From 3746f6c139ff832188f6ce15f26c66e17a4cd18e Mon Sep 17 00:00:00 2001 From: Daniele Ugoletti Date: Tue, 15 Dec 2015 23:12:04 +0100 Subject: [PATCH] movio source code v1.8 --- .gitignore | 0 Install.md | 57 + LICENSE.md | 21 + install/movio.sql | 1391 ++ src/.htaccess | 11 + src/admin/.htaccess | 13 + src/admin/ajax.php | 10 + .../classes/movio/controllers/index.html | 0 .../classes/movio/models/Mobilecontents.xml | 6 + .../classes/movio/models/index.html | 0 .../modules/codes/controllers/MakeQRCode.php | 30 + .../modules/codes/controllers/ajax/Del.php | 12 + .../modules/codes/controllers/ajax/Load.php | 36 + .../modules/codes/controllers/ajax/New.php | 14 + .../modules/codes/controllers/ajax/Set.php | 13 + .../movio/modules/codes/models/Model.xml | 6 + .../movio/modules/codes/views/Admin.xml | 20 + .../modules/codes/views/js/CodesEditor.js | 4 + .../codes/views/js/CodesEditorLoader.js | 166 + .../modules/codes/views/js/locale/en-EN.js | 12 + .../modules/codes/views/js/locale/it-IT.js | 12 + .../views/skins/CodesEditorTemplate.html | 42 + .../builder/01CreateFolders.php | 28 + .../builder/02SaveLocaleFiles.php | 25 + .../modulesBuilder/builder/03CreateModule.php | 43 + .../builder/04CreateModelFile.php | 71 + .../builder/05CreateAdminPage.php | 119 + .../modulesBuilder/builder/06CreatePage.php | 288 + .../builder/07CreateRoutingFile.php | 31 + .../modulesBuilder/builder/08AddPage.php | 19 + .../builder/09AddModuleDirective.php | 35 + .../modulesBuilder/builder/10AddSitemap.php | 10 + .../builder/11SaveModuleStructure.php | 23 + .../builder/12ImportCsvData.php | 33 + .../builder/AbstractCommand.php | 17 + .../modulesBuilder/builder/Builder.php | 64 + .../builder/d01DeleteFolders.php | 23 + .../builder/d02CleanStartup.php | 17 + .../modulesBuilder/builder/d03DeleteMenu.php | 19 + .../AdminModuleStateController.php | 21 + .../controllers/DeleteModule.php | 16 + .../controllers/StateController.php | 192 + .../services/AbstractDbService.php | 46 + .../modulesBuilder/services/CVSImporter.php | 74 + .../services/DbServiceFactory.php | 16 + .../modulesBuilder/services/MysqlService.php | 10 + .../modulesBuilder/services/PgsqlService.php | 10 + .../modules/modulesBuilder/views/Admin.xml | 273 + .../views/components/EditTableFields.php | 137 + .../views/components/NewTableFields.php | 83 + .../views/components/SelectTable.php | 67 + .../ontologybuilder/EntityResolver.php | 166 + .../movio/modules/ontologybuilder/Paths.php | 10 + .../ontologybuilder/controllers/Delete.php | 31 + .../ontologybuilder/controllers/Edit.php | 7 + .../ontologybuilder/controllers/Index.php | 7 + .../controllers/ajax/AddEntityLabel.php | 32 + .../controllers/ajax/FindEntityLabels.php | 36 + .../controllers/ajax/GetDictionaries.php | 20 + .../controllers/ajax/GetFieldTypes.php | 23 + .../controllers/ajax/GetLanguages.php | 20 + .../controllers/ajax/GetModules.php | 21 + .../controllers/ajax/GetRelationTypes.php | 27 + .../controllers/ajax/LoadEntity.php | 70 + .../controllers/ajax/SaveEntity.php | 166 + .../controllers/contentsEditor/Delete.php | 13 + .../contentsEditor/Togglevisibility.php | 15 + .../contentsEditor/ajax/GetUrl.php | 56 + .../controllers/entity/Index.php | 20 + .../controllers/entity/ajax/Thesaurus.php | 8 + .../controllers/entityFormEdit/Edit.php | 15 + .../controllers/entityFormEdit/EditDraft.php | 15 + .../entityFormEdit/ajax/Cancel.php | 9 + .../entityFormEdit/ajax/FindEntities.php | 11 + .../entityFormEdit/ajax/FindTerm.php | 21 + .../controllers/entityFormEdit/ajax/Save.php | 19 + .../entityFormEdit/ajax/SaveClose.php | 9 + .../entityFormEdit/ajax/SaveDraft.php | 19 + .../entityFormEdit/ajax/SaveDraftClose.php | 9 + .../entityLabel/ajax/DelEntityLabel.php | 13 + .../entityLabel/ajax/LoadEntityLabels.php | 24 + .../entityLabel/ajax/NewEntityLabel.php | 30 + .../entityLabel/ajax/SetEntityLabel.php | 26 + .../controllers/graph/Index.php | 9 + .../controllers/graph/List.php | 28 + .../controllers/profile/Index.php | 19 + .../controllers/relation/ajax/DelRelation.php | 18 + .../relation/ajax/LoadRelations.php | 23 + .../controllers/relation/ajax/NewRelation.php | 35 + .../controllers/relation/ajax/SetRelation.php | 29 + .../modules/ontologybuilder/models/Entity.php | 35 + .../ontologybuilder/models/EntityDocument.php | 65 + .../models/EntityLabelsDocument.php | 62 + .../ontologybuilder/models/EntityMenu.xml | 33 + .../ontologybuilder/models/EntityModel.xml | 9 + .../models/EntityProperties.php | 31 + .../models/FieldTypesDocument.php | 57 + .../ontologybuilder/models/Languages.php | 23 + .../models/RelationTypesDocument.php | 77 + .../models/proxy/EntityProxy.php | 518 + .../models/proxy/ModelProxy.php | 23 + .../models/vo/SkinAttributesVO.php | 20 + .../service/EntityTypeService.php | 209 + .../service/FieldTypeService.php | 80 + .../ontologybuilder/service/LocaleService.php | 124 + .../ontologybuilder/views/ContentsEditor.xml | 40 + .../views/EntityLabelsEditor.xml | 28 + .../modules/ontologybuilder/views/Graph.xml | 17 + .../ontologybuilder/views/OntologyBuilder.xml | 42 + .../ontologybuilder/views/RelationsEditor.xml | 28 + .../views/components/AddEntityButton.php | 36 + .../views/components/DocumentGraph.php | 166 + .../views/components/EntireGraph.php | 220 + .../views/components/Entity.php | 242 + .../views/components/EntityFormEdit.php | 309 + .../views/components/EntityList.php | 28 + .../views/components/EntityToJSON.php | 324 + .../views/components/FilterEntityType.php | 53 + .../views/components/Graph.php | 195 + .../views/components/Module.php | 60 + .../views/components/NoImage.php | 21 + .../views/components/Relation.php | 111 + .../views/components/Repeater.php | 49 + .../views/components/RepeaterForModule.php | 24 + .../views/components/ShowProfileContents.php | 35 + .../views/components/Thesaurus.php | 29 + .../views/js/ContentsEditor.js | 5 + .../views/js/EntityFormEditEntitySelect.js | 69 + .../views/js/EntityLabelsEditor.js | 4 + .../views/js/EntityLabelsEditorLoader.js | 178 + .../views/js/OntologyBuilder.js | 10 + .../views/js/OntologyBuilderEditor.js | 501 + .../views/js/RelationsEditor.js | 4 + .../views/js/RelationsEditorLoader.js | 180 + .../ontologybuilder/views/js/SearchContent.js | 405 + .../ontologybuilder/views/js/locale/en-EN.js | 66 + .../ontologybuilder/views/js/locale/it-IT.js | 66 + .../views/renderer/ActionEditDelete.php | 14 + .../views/renderer/ActionEditDeleteEntity.php | 17 + .../renderer/ActionEditDraftDeleteEntity.php | 18 + .../views/renderer/EntityName.php | 11 + .../views/renderer/EntityVisualization.php | 31 + .../skins/EntityLabelsEditorTemplate.html | 40 + .../views/skins/EntityTemplate.html | 133 + .../skins/ReferenceRelationsTemplate.html | 18 + .../views/skins/RelationsEditorTemplate.html | 36 + .../ontologybuilder/views/skins/index.html | 0 .../modules/publishApp/controllers/Index.php | 28 + .../controllers/ajax/CreateJSON.php | 23 + .../publishApp/controllers/ajax/CreateZip.php | 46 + .../publishApp/controllers/ajax/Export.php | 28 + .../controllers/ajax/ExportCodes.php | 20 + .../publishApp/controllers/ajax/GetSteps.php | 38 + .../controllers/ajax/Mysql2Sqlite.php | 32 + .../controllers/ajax/PrepareExport.php | 30 + .../publishApp/controllers/ajax/SaveSVG.php | 13 + .../movio/modules/publishApp/js/Admin.js | 7 + .../movio/modules/publishApp/js/SiteTree.js | 169 + .../movio/modules/publishApp/models/Codes.xml | 6 + .../models/DocumentIndexFulltext.xml | 6 + .../publishApp/models/Mobilefulltext.xml | 6 + .../publishApp/service/ExportService.php | 497 + .../service/Mysql2SqliteService.php | 154 + .../publishApp/service/PublishAppService.php | 79 + .../modules/publishApp/static/PublishApp.js | 144 + .../static/jquery.simplemodal.1.4.1.min.js | 25 + .../modules/publishApp/static/progressBar.css | 83 + .../movio/modules/publishApp/views/Admin.xml | 35 + .../views/components/DocumentGraph.php | 8 + .../publishApp/views/components/Graph.php | 20 + .../views/components/GraphContainer.php | 11 + .../views/components/ProgressBarDialog.php | 76 + .../views/components/SiteTreeView.php | 25 + .../siteProperties/controllers/Index.php | 11 + .../siteProperties/controllers/ajax/Save.php | 19 + .../siteProperties/views/SiteProperties.xml | 27 + .../movio/views/components/FormEdit.php | 4 + .../application/classes/movio/views/js/app.js | 4 + src/admin/application/config/acl.xml | 14 + src/admin/application/config/config.xml | 5 + .../application/config/config_common.xml | 74 + src/admin/application/config/routing.xml | 21 + src/admin/application/config/siteMap.xml | 47 + .../libs/PHPExcel/Classes/PHPExcel.php | 895 + .../PHPExcel/Classes/PHPExcel/Autoloader.php | 85 + .../PHPExcel/CachedObjectStorage/APC.php | 295 + .../CachedObjectStorage/CacheBase.php | 318 + .../PHPExcel/CachedObjectStorage/DiscISAM.php | 219 + .../PHPExcel/CachedObjectStorage/ICache.php | 112 + .../PHPExcel/CachedObjectStorage/Igbinary.php | 152 + .../PHPExcel/CachedObjectStorage/Memcache.php | 312 + .../PHPExcel/CachedObjectStorage/Memory.php | 125 + .../CachedObjectStorage/MemoryGZip.php | 137 + .../CachedObjectStorage/MemorySerialized.php | 137 + .../PHPExcel/CachedObjectStorage/PHPTemp.php | 206 + .../PHPExcel/CachedObjectStorage/SQLite.php | 306 + .../PHPExcel/CachedObjectStorage/SQLite3.php | 345 + .../PHPExcel/CachedObjectStorage/Wincache.php | 294 + .../PHPExcel/CachedObjectStorageFactory.php | 251 + .../CalcEngine/CyclicReferenceStack.php | 98 + .../Classes/PHPExcel/CalcEngine/Logger.php | 153 + .../PHPExcel/Classes/PHPExcel/Calculation.php | 3891 ++++ .../Classes/PHPExcel/Calculation/Database.php | 725 + .../Classes/PHPExcel/Calculation/DateTime.php | 1475 ++ .../PHPExcel/Calculation/Engineering.php | 2505 +++ .../PHPExcel/Calculation/Exception.php | 52 + .../PHPExcel/Calculation/ExceptionHandler.php | 49 + .../PHPExcel/Calculation/Financial.php | 2292 +++ .../PHPExcel/Calculation/FormulaParser.php | 614 + .../PHPExcel/Calculation/FormulaToken.php | 176 + .../Classes/PHPExcel/Calculation/Function.php | 149 + .../PHPExcel/Calculation/Functions.php | 815 + .../Classes/PHPExcel/Calculation/Logical.php | 288 + .../PHPExcel/Calculation/LookupRef.php | 812 + .../Classes/PHPExcel/Calculation/MathTrig.php | 1369 ++ .../PHPExcel/Calculation/Statistical.php | 3651 ++++ .../Classes/PHPExcel/Calculation/TextData.php | 589 + .../PHPExcel/Calculation/Token/Stack.php | 115 + .../PHPExcel/Calculation/functionlist.txt | 351 + .../libs/PHPExcel/Classes/PHPExcel/Cell.php | 978 + .../PHPExcel/Cell/AdvancedValueBinder.php | 192 + .../Classes/PHPExcel/Cell/DataType.php | 122 + .../Classes/PHPExcel/Cell/DataValidation.php | 472 + .../PHPExcel/Cell/DefaultValueBinder.php | 106 + .../Classes/PHPExcel/Cell/Hyperlink.php | 126 + .../Classes/PHPExcel/Cell/IValueBinder.php | 46 + .../libs/PHPExcel/Classes/PHPExcel/Chart.php | 551 + .../Classes/PHPExcel/Chart/DataSeries.php | 354 + .../PHPExcel/Chart/DataSeriesValues.php | 327 + .../Classes/PHPExcel/Chart/Exception.php | 52 + .../Classes/PHPExcel/Chart/Layout.php | 417 + .../Classes/PHPExcel/Chart/Legend.php | 171 + .../Classes/PHPExcel/Chart/PlotArea.php | 125 + .../Chart/Renderer/PHP Charting Libraries.txt | 17 + .../PHPExcel/Chart/Renderer/jpgraph.php | 837 + .../PHPExcel/Classes/PHPExcel/Chart/Title.php | 89 + .../PHPExcel/Classes/PHPExcel/Comment.php | 327 + .../Classes/PHPExcel/DocumentProperties.php | 587 + .../Classes/PHPExcel/DocumentSecurity.php | 218 + .../PHPExcel/Classes/PHPExcel/Exception.php | 52 + .../PHPExcel/Classes/PHPExcel/HashTable.php | 202 + .../PHPExcel/Classes/PHPExcel/IComparable.php | 43 + .../PHPExcel/Classes/PHPExcel/IOFactory.php | 288 + .../PHPExcel/Classes/PHPExcel/NamedRange.php | 246 + .../Classes/PHPExcel/Reader/Abstract.php | 227 + .../PHPExcel/Classes/PHPExcel/Reader/CSV.php | 415 + .../PHPExcel/Reader/DefaultReadFilter.php | 58 + .../Classes/PHPExcel/Reader/Excel2003XML.php | 802 + .../Classes/PHPExcel/Reader/Excel2007.php | 1982 ++ .../PHPExcel/Reader/Excel2007/Chart.php | 517 + .../PHPExcel/Reader/Excel2007/Theme.php | 124 + .../Classes/PHPExcel/Reader/Excel5.php | 6845 +++++++ .../Classes/PHPExcel/Reader/Excel5/Escher.php | 640 + .../Classes/PHPExcel/Reader/Exception.php | 52 + .../Classes/PHPExcel/Reader/Gnumeric.php | 873 + .../PHPExcel/Classes/PHPExcel/Reader/HTML.php | 468 + .../Classes/PHPExcel/Reader/IReadFilter.php | 47 + .../Classes/PHPExcel/Reader/IReader.php | 53 + .../Classes/PHPExcel/Reader/OOCalc.php | 695 + .../PHPExcel/Classes/PHPExcel/Reader/SYLK.php | 450 + .../Classes/PHPExcel/ReferenceHelper.php | 918 + .../PHPExcel/Classes/PHPExcel/RichText.php | 199 + .../PHPExcel/RichText/ITextElement.php | 64 + .../Classes/PHPExcel/RichText/Run.php | 102 + .../Classes/PHPExcel/RichText/TextElement.php | 108 + .../PHPExcel/Classes/PHPExcel/Settings.php | 354 + .../Classes/PHPExcel/Shared/CodePage.php | 101 + .../PHPExcel/Classes/PHPExcel/Shared/Date.php | 390 + .../Classes/PHPExcel/Shared/Drawing.php | 272 + .../Classes/PHPExcel/Shared/Escher.php | 91 + .../PHPExcel/Shared/Escher/DgContainer.php | 83 + .../Escher/DgContainer/SpgrContainer.php | 109 + .../DgContainer/SpgrContainer/SpContainer.php | 395 + .../PHPExcel/Shared/Escher/DggContainer.php | 203 + .../Escher/DggContainer/BstoreContainer.php | 65 + .../DggContainer/BstoreContainer/BSE.php | 120 + .../DggContainer/BstoreContainer/BSE/Blip.php | 91 + .../Classes/PHPExcel/Shared/Excel5.php | 317 + .../PHPExcel/Classes/PHPExcel/Shared/File.php | 178 + .../PHPExcel/Classes/PHPExcel/Shared/Font.php | 775 + .../PHPExcel/Shared/JAMA/CHANGELOG.TXT | 16 + .../Shared/JAMA/CholeskyDecomposition.php | 149 + .../Shared/JAMA/EigenvalueDecomposition.php | 862 + .../PHPExcel/Shared/JAMA/LUDecomposition.php | 258 + .../Classes/PHPExcel/Shared/JAMA/Matrix.php | 1059 + .../PHPExcel/Shared/JAMA/QRDecomposition.php | 234 + .../JAMA/SingularValueDecomposition.php | 526 + .../PHPExcel/Shared/JAMA/utils/Error.php | 82 + .../PHPExcel/Shared/JAMA/utils/Maths.php | 43 + .../PHPExcel/Classes/PHPExcel/Shared/OLE.php | 531 + .../Shared/OLE/ChainedBlockStream.php | 229 + .../Classes/PHPExcel/Shared/OLE/PPS.php | 230 + .../Classes/PHPExcel/Shared/OLE/PPS/File.php | 84 + .../Classes/PHPExcel/Shared/OLE/PPS/Root.php | 467 + .../Classes/PHPExcel/Shared/OLERead.php | 317 + .../PHPExcel/Shared/PCLZip/gnu-lgpl.txt | 504 + .../PHPExcel/Shared/PCLZip/pclzip.lib.php | 5694 ++++++ .../Classes/PHPExcel/Shared/PCLZip/readme.txt | 421 + .../PHPExcel/Shared/PasswordHasher.php | 66 + .../Classes/PHPExcel/Shared/String.php | 776 + .../Classes/PHPExcel/Shared/TimeZone.php | 140 + .../Classes/PHPExcel/Shared/XMLWriter.php | 127 + .../Classes/PHPExcel/Shared/ZipArchive.php | 114 + .../PHPExcel/Shared/ZipStreamWrapper.php | 201 + .../PHPExcel/Shared/trend/bestFitClass.php | 432 + .../Shared/trend/exponentialBestFitClass.php | 148 + .../Shared/trend/linearBestFitClass.php | 111 + .../Shared/trend/logarithmicBestFitClass.php | 120 + .../Shared/trend/polynomialBestFitClass.php | 224 + .../Shared/trend/powerBestFitClass.php | 142 + .../PHPExcel/Shared/trend/trendClass.php | 156 + .../libs/PHPExcel/Classes/PHPExcel/Style.php | 613 + .../Classes/PHPExcel/Style/Alignment.php | 409 + .../Classes/PHPExcel/Style/Border.php | 294 + .../Classes/PHPExcel/Style/Borders.php | 424 + .../PHPExcel/Classes/PHPExcel/Style/Color.php | 429 + .../Classes/PHPExcel/Style/Conditional.php | 277 + .../PHPExcel/Classes/PHPExcel/Style/Fill.php | 321 + .../PHPExcel/Classes/PHPExcel/Style/Font.php | 532 + .../Classes/PHPExcel/Style/NumberFormat.php | 708 + .../Classes/PHPExcel/Style/Protection.php | 207 + .../Classes/PHPExcel/Style/Supervisor.php | 132 + .../PHPExcel/Classes/PHPExcel/Worksheet.php | 2818 +++ .../Classes/PHPExcel/Worksheet/AutoFilter.php | 858 + .../PHPExcel/Worksheet/AutoFilter/Column.php | 394 + .../Worksheet/AutoFilter/Column/Rule.php | 464 + .../PHPExcel/Worksheet/BaseDrawing.php | 485 + .../PHPExcel/Worksheet/CellIterator.php | 161 + .../PHPExcel/Worksheet/ColumnDimension.php | 266 + .../Classes/PHPExcel/Worksheet/Drawing.php | 148 + .../PHPExcel/Worksheet/Drawing/Shadow.php | 288 + .../PHPExcel/Worksheet/HeaderFooter.php | 465 + .../Worksheet/HeaderFooterDrawing.php | 350 + .../PHPExcel/Worksheet/MemoryDrawing.php | 200 + .../PHPExcel/Worksheet/PageMargins.php | 220 + .../Classes/PHPExcel/Worksheet/PageSetup.php | 798 + .../Classes/PHPExcel/Worksheet/Protection.php | 545 + .../Classes/PHPExcel/Worksheet/Row.php | 90 + .../PHPExcel/Worksheet/RowDimension.php | 265 + .../PHPExcel/Worksheet/RowIterator.php | 148 + .../Classes/PHPExcel/Worksheet/SheetView.php | 188 + .../Classes/PHPExcel/WorksheetIterator.php | 118 + .../Classes/PHPExcel/Writer/Abstract.php | 158 + .../PHPExcel/Classes/PHPExcel/Writer/CSV.php | 313 + .../Classes/PHPExcel/Writer/Excel2007.php | 472 + .../PHPExcel/Writer/Excel2007/Chart.php | 1184 ++ .../PHPExcel/Writer/Excel2007/Comments.php | 268 + .../Writer/Excel2007/ContentTypes.php | 261 + .../PHPExcel/Writer/Excel2007/DocProps.php | 272 + .../PHPExcel/Writer/Excel2007/Drawing.php | 598 + .../PHPExcel/Writer/Excel2007/Rels.php | 417 + .../PHPExcel/Writer/Excel2007/StringTable.php | 319 + .../PHPExcel/Writer/Excel2007/Style.php | 701 + .../PHPExcel/Writer/Excel2007/Theme.php | 871 + .../PHPExcel/Writer/Excel2007/Workbook.php | 452 + .../PHPExcel/Writer/Excel2007/Worksheet.php | 1214 ++ .../PHPExcel/Writer/Excel2007/WriterPart.php | 81 + .../Classes/PHPExcel/Writer/Excel5.php | 935 + .../PHPExcel/Writer/Excel5/BIFFwriter.php | 255 + .../Classes/PHPExcel/Writer/Excel5/Escher.php | 537 + .../Classes/PHPExcel/Writer/Excel5/Font.php | 165 + .../Classes/PHPExcel/Writer/Excel5/Parser.php | 1582 ++ .../PHPExcel/Writer/Excel5/Workbook.php | 1450 ++ .../PHPExcel/Writer/Excel5/Worksheet.php | 3681 ++++ .../Classes/PHPExcel/Writer/Excel5/Xf.php | 546 + .../Classes/PHPExcel/Writer/Exception.php | 52 + .../PHPExcel/Classes/PHPExcel/Writer/HTML.php | 1527 ++ .../Classes/PHPExcel/Writer/IWriter.php | 46 + .../PHPExcel/Classes/PHPExcel/Writer/PDF.php | 90 + .../Classes/PHPExcel/Writer/PDF/Core.php | 364 + .../Classes/PHPExcel/Writer/PDF/DomPDF.php | 120 + .../Classes/PHPExcel/Writer/PDF/mPDF.php | 130 + .../Classes/PHPExcel/Writer/PDF/tcPDF.php | 136 + .../Classes/PHPExcel/locale/cs/config | 47 + .../Classes/PHPExcel/locale/cs/functions | 438 + .../Classes/PHPExcel/locale/da/config | 48 + .../Classes/PHPExcel/locale/da/functions | 438 + .../Classes/PHPExcel/locale/de/config | 47 + .../Classes/PHPExcel/locale/de/functions | 438 + .../Classes/PHPExcel/locale/en/uk/config | 32 + .../Classes/PHPExcel/locale/es/config | 47 + .../Classes/PHPExcel/locale/es/functions | 438 + .../Classes/PHPExcel/locale/fi/config | 47 + .../Classes/PHPExcel/locale/fi/functions | 438 + .../Classes/PHPExcel/locale/fr/config | 47 + .../Classes/PHPExcel/locale/fr/functions | 438 + .../Classes/PHPExcel/locale/hu/config | 47 + .../Classes/PHPExcel/locale/hu/functions | 438 + .../Classes/PHPExcel/locale/it/config | 47 + .../Classes/PHPExcel/locale/it/functions | 438 + .../Classes/PHPExcel/locale/nl/config | 47 + .../Classes/PHPExcel/locale/nl/functions | 438 + .../Classes/PHPExcel/locale/no/config | 47 + .../Classes/PHPExcel/locale/no/functions | 438 + .../Classes/PHPExcel/locale/pl/config | 47 + .../Classes/PHPExcel/locale/pl/functions | 438 + .../Classes/PHPExcel/locale/pt/br/config | 47 + .../Classes/PHPExcel/locale/pt/br/functions | 408 + .../Classes/PHPExcel/locale/pt/config | 47 + .../Classes/PHPExcel/locale/pt/functions | 408 + .../Classes/PHPExcel/locale/ru/config | 47 + .../Classes/PHPExcel/locale/ru/functions | 438 + .../Classes/PHPExcel/locale/sv/config | 47 + .../Classes/PHPExcel/locale/sv/functions | 408 + .../Classes/PHPExcel/locale/tr/config | 47 + .../Classes/PHPExcel/locale/tr/functions | 438 + .../application/libs/PHPExcel/changelog.txt | 1394 ++ .../application/libs/PHPExcel/install.txt | 75 + .../application/libs/PHPExcel/license.txt | 345 + src/admin/application/libs/dUnzip2.inc.php | 517 + src/admin/application/libs/dZip.inc.php | 146 + .../application/libs/phpqrcode/CHANGELOG | 38 + src/admin/application/libs/phpqrcode/INSTALL | 67 + src/admin/application/libs/phpqrcode/LICENSE | 165 + src/admin/application/libs/phpqrcode/README | 45 + src/admin/application/libs/phpqrcode/VERSION | 2 + .../libs/phpqrcode/bindings/tcpdf/qrcode.php | 2875 +++ .../application/libs/phpqrcode/index.php | 94 + .../application/libs/phpqrcode/phpqrcode.php | 3312 ++++ .../libs/phpqrcode/qrbitstream.php | 180 + .../application/libs/phpqrcode/qrconfig.php | 16 + .../application/libs/phpqrcode/qrconst.php | 54 + .../application/libs/phpqrcode/qrencode.php | 502 + .../application/libs/phpqrcode/qrimage.php | 95 + .../application/libs/phpqrcode/qrinput.php | 729 + .../application/libs/phpqrcode/qrlib.php | 43 + .../application/libs/phpqrcode/qrmask.php | 328 + .../application/libs/phpqrcode/qrrscode.php | 210 + .../application/libs/phpqrcode/qrspec.php | 592 + .../application/libs/phpqrcode/qrsplit.php | 311 + .../application/libs/phpqrcode/qrtools.php | 172 + .../libs/phpqrcode/tools/merge.bat | 2 + .../libs/phpqrcode/tools/merge.php | 70 + .../application/libs/phpqrcode/tools/merge.sh | 2 + .../libs/phpqrcode/tools/merged_config.php | 17 + .../libs/phpqrcode/tools/merged_header.php | 36 + src/admin/application/pageTypes/Dashboard.xml | 11 + src/admin/application/pageTypes/Login.xml | 14 + src/admin/application/pageTypes/Logout.xml | 10 + src/admin/application/pageTypes/_common.xml | 16 + src/admin/application/startup/index.php | 10 + .../application/startup/modules_custom.php | 7 + src/admin/application/startup/movio.php | 4 + src/admin/application/templates/Login.php | 54 + src/admin/application/templates/Page.php | 76 + src/admin/application/templates/Popup.php | 17 + .../application/templates/css/styles.css | 91 + .../templates/font/FontAwesome.otf | Bin 0 -> 48748 bytes .../templates/font/fontawesome-webfont.eot | Bin 0 -> 25395 bytes .../templates/font/fontawesome-webfont.svg | 284 + .../templates/font/fontawesome-webfont.ttf | Bin 0 -> 55096 bytes .../templates/font/fontawesome-webfont.woff | Bin 0 -> 29380 bytes .../application/templates/icons/audio.png | Bin 0 -> 669 bytes .../application/templates/icons/folder.png | Bin 0 -> 537 bytes .../templates/icons/icon_loading.gif | Bin 0 -> 673 bytes .../application/templates/icons/image.png | Bin 0 -> 516 bytes .../application/templates/icons/other.png | Bin 0 -> 294 bytes src/admin/application/templates/icons/pdf.png | Bin 0 -> 591 bytes .../templates/images/ajax-loader.gif | Bin 0 -> 6820 bytes .../templates/images/dragHandler.gif | Bin 0 -> 113 bytes .../templates/images/icon_delete.gif | Bin 0 -> 323 bytes .../templates/images/icon_edit.gif | Bin 0 -> 198 bytes .../application/templates/images/noimage.jpg | Bin 0 -> 1315 bytes .../application/templates/images/resize.png | Bin 0 -> 348 bytes .../templates/images/treeIcons.png | Bin 0 -> 2680 bytes .../application/templates/img/article.png | Bin 0 -> 294 bytes .../application/templates/img/attach.png | Bin 0 -> 1370 bytes .../application/templates/img/breadcrumb.png | Bin 0 -> 1118 bytes .../application/templates/img/calendar.png | Bin 0 -> 225 bytes .../application/templates/img/down-arrow.png | Bin 0 -> 4046 bytes .../application/templates/img/dummy-logo.jpg | Bin 0 -> 10971 bytes .../application/templates/img/exercise.png | Bin 0 -> 1096 bytes .../img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes .../templates/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes .../application/templates/img/login-bkg.png | Bin 0 -> 634 bytes .../templates/img/logo/logo-login.png | Bin 0 -> 4671 bytes .../templates/img/logo/logo-metacms.png | Bin 0 -> 1343 bytes .../templates/img/logo/logo-top.png | Bin 0 -> 3099 bytes .../application/templates/img/menu-active.png | Bin 0 -> 182 bytes src/admin/application/templates/img/pool.png | Bin 0 -> 1188 bytes .../application/templates/img/relation.png | Bin 0 -> 208 bytes .../application/templates/img/up-arrow.png | Bin 0 -> 4047 bytes .../templates/img/up-down-arrow.png | Bin 0 -> 4066 bytes .../application/templates/js/bootstrap.js | 2159 ++ .../application/templates/js/bootstrap.min.js | 7 + .../templates/js/jqBootstrapValidation.js | 912 + src/admin/application/templates/js/jquery.js | 9472 +++++++++ .../application/templates/js/jquery.min.js | 2 + .../application/templates/less/custom.less | 205 + .../templates/less/custom.login.less | 84 + .../templates/less/font-awesome.less | 537 + .../application/templates/less/glizy.less | 1269 ++ .../application/templates/less/global.less | 310 + .../less/libs/bootstrap-responsive.less | 1094 + .../templates/less/libs/bootstrap.less | 6039 ++++++ .../application/templates/less/libs/h5bp.less | 298 + .../templates/less/libs/mixin.less | 53 + .../application/templates/less/structure.less | 1661 ++ .../application/templates/less/styles.less | 71 + src/admin/cache/.gitkeep | 0 src/admin/getFile.php | 16 + src/admin/getImage.php | 16 + src/admin/index.php | 8 + src/admin/uploader.php | 38 + src/ajax.php | 7 + src/application/classes/movio/locale/en.php | 439 + src/application/classes/movio/locale/it.php | 411 + .../modules/europeana/EuropeanaResponseVO.php | 7 + .../movio/modules/europeana/SendRequest.php | 55 + .../europeana/views/EuropeanaShowResults.xml | 28 + .../views/components/RelatedContents.php | 67 + .../views/components/ShowResults.php | 49 + .../js/FormEditEuropeanaRelatedContents.js | 436 + .../europeana/views/skin/showresults.html | 25 + .../classes/movio/modules/news/Module.php | 21 + .../movio/modules/news/UrlResolver.php | 18 + .../movio/modules/news/config/routing.xml | 4 + .../movio/modules/news/models/Model.xml | 63 + .../movio/modules/news/views/Admin.xml | 45 + .../movio/modules/news/views/FrontEnd.xml | 58 + .../sharingButtons/controllers/ajax/Save.php | 14 + .../movio/modules/sharingButtons/js/main.js | 36 + .../modules/sharingButtons/views/Admin.xml | 25 + .../sharingButtons/views/SharingButton.php | 16 + .../views/components/GetSharingButtons.php | 113 + .../sharingButtons/views/components/Share.php | 110 + .../storyteller/controllers/PostComment.php | 51 + .../controllers/ajax/PagePicker.php | 33 + .../modules/storyteller/models/Comment.xml | 29 + .../views/components/Storyteller.xml | 43 + .../views/components/StorytellerCmp.php | 47 + .../views/skins/StorytellerSkinIterator.php | 222 + .../movio/modules/thesaurus/Exception.php | 24 + .../movio/modules/thesaurus/Module.php | 21 + .../controllers/DeleteDictionary.php | 11 + .../controllers/dictionaryEdit/ajax/Add.php | 17 + .../controllers/dictionaryEdit/ajax/Save.php | 19 + .../thesaurus/controllers/termEdit/Add.php | 23 + .../thesaurus/controllers/termEdit/Edit.php | 8 + .../controllers/termEdit/ajax/Add.php | 23 + .../controllers/termEdit/ajax/Save.php | 23 + .../controllers/treeview/ajax/DeleteTerm.php | 11 + .../controllers/treeview/ajax/GetChildren.php | 59 + .../controllers/treeview/ajax/MoveTerm.php | 11 + .../movio/modules/thesaurus/js/Admin.js | 9 + .../modules/thesaurus/js/DictionaryTree.js | 237 + .../modules/thesaurus/js/TermEditIframe.js | 41 + .../movio/modules/thesaurus/locale/en.php | 18 + .../movio/modules/thesaurus/locale/it.php | 18 + .../thesaurus/models/ChronologicTermVO.php | 19 + .../modules/thesaurus/models/Dictionary.xml | 11 + .../modules/thesaurus/models/DictionaryVO.php | 21 + .../thesaurus/models/GenericTermVO.php | 19 + .../thesaurus/models/GeographicalTermVO.php | 17 + .../movio/modules/thesaurus/models/Term.xml | 18 + .../modules/thesaurus/models/TermFactory.php | 44 + .../modules/thesaurus/models/TermTypeEnum.php | 16 + .../movio/modules/thesaurus/models/TermVO.php | 39 + .../thesaurus/models/proxy/ThesaurusProxy.php | 249 + .../static/FormatThesaurusSelectFrom.js | 7 + .../movio/modules/thesaurus/views/Admin.xml | 117 + .../views/components/DictionaryList.xml | 9 + .../views/components/DictionaryListCmp.php | 89 + .../views/components/DictionaryTreeView.php | 43 + .../views/components/SelectDictionary.php | 27 + .../thesaurus/views/components/SelectTerm.php | 53 + .../views/components/ShowTaggedContents.php | 33 + .../thesaurus/views/components/TermEdit.php | 63 + .../views/renderer/CellEditDelete.php | 50 + .../thesaurus/views/renderer/CellType.php | 9 + .../movio/modules/touristoperators/Module.php | 21 + .../modules/touristoperators/UrlResolver.php | 18 + .../touristoperators/config/routing.xml | 4 + .../touristoperators/controllers/Index.php | 24 + .../modules/touristoperators/models/Model.xml | 41 + .../modules/touristoperators/views/Admin.xml | 39 + .../touristoperators/views/FrontEnd.xml | 86 + .../views/components/RecordDetail.php | 40 + .../views/components/RecordSetMap.php | 56 + .../classes/movio/search/Content.php | 32 + .../classes/movio/search/Entity.php | 36 + .../classes/movio/search/models/Content.xml | 31 + .../classes/movio/search/models/Entity.xml | 38 + .../movio/views/AbstractLessTemplate.php | 74 + .../movio/views/TemplateModuleAdmin.xml | 56 + .../classes/movio/views/components/Boxes.xml | 27 + .../movio/views/components/BoxesCmp.php | 5 + .../movio/views/components/BoxesRepeater.php | 32 + .../movio/views/components/BoxesSidebar.xml | 20 + .../movio/views/components/GoogleMap.xml | 34 + .../movio/views/components/GoogleMapCmp.php | 71 + .../movio/views/components/ImageHotspot.php | 102 + .../movio/views/components/Photogallery.xml | 20 + .../views/components/PhotogalleryCategory.xml | 20 + .../views/components/PhotogalleryCmp.php | 39 + .../views/components/RepeaterFromModel.php | 129 + .../movio/views/components/Timeline.xml | 28 + .../movio/views/components/TimelineCmp.php | 74 + .../movio/views/components/Unity3D.xml | 27 + .../movio/views/components/Unity3DCmp.php | 35 + .../classes/movio/views/components/Video.xml | 12 + .../movio/views/components/VideoCmp.php | 22 + .../movio/ontologybuilder/locale/.gitignore | 1 + .../ontologybuilder/skins/entities/.gitignore | 1 + src/application/config/acl.xml | 4 + src/application/config/config.xml | 10 + src/application/config/config_common.xml | 75 + src/application/config/fieldTypes.xml | 139 + src/application/config/routing.xml | 17 + .../libs/captcha/CaptchaBuilder.php | 716 + .../libs/captcha/CaptchaBuilderInterface.php | 30 + .../libs/captcha/Font/captcha0.ttf | Bin 0 -> 49224 bytes .../libs/captcha/Font/captcha1.ttf | Bin 0 -> 76232 bytes .../libs/captcha/Font/captcha2.ttf | Bin 0 -> 33984 bytes .../libs/captcha/Font/captcha3.ttf | Bin 0 -> 15976 bytes .../libs/captcha/Font/captcha4.ttf | Bin 0 -> 906980 bytes .../libs/captcha/Font/captcha5.ttf | Bin 0 -> 49724 bytes .../libs/captcha/ImageFileHandler.php | 106 + src/application/libs/captcha/LICENSE | 19 + .../libs/captcha/PhraseBuilder.php | 34 + .../libs/captcha/PhraseBuilderInterface.php | 21 + src/application/libs/captcha/README.md | 108 + src/application/libs/captcha/autoload.php | 16 + src/application/libs/captcha/composer.json | 28 + src/application/libs/captcha/demo/demo.php | 14 + .../libs/captcha/demo/fingerprint.php | 15 + src/application/libs/captcha/demo/index.php | 15 + src/application/libs/captcha/demo/ocr.php | 42 + src/application/libs/captcha/demo/output.php | 15 + .../libs/openzoom/Oz/Deepzoom/Descriptor.php | 229 + .../libs/openzoom/Oz/Deepzoom/Exception.php | 42 + .../openzoom/Oz/Deepzoom/ImageCreator.php | 197 + .../libs/openzoom/thumbnail.inc.php | 677 + .../mediaArchive/Archive/index.html | 0 src/application/mediaArchive/Audio/index.html | 0 src/application/mediaArchive/Flash/index.html | 0 src/application/mediaArchive/Image/index.html | 0 .../mediaArchive/Office/index.html | 0 src/application/mediaArchive/Other/index.html | 0 src/application/mediaArchive/Pdf/index.html | 0 src/application/mediaArchive/Video/index.html | 0 src/application/pageTypes/Alias.xml | 8 + src/application/pageTypes/Common.xml | 27 + src/application/pageTypes/Cover.xml | 18 + src/application/pageTypes/DictionaryList.xml | 15 + .../pageTypes/DigitalExhibition.xml | 46 + src/application/pageTypes/Empty.xml | 6 + src/application/pageTypes/Entity.xml | 55 + src/application/pageTypes/Exhibition.xml | 60 + src/application/pageTypes/GoogleMap.xml | 11 + src/application/pageTypes/Graph.xml | 47 + src/application/pageTypes/Home.xml | 24 + src/application/pageTypes/ImageHotspot.xml | 11 + src/application/pageTypes/Login.xml | 27 + src/application/pageTypes/Logout.xml | 14 + src/application/pageTypes/LostPassword.xml | 27 + src/application/pageTypes/Page.xml | 18 + src/application/pageTypes/Photogallery.xml | 14 + .../pageTypes/Photogallery_category.xml | 14 + .../pageTypes/ProfileListContents.xml | 26 + src/application/pageTypes/Registration.xml | 48 + src/application/pageTypes/Search.xml | 11 + src/application/pageTypes/SiteMap.xml | 10 + src/application/pageTypes/Storyteller.xml | 12 + src/application/pageTypes/Timeline.xml | 12 + src/application/pageTypes/Unity3D.xml | 11 + src/application/pageTypes/UserDetails.xml | 38 + src/application/pageTypes/Video.xml | 12 + src/application/startup/index.php | 8 + src/application/startup/movio.php | 14 + src/application/startup/plugin.php | 5 + src/cache/.gitkeep | 0 src/checkUpdate.php | 19 + src/core/.htaccess | 4 + src/core/COPYRIGHT.txt | 52 + src/core/LICENSE.txt | 504 + src/core/classes/org/glizy/Assets.php | 220 + src/core/classes/org/glizy/Config.php | 336 + src/core/classes/org/glizy/Exception.php | 102 + src/core/classes/org/glizy/GlizyObject.php | 156 + src/core/classes/org/glizy/Modules.php | 174 + src/core/classes/org/glizy/ObjectFactory.php | 324 + src/core/classes/org/glizy/ObjectValues.php | 119 + src/core/classes/org/glizy/Paths.php | 169 + src/core/classes/org/glizy/Registry.php | 94 + src/core/classes/org/glizy/Request.php | 273 + src/core/classes/org/glizy/Routing.php | 516 + src/core/classes/org/glizy/Session.php | 224 + src/core/classes/org/glizy/SessionEx.php | 164 + .../classes/org/glizy/application/Acl.php | 72 + .../org/glizy/application/AclAdvanced.php | 74 + .../org/glizy/application/Application.php | 758 + .../org/glizy/application/ApplicationXML.php | 19 + .../org/glizy/application/MessageStack.php | 58 + .../classes/org/glizy/application/SiteMap.php | 251 + .../org/glizy/application/SiteMapIterator.php | 119 + .../org/glizy/application/SiteMapNode.php | 204 + .../org/glizy/application/SiteMapSimple.php | 78 + .../org/glizy/application/SiteMapXML.php | 173 + .../classes/org/glizy/application/User.php | 111 + .../glizy/authentication/AbstractLogin.php | 68 + .../authentication/AuthenticationDriver.php | 14 + .../AuthenticationException.php | 36 + .../org/glizy/authentication/Database.php | 105 + .../classes/org/glizy/cache/CacheFile.php | 158 + .../classes/org/glizy/cache/CacheFunction.php | 98 + src/core/classes/org/glizy/compilers/Acl.php | 44 + .../classes/org/glizy/compilers/Compiler.php | 107 + .../org/glizy/compilers/CompilerException.php | 16 + .../classes/org/glizy/compilers/Component.php | 108 + .../classes/org/glizy/compilers/Config.php | 141 + .../org/glizy/compilers/LayoutManagerPHP.php | 28 + .../classes/org/glizy/compilers/Model.php | 476 + .../org/glizy/compilers/ModelException.php | 26 + .../classes/org/glizy/compilers/PageType.php | 405 + .../org/glizy/compilers/PageTypeException.php | 27 + .../classes/org/glizy/compilers/Routing.php | 281 + src/core/classes/org/glizy/compilers/Skin.php | 45 + .../org/glizy/components/Authenticator.php | 69 + .../org/glizy/components/Breadcrumbs.php | 115 + .../classes/org/glizy/components/Button.php | 97 + src/core/classes/org/glizy/components/CSS.php | 119 + .../classes/org/glizy/components/Caption.php | 48 + .../classes/org/glizy/components/Checkbox.php | 103 + .../org/glizy/components/ColorPicker.php | 60 + .../org/glizy/components/Component.php | 1061 + .../glizy/components/ComponentContainer.php | 79 + .../org/glizy/components/ConfigValue.php | 53 + .../classes/org/glizy/components/DBdebug.php | 30 + .../org/glizy/components/DataDictionary.php | 152 + .../classes/org/glizy/components/DataGrid.php | 533 + .../org/glizy/components/DataGridAjax.php | 346 + .../org/glizy/components/DataGridColumn.php | 55 + .../org/glizy/components/DataProvider.php | 201 + .../classes/org/glizy/components/Date.php | 69 + .../classes/org/glizy/components/Email.php | 46 + .../org/glizy/components/EmbedPage.php | 79 + .../org/glizy/components/EmptyComponent.php | 31 + .../classes/org/glizy/components/Fieldset.php | 71 + .../org/glizy/components/FilterValue.php | 25 + .../classes/org/glizy/components/Filters.php | 66 + .../classes/org/glizy/components/Form.php | 198 + .../org/glizy/components/FormLabel.php | 29 + .../org/glizy/components/GoogleMap.php | 106 + .../classes/org/glizy/components/Groupbox.php | 89 + .../classes/org/glizy/components/HBox.php | 68 + .../classes/org/glizy/components/Hidden.php | 76 + .../org/glizy/components/HtmlButton.php | 137 + .../org/glizy/components/HtmlComponent.php | 62 + .../components/HtmlComponentContainer.php | 40 + .../org/glizy/components/HtmlFormElement.php | 204 + .../classes/org/glizy/components/Image.php | 259 + .../org/glizy/components/ImageExternal.php | 182 + .../classes/org/glizy/components/Import.php | 49 + .../classes/org/glizy/components/Input.php | 208 + .../classes/org/glizy/components/JSTab.php | 36 + .../org/glizy/components/JSTabGroup.php | 143 + .../classes/org/glizy/components/JSscript.php | 162 + .../classes/org/glizy/components/Link.php | 89 + .../classes/org/glizy/components/LinkTo.php | 112 + .../classes/org/glizy/components/List.php | 291 + .../classes/org/glizy/components/ListItem.php | 50 + .../org/glizy/components/ListMenuItem.php | 108 + .../classes/org/glizy/components/Login.php | 41 + .../classes/org/glizy/components/LoginBox.php | 153 + .../org/glizy/components/LoginCheck.php | 51 + .../classes/org/glizy/components/Logout.php | 31 + .../classes/org/glizy/components/LongText.php | 149 + .../classes/org/glizy/components/Media.php | 158 + .../org/glizy/components/MessageBox.php | 68 + .../org/glizy/components/ModelDefine.php | 16 + .../classes/org/glizy/components/Modifier.php | 61 + .../classes/org/glizy/components/Module.php | 36 + .../org/glizy/components/NavigationMenu.php | 393 + .../org/glizy/components/NullComponent.php | 17 + .../classes/org/glizy/components/Number.php | 13 + .../org/glizy/components/OutputFilter.php | 62 + .../glizy/components/OutputFilterGroup.php | 13 + .../classes/org/glizy/components/Page.php | 135 + .../org/glizy/components/PageTitle.php | 107 + .../org/glizy/components/PaginateResult.php | 451 + .../classes/org/glizy/components/Panel.php | 77 + .../org/glizy/components/PdfButton.php | 40 + .../org/glizy/components/RadioButton.php | 102 + .../org/glizy/components/RecordDetail.php | 137 + .../org/glizy/components/RecordDetailEx.php | 259 + .../org/glizy/components/RecordSetBox.php | 87 + .../org/glizy/components/RecordSetList.php | 282 + .../classes/org/glizy/components/Repeater.php | 105 + .../org/glizy/components/RepeaterRecord.php | 106 + .../classes/org/glizy/components/Script.php | 40 + .../classes/org/glizy/components/Search.php | 121 + .../org/glizy/components/SearchBox.php | 83 + .../org/glizy/components/SearchFilters.php | 142 + .../org/glizy/components/SelectPage.php | 81 + .../org/glizy/components/SimpleList.php | 83 + .../org/glizy/components/SkinDefine.php | 55 + .../classes/org/glizy/components/State.php | 138 + .../org/glizy/components/StateSwitch.php | 188 + .../org/glizy/components/StateSwitchClass.php | 18 + src/core/classes/org/glizy/components/Tab.php | 30 + .../classes/org/glizy/components/TabGroup.php | 80 + .../classes/org/glizy/components/Text.php | 109 + src/core/classes/org/glizy/components/Url.php | 46 + .../classes/org/glizy/components/UserBox.php | 57 + .../classes/org/glizy/components/VBox.php | 43 + .../components/interfaces/IDataProvider.php | 7 + .../components/interfaces/ISearchFilters.php | 6 + .../org/glizy/components/render/Render.php | 129 + .../glizy/components/render/RenderCell.php | 37 + .../render/RenderCellRecordSetList.php | 23 + .../glizy/components/render/RenderCellRow.php | 27 + .../org/glizy/dataAccess/ActiveRecord.php | 1588 ++ .../glizy/dataAccess/ActiveRecord2tables.php | 613 + .../org/glizy/dataAccess/DataAccess.php | 196 + .../org/glizy/dataAccess/RecordIterator.php | 76 + .../classes/org/glizy/dataAccess/Relation.php | 93 + .../glizy/dataAccess/RelationContentTable.php | 106 + .../org/glizy/dataAccess/RelationHasMany.php | 200 + .../org/glizy/dataAccess/RelationHasOne.php | 116 + .../glizy/dataAccess/RelationJoinTable.php | 131 + .../glizy/dataAccess/RelationMany2Many.php | 228 + .../glizy/dataAccess/cache/ActiveRecord.php | 29 + .../org/glizy/dataAccess/cache/Iterator.php | 77 + .../org/glizy/dataAccess/cache/Query.php | 74 + .../org/glizy/dataAccess/cache/QueryRedis.php | 112 + .../glizy/dataAccess/driver/Connection.php | 536 + .../AbstractRecordIterator.php | 454 + .../dataAccessDoctrine/AbstractRelation.php | 29 + .../glizy/dataAccessDoctrine/ActiveRecord.php | 681 + .../ActiveRecord2tables.php | 444 + .../ActiveRecordDocument.php | 1038 + .../ActiveRecordException.php | 47 + .../ActiveRecordSimpleDocument.php | 404 + .../glizy/dataAccessDoctrine/Connection.php | 161 + .../glizy/dataAccessDoctrine/DataAccess.php | 519 + .../org/glizy/dataAccessDoctrine/DbField.php | 78 + .../glizy/dataAccessDoctrine/IndexQueue.php | 44 + .../Query/Expression/ExpressionBuilder.php | 79 + .../dataAccessDoctrine/Query/QueryBuilder.php | 173 + .../dataAccessDoctrine/RecordIterator.php | 138 + .../RecordIterator2tables.php | 45 + .../RecordIteratorDocument.php | 558 + .../RecordIteratorSimpleDocument.php | 100 + .../dataAccessDoctrine/RelationFactory.php | 36 + .../dataAccessDoctrine/RelationJoinTable.php | 123 + .../dataAccessDoctrine/SchemaManager.php | 133 + .../dataAccessDoctrine/SqlRecordIterator.php | 228 + .../glizy/dataAccessDoctrine/SystemField.php | 17 + .../interfaces/RelationInterface.php | 9 + .../logging/DebugLogger.php | 24 + .../logging/EchoSQLLogger.php | 37 + .../glizy/dataAccessDoctrine/types/Array.php | 18 + .../dataAccessDoctrine/types/ArrayID.php | 11 + .../dataAccessDoctrine/types/Boolean.php | 13 + .../glizy/dataAccessDoctrine/types/Date.php | 16 + .../dataAccessDoctrine/types/DateTime.php | 16 + .../dataAccessDoctrine/types/DateTimeTz.php | 24 + .../glizy/dataAccessDoctrine/types/Time.php | 24 + .../glizy/dataAccessDoctrine/types/Types.php | 6 + .../vo/DocumentObjectVO.php | 58 + .../classes/org/glizy/debug/GlizyDebugBar.php | 148 + src/core/classes/org/glizy/debug/Helpers.php | 49 + src/core/classes/org/glizy/debug/Module.php | 23 + src/core/classes/org/glizy/debug/Whoops.php | 37 + .../debug/dataCollector/GlizyCollector.php | 103 + .../glizy/debug/views/components/DebugBar.php | 33 + src/core/classes/org/glizy/events/Event.php | 69 + .../org/glizy/events/EventDispatcher.php | 66 + .../org/glizy/events/EventException.php | 17 + .../org/glizy/filters/ForceNoTagText.php | 59 + .../org/glizy/filters/OutputFilter.php | 15 + .../classes/org/glizy/filters/Uppercase.php | 20 + .../org/glizy/helpers/ActiveRecord.php | 51 + src/core/classes/org/glizy/helpers/Array.php | 47 + src/core/classes/org/glizy/helpers/CSS.php | 44 + .../classes/org/glizy/helpers/Convert.php | 26 + src/core/classes/org/glizy/helpers/Files.php | 84 + src/core/classes/org/glizy/helpers/Html.php | 304 + src/core/classes/org/glizy/helpers/JS.php | 53 + src/core/classes/org/glizy/helpers/Link.php | 487 + src/core/classes/org/glizy/helpers/Mail.php | 224 + src/core/classes/org/glizy/helpers/Media.php | 16 + .../classes/org/glizy/helpers/Navigation.php | 33 + .../classes/org/glizy/helpers/PhpScript.php | 53 + src/core/classes/org/glizy/helpers/String.php | 61 + src/core/classes/org/glizy/locale/Locale.php | 79 + src/core/classes/org/glizy/locale/de.php | 188 + src/core/classes/org/glizy/locale/en.php | 194 + src/core/classes/org/glizy/locale/fr.php | 188 + src/core/classes/org/glizy/locale/it.php | 195 + src/core/classes/org/glizy/log/Console.php | 37 + src/core/classes/org/glizy/log/DB.php | 55 + .../classes/org/glizy/log/ElasticSearch.php | 122 + src/core/classes/org/glizy/log/File.php | 106 + src/core/classes/org/glizy/log/FireBug.php | 160 + src/core/classes/org/glizy/log/LiveLog.php | 123 + src/core/classes/org/glizy/log/LogBase.php | 240 + src/core/classes/org/glizy/log/LogFactory.php | 36 + src/core/classes/org/glizy/log/Mail.php | 55 + src/core/classes/org/glizy/log/Null.php | 32 + .../glizy/middleware/AbstractHttpCache.php | 27 + .../org/glizy/middleware/DynamicPage.php | 13 + .../org/glizy/middleware/IMiddleware.php | 6 + .../org/glizy/middleware/StaticPage.php | 19 + src/core/classes/org/glizy/models/Join.xml | 6 + .../classes/org/glizy/models/JoinDoctrine.xml | 6 + src/core/classes/org/glizy/models/Log.xml | 15 + .../classes/org/glizy/models/Registry.xml | 6 + src/core/classes/org/glizy/models/Role.xml | 51 + src/core/classes/org/glizy/models/User.xml | 32 + .../classes/org/glizy/models/UserGroup.xml | 7 + src/core/classes/org/glizy/models/UserLog.xml | 13 + .../classes/org/glizy/mvc/components/Page.php | 174 + .../org/glizy/mvc/components/State.php | 178 + .../mvc/components/StateTabNavigation.php | 91 + .../org/glizy/mvc/core/Application.php | 110 + .../classes/org/glizy/mvc/core/Command.php | 77 + .../org/glizy/mvc/core/CommandAjax.php | 48 + src/core/classes/org/glizy/mvc/core/Proxy.php | 24 + .../scaffold/controllers/AbstractCommand.php | 32 + .../glizy/mvc/scaffold/controllers/Add.php | 50 + .../glizy/mvc/scaffold/controllers/Delete.php | 25 + .../glizy/mvc/scaffold/controllers/Show.php | 36 + src/core/classes/org/glizy/oaipmh/OaiPmh.php | 163 + .../org/glizy/oaipmh/components/GetRecord.php | 115 + .../org/glizy/oaipmh/components/Identify.php | 32 + .../oaipmh/components/ListIdentifiers.php | 172 + .../oaipmh/components/ListMetadataFormats.php | 35 + .../glizy/oaipmh/components/ListRecords.php | 187 + .../org/glizy/oaipmh/components/ListSets.php | 55 + .../org/glizy/oaipmh/components/Page.php | 135 + .../org/glizy/oaipmh/core/AbstractMapping.php | 57 + .../org/glizy/oaipmh/core/Application.php | 137 + .../org/glizy/oaipmh/models/PicoQueue.xml | 7 + .../org/glizy/oaipmh/pageTypes/index.xml | 38 + src/core/classes/org/glizy/parser/XML.php | 88 + .../org/glizy/plugins/PluginClient.php | 17 + .../org/glizy/plugins/PluginManager.php | 43 + .../org/glizy/plugins/PluginServer.php | 40 + src/core/classes/org/glizy/plugins/Search.php | 35 + src/core/classes/org/glizy/redis/Client.php | 28 + .../org/glizy/rest/core/Application.php | 287 + .../org/glizy/rest/core/CommandRest.php | 37 + .../org/glizy/rest/core/RestRequest.php | 485 + .../glizy/rest/core/RestRequestMultipart.php | 116 + .../classes/org/glizy/sessionStore/Redis.php | 39 + .../org/glizy/template/layoutManager/DWT.php | 48 + .../template/layoutManager/LayoutManager.php | 80 + .../org/glizy/template/layoutManager/PDF.php | 249 + .../org/glizy/template/layoutManager/PHP.php | 45 + .../glizy/template/layoutManager/PHPTAL.php | 44 + .../classes/org/glizy/template/skin/PHP.php | 39 + .../org/glizy/template/skin/PHPTAL.php | 46 + .../classes/org/glizy/template/skin/Skin.php | 53 + .../classes/org/glizy/template/skin/TWIG.php | 48 + src/core/classes/org/glizy/types/Date.php | 14 + src/core/classes/org/glizy/types/DateTime.php | 14 + .../classes/org/glizy/types/DateTimeTz.php | 14 + src/core/classes/org/glizy/types/Time.php | 14 + .../glizy/validators/AbstractValidator.php | 13 + .../glizy/validators/CompositeValidator.php | 34 + .../classes/org/glizy/validators/Date.php | 21 + .../classes/org/glizy/validators/DateTime.php | 21 + .../classes/org/glizy/validators/Email.php | 26 + .../classes/org/glizy/validators/NotNull.php | 21 + .../classes/org/glizy/validators/Numeric.php | 21 + .../classes/org/glizy/validators/Text.php | 21 + .../glizy/validators/ValidationException.php | 24 + .../org/glizy/validators/Validator.php | 215 + src/core/classes/org/glizycms/Glizycms.php | 106 + .../controllers/activeRecordEdit/Delete.php | 14 + .../controllers/activeRecordEdit/Edit.php | 16 + .../activeRecordEdit/ajax/Cancel.php | 9 + .../activeRecordEdit/ajax/Save.php | 21 + .../activeRecordEdit/ajax/SaveClose.php | 14 + .../autocomplete/ajax/FindTerm.php | 62 + .../autocomplete/ajax/PagePicker.php | 26 + .../controllers/moduleEdit/Delete.php | 13 + .../contents/controllers/moduleEdit/Edit.php | 17 + .../controllers/moduleEdit/EditDraft.php | 17 + .../moduleEdit/Togglevisibility.php | 13 + .../controllers/moduleEdit/ajax/Save.php | 22 + .../controllers/moduleEdit/ajax/SaveClose.php | 14 + .../controllers/moduleEdit/ajax/SaveDraft.php | 22 + .../moduleEdit/ajax/SaveDraftClose.php | 14 + .../contents/controllers/pageEdit/Add.php | 10 + .../controllers/pageEdit/Addblock.php | 15 + .../contents/controllers/pageEdit/Edit.php | 27 + .../controllers/pageEdit/Permissions.php | 45 + .../controllers/pageEdit/Properties.php | 32 + .../controllers/pageEdit/ajax/Add.php | 28 + .../controllers/pageEdit/ajax/Addblock.php | 4 + .../pageEdit/ajax/GetChildBlocks.php | 32 + .../controllers/pageEdit/ajax/MoveBlock.php | 4 + .../controllers/pageEdit/ajax/Save.php | 25 + .../controllers/pageEdit/ajax/SaveClose.php | 18 + .../pageEdit/ajax/SavePermissions.php | 50 + .../pageEdit/ajax/SaveProperties.php | 44 + .../pageEdit/ajax/SaveTemplate.php | 16 + .../controllers/siteTree/ajax/AddPage.php | 14 + .../controllers/siteTree/ajax/Delete.php | 11 + .../controllers/siteTree/ajax/GetSiteTree.php | 115 + .../controllers/siteTree/ajax/Hide.php | 15 + .../controllers/siteTree/ajax/Lock.php | 15 + .../controllers/siteTree/ajax/Move.php | 11 + .../controllers/siteTree/ajax/Rename.php | 16 + .../controllers/siteTree/ajax/Show.php | 15 + .../controllers/siteTree/ajax/Unlock.php | 15 + .../controllers/tinymce/ajax/GlzLinkList.php | 24 + .../org/glizycms/contents/events/Menu.php | 10 + .../org/glizycms/contents/js/BlocksEdit.js | 125 + .../org/glizycms/contents/js/ContentsEdit.js | 11 + .../glizycms/contents/js/PageEditIframe.js | 41 + .../org/glizycms/contents/js/SiteTree.js | 291 + .../org/glizycms/contents/locale/en.php | 17 + .../org/glizycms/contents/locale/it.php | 31 + .../glizycms/contents/models/ContentVO.php | 57 + .../glizycms/contents/models/DocumentACL.php | 25 + .../org/glizycms/contents/models/Menu.php | 29 + .../org/glizycms/contents/models/Role.xml | 24 + .../models/proxy/ActiveRecordProxy.php | 89 + .../models/proxy/ContentFindTermProxy.php | 36 + .../contents/models/proxy/ContentProxy.php | 154 + .../contents/models/proxy/MenuProxy.php | 280 + .../models/proxy/ModuleContentProxy.php | 136 + .../contents/services/PageTypeService.php | 61 + .../glizycms/contents/views/ContentsEdit.xml | 144 + .../contents/views/components/PageEdit.php | 169 + .../contents/views/components/ShowHistory.php | 93 + .../views/components/SiteTreeView.php | 75 + .../views/renderer/AbstractCellEdit.php | 116 + .../contents/views/renderer/CellDelete.php | 12 + .../contents/views/renderer/CellEdit.php | 12 + .../views/renderer/CellEditDelete.php | 13 + .../views/renderer/CellEditDeleteVisible.php | 13 + .../views/renderer/CellEditDraftDelete.php | 16 + .../renderer/CellEditDraftDeleteVisible.php | 17 + .../contents/views/renderer/DocumentTitle.php | 13 + .../core/application/AdminApplication.php | 150 + .../glizycms/core/application/Application.php | 310 + .../glizycms/core/application/SiteMapDB.php | 132 + .../core/application/renderer/CellUser.php | 10 + .../application/renderer/CellUserActive.php | 15 + .../org/glizycms/core/helpers/Fulltext.php | 31 + .../org/glizycms/core/models/Content.xml | 171 + .../org/glizycms/core/models/Country.xml | 6 + .../org/glizycms/core/models/Language.xml | 270 + .../classes/org/glizycms/core/models/Menu.xml | 207 + .../org/glizycms/core/models/MenuDetail.xml | 6 + .../core/models/enum/FieldTypeEnum.php | 13 + .../glizycms/core/models/enum/MenuEnum.php | 8 + .../groupManager/models/UserGroup.xml | 11 + .../groupManager/views/GroupManagerEdit.xml | 43 + .../classes/org/glizycms/helpers/Media.php | 98 + .../classes/org/glizycms/helpers/Modules.php | 123 + src/core/classes/org/glizycms/js/.htaccess | 4 + .../org/glizycms/js/formEdit/GlizyFormEdit.js | 718 + .../js/formEdit/GlizyFormEditCheckbox.js | 72 + .../js/formEdit/GlizyFormEditCmsPagePicker.js | 65 + .../js/formEdit/GlizyFormEditColorPicker.js | 31 + .../glizycms/js/formEdit/GlizyFormEditDate.js | 29 + .../js/formEdit/GlizyFormEditDatetime.js | 24 + .../glizycms/js/formEdit/GlizyFormEditFile.js | 62 + .../glizycms/js/formEdit/GlizyFormEditGUID.js | 20 + .../js/formEdit/GlizyFormEditGoogleMaps.js | 272 + .../js/formEdit/GlizyFormEditImageHotspot.js | 1082 + .../js/formEdit/GlizyFormEditMediaPicker.js | 137 + .../js/formEdit/GlizyFormEditPermission.js | 37 + .../GlizyFormEditPhotoGalleryCategory.js | 34 + .../js/formEdit/GlizyFormEditSelectFrom.js | 142 + .../formEdit/GlizyFormEditSelectPageType.js | 76 + .../js/formEdit/GlizyFormEditTINYMCE.js | 41 + .../js/formEdit/GlizyFormEditTreeSelect.js | 89 + .../js/formEdit/GlizyFormEditValuesPreset.js | 29 + .../glizycms/js/formEdit2/GlizyFormEdit.js | 270 + .../js/formEdit2/GlizyFormEditCheckbox.js | 11 + .../formEdit2/GlizyFormEditCmsPagePicker.js | 83 + .../js/formEdit2/GlizyFormEditColorPicker.js | 53 + .../js/formEdit2/GlizyFormEditDate.js | 49 + .../js/formEdit2/GlizyFormEditDateTime.js | 48 + .../js/formEdit2/GlizyFormEditFile.js | 117 + .../js/formEdit2/GlizyFormEditGUID.js | 45 + .../js/formEdit2/GlizyFormEditGoogleMaps.js | 266 + .../js/formEdit2/GlizyFormEditMediaPicker.js | 179 + .../js/formEdit2/GlizyFormEditModalPage.js | 148 + .../js/formEdit2/GlizyFormEditPermission.js | 55 + .../GlizyFormEditPhotoGalleryCategory.js | 57 + .../js/formEdit2/GlizyFormEditRepeat.js | 419 + .../js/formEdit2/GlizyFormEditSelectFrom.js | 153 + .../formEdit2/GlizyFormEditSelectPageType.js | 59 + .../js/formEdit2/GlizyFormEditStandard.js | 52 + .../js/formEdit2/GlizyFormEditTINYMCE.js | 67 + .../glizycms/js/formEdit2/GlizyFormEditUrl.js | 40 + .../org/glizycms/js/glizy-locale/en-EN.js | 81 + .../org/glizycms/js/glizy-locale/it-IT.js | 81 + .../js/jquery/bootstrap-colorpicker/LICENSE | 13 + .../js/jquery/bootstrap-colorpicker/README.md | 15 + .../css/bootstrap-colorpicker.min.css | 6 + .../img/bootstrap-colorpicker/alpha.png | Bin 0 -> 3271 bytes .../img/bootstrap-colorpicker/hue.png | Bin 0 -> 2972 bytes .../img/bootstrap-colorpicker/saturation.png | Bin 0 -> 8817 bytes .../js/bootstrap-colorpicker.min.js | 21 + .../css/datetimepicker.css | 313 + .../js/bootstrap-datetimepicker.js | 1146 ++ .../js/locales/bootstrap-datepicker.uk.js | 14 + .../js/locales/bootstrap-datetimepicker.bg.js | 14 + .../js/locales/bootstrap-datetimepicker.cs.js | 14 + .../js/locales/bootstrap-datetimepicker.da.js | 14 + .../js/locales/bootstrap-datetimepicker.de.js | 14 + .../js/locales/bootstrap-datetimepicker.es.js | 14 + .../js/locales/bootstrap-datetimepicker.fi.js | 14 + .../js/locales/bootstrap-datetimepicker.fr.js | 14 + .../js/locales/bootstrap-datetimepicker.he.js | 15 + .../js/locales/bootstrap-datetimepicker.hr.js | 13 + .../js/locales/bootstrap-datetimepicker.id.js | 13 + .../js/locales/bootstrap-datetimepicker.is.js | 14 + .../js/locales/bootstrap-datetimepicker.it.js | 14 + .../js/locales/bootstrap-datetimepicker.ja.js | 13 + .../js/locales/bootstrap-datetimepicker.kr.js | 13 + .../js/locales/bootstrap-datetimepicker.lt.js | 16 + .../js/locales/bootstrap-datetimepicker.lv.js | 16 + .../js/locales/bootstrap-datetimepicker.ms.js | 14 + .../js/locales/bootstrap-datetimepicker.nb.js | 14 + .../js/locales/bootstrap-datetimepicker.nl.js | 14 + .../js/locales/bootstrap-datetimepicker.pl.js | 15 + .../locales/bootstrap-datetimepicker.pt-BR.js | 14 + .../js/locales/bootstrap-datetimepicker.pt.js | 14 + .../js/locales/bootstrap-datetimepicker.ro.js | 15 + .../bootstrap-datetimepicker.rs-latin.js | 14 + .../js/locales/bootstrap-datetimepicker.rs.js | 14 + .../js/locales/bootstrap-datetimepicker.ru.js | 14 + .../js/locales/bootstrap-datetimepicker.sk.js | 14 + .../js/locales/bootstrap-datetimepicker.sl.js | 14 + .../js/locales/bootstrap-datetimepicker.sv.js | 14 + .../js/locales/bootstrap-datetimepicker.th.js | 14 + .../js/locales/bootstrap-datetimepicker.tr.js | 15 + .../locales/bootstrap-datetimepicker.zh-CN.js | 14 + .../locales/bootstrap-datetimepicker.zh-TW.js | 13 + .../glizycms/js/jquery/dropzone/css/basic.css | 155 + .../js/jquery/dropzone/css/basic2.css | 155 + .../js/jquery/dropzone/css/dropzone.css | 410 + .../glizycms/js/jquery/dropzone/dropzone.js | 1919 ++ .../js/jquery/dropzone/dropzone.min.js | 1 + .../js/jquery/dropzone/images/spritemap.png | Bin 0 -> 10208 bytes .../jquery/dropzone/images/spritemap@2x.png | Bin 0 -> 35675 bytes .../jquery/fancytree/jquery.fancytree-all.js | 7409 +++++++ .../fancytree/jquery.fancytree-all.min.js | 44 + .../js/jquery/fancytree/skin-win7/icons.gif | Bin 0 -> 5492 bytes .../js/jquery/fancytree/skin-win7/loading.gif | Bin 0 -> 3234 bytes .../fancytree/skin-win7/ui.fancytree.css | 595 + .../fancytree/skin-win7/ui.fancytree.less | 146 + .../fancytree/skin-win7/ui.fancytree.min.css | 6 + .../jquery.pnotify/jquery.pnotify.default.css | 94 + .../jquery.pnotify/jquery.pnotify.min.js | 11 + .../js/jquery/jquery.validVal-packed.js | 1 + .../org/glizycms/js/jquery/select2/LICENSE | 12 + .../org/glizycms/js/jquery/select2/README.md | 68 + .../org/glizycms/js/jquery/select2/release.sh | 63 + .../glizycms/js/jquery/select2/select2.css | 524 + .../org/glizycms/js/jquery/select2/select2.js | 2407 +++ .../glizycms/js/jquery/select2/select2.min.js | 82 + .../glizycms/js/jquery/select2/select2.png | Bin 0 -> 613 bytes .../glizycms/js/jquery/select2/select2x2.png | Bin 0 -> 845 bytes .../glizycms/js/jquery/select2/spinner.gif | Bin 0 -> 1849 bytes .../glizycms/js/underscore/underscore-min.js | 6 + .../glizycms/js/underscore/underscore-min.map | 1 + .../js/visualsearch/cancel_search.png | Bin 0 -> 541 bytes .../glizycms/js/visualsearch/dependencies.js | 312 + .../js/visualsearch/dependencies.js.gz | Bin 0 -> 53610 bytes .../glizycms/js/visualsearch/search_glyph.png | Bin 0 -> 420 bytes .../js/visualsearch/visualsearch-datauri.css | 1 + .../visualsearch/visualsearch-datauri.css.gz | Bin 0 -> 2697 bytes .../glizycms/js/visualsearch/visualsearch.css | 1 + .../js/visualsearch/visualsearch.css.gz | Bin 0 -> 1687 bytes .../glizycms/js/visualsearch/visualsearch.js | 67 + .../js/visualsearch/visualsearch.js.gz | Bin 0 -> 7307 bytes .../js/visualsearch/visualsearch_templates.js | 2 + .../visualsearch/visualsearch_templates.js.gz | Bin 0 -> 326 bytes .../glizycms/languages/controllers/Delete.php | 14 + .../glizycms/languages/controllers/Edit.php | 4 + .../languages/controllers/ajax/Cancel.php | 4 + .../languages/controllers/ajax/Save.php | 26 + .../languages/controllers/ajax/SaveClose.php | 14 + .../org/glizycms/languages/locale/en.php | 5 + .../org/glizycms/languages/locale/it.php | 5 + .../languages/models/proxy/LanguagesProxy.php | 122 + .../org/glizycms/languages/views/Admin.xml | 48 + .../views/renderer/CellEditDelete.php | 29 + src/core/classes/org/glizycms/locale/en.php | 104 + src/core/classes/org/glizycms/locale/it.php | 105 + .../org/glizycms/mediaArchive/Bridge.php | 64 + .../org/glizycms/mediaArchive/IBridge.php | 18 + .../glizycms/mediaArchive/MediaManager.php | 143 + .../glizycms/mediaArchive/controllers/Add.php | 19 + .../mediaArchive/controllers/AddFromZip.php | 11 + .../mediaArchive/controllers/Delete.php | 11 + .../mediaArchive/controllers/Index.php | 38 + .../mediaArchive/controllers/ajax/Delete.php | 14 + .../controllers/mediaEdit/Edit.php | 13 + .../controllers/mediaEdit/ajax/Cancel.php | 9 + .../controllers/mediaEdit/ajax/Save.php | 202 + .../controllers/mediaEdit/ajax/SaveClose.php | 16 + .../glizycms/mediaArchive/media/Archive.php | 16 + .../org/glizycms/mediaArchive/media/Audio.php | 16 + .../org/glizycms/mediaArchive/media/Flash.php | 16 + .../org/glizycms/mediaArchive/media/Image.php | 532 + .../org/glizycms/mediaArchive/media/Media.php | 149 + .../glizycms/mediaArchive/media/Office.php | 16 + .../org/glizycms/mediaArchive/media/Other.php | 16 + .../org/glizycms/mediaArchive/media/Pdf.php | 15 + .../org/glizycms/mediaArchive/media/Video.php | 16 + .../org/glizycms/mediaArchive/models/Exif.xml | 5 + .../mediaArchive/models/proxy/MediaProxy.php | 196 + .../mediaArchive/services/ExifService.php | 122 + .../services/MediaMappingService.php | 183 + .../mediaArchive/views/MediaArchive.xml | 217 + .../mediaArchive/views/MediaPicker.xml | 126 + .../views/MediaStorageBrowser.xml | 23 + .../views/components/CustomStorageBrowser.php | 257 + .../views/components/FilePicker.php | 89 + .../views/components/ShowExif.php | 100 + .../views/renderer/CellMediaArchive.php | 39 + .../views/renderer/CellMediaArchiveInfo.php | 21 + .../views/renderer/CellMediaArchiveThumb.php | 25 + ...ctiveRecordSimpleDocumentArraysIndexed.php | 84 + .../classes/org/glizycms/models/Media.xml | 77 + .../modulesManager/controllers/Duplicate.php | 29 + .../controllers/ajax/Disable.php | 12 + .../controllers/ajax/Enable.php | 20 + .../modulesManager/views/ModulesManager.xml | 28 + .../views/components/Datagrid.php | 126 + .../org/glizycms/roleManager/AdminPage.xml | 47 + .../roleManager/controllers/Login.php | 22 + .../controllers/StateController.php | 130 + .../org/glizycms/roleManager/models/Group.xml | 17 + .../org/glizycms/roleManager/models/Role.xml | 6 + .../org/glizycms/roleManager/models/User.xml | 17 + .../roleManager/services/RoleService.php | 16 + .../org/glizycms/roleManager/views/Input.php | 83 + .../roleManager/views/Permissions.php | 98 + .../siteProperties/controllers/Index.php | 11 + .../siteProperties/controllers/ajax/Save.php | 18 + .../siteProperties/views/SiteProperties.xml | 23 + .../speakingUrl/AbstractDocumentResolver.php | 104 + .../speakingUrl/AbstractUrlResolver.php | 27 + .../org/glizycms/speakingUrl/IUrlResolver.php | 9 + .../org/glizycms/speakingUrl/Manager.php | 90 + .../org/glizycms/speakingUrl/PageResolver.php | 91 + .../speakingUrl/models/SpeakingUrl.xml | 28 + .../models/proxy/SpeakingUrlProxy.php | 73 + .../controllers/CheckTemplateTabDraw.php | 13 + .../template/controllers/Template.php | 15 + .../template/controllers/ajax/Save.php | 12 + .../controllers/ajax/SaveTemplate.php | 16 + .../fe/views/AbstractLessTemplate.php | 91 + .../glizycms/template/models/TemplateVO.php | 13 + .../template/models/proxy/TemplateProxy.php | 208 + .../template/views/TemplateSelect.xml | 31 + .../views/components/SelectTemplate.php | 70 + .../views/components/TemplateColorEdit.php | 88 + .../views/components/TemplateEdit.php | 89 + .../org/glizycms/userManager/fe/Module.php | 17 + .../userManager/fe/config/routing.xml | 7 + .../fe/controllers/login/Login.php | 13 + .../fe/controllers/login/Logout.php | 12 + .../fe/controllers/user/LostPassword.php | 38 + .../fe/controllers/user/Modify.php | 56 + .../fe/controllers/user/Registration.php | 40 + .../glizycms/userManager/models/UserGroup.xml | 17 + .../userManager/views/UserManagerEdit.xml | 52 + .../glizycms/views/TemplateModuleAdmin.xml | 60 + .../views/components/EditLanguage.php | 74 + .../views/components/FormButtonsPanel.php | 36 + .../glizycms/views/components/FormEdit.php | 312 + .../components/FormEditWithAjaxSteps.php | 25 + .../views/components/GoogleAnalytics.php | 35 + .../views/components/LanguageNavigation.php | 61 + .../org/glizycms/views/components/MvcPage.php | 127 + .../org/glizycms/views/components/Page.php | 157 + .../glizycms/views/components/PagePicker.php | 43 + .../views/components/SearchFilters.php | 31 + .../glizycms/views/components/SelectPage.php | 113 + .../views/components/SelectPageType.php | 148 + .../views/components/SelectPageTypeNew.php | 175 + .../views/components/VisualSearch.php | 244 + src/core/composer.json | 19 + src/core/composer.lock | 811 + src/core/core.inc.php | 869 + src/core/libs/Cache_Lite/LICENSE | 458 + src/core/libs/Cache_Lite/Lite.php | 886 + src/core/libs/Cache_Lite/Lite/File.php | 90 + src/core/libs/Cache_Lite/Lite/Function.php | 208 + .../libs/Cache_Lite/Lite/NestedOutput.php | 56 + src/core/libs/Cache_Lite/Lite/Output.php | 68 + .../DebugBar/Bridge/CacheCacheCollector.php | 62 + .../DebugBar/Bridge/DoctrineCollector.php | 98 + .../libs/DebugBar/Bridge/MonologCollector.php | 103 + .../libs/DebugBar/Bridge/PropelCollector.php | 253 + .../libs/DebugBar/Bridge/SlimCollector.php | 66 + .../Bridge/SwiftMailer/SwiftLogCollector.php | 44 + .../Bridge/SwiftMailer/SwiftMailCollector.php | 90 + .../Bridge/Twig/TraceableTwigEnvironment.php | 412 + .../Bridge/Twig/TraceableTwigTemplate.php | 126 + .../DebugBar/Bridge/Twig/TwigCollector.php | 87 + .../DataCollector/AggregatedCollector.php | 166 + .../DebugBar/DataCollector/AssetProvider.php | 28 + .../DataCollector/ConfigCollector.php | 71 + .../DebugBar/DataCollector/DataCollector.php | 90 + .../DataCollector/DataCollectorInterface.php | 31 + .../DataCollector/ExceptionsCollector.php | 111 + .../DataCollector/LocalizationCollector.php | 66 + .../DataCollector/MemoryCollector.php | 63 + .../MessagesAggregateInterface.php | 21 + .../DataCollector/MessagesCollector.php | 152 + .../DataCollector/PDO/PDOCollector.php | 182 + .../DataCollector/PDO/TraceablePDO.php | 196 + .../PDO/TraceablePDOStatement.php | 71 + .../DataCollector/PDO/TracedStatement.php | 240 + .../DataCollector/PhpInfoCollector.php | 29 + .../DebugBar/DataCollector/Renderable.php | 25 + .../DataCollector/RequestDataCollector.php | 48 + .../DataCollector/TimeDataCollector.php | 213 + .../DebugBar/DataFormatter/DataFormatter.php | 173 + .../DataFormatter/DataFormatterInterface.php | 42 + src/core/libs/DebugBar/DebugBar.php | 468 + src/core/libs/DebugBar/DebugBarException.php | 16 + .../libs/DebugBar/HttpDriverInterface.php | 63 + src/core/libs/DebugBar/JavascriptRenderer.php | 919 + src/core/libs/DebugBar/LICENSE | 19 + src/core/libs/DebugBar/OpenHandler.php | 107 + src/core/libs/DebugBar/PhpHttpDriver.php | 49 + src/core/libs/DebugBar/RequestIdGenerator.php | 22 + .../DebugBar/RequestIdGeneratorInterface.php | 21 + src/core/libs/DebugBar/Resources/.htaccess | 4 + src/core/libs/DebugBar/Resources/debugbar.css | 225 + src/core/libs/DebugBar/Resources/debugbar.js | 1085 + src/core/libs/DebugBar/Resources/icons.png | Bin 0 -> 500 bytes .../libs/DebugBar/Resources/openhandler.css | 69 + .../libs/DebugBar/Resources/openhandler.js | 201 + src/core/libs/DebugBar/Resources/php-icon.png | Bin 0 -> 3621 bytes .../font-awesome/css/font-awesome.min.css | 4 + .../vendor/font-awesome/fonts/FontAwesome.otf | Bin 0 -> 75188 bytes .../fonts/fontawesome-webfont.eot | Bin 0 -> 72449 bytes .../fonts/fontawesome-webfont.svg | 504 + .../fonts/fontawesome-webfont.ttf | Bin 0 -> 141564 bytes .../fonts/fontawesome-webfont.woff | Bin 0 -> 83760 bytes .../vendor/highlightjs/highlight.pack.js | 1 + .../vendor/highlightjs/styles/github.css | 125 + .../vendor/jquery/dist/jquery.min.js | 4 + src/core/libs/DebugBar/Resources/widgets.css | 186 + src/core/libs/DebugBar/Resources/widgets.js | 430 + .../Resources/widgets/mails/widget.css | 12 + .../Resources/widgets/mails/widget.js | 40 + .../Resources/widgets/sqlqueries/widget.css | 82 + .../Resources/widgets/sqlqueries/widget.js | 96 + .../Resources/widgets/templates/widget.css | 23 + .../Resources/widgets/templates/widget.js | 38 + src/core/libs/DebugBar/StandardDebugBar.php | 34 + .../libs/DebugBar/Storage/FileStorage.php | 108 + .../DebugBar/Storage/MemcachedStorage.php | 91 + src/core/libs/DebugBar/Storage/PdoStorage.php | 117 + .../libs/DebugBar/Storage/RedisStorage.php | 74 + .../DebugBar/Storage/StorageInterface.php | 45 + .../DebugBar/Storage/pdo_storage_schema.sql | 16 + src/core/libs/Diff/Diff.php | 179 + src/core/libs/Diff/Diff/Renderer/Abstract.php | 82 + .../libs/Diff/Diff/Renderer/Html/Array.php | 224 + .../libs/Diff/Diff/Renderer/Html/Inline.php | 143 + .../Diff/Diff/Renderer/Html/SideBySide.php | 163 + .../libs/Diff/Diff/Renderer/Text/Context.php | 128 + .../libs/Diff/Diff/Renderer/Text/Unified.php | 87 + src/core/libs/Diff/Diff/SequenceMatcher.php | 742 + .../Common/Annotations/Annotation.php | 79 + .../Annotations/Annotation/Attribute.php | 47 + .../Annotations/Annotation/Attributes.php | 37 + .../Annotation/IgnoreAnnotation.php | 54 + .../Annotations/Annotation/Required.php | 33 + .../Common/Annotations/Annotation/Target.php | 107 + .../Annotations/AnnotationException.php | 127 + .../Common/Annotations/AnnotationReader.php | 310 + .../Common/Annotations/AnnotationRegistry.php | 139 + .../Common/Annotations/CachedReader.php | 250 + .../Doctrine/Common/Annotations/DocLexer.php | 132 + .../Doctrine/Common/Annotations/DocParser.php | 988 + .../Common/Annotations/FileCacheReader.php | 258 + .../Common/Annotations/IndexedReader.php | 141 + .../Doctrine/Common/Annotations/PhpParser.php | 80 + .../Doctrine/Common/Annotations/Reader.php | 67 + .../Annotations/SimpleAnnotationReader.php | 157 + .../Common/Annotations/TokenParser.php | 175 + .../libs/Doctrine/Common/Cache/ApcCache.php | 93 + .../libs/Doctrine/Common/Cache/ArrayCache.php | 96 + src/core/libs/Doctrine/Common/Cache/Cache.php | 102 + .../Doctrine/Common/Cache/CacheProvider.php | 231 + .../libs/Doctrine/Common/Cache/FileCache.php | 132 + .../Doctrine/Common/Cache/FilesystemCache.php | 114 + .../Doctrine/Common/Cache/MemcacheCache.php | 121 + .../Doctrine/Common/Cache/MemcachedCache.php | 124 + .../Doctrine/Common/Cache/PhpFileCache.php | 108 + .../libs/Doctrine/Common/Cache/RedisCache.php | 119 + .../Doctrine/Common/Cache/WinCacheCache.php | 93 + .../Doctrine/Common/Cache/XcacheCache.php | 110 + .../Doctrine/Common/Cache/ZendDataCache.php | 84 + src/core/libs/Doctrine/Common/ClassLoader.php | 263 + .../Common/Collections/ArrayCollection.php | 500 + .../Common/Collections/Collection.php | 243 + .../Doctrine/Common/Collections/Criteria.php | 240 + .../Expr/ClosureExpressionVisitor.php | 195 + .../Common/Collections/Expr/Comparison.php | 75 + .../Collections/Expr/CompositeExpression.php | 72 + .../Common/Collections/Expr/Expression.php | 31 + .../Collections/Expr/ExpressionVisitor.php | 81 + .../Common/Collections/Expr/Value.php | 41 + .../Common/Collections/ExpressionBuilder.php | 149 + .../Common/Collections/Selectable.php | 48 + .../libs/Doctrine/Common/CommonException.php | 28 + src/core/libs/Doctrine/Common/Comparable.php | 49 + src/core/libs/Doctrine/Common/EventArgs.php | 67 + .../libs/Doctrine/Common/EventManager.php | 147 + .../libs/Doctrine/Common/EventSubscriber.php | 45 + src/core/libs/Doctrine/Common/Lexer.php | 266 + .../Doctrine/Common/NotifyPropertyChanged.php | 45 + .../Persistence/AbstractManagerRegistry.php | 259 + .../Common/Persistence/ConnectionRegistry.php | 63 + .../Persistence/Event/LifecycleEventArgs.php | 77 + .../Event/LoadClassMetadataEventArgs.php | 76 + .../Persistence/Event/ManagerEventArgs.php | 59 + .../Persistence/Event/OnClearEventArgs.php | 84 + .../Persistence/Event/PreUpdateEventArgs.php | 133 + .../Common/Persistence/ManagerRegistry.php | 112 + .../Mapping/AbstractClassMetadataFactory.php | 383 + .../Persistence/Mapping/ClassMetadata.php | 165 + .../Mapping/ClassMetadataFactory.php | 74 + .../Mapping/Driver/AnnotationDriver.php | 214 + .../Mapping/Driver/DefaultFileLocator.php | 170 + .../Persistence/Mapping/Driver/FileDriver.php | 214 + .../Mapping/Driver/FileLocator.php | 71 + .../Mapping/Driver/MappingDriver.php | 56 + .../Mapping/Driver/MappingDriverChain.php | 168 + .../Persistence/Mapping/Driver/PHPDriver.php | 72 + .../Mapping/Driver/StaticPHPDriver.php | 141 + .../Mapping/Driver/SymfonyFileLocator.php | 214 + .../Persistence/Mapping/MappingException.php | 86 + .../Persistence/Mapping/ReflectionService.php | 80 + .../Mapping/RuntimeReflectionService.php | 102 + .../Mapping/StaticReflectionService.php | 107 + .../Common/Persistence/ObjectManager.php | 152 + .../Common/Persistence/ObjectManagerAware.php | 49 + .../Common/Persistence/ObjectRepository.php | 78 + .../Common/Persistence/PersistentObject.php | 244 + .../Doctrine/Common/Persistence/Proxy.php | 60 + .../Common/PropertyChangedListener.php | 48 + .../Reflection/ClassFinderInterface.php | 38 + .../Common/Reflection/Psr0FindFile.php | 83 + .../ReflectionProviderInterface.php | 45 + .../Reflection/StaticReflectionClass.php | 112 + .../Reflection/StaticReflectionMethod.php | 103 + .../Reflection/StaticReflectionParser.php | 282 + .../Reflection/StaticReflectionProperty.php | 77 + .../libs/Doctrine/Common/Util/ClassUtils.php | 103 + src/core/libs/Doctrine/Common/Util/Debug.php | 135 + .../libs/Doctrine/Common/Util/Inflector.php | 72 + src/core/libs/Doctrine/Common/Version.php | 55 + .../Doctrine/DBAL/Cache/ArrayStatement.php | 108 + .../Doctrine/DBAL/Cache/CacheException.php | 37 + .../Doctrine/DBAL/Cache/QueryCacheProfile.php | 131 + .../DBAL/Cache/ResultCacheStatement.php | 239 + src/core/libs/Doctrine/DBAL/Configuration.php | 113 + src/core/libs/Doctrine/DBAL/Connection.php | 1308 ++ .../Doctrine/DBAL/ConnectionException.php | 54 + .../Connections/MasterSlaveConnection.php | 353 + src/core/libs/Doctrine/DBAL/DBALException.php | 106 + src/core/libs/Doctrine/DBAL/Driver.php | 72 + .../libs/Doctrine/DBAL/Driver/Connection.php | 42 + .../Driver/DrizzlePDOMySql/Connection.php | 41 + .../DBAL/Driver/DrizzlePDOMySql/Driver.php | 99 + .../DBAL/Driver/IBMDB2/DB2Connection.php | 115 + .../Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php | 111 + .../DBAL/Driver/IBMDB2/DB2Exception.php | 27 + .../DBAL/Driver/IBMDB2/DB2Statement.php | 214 + .../Doctrine/DBAL/Driver/Mysqli/Driver.php | 69 + .../DBAL/Driver/Mysqli/MysqliConnection.php | 146 + .../DBAL/Driver/Mysqli/MysqliException.php | 26 + .../DBAL/Driver/Mysqli/MysqliStatement.php | 342 + .../libs/Doctrine/DBAL/Driver/OCI8/Driver.php | 99 + .../DBAL/Driver/OCI8/OCI8Connection.php | 200 + .../DBAL/Driver/OCI8/OCI8Exception.php | 30 + .../DBAL/Driver/OCI8/OCI8Statement.php | 268 + .../Doctrine/DBAL/Driver/PDOConnection.php | 40 + .../Doctrine/DBAL/Driver/PDOIbm/Driver.php | 126 + .../Doctrine/DBAL/Driver/PDOMySql/Driver.php | 102 + .../Doctrine/DBAL/Driver/PDOOracle/Driver.php | 98 + .../Doctrine/DBAL/Driver/PDOPgSql/Driver.php | 70 + .../Doctrine/DBAL/Driver/PDOSqlite/Driver.php | 116 + .../DBAL/Driver/PDOSqlsrv/Connection.php | 45 + .../Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php | 87 + .../Doctrine/DBAL/Driver/PDOStatement.php | 50 + .../Doctrine/DBAL/Driver/ResultStatement.php | 93 + .../Doctrine/DBAL/Driver/SQLSrv/Driver.php | 72 + .../DBAL/Driver/SQLSrv/LastInsertId.php | 42 + .../DBAL/Driver/SQLSrv/SQLSrvConnection.php | 161 + .../DBAL/Driver/SQLSrv/SQLSrvException.php | 43 + .../DBAL/Driver/SQLSrv/SQLSrvStatement.php | 251 + .../libs/Doctrine/DBAL/Driver/Statement.php | 125 + src/core/libs/Doctrine/DBAL/DriverManager.php | 176 + .../DBAL/Event/ConnectionEventArgs.php | 79 + .../DBAL/Event/Listeners/MysqlSessionInit.php | 74 + .../Event/Listeners/OracleSessionInit.php | 80 + .../DBAL/Event/Listeners/SQLSessionInit.php | 63 + .../SchemaAlterTableAddColumnEventArgs.php | 114 + .../SchemaAlterTableChangeColumnEventArgs.php | 114 + .../DBAL/Event/SchemaAlterTableEventArgs.php | 99 + .../SchemaAlterTableRemoveColumnEventArgs.php | 114 + .../SchemaAlterTableRenameColumnEventArgs.php | 129 + .../Event/SchemaColumnDefinitionEventArgs.php | 137 + .../SchemaCreateTableColumnEventArgs.php | 114 + .../DBAL/Event/SchemaCreateTableEventArgs.php | 128 + .../DBAL/Event/SchemaDropTableEventArgs.php | 98 + .../Doctrine/DBAL/Event/SchemaEventArgs.php | 56 + .../Event/SchemaIndexDefinitionEventArgs.php | 122 + src/core/libs/Doctrine/DBAL/Events.php | 48 + .../libs/Doctrine/DBAL/Id/TableGenerator.php | 160 + .../DBAL/Id/TableGeneratorSchemaVisitor.php | 90 + src/core/libs/Doctrine/DBAL/LockMode.php | 42 + .../libs/Doctrine/DBAL/Logging/DebugStack.php | 69 + .../Doctrine/DBAL/Logging/EchoSQLLogger.php | 61 + .../Doctrine/DBAL/Logging/LoggerChain.php | 64 + .../libs/Doctrine/DBAL/Logging/SQLLogger.php | 54 + .../DBAL/Platforms/AbstractPlatform.php | 2854 +++ .../Doctrine/DBAL/Platforms/DB2Platform.php | 545 + .../DBAL/Platforms/DrizzlePlatform.php | 495 + .../DBAL/Platforms/Keywords/DB2Keywords.php | 438 + .../Platforms/Keywords/DrizzleKeywords.php | 340 + .../DBAL/Platforms/Keywords/KeywordList.php | 63 + .../DBAL/Platforms/Keywords/MsSQLKeywords.php | 243 + .../DBAL/Platforms/Keywords/MySQLKeywords.php | 268 + .../Platforms/Keywords/OracleKeywords.php | 156 + .../Platforms/Keywords/PostgreSQLKeywords.php | 131 + .../Keywords/ReservedKeywordsValidator.php | 116 + .../Platforms/Keywords/SQLiteKeywords.php | 164 + .../Doctrine/DBAL/Platforms/MySqlPlatform.php | 720 + .../DBAL/Platforms/OraclePlatform.php | 822 + .../DBAL/Platforms/PostgreSqlPlatform.php | 762 + .../DBAL/Platforms/SQLAzurePlatform.php | 51 + .../DBAL/Platforms/SQLServer2005Platform.php | 54 + .../DBAL/Platforms/SQLServer2008Platform.php | 100 + .../DBAL/Platforms/SQLServerPlatform.php | 905 + .../DBAL/Platforms/SqlitePlatform.php | 529 + .../Doctrine/DBAL/Portability/Connection.php | 119 + .../Doctrine/DBAL/Portability/Statement.php | 195 + .../Query/Expression/CompositeExpression.php | 130 + .../Query/Expression/ExpressionBuilder.php | 264 + .../libs/Doctrine/DBAL/Query/QueryBuilder.php | 1087 + .../Doctrine/DBAL/Query/QueryException.php | 40 + src/core/libs/Doctrine/DBAL/README.markdown | 0 .../libs/Doctrine/DBAL/SQLParserUtils.php | 183 + .../Doctrine/DBAL/Schema/AbstractAsset.php | 214 + .../DBAL/Schema/AbstractSchemaManager.php | 896 + src/core/libs/Doctrine/DBAL/Schema/Column.php | 423 + .../libs/Doctrine/DBAL/Schema/ColumnDiff.php | 58 + .../libs/Doctrine/DBAL/Schema/Comparator.php | 415 + .../libs/Doctrine/DBAL/Schema/Constraint.php | 42 + .../Doctrine/DBAL/Schema/DB2SchemaManager.php | 214 + .../DBAL/Schema/DrizzleSchemaManager.php | 96 + .../DBAL/Schema/ForeignKeyConstraint.php | 193 + src/core/libs/Doctrine/DBAL/Schema/Index.php | 242 + .../DBAL/Schema/MySqlSchemaManager.php | 208 + .../DBAL/Schema/OracleSchemaManager.php | 286 + .../DBAL/Schema/PostgreSqlSchemaManager.php | 365 + .../DBAL/Schema/SQLServerSchemaManager.php | 263 + src/core/libs/Doctrine/DBAL/Schema/Schema.php | 373 + .../Doctrine/DBAL/Schema/SchemaConfig.php | 119 + .../libs/Doctrine/DBAL/Schema/SchemaDiff.php | 176 + .../Doctrine/DBAL/Schema/SchemaException.php | 126 + .../libs/Doctrine/DBAL/Schema/Sequence.php | 120 + .../DBAL/Schema/SqliteSchemaManager.php | 190 + .../AbstractSchemaSynchronizer.php | 58 + .../Synchronizer/SchemaSynchronizer.php | 96 + .../SingleDatabaseSynchronizer.php | 197 + src/core/libs/Doctrine/DBAL/Schema/Table.php | 678 + .../libs/Doctrine/DBAL/Schema/TableDiff.php | 136 + src/core/libs/Doctrine/DBAL/Schema/View.php | 53 + .../Visitor/CreateSchemaSqlCollector.php | 178 + .../Schema/Visitor/DropSchemaSqlCollector.php | 160 + .../Doctrine/DBAL/Schema/Visitor/Graphviz.php | 151 + .../Schema/Visitor/RemoveNamespacedAssets.php | 113 + .../Doctrine/DBAL/Schema/Visitor/Visitor.php | 75 + .../DBAL/Sharding/PoolingShardConnection.php | 201 + .../DBAL/Sharding/PoolingShardManager.php | 98 + .../SQLAzureFederationsSynchronizer.php | 296 + .../SQLAzure/SQLAzureShardManager.php | 238 + .../SQLAzure/Schema/MultiTenantVisitor.php | 161 + .../ShardChoser/MultiTenantShardChoser.php | 37 + .../DBAL/Sharding/ShardChoser/ShardChoser.php | 41 + .../Doctrine/DBAL/Sharding/ShardManager.php | 95 + .../DBAL/Sharding/ShardingException.php | 61 + src/core/libs/Doctrine/DBAL/Statement.php | 264 + .../Tools/Console/Command/ImportCommand.php | 124 + .../Console/Command/ReservedWordsCommand.php | 133 + .../Tools/Console/Command/RunSqlCommand.php | 87 + .../Tools/Console/Helper/ConnectionHelper.php | 74 + .../libs/Doctrine/DBAL/Types/ArrayType.php | 64 + .../libs/Doctrine/DBAL/Types/BigIntType.php | 56 + .../libs/Doctrine/DBAL/Types/BlobType.php | 67 + .../libs/Doctrine/DBAL/Types/BooleanType.php | 57 + .../DBAL/Types/ConversionException.php | 65 + .../libs/Doctrine/DBAL/Types/DateTimeType.php | 59 + .../Doctrine/DBAL/Types/DateTimeTzType.php | 79 + .../libs/Doctrine/DBAL/Types/DateType.php | 59 + .../libs/Doctrine/DBAL/Types/DecimalType.php | 45 + .../libs/Doctrine/DBAL/Types/FloatType.php | 54 + .../libs/Doctrine/DBAL/Types/GuidType.php | 42 + .../libs/Doctrine/DBAL/Types/IntegerType.php | 53 + .../Doctrine/DBAL/Types/JsonArrayType.php | 66 + .../libs/Doctrine/DBAL/Types/ObjectType.php | 64 + .../Doctrine/DBAL/Types/SimpleArrayType.php | 69 + .../libs/Doctrine/DBAL/Types/SmallIntType.php | 52 + .../libs/Doctrine/DBAL/Types/StringType.php | 50 + .../libs/Doctrine/DBAL/Types/TextType.php | 56 + .../libs/Doctrine/DBAL/Types/TimeType.php | 68 + src/core/libs/Doctrine/DBAL/Types/Type.php | 306 + .../Doctrine/DBAL/Types/VarDateTimeType.php | 60 + src/core/libs/Doctrine/DBAL/Version.php | 55 + src/core/libs/PHPTAL5/COPYING | 504 + src/core/libs/PHPTAL5/PHPTAL.php | 1226 ++ .../PHPTAL5/PHPTAL/ConfigurationException.php | 24 + src/core/libs/PHPTAL5/PHPTAL/Context.php | 563 + .../libs/PHPTAL5/PHPTAL/DefaultKeyword.php | 39 + src/core/libs/PHPTAL5/PHPTAL/Dom/Attr.php | 196 + .../libs/PHPTAL5/PHPTAL/Dom/CDATASection.php | 49 + src/core/libs/PHPTAL5/PHPTAL/Dom/Comment.php | 28 + src/core/libs/PHPTAL5/PHPTAL/Dom/Defs.php | 246 + .../PHPTAL5/PHPTAL/Dom/DocumentBuilder.php | 63 + .../libs/PHPTAL5/PHPTAL/Dom/DocumentType.php | 33 + src/core/libs/PHPTAL5/PHPTAL/Dom/Element.php | 521 + src/core/libs/PHPTAL5/PHPTAL/Dom/Node.php | 105 + .../PHPTAL/Dom/PHPTALDocumentBuilder.php | 167 + .../PHPTAL/Dom/ProcessingInstruction.php | 34 + .../libs/PHPTAL5/PHPTAL/Dom/SaxXmlParser.php | 480 + src/core/libs/PHPTAL5/PHPTAL/Dom/Text.php | 31 + .../PHPTAL5/PHPTAL/Dom/XmlDeclaration.php | 29 + .../libs/PHPTAL5/PHPTAL/Dom/XmlnsState.php | 95 + src/core/libs/PHPTAL5/PHPTAL/Exception.php | 23 + .../libs/PHPTAL5/PHPTAL/ExceptionHandler.php | 81 + src/core/libs/PHPTAL5/PHPTAL/FileSource.php | 51 + .../PHPTAL5/PHPTAL/FileSourceResolver.php | 46 + src/core/libs/PHPTAL5/PHPTAL/Filter.php | 32 + .../libs/PHPTAL5/PHPTAL/GetTextTranslator.php | 183 + src/core/libs/PHPTAL5/PHPTAL/IOException.php | 25 + .../PHPTAL/InvalidVariableNameException.php | 25 + src/core/libs/PHPTAL5/PHPTAL/Keywords.php | 26 + .../PHPTAL5/PHPTAL/MacroMissingException.php | 24 + src/core/libs/PHPTAL5/PHPTAL/Namespace.php | 70 + .../libs/PHPTAL5/PHPTAL/Namespace/Builtin.php | 38 + .../libs/PHPTAL5/PHPTAL/Namespace/I18N.php | 32 + .../libs/PHPTAL5/PHPTAL/Namespace/METAL.php | 31 + .../libs/PHPTAL5/PHPTAL/Namespace/PHPTAL.php | 31 + .../libs/PHPTAL5/PHPTAL/Namespace/TAL.php | 36 + .../PHPTAL5/PHPTAL/NamespaceAttribute.php | 99 + .../PHPTAL/NamespaceAttributeContent.php | 23 + .../PHPTAL/NamespaceAttributeReplace.php | 23 + .../PHPTAL/NamespaceAttributeSurround.php | 23 + .../libs/PHPTAL5/PHPTAL/NothingKeyword.php | 39 + .../libs/PHPTAL5/PHPTAL/ParserException.php | 24 + .../libs/PHPTAL5/PHPTAL/Php/Attribute.php | 98 + .../PHPTAL/Php/Attribute/I18N/Attributes.php | 118 + .../PHPTAL/Php/Attribute/I18N/Data.php | 36 + .../PHPTAL/Php/Attribute/I18N/Domain.php | 50 + .../PHPTAL/Php/Attribute/I18N/Name.php | 47 + .../PHPTAL/Php/Attribute/I18N/Source.php | 48 + .../PHPTAL/Php/Attribute/I18N/Target.php | 43 + .../PHPTAL/Php/Attribute/I18N/Translate.php | 130 + .../Php/Attribute/METAL/DefineMacro.php | 67 + .../PHPTAL/Php/Attribute/METAL/DefineSlot.php | 70 + .../PHPTAL/Php/Attribute/METAL/FillSlot.php | 148 + .../PHPTAL/Php/Attribute/METAL/UseMacro.php | 135 + .../PHPTAL/Php/Attribute/PHPTAL/Cache.php | 97 + .../PHPTAL/Php/Attribute/PHPTAL/Debug.php | 34 + .../PHPTAL/Php/Attribute/PHPTAL/Id.php | 53 + .../PHPTAL/Php/Attribute/PHPTAL/Tales.php | 45 + .../PHPTAL/Php/Attribute/TAL/Attributes.php | 213 + .../PHPTAL/Php/Attribute/TAL/Comment.php | 30 + .../PHPTAL/Php/Attribute/TAL/Condition.php | 93 + .../PHPTAL/Php/Attribute/TAL/Content.php | 95 + .../PHPTAL/Php/Attribute/TAL/Define.php | 193 + .../PHPTAL/Php/Attribute/TAL/OmitTag.php | 70 + .../PHPTAL/Php/Attribute/TAL/OnError.php | 73 + .../PHPTAL/Php/Attribute/TAL/Repeat.php | 99 + .../PHPTAL/Php/Attribute/TAL/Replace.php | 117 + .../libs/PHPTAL5/PHPTAL/Php/CodeWriter.php | 511 + src/core/libs/PHPTAL5/PHPTAL/Php/State.php | 254 + .../PHPTAL5/PHPTAL/Php/TalesChainExecutor.php | 96 + .../PHPTAL5/PHPTAL/Php/TalesChainReader.php | 25 + .../libs/PHPTAL5/PHPTAL/Php/TalesInternal.php | 503 + .../libs/PHPTAL5/PHPTAL/Php/Transformer.php | 418 + src/core/libs/PHPTAL5/PHPTAL/PreFilter.php | 132 + .../PHPTAL5/PHPTAL/PreFilter/Compress.php | 282 + .../PHPTAL5/PHPTAL/PreFilter/Normalize.php | 108 + .../PHPTAL/PreFilter/StripComments.php | 34 + .../libs/PHPTAL5/PHPTAL/RepeatController.php | 323 + .../PHPTAL5/PHPTAL/RepeatControllerGroups.php | 199 + src/core/libs/PHPTAL5/PHPTAL/Source.php | 52 + .../libs/PHPTAL5/PHPTAL/SourceResolver.php | 25 + src/core/libs/PHPTAL5/PHPTAL/StringSource.php | 51 + src/core/libs/PHPTAL5/PHPTAL/Tales.php | 58 + .../libs/PHPTAL5/PHPTAL/TalesRegistry.php | 185 + .../libs/PHPTAL5/PHPTAL/TemplateException.php | 160 + src/core/libs/PHPTAL5/PHPTAL/Tokenizer.php | 69 + .../PHPTAL5/PHPTAL/TranslationService.php | 62 + src/core/libs/PHPTAL5/PHPTAL/Trigger.php | 29 + .../PHPTAL/UnknownModifierException.php | 35 + .../PHPTAL/VariableNotFoundException.php | 24 + src/core/libs/PHPTAL5/phptal_lint.php | 283 + src/core/libs/Psr/Log/AbstractLogger.php | 120 + .../libs/Psr/Log/InvalidArgumentException.php | 7 + src/core/libs/Psr/Log/LogLevel.php | 18 + .../libs/Psr/Log/LoggerAwareInterface.php | 17 + src/core/libs/Psr/Log/LoggerAwareTrait.php | 22 + src/core/libs/Psr/Log/LoggerInterface.php | 114 + src/core/libs/Psr/Log/LoggerTrait.php | 131 + src/core/libs/Psr/Log/NullLogger.php | 27 + .../libs/Psr/Log/Test/LoggerInterfaceTest.php | 130 + src/core/libs/Twig/Autoloader.php | 48 + src/core/libs/Twig/Compiler.php | 270 + src/core/libs/Twig/CompilerInterface.php | 35 + src/core/libs/Twig/Environment.php | 1254 ++ src/core/libs/Twig/Error.php | 248 + src/core/libs/Twig/Error/Loader.php | 31 + src/core/libs/Twig/Error/Runtime.php | 20 + src/core/libs/Twig/Error/Syntax.php | 20 + src/core/libs/Twig/ExistsLoaderInterface.php | 28 + src/core/libs/Twig/ExpressionParser.php | 598 + src/core/libs/Twig/Extension.php | 93 + src/core/libs/Twig/Extension/Core.php | 1463 ++ src/core/libs/Twig/Extension/Debug.php | 71 + src/core/libs/Twig/Extension/Escaper.php | 107 + src/core/libs/Twig/Extension/Optimizer.php | 35 + src/core/libs/Twig/Extension/Sandbox.php | 112 + src/core/libs/Twig/Extension/Staging.php | 113 + src/core/libs/Twig/Extension/StringLoader.php | 64 + src/core/libs/Twig/ExtensionInterface.php | 83 + src/core/libs/Twig/Filter.php | 81 + src/core/libs/Twig/Filter/Function.php | 37 + src/core/libs/Twig/Filter/Method.php | 39 + src/core/libs/Twig/Filter/Node.php | 39 + .../libs/Twig/FilterCallableInterface.php | 23 + src/core/libs/Twig/FilterInterface.php | 42 + src/core/libs/Twig/Function.php | 71 + src/core/libs/Twig/Function/Function.php | 38 + src/core/libs/Twig/Function/Method.php | 40 + src/core/libs/Twig/Function/Node.php | 39 + .../libs/Twig/FunctionCallableInterface.php | 23 + src/core/libs/Twig/FunctionInterface.php | 39 + src/core/libs/Twig/Lexer.php | 409 + src/core/libs/Twig/LexerInterface.php | 31 + src/core/libs/Twig/Loader/Array.php | 95 + src/core/libs/Twig/Loader/Chain.php | 138 + src/core/libs/Twig/Loader/Filesystem.php | 229 + src/core/libs/Twig/Loader/String.php | 59 + src/core/libs/Twig/LoaderInterface.php | 52 + src/core/libs/Twig/Markup.php | 37 + src/core/libs/Twig/Node.php | 226 + src/core/libs/Twig/Node/AutoEscape.php | 39 + src/core/libs/Twig/Node/Block.php | 44 + src/core/libs/Twig/Node/BlockReference.php | 37 + src/core/libs/Twig/Node/Body.php | 19 + src/core/libs/Twig/Node/Do.php | 38 + src/core/libs/Twig/Node/Embed.php | 38 + src/core/libs/Twig/Node/Expression.php | 20 + src/core/libs/Twig/Node/Expression/Array.php | 86 + .../libs/Twig/Node/Expression/AssignName.php | 28 + src/core/libs/Twig/Node/Expression/Binary.php | 40 + .../libs/Twig/Node/Expression/Binary/Add.php | 18 + .../libs/Twig/Node/Expression/Binary/And.php | 18 + .../Node/Expression/Binary/BitwiseAnd.php | 18 + .../Twig/Node/Expression/Binary/BitwiseOr.php | 18 + .../Node/Expression/Binary/BitwiseXor.php | 18 + .../Twig/Node/Expression/Binary/Concat.php | 18 + .../libs/Twig/Node/Expression/Binary/Div.php | 18 + .../Twig/Node/Expression/Binary/EndsWith.php | 30 + .../Twig/Node/Expression/Binary/Equal.php | 17 + .../Twig/Node/Expression/Binary/FloorDiv.php | 29 + .../Twig/Node/Expression/Binary/Greater.php | 17 + .../Node/Expression/Binary/GreaterEqual.php | 17 + .../libs/Twig/Node/Expression/Binary/In.php | 33 + .../libs/Twig/Node/Expression/Binary/Less.php | 17 + .../Twig/Node/Expression/Binary/LessEqual.php | 17 + .../Twig/Node/Expression/Binary/Matches.php | 28 + .../libs/Twig/Node/Expression/Binary/Mod.php | 18 + .../libs/Twig/Node/Expression/Binary/Mul.php | 18 + .../Twig/Node/Expression/Binary/NotEqual.php | 17 + .../Twig/Node/Expression/Binary/NotIn.php | 33 + .../libs/Twig/Node/Expression/Binary/Or.php | 18 + .../Twig/Node/Expression/Binary/Power.php | 33 + .../Twig/Node/Expression/Binary/Range.php | 33 + .../Node/Expression/Binary/StartsWith.php | 28 + .../libs/Twig/Node/Expression/Binary/Sub.php | 18 + .../Twig/Node/Expression/BlockReference.php | 51 + src/core/libs/Twig/Node/Expression/Call.php | 178 + .../libs/Twig/Node/Expression/Conditional.php | 31 + .../libs/Twig/Node/Expression/Constant.php | 23 + .../Node/Expression/ExtensionReference.php | 33 + src/core/libs/Twig/Node/Expression/Filter.php | 36 + .../Twig/Node/Expression/Filter/Default.php | 43 + .../libs/Twig/Node/Expression/Function.php | 35 + .../libs/Twig/Node/Expression/GetAttr.php | 53 + .../libs/Twig/Node/Expression/MethodCall.php | 41 + src/core/libs/Twig/Node/Expression/Name.php | 88 + src/core/libs/Twig/Node/Expression/Parent.php | 47 + .../libs/Twig/Node/Expression/TempName.php | 26 + src/core/libs/Twig/Node/Expression/Test.php | 32 + .../Twig/Node/Expression/Test/Constant.php | 46 + .../Twig/Node/Expression/Test/Defined.php | 54 + .../Twig/Node/Expression/Test/Divisibleby.php | 33 + .../libs/Twig/Node/Expression/Test/Even.php | 32 + .../libs/Twig/Node/Expression/Test/Null.php | 31 + .../libs/Twig/Node/Expression/Test/Odd.php | 32 + .../libs/Twig/Node/Expression/Test/Sameas.php | 29 + src/core/libs/Twig/Node/Expression/Unary.php | 30 + .../libs/Twig/Node/Expression/Unary/Neg.php | 18 + .../libs/Twig/Node/Expression/Unary/Not.php | 18 + .../libs/Twig/Node/Expression/Unary/Pos.php | 18 + src/core/libs/Twig/Node/Flush.php | 36 + src/core/libs/Twig/Node/For.php | 112 + src/core/libs/Twig/Node/ForLoop.php | 55 + src/core/libs/Twig/Node/If.php | 66 + src/core/libs/Twig/Node/Import.php | 50 + src/core/libs/Twig/Node/Include.php | 99 + src/core/libs/Twig/Node/Macro.php | 96 + src/core/libs/Twig/Node/Module.php | 383 + src/core/libs/Twig/Node/Print.php | 39 + src/core/libs/Twig/Node/Sandbox.php | 47 + src/core/libs/Twig/Node/SandboxedModule.php | 60 + src/core/libs/Twig/Node/SandboxedPrint.php | 59 + src/core/libs/Twig/Node/Set.php | 101 + src/core/libs/Twig/Node/SetTemp.php | 35 + src/core/libs/Twig/Node/Spaceless.php | 40 + src/core/libs/Twig/Node/Text.php | 39 + src/core/libs/Twig/NodeInterface.php | 30 + src/core/libs/Twig/NodeOutputInterface.php | 19 + src/core/libs/Twig/NodeTraverser.php | 88 + src/core/libs/Twig/NodeVisitor/Escaper.php | 167 + src/core/libs/Twig/NodeVisitor/Optimizer.php | 246 + .../libs/Twig/NodeVisitor/SafeAnalysis.php | 139 + src/core/libs/Twig/NodeVisitor/Sandbox.php | 92 + src/core/libs/Twig/NodeVisitorInterface.php | 47 + src/core/libs/Twig/Parser.php | 390 + src/core/libs/Twig/ParserInterface.php | 30 + src/core/libs/Twig/Sandbox/SecurityError.php | 19 + src/core/libs/Twig/Sandbox/SecurityPolicy.php | 119 + .../Twig/Sandbox/SecurityPolicyInterface.php | 24 + src/core/libs/Twig/SimpleFilter.php | 94 + src/core/libs/Twig/SimpleFunction.php | 84 + src/core/libs/Twig/SimpleTest.php | 46 + src/core/libs/Twig/Template.php | 484 + src/core/libs/Twig/TemplateInterface.php | 47 + src/core/libs/Twig/Test.php | 34 + src/core/libs/Twig/Test/Function.php | 35 + .../libs/Twig/Test/IntegrationTestCase.php | 154 + src/core/libs/Twig/Test/Method.php | 37 + src/core/libs/Twig/Test/Node.php | 37 + src/core/libs/Twig/Test/NodeTestCase.php | 58 + src/core/libs/Twig/TestCallableInterface.php | 21 + src/core/libs/Twig/TestInterface.php | 26 + src/core/libs/Twig/Token.php | 216 + src/core/libs/Twig/TokenParser.php | 33 + src/core/libs/Twig/TokenParser/AutoEscape.php | 89 + src/core/libs/Twig/TokenParser/Block.php | 81 + src/core/libs/Twig/TokenParser/Do.php | 42 + src/core/libs/Twig/TokenParser/Embed.php | 66 + src/core/libs/Twig/TokenParser/Extends.php | 52 + src/core/libs/Twig/TokenParser/Filter.php | 61 + src/core/libs/Twig/TokenParser/Flush.php | 42 + src/core/libs/Twig/TokenParser/For.php | 135 + src/core/libs/Twig/TokenParser/From.php | 70 + src/core/libs/Twig/TokenParser/If.php | 94 + src/core/libs/Twig/TokenParser/Import.php | 49 + src/core/libs/Twig/TokenParser/Include.php | 75 + src/core/libs/Twig/TokenParser/Macro.php | 68 + src/core/libs/Twig/TokenParser/Sandbox.php | 68 + src/core/libs/Twig/TokenParser/Set.php | 83 + src/core/libs/Twig/TokenParser/Spaceless.php | 59 + src/core/libs/Twig/TokenParser/Use.php | 76 + src/core/libs/Twig/TokenParserBroker.php | 136 + .../libs/Twig/TokenParserBrokerInterface.php | 45 + src/core/libs/Twig/TokenParserInterface.php | 43 + src/core/libs/Twig/TokenStream.php | 156 + .../libs/Whoops/Exception/ErrorException.php | 14 + src/core/libs/Whoops/Exception/Frame.php | 252 + .../libs/Whoops/Exception/FrameCollection.php | 122 + src/core/libs/Whoops/Exception/Inspector.php | 115 + .../libs/Whoops/Handler/CallbackHandler.php | 49 + src/core/libs/Whoops/Handler/Handler.php | 89 + .../libs/Whoops/Handler/HandlerInterface.php | 33 + .../Whoops/Handler/JsonResponseHandler.php | 109 + .../libs/Whoops/Handler/PrettyPageHandler.php | 333 + .../Whoops/Handler/XmlResponseHandler.php | 137 + src/core/libs/Whoops/LICENSE.md | 19 + .../Phalcon/WhoopsServiceProvider.php | 78 + .../Provider/Silex/WhoopsServiceProvider.php | 85 + .../Provider/Zend/ExceptionStrategy.php | 59 + src/core/libs/Whoops/Provider/Zend/Module.php | 106 + .../Provider/Zend/RouteNotFoundStrategy.php | 64 + .../Provider/Zend/module.config.example.php | 20 + src/core/libs/Whoops/README.md | 248 + .../libs/Whoops/Resources/pretty-page.css | 319 + .../libs/Whoops/Resources/pretty-template.php | 216 + src/core/libs/Whoops/Run.php | 382 + src/core/libs/jsmin/jsmin.php | 291 + src/core/libs/lessphp/LICENSE | 660 + src/core/libs/lessphp/README.md | 96 + src/core/libs/lessphp/composer.json | 25 + src/core/libs/lessphp/lessc.inc.php | 3734 ++++ .../libs/phpUnsharpMask/phpUnsharpMask.php | 149 + src/core/libs/phpmailer/class.phpmailer.php | 1921 ++ src/core/libs/phpmailer/class.smtp.php | 1062 + .../phpmailer/language/phpmailer.lang-br.php | 21 + .../phpmailer/language/phpmailer.lang-ca.php | 22 + .../phpmailer/language/phpmailer.lang-cz.php | 24 + .../phpmailer/language/phpmailer.lang-de.php | 23 + .../phpmailer/language/phpmailer.lang-dk.php | 24 + .../phpmailer/language/phpmailer.lang-en.php | 23 + .../phpmailer/language/phpmailer.lang-es.php | 23 + .../phpmailer/language/phpmailer.lang-et.php | 22 + .../phpmailer/language/phpmailer.lang-fi.php | 23 + .../phpmailer/language/phpmailer.lang-fo.php | 25 + .../phpmailer/language/phpmailer.lang-fr.php | 24 + .../phpmailer/language/phpmailer.lang-hu.php | 23 + .../phpmailer/language/phpmailer.lang-it.php | 28 + .../phpmailer/language/phpmailer.lang-ja.php | 25 + .../phpmailer/language/phpmailer.lang-nl.php | 23 + .../phpmailer/language/phpmailer.lang-no.php | 23 + .../phpmailer/language/phpmailer.lang-pl.php | 24 + .../phpmailer/language/phpmailer.lang-ro.php | 23 + .../phpmailer/language/phpmailer.lang-ru.php | 23 + .../phpmailer/language/phpmailer.lang-se.php | 24 + .../phpmailer/language/phpmailer.lang-tr.php | 24 + .../libs/sql-formatter/lib/SqlFormatter.php | 1085 + src/core/pages/.htaccess | 4 + src/core/pages/admin_bootstrap.php | 29 + src/core/pages/ajaxadmin_bootstrap.php | 14 + src/core/pages/bootstrap.php | 14 + src/core/pages/errors/404.php | 51 + src/core/pages/errors/debug.php | 118 + src/core/pages/errors/general.php | 52 + src/core/pages/getImage.php | 43 + src/core/static/.htaccess | 4 + src/core/static/images/calendar.gif | Bin 0 -> 223 bytes src/core/static/images/close_button.gif | Bin 0 -> 85 bytes src/core/static/images/colorPicker.gif | Bin 0 -> 5346 bytes src/core/static/images/icon_add.gif | Bin 0 -> 106 bytes src/core/static/images/icon_addThesaurus.gif | Bin 0 -> 372 bytes src/core/static/images/icon_add_off.gif | Bin 0 -> 106 bytes src/core/static/images/icon_checked.gif | Bin 0 -> 231 bytes src/core/static/images/icon_checked_off.gif | Bin 0 -> 229 bytes src/core/static/images/icon_delete.gif | Bin 0 -> 323 bytes src/core/static/images/icon_delete_off.gif | Bin 0 -> 213 bytes src/core/static/images/icon_document.gif | Bin 0 -> 354 bytes src/core/static/images/icon_down.gif | Bin 0 -> 124 bytes src/core/static/images/icon_down_off.gif | Bin 0 -> 124 bytes src/core/static/images/icon_download.gif | Bin 0 -> 339 bytes src/core/static/images/icon_download_off.gif | Bin 0 -> 339 bytes src/core/static/images/icon_edit.gif | Bin 0 -> 198 bytes src/core/static/images/icon_editDraft.gif | Bin 0 -> 211 bytes src/core/static/images/icon_editDraft_off.gif | Bin 0 -> 157 bytes src/core/static/images/icon_edit_off.gif | Bin 0 -> 145 bytes src/core/static/images/icon_folder.gif | Bin 0 -> 342 bytes src/core/static/images/icon_go.gif | Bin 0 -> 268 bytes src/core/static/images/icon_go_off.gif | Bin 0 -> 976 bytes src/core/static/images/icon_invisible.gif | Bin 0 -> 218 bytes src/core/static/images/icon_invisible_off.gif | Bin 0 -> 214 bytes src/core/static/images/icon_lock.gif | Bin 0 -> 288 bytes src/core/static/images/icon_lock_off.gif | Bin 0 -> 312 bytes src/core/static/images/icon_orderDown.gif | Bin 0 -> 59 bytes .../static/images/icon_orderDownBlack.gif | Bin 0 -> 59 bytes src/core/static/images/icon_orderUp.gif | Bin 0 -> 60 bytes src/core/static/images/icon_orderUpBlack.gif | Bin 0 -> 60 bytes src/core/static/images/icon_preview.gif | Bin 0 -> 208 bytes src/core/static/images/icon_preview_off.gif | Bin 0 -> 156 bytes src/core/static/images/icon_publish.gif | Bin 0 -> 231 bytes src/core/static/images/icon_publish_off.gif | Bin 0 -> 229 bytes src/core/static/images/icon_unchecked.gif | Bin 0 -> 223 bytes src/core/static/images/icon_unchecked_off.gif | Bin 0 -> 218 bytes src/core/static/images/icon_unpublish.gif | Bin 0 -> 223 bytes src/core/static/images/icon_unpublish_off.gif | Bin 0 -> 218 bytes src/core/static/images/icon_up.gif | Bin 0 -> 124 bytes src/core/static/images/icon_up_off.gif | Bin 0 -> 123 bytes src/core/static/images/icon_visible.gif | Bin 0 -> 83 bytes src/core/static/images/icon_visible_off.gif | Bin 0 -> 83 bytes src/core/static/images/mediaArchive.png | Bin 0 -> 3650 bytes src/core/static/images/mediaAudio.png | Bin 0 -> 6052 bytes src/core/static/images/mediaFlash.png | Bin 0 -> 2499 bytes src/core/static/images/mediaImage.png | Bin 0 -> 2632 bytes src/core/static/images/mediaOffice.png | Bin 0 -> 2677 bytes src/core/static/images/mediaOther.png | Bin 0 -> 1614 bytes src/core/static/images/mediaPdf.png | Bin 0 -> 3852 bytes src/core/static/images/mediaVideo.png | Bin 0 -> 2713 bytes src/core/static/images/noimage.jpg | Bin 0 -> 1315 bytes src/core/static/images/picker.gif | Bin 0 -> 332 bytes src/core/static/images/preload.gif | Bin 0 -> 735 bytes src/core/static/images/slider_cursor.gif | Bin 0 -> 60 bytes src/core/static/js/Glizy.js | 333 + src/core/static/js/Glizy_pageContent.js | 2620 +++ src/core/static/js/Glizy_pageFilters.js | 170 + src/core/static/js/Glizy_tiny_mce.js | 283 + src/core/static/js/dejavu/LICENSE | 19 + src/core/static/js/dejavu/README.md | 669 + src/core/static/js/dejavu/loose/dejavu.js | 2307 +++ src/core/static/js/dejavu/loose/dejavu.min.js | 7 + src/core/static/js/dejavu/strict/dejavu.js | 4822 +++++ src/core/static/js/formWithAjaxSteps.js | 95 + .../jquery.simplemodal.1.4.1.min.js | 25 + src/core/static/js/jscalendar/ChangeLog.txt | 500 + src/core/static/js/jscalendar/README.txt | 33 + .../js/jscalendar/bugtest-hidden-selects.html | 108 + .../static/js/jscalendar/calendar-blue.css | 231 + .../static/js/jscalendar/calendar-blue2.css | 235 + .../static/js/jscalendar/calendar-brown.css | 224 + .../static/js/jscalendar/calendar-green.css | 228 + .../static/js/jscalendar/calendar-setup.js | 181 + .../js/jscalendar/calendar-setup_stripped.js | 21 + .../static/js/jscalendar/calendar-system.css | 250 + .../static/js/jscalendar/calendar-tas.css | 238 + .../static/js/jscalendar/calendar-win2k-1.css | 270 + .../static/js/jscalendar/calendar-win2k-2.css | 270 + .../js/jscalendar/calendar-win2k-cold-1.css | 264 + .../js/jscalendar/calendar-win2k-cold-2.css | 270 + src/core/static/js/jscalendar/calendar.js | 1715 ++ src/core/static/js/jscalendar/calendar.php | 119 + .../static/js/jscalendar/calendar_stripped.js | 12 + src/core/static/js/jscalendar/img.gif | Bin 0 -> 223 bytes src/core/static/js/jscalendar/index.html | 333 + .../static/js/jscalendar/lang/calendar-af.js | 39 + .../static/js/jscalendar/lang/calendar-br.js | 45 + .../static/js/jscalendar/lang/calendar-ca.js | 45 + .../js/jscalendar/lang/calendar-cs-win.js | 34 + .../static/js/jscalendar/lang/calendar-da.js | 63 + .../static/js/jscalendar/lang/calendar-de.js | 123 + .../static/js/jscalendar/lang/calendar-du.js | 45 + .../static/js/jscalendar/lang/calendar-el.js | 89 + .../static/js/jscalendar/lang/calendar-en.js | 123 + .../static/js/jscalendar/lang/calendar-es.js | 114 + .../static/js/jscalendar/lang/calendar-fi.js | 98 + .../static/js/jscalendar/lang/calendar-fr.js | 109 + .../js/jscalendar/lang/calendar-hr-utf8.js | 49 + .../static/js/jscalendar/lang/calendar-hr.js | Bin 0 -> 3088 bytes .../static/js/jscalendar/lang/calendar-hu.js | 45 + .../static/js/jscalendar/lang/calendar-it.js | 86 + .../static/js/jscalendar/lang/calendar-jp.js | 45 + .../js/jscalendar/lang/calendar-ko-utf8.js | 120 + .../static/js/jscalendar/lang/calendar-ko.js | 120 + .../js/jscalendar/lang/calendar-lt-utf8.js | 114 + .../static/js/jscalendar/lang/calendar-lt.js | 114 + .../static/js/jscalendar/lang/calendar-nl.js | 45 + .../static/js/jscalendar/lang/calendar-no.js | 45 + .../js/jscalendar/lang/calendar-pl-utf8.js | 93 + .../static/js/jscalendar/lang/calendar-pl.js | 56 + .../static/js/jscalendar/lang/calendar-pt.js | 45 + .../static/js/jscalendar/lang/calendar-ro.js | 66 + .../static/js/jscalendar/lang/calendar-ru.js | 45 + .../static/js/jscalendar/lang/calendar-si.js | 94 + .../static/js/jscalendar/lang/calendar-sk.js | 99 + .../static/js/jscalendar/lang/calendar-sp.js | 63 + .../static/js/jscalendar/lang/calendar-sv.js | 93 + .../static/js/jscalendar/lang/calendar-tr.js | 58 + .../static/js/jscalendar/lang/calendar-zh.js | 45 + src/core/static/js/jscalendar/menuarrow.gif | Bin 0 -> 68 bytes src/core/static/js/jscalendar/menuarrow2.gif | Bin 0 -> 49 bytes .../static/js/jscalendar/release-notes.html | 334 + src/core/static/js/jscalendar/simple-1.html | 244 + src/core/static/js/jscalendar/simple-2.html | 108 + src/core/static/js/jscalendar/simple-3.html | 130 + .../static/js/jscalendar/test-position.html | 40 + src/core/static/js/jscalendar/test.php | 116 + src/core/static/js/locale/de.js | 33 + src/core/static/js/locale/en.js | 34 + src/core/static/js/locale/fr.js | 33 + src/core/static/js/locale/it.js | 34 + .../static/js/progressBar/progressBar.css | 83 + src/core/static/js/progressBar/progressBar.js | 52 + src/core/static/js/tiny_mce/langs/de.js | 1 + src/core/static/js/tiny_mce/langs/en.js | 1 + src/core/static/js/tiny_mce/langs/fr.js | 1 + src/core/static/js/tiny_mce/langs/it.js | 1 + src/core/static/js/tiny_mce/license.txt | 504 + .../plugins/GLZ_image/css/GLZ_image.css | 72 + .../plugins/GLZ_image/editor_plugin.js | 67 + .../js/tiny_mce/plugins/GLZ_image/image.htm | 115 + .../plugins/GLZ_image/images/sample.gif | Bin 0 -> 1624 bytes .../plugins/GLZ_image/jscripts/functions.js | 318 + .../js/tiny_mce/plugins/GLZ_image/langs/en.js | 56 + .../js/tiny_mce/plugins/GLZ_image/langs/it.js | 57 + .../plugins/GLZ_link/css/GLZ_link.css | 41 + .../plugins/GLZ_link/editor_plugin.js | 77 + .../plugins/GLZ_link/jscripts/functions.js | 400 + .../js/tiny_mce/plugins/GLZ_link/langs/en.js | 34 + .../js/tiny_mce/plugins/GLZ_link/langs/it.js | 34 + .../js/tiny_mce/plugins/GLZ_link/link.htm | 121 + .../js/tiny_mce/plugins/advhr/css/advhr.css | 5 + .../tiny_mce/plugins/advhr/editor_plugin.js | 1 + .../plugins/advhr/editor_plugin_src.js | 57 + .../js/tiny_mce/plugins/advhr/js/rule.js | 43 + .../js/tiny_mce/plugins/advhr/langs/de_dlg.js | 1 + .../js/tiny_mce/plugins/advhr/langs/en_dlg.js | 1 + .../js/tiny_mce/plugins/advhr/langs/fr_dlg.js | 1 + .../js/tiny_mce/plugins/advhr/langs/it_dlg.js | 1 + .../static/js/tiny_mce/plugins/advhr/rule.htm | 58 + .../plugins/advimage/css/advimage.css | 13 + .../plugins/advimage/editor_plugin.js | 1 + .../plugins/advimage/editor_plugin_src.js | 50 + .../js/tiny_mce/plugins/advimage/image.htm | 235 + .../tiny_mce/plugins/advimage/img/sample.gif | Bin 0 -> 1624 bytes .../js/tiny_mce/plugins/advimage/js/image.js | 462 + .../tiny_mce/plugins/advimage/langs/de_dlg.js | 1 + .../tiny_mce/plugins/advimage/langs/en_dlg.js | 1 + .../tiny_mce/plugins/advimage/langs/fr_dlg.js | 1 + .../tiny_mce/plugins/advimage/langs/it_dlg.js | 1 + .../tiny_mce/plugins/advlink/css/advlink.css | 8 + .../tiny_mce/plugins/advlink/editor_plugin.js | 1 + .../plugins/advlink/editor_plugin_src.js | 61 + .../js/tiny_mce/plugins/advlink/js/advlink.js | 532 + .../tiny_mce/plugins/advlink/langs/de_dlg.js | 1 + .../tiny_mce/plugins/advlink/langs/en_dlg.js | 1 + .../tiny_mce/plugins/advlink/langs/fr_dlg.js | 1 + .../tiny_mce/plugins/advlink/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/advlink/link.htm | 338 + .../tiny_mce/plugins/advlist/editor_plugin.js | 1 + .../plugins/advlist/editor_plugin_src.js | 176 + .../plugins/autolink/editor_plugin.js | 1 + .../plugins/autolink/editor_plugin_src.js | 172 + .../plugins/autoresize/editor_plugin.js | 1 + .../plugins/autoresize/editor_plugin_src.js | 137 + .../plugins/autosave/editor_plugin.js | 1 + .../plugins/autosave/editor_plugin_src.js | 431 + .../js/tiny_mce/plugins/autosave/langs/en.js | 4 + .../tiny_mce/plugins/bbcode/editor_plugin.js | 1 + .../plugins/bbcode/editor_plugin_src.js | 120 + .../plugins/contextmenu/editor_plugin.js | 1 + .../plugins/contextmenu/editor_plugin_src.js | 160 + .../plugins/directionality/editor_plugin.js | 1 + .../directionality/editor_plugin_src.js | 82 + .../plugins/emotions/editor_plugin.js | 1 + .../plugins/emotions/editor_plugin_src.js | 43 + .../js/tiny_mce/plugins/emotions/emotions.htm | 41 + .../plugins/emotions/img/smiley-cool.gif | Bin 0 -> 354 bytes .../plugins/emotions/img/smiley-cry.gif | Bin 0 -> 329 bytes .../emotions/img/smiley-embarassed.gif | Bin 0 -> 331 bytes .../emotions/img/smiley-foot-in-mouth.gif | Bin 0 -> 342 bytes .../plugins/emotions/img/smiley-frown.gif | Bin 0 -> 340 bytes .../plugins/emotions/img/smiley-innocent.gif | Bin 0 -> 336 bytes .../plugins/emotions/img/smiley-kiss.gif | Bin 0 -> 338 bytes .../plugins/emotions/img/smiley-laughing.gif | Bin 0 -> 343 bytes .../emotions/img/smiley-money-mouth.gif | Bin 0 -> 321 bytes .../plugins/emotions/img/smiley-sealed.gif | Bin 0 -> 323 bytes .../plugins/emotions/img/smiley-smile.gif | Bin 0 -> 344 bytes .../plugins/emotions/img/smiley-surprised.gif | Bin 0 -> 338 bytes .../emotions/img/smiley-tongue-out.gif | Bin 0 -> 328 bytes .../plugins/emotions/img/smiley-undecided.gif | Bin 0 -> 337 bytes .../plugins/emotions/img/smiley-wink.gif | Bin 0 -> 350 bytes .../plugins/emotions/img/smiley-yell.gif | Bin 0 -> 336 bytes .../tiny_mce/plugins/emotions/js/emotions.js | 22 + .../tiny_mce/plugins/emotions/langs/de_dlg.js | 1 + .../tiny_mce/plugins/emotions/langs/en_dlg.js | 1 + .../tiny_mce/plugins/emotions/langs/fr_dlg.js | 1 + .../tiny_mce/plugins/emotions/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/example/dialog.htm | 22 + .../tiny_mce/plugins/example/editor_plugin.js | 1 + .../plugins/example/editor_plugin_src.js | 84 + .../tiny_mce/plugins/example/img/example.gif | Bin 0 -> 87 bytes .../js/tiny_mce/plugins/example/js/dialog.js | 19 + .../js/tiny_mce/plugins/example/langs/en.js | 3 + .../tiny_mce/plugins/example/langs/en_dlg.js | 3 + .../example_dependency/editor_plugin.js | 1 + .../example_dependency/editor_plugin_src.js | 50 + .../plugins/fullpage/css/fullpage.css | 143 + .../plugins/fullpage/editor_plugin.js | 1 + .../plugins/fullpage/editor_plugin_src.js | 405 + .../js/tiny_mce/plugins/fullpage/fullpage.htm | 259 + .../tiny_mce/plugins/fullpage/js/fullpage.js | 232 + .../tiny_mce/plugins/fullpage/langs/de_dlg.js | 1 + .../tiny_mce/plugins/fullpage/langs/en_dlg.js | 1 + .../tiny_mce/plugins/fullpage/langs/fr_dlg.js | 1 + .../tiny_mce/plugins/fullpage/langs/it_dlg.js | 1 + .../plugins/fullscreen/editor_plugin.js | 1 + .../plugins/fullscreen/editor_plugin_src.js | 159 + .../plugins/fullscreen/fullscreen.htm | 110 + .../tiny_mce/plugins/fxeditor/css/styles.css | 88 + .../js/tiny_mce/plugins/fxeditor/dialog.html | 511 + .../plugins/fxeditor/editor_plugin.js | 85 + .../plugins/fxeditor/images/bg/content.png | Bin 0 -> 149 bytes .../plugins/fxeditor/images/formula.png | Bin 0 -> 466 bytes .../plugins/fxeditor/images/ico/ico.png | Bin 0 -> 1345 bytes .../plugins/fxeditor/images/plugin.gif | Bin 0 -> 388 bytes .../plugins/fxeditor/images/risultato.png | Bin 0 -> 4683 bytes .../tiny_mce/plugins/fxeditor/img/example.gif | Bin 0 -> 87 bytes .../js/tiny_mce/plugins/fxeditor/js/dialog.js | 301 + .../plugins/fxeditor/js/jquery-textrange.js | 178 + .../tiny_mce/plugins/fxeditor/js/mathmap.js | 353 + .../plugins/fxeditor/js/underscore-min.js | 1 + .../plugins/fxeditor/js/undo-manager.js | 121 + .../fxeditor/js/vendor/jquery-1.8.2.min.js | 2 + .../fxeditor/js/vendor/modernizr-2.6.2.min.js | 4 + .../js/tiny_mce/plugins/fxeditor/langs/en.js | 3 + .../tiny_mce/plugins/fxeditor/langs/en_dlg.js | 3 + .../js/tiny_mce/plugins/fxeditor/langs/it.js | 3 + .../tiny_mce/plugins/fxeditor/langs/it_dlg.js | 3 + .../plugins/fxeditor/less/global.less | 27 + .../plugins/fxeditor/less/libs/h5bp.less | 298 + .../plugins/fxeditor/less/libs/mixins.less | 136 + .../plugins/fxeditor/less/libs/normalize.less | 504 + .../fxeditor/less/libs/wp-default.less | 69 + .../plugins/fxeditor/less/structure.less | 202 + .../plugins/fxeditor/less/styles.less | 12 + .../tiny_mce/plugins/iespell/editor_plugin.js | 1 + .../plugins/iespell/editor_plugin_src.js | 54 + .../plugins/inlinepopups/editor_plugin.js | 1 + .../plugins/inlinepopups/editor_plugin_src.js | 699 + .../skins/clearlooks2/img/alert.gif | Bin 0 -> 810 bytes .../skins/clearlooks2/img/button.gif | Bin 0 -> 272 bytes .../skins/clearlooks2/img/buttons.gif | Bin 0 -> 1195 bytes .../skins/clearlooks2/img/confirm.gif | Bin 0 -> 907 bytes .../skins/clearlooks2/img/corners.gif | Bin 0 -> 909 bytes .../skins/clearlooks2/img/horizontal.gif | Bin 0 -> 769 bytes .../skins/clearlooks2/img/vertical.gif | Bin 0 -> 84 bytes .../inlinepopups/skins/clearlooks2/window.css | 90 + .../plugins/inlinepopups/template.htm | 387 + .../plugins/insertdatetime/editor_plugin.js | 1 + .../insertdatetime/editor_plugin_src.js | 83 + .../tiny_mce/plugins/layer/editor_plugin.js | 1 + .../plugins/layer/editor_plugin_src.js | 262 + .../plugins/legacyoutput/editor_plugin.js | 1 + .../plugins/legacyoutput/editor_plugin_src.js | 139 + .../tiny_mce/plugins/lists/editor_plugin.js | 1 + .../plugins/lists/editor_plugin_src.js | 781 + .../js/tiny_mce/plugins/media/css/media.css | 17 + .../tiny_mce/plugins/media/editor_plugin.js | 1 + .../plugins/media/editor_plugin_src.js | 890 + .../js/tiny_mce/plugins/media/js/embed.js | 73 + .../js/tiny_mce/plugins/media/js/media.js | 453 + .../js/tiny_mce/plugins/media/langs/de_dlg.js | 1 + .../js/tiny_mce/plugins/media/langs/en_dlg.js | 1 + .../js/tiny_mce/plugins/media/langs/fr_dlg.js | 1 + .../js/tiny_mce/plugins/media/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/media/media.htm | 922 + .../js/tiny_mce/plugins/media/moxieplayer.swf | Bin 0 -> 33931 bytes .../plugins/nonbreaking/editor_plugin.js | 1 + .../plugins/nonbreaking/editor_plugin_src.js | 54 + .../plugins/noneditable/editor_plugin.js | 1 + .../plugins/noneditable/editor_plugin_src.js | 95 + .../plugins/pagebreak/editor_plugin.js | 1 + .../plugins/pagebreak/editor_plugin_src.js | 74 + .../tiny_mce/plugins/paste/editor_plugin.js | 1 + .../plugins/paste/editor_plugin_src.js | 871 + .../js/tiny_mce/plugins/paste/js/pastetext.js | 36 + .../js/tiny_mce/plugins/paste/js/pasteword.js | 51 + .../js/tiny_mce/plugins/paste/langs/de_dlg.js | 1 + .../js/tiny_mce/plugins/paste/langs/en_dlg.js | 1 + .../js/tiny_mce/plugins/paste/langs/fr_dlg.js | 1 + .../js/tiny_mce/plugins/paste/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/paste/pastetext.htm | 27 + .../js/tiny_mce/plugins/paste/pasteword.htm | 21 + .../tiny_mce/plugins/preview/editor_plugin.js | 1 + .../plugins/preview/editor_plugin_src.js | 53 + .../js/tiny_mce/plugins/preview/example.html | 28 + .../plugins/preview/jscripts/embed.js | 73 + .../js/tiny_mce/plugins/preview/preview.html | 17 + .../tiny_mce/plugins/print/editor_plugin.js | 1 + .../plugins/print/editor_plugin_src.js | 34 + .../js/tiny_mce/plugins/save/editor_plugin.js | 1 + .../plugins/save/editor_plugin_src.js | 101 + .../searchreplace/css/searchreplace.css | 6 + .../plugins/searchreplace/editor_plugin.js | 1 + .../searchreplace/editor_plugin_src.js | 61 + .../plugins/searchreplace/js/searchreplace.js | 142 + .../plugins/searchreplace/langs/de_dlg.js | 1 + .../plugins/searchreplace/langs/en_dlg.js | 1 + .../plugins/searchreplace/langs/fr_dlg.js | 1 + .../plugins/searchreplace/langs/it_dlg.js | 1 + .../plugins/searchreplace/searchreplace.htm | 100 + .../plugins/spellchecker/css/content.css | 1 + .../plugins/spellchecker/editor_plugin.js | 1 + .../plugins/spellchecker/editor_plugin_src.js | 436 + .../plugins/spellchecker/img/wline.gif | Bin 0 -> 46 bytes .../js/tiny_mce/plugins/style/css/props.css | 13 + .../tiny_mce/plugins/style/editor_plugin.js | 1 + .../plugins/style/editor_plugin_src.js | 55 + .../js/tiny_mce/plugins/style/js/props.js | 635 + .../js/tiny_mce/plugins/style/langs/de_dlg.js | 1 + .../js/tiny_mce/plugins/style/langs/en_dlg.js | 1 + .../js/tiny_mce/plugins/style/langs/fr_dlg.js | 1 + .../js/tiny_mce/plugins/style/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/style/props.htm | 840 + .../plugins/tabfocus/editor_plugin.js | 1 + .../plugins/tabfocus/editor_plugin_src.js | 122 + .../static/js/tiny_mce/plugins/table/cell.htm | 180 + .../js/tiny_mce/plugins/table/css/cell.css | 17 + .../js/tiny_mce/plugins/table/css/row.css | 25 + .../js/tiny_mce/plugins/table/css/table.css | 13 + .../tiny_mce/plugins/table/editor_plugin.js | 1 + .../plugins/table/editor_plugin_src.js | 1364 ++ .../js/tiny_mce/plugins/table/js/cell.js | 319 + .../tiny_mce/plugins/table/js/merge_cells.js | 27 + .../js/tiny_mce/plugins/table/js/row.js | 237 + .../js/tiny_mce/plugins/table/js/table.js | 450 + .../js/tiny_mce/plugins/table/langs/de_dlg.js | 1 + .../js/tiny_mce/plugins/table/langs/en_dlg.js | 1 + .../js/tiny_mce/plugins/table/langs/fr_dlg.js | 1 + .../js/tiny_mce/plugins/table/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/table/merge_cells.htm | 32 + .../static/js/tiny_mce/plugins/table/row.htm | 158 + .../js/tiny_mce/plugins/table/table.htm | 188 + .../js/tiny_mce/plugins/template/blank.htm | 12 + .../plugins/template/css/template.css | 23 + .../plugins/template/editor_plugin.js | 1 + .../plugins/template/editor_plugin_src.js | 159 + .../tiny_mce/plugins/template/js/template.js | 106 + .../tiny_mce/plugins/template/langs/de_dlg.js | 1 + .../tiny_mce/plugins/template/langs/en_dlg.js | 1 + .../tiny_mce/plugins/template/langs/fr_dlg.js | 1 + .../tiny_mce/plugins/template/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/template/template.htm | 31 + .../plugins/visualchars/editor_plugin.js | 1 + .../plugins/visualchars/editor_plugin_src.js | 83 + .../plugins/wordcount/editor_plugin.js | 1 + .../plugins/wordcount/editor_plugin_src.js | 114 + .../js/tiny_mce/plugins/xhtmlxtras/abbr.htm | 142 + .../tiny_mce/plugins/xhtmlxtras/acronym.htm | 142 + .../plugins/xhtmlxtras/attributes.htm | 149 + .../js/tiny_mce/plugins/xhtmlxtras/cite.htm | 142 + .../plugins/xhtmlxtras/css/attributes.css | 11 + .../tiny_mce/plugins/xhtmlxtras/css/popup.css | 9 + .../js/tiny_mce/plugins/xhtmlxtras/del.htm | 162 + .../plugins/xhtmlxtras/editor_plugin.js | 1 + .../plugins/xhtmlxtras/editor_plugin_src.js | 132 + .../js/tiny_mce/plugins/xhtmlxtras/ins.htm | 162 + .../js/tiny_mce/plugins/xhtmlxtras/js/abbr.js | 28 + .../tiny_mce/plugins/xhtmlxtras/js/acronym.js | 28 + .../plugins/xhtmlxtras/js/attributes.js | 111 + .../js/tiny_mce/plugins/xhtmlxtras/js/cite.js | 28 + .../js/tiny_mce/plugins/xhtmlxtras/js/del.js | 53 + .../plugins/xhtmlxtras/js/element_common.js | 229 + .../js/tiny_mce/plugins/xhtmlxtras/js/ins.js | 53 + .../plugins/xhtmlxtras/langs/de_dlg.js | 1 + .../plugins/xhtmlxtras/langs/en_dlg.js | 1 + .../plugins/xhtmlxtras/langs/fr_dlg.js | 1 + .../plugins/xhtmlxtras/langs/it_dlg.js | 1 + .../js/tiny_mce/themes/advanced/about.htm | 52 + .../js/tiny_mce/themes/advanced/anchor.htm | 26 + .../js/tiny_mce/themes/advanced/charmap.htm | 51 + .../tiny_mce/themes/advanced/color_picker.htm | 74 + .../themes/advanced/editor_template.js | 1 + .../themes/advanced/editor_template_src.js | 1358 ++ .../js/tiny_mce/themes/advanced/image.htm | 80 + .../themes/advanced/img/colorpicker.jpg | Bin 0 -> 2584 bytes .../js/tiny_mce/themes/advanced/img/flash.gif | Bin 0 -> 239 bytes .../js/tiny_mce/themes/advanced/img/icons.gif | Bin 0 -> 11790 bytes .../tiny_mce/themes/advanced/img/iframe.gif | Bin 0 -> 600 bytes .../themes/advanced/img/pagebreak.gif | Bin 0 -> 325 bytes .../themes/advanced/img/quicktime.gif | Bin 0 -> 301 bytes .../themes/advanced/img/realmedia.gif | Bin 0 -> 439 bytes .../themes/advanced/img/shockwave.gif | Bin 0 -> 384 bytes .../js/tiny_mce/themes/advanced/img/trans.gif | Bin 0 -> 43 bytes .../js/tiny_mce/themes/advanced/img/video.gif | Bin 0 -> 597 bytes .../themes/advanced/img/windowsmedia.gif | Bin 0 -> 415 bytes .../js/tiny_mce/themes/advanced/js/about.js | 73 + .../js/tiny_mce/themes/advanced/js/anchor.js | 43 + .../js/tiny_mce/themes/advanced/js/charmap.js | 355 + .../themes/advanced/js/color_picker.js | 329 + .../js/tiny_mce/themes/advanced/js/image.js | 251 + .../js/tiny_mce/themes/advanced/js/link.js | 153 + .../themes/advanced/js/source_editor.js | 56 + .../js/tiny_mce/themes/advanced/langs/de.js | 1 + .../tiny_mce/themes/advanced/langs/de_dlg.js | 1 + .../js/tiny_mce/themes/advanced/langs/en.js | 1 + .../tiny_mce/themes/advanced/langs/en_dlg.js | 1 + .../js/tiny_mce/themes/advanced/langs/fr.js | 1 + .../tiny_mce/themes/advanced/langs/fr_dlg.js | 1 + .../js/tiny_mce/themes/advanced/langs/it.js | 1 + .../tiny_mce/themes/advanced/langs/it_dlg.js | 1 + .../js/tiny_mce/themes/advanced/link.htm | 57 + .../js/tiny_mce/themes/advanced/shortcuts.htm | 47 + .../themes/advanced/skins/default/content.css | 50 + .../themes/advanced/skins/default/dialog.css | 117 + .../advanced/skins/default/img/buttons.png | Bin 0 -> 3133 bytes .../advanced/skins/default/img/items.gif | Bin 0 -> 64 bytes .../advanced/skins/default/img/menu_arrow.gif | Bin 0 -> 68 bytes .../advanced/skins/default/img/menu_check.gif | Bin 0 -> 70 bytes .../advanced/skins/default/img/progress.gif | Bin 0 -> 1787 bytes .../advanced/skins/default/img/tabs.gif | Bin 0 -> 1322 bytes .../themes/advanced/skins/default/ui.css | 214 + .../advanced/skins/highcontrast/content.css | 24 + .../advanced/skins/highcontrast/dialog.css | 105 + .../themes/advanced/skins/highcontrast/ui.css | 102 + .../themes/advanced/skins/o2k7/content.css | 48 + .../themes/advanced/skins/o2k7/dialog.css | 117 + .../advanced/skins/o2k7/img/button_bg.png | Bin 0 -> 2766 bytes .../skins/o2k7/img/button_bg_black.png | Bin 0 -> 651 bytes .../skins/o2k7/img/button_bg_silver.png | Bin 0 -> 2084 bytes .../themes/advanced/skins/o2k7/ui.css | 217 + .../themes/advanced/skins/o2k7/ui_black.css | 8 + .../themes/advanced/skins/o2k7/ui_silver.css | 5 + .../themes/advanced/source_editor.htm | 25 + .../tiny_mce/themes/simple/editor_template.js | 1 + .../themes/simple/editor_template_src.js | 84 + .../js/tiny_mce/themes/simple/img/icons.gif | Bin 0 -> 806 bytes .../js/tiny_mce/themes/simple/langs/de.js | 1 + .../js/tiny_mce/themes/simple/langs/en.js | 1 + .../js/tiny_mce/themes/simple/langs/fr.js | 1 + .../js/tiny_mce/themes/simple/langs/it.js | 1 + .../themes/simple/skins/default/content.css | 25 + .../themes/simple/skins/default/ui.css | 32 + .../themes/simple/skins/o2k7/content.css | 17 + .../simple/skins/o2k7/img/button_bg.png | Bin 0 -> 5102 bytes .../tiny_mce/themes/simple/skins/o2k7/ui.css | 35 + src/core/static/js/tiny_mce/tiny_mce.js | 1 + src/core/static/js/tiny_mce/tiny_mce_popup.js | 5 + src/core/static/js/tiny_mce/tiny_mce_src.js | 16479 ++++++++++++++++ .../js/tiny_mce/utils/editable_selects.js | 70 + .../static/js/tiny_mce/utils/form_utils.js | 210 + src/core/static/js/tiny_mce/utils/mctabs.js | 162 + src/core/static/js/tiny_mce/utils/validate.js | 252 + src/export/.gitkeep | 0 src/getFile.php | 79 + src/getImage.php | 84 + src/index.php | 6 + .../OpenSeadragon/OpenSeadragon.debug.js | 4240 ++++ src/static/OpenSeadragon/OpenSeadragon.js | 1 + .../images/fullpage_grouphover.png | Bin 0 -> 4907 bytes .../OpenSeadragon/images/fullpage_hover.png | Bin 0 -> 5214 bytes .../OpenSeadragon/images/fullpage_pressed.png | Bin 0 -> 5213 bytes .../OpenSeadragon/images/fullpage_rest.png | Bin 0 -> 5155 bytes .../OpenSeadragon/images/home_grouphover.png | Bin 0 -> 4808 bytes .../OpenSeadragon/images/home_hover.png | Bin 0 -> 5107 bytes .../OpenSeadragon/images/home_pressed.png | Bin 0 -> 5138 bytes src/static/OpenSeadragon/images/home_rest.png | Bin 0 -> 5061 bytes .../images/zoomin_grouphover.png | Bin 0 -> 4794 bytes .../OpenSeadragon/images/zoomin_hover.png | Bin 0 -> 5126 bytes .../OpenSeadragon/images/zoomin_pressed.png | Bin 0 -> 5172 bytes .../OpenSeadragon/images/zoomin_rest.png | Bin 0 -> 5041 bytes .../images/zoomout_grouphover.png | Bin 0 -> 4596 bytes .../OpenSeadragon/images/zoomout_hover.png | Bin 0 -> 4931 bytes .../OpenSeadragon/images/zoomout_pressed.png | Bin 0 -> 5007 bytes .../OpenSeadragon/images/zoomout_rest.png | Bin 0 -> 4811 bytes src/static/dagre-d3/d3.v3.js | 9233 +++++++++ src/static/dagre-d3/d3.v3.min.js | 5 + src/static/dagre-d3/dagre-d3.js | 5003 +++++ src/static/dagre-d3/dagre-d3.min.js | 2 + src/static/dagre-d3/graphlib-dot.min.js | 2 + src/static/galleria/LICENSE | 21 + src/static/galleria/galleria-1.4.2.js | 6919 +++++++ src/static/galleria/galleria-1.4.2.min.js | 3 + .../galleria/plugins/flickr/flickr-demo.html | 62 + .../galleria/plugins/flickr/flickr-loader.gif | Bin 0 -> 2129 bytes .../plugins/flickr/galleria.flickr.js | 383 + .../plugins/flickr/galleria.flickr.min.js | 1 + src/static/galleria/plugins/flickr/loader.gif | Bin 0 -> 1849 bytes .../plugins/history/galleria.history.js | 146 + .../plugins/history/galleria.history.min.js | 1 + .../plugins/history/history-demo.html | 100 + .../plugins/picasa/galleria.picasa.js | 320 + .../plugins/picasa/galleria.picasa.min.js | 1 + src/static/galleria/plugins/picasa/loader.gif | Bin 0 -> 1849 bytes .../galleria/plugins/picasa/picasa-demo.html | 55 + .../galleria/themes/classic/classic-demo.html | 124 + .../themes/classic/classic-loader.gif | Bin 0 -> 1849 bytes .../galleria/themes/classic/classic-map.png | Bin 0 -> 1840 bytes .../themes/classic/galleria.classic.css | 219 + .../themes/classic/galleria.classic.js | 100 + .../themes/classic/galleria.classic.min.js | 1 + .../galleria/themes/movio/css/bg-thumb.png | Bin 0 -> 184 bytes .../movio/css/controller-left-hover.png | Bin 0 -> 580 bytes .../themes/movio/css/controller-left.png | Bin 0 -> 547 bytes .../movio/css/controller-right-hover.png | Bin 0 -> 583 bytes .../themes/movio/css/controller-right.png | Bin 0 -> 532 bytes .../galleria/themes/movio/css/loader.gif | Bin 0 -> 1849 bytes .../themes/movio/css/loader_black.gif | Bin 0 -> 3208 bytes .../themes/movio/css/loader_white.gif | Bin 0 -> 3208 bytes .../galleria/themes/movio/css/sprite.png | Bin 0 -> 2601 bytes .../galleria/themes/movio/css/style.css | 149 + .../galleria/themes/movio/galleria.gallery.js | 111 + .../themes/movio/galleria.pageflip.js | 115 + .../galleria/themes/movio/galleria.slider.js | 105 + .../themes/movio/galleria.slideshow.js | 116 + .../galleria/themes/movio/less/gallery.less | 343 + .../galleria/themes/movio/less/pageflip.less | 315 + .../galleria/themes/movio/less/slider.less | 252 + .../galleria/themes/movio/less/slideshow.less | 331 + .../galleria/themes/movio/less/style.less | 23 + src/static/handlebars/handlebars-1.0.rc.1.js | 1920 ++ .../bootstrap-editable-1.3.0/CHANGELOG.txt | 103 + .../bootstrap-editable-1.3.0/LICENSE-MIT | 22 + .../jquery/bootstrap-editable-1.3.0/README.md | 71 + .../css/bootstrap-editable.css | 434 + .../bootstrap-editable/css/img/loading.gif | Bin 0 -> 1849 bytes .../js/bootstrap-editable-inline.js | 3769 ++++ .../js/bootstrap-editable-inline.min.js | 5 + .../js/bootstrap-editable.js | 3801 ++++ .../js/bootstrap-editable.min.js | 5 + .../inputs-ext/address/address.css | 9 + .../inputs-ext/address/address.js | 165 + .../bootstrap-editable-1.5.1/CHANGELOG.txt | 237 + .../bootstrap-editable-1.5.1/LICENSE-MIT | 22 + .../jquery/bootstrap-editable-1.5.1/README.md | 124 + .../css/bootstrap-editable.css | 663 + .../bootstrap-editable/img/clear.png | Bin 0 -> 509 bytes .../bootstrap-editable/img/loading.gif | Bin 0 -> 1849 bytes .../js/bootstrap-editable.js | 7007 +++++++ .../js/bootstrap-editable.min.js | 7 + .../inputs-ext/address/address.css | 9 + .../inputs-ext/address/address.js | 170 + .../inputs-ext/typeaheadjs/lib/typeahead.js | 1139 ++ .../lib/typeahead.js-bootstrap.css | 49 + .../inputs-ext/typeaheadjs/typeaheadjs.js | 86 + .../bootstrap-wysihtml5-0.0.2.css | 102 + .../bootstrap-wysihtml5-0.0.2.js | 499 + .../bootstrap-wysihtml5-0.0.2.min.js | 1 + .../wysihtml5-0.3.0.js | 9521 +++++++++ .../wysihtml5-0.3.0.min.js | 261 + .../wysiwyg-color.css | 67 + .../inputs-ext/wysihtml5/wysihtml5.js | 138 + src/static/jquery/colorbox/README.md | 527 + src/static/jquery/colorbox/colorbox.css | 85 + src/static/jquery/colorbox/glizy/colorbox.css | 55 + .../jquery/colorbox/glizy/images/controls.png | Bin 0 -> 570 bytes .../jquery/colorbox/glizy/images/loading.gif | Bin 0 -> 9427 bytes .../colorbox/i18n/jquery.colorbox-ar.js | 15 + .../colorbox/i18n/jquery.colorbox-bg.js | 16 + .../colorbox/i18n/jquery.colorbox-ca.js | 13 + .../colorbox/i18n/jquery.colorbox-cs.js | 16 + .../colorbox/i18n/jquery.colorbox-da.js | 16 + .../colorbox/i18n/jquery.colorbox-de.js | 15 + .../colorbox/i18n/jquery.colorbox-es.js | 13 + .../colorbox/i18n/jquery.colorbox-et.js | 15 + .../colorbox/i18n/jquery.colorbox-fa.js | 18 + .../colorbox/i18n/jquery.colorbox-fi.js | 15 + .../colorbox/i18n/jquery.colorbox-fr.js | 15 + .../colorbox/i18n/jquery.colorbox-gl.js | 13 + .../colorbox/i18n/jquery.colorbox-he.js | 16 + .../colorbox/i18n/jquery.colorbox-hr.js | 15 + .../colorbox/i18n/jquery.colorbox-hu.js | 15 + .../colorbox/i18n/jquery.colorbox-id.js | 15 + .../colorbox/i18n/jquery.colorbox-it.js | 15 + .../colorbox/i18n/jquery.colorbox-ja.js | 15 + .../colorbox/i18n/jquery.colorbox-kr.js | 15 + .../colorbox/i18n/jquery.colorbox-lv.js | 16 + .../colorbox/i18n/jquery.colorbox-nl.js | 15 + .../colorbox/i18n/jquery.colorbox-no.js | 16 + .../colorbox/i18n/jquery.colorbox-pl.js | 16 + .../colorbox/i18n/jquery.colorbox-pt-br.js | 15 + .../colorbox/i18n/jquery.colorbox-ro.js | 15 + .../colorbox/i18n/jquery.colorbox-ru.js | 16 + .../colorbox/i18n/jquery.colorbox-si.js | 15 + .../colorbox/i18n/jquery.colorbox-sk.js | 15 + .../colorbox/i18n/jquery.colorbox-sr.js | 15 + .../colorbox/i18n/jquery.colorbox-sv.js | 15 + .../colorbox/i18n/jquery.colorbox-tr.js | 19 + .../colorbox/i18n/jquery.colorbox-uk.js | 16 + .../colorbox/i18n/jquery.colorbox-zh-CN.js | 15 + .../colorbox/i18n/jquery.colorbox-zh-TW.js | 15 + src/static/jquery/colorbox/images/border.png | Bin 0 -> 112 bytes .../jquery/colorbox/images/controls.png | Bin 0 -> 2893 bytes .../images/ie6/borderBottomCenter.png | Bin 0 -> 111 bytes .../colorbox/images/ie6/borderBottomLeft.png | Bin 0 -> 215 bytes .../colorbox/images/ie6/borderBottomRight.png | Bin 0 -> 217 bytes .../colorbox/images/ie6/borderMiddleLeft.png | Bin 0 -> 108 bytes .../colorbox/images/ie6/borderMiddleRight.png | Bin 0 -> 108 bytes .../colorbox/images/ie6/borderTopCenter.png | Bin 0 -> 111 bytes .../colorbox/images/ie6/borderTopLeft.png | Bin 0 -> 216 bytes .../colorbox/images/ie6/borderTopRight.png | Bin 0 -> 214 bytes src/static/jquery/colorbox/images/loading.gif | Bin 0 -> 9427 bytes .../colorbox/images/loading_background.png | Bin 0 -> 157 bytes src/static/jquery/colorbox/images/overlay.png | Bin 0 -> 182 bytes .../jquery/colorbox/jquery.colorbox-min.js | 7 + src/static/jquery/colorbox/jquery.colorbox.js | 1084 + .../jquery/datatables/media/css/demo_page.css | 122 + .../datatables/media/css/demo_table.css | 577 + .../datatables/media/css/demo_table_jui.css | 501 + .../media/css/jquery.dataTables.css | 221 + .../css/jquery.dataTables_themeroller.css | 244 + .../datatables/media/images/Sorting icons.psd | Bin 0 -> 27490 bytes .../datatables/media/images/back_disabled.png | Bin 0 -> 1361 bytes .../datatables/media/images/back_enabled.png | Bin 0 -> 1379 bytes .../media/images/back_enabled_hover.png | Bin 0 -> 1375 bytes .../datatables/media/images/favicon.ico | Bin 0 -> 894 bytes .../media/images/forward_disabled.png | Bin 0 -> 1363 bytes .../media/images/forward_enabled.png | Bin 0 -> 1380 bytes .../media/images/forward_enabled_hover.png | Bin 0 -> 1379 bytes .../datatables/media/images/sort_asc.png | Bin 0 -> 1118 bytes .../media/images/sort_asc_disabled.png | Bin 0 -> 1050 bytes .../datatables/media/images/sort_both.png | Bin 0 -> 1136 bytes .../datatables/media/images/sort_desc.png | Bin 0 -> 1127 bytes .../media/images/sort_desc_disabled.png | Bin 0 -> 1045 bytes .../media/js/jquery.dataTables.bootstrap.js | 148 + .../datatables/media/js/jquery.dataTables.js | 12099 ++++++++++++ .../media/js/jquery.dataTables.min.js | 155 + .../jquery/datatables/media/js/jquery.js | 2 + src/static/jquery/jquery-1.8.3.min.js | 2 + .../jquery/jquery-jstree/jquery.cookie.js | 96 + .../jquery/jquery-jstree/jquery.jstree.js | 4561 +++++ .../jquery/jquery-jstree/themes/apple/bg.jpg | Bin 0 -> 331 bytes .../jquery/jquery-jstree/themes/apple/d.png | Bin 0 -> 7765 bytes .../jquery-jstree/themes/apple/dot_for_ie.gif | Bin 0 -> 43 bytes .../jquery-jstree/themes/apple/style.css | 61 + .../jquery-jstree/themes/apple/throbber.gif | Bin 0 -> 1849 bytes .../jquery/jquery-jstree/themes/classic/d.gif | Bin 0 -> 3003 bytes .../jquery/jquery-jstree/themes/classic/d.png | Bin 0 -> 7535 bytes .../themes/classic/dot_for_ie.gif | Bin 0 -> 43 bytes .../jquery-jstree/themes/classic/style.css | 77 + .../jquery-jstree/themes/classic/throbber.gif | Bin 0 -> 1849 bytes .../jquery-jstree/themes/default-rtl/d.gif | Bin 0 -> 2872 bytes .../jquery-jstree/themes/default-rtl/d.png | Bin 0 -> 7459 bytes .../jquery-jstree/themes/default-rtl/dots.gif | Bin 0 -> 132 bytes .../themes/default-rtl/style.css | 84 + .../themes/default-rtl/throbber.gif | Bin 0 -> 1849 bytes .../jquery/jquery-jstree/themes/default/d.gif | Bin 0 -> 2944 bytes .../jquery/jquery-jstree/themes/default/d.png | Bin 0 -> 7635 bytes .../jquery-jstree/themes/default/style.css | 74 + .../jquery-jstree/themes/default/throbber.gif | Bin 0 -> 1849 bytes src/static/jquery/jquery-transform/README.md | 81 + .../jquery-transform/jquery.transform2d.js | 935 + .../jquery-transform/jquery.transform3d.js | 95 + .../jquery-ui/jquery-ui-1.10.4.custom.min.js | 6 + .../images/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../images/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 120 bytes .../images/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../images/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../images/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 110 bytes .../images/ui-bg_glass_75_ffffff_1x400.png | Bin 0 -> 107 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../ui-bg_inset-soft_95_fef1ec_1x100.png | Bin 0 -> 123 bytes .../images/ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_2e83ff_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_888888_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4369 bytes .../images/ui-icons_f6cf3b_256x240.png | Bin 0 -> 8884 bytes .../jquery-ui-1.10.0.custom.css | 1614 ++ .../jquery.ui.1.10.0.ie.css | 16 + .../jquery/jquery.qtip/jquery.qtip.min.css | 2 + .../jquery/jquery.qtip/jquery.qtip.min.js | 5 + .../jquery.validationEngine-da.js | 122 + .../jquery.validationEngine-de.js | 126 + .../jquery.validationEngine-en.js | 122 + .../jquery.validationEngine-es.js | 124 + .../jquery.validationEngine-fr.js | 116 + .../jquery.validationEngine-it.js | 116 + .../jquery.validationEngine-ja.js | 136 + .../jquery.validationEngine-nl.js | 123 + .../jquery.validationEngine-pt.js | 122 + .../jquery.validationEngine-ro.js | 122 + .../jquery.validationEngine-ru.js | 123 + .../jquery.validationEngine.js | 1180 ++ .../validationEngine.jquery.css | 142 + src/static/jquery/select2-3.4.6/LICENSE | 18 + src/static/jquery/select2-3.4.6/README.md | 84 + src/static/jquery/select2-3.4.6/bower.json | 8 + .../jquery/select2-3.4.6/component.json | 66 + src/static/jquery/select2-3.4.6/composer.json | 29 + src/static/jquery/select2-3.4.6/package.json | 20 + src/static/jquery/select2-3.4.6/release.sh | 79 + .../select2-3.4.6/select2-bootstrap.css | 87 + .../jquery/select2-3.4.6/select2-spinner.gif | Bin 0 -> 1849 bytes src/static/jquery/select2-3.4.6/select2.css | 646 + .../jquery/select2-3.4.6/select2.jquery.json | 36 + src/static/jquery/select2-3.4.6/select2.js | 3397 ++++ .../jquery/select2-3.4.6/select2.min.js | 22 + src/static/jquery/select2-3.4.6/select2.png | Bin 0 -> 613 bytes .../jquery/select2-3.4.6/select2_locale_ar.js | 17 + .../jquery/select2-3.4.6/select2_locale_bg.js | 18 + .../jquery/select2-3.4.6/select2_locale_ca.js | 17 + .../jquery/select2-3.4.6/select2_locale_cs.js | 49 + .../jquery/select2-3.4.6/select2_locale_da.js | 17 + .../jquery/select2-3.4.6/select2_locale_de.js | 15 + .../jquery/select2-3.4.6/select2_locale_el.js | 17 + .../select2_locale_en.js.template | 18 + .../jquery/select2-3.4.6/select2_locale_es.js | 15 + .../jquery/select2-3.4.6/select2_locale_et.js | 17 + .../jquery/select2-3.4.6/select2_locale_eu.js | 43 + .../jquery/select2-3.4.6/select2_locale_fa.js | 19 + .../jquery/select2-3.4.6/select2_locale_fi.js | 28 + .../jquery/select2-3.4.6/select2_locale_fr.js | 15 + .../jquery/select2-3.4.6/select2_locale_gl.js | 43 + .../jquery/select2-3.4.6/select2_locale_he.js | 17 + .../jquery/select2-3.4.6/select2_locale_hr.js | 22 + .../jquery/select2-3.4.6/select2_locale_hu.js | 15 + .../jquery/select2-3.4.6/select2_locale_id.js | 17 + .../jquery/select2-3.4.6/select2_locale_is.js | 15 + .../jquery/select2-3.4.6/select2_locale_it.js | 15 + .../jquery/select2-3.4.6/select2_locale_ja.js | 15 + .../jquery/select2-3.4.6/select2_locale_ka.js | 17 + .../jquery/select2-3.4.6/select2_locale_ko.js | 17 + .../jquery/select2-3.4.6/select2_locale_lt.js | 24 + .../jquery/select2-3.4.6/select2_locale_lv.js | 17 + .../jquery/select2-3.4.6/select2_locale_mk.js | 17 + .../jquery/select2-3.4.6/select2_locale_ms.js | 17 + .../jquery/select2-3.4.6/select2_locale_nl.js | 15 + .../jquery/select2-3.4.6/select2_locale_no.js | 18 + .../jquery/select2-3.4.6/select2_locale_pl.js | 22 + .../select2-3.4.6/select2_locale_pt-BR.js | 15 + .../select2-3.4.6/select2_locale_pt-PT.js | 15 + .../jquery/select2-3.4.6/select2_locale_ro.js | 15 + .../jquery/select2-3.4.6/select2_locale_rs.js | 17 + .../jquery/select2-3.4.6/select2_locale_ru.js | 21 + .../jquery/select2-3.4.6/select2_locale_sk.js | 48 + .../jquery/select2-3.4.6/select2_locale_sv.js | 17 + .../jquery/select2-3.4.6/select2_locale_th.js | 17 + .../jquery/select2-3.4.6/select2_locale_tr.js | 17 + .../jquery/select2-3.4.6/select2_locale_uk.js | 22 + .../jquery/select2-3.4.6/select2_locale_vi.js | 18 + .../select2-3.4.6/select2_locale_zh-CN.js | 14 + .../select2-3.4.6/select2_locale_zh-TW.js | 14 + src/static/jquery/select2-3.4.6/select2x2.png | Bin 0 -> 845 bytes .../visualsearch-0.5.0/backbone-1.1.0.js | 1581 ++ .../visualsearch-datauri.css | 341 + .../visualsearch-0.5.0/visualsearch.css | 341 + .../jquery/visualsearch-0.5.0/visualsearch.js | 1969 ++ src/static/js/slick/ajax-loader.gif | Bin 0 -> 4178 bytes src/static/js/slick/config.rb | 10 + src/static/js/slick/fonts/slick.eot | Bin 0 -> 2048 bytes src/static/js/slick/fonts/slick.svg | 14 + src/static/js/slick/fonts/slick.ttf | Bin 0 -> 1892 bytes src/static/js/slick/fonts/slick.woff | Bin 0 -> 1380 bytes src/static/js/slick/slick-script.js | 193 + src/static/js/slick/slick.css | 55 + src/static/js/slick/slick.js | 1851 ++ src/static/js/slick/slick.min.js | 1 + src/static/js/slick/slick.scss | 286 + src/static/mediaelement/background.png | Bin 0 -> 166 bytes src/static/mediaelement/bigplay.png | Bin 0 -> 3001 bytes src/static/mediaelement/bigplay.svg | 1 + src/static/mediaelement/controls-ted.png | Bin 0 -> 1559 bytes src/static/mediaelement/controls-wmp-bg.png | Bin 0 -> 1960 bytes src/static/mediaelement/controls-wmp.png | Bin 0 -> 5511 bytes src/static/mediaelement/controls.png | Bin 0 -> 1892 bytes src/static/mediaelement/controls.svg | 1 + src/static/mediaelement/flashmediaelement.swf | Bin 0 -> 28709 bytes src/static/mediaelement/loading.gif | Bin 0 -> 6224 bytes .../mediaelement/mediaelement-and-player.js | 5045 +++++ .../mediaelement-and-player.min.js | 172 + src/static/mediaelement/mediaelement.js | 1890 ++ src/static/mediaelement/mediaelement.min.js | 67 + .../mediaelement/mediaelementplayer.css | 864 + src/static/mediaelement/mediaelementplayer.js | 3153 +++ .../mediaelement/mediaelementplayer.min.css | 1 + .../mediaelement/mediaelementplayer.min.js | 103 + src/static/mediaelement/mejs-skins.css | 283 + .../mediaelement/silverlightmediaelement.xap | Bin 0 -> 12461 bytes src/static/movio/assets/img/loader_white.gif | Bin 0 -> 3208 bytes src/static/movio/js/movio.js | 173 + .../Default/skins/AttachmentsList.html | 3 + .../templates/Default/skins/BoxList.html | 43 + .../templates/Default/skins/BoxSearch.html | 6 + .../templates/Default/skins/BoxSidebar.html | 34 + .../movio/templates/Default/skins/Cover.html | 10 + .../Default/skins/DictionaryList.html | 89 + .../Default/skins/DigitalExhibition.html | 99 + .../templates/Default/skins/Entity_entry.html | 99 + .../templates/Default/skins/Entity_list.html | 42 + .../Default/skins/Entity_moduleImageLink.html | 16 + .../Default/skins/Entity_relationImage.html | 27 + .../skins/Entity_relationImageLink.html | 16 + .../Default/skins/Entity_relationLink.html | 13 + .../skins/EuropeanaRelatedContents.html | 46 + .../templates/Default/skins/Exhibition.html | 139 + .../templates/Default/skins/GoogleMap.html | 5 + .../Default/skins/GoogleMap_macro.html | 102 + .../Default/skins/HomeImageSlider.html | 26 + .../templates/Default/skins/ImagesList.html | 5 + .../movio/templates/Default/skins/Login.html | 34 + .../templates/Default/skins/News_entry.html | 27 + .../templates/Default/skins/News_list.html | 24 + .../templates/Default/skins/Photogallery.html | 20 + .../movio/templates/Default/skins/Search.html | 23 + .../movio/templates/Default/skins/Share.html | 24 + .../templates/Default/skins/Storyteller.html | 323 + .../templates/Default/skins/Timeline.html | 18 + .../Default/skins/TouristOperators_entry.html | 38 + .../Default/skins/TouristOperators_list.html | 24 + .../Default/skins/TouristOperators_map.html | 7 + .../templates/Default/skins/Unity3D.html | 104 + .../movio/templates/Default/skins/Video.html | 9 + .../movio/templates/Default/skins/_macro.html | 16 + .../templates/Minimal-in-blue/Template.php | 224 + .../templates/Minimal-in-blue/Template.xml | 16 + .../Minimal-in-blue/TemplateAdmin.xml | 5 + .../Minimal-in-blue/TemplateAdminGlobal.xml | 144 + .../font/font-awesome/FontAwesome.otf | Bin 0 -> 62856 bytes .../font/font-awesome/fontawesome-webfont.eot | Bin 0 -> 38205 bytes .../font/font-awesome/fontawesome-webfont.svg | 414 + .../font/font-awesome/fontawesome-webfont.ttf | Bin 0 -> 80652 bytes .../font-awesome/fontawesome-webfont.woff | Bin 0 -> 44432 bytes .../Minimal-in-blue/img/bg/bg-body.png | Bin 0 -> 469 bytes .../Minimal-in-blue/img/bg/bg-box.png | Bin 0 -> 800 bytes .../Minimal-in-blue/img/bg/bg-description.png | Bin 0 -> 184 bytes .../Minimal-in-blue/img/bg/bg-opacity.png | Bin 0 -> 184 bytes .../Minimal-in-blue/img/ico/alert-error.png | Bin 0 -> 1454 bytes .../Minimal-in-blue/img/ico/alert-ok.png | Bin 0 -> 1289 bytes .../img/ico/arrow-baloon-big.png | Bin 0 -> 599 bytes .../Minimal-in-blue/img/ico/arrow-baloon.png | Bin 0 -> 381 bytes .../Minimal-in-blue/img/logo-mobile.png | Bin 0 -> 1223 bytes .../templates/Minimal-in-blue/img/logo.png | Bin 0 -> 1979 bytes .../Minimal-in-blue/img/logo_movio.png | Bin 0 -> 1878 bytes .../Minimal-in-blue/js/bootstrap.min.js | 6 + .../Minimal-in-blue/js/jquery-1.8.2.min.js | 2 + .../templates/Minimal-in-blue/js/main.js | 10 + .../Minimal-in-blue/less/element.less | 1271 ++ .../less/font-awesome/bordered-pulled.less | 16 + .../less/font-awesome/core.less | 12 + .../less/font-awesome/fixed-width.less | 6 + .../less/font-awesome/font-awesome.less | 17 + .../less/font-awesome/icons.less | 412 + .../less/font-awesome/larger.less | 13 + .../less/font-awesome/list.less | 19 + .../less/font-awesome/mixins.less | 20 + .../less/font-awesome/path.less | 14 + .../less/font-awesome/rotated-flipped.less | 9 + .../less/font-awesome/spinning.less | 30 + .../less/font-awesome/stacked.less | 20 + .../less/font-awesome/variables.less | 381 + .../Minimal-in-blue/less/global.less | 351 + .../less/libs/bootstrap-social.less | 100 + .../Minimal-in-blue/less/libs/bootstrap.less | 2820 +++ .../Minimal-in-blue/less/libs/mixin.less | 100 + .../Minimal-in-blue/less/mobile.less | 253 + .../Minimal-in-blue/less/navigation.less | 145 + .../templates/Minimal-in-blue/less/slick.less | 137 + .../Minimal-in-blue/less/structure.less | 329 + .../Minimal-in-blue/less/styles.less | 140 + .../templates/Minimal-in-blue/less/svg.less | 59 + .../movio/templates/Minimal-in-blue/page.php | 143 + .../templates/Minimal-in-blue/preview.jpg | Bin 0 -> 15548 bytes .../Minimal-in-blue/skins/BoxList.html | 21 + .../Minimal-in-blue/skins/BoxSearch.html | 7 + .../skins/HomeImageSlider.html | 26 + src/static/movio/templates/Movio/1col.php | 131 + src/static/movio/templates/Movio/2cols.php | 158 + src/static/movio/templates/Movio/3cols.php | 163 + src/static/movio/templates/Movio/Template.php | 211 + src/static/movio/templates/Movio/Template.xml | 14 + .../movio/templates/Movio/TemplateAdmin.xml | 13 + .../templates/Movio/TemplateAdminGlobal.xml | 121 + src/static/movio/templates/Movio/cover.php | 63 + .../Movio/font/font-awesome/FontAwesome.otf | Bin 0 -> 61896 bytes .../font/font-awesome/fontawesome-webfont.eot | Bin 0 -> 37405 bytes .../font/font-awesome/fontawesome-webfont.svg | 399 + .../font/font-awesome/fontawesome-webfont.ttf | Bin 0 -> 79076 bytes .../font-awesome/fontawesome-webfont.woff | Bin 0 -> 43572 bytes .../templates/Movio/img/bg/bg-box-comment.png | Bin 0 -> 1126 bytes .../templates/Movio/img/bg/bg-box-link.png | Bin 0 -> 1263 bytes .../movio/templates/Movio/img/bg/bg-box.png | Bin 0 -> 800 bytes .../templates/Movio/img/bg/bg-description.png | Bin 0 -> 184 bytes .../templates/Movio/img/ico/alert-error.png | Bin 0 -> 1454 bytes .../templates/Movio/img/ico/alert-ok.png | Bin 0 -> 1289 bytes .../Movio/img/ico/arrow-baloon-big.png | Bin 0 -> 599 bytes .../templates/Movio/img/ico/arrow-baloon.png | Bin 0 -> 381 bytes .../templates/Movio/img/ico/arrow-button.png | Bin 0 -> 579 bytes .../templates/Movio/img/ico/eye-hover.png | Bin 0 -> 463 bytes .../movio/templates/Movio/img/ico/eye.png | Bin 0 -> 449 bytes .../movio/templates/Movio/img/ico/mov-top.png | Bin 0 -> 975 bytes .../movio/templates/Movio/img/ico/pool.png | Bin 0 -> 4159 bytes .../movio/templates/Movio/img/ico/search.png | Bin 0 -> 342 bytes .../movio/templates/Movio/img/logo-footer.png | Bin 0 -> 4557 bytes .../Movio/img/logo_fondazioneTelecom.png | Bin 0 -> 5021 bytes .../movio/templates/Movio/img/logo_movio.png | Bin 0 -> 2067 bytes .../movio/templates/Movio/img/various/app.jpg | Bin 0 -> 15769 bytes .../templates/Movio/img/various/cart.jpg | Bin 0 -> 26945 bytes .../templates/Movio/img/various/figure.jpg | Bin 0 -> 14615 bytes .../templates/Movio/img/various/gallery.jpg | Bin 0 -> 94553 bytes .../templates/Movio/img/various/header.jpg | Bin 0 -> 165481 bytes .../Movio/img/various/image-page-y.jpg | Bin 0 -> 32526 bytes .../Movio/img/various/image-page.jpg | Bin 0 -> 21452 bytes .../templates/Movio/img/various/image.jpg | Bin 0 -> 27732 bytes .../templates/Movio/img/various/img-link.jpg | Bin 0 -> 5811 bytes .../Movio/img/various/img-not-disponible.jpg | Bin 0 -> 1922 bytes .../Movio/img/various/img-slider.jpg | Bin 0 -> 76924 bytes .../movio/templates/Movio/img/various/map.jpg | Bin 0 -> 20322 bytes .../Movio/img/various/mini-img-2.jpg | Bin 0 -> 18629 bytes .../templates/Movio/img/various/mini-img.jpg | Bin 0 -> 3607 bytes .../templates/Movio/img/various/slide.jpg | Bin 0 -> 49477 bytes .../templates/Movio/img/various/visit.jpg | Bin 0 -> 22488 bytes .../movio/templates/Movio/js/bootstrap.min.js | 6 + src/static/movio/templates/Movio/js/main.js | 3 + .../Movio/js/vendor/jquery-1.8.2.min.js | 2 + .../Movio/js/vendor/modernizr-2.6.2.min.js | 4 + .../movio/templates/Movio/less/element.less | 2264 +++ .../less/font-awesome/bordered-pulled.less | 16 + .../Movio/less/font-awesome/core.less | 12 + .../Movio/less/font-awesome/fixed-width.less | 6 + .../Movio/less/font-awesome/font-awesome.less | 17 + .../Movio/less/font-awesome/icons.less | 412 + .../Movio/less/font-awesome/larger.less | 13 + .../Movio/less/font-awesome/list.less | 19 + .../Movio/less/font-awesome/mixins.less | 20 + .../Movio/less/font-awesome/path.less | 14 + .../less/font-awesome/rotated-flipped.less | 9 + .../Movio/less/font-awesome/spinning.less | 30 + .../Movio/less/font-awesome/stacked.less | 20 + .../Movio/less/font-awesome/variables.less | 381 + .../movio/templates/Movio/less/global.less | 701 + .../Movio/less/libs/bootstrap-social.less | 100 + .../templates/Movio/less/libs/bootstrap.less | 2820 +++ .../templates/Movio/less/libs/mixin.less | 237 + .../movio/templates/Movio/less/mobile.less | 105 + .../movio/templates/Movio/less/page.less | 316 + .../movio/templates/Movio/less/slick.less | 90 + .../movio/templates/Movio/less/structure.less | 579 + .../movio/templates/Movio/less/styles.less | 192 + .../movio/templates/Movio/less/svg.less | 61 + src/static/movio/templates/Movio/preview.jpg | Bin 0 -> 23846 bytes .../movio/templates/Skeleton/Template.php | 45 + .../movio/templates/Skeleton/Template.xml | 15 + .../templates/Skeleton/TemplateAdmin.xml | 5 + .../Skeleton/TemplateAdminGlobal.xml | 6 + .../movio/templates/Skeleton/css/styles.css | 11 + src/static/movio/templates/Skeleton/disabled | 0 .../font/font-awesome/FontAwesome.otf | Bin 0 -> 62856 bytes .../font/font-awesome/fontawesome-webfont.eot | Bin 0 -> 38205 bytes .../font/font-awesome/fontawesome-webfont.svg | 414 + .../font/font-awesome/fontawesome-webfont.ttf | Bin 0 -> 80652 bytes .../font-awesome/fontawesome-webfont.woff | Bin 0 -> 44432 bytes .../templates/Skeleton/img/bg/bg-box.png | Bin 0 -> 800 bytes .../Skeleton/img/bg/bg-description.png | Bin 0 -> 184 bytes .../Skeleton/img/ico/alert-error.png | Bin 0 -> 1454 bytes .../templates/Skeleton/img/ico/alert-ok.png | Bin 0 -> 1289 bytes .../Skeleton/img/ico/arrow-baloon-big.png | Bin 0 -> 599 bytes .../Skeleton/img/ico/arrow-baloon.png | Bin 0 -> 381 bytes .../templates/Skeleton/img/logo-footer.png | Bin 0 -> 4557 bytes .../templates/Skeleton/img/logo_movio.png | Bin 0 -> 2067 bytes .../templates/Skeleton/js/bootstrap.min.js | 6 + .../templates/Skeleton/js/jquery-1.8.2.min.js | 2 + .../movio/templates/Skeleton/js/main.js | 36 + .../Skeleton/less/cms-component.less | 1740 ++ .../templates/Skeleton/less/cms-global.less | 240 + .../templates/Skeleton/less/cms-layout.less | 33 + .../templates/Skeleton/less/cms-mobile.less | 76 + .../less/font-awesome/bordered-pulled.less | 16 + .../Skeleton/less/font-awesome/core.less | 12 + .../less/font-awesome/fixed-width.less | 6 + .../less/font-awesome/font-awesome.less | 17 + .../Skeleton/less/font-awesome/icons.less | 412 + .../Skeleton/less/font-awesome/larger.less | 13 + .../Skeleton/less/font-awesome/list.less | 19 + .../Skeleton/less/font-awesome/mixins.less | 20 + .../Skeleton/less/font-awesome/path.less | 14 + .../less/font-awesome/rotated-flipped.less | 9 + .../Skeleton/less/font-awesome/spinning.less | 30 + .../Skeleton/less/font-awesome/stacked.less | 20 + .../Skeleton/less/font-awesome/variables.less | 381 + .../Skeleton/less/libs/bootstrap.less | 6564 ++++++ .../Skeleton/less/libs/cms-bootstrap.less | 4806 +++++ .../Skeleton/less/libs/cms-mixin.less | 48 + .../templates/Skeleton/less/libs/mixin.less | 38 + .../movio/templates/Skeleton/less/slick.less | 132 + .../movio/templates/Skeleton/less/styles.less | 189 + src/static/movio/templates/Skeleton/page.php | 124 + .../movio/templates/Skeleton/preview.jpg | Bin 0 -> 21552 bytes .../Skeleton/skins/HomeImageSlider.html | 25 + .../templates/Sliding-windows/Template.php | 175 + .../templates/Sliding-windows/Template.xml | 22 + .../Sliding-windows/TemplateAdmin.xml | 5 + .../Sliding-windows/TemplateAdminGlobal.xml | 162 + .../templates/Sliding-windows/css/ie.css | 1 + .../css/jquery.mCustomScrollbar.css | 474 + .../templates/Sliding-windows/css/styles.css | 8 + .../Sliding-windows/img/bg/bg-box.png | Bin 0 -> 800 bytes .../Sliding-windows/img/bg/bg-description.png | Bin 0 -> 184 bytes .../Sliding-windows/img/bg/bg-opacity.png | Bin 0 -> 185 bytes .../Sliding-windows/img/ico/alert-error.png | Bin 0 -> 1454 bytes .../Sliding-windows/img/ico/alert-ok.png | Bin 0 -> 1289 bytes .../img/ico/arrow-baloon-big.png | Bin 0 -> 599 bytes .../Sliding-windows/img/ico/arrow-baloon.png | Bin 0 -> 381 bytes .../Sliding-windows/img/logo-footer.png | Bin 0 -> 4554 bytes .../templates/Sliding-windows/img/logo.png | Bin 0 -> 1866 bytes .../Sliding-windows/img/logo_movio.png | Bin 0 -> 2067 bytes .../Sliding-windows/js/bootstrap.min.js | 6 + .../Sliding-windows/js/jquery-1.8.2.min.js | 4 + .../js/jquery.mCustomScrollbar.concat.min.js | 4 + .../js/jquery.mCustomScrollbar.js | 969 + .../templates/Sliding-windows/js/jqxcore.js | 7 + .../templates/Sliding-windows/js/jqxmenu.js | 7 + .../templates/Sliding-windows/js/main.js | 89 + .../Sliding-windows/less/element.less | 1320 ++ .../less/font-awesome/bordered-pulled.less | 16 + .../less/font-awesome/core.less | 12 + .../less/font-awesome/fixed-width.less | 6 + .../less/font-awesome/font-awesome.less | 17 + .../less/font-awesome/icons.less | 412 + .../less/font-awesome/larger.less | 13 + .../less/font-awesome/list.less | 19 + .../less/font-awesome/mixins.less | 20 + .../less/font-awesome/path.less | 14 + .../less/font-awesome/rotated-flipped.less | 9 + .../less/font-awesome/spinning.less | 30 + .../less/font-awesome/stacked.less | 20 + .../less/font-awesome/variables.less | 381 + .../Sliding-windows/less/global.less | 338 + .../Sliding-windows/less/libs/bootstrap.less | 2820 +++ .../Sliding-windows/less/libs/mixin.less | 85 + .../Sliding-windows/less/mobile.less | 519 + .../Sliding-windows/less/navigation.less | 225 + .../templates/Sliding-windows/less/slick.less | 136 + .../Sliding-windows/less/structure.less | 208 + .../Sliding-windows/less/styles.less | 146 + .../templates/Sliding-windows/less/svg.less | 61 + .../movio/templates/Sliding-windows/page.php | 122 + .../Sliding-windows/pageTypes/Home.xml | 21 + .../templates/Sliding-windows/preview.jpg | Bin 0 -> 15548 bytes .../Sliding-windows/skins/BoxList.html | 21 + .../Sliding-windows/skins/Entity_entry.html | 208 + .../Sliding-windows/skins/Entity_list.html | 56 + .../skins/Entity_relationImage.html | 27 + .../skins/Entity_relationImageLink.html | 16 + .../skins/Entity_relationLink.html | 13 + .../skins/EuropeanaRelatedContents.html | 46 + .../skins/HomeImageSlider.html | 25 + .../Sliding-windows/skins/Storyteller.html | 358 + src/static/org_glizy/assets/js/Glizy.js | 295 + .../org_glizy/assets/js/Glizy_tiny_mce.js | 301 + src/static/org_glizy/assets/js/locale/de.js | 33 + src/static/org_glizy/assets/js/locale/en.js | 34 + src/static/org_glizy/assets/js/locale/fr.js | 33 + src/static/org_glizy/assets/js/locale/it.js | 34 + .../org_glizy/assets/js/tiny_mce/langs/de.js | 1 + .../org_glizy/assets/js/tiny_mce/langs/en.js | 1 + .../org_glizy/assets/js/tiny_mce/langs/fr.js | 1 + .../org_glizy/assets/js/tiny_mce/langs/it.js | 1 + .../org_glizy/assets/js/tiny_mce/license.txt | 504 + .../plugins/GLZ_image/css/GLZ_image.css | 72 + .../plugins/GLZ_image/editor_plugin.js | 67 + .../js/tiny_mce/plugins/GLZ_image/image.htm | 114 + .../plugins/GLZ_image/images/sample.gif | Bin 0 -> 1624 bytes .../plugins/GLZ_image/jscripts/functions.js | 310 + .../js/tiny_mce/plugins/GLZ_image/langs/en.js | 56 + .../js/tiny_mce/plugins/GLZ_image/langs/it.js | 57 + .../plugins/GLZ_link/css/GLZ_link.css | 41 + .../plugins/GLZ_link/editor_plugin.js | 77 + .../plugins/GLZ_link/jscripts/functions.js | 347 + .../js/tiny_mce/plugins/GLZ_link/langs/en.js | 34 + .../js/tiny_mce/plugins/GLZ_link/langs/it.js | 34 + .../js/tiny_mce/plugins/GLZ_link/link.htm | 111 + .../js/tiny_mce/plugins/advhr/css/advhr.css | 5 + .../tiny_mce/plugins/advhr/editor_plugin.js | 1 + .../plugins/advhr/editor_plugin_src.js | 57 + .../js/tiny_mce/plugins/advhr/js/rule.js | 43 + .../js/tiny_mce/plugins/advhr/langs/de_dlg.js | 1 + .../js/tiny_mce/plugins/advhr/langs/en_dlg.js | 1 + .../js/tiny_mce/plugins/advhr/langs/fr_dlg.js | 1 + .../js/tiny_mce/plugins/advhr/langs/it_dlg.js | 1 + .../assets/js/tiny_mce/plugins/advhr/rule.htm | 58 + .../plugins/advimage/css/advimage.css | 13 + .../plugins/advimage/editor_plugin.js | 1 + .../plugins/advimage/editor_plugin_src.js | 50 + .../js/tiny_mce/plugins/advimage/image.htm | 235 + .../tiny_mce/plugins/advimage/img/sample.gif | Bin 0 -> 1624 bytes .../js/tiny_mce/plugins/advimage/js/image.js | 462 + .../tiny_mce/plugins/advimage/langs/de_dlg.js | 1 + .../tiny_mce/plugins/advimage/langs/en_dlg.js | 1 + .../tiny_mce/plugins/advimage/langs/fr_dlg.js | 1 + .../tiny_mce/plugins/advimage/langs/it_dlg.js | 1 + .../tiny_mce/plugins/advlink/css/advlink.css | 8 + .../tiny_mce/plugins/advlink/editor_plugin.js | 1 + .../plugins/advlink/editor_plugin_src.js | 61 + .../js/tiny_mce/plugins/advlink/js/advlink.js | 532 + .../tiny_mce/plugins/advlink/langs/de_dlg.js | 1 + .../tiny_mce/plugins/advlink/langs/en_dlg.js | 1 + .../tiny_mce/plugins/advlink/langs/fr_dlg.js | 1 + .../tiny_mce/plugins/advlink/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/advlink/link.htm | 338 + .../tiny_mce/plugins/advlist/editor_plugin.js | 1 + .../plugins/advlist/editor_plugin_src.js | 176 + .../plugins/autolink/editor_plugin.js | 1 + .../plugins/autolink/editor_plugin_src.js | 172 + .../plugins/autoresize/editor_plugin.js | 1 + .../plugins/autoresize/editor_plugin_src.js | 137 + .../plugins/autosave/editor_plugin.js | 1 + .../plugins/autosave/editor_plugin_src.js | 431 + .../js/tiny_mce/plugins/autosave/langs/en.js | 4 + .../tiny_mce/plugins/bbcode/editor_plugin.js | 1 + .../plugins/bbcode/editor_plugin_src.js | 120 + .../plugins/contextmenu/editor_plugin.js | 1 + .../plugins/contextmenu/editor_plugin_src.js | 160 + .../plugins/directionality/editor_plugin.js | 1 + .../directionality/editor_plugin_src.js | 82 + .../plugins/emotions/editor_plugin.js | 1 + .../plugins/emotions/editor_plugin_src.js | 43 + .../js/tiny_mce/plugins/emotions/emotions.htm | 41 + .../plugins/emotions/img/smiley-cool.gif | Bin 0 -> 354 bytes .../plugins/emotions/img/smiley-cry.gif | Bin 0 -> 329 bytes .../emotions/img/smiley-embarassed.gif | Bin 0 -> 331 bytes .../emotions/img/smiley-foot-in-mouth.gif | Bin 0 -> 342 bytes .../plugins/emotions/img/smiley-frown.gif | Bin 0 -> 340 bytes .../plugins/emotions/img/smiley-innocent.gif | Bin 0 -> 336 bytes .../plugins/emotions/img/smiley-kiss.gif | Bin 0 -> 338 bytes .../plugins/emotions/img/smiley-laughing.gif | Bin 0 -> 343 bytes .../emotions/img/smiley-money-mouth.gif | Bin 0 -> 321 bytes .../plugins/emotions/img/smiley-sealed.gif | Bin 0 -> 323 bytes .../plugins/emotions/img/smiley-smile.gif | Bin 0 -> 344 bytes .../plugins/emotions/img/smiley-surprised.gif | Bin 0 -> 338 bytes .../emotions/img/smiley-tongue-out.gif | Bin 0 -> 328 bytes .../plugins/emotions/img/smiley-undecided.gif | Bin 0 -> 337 bytes .../plugins/emotions/img/smiley-wink.gif | Bin 0 -> 350 bytes .../plugins/emotions/img/smiley-yell.gif | Bin 0 -> 336 bytes .../tiny_mce/plugins/emotions/js/emotions.js | 22 + .../tiny_mce/plugins/emotions/langs/de_dlg.js | 1 + .../tiny_mce/plugins/emotions/langs/en_dlg.js | 1 + .../tiny_mce/plugins/emotions/langs/fr_dlg.js | 1 + .../tiny_mce/plugins/emotions/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/example/dialog.htm | 22 + .../tiny_mce/plugins/example/editor_plugin.js | 1 + .../plugins/example/editor_plugin_src.js | 84 + .../tiny_mce/plugins/example/img/example.gif | Bin 0 -> 87 bytes .../js/tiny_mce/plugins/example/js/dialog.js | 19 + .../js/tiny_mce/plugins/example/langs/en.js | 3 + .../tiny_mce/plugins/example/langs/en_dlg.js | 3 + .../example_dependency/editor_plugin.js | 1 + .../example_dependency/editor_plugin_src.js | 50 + .../plugins/fullpage/css/fullpage.css | 143 + .../plugins/fullpage/editor_plugin.js | 1 + .../plugins/fullpage/editor_plugin_src.js | 405 + .../js/tiny_mce/plugins/fullpage/fullpage.htm | 259 + .../tiny_mce/plugins/fullpage/js/fullpage.js | 232 + .../tiny_mce/plugins/fullpage/langs/de_dlg.js | 1 + .../tiny_mce/plugins/fullpage/langs/en_dlg.js | 1 + .../tiny_mce/plugins/fullpage/langs/fr_dlg.js | 1 + .../tiny_mce/plugins/fullpage/langs/it_dlg.js | 1 + .../plugins/fullscreen/editor_plugin.js | 1 + .../plugins/fullscreen/editor_plugin_src.js | 159 + .../plugins/fullscreen/fullscreen.htm | 110 + .../tiny_mce/plugins/iespell/editor_plugin.js | 1 + .../plugins/iespell/editor_plugin_src.js | 54 + .../plugins/inlinepopups/editor_plugin.js | 1 + .../plugins/inlinepopups/editor_plugin_src.js | 699 + .../skins/clearlooks2/img/alert.gif | Bin 0 -> 810 bytes .../skins/clearlooks2/img/button.gif | Bin 0 -> 272 bytes .../skins/clearlooks2/img/buttons.gif | Bin 0 -> 1195 bytes .../skins/clearlooks2/img/confirm.gif | Bin 0 -> 907 bytes .../skins/clearlooks2/img/corners.gif | Bin 0 -> 909 bytes .../skins/clearlooks2/img/horizontal.gif | Bin 0 -> 769 bytes .../skins/clearlooks2/img/vertical.gif | Bin 0 -> 84 bytes .../inlinepopups/skins/clearlooks2/window.css | 90 + .../plugins/inlinepopups/template.htm | 387 + .../plugins/insertdatetime/editor_plugin.js | 1 + .../insertdatetime/editor_plugin_src.js | 83 + .../tiny_mce/plugins/layer/editor_plugin.js | 1 + .../plugins/layer/editor_plugin_src.js | 262 + .../plugins/legacyoutput/editor_plugin.js | 1 + .../plugins/legacyoutput/editor_plugin_src.js | 139 + .../tiny_mce/plugins/lists/editor_plugin.js | 1 + .../plugins/lists/editor_plugin_src.js | 781 + .../js/tiny_mce/plugins/media/css/media.css | 17 + .../tiny_mce/plugins/media/editor_plugin.js | 1 + .../plugins/media/editor_plugin_src.js | 890 + .../js/tiny_mce/plugins/media/js/embed.js | 73 + .../js/tiny_mce/plugins/media/js/media.js | 453 + .../js/tiny_mce/plugins/media/langs/de_dlg.js | 1 + .../js/tiny_mce/plugins/media/langs/en_dlg.js | 1 + .../js/tiny_mce/plugins/media/langs/fr_dlg.js | 1 + .../js/tiny_mce/plugins/media/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/media/media.htm | 922 + .../js/tiny_mce/plugins/media/moxieplayer.swf | Bin 0 -> 33931 bytes .../plugins/nonbreaking/editor_plugin.js | 1 + .../plugins/nonbreaking/editor_plugin_src.js | 54 + .../plugins/noneditable/editor_plugin.js | 1 + .../plugins/noneditable/editor_plugin_src.js | 95 + .../plugins/pagebreak/editor_plugin.js | 1 + .../plugins/pagebreak/editor_plugin_src.js | 74 + .../tiny_mce/plugins/paste/editor_plugin.js | 1 + .../plugins/paste/editor_plugin_src.js | 871 + .../js/tiny_mce/plugins/paste/js/pastetext.js | 36 + .../js/tiny_mce/plugins/paste/js/pasteword.js | 51 + .../js/tiny_mce/plugins/paste/langs/de_dlg.js | 1 + .../js/tiny_mce/plugins/paste/langs/en_dlg.js | 1 + .../js/tiny_mce/plugins/paste/langs/fr_dlg.js | 1 + .../js/tiny_mce/plugins/paste/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/paste/pastetext.htm | 27 + .../js/tiny_mce/plugins/paste/pasteword.htm | 21 + .../tiny_mce/plugins/preview/editor_plugin.js | 1 + .../plugins/preview/editor_plugin_src.js | 53 + .../js/tiny_mce/plugins/preview/example.html | 28 + .../plugins/preview/jscripts/embed.js | 73 + .../js/tiny_mce/plugins/preview/preview.html | 17 + .../tiny_mce/plugins/print/editor_plugin.js | 1 + .../plugins/print/editor_plugin_src.js | 34 + .../js/tiny_mce/plugins/save/editor_plugin.js | 1 + .../plugins/save/editor_plugin_src.js | 101 + .../searchreplace/css/searchreplace.css | 6 + .../plugins/searchreplace/editor_plugin.js | 1 + .../searchreplace/editor_plugin_src.js | 61 + .../plugins/searchreplace/js/searchreplace.js | 142 + .../plugins/searchreplace/langs/de_dlg.js | 1 + .../plugins/searchreplace/langs/en_dlg.js | 1 + .../plugins/searchreplace/langs/fr_dlg.js | 1 + .../plugins/searchreplace/langs/it_dlg.js | 1 + .../plugins/searchreplace/searchreplace.htm | 100 + .../plugins/spellchecker/css/content.css | 1 + .../plugins/spellchecker/editor_plugin.js | 1 + .../plugins/spellchecker/editor_plugin_src.js | 436 + .../plugins/spellchecker/img/wline.gif | Bin 0 -> 46 bytes .../js/tiny_mce/plugins/style/css/props.css | 13 + .../tiny_mce/plugins/style/editor_plugin.js | 1 + .../plugins/style/editor_plugin_src.js | 55 + .../js/tiny_mce/plugins/style/js/props.js | 635 + .../js/tiny_mce/plugins/style/langs/de_dlg.js | 1 + .../js/tiny_mce/plugins/style/langs/en_dlg.js | 1 + .../js/tiny_mce/plugins/style/langs/fr_dlg.js | 1 + .../js/tiny_mce/plugins/style/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/style/props.htm | 840 + .../plugins/tabfocus/editor_plugin.js | 1 + .../plugins/tabfocus/editor_plugin_src.js | 122 + .../assets/js/tiny_mce/plugins/table/cell.htm | 180 + .../js/tiny_mce/plugins/table/css/cell.css | 17 + .../js/tiny_mce/plugins/table/css/row.css | 25 + .../js/tiny_mce/plugins/table/css/table.css | 13 + .../tiny_mce/plugins/table/editor_plugin.js | 1 + .../plugins/table/editor_plugin_src.js | 1364 ++ .../js/tiny_mce/plugins/table/js/cell.js | 319 + .../tiny_mce/plugins/table/js/merge_cells.js | 27 + .../js/tiny_mce/plugins/table/js/row.js | 237 + .../js/tiny_mce/plugins/table/js/table.js | 450 + .../js/tiny_mce/plugins/table/langs/de_dlg.js | 1 + .../js/tiny_mce/plugins/table/langs/en_dlg.js | 1 + .../js/tiny_mce/plugins/table/langs/fr_dlg.js | 1 + .../js/tiny_mce/plugins/table/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/table/merge_cells.htm | 32 + .../assets/js/tiny_mce/plugins/table/row.htm | 158 + .../js/tiny_mce/plugins/table/table.htm | 188 + .../js/tiny_mce/plugins/template/blank.htm | 12 + .../plugins/template/css/template.css | 23 + .../plugins/template/editor_plugin.js | 1 + .../plugins/template/editor_plugin_src.js | 159 + .../tiny_mce/plugins/template/js/template.js | 106 + .../tiny_mce/plugins/template/langs/de_dlg.js | 1 + .../tiny_mce/plugins/template/langs/en_dlg.js | 1 + .../tiny_mce/plugins/template/langs/fr_dlg.js | 1 + .../tiny_mce/plugins/template/langs/it_dlg.js | 1 + .../js/tiny_mce/plugins/template/template.htm | 31 + .../plugins/visualchars/editor_plugin.js | 1 + .../plugins/visualchars/editor_plugin_src.js | 83 + .../plugins/wordcount/editor_plugin.js | 1 + .../plugins/wordcount/editor_plugin_src.js | 114 + .../js/tiny_mce/plugins/xhtmlxtras/abbr.htm | 142 + .../tiny_mce/plugins/xhtmlxtras/acronym.htm | 142 + .../plugins/xhtmlxtras/attributes.htm | 149 + .../js/tiny_mce/plugins/xhtmlxtras/cite.htm | 142 + .../plugins/xhtmlxtras/css/attributes.css | 11 + .../tiny_mce/plugins/xhtmlxtras/css/popup.css | 9 + .../js/tiny_mce/plugins/xhtmlxtras/del.htm | 162 + .../plugins/xhtmlxtras/editor_plugin.js | 1 + .../plugins/xhtmlxtras/editor_plugin_src.js | 132 + .../js/tiny_mce/plugins/xhtmlxtras/ins.htm | 162 + .../js/tiny_mce/plugins/xhtmlxtras/js/abbr.js | 28 + .../tiny_mce/plugins/xhtmlxtras/js/acronym.js | 28 + .../plugins/xhtmlxtras/js/attributes.js | 111 + .../js/tiny_mce/plugins/xhtmlxtras/js/cite.js | 28 + .../js/tiny_mce/plugins/xhtmlxtras/js/del.js | 53 + .../plugins/xhtmlxtras/js/element_common.js | 229 + .../js/tiny_mce/plugins/xhtmlxtras/js/ins.js | 53 + .../plugins/xhtmlxtras/langs/de_dlg.js | 1 + .../plugins/xhtmlxtras/langs/en_dlg.js | 1 + .../plugins/xhtmlxtras/langs/fr_dlg.js | 1 + .../plugins/xhtmlxtras/langs/it_dlg.js | 1 + .../js/tiny_mce/themes/advanced/about.htm | 52 + .../js/tiny_mce/themes/advanced/anchor.htm | 26 + .../js/tiny_mce/themes/advanced/charmap.htm | 51 + .../tiny_mce/themes/advanced/color_picker.htm | 74 + .../themes/advanced/editor_template.js | 1 + .../themes/advanced/editor_template_src.js | 1358 ++ .../js/tiny_mce/themes/advanced/image.htm | 80 + .../themes/advanced/img/colorpicker.jpg | Bin 0 -> 2584 bytes .../js/tiny_mce/themes/advanced/img/flash.gif | Bin 0 -> 239 bytes .../js/tiny_mce/themes/advanced/img/icons.gif | Bin 0 -> 11790 bytes .../tiny_mce/themes/advanced/img/iframe.gif | Bin 0 -> 600 bytes .../themes/advanced/img/pagebreak.gif | Bin 0 -> 325 bytes .../themes/advanced/img/quicktime.gif | Bin 0 -> 301 bytes .../themes/advanced/img/realmedia.gif | Bin 0 -> 439 bytes .../themes/advanced/img/shockwave.gif | Bin 0 -> 384 bytes .../js/tiny_mce/themes/advanced/img/trans.gif | Bin 0 -> 43 bytes .../js/tiny_mce/themes/advanced/img/video.gif | Bin 0 -> 597 bytes .../themes/advanced/img/windowsmedia.gif | Bin 0 -> 415 bytes .../js/tiny_mce/themes/advanced/js/about.js | 73 + .../js/tiny_mce/themes/advanced/js/anchor.js | 43 + .../js/tiny_mce/themes/advanced/js/charmap.js | 355 + .../themes/advanced/js/color_picker.js | 329 + .../js/tiny_mce/themes/advanced/js/image.js | 251 + .../js/tiny_mce/themes/advanced/js/link.js | 153 + .../themes/advanced/js/source_editor.js | 56 + .../js/tiny_mce/themes/advanced/langs/de.js | 1 + .../tiny_mce/themes/advanced/langs/de_dlg.js | 1 + .../js/tiny_mce/themes/advanced/langs/en.js | 1 + .../tiny_mce/themes/advanced/langs/en_dlg.js | 1 + .../js/tiny_mce/themes/advanced/langs/fr.js | 1 + .../tiny_mce/themes/advanced/langs/fr_dlg.js | 1 + .../js/tiny_mce/themes/advanced/langs/it.js | 1 + .../tiny_mce/themes/advanced/langs/it_dlg.js | 1 + .../js/tiny_mce/themes/advanced/link.htm | 57 + .../js/tiny_mce/themes/advanced/shortcuts.htm | 47 + .../themes/advanced/skins/default/content.css | 50 + .../themes/advanced/skins/default/dialog.css | 117 + .../advanced/skins/default/img/buttons.png | Bin 0 -> 3133 bytes .../advanced/skins/default/img/items.gif | Bin 0 -> 64 bytes .../advanced/skins/default/img/menu_arrow.gif | Bin 0 -> 68 bytes .../advanced/skins/default/img/menu_check.gif | Bin 0 -> 70 bytes .../advanced/skins/default/img/progress.gif | Bin 0 -> 1787 bytes .../advanced/skins/default/img/tabs.gif | Bin 0 -> 1322 bytes .../themes/advanced/skins/default/ui.css | 214 + .../advanced/skins/highcontrast/content.css | 24 + .../advanced/skins/highcontrast/dialog.css | 105 + .../themes/advanced/skins/highcontrast/ui.css | 102 + .../themes/advanced/skins/o2k7/content.css | 48 + .../themes/advanced/skins/o2k7/dialog.css | 117 + .../advanced/skins/o2k7/img/button_bg.png | Bin 0 -> 2766 bytes .../skins/o2k7/img/button_bg_black.png | Bin 0 -> 651 bytes .../skins/o2k7/img/button_bg_silver.png | Bin 0 -> 2084 bytes .../themes/advanced/skins/o2k7/ui.css | 217 + .../themes/advanced/skins/o2k7/ui_black.css | 8 + .../themes/advanced/skins/o2k7/ui_silver.css | 5 + .../themes/advanced/source_editor.htm | 25 + .../tiny_mce/themes/simple/editor_template.js | 1 + .../themes/simple/editor_template_src.js | 84 + .../js/tiny_mce/themes/simple/img/icons.gif | Bin 0 -> 806 bytes .../js/tiny_mce/themes/simple/langs/de.js | 1 + .../js/tiny_mce/themes/simple/langs/en.js | 1 + .../js/tiny_mce/themes/simple/langs/fr.js | 1 + .../js/tiny_mce/themes/simple/langs/it.js | 1 + .../themes/simple/skins/default/content.css | 25 + .../themes/simple/skins/default/ui.css | 32 + .../themes/simple/skins/o2k7/content.css | 17 + .../simple/skins/o2k7/img/button_bg.png | Bin 0 -> 5102 bytes .../tiny_mce/themes/simple/skins/o2k7/ui.css | 35 + .../org_glizy/assets/js/tiny_mce/tiny_mce.js | 1 + .../assets/js/tiny_mce/tiny_mce_popup.js | 5 + .../assets/js/tiny_mce/tiny_mce_src.js | 16479 ++++++++++++++++ .../js/tiny_mce/utils/editable_selects.js | 70 + .../assets/js/tiny_mce/utils/form_utils.js | 210 + .../assets/js/tiny_mce/utils/mctabs.js | 162 + .../assets/js/tiny_mce/utils/validate.js | 252 + src/static/timelinejs/css/loading.gif | Bin 0 -> 6909 bytes src/static/timelinejs/css/themes/dark.css | 281 + .../css/themes/font/AbrilFatface-Average.css | 6 + .../css/themes/font/Arvo-PTSans.css | 6 + .../css/themes/font/Bevan-PotanoSans.css | 6 + .../css/themes/font/BreeSerif-OpenSans.css | 6 + .../css/themes/font/DroidSerif-DroidSans.css | 7 + .../css/themes/font/Georgia-Helvetica.css | 6 + .../css/themes/font/Lekton-Molengo.css | 6 + .../timelinejs/css/themes/font/Lora-Istok.css | 6 + .../themes/font/Merriweather-NewsCycle.css | 8 + .../themes/font/NewsCycle-Merriweather.css | 8 + .../css/themes/font/NixieOne-Ledger.css | 6 + src/static/timelinejs/css/themes/font/PT.css | 7 + .../css/themes/font/PTSerif-PTSans.css | 6 + .../css/themes/font/Pacifico-Arimo.css | 6 + .../css/themes/font/PlayfairDisplay-Muli.css | 6 + .../css/themes/font/PoiretOne-Molengo.css | 8 + .../css/themes/font/Rancho-Gudea.css | 6 + .../css/themes/font/SansitaOne-Kameron.css | 6 + .../timelinejs/css/themes/timeline-dark.png | Bin 0 -> 19775 bytes .../css/themes/timeline-dark@2x.png | Bin 0 -> 49145 bytes .../css/themes/timeline-texture.png | Bin 0 -> 42976 bytes src/static/timelinejs/css/timeline.css | 281 + src/static/timelinejs/css/timeline.png | Bin 0 -> 19364 bytes src/static/timelinejs/css/timeline@2x.png | Bin 0 -> 49364 bytes src/static/timelinejs/js/locale/ar.js | 2 + src/static/timelinejs/js/locale/bg.js | 2 + src/static/timelinejs/js/locale/ca.js | 2 + src/static/timelinejs/js/locale/cz.js | 2 + src/static/timelinejs/js/locale/de.js | 2 + src/static/timelinejs/js/locale/dk.js | 2 + src/static/timelinejs/js/locale/el.js | 2 + src/static/timelinejs/js/locale/en.js | 2 + src/static/timelinejs/js/locale/es.js | 2 + src/static/timelinejs/js/locale/eu.js | 2 + src/static/timelinejs/js/locale/fi.js | 2 + src/static/timelinejs/js/locale/fo.js | 2 + src/static/timelinejs/js/locale/fr.js | 2 + src/static/timelinejs/js/locale/hu.js | 2 + src/static/timelinejs/js/locale/hy.js | 2 + src/static/timelinejs/js/locale/id.js | 2 + src/static/timelinejs/js/locale/is.js | 2 + src/static/timelinejs/js/locale/it.js | 2 + src/static/timelinejs/js/locale/iw.js | 2 + src/static/timelinejs/js/locale/ja.js | 2 + src/static/timelinejs/js/locale/ko.js | 2 + src/static/timelinejs/js/locale/kr.js | 2 + src/static/timelinejs/js/locale/nl.js | 2 + src/static/timelinejs/js/locale/no.js | 2 + src/static/timelinejs/js/locale/pl.js | 2 + src/static/timelinejs/js/locale/pt-br.js | 2 + src/static/timelinejs/js/locale/pt.js | 2 + src/static/timelinejs/js/locale/ru.js | 2 + src/static/timelinejs/js/locale/sk.js | 2 + src/static/timelinejs/js/locale/sl.js | 2 + src/static/timelinejs/js/locale/sr-cy.js | 2 + src/static/timelinejs/js/locale/sr-la.js | 2 + src/static/timelinejs/js/locale/sv.js | 2 + src/static/timelinejs/js/locale/ta.js | 2 + src/static/timelinejs/js/locale/tl.js | 2 + src/static/timelinejs/js/locale/tr.js | 2 + src/static/timelinejs/js/locale/zh-ch.js | 2 + src/static/timelinejs/js/locale/zh-cn.js | 2 + src/static/timelinejs/js/locale/zh-tw.js | 2 + src/static/timelinejs/js/storyjs-embed.js | 45 + src/static/timelinejs/js/timeline-min.js | 36 + src/static/timelinejs/js/timeline.js | 9875 +++++++++ src/static/viz.js-master/.gitattributes | 1 + src/static/viz.js-master/COPYING | 129 + src/static/viz.js-master/Makefile | 46 + src/static/viz.js-master/README.txt | 13 + src/static/viz.js-master/config.h | 22 + src/static/viz.js-master/example.html | 321 + src/static/viz.js-master/post.js | 3 + src/static/viz.js-master/pre.js | 6 + src/static/viz.js-master/prova.html | 50 + src/static/viz.js-master/viz.c | 21 + src/static/viz.js-master/viz.js | 9 + src/url.php | 157 + src/zoom.php | 35 + 3418 files changed, 602710 insertions(+) create mode 100644 .gitignore create mode 100644 Install.md create mode 100644 LICENSE.md create mode 100644 install/movio.sql create mode 100644 src/.htaccess create mode 100644 src/admin/.htaccess create mode 100644 src/admin/ajax.php create mode 100644 src/admin/application/classes/movio/controllers/index.html create mode 100644 src/admin/application/classes/movio/models/Mobilecontents.xml create mode 100644 src/admin/application/classes/movio/models/index.html create mode 100644 src/admin/application/classes/movio/modules/codes/controllers/MakeQRCode.php create mode 100644 src/admin/application/classes/movio/modules/codes/controllers/ajax/Del.php create mode 100644 src/admin/application/classes/movio/modules/codes/controllers/ajax/Load.php create mode 100644 src/admin/application/classes/movio/modules/codes/controllers/ajax/New.php create mode 100644 src/admin/application/classes/movio/modules/codes/controllers/ajax/Set.php create mode 100644 src/admin/application/classes/movio/modules/codes/models/Model.xml create mode 100644 src/admin/application/classes/movio/modules/codes/views/Admin.xml create mode 100755 src/admin/application/classes/movio/modules/codes/views/js/CodesEditor.js create mode 100755 src/admin/application/classes/movio/modules/codes/views/js/CodesEditorLoader.js create mode 100644 src/admin/application/classes/movio/modules/codes/views/js/locale/en-EN.js create mode 100644 src/admin/application/classes/movio/modules/codes/views/js/locale/it-IT.js create mode 100755 src/admin/application/classes/movio/modules/codes/views/skins/CodesEditorTemplate.html create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/01CreateFolders.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/02SaveLocaleFiles.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/03CreateModule.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/04CreateModelFile.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/05CreateAdminPage.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/06CreatePage.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/07CreateRoutingFile.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/08AddPage.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/09AddModuleDirective.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/10AddSitemap.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/11SaveModuleStructure.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/12ImportCsvData.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/AbstractCommand.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/Builder.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/d01DeleteFolders.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/d02CleanStartup.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/builder/d03DeleteMenu.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/controllers/AdminModuleStateController.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/controllers/DeleteModule.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/controllers/StateController.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/services/AbstractDbService.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/services/CVSImporter.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/services/DbServiceFactory.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/services/MysqlService.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/services/PgsqlService.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/views/Admin.xml create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/views/components/EditTableFields.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/views/components/NewTableFields.php create mode 100644 src/admin/application/classes/movio/modules/modulesBuilder/views/components/SelectTable.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/EntityResolver.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/Paths.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/Delete.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/Edit.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/Index.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/AddEntityLabel.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/FindEntityLabels.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetDictionaries.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetFieldTypes.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetLanguages.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetModules.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetRelationTypes.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/LoadEntity.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/SaveEntity.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/Delete.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/Togglevisibility.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/ajax/GetUrl.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entity/Index.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entity/ajax/Thesaurus.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/Edit.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/EditDraft.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/Cancel.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/FindEntities.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/FindTerm.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/Save.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveClose.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveDraft.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveDraftClose.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/DelEntityLabel.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/LoadEntityLabels.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/NewEntityLabel.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/SetEntityLabel.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/graph/Index.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/graph/List.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/profile/Index.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/DelRelation.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/LoadRelations.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/NewRelation.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/SetRelation.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/models/Entity.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/models/EntityDocument.php create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/models/EntityLabelsDocument.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/models/EntityMenu.xml create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/models/EntityModel.xml create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/models/EntityProperties.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/models/FieldTypesDocument.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/models/Languages.php create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/models/RelationTypesDocument.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/models/proxy/EntityProxy.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/models/proxy/ModelProxy.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/models/vo/SkinAttributesVO.php create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/service/EntityTypeService.php create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/service/FieldTypeService.php create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/service/LocaleService.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/ContentsEditor.xml create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/EntityLabelsEditor.xml create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/Graph.xml create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/OntologyBuilder.xml create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/RelationsEditor.xml create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/AddEntityButton.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/DocumentGraph.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntireGraph.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/Entity.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityFormEdit.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityList.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityToJSON.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/FilterEntityType.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/Graph.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/Module.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/NoImage.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/Relation.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/Repeater.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/RepeaterForModule.php create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/views/components/ShowProfileContents.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/components/Thesaurus.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/js/ContentsEditor.js create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityFormEditEntitySelect.js create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityLabelsEditor.js create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityLabelsEditorLoader.js create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/views/js/OntologyBuilder.js create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/views/js/OntologyBuilderEditor.js create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/views/js/RelationsEditor.js create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/views/js/RelationsEditorLoader.js create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/js/SearchContent.js create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/js/locale/en-EN.js create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/js/locale/it-IT.js create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDelete.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDeleteEntity.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDraftDeleteEntity.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/EntityName.php create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/EntityVisualization.php create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/views/skins/EntityLabelsEditorTemplate.html create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/views/skins/EntityTemplate.html create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/views/skins/ReferenceRelationsTemplate.html create mode 100755 src/admin/application/classes/movio/modules/ontologybuilder/views/skins/RelationsEditorTemplate.html create mode 100644 src/admin/application/classes/movio/modules/ontologybuilder/views/skins/index.html create mode 100644 src/admin/application/classes/movio/modules/publishApp/controllers/Index.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/controllers/ajax/CreateJSON.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/controllers/ajax/CreateZip.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/controllers/ajax/Export.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/controllers/ajax/ExportCodes.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/controllers/ajax/GetSteps.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/controllers/ajax/Mysql2Sqlite.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/controllers/ajax/PrepareExport.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/controllers/ajax/SaveSVG.php create mode 100755 src/admin/application/classes/movio/modules/publishApp/js/Admin.js create mode 100755 src/admin/application/classes/movio/modules/publishApp/js/SiteTree.js create mode 100644 src/admin/application/classes/movio/modules/publishApp/models/Codes.xml create mode 100644 src/admin/application/classes/movio/modules/publishApp/models/DocumentIndexFulltext.xml create mode 100644 src/admin/application/classes/movio/modules/publishApp/models/Mobilefulltext.xml create mode 100644 src/admin/application/classes/movio/modules/publishApp/service/ExportService.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/service/Mysql2SqliteService.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/service/PublishAppService.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/static/PublishApp.js create mode 100644 src/admin/application/classes/movio/modules/publishApp/static/jquery.simplemodal.1.4.1.min.js create mode 100644 src/admin/application/classes/movio/modules/publishApp/static/progressBar.css create mode 100644 src/admin/application/classes/movio/modules/publishApp/views/Admin.xml create mode 100644 src/admin/application/classes/movio/modules/publishApp/views/components/DocumentGraph.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/views/components/Graph.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/views/components/GraphContainer.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/views/components/ProgressBarDialog.php create mode 100644 src/admin/application/classes/movio/modules/publishApp/views/components/SiteTreeView.php create mode 100644 src/admin/application/classes/movio/modules/siteProperties/controllers/Index.php create mode 100644 src/admin/application/classes/movio/modules/siteProperties/controllers/ajax/Save.php create mode 100644 src/admin/application/classes/movio/modules/siteProperties/views/SiteProperties.xml create mode 100644 src/admin/application/classes/movio/views/components/FormEdit.php create mode 100755 src/admin/application/classes/movio/views/js/app.js create mode 100644 src/admin/application/config/acl.xml create mode 100644 src/admin/application/config/config.xml create mode 100644 src/admin/application/config/config_common.xml create mode 100644 src/admin/application/config/routing.xml create mode 100644 src/admin/application/config/siteMap.xml create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Autoloader.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/APC.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/CacheBase.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/DiscISAM.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/ICache.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Igbinary.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Memcache.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Memory.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/MemoryGZip.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/MemorySerialized.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/PHPTemp.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/SQLite.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/SQLite3.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Wincache.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorageFactory.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CalcEngine/CyclicReferenceStack.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/CalcEngine/Logger.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Database.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/DateTime.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Engineering.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Exception.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/ExceptionHandler.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Financial.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/FormulaParser.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/FormulaToken.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Function.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Functions.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Logical.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/LookupRef.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/MathTrig.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Statistical.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/TextData.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Token/Stack.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/functionlist.txt create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/AdvancedValueBinder.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DataType.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DataValidation.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DefaultValueBinder.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/Hyperlink.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/IValueBinder.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/DataSeries.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/DataSeriesValues.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Exception.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Layout.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Legend.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/PlotArea.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Renderer/PHP Charting Libraries.txt create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Renderer/jpgraph.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Title.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Comment.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/DocumentProperties.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/DocumentSecurity.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Exception.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/HashTable.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/IComparable.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/IOFactory.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/NamedRange.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Abstract.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/CSV.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/DefaultReadFilter.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2003XML.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007/Chart.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007/Theme.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel5.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel5/Escher.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Exception.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Gnumeric.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/HTML.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/IReadFilter.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/IReader.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/OOCalc.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/SYLK.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/ReferenceHelper.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/ITextElement.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/Run.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/TextElement.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Settings.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/CodePage.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Date.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Drawing.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Excel5.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/File.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Font.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/CHANGELOG.TXT create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/CholeskyDecomposition.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/LUDecomposition.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/Matrix.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/QRDecomposition.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/SingularValueDecomposition.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/utils/Error.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/utils/Maths.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/ChainedBlockStream.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS/File.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS/Root.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLERead.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/gnu-lgpl.txt create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/pclzip.lib.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/readme.txt create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PasswordHasher.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/String.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/TimeZone.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/XMLWriter.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/ZipArchive.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/ZipStreamWrapper.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/bestFitClass.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/exponentialBestFitClass.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/linearBestFitClass.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/logarithmicBestFitClass.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/polynomialBestFitClass.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/powerBestFitClass.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/trendClass.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Alignment.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Border.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Borders.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Color.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Conditional.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Fill.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Font.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/NumberFormat.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Protection.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Supervisor.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter/Column.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter/Column/Rule.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/BaseDrawing.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/CellIterator.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/ColumnDimension.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Drawing.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Drawing/Shadow.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/HeaderFooter.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/HeaderFooterDrawing.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/MemoryDrawing.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/PageMargins.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/PageSetup.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Protection.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Row.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/RowDimension.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/RowIterator.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/SheetView.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/WorksheetIterator.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Abstract.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/CSV.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Chart.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Comments.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/DocProps.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Drawing.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Rels.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/StringTable.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Style.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Theme.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Workbook.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Worksheet.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/WriterPart.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/BIFFwriter.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Escher.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Font.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Parser.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Workbook.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Worksheet.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Xf.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Exception.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/HTML.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/IWriter.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/Core.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/DomPDF.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/mPDF.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/tcPDF.php create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/cs/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/cs/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/da/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/da/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/de/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/de/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/en/uk/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/es/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/es/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fi/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fi/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fr/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fr/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/hu/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/hu/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/it/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/it/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/nl/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/nl/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/no/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/no/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pl/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pl/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/br/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/br/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/ru/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/ru/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/sv/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/sv/functions create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/tr/config create mode 100755 src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/tr/functions create mode 100755 src/admin/application/libs/PHPExcel/changelog.txt create mode 100755 src/admin/application/libs/PHPExcel/install.txt create mode 100755 src/admin/application/libs/PHPExcel/license.txt create mode 100644 src/admin/application/libs/dUnzip2.inc.php create mode 100644 src/admin/application/libs/dZip.inc.php create mode 100755 src/admin/application/libs/phpqrcode/CHANGELOG create mode 100755 src/admin/application/libs/phpqrcode/INSTALL create mode 100755 src/admin/application/libs/phpqrcode/LICENSE create mode 100755 src/admin/application/libs/phpqrcode/README create mode 100755 src/admin/application/libs/phpqrcode/VERSION create mode 100755 src/admin/application/libs/phpqrcode/bindings/tcpdf/qrcode.php create mode 100755 src/admin/application/libs/phpqrcode/index.php create mode 100755 src/admin/application/libs/phpqrcode/phpqrcode.php create mode 100755 src/admin/application/libs/phpqrcode/qrbitstream.php create mode 100755 src/admin/application/libs/phpqrcode/qrconfig.php create mode 100755 src/admin/application/libs/phpqrcode/qrconst.php create mode 100755 src/admin/application/libs/phpqrcode/qrencode.php create mode 100755 src/admin/application/libs/phpqrcode/qrimage.php create mode 100755 src/admin/application/libs/phpqrcode/qrinput.php create mode 100755 src/admin/application/libs/phpqrcode/qrlib.php create mode 100755 src/admin/application/libs/phpqrcode/qrmask.php create mode 100755 src/admin/application/libs/phpqrcode/qrrscode.php create mode 100755 src/admin/application/libs/phpqrcode/qrspec.php create mode 100755 src/admin/application/libs/phpqrcode/qrsplit.php create mode 100755 src/admin/application/libs/phpqrcode/qrtools.php create mode 100755 src/admin/application/libs/phpqrcode/tools/merge.bat create mode 100755 src/admin/application/libs/phpqrcode/tools/merge.php create mode 100755 src/admin/application/libs/phpqrcode/tools/merge.sh create mode 100755 src/admin/application/libs/phpqrcode/tools/merged_config.php create mode 100755 src/admin/application/libs/phpqrcode/tools/merged_header.php create mode 100644 src/admin/application/pageTypes/Dashboard.xml create mode 100644 src/admin/application/pageTypes/Login.xml create mode 100644 src/admin/application/pageTypes/Logout.xml create mode 100644 src/admin/application/pageTypes/_common.xml create mode 100644 src/admin/application/startup/index.php create mode 100644 src/admin/application/startup/modules_custom.php create mode 100644 src/admin/application/startup/movio.php create mode 100755 src/admin/application/templates/Login.php create mode 100644 src/admin/application/templates/Page.php create mode 100755 src/admin/application/templates/Popup.php create mode 100644 src/admin/application/templates/css/styles.css create mode 100755 src/admin/application/templates/font/FontAwesome.otf create mode 100755 src/admin/application/templates/font/fontawesome-webfont.eot create mode 100755 src/admin/application/templates/font/fontawesome-webfont.svg create mode 100755 src/admin/application/templates/font/fontawesome-webfont.ttf create mode 100755 src/admin/application/templates/font/fontawesome-webfont.woff create mode 100644 src/admin/application/templates/icons/audio.png create mode 100644 src/admin/application/templates/icons/folder.png create mode 100644 src/admin/application/templates/icons/icon_loading.gif create mode 100644 src/admin/application/templates/icons/image.png create mode 100644 src/admin/application/templates/icons/other.png create mode 100644 src/admin/application/templates/icons/pdf.png create mode 100644 src/admin/application/templates/images/ajax-loader.gif create mode 100644 src/admin/application/templates/images/dragHandler.gif create mode 100644 src/admin/application/templates/images/icon_delete.gif create mode 100755 src/admin/application/templates/images/icon_edit.gif create mode 100644 src/admin/application/templates/images/noimage.jpg create mode 100644 src/admin/application/templates/images/resize.png create mode 100644 src/admin/application/templates/images/treeIcons.png create mode 100644 src/admin/application/templates/img/article.png create mode 100644 src/admin/application/templates/img/attach.png create mode 100755 src/admin/application/templates/img/breadcrumb.png create mode 100644 src/admin/application/templates/img/calendar.png create mode 100644 src/admin/application/templates/img/down-arrow.png create mode 100644 src/admin/application/templates/img/dummy-logo.jpg create mode 100644 src/admin/application/templates/img/exercise.png create mode 100644 src/admin/application/templates/img/glyphicons-halflings-white.png create mode 100644 src/admin/application/templates/img/glyphicons-halflings.png create mode 100644 src/admin/application/templates/img/login-bkg.png create mode 100644 src/admin/application/templates/img/logo/logo-login.png create mode 100644 src/admin/application/templates/img/logo/logo-metacms.png create mode 100644 src/admin/application/templates/img/logo/logo-top.png create mode 100644 src/admin/application/templates/img/menu-active.png create mode 100644 src/admin/application/templates/img/pool.png create mode 100644 src/admin/application/templates/img/relation.png create mode 100644 src/admin/application/templates/img/up-arrow.png create mode 100644 src/admin/application/templates/img/up-down-arrow.png create mode 100644 src/admin/application/templates/js/bootstrap.js create mode 100644 src/admin/application/templates/js/bootstrap.min.js create mode 100644 src/admin/application/templates/js/jqBootstrapValidation.js create mode 100644 src/admin/application/templates/js/jquery.js create mode 100644 src/admin/application/templates/js/jquery.min.js create mode 100755 src/admin/application/templates/less/custom.less create mode 100755 src/admin/application/templates/less/custom.login.less create mode 100755 src/admin/application/templates/less/font-awesome.less create mode 100755 src/admin/application/templates/less/glizy.less create mode 100755 src/admin/application/templates/less/global.less create mode 100755 src/admin/application/templates/less/libs/bootstrap-responsive.less create mode 100755 src/admin/application/templates/less/libs/bootstrap.less create mode 100755 src/admin/application/templates/less/libs/h5bp.less create mode 100755 src/admin/application/templates/less/libs/mixin.less create mode 100755 src/admin/application/templates/less/structure.less create mode 100755 src/admin/application/templates/less/styles.less create mode 100644 src/admin/cache/.gitkeep create mode 100644 src/admin/getFile.php create mode 100644 src/admin/getImage.php create mode 100644 src/admin/index.php create mode 100644 src/admin/uploader.php create mode 100644 src/ajax.php create mode 100644 src/application/classes/movio/locale/en.php create mode 100644 src/application/classes/movio/locale/it.php create mode 100644 src/application/classes/movio/modules/europeana/EuropeanaResponseVO.php create mode 100644 src/application/classes/movio/modules/europeana/SendRequest.php create mode 100644 src/application/classes/movio/modules/europeana/views/EuropeanaShowResults.xml create mode 100644 src/application/classes/movio/modules/europeana/views/components/RelatedContents.php create mode 100644 src/application/classes/movio/modules/europeana/views/components/ShowResults.php create mode 100644 src/application/classes/movio/modules/europeana/views/js/FormEditEuropeanaRelatedContents.js create mode 100644 src/application/classes/movio/modules/europeana/views/skin/showresults.html create mode 100644 src/application/classes/movio/modules/news/Module.php create mode 100644 src/application/classes/movio/modules/news/UrlResolver.php create mode 100644 src/application/classes/movio/modules/news/config/routing.xml create mode 100644 src/application/classes/movio/modules/news/models/Model.xml create mode 100644 src/application/classes/movio/modules/news/views/Admin.xml create mode 100644 src/application/classes/movio/modules/news/views/FrontEnd.xml create mode 100644 src/application/classes/movio/modules/sharingButtons/controllers/ajax/Save.php create mode 100644 src/application/classes/movio/modules/sharingButtons/js/main.js create mode 100644 src/application/classes/movio/modules/sharingButtons/views/Admin.xml create mode 100644 src/application/classes/movio/modules/sharingButtons/views/SharingButton.php create mode 100644 src/application/classes/movio/modules/sharingButtons/views/components/GetSharingButtons.php create mode 100644 src/application/classes/movio/modules/sharingButtons/views/components/Share.php create mode 100644 src/application/classes/movio/modules/storyteller/controllers/PostComment.php create mode 100644 src/application/classes/movio/modules/storyteller/controllers/ajax/PagePicker.php create mode 100755 src/application/classes/movio/modules/storyteller/models/Comment.xml create mode 100644 src/application/classes/movio/modules/storyteller/views/components/Storyteller.xml create mode 100644 src/application/classes/movio/modules/storyteller/views/components/StorytellerCmp.php create mode 100644 src/application/classes/movio/modules/storyteller/views/skins/StorytellerSkinIterator.php create mode 100644 src/application/classes/movio/modules/thesaurus/Exception.php create mode 100644 src/application/classes/movio/modules/thesaurus/Module.php create mode 100644 src/application/classes/movio/modules/thesaurus/controllers/DeleteDictionary.php create mode 100644 src/application/classes/movio/modules/thesaurus/controllers/dictionaryEdit/ajax/Add.php create mode 100644 src/application/classes/movio/modules/thesaurus/controllers/dictionaryEdit/ajax/Save.php create mode 100644 src/application/classes/movio/modules/thesaurus/controllers/termEdit/Add.php create mode 100644 src/application/classes/movio/modules/thesaurus/controllers/termEdit/Edit.php create mode 100644 src/application/classes/movio/modules/thesaurus/controllers/termEdit/ajax/Add.php create mode 100644 src/application/classes/movio/modules/thesaurus/controllers/termEdit/ajax/Save.php create mode 100644 src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/DeleteTerm.php create mode 100644 src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/GetChildren.php create mode 100644 src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/MoveTerm.php create mode 100755 src/application/classes/movio/modules/thesaurus/js/Admin.js create mode 100755 src/application/classes/movio/modules/thesaurus/js/DictionaryTree.js create mode 100755 src/application/classes/movio/modules/thesaurus/js/TermEditIframe.js create mode 100644 src/application/classes/movio/modules/thesaurus/locale/en.php create mode 100644 src/application/classes/movio/modules/thesaurus/locale/it.php create mode 100644 src/application/classes/movio/modules/thesaurus/models/ChronologicTermVO.php create mode 100644 src/application/classes/movio/modules/thesaurus/models/Dictionary.xml create mode 100644 src/application/classes/movio/modules/thesaurus/models/DictionaryVO.php create mode 100644 src/application/classes/movio/modules/thesaurus/models/GenericTermVO.php create mode 100644 src/application/classes/movio/modules/thesaurus/models/GeographicalTermVO.php create mode 100644 src/application/classes/movio/modules/thesaurus/models/Term.xml create mode 100644 src/application/classes/movio/modules/thesaurus/models/TermFactory.php create mode 100644 src/application/classes/movio/modules/thesaurus/models/TermTypeEnum.php create mode 100644 src/application/classes/movio/modules/thesaurus/models/TermVO.php create mode 100644 src/application/classes/movio/modules/thesaurus/models/proxy/ThesaurusProxy.php create mode 100644 src/application/classes/movio/modules/thesaurus/static/FormatThesaurusSelectFrom.js create mode 100644 src/application/classes/movio/modules/thesaurus/views/Admin.xml create mode 100644 src/application/classes/movio/modules/thesaurus/views/components/DictionaryList.xml create mode 100644 src/application/classes/movio/modules/thesaurus/views/components/DictionaryListCmp.php create mode 100644 src/application/classes/movio/modules/thesaurus/views/components/DictionaryTreeView.php create mode 100755 src/application/classes/movio/modules/thesaurus/views/components/SelectDictionary.php create mode 100755 src/application/classes/movio/modules/thesaurus/views/components/SelectTerm.php create mode 100755 src/application/classes/movio/modules/thesaurus/views/components/ShowTaggedContents.php create mode 100644 src/application/classes/movio/modules/thesaurus/views/components/TermEdit.php create mode 100644 src/application/classes/movio/modules/thesaurus/views/renderer/CellEditDelete.php create mode 100644 src/application/classes/movio/modules/thesaurus/views/renderer/CellType.php create mode 100644 src/application/classes/movio/modules/touristoperators/Module.php create mode 100644 src/application/classes/movio/modules/touristoperators/UrlResolver.php create mode 100644 src/application/classes/movio/modules/touristoperators/config/routing.xml create mode 100644 src/application/classes/movio/modules/touristoperators/controllers/Index.php create mode 100644 src/application/classes/movio/modules/touristoperators/models/Model.xml create mode 100644 src/application/classes/movio/modules/touristoperators/views/Admin.xml create mode 100644 src/application/classes/movio/modules/touristoperators/views/FrontEnd.xml create mode 100644 src/application/classes/movio/modules/touristoperators/views/components/RecordDetail.php create mode 100644 src/application/classes/movio/modules/touristoperators/views/components/RecordSetMap.php create mode 100644 src/application/classes/movio/search/Content.php create mode 100644 src/application/classes/movio/search/Entity.php create mode 100644 src/application/classes/movio/search/models/Content.xml create mode 100644 src/application/classes/movio/search/models/Entity.xml create mode 100644 src/application/classes/movio/views/AbstractLessTemplate.php create mode 100644 src/application/classes/movio/views/TemplateModuleAdmin.xml create mode 100644 src/application/classes/movio/views/components/Boxes.xml create mode 100644 src/application/classes/movio/views/components/BoxesCmp.php create mode 100644 src/application/classes/movio/views/components/BoxesRepeater.php create mode 100644 src/application/classes/movio/views/components/BoxesSidebar.xml create mode 100644 src/application/classes/movio/views/components/GoogleMap.xml create mode 100644 src/application/classes/movio/views/components/GoogleMapCmp.php create mode 100644 src/application/classes/movio/views/components/ImageHotspot.php create mode 100644 src/application/classes/movio/views/components/Photogallery.xml create mode 100644 src/application/classes/movio/views/components/PhotogalleryCategory.xml create mode 100644 src/application/classes/movio/views/components/PhotogalleryCmp.php create mode 100644 src/application/classes/movio/views/components/RepeaterFromModel.php create mode 100644 src/application/classes/movio/views/components/Timeline.xml create mode 100644 src/application/classes/movio/views/components/TimelineCmp.php create mode 100644 src/application/classes/movio/views/components/Unity3D.xml create mode 100644 src/application/classes/movio/views/components/Unity3DCmp.php create mode 100644 src/application/classes/movio/views/components/Video.xml create mode 100644 src/application/classes/movio/views/components/VideoCmp.php create mode 100644 src/application/classes/userModules/movio/ontologybuilder/locale/.gitignore create mode 100644 src/application/classes/userModules/movio/ontologybuilder/skins/entities/.gitignore create mode 100644 src/application/config/acl.xml create mode 100644 src/application/config/config.xml create mode 100644 src/application/config/config_common.xml create mode 100644 src/application/config/fieldTypes.xml create mode 100644 src/application/config/routing.xml create mode 100755 src/application/libs/captcha/CaptchaBuilder.php create mode 100755 src/application/libs/captcha/CaptchaBuilderInterface.php create mode 100755 src/application/libs/captcha/Font/captcha0.ttf create mode 100755 src/application/libs/captcha/Font/captcha1.ttf create mode 100755 src/application/libs/captcha/Font/captcha2.ttf create mode 100755 src/application/libs/captcha/Font/captcha3.ttf create mode 100755 src/application/libs/captcha/Font/captcha4.ttf create mode 100755 src/application/libs/captcha/Font/captcha5.ttf create mode 100755 src/application/libs/captcha/ImageFileHandler.php create mode 100755 src/application/libs/captcha/LICENSE create mode 100755 src/application/libs/captcha/PhraseBuilder.php create mode 100755 src/application/libs/captcha/PhraseBuilderInterface.php create mode 100755 src/application/libs/captcha/README.md create mode 100755 src/application/libs/captcha/autoload.php create mode 100755 src/application/libs/captcha/composer.json create mode 100755 src/application/libs/captcha/demo/demo.php create mode 100755 src/application/libs/captcha/demo/fingerprint.php create mode 100755 src/application/libs/captcha/demo/index.php create mode 100755 src/application/libs/captcha/demo/ocr.php create mode 100755 src/application/libs/captcha/demo/output.php create mode 100755 src/application/libs/openzoom/Oz/Deepzoom/Descriptor.php create mode 100755 src/application/libs/openzoom/Oz/Deepzoom/Exception.php create mode 100755 src/application/libs/openzoom/Oz/Deepzoom/ImageCreator.php create mode 100755 src/application/libs/openzoom/thumbnail.inc.php create mode 100644 src/application/mediaArchive/Archive/index.html create mode 100644 src/application/mediaArchive/Audio/index.html create mode 100644 src/application/mediaArchive/Flash/index.html create mode 100644 src/application/mediaArchive/Image/index.html create mode 100644 src/application/mediaArchive/Office/index.html create mode 100644 src/application/mediaArchive/Other/index.html create mode 100644 src/application/mediaArchive/Pdf/index.html create mode 100644 src/application/mediaArchive/Video/index.html create mode 100644 src/application/pageTypes/Alias.xml create mode 100755 src/application/pageTypes/Common.xml create mode 100644 src/application/pageTypes/Cover.xml create mode 100644 src/application/pageTypes/DictionaryList.xml create mode 100644 src/application/pageTypes/DigitalExhibition.xml create mode 100644 src/application/pageTypes/Empty.xml create mode 100644 src/application/pageTypes/Entity.xml create mode 100644 src/application/pageTypes/Exhibition.xml create mode 100644 src/application/pageTypes/GoogleMap.xml create mode 100644 src/application/pageTypes/Graph.xml create mode 100644 src/application/pageTypes/Home.xml create mode 100644 src/application/pageTypes/ImageHotspot.xml create mode 100644 src/application/pageTypes/Login.xml create mode 100644 src/application/pageTypes/Logout.xml create mode 100644 src/application/pageTypes/LostPassword.xml create mode 100644 src/application/pageTypes/Page.xml create mode 100644 src/application/pageTypes/Photogallery.xml create mode 100644 src/application/pageTypes/Photogallery_category.xml create mode 100644 src/application/pageTypes/ProfileListContents.xml create mode 100644 src/application/pageTypes/Registration.xml create mode 100644 src/application/pageTypes/Search.xml create mode 100644 src/application/pageTypes/SiteMap.xml create mode 100644 src/application/pageTypes/Storyteller.xml create mode 100644 src/application/pageTypes/Timeline.xml create mode 100644 src/application/pageTypes/Unity3D.xml create mode 100644 src/application/pageTypes/UserDetails.xml create mode 100644 src/application/pageTypes/Video.xml create mode 100644 src/application/startup/index.php create mode 100644 src/application/startup/movio.php create mode 100644 src/application/startup/plugin.php create mode 100644 src/cache/.gitkeep create mode 100644 src/checkUpdate.php create mode 100755 src/core/.htaccess create mode 100755 src/core/COPYRIGHT.txt create mode 100755 src/core/LICENSE.txt create mode 100755 src/core/classes/org/glizy/Assets.php create mode 100755 src/core/classes/org/glizy/Config.php create mode 100755 src/core/classes/org/glizy/Exception.php create mode 100755 src/core/classes/org/glizy/GlizyObject.php create mode 100755 src/core/classes/org/glizy/Modules.php create mode 100755 src/core/classes/org/glizy/ObjectFactory.php create mode 100755 src/core/classes/org/glizy/ObjectValues.php create mode 100755 src/core/classes/org/glizy/Paths.php create mode 100755 src/core/classes/org/glizy/Registry.php create mode 100755 src/core/classes/org/glizy/Request.php create mode 100755 src/core/classes/org/glizy/Routing.php create mode 100755 src/core/classes/org/glizy/Session.php create mode 100755 src/core/classes/org/glizy/SessionEx.php create mode 100755 src/core/classes/org/glizy/application/Acl.php create mode 100755 src/core/classes/org/glizy/application/AclAdvanced.php create mode 100755 src/core/classes/org/glizy/application/Application.php create mode 100755 src/core/classes/org/glizy/application/ApplicationXML.php create mode 100755 src/core/classes/org/glizy/application/MessageStack.php create mode 100755 src/core/classes/org/glizy/application/SiteMap.php create mode 100755 src/core/classes/org/glizy/application/SiteMapIterator.php create mode 100755 src/core/classes/org/glizy/application/SiteMapNode.php create mode 100755 src/core/classes/org/glizy/application/SiteMapSimple.php create mode 100755 src/core/classes/org/glizy/application/SiteMapXML.php create mode 100755 src/core/classes/org/glizy/application/User.php create mode 100755 src/core/classes/org/glizy/authentication/AbstractLogin.php create mode 100755 src/core/classes/org/glizy/authentication/AuthenticationDriver.php create mode 100755 src/core/classes/org/glizy/authentication/AuthenticationException.php create mode 100755 src/core/classes/org/glizy/authentication/Database.php create mode 100755 src/core/classes/org/glizy/cache/CacheFile.php create mode 100755 src/core/classes/org/glizy/cache/CacheFunction.php create mode 100755 src/core/classes/org/glizy/compilers/Acl.php create mode 100755 src/core/classes/org/glizy/compilers/Compiler.php create mode 100755 src/core/classes/org/glizy/compilers/CompilerException.php create mode 100755 src/core/classes/org/glizy/compilers/Component.php create mode 100755 src/core/classes/org/glizy/compilers/Config.php create mode 100755 src/core/classes/org/glizy/compilers/LayoutManagerPHP.php create mode 100755 src/core/classes/org/glizy/compilers/Model.php create mode 100755 src/core/classes/org/glizy/compilers/ModelException.php create mode 100755 src/core/classes/org/glizy/compilers/PageType.php create mode 100644 src/core/classes/org/glizy/compilers/PageTypeException.php create mode 100755 src/core/classes/org/glizy/compilers/Routing.php create mode 100755 src/core/classes/org/glizy/compilers/Skin.php create mode 100755 src/core/classes/org/glizy/components/Authenticator.php create mode 100755 src/core/classes/org/glizy/components/Breadcrumbs.php create mode 100755 src/core/classes/org/glizy/components/Button.php create mode 100755 src/core/classes/org/glizy/components/CSS.php create mode 100755 src/core/classes/org/glizy/components/Caption.php create mode 100755 src/core/classes/org/glizy/components/Checkbox.php create mode 100755 src/core/classes/org/glizy/components/ColorPicker.php create mode 100755 src/core/classes/org/glizy/components/Component.php create mode 100755 src/core/classes/org/glizy/components/ComponentContainer.php create mode 100755 src/core/classes/org/glizy/components/ConfigValue.php create mode 100755 src/core/classes/org/glizy/components/DBdebug.php create mode 100755 src/core/classes/org/glizy/components/DataDictionary.php create mode 100755 src/core/classes/org/glizy/components/DataGrid.php create mode 100644 src/core/classes/org/glizy/components/DataGridAjax.php create mode 100755 src/core/classes/org/glizy/components/DataGridColumn.php create mode 100755 src/core/classes/org/glizy/components/DataProvider.php create mode 100755 src/core/classes/org/glizy/components/Date.php create mode 100755 src/core/classes/org/glizy/components/Email.php create mode 100755 src/core/classes/org/glizy/components/EmbedPage.php create mode 100755 src/core/classes/org/glizy/components/EmptyComponent.php create mode 100755 src/core/classes/org/glizy/components/Fieldset.php create mode 100755 src/core/classes/org/glizy/components/FilterValue.php create mode 100755 src/core/classes/org/glizy/components/Filters.php create mode 100755 src/core/classes/org/glizy/components/Form.php create mode 100755 src/core/classes/org/glizy/components/FormLabel.php create mode 100755 src/core/classes/org/glizy/components/GoogleMap.php create mode 100755 src/core/classes/org/glizy/components/Groupbox.php create mode 100755 src/core/classes/org/glizy/components/HBox.php create mode 100755 src/core/classes/org/glizy/components/Hidden.php create mode 100755 src/core/classes/org/glizy/components/HtmlButton.php create mode 100755 src/core/classes/org/glizy/components/HtmlComponent.php create mode 100755 src/core/classes/org/glizy/components/HtmlComponentContainer.php create mode 100755 src/core/classes/org/glizy/components/HtmlFormElement.php create mode 100755 src/core/classes/org/glizy/components/Image.php create mode 100755 src/core/classes/org/glizy/components/ImageExternal.php create mode 100755 src/core/classes/org/glizy/components/Import.php create mode 100755 src/core/classes/org/glizy/components/Input.php create mode 100644 src/core/classes/org/glizy/components/JSTab.php create mode 100644 src/core/classes/org/glizy/components/JSTabGroup.php create mode 100755 src/core/classes/org/glizy/components/JSscript.php create mode 100755 src/core/classes/org/glizy/components/Link.php create mode 100755 src/core/classes/org/glizy/components/LinkTo.php create mode 100755 src/core/classes/org/glizy/components/List.php create mode 100755 src/core/classes/org/glizy/components/ListItem.php create mode 100755 src/core/classes/org/glizy/components/ListMenuItem.php create mode 100755 src/core/classes/org/glizy/components/Login.php create mode 100755 src/core/classes/org/glizy/components/LoginBox.php create mode 100755 src/core/classes/org/glizy/components/LoginCheck.php create mode 100755 src/core/classes/org/glizy/components/Logout.php create mode 100755 src/core/classes/org/glizy/components/LongText.php create mode 100755 src/core/classes/org/glizy/components/Media.php create mode 100755 src/core/classes/org/glizy/components/MessageBox.php create mode 100755 src/core/classes/org/glizy/components/ModelDefine.php create mode 100755 src/core/classes/org/glizy/components/Modifier.php create mode 100755 src/core/classes/org/glizy/components/Module.php create mode 100755 src/core/classes/org/glizy/components/NavigationMenu.php create mode 100755 src/core/classes/org/glizy/components/NullComponent.php create mode 100755 src/core/classes/org/glizy/components/Number.php create mode 100755 src/core/classes/org/glizy/components/OutputFilter.php create mode 100755 src/core/classes/org/glizy/components/OutputFilterGroup.php create mode 100755 src/core/classes/org/glizy/components/Page.php create mode 100755 src/core/classes/org/glizy/components/PageTitle.php create mode 100755 src/core/classes/org/glizy/components/PaginateResult.php create mode 100755 src/core/classes/org/glizy/components/Panel.php create mode 100755 src/core/classes/org/glizy/components/PdfButton.php create mode 100755 src/core/classes/org/glizy/components/RadioButton.php create mode 100755 src/core/classes/org/glizy/components/RecordDetail.php create mode 100755 src/core/classes/org/glizy/components/RecordDetailEx.php create mode 100755 src/core/classes/org/glizy/components/RecordSetBox.php create mode 100755 src/core/classes/org/glizy/components/RecordSetList.php create mode 100755 src/core/classes/org/glizy/components/Repeater.php create mode 100755 src/core/classes/org/glizy/components/RepeaterRecord.php create mode 100755 src/core/classes/org/glizy/components/Script.php create mode 100755 src/core/classes/org/glizy/components/Search.php create mode 100755 src/core/classes/org/glizy/components/SearchBox.php create mode 100755 src/core/classes/org/glizy/components/SearchFilters.php create mode 100755 src/core/classes/org/glizy/components/SelectPage.php create mode 100755 src/core/classes/org/glizy/components/SimpleList.php create mode 100755 src/core/classes/org/glizy/components/SkinDefine.php create mode 100755 src/core/classes/org/glizy/components/State.php create mode 100755 src/core/classes/org/glizy/components/StateSwitch.php create mode 100755 src/core/classes/org/glizy/components/StateSwitchClass.php create mode 100755 src/core/classes/org/glizy/components/Tab.php create mode 100755 src/core/classes/org/glizy/components/TabGroup.php create mode 100755 src/core/classes/org/glizy/components/Text.php create mode 100755 src/core/classes/org/glizy/components/Url.php create mode 100755 src/core/classes/org/glizy/components/UserBox.php create mode 100755 src/core/classes/org/glizy/components/VBox.php create mode 100644 src/core/classes/org/glizy/components/interfaces/IDataProvider.php create mode 100644 src/core/classes/org/glizy/components/interfaces/ISearchFilters.php create mode 100755 src/core/classes/org/glizy/components/render/Render.php create mode 100755 src/core/classes/org/glizy/components/render/RenderCell.php create mode 100755 src/core/classes/org/glizy/components/render/RenderCellRecordSetList.php create mode 100755 src/core/classes/org/glizy/components/render/RenderCellRow.php create mode 100755 src/core/classes/org/glizy/dataAccess/ActiveRecord.php create mode 100755 src/core/classes/org/glizy/dataAccess/ActiveRecord2tables.php create mode 100755 src/core/classes/org/glizy/dataAccess/DataAccess.php create mode 100755 src/core/classes/org/glizy/dataAccess/RecordIterator.php create mode 100755 src/core/classes/org/glizy/dataAccess/Relation.php create mode 100755 src/core/classes/org/glizy/dataAccess/RelationContentTable.php create mode 100755 src/core/classes/org/glizy/dataAccess/RelationHasMany.php create mode 100755 src/core/classes/org/glizy/dataAccess/RelationHasOne.php create mode 100755 src/core/classes/org/glizy/dataAccess/RelationJoinTable.php create mode 100755 src/core/classes/org/glizy/dataAccess/RelationMany2Many.php create mode 100755 src/core/classes/org/glizy/dataAccess/cache/ActiveRecord.php create mode 100755 src/core/classes/org/glizy/dataAccess/cache/Iterator.php create mode 100755 src/core/classes/org/glizy/dataAccess/cache/Query.php create mode 100755 src/core/classes/org/glizy/dataAccess/cache/QueryRedis.php create mode 100755 src/core/classes/org/glizy/dataAccess/driver/Connection.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/AbstractRecordIterator.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/AbstractRelation.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecord.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecord2tables.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordDocument.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordException.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordSimpleDocument.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/Connection.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/DataAccess.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/DbField.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/IndexQueue.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/Query/Expression/ExpressionBuilder.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/Query/QueryBuilder.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/RecordIterator.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/RecordIterator2tables.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/RecordIteratorDocument.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/RecordIteratorSimpleDocument.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/RelationFactory.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/RelationJoinTable.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/SchemaManager.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/SqlRecordIterator.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/SystemField.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/interfaces/RelationInterface.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/logging/DebugLogger.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/logging/EchoSQLLogger.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/types/Array.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/types/ArrayID.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/types/Boolean.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/types/Date.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/types/DateTime.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/types/DateTimeTz.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/types/Time.php create mode 100644 src/core/classes/org/glizy/dataAccessDoctrine/types/Types.php create mode 100755 src/core/classes/org/glizy/dataAccessDoctrine/vo/DocumentObjectVO.php create mode 100644 src/core/classes/org/glizy/debug/GlizyDebugBar.php create mode 100644 src/core/classes/org/glizy/debug/Helpers.php create mode 100644 src/core/classes/org/glizy/debug/Module.php create mode 100644 src/core/classes/org/glizy/debug/Whoops.php create mode 100644 src/core/classes/org/glizy/debug/dataCollector/GlizyCollector.php create mode 100644 src/core/classes/org/glizy/debug/views/components/DebugBar.php create mode 100755 src/core/classes/org/glizy/events/Event.php create mode 100755 src/core/classes/org/glizy/events/EventDispatcher.php create mode 100755 src/core/classes/org/glizy/events/EventException.php create mode 100755 src/core/classes/org/glizy/filters/ForceNoTagText.php create mode 100755 src/core/classes/org/glizy/filters/OutputFilter.php create mode 100755 src/core/classes/org/glizy/filters/Uppercase.php create mode 100755 src/core/classes/org/glizy/helpers/ActiveRecord.php create mode 100755 src/core/classes/org/glizy/helpers/Array.php create mode 100755 src/core/classes/org/glizy/helpers/CSS.php create mode 100644 src/core/classes/org/glizy/helpers/Convert.php create mode 100644 src/core/classes/org/glizy/helpers/Files.php create mode 100755 src/core/classes/org/glizy/helpers/Html.php create mode 100755 src/core/classes/org/glizy/helpers/JS.php create mode 100755 src/core/classes/org/glizy/helpers/Link.php create mode 100644 src/core/classes/org/glizy/helpers/Mail.php create mode 100755 src/core/classes/org/glizy/helpers/Media.php create mode 100755 src/core/classes/org/glizy/helpers/Navigation.php create mode 100755 src/core/classes/org/glizy/helpers/PhpScript.php create mode 100755 src/core/classes/org/glizy/helpers/String.php create mode 100755 src/core/classes/org/glizy/locale/Locale.php create mode 100755 src/core/classes/org/glizy/locale/de.php create mode 100755 src/core/classes/org/glizy/locale/en.php create mode 100755 src/core/classes/org/glizy/locale/fr.php create mode 100755 src/core/classes/org/glizy/locale/it.php create mode 100755 src/core/classes/org/glizy/log/Console.php create mode 100755 src/core/classes/org/glizy/log/DB.php create mode 100755 src/core/classes/org/glizy/log/ElasticSearch.php create mode 100755 src/core/classes/org/glizy/log/File.php create mode 100755 src/core/classes/org/glizy/log/FireBug.php create mode 100755 src/core/classes/org/glizy/log/LiveLog.php create mode 100755 src/core/classes/org/glizy/log/LogBase.php create mode 100755 src/core/classes/org/glizy/log/LogFactory.php create mode 100755 src/core/classes/org/glizy/log/Mail.php create mode 100755 src/core/classes/org/glizy/log/Null.php create mode 100755 src/core/classes/org/glizy/middleware/AbstractHttpCache.php create mode 100755 src/core/classes/org/glizy/middleware/DynamicPage.php create mode 100644 src/core/classes/org/glizy/middleware/IMiddleware.php create mode 100755 src/core/classes/org/glizy/middleware/StaticPage.php create mode 100755 src/core/classes/org/glizy/models/Join.xml create mode 100755 src/core/classes/org/glizy/models/JoinDoctrine.xml create mode 100755 src/core/classes/org/glizy/models/Log.xml create mode 100755 src/core/classes/org/glizy/models/Registry.xml create mode 100644 src/core/classes/org/glizy/models/Role.xml create mode 100755 src/core/classes/org/glizy/models/User.xml create mode 100755 src/core/classes/org/glizy/models/UserGroup.xml create mode 100755 src/core/classes/org/glizy/models/UserLog.xml create mode 100755 src/core/classes/org/glizy/mvc/components/Page.php create mode 100755 src/core/classes/org/glizy/mvc/components/State.php create mode 100755 src/core/classes/org/glizy/mvc/components/StateTabNavigation.php create mode 100755 src/core/classes/org/glizy/mvc/core/Application.php create mode 100755 src/core/classes/org/glizy/mvc/core/Command.php create mode 100755 src/core/classes/org/glizy/mvc/core/CommandAjax.php create mode 100755 src/core/classes/org/glizy/mvc/core/Proxy.php create mode 100755 src/core/classes/org/glizy/mvc/scaffold/controllers/AbstractCommand.php create mode 100755 src/core/classes/org/glizy/mvc/scaffold/controllers/Add.php create mode 100755 src/core/classes/org/glizy/mvc/scaffold/controllers/Delete.php create mode 100755 src/core/classes/org/glizy/mvc/scaffold/controllers/Show.php create mode 100755 src/core/classes/org/glizy/oaipmh/OaiPmh.php create mode 100755 src/core/classes/org/glizy/oaipmh/components/GetRecord.php create mode 100755 src/core/classes/org/glizy/oaipmh/components/Identify.php create mode 100755 src/core/classes/org/glizy/oaipmh/components/ListIdentifiers.php create mode 100755 src/core/classes/org/glizy/oaipmh/components/ListMetadataFormats.php create mode 100755 src/core/classes/org/glizy/oaipmh/components/ListRecords.php create mode 100755 src/core/classes/org/glizy/oaipmh/components/ListSets.php create mode 100755 src/core/classes/org/glizy/oaipmh/components/Page.php create mode 100755 src/core/classes/org/glizy/oaipmh/core/AbstractMapping.php create mode 100755 src/core/classes/org/glizy/oaipmh/core/Application.php create mode 100755 src/core/classes/org/glizy/oaipmh/models/PicoQueue.xml create mode 100755 src/core/classes/org/glizy/oaipmh/pageTypes/index.xml create mode 100755 src/core/classes/org/glizy/parser/XML.php create mode 100755 src/core/classes/org/glizy/plugins/PluginClient.php create mode 100755 src/core/classes/org/glizy/plugins/PluginManager.php create mode 100755 src/core/classes/org/glizy/plugins/PluginServer.php create mode 100755 src/core/classes/org/glizy/plugins/Search.php create mode 100755 src/core/classes/org/glizy/redis/Client.php create mode 100755 src/core/classes/org/glizy/rest/core/Application.php create mode 100755 src/core/classes/org/glizy/rest/core/CommandRest.php create mode 100755 src/core/classes/org/glizy/rest/core/RestRequest.php create mode 100755 src/core/classes/org/glizy/rest/core/RestRequestMultipart.php create mode 100755 src/core/classes/org/glizy/sessionStore/Redis.php create mode 100755 src/core/classes/org/glizy/template/layoutManager/DWT.php create mode 100755 src/core/classes/org/glizy/template/layoutManager/LayoutManager.php create mode 100755 src/core/classes/org/glizy/template/layoutManager/PDF.php create mode 100755 src/core/classes/org/glizy/template/layoutManager/PHP.php create mode 100755 src/core/classes/org/glizy/template/layoutManager/PHPTAL.php create mode 100755 src/core/classes/org/glizy/template/skin/PHP.php create mode 100755 src/core/classes/org/glizy/template/skin/PHPTAL.php create mode 100755 src/core/classes/org/glizy/template/skin/Skin.php create mode 100755 src/core/classes/org/glizy/template/skin/TWIG.php create mode 100644 src/core/classes/org/glizy/types/Date.php create mode 100644 src/core/classes/org/glizy/types/DateTime.php create mode 100644 src/core/classes/org/glizy/types/DateTimeTz.php create mode 100644 src/core/classes/org/glizy/types/Time.php create mode 100755 src/core/classes/org/glizy/validators/AbstractValidator.php create mode 100755 src/core/classes/org/glizy/validators/CompositeValidator.php create mode 100755 src/core/classes/org/glizy/validators/Date.php create mode 100644 src/core/classes/org/glizy/validators/DateTime.php create mode 100755 src/core/classes/org/glizy/validators/Email.php create mode 100755 src/core/classes/org/glizy/validators/NotNull.php create mode 100755 src/core/classes/org/glizy/validators/Numeric.php create mode 100755 src/core/classes/org/glizy/validators/Text.php create mode 100755 src/core/classes/org/glizy/validators/ValidationException.php create mode 100755 src/core/classes/org/glizy/validators/Validator.php create mode 100755 src/core/classes/org/glizycms/Glizycms.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/Delete.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/Edit.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/Cancel.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/Save.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/SaveClose.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/autocomplete/ajax/FindTerm.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/autocomplete/ajax/PagePicker.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/moduleEdit/Delete.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/moduleEdit/Edit.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/moduleEdit/EditDraft.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/moduleEdit/Togglevisibility.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/Save.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveClose.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveDraft.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveDraftClose.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/Add.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/Addblock.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/Edit.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/Permissions.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/Properties.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Add.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Addblock.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/GetChildBlocks.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/MoveBlock.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Save.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveClose.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SavePermissions.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveProperties.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveTemplate.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/AddPage.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Delete.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/GetSiteTree.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Hide.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Lock.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Move.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Rename.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Show.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Unlock.php create mode 100644 src/core/classes/org/glizycms/contents/controllers/tinymce/ajax/GlzLinkList.php create mode 100644 src/core/classes/org/glizycms/contents/events/Menu.php create mode 100755 src/core/classes/org/glizycms/contents/js/BlocksEdit.js create mode 100755 src/core/classes/org/glizycms/contents/js/ContentsEdit.js create mode 100755 src/core/classes/org/glizycms/contents/js/PageEditIframe.js create mode 100755 src/core/classes/org/glizycms/contents/js/SiteTree.js create mode 100644 src/core/classes/org/glizycms/contents/locale/en.php create mode 100644 src/core/classes/org/glizycms/contents/locale/it.php create mode 100644 src/core/classes/org/glizycms/contents/models/ContentVO.php create mode 100644 src/core/classes/org/glizycms/contents/models/DocumentACL.php create mode 100644 src/core/classes/org/glizycms/contents/models/Menu.php create mode 100644 src/core/classes/org/glizycms/contents/models/Role.xml create mode 100644 src/core/classes/org/glizycms/contents/models/proxy/ActiveRecordProxy.php create mode 100644 src/core/classes/org/glizycms/contents/models/proxy/ContentFindTermProxy.php create mode 100644 src/core/classes/org/glizycms/contents/models/proxy/ContentProxy.php create mode 100644 src/core/classes/org/glizycms/contents/models/proxy/MenuProxy.php create mode 100644 src/core/classes/org/glizycms/contents/models/proxy/ModuleContentProxy.php create mode 100644 src/core/classes/org/glizycms/contents/services/PageTypeService.php create mode 100644 src/core/classes/org/glizycms/contents/views/ContentsEdit.xml create mode 100644 src/core/classes/org/glizycms/contents/views/components/PageEdit.php create mode 100644 src/core/classes/org/glizycms/contents/views/components/ShowHistory.php create mode 100644 src/core/classes/org/glizycms/contents/views/components/SiteTreeView.php create mode 100644 src/core/classes/org/glizycms/contents/views/renderer/AbstractCellEdit.php create mode 100644 src/core/classes/org/glizycms/contents/views/renderer/CellDelete.php create mode 100644 src/core/classes/org/glizycms/contents/views/renderer/CellEdit.php create mode 100644 src/core/classes/org/glizycms/contents/views/renderer/CellEditDelete.php create mode 100644 src/core/classes/org/glizycms/contents/views/renderer/CellEditDeleteVisible.php create mode 100644 src/core/classes/org/glizycms/contents/views/renderer/CellEditDraftDelete.php create mode 100644 src/core/classes/org/glizycms/contents/views/renderer/CellEditDraftDeleteVisible.php create mode 100644 src/core/classes/org/glizycms/contents/views/renderer/DocumentTitle.php create mode 100644 src/core/classes/org/glizycms/core/application/AdminApplication.php create mode 100755 src/core/classes/org/glizycms/core/application/Application.php create mode 100755 src/core/classes/org/glizycms/core/application/SiteMapDB.php create mode 100644 src/core/classes/org/glizycms/core/application/renderer/CellUser.php create mode 100644 src/core/classes/org/glizycms/core/application/renderer/CellUserActive.php create mode 100644 src/core/classes/org/glizycms/core/helpers/Fulltext.php create mode 100755 src/core/classes/org/glizycms/core/models/Content.xml create mode 100755 src/core/classes/org/glizycms/core/models/Country.xml create mode 100755 src/core/classes/org/glizycms/core/models/Language.xml create mode 100755 src/core/classes/org/glizycms/core/models/Menu.xml create mode 100755 src/core/classes/org/glizycms/core/models/MenuDetail.xml create mode 100644 src/core/classes/org/glizycms/core/models/enum/FieldTypeEnum.php create mode 100644 src/core/classes/org/glizycms/core/models/enum/MenuEnum.php create mode 100755 src/core/classes/org/glizycms/groupManager/models/UserGroup.xml create mode 100755 src/core/classes/org/glizycms/groupManager/views/GroupManagerEdit.xml create mode 100755 src/core/classes/org/glizycms/helpers/Media.php create mode 100644 src/core/classes/org/glizycms/helpers/Modules.php create mode 100755 src/core/classes/org/glizycms/js/.htaccess create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEdit.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditCheckbox.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditCmsPagePicker.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditColorPicker.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditDate.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditDatetime.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditFile.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditGUID.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditGoogleMaps.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditImageHotspot.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditMediaPicker.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditPermission.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditPhotoGalleryCategory.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditSelectFrom.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditSelectPageType.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditTINYMCE.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditTreeSelect.js create mode 100644 src/core/classes/org/glizycms/js/formEdit/GlizyFormEditValuesPreset.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEdit.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditCheckbox.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditCmsPagePicker.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditColorPicker.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditDate.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditDateTime.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditFile.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditGUID.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditGoogleMaps.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditMediaPicker.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditModalPage.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditPermission.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditPhotoGalleryCategory.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditRepeat.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditSelectFrom.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditSelectPageType.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditStandard.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditTINYMCE.js create mode 100644 src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditUrl.js create mode 100644 src/core/classes/org/glizycms/js/glizy-locale/en-EN.js create mode 100644 src/core/classes/org/glizycms/js/glizy-locale/it-IT.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/LICENSE create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/README.md create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha.png create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/img/bootstrap-colorpicker/hue.png create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/img/bootstrap-colorpicker/saturation.png create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/css/datetimepicker.css create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/bootstrap-datetimepicker.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datepicker.uk.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.bg.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.cs.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.da.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.de.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.es.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.fi.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.fr.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.he.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.hr.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.id.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.is.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.it.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ja.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.kr.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.lt.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.lv.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ms.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.nb.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.nl.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pl.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pt-BR.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pt.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ro.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.rs-latin.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.rs.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ru.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sk.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sl.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sv.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.th.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.tr.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.zh-CN.js create mode 100755 src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.zh-TW.js create mode 100755 src/core/classes/org/glizycms/js/jquery/dropzone/css/basic.css create mode 100755 src/core/classes/org/glizycms/js/jquery/dropzone/css/basic2.css create mode 100755 src/core/classes/org/glizycms/js/jquery/dropzone/css/dropzone.css create mode 100755 src/core/classes/org/glizycms/js/jquery/dropzone/dropzone.js create mode 100755 src/core/classes/org/glizycms/js/jquery/dropzone/dropzone.min.js create mode 100755 src/core/classes/org/glizycms/js/jquery/dropzone/images/spritemap.png create mode 100755 src/core/classes/org/glizycms/js/jquery/dropzone/images/spritemap@2x.png create mode 100644 src/core/classes/org/glizycms/js/jquery/fancytree/jquery.fancytree-all.js create mode 100644 src/core/classes/org/glizycms/js/jquery/fancytree/jquery.fancytree-all.min.js create mode 100644 src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/icons.gif create mode 100644 src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/loading.gif create mode 100644 src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.css create mode 100644 src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.less create mode 100644 src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.min.css create mode 100755 src/core/classes/org/glizycms/js/jquery/jquery.pnotify/jquery.pnotify.default.css create mode 100644 src/core/classes/org/glizycms/js/jquery/jquery.pnotify/jquery.pnotify.min.js create mode 100644 src/core/classes/org/glizycms/js/jquery/jquery.validVal-packed.js create mode 100755 src/core/classes/org/glizycms/js/jquery/select2/LICENSE create mode 100755 src/core/classes/org/glizycms/js/jquery/select2/README.md create mode 100755 src/core/classes/org/glizycms/js/jquery/select2/release.sh create mode 100755 src/core/classes/org/glizycms/js/jquery/select2/select2.css create mode 100755 src/core/classes/org/glizycms/js/jquery/select2/select2.js create mode 100755 src/core/classes/org/glizycms/js/jquery/select2/select2.min.js create mode 100755 src/core/classes/org/glizycms/js/jquery/select2/select2.png create mode 100755 src/core/classes/org/glizycms/js/jquery/select2/select2x2.png create mode 100755 src/core/classes/org/glizycms/js/jquery/select2/spinner.gif create mode 100644 src/core/classes/org/glizycms/js/underscore/underscore-min.js create mode 100644 src/core/classes/org/glizycms/js/underscore/underscore-min.map create mode 100755 src/core/classes/org/glizycms/js/visualsearch/cancel_search.png create mode 100755 src/core/classes/org/glizycms/js/visualsearch/dependencies.js create mode 100755 src/core/classes/org/glizycms/js/visualsearch/dependencies.js.gz create mode 100755 src/core/classes/org/glizycms/js/visualsearch/search_glyph.png create mode 100755 src/core/classes/org/glizycms/js/visualsearch/visualsearch-datauri.css create mode 100755 src/core/classes/org/glizycms/js/visualsearch/visualsearch-datauri.css.gz create mode 100755 src/core/classes/org/glizycms/js/visualsearch/visualsearch.css create mode 100755 src/core/classes/org/glizycms/js/visualsearch/visualsearch.css.gz create mode 100755 src/core/classes/org/glizycms/js/visualsearch/visualsearch.js create mode 100755 src/core/classes/org/glizycms/js/visualsearch/visualsearch.js.gz create mode 100755 src/core/classes/org/glizycms/js/visualsearch/visualsearch_templates.js create mode 100755 src/core/classes/org/glizycms/js/visualsearch/visualsearch_templates.js.gz create mode 100644 src/core/classes/org/glizycms/languages/controllers/Delete.php create mode 100644 src/core/classes/org/glizycms/languages/controllers/Edit.php create mode 100644 src/core/classes/org/glizycms/languages/controllers/ajax/Cancel.php create mode 100644 src/core/classes/org/glizycms/languages/controllers/ajax/Save.php create mode 100644 src/core/classes/org/glizycms/languages/controllers/ajax/SaveClose.php create mode 100644 src/core/classes/org/glizycms/languages/locale/en.php create mode 100644 src/core/classes/org/glizycms/languages/locale/it.php create mode 100644 src/core/classes/org/glizycms/languages/models/proxy/LanguagesProxy.php create mode 100644 src/core/classes/org/glizycms/languages/views/Admin.xml create mode 100644 src/core/classes/org/glizycms/languages/views/renderer/CellEditDelete.php create mode 100644 src/core/classes/org/glizycms/locale/en.php create mode 100644 src/core/classes/org/glizycms/locale/it.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/Bridge.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/IBridge.php create mode 100755 src/core/classes/org/glizycms/mediaArchive/MediaManager.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/controllers/Add.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/controllers/AddFromZip.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/controllers/Delete.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/controllers/Index.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/controllers/ajax/Delete.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/Edit.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/Cancel.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/Save.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/SaveClose.php create mode 100755 src/core/classes/org/glizycms/mediaArchive/media/Archive.php create mode 100755 src/core/classes/org/glizycms/mediaArchive/media/Audio.php create mode 100755 src/core/classes/org/glizycms/mediaArchive/media/Flash.php create mode 100755 src/core/classes/org/glizycms/mediaArchive/media/Image.php create mode 100755 src/core/classes/org/glizycms/mediaArchive/media/Media.php create mode 100755 src/core/classes/org/glizycms/mediaArchive/media/Office.php create mode 100755 src/core/classes/org/glizycms/mediaArchive/media/Other.php create mode 100755 src/core/classes/org/glizycms/mediaArchive/media/Pdf.php create mode 100755 src/core/classes/org/glizycms/mediaArchive/media/Video.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/models/Exif.xml create mode 100644 src/core/classes/org/glizycms/mediaArchive/models/proxy/MediaProxy.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/services/ExifService.php create mode 100755 src/core/classes/org/glizycms/mediaArchive/services/MediaMappingService.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/views/MediaArchive.xml create mode 100644 src/core/classes/org/glizycms/mediaArchive/views/MediaPicker.xml create mode 100755 src/core/classes/org/glizycms/mediaArchive/views/MediaStorageBrowser.xml create mode 100644 src/core/classes/org/glizycms/mediaArchive/views/components/CustomStorageBrowser.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/views/components/FilePicker.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/views/components/ShowExif.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchive.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchiveInfo.php create mode 100644 src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchiveThumb.php create mode 100755 src/core/classes/org/glizycms/models/ActiveRecordSimpleDocumentArraysIndexed.php create mode 100755 src/core/classes/org/glizycms/models/Media.xml create mode 100644 src/core/classes/org/glizycms/modulesManager/controllers/Duplicate.php create mode 100755 src/core/classes/org/glizycms/modulesManager/controllers/ajax/Disable.php create mode 100755 src/core/classes/org/glizycms/modulesManager/controllers/ajax/Enable.php create mode 100755 src/core/classes/org/glizycms/modulesManager/views/ModulesManager.xml create mode 100644 src/core/classes/org/glizycms/modulesManager/views/components/Datagrid.php create mode 100755 src/core/classes/org/glizycms/roleManager/AdminPage.xml create mode 100644 src/core/classes/org/glizycms/roleManager/controllers/Login.php create mode 100644 src/core/classes/org/glizycms/roleManager/controllers/StateController.php create mode 100755 src/core/classes/org/glizycms/roleManager/models/Group.xml create mode 100755 src/core/classes/org/glizycms/roleManager/models/Role.xml create mode 100755 src/core/classes/org/glizycms/roleManager/models/User.xml create mode 100644 src/core/classes/org/glizycms/roleManager/services/RoleService.php create mode 100644 src/core/classes/org/glizycms/roleManager/views/Input.php create mode 100644 src/core/classes/org/glizycms/roleManager/views/Permissions.php create mode 100644 src/core/classes/org/glizycms/siteProperties/controllers/Index.php create mode 100644 src/core/classes/org/glizycms/siteProperties/controllers/ajax/Save.php create mode 100644 src/core/classes/org/glizycms/siteProperties/views/SiteProperties.xml create mode 100644 src/core/classes/org/glizycms/speakingUrl/AbstractDocumentResolver.php create mode 100644 src/core/classes/org/glizycms/speakingUrl/AbstractUrlResolver.php create mode 100644 src/core/classes/org/glizycms/speakingUrl/IUrlResolver.php create mode 100644 src/core/classes/org/glizycms/speakingUrl/Manager.php create mode 100644 src/core/classes/org/glizycms/speakingUrl/PageResolver.php create mode 100755 src/core/classes/org/glizycms/speakingUrl/models/SpeakingUrl.xml create mode 100644 src/core/classes/org/glizycms/speakingUrl/models/proxy/SpeakingUrlProxy.php create mode 100644 src/core/classes/org/glizycms/template/controllers/CheckTemplateTabDraw.php create mode 100644 src/core/classes/org/glizycms/template/controllers/Template.php create mode 100644 src/core/classes/org/glizycms/template/controllers/ajax/Save.php create mode 100644 src/core/classes/org/glizycms/template/controllers/ajax/SaveTemplate.php create mode 100644 src/core/classes/org/glizycms/template/fe/views/AbstractLessTemplate.php create mode 100644 src/core/classes/org/glizycms/template/models/TemplateVO.php create mode 100644 src/core/classes/org/glizycms/template/models/proxy/TemplateProxy.php create mode 100644 src/core/classes/org/glizycms/template/views/TemplateSelect.xml create mode 100644 src/core/classes/org/glizycms/template/views/components/SelectTemplate.php create mode 100644 src/core/classes/org/glizycms/template/views/components/TemplateColorEdit.php create mode 100644 src/core/classes/org/glizycms/template/views/components/TemplateEdit.php create mode 100644 src/core/classes/org/glizycms/userManager/fe/Module.php create mode 100644 src/core/classes/org/glizycms/userManager/fe/config/routing.xml create mode 100644 src/core/classes/org/glizycms/userManager/fe/controllers/login/Login.php create mode 100644 src/core/classes/org/glizycms/userManager/fe/controllers/login/Logout.php create mode 100644 src/core/classes/org/glizycms/userManager/fe/controllers/user/LostPassword.php create mode 100644 src/core/classes/org/glizycms/userManager/fe/controllers/user/Modify.php create mode 100644 src/core/classes/org/glizycms/userManager/fe/controllers/user/Registration.php create mode 100755 src/core/classes/org/glizycms/userManager/models/UserGroup.xml create mode 100755 src/core/classes/org/glizycms/userManager/views/UserManagerEdit.xml create mode 100644 src/core/classes/org/glizycms/views/TemplateModuleAdmin.xml create mode 100644 src/core/classes/org/glizycms/views/components/EditLanguage.php create mode 100644 src/core/classes/org/glizycms/views/components/FormButtonsPanel.php create mode 100644 src/core/classes/org/glizycms/views/components/FormEdit.php create mode 100644 src/core/classes/org/glizycms/views/components/FormEditWithAjaxSteps.php create mode 100644 src/core/classes/org/glizycms/views/components/GoogleAnalytics.php create mode 100644 src/core/classes/org/glizycms/views/components/LanguageNavigation.php create mode 100755 src/core/classes/org/glizycms/views/components/MvcPage.php create mode 100755 src/core/classes/org/glizycms/views/components/Page.php create mode 100644 src/core/classes/org/glizycms/views/components/PagePicker.php create mode 100644 src/core/classes/org/glizycms/views/components/SearchFilters.php create mode 100755 src/core/classes/org/glizycms/views/components/SelectPage.php create mode 100644 src/core/classes/org/glizycms/views/components/SelectPageType.php create mode 100644 src/core/classes/org/glizycms/views/components/SelectPageTypeNew.php create mode 100644 src/core/classes/org/glizycms/views/components/VisualSearch.php create mode 100644 src/core/composer.json create mode 100644 src/core/composer.lock create mode 100755 src/core/core.inc.php create mode 100755 src/core/libs/Cache_Lite/LICENSE create mode 100644 src/core/libs/Cache_Lite/Lite.php create mode 100644 src/core/libs/Cache_Lite/Lite/File.php create mode 100644 src/core/libs/Cache_Lite/Lite/Function.php create mode 100644 src/core/libs/Cache_Lite/Lite/NestedOutput.php create mode 100644 src/core/libs/Cache_Lite/Lite/Output.php create mode 100755 src/core/libs/DebugBar/Bridge/CacheCacheCollector.php create mode 100755 src/core/libs/DebugBar/Bridge/DoctrineCollector.php create mode 100755 src/core/libs/DebugBar/Bridge/MonologCollector.php create mode 100755 src/core/libs/DebugBar/Bridge/PropelCollector.php create mode 100755 src/core/libs/DebugBar/Bridge/SlimCollector.php create mode 100755 src/core/libs/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php create mode 100755 src/core/libs/DebugBar/Bridge/SwiftMailer/SwiftMailCollector.php create mode 100755 src/core/libs/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php create mode 100755 src/core/libs/DebugBar/Bridge/Twig/TraceableTwigTemplate.php create mode 100755 src/core/libs/DebugBar/Bridge/Twig/TwigCollector.php create mode 100755 src/core/libs/DebugBar/DataCollector/AggregatedCollector.php create mode 100755 src/core/libs/DebugBar/DataCollector/AssetProvider.php create mode 100755 src/core/libs/DebugBar/DataCollector/ConfigCollector.php create mode 100755 src/core/libs/DebugBar/DataCollector/DataCollector.php create mode 100755 src/core/libs/DebugBar/DataCollector/DataCollectorInterface.php create mode 100755 src/core/libs/DebugBar/DataCollector/ExceptionsCollector.php create mode 100755 src/core/libs/DebugBar/DataCollector/LocalizationCollector.php create mode 100755 src/core/libs/DebugBar/DataCollector/MemoryCollector.php create mode 100755 src/core/libs/DebugBar/DataCollector/MessagesAggregateInterface.php create mode 100755 src/core/libs/DebugBar/DataCollector/MessagesCollector.php create mode 100755 src/core/libs/DebugBar/DataCollector/PDO/PDOCollector.php create mode 100755 src/core/libs/DebugBar/DataCollector/PDO/TraceablePDO.php create mode 100755 src/core/libs/DebugBar/DataCollector/PDO/TraceablePDOStatement.php create mode 100755 src/core/libs/DebugBar/DataCollector/PDO/TracedStatement.php create mode 100755 src/core/libs/DebugBar/DataCollector/PhpInfoCollector.php create mode 100755 src/core/libs/DebugBar/DataCollector/Renderable.php create mode 100755 src/core/libs/DebugBar/DataCollector/RequestDataCollector.php create mode 100755 src/core/libs/DebugBar/DataCollector/TimeDataCollector.php create mode 100755 src/core/libs/DebugBar/DataFormatter/DataFormatter.php create mode 100755 src/core/libs/DebugBar/DataFormatter/DataFormatterInterface.php create mode 100755 src/core/libs/DebugBar/DebugBar.php create mode 100755 src/core/libs/DebugBar/DebugBarException.php create mode 100755 src/core/libs/DebugBar/HttpDriverInterface.php create mode 100755 src/core/libs/DebugBar/JavascriptRenderer.php create mode 100644 src/core/libs/DebugBar/LICENSE create mode 100755 src/core/libs/DebugBar/OpenHandler.php create mode 100755 src/core/libs/DebugBar/PhpHttpDriver.php create mode 100755 src/core/libs/DebugBar/RequestIdGenerator.php create mode 100755 src/core/libs/DebugBar/RequestIdGeneratorInterface.php create mode 100644 src/core/libs/DebugBar/Resources/.htaccess create mode 100755 src/core/libs/DebugBar/Resources/debugbar.css create mode 100755 src/core/libs/DebugBar/Resources/debugbar.js create mode 100755 src/core/libs/DebugBar/Resources/icons.png create mode 100755 src/core/libs/DebugBar/Resources/openhandler.css create mode 100755 src/core/libs/DebugBar/Resources/openhandler.js create mode 100755 src/core/libs/DebugBar/Resources/php-icon.png create mode 100755 src/core/libs/DebugBar/Resources/vendor/font-awesome/css/font-awesome.min.css create mode 100755 src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/FontAwesome.otf create mode 100755 src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.eot create mode 100755 src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.svg create mode 100755 src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.ttf create mode 100755 src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.woff create mode 100755 src/core/libs/DebugBar/Resources/vendor/highlightjs/highlight.pack.js create mode 100755 src/core/libs/DebugBar/Resources/vendor/highlightjs/styles/github.css create mode 100755 src/core/libs/DebugBar/Resources/vendor/jquery/dist/jquery.min.js create mode 100755 src/core/libs/DebugBar/Resources/widgets.css create mode 100755 src/core/libs/DebugBar/Resources/widgets.js create mode 100755 src/core/libs/DebugBar/Resources/widgets/mails/widget.css create mode 100755 src/core/libs/DebugBar/Resources/widgets/mails/widget.js create mode 100755 src/core/libs/DebugBar/Resources/widgets/sqlqueries/widget.css create mode 100755 src/core/libs/DebugBar/Resources/widgets/sqlqueries/widget.js create mode 100755 src/core/libs/DebugBar/Resources/widgets/templates/widget.css create mode 100755 src/core/libs/DebugBar/Resources/widgets/templates/widget.js create mode 100755 src/core/libs/DebugBar/StandardDebugBar.php create mode 100755 src/core/libs/DebugBar/Storage/FileStorage.php create mode 100755 src/core/libs/DebugBar/Storage/MemcachedStorage.php create mode 100755 src/core/libs/DebugBar/Storage/PdoStorage.php create mode 100755 src/core/libs/DebugBar/Storage/RedisStorage.php create mode 100755 src/core/libs/DebugBar/Storage/StorageInterface.php create mode 100755 src/core/libs/DebugBar/Storage/pdo_storage_schema.sql create mode 100755 src/core/libs/Diff/Diff.php create mode 100755 src/core/libs/Diff/Diff/Renderer/Abstract.php create mode 100755 src/core/libs/Diff/Diff/Renderer/Html/Array.php create mode 100755 src/core/libs/Diff/Diff/Renderer/Html/Inline.php create mode 100755 src/core/libs/Diff/Diff/Renderer/Html/SideBySide.php create mode 100755 src/core/libs/Diff/Diff/Renderer/Text/Context.php create mode 100755 src/core/libs/Diff/Diff/Renderer/Text/Unified.php create mode 100755 src/core/libs/Diff/Diff/SequenceMatcher.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/Annotation.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/Annotation/Attribute.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/Annotation/Attributes.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/Annotation/Required.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/Annotation/Target.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/AnnotationException.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/AnnotationReader.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/AnnotationRegistry.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/CachedReader.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/DocLexer.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/DocParser.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/FileCacheReader.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/IndexedReader.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/PhpParser.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/Reader.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/SimpleAnnotationReader.php create mode 100644 src/core/libs/Doctrine/Common/Annotations/TokenParser.php create mode 100644 src/core/libs/Doctrine/Common/Cache/ApcCache.php create mode 100644 src/core/libs/Doctrine/Common/Cache/ArrayCache.php create mode 100644 src/core/libs/Doctrine/Common/Cache/Cache.php create mode 100644 src/core/libs/Doctrine/Common/Cache/CacheProvider.php create mode 100644 src/core/libs/Doctrine/Common/Cache/FileCache.php create mode 100644 src/core/libs/Doctrine/Common/Cache/FilesystemCache.php create mode 100644 src/core/libs/Doctrine/Common/Cache/MemcacheCache.php create mode 100644 src/core/libs/Doctrine/Common/Cache/MemcachedCache.php create mode 100644 src/core/libs/Doctrine/Common/Cache/PhpFileCache.php create mode 100644 src/core/libs/Doctrine/Common/Cache/RedisCache.php create mode 100644 src/core/libs/Doctrine/Common/Cache/WinCacheCache.php create mode 100644 src/core/libs/Doctrine/Common/Cache/XcacheCache.php create mode 100644 src/core/libs/Doctrine/Common/Cache/ZendDataCache.php create mode 100644 src/core/libs/Doctrine/Common/ClassLoader.php create mode 100644 src/core/libs/Doctrine/Common/Collections/ArrayCollection.php create mode 100644 src/core/libs/Doctrine/Common/Collections/Collection.php create mode 100644 src/core/libs/Doctrine/Common/Collections/Criteria.php create mode 100644 src/core/libs/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php create mode 100644 src/core/libs/Doctrine/Common/Collections/Expr/Comparison.php create mode 100644 src/core/libs/Doctrine/Common/Collections/Expr/CompositeExpression.php create mode 100644 src/core/libs/Doctrine/Common/Collections/Expr/Expression.php create mode 100644 src/core/libs/Doctrine/Common/Collections/Expr/ExpressionVisitor.php create mode 100644 src/core/libs/Doctrine/Common/Collections/Expr/Value.php create mode 100644 src/core/libs/Doctrine/Common/Collections/ExpressionBuilder.php create mode 100644 src/core/libs/Doctrine/Common/Collections/Selectable.php create mode 100644 src/core/libs/Doctrine/Common/CommonException.php create mode 100644 src/core/libs/Doctrine/Common/Comparable.php create mode 100644 src/core/libs/Doctrine/Common/EventArgs.php create mode 100644 src/core/libs/Doctrine/Common/EventManager.php create mode 100644 src/core/libs/Doctrine/Common/EventSubscriber.php create mode 100644 src/core/libs/Doctrine/Common/Lexer.php create mode 100644 src/core/libs/Doctrine/Common/NotifyPropertyChanged.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/AbstractManagerRegistry.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/ConnectionRegistry.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Event/LifecycleEventArgs.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Event/LoadClassMetadataEventArgs.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Event/ManagerEventArgs.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Event/OnClearEventArgs.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Event/PreUpdateEventArgs.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/ManagerRegistry.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/ClassMetadata.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/ClassMetadataFactory.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/DefaultFileLocator.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/FileDriver.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/FileLocator.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/MappingDriver.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/PHPDriver.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/StaticPHPDriver.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/SymfonyFileLocator.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/MappingException.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/ReflectionService.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Mapping/StaticReflectionService.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/ObjectManager.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/ObjectManagerAware.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/ObjectRepository.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/PersistentObject.php create mode 100644 src/core/libs/Doctrine/Common/Persistence/Proxy.php create mode 100644 src/core/libs/Doctrine/Common/PropertyChangedListener.php create mode 100644 src/core/libs/Doctrine/Common/Reflection/ClassFinderInterface.php create mode 100644 src/core/libs/Doctrine/Common/Reflection/Psr0FindFile.php create mode 100644 src/core/libs/Doctrine/Common/Reflection/ReflectionProviderInterface.php create mode 100644 src/core/libs/Doctrine/Common/Reflection/StaticReflectionClass.php create mode 100644 src/core/libs/Doctrine/Common/Reflection/StaticReflectionMethod.php create mode 100644 src/core/libs/Doctrine/Common/Reflection/StaticReflectionParser.php create mode 100644 src/core/libs/Doctrine/Common/Reflection/StaticReflectionProperty.php create mode 100644 src/core/libs/Doctrine/Common/Util/ClassUtils.php create mode 100644 src/core/libs/Doctrine/Common/Util/Debug.php create mode 100644 src/core/libs/Doctrine/Common/Util/Inflector.php create mode 100644 src/core/libs/Doctrine/Common/Version.php create mode 100644 src/core/libs/Doctrine/DBAL/Cache/ArrayStatement.php create mode 100644 src/core/libs/Doctrine/DBAL/Cache/CacheException.php create mode 100644 src/core/libs/Doctrine/DBAL/Cache/QueryCacheProfile.php create mode 100644 src/core/libs/Doctrine/DBAL/Cache/ResultCacheStatement.php create mode 100644 src/core/libs/Doctrine/DBAL/Configuration.php create mode 100644 src/core/libs/Doctrine/DBAL/Connection.php create mode 100644 src/core/libs/Doctrine/DBAL/ConnectionException.php create mode 100644 src/core/libs/Doctrine/DBAL/Connections/MasterSlaveConnection.php create mode 100644 src/core/libs/Doctrine/DBAL/DBALException.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/Connection.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Exception.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/Mysqli/Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliException.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/OCI8/Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/PDOConnection.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/PDOIbm/Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/PDOMySql/Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/PDOOracle/Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/PDOPgSql/Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/PDOSqlite/Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/PDOStatement.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/ResultStatement.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/SQLSrv/Driver.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/SQLSrv/LastInsertId.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php create mode 100644 src/core/libs/Doctrine/DBAL/Driver/Statement.php create mode 100644 src/core/libs/Doctrine/DBAL/DriverManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/ConnectionEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/SchemaEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php create mode 100644 src/core/libs/Doctrine/DBAL/Events.php create mode 100644 src/core/libs/Doctrine/DBAL/Id/TableGenerator.php create mode 100644 src/core/libs/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php create mode 100644 src/core/libs/Doctrine/DBAL/LockMode.php create mode 100644 src/core/libs/Doctrine/DBAL/Logging/DebugStack.php create mode 100644 src/core/libs/Doctrine/DBAL/Logging/EchoSQLLogger.php create mode 100644 src/core/libs/Doctrine/DBAL/Logging/LoggerChain.php create mode 100644 src/core/libs/Doctrine/DBAL/Logging/SQLLogger.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/AbstractPlatform.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/DB2Platform.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/DrizzlePlatform.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/Keywords/KeywordList.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/Keywords/MsSQLKeywords.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/Keywords/MySQLKeywords.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/Keywords/OracleKeywords.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/Keywords/PostgreSQLKeywords.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/Keywords/SQLiteKeywords.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/MySqlPlatform.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/OraclePlatform.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/SQLAzurePlatform.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/SQLServer2005Platform.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/SQLServer2008Platform.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/SQLServerPlatform.php create mode 100644 src/core/libs/Doctrine/DBAL/Platforms/SqlitePlatform.php create mode 100644 src/core/libs/Doctrine/DBAL/Portability/Connection.php create mode 100644 src/core/libs/Doctrine/DBAL/Portability/Statement.php create mode 100644 src/core/libs/Doctrine/DBAL/Query/Expression/CompositeExpression.php create mode 100644 src/core/libs/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php create mode 100644 src/core/libs/Doctrine/DBAL/Query/QueryBuilder.php create mode 100644 src/core/libs/Doctrine/DBAL/Query/QueryException.php create mode 100644 src/core/libs/Doctrine/DBAL/README.markdown create mode 100644 src/core/libs/Doctrine/DBAL/SQLParserUtils.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/AbstractAsset.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/AbstractSchemaManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Column.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/ColumnDiff.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Comparator.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Constraint.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/DB2SchemaManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/DrizzleSchemaManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/ForeignKeyConstraint.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Index.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/MySqlSchemaManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/OracleSchemaManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/SQLServerSchemaManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Schema.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/SchemaConfig.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/SchemaDiff.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/SchemaException.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Sequence.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/SqliteSchemaManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Table.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/TableDiff.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/View.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Visitor/Graphviz.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php create mode 100644 src/core/libs/Doctrine/DBAL/Schema/Visitor/Visitor.php create mode 100644 src/core/libs/Doctrine/DBAL/Sharding/PoolingShardConnection.php create mode 100644 src/core/libs/Doctrine/DBAL/Sharding/PoolingShardManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php create mode 100644 src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php create mode 100644 src/core/libs/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php create mode 100644 src/core/libs/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php create mode 100644 src/core/libs/Doctrine/DBAL/Sharding/ShardManager.php create mode 100644 src/core/libs/Doctrine/DBAL/Sharding/ShardingException.php create mode 100644 src/core/libs/Doctrine/DBAL/Statement.php create mode 100644 src/core/libs/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php create mode 100644 src/core/libs/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php create mode 100644 src/core/libs/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php create mode 100644 src/core/libs/Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/ArrayType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/BigIntType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/BlobType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/BooleanType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/ConversionException.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/DateTimeType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/DateTimeTzType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/DateType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/DecimalType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/FloatType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/GuidType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/IntegerType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/JsonArrayType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/ObjectType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/SimpleArrayType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/SmallIntType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/StringType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/TextType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/TimeType.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/Type.php create mode 100644 src/core/libs/Doctrine/DBAL/Types/VarDateTimeType.php create mode 100644 src/core/libs/Doctrine/DBAL/Version.php create mode 100644 src/core/libs/PHPTAL5/COPYING create mode 100644 src/core/libs/PHPTAL5/PHPTAL.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/ConfigurationException.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Context.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/DefaultKeyword.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/Attr.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/CDATASection.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/Comment.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/Defs.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/DocumentBuilder.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/DocumentType.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/Element.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/Node.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/PHPTALDocumentBuilder.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/ProcessingInstruction.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/SaxXmlParser.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/Text.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/XmlDeclaration.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Dom/XmlnsState.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Exception.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/ExceptionHandler.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/FileSource.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/FileSourceResolver.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Filter.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/GetTextTranslator.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/IOException.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/InvalidVariableNameException.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Keywords.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/MacroMissingException.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Namespace.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Namespace/Builtin.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Namespace/I18N.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Namespace/METAL.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Namespace/PHPTAL.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Namespace/TAL.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/NamespaceAttribute.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeContent.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeReplace.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeSurround.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/NothingKeyword.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/ParserException.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Attributes.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Data.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Domain.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Name.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Source.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Target.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Translate.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/DefineMacro.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/DefineSlot.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/FillSlot.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/UseMacro.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Cache.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Debug.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Id.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Tales.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Attributes.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Comment.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Condition.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Content.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Define.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/OmitTag.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/OnError.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Repeat.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Replace.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/CodeWriter.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/State.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/TalesChainExecutor.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/TalesChainReader.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/TalesInternal.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Php/Transformer.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/PreFilter.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/PreFilter/Compress.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/PreFilter/Normalize.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/PreFilter/StripComments.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/RepeatController.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/RepeatControllerGroups.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Source.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/SourceResolver.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/StringSource.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Tales.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/TalesRegistry.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/TemplateException.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Tokenizer.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/TranslationService.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/Trigger.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/UnknownModifierException.php create mode 100644 src/core/libs/PHPTAL5/PHPTAL/VariableNotFoundException.php create mode 100755 src/core/libs/PHPTAL5/phptal_lint.php create mode 100755 src/core/libs/Psr/Log/AbstractLogger.php create mode 100755 src/core/libs/Psr/Log/InvalidArgumentException.php create mode 100755 src/core/libs/Psr/Log/LogLevel.php create mode 100755 src/core/libs/Psr/Log/LoggerAwareInterface.php create mode 100755 src/core/libs/Psr/Log/LoggerAwareTrait.php create mode 100755 src/core/libs/Psr/Log/LoggerInterface.php create mode 100755 src/core/libs/Psr/Log/LoggerTrait.php create mode 100755 src/core/libs/Psr/Log/NullLogger.php create mode 100755 src/core/libs/Psr/Log/Test/LoggerInterfaceTest.php create mode 100755 src/core/libs/Twig/Autoloader.php create mode 100755 src/core/libs/Twig/Compiler.php create mode 100755 src/core/libs/Twig/CompilerInterface.php create mode 100755 src/core/libs/Twig/Environment.php create mode 100755 src/core/libs/Twig/Error.php create mode 100755 src/core/libs/Twig/Error/Loader.php create mode 100755 src/core/libs/Twig/Error/Runtime.php create mode 100755 src/core/libs/Twig/Error/Syntax.php create mode 100755 src/core/libs/Twig/ExistsLoaderInterface.php create mode 100755 src/core/libs/Twig/ExpressionParser.php create mode 100755 src/core/libs/Twig/Extension.php create mode 100755 src/core/libs/Twig/Extension/Core.php create mode 100755 src/core/libs/Twig/Extension/Debug.php create mode 100755 src/core/libs/Twig/Extension/Escaper.php create mode 100755 src/core/libs/Twig/Extension/Optimizer.php create mode 100755 src/core/libs/Twig/Extension/Sandbox.php create mode 100755 src/core/libs/Twig/Extension/Staging.php create mode 100755 src/core/libs/Twig/Extension/StringLoader.php create mode 100755 src/core/libs/Twig/ExtensionInterface.php create mode 100755 src/core/libs/Twig/Filter.php create mode 100755 src/core/libs/Twig/Filter/Function.php create mode 100755 src/core/libs/Twig/Filter/Method.php create mode 100755 src/core/libs/Twig/Filter/Node.php create mode 100755 src/core/libs/Twig/FilterCallableInterface.php create mode 100755 src/core/libs/Twig/FilterInterface.php create mode 100755 src/core/libs/Twig/Function.php create mode 100755 src/core/libs/Twig/Function/Function.php create mode 100755 src/core/libs/Twig/Function/Method.php create mode 100755 src/core/libs/Twig/Function/Node.php create mode 100755 src/core/libs/Twig/FunctionCallableInterface.php create mode 100755 src/core/libs/Twig/FunctionInterface.php create mode 100755 src/core/libs/Twig/Lexer.php create mode 100755 src/core/libs/Twig/LexerInterface.php create mode 100755 src/core/libs/Twig/Loader/Array.php create mode 100755 src/core/libs/Twig/Loader/Chain.php create mode 100755 src/core/libs/Twig/Loader/Filesystem.php create mode 100755 src/core/libs/Twig/Loader/String.php create mode 100755 src/core/libs/Twig/LoaderInterface.php create mode 100755 src/core/libs/Twig/Markup.php create mode 100755 src/core/libs/Twig/Node.php create mode 100755 src/core/libs/Twig/Node/AutoEscape.php create mode 100755 src/core/libs/Twig/Node/Block.php create mode 100755 src/core/libs/Twig/Node/BlockReference.php create mode 100755 src/core/libs/Twig/Node/Body.php create mode 100755 src/core/libs/Twig/Node/Do.php create mode 100755 src/core/libs/Twig/Node/Embed.php create mode 100755 src/core/libs/Twig/Node/Expression.php create mode 100755 src/core/libs/Twig/Node/Expression/Array.php create mode 100755 src/core/libs/Twig/Node/Expression/AssignName.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Add.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/And.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/BitwiseAnd.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/BitwiseOr.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/BitwiseXor.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Concat.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Div.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/EndsWith.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Equal.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/FloorDiv.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Greater.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/GreaterEqual.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/In.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Less.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/LessEqual.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Matches.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Mod.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Mul.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/NotEqual.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/NotIn.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Or.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Power.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Range.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/StartsWith.php create mode 100755 src/core/libs/Twig/Node/Expression/Binary/Sub.php create mode 100755 src/core/libs/Twig/Node/Expression/BlockReference.php create mode 100755 src/core/libs/Twig/Node/Expression/Call.php create mode 100755 src/core/libs/Twig/Node/Expression/Conditional.php create mode 100755 src/core/libs/Twig/Node/Expression/Constant.php create mode 100755 src/core/libs/Twig/Node/Expression/ExtensionReference.php create mode 100755 src/core/libs/Twig/Node/Expression/Filter.php create mode 100755 src/core/libs/Twig/Node/Expression/Filter/Default.php create mode 100755 src/core/libs/Twig/Node/Expression/Function.php create mode 100755 src/core/libs/Twig/Node/Expression/GetAttr.php create mode 100755 src/core/libs/Twig/Node/Expression/MethodCall.php create mode 100755 src/core/libs/Twig/Node/Expression/Name.php create mode 100755 src/core/libs/Twig/Node/Expression/Parent.php create mode 100755 src/core/libs/Twig/Node/Expression/TempName.php create mode 100755 src/core/libs/Twig/Node/Expression/Test.php create mode 100755 src/core/libs/Twig/Node/Expression/Test/Constant.php create mode 100755 src/core/libs/Twig/Node/Expression/Test/Defined.php create mode 100755 src/core/libs/Twig/Node/Expression/Test/Divisibleby.php create mode 100755 src/core/libs/Twig/Node/Expression/Test/Even.php create mode 100755 src/core/libs/Twig/Node/Expression/Test/Null.php create mode 100755 src/core/libs/Twig/Node/Expression/Test/Odd.php create mode 100755 src/core/libs/Twig/Node/Expression/Test/Sameas.php create mode 100755 src/core/libs/Twig/Node/Expression/Unary.php create mode 100755 src/core/libs/Twig/Node/Expression/Unary/Neg.php create mode 100755 src/core/libs/Twig/Node/Expression/Unary/Not.php create mode 100755 src/core/libs/Twig/Node/Expression/Unary/Pos.php create mode 100755 src/core/libs/Twig/Node/Flush.php create mode 100755 src/core/libs/Twig/Node/For.php create mode 100755 src/core/libs/Twig/Node/ForLoop.php create mode 100755 src/core/libs/Twig/Node/If.php create mode 100755 src/core/libs/Twig/Node/Import.php create mode 100755 src/core/libs/Twig/Node/Include.php create mode 100755 src/core/libs/Twig/Node/Macro.php create mode 100755 src/core/libs/Twig/Node/Module.php create mode 100755 src/core/libs/Twig/Node/Print.php create mode 100755 src/core/libs/Twig/Node/Sandbox.php create mode 100755 src/core/libs/Twig/Node/SandboxedModule.php create mode 100755 src/core/libs/Twig/Node/SandboxedPrint.php create mode 100755 src/core/libs/Twig/Node/Set.php create mode 100755 src/core/libs/Twig/Node/SetTemp.php create mode 100755 src/core/libs/Twig/Node/Spaceless.php create mode 100755 src/core/libs/Twig/Node/Text.php create mode 100755 src/core/libs/Twig/NodeInterface.php create mode 100755 src/core/libs/Twig/NodeOutputInterface.php create mode 100755 src/core/libs/Twig/NodeTraverser.php create mode 100755 src/core/libs/Twig/NodeVisitor/Escaper.php create mode 100755 src/core/libs/Twig/NodeVisitor/Optimizer.php create mode 100755 src/core/libs/Twig/NodeVisitor/SafeAnalysis.php create mode 100755 src/core/libs/Twig/NodeVisitor/Sandbox.php create mode 100755 src/core/libs/Twig/NodeVisitorInterface.php create mode 100755 src/core/libs/Twig/Parser.php create mode 100755 src/core/libs/Twig/ParserInterface.php create mode 100755 src/core/libs/Twig/Sandbox/SecurityError.php create mode 100755 src/core/libs/Twig/Sandbox/SecurityPolicy.php create mode 100755 src/core/libs/Twig/Sandbox/SecurityPolicyInterface.php create mode 100755 src/core/libs/Twig/SimpleFilter.php create mode 100755 src/core/libs/Twig/SimpleFunction.php create mode 100755 src/core/libs/Twig/SimpleTest.php create mode 100755 src/core/libs/Twig/Template.php create mode 100755 src/core/libs/Twig/TemplateInterface.php create mode 100755 src/core/libs/Twig/Test.php create mode 100755 src/core/libs/Twig/Test/Function.php create mode 100755 src/core/libs/Twig/Test/IntegrationTestCase.php create mode 100755 src/core/libs/Twig/Test/Method.php create mode 100755 src/core/libs/Twig/Test/Node.php create mode 100755 src/core/libs/Twig/Test/NodeTestCase.php create mode 100755 src/core/libs/Twig/TestCallableInterface.php create mode 100755 src/core/libs/Twig/TestInterface.php create mode 100755 src/core/libs/Twig/Token.php create mode 100755 src/core/libs/Twig/TokenParser.php create mode 100755 src/core/libs/Twig/TokenParser/AutoEscape.php create mode 100755 src/core/libs/Twig/TokenParser/Block.php create mode 100755 src/core/libs/Twig/TokenParser/Do.php create mode 100755 src/core/libs/Twig/TokenParser/Embed.php create mode 100755 src/core/libs/Twig/TokenParser/Extends.php create mode 100755 src/core/libs/Twig/TokenParser/Filter.php create mode 100755 src/core/libs/Twig/TokenParser/Flush.php create mode 100755 src/core/libs/Twig/TokenParser/For.php create mode 100755 src/core/libs/Twig/TokenParser/From.php create mode 100755 src/core/libs/Twig/TokenParser/If.php create mode 100755 src/core/libs/Twig/TokenParser/Import.php create mode 100755 src/core/libs/Twig/TokenParser/Include.php create mode 100755 src/core/libs/Twig/TokenParser/Macro.php create mode 100755 src/core/libs/Twig/TokenParser/Sandbox.php create mode 100755 src/core/libs/Twig/TokenParser/Set.php create mode 100755 src/core/libs/Twig/TokenParser/Spaceless.php create mode 100755 src/core/libs/Twig/TokenParser/Use.php create mode 100755 src/core/libs/Twig/TokenParserBroker.php create mode 100755 src/core/libs/Twig/TokenParserBrokerInterface.php create mode 100755 src/core/libs/Twig/TokenParserInterface.php create mode 100755 src/core/libs/Twig/TokenStream.php create mode 100644 src/core/libs/Whoops/Exception/ErrorException.php create mode 100644 src/core/libs/Whoops/Exception/Frame.php create mode 100644 src/core/libs/Whoops/Exception/FrameCollection.php create mode 100644 src/core/libs/Whoops/Exception/Inspector.php create mode 100644 src/core/libs/Whoops/Handler/CallbackHandler.php create mode 100644 src/core/libs/Whoops/Handler/Handler.php create mode 100644 src/core/libs/Whoops/Handler/HandlerInterface.php create mode 100644 src/core/libs/Whoops/Handler/JsonResponseHandler.php create mode 100644 src/core/libs/Whoops/Handler/PrettyPageHandler.php create mode 100644 src/core/libs/Whoops/Handler/XmlResponseHandler.php create mode 100644 src/core/libs/Whoops/LICENSE.md create mode 100644 src/core/libs/Whoops/Provider/Phalcon/WhoopsServiceProvider.php create mode 100644 src/core/libs/Whoops/Provider/Silex/WhoopsServiceProvider.php create mode 100644 src/core/libs/Whoops/Provider/Zend/ExceptionStrategy.php create mode 100644 src/core/libs/Whoops/Provider/Zend/Module.php create mode 100644 src/core/libs/Whoops/Provider/Zend/RouteNotFoundStrategy.php create mode 100644 src/core/libs/Whoops/Provider/Zend/module.config.example.php create mode 100644 src/core/libs/Whoops/README.md create mode 100644 src/core/libs/Whoops/Resources/pretty-page.css create mode 100644 src/core/libs/Whoops/Resources/pretty-template.php create mode 100644 src/core/libs/Whoops/Run.php create mode 100755 src/core/libs/jsmin/jsmin.php create mode 100755 src/core/libs/lessphp/LICENSE create mode 100755 src/core/libs/lessphp/README.md create mode 100755 src/core/libs/lessphp/composer.json create mode 100755 src/core/libs/lessphp/lessc.inc.php create mode 100644 src/core/libs/phpUnsharpMask/phpUnsharpMask.php create mode 100755 src/core/libs/phpmailer/class.phpmailer.php create mode 100755 src/core/libs/phpmailer/class.smtp.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-br.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-ca.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-cz.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-de.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-dk.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-en.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-es.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-et.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-fi.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-fo.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-fr.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-hu.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-it.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-ja.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-nl.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-no.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-pl.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-ro.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-ru.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-se.php create mode 100755 src/core/libs/phpmailer/language/phpmailer.lang-tr.php create mode 100755 src/core/libs/sql-formatter/lib/SqlFormatter.php create mode 100755 src/core/pages/.htaccess create mode 100755 src/core/pages/admin_bootstrap.php create mode 100755 src/core/pages/ajaxadmin_bootstrap.php create mode 100755 src/core/pages/bootstrap.php create mode 100755 src/core/pages/errors/404.php create mode 100755 src/core/pages/errors/debug.php create mode 100755 src/core/pages/errors/general.php create mode 100755 src/core/pages/getImage.php create mode 100755 src/core/static/.htaccess create mode 100755 src/core/static/images/calendar.gif create mode 100755 src/core/static/images/close_button.gif create mode 100755 src/core/static/images/colorPicker.gif create mode 100755 src/core/static/images/icon_add.gif create mode 100644 src/core/static/images/icon_addThesaurus.gif create mode 100755 src/core/static/images/icon_add_off.gif create mode 100755 src/core/static/images/icon_checked.gif create mode 100755 src/core/static/images/icon_checked_off.gif create mode 100644 src/core/static/images/icon_delete.gif create mode 100755 src/core/static/images/icon_delete_off.gif create mode 100755 src/core/static/images/icon_document.gif create mode 100755 src/core/static/images/icon_down.gif create mode 100755 src/core/static/images/icon_down_off.gif create mode 100755 src/core/static/images/icon_download.gif create mode 100755 src/core/static/images/icon_download_off.gif create mode 100755 src/core/static/images/icon_edit.gif create mode 100755 src/core/static/images/icon_editDraft.gif create mode 100755 src/core/static/images/icon_editDraft_off.gif create mode 100755 src/core/static/images/icon_edit_off.gif create mode 100755 src/core/static/images/icon_folder.gif create mode 100755 src/core/static/images/icon_go.gif create mode 100755 src/core/static/images/icon_go_off.gif create mode 100755 src/core/static/images/icon_invisible.gif create mode 100755 src/core/static/images/icon_invisible_off.gif create mode 100755 src/core/static/images/icon_lock.gif create mode 100755 src/core/static/images/icon_lock_off.gif create mode 100644 src/core/static/images/icon_orderDown.gif create mode 100644 src/core/static/images/icon_orderDownBlack.gif create mode 100644 src/core/static/images/icon_orderUp.gif create mode 100644 src/core/static/images/icon_orderUpBlack.gif create mode 100755 src/core/static/images/icon_preview.gif create mode 100755 src/core/static/images/icon_preview_off.gif create mode 100755 src/core/static/images/icon_publish.gif create mode 100755 src/core/static/images/icon_publish_off.gif create mode 100755 src/core/static/images/icon_unchecked.gif create mode 100755 src/core/static/images/icon_unchecked_off.gif create mode 100755 src/core/static/images/icon_unpublish.gif create mode 100755 src/core/static/images/icon_unpublish_off.gif create mode 100755 src/core/static/images/icon_up.gif create mode 100755 src/core/static/images/icon_up_off.gif create mode 100755 src/core/static/images/icon_visible.gif create mode 100755 src/core/static/images/icon_visible_off.gif create mode 100644 src/core/static/images/mediaArchive.png create mode 100644 src/core/static/images/mediaAudio.png create mode 100644 src/core/static/images/mediaFlash.png create mode 100644 src/core/static/images/mediaImage.png create mode 100644 src/core/static/images/mediaOffice.png create mode 100644 src/core/static/images/mediaOther.png create mode 100644 src/core/static/images/mediaPdf.png create mode 100644 src/core/static/images/mediaVideo.png create mode 100644 src/core/static/images/noimage.jpg create mode 100755 src/core/static/images/picker.gif create mode 100755 src/core/static/images/preload.gif create mode 100755 src/core/static/images/slider_cursor.gif create mode 100644 src/core/static/js/Glizy.js create mode 100644 src/core/static/js/Glizy_pageContent.js create mode 100644 src/core/static/js/Glizy_pageFilters.js create mode 100644 src/core/static/js/Glizy_tiny_mce.js create mode 100755 src/core/static/js/dejavu/LICENSE create mode 100755 src/core/static/js/dejavu/README.md create mode 100755 src/core/static/js/dejavu/loose/dejavu.js create mode 100755 src/core/static/js/dejavu/loose/dejavu.min.js create mode 100755 src/core/static/js/dejavu/strict/dejavu.js create mode 100644 src/core/static/js/formWithAjaxSteps.js create mode 100644 src/core/static/js/jquery-simplemodal/jquery.simplemodal.1.4.1.min.js create mode 100755 src/core/static/js/jscalendar/ChangeLog.txt create mode 100755 src/core/static/js/jscalendar/README.txt create mode 100755 src/core/static/js/jscalendar/bugtest-hidden-selects.html create mode 100755 src/core/static/js/jscalendar/calendar-blue.css create mode 100755 src/core/static/js/jscalendar/calendar-blue2.css create mode 100755 src/core/static/js/jscalendar/calendar-brown.css create mode 100755 src/core/static/js/jscalendar/calendar-green.css create mode 100755 src/core/static/js/jscalendar/calendar-setup.js create mode 100755 src/core/static/js/jscalendar/calendar-setup_stripped.js create mode 100755 src/core/static/js/jscalendar/calendar-system.css create mode 100755 src/core/static/js/jscalendar/calendar-tas.css create mode 100755 src/core/static/js/jscalendar/calendar-win2k-1.css create mode 100755 src/core/static/js/jscalendar/calendar-win2k-2.css create mode 100755 src/core/static/js/jscalendar/calendar-win2k-cold-1.css create mode 100755 src/core/static/js/jscalendar/calendar-win2k-cold-2.css create mode 100755 src/core/static/js/jscalendar/calendar.js create mode 100755 src/core/static/js/jscalendar/calendar.php create mode 100755 src/core/static/js/jscalendar/calendar_stripped.js create mode 100755 src/core/static/js/jscalendar/img.gif create mode 100755 src/core/static/js/jscalendar/index.html create mode 100755 src/core/static/js/jscalendar/lang/calendar-af.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-br.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-ca.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-cs-win.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-da.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-de.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-du.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-el.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-en.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-es.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-fi.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-fr.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-hr-utf8.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-hr.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-hu.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-it.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-jp.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-ko-utf8.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-ko.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-lt-utf8.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-lt.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-nl.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-no.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-pl-utf8.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-pl.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-pt.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-ro.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-ru.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-si.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-sk.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-sp.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-sv.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-tr.js create mode 100755 src/core/static/js/jscalendar/lang/calendar-zh.js create mode 100755 src/core/static/js/jscalendar/menuarrow.gif create mode 100755 src/core/static/js/jscalendar/menuarrow2.gif create mode 100755 src/core/static/js/jscalendar/release-notes.html create mode 100755 src/core/static/js/jscalendar/simple-1.html create mode 100755 src/core/static/js/jscalendar/simple-2.html create mode 100755 src/core/static/js/jscalendar/simple-3.html create mode 100755 src/core/static/js/jscalendar/test-position.html create mode 100755 src/core/static/js/jscalendar/test.php create mode 100644 src/core/static/js/locale/de.js create mode 100644 src/core/static/js/locale/en.js create mode 100644 src/core/static/js/locale/fr.js create mode 100644 src/core/static/js/locale/it.js create mode 100644 src/core/static/js/progressBar/progressBar.css create mode 100644 src/core/static/js/progressBar/progressBar.js create mode 100755 src/core/static/js/tiny_mce/langs/de.js create mode 100755 src/core/static/js/tiny_mce/langs/en.js create mode 100755 src/core/static/js/tiny_mce/langs/fr.js create mode 100755 src/core/static/js/tiny_mce/langs/it.js create mode 100644 src/core/static/js/tiny_mce/license.txt create mode 100755 src/core/static/js/tiny_mce/plugins/GLZ_image/css/GLZ_image.css create mode 100755 src/core/static/js/tiny_mce/plugins/GLZ_image/editor_plugin.js create mode 100755 src/core/static/js/tiny_mce/plugins/GLZ_image/image.htm create mode 100755 src/core/static/js/tiny_mce/plugins/GLZ_image/images/sample.gif create mode 100644 src/core/static/js/tiny_mce/plugins/GLZ_image/jscripts/functions.js create mode 100755 src/core/static/js/tiny_mce/plugins/GLZ_image/langs/en.js create mode 100755 src/core/static/js/tiny_mce/plugins/GLZ_image/langs/it.js create mode 100644 src/core/static/js/tiny_mce/plugins/GLZ_link/css/GLZ_link.css create mode 100644 src/core/static/js/tiny_mce/plugins/GLZ_link/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/GLZ_link/jscripts/functions.js create mode 100644 src/core/static/js/tiny_mce/plugins/GLZ_link/langs/en.js create mode 100644 src/core/static/js/tiny_mce/plugins/GLZ_link/langs/it.js create mode 100644 src/core/static/js/tiny_mce/plugins/GLZ_link/link.htm create mode 100644 src/core/static/js/tiny_mce/plugins/advhr/css/advhr.css create mode 100644 src/core/static/js/tiny_mce/plugins/advhr/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/advhr/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/advhr/js/rule.js create mode 100755 src/core/static/js/tiny_mce/plugins/advhr/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/advhr/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/advhr/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/advhr/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/advhr/rule.htm create mode 100644 src/core/static/js/tiny_mce/plugins/advimage/css/advimage.css create mode 100644 src/core/static/js/tiny_mce/plugins/advimage/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/advimage/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/advimage/image.htm create mode 100644 src/core/static/js/tiny_mce/plugins/advimage/img/sample.gif create mode 100644 src/core/static/js/tiny_mce/plugins/advimage/js/image.js create mode 100755 src/core/static/js/tiny_mce/plugins/advimage/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/advimage/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/advimage/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/advimage/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/advlink/css/advlink.css create mode 100644 src/core/static/js/tiny_mce/plugins/advlink/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/advlink/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/advlink/js/advlink.js create mode 100755 src/core/static/js/tiny_mce/plugins/advlink/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/advlink/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/advlink/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/advlink/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/advlink/link.htm create mode 100644 src/core/static/js/tiny_mce/plugins/advlist/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/advlist/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/autolink/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/autolink/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/autoresize/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/autoresize/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/autosave/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/autosave/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/autosave/langs/en.js create mode 100644 src/core/static/js/tiny_mce/plugins/bbcode/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/bbcode/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/contextmenu/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/contextmenu/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/directionality/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/directionality/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/emotions.htm create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-cool.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-cry.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-embarassed.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-frown.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-innocent.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-kiss.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-laughing.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-sealed.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-smile.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-surprised.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-undecided.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-wink.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/img/smiley-yell.gif create mode 100644 src/core/static/js/tiny_mce/plugins/emotions/js/emotions.js create mode 100755 src/core/static/js/tiny_mce/plugins/emotions/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/emotions/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/emotions/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/emotions/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/example/dialog.htm create mode 100644 src/core/static/js/tiny_mce/plugins/example/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/example/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/example/img/example.gif create mode 100644 src/core/static/js/tiny_mce/plugins/example/js/dialog.js create mode 100644 src/core/static/js/tiny_mce/plugins/example/langs/en.js create mode 100644 src/core/static/js/tiny_mce/plugins/example/langs/en_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/example_dependency/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/example_dependency/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/fullpage/css/fullpage.css create mode 100644 src/core/static/js/tiny_mce/plugins/fullpage/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/fullpage/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/fullpage/fullpage.htm create mode 100644 src/core/static/js/tiny_mce/plugins/fullpage/js/fullpage.js create mode 100755 src/core/static/js/tiny_mce/plugins/fullpage/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/fullpage/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/fullpage/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/fullpage/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/fullscreen/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/fullscreen/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/fullscreen/fullscreen.htm create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/css/styles.css create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/dialog.html create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/editor_plugin.js create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/images/bg/content.png create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/images/formula.png create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/images/ico/ico.png create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/images/plugin.gif create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/images/risultato.png create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/img/example.gif create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/js/dialog.js create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/js/jquery-textrange.js create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/js/mathmap.js create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/js/underscore-min.js create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/js/undo-manager.js create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/js/vendor/jquery-1.8.2.min.js create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/js/vendor/modernizr-2.6.2.min.js create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/langs/en.js create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/langs/en_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/langs/it.js create mode 100644 src/core/static/js/tiny_mce/plugins/fxeditor/langs/it_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/less/global.less create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/h5bp.less create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/mixins.less create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/normalize.less create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/wp-default.less create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/less/structure.less create mode 100755 src/core/static/js/tiny_mce/plugins/fxeditor/less/styles.less create mode 100644 src/core/static/js/tiny_mce/plugins/iespell/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/iespell/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/inlinepopups/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/inlinepopups/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif create mode 100644 src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif create mode 100644 src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif create mode 100644 src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif create mode 100644 src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif create mode 100644 src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif create mode 100644 src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif create mode 100644 src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css create mode 100644 src/core/static/js/tiny_mce/plugins/inlinepopups/template.htm create mode 100644 src/core/static/js/tiny_mce/plugins/insertdatetime/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/insertdatetime/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/layer/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/layer/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/legacyoutput/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/legacyoutput/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/lists/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/lists/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/media/css/media.css create mode 100644 src/core/static/js/tiny_mce/plugins/media/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/media/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/media/js/embed.js create mode 100644 src/core/static/js/tiny_mce/plugins/media/js/media.js create mode 100755 src/core/static/js/tiny_mce/plugins/media/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/media/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/media/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/media/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/media/media.htm create mode 100644 src/core/static/js/tiny_mce/plugins/media/moxieplayer.swf create mode 100644 src/core/static/js/tiny_mce/plugins/nonbreaking/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/noneditable/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/noneditable/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/pagebreak/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/pagebreak/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/paste/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/paste/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/paste/js/pastetext.js create mode 100644 src/core/static/js/tiny_mce/plugins/paste/js/pasteword.js create mode 100755 src/core/static/js/tiny_mce/plugins/paste/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/paste/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/paste/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/paste/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/paste/pastetext.htm create mode 100644 src/core/static/js/tiny_mce/plugins/paste/pasteword.htm create mode 100644 src/core/static/js/tiny_mce/plugins/preview/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/preview/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/preview/example.html create mode 100644 src/core/static/js/tiny_mce/plugins/preview/jscripts/embed.js create mode 100644 src/core/static/js/tiny_mce/plugins/preview/preview.html create mode 100644 src/core/static/js/tiny_mce/plugins/print/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/print/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/save/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/save/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/searchreplace/css/searchreplace.css create mode 100644 src/core/static/js/tiny_mce/plugins/searchreplace/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/searchreplace/js/searchreplace.js create mode 100755 src/core/static/js/tiny_mce/plugins/searchreplace/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/searchreplace/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/searchreplace/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/searchreplace/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/searchreplace/searchreplace.htm create mode 100644 src/core/static/js/tiny_mce/plugins/spellchecker/css/content.css create mode 100644 src/core/static/js/tiny_mce/plugins/spellchecker/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/spellchecker/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/spellchecker/img/wline.gif create mode 100644 src/core/static/js/tiny_mce/plugins/style/css/props.css create mode 100644 src/core/static/js/tiny_mce/plugins/style/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/style/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/style/js/props.js create mode 100755 src/core/static/js/tiny_mce/plugins/style/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/style/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/style/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/style/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/style/props.htm create mode 100644 src/core/static/js/tiny_mce/plugins/tabfocus/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/tabfocus/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/table/cell.htm create mode 100644 src/core/static/js/tiny_mce/plugins/table/css/cell.css create mode 100644 src/core/static/js/tiny_mce/plugins/table/css/row.css create mode 100644 src/core/static/js/tiny_mce/plugins/table/css/table.css create mode 100644 src/core/static/js/tiny_mce/plugins/table/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/table/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/table/js/cell.js create mode 100644 src/core/static/js/tiny_mce/plugins/table/js/merge_cells.js create mode 100644 src/core/static/js/tiny_mce/plugins/table/js/row.js create mode 100644 src/core/static/js/tiny_mce/plugins/table/js/table.js create mode 100755 src/core/static/js/tiny_mce/plugins/table/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/table/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/table/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/table/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/table/merge_cells.htm create mode 100644 src/core/static/js/tiny_mce/plugins/table/row.htm create mode 100644 src/core/static/js/tiny_mce/plugins/table/table.htm create mode 100644 src/core/static/js/tiny_mce/plugins/template/blank.htm create mode 100644 src/core/static/js/tiny_mce/plugins/template/css/template.css create mode 100644 src/core/static/js/tiny_mce/plugins/template/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/template/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/template/js/template.js create mode 100755 src/core/static/js/tiny_mce/plugins/template/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/template/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/template/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/template/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/plugins/template/template.htm create mode 100644 src/core/static/js/tiny_mce/plugins/visualchars/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/visualchars/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/wordcount/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/wordcount/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/abbr.htm create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/acronym.htm create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/attributes.htm create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/cite.htm create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/css/attributes.css create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/css/popup.css create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/del.htm create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/editor_plugin.js create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/ins.htm create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/abbr.js create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/acronym.js create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/attributes.js create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/cite.js create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/del.js create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/element_common.js create mode 100644 src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/ins.js create mode 100755 src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/themes/advanced/about.htm create mode 100644 src/core/static/js/tiny_mce/themes/advanced/anchor.htm create mode 100644 src/core/static/js/tiny_mce/themes/advanced/charmap.htm create mode 100644 src/core/static/js/tiny_mce/themes/advanced/color_picker.htm create mode 100644 src/core/static/js/tiny_mce/themes/advanced/editor_template.js create mode 100644 src/core/static/js/tiny_mce/themes/advanced/editor_template_src.js create mode 100644 src/core/static/js/tiny_mce/themes/advanced/image.htm create mode 100644 src/core/static/js/tiny_mce/themes/advanced/img/colorpicker.jpg create mode 100644 src/core/static/js/tiny_mce/themes/advanced/img/flash.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/img/icons.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/img/iframe.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/img/pagebreak.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/img/quicktime.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/img/realmedia.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/img/shockwave.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/img/trans.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/img/video.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/img/windowsmedia.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/js/about.js create mode 100644 src/core/static/js/tiny_mce/themes/advanced/js/anchor.js create mode 100644 src/core/static/js/tiny_mce/themes/advanced/js/charmap.js create mode 100644 src/core/static/js/tiny_mce/themes/advanced/js/color_picker.js create mode 100644 src/core/static/js/tiny_mce/themes/advanced/js/image.js create mode 100644 src/core/static/js/tiny_mce/themes/advanced/js/link.js create mode 100644 src/core/static/js/tiny_mce/themes/advanced/js/source_editor.js create mode 100755 src/core/static/js/tiny_mce/themes/advanced/langs/de.js create mode 100755 src/core/static/js/tiny_mce/themes/advanced/langs/de_dlg.js create mode 100755 src/core/static/js/tiny_mce/themes/advanced/langs/en.js create mode 100755 src/core/static/js/tiny_mce/themes/advanced/langs/en_dlg.js create mode 100755 src/core/static/js/tiny_mce/themes/advanced/langs/fr.js create mode 100755 src/core/static/js/tiny_mce/themes/advanced/langs/fr_dlg.js create mode 100755 src/core/static/js/tiny_mce/themes/advanced/langs/it.js create mode 100755 src/core/static/js/tiny_mce/themes/advanced/langs/it_dlg.js create mode 100644 src/core/static/js/tiny_mce/themes/advanced/link.htm create mode 100644 src/core/static/js/tiny_mce/themes/advanced/shortcuts.htm create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/default/content.css create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/default/dialog.css create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/default/img/buttons.png create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/default/img/items.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/default/img/menu_check.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/default/img/progress.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/default/img/tabs.gif create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/default/ui.css create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/content.css create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/dialog.css create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/ui.css create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/content.css create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/dialog.css create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui.css create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui_black.css create mode 100644 src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css create mode 100644 src/core/static/js/tiny_mce/themes/advanced/source_editor.htm create mode 100644 src/core/static/js/tiny_mce/themes/simple/editor_template.js create mode 100644 src/core/static/js/tiny_mce/themes/simple/editor_template_src.js create mode 100644 src/core/static/js/tiny_mce/themes/simple/img/icons.gif create mode 100755 src/core/static/js/tiny_mce/themes/simple/langs/de.js create mode 100755 src/core/static/js/tiny_mce/themes/simple/langs/en.js create mode 100755 src/core/static/js/tiny_mce/themes/simple/langs/fr.js create mode 100755 src/core/static/js/tiny_mce/themes/simple/langs/it.js create mode 100644 src/core/static/js/tiny_mce/themes/simple/skins/default/content.css create mode 100644 src/core/static/js/tiny_mce/themes/simple/skins/default/ui.css create mode 100644 src/core/static/js/tiny_mce/themes/simple/skins/o2k7/content.css create mode 100644 src/core/static/js/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png create mode 100644 src/core/static/js/tiny_mce/themes/simple/skins/o2k7/ui.css create mode 100644 src/core/static/js/tiny_mce/tiny_mce.js create mode 100644 src/core/static/js/tiny_mce/tiny_mce_popup.js create mode 100644 src/core/static/js/tiny_mce/tiny_mce_src.js create mode 100644 src/core/static/js/tiny_mce/utils/editable_selects.js create mode 100644 src/core/static/js/tiny_mce/utils/form_utils.js create mode 100644 src/core/static/js/tiny_mce/utils/mctabs.js create mode 100644 src/core/static/js/tiny_mce/utils/validate.js create mode 100644 src/export/.gitkeep create mode 100644 src/getFile.php create mode 100644 src/getImage.php create mode 100644 src/index.php create mode 100644 src/static/OpenSeadragon/OpenSeadragon.debug.js create mode 100644 src/static/OpenSeadragon/OpenSeadragon.js create mode 100644 src/static/OpenSeadragon/images/fullpage_grouphover.png create mode 100644 src/static/OpenSeadragon/images/fullpage_hover.png create mode 100644 src/static/OpenSeadragon/images/fullpage_pressed.png create mode 100644 src/static/OpenSeadragon/images/fullpage_rest.png create mode 100644 src/static/OpenSeadragon/images/home_grouphover.png create mode 100644 src/static/OpenSeadragon/images/home_hover.png create mode 100644 src/static/OpenSeadragon/images/home_pressed.png create mode 100644 src/static/OpenSeadragon/images/home_rest.png create mode 100644 src/static/OpenSeadragon/images/zoomin_grouphover.png create mode 100644 src/static/OpenSeadragon/images/zoomin_hover.png create mode 100644 src/static/OpenSeadragon/images/zoomin_pressed.png create mode 100644 src/static/OpenSeadragon/images/zoomin_rest.png create mode 100644 src/static/OpenSeadragon/images/zoomout_grouphover.png create mode 100644 src/static/OpenSeadragon/images/zoomout_hover.png create mode 100644 src/static/OpenSeadragon/images/zoomout_pressed.png create mode 100644 src/static/OpenSeadragon/images/zoomout_rest.png create mode 100644 src/static/dagre-d3/d3.v3.js create mode 100644 src/static/dagre-d3/d3.v3.min.js create mode 100644 src/static/dagre-d3/dagre-d3.js create mode 100644 src/static/dagre-d3/dagre-d3.min.js create mode 100644 src/static/dagre-d3/graphlib-dot.min.js create mode 100644 src/static/galleria/LICENSE create mode 100644 src/static/galleria/galleria-1.4.2.js create mode 100644 src/static/galleria/galleria-1.4.2.min.js create mode 100644 src/static/galleria/plugins/flickr/flickr-demo.html create mode 100755 src/static/galleria/plugins/flickr/flickr-loader.gif create mode 100644 src/static/galleria/plugins/flickr/galleria.flickr.js create mode 100644 src/static/galleria/plugins/flickr/galleria.flickr.min.js create mode 100644 src/static/galleria/plugins/flickr/loader.gif create mode 100644 src/static/galleria/plugins/history/galleria.history.js create mode 100644 src/static/galleria/plugins/history/galleria.history.min.js create mode 100644 src/static/galleria/plugins/history/history-demo.html create mode 100644 src/static/galleria/plugins/picasa/galleria.picasa.js create mode 100644 src/static/galleria/plugins/picasa/galleria.picasa.min.js create mode 100644 src/static/galleria/plugins/picasa/loader.gif create mode 100644 src/static/galleria/plugins/picasa/picasa-demo.html create mode 100644 src/static/galleria/themes/classic/classic-demo.html create mode 100644 src/static/galleria/themes/classic/classic-loader.gif create mode 100644 src/static/galleria/themes/classic/classic-map.png create mode 100644 src/static/galleria/themes/classic/galleria.classic.css create mode 100644 src/static/galleria/themes/classic/galleria.classic.js create mode 100644 src/static/galleria/themes/classic/galleria.classic.min.js create mode 100644 src/static/galleria/themes/movio/css/bg-thumb.png create mode 100644 src/static/galleria/themes/movio/css/controller-left-hover.png create mode 100644 src/static/galleria/themes/movio/css/controller-left.png create mode 100644 src/static/galleria/themes/movio/css/controller-right-hover.png create mode 100644 src/static/galleria/themes/movio/css/controller-right.png create mode 100644 src/static/galleria/themes/movio/css/loader.gif create mode 100644 src/static/galleria/themes/movio/css/loader_black.gif create mode 100644 src/static/galleria/themes/movio/css/loader_white.gif create mode 100644 src/static/galleria/themes/movio/css/sprite.png create mode 100644 src/static/galleria/themes/movio/css/style.css create mode 100644 src/static/galleria/themes/movio/galleria.gallery.js create mode 100644 src/static/galleria/themes/movio/galleria.pageflip.js create mode 100644 src/static/galleria/themes/movio/galleria.slider.js create mode 100644 src/static/galleria/themes/movio/galleria.slideshow.js create mode 100755 src/static/galleria/themes/movio/less/gallery.less create mode 100755 src/static/galleria/themes/movio/less/pageflip.less create mode 100755 src/static/galleria/themes/movio/less/slider.less create mode 100755 src/static/galleria/themes/movio/less/slideshow.less create mode 100755 src/static/galleria/themes/movio/less/style.less create mode 100644 src/static/handlebars/handlebars-1.0.rc.1.js create mode 100755 src/static/jquery/bootstrap-editable-1.3.0/CHANGELOG.txt create mode 100755 src/static/jquery/bootstrap-editable-1.3.0/LICENSE-MIT create mode 100755 src/static/jquery/bootstrap-editable-1.3.0/README.md create mode 100755 src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/css/bootstrap-editable.css create mode 100755 src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/css/img/loading.gif create mode 100755 src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable-inline.js create mode 100755 src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable-inline.min.js create mode 100755 src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable.js create mode 100755 src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable.min.js create mode 100755 src/static/jquery/bootstrap-editable-1.3.0/inputs-ext/address/address.css create mode 100755 src/static/jquery/bootstrap-editable-1.3.0/inputs-ext/address/address.js create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/CHANGELOG.txt create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/LICENSE-MIT create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/README.md create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/css/bootstrap-editable.css create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/img/clear.png create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/img/loading.gif create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/js/bootstrap-editable.js create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/js/bootstrap-editable.min.js create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/address/address.css create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/address/address.js create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/lib/typeahead.js create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/lib/typeahead.js-bootstrap.css create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/typeaheadjs.js create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.css create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.js create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.min.js create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysihtml5-0.3.0.js create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysihtml5-0.3.0.min.js create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysiwyg-color.css create mode 100755 src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/wysihtml5.js create mode 100755 src/static/jquery/colorbox/README.md create mode 100644 src/static/jquery/colorbox/colorbox.css create mode 100644 src/static/jquery/colorbox/glizy/colorbox.css create mode 100755 src/static/jquery/colorbox/glizy/images/controls.png create mode 100755 src/static/jquery/colorbox/glizy/images/loading.gif create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-ar.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-bg.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-ca.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-cs.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-da.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-de.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-es.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-et.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-fa.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-fi.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-fr.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-gl.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-he.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-hr.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-hu.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-id.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-it.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-ja.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-kr.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-lv.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-nl.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-no.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-pl.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-pt-br.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-ro.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-ru.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-si.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-sk.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-sr.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-sv.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-tr.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-uk.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-zh-CN.js create mode 100755 src/static/jquery/colorbox/i18n/jquery.colorbox-zh-TW.js create mode 100644 src/static/jquery/colorbox/images/border.png create mode 100644 src/static/jquery/colorbox/images/controls.png create mode 100644 src/static/jquery/colorbox/images/ie6/borderBottomCenter.png create mode 100644 src/static/jquery/colorbox/images/ie6/borderBottomLeft.png create mode 100644 src/static/jquery/colorbox/images/ie6/borderBottomRight.png create mode 100644 src/static/jquery/colorbox/images/ie6/borderMiddleLeft.png create mode 100644 src/static/jquery/colorbox/images/ie6/borderMiddleRight.png create mode 100644 src/static/jquery/colorbox/images/ie6/borderTopCenter.png create mode 100644 src/static/jquery/colorbox/images/ie6/borderTopLeft.png create mode 100644 src/static/jquery/colorbox/images/ie6/borderTopRight.png create mode 100644 src/static/jquery/colorbox/images/loading.gif create mode 100644 src/static/jquery/colorbox/images/loading_background.png create mode 100644 src/static/jquery/colorbox/images/overlay.png create mode 100755 src/static/jquery/colorbox/jquery.colorbox-min.js create mode 100755 src/static/jquery/colorbox/jquery.colorbox.js create mode 100644 src/static/jquery/datatables/media/css/demo_page.css create mode 100644 src/static/jquery/datatables/media/css/demo_table.css create mode 100644 src/static/jquery/datatables/media/css/demo_table_jui.css create mode 100644 src/static/jquery/datatables/media/css/jquery.dataTables.css create mode 100644 src/static/jquery/datatables/media/css/jquery.dataTables_themeroller.css create mode 100644 src/static/jquery/datatables/media/images/Sorting icons.psd create mode 100644 src/static/jquery/datatables/media/images/back_disabled.png create mode 100644 src/static/jquery/datatables/media/images/back_enabled.png create mode 100644 src/static/jquery/datatables/media/images/back_enabled_hover.png create mode 100644 src/static/jquery/datatables/media/images/favicon.ico create mode 100644 src/static/jquery/datatables/media/images/forward_disabled.png create mode 100644 src/static/jquery/datatables/media/images/forward_enabled.png create mode 100644 src/static/jquery/datatables/media/images/forward_enabled_hover.png create mode 100644 src/static/jquery/datatables/media/images/sort_asc.png create mode 100644 src/static/jquery/datatables/media/images/sort_asc_disabled.png create mode 100644 src/static/jquery/datatables/media/images/sort_both.png create mode 100644 src/static/jquery/datatables/media/images/sort_desc.png create mode 100644 src/static/jquery/datatables/media/images/sort_desc_disabled.png create mode 100644 src/static/jquery/datatables/media/js/jquery.dataTables.bootstrap.js create mode 100644 src/static/jquery/datatables/media/js/jquery.dataTables.js create mode 100644 src/static/jquery/datatables/media/js/jquery.dataTables.min.js create mode 100644 src/static/jquery/datatables/media/js/jquery.js create mode 100644 src/static/jquery/jquery-1.8.3.min.js create mode 100755 src/static/jquery/jquery-jstree/jquery.cookie.js create mode 100755 src/static/jquery/jquery-jstree/jquery.jstree.js create mode 100755 src/static/jquery/jquery-jstree/themes/apple/bg.jpg create mode 100755 src/static/jquery/jquery-jstree/themes/apple/d.png create mode 100755 src/static/jquery/jquery-jstree/themes/apple/dot_for_ie.gif create mode 100755 src/static/jquery/jquery-jstree/themes/apple/style.css create mode 100755 src/static/jquery/jquery-jstree/themes/apple/throbber.gif create mode 100755 src/static/jquery/jquery-jstree/themes/classic/d.gif create mode 100755 src/static/jquery/jquery-jstree/themes/classic/d.png create mode 100755 src/static/jquery/jquery-jstree/themes/classic/dot_for_ie.gif create mode 100755 src/static/jquery/jquery-jstree/themes/classic/style.css create mode 100755 src/static/jquery/jquery-jstree/themes/classic/throbber.gif create mode 100755 src/static/jquery/jquery-jstree/themes/default-rtl/d.gif create mode 100755 src/static/jquery/jquery-jstree/themes/default-rtl/d.png create mode 100755 src/static/jquery/jquery-jstree/themes/default-rtl/dots.gif create mode 100755 src/static/jquery/jquery-jstree/themes/default-rtl/style.css create mode 100755 src/static/jquery/jquery-jstree/themes/default-rtl/throbber.gif create mode 100755 src/static/jquery/jquery-jstree/themes/default/d.gif create mode 100755 src/static/jquery/jquery-jstree/themes/default/d.png create mode 100755 src/static/jquery/jquery-jstree/themes/default/style.css create mode 100755 src/static/jquery/jquery-jstree/themes/default/throbber.gif create mode 100755 src/static/jquery/jquery-transform/README.md create mode 100755 src/static/jquery/jquery-transform/jquery.transform2d.js create mode 100755 src/static/jquery/jquery-transform/jquery.transform3d.js create mode 100755 src/static/jquery/jquery-ui/jquery-ui-1.10.4.custom.min.js create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_flat_0_aaaaaa_40x100.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_55_fbf9ee_1x400.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_65_ffffff_1x400.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_75_dadada_1x400.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_75_e6e6e6_1x400.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_75_ffffff_1x400.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_inset-soft_95_fef1ec_1x100.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_222222_256x240.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_2e83ff_256x240.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_454545_256x240.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_888888_256x240.png create mode 100755 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_cd0a0a_256x240.png create mode 100644 src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_f6cf3b_256x240.png create mode 100644 src/static/jquery/jquery-ui/jquery-ui-bootstrap/jquery-ui-1.10.0.custom.css create mode 100644 src/static/jquery/jquery-ui/jquery-ui-bootstrap/jquery.ui.1.10.0.ie.css create mode 100755 src/static/jquery/jquery.qtip/jquery.qtip.min.css create mode 100755 src/static/jquery/jquery.qtip/jquery.qtip.min.js create mode 100644 src/static/jquery/jquery.validationEngine/jquery.validationEngine-da.js create mode 100644 src/static/jquery/jquery.validationEngine/jquery.validationEngine-de.js create mode 100644 src/static/jquery/jquery.validationEngine/jquery.validationEngine-en.js create mode 100644 src/static/jquery/jquery.validationEngine/jquery.validationEngine-es.js create mode 100644 src/static/jquery/jquery.validationEngine/jquery.validationEngine-fr.js create mode 100644 src/static/jquery/jquery.validationEngine/jquery.validationEngine-it.js create mode 100644 src/static/jquery/jquery.validationEngine/jquery.validationEngine-ja.js create mode 100644 src/static/jquery/jquery.validationEngine/jquery.validationEngine-nl.js create mode 100644 src/static/jquery/jquery.validationEngine/jquery.validationEngine-pt.js create mode 100644 src/static/jquery/jquery.validationEngine/jquery.validationEngine-ro.js create mode 100644 src/static/jquery/jquery.validationEngine/jquery.validationEngine-ru.js create mode 100755 src/static/jquery/jquery.validationEngine/jquery.validationEngine.js create mode 100755 src/static/jquery/jquery.validationEngine/validationEngine.jquery.css create mode 100755 src/static/jquery/select2-3.4.6/LICENSE create mode 100755 src/static/jquery/select2-3.4.6/README.md create mode 100755 src/static/jquery/select2-3.4.6/bower.json create mode 100755 src/static/jquery/select2-3.4.6/component.json create mode 100755 src/static/jquery/select2-3.4.6/composer.json create mode 100755 src/static/jquery/select2-3.4.6/package.json create mode 100755 src/static/jquery/select2-3.4.6/release.sh create mode 100755 src/static/jquery/select2-3.4.6/select2-bootstrap.css create mode 100755 src/static/jquery/select2-3.4.6/select2-spinner.gif create mode 100755 src/static/jquery/select2-3.4.6/select2.css create mode 100755 src/static/jquery/select2-3.4.6/select2.jquery.json create mode 100755 src/static/jquery/select2-3.4.6/select2.js create mode 100755 src/static/jquery/select2-3.4.6/select2.min.js create mode 100755 src/static/jquery/select2-3.4.6/select2.png create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_ar.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_bg.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_ca.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_cs.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_da.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_de.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_el.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_en.js.template create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_es.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_et.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_eu.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_fa.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_fi.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_fr.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_gl.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_he.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_hr.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_hu.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_id.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_is.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_it.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_ja.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_ka.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_ko.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_lt.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_lv.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_mk.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_ms.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_nl.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_no.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_pl.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_pt-BR.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_pt-PT.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_ro.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_rs.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_ru.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_sk.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_sv.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_th.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_tr.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_uk.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_vi.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_zh-CN.js create mode 100755 src/static/jquery/select2-3.4.6/select2_locale_zh-TW.js create mode 100755 src/static/jquery/select2-3.4.6/select2x2.png create mode 100755 src/static/jquery/visualsearch-0.5.0/backbone-1.1.0.js create mode 100755 src/static/jquery/visualsearch-0.5.0/visualsearch-datauri.css create mode 100755 src/static/jquery/visualsearch-0.5.0/visualsearch.css create mode 100755 src/static/jquery/visualsearch-0.5.0/visualsearch.js create mode 100755 src/static/js/slick/ajax-loader.gif create mode 100755 src/static/js/slick/config.rb create mode 100755 src/static/js/slick/fonts/slick.eot create mode 100755 src/static/js/slick/fonts/slick.svg create mode 100755 src/static/js/slick/fonts/slick.ttf create mode 100755 src/static/js/slick/fonts/slick.woff create mode 100755 src/static/js/slick/slick-script.js create mode 100755 src/static/js/slick/slick.css create mode 100755 src/static/js/slick/slick.js create mode 100755 src/static/js/slick/slick.min.js create mode 100755 src/static/js/slick/slick.scss create mode 100755 src/static/mediaelement/background.png create mode 100755 src/static/mediaelement/bigplay.png create mode 100755 src/static/mediaelement/bigplay.svg create mode 100755 src/static/mediaelement/controls-ted.png create mode 100755 src/static/mediaelement/controls-wmp-bg.png create mode 100755 src/static/mediaelement/controls-wmp.png create mode 100755 src/static/mediaelement/controls.png create mode 100755 src/static/mediaelement/controls.svg create mode 100755 src/static/mediaelement/flashmediaelement.swf create mode 100755 src/static/mediaelement/loading.gif create mode 100755 src/static/mediaelement/mediaelement-and-player.js create mode 100755 src/static/mediaelement/mediaelement-and-player.min.js create mode 100755 src/static/mediaelement/mediaelement.js create mode 100755 src/static/mediaelement/mediaelement.min.js create mode 100755 src/static/mediaelement/mediaelementplayer.css create mode 100755 src/static/mediaelement/mediaelementplayer.js create mode 100755 src/static/mediaelement/mediaelementplayer.min.css create mode 100755 src/static/mediaelement/mediaelementplayer.min.js create mode 100755 src/static/mediaelement/mejs-skins.css create mode 100755 src/static/mediaelement/silverlightmediaelement.xap create mode 100644 src/static/movio/assets/img/loader_white.gif create mode 100755 src/static/movio/js/movio.js create mode 100644 src/static/movio/templates/Default/skins/AttachmentsList.html create mode 100644 src/static/movio/templates/Default/skins/BoxList.html create mode 100644 src/static/movio/templates/Default/skins/BoxSearch.html create mode 100644 src/static/movio/templates/Default/skins/BoxSidebar.html create mode 100644 src/static/movio/templates/Default/skins/Cover.html create mode 100644 src/static/movio/templates/Default/skins/DictionaryList.html create mode 100644 src/static/movio/templates/Default/skins/DigitalExhibition.html create mode 100644 src/static/movio/templates/Default/skins/Entity_entry.html create mode 100644 src/static/movio/templates/Default/skins/Entity_list.html create mode 100644 src/static/movio/templates/Default/skins/Entity_moduleImageLink.html create mode 100644 src/static/movio/templates/Default/skins/Entity_relationImage.html create mode 100644 src/static/movio/templates/Default/skins/Entity_relationImageLink.html create mode 100644 src/static/movio/templates/Default/skins/Entity_relationLink.html create mode 100644 src/static/movio/templates/Default/skins/EuropeanaRelatedContents.html create mode 100644 src/static/movio/templates/Default/skins/Exhibition.html create mode 100644 src/static/movio/templates/Default/skins/GoogleMap.html create mode 100644 src/static/movio/templates/Default/skins/GoogleMap_macro.html create mode 100644 src/static/movio/templates/Default/skins/HomeImageSlider.html create mode 100644 src/static/movio/templates/Default/skins/ImagesList.html create mode 100644 src/static/movio/templates/Default/skins/Login.html create mode 100644 src/static/movio/templates/Default/skins/News_entry.html create mode 100644 src/static/movio/templates/Default/skins/News_list.html create mode 100644 src/static/movio/templates/Default/skins/Photogallery.html create mode 100644 src/static/movio/templates/Default/skins/Search.html create mode 100644 src/static/movio/templates/Default/skins/Share.html create mode 100644 src/static/movio/templates/Default/skins/Storyteller.html create mode 100644 src/static/movio/templates/Default/skins/Timeline.html create mode 100644 src/static/movio/templates/Default/skins/TouristOperators_entry.html create mode 100644 src/static/movio/templates/Default/skins/TouristOperators_list.html create mode 100644 src/static/movio/templates/Default/skins/TouristOperators_map.html create mode 100644 src/static/movio/templates/Default/skins/Unity3D.html create mode 100644 src/static/movio/templates/Default/skins/Video.html create mode 100644 src/static/movio/templates/Default/skins/_macro.html create mode 100644 src/static/movio/templates/Minimal-in-blue/Template.php create mode 100644 src/static/movio/templates/Minimal-in-blue/Template.xml create mode 100644 src/static/movio/templates/Minimal-in-blue/TemplateAdmin.xml create mode 100644 src/static/movio/templates/Minimal-in-blue/TemplateAdminGlobal.xml create mode 100644 src/static/movio/templates/Minimal-in-blue/font/font-awesome/FontAwesome.otf create mode 100755 src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.eot create mode 100755 src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.svg create mode 100755 src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.ttf create mode 100755 src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.woff create mode 100644 src/static/movio/templates/Minimal-in-blue/img/bg/bg-body.png create mode 100644 src/static/movio/templates/Minimal-in-blue/img/bg/bg-box.png create mode 100644 src/static/movio/templates/Minimal-in-blue/img/bg/bg-description.png create mode 100644 src/static/movio/templates/Minimal-in-blue/img/bg/bg-opacity.png create mode 100644 src/static/movio/templates/Minimal-in-blue/img/ico/alert-error.png create mode 100644 src/static/movio/templates/Minimal-in-blue/img/ico/alert-ok.png create mode 100644 src/static/movio/templates/Minimal-in-blue/img/ico/arrow-baloon-big.png create mode 100644 src/static/movio/templates/Minimal-in-blue/img/ico/arrow-baloon.png create mode 100644 src/static/movio/templates/Minimal-in-blue/img/logo-mobile.png create mode 100644 src/static/movio/templates/Minimal-in-blue/img/logo.png create mode 100644 src/static/movio/templates/Minimal-in-blue/img/logo_movio.png create mode 100755 src/static/movio/templates/Minimal-in-blue/js/bootstrap.min.js create mode 100755 src/static/movio/templates/Minimal-in-blue/js/jquery-1.8.2.min.js create mode 100755 src/static/movio/templates/Minimal-in-blue/js/main.js create mode 100755 src/static/movio/templates/Minimal-in-blue/less/element.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/bordered-pulled.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/core.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/fixed-width.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/font-awesome.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/icons.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/larger.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/list.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/mixins.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/path.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/rotated-flipped.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/spinning.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/stacked.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/font-awesome/variables.less create mode 100755 src/static/movio/templates/Minimal-in-blue/less/global.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/libs/bootstrap-social.less create mode 100755 src/static/movio/templates/Minimal-in-blue/less/libs/bootstrap.less create mode 100755 src/static/movio/templates/Minimal-in-blue/less/libs/mixin.less create mode 100755 src/static/movio/templates/Minimal-in-blue/less/mobile.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/navigation.less create mode 100755 src/static/movio/templates/Minimal-in-blue/less/slick.less create mode 100755 src/static/movio/templates/Minimal-in-blue/less/structure.less create mode 100755 src/static/movio/templates/Minimal-in-blue/less/styles.less create mode 100644 src/static/movio/templates/Minimal-in-blue/less/svg.less create mode 100644 src/static/movio/templates/Minimal-in-blue/page.php create mode 100644 src/static/movio/templates/Minimal-in-blue/preview.jpg create mode 100644 src/static/movio/templates/Minimal-in-blue/skins/BoxList.html create mode 100644 src/static/movio/templates/Minimal-in-blue/skins/BoxSearch.html create mode 100644 src/static/movio/templates/Minimal-in-blue/skins/HomeImageSlider.html create mode 100755 src/static/movio/templates/Movio/1col.php create mode 100755 src/static/movio/templates/Movio/2cols.php create mode 100644 src/static/movio/templates/Movio/3cols.php create mode 100644 src/static/movio/templates/Movio/Template.php create mode 100644 src/static/movio/templates/Movio/Template.xml create mode 100644 src/static/movio/templates/Movio/TemplateAdmin.xml create mode 100644 src/static/movio/templates/Movio/TemplateAdminGlobal.xml create mode 100644 src/static/movio/templates/Movio/cover.php create mode 100644 src/static/movio/templates/Movio/font/font-awesome/FontAwesome.otf create mode 100755 src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.eot create mode 100755 src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.svg create mode 100755 src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.ttf create mode 100755 src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.woff create mode 100644 src/static/movio/templates/Movio/img/bg/bg-box-comment.png create mode 100644 src/static/movio/templates/Movio/img/bg/bg-box-link.png create mode 100644 src/static/movio/templates/Movio/img/bg/bg-box.png create mode 100644 src/static/movio/templates/Movio/img/bg/bg-description.png create mode 100644 src/static/movio/templates/Movio/img/ico/alert-error.png create mode 100644 src/static/movio/templates/Movio/img/ico/alert-ok.png create mode 100644 src/static/movio/templates/Movio/img/ico/arrow-baloon-big.png create mode 100644 src/static/movio/templates/Movio/img/ico/arrow-baloon.png create mode 100644 src/static/movio/templates/Movio/img/ico/arrow-button.png create mode 100644 src/static/movio/templates/Movio/img/ico/eye-hover.png create mode 100644 src/static/movio/templates/Movio/img/ico/eye.png create mode 100644 src/static/movio/templates/Movio/img/ico/mov-top.png create mode 100644 src/static/movio/templates/Movio/img/ico/pool.png create mode 100644 src/static/movio/templates/Movio/img/ico/search.png create mode 100644 src/static/movio/templates/Movio/img/logo-footer.png create mode 100644 src/static/movio/templates/Movio/img/logo_fondazioneTelecom.png create mode 100644 src/static/movio/templates/Movio/img/logo_movio.png create mode 100644 src/static/movio/templates/Movio/img/various/app.jpg create mode 100644 src/static/movio/templates/Movio/img/various/cart.jpg create mode 100644 src/static/movio/templates/Movio/img/various/figure.jpg create mode 100644 src/static/movio/templates/Movio/img/various/gallery.jpg create mode 100644 src/static/movio/templates/Movio/img/various/header.jpg create mode 100644 src/static/movio/templates/Movio/img/various/image-page-y.jpg create mode 100644 src/static/movio/templates/Movio/img/various/image-page.jpg create mode 100644 src/static/movio/templates/Movio/img/various/image.jpg create mode 100644 src/static/movio/templates/Movio/img/various/img-link.jpg create mode 100644 src/static/movio/templates/Movio/img/various/img-not-disponible.jpg create mode 100644 src/static/movio/templates/Movio/img/various/img-slider.jpg create mode 100644 src/static/movio/templates/Movio/img/various/map.jpg create mode 100644 src/static/movio/templates/Movio/img/various/mini-img-2.jpg create mode 100644 src/static/movio/templates/Movio/img/various/mini-img.jpg create mode 100644 src/static/movio/templates/Movio/img/various/slide.jpg create mode 100644 src/static/movio/templates/Movio/img/various/visit.jpg create mode 100755 src/static/movio/templates/Movio/js/bootstrap.min.js create mode 100755 src/static/movio/templates/Movio/js/main.js create mode 100755 src/static/movio/templates/Movio/js/vendor/jquery-1.8.2.min.js create mode 100755 src/static/movio/templates/Movio/js/vendor/modernizr-2.6.2.min.js create mode 100755 src/static/movio/templates/Movio/less/element.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/bordered-pulled.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/core.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/fixed-width.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/font-awesome.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/icons.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/larger.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/list.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/mixins.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/path.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/rotated-flipped.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/spinning.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/stacked.less create mode 100644 src/static/movio/templates/Movio/less/font-awesome/variables.less create mode 100755 src/static/movio/templates/Movio/less/global.less create mode 100644 src/static/movio/templates/Movio/less/libs/bootstrap-social.less create mode 100755 src/static/movio/templates/Movio/less/libs/bootstrap.less create mode 100755 src/static/movio/templates/Movio/less/libs/mixin.less create mode 100755 src/static/movio/templates/Movio/less/mobile.less create mode 100755 src/static/movio/templates/Movio/less/page.less create mode 100755 src/static/movio/templates/Movio/less/slick.less create mode 100755 src/static/movio/templates/Movio/less/structure.less create mode 100755 src/static/movio/templates/Movio/less/styles.less create mode 100644 src/static/movio/templates/Movio/less/svg.less create mode 100644 src/static/movio/templates/Movio/preview.jpg create mode 100644 src/static/movio/templates/Skeleton/Template.php create mode 100644 src/static/movio/templates/Skeleton/Template.xml create mode 100644 src/static/movio/templates/Skeleton/TemplateAdmin.xml create mode 100644 src/static/movio/templates/Skeleton/TemplateAdminGlobal.xml create mode 100644 src/static/movio/templates/Skeleton/css/styles.css create mode 100644 src/static/movio/templates/Skeleton/disabled create mode 100644 src/static/movio/templates/Skeleton/font/font-awesome/FontAwesome.otf create mode 100755 src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.eot create mode 100755 src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.svg create mode 100755 src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.ttf create mode 100755 src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.woff create mode 100644 src/static/movio/templates/Skeleton/img/bg/bg-box.png create mode 100644 src/static/movio/templates/Skeleton/img/bg/bg-description.png create mode 100644 src/static/movio/templates/Skeleton/img/ico/alert-error.png create mode 100644 src/static/movio/templates/Skeleton/img/ico/alert-ok.png create mode 100644 src/static/movio/templates/Skeleton/img/ico/arrow-baloon-big.png create mode 100644 src/static/movio/templates/Skeleton/img/ico/arrow-baloon.png create mode 100644 src/static/movio/templates/Skeleton/img/logo-footer.png create mode 100644 src/static/movio/templates/Skeleton/img/logo_movio.png create mode 100755 src/static/movio/templates/Skeleton/js/bootstrap.min.js create mode 100755 src/static/movio/templates/Skeleton/js/jquery-1.8.2.min.js create mode 100755 src/static/movio/templates/Skeleton/js/main.js create mode 100755 src/static/movio/templates/Skeleton/less/cms-component.less create mode 100755 src/static/movio/templates/Skeleton/less/cms-global.less create mode 100755 src/static/movio/templates/Skeleton/less/cms-layout.less create mode 100755 src/static/movio/templates/Skeleton/less/cms-mobile.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/bordered-pulled.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/core.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/fixed-width.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/font-awesome.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/icons.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/larger.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/list.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/mixins.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/path.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/rotated-flipped.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/spinning.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/stacked.less create mode 100644 src/static/movio/templates/Skeleton/less/font-awesome/variables.less create mode 100755 src/static/movio/templates/Skeleton/less/libs/bootstrap.less create mode 100755 src/static/movio/templates/Skeleton/less/libs/cms-bootstrap.less create mode 100755 src/static/movio/templates/Skeleton/less/libs/cms-mixin.less create mode 100755 src/static/movio/templates/Skeleton/less/libs/mixin.less create mode 100755 src/static/movio/templates/Skeleton/less/slick.less create mode 100755 src/static/movio/templates/Skeleton/less/styles.less create mode 100644 src/static/movio/templates/Skeleton/page.php create mode 100644 src/static/movio/templates/Skeleton/preview.jpg create mode 100644 src/static/movio/templates/Skeleton/skins/HomeImageSlider.html create mode 100644 src/static/movio/templates/Sliding-windows/Template.php create mode 100644 src/static/movio/templates/Sliding-windows/Template.xml create mode 100644 src/static/movio/templates/Sliding-windows/TemplateAdmin.xml create mode 100644 src/static/movio/templates/Sliding-windows/TemplateAdminGlobal.xml create mode 100644 src/static/movio/templates/Sliding-windows/css/ie.css create mode 100644 src/static/movio/templates/Sliding-windows/css/jquery.mCustomScrollbar.css create mode 100644 src/static/movio/templates/Sliding-windows/css/styles.css create mode 100644 src/static/movio/templates/Sliding-windows/img/bg/bg-box.png create mode 100644 src/static/movio/templates/Sliding-windows/img/bg/bg-description.png create mode 100644 src/static/movio/templates/Sliding-windows/img/bg/bg-opacity.png create mode 100644 src/static/movio/templates/Sliding-windows/img/ico/alert-error.png create mode 100644 src/static/movio/templates/Sliding-windows/img/ico/alert-ok.png create mode 100644 src/static/movio/templates/Sliding-windows/img/ico/arrow-baloon-big.png create mode 100644 src/static/movio/templates/Sliding-windows/img/ico/arrow-baloon.png create mode 100644 src/static/movio/templates/Sliding-windows/img/logo-footer.png create mode 100644 src/static/movio/templates/Sliding-windows/img/logo.png create mode 100644 src/static/movio/templates/Sliding-windows/img/logo_movio.png create mode 100755 src/static/movio/templates/Sliding-windows/js/bootstrap.min.js create mode 100644 src/static/movio/templates/Sliding-windows/js/jquery-1.8.2.min.js create mode 100755 src/static/movio/templates/Sliding-windows/js/jquery.mCustomScrollbar.concat.min.js create mode 100755 src/static/movio/templates/Sliding-windows/js/jquery.mCustomScrollbar.js create mode 100644 src/static/movio/templates/Sliding-windows/js/jqxcore.js create mode 100644 src/static/movio/templates/Sliding-windows/js/jqxmenu.js create mode 100755 src/static/movio/templates/Sliding-windows/js/main.js create mode 100755 src/static/movio/templates/Sliding-windows/less/element.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/bordered-pulled.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/core.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/fixed-width.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/font-awesome.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/icons.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/larger.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/list.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/mixins.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/path.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/rotated-flipped.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/spinning.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/stacked.less create mode 100644 src/static/movio/templates/Sliding-windows/less/font-awesome/variables.less create mode 100755 src/static/movio/templates/Sliding-windows/less/global.less create mode 100755 src/static/movio/templates/Sliding-windows/less/libs/bootstrap.less create mode 100755 src/static/movio/templates/Sliding-windows/less/libs/mixin.less create mode 100755 src/static/movio/templates/Sliding-windows/less/mobile.less create mode 100644 src/static/movio/templates/Sliding-windows/less/navigation.less create mode 100755 src/static/movio/templates/Sliding-windows/less/slick.less create mode 100755 src/static/movio/templates/Sliding-windows/less/structure.less create mode 100755 src/static/movio/templates/Sliding-windows/less/styles.less create mode 100644 src/static/movio/templates/Sliding-windows/less/svg.less create mode 100644 src/static/movio/templates/Sliding-windows/page.php create mode 100644 src/static/movio/templates/Sliding-windows/pageTypes/Home.xml create mode 100644 src/static/movio/templates/Sliding-windows/preview.jpg create mode 100644 src/static/movio/templates/Sliding-windows/skins/BoxList.html create mode 100644 src/static/movio/templates/Sliding-windows/skins/Entity_entry.html create mode 100644 src/static/movio/templates/Sliding-windows/skins/Entity_list.html create mode 100644 src/static/movio/templates/Sliding-windows/skins/Entity_relationImage.html create mode 100644 src/static/movio/templates/Sliding-windows/skins/Entity_relationImageLink.html create mode 100644 src/static/movio/templates/Sliding-windows/skins/Entity_relationLink.html create mode 100644 src/static/movio/templates/Sliding-windows/skins/EuropeanaRelatedContents.html create mode 100644 src/static/movio/templates/Sliding-windows/skins/HomeImageSlider.html create mode 100644 src/static/movio/templates/Sliding-windows/skins/Storyteller.html create mode 100644 src/static/org_glizy/assets/js/Glizy.js create mode 100644 src/static/org_glizy/assets/js/Glizy_tiny_mce.js create mode 100644 src/static/org_glizy/assets/js/locale/de.js create mode 100644 src/static/org_glizy/assets/js/locale/en.js create mode 100644 src/static/org_glizy/assets/js/locale/fr.js create mode 100644 src/static/org_glizy/assets/js/locale/it.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/langs/de.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/langs/en.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/langs/fr.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/langs/it.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/license.txt create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/css/GLZ_image.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/image.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/images/sample.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/jscripts/functions.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/langs/en.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/langs/it.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/css/GLZ_link.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/jscripts/functions.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/langs/en.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/langs/it.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/link.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/css/advhr.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/js/rule.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/rule.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/css/advimage.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/image.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/img/sample.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/js/image.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/css/advlink.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/js/advlink.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/link.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advlist/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/advlist/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/autolink/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/autolink/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/autoresize/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/autoresize/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/langs/en.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/bbcode/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/bbcode/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/contextmenu/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/contextmenu/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/directionality/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/directionality/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/emotions.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-cool.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-cry.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-embarassed.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-frown.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-innocent.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-kiss.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-laughing.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-sealed.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-smile.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-surprised.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-undecided.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-wink.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-yell.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/js/emotions.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/example/dialog.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/example/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/example/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/example/img/example.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/example/js/dialog.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/example/langs/en.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/example/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/example_dependency/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/example_dependency/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/css/fullpage.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/fullpage.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/js/fullpage.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/fullscreen.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/iespell/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/iespell/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/template.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/insertdatetime/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/insertdatetime/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/layer/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/layer/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/legacyoutput/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/legacyoutput/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/lists/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/lists/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/media/css/media.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/media/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/media/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/media/js/embed.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/media/js/media.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/media/media.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/media/moxieplayer.swf create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/nonbreaking/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/noneditable/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/noneditable/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/pagebreak/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/pagebreak/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/paste/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/paste/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/paste/js/pastetext.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/paste/js/pasteword.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/paste/pastetext.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/paste/pasteword.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/preview/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/preview/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/preview/example.html create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/preview/jscripts/embed.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/preview/preview.html create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/print/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/print/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/save/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/save/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/css/searchreplace.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/js/searchreplace.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/searchreplace.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/css/content.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/img/wline.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/style/css/props.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/style/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/style/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/style/js/props.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/style/props.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/tabfocus/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/tabfocus/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/cell.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/cell.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/row.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/table.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/cell.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/merge_cells.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/row.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/table.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/merge_cells.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/row.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/table/table.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/template/blank.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/template/css/template.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/template/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/template/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/template/js/template.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/template/template.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/visualchars/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/visualchars/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/wordcount/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/wordcount/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/abbr.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/acronym.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/attributes.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/cite.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/css/attributes.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/css/popup.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/del.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/editor_plugin.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/ins.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/abbr.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/acronym.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/attributes.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/cite.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/del.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/element_common.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/ins.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/about.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/anchor.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/charmap.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/color_picker.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/editor_template.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/editor_template_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/image.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/colorpicker.jpg create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/flash.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/icons.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/iframe.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/pagebreak.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/quicktime.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/realmedia.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/shockwave.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/trans.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/video.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/windowsmedia.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/about.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/anchor.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/charmap.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/color_picker.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/image.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/link.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/source_editor.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/de.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/de_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/en.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/en_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/fr.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/fr_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/it.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/it_dlg.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/link.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/shortcuts.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/content.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/dialog.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/buttons.png create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/items.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/menu_check.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/progress.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/tabs.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/ui.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/content.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/dialog.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/ui.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/content.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/dialog.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui_black.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/advanced/source_editor.htm create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/editor_template.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/editor_template_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/img/icons.gif create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/de.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/en.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/fr.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/it.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/default/content.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/default/ui.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/o2k7/content.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png create mode 100644 src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/o2k7/ui.css create mode 100644 src/static/org_glizy/assets/js/tiny_mce/tiny_mce.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/tiny_mce_popup.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/tiny_mce_src.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/utils/editable_selects.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/utils/form_utils.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/utils/mctabs.js create mode 100644 src/static/org_glizy/assets/js/tiny_mce/utils/validate.js create mode 100755 src/static/timelinejs/css/loading.gif create mode 100755 src/static/timelinejs/css/themes/dark.css create mode 100755 src/static/timelinejs/css/themes/font/AbrilFatface-Average.css create mode 100755 src/static/timelinejs/css/themes/font/Arvo-PTSans.css create mode 100755 src/static/timelinejs/css/themes/font/Bevan-PotanoSans.css create mode 100755 src/static/timelinejs/css/themes/font/BreeSerif-OpenSans.css create mode 100755 src/static/timelinejs/css/themes/font/DroidSerif-DroidSans.css create mode 100755 src/static/timelinejs/css/themes/font/Georgia-Helvetica.css create mode 100755 src/static/timelinejs/css/themes/font/Lekton-Molengo.css create mode 100755 src/static/timelinejs/css/themes/font/Lora-Istok.css create mode 100755 src/static/timelinejs/css/themes/font/Merriweather-NewsCycle.css create mode 100755 src/static/timelinejs/css/themes/font/NewsCycle-Merriweather.css create mode 100755 src/static/timelinejs/css/themes/font/NixieOne-Ledger.css create mode 100755 src/static/timelinejs/css/themes/font/PT.css create mode 100755 src/static/timelinejs/css/themes/font/PTSerif-PTSans.css create mode 100755 src/static/timelinejs/css/themes/font/Pacifico-Arimo.css create mode 100755 src/static/timelinejs/css/themes/font/PlayfairDisplay-Muli.css create mode 100755 src/static/timelinejs/css/themes/font/PoiretOne-Molengo.css create mode 100755 src/static/timelinejs/css/themes/font/Rancho-Gudea.css create mode 100755 src/static/timelinejs/css/themes/font/SansitaOne-Kameron.css create mode 100755 src/static/timelinejs/css/themes/timeline-dark.png create mode 100755 src/static/timelinejs/css/themes/timeline-dark@2x.png create mode 100755 src/static/timelinejs/css/themes/timeline-texture.png create mode 100755 src/static/timelinejs/css/timeline.css create mode 100755 src/static/timelinejs/css/timeline.png create mode 100755 src/static/timelinejs/css/timeline@2x.png create mode 100755 src/static/timelinejs/js/locale/ar.js create mode 100755 src/static/timelinejs/js/locale/bg.js create mode 100755 src/static/timelinejs/js/locale/ca.js create mode 100755 src/static/timelinejs/js/locale/cz.js create mode 100755 src/static/timelinejs/js/locale/de.js create mode 100755 src/static/timelinejs/js/locale/dk.js create mode 100755 src/static/timelinejs/js/locale/el.js create mode 100755 src/static/timelinejs/js/locale/en.js create mode 100755 src/static/timelinejs/js/locale/es.js create mode 100755 src/static/timelinejs/js/locale/eu.js create mode 100755 src/static/timelinejs/js/locale/fi.js create mode 100755 src/static/timelinejs/js/locale/fo.js create mode 100755 src/static/timelinejs/js/locale/fr.js create mode 100755 src/static/timelinejs/js/locale/hu.js create mode 100755 src/static/timelinejs/js/locale/hy.js create mode 100755 src/static/timelinejs/js/locale/id.js create mode 100755 src/static/timelinejs/js/locale/is.js create mode 100755 src/static/timelinejs/js/locale/it.js create mode 100755 src/static/timelinejs/js/locale/iw.js create mode 100755 src/static/timelinejs/js/locale/ja.js create mode 100755 src/static/timelinejs/js/locale/ko.js create mode 100755 src/static/timelinejs/js/locale/kr.js create mode 100755 src/static/timelinejs/js/locale/nl.js create mode 100755 src/static/timelinejs/js/locale/no.js create mode 100755 src/static/timelinejs/js/locale/pl.js create mode 100755 src/static/timelinejs/js/locale/pt-br.js create mode 100755 src/static/timelinejs/js/locale/pt.js create mode 100755 src/static/timelinejs/js/locale/ru.js create mode 100755 src/static/timelinejs/js/locale/sk.js create mode 100755 src/static/timelinejs/js/locale/sl.js create mode 100755 src/static/timelinejs/js/locale/sr-cy.js create mode 100755 src/static/timelinejs/js/locale/sr-la.js create mode 100755 src/static/timelinejs/js/locale/sv.js create mode 100755 src/static/timelinejs/js/locale/ta.js create mode 100755 src/static/timelinejs/js/locale/tl.js create mode 100755 src/static/timelinejs/js/locale/tr.js create mode 100755 src/static/timelinejs/js/locale/zh-ch.js create mode 100755 src/static/timelinejs/js/locale/zh-cn.js create mode 100755 src/static/timelinejs/js/locale/zh-tw.js create mode 100755 src/static/timelinejs/js/storyjs-embed.js create mode 100755 src/static/timelinejs/js/timeline-min.js create mode 100755 src/static/timelinejs/js/timeline.js create mode 100755 src/static/viz.js-master/.gitattributes create mode 100755 src/static/viz.js-master/COPYING create mode 100755 src/static/viz.js-master/Makefile create mode 100755 src/static/viz.js-master/README.txt create mode 100755 src/static/viz.js-master/config.h create mode 100755 src/static/viz.js-master/example.html create mode 100755 src/static/viz.js-master/post.js create mode 100755 src/static/viz.js-master/pre.js create mode 100755 src/static/viz.js-master/prova.html create mode 100755 src/static/viz.js-master/viz.c create mode 100755 src/static/viz.js-master/viz.js create mode 100644 src/url.php create mode 100644 src/zoom.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/Install.md b/Install.md new file mode 100644 index 0000000..119ca57 --- /dev/null +++ b/Install.md @@ -0,0 +1,57 @@ + +# Minimum requirements + +* Operating Sistem: Linux +* Apache 2.2.x +* MySQL 5.5 +* PHP 5.3.x with extensions: + * PDO + * PDO_mysql + * JSON + * GDlib 2 + +# Configuration +Clone the repository and publish the src folder in your webserver. + +Open config.xml, located inside the folder: application/config/ +Edit the network parameters and the DB name, username, password (to access the DB): +  +   +` + + +    + +    + +    +` + +* DB_HOST: is the name of the data base host in mysql +* DB_NAME: name of the data base +* DB_USER: name of the user connecting to the DB +* DB_PSW: password to connect to the DB + + +MOVIO can work with different configurations: the developers might use one configuration for the development and one for the production   +To have different configuration, you should copy and modify the congig.xml and rename it as config_DomainName.xml (as example, if you are using www.myserver.com, the file should be named as: config_www.myserver.com; or if the server is www. minervaeurope.org you should name the config file as: config_www.minervaeurope.org.xml) + + +You need to use an administration tool to manage mySql (es. phpMyAdmin): create the MOVIO DB (if you want to use a different name, you need to change accordingly the parameter DB_NAME in the config.xml file (see previous steps). + +Once you created the DB you need to import the file file install/movio.sql. + +The following folders must be set with ‘write’ rights: + +* cache +* application/mediaArchive (and all the sub folders) +* application/classes/userModules +* application/startup +* admin/cache + + +The Mod Rewrite in Apache must be active with right configuration in virtual-host (AllowOverride All) + +Open the browser at http://www.myserver.com to check that all has been executed correctly. +Open the admin page http://www.myserver.com/admin/ using the admim/admin to login. + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..d3eaa77 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 GruppoMeta + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/install/movio.sql b/install/movio.sql new file mode 100644 index 0000000..73596ad --- /dev/null +++ b/install/movio.sql @@ -0,0 +1,1391 @@ +-- phpMyAdmin SQL Dump +-- version 4.4.10 +-- http://www.phpmyadmin.net +-- +-- Host: localhost:3306 +-- Generation Time: Dec 15, 2015 at 10:42 PM +-- Server version: 5.6.25 +-- PHP Version: 5.5.26 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Database: `mibac_movio_vuoto` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `countries_tbl` +-- + +DROP TABLE IF EXISTS `countries_tbl`; +CREATE TABLE `countries_tbl` ( + `country_id` int(11) NOT NULL, + `country_name` varchar(255) DEFAULT NULL, + `country_639_2` char(3) DEFAULT NULL, + `country_639_1` char(2) DEFAULT NULL +) ENGINE=InnoDB AUTO_INCREMENT=161 DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `countries_tbl` +-- + +INSERT INTO `countries_tbl` (`country_id`, `country_name`, `country_639_2`, `country_639_1`) VALUES +(1, 'Afrikaans', 'afr', 'af'), +(2, 'Albanian', 'alb', 'sq'), +(3, 'Amharic', 'amh', 'am'), +(4, 'Arabic', 'ara', 'ar'), +(5, 'Armenian', 'arm', 'hy'), +(6, 'Assamese', 'asm', 'as'), +(7, 'Avestan', 'ave', 'ae'), +(8, 'Aymara', 'aym', 'ay'), +(9, 'Azerbaijani', 'aze', 'az'), +(10, 'Bashkir', 'bak', 'ba'), +(11, 'Basque', 'baq', 'eu'), +(12, 'Belarusian', 'bel', 'be'), +(13, 'Bengali', 'ben', 'bn'), +(14, 'Bihari', 'bih', 'bh'), +(15, 'Bislama', 'bis', 'bi'), +(16, 'Bosnian', 'bos', 'bs'), +(17, 'Breton', 'bre', 'br'), +(18, 'Bulgarian', 'bul', 'bg'), +(19, 'Burmese', 'bur', 'my'), +(20, 'Catalan', 'cat', 'ca'), +(21, 'Chamorro', 'cha', 'ch'), +(22, 'Chechen', 'che', 'ce'), +(23, 'Chichewa', 'nya', 'ny'), +(24, 'Chinese', 'chi', 'zh'), +(25, 'Church Slavic', 'chu', 'cu'), +(26, 'Chuvash', 'chv', 'cv'), +(27, 'Cornish', 'cor', 'kw'), +(28, 'Corsican', 'cos', 'co'), +(29, 'Croatian', 'hrv', 'hr'), +(30, 'Czech', 'cze', 'cs'), +(31, 'Danish', 'dan', 'da'), +(32, 'Dutch', 'nld', 'nl'), +(33, 'Dzongkha', 'dzo', 'dz'), +(34, 'English', 'eng', 'en'), +(35, 'Esperanto', 'epo', 'eo'), +(36, 'Estonian', 'est', 'et'), +(37, 'Faroese', 'fao', 'fo'), +(38, 'Fijian', 'fij', 'fj'), +(39, 'Finnish', 'fin', 'fi'), +(40, 'French', 'fra', 'fr'), +(41, 'Frisian', 'fry', 'fy'), +(42, 'Gaelic', 'gla', 'gd'), +(43, 'Galician', 'glg', 'gl'), +(44, 'Georgian', 'geo', 'ka'), +(45, 'German', 'deu', 'de'), +(46, 'Greek (Modern)', 'ell', 'el'), +(47, 'Guarani', 'grn', 'gn'), +(48, 'Gujarati', 'guj', 'gu'), +(49, 'Hebrew', 'heb', 'he'), +(50, 'Herero', 'her', 'hz'), +(51, 'Hindi', 'hin', 'hi'), +(52, 'Hiri Motu', 'hmo', 'ho'), +(53, 'Hungarian', 'hun', 'hu'), +(54, 'Icelandic', 'isl', 'is'), +(55, 'Indonesian', 'ind', 'id'), +(56, 'Interlingua (International Auxiliary Language Association)', 'ina', 'ia'), +(57, 'Interlingue', 'ile', 'ie'), +(58, 'Inuktitut', 'iku', 'iu'), +(59, 'Inupiaq', 'ipk', 'ik'), +(60, 'Irish', 'gle', 'ga'), +(61, 'Italian', 'ita', 'it'), +(62, 'Japanese', 'jpn', 'ja'), +(63, 'Javanese', 'jav', 'jw'), +(64, 'Kalaallisut', 'kal', 'kl'), +(65, 'Kannada', 'kan', 'kn'), +(66, 'Kashmiri', 'kas', 'ks'), +(67, 'Kazakh', 'kaz', 'kk'), +(68, 'Khmer', 'khm', 'km'), +(69, 'Kikuyu', 'kik', 'ki'), +(70, 'Kinyarwanda', 'kin', 'rw'), +(71, 'Kirghiz', 'kir', 'ky'), +(72, 'Komi', 'kom', 'kv'), +(73, 'Korean', 'kor', 'ko'), +(74, 'Kuanyama', 'kua', 'kj'), +(75, 'Kurdish', 'kur', 'ku'), +(76, 'Lao', 'lao', 'lo'), +(77, 'Latin', 'lat', 'la'), +(78, 'Latvian', 'lav', 'lv'), +(79, 'Lingala', 'lin', 'ln'), +(80, 'Lithuanian', 'lit', 'lt'), +(81, 'Luxembourgish', 'ltz', 'lb'), +(82, 'Macedonian', 'mkd', 'mk'), +(83, 'Malagasy', 'mlg', 'mg'), +(84, 'Malay', 'msa', 'ms'), +(85, 'Malayalam', 'mal', 'ml'), +(86, 'Maltese', 'mlt', 'mt'), +(87, 'Manx', 'glv', 'gv'), +(88, 'Maori', 'mao', 'mi'), +(89, 'Marathi', 'mar', 'mr'), +(90, 'Marshallese', 'mah', 'mh'), +(91, 'Moldavian', 'mol', 'mo'), +(92, 'Mongolian', 'mon', 'mn'), +(93, 'Nauru', 'nau', 'na'), +(94, 'Navajo', 'nav', 'nv'), +(95, 'Ndebele, North', 'nde', 'nd'), +(96, 'Ndebele, South', 'nbl', 'nr'), +(97, 'Ndonga', 'ndo', 'ng'), +(98, 'Nepali', 'nep', 'ne'), +(99, 'Northern Sami', 'sme', 'se'), +(100, 'Norwegian', 'nor', 'no'), +(101, 'Norwegian Bokmål', 'nob', 'nb'), +(102, 'Norwegian Nynorsk', 'nno', 'nn'), +(103, 'Occitan (post 1500)', 'oci', 'oc'), +(104, 'Oriya', 'ori', 'or'), +(105, 'Oromo', 'orm', 'om'), +(106, 'Ossetian', 'oss', 'os'), +(107, 'Pali', 'pli', 'pi'), +(108, 'Panjabi', 'pan', 'pa'), +(109, 'Persian', 'fas', 'fa'), +(110, 'Polish', 'pol', 'pl'), +(111, 'Portuguese', 'por', 'pt'), +(112, 'Pushto', 'pus', 'ps'), +(113, 'Quechua', 'que', 'qu'), +(114, 'Raeto-Romance', 'roh', 'rm'), +(115, 'Romanian', 'ron', 'ro'), +(116, 'Rundi', 'run', 'rn'), +(117, 'Russian', 'rus', 'ru'), +(118, 'Samoan', 'smo', 'sm'), +(119, 'Sango', 'sag', 'sg'), +(120, 'Sanskrit', 'san', 'sa'), +(121, 'Sardinian', 'srd', 'sc'), +(122, 'Serbian', 'srp', 'sr'), +(123, 'Shona', 'sna', 'sn'), +(124, 'Sindhi', 'snd', 'sd'), +(125, 'Sinhalese', 'sin', 'si'), +(126, 'Slovak', 'slo', 'sk'), +(127, 'Slovenian', 'slv', 'sl'), +(128, 'Somali', 'som', 'so'), +(129, 'Sotho, Southern', 'sot', 'st'), +(130, 'Spanish', 'spa', 'es'), +(131, 'Sundanese', 'sun', 'su'), +(132, 'Swahili', 'swa', 'sw'), +(133, 'Swati', 'ssw', 'ss'), +(134, 'Swedish', 'swe', 'sv'), +(135, 'Tagalog', 'tgl', 'tl'), +(136, 'Tahitian', 'tah', 'ty'), +(137, 'Tajik', 'tgk', 'tg'), +(138, 'Tamil', 'tam', 'ta'), +(139, 'Tatar', 'tat', 'tt'), +(140, 'Telugu', 'tel', 'te'), +(141, 'Thai', 'tha', 'th'), +(142, 'Tibetan', 'bod', 'bo'), +(143, 'Tsonga', 'tso', 'ts'), +(144, 'Tswana', 'tsn', 'tn'), +(145, 'Turkish', 'tur', 'tr'), +(146, 'Turkmen', 'tuk', 'tk'), +(147, 'Twi', 'twi', 'tw'), +(148, 'Uighur', 'uig', 'ug'), +(149, 'Ukrainian', 'ukr', 'uk'), +(150, 'Urdu', 'urd', 'ur'), +(151, 'Uzbek', 'uzb', 'uz'), +(152, 'Vietnamese', 'vie', 'vi'), +(153, 'Volapük', 'vol', 'vo'), +(154, 'Welsh', 'wel', 'cy'), +(155, 'Welsh', 'cym', 'cy'), +(156, 'Wolof', 'wol', 'wo'), +(157, 'Xhosa', 'xho', 'xh'), +(158, 'Yiddish', 'yid', 'yi'), +(159, 'Zhuang', 'zha', 'za'), +(160, 'Zulu', 'zul', 'zu'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `custom_code_mapping_tbl` +-- + +DROP TABLE IF EXISTS `custom_code_mapping_tbl`; +CREATE TABLE `custom_code_mapping_tbl` ( + `custom_code_mapping_id` int(10) unsigned NOT NULL, + `custom_code_mapping_description` text NOT NULL, + `custom_code_mapping_code` varchar(100) NOT NULL DEFAULT '', + `custom_code_mapping_link` varchar(100) NOT NULL DEFAULT '' +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `documents_detail_tbl` +-- + +DROP TABLE IF EXISTS `documents_detail_tbl`; +CREATE TABLE `documents_detail_tbl` ( + `document_detail_id` int(10) unsigned NOT NULL, + `document_detail_FK_document_id` int(10) unsigned NOT NULL, + `document_detail_FK_language_id` int(10) unsigned NOT NULL, + `document_detail_FK_user_id` int(10) unsigned NOT NULL, + `document_detail_modificationDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `document_detail_status` varchar(9) NOT NULL DEFAULT 'DRAFT', + `document_detail_translated` tinyint(1) unsigned NOT NULL DEFAULT '0', + `document_detail_object` longtext NOT NULL, + `document_detail_isVisible` tinyint(1) unsigned NOT NULL DEFAULT '1', + `document_detail_note` text +) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `documents_detail_tbl` +-- + +INSERT INTO `documents_detail_tbl` (`document_detail_id`, `document_detail_FK_document_id`, `document_detail_FK_language_id`, `document_detail_FK_user_id`, `document_detail_modificationDate`, `document_detail_status`, `document_detail_translated`, `document_detail_object`, `document_detail_isVisible`, `document_detail_note`) VALUES +(1, 1, 1, 1, '2015-12-15 22:32:36', 'PUBLISHED', 1, '{"id":"2","title":"Metanavigation","content":{"__indexFields":{}}}', 1, NULL), +(2, 2, 1, 1, '2015-12-15 22:32:42', 'PUBLISHED', 1, '{"id":"4","title":"Utility","content":{"__indexFields":{}}}', 1, NULL), +(3, 3, 1, 1, '2015-12-15 22:32:48', 'PUBLISHED', 1, '{"id":"5","title":"Tools","content":{"__indexFields":{}}}', 1, NULL), +(4, 4, 1, 1, '2015-12-15 22:33:24', 'PUBLISHED', 1, '{"id":"6","title":"Page 1","content":{"__indexFields":{},"images":{},"attachments":{},"text":"

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duarum enim vitarum nobis erunt instituta capienda. Quid de Pythagora? Bonum liberi: misera orbitas. Quamquam ab iis philosophiam et omnes ingenuas disciplinas habemus; Graecum enim hunc versum nostis omnes-: Suavis laborum est praeteritorum memoria. Duo Reges: constructio interrete.<\\/p>\\n

An me, inquam, nisi te audire vellem, censes haec dicturum fuisse? At ille pellit, qui permulcet sensum voluptate. Ergo opifex plus sibi proponet ad formarum quam civis excellens ad factorum pulchritudinem? Multoque hoc melius nos veriusque quam Stoici. Heri, inquam, ludis commissis ex urbe profectus veni ad vesperum. Ita enim vivunt quidam, ut eorum vita refellatur oratio. Et quod est munus, quod opus sapientiae? Quae animi affectio suum cuique tribuens atque hanc, quam dico. Non est ista, inquam, Piso, magna dissensio.<\\/p>\\n

Quo tandem modo? Sed ego in hoc resisto; Ego vero volo in virtute vim esse quam maximam; Quam ob rem tandem, inquit, non satisfacit? In eo enim positum est id, quod dicimus esse expetendum. Etiam beatissimum?<\\/p>\\n

Ita fit cum gravior, tum etiam splendidior oratio. Quodsi vultum tibi, si incessum fingeres, quo gravior viderere, non esses tui similis; Qui convenit? Itaque ad tempus ad Pisonem omnes. Expressa vero in iis aetatibus, quae iam confirmatae sunt. Nunc omni virtuti vitium contrario nomine opponitur.<\\/p>"}}', 1, NULL), +(5, 5, 1, 1, '2015-12-15 22:33:35', 'PUBLISHED', 1, '{"id":"7","title":"Page 2","content":{"__indexFields":{},"images":{},"attachments":{},"text":"

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duarum enim vitarum nobis erunt instituta capienda. Quid de Pythagora? Bonum liberi: misera orbitas. Quamquam ab iis philosophiam et omnes ingenuas disciplinas habemus; Graecum enim hunc versum nostis omnes-: Suavis laborum est praeteritorum memoria. Duo Reges: constructio interrete.<\\/p>\\n

An me, inquam, nisi te audire vellem, censes haec dicturum fuisse? At ille pellit, qui permulcet sensum voluptate. Ergo opifex plus sibi proponet ad formarum quam civis excellens ad factorum pulchritudinem? Multoque hoc melius nos veriusque quam Stoici. Heri, inquam, ludis commissis ex urbe profectus veni ad vesperum. Ita enim vivunt quidam, ut eorum vita refellatur oratio. Et quod est munus, quod opus sapientiae? Quae animi affectio suum cuique tribuens atque hanc, quam dico. Non est ista, inquam, Piso, magna dissensio.<\\/p>\\n

Quo tandem modo? Sed ego in hoc resisto; Ego vero volo in virtute vim esse quam maximam; Quam ob rem tandem, inquit, non satisfacit? In eo enim positum est id, quod dicimus esse expetendum. Etiam beatissimum?<\\/p>\\n

Ita fit cum gravior, tum etiam splendidior oratio. Quodsi vultum tibi, si incessum fingeres, quo gravior viderere, non esses tui similis; Qui convenit? Itaque ad tempus ad Pisonem omnes. Expressa vero in iis aetatibus, quae iam confirmatae sunt. Nunc omni virtuti vitium contrario nomine opponitur.<\\/p>"}}', 1, NULL), +(6, 6, 1, 1, '2015-12-15 22:34:01', 'PUBLISHED', 1, '{"id":"8","title":"Guide","content":{"__indexFields":{},"images":{},"attachments":{},"text":"

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duarum enim vitarum nobis erunt instituta capienda. Quid de Pythagora? Bonum liberi: misera orbitas. Quamquam ab iis philosophiam et omnes ingenuas disciplinas habemus; Graecum enim hunc versum nostis omnes-: Suavis laborum est praeteritorum memoria. Duo Reges: constructio interrete.<\\/p>"}}', 1, NULL), +(7, 7, 1, 1, '2015-12-15 22:35:00', 'PUBLISHED', 1, '{"id":"9","title":"Sitemap","content":{"__indexFields":{},"text":""}}', 1, NULL), +(8, 8, 1, 1, '2015-12-15 22:35:18', 'PUBLISHED', 1, '{"id":"12","title":"Lost password","content":{"__indexFields":{},"text":"","confirm":""}}', 1, NULL), +(9, 9, 1, 1, '2015-12-15 22:35:26', 'PUBLISHED', 1, '{"id":"10","title":"Search","content":{"__indexFields":{},"text":""}}', 1, NULL), +(10, 10, 1, 1, '2015-12-15 22:35:33', 'PUBLISHED', 1, '{"id":"13","title":"My details","content":{"__indexFields":{},"text":"","confirm":""}}', 1, NULL), +(11, 11, 1, 1, '2015-12-15 22:38:21', 'PUBLISHED', 1, '{"id":"14","title":"Contact","content":{"__indexFields":{},"images":{},"attachments":{},"text":""}}', 1, NULL), +(12, 12, 1, 1, '2015-12-15 22:36:37', 'PUBLISHED', 1, '{"id":"17","title":"Home","content":{"__indexFields":{},"link":"internal:1"}}', 1, NULL), +(13, 13, 1, 1, '2015-12-15 22:36:50', 'PUBLISHED', 1, '{"id":"18","title":"Sitemap","content":{"__indexFields":{},"link":"internal:9"}}', 1, NULL), +(14, 14, 1, 1, '2015-12-15 22:37:00', 'PUBLISHED', 1, '{"id":"19","title":"Search","content":{"__indexFields":{},"link":"internal:10"}}', 1, NULL), +(15, 15, 1, 1, '2015-12-15 22:37:10', 'PUBLISHED', 1, '{"id":"15","title":"Home","content":{"__indexFields":{},"link":"internal:1"}}', 1, NULL), +(16, 16, 1, 1, '2015-12-15 22:38:16', 'PUBLISHED', 1, '{"id":"16","title":"Contact","content":{"__indexFields":{},"link":"internal:14"}}', 1, NULL); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `documents_index_datetime_tbl` +-- + +DROP TABLE IF EXISTS `documents_index_datetime_tbl`; +CREATE TABLE `documents_index_datetime_tbl` ( + `document_index_datetime_id` int(10) unsigned NOT NULL, + `document_index_datetime_FK_document_detail_id` int(10) unsigned NOT NULL, + `document_index_datetime_name` varchar(100) NOT NULL, + `document_index_datetime_value` datetime NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `documents_index_date_tbl` +-- + +DROP TABLE IF EXISTS `documents_index_date_tbl`; +CREATE TABLE `documents_index_date_tbl` ( + `document_index_date_id` int(10) unsigned NOT NULL, + `document_index_date_FK_document_detail_id` int(10) unsigned NOT NULL, + `document_index_date_name` varchar(100) NOT NULL, + `document_index_date_value` date NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `documents_index_fulltext_tbl` +-- + +DROP TABLE IF EXISTS `documents_index_fulltext_tbl`; +CREATE TABLE `documents_index_fulltext_tbl` ( + `document_index_fulltext_id` int(10) unsigned NOT NULL, + `document_index_fulltext_FK_document_detail_id` int(10) unsigned NOT NULL, + `document_index_fulltext_name` varchar(100) NOT NULL, + `document_index_fulltext_value` longtext NOT NULL +) ENGINE=MyISAM AUTO_INCREMENT=18 DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `documents_index_fulltext_tbl` +-- + +INSERT INTO `documents_index_fulltext_tbl` (`document_index_fulltext_id`, `document_index_fulltext_FK_document_detail_id`, `document_index_fulltext_name`, `document_index_fulltext_value`) VALUES +(1, 1, 'fulltext', 'Metanavigation ##'), +(2, 2, 'fulltext', 'Utility ##'), +(3, 3, 'fulltext', 'Tools ##'), +(4, 4, 'fulltext', 'Page 1 ## Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duarum enim vitarum nobis erunt instituta capienda. Quid de Pythagora? Bonum liberi: misera orbitas. Quamquam ab iis philosophiam et omnes ingenuas disciplinas habemus; Graecum enim hunc versum nostis omnes-: Suavis laborum est praeteritorum memoria. Duo Reges: constructio interrete.\nAn me, inquam, nisi te audire vellem, censes haec dicturum fuisse? At ille pellit, qui permulcet sensum voluptate. Ergo opifex plus sibi proponet ad formarum quam civis excellens ad factorum pulchritudinem? Multoque hoc melius nos veriusque quam Stoici. Heri, inquam, ludis commissis ex urbe profectus veni ad vesperum. Ita enim vivunt quidam, ut eorum vita refellatur oratio. Et quod est munus, quod opus sapientiae? Quae animi affectio suum cuique tribuens atque hanc, quam dico. Non est ista, inquam, Piso, magna dissensio.\nQuo tandem modo? Sed ego in hoc resisto; Ego vero volo in virtute vim esse quam maximam; Quam ob rem tandem, inquit, non satisfacit? In eo enim positum est id, quod dicimus esse expetendum. Etiam beatissimum?\nIta fit cum gravior, tum etiam splendidior oratio. Quodsi vultum tibi, si incessum fingeres, quo gravior viderere, non esses tui similis; Qui convenit? Itaque ad tempus ad Pisonem omnes. Expressa vero in iis aetatibus, quae iam confirmatae sunt. Nunc omni virtuti vitium contrario nomine opponitur. ##'), +(5, 5, 'fulltext', 'Page 2 ## Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duarum enim vitarum nobis erunt instituta capienda. Quid de Pythagora? Bonum liberi: misera orbitas. Quamquam ab iis philosophiam et omnes ingenuas disciplinas habemus; Graecum enim hunc versum nostis omnes-: Suavis laborum est praeteritorum memoria. Duo Reges: constructio interrete.\nAn me, inquam, nisi te audire vellem, censes haec dicturum fuisse? At ille pellit, qui permulcet sensum voluptate. Ergo opifex plus sibi proponet ad formarum quam civis excellens ad factorum pulchritudinem? Multoque hoc melius nos veriusque quam Stoici. Heri, inquam, ludis commissis ex urbe profectus veni ad vesperum. Ita enim vivunt quidam, ut eorum vita refellatur oratio. Et quod est munus, quod opus sapientiae? Quae animi affectio suum cuique tribuens atque hanc, quam dico. Non est ista, inquam, Piso, magna dissensio.\nQuo tandem modo? Sed ego in hoc resisto; Ego vero volo in virtute vim esse quam maximam; Quam ob rem tandem, inquit, non satisfacit? In eo enim positum est id, quod dicimus esse expetendum. Etiam beatissimum?\nIta fit cum gravior, tum etiam splendidior oratio. Quodsi vultum tibi, si incessum fingeres, quo gravior viderere, non esses tui similis; Qui convenit? Itaque ad tempus ad Pisonem omnes. Expressa vero in iis aetatibus, quae iam confirmatae sunt. Nunc omni virtuti vitium contrario nomine opponitur. ##'), +(6, 6, 'fulltext', 'Guide ## Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duarum enim vitarum nobis erunt instituta capienda. Quid de Pythagora? Bonum liberi: misera orbitas. Quamquam ab iis philosophiam et omnes ingenuas disciplinas habemus; Graecum enim hunc versum nostis omnes-: Suavis laborum est praeteritorum memoria. Duo Reges: constructio interrete. ##'), +(7, 7, 'fulltext', 'Sitemap ##'), +(8, 8, 'fulltext', 'Lost password ##'), +(9, 9, 'fulltext', 'Search ##'), +(10, 10, 'fulltext', 'My details ##'), +(17, 11, 'fulltext', 'Contact ## '), +(12, 12, 'fulltext', 'Home ## internal:1 ##'), +(13, 13, 'fulltext', 'Sitemap ## internal:9 ##'), +(14, 14, 'fulltext', 'Search ## internal:10 ##'), +(15, 15, 'fulltext', 'Home ## internal:1 ##'), +(16, 16, 'fulltext', 'Contact ## internal:14 ##'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `documents_index_int_tbl` +-- + +DROP TABLE IF EXISTS `documents_index_int_tbl`; +CREATE TABLE `documents_index_int_tbl` ( + `document_index_int_id` int(10) unsigned NOT NULL, + `document_index_int_FK_document_detail_id` int(10) unsigned NOT NULL, + `document_index_int_name` varchar(100) NOT NULL, + `document_index_int_value` int(10) NOT NULL +) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `documents_index_int_tbl` +-- + +INSERT INTO `documents_index_int_tbl` (`document_index_int_id`, `document_index_int_FK_document_detail_id`, `document_index_int_name`, `document_index_int_value`) VALUES +(1, 1, 'id', 2), +(2, 2, 'id', 4), +(3, 3, 'id', 5), +(4, 4, 'id', 6), +(5, 5, 'id', 7), +(6, 6, 'id', 8), +(7, 7, 'id', 9), +(8, 8, 'id', 12), +(9, 9, 'id', 10), +(10, 10, 'id', 13), +(11, 11, 'id', 14), +(12, 12, 'id', 17), +(13, 13, 'id', 18), +(14, 14, 'id', 19), +(15, 15, 'id', 15), +(16, 16, 'id', 16); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `documents_index_text_tbl` +-- + +DROP TABLE IF EXISTS `documents_index_text_tbl`; +CREATE TABLE `documents_index_text_tbl` ( + `document_index_text_id` int(10) unsigned NOT NULL, + `document_index_text_FK_document_detail_id` int(10) unsigned NOT NULL, + `document_index_text_name` varchar(100) NOT NULL, + `document_index_text_value` varchar(255) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `documents_index_time_tbl` +-- + +DROP TABLE IF EXISTS `documents_index_time_tbl`; +CREATE TABLE `documents_index_time_tbl` ( + `document_index_time_id` int(10) unsigned NOT NULL, + `document_index_time_FK_document_detail_id` int(10) unsigned NOT NULL, + `document_index_time_name` varchar(100) NOT NULL, + `document_index_time_value` time NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `documents_tbl` +-- + +DROP TABLE IF EXISTS `documents_tbl`; +CREATE TABLE `documents_tbl` ( + `document_id` int(10) unsigned NOT NULL, + `document_type` varchar(255) DEFAULT NULL, + `document_creationDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `document_FK_site_id` int(10) unsigned DEFAULT NULL +) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `documents_tbl` +-- + +INSERT INTO `documents_tbl` (`document_id`, `document_type`, `document_creationDate`, `document_FK_site_id`) VALUES +(1, 'glizycms.content', '2015-12-15 22:32:36', NULL), +(2, 'glizycms.content', '2015-12-15 22:32:42', NULL), +(3, 'glizycms.content', '2015-12-15 22:32:48', NULL), +(4, 'glizycms.content', '2015-12-15 22:33:24', NULL), +(5, 'glizycms.content', '2015-12-15 22:33:35', NULL), +(6, 'glizycms.content', '2015-12-15 22:34:01', NULL), +(7, 'glizycms.content', '2015-12-15 22:35:00', NULL), +(8, 'glizycms.content', '2015-12-15 22:35:18', NULL), +(9, 'glizycms.content', '2015-12-15 22:35:26', NULL), +(10, 'glizycms.content', '2015-12-15 22:35:33', NULL), +(11, 'glizycms.content', '2015-12-15 22:35:55', NULL), +(12, 'glizycms.content', '2015-12-15 22:36:37', NULL), +(13, 'glizycms.content', '2015-12-15 22:36:50', NULL), +(14, 'glizycms.content', '2015-12-15 22:37:00', NULL), +(15, 'glizycms.content', '2015-12-15 22:37:10', NULL), +(16, 'glizycms.content', '2015-12-15 22:38:16', NULL); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `entity_properties_tbl` +-- + +DROP TABLE IF EXISTS `entity_properties_tbl`; +CREATE TABLE `entity_properties_tbl` ( + `entity_properties_id` int(10) unsigned NOT NULL, + `entity_properties_FK_entity_id` int(10) unsigned NOT NULL, + `entity_properties_type` varchar(100) NOT NULL, + `entity_properties_target_FK_entity_id` int(10) unsigned DEFAULT NULL, + `entity_properties_label_key` varchar(255) NOT NULL, + `entity_properties_required` tinyint(1) NOT NULL, + `entity_properties_show_label_in_frontend` tinyint(1) NOT NULL DEFAULT '1', + `entity_properties_relation_show` int(11) DEFAULT NULL COMMENT '0 = show images, 1 = show links, 2 = show images and links, 3 = hide', + `entity_properties_reference_relation_show` int(11) NOT NULL DEFAULT '0' COMMENT '0 = Show, 1 = Hide', + `entity_properties_dublic_core` varchar(100) DEFAULT NULL, + `entity_properties_row_index` int(10) NOT NULL, + `entity_properties_params` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `entity_tbl` +-- + +DROP TABLE IF EXISTS `entity_tbl`; +CREATE TABLE `entity_tbl` ( + `entity_id` int(10) unsigned NOT NULL, + `entity_name` varchar(255) NOT NULL, + `entity_show_relations_graph` tinyint(1) NOT NULL DEFAULT '1', + `entity_skin_attributes` text NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `joins_tbl` +-- + +DROP TABLE IF EXISTS `joins_tbl`; +CREATE TABLE `joins_tbl` ( + `join_id` int(1) unsigned NOT NULL, + `join_FK_source_id` int(10) unsigned NOT NULL, + `join_FK_dest_id` int(10) unsigned NOT NULL, + `join_objectName` varchar(50) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `languages_tbl` +-- + +DROP TABLE IF EXISTS `languages_tbl`; +CREATE TABLE `languages_tbl` ( + `language_id` int(10) unsigned NOT NULL, + `language_FK_site_id` int(10) unsigned DEFAULT NULL, + `language_name` varchar(100) NOT NULL DEFAULT '', + `language_code` varchar(10) NOT NULL DEFAULT '', + `language_FK_country_id` int(10) unsigned NOT NULL DEFAULT '0', + `language_isDefault` tinyint(1) unsigned NOT NULL DEFAULT '0', + `language_order` int(4) unsigned NOT NULL DEFAULT '0' +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `languages_tbl` +-- + +INSERT INTO `languages_tbl` (`language_id`, `language_FK_site_id`, `language_name`, `language_code`, `language_FK_country_id`, `language_isDefault`, `language_order`) VALUES +(1, NULL, 'English', 'en', 34, 1, 1); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `logs_tbl` +-- + +DROP TABLE IF EXISTS `logs_tbl`; +CREATE TABLE `logs_tbl` ( + `log_id` int(10) unsigned NOT NULL, + `log_level` varchar(100) NOT NULL DEFAULT '', + `log_date` datetime NOT NULL, + `log_ip` varchar(20) DEFAULT NULL, + `log_session` varchar(50) NOT NULL DEFAULT '', + `log_group` varchar(50) NOT NULL DEFAULT '', + `log_message` text NOT NULL, + `log_FK_user_id` int(10) DEFAULT '0', + `log_FK_site_id` int(10) unsigned DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mediadetails_tbl` +-- + +DROP TABLE IF EXISTS `mediadetails_tbl`; +CREATE TABLE `mediadetails_tbl` ( + `mediadetail_id` int(10) unsigned NOT NULL, + `mediadetail_FK_media_id` int(10) unsigned NOT NULL, + `media_FK_language_id` int(10) unsigned NOT NULL, + `media_FK_user_id` int(10) unsigned NOT NULL, + `media_modificationDate` datetime DEFAULT '0000-00-00 00:00:00', + `media_title` varchar(255) NOT NULL DEFAULT '', + `media_category` varchar(255) DEFAULT NULL, + `media_date` varchar(100) DEFAULT NULL, + `media_copyright` varchar(255) DEFAULT NULL, + `media_description` text +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `media_tbl` +-- + +DROP TABLE IF EXISTS `media_tbl`; +CREATE TABLE `media_tbl` ( + `media_id` int(10) unsigned NOT NULL, + `media_FK_site_id` int(10) unsigned DEFAULT NULL, + `media_creationDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `media_fileName` varchar(255) NOT NULL DEFAULT '', + `media_size` int(4) unsigned NOT NULL DEFAULT '0', + `media_type` enum('IMAGE','OFFICE','PDF','ARCHIVE','FLASH','AUDIO','VIDEO','OTHER') NOT NULL DEFAULT 'IMAGE', + `media_author` varchar(255) DEFAULT '', + `media_originalFileName` varchar(255) NOT NULL DEFAULT '', + `media_zoom` tinyint(1) DEFAULT '0', + `media_download` int(10) NOT NULL DEFAULT '0', + `media_watermark` tinyint(1) NOT NULL DEFAULT '0', + `media_allowDownload` tinyint(1) NOT NULL DEFAULT '1', + `media_thumbFileName` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `menudetails_tbl` +-- + +DROP TABLE IF EXISTS `menudetails_tbl`; +CREATE TABLE `menudetails_tbl` ( + `menudetail_id` int(10) unsigned NOT NULL, + `menudetail_FK_menu_id` int(10) unsigned NOT NULL DEFAULT '0', + `menudetail_FK_language_id` int(10) unsigned NOT NULL DEFAULT '0', + `menudetail_title` text NOT NULL, + `menudetail_keywords` text NOT NULL, + `menudetail_description` text NOT NULL, + `menudetail_subject` text NOT NULL, + `menudetail_creator` text NOT NULL, + `menudetail_publisher` text NOT NULL, + `menudetail_contributor` text NOT NULL, + `menudetail_type` text NOT NULL, + `menudetail_identifier` text NOT NULL, + `menudetail_source` text NOT NULL, + `menudetail_relation` text NOT NULL, + `menudetail_coverage` text NOT NULL, + `menudetail_isVisible` tinyint(1) unsigned NOT NULL DEFAULT '1', + `menudetail_titleLink` varchar(255) NOT NULL DEFAULT '', + `menudetail_linkDescription` varchar(255) NOT NULL DEFAULT '' +) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `menudetails_tbl` +-- + +INSERT INTO `menudetails_tbl` (`menudetail_id`, `menudetail_FK_menu_id`, `menudetail_FK_language_id`, `menudetail_title`, `menudetail_keywords`, `menudetail_description`, `menudetail_subject`, `menudetail_creator`, `menudetail_publisher`, `menudetail_contributor`, `menudetail_type`, `menudetail_identifier`, `menudetail_source`, `menudetail_relation`, `menudetail_coverage`, `menudetail_isVisible`, `menudetail_titleLink`, `menudetail_linkDescription`) VALUES +(1, 1, 1, 'Home', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(2, 2, 1, 'Metanavigation', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(3, 3, 1, 'Footer', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(4, 4, 1, 'Utility', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(5, 5, 1, 'Tools', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(6, 6, 1, 'Page 1', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(7, 7, 1, 'Page 2', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(8, 8, 1, 'Guide', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(9, 9, 1, 'Sitemap', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(10, 10, 1, 'Search', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(11, 11, 1, 'Logout', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(12, 12, 1, 'Lost password', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(13, 13, 1, 'My details', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(14, 14, 1, 'Contact', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(15, 15, 1, 'Home', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(16, 16, 1, 'Contact', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(17, 17, 1, 'Home', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(18, 18, 1, 'Sitemap', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''), +(19, 19, 1, 'Search', '', '', '', '', '', '', '', '', '', '', '', 1, '', ''); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `menus_tbl` +-- + +DROP TABLE IF EXISTS `menus_tbl`; +CREATE TABLE `menus_tbl` ( + `menu_id` int(10) unsigned NOT NULL, + `menu_FK_site_id` int(10) unsigned DEFAULT NULL, + `menu_parentId` int(10) unsigned DEFAULT '0', + `menu_pageType` varchar(100) NOT NULL DEFAULT '', + `menu_order` int(4) unsigned DEFAULT '0', + `menu_hasPreview` tinyint(1) unsigned DEFAULT '1', + `menu_creationDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `menu_modificationDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `menu_type` enum('HOMEPAGE','PAGE','SYSTEM') NOT NULL DEFAULT 'PAGE', + `menu_url` varchar(255) NOT NULL DEFAULT '', + `menu_isLocked` tinyint(1) unsigned NOT NULL DEFAULT '0', + `menu_hasComment` tinyint(1) NOT NULL DEFAULT '0', + `menu_printPdf` tinyint(1) NOT NULL DEFAULT '0', + `menu_extendsPermissions` tinyint(1) NOT NULL DEFAULT '0', + `menu_cssClass` varchar(255) DEFAULT NULL +) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `menus_tbl` +-- + +INSERT INTO `menus_tbl` (`menu_id`, `menu_FK_site_id`, `menu_parentId`, `menu_pageType`, `menu_order`, `menu_hasPreview`, `menu_creationDate`, `menu_modificationDate`, `menu_type`, `menu_url`, `menu_isLocked`, `menu_hasComment`, `menu_printPdf`, `menu_extendsPermissions`, `menu_cssClass`) VALUES +(1, NULL, 0, 'Home', 1, 1, '2015-01-01 12:00:00', '2015-01-01 12:00:00', 'HOMEPAGE', '', 0, 0, 0, 0, NULL), +(2, NULL, 1, 'Empty', 0, 1, '2015-01-01 12:00:00', '2015-12-15 22:32:37', 'SYSTEM', '', 0, 0, 0, 0, NULL), +(3, NULL, 1, 'Empty', 1, 1, '2015-01-01 12:00:00', '2015-01-01 12:00:00', 'SYSTEM', '', 0, 0, 0, 0, NULL), +(4, NULL, 1, 'Empty', 2, 1, '2015-01-01 12:00:00', '2015-12-15 22:32:43', 'SYSTEM', '', 0, 0, 0, 0, NULL), +(5, NULL, 1, 'Empty', 3, 1, '2015-01-01 12:00:00', '2015-12-15 22:32:48', 'SYSTEM', '', 0, 0, 0, 0, NULL), +(6, NULL, 1, 'Page', 4, 1, '2015-01-01 12:00:00', '2015-12-15 22:33:24', 'PAGE', '', 0, 0, 0, 0, NULL), +(7, NULL, 1, 'Page', 5, 1, '2015-01-01 12:00:00', '2015-12-15 22:33:35', 'PAGE', '', 0, 0, 0, 0, NULL), +(8, NULL, 4, 'Page', 1, 1, '2015-01-01 12:00:00', '2015-12-15 22:34:01', 'PAGE', '', 0, 0, 0, 0, NULL), +(9, NULL, 4, 'SiteMap', 2, 1, '2015-01-01 12:00:00', '2015-12-15 22:35:00', 'PAGE', '', 0, 0, 0, 0, NULL), +(10, NULL, 4, 'Search', 3, 1, '2015-01-01 12:00:00', '2015-12-15 22:35:26', 'PAGE', '', 0, 0, 0, 0, NULL), +(11, NULL, 4, 'Logout', 1, 1, '2015-01-01 12:00:00', '2015-01-01 12:00:00', 'SYSTEM', '', 0, 0, 0, 0, NULL), +(12, NULL, 4, 'LostPassword', 2, 1, '2015-01-01 12:00:00', '2015-12-15 22:35:18', 'SYSTEM', '', 0, 0, 0, 0, NULL), +(13, NULL, 4, 'UserDetails', 3, 1, '2015-01-01 12:00:00', '2015-12-15 22:35:33', 'SYSTEM', '', 0, 0, 0, 0, NULL), +(14, NULL, 4, 'Page', 4, 1, '2015-01-01 12:00:00', '2015-12-15 22:38:21', 'PAGE', '', 0, 0, 0, 0, NULL), +(15, NULL, 3, 'Alias', 1, 1, '2015-01-01 12:00:00', '2015-12-15 22:37:10', 'PAGE', 'alias:internal:1', 0, 0, 0, 0, NULL), +(16, NULL, 3, 'Alias', 2, 1, '2015-01-01 12:00:00', '2015-12-15 22:38:16', 'PAGE', 'alias:internal:14', 0, 0, 0, 0, NULL), +(17, NULL, 2, 'Alias', 3, 1, '2015-01-01 12:00:00', '2015-12-15 22:36:37', 'PAGE', 'alias:internal:1', 0, 0, 0, 0, NULL), +(18, NULL, 2, 'Alias', 4, 1, '2015-01-01 12:00:00', '2015-12-15 22:36:50', 'PAGE', 'alias:internal:9', 0, 0, 0, 0, NULL), +(19, NULL, 2, 'Alias', 5, 1, '2015-01-01 12:00:00', '2015-12-15 22:37:00', 'PAGE', 'alias:internal:10', 0, 0, 0, 0, NULL); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mobilecodes_tbl` +-- + +DROP TABLE IF EXISTS `mobilecodes_tbl`; +CREATE TABLE `mobilecodes_tbl` ( + `mobilecode_id` int(10) unsigned NOT NULL, + `mobilecode_code` varchar(100) NOT NULL, + `mobilecode_link` varchar(100) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mobilecontents_tbl` +-- + +DROP TABLE IF EXISTS `mobilecontents_tbl`; +CREATE TABLE `mobilecontents_tbl` ( + `content_id` int(10) unsigned NOT NULL, + `content_menuId` int(10) unsigned NOT NULL, + `content_documentId` int(10) unsigned NOT NULL, + `content_pageType` varchar(100) NOT NULL DEFAULT '', + `content_parent` int(10) unsigned DEFAULT '0', + `content_type` varchar(100) NOT NULL DEFAULT '', + `content_title` text NOT NULL, + `content_content` text NOT NULL +) ENGINE=InnoDB AUTO_INCREMENT=221 DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `mobilefulltext_tbl` +-- + +DROP TABLE IF EXISTS `mobilefulltext_tbl`; +CREATE TABLE `mobilefulltext_tbl` ( + `mobilefulltext_id` int(10) unsigned NOT NULL, + `mobilefulltext_FK_content_id` int(10) unsigned NOT NULL, + `mobilefulltext_text` longtext NOT NULL, + `mobilefulltext_title` varchar(255) NOT NULL, + `mobilefulltext_subtitle` varchar(255) DEFAULT NULL +) ENGINE=InnoDB AUTO_INCREMENT=206 DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `registry_tbl` +-- + +DROP TABLE IF EXISTS `registry_tbl`; +CREATE TABLE `registry_tbl` ( + `registry_id` int(11) NOT NULL, + `registry_FK_site_id` int(10) unsigned DEFAULT NULL, + `registry_path` varchar(255) NOT NULL DEFAULT '', + `registry_value` text NOT NULL +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `registry_tbl` +-- + +INSERT INTO `registry_tbl` (`registry_id`, `registry_FK_site_id`, `registry_path`, `registry_value`) VALUES +(1, NULL, 'movio/siteProp/it', 'a:7:{s:5:"title";s:5:"MOVIO";s:8:"subtitle";s:11:"Sottotitolo";s:7:"address";s:0:"";s:6:"footer";s:0:"";s:9:"slideShow";s:0:"";s:9:"analytics";s:0:"";s:7:"addthis";i:1;}'), +(2, NULL, 'movio/templateValues/Movio', '{"0":{"title1":"MOVIO","title2":"Sottotitolo","title3":"

Lorem ipsum dolor sit amet, consectetur adipiscing elit<\\/p>","title4":"

Omnia contraria, quos etiam insanos esse vultis.
Omnia contraria<\\/strong>, quos etiam insanos esse vultis.<\\/p>","font1":"default","font2":"default","c32308f7a298cab9fbf647f092db3fbd3":"0","c-body-background":"#FFFFFF","c-text":"#000000","c-text-heading":"#2F2F2F","c-color-link":"#CC3522","c-box-image-border":"#C6C6C6","c-metanavigation-background":"#CC3522","c-metanavigation-link":"#FFFFFF","c-metanavigation-background-hover":"#B82013","c-slider-background":"#CC3522","c-slider-text":"#FFFFFF","c-sidebar-background":"#F5F5F5","c-sidebar-background-hover":"#CC3522","c-sidebar-link":"#000000","c-sidebar-link-hover":"#FFFFFF","c-box-border":"#C6C6C6","c-box-background":"#FAFAFA","c-box-header-background":"#F3F3F3","c-box-header-link":"#000000","c-box-text":"#000000","c-icon-in-box":"#FFFFFF","c-icon-in-box-background":"#A1A1A1","c-color-border-button":"#D6D6D6","c-color-background-button":"#FFFFFF","c-color-arrow-button-slider":"#A1A1A1","c-color-arrow-button-slider-hover":"#CB3521","c-timeline-theme":"#CC3522","c-footer-background":"#363636","c-footer-border":"#5E5E5E","c-footer-text":"#FFFFFF","customCss":""}}'), +(3, NULL, 'movio/siteProp/en', 'a:7:{s:5:"title";s:10:"Demo Movio";s:8:"subtitle";s:0:"";s:7:"address";s:0:"";s:9:"copyright";s:0:"";s:9:"slideShow";s:0:"";s:9:"analytics";s:0:"";s:16:"googleMapsApiKey";s:0:"";}'); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `simple_documents_index_datetime_tbl` +-- + +DROP TABLE IF EXISTS `simple_documents_index_datetime_tbl`; +CREATE TABLE `simple_documents_index_datetime_tbl` ( + `simple_document_index_datetime_id` int(10) unsigned NOT NULL, + `simple_document_index_datetime_FK_simple_document_id` int(10) unsigned NOT NULL, + `simple_document_index_datetime_name` varchar(100) NOT NULL, + `simple_document_index_datetime_value` datetime NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `simple_documents_index_date_tbl` +-- + +DROP TABLE IF EXISTS `simple_documents_index_date_tbl`; +CREATE TABLE `simple_documents_index_date_tbl` ( + `simple_document_index_date_id` int(10) unsigned NOT NULL, + `simple_document_index_date_FK_simple_document_id` int(10) unsigned NOT NULL, + `simple_document_index_date_name` varchar(100) NOT NULL, + `simple_document_index_date_value` date NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `simple_documents_index_fulltext_tbl` +-- + +DROP TABLE IF EXISTS `simple_documents_index_fulltext_tbl`; +CREATE TABLE `simple_documents_index_fulltext_tbl` ( + `simple_document_index_fulltext_id` int(10) unsigned NOT NULL, + `simple_document_index_fulltext_FK_simple_document_id` int(10) unsigned NOT NULL, + `simple_document_index_fulltext_name` varchar(100) NOT NULL, + `simple_document_index_fulltext_value` text NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `simple_documents_index_int_tbl` +-- + +DROP TABLE IF EXISTS `simple_documents_index_int_tbl`; +CREATE TABLE `simple_documents_index_int_tbl` ( + `simple_document_index_int_id` int(10) unsigned NOT NULL, + `simple_document_index_int_FK_simple_document_id` int(10) unsigned NOT NULL, + `simple_document_index_int_name` varchar(100) NOT NULL, + `simple_document_index_int_value` int(10) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `simple_documents_index_text_tbl` +-- + +DROP TABLE IF EXISTS `simple_documents_index_text_tbl`; +CREATE TABLE `simple_documents_index_text_tbl` ( + `simple_document_index_text_id` int(10) unsigned NOT NULL, + `simple_document_index_text_FK_simple_document_id` int(10) unsigned NOT NULL, + `simple_document_index_text_name` varchar(100) NOT NULL, + `simple_document_index_text_value` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `simple_documents_index_time_tbl` +-- + +DROP TABLE IF EXISTS `simple_documents_index_time_tbl`; +CREATE TABLE `simple_documents_index_time_tbl` ( + `simple_document_index_time_id` int(10) unsigned NOT NULL, + `simple_document_index_time_FK_simple_document_id` int(10) unsigned NOT NULL, + `simple_document_index_time_name` varchar(100) NOT NULL, + `simple_document_index_time_value` time NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `simple_documents_tbl` +-- + +DROP TABLE IF EXISTS `simple_documents_tbl`; +CREATE TABLE `simple_documents_tbl` ( + `simple_document_id` int(10) unsigned NOT NULL, + `simple_document_FK_site_id` int(10) unsigned DEFAULT NULL, + `simple_document_type` varchar(255) NOT NULL, + `simple_document_object` text NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `speakingurls_tbl` +-- + +DROP TABLE IF EXISTS `speakingurls_tbl`; +CREATE TABLE `speakingurls_tbl` ( + `speakingurl_id` int(10) unsigned NOT NULL, + `speakingurl_FK_language_id` int(10) unsigned NOT NULL, + `speakingurl_FK_site_id` int(10) unsigned DEFAULT NULL, + `speakingurl_FK` int(10) unsigned NOT NULL, + `speakingurl_type` varchar(255) NOT NULL, + `speakingurl_value` varchar(255) NOT NULL, + `speakingurl_option` varchar(255) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `usergroups_tbl` +-- + +DROP TABLE IF EXISTS `usergroups_tbl`; +CREATE TABLE `usergroups_tbl` ( + `usergroup_id` int(11) NOT NULL, + `usergroup_name` varchar(50) NOT NULL DEFAULT '', + `usergroup_backEndAccess` tinyint(1) NOT NULL DEFAULT '0', + `usergroup_FK_site_id` int(10) unsigned DEFAULT NULL +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `usergroups_tbl` +-- + +INSERT INTO `usergroups_tbl` (`usergroup_id`, `usergroup_name`, `usergroup_backEndAccess`, `usergroup_FK_site_id`) VALUES +(1, 'Administrator', 1, 1), +(2, 'Supervisor', 1, 1), +(3, 'Editor', 1, 1), +(4, 'User', 0, 1); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `userlogs_tbl` +-- + +DROP TABLE IF EXISTS `userlogs_tbl`; +CREATE TABLE `userlogs_tbl` ( + `userlog_id` int(10) unsigned NOT NULL, + `userlog_FK_user_id` int(10) unsigned NOT NULL DEFAULT '0', + `userlog_FK_site_id` int(10) unsigned DEFAULT NULL, + `userlog_session` varchar(50) NOT NULL DEFAULT '', + `userlog_ip` varchar(50) NOT NULL DEFAULT '', + `userlog_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `userlog_lastAction` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- -------------------------------------------------------- + +-- +-- Table structure for table `users_tbl` +-- + +DROP TABLE IF EXISTS `users_tbl`; +CREATE TABLE `users_tbl` ( + `user_id` int(10) unsigned NOT NULL, + `user_FK_usergroup_id` int(10) unsigned NOT NULL DEFAULT '2', + `user_FK_site_id` int(10) unsigned DEFAULT NULL, + `user_dateCreation` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `user_isActive` tinyint(1) unsigned NOT NULL DEFAULT '1', + `user_loginId` varchar(100) NOT NULL DEFAULT '', + `user_password` varchar(100) NOT NULL DEFAULT '', + `user_firstName` varchar(100) NOT NULL DEFAULT '', + `user_lastName` varchar(100) NOT NULL DEFAULT '', + `user_title` varchar(50) DEFAULT NULL, + `user_companyName` varchar(255) DEFAULT NULL, + `user_address` varchar(255) DEFAULT NULL, + `user_city` varchar(255) DEFAULT NULL, + `user_zip` varchar(20) DEFAULT NULL, + `user_state` varchar(100) DEFAULT NULL, + `user_country` varchar(100) DEFAULT NULL, + `user_FK_country_id` int(50) DEFAULT '0', + `user_phone` varchar(100) DEFAULT NULL, + `user_phone2` varchar(50) DEFAULT NULL, + `user_mobile` varchar(50) DEFAULT NULL, + `user_fax` varchar(100) DEFAULT NULL, + `user_email` varchar(255) NOT NULL DEFAULT '', + `user_www` varchar(255) DEFAULT NULL, + `user_birthday` date NOT NULL DEFAULT '0000-00-00', + `user_sex` enum('M','F') DEFAULT 'M', + `user_confirmCode` varchar(200) DEFAULT NULL, + `user_wantNewsletter` tinyint(1) unsigned DEFAULT '1', + `user_isInMailinglist` tinyint(1) unsigned DEFAULT '0', + `user_position` varchar(255) DEFAULT NULL, + `user_department` varchar(255) DEFAULT NULL, + `user_extid` int(10) unsigned NOT NULL, + `user_fiscalCode` varchar(32) NOT NULL DEFAULT '', + `user_vat` varchar(32) NOT NULL DEFAULT '' +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `users_tbl` +-- + +INSERT INTO `users_tbl` (`user_id`, `user_FK_usergroup_id`, `user_FK_site_id`, `user_dateCreation`, `user_isActive`, `user_loginId`, `user_password`, `user_firstName`, `user_lastName`, `user_title`, `user_companyName`, `user_address`, `user_city`, `user_zip`, `user_state`, `user_country`, `user_FK_country_id`, `user_phone`, `user_phone2`, `user_mobile`, `user_fax`, `user_email`, `user_www`, `user_birthday`, `user_sex`, `user_confirmCode`, `user_wantNewsletter`, `user_isInMailinglist`, `user_position`, `user_department`, `user_extid`, `user_fiscalCode`, `user_vat`) VALUES +(1, 1, NULL, '2015-01-01 12:00:00', 1, 'admin', '21232f297a57a5a743894a0e4a801fc3', 'Amministratore', 'sito', '', 'Istituzione', '', '', '', '', NULL, 0, '', '', '', '', 'admin', '', '2015-01-01', 'M', '', 1, 1, '', '', 0, '', ''); + +-- +-- Indexes for dumped tables +-- + +-- +-- Indexes for table `countries_tbl` +-- +ALTER TABLE `countries_tbl` + ADD PRIMARY KEY (`country_id`); + +-- +-- Indexes for table `custom_code_mapping_tbl` +-- +ALTER TABLE `custom_code_mapping_tbl` + ADD PRIMARY KEY (`custom_code_mapping_id`); + +-- +-- Indexes for table `documents_detail_tbl` +-- +ALTER TABLE `documents_detail_tbl` + ADD PRIMARY KEY (`document_detail_id`), + ADD KEY `document_detail_fk_document_id` (`document_detail_FK_document_id`), + ADD KEY `document_detail_fk_language_id` (`document_detail_FK_language_id`), + ADD KEY `document_detail_fk_user_id` (`document_detail_FK_user_id`), + ADD KEY `document_detail_status` (`document_detail_status`); + +-- +-- Indexes for table `documents_index_datetime_tbl` +-- +ALTER TABLE `documents_index_datetime_tbl` + ADD PRIMARY KEY (`document_index_datetime_id`), + ADD KEY `document_index_datetime_fk` (`document_index_datetime_FK_document_detail_id`), + ADD KEY `document_index_datetime_name` (`document_index_datetime_name`), + ADD KEY `document_index_datetime_value` (`document_index_datetime_value`); + +-- +-- Indexes for table `documents_index_date_tbl` +-- +ALTER TABLE `documents_index_date_tbl` + ADD PRIMARY KEY (`document_index_date_id`), + ADD KEY `document_index_date_name` (`document_index_date_name`), + ADD KEY `document_index_date_value` (`document_index_date_value`), + ADD KEY `document_index_date_fk` (`document_index_date_FK_document_detail_id`) USING BTREE; + +-- +-- Indexes for table `documents_index_fulltext_tbl` +-- +ALTER TABLE `documents_index_fulltext_tbl` + ADD PRIMARY KEY (`document_index_fulltext_id`), + ADD KEY `document_index_fulltext_name` (`document_index_fulltext_name`), + ADD KEY `document_index_fulltext_fk` (`document_index_fulltext_FK_document_detail_id`) USING BTREE, + ADD FULLTEXT KEY `document_index_fulltext_value` (`document_index_fulltext_value`); + +-- +-- Indexes for table `documents_index_int_tbl` +-- +ALTER TABLE `documents_index_int_tbl` + ADD PRIMARY KEY (`document_index_int_id`), + ADD KEY `document_index_int_fk` (`document_index_int_FK_document_detail_id`), + ADD KEY `document_index_int_name` (`document_index_int_name`), + ADD KEY `document_index_int_value` (`document_index_int_value`); + +-- +-- Indexes for table `documents_index_text_tbl` +-- +ALTER TABLE `documents_index_text_tbl` + ADD PRIMARY KEY (`document_index_text_id`), + ADD KEY `document_index_text_fk` (`document_index_text_FK_document_detail_id`), + ADD KEY `document_index_text_name` (`document_index_text_name`), + ADD KEY `document_index_text_value` (`document_index_text_value`); + +-- +-- Indexes for table `documents_index_time_tbl` +-- +ALTER TABLE `documents_index_time_tbl` + ADD PRIMARY KEY (`document_index_time_id`), + ADD KEY `document_index_time_fk` (`document_index_time_FK_document_detail_id`), + ADD KEY `document_index_time_name` (`document_index_time_name`), + ADD KEY `document_index_time_value` (`document_index_time_value`); + +-- +-- Indexes for table `documents_tbl` +-- +ALTER TABLE `documents_tbl` + ADD PRIMARY KEY (`document_id`), + ADD KEY `document_type` (`document_type`), + ADD KEY `document_FK_site_id` (`document_FK_site_id`); + +-- +-- Indexes for table `entity_properties_tbl` +-- +ALTER TABLE `entity_properties_tbl` + ADD PRIMARY KEY (`entity_properties_id`), + ADD KEY `entity_properties_fk_entity_id` (`entity_properties_FK_entity_id`), + ADD KEY `entity_properties_target_fk_entity_id` (`entity_properties_target_FK_entity_id`); + +-- +-- Indexes for table `entity_tbl` +-- +ALTER TABLE `entity_tbl` + ADD PRIMARY KEY (`entity_id`); + +-- +-- Indexes for table `joins_tbl` +-- +ALTER TABLE `joins_tbl` + ADD PRIMARY KEY (`join_id`), + ADD KEY `join_FK_source_id` (`join_FK_source_id`), + ADD KEY `join_FK_dest_id` (`join_FK_dest_id`), + ADD KEY `join_objectName` (`join_objectName`); + +-- +-- Indexes for table `languages_tbl` +-- +ALTER TABLE `languages_tbl` + ADD PRIMARY KEY (`language_id`), + ADD KEY `language_FK_country_id` (`language_FK_country_id`), + ADD KEY `language_isDefault` (`language_isDefault`), + ADD KEY `language_order` (`language_order`); + +-- +-- Indexes for table `logs_tbl` +-- +ALTER TABLE `logs_tbl` + ADD PRIMARY KEY (`log_id`), + ADD KEY `log_level` (`log_level`), + ADD KEY `log_group` (`log_group`), + ADD KEY `log_FK_user_id` (`log_FK_user_id`), + ADD KEY `log_FK_site_id` (`log_FK_site_id`); + +-- +-- Indexes for table `mediadetails_tbl` +-- +ALTER TABLE `mediadetails_tbl` + ADD PRIMARY KEY (`mediadetail_id`), + ADD KEY `mediadetail_FK_media_id` (`mediadetail_FK_media_id`), + ADD KEY `media_FK_language_id` (`media_FK_language_id`), + ADD KEY `media_FK_user_id` (`media_FK_user_id`); + +-- +-- Indexes for table `media_tbl` +-- +ALTER TABLE `media_tbl` + ADD PRIMARY KEY (`media_id`), + ADD KEY `media_FK_site_id` (`media_FK_site_id`), + ADD KEY `media_type` (`media_type`); + +-- +-- Indexes for table `menudetails_tbl` +-- +ALTER TABLE `menudetails_tbl` + ADD PRIMARY KEY (`menudetail_id`), + ADD KEY `menudetail_FK_menu_id` (`menudetail_FK_menu_id`), + ADD KEY `menudetail_FK_language_id` (`menudetail_FK_language_id`); + +-- +-- Indexes for table `menus_tbl` +-- +ALTER TABLE `menus_tbl` + ADD PRIMARY KEY (`menu_id`), + ADD KEY `menu_FK_site_id` (`menu_FK_site_id`), + ADD KEY `menu_parentId` (`menu_parentId`), + ADD KEY `menu_pageType` (`menu_pageType`); + +-- +-- Indexes for table `mobilecodes_tbl` +-- +ALTER TABLE `mobilecodes_tbl` + ADD PRIMARY KEY (`mobilecode_id`); + +-- +-- Indexes for table `mobilecontents_tbl` +-- +ALTER TABLE `mobilecontents_tbl` + ADD PRIMARY KEY (`content_id`), + ADD KEY `content_menuId` (`content_menuId`), + ADD KEY `content_documentId` (`content_documentId`), + ADD KEY `content_parent` (`content_parent`); + +-- +-- Indexes for table `mobilefulltext_tbl` +-- +ALTER TABLE `mobilefulltext_tbl` + ADD PRIMARY KEY (`mobilefulltext_id`); + +-- +-- Indexes for table `registry_tbl` +-- +ALTER TABLE `registry_tbl` + ADD PRIMARY KEY (`registry_id`), + ADD KEY `registry_path` (`registry_path`); + +-- +-- Indexes for table `simple_documents_index_datetime_tbl` +-- +ALTER TABLE `simple_documents_index_datetime_tbl` + ADD PRIMARY KEY (`simple_document_index_datetime_id`), + ADD KEY `simple_document_index_datetime_name` (`simple_document_index_datetime_name`) USING BTREE, + ADD KEY `simple_document_index_datetime_value` (`simple_document_index_datetime_value`) USING BTREE, + ADD KEY `simple_document_index_datetime_fk` (`simple_document_index_datetime_FK_simple_document_id`) USING BTREE; + +-- +-- Indexes for table `simple_documents_index_date_tbl` +-- +ALTER TABLE `simple_documents_index_date_tbl` + ADD PRIMARY KEY (`simple_document_index_date_id`), + ADD KEY `simple_document_index_date_fk` (`simple_document_index_date_FK_simple_document_id`), + ADD KEY `simple_document_index_date_value` (`simple_document_index_date_value`), + ADD KEY `simple_document_index_date_name` (`simple_document_index_date_name`) USING BTREE; + +-- +-- Indexes for table `simple_documents_index_fulltext_tbl` +-- +ALTER TABLE `simple_documents_index_fulltext_tbl` + ADD PRIMARY KEY (`simple_document_index_fulltext_id`), + ADD KEY `simple_document_index_fulltext_name` (`simple_document_index_fulltext_name`), + ADD KEY `simple_document_index_fulltext_fk` (`simple_document_index_fulltext_FK_simple_document_id`) USING BTREE, + ADD FULLTEXT KEY `simple_document_index_fulltext_value` (`simple_document_index_fulltext_value`); + +-- +-- Indexes for table `simple_documents_index_int_tbl` +-- +ALTER TABLE `simple_documents_index_int_tbl` + ADD PRIMARY KEY (`simple_document_index_int_id`), + ADD KEY `simple_document_index_int_fk` (`simple_document_index_int_FK_simple_document_id`), + ADD KEY `simple_document_index_int_value` (`simple_document_index_int_value`), + ADD KEY `simple_document_index_int_name` (`simple_document_index_int_name`) USING BTREE; + +-- +-- Indexes for table `simple_documents_index_text_tbl` +-- +ALTER TABLE `simple_documents_index_text_tbl` + ADD PRIMARY KEY (`simple_document_index_text_id`), + ADD KEY `simple_document_index_text_fk` (`simple_document_index_text_FK_simple_document_id`), + ADD KEY `simple_document_index_text_value` (`simple_document_index_text_value`), + ADD KEY `simple_document_index_text_name` (`simple_document_index_text_name`) USING BTREE; + +-- +-- Indexes for table `simple_documents_index_time_tbl` +-- +ALTER TABLE `simple_documents_index_time_tbl` + ADD PRIMARY KEY (`simple_document_index_time_id`), + ADD KEY `simple_document_index_time_fk` (`simple_document_index_time_FK_simple_document_id`), + ADD KEY `simple_document_index_time_name` (`simple_document_index_time_name`) USING BTREE, + ADD KEY `simple_document_index_time_value` (`simple_document_index_time_value`); + +-- +-- Indexes for table `simple_documents_tbl` +-- +ALTER TABLE `simple_documents_tbl` + ADD PRIMARY KEY (`simple_document_id`), + ADD KEY `simple_document_type` (`simple_document_type`), + ADD KEY `simple_document_FK_site_id` (`simple_document_FK_site_id`); + +-- +-- Indexes for table `speakingurls_tbl` +-- +ALTER TABLE `speakingurls_tbl` + ADD PRIMARY KEY (`speakingurl_id`), + ADD KEY `speakingurl_FK_language_id` (`speakingurl_FK_language_id`), + ADD KEY `speakingurl_FK` (`speakingurl_FK`), + ADD KEY `speakingurl_type` (`speakingurl_type`), + ADD KEY `speakingurl_FK_site_id` (`speakingurl_FK_site_id`); + +-- +-- Indexes for table `usergroups_tbl` +-- +ALTER TABLE `usergroups_tbl` + ADD PRIMARY KEY (`usergroup_id`), + ADD KEY `usergroup_FK_site_id` (`usergroup_FK_site_id`); + +-- +-- Indexes for table `userlogs_tbl` +-- +ALTER TABLE `userlogs_tbl` + ADD PRIMARY KEY (`userlog_id`), + ADD UNIQUE KEY `userlog_FK_user_id` (`userlog_FK_user_id`), + ADD KEY `userlog_FK_site_id` (`userlog_FK_site_id`); + +-- +-- Indexes for table `users_tbl` +-- +ALTER TABLE `users_tbl` + ADD PRIMARY KEY (`user_id`), + ADD KEY `user_FK_usergroup_id` (`user_FK_usergroup_id`), + ADD KEY `user_FK_site_id` (`user_FK_site_id`), + ADD KEY `user_extid` (`user_extid`); + +-- +-- AUTO_INCREMENT for dumped tables +-- + +-- +-- AUTO_INCREMENT for table `countries_tbl` +-- +ALTER TABLE `countries_tbl` + MODIFY `country_id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=161; +-- +-- AUTO_INCREMENT for table `custom_code_mapping_tbl` +-- +ALTER TABLE `custom_code_mapping_tbl` + MODIFY `custom_code_mapping_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `documents_detail_tbl` +-- +ALTER TABLE `documents_detail_tbl` + MODIFY `document_detail_id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=17; +-- +-- AUTO_INCREMENT for table `documents_index_datetime_tbl` +-- +ALTER TABLE `documents_index_datetime_tbl` + MODIFY `document_index_datetime_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `documents_index_date_tbl` +-- +ALTER TABLE `documents_index_date_tbl` + MODIFY `document_index_date_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `documents_index_fulltext_tbl` +-- +ALTER TABLE `documents_index_fulltext_tbl` + MODIFY `document_index_fulltext_id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=18; +-- +-- AUTO_INCREMENT for table `documents_index_int_tbl` +-- +ALTER TABLE `documents_index_int_tbl` + MODIFY `document_index_int_id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=17; +-- +-- AUTO_INCREMENT for table `documents_index_text_tbl` +-- +ALTER TABLE `documents_index_text_tbl` + MODIFY `document_index_text_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `documents_index_time_tbl` +-- +ALTER TABLE `documents_index_time_tbl` + MODIFY `document_index_time_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `documents_tbl` +-- +ALTER TABLE `documents_tbl` + MODIFY `document_id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=17; +-- +-- AUTO_INCREMENT for table `entity_properties_tbl` +-- +ALTER TABLE `entity_properties_tbl` + MODIFY `entity_properties_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `entity_tbl` +-- +ALTER TABLE `entity_tbl` + MODIFY `entity_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `joins_tbl` +-- +ALTER TABLE `joins_tbl` + MODIFY `join_id` int(1) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `languages_tbl` +-- +ALTER TABLE `languages_tbl` + MODIFY `language_id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=2; +-- +-- AUTO_INCREMENT for table `mediadetails_tbl` +-- +ALTER TABLE `mediadetails_tbl` + MODIFY `mediadetail_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `media_tbl` +-- +ALTER TABLE `media_tbl` + MODIFY `media_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `menudetails_tbl` +-- +ALTER TABLE `menudetails_tbl` + MODIFY `menudetail_id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=20; +-- +-- AUTO_INCREMENT for table `menus_tbl` +-- +ALTER TABLE `menus_tbl` + MODIFY `menu_id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=20; +-- +-- AUTO_INCREMENT for table `mobilecodes_tbl` +-- +ALTER TABLE `mobilecodes_tbl` + MODIFY `mobilecode_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `mobilecontents_tbl` +-- +ALTER TABLE `mobilecontents_tbl` + MODIFY `content_id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=221; +-- +-- AUTO_INCREMENT for table `mobilefulltext_tbl` +-- +ALTER TABLE `mobilefulltext_tbl` + MODIFY `mobilefulltext_id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=206; +-- +-- AUTO_INCREMENT for table `registry_tbl` +-- +ALTER TABLE `registry_tbl` + MODIFY `registry_id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=4; +-- +-- AUTO_INCREMENT for table `simple_documents_index_datetime_tbl` +-- +ALTER TABLE `simple_documents_index_datetime_tbl` + MODIFY `simple_document_index_datetime_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `simple_documents_index_date_tbl` +-- +ALTER TABLE `simple_documents_index_date_tbl` + MODIFY `simple_document_index_date_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `simple_documents_index_fulltext_tbl` +-- +ALTER TABLE `simple_documents_index_fulltext_tbl` + MODIFY `simple_document_index_fulltext_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `simple_documents_index_int_tbl` +-- +ALTER TABLE `simple_documents_index_int_tbl` + MODIFY `simple_document_index_int_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `simple_documents_index_text_tbl` +-- +ALTER TABLE `simple_documents_index_text_tbl` + MODIFY `simple_document_index_text_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `simple_documents_index_time_tbl` +-- +ALTER TABLE `simple_documents_index_time_tbl` + MODIFY `simple_document_index_time_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `simple_documents_tbl` +-- +ALTER TABLE `simple_documents_tbl` + MODIFY `simple_document_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `usergroups_tbl` +-- +ALTER TABLE `usergroups_tbl` + MODIFY `usergroup_id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=8; +-- +-- AUTO_INCREMENT for table `userlogs_tbl` +-- +ALTER TABLE `userlogs_tbl` + MODIFY `userlog_id` int(10) unsigned NOT NULL AUTO_INCREMENT; +-- +-- AUTO_INCREMENT for table `users_tbl` +-- +ALTER TABLE `users_tbl` + MODIFY `user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/src/.htaccess b/src/.htaccess new file mode 100644 index 0000000..d4c5df9 --- /dev/null +++ b/src/.htaccess @@ -0,0 +1,11 @@ + + RewriteEngine On + RewriteRule ^(ajax\.php|static/|cache/|favicon\.ico) - [L] + + RewriteRule ^application/.*\.js - [L] + RewriteRule ^application/mediaArchive - [L] + RewriteRule ^application(/|$) - [F,NC] + + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^(.*)$ index.php [QSA,L] + \ No newline at end of file diff --git a/src/admin/.htaccess b/src/admin/.htaccess new file mode 100644 index 0000000..a227f16 --- /dev/null +++ b/src/admin/.htaccess @@ -0,0 +1,13 @@ + + RewriteEngine On + RewriteRule ^(ajax\.php|static/|cache/|favicon\.ico) - [L] + + RewriteRule ^application/.*\.js - [L] + RewriteRule ^application/templates - [L] + RewriteRule ^application(/|$) - [F,NC] + + RewriteRule ^proxy/(.*)$ ajax.php?pageId=contentseditor&ajaxTarget=Page&action=GetUrl&url=$1 [QSA,L] + RewriteRule ^rest/(.*)$ rest.php?$1 [QSA,L] + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^(.*)$ index.php [QSA,L] + \ No newline at end of file diff --git a/src/admin/ajax.php b/src/admin/ajax.php new file mode 100644 index 0000000..8220bf1 --- /dev/null +++ b/src/admin/ajax.php @@ -0,0 +1,10 @@ +useXmlSiteMap = true; +$application->setLanguage('it'); +$application->runAjax(); diff --git a/src/admin/application/classes/movio/controllers/index.html b/src/admin/application/classes/movio/controllers/index.html new file mode 100644 index 0000000..e69de29 diff --git a/src/admin/application/classes/movio/models/Mobilecontents.xml b/src/admin/application/classes/movio/models/Mobilecontents.xml new file mode 100644 index 0000000..fbd9e04 --- /dev/null +++ b/src/admin/application/classes/movio/models/Mobilecontents.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/models/index.html b/src/admin/application/classes/movio/models/index.html new file mode 100644 index 0000000..e69de29 diff --git a/src/admin/application/classes/movio/modules/codes/controllers/MakeQRCode.php b/src/admin/application/classes/movio/modules/codes/controllers/MakeQRCode.php new file mode 100644 index 0000000..6fcbf35 --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/controllers/MakeQRCode.php @@ -0,0 +1,30 @@ +load($id); + $codeType = $ar->custom_code_mapping_code ? 'c' : 'm'; + $value = $codeType == 'c' ? $ar->custom_code_mapping_code : $ar->custom_code_mapping_link; + + $codeContents = GLZ_HOST_ROOT.':'.$codeType.':'.$value; + $filePath = __Paths::get('CACHE').$id.'.png'; + + QRcode::png($codeContents, $filePath, QR_ECLEVEL_H, 4); + + header("Pragma: public"); + header("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); + header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); + header("Cache-Control: private",false); + header("Content-Type: image/png"); + header("Content-Transfer-Encoding: binary"); + header("Content-Disposition: attachment; filename=\"".$id.'.png'."\""); + @readfile($filePath) or die(); + } + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/codes/controllers/ajax/Del.php b/src/admin/application/classes/movio/modules/codes/controllers/ajax/Del.php new file mode 100644 index 0000000..1cbaf76 --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/controllers/ajax/Del.php @@ -0,0 +1,12 @@ +delete($id); + + return true; + } +} diff --git a/src/admin/application/classes/movio/modules/codes/controllers/ajax/Load.php b/src/admin/application/classes/movio/modules/codes/controllers/ajax/Load.php new file mode 100644 index 0000000..878d361 --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/controllers/ajax/Load.php @@ -0,0 +1,36 @@ + array() + ); + + foreach($it as $ar) { + $id = $ar->getId(); + + $item = array( + 'id' => $id, + 'description' => $ar->custom_code_mapping_description, + 'code' => $ar->custom_code_mapping_code, + 'resourceLink' => $ar->custom_code_mapping_link, + ); + + if ($ar->custom_code_mapping_link) { + $speakingUrlManager = $this->application->retrieveProxy('org.glizycms.speakingUrl.Manager'); + $docs = $speakingUrlManager->searchDocumentsByTerm('', $ar->custom_code_mapping_link); + $item['resourceLinkLabel'] = $docs[0]['text']; + $item['downloadQrCode'] = __Link::makeUrl('actionsMVC', array('action' => 'makeQRCode', 'id' => $id)); + } + + $result['items'][] = $item; + } + + return $result; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/codes/controllers/ajax/New.php b/src/admin/application/classes/movio/modules/codes/controllers/ajax/New.php new file mode 100644 index 0000000..a736ff9 --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/controllers/ajax/New.php @@ -0,0 +1,14 @@ +custom_code_mapping_description = $custom_code_mapping_description; + $ar->custom_code_mapping_code = $custom_code_mapping_code; + $ar->custom_code_mapping_link = $custom_code_mapping_link; + $id = $ar->save(); + return $id; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/codes/controllers/ajax/Set.php b/src/admin/application/classes/movio/modules/codes/controllers/ajax/Set.php new file mode 100644 index 0000000..9693953 --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/controllers/ajax/Set.php @@ -0,0 +1,13 @@ +load($pk)) { + $ar->$name = $value; + $ar->save(); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/codes/models/Model.xml b/src/admin/application/classes/movio/modules/codes/models/Model.xml new file mode 100644 index 0000000..e5281cc --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/models/Model.xml @@ -0,0 +1,6 @@ + + + diff --git a/src/admin/application/classes/movio/modules/codes/views/Admin.xml b/src/admin/application/classes/movio/modules/codes/views/Admin.xml new file mode 100644 index 0000000..232923a --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/views/Admin.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/codes/views/js/CodesEditor.js b/src/admin/application/classes/movio/modules/codes/views/js/CodesEditor.js new file mode 100755 index 0000000..aa832f3 --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/views/js/CodesEditor.js @@ -0,0 +1,4 @@ +GlizyApp.pages[ 'movio.modules.codes.views.Admin' ] = function( state, routing ) { + CodesEditorLoader.start(); + CodesEditorLoader.load(); +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/codes/views/js/CodesEditorLoader.js b/src/admin/application/classes/movio/modules/codes/views/js/CodesEditorLoader.js new file mode 100755 index 0000000..eefb44a --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/views/js/CodesEditorLoader.js @@ -0,0 +1,166 @@ +var CodesEditorLoader = new Object(); +CodesEditorLoader = { + start: function() + { + //turn to inline mode + $.fn.editable.defaults.mode = 'inline'; + + $('.js-addButton').live('click', function( event ) { + event.preventDefault(); + CodesEditorLoader.addRow(); + }); + + $('.js-removeButton').live('click', function( event ) { + CodesEditorLoader.deleteRow($(this).closest('tr')); + }); + + $('.js-saveButton').live('click', function(event) { + var saveButton = this; + $(this).closest('tr').find('a').editable('submit', { + url: Glizy.ajaxUrl + 'New', + ajaxOptions: { + dataType: 'json' //assuming json response + }, + success: function(data, config) { + if (data) { + var id = data.result; + //set pk + $(this).closest('tr').find('a[data-type]').editable('option', 'pk', id); + //remove unsaved class + $(this).removeClass('editable-unsaved'); + $(saveButton).hide(); + $(this).off('save.newuser'); + var $link = $(this).last(); + $link.attr('href','codes/MakeQRCode/'+id); + $link.text('Download'); + } + } + }); + }); + }, + + load: function() + { + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "Load", + dataType: "json", + success: function (data) { + var data = data.result; + CodesEditorLoader.show(data); + } + }); + }, + + getTemplate: function() + { + Handlebars.registerHelper('notNull', function(item, block) { + return (item !== null) ? block.fn(this) : block.inverse(this); + }); + + Handlebars.registerPartial('item', $('#item').html()); + + var source = $('#codes-editor-template').html(); + + return Handlebars.compile(source); + }, + + initEditableFields: function(selector) { + $(selector).editable({ + url: Glizy.ajaxUrl + 'Set', + emptytext: GlizyLocale.CodesEditorLoader.emptyText + }); + }, + + initSelect2: function(selector) { + $(selector).editable({ + url: Glizy.ajaxUrl + 'Set', + emptytext: GlizyLocale.CodesEditorLoader.emptyText, + select2: { + width: 'element', + placeholder: '', + allowClear: true, + minimumInputLength: 3, + ajax: { + url: Glizy.ajaxUrl + "&controllerName=org.glizycms.contents.controllers.autocomplete.ajax.PagePicker", + dataType: 'json', + quietMillis: 100, + data: function(term) { + return { + term: term + }; + }, + results: function(data, page ) { + return { results: data } + } + }, + formatResult: function(data) { + return data.text+'
'+data.path+''; + }, + formatSelection: function(data) { + return data.text; + } + } + }); + }, + + show: function(data) + { + data.locale = GlizyLocale.CodesEditorLoader; + + // setta il locale per ogni item + $.each(data['items'], function(index, item) { + item.locale = GlizyLocale.CodesEditorLoader; + }); + + var template = CodesEditorLoader.getTemplate(); + var html = template(data); + $("#admincontent").append(html); + + CodesEditorLoader.initEditableFields('#editTable > tbody a[data-type=text],#editTable > tbody a[data-type=textarea]'); + CodesEditorLoader.initSelect2('.js-resourceLink'); + }, + + addRow: function() + { + var source = $('#item').html(); + var template = Handlebars.compile(source); + var item = { + isNew: true, + id: null, + description: null, + code: null, + resourceLink: null, + downloadQrCode: null, + locale: GlizyLocale.CodesEditorLoader + }; + + var html = template(item); + $('#editTable tbody').append(html); + + CodesEditorLoader.initEditableFields('#editTable > tbody a[data-type=text],#editTable > tbody a[data-type=textarea]'); + CodesEditorLoader.initSelect2('.js-resourceLink'); + }, + + deleteRow: function(row) + { + if (confirm(GlizyLocale.CodesEditorLoader.delConfirm)) { + var id = $(row).find('a:first').data("pk"); + + if (id === null) { + row.remove(); + return; + } + + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "Del", + dataType: "json", + data: {id: id}, + success: function (data) { + row.remove(); + } + }); + } + }, +} diff --git a/src/admin/application/classes/movio/modules/codes/views/js/locale/en-EN.js b/src/admin/application/classes/movio/modules/codes/views/js/locale/en-EN.js new file mode 100644 index 0000000..0b515c6 --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/views/js/locale/en-EN.js @@ -0,0 +1,12 @@ +GlizyLocale.CodesEditorLoader = { + description: 'Description', + code: 'Code', + resourceLink: 'Resource link', + emptyText: 'Empty', + requiredField: 'This field is required', + oneToOne: 'One to one', + oneToMany: 'One to many', + delConfirm: 'Are you sure you want to delete this mapping?', + saveButton: 'Save', + addNewButton: 'New code' +}; \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/codes/views/js/locale/it-IT.js b/src/admin/application/classes/movio/modules/codes/views/js/locale/it-IT.js new file mode 100644 index 0000000..05bf655 --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/views/js/locale/it-IT.js @@ -0,0 +1,12 @@ +GlizyLocale.CodesEditorLoader = { + description: 'Descrizione', + code: 'Codice', + resourceLink: 'Link alla risorsa', + emptyText: 'Vuoto', + requiredField: 'Questo campo è richiesto', + oneToOne: 'Uno a uno', + oneToMany: 'Uno a molti', + delConfirm: 'Siete sicuri di voler cancellare questa mappatura selezionata?', + saveButton: 'Salva', + addNewButton: 'Nuovo codice' +}; \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/codes/views/skins/CodesEditorTemplate.html b/src/admin/application/classes/movio/modules/codes/views/skins/CodesEditorTemplate.html new file mode 100755 index 0000000..84d97eb --- /dev/null +++ b/src/admin/application/classes/movio/modules/codes/views/skins/CodesEditorTemplate.html @@ -0,0 +1,42 @@ + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/01CreateFolders.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/01CreateFolders.php new file mode 100644 index 0000000..8b3c48a --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/01CreateFolders.php @@ -0,0 +1,28 @@ +parent->getCustomModulesFolder( false ) ) ) + { + mkdir( $this->parent->getCustomModulesFolder( false ) ); + } + @mkdir( $this->parent->getCustomModulesFolder() ); + @mkdir( $this->parent->getCustomModulesFolder().'/models' ); + @mkdir( $this->parent->getCustomModulesFolder().'/views' ); + @mkdir( $this->parent->getCustomModulesFolder().'/locale' ); + @mkdir( $this->parent->getCustomModulesFolder().'/config' ); + @mkdir( $this->parent->getCustomModulesFolder().'/images' ); + + @chmod( $this->parent->getCustomModulesFolder(), 0777 ); + @chmod( $this->parent->getCustomModulesFolder().'/models', 0777 ); + @chmod( $this->parent->getCustomModulesFolder().'/views', 0777 ); + @chmod( $this->parent->getCustomModulesFolder().'/locale', 0777 ); + @chmod( $this->parent->getCustomModulesFolder().'/config', 0777 ); + @chmod( $this->parent->getCustomModulesFolder().'/images', 0777 ); + + return true; + } +} diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/02SaveLocaleFiles.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/02SaveLocaleFiles.php new file mode 100644 index 0000000..7636ed5 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/02SaveLocaleFiles.php @@ -0,0 +1,25 @@ +parent->getTableName(); + $language = $this->_application->getEditingLanguage(); + $fields = __Request::get( 'fieldName' ); + $labels = __Request::get( 'fieldLabel' ); + $output = ' \"".$labels[ $i ]."\",".GLZ_COMPILER_NEWLINE2; + } + $output .= "\t\"".$tableName."\" => \"".__Request::get( 'mbName' )."\",".GLZ_COMPILER_NEWLINE2; + $output .= "\t\"".$tableName.".views.FrontEnd\" => \"".__Request::get( 'mbName' )."\",".GLZ_COMPILER_NEWLINE2; + $output .= ');'.GLZ_COMPILER_NEWLINE2; + $output .= 'org_glizy_locale_Locale::append($strings);'.GLZ_COMPILER_NEWLINE2; + $output .= '?>'; + + file_put_contents( $this->parent->getCustomModulesFolder().'/locale/'.$language.'.php', $output ); + return true; + } +} diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/03CreateModule.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/03CreateModule.php new file mode 100644 index 0000000..450adeb --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/03CreateModule.php @@ -0,0 +1,43 @@ +parent->getModuleName(); + $tableName = $this->parent->getTableName(); + $modelName = $tableName.'.models.Model'; + $modifyUrl = 'movio_modulesBuilder?state=step3&mod=1&mbTable='.str_replace( '&', '&', rawurlencode( $tableName ) ).'&mbName='.rawurlencode( $moduleName ); + $deleteUrl = $tableName.'?action=deleteModule'; + + $output = <<id = '$tableName'; + \$moduleVO->name = __T('$tableName'); + \$moduleVO->description = ''; + \$moduleVO->version = '1.0.0'; + \$moduleVO->classPath = '$tableName'; + \$moduleVO->pageType = '{$tableName}.views.FrontEnd'; + \$moduleVO->author = ''; + \$moduleVO->authorUrl = ''; + \$moduleVO->pluginUrl = ''; + \$moduleVO->siteMapAdmin = ''. + ''. + ''. + ''. + ''; + \$moduleVO->canDuplicated = false; + org_glizy_Modules::addModule(\$moduleVO); + } +} +EOD; + + file_put_contents( $this->parent->getCustomModulesFolder().'/Module.php', $output ); + return true; + } +} diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/04CreateModelFile.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/04CreateModelFile.php new file mode 100644 index 0000000..2f1c9d5 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/04CreateModelFile.php @@ -0,0 +1,71 @@ +parent->getTableName() : $this->parent->getTableNameDb(); + + $fields = __Request::get( 'fieldName' ); + $types = __Request::get( 'fieldType', array() ); + $requireds = __Request::get( 'fieldRequired', array() ); + $admin = __Request::get( 'fieldAdmin', array() ); + $fieldSearch = __Request::get( 'fieldSearch', array() ); + $fieldKey = __Request::get( 'fieldKey', 'document_id' ); + + $output = ''.GLZ_COMPILER_NEWLINE2; + $output .= ''.GLZ_COMPILER_NEWLINE2; + + $output .= ''.GLZ_COMPILER_NEWLINE2; + if ($isDocument) { + $output .= ''.GLZ_COMPILER_NEWLINE2; + } + + for ( $i = 0; $i < count( $fields ); $i++ ) + { + if ( empty( $fields[ $i ] ) ) continue; + $required = in_array( $fields[ $i ], $requireds ) ? 'notnull' : ''; + $index = in_array( $fields[ $i ], $fieldSearch ) || in_array( $fields[ $i ], $admin ) ? 'true' : 'false'; + if ($fields[ $i ]==$fieldKey) { + $index = 'true'; + } + switch ( $types[ $i ] ) + { + case 'LONG_TEXT_HTML': + case 'LONG_TEXT': + $output .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'DATA': + $output .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'DATETIME': + $output .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'CHECKBOX': + $output .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'LIST': + $output .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'IMAGEREPEATER': + case 'MEDIAREPEATER': + $output .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'PICO': + $output .= ''.GLZ_COMPILER_NEWLINE2; + break; + default: + $output .= ''.GLZ_COMPILER_NEWLINE2; + break; + } + } + + + $output .= ''; + file_put_contents( $this->parent->getCustomModulesFolder().'/models/Model.xml', $output ); + return true; + } +} diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/05CreateAdminPage.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/05CreateAdminPage.php new file mode 100644 index 0000000..e59cb57 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/05CreateAdminPage.php @@ -0,0 +1,119 @@ +parent->getTableName(); + $fields = __Request::get( 'fieldName' ); + $types = __Request::get( 'fieldType', array() ); + $admin = __Request::get( 'fieldAdmin', array() ); + $requireds = __Request::get( 'fieldRequired', array() ); + $fieldKey = __Request::get( 'fieldKey'); + if (!$fieldKey) { + $fieldKey = 'document_id'; + } + $renderClass = $isDocument ? 'org.glizycms.contents.views.renderer.CellEditDeleteVisible' : 'org.glizycms.contents.views.renderer.CellEditDelete'; + $modelName = $tableName.'.models.Model'; + $controllerName = $isDocument ? 'moduleEdit' : 'activeRecordEdit'; + + $datagridFields = ''; + for ( $i = 0; $i < count( $fields ); $i++ ) { + if ( $types[ $i ] == IMAGEURL || + $types[ $i ] == IMAGE || + $types[ $i ] == MEDIA ) continue; + + if ( in_array( $fields[ $i ], $admin ) ) { + $datagridFields .= ''.GLZ_COMPILER_NEWLINE2; + } + } + + $formFields = ''; + for ( $i = 0; $i < count( $fields ); $i++ ) { + if ( empty( $fields[ $i ] ) ) continue; + $required = in_array( $fields[ $i ], $requireds ) ? 'true' : 'false'; + $label = '{i18n:'.$tableName.'_'.$fields[ $i ].'}'; + switch ( $types[ $i ] ) + { + case 'TEXT': + case 'IMAGEURL': + case 'URL': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'LONG_TEXT_HTML': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'LONG_TEXT': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'DATA': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'DATETIME': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'CHECKBOX': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'LIST': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'IMAGE': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'MEDIA': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'IMAGEREPEATER': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'MEDIAREPEATER': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + case 'HIDDEN': + $formFields .= ''.GLZ_COMPILER_NEWLINE2; + break; + } + } +$output = << + + + + + + + + + + $datagridFields + + + + $formFields + + + + + The files of the module and the site page will be deleted]]> + + + + + + + + +EOD; + + file_put_contents( $this->parent->getCustomModulesFolder().'/views/Admin.xml', $output ); + return true; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/06CreatePage.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/06CreatePage.php new file mode 100644 index 0000000..0c2b61c --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/06CreatePage.php @@ -0,0 +1,288 @@ +parent->getTableName(); + $fields = __Request::get( 'fieldName' ); + $types = __Request::get( 'fieldType', array() ); + $fieldSearch = __Request::get( 'fieldSearch', array() ); + $fieldListSearch = __Request::get( 'fieldListSearch', array() ); + $modelName = $tableName.'.models.Model'; + $routeUrl = $tableName; + $fieldImagesInList = ''; + $fieldImages = ''; + $firstFieldName = ''; + $skinList = ''; + $skinEntry = ''; + $fieldKey = __Request::get( 'fieldKey'); + if (!$fieldKey) { + $fieldKey = 'document_id'; + } + + // form di ricerca + $fieldInSearch = ''; + for ( $i = 0; $i < count( $fields ); $i++ ) + { + if ( in_array( $fields[ $i ], $fieldSearch ) ) + { + switch ( $types[ $i ] ) + { + case 'LIST': + $fieldInSearch .= ''.GLZ_COMPILER_NEWLINE2; + $fieldInSearch .= ''.GLZ_COMPILER_NEWLINE2; + break; + + default: + $fieldInSearch .= ''.GLZ_COMPILER_NEWLINE2; + break; + } + } + } + + + // definizione delle skin per il risultato della ricerca + $firstImageId = ''; + $firstImageRepeater = false; + for ( $i = 0; $i < count( $fields ); $i++ ) + { + if( $types[ $i ] == 'IMAGEURL' || $types[ $i ] == 'IMAGE' ) + { + $firstImageId = $fields[ $i ]; + $fieldImagesInList = ''.GLZ_COMPILER_NEWLINE2; + break; + } else if ($types[ $i ] == 'IMAGEREPEATER') { + $firstImageRepeater = true; + $firstImageId = $fields[ $i ]; + $fieldImagesInList = ''.GLZ_COMPILER_NEWLINE2; + break; + } + } + $skinList .= '

'.GLZ_COMPILER_NEWLINE2; + $skinList .= '

'.GLZ_COMPILER_NEWLINE2; + $skinList .= ''.GLZ_COMPILER_NEWLINE2; + $skinList .= '
'.GLZ_COMPILER_NEWLINE2; + + if ( $firstImageId ) { + if (!$firstImageRepeater) { + $skinList .= '
'.GLZ_COMPILER_NEWLINE2; + $skinList .= ''.GLZ_COMPILER_NEWLINE2; + $skinList .= '
'.GLZ_COMPILER_NEWLINE2; + } else { + $skinList .= '
'.GLZ_COMPILER_NEWLINE2; + $skinList .= ''.GLZ_COMPILER_NEWLINE2; + $skinList .= ''.GLZ_COMPILER_NEWLINE2; + $skinList .= ''.GLZ_COMPILER_NEWLINE2; + $skinList .= '
'.GLZ_COMPILER_NEWLINE2; + } + } + + $first = false; + for ( $i = 0; $i < count( $fields ); $i++ ) + { + if ( in_array( $fields[ $i ], $fieldListSearch ) ) + { + if ( $types[ $i ] == 'HIDDEN' || + $types[ $i ] == 'IMAGEURL' || + $types[ $i ] == 'IMAGE' || + $types[ $i ] == 'IMAGEREPEATER' || + $types[ $i ] == 'MEDIAREPEATER' || + $types[ $i ] == 'MEDIA' ) continue; + + if ( !$first ) + { + // primo campo, viene usato come titolo + $first = true; + $firstFieldName = $fields[ $i ]; + $skinList .= '

'.GLZ_COMPILER_NEWLINE2; + } + else + { + $skinList .= '

'.GLZ_COMPILER_NEWLINE2; + } + } + } + $skinList .= '
'.GLZ_COMPILER_NEWLINE2; + $skinList .= '
'.GLZ_COMPILER_NEWLINE2; + $skinList .= ''.GLZ_COMPILER_NEWLINE2; + $skinList .= '
'.GLZ_COMPILER_NEWLINE2; + $skinList .= '

'.GLZ_COMPILER_NEWLINE2; + $skinList .= '
'.GLZ_COMPILER_NEWLINE2; + $skinList .= '
'.GLZ_COMPILER_NEWLINE2; + $skinList .= '

'.GLZ_COMPILER_NEWLINE2; + $skinList = str_replace('##firstFieldName##', $firstFieldName, $skinList); + + // definizione delle skin per il dettaglio + $first = false; + $image = ''; + $imageList = ''; + $details = ''; + $text = ''; + $afterText = ''; + $skinEntry .= ''.GLZ_COMPILER_NEWLINE2; + $skinEntry .= '
'.GLZ_COMPILER_NEWLINE2; + $firstFieldName = ''; + for ( $i = 0; $i < count( $fields ); $i++ ) + { + if ( $types[ $i ] == 'HIDDEN' ) continue; + + if ( !$first ) + { + // primo campo, viene usato come titolo + $first = true; + $firstFieldName = $fields[ $i ]; + // $skinEntry .= '

'.GLZ_COMPILER_NEWLINE2; + // $skinEntry .= '
'.GLZ_COMPILER_NEWLINE2; + } + else + { + $img = ''; + switch ( $types[ $i ] ) + { + case 'IMAGEURL': + $fieldImages .= ''.GLZ_COMPILER_NEWLINE2; + $img = '
'.GLZ_COMPILER_NEWLINE2; + break; + + case 'IMAGE': + $fieldImages .= ''.GLZ_COMPILER_NEWLINE2; + $img = '
'.GLZ_COMPILER_NEWLINE2; + break; + + case 'IMAGEREPEATER': + $fieldImages .= 'contentCount==1) {'. + '$c = $this->getComponentById($this->getId()."-image_id");'. + '$c->setAttributes(array("width" => __Config::get("THUMB_WIDTH"), "height" => __Config::get("THUMB_HEIGHT")));'. + '}'. + 'return parent::loadContent($id, $bindTo);'. + '}'. + ']]>'. + ''.GLZ_COMPILER_NEWLINE2; + $afterText .= '
'.GLZ_COMPILER_NEWLINE2; + $afterText .= ''.GLZ_COMPILER_NEWLINE2; + $afterText .= ''.GLZ_COMPILER_NEWLINE2; + $afterText .= ''.GLZ_COMPILER_NEWLINE2; + $afterText .= '
'.GLZ_COMPILER_NEWLINE2; + $img = ''. + ''. + ''; + break; + + case 'MEDIAREPEATER': + $fieldImages .= ''.GLZ_COMPILER_NEWLINE2; + $afterText .= ''.GLZ_COMPILER_NEWLINE2; + $afterText .= '

'.GLZ_COMPILER_NEWLINE2; + $afterText .= '
    '.GLZ_COMPILER_NEWLINE2; + $afterText .= '
  • '.GLZ_COMPILER_NEWLINE2; + $afterText .= '
'.GLZ_COMPILER_NEWLINE2; + $afterText .= ''.GLZ_COMPILER_NEWLINE2; + break; + + case 'MEDIA': + $fieldImages .= ''.GLZ_COMPILER_NEWLINE2; + $details .= ''.GLZ_COMPILER_NEWLINE2; + $details .= '
'.GLZ_COMPILER_NEWLINE2; + $details .= '
'.GLZ_COMPILER_NEWLINE2; + $details .= '
'.GLZ_COMPILER_NEWLINE2; + break; + + case 'TEXT': + case 'DATA': + case 'LIST': + case 'URL': + if ($types[ $i ]=='URL') { + $fieldImages .= ''.GLZ_COMPILER_NEWLINE2; + } + + $details .= ''.GLZ_COMPILER_NEWLINE2; + $details .= '
'.GLZ_COMPILER_NEWLINE2; + $details .= '
'.GLZ_COMPILER_NEWLINE2; + $details .= '
'.GLZ_COMPILER_NEWLINE2; + break; + + case 'LONG_TEXT_HTML': + case 'LONG_TEXT': + $text .= ''.GLZ_COMPILER_NEWLINE2; + $text .= '

'.GLZ_COMPILER_NEWLINE2; + $text .= ''.GLZ_COMPILER_NEWLINE2; + $text .= ''.GLZ_COMPILER_NEWLINE2; + break; + + case 'HIDDEN': + break; + } + + if ( !empty( $img ) ) + { + if ( empty( $image ) ) + { + $image = $img; + } + else + { + $imageList .= $img; + } + } + } + } + + $skinEntry .= !empty( $image ) ? $image : ''; + $skinEntry .= !empty( $details ) ? '
'.$details.'
' : ''; + $skinEntry .= '
'.$text.$afterText; + $skinEntry .= '

'.GLZ_COMPILER_NEWLINE2; + if ( !empty( $imageList ) ) + { + $skinEntry .= '
'.$imageList.'
'.GLZ_COMPILER_NEWLINE2; + } + $skinEntry .= '
'.GLZ_COMPILER_NEWLINE2; + + + $output = << + + + + + + + + $fieldInSearch + + + + + + + $fieldImagesInList + + + + + + $fieldImages + + + + + + + +EOD; + + file_put_contents( $this->parent->getCustomModulesFolder().'/views/FrontEnd.xml', $output ); + return true; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/07CreateRoutingFile.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/07CreateRoutingFile.php new file mode 100644 index 0000000..8245e52 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/07CreateRoutingFile.php @@ -0,0 +1,31 @@ +parent->getTableName(); + + $fields = __Request::get( 'fieldName' ); + $fieldListSearch = __Request::get( 'fieldListSearch', array() ); + $fieldKey = __Request::get( 'fieldKey', 'document_id' ); + if (!$fieldKey) { + $fieldKey = 'document_id'; + } + $title = ''; + for ( $i = 0; $i < count( $fields ); $i++ ) + { + if (in_array( $fields[ $i ], $fieldListSearch )) { + $title = $fields[ $i ]; + break; + } + } + + $output = ''.GLZ_COMPILER_NEWLINE2; + $output .= ''.GLZ_COMPILER_NEWLINE2; + $output .= ''.GLZ_COMPILER_NEWLINE2; + $output .= ''.GLZ_COMPILER_NEWLINE2; + + file_put_contents( $this->parent->getCustomModulesFolder().'/config/routing.xml', $output ); + return true; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/08AddPage.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/08AddPage.php new file mode 100644 index 0000000..1312701 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/08AddPage.php @@ -0,0 +1,19 @@ +parent->getTableName(); + $moduleName = $this->parent->getModuleName(); + $siteMap = &org_glizy_ObjectFactory::createObject('org.glizycms.core.application.SiteMapDB'); + $siteMap->getSiteArray(); + $menuNode = &$siteMap->getHomeNode(); + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $pageId = $menuProxy->addMenu($moduleName, $menuNode->id, $tableName.'.views.FrontEnd'); + } + return true; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/09AddModuleDirective.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/09AddModuleDirective.php new file mode 100644 index 0000000..55f998b --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/09AddModuleDirective.php @@ -0,0 +1,35 @@ +parent->getTableName(); + $sitemapCustom = __Paths::get( 'APPLICATION_TO_ADMIN' ).'startup/modules_custom.php'; + if ( file_exists( $sitemapCustom ) ) + { + $output = file_get_contents( $sitemapCustom ); + } + else + { + + $output = <<isAdmin()) { + __Paths::addClassSearchPath( __Paths::get( 'APPLICATION_CLASSES' ).'userModules/' ); + } +//modules_custom.php +} +EOD; + } + // cancella entry già presenti + $output = preg_replace( "/\/\/\sstart\s".$tableName."\/\/([^\/])*\/\/\send\s".$tableName."\/\//i", "", $output ); + + // aggiunge la nuova entry + $output = str_replace( '//modules_custom.php', '// start '.$tableName.'//'.GLZ_COMPILER_NEWLINE2.$tableName.'_Module::registerModule();'.GLZ_COMPILER_NEWLINE2.'// end '.$tableName.'//'.GLZ_COMPILER_NEWLINE2.'//modules_custom.php', $output ); + + $r = file_put_contents( $sitemapCustom, $output ); + return true; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/10AddSitemap.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/10AddSitemap.php new file mode 100644 index 0000000..0a24358 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/10AddSitemap.php @@ -0,0 +1,10 @@ +parent->getTableNameDb(); + + file_put_contents( $this->parent->getCustomModulesFolder().'/Info', serialize( $values ) ); + + return true; + } + +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/12ImportCsvData.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/12ImportCsvData.php new file mode 100644 index 0000000..b305375 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/12ImportCsvData.php @@ -0,0 +1,33 @@ +parent->getTableName(); + $fields = __Request::get( 'fieldName' ); + $modelName = 'userModules.'.$tableName.'.models.Model'; + + $fieldsMap = array(); + foreach($fields as $f) { + $col = str_replace('row_', '', $f); + $fieldsMap[] = array($f, $col); + } + $ar = org_glizy_ObjectFactory::createModel($modelName); + + + $csvIterator = org_glizy_ObjectFactory::createObject('movio.modules.modulesBuilder.services.CVSImporter', __Request::get('mbCsvOptions')); + foreach($csvIterator as $row) { + if ($f) { + $ar->emptyRecord(); + foreach($fieldsMap as $f) { + $ar->{$f[0]} = $row->{$f[1]}; + } + $ar->publish(); + } + } + } + return true; + } + +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/AbstractCommand.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/AbstractCommand.php new file mode 100644 index 0000000..a0f6064 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/AbstractCommand.php @@ -0,0 +1,17 @@ +parent = $parent; + $this->_application = org_glizy_ObjectValues::get('org.glizy', 'application'); + } + + function getError() + { + return ''; + } +} diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/Builder.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/Builder.php new file mode 100644 index 0000000..a979ada --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/Builder.php @@ -0,0 +1,64 @@ +execute(); + if ( !$r ) + { + break; + } + } + } + + function executeDelete() + { + // crea le cartelle + $sequence = array( 'd01DeleteFolders', 'd02CleanStartup', 'd03DeleteMenu' ); + foreach( $sequence as $v ) + { + $c = org_glizy_ObjectFactory::createObject( 'movio.modules.modulesBuilder.builder.' . $v, $this ); + $r = $c->execute(); + if ( !$r ) + { + break; + } + } + } + + + function getModuleName() + { + return __Request::get( 'mbName' ); + } + + function getTableName() + { + return __Request::get( 'mbTable' ); + } + + function getTableNameDb() + { + return __Request::get( 'mbTableDB' ); + } + + function getCustomModulesFolder( $fullPath = true ) + { + return __Paths::get( 'APPLICATION_TO_ADMIN' ).'classes/userModules/'.( $fullPath ? $this->getTableName().'/' : '' ); + } + + function getPageTypeFolder() + { + return __Paths::get( 'APPLICATION_TO_ADMIN' ).'pageTypes/'; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/d01DeleteFolders.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/d01DeleteFolders.php new file mode 100644 index 0000000..8421513 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/d01DeleteFolders.php @@ -0,0 +1,23 @@ +deleteDirectory( $this->parent->getCustomModulesFolder() ); + return true; + } + + function deleteDirectory($dir) + { + if (!file_exists($dir)) return true; + if (!is_dir($dir) || is_link($dir)) return unlink($dir); + foreach (scandir($dir) as $item) { + if ($item == '.' || $item == '..') continue; + if (!$this->deleteDirectory($dir . "/" . $item)) { + chmod($dir . "/" . $item, 0777); + if (!$this->deleteDirectory($dir . "/" . $item)) return false; + }; + } + return rmdir($dir); + } +} diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/d02CleanStartup.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/d02CleanStartup.php new file mode 100644 index 0000000..e9bffab --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/d02CleanStartup.php @@ -0,0 +1,17 @@ +parent->getTableName(); + $sitemapCustom = __Paths::get( 'APPLICATION_TO_ADMIN' ).'startup/modules_custom.php'; + if ( file_exists( $sitemapCustom ) ) + { + $output = file_get_contents( $sitemapCustom ); + $output = preg_replace( "/\/\/\sstart\s".$tableName."\/\/([^\/])*\/\/\send\s".$tableName."\/\//i", "", $output ); + $r = file_put_contents( $sitemapCustom, $output ); + } + + return true; + } +} diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/builder/d03DeleteMenu.php b/src/admin/application/classes/movio/modules/modulesBuilder/builder/d03DeleteMenu.php new file mode 100644 index 0000000..037cf1d --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/builder/d03DeleteMenu.php @@ -0,0 +1,19 @@ +parent->getTableName(); + $siteMap = &org_glizy_ObjectFactory::createObject('org.glizycms.core.application.SiteMapDB'); + $siteMap->getSiteArray(); + $menuNode = $siteMap->getMenuByPageType($tableName.'.views.FrontEnd'); + if ($menuNode) { + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $pageId = $menuProxy->deleteMenu($menuNode->id); + } + + org_glizy_Modules::deleteCache(); + return true; + } + +} diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/controllers/AdminModuleStateController.php b/src/admin/application/classes/movio/modules/modulesBuilder/controllers/AdminModuleStateController.php new file mode 100644 index 0000000..76cec7a --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/controllers/AdminModuleStateController.php @@ -0,0 +1,21 @@ +_parent->_application->getPageType(); + list( $moduleName ) = explode( '.', $pageType ); + __Session::set( 'mbTable', $moduleName ); + glz_import( 'movio.modules.modulesBuilder.builder.*', array( 'Builder.php', 'AbstractCommand.php' ) ); + $builder = org_glizy_ObjectFactory::createObject( 'movio.modules.modulesBuilder.builder.Builder' ); + $builder->executeDelete(); + + glz_import( 'org.glizy.helpers.Navigation' ); + org_glizy_helpers_Navigation::gotoUrl(__Link::makeUrl('link', array('pageId' => 'SiteMap' ) ) ); + } + } +} + + diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/controllers/DeleteModule.php b/src/admin/application/classes/movio/modules/modulesBuilder/controllers/DeleteModule.php new file mode 100644 index 0000000..1a93aa7 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/controllers/DeleteModule.php @@ -0,0 +1,16 @@ +application->getPageType(); + list( $moduleName ) = explode( '.', $pageType ); + __Request::set( 'mbTable', $moduleName ); + $builder = org_glizy_ObjectFactory::createObject( 'movio.modules.modulesBuilder.builder.Builder' ); + $builder->executeDelete(); + + org_glizy_helpers_Navigation::gotoUrl(__Link::makeUrl('link', array('pageId' => 'glizycms_contentsedit' ) ) ); + } + } +} diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/controllers/StateController.php b/src/admin/application/classes/movio/modules/modulesBuilder/controllers/StateController.php new file mode 100644 index 0000000..35c07c2 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/controllers/StateController.php @@ -0,0 +1,192 @@ + $file_destname, + 'enclosure' => __Request::get( 'mbCsvEnclose', ';' ), + 'delimiter' => __Request::get( 'mbCsvSeparate', ';' ) + ); + $this->_parent->refreshToState( 'step3', + array( 'mbTable' => $this->getModuleName($moduleName[0]), + 'mbTableDB' => __Request::get('table'), + 'mbName' => $moduleName[0], + 'mbModuleType' => 'csv', + 'mbCsvOptions' => $options + )); + } + else + { + // errore + $this->_parent->validateAddError( __T( 'Errore nel caricamento del file' ) ); + } + + @unlink( $file_destname ); + } + else + { + // errore + $this->_parent->validateAddError( __T( 'Errore nel caricamento del file' ) ); + } + + } + } + + /** + * Submit dello step2D, � stata scelta la tabella + * + * @param string $oldState + * @return void + */ + function executeLater_step2DB( $oldState ) + { + // controlla se � stato ftto submit + if ( strtolower( __Request::get( 'action', '' ) ) == 'next' ) + { + // controlla la validit� della form + if ( $this->_parent->validate() ) + { + $this->_parent->refreshToState( 'step3', + array( 'mbTable' => $this->getModuleName(__Request::get('table')), + 'mbTableDB' => __Request::get('table'), + 'mbName' => __Request::get('table'), + 'mbModuleType' => 'db' + )); + } + } + } + + function execute_step3( $oldState ) + { + if ( strtolower( __Request::get( 'action', '' ) ) != 'next' ) + { + // in fase di modifica il nome del modulo + // viene passato in get + if ( __Request::exists( 'mbTable' ) && __Request::exists( 'mbName' ) && __Request::exists( 'mod' )) + { + // cambia il tiolo della pagina + $c = $this->_parent->getComponentById( "pageTitle" ); + $c->setAttribute( 'value', __T( 'Modifica modulo' ) ); + $c->process(); + + // imposta altri valori dal file info + $builder = org_glizy_ObjectFactory::createObject( 'movio.modules.modulesBuilder.builder.Builder' ); + $values = file_get_contents( $builder->getCustomModulesFolder().'/Info' ); + $values = unserialize( $values ); + __Request::set( 'fieldOrder', $values[ 'fieldOrder' ] ); + __Request::set( 'fieldRequired', $values[ 'fieldRequired' ] ); + __Request::set( 'fieldType', $values[ 'fieldType' ] ); + __Request::set( 'fieldSearch', $values[ 'fieldSearch' ] ); + __Request::set( 'fieldListSearch', $values[ 'fieldListSearch' ] ); + __Request::set( 'fieldAdmin', $values[ 'fieldAdmin' ] ); + __Request::set( 'fieldLabel', $values[ 'fieldLabel' ] ); + __Request::set( 'mbModuleType', isset($values[ 'mbModuleType' ]) ? $values[ 'mbModuleType' ] : 'document' ); + __Request::set( 'mbTableDB', $values[ 'tableDb' ] ); + } + } + } + + + function executeLater_step3( $oldState ) + { + // controlla se � stato fatto submit + if ( strtolower( __Request::get( 'action', '' ) ) == 'next' ) + { + // controlla la validit� della form + if ( $this->_parent->validate() ) + { + $fieldOrder = __Request::get( 'fieldOrder' ); + $fieldSearch = __Request::get( 'fieldSearch' ); + $fieldListSearch = __Request::get( 'fieldListSearch' ); + $fieldAdmin = __Request::get( 'fieldAdmin' ); + + $error = false; + if ( is_null( $fieldSearch ) ) + { + $error = true; + $this->_parent->validateAddError( __T( 'Specificare i campi per la ricerca' ) ); + } + if ( !$error && is_null( $fieldListSearch ) ) + { + $error = true; + $this->_parent->validateAddError( __T( 'Specificare i campi per il risultato della ricerca' ) ); + } + if ( !$error && is_null( $fieldAdmin ) ) + { + $error = true; + $this->_parent->validateAddError( __T( 'Specificare i campi per la lista in amministrazione' ) ); + } + + if ( !$error ) + { + __Request::set( 'fieldName', explode( ',', $fieldOrder ) ); + $builder = org_glizy_ObjectFactory::createObject( 'movio.modules.modulesBuilder.builder.Builder' ); + $builder->execute(); + + $this->_parent->refreshToState( 'step4' ); + } + } + } + } + + function executeLater_step3new( $oldState ) + { + // controlla se � stato fatto submit + if ( strtolower( __Request::get( 'action', '' ) ) == 'next' ) + { + $fieldOrder = __Request::get( 'fieldOrder' ); + __Request::set( 'fieldName', explode( ',', $fieldOrder ) ); + $mbName = __Request::get( 'mbName' ); + __Request::set( 'mbTable', $this->getModuleName($mbName) ); + __Request::set( 'mbModuleType', 'document'); + + $builder = org_glizy_ObjectFactory::createObject( 'movio.modules.modulesBuilder.builder.Builder' ); + $builder->execute(); + $this->_parent->refreshToState( 'step4' ); + } + } + + function execute_step4( $oldState ) + { + $model = __Request::get( 'mbTable' ).'.models.Model'; + $ar = __ObjectFactory::createModel($model); + + // reindicizza se necessario + if (method_exists($ar, 'reIndex')) { + $it = __ObjectFactory::createModelIterator($model); + foreach ($it as $ar) { + $ar->reIndex(); + $data = $ar->getValuesAsArray(); + $ar->fulltext = org_glizycms_core_helpers_Fulltext::make($data, $ar); + $ar->forceModified('fulltext'); + $ar->save(); + } + } + } + + private function getModuleName($mbTable) + { + return strtolower( str_replace( array( '_', ' ', ')', '(', '/', '\\' ), '', $mbTable ) ).''.uniqid(); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/services/AbstractDbService.php b/src/admin/application/classes/movio/modules/modulesBuilder/services/AbstractDbService.php new file mode 100644 index 0000000..b3aaa86 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/services/AbstractDbService.php @@ -0,0 +1,46 @@ +connectionNumber = $connectionNumber; + } + + protected function setConnParam($name, $value) + { + __Config::set($name.'#'.$this->connectionNumber, $value); + } + + public function connect($host, $port, $user, $psw, $dbname) + { + $this->setConnParam('DB_HOST', $host); + if ($port) $this->setConnParam('DB_PORT', $port); + $this->setConnParam('DB_USER', $user); + $this->setConnParam('DB_PSW', $psw); + $this->setConnParam('DB_NAME', $dbname); + + $this->connection = org_glizy_dataAccessDoctrine_DataAccess::getConnection($this->connectionNumber); + return $this->connection->connect(); + } + + public function getTableNames() + { + $sm = org_glizy_ObjectFactory::createObject('org.glizy.dataAccessDoctrine.SchemaManager', $this->connection); + return $sm->getTableNames(); + } + + public function getColumnNames($tableName) + { + $sm = org_glizy_ObjectFactory::createObject('org.glizy.dataAccessDoctrine.SchemaManager', $this->connection); + return $sm->getColumnNames($tableName); + } + + public function createRecordIterator($modelName, $tableName) + { + $model = org_glizy_ObjectFactory::createObject($modelName, $this->connectionNumber, $tableName); + return $model->createRecordIterator(); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/services/CVSImporter.php b/src/admin/application/classes/movio/modules/modulesBuilder/services/CVSImporter.php new file mode 100644 index 0000000..5c4e12a --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/services/CVSImporter.php @@ -0,0 +1,74 @@ +setDelimiter($options['delimiter']); + $csv->setEnclosure($options['enclosure']); + $excel = $csv->load($options['filePath']); + $this->worksheet = $excel->getActiveSheet(); + } + + public function getHeading() + { + $maxCol = $this->worksheet->getHighestDataColumn(); + $data = $this->worksheet->rangeToArray('A1:'.$maxCol.'1'); + return $data[0]; + } + + public function count() { + return $this->worksheet->getHighestDataRow()-1; + } + + public function ¤t() + { + return $this->data; + } + + public function key() + { + return $this->pos; + } + + public function next() + { + $this->fetch(); + } + + public function rewind() + { + $this->pos = 0; + $this->fetch(); + } + + public function valid() + { + return $this->pos <= $this->worksheet->getHighestDataRow()-1; + } + + protected function fetch() + { + $i = $this->pos + 2; + $maxCol = $this->worksheet->getHighestDataColumn(); + $data = $this->worksheet->rangeToArray('A'.$i.':'.$maxCol.$i); + + if (!is_null($data[0][0])) { + $this->data = new stdClass(); + foreach ($data[0] as $k => $v) { + $this->data->$k = $v; + } + } else { + $this->data = null; + } + + $this->pos++; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/services/DbServiceFactory.php b/src/admin/application/classes/movio/modules/modulesBuilder/services/DbServiceFactory.php new file mode 100644 index 0000000..26ab70a --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/services/DbServiceFactory.php @@ -0,0 +1,16 @@ +logAndMessage('Il dbms selezionato non è supportato', null, true); + return null; + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/services/MysqlService.php b/src/admin/application/classes/movio/modules/modulesBuilder/services/MysqlService.php new file mode 100644 index 0000000..cd046b9 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/services/MysqlService.php @@ -0,0 +1,10 @@ +setConnParam('DB_TYPE', 'mysql'); + return parent::connect($host, $port, $user, $psw, $dbname); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/services/PgsqlService.php b/src/admin/application/classes/movio/modules/modulesBuilder/services/PgsqlService.php new file mode 100644 index 0000000..cc91d3a --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/services/PgsqlService.php @@ -0,0 +1,10 @@ +setConnParam('DB_TYPE', 'pgsql'); + return parent::connect($host, $port, $user, $psw, $dbname); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/views/Admin.xml b/src/admin/application/classes/movio/modules/modulesBuilder/views/Admin.xml new file mode 100644 index 0000000..d4dc140 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/views/Admin.xml @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  • the lable that will appear in administrative panel and on the site page
  • +
  • field type
  • +
  • if the field is mandatory
  • +
  • if the field is searchable on the site page
  • +
  • if the field is present in the search results
  • +
  • if the field is present in the list in the administrative panel
  • + +The order in which the fields will appear on the site page and in the administrative panel may be changed by dragging the row of the table + ]]>
    + + + + + + + +
    +
    + + + +
  • the lable that will appear in administrative panel and on the site page
  • +
  • field type
  • +
  • if the field is mandatory
  • +
  • if the field is searchable on the site page
  • +
  • if the field is present in the search results
  • +
  • if the field is present in the list in the administrative panel
  • + +The order in which the fields will appear on the site page and in the administrative panel may be changed by dragging the row of the table + ]]>
    + + + + + + + +
    +
    + + + + + +
    +
    \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/views/components/EditTableFields.php b/src/admin/application/classes/movio/modules/modulesBuilder/views/components/EditTableFields.php new file mode 100644 index 0000000..c8fa07b --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/views/components/EditTableFields.php @@ -0,0 +1,137 @@ +getHeading(); + $i = 0; + foreach($fieldLabel as $f) { + if (!$f) continue; + $fieldOrder[] = 'row_'.$i++; + $fieldType[] = 'TEXT'; + } + } else { + + $connection = org_glizy_dataAccessDoctrine_DataAccess::getConnection(); + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($connection); + $fields = $sm->getFields($tableName); + + $fieldOrder = array(); + $fieldType = array(); + $fieldLabel = array(); + foreach($fields as $f) { + $fieldLabel[] = $f->name; + $fieldOrder[] = $f->name; + if ($f->key) { + $fieldPrimaryKey = $f->name; + } + + switch ( $f->type ) { + case 'text': + $type = 'longtext'; + break; + case 'date': + case 'datetime': + $type = 'date'; + break; + default: + $type = 'text'; + break; + } + $fieldType[] = $type; + } + + } + + $output = ''; + $output .= ''; + $theadFields = ''; + + for ($i = 0; $i < count( $fieldOrder); $i++ ) + { + $type = $fieldType[$i]; + $label = $fieldLabel[$i]; + $id = $fieldOrder[$i]; + + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + } + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + + $output .= '
    '; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= '
    '; + $output .= ''; + $output .= ''; + $output .= $theadFields.__T( 'Etichetta').''.__T( 'Tipologia').''.__T( 'Obbligatorio').''.__T( 'Ricerca').''.__T( 'Lista ricerca').''.__T( 'Lista amm.').'
    '; + $output .= ''; + $output .= ''; + $this->addOutputCode($output); + } + +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/views/components/NewTableFields.php b/src/admin/application/classes/movio/modules/modulesBuilder/views/components/NewTableFields.php new file mode 100644 index 0000000..41a229b --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/views/components/NewTableFields.php @@ -0,0 +1,83 @@ +'; + $output .= ''; + + + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''.__T('Add field').''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''.__T( 'Etichetta').''; + $output .= ''.__T( 'Tipologia').''; + $output .= ''.__T( 'Obbligatorio').''; + $output .= ''.__T( 'Ricerca').''; + $output .= ''.__T( 'Lista ricerca').''; + $output .= ''.__T( 'Lista amm.').''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $output .= ''; + $this->addOutputCode($output); + } + +} diff --git a/src/admin/application/classes/movio/modules/modulesBuilder/views/components/SelectTable.php b/src/admin/application/classes/movio/modules/modulesBuilder/views/components/SelectTable.php new file mode 100644 index 0000000..dc3d3b9 --- /dev/null +++ b/src/admin/application/classes/movio/modules/modulesBuilder/views/components/SelectTable.php @@ -0,0 +1,67 @@ +defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('emptyValue', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('rows', false, 1, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('requiredMessage', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapLabel', false, false, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + $this->_content = $this->_parent->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + + function render() + { + $dbServiceFactory = org_glizy_ObjectFactory::createObject('movio.modules.modulesBuilder.services.DbServiceFactory'); + $dbService = $dbServiceFactory->createDbService(__Config::get('DB_TYPE')); + $dbService->connect(__Config::get('DB_HOST'), __Config::get('DB_PORT'), __Config::get('DB_USER'), __Config::get('DB_PSW'), __Config::get('DB_NAME')); + $tables = $dbService->getTableNames(); + + + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['name'] = $this->getOriginalId(); + $attributes['class'] = $this->getAttribute('required') ? 'required' : ''; + $attributes['class'] .= $this->getAttribute( 'cssClass' ) != '' ? ( $attributes['class'] != '' ? ' ' : '' ).$this->getAttribute( 'cssClass' ) : ''; + $attributes['title'] = $this->getAttributeString('title'); + $attributes['onchange'] = $this->getAttribute('onChange'); + if ( $this->getAttribute('rows')>1) + { + $attributes['size'] = $this->getAttribute('rows'); + } + + $output = ''; + + $output = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), $this->getAttribute('wrapLabel'), $output, array('class' => ($this->getAttribute('required') ? 'required' : '')), false); + $this->addOutputCode($output); + } + +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/EntityResolver.php b/src/admin/application/classes/movio/modules/ontologybuilder/EntityResolver.php new file mode 100644 index 0000000..fe73673 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/EntityResolver.php @@ -0,0 +1,166 @@ +type = 'movio.modules.ontologybuilder.content'; + $this->protocol = 'movioContent:'; + } + + public function compileRouting($ar) + { + $option = unserialize($ar->speakingurl_option); + $entityTypeId = $option['entityTypeId']; + + // ricava il pageid tramite entitySelect + $menu = $this->getPage($entityTypeId); + + return $menu ? '' : ''; + } + + // NOTA: questo moetodo dovrebbe essere spostato in un'altra classe + // perché questa classe ha il compito di gestire gli url paranti, lo switch della lingua e la risoluzione dei link codificati + public function getMenuVisibleEntity($entityTypeId) + { + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityMenu'); + $menuDocument = $it->load('getVisibleEntityByTypeId', array('entityTypeId' => $entityTypeId))->first(); + + if (!is_null($menuDocument)) { + return $menuDocument; + } else { + return null; + } + } + + protected function getIdFromLink($id) + { + return str_replace($this->protocol, '', $id); + } + + public function searchDocumentsByTerm($term, $id, $protocol='', $filterType='') + { + $result = array(); + if ($protocol && $protocol!=$this->protocol) return $result; + + $application = __ObjectValues::get('org.glizy', 'application'); + $entityTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + + if ($term) { + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityDocument', 'All'); + + if ($term != '') { + $it->where('title', '%'.$term.'%', 'ILIKE'); + } + + $it->orderBy('title'); + + foreach($it as $ar) { + $entityTypeId = $entityTypeService->getEntityTypeId($ar->document_type); + + $result[] = array( + 'id' => $this->protocol.$ar->document_id, + 'text' => $ar->title, + 'path' => __T('Content').'/' . $entityTypeService->getEntityTypeName($entityTypeId) + ); + } + } elseif ($id) { + if (strpos($id, $this->protocol) !== 0) { + return $result; + } + + $ar = org_glizy_objectFactory::createModel('movio.modules.ontologybuilder.models.EntityDocument'); + $ar->load($this->getIdFromLink($id)); + $entityTypeId = $entityTypeService->getEntityTypeId($ar->document_type); + + $result[] = array( + 'id' => $this->protocol.$ar->document_id, + 'text' => $ar->title, + 'path' => __T('Content').'/' . $entityTypeService->getEntityTypeName($entityTypeId) + ); + } + + return $result; + } + + public function makeUrl($id) + { + if (strpos($id, $this->protocol) === 0) { + $id = $this->getIdFromLink($id); + return $this->makeUrlFromId($id); + } else { + return false; + } + } + + + public function makeLink($id) + { + if (strpos($id, $this->protocol) === 0) { + $id = $this->getIdFromLink($id); + return $this->makeUrlFromId($id, true); + } else { + return false; + } + } + + public function makeUrlFromRequest() + { + $id = __Request::get('document_id'); + return $this->makeUrlFromId($id); + } + + private function makeUrlFromId($id, $fullLink=false) + { + $ar = org_glizy_objectFactory::createModel('movio.modules.ontologybuilder.models.EntityDocument'); + if ($ar->load($this->getIdFromLink($id))) { + $entityTypeId = $this->getEntityTypeId($ar->document_type); + $menu = $this->getPage($entityTypeId); + + if ($ar->document_detail_isVisible && $ar->document_detail_translated && $menu) { + // if the document is visible and is traslated and the entity page exists + if ($ar->keyInDataExists('url') && $ar->url) { + $language = $this->application->getLanguage(); + $url = GLZ_HOST.'/'.$language.'/'.$ar->url; + } else { + $url = __Link::makeUrl('showEntityDetail', array( 'pageId' => $menu->id, + 'entityTypeId' => $entityTypeId, + 'document_id' => $id, + 'title' => $ar->title)); + } + + return $fullLink ? __Link::makeSimpleLink($ar->title, $url) : $url; + } + } + + // document not found, isn't visible or isn't traslated + // go to entity page or home + $speakingUrlManager = $this->application->retrieveProxy('org.glizycms.speakingUrl.Manager'); + return $speakingUrlManager->makeUrl('internal:'.( $menu ? $menu->id : __Config::get('START_PAGE'))); + } + + protected function getPage($entityTypeId) + { + $siteMap = $this->application->getSiteMap(); + $ar = org_glizy_objectFactory::createModel('org.glizycms.core.models.Content'); + $ar->content = new StdClass(); + $ar->content->entitySelect = $entityTypeId; + $ar->addFieldsToIndex(array('entitySelect' => 'text')); + $menuDocument = $ar->createRecordIterator()->where('entitySelect', $entityTypeId); + foreach ($menuDocument as $ar) { + $menu = $siteMap->getNodeById($ar->id); + // check if the page is visible + if ($menu && $menu->isVisible && $menu->pageType=='Entity') { + return $menu; + } + } + + return null; + } + + protected function getEntityTypeId($type) + { + $entityTypeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + return $entityTypeService->getEntityTypeId($type); + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/Paths.php b/src/admin/application/classes/movio/modules/ontologybuilder/Paths.php new file mode 100644 index 0000000..933d8d2 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/Paths.php @@ -0,0 +1,10 @@ +load('allFromTypeAllStatusAllLanguages', array('entityTypeId' => $id)); + + foreach($it as $ar) { + $ar->delete(); + } + + // cancella le proprietà collegate all'entità + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityProperties'); + $it->load('entityPropertiesFromId', array('entityId' => $id)); + + foreach($it as $ar) { + $ar->delete(); + } + + // cancella l'entità + $entity = org_glizy_objectFactory::createModel('movio.modules.ontologybuilder.models.Entity'); + $entity->delete($id); + + $entityTypeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityTypeService->invalidate(); + + org_glizy_helpers_Navigation::goHere(); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/Edit.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/Edit.php new file mode 100644 index 0000000..5cec5a9 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/Edit.php @@ -0,0 +1,7 @@ +getEditingLanguage(); + + $localeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + $keyLanguageCode = $localeService->keyAlreadyExists($lang, $key); + + if ($keyLanguageCode) { + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityLabelsDocument') + ->where('translation', $keyLanguageCode.':'.$key); + + $entityLabels = $it->first(); + $temp = $entityLabels->translation; + $temp[$language] = $text; + $entityLabels->translation = $temp; + $entityLabels->save(); + $localeService->invalidate(); + } else { + $entityLabels = org_glizy_objectFactory::createModel('movio.modules.ontologybuilder.models.EntityLabelsDocument'); + $entityLabels->key = $text; + $entityLabels->translation = array($language => $text); + $entityLabels->save(); + } + + return $entityLabels->key; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/FindEntityLabels.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/FindEntityLabels.php new file mode 100644 index 0000000..023433d --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/FindEntityLabels.php @@ -0,0 +1,36 @@ +getEditingLanguage(); + + if (is_null($term)) { + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityLabelsDocument'); + $it->load('entityLabelsFromLanguage', array('language' => $language)); + } else { + $params = array( + 'language' => $language, + 'term' => $term + ); + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityLabelsDocument'); + $it->load('entityLabelsFromTerm', $params); + } + + $labels = array(); + + //org_glizy_dataAccessDoctrine_DataAccess::enableLogging(); + foreach($it as $ar) { + $labels[] = array( + 'id' => $ar->key, + 'text' => $ar->translation[$language] + ); + } + + //die; + + return $labels; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetDictionaries.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetDictionaries.php new file mode 100644 index 0000000..4f2e19e --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetDictionaries.php @@ -0,0 +1,20 @@ +getAllDictionaries(); + + $result = array(); + + foreach ($dictionaries as $dictionary) { + $result[] = array( + 'id' => $dictionary->getId(), + 'name' => $dictionary->title + ); + } + + return $result; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetFieldTypes.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetFieldTypes.php new file mode 100644 index 0000000..6d41ed1 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetFieldTypes.php @@ -0,0 +1,23 @@ +getLanguage(); + + $fieldTypeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.FieldTypeService'); + $allTypes = $fieldTypeService->getAllTypes(); + + $fieldTypes = array(); + + foreach($allTypes as $key => $value) { + $fieldTypes[] = array( + 'id' => $key, + 'name' => $value['translation'][$language] + ); + } + + return $fieldTypes; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetLanguages.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetLanguages.php new file mode 100644 index 0000000..5279d9d --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetLanguages.php @@ -0,0 +1,20 @@ + $ar->language_name, + 'language_code' => $ar->language_code + ); + } + + return $languages; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetModules.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetModules.php new file mode 100644 index 0000000..7526352 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetModules.php @@ -0,0 +1,21 @@ +showInOntologyBuilder) { + $result[] = array( + 'id' => $module->id, + 'name' => $module->name + ); + } + } + + return $result; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetRelationTypes.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetRelationTypes.php new file mode 100644 index 0000000..11756c9 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/GetRelationTypes.php @@ -0,0 +1,27 @@ +getLanguage(); + + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.RelationTypesDocument'); + //$it->load('relationTypesFromLanguage', array('language' => $language)); + $it->orderBy('translation'); + + $relationTypes = array(); + + foreach($it as $ar) { + $r = array( + 'id' => $ar->key, + 'name' => $ar->translation[$language] ? $ar->translation[$language] : $ar->key + ); + + $relationTypes[$r['id']] = $r; + } + + return $relationTypes; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/LoadEntity.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/LoadEntity.php new file mode 100644 index 0000000..34bcbd1 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/LoadEntity.php @@ -0,0 +1,70 @@ +load($entityId); + + $language = $this->application->getEditingLanguage(); + + $localeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + + $entity = array( + "id" => $entityModel->entity_id, + "nameId" => $entityModel->entity_name, + "nameText" => $localeService->getTranslation($language, $entityModel->entity_name), + "showRelationsGraph" => $entityModel->entity_show_relations_graph, + ); + + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.Entity'); + $it->load('allButNot', array('entityId' => $entityId)); + + $entity["entities"] = array(); + + foreach($it as $ar) { + $entity["entities"][] = array( + "id" => $ar->entity_id, + "name" => $localeService->getTranslation($language, $ar->entity_name) + ); + } + + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityProperties'); + $it->load('entityPropertiesFromId', array('entityId' => $entityId)); + + $entity["properties"] = array(); + + foreach($it as $ar) { + + $entity["properties"][] = array( + "id" => $ar->entity_properties_id, + "type" => $ar->entity_properties_type, + "target" => $ar->entity_properties_target_FK_entity_id, + "labelId" => $ar->entity_properties_label_key, + "labelText" => $localeService->getTranslation($language, $ar->entity_properties_label_key), + "required" => $ar->entity_properties_required == 1, + "showLabelInFrontend" => $ar->entity_properties_show_label_in_frontend == 1, + "relationShow" => $ar->entity_properties_relation_show, + "dcField" => $ar->entity_properties_dublic_core, + "rowIndex" => $ar->entity_properties_row_index, + 'params' => $ar->entity_properties_params + ); + } + + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityProperties'); + $it->load('entityRelationsFromId', array('entityId' => $entityId)); + + $entity["relations"] = array(); + + foreach($it as $ar) { + $entity["relations"][] = array( + "id" => $ar->entity_properties_id, + "from" => $localeService->getTranslation($language, $ar->entity_name), + "to" => $localeService->getTranslation($language, $entity["nameText"]), + "show" => $ar->entity_properties_reference_relation_show + ); + } + + return $entity; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/SaveEntity.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/SaveEntity.php new file mode 100644 index 0000000..20316e0 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/ajax/SaveEntity.php @@ -0,0 +1,166 @@ +load($entity['id']); + $entityModel->entity_name = $entity['name']; + $entityModel->entity_show_relations_graph = $entity['showRelationsGraph'] == 'true' ? 1 : 0; + + // se è una nuova entità + if ($entity['id'] == '') { + $id = $entityModel->save(); + $resultEntity['id'] = $entity['id'] = $id; + } + + $entityProperties = org_glizy_objectFactory::createModel('movio.modules.ontologybuilder.models.EntityProperties'); + // elimina dal db le proprietà cancellate dall'utente + foreach ((array) $entity['deletedRows'] as $id) { + $entityProperties->delete($id); + } + + // aggiorna i dati delle proprietà nel db + for ($i = 0; $i < count($entity['properties']); $i++) { + $property = $entity['properties'][$i]; + $entityProperties->load($property['id']); + $entityProperties->entity_properties_FK_entity_id = $entity['id']; + $entityProperties->entity_properties_type = $property['type']; + $entityProperties->entity_properties_target_FK_entity_id = $this->checkNull($property['target']); + $entityProperties->entity_properties_label_key = $property['label']; + $entityProperties->entity_properties_required = $property['required'] == 'true' ? 1 : 0; + $entityProperties->entity_properties_show_label_in_frontend = $property['showLabelInFrontend'] == 'true' ? 1 : 0; + $entityProperties->entity_properties_relation_show = $this->checkNull($property['relationShow']); + $entityProperties->entity_properties_dublic_core = $this->checkNull($property['dcField']); + $entityProperties->entity_properties_row_index = $this->checkNull($property['rowIndex']); + $entityProperties->entity_properties_params = $this->checkNull($property['params']); + $id = $entityProperties->save(); + + // se è una nuova proprietà + if ($property['id'] == '') { + $entity['properties'][$i]['id'] = $id; + $resultEntity['newProperties'][] = $id; + } + } + + foreach ((array) $entity['relations'] as $relation) { + $entityProperties->load($relation['id']); + $entityProperties->entity_properties_reference_relation_show = $relation['show']; + $entityProperties->save(); + } + + $this->entityTypeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $this->entityTypeService->invalidate(); + + // + $skinAttributesVO = org_glizy_objectFactory::createObject('movio.modules.ontologybuilder.models.vo.SkinAttributesVO'); + $this->saveSkin($skinAttributesVO, $entity); + $this->saveListSkin($skinAttributesVO, $entity); + + $entityModel->entity_skin_attributes = serialize($skinAttributesVO); + $entityModel->save(); + + return $resultEntity; + } + + private function checkNull($value) + { + return $value !== '' ? $value : null; + } + + private function saveSkin($skinAttributesVO, $entity) + { + $figure = array(); + $outsideDL = array(); + $insideDL = array(); + + $properties = (array) $entity['properties']; + ksort($properties); + foreach ($properties as $property) { + // se la proprietà non è una relazione + if ($property['target'] == '') { + $attribute = $this->entityTypeService->getAttributeIdById($property['id']); + $showLabel = $property['showLabelInFrontend'] == 'true'; + $label = $property['label']; + $type = $property['type']; + + switch ($type) { + case 'attribute.longtext': + case 'attribute.descriptivetext': + $outsideDL[] = array('type' => 'longtext', 'name' => $attribute, + 'label' => ($property['dcField'] != 'DC.Description' && $showLabel) ? $label : '' + ); + break; + + case 'attribute.image': + case 'attribute.media': + case 'attribute.externalimage': + if ($type == 'attribute.image' && count($figure)==0) { + $figure[] = array('type' => 'image', 'name' => $attribute, 'label' => ''); + } + else { + $outsideDL[] = array('type' => 'media', 'name' => $attribute, 'label' => $showLabel ? $label : ''); + } + break; + + case 'attribute.imagelist': + $outsideDL[] = array('type' => 'imagelist', 'name' => $attribute, 'label' => $showLabel ? $label : ''); + break; + + case 'attribute.medialist': + $outsideDL[] = array('type' => 'medialist', 'name' => $attribute, 'label' => $showLabel ? $label : ''); + break; + + case 'attribute.date': + $insideDL[] = array('type' => 'date', 'name' => $attribute, 'label' => $showLabel ? $label : ''); + break; + + case 'attribute.thesaurus': + $insideDL[] = array('type' => 'thesaurus', 'name' => $attribute, 'label' => $showLabel ? $label : ''); + break; + + case 'attribute.module': + $insideDL[] = array('type' => 'module', 'name' => $attribute, 'label' => $showLabel ? $label : ''); + break; + + default: + $insideDL[] = array('type' => 'property', 'name' => $attribute, 'label' => $showLabel ? $label : ''); + } + } + } + + $skinAttributesVO->setDetailAttributes($insideDL, $figure, $outsideDL); + } + + private function saveListSkin($skinAttributesVO, $entity) + { + $attribute = false; + // cerca l'attributo con dcField uguale a DC.Description + foreach ((array) $entity['properties'] as $property) { + if ($property['dcField'] == 'DC.Description') { + $attribute = $this->entityTypeService->getAttributeIdById($property['id']); + break; + } + } + + if (!$attribute) { + // cerca il primo attributo disponibile che non sia una relazione + foreach ((array) $entity['properties'] as $property) { + // verifica che l'attributo non sia una relazione e che sia testuale + if ($property['target'] == '' && preg_match('/text$/', $property['type'])) { + $attribute = $this->entityTypeService->getAttributeIdById($property['id']); + break; + } + } + } + + if ($attribute) { + $skinAttributesVO->setDescriptionAttribute($attribute); + } + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/Delete.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/Delete.php new file mode 100644 index 0000000..6b613e4 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/Delete.php @@ -0,0 +1,13 @@ +delete($entityId); + org_glizy_helpers_Navigation::goHere(); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/Togglevisibility.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/Togglevisibility.php new file mode 100644 index 0000000..571a1dd --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/Togglevisibility.php @@ -0,0 +1,15 @@ +load($entityId); + $document->setVisible($document->isVisible() ? 0 : 1); + $document->publish(); + org_glizy_helpers_Navigation::goHere(); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/ajax/GetUrl.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/ajax/GetUrl.php new file mode 100644 index 0000000..688559a --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/contentsEditor/ajax/GetUrl.php @@ -0,0 +1,56 @@ +directOutput = true; + $langCode = $this->application->getEditingLanguage(); + $valid_url_regex = '/.*/'; + if ( !$url || !preg_match( $valid_url_regex, $url ) || !$this->user->isLogged()) { + return false; + } else { + $urlArray = parse_url ($url); + $baseUrl = strstr($url, '/', true); + list($base, $domain) = explode('.', $baseUrl, 2); + if($domain === 'wikipedia.org') { + $url = str_replace("it", $langCode, $url); + } else if(strpos($url,':')) { + $url = str_replace(":", "%3A", $url); + $url = str_replace(" ", "+", $url); + } + $contents = $this->fetchUrl($url); + $contents = preg_replace('/(?=href="\/[^\/])(href="\/)/si', 'href="http://'.$baseUrl.'/' , $contents); + $contents = preg_replace('/(?=src="\/[^\/])(src="\/)/si', 'src="http://'.$baseUrl.'/' , $contents); + if($domain === 'europeana.eu') { + $contents = str_replace('\'/portal', '\'http://'.$baseUrl.'/portal', $contents); + $contents = str_replace('"/portal', '"http://'.$baseUrl.'/portal', $contents); + $this->scriptAdjust($contents, $baseUrl); + } + return array('html' =>$contents); + } + } + + private function scriptAdjust(&$contents, $baseUrl) + { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, self::BOOTSTRAPMIN); + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); + $result = curl_exec( $ch ); + curl_close( $ch ); + $result = str_replace('\'/portal', '\'http://'.$baseUrl.'/portal', $result); + $result = str_replace('"/portal', '"http://'.$baseUrl.'/portal', $result); + $destination = "../cache/bootstrap.min.js"; + $file = fopen($destination, "w+"); + fputs($file, $result); + fclose($file); + $contents = str_replace('', '', $contents); + } + + + private function fetchUrl($url) + { + return file_get_contents('http://'.$url); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entity/Index.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entity/Index.php new file mode 100644 index 0000000..30d660f --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entity/Index.php @@ -0,0 +1,20 @@ +view->_content->entitySelect; + $visualization = $this->view->loadContent('visualization'); + + // TODO: migliorare + __Request::set('entityTypeId', $entityTypeId); + $this->setComponentsAttribute('list', 'entityTypeId', $entityTypeId); + $this->setComponentsAttribute('list', 'visualization', $visualization); + + $showForm = $this->view->loadContent('showForm'); + if ('false'===$showForm) { + $this->setComponentsVisibility('filters', false); + $this->setComponentsAttribute('list', 'title', ''); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entity/ajax/Thesaurus.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entity/ajax/Thesaurus.php new file mode 100644 index 0000000..a7bf297 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entity/ajax/Thesaurus.php @@ -0,0 +1,8 @@ + 'thesaurus', 'sendOutputState' => 'thesaurus', 'sendOutputFormat' => 'html'); + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/Edit.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/Edit.php new file mode 100644 index 0000000..ade2efa --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/Edit.php @@ -0,0 +1,15 @@ +loadContent($entityId); + if ($data) $data['__id'] = $entityId; + $this->view->setData($data); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/EditDraft.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/EditDraft.php new file mode 100644 index 0000000..60a6ad9 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/EditDraft.php @@ -0,0 +1,15 @@ +loadContent($entityId, 'DRAFT'); + if ($data) $data['__id'] = $entityId; + $this->view->setData($data); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/Cancel.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/Cancel.php new file mode 100644 index 0000000..e5a8039 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/Cancel.php @@ -0,0 +1,9 @@ +directOutput = true; + return array('url' => $this->changeAction('')); + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/FindEntities.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/FindEntities.php new file mode 100644 index 0000000..ee1750e --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/FindEntities.php @@ -0,0 +1,11 @@ +findEntities($entityTypeId, $term); + return $entities; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/FindTerm.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/FindTerm.php new file mode 100644 index 0000000..079f533 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/FindTerm.php @@ -0,0 +1,21 @@ +where($fieldName, '%'.$term.'%', 'LIKE'); + + $results = array(); + + foreach($it as $ar) { + $results[] = array( + 'id' => $ar->getId(), + 'text' => $ar->$fieldName + ); + } + + return $results; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/Save.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/Save.php new file mode 100644 index 0000000..2413295 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/Save.php @@ -0,0 +1,19 @@ +saveContent(json_decode($data)); + + $this->directOutput = true; + + // se ci sono stati errori di validazione + if (is_array($id)) { + return array('errors' => $id); + } + else { + return array('set' => array('entityId' => $id)); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveClose.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveClose.php new file mode 100644 index 0000000..47e674a --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveClose.php @@ -0,0 +1,9 @@ + $this->changeAction('')); + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveDraft.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveDraft.php new file mode 100644 index 0000000..4592687 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveDraft.php @@ -0,0 +1,19 @@ +saveContent(json_decode($data), false); + + $this->directOutput = true; + + // se ci sono stati errori di validazione + if (is_array($id)) { + return array('errors' => $id); + } + else { + return array('set' => array('entityId' => $id)); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveDraftClose.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveDraftClose.php new file mode 100644 index 0000000..d7a8236 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityFormEdit/ajax/SaveDraftClose.php @@ -0,0 +1,9 @@ + $this->changeAction('')); + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/DelEntityLabel.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/DelEntityLabel.php new file mode 100644 index 0000000..b44be15 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/DelEntityLabel.php @@ -0,0 +1,13 @@ +delete($id); + + $localeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + $localeService->invalidate(); + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/LoadEntityLabels.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/LoadEntityLabels.php new file mode 100644 index 0000000..0215edc --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/LoadEntityLabels.php @@ -0,0 +1,24 @@ +groupBy('simple_document_id') + ->orderBy('translation'); + + $result = array( + "entityLabels" => array() + ); + + foreach($it as $ar) { + $result["entityLabels"][] = array( + 'id' => $ar->getId(), + 'translation' => $ar->translation + ); + } + + return $result; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/NewEntityLabel.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/NewEntityLabel.php new file mode 100644 index 0000000..98a9fe6 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/NewEntityLabel.php @@ -0,0 +1,30 @@ +language_code; + $word = __Request::get('translation_'.$code); + $translation[$code] = $word; + if ($word != '') { + $key = $word; + } + } + + $label = org_glizy_objectFactory::createModel('movio.modules.ontologybuilder.models.EntityLabelsDocument'); + $label->key = $key; + $label->translation = $translation; + $id = $label->save(); + + $localeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + $localeService->invalidate(); + + return $id; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/SetEntityLabel.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/SetEntityLabel.php new file mode 100644 index 0000000..10e2fe8 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/entityLabel/ajax/SetEntityLabel.php @@ -0,0 +1,26 @@ +load(__Request::get('pk')); + $field = __Request::get('name'); + + if (preg_match("/translation.(.+)/", $field, $m)) { + $language = $m[1]; + $translation = $label->translation; + $translation[$language] = __Request::get('value'); + $label->translation = $translation; + } + else { + $label->$field = __Request::get('value'); + } + + $label->save(); + + $localeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + $localeService->invalidate(); + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/graph/Index.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/graph/Index.php new file mode 100644 index 0000000..320f5eb --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/graph/Index.php @@ -0,0 +1,9 @@ +view->_content->entitySelect; + __Request::set('entityTypeId', $entityTypeId); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/graph/List.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/graph/List.php new file mode 100644 index 0000000..08750a2 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/graph/List.php @@ -0,0 +1,28 @@ +view->loadContent('visualization'); + + $this->setComponentsAttribute('list', 'entityTypeId', $entityTypeId); + $this->setComponentsAttribute('list', 'visualization', $visualization); + + // simulate a new page in site structure + // for update the navigation menu, breadcrumbs and page title + $entityTypeService = org_glizy_objectFactory::createObject('movio.modules.ontologybuilder.service.EntityTypeService'); + $title = $entityTypeService->getEntityTypeName($entityTypeId); + $currentMenu = $this->application->getCurrentMenu(); + $siteMap = $this->application->getSiteMap(); + $menu = org_glizy_application_SiteMap::getEmptyMenu(); + $menu['title'] = $title; + $menu['id'] = $currentMenu->id+100000; + $menu['pageType'] = $currentMenu->pageType; + $menu['url'] = __Request::get('__url__'); + $siteMap->addChildMenu($currentMenu, $menu); + + $evt = array('type' => GLZ_EVT_SITEMAP_UPDATE, 'data' => $menu['id'] ); + $this->dispatchEvent($evt); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/profile/Index.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/profile/Index.php new file mode 100644 index 0000000..ebf3d39 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/profile/Index.php @@ -0,0 +1,19 @@ +view->_content->groupId; + if (!$groupId) { + if ($this->user->isLogged()) { + $groupId = $this->user->groupId; + } + } + + if ($groupId) { + $this->setComponentsAttribute('loginCheck', 'enabled', false); + } + + __Request::set('groupId', $groupId); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/DelRelation.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/DelRelation.php new file mode 100644 index 0000000..4ca31c4 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/DelRelation.php @@ -0,0 +1,18 @@ +delete($id); + + $entityTypeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityTypeService->invalidate(); + + $localeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + $localeService->invalidate(); + + return true; + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/LoadRelations.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/LoadRelations.php new file mode 100644 index 0000000..a9c2a77 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/LoadRelations.php @@ -0,0 +1,23 @@ +groupBy('simple_document_id') + ->orderBy('translation'); + + $result = array(); + foreach($it as $ar) { + $result["relations"][] = array( + 'id' => $ar->getId(), + 'translation' => $ar->translation, + 'cardinality' => $ar->cardinality + ); + } + + return $result; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/NewRelation.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/NewRelation.php new file mode 100644 index 0000000..d75a6bc --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/NewRelation.php @@ -0,0 +1,35 @@ +language_code; + if (__Request::get('translation_'.$code)) { + $translation[$code] = __Request::get('translation_'.$code); + if (empty($key)) { + $key = $translation[$code]; + } + } + } + + $relation = org_glizy_objectFactory::createModel('movio.modules.ontologybuilder.models.RelationTypesDocument'); + $relation->key = $key; + $relation->translation = $translation; + $relation->cardinality = __Request::get('cardinality'); + $id = $relation->save(); + + $entityTypeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityTypeService->invalidate(); + + $localeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + $localeService->invalidate(); + + return $id; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/SetRelation.php b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/SetRelation.php new file mode 100644 index 0000000..7d391b6 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/controllers/relation/ajax/SetRelation.php @@ -0,0 +1,29 @@ +load(__Request::get('pk')); + $field = __Request::get('name'); + + if (preg_match("/translation.(.+)/", $field, $m)) { + $language = $m[1]; + $translation = $relation->translation; + $translation[$language] = __Request::get('value'); + $relation->translation = $translation; + } + else { + $relation->$field = __Request::get('value'); + } + + $relation->save(); + + $entityTypeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityTypeService->invalidate(); + + $localeService = $this->application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + $localeService->invalidate(); + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/Entity.php b/src/admin/application/classes/movio/modules/ontologybuilder/models/Entity.php new file mode 100644 index 0000000..4aaec6d --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/Entity.php @@ -0,0 +1,35 @@ +setTableName('entity_tbl'); + + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($this->connection); + $sequenceName = $sm->getSequenceName($this->getTableName()); + $this->setSequenceName($sequenceName); + + $fields = $sm->getFields($this->getTableName()); + + foreach ($fields as $field) { + $this->addField($field); + } + } + + function query_all($iterator) { + $iterator->select('*') + ->orderBy('entity_name'); + } + + function query_allButNot($iterator, $entityId) { + $iterator->select('*') + ->where("entity_id <> $entityId") + ->orderBy('entity_name'); + } + + function query_allWithProperties($iterator) { + $iterator->select('*') + ->leftJoin('t1', 'entity_properties_tbl', 'e', $iterator->expr()->eq('t1.entity_id', 'e.entity_properties_FK_entity_id')) + ->orderBy('entity_properties_row_index'); + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityDocument.php b/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityDocument.php new file mode 100644 index 0000000..bd3b5e0 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityDocument.php @@ -0,0 +1,65 @@ +addField(new org_glizy_dataAccessDoctrine_DbField( + 'title', + Doctrine\DBAL\Types\Type::STRING, + 255, + false, + null, + '') + ); + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + 'subtitle', + Doctrine\DBAL\Types\Type::STRING, + 255, + false, + null, + '') + ); + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + 'url', + Doctrine\DBAL\Types\Type::STRING, + 255, + false, + null, + '') + ); + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + 'profile', + Doctrine\DBAL\Types\Type::STRING, + 255, + false, + null, + '', + false) + ); + + } + + function query_All($iterator) { + $iterator->whereTypeIs('entity%', 'LIKE'); + } + + function query_allFromTypeAllStatusAllLanguages($iterator, $entityTypeId) { + $iterator->whereTypeIs('entity'.$entityTypeId) + ->allStatuses() + ->allLanguages(); + } + + function query_allFromTypeRequest($iterator) { + $iterator->whereTypeIs('entity'.__Request::get('entityTypeId')) + ->orderBy('title'); + } + + function query_getReferenceRelations($iterator, $entityTypeId, $attribute, $value) { + $iterator->where($attribute, $value) + ->whereTypeIs('entity'.$entityTypeId); + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityLabelsDocument.php b/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityLabelsDocument.php new file mode 100755 index 0000000..808f64f --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityLabelsDocument.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use Doctrine\DBAL\Types\Type; + +class movio_modules_ontologybuilder_models_EntityLabelsDocument extends org_glizycms_models_ActiveRecordSimpleDocumentArraysIndexed +{ + function __construct($connectionNumber=0) { + parent::__construct($connectionNumber); + $this->setType('entity_labels_tbl'); + + $notNullAndText = new org_glizy_validators_CompositeValidator(); + $notNullAndText->add(new org_glizy_validators_NotNull()); + $notNullAndText->add(new org_glizy_validators_Text()); + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + 'key', + Doctrine\DBAL\Types\Type::STRING, + 255, + false, + $notNullAndText, + '', + true, + false, + '', + org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED + ) + ); + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + 'translation', + Doctrine\DBAL\Types\Type::TARRAY, + 255, + false, + new org_glizy_validators_NotNull(), + '', + true, + false, + '', + org_glizy_dataAccessDoctrine_DbField::INDEXED + ) + ); + } + + function query_all($iterator) { + } + + function query_entityLabelsFromLanguage($iterator, $language) { + $iterator->where('translation', "$language:%", 'LIKE'); + } + + function query_entityLabelsFromTerm($iterator, $language, $term) { + $iterator->where('translation', "$language:$term%", 'LIKE') + ->orderBy('translation'); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityMenu.xml b/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityMenu.xml new file mode 100644 index 0000000..314fd93 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityMenu.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityModel.xml b/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityModel.xml new file mode 100644 index 0000000..80e3d37 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityModel.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityProperties.php b/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityProperties.php new file mode 100644 index 0000000..933cafe --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/EntityProperties.php @@ -0,0 +1,31 @@ +setTableName('entity_properties_tbl'); + + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($this->connection); + $sequenceName = $sm->getSequenceName($this->getTableName()); + $this->setSequenceName($sequenceName); + + $fields = $sm->getFields($this->getTableName()); + + foreach ($fields as $field) { + $this->addField($field); + } + } + + function query_entityPropertiesFromId($iterator, $entityId) { + $iterator->select('*') + ->where("entity_properties_FK_entity_id = $entityId") + ->orderBy('entity_properties_row_index'); + } + + function query_entityRelationsFromId($iterator, $entityId) { + $iterator->select('*') + ->join('t1', 'entity_tbl', 'e', $iterator->expr()->eq('t1.entity_properties_FK_entity_id', 'e.entity_id')) + ->where("entity_properties_target_FK_entity_id = $entityId") + ->orderBy('e.entity_name'); + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/FieldTypesDocument.php b/src/admin/application/classes/movio/modules/ontologybuilder/models/FieldTypesDocument.php new file mode 100644 index 0000000..96f66cf --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/FieldTypesDocument.php @@ -0,0 +1,57 @@ +setType('field_types_tbl'); + + $notNullAndText = new org_glizy_validators_CompositeValidator(); + $notNullAndText->add(new org_glizy_validators_NotNull()); + $notNullAndText->add(new org_glizy_validators_Text()); + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + 'key', + Doctrine\DBAL\Types\Type::STRING, + 255, + false, + $notNullAndText, + '', + true, + false, + '', + org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED + ) + ); + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + 'map_to', + Doctrine\DBAL\Types\Type::STRING, + 255, + false, + $notNullAndText, + '', + true, + false, + '', + org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED + ) + ); + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + 'translation', + Doctrine\DBAL\Types\Type::TARRAY, + 255, + false, + new org_glizy_validators_NotNull(), + '', + true, + false, + '', + org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED + ) + ); + } + + function query_all($iterator) { + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/Languages.php b/src/admin/application/classes/movio/modules/ontologybuilder/models/Languages.php new file mode 100644 index 0000000..84382ef --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/Languages.php @@ -0,0 +1,23 @@ +setTableName('languages_tbl'); + + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($this->connection); + $sequenceName = $sm->getSequenceName($this->getTableName()); + $this->setSequenceName($sequenceName); + + $fields = $sm->getFields($this->getTableName()); + + foreach ($fields as $field) { + $this->addField($field); + } + } + + function query_all($iterator) { + $iterator->select('*') + ->orderBy('language_order'); + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/RelationTypesDocument.php b/src/admin/application/classes/movio/modules/ontologybuilder/models/RelationTypesDocument.php new file mode 100755 index 0000000..fa017a4 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/RelationTypesDocument.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use Doctrine\DBAL\Types\Type; + +class movio_modules_ontologybuilder_models_RelationTypesDocument extends org_glizycms_models_ActiveRecordSimpleDocumentArraysIndexed +{ + function __construct($connectionNumber=0) { + parent::__construct($connectionNumber); + $this->setType('relation_types_tbl'); + + $notNullAndText = new org_glizy_validators_CompositeValidator(); + $notNullAndText->add(new org_glizy_validators_NotNull()); + $notNullAndText->add(new org_glizy_validators_Text()); + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + 'key', + Doctrine\DBAL\Types\Type::STRING, + 255, + false, + $notNullAndText, + '', + true, + false, + '', + org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED + ) + ); + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + 'translation', + Doctrine\DBAL\Types\Type::TARRAY, + 255, + false, + new org_glizy_validators_NotNull(), + '', + true, + false, + '', + org_glizy_dataAccessDoctrine_DbField::INDEXED + ) + ); + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + 'cardinality', + Doctrine\DBAL\Types\Type::INTEGER, + 1, + false, + new org_glizy_validators_NotNull(), + 0, + true, + false, + '', + org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED + ) + ); + } + + function query_all($iterator) { + } + + function query_relationTypesFromLanguage($iterator, $language) { + $iterator->where("translation LIKE $language:%") + ->orderBy('translation'); + } + + function query_relationLabelsFromTerm($iterator, $language, $term) { + $iterator->where('translation', "$language:$term%", 'LIKE') + ->orderBy('translation'); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/proxy/EntityProxy.php b/src/admin/application/classes/movio/modules/ontologybuilder/models/proxy/EntityProxy.php new file mode 100644 index 0000000..edc5b4f --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/proxy/EntityProxy.php @@ -0,0 +1,518 @@ + '1'); + } + + $document = org_glizy_objectFactory::createObject('org.glizy.dataAccessDoctrine.ActiveRecordDocument'); + + $result = $document->load($entityId, $status); + + if (!$result) { + $languageProxy = __ObjectFactory::createObject('org.glizycms.languages.models.proxy.LanguagesProxy'); + $document->load($entityId, $status, $languageProxy->getDefaultLanguageId()); + } + + $data['__isVisible'] = $document->isVisible(); + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('title', Doctrine\DBAL\Types\Type::STRING, 255, false, null,'', false)); + $data['title'] = $document->title; + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('subtitle', Doctrine\DBAL\Types\Type::STRING, 255, false, null,'', false)); + $data['subtitle'] = $document->subtitle; + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('url', Doctrine\DBAL\Types\Type::STRING, 255, false, null, '', true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $data['url'] = $document->url; + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('profile', Doctrine\DBAL\Types\Type::TARRAY, 255, false, null, '', false)); + $data['profile'] = $document->profile; + + $application = org_glizy_ObjectValues::get('org.glizy', 'application' ); + $fieldTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.FieldTypeService'); + + $documentEntityTypeId = str_replace('entity', '', $document->getType()); + $data['entityTypeId'] = $documentEntityTypeId; + + $entityTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityTypeProperties = $entityTypeService->getEntityTypeProperties($documentEntityTypeId); + + foreach((array) $entityTypeProperties as $entityTypeProperty) { + $attribute = $entityTypeService->getAttributeIdByProperties($entityTypeProperty); + + // se l'attributo non è una relazione + if (is_null($entityTypeProperty['entity_properties_target_FK_entity_id'])) { + $type = $fieldTypeService->getTypeMapping($entityTypeProperty['entity_properties_type']); + + if ($fieldTypeService->isTypeIndexed($entityTypeProperty['entity_properties_type']) == true) { + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, $type, 255, false, null,'', false)); + } + else { + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, $type, 255, false, null, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + } + + $value = $document->$attribute; + if (is_object($value) && property_exists($value, '__restore')) { + foreach($value->__restore as $k=>$v) { + $data[$k] = $v; + } + } else { + $data[$attribute] = $value; + } + } + // se l'attributo è una relazione; + else { + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, Doctrine\DBAL\Types\Type::TEXT, 1000, false, null, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::INDEXED)); + + $relations = array(); + + if ($document->$attribute != '') { + foreach ($document->$attribute as $toEntityId) { + $title = $this->getEntityTitle($toEntityId); + if ($title) { + $relations[] = array( + 'id' => $toEntityId, + 'text' => $title + ); + } + } + } + + $data[$attribute] = $relations; + } + } + + return $data; + } + + public function saveContent($data, $publish=true) + { + $entityTypeId = $data->entityTypeId; + $entityId = $data->entityId; + + $document = org_glizy_objectFactory::createObject('org.glizy.dataAccessDoctrine.ActiveRecordDocument'); + + $document->setType('entity'.$entityTypeId); + + $result = $document->load($entityId, 'LAST_MODIFIED'); + + if (!$result) { + $languageProxy = __ObjectFactory::createObject('org.glizycms.languages.models.proxy.LanguagesProxy'); + $defaultLanguageId = $languageProxy->getDefaultLanguageId(); + $document->load($entityId, 'LAST_MODIFIED', $defaultLanguageId); + $document->setLanguage($languageProxy->getLanguageId()); + } + + $document->setVisible($data->__isVisible); + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('title', Doctrine\DBAL\Types\Type::STRING, 255, false, null,'', false)); + $document->title = $data->title; + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('subtitle', Doctrine\DBAL\Types\Type::STRING, 255, false, null,'', false)); + $document->subtitle = $data->subtitle; + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('url', Doctrine\DBAL\Types\Type::STRING, 255, false, null, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $originalUrl = $document->url; + $document->url = $data->url; + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('profile', Doctrine\DBAL\Types\Type::TARRAY, 255, false, null, '', false)); + $document->profile = $data->profile; + + $application = org_glizy_ObjectValues::get('org.glizy', 'application' ); + $fieldTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.FieldTypeService'); + + $entityTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityTypeProperties = $entityTypeService->getEntityTypeProperties($entityTypeId); + + $fulltext = $document->title.org_glizycms_Glizycms::FULLTEXT_DELIMITER; + + if ($document->subtitle) { + $fulltext .= $document->subtitle.org_glizycms_Glizycms::FULLTEXT_DELIMITER; + } + + foreach((array)$entityTypeProperties as $entityTypeProperty) { + $attribute = $entityTypeService->getAttributeIdByProperties($entityTypeProperty); + + // se l'attributo non è una relazione + if (is_null($entityTypeProperty['entity_properties_target_FK_entity_id'])) { + $type = $fieldTypeService->getTypeMapping($entityTypeProperty['entity_properties_type']); + + // TODO permettere di definire in fieldTypes.xml altri validatori per ogni tipo + if ($entityTypeProperty['entity_properties_required']) { + $validator = new org_glizy_validators_NotNull(); + } + else { + $validator = null; + } + + if ($fieldTypeService->isTypeIndexed($entityTypeProperty['entity_properties_type']) == true) { + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, $type, 255, false, $validator, '', false)); + } + else { + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, $type, 255, false, $validator, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + } + } + // se l'attributo è una relazione; + else { + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, Doctrine\DBAL\Types\Type::TEXT, 1000, false, null, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::INDEXED)); + } + + if (property_exists($data, $attribute)) { + $value = $data->$attribute; + $document->$attribute = $value; + } else { + // se l'attributo non è nei dati può essere dovuto + // ad un component custom (es phtogallery) che ha più valori da salvare + $value = array('__restore' => new StdClass); + foreach($data as $k=>$v) { + if (strpos($k, $attribute)===0) { + $value['__restore']->$k = $v; + } + } + $document->$attribute = $value; + } + + if ($fieldTypeService->isTypeIndexed($entityTypeProperty['entity_properties_type'])) { + $stripped = trim(strip_tags($value)); + if (!is_numeric($value) && strlen($stripped) > org_glizycms_Glizycms::FULLTEXT_MIN_CHAR ) { + $fulltext .= $stripped.org_glizycms_Glizycms::FULLTEXT_DELIMITER; + } + } + } + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('fulltext', Doctrine\DBAL\Types\Type::TEXT, 1000, false, null, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::FULLTEXT)); + $document->fulltext = $fulltext; + + try { + if ($publish) { + $id = $document->publish(); + } else { + if (__Config::get('glizycms.content.history')) { + $id = $document->saveHistory(); + } else { + $id = $document->save(); + } + } + + $speakingUrlProxy = __Config::get('glizycms.speakingUrl') ? org_glizy_ObjectFactory::createObject('org.glizycms.speakingUrl.models.proxy.SpeakingUrlProxy') : null; + + if ($speakingUrlProxy) { + $languageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + + if ($originalUrl != $document->url) { + //valida l'url + if (!$speakingUrlProxy->validate($document->url, $languageId, $id, 'movio.modules.ontologybuilder.content')) { + throw new org_glizy_validators_ValidationException(array('Url non valido perché già utilizzato')); + } else { + $options = array('entityTypeId' => $entityTypeId); + // aggiorna l'url parlante + $speakingUrlProxy->addUrl($document->url, $languageId, $id, 'movio.modules.ontologybuilder.content', $options); + org_glizy_cache_CacheFile::cleanPHP('../cache/'); + } + } + } + } + catch (org_glizy_validators_ValidationException $e) { + return $e->getErrors(); + } + + return $id; + } + + public function loadContentFrontend($entityId) + { + if ($entityId == 0) { + return (object) null; + } + + $data = array(); + + $document = org_glizy_objectFactory::createObject('org.glizy.dataAccessDoctrine.ActiveRecordDocument'); + + $document->load($entityId); + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('title', Doctrine\DBAL\Types\Type::STRING, 255, false, null, '', false)); + $data['title'] = $document->title; + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('subtitle', Doctrine\DBAL\Types\Type::STRING, 255, false, null, '', false)); + $data['subtitle'] = $document->subtitle; + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('url', Doctrine\DBAL\Types\Type::STRING, 255, false, null, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $data['url'] = $document->url; + + $document->addField(new org_glizy_dataAccessDoctrine_DbField('profile', Doctrine\DBAL\Types\Type::TARRAY, 255, false, null, '', false)); + $data['profile'] = $document->profile; + + $application = org_glizy_ObjectValues::get('org.glizy', 'application' ); + $fieldTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.FieldTypeService'); + + $documentEntityTypeId = str_replace('entity', '', $document->getType()); + $data['entityTypeId'] = $documentEntityTypeId; + + $entityTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityTypeProperties = $entityTypeService->getEntityTypeProperties($documentEntityTypeId); + + $localeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + $language = $application->getLanguage(); + + $relationId = 0; + + foreach((array) $entityTypeProperties as $entityTypeProperty) { + $attribute = $entityTypeService->getAttributeIdByProperties($entityTypeProperty); + + // se l'attributo non è una relazione + if (is_null($entityTypeProperty['entity_properties_target_FK_entity_id'])) { + $type = $fieldTypeService->getTypeMapping($entityTypeProperty['entity_properties_type']); + + if ($fieldTypeService->isTypeIndexed($entityTypeProperty['entity_properties_type']) == true) { + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, $type, 255, false, null, '', false)); + } + else { + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, $type, 255, false, null, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + } + + if ($entityTypeProperty['entity_properties_type'] == 'attribute.internallink') { + $speakingUrlManager = $application->retrieveProxy('org.glizycms.speakingUrl.Manager'); + $value = $speakingUrlManager->makeUrl($document->$attribute); + } else { + $value = $document->$attribute; + } + + if (is_object($value) && property_exists($value, '__restore')) { + foreach($value->__restore as $k=>$v) { + $data[$k] = $v; + } + } else { + $data[$attribute] = $value; + } + } else { // se l'attributo è una relazione; + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, Doctrine\DBAL\Types\Type::TEXT, 1000, false, null, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::INDEXED)); + + $relations = array(); + + if ($document->$attribute != '') { + foreach ($document->$attribute as $toEntityId) { + $content = $this->loadContent($toEntityId); + $content['document_id'] = $toEntityId; + $relations[] = $content; + } + } + + $data[$attribute]['id'] = 'relation'.$relationId++; + $data[$attribute]['content'] = $relations; + $data[$attribute]['relation'] = $localeService->getTranslation($language, $entityTypeProperty['entity_properties_label_key']); + } + } + + $referenceRelations = $entityTypeService->getEntityTypeReferenceRelations($documentEntityTypeId); + + $relations = array(); + + foreach((array) $referenceRelations as $referenceRelation) { + $entityTypeId = $referenceRelation['entity_properties_FK_entity_id']; + $attribute = $entityTypeService->getAttributeIdByProperties($referenceRelation); + + $document = org_glizy_objectFactory::createModel('movio.modules.ontologybuilder.models.EntityDocument'); + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, Doctrine\DBAL\Types\Type::TEXT, 1000, false, null, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $it = $document->createRecordIterator(); + $it->load('getReferenceRelations', array('entityTypeId' => $entityTypeId, 'attribute' => $attribute, 'value' => $entityId)); + + foreach ($it as $ar) { + $content = $ar->getValuesAsArray(); + $content['entityTypeId'] = str_replace('entity', '', $ar->getType()); + $data['__reference_relations']['__'.$ar->getType()]['content'][] = $content; + } + + if ($it->count() != 0) { + $type = $ar->getType(); + $relatedEntityName = $entityTypeService->getEntityTypeName(str_replace('entity', '', $type)); + $data['__reference_relations']['__'.$type]['id'] = 'relation'.$relationId; + $data['__reference_relations']['__'.$type]['relation'] = $relatedEntityName; + $data['__reference_relations']['__'.$type]['show'] = $referenceRelation['entity_properties_reference_relation_show']; + } + } + + return $data; + } + + public function getRelations($entityId) + { + if ($entityId == 0) { + return array(); + } + + $data = array(); + + $document = org_glizy_objectFactory::createObject('org.glizy.dataAccessDoctrine.ActiveRecordDocument'); + $result = $document->load($entityId); + + $data['title'] = $document->title; + + $application = org_glizy_ObjectValues::get('org.glizy', 'application' ); + $fieldTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.FieldTypeService'); + + $documentEntityTypeId = str_replace('entity', '', $document->getType()); + + $entityTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityTypeProperties = $entityTypeService->getEntityTypeProperties($documentEntityTypeId); + + $localeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + $language = $application->getLanguage(); + + $relations = array(); + + foreach((array) $entityTypeProperties as $entityTypeProperty) { + $attribute = $entityTypeService->getAttributeIdByProperties($entityTypeProperty); + + // se l'attributo è una relazione; + if (!is_null($entityTypeProperty['entity_properties_target_FK_entity_id'])) { + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, Doctrine\DBAL\Types\Type::TEXT, 1000, false, null, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::INDEXED)); + + if ($document->$attribute != '') { + foreach ($document->$attribute as $toEntityId) { + $relatedDocument = org_glizy_objectFactory::createObject('org.glizy.dataAccessDoctrine.ActiveRecordDocument'); + $result = $relatedDocument->load($toEntityId); + + if ($result == true) { + $relation = array( + 'entityTypeId' => str_replace('entity', '', $relatedDocument->getType()), + 'document_id' => $toEntityId, + 'title' => $relatedDocument->title, + 'relation' => $localeService->getTranslation($language, 'rel:'.$entityTypeProperty['entity_properties_type']) + ); + + $relations[] = $relation; + } + } + } + } + } + + $data['relations'] = $relations; + + $referenceRelations = $entityTypeService->getEntityTypeReferenceRelations($documentEntityTypeId); + $relations = array(); + + foreach((array) $referenceRelations as $referenceRelation) { + $entityTypeId = $referenceRelation['entity_properties_FK_entity_id']; + $attribute = $entityTypeService->getAttributeIdByProperties($referenceRelation); + + $document = org_glizy_objectFactory::createModel('movio.modules.ontologybuilder.models.EntityDocument'); + $document->addField(new org_glizy_dataAccessDoctrine_DbField($attribute, Doctrine\DBAL\Types\Type::TEXT, 1000, false, null, '', false, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $it = $document->createRecordIterator(); + $it->load('getReferenceRelations', array('entityTypeId' => $entityTypeId, 'attribute' => $attribute, 'value' => $entityId)); + + foreach ($it as $ar) { + $relation = array( + 'entityTypeId' => $entityTypeId, + 'document_id' => $ar->getId(), + 'title' => $ar->title, + 'relation' => $localeService->getTranslation($language, $referenceRelation['entity_properties_type']) + ); + + $relations[] = $relation; + } + } + + $data['reference_relations']= $relations; + + return $data; + } + + public function getEntityTitle($entityId) + { + $document = org_glizy_objectFactory::createObject('org.glizy.dataAccessDoctrine.ActiveRecordDocument'); + $result = $document->load($entityId); + + if ($result == false) { + return null; + } else { + return $document->title; + } + } + + public function findEntities($entityTypeId, $name) + { + $document = org_glizy_objectFactory::createObject('org.glizy.dataAccessDoctrine.ActiveRecordDocument'); + $document->addField(new org_glizy_dataAccessDoctrine_DbField('title', Doctrine\DBAL\Types\Type::STRING, 255, false, null,'', false)); + + $it = $document->createRecordIterator() + ->whereTypeIs('entity'.$entityTypeId); + + if ($name) { + $it->where('title', "%$name%", 'LIKE'); + } + + $entities = array(); + + foreach($it as $ar) { + $entities[] = array( + 'id' => $ar->getId(), + 'text' => $ar->title + ); + } + + return $entities; + } + + public function findTerm($fieldName, $model, $query, $term, $proxyParams) + { + $document = org_glizy_objectFactory::createObject('org.glizy.dataAccessDoctrine.ActiveRecordDocument'); + $document->addField(new org_glizy_dataAccessDoctrine_DbField($fieldName, Doctrine\DBAL\Types\Type::STRING, 255, false, null,'', false)); + + $it = $document->createRecordIterator() + ->whereTypeIs('entity'.$proxyParams->entityTypeId); + + if ($term != '') { + $it->where($fieldName, '%'.$term.'%', 'LIKE'); + } + + $it->orderBy($fieldName); + + $result = array(); + + foreach($it as $ar) { + $result[] = array( + 'id' => $ar->$fieldName, + 'text' => $ar->$fieldName + ); + } + + return $result; + } + + public function getContentsByProfile($groupId) + { + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $entityTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityResolver = org_glizy_objectFactory::createObject('movio.modules.ontologybuilder.EntityResolver'); + + $arGroup = org_glizy_objectFactory::createModel('org.glizycms.groupManager.models.UserGroup'); + $arGroup->load($groupId); + + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityDocument') + ->load('All') + ->where('profile', $arGroup->usergroup_name) + ->orderBy('title'); + + foreach ($it as $ar) { + $entityTypeId = $entityTypeService->getEntityTypeId($ar->getType()); + $descriptionAttribute = $entityTypeService->getDescriptionAttribute($entityTypeId); + $arMenu = $entityResolver->getMenuVisibleEntity($entityTypeId); + + if ($arMenu) { + $result[] = array( + 'title' => $ar->title, + 'description' => ($descriptionAttribute && $ar->keyInDataExists($descriptionAttribute)) ? $ar->$descriptionAttribute : '', + 'url' => __Routing::makeUrl('showEntityDetail', array('pageId' => $arMenu->id, 'entityTypeId' => $entityTypeId,'document_id' => $ar->getId())) + ); + } + } + + return $result; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/proxy/ModelProxy.php b/src/admin/application/classes/movio/modules/ontologybuilder/models/proxy/ModelProxy.php new file mode 100644 index 0000000..3537451 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/proxy/ModelProxy.php @@ -0,0 +1,23 @@ +moduleId); + + $it = org_glizy_ObjectFactory::createModelIterator($model->classPath.'.models.Model') + ->where('title', '%'.$term.'%', 'ILIKE') + ->orderBy('title'); + + $result = array(); + + foreach ($it as $ar) { + $result[] = array( + 'id' => $ar->getId(), + 'text' => $ar->title, + ); + } + + return $result; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/models/vo/SkinAttributesVO.php b/src/admin/application/classes/movio/modules/ontologybuilder/models/vo/SkinAttributesVO.php new file mode 100644 index 0000000..89c26f6 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/models/vo/SkinAttributesVO.php @@ -0,0 +1,20 @@ +description = $name; + } + + public function setDetailAttributes($properties, $figure, $body) + { + $this->properties = $properties; + $this->figure = $figure; + $this->body = $body; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/service/EntityTypeService.php b/src/admin/application/classes/movio/modules/ontologybuilder/service/EntityTypeService.php new file mode 100755 index 0000000..35d4738 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/service/EntityTypeService.php @@ -0,0 +1,209 @@ +init(); + } + + public function init() { + $options = array( + 'cacheDir' => org_glizy_Paths::get('CACHE_CODE'), + 'lifeTime' => -1, + 'readControlType' => '', + 'fileExtension' => '.php' + ); + $cacheObj = &org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFile', $options); + $cacheFileName = $cacheObj->verify(get_class( $this )); + + if ( $cacheFileName === false ) + { + $this->loadData(); + $cacheObj->save( serialize( $this->entityTypes ), NULL, get_class( $this ) ); + $cacheObj->getFileName(); + } + else + { + $this->entityTypes = unserialize( file_get_contents( $cacheFileName ) ); + } + } + + public function invalidate() + { + org_glizy_cache_CacheFile::cleanPHP(); + org_glizy_cache_CacheFile::cleanPHP(__Paths::get( 'BASE' ).'cache/'); + $this->init(); + } + + private function loadData() + { + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.RelationTypesDocument', 'all'); + + $relations = array(); + + foreach($it as $ar) { + $relations[$ar->key] = array( + 'translation' => $ar->translation, + 'cardinality' => $ar->cardinality + ); + } + + $this->entityTypes["relations"] = $relations; + + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.Entity', 'allWithProperties'); + + $entityTypes = array(); + $descriptionAttributeDc = array(); + + foreach($it as $ar) { + $entityTypes[$ar->entity_id]['name'] = $ar->entity_name; + $entityTypes[$ar->entity_id]['entity_show_relations_graph'] = $ar->entity_show_relations_graph; + $entityTypes[$ar->entity_id]['entity_skin_attributes'] = $ar->entity_skin_attributes; + + if ($ar->entity_properties_id) { + $attributeId = $this->getAttributeIdById($ar->entity_properties_id); + + $entityTypes[$ar->entity_id]['properties'][$attributeId] = array( + 'entity_properties_id' => $ar->entity_properties_id, + 'entity_properties_FK_entity_id' => $ar->entity_properties_FK_entity_id, + 'entity_properties_type' => $ar->entity_properties_type, + 'entity_properties_target_FK_entity_id' => $ar->entity_properties_target_FK_entity_id, + 'entity_properties_label_key' => $ar->entity_properties_label_key, + 'entity_properties_required' => $ar->entity_properties_required, + 'entity_properties_show_label_in_frontend' => $ar->entity_properties_show_label_in_frontend, + 'entity_properties_relation_show' => $ar->entity_properties_relation_show, + 'entity_properties_reference_relation_show' => $ar->entity_properties_reference_relation_show, + 'entity_properties_dublic_core' => $ar->entity_properties_dublic_core, + 'entity_properties_row_index' => $ar->entity_properties_row_index, + 'entity_properties_params' => $ar->entity_properties_params + ); + + $entityTypes[$ar->entity_id]['types'][$ar->entity_properties_type][] = $attributeId; + + // trova l'attributo immagine + if (!isset($entityTypes[$ar->entity_id]['imageAttribute']) && $ar->entity_properties_type == 'attribute.image' || $ar->entity_properties_type == 'attribute.image') { + $entityTypes[$ar->entity_id]['imageAttribute'] = $attributeId; + } + + // trova l'attributo descrizione + if (!isset($descriptionAttributeDc[$ar->entity_id])) { + // cerca l'attributo con dcField uguale a DC.Description + if ($ar->entity_properties_dublic_core == 'DC.Description') { + $entityTypes[$ar->entity_id]['descriptionAttribute'] = $attributeId; + $descriptionAttributeDc[$ar->entity_id] = true; + } else { + // verifica che l'attributo non sia una relazione e che sia testuale + if (!isset($entityTypes[$ar->entity_id]['descriptionAttribute']) && $ar->entity_properties_dublic_core == '' && preg_match('/text$/', $ar->entity_properties_type)) { + $entityTypes[$ar->entity_id]['descriptionAttribute'] = $attributeId; + } + } + } + } + } + + foreach($entityTypes as $entityId => $entity) { + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityProperties'); + $it->load('entityRelationsFromId', array('entityId' => $entityId)); + foreach($it as $ar) { + $entityTypes[$entityId]['reference_relations'][] = array ( + 'entity_properties_id' => $ar->entity_properties_id, + 'entity_properties_FK_entity_id' => $ar->entity_properties_FK_entity_id, + 'entity_properties_type' => $ar->entity_properties_type, + 'entity_properties_target_FK_entity_id' => $ar->entity_properties_target_FK_entity_id, + 'entity_properties_label_key' => $ar->entity_properties_label_key, + 'entity_properties_required' => $ar->entity_properties_required, + 'entity_properties_show_label_in_frontend' => $ar->entity_properties_show_label_in_frontend, + 'entity_properties_relation_show' => $ar->entity_properties_relation_show, + 'entity_properties_reference_relation_show' => $ar->entity_properties_reference_relation_show, + 'entity_properties_dublic_core' => $ar->entity_properties_dublic_core, + 'entity_properties_row_index' => $ar->entity_properties_row_index, + 'entity_properties_params' => $ar->entity_properties_params + ); + } + } + + $this->entityTypes["entityTypes"] = $entityTypes; + } + + public function getEntityTypeId($entityType) + { + return str_replace('entity', '', $entityType); + } + + public function getAttributeIdById($id) + { + return 'attribute'.$id; + } + + public function getAttributeIdByAr($ar) + { + return 'attribute'.$ar->entity_properties_id; + } + + public function getAttributeIdByProperties($properties) + { + return 'attribute'.$properties['entity_properties_id']; + } + + public function getAttributeByType($entityTypeId, $attributeType) + { + $result = $this->entityTypes["entityTypes"][$entityTypeId]['types'][$attributeType]; + + if (count($result) == 1) { + return $result[0]; + } else { + return $result; + } + } + + public function getRelations() + { + return $this->entityTypes["relations"]; + } + + public function getRelation($relation) + { + return $this->entityTypes["relations"][$relation]; + } + + public function getEntityTypeName($entityTypeId) + { + return __Tp($this->entityTypes["entityTypes"][$entityTypeId]['name']); + } + + public function getEntityTypeAttribute($entityTypeId, $attribute) + { + return __Tp($this->entityTypes["entityTypes"][$entityTypeId][$attribute]); + } + + public function getEntityTypeProperties($entityTypeId) + { + return $this->entityTypes["entityTypes"][$entityTypeId]['properties']; + } + + public function getEntityTypeAttributeProperties($entityTypeId, $attributeId) + { + return $this->entityTypes["entityTypes"][$entityTypeId]['properties'][$attributeId]; + } + + public function getEntityTypeReferenceRelations($entityTypeId) + { + return $this->entityTypes["entityTypes"][$entityTypeId]['reference_relations']; + } + + public function getDescriptionAttribute($entityTypeId) + { + return $this->entityTypes["entityTypes"][$entityTypeId]['descriptionAttribute']; + } + + public function getImageAttribute($entityTypeId) + { + return $this->entityTypes["entityTypes"][$entityTypeId]['imageAttribute']; + } + + function onRegister() + { + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/service/FieldTypeService.php b/src/admin/application/classes/movio/modules/ontologybuilder/service/FieldTypeService.php new file mode 100755 index 0000000..0194fb4 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/service/FieldTypeService.php @@ -0,0 +1,80 @@ +source = __Paths::get('APPLICATION_TO_ADMIN').'config/fieldTypes.xml'; + + $options = array( + 'cacheDir' => org_glizy_Paths::get('CACHE_CODE'), + 'lifeTime' => -1, + 'readControlType' => '', + 'fileExtension' => '.php' + ); + $cacheObj = &org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFile', $options ); + $cacheFileName = $cacheObj->verify( $this->source, get_class( $this ) ); + + if ( $cacheFileName === false ) + { + $this->loadXml(); + $cacheObj->save( serialize( $this->typeMap ), NULL, get_class( $this ) ); + $cacheObj->getFileName(); + } + else + { + $this->typeMap = unserialize( file_get_contents( $cacheFileName ) ); + } + } + + function onRegister() { + + } + + private function loadXml() { + $xml = org_glizy_ObjectFactory::createObject('org.glizy.parser.XML'); + $xml->loadAndParseNS($this->source); + $fieldTypes = $xml->getElementsByTagName('fieldType'); + + foreach ($fieldTypes as $fieldType) { + $this->typeMap[$fieldType->getAttribute('id')] = $this->loadChildNodes($fieldType); + } + } + + private function loadChildNodes($xmlNode) { + if ($xmlNode->childNodes->length == 1) { + return $xmlNode->nodeValue; + } + else { + $values = array(); + + foreach($xmlNode->childNodes as $child) { + $values[$child->nodeName] = $this->loadChildNodes($child); + } + + return $values; + } + } + + public function getTypeMapping($type) + { + return $this->typeMap[$type]['map_to']; + } + + public function getTypeTranslation($type, $language_code) + { + return $this->typeMap[$type]['translation'][$language_code]; + } + + public function isTypeIndexed($type) + { + return $this->typeMap[$type]['is_indexed'] == 'true'; + } + + public function getAllTypes() + { + return $this->typeMap; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/service/LocaleService.php b/src/admin/application/classes/movio/modules/ontologybuilder/service/LocaleService.php new file mode 100755 index 0000000..0625225 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/service/LocaleService.php @@ -0,0 +1,124 @@ +init(); + } + + public function init() + { + $options = array( + 'cacheDir' => org_glizy_Paths::get('CACHE_CODE'), + 'lifeTime' => -1, + 'readControlType' => '', + 'fileExtension' => '.php' + ); + $cacheObj = &org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFile', $options); + $cacheFileName = $cacheObj->verify(get_class( $this )); + + if ( $cacheFileName === false ) { + $this->rebuildLocale(); + $cacheObj->save( serialize( $this->locale ), NULL, get_class( $this ) ); + $cacheObj->getFileName(); + } else { + $this->locale = unserialize( file_get_contents( $cacheFileName ) ); + } + } + + public function invalidate() + { + org_glizy_cache_CacheFile::cleanPHP(); + org_glizy_cache_CacheFile::cleanPHP(__Paths::get( 'BASE' ).'cache/'); + $this->init(); + } + + function onRegister() + { + } + + public function getTranslation($lang, $key) + { + $translation = $this->locale[$lang][$key]; + + if (strpos($key, 'rel:') === 0) { + return $translation ? $translation : str_replace('rel:', '', $key); + } else { + return $translation ? $translation : $key; + } + } + + public function keyAlreadyExists($lang, $key) + { + $languageCodes = $this->getLanguageCodes(); + + foreach ($languageCodes as $languageCode) { + if ($languageCode != $lang && $this->locale[$languageCode][$key]) { + return $languageCode; + } + } + + return false; + } + + private function getLanguageCodes() + { + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.Languages', 'all'); + + $codes = array(); + + foreach($it as $ar) { + $codes[] = $ar->language_code; + } + + return $codes; + } + + public function rebuildLocale() + { + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.RelationTypesDocument'); + + $languageCodes = $this->getLanguageCodes(); + + $locale = array(); + + foreach ($it as $ar) { + foreach ($languageCodes as $languageCode) { + if (@$ar->translation) { + $tr = $ar->translation[$languageCode]; + if ($tr) { + $locale[$languageCode]['rel:'.$ar->key] = $tr; + } + } + } + } + + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityLabelsDocument', 'all'); + + foreach ($it as $ar) { + foreach ($languageCodes as $languageCode) { + $tr = $ar->translation[$languageCode]; + if (@$ar->translation) { + if ($tr) { + $locale[$languageCode][$ar->key] = $tr; + } + } + } + } + + foreach ($languageCodes as $languageCode) { + $out = 'locale = $locale; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/ContentsEditor.xml b/src/admin/application/classes/movio/modules/ontologybuilder/views/ContentsEditor.xml new file mode 100644 index 0000000..e8dbac8 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/ContentsEditor.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/EntityLabelsEditor.xml b/src/admin/application/classes/movio/modules/ontologybuilder/views/EntityLabelsEditor.xml new file mode 100644 index 0000000..7e13f04 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/EntityLabelsEditor.xml @@ -0,0 +1,28 @@ + + + + + + + + + _application->getLanguage(); + $language = $language.'-'.strtoupper($language); + $this->setAttribute('src', 'application/classes/movio/modules/ontologybuilder/views/js/locale/'.$language.'.js'); + parent::process(); +} + ]]> + + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/Graph.xml b/src/admin/application/classes/movio/modules/ontologybuilder/views/Graph.xml new file mode 100644 index 0000000..bbd3826 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/Graph.xml @@ -0,0 +1,17 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/OntologyBuilder.xml b/src/admin/application/classes/movio/modules/ontologybuilder/views/OntologyBuilder.xml new file mode 100644 index 0000000..8a53d0f --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/OntologyBuilder.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + +
  • +
    Title
    +
    + + +
    +
  • + + ]]>
    +
    \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/RelationsEditor.xml b/src/admin/application/classes/movio/modules/ontologybuilder/views/RelationsEditor.xml new file mode 100644 index 0000000..87cbbdb --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/RelationsEditor.xml @@ -0,0 +1,28 @@ + + + + + + + + + _application->getLanguage(); + $language = $language.'-'.strtoupper($language); + $this->setAttribute('src', 'application/classes/movio/modules/ontologybuilder/views/js/locale/'.$language.'.js'); + parent::process(); +} + ]]> + + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/AddEntityButton.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/AddEntityButton.php new file mode 100644 index 0000000..a19f2dc --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/AddEntityButton.php @@ -0,0 +1,36 @@ +defineAttribute('label', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('routeUrl', false, '', COMPONENT_TYPE_STRING); + + parent::init(); + } + + function render() + { + // $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('APPLICATION').'templates/js/bootstrap.min.js' ) ); + + $output = '
    '. + ''. + ' '. + $this->getAttribute('label'). + ''. + ''. + '
    '; + $this->addOutputCode($output); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/DocumentGraph.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/DocumentGraph.php new file mode 100644 index 0000000..3c58b9c --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/DocumentGraph.php @@ -0,0 +1,166 @@ +defineAttribute('entityTypeId', false, null, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('documentId', false, null, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('addGraphJsLibs.js', false, true, COMPONENT_TYPE_BOOLEAN); + + parent::init(); + } + + protected function escape($s, $trim=false) + { + $s = htmlentities($s, null, "UTF-8"); + // si taglia la stringa dopo i 60 caratteri + $s = glz_strtrim($s, 60); + return $s; + } + + protected function makeUrl($entityTypeId, $document_id) + { + return org_glizy_helpers_Link::makeUrl('showEntityDetail', array('entityTypeId' => $entityTypeId, 'document_id' => $document_id)); + } + + public function getDocumentGraph($entityTypeId, $documentId) + { + $edges = array(); + + $entityProxy = org_glizy_objectFactory::createObject('movio.modules.ontologybuilder.models.proxy.EntityProxy'); + $data = $entityProxy->getRelations($documentId); + + // se non ci sono documenti correlati + if (empty($data['relations']) && empty($data['reference_relations'])) { + return ''; + } + + $color = __Config::get('movio.graph.shapeColor'); + $entityTypeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + + $graphCode = '"'.$this->escape($data['title']).'" [label="
    ' . $this->escape($data['title']) . '
    ",style="rounded,filled", height=0.4, color="'.$color.'", fillcolor="'.$color.'", fontcolor=white, fontsize=13];'.PHP_EOL; + + foreach ($data['relations'] as $relation) { + $url = $this->makeUrl($relation['entityTypeId'], $relation['document_id']); + $graphCode .= '"'.$this->escape($relation['title']).'" [label=""];'.PHP_EOL; + $entityTypeName = $entityTypeService->getEntityTypeName($relation['entityTypeId']); + + if (!$edges[$data['title']][$entityTypeName]) { + $graphCode .= '"'.$this->escape($data['title']).'" -> "'.$entityTypeName.'";'.PHP_EOL; + $edges[$data['title']][$entityTypeName] = true; + } + + $graphCode .= '"'.$entityTypeName.'" -> "'.$this->escape($relation['title']).'";'.PHP_EOL; + $graphCode .= '"'.$entityTypeName.'" [label="
    ' . $entityTypeName . '
    "];'.PHP_EOL; + } + + $entityTypeName = $entityTypeService->getEntityTypeName($entityTypeId); + $graphCode .= '"'.$entityTypeName.'" -> "'.$this->escape($data['title']).'";'.PHP_EOL; + $graphCode .= '"'.$entityTypeName.'" [label="
    ' . $entityTypeName . '
    "];'.PHP_EOL; + + foreach ($data['reference_relations'] as $relation) { + $url = $this->makeUrl($relation['entityTypeId'], $relation['document_id']); + $graphCode .= '"'.$this->escape($relation['title']).'" [label=""];'.PHP_EOL; + + if (!$edges[$relation['title']][$entityTypeName]) { + $subEntityTypeName = $entityTypeService->getEntityTypeName($relation['entityTypeId']); + /*$graphCode .= '"'.$this->escape($relation['title']).'" -> "'.$entityTypeName.'" [dir=back];'.PHP_EOL; + $graphCode .= '"'.$subEntityTypeName.'" -> "'.$this->escape($relation['title']).'" [dir=back];'.PHP_EOL;*/ + $graphCode .= '"'.$entityTypeName.'" -> "'.$this->escape($relation['title']).'";'.PHP_EOL; + $graphCode .= '"'.$this->escape($relation['title']).'" -> "'.$subEntityTypeName.'";'.PHP_EOL; + //$graphCode .= '"'.$this->escape($relation['title']).'" [label="
    ' . $this->escape($relation['title']) . '
    "];'.PHP_EOL; + $graphCode .= '"'.$subEntityTypeName.'" [label="
    ' . $subEntityTypeName . '
    "];'.PHP_EOL; + $edges[$data['title']][$entityTypeName] = true; + } + } + + return $graphCode; + } + + public function render_html() + { + $graphCode = ''; + + $entityTypeId = $this->getAttribute('entityTypeId') ? $this->getAttribute('entityTypeId') : __Request::get('entityTypeId'); + $documentId = $this->getAttribute('documentId') ? $this->getAttribute('documentId') : __Request::get('document_id'); + + if ($entityTypeId && $documentId) { + $graphCode = $this->getDocumentGraph($entityTypeId, $documentId); + } + if(empty($graphCode)) { + return; + } + + $title = __T('Relations'); + $id = $this->getId(); + + $graphCode = << +

    {$title}

    + +
    + + + +
    + + +EOD; + + if ($this->getAttribute('addGraphJsLibs.js')) { + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/d3.v3.js'), 'head'); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/dagre-d3.js'), 'head'); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/graphlib-dot.min.js'), 'head'); + } + $this->addOutputCode( $html ); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntireGraph.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntireGraph.php new file mode 100644 index 0000000..82aa498 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntireGraph.php @@ -0,0 +1,220 @@ +defineAttribute('entityTypeId', false, null, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('generateLinks', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('addGraphJsLibs.js', false, true, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + protected function escape($s, $trim=false) + { + //$s = htmlentities(addslashes($s), null, "UTF-8"); + $s = str_replace('"', "'", $s); + return $s; + } + + protected function makeUrl($pageId, $title) + { + return org_glizy_helpers_Link::makeUrl('link', array('pageId' => $pageId, 'title' => $title)); + } + + public function getGraph($entityTypeId, &$visited, &$edges, $firstNode = false) + { + if ($visited[$entityTypeId]) { + return ''; + } else { + $entityTypeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityProperties = $entityTypeService->getEntityTypeProperties($entityTypeId); + + $graph = ''; + $color = __Config::get('movio.graph.shapeColor'); + $entityTypeName = $entityTypeService->getEntityTypeName($entityTypeId); + + if ($this->getAttribute('generateLinks')) { + $entityResolver = org_glizy_objectFactory::createObject('movio.modules.ontologybuilder.EntityResolver'); + $ar = $entityResolver->getMenuVisibleEntity($entityTypeId); + + if ($ar) { + $url = 'URL="'.$this->makeUrl($ar->id, $ar->title).'"'; + } + } + + // se è il nodo da cui inizia la ricerca ricorsiva + if ($firstNode or empty($url)) { + $s = $url ? $url.', ' : ''; + $graph .= '"'.$this->escape($entityTypeName).'" [' . $s . 'label="' . $this->escape($entityTypeName . ' ' . __Link::makeLinkWithIcon('actionsMVC', 'icon-pencil icon-white', array('action' => 'edit', 'id' => $entityTypeId, 'title' => __T('GLZ_RECORD_EDIT'))) . '') . ' "];'.PHP_EOL; + } else if ($url) { + $graph .= '"'.$this->escape($entityTypeName).'" ['.$url.'];'.PHP_EOL; + } + + $visited[$entityTypeId] = true; + + foreach ((array)$entityProperties as $entityProperty) { + if ($entityProperty['entity_properties_target_FK_entity_id']) { + $toEntityTypeId = $entityProperty['entity_properties_target_FK_entity_id']; + $toEntityTypeName = $entityTypeService->getEntityTypeName($toEntityTypeId); + $label = __Tp('rel:'.$entityProperty['entity_properties_type']); + if (!$edges[$entityTypeName][$toEntityTypeName]) { + $edges[$entityTypeName][$toEntityTypeName] = true; + $graph .= '"'.$this->escape($entityTypeName).'" -> "'.$this->escape($toEntityTypeName).'" [label="'.$this->escape($label).'"];'.PHP_EOL; + } + $graph .= $this->getGraph($toEntityTypeId, $visited, $edges); + } + } + + $referenceRelations = $entityTypeService->getEntityTypeReferenceRelations($entityTypeId); + + foreach ((array)$referenceRelations as $referenceRelation) { + if ($referenceRelation['entity_properties_target_FK_entity_id']) { + $toEntityTypeId = $referenceRelation['entity_properties_FK_entity_id']; + $toEntityTypeName = $entityTypeService->getEntityTypeName($toEntityTypeId); + $label = __Tp('rel:'.$referenceRelation['entity_properties_type']); + if (!$edges[$toEntityTypeName][$entityTypeName]) { + $edges[$toEntityTypeName][$entityTypeName] = true; + $graph .= '"'.$this->escape($toEntityTypeName).'" -> "'.$this->escape($entityTypeName).'" [label="'.$this->escape($label).'"];'.PHP_EOL; + } + $graph .= $this->getGraph($toEntityTypeId, $visited, $edges); + } + } + + $visited[$entityTypeId] = true; + + return $graph; + } + } + + public function render_html() + { + $graphCode = ''; + + $entityTypeId = $this->getAttribute('entityTypeId') ? $this->getAttribute('entityTypeId') : __Request::get('entityTypeId'); + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.Entity', 'all'); + + if ($it->count()) { + $visited = array(); + $edges = array(); + foreach ($it as $ar) { + if (!in_array($ar->getId(), array_keys($visited))) { + $graphCode .= $this->getGraph($ar->getId(), $visited, $edges, true); + } + } + } + + $graphCode = << + + + + + + +EOD; + if ($this->getAttribute('addGraphJsLibs.js')) { + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/d3.v3.js')); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/dagre-d3.js')); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/graphlib-dot.min.js')); + } + + $this->addOutputCode( $html ); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Entity.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Entity.php new file mode 100644 index 0000000..c7ade96 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Entity.php @@ -0,0 +1,242 @@ +_content = $entityProxy->loadContentFrontend($this->getId()); + + $this->createChildComponents(); + $this->initChilds(); + $this->processChilds(); + + // simulate a new page in site structure + // for update the navigation menu, breadcrumbs and page title + $currentMenu = &$this->_application->getCurrentMenu(); + $siteMap = &$this->_application->getSiteMap(); + $menu = org_glizy_application_SiteMap::getEmptyMenu(); + $menu['title'] = $this->_content['title']; + $menu['id'] = $currentMenu->id+100000; + $menu['pageType'] = $currentMenu->pageType; + // $menu['isVisible'] = false; + $menu['url'] = __Request::get('__url__'); + $siteMap->addChildMenu($currentMenu, $menu); + //$this->_application->setPageId($menu['id']); + + $evt = array('type' => GLZ_EVT_SITEMAP_UPDATE, 'data' => $menu['id'] ); + $this->dispatchEvent($evt); + } + + function createChildComponents() + { + $entityTypeId = $this->_content['entityTypeId']; + $entityTypeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $skinAttributes = unserialize($entityTypeService->getEntityTypeAttribute($entityTypeId, 'entity_skin_attributes')); + if (!$skinAttributes) { + return; + } + + $language = $this->_application->getLanguage(); + $localeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + + foreach ($skinAttributes->properties as $i => $property) { + $skinAttributes->properties[$i]['label'] = $localeService->getTranslation($language, $property['label']); + } + + foreach ($skinAttributes->body as $i => $body) { + $skinAttributes->body[$i]['label'] = $localeService->getTranslation($language, $body['label']); + } + + $groupBoxRel = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Groupbox', $this->_application, $this, 'glz:Groupbox', 'relations'); + $this->addChild($groupBoxRel); + + $skinsName = array('Entity_relationImage.html', 'Entity_relationLink.html', 'Entity_relationImageLink.html'); + $groupBox = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Groupbox', $this->_application, $this, 'glz:Groupbox', 'detail'); + $groupBox->setAttribute('skin', 'Entity_entry.html'); + $this->addChild($groupBox); + $this->_content['attributes'] = $skinAttributes; + $this->_content['relations'] = new StdClass; + + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Hidden', $this->_application, $this, 'glz:Hidden', 'attributes', 'attributes'); + $groupBox->addChild($c); + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Hidden', $this->_application, $this, 'glz:Hidden', 'relations', 'relations'); + $groupBox->addChild($c); + + if (isset($this->_content['subtitle']) && $this->_content['subtitle']) { + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.PageTitle', $this->_application, $this, 'glz:Text', 'subtitle', 'subtitle'); + $c->setAttributes(array('tag' => 'h2', 'editableRegion' => 'pageTitle', 'value' => $this->_content['subtitle'])); + $this->addChild($c); + } + + // TODO usare EntityTypeService per ottenere le proprietà in cache + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityProperties'); + $it->load('entityPropertiesFromId', array('entityId' => $entityTypeId)); + + foreach ($it as $ar) { + $attribute = $entityTypeService->getAttributeIdByAr($ar); + + + switch ($ar->entity_properties_type) { + case 'attribute.text': + case 'attribute.int': + case 'attribute.date': + case 'attribute.openlist': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Text', $this->_application, $this, 'glz:Text', $attribute, $attribute); + $groupBox->addChild($c); + break; + + case 'attribute.longtext': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.LongText', $this->_application, $this, 'glz:LongText', $attribute, $attribute); + $c->setAttribute('forceP', true); + $groupBox->addChild($c); + break; + + case 'attribute.descriptivetext': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.LongText', $this->_application, $this, 'glz:LongText', $attribute, $attribute); + $c->setAttribute('adm:htmlEditor', true); + $groupBox->addChild($c); + break; + + case 'attribute.externallink': + case 'attribute.internallink': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.LinkTo', $this->_application, $this, 'glz:LinkTo', $attribute, $attribute); + $groupBox->addChild($c); + break; + + case 'attribute.externalimage': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.ImageExternal', $this->_application, $this, 'glz:ImageExternal', $attribute, $attribute); + $groupBox->addChild($c); + break; + + case 'attribute.image': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Image', $this->_application, $this, 'glz:Image', $attribute, $attribute); + $c->setAttribute('width', __Config::get('IMG_WIDTH')); + $c->setAttribute('height', __Config::get('IMG_HEIGHT')); + $c->setAttribute('zoom', true); + $c->setAttribute('superZoom', true); + $groupBox->addChild($c); + break; + + case 'attribute.media': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Media', $this->_application, $this, 'glz:Media', $attribute, $attribute); + $groupBox->addChild($c); + break; + + case 'attribute.imagelist': + if ($this->_content[$attribute]) { + $c = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.Repeater', $this->_application, $this, 'cmp:Repeater', $attribute, $attribute); + + $subchild = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Image', $this->_application, $c, 'glz:Image', 'attaches', 'attaches'); + $subchild->setAttribute('width', __Config::get('THUMB_WIDTH')); + $subchild->setAttribute('height', __Config::get('THUMB_HEIGHT')); + $subchild->setAttribute('zoom', true); + $c->addChild($subchild); + + $groupBox->addChild($c); + } + break; + + case 'attribute.medialist': + if ($this->_content[$attribute]) { + $c = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.Repeater', $this->_application, $this, 'cmp:Repeater', $attribute, $attribute); + + $subchild = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Media', $this->_application, $c, 'glz:Media', 'attaches', 'attaches'); + $c->addChild($subchild); + + $groupBox->addChild($c); + } + break; + + case 'attribute.photogallery': + $c = &org_glizy_ObjectFactory::createComponent('movio.views.components.PhotogalleryCategory', $this->_application, $this, 'm:PhotogalleryCategory', $attribute, $attribute); + $c->setAttribute('label', $localeService->getTranslation($language, $ar->entity_properties_label_key)); + $c->setAttribute('editableRegion', 'photogallery'); + $groupBoxRel->addChild($c); + break; + + case 'attribute.europeanaRelatedContents': + $c = &org_glizy_ObjectFactory::createComponent('movio.modules.europeana.views.components.RelatedContents', $this->_application, $this, 'evc:RelatedContents', $attribute, $attribute); + $c->setAttribute('skin', 'EuropeanaRelatedContents.html'); + $c->setAttribute('label', $localeService->getTranslation($language, $ar->entity_properties_label_key)); + $c->setAttribute('editableRegion', 'europeanaRelatedContents'); + $groupBoxRel->addChild($c); + break; + + case 'attribute.thesaurus': + $c = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.Thesaurus', $this->_application, $this, 'cmp:Thesaurus', $attribute, $attribute); + $groupBox->addChild($c); + break; + + case 'attribute.module': + $c = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.RepeaterForModule', $this->_application, $this, 'cmp:Repeater', $attribute, $attribute); + $c->setAttribute('label', $localeService->getTranslation($language, $ar->entity_properties_label_key)); + $c->setAttribute('skin', 'Entity_moduleImageLink.html'); + $c->setAttribute('editableRegion', 'photogallery'); + + $module = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.Module', $this->_application, $c, 'cmp:Module', 'attaches', 'attaches'); + $c->addChild($module); + + $groupBoxRel->addChild($c); + + default: + // se l'attributo è una relazione + if (!is_null($ar->entity_properties_target_FK_entity_id) && $ar->entity_properties_relation_show != 3 && $this->_content[$attribute]['content']) { + $c = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.Repeater', $this->_application, $this, 'cmp:Repeater', $attribute, $attribute); + + $relation = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.Relation', $this->_application, $c, 'cmp:Relation', 'attaches', 'attaches'); + $c->setAttribute('skin', $skinsName[$ar->entity_properties_relation_show]); + $c->setAttribute('editableRegion', 'relations'); + $c->addChild($relation); + + $groupBoxRel->addChild($c); + } + } + } + + foreach ((array)$this->_content['__reference_relations'] as $entityTypeName => $data) { + if ($data['show'] != 3) { + $c = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.Repeater', $this->_application, $this, 'cmp:Repeater', $entityTypeName, $entityTypeName); + + $relation = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.Relation', $this->_application, $c, 'cmp:Relation', 'attaches'.$entityTypeName, 'attaches'.$entityTypeName); + $c->setAttribute('skin', $skinsName[$data['show']]); + $c->setAttribute('editableRegion', 'referenceRelations'); + $c->addChild($relation); + + $groupBoxRel->addChild($c); + } + } + + if ($entityTypeService->getEntityTypeAttribute($entityTypeId, 'entity_show_relations_graph')) { + $c = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.DocumentGraph', $this->_application, $this, 'cmp:DocumentGraph', 'document_graph', 'document_graph'); + $c->setAttribute('editableRegion', 'relationsGraph'); + $groupBoxRel->addChild($c); + } + } + + function loadContent($id) + { + // se $id è l'id di una reference relation + if (preg_match('/^__entity\d+$/', $id, $m)) { + return $this->_content['__reference_relations'][$m[0]]; + } + else { + return $this->_content[$id]; + } + } + + function addOutputCode($output, $editableRegion='', $atEnd=false) + { + if ($editableRegion=='relationsGraph' || + $editableRegion=='relations' || + $editableRegion=='referenceRelations' || + $editableRegion=='europeanaRelatedContents' || + $editableRegion=='photogallery' ) { + if (!property_exists($this->_content['relations'], $editableRegion)) { + $this->_content['relations']->{$editableRegion} = ''; + } + $this->_content['relations']->{$editableRegion} .= $output; + return; + } + parent::addOutputCode($output, $editableRegion, $atEnd); + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityFormEdit.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityFormEdit.php new file mode 100644 index 0000000..ad75ef9 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityFormEdit.php @@ -0,0 +1,309 @@ +load($entityTypeId); + + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', '__type', '__type'); + $c->setAttribute('label', 'Tipo'); + $c->setAttribute('value', __Tp($entityModel->entity_name)); + $c->setAttribute('disabled', true); + $this->addChild($c); + + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Hidden', $this->_application, $this, 'glz:Input', $entityTypeId, $entityTypeId); + $c->setAttribute('name', 'entityTypeId'); + $c->setAttribute('value', $entityTypeId); + $this->addChild($c); + + $entityId = __Request::get('entityId'); + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Hidden', $this->_application, $this, 'glz:Input', $entityId, $entityId); + $c->setAttribute('name', 'entityId'); + $c->setAttribute('value', $entityId); + $this->addChild($c); + + $id = '__isVisible'; + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Checkbox', $this->_application, $this, 'glz:Checkbox', $id, $id); + $c->setAttribute('label', __Tp('Visible')); + $c->setAttribute('data', 'type=checkbox'); + $this->addChild($c); + + $id = 'title'; + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $id, $id); + $c->setAttribute('label', __Tp('Title')); + $c->setAttribute('required', true); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $c->setAttribute('value', ''); + $this->addChild($c); + + $id = 'subtitle'; + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $id, $id); + $c->setAttribute('label', __Tp('Subtitle')); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $c->setAttribute('value', ''); + $this->addChild($c); + + $id = 'url'; + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $id, $id); + $c->setAttribute('label', __Tp('URL')); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $c->setAttribute('value', ''); + $this->addChild($c); + + $id = 'profile'; + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $id, $id); + $c->setAttribute('label', __Tp('Profile')); + $c->setAttribute('data', 'type=selectfrom;multiple=true;model=org.glizycms.groupManager.models.UserGroup;field=usergroup_name'); + $c->setAttribute('value', ''); + $this->addChild($c); + + $entityTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityProperties'); + $it->load('entityPropertiesFromId', array('entityId' => $entityTypeId)); + + foreach($it as $ar) { + $attribute = $entityTypeService->getAttributeIdByAr($ar); + + switch ($ar->entity_properties_type) { + case 'attribute.text': + case 'attribute.externalimage': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('type', 'text'); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + case 'attribute.int': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('type', 'number'); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + case 'attribute.longtext': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('type', 'multiline'); + $c->setAttribute('rows', '10'); + $c->setAttribute('cols', '90'); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + case 'attribute.descriptivetext': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('type', 'multiline'); + $c->setAttribute('rows', '10'); + $c->setAttribute('cols', '90'); + $c->setAttribute('htmlEditor', true); + $c->setAttribute('data', 'type=tinymce'); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + case 'attribute.date': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('readOnly', true); + $c->setAttribute('type', 'text'); + $c->setAttribute('data', 'type=date;date-format=yyyy-mm-dd'); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + case 'attribute.externallink': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('type', 'url'); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + case 'attribute.internallink': + $c = &org_glizy_ObjectFactory::createComponent('org.glizycms.views.components.PagePicker', $this->_application, $this, 'cms:PagePicker', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + case 'attribute.openlist': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $proxyParams = json_encode( array('entityTypeId' => $entityTypeId) ); + $proxyParams = str_replace('"', '##', $proxyParams); + $c->setAttribute('data', 'type=selectfrom;multiple=false;add_new_values=true;proxy=movio.modules.ontologybuilder.models.proxy.EntityProxy;proxy_params='.$proxyParams); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + case 'attribute.image': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('data', 'type=mediapicker;mediatype=IMAGE;preview=true'); + $c->setAttribute('size', '90'); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + case 'attribute.media': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('data', 'type=mediapicker;mediatype=ALL;preview=false'); + $c->setAttribute('size', '90'); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + case 'attribute.imagelist': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Fieldset', $this->_application, $this, 'glz:Fieldset', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('data', 'type=repeat;repeatMin=0;collapsable=false'); + + $subchild = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', 'attaches', 'attaches'); + $subchild->setAttribute('label', 'Image'); + $subchild->setAttribute('size', '90'); + $subchild->setAttribute('data', 'type=mediapicker;mediatype=IMAGE;preview=true'); + + $c->addChild($subchild); + $this->addChild($c); + break; + + case 'attribute.medialist': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Fieldset', $this->_application, $this, 'glz:Fieldset', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('data', 'type=repeat;repeatMin=0;collapsable=false'); + + $subchild = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', 'attaches', 'attaches'); + $subchild->setAttribute('label', 'Media'); + $subchild->setAttribute('size', '90'); + $subchild->setAttribute('data', 'type=mediapicker;mediatype=ALL;preview=false'); + + $c->addChild($subchild); + $this->addChild($c); + break; + + // TODO + case 'attribute.photogallery': + $c = &org_glizy_ObjectFactory::createComponent('movio.views.components.PhotogalleryCategory', $this->_application, $this, 'm:PhotogalleryCategory', $attribute, $attribute, true, 'edit'); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $this->addChild($c); + break; + + case 'attribute.europeanaRelatedContents': + $searchFields = __Config::get('movio.europeana.searchFields'); + $rows = __Config::get('movio.europeana.rows'); + $searchFieldsLabels=''; + $keyFieldsLabels = explode(',', __Config::get('movio.europeana.searchFieldsLabels')); + $last = count($keyFieldsLabels); + $counter = 0; + foreach ($keyFieldsLabels as $field) { + $counter++; + $searchFieldsLabels .= __T($field); + if($counter < $last) { + $searchFieldsLabels .=","; + } + } + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('data', 'type=europeanaRelatedContents;search_fields='.$searchFields.';search_fields_labels='.$searchFieldsLabels.';max_result='.$rows); + $c->setAttribute('value', ''); + $this->addChild($c); + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.JSscript', $this->_application, $this, 'glz:JSscript', ''); + $c->setAttribute('folder', 'movio/modules/europeana/views/js'); + $c->setAttribute('editableRegion', 'tail'); + $this->addChild($c); + break; + + case 'attribute.thesaurus': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $proxyParams = json_encode( array('dictionaryId' => $ar->entity_properties_params) ); + $proxyParams = str_replace('"', '##', $proxyParams); + $c->setAttribute('data', 'type=selectfrom;multiple=true;add_new_values=false;proxy=movio.modules.thesaurus.models.proxy.ThesaurusProxy;format_selection=formatThesaurusSelection;format_result=formatThesaurusResult;return_object=true;proxy_params='.$proxyParams); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + case 'attribute.module': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $proxyParams = json_encode( array('moduleId' => $ar->entity_properties_params) ); + $proxyParams = str_replace('"', '##', $proxyParams); + $c->setAttribute('data', 'type=selectfrom;multiple=true;proxy=movio.modules.ontologybuilder.models.proxy.ModelProxy;return_object=true;proxy_params='.$proxyParams); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + + default: + // se l'attributo è una relazione + if (!is_null($ar->entity_properties_target_FK_entity_id)) { + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $attribute, $attribute); + $c->setAttribute('label', __Tp($ar->entity_properties_label_key)); + $c->setAttribute('required', $ar->entity_properties_required == 1); + $relation = $entityTypeService->getRelation($ar->entity_properties_type); + $c->setAttribute('data', 'type=entityselect;entity_type_id='.$ar->entity_properties_target_FK_entity_id.';cardinality='.$relation['cardinality']); + $c->setAttribute('cssClass', __Config::get('glizy.formElement.admCssClass')); + $c->setAttribute('value', ''); + $this->addChild($c); + break; + } + } + } + } + + public function render_html_onEnd($value='') + { + parent::render_html_onEnd($value); + $language = $this->_application->getLanguage(); + $language = $language.'-'.strtoupper($language); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( __Paths::get('APPLICATION').'classes/movio/modules/ontologybuilder/views/js/locale/'.$language.'.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( __Paths::get('APPLICATION').'classes/movio/modules/ontologybuilder/views/js/EntityFormEditEntitySelect.js' ) ); + } + + // function loadContent($name, $bindToField=NULL) + // { + // if (strpos($name, '-')!==false) { + // list($parentId) = explode('-', $name); + // $value = parent::loadContent($parentId); + // } + // parent::loadContent($name, $bindToField); + // } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityList.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityList.php new file mode 100644 index 0000000..42a26c7 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityList.php @@ -0,0 +1,28 @@ +defineAttribute('visualization', false, 'list', COMPONENT_TYPE_STRING); + $this->defineAttribute('entityTypeId', false, 0, COMPONENT_TYPE_INTEGER); + parent::init(); + + $this->setAttribute('skin', 'Entity_list.html'); + } + + + function process() + { + $entityTypeId = $this->getAttribute('entityTypeId'); + if ($entityTypeId) { + $entityTypeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $skinAttributes = unserialize($entityTypeService->getEntityTypeAttribute($entityTypeId, 'entity_skin_attributes')); + if ($skinAttributes) { + parent::process(); + $this->_content->params = new StdClass; + $this->_content->params->visualization = $this->getAttribute('visualization'); + $this->_content->params->attributes = $skinAttributes; + } + } + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityToJSON.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityToJSON.php new file mode 100644 index 0000000..1739b03 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/EntityToJSON.php @@ -0,0 +1,324 @@ +json = array( + 'title' => '', + 'subtitle' => '', + 'content' => '', + 'relations' => array(), + 'reference_relations' => array(), + 'images' => array(), + 'imageList' => array(), + 'medias' => array(), + 'mediaList' => array(), + 'photogallery' => array() + ); + + $this->medias = array(); + + $entityProxy = org_glizy_objectFactory::createObject('movio.modules.ontologybuilder.models.proxy.EntityProxy'); + $this->_content = $entityProxy->loadContentFrontend($this->getId()); + + $this->createChildComponents(); + $this->initChilds(); + $this->processChilds(); + + // simulate a new page in site structure + // for update the navigation menu, breadcrumbs and page title + $currentMenu = &$this->_application->getCurrentMenu(); + $siteMap = &$this->_application->getSiteMap(); + $menu = org_glizy_application_SiteMap::getEmptyMenu(); + $menu['title'] = $this->_content['title']; + $menu['id'] = $currentMenu->id+100000; + $menu['pageType'] = $currentMenu->pageType; + // $menu['isVisible'] = false; + $menu['url'] = __Request::get('__url__'); + $siteMap->addChildMenu($currentMenu, $menu); + //$this->_application->setPageId($menu['id']); + + $evt = array('type' => GLZ_EVT_SITEMAP_UPDATE, 'data' => $menu['id'] ); + $this->dispatchEvent($evt); + } + + function createChildComponents() + { + $entityTypeId = $this->_content['entityTypeId']; + $entityTypeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $skinAttributes = unserialize($entityTypeService->getEntityTypeAttribute($entityTypeId, 'entity_skin_attributes')); + if (!$skinAttributes) { + return; + } + + $language = $this->_application->getLanguage(); + $localeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + + foreach ($skinAttributes->properties as $i => $property) { + $skinAttributes->properties[$i]['label'] = $localeService->getTranslation($language, $property['label']); + } + + foreach ($skinAttributes->body as $i => $body) { + $skinAttributes->body[$i]['label'] = $localeService->getTranslation($language, $body['label']); + } + + $groupBoxRel = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Groupbox', $this->_application, $this, 'glz:Groupbox', 'relations'); + $this->addChild($groupBoxRel); + + $skinsName = array('Entity_relationImage.html', 'Entity_relationLink.html', 'Entity_relationImageLink.html'); + $groupBox = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Groupbox', $this->_application, $this, 'glz:Groupbox', 'detail'); + $groupBox->setAttribute('skin', 'Entity_entry.html'); + $this->addChild($groupBox); + $this->_content['attributes'] = $skinAttributes; + $this->_content['relations'] = new StdClass; + + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Hidden', $this->_application, $this, 'glz:Hidden', 'attributes', 'attributes'); + $groupBox->addChild($c); + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Hidden', $this->_application, $this, 'glz:Hidden', 'relations', 'relations'); + $groupBox->addChild($c); + + if (isset($this->_content['subtitle']) && $this->_content['subtitle']) { + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.PageTitle', $this->_application, $this, 'glz:Text', 'subtitle', 'subtitle'); + $c->setAttributes(array('tag' => 'h2', 'editableRegion' => 'pageTitle', 'value' => $this->_content['subtitle'])); + $this->addChild($c); + } + + // TODO usare EntityTypeService per ottenere le proprietà in cache + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityProperties'); + $it->load('entityPropertiesFromId', array('entityId' => $entityTypeId)); + + $jsonRelations = array(); + + foreach ($it as $ar) { + $attribute = $entityTypeService->getAttributeIdByAr($ar); + + switch ($ar->entity_properties_type) { + case 'attribute.text': + case 'attribute.int': + case 'attribute.date': + case 'attribute.openlist': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Text', $this->_application, $this, 'glz:Text', $attribute, $attribute); + $groupBox->addChild($c); + break; + + case 'attribute.longtext': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.LongText', $this->_application, $this, 'glz:LongText', $attribute, $attribute); + $c->setAttribute('forceP', true); + $c->setAttribute('parseInternalLinks', false); + $groupBox->addChild($c); + break; + + case 'attribute.descriptivetext': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.LongText', $this->_application, $this, 'glz:LongText', $attribute, $attribute); + $c->setAttribute('adm:htmlEditor', true); + $c->setAttribute('parseInternalLinks', false); + $groupBox->addChild($c); + break; + + case 'attribute.externallink': + case 'attribute.internallink': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.LinkTo', $this->_application, $this, 'glz:LinkTo', $attribute, $attribute); + $groupBox->addChild($c); + break; + + case 'attribute.externalimage': + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.ImageExternal', $this->_application, $this, 'glz:ImageExternal', $attribute, $attribute); + $groupBox->addChild($c); + break; + + case 'attribute.image': + $this->addMedia('images', $this->_content[$attribute]); + break; + + case 'attribute.media': + $this->addMedia('medias', $this->_content[$attribute]); + break; + + case 'attribute.imagelist': + if ($this->_content[$attribute]) { + foreach ($this->_content[$attribute]->attaches as $attach) { + $this->addMedia('imageList', $attach); + } + } + break; + + case 'attribute.medialist': + if ($this->_content[$attribute]) { + foreach ($this->_content[$attribute]->attaches as $attach) { + $this->addMedia('mediaList', $attach); + } + } + break; + + case 'attribute.photogallery': + if ($this->_content[$attribute.'-images']) { + foreach ($this->_content[$attribute.'-images'] as $category) { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.models.Media'); + $it->where('media_category', '%'.$category.'%', 'LIKE') + ->orderBy('media_title'); + + foreach($it as $ar) { + $media = array( + 'id' => $ar->media_id, + 'title' => $ar->media_title, + 'fileName' => $ar->media_fileName + ); + $this->addMedia('photogallery', json_encode($media)); + } + } + } + break; + + default: + // se l'attributo è una relazione + if (!is_null($ar->entity_properties_target_FK_entity_id) && $ar->entity_properties_relation_show != 3 && $this->_content[$attribute]['content']) { + $relations = ($this->loadContent($attribute)); + $entityTypeName = $entityTypeService->getEntityTypeName($ar->entity_properties_target_FK_entity_id); + + $jsonRelations[$entityTypeName] = array(); + + foreach ($relations['content'] as $relation) { + $jsonRelation = array(); + $jsonRelation['title'] = $relation['title']; + $image = ''; + + foreach ($relation as $k => $v) { + if (is_string($v) && preg_match('/{"id":\d+,/', $v, $m)) { + $image = $v; + break; + } + } + + $image = $this->addMedia('', $image); + $jsonRelation['image'] = $image; + $jsonRelation['entityTypeId'] = $relation['entityTypeId']; + $jsonRelation['document_id'] = $relation['document_id']; + + $jsonRelations[$entityTypeName][] = $jsonRelation; + } + } + } + } + + if ($jsonRelations) { + $this->json['relations'][] = $jsonRelations; + } + + $jsonRelations = array(); + + foreach ((array)$this->_content['__reference_relations'] as $entityTypeName => $data) { + if ($data['show'] != 3) { + $entityTypeName = $data['relation']; + + $jsonRelations[$entityTypeName] = array(); + + foreach ($data['content'] as $relation) { + $jsonRelation = array(); + $jsonRelation['title'] = $relation['title']; + $image = ''; + + foreach ($relation as $k => $v) { + if (is_string($v) && preg_match('/{"id":\d+,/', $v, $m)) { + $image = $v; + break; + } + } + + $image = $this->addMedia('', $image); + $jsonRelation['image'] = $image; + $jsonRelation['entityTypeId'] = $relation['entityTypeId']; + $jsonRelation['document_id'] = $relation['document_id']; + + $jsonRelations[$entityTypeName][] = $jsonRelation; + } + + } + } + + if ($jsonRelations) { + $this->json['reference_relations'][] = $jsonRelations; + } + + if ($entityTypeService->getEntityTypeAttribute($entityTypeId, 'entity_show_relations_graph')) { + $c = &org_glizy_ObjectFactory::createComponent('movio.modules.publishApp.views.components.DocumentGraph', $this->_application, $this, 'cmp:DocumentGraph', 'document_graph', 'document_graph'); + $c->setAttribute('entityTypeId', $entityTypeId); + $c->setAttribute('documentId', $this->getId()); + $c->setAttribute('addGraphJsLibs.js', false); + $c->setAttribute('editableRegion', 'graph'); + $this->addChild($c); + } + + foreach (array('images', 'imageList', 'medias', 'mediaList', 'photogallery') as $k) { + if ($this->json[$k]) { + $this->json[$k] = array_values($this->json[$k]); + } + } + + $this->addChild($groupBox); + } + + function addMedia($key, $media) { + if ($media != '') { + $result = new StdClass(); + $media = json_decode($media); + $m = org_glizycms_mediaArchive_MediaManager::getMediaById($media->id); + if ($m == null) { + return null; + } + $result->type = $m->type; + $result->title = $media->title; + $media->type = $m->type; + if ($result->type == 'VIDEO') { + $result->url = GLZ_HOST.'/'.org_glizy_helpers_Media::getFileUrlById($media->id, true); + } else { + $result->fileName = $media->fileName; + $this->medias[$media->id] = $media->fileName; + } + + if ($key) { + $this->json[$key][$media->id] = $result; + } + } + return $result; + } + + public function getMedias() + { + return $this->medias; + } + + function addOutputCode($output, $editableRegion='', $atEnd=null) + { + if ($editableRegion == 'graph') { + $this->graph .= $output; + } else { + $this->json['content'] .= $output; + } + } + + function loadContent($id) + { + // se $id è l'id di una reference relation + if (preg_match('/^__entity\d+$/', $id, $m)) { + return $this->_content['__reference_relations'][$m[0]]; + } + else { + return $this->_content[$id]; + } + } + + public function getJson() + { + return $this->json; + } + + public function getGraph() + { + return $this->graph; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/FilterEntityType.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/FilterEntityType.php new file mode 100644 index 0000000..f059c77 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/FilterEntityType.php @@ -0,0 +1,53 @@ +defineAttribute('label', false, '{i18n:Filter by type}', COMPONENT_TYPE_STRING); + $this->defineAttribute('dataGridAjaxId', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('fieldNumber', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('recordClassName', true, '', COMPONENT_TYPE_STRING); + + parent::init(); + } + + function render() + { + $id = $this->getAttribute('id'); + $output = '
    '; + $output .= ''; + $output .= '
    '; + + $dataGridId = $this->getAttribute('dataGridAjaxId'); + $fieldNumber = $this->getAttribute('fieldNumber'); + + $output .= << + jQuery(function(){ + var table = jQuery('#$dataGridId').data('dataTable'); + setTimeout(function(){ + jQuery("#{$id}_cont").children().appendTo("#{$dataGridId}_filter"); + var ooSettings = table.fnSettings(); + $("#$id").val(ooSettings.aoPreSearchCols[$fieldNumber].sSearch); + }, 100); + + jQuery('#$id').change( function () { + table.fnFilter( $(this).val(), $fieldNumber ); + }); + }); + +EOD; + $this->addOutputCode($output); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Graph.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Graph.php new file mode 100644 index 0000000..f2ac2b8 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Graph.php @@ -0,0 +1,195 @@ +defineAttribute('entityTypeId', false, null, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('generateLinks', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('addGraphJsLibs.js', false, true, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + + $this->language = $this->_application->isAdmin() ? $this->_application->getEditingLanguage() : $this->_application->getLanguage(); + $this->localeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + } + + protected function escape($s, $trim=false) + { + return $this->localeService->getTranslation($this->language, $s); + } + + protected function makeUrl($pageId, $title) + { + return org_glizy_helpers_Link::makeUrl('link', array('pageId' => $pageId, 'title' => $title)); + } + + public function getGraph($entityTypeId, &$visited, &$edges) + { + if ($visited[$entityTypeId]) { + return ''; + } else { + $entityTypeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityProperties = $entityTypeService->getEntityTypeProperties($entityTypeId); + + $graph = ''; + $color = __Config::get('movio.graph.shapeColor'); + $entityTypeName = $entityTypeService->getEntityTypeName($entityTypeId); + + if ($this->getAttribute('generateLinks')) { + $entityResolver = org_glizy_objectFactory::createObject('movio.modules.ontologybuilder.EntityResolver'); + $ar = $entityResolver->getMenuVisibleEntity($entityTypeId); + + if ($ar) { + $url = $this->makeUrl($ar->id, $ar->title); + } + } + + // se è il nodo da cui inizia la ricerca ricorsiva + if (count($visited) == 0) { + if (empty($url)) { + $graph .= '"'.$this->escape($entityTypeName).'" [label="
    ' . $this->escape($entityTypeName) . '
    ",style="fill: #ddd"];'.PHP_EOL; + } else { + $graph .= '"'.$this->escape($entityTypeName).'" [label="",style="fill: #ddd"];'.PHP_EOL; + } + } else if ($url) { + $graph .= '"'.$this->escape($entityTypeName).'" [label="
    ' . $this->escape($entityTypeName) . '"];'.PHP_EOL; + } + + $visited[$entityTypeId] = true; + + foreach ((array)$entityProperties as $entityProperty) { + if ($entityProperty['entity_properties_target_FK_entity_id']) { + $toEntityTypeId = $entityProperty['entity_properties_target_FK_entity_id']; + $toEntityTypeName = $entityTypeService->getEntityTypeName($toEntityTypeId); + $label = __Tp('rel:'.$entityProperty['entity_properties_type']); + if (!$edges[$entityTypeName][$toEntityTypeName]) { + $edges[$entityTypeName][$toEntityTypeName] = true; + $graph .= '"'.$this->escape($entityTypeName).'" -> "'.$this->escape($toEntityTypeName).'" [label="'.$label.'"];'.PHP_EOL; + } + $graph .= $this->getGraph($toEntityTypeId, $visited, $edges); + } + } + + $referenceRelations = $entityTypeService->getEntityTypeReferenceRelations($entityTypeId); + + foreach ((array)$referenceRelations as $referenceRelation) { + if ($referenceRelation['entity_properties_target_FK_entity_id']) { + $toEntityTypeId = $referenceRelation['entity_properties_FK_entity_id']; + $toEntityTypeName = $entityTypeService->getEntityTypeName($toEntityTypeId); + $label = __Tp('rel:'.$referenceRelation['entity_properties_type']); + if (!$edges[$toEntityTypeName][$entityTypeName]) { + $edges[$toEntityTypeName][$entityTypeName] = true; + $graph .= '"'.$this->escape($toEntityTypeName).'" -> "'.$this->escape($entityTypeName).'" [label="'.$label.'"];'.PHP_EOL; + } + $graph .= $this->getGraph($toEntityTypeId, $visited, $edges); + } + } + + $visited[$entityTypeId] = true; + + return $graph; + } + } + + public function render_html() + { + $graphCode = ''; + + $entityTypeId = $this->getAttribute('entityTypeId') ? $this->getAttribute('entityTypeId') : __Request::get('entityTypeId'); + + if ($entityTypeId) { + $visited = array(); + $edges = array(); + $graphCode = $this->getGraph($entityTypeId, $visited, $edges); + } + + if (!$this->getAttribute('generateLinks')) { + $this->language = $this->_application->getEditingLanguage(); + $this->localeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + + $html = '
    '; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= '
    '; + } + + $graphCode = << + + + +
    + +EOD; + if ($this->getAttribute('addGraphJsLibs.js')) { + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/d3.v3.js')); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/dagre-d3.js')); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/graphlib-dot.min.js')); + } + + $this->addOutputCode( $html ); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Module.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Module.php new file mode 100644 index 0000000..69963ac --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Module.php @@ -0,0 +1,60 @@ +data = $this->_parent->loadContent($this->getId()); + + $this->createChildComponents(); + $this->initChilds(); + $this->processChilds(); + } + + function createChildComponents() + { + $entityTypeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $properties = $entityTypeService->getEntityTypeAttributeProperties(__Request::get('entityTypeId'), $this->_parent->getId()); + $moduleId = $properties['entity_properties_params']; + + $this->_content['title'] = $this->data->text; + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Text', $this->_application, $this, 'glz:Text', 'title', 'title'); + $this->addChild($c); + + $this->_content['url'] = __Routing::makeUrl($moduleId, array('document_id' => $this->data->id, 'title' => $this->data->text)); + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Text', $this->_application, $this, 'glz:Text', 'url', 'url'); + $this->addChild($c); + + $module = org_glizy_Modules::getModule($moduleId); + $ar = org_glizy_ObjectFactory::createModel($module->classPath.'.models.Model'); + $ar->load($this->data->id); + + if ($ar->fieldExists('image')) { + $this->_content['__image'] = $ar->image; + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Image', $this->_application, $this, 'glz:Image', '__image', '__image'); + $c->setAttribute('width', __Config::get('THUMB_WIDTH')); + $c->setAttribute('height', __Config::get('THUMB_HEIGHT')); + $c->setAttribute('crop', true); + $this->addChild($c); + + } else { + $c = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.NoImage', $this->_application, $this, 'glz:Image', '__image', '__image'); + $c->setAttribute('width', __Config::get('THUMB_SMALL_WIDTH')); + $c->setAttribute('height', __Config::get('THUMB_SMALL_HEIGHT')); + $this->addChild($c); + } + } + + function getContent() + { + $r = $this->getChildContent(); + return $r; + } + + function loadContent($id) + { + return $this->_content[$id]; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/NoImage.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/NoImage.php new file mode 100644 index 0000000..29911df --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/NoImage.php @@ -0,0 +1,21 @@ +defineAttribute('height', false, NULL, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('width', false, NULL, COMPONENT_TYPE_INTEGER); + + // call the superclass for validate the attributes + parent::init(); + } + + function getContent() + { + $width = $this->getAttribute('width') ? $this->getAttribute('width') : __Config::get('THUMB_WIDTH'); + $height = $this->getAttribute('height') ? $this->getAttribute('height') :__Config::get('THUMB_HEIGHT'); + return array('__html__' => ''); + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Relation.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Relation.php new file mode 100644 index 0000000..5e9949b --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Relation.php @@ -0,0 +1,111 @@ +_content = $this->_parent->loadContent($this->getId()); + + $this->createChildComponents(); + $this->initChilds(); + $this->processChilds(); + } + + function createChildComponents() + { + $entityTypeId = $this->_content['entityTypeId']; + + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Text', $this->_application, $this, 'glz:Text', 'title', 'title'); + $this->addChild($c); + + $this->_content['url'] = __Routing::makeUrl('showEntityDetail', array('entityTypeId' => $entityTypeId, 'document_id' => $this->_content['document_id'])); + + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Text', $this->_application, $this, 'glz:Text', 'url', 'url'); + $this->addChild($c); + + $entityTypeService = $this->_application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + + $it = org_glizy_objectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityProperties'); + $it->load('entityPropertiesFromId', array('entityId' => $entityTypeId)); + + foreach ($it as $ar) { + $attribute = $entityTypeService->getAttributeIdByAr($ar); + + switch ($ar->entity_properties_type) { + case 'attribute.image': + if (is_null($this->_content['__image']) && $this->_content[$attribute]){ + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Image', $this->_application, $this, 'glz:Image', '__image', '__image'); + $c->setAttribute('width', __Config::get('THUMB_WIDTH')); + $c->setAttribute('height', __Config::get('THUMB_HEIGHT')); + $c->setAttribute('crop', true); + $this->addChild($c); + $this->_content['__image'] = $this->_content[$attribute]; + } + break; + + } + + if (is_null($this->_content['__description']) && $ar->entity_properties_dublic_core == 'DC.Description' && $this->_content[$attribute]) { + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.LongText', $this->_application, $this, 'glz:LongText', '__description', '__description'); + $c->setAttribute('adm:htmlEditor', true); + $this->addChild($c); + $this->_content['__description'] = glz_strtrim(strip_tags($this->_content[$attribute])); + } + } + + // controlla se esiste una lista media/immagini e ne prende la prima + if (is_null($this->_content['__image'])) { + foreach ($it as $ar) { + $attribute = $entityTypeService->getAttributeIdByAr($ar); + + switch ($ar->entity_properties_type) { + case 'attribute.imagelist': + if (is_null($this->_content['__image']) && $this->_content[$attribute]){ + $objectVars = get_object_vars($this->_content[$attribute]); + $content = array_shift($objectVars); + + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.Image', $this->_application, $this, 'glz:Image', '__image', '__image'); + $c->setAttribute('width', __Config::get('THUMB_SMALL_WIDTH')); + $c->setAttribute('height', __Config::get('THUMB_SMALL_HEIGHT')); + $c->setAttribute('crop', true); + $this->addChild($c); + $this->_content['__image'] = $content[0]; + } + break; + } + } + } + + // inserisce un'immagine di default + if (is_null($this->_content['__image'])) { + $c = &org_glizy_ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.NoImage', $this->_application, $this, 'glz:Image', '__image', '__image'); + $c->setAttribute('width', __Config::get('THUMB_SMALL_WIDTH')); + $c->setAttribute('height', __Config::get('THUMB_SMALL_HEIGHT')); + $this->addChild($c); + } + + if (is_null($this->_content['__description'])) { + foreach ($it as $ar) { + $attribute = $entityTypeService->getAttributeIdByAr($ar); + + if (is_null($ar->entity_properties_target_FK_entity_id) && preg_match('/text$/', $ar->entity_properties_type) && $this->_content[$attribute]) { + $c = &org_glizy_ObjectFactory::createComponent('org.glizy.components.LongText', $this->_application, $this, 'glz:LongText', '__description', '__description'); + $c->setAttribute('adm:htmlEditor', true); + $this->addChild($c); + $this->_content['__description'] = glz_strtrim(strip_tags($this->_content[$attribute])); + } + } + } + } + + function getContent() + { + $r = $this->getChildContent(); + return $r; + } + + function loadContent($id) + { + return $this->_content[$id]; + } +} +?> \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Repeater.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Repeater.php new file mode 100644 index 0000000..25c76d4 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Repeater.php @@ -0,0 +1,49 @@ +_content = $this->_parent->loadContent($this->getId(), true); + + if (is_array($this->_content)) { + for ($i = 0; $i < count($this->_content['content']); $i++) { + if ($this->_content['content'][$i]['entityTypeId']==0) { + unset($this->_content['content'][$i]); + } + } + if (empty($this->_content['content'])) { + $this->setAttribute('visible', 'false'); + } + } + + if (is_object($this->_content)) { + $child = $this->childComponents[0]; + $childId = $child->getId(); + $this->_content = array('content' => property_exists($this->_content, $childId) ? $this->_content->$childId : array()); + $this->_content['id'] = $this->getId(); + } + } + + function getContent() + { + if (!$this->childContentsLoaded) { + $child = $this->childComponents[0]; + foreach ($this->_content['content'] as $i => $value) { + $child->setId($i); + $child->process(); + $this->_content['content'][$i] = $child->getContent(); + } + $this->childContentsLoaded = true; + } + + $this->_content['id'] = $this->getId(); + return $this->_content; + } + + function loadContent($id) + { + return $this->_content['content'][$id]; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/RepeaterForModule.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/RepeaterForModule.php new file mode 100644 index 0000000..343bf95 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/RepeaterForModule.php @@ -0,0 +1,24 @@ +_content['content'] = $this->_parent->loadContent($this->getId(), true); + + if (is_array($this->_content)) { + if (empty($this->_content['content'])) { + $this->setAttribute('visible', 'false'); + } + } + + if (is_object($this->_content)) { + $child = $this->childComponents[0]; + $childId = $child->getId(); + $this->_content = array('content' => property_exists($this->_content, $childId) ? $this->_content->$childId : array()); + $this->_content['id'] = $this->getId(); + } + + $this->_content['label'] = $this->getAttribute('label'); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/ShowProfileContents.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/ShowProfileContents.php new file mode 100755 index 0000000..06f7f36 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/ShowProfileContents.php @@ -0,0 +1,35 @@ +_content = $entityProxy->getContentsByProfile($groupId); + } + } +} + +class movio_modules_ontologybuilder_views_components_ShowProfileContents_render extends org_glizy_components_render_Render +{ + function getDefaultSkin() + { + $skin = << +
    +

    +

    +

    + + + +

    +
    +EOD; + return $skin; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Thesaurus.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Thesaurus.php new file mode 100644 index 0000000..03f263b --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/components/Thesaurus.php @@ -0,0 +1,29 @@ +_parent->loadContent($this->getId()); + + $this->_content = array(); + if ($terms && is_array($terms) && count($terms)) { + + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $termVO = $thesaurusProxy->loadTerm($terms[0]->id); + + foreach ($terms as $term) { + $this->_content[]= array( + 'title' => $term->text, + 'type' => $termVO->type, + 'url' => 'thesaurus&termId='.$term->id + ); + } + } + } + + function loadContent($id) + { + return $this->_content[$id]; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/js/ContentsEditor.js b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/ContentsEditor.js new file mode 100644 index 0000000..345e22d --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/ContentsEditor.js @@ -0,0 +1,5 @@ +GlizyApp.pages[ 'movio.modules.ontologybuilder.views.ContentsEditor' ] = function( state, routing ) { + if ( state == 'edit' ) { + Glizy.module('ontologybuilder.SearchContent').run(); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityFormEditEntitySelect.js b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityFormEditEntitySelect.js new file mode 100644 index 0000000..d35a7f7 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityFormEditEntitySelect.js @@ -0,0 +1,69 @@ +if (jQuery.GlizyRegisterType) { + jQuery.GlizyRegisterType('entityselect', { + + __construct: function () { + $(this).removeAttr('value'); + + $(this).css('width', '500px'); + + var entityTypeId = $(this).data('entity_type_id'); + var cardinality = $(this).data('cardinality'); + + $(this).select2({ + multiple: cardinality == 1, // relazione uno a molti + placeholder: '', + allowClear: true, + ajax: { + url: Glizy.ajaxUrl + "&controllerName=movio.modules.ontologybuilder_controllers.entityFormEdit.ajax.FindEntities", + dataType: 'json', + quietMillis: 100, + data: function(term, page) { + return { + entityTypeId: entityTypeId, + term: term + }; + }, + results: function(data, page ) { + return { results: data.result } + } + }, + formatSelection: function(data) { + return data.text; + }, + formatNoMatches: function(term) { + return GlizyLocale.EntityFormEditEntitySelect.noEntitiesFound; + }, + }); + + var value = jQuery(this).data('origValue'); + + // relazione uno a molti + if (cardinality == 1) { + $(this).select2('data', value); + } + // relazione uno a uno + else { + $(this).select2('data', value[0]); + } + }, + + getValue: function () { + var value = $(this).select2('val'); + + if (typeof value === 'string') { + value = value === '' ? [] : [value]; + } + + return value; + }, + + setValue: function (value) { + if (value[0].id) { + $(this).select2('data', value.length == 1 ? value[0] : value); + } + }, + + destroy: function () { + } + }); +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityLabelsEditor.js b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityLabelsEditor.js new file mode 100755 index 0000000..67b6b25 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityLabelsEditor.js @@ -0,0 +1,4 @@ +GlizyApp.pages[ 'movio.modules.ontologybuilder.views.EntityLabelsEditor' ] = function( state, routing ) { + EntityLabelsEditorLoader.start(); + EntityLabelsEditorLoader.loadEntityLabels(); +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityLabelsEditorLoader.js b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityLabelsEditorLoader.js new file mode 100755 index 0000000..a6547d1 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/EntityLabelsEditorLoader.js @@ -0,0 +1,178 @@ +var EntityLabelsEditorLoader = new Object(); +EntityLabelsEditorLoader = { + languages: [], + + start : function() + { + $('#addButton').live('click', function( event ) { + EntityLabelsEditorLoader.addRow(); + }); + + $('.-removeButton').live('click', function( event ) { + EntityLabelsEditorLoader.deleteRow($(this).closest('tr')); + }); + + $('.saveButton').live('click', function(event) { + var saveButton = this; + $(this).closest('tr').find('a').editable('submit', { + url: Glizy.ajaxUrl + 'entityLabel.NewEntityLabel', + ajaxOptions: { + dataType: 'json' //assuming json response + }, + success: function(data, config) { + if (data) { + var id = data.result; + //set pk + $(this).closest('tr').find('a').editable('option', 'pk', id); + //remove unsaved class + $(this).removeClass('editable-unsaved'); + $(saveButton).hide(); + $(this).off('save.newuser'); + } + } + }); + }); + + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "GetLanguages", + dataType: "json", + async: false, + success: function (data) { + EntityLabelsEditorLoader.languages = data.result; + } + }); + }, + + loadEntityLabels : function(id) + { + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "entityLabel.LoadEntityLabels", + dataType: "json", + data: {entityId: id}, + success: function (data) { + var entityLabels = data.result; + if (entityLabels.length === 0) { + entityLabels.entityLabels = []; + } + EntityLabelsEditorLoader.showEntityLabels(entityLabels); + } + }); + }, + + getTemplate : function() + { + Handlebars.registerHelper('showTranslations', function(entityLabel) { + var html = ""; + + $.each(EntityLabelsEditorLoader.languages, function(index, language) { + var term; + + if (entityLabel.translation !== null) { + term = entityLabel.translation[language.language_code]; + term = term !== undefined ? term : null; + } + else { + term = null; + } + + html += '' + html += ''; + html += '' + }); + + return new Handlebars.SafeString(html); + }); + + Handlebars.registerHelper('notNull', function(item, block) { + return (item !== null) ? block.fn(this) : block.inverse(this); + }); + + Handlebars.registerPartial('entity-labels', $('#entity-labels').html()); + + var source = $('#entity-labels-editor-template').html(); + + return Handlebars.compile(source); + }, + + initEditableFields: function(selector) { + $(selector).editable({ + url: Glizy.ajaxUrl + 'entityLabel.SetEntityLabel', + emptytext: GlizyLocale.EntityLabelsEditorLoader.emptyText + }); + }, + + showEntityLabels : function(entityLabels) + { + entityLabels.languages = EntityLabelsEditorLoader.languages; + entityLabels.locale = GlizyLocale.EntityLabelsEditorLoader; + + $.each(entityLabels["entityLabels"], function(index, relation) { + relation.languages = EntityLabelsEditorLoader.languages; + relation.locale = GlizyLocale.EntityLabelsEditorLoader; + }); + + var template = EntityLabelsEditorLoader.getTemplate(); + var html = template(entityLabels); + $("#admincontent").append(html); + + EntityLabelsEditorLoader.initEditableFields('#editTable > tbody a'); + }, + + addRow : function() + { + var source = $('#entity-labels').html(); + var template = Handlebars.compile(source); + var entityLabel = { + isNew: true, + id: null, + translation: null, + languages: EntityLabelsEditorLoader.languages, + locale: GlizyLocale.EntityLabelsEditorLoader + }; + + var html = template(entityLabel); + $('#editTable tbody').append(html); + + EntityLabelsEditorLoader.initEditableFields('#editTable > tbody tr:last a'); + + /* + // automatically show next editable + $('#editTable > tbody tr:last a').on('save.newuser', function(){ + var that = this; + setTimeout(function() { + var error = $(that).parents('tr').find('a').editable('validate'); + + if ($.isEmptyObject(error)) { + $(that).closest('tr').find('.saveButton').removeAttr("disabled"); + } + + $(that).closest('td').next().find('a').editable('show'); + }, 200); + }); + */ + }, + + deleteRow : function(row) + { + if (confirm(GlizyLocale.EntityLabelsEditorLoader.relationDelConfirm)) { + var id = $(row).find('a:first').data("pk"); + + if (id === null) { + row.remove(); + return; + } + + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "entityLabel.DelEntityLabel", + dataType: "json", + data: {id: id}, + success: function (data) { + row.remove(); + } + }); + } + }, +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/js/OntologyBuilder.js b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/OntologyBuilder.js new file mode 100755 index 0000000..c8fc508 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/OntologyBuilder.js @@ -0,0 +1,10 @@ +GlizyApp.pages[ 'movio.modules.ontologybuilder.views.OntologyBuilder' ] = function( state, routing ) { + + if ( state == 'edit' ) { + OntologyBuilderEditor.start(); + OntologyBuilderEditor.loadEntity(routing["id"]); + } + else { + + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/js/OntologyBuilderEditor.js b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/OntologyBuilderEditor.js new file mode 100755 index 0000000..02cb426 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/OntologyBuilderEditor.js @@ -0,0 +1,501 @@ +var OntologyBuilderEditor = new Object(); +OntologyBuilderEditor = { + deletedRows: [], + entities: [], + fieldTypes: [], + relationTypes: [], + dictionaries: [], + modules: [], + + start : function() + { + $('#addButton').live('click', function( event ) { + OntologyBuilderEditor.addRow(); + }); + + $('#saveButton').live('click', function( event ) { + OntologyBuilderEditor.saveEntity(); + }); + + $('#saveCloseButton').live('click', function( event ) { + var result = OntologyBuilderEditor.saveEntity(false); + if (result) { + history.back(); + } + }); + + $('#cancelButton').live('click', function( event ) { + history.back(); + }); + + $('.-removeButton').live('click', function( event ) { + OntologyBuilderEditor.deleteRow($(this).closest('.-property')); + }); + + $('.-typeSelector').live('change', function( event ) { + var selectedType = $("option:selected", this).attr('class'); + var property = $(this).closest('.-property'); + var selectors = []; + selectors.push( property.find('.-targetSelector') ); + selectors.push( property.find('.-relationShowSelector') ); + + if (selectedType == "-field") { + $.each(selectors, function(index, selector) { + selector.hide(); + + selector.prepend(''); + selector.val($('option:first', selector).val()); + }); + + property.find('.-relationShowSelectorPanel').hide(); + + if ($(this).val() === 'attribute.thesaurus') { + property.find('.-paramSelectorPanel').show(); + property.find('.-moduleParamSelectorPanel').hide(); + } else if ($(this).val() === 'attribute.module') { + property.find('.-paramSelectorPanel').hide(); + property.find('.-moduleParamSelectorPanel').show(); + } else { + property.find('.-paramSelectorPanel').hide(); + property.find('.-moduleParamSelectorPanel').hide(); + } + } + else { + var verb = $(':selected', this).text(); + // rimuove il prefisso "Relation: " o "Relazione: " + verb = verb.substring(verb.indexOf(':')+2); + + var $propertyLabel = $(this).parent().find('.-propertyLabel'); + if ($propertyLabel.select2('val') == '') { + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "FindEntityLabels", + dataType: "json", + data: {term: verb}, + async: false, + success: function (data) { + var result = data.result; + if (result.length == 0) { + OntologyBuilderEditor.addTerm($propertyLabel, verb); + //$propertyLabel.select2('data', {id: verb, text: verb}); + } else { + $propertyLabel.select2('data', result[0]); + } + } + }); + } + + $.each(selectors, function(index, selector) { + selector.show(); + selector.find(':first-child:empty').remove(); + }); + + property.find('.-relationShowSelectorPanel').show(); + + property.find('.-paramSelectorPanel').hide(); + property.find('.-moduleParamSelectorPanel').hide(); + } + }); + + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "GetFieldTypes", + dataType: "json", + async: false, + success: function (data) { + OntologyBuilderEditor.fieldTypes = data.result; + } + }); + + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "GetRelationTypes", + dataType: "json", + async: false, + success: function (data) { + OntologyBuilderEditor.relationTypes = data.result; + } + }); + + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "GetDictionaries", + dataType: "json", + async: false, + success: function (data) { + OntologyBuilderEditor.dictionaries = data.result; + } + }); + + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "GetModules", + dataType: "json", + async: false, + success: function (data) { + OntologyBuilderEditor.modules = data.result; + } + }); + }, + + showLoader : function(id) + { + id = typeof id !== 'undefined' ? id : "#preloader"; + $(id).css("display", "inline"); + }, + + hideLoader : function(id) + { + id = (typeof id !== 'undefined') ? id : "#preloader"; + $(id).css("display", "none"); + }, + + loadEntity : function(id) + { + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "LoadEntity", + dataType: "json", + data: {entityId: id}, + success: function (data) { + OntologyBuilderEditor.entities = data.result["entities"]; + OntologyBuilderEditor.showEntity(data.result); + } + }); + }, + + getTemplate : function() + { + Handlebars.registerHelper('selected', function(a, b) { + return a == b ? 'selected' : ''; + }); + + Handlebars.registerHelper('checked', function(value) { + return value ? 'checked' : ''; + }); + + Handlebars.registerHelper('isDisabled', function(value) { + return value === null ? 'disabled' : ''; + }); + + Handlebars.registerHelper('dictionaries', function(target) { + var html = ""; + + $.each(OntologyBuilderEditor.dictionaries, function(index, item) { + html += ''; + }); + + return new Handlebars.SafeString(html); + }); + + Handlebars.registerHelper('modules', function(target) { + var html = ""; + + $.each(OntologyBuilderEditor.modules, function(index, item) { + html += ''; + }); + + return new Handlebars.SafeString(html); + }); + + Handlebars.registerHelper('entities', function(target) { + var html = ""; + + $.each(OntologyBuilderEditor.entities, function(index, item) { + html += ''; + }); + + return new Handlebars.SafeString(html); + }); + + Handlebars.registerHelper('fieldTypes', function(type) { + var html = ""; + + $.each(OntologyBuilderEditor.fieldTypes, function(index, item) { + html += ''; + }); + + return new Handlebars.SafeString(html); + }); + + Handlebars.registerHelper('relationTypes', function(type) { + var html = ""; + + $.each(OntologyBuilderEditor.relationTypes, function(index, item) { + html += ''; + }); + + return new Handlebars.SafeString(html); + }); + + Handlebars.registerPartial('default-entity-property', $('#default-entity-property').html()); + Handlebars.registerPartial('entity-property', $('#entity-property').html()); + Handlebars.registerPartial('reference-relations-template', $('#reference-relations-template').html()); + + var source = $('#entity-template').html(); + + return Handlebars.compile(source); + }, + + // aggiunge term al dizionario delle etichette nel db + addTerm : function(item, term, key) + { + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "AddEntityLabel", + dataType: "json", + data: { + text: term, + key: key + }, + success: function (data) { + var newLabel = { + id: data.result, + text: term + }; + + if (item) { + $(item).select2('data', newLabel).select2('close'); + } + } + }); + }, + + initSelect2 : function(item) { + $(item).select2({ + minimumInputLength: 2, + ajax: { + url: Glizy.ajaxUrl + "FindEntityLabels", + dataType: 'json', + quietMillis: 100, + data: function(term, page) { + return { + term: term + }; + }, + results: function(data, page ) { + return { results: data.result } + } + }, + formatSelection: function(data) { + if (data.id == '__newTerm') { + OntologyBuilderEditor.addTerm(null, data.text, data.key); + $(item).select2('data').id = data.key ? data.key : data.text; + } + return data.text; + }, + initSelection : function (element, callback) { + var id = $(element).attr('value'); + var text = $(element).attr('data-init-text'); + callback({id: id, text: text}); + }, + escapeMarkup: function (m) { return m; }, + createSearchChoice: function(term, data) { + if ($(data).filter(function() { + return this.text.localeCompare(term)===0; + }).length===0) { + return {id:'__newTerm', text:term, key: $(item).val()}; + } + } + }); + }, + + showEntity : function(entity) + { + entity['defaultProperties'] = [{ + type: 'attribute.text', + target: null, + labelId: 1, + labelText: 'Title', + relationShow: null, + required: true, + locale: GlizyLocale.OntologyBuilderEditor + }, { + type: 'attribute.text', + target: null, + labelId: 1, + labelText: 'Subtitle', + relationShow: null, + required: false, + locale: GlizyLocale.OntologyBuilderEditor + }, { + type: 'attribute.text', + target: null, + labelId: 1, + labelText: 'URL', + relationShow: null, + required: false, + locale: GlizyLocale.OntologyBuilderEditor + }]; + + entity.locale = GlizyLocale.OntologyBuilderEditor; + + $.each(entity["properties"], function(index, property) { + property.locale = GlizyLocale.OntologyBuilderEditor; + }); + + $.each(entity["relations"], function(index, relation) { + relation.locale = GlizyLocale.OntologyBuilderEditor; + }); + + var template = OntologyBuilderEditor.getTemplate(); + var html = template(entity); + $("#admincontent").append(html); + + // forza il change dei selettori in base al loro tipo + $('.-typeSelector').change(); + + OntologyBuilderEditor.initSelect2('#entityName'); + + $.each(entity["properties"], function(index, property) { + OntologyBuilderEditor.initSelect2('#propertyLabel'+property["id"]); + }); + + $("#editTable").sortable({ + items: ".-sortable" + }); + }, + + saveEntity : function(async) + { + $('#saveButton').attr("disabled", true); + OntologyBuilderEditor.showLoader(); + + var entity = {} + + entity["id"] = $("#editTable").data("id"); + entity["name"] = $("#entityName").select2('data').id; + + if (entity["name"] === '') { + $("#entityName").select2("focus"); + OntologyBuilderEditor.hideLoader(); + $('#saveButton').attr("disabled", false); + alert(GlizyLocale.OntologyBuilderEditor.alertEmptyEntityName); + return false; + } + + entity["showRelationsGraph"] = $("#showRelationsGraph").is(':checked'); + + entity["properties"] = []; + + var existsEmptyLabels = false; + + $("#editTable .-property").each( function(index, item) { + // salta le prime 3 proprietà (title, subtitle e url) + // che sono obbligatori e non vengono salvati nel db + if (index >= 3) { + var property = {} + property["id"] = $(this).data("id"); + property["type"] = $('.-typeSelector', this).val(); + property["target"] = $('.-targetSelector', this).val(); + property["label"] = $('.-propertyLabel', this).select2('data') ? $('.-propertyLabel', this).select2('data').id : ''; + property["relationShow"] = $('.-relationShowSelector', this).val(); + property["dcField"] = $('.-dcFieldSelector', this).val(); + property["required"] = $('.-fieldRequired', this).is(':checked'); + property["showLabelInFrontend"] = $('.-showLabelInFrontend', this).is(':checked'); + property["rowIndex"] = index - 2; + + if (property["type"] === 'attribute.thesaurus') { + property["params"] = $('.-paramSelector', this).val(); + } else if (property["type"] === 'attribute.module') { + property["params"] = $('.-moduleParamSelector', this).val(); + } + + entity["properties"].push(property); + + if (property["label"] === '') { + if (!existsEmptyLabels) { + $('.-propertyLabel', this).select2("focus"); + } + existsEmptyLabels = true; + } + } + }); + + if (existsEmptyLabels) { + alert(GlizyLocale.OntologyBuilderEditor.alertEmptyLabels); + $('#saveButton').attr("disabled", false); + OntologyBuilderEditor.hideLoader(); + return false; + } + + entity["relations"] = []; + + $("#reference-relations > tbody > tr").each( function(index, item) { + var relation = {} + relation["id"] = $(this).data("id"); + relation["show"] = $('.-relationDisplaySelector', this).val(); + + entity["relations"].push(relation); + }); + + entity["deletedRows"] = OntologyBuilderEditor.deletedRows; + + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "SaveEntity", + dataType: "json", + data: {entity: entity}, + async: async, + success: function (data) { + $('#saveButton').attr("disabled", false); + OntologyBuilderEditor.hideLoader(); + OntologyBuilderEditor.deletedRows = []; + var returnEntity = data.result; + + if ($("#editTable").data("id") === '') { + $("#editTable").data("id", returnEntity["id"]); + } + + var i = 0; + + // aggiorna gli id delle nuove righe create + $("#editTable .-property").each( function() { + var id = $(this).data("id"); + if (id === '') { + $(this).data("id", returnEntity["newProperties"][i++]); + } + }); + + Glizy.events.broadcast("glizy.message.showSuccess", {"title": GlizyLocale.OntologyBuilderEditor.entitySavedMsg, "message": ""}); + }, + error: function() { + Glizy.events.broadcast("glizy.message.showError", {"title": GlizyLocale.OntologyBuilderEditor.entitySavedError, "message": ""}); + } + }); + + return true; + }, + + deleteRow : function(row) + { + if (confirm(GlizyLocale.OntologyBuilderEditor.propertyDelConfirm)) { + var id = $(row).data("id"); + OntologyBuilderEditor.deletedRows.push(id); + row.remove(); + } + }, + + addRow : function() + { + var source = $('#entity-property').html(); + var template = Handlebars.compile(source); + var property = { + type: null, + target: null, + labelId: null, + labelText: null, + relationShow: null, + showLabelInFrontend: true, + locale: GlizyLocale.OntologyBuilderEditor, + params: null + } + var html = template(property); + $('#editTable').append(html); + + OntologyBuilderEditor.initSelect2('.-propertyLabel:last'); + $(".-propertyLabel:last").select2('data', null); + + $('.-typeSelector:last').change(); + } +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/js/RelationsEditor.js b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/RelationsEditor.js new file mode 100755 index 0000000..fc04dff --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/RelationsEditor.js @@ -0,0 +1,4 @@ +GlizyApp.pages[ 'movio.modules.ontologybuilder.views.RelationsEditor' ] = function( state, routing ) { + RelationsEditorLoader.start(); + RelationsEditorLoader.loadRelations(); +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/js/RelationsEditorLoader.js b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/RelationsEditorLoader.js new file mode 100755 index 0000000..9875b94 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/RelationsEditorLoader.js @@ -0,0 +1,180 @@ +var RelationsEditorLoader = new Object(); +RelationsEditorLoader = { + languages: [], + + start : function() + { + $('.js-addButton').live('click', function( event ) { + event.preventDefault(); + RelationsEditorLoader.addRow(); + }); + + $('.js-removeButton').live('click', function( event ) { + RelationsEditorLoader.deleteRow($(this).closest('tr')); + }); + + $('.js-saveButton').live('click', function(event) { + var saveButton = this; + $(this).closest('tr').find('a').editable('submit', { + url: Glizy.ajaxUrl + 'relation.NewRelation', + ajaxOptions: { + dataType: 'json' //assuming json response + }, + success: function(data, config) { + if (data) { + var id = data.result; + //set pk + $(this).closest('tr').find('a').editable('option', 'pk', id); + //remove unsaved class + $(this).removeClass('editable-unsaved'); + $(saveButton).hide(); + $(this).off('save.newuser'); + } + } + }); + }); + + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "GetLanguages", + dataType: "json", + async: false, + success: function (data) { + RelationsEditorLoader.languages = data.result; + } + }); + }, + + loadRelations : function(id) + { + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "relation.LoadRelations", + dataType: "json", + data: {entityId: id}, + success: function (data) { + var relations = data.result; + if (relations.length === 0) { + relations.relations = []; + } + RelationsEditorLoader.showRelations(relations); + } + }); + }, + + getTemplate : function() + { + Handlebars.registerHelper('showTranslations', function(relation) { + var html = ""; + + $.each(RelationsEditorLoader.languages, function(index, language) { + var term; + + if (relation.translation !== null) { + term = relation.translation[language.language_code]; + term = term !== undefined ? term : null; + } + else { + term = null; + } + + html += '' + html += ''; + html += '' + }); + + return new Handlebars.SafeString(html); + }); + + Handlebars.registerHelper('notNull', function(item, block) { + return (item !== null) ? block.fn(this) : block.inverse(this); + }); + + Handlebars.registerPartial('relation', $('#relation').html()); + + var source = $('#relations-editor-template').html(); + + return Handlebars.compile(source); + }, + + initEditableFields: function(selector) { + $(selector).editable({ + url: Glizy.ajaxUrl + 'relation.SetRelation', + emptytext: GlizyLocale.RelationsEditorLoader.emptyText + }); + }, + + showRelations : function(relations) + { + relations.languages = RelationsEditorLoader.languages; + relations.locale = GlizyLocale.RelationsEditorLoader; + + $.each(relations["relations"], function(index, relation) { + relation.languages = RelationsEditorLoader.languages; + relation.locale = GlizyLocale.RelationsEditorLoader; + }); + + var template = RelationsEditorLoader.getTemplate(); + var html = template(relations); + $("#admincontent").append(html); + + RelationsEditorLoader.initEditableFields('#editTable > tbody a'); + }, + + addRow : function() + { + var source = $('#relation').html(); + var template = Handlebars.compile(source); + var relation = { + isNew: true, + id: null, + translation: null, + cardinality: 0, + languages: RelationsEditorLoader.languages, + locale: GlizyLocale.RelationsEditorLoader + }; + + var html = template(relation); + $('#editTable tbody').append(html); + + RelationsEditorLoader.initEditableFields('#editTable > tbody tr:last a'); + + /* + // automatically show next editable + $('#editTable > tbody tr:last a').on('save.newuser', function(){ + var that = this; + setTimeout(function() { + var error = $(that).parents('tr').find('a').editable('validate'); + + if ($.isEmptyObject(error)) { + $(that).closest('tr').find('.saveButton').removeAttr("disabled"); + } + + $(that).closest('td').next().find('a').editable('show'); + }, 200); + }); + */ + }, + + deleteRow : function(row) + { + if (confirm(GlizyLocale.RelationsEditorLoader.relationDelConfirm)) { + var id = $(row).find('a:first').data("pk"); + + if (id === null) { + row.remove(); + return; + } + + $.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "relation.DelRelation", + dataType: "json", + data: {id: id}, + success: function (data) { + row.remove(); + } + }); + } + }, +} diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/js/SearchContent.js b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/SearchContent.js new file mode 100644 index 0000000..e7f57aa --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/SearchContent.js @@ -0,0 +1,405 @@ +Glizy.module('ontologybuilder.SearchContent', function(){ + _.templateSettings.variable = "rc"; + var self = this; + + self.html = '
    ' + + '
    ' + + '
    x
    ' + + '
    ' + + '' + + '' + + ' {i18n:search on europeana}' + + ' {i18n:search on wikipedia}' + + '' + + '
    ' + + '' + + '' + + '
    '; + + self.europeanaLink = "www.europeana.eu/portal/search.html?query=<%- rc.searchTerm%>"; + self.wikipediaLink = "it.wikipedia.org/wiki/<%- rc.searchTerm%>"; + self.selectedText =''; + self.searchActive = true; + self.url = ''; + self.numField = 0; + self.instance = false; + self.maxHeigth = 0; + + this.run = function() { + var target = $("#outer"); + var menu = self.getInputFields(); + var templateData = { 'menu' : menu }; + var menu = self.getInputFields(); + var templateData = { 'menu' : menu }; + self.render(target, templateData, self.html, true); + self.resizeAdjust(); + target.css('height', ''); + $('#searchContentDiv').hide(); + self.setResize() + $("#breadcrumb-actions a").on('click', function(e){ + e.preventDefault(); + self.searchActive = self.searchActive === false; + if (!self.searchActive) { + self.setResizableDiv(target); + $('#searchResultFrame').css('height', $('#searchResultFrame').height()-40); + } + else { + self.closeSearchDiv(target); + } + }); + + $(window).resize(function() { + self.resizeAdjust(target) + self.setMaxHeight(); + if(!self.searchActive) + { + $(".formButtons").css('bottom', $('#searchContentDiv').height()); + } + self.removeSelectedText(); + }); + $(".js-closeDiv").on('click', function(){ + self.closeSearchDiv(target); + self.searchActive = true; + }); + $(window).on('keyup', function(e) { + var charCode = e.charCode || e.keyCode || e.which; + if (charCode == 27){ + self.closeSearchDiv(target); + self.searchActive = true; + } + }); + + $("#searchResultFrame").on("load", function () { + self.setFrameEvents("searchResultFrame"); + }); + + }; + + this.setMaxHeight = function() + { + self.maxHeigth = (2/3)*$(window).height(); + } + + this.setResize = function() { + var resize = false; + var split_height = $("#searchContentDiv").height(); + self.maxHeigth = (2/3)*$(window).height(); + $(document).on('mouseup', function(event) + { + resize = false; + split_height = $("#searchContentDiv").height(); + }); + + $(".resize").mousedown(function(event) + { + resize = event.pageY; + self.removeSelectedText(); + }); + $(document).mousemove(function(event) + { + if (resize) + { + if (split_height + resize - event.pageY < 200) + { + $("#searchContentDiv").height(200); + } + else if (split_height + resize - event.pageY > self.maxHeigth) + { + $("#searchContentDiv").height(self.maxHeigth); + } + else + { + $("#searchContentDiv").height(split_height + resize - event.pageY); + } + $(".formButtons").css('bottom', $('#searchContentDiv').height()); + self.setHeight(); + } + }); + + } + this.closeSearchDiv = function(target){ + self.resetResizableDiv(target); + self.resizeAdjust(target) + self.setMaxHeight(); + target.attr('style', function(i, style) + { + return style.replace(/height[^;]+;?/g, ''); + }); + } + + this.resizeAdjust = function(){ + var mid = $(window).scrollTop() + 2*Math.floor($(window).height() /5); + var searchDiv = $('#searchContentDiv'); + searchDiv.css({ 'height': mid - $('#handle').height(), + 'left': $('#sidebar').width() } ); + self.setHeight(); + self.setWidth(); + } + + this.resetResizableDiv = function(target) { + $(document).css('overflow', 'auto'); + target.removeClass('splitDiv'); + $('#searchContentDiv').hide(); + $(".formButtons").css({'position': 'fixed', 'bottom': 0, 'z-index' : 9 }); + }; + + this.setResizableDiv = function(target) { + $("#sidebar").css('position', 'fixed'); + $(target).addClass('splitDiv'); + self.setHeight(); + $('#searchContentDiv').show(); + self.setMaxHeight(); + $(".formButtons").css({'position': 'fixed', 'bottom': $('#searchContentDiv').height(), 'z-index': 1}); + $('#searchText').focus(); + $('#searchSubmit, .js-searchMode').on('click', function(){ + self.callSearch(); + }); + $('#searchText').on('keypress', function(e){ + if(e.which == 13) { + e.preventDefault(); + self.callSearch(); + } + }) + $(".js-copy").click( function (e) { + e.preventDefault(); + self.copySelectedText($(this)); + }); + }; + + this.setWidth = function(){ + var searchDiv = $('#searchContentDiv'); + $('#outer').css('overflow', 'hidden'); + searchDiv.css('width', $(document).width() - $('#sidebar').width()); + $('#handle').css('width', '100%'); + $('#searchResultFrame').css('width', "100%"); + $('#outer').css('overflow', 'auto'); + } + + this.setHeight = function() { + $("#outer").css('height', $(window).height() - $('#searchContentDiv').height()); + var iFrameHeight = $('#searchContentDiv').height() - $('#handle').height() - $('#searchForm').height() -15; + $('#searchResultFrame').css('height', iFrameHeight); + $('#loadingFrame').css('height', $('#searchResultFrame').height() -40); + }; + + this.render = function(targetTag, templateData, html, append) { + var template = _.template( html ); + var rendered = template( templateData ) + if(append){ + $(targetTag).after( rendered ); + } + else{ + $(targetTag).replaceWith( rendered ); + } + }; + +this.copySelectedText = function(el) { + selector = $(el.attr('href')); + selector.focus(); + if(selector.prop("tagName") == "TEXTAREA" && selector.attr('data-type') == "tinymce") { + tinyId = selector.attr('id'); + tinyMCE.get(tinyId).execCommand('mceInsertContent', true, self.selectedText + '
    '); + } else { + if(selector.val()) { + selector.val( selector.val() + ' ' + self.selectedText); + } else { + selector.val(self.selectedText); + } + } + self.removeSelectedText(); + } + + this.callSearch = function() { + self.searchEngine = $("input[type='radio'][name='searchType']:checked").val(); + self.searchTerm = $('#searchText').val() + if(!self.searchTerm) { + $('#searchText').focus(); + } else { + self.loadSearchResult(); + } + } + + + this.loadSearchResult = function() + { + var link =''; + switch (self.searchEngine) { + case 'wikipedia': + link = self.wikipediaLink; + break; + default: + link = self.europeanaLink; + } + var template = _.template( link ); + var templateData = { 'searchTerm' : self.searchTerm }; + link = template( templateData ); + var frameId = 'searchResultFrame'; + self.loadContent(link, frameId); + } + + this.loadContent = function(link, frameId) { + self.url = link; + self.removeSelectedText(); + $('#searchResultFrame').addClass('hidden'); + $('#loadingFrame').removeClass('hidden'); + $('#loadingFrame').css('height', $('#searchResultFrame').height() - 40); + var url = '../admin/proxy/'+ escape(link); + $('#' + frameId).attr('src', url); + }; + + this.setFrameEvents = function(frameId) { + var urlArray = self.url.split('.'); + $('#loadingFrame').addClass('hidden'); + $('#searchResultFrame').removeClass('hidden'); + $frameDocument = $('#' + frameId).contents() + if (urlArray[1] === 'europeana') { + $('#query-full', $frameDocument).hide(); + $('[id*="cb-"]', $frameDocument).on('click', function(e){ + if($(this).prop('checked')) { + link = $(this).parent().find('a').attr('href'); + self.goToLink(link) + } + }) + } else { + $('#p-search', $frameDocument).hide(); + } + $('a', $frameDocument).on('click', function(e) { + e.preventDefault(); + var link = $(this).attr('href'); + self.goToLink(link) + }); + $frameDocument.on('mouseup', function (e) { + var maxXval = $(document).width() - $("#input-menu").width()-$('#sidebar').width() + var x = Math.min(e.pageX + 5, maxXval); + var yPos = e.pageY - $('#searchResultFrame').contents().scrollTop() + $('#handle').height() + $('#searchForm').height(); + var yBottom = self.numField*$('.dropdown-menu').height(); + var maxYval = $('#searchResultFrame').height() - yBottom; + var y = Math.min(yPos, maxYval); + self.selectedText = self.getIframeSelectionText('searchResultFrame'); + if (self.selectedText) { + self.openContextMenu($('#searchResultContextmenu'), x, y); + } else { + $('#searchResultContextmenu').hide(); + } + }); + $frameDocument.on('beforeunload', function(e){ + e.preventDefault(); + }); + $('#searchResultFrame').contents().on('scroll', function(e) { + self.removeSelectedText(); + }); + self.instance = true; + }; + + this.goToLink = function (link) { + if(link) { + if (link.indexOf('#') == 0) { + /*TODO scroll to anchor... non funziona nell'iframe*/ + return; + } + var index = Math.max(link.indexOf('europeana.eu'), link.indexOf('wikipedia.org')); + if ( index < 0 ) { + return; + } else { + link = link.replace(/http:\/\//, ''); + } + self.loadContent(link, 'searchResultFrame'); + } + } + + this.getIframeSelectionText = function(iframeId) { + var iframe = document.getElementById(iframeId); + var win, doc = iframe.contentDocument; + if (doc) { + win = doc.defaultView; + } else { + win = iframe.contentWindow; + doc = win.document; + } + + if (win.getSelection) { + return win.getSelection().toString(); + } else if (doc.selection && doc.selection.createRange) { + return doc.selection.createRange().text; + } + }; + + this.openContextMenu = function(menu, x, y) { + $("#input-menumenu").addClass("open"); + menu.css( { 'top': y, 'left' : x, 'z-index': 2}); + menu.show(); + }; + + this.getInputFields = function() { + self.numField = 0; + var labelList = []; + var divCG = $('#myForm .control-group'); + var exclude = ['selectfrom', 'mediapicker', 'entityselect', 'europeanaRelatedContents']; + divCG.each( function(i, div) { + var label = $(this).find('label').html(); + var field = $($(this).find('input').get(0) || $(this).find('textarea').get(0)); + if ( (field.attr('type') == 'text' || !field.attr('type')) + && !field.attr('disabled') + && $.inArray(field.attr('data-type'), exclude) ==-1 + ) { + var item = { 'id' : field.attr('id') , + 'label': label + }; + labelList.push(item); + self.numField++; + } + }); + return labelList; + }; + + this.removeSelectedText = function() { + $('#searchResultContextmenu').hide(); + var iframe = document.getElementById('searchResultFrame'); + if(!iframe) { + return; + } + var win, doc = iframe.contentDocument; + if (doc) { + win = doc.defaultView; + } else { + win = iframe.contentWindow; + doc = win.document; + } + + if (win.getSelection()) { + if (win.getSelection().empty) { + win.getSelection().empty(); + } else if (win.getSelection().removeAllRanges) { + win.getSelection().removeAllRanges(); + } + } else if (doc.selection) { + doc.selection.empty(); + } + }; + + this.wait = function(milliseconds) { + var start = new Date().getTime(); + for (var i = 0; i < 1e7; i++) { + if ((new Date().getTime() - start) > milliseconds){ + break; + } + } + }; + +}); diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/js/locale/en-EN.js b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/locale/en-EN.js new file mode 100644 index 0000000..f79409e --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/locale/en-EN.js @@ -0,0 +1,66 @@ +GlizyLocale.OntologyBuilderEditor = { + entityNameLabel: 'Name', + attributesLabel: 'Attributes', + attributeType: 'Type', + attributeTarget: 'Target', + attributeLabel: 'Label', + attributeRelationShow: 'Relation show', + attributeDublicCore: 'Dublin core', + attributeDictionary: 'Dictionary', + attributeModule: 'Module', + field: 'Field', + relation: 'Relation', + referenceRelationsLabel: 'Reference relations', + referenceRelationsRelation: 'Relation', + referenceRelationsShow: 'Show', + referenceRelationsNone: 'There aren\'t reference relations', + relationShowImages: 'Show images', + relationShowLinks: 'Show links', + relationShowImagesLinks: 'Show images and links', + relationHide: 'Hide', + relationTo: 'to', + required: 'Required', + showLabelInFrontend: 'Show label in frontend', + entitySkin: 'Entity skin', + entityListSkin: 'Entity list skin', + showRelationsGraph: 'Show relations graph', + addButton: 'Add', + saveButton: 'Save', + saveCloseButton: 'Save and close', + modifySkinButton: 'Modify skin', + saveSkin: 'Save skin', + cancelButton: 'Cancel', + addTermToDictionary: 'Press Enter to add this term', + propertyDelConfirm: 'Are you sure you want to delete this property?', + overwriteSkinConfirm: 'Skins have been previously customized, by clicking on OK customizations will be lost.', + entitySavedMsg: 'Entity saved', + entitySavedError: 'Save error', + alertEmptyEntityName: 'Please give a name to this entity before saving.', + alertEmptyLabels: 'Please fill all empty labels before saving.', +}; + +GlizyLocale.RelationsEditorLoader = { + title: 'Relations', + cardinality: 'Cardinality', + emptyText: 'Empty', + requiredField: 'This field is required', + oneToOne: 'One to one', + oneToMany: 'One to many', + relationDelConfirm: 'Are you sure you want to delete this relation?', + saveButton: 'Save', + addNewButton: 'Add relation' +}; + +GlizyLocale.EntityLabelsEditorLoader = { + title: 'Entity labels', + emptyText: 'Empty', + requiredField: 'This field is required', + relationDelConfirm: 'Are you sure you want to delete this label?', + saveButton: 'Save', + addNewButton: 'Add label' +}; + +GlizyLocale.EntityFormEditEntitySelect = { + noEntities: 'There aren\'t entities of this type', + noEntitiesFound: 'No entities found' +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/js/locale/it-IT.js b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/locale/it-IT.js new file mode 100644 index 0000000..caefb3a --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/js/locale/it-IT.js @@ -0,0 +1,66 @@ +GlizyLocale.OntologyBuilderEditor = { + entityNameLabel: 'Nome', + attributesLabel: 'Attributi', + attributeType: 'Tipo', + attributeTarget: 'Target', + attributeLabel: 'Etichetta', + attributeRelationShow: 'Mostra relazione', + attributeDublicCore: 'Dublin core', + attributeDictionary: 'Dizionario', + attributeModule: 'Modulo', + field: 'Campo', + relation: 'Relazione', + referenceRelationsLabel: 'Relazioni referenti', + referenceRelationsRelation: 'Relazioni', + referenceRelationsShow: 'Mostra', + referenceRelationsNone: 'Non ci sono relazioni referenti', + relationShowImages: 'Mostra immagini', + relationShowLinks: 'Mostra links', + relationShowImagesLinks: 'Mostra immagini e links', + relationHide: 'Nascondi', + relationTo: 'a', + required: 'Richiesto', + showLabelInFrontend: 'Mostra etichetta nel frontend', + entitySkin: 'Skin entità', + entityListSkin: 'Skin per lista entità', + showRelationsGraph: 'Mostra grafo delle relazioni', + addButton: 'Aggiungi', + saveButton: 'Salva', + saveCloseButton: 'Salva e chiudi', + modifySkinButton: 'Modifica skin', + saveSkin: 'Salva skin', + cancelButton: 'Annulla', + addTermToDictionary: 'Premere Invio per aggiungere questo termine', + propertyDelConfirm: 'Siete sicuri di voler cancellare la proprietà selezionata?', + overwriteSkinConfirm: 'La skin era stata precedentemente personalizzata, cliccando su OK le personalizzazioni verranno perse.', + entitySavedMsg: 'Entità salvata', + entitySavedError: 'Errore nel salvataggio', + alertEmptyEntityName: 'Inserire un nome all\'entità prima di salvare.', + alertEmptyLabels: 'Inserire un valore a tutte le etichette vuote prima di salvare.', +}; + +GlizyLocale.RelationsEditorLoader = { + title: 'Relazioni', + cardinality: 'Cardinalità', + emptyText: 'Vuoto', + requiredField: 'Questo campo è richiesto', + oneToOne: 'Uno a uno', + oneToMany: 'Uno a molti', + relationDelConfirm: 'Siete sicuri di voler cancellare la relazione selezionata?', + saveButton: 'Salva', + addNewButton: 'Nuova relazione' +}; + +GlizyLocale.EntityLabelsEditorLoader = { + title: 'Etichette', + emptyText: 'Vuoto', + requiredField: 'Questo campo è richiesto', + relationDelConfirm: 'Siete sicuri di voler cancellare l\'etichetta selezionata?', + saveButton: 'Salva', + addNewButton: 'Nuova etichetta' +}; + +GlizyLocale.EntityFormEditEntitySelect = { + noEntities: 'Non ci sono entità di questo tipo', + noEntitiesFound: 'Nessuna entità trovata' +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDelete.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDelete.php new file mode 100644 index 0000000..4924fb6 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDelete.php @@ -0,0 +1,14 @@ +application->retrieveProxy('movio.modules.ontologybuilder.service.LocaleService'); + $language = $this->application->getEditingLanguage(); + $ar->entity_name = $localeService->getTranslation($language, $ar->entity_name); + + // TODO controllo acl + $ar->__url__ = __Link::makeLinkWithIcon('actionsMVC', 'icon-pencil icon-white', array('action' => 'edit', 'id' => $ar->getId(), 'title' => __T('GLZ_RECORD_EDIT'))); + $ar->__urlDelete__ = __Link::makeLinkWithIcon('actionsMVC', 'icon-remove icon-white', array('action' => 'delete', 'id' => $ar->getId(), 'title' => __T('GLZ_RECORD_EDIT')), __T('GLZ_RECORD_MSG_DELETE')); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDeleteEntity.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDeleteEntity.php new file mode 100644 index 0000000..e7f4385 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDeleteEntity.php @@ -0,0 +1,17 @@ +getType()); + + $output = __Link::makeLinkWithIcon('actionEntities', 'btn-icon icon-pencil', array('title' => __T('GLZ_RECORD_EDIT'), 'entityTypeId' => $entityTypeId, 'entityId' => $entityId, 'action' => 'edit' ) ); + $output .= __Link::makeLinkWithIcon('actionEntities', 'icon-trash btn-icon' ,array( 'title' => __T('GLZ_RECORD_DELETE'), 'entityTypeId' => $entityTypeId, 'entityId' => $entityId, 'action' => 'delete' ), __T( 'GLZ_RECORD_MSG_DELETE' ) ); + $output .= __Link::makeLinkWithIcon('actionEntities', $row->isVisible() ? 'icon-eye-open btn-icon' : 'icon-eye-close btn-icon', array( 'title' => $row->isVisible() ? __T('Hide') : __T('Show'), 'entityTypeId' => $entityTypeId, 'entityId' => $entityId, 'action' => 'togglevisibility' ) ); + + return $output; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDraftDeleteEntity.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDraftDeleteEntity.php new file mode 100644 index 0000000..aa54d78 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/ActionEditDraftDeleteEntity.php @@ -0,0 +1,18 @@ +getType()); + + $output = __Link::makeLinkWithIcon('actionEntities', 'btn-icon icon-pencil', array('title' => __T('GLZ_RECORD_EDIT'), 'entityTypeId' => $entityTypeId, 'entityId' => $entityId, 'action' => 'edit' ) ); + $output .= __Link::makeLinkWithIcon('actionEntities', 'btn-icon icon-edit', array('title' => __T('GLZ_RECORD_EDIT_DRAFT'), 'entityTypeId' => $entityTypeId, 'entityId' => $entityId, 'action' => 'editDraft' ) ); + $output .= __Link::makeLinkWithIcon('actionEntities', 'icon-trash btn-icon' ,array( 'title' => __T('GLZ_RECORD_DELETE'), 'entityTypeId' => $entityTypeId, 'entityId' => $entityId, 'action' => 'delete' ), __T( 'GLZ_RECORD_MSG_DELETE' ) ); + $output .= __Link::makeLinkWithIcon('actionEntities', $row->isVisible() ? 'icon-eye-open btn-icon' : 'icon-eye-close btn-icon', array( 'title' => $row->isVisible() ? __T('Hide') : __T('Show'), 'entityTypeId' => $entityTypeId, 'entityId' => $entityId, 'action' => 'togglevisibility' ) ); + + return $output; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/EntityName.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/EntityName.php new file mode 100644 index 0000000..4f515d1 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/EntityName.php @@ -0,0 +1,11 @@ +retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + return $entityTypeService->getEntityTypeName($entityTypeId); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/EntityVisualization.php b/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/EntityVisualization.php new file mode 100644 index 0000000..bf8d9d4 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/renderer/EntityVisualization.php @@ -0,0 +1,31 @@ +__image = ''; + + foreach ($ar->getValuesAsArray() as $value) { + if (is_string($value) && preg_match('/getImage.php\?id=(\d+)/', $value, $m)) { + $id = $m[1]; + $ar->__image = org_glizy_helpers_Media::getResizedImageById($id, true, + __Config::get('movio.thumb.entityList.width'), + __Config::get('movio.thumb.entityList.height'), + __Config::get('movio.thumb.entityList.crop') + ); + break; + } + } + + if ($ar->__image == '') { + $ar->__image =''; + } + + // TODO: verificare perché viene letto dalla request + if (!__Request::get('visualization')) { + $ar->visualization = 'list'; + } else { + $ar->visualization = __Request::get('visualization'); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/EntityLabelsEditorTemplate.html b/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/EntityLabelsEditorTemplate.html new file mode 100755 index 0000000..54a568d --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/EntityLabelsEditorTemplate.html @@ -0,0 +1,40 @@ + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/EntityTemplate.html b/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/EntityTemplate.html new file mode 100755 index 0000000..260721e --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/EntityTemplate.html @@ -0,0 +1,133 @@ + + + + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/ReferenceRelationsTemplate.html b/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/ReferenceRelationsTemplate.html new file mode 100755 index 0000000..0a21032 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/ReferenceRelationsTemplate.html @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/RelationsEditorTemplate.html b/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/RelationsEditorTemplate.html new file mode 100755 index 0000000..6d6d887 --- /dev/null +++ b/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/RelationsEditorTemplate.html @@ -0,0 +1,36 @@ + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/index.html b/src/admin/application/classes/movio/modules/ontologybuilder/views/skins/index.html new file mode 100644 index 0000000..e69de29 diff --git a/src/admin/application/classes/movio/modules/publishApp/controllers/Index.php b/src/admin/application/classes/movio/modules/publishApp/controllers/Index.php new file mode 100644 index 0000000..33334e3 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/controllers/Index.php @@ -0,0 +1,28 @@ +view, 'setData')) { + $siteProp = unserialize(org_glizy_Registry::get(__Config::get('REGISTRY_SITE_PROP').$this->application->getLanguage(), '')); + $lastUpdate = org_glizy_Registry::get('movio/modules/publishApp/lastUpdate'); + + $data = new StdClass; + $data->title = $siteProp['title']; + $data->subtitle = $siteProp['subtitle']; + + if ($lastUpdate) { + $data->lastUpdate = '

    '.__T('Last exportation date').': '. date(__T('GLZ_DATETIME_FORMAT').'

    ', $lastUpdate); + } + + $data->isExhibitionActive = 1; + + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language') + ->load('getLanguageDictionary'); + + $this->setComponentsAttribute('languages', 'rows', $it->count()); + + $this->view->setData($data); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/CreateJSON.php b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/CreateJSON.php new file mode 100644 index 0000000..61486e7 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/CreateJSON.php @@ -0,0 +1,23 @@ +user->isLogged()) + { + $json = array(); + + foreach ($languages as $language) { + $ar = __ObjectFactory::createModel('org.glizycms.core.models.Language'); + $ar->load($language); + $languageObj = new StdClass(); + $languageObj->code = $ar->language_code; + $languageObj->label = $ar->language_name; + $languageObj->file = $ar->language_name.'.db'; + $json[] = $languageObj; + } + + file_put_contents($exportPath.'package.json', json_encode($json)); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/CreateZip.php b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/CreateZip.php new file mode 100644 index 0000000..6f7cf0d --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/CreateZip.php @@ -0,0 +1,46 @@ +user->isLogged()) + { + require_once(__Paths::get('APPLICATION').'/libs/dZip.inc.php'); + $zip = new dZip($zipFile); + $this->addFolderToZip( $zip, $exportPath, $exportPath); + $zip->save(); + + org_glizy_Registry::set('movio/modules/publishApp/lastUpdate', strval(time())); + } + } + + private function addFolderToZip( &$zip, $dir, $baseDir) + { + if ($dir_handle = @opendir($dir)) + { + while ($file_name = readdir($dir_handle)) + { + if ($file_name!="." && $file_name!=".." ) + { + if ( !is_dir("$dir/$file_name") ) + { + $zipFileName = str_replace( $baseDir, '', "$dir/$file_name" ); + $zip->addFile( $dir.'/'.$file_name, $zipFileName ); + } + else + { + $this->addFolderToZip( $zip, "$dir/$file_name", $baseDir ); + } + } + } + closedir($dir_handle); + return 0; + } + else + { + return "Could not open directory $dir"; + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/Export.php b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/Export.php new file mode 100644 index 0000000..9cdd2b8 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/Export.php @@ -0,0 +1,28 @@ +user->isLogged()) + { + $mobileContentsTable = __Config::get('movio.modules.publishApp.mobileContentsTable'); + org_glizy_dataAccessDoctrine_DataAccess::truncateTable($mobileContentsTable); + + $mobileFulltextTable = __Config::get('movio.modules.publishApp.mobileFulltextTable'); + org_glizy_dataAccessDoctrine_DataAccess::truncateTable($mobileFulltextTable); + + $exportService = org_glizy_ObjectFactory::createObject('movio.modules.publishApp.service.ExportService'); + $exportService->export($languageId, $languageCode, $menuIdArray, $title, $subtitle, $creditPageId, $isExhibitionActive); + $medias = $exportService->getMedias(); + + foreach ($medias as $id => $fileName) { + $media = org_glizycms_mediaArchive_MediaManager::getMediaById($id); + @copy($media->getFileName(), $mediaPath.$fileName); + } + + return $exportService->getGraphs(); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/ExportCodes.php b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/ExportCodes.php new file mode 100644 index 0000000..b32921c --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/ExportCodes.php @@ -0,0 +1,20 @@ +user->isLogged()) + { + $it = org_glizy_objectFactory::createModelIterator('movio.modules.codes.models.Model'); + + foreach ($it as $ar) { + if (!$ar->custom_code_mapping_code) continue; + + $arCode = org_glizy_objectFactory::createModel('movio.modules.publishApp.models.Codes'); + $arCode->mobilecode_code = $ar->custom_code_mapping_code; + $arCode->mobilecode_link = $ar->custom_code_mapping_link; + $arCode->save(); + } + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/GetSteps.php b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/GetSteps.php new file mode 100644 index 0000000..567f17c --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/GetSteps.php @@ -0,0 +1,38 @@ +user->isLogged()) + { + $languages = is_array($languages) ? $languages : array($languages); + $exportPath = __Paths::get('CACHE').'export/'; + $mediaPath = $exportPath.'media/'; + $graphPath = $exportPath.'graph/'; + $zipFolder = __Paths::get('BASE').'export/'; + $zipFile = $zipFolder.'mobileContents.zip'; + + $creditPageId = str_replace('internal:', '', $creditPageId); + + $steps = array(); + + $steps[] = array('action' => 'PrepareExport', 'params' => array('exportPath' => $exportPath, 'languages' => $languages, 'mediaPath' => $mediaPath, 'graphPath' => $graphPath, 'zipFolder' => $zipFolder, 'zipFile' => $zipFile)); + $steps[] = array('action' => 'ExportCodes'); + + foreach ($languages as $languageId) { + $ar = __ObjectFactory::createModel('org.glizycms.core.models.Language'); + $ar->load($languageId); + $sqliteDb = $exportPath.$ar->language_name.'.db'; + $languageCode = $ar->language_code; + + $steps[] = array('action' => 'Export', 'params' => array('mediaPath' => $mediaPath, 'languageId' => $languageId, 'languageCode' => $languageCode, 'menuIdArray' => $menuIdArray, 'title' => $title, 'subtitle' => $subtitle, 'creditPageId' => $creditPageId, 'isExhibitionActive' => $isExhibitionActive)); + $steps[] = array('action' => 'Mysql2Sqlite', 'params' => array('exportPath' => $exportPath, 'sqliteDb' => $sqliteDb)); + } + + $steps[] = array('action' => 'CreateJSON', 'params' => array('exportPath' => $exportPath, 'languages' => $languages)); + $steps[] = array('action' => 'CreateZip', 'params' => array('exportPath' => $exportPath, 'mediaPath' => $mediaPath, 'zipFile' => $zipFile)); + + return $steps; + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/Mysql2Sqlite.php b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/Mysql2Sqlite.php new file mode 100644 index 0000000..c5e5c8a --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/Mysql2Sqlite.php @@ -0,0 +1,32 @@ +user->isLogged()) + { + $dbHost = __Config::get('DB_HOST'); + $dbUser = __Config::get('DB_USER'); + $dbPass = __Config::get('DB_PSW'); + $dbName = __Config::get('DB_NAME'); + + $tables= array( + array( + 'name' => __Config::get('movio.modules.publishApp.mobileCodesTable'), + 'type' => 'normal' + ), + array( + 'name' => __Config::get('movio.modules.publishApp.mobileContentsTable'), + 'type' => 'normal' + ), + array( + 'name' => __Config::get('movio.modules.publishApp.mobileFulltextTable'), + 'type' => 'fulltext' + ) + ); + + $mysql2SqliteService = org_glizy_ObjectFactory::createObject('movio.modules.publishApp.service.Mysql2SqliteService'); + $mysql2SqliteService->convert($dbHost, $dbUser, $dbPass, $dbName, $tables, $sqliteDb); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/PrepareExport.php b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/PrepareExport.php new file mode 100644 index 0000000..b8fdc6c --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/PrepareExport.php @@ -0,0 +1,30 @@ +user->isLogged()) + { + org_glizy_helpers_Files::deleteDirectory($exportPath); + @unlink($zipFile); + + @mkdir($exportPath); + @mkdir($mediaPath); + @mkdir($graphPath); + @mkdir($graphPath.'document'); + + foreach ($languages as $language) { + $ar = __ObjectFactory::createModel('org.glizycms.core.models.Language'); + $ar->load($language); + @mkdir($graphPath.$ar->language_code); + @mkdir($graphPath.'document/'.$ar->language_code); + } + + @mkdir($zipFolder); + @chmod($zipFolder, 0777); + + $mobileCodesTable = __Config::get('movio.modules.publishApp.mobileCodesTable'); + org_glizy_dataAccessDoctrine_DataAccess::truncateTable($mobileCodesTable); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/SaveSVG.php b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/SaveSVG.php new file mode 100644 index 0000000..6d46f52 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/controllers/ajax/SaveSVG.php @@ -0,0 +1,13 @@ +user->isLogged()) + { + $exportPath = __Paths::get('CACHE').'export/'; + $graphPath = $exportPath.'graph/'.$type.'/'.$languageCode.'/'.$id.'.svg'; + file_put_contents($graphPath, $svg); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/js/Admin.js b/src/admin/application/classes/movio/modules/publishApp/js/Admin.js new file mode 100755 index 0000000..2cbb971 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/js/Admin.js @@ -0,0 +1,7 @@ +GlizyApp.pages[ 'movio.modules.publishApp.views.Admin' ] = function( state, routing ) { + $(function(){ + if ('index'==state) { + var tree = new GlizycmsSiteTree("#js-glizycmsSiteTree", "#js-glizycmsSiteTreeAdd"); + } + }); +} diff --git a/src/admin/application/classes/movio/modules/publishApp/js/SiteTree.js b/src/admin/application/classes/movio/modules/publishApp/js/SiteTree.js new file mode 100755 index 0000000..ef07729 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/js/SiteTree.js @@ -0,0 +1,169 @@ +var GlizycmsSiteTree = dejavu.Class.declare({ + treeId: null, + tree: null, + ajaxUrl: null, + treeOffset: null, + + initialize: function(treeId, addPageId) { + var self = this; + this.treeId = treeId; + this.tree = $(this.treeId); + this.ajaxUrl = this.tree.data('ajaxurl'); + + // initialize the tree + this.tree.jstree({ + // List of active plugins + "plugins" : [ "themes","json_data","ui","crrm","cookies","dnd","types", "checkbox" ], + "json_data" : { + "ajax" : { + "url" : this.ajaxUrl+"GetSiteTree", + "data" : function (n) { + self.onResize(); + return { + "id" : n.attr ? n.attr("id").replace("node_","") : 0 + }; + } + } + }, + "cookies" : { + "save_selected" : false + } + }) + .bind("select_node.jstree", this.onNodeSelect) + .bind("remove.jstree", this.onNodeRemove) + .bind("move_node.jstree", this.onNodeMove) + .bind("loaded.jstree", this.onTreeLoaded); + this.tree.css("overflow", "auto"); + this.treeOffset = this.tree.offset(); + + // add page button + $(addPageId).click(this.onAddPageClick); + + // Listen events + Glizy.events.on("glizycms.pageAdded", this.onPageAdded); + Glizy.events.on("glizycms.refreshTree", this.onRefreshTree); + Glizy.events.on("glizycms.treeCallAjaxForMenu", this.onTreeAjaxCall); + + $(window).resize(this.onResize); + this.onResize(); + }, + + onResize: function (event) { + var h = $(window).height() - this.treeOffset.top; + this.tree.height(h); + }.$bound(), + + onTreeLoaded: function (event, data) { + this.tree.jstree('open_all'); + this.tree.jstree('check_all'); + }.$bound(), + + /** + * Tree node selected, dispatch the event with the menuId param + * @param event event DOM event + * @param object data Treeview data object + */ + onNodeSelect: function (event, data) { + if (data.rslt.e) { + Glizy.events.broadcast("glizycms.pageEdit", {"menuId": data.rslt.obj.attr("id")}); + } + }.$bound(), + + /** + * Tree node delete, send a ajax request to delete the node, + * after deleted the tree is refreshed. + * The ajax call Delete command with: + * menuId: id to delete + * @param event event DOM event + * @param object data Treeview data object + */ + onNodeRemove: function (event, data) { + var self = this; + data.rslt.obj.each(function () { + $.ajax({ + async : false, + type: 'POST', + url: self.ajaxUrl+"Delete", + data : { + "menuId" : this.id.replace("node_","") + }, + success : function (r) { + if(!r.status) { + data.inst.refresh(); + } + } + }); + }); + }.$bound(), + + /** + * Tree node move, send a ajax request to move the node, + * after the mode the tree is refreshed. + * The ajax call Move command with: + * menuId: id to move + * parentId: id of parent node + * position: a new position + * @param event event DOM event + * @param object data Treeview data object + */ + onNodeMove: function (event, data) { + var self = this; + data.rslt.o.each(function (i) { + $.ajax({ + async : false, + type: 'POST', + url: self.ajaxUrl+"Move", + data : { + "menuId" : $(this).attr("id").replace("node_",""), + "parentId" : data.rslt.cr === -1 ? 1 : data.rslt.np.attr("id").replace("node_",""), + "position" : data.rslt.cp + i + }, + success : function (r) { + if(!r.status) { + $.jstree.rollback(data.rlbk); + } + else { + $(data.rslt.oc).attr("id", "node_" + r.id); + if(data.rslt.cy && $(data.rslt.oc).children("UL").length) { + data.inst.refresh(data.inst._get_parent(data.rslt.oc)); + } + } + } + }); + }); + }.$bound(), + + onAddPageClick: function(e){ + e.preventDefault(); + Glizy.events.broadcast("glizycms.pageAdd", {"href": e.currentTarget.href}); + }.$bound(), + + onPageAdded: function(e){ + Glizy.events.broadcast("glizycms.pageEdit", {"menuId": e.message.menuId}); + var node = this.tree.find("#"+e.message.parentId); + var tree = jQuery.jstree._reference(this.treeId); + tree.refresh(node); + }.$bound(), + + onRefreshTree: function(e){ + var tree = jQuery.jstree._reference(this.treeId); + var currentNode = tree._get_node(null, false); + var parentNode = tree._get_parent(currentNode); + tree.refresh(currentNode); + }.$bound(), + + onTreeAjaxCall: function(e){ + var self = this; + $.ajax({ + async : false, + type: 'POST', + url: self.ajaxUrl+e.message.action, + data : { + "menuId" : e.message.menuId + }, + success : function (r) { + Glizy.events.broadcast("glizycms.refreshTree"); + } + }); + }.$bound(), +}); \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/models/Codes.xml b/src/admin/application/classes/movio/modules/publishApp/models/Codes.xml new file mode 100644 index 0000000..681d042 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/models/Codes.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/models/DocumentIndexFulltext.xml b/src/admin/application/classes/movio/modules/publishApp/models/DocumentIndexFulltext.xml new file mode 100644 index 0000000..2cf47b5 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/models/DocumentIndexFulltext.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/models/Mobilefulltext.xml b/src/admin/application/classes/movio/modules/publishApp/models/Mobilefulltext.xml new file mode 100644 index 0000000..6ed5e15 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/models/Mobilefulltext.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/service/ExportService.php b/src/admin/application/classes/movio/modules/publishApp/service/ExportService.php new file mode 100644 index 0000000..5ace647 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/service/ExportService.php @@ -0,0 +1,497 @@ +addMediaById($id); + $newLink = 'addMediaById($id); + $newSrc = 'src="'.$src.'"'; + $text = str_replace($links[0][$i], $newSrc, $text); + } + } + + // replace dei link inseriti a mano e non tramite il cms + if (preg_match_all('/where('media_category', '%'.$category.'%', 'LIKE'); + + foreach($it as $ar) { + $media = array( + 'id' => $ar->media_id, + 'title' => $ar->media_title, + 'fileName' => $ar->media_fileName + ); + $photogallery[$ar->media_id] = $media; + $this->addMedia(json_encode($media)); + } + } + + return array_values($photogallery); + } + + private function processPhotoGallery($contentJson) + { + $contentJson['text'] = $this->processText($contentJson['text']); + $contentJson['textAfter'] = $this->processText($contentJson['textAfter']); + + if ($contentJson['gallery-images']) { + $contentJson['photogallery'] = $this->removeLabelFromContainer($contentJson['gallery-images'], 'image'); + unset($contentJson['gallery-images']); + } + return $contentJson; + } + + private function processPhotoGalleryCategory($contentJson) + { + $contentJson['text'] = $this->processText($contentJson['text']); + $contentJson['textAfter'] = $this->processText($contentJson['textAfter']); + + if ($contentJson['gallery-images']) { + $contentJson['photogallery'] = $this->resolvePhotoGallery($contentJson['gallery-images']); + unset($contentJson['gallery-images']); + } + return $contentJson; + } + + + private function processStoryTeller($contentJson) + { + $contentJson['text'] = $this->processText($contentJson['text']); + + if ($contentJson['storyteller-story']) { + $storytellerStory = $contentJson['storyteller-story']; + + foreach($storytellerStory as $story) { + if ($story->type == 'photogallery') { + $story->gallery = $this->resolvePhotoGallery($story->gallery); + } + + $story->text = $this->processText($story->text); + $story->textAfter = $this->processText($story->textAfter); + } + } + return $contentJson; + } + + private function processImageHotspot($contentJson) + { + $contentJson['text'] = $this->processText($contentJson['text']); + + if ($contentJson['image']) { + $contentJson['image'] = json_decode($contentJson['image']); + $imageId = $contentJson['image']->image; + $image = org_glizycms_mediaArchive_MediaManager::getMediaById($imageId); + $image = $this->addMedia(json_encode($image)); + $contentJson['image']->image = $image; + } + return $contentJson; + } + + private function processTimeline($menuId, $contentJson) + { + $contentJson['text'] = $this->processText($contentJson['text']); + + $request = org_glizy_objectFactory::createObject('org.glizy.rest.core.RestRequest', GLZ_HOST_ROOT.'/ajax.php', 'GET', array('pageId' => $menuId, 'ajaxTarget' => 'timeline')); + $request->execute(); + $response = $request->getResponseBody(); + $response = json_decode($response); + $contentJson['timeline'] = $response->timeline; + if ($contentJson['timeline']->date) { + foreach ($contentJson['timeline']->date as $i => $item) { + $media = $contentJson['timeline-timelineDef'][$i]->media->fileName; + $thumbnail = $contentJson['timeline-timelineDef'][$i]->media->fileName; + $item->asset->media = $media ? 'media/'.$media : ''; + $item->asset->thumbnail = $item->asset->media; + $item->asset->caption = $this->processText($contentJson['timeline-timelineDef'][$i]->mediaCaption); + $item->text = $this->processText($contentJson['timeline-timelineDef'][$i]->text); + } + } + unset($contentJson['timeline-timelineDef']); + return $contentJson; + } + + private function processPage($contentJson) + { + $contentJson['text'] = $this->processText($contentJson['text']); + $contentJson['images'] = $this->removeLabelFromContainer($contentJson['images'], 'image'); + $contentJson['attachments'] = $this->removeLabelFromContainer($contentJson['attachments'], 'media'); + return $contentJson; + } + + private function removeLabelFromContainer($container, $key) + { + if ($container) { + $elements = array(); + + foreach ($container as $element) { + $elements[] = $element->$key; + } + + return $elements; + } else { + return $container; + } + } + + private function processExhibition($contentJson) + { + $contentJson['abstract'] = $this->processText($contentJson['abstract']); + $contentJson['ticketOffice'] = $this->processText($contentJson['ticketOffice']); + $contentJson['catalog'] = $this->processText($contentJson['catalog']); + $contentJson['sponsor1'] = $this->processText($contentJson['sponsor1']); + $contentJson['sponsor2'] = $this->processText($contentJson['sponsor2']); + $contentJson['sponsor3'] = $this->processText($contentJson['sponsor3']); + $contentJson['honoraryCommittee'] = $this->processText($contentJson['honoraryCommittee']); + $contentJson['scientificCommittee'] = $this->processText($contentJson['scientificCommittee']); + $contentJson['dedication'] = $this->processText($contentJson['dedication']); + $contentJson['aknowledgements'] = $this->processText($contentJson['aknowledgements']); + $contentJson['promotion'] = $this->processText($contentJson['promotion']); + $contentJson['pressOffice'] = $this->processText($contentJson['pressOffice']); + $contentJson['projectConstruction'] = $this->processText($contentJson['projectConstruction']); + $contentJson['reviews'] = $this->processText($contentJson['reviews']); + $contentJson['contacts'] = $this->processText($contentJson['contacts']); + $contentJson['services'] = $this->processText($contentJson['services']); + + $contentJson['images'] = $this->removeLabelFromContainer($contentJson['images'], 'image'); + $contentJson['attaches'] = $this->removeLabelFromContainer($contentJson['attaches'], 'media'); + return $contentJson; + } + + private function processDigitalExhibition($contentJson) + { + $contentJson['description'] = $this->processText($contentJson['description']); + $contentJson['credits'] = $this->processText($contentJson['credits']); + $contentJson['sponsor1'] = $this->processText($contentJson['sponsor1']); + $contentJson['sponsor2'] = $this->processText($contentJson['sponsor2']); + $contentJson['sponsor3'] = $this->processText($contentJson['sponsor3']); + $contentJson['honoraryCommittee'] = $this->processText($contentJson['honoraryCommittee']); + $contentJson['scientificCommittee'] = $this->processText($contentJson['scientificCommittee']); + $contentJson['dedication'] = $this->processText($contentJson['dedication']); + $contentJson['aknowledgements'] = $this->processText($contentJson['aknowledgements']); + $contentJson['contacts'] = $this->processText($contentJson['contacts']); + $contentJson['services'] = $this->processText($contentJson['services']); + + $contentJson['images'] = $this->removeLabelFromContainer($contentJson['images'], 'image'); + $contentJson['attaches'] = $this->removeLabelFromContainer($contentJson['attaches'], 'media'); + return $contentJson; + } + + private function processVideo($contentJson) + { + $contentJson['text'] = $this->processText($contentJson['text']); + $contentJson['video-textAlternative'] = $this->processText($contentJson['video-textAlternative']); + return $contentJson; + } + + private function processCover($contentJson) + { + $contentJson['text'] = $this->processText($contentJson['text']); + $contentJson['textAfter'] = $this->processText($contentJson['textAfter']); + return $contentJson; + } + + private function processGoogleMap($contentJson) + { + $contentJson['text'] = $this->processText($contentJson['text']); + return $contentJson; + } + + private function processGraph($contentJson, $menuId, $languageCode) + { + $parent = null; + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $c = __ObjectFactory::createComponent('movio.modules.publishApp.views.components.Graph', $application, $parent, 'cmp:Graph', 'idDummy'); + $c->setAttribute('entityTypeId', $contentJson['entitySelect']); + $c->setAttribute('generateLinks', true); + $c->setAttribute('addGraphJsLibs.js', false); + $c->process(); + $c->render(); + + $this->addGraph($languageCode, $menuId, $c->getGraphData()); + + $contentJson['graph'] = 'graph/'.$languageCode.'/'.$menuId.'.svg'; + + return $contentJson; + } + + public function export($languageId = 1, $languageCode = null, $menuIdArray = array(), $title = null, $subtitle = null, $creditPageId = null, $isExhibitionActive = null) + { + __Paths::set('APPLICATION_TEMPLATE_DEFAULT', __Paths::get('STATIC_DIR').'movio/templates/Default/'); + + $menuIdArray = array_flip($menuIdArray); + $menuIdArray = array_fill_keys(array_keys($menuIdArray), 1); + + $this->medias = array(); + + $contentProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.ContentProxy'); + + // scorre tutti i menù + $menus = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Menu'); + $menus->load('getAllMenu', array('params' => array( 'languageId' => $languageId))); + foreach ($menus as $ar) { + $menuId = $ar->menu_id; + + // salta tutte le pagine che non sono in menuIdArray + if (!$menuIdArray[$menuId]) { + continue; + } + + $contentVO = $contentProxy->readContentFromMenu($menuId, $languageId); + + $contentJson = array(); + foreach($contentVO as $k=>$v) { + if ($k == '__title') { + $contentJson['title'] = $v; + continue; + } + if (@strpos($k, '__')===0) continue; + + if (is_object($v)) { + $contentJson[$k] = $this->convertObjectToArray($v); + } else { + if (@strpos($v, '{"id"')===0) { + $v = $this->addMedia($v); + } + $contentJson[$k] = $v; + } + } + + $arMobile = org_glizy_objectFactory::createModel('movio.models.Mobilecontents'); + + // informaizoni da salvare per il menu: + // menuId, parent, titolo, pageType, type, contenuto + // salvare solo i menu visibili + // creare una tabella apposta e salvarci i dati dentro + // + if ($ar->menudetail_isVisible) { + $arMobile->content_menuId = $menuId; + $arMobile->content_pageType = $ar->menu_pageType; + $arMobile->content_parent = $ar->menu_parentId; + $arMobile->content_type = $ar->menu_type; + $arMobile->content_title = $ar->menudetail_title; + + if ($arMobile->content_pageType == 'Storyteller') { + $contentJson = $this->processStoryTeller($contentJson); + } elseif ($arMobile->content_pageType == 'Photogallery') { + $contentJson = $this->processPhotoGallery($contentJson); + } elseif ($arMobile->content_pageType == 'Photogallery_category') { + $arMobile->content_pageType = 'Photogallery'; + $contentJson = $this->processPhotoGalleryCategory($contentJson); + } elseif ($arMobile->content_pageType == 'ImageHotspot') { + $contentJson = $this->processImageHotspot($contentJson); + } elseif ($arMobile->content_pageType == 'Timeline') { + $contentJson = $this->processTimeline($menuId, $contentJson); + } elseif ($arMobile->content_pageType == 'Page') { + $contentJson = $this->processPage($contentJson); + } elseif ($arMobile->content_pageType == 'Exhibition') { + $contentJson = $this->processExhibition($contentJson); + $contentJson['isActive'] = $isExhibitionActive ? 1 : 0; + } elseif ($arMobile->content_pageType == 'DigitalExhibition') { + $contentJson = $this->processDigitalExhibition($contentJson); + } elseif ($arMobile->content_pageType == 'Home') { + $contentJson['title'] = $title; + $contentJson['subtitle'] = $subtitle; + } elseif ($arMobile->content_pageType == 'Video') { + $contentJson = $this->processVideo($contentJson); + } elseif ($arMobile->content_pageType == 'Cover') { + $contentJson = $this->processCover($contentJson); + } elseif ($arMobile->content_pageType == 'GoogleMap') { + $contentJson = $this->processGoogleMap($contentJson); + } elseif ($arMobile->content_pageType == 'Graph') { + $contentJson = $this->processGraph($contentJson, $menuId, $languageCode); + } + + if ($menuId == $creditPageId) { + $arMobile->content_pageType = 'Credits'; + $arMobile->content_parent = 0; + } + + $arMobile->content_content = json_encode($contentJson); + $contentId = $arMobile->save(); + + $it = org_glizy_objectFactory::createModelIterator('org.glizycms.core.models.Content'); + $fulltextAr = $it->where("id", $menuId) + ->whereLanguageIs($languageId) + ->selectIndex('fulltext', 'document_index_fulltext_name', 'document_index_fulltext_value')->first(); + + if ($fulltextAr->document_index_fulltext_value) { + $ar = org_glizy_objectFactory::createModel('movio.modules.publishApp.models.Mobilefulltext'); + $ar->mobilefulltext_FK_content_id = $contentId; + $ar->mobilefulltext_text = str_replace(' ##', '', $fulltextAr->document_index_fulltext_value); + $ar->mobilefulltext_title = $contentJson['title']; + $ar->mobilefulltext_subtitle = $contentJson['subtitle']; + $ar->save(); + } + + // quando menu_pageType è Entity c'è da scorrere tutti i contenuti dell'entità + // e caricare i dati + // salvare + // documenId, titolo, contenuto + if ($arMobile->content_pageType == 'Entity') { + $parent = $arMobile->content_id; + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + + $it = __ObjectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityDocument'); + $it->whereTypeIs('entity'.$contentJson['entitySelect']); + + foreach ($it as $arEntitySelect) { + $documentId = $arEntitySelect->document_id; + $c = __ObjectFactory::createComponent('movio.modules.ontologybuilder.views.components.EntityToJSON', $application, $parent, 'glz:EntityToJSON', $documentId); + $c->setAttribute('visible', true); + $c->process(); + $c->render(); + + $medias = $c->getMedias(); + $this->addMediaArray($medias); + + $graphCode = $c->getGraph(); + $this->addGraph($languageCode, $documentId, $graphCode, 'document'); + + $jsonEntity = $c->getJson(); + $jsonEntity['graph'] = 'graph/document/'.$languageCode.'/'.$documentId.'.svg'; + $jsonEntity['content'] = $this->processText($jsonEntity['content']); + + $arContentMobile = org_glizy_objectFactory::createModel('movio.models.Mobilecontents'); + $arContentMobile->content_documentId = $documentId; + $arContentMobile->content_pageType = 'EntityChild'; + $arContentMobile->content_parent = $parent; + $arContentMobile->content_title = $arEntitySelect->title; + $arContentMobile->content_content = json_encode($jsonEntity); + $contentId = $arContentMobile->save(); + + $fulltextAr = org_glizy_objectFactory::createModel('movio.modules.publishApp.models.DocumentIndexFulltext'); + $result = $fulltextAr->find(array('document_index_fulltext_FK_document_detail_id' => $arEntitySelect->document_detail_id)); + + if ($result) { + $ar = org_glizy_objectFactory::createModel('movio.modules.publishApp.models.Mobilefulltext'); + $ar->mobilefulltext_FK_content_id = $contentId; + $ar->mobilefulltext_text = str_replace(' ##', '', $fulltextAr->document_index_fulltext_value); + $ar->mobilefulltext_title = $arEntitySelect->title; + $ar->mobilefulltext_subtitle = $arEntitySelect->subtitle; + $ar->save(); + } + } + } + } + } + } + + private function convertObjectToArray($data) + { + $result = array(); + if (is_object($data)) { + $objectKeys = array_keys(get_object_vars($data)); + if ($objectKeys) { + $numItems = 0; + foreach($objectKeys as $k) { + $numItems = max(count($data->{$k}), $numItems); + } + for($i=0; $i < $numItems; $i++) { + $tempObj = new StdClass; + foreach($objectKeys as $k) { + $v = $data->{$k}[$i]; + if (@strpos($v, '{"id"')===0) { + $v = $this->addMedia($v); + } + + $tempObj->{$k} = $v; + } + + $result[] = $tempObj; + } + } + } + + return $result; + } + + private function addMedia($media) + { + $result = new StdClass(); + $media = json_decode($media); + $m = org_glizycms_mediaArchive_MediaManager::getMediaById($media->id); + if ($m == null) { + return null; + } + $result->type = $m->type; + $result->title = $media->title; + if ($result->type == 'VIDEO') { + $result->url = GLZ_HOST.'/'.org_glizy_helpers_Media::getFileUrlById($media->id, true); + } else { + $result->fileName = $media->fileName; + $this->medias[$media->id] = $media->fileName; + } + return $result; + } + + private function addMediaById($mediaId) + { + $media = org_glizycms_mediaArchive_MediaManager::getMediaById($mediaId); + + if ($media == null) { + return null; + } + + if ($media->type == 'VIDEO') { + return GLZ_HOST.'/'.org_glizy_helpers_Media::getFileUrlById($media->id); + } else { + $this->medias[$media->id] = $media->fileName; + return 'media/'.$media->fileName; + } + } + + private function addMediaArray($medias) + { + foreach ($medias as $mediaId => $mediaFileName) { + $this->medias[$mediaId] = $mediaFileName; + } + } + + public function getMedias() + { + return $this->medias; + } + + private function addGraph($languageCode, $id, $graphCode, $type = '') + { + return $this->graphs[] = array('languageCode' => $languageCode, 'id' => $id, 'code' => $graphCode, 'type' => $type); + } + + public function getGraphs() + { + return $this->graphs; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/service/Mysql2SqliteService.php b/src/admin/application/classes/movio/modules/publishApp/service/Mysql2SqliteService.php new file mode 100644 index 0000000..bfea51b --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/service/Mysql2SqliteService.php @@ -0,0 +1,154 @@ + 'SET NAMES utf8' ); + $mysqli = new PDO( "mysql:host=".$dbHost.";dbname=".$dbName, $dbUser, $dbPass, $options ); + } catch( PDOException $e ) { + $this->showMessageAndDie( $e->getMessage() ); + } + + try { + @unlink( $sqliteDb ); + $sqlite = new PDO( "sqlite:".$sqliteDb ); + } catch( PDOException $e ) { + $this->showMessageAndDie($e->getMessage()); + } + + foreach($tables as $table) { + $this->converTable($mysqli, $sqlite, $table['name'], $table['type'] === 'fulltext'); + } + } + + private function converTable( $mysqli, $sqlite, $tableName, $fts3 = false) + { + $createFields = array(); + $pkFields = array(); + $indexFields = array(); + $tableFields = array(); + + foreach ( $mysqli->query( "SHOW COLUMNS FROM ".$tableName ) as $row ) + { + $tableFields[] = $row[ "Field" ]; + $fieldType = "TEXT"; + if ( stripos( $row[ "Type" ], "int(" ) !== false ) + { + $fieldType = "INTEGER"; + } + elseif ( stripos( $row[ "Type" ], "datetime") !== false ) + { + $fieldType = "DATETIME"; + } + elseif ( stripos( $row[ "Type" ], "date" ) !== false ) + { + $fieldType = "DATE"; + } + + if ( $row[ "Key" ] == "PRI" ) + { + if ($fts3 == true) { + // non considera questo campo + array_pop($tableFields); + continue; + } + + //$fieldType = "INTEGER"; + $pkFields[] = $row[ "Field" ]; + } + else if ( $row[ "Key" ] == "MUL" ) + { + $indexFields[] = "CREATE INDEX ".$row[ "Field" ]."_index ON ".$tableName."(".$row[ "Field" ].")"; + } + + $createFields[] = $row[ "Field" ]." ".$fieldType; + } + + if ($fts3 == true) { + $sqlCreate= "CREATE VIRTUAL TABLE ".$tableName." USING fts3(".implode(",", $createFields).")"; + } else { + if ( count( $pkFields ) ) { + array_push( $createFields, "PRIMARY KEY (".implode( ",", $pkFields ).")" ); + } + $sqlCreate= "CREATE TABLE ".$tableName." (".implode(",", $createFields).")"; + } + + + // create the table + $r = $sqlite->exec( $sqlCreate ); + if ($r === false) { + $this->showMessageAndDie( print_r( $sqlite->errorInfo(), true) ); + } + + // insert statement + $insertSqlPart = str_repeat( "?,", count( $tableFields ) ); + $insertSqlPart = substr( $insertSqlPart, 0, -1 ); + $insertSql = "INSERT INTO ".$tableName."(".implode(",", $tableFields).") VALUES ( ".$insertSqlPart." ) "; + $sth = $sqlite->prepare( $insertSql ); + + // get the number of records in the table + $sthCount = $mysqli->query( "SELECT count(*) FROM ".$tableName ); + $row = $sthCount->fetch(); + $numRows = $row[ 0 ]; + $sthCount->closeCursor(); + + // read and convert all records + $pageLength = 100000; + $currentPage = 0; + $i = 0; + while ( true ) + { + $sqlite->beginTransaction(); + foreach ( $mysqli->query( "SELECT * FROM ".$tableName." LIMIT ".$currentPage.",".$pageLength ) as $row ) + { + $params = array(); + foreach( $tableFields as $v ) + { + $params[] = $row[ $v ]; + } + + $r = $sth->execute( $params ); + if ( !$r ) + { + // error + $this->showMessageAndDie( print_r( $sqlite->errorInfo(), true) ); + } + + $i++; + } + $sqlite->commit(); + + if ( $i < $numRows ) + { + echo "."; + $currentPage += $pageLength; + } + else + { + break; + } + } + + // create index + if ( count( $indexFields ) ) + { + $sqlite->exec( implode( ";", $indexFields ) ); + } + } + + private function showMessage($message) + { + echo $message."\n"; + } + + private function showMessageAndDie($message) + { + die( $message."\n\n" ); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/service/PublishAppService.php b/src/admin/application/classes/movio/modules/publishApp/service/PublishAppService.php new file mode 100644 index 0000000..258a97d --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/service/PublishAppService.php @@ -0,0 +1,79 @@ +export(); + $medias = $exportService->getMedias(); + + foreach ($medias as $id => $fileName) { + $media = org_glizycms_mediaArchive_MediaManager::getMediaById($id); + copy($media->getFileName(), $mediaPath.$fileName); + } + + $dbHost = __Config::get('DB_HOST'); + $dbUser = __Config::get('DB_USER'); + $dbPass = __Config::get('DB_PSW'); + $dbName = __Config::get('DB_NAME'); + $tableName = __Config::get('movio.modules.publishApp.mobileContentsTable'); + $sqliteDb = $exportPath.__Config::get('movio.modules.publishApp.sqliteDbName'); + + $mysql2SqliteService = org_glizy_ObjectFactory::createObject('movio.modules.publishApp.service.Mysql2SqliteService'); + $mysql2SqliteService->convert($dbHost, $dbUser, $dbPass, $dbName, $tableName, $sqliteDb); + + $this->createZip($exportPath, $zipPath); + org_glizy_Registry::set('movio/modules/publishApp/lastUpdate', time()); + } + + protected function createZip($exportPath, $zipPath) + { + require_once(__Paths::get('APPLICATION').'/libs/dZip.inc.php'); + $zip = new dZip( $zipPath ); + $this->addFolderToZip( $zip, $exportPath, $exportPath); + $zip->save(); + } + + private function addFolderToZip( &$zip, $dir, $baseDir) + { + if ($dir_handle = @opendir($dir)) + { + while ($file_name = readdir($dir_handle)) + { + if ($file_name!="." && $file_name!=".." ) + { + if ( !is_dir("$dir/$file_name") ) + { + $zipFileName = str_replace( $baseDir, '', "$dir/$file_name" ); + $zip->addFile( $dir.'/'.$file_name, $zipFileName ); + } + else + { + $this->addFolderToZip( $zip, "$dir/$file_name", $baseDir ); + } + } + } + closedir($dir_handle); + return 0; + } + else + { + return "Could not open directory $dir"; + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/static/PublishApp.js b/src/admin/application/classes/movio/modules/publishApp/static/PublishApp.js new file mode 100644 index 0000000..09b0d05 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/static/PublishApp.js @@ -0,0 +1,144 @@ +$(function(){ + var progressPart, progress, steps, stepPos, stepResult, $button; + + function openExportDialog() { + window.onbeforeunload = exitWarning; + $( "#progress_bar" ).modal({ overlayCss: {background: "#000"}, overlayClose: false, closeHTML:'' }); + } + + function closeExportDialog() { + window.onbeforeunload = null; + $.modal.close(); + resetProgressBar(); + } + + function exitWarning(e) { + var msg = 'Attenzione, uscendo da questa pagina verra\' interrotto il processo in corso!'; + e = e || window.event; + // For IE and Firefox prior to version 4 + if (e) { + e.returnValue = msg; + } + // For Safari + return msg; + }; + + function resetProgressBar() { + jQuery.fx.off = true; + $('#progress_bar .ui-progress').width("0%"); + $('#progress_bar .ui-label').hide(); + }; + + function execStep() { + if ( stepPos >= steps.length ) + { + alert( 'Esportazione completata' ); + $button.removeAttr("disabled"); + closeExportDialog(); + if ( stepResult.status ) + { + location.href = stepResult.result; + } + + return; + } + progress += progressPart; + + $('#progress_bar .ui-progress').animateProgress( progress ); + + // per ogni azione esegue una richiesta ajax + jQuery.ajax( { + url: Glizy.ajaxUrl+steps[ stepPos ].action, + data: steps[ stepPos ].params, + dataType: "json", + success: function( data ){ + if (data.result) { + $("#graph").hide(); + + $.each(data.result, function( index, value ) { + $("#graph").html(value['code']); + + $.ajax({ + url: Glizy.ajaxUrl+"saveSVG", + async: false, + dataType: 'json', + type: 'POST', + data: { + languageCode: value['languageCode'], + id: value['id'], + svg: $('#graph_div').html(), + type: value['type'] + }, + success: function( data ) { + } + }); + }); + } + stepResult = data; + stepPos++; + execStep(); + } } ); + }; + + function getTreeData() { + var menuIdArray = []; + + $("#js-glizycmsSiteTree").find(".jstree-undetermined").each(function(i, element){ + menuIdArray.push($(element).attr("id")); + }); + + $("#js-glizycmsSiteTree").find(".jstree-checked").each(function(i, element){ + menuIdArray.push($(element).attr("id")); + }); + + return menuIdArray; + }; + + $('input.js-publish-app').click(function(e){ + $button = $(this); + $button.attr("disabled", "disabled"); + + e.preventDefault(); + + var menuIdArray = getTreeData(); + + if (menuIdArray.length == 0) { + alert( 'Selezionare almeno una pagina da esportare.' ); + $button.removeAttr("disabled"); + return; + } + + $.ajax({ + url: Glizy.ajaxUrl+"getSteps", + dataType: 'json', + data: { + languages: $('#languages').val(), + menuIdArray: menuIdArray, + title: $('#title').val(), + subtitle: $('#subtitle').val(), + creditPageId: $('#creditPageId').val(), + isExhibitionActive: $('#isExhibitionActive').attr('checked'), + }, + success: function( data ) { + if ( data.status ) + { + if (data.result.length == 0) { + alert( 'Non ci sono dati da esportare' ); + } else { + openExportDialog(); + progressPart = 100 / data.result.length; + progress = 0; + stepPos = 0; + steps = data.result; + execStep(); + } + } + else + { + alert( 'Si è verificato un errore' ); + $button.removeAttr("disabled"); + } + } + }); + }) +}); \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/static/jquery.simplemodal.1.4.1.min.js b/src/admin/application/classes/movio/modules/publishApp/static/jquery.simplemodal.1.4.1.min.js new file mode 100644 index 0000000..479721d --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/static/jquery.simplemodal.1.4.1.min.js @@ -0,0 +1,25 @@ +/* + * SimpleModal 1.4.1 - jQuery Plugin + * http://www.ericmmartin.com/projects/simplemodal/ + * Copyright (c) 2010 Eric Martin (http://twitter.com/ericmmartin) + * Dual licensed under the MIT and GPL licenses + * Revision: $Id: jquery.simplemodal.js 261 2010-11-05 21:16:20Z emartin24 $ + */ +(function(d){var k=d.browser.msie&&parseInt(d.browser.version)===6&&typeof window.XMLHttpRequest!=="object",m=d.browser.msie&&parseInt(d.browser.version)===7,l=null,f=[];d.modal=function(a,b){return d.modal.impl.init(a,b)};d.modal.close=function(){d.modal.impl.close()};d.modal.focus=function(a){d.modal.impl.focus(a)};d.modal.setContainerDimensions=function(){d.modal.impl.setContainerDimensions()};d.modal.setPosition=function(){d.modal.impl.setPosition()};d.modal.update=function(a,b){d.modal.impl.update(a, +b)};d.fn.modal=function(a){return d.modal.impl.init(this,a)};d.modal.defaults={appendTo:"body",focus:true,opacity:50,overlayId:"simplemodal-overlay",overlayCss:{},containerId:"simplemodal-container",containerCss:{},dataId:"simplemodal-data",dataCss:{},minHeight:null,minWidth:null,maxHeight:null,maxWidth:null,autoResize:false,autoPosition:true,zIndex:1E3,close:true,closeHTML:'',closeClass:"simplemodal-close",escClose:true,overlayClose:false,position:null, +persist:false,modal:true,onOpen:null,onShow:null,onClose:null};d.modal.impl={d:{},init:function(a,b){var c=this;if(c.d.data)return false;l=d.browser.msie&&!d.boxModel;c.o=d.extend({},d.modal.defaults,b);c.zIndex=c.o.zIndex;c.occb=false;if(typeof a==="object"){a=a instanceof jQuery?a:d(a);c.d.placeholder=false;if(a.parent().parent().size()>0){a.before(d("").attr("id","simplemodal-placeholder").css({display:"none"}));c.d.placeholder=true;c.display=a.css("display");if(!c.o.persist)c.d.orig= +a.clone(true)}}else if(typeof a==="string"||typeof a==="number")a=d("
    ").html(a);else{alert("SimpleModal Error: Unsupported data type: "+typeof a);return c}c.create(a);c.open();d.isFunction(c.o.onShow)&&c.o.onShow.apply(c,[c.d]);return c},create:function(a){var b=this;f=b.getDimensions();if(b.o.modal&&k)b.d.iframe=d('').css(d.extend(b.o.iframeCss,{display:"none",opacity:0,position:"fixed",height:f[0],width:f[1],zIndex:b.o.zIndex,top:0,left:0})).appendTo(b.o.appendTo); +b.d.overlay=d("
    ").attr("id",b.o.overlayId).addClass("simplemodal-overlay").css(d.extend(b.o.overlayCss,{display:"none",opacity:b.o.opacity/100,height:b.o.modal?f[0]:0,width:b.o.modal?f[1]:0,position:"fixed",left:0,top:0,zIndex:b.o.zIndex+1})).appendTo(b.o.appendTo);b.d.container=d("
    ").attr("id",b.o.containerId).addClass("simplemodal-container").css(d.extend(b.o.containerCss,{display:"none",position:"fixed",zIndex:b.o.zIndex+2})).append(b.o.close&&b.o.closeHTML?d(b.o.closeHTML).addClass(b.o.closeClass): +"").appendTo(b.o.appendTo);b.d.wrap=d("
    ").attr("tabIndex",-1).addClass("simplemodal-wrap").css({height:"100%",outline:0,width:"100%"}).appendTo(b.d.container);b.d.data=a.attr("id",a.attr("id")||b.o.dataId).addClass("simplemodal-data").css(d.extend(b.o.dataCss,{display:"none"})).appendTo("body");b.setContainerDimensions();b.d.data.appendTo(b.d.wrap);if(k||l)b.fixIE()},bindEvents:function(){var a=this;d("."+a.o.closeClass).bind("click.simplemodal",function(b){b.preventDefault();a.close()}); +a.o.modal&&a.o.close&&a.o.overlayClose&&a.d.overlay.bind("click.simplemodal",function(b){b.preventDefault();a.close()});d(document).bind("keydown.simplemodal",function(b){if(a.o.modal&&b.keyCode===9)a.watchTab(b);else if(a.o.close&&a.o.escClose&&b.keyCode===27){b.preventDefault();a.close()}});d(window).bind("resize.simplemodal",function(){f=a.getDimensions();a.o.autoResize?a.setContainerDimensions():a.o.autoPosition&&a.setPosition();if(k||l)a.fixIE();else if(a.o.modal){a.d.iframe&&a.d.iframe.css({height:f[0], +width:f[1]});a.d.overlay.css({height:f[0],width:f[1]})}})},unbindEvents:function(){d("."+this.o.closeClass).unbind("click.simplemodal");d(document).unbind("keydown.simplemodal");d(window).unbind("resize.simplemodal");this.d.overlay.unbind("click.simplemodal")},fixIE:function(){var a=this,b=a.o.position;d.each([a.d.iframe||null,!a.o.modal?null:a.d.overlay,a.d.container],function(c,h){if(h){var g=h[0].style;g.position="absolute";if(c<2){g.removeExpression("height");g.removeExpression("width");g.setExpression("height", +'document.body.scrollHeight > document.body.clientHeight ? document.body.scrollHeight : document.body.clientHeight + "px"');g.setExpression("width",'document.body.scrollWidth > document.body.clientWidth ? document.body.scrollWidth : document.body.clientWidth + "px"')}else{var e;if(b&&b.constructor===Array){c=b[0]?typeof b[0]==="number"?b[0].toString():b[0].replace(/px/,""):h.css("top").replace(/px/,"");c=c.indexOf("%")===-1?c+' + (t = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"': +parseInt(c.replace(/%/,""))+' * ((document.documentElement.clientHeight || document.body.clientHeight) / 100) + (t = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"';if(b[1]){e=typeof b[1]==="number"?b[1].toString():b[1].replace(/px/,"");e=e.indexOf("%")===-1?e+' + (t = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft) + "px"':parseInt(e.replace(/%/,""))+' * ((document.documentElement.clientWidth || document.body.clientWidth) / 100) + (t = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft) + "px"'}}else{c= +'(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (t = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"';e='(document.documentElement.clientWidth || document.body.clientWidth) / 2 - (this.offsetWidth / 2) + (t = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft) + "px"'}g.removeExpression("top");g.removeExpression("left");g.setExpression("top", +c);g.setExpression("left",e)}}})},focus:function(a){var b=this;a=a&&d.inArray(a,["first","last"])!==-1?a:"first";var c=d(":input:enabled:visible:"+a,b.d.wrap);setTimeout(function(){c.length>0?c.focus():b.d.wrap.focus()},10)},getDimensions:function(){var a=d(window);return[d.browser.opera&&d.browser.version>"9.5"&&d.fn.jquery<"1.3"||d.browser.opera&&d.browser.version<"9.5"&&d.fn.jquery>"1.2.6"?a[0].innerHeight:a.height(),a.width()]},getVal:function(a,b){return a?typeof a==="number"?a:a==="auto"?0: +a.indexOf("%")>0?parseInt(a.replace(/%/,""))/100*(b==="h"?f[0]:f[1]):parseInt(a.replace(/px/,"")):null},update:function(a,b){var c=this;if(!c.d.data)return false;c.d.origHeight=c.getVal(a,"h");c.d.origWidth=c.getVal(b,"w");c.d.data.hide();a&&c.d.container.css("height",a);b&&c.d.container.css("width",b);c.setContainerDimensions();c.d.data.show();c.o.focus&&c.focus();c.unbindEvents();c.bindEvents()},setContainerDimensions:function(){var a=this,b=k||m,c=a.d.origHeight?a.d.origHeight:d.browser.opera? +a.d.container.height():a.getVal(b?a.d.container[0].currentStyle.height:a.d.container.css("height"),"h");b=a.d.origWidth?a.d.origWidth:d.browser.opera?a.d.container.width():a.getVal(b?a.d.container[0].currentStyle.width:a.d.container.css("width"),"w");var h=a.d.data.outerHeight(true),g=a.d.data.outerWidth(true);a.d.origHeight=a.d.origHeight||c;a.d.origWidth=a.d.origWidth||b;var e=a.o.maxHeight?a.getVal(a.o.maxHeight,"h"):null,i=a.o.maxWidth?a.getVal(a.o.maxWidth,"w"):null;e=e&&ee?e:ce?e:a.o.minHeight&&j!=="auto"&&hi?i:bi?i:a.o.minWidth&&e!=="auto"&&gc||g>b?"auto":"visible"});a.o.autoPosition&&a.setPosition()},setPosition:function(){var a=this,b,c;b=f[0]/2-a.d.container.outerHeight(true)/2;c=f[1]/2-a.d.container.outerWidth(true)/ +2;if(a.o.position&&Object.prototype.toString.call(a.o.position)==="[object Array]"){b=a.o.position[0]||b;c=a.o.position[1]||c}else{b=b;c=c}a.d.container.css({left:c,top:b})},watchTab:function(a){var b=this;if(d(a.target).parents(".simplemodal-container").length>0){b.inputs=d(":input:enabled:visible:first, :input:enabled:visible:last",b.d.data[0]);if(!a.shiftKey&&a.target===b.inputs[b.inputs.length-1]||a.shiftKey&&a.target===b.inputs[0]||b.inputs.length===0){a.preventDefault();b.focus(a.shiftKey?"last": +"first")}}else{a.preventDefault();b.focus()}},open:function(){var a=this;a.d.iframe&&a.d.iframe.show();if(d.isFunction(a.o.onOpen))a.o.onOpen.apply(a,[a.d]);else{a.d.overlay.show();a.d.container.show();a.d.data.show()}a.o.focus&&a.focus();a.bindEvents()},close:function(){var a=this;if(!a.d.data)return false;a.unbindEvents();if(d.isFunction(a.o.onClose)&&!a.occb){a.occb=true;a.o.onClose.apply(a,[a.d])}else{if(a.d.placeholder){var b=d("#simplemodal-placeholder");if(a.o.persist)b.replaceWith(a.d.data.removeClass("simplemodal-data").css("display", +a.display));else{a.d.data.hide().remove();b.replaceWith(a.d.orig)}}else a.d.data.hide().remove();a.d.container.hide().remove();a.d.overlay.hide();a.d.iframe&&a.d.iframe.hide().remove();setTimeout(function(){a.d.overlay.remove();a.d={}},10)}}}})(jQuery); diff --git a/src/admin/application/classes/movio/modules/publishApp/static/progressBar.css b/src/admin/application/classes/movio/modules/publishApp/static/progressBar.css new file mode 100644 index 0000000..afcdb8f --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/static/progressBar.css @@ -0,0 +1,83 @@ +/* Progress Bar */ + +#progress_bar +{ + margin-left: auto ; + margin-right: auto ; + width: 400px; + display: none; +} + +.ui-progress-bar { + margin-top: 3em; + margin-bottom: 3em; +} + +.ui-progress span.ui-label { + font-size: 1.2em; + position: absolute; + right: 0; + line-height: 33px; + padding-right: 12px; + color: rgba(0,0,0,0.6); + text-shadow: rgba(255,255,255, 0.45) 0 1px 0px; + white-space: nowrap; +} + +@-webkit-keyframes animate-stripes { + from { + background-position: 0 0; + } + + to { + background-position: 44px 0; + } +} + +.ui-progress-bar { + position: relative; + height: 35px; + padding-right: 2px; + background-color: #abb2bc; + border-radius: 35px; + -moz-border-radius: 35px; + -webkit-border-radius: 35px; + background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #b6bcc6), color-stop(1, #9da5b0)); + background: -moz-linear-gradient(#9da5b0 0%, #b6bcc6 100%); + -webkit-box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.5), 0px 1px 0px 0px #FFF; + -moz-box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.5), 0px 1px 0px 0px #FFF; + box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.5), 0px 1px 0px 0px #FFF; +} + +.ui-progress { + position: relative; + display: block; + overflow: hidden; + height: 33px; + -moz-border-radius: 35px; + -webkit-border-radius: 35px; + border-radius: 35px; + -webkit-background-size: 44px 44px; + background-color: #74d04c; + background: -webkit-gradient(linear, 0 0, 44 44, + color-stop(0.00, rgba(255,255,255,0.17)), + color-stop(0.25, rgba(255,255,255,0.17)), + color-stop(0.26, rgba(255,255,255,0)), + color-stop(0.50, rgba(255,255,255,0)), + color-stop(0.51, rgba(255,255,255,0.17)), + color-stop(0.75, rgba(255,255,255,0.17)), + color-stop(0.76, rgba(255,255,255,0)), + color-stop(1.00, rgba(255,255,255,0)) + ), -webkit-gradient(linear, left bottom, left top, color-stop(0, #74d04c), color-stop(1, #9bdd62)); + background: -moz-repeating-linear-gradient(top left -30deg, + rgba(255,255,255,0.17), + rgba(255,255,255,0.17) 15px, + rgba(255,255,255,0) 15px, + rgba(255,255,255,0) 30px + ), -moz-linear-gradient(#9bdd62 0%, #74d04c 100%); + -webkit-box-shadow: inset 0px 1px 0px 0px #dbf383, inset 0px -1px 1px #58c43a; + -moz-box-shadow: inset 0px 1px 0px 0px #dbf383, inset 0px -1px 1px #58c43a; + box-shadow: inset 0px 1px 0px 0px #dbf383, inset 0px -1px 1px #58c43a; + border: 1px solid #4c8932; + -webkit-animation: animate-stripes 2s linear infinite; +} diff --git a/src/admin/application/classes/movio/modules/publishApp/views/Admin.xml b/src/admin/application/classes/movio/modules/publishApp/views/Admin.xml new file mode 100644 index 0000000..fdaebc2 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/views/Admin.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/views/components/DocumentGraph.php b/src/admin/application/classes/movio/modules/publishApp/views/components/DocumentGraph.php new file mode 100644 index 0000000..fc3c26f --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/views/components/DocumentGraph.php @@ -0,0 +1,8 @@ +graphData .= $output; + } + + public function getGraphData() + { + return $this->graphData; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/views/components/GraphContainer.php b/src/admin/application/classes/movio/modules/publishApp/views/components/GraphContainer.php new file mode 100644 index 0000000..085113d --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/views/components/GraphContainer.php @@ -0,0 +1,11 @@ +addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/d3.v3.min.js')); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/dagre-d3.min.js')); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile(__Paths::get('STATIC_DIR').'dagre-d3/graphlib-dot.min.js')); + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/publishApp/views/components/ProgressBarDialog.php b/src/admin/application/classes/movio/modules/publishApp/views/components/ProgressBarDialog.php new file mode 100644 index 0000000..13effde --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/views/components/ProgressBarDialog.php @@ -0,0 +1,76 @@ +addOutputCode( org_glizy_helpers_CSS::linkCSSfile( __Paths::get('APPLICATION_CLASSES').'movio/modules/publishApp/static/progressBar.css' ), 'head' ); + + $output = << +$(function() { + var state = 'progress'; + + (function ($) { + $.fn.animateProgress = function (progress, callback) { + jQuery.fx.off = false; + //var myduration = (progress - old_progress) * 1000 * (durata_totale_stimata / 100); + old_progress = progress; + return this.each(function () { + $(this).animate({ + width: String(progress) + '%' + }, { + //duration: myduration, + + easing: 'swing', + + step: function (progress) { + if (state === 'progress') { + + jQuery.fx.off = false; + + var labelEl = $('.ui-label', this), + valueEl = $('.value', labelEl); + + if (Math.ceil(progress) < 20) { + labelEl.hide(); + } else { + if (labelEl.is(":hidden")) { + labelEl.fadeIn(); + } + } + + valueEl.text(Math.ceil(progress) + '%'); + } + }, + + complete: function (scope, i, elem) { + if (callback) { + scope = 0; + callback.call(this, i, elem); + } + } + }); + }); + }; + }(jQuery)); + + + var resetProgressBar = function () { + jQuery.fx.off = true; + $('#progress_bar .ui-progress').width("0%"); + $('#progress_bar .ui-label').hide(); + }; + + resetProgressBar(); +}); + +EOD; + + $output .= '
    +
    + +
    '; + $this->addOutputCode( $output ); + } +} +?> diff --git a/src/admin/application/classes/movio/modules/publishApp/views/components/SiteTreeView.php b/src/admin/application/classes/movio/modules/publishApp/views/components/SiteTreeView.php new file mode 100644 index 0000000..af8b555 --- /dev/null +++ b/src/admin/application/classes/movio/modules/publishApp/views/components/SiteTreeView.php @@ -0,0 +1,25 @@ + +
    +

    +
    +
    +
    +
    +
    + +
    + +EOD; + return $skin; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/siteProperties/controllers/Index.php b/src/admin/application/classes/movio/modules/siteProperties/controllers/Index.php new file mode 100644 index 0000000..4012984 --- /dev/null +++ b/src/admin/application/classes/movio/modules/siteProperties/controllers/Index.php @@ -0,0 +1,11 @@ +application->getEditingLanguage(), '')); + if ($siteProp) { + $this->view->setData($siteProp); + } + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/siteProperties/controllers/ajax/Save.php b/src/admin/application/classes/movio/modules/siteProperties/controllers/ajax/Save.php new file mode 100644 index 0000000..fcaef70 --- /dev/null +++ b/src/admin/application/classes/movio/modules/siteProperties/controllers/ajax/Save.php @@ -0,0 +1,19 @@ +title; + $newData['subtitle'] = $data->subtitle; + $newData['address'] = $data->address; + $newData['copyright'] = $data->copyright; + $newData['slideShow'] = $data->slideShow; + $newData['analytics'] = $data->analytics; + $newData['googleMapsApiKey'] = $data->googleMapsApiKey; + + org_glizy_Registry::set(__Config::get('REGISTRY_SITE_PROP').$this->application->getEditingLanguage(), serialize($newData)); + return true; + } +} \ No newline at end of file diff --git a/src/admin/application/classes/movio/modules/siteProperties/views/SiteProperties.xml b/src/admin/application/classes/movio/modules/siteProperties/views/SiteProperties.xml new file mode 100644 index 0000000..80182b8 --- /dev/null +++ b/src/admin/application/classes/movio/modules/siteProperties/views/SiteProperties.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/admin/application/classes/movio/views/components/FormEdit.php b/src/admin/application/classes/movio/views/components/FormEdit.php new file mode 100644 index 0000000..a133c0a --- /dev/null +++ b/src/admin/application/classes/movio/views/components/FormEdit.php @@ -0,0 +1,4 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/admin/application/config/config.xml b/src/admin/application/config/config.xml new file mode 100644 index 0000000..727a00c --- /dev/null +++ b/src/admin/application/config/config.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/admin/application/config/config_common.xml b/src/admin/application/config/config_common.xml new file mode 100644 index 0000000..bba3935 --- /dev/null +++ b/src/admin/application/config/config_common.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ##FORM_LABEL## +
    + ##FORM_ITEM## +
    + + ]]>
    + + ##FORM_LABEL## +
    + ##FORM_ITEM## +
    + + ]]>
    + +
    + ##CONTENT## +
    + + ]]>
    +
    diff --git a/src/admin/application/config/routing.xml b/src/admin/application/config/routing.xml new file mode 100644 index 0000000..afac957 --- /dev/null +++ b/src/admin/application/config/routing.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/admin/application/config/siteMap.xml b/src/admin/application/config/siteMap.xml new file mode 100644 index 0000000..460cd90 --- /dev/null +++ b/src/admin/application/config/siteMap.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel.php new file mode 100755 index 0000000..abacb97 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel.php @@ -0,0 +1,895 @@ +_uniqueID = uniqid(); + $this->_calculationEngine = PHPExcel_Calculation::getInstance($this); + + // Initialise worksheet collection and add one worksheet + $this->_workSheetCollection = array(); + $this->_workSheetCollection[] = new PHPExcel_Worksheet($this); + $this->_activeSheetIndex = 0; + + // Create document properties + $this->_properties = new PHPExcel_DocumentProperties(); + + // Create document security + $this->_security = new PHPExcel_DocumentSecurity(); + + // Set named ranges + $this->_namedRanges = array(); + + // Create the cellXf supervisor + $this->_cellXfSupervisor = new PHPExcel_Style(true); + $this->_cellXfSupervisor->bindParent($this); + + // Create the default style + $this->addCellXf(new PHPExcel_Style); + $this->addCellStyleXf(new PHPExcel_Style); + } + + /** + * Code to execute when this worksheet is unset() + * + */ + public function __destruct() { + PHPExcel_Calculation::unsetInstance($this); + $this->disconnectWorksheets(); + } // function __destruct() + + /** + * Disconnect all worksheets from this PHPExcel workbook object, + * typically so that the PHPExcel object can be unset + * + */ + public function disconnectWorksheets() + { + $worksheet = NULL; + foreach($this->_workSheetCollection as $k => &$worksheet) { + $worksheet->disconnectCells(); + $this->_workSheetCollection[$k] = null; + } + unset($worksheet); + $this->_workSheetCollection = array(); + } + + /** + * Return the calculation engine for this worksheet + * + * @return PHPExcel_Calculation + */ + public function getCalculationEngine() + { + return $this->_calculationEngine; + } // function getCellCacheController() + + /** + * Get properties + * + * @return PHPExcel_DocumentProperties + */ + public function getProperties() + { + return $this->_properties; + } + + /** + * Set properties + * + * @param PHPExcel_DocumentProperties $pValue + */ + public function setProperties(PHPExcel_DocumentProperties $pValue) + { + $this->_properties = $pValue; + } + + /** + * Get security + * + * @return PHPExcel_DocumentSecurity + */ + public function getSecurity() + { + return $this->_security; + } + + /** + * Set security + * + * @param PHPExcel_DocumentSecurity $pValue + */ + public function setSecurity(PHPExcel_DocumentSecurity $pValue) + { + $this->_security = $pValue; + } + + /** + * Get active sheet + * + * @return PHPExcel_Worksheet + */ + public function getActiveSheet() + { + return $this->_workSheetCollection[$this->_activeSheetIndex]; + } + + /** + * Create sheet and add it to this workbook + * + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) + * @return PHPExcel_Worksheet + * @throws PHPExcel_Exception + */ + public function createSheet($iSheetIndex = NULL) + { + $newSheet = new PHPExcel_Worksheet($this); + $this->addSheet($newSheet, $iSheetIndex); + return $newSheet; + } + + /** + * Check if a sheet with a specified name already exists + * + * @param string $pSheetName Name of the worksheet to check + * @return boolean + */ + public function sheetNameExists($pSheetName) + { + return ($this->getSheetByName($pSheetName) !== NULL); + } + + /** + * Add sheet + * + * @param PHPExcel_Worksheet $pSheet + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) + * @return PHPExcel_Worksheet + * @throws PHPExcel_Exception + */ + public function addSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = NULL) + { + if ($this->sheetNameExists($pSheet->getTitle())) { + throw new PHPExcel_Exception( + "Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename this worksheet first." + ); + } + + if($iSheetIndex === NULL) { + if ($this->_activeSheetIndex < 0) { + $this->_activeSheetIndex = 0; + } + $this->_workSheetCollection[] = $pSheet; + } else { + // Insert the sheet at the requested index + array_splice( + $this->_workSheetCollection, + $iSheetIndex, + 0, + array($pSheet) + ); + + // Adjust active sheet index if necessary + if ($this->_activeSheetIndex >= $iSheetIndex) { + ++$this->_activeSheetIndex; + } + } + return $pSheet; + } + + /** + * Remove sheet by index + * + * @param int $pIndex Active sheet index + * @throws PHPExcel_Exception + */ + public function removeSheetByIndex($pIndex = 0) + { + + $numSheets = count($this->_workSheetCollection); + + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "You tried to remove a sheet by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}." + ); + } else { + array_splice($this->_workSheetCollection, $pIndex, 1); + } + // Adjust active sheet index if necessary + if (($this->_activeSheetIndex >= $pIndex) && + ($pIndex > count($this->_workSheetCollection) - 1)) { + --$this->_activeSheetIndex; + } + + } + + /** + * Get sheet by index + * + * @param int $pIndex Sheet index + * @return PHPExcel_Worksheet + * @throws PHPExcel_Exception + */ + public function getSheet($pIndex = 0) + { + + $numSheets = count($this->_workSheetCollection); + + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "Your requested sheet index: {$pIndex} is out of bounds. The actual number of sheets is {$numSheets}." + ); + } else { + return $this->_workSheetCollection[$pIndex]; + } + } + + /** + * Get all sheets + * + * @return PHPExcel_Worksheet[] + */ + public function getAllSheets() + { + return $this->_workSheetCollection; + } + + /** + * Get sheet by name + * + * @param string $pName Sheet name + * @return PHPExcel_Worksheet + */ + public function getSheetByName($pName = '') + { + $worksheetCount = count($this->_workSheetCollection); + for ($i = 0; $i < $worksheetCount; ++$i) { + if ($this->_workSheetCollection[$i]->getTitle() === $pName) { + return $this->_workSheetCollection[$i]; + } + } + + return NULL; + } + + /** + * Get index for sheet + * + * @param PHPExcel_Worksheet $pSheet + * @return Sheet index + * @throws PHPExcel_Exception + */ + public function getIndex(PHPExcel_Worksheet $pSheet) + { + foreach ($this->_workSheetCollection as $key => $value) { + if ($value->getHashCode() == $pSheet->getHashCode()) { + return $key; + } + } + + throw new PHPExcel_Exception("Sheet does not exist."); + } + + /** + * Set index for sheet by sheet name. + * + * @param string $sheetName Sheet name to modify index for + * @param int $newIndex New index for the sheet + * @return New sheet index + * @throws PHPExcel_Exception + */ + public function setIndexByName($sheetName, $newIndex) + { + $oldIndex = $this->getIndex($this->getSheetByName($sheetName)); + $pSheet = array_splice( + $this->_workSheetCollection, + $oldIndex, + 1 + ); + array_splice( + $this->_workSheetCollection, + $newIndex, + 0, + $pSheet + ); + return $newIndex; + } + + /** + * Get sheet count + * + * @return int + */ + public function getSheetCount() + { + return count($this->_workSheetCollection); + } + + /** + * Get active sheet index + * + * @return int Active sheet index + */ + public function getActiveSheetIndex() + { + return $this->_activeSheetIndex; + } + + /** + * Set active sheet index + * + * @param int $pIndex Active sheet index + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setActiveSheetIndex($pIndex = 0) + { + $numSheets = count($this->_workSheetCollection); + + if ($pIndex > $numSheets - 1) { + throw new PHPExcel_Exception( + "You tried to set a sheet active by the out of bounds index: {$pIndex}. The actual number of sheets is {$numSheets}." + ); + } else { + $this->_activeSheetIndex = $pIndex; + } + return $this->getActiveSheet(); + } + + /** + * Set active sheet index by name + * + * @param string $pValue Sheet title + * @return PHPExcel_Worksheet + * @throws PHPExcel_Exception + */ + public function setActiveSheetIndexByName($pValue = '') + { + if (($worksheet = $this->getSheetByName($pValue)) instanceof PHPExcel_Worksheet) { + $this->setActiveSheetIndex($this->getIndex($worksheet)); + return $worksheet; + } + + throw new PHPExcel_Exception('Workbook does not contain sheet:' . $pValue); + } + + /** + * Get sheet names + * + * @return string[] + */ + public function getSheetNames() + { + $returnValue = array(); + $worksheetCount = $this->getSheetCount(); + for ($i = 0; $i < $worksheetCount; ++$i) { + $returnValue[] = $this->getSheet($i)->getTitle(); + } + + return $returnValue; + } + + /** + * Add external sheet + * + * @param PHPExcel_Worksheet $pSheet External sheet to add + * @param int|null $iSheetIndex Index where sheet should go (0,1,..., or null for last) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function addExternalSheet(PHPExcel_Worksheet $pSheet, $iSheetIndex = null) { + if ($this->sheetNameExists($pSheet->getTitle())) { + throw new PHPExcel_Exception("Workbook already contains a worksheet named '{$pSheet->getTitle()}'. Rename the external sheet first."); + } + + // count how many cellXfs there are in this workbook currently, we will need this below + $countCellXfs = count($this->_cellXfCollection); + + // copy all the shared cellXfs from the external workbook and append them to the current + foreach ($pSheet->getParent()->getCellXfCollection() as $cellXf) { + $this->addCellXf(clone $cellXf); + } + + // move sheet to this workbook + $pSheet->rebindParent($this); + + // update the cellXfs + foreach ($pSheet->getCellCollection(false) as $cellID) { + $cell = $pSheet->getCell($cellID); + $cell->setXfIndex( $cell->getXfIndex() + $countCellXfs ); + } + + return $this->addSheet($pSheet, $iSheetIndex); + } + + /** + * Get named ranges + * + * @return PHPExcel_NamedRange[] + */ + public function getNamedRanges() { + return $this->_namedRanges; + } + + /** + * Add named range + * + * @param PHPExcel_NamedRange $namedRange + * @return PHPExcel + */ + public function addNamedRange(PHPExcel_NamedRange $namedRange) { + if ($namedRange->getScope() == null) { + // global scope + $this->_namedRanges[$namedRange->getName()] = $namedRange; + } else { + // local scope + $this->_namedRanges[$namedRange->getScope()->getTitle().'!'.$namedRange->getName()] = $namedRange; + } + return true; + } + + /** + * Get named range + * + * @param string $namedRange + * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope + * @return PHPExcel_NamedRange|null + */ + public function getNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) { + $returnValue = null; + + if ($namedRange != '' && ($namedRange !== NULL)) { + // first look for global defined name + if (isset($this->_namedRanges[$namedRange])) { + $returnValue = $this->_namedRanges[$namedRange]; + } + + // then look for local defined name (has priority over global defined name if both names exist) + if (($pSheet !== NULL) && isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) { + $returnValue = $this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]; + } + } + + return $returnValue; + } + + /** + * Remove named range + * + * @param string $namedRange + * @param PHPExcel_Worksheet|null $pSheet Scope: use null for global scope. + * @return PHPExcel + */ + public function removeNamedRange($namedRange, PHPExcel_Worksheet $pSheet = null) { + if ($pSheet === NULL) { + if (isset($this->_namedRanges[$namedRange])) { + unset($this->_namedRanges[$namedRange]); + } + } else { + if (isset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange])) { + unset($this->_namedRanges[$pSheet->getTitle() . '!' . $namedRange]); + } + } + return $this; + } + + /** + * Get worksheet iterator + * + * @return PHPExcel_WorksheetIterator + */ + public function getWorksheetIterator() { + return new PHPExcel_WorksheetIterator($this); + } + + /** + * Copy workbook (!= clone!) + * + * @return PHPExcel + */ + public function copy() { + $copied = clone $this; + + $worksheetCount = count($this->_workSheetCollection); + for ($i = 0; $i < $worksheetCount; ++$i) { + $this->_workSheetCollection[$i] = $this->_workSheetCollection[$i]->copy(); + $this->_workSheetCollection[$i]->rebindParent($this); + } + + return $copied; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + foreach($this as $key => $val) { + if (is_object($val) || (is_array($val))) { + $this->{$key} = unserialize(serialize($val)); + } + } + } + + /** + * Get the workbook collection of cellXfs + * + * @return PHPExcel_Style[] + */ + public function getCellXfCollection() + { + return $this->_cellXfCollection; + } + + /** + * Get cellXf by index + * + * @param int $pIndex + * @return PHPExcel_Style + */ + public function getCellXfByIndex($pIndex = 0) + { + return $this->_cellXfCollection[$pIndex]; + } + + /** + * Get cellXf by hash code + * + * @param string $pValue + * @return PHPExcel_Style|false + */ + public function getCellXfByHashCode($pValue = '') + { + foreach ($this->_cellXfCollection as $cellXf) { + if ($cellXf->getHashCode() == $pValue) { + return $cellXf; + } + } + return false; + } + + /** + * Check if style exists in style collection + * + * @param PHPExcel_Style $pCellStyle + * @return boolean + */ + public function cellXfExists($pCellStyle = null) + { + return in_array($pCellStyle, $this->_cellXfCollection, true); + } + + /** + * Get default style + * + * @return PHPExcel_Style + * @throws PHPExcel_Exception + */ + public function getDefaultStyle() + { + if (isset($this->_cellXfCollection[0])) { + return $this->_cellXfCollection[0]; + } + throw new PHPExcel_Exception('No default style found for this workbook'); + } + + /** + * Add a cellXf to the workbook + * + * @param PHPExcel_Style $style + */ + public function addCellXf(PHPExcel_Style $style) + { + $this->_cellXfCollection[] = $style; + $style->setIndex(count($this->_cellXfCollection) - 1); + } + + /** + * Remove cellXf by index. It is ensured that all cells get their xf index updated. + * + * @param int $pIndex Index to cellXf + * @throws PHPExcel_Exception + */ + public function removeCellXfByIndex($pIndex = 0) + { + if ($pIndex > count($this->_cellXfCollection) - 1) { + throw new PHPExcel_Exception("CellXf index is out of bounds."); + } else { + // first remove the cellXf + array_splice($this->_cellXfCollection, $pIndex, 1); + + // then update cellXf indexes for cells + foreach ($this->_workSheetCollection as $worksheet) { + foreach ($worksheet->getCellCollection(false) as $cellID) { + $cell = $worksheet->getCell($cellID); + $xfIndex = $cell->getXfIndex(); + if ($xfIndex > $pIndex ) { + // decrease xf index by 1 + $cell->setXfIndex($xfIndex - 1); + } else if ($xfIndex == $pIndex) { + // set to default xf index 0 + $cell->setXfIndex(0); + } + } + } + } + } + + /** + * Get the cellXf supervisor + * + * @return PHPExcel_Style + */ + public function getCellXfSupervisor() + { + return $this->_cellXfSupervisor; + } + + /** + * Get the workbook collection of cellStyleXfs + * + * @return PHPExcel_Style[] + */ + public function getCellStyleXfCollection() + { + return $this->_cellStyleXfCollection; + } + + /** + * Get cellStyleXf by index + * + * @param int $pIndex + * @return PHPExcel_Style + */ + public function getCellStyleXfByIndex($pIndex = 0) + { + return $this->_cellStyleXfCollection[$pIndex]; + } + + /** + * Get cellStyleXf by hash code + * + * @param string $pValue + * @return PHPExcel_Style|false + */ + public function getCellStyleXfByHashCode($pValue = '') + { + foreach ($this->_cellXfStyleCollection as $cellStyleXf) { + if ($cellStyleXf->getHashCode() == $pValue) { + return $cellStyleXf; + } + } + return false; + } + + /** + * Add a cellStyleXf to the workbook + * + * @param PHPExcel_Style $pStyle + */ + public function addCellStyleXf(PHPExcel_Style $pStyle) + { + $this->_cellStyleXfCollection[] = $pStyle; + $pStyle->setIndex(count($this->_cellStyleXfCollection) - 1); + } + + /** + * Remove cellStyleXf by index + * + * @param int $pIndex + * @throws PHPExcel_Exception + */ + public function removeCellStyleXfByIndex($pIndex = 0) + { + if ($pIndex > count($this->_cellStyleXfCollection) - 1) { + throw new PHPExcel_Exception("CellStyleXf index is out of bounds."); + } else { + array_splice($this->_cellStyleXfCollection, $pIndex, 1); + } + } + + /** + * Eliminate all unneeded cellXf and afterwards update the xfIndex for all cells + * and columns in the workbook + */ + public function garbageCollect() + { + // how many references are there to each cellXf ? + $countReferencesCellXf = array(); + foreach ($this->_cellXfCollection as $index => $cellXf) { + $countReferencesCellXf[$index] = 0; + } + + foreach ($this->getWorksheetIterator() as $sheet) { + + // from cells + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); + ++$countReferencesCellXf[$cell->getXfIndex()]; + } + + // from row dimensions + foreach ($sheet->getRowDimensions() as $rowDimension) { + if ($rowDimension->getXfIndex() !== null) { + ++$countReferencesCellXf[$rowDimension->getXfIndex()]; + } + } + + // from column dimensions + foreach ($sheet->getColumnDimensions() as $columnDimension) { + ++$countReferencesCellXf[$columnDimension->getXfIndex()]; + } + } + + // remove cellXfs without references and create mapping so we can update xfIndex + // for all cells and columns + $countNeededCellXfs = 0; + foreach ($this->_cellXfCollection as $index => $cellXf) { + if ($countReferencesCellXf[$index] > 0 || $index == 0) { // we must never remove the first cellXf + ++$countNeededCellXfs; + } else { + unset($this->_cellXfCollection[$index]); + } + $map[$index] = $countNeededCellXfs - 1; + } + $this->_cellXfCollection = array_values($this->_cellXfCollection); + + // update the index for all cellXfs + foreach ($this->_cellXfCollection as $i => $cellXf) { + $cellXf->setIndex($i); + } + + // make sure there is always at least one cellXf (there should be) + if (empty($this->_cellXfCollection)) { + $this->_cellXfCollection[] = new PHPExcel_Style(); + } + + // update the xfIndex for all cells, row dimensions, column dimensions + foreach ($this->getWorksheetIterator() as $sheet) { + + // for all cells + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); + $cell->setXfIndex( $map[$cell->getXfIndex()] ); + } + + // for all row dimensions + foreach ($sheet->getRowDimensions() as $rowDimension) { + if ($rowDimension->getXfIndex() !== null) { + $rowDimension->setXfIndex( $map[$rowDimension->getXfIndex()] ); + } + } + + // for all column dimensions + foreach ($sheet->getColumnDimensions() as $columnDimension) { + $columnDimension->setXfIndex( $map[$columnDimension->getXfIndex()] ); + } + + // also do garbage collection for all the sheets + $sheet->garbageCollect(); + } + } + + /** + * Return the unique ID value assigned to this spreadsheet workbook + * + * @return string + */ + public function getID() { + return $this->_uniqueID; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Autoloader.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Autoloader.php new file mode 100755 index 0000000..25aa38d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Autoloader.php @@ -0,0 +1,85 @@ +_currentCellIsDirty) { + $this->_currentObject->detach(); + + if (!apc_store($this->_cachePrefix.$this->_currentObjectID.'.cache',serialize($this->_currentObject),$this->_cacheTime)) { + $this->__destruct(); + throw new PHPExcel_Exception('Failed to store cell '.$this->_currentObjectID.' in APC'); + } + $this->_currentCellIsDirty = false; + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @access public + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + $this->_cellCache[$pCoord] = true; + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + $this->_currentCellIsDirty = true; + + return $cell; + } // function addCacheData() + + + /** + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? + * + * @access public + * @param string $pCoord Coordinate address of the cell to check + * @return void + * @return boolean + */ + public function isDataSet($pCoord) { + // Check if the requested entry is the current object, or exists in the cache + if (parent::isDataSet($pCoord)) { + if ($this->_currentObjectID == $pCoord) { + return true; + } + // Check if the requested entry still exists in apc + $success = apc_fetch($this->_cachePrefix.$pCoord.'.cache'); + if ($success === FALSE) { + // Entry no longer exists in APC, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in APC cache'); + } + return true; + } + return false; + } // function isDataSet() + + + /** + * Get cell at a specific coordinate + * + * @access public + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (parent::isDataSet($pCoord)) { + $obj = apc_fetch($this->_cachePrefix.$pCoord.'.cache'); + if ($obj === FALSE) { + // Entry no longer exists in APC, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in APC cache'); + } + } else { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = unserialize($obj); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + + /** + * Delete a cell in cache identified by coordinate address + * + * @access public + * @param string $pCoord Coordinate address of the cell to delete + * @throws PHPExcel_Exception + */ + public function deleteCacheData($pCoord) { + // Delete the entry from APC + apc_delete($this->_cachePrefix.$pCoord.'.cache'); + + // Delete the entry from our cell address array + parent::deleteCacheData($pCoord); + } // function deleteCacheData() + + + /** + * Clone the cell collection + * + * @access public + * @param PHPExcel_Worksheet $parent The new worksheet + * @throws PHPExcel_Exception + * @return void + */ + public function copyCellCollection(PHPExcel_Worksheet $parent) { + parent::copyCellCollection($parent); + // Get a new id for the new file name + $baseUnique = $this->_getUniqueID(); + $newCachePrefix = substr(md5($baseUnique),0,8).'.'; + $cacheList = $this->getCellList(); + foreach($cacheList as $cellID) { + if ($cellID != $this->_currentObjectID) { + $obj = apc_fetch($this->_cachePrefix.$cellID.'.cache'); + if ($obj === FALSE) { + // Entry no longer exists in APC, so clear it from the cache array + parent::deleteCacheData($cellID); + throw new PHPExcel_Exception('Cell entry '.$cellID.' no longer exists in APC'); + } + if (!apc_store($newCachePrefix.$cellID.'.cache',$obj,$this->_cacheTime)) { + $this->__destruct(); + throw new PHPExcel_Exception('Failed to store cell '.$cellID.' in APC'); + } + } + } + $this->_cachePrefix = $newCachePrefix; + } // function copyCellCollection() + + + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + if ($this->_currentObject !== NULL) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + + // Flush the APC cache + $this->__destruct(); + + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + + + /** + * Initialise this new cell collection + * + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection + * @param array of mixed $arguments Additional initialisation arguments + */ + public function __construct(PHPExcel_Worksheet $parent, $arguments) { + $cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600; + + if ($this->_cachePrefix === NULL) { + $baseUnique = $this->_getUniqueID(); + $this->_cachePrefix = substr(md5($baseUnique),0,8).'.'; + $this->_cacheTime = $cacheTime; + + parent::__construct($parent); + } + } // function __construct() + + + /** + * Destroy this cell collection + */ + public function __destruct() { + $cacheList = $this->getCellList(); + foreach($cacheList as $cellID) { + apc_delete($this->_cachePrefix.$cellID.'.cache'); + } + } // function __destruct() + + + /** + * Identify whether the caching method is currently available + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build + * + * @return boolean + */ + public static function cacheMethodIsAvailable() { + if (!function_exists('apc_store')) { + return FALSE; + } + if (apc_sma_info() === FALSE) { + return FALSE; + } + + return TRUE; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/CacheBase.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/CacheBase.php new file mode 100755 index 0000000..675cb03 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/CacheBase.php @@ -0,0 +1,318 @@ +_parent = $parent; + } // function __construct() + + + /** + * Return the parent worksheet for this cell collection + * + * @return PHPExcel_Worksheet + */ + public function getParent() + { + return $this->_parent; + } + + /** + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? + * + * @param string $pCoord Coordinate address of the cell to check + * @return boolean + */ + public function isDataSet($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return true; + } + // Check if the requested entry exists in the cache + return isset($this->_cellCache[$pCoord]); + } // function isDataSet() + + + /** + * Move a cell object from one address to another + * + * @param string $fromAddress Current address of the cell to move + * @param string $toAddress Destination address of the cell to move + * @return boolean + */ + public function moveCell($fromAddress, $toAddress) { + if ($fromAddress === $this->_currentObjectID) { + $this->_currentObjectID = $toAddress; + } + $this->_currentCellIsDirty = true; + if (isset($this->_cellCache[$fromAddress])) { + $this->_cellCache[$toAddress] = &$this->_cellCache[$fromAddress]; + unset($this->_cellCache[$fromAddress]); + } + + return TRUE; + } // function moveCell() + + + /** + * Add or Update a cell in cache + * + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception + */ + public function updateCacheData(PHPExcel_Cell $cell) { + return $this->addCacheData($cell->getCoordinate(),$cell); + } // function updateCacheData() + + + /** + * Delete a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to delete + * @throws PHPExcel_Exception + */ + public function deleteCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + $this->_currentObject->detach(); + $this->_currentObjectID = $this->_currentObject = null; + } + + if (is_object($this->_cellCache[$pCoord])) { + $this->_cellCache[$pCoord]->detach(); + unset($this->_cellCache[$pCoord]); + } + $this->_currentCellIsDirty = false; + } // function deleteCacheData() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + return array_keys($this->_cellCache); + } // function getCellList() + + + /** + * Sort the list of all cell addresses currently held in cache by row and column + * + * @return void + */ + public function getSortedCellList() { + $sortKeys = array(); + foreach ($this->getCellList() as $coord) { + sscanf($coord,'%[A-Z]%d', $column, $row); + $sortKeys[sprintf('%09d%3s',$row,$column)] = $coord; + } + ksort($sortKeys); + + return array_values($sortKeys); + } // function sortCellList() + + + + /** + * Get highest worksheet column and highest row that have cell records + * + * @return array Highest column name and highest row number + */ + public function getHighestRowAndColumn() + { + // Lookup highest column and highest row + $col = array('A' => '1A'); + $row = array(1); + foreach ($this->getCellList() as $coord) { + sscanf($coord,'%[A-Z]%d', $c, $r); + $row[$r] = $r; + $col[$c] = strlen($c).$c; + } + if (!empty($row)) { + // Determine highest column and row + $highestRow = max($row); + $highestColumn = substr(max($col),1); + } + + return array( 'row' => $highestRow, + 'column' => $highestColumn + ); + } + + + /** + * Return the cell address of the currently active cell object + * + * @return string + */ + public function getCurrentAddress() + { + return $this->_currentObjectID; + } + + /** + * Return the column address of the currently active cell object + * + * @return string + */ + public function getCurrentColumn() + { + sscanf($this->_currentObjectID, '%[A-Z]%d', $column, $row); + return $column; + } + + /** + * Return the row address of the currently active cell object + * + * @return string + */ + public function getCurrentRow() + { + sscanf($this->_currentObjectID, '%[A-Z]%d', $column, $row); + return $row; + } + + /** + * Get highest worksheet column + * + * @return string Highest column name + */ + public function getHighestColumn() + { + $colRow = $this->getHighestRowAndColumn(); + return $colRow['column']; + } + + /** + * Get highest worksheet row + * + * @return int Highest row number + */ + public function getHighestRow() + { + $colRow = $this->getHighestRowAndColumn(); + return $colRow['row']; + } + + + /** + * Generate a unique ID for cache referencing + * + * @return string Unique Reference + */ + protected function _getUniqueID() { + if (function_exists('posix_getpid')) { + $baseUnique = posix_getpid(); + } else { + $baseUnique = mt_rand(); + } + return uniqid($baseUnique,true); + } + + /** + * Clone the cell collection + * + * @param PHPExcel_Worksheet $parent The new worksheet + * @return void + */ + public function copyCellCollection(PHPExcel_Worksheet $parent) { + $this->_currentCellIsDirty; + $this->_storeData(); + + $this->_parent = $parent; + if (($this->_currentObject !== NULL) && (is_object($this->_currentObject))) { + $this->_currentObject->attach($this); + } + } // function copyCellCollection() + + + /** + * Identify whether the caching method is currently available + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build + * + * @return boolean + */ + public static function cacheMethodIsAvailable() { + return true; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/DiscISAM.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/DiscISAM.php new file mode 100755 index 0000000..10dce7d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/DiscISAM.php @@ -0,0 +1,219 @@ +_currentCellIsDirty) { + $this->_currentObject->detach(); + + fseek($this->_fileHandle,0,SEEK_END); + $offset = ftell($this->_fileHandle); + fwrite($this->_fileHandle, serialize($this->_currentObject)); + $this->_cellCache[$this->_currentObjectID] = array('ptr' => $offset, + 'sz' => ftell($this->_fileHandle) - $offset + ); + $this->_currentCellIsDirty = false; + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + $this->_currentCellIsDirty = true; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (!isset($this->_cellCache[$pCoord])) { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + fseek($this->_fileHandle,$this->_cellCache[$pCoord]['ptr']); + $this->_currentObject = unserialize(fread($this->_fileHandle,$this->_cellCache[$pCoord]['sz'])); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + + /** + * Clone the cell collection + * + * @param PHPExcel_Worksheet $parent The new worksheet + * @return void + */ + public function copyCellCollection(PHPExcel_Worksheet $parent) { + parent::copyCellCollection($parent); + // Get a new id for the new file name + $baseUnique = $this->_getUniqueID(); + $newFileName = $this->_cacheDirectory.'/PHPExcel.'.$baseUnique.'.cache'; + // Copy the existing cell cache file + copy ($this->_fileName,$newFileName); + $this->_fileName = $newFileName; + // Open the copied cell cache file + $this->_fileHandle = fopen($this->_fileName,'a+'); + } // function copyCellCollection() + + + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + + // Close down the temporary cache file + $this->__destruct(); + } // function unsetWorksheetCells() + + + /** + * Initialise this new cell collection + * + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection + * @param array of mixed $arguments Additional initialisation arguments + */ + public function __construct(PHPExcel_Worksheet $parent, $arguments) { + $this->_cacheDirectory = ((isset($arguments['dir'])) && ($arguments['dir'] !== NULL)) + ? $arguments['dir'] + : PHPExcel_Shared_File::sys_get_temp_dir(); + + parent::__construct($parent); + if (is_null($this->_fileHandle)) { + $baseUnique = $this->_getUniqueID(); + $this->_fileName = $this->_cacheDirectory.'/PHPExcel.'.$baseUnique.'.cache'; + $this->_fileHandle = fopen($this->_fileName,'a+'); + } + } // function __construct() + + + /** + * Destroy this cell collection + */ + public function __destruct() { + if (!is_null($this->_fileHandle)) { + fclose($this->_fileHandle); + unlink($this->_fileName); + } + $this->_fileHandle = null; + } // function __destruct() + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/ICache.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/ICache.php new file mode 100755 index 0000000..5902d66 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/ICache.php @@ -0,0 +1,112 @@ +_currentCellIsDirty) { + $this->_currentObject->detach(); + + $this->_cellCache[$this->_currentObjectID] = igbinary_serialize($this->_currentObject); + $this->_currentCellIsDirty = false; + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + $this->_currentCellIsDirty = true; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (!isset($this->_cellCache[$pCoord])) { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = igbinary_unserialize($this->_cellCache[$pCoord]); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + + + /** + * Identify whether the caching method is currently available + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build + * + * @return boolean + */ + public static function cacheMethodIsAvailable() { + if (!function_exists('igbinary_serialize')) { + return false; + } + + return true; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Memcache.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Memcache.php new file mode 100755 index 0000000..8c1c8a2 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Memcache.php @@ -0,0 +1,312 @@ +_currentCellIsDirty) { + $this->_currentObject->detach(); + + $obj = serialize($this->_currentObject); + if (!$this->_memcache->replace($this->_cachePrefix.$this->_currentObjectID.'.cache',$obj,NULL,$this->_cacheTime)) { + if (!$this->_memcache->add($this->_cachePrefix.$this->_currentObjectID.'.cache',$obj,NULL,$this->_cacheTime)) { + $this->__destruct(); + throw new PHPExcel_Exception('Failed to store cell '.$this->_currentObjectID.' in MemCache'); + } + } + $this->_currentCellIsDirty = false; + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + $this->_cellCache[$pCoord] = true; + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + $this->_currentCellIsDirty = true; + + return $cell; + } // function addCacheData() + + + /** + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? + * + * @param string $pCoord Coordinate address of the cell to check + * @return void + * @return boolean + */ + public function isDataSet($pCoord) { + // Check if the requested entry is the current object, or exists in the cache + if (parent::isDataSet($pCoord)) { + if ($this->_currentObjectID == $pCoord) { + return true; + } + // Check if the requested entry still exists in Memcache + $success = $this->_memcache->get($this->_cachePrefix.$pCoord.'.cache'); + if ($success === false) { + // Entry no longer exists in Memcache, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in MemCache'); + } + return true; + } + return false; + } // function isDataSet() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (parent::isDataSet($pCoord)) { + $obj = $this->_memcache->get($this->_cachePrefix.$pCoord.'.cache'); + if ($obj === false) { + // Entry no longer exists in Memcache, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in MemCache'); + } + } else { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = unserialize($obj); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + + /** + * Delete a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to delete + * @throws PHPExcel_Exception + */ + public function deleteCacheData($pCoord) { + // Delete the entry from Memcache + $this->_memcache->delete($this->_cachePrefix.$pCoord.'.cache'); + + // Delete the entry from our cell address array + parent::deleteCacheData($pCoord); + } // function deleteCacheData() + + + /** + * Clone the cell collection + * + * @param PHPExcel_Worksheet $parent The new worksheet + * @return void + */ + public function copyCellCollection(PHPExcel_Worksheet $parent) { + parent::copyCellCollection($parent); + // Get a new id for the new file name + $baseUnique = $this->_getUniqueID(); + $newCachePrefix = substr(md5($baseUnique),0,8).'.'; + $cacheList = $this->getCellList(); + foreach($cacheList as $cellID) { + if ($cellID != $this->_currentObjectID) { + $obj = $this->_memcache->get($this->_cachePrefix.$cellID.'.cache'); + if ($obj === false) { + // Entry no longer exists in Memcache, so clear it from the cache array + parent::deleteCacheData($cellID); + throw new PHPExcel_Exception('Cell entry '.$cellID.' no longer exists in MemCache'); + } + if (!$this->_memcache->add($newCachePrefix.$cellID.'.cache',$obj,NULL,$this->_cacheTime)) { + $this->__destruct(); + throw new PHPExcel_Exception('Failed to store cell '.$cellID.' in MemCache'); + } + } + } + $this->_cachePrefix = $newCachePrefix; + } // function copyCellCollection() + + + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + + // Flush the Memcache cache + $this->__destruct(); + + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + + + /** + * Initialise this new cell collection + * + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection + * @param array of mixed $arguments Additional initialisation arguments + */ + public function __construct(PHPExcel_Worksheet $parent, $arguments) { + $memcacheServer = (isset($arguments['memcacheServer'])) ? $arguments['memcacheServer'] : 'localhost'; + $memcachePort = (isset($arguments['memcachePort'])) ? $arguments['memcachePort'] : 11211; + $cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600; + + if (is_null($this->_cachePrefix)) { + $baseUnique = $this->_getUniqueID(); + $this->_cachePrefix = substr(md5($baseUnique),0,8).'.'; + + // Set a new Memcache object and connect to the Memcache server + $this->_memcache = new Memcache(); + if (!$this->_memcache->addServer($memcacheServer, $memcachePort, false, 50, 5, 5, true, array($this, 'failureCallback'))) { + throw new PHPExcel_Exception('Could not connect to MemCache server at '.$memcacheServer.':'.$memcachePort); + } + $this->_cacheTime = $cacheTime; + + parent::__construct($parent); + } + } // function __construct() + + + /** + * Memcache error handler + * + * @param string $host Memcache server + * @param integer $port Memcache port + * @throws PHPExcel_Exception + */ + public function failureCallback($host, $port) { + throw new PHPExcel_Exception('memcache '.$host.':'.$port.' failed'); + } + + + /** + * Destroy this cell collection + */ + public function __destruct() { + $cacheList = $this->getCellList(); + foreach($cacheList as $cellID) { + $this->_memcache->delete($this->_cachePrefix.$cellID.'.cache'); + } + } // function __destruct() + + /** + * Identify whether the caching method is currently available + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build + * + * @return boolean + */ + public static function cacheMethodIsAvailable() { + if (!function_exists('memcache_add')) { + return false; + } + + return true; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Memory.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Memory.php new file mode 100755 index 0000000..1f2cc88 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Memory.php @@ -0,0 +1,125 @@ +_cellCache[$pCoord] = $cell; + + // Set current entry to the new/updated entry + $this->_currentObjectID = $pCoord; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + // Check if the entry that has been requested actually exists + if (!isset($this->_cellCache[$pCoord])) { + $this->_currentObjectID = NULL; + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + + // Return requested entry + return $this->_cellCache[$pCoord]; + } // function getCacheData() + + + /** + * Clone the cell collection + * + * @param PHPExcel_Worksheet $parent The new worksheet + * @return void + */ + public function copyCellCollection(PHPExcel_Worksheet $parent) { + parent::copyCellCollection($parent); + + $newCollection = array(); + foreach($this->_cellCache as $k => &$cell) { + $newCollection[$k] = clone $cell; + $newCollection[$k]->attach($parent); + } + + $this->_cellCache = $newCollection; + } + + + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + // Because cells are all stored as intact objects in memory, we need to detach each one from the parent + foreach($this->_cellCache as $k => &$cell) { + $cell->detach(); + $this->_cellCache[$k] = null; + } + unset($cell); + + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/MemoryGZip.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/MemoryGZip.php new file mode 100755 index 0000000..33c3337 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/MemoryGZip.php @@ -0,0 +1,137 @@ +_currentCellIsDirty) { + $this->_currentObject->detach(); + + $this->_cellCache[$this->_currentObjectID] = gzdeflate(serialize($this->_currentObject)); + $this->_currentCellIsDirty = false; + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + $this->_currentCellIsDirty = true; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (!isset($this->_cellCache[$pCoord])) { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = unserialize(gzinflate($this->_cellCache[$pCoord])); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/MemorySerialized.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/MemorySerialized.php new file mode 100755 index 0000000..cd11cc4 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/MemorySerialized.php @@ -0,0 +1,137 @@ +_currentCellIsDirty) { + $this->_currentObject->detach(); + + $this->_cellCache[$this->_currentObjectID] = serialize($this->_currentObject); + $this->_currentCellIsDirty = false; + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + $this->_currentCellIsDirty = true; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (!isset($this->_cellCache[$pCoord])) { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = unserialize($this->_cellCache[$pCoord]); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/PHPTemp.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/PHPTemp.php new file mode 100755 index 0000000..7a53fcb --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/PHPTemp.php @@ -0,0 +1,206 @@ +_currentCellIsDirty) { + $this->_currentObject->detach(); + + fseek($this->_fileHandle,0,SEEK_END); + $offset = ftell($this->_fileHandle); + fwrite($this->_fileHandle, serialize($this->_currentObject)); + $this->_cellCache[$this->_currentObjectID] = array('ptr' => $offset, + 'sz' => ftell($this->_fileHandle) - $offset + ); + $this->_currentCellIsDirty = false; + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + $this->_currentCellIsDirty = true; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + if (!isset($this->_cellCache[$pCoord])) { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + fseek($this->_fileHandle,$this->_cellCache[$pCoord]['ptr']); + $this->_currentObject = unserialize(fread($this->_fileHandle,$this->_cellCache[$pCoord]['sz'])); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + + /** + * Clone the cell collection + * + * @param PHPExcel_Worksheet $parent The new worksheet + * @return void + */ + public function copyCellCollection(PHPExcel_Worksheet $parent) { + parent::copyCellCollection($parent); + // Open a new stream for the cell cache data + $newFileHandle = fopen('php://temp/maxmemory:'.$this->_memoryCacheSize,'a+'); + // Copy the existing cell cache data to the new stream + fseek($this->_fileHandle,0); + while (!feof($this->_fileHandle)) { + fwrite($newFileHandle,fread($this->_fileHandle, 1024)); + } + $this->_fileHandle = $newFileHandle; + } // function copyCellCollection() + + + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + + // Close down the php://temp file + $this->__destruct(); + } // function unsetWorksheetCells() + + + /** + * Initialise this new cell collection + * + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection + * @param array of mixed $arguments Additional initialisation arguments + */ + public function __construct(PHPExcel_Worksheet $parent, $arguments) { + $this->_memoryCacheSize = (isset($arguments['memoryCacheSize'])) ? $arguments['memoryCacheSize'] : '1MB'; + + parent::__construct($parent); + if (is_null($this->_fileHandle)) { + $this->_fileHandle = fopen('php://temp/maxmemory:'.$this->_memoryCacheSize,'a+'); + } + } // function __construct() + + + /** + * Destroy this cell collection + */ + public function __destruct() { + if (!is_null($this->_fileHandle)) { + fclose($this->_fileHandle); + } + $this->_fileHandle = null; + } // function __destruct() + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/SQLite.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/SQLite.php new file mode 100755 index 0000000..d96da0f --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/SQLite.php @@ -0,0 +1,306 @@ +_currentCellIsDirty) { + $this->_currentObject->detach(); + + if (!$this->_DBHandle->queryExec("INSERT OR REPLACE INTO kvp_".$this->_TableName." VALUES('".$this->_currentObjectID."','".sqlite_escape_string(serialize($this->_currentObject))."')")) + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); + $this->_currentCellIsDirty = false; + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + $this->_currentCellIsDirty = true; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + $query = "SELECT value FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'"; + $cellResultSet = $this->_DBHandle->query($query,SQLITE_ASSOC); + if ($cellResultSet === false) { + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); + } elseif ($cellResultSet->numRows() == 0) { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + + $cellResult = $cellResultSet->fetchSingle(); + $this->_currentObject = unserialize($cellResult); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Is a value set for an indexed cell? + * + * @param string $pCoord Coordinate address of the cell to check + * @return boolean + */ + public function isDataSet($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return true; + } + + // Check if the requested entry exists in the cache + $query = "SELECT id FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'"; + $cellResultSet = $this->_DBHandle->query($query,SQLITE_ASSOC); + if ($cellResultSet === false) { + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); + } elseif ($cellResultSet->numRows() == 0) { + // Return null if requested entry doesn't exist in cache + return false; + } + return true; + } // function isDataSet() + + + /** + * Delete a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to delete + * @throws PHPExcel_Exception + */ + public function deleteCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + $this->_currentObject->detach(); + $this->_currentObjectID = $this->_currentObject = null; + } + + // Check if the requested entry exists in the cache + $query = "DELETE FROM kvp_".$this->_TableName." WHERE id='".$pCoord."'"; + if (!$this->_DBHandle->queryExec($query)) + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); + + $this->_currentCellIsDirty = false; + } // function deleteCacheData() + + + /** + * Move a cell object from one address to another + * + * @param string $fromAddress Current address of the cell to move + * @param string $toAddress Destination address of the cell to move + * @return boolean + */ + public function moveCell($fromAddress, $toAddress) { + if ($fromAddress === $this->_currentObjectID) { + $this->_currentObjectID = $toAddress; + } + + $query = "DELETE FROM kvp_".$this->_TableName." WHERE id='".$toAddress."'"; + $result = $this->_DBHandle->exec($query); + if ($result === false) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + + $query = "UPDATE kvp_".$this->_TableName." SET id='".$toAddress."' WHERE id='".$fromAddress."'"; + $result = $this->_DBHandle->exec($query); + if ($result === false) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + + return TRUE; + } // function moveCell() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + $query = "SELECT id FROM kvp_".$this->_TableName; + $cellIdsResult = $this->_DBHandle->unbufferedQuery($query,SQLITE_ASSOC); + if ($cellIdsResult === false) + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); + + $cellKeys = array(); + foreach($cellIdsResult as $row) { + $cellKeys[] = $row['id']; + } + + return $cellKeys; + } // function getCellList() + + + /** + * Clone the cell collection + * + * @param PHPExcel_Worksheet $parent The new worksheet + * @return void + */ + public function copyCellCollection(PHPExcel_Worksheet $parent) { + $this->_currentCellIsDirty; + $this->_storeData(); + + // Get a new id for the new table name + $tableName = str_replace('.','_',$this->_getUniqueID()); + if (!$this->_DBHandle->queryExec('CREATE TABLE kvp_'.$tableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB) + AS SELECT * FROM kvp_'.$this->_TableName)) + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); + + // Copy the existing cell cache file + $this->_TableName = $tableName; + } // function copyCellCollection() + + + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + + // Close down the temporary cache file + $this->__destruct(); + } // function unsetWorksheetCells() + + + /** + * Initialise this new cell collection + * + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection + */ + public function __construct(PHPExcel_Worksheet $parent) { + parent::__construct($parent); + if (is_null($this->_DBHandle)) { + $this->_TableName = str_replace('.','_',$this->_getUniqueID()); + $_DBName = ':memory:'; + + $this->_DBHandle = new SQLiteDatabase($_DBName); + if ($this->_DBHandle === false) + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); + if (!$this->_DBHandle->queryExec('CREATE TABLE kvp_'.$this->_TableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)')) + throw new PHPExcel_Exception(sqlite_error_string($this->_DBHandle->lastError())); + } + } // function __construct() + + + /** + * Destroy this cell collection + */ + public function __destruct() { + if (!is_null($this->_DBHandle)) { + $this->_DBHandle->queryExec('DROP TABLE kvp_'.$this->_TableName); + } + $this->_DBHandle = null; + } // function __destruct() + + + /** + * Identify whether the caching method is currently available + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build + * + * @return boolean + */ + public static function cacheMethodIsAvailable() { + if (!function_exists('sqlite_open')) { + return false; + } + + return true; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/SQLite3.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/SQLite3.php new file mode 100755 index 0000000..a3e6fc8 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/SQLite3.php @@ -0,0 +1,345 @@ +_currentCellIsDirty) { + $this->_currentObject->detach(); + + $this->_insertQuery->bindValue('id',$this->_currentObjectID,SQLITE3_TEXT); + $this->_insertQuery->bindValue('data',serialize($this->_currentObject),SQLITE3_BLOB); + $result = $this->_insertQuery->execute(); + if ($result === false) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + $this->_currentCellIsDirty = false; + } + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + $this->_currentCellIsDirty = true; + + return $cell; + } // function addCacheData() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + $this->_selectQuery->bindValue('id',$pCoord,SQLITE3_TEXT); + $cellResult = $this->_selectQuery->execute(); + if ($cellResult === FALSE) { + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + } + $cellData = $cellResult->fetchArray(SQLITE3_ASSOC); + if ($cellData === FALSE) { + // Return null if requested entry doesn't exist in cache + return NULL; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + + $this->_currentObject = unserialize($cellData['value']); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Is a value set for an indexed cell? + * + * @param string $pCoord Coordinate address of the cell to check + * @return boolean + */ + public function isDataSet($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return TRUE; + } + + // Check if the requested entry exists in the cache + $this->_selectQuery->bindValue('id',$pCoord,SQLITE3_TEXT); + $cellResult = $this->_selectQuery->execute(); + if ($cellResult === FALSE) { + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + } + $cellData = $cellResult->fetchArray(SQLITE3_ASSOC); + + return ($cellData === FALSE) ? FALSE : TRUE; + } // function isDataSet() + + + /** + * Delete a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to delete + * @throws PHPExcel_Exception + */ + public function deleteCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + $this->_currentObject->detach(); + $this->_currentObjectID = $this->_currentObject = NULL; + } + + // Check if the requested entry exists in the cache + $this->_deleteQuery->bindValue('id',$pCoord,SQLITE3_TEXT); + $result = $this->_deleteQuery->execute(); + if ($result === FALSE) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + + $this->_currentCellIsDirty = FALSE; + } // function deleteCacheData() + + + /** + * Move a cell object from one address to another + * + * @param string $fromAddress Current address of the cell to move + * @param string $toAddress Destination address of the cell to move + * @return boolean + */ + public function moveCell($fromAddress, $toAddress) { + if ($fromAddress === $this->_currentObjectID) { + $this->_currentObjectID = $toAddress; + } + + $this->_deleteQuery->bindValue('id',$toAddress,SQLITE3_TEXT); + $result = $this->_deleteQuery->execute(); + if ($result === false) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + + $this->_updateQuery->bindValue('toid',$toAddress,SQLITE3_TEXT); + $this->_updateQuery->bindValue('fromid',$fromAddress,SQLITE3_TEXT); + $result = $this->_updateQuery->execute(); + if ($result === false) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + + return TRUE; + } // function moveCell() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + $query = "SELECT id FROM kvp_".$this->_TableName; + $cellIdsResult = $this->_DBHandle->query($query); + if ($cellIdsResult === false) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + + $cellKeys = array(); + while ($row = $cellIdsResult->fetchArray(SQLITE3_ASSOC)) { + $cellKeys[] = $row['id']; + } + + return $cellKeys; + } // function getCellList() + + + /** + * Clone the cell collection + * + * @param PHPExcel_Worksheet $parent The new worksheet + * @return void + */ + public function copyCellCollection(PHPExcel_Worksheet $parent) { + $this->_currentCellIsDirty; + $this->_storeData(); + + // Get a new id for the new table name + $tableName = str_replace('.','_',$this->_getUniqueID()); + if (!$this->_DBHandle->exec('CREATE TABLE kvp_'.$tableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB) + AS SELECT * FROM kvp_'.$this->_TableName)) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + + // Copy the existing cell cache file + $this->_TableName = $tableName; + } // function copyCellCollection() + + + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + + // Close down the temporary cache file + $this->__destruct(); + } // function unsetWorksheetCells() + + + /** + * Initialise this new cell collection + * + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection + */ + public function __construct(PHPExcel_Worksheet $parent) { + parent::__construct($parent); + if (is_null($this->_DBHandle)) { + $this->_TableName = str_replace('.','_',$this->_getUniqueID()); + $_DBName = ':memory:'; + + $this->_DBHandle = new SQLite3($_DBName); + if ($this->_DBHandle === false) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + if (!$this->_DBHandle->exec('CREATE TABLE kvp_'.$this->_TableName.' (id VARCHAR(12) PRIMARY KEY, value BLOB)')) + throw new PHPExcel_Exception($this->_DBHandle->lastErrorMsg()); + } + + $this->_selectQuery = $this->_DBHandle->prepare("SELECT value FROM kvp_".$this->_TableName." WHERE id = :id"); + $this->_insertQuery = $this->_DBHandle->prepare("INSERT OR REPLACE INTO kvp_".$this->_TableName." VALUES(:id,:data)"); + $this->_updateQuery = $this->_DBHandle->prepare("UPDATE kvp_".$this->_TableName." SET id=:toId WHERE id=:fromId"); + $this->_deleteQuery = $this->_DBHandle->prepare("DELETE FROM kvp_".$this->_TableName." WHERE id = :id"); + } // function __construct() + + + /** + * Destroy this cell collection + */ + public function __destruct() { + if (!is_null($this->_DBHandle)) { + $this->_DBHandle->exec('DROP TABLE kvp_'.$this->_TableName); + $this->_DBHandle->close(); + } + $this->_DBHandle = null; + } // function __destruct() + + + /** + * Identify whether the caching method is currently available + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build + * + * @return boolean + */ + public static function cacheMethodIsAvailable() { + if (!class_exists('SQLite3',FALSE)) { + return false; + } + + return true; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Wincache.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Wincache.php new file mode 100755 index 0000000..d4549d3 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorage/Wincache.php @@ -0,0 +1,294 @@ +_currentCellIsDirty) { + $this->_currentObject->detach(); + + $obj = serialize($this->_currentObject); + if (wincache_ucache_exists($this->_cachePrefix.$this->_currentObjectID.'.cache')) { + if (!wincache_ucache_set($this->_cachePrefix.$this->_currentObjectID.'.cache', $obj, $this->_cacheTime)) { + $this->__destruct(); + throw new PHPExcel_Exception('Failed to store cell '.$this->_currentObjectID.' in WinCache'); + } + } else { + if (!wincache_ucache_add($this->_cachePrefix.$this->_currentObjectID.'.cache', $obj, $this->_cacheTime)) { + $this->__destruct(); + throw new PHPExcel_Exception('Failed to store cell '.$this->_currentObjectID.' in WinCache'); + } + } + $this->_currentCellIsDirty = false; + } + + $this->_currentObjectID = $this->_currentObject = null; + } // function _storeData() + + + /** + * Add or Update a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to update + * @param PHPExcel_Cell $cell Cell to update + * @return void + * @throws PHPExcel_Exception + */ + public function addCacheData($pCoord, PHPExcel_Cell $cell) { + if (($pCoord !== $this->_currentObjectID) && ($this->_currentObjectID !== null)) { + $this->_storeData(); + } + $this->_cellCache[$pCoord] = true; + + $this->_currentObjectID = $pCoord; + $this->_currentObject = $cell; + $this->_currentCellIsDirty = true; + + return $cell; + } // function addCacheData() + + + /** + * Is a value set in the current PHPExcel_CachedObjectStorage_ICache for an indexed cell? + * + * @param string $pCoord Coordinate address of the cell to check + * @return boolean + */ + public function isDataSet($pCoord) { + // Check if the requested entry is the current object, or exists in the cache + if (parent::isDataSet($pCoord)) { + if ($this->_currentObjectID == $pCoord) { + return true; + } + // Check if the requested entry still exists in cache + $success = wincache_ucache_exists($this->_cachePrefix.$pCoord.'.cache'); + if ($success === false) { + // Entry no longer exists in Wincache, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in WinCache'); + } + return true; + } + return false; + } // function isDataSet() + + + /** + * Get cell at a specific coordinate + * + * @param string $pCoord Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found, or null if not found + */ + public function getCacheData($pCoord) { + if ($pCoord === $this->_currentObjectID) { + return $this->_currentObject; + } + $this->_storeData(); + + // Check if the entry that has been requested actually exists + $obj = null; + if (parent::isDataSet($pCoord)) { + $success = false; + $obj = wincache_ucache_get($this->_cachePrefix.$pCoord.'.cache', $success); + if ($success === false) { + // Entry no longer exists in WinCache, so clear it from the cache array + parent::deleteCacheData($pCoord); + throw new PHPExcel_Exception('Cell entry '.$pCoord.' no longer exists in WinCache'); + } + } else { + // Return null if requested entry doesn't exist in cache + return null; + } + + // Set current entry to the requested entry + $this->_currentObjectID = $pCoord; + $this->_currentObject = unserialize($obj); + // Re-attach this as the cell's parent + $this->_currentObject->attach($this); + + // Return requested entry + return $this->_currentObject; + } // function getCacheData() + + + /** + * Get a list of all cell addresses currently held in cache + * + * @return array of string + */ + public function getCellList() { + if ($this->_currentObjectID !== null) { + $this->_storeData(); + } + + return parent::getCellList(); + } + + + /** + * Delete a cell in cache identified by coordinate address + * + * @param string $pCoord Coordinate address of the cell to delete + * @throws PHPExcel_Exception + */ + public function deleteCacheData($pCoord) { + // Delete the entry from Wincache + wincache_ucache_delete($this->_cachePrefix.$pCoord.'.cache'); + + // Delete the entry from our cell address array + parent::deleteCacheData($pCoord); + } // function deleteCacheData() + + + /** + * Clone the cell collection + * + * @param PHPExcel_Worksheet $parent The new worksheet + * @return void + */ + public function copyCellCollection(PHPExcel_Worksheet $parent) { + parent::copyCellCollection($parent); + // Get a new id for the new file name + $baseUnique = $this->_getUniqueID(); + $newCachePrefix = substr(md5($baseUnique),0,8).'.'; + $cacheList = $this->getCellList(); + foreach($cacheList as $cellID) { + if ($cellID != $this->_currentObjectID) { + $success = false; + $obj = wincache_ucache_get($this->_cachePrefix.$cellID.'.cache', $success); + if ($success === false) { + // Entry no longer exists in WinCache, so clear it from the cache array + parent::deleteCacheData($cellID); + throw new PHPExcel_Exception('Cell entry '.$cellID.' no longer exists in Wincache'); + } + if (!wincache_ucache_add($newCachePrefix.$cellID.'.cache', $obj, $this->_cacheTime)) { + $this->__destruct(); + throw new PHPExcel_Exception('Failed to store cell '.$cellID.' in Wincache'); + } + } + } + $this->_cachePrefix = $newCachePrefix; + } // function copyCellCollection() + + + /** + * Clear the cell collection and disconnect from our parent + * + * @return void + */ + public function unsetWorksheetCells() { + if(!is_null($this->_currentObject)) { + $this->_currentObject->detach(); + $this->_currentObject = $this->_currentObjectID = null; + } + + // Flush the WinCache cache + $this->__destruct(); + + $this->_cellCache = array(); + + // detach ourself from the worksheet, so that it can then delete this object successfully + $this->_parent = null; + } // function unsetWorksheetCells() + + + /** + * Initialise this new cell collection + * + * @param PHPExcel_Worksheet $parent The worksheet for this cell collection + * @param array of mixed $arguments Additional initialisation arguments + */ + public function __construct(PHPExcel_Worksheet $parent, $arguments) { + $cacheTime = (isset($arguments['cacheTime'])) ? $arguments['cacheTime'] : 600; + + if (is_null($this->_cachePrefix)) { + $baseUnique = $this->_getUniqueID(); + $this->_cachePrefix = substr(md5($baseUnique),0,8).'.'; + $this->_cacheTime = $cacheTime; + + parent::__construct($parent); + } + } // function __construct() + + + /** + * Destroy this cell collection + */ + public function __destruct() { + $cacheList = $this->getCellList(); + foreach($cacheList as $cellID) { + wincache_ucache_delete($this->_cachePrefix.$cellID.'.cache'); + } + } // function __destruct() + + + /** + * Identify whether the caching method is currently available + * Some methods are dependent on the availability of certain extensions being enabled in the PHP build + * + * @return boolean + */ + public static function cacheMethodIsAvailable() { + if (!function_exists('wincache_ucache_add')) { + return false; + } + + return true; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorageFactory.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorageFactory.php new file mode 100755 index 0000000..8d394fe --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CachedObjectStorageFactory.php @@ -0,0 +1,251 @@ + array( + ), + self::cache_in_memory_gzip => array( + ), + self::cache_in_memory_serialized => array( + ), + self::cache_igbinary => array( + ), + self::cache_to_phpTemp => array( 'memoryCacheSize' => '1MB' + ), + self::cache_to_discISAM => array( 'dir' => NULL + ), + self::cache_to_apc => array( 'cacheTime' => 600 + ), + self::cache_to_memcache => array( 'memcacheServer' => 'localhost', + 'memcachePort' => 11211, + 'cacheTime' => 600 + ), + self::cache_to_wincache => array( 'cacheTime' => 600 + ), + self::cache_to_sqlite => array( + ), + self::cache_to_sqlite3 => array( + ), + ); + + + /** + * Arguments for the active cache storage method + * + * @var array of mixed array + */ + private static $_storageMethodParameters = array(); + + + /** + * Return the current cache storage method + * + * @return string|NULL + **/ + public static function getCacheStorageMethod() + { + return self::$_cacheStorageMethod; + } // function getCacheStorageMethod() + + + /** + * Return the current cache storage class + * + * @return PHPExcel_CachedObjectStorage_ICache|NULL + **/ + public static function getCacheStorageClass() + { + return self::$_cacheStorageClass; + } // function getCacheStorageClass() + + + /** + * Return the list of all possible cache storage methods + * + * @return string[] + **/ + public static function getAllCacheStorageMethods() + { + return self::$_storageMethods; + } // function getCacheStorageMethods() + + + /** + * Return the list of all available cache storage methods + * + * @return string[] + **/ + public static function getCacheStorageMethods() + { + $activeMethods = array(); + foreach(self::$_storageMethods as $storageMethod) { + $cacheStorageClass = 'PHPExcel_CachedObjectStorage_' . $storageMethod; + if (call_user_func(array($cacheStorageClass, 'cacheMethodIsAvailable'))) { + $activeMethods[] = $storageMethod; + } + } + return $activeMethods; + } // function getCacheStorageMethods() + + + /** + * Identify the cache storage method to use + * + * @param string $method Name of the method to use for cell cacheing + * @param array of mixed $arguments Additional arguments to pass to the cell caching class + * when instantiating + * @return boolean + **/ + public static function initialize($method = self::cache_in_memory, $arguments = array()) + { + if (!in_array($method,self::$_storageMethods)) { + return FALSE; + } + + $cacheStorageClass = 'PHPExcel_CachedObjectStorage_'.$method; + if (!call_user_func(array( $cacheStorageClass, + 'cacheMethodIsAvailable'))) { + return FALSE; + } + + self::$_storageMethodParameters[$method] = self::$_storageMethodDefaultParameters[$method]; + foreach($arguments as $k => $v) { + if (array_key_exists($k, self::$_storageMethodParameters[$method])) { + self::$_storageMethodParameters[$method][$k] = $v; + } + } + + if (self::$_cacheStorageMethod === NULL) { + self::$_cacheStorageClass = 'PHPExcel_CachedObjectStorage_' . $method; + self::$_cacheStorageMethod = $method; + } + return TRUE; + } // function initialize() + + + /** + * Initialise the cache storage + * + * @param PHPExcel_Worksheet $parent Enable cell caching for this worksheet + * @return PHPExcel_CachedObjectStorage_ICache + **/ + public static function getInstance(PHPExcel_Worksheet $parent) + { + $cacheMethodIsAvailable = TRUE; + if (self::$_cacheStorageMethod === NULL) { + $cacheMethodIsAvailable = self::initialize(); + } + + if ($cacheMethodIsAvailable) { + $instance = new self::$_cacheStorageClass( $parent, + self::$_storageMethodParameters[self::$_cacheStorageMethod] + ); + if ($instance !== NULL) { + return $instance; + } + } + + return FALSE; + } // function getInstance() + + + /** + * Clear the cache storage + * + **/ + public static function finalize() + { + self::$_cacheStorageMethod = NULL; + self::$_cacheStorageClass = NULL; + self::$_storageMethodParameters = array(); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CalcEngine/CyclicReferenceStack.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CalcEngine/CyclicReferenceStack.php new file mode 100755 index 0000000..cfc57c2 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CalcEngine/CyclicReferenceStack.php @@ -0,0 +1,98 @@ +_stack); + } + + /** + * Push a new entry onto the stack + * + * @param mixed $value + */ + public function push($value) { + $this->_stack[] = $value; + } // function push() + + /** + * Pop the last entry from the stack + * + * @return mixed + */ + public function pop() { + return array_pop($this->_stack); + } // function pop() + + /** + * Test to see if a specified entry exists on the stack + * + * @param mixed $value The value to test + */ + public function onStack($value) { + return in_array($value, $this->_stack); + } + + /** + * Clear the stack + */ + public function clear() { + $this->_stack = array(); + } // function push() + + /** + * Return an array of all entries on the stack + * + * @return mixed[] + */ + public function showStack() { + return $this->_stack; + } + +} // class PHPExcel_CalcEngine_CyclicReferenceStack diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CalcEngine/Logger.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CalcEngine/Logger.php new file mode 100755 index 0000000..1484767 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/CalcEngine/Logger.php @@ -0,0 +1,153 @@ +_cellStack = $stack; + } + + /** + * Enable/Disable Calculation engine logging + * + * @param boolean $pValue + */ + public function setWriteDebugLog($pValue = FALSE) { + $this->_writeDebugLog = $pValue; + } + + /** + * Return whether calculation engine logging is enabled or disabled + * + * @return boolean + */ + public function getWriteDebugLog() { + return $this->_writeDebugLog; + } + + /** + * Enable/Disable echoing of debug log information + * + * @param boolean $pValue + */ + public function setEchoDebugLog($pValue = FALSE) { + $this->_echoDebugLog = $pValue; + } + + /** + * Return whether echoing of debug log information is enabled or disabled + * + * @return boolean + */ + public function getEchoDebugLog() { + return $this->_echoDebugLog; + } + + /** + * Write an entry to the calculation engine debug log + */ + public function writeDebugLog() { + // Only write the debug log if logging is enabled + if ($this->_writeDebugLog) { + $message = implode(func_get_args()); + $cellReference = implode(' -> ', $this->_cellStack->showStack()); + if ($this->_echoDebugLog) { + echo $cellReference, + ($this->_cellStack->count() > 0 ? ' => ' : ''), + $message, + PHP_EOL; + } + $this->_debugLog[] = $cellReference . + ($this->_cellStack->count() > 0 ? ' => ' : '') . + $message; + } + } // function _writeDebug() + + /** + * Clear the calculation engine debug log + */ + public function clearLog() { + $this->_debugLog = array(); + } // function flushLogger() + + /** + * Return the calculation engine debug log + * + * @return string[] + */ + public function getLog() { + return $this->_debugLog; + } // function flushLogger() + +} // class PHPExcel_CalcEngine_Logger + diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation.php new file mode 100755 index 0000000..4345ee5 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation.php @@ -0,0 +1,3891 @@ +=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]{1,3})\$?(\d{1,7})'); + // Named Range of cells + define('CALCULATION_REGEXP_NAMEDRANGE','((([^\s,!&%^\/\*\+<>=-]*)|(\'[^\']*\')|(\"[^\"]*\"))!)?([_A-Z][_A-Z0-9\.]*)'); + } else { + // Cell reference (cell or range of cells, with or without a sheet reference) + define('CALCULATION_REGEXP_CELLREF','(((\w*)|(\'[^\']*\')|(\"[^\"]*\"))!)?\$?([a-z]{1,3})\$?(\d+)'); + // Named Range of cells + define('CALCULATION_REGEXP_NAMEDRANGE','(((\w*)|(\'.*\')|(\".*\"))!)?([_A-Z][_A-Z0-9\.]*)'); + } +} + + +/** + * PHPExcel_Calculation (Multiton) + * + * @category PHPExcel + * @package PHPExcel_Calculation + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Calculation { + + /** Constants */ + /** Regular Expressions */ + // Numeric operand + const CALCULATION_REGEXP_NUMBER = '[-+]?\d*\.?\d+(e[-+]?\d+)?'; + // String operand + const CALCULATION_REGEXP_STRING = '"(?:[^"]|"")*"'; + // Opening bracket + const CALCULATION_REGEXP_OPENBRACE = '\('; + // Function (allow for the old @ symbol that could be used to prefix a function, but we'll ignore it) + const CALCULATION_REGEXP_FUNCTION = '@?([A-Z][A-Z0-9\.]*)[\s]*\('; + // Cell reference (cell or range of cells, with or without a sheet reference) + const CALCULATION_REGEXP_CELLREF = CALCULATION_REGEXP_CELLREF; + // Named Range of cells + const CALCULATION_REGEXP_NAMEDRANGE = CALCULATION_REGEXP_NAMEDRANGE; + // Error + const CALCULATION_REGEXP_ERROR = '\#[A-Z][A-Z0_\/]*[!\?]?'; + + + /** constants */ + const RETURN_ARRAY_AS_ERROR = 'error'; + const RETURN_ARRAY_AS_VALUE = 'value'; + const RETURN_ARRAY_AS_ARRAY = 'array'; + + private static $returnArrayAsType = self::RETURN_ARRAY_AS_VALUE; + + + /** + * Instance of this class + * + * @access private + * @var PHPExcel_Calculation + */ + private static $_instance; + + + /** + * Instance of the workbook this Calculation Engine is using + * + * @access private + * @var PHPExcel + */ + private $_workbook; + + /** + * List of instances of the calculation engine that we've instantiated for individual workbooks + * + * @access private + * @var PHPExcel_Calculation[] + */ + private static $_workbookSets; + + /** + * Calculation cache + * + * @access private + * @var array + */ + private $_calculationCache = array (); + + + /** + * Calculation cache enabled + * + * @access private + * @var boolean + */ + private $_calculationCacheEnabled = TRUE; + + + /** + * List of operators that can be used within formulae + * The true/false value indicates whether it is a binary operator or a unary operator + * + * @access private + * @var array + */ + private static $_operators = array('+' => TRUE, '-' => TRUE, '*' => TRUE, '/' => TRUE, + '^' => TRUE, '&' => TRUE, '%' => FALSE, '~' => FALSE, + '>' => TRUE, '<' => TRUE, '=' => TRUE, '>=' => TRUE, + '<=' => TRUE, '<>' => TRUE, '|' => TRUE, ':' => TRUE + ); + + + /** + * List of binary operators (those that expect two operands) + * + * @access private + * @var array + */ + private static $_binaryOperators = array('+' => TRUE, '-' => TRUE, '*' => TRUE, '/' => TRUE, + '^' => TRUE, '&' => TRUE, '>' => TRUE, '<' => TRUE, + '=' => TRUE, '>=' => TRUE, '<=' => TRUE, '<>' => TRUE, + '|' => TRUE, ':' => TRUE + ); + + /** + * The debug log generated by the calculation engine + * + * @access private + * @var PHPExcel_CalcEngine_Logger + * + */ + private $debugLog; + + /** + * Flag to determine how formula errors should be handled + * If true, then a user error will be triggered + * If false, then an exception will be thrown + * + * @access public + * @var boolean + * + */ + public $suppressFormulaErrors = FALSE; + + /** + * Error message for any error that was raised/thrown by the calculation engine + * + * @access public + * @var string + * + */ + public $formulaError = NULL; + + /** + * An array of the nested cell references accessed by the calculation engine, used for the debug log + * + * @access private + * @var array of string + * + */ + private $_cyclicReferenceStack; + + /** + * Current iteration counter for cyclic formulae + * If the value is 0 (or less) then cyclic formulae will throw an exception, + * otherwise they will iterate to the limit defined here before returning a result + * + * @var integer + * + */ + private $_cyclicFormulaCount = 0; + + private $_cyclicFormulaCell = ''; + + /** + * Number of iterations for cyclic formulae + * + * @var integer + * + */ + public $cyclicFormulaCount = 0; + + /** + * Precision used for calculations + * + * @var integer + * + */ + private $_savedPrecision = 14; + + + /** + * The current locale setting + * + * @var string + * + */ + private static $_localeLanguage = 'en_us'; // US English (default locale) + + /** + * List of available locale settings + * Note that this is read for the locale subdirectory only when requested + * + * @var string[] + * + */ + private static $_validLocaleLanguages = array( 'en' // English (default language) + ); + /** + * Locale-specific argument separator for function arguments + * + * @var string + * + */ + private static $_localeArgumentSeparator = ','; + private static $_localeFunctions = array(); + + /** + * Locale-specific translations for Excel constants (True, False and Null) + * + * @var string[] + * + */ + public static $_localeBoolean = array( 'TRUE' => 'TRUE', + 'FALSE' => 'FALSE', + 'NULL' => 'NULL' + ); + + + /** + * Excel constant string translations to their PHP equivalents + * Constant conversion from text name/value to actual (datatyped) value + * + * @var string[] + * + */ + private static $_ExcelConstants = array('TRUE' => TRUE, + 'FALSE' => FALSE, + 'NULL' => NULL + ); + + // PHPExcel functions + private static $_PHPExcelFunctions = array( // PHPExcel functions + 'ABS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'abs', + 'argumentCount' => '1' + ), + 'ACCRINT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::ACCRINT', + 'argumentCount' => '4-7' + ), + 'ACCRINTM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::ACCRINTM', + 'argumentCount' => '3-5' + ), + 'ACOS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'acos', + 'argumentCount' => '1' + ), + 'ACOSH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'acosh', + 'argumentCount' => '1' + ), + 'ADDRESS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::CELL_ADDRESS', + 'argumentCount' => '2-5' + ), + 'AMORDEGRC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::AMORDEGRC', + 'argumentCount' => '6,7' + ), + 'AMORLINC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::AMORLINC', + 'argumentCount' => '6,7' + ), + 'AND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, + 'functionCall' => 'PHPExcel_Calculation_Logical::LOGICAL_AND', + 'argumentCount' => '1+' + ), + 'AREAS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '1' + ), + 'ASC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '1' + ), + 'ASIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'asin', + 'argumentCount' => '1' + ), + 'ASINH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'asinh', + 'argumentCount' => '1' + ), + 'ATAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'atan', + 'argumentCount' => '1' + ), + 'ATAN2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::ATAN2', + 'argumentCount' => '2' + ), + 'ATANH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'atanh', + 'argumentCount' => '1' + ), + 'AVEDEV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::AVEDEV', + 'argumentCount' => '1+' + ), + 'AVERAGE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::AVERAGE', + 'argumentCount' => '1+' + ), + 'AVERAGEA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::AVERAGEA', + 'argumentCount' => '1+' + ), + 'AVERAGEIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::AVERAGEIF', + 'argumentCount' => '2,3' + ), + 'AVERAGEIFS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '3+' + ), + 'BAHTTEXT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '1' + ), + 'BESSELI' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELI', + 'argumentCount' => '2' + ), + 'BESSELJ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELJ', + 'argumentCount' => '2' + ), + 'BESSELK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELK', + 'argumentCount' => '2' + ), + 'BESSELY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::BESSELY', + 'argumentCount' => '2' + ), + 'BETADIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::BETADIST', + 'argumentCount' => '3-5' + ), + 'BETAINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::BETAINV', + 'argumentCount' => '3-5' + ), + 'BIN2DEC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::BINTODEC', + 'argumentCount' => '1' + ), + 'BIN2HEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::BINTOHEX', + 'argumentCount' => '1,2' + ), + 'BIN2OCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::BINTOOCT', + 'argumentCount' => '1,2' + ), + 'BINOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::BINOMDIST', + 'argumentCount' => '4' + ), + 'CEILING' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::CEILING', + 'argumentCount' => '2' + ), + 'CELL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '1,2' + ), + 'CHAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::CHARACTER', + 'argumentCount' => '1' + ), + 'CHIDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::CHIDIST', + 'argumentCount' => '2' + ), + 'CHIINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::CHIINV', + 'argumentCount' => '2' + ), + 'CHITEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2' + ), + 'CHOOSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::CHOOSE', + 'argumentCount' => '2+' + ), + 'CLEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::TRIMNONPRINTABLE', + 'argumentCount' => '1' + ), + 'CODE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::ASCIICODE', + 'argumentCount' => '1' + ), + 'COLUMN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::COLUMN', + 'argumentCount' => '-1', + 'passByReference' => array(TRUE) + ), + 'COLUMNS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::COLUMNS', + 'argumentCount' => '1' + ), + 'COMBIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::COMBIN', + 'argumentCount' => '2' + ), + 'COMPLEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::COMPLEX', + 'argumentCount' => '2,3' + ), + 'CONCATENATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::CONCATENATE', + 'argumentCount' => '1+' + ), + 'CONFIDENCE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::CONFIDENCE', + 'argumentCount' => '3' + ), + 'CONVERT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::CONVERTUOM', + 'argumentCount' => '3' + ), + 'CORREL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::CORREL', + 'argumentCount' => '2' + ), + 'COS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'cos', + 'argumentCount' => '1' + ), + 'COSH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'cosh', + 'argumentCount' => '1' + ), + 'COUNT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::COUNT', + 'argumentCount' => '1+' + ), + 'COUNTA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::COUNTA', + 'argumentCount' => '1+' + ), + 'COUNTBLANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::COUNTBLANK', + 'argumentCount' => '1' + ), + 'COUNTIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::COUNTIF', + 'argumentCount' => '2' + ), + 'COUNTIFS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2' + ), + 'COUPDAYBS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPDAYBS', + 'argumentCount' => '3,4' + ), + 'COUPDAYS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPDAYS', + 'argumentCount' => '3,4' + ), + 'COUPDAYSNC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPDAYSNC', + 'argumentCount' => '3,4' + ), + 'COUPNCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPNCD', + 'argumentCount' => '3,4' + ), + 'COUPNUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPNUM', + 'argumentCount' => '3,4' + ), + 'COUPPCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::COUPPCD', + 'argumentCount' => '3,4' + ), + 'COVAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::COVAR', + 'argumentCount' => '2' + ), + 'CRITBINOM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::CRITBINOM', + 'argumentCount' => '3' + ), + 'CUBEKPIMEMBER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '?' + ), + 'CUBEMEMBER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '?' + ), + 'CUBEMEMBERPROPERTY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '?' + ), + 'CUBERANKEDMEMBER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '?' + ), + 'CUBESET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '?' + ), + 'CUBESETCOUNT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '?' + ), + 'CUBEVALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_CUBE, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '?' + ), + 'CUMIPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::CUMIPMT', + 'argumentCount' => '6' + ), + 'CUMPRINC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::CUMPRINC', + 'argumentCount' => '6' + ), + 'DATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::DATE', + 'argumentCount' => '3' + ), + 'DATEDIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::DATEDIF', + 'argumentCount' => '2,3' + ), + 'DATEVALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::DATEVALUE', + 'argumentCount' => '1' + ), + 'DAVERAGE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DAVERAGE', + 'argumentCount' => '3' + ), + 'DAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::DAYOFMONTH', + 'argumentCount' => '1' + ), + 'DAYS360' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::DAYS360', + 'argumentCount' => '2,3' + ), + 'DB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::DB', + 'argumentCount' => '4,5' + ), + 'DCOUNT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DCOUNT', + 'argumentCount' => '3' + ), + 'DCOUNTA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DCOUNTA', + 'argumentCount' => '3' + ), + 'DDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::DDB', + 'argumentCount' => '4,5' + ), + 'DEC2BIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::DECTOBIN', + 'argumentCount' => '1,2' + ), + 'DEC2HEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::DECTOHEX', + 'argumentCount' => '1,2' + ), + 'DEC2OCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::DECTOOCT', + 'argumentCount' => '1,2' + ), + 'DEGREES' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'rad2deg', + 'argumentCount' => '1' + ), + 'DELTA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::DELTA', + 'argumentCount' => '1,2' + ), + 'DEVSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::DEVSQ', + 'argumentCount' => '1+' + ), + 'DGET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DGET', + 'argumentCount' => '3' + ), + 'DISC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::DISC', + 'argumentCount' => '4,5' + ), + 'DMAX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DMAX', + 'argumentCount' => '3' + ), + 'DMIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DMIN', + 'argumentCount' => '3' + ), + 'DOLLAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::DOLLAR', + 'argumentCount' => '1,2' + ), + 'DOLLARDE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::DOLLARDE', + 'argumentCount' => '2' + ), + 'DOLLARFR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::DOLLARFR', + 'argumentCount' => '2' + ), + 'DPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DPRODUCT', + 'argumentCount' => '3' + ), + 'DSTDEV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DSTDEV', + 'argumentCount' => '3' + ), + 'DSTDEVP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DSTDEVP', + 'argumentCount' => '3' + ), + 'DSUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DSUM', + 'argumentCount' => '3' + ), + 'DURATION' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '5,6' + ), + 'DVAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DVAR', + 'argumentCount' => '3' + ), + 'DVARP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATABASE, + 'functionCall' => 'PHPExcel_Calculation_Database::DVARP', + 'argumentCount' => '3' + ), + 'EDATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::EDATE', + 'argumentCount' => '2' + ), + 'EFFECT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::EFFECT', + 'argumentCount' => '2' + ), + 'EOMONTH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::EOMONTH', + 'argumentCount' => '2' + ), + 'ERF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::ERF', + 'argumentCount' => '1,2' + ), + 'ERFC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::ERFC', + 'argumentCount' => '1' + ), + 'ERROR.TYPE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::ERROR_TYPE', + 'argumentCount' => '1' + ), + 'EVEN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::EVEN', + 'argumentCount' => '1' + ), + 'EXACT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2' + ), + 'EXP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'exp', + 'argumentCount' => '1' + ), + 'EXPONDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::EXPONDIST', + 'argumentCount' => '3' + ), + 'FACT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::FACT', + 'argumentCount' => '1' + ), + 'FACTDOUBLE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::FACTDOUBLE', + 'argumentCount' => '1' + ), + 'FALSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, + 'functionCall' => 'PHPExcel_Calculation_Logical::FALSE', + 'argumentCount' => '0' + ), + 'FDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '3' + ), + 'FIND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHSENSITIVE', + 'argumentCount' => '2,3' + ), + 'FINDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHSENSITIVE', + 'argumentCount' => '2,3' + ), + 'FINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '3' + ), + 'FISHER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::FISHER', + 'argumentCount' => '1' + ), + 'FISHERINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::FISHERINV', + 'argumentCount' => '1' + ), + 'FIXED' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::FIXEDFORMAT', + 'argumentCount' => '1-3' + ), + 'FLOOR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::FLOOR', + 'argumentCount' => '2' + ), + 'FORECAST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::FORECAST', + 'argumentCount' => '3' + ), + 'FREQUENCY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2' + ), + 'FTEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2' + ), + 'FV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::FV', + 'argumentCount' => '3-5' + ), + 'FVSCHEDULE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::FVSCHEDULE', + 'argumentCount' => '2' + ), + 'GAMMADIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::GAMMADIST', + 'argumentCount' => '4' + ), + 'GAMMAINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::GAMMAINV', + 'argumentCount' => '3' + ), + 'GAMMALN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::GAMMALN', + 'argumentCount' => '1' + ), + 'GCD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::GCD', + 'argumentCount' => '1+' + ), + 'GEOMEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::GEOMEAN', + 'argumentCount' => '1+' + ), + 'GESTEP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::GESTEP', + 'argumentCount' => '1,2' + ), + 'GETPIVOTDATA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2+' + ), + 'GROWTH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::GROWTH', + 'argumentCount' => '1-4' + ), + 'HARMEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::HARMEAN', + 'argumentCount' => '1+' + ), + 'HEX2BIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::HEXTOBIN', + 'argumentCount' => '1,2' + ), + 'HEX2DEC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::HEXTODEC', + 'argumentCount' => '1' + ), + 'HEX2OCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::HEXTOOCT', + 'argumentCount' => '1,2' + ), + 'HLOOKUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '3,4' + ), + 'HOUR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::HOUROFDAY', + 'argumentCount' => '1' + ), + 'HYPERLINK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::HYPERLINK', + 'argumentCount' => '1,2', + 'passCellReference'=> TRUE + ), + 'HYPGEOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::HYPGEOMDIST', + 'argumentCount' => '4' + ), + 'IF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, + 'functionCall' => 'PHPExcel_Calculation_Logical::STATEMENT_IF', + 'argumentCount' => '1-3' + ), + 'IFERROR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, + 'functionCall' => 'PHPExcel_Calculation_Logical::IFERROR', + 'argumentCount' => '2' + ), + 'IMABS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMABS', + 'argumentCount' => '1' + ), + 'IMAGINARY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMAGINARY', + 'argumentCount' => '1' + ), + 'IMARGUMENT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMARGUMENT', + 'argumentCount' => '1' + ), + 'IMCONJUGATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMCONJUGATE', + 'argumentCount' => '1' + ), + 'IMCOS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMCOS', + 'argumentCount' => '1' + ), + 'IMDIV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMDIV', + 'argumentCount' => '2' + ), + 'IMEXP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMEXP', + 'argumentCount' => '1' + ), + 'IMLN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMLN', + 'argumentCount' => '1' + ), + 'IMLOG10' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMLOG10', + 'argumentCount' => '1' + ), + 'IMLOG2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMLOG2', + 'argumentCount' => '1' + ), + 'IMPOWER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMPOWER', + 'argumentCount' => '2' + ), + 'IMPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMPRODUCT', + 'argumentCount' => '1+' + ), + 'IMREAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMREAL', + 'argumentCount' => '1' + ), + 'IMSIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMSIN', + 'argumentCount' => '1' + ), + 'IMSQRT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMSQRT', + 'argumentCount' => '1' + ), + 'IMSUB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMSUB', + 'argumentCount' => '2' + ), + 'IMSUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::IMSUM', + 'argumentCount' => '1+' + ), + 'INDEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::INDEX', + 'argumentCount' => '1-4' + ), + 'INDIRECT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::INDIRECT', + 'argumentCount' => '1,2', + 'passCellReference'=> TRUE + ), + 'INFO' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '1' + ), + 'INT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::INT', + 'argumentCount' => '1' + ), + 'INTERCEPT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::INTERCEPT', + 'argumentCount' => '2' + ), + 'INTRATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::INTRATE', + 'argumentCount' => '4,5' + ), + 'IPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::IPMT', + 'argumentCount' => '4-6' + ), + 'IRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::IRR', + 'argumentCount' => '1,2' + ), + 'ISBLANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::IS_BLANK', + 'argumentCount' => '1' + ), + 'ISERR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::IS_ERR', + 'argumentCount' => '1' + ), + 'ISERROR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::IS_ERROR', + 'argumentCount' => '1' + ), + 'ISEVEN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::IS_EVEN', + 'argumentCount' => '1' + ), + 'ISLOGICAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::IS_LOGICAL', + 'argumentCount' => '1' + ), + 'ISNA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::IS_NA', + 'argumentCount' => '1' + ), + 'ISNONTEXT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::IS_NONTEXT', + 'argumentCount' => '1' + ), + 'ISNUMBER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::IS_NUMBER', + 'argumentCount' => '1' + ), + 'ISODD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::IS_ODD', + 'argumentCount' => '1' + ), + 'ISPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::ISPMT', + 'argumentCount' => '4' + ), + 'ISREF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '1' + ), + 'ISTEXT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::IS_TEXT', + 'argumentCount' => '1' + ), + 'JIS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '1' + ), + 'KURT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::KURT', + 'argumentCount' => '1+' + ), + 'LARGE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::LARGE', + 'argumentCount' => '2' + ), + 'LCM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::LCM', + 'argumentCount' => '1+' + ), + 'LEFT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::LEFT', + 'argumentCount' => '1,2' + ), + 'LEFTB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::LEFT', + 'argumentCount' => '1,2' + ), + 'LEN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::STRINGLENGTH', + 'argumentCount' => '1' + ), + 'LENB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::STRINGLENGTH', + 'argumentCount' => '1' + ), + 'LINEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::LINEST', + 'argumentCount' => '1-4' + ), + 'LN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'log', + 'argumentCount' => '1' + ), + 'LOG' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::LOG_BASE', + 'argumentCount' => '1,2' + ), + 'LOG10' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'log10', + 'argumentCount' => '1' + ), + 'LOGEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::LOGEST', + 'argumentCount' => '1-4' + ), + 'LOGINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::LOGINV', + 'argumentCount' => '3' + ), + 'LOGNORMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::LOGNORMDIST', + 'argumentCount' => '3' + ), + 'LOOKUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::LOOKUP', + 'argumentCount' => '2,3' + ), + 'LOWER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::LOWERCASE', + 'argumentCount' => '1' + ), + 'MATCH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::MATCH', + 'argumentCount' => '2,3' + ), + 'MAX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::MAX', + 'argumentCount' => '1+' + ), + 'MAXA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::MAXA', + 'argumentCount' => '1+' + ), + 'MAXIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::MAXIF', + 'argumentCount' => '2+' + ), + 'MDETERM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MDETERM', + 'argumentCount' => '1' + ), + 'MDURATION' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '5,6' + ), + 'MEDIAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::MEDIAN', + 'argumentCount' => '1+' + ), + 'MEDIANIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2+' + ), + 'MID' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::MID', + 'argumentCount' => '3' + ), + 'MIDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::MID', + 'argumentCount' => '3' + ), + 'MIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::MIN', + 'argumentCount' => '1+' + ), + 'MINA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::MINA', + 'argumentCount' => '1+' + ), + 'MINIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::MINIF', + 'argumentCount' => '2+' + ), + 'MINUTE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::MINUTEOFHOUR', + 'argumentCount' => '1' + ), + 'MINVERSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MINVERSE', + 'argumentCount' => '1' + ), + 'MIRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::MIRR', + 'argumentCount' => '3' + ), + 'MMULT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MMULT', + 'argumentCount' => '2' + ), + 'MOD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MOD', + 'argumentCount' => '2' + ), + 'MODE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::MODE', + 'argumentCount' => '1+' + ), + 'MONTH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::MONTHOFYEAR', + 'argumentCount' => '1' + ), + 'MROUND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MROUND', + 'argumentCount' => '2' + ), + 'MULTINOMIAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::MULTINOMIAL', + 'argumentCount' => '1+' + ), + 'N' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::N', + 'argumentCount' => '1' + ), + 'NA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::NA', + 'argumentCount' => '0' + ), + 'NEGBINOMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::NEGBINOMDIST', + 'argumentCount' => '3' + ), + 'NETWORKDAYS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::NETWORKDAYS', + 'argumentCount' => '2+' + ), + 'NOMINAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::NOMINAL', + 'argumentCount' => '2' + ), + 'NORMDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::NORMDIST', + 'argumentCount' => '4' + ), + 'NORMINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::NORMINV', + 'argumentCount' => '3' + ), + 'NORMSDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::NORMSDIST', + 'argumentCount' => '1' + ), + 'NORMSINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::NORMSINV', + 'argumentCount' => '1' + ), + 'NOT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, + 'functionCall' => 'PHPExcel_Calculation_Logical::NOT', + 'argumentCount' => '1' + ), + 'NOW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::DATETIMENOW', + 'argumentCount' => '0' + ), + 'NPER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::NPER', + 'argumentCount' => '3-5' + ), + 'NPV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::NPV', + 'argumentCount' => '2+' + ), + 'OCT2BIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::OCTTOBIN', + 'argumentCount' => '1,2' + ), + 'OCT2DEC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::OCTTODEC', + 'argumentCount' => '1' + ), + 'OCT2HEX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_ENGINEERING, + 'functionCall' => 'PHPExcel_Calculation_Engineering::OCTTOHEX', + 'argumentCount' => '1,2' + ), + 'ODD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::ODD', + 'argumentCount' => '1' + ), + 'ODDFPRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '8,9' + ), + 'ODDFYIELD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '8,9' + ), + 'ODDLPRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '7,8' + ), + 'ODDLYIELD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '7,8' + ), + 'OFFSET' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::OFFSET', + 'argumentCount' => '3,5', + 'passCellReference'=> TRUE, + 'passByReference' => array(TRUE) + ), + 'OR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, + 'functionCall' => 'PHPExcel_Calculation_Logical::LOGICAL_OR', + 'argumentCount' => '1+' + ), + 'PEARSON' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::CORREL', + 'argumentCount' => '2' + ), + 'PERCENTILE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::PERCENTILE', + 'argumentCount' => '2' + ), + 'PERCENTRANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::PERCENTRANK', + 'argumentCount' => '2,3' + ), + 'PERMUT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::PERMUT', + 'argumentCount' => '2' + ), + 'PHONETIC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '1' + ), + 'PI' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'pi', + 'argumentCount' => '0' + ), + 'PMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::PMT', + 'argumentCount' => '3-5' + ), + 'POISSON' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::POISSON', + 'argumentCount' => '3' + ), + 'POWER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::POWER', + 'argumentCount' => '2' + ), + 'PPMT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::PPMT', + 'argumentCount' => '4-6' + ), + 'PRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::PRICE', + 'argumentCount' => '6,7' + ), + 'PRICEDISC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::PRICEDISC', + 'argumentCount' => '4,5' + ), + 'PRICEMAT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::PRICEMAT', + 'argumentCount' => '5,6' + ), + 'PROB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '3,4' + ), + 'PRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::PRODUCT', + 'argumentCount' => '1+' + ), + 'PROPER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::PROPERCASE', + 'argumentCount' => '1' + ), + 'PV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::PV', + 'argumentCount' => '3-5' + ), + 'QUARTILE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::QUARTILE', + 'argumentCount' => '2' + ), + 'QUOTIENT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::QUOTIENT', + 'argumentCount' => '2' + ), + 'RADIANS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'deg2rad', + 'argumentCount' => '1' + ), + 'RAND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::RAND', + 'argumentCount' => '0' + ), + 'RANDBETWEEN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::RAND', + 'argumentCount' => '2' + ), + 'RANK' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::RANK', + 'argumentCount' => '2,3' + ), + 'RATE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::RATE', + 'argumentCount' => '3-6' + ), + 'RECEIVED' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::RECEIVED', + 'argumentCount' => '4-5' + ), + 'REPLACE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::REPLACE', + 'argumentCount' => '4' + ), + 'REPLACEB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::REPLACE', + 'argumentCount' => '4' + ), + 'REPT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'str_repeat', + 'argumentCount' => '2' + ), + 'RIGHT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::RIGHT', + 'argumentCount' => '1,2' + ), + 'RIGHTB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::RIGHT', + 'argumentCount' => '1,2' + ), + 'ROMAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::ROMAN', + 'argumentCount' => '1,2' + ), + 'ROUND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'round', + 'argumentCount' => '2' + ), + 'ROUNDDOWN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::ROUNDDOWN', + 'argumentCount' => '2' + ), + 'ROUNDUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::ROUNDUP', + 'argumentCount' => '2' + ), + 'ROW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::ROW', + 'argumentCount' => '-1', + 'passByReference' => array(TRUE) + ), + 'ROWS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::ROWS', + 'argumentCount' => '1' + ), + 'RSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::RSQ', + 'argumentCount' => '2' + ), + 'RTD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '1+' + ), + 'SEARCH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHINSENSITIVE', + 'argumentCount' => '2,3' + ), + 'SEARCHB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::SEARCHINSENSITIVE', + 'argumentCount' => '2,3' + ), + 'SECOND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::SECONDOFMINUTE', + 'argumentCount' => '1' + ), + 'SERIESSUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SERIESSUM', + 'argumentCount' => '4' + ), + 'SIGN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SIGN', + 'argumentCount' => '1' + ), + 'SIN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'sin', + 'argumentCount' => '1' + ), + 'SINH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'sinh', + 'argumentCount' => '1' + ), + 'SKEW' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::SKEW', + 'argumentCount' => '1+' + ), + 'SLN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::SLN', + 'argumentCount' => '3' + ), + 'SLOPE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::SLOPE', + 'argumentCount' => '2' + ), + 'SMALL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::SMALL', + 'argumentCount' => '2' + ), + 'SQRT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'sqrt', + 'argumentCount' => '1' + ), + 'SQRTPI' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SQRTPI', + 'argumentCount' => '1' + ), + 'STANDARDIZE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::STANDARDIZE', + 'argumentCount' => '3' + ), + 'STDEV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::STDEV', + 'argumentCount' => '1+' + ), + 'STDEVA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::STDEVA', + 'argumentCount' => '1+' + ), + 'STDEVP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::STDEVP', + 'argumentCount' => '1+' + ), + 'STDEVPA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::STDEVPA', + 'argumentCount' => '1+' + ), + 'STEYX' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::STEYX', + 'argumentCount' => '2' + ), + 'SUBSTITUTE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::SUBSTITUTE', + 'argumentCount' => '3,4' + ), + 'SUBTOTAL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUBTOTAL', + 'argumentCount' => '2+' + ), + 'SUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUM', + 'argumentCount' => '1+' + ), + 'SUMIF' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMIF', + 'argumentCount' => '2,3' + ), + 'SUMIFS' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '?' + ), + 'SUMPRODUCT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMPRODUCT', + 'argumentCount' => '1+' + ), + 'SUMSQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMSQ', + 'argumentCount' => '1+' + ), + 'SUMX2MY2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMX2MY2', + 'argumentCount' => '2' + ), + 'SUMX2PY2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMX2PY2', + 'argumentCount' => '2' + ), + 'SUMXMY2' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::SUMXMY2', + 'argumentCount' => '2' + ), + 'SYD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::SYD', + 'argumentCount' => '4' + ), + 'T' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::RETURNSTRING', + 'argumentCount' => '1' + ), + 'TAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'tan', + 'argumentCount' => '1' + ), + 'TANH' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'tanh', + 'argumentCount' => '1' + ), + 'TBILLEQ' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::TBILLEQ', + 'argumentCount' => '3' + ), + 'TBILLPRICE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::TBILLPRICE', + 'argumentCount' => '3' + ), + 'TBILLYIELD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::TBILLYIELD', + 'argumentCount' => '3' + ), + 'TDIST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::TDIST', + 'argumentCount' => '3' + ), + 'TEXT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::TEXTFORMAT', + 'argumentCount' => '2' + ), + 'TIME' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::TIME', + 'argumentCount' => '3' + ), + 'TIMEVALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::TIMEVALUE', + 'argumentCount' => '1' + ), + 'TINV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::TINV', + 'argumentCount' => '2' + ), + 'TODAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::DATENOW', + 'argumentCount' => '0' + ), + 'TRANSPOSE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::TRANSPOSE', + 'argumentCount' => '1' + ), + 'TREND' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::TREND', + 'argumentCount' => '1-4' + ), + 'TRIM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::TRIMSPACES', + 'argumentCount' => '1' + ), + 'TRIMMEAN' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::TRIMMEAN', + 'argumentCount' => '2' + ), + 'TRUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOGICAL, + 'functionCall' => 'PHPExcel_Calculation_Logical::TRUE', + 'argumentCount' => '0' + ), + 'TRUNC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_MATH_AND_TRIG, + 'functionCall' => 'PHPExcel_Calculation_MathTrig::TRUNC', + 'argumentCount' => '1,2' + ), + 'TTEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '4' + ), + 'TYPE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::TYPE', + 'argumentCount' => '1' + ), + 'UPPER' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_TextData::UPPERCASE', + 'argumentCount' => '1' + ), + 'USDOLLAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '2' + ), + 'VALUE' => array('category' => PHPExcel_Calculation_Function::CATEGORY_TEXT_AND_DATA, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '1' + ), + 'VAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::VARFunc', + 'argumentCount' => '1+' + ), + 'VARA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::VARA', + 'argumentCount' => '1+' + ), + 'VARP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::VARP', + 'argumentCount' => '1+' + ), + 'VARPA' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::VARPA', + 'argumentCount' => '1+' + ), + 'VDB' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '5-7' + ), + 'VERSION' => array('category' => PHPExcel_Calculation_Function::CATEGORY_INFORMATION, + 'functionCall' => 'PHPExcel_Calculation_Functions::VERSION', + 'argumentCount' => '0' + ), + 'VLOOKUP' => array('category' => PHPExcel_Calculation_Function::CATEGORY_LOOKUP_AND_REFERENCE, + 'functionCall' => 'PHPExcel_Calculation_LookupRef::VLOOKUP', + 'argumentCount' => '3,4' + ), + 'WEEKDAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::DAYOFWEEK', + 'argumentCount' => '1,2' + ), + 'WEEKNUM' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::WEEKOFYEAR', + 'argumentCount' => '1,2' + ), + 'WEIBULL' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::WEIBULL', + 'argumentCount' => '4' + ), + 'WORKDAY' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::WORKDAY', + 'argumentCount' => '2+' + ), + 'XIRR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::XIRR', + 'argumentCount' => '2,3' + ), + 'XNPV' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::XNPV', + 'argumentCount' => '3' + ), + 'YEAR' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::YEAR', + 'argumentCount' => '1' + ), + 'YEARFRAC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_DATE_AND_TIME, + 'functionCall' => 'PHPExcel_Calculation_DateTime::YEARFRAC', + 'argumentCount' => '2,3' + ), + 'YIELD' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Functions::DUMMY', + 'argumentCount' => '6,7' + ), + 'YIELDDISC' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::YIELDDISC', + 'argumentCount' => '4,5' + ), + 'YIELDMAT' => array('category' => PHPExcel_Calculation_Function::CATEGORY_FINANCIAL, + 'functionCall' => 'PHPExcel_Calculation_Financial::YIELDMAT', + 'argumentCount' => '5,6' + ), + 'ZTEST' => array('category' => PHPExcel_Calculation_Function::CATEGORY_STATISTICAL, + 'functionCall' => 'PHPExcel_Calculation_Statistical::ZTEST', + 'argumentCount' => '2-3' + ) + ); + + + // Internal functions used for special control purposes + private static $_controlFunctions = array( + 'MKMATRIX' => array('argumentCount' => '*', + 'functionCall' => 'self::_mkMatrix' + ) + ); + + + + + private function __construct(PHPExcel $workbook = NULL) { + $setPrecision = (PHP_INT_SIZE == 4) ? 14 : 16; + $this->_savedPrecision = ini_get('precision'); + if ($this->_savedPrecision < $setPrecision) { + ini_set('precision',$setPrecision); + } + + if ($workbook !== NULL) { + self::$_workbookSets[$workbook->getID()] = $this; + } + + $this->_workbook = $workbook; + $this->_cyclicReferenceStack = new PHPExcel_CalcEngine_CyclicReferenceStack(); + $this->_debugLog = new PHPExcel_CalcEngine_Logger($this->_cyclicReferenceStack); + } // function __construct() + + + public function __destruct() { + if ($this->_savedPrecision != ini_get('precision')) { + ini_set('precision',$this->_savedPrecision); + } + } + + private static function _loadLocales() { + $localeFileDirectory = PHPEXCEL_ROOT.'PHPExcel/locale/'; + foreach (glob($localeFileDirectory.'/*',GLOB_ONLYDIR) as $filename) { + $filename = substr($filename,strlen($localeFileDirectory)+1); + if ($filename != 'en') { + self::$_validLocaleLanguages[] = $filename; + } + } + } + + /** + * Get an instance of this class + * + * @access public + * @param PHPExcel $workbook Injected workbook for working with a PHPExcel object, + * or NULL to create a standalone claculation engine + * @return PHPExcel_Calculation + */ + public static function getInstance(PHPExcel $workbook = NULL) { + if ($workbook !== NULL) { + if (isset(self::$_workbookSets[$workbook->getID()])) { + return self::$_workbookSets[$workbook->getID()]; + } + return new PHPExcel_Calculation($workbook); + } + + if (!isset(self::$_instance) || (self::$_instance === NULL)) { + self::$_instance = new PHPExcel_Calculation(); + } + + return self::$_instance; + } // function getInstance() + + /** + * Unset an instance of this class + * + * @access public + * @param PHPExcel $workbook Injected workbook identifying the instance to unset + */ + public static function unsetInstance(PHPExcel $workbook = NULL) { + if ($workbook !== NULL) { + if (isset(self::$_workbookSets[$workbook->getID()])) { + unset(self::$_workbookSets[$workbook->getID()]); + } + } + } + + /** + * Flush the calculation cache for any existing instance of this class + * but only if a PHPExcel_Calculation instance exists + * + * @access public + * @return null + */ + public function flushInstance() { + $this->clearCalculationCache(); + } // function flushInstance() + + + /** + * Get the debuglog for this claculation engine instance + * + * @access public + * @return PHPExcel_CalcEngine_Logger + */ + public function getDebugLog() { + return $this->_debugLog; + } + + /** + * __clone implementation. Cloning should not be allowed in a Singleton! + * + * @access public + * @throws PHPExcel_Calculation_Exception + */ + public final function __clone() { + throw new PHPExcel_Calculation_Exception ('Cloning the calculation engine is not allowed!'); + } // function __clone() + + + /** + * Return the locale-specific translation of TRUE + * + * @access public + * @return string locale-specific translation of TRUE + */ + public static function getTRUE() { + return self::$_localeBoolean['TRUE']; + } + + /** + * Return the locale-specific translation of FALSE + * + * @access public + * @return string locale-specific translation of FALSE + */ + public static function getFALSE() { + return self::$_localeBoolean['FALSE']; + } + + /** + * Set the Array Return Type (Array or Value of first element in the array) + * + * @access public + * @param string $returnType Array return type + * @return boolean Success or failure + */ + public static function setArrayReturnType($returnType) { + if (($returnType == self::RETURN_ARRAY_AS_VALUE) || + ($returnType == self::RETURN_ARRAY_AS_ERROR) || + ($returnType == self::RETURN_ARRAY_AS_ARRAY)) { + self::$returnArrayAsType = $returnType; + return TRUE; + } + return FALSE; + } // function setArrayReturnType() + + + /** + * Return the Array Return Type (Array or Value of first element in the array) + * + * @access public + * @return string $returnType Array return type + */ + public static function getArrayReturnType() { + return self::$returnArrayAsType; + } // function getArrayReturnType() + + + /** + * Is calculation caching enabled? + * + * @access public + * @return boolean + */ + public function getCalculationCacheEnabled() { + return $this->_calculationCacheEnabled; + } // function getCalculationCacheEnabled() + + /** + * Enable/disable calculation cache + * + * @access public + * @param boolean $pValue + */ + public function setCalculationCacheEnabled($pValue = TRUE) { + $this->_calculationCacheEnabled = $pValue; + $this->clearCalculationCache(); + } // function setCalculationCacheEnabled() + + + /** + * Enable calculation cache + */ + public function enableCalculationCache() { + $this->setCalculationCacheEnabled(TRUE); + } // function enableCalculationCache() + + + /** + * Disable calculation cache + */ + public function disableCalculationCache() { + $this->setCalculationCacheEnabled(FALSE); + } // function disableCalculationCache() + + + /** + * Clear calculation cache + */ + public function clearCalculationCache() { + $this->_calculationCache = array(); + } // function clearCalculationCache() + + /** + * Clear calculation cache for a specified worksheet + * + * @param string $worksheetName + */ + public function clearCalculationCacheForWorksheet($worksheetName) { + if (isset($this->_calculationCache[$worksheetName])) { + unset($this->_calculationCache[$worksheetName]); + } + } // function clearCalculationCacheForWorksheet() + + /** + * Rename calculation cache for a specified worksheet + * + * @param string $fromWorksheetName + * @param string $toWorksheetName + */ + public function renameCalculationCacheForWorksheet($fromWorksheetName, $toWorksheetName) { + if (isset($this->_calculationCache[$fromWorksheetName])) { + $this->_calculationCache[$toWorksheetName] = &$this->_calculationCache[$fromWorksheetName]; + unset($this->_calculationCache[$fromWorksheetName]); + } + } // function renameCalculationCacheForWorksheet() + + + /** + * Get the currently defined locale code + * + * @return string + */ + public function getLocale() { + return self::$_localeLanguage; + } // function getLocale() + + + /** + * Set the locale code + * + * @param string $locale The locale to use for formula translation + * @return boolean + */ + public function setLocale($locale = 'en_us') { + // Identify our locale and language + $language = $locale = strtolower($locale); + if (strpos($locale,'_') !== FALSE) { + list($language) = explode('_',$locale); + } + + if (count(self::$_validLocaleLanguages) == 1) + self::_loadLocales(); + + // Test whether we have any language data for this language (any locale) + if (in_array($language,self::$_validLocaleLanguages)) { + // initialise language/locale settings + self::$_localeFunctions = array(); + self::$_localeArgumentSeparator = ','; + self::$_localeBoolean = array('TRUE' => 'TRUE', 'FALSE' => 'FALSE', 'NULL' => 'NULL'); + // Default is English, if user isn't requesting english, then read the necessary data from the locale files + if ($locale != 'en_us') { + // Search for a file with a list of function names for locale + $functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.str_replace('_',DIRECTORY_SEPARATOR,$locale).DIRECTORY_SEPARATOR.'functions'; + if (!file_exists($functionNamesFile)) { + // If there isn't a locale specific function file, look for a language specific function file + $functionNamesFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.'functions'; + if (!file_exists($functionNamesFile)) { + return FALSE; + } + } + // Retrieve the list of locale or language specific function names + $localeFunctions = file($functionNamesFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + foreach ($localeFunctions as $localeFunction) { + list($localeFunction) = explode('##',$localeFunction); // Strip out comments + if (strpos($localeFunction,'=') !== FALSE) { + list($fName,$lfName) = explode('=',$localeFunction); + $fName = trim($fName); + $lfName = trim($lfName); + if ((isset(self::$_PHPExcelFunctions[$fName])) && ($lfName != '') && ($fName != $lfName)) { + self::$_localeFunctions[$fName] = $lfName; + } + } + } + // Default the TRUE and FALSE constants to the locale names of the TRUE() and FALSE() functions + if (isset(self::$_localeFunctions['TRUE'])) { self::$_localeBoolean['TRUE'] = self::$_localeFunctions['TRUE']; } + if (isset(self::$_localeFunctions['FALSE'])) { self::$_localeBoolean['FALSE'] = self::$_localeFunctions['FALSE']; } + + $configFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.str_replace('_',DIRECTORY_SEPARATOR,$locale).DIRECTORY_SEPARATOR.'config'; + if (!file_exists($configFile)) { + $configFile = PHPEXCEL_ROOT . 'PHPExcel'.DIRECTORY_SEPARATOR.'locale'.DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.'config'; + } + if (file_exists($configFile)) { + $localeSettings = file($configFile,FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + foreach ($localeSettings as $localeSetting) { + list($localeSetting) = explode('##',$localeSetting); // Strip out comments + if (strpos($localeSetting,'=') !== FALSE) { + list($settingName,$settingValue) = explode('=',$localeSetting); + $settingName = strtoupper(trim($settingName)); + switch ($settingName) { + case 'ARGUMENTSEPARATOR' : + self::$_localeArgumentSeparator = trim($settingValue); + break; + } + } + } + } + } + + self::$functionReplaceFromExcel = self::$functionReplaceToExcel = + self::$functionReplaceFromLocale = self::$functionReplaceToLocale = NULL; + self::$_localeLanguage = $locale; + return TRUE; + } + return FALSE; + } // function setLocale() + + + + public static function _translateSeparator($fromSeparator,$toSeparator,$formula,&$inBraces) { + $strlen = mb_strlen($formula); + for ($i = 0; $i < $strlen; ++$i) { + $chr = mb_substr($formula,$i,1); + switch ($chr) { + case '{' : $inBraces = TRUE; + break; + case '}' : $inBraces = FALSE; + break; + case $fromSeparator : + if (!$inBraces) { + $formula = mb_substr($formula,0,$i).$toSeparator.mb_substr($formula,$i+1); + } + } + } + return $formula; + } + + private static function _translateFormula($from,$to,$formula,$fromSeparator,$toSeparator) { + // Convert any Excel function names to the required language + if (self::$_localeLanguage !== 'en_us') { + $inBraces = FALSE; + // If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators + if (strpos($formula,'"') !== FALSE) { + // So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded + // the formula + $temp = explode('"',$formula); + $i = FALSE; + foreach($temp as &$value) { + // Only count/replace in alternating array entries + if ($i = !$i) { + $value = preg_replace($from,$to,$value); + $value = self::_translateSeparator($fromSeparator,$toSeparator,$value,$inBraces); + } + } + unset($value); + // Then rebuild the formula string + $formula = implode('"',$temp); + } else { + // If there's no quoted strings, then we do a simple count/replace + $formula = preg_replace($from,$to,$formula); + $formula = self::_translateSeparator($fromSeparator,$toSeparator,$formula,$inBraces); + } + } + + return $formula; + } + + private static $functionReplaceFromExcel = NULL; + private static $functionReplaceToLocale = NULL; + + public function _translateFormulaToLocale($formula) { + if (self::$functionReplaceFromExcel === NULL) { + self::$functionReplaceFromExcel = array(); + foreach(array_keys(self::$_localeFunctions) as $excelFunctionName) { + self::$functionReplaceFromExcel[] = '/(@?[^\w\.])'.preg_quote($excelFunctionName).'([\s]*\()/Ui'; + } + foreach(array_keys(self::$_localeBoolean) as $excelBoolean) { + self::$functionReplaceFromExcel[] = '/(@?[^\w\.])'.preg_quote($excelBoolean).'([^\w\.])/Ui'; + } + + } + + if (self::$functionReplaceToLocale === NULL) { + self::$functionReplaceToLocale = array(); + foreach(array_values(self::$_localeFunctions) as $localeFunctionName) { + self::$functionReplaceToLocale[] = '$1'.trim($localeFunctionName).'$2'; + } + foreach(array_values(self::$_localeBoolean) as $localeBoolean) { + self::$functionReplaceToLocale[] = '$1'.trim($localeBoolean).'$2'; + } + } + + return self::_translateFormula(self::$functionReplaceFromExcel,self::$functionReplaceToLocale,$formula,',',self::$_localeArgumentSeparator); + } // function _translateFormulaToLocale() + + + private static $functionReplaceFromLocale = NULL; + private static $functionReplaceToExcel = NULL; + + public function _translateFormulaToEnglish($formula) { + if (self::$functionReplaceFromLocale === NULL) { + self::$functionReplaceFromLocale = array(); + foreach(array_values(self::$_localeFunctions) as $localeFunctionName) { + self::$functionReplaceFromLocale[] = '/(@?[^\w\.])'.preg_quote($localeFunctionName).'([\s]*\()/Ui'; + } + foreach(array_values(self::$_localeBoolean) as $excelBoolean) { + self::$functionReplaceFromLocale[] = '/(@?[^\w\.])'.preg_quote($excelBoolean).'([^\w\.])/Ui'; + } + } + + if (self::$functionReplaceToExcel === NULL) { + self::$functionReplaceToExcel = array(); + foreach(array_keys(self::$_localeFunctions) as $excelFunctionName) { + self::$functionReplaceToExcel[] = '$1'.trim($excelFunctionName).'$2'; + } + foreach(array_keys(self::$_localeBoolean) as $excelBoolean) { + self::$functionReplaceToExcel[] = '$1'.trim($excelBoolean).'$2'; + } + } + + return self::_translateFormula(self::$functionReplaceFromLocale,self::$functionReplaceToExcel,$formula,self::$_localeArgumentSeparator,','); + } // function _translateFormulaToEnglish() + + + public static function _localeFunc($function) { + if (self::$_localeLanguage !== 'en_us') { + $functionName = trim($function,'('); + if (isset(self::$_localeFunctions[$functionName])) { + $brace = ($functionName != $function); + $function = self::$_localeFunctions[$functionName]; + if ($brace) { $function .= '('; } + } + } + return $function; + } + + + + + /** + * Wrap string values in quotes + * + * @param mixed $value + * @return mixed + */ + public static function _wrapResult($value) { + if (is_string($value)) { + // Error values cannot be "wrapped" + if (preg_match('/^'.self::CALCULATION_REGEXP_ERROR.'$/i', $value, $match)) { + // Return Excel errors "as is" + return $value; + } + // Return strings wrapped in quotes + return '"'.$value.'"'; + // Convert numeric errors to NaN error + } else if((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) { + return PHPExcel_Calculation_Functions::NaN(); + } + + return $value; + } // function _wrapResult() + + + /** + * Remove quotes used as a wrapper to identify string values + * + * @param mixed $value + * @return mixed + */ + public static function _unwrapResult($value) { + if (is_string($value)) { + if ((isset($value{0})) && ($value{0} == '"') && (substr($value,-1) == '"')) { + return substr($value,1,-1); + } + // Convert numeric errors to NaN error + } else if((is_float($value)) && ((is_nan($value)) || (is_infinite($value)))) { + return PHPExcel_Calculation_Functions::NaN(); + } + return $value; + } // function _unwrapResult() + + + + + /** + * Calculate cell value (using formula from a cell ID) + * Retained for backward compatibility + * + * @access public + * @param PHPExcel_Cell $pCell Cell to calculate + * @return mixed + * @throws PHPExcel_Calculation_Exception + */ + public function calculate(PHPExcel_Cell $pCell = NULL) { + try { + return $this->calculateCellValue($pCell); + } catch (PHPExcel_Exception $e) { + throw new PHPExcel_Calculation_Exception($e->getMessage()); + } + } // function calculate() + + + /** + * Calculate the value of a cell formula + * + * @access public + * @param PHPExcel_Cell $pCell Cell to calculate + * @param Boolean $resetLog Flag indicating whether the debug log should be reset or not + * @return mixed + * @throws PHPExcel_Calculation_Exception + */ + public function calculateCellValue(PHPExcel_Cell $pCell = NULL, $resetLog = TRUE) { + if ($pCell === NULL) { + return NULL; + } + + $returnArrayAsType = self::$returnArrayAsType; + if ($resetLog) { + // Initialise the logging settings if requested + $this->formulaError = null; + $this->_debugLog->clearLog(); + $this->_cyclicReferenceStack->clear(); + $this->_cyclicFormulaCount = 1; + + self::$returnArrayAsType = self::RETURN_ARRAY_AS_ARRAY; + } + + // Execute the calculation for the cell formula + try { + $result = self::_unwrapResult($this->_calculateFormulaValue($pCell->getValue(), $pCell->getCoordinate(), $pCell)); + } catch (PHPExcel_Exception $e) { + throw new PHPExcel_Calculation_Exception($e->getMessage()); + } + + if ((is_array($result)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { + self::$returnArrayAsType = $returnArrayAsType; + $testResult = PHPExcel_Calculation_Functions::flattenArray($result); + if (self::$returnArrayAsType == self::RETURN_ARRAY_AS_ERROR) { + return PHPExcel_Calculation_Functions::VALUE(); + } + // If there's only a single cell in the array, then we allow it + if (count($testResult) != 1) { + // If keys are numeric, then it's a matrix result rather than a cell range result, so we permit it + $r = array_keys($result); + $r = array_shift($r); + if (!is_numeric($r)) { return PHPExcel_Calculation_Functions::VALUE(); } + if (is_array($result[$r])) { + $c = array_keys($result[$r]); + $c = array_shift($c); + if (!is_numeric($c)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + } + $result = array_shift($testResult); + } + self::$returnArrayAsType = $returnArrayAsType; + + + if ($result === NULL) { + return 0; + } elseif((is_float($result)) && ((is_nan($result)) || (is_infinite($result)))) { + return PHPExcel_Calculation_Functions::NaN(); + } + return $result; + } // function calculateCellValue( + + + /** + * Validate and parse a formula string + * + * @param string $formula Formula to parse + * @return array + * @throws PHPExcel_Calculation_Exception + */ + public function parseFormula($formula) { + // Basic validation that this is indeed a formula + // We return an empty array if not + $formula = trim($formula); + if ((!isset($formula{0})) || ($formula{0} != '=')) return array(); + $formula = ltrim(substr($formula,1)); + if (!isset($formula{0})) return array(); + + // Parse the formula and return the token stack + return $this->_parseFormula($formula); + } // function parseFormula() + + + /** + * Calculate the value of a formula + * + * @param string $formula Formula to parse + * @param string $cellID Address of the cell to calculate + * @param PHPExcel_Cell $pCell Cell to calculate + * @return mixed + * @throws PHPExcel_Calculation_Exception + */ + public function calculateFormula($formula, $cellID=NULL, PHPExcel_Cell $pCell = NULL) { + // Initialise the logging settings + $this->formulaError = null; + $this->_debugLog->clearLog(); + $this->_cyclicReferenceStack->clear(); + + // Disable calculation cacheing because it only applies to cell calculations, not straight formulae + // But don't actually flush any cache + $resetCache = $this->getCalculationCacheEnabled(); + $this->_calculationCacheEnabled = FALSE; + // Execute the calculation + try { + $result = self::_unwrapResult($this->_calculateFormulaValue($formula, $cellID, $pCell)); + } catch (PHPExcel_Exception $e) { + throw new PHPExcel_Calculation_Exception($e->getMessage()); + } + + // Reset calculation cacheing to its previous state + $this->_calculationCacheEnabled = $resetCache; + + return $result; + } // function calculateFormula() + + + public function getValueFromCache($worksheetName, $cellID, &$cellValue) { + // Is calculation cacheing enabled? + // Is the value present in calculation cache? +//echo 'Test cache for ',$worksheetName,'!',$cellID,PHP_EOL; + $this->_debugLog->writeDebugLog('Testing cache value for cell ', $worksheetName, '!', $cellID); + if (($this->_calculationCacheEnabled) && (isset($this->_calculationCache[$worksheetName][$cellID]))) { +//echo 'Retrieve from cache',PHP_EOL; + $this->_debugLog->writeDebugLog('Retrieving value for cell ', $worksheetName, '!', $cellID, ' from cache'); + // Return the cached result + $cellValue = $this->_calculationCache[$worksheetName][$cellID]; + return TRUE; + } + return FALSE; + } + + public function saveValueToCache($worksheetName, $cellID, $cellValue) { + if ($this->_calculationCacheEnabled) { + $this->_calculationCache[$worksheetName][$cellID] = $cellValue; + } + } + + /** + * Parse a cell formula and calculate its value + * + * @param string $formula The formula to parse and calculate + * @param string $cellID The ID (e.g. A3) of the cell that we are calculating + * @param PHPExcel_Cell $pCell Cell to calculate + * @return mixed + * @throws PHPExcel_Calculation_Exception + */ + public function _calculateFormulaValue($formula, $cellID=null, PHPExcel_Cell $pCell = null) { + $cellValue = ''; + + // Basic validation that this is indeed a formula + // We simply return the cell value if not + $formula = trim($formula); + if ($formula{0} != '=') return self::_wrapResult($formula); + $formula = ltrim(substr($formula,1)); + if (!isset($formula{0})) return self::_wrapResult($formula); + + $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL; + $wsTitle = ($pCellParent !== NULL) ? $pCellParent->getTitle() : "\x00Wrk"; + + if (($cellID !== NULL) && ($this->getValueFromCache($wsTitle, $cellID, $cellValue))) { + return $cellValue; + } + + if (($wsTitle{0} !== "\x00") && ($this->_cyclicReferenceStack->onStack($wsTitle.'!'.$cellID))) { + if ($this->cyclicFormulaCount <= 0) { + return $this->_raiseFormulaError('Cyclic Reference in Formula'); + } elseif (($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) && + ($this->_cyclicFormulaCell == $wsTitle.'!'.$cellID)) { + return $cellValue; + } elseif ($this->_cyclicFormulaCell == $wsTitle.'!'.$cellID) { + ++$this->_cyclicFormulaCount; + if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) { + return $cellValue; + } + } elseif ($this->_cyclicFormulaCell == '') { + $this->_cyclicFormulaCell = $wsTitle.'!'.$cellID; + if ($this->_cyclicFormulaCount >= $this->cyclicFormulaCount) { + return $cellValue; + } + } + } + + // Parse the formula onto the token stack and calculate the value + $this->_cyclicReferenceStack->push($wsTitle.'!'.$cellID); + $cellValue = $this->_processTokenStack($this->_parseFormula($formula, $pCell), $cellID, $pCell); + $this->_cyclicReferenceStack->pop(); + + // Save to calculation cache + if ($cellID !== NULL) { + $this->saveValueToCache($wsTitle, $cellID, $cellValue); + } + + // Return the calculated value + return $cellValue; + } // function _calculateFormulaValue() + + + /** + * Ensure that paired matrix operands are both matrices and of the same size + * + * @param mixed &$operand1 First matrix operand + * @param mixed &$operand2 Second matrix operand + * @param integer $resize Flag indicating whether the matrices should be resized to match + * and (if so), whether the smaller dimension should grow or the + * larger should shrink. + * 0 = no resize + * 1 = shrink to fit + * 2 = extend to fit + */ + private static function _checkMatrixOperands(&$operand1,&$operand2,$resize = 1) { + // Examine each of the two operands, and turn them into an array if they aren't one already + // Note that this function should only be called if one or both of the operand is already an array + if (!is_array($operand1)) { + list($matrixRows,$matrixColumns) = self::_getMatrixDimensions($operand2); + $operand1 = array_fill(0,$matrixRows,array_fill(0,$matrixColumns,$operand1)); + $resize = 0; + } elseif (!is_array($operand2)) { + list($matrixRows,$matrixColumns) = self::_getMatrixDimensions($operand1); + $operand2 = array_fill(0,$matrixRows,array_fill(0,$matrixColumns,$operand2)); + $resize = 0; + } + + list($matrix1Rows,$matrix1Columns) = self::_getMatrixDimensions($operand1); + list($matrix2Rows,$matrix2Columns) = self::_getMatrixDimensions($operand2); + if (($matrix1Rows == $matrix2Columns) && ($matrix2Rows == $matrix1Columns)) { + $resize = 1; + } + + if ($resize == 2) { + // Given two matrices of (potentially) unequal size, convert the smaller in each dimension to match the larger + self::_resizeMatricesExtend($operand1,$operand2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns); + } elseif ($resize == 1) { + // Given two matrices of (potentially) unequal size, convert the larger in each dimension to match the smaller + self::_resizeMatricesShrink($operand1,$operand2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns); + } + return array( $matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns); + } // function _checkMatrixOperands() + + + /** + * Read the dimensions of a matrix, and re-index it with straight numeric keys starting from row 0, column 0 + * + * @param mixed &$matrix matrix operand + * @return array An array comprising the number of rows, and number of columns + */ + public static function _getMatrixDimensions(&$matrix) { + $matrixRows = count($matrix); + $matrixColumns = 0; + foreach($matrix as $rowKey => $rowValue) { + $matrixColumns = max(count($rowValue),$matrixColumns); + if (!is_array($rowValue)) { + $matrix[$rowKey] = array($rowValue); + } else { + $matrix[$rowKey] = array_values($rowValue); + } + } + $matrix = array_values($matrix); + return array($matrixRows,$matrixColumns); + } // function _getMatrixDimensions() + + + /** + * Ensure that paired matrix operands are both matrices of the same size + * + * @param mixed &$matrix1 First matrix operand + * @param mixed &$matrix2 Second matrix operand + * @param integer $matrix1Rows Row size of first matrix operand + * @param integer $matrix1Columns Column size of first matrix operand + * @param integer $matrix2Rows Row size of second matrix operand + * @param integer $matrix2Columns Column size of second matrix operand + */ + private static function _resizeMatricesShrink(&$matrix1,&$matrix2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns) { + if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) { + if ($matrix2Rows < $matrix1Rows) { + for ($i = $matrix2Rows; $i < $matrix1Rows; ++$i) { + unset($matrix1[$i]); + } + } + if ($matrix2Columns < $matrix1Columns) { + for ($i = 0; $i < $matrix1Rows; ++$i) { + for ($j = $matrix2Columns; $j < $matrix1Columns; ++$j) { + unset($matrix1[$i][$j]); + } + } + } + } + + if (($matrix1Columns < $matrix2Columns) || ($matrix1Rows < $matrix2Rows)) { + if ($matrix1Rows < $matrix2Rows) { + for ($i = $matrix1Rows; $i < $matrix2Rows; ++$i) { + unset($matrix2[$i]); + } + } + if ($matrix1Columns < $matrix2Columns) { + for ($i = 0; $i < $matrix2Rows; ++$i) { + for ($j = $matrix1Columns; $j < $matrix2Columns; ++$j) { + unset($matrix2[$i][$j]); + } + } + } + } + } // function _resizeMatricesShrink() + + + /** + * Ensure that paired matrix operands are both matrices of the same size + * + * @param mixed &$matrix1 First matrix operand + * @param mixed &$matrix2 Second matrix operand + * @param integer $matrix1Rows Row size of first matrix operand + * @param integer $matrix1Columns Column size of first matrix operand + * @param integer $matrix2Rows Row size of second matrix operand + * @param integer $matrix2Columns Column size of second matrix operand + */ + private static function _resizeMatricesExtend(&$matrix1,&$matrix2,$matrix1Rows,$matrix1Columns,$matrix2Rows,$matrix2Columns) { + if (($matrix2Columns < $matrix1Columns) || ($matrix2Rows < $matrix1Rows)) { + if ($matrix2Columns < $matrix1Columns) { + for ($i = 0; $i < $matrix2Rows; ++$i) { + $x = $matrix2[$i][$matrix2Columns-1]; + for ($j = $matrix2Columns; $j < $matrix1Columns; ++$j) { + $matrix2[$i][$j] = $x; + } + } + } + if ($matrix2Rows < $matrix1Rows) { + $x = $matrix2[$matrix2Rows-1]; + for ($i = 0; $i < $matrix1Rows; ++$i) { + $matrix2[$i] = $x; + } + } + } + + if (($matrix1Columns < $matrix2Columns) || ($matrix1Rows < $matrix2Rows)) { + if ($matrix1Columns < $matrix2Columns) { + for ($i = 0; $i < $matrix1Rows; ++$i) { + $x = $matrix1[$i][$matrix1Columns-1]; + for ($j = $matrix1Columns; $j < $matrix2Columns; ++$j) { + $matrix1[$i][$j] = $x; + } + } + } + if ($matrix1Rows < $matrix2Rows) { + $x = $matrix1[$matrix1Rows-1]; + for ($i = 0; $i < $matrix2Rows; ++$i) { + $matrix1[$i] = $x; + } + } + } + } // function _resizeMatricesExtend() + + + /** + * Format details of an operand for display in the log (based on operand type) + * + * @param mixed $value First matrix operand + * @return mixed + */ + private function _showValue($value) { + if ($this->_debugLog->getWriteDebugLog()) { + $testArray = PHPExcel_Calculation_Functions::flattenArray($value); + if (count($testArray) == 1) { + $value = array_pop($testArray); + } + + if (is_array($value)) { + $returnMatrix = array(); + $pad = $rpad = ', '; + foreach($value as $row) { + if (is_array($row)) { + $returnMatrix[] = implode($pad,array_map(array($this,'_showValue'),$row)); + $rpad = '; '; + } else { + $returnMatrix[] = $this->_showValue($row); + } + } + return '{ '.implode($rpad,$returnMatrix).' }'; + } elseif(is_string($value) && (trim($value,'"') == $value)) { + return '"'.$value.'"'; + } elseif(is_bool($value)) { + return ($value) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE']; + } + } + return PHPExcel_Calculation_Functions::flattenSingleValue($value); + } // function _showValue() + + + /** + * Format type and details of an operand for display in the log (based on operand type) + * + * @param mixed $value First matrix operand + * @return mixed + */ + private function _showTypeDetails($value) { + if ($this->_debugLog->getWriteDebugLog()) { + $testArray = PHPExcel_Calculation_Functions::flattenArray($value); + if (count($testArray) == 1) { + $value = array_pop($testArray); + } + + if ($value === NULL) { + return 'a NULL value'; + } elseif (is_float($value)) { + $typeString = 'a floating point number'; + } elseif(is_int($value)) { + $typeString = 'an integer number'; + } elseif(is_bool($value)) { + $typeString = 'a boolean'; + } elseif(is_array($value)) { + $typeString = 'a matrix'; + } else { + if ($value == '') { + return 'an empty string'; + } elseif ($value{0} == '#') { + return 'a '.$value.' error'; + } else { + $typeString = 'a string'; + } + } + return $typeString.' with a value of '.$this->_showValue($value); + } + } // function _showTypeDetails() + + + private static function _convertMatrixReferences($formula) { + static $matrixReplaceFrom = array('{',';','}'); + static $matrixReplaceTo = array('MKMATRIX(MKMATRIX(','),MKMATRIX(','))'); + + // Convert any Excel matrix references to the MKMATRIX() function + if (strpos($formula,'{') !== FALSE) { + // If there is the possibility of braces within a quoted string, then we don't treat those as matrix indicators + if (strpos($formula,'"') !== FALSE) { + // So instead we skip replacing in any quoted strings by only replacing in every other array element after we've exploded + // the formula + $temp = explode('"',$formula); + // Open and Closed counts used for trapping mismatched braces in the formula + $openCount = $closeCount = 0; + $i = FALSE; + foreach($temp as &$value) { + // Only count/replace in alternating array entries + if ($i = !$i) { + $openCount += substr_count($value,'{'); + $closeCount += substr_count($value,'}'); + $value = str_replace($matrixReplaceFrom,$matrixReplaceTo,$value); + } + } + unset($value); + // Then rebuild the formula string + $formula = implode('"',$temp); + } else { + // If there's no quoted strings, then we do a simple count/replace + $openCount = substr_count($formula,'{'); + $closeCount = substr_count($formula,'}'); + $formula = str_replace($matrixReplaceFrom,$matrixReplaceTo,$formula); + } + // Trap for mismatched braces and trigger an appropriate error + if ($openCount < $closeCount) { + if ($openCount > 0) { + return $this->_raiseFormulaError("Formula Error: Mismatched matrix braces '}'"); + } else { + return $this->_raiseFormulaError("Formula Error: Unexpected '}' encountered"); + } + } elseif ($openCount > $closeCount) { + if ($closeCount > 0) { + return $this->_raiseFormulaError("Formula Error: Mismatched matrix braces '{'"); + } else { + return $this->_raiseFormulaError("Formula Error: Unexpected '{' encountered"); + } + } + } + + return $formula; + } // function _convertMatrixReferences() + + + private static function _mkMatrix() { + return func_get_args(); + } // function _mkMatrix() + + + // Binary Operators + // These operators always work on two values + // Array key is the operator, the value indicates whether this is a left or right associative operator + private static $_operatorAssociativity = array( + '^' => 0, // Exponentiation + '*' => 0, '/' => 0, // Multiplication and Division + '+' => 0, '-' => 0, // Addition and Subtraction + '&' => 0, // Concatenation + '|' => 0, ':' => 0, // Intersect and Range + '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison + ); + + // Comparison (Boolean) Operators + // These operators work on two values, but always return a boolean result + private static $_comparisonOperators = array('>' => TRUE, '<' => TRUE, '=' => TRUE, '>=' => TRUE, '<=' => TRUE, '<>' => TRUE); + + // Operator Precedence + // This list includes all valid operators, whether binary (including boolean) or unary (such as %) + // Array key is the operator, the value is its precedence + private static $_operatorPrecedence = array( + ':' => 8, // Range + '|' => 7, // Intersect + '~' => 6, // Negation + '%' => 5, // Percentage + '^' => 4, // Exponentiation + '*' => 3, '/' => 3, // Multiplication and Division + '+' => 2, '-' => 2, // Addition and Subtraction + '&' => 1, // Concatenation + '>' => 0, '<' => 0, '=' => 0, '>=' => 0, '<=' => 0, '<>' => 0 // Comparison + ); + + // Convert infix to postfix notation + private function _parseFormula($formula, PHPExcel_Cell $pCell = NULL) { + if (($formula = self::_convertMatrixReferences(trim($formula))) === FALSE) { + return FALSE; + } + + // If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent worksheet), + // so we store the parent worksheet so that we can re-attach it when necessary + $pCellParent = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL; + + $regexpMatchString = '/^('.self::CALCULATION_REGEXP_FUNCTION. + '|'.self::CALCULATION_REGEXP_NUMBER. + '|'.self::CALCULATION_REGEXP_STRING. + '|'.self::CALCULATION_REGEXP_OPENBRACE. + '|'.self::CALCULATION_REGEXP_CELLREF. + '|'.self::CALCULATION_REGEXP_NAMEDRANGE. + '|'.self::CALCULATION_REGEXP_ERROR. + ')/si'; + + // Start with initialisation + $index = 0; + $stack = new PHPExcel_Calculation_Token_Stack; + $output = array(); + $expectingOperator = FALSE; // We use this test in syntax-checking the expression to determine when a + // - is a negation or + is a positive operator rather than an operation + $expectingOperand = FALSE; // We use this test in syntax-checking the expression to determine whether an operand + // should be null in a function call + // The guts of the lexical parser + // Loop through the formula extracting each operator and operand in turn + while(TRUE) { +//echo 'Assessing Expression '.substr($formula, $index),PHP_EOL; + $opCharacter = $formula{$index}; // Get the first character of the value at the current index position +//echo 'Initial character of expression block is '.$opCharacter,PHP_EOL; + if ((isset(self::$_comparisonOperators[$opCharacter])) && (strlen($formula) > $index) && (isset(self::$_comparisonOperators[$formula{$index+1}]))) { + $opCharacter .= $formula{++$index}; +//echo 'Initial character of expression block is comparison operator '.$opCharacter.PHP_EOL; + } + + // Find out if we're currently at the beginning of a number, variable, cell reference, function, parenthesis or operand + $isOperandOrFunction = preg_match($regexpMatchString, substr($formula, $index), $match); +//echo '$isOperandOrFunction is '.(($isOperandOrFunction) ? 'True' : 'False').PHP_EOL; +//var_dump($match); + + if ($opCharacter == '-' && !$expectingOperator) { // Is it a negation instead of a minus? +//echo 'Element is a Negation operator',PHP_EOL; + $stack->push('Unary Operator','~'); // Put a negation on the stack + ++$index; // and drop the negation symbol + } elseif ($opCharacter == '%' && $expectingOperator) { +//echo 'Element is a Percentage operator',PHP_EOL; + $stack->push('Unary Operator','%'); // Put a percentage on the stack + ++$index; + } elseif ($opCharacter == '+' && !$expectingOperator) { // Positive (unary plus rather than binary operator plus) can be discarded? +//echo 'Element is a Positive number, not Plus operator',PHP_EOL; + ++$index; // Drop the redundant plus symbol + } elseif ((($opCharacter == '~') || ($opCharacter == '|')) && (!$isOperandOrFunction)) { // We have to explicitly deny a tilde or pipe, because they are legal + return $this->_raiseFormulaError("Formula Error: Illegal character '~'"); // on the stack but not in the input expression + + } elseif ((isset(self::$_operators[$opCharacter]) or $isOperandOrFunction) && $expectingOperator) { // Are we putting an operator on the stack? +//echo 'Element with value '.$opCharacter.' is an Operator',PHP_EOL; + while($stack->count() > 0 && + ($o2 = $stack->last()) && + isset(self::$_operators[$o2['value']]) && + @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_operatorPrecedence[$o2['value']])) { + $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output + } + $stack->push('Binary Operator',$opCharacter); // Finally put our current operator onto the stack + ++$index; + $expectingOperator = FALSE; + + } elseif ($opCharacter == ')' && $expectingOperator) { // Are we expecting to close a parenthesis? +//echo 'Element is a Closing bracket',PHP_EOL; + $expectingOperand = FALSE; + while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last ( + if ($o2 === NULL) return $this->_raiseFormulaError('Formula Error: Unexpected closing brace ")"'); + else $output[] = $o2; + } + $d = $stack->last(2); + if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches)) { // Did this parenthesis just close a function? + $functionName = $matches[1]; // Get the function name +//echo 'Closed Function is '.$functionName,PHP_EOL; + $d = $stack->pop(); + $argumentCount = $d['value']; // See how many arguments there were (argument count is the next value stored on the stack) +//if ($argumentCount == 0) { +// echo 'With no arguments',PHP_EOL; +//} elseif ($argumentCount == 1) { +// echo 'With 1 argument',PHP_EOL; +//} else { +// echo 'With '.$argumentCount.' arguments',PHP_EOL; +//} + $output[] = $d; // Dump the argument count on the output + $output[] = $stack->pop(); // Pop the function and push onto the output + if (isset(self::$_controlFunctions[$functionName])) { +//echo 'Built-in function '.$functionName,PHP_EOL; + $expectedArgumentCount = self::$_controlFunctions[$functionName]['argumentCount']; + $functionCall = self::$_controlFunctions[$functionName]['functionCall']; + } elseif (isset(self::$_PHPExcelFunctions[$functionName])) { +//echo 'PHPExcel function '.$functionName,PHP_EOL; + $expectedArgumentCount = self::$_PHPExcelFunctions[$functionName]['argumentCount']; + $functionCall = self::$_PHPExcelFunctions[$functionName]['functionCall']; + } else { // did we somehow push a non-function on the stack? this should never happen + return $this->_raiseFormulaError("Formula Error: Internal error, non-function on stack"); + } + // Check the argument count + $argumentCountError = FALSE; + if (is_numeric($expectedArgumentCount)) { + if ($expectedArgumentCount < 0) { +//echo '$expectedArgumentCount is between 0 and '.abs($expectedArgumentCount),PHP_EOL; + if ($argumentCount > abs($expectedArgumentCount)) { + $argumentCountError = TRUE; + $expectedArgumentCountString = 'no more than '.abs($expectedArgumentCount); + } + } else { +//echo '$expectedArgumentCount is numeric '.$expectedArgumentCount,PHP_EOL; + if ($argumentCount != $expectedArgumentCount) { + $argumentCountError = TRUE; + $expectedArgumentCountString = $expectedArgumentCount; + } + } + } elseif ($expectedArgumentCount != '*') { + $isOperandOrFunction = preg_match('/(\d*)([-+,])(\d*)/',$expectedArgumentCount,$argMatch); +//print_r($argMatch); +//echo PHP_EOL; + switch ($argMatch[2]) { + case '+' : + if ($argumentCount < $argMatch[1]) { + $argumentCountError = TRUE; + $expectedArgumentCountString = $argMatch[1].' or more '; + } + break; + case '-' : + if (($argumentCount < $argMatch[1]) || ($argumentCount > $argMatch[3])) { + $argumentCountError = TRUE; + $expectedArgumentCountString = 'between '.$argMatch[1].' and '.$argMatch[3]; + } + break; + case ',' : + if (($argumentCount != $argMatch[1]) && ($argumentCount != $argMatch[3])) { + $argumentCountError = TRUE; + $expectedArgumentCountString = 'either '.$argMatch[1].' or '.$argMatch[3]; + } + break; + } + } + if ($argumentCountError) { + return $this->_raiseFormulaError("Formula Error: Wrong number of arguments for $functionName() function: $argumentCount given, ".$expectedArgumentCountString." expected"); + } + } + ++$index; + + } elseif ($opCharacter == ',') { // Is this the separator for function arguments? +//echo 'Element is a Function argument separator',PHP_EOL; + while (($o2 = $stack->pop()) && $o2['value'] != '(') { // Pop off the stack back to the last ( + if ($o2 === NULL) return $this->_raiseFormulaError("Formula Error: Unexpected ,"); + else $output[] = $o2; // pop the argument expression stuff and push onto the output + } + // If we've a comma when we're expecting an operand, then what we actually have is a null operand; + // so push a null onto the stack + if (($expectingOperand) || (!$expectingOperator)) { + $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => NULL); + } + // make sure there was a function + $d = $stack->last(2); + if (!preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $d['value'], $matches)) + return $this->_raiseFormulaError("Formula Error: Unexpected ,"); + $d = $stack->pop(); + $stack->push($d['type'],++$d['value'],$d['reference']); // increment the argument count + $stack->push('Brace', '('); // put the ( back on, we'll need to pop back to it again + $expectingOperator = FALSE; + $expectingOperand = TRUE; + ++$index; + + } elseif ($opCharacter == '(' && !$expectingOperator) { +// echo 'Element is an Opening Bracket
    '; + $stack->push('Brace', '('); + ++$index; + + } elseif ($isOperandOrFunction && !$expectingOperator) { // do we now have a function/variable/number? + $expectingOperator = TRUE; + $expectingOperand = FALSE; + $val = $match[1]; + $length = strlen($val); +// echo 'Element with value '.$val.' is an Operand, Variable, Constant, String, Number, Cell Reference or Function
    '; + + if (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $val, $matches)) { + $val = preg_replace('/\s/','',$val); +// echo 'Element '.$val.' is a Function
    '; + if (isset(self::$_PHPExcelFunctions[strtoupper($matches[1])]) || isset(self::$_controlFunctions[strtoupper($matches[1])])) { // it's a function + $stack->push('Function', strtoupper($val)); + $ax = preg_match('/^\s*(\s*\))/i', substr($formula, $index+$length), $amatch); + if ($ax) { + $stack->push('Operand Count for Function '.strtoupper($val).')', 0); + $expectingOperator = TRUE; + } else { + $stack->push('Operand Count for Function '.strtoupper($val).')', 1); + $expectingOperator = FALSE; + } + $stack->push('Brace', '('); + } else { // it's a var w/ implicit multiplication + $output[] = array('type' => 'Value', 'value' => $matches[1], 'reference' => NULL); + } + } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $val, $matches)) { +// echo 'Element '.$val.' is a Cell reference
    '; + // Watch for this case-change when modifying to allow cell references in different worksheets... + // Should only be applied to the actual cell column, not the worksheet name + + // If the last entry on the stack was a : operator, then we have a cell range reference + $testPrevOp = $stack->last(1); + if ($testPrevOp['value'] == ':') { + // If we have a worksheet reference, then we're playing with a 3D reference + if ($matches[2] == '') { + // Otherwise, we 'inherit' the worksheet reference from the start cell reference + // The start of the cell range reference should be the last entry in $output + $startCellRef = $output[count($output)-1]['value']; + preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $startCellRef, $startMatches); + if ($startMatches[2] > '') { + $val = $startMatches[2].'!'.$val; + } + } else { + return $this->_raiseFormulaError("3D Range references are not yet supported"); + } + } + + $output[] = array('type' => 'Cell Reference', 'value' => $val, 'reference' => $val); +// $expectingOperator = FALSE; + } else { // it's a variable, constant, string, number or boolean +// echo 'Element is a Variable, Constant, String, Number or Boolean
    '; + // If the last entry on the stack was a : operator, then we may have a row or column range reference + $testPrevOp = $stack->last(1); + if ($testPrevOp['value'] == ':') { + $startRowColRef = $output[count($output)-1]['value']; + $rangeWS1 = ''; + if (strpos('!',$startRowColRef) !== FALSE) { + list($rangeWS1,$startRowColRef) = explode('!',$startRowColRef); + } + if ($rangeWS1 != '') $rangeWS1 .= '!'; + $rangeWS2 = $rangeWS1; + if (strpos('!',$val) !== FALSE) { + list($rangeWS2,$val) = explode('!',$val); + } + if ($rangeWS2 != '') $rangeWS2 .= '!'; + if ((is_integer($startRowColRef)) && (ctype_digit($val)) && + ($startRowColRef <= 1048576) && ($val <= 1048576)) { + // Row range + $endRowColRef = ($pCellParent !== NULL) ? $pCellParent->getHighestColumn() : 'XFD'; // Max 16,384 columns for Excel2007 + $output[count($output)-1]['value'] = $rangeWS1.'A'.$startRowColRef; + $val = $rangeWS2.$endRowColRef.$val; + } elseif ((ctype_alpha($startRowColRef)) && (ctype_alpha($val)) && + (strlen($startRowColRef) <= 3) && (strlen($val) <= 3)) { + // Column range + $endRowColRef = ($pCellParent !== NULL) ? $pCellParent->getHighestRow() : 1048576; // Max 1,048,576 rows for Excel2007 + $output[count($output)-1]['value'] = $rangeWS1.strtoupper($startRowColRef).'1'; + $val = $rangeWS2.$val.$endRowColRef; + } + } + + $localeConstant = FALSE; + if ($opCharacter == '"') { +// echo 'Element is a String
    '; + // UnEscape any quotes within the string + $val = self::_wrapResult(str_replace('""','"',self::_unwrapResult($val))); + } elseif (is_numeric($val)) { +// echo 'Element is a Number
    '; + if ((strpos($val,'.') !== FALSE) || (stripos($val,'e') !== FALSE) || ($val > PHP_INT_MAX) || ($val < -PHP_INT_MAX)) { +// echo 'Casting '.$val.' to float
    '; + $val = (float) $val; + } else { +// echo 'Casting '.$val.' to integer
    '; + $val = (integer) $val; + } + } elseif (isset(self::$_ExcelConstants[trim(strtoupper($val))])) { + $excelConstant = trim(strtoupper($val)); +// echo 'Element '.$excelConstant.' is an Excel Constant
    '; + $val = self::$_ExcelConstants[$excelConstant]; + } elseif (($localeConstant = array_search(trim(strtoupper($val)), self::$_localeBoolean)) !== FALSE) { +// echo 'Element '.$localeConstant.' is an Excel Constant
    '; + $val = self::$_ExcelConstants[$localeConstant]; + } + $details = array('type' => 'Value', 'value' => $val, 'reference' => NULL); + if ($localeConstant) { $details['localeValue'] = $localeConstant; } + $output[] = $details; + } + $index += $length; + + } elseif ($opCharacter == '$') { // absolute row or column range + ++$index; + } elseif ($opCharacter == ')') { // miscellaneous error checking + if ($expectingOperand) { + $output[] = array('type' => 'NULL Value', 'value' => self::$_ExcelConstants['NULL'], 'reference' => NULL); + $expectingOperand = FALSE; + $expectingOperator = TRUE; + } else { + return $this->_raiseFormulaError("Formula Error: Unexpected ')'"); + } + } elseif (isset(self::$_operators[$opCharacter]) && !$expectingOperator) { + return $this->_raiseFormulaError("Formula Error: Unexpected operator '$opCharacter'"); + } else { // I don't even want to know what you did to get here + return $this->_raiseFormulaError("Formula Error: An unexpected error occured"); + } + // Test for end of formula string + if ($index == strlen($formula)) { + // Did we end with an operator?. + // Only valid for the % unary operator + if ((isset(self::$_operators[$opCharacter])) && ($opCharacter != '%')) { + return $this->_raiseFormulaError("Formula Error: Operator '$opCharacter' has no operands"); + } else { + break; + } + } + // Ignore white space + while (($formula{$index} == "\n") || ($formula{$index} == "\r")) { + ++$index; + } + if ($formula{$index} == ' ') { + while ($formula{$index} == ' ') { + ++$index; + } + // If we're expecting an operator, but only have a space between the previous and next operands (and both are + // Cell References) then we have an INTERSECTION operator +// echo 'Possible Intersect Operator
    '; + if (($expectingOperator) && (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'.*/Ui', substr($formula, $index), $match)) && + ($output[count($output)-1]['type'] == 'Cell Reference')) { +// echo 'Element is an Intersect Operator
    '; + while($stack->count() > 0 && + ($o2 = $stack->last()) && + isset(self::$_operators[$o2['value']]) && + @(self::$_operatorAssociativity[$opCharacter] ? self::$_operatorPrecedence[$opCharacter] < self::$_operatorPrecedence[$o2['value']] : self::$_operatorPrecedence[$opCharacter] <= self::$_operatorPrecedence[$o2['value']])) { + $output[] = $stack->pop(); // Swap operands and higher precedence operators from the stack to the output + } + $stack->push('Binary Operator','|'); // Put an Intersect Operator on the stack + $expectingOperator = FALSE; + } + } + } + + while (($op = $stack->pop()) !== NULL) { // pop everything off the stack and push onto output + if ((is_array($op) && $op['value'] == '(') || ($op === '(')) + return $this->_raiseFormulaError("Formula Error: Expecting ')'"); // if there are any opening braces on the stack, then braces were unbalanced + $output[] = $op; + } + return $output; + } // function _parseFormula() + + + private static function _dataTestReference(&$operandData) + { + $operand = $operandData['value']; + if (($operandData['reference'] === NULL) && (is_array($operand))) { + $rKeys = array_keys($operand); + $rowKey = array_shift($rKeys); + $cKeys = array_keys(array_keys($operand[$rowKey])); + $colKey = array_shift($cKeys); + if (ctype_upper($colKey)) { + $operandData['reference'] = $colKey.$rowKey; + } + } + return $operand; + } + + // evaluate postfix notation + private function _processTokenStack($tokens, $cellID = NULL, PHPExcel_Cell $pCell = NULL) { + if ($tokens == FALSE) return FALSE; + + // If we're using cell caching, then $pCell may well be flushed back to the cache (which detaches the parent cell collection), + // so we store the parent cell collection so that we can re-attach it when necessary + $pCellWorksheet = ($pCell !== NULL) ? $pCell->getWorksheet() : NULL; + $pCellParent = ($pCell !== NULL) ? $pCell->getParent() : null; + $stack = new PHPExcel_Calculation_Token_Stack; + + // Loop through each token in turn + foreach ($tokens as $tokenData) { +// print_r($tokenData); +// echo '
    '; + $token = $tokenData['value']; +// echo 'Token is '.$token.'
    '; + // if the token is a binary operator, pop the top two values off the stack, do the operation, and push the result back on the stack + if (isset(self::$_binaryOperators[$token])) { +// echo 'Token is a binary operator
    '; + // We must have two operands, error if we don't + if (($operand2Data = $stack->pop()) === NULL) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); + if (($operand1Data = $stack->pop()) === NULL) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); + + $operand1 = self::_dataTestReference($operand1Data); + $operand2 = self::_dataTestReference($operand2Data); + + // Log what we're doing + if ($token == ':') { + $this->_debugLog->writeDebugLog('Evaluating Range ', $this->_showValue($operand1Data['reference']), ' ', $token, ' ', $this->_showValue($operand2Data['reference'])); + } else { + $this->_debugLog->writeDebugLog('Evaluating ', $this->_showValue($operand1), ' ', $token, ' ', $this->_showValue($operand2)); + } + + // Process the operation in the appropriate manner + switch ($token) { + // Comparison (Boolean) Operators + case '>' : // Greater than + case '<' : // Less than + case '>=' : // Greater than or Equal to + case '<=' : // Less than or Equal to + case '=' : // Equality + case '<>' : // Inequality + $this->_executeBinaryComparisonOperation($cellID,$operand1,$operand2,$token,$stack); + break; + // Binary Operators + case ':' : // Range + $sheet1 = $sheet2 = ''; + if (strpos($operand1Data['reference'],'!') !== FALSE) { + list($sheet1,$operand1Data['reference']) = explode('!',$operand1Data['reference']); + } else { + $sheet1 = ($pCellParent !== NULL) ? $pCellWorksheet->getTitle() : ''; + } + if (strpos($operand2Data['reference'],'!') !== FALSE) { + list($sheet2,$operand2Data['reference']) = explode('!',$operand2Data['reference']); + } else { + $sheet2 = $sheet1; + } + if ($sheet1 == $sheet2) { + if ($operand1Data['reference'] === NULL) { + if ((trim($operand1Data['value']) != '') && (is_numeric($operand1Data['value']))) { + $operand1Data['reference'] = $pCell->getColumn().$operand1Data['value']; + } elseif (trim($operand1Data['reference']) == '') { + $operand1Data['reference'] = $pCell->getCoordinate(); + } else { + $operand1Data['reference'] = $operand1Data['value'].$pCell->getRow(); + } + } + if ($operand2Data['reference'] === NULL) { + if ((trim($operand2Data['value']) != '') && (is_numeric($operand2Data['value']))) { + $operand2Data['reference'] = $pCell->getColumn().$operand2Data['value']; + } elseif (trim($operand2Data['reference']) == '') { + $operand2Data['reference'] = $pCell->getCoordinate(); + } else { + $operand2Data['reference'] = $operand2Data['value'].$pCell->getRow(); + } + } + + $oData = array_merge(explode(':',$operand1Data['reference']),explode(':',$operand2Data['reference'])); + $oCol = $oRow = array(); + foreach($oData as $oDatum) { + $oCR = PHPExcel_Cell::coordinateFromString($oDatum); + $oCol[] = PHPExcel_Cell::columnIndexFromString($oCR[0]) - 1; + $oRow[] = $oCR[1]; + } + $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow); + if ($pCellParent !== NULL) { + $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($sheet1), FALSE); + } else { + return $this->_raiseFormulaError('Unable to access Cell Reference'); + } + $stack->push('Cell Reference',$cellValue,$cellRef); + } else { + $stack->push('Error',PHPExcel_Calculation_Functions::REF(),NULL); + } + + break; + case '+' : // Addition + $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'plusEquals',$stack); + break; + case '-' : // Subtraction + $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'minusEquals',$stack); + break; + case '*' : // Multiplication + $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'arrayTimesEquals',$stack); + break; + case '/' : // Division + $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'arrayRightDivide',$stack); + break; + case '^' : // Exponential + $this->_executeNumericBinaryOperation($cellID,$operand1,$operand2,$token,'power',$stack); + break; + case '&' : // Concatenation + // If either of the operands is a matrix, we need to treat them both as matrices + // (converting the other operand to a matrix if need be); then perform the required + // matrix operation + if (is_bool($operand1)) { + $operand1 = ($operand1) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE']; + } + if (is_bool($operand2)) { + $operand2 = ($operand2) ? self::$_localeBoolean['TRUE'] : self::$_localeBoolean['FALSE']; + } + if ((is_array($operand1)) || (is_array($operand2))) { + // Ensure that both operands are arrays/matrices + self::_checkMatrixOperands($operand1,$operand2,2); + try { + // Convert operand 1 from a PHP array to a matrix + $matrix = new PHPExcel_Shared_JAMA_Matrix($operand1); + // Perform the required operation against the operand 1 matrix, passing in operand 2 + $matrixResult = $matrix->concat($operand2); + $result = $matrixResult->getArray(); + } catch (PHPExcel_Exception $ex) { + $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage()); + $result = '#VALUE!'; + } + } else { + $result = '"'.str_replace('""','"',self::_unwrapResult($operand1,'"').self::_unwrapResult($operand2,'"')).'"'; + } + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result)); + $stack->push('Value',$result); + break; + case '|' : // Intersect + $rowIntersect = array_intersect_key($operand1,$operand2); + $cellIntersect = $oCol = $oRow = array(); + foreach(array_keys($rowIntersect) as $row) { + $oRow[] = $row; + foreach($rowIntersect[$row] as $col => $data) { + $oCol[] = PHPExcel_Cell::columnIndexFromString($col) - 1; + $cellIntersect[$row] = array_intersect_key($operand1[$row],$operand2[$row]); + } + } + $cellRef = PHPExcel_Cell::stringFromColumnIndex(min($oCol)).min($oRow).':'.PHPExcel_Cell::stringFromColumnIndex(max($oCol)).max($oRow); + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($cellIntersect)); + $stack->push('Value',$cellIntersect,$cellRef); + break; + } + + // if the token is a unary operator, pop one value off the stack, do the operation, and push it back on + } elseif (($token === '~') || ($token === '%')) { +// echo 'Token is a unary operator
    '; + if (($arg = $stack->pop()) === NULL) return $this->_raiseFormulaError('Internal error - Operand value missing from stack'); + $arg = $arg['value']; + if ($token === '~') { +// echo 'Token is a negation operator
    '; + $this->_debugLog->writeDebugLog('Evaluating Negation of ', $this->_showValue($arg)); + $multiplier = -1; + } else { +// echo 'Token is a percentile operator
    '; + $this->_debugLog->writeDebugLog('Evaluating Percentile of ', $this->_showValue($arg)); + $multiplier = 0.01; + } + if (is_array($arg)) { + self::_checkMatrixOperands($arg,$multiplier,2); + try { + $matrix1 = new PHPExcel_Shared_JAMA_Matrix($arg); + $matrixResult = $matrix1->arrayTimesEquals($multiplier); + $result = $matrixResult->getArray(); + } catch (PHPExcel_Exception $ex) { + $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage()); + $result = '#VALUE!'; + } + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result)); + $stack->push('Value',$result); + } else { + $this->_executeNumericBinaryOperation($cellID,$multiplier,$arg,'*','arrayTimesEquals',$stack); + } + + } elseif (preg_match('/^'.self::CALCULATION_REGEXP_CELLREF.'$/i', $token, $matches)) { + $cellRef = NULL; +// echo 'Element '.$token.' is a Cell reference
    '; + if (isset($matches[8])) { +// echo 'Reference is a Range of cells
    '; + if ($pCell === NULL) { +// We can't access the range, so return a REF error + $cellValue = PHPExcel_Calculation_Functions::REF(); + } else { + $cellRef = $matches[6].$matches[7].':'.$matches[9].$matches[10]; + if ($matches[2] > '') { + $matches[2] = trim($matches[2],"\"'"); + if ((strpos($matches[2],'[') !== FALSE) || (strpos($matches[2],']') !== FALSE)) { + // It's a Reference to an external workbook (not currently supported) + return $this->_raiseFormulaError('Unable to access External Workbook'); + } + $matches[2] = trim($matches[2],"\"'"); +// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
    '; + $this->_debugLog->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in worksheet ', $matches[2]); + if ($pCellParent !== NULL) { + $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE); + } else { + return $this->_raiseFormulaError('Unable to access Cell Reference'); + } + $this->_debugLog->writeDebugLog('Evaluation Result for cells ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this->_showTypeDetails($cellValue)); +// $cellRef = $matches[2].'!'.$cellRef; + } else { +// echo '$cellRef='.$cellRef.' in current worksheet
    '; + $this->_debugLog->writeDebugLog('Evaluating Cell Range ', $cellRef, ' in current worksheet'); + if ($pCellParent !== NULL) { + $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE); + } else { + return $this->_raiseFormulaError('Unable to access Cell Reference'); + } + $this->_debugLog->writeDebugLog('Evaluation Result for cells ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); + } + } + } else { +// echo 'Reference is a single Cell
    '; + if ($pCell === NULL) { +// We can't access the cell, so return a REF error + $cellValue = PHPExcel_Calculation_Functions::REF(); + } else { + $cellRef = $matches[6].$matches[7]; + if ($matches[2] > '') { + $matches[2] = trim($matches[2],"\"'"); + if ((strpos($matches[2],'[') !== FALSE) || (strpos($matches[2],']') !== FALSE)) { + // It's a Reference to an external workbook (not currently supported) + return $this->_raiseFormulaError('Unable to access External Workbook'); + } +// echo '$cellRef='.$cellRef.' in worksheet '.$matches[2].'
    '; + $this->_debugLog->writeDebugLog('Evaluating Cell ', $cellRef, ' in worksheet ', $matches[2]); + if ($pCellParent !== NULL) { + if ($this->_workbook->getSheetByName($matches[2])->cellExists($cellRef)) { + $cellValue = $this->extractCellRange($cellRef, $this->_workbook->getSheetByName($matches[2]), FALSE); + $pCell->attach($pCellParent); + } else { + $cellValue = NULL; + } + } else { + return $this->_raiseFormulaError('Unable to access Cell Reference'); + } + $this->_debugLog->writeDebugLog('Evaluation Result for cell ', $cellRef, ' in worksheet ', $matches[2], ' is ', $this->_showTypeDetails($cellValue)); +// $cellRef = $matches[2].'!'.$cellRef; + } else { +// echo '$cellRef='.$cellRef.' in current worksheet
    '; + $this->_debugLog->writeDebugLog('Evaluating Cell ', $cellRef, ' in current worksheet'); + if ($pCellParent->isDataSet($cellRef)) { + $cellValue = $this->extractCellRange($cellRef, $pCellWorksheet, FALSE); + $pCell->attach($pCellParent); + } else { + $cellValue = NULL; + } + $this->_debugLog->writeDebugLog('Evaluation Result for cell ', $cellRef, ' is ', $this->_showTypeDetails($cellValue)); + } + } + } + $stack->push('Value',$cellValue,$cellRef); + + // if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on + } elseif (preg_match('/^'.self::CALCULATION_REGEXP_FUNCTION.'$/i', $token, $matches)) { +// echo 'Token is a function
    '; + $functionName = $matches[1]; + $argCount = $stack->pop(); + $argCount = $argCount['value']; + if ($functionName != 'MKMATRIX') { + $this->_debugLog->writeDebugLog('Evaluating Function ', self::_localeFunc($functionName), '() with ', (($argCount == 0) ? 'no' : $argCount), ' argument', (($argCount == 1) ? '' : 's')); + } + if ((isset(self::$_PHPExcelFunctions[$functionName])) || (isset(self::$_controlFunctions[$functionName]))) { // function + if (isset(self::$_PHPExcelFunctions[$functionName])) { + $functionCall = self::$_PHPExcelFunctions[$functionName]['functionCall']; + $passByReference = isset(self::$_PHPExcelFunctions[$functionName]['passByReference']); + $passCellReference = isset(self::$_PHPExcelFunctions[$functionName]['passCellReference']); + } elseif (isset(self::$_controlFunctions[$functionName])) { + $functionCall = self::$_controlFunctions[$functionName]['functionCall']; + $passByReference = isset(self::$_controlFunctions[$functionName]['passByReference']); + $passCellReference = isset(self::$_controlFunctions[$functionName]['passCellReference']); + } + // get the arguments for this function +// echo 'Function '.$functionName.' expects '.$argCount.' arguments
    '; + $args = $argArrayVals = array(); + for ($i = 0; $i < $argCount; ++$i) { + $arg = $stack->pop(); + $a = $argCount - $i - 1; + if (($passByReference) && + (isset(self::$_PHPExcelFunctions[$functionName]['passByReference'][$a])) && + (self::$_PHPExcelFunctions[$functionName]['passByReference'][$a])) { + if ($arg['reference'] === NULL) { + $args[] = $cellID; + if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($cellID); } + } else { + $args[] = $arg['reference']; + if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($arg['reference']); } + } + } else { + $args[] = self::_unwrapResult($arg['value']); + if ($functionName != 'MKMATRIX') { $argArrayVals[] = $this->_showValue($arg['value']); } + } + } + // Reverse the order of the arguments + krsort($args); + if (($passByReference) && ($argCount == 0)) { + $args[] = $cellID; + $argArrayVals[] = $this->_showValue($cellID); + } +// echo 'Arguments are: '; +// print_r($args); +// echo '
    '; + if ($functionName != 'MKMATRIX') { + if ($this->_debugLog->getWriteDebugLog()) { + krsort($argArrayVals); + $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', implode(self::$_localeArgumentSeparator.' ',PHPExcel_Calculation_Functions::flattenArray($argArrayVals)), ' )'); + } + } + // Process each argument in turn, building the return value as an array +// if (($argCount == 1) && (is_array($args[1])) && ($functionName != 'MKMATRIX')) { +// $operand1 = $args[1]; +// $this->_debugLog->writeDebugLog('Argument is a matrix: ', $this->_showValue($operand1)); +// $result = array(); +// $row = 0; +// foreach($operand1 as $args) { +// if (is_array($args)) { +// foreach($args as $arg) { +// $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($arg), ' )'); +// $r = call_user_func_array($functionCall,$arg); +// $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r)); +// $result[$row][] = $r; +// } +// ++$row; +// } else { +// $this->_debugLog->writeDebugLog('Evaluating ', self::_localeFunc($functionName), '( ', $this->_showValue($args), ' )'); +// $r = call_user_func_array($functionCall,$args); +// $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($r)); +// $result[] = $r; +// } +// } +// } else { + // Process the argument with the appropriate function call + if ($passCellReference) { + $args[] = $pCell; + } + if (strpos($functionCall,'::') !== FALSE) { + $result = call_user_func_array(explode('::',$functionCall),$args); + } else { + foreach($args as &$arg) { + $arg = PHPExcel_Calculation_Functions::flattenSingleValue($arg); + } + unset($arg); + $result = call_user_func_array($functionCall,$args); + } +// } + if ($functionName != 'MKMATRIX') { + $this->_debugLog->writeDebugLog('Evaluation Result for ', self::_localeFunc($functionName), '() function call is ', $this->_showTypeDetails($result)); + } + $stack->push('Value',self::_wrapResult($result)); + } + + } else { + // if the token is a number, boolean, string or an Excel error, push it onto the stack + if (isset(self::$_ExcelConstants[strtoupper($token)])) { + $excelConstant = strtoupper($token); +// echo 'Token is a PHPExcel constant: '.$excelConstant.'
    '; + $stack->push('Constant Value',self::$_ExcelConstants[$excelConstant]); + $this->_debugLog->writeDebugLog('Evaluating Constant ', $excelConstant, ' as ', $this->_showTypeDetails(self::$_ExcelConstants[$excelConstant])); + } elseif ((is_numeric($token)) || ($token === NULL) || (is_bool($token)) || ($token == '') || ($token{0} == '"') || ($token{0} == '#')) { +// echo 'Token is a number, boolean, string, null or an Excel error
    '; + $stack->push('Value',$token); + // if the token is a named range, push the named range name onto the stack + } elseif (preg_match('/^'.self::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $token, $matches)) { +// echo 'Token is a named range
    '; + $namedRange = $matches[6]; +// echo 'Named Range is '.$namedRange.'
    '; + $this->_debugLog->writeDebugLog('Evaluating Named Range ', $namedRange); + $cellValue = $this->extractNamedRange($namedRange, ((NULL !== $pCell) ? $pCellWorksheet : NULL), FALSE); + $pCell->attach($pCellParent); + $this->_debugLog->writeDebugLog('Evaluation Result for named range ', $namedRange, ' is ', $this->_showTypeDetails($cellValue)); + $stack->push('Named Range',$cellValue,$namedRange); + } else { + return $this->_raiseFormulaError("undefined variable '$token'"); + } + } + } + // when we're out of tokens, the stack should have a single element, the final result + if ($stack->count() != 1) return $this->_raiseFormulaError("internal error"); + $output = $stack->pop(); + $output = $output['value']; + +// if ((is_array($output)) && (self::$returnArrayAsType != self::RETURN_ARRAY_AS_ARRAY)) { +// return array_shift(PHPExcel_Calculation_Functions::flattenArray($output)); +// } + return $output; + } // function _processTokenStack() + + + private function _validateBinaryOperand($cellID, &$operand, &$stack) { + // Numbers, matrices and booleans can pass straight through, as they're already valid + if (is_string($operand)) { + // We only need special validations for the operand if it is a string + // Start by stripping off the quotation marks we use to identify true excel string values internally + if ($operand > '' && $operand{0} == '"') { $operand = self::_unwrapResult($operand); } + // If the string is a numeric value, we treat it as a numeric, so no further testing + if (!is_numeric($operand)) { + // If not a numeric, test to see if the value is an Excel error, and so can't be used in normal binary operations + if ($operand > '' && $operand{0} == '#') { + $stack->push('Value', $operand); + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($operand)); + return FALSE; + } elseif (!PHPExcel_Shared_String::convertToNumberIfFraction($operand)) { + // If not a numeric or a fraction, then it's a text string, and so can't be used in mathematical binary operations + $stack->push('Value', '#VALUE!'); + $this->_debugLog->writeDebugLog('Evaluation Result is a ', $this->_showTypeDetails('#VALUE!')); + return FALSE; + } + } + } + + // return a true if the value of the operand is one that we can use in normal binary operations + return TRUE; + } // function _validateBinaryOperand() + + + private function _executeBinaryComparisonOperation($cellID, $operand1, $operand2, $operation, &$stack, $recursingArrays=FALSE) { + // If we're dealing with matrix operations, we want a matrix result + if ((is_array($operand1)) || (is_array($operand2))) { + $result = array(); + if ((is_array($operand1)) && (!is_array($operand2))) { + foreach($operand1 as $x => $operandData) { + $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_showValue($operand2)); + $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2,$operation,$stack); + $r = $stack->pop(); + $result[$x] = $r['value']; + } + } elseif ((!is_array($operand1)) && (is_array($operand2))) { + foreach($operand2 as $x => $operandData) { + $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operand1), ' ', $operation, ' ', $this->_showValue($operandData)); + $this->_executeBinaryComparisonOperation($cellID,$operand1,$operandData,$operation,$stack); + $r = $stack->pop(); + $result[$x] = $r['value']; + } + } else { + if (!$recursingArrays) { self::_checkMatrixOperands($operand1,$operand2,2); } + foreach($operand1 as $x => $operandData) { + $this->_debugLog->writeDebugLog('Evaluating Comparison ', $this->_showValue($operandData), ' ', $operation, ' ', $this->_showValue($operand2[$x])); + $this->_executeBinaryComparisonOperation($cellID,$operandData,$operand2[$x],$operation,$stack,TRUE); + $r = $stack->pop(); + $result[$x] = $r['value']; + } + } + // Log the result details + $this->_debugLog->writeDebugLog('Comparison Evaluation Result is ', $this->_showTypeDetails($result)); + // And push the result onto the stack + $stack->push('Array',$result); + return TRUE; + } + + // Simple validate the two operands if they are string values + if (is_string($operand1) && $operand1 > '' && $operand1{0} == '"') { $operand1 = self::_unwrapResult($operand1); } + if (is_string($operand2) && $operand2 > '' && $operand2{0} == '"') { $operand2 = self::_unwrapResult($operand2); } + + // execute the necessary operation + switch ($operation) { + // Greater than + case '>': + $result = ($operand1 > $operand2); + break; + // Less than + case '<': + $result = ($operand1 < $operand2); + break; + // Equality + case '=': + $result = ($operand1 == $operand2); + break; + // Greater than or equal + case '>=': + $result = ($operand1 >= $operand2); + break; + // Less than or equal + case '<=': + $result = ($operand1 <= $operand2); + break; + // Inequality + case '<>': + $result = ($operand1 != $operand2); + break; + } + + // Log the result details + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result)); + // And push the result onto the stack + $stack->push('Value',$result); + return TRUE; + } // function _executeBinaryComparisonOperation() + + + private function _executeNumericBinaryOperation($cellID,$operand1,$operand2,$operation,$matrixFunction,&$stack) { + // Validate the two operands + if (!$this->_validateBinaryOperand($cellID,$operand1,$stack)) return FALSE; + if (!$this->_validateBinaryOperand($cellID,$operand2,$stack)) return FALSE; + + $executeMatrixOperation = FALSE; + // If either of the operands is a matrix, we need to treat them both as matrices + // (converting the other operand to a matrix if need be); then perform the required + // matrix operation + if ((is_array($operand1)) || (is_array($operand2))) { + // Ensure that both operands are arrays/matrices + $executeMatrixOperation = TRUE; + $mSize = array(); + list($mSize[],$mSize[],$mSize[],$mSize[]) = self::_checkMatrixOperands($operand1,$operand2,2); + + // But if they're both single cell matrices, then we can treat them as simple values + if (array_sum($mSize) == 4) { + $executeMatrixOperation = FALSE; + $operand1 = $operand1[0][0]; + $operand2 = $operand2[0][0]; + } + } + + if ($executeMatrixOperation) { + try { + // Convert operand 1 from a PHP array to a matrix + $matrix = new PHPExcel_Shared_JAMA_Matrix($operand1); + // Perform the required operation against the operand 1 matrix, passing in operand 2 + $matrixResult = $matrix->$matrixFunction($operand2); + $result = $matrixResult->getArray(); + } catch (PHPExcel_Exception $ex) { + $this->_debugLog->writeDebugLog('JAMA Matrix Exception: ', $ex->getMessage()); + $result = '#VALUE!'; + } + } else { + if ((PHPExcel_Calculation_Functions::getCompatibilityMode() != PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) && + ((is_string($operand1) && !is_numeric($operand1)) || (is_string($operand2) && !is_numeric($operand2)))) { + $result = PHPExcel_Calculation_Functions::VALUE(); + } else { + // If we're dealing with non-matrix operations, execute the necessary operation + switch ($operation) { + // Addition + case '+': + $result = $operand1+$operand2; + break; + // Subtraction + case '-': + $result = $operand1-$operand2; + break; + // Multiplication + case '*': + $result = $operand1*$operand2; + break; + // Division + case '/': + if ($operand2 == 0) { + // Trap for Divide by Zero error + $stack->push('Value','#DIV/0!'); + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails('#DIV/0!')); + return FALSE; + } else { + $result = $operand1/$operand2; + } + break; + // Power + case '^': + $result = pow($operand1,$operand2); + break; + } + } + } + + // Log the result details + $this->_debugLog->writeDebugLog('Evaluation Result is ', $this->_showTypeDetails($result)); + // And push the result onto the stack + $stack->push('Value',$result); + return TRUE; + } // function _executeNumericBinaryOperation() + + + // trigger an error, but nicely, if need be + protected function _raiseFormulaError($errorMessage) { + $this->formulaError = $errorMessage; + $this->_cyclicReferenceStack->clear(); + if (!$this->suppressFormulaErrors) throw new PHPExcel_Calculation_Exception($errorMessage); + trigger_error($errorMessage, E_USER_ERROR); + } // function _raiseFormulaError() + + + /** + * Extract range values + * + * @param string &$pRange String based range representation + * @param PHPExcel_Worksheet $pSheet Worksheet + * @param boolean $resetLog Flag indicating whether calculation log should be reset or not + * @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned. + * @throws PHPExcel_Calculation_Exception + */ + public function extractCellRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = NULL, $resetLog = TRUE) { + // Return value + $returnValue = array (); + +// echo 'extractCellRange('.$pRange.')',PHP_EOL; + if ($pSheet !== NULL) { + $pSheetName = $pSheet->getTitle(); +// echo 'Passed sheet name is '.$pSheetName.PHP_EOL; +// echo 'Range reference is '.$pRange.PHP_EOL; + if (strpos ($pRange, '!') !== false) { +// echo '$pRange reference includes sheet reference',PHP_EOL; + list($pSheetName,$pRange) = PHPExcel_Worksheet::extractSheetTitle($pRange, true); +// echo 'New sheet name is '.$pSheetName,PHP_EOL; +// echo 'Adjusted Range reference is '.$pRange,PHP_EOL; + $pSheet = $this->_workbook->getSheetByName($pSheetName); + } + + // Extract range + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); + $pRange = $pSheetName.'!'.$pRange; + if (!isset($aReferences[1])) { + // Single cell in range + sscanf($aReferences[0],'%[A-Z]%d', $currentCol, $currentRow); + $cellValue = NULL; + if ($pSheet->cellExists($aReferences[0])) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } else { + // Extract cell data for all cells in the range + foreach ($aReferences as $reference) { + // Extract range + sscanf($reference,'%[A-Z]%d', $currentCol, $currentRow); + $cellValue = NULL; + if ($pSheet->cellExists($reference)) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } + } + } + + // Return + return $returnValue; + } // function extractCellRange() + + + /** + * Extract range values + * + * @param string &$pRange String based range representation + * @param PHPExcel_Worksheet $pSheet Worksheet + * @return mixed Array of values in range if range contains more than one element. Otherwise, a single value is returned. + * @param boolean $resetLog Flag indicating whether calculation log should be reset or not + * @throws PHPExcel_Calculation_Exception + */ + public function extractNamedRange(&$pRange = 'A1', PHPExcel_Worksheet $pSheet = NULL, $resetLog = TRUE) { + // Return value + $returnValue = array (); + +// echo 'extractNamedRange('.$pRange.')
    '; + if ($pSheet !== NULL) { + $pSheetName = $pSheet->getTitle(); +// echo 'Current sheet name is '.$pSheetName.'
    '; +// echo 'Range reference is '.$pRange.'
    '; + if (strpos ($pRange, '!') !== false) { +// echo '$pRange reference includes sheet reference',PHP_EOL; + list($pSheetName,$pRange) = PHPExcel_Worksheet::extractSheetTitle($pRange, true); +// echo 'New sheet name is '.$pSheetName,PHP_EOL; +// echo 'Adjusted Range reference is '.$pRange,PHP_EOL; + $pSheet = $this->_workbook->getSheetByName($pSheetName); + } + + // Named range? + $namedRange = PHPExcel_NamedRange::resolveRange($pRange, $pSheet); + if ($namedRange !== NULL) { + $pSheet = $namedRange->getWorksheet(); +// echo 'Named Range '.$pRange.' ('; + $pRange = $namedRange->getRange(); + $splitRange = PHPExcel_Cell::splitRange($pRange); + // Convert row and column references + if (ctype_alpha($splitRange[0][0])) { + $pRange = $splitRange[0][0] . '1:' . $splitRange[0][1] . $namedRange->getWorksheet()->getHighestRow(); + } elseif(ctype_digit($splitRange[0][0])) { + $pRange = 'A' . $splitRange[0][0] . ':' . $namedRange->getWorksheet()->getHighestColumn() . $splitRange[0][1]; + } +// echo $pRange.') is in sheet '.$namedRange->getWorksheet()->getTitle().'
    '; + +// if ($pSheet->getTitle() != $namedRange->getWorksheet()->getTitle()) { +// if (!$namedRange->getLocalOnly()) { +// $pSheet = $namedRange->getWorksheet(); +// } else { +// return $returnValue; +// } +// } + } else { + return PHPExcel_Calculation_Functions::REF(); + } + + // Extract range + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); +// var_dump($aReferences); + if (!isset($aReferences[1])) { + // Single cell (or single column or row) in range + list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($aReferences[0]); + $cellValue = NULL; + if ($pSheet->cellExists($aReferences[0])) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($aReferences[0])->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } else { + // Extract cell data for all cells in the range + foreach ($aReferences as $reference) { + // Extract range + list($currentCol,$currentRow) = PHPExcel_Cell::coordinateFromString($reference); +// echo 'NAMED RANGE: $currentCol='.$currentCol.' $currentRow='.$currentRow.'
    '; + $cellValue = NULL; + if ($pSheet->cellExists($reference)) { + $returnValue[$currentRow][$currentCol] = $pSheet->getCell($reference)->getCalculatedValue($resetLog); + } else { + $returnValue[$currentRow][$currentCol] = NULL; + } + } + } +// print_r($returnValue); +// echo '
    '; + } + + // Return + return $returnValue; + } // function extractNamedRange() + + + /** + * Is a specific function implemented? + * + * @param string $pFunction Function Name + * @return boolean + */ + public function isImplemented($pFunction = '') { + $pFunction = strtoupper ($pFunction); + if (isset(self::$_PHPExcelFunctions[$pFunction])) { + return (self::$_PHPExcelFunctions[$pFunction]['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY'); + } else { + return FALSE; + } + } // function isImplemented() + + + /** + * Get a list of all implemented functions as an array of function objects + * + * @return array of PHPExcel_Calculation_Function + */ + public function listFunctions() { + // Return value + $returnValue = array(); + // Loop functions + foreach(self::$_PHPExcelFunctions as $functionName => $function) { + if ($function['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY') { + $returnValue[$functionName] = new PHPExcel_Calculation_Function($function['category'], + $functionName, + $function['functionCall'] + ); + } + } + + // Return + return $returnValue; + } // function listFunctions() + + + /** + * Get a list of all Excel function names + * + * @return array + */ + public function listAllFunctionNames() { + return array_keys(self::$_PHPExcelFunctions); + } // function listAllFunctionNames() + + /** + * Get a list of implemented Excel function names + * + * @return array + */ + public function listFunctionNames() { + // Return value + $returnValue = array(); + // Loop functions + foreach(self::$_PHPExcelFunctions as $functionName => $function) { + if ($function['functionCall'] != 'PHPExcel_Calculation_Functions::DUMMY') { + $returnValue[] = $functionName; + } + } + + // Return + return $returnValue; + } // function listFunctionNames() + +} // class PHPExcel_Calculation + diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Database.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Database.php new file mode 100755 index 0000000..df68045 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Database.php @@ -0,0 +1,725 @@ + $criteriaName) { + $testCondition = array(); + $testConditionCount = 0; + foreach($criteria as $row => $criterion) { + if ($criterion[$key] > '') { + $testCondition[] = '[:'.$criteriaName.']'.PHPExcel_Calculation_Functions::_ifCondition($criterion[$key]); + $testConditionCount++; + } + } + if ($testConditionCount > 1) { + $testConditions[] = 'OR('.implode(',',$testCondition).')'; + $testConditionsCount++; + } elseif($testConditionCount == 1) { + $testConditions[] = $testCondition[0]; + $testConditionsCount++; + } + } + + if ($testConditionsCount > 1) { + $testConditionSet = 'AND('.implode(',',$testConditions).')'; + } elseif($testConditionsCount == 1) { + $testConditionSet = $testConditions[0]; + } + + // Loop through each row of the database + foreach($database as $dataRow => $dataValues) { + // Substitute actual values from the database row for our [:placeholders] + $testConditionList = $testConditionSet; + foreach($criteriaNames as $key => $criteriaName) { + $k = array_search($criteriaName,$fieldNames); + if (isset($dataValues[$k])) { + $dataValue = $dataValues[$k]; + $dataValue = (is_string($dataValue)) ? PHPExcel_Calculation::_wrapResult(strtoupper($dataValue)) : $dataValue; + $testConditionList = str_replace('[:'.$criteriaName.']',$dataValue,$testConditionList); + } + } + // evaluate the criteria against the row data + $result = PHPExcel_Calculation::getInstance()->_calculateFormulaValue('='.$testConditionList); + // If the row failed to meet the criteria, remove it from the database + if (!$result) { + unset($database[$dataRow]); + } + } + + return $database; + } + + + /** + * DAVERAGE + * + * Averages the values in a column of a list or database that match conditions you specify. + * + * Excel Function: + * DAVERAGE(database,field,criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return float + * + */ + public static function DAVERAGE($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::AVERAGE($colData); + } // function DAVERAGE() + + + /** + * DCOUNT + * + * Counts the cells that contain numbers in a column of a list or database that match conditions + * that you specify. + * + * Excel Function: + * DCOUNT(database,[field],criteria) + * + * Excel Function: + * DAVERAGE(database,field,criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return integer + * + * @TODO The field argument is optional. If field is omitted, DCOUNT counts all records in the + * database that match the criteria. + * + */ + public static function DCOUNT($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::COUNT($colData); + } // function DCOUNT() + + + /** + * DCOUNTA + * + * Counts the nonblank cells in a column of a list or database that match conditions that you specify. + * + * Excel Function: + * DCOUNTA(database,[field],criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return integer + * + * @TODO The field argument is optional. If field is omitted, DCOUNTA counts all records in the + * database that match the criteria. + * + */ + public static function DCOUNTA($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::COUNTA($colData); + } // function DCOUNTA() + + + /** + * DGET + * + * Extracts a single value from a column of a list or database that matches conditions that you + * specify. + * + * Excel Function: + * DGET(database,field,criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return mixed + * + */ + public static function DGET($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + if (count($colData) > 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + + return $colData[0]; + } // function DGET() + + + /** + * DMAX + * + * Returns the largest number in a column of a list or database that matches conditions you that + * specify. + * + * Excel Function: + * DMAX(database,field,criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return float + * + */ + public static function DMAX($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::MAX($colData); + } // function DMAX() + + + /** + * DMIN + * + * Returns the smallest number in a column of a list or database that matches conditions you that + * specify. + * + * Excel Function: + * DMIN(database,field,criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return float + * + */ + public static function DMIN($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::MIN($colData); + } // function DMIN() + + + /** + * DPRODUCT + * + * Multiplies the values in a column of a list or database that match conditions that you specify. + * + * Excel Function: + * DPRODUCT(database,field,criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return float + * + */ + public static function DPRODUCT($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_MathTrig::PRODUCT($colData); + } // function DPRODUCT() + + + /** + * DSTDEV + * + * Estimates the standard deviation of a population based on a sample by using the numbers in a + * column of a list or database that match conditions that you specify. + * + * Excel Function: + * DSTDEV(database,field,criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return float + * + */ + public static function DSTDEV($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::STDEV($colData); + } // function DSTDEV() + + + /** + * DSTDEVP + * + * Calculates the standard deviation of a population based on the entire population by using the + * numbers in a column of a list or database that match conditions that you specify. + * + * Excel Function: + * DSTDEVP(database,field,criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return float + * + */ + public static function DSTDEVP($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::STDEVP($colData); + } // function DSTDEVP() + + + /** + * DSUM + * + * Adds the numbers in a column of a list or database that match conditions that you specify. + * + * Excel Function: + * DSUM(database,field,criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return float + * + */ + public static function DSUM($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_MathTrig::SUM($colData); + } // function DSUM() + + + /** + * DVAR + * + * Estimates the variance of a population based on a sample by using the numbers in a column + * of a list or database that match conditions that you specify. + * + * Excel Function: + * DVAR(database,field,criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return float + * + */ + public static function DVAR($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::VARFunc($colData); + } // function DVAR() + + + /** + * DVARP + * + * Calculates the variance of a population based on the entire population by using the numbers + * in a column of a list or database that match conditions that you specify. + * + * Excel Function: + * DVARP(database,field,criteria) + * + * @access public + * @category Database Functions + * @param mixed[] $database The range of cells that makes up the list or database. + * A database is a list of related data in which rows of related + * information are records, and columns of data are fields. The + * first row of the list contains labels for each column. + * @param string|integer $field Indicates which column is used in the function. Enter the + * column label enclosed between double quotation marks, such as + * "Age" or "Yield," or a number (without quotation marks) that + * represents the position of the column within the list: 1 for + * the first column, 2 for the second column, and so on. + * @param mixed[] $criteria The range of cells that contains the conditions you specify. + * You can use any range for the criteria argument, as long as it + * includes at least one column label and at least one cell below + * the column label in which you specify a condition for the + * column. + * @return float + * + */ + public static function DVARP($database,$field,$criteria) { + $field = self::__fieldExtract($database,$field); + if (is_null($field)) { + return NULL; + } + + // reduce the database to a set of rows that match all the criteria + $database = self::__filter($database,$criteria); + // extract an array of values for the requested column + $colData = array(); + foreach($database as $row) { + $colData[] = $row[$field]; + } + + // Return + return PHPExcel_Calculation_Statistical::VARP($colData); + } // function DVARP() + + +} // class PHPExcel_Calculation_Database diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/DateTime.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/DateTime.php new file mode 100755 index 0000000..2d5180a --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/DateTime.php @@ -0,0 +1,1475 @@ +format('m'); + $oYear = (int) $PHPDateObject->format('Y'); + + $adjustmentMonthsString = (string) $adjustmentMonths; + if ($adjustmentMonths > 0) { + $adjustmentMonthsString = '+'.$adjustmentMonths; + } + if ($adjustmentMonths != 0) { + $PHPDateObject->modify($adjustmentMonthsString.' months'); + } + $nMonth = (int) $PHPDateObject->format('m'); + $nYear = (int) $PHPDateObject->format('Y'); + + $monthDiff = ($nMonth - $oMonth) + (($nYear - $oYear) * 12); + if ($monthDiff != $adjustmentMonths) { + $adjustDays = (int) $PHPDateObject->format('d'); + $adjustDaysString = '-'.$adjustDays.' days'; + $PHPDateObject->modify($adjustDaysString); + } + return $PHPDateObject; + } // function _adjustDateByMonths() + + + /** + * DATETIMENOW + * + * Returns the current date and time. + * The NOW function is useful when you need to display the current date and time on a worksheet or + * calculate a value based on the current date and time, and have that value updated each time you + * open the worksheet. + * + * NOTE: When used in a Cell Formula, MS Excel changes the cell format so that it matches the date + * and time format of your regional settings. PHPExcel does not change cell formatting in this way. + * + * Excel Function: + * NOW() + * + * @access public + * @category Date/Time Functions + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function DATETIMENOW() { + $saveTimeZone = date_default_timezone_get(); + date_default_timezone_set('UTC'); + $retValue = False; + switch (PHPExcel_Calculation_Functions::getReturnDateType()) { + case PHPExcel_Calculation_Functions::RETURNDATE_EXCEL : + $retValue = (float) PHPExcel_Shared_Date::PHPToExcel(time()); + break; + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC : + $retValue = (integer) time(); + break; + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT : + $retValue = new DateTime(); + break; + } + date_default_timezone_set($saveTimeZone); + + return $retValue; + } // function DATETIMENOW() + + + /** + * DATENOW + * + * Returns the current date. + * The NOW function is useful when you need to display the current date and time on a worksheet or + * calculate a value based on the current date and time, and have that value updated each time you + * open the worksheet. + * + * NOTE: When used in a Cell Formula, MS Excel changes the cell format so that it matches the date + * and time format of your regional settings. PHPExcel does not change cell formatting in this way. + * + * Excel Function: + * TODAY() + * + * @access public + * @category Date/Time Functions + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function DATENOW() { + $saveTimeZone = date_default_timezone_get(); + date_default_timezone_set('UTC'); + $retValue = False; + $excelDateTime = floor(PHPExcel_Shared_Date::PHPToExcel(time())); + switch (PHPExcel_Calculation_Functions::getReturnDateType()) { + case PHPExcel_Calculation_Functions::RETURNDATE_EXCEL : + $retValue = (float) $excelDateTime; + break; + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC : + $retValue = (integer) PHPExcel_Shared_Date::ExcelToPHP($excelDateTime); + break; + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT : + $retValue = PHPExcel_Shared_Date::ExcelToPHPObject($excelDateTime); + break; + } + date_default_timezone_set($saveTimeZone); + + return $retValue; + } // function DATENOW() + + + /** + * DATE + * + * The DATE function returns a value that represents a particular date. + * + * NOTE: When used in a Cell Formula, MS Excel changes the cell format so that it matches the date + * format of your regional settings. PHPExcel does not change cell formatting in this way. + * + * Excel Function: + * DATE(year,month,day) + * + * PHPExcel is a lot more forgiving than MS Excel when passing non numeric values to this function. + * A Month name or abbreviation (English only at this point) such as 'January' or 'Jan' will still be accepted, + * as will a day value with a suffix (e.g. '21st' rather than simply 21); again only English language. + * + * @access public + * @category Date/Time Functions + * @param integer $year The value of the year argument can include one to four digits. + * Excel interprets the year argument according to the configured + * date system: 1900 or 1904. + * If year is between 0 (zero) and 1899 (inclusive), Excel adds that + * value to 1900 to calculate the year. For example, DATE(108,1,2) + * returns January 2, 2008 (1900+108). + * If year is between 1900 and 9999 (inclusive), Excel uses that + * value as the year. For example, DATE(2008,1,2) returns January 2, + * 2008. + * If year is less than 0 or is 10000 or greater, Excel returns the + * #NUM! error value. + * @param integer $month A positive or negative integer representing the month of the year + * from 1 to 12 (January to December). + * If month is greater than 12, month adds that number of months to + * the first month in the year specified. For example, DATE(2008,14,2) + * returns the serial number representing February 2, 2009. + * If month is less than 1, month subtracts the magnitude of that + * number of months, plus 1, from the first month in the year + * specified. For example, DATE(2008,-3,2) returns the serial number + * representing September 2, 2007. + * @param integer $day A positive or negative integer representing the day of the month + * from 1 to 31. + * If day is greater than the number of days in the month specified, + * day adds that number of days to the first day in the month. For + * example, DATE(2008,1,35) returns the serial number representing + * February 4, 2008. + * If day is less than 1, day subtracts the magnitude that number of + * days, plus one, from the first day of the month specified. For + * example, DATE(2008,1,-15) returns the serial number representing + * December 16, 2007. + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function DATE($year = 0, $month = 1, $day = 1) { + $year = PHPExcel_Calculation_Functions::flattenSingleValue($year); + $month = PHPExcel_Calculation_Functions::flattenSingleValue($month); + $day = PHPExcel_Calculation_Functions::flattenSingleValue($day); + + if (($month !== NULL) && (!is_numeric($month))) { + $month = PHPExcel_Shared_Date::monthStringToNumber($month); + } + + if (($day !== NULL) && (!is_numeric($day))) { + $day = PHPExcel_Shared_Date::dayStringToNumber($day); + } + + $year = ($year !== NULL) ? PHPExcel_Shared_String::testStringAsNumeric($year) : 0; + $month = ($month !== NULL) ? PHPExcel_Shared_String::testStringAsNumeric($month) : 0; + $day = ($day !== NULL) ? PHPExcel_Shared_String::testStringAsNumeric($day) : 0; + if ((!is_numeric($year)) || + (!is_numeric($month)) || + (!is_numeric($day))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $year = (integer) $year; + $month = (integer) $month; + $day = (integer) $day; + + $baseYear = PHPExcel_Shared_Date::getExcelCalendar(); + // Validate parameters + if ($year < ($baseYear-1900)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ((($baseYear-1900) != 0) && ($year < $baseYear) && ($year >= 1900)) { + return PHPExcel_Calculation_Functions::NaN(); + } + + if (($year < $baseYear) && ($year >= ($baseYear-1900))) { + $year += 1900; + } + + if ($month < 1) { + // Handle year/month adjustment if month < 1 + --$month; + $year += ceil($month / 12) - 1; + $month = 13 - abs($month % 12); + } elseif ($month > 12) { + // Handle year/month adjustment if month > 12 + $year += floor($month / 12); + $month = ($month % 12); + } + + // Re-validate the year parameter after adjustments + if (($year < $baseYear) || ($year >= 10000)) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Execute function + $excelDateValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year, $month, $day); + switch (PHPExcel_Calculation_Functions::getReturnDateType()) { + case PHPExcel_Calculation_Functions::RETURNDATE_EXCEL : + return (float) $excelDateValue; + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC : + return (integer) PHPExcel_Shared_Date::ExcelToPHP($excelDateValue); + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT : + return PHPExcel_Shared_Date::ExcelToPHPObject($excelDateValue); + } + } // function DATE() + + + /** + * TIME + * + * The TIME function returns a value that represents a particular time. + * + * NOTE: When used in a Cell Formula, MS Excel changes the cell format so that it matches the time + * format of your regional settings. PHPExcel does not change cell formatting in this way. + * + * Excel Function: + * TIME(hour,minute,second) + * + * @access public + * @category Date/Time Functions + * @param integer $hour A number from 0 (zero) to 32767 representing the hour. + * Any value greater than 23 will be divided by 24 and the remainder + * will be treated as the hour value. For example, TIME(27,0,0) = + * TIME(3,0,0) = .125 or 3:00 AM. + * @param integer $minute A number from 0 to 32767 representing the minute. + * Any value greater than 59 will be converted to hours and minutes. + * For example, TIME(0,750,0) = TIME(12,30,0) = .520833 or 12:30 PM. + * @param integer $second A number from 0 to 32767 representing the second. + * Any value greater than 59 will be converted to hours, minutes, + * and seconds. For example, TIME(0,0,2000) = TIME(0,33,22) = .023148 + * or 12:33:20 AM + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function TIME($hour = 0, $minute = 0, $second = 0) { + $hour = PHPExcel_Calculation_Functions::flattenSingleValue($hour); + $minute = PHPExcel_Calculation_Functions::flattenSingleValue($minute); + $second = PHPExcel_Calculation_Functions::flattenSingleValue($second); + + if ($hour == '') { $hour = 0; } + if ($minute == '') { $minute = 0; } + if ($second == '') { $second = 0; } + + if ((!is_numeric($hour)) || (!is_numeric($minute)) || (!is_numeric($second))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $hour = (integer) $hour; + $minute = (integer) $minute; + $second = (integer) $second; + + if ($second < 0) { + $minute += floor($second / 60); + $second = 60 - abs($second % 60); + if ($second == 60) { $second = 0; } + } elseif ($second >= 60) { + $minute += floor($second / 60); + $second = $second % 60; + } + if ($minute < 0) { + $hour += floor($minute / 60); + $minute = 60 - abs($minute % 60); + if ($minute == 60) { $minute = 0; } + } elseif ($minute >= 60) { + $hour += floor($minute / 60); + $minute = $minute % 60; + } + + if ($hour > 23) { + $hour = $hour % 24; + } elseif ($hour < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Execute function + switch (PHPExcel_Calculation_Functions::getReturnDateType()) { + case PHPExcel_Calculation_Functions::RETURNDATE_EXCEL : + $date = 0; + $calendar = PHPExcel_Shared_Date::getExcelCalendar(); + if ($calendar != PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900) { + $date = 1; + } + return (float) PHPExcel_Shared_Date::FormattedPHPToExcel($calendar, 1, $date, $hour, $minute, $second); + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC : + return (integer) PHPExcel_Shared_Date::ExcelToPHP(PHPExcel_Shared_Date::FormattedPHPToExcel(1970, 1, 1, $hour, $minute, $second)); // -2147468400; // -2147472000 + 3600 + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT : + $dayAdjust = 0; + if ($hour < 0) { + $dayAdjust = floor($hour / 24); + $hour = 24 - abs($hour % 24); + if ($hour == 24) { $hour = 0; } + } elseif ($hour >= 24) { + $dayAdjust = floor($hour / 24); + $hour = $hour % 24; + } + $phpDateObject = new DateTime('1900-01-01 '.$hour.':'.$minute.':'.$second); + if ($dayAdjust != 0) { + $phpDateObject->modify($dayAdjust.' days'); + } + return $phpDateObject; + } + } // function TIME() + + + /** + * DATEVALUE + * + * Returns a value that represents a particular date. + * Use DATEVALUE to convert a date represented by a text string to an Excel or PHP date/time stamp + * value. + * + * NOTE: When used in a Cell Formula, MS Excel changes the cell format so that it matches the date + * format of your regional settings. PHPExcel does not change cell formatting in this way. + * + * Excel Function: + * DATEVALUE(dateValue) + * + * @access public + * @category Date/Time Functions + * @param string $dateValue Text that represents a date in a Microsoft Excel date format. + * For example, "1/30/2008" or "30-Jan-2008" are text strings within + * quotation marks that represent dates. Using the default date + * system in Excel for Windows, date_text must represent a date from + * January 1, 1900, to December 31, 9999. Using the default date + * system in Excel for the Macintosh, date_text must represent a date + * from January 1, 1904, to December 31, 9999. DATEVALUE returns the + * #VALUE! error value if date_text is out of this range. + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function DATEVALUE($dateValue = 1) { + $dateValue = trim(PHPExcel_Calculation_Functions::flattenSingleValue($dateValue),'"'); + // Strip any ordinals because they're allowed in Excel (English only) + $dateValue = preg_replace('/(\d)(st|nd|rd|th)([ -\/])/Ui','$1$3',$dateValue); + // Convert separators (/ . or space) to hyphens (should also handle dot used for ordinals in some countries, e.g. Denmark, Germany) + $dateValue = str_replace(array('/','.','-',' '),array(' ',' ',' ',' '),$dateValue); + + $yearFound = false; + $t1 = explode(' ',$dateValue); + foreach($t1 as &$t) { + if ((is_numeric($t)) && ($t > 31)) { + if ($yearFound) { + return PHPExcel_Calculation_Functions::VALUE(); + } else { + if ($t < 100) { $t += 1900; } + $yearFound = true; + } + } + } + if ((count($t1) == 1) && (strpos($t,':') != false)) { + // We've been fed a time value without any date + return 0.0; + } elseif (count($t1) == 2) { + // We only have two parts of the date: either day/month or month/year + if ($yearFound) { + array_unshift($t1,1); + } else { + array_push($t1,date('Y')); + } + } + unset($t); + $dateValue = implode(' ',$t1); + + $PHPDateArray = date_parse($dateValue); + if (($PHPDateArray === False) || ($PHPDateArray['error_count'] > 0)) { + $testVal1 = strtok($dateValue,'- '); + if ($testVal1 !== False) { + $testVal2 = strtok('- '); + if ($testVal2 !== False) { + $testVal3 = strtok('- '); + if ($testVal3 === False) { + $testVal3 = strftime('%Y'); + } + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + $PHPDateArray = date_parse($testVal1.'-'.$testVal2.'-'.$testVal3); + if (($PHPDateArray === False) || ($PHPDateArray['error_count'] > 0)) { + $PHPDateArray = date_parse($testVal2.'-'.$testVal1.'-'.$testVal3); + if (($PHPDateArray === False) || ($PHPDateArray['error_count'] > 0)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + } + + if (($PHPDateArray !== False) && ($PHPDateArray['error_count'] == 0)) { + // Execute function + if ($PHPDateArray['year'] == '') { $PHPDateArray['year'] = strftime('%Y'); } + if ($PHPDateArray['year'] < 1900) + return PHPExcel_Calculation_Functions::VALUE(); + if ($PHPDateArray['month'] == '') { $PHPDateArray['month'] = strftime('%m'); } + if ($PHPDateArray['day'] == '') { $PHPDateArray['day'] = strftime('%d'); } + $excelDateValue = floor(PHPExcel_Shared_Date::FormattedPHPToExcel($PHPDateArray['year'],$PHPDateArray['month'],$PHPDateArray['day'],$PHPDateArray['hour'],$PHPDateArray['minute'],$PHPDateArray['second'])); + + switch (PHPExcel_Calculation_Functions::getReturnDateType()) { + case PHPExcel_Calculation_Functions::RETURNDATE_EXCEL : + return (float) $excelDateValue; + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC : + return (integer) PHPExcel_Shared_Date::ExcelToPHP($excelDateValue); + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT : + return new DateTime($PHPDateArray['year'].'-'.$PHPDateArray['month'].'-'.$PHPDateArray['day'].' 00:00:00'); + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function DATEVALUE() + + + /** + * TIMEVALUE + * + * Returns a value that represents a particular time. + * Use TIMEVALUE to convert a time represented by a text string to an Excel or PHP date/time stamp + * value. + * + * NOTE: When used in a Cell Formula, MS Excel changes the cell format so that it matches the time + * format of your regional settings. PHPExcel does not change cell formatting in this way. + * + * Excel Function: + * TIMEVALUE(timeValue) + * + * @access public + * @category Date/Time Functions + * @param string $timeValue A text string that represents a time in any one of the Microsoft + * Excel time formats; for example, "6:45 PM" and "18:45" text strings + * within quotation marks that represent time. + * Date information in time_text is ignored. + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function TIMEVALUE($timeValue) { + $timeValue = trim(PHPExcel_Calculation_Functions::flattenSingleValue($timeValue),'"'); + $timeValue = str_replace(array('/','.'),array('-','-'),$timeValue); + + $PHPDateArray = date_parse($timeValue); + if (($PHPDateArray !== False) && ($PHPDateArray['error_count'] == 0)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + $excelDateValue = PHPExcel_Shared_Date::FormattedPHPToExcel($PHPDateArray['year'],$PHPDateArray['month'],$PHPDateArray['day'],$PHPDateArray['hour'],$PHPDateArray['minute'],$PHPDateArray['second']); + } else { + $excelDateValue = PHPExcel_Shared_Date::FormattedPHPToExcel(1900,1,1,$PHPDateArray['hour'],$PHPDateArray['minute'],$PHPDateArray['second']) - 1; + } + + switch (PHPExcel_Calculation_Functions::getReturnDateType()) { + case PHPExcel_Calculation_Functions::RETURNDATE_EXCEL : + return (float) $excelDateValue; + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC : + return (integer) $phpDateValue = PHPExcel_Shared_Date::ExcelToPHP($excelDateValue+25569) - 3600;; + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT : + return new DateTime('1900-01-01 '.$PHPDateArray['hour'].':'.$PHPDateArray['minute'].':'.$PHPDateArray['second']); + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function TIMEVALUE() + + + /** + * DATEDIF + * + * @param mixed $startDate Excel date serial value, PHP date/time stamp, PHP DateTime object + * or a standard date string + * @param mixed $endDate Excel date serial value, PHP date/time stamp, PHP DateTime object + * or a standard date string + * @param string $unit + * @return integer Interval between the dates + */ + public static function DATEDIF($startDate = 0, $endDate = 0, $unit = 'D') { + $startDate = PHPExcel_Calculation_Functions::flattenSingleValue($startDate); + $endDate = PHPExcel_Calculation_Functions::flattenSingleValue($endDate); + $unit = strtoupper(PHPExcel_Calculation_Functions::flattenSingleValue($unit)); + + if (is_string($startDate = self::_getDateValue($startDate))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (is_string($endDate = self::_getDateValue($endDate))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + // Validate parameters + if ($startDate >= $endDate) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Execute function + $difference = $endDate - $startDate; + + $PHPStartDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($startDate); + $startDays = $PHPStartDateObject->format('j'); + $startMonths = $PHPStartDateObject->format('n'); + $startYears = $PHPStartDateObject->format('Y'); + + $PHPEndDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($endDate); + $endDays = $PHPEndDateObject->format('j'); + $endMonths = $PHPEndDateObject->format('n'); + $endYears = $PHPEndDateObject->format('Y'); + + $retVal = PHPExcel_Calculation_Functions::NaN(); + switch ($unit) { + case 'D': + $retVal = intval($difference); + break; + case 'M': + $retVal = intval($endMonths - $startMonths) + (intval($endYears - $startYears) * 12); + // We're only interested in full months + if ($endDays < $startDays) { + --$retVal; + } + break; + case 'Y': + $retVal = intval($endYears - $startYears); + // We're only interested in full months + if ($endMonths < $startMonths) { + --$retVal; + } elseif (($endMonths == $startMonths) && ($endDays < $startDays)) { + --$retVal; + } + break; + case 'MD': + if ($endDays < $startDays) { + $retVal = $endDays; + $PHPEndDateObject->modify('-'.$endDays.' days'); + $adjustDays = $PHPEndDateObject->format('j'); + if ($adjustDays > $startDays) { + $retVal += ($adjustDays - $startDays); + } + } else { + $retVal = $endDays - $startDays; + } + break; + case 'YM': + $retVal = intval($endMonths - $startMonths); + if ($retVal < 0) $retVal = 12 + $retVal; + // We're only interested in full months + if ($endDays < $startDays) { + --$retVal; + } + break; + case 'YD': + $retVal = intval($difference); + if ($endYears > $startYears) { + while ($endYears > $startYears) { + $PHPEndDateObject->modify('-1 year'); + $endYears = $PHPEndDateObject->format('Y'); + } + $retVal = $PHPEndDateObject->format('z') - $PHPStartDateObject->format('z'); + if ($retVal < 0) { $retVal += 365; } + } + break; + default: + $retVal = PHPExcel_Calculation_Functions::NaN(); + } + return $retVal; + } // function DATEDIF() + + + /** + * DAYS360 + * + * Returns the number of days between two dates based on a 360-day year (twelve 30-day months), + * which is used in some accounting calculations. Use this function to help compute payments if + * your accounting system is based on twelve 30-day months. + * + * Excel Function: + * DAYS360(startDate,endDate[,method]) + * + * @access public + * @category Date/Time Functions + * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param boolean $method US or European Method + * FALSE or omitted: U.S. (NASD) method. If the starting date is + * the last day of a month, it becomes equal to the 30th of the + * same month. If the ending date is the last day of a month and + * the starting date is earlier than the 30th of a month, the + * ending date becomes equal to the 1st of the next month; + * otherwise the ending date becomes equal to the 30th of the + * same month. + * TRUE: European method. Starting dates and ending dates that + * occur on the 31st of a month become equal to the 30th of the + * same month. + * @return integer Number of days between start date and end date + */ + public static function DAYS360($startDate = 0, $endDate = 0, $method = false) { + $startDate = PHPExcel_Calculation_Functions::flattenSingleValue($startDate); + $endDate = PHPExcel_Calculation_Functions::flattenSingleValue($endDate); + + if (is_string($startDate = self::_getDateValue($startDate))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (is_string($endDate = self::_getDateValue($endDate))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (!is_bool($method)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + // Execute function + $PHPStartDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($startDate); + $startDay = $PHPStartDateObject->format('j'); + $startMonth = $PHPStartDateObject->format('n'); + $startYear = $PHPStartDateObject->format('Y'); + + $PHPEndDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($endDate); + $endDay = $PHPEndDateObject->format('j'); + $endMonth = $PHPEndDateObject->format('n'); + $endYear = $PHPEndDateObject->format('Y'); + + return self::_dateDiff360($startDay, $startMonth, $startYear, $endDay, $endMonth, $endYear, !$method); + } // function DAYS360() + + + /** + * YEARFRAC + * + * Calculates the fraction of the year represented by the number of whole days between two dates + * (the start_date and the end_date). + * Use the YEARFRAC worksheet function to identify the proportion of a whole year's benefits or + * obligations to assign to a specific term. + * + * Excel Function: + * YEARFRAC(startDate,endDate[,method]) + * + * @access public + * @category Date/Time Functions + * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param integer $method Method used for the calculation + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float fraction of the year + */ + public static function YEARFRAC($startDate = 0, $endDate = 0, $method = 0) { + $startDate = PHPExcel_Calculation_Functions::flattenSingleValue($startDate); + $endDate = PHPExcel_Calculation_Functions::flattenSingleValue($endDate); + $method = PHPExcel_Calculation_Functions::flattenSingleValue($method); + + if (is_string($startDate = self::_getDateValue($startDate))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (is_string($endDate = self::_getDateValue($endDate))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (((is_numeric($method)) && (!is_string($method))) || ($method == '')) { + switch($method) { + case 0 : + return self::DAYS360($startDate,$endDate) / 360; + case 1 : + $days = self::DATEDIF($startDate,$endDate); + $startYear = self::YEAR($startDate); + $endYear = self::YEAR($endDate); + $years = $endYear - $startYear + 1; + $leapDays = 0; + if ($years == 1) { + if (self::_isLeapYear($endYear)) { + $startMonth = self::MONTHOFYEAR($startDate); + $endMonth = self::MONTHOFYEAR($endDate); + $endDay = self::DAYOFMONTH($endDate); + if (($startMonth < 3) || + (($endMonth * 100 + $endDay) >= (2 * 100 + 29))) { + $leapDays += 1; + } + } + } else { + for($year = $startYear; $year <= $endYear; ++$year) { + if ($year == $startYear) { + $startMonth = self::MONTHOFYEAR($startDate); + $startDay = self::DAYOFMONTH($startDate); + if ($startMonth < 3) { + $leapDays += (self::_isLeapYear($year)) ? 1 : 0; + } + } elseif($year == $endYear) { + $endMonth = self::MONTHOFYEAR($endDate); + $endDay = self::DAYOFMONTH($endDate); + if (($endMonth * 100 + $endDay) >= (2 * 100 + 29)) { + $leapDays += (self::_isLeapYear($year)) ? 1 : 0; + } + } else { + $leapDays += (self::_isLeapYear($year)) ? 1 : 0; + } + } + if ($years == 2) { + if (($leapDays == 0) && (self::_isLeapYear($startYear)) && ($days > 365)) { + $leapDays = 1; + } elseif ($days < 366) { + $years = 1; + } + } + $leapDays /= $years; + } + return $days / (365 + $leapDays); + case 2 : + return self::DATEDIF($startDate,$endDate) / 360; + case 3 : + return self::DATEDIF($startDate,$endDate) / 365; + case 4 : + return self::DAYS360($startDate,$endDate,True) / 360; + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function YEARFRAC() + + + /** + * NETWORKDAYS + * + * Returns the number of whole working days between start_date and end_date. Working days + * exclude weekends and any dates identified in holidays. + * Use NETWORKDAYS to calculate employee benefits that accrue based on the number of days + * worked during a specific term. + * + * Excel Function: + * NETWORKDAYS(startDate,endDate[,holidays[,holiday[,...]]]) + * + * @access public + * @category Date/Time Functions + * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param mixed $holidays,... Optional series of Excel date serial value (float), PHP date + * timestamp (integer), PHP DateTime object, or a standard date + * strings that will be excluded from the working calendar, such + * as state and federal holidays and floating holidays. + * @return integer Interval between the dates + */ + public static function NETWORKDAYS($startDate,$endDate) { + // Retrieve the mandatory start and end date that are referenced in the function definition + $startDate = PHPExcel_Calculation_Functions::flattenSingleValue($startDate); + $endDate = PHPExcel_Calculation_Functions::flattenSingleValue($endDate); + // Flush the mandatory start and end date that are referenced in the function definition, and get the optional days + $dateArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + array_shift($dateArgs); + array_shift($dateArgs); + + // Validate the start and end dates + if (is_string($startDate = $sDate = self::_getDateValue($startDate))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $startDate = (float) floor($startDate); + if (is_string($endDate = $eDate = self::_getDateValue($endDate))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $endDate = (float) floor($endDate); + + if ($sDate > $eDate) { + $startDate = $eDate; + $endDate = $sDate; + } + + // Execute function + $startDoW = 6 - self::DAYOFWEEK($startDate,2); + if ($startDoW < 0) { $startDoW = 0; } + $endDoW = self::DAYOFWEEK($endDate,2); + if ($endDoW >= 6) { $endDoW = 0; } + + $wholeWeekDays = floor(($endDate - $startDate) / 7) * 5; + $partWeekDays = $endDoW + $startDoW; + if ($partWeekDays > 5) { + $partWeekDays -= 5; + } + + // Test any extra holiday parameters + $holidayCountedArray = array(); + foreach ($dateArgs as $holidayDate) { + if (is_string($holidayDate = self::_getDateValue($holidayDate))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (($holidayDate >= $startDate) && ($holidayDate <= $endDate)) { + if ((self::DAYOFWEEK($holidayDate,2) < 6) && (!in_array($holidayDate,$holidayCountedArray))) { + --$partWeekDays; + $holidayCountedArray[] = $holidayDate; + } + } + } + + if ($sDate > $eDate) { + return 0 - ($wholeWeekDays + $partWeekDays); + } + return $wholeWeekDays + $partWeekDays; + } // function NETWORKDAYS() + + + /** + * WORKDAY + * + * Returns the date that is the indicated number of working days before or after a date (the + * starting date). Working days exclude weekends and any dates identified as holidays. + * Use WORKDAY to exclude weekends or holidays when you calculate invoice due dates, expected + * delivery times, or the number of days of work performed. + * + * Excel Function: + * WORKDAY(startDate,endDays[,holidays[,holiday[,...]]]) + * + * @access public + * @category Date/Time Functions + * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param integer $endDays The number of nonweekend and nonholiday days before or after + * startDate. A positive value for days yields a future date; a + * negative value yields a past date. + * @param mixed $holidays,... Optional series of Excel date serial value (float), PHP date + * timestamp (integer), PHP DateTime object, or a standard date + * strings that will be excluded from the working calendar, such + * as state and federal holidays and floating holidays. + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function WORKDAY($startDate,$endDays) { + // Retrieve the mandatory start date and days that are referenced in the function definition + $startDate = PHPExcel_Calculation_Functions::flattenSingleValue($startDate); + $endDays = PHPExcel_Calculation_Functions::flattenSingleValue($endDays); + // Flush the mandatory start date and days that are referenced in the function definition, and get the optional days + $dateArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + array_shift($dateArgs); + array_shift($dateArgs); + + if ((is_string($startDate = self::_getDateValue($startDate))) || (!is_numeric($endDays))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $startDate = (float) floor($startDate); + $endDays = (int) floor($endDays); + // If endDays is 0, we always return startDate + if ($endDays == 0) { return $startDate; } + + $decrementing = ($endDays < 0) ? True : False; + + // Adjust the start date if it falls over a weekend + + $startDoW = self::DAYOFWEEK($startDate,3); + if (self::DAYOFWEEK($startDate,3) >= 5) { + $startDate += ($decrementing) ? -$startDoW + 4: 7 - $startDoW; + ($decrementing) ? $endDays++ : $endDays--; + } + + // Add endDays + $endDate = (float) $startDate + (intval($endDays / 5) * 7) + ($endDays % 5); + + // Adjust the calculated end date if it falls over a weekend + $endDoW = self::DAYOFWEEK($endDate,3); + if ($endDoW >= 5) { + $endDate += ($decrementing) ? -$endDoW + 4: 7 - $endDoW; + } + + // Test any extra holiday parameters + if (!empty($dateArgs)) { + $holidayCountedArray = $holidayDates = array(); + foreach ($dateArgs as $holidayDate) { + if (($holidayDate !== NULL) && (trim($holidayDate) > '')) { + if (is_string($holidayDate = self::_getDateValue($holidayDate))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (self::DAYOFWEEK($holidayDate,3) < 5) { + $holidayDates[] = $holidayDate; + } + } + } + if ($decrementing) { + rsort($holidayDates, SORT_NUMERIC); + } else { + sort($holidayDates, SORT_NUMERIC); + } + foreach ($holidayDates as $holidayDate) { + if ($decrementing) { + if (($holidayDate <= $startDate) && ($holidayDate >= $endDate)) { + if (!in_array($holidayDate,$holidayCountedArray)) { + --$endDate; + $holidayCountedArray[] = $holidayDate; + } + } + } else { + if (($holidayDate >= $startDate) && ($holidayDate <= $endDate)) { + if (!in_array($holidayDate,$holidayCountedArray)) { + ++$endDate; + $holidayCountedArray[] = $holidayDate; + } + } + } + // Adjust the calculated end date if it falls over a weekend + $endDoW = self::DAYOFWEEK($endDate,3); + if ($endDoW >= 5) { + $endDate += ($decrementing) ? -$endDoW + 4: 7 - $endDoW; + } + + } + } + + switch (PHPExcel_Calculation_Functions::getReturnDateType()) { + case PHPExcel_Calculation_Functions::RETURNDATE_EXCEL : + return (float) $endDate; + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC : + return (integer) PHPExcel_Shared_Date::ExcelToPHP($endDate); + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT : + return PHPExcel_Shared_Date::ExcelToPHPObject($endDate); + } + } // function WORKDAY() + + + /** + * DAYOFMONTH + * + * Returns the day of the month, for a specified date. The day is given as an integer + * ranging from 1 to 31. + * + * Excel Function: + * DAY(dateValue) + * + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @return int Day of the month + */ + public static function DAYOFMONTH($dateValue = 1) { + $dateValue = PHPExcel_Calculation_Functions::flattenSingleValue($dateValue); + + if (is_string($dateValue = self::_getDateValue($dateValue))) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif ($dateValue == 0.0) { + return 0; + } elseif ($dateValue < 0.0) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Execute function + $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); + + return (int) $PHPDateObject->format('j'); + } // function DAYOFMONTH() + + + /** + * DAYOFWEEK + * + * Returns the day of the week for a specified date. The day is given as an integer + * ranging from 0 to 7 (dependent on the requested style). + * + * Excel Function: + * WEEKDAY(dateValue[,style]) + * + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param int $style A number that determines the type of return value + * 1 or omitted Numbers 1 (Sunday) through 7 (Saturday). + * 2 Numbers 1 (Monday) through 7 (Sunday). + * 3 Numbers 0 (Monday) through 6 (Sunday). + * @return int Day of the week value + */ + public static function DAYOFWEEK($dateValue = 1, $style = 1) { + $dateValue = PHPExcel_Calculation_Functions::flattenSingleValue($dateValue); + $style = PHPExcel_Calculation_Functions::flattenSingleValue($style); + + if (!is_numeric($style)) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif (($style < 1) || ($style > 3)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $style = floor($style); + + if (is_string($dateValue = self::_getDateValue($dateValue))) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif ($dateValue < 0.0) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Execute function + $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); + $DoW = $PHPDateObject->format('w'); + + $firstDay = 1; + switch ($style) { + case 1: ++$DoW; + break; + case 2: if ($DoW == 0) { $DoW = 7; } + break; + case 3: if ($DoW == 0) { $DoW = 7; } + $firstDay = 0; + --$DoW; + break; + } + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL) { + // Test for Excel's 1900 leap year, and introduce the error as required + if (($PHPDateObject->format('Y') == 1900) && ($PHPDateObject->format('n') <= 2)) { + --$DoW; + if ($DoW < $firstDay) { + $DoW += 7; + } + } + } + + return (int) $DoW; + } // function DAYOFWEEK() + + + /** + * WEEKOFYEAR + * + * Returns the week of the year for a specified date. + * The WEEKNUM function considers the week containing January 1 to be the first week of the year. + * However, there is a European standard that defines the first week as the one with the majority + * of days (four or more) falling in the new year. This means that for years in which there are + * three days or less in the first week of January, the WEEKNUM function returns week numbers + * that are incorrect according to the European standard. + * + * Excel Function: + * WEEKNUM(dateValue[,style]) + * + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param boolean $method Week begins on Sunday or Monday + * 1 or omitted Week begins on Sunday. + * 2 Week begins on Monday. + * @return int Week Number + */ + public static function WEEKOFYEAR($dateValue = 1, $method = 1) { + $dateValue = PHPExcel_Calculation_Functions::flattenSingleValue($dateValue); + $method = PHPExcel_Calculation_Functions::flattenSingleValue($method); + + if (!is_numeric($method)) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif (($method < 1) || ($method > 2)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $method = floor($method); + + if (is_string($dateValue = self::_getDateValue($dateValue))) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif ($dateValue < 0.0) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Execute function + $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); + $dayOfYear = $PHPDateObject->format('z'); + $dow = $PHPDateObject->format('w'); + $PHPDateObject->modify('-'.$dayOfYear.' days'); + $dow = $PHPDateObject->format('w'); + $daysInFirstWeek = 7 - (($dow + (2 - $method)) % 7); + $dayOfYear -= $daysInFirstWeek; + $weekOfYear = ceil($dayOfYear / 7) + 1; + + return (int) $weekOfYear; + } // function WEEKOFYEAR() + + + /** + * MONTHOFYEAR + * + * Returns the month of a date represented by a serial number. + * The month is given as an integer, ranging from 1 (January) to 12 (December). + * + * Excel Function: + * MONTH(dateValue) + * + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @return int Month of the year + */ + public static function MONTHOFYEAR($dateValue = 1) { + $dateValue = PHPExcel_Calculation_Functions::flattenSingleValue($dateValue); + + if (is_string($dateValue = self::_getDateValue($dateValue))) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif ($dateValue < 0.0) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Execute function + $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); + + return (int) $PHPDateObject->format('n'); + } // function MONTHOFYEAR() + + + /** + * YEAR + * + * Returns the year corresponding to a date. + * The year is returned as an integer in the range 1900-9999. + * + * Excel Function: + * YEAR(dateValue) + * + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @return int Year + */ + public static function YEAR($dateValue = 1) { + $dateValue = PHPExcel_Calculation_Functions::flattenSingleValue($dateValue); + + if (is_string($dateValue = self::_getDateValue($dateValue))) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif ($dateValue < 0.0) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Execute function + $PHPDateObject = PHPExcel_Shared_Date::ExcelToPHPObject($dateValue); + + return (int) $PHPDateObject->format('Y'); + } // function YEAR() + + + /** + * HOUROFDAY + * + * Returns the hour of a time value. + * The hour is given as an integer, ranging from 0 (12:00 A.M.) to 23 (11:00 P.M.). + * + * Excel Function: + * HOUR(timeValue) + * + * @param mixed $timeValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard time string + * @return int Hour + */ + public static function HOUROFDAY($timeValue = 0) { + $timeValue = PHPExcel_Calculation_Functions::flattenSingleValue($timeValue); + + if (!is_numeric($timeValue)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) { + $testVal = strtok($timeValue,'/-: '); + if (strlen($testVal) < strlen($timeValue)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + $timeValue = self::_getTimeValue($timeValue); + if (is_string($timeValue)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + // Execute function + if ($timeValue >= 1) { + $timeValue = fmod($timeValue,1); + } elseif ($timeValue < 0.0) { + return PHPExcel_Calculation_Functions::NaN(); + } + $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + + return (int) gmdate('G',$timeValue); + } // function HOUROFDAY() + + + /** + * MINUTEOFHOUR + * + * Returns the minutes of a time value. + * The minute is given as an integer, ranging from 0 to 59. + * + * Excel Function: + * MINUTE(timeValue) + * + * @param mixed $timeValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard time string + * @return int Minute + */ + public static function MINUTEOFHOUR($timeValue = 0) { + $timeValue = $timeTester = PHPExcel_Calculation_Functions::flattenSingleValue($timeValue); + + if (!is_numeric($timeValue)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) { + $testVal = strtok($timeValue,'/-: '); + if (strlen($testVal) < strlen($timeValue)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + $timeValue = self::_getTimeValue($timeValue); + if (is_string($timeValue)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + // Execute function + if ($timeValue >= 1) { + $timeValue = fmod($timeValue,1); + } elseif ($timeValue < 0.0) { + return PHPExcel_Calculation_Functions::NaN(); + } + $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + + return (int) gmdate('i',$timeValue); + } // function MINUTEOFHOUR() + + + /** + * SECONDOFMINUTE + * + * Returns the seconds of a time value. + * The second is given as an integer in the range 0 (zero) to 59. + * + * Excel Function: + * SECOND(timeValue) + * + * @param mixed $timeValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard time string + * @return int Second + */ + public static function SECONDOFMINUTE($timeValue = 0) { + $timeValue = PHPExcel_Calculation_Functions::flattenSingleValue($timeValue); + + if (!is_numeric($timeValue)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) { + $testVal = strtok($timeValue,'/-: '); + if (strlen($testVal) < strlen($timeValue)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + $timeValue = self::_getTimeValue($timeValue); + if (is_string($timeValue)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + // Execute function + if ($timeValue >= 1) { + $timeValue = fmod($timeValue,1); + } elseif ($timeValue < 0.0) { + return PHPExcel_Calculation_Functions::NaN(); + } + $timeValue = PHPExcel_Shared_Date::ExcelToPHP($timeValue); + + return (int) gmdate('s',$timeValue); + } // function SECONDOFMINUTE() + + + /** + * EDATE + * + * Returns the serial number that represents the date that is the indicated number of months + * before or after a specified date (the start_date). + * Use EDATE to calculate maturity dates or due dates that fall on the same day of the month + * as the date of issue. + * + * Excel Function: + * EDATE(dateValue,adjustmentMonths) + * + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param int $adjustmentMonths The number of months before or after start_date. + * A positive value for months yields a future date; + * a negative value yields a past date. + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function EDATE($dateValue = 1, $adjustmentMonths = 0) { + $dateValue = PHPExcel_Calculation_Functions::flattenSingleValue($dateValue); + $adjustmentMonths = PHPExcel_Calculation_Functions::flattenSingleValue($adjustmentMonths); + + if (!is_numeric($adjustmentMonths)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $adjustmentMonths = floor($adjustmentMonths); + + if (is_string($dateValue = self::_getDateValue($dateValue))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + // Execute function + $PHPDateObject = self::_adjustDateByMonths($dateValue,$adjustmentMonths); + + switch (PHPExcel_Calculation_Functions::getReturnDateType()) { + case PHPExcel_Calculation_Functions::RETURNDATE_EXCEL : + return (float) PHPExcel_Shared_Date::PHPToExcel($PHPDateObject); + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC : + return (integer) PHPExcel_Shared_Date::ExcelToPHP(PHPExcel_Shared_Date::PHPToExcel($PHPDateObject)); + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT : + return $PHPDateObject; + } + } // function EDATE() + + + /** + * EOMONTH + * + * Returns the date value for the last day of the month that is the indicated number of months + * before or after start_date. + * Use EOMONTH to calculate maturity dates or due dates that fall on the last day of the month. + * + * Excel Function: + * EOMONTH(dateValue,adjustmentMonths) + * + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param int $adjustmentMonths The number of months before or after start_date. + * A positive value for months yields a future date; + * a negative value yields a past date. + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function EOMONTH($dateValue = 1, $adjustmentMonths = 0) { + $dateValue = PHPExcel_Calculation_Functions::flattenSingleValue($dateValue); + $adjustmentMonths = PHPExcel_Calculation_Functions::flattenSingleValue($adjustmentMonths); + + if (!is_numeric($adjustmentMonths)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $adjustmentMonths = floor($adjustmentMonths); + + if (is_string($dateValue = self::_getDateValue($dateValue))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + // Execute function + $PHPDateObject = self::_adjustDateByMonths($dateValue,$adjustmentMonths+1); + $adjustDays = (int) $PHPDateObject->format('d'); + $adjustDaysString = '-'.$adjustDays.' days'; + $PHPDateObject->modify($adjustDaysString); + + switch (PHPExcel_Calculation_Functions::getReturnDateType()) { + case PHPExcel_Calculation_Functions::RETURNDATE_EXCEL : + return (float) PHPExcel_Shared_Date::PHPToExcel($PHPDateObject); + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC : + return (integer) PHPExcel_Shared_Date::ExcelToPHP(PHPExcel_Shared_Date::PHPToExcel($PHPDateObject)); + case PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT : + return $PHPDateObject; + } + } // function EOMONTH() + +} // class PHPExcel_Calculation_DateTime + diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Engineering.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Engineering.php new file mode 100755 index 0000000..340ce32 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Engineering.php @@ -0,0 +1,2505 @@ + array( 'Group' => 'Mass', 'Unit Name' => 'Gram', 'AllowPrefix' => True ), + 'sg' => array( 'Group' => 'Mass', 'Unit Name' => 'Slug', 'AllowPrefix' => False ), + 'lbm' => array( 'Group' => 'Mass', 'Unit Name' => 'Pound mass (avoirdupois)', 'AllowPrefix' => False ), + 'u' => array( 'Group' => 'Mass', 'Unit Name' => 'U (atomic mass unit)', 'AllowPrefix' => True ), + 'ozm' => array( 'Group' => 'Mass', 'Unit Name' => 'Ounce mass (avoirdupois)', 'AllowPrefix' => False ), + 'm' => array( 'Group' => 'Distance', 'Unit Name' => 'Meter', 'AllowPrefix' => True ), + 'mi' => array( 'Group' => 'Distance', 'Unit Name' => 'Statute mile', 'AllowPrefix' => False ), + 'Nmi' => array( 'Group' => 'Distance', 'Unit Name' => 'Nautical mile', 'AllowPrefix' => False ), + 'in' => array( 'Group' => 'Distance', 'Unit Name' => 'Inch', 'AllowPrefix' => False ), + 'ft' => array( 'Group' => 'Distance', 'Unit Name' => 'Foot', 'AllowPrefix' => False ), + 'yd' => array( 'Group' => 'Distance', 'Unit Name' => 'Yard', 'AllowPrefix' => False ), + 'ang' => array( 'Group' => 'Distance', 'Unit Name' => 'Angstrom', 'AllowPrefix' => True ), + 'Pica' => array( 'Group' => 'Distance', 'Unit Name' => 'Pica (1/72 in)', 'AllowPrefix' => False ), + 'yr' => array( 'Group' => 'Time', 'Unit Name' => 'Year', 'AllowPrefix' => False ), + 'day' => array( 'Group' => 'Time', 'Unit Name' => 'Day', 'AllowPrefix' => False ), + 'hr' => array( 'Group' => 'Time', 'Unit Name' => 'Hour', 'AllowPrefix' => False ), + 'mn' => array( 'Group' => 'Time', 'Unit Name' => 'Minute', 'AllowPrefix' => False ), + 'sec' => array( 'Group' => 'Time', 'Unit Name' => 'Second', 'AllowPrefix' => True ), + 'Pa' => array( 'Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => True ), + 'p' => array( 'Group' => 'Pressure', 'Unit Name' => 'Pascal', 'AllowPrefix' => True ), + 'atm' => array( 'Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => True ), + 'at' => array( 'Group' => 'Pressure', 'Unit Name' => 'Atmosphere', 'AllowPrefix' => True ), + 'mmHg' => array( 'Group' => 'Pressure', 'Unit Name' => 'mm of Mercury', 'AllowPrefix' => True ), + 'N' => array( 'Group' => 'Force', 'Unit Name' => 'Newton', 'AllowPrefix' => True ), + 'dyn' => array( 'Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => True ), + 'dy' => array( 'Group' => 'Force', 'Unit Name' => 'Dyne', 'AllowPrefix' => True ), + 'lbf' => array( 'Group' => 'Force', 'Unit Name' => 'Pound force', 'AllowPrefix' => False ), + 'J' => array( 'Group' => 'Energy', 'Unit Name' => 'Joule', 'AllowPrefix' => True ), + 'e' => array( 'Group' => 'Energy', 'Unit Name' => 'Erg', 'AllowPrefix' => True ), + 'c' => array( 'Group' => 'Energy', 'Unit Name' => 'Thermodynamic calorie', 'AllowPrefix' => True ), + 'cal' => array( 'Group' => 'Energy', 'Unit Name' => 'IT calorie', 'AllowPrefix' => True ), + 'eV' => array( 'Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => True ), + 'ev' => array( 'Group' => 'Energy', 'Unit Name' => 'Electron volt', 'AllowPrefix' => True ), + 'HPh' => array( 'Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => False ), + 'hh' => array( 'Group' => 'Energy', 'Unit Name' => 'Horsepower-hour', 'AllowPrefix' => False ), + 'Wh' => array( 'Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => True ), + 'wh' => array( 'Group' => 'Energy', 'Unit Name' => 'Watt-hour', 'AllowPrefix' => True ), + 'flb' => array( 'Group' => 'Energy', 'Unit Name' => 'Foot-pound', 'AllowPrefix' => False ), + 'BTU' => array( 'Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => False ), + 'btu' => array( 'Group' => 'Energy', 'Unit Name' => 'BTU', 'AllowPrefix' => False ), + 'HP' => array( 'Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => False ), + 'h' => array( 'Group' => 'Power', 'Unit Name' => 'Horsepower', 'AllowPrefix' => False ), + 'W' => array( 'Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => True ), + 'w' => array( 'Group' => 'Power', 'Unit Name' => 'Watt', 'AllowPrefix' => True ), + 'T' => array( 'Group' => 'Magnetism', 'Unit Name' => 'Tesla', 'AllowPrefix' => True ), + 'ga' => array( 'Group' => 'Magnetism', 'Unit Name' => 'Gauss', 'AllowPrefix' => True ), + 'C' => array( 'Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => False ), + 'cel' => array( 'Group' => 'Temperature', 'Unit Name' => 'Celsius', 'AllowPrefix' => False ), + 'F' => array( 'Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => False ), + 'fah' => array( 'Group' => 'Temperature', 'Unit Name' => 'Fahrenheit', 'AllowPrefix' => False ), + 'K' => array( 'Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => False ), + 'kel' => array( 'Group' => 'Temperature', 'Unit Name' => 'Kelvin', 'AllowPrefix' => False ), + 'tsp' => array( 'Group' => 'Liquid', 'Unit Name' => 'Teaspoon', 'AllowPrefix' => False ), + 'tbs' => array( 'Group' => 'Liquid', 'Unit Name' => 'Tablespoon', 'AllowPrefix' => False ), + 'oz' => array( 'Group' => 'Liquid', 'Unit Name' => 'Fluid Ounce', 'AllowPrefix' => False ), + 'cup' => array( 'Group' => 'Liquid', 'Unit Name' => 'Cup', 'AllowPrefix' => False ), + 'pt' => array( 'Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => False ), + 'us_pt' => array( 'Group' => 'Liquid', 'Unit Name' => 'U.S. Pint', 'AllowPrefix' => False ), + 'uk_pt' => array( 'Group' => 'Liquid', 'Unit Name' => 'U.K. Pint', 'AllowPrefix' => False ), + 'qt' => array( 'Group' => 'Liquid', 'Unit Name' => 'Quart', 'AllowPrefix' => False ), + 'gal' => array( 'Group' => 'Liquid', 'Unit Name' => 'Gallon', 'AllowPrefix' => False ), + 'l' => array( 'Group' => 'Liquid', 'Unit Name' => 'Litre', 'AllowPrefix' => True ), + 'lt' => array( 'Group' => 'Liquid', 'Unit Name' => 'Litre', 'AllowPrefix' => True ) + ); + + /** + * Details of the Multiplier prefixes that can be used with Units of Measure in CONVERTUOM() + * + * @var mixed[] + */ + private static $_conversionMultipliers = array( 'Y' => array( 'multiplier' => 1E24, 'name' => 'yotta' ), + 'Z' => array( 'multiplier' => 1E21, 'name' => 'zetta' ), + 'E' => array( 'multiplier' => 1E18, 'name' => 'exa' ), + 'P' => array( 'multiplier' => 1E15, 'name' => 'peta' ), + 'T' => array( 'multiplier' => 1E12, 'name' => 'tera' ), + 'G' => array( 'multiplier' => 1E9, 'name' => 'giga' ), + 'M' => array( 'multiplier' => 1E6, 'name' => 'mega' ), + 'k' => array( 'multiplier' => 1E3, 'name' => 'kilo' ), + 'h' => array( 'multiplier' => 1E2, 'name' => 'hecto' ), + 'e' => array( 'multiplier' => 1E1, 'name' => 'deka' ), + 'd' => array( 'multiplier' => 1E-1, 'name' => 'deci' ), + 'c' => array( 'multiplier' => 1E-2, 'name' => 'centi' ), + 'm' => array( 'multiplier' => 1E-3, 'name' => 'milli' ), + 'u' => array( 'multiplier' => 1E-6, 'name' => 'micro' ), + 'n' => array( 'multiplier' => 1E-9, 'name' => 'nano' ), + 'p' => array( 'multiplier' => 1E-12, 'name' => 'pico' ), + 'f' => array( 'multiplier' => 1E-15, 'name' => 'femto' ), + 'a' => array( 'multiplier' => 1E-18, 'name' => 'atto' ), + 'z' => array( 'multiplier' => 1E-21, 'name' => 'zepto' ), + 'y' => array( 'multiplier' => 1E-24, 'name' => 'yocto' ) + ); + + /** + * Details of the Units of measure conversion factors, organised by group + * + * @var mixed[] + */ + private static $_unitConversions = array( 'Mass' => array( 'g' => array( 'g' => 1.0, + 'sg' => 6.85220500053478E-05, + 'lbm' => 2.20462291469134E-03, + 'u' => 6.02217000000000E+23, + 'ozm' => 3.52739718003627E-02 + ), + 'sg' => array( 'g' => 1.45938424189287E+04, + 'sg' => 1.0, + 'lbm' => 3.21739194101647E+01, + 'u' => 8.78866000000000E+27, + 'ozm' => 5.14782785944229E+02 + ), + 'lbm' => array( 'g' => 4.5359230974881148E+02, + 'sg' => 3.10810749306493E-02, + 'lbm' => 1.0, + 'u' => 2.73161000000000E+26, + 'ozm' => 1.60000023429410E+01 + ), + 'u' => array( 'g' => 1.66053100460465E-24, + 'sg' => 1.13782988532950E-28, + 'lbm' => 3.66084470330684E-27, + 'u' => 1.0, + 'ozm' => 5.85735238300524E-26 + ), + 'ozm' => array( 'g' => 2.83495152079732E+01, + 'sg' => 1.94256689870811E-03, + 'lbm' => 6.24999908478882E-02, + 'u' => 1.70725600000000E+25, + 'ozm' => 1.0 + ) + ), + 'Distance' => array( 'm' => array( 'm' => 1.0, + 'mi' => 6.21371192237334E-04, + 'Nmi' => 5.39956803455724E-04, + 'in' => 3.93700787401575E+01, + 'ft' => 3.28083989501312E+00, + 'yd' => 1.09361329797891E+00, + 'ang' => 1.00000000000000E+10, + 'Pica' => 2.83464566929116E+03 + ), + 'mi' => array( 'm' => 1.60934400000000E+03, + 'mi' => 1.0, + 'Nmi' => 8.68976241900648E-01, + 'in' => 6.33600000000000E+04, + 'ft' => 5.28000000000000E+03, + 'yd' => 1.76000000000000E+03, + 'ang' => 1.60934400000000E+13, + 'Pica' => 4.56191999999971E+06 + ), + 'Nmi' => array( 'm' => 1.85200000000000E+03, + 'mi' => 1.15077944802354E+00, + 'Nmi' => 1.0, + 'in' => 7.29133858267717E+04, + 'ft' => 6.07611548556430E+03, + 'yd' => 2.02537182785694E+03, + 'ang' => 1.85200000000000E+13, + 'Pica' => 5.24976377952723E+06 + ), + 'in' => array( 'm' => 2.54000000000000E-02, + 'mi' => 1.57828282828283E-05, + 'Nmi' => 1.37149028077754E-05, + 'in' => 1.0, + 'ft' => 8.33333333333333E-02, + 'yd' => 2.77777777686643E-02, + 'ang' => 2.54000000000000E+08, + 'Pica' => 7.19999999999955E+01 + ), + 'ft' => array( 'm' => 3.04800000000000E-01, + 'mi' => 1.89393939393939E-04, + 'Nmi' => 1.64578833693305E-04, + 'in' => 1.20000000000000E+01, + 'ft' => 1.0, + 'yd' => 3.33333333223972E-01, + 'ang' => 3.04800000000000E+09, + 'Pica' => 8.63999999999946E+02 + ), + 'yd' => array( 'm' => 9.14400000300000E-01, + 'mi' => 5.68181818368230E-04, + 'Nmi' => 4.93736501241901E-04, + 'in' => 3.60000000118110E+01, + 'ft' => 3.00000000000000E+00, + 'yd' => 1.0, + 'ang' => 9.14400000300000E+09, + 'Pica' => 2.59200000085023E+03 + ), + 'ang' => array( 'm' => 1.00000000000000E-10, + 'mi' => 6.21371192237334E-14, + 'Nmi' => 5.39956803455724E-14, + 'in' => 3.93700787401575E-09, + 'ft' => 3.28083989501312E-10, + 'yd' => 1.09361329797891E-10, + 'ang' => 1.0, + 'Pica' => 2.83464566929116E-07 + ), + 'Pica' => array( 'm' => 3.52777777777800E-04, + 'mi' => 2.19205948372629E-07, + 'Nmi' => 1.90484761219114E-07, + 'in' => 1.38888888888898E-02, + 'ft' => 1.15740740740748E-03, + 'yd' => 3.85802469009251E-04, + 'ang' => 3.52777777777800E+06, + 'Pica' => 1.0 + ) + ), + 'Time' => array( 'yr' => array( 'yr' => 1.0, + 'day' => 365.25, + 'hr' => 8766.0, + 'mn' => 525960.0, + 'sec' => 31557600.0 + ), + 'day' => array( 'yr' => 2.73785078713210E-03, + 'day' => 1.0, + 'hr' => 24.0, + 'mn' => 1440.0, + 'sec' => 86400.0 + ), + 'hr' => array( 'yr' => 1.14077116130504E-04, + 'day' => 4.16666666666667E-02, + 'hr' => 1.0, + 'mn' => 60.0, + 'sec' => 3600.0 + ), + 'mn' => array( 'yr' => 1.90128526884174E-06, + 'day' => 6.94444444444444E-04, + 'hr' => 1.66666666666667E-02, + 'mn' => 1.0, + 'sec' => 60.0 + ), + 'sec' => array( 'yr' => 3.16880878140289E-08, + 'day' => 1.15740740740741E-05, + 'hr' => 2.77777777777778E-04, + 'mn' => 1.66666666666667E-02, + 'sec' => 1.0 + ) + ), + 'Pressure' => array( 'Pa' => array( 'Pa' => 1.0, + 'p' => 1.0, + 'atm' => 9.86923299998193E-06, + 'at' => 9.86923299998193E-06, + 'mmHg' => 7.50061707998627E-03 + ), + 'p' => array( 'Pa' => 1.0, + 'p' => 1.0, + 'atm' => 9.86923299998193E-06, + 'at' => 9.86923299998193E-06, + 'mmHg' => 7.50061707998627E-03 + ), + 'atm' => array( 'Pa' => 1.01324996583000E+05, + 'p' => 1.01324996583000E+05, + 'atm' => 1.0, + 'at' => 1.0, + 'mmHg' => 760.0 + ), + 'at' => array( 'Pa' => 1.01324996583000E+05, + 'p' => 1.01324996583000E+05, + 'atm' => 1.0, + 'at' => 1.0, + 'mmHg' => 760.0 + ), + 'mmHg' => array( 'Pa' => 1.33322363925000E+02, + 'p' => 1.33322363925000E+02, + 'atm' => 1.31578947368421E-03, + 'at' => 1.31578947368421E-03, + 'mmHg' => 1.0 + ) + ), + 'Force' => array( 'N' => array( 'N' => 1.0, + 'dyn' => 1.0E+5, + 'dy' => 1.0E+5, + 'lbf' => 2.24808923655339E-01 + ), + 'dyn' => array( 'N' => 1.0E-5, + 'dyn' => 1.0, + 'dy' => 1.0, + 'lbf' => 2.24808923655339E-06 + ), + 'dy' => array( 'N' => 1.0E-5, + 'dyn' => 1.0, + 'dy' => 1.0, + 'lbf' => 2.24808923655339E-06 + ), + 'lbf' => array( 'N' => 4.448222, + 'dyn' => 4.448222E+5, + 'dy' => 4.448222E+5, + 'lbf' => 1.0 + ) + ), + 'Energy' => array( 'J' => array( 'J' => 1.0, + 'e' => 9.99999519343231E+06, + 'c' => 2.39006249473467E-01, + 'cal' => 2.38846190642017E-01, + 'eV' => 6.24145700000000E+18, + 'ev' => 6.24145700000000E+18, + 'HPh' => 3.72506430801000E-07, + 'hh' => 3.72506430801000E-07, + 'Wh' => 2.77777916238711E-04, + 'wh' => 2.77777916238711E-04, + 'flb' => 2.37304222192651E+01, + 'BTU' => 9.47815067349015E-04, + 'btu' => 9.47815067349015E-04 + ), + 'e' => array( 'J' => 1.00000048065700E-07, + 'e' => 1.0, + 'c' => 2.39006364353494E-08, + 'cal' => 2.38846305445111E-08, + 'eV' => 6.24146000000000E+11, + 'ev' => 6.24146000000000E+11, + 'HPh' => 3.72506609848824E-14, + 'hh' => 3.72506609848824E-14, + 'Wh' => 2.77778049754611E-11, + 'wh' => 2.77778049754611E-11, + 'flb' => 2.37304336254586E-06, + 'BTU' => 9.47815522922962E-11, + 'btu' => 9.47815522922962E-11 + ), + 'c' => array( 'J' => 4.18399101363672E+00, + 'e' => 4.18398900257312E+07, + 'c' => 1.0, + 'cal' => 9.99330315287563E-01, + 'eV' => 2.61142000000000E+19, + 'ev' => 2.61142000000000E+19, + 'HPh' => 1.55856355899327E-06, + 'hh' => 1.55856355899327E-06, + 'Wh' => 1.16222030532950E-03, + 'wh' => 1.16222030532950E-03, + 'flb' => 9.92878733152102E+01, + 'BTU' => 3.96564972437776E-03, + 'btu' => 3.96564972437776E-03 + ), + 'cal' => array( 'J' => 4.18679484613929E+00, + 'e' => 4.18679283372801E+07, + 'c' => 1.00067013349059E+00, + 'cal' => 1.0, + 'eV' => 2.61317000000000E+19, + 'ev' => 2.61317000000000E+19, + 'HPh' => 1.55960800463137E-06, + 'hh' => 1.55960800463137E-06, + 'Wh' => 1.16299914807955E-03, + 'wh' => 1.16299914807955E-03, + 'flb' => 9.93544094443283E+01, + 'BTU' => 3.96830723907002E-03, + 'btu' => 3.96830723907002E-03 + ), + 'eV' => array( 'J' => 1.60219000146921E-19, + 'e' => 1.60218923136574E-12, + 'c' => 3.82933423195043E-20, + 'cal' => 3.82676978535648E-20, + 'eV' => 1.0, + 'ev' => 1.0, + 'HPh' => 5.96826078912344E-26, + 'hh' => 5.96826078912344E-26, + 'Wh' => 4.45053000026614E-23, + 'wh' => 4.45053000026614E-23, + 'flb' => 3.80206452103492E-18, + 'BTU' => 1.51857982414846E-22, + 'btu' => 1.51857982414846E-22 + ), + 'ev' => array( 'J' => 1.60219000146921E-19, + 'e' => 1.60218923136574E-12, + 'c' => 3.82933423195043E-20, + 'cal' => 3.82676978535648E-20, + 'eV' => 1.0, + 'ev' => 1.0, + 'HPh' => 5.96826078912344E-26, + 'hh' => 5.96826078912344E-26, + 'Wh' => 4.45053000026614E-23, + 'wh' => 4.45053000026614E-23, + 'flb' => 3.80206452103492E-18, + 'BTU' => 1.51857982414846E-22, + 'btu' => 1.51857982414846E-22 + ), + 'HPh' => array( 'J' => 2.68451741316170E+06, + 'e' => 2.68451612283024E+13, + 'c' => 6.41616438565991E+05, + 'cal' => 6.41186757845835E+05, + 'eV' => 1.67553000000000E+25, + 'ev' => 1.67553000000000E+25, + 'HPh' => 1.0, + 'hh' => 1.0, + 'Wh' => 7.45699653134593E+02, + 'wh' => 7.45699653134593E+02, + 'flb' => 6.37047316692964E+07, + 'BTU' => 2.54442605275546E+03, + 'btu' => 2.54442605275546E+03 + ), + 'hh' => array( 'J' => 2.68451741316170E+06, + 'e' => 2.68451612283024E+13, + 'c' => 6.41616438565991E+05, + 'cal' => 6.41186757845835E+05, + 'eV' => 1.67553000000000E+25, + 'ev' => 1.67553000000000E+25, + 'HPh' => 1.0, + 'hh' => 1.0, + 'Wh' => 7.45699653134593E+02, + 'wh' => 7.45699653134593E+02, + 'flb' => 6.37047316692964E+07, + 'BTU' => 2.54442605275546E+03, + 'btu' => 2.54442605275546E+03 + ), + 'Wh' => array( 'J' => 3.59999820554720E+03, + 'e' => 3.59999647518369E+10, + 'c' => 8.60422069219046E+02, + 'cal' => 8.59845857713046E+02, + 'eV' => 2.24692340000000E+22, + 'ev' => 2.24692340000000E+22, + 'HPh' => 1.34102248243839E-03, + 'hh' => 1.34102248243839E-03, + 'Wh' => 1.0, + 'wh' => 1.0, + 'flb' => 8.54294774062316E+04, + 'BTU' => 3.41213254164705E+00, + 'btu' => 3.41213254164705E+00 + ), + 'wh' => array( 'J' => 3.59999820554720E+03, + 'e' => 3.59999647518369E+10, + 'c' => 8.60422069219046E+02, + 'cal' => 8.59845857713046E+02, + 'eV' => 2.24692340000000E+22, + 'ev' => 2.24692340000000E+22, + 'HPh' => 1.34102248243839E-03, + 'hh' => 1.34102248243839E-03, + 'Wh' => 1.0, + 'wh' => 1.0, + 'flb' => 8.54294774062316E+04, + 'BTU' => 3.41213254164705E+00, + 'btu' => 3.41213254164705E+00 + ), + 'flb' => array( 'J' => 4.21400003236424E-02, + 'e' => 4.21399800687660E+05, + 'c' => 1.00717234301644E-02, + 'cal' => 1.00649785509554E-02, + 'eV' => 2.63015000000000E+17, + 'ev' => 2.63015000000000E+17, + 'HPh' => 1.56974211145130E-08, + 'hh' => 1.56974211145130E-08, + 'Wh' => 1.17055614802000E-05, + 'wh' => 1.17055614802000E-05, + 'flb' => 1.0, + 'BTU' => 3.99409272448406E-05, + 'btu' => 3.99409272448406E-05 + ), + 'BTU' => array( 'J' => 1.05505813786749E+03, + 'e' => 1.05505763074665E+10, + 'c' => 2.52165488508168E+02, + 'cal' => 2.51996617135510E+02, + 'eV' => 6.58510000000000E+21, + 'ev' => 6.58510000000000E+21, + 'HPh' => 3.93015941224568E-04, + 'hh' => 3.93015941224568E-04, + 'Wh' => 2.93071851047526E-01, + 'wh' => 2.93071851047526E-01, + 'flb' => 2.50369750774671E+04, + 'BTU' => 1.0, + 'btu' => 1.0, + ), + 'btu' => array( 'J' => 1.05505813786749E+03, + 'e' => 1.05505763074665E+10, + 'c' => 2.52165488508168E+02, + 'cal' => 2.51996617135510E+02, + 'eV' => 6.58510000000000E+21, + 'ev' => 6.58510000000000E+21, + 'HPh' => 3.93015941224568E-04, + 'hh' => 3.93015941224568E-04, + 'Wh' => 2.93071851047526E-01, + 'wh' => 2.93071851047526E-01, + 'flb' => 2.50369750774671E+04, + 'BTU' => 1.0, + 'btu' => 1.0, + ) + ), + 'Power' => array( 'HP' => array( 'HP' => 1.0, + 'h' => 1.0, + 'W' => 7.45701000000000E+02, + 'w' => 7.45701000000000E+02 + ), + 'h' => array( 'HP' => 1.0, + 'h' => 1.0, + 'W' => 7.45701000000000E+02, + 'w' => 7.45701000000000E+02 + ), + 'W' => array( 'HP' => 1.34102006031908E-03, + 'h' => 1.34102006031908E-03, + 'W' => 1.0, + 'w' => 1.0 + ), + 'w' => array( 'HP' => 1.34102006031908E-03, + 'h' => 1.34102006031908E-03, + 'W' => 1.0, + 'w' => 1.0 + ) + ), + 'Magnetism' => array( 'T' => array( 'T' => 1.0, + 'ga' => 10000.0 + ), + 'ga' => array( 'T' => 0.0001, + 'ga' => 1.0 + ) + ), + 'Liquid' => array( 'tsp' => array( 'tsp' => 1.0, + 'tbs' => 3.33333333333333E-01, + 'oz' => 1.66666666666667E-01, + 'cup' => 2.08333333333333E-02, + 'pt' => 1.04166666666667E-02, + 'us_pt' => 1.04166666666667E-02, + 'uk_pt' => 8.67558516821960E-03, + 'qt' => 5.20833333333333E-03, + 'gal' => 1.30208333333333E-03, + 'l' => 4.92999408400710E-03, + 'lt' => 4.92999408400710E-03 + ), + 'tbs' => array( 'tsp' => 3.00000000000000E+00, + 'tbs' => 1.0, + 'oz' => 5.00000000000000E-01, + 'cup' => 6.25000000000000E-02, + 'pt' => 3.12500000000000E-02, + 'us_pt' => 3.12500000000000E-02, + 'uk_pt' => 2.60267555046588E-02, + 'qt' => 1.56250000000000E-02, + 'gal' => 3.90625000000000E-03, + 'l' => 1.47899822520213E-02, + 'lt' => 1.47899822520213E-02 + ), + 'oz' => array( 'tsp' => 6.00000000000000E+00, + 'tbs' => 2.00000000000000E+00, + 'oz' => 1.0, + 'cup' => 1.25000000000000E-01, + 'pt' => 6.25000000000000E-02, + 'us_pt' => 6.25000000000000E-02, + 'uk_pt' => 5.20535110093176E-02, + 'qt' => 3.12500000000000E-02, + 'gal' => 7.81250000000000E-03, + 'l' => 2.95799645040426E-02, + 'lt' => 2.95799645040426E-02 + ), + 'cup' => array( 'tsp' => 4.80000000000000E+01, + 'tbs' => 1.60000000000000E+01, + 'oz' => 8.00000000000000E+00, + 'cup' => 1.0, + 'pt' => 5.00000000000000E-01, + 'us_pt' => 5.00000000000000E-01, + 'uk_pt' => 4.16428088074541E-01, + 'qt' => 2.50000000000000E-01, + 'gal' => 6.25000000000000E-02, + 'l' => 2.36639716032341E-01, + 'lt' => 2.36639716032341E-01 + ), + 'pt' => array( 'tsp' => 9.60000000000000E+01, + 'tbs' => 3.20000000000000E+01, + 'oz' => 1.60000000000000E+01, + 'cup' => 2.00000000000000E+00, + 'pt' => 1.0, + 'us_pt' => 1.0, + 'uk_pt' => 8.32856176149081E-01, + 'qt' => 5.00000000000000E-01, + 'gal' => 1.25000000000000E-01, + 'l' => 4.73279432064682E-01, + 'lt' => 4.73279432064682E-01 + ), + 'us_pt' => array( 'tsp' => 9.60000000000000E+01, + 'tbs' => 3.20000000000000E+01, + 'oz' => 1.60000000000000E+01, + 'cup' => 2.00000000000000E+00, + 'pt' => 1.0, + 'us_pt' => 1.0, + 'uk_pt' => 8.32856176149081E-01, + 'qt' => 5.00000000000000E-01, + 'gal' => 1.25000000000000E-01, + 'l' => 4.73279432064682E-01, + 'lt' => 4.73279432064682E-01 + ), + 'uk_pt' => array( 'tsp' => 1.15266000000000E+02, + 'tbs' => 3.84220000000000E+01, + 'oz' => 1.92110000000000E+01, + 'cup' => 2.40137500000000E+00, + 'pt' => 1.20068750000000E+00, + 'us_pt' => 1.20068750000000E+00, + 'uk_pt' => 1.0, + 'qt' => 6.00343750000000E-01, + 'gal' => 1.50085937500000E-01, + 'l' => 5.68260698087162E-01, + 'lt' => 5.68260698087162E-01 + ), + 'qt' => array( 'tsp' => 1.92000000000000E+02, + 'tbs' => 6.40000000000000E+01, + 'oz' => 3.20000000000000E+01, + 'cup' => 4.00000000000000E+00, + 'pt' => 2.00000000000000E+00, + 'us_pt' => 2.00000000000000E+00, + 'uk_pt' => 1.66571235229816E+00, + 'qt' => 1.0, + 'gal' => 2.50000000000000E-01, + 'l' => 9.46558864129363E-01, + 'lt' => 9.46558864129363E-01 + ), + 'gal' => array( 'tsp' => 7.68000000000000E+02, + 'tbs' => 2.56000000000000E+02, + 'oz' => 1.28000000000000E+02, + 'cup' => 1.60000000000000E+01, + 'pt' => 8.00000000000000E+00, + 'us_pt' => 8.00000000000000E+00, + 'uk_pt' => 6.66284940919265E+00, + 'qt' => 4.00000000000000E+00, + 'gal' => 1.0, + 'l' => 3.78623545651745E+00, + 'lt' => 3.78623545651745E+00 + ), + 'l' => array( 'tsp' => 2.02840000000000E+02, + 'tbs' => 6.76133333333333E+01, + 'oz' => 3.38066666666667E+01, + 'cup' => 4.22583333333333E+00, + 'pt' => 2.11291666666667E+00, + 'us_pt' => 2.11291666666667E+00, + 'uk_pt' => 1.75975569552166E+00, + 'qt' => 1.05645833333333E+00, + 'gal' => 2.64114583333333E-01, + 'l' => 1.0, + 'lt' => 1.0 + ), + 'lt' => array( 'tsp' => 2.02840000000000E+02, + 'tbs' => 6.76133333333333E+01, + 'oz' => 3.38066666666667E+01, + 'cup' => 4.22583333333333E+00, + 'pt' => 2.11291666666667E+00, + 'us_pt' => 2.11291666666667E+00, + 'uk_pt' => 1.75975569552166E+00, + 'qt' => 1.05645833333333E+00, + 'gal' => 2.64114583333333E-01, + 'l' => 1.0, + 'lt' => 1.0 + ) + ) + ); + + + /** + * _parseComplex + * + * Parses a complex number into its real and imaginary parts, and an I or J suffix + * + * @param string $complexNumber The complex number + * @return string[] Indexed on "real", "imaginary" and "suffix" + */ + public static function _parseComplex($complexNumber) { + $workString = (string) $complexNumber; + + $realNumber = $imaginary = 0; + // Extract the suffix, if there is one + $suffix = substr($workString,-1); + if (!is_numeric($suffix)) { + $workString = substr($workString,0,-1); + } else { + $suffix = ''; + } + + // Split the input into its Real and Imaginary components + $leadingSign = 0; + if (strlen($workString) > 0) { + $leadingSign = (($workString{0} == '+') || ($workString{0} == '-')) ? 1 : 0; + } + $power = ''; + $realNumber = strtok($workString, '+-'); + if (strtoupper(substr($realNumber,-1)) == 'E') { + $power = strtok('+-'); + ++$leadingSign; + } + + $realNumber = substr($workString,0,strlen($realNumber)+strlen($power)+$leadingSign); + + if ($suffix != '') { + $imaginary = substr($workString,strlen($realNumber)); + + if (($imaginary == '') && (($realNumber == '') || ($realNumber == '+') || ($realNumber == '-'))) { + $imaginary = $realNumber.'1'; + $realNumber = '0'; + } else if ($imaginary == '') { + $imaginary = $realNumber; + $realNumber = '0'; + } elseif (($imaginary == '+') || ($imaginary == '-')) { + $imaginary .= '1'; + } + } + + return array( 'real' => $realNumber, + 'imaginary' => $imaginary, + 'suffix' => $suffix + ); + } // function _parseComplex() + + + /** + * Cleans the leading characters in a complex number string + * + * @param string $complexNumber The complex number to clean + * @return string The "cleaned" complex number + */ + private static function _cleanComplex($complexNumber) { + if ($complexNumber{0} == '+') $complexNumber = substr($complexNumber,1); + if ($complexNumber{0} == '0') $complexNumber = substr($complexNumber,1); + if ($complexNumber{0} == '.') $complexNumber = '0'.$complexNumber; + if ($complexNumber{0} == '+') $complexNumber = substr($complexNumber,1); + return $complexNumber; + } + + /** + * Formats a number base string value with leading zeroes + * + * @param string $xVal The "number" to pad + * @param integer $places The length that we want to pad this value + * @return string The padded "number" + */ + private static function _nbrConversionFormat($xVal, $places) { + if (!is_null($places)) { + if (strlen($xVal) <= $places) { + return substr(str_pad($xVal, $places, '0', STR_PAD_LEFT), -10); + } else { + return PHPExcel_Calculation_Functions::NaN(); + } + } + + return substr($xVal, -10); + } // function _nbrConversionFormat() + + /** + * BESSELI + * + * Returns the modified Bessel function In(x), which is equivalent to the Bessel function evaluated + * for purely imaginary arguments + * + * Excel Function: + * BESSELI(x,ord) + * + * @access public + * @category Engineering Functions + * @param float $x The value at which to evaluate the function. + * If x is nonnumeric, BESSELI returns the #VALUE! error value. + * @param integer $ord The order of the Bessel function. + * If ord is not an integer, it is truncated. + * If $ord is nonnumeric, BESSELI returns the #VALUE! error value. + * If $ord < 0, BESSELI returns the #NUM! error value. + * @return float + * + */ + public static function BESSELI($x, $ord) { + $x = (is_null($x)) ? 0.0 : PHPExcel_Calculation_Functions::flattenSingleValue($x); + $ord = (is_null($ord)) ? 0.0 : PHPExcel_Calculation_Functions::flattenSingleValue($ord); + + if ((is_numeric($x)) && (is_numeric($ord))) { + $ord = floor($ord); + if ($ord < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + + if (abs($x) <= 30) { + $fResult = $fTerm = pow($x / 2, $ord) / PHPExcel_Calculation_MathTrig::FACT($ord); + $ordK = 1; + $fSqrX = ($x * $x) / 4; + do { + $fTerm *= $fSqrX; + $fTerm /= ($ordK * ($ordK + $ord)); + $fResult += $fTerm; + } while ((abs($fTerm) > 1e-12) && (++$ordK < 100)); + } else { + $f_2_PI = 2 * M_PI; + + $fXAbs = abs($x); + $fResult = exp($fXAbs) / sqrt($f_2_PI * $fXAbs); + if (($ord & 1) && ($x < 0)) { + $fResult = -$fResult; + } + } + return (is_nan($fResult)) ? PHPExcel_Calculation_Functions::NaN() : $fResult; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function BESSELI() + + + /** + * BESSELJ + * + * Returns the Bessel function + * + * Excel Function: + * BESSELJ(x,ord) + * + * @access public + * @category Engineering Functions + * @param float $x The value at which to evaluate the function. + * If x is nonnumeric, BESSELJ returns the #VALUE! error value. + * @param integer $ord The order of the Bessel function. If n is not an integer, it is truncated. + * If $ord is nonnumeric, BESSELJ returns the #VALUE! error value. + * If $ord < 0, BESSELJ returns the #NUM! error value. + * @return float + * + */ + public static function BESSELJ($x, $ord) { + $x = (is_null($x)) ? 0.0 : PHPExcel_Calculation_Functions::flattenSingleValue($x); + $ord = (is_null($ord)) ? 0.0 : PHPExcel_Calculation_Functions::flattenSingleValue($ord); + + if ((is_numeric($x)) && (is_numeric($ord))) { + $ord = floor($ord); + if ($ord < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + + $fResult = 0; + if (abs($x) <= 30) { + $fResult = $fTerm = pow($x / 2, $ord) / PHPExcel_Calculation_MathTrig::FACT($ord); + $ordK = 1; + $fSqrX = ($x * $x) / -4; + do { + $fTerm *= $fSqrX; + $fTerm /= ($ordK * ($ordK + $ord)); + $fResult += $fTerm; + } while ((abs($fTerm) > 1e-12) && (++$ordK < 100)); + } else { + $f_PI_DIV_2 = M_PI / 2; + $f_PI_DIV_4 = M_PI / 4; + + $fXAbs = abs($x); + $fResult = sqrt(M_2DIVPI / $fXAbs) * cos($fXAbs - $ord * $f_PI_DIV_2 - $f_PI_DIV_4); + if (($ord & 1) && ($x < 0)) { + $fResult = -$fResult; + } + } + return (is_nan($fResult)) ? PHPExcel_Calculation_Functions::NaN() : $fResult; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function BESSELJ() + + + private static function _Besselk0($fNum) { + if ($fNum <= 2) { + $fNum2 = $fNum * 0.5; + $y = ($fNum2 * $fNum2); + $fRet = -log($fNum2) * self::BESSELI($fNum, 0) + + (-0.57721566 + $y * (0.42278420 + $y * (0.23069756 + $y * (0.3488590e-1 + $y * (0.262698e-2 + $y * + (0.10750e-3 + $y * 0.74e-5)))))); + } else { + $y = 2 / $fNum; + $fRet = exp(-$fNum) / sqrt($fNum) * + (1.25331414 + $y * (-0.7832358e-1 + $y * (0.2189568e-1 + $y * (-0.1062446e-1 + $y * + (0.587872e-2 + $y * (-0.251540e-2 + $y * 0.53208e-3)))))); + } + return $fRet; + } // function _Besselk0() + + + private static function _Besselk1($fNum) { + if ($fNum <= 2) { + $fNum2 = $fNum * 0.5; + $y = ($fNum2 * $fNum2); + $fRet = log($fNum2) * self::BESSELI($fNum, 1) + + (1 + $y * (0.15443144 + $y * (-0.67278579 + $y * (-0.18156897 + $y * (-0.1919402e-1 + $y * + (-0.110404e-2 + $y * (-0.4686e-4))))))) / $fNum; + } else { + $y = 2 / $fNum; + $fRet = exp(-$fNum) / sqrt($fNum) * + (1.25331414 + $y * (0.23498619 + $y * (-0.3655620e-1 + $y * (0.1504268e-1 + $y * (-0.780353e-2 + $y * + (0.325614e-2 + $y * (-0.68245e-3))))))); + } + return $fRet; + } // function _Besselk1() + + + /** + * BESSELK + * + * Returns the modified Bessel function Kn(x), which is equivalent to the Bessel functions evaluated + * for purely imaginary arguments. + * + * Excel Function: + * BESSELK(x,ord) + * + * @access public + * @category Engineering Functions + * @param float $x The value at which to evaluate the function. + * If x is nonnumeric, BESSELK returns the #VALUE! error value. + * @param integer $ord The order of the Bessel function. If n is not an integer, it is truncated. + * If $ord is nonnumeric, BESSELK returns the #VALUE! error value. + * If $ord < 0, BESSELK returns the #NUM! error value. + * @return float + * + */ + public static function BESSELK($x, $ord) { + $x = (is_null($x)) ? 0.0 : PHPExcel_Calculation_Functions::flattenSingleValue($x); + $ord = (is_null($ord)) ? 0.0 : PHPExcel_Calculation_Functions::flattenSingleValue($ord); + + if ((is_numeric($x)) && (is_numeric($ord))) { + if (($ord < 0) || ($x == 0.0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + + switch(floor($ord)) { + case 0 : return self::_Besselk0($x); + break; + case 1 : return self::_Besselk1($x); + break; + default : $fTox = 2 / $x; + $fBkm = self::_Besselk0($x); + $fBk = self::_Besselk1($x); + for ($n = 1; $n < $ord; ++$n) { + $fBkp = $fBkm + $n * $fTox * $fBk; + $fBkm = $fBk; + $fBk = $fBkp; + } + } + return (is_nan($fBk)) ? PHPExcel_Calculation_Functions::NaN() : $fBk; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function BESSELK() + + + private static function _Bessely0($fNum) { + if ($fNum < 8.0) { + $y = ($fNum * $fNum); + $f1 = -2957821389.0 + $y * (7062834065.0 + $y * (-512359803.6 + $y * (10879881.29 + $y * (-86327.92757 + $y * 228.4622733)))); + $f2 = 40076544269.0 + $y * (745249964.8 + $y * (7189466.438 + $y * (47447.26470 + $y * (226.1030244 + $y)))); + $fRet = $f1 / $f2 + 0.636619772 * self::BESSELJ($fNum, 0) * log($fNum); + } else { + $z = 8.0 / $fNum; + $y = ($z * $z); + $xx = $fNum - 0.785398164; + $f1 = 1 + $y * (-0.1098628627e-2 + $y * (0.2734510407e-4 + $y * (-0.2073370639e-5 + $y * 0.2093887211e-6))); + $f2 = -0.1562499995e-1 + $y * (0.1430488765e-3 + $y * (-0.6911147651e-5 + $y * (0.7621095161e-6 + $y * (-0.934945152e-7)))); + $fRet = sqrt(0.636619772 / $fNum) * (sin($xx) * $f1 + $z * cos($xx) * $f2); + } + return $fRet; + } // function _Bessely0() + + + private static function _Bessely1($fNum) { + if ($fNum < 8.0) { + $y = ($fNum * $fNum); + $f1 = $fNum * (-0.4900604943e13 + $y * (0.1275274390e13 + $y * (-0.5153438139e11 + $y * (0.7349264551e9 + $y * + (-0.4237922726e7 + $y * 0.8511937935e4))))); + $f2 = 0.2499580570e14 + $y * (0.4244419664e12 + $y * (0.3733650367e10 + $y * (0.2245904002e8 + $y * + (0.1020426050e6 + $y * (0.3549632885e3 + $y))))); + $fRet = $f1 / $f2 + 0.636619772 * ( self::BESSELJ($fNum, 1) * log($fNum) - 1 / $fNum); + } else { + $fRet = sqrt(0.636619772 / $fNum) * sin($fNum - 2.356194491); + } + return $fRet; + } // function _Bessely1() + + + /** + * BESSELY + * + * Returns the Bessel function, which is also called the Weber function or the Neumann function. + * + * Excel Function: + * BESSELY(x,ord) + * + * @access public + * @category Engineering Functions + * @param float $x The value at which to evaluate the function. + * If x is nonnumeric, BESSELK returns the #VALUE! error value. + * @param integer $ord The order of the Bessel function. If n is not an integer, it is truncated. + * If $ord is nonnumeric, BESSELK returns the #VALUE! error value. + * If $ord < 0, BESSELK returns the #NUM! error value. + * + * @return float + */ + public static function BESSELY($x, $ord) { + $x = (is_null($x)) ? 0.0 : PHPExcel_Calculation_Functions::flattenSingleValue($x); + $ord = (is_null($ord)) ? 0.0 : PHPExcel_Calculation_Functions::flattenSingleValue($ord); + + if ((is_numeric($x)) && (is_numeric($ord))) { + if (($ord < 0) || ($x == 0.0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + + switch(floor($ord)) { + case 0 : return self::_Bessely0($x); + break; + case 1 : return self::_Bessely1($x); + break; + default: $fTox = 2 / $x; + $fBym = self::_Bessely0($x); + $fBy = self::_Bessely1($x); + for ($n = 1; $n < $ord; ++$n) { + $fByp = $n * $fTox * $fBy - $fBym; + $fBym = $fBy; + $fBy = $fByp; + } + } + return (is_nan($fBy)) ? PHPExcel_Calculation_Functions::NaN() : $fBy; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function BESSELY() + + + /** + * BINTODEC + * + * Return a binary value as decimal. + * + * Excel Function: + * BIN2DEC(x) + * + * @access public + * @category Engineering Functions + * @param string $x The binary number (as a string) that you want to convert. The number + * cannot contain more than 10 characters (10 bits). The most significant + * bit of number is the sign bit. The remaining 9 bits are magnitude bits. + * Negative numbers are represented using two's-complement notation. + * If number is not a valid binary number, or if number contains more than + * 10 characters (10 bits), BIN2DEC returns the #NUM! error value. + * @return string + */ + public static function BINTODEC($x) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + + if (is_bool($x)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + $x = (int) $x; + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) { + $x = floor($x); + } + $x = (string) $x; + if (strlen($x) > preg_match_all('/[01]/',$x,$out)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (strlen($x) > 10) { + return PHPExcel_Calculation_Functions::NaN(); + } elseif (strlen($x) == 10) { + // Two's Complement + $x = substr($x,-9); + return '-'.(512-bindec($x)); + } + return bindec($x); + } // function BINTODEC() + + + /** + * BINTOHEX + * + * Return a binary value as hex. + * + * Excel Function: + * BIN2HEX(x[,places]) + * + * @access public + * @category Engineering Functions + * @param string $x The binary number (as a string) that you want to convert. The number + * cannot contain more than 10 characters (10 bits). The most significant + * bit of number is the sign bit. The remaining 9 bits are magnitude bits. + * Negative numbers are represented using two's-complement notation. + * If number is not a valid binary number, or if number contains more than + * 10 characters (10 bits), BIN2HEX returns the #NUM! error value. + * @param integer $places The number of characters to use. If places is omitted, BIN2HEX uses the + * minimum number of characters necessary. Places is useful for padding the + * return value with leading 0s (zeros). + * If places is not an integer, it is truncated. + * If places is nonnumeric, BIN2HEX returns the #VALUE! error value. + * If places is negative, BIN2HEX returns the #NUM! error value. + * @return string + */ + public static function BINTOHEX($x, $places=NULL) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + $places = PHPExcel_Calculation_Functions::flattenSingleValue($places); + + if (is_bool($x)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + $x = (int) $x; + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) { + $x = floor($x); + } + $x = (string) $x; + if (strlen($x) > preg_match_all('/[01]/',$x,$out)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (strlen($x) > 10) { + return PHPExcel_Calculation_Functions::NaN(); + } elseif (strlen($x) == 10) { + // Two's Complement + return str_repeat('F',8).substr(strtoupper(dechex(bindec(substr($x,-9)))),-2); + } + $hexVal = (string) strtoupper(dechex(bindec($x))); + + return self::_nbrConversionFormat($hexVal,$places); + } // function BINTOHEX() + + + /** + * BINTOOCT + * + * Return a binary value as octal. + * + * Excel Function: + * BIN2OCT(x[,places]) + * + * @access public + * @category Engineering Functions + * @param string $x The binary number (as a string) that you want to convert. The number + * cannot contain more than 10 characters (10 bits). The most significant + * bit of number is the sign bit. The remaining 9 bits are magnitude bits. + * Negative numbers are represented using two's-complement notation. + * If number is not a valid binary number, or if number contains more than + * 10 characters (10 bits), BIN2OCT returns the #NUM! error value. + * @param integer $places The number of characters to use. If places is omitted, BIN2OCT uses the + * minimum number of characters necessary. Places is useful for padding the + * return value with leading 0s (zeros). + * If places is not an integer, it is truncated. + * If places is nonnumeric, BIN2OCT returns the #VALUE! error value. + * If places is negative, BIN2OCT returns the #NUM! error value. + * @return string + */ + public static function BINTOOCT($x, $places=NULL) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + $places = PHPExcel_Calculation_Functions::flattenSingleValue($places); + + if (is_bool($x)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + $x = (int) $x; + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) { + $x = floor($x); + } + $x = (string) $x; + if (strlen($x) > preg_match_all('/[01]/',$x,$out)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (strlen($x) > 10) { + return PHPExcel_Calculation_Functions::NaN(); + } elseif (strlen($x) == 10) { + // Two's Complement + return str_repeat('7',7).substr(strtoupper(decoct(bindec(substr($x,-9)))),-3); + } + $octVal = (string) decoct(bindec($x)); + + return self::_nbrConversionFormat($octVal,$places); + } // function BINTOOCT() + + + /** + * DECTOBIN + * + * Return a decimal value as binary. + * + * Excel Function: + * DEC2BIN(x[,places]) + * + * @access public + * @category Engineering Functions + * @param string $x The decimal integer you want to convert. If number is negative, + * valid place values are ignored and DEC2BIN returns a 10-character + * (10-bit) binary number in which the most significant bit is the sign + * bit. The remaining 9 bits are magnitude bits. Negative numbers are + * represented using two's-complement notation. + * If number < -512 or if number > 511, DEC2BIN returns the #NUM! error + * value. + * If number is nonnumeric, DEC2BIN returns the #VALUE! error value. + * If DEC2BIN requires more than places characters, it returns the #NUM! + * error value. + * @param integer $places The number of characters to use. If places is omitted, DEC2BIN uses + * the minimum number of characters necessary. Places is useful for + * padding the return value with leading 0s (zeros). + * If places is not an integer, it is truncated. + * If places is nonnumeric, DEC2BIN returns the #VALUE! error value. + * If places is zero or negative, DEC2BIN returns the #NUM! error value. + * @return string + */ + public static function DECTOBIN($x, $places=NULL) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + $places = PHPExcel_Calculation_Functions::flattenSingleValue($places); + + if (is_bool($x)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + $x = (int) $x; + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + $x = (string) $x; + if (strlen($x) > preg_match_all('/[-0123456789.]/',$x,$out)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $x = (string) floor($x); + $r = decbin($x); + if (strlen($r) == 32) { + // Two's Complement + $r = substr($r,-10); + } elseif (strlen($r) > 11) { + return PHPExcel_Calculation_Functions::NaN(); + } + + return self::_nbrConversionFormat($r,$places); + } // function DECTOBIN() + + + /** + * DECTOHEX + * + * Return a decimal value as hex. + * + * Excel Function: + * DEC2HEX(x[,places]) + * + * @access public + * @category Engineering Functions + * @param string $x The decimal integer you want to convert. If number is negative, + * places is ignored and DEC2HEX returns a 10-character (40-bit) + * hexadecimal number in which the most significant bit is the sign + * bit. The remaining 39 bits are magnitude bits. Negative numbers + * are represented using two's-complement notation. + * If number < -549,755,813,888 or if number > 549,755,813,887, + * DEC2HEX returns the #NUM! error value. + * If number is nonnumeric, DEC2HEX returns the #VALUE! error value. + * If DEC2HEX requires more than places characters, it returns the + * #NUM! error value. + * @param integer $places The number of characters to use. If places is omitted, DEC2HEX uses + * the minimum number of characters necessary. Places is useful for + * padding the return value with leading 0s (zeros). + * If places is not an integer, it is truncated. + * If places is nonnumeric, DEC2HEX returns the #VALUE! error value. + * If places is zero or negative, DEC2HEX returns the #NUM! error value. + * @return string + */ + public static function DECTOHEX($x, $places=null) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + $places = PHPExcel_Calculation_Functions::flattenSingleValue($places); + + if (is_bool($x)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + $x = (int) $x; + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + $x = (string) $x; + if (strlen($x) > preg_match_all('/[-0123456789.]/',$x,$out)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $x = (string) floor($x); + $r = strtoupper(dechex($x)); + if (strlen($r) == 8) { + // Two's Complement + $r = 'FF'.$r; + } + + return self::_nbrConversionFormat($r,$places); + } // function DECTOHEX() + + + /** + * DECTOOCT + * + * Return an decimal value as octal. + * + * Excel Function: + * DEC2OCT(x[,places]) + * + * @access public + * @category Engineering Functions + * @param string $x The decimal integer you want to convert. If number is negative, + * places is ignored and DEC2OCT returns a 10-character (30-bit) + * octal number in which the most significant bit is the sign bit. + * The remaining 29 bits are magnitude bits. Negative numbers are + * represented using two's-complement notation. + * If number < -536,870,912 or if number > 536,870,911, DEC2OCT + * returns the #NUM! error value. + * If number is nonnumeric, DEC2OCT returns the #VALUE! error value. + * If DEC2OCT requires more than places characters, it returns the + * #NUM! error value. + * @param integer $places The number of characters to use. If places is omitted, DEC2OCT uses + * the minimum number of characters necessary. Places is useful for + * padding the return value with leading 0s (zeros). + * If places is not an integer, it is truncated. + * If places is nonnumeric, DEC2OCT returns the #VALUE! error value. + * If places is zero or negative, DEC2OCT returns the #NUM! error value. + * @return string + */ + public static function DECTOOCT($x, $places=null) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + $places = PHPExcel_Calculation_Functions::flattenSingleValue($places); + + if (is_bool($x)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + $x = (int) $x; + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + $x = (string) $x; + if (strlen($x) > preg_match_all('/[-0123456789.]/',$x,$out)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $x = (string) floor($x); + $r = decoct($x); + if (strlen($r) == 11) { + // Two's Complement + $r = substr($r,-10); + } + + return self::_nbrConversionFormat($r,$places); + } // function DECTOOCT() + + + /** + * HEXTOBIN + * + * Return a hex value as binary. + * + * Excel Function: + * HEX2BIN(x[,places]) + * + * @access public + * @category Engineering Functions + * @param string $x the hexadecimal number you want to convert. Number cannot + * contain more than 10 characters. The most significant bit of + * number is the sign bit (40th bit from the right). The remaining + * 9 bits are magnitude bits. Negative numbers are represented + * using two's-complement notation. + * If number is negative, HEX2BIN ignores places and returns a + * 10-character binary number. + * If number is negative, it cannot be less than FFFFFFFE00, and + * if number is positive, it cannot be greater than 1FF. + * If number is not a valid hexadecimal number, HEX2BIN returns + * the #NUM! error value. + * If HEX2BIN requires more than places characters, it returns + * the #NUM! error value. + * @param integer $places The number of characters to use. If places is omitted, + * HEX2BIN uses the minimum number of characters necessary. Places + * is useful for padding the return value with leading 0s (zeros). + * If places is not an integer, it is truncated. + * If places is nonnumeric, HEX2BIN returns the #VALUE! error value. + * If places is negative, HEX2BIN returns the #NUM! error value. + * @return string + */ + public static function HEXTOBIN($x, $places=null) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + $places = PHPExcel_Calculation_Functions::flattenSingleValue($places); + + if (is_bool($x)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $x = (string) $x; + if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/',strtoupper($x),$out)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $binVal = decbin(hexdec($x)); + + return substr(self::_nbrConversionFormat($binVal,$places),-10); + } // function HEXTOBIN() + + + /** + * HEXTODEC + * + * Return a hex value as decimal. + * + * Excel Function: + * HEX2DEC(x) + * + * @access public + * @category Engineering Functions + * @param string $x The hexadecimal number you want to convert. This number cannot + * contain more than 10 characters (40 bits). The most significant + * bit of number is the sign bit. The remaining 39 bits are magnitude + * bits. Negative numbers are represented using two's-complement + * notation. + * If number is not a valid hexadecimal number, HEX2DEC returns the + * #NUM! error value. + * @return string + */ + public static function HEXTODEC($x) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + + if (is_bool($x)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $x = (string) $x; + if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/',strtoupper($x),$out)) { + return PHPExcel_Calculation_Functions::NaN(); + } + return hexdec($x); + } // function HEXTODEC() + + + /** + * HEXTOOCT + * + * Return a hex value as octal. + * + * Excel Function: + * HEX2OCT(x[,places]) + * + * @access public + * @category Engineering Functions + * @param string $x The hexadecimal number you want to convert. Number cannot + * contain more than 10 characters. The most significant bit of + * number is the sign bit. The remaining 39 bits are magnitude + * bits. Negative numbers are represented using two's-complement + * notation. + * If number is negative, HEX2OCT ignores places and returns a + * 10-character octal number. + * If number is negative, it cannot be less than FFE0000000, and + * if number is positive, it cannot be greater than 1FFFFFFF. + * If number is not a valid hexadecimal number, HEX2OCT returns + * the #NUM! error value. + * If HEX2OCT requires more than places characters, it returns + * the #NUM! error value. + * @param integer $places The number of characters to use. If places is omitted, HEX2OCT + * uses the minimum number of characters necessary. Places is + * useful for padding the return value with leading 0s (zeros). + * If places is not an integer, it is truncated. + * If places is nonnumeric, HEX2OCT returns the #VALUE! error + * value. + * If places is negative, HEX2OCT returns the #NUM! error value. + * @return string + */ + public static function HEXTOOCT($x, $places=null) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + $places = PHPExcel_Calculation_Functions::flattenSingleValue($places); + + if (is_bool($x)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $x = (string) $x; + if (strlen($x) > preg_match_all('/[0123456789ABCDEF]/',strtoupper($x),$out)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $octVal = decoct(hexdec($x)); + + return self::_nbrConversionFormat($octVal,$places); + } // function HEXTOOCT() + + + /** + * OCTTOBIN + * + * Return an octal value as binary. + * + * Excel Function: + * OCT2BIN(x[,places]) + * + * @access public + * @category Engineering Functions + * @param string $x The octal number you want to convert. Number may not + * contain more than 10 characters. The most significant + * bit of number is the sign bit. The remaining 29 bits + * are magnitude bits. Negative numbers are represented + * using two's-complement notation. + * If number is negative, OCT2BIN ignores places and returns + * a 10-character binary number. + * If number is negative, it cannot be less than 7777777000, + * and if number is positive, it cannot be greater than 777. + * If number is not a valid octal number, OCT2BIN returns + * the #NUM! error value. + * If OCT2BIN requires more than places characters, it + * returns the #NUM! error value. + * @param integer $places The number of characters to use. If places is omitted, + * OCT2BIN uses the minimum number of characters necessary. + * Places is useful for padding the return value with + * leading 0s (zeros). + * If places is not an integer, it is truncated. + * If places is nonnumeric, OCT2BIN returns the #VALUE! + * error value. + * If places is negative, OCT2BIN returns the #NUM! error + * value. + * @return string + */ + public static function OCTTOBIN($x, $places=null) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + $places = PHPExcel_Calculation_Functions::flattenSingleValue($places); + + if (is_bool($x)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $x = (string) $x; + if (preg_match_all('/[01234567]/',$x,$out) != strlen($x)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $r = decbin(octdec($x)); + + return self::_nbrConversionFormat($r,$places); + } // function OCTTOBIN() + + + /** + * OCTTODEC + * + * Return an octal value as decimal. + * + * Excel Function: + * OCT2DEC(x) + * + * @access public + * @category Engineering Functions + * @param string $x The octal number you want to convert. Number may not contain + * more than 10 octal characters (30 bits). The most significant + * bit of number is the sign bit. The remaining 29 bits are + * magnitude bits. Negative numbers are represented using + * two's-complement notation. + * If number is not a valid octal number, OCT2DEC returns the + * #NUM! error value. + * @return string + */ + public static function OCTTODEC($x) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + + if (is_bool($x)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $x = (string) $x; + if (preg_match_all('/[01234567]/',$x,$out) != strlen($x)) { + return PHPExcel_Calculation_Functions::NaN(); + } + return octdec($x); + } // function OCTTODEC() + + + /** + * OCTTOHEX + * + * Return an octal value as hex. + * + * Excel Function: + * OCT2HEX(x[,places]) + * + * @access public + * @category Engineering Functions + * @param string $x The octal number you want to convert. Number may not contain + * more than 10 octal characters (30 bits). The most significant + * bit of number is the sign bit. The remaining 29 bits are + * magnitude bits. Negative numbers are represented using + * two's-complement notation. + * If number is negative, OCT2HEX ignores places and returns a + * 10-character hexadecimal number. + * If number is not a valid octal number, OCT2HEX returns the + * #NUM! error value. + * If OCT2HEX requires more than places characters, it returns + * the #NUM! error value. + * @param integer $places The number of characters to use. If places is omitted, OCT2HEX + * uses the minimum number of characters necessary. Places is useful + * for padding the return value with leading 0s (zeros). + * If places is not an integer, it is truncated. + * If places is nonnumeric, OCT2HEX returns the #VALUE! error value. + * If places is negative, OCT2HEX returns the #NUM! error value. + * @return string + */ + public static function OCTTOHEX($x, $places=null) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + $places = PHPExcel_Calculation_Functions::flattenSingleValue($places); + + if (is_bool($x)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $x = (string) $x; + if (preg_match_all('/[01234567]/',$x,$out) != strlen($x)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $hexVal = strtoupper(dechex(octdec($x))); + + return self::_nbrConversionFormat($hexVal,$places); + } // function OCTTOHEX() + + + /** + * COMPLEX + * + * Converts real and imaginary coefficients into a complex number of the form x + yi or x + yj. + * + * Excel Function: + * COMPLEX(realNumber,imaginary[,places]) + * + * @access public + * @category Engineering Functions + * @param float $realNumber The real coefficient of the complex number. + * @param float $imaginary The imaginary coefficient of the complex number. + * @param string $suffix The suffix for the imaginary component of the complex number. + * If omitted, the suffix is assumed to be "i". + * @return string + */ + public static function COMPLEX($realNumber=0.0, $imaginary=0.0, $suffix='i') { + $realNumber = (is_null($realNumber)) ? 0.0 : PHPExcel_Calculation_Functions::flattenSingleValue($realNumber); + $imaginary = (is_null($imaginary)) ? 0.0 : PHPExcel_Calculation_Functions::flattenSingleValue($imaginary); + $suffix = (is_null($suffix)) ? 'i' : PHPExcel_Calculation_Functions::flattenSingleValue($suffix); + + if (((is_numeric($realNumber)) && (is_numeric($imaginary))) && + (($suffix == 'i') || ($suffix == 'j') || ($suffix == ''))) { + $realNumber = (float) $realNumber; + $imaginary = (float) $imaginary; + + if ($suffix == '') $suffix = 'i'; + if ($realNumber == 0.0) { + if ($imaginary == 0.0) { + return (string) '0'; + } elseif ($imaginary == 1.0) { + return (string) $suffix; + } elseif ($imaginary == -1.0) { + return (string) '-'.$suffix; + } + return (string) $imaginary.$suffix; + } elseif ($imaginary == 0.0) { + return (string) $realNumber; + } elseif ($imaginary == 1.0) { + return (string) $realNumber.'+'.$suffix; + } elseif ($imaginary == -1.0) { + return (string) $realNumber.'-'.$suffix; + } + if ($imaginary > 0) { $imaginary = (string) '+'.$imaginary; } + return (string) $realNumber.$imaginary.$suffix; + } + + return PHPExcel_Calculation_Functions::VALUE(); + } // function COMPLEX() + + + /** + * IMAGINARY + * + * Returns the imaginary coefficient of a complex number in x + yi or x + yj text format. + * + * Excel Function: + * IMAGINARY(complexNumber) + * + * @access public + * @category Engineering Functions + * @param string $complexNumber The complex number for which you want the imaginary + * coefficient. + * @return float + */ + public static function IMAGINARY($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + return $parsedComplex['imaginary']; + } // function IMAGINARY() + + + /** + * IMREAL + * + * Returns the real coefficient of a complex number in x + yi or x + yj text format. + * + * Excel Function: + * IMREAL(complexNumber) + * + * @access public + * @category Engineering Functions + * @param string $complexNumber The complex number for which you want the real coefficient. + * @return float + */ + public static function IMREAL($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + return $parsedComplex['real']; + } // function IMREAL() + + + /** + * IMABS + * + * Returns the absolute value (modulus) of a complex number in x + yi or x + yj text format. + * + * Excel Function: + * IMABS(complexNumber) + * + * @param string $complexNumber The complex number for which you want the absolute value. + * @return float + */ + public static function IMABS($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + + return sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])); + } // function IMABS() + + + /** + * IMARGUMENT + * + * Returns the argument theta of a complex number, i.e. the angle in radians from the real + * axis to the representation of the number in polar coordinates. + * + * Excel Function: + * IMARGUMENT(complexNumber) + * + * @param string $complexNumber The complex number for which you want the argument theta. + * @return float + */ + public static function IMARGUMENT($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + + if ($parsedComplex['real'] == 0.0) { + if ($parsedComplex['imaginary'] == 0.0) { + return 0.0; + } elseif($parsedComplex['imaginary'] < 0.0) { + return M_PI / -2; + } else { + return M_PI / 2; + } + } elseif ($parsedComplex['real'] > 0.0) { + return atan($parsedComplex['imaginary'] / $parsedComplex['real']); + } elseif ($parsedComplex['imaginary'] < 0.0) { + return 0 - (M_PI - atan(abs($parsedComplex['imaginary']) / abs($parsedComplex['real']))); + } else { + return M_PI - atan($parsedComplex['imaginary'] / abs($parsedComplex['real'])); + } + } // function IMARGUMENT() + + + /** + * IMCONJUGATE + * + * Returns the complex conjugate of a complex number in x + yi or x + yj text format. + * + * Excel Function: + * IMCONJUGATE(complexNumber) + * + * @param string $complexNumber The complex number for which you want the conjugate. + * @return string + */ + public static function IMCONJUGATE($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + + if ($parsedComplex['imaginary'] == 0.0) { + return $parsedComplex['real']; + } else { + return self::_cleanComplex( self::COMPLEX( $parsedComplex['real'], + 0 - $parsedComplex['imaginary'], + $parsedComplex['suffix'] + ) + ); + } + } // function IMCONJUGATE() + + + /** + * IMCOS + * + * Returns the cosine of a complex number in x + yi or x + yj text format. + * + * Excel Function: + * IMCOS(complexNumber) + * + * @param string $complexNumber The complex number for which you want the cosine. + * @return string|float + */ + public static function IMCOS($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + + if ($parsedComplex['imaginary'] == 0.0) { + return cos($parsedComplex['real']); + } else { + return self::IMCONJUGATE(self::COMPLEX(cos($parsedComplex['real']) * cosh($parsedComplex['imaginary']),sin($parsedComplex['real']) * sinh($parsedComplex['imaginary']),$parsedComplex['suffix'])); + } + } // function IMCOS() + + + /** + * IMSIN + * + * Returns the sine of a complex number in x + yi or x + yj text format. + * + * Excel Function: + * IMSIN(complexNumber) + * + * @param string $complexNumber The complex number for which you want the sine. + * @return string|float + */ + public static function IMSIN($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + + if ($parsedComplex['imaginary'] == 0.0) { + return sin($parsedComplex['real']); + } else { + return self::COMPLEX(sin($parsedComplex['real']) * cosh($parsedComplex['imaginary']),cos($parsedComplex['real']) * sinh($parsedComplex['imaginary']),$parsedComplex['suffix']); + } + } // function IMSIN() + + + /** + * IMSQRT + * + * Returns the square root of a complex number in x + yi or x + yj text format. + * + * Excel Function: + * IMSQRT(complexNumber) + * + * @param string $complexNumber The complex number for which you want the square root. + * @return string + */ + public static function IMSQRT($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + + $theta = self::IMARGUMENT($complexNumber); + $d1 = cos($theta / 2); + $d2 = sin($theta / 2); + $r = sqrt(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary']))); + + if ($parsedComplex['suffix'] == '') { + return self::COMPLEX($d1 * $r,$d2 * $r); + } else { + return self::COMPLEX($d1 * $r,$d2 * $r,$parsedComplex['suffix']); + } + } // function IMSQRT() + + + /** + * IMLN + * + * Returns the natural logarithm of a complex number in x + yi or x + yj text format. + * + * Excel Function: + * IMLN(complexNumber) + * + * @param string $complexNumber The complex number for which you want the natural logarithm. + * @return string + */ + public static function IMLN($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + + if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + + $logR = log(sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary']))); + $t = self::IMARGUMENT($complexNumber); + + if ($parsedComplex['suffix'] == '') { + return self::COMPLEX($logR,$t); + } else { + return self::COMPLEX($logR,$t,$parsedComplex['suffix']); + } + } // function IMLN() + + + /** + * IMLOG10 + * + * Returns the common logarithm (base 10) of a complex number in x + yi or x + yj text format. + * + * Excel Function: + * IMLOG10(complexNumber) + * + * @param string $complexNumber The complex number for which you want the common logarithm. + * @return string + */ + public static function IMLOG10($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + + if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) { + return PHPExcel_Calculation_Functions::NaN(); + } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) { + return log10($parsedComplex['real']); + } + + return self::IMPRODUCT(log10(EULER),self::IMLN($complexNumber)); + } // function IMLOG10() + + + /** + * IMLOG2 + * + * Returns the base-2 logarithm of a complex number in x + yi or x + yj text format. + * + * Excel Function: + * IMLOG2(complexNumber) + * + * @param string $complexNumber The complex number for which you want the base-2 logarithm. + * @return string + */ + public static function IMLOG2($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + + if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) { + return PHPExcel_Calculation_Functions::NaN(); + } elseif (($parsedComplex['real'] > 0.0) && ($parsedComplex['imaginary'] == 0.0)) { + return log($parsedComplex['real'],2); + } + + return self::IMPRODUCT(log(EULER,2),self::IMLN($complexNumber)); + } // function IMLOG2() + + + /** + * IMEXP + * + * Returns the exponential of a complex number in x + yi or x + yj text format. + * + * Excel Function: + * IMEXP(complexNumber) + * + * @param string $complexNumber The complex number for which you want the exponential. + * @return string + */ + public static function IMEXP($complexNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + + $parsedComplex = self::_parseComplex($complexNumber); + + if (($parsedComplex['real'] == 0.0) && ($parsedComplex['imaginary'] == 0.0)) { + return '1'; + } + + $e = exp($parsedComplex['real']); + $eX = $e * cos($parsedComplex['imaginary']); + $eY = $e * sin($parsedComplex['imaginary']); + + if ($parsedComplex['suffix'] == '') { + return self::COMPLEX($eX,$eY); + } else { + return self::COMPLEX($eX,$eY,$parsedComplex['suffix']); + } + } // function IMEXP() + + + /** + * IMPOWER + * + * Returns a complex number in x + yi or x + yj text format raised to a power. + * + * Excel Function: + * IMPOWER(complexNumber,realNumber) + * + * @param string $complexNumber The complex number you want to raise to a power. + * @param float $realNumber The power to which you want to raise the complex number. + * @return string + */ + public static function IMPOWER($complexNumber,$realNumber) { + $complexNumber = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber); + $realNumber = PHPExcel_Calculation_Functions::flattenSingleValue($realNumber); + + if (!is_numeric($realNumber)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + $parsedComplex = self::_parseComplex($complexNumber); + + $r = sqrt(($parsedComplex['real'] * $parsedComplex['real']) + ($parsedComplex['imaginary'] * $parsedComplex['imaginary'])); + $rPower = pow($r,$realNumber); + $theta = self::IMARGUMENT($complexNumber) * $realNumber; + if ($theta == 0) { + return 1; + } elseif ($parsedComplex['imaginary'] == 0.0) { + return self::COMPLEX($rPower * cos($theta),$rPower * sin($theta),$parsedComplex['suffix']); + } else { + return self::COMPLEX($rPower * cos($theta),$rPower * sin($theta),$parsedComplex['suffix']); + } + } // function IMPOWER() + + + /** + * IMDIV + * + * Returns the quotient of two complex numbers in x + yi or x + yj text format. + * + * Excel Function: + * IMDIV(complexDividend,complexDivisor) + * + * @param string $complexDividend The complex numerator or dividend. + * @param string $complexDivisor The complex denominator or divisor. + * @return string + */ + public static function IMDIV($complexDividend,$complexDivisor) { + $complexDividend = PHPExcel_Calculation_Functions::flattenSingleValue($complexDividend); + $complexDivisor = PHPExcel_Calculation_Functions::flattenSingleValue($complexDivisor); + + $parsedComplexDividend = self::_parseComplex($complexDividend); + $parsedComplexDivisor = self::_parseComplex($complexDivisor); + + if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] != '') && + ($parsedComplexDividend['suffix'] != $parsedComplexDivisor['suffix'])) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (($parsedComplexDividend['suffix'] != '') && ($parsedComplexDivisor['suffix'] == '')) { + $parsedComplexDivisor['suffix'] = $parsedComplexDividend['suffix']; + } + + $d1 = ($parsedComplexDividend['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['imaginary']); + $d2 = ($parsedComplexDividend['imaginary'] * $parsedComplexDivisor['real']) - ($parsedComplexDividend['real'] * $parsedComplexDivisor['imaginary']); + $d3 = ($parsedComplexDivisor['real'] * $parsedComplexDivisor['real']) + ($parsedComplexDivisor['imaginary'] * $parsedComplexDivisor['imaginary']); + + $r = $d1/$d3; + $i = $d2/$d3; + + if ($i > 0.0) { + return self::_cleanComplex($r.'+'.$i.$parsedComplexDivisor['suffix']); + } elseif ($i < 0.0) { + return self::_cleanComplex($r.$i.$parsedComplexDivisor['suffix']); + } else { + return $r; + } + } // function IMDIV() + + + /** + * IMSUB + * + * Returns the difference of two complex numbers in x + yi or x + yj text format. + * + * Excel Function: + * IMSUB(complexNumber1,complexNumber2) + * + * @param string $complexNumber1 The complex number from which to subtract complexNumber2. + * @param string $complexNumber2 The complex number to subtract from complexNumber1. + * @return string + */ + public static function IMSUB($complexNumber1,$complexNumber2) { + $complexNumber1 = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber1); + $complexNumber2 = PHPExcel_Calculation_Functions::flattenSingleValue($complexNumber2); + + $parsedComplex1 = self::_parseComplex($complexNumber1); + $parsedComplex2 = self::_parseComplex($complexNumber2); + + if ((($parsedComplex1['suffix'] != '') && ($parsedComplex2['suffix'] != '')) && + ($parsedComplex1['suffix'] != $parsedComplex2['suffix'])) { + return PHPExcel_Calculation_Functions::NaN(); + } elseif (($parsedComplex1['suffix'] == '') && ($parsedComplex2['suffix'] != '')) { + $parsedComplex1['suffix'] = $parsedComplex2['suffix']; + } + + $d1 = $parsedComplex1['real'] - $parsedComplex2['real']; + $d2 = $parsedComplex1['imaginary'] - $parsedComplex2['imaginary']; + + return self::COMPLEX($d1,$d2,$parsedComplex1['suffix']); + } // function IMSUB() + + + /** + * IMSUM + * + * Returns the sum of two or more complex numbers in x + yi or x + yj text format. + * + * Excel Function: + * IMSUM(complexNumber[,complexNumber[,...]]) + * + * @param string $complexNumber,... Series of complex numbers to add + * @return string + */ + public static function IMSUM() { + // Return value + $returnValue = self::_parseComplex('0'); + $activeSuffix = ''; + + // Loop through the arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + foreach ($aArgs as $arg) { + $parsedComplex = self::_parseComplex($arg); + + if ($activeSuffix == '') { + $activeSuffix = $parsedComplex['suffix']; + } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + $returnValue['real'] += $parsedComplex['real']; + $returnValue['imaginary'] += $parsedComplex['imaginary']; + } + + if ($returnValue['imaginary'] == 0.0) { $activeSuffix = ''; } + return self::COMPLEX($returnValue['real'],$returnValue['imaginary'],$activeSuffix); + } // function IMSUM() + + + /** + * IMPRODUCT + * + * Returns the product of two or more complex numbers in x + yi or x + yj text format. + * + * Excel Function: + * IMPRODUCT(complexNumber[,complexNumber[,...]]) + * + * @param string $complexNumber,... Series of complex numbers to multiply + * @return string + */ + public static function IMPRODUCT() { + // Return value + $returnValue = self::_parseComplex('1'); + $activeSuffix = ''; + + // Loop through the arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + foreach ($aArgs as $arg) { + $parsedComplex = self::_parseComplex($arg); + + $workValue = $returnValue; + if (($parsedComplex['suffix'] != '') && ($activeSuffix == '')) { + $activeSuffix = $parsedComplex['suffix']; + } elseif (($parsedComplex['suffix'] != '') && ($activeSuffix != $parsedComplex['suffix'])) { + return PHPExcel_Calculation_Functions::NaN(); + } + $returnValue['real'] = ($workValue['real'] * $parsedComplex['real']) - ($workValue['imaginary'] * $parsedComplex['imaginary']); + $returnValue['imaginary'] = ($workValue['real'] * $parsedComplex['imaginary']) + ($workValue['imaginary'] * $parsedComplex['real']); + } + + if ($returnValue['imaginary'] == 0.0) { $activeSuffix = ''; } + return self::COMPLEX($returnValue['real'],$returnValue['imaginary'],$activeSuffix); + } // function IMPRODUCT() + + + /** + * DELTA + * + * Tests whether two values are equal. Returns 1 if number1 = number2; returns 0 otherwise. + * Use this function to filter a set of values. For example, by summing several DELTA + * functions you calculate the count of equal pairs. This function is also known as the + * Kronecker Delta function. + * + * Excel Function: + * DELTA(a[,b]) + * + * @param float $a The first number. + * @param float $b The second number. If omitted, b is assumed to be zero. + * @return int + */ + public static function DELTA($a, $b=0) { + $a = PHPExcel_Calculation_Functions::flattenSingleValue($a); + $b = PHPExcel_Calculation_Functions::flattenSingleValue($b); + + return (int) ($a == $b); + } // function DELTA() + + + /** + * GESTEP + * + * Excel Function: + * GESTEP(number[,step]) + * + * Returns 1 if number >= step; returns 0 (zero) otherwise + * Use this function to filter a set of values. For example, by summing several GESTEP + * functions you calculate the count of values that exceed a threshold. + * + * @param float $number The value to test against step. + * @param float $step The threshold value. + * If you omit a value for step, GESTEP uses zero. + * @return int + */ + public static function GESTEP($number, $step=0) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + $step = PHPExcel_Calculation_Functions::flattenSingleValue($step); + + return (int) ($number >= $step); + } // function GESTEP() + + + // + // Private method to calculate the erf value + // + private static $_two_sqrtpi = 1.128379167095512574; + + public static function _erfVal($x) { + if (abs($x) > 2.2) { + return 1 - self::_erfcVal($x); + } + $sum = $term = $x; + $xsqr = ($x * $x); + $j = 1; + do { + $term *= $xsqr / $j; + $sum -= $term / (2 * $j + 1); + ++$j; + $term *= $xsqr / $j; + $sum += $term / (2 * $j + 1); + ++$j; + if ($sum == 0.0) { + break; + } + } while (abs($term / $sum) > PRECISION); + return self::$_two_sqrtpi * $sum; + } // function _erfVal() + + + /** + * ERF + * + * Returns the error function integrated between the lower and upper bound arguments. + * + * Note: In Excel 2007 or earlier, if you input a negative value for the upper or lower bound arguments, + * the function would return a #NUM! error. However, in Excel 2010, the function algorithm was + * improved, so that it can now calculate the function for both positive and negative ranges. + * PHPExcel follows Excel 2010 behaviour, and accepts nagative arguments. + * + * Excel Function: + * ERF(lower[,upper]) + * + * @param float $lower lower bound for integrating ERF + * @param float $upper upper bound for integrating ERF. + * If omitted, ERF integrates between zero and lower_limit + * @return float + */ + public static function ERF($lower, $upper = NULL) { + $lower = PHPExcel_Calculation_Functions::flattenSingleValue($lower); + $upper = PHPExcel_Calculation_Functions::flattenSingleValue($upper); + + if (is_numeric($lower)) { + if (is_null($upper)) { + return self::_erfVal($lower); + } + if (is_numeric($upper)) { + return self::_erfVal($upper) - self::_erfVal($lower); + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function ERF() + + + // + // Private method to calculate the erfc value + // + private static $_one_sqrtpi = 0.564189583547756287; + + private static function _erfcVal($x) { + if (abs($x) < 2.2) { + return 1 - self::_erfVal($x); + } + if ($x < 0) { + return 2 - self::ERFC(-$x); + } + $a = $n = 1; + $b = $c = $x; + $d = ($x * $x) + 0.5; + $q1 = $q2 = $b / $d; + $t = 0; + do { + $t = $a * $n + $b * $x; + $a = $b; + $b = $t; + $t = $c * $n + $d * $x; + $c = $d; + $d = $t; + $n += 0.5; + $q1 = $q2; + $q2 = $b / $d; + } while ((abs($q1 - $q2) / $q2) > PRECISION); + return self::$_one_sqrtpi * exp(-$x * $x) * $q2; + } // function _erfcVal() + + + /** + * ERFC + * + * Returns the complementary ERF function integrated between x and infinity + * + * Note: In Excel 2007 or earlier, if you input a negative value for the lower bound argument, + * the function would return a #NUM! error. However, in Excel 2010, the function algorithm was + * improved, so that it can now calculate the function for both positive and negative x values. + * PHPExcel follows Excel 2010 behaviour, and accepts nagative arguments. + * + * Excel Function: + * ERFC(x) + * + * @param float $x The lower bound for integrating ERFC + * @return float + */ + public static function ERFC($x) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + + if (is_numeric($x)) { + return self::_erfcVal($x); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function ERFC() + + + /** + * getConversionGroups + * Returns a list of the different conversion groups for UOM conversions + * + * @return array + */ + public static function getConversionGroups() { + $conversionGroups = array(); + foreach(self::$_conversionUnits as $conversionUnit) { + $conversionGroups[] = $conversionUnit['Group']; + } + return array_merge(array_unique($conversionGroups)); + } // function getConversionGroups() + + + /** + * getConversionGroupUnits + * Returns an array of units of measure, for a specified conversion group, or for all groups + * + * @param string $group The group whose units of measure you want to retrieve + * @return array + */ + public static function getConversionGroupUnits($group = NULL) { + $conversionGroups = array(); + foreach(self::$_conversionUnits as $conversionUnit => $conversionGroup) { + if ((is_null($group)) || ($conversionGroup['Group'] == $group)) { + $conversionGroups[$conversionGroup['Group']][] = $conversionUnit; + } + } + return $conversionGroups; + } // function getConversionGroupUnits() + + + /** + * getConversionGroupUnitDetails + * + * @param string $group The group whose units of measure you want to retrieve + * @return array + */ + public static function getConversionGroupUnitDetails($group = NULL) { + $conversionGroups = array(); + foreach(self::$_conversionUnits as $conversionUnit => $conversionGroup) { + if ((is_null($group)) || ($conversionGroup['Group'] == $group)) { + $conversionGroups[$conversionGroup['Group']][] = array( 'unit' => $conversionUnit, + 'description' => $conversionGroup['Unit Name'] + ); + } + } + return $conversionGroups; + } // function getConversionGroupUnitDetails() + + + /** + * getConversionMultipliers + * Returns an array of the Multiplier prefixes that can be used with Units of Measure in CONVERTUOM() + * + * @return array of mixed + */ + public static function getConversionMultipliers() { + return self::$_conversionMultipliers; + } // function getConversionGroups() + + + /** + * CONVERTUOM + * + * Converts a number from one measurement system to another. + * For example, CONVERT can translate a table of distances in miles to a table of distances + * in kilometers. + * + * Excel Function: + * CONVERT(value,fromUOM,toUOM) + * + * @param float $value The value in fromUOM to convert. + * @param string $fromUOM The units for value. + * @param string $toUOM The units for the result. + * + * @return float + */ + public static function CONVERTUOM($value, $fromUOM, $toUOM) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $fromUOM = PHPExcel_Calculation_Functions::flattenSingleValue($fromUOM); + $toUOM = PHPExcel_Calculation_Functions::flattenSingleValue($toUOM); + + if (!is_numeric($value)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $fromMultiplier = 1.0; + if (isset(self::$_conversionUnits[$fromUOM])) { + $unitGroup1 = self::$_conversionUnits[$fromUOM]['Group']; + } else { + $fromMultiplier = substr($fromUOM,0,1); + $fromUOM = substr($fromUOM,1); + if (isset(self::$_conversionMultipliers[$fromMultiplier])) { + $fromMultiplier = self::$_conversionMultipliers[$fromMultiplier]['multiplier']; + } else { + return PHPExcel_Calculation_Functions::NA(); + } + if ((isset(self::$_conversionUnits[$fromUOM])) && (self::$_conversionUnits[$fromUOM]['AllowPrefix'])) { + $unitGroup1 = self::$_conversionUnits[$fromUOM]['Group']; + } else { + return PHPExcel_Calculation_Functions::NA(); + } + } + $value *= $fromMultiplier; + + $toMultiplier = 1.0; + if (isset(self::$_conversionUnits[$toUOM])) { + $unitGroup2 = self::$_conversionUnits[$toUOM]['Group']; + } else { + $toMultiplier = substr($toUOM,0,1); + $toUOM = substr($toUOM,1); + if (isset(self::$_conversionMultipliers[$toMultiplier])) { + $toMultiplier = self::$_conversionMultipliers[$toMultiplier]['multiplier']; + } else { + return PHPExcel_Calculation_Functions::NA(); + } + if ((isset(self::$_conversionUnits[$toUOM])) && (self::$_conversionUnits[$toUOM]['AllowPrefix'])) { + $unitGroup2 = self::$_conversionUnits[$toUOM]['Group']; + } else { + return PHPExcel_Calculation_Functions::NA(); + } + } + if ($unitGroup1 != $unitGroup2) { + return PHPExcel_Calculation_Functions::NA(); + } + + if (($fromUOM == $toUOM) && ($fromMultiplier == $toMultiplier)) { + // We've already factored $fromMultiplier into the value, so we need + // to reverse it again + return $value / $fromMultiplier; + } elseif ($unitGroup1 == 'Temperature') { + if (($fromUOM == 'F') || ($fromUOM == 'fah')) { + if (($toUOM == 'F') || ($toUOM == 'fah')) { + return $value; + } else { + $value = (($value - 32) / 1.8); + if (($toUOM == 'K') || ($toUOM == 'kel')) { + $value += 273.15; + } + return $value; + } + } elseif ((($fromUOM == 'K') || ($fromUOM == 'kel')) && + (($toUOM == 'K') || ($toUOM == 'kel'))) { + return $value; + } elseif ((($fromUOM == 'C') || ($fromUOM == 'cel')) && + (($toUOM == 'C') || ($toUOM == 'cel'))) { + return $value; + } + if (($toUOM == 'F') || ($toUOM == 'fah')) { + if (($fromUOM == 'K') || ($fromUOM == 'kel')) { + $value -= 273.15; + } + return ($value * 1.8) + 32; + } + if (($toUOM == 'C') || ($toUOM == 'cel')) { + return $value - 273.15; + } + return $value + 273.15; + } + return ($value * self::$_unitConversions[$unitGroup1][$fromUOM][$toUOM]) / $toMultiplier; + } // function CONVERTUOM() + +} // class PHPExcel_Calculation_Engineering diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Exception.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Exception.php new file mode 100755 index 0000000..262e6b9 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Exception.php @@ -0,0 +1,52 @@ +line = $line; + $e->file = $file; + throw $e; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/ExceptionHandler.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/ExceptionHandler.php new file mode 100755 index 0000000..a0f1dd4 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/ExceptionHandler.php @@ -0,0 +1,49 @@ +format('d') == $testDate->format('t')); + } // function _lastDayOfMonth() + + + /** + * _firstDayOfMonth + * + * Returns a boolean TRUE/FALSE indicating if this date is the first date of the month + * + * @param DateTime $testDate The date for testing + * @return boolean + */ + private static function _firstDayOfMonth($testDate) + { + return ($testDate->format('d') == 1); + } // function _firstDayOfMonth() + + + private static function _coupFirstPeriodDate($settlement, $maturity, $frequency, $next) + { + $months = 12 / $frequency; + + $result = PHPExcel_Shared_Date::ExcelToPHPObject($maturity); + $eom = self::_lastDayOfMonth($result); + + while ($settlement < PHPExcel_Shared_Date::PHPToExcel($result)) { + $result->modify('-'.$months.' months'); + } + if ($next) { + $result->modify('+'.$months.' months'); + } + + if ($eom) { + $result->modify('-1 day'); + } + + return PHPExcel_Shared_Date::PHPToExcel($result); + } // function _coupFirstPeriodDate() + + + private static function _validFrequency($frequency) + { + if (($frequency == 1) || ($frequency == 2) || ($frequency == 4)) { + return true; + } + if ((PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) && + (($frequency == 6) || ($frequency == 12))) { + return true; + } + return false; + } // function _validFrequency() + + + /** + * _daysPerYear + * + * Returns the number of days in a specified year, as defined by the "basis" value + * + * @param integer $year The year against which we're testing + * @param integer $basis The type of day count: + * 0 or omitted US (NASD) 360 + * 1 Actual (365 or 366 in a leap year) + * 2 360 + * 3 365 + * 4 European 360 + * @return integer + */ + private static function _daysPerYear($year, $basis=0) + { + switch ($basis) { + case 0 : + case 2 : + case 4 : + $daysPerYear = 360; + break; + case 3 : + $daysPerYear = 365; + break; + case 1 : + $daysPerYear = (PHPExcel_Calculation_DateTime::_isLeapYear($year)) ? 366 : 365; + break; + default : + return PHPExcel_Calculation_Functions::NaN(); + } + return $daysPerYear; + } // function _daysPerYear() + + + private static function _interestAndPrincipal($rate=0, $per=0, $nper=0, $pv=0, $fv=0, $type=0) + { + $pmt = self::PMT($rate, $nper, $pv, $fv, $type); + $capital = $pv; + for ($i = 1; $i<= $per; ++$i) { + $interest = ($type && $i == 1) ? 0 : -$capital * $rate; + $principal = $pmt - $interest; + $capital += $principal; + } + return array($interest, $principal); + } // function _interestAndPrincipal() + + + /** + * ACCRINT + * + * Returns the accrued interest for a security that pays periodic interest. + * + * Excel Function: + * ACCRINT(issue,firstinterest,settlement,rate,par,frequency[,basis]) + * + * @access public + * @category Financial Functions + * @param mixed $issue The security's issue date. + * @param mixed $firstinterest The security's first interest date. + * @param mixed $settlement The security's settlement date. + * The security settlement date is the date after the issue date + * when the security is traded to the buyer. + * @param float $rate The security's annual coupon rate. + * @param float $par The security's par value. + * If you omit par, ACCRINT uses $1,000. + * @param integer $frequency the number of coupon payments per year. + * Valid frequency values are: + * 1 Annual + * 2 Semi-Annual + * 4 Quarterly + * If working in Gnumeric Mode, the following frequency options are + * also available + * 6 Bimonthly + * 12 Monthly + * @param integer $basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function ACCRINT($issue, $firstinterest, $settlement, $rate, $par=1000, $frequency=1, $basis=0) + { + $issue = PHPExcel_Calculation_Functions::flattenSingleValue($issue); + $firstinterest = PHPExcel_Calculation_Functions::flattenSingleValue($firstinterest); + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $par = (is_null($par)) ? 1000 : PHPExcel_Calculation_Functions::flattenSingleValue($par); + $frequency = (is_null($frequency)) ? 1 : PHPExcel_Calculation_Functions::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + // Validate + if ((is_numeric($rate)) && (is_numeric($par))) { + $rate = (float) $rate; + $par = (float) $par; + if (($rate <= 0) || ($par <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $daysBetweenIssueAndSettlement = PHPExcel_Calculation_DateTime::YEARFRAC($issue, $settlement, $basis); + if (!is_numeric($daysBetweenIssueAndSettlement)) { + // return date error + return $daysBetweenIssueAndSettlement; + } + + return $par * $rate * $daysBetweenIssueAndSettlement; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function ACCRINT() + + + /** + * ACCRINTM + * + * Returns the accrued interest for a security that pays interest at maturity. + * + * Excel Function: + * ACCRINTM(issue,settlement,rate[,par[,basis]]) + * + * @access public + * @category Financial Functions + * @param mixed issue The security's issue date. + * @param mixed settlement The security's settlement (or maturity) date. + * @param float rate The security's annual coupon rate. + * @param float par The security's par value. + * If you omit par, ACCRINT uses $1,000. + * @param integer basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function ACCRINTM($issue, $settlement, $rate, $par=1000, $basis=0) { + $issue = PHPExcel_Calculation_Functions::flattenSingleValue($issue); + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $par = (is_null($par)) ? 1000 : PHPExcel_Calculation_Functions::flattenSingleValue($par); + $basis = (is_null($basis)) ? 0 : PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + // Validate + if ((is_numeric($rate)) && (is_numeric($par))) { + $rate = (float) $rate; + $par = (float) $par; + if (($rate <= 0) || ($par <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $daysBetweenIssueAndSettlement = PHPExcel_Calculation_DateTime::YEARFRAC($issue, $settlement, $basis); + if (!is_numeric($daysBetweenIssueAndSettlement)) { + // return date error + return $daysBetweenIssueAndSettlement; + } + return $par * $rate * $daysBetweenIssueAndSettlement; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function ACCRINTM() + + + /** + * AMORDEGRC + * + * Returns the depreciation for each accounting period. + * This function is provided for the French accounting system. If an asset is purchased in + * the middle of the accounting period, the prorated depreciation is taken into account. + * The function is similar to AMORLINC, except that a depreciation coefficient is applied in + * the calculation depending on the life of the assets. + * This function will return the depreciation until the last period of the life of the assets + * or until the cumulated value of depreciation is greater than the cost of the assets minus + * the salvage value. + * + * Excel Function: + * AMORDEGRC(cost,purchased,firstPeriod,salvage,period,rate[,basis]) + * + * @access public + * @category Financial Functions + * @param float cost The cost of the asset. + * @param mixed purchased Date of the purchase of the asset. + * @param mixed firstPeriod Date of the end of the first period. + * @param mixed salvage The salvage value at the end of the life of the asset. + * @param float period The period. + * @param float rate Rate of depreciation. + * @param integer basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function AMORDEGRC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis=0) { + $cost = PHPExcel_Calculation_Functions::flattenSingleValue($cost); + $purchased = PHPExcel_Calculation_Functions::flattenSingleValue($purchased); + $firstPeriod = PHPExcel_Calculation_Functions::flattenSingleValue($firstPeriod); + $salvage = PHPExcel_Calculation_Functions::flattenSingleValue($salvage); + $period = floor(PHPExcel_Calculation_Functions::flattenSingleValue($period)); + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + // The depreciation coefficients are: + // Life of assets (1/rate) Depreciation coefficient + // Less than 3 years 1 + // Between 3 and 4 years 1.5 + // Between 5 and 6 years 2 + // More than 6 years 2.5 + $fUsePer = 1.0 / $rate; + if ($fUsePer < 3.0) { + $amortiseCoeff = 1.0; + } elseif ($fUsePer < 5.0) { + $amortiseCoeff = 1.5; + } elseif ($fUsePer <= 6.0) { + $amortiseCoeff = 2.0; + } else { + $amortiseCoeff = 2.5; + } + + $rate *= $amortiseCoeff; + $fNRate = round(PHPExcel_Calculation_DateTime::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost,0); + $cost -= $fNRate; + $fRest = $cost - $salvage; + + for ($n = 0; $n < $period; ++$n) { + $fNRate = round($rate * $cost,0); + $fRest -= $fNRate; + + if ($fRest < 0.0) { + switch ($period - $n) { + case 0 : + case 1 : return round($cost * 0.5, 0); + break; + default : return 0.0; + break; + } + } + $cost -= $fNRate; + } + return $fNRate; + } // function AMORDEGRC() + + + /** + * AMORLINC + * + * Returns the depreciation for each accounting period. + * This function is provided for the French accounting system. If an asset is purchased in + * the middle of the accounting period, the prorated depreciation is taken into account. + * + * Excel Function: + * AMORLINC(cost,purchased,firstPeriod,salvage,period,rate[,basis]) + * + * @access public + * @category Financial Functions + * @param float cost The cost of the asset. + * @param mixed purchased Date of the purchase of the asset. + * @param mixed firstPeriod Date of the end of the first period. + * @param mixed salvage The salvage value at the end of the life of the asset. + * @param float period The period. + * @param float rate Rate of depreciation. + * @param integer basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function AMORLINC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis=0) { + $cost = PHPExcel_Calculation_Functions::flattenSingleValue($cost); + $purchased = PHPExcel_Calculation_Functions::flattenSingleValue($purchased); + $firstPeriod = PHPExcel_Calculation_Functions::flattenSingleValue($firstPeriod); + $salvage = PHPExcel_Calculation_Functions::flattenSingleValue($salvage); + $period = PHPExcel_Calculation_Functions::flattenSingleValue($period); + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + $fOneRate = $cost * $rate; + $fCostDelta = $cost - $salvage; + // Note, quirky variation for leap years on the YEARFRAC for this function + $purchasedYear = PHPExcel_Calculation_DateTime::YEAR($purchased); + $yearFrac = PHPExcel_Calculation_DateTime::YEARFRAC($purchased, $firstPeriod, $basis); + + if (($basis == 1) && ($yearFrac < 1) && (PHPExcel_Calculation_DateTime::_isLeapYear($purchasedYear))) { + $yearFrac *= 365 / 366; + } + + $f0Rate = $yearFrac * $rate * $cost; + $nNumOfFullPeriods = intval(($cost - $salvage - $f0Rate) / $fOneRate); + + if ($period == 0) { + return $f0Rate; + } elseif ($period <= $nNumOfFullPeriods) { + return $fOneRate; + } elseif ($period == ($nNumOfFullPeriods + 1)) { + return ($fCostDelta - $fOneRate * $nNumOfFullPeriods - $f0Rate); + } else { + return 0.0; + } + } // function AMORLINC() + + + /** + * COUPDAYBS + * + * Returns the number of days from the beginning of the coupon period to the settlement date. + * + * Excel Function: + * COUPDAYBS(settlement,maturity,frequency[,basis]) + * + * @access public + * @category Financial Functions + * @param mixed settlement The security's settlement date. + * The security settlement date is the date after the issue + * date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param mixed frequency the number of coupon payments per year. + * Valid frequency values are: + * 1 Annual + * 2 Semi-Annual + * 4 Quarterly + * If working in Gnumeric Mode, the following frequency options are + * also available + * 6 Bimonthly + * 12 Monthly + * @param integer basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function COUPDAYBS($settlement, $maturity, $frequency, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + if (is_string($settlement = PHPExcel_Calculation_DateTime::_getDateValue($settlement))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (is_string($maturity = PHPExcel_Calculation_DateTime::_getDateValue($maturity))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return PHPExcel_Calculation_Functions::NaN(); + } + + $daysPerYear = self::_daysPerYear(PHPExcel_Calculation_DateTime::YEAR($settlement),$basis); + $prev = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, False); + + return PHPExcel_Calculation_DateTime::YEARFRAC($prev, $settlement, $basis) * $daysPerYear; + } // function COUPDAYBS() + + + /** + * COUPDAYS + * + * Returns the number of days in the coupon period that contains the settlement date. + * + * Excel Function: + * COUPDAYS(settlement,maturity,frequency[,basis]) + * + * @access public + * @category Financial Functions + * @param mixed settlement The security's settlement date. + * The security settlement date is the date after the issue + * date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param mixed frequency the number of coupon payments per year. + * Valid frequency values are: + * 1 Annual + * 2 Semi-Annual + * 4 Quarterly + * If working in Gnumeric Mode, the following frequency options are + * also available + * 6 Bimonthly + * 12 Monthly + * @param integer basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function COUPDAYS($settlement, $maturity, $frequency, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + if (is_string($settlement = PHPExcel_Calculation_DateTime::_getDateValue($settlement))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (is_string($maturity = PHPExcel_Calculation_DateTime::_getDateValue($maturity))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return PHPExcel_Calculation_Functions::NaN(); + } + + switch ($basis) { + case 3: // Actual/365 + return 365 / $frequency; + case 1: // Actual/actual + if ($frequency == 1) { + $daysPerYear = self::_daysPerYear(PHPExcel_Calculation_DateTime::YEAR($maturity),$basis); + return ($daysPerYear / $frequency); + } else { + $prev = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, False); + $next = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); + return ($next - $prev); + } + default: // US (NASD) 30/360, Actual/360 or European 30/360 + return 360 / $frequency; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function COUPDAYS() + + + /** + * COUPDAYSNC + * + * Returns the number of days from the settlement date to the next coupon date. + * + * Excel Function: + * COUPDAYSNC(settlement,maturity,frequency[,basis]) + * + * @access public + * @category Financial Functions + * @param mixed settlement The security's settlement date. + * The security settlement date is the date after the issue + * date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param mixed frequency the number of coupon payments per year. + * Valid frequency values are: + * 1 Annual + * 2 Semi-Annual + * 4 Quarterly + * If working in Gnumeric Mode, the following frequency options are + * also available + * 6 Bimonthly + * 12 Monthly + * @param integer basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function COUPDAYSNC($settlement, $maturity, $frequency, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + if (is_string($settlement = PHPExcel_Calculation_DateTime::_getDateValue($settlement))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (is_string($maturity = PHPExcel_Calculation_DateTime::_getDateValue($maturity))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return PHPExcel_Calculation_Functions::NaN(); + } + + $daysPerYear = self::_daysPerYear(PHPExcel_Calculation_DateTime::YEAR($settlement),$basis); + $next = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); + + return PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $next, $basis) * $daysPerYear; + } // function COUPDAYSNC() + + + /** + * COUPNCD + * + * Returns the next coupon date after the settlement date. + * + * Excel Function: + * COUPNCD(settlement,maturity,frequency[,basis]) + * + * @access public + * @category Financial Functions + * @param mixed settlement The security's settlement date. + * The security settlement date is the date after the issue + * date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param mixed frequency the number of coupon payments per year. + * Valid frequency values are: + * 1 Annual + * 2 Semi-Annual + * 4 Quarterly + * If working in Gnumeric Mode, the following frequency options are + * also available + * 6 Bimonthly + * 12 Monthly + * @param integer basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function COUPNCD($settlement, $maturity, $frequency, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + if (is_string($settlement = PHPExcel_Calculation_DateTime::_getDateValue($settlement))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (is_string($maturity = PHPExcel_Calculation_DateTime::_getDateValue($maturity))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return PHPExcel_Calculation_Functions::NaN(); + } + + return self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); + } // function COUPNCD() + + + /** + * COUPNUM + * + * Returns the number of coupons payable between the settlement date and maturity date, + * rounded up to the nearest whole coupon. + * + * Excel Function: + * COUPNUM(settlement,maturity,frequency[,basis]) + * + * @access public + * @category Financial Functions + * @param mixed settlement The security's settlement date. + * The security settlement date is the date after the issue + * date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param mixed frequency the number of coupon payments per year. + * Valid frequency values are: + * 1 Annual + * 2 Semi-Annual + * 4 Quarterly + * If working in Gnumeric Mode, the following frequency options are + * also available + * 6 Bimonthly + * 12 Monthly + * @param integer basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return integer + */ + public static function COUPNUM($settlement, $maturity, $frequency, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + if (is_string($settlement = PHPExcel_Calculation_DateTime::_getDateValue($settlement))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (is_string($maturity = PHPExcel_Calculation_DateTime::_getDateValue($maturity))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return PHPExcel_Calculation_Functions::NaN(); + } + + $settlement = self::_coupFirstPeriodDate($settlement, $maturity, $frequency, True); + $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity, $basis) * 365; + + switch ($frequency) { + case 1: // annual payments + return ceil($daysBetweenSettlementAndMaturity / 360); + case 2: // half-yearly + return ceil($daysBetweenSettlementAndMaturity / 180); + case 4: // quarterly + return ceil($daysBetweenSettlementAndMaturity / 90); + case 6: // bimonthly + return ceil($daysBetweenSettlementAndMaturity / 60); + case 12: // monthly + return ceil($daysBetweenSettlementAndMaturity / 30); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function COUPNUM() + + + /** + * COUPPCD + * + * Returns the previous coupon date before the settlement date. + * + * Excel Function: + * COUPPCD(settlement,maturity,frequency[,basis]) + * + * @access public + * @category Financial Functions + * @param mixed settlement The security's settlement date. + * The security settlement date is the date after the issue + * date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param mixed frequency the number of coupon payments per year. + * Valid frequency values are: + * 1 Annual + * 2 Semi-Annual + * 4 Quarterly + * If working in Gnumeric Mode, the following frequency options are + * also available + * 6 Bimonthly + * 12 Monthly + * @param integer basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function COUPPCD($settlement, $maturity, $frequency, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + if (is_string($settlement = PHPExcel_Calculation_DateTime::_getDateValue($settlement))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (is_string($maturity = PHPExcel_Calculation_DateTime::_getDateValue($maturity))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return PHPExcel_Calculation_Functions::NaN(); + } + + return self::_coupFirstPeriodDate($settlement, $maturity, $frequency, False); + } // function COUPPCD() + + + /** + * CUMIPMT + * + * Returns the cumulative interest paid on a loan between the start and end periods. + * + * Excel Function: + * CUMIPMT(rate,nper,pv,start,end[,type]) + * + * @access public + * @category Financial Functions + * @param float $rate The Interest rate + * @param integer $nper The total number of payment periods + * @param float $pv Present Value + * @param integer $start The first period in the calculation. + * Payment periods are numbered beginning with 1. + * @param integer $end The last period in the calculation. + * @param integer $type A number 0 or 1 and indicates when payments are due: + * 0 or omitted At the end of the period. + * 1 At the beginning of the period. + * @return float + */ + public static function CUMIPMT($rate, $nper, $pv, $start, $end, $type = 0) { + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $nper = (int) PHPExcel_Calculation_Functions::flattenSingleValue($nper); + $pv = PHPExcel_Calculation_Functions::flattenSingleValue($pv); + $start = (int) PHPExcel_Calculation_Functions::flattenSingleValue($start); + $end = (int) PHPExcel_Calculation_Functions::flattenSingleValue($end); + $type = (int) PHPExcel_Calculation_Functions::flattenSingleValue($type); + + // Validate parameters + if ($type != 0 && $type != 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ($start < 1 || $start > $end) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + // Calculate + $interest = 0; + for ($per = $start; $per <= $end; ++$per) { + $interest += self::IPMT($rate, $per, $nper, $pv, 0, $type); + } + + return $interest; + } // function CUMIPMT() + + + /** + * CUMPRINC + * + * Returns the cumulative principal paid on a loan between the start and end periods. + * + * Excel Function: + * CUMPRINC(rate,nper,pv,start,end[,type]) + * + * @access public + * @category Financial Functions + * @param float $rate The Interest rate + * @param integer $nper The total number of payment periods + * @param float $pv Present Value + * @param integer $start The first period in the calculation. + * Payment periods are numbered beginning with 1. + * @param integer $end The last period in the calculation. + * @param integer $type A number 0 or 1 and indicates when payments are due: + * 0 or omitted At the end of the period. + * 1 At the beginning of the period. + * @return float + */ + public static function CUMPRINC($rate, $nper, $pv, $start, $end, $type = 0) { + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $nper = (int) PHPExcel_Calculation_Functions::flattenSingleValue($nper); + $pv = PHPExcel_Calculation_Functions::flattenSingleValue($pv); + $start = (int) PHPExcel_Calculation_Functions::flattenSingleValue($start); + $end = (int) PHPExcel_Calculation_Functions::flattenSingleValue($end); + $type = (int) PHPExcel_Calculation_Functions::flattenSingleValue($type); + + // Validate parameters + if ($type != 0 && $type != 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ($start < 1 || $start > $end) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + // Calculate + $principal = 0; + for ($per = $start; $per <= $end; ++$per) { + $principal += self::PPMT($rate, $per, $nper, $pv, 0, $type); + } + + return $principal; + } // function CUMPRINC() + + + /** + * DB + * + * Returns the depreciation of an asset for a specified period using the + * fixed-declining balance method. + * This form of depreciation is used if you want to get a higher depreciation value + * at the beginning of the depreciation (as opposed to linear depreciation). The + * depreciation value is reduced with every depreciation period by the depreciation + * already deducted from the initial cost. + * + * Excel Function: + * DB(cost,salvage,life,period[,month]) + * + * @access public + * @category Financial Functions + * @param float cost Initial cost of the asset. + * @param float salvage Value at the end of the depreciation. + * (Sometimes called the salvage value of the asset) + * @param integer life Number of periods over which the asset is depreciated. + * (Sometimes called the useful life of the asset) + * @param integer period The period for which you want to calculate the + * depreciation. Period must use the same units as life. + * @param integer month Number of months in the first year. If month is omitted, + * it defaults to 12. + * @return float + */ + public static function DB($cost, $salvage, $life, $period, $month=12) { + $cost = PHPExcel_Calculation_Functions::flattenSingleValue($cost); + $salvage = PHPExcel_Calculation_Functions::flattenSingleValue($salvage); + $life = PHPExcel_Calculation_Functions::flattenSingleValue($life); + $period = PHPExcel_Calculation_Functions::flattenSingleValue($period); + $month = PHPExcel_Calculation_Functions::flattenSingleValue($month); + + // Validate + if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($month))) { + $cost = (float) $cost; + $salvage = (float) $salvage; + $life = (int) $life; + $period = (int) $period; + $month = (int) $month; + if ($cost == 0) { + return 0.0; + } elseif (($cost < 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($month < 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + // Set Fixed Depreciation Rate + $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life)); + $fixedDepreciationRate = round($fixedDepreciationRate, 3); + + // Loop through each period calculating the depreciation + $previousDepreciation = 0; + for ($per = 1; $per <= $period; ++$per) { + if ($per == 1) { + $depreciation = $cost * $fixedDepreciationRate * $month / 12; + } elseif ($per == ($life + 1)) { + $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate * (12 - $month) / 12; + } else { + $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate; + } + $previousDepreciation += $depreciation; + } + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) { + $depreciation = round($depreciation,2); + } + return $depreciation; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function DB() + + + /** + * DDB + * + * Returns the depreciation of an asset for a specified period using the + * double-declining balance method or some other method you specify. + * + * Excel Function: + * DDB(cost,salvage,life,period[,factor]) + * + * @access public + * @category Financial Functions + * @param float cost Initial cost of the asset. + * @param float salvage Value at the end of the depreciation. + * (Sometimes called the salvage value of the asset) + * @param integer life Number of periods over which the asset is depreciated. + * (Sometimes called the useful life of the asset) + * @param integer period The period for which you want to calculate the + * depreciation. Period must use the same units as life. + * @param float factor The rate at which the balance declines. + * If factor is omitted, it is assumed to be 2 (the + * double-declining balance method). + * @return float + */ + public static function DDB($cost, $salvage, $life, $period, $factor=2.0) { + $cost = PHPExcel_Calculation_Functions::flattenSingleValue($cost); + $salvage = PHPExcel_Calculation_Functions::flattenSingleValue($salvage); + $life = PHPExcel_Calculation_Functions::flattenSingleValue($life); + $period = PHPExcel_Calculation_Functions::flattenSingleValue($period); + $factor = PHPExcel_Calculation_Functions::flattenSingleValue($factor); + + // Validate + if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($factor))) { + $cost = (float) $cost; + $salvage = (float) $salvage; + $life = (int) $life; + $period = (int) $period; + $factor = (float) $factor; + if (($cost <= 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($factor <= 0.0) || ($period > $life)) { + return PHPExcel_Calculation_Functions::NaN(); + } + // Set Fixed Depreciation Rate + $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life)); + $fixedDepreciationRate = round($fixedDepreciationRate, 3); + + // Loop through each period calculating the depreciation + $previousDepreciation = 0; + for ($per = 1; $per <= $period; ++$per) { + $depreciation = min( ($cost - $previousDepreciation) * ($factor / $life), ($cost - $salvage - $previousDepreciation) ); + $previousDepreciation += $depreciation; + } + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) { + $depreciation = round($depreciation,2); + } + return $depreciation; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function DDB() + + + /** + * DISC + * + * Returns the discount rate for a security. + * + * Excel Function: + * DISC(settlement,maturity,price,redemption[,basis]) + * + * @access public + * @category Financial Functions + * @param mixed settlement The security's settlement date. + * The security settlement date is the date after the issue + * date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param integer price The security's price per $100 face value. + * @param integer redemption The security's redemption value per $100 face value. + * @param integer basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function DISC($settlement, $maturity, $price, $redemption, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $price = PHPExcel_Calculation_Functions::flattenSingleValue($price); + $redemption = PHPExcel_Calculation_Functions::flattenSingleValue($redemption); + $basis = PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + // Validate + if ((is_numeric($price)) && (is_numeric($redemption)) && (is_numeric($basis))) { + $price = (float) $price; + $redemption = (float) $redemption; + $basis = (int) $basis; + if (($price <= 0) || ($redemption <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity, $basis); + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + // return date error + return $daysBetweenSettlementAndMaturity; + } + + return ((1 - $price / $redemption) / $daysBetweenSettlementAndMaturity); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function DISC() + + + /** + * DOLLARDE + * + * Converts a dollar price expressed as an integer part and a fraction + * part into a dollar price expressed as a decimal number. + * Fractional dollar numbers are sometimes used for security prices. + * + * Excel Function: + * DOLLARDE(fractional_dollar,fraction) + * + * @access public + * @category Financial Functions + * @param float $fractional_dollar Fractional Dollar + * @param integer $fraction Fraction + * @return float + */ + public static function DOLLARDE($fractional_dollar = Null, $fraction = 0) { + $fractional_dollar = PHPExcel_Calculation_Functions::flattenSingleValue($fractional_dollar); + $fraction = (int)PHPExcel_Calculation_Functions::flattenSingleValue($fraction); + + // Validate parameters + if (is_null($fractional_dollar) || $fraction < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ($fraction == 0) { + return PHPExcel_Calculation_Functions::DIV0(); + } + + $dollars = floor($fractional_dollar); + $cents = fmod($fractional_dollar,1); + $cents /= $fraction; + $cents *= pow(10,ceil(log10($fraction))); + return $dollars + $cents; + } // function DOLLARDE() + + + /** + * DOLLARFR + * + * Converts a dollar price expressed as a decimal number into a dollar price + * expressed as a fraction. + * Fractional dollar numbers are sometimes used for security prices. + * + * Excel Function: + * DOLLARFR(decimal_dollar,fraction) + * + * @access public + * @category Financial Functions + * @param float $decimal_dollar Decimal Dollar + * @param integer $fraction Fraction + * @return float + */ + public static function DOLLARFR($decimal_dollar = Null, $fraction = 0) { + $decimal_dollar = PHPExcel_Calculation_Functions::flattenSingleValue($decimal_dollar); + $fraction = (int)PHPExcel_Calculation_Functions::flattenSingleValue($fraction); + + // Validate parameters + if (is_null($decimal_dollar) || $fraction < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ($fraction == 0) { + return PHPExcel_Calculation_Functions::DIV0(); + } + + $dollars = floor($decimal_dollar); + $cents = fmod($decimal_dollar,1); + $cents *= $fraction; + $cents *= pow(10,-ceil(log10($fraction))); + return $dollars + $cents; + } // function DOLLARFR() + + + /** + * EFFECT + * + * Returns the effective interest rate given the nominal rate and the number of + * compounding payments per year. + * + * Excel Function: + * EFFECT(nominal_rate,npery) + * + * @access public + * @category Financial Functions + * @param float $nominal_rate Nominal interest rate + * @param integer $npery Number of compounding payments per year + * @return float + */ + public static function EFFECT($nominal_rate = 0, $npery = 0) { + $nominal_rate = PHPExcel_Calculation_Functions::flattenSingleValue($nominal_rate); + $npery = (int)PHPExcel_Calculation_Functions::flattenSingleValue($npery); + + // Validate parameters + if ($nominal_rate <= 0 || $npery < 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + + return pow((1 + $nominal_rate / $npery), $npery) - 1; + } // function EFFECT() + + + /** + * FV + * + * Returns the Future Value of a cash flow with constant payments and interest rate (annuities). + * + * Excel Function: + * FV(rate,nper,pmt[,pv[,type]]) + * + * @access public + * @category Financial Functions + * @param float $rate The interest rate per period + * @param int $nper Total number of payment periods in an annuity + * @param float $pmt The payment made each period: it cannot change over the + * life of the annuity. Typically, pmt contains principal + * and interest but no other fees or taxes. + * @param float $pv Present Value, or the lump-sum amount that a series of + * future payments is worth right now. + * @param integer $type A number 0 or 1 and indicates when payments are due: + * 0 or omitted At the end of the period. + * 1 At the beginning of the period. + * @return float + */ + public static function FV($rate = 0, $nper = 0, $pmt = 0, $pv = 0, $type = 0) { + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $nper = PHPExcel_Calculation_Functions::flattenSingleValue($nper); + $pmt = PHPExcel_Calculation_Functions::flattenSingleValue($pmt); + $pv = PHPExcel_Calculation_Functions::flattenSingleValue($pv); + $type = PHPExcel_Calculation_Functions::flattenSingleValue($type); + + // Validate parameters + if ($type != 0 && $type != 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Calculate + if (!is_null($rate) && $rate != 0) { + return -$pv * pow(1 + $rate, $nper) - $pmt * (1 + $rate * $type) * (pow(1 + $rate, $nper) - 1) / $rate; + } else { + return -$pv - $pmt * $nper; + } + } // function FV() + + + /** + * FVSCHEDULE + * + * Returns the future value of an initial principal after applying a series of compound interest rates. + * Use FVSCHEDULE to calculate the future value of an investment with a variable or adjustable rate. + * + * Excel Function: + * FVSCHEDULE(principal,schedule) + * + * @param float $principal The present value. + * @param float[] $schedule An array of interest rates to apply. + * @return float + */ + public static function FVSCHEDULE($principal, $schedule) { + $principal = PHPExcel_Calculation_Functions::flattenSingleValue($principal); + $schedule = PHPExcel_Calculation_Functions::flattenArray($schedule); + + foreach($schedule as $rate) { + $principal *= 1 + $rate; + } + + return $principal; + } // function FVSCHEDULE() + + + /** + * INTRATE + * + * Returns the interest rate for a fully invested security. + * + * Excel Function: + * INTRATE(settlement,maturity,investment,redemption[,basis]) + * + * @param mixed $settlement The security's settlement date. + * The security settlement date is the date after the issue date when the security is traded to the buyer. + * @param mixed $maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param integer $investment The amount invested in the security. + * @param integer $redemption The amount to be received at maturity. + * @param integer $basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function INTRATE($settlement, $maturity, $investment, $redemption, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $investment = PHPExcel_Calculation_Functions::flattenSingleValue($investment); + $redemption = PHPExcel_Calculation_Functions::flattenSingleValue($redemption); + $basis = PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + // Validate + if ((is_numeric($investment)) && (is_numeric($redemption)) && (is_numeric($basis))) { + $investment = (float) $investment; + $redemption = (float) $redemption; + $basis = (int) $basis; + if (($investment <= 0) || ($redemption <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity, $basis); + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + // return date error + return $daysBetweenSettlementAndMaturity; + } + + return (($redemption / $investment) - 1) / ($daysBetweenSettlementAndMaturity); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function INTRATE() + + + /** + * IPMT + * + * Returns the interest payment for a given period for an investment based on periodic, constant payments and a constant interest rate. + * + * Excel Function: + * IPMT(rate,per,nper,pv[,fv][,type]) + * + * @param float $rate Interest rate per period + * @param int $per Period for which we want to find the interest + * @param int $nper Number of periods + * @param float $pv Present Value + * @param float $fv Future Value + * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period + * @return float + */ + public static function IPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0) { + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $per = (int) PHPExcel_Calculation_Functions::flattenSingleValue($per); + $nper = (int) PHPExcel_Calculation_Functions::flattenSingleValue($nper); + $pv = PHPExcel_Calculation_Functions::flattenSingleValue($pv); + $fv = PHPExcel_Calculation_Functions::flattenSingleValue($fv); + $type = (int) PHPExcel_Calculation_Functions::flattenSingleValue($type); + + // Validate parameters + if ($type != 0 && $type != 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ($per <= 0 || $per > $nper) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + // Calculate + $interestAndPrincipal = self::_interestAndPrincipal($rate, $per, $nper, $pv, $fv, $type); + return $interestAndPrincipal[0]; + } // function IPMT() + + /** + * IRR + * + * Returns the internal rate of return for a series of cash flows represented by the numbers in values. + * These cash flows do not have to be even, as they would be for an annuity. However, the cash flows must occur + * at regular intervals, such as monthly or annually. The internal rate of return is the interest rate received + * for an investment consisting of payments (negative values) and income (positive values) that occur at regular + * periods. + * + * Excel Function: + * IRR(values[,guess]) + * + * @param float[] $values An array or a reference to cells that contain numbers for which you want + * to calculate the internal rate of return. + * Values must contain at least one positive value and one negative value to + * calculate the internal rate of return. + * @param float $guess A number that you guess is close to the result of IRR + * @return float + */ + public static function IRR($values, $guess = 0.1) { + if (!is_array($values)) return PHPExcel_Calculation_Functions::VALUE(); + $values = PHPExcel_Calculation_Functions::flattenArray($values); + $guess = PHPExcel_Calculation_Functions::flattenSingleValue($guess); + + // create an initial range, with a root somewhere between 0 and guess + $x1 = 0.0; + $x2 = $guess; + $f1 = self::NPV($x1, $values); + $f2 = self::NPV($x2, $values); + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + if (($f1 * $f2) < 0.0) break; + if (abs($f1) < abs($f2)) { + $f1 = self::NPV($x1 += 1.6 * ($x1 - $x2), $values); + } else { + $f2 = self::NPV($x2 += 1.6 * ($x2 - $x1), $values); + } + } + if (($f1 * $f2) > 0.0) return PHPExcel_Calculation_Functions::VALUE(); + + $f = self::NPV($x1, $values); + if ($f < 0.0) { + $rtb = $x1; + $dx = $x2 - $x1; + } else { + $rtb = $x2; + $dx = $x1 - $x2; + } + + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + $dx *= 0.5; + $x_mid = $rtb + $dx; + $f_mid = self::NPV($x_mid, $values); + if ($f_mid <= 0.0) + $rtb = $x_mid; + if ((abs($f_mid) < FINANCIAL_PRECISION) || (abs($dx) < FINANCIAL_PRECISION)) + return $x_mid; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function IRR() + + + /** + * ISPMT + * + * Returns the interest payment for an investment based on an interest rate and a constant payment schedule. + * + * Excel Function: + * =ISPMT(interest_rate, period, number_payments, PV) + * + * interest_rate is the interest rate for the investment + * + * period is the period to calculate the interest rate. It must be betweeen 1 and number_payments. + * + * number_payments is the number of payments for the annuity + * + * PV is the loan amount or present value of the payments + */ + public static function ISPMT() { + // Return value + $returnValue = 0; + + // Get the parameters + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + $interestRate = array_shift($aArgs); + $period = array_shift($aArgs); + $numberPeriods = array_shift($aArgs); + $principleRemaining = array_shift($aArgs); + + // Calculate + $principlePayment = ($principleRemaining * 1.0) / ($numberPeriods * 1.0); + for($i=0; $i <= $period; ++$i) { + $returnValue = $interestRate * $principleRemaining * -1; + $principleRemaining -= $principlePayment; + // principle needs to be 0 after the last payment, don't let floating point screw it up + if($i == $numberPeriods) { + $returnValue = 0; + } + } + return($returnValue); + } // function ISPMT() + + + /** + * MIRR + * + * Returns the modified internal rate of return for a series of periodic cash flows. MIRR considers both + * the cost of the investment and the interest received on reinvestment of cash. + * + * Excel Function: + * MIRR(values,finance_rate, reinvestment_rate) + * + * @param float[] $values An array or a reference to cells that contain a series of payments and + * income occurring at regular intervals. + * Payments are negative value, income is positive values. + * @param float $finance_rate The interest rate you pay on the money used in the cash flows + * @param float $reinvestment_rate The interest rate you receive on the cash flows as you reinvest them + * @return float + */ + public static function MIRR($values, $finance_rate, $reinvestment_rate) { + if (!is_array($values)) return PHPExcel_Calculation_Functions::VALUE(); + $values = PHPExcel_Calculation_Functions::flattenArray($values); + $finance_rate = PHPExcel_Calculation_Functions::flattenSingleValue($finance_rate); + $reinvestment_rate = PHPExcel_Calculation_Functions::flattenSingleValue($reinvestment_rate); + $n = count($values); + + $rr = 1.0 + $reinvestment_rate; + $fr = 1.0 + $finance_rate; + + $npv_pos = $npv_neg = 0.0; + foreach($values as $i => $v) { + if ($v >= 0) { + $npv_pos += $v / pow($rr, $i); + } else { + $npv_neg += $v / pow($fr, $i); + } + } + + if (($npv_neg == 0) || ($npv_pos == 0) || ($reinvestment_rate <= -1)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + $mirr = pow((-$npv_pos * pow($rr, $n)) + / ($npv_neg * ($rr)), (1.0 / ($n - 1))) - 1.0; + + return (is_finite($mirr) ? $mirr : PHPExcel_Calculation_Functions::VALUE()); + } // function MIRR() + + + /** + * NOMINAL + * + * Returns the nominal interest rate given the effective rate and the number of compounding payments per year. + * + * @param float $effect_rate Effective interest rate + * @param int $npery Number of compounding payments per year + * @return float + */ + public static function NOMINAL($effect_rate = 0, $npery = 0) { + $effect_rate = PHPExcel_Calculation_Functions::flattenSingleValue($effect_rate); + $npery = (int)PHPExcel_Calculation_Functions::flattenSingleValue($npery); + + // Validate parameters + if ($effect_rate <= 0 || $npery < 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Calculate + return $npery * (pow($effect_rate + 1, 1 / $npery) - 1); + } // function NOMINAL() + + + /** + * NPER + * + * Returns the number of periods for a cash flow with constant periodic payments (annuities), and interest rate. + * + * @param float $rate Interest rate per period + * @param int $pmt Periodic payment (annuity) + * @param float $pv Present Value + * @param float $fv Future Value + * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period + * @return float + */ + public static function NPER($rate = 0, $pmt = 0, $pv = 0, $fv = 0, $type = 0) { + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $pmt = PHPExcel_Calculation_Functions::flattenSingleValue($pmt); + $pv = PHPExcel_Calculation_Functions::flattenSingleValue($pv); + $fv = PHPExcel_Calculation_Functions::flattenSingleValue($fv); + $type = PHPExcel_Calculation_Functions::flattenSingleValue($type); + + // Validate parameters + if ($type != 0 && $type != 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Calculate + if (!is_null($rate) && $rate != 0) { + if ($pmt == 0 && $pv == 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + return log(($pmt * (1 + $rate * $type) / $rate - $fv) / ($pv + $pmt * (1 + $rate * $type) / $rate)) / log(1 + $rate); + } else { + if ($pmt == 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + return (-$pv -$fv) / $pmt; + } + } // function NPER() + + /** + * NPV + * + * Returns the Net Present Value of a cash flow series given a discount rate. + * + * @return float + */ + public static function NPV() { + // Return value + $returnValue = 0; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + + // Calculate + $rate = array_shift($aArgs); + for ($i = 1; $i <= count($aArgs); ++$i) { + // Is it a numeric value? + if (is_numeric($aArgs[$i - 1])) { + $returnValue += $aArgs[$i - 1] / pow(1 + $rate, $i); + } + } + + // Return + return $returnValue; + } // function NPV() + + /** + * PMT + * + * Returns the constant payment (annuity) for a cash flow with a constant interest rate. + * + * @param float $rate Interest rate per period + * @param int $nper Number of periods + * @param float $pv Present Value + * @param float $fv Future Value + * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period + * @return float + */ + public static function PMT($rate = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0) { + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $nper = PHPExcel_Calculation_Functions::flattenSingleValue($nper); + $pv = PHPExcel_Calculation_Functions::flattenSingleValue($pv); + $fv = PHPExcel_Calculation_Functions::flattenSingleValue($fv); + $type = PHPExcel_Calculation_Functions::flattenSingleValue($type); + + // Validate parameters + if ($type != 0 && $type != 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Calculate + if (!is_null($rate) && $rate != 0) { + return (-$fv - $pv * pow(1 + $rate, $nper)) / (1 + $rate * $type) / ((pow(1 + $rate, $nper) - 1) / $rate); + } else { + return (-$pv - $fv) / $nper; + } + } // function PMT() + + + /** + * PPMT + * + * Returns the interest payment for a given period for an investment based on periodic, constant payments and a constant interest rate. + * + * @param float $rate Interest rate per period + * @param int $per Period for which we want to find the interest + * @param int $nper Number of periods + * @param float $pv Present Value + * @param float $fv Future Value + * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period + * @return float + */ + public static function PPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0) { + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $per = (int) PHPExcel_Calculation_Functions::flattenSingleValue($per); + $nper = (int) PHPExcel_Calculation_Functions::flattenSingleValue($nper); + $pv = PHPExcel_Calculation_Functions::flattenSingleValue($pv); + $fv = PHPExcel_Calculation_Functions::flattenSingleValue($fv); + $type = (int) PHPExcel_Calculation_Functions::flattenSingleValue($type); + + // Validate parameters + if ($type != 0 && $type != 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ($per <= 0 || $per > $nper) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + // Calculate + $interestAndPrincipal = self::_interestAndPrincipal($rate, $per, $nper, $pv, $fv, $type); + return $interestAndPrincipal[1]; + } // function PPMT() + + + public static function PRICE($settlement, $maturity, $rate, $yield, $redemption, $frequency, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $rate = (float) PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $yield = (float) PHPExcel_Calculation_Functions::flattenSingleValue($yield); + $redemption = (float) PHPExcel_Calculation_Functions::flattenSingleValue($redemption); + $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency); + $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + if (is_string($settlement = PHPExcel_Calculation_DateTime::_getDateValue($settlement))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (is_string($maturity = PHPExcel_Calculation_DateTime::_getDateValue($maturity))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (($settlement > $maturity) || + (!self::_validFrequency($frequency)) || + (($basis < 0) || ($basis > 4))) { + return PHPExcel_Calculation_Functions::NaN(); + } + + $dsc = self::COUPDAYSNC($settlement, $maturity, $frequency, $basis); + $e = self::COUPDAYS($settlement, $maturity, $frequency, $basis); + $n = self::COUPNUM($settlement, $maturity, $frequency, $basis); + $a = self::COUPDAYBS($settlement, $maturity, $frequency, $basis); + + $baseYF = 1.0 + ($yield / $frequency); + $rfp = 100 * ($rate / $frequency); + $de = $dsc / $e; + + $result = $redemption / pow($baseYF, (--$n + $de)); + for($k = 0; $k <= $n; ++$k) { + $result += $rfp / (pow($baseYF, ($k + $de))); + } + $result -= $rfp * ($a / $e); + + return $result; + } // function PRICE() + + + /** + * PRICEDISC + * + * Returns the price per $100 face value of a discounted security. + * + * @param mixed settlement The security's settlement date. + * The security settlement date is the date after the issue date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param int discount The security's discount rate. + * @param int redemption The security's redemption value per $100 face value. + * @param int basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function PRICEDISC($settlement, $maturity, $discount, $redemption, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $discount = (float) PHPExcel_Calculation_Functions::flattenSingleValue($discount); + $redemption = (float) PHPExcel_Calculation_Functions::flattenSingleValue($redemption); + $basis = (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + // Validate + if ((is_numeric($discount)) && (is_numeric($redemption)) && (is_numeric($basis))) { + if (($discount <= 0) || ($redemption <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity, $basis); + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + // return date error + return $daysBetweenSettlementAndMaturity; + } + + return $redemption * (1 - $discount * $daysBetweenSettlementAndMaturity); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function PRICEDISC() + + + /** + * PRICEMAT + * + * Returns the price per $100 face value of a security that pays interest at maturity. + * + * @param mixed settlement The security's settlement date. + * The security's settlement date is the date after the issue date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param mixed issue The security's issue date. + * @param int rate The security's interest rate at date of issue. + * @param int yield The security's annual yield. + * @param int basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function PRICEMAT($settlement, $maturity, $issue, $rate, $yield, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $issue = PHPExcel_Calculation_Functions::flattenSingleValue($issue); + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $yield = PHPExcel_Calculation_Functions::flattenSingleValue($yield); + $basis = (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + // Validate + if (is_numeric($rate) && is_numeric($yield)) { + if (($rate <= 0) || ($yield <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $daysPerYear = self::_daysPerYear(PHPExcel_Calculation_DateTime::YEAR($settlement),$basis); + if (!is_numeric($daysPerYear)) { + return $daysPerYear; + } + $daysBetweenIssueAndSettlement = PHPExcel_Calculation_DateTime::YEARFRAC($issue, $settlement, $basis); + if (!is_numeric($daysBetweenIssueAndSettlement)) { + // return date error + return $daysBetweenIssueAndSettlement; + } + $daysBetweenIssueAndSettlement *= $daysPerYear; + $daysBetweenIssueAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($issue, $maturity, $basis); + if (!is_numeric($daysBetweenIssueAndMaturity)) { + // return date error + return $daysBetweenIssueAndMaturity; + } + $daysBetweenIssueAndMaturity *= $daysPerYear; + $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity, $basis); + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + // return date error + return $daysBetweenSettlementAndMaturity; + } + $daysBetweenSettlementAndMaturity *= $daysPerYear; + + return ((100 + (($daysBetweenIssueAndMaturity / $daysPerYear) * $rate * 100)) / + (1 + (($daysBetweenSettlementAndMaturity / $daysPerYear) * $yield)) - + (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate * 100)); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function PRICEMAT() + + + /** + * PV + * + * Returns the Present Value of a cash flow with constant payments and interest rate (annuities). + * + * @param float $rate Interest rate per period + * @param int $nper Number of periods + * @param float $pmt Periodic payment (annuity) + * @param float $fv Future Value + * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period + * @return float + */ + public static function PV($rate = 0, $nper = 0, $pmt = 0, $fv = 0, $type = 0) { + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $nper = PHPExcel_Calculation_Functions::flattenSingleValue($nper); + $pmt = PHPExcel_Calculation_Functions::flattenSingleValue($pmt); + $fv = PHPExcel_Calculation_Functions::flattenSingleValue($fv); + $type = PHPExcel_Calculation_Functions::flattenSingleValue($type); + + // Validate parameters + if ($type != 0 && $type != 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + + // Calculate + if (!is_null($rate) && $rate != 0) { + return (-$pmt * (1 + $rate * $type) * ((pow(1 + $rate, $nper) - 1) / $rate) - $fv) / pow(1 + $rate, $nper); + } else { + return -$fv - $pmt * $nper; + } + } // function PV() + + + /** + * RATE + * + * Returns the interest rate per period of an annuity. + * RATE is calculated by iteration and can have zero or more solutions. + * If the successive results of RATE do not converge to within 0.0000001 after 20 iterations, + * RATE returns the #NUM! error value. + * + * Excel Function: + * RATE(nper,pmt,pv[,fv[,type[,guess]]]) + * + * @access public + * @category Financial Functions + * @param float nper The total number of payment periods in an annuity. + * @param float pmt The payment made each period and cannot change over the life + * of the annuity. + * Typically, pmt includes principal and interest but no other + * fees or taxes. + * @param float pv The present value - the total amount that a series of future + * payments is worth now. + * @param float fv The future value, or a cash balance you want to attain after + * the last payment is made. If fv is omitted, it is assumed + * to be 0 (the future value of a loan, for example, is 0). + * @param integer type A number 0 or 1 and indicates when payments are due: + * 0 or omitted At the end of the period. + * 1 At the beginning of the period. + * @param float guess Your guess for what the rate will be. + * If you omit guess, it is assumed to be 10 percent. + * @return float + **/ + public static function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1) { + $nper = (int) PHPExcel_Calculation_Functions::flattenSingleValue($nper); + $pmt = PHPExcel_Calculation_Functions::flattenSingleValue($pmt); + $pv = PHPExcel_Calculation_Functions::flattenSingleValue($pv); + $fv = (is_null($fv)) ? 0.0 : PHPExcel_Calculation_Functions::flattenSingleValue($fv); + $type = (is_null($type)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($type); + $guess = (is_null($guess)) ? 0.1 : PHPExcel_Calculation_Functions::flattenSingleValue($guess); + + $rate = $guess; + if (abs($rate) < FINANCIAL_PRECISION) { + $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; + } else { + $f = exp($nper * log(1 + $rate)); + $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; + } + $y0 = $pv + $pmt * $nper + $fv; + $y1 = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; + + // find root by secant method + $i = $x0 = 0.0; + $x1 = $rate; + while ((abs($y0 - $y1) > FINANCIAL_PRECISION) && ($i < FINANCIAL_MAX_ITERATIONS)) { + $rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0); + $x0 = $x1; + $x1 = $rate; + if (($nper * abs($pmt)) > ($pv - $fv)) + $x1 = abs($x1); + + if (abs($rate) < FINANCIAL_PRECISION) { + $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv; + } else { + $f = exp($nper * log(1 + $rate)); + $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv; + } + + $y0 = $y1; + $y1 = $y; + ++$i; + } + return $rate; + } // function RATE() + + + /** + * RECEIVED + * + * Returns the price per $100 face value of a discounted security. + * + * @param mixed settlement The security's settlement date. + * The security settlement date is the date after the issue date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param int investment The amount invested in the security. + * @param int discount The security's discount rate. + * @param int basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function RECEIVED($settlement, $maturity, $investment, $discount, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $investment = (float) PHPExcel_Calculation_Functions::flattenSingleValue($investment); + $discount = (float) PHPExcel_Calculation_Functions::flattenSingleValue($discount); + $basis = (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + // Validate + if ((is_numeric($investment)) && (is_numeric($discount)) && (is_numeric($basis))) { + if (($investment <= 0) || ($discount <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity, $basis); + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + // return date error + return $daysBetweenSettlementAndMaturity; + } + + return $investment / ( 1 - ($discount * $daysBetweenSettlementAndMaturity)); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function RECEIVED() + + + /** + * SLN + * + * Returns the straight-line depreciation of an asset for one period + * + * @param cost Initial cost of the asset + * @param salvage Value at the end of the depreciation + * @param life Number of periods over which the asset is depreciated + * @return float + */ + public static function SLN($cost, $salvage, $life) { + $cost = PHPExcel_Calculation_Functions::flattenSingleValue($cost); + $salvage = PHPExcel_Calculation_Functions::flattenSingleValue($salvage); + $life = PHPExcel_Calculation_Functions::flattenSingleValue($life); + + // Calculate + if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life))) { + if ($life < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + return ($cost - $salvage) / $life; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function SLN() + + + /** + * SYD + * + * Returns the sum-of-years' digits depreciation of an asset for a specified period. + * + * @param cost Initial cost of the asset + * @param salvage Value at the end of the depreciation + * @param life Number of periods over which the asset is depreciated + * @param period Period + * @return float + */ + public static function SYD($cost, $salvage, $life, $period) { + $cost = PHPExcel_Calculation_Functions::flattenSingleValue($cost); + $salvage = PHPExcel_Calculation_Functions::flattenSingleValue($salvage); + $life = PHPExcel_Calculation_Functions::flattenSingleValue($life); + $period = PHPExcel_Calculation_Functions::flattenSingleValue($period); + + // Calculate + if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period))) { + if (($life < 1) || ($period > $life)) { + return PHPExcel_Calculation_Functions::NaN(); + } + return (($cost - $salvage) * ($life - $period + 1) * 2) / ($life * ($life + 1)); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function SYD() + + + /** + * TBILLEQ + * + * Returns the bond-equivalent yield for a Treasury bill. + * + * @param mixed settlement The Treasury bill's settlement date. + * The Treasury bill's settlement date is the date after the issue date when the Treasury bill is traded to the buyer. + * @param mixed maturity The Treasury bill's maturity date. + * The maturity date is the date when the Treasury bill expires. + * @param int discount The Treasury bill's discount rate. + * @return float + */ + public static function TBILLEQ($settlement, $maturity, $discount) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $discount = PHPExcel_Calculation_Functions::flattenSingleValue($discount); + + // Use TBILLPRICE for validation + $testValue = self::TBILLPRICE($settlement, $maturity, $discount); + if (is_string($testValue)) { + return $testValue; + } + + if (is_string($maturity = PHPExcel_Calculation_DateTime::_getDateValue($maturity))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + ++$maturity; + $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity) * 360; + } else { + $daysBetweenSettlementAndMaturity = (PHPExcel_Calculation_DateTime::_getDateValue($maturity) - PHPExcel_Calculation_DateTime::_getDateValue($settlement)); + } + + return (365 * $discount) / (360 - $discount * $daysBetweenSettlementAndMaturity); + } // function TBILLEQ() + + + /** + * TBILLPRICE + * + * Returns the yield for a Treasury bill. + * + * @param mixed settlement The Treasury bill's settlement date. + * The Treasury bill's settlement date is the date after the issue date when the Treasury bill is traded to the buyer. + * @param mixed maturity The Treasury bill's maturity date. + * The maturity date is the date when the Treasury bill expires. + * @param int discount The Treasury bill's discount rate. + * @return float + */ + public static function TBILLPRICE($settlement, $maturity, $discount) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $discount = PHPExcel_Calculation_Functions::flattenSingleValue($discount); + + if (is_string($maturity = PHPExcel_Calculation_DateTime::_getDateValue($maturity))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + // Validate + if (is_numeric($discount)) { + if ($discount <= 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + ++$maturity; + $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity) * 360; + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + // return date error + return $daysBetweenSettlementAndMaturity; + } + } else { + $daysBetweenSettlementAndMaturity = (PHPExcel_Calculation_DateTime::_getDateValue($maturity) - PHPExcel_Calculation_DateTime::_getDateValue($settlement)); + } + + if ($daysBetweenSettlementAndMaturity > 360) { + return PHPExcel_Calculation_Functions::NaN(); + } + + $price = 100 * (1 - (($discount * $daysBetweenSettlementAndMaturity) / 360)); + if ($price <= 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + return $price; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function TBILLPRICE() + + + /** + * TBILLYIELD + * + * Returns the yield for a Treasury bill. + * + * @param mixed settlement The Treasury bill's settlement date. + * The Treasury bill's settlement date is the date after the issue date when the Treasury bill is traded to the buyer. + * @param mixed maturity The Treasury bill's maturity date. + * The maturity date is the date when the Treasury bill expires. + * @param int price The Treasury bill's price per $100 face value. + * @return float + */ + public static function TBILLYIELD($settlement, $maturity, $price) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $price = PHPExcel_Calculation_Functions::flattenSingleValue($price); + + // Validate + if (is_numeric($price)) { + if ($price <= 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + ++$maturity; + $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity) * 360; + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + // return date error + return $daysBetweenSettlementAndMaturity; + } + } else { + $daysBetweenSettlementAndMaturity = (PHPExcel_Calculation_DateTime::_getDateValue($maturity) - PHPExcel_Calculation_DateTime::_getDateValue($settlement)); + } + + if ($daysBetweenSettlementAndMaturity > 360) { + return PHPExcel_Calculation_Functions::NaN(); + } + + return ((100 - $price) / $price) * (360 / $daysBetweenSettlementAndMaturity); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function TBILLYIELD() + + + public static function XIRR($values, $dates, $guess = 0.1) { + if ((!is_array($values)) && (!is_array($dates))) return PHPExcel_Calculation_Functions::VALUE(); + $values = PHPExcel_Calculation_Functions::flattenArray($values); + $dates = PHPExcel_Calculation_Functions::flattenArray($dates); + $guess = PHPExcel_Calculation_Functions::flattenSingleValue($guess); + if (count($values) != count($dates)) return PHPExcel_Calculation_Functions::NaN(); + + // create an initial range, with a root somewhere between 0 and guess + $x1 = 0.0; + $x2 = $guess; + $f1 = self::XNPV($x1, $values, $dates); + $f2 = self::XNPV($x2, $values, $dates); + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + if (($f1 * $f2) < 0.0) break; + if (abs($f1) < abs($f2)) { + $f1 = self::XNPV($x1 += 1.6 * ($x1 - $x2), $values, $dates); + } else { + $f2 = self::XNPV($x2 += 1.6 * ($x2 - $x1), $values, $dates); + } + } + if (($f1 * $f2) > 0.0) return PHPExcel_Calculation_Functions::VALUE(); + + $f = self::XNPV($x1, $values, $dates); + if ($f < 0.0) { + $rtb = $x1; + $dx = $x2 - $x1; + } else { + $rtb = $x2; + $dx = $x1 - $x2; + } + + for ($i = 0; $i < FINANCIAL_MAX_ITERATIONS; ++$i) { + $dx *= 0.5; + $x_mid = $rtb + $dx; + $f_mid = self::XNPV($x_mid, $values, $dates); + if ($f_mid <= 0.0) $rtb = $x_mid; + if ((abs($f_mid) < FINANCIAL_PRECISION) || (abs($dx) < FINANCIAL_PRECISION)) return $x_mid; + } + return PHPExcel_Calculation_Functions::VALUE(); + } + + + /** + * XNPV + * + * Returns the net present value for a schedule of cash flows that is not necessarily periodic. + * To calculate the net present value for a series of cash flows that is periodic, use the NPV function. + * + * Excel Function: + * =XNPV(rate,values,dates) + * + * @param float $rate The discount rate to apply to the cash flows. + * @param array of float $values A series of cash flows that corresponds to a schedule of payments in dates. The first payment is optional and corresponds to a cost or payment that occurs at the beginning of the investment. If the first value is a cost or payment, it must be a negative value. All succeeding payments are discounted based on a 365-day year. The series of values must contain at least one positive value and one negative value. + * @param array of mixed $dates A schedule of payment dates that corresponds to the cash flow payments. The first payment date indicates the beginning of the schedule of payments. All other dates must be later than this date, but they may occur in any order. + * @return float + */ + public static function XNPV($rate, $values, $dates) { + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + if (!is_numeric($rate)) return PHPExcel_Calculation_Functions::VALUE(); + if ((!is_array($values)) || (!is_array($dates))) return PHPExcel_Calculation_Functions::VALUE(); + $values = PHPExcel_Calculation_Functions::flattenArray($values); + $dates = PHPExcel_Calculation_Functions::flattenArray($dates); + $valCount = count($values); + if ($valCount != count($dates)) return PHPExcel_Calculation_Functions::NaN(); + if ((min($values) > 0) || (max($values) < 0)) return PHPExcel_Calculation_Functions::VALUE(); + + $xnpv = 0.0; + for ($i = 0; $i < $valCount; ++$i) { + if (!is_numeric($values[$i])) return PHPExcel_Calculation_Functions::VALUE(); + $xnpv += $values[$i] / pow(1 + $rate, PHPExcel_Calculation_DateTime::DATEDIF($dates[0],$dates[$i],'d') / 365); + } + return (is_finite($xnpv)) ? $xnpv : PHPExcel_Calculation_Functions::VALUE(); + } // function XNPV() + + + /** + * YIELDDISC + * + * Returns the annual yield of a security that pays interest at maturity. + * + * @param mixed settlement The security's settlement date. + * The security's settlement date is the date after the issue date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param int price The security's price per $100 face value. + * @param int redemption The security's redemption value per $100 face value. + * @param int basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function YIELDDISC($settlement, $maturity, $price, $redemption, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $price = PHPExcel_Calculation_Functions::flattenSingleValue($price); + $redemption = PHPExcel_Calculation_Functions::flattenSingleValue($redemption); + $basis = (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + // Validate + if (is_numeric($price) && is_numeric($redemption)) { + if (($price <= 0) || ($redemption <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $daysPerYear = self::_daysPerYear(PHPExcel_Calculation_DateTime::YEAR($settlement),$basis); + if (!is_numeric($daysPerYear)) { + return $daysPerYear; + } + $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity,$basis); + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + // return date error + return $daysBetweenSettlementAndMaturity; + } + $daysBetweenSettlementAndMaturity *= $daysPerYear; + + return (($redemption - $price) / $price) * ($daysPerYear / $daysBetweenSettlementAndMaturity); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function YIELDDISC() + + + /** + * YIELDMAT + * + * Returns the annual yield of a security that pays interest at maturity. + * + * @param mixed settlement The security's settlement date. + * The security's settlement date is the date after the issue date when the security is traded to the buyer. + * @param mixed maturity The security's maturity date. + * The maturity date is the date when the security expires. + * @param mixed issue The security's issue date. + * @param int rate The security's interest rate at date of issue. + * @param int price The security's price per $100 face value. + * @param int basis The type of day count to use. + * 0 or omitted US (NASD) 30/360 + * 1 Actual/actual + * 2 Actual/360 + * 3 Actual/365 + * 4 European 30/360 + * @return float + */ + public static function YIELDMAT($settlement, $maturity, $issue, $rate, $price, $basis=0) { + $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement); + $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity); + $issue = PHPExcel_Calculation_Functions::flattenSingleValue($issue); + $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate); + $price = PHPExcel_Calculation_Functions::flattenSingleValue($price); + $basis = (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis); + + // Validate + if (is_numeric($rate) && is_numeric($price)) { + if (($rate <= 0) || ($price <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $daysPerYear = self::_daysPerYear(PHPExcel_Calculation_DateTime::YEAR($settlement),$basis); + if (!is_numeric($daysPerYear)) { + return $daysPerYear; + } + $daysBetweenIssueAndSettlement = PHPExcel_Calculation_DateTime::YEARFRAC($issue, $settlement, $basis); + if (!is_numeric($daysBetweenIssueAndSettlement)) { + // return date error + return $daysBetweenIssueAndSettlement; + } + $daysBetweenIssueAndSettlement *= $daysPerYear; + $daysBetweenIssueAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($issue, $maturity, $basis); + if (!is_numeric($daysBetweenIssueAndMaturity)) { + // return date error + return $daysBetweenIssueAndMaturity; + } + $daysBetweenIssueAndMaturity *= $daysPerYear; + $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity, $basis); + if (!is_numeric($daysBetweenSettlementAndMaturity)) { + // return date error + return $daysBetweenSettlementAndMaturity; + } + $daysBetweenSettlementAndMaturity *= $daysPerYear; + + return ((1 + (($daysBetweenIssueAndMaturity / $daysPerYear) * $rate) - (($price / 100) + (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate))) / + (($price / 100) + (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate))) * + ($daysPerYear / $daysBetweenSettlementAndMaturity); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function YIELDMAT() + +} // class PHPExcel_Calculation_Financial diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/FormulaParser.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/FormulaParser.php new file mode 100755 index 0000000..821b085 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/FormulaParser.php @@ -0,0 +1,614 @@ +<"; + const OPERATORS_POSTFIX = "%"; + + /** + * Formula + * + * @var string + */ + private $_formula; + + /** + * Tokens + * + * @var PHPExcel_Calculation_FormulaToken[] + */ + private $_tokens = array(); + + /** + * Create a new PHPExcel_Calculation_FormulaParser + * + * @param string $pFormula Formula to parse + * @throws PHPExcel_Calculation_Exception + */ + public function __construct($pFormula = '') + { + // Check parameters + if (is_null($pFormula)) { + throw new PHPExcel_Calculation_Exception("Invalid parameter passed: formula"); + } + + // Initialise values + $this->_formula = trim($pFormula); + // Parse! + $this->_parseToTokens(); + } + + /** + * Get Formula + * + * @return string + */ + public function getFormula() { + return $this->_formula; + } + + /** + * Get Token + * + * @param int $pId Token id + * @return string + * @throws PHPExcel_Calculation_Exception + */ + public function getToken($pId = 0) { + if (isset($this->_tokens[$pId])) { + return $this->_tokens[$pId]; + } else { + throw new PHPExcel_Calculation_Exception("Token with id $pId does not exist."); + } + } + + /** + * Get Token count + * + * @return string + */ + public function getTokenCount() { + return count($this->_tokens); + } + + /** + * Get Tokens + * + * @return PHPExcel_Calculation_FormulaToken[] + */ + public function getTokens() { + return $this->_tokens; + } + + /** + * Parse to tokens + */ + private function _parseToTokens() { + // No attempt is made to verify formulas; assumes formulas are derived from Excel, where + // they can only exist if valid; stack overflows/underflows sunk as nulls without exceptions. + + // Check if the formula has a valid starting = + $formulaLength = strlen($this->_formula); + if ($formulaLength < 2 || $this->_formula{0} != '=') return; + + // Helper variables + $tokens1 = $tokens2 = $stack = array(); + $inString = $inPath = $inRange = $inError = false; + $token = $previousToken = $nextToken = null; + + $index = 1; + $value = ''; + + $ERRORS = array("#NULL!", "#DIV/0!", "#VALUE!", "#REF!", "#NAME?", "#NUM!", "#N/A"); + $COMPARATORS_MULTI = array(">=", "<=", "<>"); + + while ($index < $formulaLength) { + // state-dependent character evaluation (order is important) + + // double-quoted strings + // embeds are doubled + // end marks token + if ($inString) { + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) { + if ((($index + 2) <= $formulaLength) && ($this->_formula{$index + 1} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE)) { + $value .= PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE; + ++$index; + } else { + $inString = false; + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_TEXT); + $value = ""; + } + } else { + $value .= $this->_formula{$index}; + } + ++$index; + continue; + } + + // single-quoted strings (links) + // embeds are double + // end does not mark a token + if ($inPath) { + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) { + if ((($index + 2) <= $formulaLength) && ($this->_formula{$index + 1} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE)) { + $value .= PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE; + ++$index; + } else { + $inPath = false; + } + } else { + $value .= $this->_formula{$index}; + } + ++$index; + continue; + } + + // bracked strings (R1C1 range index or linked workbook name) + // no embeds (changed to "()" by Excel) + // end does not mark a token + if ($inRange) { + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACKET_CLOSE) { + $inRange = false; + } + $value .= $this->_formula{$index}; + ++$index; + continue; + } + + // error values + // end marks a token, determined from absolute list of values + if ($inError) { + $value .= $this->_formula{$index}; + ++$index; + if (in_array($value, $ERRORS)) { + $inError = false; + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_ERROR); + $value = ""; + } + continue; + } + + // scientific notation check + if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_SN, $this->_formula{$index}) !== false) { + if (strlen($value) > 1) { + if (preg_match("/^[1-9]{1}(\.[0-9]+)?E{1}$/", $this->_formula{$index}) != 0) { + $value .= $this->_formula{$index}; + ++$index; + continue; + } + } + } + + // independent character evaluation (order not important) + + // establish state-dependent character evaluations + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_DOUBLE) { + if (strlen($value > 0)) { // unexpected + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); + $value = ""; + } + $inString = true; + ++$index; + continue; + } + + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::QUOTE_SINGLE) { + if (strlen($value) > 0) { // unexpected + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); + $value = ""; + } + $inPath = true; + ++$index; + continue; + } + + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACKET_OPEN) { + $inRange = true; + $value .= PHPExcel_Calculation_FormulaParser::BRACKET_OPEN; + ++$index; + continue; + } + + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::ERROR_START) { + if (strlen($value) > 0) { // unexpected + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); + $value = ""; + } + $inError = true; + $value .= PHPExcel_Calculation_FormulaParser::ERROR_START; + ++$index; + continue; + } + + // mark start and end of arrays and array rows + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACE_OPEN) { + if (strlen($value) > 0) { // unexpected + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN); + $value = ""; + } + + $tmp = new PHPExcel_Calculation_FormulaToken("ARRAY", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); + $tokens1[] = $tmp; + $stack[] = clone $tmp; + + $tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); + $tokens1[] = $tmp; + $stack[] = clone $tmp; + + ++$index; + continue; + } + + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::SEMICOLON) { + if (strlen($value) > 0) { + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); + $value = ""; + } + + $tmp = array_pop($stack); + $tmp->setValue(""); + $tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); + $tokens1[] = $tmp; + + $tmp = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT); + $tokens1[] = $tmp; + + $tmp = new PHPExcel_Calculation_FormulaToken("ARRAYROW", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); + $tokens1[] = $tmp; + $stack[] = clone $tmp; + + ++$index; + continue; + } + + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::BRACE_CLOSE) { + if (strlen($value) > 0) { + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); + $value = ""; + } + + $tmp = array_pop($stack); + $tmp->setValue(""); + $tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); + $tokens1[] = $tmp; + + $tmp = array_pop($stack); + $tmp->setValue(""); + $tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); + $tokens1[] = $tmp; + + ++$index; + continue; + } + + // trim white-space + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::WHITESPACE) { + if (strlen($value) > 0) { + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); + $value = ""; + } + $tokens1[] = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE); + ++$index; + while (($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::WHITESPACE) && ($index < $formulaLength)) { + ++$index; + } + continue; + } + + // multi-character comparators + if (($index + 2) <= $formulaLength) { + if (in_array(substr($this->_formula, $index, 2), $COMPARATORS_MULTI)) { + if (strlen($value) > 0) { + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); + $value = ""; + } + $tokens1[] = new PHPExcel_Calculation_FormulaToken(substr($this->_formula, $index, 2), PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL); + $index += 2; + continue; + } + } + + // standard infix operators + if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_INFIX, $this->_formula{$index}) !== false) { + if (strlen($value) > 0) { + $tokens1[] =new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); + $value = ""; + } + $tokens1[] = new PHPExcel_Calculation_FormulaToken($this->_formula{$index}, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX); + ++$index; + continue; + } + + // standard postfix operators (only one) + if (strpos(PHPExcel_Calculation_FormulaParser::OPERATORS_POSTFIX, $this->_formula{$index}) !== false) { + if (strlen($value) > 0) { + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); + $value = ""; + } + $tokens1[] = new PHPExcel_Calculation_FormulaToken($this->_formula{$index}, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX); + ++$index; + continue; + } + + // start subexpression or function + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::PAREN_OPEN) { + if (strlen($value) > 0) { + $tmp = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); + $tokens1[] = $tmp; + $stack[] = clone $tmp; + $value = ""; + } else { + $tmp = new PHPExcel_Calculation_FormulaToken("", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START); + $tokens1[] = $tmp; + $stack[] = clone $tmp; + } + ++$index; + continue; + } + + // function, subexpression, or array parameters, or operand unions + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::COMMA) { + if (strlen($value) > 0) { + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); + $value = ""; + } + + $tmp = array_pop($stack); + $tmp->setValue(""); + $tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); + $stack[] = $tmp; + + if ($tmp->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) { + $tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_UNION); + } else { + $tokens1[] = new PHPExcel_Calculation_FormulaToken(",", PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_ARGUMENT); + } + ++$index; + continue; + } + + // stop subexpression + if ($this->_formula{$index} == PHPExcel_Calculation_FormulaParser::PAREN_CLOSE) { + if (strlen($value) > 0) { + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); + $value = ""; + } + + $tmp = array_pop($stack); + $tmp->setValue(""); + $tmp->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP); + $tokens1[] = $tmp; + + ++$index; + continue; + } + + // token accumulation + $value .= $this->_formula{$index}; + ++$index; + } + + // dump remaining accumulation + if (strlen($value) > 0) { + $tokens1[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND); + } + + // move tokenList to new set, excluding unnecessary white-space tokens and converting necessary ones to intersections + $tokenCount = count($tokens1); + for ($i = 0; $i < $tokenCount; ++$i) { + $token = $tokens1[$i]; + if (isset($tokens1[$i - 1])) { + $previousToken = $tokens1[$i - 1]; + } else { + $previousToken = null; + } + if (isset($tokens1[$i + 1])) { + $nextToken = $tokens1[$i + 1]; + } else { + $nextToken = null; + } + + if (is_null($token)) { + continue; + } + + if ($token->getTokenType() != PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_WHITESPACE) { + $tokens2[] = $token; + continue; + } + + if (is_null($previousToken)) { + continue; + } + + if (! ( + (($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || + (($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || + ($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND) + ) ) { + continue; + } + + if (is_null($nextToken)) { + continue; + } + + if (! ( + (($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) || + (($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($nextToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_START)) || + ($nextToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND) + ) ) { + continue; + } + + $tokens2[] = new PHPExcel_Calculation_FormulaToken($value, PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX, PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_INTERSECTION); + } + + // move tokens to final list, switching infix "-" operators to prefix when appropriate, switching infix "+" operators + // to noop when appropriate, identifying operand and infix-operator subtypes, and pulling "@" from function names + $this->_tokens = array(); + + $tokenCount = count($tokens2); + for ($i = 0; $i < $tokenCount; ++$i) { + $token = $tokens2[$i]; + if (isset($tokens2[$i - 1])) { + $previousToken = $tokens2[$i - 1]; + } else { + $previousToken = null; + } + if (isset($tokens2[$i + 1])) { + $nextToken = $tokens2[$i + 1]; + } else { + $nextToken = null; + } + + if (is_null($token)) { + continue; + } + + if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "-") { + if ($i == 0) { + $token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX); + } else if ( + (($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || + (($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || + ($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) || + ($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND) + ) { + $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH); + } else { + $token->setTokenType(PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPREFIX); + } + + $this->_tokens[] = $token; + continue; + } + + if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getValue() == "+") { + if ($i == 0) { + continue; + } else if ( + (($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || + (($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_SUBEXPRESSION) && ($previousToken->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_STOP)) || + ($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORPOSTFIX) || + ($previousToken->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND) + ) { + $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH); + } else { + continue; + } + + $this->_tokens[] = $token; + continue; + } + + if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERATORINFIX && $token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) { + if (strpos("<>=", substr($token->getValue(), 0, 1)) !== false) { + $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL); + } else if ($token->getValue() == "&") { + $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_CONCATENATION); + } else { + $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_MATH); + } + + $this->_tokens[] = $token; + continue; + } + + if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_OPERAND && $token->getTokenSubType() == PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) { + if (!is_numeric($token->getValue())) { + if (strtoupper($token->getValue()) == "TRUE" || strtoupper($token->getValue() == "FALSE")) { + $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_LOGICAL); + } else { + $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_RANGE); + } + } else { + $token->setTokenSubType(PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NUMBER); + } + + $this->_tokens[] = $token; + continue; + } + + if ($token->getTokenType() == PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_FUNCTION) { + if (strlen($token->getValue() > 0)) { + if (substr($token->getValue(), 0, 1) == "@") { + $token->setValue(substr($token->getValue(), 1)); + } + } + } + + $this->_tokens[] = $token; + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/FormulaToken.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/FormulaToken.php new file mode 100755 index 0000000..5559e67 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/FormulaToken.php @@ -0,0 +1,176 @@ +_value = $pValue; + $this->_tokenType = $pTokenType; + $this->_tokenSubType = $pTokenSubType; + } + + /** + * Get Value + * + * @return string + */ + public function getValue() { + return $this->_value; + } + + /** + * Set Value + * + * @param string $value + */ + public function setValue($value) { + $this->_value = $value; + } + + /** + * Get Token Type (represented by TOKEN_TYPE_*) + * + * @return string + */ + public function getTokenType() { + return $this->_tokenType; + } + + /** + * Set Token Type + * + * @param string $value + */ + public function setTokenType($value = PHPExcel_Calculation_FormulaToken::TOKEN_TYPE_UNKNOWN) { + $this->_tokenType = $value; + } + + /** + * Get Token SubType (represented by TOKEN_SUBTYPE_*) + * + * @return string + */ + public function getTokenSubType() { + return $this->_tokenSubType; + } + + /** + * Set Token SubType + * + * @param string $value + */ + public function setTokenSubType($value = PHPExcel_Calculation_FormulaToken::TOKEN_SUBTYPE_NOTHING) { + $this->_tokenSubType = $value; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Function.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Function.php new file mode 100755 index 0000000..b1371e1 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Function.php @@ -0,0 +1,149 @@ +_category = $pCategory; + $this->_excelName = $pExcelName; + $this->_phpExcelName = $pPHPExcelName; + } else { + throw new PHPExcel_Calculation_Exception("Invalid parameters passed."); + } + } + + /** + * Get Category (represented by CATEGORY_*) + * + * @return string + */ + public function getCategory() { + return $this->_category; + } + + /** + * Set Category (represented by CATEGORY_*) + * + * @param string $value + * @throws PHPExcel_Calculation_Exception + */ + public function setCategory($value = null) { + if (!is_null($value)) { + $this->_category = $value; + } else { + throw new PHPExcel_Calculation_Exception("Invalid parameter passed."); + } + } + + /** + * Get Excel name + * + * @return string + */ + public function getExcelName() { + return $this->_excelName; + } + + /** + * Set Excel name + * + * @param string $value + */ + public function setExcelName($value) { + $this->_excelName = $value; + } + + /** + * Get PHPExcel name + * + * @return string + */ + public function getPHPExcelName() { + return $this->_phpExcelName; + } + + /** + * Set PHPExcel name + * + * @param string $value + */ + public function setPHPExcelName($value) { + $this->_phpExcelName = $value; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Functions.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Functions.php new file mode 100755 index 0000000..6b894d8 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Functions.php @@ -0,0 +1,815 @@ + '#NULL!', + 'divisionbyzero' => '#DIV/0!', + 'value' => '#VALUE!', + 'reference' => '#REF!', + 'name' => '#NAME?', + 'num' => '#NUM!', + 'na' => '#N/A', + 'gettingdata' => '#GETTING_DATA' + ); + + + /** + * Set the Compatibility Mode + * + * @access public + * @category Function Configuration + * @param string $compatibilityMode Compatibility Mode + * Permitted values are: + * PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel' + * PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric' + * PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc' + * @return boolean (Success or Failure) + */ + public static function setCompatibilityMode($compatibilityMode) { + if (($compatibilityMode == self::COMPATIBILITY_EXCEL) || + ($compatibilityMode == self::COMPATIBILITY_GNUMERIC) || + ($compatibilityMode == self::COMPATIBILITY_OPENOFFICE)) { + self::$compatibilityMode = $compatibilityMode; + return True; + } + return False; + } // function setCompatibilityMode() + + + /** + * Return the current Compatibility Mode + * + * @access public + * @category Function Configuration + * @return string Compatibility Mode + * Possible Return values are: + * PHPExcel_Calculation_Functions::COMPATIBILITY_EXCEL 'Excel' + * PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC 'Gnumeric' + * PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE 'OpenOfficeCalc' + */ + public static function getCompatibilityMode() { + return self::$compatibilityMode; + } // function getCompatibilityMode() + + + /** + * Set the Return Date Format used by functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object) + * + * @access public + * @category Function Configuration + * @param string $returnDateType Return Date Format + * Permitted values are: + * PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P' + * PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O' + * PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E' + * @return boolean Success or failure + */ + public static function setReturnDateType($returnDateType) { + if (($returnDateType == self::RETURNDATE_PHP_NUMERIC) || + ($returnDateType == self::RETURNDATE_PHP_OBJECT) || + ($returnDateType == self::RETURNDATE_EXCEL)) { + self::$ReturnDateType = $returnDateType; + return True; + } + return False; + } // function setReturnDateType() + + + /** + * Return the current Return Date Format for functions that return a date/time (Excel, PHP Serialized Numeric or PHP Object) + * + * @access public + * @category Function Configuration + * @return string Return Date Format + * Possible Return values are: + * PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC 'P' + * PHPExcel_Calculation_Functions::RETURNDATE_PHP_OBJECT 'O' + * PHPExcel_Calculation_Functions::RETURNDATE_EXCEL 'E' + */ + public static function getReturnDateType() { + return self::$ReturnDateType; + } // function getReturnDateType() + + + /** + * DUMMY + * + * @access public + * @category Error Returns + * @return string #Not Yet Implemented + */ + public static function DUMMY() { + return '#Not Yet Implemented'; + } // function DUMMY() + + + /** + * DIV0 + * + * @access public + * @category Error Returns + * @return string #Not Yet Implemented + */ + public static function DIV0() { + return self::$_errorCodes['divisionbyzero']; + } // function DIV0() + + + /** + * NA + * + * Excel Function: + * =NA() + * + * Returns the error value #N/A + * #N/A is the error value that means "no value is available." + * + * @access public + * @category Logical Functions + * @return string #N/A! + */ + public static function NA() { + return self::$_errorCodes['na']; + } // function NA() + + + /** + * NaN + * + * Returns the error value #NUM! + * + * @access public + * @category Error Returns + * @return string #NUM! + */ + public static function NaN() { + return self::$_errorCodes['num']; + } // function NaN() + + + /** + * NAME + * + * Returns the error value #NAME? + * + * @access public + * @category Error Returns + * @return string #NAME? + */ + public static function NAME() { + return self::$_errorCodes['name']; + } // function NAME() + + + /** + * REF + * + * Returns the error value #REF! + * + * @access public + * @category Error Returns + * @return string #REF! + */ + public static function REF() { + return self::$_errorCodes['reference']; + } // function REF() + + + /** + * NULL + * + * Returns the error value #NULL! + * + * @access public + * @category Error Returns + * @return string #REF! + */ + public static function NULL() { + return self::$_errorCodes['null']; + } // function NULL() + + + /** + * VALUE + * + * Returns the error value #VALUE! + * + * @access public + * @category Error Returns + * @return string #VALUE! + */ + public static function VALUE() { + return self::$_errorCodes['value']; + } // function VALUE() + + + public static function isMatrixValue($idx) { + return ((substr_count($idx,'.') <= 1) || (preg_match('/\.[A-Z]/',$idx) > 0)); + } + + + public static function isValue($idx) { + return (substr_count($idx,'.') == 0); + } + + + public static function isCellValue($idx) { + return (substr_count($idx,'.') > 1); + } + + + public static function _ifCondition($condition) { + $condition = PHPExcel_Calculation_Functions::flattenSingleValue($condition); + if (!isset($condition{0})) + $condition = '=""'; + if (!in_array($condition{0},array('>', '<', '='))) { + if (!is_numeric($condition)) { $condition = PHPExcel_Calculation::_wrapResult(strtoupper($condition)); } + return '='.$condition; + } else { + preg_match('/([<>=]+)(.*)/',$condition,$matches); + list(,$operator,$operand) = $matches; + if (!is_numeric($operand)) { $operand = PHPExcel_Calculation::_wrapResult(strtoupper($operand)); } + return $operator.$operand; + } + } // function _ifCondition() + + + /** + * ERROR_TYPE + * + * @param mixed $value Value to check + * @return boolean + */ + public static function ERROR_TYPE($value = '') { + $value = self::flattenSingleValue($value); + + $i = 1; + foreach(self::$_errorCodes as $errorCode) { + if ($value === $errorCode) { + return $i; + } + ++$i; + } + return self::NA(); + } // function ERROR_TYPE() + + + /** + * IS_BLANK + * + * @param mixed $value Value to check + * @return boolean + */ + public static function IS_BLANK($value = NULL) { + if (!is_null($value)) { + $value = self::flattenSingleValue($value); + } + + return is_null($value); + } // function IS_BLANK() + + + /** + * IS_ERR + * + * @param mixed $value Value to check + * @return boolean + */ + public static function IS_ERR($value = '') { + $value = self::flattenSingleValue($value); + + return self::IS_ERROR($value) && (!self::IS_NA($value)); + } // function IS_ERR() + + + /** + * IS_ERROR + * + * @param mixed $value Value to check + * @return boolean + */ + public static function IS_ERROR($value = '') { + $value = self::flattenSingleValue($value); + + if (!is_string($value)) + return false; + return in_array($value, array_values(self::$_errorCodes)); + } // function IS_ERROR() + + + /** + * IS_NA + * + * @param mixed $value Value to check + * @return boolean + */ + public static function IS_NA($value = '') { + $value = self::flattenSingleValue($value); + + return ($value === self::NA()); + } // function IS_NA() + + + /** + * IS_EVEN + * + * @param mixed $value Value to check + * @return boolean + */ + public static function IS_EVEN($value = NULL) { + $value = self::flattenSingleValue($value); + + if ($value === NULL) + return self::NAME(); + if ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) + return self::VALUE(); + return ($value % 2 == 0); + } // function IS_EVEN() + + + /** + * IS_ODD + * + * @param mixed $value Value to check + * @return boolean + */ + public static function IS_ODD($value = NULL) { + $value = self::flattenSingleValue($value); + + if ($value === NULL) + return self::NAME(); + if ((is_bool($value)) || ((is_string($value)) && (!is_numeric($value)))) + return self::VALUE(); + return (abs($value) % 2 == 1); + } // function IS_ODD() + + + /** + * IS_NUMBER + * + * @param mixed $value Value to check + * @return boolean + */ + public static function IS_NUMBER($value = NULL) { + $value = self::flattenSingleValue($value); + + if (is_string($value)) { + return False; + } + return is_numeric($value); + } // function IS_NUMBER() + + + /** + * IS_LOGICAL + * + * @param mixed $value Value to check + * @return boolean + */ + public static function IS_LOGICAL($value = NULL) { + $value = self::flattenSingleValue($value); + + return is_bool($value); + } // function IS_LOGICAL() + + + /** + * IS_TEXT + * + * @param mixed $value Value to check + * @return boolean + */ + public static function IS_TEXT($value = NULL) { + $value = self::flattenSingleValue($value); + + return (is_string($value) && !self::IS_ERROR($value)); + } // function IS_TEXT() + + + /** + * IS_NONTEXT + * + * @param mixed $value Value to check + * @return boolean + */ + public static function IS_NONTEXT($value = NULL) { + return !self::IS_TEXT($value); + } // function IS_NONTEXT() + + + /** + * VERSION + * + * @return string Version information + */ + public static function VERSION() { + return 'PHPExcel 1.7.9, 2013-06-02'; + } // function VERSION() + + + /** + * N + * + * Returns a value converted to a number + * + * @param value The value you want converted + * @return number N converts values listed in the following table + * If value is or refers to N returns + * A number That number + * A date The serial number of that date + * TRUE 1 + * FALSE 0 + * An error value The error value + * Anything else 0 + */ + public static function N($value = NULL) { + while (is_array($value)) { + $value = array_shift($value); + } + + switch (gettype($value)) { + case 'double' : + case 'float' : + case 'integer' : + return $value; + break; + case 'boolean' : + return (integer) $value; + break; + case 'string' : + // Errors + if ((strlen($value) > 0) && ($value{0} == '#')) { + return $value; + } + break; + } + return 0; + } // function N() + + + /** + * TYPE + * + * Returns a number that identifies the type of a value + * + * @param value The value you want tested + * @return number N converts values listed in the following table + * If value is or refers to N returns + * A number 1 + * Text 2 + * Logical Value 4 + * An error value 16 + * Array or Matrix 64 + */ + public static function TYPE($value = NULL) { + $value = self::flattenArrayIndexed($value); + if (is_array($value) && (count($value) > 1)) { + $a = array_keys($value); + $a = array_pop($a); + // Range of cells is an error + if (self::isCellValue($a)) { + return 16; + // Test for Matrix + } elseif (self::isMatrixValue($a)) { + return 64; + } + } elseif(empty($value)) { + // Empty Cell + return 1; + } + $value = self::flattenSingleValue($value); + + if (($value === NULL) || (is_float($value)) || (is_int($value))) { + return 1; + } elseif(is_bool($value)) { + return 4; + } elseif(is_array($value)) { + return 64; + break; + } elseif(is_string($value)) { + // Errors + if ((strlen($value) > 0) && ($value{0} == '#')) { + return 16; + } + return 2; + } + return 0; + } // function TYPE() + + + /** + * Convert a multi-dimensional array to a simple 1-dimensional array + * + * @param array $array Array to be flattened + * @return array Flattened array + */ + public static function flattenArray($array) { + if (!is_array($array)) { + return (array) $array; + } + + $arrayValues = array(); + foreach ($array as $value) { + if (is_array($value)) { + foreach ($value as $val) { + if (is_array($val)) { + foreach ($val as $v) { + $arrayValues[] = $v; + } + } else { + $arrayValues[] = $val; + } + } + } else { + $arrayValues[] = $value; + } + } + + return $arrayValues; + } // function flattenArray() + + + /** + * Convert a multi-dimensional array to a simple 1-dimensional array, but retain an element of indexing + * + * @param array $array Array to be flattened + * @return array Flattened array + */ + public static function flattenArrayIndexed($array) { + if (!is_array($array)) { + return (array) $array; + } + + $arrayValues = array(); + foreach ($array as $k1 => $value) { + if (is_array($value)) { + foreach ($value as $k2 => $val) { + if (is_array($val)) { + foreach ($val as $k3 => $v) { + $arrayValues[$k1.'.'.$k2.'.'.$k3] = $v; + } + } else { + $arrayValues[$k1.'.'.$k2] = $val; + } + } + } else { + $arrayValues[$k1] = $value; + } + } + + return $arrayValues; + } // function flattenArrayIndexed() + + + /** + * Convert an array to a single scalar value by extracting the first element + * + * @param mixed $value Array or scalar value + * @return mixed + */ + public static function flattenSingleValue($value = '') { + while (is_array($value)) { + $value = array_pop($value); + } + + return $value; + } // function flattenSingleValue() + +} // class PHPExcel_Calculation_Functions + + +// +// There are a few mathematical functions that aren't available on all versions of PHP for all platforms +// These functions aren't available in Windows implementations of PHP prior to version 5.3.0 +// So we test if they do exist for this version of PHP/operating platform; and if not we create them +// +if (!function_exists('acosh')) { + function acosh($x) { + return 2 * log(sqrt(($x + 1) / 2) + sqrt(($x - 1) / 2)); + } // function acosh() +} + +if (!function_exists('asinh')) { + function asinh($x) { + return log($x + sqrt(1 + $x * $x)); + } // function asinh() +} + +if (!function_exists('atanh')) { + function atanh($x) { + return (log(1 + $x) - log(1 - $x)) / 2; + } // function atanh() +} + +if (!function_exists('money_format')) { + function money_format($format, $number) { + $regex = array( '/%((?:[\^!\-]|\+|\(|\=.)*)([0-9]+)?(?:#([0-9]+))?', + '(?:\.([0-9]+))?([in%])/' + ); + $regex = implode('', $regex); + if (setlocale(LC_MONETARY, null) == '') { + setlocale(LC_MONETARY, ''); + } + $locale = localeconv(); + $number = floatval($number); + if (!preg_match($regex, $format, $fmatch)) { + trigger_error("No format specified or invalid format", E_USER_WARNING); + return $number; + } + $flags = array( 'fillchar' => preg_match('/\=(.)/', $fmatch[1], $match) ? $match[1] : ' ', + 'nogroup' => preg_match('/\^/', $fmatch[1]) > 0, + 'usesignal' => preg_match('/\+|\(/', $fmatch[1], $match) ? $match[0] : '+', + 'nosimbol' => preg_match('/\!/', $fmatch[1]) > 0, + 'isleft' => preg_match('/\-/', $fmatch[1]) > 0 + ); + $width = trim($fmatch[2]) ? (int)$fmatch[2] : 0; + $left = trim($fmatch[3]) ? (int)$fmatch[3] : 0; + $right = trim($fmatch[4]) ? (int)$fmatch[4] : $locale['int_frac_digits']; + $conversion = $fmatch[5]; + $positive = true; + if ($number < 0) { + $positive = false; + $number *= -1; + } + $letter = $positive ? 'p' : 'n'; + $prefix = $suffix = $cprefix = $csuffix = $signal = ''; + if (!$positive) { + $signal = $locale['negative_sign']; + switch (true) { + case $locale['n_sign_posn'] == 0 || $flags['usesignal'] == '(': + $prefix = '('; + $suffix = ')'; + break; + case $locale['n_sign_posn'] == 1: + $prefix = $signal; + break; + case $locale['n_sign_posn'] == 2: + $suffix = $signal; + break; + case $locale['n_sign_posn'] == 3: + $cprefix = $signal; + break; + case $locale['n_sign_posn'] == 4: + $csuffix = $signal; + break; + } + } + if (!$flags['nosimbol']) { + $currency = $cprefix; + $currency .= ($conversion == 'i' ? $locale['int_curr_symbol'] : $locale['currency_symbol']); + $currency .= $csuffix; + $currency = iconv('ISO-8859-1','UTF-8',$currency); + } else { + $currency = ''; + } + $space = $locale["{$letter}_sep_by_space"] ? ' ' : ''; + + if (!isset($locale['mon_decimal_point']) || empty($locale['mon_decimal_point'])) { + $locale['mon_decimal_point'] = (!isset($locale['decimal_point']) || empty($locale['decimal_point'])) ? + $locale['decimal_point'] : + '.'; + } + + $number = number_format($number, $right, $locale['mon_decimal_point'], $flags['nogroup'] ? '' : $locale['mon_thousands_sep'] ); + $number = explode($locale['mon_decimal_point'], $number); + + $n = strlen($prefix) + strlen($currency); + if ($left > 0 && $left > $n) { + if ($flags['isleft']) { + $number[0] .= str_repeat($flags['fillchar'], $left - $n); + } else { + $number[0] = str_repeat($flags['fillchar'], $left - $n) . $number[0]; + } + } + $number = implode($locale['mon_decimal_point'], $number); + if ($locale["{$letter}_cs_precedes"]) { + $number = $prefix . $currency . $space . $number . $suffix; + } else { + $number = $prefix . $number . $space . $currency . $suffix; + } + if ($width > 0) { + $number = str_pad($number, $width, $flags['fillchar'], $flags['isleft'] ? STR_PAD_RIGHT : STR_PAD_LEFT); + } + $format = str_replace($fmatch[0], $number, $format); + return $format; + } // function money_format() +} + + +// +// Strangely, PHP doesn't have a mb_str_replace multibyte function +// As we'll only ever use this function with UTF-8 characters, we can simply "hard-code" the character set +// +if ((!function_exists('mb_str_replace')) && + (function_exists('mb_substr')) && (function_exists('mb_strlen')) && (function_exists('mb_strpos'))) { + function mb_str_replace($search, $replace, $subject) { + if(is_array($subject)) { + $ret = array(); + foreach($subject as $key => $val) { + $ret[$key] = mb_str_replace($search, $replace, $val); + } + return $ret; + } + + foreach((array) $search as $key => $s) { + if($s == '') { + continue; + } + $r = !is_array($replace) ? $replace : (array_key_exists($key, $replace) ? $replace[$key] : ''); + $pos = mb_strpos($subject, $s, 0, 'UTF-8'); + while($pos !== false) { + $subject = mb_substr($subject, 0, $pos, 'UTF-8') . $r . mb_substr($subject, $pos + mb_strlen($s, 'UTF-8'), 65535, 'UTF-8'); + $pos = mb_strpos($subject, $s, $pos + mb_strlen($r, 'UTF-8'), 'UTF-8'); + } + } + return $subject; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Logical.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Logical.php new file mode 100755 index 0000000..85bc61b --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Logical.php @@ -0,0 +1,288 @@ + $arg) { + // Is it a boolean value? + if (is_bool($arg)) { + $returnValue = $returnValue && $arg; + } elseif ((is_numeric($arg)) && (!is_string($arg))) { + $returnValue = $returnValue && ($arg != 0); + } elseif (is_string($arg)) { + $arg = strtoupper($arg); + if (($arg == 'TRUE') || ($arg == PHPExcel_Calculation::getTRUE())) { + $arg = TRUE; + } elseif (($arg == 'FALSE') || ($arg == PHPExcel_Calculation::getFALSE())) { + $arg = FALSE; + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + $returnValue = $returnValue && ($arg != 0); + } + } + + // Return + if ($argCount < 0) { + return PHPExcel_Calculation_Functions::VALUE(); + } + return $returnValue; + } // function LOGICAL_AND() + + + /** + * LOGICAL_OR + * + * Returns boolean TRUE if any argument is TRUE; returns FALSE if all arguments are FALSE. + * + * Excel Function: + * =OR(logical1[,logical2[, ...]]) + * + * The arguments must evaluate to logical values such as TRUE or FALSE, or the arguments must be arrays + * or references that contain logical values. + * + * Boolean arguments are treated as True or False as appropriate + * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds + * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * + * @access public + * @category Logical Functions + * @param mixed $arg,... Data values + * @return boolean The logical OR of the arguments. + */ + public static function LOGICAL_OR() { + // Return value + $returnValue = FALSE; + + // Loop through the arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + $argCount = -1; + foreach ($aArgs as $argCount => $arg) { + // Is it a boolean value? + if (is_bool($arg)) { + $returnValue = $returnValue || $arg; + } elseif ((is_numeric($arg)) && (!is_string($arg))) { + $returnValue = $returnValue || ($arg != 0); + } elseif (is_string($arg)) { + $arg = strtoupper($arg); + if (($arg == 'TRUE') || ($arg == PHPExcel_Calculation::getTRUE())) { + $arg = TRUE; + } elseif (($arg == 'FALSE') || ($arg == PHPExcel_Calculation::getFALSE())) { + $arg = FALSE; + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + $returnValue = $returnValue || ($arg != 0); + } + } + + // Return + if ($argCount < 0) { + return PHPExcel_Calculation_Functions::VALUE(); + } + return $returnValue; + } // function LOGICAL_OR() + + + /** + * NOT + * + * Returns the boolean inverse of the argument. + * + * Excel Function: + * =NOT(logical) + * + * The argument must evaluate to a logical value such as TRUE or FALSE + * + * Boolean arguments are treated as True or False as appropriate + * Integer or floating point arguments are treated as True, except for 0 or 0.0 which are False + * If any argument value is a string, or a Null, the function returns a #VALUE! error, unless the string holds + * the value TRUE or FALSE, in which case it is evaluated as the corresponding boolean value + * + * @access public + * @category Logical Functions + * @param mixed $logical A value or expression that can be evaluated to TRUE or FALSE + * @return boolean The boolean inverse of the argument. + */ + public static function NOT($logical=FALSE) { + $logical = PHPExcel_Calculation_Functions::flattenSingleValue($logical); + if (is_string($logical)) { + $logical = strtoupper($logical); + if (($logical == 'TRUE') || ($logical == PHPExcel_Calculation::getTRUE())) { + return FALSE; + } elseif (($logical == 'FALSE') || ($logical == PHPExcel_Calculation::getFALSE())) { + return TRUE; + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + + return !$logical; + } // function NOT() + + /** + * STATEMENT_IF + * + * Returns one value if a condition you specify evaluates to TRUE and another value if it evaluates to FALSE. + * + * Excel Function: + * =IF(condition[,returnIfTrue[,returnIfFalse]]) + * + * Condition is any value or expression that can be evaluated to TRUE or FALSE. + * For example, A10=100 is a logical expression; if the value in cell A10 is equal to 100, + * the expression evaluates to TRUE. Otherwise, the expression evaluates to FALSE. + * This argument can use any comparison calculation operator. + * ReturnIfTrue is the value that is returned if condition evaluates to TRUE. + * For example, if this argument is the text string "Within budget" and the condition argument evaluates to TRUE, + * then the IF function returns the text "Within budget" + * If condition is TRUE and ReturnIfTrue is blank, this argument returns 0 (zero). To display the word TRUE, use + * the logical value TRUE for this argument. + * ReturnIfTrue can be another formula. + * ReturnIfFalse is the value that is returned if condition evaluates to FALSE. + * For example, if this argument is the text string "Over budget" and the condition argument evaluates to FALSE, + * then the IF function returns the text "Over budget". + * If condition is FALSE and ReturnIfFalse is omitted, then the logical value FALSE is returned. + * If condition is FALSE and ReturnIfFalse is blank, then the value 0 (zero) is returned. + * ReturnIfFalse can be another formula. + * + * @access public + * @category Logical Functions + * @param mixed $condition Condition to evaluate + * @param mixed $returnIfTrue Value to return when condition is true + * @param mixed $returnIfFalse Optional value to return when condition is false + * @return mixed The value of returnIfTrue or returnIfFalse determined by condition + */ + public static function STATEMENT_IF($condition = TRUE, $returnIfTrue = 0, $returnIfFalse = FALSE) { + $condition = (is_null($condition)) ? TRUE : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($condition); + $returnIfTrue = (is_null($returnIfTrue)) ? 0 : PHPExcel_Calculation_Functions::flattenSingleValue($returnIfTrue); + $returnIfFalse = (is_null($returnIfFalse)) ? FALSE : PHPExcel_Calculation_Functions::flattenSingleValue($returnIfFalse); + + return ($condition) ? $returnIfTrue : $returnIfFalse; + } // function STATEMENT_IF() + + + /** + * IFERROR + * + * Excel Function: + * =IFERROR(testValue,errorpart) + * + * @access public + * @category Logical Functions + * @param mixed $testValue Value to check, is also the value returned when no error + * @param mixed $errorpart Value to return when testValue is an error condition + * @return mixed The value of errorpart or testValue determined by error condition + */ + public static function IFERROR($testValue = '', $errorpart = '') { + $testValue = (is_null($testValue)) ? '' : PHPExcel_Calculation_Functions::flattenSingleValue($testValue); + $errorpart = (is_null($errorpart)) ? '' : PHPExcel_Calculation_Functions::flattenSingleValue($errorpart); + + return self::STATEMENT_IF(PHPExcel_Calculation_Functions::IS_ERROR($testValue), $errorpart, $testValue); + } // function IFERROR() + +} // class PHPExcel_Calculation_Logical diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/LookupRef.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/LookupRef.php new file mode 100755 index 0000000..f357ff8 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/LookupRef.php @@ -0,0 +1,812 @@ + '') { + if (strpos($sheetText,' ') !== False) { $sheetText = "'".$sheetText."'"; } + $sheetText .='!'; + } + if ((!is_bool($referenceStyle)) || $referenceStyle) { + $rowRelative = $columnRelative = '$'; + $column = PHPExcel_Cell::stringFromColumnIndex($column-1); + if (($relativity == 2) || ($relativity == 4)) { $columnRelative = ''; } + if (($relativity == 3) || ($relativity == 4)) { $rowRelative = ''; } + return $sheetText.$columnRelative.$column.$rowRelative.$row; + } else { + if (($relativity == 2) || ($relativity == 4)) { $column = '['.$column.']'; } + if (($relativity == 3) || ($relativity == 4)) { $row = '['.$row.']'; } + return $sheetText.'R'.$row.'C'.$column; + } + } // function CELL_ADDRESS() + + + /** + * COLUMN + * + * Returns the column number of the given cell reference + * If the cell reference is a range of cells, COLUMN returns the column numbers of each column in the reference as a horizontal array. + * If cell reference is omitted, and the function is being called through the calculation engine, then it is assumed to be the + * reference of the cell in which the COLUMN function appears; otherwise this function returns 0. + * + * Excel Function: + * =COLUMN([cellAddress]) + * + * @param cellAddress A reference to a range of cells for which you want the column numbers + * @return integer or array of integer + */ + public static function COLUMN($cellAddress=Null) { + if (is_null($cellAddress) || trim($cellAddress) === '') { return 0; } + + if (is_array($cellAddress)) { + foreach($cellAddress as $columnKey => $value) { + $columnKey = preg_replace('/[^a-z]/i','',$columnKey); + return (integer) PHPExcel_Cell::columnIndexFromString($columnKey); + } + } else { + if (strpos($cellAddress,'!') !== false) { + list($sheet,$cellAddress) = explode('!',$cellAddress); + } + if (strpos($cellAddress,':') !== false) { + list($startAddress,$endAddress) = explode(':',$cellAddress); + $startAddress = preg_replace('/[^a-z]/i','',$startAddress); + $endAddress = preg_replace('/[^a-z]/i','',$endAddress); + $returnValue = array(); + do { + $returnValue[] = (integer) PHPExcel_Cell::columnIndexFromString($startAddress); + } while ($startAddress++ != $endAddress); + return $returnValue; + } else { + $cellAddress = preg_replace('/[^a-z]/i','',$cellAddress); + return (integer) PHPExcel_Cell::columnIndexFromString($cellAddress); + } + } + } // function COLUMN() + + + /** + * COLUMNS + * + * Returns the number of columns in an array or reference. + * + * Excel Function: + * =COLUMNS(cellAddress) + * + * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of columns + * @return integer The number of columns in cellAddress + */ + public static function COLUMNS($cellAddress=Null) { + if (is_null($cellAddress) || $cellAddress === '') { + return 1; + } elseif (!is_array($cellAddress)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + $x = array_keys($cellAddress); + $x = array_shift($x); + $isMatrix = (is_numeric($x)); + list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); + + if ($isMatrix) { + return $rows; + } else { + return $columns; + } + } // function COLUMNS() + + + /** + * ROW + * + * Returns the row number of the given cell reference + * If the cell reference is a range of cells, ROW returns the row numbers of each row in the reference as a vertical array. + * If cell reference is omitted, and the function is being called through the calculation engine, then it is assumed to be the + * reference of the cell in which the ROW function appears; otherwise this function returns 0. + * + * Excel Function: + * =ROW([cellAddress]) + * + * @param cellAddress A reference to a range of cells for which you want the row numbers + * @return integer or array of integer + */ + public static function ROW($cellAddress=Null) { + if (is_null($cellAddress) || trim($cellAddress) === '') { return 0; } + + if (is_array($cellAddress)) { + foreach($cellAddress as $columnKey => $rowValue) { + foreach($rowValue as $rowKey => $cellValue) { + return (integer) preg_replace('/[^0-9]/i','',$rowKey); + } + } + } else { + if (strpos($cellAddress,'!') !== false) { + list($sheet,$cellAddress) = explode('!',$cellAddress); + } + if (strpos($cellAddress,':') !== false) { + list($startAddress,$endAddress) = explode(':',$cellAddress); + $startAddress = preg_replace('/[^0-9]/','',$startAddress); + $endAddress = preg_replace('/[^0-9]/','',$endAddress); + $returnValue = array(); + do { + $returnValue[][] = (integer) $startAddress; + } while ($startAddress++ != $endAddress); + return $returnValue; + } else { + list($cellAddress) = explode(':',$cellAddress); + return (integer) preg_replace('/[^0-9]/','',$cellAddress); + } + } + } // function ROW() + + + /** + * ROWS + * + * Returns the number of rows in an array or reference. + * + * Excel Function: + * =ROWS(cellAddress) + * + * @param cellAddress An array or array formula, or a reference to a range of cells for which you want the number of rows + * @return integer The number of rows in cellAddress + */ + public static function ROWS($cellAddress=Null) { + if (is_null($cellAddress) || $cellAddress === '') { + return 1; + } elseif (!is_array($cellAddress)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + $i = array_keys($cellAddress); + $isMatrix = (is_numeric(array_shift($i))); + list($columns,$rows) = PHPExcel_Calculation::_getMatrixDimensions($cellAddress); + + if ($isMatrix) { + return $columns; + } else { + return $rows; + } + } // function ROWS() + + + /** + * HYPERLINK + * + * Excel Function: + * =HYPERLINK(linkURL,displayName) + * + * @access public + * @category Logical Functions + * @param string $linkURL Value to check, is also the value returned when no error + * @param string $displayName Value to return when testValue is an error condition + * @param PHPExcel_Cell $pCell The cell to set the hyperlink in + * @return mixed The value of $displayName (or $linkURL if $displayName was blank) + */ + public static function HYPERLINK($linkURL = '', $displayName = null, PHPExcel_Cell $pCell = null) { + $args = func_get_args(); + $pCell = array_pop($args); + + $linkURL = (is_null($linkURL)) ? '' : PHPExcel_Calculation_Functions::flattenSingleValue($linkURL); + $displayName = (is_null($displayName)) ? '' : PHPExcel_Calculation_Functions::flattenSingleValue($displayName); + + if ((!is_object($pCell)) || (trim($linkURL) == '')) { + return PHPExcel_Calculation_Functions::REF(); + } + + if ((is_object($displayName)) || trim($displayName) == '') { + $displayName = $linkURL; + } + + $pCell->getHyperlink()->setUrl($linkURL); + + return $displayName; + } // function HYPERLINK() + + + /** + * INDIRECT + * + * Returns the reference specified by a text string. + * References are immediately evaluated to display their contents. + * + * Excel Function: + * =INDIRECT(cellAddress) + * + * NOTE - INDIRECT() does not yet support the optional a1 parameter introduced in Excel 2010 + * + * @param cellAddress $cellAddress The cell address of the current cell (containing this formula) + * @param PHPExcel_Cell $pCell The current cell (containing this formula) + * @return mixed The cells referenced by cellAddress + * + * @todo Support for the optional a1 parameter introduced in Excel 2010 + * + */ + public static function INDIRECT($cellAddress = NULL, PHPExcel_Cell $pCell = NULL) { + $cellAddress = PHPExcel_Calculation_Functions::flattenSingleValue($cellAddress); + if (is_null($cellAddress) || $cellAddress === '') { + return PHPExcel_Calculation_Functions::REF(); + } + + $cellAddress1 = $cellAddress; + $cellAddress2 = NULL; + if (strpos($cellAddress,':') !== false) { + list($cellAddress1,$cellAddress2) = explode(':',$cellAddress); + } + + if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress1, $matches)) || + ((!is_null($cellAddress2)) && (!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $cellAddress2, $matches)))) { + if (!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $cellAddress1, $matches)) { + return PHPExcel_Calculation_Functions::REF(); + } + + if (strpos($cellAddress,'!') !== FALSE) { + list($sheetName, $cellAddress) = explode('!',$cellAddress); + $sheetName = trim($sheetName, "'"); + $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); + } else { + $pSheet = $pCell->getParent(); + } + + return PHPExcel_Calculation::getInstance()->extractNamedRange($cellAddress, $pSheet, FALSE); + } + + if (strpos($cellAddress,'!') !== FALSE) { + list($sheetName,$cellAddress) = explode('!',$cellAddress); + $sheetName = trim($sheetName, "'"); + $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); + } else { + $pSheet = $pCell->getParent(); + } + + return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, FALSE); + } // function INDIRECT() + + + /** + * OFFSET + * + * Returns a reference to a range that is a specified number of rows and columns from a cell or range of cells. + * The reference that is returned can be a single cell or a range of cells. You can specify the number of rows and + * the number of columns to be returned. + * + * Excel Function: + * =OFFSET(cellAddress, rows, cols, [height], [width]) + * + * @param cellAddress The reference from which you want to base the offset. Reference must refer to a cell or + * range of adjacent cells; otherwise, OFFSET returns the #VALUE! error value. + * @param rows The number of rows, up or down, that you want the upper-left cell to refer to. + * Using 5 as the rows argument specifies that the upper-left cell in the reference is + * five rows below reference. Rows can be positive (which means below the starting reference) + * or negative (which means above the starting reference). + * @param cols The number of columns, to the left or right, that you want the upper-left cell of the result + * to refer to. Using 5 as the cols argument specifies that the upper-left cell in the + * reference is five columns to the right of reference. Cols can be positive (which means + * to the right of the starting reference) or negative (which means to the left of the + * starting reference). + * @param height The height, in number of rows, that you want the returned reference to be. Height must be a positive number. + * @param width The width, in number of columns, that you want the returned reference to be. Width must be a positive number. + * @return string A reference to a cell or range of cells + */ + public static function OFFSET($cellAddress=Null,$rows=0,$columns=0,$height=null,$width=null) { + $rows = PHPExcel_Calculation_Functions::flattenSingleValue($rows); + $columns = PHPExcel_Calculation_Functions::flattenSingleValue($columns); + $height = PHPExcel_Calculation_Functions::flattenSingleValue($height); + $width = PHPExcel_Calculation_Functions::flattenSingleValue($width); + if ($cellAddress == Null) { + return 0; + } + + $args = func_get_args(); + $pCell = array_pop($args); + if (!is_object($pCell)) { + return PHPExcel_Calculation_Functions::REF(); + } + + $sheetName = NULL; + if (strpos($cellAddress,"!")) { + list($sheetName,$cellAddress) = explode("!",$cellAddress); + $sheetName = trim($sheetName, "'"); + } + if (strpos($cellAddress,":")) { + list($startCell,$endCell) = explode(":",$cellAddress); + } else { + $startCell = $endCell = $cellAddress; + } + list($startCellColumn,$startCellRow) = PHPExcel_Cell::coordinateFromString($startCell); + list($endCellColumn,$endCellRow) = PHPExcel_Cell::coordinateFromString($endCell); + + $startCellRow += $rows; + $startCellColumn = PHPExcel_Cell::columnIndexFromString($startCellColumn) - 1; + $startCellColumn += $columns; + + if (($startCellRow <= 0) || ($startCellColumn < 0)) { + return PHPExcel_Calculation_Functions::REF(); + } + $endCellColumn = PHPExcel_Cell::columnIndexFromString($endCellColumn) - 1; + if (($width != null) && (!is_object($width))) { + $endCellColumn = $startCellColumn + $width - 1; + } else { + $endCellColumn += $columns; + } + $startCellColumn = PHPExcel_Cell::stringFromColumnIndex($startCellColumn); + + if (($height != null) && (!is_object($height))) { + $endCellRow = $startCellRow + $height - 1; + } else { + $endCellRow += $rows; + } + + if (($endCellRow <= 0) || ($endCellColumn < 0)) { + return PHPExcel_Calculation_Functions::REF(); + } + $endCellColumn = PHPExcel_Cell::stringFromColumnIndex($endCellColumn); + + $cellAddress = $startCellColumn.$startCellRow; + if (($startCellColumn != $endCellColumn) || ($startCellRow != $endCellRow)) { + $cellAddress .= ':'.$endCellColumn.$endCellRow; + } + + if ($sheetName !== NULL) { + $pSheet = $pCell->getParent()->getParent()->getSheetByName($sheetName); + } else { + $pSheet = $pCell->getParent(); + } + + return PHPExcel_Calculation::getInstance()->extractCellRange($cellAddress, $pSheet, False); + } // function OFFSET() + + + /** + * CHOOSE + * + * Uses lookup_value to return a value from the list of value arguments. + * Use CHOOSE to select one of up to 254 values based on the lookup_value. + * + * Excel Function: + * =CHOOSE(index_num, value1, [value2], ...) + * + * @param index_num Specifies which value argument is selected. + * Index_num must be a number between 1 and 254, or a formula or reference to a cell containing a number + * between 1 and 254. + * @param value1... Value1 is required, subsequent values are optional. + * Between 1 to 254 value arguments from which CHOOSE selects a value or an action to perform based on + * index_num. The arguments can be numbers, cell references, defined names, formulas, functions, or + * text. + * @return mixed The selected value + */ + public static function CHOOSE() { + $chooseArgs = func_get_args(); + $chosenEntry = PHPExcel_Calculation_Functions::flattenArray(array_shift($chooseArgs)); + $entryCount = count($chooseArgs) - 1; + + if(is_array($chosenEntry)) { + $chosenEntry = array_shift($chosenEntry); + } + if ((is_numeric($chosenEntry)) && (!is_bool($chosenEntry))) { + --$chosenEntry; + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + $chosenEntry = floor($chosenEntry); + if (($chosenEntry <= 0) || ($chosenEntry > $entryCount)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (is_array($chooseArgs[$chosenEntry])) { + return PHPExcel_Calculation_Functions::flattenArray($chooseArgs[$chosenEntry]); + } else { + return $chooseArgs[$chosenEntry]; + } + } // function CHOOSE() + + + /** + * MATCH + * + * The MATCH function searches for a specified item in a range of cells + * + * Excel Function: + * =MATCH(lookup_value, lookup_array, [match_type]) + * + * @param lookup_value The value that you want to match in lookup_array + * @param lookup_array The range of cells being searched + * @param match_type The number -1, 0, or 1. -1 means above, 0 means exact match, 1 means below. If match_type is 1 or -1, the list has to be ordered. + * @return integer The relative position of the found item + */ + public static function MATCH($lookup_value, $lookup_array, $match_type=1) { + $lookup_array = PHPExcel_Calculation_Functions::flattenArray($lookup_array); + $lookup_value = PHPExcel_Calculation_Functions::flattenSingleValue($lookup_value); + $match_type = (is_null($match_type)) ? 1 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($match_type); + // MATCH is not case sensitive + $lookup_value = strtolower($lookup_value); + + // lookup_value type has to be number, text, or logical values + if ((!is_numeric($lookup_value)) && (!is_string($lookup_value)) && (!is_bool($lookup_value))) { + return PHPExcel_Calculation_Functions::NA(); + } + + // match_type is 0, 1 or -1 + if (($match_type !== 0) && ($match_type !== -1) && ($match_type !== 1)) { + return PHPExcel_Calculation_Functions::NA(); + } + + // lookup_array should not be empty + $lookupArraySize = count($lookup_array); + if ($lookupArraySize <= 0) { + return PHPExcel_Calculation_Functions::NA(); + } + + // lookup_array should contain only number, text, or logical values, or empty (null) cells + foreach($lookup_array as $i => $lookupArrayValue) { + // check the type of the value + if ((!is_numeric($lookupArrayValue)) && (!is_string($lookupArrayValue)) && + (!is_bool($lookupArrayValue)) && (!is_null($lookupArrayValue))) { + return PHPExcel_Calculation_Functions::NA(); + } + // convert strings to lowercase for case-insensitive testing + if (is_string($lookupArrayValue)) { + $lookup_array[$i] = strtolower($lookupArrayValue); + } + if ((is_null($lookupArrayValue)) && (($match_type == 1) || ($match_type == -1))) { + $lookup_array = array_slice($lookup_array,0,$i-1); + } + } + + // if match_type is 1 or -1, the list has to be ordered + if ($match_type == 1) { + asort($lookup_array); + $keySet = array_keys($lookup_array); + } elseif($match_type == -1) { + arsort($lookup_array); + $keySet = array_keys($lookup_array); + } + + // ** + // find the match + // ** + // loop on the cells +// var_dump($lookup_array); +// echo '
    '; + foreach($lookup_array as $i => $lookupArrayValue) { + if (($match_type == 0) && ($lookupArrayValue == $lookup_value)) { + // exact match + return ++$i; + } elseif (($match_type == -1) && ($lookupArrayValue <= $lookup_value)) { +// echo '$i = '.$i.' => '; +// var_dump($lookupArrayValue); +// echo '
    '; +// echo 'Keyset = '; +// var_dump($keySet); +// echo '
    '; + $i = array_search($i,$keySet); +// echo '$i='.$i.'
    '; + // if match_type is -1 <=> find the smallest value that is greater than or equal to lookup_value + if ($i < 1){ + // 1st cell was allready smaller than the lookup_value + break; + } else { + // the previous cell was the match + return $keySet[$i-1]+1; + } + } elseif (($match_type == 1) && ($lookupArrayValue >= $lookup_value)) { +// echo '$i = '.$i.' => '; +// var_dump($lookupArrayValue); +// echo '
    '; +// echo 'Keyset = '; +// var_dump($keySet); +// echo '
    '; + $i = array_search($i,$keySet); +// echo '$i='.$i.'
    '; + // if match_type is 1 <=> find the largest value that is less than or equal to lookup_value + if ($i < 1){ + // 1st cell was allready bigger than the lookup_value + break; + } else { + // the previous cell was the match + return $keySet[$i-1]+1; + } + } + } + + // unsuccessful in finding a match, return #N/A error value + return PHPExcel_Calculation_Functions::NA(); + } // function MATCH() + + + /** + * INDEX + * + * Uses an index to choose a value from a reference or array + * + * Excel Function: + * =INDEX(range_array, row_num, [column_num]) + * + * @param range_array A range of cells or an array constant + * @param row_num The row in array from which to return a value. If row_num is omitted, column_num is required. + * @param column_num The column in array from which to return a value. If column_num is omitted, row_num is required. + * @return mixed the value of a specified cell or array of cells + */ + public static function INDEX($arrayValues,$rowNum = 0,$columnNum = 0) { + + if (($rowNum < 0) || ($columnNum < 0)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (!is_array($arrayValues)) { + return PHPExcel_Calculation_Functions::REF(); + } + + $rowKeys = array_keys($arrayValues); + $columnKeys = @array_keys($arrayValues[$rowKeys[0]]); + + if ($columnNum > count($columnKeys)) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif ($columnNum == 0) { + if ($rowNum == 0) { + return $arrayValues; + } + $rowNum = $rowKeys[--$rowNum]; + $returnArray = array(); + foreach($arrayValues as $arrayColumn) { + if (is_array($arrayColumn)) { + if (isset($arrayColumn[$rowNum])) { + $returnArray[] = $arrayColumn[$rowNum]; + } else { + return $arrayValues[$rowNum]; + } + } else { + return $arrayValues[$rowNum]; + } + } + return $returnArray; + } + $columnNum = $columnKeys[--$columnNum]; + if ($rowNum > count($rowKeys)) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif ($rowNum == 0) { + return $arrayValues[$columnNum]; + } + $rowNum = $rowKeys[--$rowNum]; + + return $arrayValues[$rowNum][$columnNum]; + } // function INDEX() + + + /** + * TRANSPOSE + * + * @param array $matrixData A matrix of values + * @return array + * + * Unlike the Excel TRANSPOSE function, which will only work on a single row or column, this function will transpose a full matrix. + */ + public static function TRANSPOSE($matrixData) { + $returnMatrix = array(); + if (!is_array($matrixData)) { $matrixData = array(array($matrixData)); } + + $column = 0; + foreach($matrixData as $matrixRow) { + $row = 0; + foreach($matrixRow as $matrixCell) { + $returnMatrix[$row][$column] = $matrixCell; + ++$row; + } + ++$column; + } + return $returnMatrix; + } // function TRANSPOSE() + + + private static function _vlookupSort($a,$b) { + $f = array_keys($a); + $firstColumn = array_shift($f); + if (strtolower($a[$firstColumn]) == strtolower($b[$firstColumn])) { + return 0; + } + return (strtolower($a[$firstColumn]) < strtolower($b[$firstColumn])) ? -1 : 1; + } // function _vlookupSort() + + + /** + * VLOOKUP + * The VLOOKUP function searches for value in the left-most column of lookup_array and returns the value in the same row based on the index_number. + * @param lookup_value The value that you want to match in lookup_array + * @param lookup_array The range of cells being searched + * @param index_number The column number in table_array from which the matching value must be returned. The first column is 1. + * @param not_exact_match Determines if you are looking for an exact match based on lookup_value. + * @return mixed The value of the found cell + */ + public static function VLOOKUP($lookup_value, $lookup_array, $index_number, $not_exact_match=true) { + $lookup_value = PHPExcel_Calculation_Functions::flattenSingleValue($lookup_value); + $index_number = PHPExcel_Calculation_Functions::flattenSingleValue($index_number); + $not_exact_match = PHPExcel_Calculation_Functions::flattenSingleValue($not_exact_match); + + // index_number must be greater than or equal to 1 + if ($index_number < 1) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + // index_number must be less than or equal to the number of columns in lookup_array + if ((!is_array($lookup_array)) || (empty($lookup_array))) { + return PHPExcel_Calculation_Functions::REF(); + } else { + $f = array_keys($lookup_array); + $firstRow = array_pop($f); + if ((!is_array($lookup_array[$firstRow])) || ($index_number > count($lookup_array[$firstRow]))) { + return PHPExcel_Calculation_Functions::REF(); + } else { + $columnKeys = array_keys($lookup_array[$firstRow]); + $returnColumn = $columnKeys[--$index_number]; + $firstColumn = array_shift($columnKeys); + } + } + + if (!$not_exact_match) { + uasort($lookup_array,array('self','_vlookupSort')); + } + + $rowNumber = $rowValue = False; + foreach($lookup_array as $rowKey => $rowData) { + if (strtolower($rowData[$firstColumn]) > strtolower($lookup_value)) { + break; + } + $rowNumber = $rowKey; + $rowValue = $rowData[$firstColumn]; + } + + if ($rowNumber !== false) { + if ((!$not_exact_match) && ($rowValue != $lookup_value)) { + // if an exact match is required, we have what we need to return an appropriate response + return PHPExcel_Calculation_Functions::NA(); + } else { + // otherwise return the appropriate value + return $lookup_array[$rowNumber][$returnColumn]; + } + } + + return PHPExcel_Calculation_Functions::NA(); + } // function VLOOKUP() + + + /** + * LOOKUP + * The LOOKUP function searches for value either from a one-row or one-column range or from an array. + * @param lookup_value The value that you want to match in lookup_array + * @param lookup_vector The range of cells being searched + * @param result_vector The column from which the matching value must be returned + * @return mixed The value of the found cell + */ + public static function LOOKUP($lookup_value, $lookup_vector, $result_vector=null) { + $lookup_value = PHPExcel_Calculation_Functions::flattenSingleValue($lookup_value); + + if (!is_array($lookup_vector)) { + return PHPExcel_Calculation_Functions::NA(); + } + $lookupRows = count($lookup_vector); + $l = array_keys($lookup_vector); + $l = array_shift($l); + $lookupColumns = count($lookup_vector[$l]); + if ((($lookupRows == 1) && ($lookupColumns > 1)) || (($lookupRows == 2) && ($lookupColumns != 2))) { + $lookup_vector = self::TRANSPOSE($lookup_vector); + $lookupRows = count($lookup_vector); + $l = array_keys($lookup_vector); + $lookupColumns = count($lookup_vector[array_shift($l)]); + } + + if (is_null($result_vector)) { + $result_vector = $lookup_vector; + } + $resultRows = count($result_vector); + $l = array_keys($result_vector); + $l = array_shift($l); + $resultColumns = count($result_vector[$l]); + if ((($resultRows == 1) && ($resultColumns > 1)) || (($resultRows == 2) && ($resultColumns != 2))) { + $result_vector = self::TRANSPOSE($result_vector); + $resultRows = count($result_vector); + $r = array_keys($result_vector); + $resultColumns = count($result_vector[array_shift($r)]); + } + + if ($lookupRows == 2) { + $result_vector = array_pop($lookup_vector); + $lookup_vector = array_shift($lookup_vector); + } + if ($lookupColumns != 2) { + foreach($lookup_vector as &$value) { + if (is_array($value)) { + $k = array_keys($value); + $key1 = $key2 = array_shift($k); + $key2++; + $dataValue1 = $value[$key1]; + } else { + $key1 = 0; + $key2 = 1; + $dataValue1 = $value; + } + $dataValue2 = array_shift($result_vector); + if (is_array($dataValue2)) { + $dataValue2 = array_shift($dataValue2); + } + $value = array($key1 => $dataValue1, $key2 => $dataValue2); + } + unset($value); + } + + return self::VLOOKUP($lookup_value,$lookup_vector,2); + } // function LOOKUP() + +} // class PHPExcel_Calculation_LookupRef diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/MathTrig.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/MathTrig.php new file mode 100755 index 0000000..0e2ac95 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/MathTrig.php @@ -0,0 +1,1369 @@ + 1; --$i) { + if (($value % $i) == 0) { + $factorArray = array_merge($factorArray,self::_factors($value / $i)); + $factorArray = array_merge($factorArray,self::_factors($i)); + if ($i <= sqrt($value)) { + break; + } + } + } + if (!empty($factorArray)) { + rsort($factorArray); + return $factorArray; + } else { + return array((integer) $value); + } + } // function _factors() + + + private static function _romanCut($num, $n) { + return ($num - ($num % $n ) ) / $n; + } // function _romanCut() + + + /** + * ATAN2 + * + * This function calculates the arc tangent of the two variables x and y. It is similar to + * calculating the arc tangent of y ÷ x, except that the signs of both arguments are used + * to determine the quadrant of the result. + * The arctangent is the angle from the x-axis to a line containing the origin (0, 0) and a + * point with coordinates (xCoordinate, yCoordinate). The angle is given in radians between + * -pi and pi, excluding -pi. + * + * Note that the Excel ATAN2() function accepts its arguments in the reverse order to the standard + * PHP atan2() function, so we need to reverse them here before calling the PHP atan() function. + * + * Excel Function: + * ATAN2(xCoordinate,yCoordinate) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param float $xCoordinate The x-coordinate of the point. + * @param float $yCoordinate The y-coordinate of the point. + * @return float The inverse tangent of the specified x- and y-coordinates. + */ + public static function ATAN2($xCoordinate = NULL, $yCoordinate = NULL) { + $xCoordinate = PHPExcel_Calculation_Functions::flattenSingleValue($xCoordinate); + $yCoordinate = PHPExcel_Calculation_Functions::flattenSingleValue($yCoordinate); + + $xCoordinate = ($xCoordinate !== NULL) ? $xCoordinate : 0.0; + $yCoordinate = ($yCoordinate !== NULL) ? $yCoordinate : 0.0; + + if (((is_numeric($xCoordinate)) || (is_bool($xCoordinate))) && + ((is_numeric($yCoordinate))) || (is_bool($yCoordinate))) { + $xCoordinate = (float) $xCoordinate; + $yCoordinate = (float) $yCoordinate; + + if (($xCoordinate == 0) && ($yCoordinate == 0)) { + return PHPExcel_Calculation_Functions::DIV0(); + } + + return atan2($yCoordinate, $xCoordinate); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function ATAN2() + + + /** + * CEILING + * + * Returns number rounded up, away from zero, to the nearest multiple of significance. + * For example, if you want to avoid using pennies in your prices and your product is + * priced at $4.42, use the formula =CEILING(4.42,0.05) to round prices up to the + * nearest nickel. + * + * Excel Function: + * CEILING(number[,significance]) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param float $number The number you want to round. + * @param float $significance The multiple to which you want to round. + * @return float Rounded Number + */ + public static function CEILING($number, $significance = NULL) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + $significance = PHPExcel_Calculation_Functions::flattenSingleValue($significance); + + if ((is_null($significance)) && + (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC)) { + $significance = $number/abs($number); + } + + if ((is_numeric($number)) && (is_numeric($significance))) { + if ($significance == 0.0) { + return 0.0; + } elseif (self::SIGN($number) == self::SIGN($significance)) { + return ceil($number / $significance) * $significance; + } else { + return PHPExcel_Calculation_Functions::NaN(); + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function CEILING() + + + /** + * COMBIN + * + * Returns the number of combinations for a given number of items. Use COMBIN to + * determine the total possible number of groups for a given number of items. + * + * Excel Function: + * COMBIN(numObjs,numInSet) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param int $numObjs Number of different objects + * @param int $numInSet Number of objects in each combination + * @return int Number of combinations + */ + public static function COMBIN($numObjs, $numInSet) { + $numObjs = PHPExcel_Calculation_Functions::flattenSingleValue($numObjs); + $numInSet = PHPExcel_Calculation_Functions::flattenSingleValue($numInSet); + + if ((is_numeric($numObjs)) && (is_numeric($numInSet))) { + if ($numObjs < $numInSet) { + return PHPExcel_Calculation_Functions::NaN(); + } elseif ($numInSet < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + return round(self::FACT($numObjs) / self::FACT($numObjs - $numInSet)) / self::FACT($numInSet); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function COMBIN() + + + /** + * EVEN + * + * Returns number rounded up to the nearest even integer. + * You can use this function for processing items that come in twos. For example, + * a packing crate accepts rows of one or two items. The crate is full when + * the number of items, rounded up to the nearest two, matches the crate's + * capacity. + * + * Excel Function: + * EVEN(number) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param float $number Number to round + * @return int Rounded Number + */ + public static function EVEN($number) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + + if (is_null($number)) { + return 0; + } elseif (is_bool($number)) { + $number = (int) $number; + } + + if (is_numeric($number)) { + $significance = 2 * self::SIGN($number); + return (int) self::CEILING($number,$significance); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function EVEN() + + + /** + * FACT + * + * Returns the factorial of a number. + * The factorial of a number is equal to 1*2*3*...* number. + * + * Excel Function: + * FACT(factVal) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param float $factVal Factorial Value + * @return int Factorial + */ + public static function FACT($factVal) { + $factVal = PHPExcel_Calculation_Functions::flattenSingleValue($factVal); + + if (is_numeric($factVal)) { + if ($factVal < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + $factLoop = floor($factVal); + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) { + if ($factVal > $factLoop) { + return PHPExcel_Calculation_Functions::NaN(); + } + } + + $factorial = 1; + while ($factLoop > 1) { + $factorial *= $factLoop--; + } + return $factorial ; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function FACT() + + + /** + * FACTDOUBLE + * + * Returns the double factorial of a number. + * + * Excel Function: + * FACTDOUBLE(factVal) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param float $factVal Factorial Value + * @return int Double Factorial + */ + public static function FACTDOUBLE($factVal) { + $factLoop = PHPExcel_Calculation_Functions::flattenSingleValue($factVal); + + if (is_numeric($factLoop)) { + $factLoop = floor($factLoop); + if ($factVal < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + $factorial = 1; + while ($factLoop > 1) { + $factorial *= $factLoop--; + --$factLoop; + } + return $factorial ; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function FACTDOUBLE() + + + /** + * FLOOR + * + * Rounds number down, toward zero, to the nearest multiple of significance. + * + * Excel Function: + * FLOOR(number[,significance]) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param float $number Number to round + * @param float $significance Significance + * @return float Rounded Number + */ + public static function FLOOR($number, $significance = NULL) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + $significance = PHPExcel_Calculation_Functions::flattenSingleValue($significance); + + if ((is_null($significance)) && (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC)) { + $significance = $number/abs($number); + } + + if ((is_numeric($number)) && (is_numeric($significance))) { + if ((float) $significance == 0.0) { + return PHPExcel_Calculation_Functions::DIV0(); + } + if (self::SIGN($number) == self::SIGN($significance)) { + return floor($number / $significance) * $significance; + } else { + return PHPExcel_Calculation_Functions::NaN(); + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function FLOOR() + + + /** + * GCD + * + * Returns the greatest common divisor of a series of numbers. + * The greatest common divisor is the largest integer that divides both + * number1 and number2 without a remainder. + * + * Excel Function: + * GCD(number1[,number2[, ...]]) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @return integer Greatest Common Divisor + */ + public static function GCD() { + $returnValue = 1; + $allValuesFactors = array(); + // Loop through arguments + foreach(PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $value) { + if (!is_numeric($value)) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif ($value == 0) { + continue; + } elseif($value < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + $myFactors = self::_factors($value); + $myCountedFactors = array_count_values($myFactors); + $allValuesFactors[] = $myCountedFactors; + } + $allValuesCount = count($allValuesFactors); + if ($allValuesCount == 0) { + return 0; + } + + $mergedArray = $allValuesFactors[0]; + for ($i=1;$i < $allValuesCount; ++$i) { + $mergedArray = array_intersect_key($mergedArray,$allValuesFactors[$i]); + } + $mergedArrayValues = count($mergedArray); + if ($mergedArrayValues == 0) { + return $returnValue; + } elseif ($mergedArrayValues > 1) { + foreach($mergedArray as $mergedKey => $mergedValue) { + foreach($allValuesFactors as $highestPowerTest) { + foreach($highestPowerTest as $testKey => $testValue) { + if (($testKey == $mergedKey) && ($testValue < $mergedValue)) { + $mergedArray[$mergedKey] = $testValue; + $mergedValue = $testValue; + } + } + } + } + + $returnValue = 1; + foreach($mergedArray as $key => $value) { + $returnValue *= pow($key,$value); + } + return $returnValue; + } else { + $keys = array_keys($mergedArray); + $key = $keys[0]; + $value = $mergedArray[$key]; + foreach($allValuesFactors as $testValue) { + foreach($testValue as $mergedKey => $mergedValue) { + if (($mergedKey == $key) && ($mergedValue < $value)) { + $value = $mergedValue; + } + } + } + return pow($key,$value); + } + } // function GCD() + + + /** + * INT + * + * Casts a floating point value to an integer + * + * Excel Function: + * INT(number) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param float $number Number to cast to an integer + * @return integer Integer value + */ + public static function INT($number) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + + if (is_null($number)) { + return 0; + } elseif (is_bool($number)) { + return (int) $number; + } + if (is_numeric($number)) { + return (int) floor($number); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function INT() + + + /** + * LCM + * + * Returns the lowest common multiplier of a series of numbers + * The least common multiple is the smallest positive integer that is a multiple + * of all integer arguments number1, number2, and so on. Use LCM to add fractions + * with different denominators. + * + * Excel Function: + * LCM(number1[,number2[, ...]]) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @return int Lowest Common Multiplier + */ + public static function LCM() { + $returnValue = 1; + $allPoweredFactors = array(); + // Loop through arguments + foreach(PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $value) { + if (!is_numeric($value)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if ($value == 0) { + return 0; + } elseif ($value < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + $myFactors = self::_factors(floor($value)); + $myCountedFactors = array_count_values($myFactors); + $myPoweredFactors = array(); + foreach($myCountedFactors as $myCountedFactor => $myCountedPower) { + $myPoweredFactors[$myCountedFactor] = pow($myCountedFactor,$myCountedPower); + } + foreach($myPoweredFactors as $myPoweredValue => $myPoweredFactor) { + if (array_key_exists($myPoweredValue,$allPoweredFactors)) { + if ($allPoweredFactors[$myPoweredValue] < $myPoweredFactor) { + $allPoweredFactors[$myPoweredValue] = $myPoweredFactor; + } + } else { + $allPoweredFactors[$myPoweredValue] = $myPoweredFactor; + } + } + } + foreach($allPoweredFactors as $allPoweredFactor) { + $returnValue *= (integer) $allPoweredFactor; + } + return $returnValue; + } // function LCM() + + + /** + * LOG_BASE + * + * Returns the logarithm of a number to a specified base. The default base is 10. + * + * Excel Function: + * LOG(number[,base]) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param float $number The positive real number for which you want the logarithm + * @param float $base The base of the logarithm. If base is omitted, it is assumed to be 10. + * @return float + */ + public static function LOG_BASE($number = NULL, $base = 10) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + $base = (is_null($base)) ? 10 : (float) PHPExcel_Calculation_Functions::flattenSingleValue($base); + + if ((!is_numeric($base)) || (!is_numeric($number))) + return PHPExcel_Calculation_Functions::VALUE(); + if (($base <= 0) || ($number <= 0)) + return PHPExcel_Calculation_Functions::NaN(); + return log($number, $base); + } // function LOG_BASE() + + + /** + * MDETERM + * + * Returns the matrix determinant of an array. + * + * Excel Function: + * MDETERM(array) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param array $matrixValues A matrix of values + * @return float + */ + public static function MDETERM($matrixValues) { + $matrixData = array(); + if (!is_array($matrixValues)) { $matrixValues = array(array($matrixValues)); } + + $row = $maxColumn = 0; + foreach($matrixValues as $matrixRow) { + if (!is_array($matrixRow)) { $matrixRow = array($matrixRow); } + $column = 0; + foreach($matrixRow as $matrixCell) { + if ((is_string($matrixCell)) || ($matrixCell === null)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $matrixData[$column][$row] = $matrixCell; + ++$column; + } + if ($column > $maxColumn) { $maxColumn = $column; } + ++$row; + } + if ($row != $maxColumn) { return PHPExcel_Calculation_Functions::VALUE(); } + + try { + $matrix = new PHPExcel_Shared_JAMA_Matrix($matrixData); + return $matrix->det(); + } catch (PHPExcel_Exception $ex) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } // function MDETERM() + + + /** + * MINVERSE + * + * Returns the inverse matrix for the matrix stored in an array. + * + * Excel Function: + * MINVERSE(array) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param array $matrixValues A matrix of values + * @return array + */ + public static function MINVERSE($matrixValues) { + $matrixData = array(); + if (!is_array($matrixValues)) { $matrixValues = array(array($matrixValues)); } + + $row = $maxColumn = 0; + foreach($matrixValues as $matrixRow) { + if (!is_array($matrixRow)) { $matrixRow = array($matrixRow); } + $column = 0; + foreach($matrixRow as $matrixCell) { + if ((is_string($matrixCell)) || ($matrixCell === null)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $matrixData[$column][$row] = $matrixCell; + ++$column; + } + if ($column > $maxColumn) { $maxColumn = $column; } + ++$row; + } + if ($row != $maxColumn) { return PHPExcel_Calculation_Functions::VALUE(); } + + try { + $matrix = new PHPExcel_Shared_JAMA_Matrix($matrixData); + return $matrix->inverse()->getArray(); + } catch (PHPExcel_Exception $ex) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } // function MINVERSE() + + + /** + * MMULT + * + * @param array $matrixData1 A matrix of values + * @param array $matrixData2 A matrix of values + * @return array + */ + public static function MMULT($matrixData1,$matrixData2) { + $matrixAData = $matrixBData = array(); + if (!is_array($matrixData1)) { $matrixData1 = array(array($matrixData1)); } + if (!is_array($matrixData2)) { $matrixData2 = array(array($matrixData2)); } + + $rowA = 0; + foreach($matrixData1 as $matrixRow) { + if (!is_array($matrixRow)) { $matrixRow = array($matrixRow); } + $columnA = 0; + foreach($matrixRow as $matrixCell) { + if ((is_string($matrixCell)) || ($matrixCell === null)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $matrixAData[$rowA][$columnA] = $matrixCell; + ++$columnA; + } + ++$rowA; + } + try { + $matrixA = new PHPExcel_Shared_JAMA_Matrix($matrixAData); + $rowB = 0; + foreach($matrixData2 as $matrixRow) { + if (!is_array($matrixRow)) { $matrixRow = array($matrixRow); } + $columnB = 0; + foreach($matrixRow as $matrixCell) { + if ((is_string($matrixCell)) || ($matrixCell === null)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $matrixBData[$rowB][$columnB] = $matrixCell; + ++$columnB; + } + ++$rowB; + } + $matrixB = new PHPExcel_Shared_JAMA_Matrix($matrixBData); + + if (($rowA != $columnB) || ($rowB != $columnA)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + return $matrixA->times($matrixB)->getArray(); + } catch (PHPExcel_Exception $ex) { + return PHPExcel_Calculation_Functions::VALUE(); + } + } // function MMULT() + + + /** + * MOD + * + * @param int $a Dividend + * @param int $b Divisor + * @return int Remainder + */ + public static function MOD($a = 1, $b = 1) { + $a = PHPExcel_Calculation_Functions::flattenSingleValue($a); + $b = PHPExcel_Calculation_Functions::flattenSingleValue($b); + + if ($b == 0.0) { + return PHPExcel_Calculation_Functions::DIV0(); + } elseif (($a < 0.0) && ($b > 0.0)) { + return $b - fmod(abs($a),$b); + } elseif (($a > 0.0) && ($b < 0.0)) { + return $b + fmod($a,abs($b)); + } + + return fmod($a,$b); + } // function MOD() + + + /** + * MROUND + * + * Rounds a number to the nearest multiple of a specified value + * + * @param float $number Number to round + * @param int $multiple Multiple to which you want to round $number + * @return float Rounded Number + */ + public static function MROUND($number,$multiple) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + $multiple = PHPExcel_Calculation_Functions::flattenSingleValue($multiple); + + if ((is_numeric($number)) && (is_numeric($multiple))) { + if ($multiple == 0) { + return 0; + } + if ((self::SIGN($number)) == (self::SIGN($multiple))) { + $multiplier = 1 / $multiple; + return round($number * $multiplier) / $multiplier; + } + return PHPExcel_Calculation_Functions::NaN(); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function MROUND() + + + /** + * MULTINOMIAL + * + * Returns the ratio of the factorial of a sum of values to the product of factorials. + * + * @param array of mixed Data Series + * @return float + */ + public static function MULTINOMIAL() { + $summer = 0; + $divisor = 1; + // Loop through arguments + foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) { + // Is it a numeric value? + if (is_numeric($arg)) { + if ($arg < 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + $summer += floor($arg); + $divisor *= self::FACT($arg); + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + + // Return + if ($summer > 0) { + $summer = self::FACT($summer); + return $summer / $divisor; + } + return 0; + } // function MULTINOMIAL() + + + /** + * ODD + * + * Returns number rounded up to the nearest odd integer. + * + * @param float $number Number to round + * @return int Rounded Number + */ + public static function ODD($number) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + + if (is_null($number)) { + return 1; + } elseif (is_bool($number)) { + $number = (int) $number; + } + + if (is_numeric($number)) { + $significance = self::SIGN($number); + if ($significance == 0) { + return 1; + } + + $result = self::CEILING($number,$significance); + if ($result == self::EVEN($result)) { + $result += $significance; + } + + return (int) $result; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function ODD() + + + /** + * POWER + * + * Computes x raised to the power y. + * + * @param float $x + * @param float $y + * @return float + */ + public static function POWER($x = 0, $y = 2) { + $x = PHPExcel_Calculation_Functions::flattenSingleValue($x); + $y = PHPExcel_Calculation_Functions::flattenSingleValue($y); + + // Validate parameters + if ($x == 0.0 && $y == 0.0) { + return PHPExcel_Calculation_Functions::NaN(); + } elseif ($x == 0.0 && $y < 0.0) { + return PHPExcel_Calculation_Functions::DIV0(); + } + + // Return + $result = pow($x, $y); + return (!is_nan($result) && !is_infinite($result)) ? $result : PHPExcel_Calculation_Functions::NaN(); + } // function POWER() + + + /** + * PRODUCT + * + * PRODUCT returns the product of all the values and cells referenced in the argument list. + * + * Excel Function: + * PRODUCT(value1[,value2[, ...]]) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function PRODUCT() { + // Return value + $returnValue = null; + + // Loop through arguments + foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + if (is_null($returnValue)) { + $returnValue = $arg; + } else { + $returnValue *= $arg; + } + } + } + + // Return + if (is_null($returnValue)) { + return 0; + } + return $returnValue; + } // function PRODUCT() + + + /** + * QUOTIENT + * + * QUOTIENT function returns the integer portion of a division. Numerator is the divided number + * and denominator is the divisor. + * + * Excel Function: + * QUOTIENT(value1[,value2[, ...]]) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function QUOTIENT() { + // Return value + $returnValue = null; + + // Loop through arguments + foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + if (is_null($returnValue)) { + $returnValue = ($arg == 0) ? 0 : $arg; + } else { + if (($returnValue == 0) || ($arg == 0)) { + $returnValue = 0; + } else { + $returnValue /= $arg; + } + } + } + } + + // Return + return intval($returnValue); + } // function QUOTIENT() + + + /** + * RAND + * + * @param int $min Minimal value + * @param int $max Maximal value + * @return int Random number + */ + public static function RAND($min = 0, $max = 0) { + $min = PHPExcel_Calculation_Functions::flattenSingleValue($min); + $max = PHPExcel_Calculation_Functions::flattenSingleValue($max); + + if ($min == 0 && $max == 0) { + return (rand(0,10000000)) / 10000000; + } else { + return rand($min, $max); + } + } // function RAND() + + + public static function ROMAN($aValue, $style=0) { + $aValue = PHPExcel_Calculation_Functions::flattenSingleValue($aValue); + $style = (is_null($style)) ? 0 : (integer) PHPExcel_Calculation_Functions::flattenSingleValue($style); + if ((!is_numeric($aValue)) || ($aValue < 0) || ($aValue >= 4000)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $aValue = (integer) $aValue; + if ($aValue == 0) { + return ''; + } + + $mill = Array('', 'M', 'MM', 'MMM', 'MMMM', 'MMMMM'); + $cent = Array('', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM'); + $tens = Array('', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC'); + $ones = Array('', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'); + + $roman = ''; + while ($aValue > 5999) { + $roman .= 'M'; + $aValue -= 1000; + } + $m = self::_romanCut($aValue, 1000); $aValue %= 1000; + $c = self::_romanCut($aValue, 100); $aValue %= 100; + $t = self::_romanCut($aValue, 10); $aValue %= 10; + + return $roman.$mill[$m].$cent[$c].$tens[$t].$ones[$aValue]; + } // function ROMAN() + + + /** + * ROUNDUP + * + * Rounds a number up to a specified number of decimal places + * + * @param float $number Number to round + * @param int $digits Number of digits to which you want to round $number + * @return float Rounded Number + */ + public static function ROUNDUP($number,$digits) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + $digits = PHPExcel_Calculation_Functions::flattenSingleValue($digits); + + if ((is_numeric($number)) && (is_numeric($digits))) { + $significance = pow(10,(int) $digits); + if ($number < 0.0) { + return floor($number * $significance) / $significance; + } else { + return ceil($number * $significance) / $significance; + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function ROUNDUP() + + + /** + * ROUNDDOWN + * + * Rounds a number down to a specified number of decimal places + * + * @param float $number Number to round + * @param int $digits Number of digits to which you want to round $number + * @return float Rounded Number + */ + public static function ROUNDDOWN($number,$digits) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + $digits = PHPExcel_Calculation_Functions::flattenSingleValue($digits); + + if ((is_numeric($number)) && (is_numeric($digits))) { + $significance = pow(10,(int) $digits); + if ($number < 0.0) { + return ceil($number * $significance) / $significance; + } else { + return floor($number * $significance) / $significance; + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function ROUNDDOWN() + + + /** + * SERIESSUM + * + * Returns the sum of a power series + * + * @param float $x Input value to the power series + * @param float $n Initial power to which you want to raise $x + * @param float $m Step by which to increase $n for each term in the series + * @param array of mixed Data Series + * @return float + */ + public static function SERIESSUM() { + // Return value + $returnValue = 0; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + + $x = array_shift($aArgs); + $n = array_shift($aArgs); + $m = array_shift($aArgs); + + if ((is_numeric($x)) && (is_numeric($n)) && (is_numeric($m))) { + // Calculate + $i = 0; + foreach($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $returnValue += $arg * pow($x,$n + ($m * $i++)); + } else { + return PHPExcel_Calculation_Functions::VALUE(); + } + } + // Return + return $returnValue; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function SERIESSUM() + + + /** + * SIGN + * + * Determines the sign of a number. Returns 1 if the number is positive, zero (0) + * if the number is 0, and -1 if the number is negative. + * + * @param float $number Number to round + * @return int sign value + */ + public static function SIGN($number) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + + if (is_bool($number)) + return (int) $number; + if (is_numeric($number)) { + if ($number == 0.0) { + return 0; + } + return $number / abs($number); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function SIGN() + + + /** + * SQRTPI + * + * Returns the square root of (number * pi). + * + * @param float $number Number + * @return float Square Root of Number * Pi + */ + public static function SQRTPI($number) { + $number = PHPExcel_Calculation_Functions::flattenSingleValue($number); + + if (is_numeric($number)) { + if ($number < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + return sqrt($number * M_PI) ; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function SQRTPI() + + + /** + * SUBTOTAL + * + * Returns a subtotal in a list or database. + * + * @param int the number 1 to 11 that specifies which function to + * use in calculating subtotals within a list. + * @param array of mixed Data Series + * @return float + */ + public static function SUBTOTAL() { + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + + // Calculate + $subtotal = array_shift($aArgs); + + if ((is_numeric($subtotal)) && (!is_string($subtotal))) { + switch($subtotal) { + case 1 : + return PHPExcel_Calculation_Statistical::AVERAGE($aArgs); + break; + case 2 : + return PHPExcel_Calculation_Statistical::COUNT($aArgs); + break; + case 3 : + return PHPExcel_Calculation_Statistical::COUNTA($aArgs); + break; + case 4 : + return PHPExcel_Calculation_Statistical::MAX($aArgs); + break; + case 5 : + return PHPExcel_Calculation_Statistical::MIN($aArgs); + break; + case 6 : + return self::PRODUCT($aArgs); + break; + case 7 : + return PHPExcel_Calculation_Statistical::STDEV($aArgs); + break; + case 8 : + return PHPExcel_Calculation_Statistical::STDEVP($aArgs); + break; + case 9 : + return self::SUM($aArgs); + break; + case 10 : + return PHPExcel_Calculation_Statistical::VARFunc($aArgs); + break; + case 11 : + return PHPExcel_Calculation_Statistical::VARP($aArgs); + break; + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function SUBTOTAL() + + + /** + * SUM + * + * SUM computes the sum of all the values and cells referenced in the argument list. + * + * Excel Function: + * SUM(value1[,value2[, ...]]) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function SUM() { + // Return value + $returnValue = 0; + + // Loop through the arguments + foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $returnValue += $arg; + } + } + + // Return + return $returnValue; + } // function SUM() + + + /** + * SUMIF + * + * Counts the number of cells that contain numbers within the list of arguments + * + * Excel Function: + * SUMIF(value1[,value2[, ...]],condition) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @param string $condition The criteria that defines which cells will be summed. + * @return float + */ + public static function SUMIF($aArgs,$condition,$sumArgs = array()) { + // Return value + $returnValue = 0; + + $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs); + $sumArgs = PHPExcel_Calculation_Functions::flattenArray($sumArgs); + if (empty($sumArgs)) { + $sumArgs = $aArgs; + } + $condition = PHPExcel_Calculation_Functions::_ifCondition($condition); + // Loop through arguments + foreach ($aArgs as $key => $arg) { + if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } + $testCondition = '='.$arg.$condition; + if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { + // Is it a value within our criteria + $returnValue += $sumArgs[$key]; + } + } + + // Return + return $returnValue; + } // function SUMIF() + + + /** + * SUMPRODUCT + * + * Excel Function: + * SUMPRODUCT(value1[,value2[, ...]]) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function SUMPRODUCT() { + $arrayList = func_get_args(); + + $wrkArray = PHPExcel_Calculation_Functions::flattenArray(array_shift($arrayList)); + $wrkCellCount = count($wrkArray); + + for ($i=0; $i< $wrkCellCount; ++$i) { + if ((!is_numeric($wrkArray[$i])) || (is_string($wrkArray[$i]))) { + $wrkArray[$i] = 0; + } + } + + foreach($arrayList as $matrixData) { + $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData); + $count = count($array2); + if ($wrkCellCount != $count) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + foreach ($array2 as $i => $val) { + if ((!is_numeric($val)) || (is_string($val))) { + $val = 0; + } + $wrkArray[$i] *= $val; + } + } + + return array_sum($wrkArray); + } // function SUMPRODUCT() + + + /** + * SUMSQ + * + * SUMSQ returns the sum of the squares of the arguments + * + * Excel Function: + * SUMSQ(value1[,value2[, ...]]) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function SUMSQ() { + // Return value + $returnValue = 0; + + // Loop through arguments + foreach (PHPExcel_Calculation_Functions::flattenArray(func_get_args()) as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $returnValue += ($arg * $arg); + } + } + + // Return + return $returnValue; + } // function SUMSQ() + + + /** + * SUMX2MY2 + * + * @param mixed[] $matrixData1 Matrix #1 + * @param mixed[] $matrixData2 Matrix #2 + * @return float + */ + public static function SUMX2MY2($matrixData1,$matrixData2) { + $array1 = PHPExcel_Calculation_Functions::flattenArray($matrixData1); + $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData2); + $count1 = count($array1); + $count2 = count($array2); + if ($count1 < $count2) { + $count = $count1; + } else { + $count = $count2; + } + + $result = 0; + for ($i = 0; $i < $count; ++$i) { + if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) && + ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) { + $result += ($array1[$i] * $array1[$i]) - ($array2[$i] * $array2[$i]); + } + } + + return $result; + } // function SUMX2MY2() + + + /** + * SUMX2PY2 + * + * @param mixed[] $matrixData1 Matrix #1 + * @param mixed[] $matrixData2 Matrix #2 + * @return float + */ + public static function SUMX2PY2($matrixData1,$matrixData2) { + $array1 = PHPExcel_Calculation_Functions::flattenArray($matrixData1); + $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData2); + $count1 = count($array1); + $count2 = count($array2); + if ($count1 < $count2) { + $count = $count1; + } else { + $count = $count2; + } + + $result = 0; + for ($i = 0; $i < $count; ++$i) { + if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) && + ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) { + $result += ($array1[$i] * $array1[$i]) + ($array2[$i] * $array2[$i]); + } + } + + return $result; + } // function SUMX2PY2() + + + /** + * SUMXMY2 + * + * @param mixed[] $matrixData1 Matrix #1 + * @param mixed[] $matrixData2 Matrix #2 + * @return float + */ + public static function SUMXMY2($matrixData1,$matrixData2) { + $array1 = PHPExcel_Calculation_Functions::flattenArray($matrixData1); + $array2 = PHPExcel_Calculation_Functions::flattenArray($matrixData2); + $count1 = count($array1); + $count2 = count($array2); + if ($count1 < $count2) { + $count = $count1; + } else { + $count = $count2; + } + + $result = 0; + for ($i = 0; $i < $count; ++$i) { + if (((is_numeric($array1[$i])) && (!is_string($array1[$i]))) && + ((is_numeric($array2[$i])) && (!is_string($array2[$i])))) { + $result += ($array1[$i] - $array2[$i]) * ($array1[$i] - $array2[$i]); + } + } + + return $result; + } // function SUMXMY2() + + + /** + * TRUNC + * + * Truncates value to the number of fractional digits by number_digits. + * + * @param float $value + * @param int $digits + * @return float Truncated value + */ + public static function TRUNC($value = 0, $digits = 0) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $digits = PHPExcel_Calculation_Functions::flattenSingleValue($digits); + + // Validate parameters + if ((!is_numeric($value)) || (!is_numeric($digits))) + return PHPExcel_Calculation_Functions::VALUE(); + $digits = floor($digits); + + // Truncate + $adjust = pow(10, $digits); + + if (($digits > 0) && (rtrim(intval((abs($value) - abs(intval($value))) * $adjust),'0') < $adjust/10)) + return $value; + + return (intval($value * $adjust)) / $adjust; + } // function TRUNC() + +} // class PHPExcel_Calculation_MathTrig diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Statistical.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Statistical.php new file mode 100755 index 0000000..4f6d28a --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Statistical.php @@ -0,0 +1,3651 @@ + $value) { + if ((is_bool($value)) || (is_string($value)) || (is_null($value))) { + unset($array1[$key]); + unset($array2[$key]); + } + } + foreach($array2 as $key => $value) { + if ((is_bool($value)) || (is_string($value)) || (is_null($value))) { + unset($array1[$key]); + unset($array2[$key]); + } + } + $array1 = array_merge($array1); + $array2 = array_merge($array2); + + return True; + } // function _checkTrendArrays() + + + /** + * Beta function. + * + * @author Jaco van Kooten + * + * @param p require p>0 + * @param q require q>0 + * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow + */ + private static function _beta($p, $q) { + if ($p <= 0.0 || $q <= 0.0 || ($p + $q) > LOG_GAMMA_X_MAX_VALUE) { + return 0.0; + } else { + return exp(self::_logBeta($p, $q)); + } + } // function _beta() + + + /** + * Incomplete beta function + * + * @author Jaco van Kooten + * @author Paul Meagher + * + * The computation is based on formulas from Numerical Recipes, Chapter 6.4 (W.H. Press et al, 1992). + * @param x require 0<=x<=1 + * @param p require p>0 + * @param q require q>0 + * @return 0 if x<0, p<=0, q<=0 or p+q>2.55E305 and 1 if x>1 to avoid errors and over/underflow + */ + private static function _incompleteBeta($x, $p, $q) { + if ($x <= 0.0) { + return 0.0; + } elseif ($x >= 1.0) { + return 1.0; + } elseif (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) { + return 0.0; + } + $beta_gam = exp((0 - self::_logBeta($p, $q)) + $p * log($x) + $q * log(1.0 - $x)); + if ($x < ($p + 1.0) / ($p + $q + 2.0)) { + return $beta_gam * self::_betaFraction($x, $p, $q) / $p; + } else { + return 1.0 - ($beta_gam * self::_betaFraction(1 - $x, $q, $p) / $q); + } + } // function _incompleteBeta() + + + // Function cache for _logBeta function + private static $_logBetaCache_p = 0.0; + private static $_logBetaCache_q = 0.0; + private static $_logBetaCache_result = 0.0; + + /** + * The natural logarithm of the beta function. + * + * @param p require p>0 + * @param q require q>0 + * @return 0 if p<=0, q<=0 or p+q>2.55E305 to avoid errors and over/underflow + * @author Jaco van Kooten + */ + private static function _logBeta($p, $q) { + if ($p != self::$_logBetaCache_p || $q != self::$_logBetaCache_q) { + self::$_logBetaCache_p = $p; + self::$_logBetaCache_q = $q; + if (($p <= 0.0) || ($q <= 0.0) || (($p + $q) > LOG_GAMMA_X_MAX_VALUE)) { + self::$_logBetaCache_result = 0.0; + } else { + self::$_logBetaCache_result = self::_logGamma($p) + self::_logGamma($q) - self::_logGamma($p + $q); + } + } + return self::$_logBetaCache_result; + } // function _logBeta() + + + /** + * Evaluates of continued fraction part of incomplete beta function. + * Based on an idea from Numerical Recipes (W.H. Press et al, 1992). + * @author Jaco van Kooten + */ + private static function _betaFraction($x, $p, $q) { + $c = 1.0; + $sum_pq = $p + $q; + $p_plus = $p + 1.0; + $p_minus = $p - 1.0; + $h = 1.0 - $sum_pq * $x / $p_plus; + if (abs($h) < XMININ) { + $h = XMININ; + } + $h = 1.0 / $h; + $frac = $h; + $m = 1; + $delta = 0.0; + while ($m <= MAX_ITERATIONS && abs($delta-1.0) > PRECISION ) { + $m2 = 2 * $m; + // even index for d + $d = $m * ($q - $m) * $x / ( ($p_minus + $m2) * ($p + $m2)); + $h = 1.0 + $d * $h; + if (abs($h) < XMININ) { + $h = XMININ; + } + $h = 1.0 / $h; + $c = 1.0 + $d / $c; + if (abs($c) < XMININ) { + $c = XMININ; + } + $frac *= $h * $c; + // odd index for d + $d = -($p + $m) * ($sum_pq + $m) * $x / (($p + $m2) * ($p_plus + $m2)); + $h = 1.0 + $d * $h; + if (abs($h) < XMININ) { + $h = XMININ; + } + $h = 1.0 / $h; + $c = 1.0 + $d / $c; + if (abs($c) < XMININ) { + $c = XMININ; + } + $delta = $h * $c; + $frac *= $delta; + ++$m; + } + return $frac; + } // function _betaFraction() + + + /** + * logGamma function + * + * @version 1.1 + * @author Jaco van Kooten + * + * Original author was Jaco van Kooten. Ported to PHP by Paul Meagher. + * + * The natural logarithm of the gamma function.
    + * Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz
    + * Applied Mathematics Division
    + * Argonne National Laboratory
    + * Argonne, IL 60439
    + *

    + * References: + *

      + *
    1. W. J. Cody and K. E. Hillstrom, 'Chebyshev Approximations for the Natural + * Logarithm of the Gamma Function,' Math. Comp. 21, 1967, pp. 198-203.
    2. + *
    3. K. E. Hillstrom, ANL/AMD Program ANLC366S, DGAMMA/DLGAMA, May, 1969.
    4. + *
    5. Hart, Et. Al., Computer Approximations, Wiley and sons, New York, 1968.
    6. + *
    + *

    + *

    + * From the original documentation: + *

    + *

    + * This routine calculates the LOG(GAMMA) function for a positive real argument X. + * Computation is based on an algorithm outlined in references 1 and 2. + * The program uses rational functions that theoretically approximate LOG(GAMMA) + * to at least 18 significant decimal digits. The approximation for X > 12 is from + * reference 3, while approximations for X < 12.0 are similar to those in reference + * 1, but are unpublished. The accuracy achieved depends on the arithmetic system, + * the compiler, the intrinsic functions, and proper selection of the + * machine-dependent constants. + *

    + *

    + * Error returns:
    + * The program returns the value XINF for X .LE. 0.0 or when overflow would occur. + * The computation is believed to be free of underflow and overflow. + *

    + * @return MAX_VALUE for x < 0.0 or when overflow would occur, i.e. x > 2.55E305 + */ + + // Function cache for logGamma + private static $_logGammaCache_result = 0.0; + private static $_logGammaCache_x = 0.0; + + private static function _logGamma($x) { + // Log Gamma related constants + static $lg_d1 = -0.5772156649015328605195174; + static $lg_d2 = 0.4227843350984671393993777; + static $lg_d4 = 1.791759469228055000094023; + + static $lg_p1 = array( 4.945235359296727046734888, + 201.8112620856775083915565, + 2290.838373831346393026739, + 11319.67205903380828685045, + 28557.24635671635335736389, + 38484.96228443793359990269, + 26377.48787624195437963534, + 7225.813979700288197698961 ); + static $lg_p2 = array( 4.974607845568932035012064, + 542.4138599891070494101986, + 15506.93864978364947665077, + 184793.2904445632425417223, + 1088204.76946882876749847, + 3338152.967987029735917223, + 5106661.678927352456275255, + 3074109.054850539556250927 ); + static $lg_p4 = array( 14745.02166059939948905062, + 2426813.369486704502836312, + 121475557.4045093227939592, + 2663432449.630976949898078, + 29403789566.34553899906876, + 170266573776.5398868392998, + 492612579337.743088758812, + 560625185622.3951465078242 ); + + static $lg_q1 = array( 67.48212550303777196073036, + 1113.332393857199323513008, + 7738.757056935398733233834, + 27639.87074403340708898585, + 54993.10206226157329794414, + 61611.22180066002127833352, + 36351.27591501940507276287, + 8785.536302431013170870835 ); + static $lg_q2 = array( 183.0328399370592604055942, + 7765.049321445005871323047, + 133190.3827966074194402448, + 1136705.821321969608938755, + 5267964.117437946917577538, + 13467014.54311101692290052, + 17827365.30353274213975932, + 9533095.591844353613395747 ); + static $lg_q4 = array( 2690.530175870899333379843, + 639388.5654300092398984238, + 41355999.30241388052042842, + 1120872109.61614794137657, + 14886137286.78813811542398, + 101680358627.2438228077304, + 341747634550.7377132798597, + 446315818741.9713286462081 ); + + static $lg_c = array( -0.001910444077728, + 8.4171387781295e-4, + -5.952379913043012e-4, + 7.93650793500350248e-4, + -0.002777777777777681622553, + 0.08333333333333333331554247, + 0.0057083835261 ); + + // Rough estimate of the fourth root of logGamma_xBig + static $lg_frtbig = 2.25e76; + static $pnt68 = 0.6796875; + + + if ($x == self::$_logGammaCache_x) { + return self::$_logGammaCache_result; + } + $y = $x; + if ($y > 0.0 && $y <= LOG_GAMMA_X_MAX_VALUE) { + if ($y <= EPS) { + $res = -log(y); + } elseif ($y <= 1.5) { + // --------------------- + // EPS .LT. X .LE. 1.5 + // --------------------- + if ($y < $pnt68) { + $corr = -log($y); + $xm1 = $y; + } else { + $corr = 0.0; + $xm1 = $y - 1.0; + } + if ($y <= 0.5 || $y >= $pnt68) { + $xden = 1.0; + $xnum = 0.0; + for ($i = 0; $i < 8; ++$i) { + $xnum = $xnum * $xm1 + $lg_p1[$i]; + $xden = $xden * $xm1 + $lg_q1[$i]; + } + $res = $corr + $xm1 * ($lg_d1 + $xm1 * ($xnum / $xden)); + } else { + $xm2 = $y - 1.0; + $xden = 1.0; + $xnum = 0.0; + for ($i = 0; $i < 8; ++$i) { + $xnum = $xnum * $xm2 + $lg_p2[$i]; + $xden = $xden * $xm2 + $lg_q2[$i]; + } + $res = $corr + $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden)); + } + } elseif ($y <= 4.0) { + // --------------------- + // 1.5 .LT. X .LE. 4.0 + // --------------------- + $xm2 = $y - 2.0; + $xden = 1.0; + $xnum = 0.0; + for ($i = 0; $i < 8; ++$i) { + $xnum = $xnum * $xm2 + $lg_p2[$i]; + $xden = $xden * $xm2 + $lg_q2[$i]; + } + $res = $xm2 * ($lg_d2 + $xm2 * ($xnum / $xden)); + } elseif ($y <= 12.0) { + // ---------------------- + // 4.0 .LT. X .LE. 12.0 + // ---------------------- + $xm4 = $y - 4.0; + $xden = -1.0; + $xnum = 0.0; + for ($i = 0; $i < 8; ++$i) { + $xnum = $xnum * $xm4 + $lg_p4[$i]; + $xden = $xden * $xm4 + $lg_q4[$i]; + } + $res = $lg_d4 + $xm4 * ($xnum / $xden); + } else { + // --------------------------------- + // Evaluate for argument .GE. 12.0 + // --------------------------------- + $res = 0.0; + if ($y <= $lg_frtbig) { + $res = $lg_c[6]; + $ysq = $y * $y; + for ($i = 0; $i < 6; ++$i) + $res = $res / $ysq + $lg_c[$i]; + } + $res /= $y; + $corr = log($y); + $res = $res + log(SQRT2PI) - 0.5 * $corr; + $res += $y * ($corr - 1.0); + } + } else { + // -------------------------- + // Return for bad arguments + // -------------------------- + $res = MAX_VALUE; + } + // ------------------------------ + // Final adjustments and return + // ------------------------------ + self::$_logGammaCache_x = $x; + self::$_logGammaCache_result = $res; + return $res; + } // function _logGamma() + + + // + // Private implementation of the incomplete Gamma function + // + private static function _incompleteGamma($a,$x) { + static $max = 32; + $summer = 0; + for ($n=0; $n<=$max; ++$n) { + $divisor = $a; + for ($i=1; $i<=$n; ++$i) { + $divisor *= ($a + $i); + } + $summer += (pow($x,$n) / $divisor); + } + return pow($x,$a) * exp(0-$x) * $summer; + } // function _incompleteGamma() + + + // + // Private implementation of the Gamma function + // + private static function _gamma($data) { + if ($data == 0.0) return 0; + + static $p0 = 1.000000000190015; + static $p = array ( 1 => 76.18009172947146, + 2 => -86.50532032941677, + 3 => 24.01409824083091, + 4 => -1.231739572450155, + 5 => 1.208650973866179e-3, + 6 => -5.395239384953e-6 + ); + + $y = $x = $data; + $tmp = $x + 5.5; + $tmp -= ($x + 0.5) * log($tmp); + + $summer = $p0; + for ($j=1;$j<=6;++$j) { + $summer += ($p[$j] / ++$y); + } + return exp(0 - $tmp + log(SQRT2PI * $summer / $x)); + } // function _gamma() + + + /*************************************************************************** + * inverse_ncdf.php + * ------------------- + * begin : Friday, January 16, 2004 + * copyright : (C) 2004 Michael Nickerson + * email : nickersonm@yahoo.com + * + ***************************************************************************/ + private static function _inverse_ncdf($p) { + // Inverse ncdf approximation by Peter J. Acklam, implementation adapted to + // PHP by Michael Nickerson, using Dr. Thomas Ziegler's C implementation as + // a guide. http://home.online.no/~pjacklam/notes/invnorm/index.html + // I have not checked the accuracy of this implementation. Be aware that PHP + // will truncate the coeficcients to 14 digits. + + // You have permission to use and distribute this function freely for + // whatever purpose you want, but please show common courtesy and give credit + // where credit is due. + + // Input paramater is $p - probability - where 0 < p < 1. + + // Coefficients in rational approximations + static $a = array( 1 => -3.969683028665376e+01, + 2 => 2.209460984245205e+02, + 3 => -2.759285104469687e+02, + 4 => 1.383577518672690e+02, + 5 => -3.066479806614716e+01, + 6 => 2.506628277459239e+00 + ); + + static $b = array( 1 => -5.447609879822406e+01, + 2 => 1.615858368580409e+02, + 3 => -1.556989798598866e+02, + 4 => 6.680131188771972e+01, + 5 => -1.328068155288572e+01 + ); + + static $c = array( 1 => -7.784894002430293e-03, + 2 => -3.223964580411365e-01, + 3 => -2.400758277161838e+00, + 4 => -2.549732539343734e+00, + 5 => 4.374664141464968e+00, + 6 => 2.938163982698783e+00 + ); + + static $d = array( 1 => 7.784695709041462e-03, + 2 => 3.224671290700398e-01, + 3 => 2.445134137142996e+00, + 4 => 3.754408661907416e+00 + ); + + // Define lower and upper region break-points. + $p_low = 0.02425; //Use lower region approx. below this + $p_high = 1 - $p_low; //Use upper region approx. above this + + if (0 < $p && $p < $p_low) { + // Rational approximation for lower region. + $q = sqrt(-2 * log($p)); + return ((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) / + (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1); + } elseif ($p_low <= $p && $p <= $p_high) { + // Rational approximation for central region. + $q = $p - 0.5; + $r = $q * $q; + return ((((($a[1] * $r + $a[2]) * $r + $a[3]) * $r + $a[4]) * $r + $a[5]) * $r + $a[6]) * $q / + ((((($b[1] * $r + $b[2]) * $r + $b[3]) * $r + $b[4]) * $r + $b[5]) * $r + 1); + } elseif ($p_high < $p && $p < 1) { + // Rational approximation for upper region. + $q = sqrt(-2 * log(1 - $p)); + return -((((($c[1] * $q + $c[2]) * $q + $c[3]) * $q + $c[4]) * $q + $c[5]) * $q + $c[6]) / + (((($d[1] * $q + $d[2]) * $q + $d[3]) * $q + $d[4]) * $q + 1); + } + // If 0 < p < 1, return a null value + return PHPExcel_Calculation_Functions::NULL(); + } // function _inverse_ncdf() + + + private static function _inverse_ncdf2($prob) { + // Approximation of inverse standard normal CDF developed by + // B. Moro, "The Full Monte," Risk 8(2), Feb 1995, 57-58. + + $a1 = 2.50662823884; + $a2 = -18.61500062529; + $a3 = 41.39119773534; + $a4 = -25.44106049637; + + $b1 = -8.4735109309; + $b2 = 23.08336743743; + $b3 = -21.06224101826; + $b4 = 3.13082909833; + + $c1 = 0.337475482272615; + $c2 = 0.976169019091719; + $c3 = 0.160797971491821; + $c4 = 2.76438810333863E-02; + $c5 = 3.8405729373609E-03; + $c6 = 3.951896511919E-04; + $c7 = 3.21767881768E-05; + $c8 = 2.888167364E-07; + $c9 = 3.960315187E-07; + + $y = $prob - 0.5; + if (abs($y) < 0.42) { + $z = ($y * $y); + $z = $y * ((($a4 * $z + $a3) * $z + $a2) * $z + $a1) / (((($b4 * $z + $b3) * $z + $b2) * $z + $b1) * $z + 1); + } else { + if ($y > 0) { + $z = log(-log(1 - $prob)); + } else { + $z = log(-log($prob)); + } + $z = $c1 + $z * ($c2 + $z * ($c3 + $z * ($c4 + $z * ($c5 + $z * ($c6 + $z * ($c7 + $z * ($c8 + $z * $c9))))))); + if ($y < 0) { + $z = -$z; + } + } + return $z; + } // function _inverse_ncdf2() + + + private static function _inverse_ncdf3($p) { + // ALGORITHM AS241 APPL. STATIST. (1988) VOL. 37, NO. 3. + // Produces the normal deviate Z corresponding to a given lower + // tail area of P; Z is accurate to about 1 part in 10**16. + // + // This is a PHP version of the original FORTRAN code that can + // be found at http://lib.stat.cmu.edu/apstat/ + $split1 = 0.425; + $split2 = 5; + $const1 = 0.180625; + $const2 = 1.6; + + // coefficients for p close to 0.5 + $a0 = 3.3871328727963666080; + $a1 = 1.3314166789178437745E+2; + $a2 = 1.9715909503065514427E+3; + $a3 = 1.3731693765509461125E+4; + $a4 = 4.5921953931549871457E+4; + $a5 = 6.7265770927008700853E+4; + $a6 = 3.3430575583588128105E+4; + $a7 = 2.5090809287301226727E+3; + + $b1 = 4.2313330701600911252E+1; + $b2 = 6.8718700749205790830E+2; + $b3 = 5.3941960214247511077E+3; + $b4 = 2.1213794301586595867E+4; + $b5 = 3.9307895800092710610E+4; + $b6 = 2.8729085735721942674E+4; + $b7 = 5.2264952788528545610E+3; + + // coefficients for p not close to 0, 0.5 or 1. + $c0 = 1.42343711074968357734; + $c1 = 4.63033784615654529590; + $c2 = 5.76949722146069140550; + $c3 = 3.64784832476320460504; + $c4 = 1.27045825245236838258; + $c5 = 2.41780725177450611770E-1; + $c6 = 2.27238449892691845833E-2; + $c7 = 7.74545014278341407640E-4; + + $d1 = 2.05319162663775882187; + $d2 = 1.67638483018380384940; + $d3 = 6.89767334985100004550E-1; + $d4 = 1.48103976427480074590E-1; + $d5 = 1.51986665636164571966E-2; + $d6 = 5.47593808499534494600E-4; + $d7 = 1.05075007164441684324E-9; + + // coefficients for p near 0 or 1. + $e0 = 6.65790464350110377720; + $e1 = 5.46378491116411436990; + $e2 = 1.78482653991729133580; + $e3 = 2.96560571828504891230E-1; + $e4 = 2.65321895265761230930E-2; + $e5 = 1.24266094738807843860E-3; + $e6 = 2.71155556874348757815E-5; + $e7 = 2.01033439929228813265E-7; + + $f1 = 5.99832206555887937690E-1; + $f2 = 1.36929880922735805310E-1; + $f3 = 1.48753612908506148525E-2; + $f4 = 7.86869131145613259100E-4; + $f5 = 1.84631831751005468180E-5; + $f6 = 1.42151175831644588870E-7; + $f7 = 2.04426310338993978564E-15; + + $q = $p - 0.5; + + // computation for p close to 0.5 + if (abs($q) <= split1) { + $R = $const1 - $q * $q; + $z = $q * ((((((($a7 * $R + $a6) * $R + $a5) * $R + $a4) * $R + $a3) * $R + $a2) * $R + $a1) * $R + $a0) / + ((((((($b7 * $R + $b6) * $R + $b5) * $R + $b4) * $R + $b3) * $R + $b2) * $R + $b1) * $R + 1); + } else { + if ($q < 0) { + $R = $p; + } else { + $R = 1 - $p; + } + $R = pow(-log($R),2); + + // computation for p not close to 0, 0.5 or 1. + If ($R <= $split2) { + $R = $R - $const2; + $z = ((((((($c7 * $R + $c6) * $R + $c5) * $R + $c4) * $R + $c3) * $R + $c2) * $R + $c1) * $R + $c0) / + ((((((($d7 * $R + $d6) * $R + $d5) * $R + $d4) * $R + $d3) * $R + $d2) * $R + $d1) * $R + 1); + } else { + // computation for p near 0 or 1. + $R = $R - $split2; + $z = ((((((($e7 * $R + $e6) * $R + $e5) * $R + $e4) * $R + $e3) * $R + $e2) * $R + $e1) * $R + $e0) / + ((((((($f7 * $R + $f6) * $R + $f5) * $R + $f4) * $R + $f3) * $R + $f2) * $R + $f1) * $R + 1); + } + if ($q < 0) { + $z = -$z; + } + } + return $z; + } // function _inverse_ncdf3() + + + /** + * AVEDEV + * + * Returns the average of the absolute deviations of data points from their mean. + * AVEDEV is a measure of the variability in a data set. + * + * Excel Function: + * AVEDEV(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function AVEDEV() { + $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()); + + // Return value + $returnValue = null; + + $aMean = self::AVERAGE($aArgs); + if ($aMean != PHPExcel_Calculation_Functions::DIV0()) { + $aCount = 0; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; + } + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + if (is_null($returnValue)) { + $returnValue = abs($arg - $aMean); + } else { + $returnValue += abs($arg - $aMean); + } + ++$aCount; + } + } + + // Return + if ($aCount == 0) { + return PHPExcel_Calculation_Functions::DIV0(); + } + return $returnValue / $aCount; + } + return PHPExcel_Calculation_Functions::NaN(); + } // function AVEDEV() + + + /** + * AVERAGE + * + * Returns the average (arithmetic mean) of the arguments + * + * Excel Function: + * AVERAGE(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function AVERAGE() { + $returnValue = $aCount = 0; + + // Loop through arguments + foreach (PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) { + if ((is_bool($arg)) && + ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; + } + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + if (is_null($returnValue)) { + $returnValue = $arg; + } else { + $returnValue += $arg; + } + ++$aCount; + } + } + + // Return + if ($aCount > 0) { + return $returnValue / $aCount; + } else { + return PHPExcel_Calculation_Functions::DIV0(); + } + } // function AVERAGE() + + + /** + * AVERAGEA + * + * Returns the average of its arguments, including numbers, text, and logical values + * + * Excel Function: + * AVERAGEA(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function AVERAGEA() { + // Return value + $returnValue = null; + + $aCount = 0; + // Loop through arguments + foreach (PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()) as $k => $arg) { + if ((is_bool($arg)) && + (!PHPExcel_Calculation_Functions::isMatrixValue($k))) { + } else { + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + if (is_null($returnValue)) { + $returnValue = $arg; + } else { + $returnValue += $arg; + } + ++$aCount; + } + } + } + + // Return + if ($aCount > 0) { + return $returnValue / $aCount; + } else { + return PHPExcel_Calculation_Functions::DIV0(); + } + } // function AVERAGEA() + + + /** + * AVERAGEIF + * + * Returns the average value from a range of cells that contain numbers within the list of arguments + * + * Excel Function: + * AVERAGEIF(value1[,value2[, ...]],condition) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @param string $condition The criteria that defines which cells will be checked. + * @param mixed[] $averageArgs Data values + * @return float + */ + public static function AVERAGEIF($aArgs,$condition,$averageArgs = array()) { + // Return value + $returnValue = 0; + + $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs); + $averageArgs = PHPExcel_Calculation_Functions::flattenArray($averageArgs); + if (empty($averageArgs)) { + $averageArgs = $aArgs; + } + $condition = PHPExcel_Calculation_Functions::_ifCondition($condition); + // Loop through arguments + $aCount = 0; + foreach ($aArgs as $key => $arg) { + if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } + $testCondition = '='.$arg.$condition; + if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { + if ((is_null($returnValue)) || ($arg > $returnValue)) { + $returnValue += $arg; + ++$aCount; + } + } + } + + // Return + if ($aCount > 0) { + return $returnValue / $aCount; + } else { + return PHPExcel_Calculation_Functions::DIV0(); + } + } // function AVERAGEIF() + + + /** + * BETADIST + * + * Returns the beta distribution. + * + * @param float $value Value at which you want to evaluate the distribution + * @param float $alpha Parameter to the distribution + * @param float $beta Parameter to the distribution + * @param boolean $cumulative + * @return float + * + */ + public static function BETADIST($value,$alpha,$beta,$rMin=0,$rMax=1) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha); + $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta); + $rMin = PHPExcel_Calculation_Functions::flattenSingleValue($rMin); + $rMax = PHPExcel_Calculation_Functions::flattenSingleValue($rMax); + + if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) { + if (($value < $rMin) || ($value > $rMax) || ($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ($rMin > $rMax) { + $tmp = $rMin; + $rMin = $rMax; + $rMax = $tmp; + } + $value -= $rMin; + $value /= ($rMax - $rMin); + return self::_incompleteBeta($value,$alpha,$beta); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function BETADIST() + + + /** + * BETAINV + * + * Returns the inverse of the beta distribution. + * + * @param float $probability Probability at which you want to evaluate the distribution + * @param float $alpha Parameter to the distribution + * @param float $beta Parameter to the distribution + * @param float $rMin Minimum value + * @param float $rMax Maximum value + * @param boolean $cumulative + * @return float + * + */ + public static function BETAINV($probability,$alpha,$beta,$rMin=0,$rMax=1) { + $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability); + $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha); + $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta); + $rMin = PHPExcel_Calculation_Functions::flattenSingleValue($rMin); + $rMax = PHPExcel_Calculation_Functions::flattenSingleValue($rMax); + + if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta)) && (is_numeric($rMin)) && (is_numeric($rMax))) { + if (($alpha <= 0) || ($beta <= 0) || ($rMin == $rMax) || ($probability <= 0) || ($probability > 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ($rMin > $rMax) { + $tmp = $rMin; + $rMin = $rMax; + $rMax = $tmp; + } + $a = 0; + $b = 2; + + $i = 0; + while ((($b - $a) > PRECISION) && ($i++ < MAX_ITERATIONS)) { + $guess = ($a + $b) / 2; + $result = self::BETADIST($guess, $alpha, $beta); + if (($result == $probability) || ($result == 0)) { + $b = $a; + } elseif ($result > $probability) { + $b = $guess; + } else { + $a = $guess; + } + } + if ($i == MAX_ITERATIONS) { + return PHPExcel_Calculation_Functions::NA(); + } + return round($rMin + $guess * ($rMax - $rMin),12); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function BETAINV() + + + /** + * BINOMDIST + * + * Returns the individual term binomial distribution probability. Use BINOMDIST in problems with + * a fixed number of tests or trials, when the outcomes of any trial are only success or failure, + * when trials are independent, and when the probability of success is constant throughout the + * experiment. For example, BINOMDIST can calculate the probability that two of the next three + * babies born are male. + * + * @param float $value Number of successes in trials + * @param float $trials Number of trials + * @param float $probability Probability of success on each trial + * @param boolean $cumulative + * @return float + * + * @todo Cumulative distribution function + * + */ + public static function BINOMDIST($value, $trials, $probability, $cumulative) { + $value = floor(PHPExcel_Calculation_Functions::flattenSingleValue($value)); + $trials = floor(PHPExcel_Calculation_Functions::flattenSingleValue($trials)); + $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability); + + if ((is_numeric($value)) && (is_numeric($trials)) && (is_numeric($probability))) { + if (($value < 0) || ($value > $trials)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (($probability < 0) || ($probability > 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ((is_numeric($cumulative)) || (is_bool($cumulative))) { + if ($cumulative) { + $summer = 0; + for ($i = 0; $i <= $value; ++$i) { + $summer += PHPExcel_Calculation_MathTrig::COMBIN($trials,$i) * pow($probability,$i) * pow(1 - $probability,$trials - $i); + } + return $summer; + } else { + return PHPExcel_Calculation_MathTrig::COMBIN($trials,$value) * pow($probability,$value) * pow(1 - $probability,$trials - $value) ; + } + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function BINOMDIST() + + + /** + * CHIDIST + * + * Returns the one-tailed probability of the chi-squared distribution. + * + * @param float $value Value for the function + * @param float $degrees degrees of freedom + * @return float + */ + public static function CHIDIST($value, $degrees) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees)); + + if ((is_numeric($value)) && (is_numeric($degrees))) { + if ($degrees < 1) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ($value < 0) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) { + return 1; + } + return PHPExcel_Calculation_Functions::NaN(); + } + return 1 - (self::_incompleteGamma($degrees/2,$value/2) / self::_gamma($degrees/2)); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function CHIDIST() + + + /** + * CHIINV + * + * Returns the one-tailed probability of the chi-squared distribution. + * + * @param float $probability Probability for the function + * @param float $degrees degrees of freedom + * @return float + */ + public static function CHIINV($probability, $degrees) { + $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability); + $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees)); + + if ((is_numeric($probability)) && (is_numeric($degrees))) { + + $xLo = 100; + $xHi = 0; + + $x = $xNew = 1; + $dx = 1; + $i = 0; + + while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { + // Apply Newton-Raphson step + $result = self::CHIDIST($x, $degrees); + $error = $result - $probability; + if ($error == 0.0) { + $dx = 0; + } elseif ($error < 0.0) { + $xLo = $x; + } else { + $xHi = $x; + } + // Avoid division by zero + if ($result != 0.0) { + $dx = $error / $result; + $xNew = $x - $dx; + } + // If the NR fails to converge (which for example may be the + // case if the initial guess is too rough) we apply a bisection + // step to determine a more narrow interval around the root. + if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { + $xNew = ($xLo + $xHi) / 2; + $dx = $xNew - $x; + } + $x = $xNew; + } + if ($i == MAX_ITERATIONS) { + return PHPExcel_Calculation_Functions::NA(); + } + return round($x,12); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function CHIINV() + + + /** + * CONFIDENCE + * + * Returns the confidence interval for a population mean + * + * @param float $alpha + * @param float $stdDev Standard Deviation + * @param float $size + * @return float + * + */ + public static function CONFIDENCE($alpha,$stdDev,$size) { + $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha); + $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev); + $size = floor(PHPExcel_Calculation_Functions::flattenSingleValue($size)); + + if ((is_numeric($alpha)) && (is_numeric($stdDev)) && (is_numeric($size))) { + if (($alpha <= 0) || ($alpha >= 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (($stdDev <= 0) || ($size < 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + return self::NORMSINV(1 - $alpha / 2) * $stdDev / sqrt($size); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function CONFIDENCE() + + + /** + * CORREL + * + * Returns covariance, the average of the products of deviations for each data point pair. + * + * @param array of mixed Data Series Y + * @param array of mixed Data Series X + * @return float + */ + public static function CORREL($yValues,$xValues=null) { + if ((is_null($xValues)) || (!is_array($yValues)) || (!is_array($xValues))) { + return PHPExcel_Calculation_Functions::VALUE(); + } + if (!self::_checkTrendArrays($yValues,$xValues)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $yValueCount = count($yValues); + $xValueCount = count($xValues); + + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { + return PHPExcel_Calculation_Functions::NA(); + } elseif ($yValueCount == 1) { + return PHPExcel_Calculation_Functions::DIV0(); + } + + $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues); + return $bestFitLinear->getCorrelation(); + } // function CORREL() + + + /** + * COUNT + * + * Counts the number of cells that contain numbers within the list of arguments + * + * Excel Function: + * COUNT(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return int + */ + public static function COUNT() { + // Return value + $returnValue = 0; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()); + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; + } + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + ++$returnValue; + } + } + + // Return + return $returnValue; + } // function COUNT() + + + /** + * COUNTA + * + * Counts the number of cells that are not empty within the list of arguments + * + * Excel Function: + * COUNTA(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return int + */ + public static function COUNTA() { + // Return value + $returnValue = 0; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + foreach ($aArgs as $arg) { + // Is it a numeric, boolean or string value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { + ++$returnValue; + } + } + + // Return + return $returnValue; + } // function COUNTA() + + + /** + * COUNTBLANK + * + * Counts the number of empty cells within the list of arguments + * + * Excel Function: + * COUNTBLANK(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return int + */ + public static function COUNTBLANK() { + // Return value + $returnValue = 0; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + foreach ($aArgs as $arg) { + // Is it a blank cell? + if ((is_null($arg)) || ((is_string($arg)) && ($arg == ''))) { + ++$returnValue; + } + } + + // Return + return $returnValue; + } // function COUNTBLANK() + + + /** + * COUNTIF + * + * Counts the number of cells that contain numbers within the list of arguments + * + * Excel Function: + * COUNTIF(value1[,value2[, ...]],condition) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @param string $condition The criteria that defines which cells will be counted. + * @return int + */ + public static function COUNTIF($aArgs,$condition) { + // Return value + $returnValue = 0; + + $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs); + $condition = PHPExcel_Calculation_Functions::_ifCondition($condition); + // Loop through arguments + foreach ($aArgs as $arg) { + if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } + $testCondition = '='.$arg.$condition; + if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { + // Is it a value within our criteria + ++$returnValue; + } + } + + // Return + return $returnValue; + } // function COUNTIF() + + + /** + * COVAR + * + * Returns covariance, the average of the products of deviations for each data point pair. + * + * @param array of mixed Data Series Y + * @param array of mixed Data Series X + * @return float + */ + public static function COVAR($yValues,$xValues) { + if (!self::_checkTrendArrays($yValues,$xValues)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $yValueCount = count($yValues); + $xValueCount = count($xValues); + + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { + return PHPExcel_Calculation_Functions::NA(); + } elseif ($yValueCount == 1) { + return PHPExcel_Calculation_Functions::DIV0(); + } + + $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues); + return $bestFitLinear->getCovariance(); + } // function COVAR() + + + /** + * CRITBINOM + * + * Returns the smallest value for which the cumulative binomial distribution is greater + * than or equal to a criterion value + * + * See http://support.microsoft.com/kb/828117/ for details of the algorithm used + * + * @param float $trials number of Bernoulli trials + * @param float $probability probability of a success on each trial + * @param float $alpha criterion value + * @return int + * + * @todo Warning. This implementation differs from the algorithm detailed on the MS + * web site in that $CumPGuessMinus1 = $CumPGuess - 1 rather than $CumPGuess - $PGuess + * This eliminates a potential endless loop error, but may have an adverse affect on the + * accuracy of the function (although all my tests have so far returned correct results). + * + */ + public static function CRITBINOM($trials, $probability, $alpha) { + $trials = floor(PHPExcel_Calculation_Functions::flattenSingleValue($trials)); + $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability); + $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha); + + if ((is_numeric($trials)) && (is_numeric($probability)) && (is_numeric($alpha))) { + if ($trials < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (($probability < 0) || ($probability > 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (($alpha < 0) || ($alpha > 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ($alpha <= 0.5) { + $t = sqrt(log(1 / ($alpha * $alpha))); + $trialsApprox = 0 - ($t + (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t)); + } else { + $t = sqrt(log(1 / pow(1 - $alpha,2))); + $trialsApprox = $t - (2.515517 + 0.802853 * $t + 0.010328 * $t * $t) / (1 + 1.432788 * $t + 0.189269 * $t * $t + 0.001308 * $t * $t * $t); + } + $Guess = floor($trials * $probability + $trialsApprox * sqrt($trials * $probability * (1 - $probability))); + if ($Guess < 0) { + $Guess = 0; + } elseif ($Guess > $trials) { + $Guess = $trials; + } + + $TotalUnscaledProbability = $UnscaledPGuess = $UnscaledCumPGuess = 0.0; + $EssentiallyZero = 10e-12; + + $m = floor($trials * $probability); + ++$TotalUnscaledProbability; + if ($m == $Guess) { ++$UnscaledPGuess; } + if ($m <= $Guess) { ++$UnscaledCumPGuess; } + + $PreviousValue = 1; + $Done = False; + $k = $m + 1; + while ((!$Done) && ($k <= $trials)) { + $CurrentValue = $PreviousValue * ($trials - $k + 1) * $probability / ($k * (1 - $probability)); + $TotalUnscaledProbability += $CurrentValue; + if ($k == $Guess) { $UnscaledPGuess += $CurrentValue; } + if ($k <= $Guess) { $UnscaledCumPGuess += $CurrentValue; } + if ($CurrentValue <= $EssentiallyZero) { $Done = True; } + $PreviousValue = $CurrentValue; + ++$k; + } + + $PreviousValue = 1; + $Done = False; + $k = $m - 1; + while ((!$Done) && ($k >= 0)) { + $CurrentValue = $PreviousValue * $k + 1 * (1 - $probability) / (($trials - $k) * $probability); + $TotalUnscaledProbability += $CurrentValue; + if ($k == $Guess) { $UnscaledPGuess += $CurrentValue; } + if ($k <= $Guess) { $UnscaledCumPGuess += $CurrentValue; } + if ($CurrentValue <= $EssentiallyZero) { $Done = True; } + $PreviousValue = $CurrentValue; + --$k; + } + + $PGuess = $UnscaledPGuess / $TotalUnscaledProbability; + $CumPGuess = $UnscaledCumPGuess / $TotalUnscaledProbability; + +// $CumPGuessMinus1 = $CumPGuess - $PGuess; + $CumPGuessMinus1 = $CumPGuess - 1; + + while (True) { + if (($CumPGuessMinus1 < $alpha) && ($CumPGuess >= $alpha)) { + return $Guess; + } elseif (($CumPGuessMinus1 < $alpha) && ($CumPGuess < $alpha)) { + $PGuessPlus1 = $PGuess * ($trials - $Guess) * $probability / $Guess / (1 - $probability); + $CumPGuessMinus1 = $CumPGuess; + $CumPGuess = $CumPGuess + $PGuessPlus1; + $PGuess = $PGuessPlus1; + ++$Guess; + } elseif (($CumPGuessMinus1 >= $alpha) && ($CumPGuess >= $alpha)) { + $PGuessMinus1 = $PGuess * $Guess * (1 - $probability) / ($trials - $Guess + 1) / $probability; + $CumPGuess = $CumPGuessMinus1; + $CumPGuessMinus1 = $CumPGuessMinus1 - $PGuess; + $PGuess = $PGuessMinus1; + --$Guess; + } + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function CRITBINOM() + + + /** + * DEVSQ + * + * Returns the sum of squares of deviations of data points from their sample mean. + * + * Excel Function: + * DEVSQ(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function DEVSQ() { + $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()); + + // Return value + $returnValue = null; + + $aMean = self::AVERAGE($aArgs); + if ($aMean != PHPExcel_Calculation_Functions::DIV0()) { + $aCount = -1; + foreach ($aArgs as $k => $arg) { + // Is it a numeric value? + if ((is_bool($arg)) && + ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; + } + if ((is_numeric($arg)) && (!is_string($arg))) { + if (is_null($returnValue)) { + $returnValue = pow(($arg - $aMean),2); + } else { + $returnValue += pow(($arg - $aMean),2); + } + ++$aCount; + } + } + + // Return + if (is_null($returnValue)) { + return PHPExcel_Calculation_Functions::NaN(); + } else { + return $returnValue; + } + } + return self::NA(); + } // function DEVSQ() + + + /** + * EXPONDIST + * + * Returns the exponential distribution. Use EXPONDIST to model the time between events, + * such as how long an automated bank teller takes to deliver cash. For example, you can + * use EXPONDIST to determine the probability that the process takes at most 1 minute. + * + * @param float $value Value of the function + * @param float $lambda The parameter value + * @param boolean $cumulative + * @return float + */ + public static function EXPONDIST($value, $lambda, $cumulative) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $lambda = PHPExcel_Calculation_Functions::flattenSingleValue($lambda); + $cumulative = PHPExcel_Calculation_Functions::flattenSingleValue($cumulative); + + if ((is_numeric($value)) && (is_numeric($lambda))) { + if (($value < 0) || ($lambda < 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ((is_numeric($cumulative)) || (is_bool($cumulative))) { + if ($cumulative) { + return 1 - exp(0-$value*$lambda); + } else { + return $lambda * exp(0-$value*$lambda); + } + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function EXPONDIST() + + + /** + * FISHER + * + * Returns the Fisher transformation at x. This transformation produces a function that + * is normally distributed rather than skewed. Use this function to perform hypothesis + * testing on the correlation coefficient. + * + * @param float $value + * @return float + */ + public static function FISHER($value) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + + if (is_numeric($value)) { + if (($value <= -1) || ($value >= 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + return 0.5 * log((1+$value)/(1-$value)); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function FISHER() + + + /** + * FISHERINV + * + * Returns the inverse of the Fisher transformation. Use this transformation when + * analyzing correlations between ranges or arrays of data. If y = FISHER(x), then + * FISHERINV(y) = x. + * + * @param float $value + * @return float + */ + public static function FISHERINV($value) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + + if (is_numeric($value)) { + return (exp(2 * $value) - 1) / (exp(2 * $value) + 1); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function FISHERINV() + + + /** + * FORECAST + * + * Calculates, or predicts, a future value by using existing values. The predicted value is a y-value for a given x-value. + * + * @param float Value of X for which we want to find Y + * @param array of mixed Data Series Y + * @param array of mixed Data Series X + * @return float + */ + public static function FORECAST($xValue,$yValues,$xValues) { + $xValue = PHPExcel_Calculation_Functions::flattenSingleValue($xValue); + if (!is_numeric($xValue)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (!self::_checkTrendArrays($yValues,$xValues)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $yValueCount = count($yValues); + $xValueCount = count($xValues); + + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { + return PHPExcel_Calculation_Functions::NA(); + } elseif ($yValueCount == 1) { + return PHPExcel_Calculation_Functions::DIV0(); + } + + $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues); + return $bestFitLinear->getValueOfYForX($xValue); + } // function FORECAST() + + + /** + * GAMMADIST + * + * Returns the gamma distribution. + * + * @param float $value Value at which you want to evaluate the distribution + * @param float $a Parameter to the distribution + * @param float $b Parameter to the distribution + * @param boolean $cumulative + * @return float + * + */ + public static function GAMMADIST($value,$a,$b,$cumulative) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $a = PHPExcel_Calculation_Functions::flattenSingleValue($a); + $b = PHPExcel_Calculation_Functions::flattenSingleValue($b); + + if ((is_numeric($value)) && (is_numeric($a)) && (is_numeric($b))) { + if (($value < 0) || ($a <= 0) || ($b <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ((is_numeric($cumulative)) || (is_bool($cumulative))) { + if ($cumulative) { + return self::_incompleteGamma($a,$value / $b) / self::_gamma($a); + } else { + return (1 / (pow($b,$a) * self::_gamma($a))) * pow($value,$a-1) * exp(0-($value / $b)); + } + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function GAMMADIST() + + + /** + * GAMMAINV + * + * Returns the inverse of the beta distribution. + * + * @param float $probability Probability at which you want to evaluate the distribution + * @param float $alpha Parameter to the distribution + * @param float $beta Parameter to the distribution + * @return float + * + */ + public static function GAMMAINV($probability,$alpha,$beta) { + $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability); + $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha); + $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta); + + if ((is_numeric($probability)) && (is_numeric($alpha)) && (is_numeric($beta))) { + if (($alpha <= 0) || ($beta <= 0) || ($probability < 0) || ($probability > 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + + $xLo = 0; + $xHi = $alpha * $beta * 5; + + $x = $xNew = 1; + $error = $pdf = 0; + $dx = 1024; + $i = 0; + + while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { + // Apply Newton-Raphson step + $error = self::GAMMADIST($x, $alpha, $beta, True) - $probability; + if ($error < 0.0) { + $xLo = $x; + } else { + $xHi = $x; + } + $pdf = self::GAMMADIST($x, $alpha, $beta, False); + // Avoid division by zero + if ($pdf != 0.0) { + $dx = $error / $pdf; + $xNew = $x - $dx; + } + // If the NR fails to converge (which for example may be the + // case if the initial guess is too rough) we apply a bisection + // step to determine a more narrow interval around the root. + if (($xNew < $xLo) || ($xNew > $xHi) || ($pdf == 0.0)) { + $xNew = ($xLo + $xHi) / 2; + $dx = $xNew - $x; + } + $x = $xNew; + } + if ($i == MAX_ITERATIONS) { + return PHPExcel_Calculation_Functions::NA(); + } + return $x; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function GAMMAINV() + + + /** + * GAMMALN + * + * Returns the natural logarithm of the gamma function. + * + * @param float $value + * @return float + */ + public static function GAMMALN($value) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + + if (is_numeric($value)) { + if ($value <= 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + return log(self::_gamma($value)); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function GAMMALN() + + + /** + * GEOMEAN + * + * Returns the geometric mean of an array or range of positive data. For example, you + * can use GEOMEAN to calculate average growth rate given compound interest with + * variable rates. + * + * Excel Function: + * GEOMEAN(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function GEOMEAN() { + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + + $aMean = PHPExcel_Calculation_MathTrig::PRODUCT($aArgs); + if (is_numeric($aMean) && ($aMean > 0)) { + $aCount = self::COUNT($aArgs) ; + if (self::MIN($aArgs) > 0) { + return pow($aMean, (1 / $aCount)); + } + } + return PHPExcel_Calculation_Functions::NaN(); + } // GEOMEAN() + + + /** + * GROWTH + * + * Returns values along a predicted emponential trend + * + * @param array of mixed Data Series Y + * @param array of mixed Data Series X + * @param array of mixed Values of X for which we want to find Y + * @param boolean A logical value specifying whether to force the intersect to equal 0. + * @return array of float + */ + public static function GROWTH($yValues,$xValues=array(),$newValues=array(),$const=True) { + $yValues = PHPExcel_Calculation_Functions::flattenArray($yValues); + $xValues = PHPExcel_Calculation_Functions::flattenArray($xValues); + $newValues = PHPExcel_Calculation_Functions::flattenArray($newValues); + $const = (is_null($const)) ? True : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const); + + $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL,$yValues,$xValues,$const); + if (empty($newValues)) { + $newValues = $bestFitExponential->getXValues(); + } + + $returnArray = array(); + foreach($newValues as $xValue) { + $returnArray[0][] = $bestFitExponential->getValueOfYForX($xValue); + } + + return $returnArray; + } // function GROWTH() + + + /** + * HARMEAN + * + * Returns the harmonic mean of a data set. The harmonic mean is the reciprocal of the + * arithmetic mean of reciprocals. + * + * Excel Function: + * HARMEAN(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function HARMEAN() { + // Return value + $returnValue = PHPExcel_Calculation_Functions::NA(); + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + if (self::MIN($aArgs) < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + $aCount = 0; + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + if ($arg <= 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (is_null($returnValue)) { + $returnValue = (1 / $arg); + } else { + $returnValue += (1 / $arg); + } + ++$aCount; + } + } + + // Return + if ($aCount > 0) { + return 1 / ($returnValue / $aCount); + } else { + return $returnValue; + } + } // function HARMEAN() + + + /** + * HYPGEOMDIST + * + * Returns the hypergeometric distribution. HYPGEOMDIST returns the probability of a given number of + * sample successes, given the sample size, population successes, and population size. + * + * @param float $sampleSuccesses Number of successes in the sample + * @param float $sampleNumber Size of the sample + * @param float $populationSuccesses Number of successes in the population + * @param float $populationNumber Population size + * @return float + * + */ + public static function HYPGEOMDIST($sampleSuccesses, $sampleNumber, $populationSuccesses, $populationNumber) { + $sampleSuccesses = floor(PHPExcel_Calculation_Functions::flattenSingleValue($sampleSuccesses)); + $sampleNumber = floor(PHPExcel_Calculation_Functions::flattenSingleValue($sampleNumber)); + $populationSuccesses = floor(PHPExcel_Calculation_Functions::flattenSingleValue($populationSuccesses)); + $populationNumber = floor(PHPExcel_Calculation_Functions::flattenSingleValue($populationNumber)); + + if ((is_numeric($sampleSuccesses)) && (is_numeric($sampleNumber)) && (is_numeric($populationSuccesses)) && (is_numeric($populationNumber))) { + if (($sampleSuccesses < 0) || ($sampleSuccesses > $sampleNumber) || ($sampleSuccesses > $populationSuccesses)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (($sampleNumber <= 0) || ($sampleNumber > $populationNumber)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (($populationSuccesses <= 0) || ($populationSuccesses > $populationNumber)) { + return PHPExcel_Calculation_Functions::NaN(); + } + return PHPExcel_Calculation_MathTrig::COMBIN($populationSuccesses,$sampleSuccesses) * + PHPExcel_Calculation_MathTrig::COMBIN($populationNumber - $populationSuccesses,$sampleNumber - $sampleSuccesses) / + PHPExcel_Calculation_MathTrig::COMBIN($populationNumber,$sampleNumber); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function HYPGEOMDIST() + + + /** + * INTERCEPT + * + * Calculates the point at which a line will intersect the y-axis by using existing x-values and y-values. + * + * @param array of mixed Data Series Y + * @param array of mixed Data Series X + * @return float + */ + public static function INTERCEPT($yValues,$xValues) { + if (!self::_checkTrendArrays($yValues,$xValues)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $yValueCount = count($yValues); + $xValueCount = count($xValues); + + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { + return PHPExcel_Calculation_Functions::NA(); + } elseif ($yValueCount == 1) { + return PHPExcel_Calculation_Functions::DIV0(); + } + + $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues); + return $bestFitLinear->getIntersect(); + } // function INTERCEPT() + + + /** + * KURT + * + * Returns the kurtosis of a data set. Kurtosis characterizes the relative peakedness + * or flatness of a distribution compared with the normal distribution. Positive + * kurtosis indicates a relatively peaked distribution. Negative kurtosis indicates a + * relatively flat distribution. + * + * @param array Data Series + * @return float + */ + public static function KURT() { + $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()); + $mean = self::AVERAGE($aArgs); + $stdDev = self::STDEV($aArgs); + + if ($stdDev > 0) { + $count = $summer = 0; + // Loop through arguments + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!PHPExcel_Calculation_Functions::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $summer += pow((($arg - $mean) / $stdDev),4) ; + ++$count; + } + } + } + + // Return + if ($count > 3) { + return $summer * ($count * ($count+1) / (($count-1) * ($count-2) * ($count-3))) - (3 * pow($count-1,2) / (($count-2) * ($count-3))); + } + } + return PHPExcel_Calculation_Functions::DIV0(); + } // function KURT() + + + /** + * LARGE + * + * Returns the nth largest value in a data set. You can use this function to + * select a value based on its relative standing. + * + * Excel Function: + * LARGE(value1[,value2[, ...]],entry) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @param int $entry Position (ordered from the largest) in the array or range of data to return + * @return float + * + */ + public static function LARGE() { + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + + // Calculate + $entry = floor(array_pop($aArgs)); + + if ((is_numeric($entry)) && (!is_string($entry))) { + $mArgs = array(); + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $mArgs[] = $arg; + } + } + $count = self::COUNT($mArgs); + $entry = floor(--$entry); + if (($entry < 0) || ($entry >= $count) || ($count == 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + rsort($mArgs); + return $mArgs[$entry]; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function LARGE() + + + /** + * LINEST + * + * Calculates the statistics for a line by using the "least squares" method to calculate a straight line that best fits your data, + * and then returns an array that describes the line. + * + * @param array of mixed Data Series Y + * @param array of mixed Data Series X + * @param boolean A logical value specifying whether to force the intersect to equal 0. + * @param boolean A logical value specifying whether to return additional regression statistics. + * @return array + */ + public static function LINEST($yValues, $xValues = NULL, $const = TRUE, $stats = FALSE) { + $const = (is_null($const)) ? TRUE : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const); + $stats = (is_null($stats)) ? FALSE : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($stats); + if (is_null($xValues)) $xValues = range(1,count(PHPExcel_Calculation_Functions::flattenArray($yValues))); + + if (!self::_checkTrendArrays($yValues,$xValues)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $yValueCount = count($yValues); + $xValueCount = count($xValues); + + + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { + return PHPExcel_Calculation_Functions::NA(); + } elseif ($yValueCount == 1) { + return 0; + } + + $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues,$const); + if ($stats) { + return array( array( $bestFitLinear->getSlope(), + $bestFitLinear->getSlopeSE(), + $bestFitLinear->getGoodnessOfFit(), + $bestFitLinear->getF(), + $bestFitLinear->getSSRegression(), + ), + array( $bestFitLinear->getIntersect(), + $bestFitLinear->getIntersectSE(), + $bestFitLinear->getStdevOfResiduals(), + $bestFitLinear->getDFResiduals(), + $bestFitLinear->getSSResiduals() + ) + ); + } else { + return array( $bestFitLinear->getSlope(), + $bestFitLinear->getIntersect() + ); + } + } // function LINEST() + + + /** + * LOGEST + * + * Calculates an exponential curve that best fits the X and Y data series, + * and then returns an array that describes the line. + * + * @param array of mixed Data Series Y + * @param array of mixed Data Series X + * @param boolean A logical value specifying whether to force the intersect to equal 0. + * @param boolean A logical value specifying whether to return additional regression statistics. + * @return array + */ + public static function LOGEST($yValues,$xValues=null,$const=True,$stats=False) { + $const = (is_null($const)) ? True : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const); + $stats = (is_null($stats)) ? False : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($stats); + if (is_null($xValues)) $xValues = range(1,count(PHPExcel_Calculation_Functions::flattenArray($yValues))); + + if (!self::_checkTrendArrays($yValues,$xValues)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $yValueCount = count($yValues); + $xValueCount = count($xValues); + + foreach($yValues as $value) { + if ($value <= 0.0) { + return PHPExcel_Calculation_Functions::NaN(); + } + } + + + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { + return PHPExcel_Calculation_Functions::NA(); + } elseif ($yValueCount == 1) { + return 1; + } + + $bestFitExponential = trendClass::calculate(trendClass::TREND_EXPONENTIAL,$yValues,$xValues,$const); + if ($stats) { + return array( array( $bestFitExponential->getSlope(), + $bestFitExponential->getSlopeSE(), + $bestFitExponential->getGoodnessOfFit(), + $bestFitExponential->getF(), + $bestFitExponential->getSSRegression(), + ), + array( $bestFitExponential->getIntersect(), + $bestFitExponential->getIntersectSE(), + $bestFitExponential->getStdevOfResiduals(), + $bestFitExponential->getDFResiduals(), + $bestFitExponential->getSSResiduals() + ) + ); + } else { + return array( $bestFitExponential->getSlope(), + $bestFitExponential->getIntersect() + ); + } + } // function LOGEST() + + + /** + * LOGINV + * + * Returns the inverse of the normal cumulative distribution + * + * @param float $probability + * @param float $mean + * @param float $stdDev + * @return float + * + * @todo Try implementing P J Acklam's refinement algorithm for greater + * accuracy if I can get my head round the mathematics + * (as described at) http://home.online.no/~pjacklam/notes/invnorm/ + */ + public static function LOGINV($probability, $mean, $stdDev) { + $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability); + $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean); + $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev); + + if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) { + if (($probability < 0) || ($probability > 1) || ($stdDev <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + return exp($mean + $stdDev * self::NORMSINV($probability)); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function LOGINV() + + + /** + * LOGNORMDIST + * + * Returns the cumulative lognormal distribution of x, where ln(x) is normally distributed + * with parameters mean and standard_dev. + * + * @param float $value + * @param float $mean + * @param float $stdDev + * @return float + */ + public static function LOGNORMDIST($value, $mean, $stdDev) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean); + $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev); + + if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) { + if (($value <= 0) || ($stdDev <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + return self::NORMSDIST((log($value) - $mean) / $stdDev); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function LOGNORMDIST() + + + /** + * MAX + * + * MAX returns the value of the element of the values passed that has the highest value, + * with negative numbers considered smaller than positive numbers. + * + * Excel Function: + * MAX(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function MAX() { + // Return value + $returnValue = null; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + if ((is_null($returnValue)) || ($arg > $returnValue)) { + $returnValue = $arg; + } + } + } + + // Return + if(is_null($returnValue)) { + return 0; + } + return $returnValue; + } // function MAX() + + + /** + * MAXA + * + * Returns the greatest value in a list of arguments, including numbers, text, and logical values + * + * Excel Function: + * MAXA(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function MAXA() { + // Return value + $returnValue = null; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + if ((is_null($returnValue)) || ($arg > $returnValue)) { + $returnValue = $arg; + } + } + } + + // Return + if(is_null($returnValue)) { + return 0; + } + return $returnValue; + } // function MAXA() + + + /** + * MAXIF + * + * Counts the maximum value within a range of cells that contain numbers within the list of arguments + * + * Excel Function: + * MAXIF(value1[,value2[, ...]],condition) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @param string $condition The criteria that defines which cells will be checked. + * @return float + */ + public static function MAXIF($aArgs,$condition,$sumArgs = array()) { + // Return value + $returnValue = null; + + $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs); + $sumArgs = PHPExcel_Calculation_Functions::flattenArray($sumArgs); + if (empty($sumArgs)) { + $sumArgs = $aArgs; + } + $condition = PHPExcel_Calculation_Functions::_ifCondition($condition); + // Loop through arguments + foreach ($aArgs as $key => $arg) { + if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } + $testCondition = '='.$arg.$condition; + if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { + if ((is_null($returnValue)) || ($arg > $returnValue)) { + $returnValue = $arg; + } + } + } + + // Return + return $returnValue; + } // function MAXIF() + + + /** + * MEDIAN + * + * Returns the median of the given numbers. The median is the number in the middle of a set of numbers. + * + * Excel Function: + * MEDIAN(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function MEDIAN() { + // Return value + $returnValue = PHPExcel_Calculation_Functions::NaN(); + + $mArgs = array(); + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $mArgs[] = $arg; + } + } + + $mValueCount = count($mArgs); + if ($mValueCount > 0) { + sort($mArgs,SORT_NUMERIC); + $mValueCount = $mValueCount / 2; + if ($mValueCount == floor($mValueCount)) { + $returnValue = ($mArgs[$mValueCount--] + $mArgs[$mValueCount]) / 2; + } else { + $mValueCount == floor($mValueCount); + $returnValue = $mArgs[$mValueCount]; + } + } + + // Return + return $returnValue; + } // function MEDIAN() + + + /** + * MIN + * + * MIN returns the value of the element of the values passed that has the smallest value, + * with negative numbers considered smaller than positive numbers. + * + * Excel Function: + * MIN(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function MIN() { + // Return value + $returnValue = null; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + if ((is_null($returnValue)) || ($arg < $returnValue)) { + $returnValue = $arg; + } + } + } + + // Return + if(is_null($returnValue)) { + return 0; + } + return $returnValue; + } // function MIN() + + + /** + * MINA + * + * Returns the smallest value in a list of arguments, including numbers, text, and logical values + * + * Excel Function: + * MINA(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function MINA() { + // Return value + $returnValue = null; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) && ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + if ((is_null($returnValue)) || ($arg < $returnValue)) { + $returnValue = $arg; + } + } + } + + // Return + if(is_null($returnValue)) { + return 0; + } + return $returnValue; + } // function MINA() + + + /** + * MINIF + * + * Returns the minimum value within a range of cells that contain numbers within the list of arguments + * + * Excel Function: + * MINIF(value1[,value2[, ...]],condition) + * + * @access public + * @category Mathematical and Trigonometric Functions + * @param mixed $arg,... Data values + * @param string $condition The criteria that defines which cells will be checked. + * @return float + */ + public static function MINIF($aArgs,$condition,$sumArgs = array()) { + // Return value + $returnValue = null; + + $aArgs = PHPExcel_Calculation_Functions::flattenArray($aArgs); + $sumArgs = PHPExcel_Calculation_Functions::flattenArray($sumArgs); + if (empty($sumArgs)) { + $sumArgs = $aArgs; + } + $condition = PHPExcel_Calculation_Functions::_ifCondition($condition); + // Loop through arguments + foreach ($aArgs as $key => $arg) { + if (!is_numeric($arg)) { $arg = PHPExcel_Calculation::_wrapResult(strtoupper($arg)); } + $testCondition = '='.$arg.$condition; + if (PHPExcel_Calculation::getInstance()->_calculateFormulaValue($testCondition)) { + if ((is_null($returnValue)) || ($arg < $returnValue)) { + $returnValue = $arg; + } + } + } + + // Return + return $returnValue; + } // function MINIF() + + + // + // Special variant of array_count_values that isn't limited to strings and integers, + // but can work with floating point numbers as values + // + private static function _modeCalc($data) { + $frequencyArray = array(); + foreach($data as $datum) { + $found = False; + foreach($frequencyArray as $key => $value) { + if ((string) $value['value'] == (string) $datum) { + ++$frequencyArray[$key]['frequency']; + $found = True; + break; + } + } + if (!$found) { + $frequencyArray[] = array('value' => $datum, + 'frequency' => 1 ); + } + } + + foreach($frequencyArray as $key => $value) { + $frequencyList[$key] = $value['frequency']; + $valueList[$key] = $value['value']; + } + array_multisort($frequencyList, SORT_DESC, $valueList, SORT_ASC, SORT_NUMERIC, $frequencyArray); + + if ($frequencyArray[0]['frequency'] == 1) { + return PHPExcel_Calculation_Functions::NA(); + } + return $frequencyArray[0]['value']; + } // function _modeCalc() + + + /** + * MODE + * + * Returns the most frequently occurring, or repetitive, value in an array or range of data + * + * Excel Function: + * MODE(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function MODE() { + // Return value + $returnValue = PHPExcel_Calculation_Functions::NA(); + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + + $mArgs = array(); + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $mArgs[] = $arg; + } + } + + if (!empty($mArgs)) { + return self::_modeCalc($mArgs); + } + + // Return + return $returnValue; + } // function MODE() + + + /** + * NEGBINOMDIST + * + * Returns the negative binomial distribution. NEGBINOMDIST returns the probability that + * there will be number_f failures before the number_s-th success, when the constant + * probability of a success is probability_s. This function is similar to the binomial + * distribution, except that the number of successes is fixed, and the number of trials is + * variable. Like the binomial, trials are assumed to be independent. + * + * @param float $failures Number of Failures + * @param float $successes Threshold number of Successes + * @param float $probability Probability of success on each trial + * @return float + * + */ + public static function NEGBINOMDIST($failures, $successes, $probability) { + $failures = floor(PHPExcel_Calculation_Functions::flattenSingleValue($failures)); + $successes = floor(PHPExcel_Calculation_Functions::flattenSingleValue($successes)); + $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability); + + if ((is_numeric($failures)) && (is_numeric($successes)) && (is_numeric($probability))) { + if (($failures < 0) || ($successes < 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (($probability < 0) || ($probability > 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) { + if (($failures + $successes - 1) <= 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + } + return (PHPExcel_Calculation_MathTrig::COMBIN($failures + $successes - 1,$successes - 1)) * (pow($probability,$successes)) * (pow(1 - $probability,$failures)) ; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function NEGBINOMDIST() + + + /** + * NORMDIST + * + * Returns the normal distribution for the specified mean and standard deviation. This + * function has a very wide range of applications in statistics, including hypothesis + * testing. + * + * @param float $value + * @param float $mean Mean Value + * @param float $stdDev Standard Deviation + * @param boolean $cumulative + * @return float + * + */ + public static function NORMDIST($value, $mean, $stdDev, $cumulative) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean); + $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev); + + if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) { + if ($stdDev < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ((is_numeric($cumulative)) || (is_bool($cumulative))) { + if ($cumulative) { + return 0.5 * (1 + PHPExcel_Calculation_Engineering::_erfVal(($value - $mean) / ($stdDev * sqrt(2)))); + } else { + return (1 / (SQRT2PI * $stdDev)) * exp(0 - (pow($value - $mean,2) / (2 * ($stdDev * $stdDev)))); + } + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function NORMDIST() + + + /** + * NORMINV + * + * Returns the inverse of the normal cumulative distribution for the specified mean and standard deviation. + * + * @param float $value + * @param float $mean Mean Value + * @param float $stdDev Standard Deviation + * @return float + * + */ + public static function NORMINV($probability,$mean,$stdDev) { + $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability); + $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean); + $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev); + + if ((is_numeric($probability)) && (is_numeric($mean)) && (is_numeric($stdDev))) { + if (($probability < 0) || ($probability > 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ($stdDev < 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + return (self::_inverse_ncdf($probability) * $stdDev) + $mean; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function NORMINV() + + + /** + * NORMSDIST + * + * Returns the standard normal cumulative distribution function. The distribution has + * a mean of 0 (zero) and a standard deviation of one. Use this function in place of a + * table of standard normal curve areas. + * + * @param float $value + * @return float + */ + public static function NORMSDIST($value) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + + return self::NORMDIST($value, 0, 1, True); + } // function NORMSDIST() + + + /** + * NORMSINV + * + * Returns the inverse of the standard normal cumulative distribution + * + * @param float $value + * @return float + */ + public static function NORMSINV($value) { + return self::NORMINV($value, 0, 1); + } // function NORMSINV() + + + /** + * PERCENTILE + * + * Returns the nth percentile of values in a range.. + * + * Excel Function: + * PERCENTILE(value1[,value2[, ...]],entry) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @param float $entry Percentile value in the range 0..1, inclusive. + * @return float + */ + public static function PERCENTILE() { + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + + // Calculate + $entry = array_pop($aArgs); + + if ((is_numeric($entry)) && (!is_string($entry))) { + if (($entry < 0) || ($entry > 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $mArgs = array(); + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $mArgs[] = $arg; + } + } + $mValueCount = count($mArgs); + if ($mValueCount > 0) { + sort($mArgs); + $count = self::COUNT($mArgs); + $index = $entry * ($count-1); + $iBase = floor($index); + if ($index == $iBase) { + return $mArgs[$index]; + } else { + $iNext = $iBase + 1; + $iProportion = $index - $iBase; + return $mArgs[$iBase] + (($mArgs[$iNext] - $mArgs[$iBase]) * $iProportion) ; + } + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function PERCENTILE() + + + /** + * PERCENTRANK + * + * Returns the rank of a value in a data set as a percentage of the data set. + * + * @param array of number An array of, or a reference to, a list of numbers. + * @param number The number whose rank you want to find. + * @param number The number of significant digits for the returned percentage value. + * @return float + */ + public static function PERCENTRANK($valueSet,$value,$significance=3) { + $valueSet = PHPExcel_Calculation_Functions::flattenArray($valueSet); + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $significance = (is_null($significance)) ? 3 : (integer) PHPExcel_Calculation_Functions::flattenSingleValue($significance); + + foreach($valueSet as $key => $valueEntry) { + if (!is_numeric($valueEntry)) { + unset($valueSet[$key]); + } + } + sort($valueSet,SORT_NUMERIC); + $valueCount = count($valueSet); + if ($valueCount == 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + + $valueAdjustor = $valueCount - 1; + if (($value < $valueSet[0]) || ($value > $valueSet[$valueAdjustor])) { + return PHPExcel_Calculation_Functions::NA(); + } + + $pos = array_search($value,$valueSet); + if ($pos === False) { + $pos = 0; + $testValue = $valueSet[0]; + while ($testValue < $value) { + $testValue = $valueSet[++$pos]; + } + --$pos; + $pos += (($value - $valueSet[$pos]) / ($testValue - $valueSet[$pos])); + } + + return round($pos / $valueAdjustor,$significance); + } // function PERCENTRANK() + + + /** + * PERMUT + * + * Returns the number of permutations for a given number of objects that can be + * selected from number objects. A permutation is any set or subset of objects or + * events where internal order is significant. Permutations are different from + * combinations, for which the internal order is not significant. Use this function + * for lottery-style probability calculations. + * + * @param int $numObjs Number of different objects + * @param int $numInSet Number of objects in each permutation + * @return int Number of permutations + */ + public static function PERMUT($numObjs,$numInSet) { + $numObjs = PHPExcel_Calculation_Functions::flattenSingleValue($numObjs); + $numInSet = PHPExcel_Calculation_Functions::flattenSingleValue($numInSet); + + if ((is_numeric($numObjs)) && (is_numeric($numInSet))) { + $numInSet = floor($numInSet); + if ($numObjs < $numInSet) { + return PHPExcel_Calculation_Functions::NaN(); + } + return round(PHPExcel_Calculation_MathTrig::FACT($numObjs) / PHPExcel_Calculation_MathTrig::FACT($numObjs - $numInSet)); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function PERMUT() + + + /** + * POISSON + * + * Returns the Poisson distribution. A common application of the Poisson distribution + * is predicting the number of events over a specific time, such as the number of + * cars arriving at a toll plaza in 1 minute. + * + * @param float $value + * @param float $mean Mean Value + * @param boolean $cumulative + * @return float + * + */ + public static function POISSON($value, $mean, $cumulative) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean); + + if ((is_numeric($value)) && (is_numeric($mean))) { + if (($value <= 0) || ($mean <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ((is_numeric($cumulative)) || (is_bool($cumulative))) { + if ($cumulative) { + $summer = 0; + for ($i = 0; $i <= floor($value); ++$i) { + $summer += pow($mean,$i) / PHPExcel_Calculation_MathTrig::FACT($i); + } + return exp(0-$mean) * $summer; + } else { + return (exp(0-$mean) * pow($mean,$value)) / PHPExcel_Calculation_MathTrig::FACT($value); + } + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function POISSON() + + + /** + * QUARTILE + * + * Returns the quartile of a data set. + * + * Excel Function: + * QUARTILE(value1[,value2[, ...]],entry) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @param int $entry Quartile value in the range 1..3, inclusive. + * @return float + */ + public static function QUARTILE() { + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + + // Calculate + $entry = floor(array_pop($aArgs)); + + if ((is_numeric($entry)) && (!is_string($entry))) { + $entry /= 4; + if (($entry < 0) || ($entry > 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + return self::PERCENTILE($aArgs,$entry); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function QUARTILE() + + + /** + * RANK + * + * Returns the rank of a number in a list of numbers. + * + * @param number The number whose rank you want to find. + * @param array of number An array of, or a reference to, a list of numbers. + * @param mixed Order to sort the values in the value set + * @return float + */ + public static function RANK($value,$valueSet,$order=0) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $valueSet = PHPExcel_Calculation_Functions::flattenArray($valueSet); + $order = (is_null($order)) ? 0 : (integer) PHPExcel_Calculation_Functions::flattenSingleValue($order); + + foreach($valueSet as $key => $valueEntry) { + if (!is_numeric($valueEntry)) { + unset($valueSet[$key]); + } + } + + if ($order == 0) { + rsort($valueSet,SORT_NUMERIC); + } else { + sort($valueSet,SORT_NUMERIC); + } + $pos = array_search($value,$valueSet); + if ($pos === False) { + return PHPExcel_Calculation_Functions::NA(); + } + + return ++$pos; + } // function RANK() + + + /** + * RSQ + * + * Returns the square of the Pearson product moment correlation coefficient through data points in known_y's and known_x's. + * + * @param array of mixed Data Series Y + * @param array of mixed Data Series X + * @return float + */ + public static function RSQ($yValues,$xValues) { + if (!self::_checkTrendArrays($yValues,$xValues)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $yValueCount = count($yValues); + $xValueCount = count($xValues); + + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { + return PHPExcel_Calculation_Functions::NA(); + } elseif ($yValueCount == 1) { + return PHPExcel_Calculation_Functions::DIV0(); + } + + $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues); + return $bestFitLinear->getGoodnessOfFit(); + } // function RSQ() + + + /** + * SKEW + * + * Returns the skewness of a distribution. Skewness characterizes the degree of asymmetry + * of a distribution around its mean. Positive skewness indicates a distribution with an + * asymmetric tail extending toward more positive values. Negative skewness indicates a + * distribution with an asymmetric tail extending toward more negative values. + * + * @param array Data Series + * @return float + */ + public static function SKEW() { + $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()); + $mean = self::AVERAGE($aArgs); + $stdDev = self::STDEV($aArgs); + + $count = $summer = 0; + // Loop through arguments + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!PHPExcel_Calculation_Functions::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $summer += pow((($arg - $mean) / $stdDev),3) ; + ++$count; + } + } + } + + // Return + if ($count > 2) { + return $summer * ($count / (($count-1) * ($count-2))); + } + return PHPExcel_Calculation_Functions::DIV0(); + } // function SKEW() + + + /** + * SLOPE + * + * Returns the slope of the linear regression line through data points in known_y's and known_x's. + * + * @param array of mixed Data Series Y + * @param array of mixed Data Series X + * @return float + */ + public static function SLOPE($yValues,$xValues) { + if (!self::_checkTrendArrays($yValues,$xValues)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $yValueCount = count($yValues); + $xValueCount = count($xValues); + + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { + return PHPExcel_Calculation_Functions::NA(); + } elseif ($yValueCount == 1) { + return PHPExcel_Calculation_Functions::DIV0(); + } + + $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues); + return $bestFitLinear->getSlope(); + } // function SLOPE() + + + /** + * SMALL + * + * Returns the nth smallest value in a data set. You can use this function to + * select a value based on its relative standing. + * + * Excel Function: + * SMALL(value1[,value2[, ...]],entry) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @param int $entry Position (ordered from the smallest) in the array or range of data to return + * @return float + */ + public static function SMALL() { + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + + // Calculate + $entry = array_pop($aArgs); + + if ((is_numeric($entry)) && (!is_string($entry))) { + $mArgs = array(); + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $mArgs[] = $arg; + } + } + $count = self::COUNT($mArgs); + $entry = floor(--$entry); + if (($entry < 0) || ($entry >= $count) || ($count == 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + sort($mArgs); + return $mArgs[$entry]; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function SMALL() + + + /** + * STANDARDIZE + * + * Returns a normalized value from a distribution characterized by mean and standard_dev. + * + * @param float $value Value to normalize + * @param float $mean Mean Value + * @param float $stdDev Standard Deviation + * @return float Standardized value + */ + public static function STANDARDIZE($value,$mean,$stdDev) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $mean = PHPExcel_Calculation_Functions::flattenSingleValue($mean); + $stdDev = PHPExcel_Calculation_Functions::flattenSingleValue($stdDev); + + if ((is_numeric($value)) && (is_numeric($mean)) && (is_numeric($stdDev))) { + if ($stdDev <= 0) { + return PHPExcel_Calculation_Functions::NaN(); + } + return ($value - $mean) / $stdDev ; + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function STANDARDIZE() + + + /** + * STDEV + * + * Estimates standard deviation based on a sample. The standard deviation is a measure of how + * widely values are dispersed from the average value (the mean). + * + * Excel Function: + * STDEV(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function STDEV() { + $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()); + + // Return value + $returnValue = null; + + $aMean = self::AVERAGE($aArgs); + if (!is_null($aMean)) { + $aCount = -1; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; + } + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + if (is_null($returnValue)) { + $returnValue = pow(($arg - $aMean),2); + } else { + $returnValue += pow(($arg - $aMean),2); + } + ++$aCount; + } + } + + // Return + if (($aCount > 0) && ($returnValue >= 0)) { + return sqrt($returnValue / $aCount); + } + } + return PHPExcel_Calculation_Functions::DIV0(); + } // function STDEV() + + + /** + * STDEVA + * + * Estimates standard deviation based on a sample, including numbers, text, and logical values + * + * Excel Function: + * STDEVA(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function STDEVA() { + $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()); + + // Return value + $returnValue = null; + + $aMean = self::AVERAGEA($aArgs); + if (!is_null($aMean)) { + $aCount = -1; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!PHPExcel_Calculation_Functions::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + if (is_null($returnValue)) { + $returnValue = pow(($arg - $aMean),2); + } else { + $returnValue += pow(($arg - $aMean),2); + } + ++$aCount; + } + } + } + + // Return + if (($aCount > 0) && ($returnValue >= 0)) { + return sqrt($returnValue / $aCount); + } + } + return PHPExcel_Calculation_Functions::DIV0(); + } // function STDEVA() + + + /** + * STDEVP + * + * Calculates standard deviation based on the entire population + * + * Excel Function: + * STDEVP(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function STDEVP() { + $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()); + + // Return value + $returnValue = null; + + $aMean = self::AVERAGE($aArgs); + if (!is_null($aMean)) { + $aCount = 0; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + ((!PHPExcel_Calculation_Functions::isCellValue($k)) || (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE))) { + $arg = (integer) $arg; + } + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + if (is_null($returnValue)) { + $returnValue = pow(($arg - $aMean),2); + } else { + $returnValue += pow(($arg - $aMean),2); + } + ++$aCount; + } + } + + // Return + if (($aCount > 0) && ($returnValue >= 0)) { + return sqrt($returnValue / $aCount); + } + } + return PHPExcel_Calculation_Functions::DIV0(); + } // function STDEVP() + + + /** + * STDEVPA + * + * Calculates standard deviation based on the entire population, including numbers, text, and logical values + * + * Excel Function: + * STDEVPA(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function STDEVPA() { + $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()); + + // Return value + $returnValue = null; + + $aMean = self::AVERAGEA($aArgs); + if (!is_null($aMean)) { + $aCount = 0; + foreach ($aArgs as $k => $arg) { + if ((is_bool($arg)) && + (!PHPExcel_Calculation_Functions::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + if (is_null($returnValue)) { + $returnValue = pow(($arg - $aMean),2); + } else { + $returnValue += pow(($arg - $aMean),2); + } + ++$aCount; + } + } + } + + // Return + if (($aCount > 0) && ($returnValue >= 0)) { + return sqrt($returnValue / $aCount); + } + } + return PHPExcel_Calculation_Functions::DIV0(); + } // function STDEVPA() + + + /** + * STEYX + * + * Returns the standard error of the predicted y-value for each x in the regression. + * + * @param array of mixed Data Series Y + * @param array of mixed Data Series X + * @return float + */ + public static function STEYX($yValues,$xValues) { + if (!self::_checkTrendArrays($yValues,$xValues)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + $yValueCount = count($yValues); + $xValueCount = count($xValues); + + if (($yValueCount == 0) || ($yValueCount != $xValueCount)) { + return PHPExcel_Calculation_Functions::NA(); + } elseif ($yValueCount == 1) { + return PHPExcel_Calculation_Functions::DIV0(); + } + + $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues); + return $bestFitLinear->getStdevOfResiduals(); + } // function STEYX() + + + /** + * TDIST + * + * Returns the probability of Student's T distribution. + * + * @param float $value Value for the function + * @param float $degrees degrees of freedom + * @param float $tails number of tails (1 or 2) + * @return float + */ + public static function TDIST($value, $degrees, $tails) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees)); + $tails = floor(PHPExcel_Calculation_Functions::flattenSingleValue($tails)); + + if ((is_numeric($value)) && (is_numeric($degrees)) && (is_numeric($tails))) { + if (($value < 0) || ($degrees < 1) || ($tails < 1) || ($tails > 2)) { + return PHPExcel_Calculation_Functions::NaN(); + } + // tdist, which finds the probability that corresponds to a given value + // of t with k degrees of freedom. This algorithm is translated from a + // pascal function on p81 of "Statistical Computing in Pascal" by D + // Cooke, A H Craven & G M Clark (1985: Edward Arnold (Pubs.) Ltd: + // London). The above Pascal algorithm is itself a translation of the + // fortran algoritm "AS 3" by B E Cooper of the Atlas Computer + // Laboratory as reported in (among other places) "Applied Statistics + // Algorithms", editied by P Griffiths and I D Hill (1985; Ellis + // Horwood Ltd.; W. Sussex, England). + $tterm = $degrees; + $ttheta = atan2($value,sqrt($tterm)); + $tc = cos($ttheta); + $ts = sin($ttheta); + $tsum = 0; + + if (($degrees % 2) == 1) { + $ti = 3; + $tterm = $tc; + } else { + $ti = 2; + $tterm = 1; + } + + $tsum = $tterm; + while ($ti < $degrees) { + $tterm *= $tc * $tc * ($ti - 1) / $ti; + $tsum += $tterm; + $ti += 2; + } + $tsum *= $ts; + if (($degrees % 2) == 1) { $tsum = M_2DIVPI * ($tsum + $ttheta); } + $tValue = 0.5 * (1 + $tsum); + if ($tails == 1) { + return 1 - abs($tValue); + } else { + return 1 - abs((1 - $tValue) - $tValue); + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function TDIST() + + + /** + * TINV + * + * Returns the one-tailed probability of the chi-squared distribution. + * + * @param float $probability Probability for the function + * @param float $degrees degrees of freedom + * @return float + */ + public static function TINV($probability, $degrees) { + $probability = PHPExcel_Calculation_Functions::flattenSingleValue($probability); + $degrees = floor(PHPExcel_Calculation_Functions::flattenSingleValue($degrees)); + + if ((is_numeric($probability)) && (is_numeric($degrees))) { + $xLo = 100; + $xHi = 0; + + $x = $xNew = 1; + $dx = 1; + $i = 0; + + while ((abs($dx) > PRECISION) && ($i++ < MAX_ITERATIONS)) { + // Apply Newton-Raphson step + $result = self::TDIST($x, $degrees, 2); + $error = $result - $probability; + if ($error == 0.0) { + $dx = 0; + } elseif ($error < 0.0) { + $xLo = $x; + } else { + $xHi = $x; + } + // Avoid division by zero + if ($result != 0.0) { + $dx = $error / $result; + $xNew = $x - $dx; + } + // If the NR fails to converge (which for example may be the + // case if the initial guess is too rough) we apply a bisection + // step to determine a more narrow interval around the root. + if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) { + $xNew = ($xLo + $xHi) / 2; + $dx = $xNew - $x; + } + $x = $xNew; + } + if ($i == MAX_ITERATIONS) { + return PHPExcel_Calculation_Functions::NA(); + } + return round($x,12); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function TINV() + + + /** + * TREND + * + * Returns values along a linear trend + * + * @param array of mixed Data Series Y + * @param array of mixed Data Series X + * @param array of mixed Values of X for which we want to find Y + * @param boolean A logical value specifying whether to force the intersect to equal 0. + * @return array of float + */ + public static function TREND($yValues,$xValues=array(),$newValues=array(),$const=True) { + $yValues = PHPExcel_Calculation_Functions::flattenArray($yValues); + $xValues = PHPExcel_Calculation_Functions::flattenArray($xValues); + $newValues = PHPExcel_Calculation_Functions::flattenArray($newValues); + $const = (is_null($const)) ? True : (boolean) PHPExcel_Calculation_Functions::flattenSingleValue($const); + + $bestFitLinear = trendClass::calculate(trendClass::TREND_LINEAR,$yValues,$xValues,$const); + if (empty($newValues)) { + $newValues = $bestFitLinear->getXValues(); + } + + $returnArray = array(); + foreach($newValues as $xValue) { + $returnArray[0][] = $bestFitLinear->getValueOfYForX($xValue); + } + + return $returnArray; + } // function TREND() + + + /** + * TRIMMEAN + * + * Returns the mean of the interior of a data set. TRIMMEAN calculates the mean + * taken by excluding a percentage of data points from the top and bottom tails + * of a data set. + * + * Excel Function: + * TRIMEAN(value1[,value2[, ...]],$discard) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @param float $discard Percentage to discard + * @return float + */ + public static function TRIMMEAN() { + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + + // Calculate + $percent = array_pop($aArgs); + + if ((is_numeric($percent)) && (!is_string($percent))) { + if (($percent < 0) || ($percent > 1)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $mArgs = array(); + foreach ($aArgs as $arg) { + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $mArgs[] = $arg; + } + } + $discard = floor(self::COUNT($mArgs) * $percent / 2); + sort($mArgs); + for ($i=0; $i < $discard; ++$i) { + array_pop($mArgs); + array_shift($mArgs); + } + return self::AVERAGE($mArgs); + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function TRIMMEAN() + + + /** + * VARFunc + * + * Estimates variance based on a sample. + * + * Excel Function: + * VAR(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function VARFunc() { + // Return value + $returnValue = PHPExcel_Calculation_Functions::DIV0(); + + $summerA = $summerB = 0; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + $aCount = 0; + foreach ($aArgs as $arg) { + if (is_bool($arg)) { $arg = (integer) $arg; } + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $summerA += ($arg * $arg); + $summerB += $arg; + ++$aCount; + } + } + + // Return + if ($aCount > 1) { + $summerA *= $aCount; + $summerB *= $summerB; + $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1)); + } + return $returnValue; + } // function VARFunc() + + + /** + * VARA + * + * Estimates variance based on a sample, including numbers, text, and logical values + * + * Excel Function: + * VARA(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function VARA() { + // Return value + $returnValue = PHPExcel_Calculation_Functions::DIV0(); + + $summerA = $summerB = 0; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()); + $aCount = 0; + foreach ($aArgs as $k => $arg) { + if ((is_string($arg)) && + (PHPExcel_Calculation_Functions::isValue($k))) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif ((is_string($arg)) && + (!PHPExcel_Calculation_Functions::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + $summerA += ($arg * $arg); + $summerB += $arg; + ++$aCount; + } + } + } + + // Return + if ($aCount > 1) { + $summerA *= $aCount; + $summerB *= $summerB; + $returnValue = ($summerA - $summerB) / ($aCount * ($aCount - 1)); + } + return $returnValue; + } // function VARA() + + + /** + * VARP + * + * Calculates variance based on the entire population + * + * Excel Function: + * VARP(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function VARP() { + // Return value + $returnValue = PHPExcel_Calculation_Functions::DIV0(); + + $summerA = $summerB = 0; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + $aCount = 0; + foreach ($aArgs as $arg) { + if (is_bool($arg)) { $arg = (integer) $arg; } + // Is it a numeric value? + if ((is_numeric($arg)) && (!is_string($arg))) { + $summerA += ($arg * $arg); + $summerB += $arg; + ++$aCount; + } + } + + // Return + if ($aCount > 0) { + $summerA *= $aCount; + $summerB *= $summerB; + $returnValue = ($summerA - $summerB) / ($aCount * $aCount); + } + return $returnValue; + } // function VARP() + + + /** + * VARPA + * + * Calculates variance based on the entire population, including numbers, text, and logical values + * + * Excel Function: + * VARPA(value1[,value2[, ...]]) + * + * @access public + * @category Statistical Functions + * @param mixed $arg,... Data values + * @return float + */ + public static function VARPA() { + // Return value + $returnValue = PHPExcel_Calculation_Functions::DIV0(); + + $summerA = $summerB = 0; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArrayIndexed(func_get_args()); + $aCount = 0; + foreach ($aArgs as $k => $arg) { + if ((is_string($arg)) && + (PHPExcel_Calculation_Functions::isValue($k))) { + return PHPExcel_Calculation_Functions::VALUE(); + } elseif ((is_string($arg)) && + (!PHPExcel_Calculation_Functions::isMatrixValue($k))) { + } else { + // Is it a numeric value? + if ((is_numeric($arg)) || (is_bool($arg)) || ((is_string($arg) & ($arg != '')))) { + if (is_bool($arg)) { + $arg = (integer) $arg; + } elseif (is_string($arg)) { + $arg = 0; + } + $summerA += ($arg * $arg); + $summerB += $arg; + ++$aCount; + } + } + } + + // Return + if ($aCount > 0) { + $summerA *= $aCount; + $summerB *= $summerB; + $returnValue = ($summerA - $summerB) / ($aCount * $aCount); + } + return $returnValue; + } // function VARPA() + + + /** + * WEIBULL + * + * Returns the Weibull distribution. Use this distribution in reliability + * analysis, such as calculating a device's mean time to failure. + * + * @param float $value + * @param float $alpha Alpha Parameter + * @param float $beta Beta Parameter + * @param boolean $cumulative + * @return float + * + */ + public static function WEIBULL($value, $alpha, $beta, $cumulative) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $alpha = PHPExcel_Calculation_Functions::flattenSingleValue($alpha); + $beta = PHPExcel_Calculation_Functions::flattenSingleValue($beta); + + if ((is_numeric($value)) && (is_numeric($alpha)) && (is_numeric($beta))) { + if (($value < 0) || ($alpha <= 0) || ($beta <= 0)) { + return PHPExcel_Calculation_Functions::NaN(); + } + if ((is_numeric($cumulative)) || (is_bool($cumulative))) { + if ($cumulative) { + return 1 - exp(0 - pow($value / $beta,$alpha)); + } else { + return ($alpha / pow($beta,$alpha)) * pow($value,$alpha - 1) * exp(0 - pow($value / $beta,$alpha)); + } + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function WEIBULL() + + + /** + * ZTEST + * + * Returns the Weibull distribution. Use this distribution in reliability + * analysis, such as calculating a device's mean time to failure. + * + * @param float $dataSet + * @param float $m0 Alpha Parameter + * @param float $sigma Beta Parameter + * @param boolean $cumulative + * @return float + * + */ + public static function ZTEST($dataSet, $m0, $sigma = NULL) { + $dataSet = PHPExcel_Calculation_Functions::flattenArrayIndexed($dataSet); + $m0 = PHPExcel_Calculation_Functions::flattenSingleValue($m0); + $sigma = PHPExcel_Calculation_Functions::flattenSingleValue($sigma); + + if (is_null($sigma)) { + $sigma = self::STDEV($dataSet); + } + $n = count($dataSet); + + return 1 - self::NORMSDIST((self::AVERAGE($dataSet) - $m0)/($sigma/SQRT($n))); + } // function ZTEST() + +} // class PHPExcel_Calculation_Statistical diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/TextData.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/TextData.php new file mode 100755 index 0000000..101149a --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/TextData.php @@ -0,0 +1,589 @@ +=0 && ord($c{0}) <= 127) + return ord($c{0}); + if (ord($c{0}) >= 192 && ord($c{0}) <= 223) + return (ord($c{0})-192)*64 + (ord($c{1})-128); + if (ord($c{0}) >= 224 && ord($c{0}) <= 239) + return (ord($c{0})-224)*4096 + (ord($c{1})-128)*64 + (ord($c{2})-128); + if (ord($c{0}) >= 240 && ord($c{0}) <= 247) + return (ord($c{0})-240)*262144 + (ord($c{1})-128)*4096 + (ord($c{2})-128)*64 + (ord($c{3})-128); + if (ord($c{0}) >= 248 && ord($c{0}) <= 251) + return (ord($c{0})-248)*16777216 + (ord($c{1})-128)*262144 + (ord($c{2})-128)*4096 + (ord($c{3})-128)*64 + (ord($c{4})-128); + if (ord($c{0}) >= 252 && ord($c{0}) <= 253) + return (ord($c{0})-252)*1073741824 + (ord($c{1})-128)*16777216 + (ord($c{2})-128)*262144 + (ord($c{3})-128)*4096 + (ord($c{4})-128)*64 + (ord($c{5})-128); + if (ord($c{0}) >= 254 && ord($c{0}) <= 255) //error + return PHPExcel_Calculation_Functions::VALUE(); + return 0; + } // function _uniord() + + /** + * CHARACTER + * + * @param string $character Value + * @return int + */ + public static function CHARACTER($character) { + $character = PHPExcel_Calculation_Functions::flattenSingleValue($character); + + if ((!is_numeric($character)) || ($character < 0)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (function_exists('mb_convert_encoding')) { + return mb_convert_encoding('&#'.intval($character).';', 'UTF-8', 'HTML-ENTITIES'); + } else { + return chr(intval($character)); + } + } + + + /** + * TRIMNONPRINTABLE + * + * @param mixed $stringValue Value to check + * @return string + */ + public static function TRIMNONPRINTABLE($stringValue = '') { + $stringValue = PHPExcel_Calculation_Functions::flattenSingleValue($stringValue); + + if (is_bool($stringValue)) { + return ($stringValue) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + + if (self::$_invalidChars == Null) { + self::$_invalidChars = range(chr(0),chr(31)); + } + + if (is_string($stringValue) || is_numeric($stringValue)) { + return str_replace(self::$_invalidChars,'',trim($stringValue,"\x00..\x1F")); + } + return NULL; + } // function TRIMNONPRINTABLE() + + + /** + * TRIMSPACES + * + * @param mixed $stringValue Value to check + * @return string + */ + public static function TRIMSPACES($stringValue = '') { + $stringValue = PHPExcel_Calculation_Functions::flattenSingleValue($stringValue); + + if (is_bool($stringValue)) { + return ($stringValue) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + + if (is_string($stringValue) || is_numeric($stringValue)) { + return trim(preg_replace('/ +/',' ',trim($stringValue,' '))); + } + return NULL; + } // function TRIMSPACES() + + + /** + * ASCIICODE + * + * @param string $characters Value + * @return int + */ + public static function ASCIICODE($characters) { + if (($characters === NULL) || ($characters === '')) + return PHPExcel_Calculation_Functions::VALUE(); + $characters = PHPExcel_Calculation_Functions::flattenSingleValue($characters); + if (is_bool($characters)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + $characters = (int) $characters; + } else { + $characters = ($characters) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + } + + $character = $characters; + if ((function_exists('mb_strlen')) && (function_exists('mb_substr'))) { + if (mb_strlen($characters, 'UTF-8') > 1) { $character = mb_substr($characters, 0, 1, 'UTF-8'); } + return self::_uniord($character); + } else { + if (strlen($characters) > 0) { $character = substr($characters, 0, 1); } + return ord($character); + } + } // function ASCIICODE() + + + /** + * CONCATENATE + * + * @return string + */ + public static function CONCATENATE() { + // Return value + $returnValue = ''; + + // Loop through arguments + $aArgs = PHPExcel_Calculation_Functions::flattenArray(func_get_args()); + foreach ($aArgs as $arg) { + if (is_bool($arg)) { + if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_OPENOFFICE) { + $arg = (int) $arg; + } else { + $arg = ($arg) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + } + $returnValue .= $arg; + } + + // Return + return $returnValue; + } // function CONCATENATE() + + + /** + * DOLLAR + * + * This function converts a number to text using currency format, with the decimals rounded to the specified place. + * The format used is $#,##0.00_);($#,##0.00).. + * + * @param float $value The value to format + * @param int $decimals The number of digits to display to the right of the decimal point. + * If decimals is negative, number is rounded to the left of the decimal point. + * If you omit decimals, it is assumed to be 2 + * @return string + */ + public static function DOLLAR($value = 0, $decimals = 2) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $decimals = is_null($decimals) ? 0 : PHPExcel_Calculation_Functions::flattenSingleValue($decimals); + + // Validate parameters + if (!is_numeric($value) || !is_numeric($decimals)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $decimals = floor($decimals); + + if ($decimals > 0) { + return money_format('%.'.$decimals.'n',$value); + } else { + $round = pow(10,abs($decimals)); + if ($value < 0) { $round = 0-$round; } + $value = PHPExcel_Calculation_MathTrig::MROUND($value,$round); + // The implementation of money_format used if the standard PHP function is not available can't handle decimal places of 0, + // so we display to 1 dp and chop off that character and the decimal separator using substr + return substr(money_format('%.1n',$value),0,-2); + } + } // function DOLLAR() + + + /** + * SEARCHSENSITIVE + * + * @param string $needle The string to look for + * @param string $haystack The string in which to look + * @param int $offset Offset within $haystack + * @return string + */ + public static function SEARCHSENSITIVE($needle,$haystack,$offset=1) { + $needle = PHPExcel_Calculation_Functions::flattenSingleValue($needle); + $haystack = PHPExcel_Calculation_Functions::flattenSingleValue($haystack); + $offset = PHPExcel_Calculation_Functions::flattenSingleValue($offset); + + if (!is_bool($needle)) { + if (is_bool($haystack)) { + $haystack = ($haystack) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + + if (($offset > 0) && (PHPExcel_Shared_String::CountCharacters($haystack) > $offset)) { + if (PHPExcel_Shared_String::CountCharacters($needle) == 0) { + return $offset; + } + if (function_exists('mb_strpos')) { + $pos = mb_strpos($haystack, $needle, --$offset, 'UTF-8'); + } else { + $pos = strpos($haystack, $needle, --$offset); + } + if ($pos !== false) { + return ++$pos; + } + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function SEARCHSENSITIVE() + + + /** + * SEARCHINSENSITIVE + * + * @param string $needle The string to look for + * @param string $haystack The string in which to look + * @param int $offset Offset within $haystack + * @return string + */ + public static function SEARCHINSENSITIVE($needle,$haystack,$offset=1) { + $needle = PHPExcel_Calculation_Functions::flattenSingleValue($needle); + $haystack = PHPExcel_Calculation_Functions::flattenSingleValue($haystack); + $offset = PHPExcel_Calculation_Functions::flattenSingleValue($offset); + + if (!is_bool($needle)) { + if (is_bool($haystack)) { + $haystack = ($haystack) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + + if (($offset > 0) && (PHPExcel_Shared_String::CountCharacters($haystack) > $offset)) { + if (PHPExcel_Shared_String::CountCharacters($needle) == 0) { + return $offset; + } + if (function_exists('mb_stripos')) { + $pos = mb_stripos($haystack, $needle, --$offset,'UTF-8'); + } else { + $pos = stripos($haystack, $needle, --$offset); + } + if ($pos !== false) { + return ++$pos; + } + } + } + return PHPExcel_Calculation_Functions::VALUE(); + } // function SEARCHINSENSITIVE() + + + /** + * FIXEDFORMAT + * + * @param mixed $value Value to check + * @param integer $decimals + * @param boolean $no_commas + * @return boolean + */ + public static function FIXEDFORMAT($value, $decimals = 2, $no_commas = FALSE) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $decimals = PHPExcel_Calculation_Functions::flattenSingleValue($decimals); + $no_commas = PHPExcel_Calculation_Functions::flattenSingleValue($no_commas); + + // Validate parameters + if (!is_numeric($value) || !is_numeric($decimals)) { + return PHPExcel_Calculation_Functions::NaN(); + } + $decimals = floor($decimals); + + $valueResult = round($value,$decimals); + if ($decimals < 0) { $decimals = 0; } + if (!$no_commas) { + $valueResult = number_format($valueResult,$decimals); + } + + return (string) $valueResult; + } // function FIXEDFORMAT() + + + /** + * LEFT + * + * @param string $value Value + * @param int $chars Number of characters + * @return string + */ + public static function LEFT($value = '', $chars = 1) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); + + if ($chars < 0) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (is_bool($value)) { + $value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + + if (function_exists('mb_substr')) { + return mb_substr($value, 0, $chars, 'UTF-8'); + } else { + return substr($value, 0, $chars); + } + } // function LEFT() + + + /** + * MID + * + * @param string $value Value + * @param int $start Start character + * @param int $chars Number of characters + * @return string + */ + public static function MID($value = '', $start = 1, $chars = null) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $start = PHPExcel_Calculation_Functions::flattenSingleValue($start); + $chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); + + if (($start < 1) || ($chars < 0)) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (is_bool($value)) { + $value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + + if (function_exists('mb_substr')) { + return mb_substr($value, --$start, $chars, 'UTF-8'); + } else { + return substr($value, --$start, $chars); + } + } // function MID() + + + /** + * RIGHT + * + * @param string $value Value + * @param int $chars Number of characters + * @return string + */ + public static function RIGHT($value = '', $chars = 1) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); + + if ($chars < 0) { + return PHPExcel_Calculation_Functions::VALUE(); + } + + if (is_bool($value)) { + $value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + + if ((function_exists('mb_substr')) && (function_exists('mb_strlen'))) { + return mb_substr($value, mb_strlen($value, 'UTF-8') - $chars, $chars, 'UTF-8'); + } else { + return substr($value, strlen($value) - $chars); + } + } // function RIGHT() + + + /** + * STRINGLENGTH + * + * @param string $value Value + * @return string + */ + public static function STRINGLENGTH($value = '') { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + + if (is_bool($value)) { + $value = ($value) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + + if (function_exists('mb_strlen')) { + return mb_strlen($value, 'UTF-8'); + } else { + return strlen($value); + } + } // function STRINGLENGTH() + + + /** + * LOWERCASE + * + * Converts a string value to upper case. + * + * @param string $mixedCaseString + * @return string + */ + public static function LOWERCASE($mixedCaseString) { + $mixedCaseString = PHPExcel_Calculation_Functions::flattenSingleValue($mixedCaseString); + + if (is_bool($mixedCaseString)) { + $mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + + return PHPExcel_Shared_String::StrToLower($mixedCaseString); + } // function LOWERCASE() + + + /** + * UPPERCASE + * + * Converts a string value to upper case. + * + * @param string $mixedCaseString + * @return string + */ + public static function UPPERCASE($mixedCaseString) { + $mixedCaseString = PHPExcel_Calculation_Functions::flattenSingleValue($mixedCaseString); + + if (is_bool($mixedCaseString)) { + $mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + + return PHPExcel_Shared_String::StrToUpper($mixedCaseString); + } // function UPPERCASE() + + + /** + * PROPERCASE + * + * Converts a string value to upper case. + * + * @param string $mixedCaseString + * @return string + */ + public static function PROPERCASE($mixedCaseString) { + $mixedCaseString = PHPExcel_Calculation_Functions::flattenSingleValue($mixedCaseString); + + if (is_bool($mixedCaseString)) { + $mixedCaseString = ($mixedCaseString) ? PHPExcel_Calculation::getTRUE() : PHPExcel_Calculation::getFALSE(); + } + + return PHPExcel_Shared_String::StrToTitle($mixedCaseString); + } // function PROPERCASE() + + + /** + * REPLACE + * + * @param string $oldText String to modify + * @param int $start Start character + * @param int $chars Number of characters + * @param string $newText String to replace in defined position + * @return string + */ + public static function REPLACE($oldText = '', $start = 1, $chars = null, $newText) { + $oldText = PHPExcel_Calculation_Functions::flattenSingleValue($oldText); + $start = PHPExcel_Calculation_Functions::flattenSingleValue($start); + $chars = PHPExcel_Calculation_Functions::flattenSingleValue($chars); + $newText = PHPExcel_Calculation_Functions::flattenSingleValue($newText); + + $left = self::LEFT($oldText,$start-1); + $right = self::RIGHT($oldText,self::STRINGLENGTH($oldText)-($start+$chars)+1); + + return $left.$newText.$right; + } // function REPLACE() + + + /** + * SUBSTITUTE + * + * @param string $text Value + * @param string $fromText From Value + * @param string $toText To Value + * @param integer $instance Instance Number + * @return string + */ + public static function SUBSTITUTE($text = '', $fromText = '', $toText = '', $instance = 0) { + $text = PHPExcel_Calculation_Functions::flattenSingleValue($text); + $fromText = PHPExcel_Calculation_Functions::flattenSingleValue($fromText); + $toText = PHPExcel_Calculation_Functions::flattenSingleValue($toText); + $instance = floor(PHPExcel_Calculation_Functions::flattenSingleValue($instance)); + + if ($instance == 0) { + if(function_exists('mb_str_replace')) { + return mb_str_replace($fromText,$toText,$text); + } else { + return str_replace($fromText,$toText,$text); + } + } else { + $pos = -1; + while($instance > 0) { + if (function_exists('mb_strpos')) { + $pos = mb_strpos($text, $fromText, $pos+1, 'UTF-8'); + } else { + $pos = strpos($text, $fromText, $pos+1); + } + if ($pos === false) { + break; + } + --$instance; + } + if ($pos !== false) { + if (function_exists('mb_strlen')) { + return self::REPLACE($text,++$pos,mb_strlen($fromText, 'UTF-8'),$toText); + } else { + return self::REPLACE($text,++$pos,strlen($fromText),$toText); + } + } + } + + return $text; + } // function SUBSTITUTE() + + + /** + * RETURNSTRING + * + * @param mixed $testValue Value to check + * @return boolean + */ + public static function RETURNSTRING($testValue = '') { + $testValue = PHPExcel_Calculation_Functions::flattenSingleValue($testValue); + + if (is_string($testValue)) { + return $testValue; + } + return Null; + } // function RETURNSTRING() + + + /** + * TEXTFORMAT + * + * @param mixed $value Value to check + * @param string $format Format mask to use + * @return boolean + */ + public static function TEXTFORMAT($value,$format) { + $value = PHPExcel_Calculation_Functions::flattenSingleValue($value); + $format = PHPExcel_Calculation_Functions::flattenSingleValue($format); + + if ((is_string($value)) && (!is_numeric($value)) && PHPExcel_Shared_Date::isDateTimeFormatCode($format)) { + $value = PHPExcel_Calculation_DateTime::DATEVALUE($value); + } + + return (string) PHPExcel_Style_NumberFormat::toFormattedString($value,$format); + } // function TEXTFORMAT() + +} // class PHPExcel_Calculation_TextData diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Token/Stack.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Token/Stack.php new file mode 100755 index 0000000..4466199 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/Token/Stack.php @@ -0,0 +1,115 @@ +_count; + } // function count() + + /** + * Push a new entry onto the stack + * + * @param mixed $type + * @param mixed $value + * @param mixed $reference + */ + public function push($type, $value, $reference = NULL) { + $this->_stack[$this->_count++] = array('type' => $type, + 'value' => $value, + 'reference' => $reference + ); + if ($type == 'Function') { + $localeFunction = PHPExcel_Calculation::_localeFunc($value); + if ($localeFunction != $value) { + $this->_stack[($this->_count - 1)]['localeValue'] = $localeFunction; + } + } + } // function push() + + /** + * Pop the last entry from the stack + * + * @return mixed + */ + public function pop() { + if ($this->_count > 0) { + return $this->_stack[--$this->_count]; + } + return NULL; + } // function pop() + + /** + * Return an entry from the stack without removing it + * + * @param integer $n number indicating how far back in the stack we want to look + * @return mixed + */ + public function last($n = 1) { + if ($this->_count - $n < 0) { + return NULL; + } + return $this->_stack[$this->_count - $n]; + } // function last() + + /** + * Clear the stack + */ + function clear() { + $this->_stack = array(); + $this->_count = 0; + } + +} // class PHPExcel_Calculation_Token_Stack diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/functionlist.txt b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/functionlist.txt new file mode 100755 index 0000000..67dbd49 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Calculation/functionlist.txt @@ -0,0 +1,351 @@ +ABS +ACCRINT +ACCRINTM +ACOS +ACOSH +ADDRESS +AMORDEGRC +AMORLINC +AND +AREAS +ASC +ASIN +ASINH +ATAN +ATAN2 +ATANH +AVEDEV +AVERAGE +AVERAGEA +AVERAGEIF +AVERAGEIFS +BAHTTEXT +BESSELI +BESSELJ +BESSELK +BESSELY +BETADIST +BETAINV +BIN2DEC +BIN2HEX +BIN2OCT +BINOMDIST +CEILING +CELL +CHAR +CHIDIST +CHIINV +CHITEST +CHOOSE +CLEAN +CODE +COLUMN +COLUMNS +COMBIN +COMPLEX +CONCATENATE +CONFIDENCE +CONVERT +CORREL +COS +COSH +COUNT +COUNTA +COUNTBLANK +COUNTIF +COUNTIFS +COUPDAYBS +COUPDAYBS +COUPDAYSNC +COUPNCD +COUPNUM +COUPPCD +COVAR +CRITBINOM +CUBEKPIMEMBER +CUBEMEMBER +CUBEMEMBERPROPERTY +CUBERANKEDMEMBER +CUBESET +CUBESETCOUNT +CUBEVALUE +CUMIPMT +CUMPRINC +DATE +DATEDIF +DATEVALUE +DAVERAGE +DAY +DAYS360 +DB +DCOUNT +DCOUNTA +DDB +DEC2BIN +DEC2HEX +DEC2OCT +DEGREES +DELTA +DEVSQ +DGET +DISC +DMAX +DMIN +DOLLAR +DOLLARDE +DOLLARFR +DPRODUCT +DSTDEV +DSTDEVP +DSUM +DURATION +DVAR +DVARP +EDATE +EFFECT +EOMONTH +ERF +ERFC +ERROR.TYPE +EVEN +EXACT +EXP +EXPONDIST +FACT +FACTDOUBLE +FALSE +FDIST +FIND +FINDB +FINV +FISHER +FISHERINV +FIXED +FLOOR +FORECAST +FREQUENCY +FTEST +FV +FVSCHEDULE +GAMAMDIST +GAMMAINV +GAMMALN +GCD +GEOMEAN +GESTEP +GETPIVOTDATA +GROWTH +HARMEAN +HEX2BIN +HEX2OCT +HLOOKUP +HOUR +HYPERLINK +HYPGEOMDIST +IF +IFERROR +IMABS +IMAGINARY +IMARGUMENT +IMCONJUGATE +IMCOS +IMEXP +IMLN +IMLOG10 +IMLOG2 +IMPOWER +IMPRODUCT +IMREAL +IMSIN +IMSQRT +IMSUB +IMSUM +INDEX +INDIRECT +INFO +INT +INTERCEPT +INTRATE +IPMT +IRR +ISBLANK +ISERR +ISERROR +ISEVEN +ISLOGICAL +ISNA +ISNONTEXT +ISNUMBER +ISODD +ISPMT +ISREF +ISTEXT +JIS +KURT +LARGE +LCM +LEFT +LEFTB +LEN +LENB +LINEST +LN +LOG +LOG10 +LOGEST +LOGINV +LOGNORMDIST +LOOKUP +LOWER +MATCH +MAX +MAXA +MDETERM +MDURATION +MEDIAN +MID +MIDB +MIN +MINA +MINUTE +MINVERSE +MIRR +MMULT +MOD +MODE +MONTH +MROUND +MULTINOMIAL +N +NA +NEGBINOMDIST +NETWORKDAYS +NOMINAL +NORMDIST +NORMINV +NORMSDIST +NORMSINV +NOT +NOW +NPER +NPV +OCT2BIN +OCT2DEC +OCT2HEX +ODD +ODDFPRICE +ODDFYIELD +ODDLPRICE +ODDLYIELD +OFFSET +OR +PEARSON +PERCENTILE +PERCENTRANK +PERMUT +PHONETIC +PI +PMT +POISSON +POWER +PPMT +PRICE +PRICEDISC +PRICEMAT +PROB +PRODUCT +PROPER +PV +QUARTILE +QUOTIENT +RADIANS +RAND +RANDBETWEEN +RANK +RATE +RECEIVED +REPLACE +REPLACEB +REPT +RIGHT +RIGHTB +ROMAN +ROUND +ROUNDDOWN +ROUNDUP +ROW +ROWS +RSQ +RTD +SEARCH +SEARCHB +SECOND +SERIESSUM +SIGN +SIN +SINH +SKEW +SLN +SLOPE +SMALL +SQRT +SQRTPI +STANDARDIZE +STDEV +STDEVA +STDEVP +STDEVPA +STEYX +SUBSTITUTE +SUBTOTAL +SUM +SUMIF +SUMIFS +SUMPRODUCT +SUMSQ +SUMX2MY2 +SUMX2PY2 +SUMXMY2 +SYD +T +TAN +TANH +TBILLEQ +TBILLPRICE +TBILLYIELD +TDIST +TEXT +TIME +TIMEVALUE +TINV +TODAY +TRANSPOSE +TREND +TRIM +TRIMMEAN +TRUE +TRUNC +TTEST +TYPE +UPPER +USDOLLAR +VALUE +VAR +VARA +VARP +VARPA +VDB +VERSION +VLOOKUP +WEEKDAY +WEEKNUM +WEIBULL +WORKDAY +XIRR +XNPV +YEAR +YEARFRAC +YIELD +YIELDDISC +YIELDMAT +ZTEST diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell.php new file mode 100755 index 0000000..e652a55 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell.php @@ -0,0 +1,978 @@ +_parent->updateCacheData($this); + + return $this; + } + + public function detach() { + $this->_parent = NULL; + } + + public function attach(PHPExcel_CachedObjectStorage_CacheBase $parent) { + + + $this->_parent = $parent; + } + + + /** + * Create a new Cell + * + * @param mixed $pValue + * @param string $pDataType + * @param PHPExcel_Worksheet $pSheet + * @throws PHPExcel_Exception + */ + public function __construct($pValue = NULL, $pDataType = NULL, PHPExcel_Worksheet $pSheet = NULL) + { + // Initialise cell value + $this->_value = $pValue; + + // Set worksheet cache + $this->_parent = $pSheet->getCellCacheController(); + + // Set datatype? + if ($pDataType !== NULL) { + if ($pDataType == PHPExcel_Cell_DataType::TYPE_STRING2) + $pDataType = PHPExcel_Cell_DataType::TYPE_STRING; + $this->_dataType = $pDataType; + } else { + if (!self::getValueBinder()->bindValue($this, $pValue)) { + throw new PHPExcel_Exception("Value could not be bound to cell."); + } + } + + // set default index to cellXf + $this->_xfIndex = 0; + } + + /** + * Get cell coordinate column + * + * @return string + */ + public function getColumn() + { + return $this->_parent->getCurrentColumn(); + } + + /** + * Get cell coordinate row + * + * @return int + */ + public function getRow() + { + return $this->_parent->getCurrentRow(); + } + + /** + * Get cell coordinate + * + * @return string + */ + public function getCoordinate() + { + return $this->_parent->getCurrentAddress(); + } + + /** + * Get cell value + * + * @return mixed + */ + public function getValue() + { + return $this->_value; + } + + /** + * Get cell value with formatting + * + * @return string + */ + public function getFormattedValue() + { + return (string) PHPExcel_Style_NumberFormat::toFormattedString( + $this->getCalculatedValue(), + $this->getWorksheet()->getParent()->getCellXfByIndex($this->getXfIndex()) + ->getNumberFormat()->getFormatCode() + ); + } + + /** + * Set cell value + * + * Sets the value for a cell, automatically determining the datatype using the value binder + * + * @param mixed $pValue Value + * @return PHPExcel_Cell + * @throws PHPExcel_Exception + */ + public function setValue($pValue = NULL) + { + if (!self::getValueBinder()->bindValue($this, $pValue)) { + throw new PHPExcel_Exception("Value could not be bound to cell."); + } + return $this; + } + + /** + * Set the value for a cell, with the explicit data type passed to the method (bypassing any use of the value binder) + * + * @param mixed $pValue Value + * @param string $pDataType Explicit data type + * @return PHPExcel_Cell + * @throws PHPExcel_Exception + */ + public function setValueExplicit($pValue = NULL, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING) + { + // set the value according to data type + switch ($pDataType) { + case PHPExcel_Cell_DataType::TYPE_STRING2: + $pDataType = PHPExcel_Cell_DataType::TYPE_STRING; + case PHPExcel_Cell_DataType::TYPE_STRING: + case PHPExcel_Cell_DataType::TYPE_NULL: + case PHPExcel_Cell_DataType::TYPE_INLINE: + $this->_value = PHPExcel_Cell_DataType::checkString($pValue); + break; + case PHPExcel_Cell_DataType::TYPE_NUMERIC: + $this->_value = (float)$pValue; + break; + case PHPExcel_Cell_DataType::TYPE_FORMULA: + $this->_value = (string)$pValue; + break; + case PHPExcel_Cell_DataType::TYPE_BOOL: + $this->_value = (bool)$pValue; + break; + case PHPExcel_Cell_DataType::TYPE_ERROR: + $this->_value = PHPExcel_Cell_DataType::checkErrorCode($pValue); + break; + default: + throw new PHPExcel_Exception('Invalid datatype: ' . $pDataType); + break; + } + + // set the datatype + $this->_dataType = $pDataType; + + return $this->notifyCacheController(); + } + + /** + * Get calculated cell value + * + * @deprecated Since version 1.7.8 for planned changes to cell for array formula handling + * + * @param boolean $resetLog Whether the calculation engine logger should be reset or not + * @return mixed + * @throws PHPExcel_Exception + */ + public function getCalculatedValue($resetLog = TRUE) + { +//echo 'Cell '.$this->getCoordinate().' value is a '.$this->_dataType.' with a value of '.$this->getValue().PHP_EOL; + if ($this->_dataType == PHPExcel_Cell_DataType::TYPE_FORMULA) { + try { +//echo 'Cell value for '.$this->getCoordinate().' is a formula: Calculating value'.PHP_EOL; + $result = PHPExcel_Calculation::getInstance( + $this->getWorksheet()->getParent() + )->calculateCellValue($this,$resetLog); +//echo $this->getCoordinate().' calculation result is '.$result.PHP_EOL; + // We don't yet handle array returns + if (is_array($result)) { + while (is_array($result)) { + $result = array_pop($result); + } + } + } catch ( PHPExcel_Exception $ex ) { + if (($ex->getMessage() === 'Unable to access External Workbook') && ($this->_calculatedValue !== NULL)) { +//echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().PHP_EOL; + return $this->_calculatedValue; // Fallback for calculations referencing external files. + } +//echo 'Calculation Exception: '.$ex->getMessage().PHP_EOL; + $result = '#N/A'; + throw new PHPExcel_Calculation_Exception( + $this->getWorksheet()->getTitle().'!'.$this->getCoordinate().' -> '.$ex->getMessage() + ); + } + + if ($result === '#Not Yet Implemented') { +//echo 'Returning fallback value of '.$this->_calculatedValue.' for cell '.$this->getCoordinate().PHP_EOL; + return $this->_calculatedValue; // Fallback if calculation engine does not support the formula. + } +//echo 'Returning calculated value of '.$result.' for cell '.$this->getCoordinate().PHP_EOL; + return $result; + } elseif($this->_value instanceof PHPExcel_RichText) { +// echo 'Cell value for '.$this->getCoordinate().' is rich text: Returning data value of '.$this->_value.'
    '; + return $this->_value->getPlainText(); + } +// echo 'Cell value for '.$this->getCoordinate().' is not a formula: Returning data value of '.$this->_value.'
    '; + return $this->_value; + } + + /** + * Set old calculated value (cached) + * + * @param mixed $pValue Value + * @return PHPExcel_Cell + */ + public function setCalculatedValue($pValue = NULL) + { + if ($pValue !== NULL) { + $this->_calculatedValue = (is_numeric($pValue)) ? (float) $pValue : $pValue; + } + + return $this->notifyCacheController(); + } + + /** + * Get old calculated value (cached) + * This returns the value last calculated by MS Excel or whichever spreadsheet program was used to + * create the original spreadsheet file. + * Note that this value is not guaranteed to refelect the actual calculated value because it is + * possible that auto-calculation was disabled in the original spreadsheet, and underlying data + * values used by the formula have changed since it was last calculated. + * + * @return mixed + */ + public function getOldCalculatedValue() + { + return $this->_calculatedValue; + } + + /** + * Get cell data type + * + * @return string + */ + public function getDataType() + { + return $this->_dataType; + } + + /** + * Set cell data type + * + * @param string $pDataType + * @return PHPExcel_Cell + */ + public function setDataType($pDataType = PHPExcel_Cell_DataType::TYPE_STRING) + { + if ($pDataType == PHPExcel_Cell_DataType::TYPE_STRING2) + $pDataType = PHPExcel_Cell_DataType::TYPE_STRING; + + $this->_dataType = $pDataType; + + return $this->notifyCacheController(); + } + + /** + * Does this cell contain Data validation rules? + * + * @return boolean + * @throws PHPExcel_Exception + */ + public function hasDataValidation() + { + if (!isset($this->_parent)) { + throw new PHPExcel_Exception('Cannot check for data validation when cell is not bound to a worksheet'); + } + + return $this->getWorksheet()->dataValidationExists($this->getCoordinate()); + } + + /** + * Get Data validation rules + * + * @return PHPExcel_Cell_DataValidation + * @throws PHPExcel_Exception + */ + public function getDataValidation() + { + if (!isset($this->_parent)) { + throw new PHPExcel_Exception('Cannot get data validation for cell that is not bound to a worksheet'); + } + + return $this->getWorksheet()->getDataValidation($this->getCoordinate()); + } + + /** + * Set Data validation rules + * + * @param PHPExcel_Cell_DataValidation $pDataValidation + * @return PHPExcel_Cell + * @throws PHPExcel_Exception + */ + public function setDataValidation(PHPExcel_Cell_DataValidation $pDataValidation = NULL) + { + if (!isset($this->_parent)) { + throw new PHPExcel_Exception('Cannot set data validation for cell that is not bound to a worksheet'); + } + + $this->getWorksheet()->setDataValidation($this->getCoordinate(), $pDataValidation); + + return $this->notifyCacheController(); + } + + /** + * Does this cell contain a Hyperlink? + * + * @return boolean + * @throws PHPExcel_Exception + */ + public function hasHyperlink() + { + if (!isset($this->_parent)) { + throw new PHPExcel_Exception('Cannot check for hyperlink when cell is not bound to a worksheet'); + } + + return $this->getWorksheet()->hyperlinkExists($this->getCoordinate()); + } + + /** + * Get Hyperlink + * + * @return PHPExcel_Cell_Hyperlink + * @throws PHPExcel_Exception + */ + public function getHyperlink() + { + if (!isset($this->_parent)) { + throw new PHPExcel_Exception('Cannot get hyperlink for cell that is not bound to a worksheet'); + } + + return $this->getWorksheet()->getHyperlink($this->getCoordinate()); + } + + /** + * Set Hyperlink + * + * @param PHPExcel_Cell_Hyperlink $pHyperlink + * @return PHPExcel_Cell + * @throws PHPExcel_Exception + */ + public function setHyperlink(PHPExcel_Cell_Hyperlink $pHyperlink = NULL) + { + if (!isset($this->_parent)) { + throw new PHPExcel_Exception('Cannot set hyperlink for cell that is not bound to a worksheet'); + } + + $this->getWorksheet()->setHyperlink($this->getCoordinate(), $pHyperlink); + + return $this->notifyCacheController(); + } + + /** + * Get parent worksheet + * + * @return PHPExcel_Worksheet + */ + public function getParent() { + return $this->_parent; + } + + /** + * Get parent worksheet + * + * @return PHPExcel_Worksheet + */ + public function getWorksheet() { + return $this->_parent->getParent(); + } + + /** + * Get cell style + * + * @return PHPExcel_Style + */ + public function getStyle() + { + return $this->getWorksheet()->getParent()->getCellXfByIndex($this->getXfIndex()); + } + + /** + * Re-bind parent + * + * @param PHPExcel_Worksheet $parent + * @return PHPExcel_Cell + */ + public function rebindParent(PHPExcel_Worksheet $parent) { + $this->_parent = $parent->getCellCacheController(); + + return $this->notifyCacheController(); + } + + /** + * Is cell in a specific range? + * + * @param string $pRange Cell range (e.g. A1:A1) + * @return boolean + */ + public function isInRange($pRange = 'A1:A1') + { + list($rangeStart,$rangeEnd) = self::rangeBoundaries($pRange); + + // Translate properties + $myColumn = self::columnIndexFromString($this->getColumn()); + $myRow = $this->getRow(); + + // Verify if cell is in range + return (($rangeStart[0] <= $myColumn) && ($rangeEnd[0] >= $myColumn) && + ($rangeStart[1] <= $myRow) && ($rangeEnd[1] >= $myRow) + ); + } + + /** + * Coordinate from string + * + * @param string $pCoordinateString + * @return array Array containing column and row (indexes 0 and 1) + * @throws PHPExcel_Exception + */ + public static function coordinateFromString($pCoordinateString = 'A1') + { + if (preg_match("/^([$]?[A-Z]{1,3})([$]?\d{1,7})$/", $pCoordinateString, $matches)) { + return array($matches[1],$matches[2]); + } elseif ((strpos($pCoordinateString,':') !== FALSE) || (strpos($pCoordinateString,',') !== FALSE)) { + throw new PHPExcel_Exception('Cell coordinate string can not be a range of cells'); + } elseif ($pCoordinateString == '') { + throw new PHPExcel_Exception('Cell coordinate can not be zero-length string'); + } + + throw new PHPExcel_Exception('Invalid cell coordinate '.$pCoordinateString); + } + + /** + * Make string row, column or cell coordinate absolute + * + * @param string $pCoordinateString e.g. 'A' or '1' or 'A1' + * Note that this value can be a row or column reference as well as a cell reference + * @return string Absolute coordinate e.g. '$A' or '$1' or '$A$1' + * @throws PHPExcel_Exception + */ + public static function absoluteReference($pCoordinateString = 'A1') + { + if (strpos($pCoordinateString,':') === FALSE && strpos($pCoordinateString,',') === FALSE) { + // Split out any worksheet name from the reference + $worksheet = ''; + $cellAddress = explode('!',$pCoordinateString); + if (count($cellAddress) > 1) { + list($worksheet,$pCoordinateString) = $cellAddress; + } + if ($worksheet > '') $worksheet .= '!'; + + // Create absolute coordinate + if (ctype_digit($pCoordinateString)) { + return $worksheet . '$' . $pCoordinateString; + } elseif (ctype_alpha($pCoordinateString)) { + return $worksheet . '$' . strtoupper($pCoordinateString); + } + return $worksheet . self::absoluteCoordinate($pCoordinateString); + } + + throw new PHPExcel_Exception('Cell coordinate string can not be a range of cells'); + } + + /** + * Make string coordinate absolute + * + * @param string $pCoordinateString e.g. 'A1' + * @return string Absolute coordinate e.g. '$A$1' + * @throws PHPExcel_Exception + */ + public static function absoluteCoordinate($pCoordinateString = 'A1') + { + if (strpos($pCoordinateString,':') === FALSE && strpos($pCoordinateString,',') === FALSE) { + // Split out any worksheet name from the coordinate + $worksheet = ''; + $cellAddress = explode('!',$pCoordinateString); + if (count($cellAddress) > 1) { + list($worksheet,$pCoordinateString) = $cellAddress; + } + if ($worksheet > '') $worksheet .= '!'; + + // Create absolute coordinate + list($column, $row) = self::coordinateFromString($pCoordinateString); + $column = ltrim($column,'$'); + $row = ltrim($row,'$'); + return $worksheet . '$' . $column . '$' . $row; + } + + throw new PHPExcel_Exception('Cell coordinate string can not be a range of cells'); + } + + /** + * Split range into coordinate strings + * + * @param string $pRange e.g. 'B4:D9' or 'B4:D9,H2:O11' or 'B4' + * @return array Array containg one or more arrays containing one or two coordinate strings + * e.g. array('B4','D9') or array(array('B4','D9'),array('H2','O11')) + * or array('B4') + */ + public static function splitRange($pRange = 'A1:A1') + { + // Ensure $pRange is a valid range + if(empty($pRange)) { + $pRange = self::DEFAULT_RANGE; + } + + $exploded = explode(',', $pRange); + $counter = count($exploded); + for ($i = 0; $i < $counter; ++$i) { + $exploded[$i] = explode(':', $exploded[$i]); + } + return $exploded; + } + + /** + * Build range from coordinate strings + * + * @param array $pRange Array containg one or more arrays containing one or two coordinate strings + * @return string String representation of $pRange + * @throws PHPExcel_Exception + */ + public static function buildRange($pRange) + { + // Verify range + if (!is_array($pRange) || empty($pRange) || !is_array($pRange[0])) { + throw new PHPExcel_Exception('Range does not contain any information'); + } + + // Build range + $imploded = array(); + $counter = count($pRange); + for ($i = 0; $i < $counter; ++$i) { + $pRange[$i] = implode(':', $pRange[$i]); + } + $imploded = implode(',', $pRange); + + return $imploded; + } + + /** + * Calculate range boundaries + * + * @param string $pRange Cell range (e.g. A1:A1) + * @return array Range coordinates array(Start Cell, End Cell) + * where Start Cell and End Cell are arrays (Column Number, Row Number) + */ + public static function rangeBoundaries($pRange = 'A1:A1') + { + // Ensure $pRange is a valid range + if(empty($pRange)) { + $pRange = self::DEFAULT_RANGE; + } + + // Uppercase coordinate + $pRange = strtoupper($pRange); + + // Extract range + if (strpos($pRange, ':') === FALSE) { + $rangeA = $rangeB = $pRange; + } else { + list($rangeA, $rangeB) = explode(':', $pRange); + } + + // Calculate range outer borders + $rangeStart = self::coordinateFromString($rangeA); + $rangeEnd = self::coordinateFromString($rangeB); + + // Translate column into index + $rangeStart[0] = self::columnIndexFromString($rangeStart[0]); + $rangeEnd[0] = self::columnIndexFromString($rangeEnd[0]); + + return array($rangeStart, $rangeEnd); + } + + /** + * Calculate range dimension + * + * @param string $pRange Cell range (e.g. A1:A1) + * @return array Range dimension (width, height) + */ + public static function rangeDimension($pRange = 'A1:A1') + { + // Calculate range outer borders + list($rangeStart,$rangeEnd) = self::rangeBoundaries($pRange); + + return array( ($rangeEnd[0] - $rangeStart[0] + 1), ($rangeEnd[1] - $rangeStart[1] + 1) ); + } + + /** + * Calculate range boundaries + * + * @param string $pRange Cell range (e.g. A1:A1) + * @return array Range coordinates array(Start Cell, End Cell) + * where Start Cell and End Cell are arrays (Column ID, Row Number) + */ + public static function getRangeBoundaries($pRange = 'A1:A1') + { + // Ensure $pRange is a valid range + if(empty($pRange)) { + $pRange = self::DEFAULT_RANGE; + } + + // Uppercase coordinate + $pRange = strtoupper($pRange); + + // Extract range + if (strpos($pRange, ':') === FALSE) { + $rangeA = $rangeB = $pRange; + } else { + list($rangeA, $rangeB) = explode(':', $pRange); + } + + return array( self::coordinateFromString($rangeA), self::coordinateFromString($rangeB)); + } + + /** + * Column index from string + * + * @param string $pString + * @return int Column index (base 1 !!!) + */ + public static function columnIndexFromString($pString = 'A') + { + // Using a lookup cache adds a slight memory overhead, but boosts speed + // caching using a static within the method is faster than a class static, + // though it's additional memory overhead + static $_indexCache = array(); + + if (isset($_indexCache[$pString])) + return $_indexCache[$pString]; + + // It's surprising how costly the strtoupper() and ord() calls actually are, so we use a lookup array rather than use ord() + // and make it case insensitive to get rid of the strtoupper() as well. Because it's a static, there's no significant + // memory overhead either + static $_columnLookup = array( + 'A' => 1, 'B' => 2, 'C' => 3, 'D' => 4, 'E' => 5, 'F' => 6, 'G' => 7, 'H' => 8, 'I' => 9, 'J' => 10, 'K' => 11, 'L' => 12, 'M' => 13, + 'N' => 14, 'O' => 15, 'P' => 16, 'Q' => 17, 'R' => 18, 'S' => 19, 'T' => 20, 'U' => 21, 'V' => 22, 'W' => 23, 'X' => 24, 'Y' => 25, 'Z' => 26, + 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5, 'f' => 6, 'g' => 7, 'h' => 8, 'i' => 9, 'j' => 10, 'k' => 11, 'l' => 12, 'm' => 13, + 'n' => 14, 'o' => 15, 'p' => 16, 'q' => 17, 'r' => 18, 's' => 19, 't' => 20, 'u' => 21, 'v' => 22, 'w' => 23, 'x' => 24, 'y' => 25, 'z' => 26 + ); + + // We also use the language construct isset() rather than the more costly strlen() function to match the length of $pString + // for improved performance + if (isset($pString{0})) { + if (!isset($pString{1})) { + $_indexCache[$pString] = $_columnLookup[$pString]; + return $_indexCache[$pString]; + } elseif(!isset($pString{2})) { + $_indexCache[$pString] = $_columnLookup[$pString{0}] * 26 + $_columnLookup[$pString{1}]; + return $_indexCache[$pString]; + } elseif(!isset($pString{3})) { + $_indexCache[$pString] = $_columnLookup[$pString{0}] * 676 + $_columnLookup[$pString{1}] * 26 + $_columnLookup[$pString{2}]; + return $_indexCache[$pString]; + } + } + throw new PHPExcel_Exception("Column string index can not be " . ((isset($pString{0})) ? "longer than 3 characters" : "empty")); + } + + /** + * String from columnindex + * + * @param int $pColumnIndex Column index (base 0 !!!) + * @return string + */ + public static function stringFromColumnIndex($pColumnIndex = 0) + { + // Using a lookup cache adds a slight memory overhead, but boosts speed + // caching using a static within the method is faster than a class static, + // though it's additional memory overhead + static $_indexCache = array(); + + if (!isset($_indexCache[$pColumnIndex])) { + // Determine column string + if ($pColumnIndex < 26) { + $_indexCache[$pColumnIndex] = chr(65 + $pColumnIndex); + } elseif ($pColumnIndex < 702) { + $_indexCache[$pColumnIndex] = chr(64 + ($pColumnIndex / 26)) . + chr(65 + $pColumnIndex % 26); + } else { + $_indexCache[$pColumnIndex] = chr(64 + (($pColumnIndex - 26) / 676)) . + chr(65 + ((($pColumnIndex - 26) % 676) / 26)) . + chr(65 + $pColumnIndex % 26); + } + } + return $_indexCache[$pColumnIndex]; + } + + /** + * Extract all cell references in range + * + * @param string $pRange Range (e.g. A1 or A1:C10 or A1:E10 A20:E25) + * @return array Array containing single cell references + */ + public static function extractAllCellReferencesInRange($pRange = 'A1') { + // Returnvalue + $returnValue = array(); + + // Explode spaces + $cellBlocks = explode(' ', str_replace('$', '', strtoupper($pRange))); + foreach ($cellBlocks as $cellBlock) { + // Single cell? + if (strpos($cellBlock,':') === FALSE && strpos($cellBlock,',') === FALSE) { + $returnValue[] = $cellBlock; + continue; + } + + // Range... + $ranges = self::splitRange($cellBlock); + foreach($ranges as $range) { + // Single cell? + if (!isset($range[1])) { + $returnValue[] = $range[0]; + continue; + } + + // Range... + list($rangeStart, $rangeEnd) = $range; + sscanf($rangeStart,'%[A-Z]%d', $startCol, $startRow); + sscanf($rangeEnd,'%[A-Z]%d', $endCol, $endRow); + $endCol++; + + // Current data + $currentCol = $startCol; + $currentRow = $startRow; + + // Loop cells + while ($currentCol != $endCol) { + while ($currentRow <= $endRow) { + $returnValue[] = $currentCol.$currentRow; + ++$currentRow; + } + ++$currentCol; + $currentRow = $startRow; + } + } + } + + // Sort the result by column and row + $sortKeys = array(); + foreach (array_unique($returnValue) as $coord) { + sscanf($coord,'%[A-Z]%d', $column, $row); + $sortKeys[sprintf('%3s%09d',$column,$row)] = $coord; + } + ksort($sortKeys); + + // Return value + return array_values($sortKeys); + } + + /** + * Compare 2 cells + * + * @param PHPExcel_Cell $a Cell a + * @param PHPExcel_Cell $b Cell b + * @return int Result of comparison (always -1 or 1, never zero!) + */ + public static function compareCells(PHPExcel_Cell $a, PHPExcel_Cell $b) + { + if ($a->getRow() < $b->getRow()) { + return -1; + } elseif ($a->getRow() > $b->getRow()) { + return 1; + } elseif (self::columnIndexFromString($a->getColumn()) < self::columnIndexFromString($b->getColumn())) { + return -1; + } else { + return 1; + } + } + + /** + * Get value binder to use + * + * @return PHPExcel_Cell_IValueBinder + */ + public static function getValueBinder() { + if (self::$_valueBinder === NULL) { + self::$_valueBinder = new PHPExcel_Cell_DefaultValueBinder(); + } + + return self::$_valueBinder; + } + + /** + * Set value binder to use + * + * @param PHPExcel_Cell_IValueBinder $binder + * @throws PHPExcel_Exception + */ + public static function setValueBinder(PHPExcel_Cell_IValueBinder $binder = NULL) { + if ($binder === NULL) { + throw new PHPExcel_Exception("A PHPExcel_Cell_IValueBinder is required for PHPExcel to function correctly."); + } + + self::$_valueBinder = $binder; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if ((is_object($value)) && ($key != '_parent')) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } + + /** + * Get index to cellXf + * + * @return int + */ + public function getXfIndex() + { + return $this->_xfIndex; + } + + /** + * Set index to cellXf + * + * @param int $pValue + * @return PHPExcel_Cell + */ + public function setXfIndex($pValue = 0) + { + $this->_xfIndex = $pValue; + + return $this->notifyCacheController(); + } + + /** + * @deprecated Since version 1.7.8 for planned changes to cell for array formula handling + */ + public function setFormulaAttributes($pAttributes) + { + $this->_formulaAttributes = $pAttributes; + return $this; + } + + /** + * @deprecated Since version 1.7.8 for planned changes to cell for array formula handling + */ + public function getFormulaAttributes() + { + return $this->_formulaAttributes; + } + + /** + * Convert to string + * + * @return string + */ + public function __toString() + { + return (string) $this->getValue(); + } + +} + diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/AdvancedValueBinder.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/AdvancedValueBinder.php new file mode 100755 index 0000000..98994fb --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/AdvancedValueBinder.php @@ -0,0 +1,192 @@ +setValueExplicit( TRUE, PHPExcel_Cell_DataType::TYPE_BOOL); + return true; + } elseif($value == PHPExcel_Calculation::getFALSE()) { + $cell->setValueExplicit( FALSE, PHPExcel_Cell_DataType::TYPE_BOOL); + return true; + } + + // Check for number in scientific format + if (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NUMBER.'$/', $value)) { + $cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + return true; + } + + // Check for fraction + if (preg_match('/^([+-]?) *([0-9]*)\s?\/\s*([0-9]*)$/', $value, $matches)) { + // Convert value to number + $value = $matches[2] / $matches[3]; + if ($matches[1] == '-') $value = 0 - $value; + $cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( '??/??' ); + return true; + } elseif (preg_match('/^([+-]?)([0-9]*) +([0-9]*)\s?\/\s*([0-9]*)$/', $value, $matches)) { + // Convert value to number + $value = $matches[2] + ($matches[3] / $matches[4]); + if ($matches[1] == '-') $value = 0 - $value; + $cell->setValueExplicit( (float) $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( '# ??/??' ); + return true; + } + + // Check for percentage + if (preg_match('/^\-?[0-9]*\.?[0-9]*\s?\%$/', $value)) { + // Convert value to number + $value = (float) str_replace('%', '', $value) / 100; + $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00 ); + return true; + } + + // Check for currency + $currencyCode = PHPExcel_Shared_String::getCurrencyCode(); + $decimalSeparator = PHPExcel_Shared_String::getDecimalSeparator(); + $thousandsSeparator = PHPExcel_Shared_String::getThousandsSeparator(); + if (preg_match('/^'.preg_quote($currencyCode).' *(\d{1,3}('.preg_quote($thousandsSeparator).'\d{3})*|(\d+))('.preg_quote($decimalSeparator).'\d{2})?$/', $value)) { + // Convert value to number + $value = (float) trim(str_replace(array($currencyCode, $thousandsSeparator, $decimalSeparator), array('', '', '.'), $value)); + $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( + str_replace('$', $currencyCode, PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE ) + ); + return true; + } elseif (preg_match('/^\$ *(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$/', $value)) { + // Convert value to number + $value = (float) trim(str_replace(array('$',','), '', $value)); + $cell->setValueExplicit( $value, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE ); + return true; + } + + // Check for time without seconds e.g. '9:45', '09:45' + if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d$/', $value)) { + // Convert value to number + list($h, $m) = explode(':', $value); + $days = $h / 24 + $m / 1440; + $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3 ); + return true; + } + + // Check for time with seconds '9:45:59', '09:45:59' + if (preg_match('/^(\d|[0-1]\d|2[0-3]):[0-5]\d:[0-5]\d$/', $value)) { + // Convert value to number + list($h, $m, $s) = explode(':', $value); + $days = $h / 24 + $m / 1440 + $s / 86400; + // Convert value to number + $cell->setValueExplicit($days, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode( PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4 ); + return true; + } + + // Check for datetime, e.g. '2008-12-31', '2008-12-31 15:59', '2008-12-31 15:59:10' + if (($d = PHPExcel_Shared_Date::stringToExcel($value)) !== false) { + // Convert value to number + $cell->setValueExplicit($d, PHPExcel_Cell_DataType::TYPE_NUMERIC); + // Determine style. Either there is a time part or not. Look for ':' + if (strpos($value, ':') !== false) { + $formatCode = 'yyyy-mm-dd h:mm'; + } else { + $formatCode = 'yyyy-mm-dd'; + } + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getNumberFormat()->setFormatCode($formatCode); + return true; + } + + // Check for newline character "\n" + if (strpos($value, "\n") !== FALSE) { + $value = PHPExcel_Shared_String::SanitizeUTF8($value); + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); + // Set style + $cell->getWorksheet()->getStyle( $cell->getCoordinate() ) + ->getAlignment()->setWrapText(TRUE); + return true; + } + } + + // Not bound yet? Use parent... + return parent::bindValue($cell, $value); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DataType.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DataType.php new file mode 100755 index 0000000..66be461 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DataType.php @@ -0,0 +1,122 @@ + 0, + '#DIV/0!' => 1, + '#VALUE!' => 2, + '#REF!' => 3, + '#NAME?' => 4, + '#NUM!' => 5, + '#N/A' => 6 + ); + + /** + * Get list of error codes + * + * @return array + */ + public static function getErrorCodes() { + return self::$_errorCodes; + } + + /** + * DataType for value + * + * @deprecated Replaced by PHPExcel_Cell_IValueBinder infrastructure, will be removed in version 1.8.0 + * @param mixed $pValue + * @return string + */ + public static function dataTypeForValue($pValue = null) { + return PHPExcel_Cell_DefaultValueBinder::dataTypeForValue($pValue); + } + + /** + * Check a string that it satisfies Excel requirements + * + * @param mixed Value to sanitize to an Excel string + * @return mixed Sanitized value + */ + public static function checkString($pValue = null) + { + if ($pValue instanceof PHPExcel_RichText) { + // TODO: Sanitize Rich-Text string (max. character count is 32,767) + return $pValue; + } + + // string must never be longer than 32,767 characters, truncate if necessary + $pValue = PHPExcel_Shared_String::Substring($pValue, 0, 32767); + + // we require that newline is represented as "\n" in core, not as "\r\n" or "\r" + $pValue = str_replace(array("\r\n", "\r"), "\n", $pValue); + + return $pValue; + } + + /** + * Check a value that it is a valid error code + * + * @param mixed Value to sanitize to an Excel error code + * @return string Sanitized value + */ + public static function checkErrorCode($pValue = null) + { + $pValue = (string) $pValue; + + if ( !array_key_exists($pValue, self::$_errorCodes) ) { + $pValue = '#NULL!'; + } + + return $pValue; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DataValidation.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DataValidation.php new file mode 100755 index 0000000..c4f3ace --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DataValidation.php @@ -0,0 +1,472 @@ +_formula1 = ''; + $this->_formula2 = ''; + $this->_type = PHPExcel_Cell_DataValidation::TYPE_NONE; + $this->_errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP; + $this->_operator = ''; + $this->_allowBlank = FALSE; + $this->_showDropDown = FALSE; + $this->_showInputMessage = FALSE; + $this->_showErrorMessage = FALSE; + $this->_errorTitle = ''; + $this->_error = ''; + $this->_promptTitle = ''; + $this->_prompt = ''; + } + + /** + * Get Formula 1 + * + * @return string + */ + public function getFormula1() { + return $this->_formula1; + } + + /** + * Set Formula 1 + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setFormula1($value = '') { + $this->_formula1 = $value; + return $this; + } + + /** + * Get Formula 2 + * + * @return string + */ + public function getFormula2() { + return $this->_formula2; + } + + /** + * Set Formula 2 + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setFormula2($value = '') { + $this->_formula2 = $value; + return $this; + } + + /** + * Get Type + * + * @return string + */ + public function getType() { + return $this->_type; + } + + /** + * Set Type + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setType($value = PHPExcel_Cell_DataValidation::TYPE_NONE) { + $this->_type = $value; + return $this; + } + + /** + * Get Error style + * + * @return string + */ + public function getErrorStyle() { + return $this->_errorStyle; + } + + /** + * Set Error style + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setErrorStyle($value = PHPExcel_Cell_DataValidation::STYLE_STOP) { + $this->_errorStyle = $value; + return $this; + } + + /** + * Get Operator + * + * @return string + */ + public function getOperator() { + return $this->_operator; + } + + /** + * Set Operator + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setOperator($value = '') { + $this->_operator = $value; + return $this; + } + + /** + * Get Allow Blank + * + * @return boolean + */ + public function getAllowBlank() { + return $this->_allowBlank; + } + + /** + * Set Allow Blank + * + * @param boolean $value + * @return PHPExcel_Cell_DataValidation + */ + public function setAllowBlank($value = false) { + $this->_allowBlank = $value; + return $this; + } + + /** + * Get Show DropDown + * + * @return boolean + */ + public function getShowDropDown() { + return $this->_showDropDown; + } + + /** + * Set Show DropDown + * + * @param boolean $value + * @return PHPExcel_Cell_DataValidation + */ + public function setShowDropDown($value = false) { + $this->_showDropDown = $value; + return $this; + } + + /** + * Get Show InputMessage + * + * @return boolean + */ + public function getShowInputMessage() { + return $this->_showInputMessage; + } + + /** + * Set Show InputMessage + * + * @param boolean $value + * @return PHPExcel_Cell_DataValidation + */ + public function setShowInputMessage($value = false) { + $this->_showInputMessage = $value; + return $this; + } + + /** + * Get Show ErrorMessage + * + * @return boolean + */ + public function getShowErrorMessage() { + return $this->_showErrorMessage; + } + + /** + * Set Show ErrorMessage + * + * @param boolean $value + * @return PHPExcel_Cell_DataValidation + */ + public function setShowErrorMessage($value = false) { + $this->_showErrorMessage = $value; + return $this; + } + + /** + * Get Error title + * + * @return string + */ + public function getErrorTitle() { + return $this->_errorTitle; + } + + /** + * Set Error title + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setErrorTitle($value = '') { + $this->_errorTitle = $value; + return $this; + } + + /** + * Get Error + * + * @return string + */ + public function getError() { + return $this->_error; + } + + /** + * Set Error + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setError($value = '') { + $this->_error = $value; + return $this; + } + + /** + * Get Prompt title + * + * @return string + */ + public function getPromptTitle() { + return $this->_promptTitle; + } + + /** + * Set Prompt title + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setPromptTitle($value = '') { + $this->_promptTitle = $value; + return $this; + } + + /** + * Get Prompt + * + * @return string + */ + public function getPrompt() { + return $this->_prompt; + } + + /** + * Set Prompt + * + * @param string $value + * @return PHPExcel_Cell_DataValidation + */ + public function setPrompt($value = '') { + $this->_prompt = $value; + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_formula1 + . $this->_formula2 + . $this->_type = PHPExcel_Cell_DataValidation::TYPE_NONE + . $this->_errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP + . $this->_operator + . ($this->_allowBlank ? 't' : 'f') + . ($this->_showDropDown ? 't' : 'f') + . ($this->_showInputMessage ? 't' : 'f') + . ($this->_showErrorMessage ? 't' : 'f') + . $this->_errorTitle + . $this->_error + . $this->_promptTitle + . $this->_prompt + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DefaultValueBinder.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DefaultValueBinder.php new file mode 100755 index 0000000..01be519 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/DefaultValueBinder.php @@ -0,0 +1,106 @@ +setValueExplicit( $value, self::dataTypeForValue($value) ); + + // Done! + return TRUE; + } + + /** + * DataType for value + * + * @param mixed $pValue + * @return string + */ + public static function dataTypeForValue($pValue = null) { + // Match the value against a few data types + if (is_null($pValue)) { + return PHPExcel_Cell_DataType::TYPE_NULL; + + } elseif ($pValue === '') { + return PHPExcel_Cell_DataType::TYPE_STRING; + + } elseif ($pValue instanceof PHPExcel_RichText) { + return PHPExcel_Cell_DataType::TYPE_INLINE; + + } elseif ($pValue{0} === '=' && strlen($pValue) > 1) { + return PHPExcel_Cell_DataType::TYPE_FORMULA; + + } elseif (is_bool($pValue)) { + return PHPExcel_Cell_DataType::TYPE_BOOL; + + } elseif (is_float($pValue) || is_int($pValue)) { + return PHPExcel_Cell_DataType::TYPE_NUMERIC; + + } elseif (preg_match('/^\-?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)$/', $pValue)) { + return PHPExcel_Cell_DataType::TYPE_NUMERIC; + + } elseif (is_string($pValue) && array_key_exists($pValue, PHPExcel_Cell_DataType::getErrorCodes())) { + return PHPExcel_Cell_DataType::TYPE_ERROR; + + } else { + return PHPExcel_Cell_DataType::TYPE_STRING; + + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/Hyperlink.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/Hyperlink.php new file mode 100755 index 0000000..f277559 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/Hyperlink.php @@ -0,0 +1,126 @@ +_url = $pUrl; + $this->_tooltip = $pTooltip; + } + + /** + * Get URL + * + * @return string + */ + public function getUrl() { + return $this->_url; + } + + /** + * Set URL + * + * @param string $value + * @return PHPExcel_Cell_Hyperlink + */ + public function setUrl($value = '') { + $this->_url = $value; + return $this; + } + + /** + * Get tooltip + * + * @return string + */ + public function getTooltip() { + return $this->_tooltip; + } + + /** + * Set tooltip + * + * @param string $value + * @return PHPExcel_Cell_Hyperlink + */ + public function setTooltip($value = '') { + $this->_tooltip = $value; + return $this; + } + + /** + * Is this hyperlink internal? (to another worksheet) + * + * @return boolean + */ + public function isInternal() { + return strpos($this->_url, 'sheet://') !== false; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_url + . $this->_tooltip + . __CLASS__ + ); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/IValueBinder.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/IValueBinder.php new file mode 100755 index 0000000..4221869 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Cell/IValueBinder.php @@ -0,0 +1,46 @@ +_name = $name; + $this->_title = $title; + $this->_legend = $legend; + $this->_xAxisLabel = $xAxisLabel; + $this->_yAxisLabel = $yAxisLabel; + $this->_plotArea = $plotArea; + $this->_plotVisibleOnly = $plotVisibleOnly; + $this->_displayBlanksAs = $displayBlanksAs; + } + + /** + * Get Name + * + * @return string + */ + public function getName() { + return $this->_name; + } + + /** + * Get Worksheet + * + * @return PHPExcel_Worksheet + */ + public function getWorksheet() { + return $this->_worksheet; + } + + /** + * Set Worksheet + * + * @param PHPExcel_Worksheet $pValue + * @throws PHPExcel_Chart_Exception + * @return PHPExcel_Chart + */ + public function setWorksheet(PHPExcel_Worksheet $pValue = null) { + $this->_worksheet = $pValue; + + return $this; + } + + /** + * Get Title + * + * @return PHPExcel_Chart_Title + */ + public function getTitle() { + return $this->_title; + } + + /** + * Set Title + * + * @param PHPExcel_Chart_Title $title + * @return PHPExcel_Chart + */ + public function setTitle(PHPExcel_Chart_Title $title) { + $this->_title = $title; + + return $this; + } + + /** + * Get Legend + * + * @return PHPExcel_Chart_Legend + */ + public function getLegend() { + return $this->_legend; + } + + /** + * Set Legend + * + * @param PHPExcel_Chart_Legend $legend + * @return PHPExcel_Chart + */ + public function setLegend(PHPExcel_Chart_Legend $legend) { + $this->_legend = $legend; + + return $this; + } + + /** + * Get X-Axis Label + * + * @return PHPExcel_Chart_Title + */ + public function getXAxisLabel() { + return $this->_xAxisLabel; + } + + /** + * Set X-Axis Label + * + * @param PHPExcel_Chart_Title $label + * @return PHPExcel_Chart + */ + public function setXAxisLabel(PHPExcel_Chart_Title $label) { + $this->_xAxisLabel = $label; + + return $this; + } + + /** + * Get Y-Axis Label + * + * @return PHPExcel_Chart_Title + */ + public function getYAxisLabel() { + return $this->_yAxisLabel; + } + + /** + * Set Y-Axis Label + * + * @param PHPExcel_Chart_Title $label + * @return PHPExcel_Chart + */ + public function setYAxisLabel(PHPExcel_Chart_Title $label) { + $this->_yAxisLabel = $label; + + return $this; + } + + /** + * Get Plot Area + * + * @return PHPExcel_Chart_PlotArea + */ + public function getPlotArea() { + return $this->_plotArea; + } + + /** + * Get Plot Visible Only + * + * @return boolean + */ + public function getPlotVisibleOnly() { + return $this->_plotVisibleOnly; + } + + /** + * Set Plot Visible Only + * + * @param boolean $plotVisibleOnly + * @return PHPExcel_Chart + */ + public function setPlotVisibleOnly($plotVisibleOnly = true) { + $this->_plotVisibleOnly = $plotVisibleOnly; + + return $this; + } + + /** + * Get Display Blanks as + * + * @return string + */ + public function getDisplayBlanksAs() { + return $this->_displayBlanksAs; + } + + /** + * Set Display Blanks as + * + * @param string $displayBlanksAs + * @return PHPExcel_Chart + */ + public function setDisplayBlanksAs($displayBlanksAs = '0') { + $this->_displayBlanksAs = $displayBlanksAs; + } + + + /** + * Set the Top Left position for the chart + * + * @param string $cell + * @param integer $xOffset + * @param integer $yOffset + * @return PHPExcel_Chart + */ + public function setTopLeftPosition($cell, $xOffset=null, $yOffset=null) { + $this->_topLeftCellRef = $cell; + if (!is_null($xOffset)) + $this->setTopLeftXOffset($xOffset); + if (!is_null($yOffset)) + $this->setTopLeftYOffset($yOffset); + + return $this; + } + + /** + * Get the top left position of the chart + * + * @return array an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell + */ + public function getTopLeftPosition() { + return array( 'cell' => $this->_topLeftCellRef, + 'xOffset' => $this->_topLeftXOffset, + 'yOffset' => $this->_topLeftYOffset + ); + } + + /** + * Get the cell address where the top left of the chart is fixed + * + * @return string + */ + public function getTopLeftCell() { + return $this->_topLeftCellRef; + } + + /** + * Set the Top Left cell position for the chart + * + * @param string $cell + * @return PHPExcel_Chart + */ + public function setTopLeftCell($cell) { + $this->_topLeftCellRef = $cell; + + return $this; + } + + /** + * Set the offset position within the Top Left cell for the chart + * + * @param integer $xOffset + * @param integer $yOffset + * @return PHPExcel_Chart + */ + public function setTopLeftOffset($xOffset=null,$yOffset=null) { + if (!is_null($xOffset)) + $this->setTopLeftXOffset($xOffset); + if (!is_null($yOffset)) + $this->setTopLeftYOffset($yOffset); + + return $this; + } + + /** + * Get the offset position within the Top Left cell for the chart + * + * @return integer[] + */ + public function getTopLeftOffset() { + return array( 'X' => $this->_topLeftXOffset, + 'Y' => $this->_topLeftYOffset + ); + } + + public function setTopLeftXOffset($xOffset) { + $this->_topLeftXOffset = $xOffset; + + return $this; + } + + public function getTopLeftXOffset() { + return $this->_topLeftXOffset; + } + + public function setTopLeftYOffset($yOffset) { + $this->_topLeftYOffset = $yOffset; + + return $this; + } + + public function getTopLeftYOffset() { + return $this->_topLeftYOffset; + } + + /** + * Set the Bottom Right position of the chart + * + * @param string $cell + * @param integer $xOffset + * @param integer $yOffset + * @return PHPExcel_Chart + */ + public function setBottomRightPosition($cell, $xOffset=null, $yOffset=null) { + $this->_bottomRightCellRef = $cell; + if (!is_null($xOffset)) + $this->setBottomRightXOffset($xOffset); + if (!is_null($yOffset)) + $this->setBottomRightYOffset($yOffset); + + return $this; + } + + /** + * Get the bottom right position of the chart + * + * @return array an associative array containing the cell address, X-Offset and Y-Offset from the top left of that cell + */ + public function getBottomRightPosition() { + return array( 'cell' => $this->_bottomRightCellRef, + 'xOffset' => $this->_bottomRightXOffset, + 'yOffset' => $this->_bottomRightYOffset + ); + } + + public function setBottomRightCell($cell) { + $this->_bottomRightCellRef = $cell; + + return $this; + } + + /** + * Get the cell address where the bottom right of the chart is fixed + * + * @return string + */ + public function getBottomRightCell() { + return $this->_bottomRightCellRef; + } + + /** + * Set the offset position within the Bottom Right cell for the chart + * + * @param integer $xOffset + * @param integer $yOffset + * @return PHPExcel_Chart + */ + public function setBottomRightOffset($xOffset=null,$yOffset=null) { + if (!is_null($xOffset)) + $this->setBottomRightXOffset($xOffset); + if (!is_null($yOffset)) + $this->setBottomRightYOffset($yOffset); + + return $this; + } + + /** + * Get the offset position within the Bottom Right cell for the chart + * + * @return integer[] + */ + public function getBottomRightOffset() { + return array( 'X' => $this->_bottomRightXOffset, + 'Y' => $this->_bottomRightYOffset + ); + } + + public function setBottomRightXOffset($xOffset) { + $this->_bottomRightXOffset = $xOffset; + + return $this; + } + + public function getBottomRightXOffset() { + return $this->_bottomRightXOffset; + } + + public function setBottomRightYOffset($yOffset) { + $this->_bottomRightYOffset = $yOffset; + + return $this; + } + + public function getBottomRightYOffset() { + return $this->_bottomRightYOffset; + } + + + public function refresh() { + if ($this->_worksheet !== NULL) { + $this->_plotArea->refresh($this->_worksheet); + } + } + + public function render($outputDestination = null) { + $libraryName = PHPExcel_Settings::getChartRendererName(); + if (is_null($libraryName)) { + return false; + } + // Ensure that data series values are up-to-date before we render + $this->refresh(); + + $libraryPath = PHPExcel_Settings::getChartRendererPath(); + $includePath = str_replace('\\','/',get_include_path()); + $rendererPath = str_replace('\\','/',$libraryPath); + if (strpos($rendererPath,$includePath) === false) { + set_include_path(get_include_path() . PATH_SEPARATOR . $libraryPath); + } + + $rendererName = 'PHPExcel_Chart_Renderer_'.$libraryName; + $renderer = new $rendererName($this); + + if ($outputDestination == 'php://output') { + $outputDestination = null; + } + return $renderer->render($outputDestination); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/DataSeries.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/DataSeries.php new file mode 100755 index 0000000..87b0bd4 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/DataSeries.php @@ -0,0 +1,354 @@ +_plotType = $plotType; + $this->_plotGrouping = $plotGrouping; + $this->_plotOrder = $plotOrder; + $keys = array_keys($plotValues); + $this->_plotValues = $plotValues; + if ((count($plotLabel) == 0) || (is_null($plotLabel[$keys[0]]))) { + $plotLabel[$keys[0]] = new PHPExcel_Chart_DataSeriesValues(); + } + + $this->_plotLabel = $plotLabel; + if ((count($plotCategory) == 0) || (is_null($plotCategory[$keys[0]]))) { + $plotCategory[$keys[0]] = new PHPExcel_Chart_DataSeriesValues(); + } + $this->_plotCategory = $plotCategory; + $this->_smoothLine = $smoothLine; + $this->_plotStyle = $plotStyle; + } + + /** + * Get Plot Type + * + * @return string + */ + public function getPlotType() { + return $this->_plotType; + } + + /** + * Set Plot Type + * + * @param string $plotType + */ + public function setPlotType($plotType = '') { + $this->_plotType = $plotType; + } + + /** + * Get Plot Grouping Type + * + * @return string + */ + public function getPlotGrouping() { + return $this->_plotGrouping; + } + + /** + * Set Plot Grouping Type + * + * @param string $groupingType + */ + public function setPlotGrouping($groupingType = null) { + $this->_plotGrouping = $groupingType; + } + + /** + * Get Plot Direction + * + * @return string + */ + public function getPlotDirection() { + return $this->_plotDirection; + } + + /** + * Set Plot Direction + * + * @param string $plotDirection + */ + public function setPlotDirection($plotDirection = null) { + $this->_plotDirection = $plotDirection; + } + + /** + * Get Plot Order + * + * @return string + */ + public function getPlotOrder() { + return $this->_plotOrder; + } + + /** + * Get Plot Labels + * + * @return array of PHPExcel_Chart_DataSeriesValues + */ + public function getPlotLabels() { + return $this->_plotLabel; + } + + /** + * Get Plot Label by Index + * + * @return PHPExcel_Chart_DataSeriesValues + */ + public function getPlotLabelByIndex($index) { + $keys = array_keys($this->_plotLabel); + if (in_array($index,$keys)) { + return $this->_plotLabel[$index]; + } elseif(isset($keys[$index])) { + return $this->_plotLabel[$keys[$index]]; + } + return false; + } + + /** + * Get Plot Categories + * + * @return array of PHPExcel_Chart_DataSeriesValues + */ + public function getPlotCategories() { + return $this->_plotCategory; + } + + /** + * Get Plot Category by Index + * + * @return PHPExcel_Chart_DataSeriesValues + */ + public function getPlotCategoryByIndex($index) { + $keys = array_keys($this->_plotCategory); + if (in_array($index,$keys)) { + return $this->_plotCategory[$index]; + } elseif(isset($keys[$index])) { + return $this->_plotCategory[$keys[$index]]; + } + return false; + } + + /** + * Get Plot Style + * + * @return string + */ + public function getPlotStyle() { + return $this->_plotStyle; + } + + /** + * Set Plot Style + * + * @param string $plotStyle + */ + public function setPlotStyle($plotStyle = null) { + $this->_plotStyle = $plotStyle; + } + + /** + * Get Plot Values + * + * @return array of PHPExcel_Chart_DataSeriesValues + */ + public function getPlotValues() { + return $this->_plotValues; + } + + /** + * Get Plot Values by Index + * + * @return PHPExcel_Chart_DataSeriesValues + */ + public function getPlotValuesByIndex($index) { + $keys = array_keys($this->_plotValues); + if (in_array($index,$keys)) { + return $this->_plotValues[$index]; + } elseif(isset($keys[$index])) { + return $this->_plotValues[$keys[$index]]; + } + return false; + } + + /** + * Get Number of Plot Series + * + * @return integer + */ + public function getPlotSeriesCount() { + return count($this->_plotValues); + } + + /** + * Get Smooth Line + * + * @return boolean + */ + public function getSmoothLine() { + return $this->_smoothLine; + } + + /** + * Set Smooth Line + * + * @param boolean $smoothLine + */ + public function setSmoothLine($smoothLine = TRUE) { + $this->_smoothLine = $smoothLine; + } + + public function refresh(PHPExcel_Worksheet $worksheet) { + foreach($this->_plotValues as $plotValues) { + if ($plotValues !== NULL) + $plotValues->refresh($worksheet, TRUE); + } + foreach($this->_plotLabel as $plotValues) { + if ($plotValues !== NULL) + $plotValues->refresh($worksheet, TRUE); + } + foreach($this->_plotCategory as $plotValues) { + if ($plotValues !== NULL) + $plotValues->refresh($worksheet, FALSE); + } + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/DataSeriesValues.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/DataSeriesValues.php new file mode 100755 index 0000000..7bf796f --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/DataSeriesValues.php @@ -0,0 +1,327 @@ +setDataType($dataType); + $this->_dataSource = $dataSource; + $this->_formatCode = $formatCode; + $this->_pointCount = $pointCount; + $this->_dataValues = $dataValues; + $this->_marker = $marker; + } + + /** + * Get Series Data Type + * + * @return string + */ + public function getDataType() { + return $this->_dataType; + } + + /** + * Set Series Data Type + * + * @param string $dataType Datatype of this data series + * Typical values are: + * PHPExcel_Chart_DataSeriesValues::DATASERIES_TYPE_STRING + * Normally used for axis point values + * PHPExcel_Chart_DataSeriesValues::DATASERIES_TYPE_NUMBER + * Normally used for chart data values + * @return PHPExcel_Chart_DataSeriesValues + */ + public function setDataType($dataType = self::DATASERIES_TYPE_NUMBER) { + if (!in_array($dataType, self::$_dataTypeValues)) { + throw new PHPExcel_Chart_Exception('Invalid datatype for chart data series values'); + } + $this->_dataType = $dataType; + + return $this; + } + + /** + * Get Series Data Source (formula) + * + * @return string + */ + public function getDataSource() { + return $this->_dataSource; + } + + /** + * Set Series Data Source (formula) + * + * @param string $dataSource + * @return PHPExcel_Chart_DataSeriesValues + */ + public function setDataSource($dataSource = null, $refreshDataValues = true) { + $this->_dataSource = $dataSource; + + if ($refreshDataValues) { + // TO DO + } + + return $this; + } + + /** + * Get Point Marker + * + * @return string + */ + public function getPointMarker() { + return $this->_marker; + } + + /** + * Set Point Marker + * + * @param string $marker + * @return PHPExcel_Chart_DataSeriesValues + */ + public function setPointMarker($marker = null) { + $this->_marker = $marker; + + return $this; + } + + /** + * Get Series Format Code + * + * @return string + */ + public function getFormatCode() { + return $this->_formatCode; + } + + /** + * Set Series Format Code + * + * @param string $formatCode + * @return PHPExcel_Chart_DataSeriesValues + */ + public function setFormatCode($formatCode = null) { + $this->_formatCode = $formatCode; + + return $this; + } + + /** + * Get Series Point Count + * + * @return integer + */ + public function getPointCount() { + return $this->_pointCount; + } + + /** + * Identify if the Data Series is a multi-level or a simple series + * + * @return boolean + */ + public function isMultiLevelSeries() { + if (count($this->_dataValues) > 0) { + return is_array($this->_dataValues[0]); + } + return null; + } + + /** + * Return the level count of a multi-level Data Series + * + * @return boolean + */ + public function multiLevelCount() { + $levelCount = 0; + foreach($this->_dataValues as $dataValueSet) { + $levelCount = max($levelCount,count($dataValueSet)); + } + return $levelCount; + } + + /** + * Get Series Data Values + * + * @return array of mixed + */ + public function getDataValues() { + return $this->_dataValues; + } + + /** + * Get the first Series Data value + * + * @return mixed + */ + public function getDataValue() { + $count = count($this->_dataValues); + if ($count == 0) { + return null; + } elseif ($count == 1) { + return $this->_dataValues[0]; + } + return $this->_dataValues; + } + + /** + * Set Series Data Values + * + * @param array $dataValues + * @param boolean $refreshDataSource + * TRUE - refresh the value of _dataSource based on the values of $dataValues + * FALSE - don't change the value of _dataSource + * @return PHPExcel_Chart_DataSeriesValues + */ + public function setDataValues($dataValues = array(), $refreshDataSource = TRUE) { + $this->_dataValues = PHPExcel_Calculation_Functions::flattenArray($dataValues); + $this->_pointCount = count($dataValues); + + if ($refreshDataSource) { + // TO DO + } + + return $this; + } + + private function _stripNulls($var) { + return $var !== NULL; + } + + public function refresh(PHPExcel_Worksheet $worksheet, $flatten = TRUE) { + if ($this->_dataSource !== NULL) { + $calcEngine = PHPExcel_Calculation::getInstance($worksheet->getParent()); + $newDataValues = PHPExcel_Calculation::_unwrapResult( + $calcEngine->_calculateFormulaValue( + '='.$this->_dataSource, + NULL, + $worksheet->getCell('A1') + ) + ); + if ($flatten) { + $this->_dataValues = PHPExcel_Calculation_Functions::flattenArray($newDataValues); + foreach($this->_dataValues as &$dataValue) { + if ((!empty($dataValue)) && ($dataValue[0] == '#')) { + $dataValue = 0.0; + } + } + unset($dataValue); + } else { + $cellRange = explode('!',$this->_dataSource); + if (count($cellRange) > 1) { + list(,$cellRange) = $cellRange; + } + + $dimensions = PHPExcel_Cell::rangeDimension(str_replace('$','',$cellRange)); + if (($dimensions[0] == 1) || ($dimensions[1] == 1)) { + $this->_dataValues = PHPExcel_Calculation_Functions::flattenArray($newDataValues); + } else { + $newArray = array_values(array_shift($newDataValues)); + foreach($newArray as $i => $newDataSet) { + $newArray[$i] = array($newDataSet); + } + + foreach($newDataValues as $newDataSet) { + $i = 0; + foreach($newDataSet as $newDataVal) { + array_unshift($newArray[$i++],$newDataVal); + } + } + $this->_dataValues = $newArray; + } + } + $this->_pointCount = count($this->_dataValues); + } + + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Exception.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Exception.php new file mode 100755 index 0000000..c7a84df --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Exception.php @@ -0,0 +1,52 @@ +line = $line; + $e->file = $file; + throw $e; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Layout.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Layout.php new file mode 100755 index 0000000..485b434 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Layout.php @@ -0,0 +1,417 @@ +_layoutTarget = $layout['layoutTarget']; } + if (isset($layout['xMode'])) { $this->_xMode = $layout['xMode']; } + if (isset($layout['yMode'])) { $this->_yMode = $layout['yMode']; } + if (isset($layout['x'])) { $this->_xPos = (float) $layout['x']; } + if (isset($layout['y'])) { $this->_yPos = (float) $layout['y']; } + if (isset($layout['w'])) { $this->_width = (float) $layout['w']; } + if (isset($layout['h'])) { $this->_height = (float) $layout['h']; } + } + + /** + * Get Layout Target + * + * @return string + */ + public function getLayoutTarget() { + return $this->_layoutTarget; + } + + /** + * Set Layout Target + * + * @param Layout Target $value + */ + public function setLayoutTarget($value) { + $this->_layoutTarget = $value; + } + + /** + * Get X-Mode + * + * @return string + */ + public function getXMode() { + return $this->_xMode; + } + + /** + * Set X-Mode + * + * @param X-Mode $value + */ + public function setXMode($value) { + $this->_xMode = $value; + } + + /** + * Get Y-Mode + * + * @return string + */ + public function getYMode() { + return $this->_xMode; + } + + /** + * Set Y-Mode + * + * @param Y-Mode $value + */ + public function setYMode($value) { + $this->_xMode = $value; + } + + /** + * Get X-Position + * + * @return number + */ + public function getXPosition() { + return $this->_xPos; + } + + /** + * Set X-Position + * + * @param X-Position $value + */ + public function setXPosition($value) { + $this->_xPos = $value; + } + + /** + * Get Y-Position + * + * @return number + */ + public function getYPosition() { + return $this->_yPos; + } + + /** + * Set Y-Position + * + * @param Y-Position $value + */ + public function setYPosition($value) { + $this->_yPos = $value; + } + + /** + * Get Width + * + * @return number + */ + public function getWidth() { + return $this->_width; + } + + /** + * Set Width + * + * @param Width $value + */ + public function setWidth($value) { + $this->_width = $value; + } + + /** + * Get Height + * + * @return number + */ + public function getHeight() { + return $this->_height; + } + + /** + * Set Height + * + * @param Height $value + */ + public function setHeight($value) { + $this->_height = $value; + } + + + /** + * Get show legend key + * + * @return boolean + */ + public function getShowLegendKey() { + return $this->_showLegendKey; + } + + /** + * Set show legend key + * Specifies that legend keys should be shown in data labels. + * + * @param boolean $value Show legend key + */ + public function setShowLegendKey($value) { + $this->_showLegendKey = $value; + } + + /** + * Get show value + * + * @return boolean + */ + public function getShowVal() { + return $this->_showVal; + } + + /** + * Set show val + * Specifies that the value should be shown in data labels. + * + * @param boolean $value Show val + */ + public function setShowVal($value) { + $this->_showVal = $value; + } + + /** + * Get show category name + * + * @return boolean + */ + public function getShowCatName() { + return $this->_showCatName; + } + + /** + * Set show cat name + * Specifies that the category name should be shown in data labels. + * + * @param boolean $value Show cat name + */ + public function setShowCatName($value) { + $this->_showCatName = $value; + } + + /** + * Get show data series name + * + * @return boolean + */ + public function getShowSerName() { + return $this->_showSerName; + } + + /** + * Set show ser name + * Specifies that the series name should be shown in data labels. + * + * @param boolean $value Show ser name + */ + public function setShowSerName($value) { + $this->_showSerName = $value; + } + + /** + * Get show percentage + * + * @return boolean + */ + public function getShowPercent() { + return $this->_showPercent; + } + + /** + * Set show percentage + * Specifies that the percentage should be shown in data labels. + * + * @param boolean $value Show percentage + */ + public function setShowPercent($value) { + $this->_showPercent = $value; + } + + /** + * Get show bubble size + * + * @return boolean + */ + public function getShowBubbleSize() { + return $this->_showBubbleSize; + } + + /** + * Set show bubble size + * Specifies that the bubble size should be shown in data labels. + * + * @param boolean $value Show bubble size + */ + public function setShowBubbleSize($value) { + $this->_showBubbleSize = $value; + } + + /** + * Get show leader lines + * + * @return boolean + */ + public function getShowLeaderLines() { + return $this->_showLeaderLines; + } + + /** + * Set show leader lines + * Specifies that leader lines should be shown in data labels. + * + * @param boolean $value Show leader lines + */ + public function setShowLeaderLines($value) { + $this->_showLeaderLines = $value; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Legend.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Legend.php new file mode 100755 index 0000000..bf21e62 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Legend.php @@ -0,0 +1,171 @@ + self::POSITION_BOTTOM, + self::xlLegendPositionCorner => self::POSITION_TOPRIGHT, + self::xlLegendPositionCustom => '??', + self::xlLegendPositionLeft => self::POSITION_LEFT, + self::xlLegendPositionRight => self::POSITION_RIGHT, + self::xlLegendPositionTop => self::POSITION_TOP + ); + + /** + * Legend position + * + * @var string + */ + private $_position = self::POSITION_RIGHT; + + /** + * Allow overlay of other elements? + * + * @var boolean + */ + private $_overlay = TRUE; + + /** + * Legend Layout + * + * @var PHPExcel_Chart_Layout + */ + private $_layout = NULL; + + + /** + * Create a new PHPExcel_Chart_Legend + */ + public function __construct($position = self::POSITION_RIGHT, PHPExcel_Chart_Layout $layout = NULL, $overlay = FALSE) + { + $this->setPosition($position); + $this->_layout = $layout; + $this->setOverlay($overlay); + } + + /** + * Get legend position as an excel string value + * + * @return string + */ + public function getPosition() { + return $this->_position; + } + + /** + * Get legend position using an excel string value + * + * @param string $position + */ + public function setPosition($position = self::POSITION_RIGHT) { + if (!in_array($position,self::$_positionXLref)) { + return false; + } + + $this->_position = $position; + return true; + } + + /** + * Get legend position as an Excel internal numeric value + * + * @return number + */ + public function getPositionXL() { + return array_search($this->_position,self::$_positionXLref); + } + + /** + * Set legend position using an Excel internal numeric value + * + * @param number $positionXL + */ + public function setPositionXL($positionXL = self::xlLegendPositionRight) { + if (!array_key_exists($positionXL,self::$_positionXLref)) { + return false; + } + + $this->_position = self::$_positionXLref[$positionXL]; + return true; + } + + /** + * Get allow overlay of other elements? + * + * @return boolean + */ + public function getOverlay() { + return $this->_overlay; + } + + /** + * Set allow overlay of other elements? + * + * @param boolean $overlay + * @return boolean + */ + public function setOverlay($overlay = FALSE) { + if (!is_bool($overlay)) { + return false; + } + + $this->_overlay = $overlay; + return true; + } + + /** + * Get Layout + * + * @return PHPExcel_Chart_Layout + */ + public function getLayout() { + return $this->_layout; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/PlotArea.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/PlotArea.php new file mode 100755 index 0000000..64e647a --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/PlotArea.php @@ -0,0 +1,125 @@ +_layout = $layout; + $this->_plotSeries = $plotSeries; + } + + /** + * Get Layout + * + * @return PHPExcel_Chart_Layout + */ + public function getLayout() { + return $this->_layout; + } + + /** + * Get Number of Plot Groups + * + * @return array of PHPExcel_Chart_DataSeries + */ + public function getPlotGroupCount() { + return count($this->_plotSeries); + } + + /** + * Get Number of Plot Series + * + * @return integer + */ + public function getPlotSeriesCount() { + $seriesCount = 0; + foreach($this->_plotSeries as $plot) { + $seriesCount += $plot->getPlotSeriesCount(); + } + return $seriesCount; + } + + /** + * Get Plot Series + * + * @return array of PHPExcel_Chart_DataSeries + */ + public function getPlotGroup() { + return $this->_plotSeries; + } + + /** + * Get Plot Series by Index + * + * @return PHPExcel_Chart_DataSeries + */ + public function getPlotGroupByIndex($index) { + return $this->_plotSeries[$index]; + } + + /** + * Set Plot Series + * + * @param [PHPExcel_Chart_DataSeries] + */ + public function setPlotSeries($plotSeries = array()) { + $this->_plotSeries = $plotSeries; + } + + public function refresh(PHPExcel_Worksheet $worksheet) { + foreach($this->_plotSeries as $plotSeries) { + $plotSeries->refresh($worksheet); + } + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Renderer/PHP Charting Libraries.txt b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Renderer/PHP Charting Libraries.txt new file mode 100755 index 0000000..20a8258 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Renderer/PHP Charting Libraries.txt @@ -0,0 +1,17 @@ +ChartDirector + http://www.advsofteng.com/cdphp.html + +GraPHPite + http://graphpite.sourceforge.net/ + +JpGraph + http://www.aditus.nu/jpgraph/ + +LibChart + http://naku.dohcrew.com/libchart/pages/introduction/ + +pChart + http://pchart.sourceforge.net/ + +TeeChart + http://www.steema.com/products/teechart/overview.html diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Renderer/jpgraph.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Renderer/jpgraph.php new file mode 100755 index 0000000..973ba2c --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Renderer/jpgraph.php @@ -0,0 +1,837 @@ + MARK_DIAMOND, + 'square' => MARK_SQUARE, + 'triangle' => MARK_UTRIANGLE, + 'x' => MARK_X, + 'star' => MARK_STAR, + 'dot' => MARK_FILLEDCIRCLE, + 'dash' => MARK_DTRIANGLE, + 'circle' => MARK_CIRCLE, + 'plus' => MARK_CROSS + ); + + + private $_chart = null; + + private $_graph = null; + + private static $_plotColour = 0; + + private static $_plotMark = 0; + + + private function _formatPointMarker($seriesPlot,$markerID) { + $plotMarkKeys = array_keys(self::$_markSet); + if (is_null($markerID)) { + // Use default plot marker (next marker in the series) + self::$_plotMark %= count(self::$_markSet); + $seriesPlot->mark->SetType(self::$_markSet[$plotMarkKeys[self::$_plotMark++]]); + } elseif ($markerID !== 'none') { + // Use specified plot marker (if it exists) + if (isset(self::$_markSet[$markerID])) { + $seriesPlot->mark->SetType(self::$_markSet[$markerID]); + } else { + // If the specified plot marker doesn't exist, use default plot marker (next marker in the series) + self::$_plotMark %= count(self::$_markSet); + $seriesPlot->mark->SetType(self::$_markSet[$plotMarkKeys[self::$_plotMark++]]); + } + } else { + // Hide plot marker + $seriesPlot->mark->Hide(); + } + $seriesPlot->mark->SetColor(self::$_colourSet[self::$_plotColour]); + $seriesPlot->mark->SetFillColor(self::$_colourSet[self::$_plotColour]); + $seriesPlot->SetColor(self::$_colourSet[self::$_plotColour++]); + + return $seriesPlot; + } // function _formatPointMarker() + + + private function _formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation = '') { + $datasetLabelFormatCode = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getFormatCode(); + if (!is_null($datasetLabelFormatCode)) { + // Retrieve any label formatting code + $datasetLabelFormatCode = stripslashes($datasetLabelFormatCode); + } + + $testCurrentIndex = 0; + foreach($datasetLabels as $i => $datasetLabel) { + if (is_array($datasetLabel)) { + if ($rotation == 'bar') { + $datasetLabels[$i] = implode(" ",$datasetLabel); + } else { + $datasetLabel = array_reverse($datasetLabel); + $datasetLabels[$i] = implode("\n",$datasetLabel); + } + } else { + // Format labels according to any formatting code + if (!is_null($datasetLabelFormatCode)) { + $datasetLabels[$i] = PHPExcel_Style_NumberFormat::toFormattedString($datasetLabel,$datasetLabelFormatCode); + } + } + ++$testCurrentIndex; + } + + return $datasetLabels; + } // function _formatDataSetLabels() + + + private function _percentageSumCalculation($groupID,$seriesCount) { + // Adjust our values to a percentage value across all series in the group + for($i = 0; $i < $seriesCount; ++$i) { + if ($i == 0) { + $sumValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); + } else { + $nextValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); + foreach($nextValues as $k => $value) { + if (isset($sumValues[$k])) { + $sumValues[$k] += $value; + } else { + $sumValues[$k] = $value; + } + } + } + } + + return $sumValues; + } // function _percentageSumCalculation() + + + private function _percentageAdjustValues($dataValues,$sumValues) { + foreach($dataValues as $k => $dataValue) { + $dataValues[$k] = $dataValue / $sumValues[$k] * 100; + } + + return $dataValues; + } // function _percentageAdjustValues() + + + private function _getCaption($captionElement) { + // Read any caption + $caption = (!is_null($captionElement)) ? $captionElement->getCaption() : NULL; + // Test if we have a title caption to display + if (!is_null($caption)) { + // If we do, it could be a plain string or an array + if (is_array($caption)) { + // Implode an array to a plain string + $caption = implode('',$caption); + } + } + return $caption; + } // function _getCaption() + + + private function _renderTitle() { + $title = $this->_getCaption($this->_chart->getTitle()); + if (!is_null($title)) { + $this->_graph->title->Set($title); + } + } // function _renderTitle() + + + private function _renderLegend() { + $legend = $this->_chart->getLegend(); + if (!is_null($legend)) { + $legendPosition = $legend->getPosition(); + $legendOverlay = $legend->getOverlay(); + switch ($legendPosition) { + case 'r' : + $this->_graph->legend->SetPos(0.01,0.5,'right','center'); // right + $this->_graph->legend->SetColumns(1); + break; + case 'l' : + $this->_graph->legend->SetPos(0.01,0.5,'left','center'); // left + $this->_graph->legend->SetColumns(1); + break; + case 't' : + $this->_graph->legend->SetPos(0.5,0.01,'center','top'); // top + break; + case 'b' : + $this->_graph->legend->SetPos(0.5,0.99,'center','bottom'); // bottom + break; + default : + $this->_graph->legend->SetPos(0.01,0.01,'right','top'); // top-right + $this->_graph->legend->SetColumns(1); + break; + } + } else { + $this->_graph->legend->Hide(); + } + } // function _renderLegend() + + + private function _renderCartesianPlotArea($type='textlin') { + $this->_graph = new Graph(self::$_width,self::$_height); + $this->_graph->SetScale($type); + + $this->_renderTitle(); + + // Rotate for bar rather than column chart + $rotation = $this->_chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotDirection(); + $reverse = ($rotation == 'bar') ? true : false; + + $xAxisLabel = $this->_chart->getXAxisLabel(); + if (!is_null($xAxisLabel)) { + $title = $this->_getCaption($xAxisLabel); + if (!is_null($title)) { + $this->_graph->xaxis->SetTitle($title,'center'); + $this->_graph->xaxis->title->SetMargin(35); + if ($reverse) { + $this->_graph->xaxis->title->SetAngle(90); + $this->_graph->xaxis->title->SetMargin(90); + } + } + } + + $yAxisLabel = $this->_chart->getYAxisLabel(); + if (!is_null($yAxisLabel)) { + $title = $this->_getCaption($yAxisLabel); + if (!is_null($title)) { + $this->_graph->yaxis->SetTitle($title,'center'); + if ($reverse) { + $this->_graph->yaxis->title->SetAngle(0); + $this->_graph->yaxis->title->SetMargin(-55); + } + } + } + } // function _renderCartesianPlotArea() + + + private function _renderPiePlotArea($doughnut = False) { + $this->_graph = new PieGraph(self::$_width,self::$_height); + + $this->_renderTitle(); + } // function _renderPiePlotArea() + + + private function _renderRadarPlotArea() { + $this->_graph = new RadarGraph(self::$_width,self::$_height); + $this->_graph->SetScale('lin'); + + $this->_renderTitle(); + } // function _renderRadarPlotArea() + + + private function _renderPlotLine($groupID, $filled = false, $combination = false, $dimensions = '2d') { + $grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); + + $labelCount = count($this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); + if ($labelCount > 0) { + $datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); + $datasetLabels = $this->_formatDataSetLabels($groupID, $datasetLabels, $labelCount); + $this->_graph->xaxis->SetTickLabels($datasetLabels); + } + + $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); + $seriesPlots = array(); + if ($grouping == 'percentStacked') { + $sumValues = $this->_percentageSumCalculation($groupID,$seriesCount); + } + + // Loop through each data series in turn + for($i = 0; $i < $seriesCount; ++$i) { + $dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); + $marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker(); + + if ($grouping == 'percentStacked') { + $dataValues = $this->_percentageAdjustValues($dataValues,$sumValues); + } + + // Fill in any missing values in the $dataValues array + $testCurrentIndex = 0; + foreach($dataValues as $k => $dataValue) { + while($k != $testCurrentIndex) { + $dataValues[$testCurrentIndex] = null; + ++$testCurrentIndex; + } + ++$testCurrentIndex; + } + + $seriesPlot = new LinePlot($dataValues); + if ($combination) { + $seriesPlot->SetBarCenter(); + } + + if ($filled) { + $seriesPlot->SetFilled(true); + $seriesPlot->SetColor('black'); + $seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour++]); + } else { + // Set the appropriate plot marker + $this->_formatPointMarker($seriesPlot,$marker); + } + $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue(); + $seriesPlot->SetLegend($dataLabel); + + $seriesPlots[] = $seriesPlot; + } + + if ($grouping == 'standard') { + $groupPlot = $seriesPlots; + } else { + $groupPlot = new AccLinePlot($seriesPlots); + } + $this->_graph->Add($groupPlot); + } // function _renderPlotLine() + + + private function _renderPlotBar($groupID, $dimensions = '2d') { + $rotation = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotDirection(); + // Rotate for bar rather than column chart + if (($groupID == 0) && ($rotation == 'bar')) { + $this->_graph->Set90AndMargin(); + } + $grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); + + $labelCount = count($this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); + if ($labelCount > 0) { + $datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); + $datasetLabels = $this->_formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation); + // Rotate for bar rather than column chart + if ($rotation == 'bar') { + $datasetLabels = array_reverse($datasetLabels); + $this->_graph->yaxis->SetPos('max'); + $this->_graph->yaxis->SetLabelAlign('center','top'); + $this->_graph->yaxis->SetLabelSide(SIDE_RIGHT); + } + $this->_graph->xaxis->SetTickLabels($datasetLabels); + } + + + $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); + $seriesPlots = array(); + if ($grouping == 'percentStacked') { + $sumValues = $this->_percentageSumCalculation($groupID,$seriesCount); + } + + // Loop through each data series in turn + for($j = 0; $j < $seriesCount; ++$j) { + $dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues(); + if ($grouping == 'percentStacked') { + $dataValues = $this->_percentageAdjustValues($dataValues,$sumValues); + } + + // Fill in any missing values in the $dataValues array + $testCurrentIndex = 0; + foreach($dataValues as $k => $dataValue) { + while($k != $testCurrentIndex) { + $dataValues[$testCurrentIndex] = null; + ++$testCurrentIndex; + } + ++$testCurrentIndex; + } + + // Reverse the $dataValues order for bar rather than column chart + if ($rotation == 'bar') { + $dataValues = array_reverse($dataValues); + } + $seriesPlot = new BarPlot($dataValues); + $seriesPlot->SetColor('black'); + $seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour++]); + if ($dimensions == '3d') { + $seriesPlot->SetShadow(); + } + if (!$this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)) { + $dataLabel = ''; + } else { + $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)->getDataValue(); + } + $seriesPlot->SetLegend($dataLabel); + + $seriesPlots[] = $seriesPlot; + } + // Reverse the plot order for bar rather than column chart + if (($rotation == 'bar') && (!($grouping == 'percentStacked'))) { + $seriesPlots = array_reverse($seriesPlots); + } + + if ($grouping == 'clustered') { + $groupPlot = new GroupBarPlot($seriesPlots); + } elseif ($grouping == 'standard') { + $groupPlot = new GroupBarPlot($seriesPlots); + } else { + $groupPlot = new AccBarPlot($seriesPlots); + if ($dimensions == '3d') { + $groupPlot->SetShadow(); + } + } + + $this->_graph->Add($groupPlot); + } // function _renderPlotBar() + + + private function _renderPlotScatter($groupID,$bubble) { + $grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); + $scatterStyle = $bubbleSize = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); + + $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); + $seriesPlots = array(); + + // Loop through each data series in turn + for($i = 0; $i < $seriesCount; ++$i) { + $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); + $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); + + foreach($dataValuesY as $k => $dataValueY) { + $dataValuesY[$k] = $k; + } + + $seriesPlot = new ScatterPlot($dataValuesX,$dataValuesY); + if ($scatterStyle == 'lineMarker') { + $seriesPlot->SetLinkPoints(); + $seriesPlot->link->SetColor(self::$_colourSet[self::$_plotColour]); + } elseif ($scatterStyle == 'smoothMarker') { + $spline = new Spline($dataValuesY,$dataValuesX); + list($splineDataY,$splineDataX) = $spline->Get(count($dataValuesX) * self::$_width / 20); + $lplot = new LinePlot($splineDataX,$splineDataY); + $lplot->SetColor(self::$_colourSet[self::$_plotColour]); + + $this->_graph->Add($lplot); + } + + if ($bubble) { + $this->_formatPointMarker($seriesPlot,'dot'); + $seriesPlot->mark->SetColor('black'); + $seriesPlot->mark->SetSize($bubbleSize); + } else { + $marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker(); + $this->_formatPointMarker($seriesPlot,$marker); + } + $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue(); + $seriesPlot->SetLegend($dataLabel); + + $this->_graph->Add($seriesPlot); + } + } // function _renderPlotScatter() + + + private function _renderPlotRadar($groupID) { + $radarStyle = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); + + $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); + $seriesPlots = array(); + + // Loop through each data series in turn + for($i = 0; $i < $seriesCount; ++$i) { + $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); + $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); + $marker = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker(); + + $dataValues = array(); + foreach($dataValuesY as $k => $dataValueY) { + $dataValues[$k] = implode(' ',array_reverse($dataValueY)); + } + $tmp = array_shift($dataValues); + $dataValues[] = $tmp; + $tmp = array_shift($dataValuesX); + $dataValuesX[] = $tmp; + + $this->_graph->SetTitles(array_reverse($dataValues)); + + $seriesPlot = new RadarPlot(array_reverse($dataValuesX)); + + $dataLabel = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue(); + $seriesPlot->SetColor(self::$_colourSet[self::$_plotColour++]); + if ($radarStyle == 'filled') { + $seriesPlot->SetFillColor(self::$_colourSet[self::$_plotColour]); + } + $this->_formatPointMarker($seriesPlot,$marker); + $seriesPlot->SetLegend($dataLabel); + + $this->_graph->Add($seriesPlot); + } + } // function _renderPlotRadar() + + + private function _renderPlotContour($groupID) { + $contourStyle = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); + + $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); + $seriesPlots = array(); + + $dataValues = array(); + // Loop through each data series in turn + for($i = 0; $i < $seriesCount; ++$i) { + $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); + $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); + + $dataValues[$i] = $dataValuesX; + } + $seriesPlot = new ContourPlot($dataValues); + + $this->_graph->Add($seriesPlot); + } // function _renderPlotContour() + + + private function _renderPlotStock($groupID) { + $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); + $plotOrder = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder(); + $seriesPlots = array(); + + $dataValues = array(); + // Loop through each data series in turn + for($i = 0; $i < $seriesCount; ++$i) { + $dataValuesY = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); + $dataValuesX = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); + + foreach($dataValuesX as $j => $dataValueX) + $dataValues[$j][$plotOrder[$i]] = $dataValueX; + } + + $seriesPlot = new StockPlot($dataValues); + + $this->_graph->Add($seriesPlot); + } // function _renderPlotStock() + + + private function _renderAreaChart($groupCount, $dimensions = '2d') { + require_once('jpgraph_line.php'); + + $this->_renderCartesianPlotArea(); + + for($i = 0; $i < $groupCount; ++$i) { + $this->_renderPlotLine($i,True,False,$dimensions); + } + } // function _renderAreaChart() + + + private function _renderLineChart($groupCount, $dimensions = '2d') { + require_once('jpgraph_line.php'); + + $this->_renderCartesianPlotArea(); + + for($i = 0; $i < $groupCount; ++$i) { + $this->_renderPlotLine($i,False,False,$dimensions); + } + } // function _renderLineChart() + + + private function _renderBarChart($groupCount, $dimensions = '2d') { + require_once('jpgraph_bar.php'); + + $this->_renderCartesianPlotArea(); + + for($i = 0; $i < $groupCount; ++$i) { + $this->_renderPlotBar($i,$dimensions); + } + } // function _renderBarChart() + + + private function _renderScatterChart($groupCount) { + require_once('jpgraph_scatter.php'); + require_once('jpgraph_regstat.php'); + require_once('jpgraph_line.php'); + + $this->_renderCartesianPlotArea('linlin'); + + for($i = 0; $i < $groupCount; ++$i) { + $this->_renderPlotScatter($i,false); + } + } // function _renderScatterChart() + + + private function _renderBubbleChart($groupCount) { + require_once('jpgraph_scatter.php'); + + $this->_renderCartesianPlotArea('linlin'); + + for($i = 0; $i < $groupCount; ++$i) { + $this->_renderPlotScatter($i,true); + } + } // function _renderBubbleChart() + + + private function _renderPieChart($groupCount, $dimensions = '2d', $doughnut = False, $multiplePlots = False) { + require_once('jpgraph_pie.php'); + if ($dimensions == '3d') { + require_once('jpgraph_pie3d.php'); + } + + $this->_renderPiePlotArea($doughnut); + + $iLimit = ($multiplePlots) ? $groupCount : 1; + for($groupID = 0; $groupID < $iLimit; ++$groupID) { + $grouping = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); + $exploded = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); + if ($groupID == 0) { + $labelCount = count($this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); + if ($labelCount > 0) { + $datasetLabels = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); + $datasetLabels = $this->_formatDataSetLabels($groupID, $datasetLabels, $labelCount); + } + } + + $seriesCount = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); + $seriesPlots = array(); + // For pie charts, we only display the first series: doughnut charts generally display all series + $jLimit = ($multiplePlots) ? $seriesCount : 1; + // Loop through each data series in turn + for($j = 0; $j < $jLimit; ++$j) { + $dataValues = $this->_chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues(); + + // Fill in any missing values in the $dataValues array + $testCurrentIndex = 0; + foreach($dataValues as $k => $dataValue) { + while($k != $testCurrentIndex) { + $dataValues[$testCurrentIndex] = null; + ++$testCurrentIndex; + } + ++$testCurrentIndex; + } + + if ($dimensions == '3d') { + $seriesPlot = new PiePlot3D($dataValues); + } else { + if ($doughnut) { + $seriesPlot = new PiePlotC($dataValues); + } else { + $seriesPlot = new PiePlot($dataValues); + } + } + + if ($multiplePlots) { + $seriesPlot->SetSize(($jLimit-$j) / ($jLimit * 4)); + } + + if ($doughnut) { + $seriesPlot->SetMidColor('white'); + } + + $seriesPlot->SetColor(self::$_colourSet[self::$_plotColour++]); + if (count($datasetLabels) > 0) + $seriesPlot->SetLabels(array_fill(0,count($datasetLabels),'')); + if ($dimensions != '3d') { + $seriesPlot->SetGuideLines(false); + } + if ($j == 0) { + if ($exploded) { + $seriesPlot->ExplodeAll(); + } + $seriesPlot->SetLegends($datasetLabels); + } + + $this->_graph->Add($seriesPlot); + } + } + } // function _renderPieChart() + + + private function _renderRadarChart($groupCount) { + require_once('jpgraph_radar.php'); + + $this->_renderRadarPlotArea(); + + for($groupID = 0; $groupID < $groupCount; ++$groupID) { + $this->_renderPlotRadar($groupID); + } + } // function _renderRadarChart() + + + private function _renderStockChart($groupCount) { + require_once('jpgraph_stock.php'); + + $this->_renderCartesianPlotArea(); + + for($groupID = 0; $groupID < $groupCount; ++$i) { + $this->_renderPlotStock($groupID); + } + } // function _renderStockChart() + + + private function _renderContourChart($groupCount,$dimensions) { + require_once('jpgraph_contour.php'); + + $this->_renderCartesianPlotArea('intint'); + + for($i = 0; $i < $groupCount; ++$i) { + $this->_renderPlotContour($i); + } + } // function _renderContourChart() + + + private function _renderCombinationChart($groupCount,$dimensions,$outputDestination) { + require_once('jpgraph_line.php'); + require_once('jpgraph_bar.php'); + require_once('jpgraph_scatter.php'); + require_once('jpgraph_regstat.php'); + require_once('jpgraph_line.php'); + + $this->_renderCartesianPlotArea(); + + for($i = 0; $i < $groupCount; ++$i) { + $dimensions = null; + $chartType = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType(); + switch ($chartType) { + case 'area3DChart' : + $dimensions = '3d'; + case 'areaChart' : + $this->_renderPlotLine($i,True,True,$dimensions); + break; + case 'bar3DChart' : + $dimensions = '3d'; + case 'barChart' : + $this->_renderPlotBar($i,$dimensions); + break; + case 'line3DChart' : + $dimensions = '3d'; + case 'lineChart' : + $this->_renderPlotLine($i,False,True,$dimensions); + break; + case 'scatterChart' : + $this->_renderPlotScatter($i,false); + break; + case 'bubbleChart' : + $this->_renderPlotScatter($i,true); + break; + default : + $this->_graph = null; + return false; + } + } + + $this->_renderLegend(); + + $this->_graph->Stroke($outputDestination); + return true; + } // function _renderCombinationChart() + + + public function render($outputDestination) { + self::$_plotColour = 0; + + $groupCount = $this->_chart->getPlotArea()->getPlotGroupCount(); + + $dimensions = null; + if ($groupCount == 1) { + $chartType = $this->_chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType(); + } else { + $chartTypes = array(); + for($i = 0; $i < $groupCount; ++$i) { + $chartTypes[] = $this->_chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType(); + } + $chartTypes = array_unique($chartTypes); + if (count($chartTypes) == 1) { + $chartType = array_pop($chartTypes); + } elseif (count($chartTypes) == 0) { + echo 'Chart is not yet implemented
    '; + return false; + } else { + return $this->_renderCombinationChart($groupCount,$dimensions,$outputDestination); + } + } + + switch ($chartType) { + case 'area3DChart' : + $dimensions = '3d'; + case 'areaChart' : + $this->_renderAreaChart($groupCount,$dimensions); + break; + case 'bar3DChart' : + $dimensions = '3d'; + case 'barChart' : + $this->_renderBarChart($groupCount,$dimensions); + break; + case 'line3DChart' : + $dimensions = '3d'; + case 'lineChart' : + $this->_renderLineChart($groupCount,$dimensions); + break; + case 'pie3DChart' : + $dimensions = '3d'; + case 'pieChart' : + $this->_renderPieChart($groupCount,$dimensions,False,False); + break; + case 'doughnut3DChart' : + $dimensions = '3d'; + case 'doughnutChart' : + $this->_renderPieChart($groupCount,$dimensions,True,True); + break; + case 'scatterChart' : + $this->_renderScatterChart($groupCount); + break; + case 'bubbleChart' : + $this->_renderBubbleChart($groupCount); + break; + case 'radarChart' : + $this->_renderRadarChart($groupCount); + break; + case 'surface3DChart' : + $dimensions = '3d'; + case 'surfaceChart' : + $this->_renderContourChart($groupCount,$dimensions); + break; + case 'stockChart' : + $this->_renderStockChart($groupCount,$dimensions); + break; + default : + echo $chartType.' is not yet implemented
    '; + return false; + } + $this->_renderLegend(); + + $this->_graph->Stroke($outputDestination); + return true; + } // function render() + + + /** + * Create a new PHPExcel_Chart_Renderer_jpgraph + */ + public function __construct(PHPExcel_Chart $chart) + { + $this->_graph = null; + $this->_chart = $chart; + } // function __construct() + +} // PHPExcel_Chart_Renderer_jpgraph diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Title.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Title.php new file mode 100755 index 0000000..2046cfd --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Chart/Title.php @@ -0,0 +1,89 @@ +_caption = $caption; + $this->_layout = $layout; + } + + /** + * Get caption + * + * @return string + */ + public function getCaption() { + return $this->_caption; + } + + /** + * Set caption + * + * @param string $caption + */ + public function setCaption($caption = null) { + $this->_caption = $caption; + } + + /** + * Get Layout + * + * @return PHPExcel_Chart_Layout + */ + public function getLayout() { + return $this->_layout; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Comment.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Comment.php new file mode 100755 index 0000000..ef1818e --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Comment.php @@ -0,0 +1,327 @@ +_author = 'Author'; + $this->_text = new PHPExcel_RichText(); + $this->_fillColor = new PHPExcel_Style_Color('FFFFFFE1'); + $this->_alignment = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; + } + + /** + * Get Author + * + * @return string + */ + public function getAuthor() { + return $this->_author; + } + + /** + * Set Author + * + * @param string $pValue + * @return PHPExcel_Comment + */ + public function setAuthor($pValue = '') { + $this->_author = $pValue; + return $this; + } + + /** + * Get Rich text comment + * + * @return PHPExcel_RichText + */ + public function getText() { + return $this->_text; + } + + /** + * Set Rich text comment + * + * @param PHPExcel_RichText $pValue + * @return PHPExcel_Comment + */ + public function setText(PHPExcel_RichText $pValue) { + $this->_text = $pValue; + return $this; + } + + /** + * Get comment width (CSS style, i.e. XXpx or YYpt) + * + * @return string + */ + public function getWidth() { + return $this->_width; + } + + /** + * Set comment width (CSS style, i.e. XXpx or YYpt) + * + * @param string $value + * @return PHPExcel_Comment + */ + public function setWidth($value = '96pt') { + $this->_width = $value; + return $this; + } + + /** + * Get comment height (CSS style, i.e. XXpx or YYpt) + * + * @return string + */ + public function getHeight() { + return $this->_height; + } + + /** + * Set comment height (CSS style, i.e. XXpx or YYpt) + * + * @param string $value + * @return PHPExcel_Comment + */ + public function setHeight($value = '55.5pt') { + $this->_height = $value; + return $this; + } + + /** + * Get left margin (CSS style, i.e. XXpx or YYpt) + * + * @return string + */ + public function getMarginLeft() { + return $this->_marginLeft; + } + + /** + * Set left margin (CSS style, i.e. XXpx or YYpt) + * + * @param string $value + * @return PHPExcel_Comment + */ + public function setMarginLeft($value = '59.25pt') { + $this->_marginLeft = $value; + return $this; + } + + /** + * Get top margin (CSS style, i.e. XXpx or YYpt) + * + * @return string + */ + public function getMarginTop() { + return $this->_marginTop; + } + + /** + * Set top margin (CSS style, i.e. XXpx or YYpt) + * + * @param string $value + * @return PHPExcel_Comment + */ + public function setMarginTop($value = '1.5pt') { + $this->_marginTop = $value; + return $this; + } + + /** + * Is the comment visible by default? + * + * @return boolean + */ + public function getVisible() { + return $this->_visible; + } + + /** + * Set comment default visibility + * + * @param boolean $value + * @return PHPExcel_Comment + */ + public function setVisible($value = false) { + $this->_visible = $value; + return $this; + } + + /** + * Get fill color + * + * @return PHPExcel_Style_Color + */ + public function getFillColor() { + return $this->_fillColor; + } + + /** + * Set Alignment + * + * @param string $pValue + * @return PHPExcel_Comment + */ + public function setAlignment($pValue = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL) { + $this->_alignment = $pValue; + return $this; + } + + /** + * Get Alignment + * + * @return string + */ + public function getAlignment() { + return $this->_alignment; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_author + . $this->_text->getHashCode() + . $this->_width + . $this->_height + . $this->_marginLeft + . $this->_marginTop + . ($this->_visible ? 1 : 0) + . $this->_fillColor->getHashCode() + . $this->_alignment + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } + + /** + * Convert to string + * + * @return string + */ + public function __toString() { + return $this->_text->getPlainText(); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/DocumentProperties.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/DocumentProperties.php new file mode 100755 index 0000000..2a6370a --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/DocumentProperties.php @@ -0,0 +1,587 @@ +_lastModifiedBy = $this->_creator; + $this->_created = time(); + $this->_modified = time(); + } + + /** + * Get Creator + * + * @return string + */ + public function getCreator() { + return $this->_creator; + } + + /** + * Set Creator + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCreator($pValue = '') { + $this->_creator = $pValue; + return $this; + } + + /** + * Get Last Modified By + * + * @return string + */ + public function getLastModifiedBy() { + return $this->_lastModifiedBy; + } + + /** + * Set Last Modified By + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setLastModifiedBy($pValue = '') { + $this->_lastModifiedBy = $pValue; + return $this; + } + + /** + * Get Created + * + * @return datetime + */ + public function getCreated() { + return $this->_created; + } + + /** + * Set Created + * + * @param datetime $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCreated($pValue = null) { + if ($pValue === NULL) { + $pValue = time(); + } elseif (is_string($pValue)) { + if (is_numeric($pValue)) { + $pValue = intval($pValue); + } else { + $pValue = strtotime($pValue); + } + } + + $this->_created = $pValue; + return $this; + } + + /** + * Get Modified + * + * @return datetime + */ + public function getModified() { + return $this->_modified; + } + + /** + * Set Modified + * + * @param datetime $pValue + * @return PHPExcel_DocumentProperties + */ + public function setModified($pValue = null) { + if ($pValue === NULL) { + $pValue = time(); + } elseif (is_string($pValue)) { + if (is_numeric($pValue)) { + $pValue = intval($pValue); + } else { + $pValue = strtotime($pValue); + } + } + + $this->_modified = $pValue; + return $this; + } + + /** + * Get Title + * + * @return string + */ + public function getTitle() { + return $this->_title; + } + + /** + * Set Title + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setTitle($pValue = '') { + $this->_title = $pValue; + return $this; + } + + /** + * Get Description + * + * @return string + */ + public function getDescription() { + return $this->_description; + } + + /** + * Set Description + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setDescription($pValue = '') { + $this->_description = $pValue; + return $this; + } + + /** + * Get Subject + * + * @return string + */ + public function getSubject() { + return $this->_subject; + } + + /** + * Set Subject + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setSubject($pValue = '') { + $this->_subject = $pValue; + return $this; + } + + /** + * Get Keywords + * + * @return string + */ + public function getKeywords() { + return $this->_keywords; + } + + /** + * Set Keywords + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setKeywords($pValue = '') { + $this->_keywords = $pValue; + return $this; + } + + /** + * Get Category + * + * @return string + */ + public function getCategory() { + return $this->_category; + } + + /** + * Set Category + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCategory($pValue = '') { + $this->_category = $pValue; + return $this; + } + + /** + * Get Company + * + * @return string + */ + public function getCompany() { + return $this->_company; + } + + /** + * Set Company + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setCompany($pValue = '') { + $this->_company = $pValue; + return $this; + } + + /** + * Get Manager + * + * @return string + */ + public function getManager() { + return $this->_manager; + } + + /** + * Set Manager + * + * @param string $pValue + * @return PHPExcel_DocumentProperties + */ + public function setManager($pValue = '') { + $this->_manager = $pValue; + return $this; + } + + /** + * Get a List of Custom Property Names + * + * @return array of string + */ + public function getCustomProperties() { + return array_keys($this->_customProperties); + } + + /** + * Check if a Custom Property is defined + * + * @param string $propertyName + * @return boolean + */ + public function isCustomPropertySet($propertyName) { + return isset($this->_customProperties[$propertyName]); + } + + /** + * Get a Custom Property Value + * + * @param string $propertyName + * @return string + */ + public function getCustomPropertyValue($propertyName) { + if (isset($this->_customProperties[$propertyName])) { + return $this->_customProperties[$propertyName]['value']; + } + + } + + /** + * Get a Custom Property Type + * + * @param string $propertyName + * @return string + */ + public function getCustomPropertyType($propertyName) { + if (isset($this->_customProperties[$propertyName])) { + return $this->_customProperties[$propertyName]['type']; + } + + } + + /** + * Set a Custom Property + * + * @param string $propertyName + * @param mixed $propertyValue + * @param string $propertyType + * 'i' : Integer + * 'f' : Floating Point + * 's' : String + * 'd' : Date/Time + * 'b' : Boolean + * @return PHPExcel_DocumentProperties + */ + public function setCustomProperty($propertyName,$propertyValue='',$propertyType=NULL) { + if (($propertyType === NULL) || (!in_array($propertyType,array(self::PROPERTY_TYPE_INTEGER, + self::PROPERTY_TYPE_FLOAT, + self::PROPERTY_TYPE_STRING, + self::PROPERTY_TYPE_DATE, + self::PROPERTY_TYPE_BOOLEAN)))) { + if ($propertyValue === NULL) { + $propertyType = self::PROPERTY_TYPE_STRING; + } elseif (is_float($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_FLOAT; + } elseif(is_int($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_INTEGER; + } elseif (is_bool($propertyValue)) { + $propertyType = self::PROPERTY_TYPE_BOOLEAN; + } else { + $propertyType = self::PROPERTY_TYPE_STRING; + } + } + + $this->_customProperties[$propertyName] = array('value' => $propertyValue, 'type' => $propertyType); + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } + + public static function convertProperty($propertyValue,$propertyType) { + switch ($propertyType) { + case 'empty' : // Empty + return ''; + break; + case 'null' : // Null + return NULL; + break; + case 'i1' : // 1-Byte Signed Integer + case 'i2' : // 2-Byte Signed Integer + case 'i4' : // 4-Byte Signed Integer + case 'i8' : // 8-Byte Signed Integer + case 'int' : // Integer + return (int) $propertyValue; + break; + case 'ui1' : // 1-Byte Unsigned Integer + case 'ui2' : // 2-Byte Unsigned Integer + case 'ui4' : // 4-Byte Unsigned Integer + case 'ui8' : // 8-Byte Unsigned Integer + case 'uint' : // Unsigned Integer + return abs((int) $propertyValue); + break; + case 'r4' : // 4-Byte Real Number + case 'r8' : // 8-Byte Real Number + case 'decimal' : // Decimal + return (float) $propertyValue; + break; + case 'lpstr' : // LPSTR + case 'lpwstr' : // LPWSTR + case 'bstr' : // Basic String + return $propertyValue; + break; + case 'date' : // Date and Time + case 'filetime' : // File Time + return strtotime($propertyValue); + break; + case 'bool' : // Boolean + return ($propertyValue == 'true') ? True : False; + break; + case 'cy' : // Currency + case 'error' : // Error Status Code + case 'vector' : // Vector + case 'array' : // Array + case 'blob' : // Binary Blob + case 'oblob' : // Binary Blob Object + case 'stream' : // Binary Stream + case 'ostream' : // Binary Stream Object + case 'storage' : // Binary Storage + case 'ostorage' : // Binary Storage Object + case 'vstream' : // Binary Versioned Stream + case 'clsid' : // Class ID + case 'cf' : // Clipboard Data + return $propertyValue; + break; + } + return $propertyValue; + } + + public static function convertPropertyType($propertyType) { + switch ($propertyType) { + case 'i1' : // 1-Byte Signed Integer + case 'i2' : // 2-Byte Signed Integer + case 'i4' : // 4-Byte Signed Integer + case 'i8' : // 8-Byte Signed Integer + case 'int' : // Integer + case 'ui1' : // 1-Byte Unsigned Integer + case 'ui2' : // 2-Byte Unsigned Integer + case 'ui4' : // 4-Byte Unsigned Integer + case 'ui8' : // 8-Byte Unsigned Integer + case 'uint' : // Unsigned Integer + return self::PROPERTY_TYPE_INTEGER; + break; + case 'r4' : // 4-Byte Real Number + case 'r8' : // 8-Byte Real Number + case 'decimal' : // Decimal + return self::PROPERTY_TYPE_FLOAT; + break; + case 'empty' : // Empty + case 'null' : // Null + case 'lpstr' : // LPSTR + case 'lpwstr' : // LPWSTR + case 'bstr' : // Basic String + return self::PROPERTY_TYPE_STRING; + break; + case 'date' : // Date and Time + case 'filetime' : // File Time + return self::PROPERTY_TYPE_DATE; + break; + case 'bool' : // Boolean + return self::PROPERTY_TYPE_BOOLEAN; + break; + case 'cy' : // Currency + case 'error' : // Error Status Code + case 'vector' : // Vector + case 'array' : // Array + case 'blob' : // Binary Blob + case 'oblob' : // Binary Blob Object + case 'stream' : // Binary Stream + case 'ostream' : // Binary Stream Object + case 'storage' : // Binary Storage + case 'ostorage' : // Binary Storage Object + case 'vstream' : // Binary Versioned Stream + case 'clsid' : // Class ID + case 'cf' : // Clipboard Data + return self::PROPERTY_TYPE_UNKNOWN; + break; + } + return self::PROPERTY_TYPE_UNKNOWN; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/DocumentSecurity.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/DocumentSecurity.php new file mode 100755 index 0000000..e3e8378 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/DocumentSecurity.php @@ -0,0 +1,218 @@ +_lockRevision = false; + $this->_lockStructure = false; + $this->_lockWindows = false; + $this->_revisionsPassword = ''; + $this->_workbookPassword = ''; + } + + /** + * Is some sort of dcument security enabled? + * + * @return boolean + */ + function isSecurityEnabled() { + return $this->_lockRevision || + $this->_lockStructure || + $this->_lockWindows; + } + + /** + * Get LockRevision + * + * @return boolean + */ + function getLockRevision() { + return $this->_lockRevision; + } + + /** + * Set LockRevision + * + * @param boolean $pValue + * @return PHPExcel_DocumentSecurity + */ + function setLockRevision($pValue = false) { + $this->_lockRevision = $pValue; + return $this; + } + + /** + * Get LockStructure + * + * @return boolean + */ + function getLockStructure() { + return $this->_lockStructure; + } + + /** + * Set LockStructure + * + * @param boolean $pValue + * @return PHPExcel_DocumentSecurity + */ + function setLockStructure($pValue = false) { + $this->_lockStructure = $pValue; + return $this; + } + + /** + * Get LockWindows + * + * @return boolean + */ + function getLockWindows() { + return $this->_lockWindows; + } + + /** + * Set LockWindows + * + * @param boolean $pValue + * @return PHPExcel_DocumentSecurity + */ + function setLockWindows($pValue = false) { + $this->_lockWindows = $pValue; + return $this; + } + + /** + * Get RevisionsPassword (hashed) + * + * @return string + */ + function getRevisionsPassword() { + return $this->_revisionsPassword; + } + + /** + * Set RevisionsPassword + * + * @param string $pValue + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @return PHPExcel_DocumentSecurity + */ + function setRevisionsPassword($pValue = '', $pAlreadyHashed = false) { + if (!$pAlreadyHashed) { + $pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); + } + $this->_revisionsPassword = $pValue; + return $this; + } + + /** + * Get WorkbookPassword (hashed) + * + * @return string + */ + function getWorkbookPassword() { + return $this->_workbookPassword; + } + + /** + * Set WorkbookPassword + * + * @param string $pValue + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @return PHPExcel_DocumentSecurity + */ + function setWorkbookPassword($pValue = '', $pAlreadyHashed = false) { + if (!$pAlreadyHashed) { + $pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); + } + $this->_workbookPassword = $pValue; + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Exception.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Exception.php new file mode 100755 index 0000000..78c9521 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Exception.php @@ -0,0 +1,52 @@ +line = $line; + $e->file = $file; + throw $e; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/HashTable.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/HashTable.php new file mode 100755 index 0000000..100c7ec --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/HashTable.php @@ -0,0 +1,202 @@ +addFromSource($pSource); + } + } + + /** + * Add HashTable items from source + * + * @param PHPExcel_IComparable[] $pSource Source array to create HashTable from + * @throws PHPExcel_Exception + */ + public function addFromSource($pSource = null) { + // Check if an array was passed + if ($pSource == null) { + return; + } else if (!is_array($pSource)) { + throw new PHPExcel_Exception('Invalid array parameter passed.'); + } + + foreach ($pSource as $item) { + $this->add($item); + } + } + + /** + * Add HashTable item + * + * @param PHPExcel_IComparable $pSource Item to add + * @throws PHPExcel_Exception + */ + public function add(PHPExcel_IComparable $pSource = null) { + $hash = $pSource->getHashCode(); + if (!isset($this->_items[$hash])) { + $this->_items[$hash] = $pSource; + $this->_keyMap[count($this->_items) - 1] = $hash; + } + } + + /** + * Remove HashTable item + * + * @param PHPExcel_IComparable $pSource Item to remove + * @throws PHPExcel_Exception + */ + public function remove(PHPExcel_IComparable $pSource = null) { + $hash = $pSource->getHashCode(); + if (isset($this->_items[$hash])) { + unset($this->_items[$hash]); + + $deleteKey = -1; + foreach ($this->_keyMap as $key => $value) { + if ($deleteKey >= 0) { + $this->_keyMap[$key - 1] = $value; + } + + if ($value == $hash) { + $deleteKey = $key; + } + } + unset($this->_keyMap[count($this->_keyMap) - 1]); + } + } + + /** + * Clear HashTable + * + */ + public function clear() { + $this->_items = array(); + $this->_keyMap = array(); + } + + /** + * Count + * + * @return int + */ + public function count() { + return count($this->_items); + } + + /** + * Get index for hash code + * + * @param string $pHashCode + * @return int Index + */ + public function getIndexForHashCode($pHashCode = '') { + return array_search($pHashCode, $this->_keyMap); + } + + /** + * Get by index + * + * @param int $pIndex + * @return PHPExcel_IComparable + * + */ + public function getByIndex($pIndex = 0) { + if (isset($this->_keyMap[$pIndex])) { + return $this->getByHashCode( $this->_keyMap[$pIndex] ); + } + + return null; + } + + /** + * Get by hashcode + * + * @param string $pHashCode + * @return PHPExcel_IComparable + * + */ + public function getByHashCode($pHashCode = '') { + if (isset($this->_items[$pHashCode])) { + return $this->_items[$pHashCode]; + } + + return null; + } + + /** + * HashTable to array + * + * @return PHPExcel_IComparable[] + */ + public function toArray() { + return $this->_items; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/IComparable.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/IComparable.php new file mode 100755 index 0000000..fb1c33c --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/IComparable.php @@ -0,0 +1,43 @@ + 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ), + array( 'type' => 'IReader', 'path' => 'PHPExcel/Reader/{0}.php', 'class' => 'PHPExcel_Reader_{0}' ) + ); + + /** + * Autoresolve classes + * + * @var array + * @access private + * @static + */ + private static $_autoResolveClasses = array( + 'Excel2007', + 'Excel5', + 'Excel2003XML', + 'OOCalc', + 'SYLK', + 'Gnumeric', + 'HTML', + 'CSV', + ); + + /** + * Private constructor for PHPExcel_IOFactory + */ + private function __construct() { } + + /** + * Get search locations + * + * @static + * @access public + * @return array + */ + public static function getSearchLocations() { + return self::$_searchLocations; + } // function getSearchLocations() + + /** + * Set search locations + * + * @static + * @access public + * @param array $value + * @throws PHPExcel_Reader_Exception + */ + public static function setSearchLocations($value) { + if (is_array($value)) { + self::$_searchLocations = $value; + } else { + throw new PHPExcel_Reader_Exception('Invalid parameter passed.'); + } + } // function setSearchLocations() + + /** + * Add search location + * + * @static + * @access public + * @param string $type Example: IWriter + * @param string $location Example: PHPExcel/Writer/{0}.php + * @param string $classname Example: PHPExcel_Writer_{0} + */ + public static function addSearchLocation($type = '', $location = '', $classname = '') { + self::$_searchLocations[] = array( 'type' => $type, 'path' => $location, 'class' => $classname ); + } // function addSearchLocation() + + /** + * Create PHPExcel_Writer_IWriter + * + * @static + * @access public + * @param PHPExcel $phpExcel + * @param string $writerType Example: Excel2007 + * @return PHPExcel_Writer_IWriter + * @throws PHPExcel_Reader_Exception + */ + public static function createWriter(PHPExcel $phpExcel, $writerType = '') { + // Search type + $searchType = 'IWriter'; + + // Include class + foreach (self::$_searchLocations as $searchLocation) { + if ($searchLocation['type'] == $searchType) { + $className = str_replace('{0}', $writerType, $searchLocation['class']); + + $instance = new $className($phpExcel); + if ($instance !== NULL) { + return $instance; + } + } + } + + // Nothing found... + throw new PHPExcel_Reader_Exception("No $searchType found for type $writerType"); + } // function createWriter() + + /** + * Create PHPExcel_Reader_IReader + * + * @static + * @access public + * @param string $readerType Example: Excel2007 + * @return PHPExcel_Reader_IReader + * @throws PHPExcel_Reader_Exception + */ + public static function createReader($readerType = '') { + // Search type + $searchType = 'IReader'; + + // Include class + foreach (self::$_searchLocations as $searchLocation) { + if ($searchLocation['type'] == $searchType) { + $className = str_replace('{0}', $readerType, $searchLocation['class']); + + $instance = new $className(); + if ($instance !== NULL) { + return $instance; + } + } + } + + // Nothing found... + throw new PHPExcel_Reader_Exception("No $searchType found for type $readerType"); + } // function createReader() + + /** + * Loads PHPExcel from file using automatic PHPExcel_Reader_IReader resolution + * + * @static + * @access public + * @param string $pFilename The name of the spreadsheet file + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public static function load($pFilename) { + $reader = self::createReaderForFile($pFilename); + return $reader->load($pFilename); + } // function load() + + /** + * Identify file type using automatic PHPExcel_Reader_IReader resolution + * + * @static + * @access public + * @param string $pFilename The name of the spreadsheet file to identify + * @return string + * @throws PHPExcel_Reader_Exception + */ + public static function identify($pFilename) { + $reader = self::createReaderForFile($pFilename); + $className = get_class($reader); + $classType = explode('_',$className); + unset($reader); + return array_pop($classType); + } // function identify() + + /** + * Create PHPExcel_Reader_IReader for file using automatic PHPExcel_Reader_IReader resolution + * + * @static + * @access public + * @param string $pFilename The name of the spreadsheet file + * @return PHPExcel_Reader_IReader + * @throws PHPExcel_Reader_Exception + */ + public static function createReaderForFile($pFilename) { + + // First, lucky guess by inspecting file extension + $pathinfo = pathinfo($pFilename); + + $extensionType = NULL; + if (isset($pathinfo['extension'])) { + switch (strtolower($pathinfo['extension'])) { + case 'xlsx': // Excel (OfficeOpenXML) Spreadsheet + case 'xlsm': // Excel (OfficeOpenXML) Macro Spreadsheet (macros will be discarded) + case 'xltx': // Excel (OfficeOpenXML) Template + case 'xltm': // Excel (OfficeOpenXML) Macro Template (macros will be discarded) + $extensionType = 'Excel2007'; + break; + case 'xls': // Excel (BIFF) Spreadsheet + case 'xlt': // Excel (BIFF) Template + $extensionType = 'Excel5'; + break; + case 'ods': // Open/Libre Offic Calc + case 'ots': // Open/Libre Offic Calc Template + $extensionType = 'OOCalc'; + break; + case 'slk': + $extensionType = 'SYLK'; + break; + case 'xml': // Excel 2003 SpreadSheetML + $extensionType = 'Excel2003XML'; + break; + case 'gnumeric': + $extensionType = 'Gnumeric'; + break; + case 'htm': + case 'html': + $extensionType = 'HTML'; + break; + case 'csv': + // Do nothing + // We must not try to use CSV reader since it loads + // all files including Excel files etc. + break; + default: + break; + } + + if ($extensionType !== NULL) { + $reader = self::createReader($extensionType); + // Let's see if we are lucky + if (isset($reader) && $reader->canRead($pFilename)) { + return $reader; + } + } + } + + // If we reach here then "lucky guess" didn't give any result + // Try walking through all the options in self::$_autoResolveClasses + foreach (self::$_autoResolveClasses as $autoResolveClass) { + // Ignore our original guess, we know that won't work + if ($autoResolveClass !== $extensionType) { + $reader = self::createReader($autoResolveClass); + if ($reader->canRead($pFilename)) { + return $reader; + } + } + } + + throw new PHPExcel_Reader_Exception('Unable to identify a reader for this file'); + } // function createReaderForFile() +} \ No newline at end of file diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/NamedRange.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/NamedRange.php new file mode 100755 index 0000000..9e7d41e --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/NamedRange.php @@ -0,0 +1,246 @@ +_worksheet) + * + * @var bool + */ + private $_localOnly; + + /** + * Scope + * + * @var PHPExcel_Worksheet + */ + private $_scope; + + /** + * Create a new NamedRange + * + * @param string $pName + * @param PHPExcel_Worksheet $pWorksheet + * @param string $pRange + * @param bool $pLocalOnly + * @param PHPExcel_Worksheet|null $pScope Scope. Only applies when $pLocalOnly = true. Null for global scope. + * @throws PHPExcel_Exception + */ + public function __construct($pName = null, PHPExcel_Worksheet $pWorksheet, $pRange = 'A1', $pLocalOnly = false, $pScope = null) + { + // Validate data + if (($pName === NULL) || ($pWorksheet === NULL) || ($pRange === NULL)) { + throw new PHPExcel_Exception('Parameters can not be null.'); + } + + // Set local members + $this->_name = $pName; + $this->_worksheet = $pWorksheet; + $this->_range = $pRange; + $this->_localOnly = $pLocalOnly; + $this->_scope = ($pLocalOnly == true) ? + (($pScope == null) ? $pWorksheet : $pScope) : null; + } + + /** + * Get name + * + * @return string + */ + public function getName() { + return $this->_name; + } + + /** + * Set name + * + * @param string $value + * @return PHPExcel_NamedRange + */ + public function setName($value = null) { + if ($value !== NULL) { + // Old title + $oldTitle = $this->_name; + + // Re-attach + if ($this->_worksheet !== NULL) { + $this->_worksheet->getParent()->removeNamedRange($this->_name,$this->_worksheet); + } + $this->_name = $value; + + if ($this->_worksheet !== NULL) { + $this->_worksheet->getParent()->addNamedRange($this); + } + + // New title + $newTitle = $this->_name; + PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_worksheet->getParent(), $oldTitle, $newTitle); + } + return $this; + } + + /** + * Get worksheet + * + * @return PHPExcel_Worksheet + */ + public function getWorksheet() { + return $this->_worksheet; + } + + /** + * Set worksheet + * + * @param PHPExcel_Worksheet $value + * @return PHPExcel_NamedRange + */ + public function setWorksheet(PHPExcel_Worksheet $value = null) { + if ($value !== NULL) { + $this->_worksheet = $value; + } + return $this; + } + + /** + * Get range + * + * @return string + */ + public function getRange() { + return $this->_range; + } + + /** + * Set range + * + * @param string $value + * @return PHPExcel_NamedRange + */ + public function setRange($value = null) { + if ($value !== NULL) { + $this->_range = $value; + } + return $this; + } + + /** + * Get localOnly + * + * @return bool + */ + public function getLocalOnly() { + return $this->_localOnly; + } + + /** + * Set localOnly + * + * @param bool $value + * @return PHPExcel_NamedRange + */ + public function setLocalOnly($value = false) { + $this->_localOnly = $value; + $this->_scope = $value ? $this->_worksheet : null; + return $this; + } + + /** + * Get scope + * + * @return PHPExcel_Worksheet|null + */ + public function getScope() { + return $this->_scope; + } + + /** + * Set scope + * + * @param PHPExcel_Worksheet|null $value + * @return PHPExcel_NamedRange + */ + public function setScope(PHPExcel_Worksheet $value = null) { + $this->_scope = $value; + $this->_localOnly = ($value == null) ? false : true; + return $this; + } + + /** + * Resolve a named range to a regular cell range + * + * @param string $pNamedRange Named range + * @param PHPExcel_Worksheet|null $pSheet Scope. Use null for global scope + * @return PHPExcel_NamedRange + */ + public static function resolveRange($pNamedRange = '', PHPExcel_Worksheet $pSheet) { + return $pSheet->getParent()->getNamedRange($pNamedRange, $pSheet); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Abstract.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Abstract.php new file mode 100755 index 0000000..62fe979 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Abstract.php @@ -0,0 +1,227 @@ +_readDataOnly; + } + + /** + * Set read data only + * Set to true, to advise the Reader only to read data values for cells, and to ignore any formatting information. + * Set to false (the default) to advise the Reader to read both data and formatting for cells. + * + * @param boolean $pValue + * + * @return PHPExcel_Reader_IReader + */ + public function setReadDataOnly($pValue = FALSE) { + $this->_readDataOnly = $pValue; + return $this; + } + + /** + * Read charts in workbook? + * If this is true, then the Reader will include any charts that exist in the workbook. + * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. + * If false (the default) it will ignore any charts defined in the workbook file. + * + * @return boolean + */ + public function getIncludeCharts() { + return $this->_includeCharts; + } + + /** + * Set read charts in workbook + * Set to true, to advise the Reader to include any charts that exist in the workbook. + * Note that a ReadDataOnly value of false overrides, and charts won't be read regardless of the IncludeCharts value. + * Set to false (the default) to discard charts. + * + * @param boolean $pValue + * + * @return PHPExcel_Reader_IReader + */ + public function setIncludeCharts($pValue = FALSE) { + $this->_includeCharts = (boolean) $pValue; + return $this; + } + + /** + * Get which sheets to load + * Returns either an array of worksheet names (the list of worksheets that should be loaded), or a null + * indicating that all worksheets in the workbook should be loaded. + * + * @return mixed + */ + public function getLoadSheetsOnly() + { + return $this->_loadSheetsOnly; + } + + /** + * Set which sheets to load + * + * @param mixed $value + * This should be either an array of worksheet names to be loaded, or a string containing a single worksheet name. + * If NULL, then it tells the Reader to read all worksheets in the workbook + * + * @return PHPExcel_Reader_IReader + */ + public function setLoadSheetsOnly($value = NULL) + { + $this->_loadSheetsOnly = is_array($value) ? + $value : array($value); + return $this; + } + + /** + * Set all sheets to load + * Tells the Reader to load all worksheets from the workbook. + * + * @return PHPExcel_Reader_IReader + */ + public function setLoadAllSheets() + { + $this->_loadSheetsOnly = NULL; + return $this; + } + + /** + * Read filter + * + * @return PHPExcel_Reader_IReadFilter + */ + public function getReadFilter() { + return $this->_readFilter; + } + + /** + * Set read filter + * + * @param PHPExcel_Reader_IReadFilter $pValue + * @return PHPExcel_Reader_IReader + */ + public function setReadFilter(PHPExcel_Reader_IReadFilter $pValue) { + $this->_readFilter = $pValue; + return $this; + } + + /** + * Open file for reading + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + * @return resource + */ + protected function _openFile($pFilename) + { + // Check if file exists + if (!file_exists($pFilename) || !is_readable($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Open file + $this->_fileHandle = fopen($pFilename, 'r'); + if ($this->_fileHandle === FALSE) { + throw new PHPExcel_Reader_Exception("Could not open file " . $pFilename . " for reading."); + } + } + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + // Check if file exists + try { + $this->_openFile($pFilename); + } catch (Exception $e) { + return FALSE; + } + + $readable = $this->_isValidFormat(); + fclose ($this->_fileHandle); + return $readable; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/CSV.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/CSV.php new file mode 100755 index 0000000..dbe346e --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/CSV.php @@ -0,0 +1,415 @@ +_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + /** + * Validate that the current file is a CSV file + * + * @return boolean + */ + protected function _isValidFormat() + { + return TRUE; + } + + /** + * Set input encoding + * + * @param string $pValue Input encoding + */ + public function setInputEncoding($pValue = 'UTF-8') + { + $this->_inputEncoding = $pValue; + return $this; + } + + /** + * Get input encoding + * + * @return string + */ + public function getInputEncoding() + { + return $this->_inputEncoding; + } + + /** + * Move filepointer past any BOM marker + * + */ + protected function _skipBOM() + { + rewind($this->_fileHandle); + + switch ($this->_inputEncoding) { + case 'UTF-8': + fgets($this->_fileHandle, 4) == "\xEF\xBB\xBF" ? + fseek($this->_fileHandle, 3) : fseek($this->_fileHandle, 0); + break; + case 'UTF-16LE': + fgets($this->_fileHandle, 3) == "\xFF\xFE" ? + fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0); + break; + case 'UTF-16BE': + fgets($this->_fileHandle, 3) == "\xFE\xFF" ? + fseek($this->_fileHandle, 2) : fseek($this->_fileHandle, 0); + break; + case 'UTF-32LE': + fgets($this->_fileHandle, 5) == "\xFF\xFE\x00\x00" ? + fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0); + break; + case 'UTF-32BE': + fgets($this->_fileHandle, 5) == "\x00\x00\xFE\xFF" ? + fseek($this->_fileHandle, 4) : fseek($this->_fileHandle, 0); + break; + default: + break; + } + } + + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Open file + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + $fileHandle = $this->_fileHandle; + + // Skip BOM, if any + $this->_skipBOM(); + + $escapeEnclosures = array( "\\" . $this->_enclosure, $this->_enclosure . $this->_enclosure ); + + $worksheetInfo = array(); + $worksheetInfo[0]['worksheetName'] = 'Worksheet'; + $worksheetInfo[0]['lastColumnLetter'] = 'A'; + $worksheetInfo[0]['lastColumnIndex'] = 0; + $worksheetInfo[0]['totalRows'] = 0; + $worksheetInfo[0]['totalColumns'] = 0; + + // Loop through each line of the file in turn + while (($rowData = fgetcsv($fileHandle, 0, $this->_delimiter, $this->_enclosure)) !== FALSE) { + $worksheetInfo[0]['totalRows']++; + $worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], count($rowData) - 1); + } + + $worksheetInfo[0]['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex']); + $worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1; + + // Close file + fclose($fileHandle); + + return $worksheetInfo; + } + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + $lineEnding = ini_get('auto_detect_line_endings'); + ini_set('auto_detect_line_endings', true); + + // Open file + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + $fileHandle = $this->_fileHandle; + + // Skip BOM, if any + $this->_skipBOM(); + + // Create new PHPExcel object + while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { + $objPHPExcel->createSheet(); + } + $sheet = $objPHPExcel->setActiveSheetIndex($this->_sheetIndex); + + $escapeEnclosures = array( "\\" . $this->_enclosure, + $this->_enclosure . $this->_enclosure + ); + + // Set our starting row based on whether we're in contiguous mode or not + $currentRow = 1; + if ($this->_contiguous) { + $currentRow = ($this->_contiguousRow == -1) ? $sheet->getHighestRow(): $this->_contiguousRow; + } + + // Loop through each line of the file in turn + while (($rowData = fgetcsv($fileHandle, 0, $this->_delimiter, $this->_enclosure)) !== FALSE) { + $columnLetter = 'A'; + foreach($rowData as $rowDatum) { + if ($rowDatum != '' && $this->_readFilter->readCell($columnLetter, $currentRow)) { + // Unescape enclosures + $rowDatum = str_replace($escapeEnclosures, $this->_enclosure, $rowDatum); + + // Convert encoding if necessary + if ($this->_inputEncoding !== 'UTF-8') { + $rowDatum = PHPExcel_Shared_String::ConvertEncoding($rowDatum, 'UTF-8', $this->_inputEncoding); + } + + // Set cell value + $sheet->getCell($columnLetter . $currentRow)->setValue($rowDatum); + } + ++$columnLetter; + } + ++$currentRow; + } + + // Close file + fclose($fileHandle); + + if ($this->_contiguous) { + $this->_contiguousRow = $currentRow; + } + + ini_set('auto_detect_line_endings', $lineEnding); + + // Return + return $objPHPExcel; + } + + /** + * Get delimiter + * + * @return string + */ + public function getDelimiter() { + return $this->_delimiter; + } + + /** + * Set delimiter + * + * @param string $pValue Delimiter, defaults to , + * @return PHPExcel_Reader_CSV + */ + public function setDelimiter($pValue = ',') { + $this->_delimiter = $pValue; + return $this; + } + + /** + * Get enclosure + * + * @return string + */ + public function getEnclosure() { + return $this->_enclosure; + } + + /** + * Set enclosure + * + * @param string $pValue Enclosure, defaults to " + * @return PHPExcel_Reader_CSV + */ + public function setEnclosure($pValue = '"') { + if ($pValue == '') { + $pValue = '"'; + } + $this->_enclosure = $pValue; + return $this; + } + + /** + * Get line ending + * + * @return string + */ + public function getLineEnding() { + return $this->_lineEnding; + } + + /** + * Set line ending + * + * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL) + * @return PHPExcel_Reader_CSV + */ + public function setLineEnding($pValue = PHP_EOL) { + $this->_lineEnding = $pValue; + return $this; + } + + /** + * Get sheet index + * + * @return integer + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param integer $pValue Sheet index + * @return PHPExcel_Reader_CSV + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } + + /** + * Set Contiguous + * + * @param boolean $contiguous + */ + public function setContiguous($contiguous = FALSE) + { + $this->_contiguous = (bool) $contiguous; + if (!$contiguous) { + $this->_contiguousRow = -1; + } + + return $this; + } + + /** + * Get Contiguous + * + * @return boolean + */ + public function getContiguous() { + return $this->_contiguous; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/DefaultReadFilter.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/DefaultReadFilter.php new file mode 100755 index 0000000..4ab585c --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/DefaultReadFilter.php @@ -0,0 +1,58 @@ +_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + + // Office xmlns:o="urn:schemas-microsoft-com:office:office" + // Excel xmlns:x="urn:schemas-microsoft-com:office:excel" + // XML Spreadsheet xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" + // Spreadsheet component xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" + // XML schema xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" + // XML data type xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" + // MS-persist recordset xmlns:rs="urn:schemas-microsoft-com:rowset" + // Rowset xmlns:z="#RowsetSchema" + // + + $signature = array( + '' + ); + + // Open file + $this->_openFile($pFilename); + $fileHandle = $this->_fileHandle; + + // Read sample data (first 2 KB will do) + $data = fread($fileHandle, 2048); + fclose($fileHandle); + + $valid = true; + foreach($signature as $match) { + // every part of the signature must be present + if (strpos($data, $match) === false) { + $valid = false; + break; + } + } + + // Retrieve charset encoding + if(preg_match('//um',$data,$matches)) { + $this->_charSet = strtoupper($matches[1]); + } +// echo 'Character Set is ',$this->_charSet,'
    '; + + return $valid; + } + + + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + if (!$this->canRead($pFilename)) { + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + + $worksheetNames = array(); + + $xml = simplexml_load_file($pFilename); + $namespaces = $xml->getNamespaces(true); + + $xml_ss = $xml->children($namespaces['ss']); + foreach($xml_ss->Worksheet as $worksheet) { + $worksheet_ss = $worksheet->attributes($namespaces['ss']); + $worksheetNames[] = self::_convertStringEncoding((string) $worksheet_ss['Name'],$this->_charSet); + } + + return $worksheetNames; + } + + + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $worksheetInfo = array(); + + $xml = simplexml_load_file($pFilename); + $namespaces = $xml->getNamespaces(true); + + $worksheetID = 1; + $xml_ss = $xml->children($namespaces['ss']); + foreach($xml_ss->Worksheet as $worksheet) { + $worksheet_ss = $worksheet->attributes($namespaces['ss']); + + $tmpInfo = array(); + $tmpInfo['worksheetName'] = ''; + $tmpInfo['lastColumnLetter'] = 'A'; + $tmpInfo['lastColumnIndex'] = 0; + $tmpInfo['totalRows'] = 0; + $tmpInfo['totalColumns'] = 0; + + if (isset($worksheet_ss['Name'])) { + $tmpInfo['worksheetName'] = (string) $worksheet_ss['Name']; + } else { + $tmpInfo['worksheetName'] = "Worksheet_{$worksheetID}"; + } + + if (isset($worksheet->Table->Row)) { + $rowIndex = 0; + + foreach($worksheet->Table->Row as $rowData) { + $columnIndex = 0; + $rowHasData = false; + + foreach($rowData->Cell as $cell) { + if (isset($cell->Data)) { + $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex); + $rowHasData = true; + } + + ++$columnIndex; + } + + ++$rowIndex; + + if ($rowHasData) { + $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex); + } + } + } + + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; + + $worksheetInfo[] = $tmpInfo; + ++$worksheetID; + } + + return $worksheetInfo; + } + + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + + private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) { + $styleAttributeValue = strtolower($styleAttributeValue); + foreach($styleList as $style) { + if ($styleAttributeValue == strtolower($style)) { + $styleAttributeValue = $style; + return true; + } + } + return false; + } + + + /** + * pixel units to excel width units(units of 1/256th of a character width) + * @param pxs + * @return + */ + private static function _pixel2WidthUnits($pxs) { + $UNIT_OFFSET_MAP = array(0, 36, 73, 109, 146, 182, 219); + + $widthUnits = 256 * ($pxs / 7); + $widthUnits += $UNIT_OFFSET_MAP[($pxs % 7)]; + return $widthUnits; + } + + + /** + * excel width units(units of 1/256th of a character width) to pixel units + * @param widthUnits + * @return + */ + private static function _widthUnits2Pixel($widthUnits) { + $pixels = ($widthUnits / 256) * 7; + $offsetWidthUnits = $widthUnits % 256; + $pixels += round($offsetWidthUnits / (256 / 7)); + return $pixels; + } + + + private static function _hex2str($hex) { + return chr(hexdec($hex[1])); + } + + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + $fromFormats = array('\-', '\ '); + $toFormats = array('-', ' '); + + $underlineStyles = array ( + PHPExcel_Style_Font::UNDERLINE_NONE, + PHPExcel_Style_Font::UNDERLINE_DOUBLE, + PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING, + PHPExcel_Style_Font::UNDERLINE_SINGLE, + PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING + ); + $verticalAlignmentStyles = array ( + PHPExcel_Style_Alignment::VERTICAL_BOTTOM, + PHPExcel_Style_Alignment::VERTICAL_TOP, + PHPExcel_Style_Alignment::VERTICAL_CENTER, + PHPExcel_Style_Alignment::VERTICAL_JUSTIFY + ); + $horizontalAlignmentStyles = array ( + PHPExcel_Style_Alignment::HORIZONTAL_GENERAL, + PHPExcel_Style_Alignment::HORIZONTAL_LEFT, + PHPExcel_Style_Alignment::HORIZONTAL_RIGHT, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS, + PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY + ); + + $timezoneObj = new DateTimeZone('Europe/London'); + $GMT = new DateTimeZone('UTC'); + + + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + if (!$this->canRead($pFilename)) { + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + + $xml = simplexml_load_file($pFilename); + $namespaces = $xml->getNamespaces(true); + + $docProps = $objPHPExcel->getProperties(); + if (isset($xml->DocumentProperties[0])) { + foreach($xml->DocumentProperties[0] as $propertyName => $propertyValue) { + switch ($propertyName) { + case 'Title' : + $docProps->setTitle(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Subject' : + $docProps->setSubject(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Author' : + $docProps->setCreator(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Created' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + break; + case 'LastAuthor' : + $docProps->setLastModifiedBy(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'LastSaved' : + $lastSaveDate = strtotime($propertyValue); + $docProps->setModified($lastSaveDate); + break; + case 'Company' : + $docProps->setCompany(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Category' : + $docProps->setCategory(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Manager' : + $docProps->setManager(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Keywords' : + $docProps->setKeywords(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + case 'Description' : + $docProps->setDescription(self::_convertStringEncoding($propertyValue,$this->_charSet)); + break; + } + } + } + if (isset($xml->CustomDocumentProperties)) { + foreach($xml->CustomDocumentProperties[0] as $propertyName => $propertyValue) { + $propertyAttributes = $propertyValue->attributes($namespaces['dt']); + $propertyName = preg_replace_callback('/_x([0-9a-z]{4})_/','PHPExcel_Reader_Excel2003XML::_hex2str',$propertyName); + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_UNKNOWN; + switch((string) $propertyAttributes) { + case 'string' : + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; + $propertyValue = trim($propertyValue); + break; + case 'boolean' : + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN; + $propertyValue = (bool) $propertyValue; + break; + case 'integer' : + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_INTEGER; + $propertyValue = intval($propertyValue); + break; + case 'float' : + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT; + $propertyValue = floatval($propertyValue); + break; + case 'dateTime.tz' : + $propertyType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE; + $propertyValue = strtotime(trim($propertyValue)); + break; + } + $docProps->setCustomProperty($propertyName,$propertyValue,$propertyType); + } + } + + foreach($xml->Styles[0] as $style) { + $style_ss = $style->attributes($namespaces['ss']); + $styleID = (string) $style_ss['ID']; +// echo 'Style ID = '.$styleID.'
    '; + if ($styleID == 'Default') { + $this->_styles['Default'] = array(); + } else { + $this->_styles[$styleID] = $this->_styles['Default']; + } + foreach ($style as $styleType => $styleData) { + $styleAttributes = $styleData->attributes($namespaces['ss']); +// echo $styleType.'
    '; + switch ($styleType) { + case 'Alignment' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
    '; + $styleAttributeValue = (string) $styleAttributeValue; + switch ($styleAttributeKey) { + case 'Vertical' : + if (self::identifyFixedStyleValue($verticalAlignmentStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['alignment']['vertical'] = $styleAttributeValue; + } + break; + case 'Horizontal' : + if (self::identifyFixedStyleValue($horizontalAlignmentStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['alignment']['horizontal'] = $styleAttributeValue; + } + break; + case 'WrapText' : + $this->_styles[$styleID]['alignment']['wrap'] = true; + break; + } + } + break; + case 'Borders' : + foreach($styleData->Border as $borderStyle) { + $borderAttributes = $borderStyle->attributes($namespaces['ss']); + $thisBorder = array(); + foreach($borderAttributes as $borderStyleKey => $borderStyleValue) { +// echo $borderStyleKey.' = '.$borderStyleValue.'
    '; + switch ($borderStyleKey) { + case 'LineStyle' : + $thisBorder['style'] = PHPExcel_Style_Border::BORDER_MEDIUM; +// $thisBorder['style'] = $borderStyleValue; + break; + case 'Weight' : +// $thisBorder['style'] = $borderStyleValue; + break; + case 'Position' : + $borderPosition = strtolower($borderStyleValue); + break; + case 'Color' : + $borderColour = substr($borderStyleValue,1); + $thisBorder['color']['rgb'] = $borderColour; + break; + } + } + if (!empty($thisBorder)) { + if (($borderPosition == 'left') || ($borderPosition == 'right') || ($borderPosition == 'top') || ($borderPosition == 'bottom')) { + $this->_styles[$styleID]['borders'][$borderPosition] = $thisBorder; + } + } + } + break; + case 'Font' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
    '; + $styleAttributeValue = (string) $styleAttributeValue; + switch ($styleAttributeKey) { + case 'FontName' : + $this->_styles[$styleID]['font']['name'] = $styleAttributeValue; + break; + case 'Size' : + $this->_styles[$styleID]['font']['size'] = $styleAttributeValue; + break; + case 'Color' : + $this->_styles[$styleID]['font']['color']['rgb'] = substr($styleAttributeValue,1); + break; + case 'Bold' : + $this->_styles[$styleID]['font']['bold'] = true; + break; + case 'Italic' : + $this->_styles[$styleID]['font']['italic'] = true; + break; + case 'Underline' : + if (self::identifyFixedStyleValue($underlineStyles,$styleAttributeValue)) { + $this->_styles[$styleID]['font']['underline'] = $styleAttributeValue; + } + break; + } + } + break; + case 'Interior' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
    '; + switch ($styleAttributeKey) { + case 'Color' : + $this->_styles[$styleID]['fill']['color']['rgb'] = substr($styleAttributeValue,1); + break; + } + } + break; + case 'NumberFormat' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
    '; + $styleAttributeValue = str_replace($fromFormats,$toFormats,$styleAttributeValue); + switch ($styleAttributeValue) { + case 'Short Date' : + $styleAttributeValue = 'dd/mm/yyyy'; + break; + } + if ($styleAttributeValue > '') { + $this->_styles[$styleID]['numberformat']['code'] = $styleAttributeValue; + } + } + break; + case 'Protection' : + foreach($styleAttributes as $styleAttributeKey => $styleAttributeValue) { +// echo $styleAttributeKey.' = '.$styleAttributeValue.'
    '; + } + break; + } + } +// print_r($this->_styles[$styleID]); +// echo '
    '; + } +// echo '
    '; + + $worksheetID = 0; + $xml_ss = $xml->children($namespaces['ss']); + + foreach($xml_ss->Worksheet as $worksheet) { + $worksheet_ss = $worksheet->attributes($namespaces['ss']); + + if ((isset($this->_loadSheetsOnly)) && (isset($worksheet_ss['Name'])) && + (!in_array($worksheet_ss['Name'], $this->_loadSheetsOnly))) { + continue; + } + +// echo '

    Worksheet: ',$worksheet_ss['Name'],'

    '; +// + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + if (isset($worksheet_ss['Name'])) { + $worksheetName = self::_convertStringEncoding((string) $worksheet_ss['Name'],$this->_charSet); + // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in + // formula cells... during the load, all formulae should be correct, and we're simply bringing + // the worksheet name in line with the formula, not the reverse + $objPHPExcel->getActiveSheet()->setTitle($worksheetName,false); + } + + $columnID = 'A'; + if (isset($worksheet->Table->Column)) { + foreach($worksheet->Table->Column as $columnData) { + $columnData_ss = $columnData->attributes($namespaces['ss']); + if (isset($columnData_ss['Index'])) { + $columnID = PHPExcel_Cell::stringFromColumnIndex($columnData_ss['Index']-1); + } + if (isset($columnData_ss['Width'])) { + $columnWidth = $columnData_ss['Width']; +// echo 'Setting column width for '.$columnID.' to '.$columnWidth.'
    '; + $objPHPExcel->getActiveSheet()->getColumnDimension($columnID)->setWidth($columnWidth / 5.4); + } + ++$columnID; + } + } + + $rowID = 1; + if (isset($worksheet->Table->Row)) { + foreach($worksheet->Table->Row as $rowData) { + $rowHasData = false; + $row_ss = $rowData->attributes($namespaces['ss']); + if (isset($row_ss['Index'])) { + $rowID = (integer) $row_ss['Index']; + } +// echo 'Row '.$rowID.'
    '; + + $columnID = 'A'; + foreach($rowData->Cell as $cell) { + + $cell_ss = $cell->attributes($namespaces['ss']); + if (isset($cell_ss['Index'])) { + $columnID = PHPExcel_Cell::stringFromColumnIndex($cell_ss['Index']-1); + } + $cellRange = $columnID.$rowID; + + if ($this->getReadFilter() !== NULL) { + if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) { + continue; + } + } + + if ((isset($cell_ss['MergeAcross'])) || (isset($cell_ss['MergeDown']))) { + $columnTo = $columnID; + if (isset($cell_ss['MergeAcross'])) { + $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cell_ss['MergeAcross'] -1); + } + $rowTo = $rowID; + if (isset($cell_ss['MergeDown'])) { + $rowTo = $rowTo + $cell_ss['MergeDown']; + } + $cellRange .= ':'.$columnTo.$rowTo; + $objPHPExcel->getActiveSheet()->mergeCells($cellRange); + } + + $cellIsSet = $hasCalculatedValue = false; + $cellDataFormula = ''; + if (isset($cell_ss['Formula'])) { + $cellDataFormula = $cell_ss['Formula']; + // added this as a check for array formulas + if (isset($cell_ss['ArrayRange'])) { + $cellDataCSEFormula = $cell_ss['ArrayRange']; +// echo "found an array formula at ".$columnID.$rowID."
    "; + } + $hasCalculatedValue = true; + } + if (isset($cell->Data)) { + $cellValue = $cellData = $cell->Data; + $type = PHPExcel_Cell_DataType::TYPE_NULL; + $cellData_ss = $cellData->attributes($namespaces['ss']); + if (isset($cellData_ss['Type'])) { + $cellDataType = $cellData_ss['Type']; + switch ($cellDataType) { + /* + const TYPE_STRING = 's'; + const TYPE_FORMULA = 'f'; + const TYPE_NUMERIC = 'n'; + const TYPE_BOOL = 'b'; + const TYPE_NULL = 'null'; + const TYPE_INLINE = 'inlineStr'; + const TYPE_ERROR = 'e'; + */ + case 'String' : + $cellValue = self::_convertStringEncoding($cellValue,$this->_charSet); + $type = PHPExcel_Cell_DataType::TYPE_STRING; + break; + case 'Number' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $cellValue = (float) $cellValue; + if (floor($cellValue) == $cellValue) { + $cellValue = (integer) $cellValue; + } + break; + case 'Boolean' : + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $cellValue = ($cellValue != 0); + break; + case 'DateTime' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $cellValue = PHPExcel_Shared_Date::PHPToExcel(strtotime($cellValue)); + break; + case 'Error' : + $type = PHPExcel_Cell_DataType::TYPE_ERROR; + break; + } + } + + if ($hasCalculatedValue) { +// echo 'FORMULA
    '; + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; + $columnNumber = PHPExcel_Cell::columnIndexFromString($columnID); + if (substr($cellDataFormula,0,3) == 'of:') { + $cellDataFormula = substr($cellDataFormula,3); +// echo 'Before: ',$cellDataFormula,'
    '; + $temp = explode('"',$cellDataFormula); + $key = false; + foreach($temp as &$value) { + // Only replace in alternate array entries (i.e. non-quoted blocks) + if ($key = !$key) { + $value = str_replace(array('[.','.',']'),'',$value); + } + } + } else { + // Convert R1C1 style references to A1 style references (but only when not quoted) +// echo 'Before: ',$cellDataFormula,'
    '; + $temp = explode('"',$cellDataFormula); + $key = false; + foreach($temp as &$value) { + // Only replace in alternate array entries (i.e. non-quoted blocks) + if ($key = !$key) { + preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE); + // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way + // through the formula from left to right. Reversing means that we work right to left.through + // the formula + $cellReferences = array_reverse($cellReferences); + // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, + // then modify the formula to use that new reference + foreach($cellReferences as $cellReference) { + $rowReference = $cellReference[2][0]; + // Empty R reference is the current row + if ($rowReference == '') $rowReference = $rowID; + // Bracketed R references are relative to the current row + if ($rowReference{0} == '[') $rowReference = $rowID + trim($rowReference,'[]'); + $columnReference = $cellReference[4][0]; + // Empty C reference is the current column + if ($columnReference == '') $columnReference = $columnNumber; + // Bracketed C references are relative to the current column + if ($columnReference{0} == '[') $columnReference = $columnNumber + trim($columnReference,'[]'); + $A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; + $value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0])); + } + } + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); +// echo 'After: ',$cellDataFormula,'
    '; + } + +// echo 'Cell '.$columnID.$rowID.' is a '.$type.' with a value of '.(($hasCalculatedValue) ? $cellDataFormula : $cellValue).'
    '; +// + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $cellValue),$type); + if ($hasCalculatedValue) { +// echo 'Formula result is '.$cellValue.'
    '; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setCalculatedValue($cellValue); + } + $cellIsSet = $rowHasData = true; + } + + if (isset($cell->Comment)) { +// echo 'comment found
    '; + $commentAttributes = $cell->Comment->attributes($namespaces['ss']); + $author = 'unknown'; + if (isset($commentAttributes->Author)) { + $author = (string)$commentAttributes->Author; +// echo 'Author: ',$author,'
    '; + } + $node = $cell->Comment->Data->asXML(); +// $annotation = str_replace('html:','',substr($node,49,-10)); +// echo $annotation,'
    '; + $annotation = strip_tags($node); +// echo 'Annotation: ',$annotation,'
    '; + $objPHPExcel->getActiveSheet()->getComment( $columnID.$rowID ) + ->setAuthor(self::_convertStringEncoding($author ,$this->_charSet)) + ->setText($this->_parseRichText($annotation) ); + } + + if (($cellIsSet) && (isset($cell_ss['StyleID']))) { + $style = (string) $cell_ss['StyleID']; +// echo 'Cell style for '.$columnID.$rowID.' is '.$style.'
    '; + if ((isset($this->_styles[$style])) && (!empty($this->_styles[$style]))) { +// echo 'Cell '.$columnID.$rowID.'
    '; +// print_r($this->_styles[$style]); +// echo '
    '; + if (!$objPHPExcel->getActiveSheet()->cellExists($columnID.$rowID)) { + $objPHPExcel->getActiveSheet()->getCell($columnID.$rowID)->setValue(NULL); + } + $objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($this->_styles[$style]); + } + } + ++$columnID; + } + + if ($rowHasData) { + if (isset($row_ss['StyleID'])) { + $rowStyle = $row_ss['StyleID']; + } + if (isset($row_ss['Height'])) { + $rowHeight = $row_ss['Height']; +// echo 'Setting row height to '.$rowHeight.'
    '; + $objPHPExcel->getActiveSheet()->getRowDimension($rowID)->setRowHeight($rowHeight); + } + } + + ++$rowID; + } + } + ++$worksheetID; + } + + // Return + return $objPHPExcel; + } + + + private static function _convertStringEncoding($string,$charset) { + if ($charset != 'UTF-8') { + return PHPExcel_Shared_String::ConvertEncoding($string,'UTF-8',$charset); + } + return $string; + } + + + private function _parseRichText($is = '') { + $value = new PHPExcel_RichText(); + + $value->createText(self::_convertStringEncoding($is,$this->_charSet)); + + return $value; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007.php new file mode 100755 index 0000000..6e9a420 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007.php @@ -0,0 +1,1982 @@ +_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + $this->_referenceHelper = PHPExcel_ReferenceHelper::getInstance(); + } + + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Check if zip class exists + if (!class_exists('ZipArchive',FALSE)) { + throw new PHPExcel_Reader_Exception("ZipArchive library is not enabled"); + } + + $xl = false; + // Load file + $zip = new ZipArchive; + if ($zip->open($pFilename) === true) { + // check if it is an OOXML archive + $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); + if ($rels !== false) { + foreach ($rels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": + if (basename($rel["Target"]) == 'workbook.xml') { + $xl = true; + } + break; + + } + } + } + $zip->close(); + } + + return $xl; + } + + + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $worksheetNames = array(); + + $zip = new ZipArchive; + $zip->open($pFilename); + + // The files we're looking at here are small enough that simpleXML is more efficient than XMLReader + $rels = simplexml_load_string( + $this->_getFromZipArchive($zip, "_rels/.rels") + ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($rels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": + $xmlWorkbook = simplexml_load_string( + $this->_getFromZipArchive($zip, "{$rel['Target']}") + ); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + + if ($xmlWorkbook->sheets) { + foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { + // Check if sheet should be skipped + $worksheetNames[] = (string) $eleSheet["name"]; + } + } + } + } + + $zip->close(); + + return $worksheetNames; + } + + + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $worksheetInfo = array(); + + $zip = new ZipArchive; + $zip->open($pFilename); + + $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($rels->Relationship as $rel) { + if ($rel["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument") { + $dir = dirname($rel["Target"]); + $relsWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); + + $worksheets = array(); + foreach ($relsWorkbook->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet") { + $worksheets[(string) $ele["Id"]] = $ele["Target"]; + } + } + + $xmlWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + if ($xmlWorkbook->sheets) { + $dir = dirname($rel["Target"]); + foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { + $tmpInfo = array( + 'worksheetName' => (string) $eleSheet["name"], + 'lastColumnLetter' => 'A', + 'lastColumnIndex' => 0, + 'totalRows' => 0, + 'totalColumns' => 0, + ); + + $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; + + $xml = new XMLReader(); + $res = $xml->open('zip://'.PHPExcel_Shared_File::realpath($pFilename).'#'."$dir/$fileWorksheet"); + $xml->setParserProperty(2,true); + + $currCells = 0; + while ($xml->read()) { + if ($xml->name == 'row' && $xml->nodeType == XMLReader::ELEMENT) { + $row = $xml->getAttribute('r'); + $tmpInfo['totalRows'] = $row; + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $currCells = 0; + } elseif ($xml->name == 'c' && $xml->nodeType == XMLReader::ELEMENT) { + $currCells++; + } + } + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $xml->close(); + + $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1; + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + + $worksheetInfo[] = $tmpInfo; + } + } + } + } + + $zip->close(); + + return $worksheetInfo; + } + + + private static function _castToBool($c) { +// echo 'Initial Cast to Boolean
    '; + $value = isset($c->v) ? (string) $c->v : NULL; + if ($value == '0') { + return FALSE; + } elseif ($value == '1') { + return TRUE; + } else { + return (bool)$c->v; + } + return $value; + } // function _castToBool() + + + private static function _castToError($c) { +// echo 'Initial Cast to Error
    '; + return isset($c->v) ? (string) $c->v : NULL; + } // function _castToError() + + + private static function _castToString($c) { +// echo 'Initial Cast to String
    '; + return isset($c->v) ? (string) $c->v : NULL; + } // function _castToString() + + + private function _castToFormula($c,$r,&$cellDataType,&$value,&$calculatedValue,&$sharedFormulas,$castBaseType) { +// echo 'Formula
    '; +// echo '$c->f is '.$c->f.'
    '; + $cellDataType = 'f'; + $value = "={$c->f}"; + $calculatedValue = self::$castBaseType($c); + + // Shared formula? + if (isset($c->f['t']) && strtolower((string)$c->f['t']) == 'shared') { +// echo 'SHARED FORMULA
    '; + $instance = (string)$c->f['si']; + +// echo 'Instance ID = '.$instance.'
    '; +// +// echo 'Shared Formula Array:
    ';
    +//			print_r($sharedFormulas);
    +//			echo '
    '; + if (!isset($sharedFormulas[(string)$c->f['si']])) { +// echo 'SETTING NEW SHARED FORMULA
    '; +// echo 'Master is '.$r.'
    '; +// echo 'Formula is '.$value.'
    '; + $sharedFormulas[$instance] = array( 'master' => $r, + 'formula' => $value + ); +// echo 'New Shared Formula Array:
    ';
    +//				print_r($sharedFormulas);
    +//				echo '
    '; + } else { +// echo 'GETTING SHARED FORMULA
    '; +// echo 'Master is '.$sharedFormulas[$instance]['master'].'
    '; +// echo 'Formula is '.$sharedFormulas[$instance]['formula'].'
    '; + $master = PHPExcel_Cell::coordinateFromString($sharedFormulas[$instance]['master']); + $current = PHPExcel_Cell::coordinateFromString($r); + + $difference = array(0, 0); + $difference[0] = PHPExcel_Cell::columnIndexFromString($current[0]) - PHPExcel_Cell::columnIndexFromString($master[0]); + $difference[1] = $current[1] - $master[1]; + + $value = $this->_referenceHelper->updateFormulaReferences( $sharedFormulas[$instance]['formula'], + 'A1', + $difference[0], + $difference[1] + ); +// echo 'Adjusted Formula is '.$value.'
    '; + } + } + } + + + public function _getFromZipArchive(ZipArchive $archive, $fileName = '') + { + // Root-relative paths + if (strpos($fileName, '//') !== false) + { + $fileName = substr($fileName, strpos($fileName, '//') + 1); + } + $fileName = PHPExcel_Shared_File::realpath($fileName); + + // Apache POI fixes + $contents = $archive->getFromName($fileName); + if ($contents === false) + { + $contents = $archive->getFromName(substr($fileName, 1)); + } + + return $contents; + } + + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Initialisations + $excel = new PHPExcel; + $excel->removeSheetByIndex(0); + if (!$this->_readDataOnly) { + $excel->removeCellStyleXfByIndex(0); // remove the default style + $excel->removeCellXfByIndex(0); // remove the default style + } + $zip = new ZipArchive; + $zip->open($pFilename); + + // Read the theme first, because we need the colour scheme when reading the styles + $wbRels = simplexml_load_string($this->_getFromZipArchive($zip, "xl/_rels/workbook.xml.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($wbRels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme": + $themeOrderArray = array('lt1','dk1','lt2','dk2'); + $themeOrderAdditional = count($themeOrderArray); + + $xmlTheme = simplexml_load_string($this->_getFromZipArchive($zip, "xl/{$rel['Target']}")); + if (is_object($xmlTheme)) { + $xmlThemeName = $xmlTheme->attributes(); + $xmlTheme = $xmlTheme->children("http://schemas.openxmlformats.org/drawingml/2006/main"); + $themeName = (string)$xmlThemeName['name']; + + $colourScheme = $xmlTheme->themeElements->clrScheme->attributes(); + $colourSchemeName = (string)$colourScheme['name']; + $colourScheme = $xmlTheme->themeElements->clrScheme->children("http://schemas.openxmlformats.org/drawingml/2006/main"); + + $themeColours = array(); + foreach ($colourScheme as $k => $xmlColour) { + $themePos = array_search($k,$themeOrderArray); + if ($themePos === false) { + $themePos = $themeOrderAdditional++; + } + if (isset($xmlColour->sysClr)) { + $xmlColourData = $xmlColour->sysClr->attributes(); + $themeColours[$themePos] = $xmlColourData['lastClr']; + } elseif (isset($xmlColour->srgbClr)) { + $xmlColourData = $xmlColour->srgbClr->attributes(); + $themeColours[$themePos] = $xmlColourData['val']; + } + } + self::$_theme = new PHPExcel_Reader_Excel2007_Theme($themeName,$colourSchemeName,$themeColours); + } + break; + } + } + + $rels = simplexml_load_string($this->_getFromZipArchive($zip, "_rels/.rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($rels->Relationship as $rel) { + switch ($rel["Type"]) { + case "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties": + $xmlCore = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); + if (is_object($xmlCore)) { + $xmlCore->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/"); + $xmlCore->registerXPathNamespace("dcterms", "http://purl.org/dc/terms/"); + $xmlCore->registerXPathNamespace("cp", "http://schemas.openxmlformats.org/package/2006/metadata/core-properties"); + $docProps = $excel->getProperties(); + $docProps->setCreator((string) self::array_item($xmlCore->xpath("dc:creator"))); + $docProps->setLastModifiedBy((string) self::array_item($xmlCore->xpath("cp:lastModifiedBy"))); + $docProps->setCreated(strtotime(self::array_item($xmlCore->xpath("dcterms:created")))); //! respect xsi:type + $docProps->setModified(strtotime(self::array_item($xmlCore->xpath("dcterms:modified")))); //! respect xsi:type + $docProps->setTitle((string) self::array_item($xmlCore->xpath("dc:title"))); + $docProps->setDescription((string) self::array_item($xmlCore->xpath("dc:description"))); + $docProps->setSubject((string) self::array_item($xmlCore->xpath("dc:subject"))); + $docProps->setKeywords((string) self::array_item($xmlCore->xpath("cp:keywords"))); + $docProps->setCategory((string) self::array_item($xmlCore->xpath("cp:category"))); + } + break; + + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties": + $xmlCore = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); + if (is_object($xmlCore)) { + $docProps = $excel->getProperties(); + if (isset($xmlCore->Company)) + $docProps->setCompany((string) $xmlCore->Company); + if (isset($xmlCore->Manager)) + $docProps->setManager((string) $xmlCore->Manager); + } + break; + + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties": + $xmlCore = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); + if (is_object($xmlCore)) { + $docProps = $excel->getProperties(); + foreach ($xmlCore as $xmlProperty) { + $cellDataOfficeAttributes = $xmlProperty->attributes(); + if (isset($cellDataOfficeAttributes['name'])) { + $propertyName = (string) $cellDataOfficeAttributes['name']; + $cellDataOfficeChildren = $xmlProperty->children('http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); + $attributeType = $cellDataOfficeChildren->getName(); + $attributeValue = (string) $cellDataOfficeChildren->{$attributeType}; + $attributeValue = PHPExcel_DocumentProperties::convertProperty($attributeValue,$attributeType); + $attributeType = PHPExcel_DocumentProperties::convertPropertyType($attributeType); + $docProps->setCustomProperty($propertyName,$attributeValue,$attributeType); + } + } + } + break; + + case "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument": + $dir = dirname($rel["Target"]); + $relsWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/_rels/" . basename($rel["Target"]) . ".rels")); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $relsWorkbook->registerXPathNamespace("rel", "http://schemas.openxmlformats.org/package/2006/relationships"); + + $sharedStrings = array(); + $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings']")); + $xmlStrings = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + if (isset($xmlStrings) && isset($xmlStrings->si)) { + foreach ($xmlStrings->si as $val) { + if (isset($val->t)) { + $sharedStrings[] = PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $val->t ); + } elseif (isset($val->r)) { + $sharedStrings[] = $this->_parseRichText($val); + } + } + } + + $worksheets = array(); + foreach ($relsWorkbook->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet") { + $worksheets[(string) $ele["Id"]] = $ele["Target"]; + } + } + + $styles = array(); + $cellStyles = array(); + $xpath = self::array_item($relsWorkbook->xpath("rel:Relationship[@Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles']")); + $xmlStyles = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$xpath[Target]")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $numFmts = null; + if ($xmlStyles && $xmlStyles->numFmts[0]) { + $numFmts = $xmlStyles->numFmts[0]; + } + if (isset($numFmts) && ($numFmts !== NULL)) { + $numFmts->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + } + if (!$this->_readDataOnly && $xmlStyles) { + foreach ($xmlStyles->cellXfs->xf as $xf) { + $numFmt = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + + if ($xf["numFmtId"]) { + if (isset($numFmts)) { + $tmpNumFmt = self::array_item($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]")); + + if (isset($tmpNumFmt["formatCode"])) { + $numFmt = (string) $tmpNumFmt["formatCode"]; + } + } + + if ((int)$xf["numFmtId"] < 164) { + $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]); + } + } + //$numFmt = str_replace('mm', 'i', $numFmt); + //$numFmt = str_replace('h', 'H', $numFmt); + + $style = (object) array( + "numFmt" => $numFmt, + "font" => $xmlStyles->fonts->font[intval($xf["fontId"])], + "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])], + "border" => $xmlStyles->borders->border[intval($xf["borderId"])], + "alignment" => $xf->alignment, + "protection" => $xf->protection, + ); + $styles[] = $style; + + // add style to cellXf collection + $objStyle = new PHPExcel_Style; + self::_readStyle($objStyle, $style); + $excel->addCellXf($objStyle); + } + + foreach ($xmlStyles->cellStyleXfs->xf as $xf) { + $numFmt = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + if ($numFmts && $xf["numFmtId"]) { + $tmpNumFmt = self::array_item($numFmts->xpath("sml:numFmt[@numFmtId=$xf[numFmtId]]")); + if (isset($tmpNumFmt["formatCode"])) { + $numFmt = (string) $tmpNumFmt["formatCode"]; + } else if ((int)$xf["numFmtId"] < 165) { + $numFmt = PHPExcel_Style_NumberFormat::builtInFormatCode((int)$xf["numFmtId"]); + } + } + + $cellStyle = (object) array( + "numFmt" => $numFmt, + "font" => $xmlStyles->fonts->font[intval($xf["fontId"])], + "fill" => $xmlStyles->fills->fill[intval($xf["fillId"])], + "border" => $xmlStyles->borders->border[intval($xf["borderId"])], + "alignment" => $xf->alignment, + "protection" => $xf->protection, + ); + $cellStyles[] = $cellStyle; + + // add style to cellStyleXf collection + $objStyle = new PHPExcel_Style; + self::_readStyle($objStyle, $cellStyle); + $excel->addCellStyleXf($objStyle); + } + } + + $dxfs = array(); + if (!$this->_readDataOnly && $xmlStyles) { + // Conditional Styles + if ($xmlStyles->dxfs) { + foreach ($xmlStyles->dxfs->dxf as $dxf) { + $style = new PHPExcel_Style(FALSE, TRUE); + self::_readStyle($style, $dxf); + $dxfs[] = $style; + } + } + // Cell Styles + if ($xmlStyles->cellStyles) { + foreach ($xmlStyles->cellStyles->cellStyle as $cellStyle) { + if (intval($cellStyle['builtinId']) == 0) { + if (isset($cellStyles[intval($cellStyle['xfId'])])) { + // Set default style + $style = new PHPExcel_Style; + self::_readStyle($style, $cellStyles[intval($cellStyle['xfId'])]); + + // normal style, currently not using it for anything + } + } + } + } + } + + $xmlWorkbook = simplexml_load_string($this->_getFromZipArchive($zip, "{$rel['Target']}")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + + // Set base date + if ($xmlWorkbook->workbookPr) { + PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900); + if (isset($xmlWorkbook->workbookPr['date1904'])) { + if (self::boolean((string) $xmlWorkbook->workbookPr['date1904'])) { + PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_MAC_1904); + } + } + } + + $sheetId = 0; // keep track of new sheet id in final workbook + $oldSheetId = -1; // keep track of old sheet id in final workbook + $countSkippedSheets = 0; // keep track of number of skipped sheets + $mapSheetId = array(); // mapping of sheet ids from old to new + + + $charts = $chartDetails = array(); + + if ($xmlWorkbook->sheets) { + foreach ($xmlWorkbook->sheets->sheet as $eleSheet) { + ++$oldSheetId; + + // Check if sheet should be skipped + if (isset($this->_loadSheetsOnly) && !in_array((string) $eleSheet["name"], $this->_loadSheetsOnly)) { + ++$countSkippedSheets; + $mapSheetId[$oldSheetId] = null; + continue; + } + + // Map old sheet id in original workbook to new sheet id. + // They will differ if loadSheetsOnly() is being used + $mapSheetId[$oldSheetId] = $oldSheetId - $countSkippedSheets; + + // Load sheet + $docSheet = $excel->createSheet(); + // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet + // references in formula cells... during the load, all formulae should be correct, + // and we're simply bringing the worksheet name in line with the formula, not the + // reverse + $docSheet->setTitle((string) $eleSheet["name"],false); + $fileWorksheet = $worksheets[(string) self::array_item($eleSheet->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; + $xmlSheet = simplexml_load_string($this->_getFromZipArchive($zip, "$dir/$fileWorksheet")); //~ http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + + $sharedFormulas = array(); + + if (isset($eleSheet["state"]) && (string) $eleSheet["state"] != '') { + $docSheet->setSheetState( (string) $eleSheet["state"] ); + } + + if (isset($xmlSheet->sheetViews) && isset($xmlSheet->sheetViews->sheetView)) { + if (isset($xmlSheet->sheetViews->sheetView['zoomScale'])) { + $docSheet->getSheetView()->setZoomScale( intval($xmlSheet->sheetViews->sheetView['zoomScale']) ); + } + + if (isset($xmlSheet->sheetViews->sheetView['zoomScaleNormal'])) { + $docSheet->getSheetView()->setZoomScaleNormal( intval($xmlSheet->sheetViews->sheetView['zoomScaleNormal']) ); + } + + if (isset($xmlSheet->sheetViews->sheetView['view'])) { + $docSheet->getSheetView()->setView((string) $xmlSheet->sheetViews->sheetView['view']); + } + + if (isset($xmlSheet->sheetViews->sheetView['showGridLines'])) { + $docSheet->setShowGridLines(self::boolean((string)$xmlSheet->sheetViews->sheetView['showGridLines'])); + } + + if (isset($xmlSheet->sheetViews->sheetView['showRowColHeaders'])) { + $docSheet->setShowRowColHeaders(self::boolean((string)$xmlSheet->sheetViews->sheetView['showRowColHeaders'])); + } + + if (isset($xmlSheet->sheetViews->sheetView['rightToLeft'])) { + $docSheet->setRightToLeft(self::boolean((string)$xmlSheet->sheetViews->sheetView['rightToLeft'])); + } + + if (isset($xmlSheet->sheetViews->sheetView->pane)) { + if (isset($xmlSheet->sheetViews->sheetView->pane['topLeftCell'])) { + $docSheet->freezePane( (string)$xmlSheet->sheetViews->sheetView->pane['topLeftCell'] ); + } else { + $xSplit = 0; + $ySplit = 0; + + if (isset($xmlSheet->sheetViews->sheetView->pane['xSplit'])) { + $xSplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['xSplit']); + } + + if (isset($xmlSheet->sheetViews->sheetView->pane['ySplit'])) { + $ySplit = 1 + intval($xmlSheet->sheetViews->sheetView->pane['ySplit']); + } + + $docSheet->freezePaneByColumnAndRow($xSplit, $ySplit); + } + } + + if (isset($xmlSheet->sheetViews->sheetView->selection)) { + if (isset($xmlSheet->sheetViews->sheetView->selection['sqref'])) { + $sqref = (string)$xmlSheet->sheetViews->sheetView->selection['sqref']; + $sqref = explode(' ', $sqref); + $sqref = $sqref[0]; + $docSheet->setSelectedCells($sqref); + } + } + + } + + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->tabColor)) { + if (isset($xmlSheet->sheetPr->tabColor['rgb'])) { + $docSheet->getTabColor()->setARGB( (string)$xmlSheet->sheetPr->tabColor['rgb'] ); + } + } + + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->outlinePr)) { + if (isset($xmlSheet->sheetPr->outlinePr['summaryRight']) && + !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryRight'])) { + $docSheet->setShowSummaryRight(FALSE); + } else { + $docSheet->setShowSummaryRight(TRUE); + } + + if (isset($xmlSheet->sheetPr->outlinePr['summaryBelow']) && + !self::boolean((string) $xmlSheet->sheetPr->outlinePr['summaryBelow'])) { + $docSheet->setShowSummaryBelow(FALSE); + } else { + $docSheet->setShowSummaryBelow(TRUE); + } + } + + if (isset($xmlSheet->sheetPr) && isset($xmlSheet->sheetPr->pageSetUpPr)) { + if (isset($xmlSheet->sheetPr->pageSetUpPr['fitToPage']) && + !self::boolean((string) $xmlSheet->sheetPr->pageSetUpPr['fitToPage'])) { + $docSheet->getPageSetup()->setFitToPage(FALSE); + } else { + $docSheet->getPageSetup()->setFitToPage(TRUE); + } + } + + if (isset($xmlSheet->sheetFormatPr)) { + if (isset($xmlSheet->sheetFormatPr['customHeight']) && + self::boolean((string) $xmlSheet->sheetFormatPr['customHeight']) && + isset($xmlSheet->sheetFormatPr['defaultRowHeight'])) { + $docSheet->getDefaultRowDimension()->setRowHeight( (float)$xmlSheet->sheetFormatPr['defaultRowHeight'] ); + } + if (isset($xmlSheet->sheetFormatPr['defaultColWidth'])) { + $docSheet->getDefaultColumnDimension()->setWidth( (float)$xmlSheet->sheetFormatPr['defaultColWidth'] ); + } + if (isset($xmlSheet->sheetFormatPr['zeroHeight']) && + ((string)$xmlSheet->sheetFormatPr['zeroHeight'] == '1')) { + $docSheet->getDefaultRowDimension()->setzeroHeight(true); + } + } + + if (isset($xmlSheet->cols) && !$this->_readDataOnly) { + foreach ($xmlSheet->cols->col as $col) { + for ($i = intval($col["min"]) - 1; $i < intval($col["max"]); ++$i) { + if ($col["style"] && !$this->_readDataOnly) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setXfIndex(intval($col["style"])); + } + if (self::boolean($col["bestFit"])) { + //$docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setAutoSize(TRUE); + } + if (self::boolean($col["hidden"])) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setVisible(FALSE); + } + if (self::boolean($col["collapsed"])) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setCollapsed(TRUE); + } + if ($col["outlineLevel"] > 0) { + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setOutlineLevel(intval($col["outlineLevel"])); + } + $docSheet->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($i))->setWidth(floatval($col["width"])); + + if (intval($col["max"]) == 16384) { + break; + } + } + } + } + + if (isset($xmlSheet->printOptions) && !$this->_readDataOnly) { + if (self::boolean((string) $xmlSheet->printOptions['gridLinesSet'])) { + $docSheet->setShowGridlines(TRUE); + } + + if (self::boolean((string) $xmlSheet->printOptions['gridLines'])) { + $docSheet->setPrintGridlines(TRUE); + } + + if (self::boolean((string) $xmlSheet->printOptions['horizontalCentered'])) { + $docSheet->getPageSetup()->setHorizontalCentered(TRUE); + } + if (self::boolean((string) $xmlSheet->printOptions['verticalCentered'])) { + $docSheet->getPageSetup()->setVerticalCentered(TRUE); + } + } + + if ($xmlSheet && $xmlSheet->sheetData && $xmlSheet->sheetData->row) { + foreach ($xmlSheet->sheetData->row as $row) { + if ($row["ht"] && !$this->_readDataOnly) { + $docSheet->getRowDimension(intval($row["r"]))->setRowHeight(floatval($row["ht"])); + } + if (self::boolean($row["hidden"]) && !$this->_readDataOnly) { + $docSheet->getRowDimension(intval($row["r"]))->setVisible(FALSE); + } + if (self::boolean($row["collapsed"])) { + $docSheet->getRowDimension(intval($row["r"]))->setCollapsed(TRUE); + } + if ($row["outlineLevel"] > 0) { + $docSheet->getRowDimension(intval($row["r"]))->setOutlineLevel(intval($row["outlineLevel"])); + } + if ($row["s"] && !$this->_readDataOnly) { + $docSheet->getRowDimension(intval($row["r"]))->setXfIndex(intval($row["s"])); + } + + foreach ($row->c as $c) { + $r = (string) $c["r"]; + $cellDataType = (string) $c["t"]; + $value = null; + $calculatedValue = null; + + // Read cell? + if ($this->getReadFilter() !== NULL) { + $coordinates = PHPExcel_Cell::coordinateFromString($r); + + if (!$this->getReadFilter()->readCell($coordinates[0], $coordinates[1], $docSheet->getTitle())) { + continue; + } + } + + // echo 'Reading cell '.$coordinates[0].$coordinates[1].'
    '; + // print_r($c); + // echo '
    '; + // echo 'Cell Data Type is '.$cellDataType.': '; + // + // Read cell! + switch ($cellDataType) { + case "s": + // echo 'String
    '; + if ((string)$c->v != '') { + $value = $sharedStrings[intval($c->v)]; + + if ($value instanceof PHPExcel_RichText) { + $value = clone $value; + } + } else { + $value = ''; + } + + break; + case "b": + // echo 'Boolean
    '; + if (!isset($c->f)) { + $value = self::_castToBool($c); + } else { + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToBool'); + if (isset($c->f['t'])) { + $att = array(); + $att = $c->f; + $docSheet->getCell($r)->setFormulaAttributes($att); + } + // echo '$calculatedValue = '.$calculatedValue.'
    '; + } + break; + case "inlineStr": + // echo 'Inline String
    '; + $value = $this->_parseRichText($c->is); + + break; + case "e": + // echo 'Error
    '; + if (!isset($c->f)) { + $value = self::_castToError($c); + } else { + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToError'); + // echo '$calculatedValue = '.$calculatedValue.'
    '; + } + + break; + + default: + // echo 'Default
    '; + if (!isset($c->f)) { + // echo 'Not a Formula
    '; + $value = self::_castToString($c); + } else { + // echo 'Treat as Formula
    '; + // Formula + $this->_castToFormula($c,$r,$cellDataType,$value,$calculatedValue,$sharedFormulas,'_castToString'); + // echo '$calculatedValue = '.$calculatedValue.'
    '; + } + + break; + } + // echo 'Value is '.$value.'
    '; + + // Check for numeric values + if (is_numeric($value) && $cellDataType != 's') { + if ($value == (int)$value) $value = (int)$value; + elseif ($value == (float)$value) $value = (float)$value; + elseif ($value == (double)$value) $value = (double)$value; + } + + // Rich text? + if ($value instanceof PHPExcel_RichText && $this->_readDataOnly) { + $value = $value->getPlainText(); + } + + $cell = $docSheet->getCell($r); + // Assign value + if ($cellDataType != '') { + $cell->setValueExplicit($value, $cellDataType); + } else { + $cell->setValue($value); + } + if ($calculatedValue !== NULL) { + $cell->setCalculatedValue($calculatedValue); + } + + // Style information? + if ($c["s"] && !$this->_readDataOnly) { + // no style index means 0, it seems + $cell->setXfIndex(isset($styles[intval($c["s"])]) ? + intval($c["s"]) : 0); + } + } + } + } + + $conditionals = array(); + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->conditionalFormatting) { + foreach ($xmlSheet->conditionalFormatting as $conditional) { + foreach ($conditional->cfRule as $cfRule) { + if ( + ( + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_NONE || + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CELLIS || + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT || + (string)$cfRule["type"] == PHPExcel_Style_Conditional::CONDITION_EXPRESSION + ) && isset($dxfs[intval($cfRule["dxfId"])]) + ) { + $conditionals[(string) $conditional["sqref"]][intval($cfRule["priority"])] = $cfRule; + } + } + } + + foreach ($conditionals as $ref => $cfRules) { + ksort($cfRules); + $conditionalStyles = array(); + foreach ($cfRules as $cfRule) { + $objConditional = new PHPExcel_Style_Conditional(); + $objConditional->setConditionType((string)$cfRule["type"]); + $objConditional->setOperatorType((string)$cfRule["operator"]); + + if ((string)$cfRule["text"] != '') { + $objConditional->setText((string)$cfRule["text"]); + } + + if (count($cfRule->formula) > 1) { + foreach ($cfRule->formula as $formula) { + $objConditional->addCondition((string)$formula); + } + } else { + $objConditional->addCondition((string)$cfRule->formula); + } + $objConditional->setStyle(clone $dxfs[intval($cfRule["dxfId"])]); + $conditionalStyles[] = $objConditional; + } + + // Extract all cell references in $ref + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($ref); + foreach ($aReferences as $reference) { + $docSheet->getStyle($reference)->setConditionalStyles($conditionalStyles); + } + } + } + + $aKeys = array("sheet", "objects", "scenarios", "formatCells", "formatColumns", "formatRows", "insertColumns", "insertRows", "insertHyperlinks", "deleteColumns", "deleteRows", "selectLockedCells", "sort", "autoFilter", "pivotTables", "selectUnlockedCells"); + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { + foreach ($aKeys as $key) { + $method = "set" . ucfirst($key); + $docSheet->getProtection()->$method(self::boolean((string) $xmlSheet->sheetProtection[$key])); + } + } + + if (!$this->_readDataOnly && $xmlSheet && $xmlSheet->sheetProtection) { + $docSheet->getProtection()->setPassword((string) $xmlSheet->sheetProtection["password"], TRUE); + if ($xmlSheet->protectedRanges->protectedRange) { + foreach ($xmlSheet->protectedRanges->protectedRange as $protectedRange) { + $docSheet->protectCells((string) $protectedRange["sqref"], (string) $protectedRange["password"], true); + } + } + } + + if ($xmlSheet && $xmlSheet->autoFilter && !$this->_readDataOnly) { + $autoFilter = $docSheet->getAutoFilter(); + $autoFilter->setRange((string) $xmlSheet->autoFilter["ref"]); + foreach ($xmlSheet->autoFilter->filterColumn as $filterColumn) { + $column = $autoFilter->getColumnByOffset((integer) $filterColumn["colId"]); + // Check for standard filters + if ($filterColumn->filters) { + $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER); + $filters = $filterColumn->filters; + if ((isset($filters["blank"])) && ($filters["blank"] == 1)) { + $column->createRule()->setRule( + NULL, // Operator is undefined, but always treated as EQUAL + '' + ) + ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER); + } + // Standard filters are always an OR join, so no join rule needs to be set + // Entries can be either filter elements + foreach ($filters->filter as $filterRule) { + $column->createRule()->setRule( + NULL, // Operator is undefined, but always treated as EQUAL + (string) $filterRule["val"] + ) + ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER); + } + // Or Date Group elements + foreach ($filters->dateGroupItem as $dateGroupItem) { + $column->createRule()->setRule( + NULL, // Operator is undefined, but always treated as EQUAL + array( + 'year' => (string) $dateGroupItem["year"], + 'month' => (string) $dateGroupItem["month"], + 'day' => (string) $dateGroupItem["day"], + 'hour' => (string) $dateGroupItem["hour"], + 'minute' => (string) $dateGroupItem["minute"], + 'second' => (string) $dateGroupItem["second"], + ), + (string) $dateGroupItem["dateTimeGrouping"] + ) + ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP); + } + } + // Check for custom filters + if ($filterColumn->customFilters) { + $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER); + $customFilters = $filterColumn->customFilters; + // Custom filters can an AND or an OR join; + // and there should only ever be one or two entries + if ((isset($customFilters["and"])) && ($customFilters["and"] == 1)) { + $column->setJoin(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND); + } + foreach ($customFilters->customFilter as $filterRule) { + $column->createRule()->setRule( + (string) $filterRule["operator"], + (string) $filterRule["val"] + ) + ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_CUSTOMFILTER); + } + } + // Check for dynamic filters + if ($filterColumn->dynamicFilter) { + $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER); + // We should only ever have one dynamic filter + foreach ($filterColumn->dynamicFilter as $filterRule) { + $column->createRule()->setRule( + NULL, // Operator is undefined, but always treated as EQUAL + (string) $filterRule["val"], + (string) $filterRule["type"] + ) + ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER); + if (isset($filterRule["val"])) { + $column->setAttribute('val',(string) $filterRule["val"]); + } + if (isset($filterRule["maxVal"])) { + $column->setAttribute('maxVal',(string) $filterRule["maxVal"]); + } + } + } + // Check for dynamic filters + if ($filterColumn->top10) { + $column->setFilterType(PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER); + // We should only ever have one top10 filter + foreach ($filterColumn->top10 as $filterRule) { + $column->createRule()->setRule( + (((isset($filterRule["percent"])) && ($filterRule["percent"] == 1)) + ? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT + : PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE + ), + (string) $filterRule["val"], + (((isset($filterRule["top"])) && ($filterRule["top"] == 1)) + ? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP + : PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM + ) + ) + ->setRuleType(PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_TOPTENFILTER); + } + } + } + } + + if ($xmlSheet && $xmlSheet->mergeCells && $xmlSheet->mergeCells->mergeCell && !$this->_readDataOnly) { + foreach ($xmlSheet->mergeCells->mergeCell as $mergeCell) { + $mergeRef = (string) $mergeCell["ref"]; + if (strpos($mergeRef,':') !== FALSE) { + $docSheet->mergeCells((string) $mergeCell["ref"]); + } + } + } + + if ($xmlSheet && $xmlSheet->pageMargins && !$this->_readDataOnly) { + $docPageMargins = $docSheet->getPageMargins(); + $docPageMargins->setLeft(floatval($xmlSheet->pageMargins["left"])); + $docPageMargins->setRight(floatval($xmlSheet->pageMargins["right"])); + $docPageMargins->setTop(floatval($xmlSheet->pageMargins["top"])); + $docPageMargins->setBottom(floatval($xmlSheet->pageMargins["bottom"])); + $docPageMargins->setHeader(floatval($xmlSheet->pageMargins["header"])); + $docPageMargins->setFooter(floatval($xmlSheet->pageMargins["footer"])); + } + + if ($xmlSheet && $xmlSheet->pageSetup && !$this->_readDataOnly) { + $docPageSetup = $docSheet->getPageSetup(); + + if (isset($xmlSheet->pageSetup["orientation"])) { + $docPageSetup->setOrientation((string) $xmlSheet->pageSetup["orientation"]); + } + if (isset($xmlSheet->pageSetup["paperSize"])) { + $docPageSetup->setPaperSize(intval($xmlSheet->pageSetup["paperSize"])); + } + if (isset($xmlSheet->pageSetup["scale"])) { + $docPageSetup->setScale(intval($xmlSheet->pageSetup["scale"]), FALSE); + } + if (isset($xmlSheet->pageSetup["fitToHeight"]) && intval($xmlSheet->pageSetup["fitToHeight"]) >= 0) { + $docPageSetup->setFitToHeight(intval($xmlSheet->pageSetup["fitToHeight"]), FALSE); + } + if (isset($xmlSheet->pageSetup["fitToWidth"]) && intval($xmlSheet->pageSetup["fitToWidth"]) >= 0) { + $docPageSetup->setFitToWidth(intval($xmlSheet->pageSetup["fitToWidth"]), FALSE); + } + if (isset($xmlSheet->pageSetup["firstPageNumber"]) && isset($xmlSheet->pageSetup["useFirstPageNumber"]) && + self::boolean((string) $xmlSheet->pageSetup["useFirstPageNumber"])) { + $docPageSetup->setFirstPageNumber(intval($xmlSheet->pageSetup["firstPageNumber"])); + } + } + + if ($xmlSheet && $xmlSheet->headerFooter && !$this->_readDataOnly) { + $docHeaderFooter = $docSheet->getHeaderFooter(); + + if (isset($xmlSheet->headerFooter["differentOddEven"]) && + self::boolean((string)$xmlSheet->headerFooter["differentOddEven"])) { + $docHeaderFooter->setDifferentOddEven(TRUE); + } else { + $docHeaderFooter->setDifferentOddEven(FALSE); + } + if (isset($xmlSheet->headerFooter["differentFirst"]) && + self::boolean((string)$xmlSheet->headerFooter["differentFirst"])) { + $docHeaderFooter->setDifferentFirst(TRUE); + } else { + $docHeaderFooter->setDifferentFirst(FALSE); + } + if (isset($xmlSheet->headerFooter["scaleWithDoc"]) && + !self::boolean((string)$xmlSheet->headerFooter["scaleWithDoc"])) { + $docHeaderFooter->setScaleWithDocument(FALSE); + } else { + $docHeaderFooter->setScaleWithDocument(TRUE); + } + if (isset($xmlSheet->headerFooter["alignWithMargins"]) && + !self::boolean((string)$xmlSheet->headerFooter["alignWithMargins"])) { + $docHeaderFooter->setAlignWithMargins(FALSE); + } else { + $docHeaderFooter->setAlignWithMargins(TRUE); + } + + $docHeaderFooter->setOddHeader((string) $xmlSheet->headerFooter->oddHeader); + $docHeaderFooter->setOddFooter((string) $xmlSheet->headerFooter->oddFooter); + $docHeaderFooter->setEvenHeader((string) $xmlSheet->headerFooter->evenHeader); + $docHeaderFooter->setEvenFooter((string) $xmlSheet->headerFooter->evenFooter); + $docHeaderFooter->setFirstHeader((string) $xmlSheet->headerFooter->firstHeader); + $docHeaderFooter->setFirstFooter((string) $xmlSheet->headerFooter->firstFooter); + } + + if ($xmlSheet && $xmlSheet->rowBreaks && $xmlSheet->rowBreaks->brk && !$this->_readDataOnly) { + foreach ($xmlSheet->rowBreaks->brk as $brk) { + if ($brk["man"]) { + $docSheet->setBreak("A$brk[id]", PHPExcel_Worksheet::BREAK_ROW); + } + } + } + if ($xmlSheet && $xmlSheet->colBreaks && $xmlSheet->colBreaks->brk && !$this->_readDataOnly) { + foreach ($xmlSheet->colBreaks->brk as $brk) { + if ($brk["man"]) { + $docSheet->setBreak(PHPExcel_Cell::stringFromColumnIndex((string) $brk["id"]) . "1", PHPExcel_Worksheet::BREAK_COLUMN); + } + } + } + + if ($xmlSheet && $xmlSheet->dataValidations && !$this->_readDataOnly) { + foreach ($xmlSheet->dataValidations->dataValidation as $dataValidation) { + // Uppercase coordinate + $range = strtoupper($dataValidation["sqref"]); + $rangeSet = explode(' ',$range); + foreach($rangeSet as $range) { + $stRange = $docSheet->shrinkRangeToFit($range); + + // Extract all cell references in $range + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($stRange); + foreach ($aReferences as $reference) { + // Create validation + $docValidation = $docSheet->getCell($reference)->getDataValidation(); + $docValidation->setType((string) $dataValidation["type"]); + $docValidation->setErrorStyle((string) $dataValidation["errorStyle"]); + $docValidation->setOperator((string) $dataValidation["operator"]); + $docValidation->setAllowBlank($dataValidation["allowBlank"] != 0); + $docValidation->setShowDropDown($dataValidation["showDropDown"] == 0); + $docValidation->setShowInputMessage($dataValidation["showInputMessage"] != 0); + $docValidation->setShowErrorMessage($dataValidation["showErrorMessage"] != 0); + $docValidation->setErrorTitle((string) $dataValidation["errorTitle"]); + $docValidation->setError((string) $dataValidation["error"]); + $docValidation->setPromptTitle((string) $dataValidation["promptTitle"]); + $docValidation->setPrompt((string) $dataValidation["prompt"]); + $docValidation->setFormula1((string) $dataValidation->formula1); + $docValidation->setFormula2((string) $dataValidation->formula2); + } + } + } + } + + // Add hyperlinks + $hyperlinks = array(); + if (!$this->_readDataOnly) { + // Locate hyperlink relations + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink") { + $hyperlinks[(string)$ele["Id"]] = (string)$ele["Target"]; + } + } + } + + // Loop through hyperlinks + if ($xmlSheet && $xmlSheet->hyperlinks) { + foreach ($xmlSheet->hyperlinks->hyperlink as $hyperlink) { + // Link url + $linkRel = $hyperlink->attributes('http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($hyperlink['ref']) as $cellReference) { + $cell = $docSheet->getCell( $cellReference ); + if (isset($linkRel['id'])) { + $hyperlinkUrl = $hyperlinks[ (string)$linkRel['id'] ]; + if (isset($hyperlink['location'])) { + $hyperlinkUrl .= '#' . (string) $hyperlink['location']; + } + $cell->getHyperlink()->setUrl($hyperlinkUrl); + } elseif (isset($hyperlink['location'])) { + $cell->getHyperlink()->setUrl( 'sheet://' . (string)$hyperlink['location'] ); + } + + // Tooltip + if (isset($hyperlink['tooltip'])) { + $cell->getHyperlink()->setTooltip( (string)$hyperlink['tooltip'] ); + } + } + } + } + } + + // Add comments + $comments = array(); + $vmlComments = array(); + if (!$this->_readDataOnly) { + // Locate comment relations + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments") { + $comments[(string)$ele["Id"]] = (string)$ele["Target"]; + } + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { + $vmlComments[(string)$ele["Id"]] = (string)$ele["Target"]; + } + } + } + + // Loop through comments + foreach ($comments as $relName => $relPath) { + // Load comments file + $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); + $commentsFile = simplexml_load_string($this->_getFromZipArchive($zip, $relPath) ); + + // Utility variables + $authors = array(); + + // Loop through authors + foreach ($commentsFile->authors->author as $author) { + $authors[] = (string)$author; + } + + // Loop through contents + foreach ($commentsFile->commentList->comment as $comment) { + $docSheet->getComment( (string)$comment['ref'] )->setAuthor( $authors[(string)$comment['authorId']] ); + $docSheet->getComment( (string)$comment['ref'] )->setText( $this->_parseRichText($comment->text) ); + } + } + + // Loop through VML comments + foreach ($vmlComments as $relName => $relPath) { + // Load VML comments file + $relPath = PHPExcel_Shared_File::realpath(dirname("$dir/$fileWorksheet") . "/" . $relPath); + $vmlCommentsFile = simplexml_load_string( $this->_getFromZipArchive($zip, $relPath) ); + $vmlCommentsFile->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + + $shapes = $vmlCommentsFile->xpath('//v:shape'); + foreach ($shapes as $shape) { + $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + + if (isset($shape['style'])) { + $style = (string)$shape['style']; + $fillColor = strtoupper( substr( (string)$shape['fillcolor'], 1 ) ); + $column = null; + $row = null; + + $clientData = $shape->xpath('.//x:ClientData'); + if (is_array($clientData) && !empty($clientData)) { + $clientData = $clientData[0]; + + if ( isset($clientData['ObjectType']) && (string)$clientData['ObjectType'] == 'Note' ) { + $temp = $clientData->xpath('.//x:Row'); + if (is_array($temp)) $row = $temp[0]; + + $temp = $clientData->xpath('.//x:Column'); + if (is_array($temp)) $column = $temp[0]; + } + } + + if (($column !== NULL) && ($row !== NULL)) { + // Set comment properties + $comment = $docSheet->getCommentByColumnAndRow((string) $column, $row + 1); + $comment->getFillColor()->setRGB( $fillColor ); + + // Parse style + $styleArray = explode(';', str_replace(' ', '', $style)); + foreach ($styleArray as $stylePair) { + $stylePair = explode(':', $stylePair); + + if ($stylePair[0] == 'margin-left') $comment->setMarginLeft($stylePair[1]); + if ($stylePair[0] == 'margin-top') $comment->setMarginTop($stylePair[1]); + if ($stylePair[0] == 'width') $comment->setWidth($stylePair[1]); + if ($stylePair[0] == 'height') $comment->setHeight($stylePair[1]); + if ($stylePair[0] == 'visibility') $comment->setVisible( $stylePair[1] == 'visible' ); + + } + } + } + } + } + + // Header/footer images + if ($xmlSheet && $xmlSheet->legacyDrawingHF && !$this->_readDataOnly) { + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $vmlRelationship = ''; + + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing") { + $vmlRelationship = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); + } + } + + if ($vmlRelationship != '') { + // Fetch linked images + $relsVML = simplexml_load_string($this->_getFromZipArchive($zip, dirname($vmlRelationship) . '/_rels/' . basename($vmlRelationship) . '.rels' )); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $drawings = array(); + foreach ($relsVML->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { + $drawings[(string) $ele["Id"]] = self::dir_add($vmlRelationship, $ele["Target"]); + } + } + + // Fetch VML document + $vmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $vmlRelationship)); + $vmlDrawing->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + + $hfImages = array(); + + $shapes = $vmlDrawing->xpath('//v:shape'); + foreach ($shapes as $shape) { + $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); + $imageData = $shape->xpath('//v:imagedata'); + $imageData = $imageData[0]; + + $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office'); + $style = self::toCSSArray( (string)$shape['style'] ); + + $hfImages[ (string)$shape['id'] ] = new PHPExcel_Worksheet_HeaderFooterDrawing(); + if (isset($imageData['title'])) { + $hfImages[ (string)$shape['id'] ]->setName( (string)$imageData['title'] ); + } + + $hfImages[ (string)$shape['id'] ]->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $drawings[(string)$imageData['relid']], false); + $hfImages[ (string)$shape['id'] ]->setResizeProportional(false); + $hfImages[ (string)$shape['id'] ]->setWidth($style['width']); + $hfImages[ (string)$shape['id'] ]->setHeight($style['height']); + $hfImages[ (string)$shape['id'] ]->setOffsetX($style['margin-left']); + $hfImages[ (string)$shape['id'] ]->setOffsetY($style['margin-top']); + $hfImages[ (string)$shape['id'] ]->setResizeProportional(true); + } + + $docSheet->getHeaderFooter()->setImages($hfImages); + } + } + } + + } + +// TODO: Autoshapes from twoCellAnchors! + if ($zip->locateName(dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels")) { + $relsWorksheet = simplexml_load_string($this->_getFromZipArchive($zip, dirname("$dir/$fileWorksheet") . "/_rels/" . basename($fileWorksheet) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $drawings = array(); + foreach ($relsWorksheet->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing") { + $drawings[(string) $ele["Id"]] = self::dir_add("$dir/$fileWorksheet", $ele["Target"]); + } + } + if ($xmlSheet->drawing && !$this->_readDataOnly) { + foreach ($xmlSheet->drawing as $drawing) { + $fileDrawing = $drawings[(string) self::array_item($drawing->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "id")]; + $relsDrawing = simplexml_load_string($this->_getFromZipArchive($zip, dirname($fileDrawing) . "/_rels/" . basename($fileDrawing) . ".rels") ); //~ http://schemas.openxmlformats.org/package/2006/relationships"); + $images = array(); + + if ($relsDrawing && $relsDrawing->Relationship) { + foreach ($relsDrawing->Relationship as $ele) { + if ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") { + $images[(string) $ele["Id"]] = self::dir_add($fileDrawing, $ele["Target"]); + } elseif ($ele["Type"] == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart") { + if ($this->_includeCharts) { + $charts[self::dir_add($fileDrawing, $ele["Target"])] = array('id' => (string) $ele["Id"], + 'sheet' => $docSheet->getTitle() + ); + } + } + } + } + $xmlDrawing = simplexml_load_string($this->_getFromZipArchive($zip, $fileDrawing))->children("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"); + + if ($xmlDrawing->oneCellAnchor) { + foreach ($xmlDrawing->oneCellAnchor as $oneCellAnchor) { + if ($oneCellAnchor->pic->blipFill) { + $blip = $oneCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; + $xfrm = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; + $outerShdw = $oneCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; + $objDrawing = new PHPExcel_Worksheet_Drawing; + $objDrawing->setName((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); + $objDrawing->setDescription((string) self::array_item($oneCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); + $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); + $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1)); + $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff)); + $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff)); + $objDrawing->setResizeProportional(false); + $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cx"))); + $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cy"))); + if ($xfrm) { + $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); + } + if ($outerShdw) { + $shadow = $objDrawing->getShadow(); + $shadow->setVisible(true); + $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); + $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); + $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); + $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); + $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); + $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); + } + $objDrawing->setWorksheet($docSheet); + } else { + // ? Can charts be positioned with a oneCellAnchor ? + $coordinates = PHPExcel_Cell::stringFromColumnIndex((string) $oneCellAnchor->from->col) . ($oneCellAnchor->from->row + 1); + $offsetX = PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->colOff); + $offsetY = PHPExcel_Shared_Drawing::EMUToPixels($oneCellAnchor->from->rowOff); + $width = PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cx")); + $height = PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($oneCellAnchor->ext->attributes(), "cy")); + } + } + } + if ($xmlDrawing->twoCellAnchor) { + foreach ($xmlDrawing->twoCellAnchor as $twoCellAnchor) { + if ($twoCellAnchor->pic->blipFill) { + $blip = $twoCellAnchor->pic->blipFill->children("http://schemas.openxmlformats.org/drawingml/2006/main")->blip; + $xfrm = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->xfrm; + $outerShdw = $twoCellAnchor->pic->spPr->children("http://schemas.openxmlformats.org/drawingml/2006/main")->effectLst->outerShdw; + $objDrawing = new PHPExcel_Worksheet_Drawing; + $objDrawing->setName((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "name")); + $objDrawing->setDescription((string) self::array_item($twoCellAnchor->pic->nvPicPr->cNvPr->attributes(), "descr")); + $objDrawing->setPath("zip://".PHPExcel_Shared_File::realpath($pFilename)."#" . $images[(string) self::array_item($blip->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"), "embed")], false); + $objDrawing->setCoordinates(PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1)); + $objDrawing->setOffsetX(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff)); + $objDrawing->setOffsetY(PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff)); + $objDrawing->setResizeProportional(false); + + $objDrawing->setWidth(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cx"))); + $objDrawing->setHeight(PHPExcel_Shared_Drawing::EMUToPixels(self::array_item($xfrm->ext->attributes(), "cy"))); + + if ($xfrm) { + $objDrawing->setRotation(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($xfrm->attributes(), "rot"))); + } + if ($outerShdw) { + $shadow = $objDrawing->getShadow(); + $shadow->setVisible(true); + $shadow->setBlurRadius(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "blurRad"))); + $shadow->setDistance(PHPExcel_Shared_Drawing::EMUTopixels(self::array_item($outerShdw->attributes(), "dist"))); + $shadow->setDirection(PHPExcel_Shared_Drawing::angleToDegrees(self::array_item($outerShdw->attributes(), "dir"))); + $shadow->setAlignment((string) self::array_item($outerShdw->attributes(), "algn")); + $shadow->getColor()->setRGB(self::array_item($outerShdw->srgbClr->attributes(), "val")); + $shadow->setAlpha(self::array_item($outerShdw->srgbClr->alpha->attributes(), "val") / 1000); + } + $objDrawing->setWorksheet($docSheet); + } elseif(($this->_includeCharts) && ($twoCellAnchor->graphicFrame)) { + $fromCoordinate = PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->from->col) . ($twoCellAnchor->from->row + 1); + $fromOffsetX = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->colOff); + $fromOffsetY = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->from->rowOff); + $toCoordinate = PHPExcel_Cell::stringFromColumnIndex((string) $twoCellAnchor->to->col) . ($twoCellAnchor->to->row + 1); + $toOffsetX = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->to->colOff); + $toOffsetY = PHPExcel_Shared_Drawing::EMUToPixels($twoCellAnchor->to->rowOff); + $graphic = $twoCellAnchor->graphicFrame->children("http://schemas.openxmlformats.org/drawingml/2006/main")->graphic; + $chartRef = $graphic->graphicData->children("http://schemas.openxmlformats.org/drawingml/2006/chart")->chart; + $thisChart = (string) $chartRef->attributes("http://schemas.openxmlformats.org/officeDocument/2006/relationships"); + + $chartDetails[$docSheet->getTitle().'!'.$thisChart] = + array( 'fromCoordinate' => $fromCoordinate, + 'fromOffsetX' => $fromOffsetX, + 'fromOffsetY' => $fromOffsetY, + 'toCoordinate' => $toCoordinate, + 'toOffsetX' => $toOffsetX, + 'toOffsetY' => $toOffsetY, + 'worksheetTitle' => $docSheet->getTitle() + ); + } + } + } + + } + } + } + + // Loop through definedNames + if ($xmlWorkbook->definedNames) { + foreach ($xmlWorkbook->definedNames->definedName as $definedName) { + // Extract range + $extractedRange = (string)$definedName; + $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); + if (($spos = strpos($extractedRange,'!')) !== false) { + $extractedRange = substr($extractedRange,0,$spos).str_replace('$', '', substr($extractedRange,$spos)); + } else { + $extractedRange = str_replace('$', '', $extractedRange); + } + + // Valid range? + if (stripos((string)$definedName, '#REF!') !== FALSE || $extractedRange == '') { + continue; + } + + // Some definedNames are only applicable if we are on the same sheet... + if ((string)$definedName['localSheetId'] != '' && (string)$definedName['localSheetId'] == $sheetId) { + // Switch on type + switch ((string)$definedName['name']) { + + case '_xlnm._FilterDatabase': + if ((string)$definedName['hidden'] !== '1') { + $docSheet->getAutoFilter()->setRange($extractedRange); + } + break; + + case '_xlnm.Print_Titles': + // Split $extractedRange + $extractedRange = explode(',', $extractedRange); + + // Set print titles + foreach ($extractedRange as $range) { + $matches = array(); + $range = str_replace('$', '', $range); + + // check for repeating columns, e g. 'A:A' or 'A:D' + if (preg_match('/!?([A-Z]+)\:([A-Z]+)$/', $range, $matches)) { + $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($matches[1], $matches[2])); + } + // check for repeating rows, e.g. '1:1' or '1:5' + elseif (preg_match('/!?(\d+)\:(\d+)$/', $range, $matches)) { + $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($matches[1], $matches[2])); + } + } + break; + + case '_xlnm.Print_Area': + $rangeSets = explode(',', $extractedRange); // FIXME: what if sheetname contains comma? + $newRangeSets = array(); + foreach($rangeSets as $rangeSet) { + $range = explode('!', $rangeSet); // FIXME: what if sheetname contains exclamation mark? + $rangeSet = isset($range[1]) ? $range[1] : $range[0]; + if (strpos($rangeSet, ':') === FALSE) { + $rangeSet = $rangeSet . ':' . $rangeSet; + } + $newRangeSets[] = str_replace('$', '', $rangeSet); + } + $docSheet->getPageSetup()->setPrintArea(implode(',',$newRangeSets)); + break; + + default: + break; + } + } + } + } + + // Next sheet id + ++$sheetId; + } + + // Loop through definedNames + if ($xmlWorkbook->definedNames) { + foreach ($xmlWorkbook->definedNames->definedName as $definedName) { + // Extract range + $extractedRange = (string)$definedName; + $extractedRange = preg_replace('/\'(\w+)\'\!/', '', $extractedRange); + if (($spos = strpos($extractedRange,'!')) !== false) { + $extractedRange = substr($extractedRange,0,$spos).str_replace('$', '', substr($extractedRange,$spos)); + } else { + $extractedRange = str_replace('$', '', $extractedRange); + } + + // Valid range? + if (stripos((string)$definedName, '#REF!') !== false || $extractedRange == '') { + continue; + } + + // Some definedNames are only applicable if we are on the same sheet... + if ((string)$definedName['localSheetId'] != '') { + // Local defined name + // Switch on type + switch ((string)$definedName['name']) { + + case '_xlnm._FilterDatabase': + case '_xlnm.Print_Titles': + case '_xlnm.Print_Area': + break; + + default: + if ($mapSheetId[(integer) $definedName['localSheetId']] !== null) { + $range = explode('!', (string)$definedName); + if (count($range) == 2) { + $range[0] = str_replace("''", "'", $range[0]); + $range[0] = str_replace("'", "", $range[0]); + if ($worksheet = $docSheet->getParent()->getSheetByName($range[0])) { + $extractedRange = str_replace('$', '', $range[1]); + $scope = $docSheet->getParent()->getSheet($mapSheetId[(integer) $definedName['localSheetId']]); + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $worksheet, $extractedRange, true, $scope) ); + } + } + } + break; + } + } else if (!isset($definedName['localSheetId'])) { + // "Global" definedNames + $locatedSheet = null; + $extractedSheetName = ''; + if (strpos( (string)$definedName, '!' ) !== false) { + // Extract sheet name + $extractedSheetName = PHPExcel_Worksheet::extractSheetTitle( (string)$definedName, true ); + $extractedSheetName = $extractedSheetName[0]; + + // Locate sheet + $locatedSheet = $excel->getSheetByName($extractedSheetName); + + // Modify range + $range = explode('!', $extractedRange); + $extractedRange = isset($range[1]) ? $range[1] : $range[0]; + } + + if ($locatedSheet !== NULL) { + $excel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $locatedSheet, $extractedRange, false) ); + } + } + } + } + } + + if ((!$this->_readDataOnly) || (!empty($this->_loadSheetsOnly))) { + // active sheet index + $activeTab = intval($xmlWorkbook->bookViews->workbookView["activeTab"]); // refers to old sheet index + + // keep active sheet index if sheet is still loaded, else first sheet is set as the active + if (isset($mapSheetId[$activeTab]) && $mapSheetId[$activeTab] !== null) { + $excel->setActiveSheetIndex($mapSheetId[$activeTab]); + } else { + if ($excel->getSheetCount() == 0) { + $excel->createSheet(); + } + $excel->setActiveSheetIndex(0); + } + } + break; + } + + } + + + if (!$this->_readDataOnly) { + $contentTypes = simplexml_load_string($this->_getFromZipArchive($zip, "[Content_Types].xml")); + foreach ($contentTypes->Override as $contentType) { + switch ($contentType["ContentType"]) { + case "application/vnd.openxmlformats-officedocument.drawingml.chart+xml": + if ($this->_includeCharts) { + $chartEntryRef = ltrim($contentType['PartName'],'/'); + $chartElements = simplexml_load_string($this->_getFromZipArchive($zip, $chartEntryRef)); + $objChart = PHPExcel_Reader_Excel2007_Chart::readChart($chartElements,basename($chartEntryRef,'.xml')); + +// echo 'Chart ',$chartEntryRef,'
    '; +// var_dump($charts[$chartEntryRef]); +// + if (isset($charts[$chartEntryRef])) { + $chartPositionRef = $charts[$chartEntryRef]['sheet'].'!'.$charts[$chartEntryRef]['id']; +// echo 'Position Ref ',$chartPositionRef,'
    '; + if (isset($chartDetails[$chartPositionRef])) { +// var_dump($chartDetails[$chartPositionRef]); + + $excel->getSheetByName($charts[$chartEntryRef]['sheet'])->addChart($objChart); + $objChart->setWorksheet($excel->getSheetByName($charts[$chartEntryRef]['sheet'])); + $objChart->setTopLeftPosition( $chartDetails[$chartPositionRef]['fromCoordinate'], + $chartDetails[$chartPositionRef]['fromOffsetX'], + $chartDetails[$chartPositionRef]['fromOffsetY'] + ); + $objChart->setBottomRightPosition( $chartDetails[$chartPositionRef]['toCoordinate'], + $chartDetails[$chartPositionRef]['toOffsetX'], + $chartDetails[$chartPositionRef]['toOffsetY'] + ); + } + } + } + } + } + } + + $zip->close(); + + return $excel; + } + + + private static function _readColor($color, $background=FALSE) { + if (isset($color["rgb"])) { + return (string)$color["rgb"]; + } else if (isset($color["indexed"])) { + return PHPExcel_Style_Color::indexedColor($color["indexed"]-7,$background)->getARGB(); + } else if (isset($color["theme"])) { + if (self::$_theme !== NULL) { + $returnColour = self::$_theme->getColourByIndex((int)$color["theme"]); + if (isset($color["tint"])) { + $tintAdjust = (float) $color["tint"]; + $returnColour = PHPExcel_Style_Color::changeBrightness($returnColour, $tintAdjust); + } + return 'FF'.$returnColour; + } + } + + if ($background) { + return 'FFFFFFFF'; + } + return 'FF000000'; + } + + + private static function _readStyle($docStyle, $style) { + // format code +// if (isset($style->numFmt)) { +// if (isset($style->numFmt['formatCode'])) { +// $docStyle->getNumberFormat()->setFormatCode((string) $style->numFmt['formatCode']); +// } else { + $docStyle->getNumberFormat()->setFormatCode($style->numFmt); +// } +// } + + // font + if (isset($style->font)) { + $docStyle->getFont()->setName((string) $style->font->name["val"]); + $docStyle->getFont()->setSize((string) $style->font->sz["val"]); + if (isset($style->font->b)) { + $docStyle->getFont()->setBold(!isset($style->font->b["val"]) || self::boolean((string) $style->font->b["val"])); + } + if (isset($style->font->i)) { + $docStyle->getFont()->setItalic(!isset($style->font->i["val"]) || self::boolean((string) $style->font->i["val"])); + } + if (isset($style->font->strike)) { + $docStyle->getFont()->setStrikethrough(!isset($style->font->strike["val"]) || self::boolean((string) $style->font->strike["val"])); + } + $docStyle->getFont()->getColor()->setARGB(self::_readColor($style->font->color)); + + if (isset($style->font->u) && !isset($style->font->u["val"])) { + $docStyle->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); + } else if (isset($style->font->u) && isset($style->font->u["val"])) { + $docStyle->getFont()->setUnderline((string)$style->font->u["val"]); + } + + if (isset($style->font->vertAlign) && isset($style->font->vertAlign["val"])) { + $vertAlign = strtolower((string)$style->font->vertAlign["val"]); + if ($vertAlign == 'superscript') { + $docStyle->getFont()->setSuperScript(true); + } + if ($vertAlign == 'subscript') { + $docStyle->getFont()->setSubScript(true); + } + } + } + + // fill + if (isset($style->fill)) { + if ($style->fill->gradientFill) { + $gradientFill = $style->fill->gradientFill[0]; + if(!empty($gradientFill["type"])) { + $docStyle->getFill()->setFillType((string) $gradientFill["type"]); + } + $docStyle->getFill()->setRotation(floatval($gradientFill["degree"])); + $gradientFill->registerXPathNamespace("sml", "http://schemas.openxmlformats.org/spreadsheetml/2006/main"); + $docStyle->getFill()->getStartColor()->setARGB(self::_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=0]"))->color) ); + $docStyle->getFill()->getEndColor()->setARGB(self::_readColor( self::array_item($gradientFill->xpath("sml:stop[@position=1]"))->color) ); + } elseif ($style->fill->patternFill) { + $patternType = (string)$style->fill->patternFill["patternType"] != '' ? (string)$style->fill->patternFill["patternType"] : 'solid'; + $docStyle->getFill()->setFillType($patternType); + if ($style->fill->patternFill->fgColor) { + $docStyle->getFill()->getStartColor()->setARGB(self::_readColor($style->fill->patternFill->fgColor,true)); + } else { + $docStyle->getFill()->getStartColor()->setARGB('FF000000'); + } + if ($style->fill->patternFill->bgColor) { + $docStyle->getFill()->getEndColor()->setARGB(self::_readColor($style->fill->patternFill->bgColor,true)); + } + } + } + + // border + if (isset($style->border)) { + $diagonalUp = self::boolean((string) $style->border["diagonalUp"]); + $diagonalDown = self::boolean((string) $style->border["diagonalDown"]); + if (!$diagonalUp && !$diagonalDown) { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); + } elseif ($diagonalUp && !$diagonalDown) { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); + } elseif (!$diagonalUp && $diagonalDown) { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); + } else { + $docStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); + } + self::_readBorder($docStyle->getBorders()->getLeft(), $style->border->left); + self::_readBorder($docStyle->getBorders()->getRight(), $style->border->right); + self::_readBorder($docStyle->getBorders()->getTop(), $style->border->top); + self::_readBorder($docStyle->getBorders()->getBottom(), $style->border->bottom); + self::_readBorder($docStyle->getBorders()->getDiagonal(), $style->border->diagonal); + } + + // alignment + if (isset($style->alignment)) { + $docStyle->getAlignment()->setHorizontal((string) $style->alignment["horizontal"]); + $docStyle->getAlignment()->setVertical((string) $style->alignment["vertical"]); + + $textRotation = 0; + if ((int)$style->alignment["textRotation"] <= 90) { + $textRotation = (int)$style->alignment["textRotation"]; + } else if ((int)$style->alignment["textRotation"] > 90) { + $textRotation = 90 - (int)$style->alignment["textRotation"]; + } + + $docStyle->getAlignment()->setTextRotation(intval($textRotation)); + $docStyle->getAlignment()->setWrapText(self::boolean((string) $style->alignment["wrapText"])); + $docStyle->getAlignment()->setShrinkToFit(self::boolean((string) $style->alignment["shrinkToFit"])); + $docStyle->getAlignment()->setIndent( intval((string)$style->alignment["indent"]) > 0 ? intval((string)$style->alignment["indent"]) : 0 ); + } + + // protection + if (isset($style->protection)) { + if (isset($style->protection['locked'])) { + if (self::boolean((string) $style->protection['locked'])) { + $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_PROTECTED); + } else { + $docStyle->getProtection()->setLocked(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); + } + } + + if (isset($style->protection['hidden'])) { + if (self::boolean((string) $style->protection['hidden'])) { + $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_PROTECTED); + } else { + $docStyle->getProtection()->setHidden(PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); + } + } + } + } + + + private static function _readBorder($docBorder, $eleBorder) { + if (isset($eleBorder["style"])) { + $docBorder->setBorderStyle((string) $eleBorder["style"]); + } + if (isset($eleBorder->color)) { + $docBorder->getColor()->setARGB(self::_readColor($eleBorder->color)); + } + } + + + private function _parseRichText($is = null) { + $value = new PHPExcel_RichText(); + + if (isset($is->t)) { + $value->createText( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $is->t ) ); + } else { + foreach ($is->r as $run) { + if (!isset($run->rPr)) { + $objText = $value->createText( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $run->t ) ); + + } else { + $objText = $value->createTextRun( PHPExcel_Shared_String::ControlCharacterOOXML2PHP( (string) $run->t ) ); + + if (isset($run->rPr->rFont["val"])) { + $objText->getFont()->setName((string) $run->rPr->rFont["val"]); + } + + if (isset($run->rPr->sz["val"])) { + $objText->getFont()->setSize((string) $run->rPr->sz["val"]); + } + + if (isset($run->rPr->color)) { + $objText->getFont()->setColor( new PHPExcel_Style_Color( self::_readColor($run->rPr->color) ) ); + } + + if ((isset($run->rPr->b["val"]) && self::boolean((string) $run->rPr->b["val"])) || + (isset($run->rPr->b) && !isset($run->rPr->b["val"]))) { + $objText->getFont()->setBold(TRUE); + } + + if ((isset($run->rPr->i["val"]) && self::boolean((string) $run->rPr->i["val"])) || + (isset($run->rPr->i) && !isset($run->rPr->i["val"]))) { + $objText->getFont()->setItalic(TRUE); + } + + if (isset($run->rPr->vertAlign) && isset($run->rPr->vertAlign["val"])) { + $vertAlign = strtolower((string)$run->rPr->vertAlign["val"]); + if ($vertAlign == 'superscript') { + $objText->getFont()->setSuperScript(TRUE); + } + if ($vertAlign == 'subscript') { + $objText->getFont()->setSubScript(TRUE); + } + } + + if (isset($run->rPr->u) && !isset($run->rPr->u["val"])) { + $objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); + } else if (isset($run->rPr->u) && isset($run->rPr->u["val"])) { + $objText->getFont()->setUnderline((string)$run->rPr->u["val"]); + } + + if ((isset($run->rPr->strike["val"]) && self::boolean((string) $run->rPr->strike["val"])) || + (isset($run->rPr->strike) && !isset($run->rPr->strike["val"]))) { + $objText->getFont()->setStrikethrough(TRUE); + } + } + } + } + + return $value; + } + + + private static function array_item($array, $key = 0) { + return (isset($array[$key]) ? $array[$key] : null); + } + + + private static function dir_add($base, $add) { + return preg_replace('~[^/]+/\.\./~', '', dirname($base) . "/$add"); + } + + + private static function toCSSArray($style) { + $style = str_replace(array("\r","\n"), "", $style); + + $temp = explode(';', $style); + $style = array(); + foreach ($temp as $item) { + $item = explode(':', $item); + + if (strpos($item[1], 'px') !== false) { + $item[1] = str_replace('px', '', $item[1]); + } + if (strpos($item[1], 'pt') !== false) { + $item[1] = str_replace('pt', '', $item[1]); + $item[1] = PHPExcel_Shared_Font::fontSizeToPixels($item[1]); + } + if (strpos($item[1], 'in') !== false) { + $item[1] = str_replace('in', '', $item[1]); + $item[1] = PHPExcel_Shared_Font::inchSizeToPixels($item[1]); + } + if (strpos($item[1], 'cm') !== false) { + $item[1] = str_replace('cm', '', $item[1]); + $item[1] = PHPExcel_Shared_Font::centimeterSizeToPixels($item[1]); + } + + $style[$item[0]] = $item[1]; + } + + return $style; + } + + private static function boolean($value = NULL) + { + if (is_numeric($value)) { + return (bool) $value; + } + return ($value === 'true' || $value === 'TRUE') ? TRUE : FALSE; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007/Chart.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007/Chart.php new file mode 100755 index 0000000..235fa24 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007/Chart.php @@ -0,0 +1,517 @@ +attributes(); + if (isset($attributes[$name])) { + if ($format == 'string') { + return (string) $attributes[$name]; + } elseif ($format == 'integer') { + return (integer) $attributes[$name]; + } elseif ($format == 'boolean') { + return (boolean) ($attributes[$name] === '0' || $attributes[$name] !== 'true') ? false : true; + } else { + return (float) $attributes[$name]; + } + } + return null; + } // function _getAttribute() + + + private static function _readColor($color,$background=false) { + if (isset($color["rgb"])) { + return (string)$color["rgb"]; + } else if (isset($color["indexed"])) { + return PHPExcel_Style_Color::indexedColor($color["indexed"]-7,$background)->getARGB(); + } + } + + + public static function readChart($chartElements,$chartName) { + $namespacesChartMeta = $chartElements->getNamespaces(true); + $chartElementsC = $chartElements->children($namespacesChartMeta['c']); + + $XaxisLabel = $YaxisLabel = $legend = $title = NULL; + $dispBlanksAs = $plotVisOnly = NULL; + + foreach($chartElementsC as $chartElementKey => $chartElement) { + switch ($chartElementKey) { + case "chart": + foreach($chartElement as $chartDetailsKey => $chartDetails) { + $chartDetailsC = $chartDetails->children($namespacesChartMeta['c']); + switch ($chartDetailsKey) { + case "plotArea": + $plotAreaLayout = $XaxisLable = $YaxisLable = null; + $plotSeries = $plotAttributes = array(); + foreach($chartDetails as $chartDetailKey => $chartDetail) { + switch ($chartDetailKey) { + case "layout": + $plotAreaLayout = self::_chartLayoutDetails($chartDetail,$namespacesChartMeta,'plotArea'); + break; + case "catAx": + if (isset($chartDetail->title)) { + $XaxisLabel = self::_chartTitle($chartDetail->title->children($namespacesChartMeta['c']),$namespacesChartMeta,'cat'); + } + break; + case "dateAx": + if (isset($chartDetail->title)) { + $XaxisLabel = self::_chartTitle($chartDetail->title->children($namespacesChartMeta['c']),$namespacesChartMeta,'cat'); + } + break; + case "valAx": + if (isset($chartDetail->title)) { + $YaxisLabel = self::_chartTitle($chartDetail->title->children($namespacesChartMeta['c']),$namespacesChartMeta,'cat'); + } + break; + case "barChart": + case "bar3DChart": + $barDirection = self::_getAttribute($chartDetail->barDir, 'val', 'string'); + $plotSer = self::_chartDataSeries($chartDetail,$namespacesChartMeta,$chartDetailKey); + $plotSer->setPlotDirection($barDirection); + $plotSeries[] = $plotSer; + $plotAttributes = self::_readChartAttributes($chartDetail); + break; + case "lineChart": + case "line3DChart": + $plotSeries[] = self::_chartDataSeries($chartDetail,$namespacesChartMeta,$chartDetailKey); + $plotAttributes = self::_readChartAttributes($chartDetail); + break; + case "areaChart": + case "area3DChart": + $plotSeries[] = self::_chartDataSeries($chartDetail,$namespacesChartMeta,$chartDetailKey); + $plotAttributes = self::_readChartAttributes($chartDetail); + break; + case "doughnutChart": + case "pieChart": + case "pie3DChart": + $explosion = isset($chartDetail->ser->explosion); + $plotSer = self::_chartDataSeries($chartDetail,$namespacesChartMeta,$chartDetailKey); + $plotSer->setPlotStyle($explosion); + $plotSeries[] = $plotSer; + $plotAttributes = self::_readChartAttributes($chartDetail); + break; + case "scatterChart": + $scatterStyle = self::_getAttribute($chartDetail->scatterStyle, 'val', 'string'); + $plotSer = self::_chartDataSeries($chartDetail,$namespacesChartMeta,$chartDetailKey); + $plotSer->setPlotStyle($scatterStyle); + $plotSeries[] = $plotSer; + $plotAttributes = self::_readChartAttributes($chartDetail); + break; + case "bubbleChart": + $bubbleScale = self::_getAttribute($chartDetail->bubbleScale, 'val', 'integer'); + $plotSer = self::_chartDataSeries($chartDetail,$namespacesChartMeta,$chartDetailKey); + $plotSer->setPlotStyle($bubbleScale); + $plotSeries[] = $plotSer; + $plotAttributes = self::_readChartAttributes($chartDetail); + break; + case "radarChart": + $radarStyle = self::_getAttribute($chartDetail->radarStyle, 'val', 'string'); + $plotSer = self::_chartDataSeries($chartDetail,$namespacesChartMeta,$chartDetailKey); + $plotSer->setPlotStyle($radarStyle); + $plotSeries[] = $plotSer; + $plotAttributes = self::_readChartAttributes($chartDetail); + break; + case "surfaceChart": + case "surface3DChart": + $wireFrame = self::_getAttribute($chartDetail->wireframe, 'val', 'boolean'); + $plotSer = self::_chartDataSeries($chartDetail,$namespacesChartMeta,$chartDetailKey); + $plotSer->setPlotStyle($wireFrame); + $plotSeries[] = $plotSer; + $plotAttributes = self::_readChartAttributes($chartDetail); + break; + case "stockChart": + $plotSeries[] = self::_chartDataSeries($chartDetail,$namespacesChartMeta,$chartDetailKey); + $plotAttributes = self::_readChartAttributes($plotAreaLayout); + break; + } + } + if ($plotAreaLayout == NULL) { + $plotAreaLayout = new PHPExcel_Chart_Layout(); + } + $plotArea = new PHPExcel_Chart_PlotArea($plotAreaLayout,$plotSeries); + self::_setChartAttributes($plotAreaLayout,$plotAttributes); + break; + case "plotVisOnly": + $plotVisOnly = self::_getAttribute($chartDetails, 'val', 'string'); + break; + case "dispBlanksAs": + $dispBlanksAs = self::_getAttribute($chartDetails, 'val', 'string'); + break; + case "title": + $title = self::_chartTitle($chartDetails,$namespacesChartMeta,'title'); + break; + case "legend": + $legendPos = 'r'; + $legendLayout = null; + $legendOverlay = false; + foreach($chartDetails as $chartDetailKey => $chartDetail) { + switch ($chartDetailKey) { + case "legendPos": + $legendPos = self::_getAttribute($chartDetail, 'val', 'string'); + break; + case "overlay": + $legendOverlay = self::_getAttribute($chartDetail, 'val', 'boolean'); + break; + case "layout": + $legendLayout = self::_chartLayoutDetails($chartDetail,$namespacesChartMeta,'legend'); + break; + } + } + $legend = new PHPExcel_Chart_Legend($legendPos, $legendLayout, $legendOverlay); + break; + } + } + } + } + $chart = new PHPExcel_Chart($chartName,$title,$legend,$plotArea,$plotVisOnly,$dispBlanksAs,$XaxisLabel,$YaxisLabel); + + return $chart; + } // function readChart() + + + private static function _chartTitle($titleDetails,$namespacesChartMeta,$type) { + $caption = array(); + $titleLayout = null; + foreach($titleDetails as $titleDetailKey => $chartDetail) { + switch ($titleDetailKey) { + case "tx": + $titleDetails = $chartDetail->rich->children($namespacesChartMeta['a']); + foreach($titleDetails as $titleKey => $titleDetail) { + switch ($titleKey) { + case "p": + $titleDetailPart = $titleDetail->children($namespacesChartMeta['a']); + $caption[] = self::_parseRichText($titleDetailPart); + } + } + break; + case "layout": + $titleLayout = self::_chartLayoutDetails($chartDetail,$namespacesChartMeta); + break; + } + } + + return new PHPExcel_Chart_Title($caption, $titleLayout); + } // function _chartTitle() + + + private static function _chartLayoutDetails($chartDetail,$namespacesChartMeta) { + if (!isset($chartDetail->manualLayout)) { + return null; + } + $details = $chartDetail->manualLayout->children($namespacesChartMeta['c']); + if (is_null($details)) { + return null; + } + $layout = array(); + foreach($details as $detailKey => $detail) { +// echo $detailKey,' => ',self::_getAttribute($detail, 'val', 'string'),PHP_EOL; + $layout[$detailKey] = self::_getAttribute($detail, 'val', 'string'); + } + return new PHPExcel_Chart_Layout($layout); + } // function _chartLayoutDetails() + + + private static function _chartDataSeries($chartDetail,$namespacesChartMeta,$plotType) { + $multiSeriesType = NULL; + $smoothLine = false; + $seriesLabel = $seriesCategory = $seriesValues = $plotOrder = array(); + + $seriesDetailSet = $chartDetail->children($namespacesChartMeta['c']); + foreach($seriesDetailSet as $seriesDetailKey => $seriesDetails) { + switch ($seriesDetailKey) { + case "grouping": + $multiSeriesType = self::_getAttribute($chartDetail->grouping, 'val', 'string'); + break; + case "ser": + $marker = NULL; + foreach($seriesDetails as $seriesKey => $seriesDetail) { + switch ($seriesKey) { + case "idx": + $seriesIndex = self::_getAttribute($seriesDetail, 'val', 'integer'); + break; + case "order": + $seriesOrder = self::_getAttribute($seriesDetail, 'val', 'integer'); + $plotOrder[$seriesIndex] = $seriesOrder; + break; + case "tx": + $seriesLabel[$seriesIndex] = self::_chartDataSeriesValueSet($seriesDetail,$namespacesChartMeta); + break; + case "marker": + $marker = self::_getAttribute($seriesDetail->symbol, 'val', 'string'); + break; + case "smooth": + $smoothLine = self::_getAttribute($seriesDetail, 'val', 'boolean'); + break; + case "cat": + $seriesCategory[$seriesIndex] = self::_chartDataSeriesValueSet($seriesDetail,$namespacesChartMeta); + break; + case "val": + $seriesValues[$seriesIndex] = self::_chartDataSeriesValueSet($seriesDetail,$namespacesChartMeta,$marker); + break; + case "xVal": + $seriesCategory[$seriesIndex] = self::_chartDataSeriesValueSet($seriesDetail,$namespacesChartMeta,$marker); + break; + case "yVal": + $seriesValues[$seriesIndex] = self::_chartDataSeriesValueSet($seriesDetail,$namespacesChartMeta,$marker); + break; + } + } + } + } + return new PHPExcel_Chart_DataSeries($plotType,$multiSeriesType,$plotOrder,$seriesLabel,$seriesCategory,$seriesValues,$smoothLine); + } // function _chartDataSeries() + + + private static function _chartDataSeriesValueSet($seriesDetail, $namespacesChartMeta, $marker = null, $smoothLine = false) { + if (isset($seriesDetail->strRef)) { + $seriesSource = (string) $seriesDetail->strRef->f; + $seriesData = self::_chartDataSeriesValues($seriesDetail->strRef->strCache->children($namespacesChartMeta['c']),'s'); + + return new PHPExcel_Chart_DataSeriesValues('String',$seriesSource,$seriesData['formatCode'],$seriesData['pointCount'],$seriesData['dataValues'],$marker,$smoothLine); + } elseif (isset($seriesDetail->numRef)) { + $seriesSource = (string) $seriesDetail->numRef->f; + $seriesData = self::_chartDataSeriesValues($seriesDetail->numRef->numCache->children($namespacesChartMeta['c'])); + + return new PHPExcel_Chart_DataSeriesValues('Number',$seriesSource,$seriesData['formatCode'],$seriesData['pointCount'],$seriesData['dataValues'],$marker,$smoothLine); + } elseif (isset($seriesDetail->multiLvlStrRef)) { + $seriesSource = (string) $seriesDetail->multiLvlStrRef->f; + $seriesData = self::_chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlStrRef->multiLvlStrCache->children($namespacesChartMeta['c']),'s'); + $seriesData['pointCount'] = count($seriesData['dataValues']); + + return new PHPExcel_Chart_DataSeriesValues('String',$seriesSource,$seriesData['formatCode'],$seriesData['pointCount'],$seriesData['dataValues'],$marker,$smoothLine); + } elseif (isset($seriesDetail->multiLvlNumRef)) { + $seriesSource = (string) $seriesDetail->multiLvlNumRef->f; + $seriesData = self::_chartDataSeriesValuesMultiLevel($seriesDetail->multiLvlNumRef->multiLvlNumCache->children($namespacesChartMeta['c']),'s'); + $seriesData['pointCount'] = count($seriesData['dataValues']); + + return new PHPExcel_Chart_DataSeriesValues('String',$seriesSource,$seriesData['formatCode'],$seriesData['pointCount'],$seriesData['dataValues'],$marker,$smoothLine); + } + return null; + } // function _chartDataSeriesValueSet() + + + private static function _chartDataSeriesValues($seriesValueSet,$dataType='n') { + $seriesVal = array(); + $formatCode = ''; + $pointCount = 0; + + foreach($seriesValueSet as $seriesValueIdx => $seriesValue) { + switch ($seriesValueIdx) { + case 'ptCount': + $pointCount = self::_getAttribute($seriesValue, 'val', 'integer'); + break; + case 'formatCode': + $formatCode = (string) $seriesValue; + break; + case 'pt': + $pointVal = self::_getAttribute($seriesValue, 'idx', 'integer'); + if ($dataType == 's') { + $seriesVal[$pointVal] = (string) $seriesValue->v; + } else { + $seriesVal[$pointVal] = (float) $seriesValue->v; + } + break; + } + } + + if (empty($seriesVal)) { + $seriesVal = NULL; + } + + return array( 'formatCode' => $formatCode, + 'pointCount' => $pointCount, + 'dataValues' => $seriesVal + ); + } // function _chartDataSeriesValues() + + + private static function _chartDataSeriesValuesMultiLevel($seriesValueSet,$dataType='n') { + $seriesVal = array(); + $formatCode = ''; + $pointCount = 0; + + foreach($seriesValueSet->lvl as $seriesLevelIdx => $seriesLevel) { + foreach($seriesLevel as $seriesValueIdx => $seriesValue) { + switch ($seriesValueIdx) { + case 'ptCount': + $pointCount = self::_getAttribute($seriesValue, 'val', 'integer'); + break; + case 'formatCode': + $formatCode = (string) $seriesValue; + break; + case 'pt': + $pointVal = self::_getAttribute($seriesValue, 'idx', 'integer'); + if ($dataType == 's') { + $seriesVal[$pointVal][] = (string) $seriesValue->v; + } else { + $seriesVal[$pointVal][] = (float) $seriesValue->v; + } + break; + } + } + } + + return array( 'formatCode' => $formatCode, + 'pointCount' => $pointCount, + 'dataValues' => $seriesVal + ); + } // function _chartDataSeriesValuesMultiLevel() + + private static function _parseRichText($titleDetailPart = null) { + $value = new PHPExcel_RichText(); + + foreach($titleDetailPart as $titleDetailElementKey => $titleDetailElement) { + if (isset($titleDetailElement->t)) { + $objText = $value->createTextRun( (string) $titleDetailElement->t ); + } + if (isset($titleDetailElement->rPr)) { + if (isset($titleDetailElement->rPr->rFont["val"])) { + $objText->getFont()->setName((string) $titleDetailElement->rPr->rFont["val"]); + } + + $fontSize = (self::_getAttribute($titleDetailElement->rPr, 'sz', 'integer')); + if (!is_null($fontSize)) { + $objText->getFont()->setSize(floor($fontSize / 100)); + } + + $fontColor = (self::_getAttribute($titleDetailElement->rPr, 'color', 'string')); + if (!is_null($fontColor)) { + $objText->getFont()->setColor( new PHPExcel_Style_Color( self::_readColor($fontColor) ) ); + } + + $bold = self::_getAttribute($titleDetailElement->rPr, 'b', 'boolean'); + if (!is_null($bold)) { + $objText->getFont()->setBold($bold); + } + + $italic = self::_getAttribute($titleDetailElement->rPr, 'i', 'boolean'); + if (!is_null($italic)) { + $objText->getFont()->setItalic($italic); + } + + $baseline = self::_getAttribute($titleDetailElement->rPr, 'baseline', 'integer'); + if (!is_null($baseline)) { + if ($baseline > 0) { + $objText->getFont()->setSuperScript(true); + } elseif($baseline < 0) { + $objText->getFont()->setSubScript(true); + } + } + + $underscore = (self::_getAttribute($titleDetailElement->rPr, 'u', 'string')); + if (!is_null($underscore)) { + if ($underscore == 'sng') { + $objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); + } elseif($underscore == 'dbl') { + $objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_DOUBLE); + } else { + $objText->getFont()->setUnderline(PHPExcel_Style_Font::UNDERLINE_NONE); + } + } + + $strikethrough = (self::_getAttribute($titleDetailElement->rPr, 's', 'string')); + if (!is_null($strikethrough)) { + if ($strikethrough == 'noStrike') { + $objText->getFont()->setStrikethrough(false); + } else { + $objText->getFont()->setStrikethrough(true); + } + } + } + } + + return $value; + } + + private static function _readChartAttributes($chartDetail) { + $plotAttributes = array(); + if (isset($chartDetail->dLbls)) { + if (isset($chartDetail->dLbls->howLegendKey)) { + $plotAttributes['showLegendKey'] = self::_getAttribute($chartDetail->dLbls->showLegendKey, 'val', 'string'); + } + if (isset($chartDetail->dLbls->showVal)) { + $plotAttributes['showVal'] = self::_getAttribute($chartDetail->dLbls->showVal, 'val', 'string'); + } + if (isset($chartDetail->dLbls->showCatName)) { + $plotAttributes['showCatName'] = self::_getAttribute($chartDetail->dLbls->showCatName, 'val', 'string'); + } + if (isset($chartDetail->dLbls->showSerName)) { + $plotAttributes['showSerName'] = self::_getAttribute($chartDetail->dLbls->showSerName, 'val', 'string'); + } + if (isset($chartDetail->dLbls->showPercent)) { + $plotAttributes['showPercent'] = self::_getAttribute($chartDetail->dLbls->showPercent, 'val', 'string'); + } + if (isset($chartDetail->dLbls->showBubbleSize)) { + $plotAttributes['showBubbleSize'] = self::_getAttribute($chartDetail->dLbls->showBubbleSize, 'val', 'string'); + } + if (isset($chartDetail->dLbls->showLeaderLines)) { + $plotAttributes['showLeaderLines'] = self::_getAttribute($chartDetail->dLbls->showLeaderLines, 'val', 'string'); + } + } + + return $plotAttributes; + } + + private static function _setChartAttributes($plotArea,$plotAttributes) + { + foreach($plotAttributes as $plotAttributeKey => $plotAttributeValue) { + switch($plotAttributeKey) { + case 'showLegendKey' : + $plotArea->setShowLegendKey($plotAttributeValue); + break; + case 'showVal' : + $plotArea->setShowVal($plotAttributeValue); + break; + case 'showCatName' : + $plotArea->setShowCatName($plotAttributeValue); + break; + case 'showSerName' : + $plotArea->setShowSerName($plotAttributeValue); + break; + case 'showPercent' : + $plotArea->setShowPercent($plotAttributeValue); + break; + case 'showBubbleSize' : + $plotArea->setShowBubbleSize($plotAttributeValue); + break; + case 'showLeaderLines' : + $plotArea->setShowLeaderLines($plotAttributeValue); + break; + } + } + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007/Theme.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007/Theme.php new file mode 100755 index 0000000..62040a4 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel2007/Theme.php @@ -0,0 +1,124 @@ +_themeName = $themeName; + $this->_colourSchemeName = $colourSchemeName; + $this->_colourMap = $colourMap; + } + + /** + * Get Theme Name + * + * @return string + */ + public function getThemeName() + { + return $this->_themeName; + } + + /** + * Get colour Scheme Name + * + * @return string + */ + public function getColourSchemeName() { + return $this->_colourSchemeName; + } + + /** + * Get colour Map Value by Position + * + * @return string + */ + public function getColourByIndex($index=0) { + if (isset($this->_colourMap[$index])) { + return $this->_colourMap[$index]; + } + return null; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if ((is_object($value)) && ($key != '_parent')) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel5.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel5.php new file mode 100755 index 0000000..c9cdb63 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel5.php @@ -0,0 +1,6845 @@ +_data + * + * @var int + */ + private $_dataSize; + + /** + * Current position in stream + * + * @var integer + */ + private $_pos; + + /** + * Workbook to be returned by the reader. + * + * @var PHPExcel + */ + private $_phpExcel; + + /** + * Worksheet that is currently being built by the reader. + * + * @var PHPExcel_Worksheet + */ + private $_phpSheet; + + /** + * BIFF version + * + * @var int + */ + private $_version; + + /** + * Codepage set in the Excel file being read. Only important for BIFF5 (Excel 5.0 - Excel 95) + * For BIFF8 (Excel 97 - Excel 2003) this will always have the value 'UTF-16LE' + * + * @var string + */ + private $_codepage; + + /** + * Shared formats + * + * @var array + */ + private $_formats; + + /** + * Shared fonts + * + * @var array + */ + private $_objFonts; + + /** + * Color palette + * + * @var array + */ + private $_palette; + + /** + * Worksheets + * + * @var array + */ + private $_sheets; + + /** + * External books + * + * @var array + */ + private $_externalBooks; + + /** + * REF structures. Only applies to BIFF8. + * + * @var array + */ + private $_ref; + + /** + * External names + * + * @var array + */ + private $_externalNames; + + /** + * Defined names + * + * @var array + */ + private $_definedname; + + /** + * Shared strings. Only applies to BIFF8. + * + * @var array + */ + private $_sst; + + /** + * Panes are frozen? (in sheet currently being read). See WINDOW2 record. + * + * @var boolean + */ + private $_frozen; + + /** + * Fit printout to number of pages? (in sheet currently being read). See SHEETPR record. + * + * @var boolean + */ + private $_isFitToPages; + + /** + * Objects. One OBJ record contributes with one entry. + * + * @var array + */ + private $_objs; + + /** + * Text Objects. One TXO record corresponds with one entry. + * + * @var array + */ + private $_textObjects; + + /** + * Cell Annotations (BIFF8) + * + * @var array + */ + private $_cellNotes; + + /** + * The combined MSODRAWINGGROUP data + * + * @var string + */ + private $_drawingGroupData; + + /** + * The combined MSODRAWING data (per sheet) + * + * @var string + */ + private $_drawingData; + + /** + * Keep track of XF index + * + * @var int + */ + private $_xfIndex; + + /** + * Mapping of XF index (that is a cell XF) to final index in cellXf collection + * + * @var array + */ + private $_mapCellXfIndex; + + /** + * Mapping of XF index (that is a style XF) to final index in cellStyleXf collection + * + * @var array + */ + private $_mapCellStyleXfIndex; + + /** + * The shared formulas in a sheet. One SHAREDFMLA record contributes with one value. + * + * @var array + */ + private $_sharedFormulas; + + /** + * The shared formula parts in a sheet. One FORMULA record contributes with one value if it + * refers to a shared formula. + * + * @var array + */ + private $_sharedFormulaParts; + + + /** + * Create a new PHPExcel_Reader_Excel5 instance + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + try { + // Use ParseXL for the hard work. + $ole = new PHPExcel_Shared_OLERead(); + + // get excel data + $res = $ole->read($pFilename); + return true; + } catch (PHPExcel_Exception $e) { + return false; + } + } + + + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $worksheetNames = array(); + + // Read the OLE file + $this->_loadOLE($pFilename); + + // total byte size of Excel data (workbook global substream + sheet substreams) + $this->_dataSize = strlen($this->_data); + + $this->_pos = 0; + $this->_sheets = array(); + + // Parse Workbook Global Substream + while ($this->_pos < $this->_dataSize) { + $code = self::_GetInt2d($this->_data, $this->_pos); + + switch ($code) { + case self::XLS_Type_BOF: $this->_readBof(); break; + case self::XLS_Type_SHEET: $this->_readSheet(); break; + case self::XLS_Type_EOF: $this->_readDefault(); break 2; + default: $this->_readDefault(); break; + } + } + + foreach ($this->_sheets as $sheet) { + if ($sheet['sheetType'] != 0x00) { + // 0x00: Worksheet, 0x02: Chart, 0x06: Visual Basic module + continue; + } + + $worksheetNames[] = $sheet['name']; + } + + return $worksheetNames; + } + + + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $worksheetInfo = array(); + + // Read the OLE file + $this->_loadOLE($pFilename); + + // total byte size of Excel data (workbook global substream + sheet substreams) + $this->_dataSize = strlen($this->_data); + + // initialize + $this->_pos = 0; + $this->_sheets = array(); + + // Parse Workbook Global Substream + while ($this->_pos < $this->_dataSize) { + $code = self::_GetInt2d($this->_data, $this->_pos); + + switch ($code) { + case self::XLS_Type_BOF: $this->_readBof(); break; + case self::XLS_Type_SHEET: $this->_readSheet(); break; + case self::XLS_Type_EOF: $this->_readDefault(); break 2; + default: $this->_readDefault(); break; + } + } + + // Parse the individual sheets + foreach ($this->_sheets as $sheet) { + + if ($sheet['sheetType'] != 0x00) { + // 0x00: Worksheet + // 0x02: Chart + // 0x06: Visual Basic module + continue; + } + + $tmpInfo = array(); + $tmpInfo['worksheetName'] = $sheet['name']; + $tmpInfo['lastColumnLetter'] = 'A'; + $tmpInfo['lastColumnIndex'] = 0; + $tmpInfo['totalRows'] = 0; + $tmpInfo['totalColumns'] = 0; + + $this->_pos = $sheet['offset']; + + while ($this->_pos <= $this->_dataSize - 4) { + $code = self::_GetInt2d($this->_data, $this->_pos); + + switch ($code) { + case self::XLS_Type_RK: + case self::XLS_Type_LABELSST: + case self::XLS_Type_NUMBER: + case self::XLS_Type_FORMULA: + case self::XLS_Type_BOOLERR: + case self::XLS_Type_LABEL: + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + $rowIndex = self::_GetInt2d($recordData, 0) + 1; + $columnIndex = self::_GetInt2d($recordData, 2); + + $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex); + $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex); + break; + case self::XLS_Type_BOF: $this->_readBof(); break; + case self::XLS_Type_EOF: $this->_readDefault(); break 2; + default: $this->_readDefault(); break; + } + } + + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; + + $worksheetInfo[] = $tmpInfo; + } + + return $worksheetInfo; + } + + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Read the OLE file + $this->_loadOLE($pFilename); + + // Initialisations + $this->_phpExcel = new PHPExcel; + $this->_phpExcel->removeSheetByIndex(0); // remove 1st sheet + if (!$this->_readDataOnly) { + $this->_phpExcel->removeCellStyleXfByIndex(0); // remove the default style + $this->_phpExcel->removeCellXfByIndex(0); // remove the default style + } + + // Read the summary information stream (containing meta data) + $this->_readSummaryInformation(); + + // Read the Additional document summary information stream (containing application-specific meta data) + $this->_readDocumentSummaryInformation(); + + // total byte size of Excel data (workbook global substream + sheet substreams) + $this->_dataSize = strlen($this->_data); + + // initialize + $this->_pos = 0; + $this->_codepage = 'CP1252'; + $this->_formats = array(); + $this->_objFonts = array(); + $this->_palette = array(); + $this->_sheets = array(); + $this->_externalBooks = array(); + $this->_ref = array(); + $this->_definedname = array(); + $this->_sst = array(); + $this->_drawingGroupData = ''; + $this->_xfIndex = ''; + $this->_mapCellXfIndex = array(); + $this->_mapCellStyleXfIndex = array(); + + // Parse Workbook Global Substream + while ($this->_pos < $this->_dataSize) { + $code = self::_GetInt2d($this->_data, $this->_pos); + + switch ($code) { + case self::XLS_Type_BOF: $this->_readBof(); break; + case self::XLS_Type_FILEPASS: $this->_readFilepass(); break; + case self::XLS_Type_CODEPAGE: $this->_readCodepage(); break; + case self::XLS_Type_DATEMODE: $this->_readDateMode(); break; + case self::XLS_Type_FONT: $this->_readFont(); break; + case self::XLS_Type_FORMAT: $this->_readFormat(); break; + case self::XLS_Type_XF: $this->_readXf(); break; + case self::XLS_Type_XFEXT: $this->_readXfExt(); break; + case self::XLS_Type_STYLE: $this->_readStyle(); break; + case self::XLS_Type_PALETTE: $this->_readPalette(); break; + case self::XLS_Type_SHEET: $this->_readSheet(); break; + case self::XLS_Type_EXTERNALBOOK: $this->_readExternalBook(); break; + case self::XLS_Type_EXTERNNAME: $this->_readExternName(); break; + case self::XLS_Type_EXTERNSHEET: $this->_readExternSheet(); break; + case self::XLS_Type_DEFINEDNAME: $this->_readDefinedName(); break; + case self::XLS_Type_MSODRAWINGGROUP: $this->_readMsoDrawingGroup(); break; + case self::XLS_Type_SST: $this->_readSst(); break; + case self::XLS_Type_EOF: $this->_readDefault(); break 2; + default: $this->_readDefault(); break; + } + } + + // Resolve indexed colors for font, fill, and border colors + // Cannot be resolved already in XF record, because PALETTE record comes afterwards + if (!$this->_readDataOnly) { + foreach ($this->_objFonts as $objFont) { + if (isset($objFont->colorIndex)) { + $color = self::_readColor($objFont->colorIndex,$this->_palette,$this->_version); + $objFont->getColor()->setRGB($color['rgb']); + } + } + + foreach ($this->_phpExcel->getCellXfCollection() as $objStyle) { + // fill start and end color + $fill = $objStyle->getFill(); + + if (isset($fill->startcolorIndex)) { + $startColor = self::_readColor($fill->startcolorIndex,$this->_palette,$this->_version); + $fill->getStartColor()->setRGB($startColor['rgb']); + } + + if (isset($fill->endcolorIndex)) { + $endColor = self::_readColor($fill->endcolorIndex,$this->_palette,$this->_version); + $fill->getEndColor()->setRGB($endColor['rgb']); + } + + // border colors + $top = $objStyle->getBorders()->getTop(); + $right = $objStyle->getBorders()->getRight(); + $bottom = $objStyle->getBorders()->getBottom(); + $left = $objStyle->getBorders()->getLeft(); + $diagonal = $objStyle->getBorders()->getDiagonal(); + + if (isset($top->colorIndex)) { + $borderTopColor = self::_readColor($top->colorIndex,$this->_palette,$this->_version); + $top->getColor()->setRGB($borderTopColor['rgb']); + } + + if (isset($right->colorIndex)) { + $borderRightColor = self::_readColor($right->colorIndex,$this->_palette,$this->_version); + $right->getColor()->setRGB($borderRightColor['rgb']); + } + + if (isset($bottom->colorIndex)) { + $borderBottomColor = self::_readColor($bottom->colorIndex,$this->_palette,$this->_version); + $bottom->getColor()->setRGB($borderBottomColor['rgb']); + } + + if (isset($left->colorIndex)) { + $borderLeftColor = self::_readColor($left->colorIndex,$this->_palette,$this->_version); + $left->getColor()->setRGB($borderLeftColor['rgb']); + } + + if (isset($diagonal->colorIndex)) { + $borderDiagonalColor = self::_readColor($diagonal->colorIndex,$this->_palette,$this->_version); + $diagonal->getColor()->setRGB($borderDiagonalColor['rgb']); + } + } + } + + // treat MSODRAWINGGROUP records, workbook-level Escher + if (!$this->_readDataOnly && $this->_drawingGroupData) { + $escherWorkbook = new PHPExcel_Shared_Escher(); + $reader = new PHPExcel_Reader_Excel5_Escher($escherWorkbook); + $escherWorkbook = $reader->load($this->_drawingGroupData); + + // debug Escher stream + //$debug = new Debug_Escher(new PHPExcel_Shared_Escher()); + //$debug->load($this->_drawingGroupData); + } + + // Parse the individual sheets + foreach ($this->_sheets as $sheet) { + + if ($sheet['sheetType'] != 0x00) { + // 0x00: Worksheet, 0x02: Chart, 0x06: Visual Basic module + continue; + } + + // check if sheet should be skipped + if (isset($this->_loadSheetsOnly) && !in_array($sheet['name'], $this->_loadSheetsOnly)) { + continue; + } + + // add sheet to PHPExcel object + $this->_phpSheet = $this->_phpExcel->createSheet(); + // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in formula + // cells... during the load, all formulae should be correct, and we're simply bringing the worksheet + // name in line with the formula, not the reverse + $this->_phpSheet->setTitle($sheet['name'],false); + $this->_phpSheet->setSheetState($sheet['sheetState']); + + $this->_pos = $sheet['offset']; + + // Initialize isFitToPages. May change after reading SHEETPR record. + $this->_isFitToPages = false; + + // Initialize drawingData + $this->_drawingData = ''; + + // Initialize objs + $this->_objs = array(); + + // Initialize shared formula parts + $this->_sharedFormulaParts = array(); + + // Initialize shared formulas + $this->_sharedFormulas = array(); + + // Initialize text objs + $this->_textObjects = array(); + + // Initialize cell annotations + $this->_cellNotes = array(); + $this->textObjRef = -1; + + while ($this->_pos <= $this->_dataSize - 4) { + $code = self::_GetInt2d($this->_data, $this->_pos); + + switch ($code) { + case self::XLS_Type_BOF: $this->_readBof(); break; + case self::XLS_Type_PRINTGRIDLINES: $this->_readPrintGridlines(); break; + case self::XLS_Type_DEFAULTROWHEIGHT: $this->_readDefaultRowHeight(); break; + case self::XLS_Type_SHEETPR: $this->_readSheetPr(); break; + case self::XLS_Type_HORIZONTALPAGEBREAKS: $this->_readHorizontalPageBreaks(); break; + case self::XLS_Type_VERTICALPAGEBREAKS: $this->_readVerticalPageBreaks(); break; + case self::XLS_Type_HEADER: $this->_readHeader(); break; + case self::XLS_Type_FOOTER: $this->_readFooter(); break; + case self::XLS_Type_HCENTER: $this->_readHcenter(); break; + case self::XLS_Type_VCENTER: $this->_readVcenter(); break; + case self::XLS_Type_LEFTMARGIN: $this->_readLeftMargin(); break; + case self::XLS_Type_RIGHTMARGIN: $this->_readRightMargin(); break; + case self::XLS_Type_TOPMARGIN: $this->_readTopMargin(); break; + case self::XLS_Type_BOTTOMMARGIN: $this->_readBottomMargin(); break; + case self::XLS_Type_PAGESETUP: $this->_readPageSetup(); break; + case self::XLS_Type_PROTECT: $this->_readProtect(); break; + case self::XLS_Type_SCENPROTECT: $this->_readScenProtect(); break; + case self::XLS_Type_OBJECTPROTECT: $this->_readObjectProtect(); break; + case self::XLS_Type_PASSWORD: $this->_readPassword(); break; + case self::XLS_Type_DEFCOLWIDTH: $this->_readDefColWidth(); break; + case self::XLS_Type_COLINFO: $this->_readColInfo(); break; + case self::XLS_Type_DIMENSION: $this->_readDefault(); break; + case self::XLS_Type_ROW: $this->_readRow(); break; + case self::XLS_Type_DBCELL: $this->_readDefault(); break; + case self::XLS_Type_RK: $this->_readRk(); break; + case self::XLS_Type_LABELSST: $this->_readLabelSst(); break; + case self::XLS_Type_MULRK: $this->_readMulRk(); break; + case self::XLS_Type_NUMBER: $this->_readNumber(); break; + case self::XLS_Type_FORMULA: $this->_readFormula(); break; + case self::XLS_Type_SHAREDFMLA: $this->_readSharedFmla(); break; + case self::XLS_Type_BOOLERR: $this->_readBoolErr(); break; + case self::XLS_Type_MULBLANK: $this->_readMulBlank(); break; + case self::XLS_Type_LABEL: $this->_readLabel(); break; + case self::XLS_Type_BLANK: $this->_readBlank(); break; + case self::XLS_Type_MSODRAWING: $this->_readMsoDrawing(); break; + case self::XLS_Type_OBJ: $this->_readObj(); break; + case self::XLS_Type_WINDOW2: $this->_readWindow2(); break; + case self::XLS_Type_PAGELAYOUTVIEW: $this->_readPageLayoutView(); break; + case self::XLS_Type_SCL: $this->_readScl(); break; + case self::XLS_Type_PANE: $this->_readPane(); break; + case self::XLS_Type_SELECTION: $this->_readSelection(); break; + case self::XLS_Type_MERGEDCELLS: $this->_readMergedCells(); break; + case self::XLS_Type_HYPERLINK: $this->_readHyperLink(); break; + case self::XLS_Type_DATAVALIDATIONS: $this->_readDataValidations(); break; + case self::XLS_Type_DATAVALIDATION: $this->_readDataValidation(); break; + case self::XLS_Type_SHEETLAYOUT: $this->_readSheetLayout(); break; + case self::XLS_Type_SHEETPROTECTION: $this->_readSheetProtection(); break; + case self::XLS_Type_RANGEPROTECTION: $this->_readRangeProtection(); break; + case self::XLS_Type_NOTE: $this->_readNote(); break; + //case self::XLS_Type_IMDATA: $this->_readImData(); break; + case self::XLS_Type_TXO: $this->_readTextObject(); break; + case self::XLS_Type_CONTINUE: $this->_readContinue(); break; + case self::XLS_Type_EOF: $this->_readDefault(); break 2; + default: $this->_readDefault(); break; + } + + } + + // treat MSODRAWING records, sheet-level Escher + if (!$this->_readDataOnly && $this->_drawingData) { + $escherWorksheet = new PHPExcel_Shared_Escher(); + $reader = new PHPExcel_Reader_Excel5_Escher($escherWorksheet); + $escherWorksheet = $reader->load($this->_drawingData); + + // debug Escher stream + //$debug = new Debug_Escher(new PHPExcel_Shared_Escher()); + //$debug->load($this->_drawingData); + + // get all spContainers in one long array, so they can be mapped to OBJ records + $allSpContainers = $escherWorksheet->getDgContainer()->getSpgrContainer()->getAllSpContainers(); + } + + // treat OBJ records + foreach ($this->_objs as $n => $obj) { +// echo '
    Object reference is ',$n,'
    '; +// var_dump($obj); +// echo '
    '; + + // the first shape container never has a corresponding OBJ record, hence $n + 1 + if (isset($allSpContainers[$n + 1]) && is_object($allSpContainers[$n + 1])) { + $spContainer = $allSpContainers[$n + 1]; + + // we skip all spContainers that are a part of a group shape since we cannot yet handle those + if ($spContainer->getNestingLevel() > 1) { + continue; + } + + // calculate the width and height of the shape + list($startColumn, $startRow) = PHPExcel_Cell::coordinateFromString($spContainer->getStartCoordinates()); + list($endColumn, $endRow) = PHPExcel_Cell::coordinateFromString($spContainer->getEndCoordinates()); + + $startOffsetX = $spContainer->getStartOffsetX(); + $startOffsetY = $spContainer->getStartOffsetY(); + $endOffsetX = $spContainer->getEndOffsetX(); + $endOffsetY = $spContainer->getEndOffsetY(); + + $width = PHPExcel_Shared_Excel5::getDistanceX($this->_phpSheet, $startColumn, $startOffsetX, $endColumn, $endOffsetX); + $height = PHPExcel_Shared_Excel5::getDistanceY($this->_phpSheet, $startRow, $startOffsetY, $endRow, $endOffsetY); + + // calculate offsetX and offsetY of the shape + $offsetX = $startOffsetX * PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, $startColumn) / 1024; + $offsetY = $startOffsetY * PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $startRow) / 256; + + switch ($obj['otObjType']) { + case 0x19: + // Note +// echo 'Cell Annotation Object
    '; +// echo 'Object ID is ',$obj['idObjID'],'
    '; +// + if (isset($this->_cellNotes[$obj['idObjID']])) { + $cellNote = $this->_cellNotes[$obj['idObjID']]; + + if (isset($this->_textObjects[$obj['idObjID']])) { + $textObject = $this->_textObjects[$obj['idObjID']]; + $this->_cellNotes[$obj['idObjID']]['objTextData'] = $textObject; + } + } + break; + + case 0x08: +// echo 'Picture Object
    '; + // picture + + // get index to BSE entry (1-based) + $BSEindex = $spContainer->getOPT(0x0104); + $BSECollection = $escherWorkbook->getDggContainer()->getBstoreContainer()->getBSECollection(); + $BSE = $BSECollection[$BSEindex - 1]; + $blipType = $BSE->getBlipType(); + + // need check because some blip types are not supported by Escher reader such as EMF + if ($blip = $BSE->getBlip()) { + $ih = imagecreatefromstring($blip->getData()); + $drawing = new PHPExcel_Worksheet_MemoryDrawing(); + $drawing->setImageResource($ih); + + // width, height, offsetX, offsetY + $drawing->setResizeProportional(false); + $drawing->setWidth($width); + $drawing->setHeight($height); + $drawing->setOffsetX($offsetX); + $drawing->setOffsetY($offsetY); + + switch ($blipType) { + case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG: + $drawing->setRenderingFunction(PHPExcel_Worksheet_MemoryDrawing::RENDERING_JPEG); + $drawing->setMimeType(PHPExcel_Worksheet_MemoryDrawing::MIMETYPE_JPEG); + break; + + case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG: + $drawing->setRenderingFunction(PHPExcel_Worksheet_MemoryDrawing::RENDERING_PNG); + $drawing->setMimeType(PHPExcel_Worksheet_MemoryDrawing::MIMETYPE_PNG); + break; + } + + $drawing->setWorksheet($this->_phpSheet); + $drawing->setCoordinates($spContainer->getStartCoordinates()); + } + + break; + + default: + // other object type + break; + + } + } + } + + // treat SHAREDFMLA records + if ($this->_version == self::XLS_BIFF8) { + foreach ($this->_sharedFormulaParts as $cell => $baseCell) { + list($column, $row) = PHPExcel_Cell::coordinateFromString($cell); + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($column, $row, $this->_phpSheet->getTitle()) ) { + $formula = $this->_getFormulaFromStructure($this->_sharedFormulas[$baseCell], $cell); + $this->_phpSheet->getCell($cell)->setValueExplicit('=' . $formula, PHPExcel_Cell_DataType::TYPE_FORMULA); + } + } + } + + if (!empty($this->_cellNotes)) { + foreach($this->_cellNotes as $note => $noteDetails) { + if (!isset($noteDetails['objTextData'])) { + if (isset($this->_textObjects[$note])) { + $textObject = $this->_textObjects[$note]; + $noteDetails['objTextData'] = $textObject; + } else { + $noteDetails['objTextData']['text'] = ''; + } + } +// echo 'Cell annotation ',$note,'
    '; +// var_dump($noteDetails); +// echo '
    '; + $cellAddress = str_replace('$','',$noteDetails['cellRef']); + $this->_phpSheet->getComment( $cellAddress ) + ->setAuthor( $noteDetails['author'] ) + ->setText($this->_parseRichText($noteDetails['objTextData']['text']) ); + } + } + } + + // add the named ranges (defined names) + foreach ($this->_definedname as $definedName) { + if ($definedName['isBuiltInName']) { + switch ($definedName['name']) { + + case pack('C', 0x06): + // print area + // in general, formula looks like this: Foo!$C$7:$J$66,Bar!$A$1:$IV$2 + $ranges = explode(',', $definedName['formula']); // FIXME: what if sheetname contains comma? + + $extractedRanges = array(); + foreach ($ranges as $range) { + // $range should look like one of these + // Foo!$C$7:$J$66 + // Bar!$A$1:$IV$2 + + $explodes = explode('!', $range); // FIXME: what if sheetname contains exclamation mark? + $sheetName = trim($explodes[0], "'"); + + if (count($explodes) == 2) { + if (strpos($explodes[1], ':') === FALSE) { + $explodes[1] = $explodes[1] . ':' . $explodes[1]; + } + $extractedRanges[] = str_replace('$', '', $explodes[1]); // C7:J66 + } + } + if ($docSheet = $this->_phpExcel->getSheetByName($sheetName)) { + $docSheet->getPageSetup()->setPrintArea(implode(',', $extractedRanges)); // C7:J66,A1:IV2 + } + break; + + case pack('C', 0x07): + // print titles (repeating rows) + // Assuming BIFF8, there are 3 cases + // 1. repeating rows + // formula looks like this: Sheet!$A$1:$IV$2 + // rows 1-2 repeat + // 2. repeating columns + // formula looks like this: Sheet!$A$1:$B$65536 + // columns A-B repeat + // 3. both repeating rows and repeating columns + // formula looks like this: Sheet!$A$1:$B$65536,Sheet!$A$1:$IV$2 + + $ranges = explode(',', $definedName['formula']); // FIXME: what if sheetname contains comma? + + foreach ($ranges as $range) { + // $range should look like this one of these + // Sheet!$A$1:$B$65536 + // Sheet!$A$1:$IV$2 + + $explodes = explode('!', $range); + + if (count($explodes) == 2) { + if ($docSheet = $this->_phpExcel->getSheetByName($explodes[0])) { + + $extractedRange = $explodes[1]; + $extractedRange = str_replace('$', '', $extractedRange); + + $coordinateStrings = explode(':', $extractedRange); + if (count($coordinateStrings) == 2) { + list($firstColumn, $firstRow) = PHPExcel_Cell::coordinateFromString($coordinateStrings[0]); + list($lastColumn, $lastRow) = PHPExcel_Cell::coordinateFromString($coordinateStrings[1]); + + if ($firstColumn == 'A' and $lastColumn == 'IV') { + // then we have repeating rows + $docSheet->getPageSetup()->setRowsToRepeatAtTop(array($firstRow, $lastRow)); + } elseif ($firstRow == 1 and $lastRow == 65536) { + // then we have repeating columns + $docSheet->getPageSetup()->setColumnsToRepeatAtLeft(array($firstColumn, $lastColumn)); + } + } + } + } + } + break; + + } + } else { + // Extract range + $explodes = explode('!', $definedName['formula']); + + if (count($explodes) == 2) { + if (($docSheet = $this->_phpExcel->getSheetByName($explodes[0])) || + ($docSheet = $this->_phpExcel->getSheetByName(trim($explodes[0],"'")))) { + $extractedRange = $explodes[1]; + $extractedRange = str_replace('$', '', $extractedRange); + + $localOnly = ($definedName['scope'] == 0) ? false : true; + + $scope = ($definedName['scope'] == 0) ? + null : $this->_phpExcel->getSheetByName($this->_sheets[$definedName['scope'] - 1]['name']); + + $this->_phpExcel->addNamedRange( new PHPExcel_NamedRange((string)$definedName['name'], $docSheet, $extractedRange, $localOnly, $scope) ); + } + } else { + // Named Value + // TODO Provide support for named values + } + } + } + + return $this->_phpExcel; + } + + + /** + * Use OLE reader to extract the relevant data streams from the OLE file + * + * @param string $pFilename + */ + private function _loadOLE($pFilename) + { + // OLE reader + $ole = new PHPExcel_Shared_OLERead(); + + // get excel data, + $res = $ole->read($pFilename); + // Get workbook data: workbook stream + sheet streams + $this->_data = $ole->getStream($ole->wrkbook); + + // Get summary information data + $this->_summaryInformation = $ole->getStream($ole->summaryInformation); + + // Get additional document summary information data + $this->_documentSummaryInformation = $ole->getStream($ole->documentSummaryInformation); + + // Get user-defined property data +// $this->_userDefinedProperties = $ole->getUserDefinedProperties(); + } + + + /** + * Read summary information + */ + private function _readSummaryInformation() + { + if (!isset($this->_summaryInformation)) { + return; + } + + // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) + // offset: 2; size: 2; + // offset: 4; size: 2; OS version + // offset: 6; size: 2; OS indicator + // offset: 8; size: 16 + // offset: 24; size: 4; section count + $secCount = self::_GetInt4d($this->_summaryInformation, 24); + + // offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9 + // offset: 44; size: 4 + $secOffset = self::_GetInt4d($this->_summaryInformation, 44); + + // section header + // offset: $secOffset; size: 4; section length + $secLength = self::_GetInt4d($this->_summaryInformation, $secOffset); + + // offset: $secOffset+4; size: 4; property count + $countProperties = self::_GetInt4d($this->_summaryInformation, $secOffset+4); + + // initialize code page (used to resolve string values) + $codePage = 'CP1252'; + + // offset: ($secOffset+8); size: var + // loop through property decarations and properties + for ($i = 0; $i < $countProperties; ++$i) { + + // offset: ($secOffset+8) + (8 * $i); size: 4; property ID + $id = self::_GetInt4d($this->_summaryInformation, ($secOffset+8) + (8 * $i)); + + // Use value of property id as appropriate + // offset: ($secOffset+12) + (8 * $i); size: 4; offset from beginning of section (48) + $offset = self::_GetInt4d($this->_summaryInformation, ($secOffset+12) + (8 * $i)); + + $type = self::_GetInt4d($this->_summaryInformation, $secOffset + $offset); + + // initialize property value + $value = null; + + // extract property value based on property type + switch ($type) { + case 0x02: // 2 byte signed integer + $value = self::_GetInt2d($this->_summaryInformation, $secOffset + 4 + $offset); + break; + + case 0x03: // 4 byte signed integer + $value = self::_GetInt4d($this->_summaryInformation, $secOffset + 4 + $offset); + break; + + case 0x13: // 4 byte unsigned integer + // not needed yet, fix later if necessary + break; + + case 0x1E: // null-terminated string prepended by dword string length + $byteLength = self::_GetInt4d($this->_summaryInformation, $secOffset + 4 + $offset); + $value = substr($this->_summaryInformation, $secOffset + 8 + $offset, $byteLength); + $value = PHPExcel_Shared_String::ConvertEncoding($value, 'UTF-8', $codePage); + $value = rtrim($value); + break; + + case 0x40: // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + // PHP-time + $value = PHPExcel_Shared_OLE::OLE2LocalDate(substr($this->_summaryInformation, $secOffset + 4 + $offset, 8)); + break; + + case 0x47: // Clipboard format + // not needed yet, fix later if necessary + break; + } + + switch ($id) { + case 0x01: // Code Page + $codePage = PHPExcel_Shared_CodePage::NumberToName($value); + break; + + case 0x02: // Title + $this->_phpExcel->getProperties()->setTitle($value); + break; + + case 0x03: // Subject + $this->_phpExcel->getProperties()->setSubject($value); + break; + + case 0x04: // Author (Creator) + $this->_phpExcel->getProperties()->setCreator($value); + break; + + case 0x05: // Keywords + $this->_phpExcel->getProperties()->setKeywords($value); + break; + + case 0x06: // Comments (Description) + $this->_phpExcel->getProperties()->setDescription($value); + break; + + case 0x07: // Template + // Not supported by PHPExcel + break; + + case 0x08: // Last Saved By (LastModifiedBy) + $this->_phpExcel->getProperties()->setLastModifiedBy($value); + break; + + case 0x09: // Revision + // Not supported by PHPExcel + break; + + case 0x0A: // Total Editing Time + // Not supported by PHPExcel + break; + + case 0x0B: // Last Printed + // Not supported by PHPExcel + break; + + case 0x0C: // Created Date/Time + $this->_phpExcel->getProperties()->setCreated($value); + break; + + case 0x0D: // Modified Date/Time + $this->_phpExcel->getProperties()->setModified($value); + break; + + case 0x0E: // Number of Pages + // Not supported by PHPExcel + break; + + case 0x0F: // Number of Words + // Not supported by PHPExcel + break; + + case 0x10: // Number of Characters + // Not supported by PHPExcel + break; + + case 0x11: // Thumbnail + // Not supported by PHPExcel + break; + + case 0x12: // Name of creating application + // Not supported by PHPExcel + break; + + case 0x13: // Security + // Not supported by PHPExcel + break; + + } + } + } + + + /** + * Read additional document summary information + */ + private function _readDocumentSummaryInformation() + { + if (!isset($this->_documentSummaryInformation)) { + return; + } + + // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) + // offset: 2; size: 2; + // offset: 4; size: 2; OS version + // offset: 6; size: 2; OS indicator + // offset: 8; size: 16 + // offset: 24; size: 4; section count + $secCount = self::_GetInt4d($this->_documentSummaryInformation, 24); +// echo '$secCount = ',$secCount,'
    '; + + // offset: 28; size: 16; first section's class id: 02 d5 cd d5 9c 2e 1b 10 93 97 08 00 2b 2c f9 ae + // offset: 44; size: 4; first section offset + $secOffset = self::_GetInt4d($this->_documentSummaryInformation, 44); +// echo '$secOffset = ',$secOffset,'
    '; + + // section header + // offset: $secOffset; size: 4; section length + $secLength = self::_GetInt4d($this->_documentSummaryInformation, $secOffset); +// echo '$secLength = ',$secLength,'
    '; + + // offset: $secOffset+4; size: 4; property count + $countProperties = self::_GetInt4d($this->_documentSummaryInformation, $secOffset+4); +// echo '$countProperties = ',$countProperties,'
    '; + + // initialize code page (used to resolve string values) + $codePage = 'CP1252'; + + // offset: ($secOffset+8); size: var + // loop through property decarations and properties + for ($i = 0; $i < $countProperties; ++$i) { +// echo 'Property ',$i,'
    '; + // offset: ($secOffset+8) + (8 * $i); size: 4; property ID + $id = self::_GetInt4d($this->_documentSummaryInformation, ($secOffset+8) + (8 * $i)); +// echo 'ID is ',$id,'
    '; + + // Use value of property id as appropriate + // offset: 60 + 8 * $i; size: 4; offset from beginning of section (48) + $offset = self::_GetInt4d($this->_documentSummaryInformation, ($secOffset+12) + (8 * $i)); + + $type = self::_GetInt4d($this->_documentSummaryInformation, $secOffset + $offset); +// echo 'Type is ',$type,', '; + + // initialize property value + $value = null; + + // extract property value based on property type + switch ($type) { + case 0x02: // 2 byte signed integer + $value = self::_GetInt2d($this->_documentSummaryInformation, $secOffset + 4 + $offset); + break; + + case 0x03: // 4 byte signed integer + $value = self::_GetInt4d($this->_documentSummaryInformation, $secOffset + 4 + $offset); + break; + + case 0x0B: // Boolean + $value = self::_GetInt2d($this->_documentSummaryInformation, $secOffset + 4 + $offset); + $value = ($value == 0 ? false : true); + break; + + case 0x13: // 4 byte unsigned integer + // not needed yet, fix later if necessary + break; + + case 0x1E: // null-terminated string prepended by dword string length + $byteLength = self::_GetInt4d($this->_documentSummaryInformation, $secOffset + 4 + $offset); + $value = substr($this->_documentSummaryInformation, $secOffset + 8 + $offset, $byteLength); + $value = PHPExcel_Shared_String::ConvertEncoding($value, 'UTF-8', $codePage); + $value = rtrim($value); + break; + + case 0x40: // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + // PHP-Time + $value = PHPExcel_Shared_OLE::OLE2LocalDate(substr($this->_documentSummaryInformation, $secOffset + 4 + $offset, 8)); + break; + + case 0x47: // Clipboard format + // not needed yet, fix later if necessary + break; + } + + switch ($id) { + case 0x01: // Code Page + $codePage = PHPExcel_Shared_CodePage::NumberToName($value); + break; + + case 0x02: // Category + $this->_phpExcel->getProperties()->setCategory($value); + break; + + case 0x03: // Presentation Target + // Not supported by PHPExcel + break; + + case 0x04: // Bytes + // Not supported by PHPExcel + break; + + case 0x05: // Lines + // Not supported by PHPExcel + break; + + case 0x06: // Paragraphs + // Not supported by PHPExcel + break; + + case 0x07: // Slides + // Not supported by PHPExcel + break; + + case 0x08: // Notes + // Not supported by PHPExcel + break; + + case 0x09: // Hidden Slides + // Not supported by PHPExcel + break; + + case 0x0A: // MM Clips + // Not supported by PHPExcel + break; + + case 0x0B: // Scale Crop + // Not supported by PHPExcel + break; + + case 0x0C: // Heading Pairs + // Not supported by PHPExcel + break; + + case 0x0D: // Titles of Parts + // Not supported by PHPExcel + break; + + case 0x0E: // Manager + $this->_phpExcel->getProperties()->setManager($value); + break; + + case 0x0F: // Company + $this->_phpExcel->getProperties()->setCompany($value); + break; + + case 0x10: // Links up-to-date + // Not supported by PHPExcel + break; + + } + } + } + + + /** + * Reads a general type of BIFF record. Does nothing except for moving stream pointer forward to next record. + */ + private function _readDefault() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); +// $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + } + + + /** + * The NOTE record specifies a comment associated with a particular cell. In Excel 95 (BIFF7) and earlier versions, + * this record stores a note (cell note). This feature was significantly enhanced in Excel 97. + */ + private function _readNote() + { +// echo 'Read Cell Annotation
    '; + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + $cellAddress = $this->_readBIFF8CellAddress(substr($recordData, 0, 4)); + if ($this->_version == self::XLS_BIFF8) { + $noteObjID = self::_GetInt2d($recordData, 6); + $noteAuthor = self::_readUnicodeStringLong(substr($recordData, 8)); + $noteAuthor = $noteAuthor['value']; +// echo 'Note Address=',$cellAddress,'
    '; +// echo 'Note Object ID=',$noteObjID,'
    '; +// echo 'Note Author=',$noteAuthor,'
    '; +// + $this->_cellNotes[$noteObjID] = array('cellRef' => $cellAddress, + 'objectID' => $noteObjID, + 'author' => $noteAuthor + ); + } else { + $extension = false; + if ($cellAddress == '$B$65536') { + // If the address row is -1 and the column is 0, (which translates as $B$65536) then this is a continuation + // note from the previous cell annotation. We're not yet handling this, so annotations longer than the + // max 2048 bytes will probably throw a wobbly. + $row = self::_GetInt2d($recordData, 0); + $extension = true; + $cellAddress = array_pop(array_keys($this->_phpSheet->getComments())); + } +// echo 'Note Address=',$cellAddress,'
    '; + + $cellAddress = str_replace('$','',$cellAddress); + $noteLength = self::_GetInt2d($recordData, 4); + $noteText = trim(substr($recordData, 6)); +// echo 'Note Length=',$noteLength,'
    '; +// echo 'Note Text=',$noteText,'
    '; + + if ($extension) { + // Concatenate this extension with the currently set comment for the cell + $comment = $this->_phpSheet->getComment( $cellAddress ); + $commentText = $comment->getText()->getPlainText(); + $comment->setText($this->_parseRichText($commentText.$noteText) ); + } else { + // Set comment for the cell + $this->_phpSheet->getComment( $cellAddress ) +// ->setAuthor( $author ) + ->setText($this->_parseRichText($noteText) ); + } + } + + } + + + /** + * The TEXT Object record contains the text associated with a cell annotation. + */ + private function _readTextObject() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // recordData consists of an array of subrecords looking like this: + // grbit: 2 bytes; Option Flags + // rot: 2 bytes; rotation + // cchText: 2 bytes; length of the text (in the first continue record) + // cbRuns: 2 bytes; length of the formatting (in the second continue record) + // followed by the continuation records containing the actual text and formatting + $grbitOpts = self::_GetInt2d($recordData, 0); + $rot = self::_GetInt2d($recordData, 2); + $cchText = self::_GetInt2d($recordData, 10); + $cbRuns = self::_GetInt2d($recordData, 12); + $text = $this->_getSplicedRecordData(); + + $this->_textObjects[$this->textObjRef] = array( + 'text' => substr($text["recordData"],$text["spliceOffsets"][0]+1,$cchText), + 'format' => substr($text["recordData"],$text["spliceOffsets"][1],$cbRuns), + 'alignment' => $grbitOpts, + 'rotation' => $rot + ); + +// echo '_readTextObject()
    '; +// var_dump($this->_textObjects[$this->textObjRef]); +// echo '
    '; + } + + + /** + * Read BOF + */ + private function _readBof() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 2; size: 2; type of the following data + $substreamType = self::_GetInt2d($recordData, 2); + + switch ($substreamType) { + case self::XLS_WorkbookGlobals: + $version = self::_GetInt2d($recordData, 0); + if (($version != self::XLS_BIFF8) && ($version != self::XLS_BIFF7)) { + throw new PHPExcel_Reader_Exception('Cannot read this Excel file. Version is too old.'); + } + $this->_version = $version; + break; + + case self::XLS_Worksheet: + // do not use this version information for anything + // it is unreliable (OpenOffice doc, 5.8), use only version information from the global stream + break; + + default: + // substream, e.g. chart + // just skip the entire substream + do { + $code = self::_GetInt2d($this->_data, $this->_pos); + $this->_readDefault(); + } while ($code != self::XLS_Type_EOF && $this->_pos < $this->_dataSize); + break; + } + } + + + /** + * FILEPASS + * + * This record is part of the File Protection Block. It + * contains information about the read/write password of the + * file. All record contents following this record will be + * encrypted. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readFilepass() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); +// $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + throw new PHPExcel_Reader_Exception('Cannot read encrypted file'); + } + + + /** + * CODEPAGE + * + * This record stores the text encoding used to write byte + * strings, stored as MS Windows code page identifier. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readCodepage() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; code page identifier + $codepage = self::_GetInt2d($recordData, 0); + + $this->_codepage = PHPExcel_Shared_CodePage::NumberToName($codepage); + } + + + /** + * DATEMODE + * + * This record specifies the base date for displaying date + * values. All dates are stored as count of days past this + * base date. In BIFF2-BIFF4 this record is part of the + * Calculation Settings Block. In BIFF5-BIFF8 it is + * stored in the Workbook Globals Substream. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readDateMode() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; 0 = base 1900, 1 = base 1904 + PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_WINDOWS_1900); + if (ord($recordData{0}) == 1) { + PHPExcel_Shared_Date::setExcelCalendar(PHPExcel_Shared_Date::CALENDAR_MAC_1904); + } + } + + + /** + * Read a FONT record + */ + private function _readFont() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + $objFont = new PHPExcel_Style_Font(); + + // offset: 0; size: 2; height of the font (in twips = 1/20 of a point) + $size = self::_GetInt2d($recordData, 0); + $objFont->setSize($size / 20); + + // offset: 2; size: 2; option flags + // bit: 0; mask 0x0001; bold (redundant in BIFF5-BIFF8) + // bit: 1; mask 0x0002; italic + $isItalic = (0x0002 & self::_GetInt2d($recordData, 2)) >> 1; + if ($isItalic) $objFont->setItalic(true); + + // bit: 2; mask 0x0004; underlined (redundant in BIFF5-BIFF8) + // bit: 3; mask 0x0008; strike + $isStrike = (0x0008 & self::_GetInt2d($recordData, 2)) >> 3; + if ($isStrike) $objFont->setStrikethrough(true); + + // offset: 4; size: 2; colour index + $colorIndex = self::_GetInt2d($recordData, 4); + $objFont->colorIndex = $colorIndex; + + // offset: 6; size: 2; font weight + $weight = self::_GetInt2d($recordData, 6); + switch ($weight) { + case 0x02BC: + $objFont->setBold(true); + break; + } + + // offset: 8; size: 2; escapement type + $escapement = self::_GetInt2d($recordData, 8); + switch ($escapement) { + case 0x0001: + $objFont->setSuperScript(true); + break; + case 0x0002: + $objFont->setSubScript(true); + break; + } + + // offset: 10; size: 1; underline type + $underlineType = ord($recordData{10}); + switch ($underlineType) { + case 0x00: + break; // no underline + case 0x01: + $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE); + break; + case 0x02: + $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_DOUBLE); + break; + case 0x21: + $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING); + break; + case 0x22: + $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING); + break; + } + + // offset: 11; size: 1; font family + // offset: 12; size: 1; character set + // offset: 13; size: 1; not used + // offset: 14; size: var; font name + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringShort(substr($recordData, 14)); + } else { + $string = $this->_readByteStringShort(substr($recordData, 14)); + } + $objFont->setName($string['value']); + + $this->_objFonts[] = $objFont; + } + } + + + /** + * FORMAT + * + * This record contains information about a number format. + * All FORMAT records occur together in a sequential list. + * + * In BIFF2-BIFF4 other records referencing a FORMAT record + * contain a zero-based index into this list. From BIFF5 on + * the FORMAT record contains the index itself that will be + * used by other records. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readFormat() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + $indexCode = self::_GetInt2d($recordData, 0); + + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringLong(substr($recordData, 2)); + } else { + // BIFF7 + $string = $this->_readByteStringShort(substr($recordData, 2)); + } + + $formatString = $string['value']; + $this->_formats[$indexCode] = $formatString; + } + } + + + /** + * XF - Extended Format + * + * This record contains formatting information for cells, rows, columns or styles. + * According to http://support.microsoft.com/kb/147732 there are always at least 15 cell style XF + * and 1 cell XF. + * Inspection of Excel files generated by MS Office Excel shows that XF records 0-14 are cell style XF + * and XF record 15 is a cell XF + * We only read the first cell style XF and skip the remaining cell style XF records + * We read all cell XF records. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readXf() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + $objStyle = new PHPExcel_Style(); + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; Index to FONT record + if (self::_GetInt2d($recordData, 0) < 4) { + $fontIndex = self::_GetInt2d($recordData, 0); + } else { + // this has to do with that index 4 is omitted in all BIFF versions for some strange reason + // check the OpenOffice documentation of the FONT record + $fontIndex = self::_GetInt2d($recordData, 0) - 1; + } + $objStyle->setFont($this->_objFonts[$fontIndex]); + + // offset: 2; size: 2; Index to FORMAT record + $numberFormatIndex = self::_GetInt2d($recordData, 2); + if (isset($this->_formats[$numberFormatIndex])) { + // then we have user-defined format code + $numberformat = array('code' => $this->_formats[$numberFormatIndex]); + } elseif (($code = PHPExcel_Style_NumberFormat::builtInFormatCode($numberFormatIndex)) !== '') { + // then we have built-in format code + $numberformat = array('code' => $code); + } else { + // we set the general format code + $numberformat = array('code' => 'General'); + } + $objStyle->getNumberFormat()->setFormatCode($numberformat['code']); + + // offset: 4; size: 2; XF type, cell protection, and parent style XF + // bit 2-0; mask 0x0007; XF_TYPE_PROT + $xfTypeProt = self::_GetInt2d($recordData, 4); + // bit 0; mask 0x01; 1 = cell is locked + $isLocked = (0x01 & $xfTypeProt) >> 0; + $objStyle->getProtection()->setLocked($isLocked ? + PHPExcel_Style_Protection::PROTECTION_INHERIT : PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); + + // bit 1; mask 0x02; 1 = Formula is hidden + $isHidden = (0x02 & $xfTypeProt) >> 1; + $objStyle->getProtection()->setHidden($isHidden ? + PHPExcel_Style_Protection::PROTECTION_PROTECTED : PHPExcel_Style_Protection::PROTECTION_UNPROTECTED); + + // bit 2; mask 0x04; 0 = Cell XF, 1 = Cell Style XF + $isCellStyleXf = (0x04 & $xfTypeProt) >> 2; + + // offset: 6; size: 1; Alignment and text break + // bit 2-0, mask 0x07; horizontal alignment + $horAlign = (0x07 & ord($recordData{6})) >> 0; + switch ($horAlign) { + case 0: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_GENERAL); + break; + case 1: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_LEFT); + break; + case 2: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER); + break; + case 3: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_RIGHT); + break; + case 5: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY); + break; + case 6: + $objStyle->getAlignment()->setHorizontal(PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS); + break; + } + // bit 3, mask 0x08; wrap text + $wrapText = (0x08 & ord($recordData{6})) >> 3; + switch ($wrapText) { + case 0: + $objStyle->getAlignment()->setWrapText(false); + break; + case 1: + $objStyle->getAlignment()->setWrapText(true); + break; + } + // bit 6-4, mask 0x70; vertical alignment + $vertAlign = (0x70 & ord($recordData{6})) >> 4; + switch ($vertAlign) { + case 0: + $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_TOP); + break; + case 1: + $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_CENTER); + break; + case 2: + $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_BOTTOM); + break; + case 3: + $objStyle->getAlignment()->setVertical(PHPExcel_Style_Alignment::VERTICAL_JUSTIFY); + break; + } + + if ($this->_version == self::XLS_BIFF8) { + // offset: 7; size: 1; XF_ROTATION: Text rotation angle + $angle = ord($recordData{7}); + $rotation = 0; + if ($angle <= 90) { + $rotation = $angle; + } else if ($angle <= 180) { + $rotation = 90 - $angle; + } else if ($angle == 255) { + $rotation = -165; + } + $objStyle->getAlignment()->setTextRotation($rotation); + + // offset: 8; size: 1; Indentation, shrink to cell size, and text direction + // bit: 3-0; mask: 0x0F; indent level + $indent = (0x0F & ord($recordData{8})) >> 0; + $objStyle->getAlignment()->setIndent($indent); + + // bit: 4; mask: 0x10; 1 = shrink content to fit into cell + $shrinkToFit = (0x10 & ord($recordData{8})) >> 4; + switch ($shrinkToFit) { + case 0: + $objStyle->getAlignment()->setShrinkToFit(false); + break; + case 1: + $objStyle->getAlignment()->setShrinkToFit(true); + break; + } + + // offset: 9; size: 1; Flags used for attribute groups + + // offset: 10; size: 4; Cell border lines and background area + // bit: 3-0; mask: 0x0000000F; left style + if ($bordersLeftStyle = self::_mapBorderStyle((0x0000000F & self::_GetInt4d($recordData, 10)) >> 0)) { + $objStyle->getBorders()->getLeft()->setBorderStyle($bordersLeftStyle); + } + // bit: 7-4; mask: 0x000000F0; right style + if ($bordersRightStyle = self::_mapBorderStyle((0x000000F0 & self::_GetInt4d($recordData, 10)) >> 4)) { + $objStyle->getBorders()->getRight()->setBorderStyle($bordersRightStyle); + } + // bit: 11-8; mask: 0x00000F00; top style + if ($bordersTopStyle = self::_mapBorderStyle((0x00000F00 & self::_GetInt4d($recordData, 10)) >> 8)) { + $objStyle->getBorders()->getTop()->setBorderStyle($bordersTopStyle); + } + // bit: 15-12; mask: 0x0000F000; bottom style + if ($bordersBottomStyle = self::_mapBorderStyle((0x0000F000 & self::_GetInt4d($recordData, 10)) >> 12)) { + $objStyle->getBorders()->getBottom()->setBorderStyle($bordersBottomStyle); + } + // bit: 22-16; mask: 0x007F0000; left color + $objStyle->getBorders()->getLeft()->colorIndex = (0x007F0000 & self::_GetInt4d($recordData, 10)) >> 16; + + // bit: 29-23; mask: 0x3F800000; right color + $objStyle->getBorders()->getRight()->colorIndex = (0x3F800000 & self::_GetInt4d($recordData, 10)) >> 23; + + // bit: 30; mask: 0x40000000; 1 = diagonal line from top left to right bottom + $diagonalDown = (0x40000000 & self::_GetInt4d($recordData, 10)) >> 30 ? + true : false; + + // bit: 31; mask: 0x80000000; 1 = diagonal line from bottom left to top right + $diagonalUp = (0x80000000 & self::_GetInt4d($recordData, 10)) >> 31 ? + true : false; + + if ($diagonalUp == false && $diagonalDown == false) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_NONE); + } elseif ($diagonalUp == true && $diagonalDown == false) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_UP); + } elseif ($diagonalUp == false && $diagonalDown == true) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_DOWN); + } elseif ($diagonalUp == true && $diagonalDown == true) { + $objStyle->getBorders()->setDiagonalDirection(PHPExcel_Style_Borders::DIAGONAL_BOTH); + } + + // offset: 14; size: 4; + // bit: 6-0; mask: 0x0000007F; top color + $objStyle->getBorders()->getTop()->colorIndex = (0x0000007F & self::_GetInt4d($recordData, 14)) >> 0; + + // bit: 13-7; mask: 0x00003F80; bottom color + $objStyle->getBorders()->getBottom()->colorIndex = (0x00003F80 & self::_GetInt4d($recordData, 14)) >> 7; + + // bit: 20-14; mask: 0x001FC000; diagonal color + $objStyle->getBorders()->getDiagonal()->colorIndex = (0x001FC000 & self::_GetInt4d($recordData, 14)) >> 14; + + // bit: 24-21; mask: 0x01E00000; diagonal style + if ($bordersDiagonalStyle = self::_mapBorderStyle((0x01E00000 & self::_GetInt4d($recordData, 14)) >> 21)) { + $objStyle->getBorders()->getDiagonal()->setBorderStyle($bordersDiagonalStyle); + } + + // bit: 31-26; mask: 0xFC000000 fill pattern + if ($fillType = self::_mapFillPattern((0xFC000000 & self::_GetInt4d($recordData, 14)) >> 26)) { + $objStyle->getFill()->setFillType($fillType); + } + // offset: 18; size: 2; pattern and background colour + // bit: 6-0; mask: 0x007F; color index for pattern color + $objStyle->getFill()->startcolorIndex = (0x007F & self::_GetInt2d($recordData, 18)) >> 0; + + // bit: 13-7; mask: 0x3F80; color index for pattern background + $objStyle->getFill()->endcolorIndex = (0x3F80 & self::_GetInt2d($recordData, 18)) >> 7; + } else { + // BIFF5 + + // offset: 7; size: 1; Text orientation and flags + $orientationAndFlags = ord($recordData{7}); + + // bit: 1-0; mask: 0x03; XF_ORIENTATION: Text orientation + $xfOrientation = (0x03 & $orientationAndFlags) >> 0; + switch ($xfOrientation) { + case 0: + $objStyle->getAlignment()->setTextRotation(0); + break; + case 1: + $objStyle->getAlignment()->setTextRotation(-165); + break; + case 2: + $objStyle->getAlignment()->setTextRotation(90); + break; + case 3: + $objStyle->getAlignment()->setTextRotation(-90); + break; + } + + // offset: 8; size: 4; cell border lines and background area + $borderAndBackground = self::_GetInt4d($recordData, 8); + + // bit: 6-0; mask: 0x0000007F; color index for pattern color + $objStyle->getFill()->startcolorIndex = (0x0000007F & $borderAndBackground) >> 0; + + // bit: 13-7; mask: 0x00003F80; color index for pattern background + $objStyle->getFill()->endcolorIndex = (0x00003F80 & $borderAndBackground) >> 7; + + // bit: 21-16; mask: 0x003F0000; fill pattern + $objStyle->getFill()->setFillType(self::_mapFillPattern((0x003F0000 & $borderAndBackground) >> 16)); + + // bit: 24-22; mask: 0x01C00000; bottom line style + $objStyle->getBorders()->getBottom()->setBorderStyle(self::_mapBorderStyle((0x01C00000 & $borderAndBackground) >> 22)); + + // bit: 31-25; mask: 0xFE000000; bottom line color + $objStyle->getBorders()->getBottom()->colorIndex = (0xFE000000 & $borderAndBackground) >> 25; + + // offset: 12; size: 4; cell border lines + $borderLines = self::_GetInt4d($recordData, 12); + + // bit: 2-0; mask: 0x00000007; top line style + $objStyle->getBorders()->getTop()->setBorderStyle(self::_mapBorderStyle((0x00000007 & $borderLines) >> 0)); + + // bit: 5-3; mask: 0x00000038; left line style + $objStyle->getBorders()->getLeft()->setBorderStyle(self::_mapBorderStyle((0x00000038 & $borderLines) >> 3)); + + // bit: 8-6; mask: 0x000001C0; right line style + $objStyle->getBorders()->getRight()->setBorderStyle(self::_mapBorderStyle((0x000001C0 & $borderLines) >> 6)); + + // bit: 15-9; mask: 0x0000FE00; top line color index + $objStyle->getBorders()->getTop()->colorIndex = (0x0000FE00 & $borderLines) >> 9; + + // bit: 22-16; mask: 0x007F0000; left line color index + $objStyle->getBorders()->getLeft()->colorIndex = (0x007F0000 & $borderLines) >> 16; + + // bit: 29-23; mask: 0x3F800000; right line color index + $objStyle->getBorders()->getRight()->colorIndex = (0x3F800000 & $borderLines) >> 23; + } + + // add cellStyleXf or cellXf and update mapping + if ($isCellStyleXf) { + // we only read one style XF record which is always the first + if ($this->_xfIndex == 0) { + $this->_phpExcel->addCellStyleXf($objStyle); + $this->_mapCellStyleXfIndex[$this->_xfIndex] = 0; + } + } else { + // we read all cell XF records + $this->_phpExcel->addCellXf($objStyle); + $this->_mapCellXfIndex[$this->_xfIndex] = count($this->_phpExcel->getCellXfCollection()) - 1; + } + + // update XF index for when we read next record + ++$this->_xfIndex; + } + } + + + /** + * + */ + private function _readXfExt() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; 0x087D = repeated header + + // offset: 2; size: 2 + + // offset: 4; size: 8; not used + + // offset: 12; size: 2; record version + + // offset: 14; size: 2; index to XF record which this record modifies + $ixfe = self::_GetInt2d($recordData, 14); + + // offset: 16; size: 2; not used + + // offset: 18; size: 2; number of extension properties that follow + $cexts = self::_GetInt2d($recordData, 18); + + // start reading the actual extension data + $offset = 20; + while ($offset < $length) { + // extension type + $extType = self::_GetInt2d($recordData, $offset); + + // extension length + $cb = self::_GetInt2d($recordData, $offset + 2); + + // extension data + $extData = substr($recordData, $offset + 4, $cb); + + switch ($extType) { + case 4: // fill start color + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $fill = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFill(); + $fill->getStartColor()->setRGB($rgb); + unset($fill->startcolorIndex); // normal color index does not apply, discard + } + } + break; + + case 5: // fill end color + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $fill = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFill(); + $fill->getEndColor()->setRGB($rgb); + unset($fill->endcolorIndex); // normal color index does not apply, discard + } + } + break; + + case 7: // border color top + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $top = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getTop(); + $top->getColor()->setRGB($rgb); + unset($top->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 8: // border color bottom + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $bottom = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getBottom(); + $bottom->getColor()->setRGB($rgb); + unset($bottom->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 9: // border color left + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $left = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getLeft(); + $left->getColor()->setRGB($rgb); + unset($left->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 10: // border color right + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $right = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getRight(); + $right->getColor()->setRGB($rgb); + unset($right->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 11: // border color diagonal + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $diagonal = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getBorders()->getDiagonal(); + $diagonal->getColor()->setRGB($rgb); + unset($diagonal->colorIndex); // normal color index does not apply, discard + } + } + break; + + case 13: // font color + $xclfType = self::_GetInt2d($extData, 0); // color type + $xclrValue = substr($extData, 4, 4); // color value (value based on color type) + + if ($xclfType == 2) { + $rgb = sprintf('%02X%02X%02X', ord($xclrValue{0}), ord($xclrValue{1}), ord($xclrValue{2})); + + // modify the relevant style property + if ( isset($this->_mapCellXfIndex[$ixfe]) ) { + $font = $this->_phpExcel->getCellXfByIndex($this->_mapCellXfIndex[$ixfe])->getFont(); + $font->getColor()->setRGB($rgb); + unset($font->colorIndex); // normal color index does not apply, discard + } + } + break; + } + + $offset += $cb; + } + } + + } + + + /** + * Read STYLE record + */ + private function _readStyle() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; index to XF record and flag for built-in style + $ixfe = self::_GetInt2d($recordData, 0); + + // bit: 11-0; mask 0x0FFF; index to XF record + $xfIndex = (0x0FFF & $ixfe) >> 0; + + // bit: 15; mask 0x8000; 0 = user-defined style, 1 = built-in style + $isBuiltIn = (bool) ((0x8000 & $ixfe) >> 15); + + if ($isBuiltIn) { + // offset: 2; size: 1; identifier for built-in style + $builtInId = ord($recordData{2}); + + switch ($builtInId) { + case 0x00: + // currently, we are not using this for anything + break; + + default: + break; + } + + } else { + // user-defined; not supported by PHPExcel + } + } + } + + + /** + * Read PALETTE record + */ + private function _readPalette() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; number of following colors + $nm = self::_GetInt2d($recordData, 0); + + // list of RGB colors + for ($i = 0; $i < $nm; ++$i) { + $rgb = substr($recordData, 2 + 4 * $i, 4); + $this->_palette[] = self::_readRGB($rgb); + } + } + } + + + /** + * SHEET + * + * This record is located in the Workbook Globals + * Substream and represents a sheet inside the workbook. + * One SHEET record is written for each sheet. It stores the + * sheet name and a stream offset to the BOF record of the + * respective Sheet Substream within the Workbook Stream. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readSheet() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 4; absolute stream position of the BOF record of the sheet + $rec_offset = self::_GetInt4d($recordData, 0); + + // offset: 4; size: 1; sheet state + switch (ord($recordData{4})) { + case 0x00: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; + case 0x01: $sheetState = PHPExcel_Worksheet::SHEETSTATE_HIDDEN; break; + case 0x02: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VERYHIDDEN; break; + default: $sheetState = PHPExcel_Worksheet::SHEETSTATE_VISIBLE; break; + } + + // offset: 5; size: 1; sheet type + $sheetType = ord($recordData{5}); + + // offset: 6; size: var; sheet name + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringShort(substr($recordData, 6)); + $rec_name = $string['value']; + } elseif ($this->_version == self::XLS_BIFF7) { + $string = $this->_readByteStringShort(substr($recordData, 6)); + $rec_name = $string['value']; + } + + $this->_sheets[] = array( + 'name' => $rec_name, + 'offset' => $rec_offset, + 'sheetState' => $sheetState, + 'sheetType' => $sheetType, + ); + } + + + /** + * Read EXTERNALBOOK record + */ + private function _readExternalBook() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset within record data + $offset = 0; + + // there are 4 types of records + if (strlen($recordData) > 4) { + // external reference + // offset: 0; size: 2; number of sheet names ($nm) + $nm = self::_GetInt2d($recordData, 0); + $offset += 2; + + // offset: 2; size: var; encoded URL without sheet name (Unicode string, 16-bit length) + $encodedUrlString = self::_readUnicodeStringLong(substr($recordData, 2)); + $offset += $encodedUrlString['size']; + + // offset: var; size: var; list of $nm sheet names (Unicode strings, 16-bit length) + $externalSheetNames = array(); + for ($i = 0; $i < $nm; ++$i) { + $externalSheetNameString = self::_readUnicodeStringLong(substr($recordData, $offset)); + $externalSheetNames[] = $externalSheetNameString['value']; + $offset += $externalSheetNameString['size']; + } + + // store the record data + $this->_externalBooks[] = array( + 'type' => 'external', + 'encodedUrl' => $encodedUrlString['value'], + 'externalSheetNames' => $externalSheetNames, + ); + + } elseif (substr($recordData, 2, 2) == pack('CC', 0x01, 0x04)) { + // internal reference + // offset: 0; size: 2; number of sheet in this document + // offset: 2; size: 2; 0x01 0x04 + $this->_externalBooks[] = array( + 'type' => 'internal', + ); + } elseif (substr($recordData, 0, 4) == pack('vCC', 0x0001, 0x01, 0x3A)) { + // add-in function + // offset: 0; size: 2; 0x0001 + $this->_externalBooks[] = array( + 'type' => 'addInFunction', + ); + } elseif (substr($recordData, 0, 2) == pack('v', 0x0000)) { + // DDE links, OLE links + // offset: 0; size: 2; 0x0000 + // offset: 2; size: var; encoded source document name + $this->_externalBooks[] = array( + 'type' => 'DDEorOLE', + ); + } + } + + + /** + * Read EXTERNNAME record. + */ + private function _readExternName() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // external sheet references provided for named cells + if ($this->_version == self::XLS_BIFF8) { + // offset: 0; size: 2; options + $options = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; + + // offset: 4; size: 2; not used + + // offset: 6; size: var + $nameString = self::_readUnicodeStringShort(substr($recordData, 6)); + + // offset: var; size: var; formula data + $offset = 6 + $nameString['size']; + $formula = $this->_getFormulaFromStructure(substr($recordData, $offset)); + + $this->_externalNames[] = array( + 'name' => $nameString['value'], + 'formula' => $formula, + ); + } + } + + + /** + * Read EXTERNSHEET record + */ + private function _readExternSheet() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // external sheet references provided for named cells + if ($this->_version == self::XLS_BIFF8) { + // offset: 0; size: 2; number of following ref structures + $nm = self::_GetInt2d($recordData, 0); + for ($i = 0; $i < $nm; ++$i) { + $this->_ref[] = array( + // offset: 2 + 6 * $i; index to EXTERNALBOOK record + 'externalBookIndex' => self::_GetInt2d($recordData, 2 + 6 * $i), + // offset: 4 + 6 * $i; index to first sheet in EXTERNALBOOK record + 'firstSheetIndex' => self::_GetInt2d($recordData, 4 + 6 * $i), + // offset: 6 + 6 * $i; index to last sheet in EXTERNALBOOK record + 'lastSheetIndex' => self::_GetInt2d($recordData, 6 + 6 * $i), + ); + } + } + } + + + /** + * DEFINEDNAME + * + * This record is part of a Link Table. It contains the name + * and the token array of an internal defined name. Token + * arrays of defined names contain tokens with aberrant + * token classes. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readDefinedName() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8) { + // retrieves named cells + + // offset: 0; size: 2; option flags + $opts = self::_GetInt2d($recordData, 0); + + // bit: 5; mask: 0x0020; 0 = user-defined name, 1 = built-in-name + $isBuiltInName = (0x0020 & $opts) >> 5; + + // offset: 2; size: 1; keyboard shortcut + + // offset: 3; size: 1; length of the name (character count) + $nlen = ord($recordData{3}); + + // offset: 4; size: 2; size of the formula data (it can happen that this is zero) + // note: there can also be additional data, this is not included in $flen + $flen = self::_GetInt2d($recordData, 4); + + // offset: 8; size: 2; 0=Global name, otherwise index to sheet (1-based) + $scope = self::_GetInt2d($recordData, 8); + + // offset: 14; size: var; Name (Unicode string without length field) + $string = self::_readUnicodeString(substr($recordData, 14), $nlen); + + // offset: var; size: $flen; formula data + $offset = 14 + $string['size']; + $formulaStructure = pack('v', $flen) . substr($recordData, $offset); + + try { + $formula = $this->_getFormulaFromStructure($formulaStructure); + } catch (PHPExcel_Exception $e) { + $formula = ''; + } + + $this->_definedname[] = array( + 'isBuiltInName' => $isBuiltInName, + 'name' => $string['value'], + 'formula' => $formula, + 'scope' => $scope, + ); + } + } + + + /** + * Read MSODRAWINGGROUP record + */ + private function _readMsoDrawingGroup() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + + // get spliced record data + $splicedRecordData = $this->_getSplicedRecordData(); + $recordData = $splicedRecordData['recordData']; + + $this->_drawingGroupData .= $recordData; + } + + + /** + * SST - Shared String Table + * + * This record contains a list of all strings used anywhere + * in the workbook. Each string occurs only once. The + * workbook uses indexes into the list to reference the + * strings. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + **/ + private function _readSst() + { + // offset within (spliced) record data + $pos = 0; + + // get spliced record data + $splicedRecordData = $this->_getSplicedRecordData(); + + $recordData = $splicedRecordData['recordData']; + $spliceOffsets = $splicedRecordData['spliceOffsets']; + + // offset: 0; size: 4; total number of strings in the workbook + $pos += 4; + + // offset: 4; size: 4; number of following strings ($nm) + $nm = self::_GetInt4d($recordData, 4); + $pos += 4; + + // loop through the Unicode strings (16-bit length) + for ($i = 0; $i < $nm; ++$i) { + + // number of characters in the Unicode string + $numChars = self::_GetInt2d($recordData, $pos); + $pos += 2; + + // option flags + $optionFlags = ord($recordData{$pos}); + ++$pos; + + // bit: 0; mask: 0x01; 0 = compressed; 1 = uncompressed + $isCompressed = (($optionFlags & 0x01) == 0) ; + + // bit: 2; mask: 0x02; 0 = ordinary; 1 = Asian phonetic + $hasAsian = (($optionFlags & 0x04) != 0); + + // bit: 3; mask: 0x03; 0 = ordinary; 1 = Rich-Text + $hasRichText = (($optionFlags & 0x08) != 0); + + if ($hasRichText) { + // number of Rich-Text formatting runs + $formattingRuns = self::_GetInt2d($recordData, $pos); + $pos += 2; + } + + if ($hasAsian) { + // size of Asian phonetic setting + $extendedRunLength = self::_GetInt4d($recordData, $pos); + $pos += 4; + } + + // expected byte length of character array if not split + $len = ($isCompressed) ? $numChars : $numChars * 2; + + // look up limit position + foreach ($spliceOffsets as $spliceOffset) { + // it can happen that the string is empty, therefore we need + // <= and not just < + if ($pos <= $spliceOffset) { + $limitpos = $spliceOffset; + break; + } + } + + if ($pos + $len <= $limitpos) { + // character array is not split between records + + $retstr = substr($recordData, $pos, $len); + $pos += $len; + + } else { + // character array is split between records + + // first part of character array + $retstr = substr($recordData, $pos, $limitpos - $pos); + + $bytesRead = $limitpos - $pos; + + // remaining characters in Unicode string + $charsLeft = $numChars - (($isCompressed) ? $bytesRead : ($bytesRead / 2)); + + $pos = $limitpos; + + // keep reading the characters + while ($charsLeft > 0) { + + // look up next limit position, in case the string span more than one continue record + foreach ($spliceOffsets as $spliceOffset) { + if ($pos < $spliceOffset) { + $limitpos = $spliceOffset; + break; + } + } + + // repeated option flags + // OpenOffice.org documentation 5.21 + $option = ord($recordData{$pos}); + ++$pos; + + if ($isCompressed && ($option == 0)) { + // 1st fragment compressed + // this fragment compressed + $len = min($charsLeft, $limitpos - $pos); + $retstr .= substr($recordData, $pos, $len); + $charsLeft -= $len; + $isCompressed = true; + + } elseif (!$isCompressed && ($option != 0)) { + // 1st fragment uncompressed + // this fragment uncompressed + $len = min($charsLeft * 2, $limitpos - $pos); + $retstr .= substr($recordData, $pos, $len); + $charsLeft -= $len / 2; + $isCompressed = false; + + } elseif (!$isCompressed && ($option == 0)) { + // 1st fragment uncompressed + // this fragment compressed + $len = min($charsLeft, $limitpos - $pos); + for ($j = 0; $j < $len; ++$j) { + $retstr .= $recordData{$pos + $j} . chr(0); + } + $charsLeft -= $len; + $isCompressed = false; + + } else { + // 1st fragment compressed + // this fragment uncompressed + $newstr = ''; + for ($j = 0; $j < strlen($retstr); ++$j) { + $newstr .= $retstr[$j] . chr(0); + } + $retstr = $newstr; + $len = min($charsLeft * 2, $limitpos - $pos); + $retstr .= substr($recordData, $pos, $len); + $charsLeft -= $len / 2; + $isCompressed = false; + } + + $pos += $len; + } + } + + // convert to UTF-8 + $retstr = self::_encodeUTF16($retstr, $isCompressed); + + // read additional Rich-Text information, if any + $fmtRuns = array(); + if ($hasRichText) { + // list of formatting runs + for ($j = 0; $j < $formattingRuns; ++$j) { + // first formatted character; zero-based + $charPos = self::_GetInt2d($recordData, $pos + $j * 4); + + // index to font record + $fontIndex = self::_GetInt2d($recordData, $pos + 2 + $j * 4); + + $fmtRuns[] = array( + 'charPos' => $charPos, + 'fontIndex' => $fontIndex, + ); + } + $pos += 4 * $formattingRuns; + } + + // read additional Asian phonetics information, if any + if ($hasAsian) { + // For Asian phonetic settings, we skip the extended string data + $pos += $extendedRunLength; + } + + // store the shared sting + $this->_sst[] = array( + 'value' => $retstr, + 'fmtRuns' => $fmtRuns, + ); + } + + // _getSplicedRecordData() takes care of moving current position in data stream + } + + + /** + * Read PRINTGRIDLINES record + */ + private function _readPrintGridlines() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { + // offset: 0; size: 2; 0 = do not print sheet grid lines; 1 = print sheet gridlines + $printGridlines = (bool) self::_GetInt2d($recordData, 0); + $this->_phpSheet->setPrintGridlines($printGridlines); + } + } + + + /** + * Read DEFAULTROWHEIGHT record + */ + private function _readDefaultRowHeight() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; option flags + // offset: 2; size: 2; default height for unused rows, (twips 1/20 point) + $height = self::_GetInt2d($recordData, 2); + $this->_phpSheet->getDefaultRowDimension()->setRowHeight($height / 20); + } + + + /** + * Read SHEETPR record + */ + private function _readSheetPr() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2 + + // bit: 6; mask: 0x0040; 0 = outline buttons above outline group + $isSummaryBelow = (0x0040 & self::_GetInt2d($recordData, 0)) >> 6; + $this->_phpSheet->setShowSummaryBelow($isSummaryBelow); + + // bit: 7; mask: 0x0080; 0 = outline buttons left of outline group + $isSummaryRight = (0x0080 & self::_GetInt2d($recordData, 0)) >> 7; + $this->_phpSheet->setShowSummaryRight($isSummaryRight); + + // bit: 8; mask: 0x100; 0 = scale printout in percent, 1 = fit printout to number of pages + // this corresponds to radio button setting in page setup dialog in Excel + $this->_isFitToPages = (bool) ((0x0100 & self::_GetInt2d($recordData, 0)) >> 8); + } + + + /** + * Read HORIZONTALPAGEBREAKS record + */ + private function _readHorizontalPageBreaks() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { + + // offset: 0; size: 2; number of the following row index structures + $nm = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 6 * $nm; list of $nm row index structures + for ($i = 0; $i < $nm; ++$i) { + $r = self::_GetInt2d($recordData, 2 + 6 * $i); + $cf = self::_GetInt2d($recordData, 2 + 6 * $i + 2); + $cl = self::_GetInt2d($recordData, 2 + 6 * $i + 4); + + // not sure why two column indexes are necessary? + $this->_phpSheet->setBreakByColumnAndRow($cf, $r, PHPExcel_Worksheet::BREAK_ROW); + } + } + } + + + /** + * Read VERTICALPAGEBREAKS record + */ + private function _readVerticalPageBreaks() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { + // offset: 0; size: 2; number of the following column index structures + $nm = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 6 * $nm; list of $nm row index structures + for ($i = 0; $i < $nm; ++$i) { + $c = self::_GetInt2d($recordData, 2 + 6 * $i); + $rf = self::_GetInt2d($recordData, 2 + 6 * $i + 2); + $rl = self::_GetInt2d($recordData, 2 + 6 * $i + 4); + + // not sure why two row indexes are necessary? + $this->_phpSheet->setBreakByColumnAndRow($c, $rf, PHPExcel_Worksheet::BREAK_COLUMN); + } + } + } + + + /** + * Read HEADER record + */ + private function _readHeader() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: var + // realized that $recordData can be empty even when record exists + if ($recordData) { + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringLong($recordData); + } else { + $string = $this->_readByteStringShort($recordData); + } + + $this->_phpSheet->getHeaderFooter()->setOddHeader($string['value']); + $this->_phpSheet->getHeaderFooter()->setEvenHeader($string['value']); + } + } + } + + + /** + * Read FOOTER record + */ + private function _readFooter() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: var + // realized that $recordData can be empty even when record exists + if ($recordData) { + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringLong($recordData); + } else { + $string = $this->_readByteStringShort($recordData); + } + $this->_phpSheet->getHeaderFooter()->setOddFooter($string['value']); + $this->_phpSheet->getHeaderFooter()->setEvenFooter($string['value']); + } + } + } + + + /** + * Read HCENTER record + */ + private function _readHcenter() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; 0 = print sheet left aligned, 1 = print sheet centered horizontally + $isHorizontalCentered = (bool) self::_GetInt2d($recordData, 0); + + $this->_phpSheet->getPageSetup()->setHorizontalCentered($isHorizontalCentered); + } + } + + + /** + * Read VCENTER record + */ + private function _readVcenter() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; 0 = print sheet aligned at top page border, 1 = print sheet vertically centered + $isVerticalCentered = (bool) self::_GetInt2d($recordData, 0); + + $this->_phpSheet->getPageSetup()->setVerticalCentered($isVerticalCentered); + } + } + + + /** + * Read LEFTMARGIN record + */ + private function _readLeftMargin() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 8 + $this->_phpSheet->getPageMargins()->setLeft(self::_extractNumber($recordData)); + } + } + + + /** + * Read RIGHTMARGIN record + */ + private function _readRightMargin() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 8 + $this->_phpSheet->getPageMargins()->setRight(self::_extractNumber($recordData)); + } + } + + + /** + * Read TOPMARGIN record + */ + private function _readTopMargin() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 8 + $this->_phpSheet->getPageMargins()->setTop(self::_extractNumber($recordData)); + } + } + + + /** + * Read BOTTOMMARGIN record + */ + private function _readBottomMargin() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 8 + $this->_phpSheet->getPageMargins()->setBottom(self::_extractNumber($recordData)); + } + } + + + /** + * Read PAGESETUP record + */ + private function _readPageSetup() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; paper size + $paperSize = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; scaling factor + $scale = self::_GetInt2d($recordData, 2); + + // offset: 6; size: 2; fit worksheet width to this number of pages, 0 = use as many as needed + $fitToWidth = self::_GetInt2d($recordData, 6); + + // offset: 8; size: 2; fit worksheet height to this number of pages, 0 = use as many as needed + $fitToHeight = self::_GetInt2d($recordData, 8); + + // offset: 10; size: 2; option flags + + // bit: 1; mask: 0x0002; 0=landscape, 1=portrait + $isPortrait = (0x0002 & self::_GetInt2d($recordData, 10)) >> 1; + + // bit: 2; mask: 0x0004; 1= paper size, scaling factor, paper orient. not init + // when this bit is set, do not use flags for those properties + $isNotInit = (0x0004 & self::_GetInt2d($recordData, 10)) >> 2; + + if (!$isNotInit) { + $this->_phpSheet->getPageSetup()->setPaperSize($paperSize); + switch ($isPortrait) { + case 0: $this->_phpSheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE); break; + case 1: $this->_phpSheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT); break; + } + + $this->_phpSheet->getPageSetup()->setScale($scale, false); + $this->_phpSheet->getPageSetup()->setFitToPage((bool) $this->_isFitToPages); + $this->_phpSheet->getPageSetup()->setFitToWidth($fitToWidth, false); + $this->_phpSheet->getPageSetup()->setFitToHeight($fitToHeight, false); + } + + // offset: 16; size: 8; header margin (IEEE 754 floating-point value) + $marginHeader = self::_extractNumber(substr($recordData, 16, 8)); + $this->_phpSheet->getPageMargins()->setHeader($marginHeader); + + // offset: 24; size: 8; footer margin (IEEE 754 floating-point value) + $marginFooter = self::_extractNumber(substr($recordData, 24, 8)); + $this->_phpSheet->getPageMargins()->setFooter($marginFooter); + } + } + + + /** + * PROTECT - Sheet protection (BIFF2 through BIFF8) + * if this record is omitted, then it also means no sheet protection + */ + private function _readProtect() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; + + // bit 0, mask 0x01; 1 = sheet is protected + $bool = (0x01 & self::_GetInt2d($recordData, 0)) >> 0; + $this->_phpSheet->getProtection()->setSheet((bool)$bool); + } + + + /** + * SCENPROTECT + */ + private function _readScenProtect() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; + + // bit: 0, mask 0x01; 1 = scenarios are protected + $bool = (0x01 & self::_GetInt2d($recordData, 0)) >> 0; + + $this->_phpSheet->getProtection()->setScenarios((bool)$bool); + } + + + /** + * OBJECTPROTECT + */ + private function _readObjectProtect() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; + + // bit: 0, mask 0x01; 1 = objects are protected + $bool = (0x01 & self::_GetInt2d($recordData, 0)) >> 0; + + $this->_phpSheet->getProtection()->setObjects((bool)$bool); + } + + + /** + * PASSWORD - Sheet protection (hashed) password (BIFF2 through BIFF8) + */ + private function _readPassword() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; 16-bit hash value of password + $password = strtoupper(dechex(self::_GetInt2d($recordData, 0))); // the hashed password + $this->_phpSheet->getProtection()->setPassword($password, true); + } + } + + + /** + * Read DEFCOLWIDTH record + */ + private function _readDefColWidth() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; default column width + $width = self::_GetInt2d($recordData, 0); + if ($width != 8) { + $this->_phpSheet->getDefaultColumnDimension()->setWidth($width); + } + } + + + /** + * Read COLINFO record + */ + private function _readColInfo() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; index to first column in range + $fc = self::_GetInt2d($recordData, 0); // first column index + + // offset: 2; size: 2; index to last column in range + $lc = self::_GetInt2d($recordData, 2); // first column index + + // offset: 4; size: 2; width of the column in 1/256 of the width of the zero character + $width = self::_GetInt2d($recordData, 4); + + // offset: 6; size: 2; index to XF record for default column formatting + $xfIndex = self::_GetInt2d($recordData, 6); + + // offset: 8; size: 2; option flags + + // bit: 0; mask: 0x0001; 1= columns are hidden + $isHidden = (0x0001 & self::_GetInt2d($recordData, 8)) >> 0; + + // bit: 10-8; mask: 0x0700; outline level of the columns (0 = no outline) + $level = (0x0700 & self::_GetInt2d($recordData, 8)) >> 8; + + // bit: 12; mask: 0x1000; 1 = collapsed + $isCollapsed = (0x1000 & self::_GetInt2d($recordData, 8)) >> 12; + + // offset: 10; size: 2; not used + + for ($i = $fc; $i <= $lc; ++$i) { + if ($lc == 255 || $lc == 256) { + $this->_phpSheet->getDefaultColumnDimension()->setWidth($width / 256); + break; + } + $this->_phpSheet->getColumnDimensionByColumn($i)->setWidth($width / 256); + $this->_phpSheet->getColumnDimensionByColumn($i)->setVisible(!$isHidden); + $this->_phpSheet->getColumnDimensionByColumn($i)->setOutlineLevel($level); + $this->_phpSheet->getColumnDimensionByColumn($i)->setCollapsed($isCollapsed); + $this->_phpSheet->getColumnDimensionByColumn($i)->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } + + + /** + * ROW + * + * This record contains the properties of a single row in a + * sheet. Rows and cells in a sheet are divided into blocks + * of 32 rows. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readRow() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; index of this row + $r = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to column of the first cell which is described by a cell record + + // offset: 4; size: 2; index to column of the last cell which is described by a cell record, increased by 1 + + // offset: 6; size: 2; + + // bit: 14-0; mask: 0x7FFF; height of the row, in twips = 1/20 of a point + $height = (0x7FFF & self::_GetInt2d($recordData, 6)) >> 0; + + // bit: 15: mask: 0x8000; 0 = row has custom height; 1= row has default height + $useDefaultHeight = (0x8000 & self::_GetInt2d($recordData, 6)) >> 15; + + if (!$useDefaultHeight) { + $this->_phpSheet->getRowDimension($r + 1)->setRowHeight($height / 20); + } + + // offset: 8; size: 2; not used + + // offset: 10; size: 2; not used in BIFF5-BIFF8 + + // offset: 12; size: 4; option flags and default row formatting + + // bit: 2-0: mask: 0x00000007; outline level of the row + $level = (0x00000007 & self::_GetInt4d($recordData, 12)) >> 0; + $this->_phpSheet->getRowDimension($r + 1)->setOutlineLevel($level); + + // bit: 4; mask: 0x00000010; 1 = outline group start or ends here... and is collapsed + $isCollapsed = (0x00000010 & self::_GetInt4d($recordData, 12)) >> 4; + $this->_phpSheet->getRowDimension($r + 1)->setCollapsed($isCollapsed); + + // bit: 5; mask: 0x00000020; 1 = row is hidden + $isHidden = (0x00000020 & self::_GetInt4d($recordData, 12)) >> 5; + $this->_phpSheet->getRowDimension($r + 1)->setVisible(!$isHidden); + + // bit: 7; mask: 0x00000080; 1 = row has explicit format + $hasExplicitFormat = (0x00000080 & self::_GetInt4d($recordData, 12)) >> 7; + + // bit: 27-16; mask: 0x0FFF0000; only applies when hasExplicitFormat = 1; index to XF record + $xfIndex = (0x0FFF0000 & self::_GetInt4d($recordData, 12)) >> 16; + + if ($hasExplicitFormat) { + $this->_phpSheet->getRowDimension($r + 1)->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } + + + /** + * Read RK record + * This record represents a cell that contains an RK value + * (encoded integer or floating-point value). If a + * floating-point value cannot be encoded to an RK value, + * a NUMBER record will be written. This record replaces the + * record INTEGER written in BIFF2. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readRk() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to column + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset: 4; size: 2; index to XF record + $xfIndex = self::_GetInt2d($recordData, 4); + + // offset: 6; size: 4; RK value + $rknum = self::_GetInt4d($recordData, 6); + $numValue = self::_GetIEEE754($rknum); + + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + if (!$this->_readDataOnly) { + // add style information + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + + // add cell + $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); + } + } + + + /** + * Read LABELSST record + * This record represents a cell that contains a string. It + * replaces the LABEL record and RSTRING record used in + * BIFF2-BIFF5. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readLabelSst() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to column + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset: 4; size: 2; index to XF record + $xfIndex = self::_GetInt2d($recordData, 4); + + // offset: 6; size: 4; index to SST record + $index = self::_GetInt4d($recordData, 6); + + // add cell + if (($fmtRuns = $this->_sst[$index]['fmtRuns']) && !$this->_readDataOnly) { + // then we should treat as rich text + $richText = new PHPExcel_RichText(); + $charPos = 0; + $sstCount = count($this->_sst[$index]['fmtRuns']); + for ($i = 0; $i <= $sstCount; ++$i) { + if (isset($fmtRuns[$i])) { + $text = PHPExcel_Shared_String::Substring($this->_sst[$index]['value'], $charPos, $fmtRuns[$i]['charPos'] - $charPos); + $charPos = $fmtRuns[$i]['charPos']; + } else { + $text = PHPExcel_Shared_String::Substring($this->_sst[$index]['value'], $charPos, PHPExcel_Shared_String::CountCharacters($this->_sst[$index]['value'])); + } + + if (PHPExcel_Shared_String::CountCharacters($text) > 0) { + if ($i == 0) { // first text run, no style + $richText->createText($text); + } else { + $textRun = $richText->createTextRun($text); + if (isset($fmtRuns[$i - 1])) { + if ($fmtRuns[$i - 1]['fontIndex'] < 4) { + $fontIndex = $fmtRuns[$i - 1]['fontIndex']; + } else { + // this has to do with that index 4 is omitted in all BIFF versions for some strange reason + // check the OpenOffice documentation of the FONT record + $fontIndex = $fmtRuns[$i - 1]['fontIndex'] - 1; + } + $textRun->setFont(clone $this->_objFonts[$fontIndex]); + } + } + } + } + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + $cell->setValueExplicit($richText, PHPExcel_Cell_DataType::TYPE_STRING); + } else { + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + $cell->setValueExplicit($this->_sst[$index]['value'], PHPExcel_Cell_DataType::TYPE_STRING); + } + + if (!$this->_readDataOnly) { + // add style information + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } + + + /** + * Read MULRK record + * This record represents a cell range containing RK value + * cells. All cells are located in the same row. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readMulRk() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to first column + $colFirst = self::_GetInt2d($recordData, 2); + + // offset: var; size: 2; index to last column + $colLast = self::_GetInt2d($recordData, $length - 2); + $columns = $colLast - $colFirst + 1; + + // offset within record data + $offset = 4; + + for ($i = 0; $i < $columns; ++$i) { + $columnString = PHPExcel_Cell::stringFromColumnIndex($colFirst + $i); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + + // offset: var; size: 2; index to XF record + $xfIndex = self::_GetInt2d($recordData, $offset); + + // offset: var; size: 4; RK value + $numValue = self::_GetIEEE754(self::_GetInt4d($recordData, $offset + 2)); + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + if (!$this->_readDataOnly) { + // add style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + + // add cell value + $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); + } + + $offset += 6; + } + } + + + /** + * Read NUMBER record + * This record represents a cell that contains a + * floating-point value. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readNumber() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size 2; index to column + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset 4; size: 2; index to XF record + $xfIndex = self::_GetInt2d($recordData, 4); + + $numValue = self::_extractNumber(substr($recordData, 6, 8)); + + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + if (!$this->_readDataOnly) { + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + + // add cell value + $cell->setValueExplicit($numValue, PHPExcel_Cell_DataType::TYPE_NUMERIC); + } + } + + + /** + * Read FORMULA record + perhaps a following STRING record if formula result is a string + * This record contains the token array and the result of a + * formula cell. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readFormula() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; row index + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; col index + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // offset: 20: size: variable; formula structure + $formulaStructure = substr($recordData, 20); + + // offset: 14: size: 2; option flags, recalculate always, recalculate on open etc. + $options = self::_GetInt2d($recordData, 14); + + // bit: 0; mask: 0x0001; 1 = recalculate always + // bit: 1; mask: 0x0002; 1 = calculate on open + // bit: 2; mask: 0x0008; 1 = part of a shared formula + $isPartOfSharedFormula = (bool) (0x0008 & $options); + + // WARNING: + // We can apparently not rely on $isPartOfSharedFormula. Even when $isPartOfSharedFormula = true + // the formula data may be ordinary formula data, therefore we need to check + // explicitly for the tExp token (0x01) + $isPartOfSharedFormula = $isPartOfSharedFormula && ord($formulaStructure{2}) == 0x01; + + if ($isPartOfSharedFormula) { + // part of shared formula which means there will be a formula with a tExp token and nothing else + // get the base cell, grab tExp token + $baseRow = self::_GetInt2d($formulaStructure, 3); + $baseCol = self::_GetInt2d($formulaStructure, 5); + $this->_baseCell = PHPExcel_Cell::stringFromColumnIndex($baseCol). ($baseRow + 1); + } + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + + if ($isPartOfSharedFormula) { + // formula is added to this cell after the sheet has been read + $this->_sharedFormulaParts[$columnString . ($row + 1)] = $this->_baseCell; + } + + // offset: 16: size: 4; not used + + // offset: 4; size: 2; XF index + $xfIndex = self::_GetInt2d($recordData, 4); + + // offset: 6; size: 8; result of the formula + if ( (ord($recordData{6}) == 0) + && (ord($recordData{12}) == 255) + && (ord($recordData{13}) == 255) ) { + + // String formula. Result follows in appended STRING record + $dataType = PHPExcel_Cell_DataType::TYPE_STRING; + + // read possible SHAREDFMLA record + $code = self::_GetInt2d($this->_data, $this->_pos); + if ($code == self::XLS_Type_SHAREDFMLA) { + $this->_readSharedFmla(); + } + + // read STRING record + $value = $this->_readString(); + + } elseif ((ord($recordData{6}) == 1) + && (ord($recordData{12}) == 255) + && (ord($recordData{13}) == 255)) { + + // Boolean formula. Result is in +2; 0=false, 1=true + $dataType = PHPExcel_Cell_DataType::TYPE_BOOL; + $value = (bool) ord($recordData{8}); + + } elseif ((ord($recordData{6}) == 2) + && (ord($recordData{12}) == 255) + && (ord($recordData{13}) == 255)) { + + // Error formula. Error code is in +2 + $dataType = PHPExcel_Cell_DataType::TYPE_ERROR; + $value = self::_mapErrorCode(ord($recordData{8})); + + } elseif ((ord($recordData{6}) == 3) + && (ord($recordData{12}) == 255) + && (ord($recordData{13}) == 255)) { + + // Formula result is a null string + $dataType = PHPExcel_Cell_DataType::TYPE_NULL; + $value = ''; + + } else { + + // forumla result is a number, first 14 bytes like _NUMBER record + $dataType = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $value = self::_extractNumber(substr($recordData, 6, 8)); + + } + + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + if (!$this->_readDataOnly) { + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + + // store the formula + if (!$isPartOfSharedFormula) { + // not part of shared formula + // add cell value. If we can read formula, populate with formula, otherwise just used cached value + try { + if ($this->_version != self::XLS_BIFF8) { + throw new PHPExcel_Reader_Exception('Not BIFF8. Can only read BIFF8 formulas'); + } + $formula = $this->_getFormulaFromStructure($formulaStructure); // get formula in human language + $cell->setValueExplicit('=' . $formula, PHPExcel_Cell_DataType::TYPE_FORMULA); + + } catch (PHPExcel_Exception $e) { + $cell->setValueExplicit($value, $dataType); + } + } else { + if ($this->_version == self::XLS_BIFF8) { + // do nothing at this point, formula id added later in the code + } else { + $cell->setValueExplicit($value, $dataType); + } + } + + // store the cached calculated value + $cell->setCalculatedValue($value); + } + } + + + /** + * Read a SHAREDFMLA record. This function just stores the binary shared formula in the reader, + * which usually contains relative references. + * These will be used to construct the formula in each shared formula part after the sheet is read. + */ + private function _readSharedFmla() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0, size: 6; cell range address of the area used by the shared formula, not used for anything + $cellRange = substr($recordData, 0, 6); + $cellRange = $this->_readBIFF5CellRangeAddressFixed($cellRange); // note: even BIFF8 uses BIFF5 syntax + + // offset: 6, size: 1; not used + + // offset: 7, size: 1; number of existing FORMULA records for this shared formula + $no = ord($recordData{7}); + + // offset: 8, size: var; Binary token array of the shared formula + $formula = substr($recordData, 8); + + // at this point we only store the shared formula for later use + $this->_sharedFormulas[$this->_baseCell] = $formula; + + } + + + /** + * Read a STRING record from current stream position and advance the stream pointer to next record + * This record is used for storing result from FORMULA record when it is a string, and + * it occurs directly after the FORMULA record + * + * @return string The string contents as UTF-8 + */ + private function _readString() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringLong($recordData); + $value = $string['value']; + } else { + $string = $this->_readByteStringLong($recordData); + $value = $string['value']; + } + + return $value; + } + + + /** + * Read BOOLERR record + * This record represents a Boolean value or error value + * cell. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readBoolErr() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; row index + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; column index + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset: 4; size: 2; index to XF record + $xfIndex = self::_GetInt2d($recordData, 4); + + // offset: 6; size: 1; the boolean value or error value + $boolErr = ord($recordData{6}); + + // offset: 7; size: 1; 0=boolean; 1=error + $isError = ord($recordData{7}); + + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + switch ($isError) { + case 0: // boolean + $value = (bool) $boolErr; + + // add cell value + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_BOOL); + break; + + case 1: // error type + $value = self::_mapErrorCode($boolErr); + + // add cell value + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_ERROR); + break; + } + + if (!$this->_readDataOnly) { + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } + + + /** + * Read MULBLANK record + * This record represents a cell range of empty cells. All + * cells are located in the same row + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readMulBlank() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to first column + $fc = self::_GetInt2d($recordData, 2); + + // offset: 4; size: 2 x nc; list of indexes to XF records + // add style information + if (!$this->_readDataOnly) { + for ($i = 0; $i < $length / 2 - 3; ++$i) { + $columnString = PHPExcel_Cell::stringFromColumnIndex($fc + $i); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + $xfIndex = self::_GetInt2d($recordData, 4 + 2 * $i); + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } + + // offset: 6; size 2; index to last column (not needed) + } + + + /** + * Read LABEL record + * This record represents a cell that contains a string. In + * BIFF8 it is usually replaced by the LABELSST record. + * Excel still uses this record, if it copies unformatted + * text cells to the clipboard. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readLabel() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; index to row + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to column + $column = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($column); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset: 4; size: 2; XF index + $xfIndex = self::_GetInt2d($recordData, 4); + + // add cell value + // todo: what if string is very long? continue record + if ($this->_version == self::XLS_BIFF8) { + $string = self::_readUnicodeStringLong(substr($recordData, 6)); + $value = $string['value']; + } else { + $string = $this->_readByteStringLong(substr($recordData, 6)); + $value = $string['value']; + } + $cell = $this->_phpSheet->getCell($columnString . ($row + 1)); + $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_STRING); + + if (!$this->_readDataOnly) { + // add cell style + $cell->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + } + + + /** + * Read BLANK record + */ + private function _readBlank() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; row index + $row = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; col index + $col = self::_GetInt2d($recordData, 2); + $columnString = PHPExcel_Cell::stringFromColumnIndex($col); + + // Read cell? + if (($this->getReadFilter() !== NULL) && $this->getReadFilter()->readCell($columnString, $row + 1, $this->_phpSheet->getTitle()) ) { + // offset: 4; size: 2; XF index + $xfIndex = self::_GetInt2d($recordData, 4); + + // add style information + if (!$this->_readDataOnly) { + $this->_phpSheet->getCell($columnString . ($row + 1))->setXfIndex($this->_mapCellXfIndex[$xfIndex]); + } + } + + } + + + /** + * Read MSODRAWING record + */ + private function _readMsoDrawing() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + + // get spliced record data + $splicedRecordData = $this->_getSplicedRecordData(); + $recordData = $splicedRecordData['recordData']; + + $this->_drawingData .= $recordData; + } + + + /** + * Read OBJ record + */ + private function _readObj() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly || $this->_version != self::XLS_BIFF8) { + return; + } + + // recordData consists of an array of subrecords looking like this: + // ft: 2 bytes; ftCmo type (0x15) + // cb: 2 bytes; size in bytes of ftCmo data + // ot: 2 bytes; Object Type + // id: 2 bytes; Object id number + // grbit: 2 bytes; Option Flags + // data: var; subrecord data + + // for now, we are just interested in the second subrecord containing the object type + $ftCmoType = self::_GetInt2d($recordData, 0); + $cbCmoSize = self::_GetInt2d($recordData, 2); + $otObjType = self::_GetInt2d($recordData, 4); + $idObjID = self::_GetInt2d($recordData, 6); + $grbitOpts = self::_GetInt2d($recordData, 6); + + $this->_objs[] = array( + 'ftCmoType' => $ftCmoType, + 'cbCmoSize' => $cbCmoSize, + 'otObjType' => $otObjType, + 'idObjID' => $idObjID, + 'grbitOpts' => $grbitOpts + ); + $this->textObjRef = $idObjID; + +// echo '_readObj()
    '; +// var_dump(end($this->_objs)); +// echo '
    '; + } + + + /** + * Read WINDOW2 record + */ + private function _readWindow2() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; option flags + $options = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; index to first visible row + $firstVisibleRow = self::_GetInt2d($recordData, 2); + + // offset: 4; size: 2; index to first visible colum + $firstVisibleColumn = self::_GetInt2d($recordData, 4); + if ($this->_version === self::XLS_BIFF8) { + // offset: 8; size: 2; not used + // offset: 10; size: 2; cached magnification factor in page break preview (in percent); 0 = Default (60%) + // offset: 12; size: 2; cached magnification factor in normal view (in percent); 0 = Default (100%) + // offset: 14; size: 4; not used + $zoomscaleInPageBreakPreview = self::_GetInt2d($recordData, 10); + if ($zoomscaleInPageBreakPreview === 0) $zoomscaleInPageBreakPreview = 60; + $zoomscaleInNormalView = self::_GetInt2d($recordData, 12); + if ($zoomscaleInNormalView === 0) $zoomscaleInNormalView = 100; + } + + // bit: 1; mask: 0x0002; 0 = do not show gridlines, 1 = show gridlines + $showGridlines = (bool) ((0x0002 & $options) >> 1); + $this->_phpSheet->setShowGridlines($showGridlines); + + // bit: 2; mask: 0x0004; 0 = do not show headers, 1 = show headers + $showRowColHeaders = (bool) ((0x0004 & $options) >> 2); + $this->_phpSheet->setShowRowColHeaders($showRowColHeaders); + + // bit: 3; mask: 0x0008; 0 = panes are not frozen, 1 = panes are frozen + $this->_frozen = (bool) ((0x0008 & $options) >> 3); + + // bit: 6; mask: 0x0040; 0 = columns from left to right, 1 = columns from right to left + $this->_phpSheet->setRightToLeft((bool)((0x0040 & $options) >> 6)); + + // bit: 10; mask: 0x0400; 0 = sheet not active, 1 = sheet active + $isActive = (bool) ((0x0400 & $options) >> 10); + if ($isActive) { + $this->_phpExcel->setActiveSheetIndex($this->_phpExcel->getIndex($this->_phpSheet)); + } + + // bit: 11; mask: 0x0800; 0 = normal view, 1 = page break view + $isPageBreakPreview = (bool) ((0x0800 & $options) >> 11); + + //FIXME: set $firstVisibleRow and $firstVisibleColumn + + if ($this->_phpSheet->getSheetView()->getView() !== PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT) { + //NOTE: this setting is inferior to page layout view(Excel2007-) + $view = $isPageBreakPreview? PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW : + PHPExcel_Worksheet_SheetView::SHEETVIEW_NORMAL; + $this->_phpSheet->getSheetView()->setView($view); + if ($this->_version === self::XLS_BIFF8) { + $zoomScale = $isPageBreakPreview? $zoomscaleInPageBreakPreview : $zoomscaleInNormalView; + $this->_phpSheet->getSheetView()->setZoomScale($zoomScale); + $this->_phpSheet->getSheetView()->setZoomScaleNormal($zoomscaleInNormalView); + } + } + } + + /** + * Read PLV Record(Created by Excel2007 or upper) + */ + private function _readPageLayoutView(){ + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + //var_dump(unpack("vrt/vgrbitFrt/V2reserved/vwScalePLV/vgrbit", $recordData)); + + // offset: 0; size: 2; rt + //->ignore + $rt = self::_GetInt2d($recordData, 0); + // offset: 2; size: 2; grbitfr + //->ignore + $grbitFrt = self::_GetInt2d($recordData, 2); + // offset: 4; size: 8; reserved + //->ignore + + // offset: 12; size 2; zoom scale + $wScalePLV = self::_GetInt2d($recordData, 12); + // offset: 14; size 2; grbit + $grbit = self::_GetInt2d($recordData, 14); + + // decomprise grbit + $fPageLayoutView = $grbit & 0x01; + $fRulerVisible = ($grbit >> 1) & 0x01; //no support + $fWhitespaceHidden = ($grbit >> 3) & 0x01; //no support + + if ($fPageLayoutView === 1) { + $this->_phpSheet->getSheetView()->setView(PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT); + $this->_phpSheet->getSheetView()->setZoomScale($wScalePLV); //set by Excel2007 only if SHEETVIEW_PAGE_LAYOUT + } + //otherwise, we cannot know whether SHEETVIEW_PAGE_LAYOUT or SHEETVIEW_PAGE_BREAK_PREVIEW. + } + + /** + * Read SCL record + */ + private function _readScl() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // offset: 0; size: 2; numerator of the view magnification + $numerator = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; numerator of the view magnification + $denumerator = self::_GetInt2d($recordData, 2); + + // set the zoom scale (in percent) + $this->_phpSheet->getSheetView()->setZoomScale($numerator * 100 / $denumerator); + } + + + /** + * Read PANE record + */ + private function _readPane() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; position of vertical split + $px = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; position of horizontal split + $py = self::_GetInt2d($recordData, 2); + + if ($this->_frozen) { + // frozen panes + $this->_phpSheet->freezePane(PHPExcel_Cell::stringFromColumnIndex($px) . ($py + 1)); + } else { + // unfrozen panes; split windows; not supported by PHPExcel core + } + } + } + + + /** + * Read SELECTION record. There is one such record for each pane in the sheet. + */ + private function _readSelection() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 1; pane identifier + $paneId = ord($recordData{0}); + + // offset: 1; size: 2; index to row of the active cell + $r = self::_GetInt2d($recordData, 1); + + // offset: 3; size: 2; index to column of the active cell + $c = self::_GetInt2d($recordData, 3); + + // offset: 5; size: 2; index into the following cell range list to the + // entry that contains the active cell + $index = self::_GetInt2d($recordData, 5); + + // offset: 7; size: var; cell range address list containing all selected cell ranges + $data = substr($recordData, 7); + $cellRangeAddressList = $this->_readBIFF5CellRangeAddressList($data); // note: also BIFF8 uses BIFF5 syntax + + $selectedCells = $cellRangeAddressList['cellRangeAddresses'][0]; + + // first row '1' + last row '16384' indicates that full column is selected (apparently also in BIFF8!) + if (preg_match('/^([A-Z]+1\:[A-Z]+)16384$/', $selectedCells)) { + $selectedCells = preg_replace('/^([A-Z]+1\:[A-Z]+)16384$/', '${1}1048576', $selectedCells); + } + + // first row '1' + last row '65536' indicates that full column is selected + if (preg_match('/^([A-Z]+1\:[A-Z]+)65536$/', $selectedCells)) { + $selectedCells = preg_replace('/^([A-Z]+1\:[A-Z]+)65536$/', '${1}1048576', $selectedCells); + } + + // first column 'A' + last column 'IV' indicates that full row is selected + if (preg_match('/^(A[0-9]+\:)IV([0-9]+)$/', $selectedCells)) { + $selectedCells = preg_replace('/^(A[0-9]+\:)IV([0-9]+)$/', '${1}XFD${2}', $selectedCells); + } + + $this->_phpSheet->setSelectedCells($selectedCells); + } + } + + + private function _includeCellRangeFiltered($cellRangeAddress) + { + $includeCellRange = true; + if ($this->getReadFilter() !== NULL) { + $includeCellRange = false; + $rangeBoundaries = PHPExcel_Cell::getRangeBoundaries($cellRangeAddress); + $rangeBoundaries[1][0]++; + for ($row = $rangeBoundaries[0][1]; $row <= $rangeBoundaries[1][1]; $row++) { + for ($column = $rangeBoundaries[0][0]; $column != $rangeBoundaries[1][0]; $column++) { + if ($this->getReadFilter()->readCell($column, $row, $this->_phpSheet->getTitle())) { + $includeCellRange = true; + break 2; + } + } + } + } + return $includeCellRange; + } + + + /** + * MERGEDCELLS + * + * This record contains the addresses of merged cell ranges + * in the current sheet. + * + * -- "OpenOffice.org's Documentation of the Microsoft + * Excel File Format" + */ + private function _readMergedCells() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_version == self::XLS_BIFF8 && !$this->_readDataOnly) { + $cellRangeAddressList = $this->_readBIFF8CellRangeAddressList($recordData); + foreach ($cellRangeAddressList['cellRangeAddresses'] as $cellRangeAddress) { + if ((strpos($cellRangeAddress,':') !== FALSE) && + ($this->_includeCellRangeFiltered($cellRangeAddress))) { + $this->_phpSheet->mergeCells($cellRangeAddress); + } + } + } + } + + + /** + * Read HYPERLINK record + */ + private function _readHyperLink() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer forward to next record + $this->_pos += 4 + $length; + + if (!$this->_readDataOnly) { + // offset: 0; size: 8; cell range address of all cells containing this hyperlink + try { + $cellRange = $this->_readBIFF8CellRangeAddressFixed($recordData, 0, 8); + } catch (PHPExcel_Exception $e) { + return; + } + + // offset: 8, size: 16; GUID of StdLink + + // offset: 24, size: 4; unknown value + + // offset: 28, size: 4; option flags + + // bit: 0; mask: 0x00000001; 0 = no link or extant, 1 = file link or URL + $isFileLinkOrUrl = (0x00000001 & self::_GetInt2d($recordData, 28)) >> 0; + + // bit: 1; mask: 0x00000002; 0 = relative path, 1 = absolute path or URL + $isAbsPathOrUrl = (0x00000001 & self::_GetInt2d($recordData, 28)) >> 1; + + // bit: 2 (and 4); mask: 0x00000014; 0 = no description + $hasDesc = (0x00000014 & self::_GetInt2d($recordData, 28)) >> 2; + + // bit: 3; mask: 0x00000008; 0 = no text, 1 = has text + $hasText = (0x00000008 & self::_GetInt2d($recordData, 28)) >> 3; + + // bit: 7; mask: 0x00000080; 0 = no target frame, 1 = has target frame + $hasFrame = (0x00000080 & self::_GetInt2d($recordData, 28)) >> 7; + + // bit: 8; mask: 0x00000100; 0 = file link or URL, 1 = UNC path (inc. server name) + $isUNC = (0x00000100 & self::_GetInt2d($recordData, 28)) >> 8; + + // offset within record data + $offset = 32; + + if ($hasDesc) { + // offset: 32; size: var; character count of description text + $dl = self::_GetInt4d($recordData, 32); + // offset: 36; size: var; character array of description text, no Unicode string header, always 16-bit characters, zero terminated + $desc = self::_encodeUTF16(substr($recordData, 36, 2 * ($dl - 1)), false); + $offset += 4 + 2 * $dl; + } + if ($hasFrame) { + $fl = self::_GetInt4d($recordData, $offset); + $offset += 4 + 2 * $fl; + } + + // detect type of hyperlink (there are 4 types) + $hyperlinkType = null; + + if ($isUNC) { + $hyperlinkType = 'UNC'; + } else if (!$isFileLinkOrUrl) { + $hyperlinkType = 'workbook'; + } else if (ord($recordData{$offset}) == 0x03) { + $hyperlinkType = 'local'; + } else if (ord($recordData{$offset}) == 0xE0) { + $hyperlinkType = 'URL'; + } + + switch ($hyperlinkType) { + case 'URL': + // section 5.58.2: Hyperlink containing a URL + // e.g. http://example.org/index.php + + // offset: var; size: 16; GUID of URL Moniker + $offset += 16; + // offset: var; size: 4; size (in bytes) of character array of the URL including trailing zero word + $us = self::_GetInt4d($recordData, $offset); + $offset += 4; + // offset: var; size: $us; character array of the URL, no Unicode string header, always 16-bit characters, zero-terminated + $url = self::_encodeUTF16(substr($recordData, $offset, $us - 2), false); + $url .= $hasText ? '#' : ''; + $offset += $us; + break; + + case 'local': + // section 5.58.3: Hyperlink to local file + // examples: + // mydoc.txt + // ../../somedoc.xls#Sheet!A1 + + // offset: var; size: 16; GUI of File Moniker + $offset += 16; + + // offset: var; size: 2; directory up-level count. + $upLevelCount = self::_GetInt2d($recordData, $offset); + $offset += 2; + + // offset: var; size: 4; character count of the shortened file path and name, including trailing zero word + $sl = self::_GetInt4d($recordData, $offset); + $offset += 4; + + // offset: var; size: sl; character array of the shortened file path and name in 8.3-DOS-format (compressed Unicode string) + $shortenedFilePath = substr($recordData, $offset, $sl); + $shortenedFilePath = self::_encodeUTF16($shortenedFilePath, true); + $shortenedFilePath = substr($shortenedFilePath, 0, -1); // remove trailing zero + + $offset += $sl; + + // offset: var; size: 24; unknown sequence + $offset += 24; + + // extended file path + // offset: var; size: 4; size of the following file link field including string lenth mark + $sz = self::_GetInt4d($recordData, $offset); + $offset += 4; + + // only present if $sz > 0 + if ($sz > 0) { + // offset: var; size: 4; size of the character array of the extended file path and name + $xl = self::_GetInt4d($recordData, $offset); + $offset += 4; + + // offset: var; size 2; unknown + $offset += 2; + + // offset: var; size $xl; character array of the extended file path and name. + $extendedFilePath = substr($recordData, $offset, $xl); + $extendedFilePath = self::_encodeUTF16($extendedFilePath, false); + $offset += $xl; + } + + // construct the path + $url = str_repeat('..\\', $upLevelCount); + $url .= ($sz > 0) ? + $extendedFilePath : $shortenedFilePath; // use extended path if available + $url .= $hasText ? '#' : ''; + + break; + + + case 'UNC': + // section 5.58.4: Hyperlink to a File with UNC (Universal Naming Convention) Path + // todo: implement + return; + + case 'workbook': + // section 5.58.5: Hyperlink to the Current Workbook + // e.g. Sheet2!B1:C2, stored in text mark field + $url = 'sheet://'; + break; + + default: + return; + + } + + if ($hasText) { + // offset: var; size: 4; character count of text mark including trailing zero word + $tl = self::_GetInt4d($recordData, $offset); + $offset += 4; + // offset: var; size: var; character array of the text mark without the # sign, no Unicode header, always 16-bit characters, zero-terminated + $text = self::_encodeUTF16(substr($recordData, $offset, 2 * ($tl - 1)), false); + $url .= $text; + } + + // apply the hyperlink to all the relevant cells + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cellRange) as $coordinate) { + $this->_phpSheet->getCell($coordinate)->getHyperLink()->setUrl($url); + } + } + } + + + /** + * Read DATAVALIDATIONS record + */ + private function _readDataValidations() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer forward to next record + $this->_pos += 4 + $length; + } + + + /** + * Read DATAVALIDATION record + */ + private function _readDataValidation() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer forward to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 4; Options + $options = self::_GetInt4d($recordData, 0); + + // bit: 0-3; mask: 0x0000000F; type + $type = (0x0000000F & $options) >> 0; + switch ($type) { + case 0x00: $type = PHPExcel_Cell_DataValidation::TYPE_NONE; break; + case 0x01: $type = PHPExcel_Cell_DataValidation::TYPE_WHOLE; break; + case 0x02: $type = PHPExcel_Cell_DataValidation::TYPE_DECIMAL; break; + case 0x03: $type = PHPExcel_Cell_DataValidation::TYPE_LIST; break; + case 0x04: $type = PHPExcel_Cell_DataValidation::TYPE_DATE; break; + case 0x05: $type = PHPExcel_Cell_DataValidation::TYPE_TIME; break; + case 0x06: $type = PHPExcel_Cell_DataValidation::TYPE_TEXTLENGTH; break; + case 0x07: $type = PHPExcel_Cell_DataValidation::TYPE_CUSTOM; break; + } + + // bit: 4-6; mask: 0x00000070; error type + $errorStyle = (0x00000070 & $options) >> 4; + switch ($errorStyle) { + case 0x00: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_STOP; break; + case 0x01: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_WARNING; break; + case 0x02: $errorStyle = PHPExcel_Cell_DataValidation::STYLE_INFORMATION; break; + } + + // bit: 7; mask: 0x00000080; 1= formula is explicit (only applies to list) + // I have only seen cases where this is 1 + $explicitFormula = (0x00000080 & $options) >> 7; + + // bit: 8; mask: 0x00000100; 1= empty cells allowed + $allowBlank = (0x00000100 & $options) >> 8; + + // bit: 9; mask: 0x00000200; 1= suppress drop down arrow in list type validity + $suppressDropDown = (0x00000200 & $options) >> 9; + + // bit: 18; mask: 0x00040000; 1= show prompt box if cell selected + $showInputMessage = (0x00040000 & $options) >> 18; + + // bit: 19; mask: 0x00080000; 1= show error box if invalid values entered + $showErrorMessage = (0x00080000 & $options) >> 19; + + // bit: 20-23; mask: 0x00F00000; condition operator + $operator = (0x00F00000 & $options) >> 20; + switch ($operator) { + case 0x00: $operator = PHPExcel_Cell_DataValidation::OPERATOR_BETWEEN ; break; + case 0x01: $operator = PHPExcel_Cell_DataValidation::OPERATOR_NOTBETWEEN ; break; + case 0x02: $operator = PHPExcel_Cell_DataValidation::OPERATOR_EQUAL ; break; + case 0x03: $operator = PHPExcel_Cell_DataValidation::OPERATOR_NOTEQUAL ; break; + case 0x04: $operator = PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHAN ; break; + case 0x05: $operator = PHPExcel_Cell_DataValidation::OPERATOR_LESSTHAN ; break; + case 0x06: $operator = PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHANOREQUAL; break; + case 0x07: $operator = PHPExcel_Cell_DataValidation::OPERATOR_LESSTHANOREQUAL ; break; + } + + // offset: 4; size: var; title of the prompt box + $offset = 4; + $string = self::_readUnicodeStringLong(substr($recordData, $offset)); + $promptTitle = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: var; title of the error box + $string = self::_readUnicodeStringLong(substr($recordData, $offset)); + $errorTitle = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: var; text of the prompt box + $string = self::_readUnicodeStringLong(substr($recordData, $offset)); + $prompt = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: var; text of the error box + $string = self::_readUnicodeStringLong(substr($recordData, $offset)); + $error = $string['value'] !== chr(0) ? + $string['value'] : ''; + $offset += $string['size']; + + // offset: var; size: 2; size of the formula data for the first condition + $sz1 = self::_GetInt2d($recordData, $offset); + $offset += 2; + + // offset: var; size: 2; not used + $offset += 2; + + // offset: var; size: $sz1; formula data for first condition (without size field) + $formula1 = substr($recordData, $offset, $sz1); + $formula1 = pack('v', $sz1) . $formula1; // prepend the length + try { + $formula1 = $this->_getFormulaFromStructure($formula1); + + // in list type validity, null characters are used as item separators + if ($type == PHPExcel_Cell_DataValidation::TYPE_LIST) { + $formula1 = str_replace(chr(0), ',', $formula1); + } + } catch (PHPExcel_Exception $e) { + return; + } + $offset += $sz1; + + // offset: var; size: 2; size of the formula data for the first condition + $sz2 = self::_GetInt2d($recordData, $offset); + $offset += 2; + + // offset: var; size: 2; not used + $offset += 2; + + // offset: var; size: $sz2; formula data for second condition (without size field) + $formula2 = substr($recordData, $offset, $sz2); + $formula2 = pack('v', $sz2) . $formula2; // prepend the length + try { + $formula2 = $this->_getFormulaFromStructure($formula2); + } catch (PHPExcel_Exception $e) { + return; + } + $offset += $sz2; + + // offset: var; size: var; cell range address list with + $cellRangeAddressList = $this->_readBIFF8CellRangeAddressList(substr($recordData, $offset)); + $cellRangeAddresses = $cellRangeAddressList['cellRangeAddresses']; + + foreach ($cellRangeAddresses as $cellRange) { + $stRange = $this->_phpSheet->shrinkRangeToFit($cellRange); + $stRange = PHPExcel_Cell::extractAllCellReferencesInRange($stRange); + foreach ($stRange as $coordinate) { + $objValidation = $this->_phpSheet->getCell($coordinate)->getDataValidation(); + $objValidation->setType($type); + $objValidation->setErrorStyle($errorStyle); + $objValidation->setAllowBlank((bool)$allowBlank); + $objValidation->setShowInputMessage((bool)$showInputMessage); + $objValidation->setShowErrorMessage((bool)$showErrorMessage); + $objValidation->setShowDropDown(!$suppressDropDown); + $objValidation->setOperator($operator); + $objValidation->setErrorTitle($errorTitle); + $objValidation->setError($error); + $objValidation->setPromptTitle($promptTitle); + $objValidation->setPrompt($prompt); + $objValidation->setFormula1($formula1); + $objValidation->setFormula2($formula2); + } + } + + } + + + /** + * Read SHEETLAYOUT record. Stores sheet tab color information. + */ + private function _readSheetLayout() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // local pointer in record data + $offset = 0; + + if (!$this->_readDataOnly) { + // offset: 0; size: 2; repeated record identifier 0x0862 + + // offset: 2; size: 10; not used + + // offset: 12; size: 4; size of record data + // Excel 2003 uses size of 0x14 (documented), Excel 2007 uses size of 0x28 (not documented?) + $sz = self::_GetInt4d($recordData, 12); + + switch ($sz) { + case 0x14: + // offset: 16; size: 2; color index for sheet tab + $colorIndex = self::_GetInt2d($recordData, 16); + $color = self::_readColor($colorIndex,$this->_palette,$this->_version); + $this->_phpSheet->getTabColor()->setRGB($color['rgb']); + break; + + case 0x28: + // TODO: Investigate structure for .xls SHEETLAYOUT record as saved by MS Office Excel 2007 + return; + break; + } + } + } + + + /** + * Read SHEETPROTECTION record (FEATHEADR) + */ + private function _readSheetProtection() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + if ($this->_readDataOnly) { + return; + } + + // offset: 0; size: 2; repeated record header + + // offset: 2; size: 2; FRT cell reference flag (=0 currently) + + // offset: 4; size: 8; Currently not used and set to 0 + + // offset: 12; size: 2; Shared feature type index (2=Enhanced Protetion, 4=SmartTag) + $isf = self::_GetInt2d($recordData, 12); + if ($isf != 2) { + return; + } + + // offset: 14; size: 1; =1 since this is a feat header + + // offset: 15; size: 4; size of rgbHdrSData + + // rgbHdrSData, assume "Enhanced Protection" + // offset: 19; size: 2; option flags + $options = self::_GetInt2d($recordData, 19); + + // bit: 0; mask 0x0001; 1 = user may edit objects, 0 = users must not edit objects + $bool = (0x0001 & $options) >> 0; + $this->_phpSheet->getProtection()->setObjects(!$bool); + + // bit: 1; mask 0x0002; edit scenarios + $bool = (0x0002 & $options) >> 1; + $this->_phpSheet->getProtection()->setScenarios(!$bool); + + // bit: 2; mask 0x0004; format cells + $bool = (0x0004 & $options) >> 2; + $this->_phpSheet->getProtection()->setFormatCells(!$bool); + + // bit: 3; mask 0x0008; format columns + $bool = (0x0008 & $options) >> 3; + $this->_phpSheet->getProtection()->setFormatColumns(!$bool); + + // bit: 4; mask 0x0010; format rows + $bool = (0x0010 & $options) >> 4; + $this->_phpSheet->getProtection()->setFormatRows(!$bool); + + // bit: 5; mask 0x0020; insert columns + $bool = (0x0020 & $options) >> 5; + $this->_phpSheet->getProtection()->setInsertColumns(!$bool); + + // bit: 6; mask 0x0040; insert rows + $bool = (0x0040 & $options) >> 6; + $this->_phpSheet->getProtection()->setInsertRows(!$bool); + + // bit: 7; mask 0x0080; insert hyperlinks + $bool = (0x0080 & $options) >> 7; + $this->_phpSheet->getProtection()->setInsertHyperlinks(!$bool); + + // bit: 8; mask 0x0100; delete columns + $bool = (0x0100 & $options) >> 8; + $this->_phpSheet->getProtection()->setDeleteColumns(!$bool); + + // bit: 9; mask 0x0200; delete rows + $bool = (0x0200 & $options) >> 9; + $this->_phpSheet->getProtection()->setDeleteRows(!$bool); + + // bit: 10; mask 0x0400; select locked cells + $bool = (0x0400 & $options) >> 10; + $this->_phpSheet->getProtection()->setSelectLockedCells(!$bool); + + // bit: 11; mask 0x0800; sort cell range + $bool = (0x0800 & $options) >> 11; + $this->_phpSheet->getProtection()->setSort(!$bool); + + // bit: 12; mask 0x1000; auto filter + $bool = (0x1000 & $options) >> 12; + $this->_phpSheet->getProtection()->setAutoFilter(!$bool); + + // bit: 13; mask 0x2000; pivot tables + $bool = (0x2000 & $options) >> 13; + $this->_phpSheet->getProtection()->setPivotTables(!$bool); + + // bit: 14; mask 0x4000; select unlocked cells + $bool = (0x4000 & $options) >> 14; + $this->_phpSheet->getProtection()->setSelectUnlockedCells(!$bool); + + // offset: 21; size: 2; not used + } + + + /** + * Read RANGEPROTECTION record + * Reading of this record is based on Microsoft Office Excel 97-2000 Binary File Format Specification, + * where it is referred to as FEAT record + */ + private function _readRangeProtection() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // move stream pointer to next record + $this->_pos += 4 + $length; + + // local pointer in record data + $offset = 0; + + if (!$this->_readDataOnly) { + $offset += 12; + + // offset: 12; size: 2; shared feature type, 2 = enhanced protection, 4 = smart tag + $isf = self::_GetInt2d($recordData, 12); + if ($isf != 2) { + // we only read FEAT records of type 2 + return; + } + $offset += 2; + + $offset += 5; + + // offset: 19; size: 2; count of ref ranges this feature is on + $cref = self::_GetInt2d($recordData, 19); + $offset += 2; + + $offset += 6; + + // offset: 27; size: 8 * $cref; list of cell ranges (like in hyperlink record) + $cellRanges = array(); + for ($i = 0; $i < $cref; ++$i) { + try { + $cellRange = $this->_readBIFF8CellRangeAddressFixed(substr($recordData, 27 + 8 * $i, 8)); + } catch (PHPExcel_Exception $e) { + return; + } + $cellRanges[] = $cellRange; + $offset += 8; + } + + // offset: var; size: var; variable length of feature specific data + $rgbFeat = substr($recordData, $offset); + $offset += 4; + + // offset: var; size: 4; the encrypted password (only 16-bit although field is 32-bit) + $wPassword = self::_GetInt4d($recordData, $offset); + $offset += 4; + + // Apply range protection to sheet + if ($cellRanges) { + $this->_phpSheet->protectCells(implode(' ', $cellRanges), strtoupper(dechex($wPassword)), true); + } + } + } + + + /** + * Read IMDATA record + */ + private function _readImData() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + + // get spliced record data + $splicedRecordData = $this->_getSplicedRecordData(); + $recordData = $splicedRecordData['recordData']; + + // UNDER CONSTRUCTION + + // offset: 0; size: 2; image format + $cf = self::_GetInt2d($recordData, 0); + + // offset: 2; size: 2; environment from which the file was written + $env = self::_GetInt2d($recordData, 2); + + // offset: 4; size: 4; length of the image data + $lcb = self::_GetInt4d($recordData, 4); + + // offset: 8; size: var; image data + $iData = substr($recordData, 8); + + switch ($cf) { + case 0x09: // Windows bitmap format + // BITMAPCOREINFO + // 1. BITMAPCOREHEADER + // offset: 0; size: 4; bcSize, Specifies the number of bytes required by the structure + $bcSize = self::_GetInt4d($iData, 0); +// var_dump($bcSize); + + // offset: 4; size: 2; bcWidth, specifies the width of the bitmap, in pixels + $bcWidth = self::_GetInt2d($iData, 4); +// var_dump($bcWidth); + + // offset: 6; size: 2; bcHeight, specifies the height of the bitmap, in pixels. + $bcHeight = self::_GetInt2d($iData, 6); +// var_dump($bcHeight); + $ih = imagecreatetruecolor($bcWidth, $bcHeight); + + // offset: 8; size: 2; bcPlanes, specifies the number of planes for the target device. This value must be 1 + + // offset: 10; size: 2; bcBitCount specifies the number of bits-per-pixel. This value must be 1, 4, 8, or 24 + $bcBitCount = self::_GetInt2d($iData, 10); +// var_dump($bcBitCount); + + $rgbString = substr($iData, 12); + $rgbTriples = array(); + while (strlen($rgbString) > 0) { + $rgbTriples[] = unpack('Cb/Cg/Cr', $rgbString); + $rgbString = substr($rgbString, 3); + } + $x = 0; + $y = 0; + foreach ($rgbTriples as $i => $rgbTriple) { + $color = imagecolorallocate($ih, $rgbTriple['r'], $rgbTriple['g'], $rgbTriple['b']); + imagesetpixel($ih, $x, $bcHeight - 1 - $y, $color); + $x = ($x + 1) % $bcWidth; + $y = $y + floor(($x + 1) / $bcWidth); + } + //imagepng($ih, 'image.png'); + + $drawing = new PHPExcel_Worksheet_Drawing(); + $drawing->setPath($filename); + $drawing->setWorksheet($this->_phpSheet); + + break; + + case 0x02: // Windows metafile or Macintosh PICT format + case 0x0e: // native format + default; + break; + + } + + // _getSplicedRecordData() takes care of moving current position in data stream + } + + + /** + * Read a free CONTINUE record. Free CONTINUE record may be a camouflaged MSODRAWING record + * When MSODRAWING data on a sheet exceeds 8224 bytes, CONTINUE records are used instead. Undocumented. + * In this case, we must treat the CONTINUE record as a MSODRAWING record + */ + private function _readContinue() + { + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $recordData = substr($this->_data, $this->_pos + 4, $length); + + // check if we are reading drawing data + // this is in case a free CONTINUE record occurs in other circumstances we are unaware of + if ($this->_drawingData == '') { + // move stream pointer to next record + $this->_pos += 4 + $length; + + return; + } + + // check if record data is at least 4 bytes long, otherwise there is no chance this is MSODRAWING data + if ($length < 4) { + // move stream pointer to next record + $this->_pos += 4 + $length; + + return; + } + + // dirty check to see if CONTINUE record could be a camouflaged MSODRAWING record + // look inside CONTINUE record to see if it looks like a part of an Escher stream + // we know that Escher stream may be split at least at + // 0xF003 MsofbtSpgrContainer + // 0xF004 MsofbtSpContainer + // 0xF00D MsofbtClientTextbox + $validSplitPoints = array(0xF003, 0xF004, 0xF00D); // add identifiers if we find more + + $splitPoint = self::_GetInt2d($recordData, 2); + if (in_array($splitPoint, $validSplitPoints)) { + // get spliced record data (and move pointer to next record) + $splicedRecordData = $this->_getSplicedRecordData(); + $this->_drawingData .= $splicedRecordData['recordData']; + + return; + } + + // move stream pointer to next record + $this->_pos += 4 + $length; + + } + + + /** + * Reads a record from current position in data stream and continues reading data as long as CONTINUE + * records are found. Splices the record data pieces and returns the combined string as if record data + * is in one piece. + * Moves to next current position in data stream to start of next record different from a CONtINUE record + * + * @return array + */ + private function _getSplicedRecordData() + { + $data = ''; + $spliceOffsets = array(); + + $i = 0; + $spliceOffsets[0] = 0; + + do { + ++$i; + + // offset: 0; size: 2; identifier + $identifier = self::_GetInt2d($this->_data, $this->_pos); + // offset: 2; size: 2; length + $length = self::_GetInt2d($this->_data, $this->_pos + 2); + $data .= substr($this->_data, $this->_pos + 4, $length); + + $spliceOffsets[$i] = $spliceOffsets[$i - 1] + $length; + + $this->_pos += 4 + $length; + $nextIdentifier = self::_GetInt2d($this->_data, $this->_pos); + } + while ($nextIdentifier == self::XLS_Type_CONTINUE); + + $splicedData = array( + 'recordData' => $data, + 'spliceOffsets' => $spliceOffsets, + ); + + return $splicedData; + + } + + + /** + * Convert formula structure into human readable Excel formula like 'A3+A5*5' + * + * @param string $formulaStructure The complete binary data for the formula + * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas + * @return string Human readable formula + */ + private function _getFormulaFromStructure($formulaStructure, $baseCell = 'A1') + { + // offset: 0; size: 2; size of the following formula data + $sz = self::_GetInt2d($formulaStructure, 0); + + // offset: 2; size: sz + $formulaData = substr($formulaStructure, 2, $sz); + + // for debug: dump the formula data + //echo ''; + //echo 'size: ' . $sz . "\n"; + //echo 'the entire formula data: '; + //Debug::dump($formulaData); + //echo "\n----\n"; + + // offset: 2 + sz; size: variable (optional) + if (strlen($formulaStructure) > 2 + $sz) { + $additionalData = substr($formulaStructure, 2 + $sz); + + // for debug: dump the additional data + //echo 'the entire additional data: '; + //Debug::dump($additionalData); + //echo "\n----\n"; + + } else { + $additionalData = ''; + } + + return $this->_getFormulaFromData($formulaData, $additionalData, $baseCell); + } + + + /** + * Take formula data and additional data for formula and return human readable formula + * + * @param string $formulaData The binary data for the formula itself + * @param string $additionalData Additional binary data going with the formula + * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas + * @return string Human readable formula + */ + private function _getFormulaFromData($formulaData, $additionalData = '', $baseCell = 'A1') + { + // start parsing the formula data + $tokens = array(); + + while (strlen($formulaData) > 0 and $token = $this->_getNextToken($formulaData, $baseCell)) { + $tokens[] = $token; + $formulaData = substr($formulaData, $token['size']); + + // for debug: dump the token + //var_dump($token); + } + + $formulaString = $this->_createFormulaFromTokens($tokens, $additionalData); + + return $formulaString; + } + + + /** + * Take array of tokens together with additional data for formula and return human readable formula + * + * @param array $tokens + * @param array $additionalData Additional binary data going with the formula + * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas + * @return string Human readable formula + */ + private function _createFormulaFromTokens($tokens, $additionalData) + { + // empty formula? + if (empty($tokens)) { + return ''; + } + + $formulaStrings = array(); + foreach ($tokens as $token) { + // initialize spaces + $space0 = isset($space0) ? $space0 : ''; // spaces before next token, not tParen + $space1 = isset($space1) ? $space1 : ''; // carriage returns before next token, not tParen + $space2 = isset($space2) ? $space2 : ''; // spaces before opening parenthesis + $space3 = isset($space3) ? $space3 : ''; // carriage returns before opening parenthesis + $space4 = isset($space4) ? $space4 : ''; // spaces before closing parenthesis + $space5 = isset($space5) ? $space5 : ''; // carriage returns before closing parenthesis + + switch ($token['name']) { + case 'tAdd': // addition + case 'tConcat': // addition + case 'tDiv': // division + case 'tEQ': // equality + case 'tGE': // greater than or equal + case 'tGT': // greater than + case 'tIsect': // intersection + case 'tLE': // less than or equal + case 'tList': // less than or equal + case 'tLT': // less than + case 'tMul': // multiplication + case 'tNE': // multiplication + case 'tPower': // power + case 'tRange': // range + case 'tSub': // subtraction + $op2 = array_pop($formulaStrings); + $op1 = array_pop($formulaStrings); + $formulaStrings[] = "$op1$space1$space0{$token['data']}$op2"; + unset($space0, $space1); + break; + case 'tUplus': // unary plus + case 'tUminus': // unary minus + $op = array_pop($formulaStrings); + $formulaStrings[] = "$space1$space0{$token['data']}$op"; + unset($space0, $space1); + break; + case 'tPercent': // percent sign + $op = array_pop($formulaStrings); + $formulaStrings[] = "$op$space1$space0{$token['data']}"; + unset($space0, $space1); + break; + case 'tAttrVolatile': // indicates volatile function + case 'tAttrIf': + case 'tAttrSkip': + case 'tAttrChoose': + // token is only important for Excel formula evaluator + // do nothing + break; + case 'tAttrSpace': // space / carriage return + // space will be used when next token arrives, do not alter formulaString stack + switch ($token['data']['spacetype']) { + case 'type0': + $space0 = str_repeat(' ', $token['data']['spacecount']); + break; + case 'type1': + $space1 = str_repeat("\n", $token['data']['spacecount']); + break; + case 'type2': + $space2 = str_repeat(' ', $token['data']['spacecount']); + break; + case 'type3': + $space3 = str_repeat("\n", $token['data']['spacecount']); + break; + case 'type4': + $space4 = str_repeat(' ', $token['data']['spacecount']); + break; + case 'type5': + $space5 = str_repeat("\n", $token['data']['spacecount']); + break; + } + break; + case 'tAttrSum': // SUM function with one parameter + $op = array_pop($formulaStrings); + $formulaStrings[] = "{$space1}{$space0}SUM($op)"; + unset($space0, $space1); + break; + case 'tFunc': // function with fixed number of arguments + case 'tFuncV': // function with variable number of arguments + if ($token['data']['function'] != '') { + // normal function + $ops = array(); // array of operators + for ($i = 0; $i < $token['data']['args']; ++$i) { + $ops[] = array_pop($formulaStrings); + } + $ops = array_reverse($ops); + $formulaStrings[] = "$space1$space0{$token['data']['function']}(" . implode(',', $ops) . ")"; + unset($space0, $space1); + } else { + // add-in function + $ops = array(); // array of operators + for ($i = 0; $i < $token['data']['args'] - 1; ++$i) { + $ops[] = array_pop($formulaStrings); + } + $ops = array_reverse($ops); + $function = array_pop($formulaStrings); + $formulaStrings[] = "$space1$space0$function(" . implode(',', $ops) . ")"; + unset($space0, $space1); + } + break; + case 'tParen': // parenthesis + $expression = array_pop($formulaStrings); + $formulaStrings[] = "$space3$space2($expression$space5$space4)"; + unset($space2, $space3, $space4, $space5); + break; + case 'tArray': // array constant + $constantArray = self::_readBIFF8ConstantArray($additionalData); + $formulaStrings[] = $space1 . $space0 . $constantArray['value']; + $additionalData = substr($additionalData, $constantArray['size']); // bite of chunk of additional data + unset($space0, $space1); + break; + case 'tMemArea': + // bite off chunk of additional data + $cellRangeAddressList = $this->_readBIFF8CellRangeAddressList($additionalData); + $additionalData = substr($additionalData, $cellRangeAddressList['size']); + $formulaStrings[] = "$space1$space0{$token['data']}"; + unset($space0, $space1); + break; + case 'tArea': // cell range address + case 'tBool': // boolean + case 'tErr': // error code + case 'tInt': // integer + case 'tMemErr': + case 'tMemFunc': + case 'tMissArg': + case 'tName': + case 'tNameX': + case 'tNum': // number + case 'tRef': // single cell reference + case 'tRef3d': // 3d cell reference + case 'tArea3d': // 3d cell range reference + case 'tRefN': + case 'tAreaN': + case 'tStr': // string + $formulaStrings[] = "$space1$space0{$token['data']}"; + unset($space0, $space1); + break; + } + } + $formulaString = $formulaStrings[0]; + + // for debug: dump the human readable formula + //echo '----' . "\n"; + //echo 'Formula: ' . $formulaString; + + return $formulaString; + } + + + /** + * Fetch next token from binary formula data + * + * @param string Formula data + * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas + * @return array + * @throws PHPExcel_Reader_Exception + */ + private function _getNextToken($formulaData, $baseCell = 'A1') + { + // offset: 0; size: 1; token id + $id = ord($formulaData[0]); // token id + $name = false; // initialize token name + + switch ($id) { + case 0x03: $name = 'tAdd'; $size = 1; $data = '+'; break; + case 0x04: $name = 'tSub'; $size = 1; $data = '-'; break; + case 0x05: $name = 'tMul'; $size = 1; $data = '*'; break; + case 0x06: $name = 'tDiv'; $size = 1; $data = '/'; break; + case 0x07: $name = 'tPower'; $size = 1; $data = '^'; break; + case 0x08: $name = 'tConcat'; $size = 1; $data = '&'; break; + case 0x09: $name = 'tLT'; $size = 1; $data = '<'; break; + case 0x0A: $name = 'tLE'; $size = 1; $data = '<='; break; + case 0x0B: $name = 'tEQ'; $size = 1; $data = '='; break; + case 0x0C: $name = 'tGE'; $size = 1; $data = '>='; break; + case 0x0D: $name = 'tGT'; $size = 1; $data = '>'; break; + case 0x0E: $name = 'tNE'; $size = 1; $data = '<>'; break; + case 0x0F: $name = 'tIsect'; $size = 1; $data = ' '; break; + case 0x10: $name = 'tList'; $size = 1; $data = ','; break; + case 0x11: $name = 'tRange'; $size = 1; $data = ':'; break; + case 0x12: $name = 'tUplus'; $size = 1; $data = '+'; break; + case 0x13: $name = 'tUminus'; $size = 1; $data = '-'; break; + case 0x14: $name = 'tPercent'; $size = 1; $data = '%'; break; + case 0x15: // parenthesis + $name = 'tParen'; + $size = 1; + $data = null; + break; + case 0x16: // missing argument + $name = 'tMissArg'; + $size = 1; + $data = ''; + break; + case 0x17: // string + $name = 'tStr'; + // offset: 1; size: var; Unicode string, 8-bit string length + $string = self::_readUnicodeStringShort(substr($formulaData, 1)); + $size = 1 + $string['size']; + $data = self::_UTF8toExcelDoubleQuoted($string['value']); + break; + case 0x19: // Special attribute + // offset: 1; size: 1; attribute type flags: + switch (ord($formulaData[1])) { + case 0x01: + $name = 'tAttrVolatile'; + $size = 4; + $data = null; + break; + case 0x02: + $name = 'tAttrIf'; + $size = 4; + $data = null; + break; + case 0x04: + $name = 'tAttrChoose'; + // offset: 2; size: 2; number of choices in the CHOOSE function ($nc, number of parameters decreased by 1) + $nc = self::_GetInt2d($formulaData, 2); + // offset: 4; size: 2 * $nc + // offset: 4 + 2 * $nc; size: 2 + $size = 2 * $nc + 6; + $data = null; + break; + case 0x08: + $name = 'tAttrSkip'; + $size = 4; + $data = null; + break; + case 0x10: + $name = 'tAttrSum'; + $size = 4; + $data = null; + break; + case 0x40: + case 0x41: + $name = 'tAttrSpace'; + $size = 4; + // offset: 2; size: 2; space type and position + switch (ord($formulaData[2])) { + case 0x00: + $spacetype = 'type0'; + break; + case 0x01: + $spacetype = 'type1'; + break; + case 0x02: + $spacetype = 'type2'; + break; + case 0x03: + $spacetype = 'type3'; + break; + case 0x04: + $spacetype = 'type4'; + break; + case 0x05: + $spacetype = 'type5'; + break; + default: + throw new PHPExcel_Reader_Exception('Unrecognized space type in tAttrSpace token'); + break; + } + // offset: 3; size: 1; number of inserted spaces/carriage returns + $spacecount = ord($formulaData[3]); + + $data = array('spacetype' => $spacetype, 'spacecount' => $spacecount); + break; + default: + throw new PHPExcel_Reader_Exception('Unrecognized attribute flag in tAttr token'); + break; + } + break; + case 0x1C: // error code + // offset: 1; size: 1; error code + $name = 'tErr'; + $size = 2; + $data = self::_mapErrorCode(ord($formulaData[1])); + break; + case 0x1D: // boolean + // offset: 1; size: 1; 0 = false, 1 = true; + $name = 'tBool'; + $size = 2; + $data = ord($formulaData[1]) ? 'TRUE' : 'FALSE'; + break; + case 0x1E: // integer + // offset: 1; size: 2; unsigned 16-bit integer + $name = 'tInt'; + $size = 3; + $data = self::_GetInt2d($formulaData, 1); + break; + case 0x1F: // number + // offset: 1; size: 8; + $name = 'tNum'; + $size = 9; + $data = self::_extractNumber(substr($formulaData, 1)); + $data = str_replace(',', '.', (string)$data); // in case non-English locale + break; + case 0x20: // array constant + case 0x40: + case 0x60: + // offset: 1; size: 7; not used + $name = 'tArray'; + $size = 8; + $data = null; + break; + case 0x21: // function with fixed number of arguments + case 0x41: + case 0x61: + $name = 'tFunc'; + $size = 3; + // offset: 1; size: 2; index to built-in sheet function + switch (self::_GetInt2d($formulaData, 1)) { + case 2: $function = 'ISNA'; $args = 1; break; + case 3: $function = 'ISERROR'; $args = 1; break; + case 10: $function = 'NA'; $args = 0; break; + case 15: $function = 'SIN'; $args = 1; break; + case 16: $function = 'COS'; $args = 1; break; + case 17: $function = 'TAN'; $args = 1; break; + case 18: $function = 'ATAN'; $args = 1; break; + case 19: $function = 'PI'; $args = 0; break; + case 20: $function = 'SQRT'; $args = 1; break; + case 21: $function = 'EXP'; $args = 1; break; + case 22: $function = 'LN'; $args = 1; break; + case 23: $function = 'LOG10'; $args = 1; break; + case 24: $function = 'ABS'; $args = 1; break; + case 25: $function = 'INT'; $args = 1; break; + case 26: $function = 'SIGN'; $args = 1; break; + case 27: $function = 'ROUND'; $args = 2; break; + case 30: $function = 'REPT'; $args = 2; break; + case 31: $function = 'MID'; $args = 3; break; + case 32: $function = 'LEN'; $args = 1; break; + case 33: $function = 'VALUE'; $args = 1; break; + case 34: $function = 'TRUE'; $args = 0; break; + case 35: $function = 'FALSE'; $args = 0; break; + case 38: $function = 'NOT'; $args = 1; break; + case 39: $function = 'MOD'; $args = 2; break; + case 40: $function = 'DCOUNT'; $args = 3; break; + case 41: $function = 'DSUM'; $args = 3; break; + case 42: $function = 'DAVERAGE'; $args = 3; break; + case 43: $function = 'DMIN'; $args = 3; break; + case 44: $function = 'DMAX'; $args = 3; break; + case 45: $function = 'DSTDEV'; $args = 3; break; + case 48: $function = 'TEXT'; $args = 2; break; + case 61: $function = 'MIRR'; $args = 3; break; + case 63: $function = 'RAND'; $args = 0; break; + case 65: $function = 'DATE'; $args = 3; break; + case 66: $function = 'TIME'; $args = 3; break; + case 67: $function = 'DAY'; $args = 1; break; + case 68: $function = 'MONTH'; $args = 1; break; + case 69: $function = 'YEAR'; $args = 1; break; + case 71: $function = 'HOUR'; $args = 1; break; + case 72: $function = 'MINUTE'; $args = 1; break; + case 73: $function = 'SECOND'; $args = 1; break; + case 74: $function = 'NOW'; $args = 0; break; + case 75: $function = 'AREAS'; $args = 1; break; + case 76: $function = 'ROWS'; $args = 1; break; + case 77: $function = 'COLUMNS'; $args = 1; break; + case 83: $function = 'TRANSPOSE'; $args = 1; break; + case 86: $function = 'TYPE'; $args = 1; break; + case 97: $function = 'ATAN2'; $args = 2; break; + case 98: $function = 'ASIN'; $args = 1; break; + case 99: $function = 'ACOS'; $args = 1; break; + case 105: $function = 'ISREF'; $args = 1; break; + case 111: $function = 'CHAR'; $args = 1; break; + case 112: $function = 'LOWER'; $args = 1; break; + case 113: $function = 'UPPER'; $args = 1; break; + case 114: $function = 'PROPER'; $args = 1; break; + case 117: $function = 'EXACT'; $args = 2; break; + case 118: $function = 'TRIM'; $args = 1; break; + case 119: $function = 'REPLACE'; $args = 4; break; + case 121: $function = 'CODE'; $args = 1; break; + case 126: $function = 'ISERR'; $args = 1; break; + case 127: $function = 'ISTEXT'; $args = 1; break; + case 128: $function = 'ISNUMBER'; $args = 1; break; + case 129: $function = 'ISBLANK'; $args = 1; break; + case 130: $function = 'T'; $args = 1; break; + case 131: $function = 'N'; $args = 1; break; + case 140: $function = 'DATEVALUE'; $args = 1; break; + case 141: $function = 'TIMEVALUE'; $args = 1; break; + case 142: $function = 'SLN'; $args = 3; break; + case 143: $function = 'SYD'; $args = 4; break; + case 162: $function = 'CLEAN'; $args = 1; break; + case 163: $function = 'MDETERM'; $args = 1; break; + case 164: $function = 'MINVERSE'; $args = 1; break; + case 165: $function = 'MMULT'; $args = 2; break; + case 184: $function = 'FACT'; $args = 1; break; + case 189: $function = 'DPRODUCT'; $args = 3; break; + case 190: $function = 'ISNONTEXT'; $args = 1; break; + case 195: $function = 'DSTDEVP'; $args = 3; break; + case 196: $function = 'DVARP'; $args = 3; break; + case 198: $function = 'ISLOGICAL'; $args = 1; break; + case 199: $function = 'DCOUNTA'; $args = 3; break; + case 207: $function = 'REPLACEB'; $args = 4; break; + case 210: $function = 'MIDB'; $args = 3; break; + case 211: $function = 'LENB'; $args = 1; break; + case 212: $function = 'ROUNDUP'; $args = 2; break; + case 213: $function = 'ROUNDDOWN'; $args = 2; break; + case 214: $function = 'ASC'; $args = 1; break; + case 215: $function = 'DBCS'; $args = 1; break; + case 221: $function = 'TODAY'; $args = 0; break; + case 229: $function = 'SINH'; $args = 1; break; + case 230: $function = 'COSH'; $args = 1; break; + case 231: $function = 'TANH'; $args = 1; break; + case 232: $function = 'ASINH'; $args = 1; break; + case 233: $function = 'ACOSH'; $args = 1; break; + case 234: $function = 'ATANH'; $args = 1; break; + case 235: $function = 'DGET'; $args = 3; break; + case 244: $function = 'INFO'; $args = 1; break; + case 252: $function = 'FREQUENCY'; $args = 2; break; + case 261: $function = 'ERROR.TYPE'; $args = 1; break; + case 271: $function = 'GAMMALN'; $args = 1; break; + case 273: $function = 'BINOMDIST'; $args = 4; break; + case 274: $function = 'CHIDIST'; $args = 2; break; + case 275: $function = 'CHIINV'; $args = 2; break; + case 276: $function = 'COMBIN'; $args = 2; break; + case 277: $function = 'CONFIDENCE'; $args = 3; break; + case 278: $function = 'CRITBINOM'; $args = 3; break; + case 279: $function = 'EVEN'; $args = 1; break; + case 280: $function = 'EXPONDIST'; $args = 3; break; + case 281: $function = 'FDIST'; $args = 3; break; + case 282: $function = 'FINV'; $args = 3; break; + case 283: $function = 'FISHER'; $args = 1; break; + case 284: $function = 'FISHERINV'; $args = 1; break; + case 285: $function = 'FLOOR'; $args = 2; break; + case 286: $function = 'GAMMADIST'; $args = 4; break; + case 287: $function = 'GAMMAINV'; $args = 3; break; + case 288: $function = 'CEILING'; $args = 2; break; + case 289: $function = 'HYPGEOMDIST'; $args = 4; break; + case 290: $function = 'LOGNORMDIST'; $args = 3; break; + case 291: $function = 'LOGINV'; $args = 3; break; + case 292: $function = 'NEGBINOMDIST'; $args = 3; break; + case 293: $function = 'NORMDIST'; $args = 4; break; + case 294: $function = 'NORMSDIST'; $args = 1; break; + case 295: $function = 'NORMINV'; $args = 3; break; + case 296: $function = 'NORMSINV'; $args = 1; break; + case 297: $function = 'STANDARDIZE'; $args = 3; break; + case 298: $function = 'ODD'; $args = 1; break; + case 299: $function = 'PERMUT'; $args = 2; break; + case 300: $function = 'POISSON'; $args = 3; break; + case 301: $function = 'TDIST'; $args = 3; break; + case 302: $function = 'WEIBULL'; $args = 4; break; + case 303: $function = 'SUMXMY2'; $args = 2; break; + case 304: $function = 'SUMX2MY2'; $args = 2; break; + case 305: $function = 'SUMX2PY2'; $args = 2; break; + case 306: $function = 'CHITEST'; $args = 2; break; + case 307: $function = 'CORREL'; $args = 2; break; + case 308: $function = 'COVAR'; $args = 2; break; + case 309: $function = 'FORECAST'; $args = 3; break; + case 310: $function = 'FTEST'; $args = 2; break; + case 311: $function = 'INTERCEPT'; $args = 2; break; + case 312: $function = 'PEARSON'; $args = 2; break; + case 313: $function = 'RSQ'; $args = 2; break; + case 314: $function = 'STEYX'; $args = 2; break; + case 315: $function = 'SLOPE'; $args = 2; break; + case 316: $function = 'TTEST'; $args = 4; break; + case 325: $function = 'LARGE'; $args = 2; break; + case 326: $function = 'SMALL'; $args = 2; break; + case 327: $function = 'QUARTILE'; $args = 2; break; + case 328: $function = 'PERCENTILE'; $args = 2; break; + case 331: $function = 'TRIMMEAN'; $args = 2; break; + case 332: $function = 'TINV'; $args = 2; break; + case 337: $function = 'POWER'; $args = 2; break; + case 342: $function = 'RADIANS'; $args = 1; break; + case 343: $function = 'DEGREES'; $args = 1; break; + case 346: $function = 'COUNTIF'; $args = 2; break; + case 347: $function = 'COUNTBLANK'; $args = 1; break; + case 350: $function = 'ISPMT'; $args = 4; break; + case 351: $function = 'DATEDIF'; $args = 3; break; + case 352: $function = 'DATESTRING'; $args = 1; break; + case 353: $function = 'NUMBERSTRING'; $args = 2; break; + case 360: $function = 'PHONETIC'; $args = 1; break; + case 368: $function = 'BAHTTEXT'; $args = 1; break; + default: + throw new PHPExcel_Reader_Exception('Unrecognized function in formula'); + break; + } + $data = array('function' => $function, 'args' => $args); + break; + case 0x22: // function with variable number of arguments + case 0x42: + case 0x62: + $name = 'tFuncV'; + $size = 4; + // offset: 1; size: 1; number of arguments + $args = ord($formulaData[1]); + // offset: 2: size: 2; index to built-in sheet function + $index = self::_GetInt2d($formulaData, 2); + switch ($index) { + case 0: $function = 'COUNT'; break; + case 1: $function = 'IF'; break; + case 4: $function = 'SUM'; break; + case 5: $function = 'AVERAGE'; break; + case 6: $function = 'MIN'; break; + case 7: $function = 'MAX'; break; + case 8: $function = 'ROW'; break; + case 9: $function = 'COLUMN'; break; + case 11: $function = 'NPV'; break; + case 12: $function = 'STDEV'; break; + case 13: $function = 'DOLLAR'; break; + case 14: $function = 'FIXED'; break; + case 28: $function = 'LOOKUP'; break; + case 29: $function = 'INDEX'; break; + case 36: $function = 'AND'; break; + case 37: $function = 'OR'; break; + case 46: $function = 'VAR'; break; + case 49: $function = 'LINEST'; break; + case 50: $function = 'TREND'; break; + case 51: $function = 'LOGEST'; break; + case 52: $function = 'GROWTH'; break; + case 56: $function = 'PV'; break; + case 57: $function = 'FV'; break; + case 58: $function = 'NPER'; break; + case 59: $function = 'PMT'; break; + case 60: $function = 'RATE'; break; + case 62: $function = 'IRR'; break; + case 64: $function = 'MATCH'; break; + case 70: $function = 'WEEKDAY'; break; + case 78: $function = 'OFFSET'; break; + case 82: $function = 'SEARCH'; break; + case 100: $function = 'CHOOSE'; break; + case 101: $function = 'HLOOKUP'; break; + case 102: $function = 'VLOOKUP'; break; + case 109: $function = 'LOG'; break; + case 115: $function = 'LEFT'; break; + case 116: $function = 'RIGHT'; break; + case 120: $function = 'SUBSTITUTE'; break; + case 124: $function = 'FIND'; break; + case 125: $function = 'CELL'; break; + case 144: $function = 'DDB'; break; + case 148: $function = 'INDIRECT'; break; + case 167: $function = 'IPMT'; break; + case 168: $function = 'PPMT'; break; + case 169: $function = 'COUNTA'; break; + case 183: $function = 'PRODUCT'; break; + case 193: $function = 'STDEVP'; break; + case 194: $function = 'VARP'; break; + case 197: $function = 'TRUNC'; break; + case 204: $function = 'USDOLLAR'; break; + case 205: $function = 'FINDB'; break; + case 206: $function = 'SEARCHB'; break; + case 208: $function = 'LEFTB'; break; + case 209: $function = 'RIGHTB'; break; + case 216: $function = 'RANK'; break; + case 219: $function = 'ADDRESS'; break; + case 220: $function = 'DAYS360'; break; + case 222: $function = 'VDB'; break; + case 227: $function = 'MEDIAN'; break; + case 228: $function = 'SUMPRODUCT'; break; + case 247: $function = 'DB'; break; + case 255: $function = ''; break; + case 269: $function = 'AVEDEV'; break; + case 270: $function = 'BETADIST'; break; + case 272: $function = 'BETAINV'; break; + case 317: $function = 'PROB'; break; + case 318: $function = 'DEVSQ'; break; + case 319: $function = 'GEOMEAN'; break; + case 320: $function = 'HARMEAN'; break; + case 321: $function = 'SUMSQ'; break; + case 322: $function = 'KURT'; break; + case 323: $function = 'SKEW'; break; + case 324: $function = 'ZTEST'; break; + case 329: $function = 'PERCENTRANK'; break; + case 330: $function = 'MODE'; break; + case 336: $function = 'CONCATENATE'; break; + case 344: $function = 'SUBTOTAL'; break; + case 345: $function = 'SUMIF'; break; + case 354: $function = 'ROMAN'; break; + case 358: $function = 'GETPIVOTDATA'; break; + case 359: $function = 'HYPERLINK'; break; + case 361: $function = 'AVERAGEA'; break; + case 362: $function = 'MAXA'; break; + case 363: $function = 'MINA'; break; + case 364: $function = 'STDEVPA'; break; + case 365: $function = 'VARPA'; break; + case 366: $function = 'STDEVA'; break; + case 367: $function = 'VARA'; break; + default: + throw new PHPExcel_Reader_Exception('Unrecognized function in formula'); + break; + } + $data = array('function' => $function, 'args' => $args); + break; + case 0x23: // index to defined name + case 0x43: + case 0x63: + $name = 'tName'; + $size = 5; + // offset: 1; size: 2; one-based index to definedname record + $definedNameIndex = self::_GetInt2d($formulaData, 1) - 1; + // offset: 2; size: 2; not used + $data = $this->_definedname[$definedNameIndex]['name']; + break; + case 0x24: // single cell reference e.g. A5 + case 0x44: + case 0x64: + $name = 'tRef'; + $size = 5; + $data = $this->_readBIFF8CellAddress(substr($formulaData, 1, 4)); + break; + case 0x25: // cell range reference to cells in the same sheet (2d) + case 0x45: + case 0x65: + $name = 'tArea'; + $size = 9; + $data = $this->_readBIFF8CellRangeAddress(substr($formulaData, 1, 8)); + break; + case 0x26: // Constant reference sub-expression + case 0x46: + case 0x66: + $name = 'tMemArea'; + // offset: 1; size: 4; not used + // offset: 5; size: 2; size of the following subexpression + $subSize = self::_GetInt2d($formulaData, 5); + $size = 7 + $subSize; + $data = $this->_getFormulaFromData(substr($formulaData, 7, $subSize)); + break; + case 0x27: // Deleted constant reference sub-expression + case 0x47: + case 0x67: + $name = 'tMemErr'; + // offset: 1; size: 4; not used + // offset: 5; size: 2; size of the following subexpression + $subSize = self::_GetInt2d($formulaData, 5); + $size = 7 + $subSize; + $data = $this->_getFormulaFromData(substr($formulaData, 7, $subSize)); + break; + case 0x29: // Variable reference sub-expression + case 0x49: + case 0x69: + $name = 'tMemFunc'; + // offset: 1; size: 2; size of the following sub-expression + $subSize = self::_GetInt2d($formulaData, 1); + $size = 3 + $subSize; + $data = $this->_getFormulaFromData(substr($formulaData, 3, $subSize)); + break; + + case 0x2C: // Relative 2d cell reference reference, used in shared formulas and some other places + case 0x4C: + case 0x6C: + $name = 'tRefN'; + $size = 5; + $data = $this->_readBIFF8CellAddressB(substr($formulaData, 1, 4), $baseCell); + break; + + case 0x2D: // Relative 2d range reference + case 0x4D: + case 0x6D: + $name = 'tAreaN'; + $size = 9; + $data = $this->_readBIFF8CellRangeAddressB(substr($formulaData, 1, 8), $baseCell); + break; + + case 0x39: // External name + case 0x59: + case 0x79: + $name = 'tNameX'; + $size = 7; + // offset: 1; size: 2; index to REF entry in EXTERNSHEET record + // offset: 3; size: 2; one-based index to DEFINEDNAME or EXTERNNAME record + $index = self::_GetInt2d($formulaData, 3); + // assume index is to EXTERNNAME record + $data = $this->_externalNames[$index - 1]['name']; + // offset: 5; size: 2; not used + break; + + case 0x3A: // 3d reference to cell + case 0x5A: + case 0x7A: + $name = 'tRef3d'; + $size = 7; + + try { + // offset: 1; size: 2; index to REF entry + $sheetRange = $this->_readSheetRangeByRefIndex(self::_GetInt2d($formulaData, 1)); + // offset: 3; size: 4; cell address + $cellAddress = $this->_readBIFF8CellAddress(substr($formulaData, 3, 4)); + + $data = "$sheetRange!$cellAddress"; + } catch (PHPExcel_Exception $e) { + // deleted sheet reference + $data = '#REF!'; + } + + break; + case 0x3B: // 3d reference to cell range + case 0x5B: + case 0x7B: + $name = 'tArea3d'; + $size = 11; + + try { + // offset: 1; size: 2; index to REF entry + $sheetRange = $this->_readSheetRangeByRefIndex(self::_GetInt2d($formulaData, 1)); + // offset: 3; size: 8; cell address + $cellRangeAddress = $this->_readBIFF8CellRangeAddress(substr($formulaData, 3, 8)); + + $data = "$sheetRange!$cellRangeAddress"; + } catch (PHPExcel_Exception $e) { + // deleted sheet reference + $data = '#REF!'; + } + + break; + // Unknown cases // don't know how to deal with + default: + throw new PHPExcel_Reader_Exception('Unrecognized token ' . sprintf('%02X', $id) . ' in formula'); + break; + } + + return array( + 'id' => $id, + 'name' => $name, + 'size' => $size, + 'data' => $data, + ); + } + + + /** + * Reads a cell address in BIFF8 e.g. 'A2' or '$A$2' + * section 3.3.4 + * + * @param string $cellAddressStructure + * @return string + */ + private function _readBIFF8CellAddress($cellAddressStructure) + { + // offset: 0; size: 2; index to row (0... 65535) (or offset (-32768... 32767)) + $row = self::_GetInt2d($cellAddressStructure, 0) + 1; + + // offset: 2; size: 2; index to column or column offset + relative flags + + // bit: 7-0; mask 0x00FF; column index + $column = PHPExcel_Cell::stringFromColumnIndex(0x00FF & self::_GetInt2d($cellAddressStructure, 2)); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($cellAddressStructure, 2))) { + $column = '$' . $column; + } + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($cellAddressStructure, 2))) { + $row = '$' . $row; + } + + return $column . $row; + } + + + /** + * Reads a cell address in BIFF8 for shared formulas. Uses positive and negative values for row and column + * to indicate offsets from a base cell + * section 3.3.4 + * + * @param string $cellAddressStructure + * @param string $baseCell Base cell, only needed when formula contains tRefN tokens, e.g. with shared formulas + * @return string + */ + private function _readBIFF8CellAddressB($cellAddressStructure, $baseCell = 'A1') + { + list($baseCol, $baseRow) = PHPExcel_Cell::coordinateFromString($baseCell); + $baseCol = PHPExcel_Cell::columnIndexFromString($baseCol) - 1; + + // offset: 0; size: 2; index to row (0... 65535) (or offset (-32768... 32767)) + $rowIndex = self::_GetInt2d($cellAddressStructure, 0); + $row = self::_GetInt2d($cellAddressStructure, 0) + 1; + + // offset: 2; size: 2; index to column or column offset + relative flags + + // bit: 7-0; mask 0x00FF; column index + $colIndex = 0x00FF & self::_GetInt2d($cellAddressStructure, 2); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($cellAddressStructure, 2))) { + $column = PHPExcel_Cell::stringFromColumnIndex($colIndex); + $column = '$' . $column; + } else { + $colIndex = ($colIndex <= 127) ? $colIndex : $colIndex - 256; + $column = PHPExcel_Cell::stringFromColumnIndex($baseCol + $colIndex); + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($cellAddressStructure, 2))) { + $row = '$' . $row; + } else { + $rowIndex = ($rowIndex <= 32767) ? $rowIndex : $rowIndex - 65536; + $row = $baseRow + $rowIndex; + } + + return $column . $row; + } + + + /** + * Reads a cell range address in BIFF5 e.g. 'A2:B6' or 'A1' + * always fixed range + * section 2.5.14 + * + * @param string $subData + * @return string + * @throws PHPExcel_Reader_Exception + */ + private function _readBIFF5CellRangeAddressFixed($subData) + { + // offset: 0; size: 2; index to first row + $fr = self::_GetInt2d($subData, 0) + 1; + + // offset: 2; size: 2; index to last row + $lr = self::_GetInt2d($subData, 2) + 1; + + // offset: 4; size: 1; index to first column + $fc = ord($subData{4}); + + // offset: 5; size: 1; index to last column + $lc = ord($subData{5}); + + // check values + if ($fr > $lr || $fc > $lc) { + throw new PHPExcel_Reader_Exception('Not a cell range address'); + } + + // column index to letter + $fc = PHPExcel_Cell::stringFromColumnIndex($fc); + $lc = PHPExcel_Cell::stringFromColumnIndex($lc); + + if ($fr == $lr and $fc == $lc) { + return "$fc$fr"; + } + return "$fc$fr:$lc$lr"; + } + + + /** + * Reads a cell range address in BIFF8 e.g. 'A2:B6' or 'A1' + * always fixed range + * section 2.5.14 + * + * @param string $subData + * @return string + * @throws PHPExcel_Reader_Exception + */ + private function _readBIFF8CellRangeAddressFixed($subData) + { + // offset: 0; size: 2; index to first row + $fr = self::_GetInt2d($subData, 0) + 1; + + // offset: 2; size: 2; index to last row + $lr = self::_GetInt2d($subData, 2) + 1; + + // offset: 4; size: 2; index to first column + $fc = self::_GetInt2d($subData, 4); + + // offset: 6; size: 2; index to last column + $lc = self::_GetInt2d($subData, 6); + + // check values + if ($fr > $lr || $fc > $lc) { + throw new PHPExcel_Reader_Exception('Not a cell range address'); + } + + // column index to letter + $fc = PHPExcel_Cell::stringFromColumnIndex($fc); + $lc = PHPExcel_Cell::stringFromColumnIndex($lc); + + if ($fr == $lr and $fc == $lc) { + return "$fc$fr"; + } + return "$fc$fr:$lc$lr"; + } + + + /** + * Reads a cell range address in BIFF8 e.g. 'A2:B6' or '$A$2:$B$6' + * there are flags indicating whether column/row index is relative + * section 3.3.4 + * + * @param string $subData + * @return string + */ + private function _readBIFF8CellRangeAddress($subData) + { + // todo: if cell range is just a single cell, should this funciton + // not just return e.g. 'A1' and not 'A1:A1' ? + + // offset: 0; size: 2; index to first row (0... 65535) (or offset (-32768... 32767)) + $fr = self::_GetInt2d($subData, 0) + 1; + + // offset: 2; size: 2; index to last row (0... 65535) (or offset (-32768... 32767)) + $lr = self::_GetInt2d($subData, 2) + 1; + + // offset: 4; size: 2; index to first column or column offset + relative flags + + // bit: 7-0; mask 0x00FF; column index + $fc = PHPExcel_Cell::stringFromColumnIndex(0x00FF & self::_GetInt2d($subData, 4)); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($subData, 4))) { + $fc = '$' . $fc; + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($subData, 4))) { + $fr = '$' . $fr; + } + + // offset: 6; size: 2; index to last column or column offset + relative flags + + // bit: 7-0; mask 0x00FF; column index + $lc = PHPExcel_Cell::stringFromColumnIndex(0x00FF & self::_GetInt2d($subData, 6)); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($subData, 6))) { + $lc = '$' . $lc; + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($subData, 6))) { + $lr = '$' . $lr; + } + + return "$fc$fr:$lc$lr"; + } + + + /** + * Reads a cell range address in BIFF8 for shared formulas. Uses positive and negative values for row and column + * to indicate offsets from a base cell + * section 3.3.4 + * + * @param string $subData + * @param string $baseCell Base cell + * @return string Cell range address + */ + private function _readBIFF8CellRangeAddressB($subData, $baseCell = 'A1') + { + list($baseCol, $baseRow) = PHPExcel_Cell::coordinateFromString($baseCell); + $baseCol = PHPExcel_Cell::columnIndexFromString($baseCol) - 1; + + // TODO: if cell range is just a single cell, should this funciton + // not just return e.g. 'A1' and not 'A1:A1' ? + + // offset: 0; size: 2; first row + $frIndex = self::_GetInt2d($subData, 0); // adjust below + + // offset: 2; size: 2; relative index to first row (0... 65535) should be treated as offset (-32768... 32767) + $lrIndex = self::_GetInt2d($subData, 2); // adjust below + + // offset: 4; size: 2; first column with relative/absolute flags + + // bit: 7-0; mask 0x00FF; column index + $fcIndex = 0x00FF & self::_GetInt2d($subData, 4); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($subData, 4))) { + // absolute column index + $fc = PHPExcel_Cell::stringFromColumnIndex($fcIndex); + $fc = '$' . $fc; + } else { + // column offset + $fcIndex = ($fcIndex <= 127) ? $fcIndex : $fcIndex - 256; + $fc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $fcIndex); + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($subData, 4))) { + // absolute row index + $fr = $frIndex + 1; + $fr = '$' . $fr; + } else { + // row offset + $frIndex = ($frIndex <= 32767) ? $frIndex : $frIndex - 65536; + $fr = $baseRow + $frIndex; + } + + // offset: 6; size: 2; last column with relative/absolute flags + + // bit: 7-0; mask 0x00FF; column index + $lcIndex = 0x00FF & self::_GetInt2d($subData, 6); + $lcIndex = ($lcIndex <= 127) ? $lcIndex : $lcIndex - 256; + $lc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $lcIndex); + + // bit: 14; mask 0x4000; (1 = relative column index, 0 = absolute column index) + if (!(0x4000 & self::_GetInt2d($subData, 6))) { + // absolute column index + $lc = PHPExcel_Cell::stringFromColumnIndex($lcIndex); + $lc = '$' . $lc; + } else { + // column offset + $lcIndex = ($lcIndex <= 127) ? $lcIndex : $lcIndex - 256; + $lc = PHPExcel_Cell::stringFromColumnIndex($baseCol + $lcIndex); + } + + // bit: 15; mask 0x8000; (1 = relative row index, 0 = absolute row index) + if (!(0x8000 & self::_GetInt2d($subData, 6))) { + // absolute row index + $lr = $lrIndex + 1; + $lr = '$' . $lr; + } else { + // row offset + $lrIndex = ($lrIndex <= 32767) ? $lrIndex : $lrIndex - 65536; + $lr = $baseRow + $lrIndex; + } + + return "$fc$fr:$lc$lr"; + } + + + /** + * Read BIFF8 cell range address list + * section 2.5.15 + * + * @param string $subData + * @return array + */ + private function _readBIFF8CellRangeAddressList($subData) + { + $cellRangeAddresses = array(); + + // offset: 0; size: 2; number of the following cell range addresses + $nm = self::_GetInt2d($subData, 0); + + $offset = 2; + // offset: 2; size: 8 * $nm; list of $nm (fixed) cell range addresses + for ($i = 0; $i < $nm; ++$i) { + $cellRangeAddresses[] = $this->_readBIFF8CellRangeAddressFixed(substr($subData, $offset, 8)); + $offset += 8; + } + + return array( + 'size' => 2 + 8 * $nm, + 'cellRangeAddresses' => $cellRangeAddresses, + ); + } + + + /** + * Read BIFF5 cell range address list + * section 2.5.15 + * + * @param string $subData + * @return array + */ + private function _readBIFF5CellRangeAddressList($subData) + { + $cellRangeAddresses = array(); + + // offset: 0; size: 2; number of the following cell range addresses + $nm = self::_GetInt2d($subData, 0); + + $offset = 2; + // offset: 2; size: 6 * $nm; list of $nm (fixed) cell range addresses + for ($i = 0; $i < $nm; ++$i) { + $cellRangeAddresses[] = $this->_readBIFF5CellRangeAddressFixed(substr($subData, $offset, 6)); + $offset += 6; + } + + return array( + 'size' => 2 + 6 * $nm, + 'cellRangeAddresses' => $cellRangeAddresses, + ); + } + + + /** + * Get a sheet range like Sheet1:Sheet3 from REF index + * Note: If there is only one sheet in the range, one gets e.g Sheet1 + * It can also happen that the REF structure uses the -1 (FFFF) code to indicate deleted sheets, + * in which case an PHPExcel_Reader_Exception is thrown + * + * @param int $index + * @return string|false + * @throws PHPExcel_Reader_Exception + */ + private function _readSheetRangeByRefIndex($index) + { + if (isset($this->_ref[$index])) { + + $type = $this->_externalBooks[$this->_ref[$index]['externalBookIndex']]['type']; + + switch ($type) { + case 'internal': + // check if we have a deleted 3d reference + if ($this->_ref[$index]['firstSheetIndex'] == 0xFFFF or $this->_ref[$index]['lastSheetIndex'] == 0xFFFF) { + throw new PHPExcel_Reader_Exception('Deleted sheet reference'); + } + + // we have normal sheet range (collapsed or uncollapsed) + $firstSheetName = $this->_sheets[$this->_ref[$index]['firstSheetIndex']]['name']; + $lastSheetName = $this->_sheets[$this->_ref[$index]['lastSheetIndex']]['name']; + + if ($firstSheetName == $lastSheetName) { + // collapsed sheet range + $sheetRange = $firstSheetName; + } else { + $sheetRange = "$firstSheetName:$lastSheetName"; + } + + // escape the single-quotes + $sheetRange = str_replace("'", "''", $sheetRange); + + // if there are special characters, we need to enclose the range in single-quotes + // todo: check if we have identified the whole set of special characters + // it seems that the following characters are not accepted for sheet names + // and we may assume that they are not present: []*/:\? + if (preg_match("/[ !\"@#£$%&{()}<>=+'|^,;-]/", $sheetRange)) { + $sheetRange = "'$sheetRange'"; + } + + return $sheetRange; + break; + + default: + // TODO: external sheet support + throw new PHPExcel_Reader_Exception('Excel5 reader only supports internal sheets in fomulas'); + break; + } + } + return false; + } + + + /** + * read BIFF8 constant value array from array data + * returns e.g. array('value' => '{1,2;3,4}', 'size' => 40} + * section 2.5.8 + * + * @param string $arrayData + * @return array + */ + private static function _readBIFF8ConstantArray($arrayData) + { + // offset: 0; size: 1; number of columns decreased by 1 + $nc = ord($arrayData[0]); + + // offset: 1; size: 2; number of rows decreased by 1 + $nr = self::_GetInt2d($arrayData, 1); + $size = 3; // initialize + $arrayData = substr($arrayData, 3); + + // offset: 3; size: var; list of ($nc + 1) * ($nr + 1) constant values + $matrixChunks = array(); + for ($r = 1; $r <= $nr + 1; ++$r) { + $items = array(); + for ($c = 1; $c <= $nc + 1; ++$c) { + $constant = self::_readBIFF8Constant($arrayData); + $items[] = $constant['value']; + $arrayData = substr($arrayData, $constant['size']); + $size += $constant['size']; + } + $matrixChunks[] = implode(',', $items); // looks like e.g. '1,"hello"' + } + $matrix = '{' . implode(';', $matrixChunks) . '}'; + + return array( + 'value' => $matrix, + 'size' => $size, + ); + } + + + /** + * read BIFF8 constant value which may be 'Empty Value', 'Number', 'String Value', 'Boolean Value', 'Error Value' + * section 2.5.7 + * returns e.g. array('value' => '5', 'size' => 9) + * + * @param string $valueData + * @return array + */ + private static function _readBIFF8Constant($valueData) + { + // offset: 0; size: 1; identifier for type of constant + $identifier = ord($valueData[0]); + + switch ($identifier) { + case 0x00: // empty constant (what is this?) + $value = ''; + $size = 9; + break; + case 0x01: // number + // offset: 1; size: 8; IEEE 754 floating-point value + $value = self::_extractNumber(substr($valueData, 1, 8)); + $size = 9; + break; + case 0x02: // string value + // offset: 1; size: var; Unicode string, 16-bit string length + $string = self::_readUnicodeStringLong(substr($valueData, 1)); + $value = '"' . $string['value'] . '"'; + $size = 1 + $string['size']; + break; + case 0x04: // boolean + // offset: 1; size: 1; 0 = FALSE, 1 = TRUE + if (ord($valueData[1])) { + $value = 'TRUE'; + } else { + $value = 'FALSE'; + } + $size = 9; + break; + case 0x10: // error code + // offset: 1; size: 1; error code + $value = self::_mapErrorCode(ord($valueData[1])); + $size = 9; + break; + } + return array( + 'value' => $value, + 'size' => $size, + ); + } + + + /** + * Extract RGB color + * OpenOffice.org's Documentation of the Microsoft Excel File Format, section 2.5.4 + * + * @param string $rgb Encoded RGB value (4 bytes) + * @return array + */ + private static function _readRGB($rgb) + { + // offset: 0; size 1; Red component + $r = ord($rgb{0}); + + // offset: 1; size: 1; Green component + $g = ord($rgb{1}); + + // offset: 2; size: 1; Blue component + $b = ord($rgb{2}); + + // HEX notation, e.g. 'FF00FC' + $rgb = sprintf('%02X%02X%02X', $r, $g, $b); + + return array('rgb' => $rgb); + } + + + /** + * Read byte string (8-bit string length) + * OpenOffice documentation: 2.5.2 + * + * @param string $subData + * @return array + */ + private function _readByteStringShort($subData) + { + // offset: 0; size: 1; length of the string (character count) + $ln = ord($subData[0]); + + // offset: 1: size: var; character array (8-bit characters) + $value = $this->_decodeCodepage(substr($subData, 1, $ln)); + + return array( + 'value' => $value, + 'size' => 1 + $ln, // size in bytes of data structure + ); + } + + + /** + * Read byte string (16-bit string length) + * OpenOffice documentation: 2.5.2 + * + * @param string $subData + * @return array + */ + private function _readByteStringLong($subData) + { + // offset: 0; size: 2; length of the string (character count) + $ln = self::_GetInt2d($subData, 0); + + // offset: 2: size: var; character array (8-bit characters) + $value = $this->_decodeCodepage(substr($subData, 2)); + + //return $string; + return array( + 'value' => $value, + 'size' => 2 + $ln, // size in bytes of data structure + ); + } + + + /** + * Extracts an Excel Unicode short string (8-bit string length) + * OpenOffice documentation: 2.5.3 + * function will automatically find out where the Unicode string ends. + * + * @param string $subData + * @return array + */ + private static function _readUnicodeStringShort($subData) + { + $value = ''; + + // offset: 0: size: 1; length of the string (character count) + $characterCount = ord($subData[0]); + + $string = self::_readUnicodeString(substr($subData, 1), $characterCount); + + // add 1 for the string length + $string['size'] += 1; + + return $string; + } + + + /** + * Extracts an Excel Unicode long string (16-bit string length) + * OpenOffice documentation: 2.5.3 + * this function is under construction, needs to support rich text, and Asian phonetic settings + * + * @param string $subData + * @return array + */ + private static function _readUnicodeStringLong($subData) + { + $value = ''; + + // offset: 0: size: 2; length of the string (character count) + $characterCount = self::_GetInt2d($subData, 0); + + $string = self::_readUnicodeString(substr($subData, 2), $characterCount); + + // add 2 for the string length + $string['size'] += 2; + + return $string; + } + + + /** + * Read Unicode string with no string length field, but with known character count + * this function is under construction, needs to support rich text, and Asian phonetic settings + * OpenOffice.org's Documentation of the Microsoft Excel File Format, section 2.5.3 + * + * @param string $subData + * @param int $characterCount + * @return array + */ + private static function _readUnicodeString($subData, $characterCount) + { + $value = ''; + + // offset: 0: size: 1; option flags + + // bit: 0; mask: 0x01; character compression (0 = compressed 8-bit, 1 = uncompressed 16-bit) + $isCompressed = !((0x01 & ord($subData[0])) >> 0); + + // bit: 2; mask: 0x04; Asian phonetic settings + $hasAsian = (0x04) & ord($subData[0]) >> 2; + + // bit: 3; mask: 0x08; Rich-Text settings + $hasRichText = (0x08) & ord($subData[0]) >> 3; + + // offset: 1: size: var; character array + // this offset assumes richtext and Asian phonetic settings are off which is generally wrong + // needs to be fixed + $value = self::_encodeUTF16(substr($subData, 1, $isCompressed ? $characterCount : 2 * $characterCount), $isCompressed); + + return array( + 'value' => $value, + 'size' => $isCompressed ? 1 + $characterCount : 1 + 2 * $characterCount, // the size in bytes including the option flags + ); + } + + + /** + * Convert UTF-8 string to string surounded by double quotes. Used for explicit string tokens in formulas. + * Example: hello"world --> "hello""world" + * + * @param string $value UTF-8 encoded string + * @return string + */ + private static function _UTF8toExcelDoubleQuoted($value) + { + return '"' . str_replace('"', '""', $value) . '"'; + } + + + /** + * Reads first 8 bytes of a string and return IEEE 754 float + * + * @param string $data Binary string that is at least 8 bytes long + * @return float + */ + private static function _extractNumber($data) + { + $rknumhigh = self::_GetInt4d($data, 4); + $rknumlow = self::_GetInt4d($data, 0); + $sign = ($rknumhigh & 0x80000000) >> 31; + $exp = (($rknumhigh & 0x7ff00000) >> 20) - 1023; + $mantissa = (0x100000 | ($rknumhigh & 0x000fffff)); + $mantissalow1 = ($rknumlow & 0x80000000) >> 31; + $mantissalow2 = ($rknumlow & 0x7fffffff); + $value = $mantissa / pow( 2 , (20 - $exp)); + + if ($mantissalow1 != 0) { + $value += 1 / pow (2 , (21 - $exp)); + } + + $value += $mantissalow2 / pow (2 , (52 - $exp)); + if ($sign) { + $value *= -1; + } + + return $value; + } + + + private static function _GetIEEE754($rknum) + { + if (($rknum & 0x02) != 0) { + $value = $rknum >> 2; + } else { + // changes by mmp, info on IEEE754 encoding from + // research.microsoft.com/~hollasch/cgindex/coding/ieeefloat.html + // The RK format calls for using only the most significant 30 bits + // of the 64 bit floating point value. The other 34 bits are assumed + // to be 0 so we use the upper 30 bits of $rknum as follows... + $sign = ($rknum & 0x80000000) >> 31; + $exp = ($rknum & 0x7ff00000) >> 20; + $mantissa = (0x100000 | ($rknum & 0x000ffffc)); + $value = $mantissa / pow( 2 , (20- ($exp - 1023))); + if ($sign) { + $value = -1 * $value; + } + //end of changes by mmp + } + if (($rknum & 0x01) != 0) { + $value /= 100; + } + return $value; + } + + + /** + * Get UTF-8 string from (compressed or uncompressed) UTF-16 string + * + * @param string $string + * @param bool $compressed + * @return string + */ + private static function _encodeUTF16($string, $compressed = '') + { + if ($compressed) { + $string = self::_uncompressByteString($string); + } + + return PHPExcel_Shared_String::ConvertEncoding($string, 'UTF-8', 'UTF-16LE'); + } + + + /** + * Convert UTF-16 string in compressed notation to uncompressed form. Only used for BIFF8. + * + * @param string $string + * @return string + */ + private static function _uncompressByteString($string) + { + $uncompressedString = ''; + $strLen = strlen($string); + for ($i = 0; $i < $strLen; ++$i) { + $uncompressedString .= $string[$i] . "\0"; + } + + return $uncompressedString; + } + + + /** + * Convert string to UTF-8. Only used for BIFF5. + * + * @param string $string + * @return string + */ + private function _decodeCodepage($string) + { + return PHPExcel_Shared_String::ConvertEncoding($string, 'UTF-8', $this->_codepage); + } + + + /** + * Read 16-bit unsigned integer + * + * @param string $data + * @param int $pos + * @return int + */ + public static function _GetInt2d($data, $pos) + { + return ord($data[$pos]) | (ord($data[$pos+1]) << 8); + } + + + /** + * Read 32-bit signed integer + * + * @param string $data + * @param int $pos + * @return int + */ + public static function _GetInt4d($data, $pos) + { + // FIX: represent numbers correctly on 64-bit system + // http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334 + // Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems + $_or_24 = ord($data[$pos + 3]); + if ($_or_24 >= 128) { + // negative number + $_ord_24 = -abs((256 - $_or_24) << 24); + } else { + $_ord_24 = ($_or_24 & 127) << 24; + } + return ord($data[$pos]) | (ord($data[$pos+1]) << 8) | (ord($data[$pos+2]) << 16) | $_ord_24; + } + + + /** + * Read color + * + * @param int $color Indexed color + * @param array $palette Color palette + * @return array RGB color value, example: array('rgb' => 'FF0000') + */ + private static function _readColor($color,$palette,$version) + { + if ($color <= 0x07 || $color >= 0x40) { + // special built-in color + return self::_mapBuiltInColor($color); + } elseif (isset($palette) && isset($palette[$color - 8])) { + // palette color, color index 0x08 maps to pallete index 0 + return $palette[$color - 8]; + } else { + // default color table + if ($version == self::XLS_BIFF8) { + return self::_mapColor($color); + } else { + // BIFF5 + return self::_mapColorBIFF5($color); + } + } + + return $color; + } + + + /** + * Map border style + * OpenOffice documentation: 2.5.11 + * + * @param int $index + * @return string + */ + private static function _mapBorderStyle($index) + { + switch ($index) { + case 0x00: return PHPExcel_Style_Border::BORDER_NONE; + case 0x01: return PHPExcel_Style_Border::BORDER_THIN; + case 0x02: return PHPExcel_Style_Border::BORDER_MEDIUM; + case 0x03: return PHPExcel_Style_Border::BORDER_DASHED; + case 0x04: return PHPExcel_Style_Border::BORDER_DOTTED; + case 0x05: return PHPExcel_Style_Border::BORDER_THICK; + case 0x06: return PHPExcel_Style_Border::BORDER_DOUBLE; + case 0x07: return PHPExcel_Style_Border::BORDER_HAIR; + case 0x08: return PHPExcel_Style_Border::BORDER_MEDIUMDASHED; + case 0x09: return PHPExcel_Style_Border::BORDER_DASHDOT; + case 0x0A: return PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT; + case 0x0B: return PHPExcel_Style_Border::BORDER_DASHDOTDOT; + case 0x0C: return PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT; + case 0x0D: return PHPExcel_Style_Border::BORDER_SLANTDASHDOT; + default: return PHPExcel_Style_Border::BORDER_NONE; + } + } + + + /** + * Get fill pattern from index + * OpenOffice documentation: 2.5.12 + * + * @param int $index + * @return string + */ + private static function _mapFillPattern($index) + { + switch ($index) { + case 0x00: return PHPExcel_Style_Fill::FILL_NONE; + case 0x01: return PHPExcel_Style_Fill::FILL_SOLID; + case 0x02: return PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY; + case 0x03: return PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY; + case 0x04: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY; + case 0x05: return PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL; + case 0x06: return PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL; + case 0x07: return PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN; + case 0x08: return PHPExcel_Style_Fill::FILL_PATTERN_DARKUP; + case 0x09: return PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID; + case 0x0A: return PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS; + case 0x0B: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL; + case 0x0C: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL; + case 0x0D: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN; + case 0x0E: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP; + case 0x0F: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID; + case 0x10: return PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS; + case 0x11: return PHPExcel_Style_Fill::FILL_PATTERN_GRAY125; + case 0x12: return PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625; + default: return PHPExcel_Style_Fill::FILL_NONE; + } + } + + + /** + * Map error code, e.g. '#N/A' + * + * @param int $subData + * @return string + */ + private static function _mapErrorCode($subData) + { + switch ($subData) { + case 0x00: return '#NULL!'; break; + case 0x07: return '#DIV/0!'; break; + case 0x0F: return '#VALUE!'; break; + case 0x17: return '#REF!'; break; + case 0x1D: return '#NAME?'; break; + case 0x24: return '#NUM!'; break; + case 0x2A: return '#N/A'; break; + default: return false; + } + } + + + /** + * Map built-in color to RGB value + * + * @param int $color Indexed color + * @return array + */ + private static function _mapBuiltInColor($color) + { + switch ($color) { + case 0x00: return array('rgb' => '000000'); + case 0x01: return array('rgb' => 'FFFFFF'); + case 0x02: return array('rgb' => 'FF0000'); + case 0x03: return array('rgb' => '00FF00'); + case 0x04: return array('rgb' => '0000FF'); + case 0x05: return array('rgb' => 'FFFF00'); + case 0x06: return array('rgb' => 'FF00FF'); + case 0x07: return array('rgb' => '00FFFF'); + case 0x40: return array('rgb' => '000000'); // system window text color + case 0x41: return array('rgb' => 'FFFFFF'); // system window background color + default: return array('rgb' => '000000'); + } + } + + + /** + * Map color array from BIFF5 built-in color index + * + * @param int $subData + * @return array + */ + private static function _mapColorBIFF5($subData) + { + switch ($subData) { + case 0x08: return array('rgb' => '000000'); + case 0x09: return array('rgb' => 'FFFFFF'); + case 0x0A: return array('rgb' => 'FF0000'); + case 0x0B: return array('rgb' => '00FF00'); + case 0x0C: return array('rgb' => '0000FF'); + case 0x0D: return array('rgb' => 'FFFF00'); + case 0x0E: return array('rgb' => 'FF00FF'); + case 0x0F: return array('rgb' => '00FFFF'); + case 0x10: return array('rgb' => '800000'); + case 0x11: return array('rgb' => '008000'); + case 0x12: return array('rgb' => '000080'); + case 0x13: return array('rgb' => '808000'); + case 0x14: return array('rgb' => '800080'); + case 0x15: return array('rgb' => '008080'); + case 0x16: return array('rgb' => 'C0C0C0'); + case 0x17: return array('rgb' => '808080'); + case 0x18: return array('rgb' => '8080FF'); + case 0x19: return array('rgb' => '802060'); + case 0x1A: return array('rgb' => 'FFFFC0'); + case 0x1B: return array('rgb' => 'A0E0F0'); + case 0x1C: return array('rgb' => '600080'); + case 0x1D: return array('rgb' => 'FF8080'); + case 0x1E: return array('rgb' => '0080C0'); + case 0x1F: return array('rgb' => 'C0C0FF'); + case 0x20: return array('rgb' => '000080'); + case 0x21: return array('rgb' => 'FF00FF'); + case 0x22: return array('rgb' => 'FFFF00'); + case 0x23: return array('rgb' => '00FFFF'); + case 0x24: return array('rgb' => '800080'); + case 0x25: return array('rgb' => '800000'); + case 0x26: return array('rgb' => '008080'); + case 0x27: return array('rgb' => '0000FF'); + case 0x28: return array('rgb' => '00CFFF'); + case 0x29: return array('rgb' => '69FFFF'); + case 0x2A: return array('rgb' => 'E0FFE0'); + case 0x2B: return array('rgb' => 'FFFF80'); + case 0x2C: return array('rgb' => 'A6CAF0'); + case 0x2D: return array('rgb' => 'DD9CB3'); + case 0x2E: return array('rgb' => 'B38FEE'); + case 0x2F: return array('rgb' => 'E3E3E3'); + case 0x30: return array('rgb' => '2A6FF9'); + case 0x31: return array('rgb' => '3FB8CD'); + case 0x32: return array('rgb' => '488436'); + case 0x33: return array('rgb' => '958C41'); + case 0x34: return array('rgb' => '8E5E42'); + case 0x35: return array('rgb' => 'A0627A'); + case 0x36: return array('rgb' => '624FAC'); + case 0x37: return array('rgb' => '969696'); + case 0x38: return array('rgb' => '1D2FBE'); + case 0x39: return array('rgb' => '286676'); + case 0x3A: return array('rgb' => '004500'); + case 0x3B: return array('rgb' => '453E01'); + case 0x3C: return array('rgb' => '6A2813'); + case 0x3D: return array('rgb' => '85396A'); + case 0x3E: return array('rgb' => '4A3285'); + case 0x3F: return array('rgb' => '424242'); + default: return array('rgb' => '000000'); + } + } + + + /** + * Map color array from BIFF8 built-in color index + * + * @param int $subData + * @return array + */ + private static function _mapColor($subData) + { + switch ($subData) { + case 0x08: return array('rgb' => '000000'); + case 0x09: return array('rgb' => 'FFFFFF'); + case 0x0A: return array('rgb' => 'FF0000'); + case 0x0B: return array('rgb' => '00FF00'); + case 0x0C: return array('rgb' => '0000FF'); + case 0x0D: return array('rgb' => 'FFFF00'); + case 0x0E: return array('rgb' => 'FF00FF'); + case 0x0F: return array('rgb' => '00FFFF'); + case 0x10: return array('rgb' => '800000'); + case 0x11: return array('rgb' => '008000'); + case 0x12: return array('rgb' => '000080'); + case 0x13: return array('rgb' => '808000'); + case 0x14: return array('rgb' => '800080'); + case 0x15: return array('rgb' => '008080'); + case 0x16: return array('rgb' => 'C0C0C0'); + case 0x17: return array('rgb' => '808080'); + case 0x18: return array('rgb' => '9999FF'); + case 0x19: return array('rgb' => '993366'); + case 0x1A: return array('rgb' => 'FFFFCC'); + case 0x1B: return array('rgb' => 'CCFFFF'); + case 0x1C: return array('rgb' => '660066'); + case 0x1D: return array('rgb' => 'FF8080'); + case 0x1E: return array('rgb' => '0066CC'); + case 0x1F: return array('rgb' => 'CCCCFF'); + case 0x20: return array('rgb' => '000080'); + case 0x21: return array('rgb' => 'FF00FF'); + case 0x22: return array('rgb' => 'FFFF00'); + case 0x23: return array('rgb' => '00FFFF'); + case 0x24: return array('rgb' => '800080'); + case 0x25: return array('rgb' => '800000'); + case 0x26: return array('rgb' => '008080'); + case 0x27: return array('rgb' => '0000FF'); + case 0x28: return array('rgb' => '00CCFF'); + case 0x29: return array('rgb' => 'CCFFFF'); + case 0x2A: return array('rgb' => 'CCFFCC'); + case 0x2B: return array('rgb' => 'FFFF99'); + case 0x2C: return array('rgb' => '99CCFF'); + case 0x2D: return array('rgb' => 'FF99CC'); + case 0x2E: return array('rgb' => 'CC99FF'); + case 0x2F: return array('rgb' => 'FFCC99'); + case 0x30: return array('rgb' => '3366FF'); + case 0x31: return array('rgb' => '33CCCC'); + case 0x32: return array('rgb' => '99CC00'); + case 0x33: return array('rgb' => 'FFCC00'); + case 0x34: return array('rgb' => 'FF9900'); + case 0x35: return array('rgb' => 'FF6600'); + case 0x36: return array('rgb' => '666699'); + case 0x37: return array('rgb' => '969696'); + case 0x38: return array('rgb' => '003366'); + case 0x39: return array('rgb' => '339966'); + case 0x3A: return array('rgb' => '003300'); + case 0x3B: return array('rgb' => '333300'); + case 0x3C: return array('rgb' => '993300'); + case 0x3D: return array('rgb' => '993366'); + case 0x3E: return array('rgb' => '333399'); + case 0x3F: return array('rgb' => '333333'); + default: return array('rgb' => '000000'); + } + } + + + private function _parseRichText($is = '') { + $value = new PHPExcel_RichText(); + + $value->createText($is); + + return $value; + } + +} \ No newline at end of file diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel5/Escher.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel5/Escher.php new file mode 100755 index 0000000..2fcc23b --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Excel5/Escher.php @@ -0,0 +1,640 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Reader_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** + * PHPExcel_Reader_Excel5_Escher + * + * @category PHPExcel + * @package PHPExcel_Reader_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Reader_Excel5_Escher +{ + const DGGCONTAINER = 0xF000; + const BSTORECONTAINER = 0xF001; + const DGCONTAINER = 0xF002; + const SPGRCONTAINER = 0xF003; + const SPCONTAINER = 0xF004; + const DGG = 0xF006; + const BSE = 0xF007; + const DG = 0xF008; + const SPGR = 0xF009; + const SP = 0xF00A; + const OPT = 0xF00B; + const CLIENTTEXTBOX = 0xF00D; + const CLIENTANCHOR = 0xF010; + const CLIENTDATA = 0xF011; + const BLIPJPEG = 0xF01D; + const BLIPPNG = 0xF01E; + const SPLITMENUCOLORS = 0xF11E; + const TERTIARYOPT = 0xF122; + + /** + * Escher stream data (binary) + * + * @var string + */ + private $_data; + + /** + * Size in bytes of the Escher stream data + * + * @var int + */ + private $_dataSize; + + /** + * Current position of stream pointer in Escher stream data + * + * @var int + */ + private $_pos; + + /** + * The object to be returned by the reader. Modified during load. + * + * @var mixed + */ + private $_object; + + /** + * Create a new PHPExcel_Reader_Excel5_Escher instance + * + * @param mixed $object + */ + public function __construct($object) + { + $this->_object = $object; + } + + /** + * Load Escher stream data. May be a partial Escher stream. + * + * @param string $data + */ + public function load($data) + { + $this->_data = $data; + + // total byte size of Excel data (workbook global substream + sheet substreams) + $this->_dataSize = strlen($this->_data); + + $this->_pos = 0; + + // Parse Escher stream + while ($this->_pos < $this->_dataSize) { + + // offset: 2; size: 2: Record Type + $fbt = PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos + 2); + + switch ($fbt) { + case self::DGGCONTAINER: $this->_readDggContainer(); break; + case self::DGG: $this->_readDgg(); break; + case self::BSTORECONTAINER: $this->_readBstoreContainer(); break; + case self::BSE: $this->_readBSE(); break; + case self::BLIPJPEG: $this->_readBlipJPEG(); break; + case self::BLIPPNG: $this->_readBlipPNG(); break; + case self::OPT: $this->_readOPT(); break; + case self::TERTIARYOPT: $this->_readTertiaryOPT(); break; + case self::SPLITMENUCOLORS: $this->_readSplitMenuColors(); break; + case self::DGCONTAINER: $this->_readDgContainer(); break; + case self::DG: $this->_readDg(); break; + case self::SPGRCONTAINER: $this->_readSpgrContainer(); break; + case self::SPCONTAINER: $this->_readSpContainer(); break; + case self::SPGR: $this->_readSpgr(); break; + case self::SP: $this->_readSp(); break; + case self::CLIENTTEXTBOX: $this->_readClientTextbox(); break; + case self::CLIENTANCHOR: $this->_readClientAnchor(); break; + case self::CLIENTDATA: $this->_readClientData(); break; + default: $this->_readDefault(); break; + } + } + + return $this->_object; + } + + /** + * Read a generic record + */ + private function _readDefault() + { + // offset 0; size: 2; recVer and recInstance + $verInstance = PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos); + + // offset: 2; size: 2: Record Type + $fbt = PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos + 2); + + // bit: 0-3; mask: 0x000F; recVer + $recVer = (0x000F & $verInstance) >> 0; + + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + } + + /** + * Read DggContainer record (Drawing Group Container) + */ + private function _readDggContainer() + { + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + + // record is a container, read contents + $dggContainer = new PHPExcel_Shared_Escher_DggContainer(); + $this->_object->setDggContainer($dggContainer); + $reader = new PHPExcel_Reader_Excel5_Escher($dggContainer); + $reader->load($recordData); + } + + /** + * Read Dgg record (Drawing Group) + */ + private function _readDgg() + { + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + } + + /** + * Read BstoreContainer record (Blip Store Container) + */ + private function _readBstoreContainer() + { + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + + // record is a container, read contents + $bstoreContainer = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer(); + $this->_object->setBstoreContainer($bstoreContainer); + $reader = new PHPExcel_Reader_Excel5_Escher($bstoreContainer); + $reader->load($recordData); + } + + /** + * Read BSE record + */ + private function _readBSE() + { + // offset: 0; size: 2; recVer and recInstance + + // bit: 4-15; mask: 0xFFF0; recInstance + $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4; + + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + + // add BSE to BstoreContainer + $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); + $this->_object->addBSE($BSE); + + $BSE->setBLIPType($recInstance); + + // offset: 0; size: 1; btWin32 (MSOBLIPTYPE) + $btWin32 = ord($recordData[0]); + + // offset: 1; size: 1; btWin32 (MSOBLIPTYPE) + $btMacOS = ord($recordData[1]); + + // offset: 2; size: 16; MD4 digest + $rgbUid = substr($recordData, 2, 16); + + // offset: 18; size: 2; tag + $tag = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 18); + + // offset: 20; size: 4; size of BLIP in bytes + $size = PHPExcel_Reader_Excel5::_GetInt4d($recordData, 20); + + // offset: 24; size: 4; number of references to this BLIP + $cRef = PHPExcel_Reader_Excel5::_GetInt4d($recordData, 24); + + // offset: 28; size: 4; MSOFO file offset + $foDelay = PHPExcel_Reader_Excel5::_GetInt4d($recordData, 28); + + // offset: 32; size: 1; unused1 + $unused1 = ord($recordData{32}); + + // offset: 33; size: 1; size of nameData in bytes (including null terminator) + $cbName = ord($recordData{33}); + + // offset: 34; size: 1; unused2 + $unused2 = ord($recordData{34}); + + // offset: 35; size: 1; unused3 + $unused3 = ord($recordData{35}); + + // offset: 36; size: $cbName; nameData + $nameData = substr($recordData, 36, $cbName); + + // offset: 36 + $cbName, size: var; the BLIP data + $blipData = substr($recordData, 36 + $cbName); + + // record is a container, read contents + $reader = new PHPExcel_Reader_Excel5_Escher($BSE); + $reader->load($blipData); + } + + /** + * Read BlipJPEG record. Holds raw JPEG image data + */ + private function _readBlipJPEG() + { + // offset: 0; size: 2; recVer and recInstance + + // bit: 4-15; mask: 0xFFF0; recInstance + $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4; + + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + + $pos = 0; + + // offset: 0; size: 16; rgbUid1 (MD4 digest of) + $rgbUid1 = substr($recordData, 0, 16); + $pos += 16; + + // offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3 + if (in_array($recInstance, array(0x046B, 0x06E3))) { + $rgbUid2 = substr($recordData, 16, 16); + $pos += 16; + } + + // offset: var; size: 1; tag + $tag = ord($recordData{$pos}); + $pos += 1; + + // offset: var; size: var; the raw image data + $data = substr($recordData, $pos); + + $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); + $blip->setData($data); + + $this->_object->setBlip($blip); + } + + /** + * Read BlipPNG record. Holds raw PNG image data + */ + private function _readBlipPNG() + { + // offset: 0; size: 2; recVer and recInstance + + // bit: 4-15; mask: 0xFFF0; recInstance + $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4; + + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + + $pos = 0; + + // offset: 0; size: 16; rgbUid1 (MD4 digest of) + $rgbUid1 = substr($recordData, 0, 16); + $pos += 16; + + // offset: 16; size: 16; rgbUid2 (MD4 digest), only if $recInstance = 0x46B or 0x6E3 + if ($recInstance == 0x06E1) { + $rgbUid2 = substr($recordData, 16, 16); + $pos += 16; + } + + // offset: var; size: 1; tag + $tag = ord($recordData{$pos}); + $pos += 1; + + // offset: var; size: var; the raw image data + $data = substr($recordData, $pos); + + $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); + $blip->setData($data); + + $this->_object->setBlip($blip); + } + + /** + * Read OPT record. This record may occur within DggContainer record or SpContainer + */ + private function _readOPT() + { + // offset: 0; size: 2; recVer and recInstance + + // bit: 4-15; mask: 0xFFF0; recInstance + $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4; + + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + + $this->_readOfficeArtRGFOPTE($recordData, $recInstance); + } + + /** + * Read TertiaryOPT record + */ + private function _readTertiaryOPT() + { + // offset: 0; size: 2; recVer and recInstance + + // bit: 4-15; mask: 0xFFF0; recInstance + $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4; + + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + } + + /** + * Read SplitMenuColors record + */ + private function _readSplitMenuColors() + { + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + } + + /** + * Read DgContainer record (Drawing Container) + */ + private function _readDgContainer() + { + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + + // record is a container, read contents + $dgContainer = new PHPExcel_Shared_Escher_DgContainer(); + $this->_object->setDgContainer($dgContainer); + $reader = new PHPExcel_Reader_Excel5_Escher($dgContainer); + $escher = $reader->load($recordData); + } + + /** + * Read Dg record (Drawing) + */ + private function _readDg() + { + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + } + + /** + * Read SpgrContainer record (Shape Group Container) + */ + private function _readSpgrContainer() + { + // context is either context DgContainer or SpgrContainer + + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + + // record is a container, read contents + $spgrContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer(); + + if ($this->_object instanceof PHPExcel_Shared_Escher_DgContainer) { + // DgContainer + $this->_object->setSpgrContainer($spgrContainer); + } else { + // SpgrContainer + $this->_object->addChild($spgrContainer); + } + + $reader = new PHPExcel_Reader_Excel5_Escher($spgrContainer); + $escher = $reader->load($recordData); + } + + /** + * Read SpContainer record (Shape Container) + */ + private function _readSpContainer() + { + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // add spContainer to spgrContainer + $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); + $this->_object->addChild($spContainer); + + // move stream pointer to next record + $this->_pos += 8 + $length; + + // record is a container, read contents + $reader = new PHPExcel_Reader_Excel5_Escher($spContainer); + $escher = $reader->load($recordData); + } + + /** + * Read Spgr record (Shape Group) + */ + private function _readSpgr() + { + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + } + + /** + * Read Sp record (Shape) + */ + private function _readSp() + { + // offset: 0; size: 2; recVer and recInstance + + // bit: 4-15; mask: 0xFFF0; recInstance + $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4; + + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + } + + /** + * Read ClientTextbox record + */ + private function _readClientTextbox() + { + // offset: 0; size: 2; recVer and recInstance + + // bit: 4-15; mask: 0xFFF0; recInstance + $recInstance = (0xFFF0 & PHPExcel_Reader_Excel5::_GetInt2d($this->_data, $this->_pos)) >> 4; + + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + } + + /** + * Read ClientAnchor record. This record holds information about where the shape is anchored in worksheet + */ + private function _readClientAnchor() + { + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + + // offset: 2; size: 2; upper-left corner column index (0-based) + $c1 = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 2); + + // offset: 4; size: 2; upper-left corner horizontal offset in 1/1024 of column width + $startOffsetX = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 4); + + // offset: 6; size: 2; upper-left corner row index (0-based) + $r1 = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 6); + + // offset: 8; size: 2; upper-left corner vertical offset in 1/256 of row height + $startOffsetY = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 8); + + // offset: 10; size: 2; bottom-right corner column index (0-based) + $c2 = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 10); + + // offset: 12; size: 2; bottom-right corner horizontal offset in 1/1024 of column width + $endOffsetX = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 12); + + // offset: 14; size: 2; bottom-right corner row index (0-based) + $r2 = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 14); + + // offset: 16; size: 2; bottom-right corner vertical offset in 1/256 of row height + $endOffsetY = PHPExcel_Reader_Excel5::_GetInt2d($recordData, 16); + + // set the start coordinates + $this->_object->setStartCoordinates(PHPExcel_Cell::stringFromColumnIndex($c1) . ($r1 + 1)); + + // set the start offsetX + $this->_object->setStartOffsetX($startOffsetX); + + // set the start offsetY + $this->_object->setStartOffsetY($startOffsetY); + + // set the end coordinates + $this->_object->setEndCoordinates(PHPExcel_Cell::stringFromColumnIndex($c2) . ($r2 + 1)); + + // set the end offsetX + $this->_object->setEndOffsetX($endOffsetX); + + // set the end offsetY + $this->_object->setEndOffsetY($endOffsetY); + } + + /** + * Read ClientData record + */ + private function _readClientData() + { + $length = PHPExcel_Reader_Excel5::_GetInt4d($this->_data, $this->_pos + 4); + $recordData = substr($this->_data, $this->_pos + 8, $length); + + // move stream pointer to next record + $this->_pos += 8 + $length; + } + + /** + * Read OfficeArtRGFOPTE table of property-value pairs + * + * @param string $data Binary data + * @param int $n Number of properties + */ + private function _readOfficeArtRGFOPTE($data, $n) { + + $splicedComplexData = substr($data, 6 * $n); + + // loop through property-value pairs + for ($i = 0; $i < $n; ++$i) { + // read 6 bytes at a time + $fopte = substr($data, 6 * $i, 6); + + // offset: 0; size: 2; opid + $opid = PHPExcel_Reader_Excel5::_GetInt2d($fopte, 0); + + // bit: 0-13; mask: 0x3FFF; opid.opid + $opidOpid = (0x3FFF & $opid) >> 0; + + // bit: 14; mask 0x4000; 1 = value in op field is BLIP identifier + $opidFBid = (0x4000 & $opid) >> 14; + + // bit: 15; mask 0x8000; 1 = this is a complex property, op field specifies size of complex data + $opidFComplex = (0x8000 & $opid) >> 15; + + // offset: 2; size: 4; the value for this property + $op = PHPExcel_Reader_Excel5::_GetInt4d($fopte, 2); + + if ($opidFComplex) { + $complexData = substr($splicedComplexData, 0, $op); + $splicedComplexData = substr($splicedComplexData, $op); + + // we store string value with complex data + $value = $complexData; + } else { + // we store integer value + $value = $op; + } + + $this->_object->setOPT($opidOpid, $value); + } + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Exception.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Exception.php new file mode 100755 index 0000000..3ba1c10 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Exception.php @@ -0,0 +1,52 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Reader_Exception + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Reader_Exception extends PHPExcel_Exception { + /** + * Error handler callback + * + * @param mixed $code + * @param mixed $string + * @param mixed $file + * @param mixed $line + * @param mixed $context + */ + public static function errorHandlerCallback($code, $string, $file, $line, $context) { + $e = new self($string, $code); + $e->line = $line; + $e->file = $file; + throw $e; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Gnumeric.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Gnumeric.php new file mode 100755 index 0000000..902c5a5 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/Gnumeric.php @@ -0,0 +1,873 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** PHPExcel root directory */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); +} + +/** + * PHPExcel_Reader_Gnumeric + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Reader_Gnumeric extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader +{ + /** + * Formats + * + * @var array + */ + private $_styles = array(); + + /** + * Shared Expressions + * + * @var array + */ + private $_expressions = array(); + + private $_referenceHelper = null; + + + /** + * Create a new PHPExcel_Reader_Gnumeric + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + $this->_referenceHelper = PHPExcel_ReferenceHelper::getInstance(); + } + + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Check if gzlib functions are available + if (!function_exists('gzread')) { + throw new PHPExcel_Reader_Exception("gzlib library is not enabled"); + } + + // Read signature data (first 3 bytes) + $fh = fopen($pFilename, 'r'); + $data = fread($fh, 2); + fclose($fh); + + if ($data != chr(0x1F).chr(0x8B)) { + return false; + } + + return true; + } + + + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $xml = new XMLReader(); + $xml->open( + 'compress.zlib://'.realpath($pFilename) + ); + $xml->setParserProperty(2,true); + + $worksheetNames = array(); + while ($xml->read()) { + if ($xml->name == 'gnm:SheetName' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $worksheetNames[] = (string) $xml->value; + } elseif ($xml->name == 'gnm:Sheets') { + // break out of the loop once we've got our sheet names rather than parse the entire file + break; + } + } + + return $worksheetNames; + } + + + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $xml = new XMLReader(); + $xml->open( + 'compress.zlib://'.realpath($pFilename) + ); + $xml->setParserProperty(2,true); + + $worksheetInfo = array(); + while ($xml->read()) { + if ($xml->name == 'gnm:Sheet' && $xml->nodeType == XMLReader::ELEMENT) { + $tmpInfo = array( + 'worksheetName' => '', + 'lastColumnLetter' => 'A', + 'lastColumnIndex' => 0, + 'totalRows' => 0, + 'totalColumns' => 0, + ); + + while ($xml->read()) { + if ($xml->name == 'gnm:Name' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $tmpInfo['worksheetName'] = (string) $xml->value; + } elseif ($xml->name == 'gnm:MaxCol' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $tmpInfo['lastColumnIndex'] = (int) $xml->value; + $tmpInfo['totalColumns'] = (int) $xml->value + 1; + } elseif ($xml->name == 'gnm:MaxRow' && $xml->nodeType == XMLReader::ELEMENT) { + $xml->read(); // Move onto the value node + $tmpInfo['totalRows'] = (int) $xml->value + 1; + break; + } + } + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + $worksheetInfo[] = $tmpInfo; + } + } + + return $worksheetInfo; + } + + + private function _gzfileGetContents($filename) { + $file = @gzopen($filename, 'rb'); + if ($file !== false) { + $data = ''; + while (!gzeof($file)) { + $data .= gzread($file, 1024); + } + gzclose($file); + } + return $data; + } + + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $timezoneObj = new DateTimeZone('Europe/London'); + $GMT = new DateTimeZone('UTC'); + + $gFileData = $this->_gzfileGetContents($pFilename); + +// echo '<pre>'; +// echo htmlentities($gFileData,ENT_QUOTES,'UTF-8'); +// echo '</pre><hr />'; +// + $xml = simplexml_load_string($gFileData); + $namespacesMeta = $xml->getNamespaces(true); + +// var_dump($namespacesMeta); +// + $gnmXML = $xml->children($namespacesMeta['gnm']); + + $docProps = $objPHPExcel->getProperties(); + // Document Properties are held differently, depending on the version of Gnumeric + if (isset($namespacesMeta['office'])) { + $officeXML = $xml->children($namespacesMeta['office']); + $officeDocXML = $officeXML->{'document-meta'}; + $officeDocMetaXML = $officeDocXML->meta; + + foreach($officeDocMetaXML as $officePropertyData) { + + $officePropertyDC = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']); + } + foreach($officePropertyDC as $propertyName => $propertyValue) { + $propertyValue = (string) $propertyValue; + switch ($propertyName) { + case 'title' : + $docProps->setTitle(trim($propertyValue)); + break; + case 'subject' : + $docProps->setSubject(trim($propertyValue)); + break; + case 'creator' : + $docProps->setCreator(trim($propertyValue)); + $docProps->setLastModifiedBy(trim($propertyValue)); + break; + case 'date' : + $creationDate = strtotime(trim($propertyValue)); + $docProps->setCreated($creationDate); + $docProps->setModified($creationDate); + break; + case 'description' : + $docProps->setDescription(trim($propertyValue)); + break; + } + } + $officePropertyMeta = array(); + if (isset($namespacesMeta['meta'])) { + $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']); + } + foreach($officePropertyMeta as $propertyName => $propertyValue) { + $attributes = $propertyValue->attributes($namespacesMeta['meta']); + $propertyValue = (string) $propertyValue; + switch ($propertyName) { + case 'keyword' : + $docProps->setKeywords(trim($propertyValue)); + break; + case 'initial-creator' : + $docProps->setCreator(trim($propertyValue)); + $docProps->setLastModifiedBy(trim($propertyValue)); + break; + case 'creation-date' : + $creationDate = strtotime(trim($propertyValue)); + $docProps->setCreated($creationDate); + $docProps->setModified($creationDate); + break; + case 'user-defined' : + list(,$attrName) = explode(':',$attributes['name']); + switch ($attrName) { + case 'publisher' : + $docProps->setCompany(trim($propertyValue)); + break; + case 'category' : + $docProps->setCategory(trim($propertyValue)); + break; + case 'manager' : + $docProps->setManager(trim($propertyValue)); + break; + } + break; + } + } + } + } elseif (isset($gnmXML->Summary)) { + foreach($gnmXML->Summary->Item as $summaryItem) { + $propertyName = $summaryItem->name; + $propertyValue = $summaryItem->{'val-string'}; + switch ($propertyName) { + case 'title' : + $docProps->setTitle(trim($propertyValue)); + break; + case 'comments' : + $docProps->setDescription(trim($propertyValue)); + break; + case 'keywords' : + $docProps->setKeywords(trim($propertyValue)); + break; + case 'category' : + $docProps->setCategory(trim($propertyValue)); + break; + case 'manager' : + $docProps->setManager(trim($propertyValue)); + break; + case 'author' : + $docProps->setCreator(trim($propertyValue)); + $docProps->setLastModifiedBy(trim($propertyValue)); + break; + case 'company' : + $docProps->setCompany(trim($propertyValue)); + break; + } + } + } + + $worksheetID = 0; + foreach($gnmXML->Sheets->Sheet as $sheet) { + $worksheetName = (string) $sheet->Name; +// echo '<b>Worksheet: ',$worksheetName,'</b><br />'; + if ((isset($this->_loadSheetsOnly)) && (!in_array($worksheetName, $this->_loadSheetsOnly))) { + continue; + } + + $maxRow = $maxCol = 0; + + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in formula + // cells... during the load, all formulae should be correct, and we're simply bringing the worksheet + // name in line with the formula, not the reverse + $objPHPExcel->getActiveSheet()->setTitle($worksheetName,false); + + if ((!$this->_readDataOnly) && (isset($sheet->PrintInformation))) { + if (isset($sheet->PrintInformation->Margins)) { + foreach($sheet->PrintInformation->Margins->children('gnm',TRUE) as $key => $margin) { + $marginAttributes = $margin->attributes(); + $marginSize = 72 / 100; // Default + switch($marginAttributes['PrefUnit']) { + case 'mm' : + $marginSize = intval($marginAttributes['Points']) / 100; + break; + } + switch($key) { + case 'top' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setTop($marginSize); + break; + case 'bottom' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setBottom($marginSize); + break; + case 'left' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setLeft($marginSize); + break; + case 'right' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setRight($marginSize); + break; + case 'header' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setHeader($marginSize); + break; + case 'footer' : + $objPHPExcel->getActiveSheet()->getPageMargins()->setFooter($marginSize); + break; + } + } + } + } + + foreach($sheet->Cells->Cell as $cell) { + $cellAttributes = $cell->attributes(); + $row = (int) $cellAttributes->Row + 1; + $column = (int) $cellAttributes->Col; + + if ($row > $maxRow) $maxRow = $row; + if ($column > $maxCol) $maxCol = $column; + + $column = PHPExcel_Cell::stringFromColumnIndex($column); + + // Read cell? + if ($this->getReadFilter() !== NULL) { + if (!$this->getReadFilter()->readCell($column, $row, $worksheetName)) { + continue; + } + } + + $ValueType = $cellAttributes->ValueType; + $ExprID = (string) $cellAttributes->ExprID; +// echo 'Cell ',$column,$row,'<br />'; +// echo 'Type is ',$ValueType,'<br />'; +// echo 'Value is ',$cell,'<br />'; + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; + if ($ExprID > '') { + if (((string) $cell) > '') { + + $this->_expressions[$ExprID] = array( 'column' => $cellAttributes->Col, + 'row' => $cellAttributes->Row, + 'formula' => (string) $cell + ); +// echo 'NEW EXPRESSION ',$ExprID,'<br />'; + } else { + $expression = $this->_expressions[$ExprID]; + + $cell = $this->_referenceHelper->updateFormulaReferences( $expression['formula'], + 'A1', + $cellAttributes->Col - $expression['column'], + $cellAttributes->Row - $expression['row'], + $worksheetName + ); +// echo 'SHARED EXPRESSION ',$ExprID,'<br />'; +// echo 'New Value is ',$cell,'<br />'; + } + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; + } else { + switch($ValueType) { + case '10' : // NULL + $type = PHPExcel_Cell_DataType::TYPE_NULL; + break; + case '20' : // Boolean + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $cell = ($cell == 'TRUE') ? True : False; + break; + case '30' : // Integer + $cell = intval($cell); + case '40' : // Float + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + break; + case '50' : // Error + $type = PHPExcel_Cell_DataType::TYPE_ERROR; + break; + case '60' : // String + $type = PHPExcel_Cell_DataType::TYPE_STRING; + break; + case '70' : // Cell Range + case '80' : // Array + } + } + $objPHPExcel->getActiveSheet()->getCell($column.$row)->setValueExplicit($cell,$type); + } + + if ((!$this->_readDataOnly) && (isset($sheet->Objects))) { + foreach($sheet->Objects->children('gnm',TRUE) as $key => $comment) { + $commentAttributes = $comment->attributes(); + // Only comment objects are handled at the moment + if ($commentAttributes->Text) { + $objPHPExcel->getActiveSheet()->getComment( (string)$commentAttributes->ObjectBound ) + ->setAuthor( (string)$commentAttributes->Author ) + ->setText($this->_parseRichText((string)$commentAttributes->Text) ); + } + } + } +// echo '$maxCol=',$maxCol,'; $maxRow=',$maxRow,'<br />'; +// + foreach($sheet->Styles->StyleRegion as $styleRegion) { + $styleAttributes = $styleRegion->attributes(); + if (($styleAttributes['startRow'] <= $maxRow) && + ($styleAttributes['startCol'] <= $maxCol)) { + + $startColumn = PHPExcel_Cell::stringFromColumnIndex((int) $styleAttributes['startCol']); + $startRow = $styleAttributes['startRow'] + 1; + + $endColumn = ($styleAttributes['endCol'] > $maxCol) ? $maxCol : (int) $styleAttributes['endCol']; + $endColumn = PHPExcel_Cell::stringFromColumnIndex($endColumn); + $endRow = ($styleAttributes['endRow'] > $maxRow) ? $maxRow : $styleAttributes['endRow']; + $endRow += 1; + $cellRange = $startColumn.$startRow.':'.$endColumn.$endRow; +// echo $cellRange,'<br />'; + + $styleAttributes = $styleRegion->Style->attributes(); +// var_dump($styleAttributes); +// echo '<br />'; + + // We still set the number format mask for date/time values, even if _readDataOnly is true + if ((!$this->_readDataOnly) || + (PHPExcel_Shared_Date::isDateTimeFormatCode($styleArray['numberformat']['code']))) { + $styleArray = array(); + $styleArray['numberformat']['code'] = (string) $styleAttributes['Format']; + // If _readDataOnly is false, we set all formatting information + if (!$this->_readDataOnly) { + switch($styleAttributes['HAlign']) { + case '1' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; + break; + case '2' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_LEFT; + break; + case '4' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_RIGHT; + break; + case '8' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_CENTER; + break; + case '16' : + case '64' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS; + break; + case '32' : + $styleArray['alignment']['horizontal'] = PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY; + break; + } + + switch($styleAttributes['VAlign']) { + case '1' : + $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_TOP; + break; + case '2' : + $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_BOTTOM; + break; + case '4' : + $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_CENTER; + break; + case '8' : + $styleArray['alignment']['vertical'] = PHPExcel_Style_Alignment::VERTICAL_JUSTIFY; + break; + } + + $styleArray['alignment']['wrap'] = ($styleAttributes['WrapText'] == '1') ? True : False; + $styleArray['alignment']['shrinkToFit'] = ($styleAttributes['ShrinkToFit'] == '1') ? True : False; + $styleArray['alignment']['indent'] = (intval($styleAttributes["Indent"]) > 0) ? $styleAttributes["indent"] : 0; + + $RGB = self::_parseGnumericColour($styleAttributes["Fore"]); + $styleArray['font']['color']['rgb'] = $RGB; + $RGB = self::_parseGnumericColour($styleAttributes["Back"]); + $shade = $styleAttributes["Shade"]; + if (($RGB != '000000') || ($shade != '0')) { + $styleArray['fill']['color']['rgb'] = $styleArray['fill']['startcolor']['rgb'] = $RGB; + $RGB2 = self::_parseGnumericColour($styleAttributes["PatternColor"]); + $styleArray['fill']['endcolor']['rgb'] = $RGB2; + switch($shade) { + case '1' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_SOLID; + break; + case '2' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR; + break; + case '3' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_GRADIENT_PATH; + break; + case '4' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN; + break; + case '5' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY; + break; + case '6' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID; + break; + case '7' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL; + break; + case '8' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS; + break; + case '9' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKUP; + break; + case '10' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL; + break; + case '11' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625; + break; + case '12' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_GRAY125; + break; + case '13' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN; + break; + case '14' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY; + break; + case '15' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID; + break; + case '16' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL; + break; + case '17' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS; + break; + case '18' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP; + break; + case '19' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL; + break; + case '20' : + $styleArray['fill']['type'] = PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY; + break; + } + } + + $fontAttributes = $styleRegion->Style->Font->attributes(); +// var_dump($fontAttributes); +// echo '<br />'; + $styleArray['font']['name'] = (string) $styleRegion->Style->Font; + $styleArray['font']['size'] = intval($fontAttributes['Unit']); + $styleArray['font']['bold'] = ($fontAttributes['Bold'] == '1') ? True : False; + $styleArray['font']['italic'] = ($fontAttributes['Italic'] == '1') ? True : False; + $styleArray['font']['strike'] = ($fontAttributes['StrikeThrough'] == '1') ? True : False; + switch($fontAttributes['Underline']) { + case '1' : + $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_SINGLE; + break; + case '2' : + $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_DOUBLE; + break; + case '3' : + $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING; + break; + case '4' : + $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING; + break; + default : + $styleArray['font']['underline'] = PHPExcel_Style_Font::UNDERLINE_NONE; + break; + } + switch($fontAttributes['Script']) { + case '1' : + $styleArray['font']['superScript'] = True; + break; + case '-1' : + $styleArray['font']['subScript'] = True; + break; + } + + if (isset($styleRegion->Style->StyleBorder)) { + if (isset($styleRegion->Style->StyleBorder->Top)) { + $styleArray['borders']['top'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Top->attributes()); + } + if (isset($styleRegion->Style->StyleBorder->Bottom)) { + $styleArray['borders']['bottom'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Bottom->attributes()); + } + if (isset($styleRegion->Style->StyleBorder->Left)) { + $styleArray['borders']['left'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Left->attributes()); + } + if (isset($styleRegion->Style->StyleBorder->Right)) { + $styleArray['borders']['right'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Right->attributes()); + } + if ((isset($styleRegion->Style->StyleBorder->Diagonal)) && (isset($styleRegion->Style->StyleBorder->{'Rev-Diagonal'}))) { + $styleArray['borders']['diagonal'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Diagonal->attributes()); + $styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_BOTH; + } elseif (isset($styleRegion->Style->StyleBorder->Diagonal)) { + $styleArray['borders']['diagonal'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->Diagonal->attributes()); + $styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_UP; + } elseif (isset($styleRegion->Style->StyleBorder->{'Rev-Diagonal'})) { + $styleArray['borders']['diagonal'] = self::_parseBorderAttributes($styleRegion->Style->StyleBorder->{'Rev-Diagonal'}->attributes()); + $styleArray['borders']['diagonaldirection'] = PHPExcel_Style_Borders::DIAGONAL_DOWN; + } + } + if (isset($styleRegion->Style->HyperLink)) { + // TO DO + $hyperlink = $styleRegion->Style->HyperLink->attributes(); + } + } +// var_dump($styleArray); +// echo '<br />'; + $objPHPExcel->getActiveSheet()->getStyle($cellRange)->applyFromArray($styleArray); + } + } + } + + if ((!$this->_readDataOnly) && (isset($sheet->Cols))) { + // Column Widths + $columnAttributes = $sheet->Cols->attributes(); + $defaultWidth = $columnAttributes['DefaultSizePts'] / 5.4; + $c = 0; + foreach($sheet->Cols->ColInfo as $columnOverride) { + $columnAttributes = $columnOverride->attributes(); + $column = $columnAttributes['No']; + $columnWidth = $columnAttributes['Unit'] / 5.4; + $hidden = ((isset($columnAttributes['Hidden'])) && ($columnAttributes['Hidden'] == '1')) ? true : false; + $columnCount = (isset($columnAttributes['Count'])) ? $columnAttributes['Count'] : 1; + while ($c < $column) { + $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($defaultWidth); + ++$c; + } + while (($c < ($column+$columnCount)) && ($c <= $maxCol)) { + $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($columnWidth); + if ($hidden) { + $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setVisible(false); + } + ++$c; + } + } + while ($c <= $maxCol) { + $objPHPExcel->getActiveSheet()->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($c))->setWidth($defaultWidth); + ++$c; + } + } + + if ((!$this->_readDataOnly) && (isset($sheet->Rows))) { + // Row Heights + $rowAttributes = $sheet->Rows->attributes(); + $defaultHeight = $rowAttributes['DefaultSizePts']; + $r = 0; + + foreach($sheet->Rows->RowInfo as $rowOverride) { + $rowAttributes = $rowOverride->attributes(); + $row = $rowAttributes['No']; + $rowHeight = $rowAttributes['Unit']; + $hidden = ((isset($rowAttributes['Hidden'])) && ($rowAttributes['Hidden'] == '1')) ? true : false; + $rowCount = (isset($rowAttributes['Count'])) ? $rowAttributes['Count'] : 1; + while ($r < $row) { + ++$r; + $objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($defaultHeight); + } + while (($r < ($row+$rowCount)) && ($r < $maxRow)) { + ++$r; + $objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($rowHeight); + if ($hidden) { + $objPHPExcel->getActiveSheet()->getRowDimension($r)->setVisible(false); + } + } + } + while ($r < $maxRow) { + ++$r; + $objPHPExcel->getActiveSheet()->getRowDimension($r)->setRowHeight($defaultHeight); + } + } + + // Handle Merged Cells in this worksheet + if (isset($sheet->MergedRegions)) { + foreach($sheet->MergedRegions->Merge as $mergeCells) { + if (strpos($mergeCells,':') !== FALSE) { + $objPHPExcel->getActiveSheet()->mergeCells($mergeCells); + } + } + } + + $worksheetID++; + } + + // Loop through definedNames (global named ranges) + if (isset($gnmXML->Names)) { + foreach($gnmXML->Names->Name as $namedRange) { + $name = (string) $namedRange->name; + $range = (string) $namedRange->value; + if (stripos($range, '#REF!') !== false) { + continue; + } + + $range = explode('!',$range); + $range[0] = trim($range[0],"'");; + if ($worksheet = $objPHPExcel->getSheetByName($range[0])) { + $extractedRange = str_replace('$', '', $range[1]); + $objPHPExcel->addNamedRange( new PHPExcel_NamedRange($name, $worksheet, $extractedRange) ); + } + } + } + + + // Return + return $objPHPExcel; + } + + + private static function _parseBorderAttributes($borderAttributes) + { + $styleArray = array(); + + if (isset($borderAttributes["Color"])) { + $RGB = self::_parseGnumericColour($borderAttributes["Color"]); + $styleArray['color']['rgb'] = $RGB; + } + + switch ($borderAttributes["Style"]) { + case '0' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_NONE; + break; + case '1' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case '2' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUM; + break; + case '4' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHED; + break; + case '5' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_THICK; + break; + case '6' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_DOUBLE; + break; + case '7' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_DOTTED; + break; + case '9' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHDOT; + break; + case '10' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT; + break; + case '11' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_DASHDOTDOT; + break; + case '12' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT; + break; + case '13' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT; + break; + case '3' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_SLANTDASHDOT; + break; + case '8' : + $styleArray['style'] = PHPExcel_Style_Border::BORDER_MEDIUMDASHED; + break; + } + return $styleArray; + } + + + private function _parseRichText($is = '') { + $value = new PHPExcel_RichText(); + + $value->createText($is); + + return $value; + } + + + private static function _parseGnumericColour($gnmColour) { + list($gnmR,$gnmG,$gnmB) = explode(':',$gnmColour); + $gnmR = substr(str_pad($gnmR,4,'0',STR_PAD_RIGHT),0,2); + $gnmG = substr(str_pad($gnmG,4,'0',STR_PAD_RIGHT),0,2); + $gnmB = substr(str_pad($gnmB,4,'0',STR_PAD_RIGHT),0,2); + $RGB = $gnmR.$gnmG.$gnmB; +// echo 'Excel Colour: ',$RGB,'<br />'; + return $RGB; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/HTML.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/HTML.php new file mode 100755 index 0000000..c5e6af9 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/HTML.php @@ -0,0 +1,468 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** PHPExcel root directory */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); +} + +/** + * PHPExcel_Reader_HTML + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Reader_HTML extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader +{ + /** + * Input encoding + * + * @var string + */ + private $_inputEncoding = 'ANSI'; + + /** + * Sheet index to read + * + * @var int + */ + private $_sheetIndex = 0; + + /** + * Formats + * + * @var array + */ + private $_formats = array( 'h1' => array( 'font' => array( 'bold' => true, + 'size' => 24, + ), + ), // Bold, 24pt + 'h2' => array( 'font' => array( 'bold' => true, + 'size' => 18, + ), + ), // Bold, 18pt + 'h3' => array( 'font' => array( 'bold' => true, + 'size' => 13.5, + ), + ), // Bold, 13.5pt + 'h4' => array( 'font' => array( 'bold' => true, + 'size' => 12, + ), + ), // Bold, 12pt + 'h5' => array( 'font' => array( 'bold' => true, + 'size' => 10, + ), + ), // Bold, 10pt + 'h6' => array( 'font' => array( 'bold' => true, + 'size' => 7.5, + ), + ), // Bold, 7.5pt + 'a' => array( 'font' => array( 'underline' => true, + 'color' => array( 'argb' => PHPExcel_Style_Color::COLOR_BLUE, + ), + ), + ), // Blue underlined + 'hr' => array( 'borders' => array( 'bottom' => array( 'style' => PHPExcel_Style_Border::BORDER_THIN, + 'color' => array( PHPExcel_Style_Color::COLOR_BLACK, + ), + ), + ), + ), // Bottom border + ); + + + /** + * Create a new PHPExcel_Reader_HTML + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + /** + * Validate that the current file is an HTML file + * + * @return boolean + */ + protected function _isValidFormat() + { + // Reading 2048 bytes should be enough to validate that the format is HTML + $data = fread($this->_fileHandle, 2048); + if ((strpos('<',$data) !== FALSE) && + (strlen($data) !== strlen(strip_tags($data)))) { + return TRUE; + } + + return FALSE; + } + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + /** + * Set input encoding + * + * @param string $pValue Input encoding + */ + public function setInputEncoding($pValue = 'ANSI') + { + $this->_inputEncoding = $pValue; + return $this; + } + + /** + * Get input encoding + * + * @return string + */ + public function getInputEncoding() + { + return $this->_inputEncoding; + } + + // Data Array used for testing only, should write to PHPExcel object on completion of tests + private $_dataArray = array(); + + private $_tableLevel = 0; + private $_nestedColumn = array('A'); + + private function _setTableStartColumn($column) { + if ($this->_tableLevel == 0) + $column = 'A'; + ++$this->_tableLevel; + $this->_nestedColumn[$this->_tableLevel] = $column; + + return $this->_nestedColumn[$this->_tableLevel]; + } + + private function _getTableStartColumn() { + return $this->_nestedColumn[$this->_tableLevel]; + } + + private function _releaseTableStartColumn() { + --$this->_tableLevel; + return array_pop($this->_nestedColumn); + } + + private function _flushCell($sheet,$column,$row,&$cellContent) { + if (is_string($cellContent)) { + // Simple String content + if (trim($cellContent) > '') { + // Only actually write it if there's content in the string +// echo 'FLUSH CELL: ' , $column , $row , ' => ' , $cellContent , '<br />'; + // Write to worksheet to be done here... + // ... we return the cell so we can mess about with styles more easily + $cell = $sheet->setCellValue($column.$row,$cellContent,true); + $this->_dataArray[$row][$column] = $cellContent; + } + } else { + // We have a Rich Text run + // TODO + $this->_dataArray[$row][$column] = 'RICH TEXT: ' . $cellContent; + } + $cellContent = (string) ''; + } + + private function _processDomElement(DOMNode $element, $sheet, &$row, &$column, &$cellContent){ + foreach($element->childNodes as $child){ + if ($child instanceof DOMText) { + $domText = preg_replace('/\s+/',' ',trim($child->nodeValue)); + if (is_string($cellContent)) { + // simply append the text if the cell content is a plain text string + $cellContent .= $domText; + } else { + // but if we have a rich text run instead, we need to append it correctly + // TODO + } + } elseif($child instanceof DOMElement) { +// echo '<b>DOM ELEMENT: </b>' , strtoupper($child->nodeName) , '<br />'; + + $attributeArray = array(); + foreach($child->attributes as $attribute) { +// echo '<b>ATTRIBUTE: </b>' , $attribute->name , ' => ' , $attribute->value , '<br />'; + $attributeArray[$attribute->name] = $attribute->value; + } + + switch($child->nodeName) { + case 'meta' : + foreach($attributeArray as $attributeName => $attributeValue) { + switch($attributeName) { + case 'content': + // TODO + // Extract character set, so we can convert to UTF-8 if required + break; + } + } + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); + break; + case 'title' : + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); + $sheet->setTitle($cellContent); + $cellContent = ''; + break; + case 'span' : + case 'div' : + case 'font' : + case 'i' : + case 'em' : + case 'strong': + case 'b' : +// echo 'STYLING, SPAN OR DIV<br />'; + if ($cellContent > '') + $cellContent .= ' '; + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); + if ($cellContent > '') + $cellContent .= ' '; +// echo 'END OF STYLING, SPAN OR DIV<br />'; + break; + case 'hr' : + $this->_flushCell($sheet,$column,$row,$cellContent); + ++$row; + if (isset($this->_formats[$child->nodeName])) { + $sheet->getStyle($column.$row)->applyFromArray($this->_formats[$child->nodeName]); + } else { + $cellContent = '----------'; + $this->_flushCell($sheet,$column,$row,$cellContent); + } + ++$row; + case 'br' : + if ($this->_tableLevel > 0) { + // If we're inside a table, replace with a \n + $cellContent .= "\n"; + } else { + // Otherwise flush our existing content and move the row cursor on + $this->_flushCell($sheet,$column,$row,$cellContent); + ++$row; + } +// echo 'HARD LINE BREAK: ' , '<br />'; + break; + case 'a' : +// echo 'START OF HYPERLINK: ' , '<br />'; + foreach($attributeArray as $attributeName => $attributeValue) { + switch($attributeName) { + case 'href': +// echo 'Link to ' , $attributeValue , '<br />'; + $sheet->getCell($column.$row)->getHyperlink()->setUrl($attributeValue); + if (isset($this->_formats[$child->nodeName])) { + $sheet->getStyle($column.$row)->applyFromArray($this->_formats[$child->nodeName]); + } + break; + } + } + $cellContent .= ' '; + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); +// echo 'END OF HYPERLINK:' , '<br />'; + break; + case 'h1' : + case 'h2' : + case 'h3' : + case 'h4' : + case 'h5' : + case 'h6' : + case 'ol' : + case 'ul' : + case 'p' : + if ($this->_tableLevel > 0) { + // If we're inside a table, replace with a \n + $cellContent .= "\n"; +// echo 'LIST ENTRY: ' , '<br />'; + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); +// echo 'END OF LIST ENTRY:' , '<br />'; + } else { + if ($cellContent > '') { + $this->_flushCell($sheet,$column,$row,$cellContent); + $row += 2; + } +// echo 'START OF PARAGRAPH: ' , '<br />'; + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); +// echo 'END OF PARAGRAPH:' , '<br />'; + $this->_flushCell($sheet,$column,$row,$cellContent); + + if (isset($this->_formats[$child->nodeName])) { + $sheet->getStyle($column.$row)->applyFromArray($this->_formats[$child->nodeName]); + } + + $row += 2; + $column = 'A'; + } + break; + case 'li' : + if ($this->_tableLevel > 0) { + // If we're inside a table, replace with a \n + $cellContent .= "\n"; +// echo 'LIST ENTRY: ' , '<br />'; + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); +// echo 'END OF LIST ENTRY:' , '<br />'; + } else { + if ($cellContent > '') { + $this->_flushCell($sheet,$column,$row,$cellContent); + } + ++$row; +// echo 'LIST ENTRY: ' , '<br />'; + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); +// echo 'END OF LIST ENTRY:' , '<br />'; + $this->_flushCell($sheet,$column,$row,$cellContent); + $column = 'A'; + } + break; + case 'table' : + $this->_flushCell($sheet,$column,$row,$cellContent); + $column = $this->_setTableStartColumn($column); +// echo 'START OF TABLE LEVEL ' , $this->_tableLevel , '<br />'; + if ($this->_tableLevel > 1) + --$row; + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); +// echo 'END OF TABLE LEVEL ' , $this->_tableLevel , '<br />'; + $column = $this->_releaseTableStartColumn(); + if ($this->_tableLevel > 1) { + ++$column; + } else { + ++$row; + } + break; + case 'thead' : + case 'tbody' : + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); + break; + case 'tr' : + ++$row; + $column = $this->_getTableStartColumn(); + $cellContent = ''; +// echo 'START OF TABLE ' , $this->_tableLevel , ' ROW<br />'; + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); +// echo 'END OF TABLE ' , $this->_tableLevel , ' ROW<br />'; + break; + case 'th' : + case 'td' : +// echo 'START OF TABLE ' , $this->_tableLevel , ' CELL<br />'; + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); +// echo 'END OF TABLE ' , $this->_tableLevel , ' CELL<br />'; + $this->_flushCell($sheet,$column,$row,$cellContent); + ++$column; + break; + case 'body' : + $row = 1; + $column = 'A'; + $content = ''; + $this->_tableLevel = 0; + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); + break; + default: + $this->_processDomElement($child,$sheet,$row,$column,$cellContent); + } + } + } + } + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Open file to validate + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid HTML file."); + } + // Close after validating + fclose ($this->_fileHandle); + + // Create new PHPExcel + while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { + $objPHPExcel->createSheet(); + } + $objPHPExcel->setActiveSheetIndex( $this->_sheetIndex ); + + // Create a new DOM object + $dom = new domDocument; + // Reload the HTML file into the DOM object + $loaded = $dom->loadHTMLFile($pFilename); + if ($loaded === FALSE) { + throw new PHPExcel_Reader_Exception('Failed to load ',$pFilename,' as a DOM Document'); + } + + // Discard white space + $dom->preserveWhiteSpace = false; + + + $row = 0; + $column = 'A'; + $content = ''; + $this->_processDomElement($dom,$objPHPExcel->getActiveSheet(),$row,$column,$content); + +// echo '<hr />'; +// var_dump($this->_dataArray); + + // Return + return $objPHPExcel; + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Reader_HTML + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/IReadFilter.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/IReadFilter.php new file mode 100755 index 0000000..bee2b40 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/IReadFilter.php @@ -0,0 +1,47 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Reader_IReadFilter + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +interface PHPExcel_Reader_IReadFilter +{ + /** + * Should this cell be read? + * + * @param $column String column index + * @param $row Row index + * @param $worksheetName Optional worksheet name + * @return boolean + */ + public function readCell($column, $row, $worksheetName = ''); +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/IReader.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/IReader.php new file mode 100755 index 0000000..a064731 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/IReader.php @@ -0,0 +1,53 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Reader_IReader + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +interface PHPExcel_Reader_IReader +{ + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + */ + public function canRead($pFilename); + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename); +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/OOCalc.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/OOCalc.php new file mode 100755 index 0000000..4bd4933 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/OOCalc.php @@ -0,0 +1,695 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** PHPExcel root directory */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); +} + +/** + * PHPExcel_Reader_OOCalc + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Reader_OOCalc extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader +{ + /** + * Formats + * + * @var array + */ + private $_styles = array(); + + + /** + * Create a new PHPExcel_Reader_OOCalc + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + + /** + * Can the current PHPExcel_Reader_IReader read the file? + * + * @param string $pFilename + * @return boolean + * @throws PHPExcel_Reader_Exception + */ + public function canRead($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + // Check if zip class exists + if (!class_exists('ZipArchive',FALSE)) { + throw new PHPExcel_Reader_Exception("ZipArchive library is not enabled"); + } + + $mimeType = 'UNKNOWN'; + // Load file + $zip = new ZipArchive; + if ($zip->open($pFilename) === true) { + // check if it is an OOXML archive + $stat = $zip->statName('mimetype'); + if ($stat && ($stat['size'] <= 255)) { + $mimeType = $zip->getFromName($stat['name']); + } elseif($stat = $zip->statName('META-INF/manifest.xml')) { + $xml = simplexml_load_string($zip->getFromName('META-INF/manifest.xml')); + $namespacesContent = $xml->getNamespaces(true); + if (isset($namespacesContent['manifest'])) { + $manifest = $xml->children($namespacesContent['manifest']); + foreach($manifest as $manifestDataSet) { + $manifestAttributes = $manifestDataSet->attributes($namespacesContent['manifest']); + if ($manifestAttributes->{'full-path'} == '/') { + $mimeType = (string) $manifestAttributes->{'media-type'}; + break; + } + } + } + } + + $zip->close(); + + return ($mimeType === 'application/vnd.oasis.opendocument.spreadsheet'); + } + + return FALSE; + } + + + /** + * Reads names of the worksheets from a file, without parsing the whole file to a PHPExcel object + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetNames($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $zip = new ZipArchive; + if (!$zip->open($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); + } + + $worksheetNames = array(); + + $xml = new XMLReader(); + $res = $xml->open('zip://'.realpath($pFilename).'#content.xml'); + $xml->setParserProperty(2,true); + + // Step into the first level of content of the XML + $xml->read(); + while ($xml->read()) { + // Quickly jump through to the office:body node + while ($xml->name !== 'office:body') { + if ($xml->isEmptyElement) + $xml->read(); + else + $xml->next(); + } + // Now read each node until we find our first table:table node + while ($xml->read()) { + if ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) { + // Loop through each table:table node reading the table:name attribute for each worksheet name + do { + $worksheetNames[] = $xml->getAttribute('table:name'); + $xml->next(); + } while ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT); + } + } + } + + return $worksheetNames; + } + + + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $worksheetInfo = array(); + + $zip = new ZipArchive; + if (!$zip->open($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); + } + + $xml = new XMLReader(); + $res = $xml->open('zip://'.realpath($pFilename).'#content.xml'); + $xml->setParserProperty(2,true); + + // Step into the first level of content of the XML + $xml->read(); + while ($xml->read()) { + // Quickly jump through to the office:body node + while ($xml->name !== 'office:body') { + if ($xml->isEmptyElement) + $xml->read(); + else + $xml->next(); + } + // Now read each node until we find our first table:table node + while ($xml->read()) { + if ($xml->name == 'table:table' && $xml->nodeType == XMLReader::ELEMENT) { + $worksheetNames[] = $xml->getAttribute('table:name'); + + $tmpInfo = array( + 'worksheetName' => $xml->getAttribute('table:name'), + 'lastColumnLetter' => 'A', + 'lastColumnIndex' => 0, + 'totalRows' => 0, + 'totalColumns' => 0, + ); + + // Loop through each child node of the table:table element reading + $currCells = 0; + do { + $xml->read(); + if ($xml->name == 'table:table-row' && $xml->nodeType == XMLReader::ELEMENT) { + $rowspan = $xml->getAttribute('table:number-rows-repeated'); + $rowspan = empty($rowspan) ? 1 : $rowspan; + $tmpInfo['totalRows'] += $rowspan; + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $currCells = 0; + // Step into the row + $xml->read(); + do { + if ($xml->name == 'table:table-cell' && $xml->nodeType == XMLReader::ELEMENT) { + if (!$xml->isEmptyElement) { + $currCells++; + $xml->next(); + } else { + $xml->read(); + } + } elseif ($xml->name == 'table:covered-table-cell' && $xml->nodeType == XMLReader::ELEMENT) { + $mergeSize = $xml->getAttribute('table:number-columns-repeated'); + $currCells += $mergeSize; + $xml->read(); + } + } while ($xml->name != 'table:table-row'); + } + } while ($xml->name != 'table:table'); + + $tmpInfo['totalColumns'] = max($tmpInfo['totalColumns'],$currCells); + $tmpInfo['lastColumnIndex'] = $tmpInfo['totalColumns'] - 1; + $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); + $worksheetInfo[] = $tmpInfo; + } + } + +// foreach($workbookData->table as $worksheetDataSet) { +// $worksheetData = $worksheetDataSet->children($namespacesContent['table']); +// $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); +// +// $rowIndex = 0; +// foreach ($worksheetData as $key => $rowData) { +// switch ($key) { +// case 'table-row' : +// $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); +// $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? +// $rowDataTableAttributes['number-rows-repeated'] : 1; +// $columnIndex = 0; +// +// foreach ($rowData as $key => $cellData) { +// $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); +// $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? +// $cellDataTableAttributes['number-columns-repeated'] : 1; +// $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); +// if (isset($cellDataOfficeAttributes['value-type'])) { +// $tmpInfo['lastColumnIndex'] = max($tmpInfo['lastColumnIndex'], $columnIndex + $colRepeats - 1); +// $tmpInfo['totalRows'] = max($tmpInfo['totalRows'], $rowIndex + $rowRepeats); +// } +// $columnIndex += $colRepeats; +// } +// $rowIndex += $rowRepeats; +// break; +// } +// } +// +// $tmpInfo['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($tmpInfo['lastColumnIndex']); +// $tmpInfo['totalColumns'] = $tmpInfo['lastColumnIndex'] + 1; +// +// } +// } + } + + return $worksheetInfo; + } + + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + + private static function identifyFixedStyleValue($styleList,&$styleAttributeValue) { + $styleAttributeValue = strtolower($styleAttributeValue); + foreach($styleList as $style) { + if ($styleAttributeValue == strtolower($style)) { + $styleAttributeValue = $style; + return true; + } + } + return false; + } + + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Check if file exists + if (!file_exists($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! File does not exist."); + } + + $timezoneObj = new DateTimeZone('Europe/London'); + $GMT = new DateTimeZone('UTC'); + + $zip = new ZipArchive; + if (!$zip->open($pFilename)) { + throw new PHPExcel_Reader_Exception("Could not open " . $pFilename . " for reading! Error opening file."); + } + +// echo '<h1>Meta Information</h1>'; + $xml = simplexml_load_string($zip->getFromName("meta.xml")); + $namespacesMeta = $xml->getNamespaces(true); +// echo '<pre>'; +// print_r($namespacesMeta); +// echo '</pre><hr />'; + + $docProps = $objPHPExcel->getProperties(); + $officeProperty = $xml->children($namespacesMeta['office']); + foreach($officeProperty as $officePropertyData) { + $officePropertyDC = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyDC = $officePropertyData->children($namespacesMeta['dc']); + } + foreach($officePropertyDC as $propertyName => $propertyValue) { + switch ($propertyName) { + case 'title' : + $docProps->setTitle($propertyValue); + break; + case 'subject' : + $docProps->setSubject($propertyValue); + break; + case 'creator' : + $docProps->setCreator($propertyValue); + $docProps->setLastModifiedBy($propertyValue); + break; + case 'date' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + $docProps->setModified($creationDate); + break; + case 'description' : + $docProps->setDescription($propertyValue); + break; + } + } + $officePropertyMeta = array(); + if (isset($namespacesMeta['dc'])) { + $officePropertyMeta = $officePropertyData->children($namespacesMeta['meta']); + } + foreach($officePropertyMeta as $propertyName => $propertyValue) { + $propertyValueAttributes = $propertyValue->attributes($namespacesMeta['meta']); + switch ($propertyName) { + case 'initial-creator' : + $docProps->setCreator($propertyValue); + break; + case 'keyword' : + $docProps->setKeywords($propertyValue); + break; + case 'creation-date' : + $creationDate = strtotime($propertyValue); + $docProps->setCreated($creationDate); + break; + case 'user-defined' : + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; + foreach ($propertyValueAttributes as $key => $value) { + if ($key == 'name') { + $propertyValueName = (string) $value; + } elseif($key == 'value-type') { + switch ($value) { + case 'date' : + $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'date'); + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_DATE; + break; + case 'boolean' : + $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'bool'); + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_BOOLEAN; + break; + case 'float' : + $propertyValue = PHPExcel_DocumentProperties::convertProperty($propertyValue,'r4'); + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_FLOAT; + break; + default : + $propertyValueType = PHPExcel_DocumentProperties::PROPERTY_TYPE_STRING; + } + } + } + $docProps->setCustomProperty($propertyValueName,$propertyValue,$propertyValueType); + break; + } + } + } + + +// echo '<h1>Workbook Content</h1>'; + $xml = simplexml_load_string($zip->getFromName("content.xml")); + $namespacesContent = $xml->getNamespaces(true); +// echo '<pre>'; +// print_r($namespacesContent); +// echo '</pre><hr />'; + + $workbook = $xml->children($namespacesContent['office']); + foreach($workbook->body->spreadsheet as $workbookData) { + $workbookData = $workbookData->children($namespacesContent['table']); + $worksheetID = 0; + foreach($workbookData->table as $worksheetDataSet) { + $worksheetData = $worksheetDataSet->children($namespacesContent['table']); +// print_r($worksheetData); +// echo '<br />'; + $worksheetDataAttributes = $worksheetDataSet->attributes($namespacesContent['table']); +// print_r($worksheetDataAttributes); +// echo '<br />'; + if ((isset($this->_loadSheetsOnly)) && (isset($worksheetDataAttributes['name'])) && + (!in_array($worksheetDataAttributes['name'], $this->_loadSheetsOnly))) { + continue; + } + +// echo '<h2>Worksheet '.$worksheetDataAttributes['name'].'</h2>'; + // Create new Worksheet + $objPHPExcel->createSheet(); + $objPHPExcel->setActiveSheetIndex($worksheetID); + if (isset($worksheetDataAttributes['name'])) { + $worksheetName = (string) $worksheetDataAttributes['name']; + // Use false for $updateFormulaCellReferences to prevent adjustment of worksheet references in + // formula cells... during the load, all formulae should be correct, and we're simply + // bringing the worksheet name in line with the formula, not the reverse + $objPHPExcel->getActiveSheet()->setTitle($worksheetName,false); + } + + $rowID = 1; + foreach($worksheetData as $key => $rowData) { +// echo '<b>'.$key.'</b><br />'; + switch ($key) { + case 'table-header-rows': + foreach ($rowData as $key=>$cellData) { + $rowData = $cellData; + break; + } + case 'table-row' : + $rowDataTableAttributes = $rowData->attributes($namespacesContent['table']); + $rowRepeats = (isset($rowDataTableAttributes['number-rows-repeated'])) ? + $rowDataTableAttributes['number-rows-repeated'] : 1; + $columnID = 'A'; + foreach($rowData as $key => $cellData) { + if ($this->getReadFilter() !== NULL) { + if (!$this->getReadFilter()->readCell($columnID, $rowID, $worksheetName)) { + continue; + } + } + +// echo '<b>'.$columnID.$rowID.'</b><br />'; + $cellDataText = (isset($namespacesContent['text'])) ? + $cellData->children($namespacesContent['text']) : + ''; + $cellDataOffice = $cellData->children($namespacesContent['office']); + $cellDataOfficeAttributes = $cellData->attributes($namespacesContent['office']); + $cellDataTableAttributes = $cellData->attributes($namespacesContent['table']); + +// echo 'Office Attributes: '; +// print_r($cellDataOfficeAttributes); +// echo '<br />Table Attributes: '; +// print_r($cellDataTableAttributes); +// echo '<br />Cell Data Text'; +// print_r($cellDataText); +// echo '<br />'; +// + $type = $formatting = $hyperlink = null; + $hasCalculatedValue = false; + $cellDataFormula = ''; + if (isset($cellDataTableAttributes['formula'])) { + $cellDataFormula = $cellDataTableAttributes['formula']; + $hasCalculatedValue = true; + } + + if (isset($cellDataOffice->annotation)) { +// echo 'Cell has comment<br />'; + $annotationText = $cellDataOffice->annotation->children($namespacesContent['text']); + $textArray = array(); + foreach($annotationText as $t) { + foreach($t->span as $text) { + $textArray[] = (string)$text; + } + } + $text = implode("\n",$textArray); +// echo $text,'<br />'; + $objPHPExcel->getActiveSheet()->getComment( $columnID.$rowID ) +// ->setAuthor( $author ) + ->setText($this->_parseRichText($text) ); + } + + if (isset($cellDataText->p)) { + // Consolidate if there are multiple p records (maybe with spans as well) + $dataArray = array(); + // Text can have multiple text:p and within those, multiple text:span. + // text:p newlines, but text:span does not. + // Also, here we assume there is no text data is span fields are specified, since + // we have no way of knowing proper positioning anyway. + foreach ($cellDataText->p as $pData) { + if (isset($pData->span)) { + // span sections do not newline, so we just create one large string here + $spanSection = ""; + foreach ($pData->span as $spanData) { + $spanSection .= $spanData; + } + array_push($dataArray, $spanSection); + } else { + array_push($dataArray, $pData); + } + } + $allCellDataText = implode($dataArray, "\n"); + +// echo 'Value Type is '.$cellDataOfficeAttributes['value-type'].'<br />'; + switch ($cellDataOfficeAttributes['value-type']) { + case 'string' : + $type = PHPExcel_Cell_DataType::TYPE_STRING; + $dataValue = $allCellDataText; + if (isset($dataValue->a)) { + $dataValue = $dataValue->a; + $cellXLinkAttributes = $dataValue->attributes($namespacesContent['xlink']); + $hyperlink = $cellXLinkAttributes['href']; + } + break; + case 'boolean' : + $type = PHPExcel_Cell_DataType::TYPE_BOOL; + $dataValue = ($allCellDataText == 'TRUE') ? True : False; + break; + case 'percentage' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = (float) $cellDataOfficeAttributes['value']; + if (floor($dataValue) == $dataValue) { + $dataValue = (integer) $dataValue; + } + $formatting = PHPExcel_Style_NumberFormat::FORMAT_PERCENTAGE_00; + break; + case 'currency' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = (float) $cellDataOfficeAttributes['value']; + if (floor($dataValue) == $dataValue) { + $dataValue = (integer) $dataValue; + } + $formatting = PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE; + break; + case 'float' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = (float) $cellDataOfficeAttributes['value']; + if (floor($dataValue) == $dataValue) { + if ($dataValue = (integer) $dataValue) + $dataValue = (integer) $dataValue; + else + $dataValue = (float) $dataValue; + } + break; + case 'date' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dateObj = new DateTime($cellDataOfficeAttributes['date-value'], $GMT); + $dateObj->setTimeZone($timezoneObj); + list($year,$month,$day,$hour,$minute,$second) = explode(' ',$dateObj->format('Y m d H i s')); + $dataValue = PHPExcel_Shared_Date::FormattedPHPToExcel($year,$month,$day,$hour,$minute,$second); + if ($dataValue != floor($dataValue)) { + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15.' '.PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; + } else { + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15; + } + break; + case 'time' : + $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; + $dataValue = PHPExcel_Shared_Date::PHPToExcel(strtotime('01-01-1970 '.implode(':',sscanf($cellDataOfficeAttributes['time-value'],'PT%dH%dM%dS')))); + $formatting = PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4; + break; + } +// echo 'Data value is '.$dataValue.'<br />'; +// if ($hyperlink !== NULL) { +// echo 'Hyperlink is '.$hyperlink.'<br />'; +// } + } else { + $type = PHPExcel_Cell_DataType::TYPE_NULL; + $dataValue = NULL; + } + + if ($hasCalculatedValue) { + $type = PHPExcel_Cell_DataType::TYPE_FORMULA; +// echo 'Formula: '.$cellDataFormula.'<br />'; + $cellDataFormula = substr($cellDataFormula,strpos($cellDataFormula,':=')+1); + $temp = explode('"',$cellDataFormula); + $tKey = false; + foreach($temp as &$value) { + // Only replace in alternate array entries (i.e. non-quoted blocks) + if ($tKey = !$tKey) { + $value = preg_replace('/\[\.(.*):\.(.*)\]/Ui','$1:$2',$value); + $value = preg_replace('/\[\.(.*)\]/Ui','$1',$value); + $value = PHPExcel_Calculation::_translateSeparator(';',',',$value,$inBraces); + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); +// echo 'Adjusted Formula: '.$cellDataFormula.'<br />'; + } + + $colRepeats = (isset($cellDataTableAttributes['number-columns-repeated'])) ? + $cellDataTableAttributes['number-columns-repeated'] : 1; + if ($type !== NULL) { + for ($i = 0; $i < $colRepeats; ++$i) { + if ($i > 0) { + ++$columnID; + } + if ($type !== PHPExcel_Cell_DataType::TYPE_NULL) { + for ($rowAdjust = 0; $rowAdjust < $rowRepeats; ++$rowAdjust) { + $rID = $rowID + $rowAdjust; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setValueExplicit((($hasCalculatedValue) ? $cellDataFormula : $dataValue),$type); + if ($hasCalculatedValue) { +// echo 'Forumla result is '.$dataValue.'<br />'; + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->setCalculatedValue($dataValue); + } + if ($formatting !== NULL) { + $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode($formatting); + } else { + $objPHPExcel->getActiveSheet()->getStyle($columnID.$rID)->getNumberFormat()->setFormatCode(PHPExcel_Style_NumberFormat::FORMAT_GENERAL); + } + if ($hyperlink !== NULL) { + $objPHPExcel->getActiveSheet()->getCell($columnID.$rID)->getHyperlink()->setUrl($hyperlink); + } + } + } + } + } + + // Merged cells + if ((isset($cellDataTableAttributes['number-columns-spanned'])) || (isset($cellDataTableAttributes['number-rows-spanned']))) { + if (($type !== PHPExcel_Cell_DataType::TYPE_NULL) || (!$this->_readDataOnly)) { + $columnTo = $columnID; + if (isset($cellDataTableAttributes['number-columns-spanned'])) { + $columnTo = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($columnID) + $cellDataTableAttributes['number-columns-spanned'] -2); + } + $rowTo = $rowID; + if (isset($cellDataTableAttributes['number-rows-spanned'])) { + $rowTo = $rowTo + $cellDataTableAttributes['number-rows-spanned'] - 1; + } + $cellRange = $columnID.$rowID.':'.$columnTo.$rowTo; + $objPHPExcel->getActiveSheet()->mergeCells($cellRange); + } + } + + ++$columnID; + } + $rowID += $rowRepeats; + break; + } + } + ++$worksheetID; + } + } + + // Return + return $objPHPExcel; + } + + + private function _parseRichText($is = '') { + $value = new PHPExcel_RichText(); + + $value->createText($is); + + return $value; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/SYLK.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/SYLK.php new file mode 100755 index 0000000..f9e3530 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Reader/SYLK.php @@ -0,0 +1,450 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** PHPExcel root directory */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); +} + +/** + * PHPExcel_Reader_SYLK + * + * @category PHPExcel + * @package PHPExcel_Reader + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Reader_SYLK extends PHPExcel_Reader_Abstract implements PHPExcel_Reader_IReader +{ + /** + * Input encoding + * + * @var string + */ + private $_inputEncoding = 'ANSI'; + + /** + * Sheet index to read + * + * @var int + */ + private $_sheetIndex = 0; + + /** + * Formats + * + * @var array + */ + private $_formats = array(); + + /** + * Format Count + * + * @var int + */ + private $_format = 0; + + /** + * Create a new PHPExcel_Reader_SYLK + */ + public function __construct() { + $this->_readFilter = new PHPExcel_Reader_DefaultReadFilter(); + } + + /** + * Validate that the current file is a SYLK file + * + * @return boolean + */ + protected function _isValidFormat() + { + // Read sample data (first 2 KB will do) + $data = fread($this->_fileHandle, 2048); + + // Count delimiters in file + $delimiterCount = substr_count($data, ';'); + if ($delimiterCount < 1) { + return FALSE; + } + + // Analyze first line looking for ID; signature + $lines = explode("\n", $data); + if (substr($lines[0],0,4) != 'ID;P') { + return FALSE; + } + + return TRUE; + } + + /** + * Set input encoding + * + * @param string $pValue Input encoding + */ + public function setInputEncoding($pValue = 'ANSI') + { + $this->_inputEncoding = $pValue; + return $this; + } + + /** + * Get input encoding + * + * @return string + */ + public function getInputEncoding() + { + return $this->_inputEncoding; + } + + /** + * Return worksheet info (Name, Last Column Letter, Last Column Index, Total Rows, Total Columns) + * + * @param string $pFilename + * @throws PHPExcel_Reader_Exception + */ + public function listWorksheetInfo($pFilename) + { + // Open file + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + $fileHandle = $this->_fileHandle; + rewind($fileHandle); + + $worksheetInfo = array(); + $worksheetInfo[0]['worksheetName'] = 'Worksheet'; + $worksheetInfo[0]['lastColumnLetter'] = 'A'; + $worksheetInfo[0]['lastColumnIndex'] = 0; + $worksheetInfo[0]['totalRows'] = 0; + $worksheetInfo[0]['totalColumns'] = 0; + + // Loop through file + $rowData = array(); + + // loop through one row (line) at a time in the file + $rowIndex = 0; + while (($rowData = fgets($fileHandle)) !== FALSE) { + $columnIndex = 0; + + // convert SYLK encoded $rowData to UTF-8 + $rowData = PHPExcel_Shared_String::SYLKtoUTF8($rowData); + + // explode each row at semicolons while taking into account that literal semicolon (;) + // is escaped like this (;;) + $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData))))); + + $dataType = array_shift($rowData); + if ($dataType == 'C') { + // Read cell value data + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : + $columnIndex = substr($rowDatum,1) - 1; + break; + case 'R' : + case 'Y' : + $rowIndex = substr($rowDatum,1); + break; + } + + $worksheetInfo[0]['totalRows'] = max($worksheetInfo[0]['totalRows'], $rowIndex); + $worksheetInfo[0]['lastColumnIndex'] = max($worksheetInfo[0]['lastColumnIndex'], $columnIndex); + } + } + } + + $worksheetInfo[0]['lastColumnLetter'] = PHPExcel_Cell::stringFromColumnIndex($worksheetInfo[0]['lastColumnIndex']); + $worksheetInfo[0]['totalColumns'] = $worksheetInfo[0]['lastColumnIndex'] + 1; + + // Close file + fclose($fileHandle); + + return $worksheetInfo; + } + + /** + * Loads PHPExcel from file + * + * @param string $pFilename + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function load($pFilename) + { + // Create new PHPExcel + $objPHPExcel = new PHPExcel(); + + // Load into this instance + return $this->loadIntoExisting($pFilename, $objPHPExcel); + } + + /** + * Loads PHPExcel from file into PHPExcel instance + * + * @param string $pFilename + * @param PHPExcel $objPHPExcel + * @return PHPExcel + * @throws PHPExcel_Reader_Exception + */ + public function loadIntoExisting($pFilename, PHPExcel $objPHPExcel) + { + // Open file + $this->_openFile($pFilename); + if (!$this->_isValidFormat()) { + fclose ($this->_fileHandle); + throw new PHPExcel_Reader_Exception($pFilename . " is an Invalid Spreadsheet file."); + } + $fileHandle = $this->_fileHandle; + rewind($fileHandle); + + // Create new PHPExcel + while ($objPHPExcel->getSheetCount() <= $this->_sheetIndex) { + $objPHPExcel->createSheet(); + } + $objPHPExcel->setActiveSheetIndex( $this->_sheetIndex ); + + $fromFormats = array('\-', '\ '); + $toFormats = array('-', ' '); + + // Loop through file + $rowData = array(); + $column = $row = ''; + + // loop through one row (line) at a time in the file + while (($rowData = fgets($fileHandle)) !== FALSE) { + + // convert SYLK encoded $rowData to UTF-8 + $rowData = PHPExcel_Shared_String::SYLKtoUTF8($rowData); + + // explode each row at semicolons while taking into account that literal semicolon (;) + // is escaped like this (;;) + $rowData = explode("\t",str_replace('¤',';',str_replace(';',"\t",str_replace(';;','¤',rtrim($rowData))))); + + $dataType = array_shift($rowData); + // Read shared styles + if ($dataType == 'P') { + $formatArray = array(); + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'P' : $formatArray['numberformat']['code'] = str_replace($fromFormats,$toFormats,substr($rowDatum,1)); + break; + case 'E' : + case 'F' : $formatArray['font']['name'] = substr($rowDatum,1); + break; + case 'L' : $formatArray['font']['size'] = substr($rowDatum,1); + break; + case 'S' : $styleSettings = substr($rowDatum,1); + for ($i=0;$i<strlen($styleSettings);++$i) { + switch ($styleSettings{$i}) { + case 'I' : $formatArray['font']['italic'] = true; + break; + case 'D' : $formatArray['font']['bold'] = true; + break; + case 'T' : $formatArray['borders']['top']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'B' : $formatArray['borders']['bottom']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'L' : $formatArray['borders']['left']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'R' : $formatArray['borders']['right']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + } + } + break; + } + } + $this->_formats['P'.$this->_format++] = $formatArray; + // Read cell value data + } elseif ($dataType == 'C') { + $hasCalculatedValue = false; + $cellData = $cellDataFormula = ''; + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + case 'K' : $cellData = substr($rowDatum,1); + break; + case 'E' : $cellDataFormula = '='.substr($rowDatum,1); + // Convert R1C1 style references to A1 style references (but only when not quoted) + $temp = explode('"',$cellDataFormula); + $key = false; + foreach($temp as &$value) { + // Only count/replace in alternate array entries + if ($key = !$key) { + preg_match_all('/(R(\[?-?\d*\]?))(C(\[?-?\d*\]?))/',$value, $cellReferences,PREG_SET_ORDER+PREG_OFFSET_CAPTURE); + // Reverse the matches array, otherwise all our offsets will become incorrect if we modify our way + // through the formula from left to right. Reversing means that we work right to left.through + // the formula + $cellReferences = array_reverse($cellReferences); + // Loop through each R1C1 style reference in turn, converting it to its A1 style equivalent, + // then modify the formula to use that new reference + foreach($cellReferences as $cellReference) { + $rowReference = $cellReference[2][0]; + // Empty R reference is the current row + if ($rowReference == '') $rowReference = $row; + // Bracketed R references are relative to the current row + if ($rowReference{0} == '[') $rowReference = $row + trim($rowReference,'[]'); + $columnReference = $cellReference[4][0]; + // Empty C reference is the current column + if ($columnReference == '') $columnReference = $column; + // Bracketed C references are relative to the current column + if ($columnReference{0} == '[') $columnReference = $column + trim($columnReference,'[]'); + $A1CellReference = PHPExcel_Cell::stringFromColumnIndex($columnReference-1).$rowReference; + + $value = substr_replace($value,$A1CellReference,$cellReference[0][1],strlen($cellReference[0][0])); + } + } + } + unset($value); + // Then rebuild the formula string + $cellDataFormula = implode('"',$temp); + $hasCalculatedValue = true; + break; + } + } + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + $cellData = PHPExcel_Calculation::_unwrapResult($cellData); + + // Set cell value + $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setValue(($hasCalculatedValue) ? $cellDataFormula : $cellData); + if ($hasCalculatedValue) { + $cellData = PHPExcel_Calculation::_unwrapResult($cellData); + $objPHPExcel->getActiveSheet()->getCell($columnLetter.$row)->setCalculatedValue($cellData); + } + // Read cell formatting + } elseif ($dataType == 'F') { + $formatStyle = $columnWidth = $styleSettings = ''; + $styleData = array(); + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + case 'P' : $formatStyle = $rowDatum; + break; + case 'W' : list($startCol,$endCol,$columnWidth) = explode(' ',substr($rowDatum,1)); + break; + case 'S' : $styleSettings = substr($rowDatum,1); + for ($i=0;$i<strlen($styleSettings);++$i) { + switch ($styleSettings{$i}) { + case 'I' : $styleData['font']['italic'] = true; + break; + case 'D' : $styleData['font']['bold'] = true; + break; + case 'T' : $styleData['borders']['top']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'B' : $styleData['borders']['bottom']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'L' : $styleData['borders']['left']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + case 'R' : $styleData['borders']['right']['style'] = PHPExcel_Style_Border::BORDER_THIN; + break; + } + } + break; + } + } + if (($formatStyle > '') && ($column > '') && ($row > '')) { + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + if (isset($this->_formats[$formatStyle])) { + $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($this->_formats[$formatStyle]); + } + } + if ((!empty($styleData)) && ($column > '') && ($row > '')) { + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($column-1); + $objPHPExcel->getActiveSheet()->getStyle($columnLetter.$row)->applyFromArray($styleData); + } + if ($columnWidth > '') { + if ($startCol == $endCol) { + $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth); + } else { + $startCol = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $endCol = PHPExcel_Cell::stringFromColumnIndex($endCol-1); + $objPHPExcel->getActiveSheet()->getColumnDimension($startCol)->setWidth($columnWidth); + do { + $objPHPExcel->getActiveSheet()->getColumnDimension(++$startCol)->setWidth($columnWidth); + } while ($startCol != $endCol); + } + } + } else { + foreach($rowData as $rowDatum) { + switch($rowDatum{0}) { + case 'C' : + case 'X' : $column = substr($rowDatum,1); + break; + case 'R' : + case 'Y' : $row = substr($rowDatum,1); + break; + } + } + } + } + + // Close file + fclose($fileHandle); + + // Return + return $objPHPExcel; + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Reader_SYLK + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/ReferenceHelper.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/ReferenceHelper.php new file mode 100755 index 0000000..bf7771a --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/ReferenceHelper.php @@ -0,0 +1,918 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_ReferenceHelper (Singleton) + * + * @category PHPExcel + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_ReferenceHelper +{ + /** Constants */ + /** Regular Expressions */ + const REFHELPER_REGEXP_CELLREF = '((\w*|\'[^!]*\')!)?(?<![:a-z\$])(\$?[a-z]{1,3}\$?\d+)(?=[^:!\d\'])'; + const REFHELPER_REGEXP_CELLRANGE = '((\w*|\'[^!]*\')!)?(\$?[a-z]{1,3}\$?\d+):(\$?[a-z]{1,3}\$?\d+)'; + const REFHELPER_REGEXP_ROWRANGE = '((\w*|\'[^!]*\')!)?(\$?\d+):(\$?\d+)'; + const REFHELPER_REGEXP_COLRANGE = '((\w*|\'[^!]*\')!)?(\$?[a-z]{1,3}):(\$?[a-z]{1,3})'; + + /** + * Instance of this class + * + * @var PHPExcel_ReferenceHelper + */ + private static $_instance; + + /** + * Get an instance of this class + * + * @return PHPExcel_ReferenceHelper + */ + public static function getInstance() { + if (!isset(self::$_instance) || (self::$_instance === NULL)) { + self::$_instance = new PHPExcel_ReferenceHelper(); + } + + return self::$_instance; + } + + /** + * Create a new PHPExcel_ReferenceHelper + */ + protected function __construct() { + } + + /** + * Compare two column addresses + * Intended for use as a Callback function for sorting column addresses by column + * + * @param string $a First column to test (e.g. 'AA') + * @param string $b Second column to test (e.g. 'Z') + * @return integer + */ + public static function columnSort($a, $b) { + return strcasecmp(strlen($a) . $a, strlen($b) . $b); + } + + /** + * Compare two column addresses + * Intended for use as a Callback function for reverse sorting column addresses by column + * + * @param string $a First column to test (e.g. 'AA') + * @param string $b Second column to test (e.g. 'Z') + * @return integer + */ + public static function columnReverseSort($a, $b) { + return 1 - strcasecmp(strlen($a) . $a, strlen($b) . $b); + } + + /** + * Compare two cell addresses + * Intended for use as a Callback function for sorting cell addresses by column and row + * + * @param string $a First cell to test (e.g. 'AA1') + * @param string $b Second cell to test (e.g. 'Z1') + * @return integer + */ + public static function cellSort($a, $b) { + sscanf($a,'%[A-Z]%d', $ac, $ar); + sscanf($b,'%[A-Z]%d', $bc, $br); + + if ($ar == $br) { + return strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); + } + return ($ar < $br) ? -1 : 1; + } + + /** + * Compare two cell addresses + * Intended for use as a Callback function for sorting cell addresses by column and row + * + * @param string $a First cell to test (e.g. 'AA1') + * @param string $b Second cell to test (e.g. 'Z1') + * @return integer + */ + public static function cellReverseSort($a, $b) { + sscanf($a,'%[A-Z]%d', $ac, $ar); + sscanf($b,'%[A-Z]%d', $bc, $br); + + if ($ar == $br) { + return 1 - strcasecmp(strlen($ac) . $ac, strlen($bc) . $bc); + } + return ($ar < $br) ? 1 : -1; + } + + /** + * Test whether a cell address falls within a defined range of cells + * + * @param string $cellAddress Address of the cell we're testing + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @return boolean + */ + private static function cellAddressInDeleteRange($cellAddress, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols) { + list($cellColumn, $cellRow) = PHPExcel_Cell::coordinateFromString($cellAddress); + $cellColumnIndex = PHPExcel_Cell::columnIndexFromString($cellColumn); + // Is cell within the range of rows/columns if we're deleting + if ($pNumRows < 0 && + ($cellRow >= ($beforeRow + $pNumRows)) && + ($cellRow < $beforeRow)) { + return TRUE; + } elseif ($pNumCols < 0 && + ($cellColumnIndex >= ($beforeColumnIndex + $pNumCols)) && + ($cellColumnIndex < $beforeColumnIndex)) { + return TRUE; + } + return FALSE; + } + + /** + * Update page breaks when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustPageBreaks(PHPExcel_Worksheet $pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aBreaks = $pSheet->getBreaks(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aBreaks, array('PHPExcel_ReferenceHelper','cellSort')); + + foreach ($aBreaks as $key => $value) { + if (self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { + // If we're deleting, then clear any defined breaks that are within the range + // of rows/columns that we're deleting + $pSheet->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); + } else { + // Otherwise update any affected breaks by inserting a new break at the appropriate point + // and removing the old affected break + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setBreak($newReference, $value) + ->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); + } + } + } + } + + /** + * Update cell comments when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aComments = $pSheet->getComments(); + $aNewComments = array(); // the new array of all comments + + foreach ($aComments as $key => &$value) { + // Any comments inside a deleted range will be ignored + if (!self::cellAddressInDeleteRange($key, $beforeRow, $pNumRows, $beforeColumnIndex, $pNumCols)) { + // Otherwise build a new array of comments indexed by the adjusted cell reference + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + $aNewComments[$newReference] = $value; + } + } + // Replace the comments array with the new set of comments + $pSheet->setComments($aNewComments); + } + + /** + * Update hyperlinks when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aHyperlinkCollection = $pSheet->getHyperlinkCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aHyperlinkCollection, array('PHPExcel_ReferenceHelper','cellSort')); + + foreach ($aHyperlinkCollection as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setHyperlink( $newReference, $value ); + $pSheet->setHyperlink( $key, null ); + } + } + } + + /** + * Update data validations when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aDataValidationCollection = $pSheet->getDataValidationCollection(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aDataValidationCollection, array('PHPExcel_ReferenceHelper','cellSort')); + foreach ($aDataValidationCollection as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->setDataValidation( $newReference, $value ); + $pSheet->setDataValidation( $key, null ); + } + } + } + + /** + * Update merged cells when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aMergeCells = $pSheet->getMergeCells(); + $aNewMergeCells = array(); // the new array of all merge cells + foreach ($aMergeCells as $key => &$value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + $aNewMergeCells[$newReference] = $newReference; + } + $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array + } + + /** + * Update protected cells when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aProtectedCells = $pSheet->getProtectedCells(); + ($pNumCols > 0 || $pNumRows > 0) ? + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellReverseSort')) : + uksort($aProtectedCells, array('PHPExcel_ReferenceHelper','cellSort')); + foreach ($aProtectedCells as $key => $value) { + $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); + if ($key != $newReference) { + $pSheet->protectCells( $newReference, $value, true ); + $pSheet->unprotectCells( $key ); + } + } + } + + /** + * Update column dimensions when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true); + if (!empty($aColumnDimensions)) { + foreach ($aColumnDimensions as $objColumnDimension) { + $newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows); + list($newReference) = PHPExcel_Cell::coordinateFromString($newReference); + if ($objColumnDimension->getColumnIndex() != $newReference) { + $objColumnDimension->setColumnIndex($newReference); + } + } + $pSheet->refreshColumnDimensions(); + } + } + + /** + * Update row dimensions when inserting/deleting rows/columns + * + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @param string $pBefore Insert/Delete before this cell address (e.g. 'A1') + * @param integer $beforeColumnIndex Index number of the column we're inserting/deleting before + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $beforeRow Number of the row we're inserting/deleting before + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + */ + protected function _adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows) + { + $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true); + if (!empty($aRowDimensions)) { + foreach ($aRowDimensions as $objRowDimension) { + $newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows); + list(, $newReference) = PHPExcel_Cell::coordinateFromString($newReference); + if ($objRowDimension->getRowIndex() != $newReference) { + $objRowDimension->setRowIndex($newReference); + } + } + $pSheet->refreshRowDimensions(); + + $copyDimension = $pSheet->getRowDimension($beforeRow - 1); + for ($i = $beforeRow; $i <= $beforeRow - 1 + $pNumRows; ++$i) { + $newDimension = $pSheet->getRowDimension($i); + $newDimension->setRowHeight($copyDimension->getRowHeight()); + $newDimension->setVisible($copyDimension->getVisible()); + $newDimension->setOutlineLevel($copyDimension->getOutlineLevel()); + $newDimension->setCollapsed($copyDimension->getCollapsed()); + } + } + } + + /** + * Insert a new column or row, updating all possible related data + * + * @param string $pBefore Insert before this cell address (e.g. 'A1') + * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) + * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) + * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing + * @throws PHPExcel_Exception + */ + public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = NULL) + { + $remove = ($pNumCols < 0 || $pNumRows < 0); + $aCellCollection = $pSheet->getCellCollection(); + + // Get coordinates of $pBefore + $beforeColumn = 'A'; + $beforeRow = 1; + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString($pBefore); + $beforeColumnIndex = PHPExcel_Cell::columnIndexFromString($beforeColumn); + + // Clear cells if we are removing columns or rows + $highestColumn = $pSheet->getHighestColumn(); + $highestRow = $pSheet->getHighestRow(); + + // 1. Clear column strips if we are removing columns + if ($pNumCols < 0 && $beforeColumnIndex - 2 + $pNumCols > 0) { + for ($i = 1; $i <= $highestRow - 1; ++$i) { + for ($j = $beforeColumnIndex - 1 + $pNumCols; $j <= $beforeColumnIndex - 2; ++$j) { + $coordinate = PHPExcel_Cell::stringFromColumnIndex($j) . $i; + $pSheet->removeConditionalStyles($coordinate); + if ($pSheet->cellExists($coordinate)) { + $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); + $pSheet->getCell($coordinate)->setXfIndex(0); + } + } + } + } + + // 2. Clear row strips if we are removing rows + if ($pNumRows < 0 && $beforeRow - 1 + $pNumRows > 0) { + for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { + for ($j = $beforeRow + $pNumRows; $j <= $beforeRow - 1; ++$j) { + $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . $j; + $pSheet->removeConditionalStyles($coordinate); + if ($pSheet->cellExists($coordinate)) { + $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); + $pSheet->getCell($coordinate)->setXfIndex(0); + } + } + } + } + + // Loop through cells, bottom-up, and change cell coordinates + while (($cellID = $remove ? array_shift($aCellCollection) : array_pop($aCellCollection))) { + $cell = $pSheet->getCell($cellID); + $cellIndex = PHPExcel_Cell::columnIndexFromString($cell->getColumn()); + if ($cellIndex-1 + $pNumCols < 0) { + continue; + } + + // New coordinates + $newCoordinates = PHPExcel_Cell::stringFromColumnIndex($cellIndex-1 + $pNumCols) . ($cell->getRow() + $pNumRows); + + // Should the cell be updated? Move value and cellXf index from one cell to another. + if (($cellIndex >= $beforeColumnIndex) && + ($cell->getRow() >= $beforeRow)) { + + // Update cell styles + $pSheet->getCell($newCoordinates)->setXfIndex($cell->getXfIndex()); + + // Insert this cell at its new location + if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { + // Formula should be adjusted + $pSheet->getCell($newCoordinates) + ->setValue($this->updateFormulaReferences($cell->getValue(), + $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle())); + } else { + // Formula should not be adjusted + $pSheet->getCell($newCoordinates)->setValue($cell->getValue()); + } + + // Clear the original cell + $pSheet->getCellCacheController()->deleteCacheData($cellID); + + } else { + /* We don't need to update styles for rows/columns before our insertion position, + but we do still need to adjust any formulae in those cells */ + if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { + // Formula should be adjusted + $cell->setValue($this->updateFormulaReferences($cell->getValue(), + $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle())); + } + + } + } + + // Duplicate styles for the newly inserted cells + $highestColumn = $pSheet->getHighestColumn(); + $highestRow = $pSheet->getHighestRow(); + + if ($pNumCols > 0 && $beforeColumnIndex - 2 > 0) { + for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) { + + // Style + $coordinate = PHPExcel_Cell::stringFromColumnIndex( $beforeColumnIndex - 2 ) . $i; + if ($pSheet->cellExists($coordinate)) { + $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); + $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? + $pSheet->getConditionalStyles($coordinate) : false; + for ($j = $beforeColumnIndex - 1; $j <= $beforeColumnIndex - 2 + $pNumCols; ++$j) { + $pSheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex); + if ($conditionalStyles) { + $cloned = array(); + foreach ($conditionalStyles as $conditionalStyle) { + $cloned[] = clone $conditionalStyle; + } + $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($j) . $i, $cloned); + } + } + } + + } + } + + if ($pNumRows > 0 && $beforeRow - 1 > 0) { + for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { + + // Style + $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . ($beforeRow - 1); + if ($pSheet->cellExists($coordinate)) { + $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); + $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? + $pSheet->getConditionalStyles($coordinate) : false; + for ($j = $beforeRow; $j <= $beforeRow - 1 + $pNumRows; ++$j) { + $pSheet->getCell(PHPExcel_Cell::stringFromColumnIndex($i) . $j)->setXfIndex($xfIndex); + if ($conditionalStyles) { + $cloned = array(); + foreach ($conditionalStyles as $conditionalStyle) { + $cloned[] = clone $conditionalStyle; + } + $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($i) . $j, $cloned); + } + } + } + } + } + + // Update worksheet: column dimensions + $this->_adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: row dimensions + $this->_adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: page breaks + $this->_adjustPageBreaks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: comments + $this->_adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: hyperlinks + $this->_adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: data validations + $this->_adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: merge cells + $this->_adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: protected cells + $this->_adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); + + // Update worksheet: autofilter + $autoFilter = $pSheet->getAutoFilter(); + $autoFilterRange = $autoFilter->getRange(); + if (!empty($autoFilterRange)) { + if ($pNumCols != 0) { + $autoFilterColumns = array_keys($autoFilter->getColumns()); + if (count($autoFilterColumns) > 0) { + sscanf($pBefore,'%[A-Z]%d', $column, $row); + $columnIndex = PHPExcel_Cell::columnIndexFromString($column); + list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($autoFilterRange); + if ($columnIndex <= $rangeEnd[0]) { + if ($pNumCols < 0) { + // If we're actually deleting any columns that fall within the autofilter range, + // then we delete any rules for those columns + $deleteColumn = $columnIndex + $pNumCols - 1; + $deleteCount = abs($pNumCols); + for ($i = 1; $i <= $deleteCount; ++$i) { + if (in_array(PHPExcel_Cell::stringFromColumnIndex($deleteColumn),$autoFilterColumns)) { + $autoFilter->clearColumn(PHPExcel_Cell::stringFromColumnIndex($deleteColumn)); + } + ++$deleteColumn; + } + } + $startCol = ($columnIndex > $rangeStart[0]) ? $columnIndex : $rangeStart[0]; + + // Shuffle columns in autofilter range + if ($pNumCols > 0) { + // For insert, we shuffle from end to beginning to avoid overwriting + $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1); + $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); + + $startColRef = $startCol; + $endColRef = $rangeEnd[0]; + $toColRef = $rangeEnd[0]+$pNumCols; + + do { + $autoFilter->shiftColumn(PHPExcel_Cell::stringFromColumnIndex($endColRef-1),PHPExcel_Cell::stringFromColumnIndex($toColRef-1)); + --$endColRef; + --$toColRef; + } while ($startColRef <= $endColRef); + } else { + // For delete, we shuffle from beginning to end to avoid overwriting + $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol-1); + $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol+$pNumCols-1); + $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); + do { + $autoFilter->shiftColumn($startColID,$toColID); + ++$startColID; + ++$toColID; + } while ($startColID != $endColID); + } + } + } + } + $pSheet->setAutoFilter( $this->updateCellReference($autoFilterRange, $pBefore, $pNumCols, $pNumRows) ); + } + + // Update worksheet: freeze pane + if ($pSheet->getFreezePane() != '') { + $pSheet->freezePane( $this->updateCellReference($pSheet->getFreezePane(), $pBefore, $pNumCols, $pNumRows) ); + } + + // Page setup + if ($pSheet->getPageSetup()->isPrintAreaSet()) { + $pSheet->getPageSetup()->setPrintArea( $this->updateCellReference($pSheet->getPageSetup()->getPrintArea(), $pBefore, $pNumCols, $pNumRows) ); + } + + // Update worksheet: drawings + $aDrawings = $pSheet->getDrawingCollection(); + foreach ($aDrawings as $objDrawing) { + $newReference = $this->updateCellReference($objDrawing->getCoordinates(), $pBefore, $pNumCols, $pNumRows); + if ($objDrawing->getCoordinates() != $newReference) { + $objDrawing->setCoordinates($newReference); + } + } + + // Update workbook: named ranges + if (count($pSheet->getParent()->getNamedRanges()) > 0) { + foreach ($pSheet->getParent()->getNamedRanges() as $namedRange) { + if ($namedRange->getWorksheet()->getHashCode() == $pSheet->getHashCode()) { + $namedRange->setRange( + $this->updateCellReference($namedRange->getRange(), $pBefore, $pNumCols, $pNumRows) + ); + } + } + } + + // Garbage collect + $pSheet->garbageCollect(); + } + + /** + * Update references within formulas + * + * @param string $pFormula Formula to update + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to insert + * @param int $pNumRows Number of rows to insert + * @param string $sheetName Worksheet name/title + * @return string Updated formula + * @throws PHPExcel_Exception + */ + public function updateFormulaReferences($pFormula = '', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, $sheetName = '') { + // Update cell references in the formula + $formulaBlocks = explode('"',$pFormula); + $i = false; + foreach($formulaBlocks as &$formulaBlock) { + // Ignore blocks that were enclosed in quotes (alternating entries in the $formulaBlocks array after the explode) + if ($i = !$i) { + $adjustCount = 0; + $newCellTokens = $cellTokens = array(); + // Search for row ranges (e.g. 'Sheet1'!3:5 or 3:5) with or without $ absolutes (e.g. $3:5) + $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_ROWRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); + if ($matchCount > 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3].':'.$match[4]; + $modified3 = substr($this->updateCellReference('$A'.$match[3],$pBefore,$pNumCols,$pNumRows),2); + $modified4 = substr($this->updateCellReference('$A'.$match[4],$pBefore,$pNumCols,$pNumRows),2); + + if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3.':'.$modified4; + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = 100000; + $row = 10000000+trim($match[3],'$'); + $cellIndex = $column.$row; + + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(?<!\d)'.preg_quote($fromString).'(?!\d)/i'; + ++$adjustCount; + } + } + } + } + // Search for column ranges (e.g. 'Sheet1'!C:E or C:E) with or without $ absolutes (e.g. $C:E) + $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_COLRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); + if ($matchCount > 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3].':'.$match[4]; + $modified3 = substr($this->updateCellReference($match[3].'$1',$pBefore,$pNumCols,$pNumRows),0,-2); + $modified4 = substr($this->updateCellReference($match[4].'$1',$pBefore,$pNumCols,$pNumRows),0,-2); + + if ($match[3].':'.$match[4] !== $modified3.':'.$modified4) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3.':'.$modified4; + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = PHPExcel_Cell::columnIndexFromString(trim($match[3],'$')) + 100000; + $row = 10000000; + $cellIndex = $column.$row; + + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(?<![A-Z])'.preg_quote($fromString).'(?![A-Z])/i'; + ++$adjustCount; + } + } + } + } + // Search for cell ranges (e.g. 'Sheet1'!A3:C5 or A3:C5) with or without $ absolutes (e.g. $A1:C$5) + $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_CELLRANGE.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); + if ($matchCount > 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3].':'.$match[4]; + $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows); + $modified4 = $this->updateCellReference($match[4],$pBefore,$pNumCols,$pNumRows); + + if ($match[3].$match[4] !== $modified3.$modified4) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3.':'.$modified4; + list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]); + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000; + $row = trim($row,'$') + 10000000; + $cellIndex = $column.$row; + + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(?<![A-Z])'.preg_quote($fromString).'(?!\d)/i'; + ++$adjustCount; + } + } + } + } + // Search for cell references (e.g. 'Sheet1'!A3 or C5) with or without $ absolutes (e.g. $A1 or C$5) + $matchCount = preg_match_all('/'.self::REFHELPER_REGEXP_CELLREF.'/i', ' '.$formulaBlock.' ', $matches, PREG_SET_ORDER); + if ($matchCount > 0) { + foreach($matches as $match) { + $fromString = ($match[2] > '') ? $match[2].'!' : ''; + $fromString .= $match[3]; + $modified3 = $this->updateCellReference($match[3],$pBefore,$pNumCols,$pNumRows); + + if ($match[3] !== $modified3) { + if (($match[2] == '') || (trim($match[2],"'") == $sheetName)) { + $toString = ($match[2] > '') ? $match[2].'!' : ''; + $toString .= $modified3; + list($column,$row) = PHPExcel_Cell::coordinateFromString($match[3]); + // Max worksheet size is 1,048,576 rows by 16,384 columns in Excel 2007, so our adjustments need to be at least one digit more + $column = PHPExcel_Cell::columnIndexFromString(trim($column,'$')) + 100000; + $row = trim($row,'$') + 10000000; + $cellIndex = $column.$row; + + $newCellTokens[$cellIndex] = preg_quote($toString); + $cellTokens[$cellIndex] = '/(?<![A-Z])'.preg_quote($fromString).'(?!\d)/i'; + ++$adjustCount; + } + } + } + } + if ($adjustCount > 0) { + if ($pNumCols > 0) { + krsort($cellTokens); + krsort($newCellTokens); + } else { + ksort($cellTokens); + ksort($newCellTokens); + } + // Update cell references in the formula + $formulaBlock = str_replace('\\','',preg_replace($cellTokens,$newCellTokens,$formulaBlock)); + } + } + } + unset($formulaBlock); + + // Then rebuild the formula string + return implode('"',$formulaBlocks); + } + + /** + * Update cell reference + * + * @param string $pCellRange Cell range + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell range + * @throws PHPExcel_Exception + */ + public function updateCellReference($pCellRange = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + // Is it in another worksheet? Will not have to update anything. + if (strpos($pCellRange, "!") !== false) { + return $pCellRange; + // Is it a range or a single cell? + } elseif (strpos($pCellRange, ':') === false && strpos($pCellRange, ',') === false) { + // Single cell + return $this->_updateSingleCellReference($pCellRange, $pBefore, $pNumCols, $pNumRows); + } elseif (strpos($pCellRange, ':') !== false || strpos($pCellRange, ',') !== false) { + // Range + return $this->_updateCellRange($pCellRange, $pBefore, $pNumCols, $pNumRows); + } else { + // Return original + return $pCellRange; + } + } + + /** + * Update named formulas (i.e. containing worksheet references / named ranges) + * + * @param PHPExcel $pPhpExcel Object to update + * @param string $oldName Old name (name to replace) + * @param string $newName New name + */ + public function updateNamedFormulas(PHPExcel $pPhpExcel, $oldName = '', $newName = '') { + if ($oldName == '') { + return; + } + + foreach ($pPhpExcel->getWorksheetIterator() as $sheet) { + foreach ($sheet->getCellCollection(false) as $cellID) { + $cell = $sheet->getCell($cellID); + if (($cell !== NULL) && ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA)) { + $formula = $cell->getValue(); + if (strpos($formula, $oldName) !== false) { + $formula = str_replace("'" . $oldName . "'!", "'" . $newName . "'!", $formula); + $formula = str_replace($oldName . "!", $newName . "!", $formula); + $cell->setValueExplicit($formula, PHPExcel_Cell_DataType::TYPE_FORMULA); + } + } + } + } + } + + /** + * Update cell range + * + * @param string $pCellRange Cell range (e.g. 'B2:D4', 'B:C' or '2:3') + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell range + * @throws PHPExcel_Exception + */ + private function _updateCellRange($pCellRange = 'A1:A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + if (strpos($pCellRange,':') !== false || strpos($pCellRange, ',') !== false) { + // Update range + $range = PHPExcel_Cell::splitRange($pCellRange); + $ic = count($range); + for ($i = 0; $i < $ic; ++$i) { + $jc = count($range[$i]); + for ($j = 0; $j < $jc; ++$j) { + if (ctype_alpha($range[$i][$j])) { + $r = PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference($range[$i][$j].'1', $pBefore, $pNumCols, $pNumRows)); + $range[$i][$j] = $r[0]; + } elseif(ctype_digit($range[$i][$j])) { + $r = PHPExcel_Cell::coordinateFromString($this->_updateSingleCellReference('A'.$range[$i][$j], $pBefore, $pNumCols, $pNumRows)); + $range[$i][$j] = $r[1]; + } else { + $range[$i][$j] = $this->_updateSingleCellReference($range[$i][$j], $pBefore, $pNumCols, $pNumRows); + } + } + } + + // Recreate range string + return PHPExcel_Cell::buildRange($range); + } else { + throw new PHPExcel_Exception("Only cell ranges may be passed to this method."); + } + } + + /** + * Update single cell reference + * + * @param string $pCellReference Single cell reference + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to increment + * @param int $pNumRows Number of rows to increment + * @return string Updated cell reference + * @throws PHPExcel_Exception + */ + private function _updateSingleCellReference($pCellReference = 'A1', $pBefore = 'A1', $pNumCols = 0, $pNumRows = 0) { + if (strpos($pCellReference, ':') === false && strpos($pCellReference, ',') === false) { + // Get coordinates of $pBefore + list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString( $pBefore ); + + // Get coordinates of $pCellReference + list($newColumn, $newRow) = PHPExcel_Cell::coordinateFromString( $pCellReference ); + + // Verify which parts should be updated + $updateColumn = (($newColumn{0} != '$') && ($beforeColumn{0} != '$') && + PHPExcel_Cell::columnIndexFromString($newColumn) >= PHPExcel_Cell::columnIndexFromString($beforeColumn)); + + $updateRow = (($newRow{0} != '$') && ($beforeRow{0} != '$') && + $newRow >= $beforeRow); + + // Create new column reference + if ($updateColumn) { + $newColumn = PHPExcel_Cell::stringFromColumnIndex( PHPExcel_Cell::columnIndexFromString($newColumn) - 1 + $pNumCols ); + } + + // Create new row reference + if ($updateRow) { + $newRow = $newRow + $pNumRows; + } + + // Return new reference + return $newColumn . $newRow; + } else { + throw new PHPExcel_Exception("Only single cell references may be passed to this method."); + } + } + + /** + * __clone implementation. Cloning should not be allowed in a Singleton! + * + * @throws PHPExcel_Exception + */ + public final function __clone() { + throw new PHPExcel_Exception("Cloning a Singleton is not allowed!"); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText.php new file mode 100755 index 0000000..828194d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText.php @@ -0,0 +1,199 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_RichText + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_RichText + * + * @category PHPExcel + * @package PHPExcel_RichText + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_RichText implements PHPExcel_IComparable +{ + /** + * Rich text elements + * + * @var PHPExcel_RichText_ITextElement[] + */ + private $_richTextElements; + + /** + * Create a new PHPExcel_RichText instance + * + * @param PHPExcel_Cell $pCell + * @throws PHPExcel_Exception + */ + public function __construct(PHPExcel_Cell $pCell = null) + { + // Initialise variables + $this->_richTextElements = array(); + + // Rich-Text string attached to cell? + if ($pCell !== NULL) { + // Add cell text and style + if ($pCell->getValue() != "") { + $objRun = new PHPExcel_RichText_Run($pCell->getValue()); + $objRun->setFont(clone $pCell->getParent()->getStyle($pCell->getCoordinate())->getFont()); + $this->addText($objRun); + } + + // Set parent value + $pCell->setValueExplicit($this, PHPExcel_Cell_DataType::TYPE_STRING); + } + } + + /** + * Add text + * + * @param PHPExcel_RichText_ITextElement $pText Rich text element + * @throws PHPExcel_Exception + * @return PHPExcel_RichText + */ + public function addText(PHPExcel_RichText_ITextElement $pText = null) + { + $this->_richTextElements[] = $pText; + return $this; + } + + /** + * Create text + * + * @param string $pText Text + * @return PHPExcel_RichText_TextElement + * @throws PHPExcel_Exception + */ + public function createText($pText = '') + { + $objText = new PHPExcel_RichText_TextElement($pText); + $this->addText($objText); + return $objText; + } + + /** + * Create text run + * + * @param string $pText Text + * @return PHPExcel_RichText_Run + * @throws PHPExcel_Exception + */ + public function createTextRun($pText = '') + { + $objText = new PHPExcel_RichText_Run($pText); + $this->addText($objText); + return $objText; + } + + /** + * Get plain text + * + * @return string + */ + public function getPlainText() + { + // Return value + $returnValue = ''; + + // Loop through all PHPExcel_RichText_ITextElement + foreach ($this->_richTextElements as $text) { + $returnValue .= $text->getText(); + } + + // Return + return $returnValue; + } + + /** + * Convert to string + * + * @return string + */ + public function __toString() + { + return $this->getPlainText(); + } + + /** + * Get Rich Text elements + * + * @return PHPExcel_RichText_ITextElement[] + */ + public function getRichTextElements() + { + return $this->_richTextElements; + } + + /** + * Set Rich Text elements + * + * @param PHPExcel_RichText_ITextElement[] $pElements Array of elements + * @throws PHPExcel_Exception + * @return PHPExcel_RichText + */ + public function setRichTextElements($pElements = null) + { + if (is_array($pElements)) { + $this->_richTextElements = $pElements; + } else { + throw new PHPExcel_Exception("Invalid PHPExcel_RichText_ITextElement[] array passed."); + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() + { + $hashElements = ''; + foreach ($this->_richTextElements as $element) { + $hashElements .= $element->getHashCode(); + } + + return md5( + $hashElements + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() + { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/ITextElement.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/ITextElement.php new file mode 100755 index 0000000..e47af0c --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/ITextElement.php @@ -0,0 +1,64 @@ +<?php +/** + * PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_RichText + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_RichText_ITextElement + * + * @category PHPExcel + * @package PHPExcel_RichText + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +interface PHPExcel_RichText_ITextElement +{ + /** + * Get text + * + * @return string Text + */ + public function getText(); + + /** + * Set text + * + * @param $pText string Text + * @return PHPExcel_RichText_ITextElement + */ + public function setText($pText = ''); + + /** + * Get font + * + * @return PHPExcel_Style_Font + */ + public function getFont(); + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode(); +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/Run.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/Run.php new file mode 100755 index 0000000..8ae61ce --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/Run.php @@ -0,0 +1,102 @@ +<?php +/** + * PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_RichText + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_RichText_Run + * + * @category PHPExcel + * @package PHPExcel_RichText + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_RichText_Run extends PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement +{ + /** + * Font + * + * @var PHPExcel_Style_Font + */ + private $_font; + + /** + * Create a new PHPExcel_RichText_Run instance + * + * @param string $pText Text + */ + public function __construct($pText = '') + { + // Initialise variables + $this->setText($pText); + $this->_font = new PHPExcel_Style_Font(); + } + + /** + * Get font + * + * @return PHPExcel_Style_Font + */ + public function getFont() { + return $this->_font; + } + + /** + * Set font + * + * @param PHPExcel_Style_Font $pFont Font + * @throws PHPExcel_Exception + * @return PHPExcel_RichText_ITextElement + */ + public function setFont(PHPExcel_Style_Font $pFont = null) { + $this->_font = $pFont; + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->getText() + . $this->_font->getHashCode() + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/TextElement.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/TextElement.php new file mode 100755 index 0000000..b1ddbc4 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/RichText/TextElement.php @@ -0,0 +1,108 @@ +<?php +/** + * PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_RichText + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_RichText_TextElement + * + * @category PHPExcel + * @package PHPExcel_RichText + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_RichText_TextElement implements PHPExcel_RichText_ITextElement +{ + /** + * Text + * + * @var string + */ + private $_text; + + /** + * Create a new PHPExcel_RichText_TextElement instance + * + * @param string $pText Text + */ + public function __construct($pText = '') + { + // Initialise variables + $this->_text = $pText; + } + + /** + * Get text + * + * @return string Text + */ + public function getText() { + return $this->_text; + } + + /** + * Set text + * + * @param $pText string Text + * @return PHPExcel_RichText_ITextElement + */ + public function setText($pText = '') { + $this->_text = $pText; + return $this; + } + + /** + * Get font + * + * @return PHPExcel_Style_Font + */ + public function getFont() { + return null; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_text + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Settings.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Settings.php new file mode 100755 index 0000000..d7e9f83 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Settings.php @@ -0,0 +1,354 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Settings + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** PHPExcel root directory */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); +} + + +class PHPExcel_Settings +{ + /** constants */ + /** Available Zip library classes */ + const PCLZIP = 'PHPExcel_Shared_ZipArchive'; + const ZIPARCHIVE = 'ZipArchive'; + + /** Optional Chart Rendering libraries */ + const CHART_RENDERER_JPGRAPH = 'jpgraph'; + + /** Optional PDF Rendering libraries */ + const PDF_RENDERER_TCPDF = 'tcPDF'; + const PDF_RENDERER_DOMPDF = 'DomPDF'; + const PDF_RENDERER_MPDF = 'mPDF'; + + + private static $_chartRenderers = array( + self::CHART_RENDERER_JPGRAPH, + ); + + private static $_pdfRenderers = array( + self::PDF_RENDERER_TCPDF, + self::PDF_RENDERER_DOMPDF, + self::PDF_RENDERER_MPDF, + ); + + + /** + * Name of the class used for Zip file management + * e.g. + * ZipArchive + * + * @var string + */ + private static $_zipClass = self::ZIPARCHIVE; + + + /** + * Name of the external Library used for rendering charts + * e.g. + * jpgraph + * + * @var string + */ + private static $_chartRendererName = NULL; + + /** + * Directory Path to the external Library used for rendering charts + * + * @var string + */ + private static $_chartRendererPath = NULL; + + + /** + * Name of the external Library used for rendering PDF files + * e.g. + * mPDF + * + * @var string + */ + private static $_pdfRendererName = NULL; + + /** + * Directory Path to the external Library used for rendering PDF files + * + * @var string + */ + private static $_pdfRendererPath = NULL; + + + /** + * Set the Zip handler Class that PHPExcel should use for Zip file management (PCLZip or ZipArchive) + * + * @param string $zipClass The Zip handler class that PHPExcel should use for Zip file management + * e.g. PHPExcel_Settings::PCLZip or PHPExcel_Settings::ZipArchive + * @return boolean Success or failure + */ + public static function setZipClass($zipClass) + { + if (($zipClass === self::PCLZIP) || + ($zipClass === self::ZIPARCHIVE)) { + self::$_zipClass = $zipClass; + return TRUE; + } + return FALSE; + } // function setZipClass() + + + /** + * Return the name of the Zip handler Class that PHPExcel is configured to use (PCLZip or ZipArchive) + * or Zip file management + * + * @return string Name of the Zip handler Class that PHPExcel is configured to use + * for Zip file management + * e.g. PHPExcel_Settings::PCLZip or PHPExcel_Settings::ZipArchive + */ + public static function getZipClass() + { + return self::$_zipClass; + } // function getZipClass() + + + /** + * Return the name of the method that is currently configured for cell cacheing + * + * @return string Name of the cacheing method + */ + public static function getCacheStorageMethod() + { + return PHPExcel_CachedObjectStorageFactory::getCacheStorageMethod(); + } // function getCacheStorageMethod() + + + /** + * Return the name of the class that is currently being used for cell cacheing + * + * @return string Name of the class currently being used for cacheing + */ + public static function getCacheStorageClass() + { + return PHPExcel_CachedObjectStorageFactory::getCacheStorageClass(); + } // function getCacheStorageClass() + + + /** + * Set the method that should be used for cell cacheing + * + * @param string $method Name of the cacheing method + * @param array $arguments Optional configuration arguments for the cacheing method + * @return boolean Success or failure + */ + public static function setCacheStorageMethod( + $method = PHPExcel_CachedObjectStorageFactory::cache_in_memory, + $arguments = array() + ) + { + return PHPExcel_CachedObjectStorageFactory::initialize($method, $arguments); + } // function setCacheStorageMethod() + + + /** + * Set the locale code to use for formula translations and any special formatting + * + * @param string $locale The locale code to use (e.g. "fr" or "pt_br" or "en_uk") + * @return boolean Success or failure + */ + public static function setLocale($locale='en_us') + { + return PHPExcel_Calculation::getInstance()->setLocale($locale); + } // function setLocale() + + + /** + * Set details of the external library that PHPExcel should use for rendering charts + * + * @param string $libraryName Internal reference name of the library + * e.g. PHPExcel_Settings::CHART_RENDERER_JPGRAPH + * @param string $libraryBaseDir Directory path to the library's base folder + * + * @return boolean Success or failure + */ + public static function setChartRenderer($libraryName, $libraryBaseDir) + { + if (!self::setChartRendererName($libraryName)) + return FALSE; + return self::setChartRendererPath($libraryBaseDir); + } // function setChartRenderer() + + + /** + * Identify to PHPExcel the external library to use for rendering charts + * + * @param string $libraryName Internal reference name of the library + * e.g. PHPExcel_Settings::CHART_RENDERER_JPGRAPH + * + * @return boolean Success or failure + */ + public static function setChartRendererName($libraryName) + { + if (!in_array($libraryName,self::$_chartRenderers)) { + return FALSE; + } + + self::$_chartRendererName = $libraryName; + + return TRUE; + } // function setChartRendererName() + + + /** + * Tell PHPExcel where to find the external library to use for rendering charts + * + * @param string $libraryBaseDir Directory path to the library's base folder + * @return boolean Success or failure + */ + public static function setChartRendererPath($libraryBaseDir) + { + if ((file_exists($libraryBaseDir) === false) || (is_readable($libraryBaseDir) === false)) { + return FALSE; + } + self::$_chartRendererPath = $libraryBaseDir; + + return TRUE; + } // function setChartRendererPath() + + + /** + * Return the Chart Rendering Library that PHPExcel is currently configured to use (e.g. jpgraph) + * + * @return string|NULL Internal reference name of the Chart Rendering Library that PHPExcel is + * currently configured to use + * e.g. PHPExcel_Settings::CHART_RENDERER_JPGRAPH + */ + public static function getChartRendererName() + { + return self::$_chartRendererName; + } // function getChartRendererName() + + + /** + * Return the directory path to the Chart Rendering Library that PHPExcel is currently configured to use + * + * @return string|NULL Directory Path to the Chart Rendering Library that PHPExcel is + * currently configured to use + */ + public static function getChartRendererPath() + { + return self::$_chartRendererPath; + } // function getChartRendererPath() + + + /** + * Set details of the external library that PHPExcel should use for rendering PDF files + * + * @param string $libraryName Internal reference name of the library + * e.g. PHPExcel_Settings::PDF_RENDERER_TCPDF, + * PHPExcel_Settings::PDF_RENDERER_DOMPDF + * or PHPExcel_Settings::PDF_RENDERER_MPDF + * @param string $libraryBaseDir Directory path to the library's base folder + * + * @return boolean Success or failure + */ + public static function setPdfRenderer($libraryName, $libraryBaseDir) + { + if (!self::setPdfRendererName($libraryName)) + return FALSE; + return self::setPdfRendererPath($libraryBaseDir); + } // function setPdfRenderer() + + + /** + * Identify to PHPExcel the external library to use for rendering PDF files + * + * @param string $libraryName Internal reference name of the library + * e.g. PHPExcel_Settings::PDF_RENDERER_TCPDF, + * PHPExcel_Settings::PDF_RENDERER_DOMPDF + * or PHPExcel_Settings::PDF_RENDERER_MPDF + * + * @return boolean Success or failure + */ + public static function setPdfRendererName($libraryName) + { + if (!in_array($libraryName,self::$_pdfRenderers)) { + return FALSE; + } + + self::$_pdfRendererName = $libraryName; + + return TRUE; + } // function setPdfRendererName() + + + /** + * Tell PHPExcel where to find the external library to use for rendering PDF files + * + * @param string $libraryBaseDir Directory path to the library's base folder + * @return boolean Success or failure + */ + public static function setPdfRendererPath($libraryBaseDir) + { + if ((file_exists($libraryBaseDir) === false) || (is_readable($libraryBaseDir) === false)) { + return FALSE; + } + self::$_pdfRendererPath = $libraryBaseDir; + + return TRUE; + } // function setPdfRendererPath() + + + /** + * Return the PDF Rendering Library that PHPExcel is currently configured to use (e.g. dompdf) + * + * @return string|NULL Internal reference name of the PDF Rendering Library that PHPExcel is + * currently configured to use + * e.g. PHPExcel_Settings::PDF_RENDERER_TCPDF, + * PHPExcel_Settings::PDF_RENDERER_DOMPDF + * or PHPExcel_Settings::PDF_RENDERER_MPDF + */ + public static function getPdfRendererName() + { + return self::$_pdfRendererName; + } // function getPdfRendererName() + + + /** + * Return the directory path to the PDF Rendering Library that PHPExcel is currently configured to use + * + * @return string|NULL Directory Path to the PDF Rendering Library that PHPExcel is + * currently configured to use + */ + public static function getPdfRendererPath() + { + return self::$_pdfRendererPath; + } // function getPdfRendererPath() + +} \ No newline at end of file diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/CodePage.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/CodePage.php new file mode 100755 index 0000000..af70760 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/CodePage.php @@ -0,0 +1,101 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Shared_CodePage + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_CodePage +{ + /** + * Convert Microsoft Code Page Identifier to Code Page Name which iconv + * and mbstring understands + * + * @param integer $codePage Microsoft Code Page Indentifier + * @return string Code Page Name + * @throws PHPExcel_Exception + */ + public static function NumberToName($codePage = 1252) + { + switch ($codePage) { + case 367: return 'ASCII'; break; // ASCII + case 437: return 'CP437'; break; // OEM US + case 720: throw new PHPExcel_Exception('Code page 720 not supported.'); + break; // OEM Arabic + case 737: return 'CP737'; break; // OEM Greek + case 775: return 'CP775'; break; // OEM Baltic + case 850: return 'CP850'; break; // OEM Latin I + case 852: return 'CP852'; break; // OEM Latin II (Central European) + case 855: return 'CP855'; break; // OEM Cyrillic + case 857: return 'CP857'; break; // OEM Turkish + case 858: return 'CP858'; break; // OEM Multilingual Latin I with Euro + case 860: return 'CP860'; break; // OEM Portugese + case 861: return 'CP861'; break; // OEM Icelandic + case 862: return 'CP862'; break; // OEM Hebrew + case 863: return 'CP863'; break; // OEM Canadian (French) + case 864: return 'CP864'; break; // OEM Arabic + case 865: return 'CP865'; break; // OEM Nordic + case 866: return 'CP866'; break; // OEM Cyrillic (Russian) + case 869: return 'CP869'; break; // OEM Greek (Modern) + case 874: return 'CP874'; break; // ANSI Thai + case 932: return 'CP932'; break; // ANSI Japanese Shift-JIS + case 936: return 'CP936'; break; // ANSI Chinese Simplified GBK + case 949: return 'CP949'; break; // ANSI Korean (Wansung) + case 950: return 'CP950'; break; // ANSI Chinese Traditional BIG5 + case 1200: return 'UTF-16LE'; break; // UTF-16 (BIFF8) + case 1250: return 'CP1250'; break; // ANSI Latin II (Central European) + case 1251: return 'CP1251'; break; // ANSI Cyrillic + case 0: // CodePage is not always correctly set when the xls file was saved by Apple's Numbers program + case 1252: return 'CP1252'; break; // ANSI Latin I (BIFF4-BIFF7) + case 1253: return 'CP1253'; break; // ANSI Greek + case 1254: return 'CP1254'; break; // ANSI Turkish + case 1255: return 'CP1255'; break; // ANSI Hebrew + case 1256: return 'CP1256'; break; // ANSI Arabic + case 1257: return 'CP1257'; break; // ANSI Baltic + case 1258: return 'CP1258'; break; // ANSI Vietnamese + case 1361: return 'CP1361'; break; // ANSI Korean (Johab) + case 10000: return 'MAC'; break; // Apple Roman + case 10006: return 'MACGREEK'; break; // Macintosh Greek + case 10007: return 'MACCYRILLIC'; break; // Macintosh Cyrillic + case 10029: return 'MACCENTRALEUROPE'; break; // Macintosh Central Europe + case 10079: return 'MACICELAND'; break; // Macintosh Icelandic + case 10081: return 'MACTURKISH'; break; // Macintosh Turkish + case 32768: return 'MAC'; break; // Apple Roman + case 32769: throw new PHPExcel_Exception('Code page 32769 not supported.'); + break; // ANSI Latin I (BIFF2-BIFF3) + case 65000: return 'UTF-7'; break; // Unicode (UTF-7) + case 65001: return 'UTF-8'; break; // Unicode (UTF-8) + } + + throw new PHPExcel_Exception('Unknown codepage: ' . $codePage); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Date.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Date.php new file mode 100755 index 0000000..6af4b3b --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Date.php @@ -0,0 +1,390 @@ +<?php + +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Shared_Date + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Date +{ + /** constants */ + const CALENDAR_WINDOWS_1900 = 1900; // Base date of 1st Jan 1900 = 1.0 + const CALENDAR_MAC_1904 = 1904; // Base date of 2nd Jan 1904 = 1.0 + + /* + * Names of the months of the year, indexed by shortname + * Planned usage for locale settings + * + * @public + * @var string[] + */ + public static $_monthNames = array( 'Jan' => 'January', + 'Feb' => 'February', + 'Mar' => 'March', + 'Apr' => 'April', + 'May' => 'May', + 'Jun' => 'June', + 'Jul' => 'July', + 'Aug' => 'August', + 'Sep' => 'September', + 'Oct' => 'October', + 'Nov' => 'November', + 'Dec' => 'December', + ); + + /* + * Names of the months of the year, indexed by shortname + * Planned usage for locale settings + * + * @public + * @var string[] + */ + public static $_numberSuffixes = array( 'st', + 'nd', + 'rd', + 'th', + ); + + /* + * Base calendar year to use for calculations + * + * @private + * @var int + */ + protected static $_excelBaseDate = self::CALENDAR_WINDOWS_1900; + + /** + * Set the Excel calendar (Windows 1900 or Mac 1904) + * + * @param integer $baseDate Excel base date (1900 or 1904) + * @return boolean Success or failure + */ + public static function setExcelCalendar($baseDate) { + if (($baseDate == self::CALENDAR_WINDOWS_1900) || + ($baseDate == self::CALENDAR_MAC_1904)) { + self::$_excelBaseDate = $baseDate; + return TRUE; + } + return FALSE; + } // function setExcelCalendar() + + + /** + * Return the Excel calendar (Windows 1900 or Mac 1904) + * + * @return integer Excel base date (1900 or 1904) + */ + public static function getExcelCalendar() { + return self::$_excelBaseDate; + } // function getExcelCalendar() + + + /** + * Convert a date from Excel to PHP + * + * @param long $dateValue Excel date/time value + * @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as + * a UST timestamp, or adjusted to UST + * @param string $timezone The timezone for finding the adjustment from UST + * @return long PHP serialized date/time + */ + public static function ExcelToPHP($dateValue = 0, $adjustToTimezone = FALSE, $timezone = NULL) { + if (self::$_excelBaseDate == self::CALENDAR_WINDOWS_1900) { + $my_excelBaseDate = 25569; + // Adjust for the spurious 29-Feb-1900 (Day 60) + if ($dateValue < 60) { + --$my_excelBaseDate; + } + } else { + $my_excelBaseDate = 24107; + } + + // Perform conversion + if ($dateValue >= 1) { + $utcDays = $dateValue - $my_excelBaseDate; + $returnValue = round($utcDays * 86400); + if (($returnValue <= PHP_INT_MAX) && ($returnValue >= -PHP_INT_MAX)) { + $returnValue = (integer) $returnValue; + } + } else { + $hours = round($dateValue * 24); + $mins = round($dateValue * 1440) - round($hours * 60); + $secs = round($dateValue * 86400) - round($hours * 3600) - round($mins * 60); + $returnValue = (integer) gmmktime($hours, $mins, $secs); + } + + $timezoneAdjustment = ($adjustToTimezone) ? + PHPExcel_Shared_TimeZone::getTimezoneAdjustment($timezone, $returnValue) : + 0; + + // Return + return $returnValue + $timezoneAdjustment; + } // function ExcelToPHP() + + + /** + * Convert a date from Excel to a PHP Date/Time object + * + * @param integer $dateValue Excel date/time value + * @return integer PHP date/time object + */ + public static function ExcelToPHPObject($dateValue = 0) { + $dateTime = self::ExcelToPHP($dateValue); + $days = floor($dateTime / 86400); + $time = round((($dateTime / 86400) - $days) * 86400); + $hours = round($time / 3600); + $minutes = round($time / 60) - ($hours * 60); + $seconds = round($time) - ($hours * 3600) - ($minutes * 60); + + $dateObj = date_create('1-Jan-1970+'.$days.' days'); + $dateObj->setTime($hours,$minutes,$seconds); + + return $dateObj; + } // function ExcelToPHPObject() + + + /** + * Convert a date from PHP to Excel + * + * @param mixed $dateValue PHP serialized date/time or date object + * @param boolean $adjustToTimezone Flag indicating whether $dateValue should be treated as + * a UST timestamp, or adjusted to UST + * @param string $timezone The timezone for finding the adjustment from UST + * @return mixed Excel date/time value + * or boolean FALSE on failure + */ + public static function PHPToExcel($dateValue = 0, $adjustToTimezone = FALSE, $timezone = NULL) { + $saveTimeZone = date_default_timezone_get(); + date_default_timezone_set('UTC'); + $retValue = FALSE; + if ((is_object($dateValue)) && ($dateValue instanceof DateTime)) { + $retValue = self::FormattedPHPToExcel( $dateValue->format('Y'), $dateValue->format('m'), $dateValue->format('d'), + $dateValue->format('H'), $dateValue->format('i'), $dateValue->format('s') + ); + } elseif (is_numeric($dateValue)) { + $retValue = self::FormattedPHPToExcel( date('Y',$dateValue), date('m',$dateValue), date('d',$dateValue), + date('H',$dateValue), date('i',$dateValue), date('s',$dateValue) + ); + } + date_default_timezone_set($saveTimeZone); + + return $retValue; + } // function PHPToExcel() + + + /** + * FormattedPHPToExcel + * + * @param long $year + * @param long $month + * @param long $day + * @param long $hours + * @param long $minutes + * @param long $seconds + * @return long Excel date/time value + */ + public static function FormattedPHPToExcel($year, $month, $day, $hours=0, $minutes=0, $seconds=0) { + if (self::$_excelBaseDate == self::CALENDAR_WINDOWS_1900) { + // + // Fudge factor for the erroneous fact that the year 1900 is treated as a Leap Year in MS Excel + // This affects every date following 28th February 1900 + // + $excel1900isLeapYear = TRUE; + if (($year == 1900) && ($month <= 2)) { $excel1900isLeapYear = FALSE; } + $my_excelBaseDate = 2415020; + } else { + $my_excelBaseDate = 2416481; + $excel1900isLeapYear = FALSE; + } + + // Julian base date Adjustment + if ($month > 2) { + $month -= 3; + } else { + $month += 9; + --$year; + } + + // Calculate the Julian Date, then subtract the Excel base date (JD 2415020 = 31-Dec-1899 Giving Excel Date of 0) + $century = substr($year,0,2); + $decade = substr($year,2,2); + $excelDate = floor((146097 * $century) / 4) + floor((1461 * $decade) / 4) + floor((153 * $month + 2) / 5) + $day + 1721119 - $my_excelBaseDate + $excel1900isLeapYear; + + $excelTime = (($hours * 3600) + ($minutes * 60) + $seconds) / 86400; + + return (float) $excelDate + $excelTime; + } // function FormattedPHPToExcel() + + + /** + * Is a given cell a date/time? + * + * @param PHPExcel_Cell $pCell + * @return boolean + */ + public static function isDateTime(PHPExcel_Cell $pCell) { + return self::isDateTimeFormat( + $pCell->getWorksheet()->getStyle( + $pCell->getCoordinate() + )->getNumberFormat() + ); + } // function isDateTime() + + + /** + * Is a given number format a date/time? + * + * @param PHPExcel_Style_NumberFormat $pFormat + * @return boolean + */ + public static function isDateTimeFormat(PHPExcel_Style_NumberFormat $pFormat) { + return self::isDateTimeFormatCode($pFormat->getFormatCode()); + } // function isDateTimeFormat() + + + private static $possibleDateFormatCharacters = 'eymdHs'; + + /** + * Is a given number format code a date/time? + * + * @param string $pFormatCode + * @return boolean + */ + public static function isDateTimeFormatCode($pFormatCode = '') { + // Switch on formatcode + switch ($pFormatCode) { + // General contains an epoch letter 'e', so we trap for it explicitly here + case PHPExcel_Style_NumberFormat::FORMAT_GENERAL: + return FALSE; + // Explicitly defined date formats + case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDD2: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_DDMMYYYY: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMYSLASH: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMYMINUS: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_DMMINUS: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_MYMINUS: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_DATETIME: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME1: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME2: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME3: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME4: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME5: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME6: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME7: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_TIME8: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_YYYYMMDDSLASH: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX14: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX15: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX16: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX17: + case PHPExcel_Style_NumberFormat::FORMAT_DATE_XLSX22: + return TRUE; + } + + // Typically number, currency or accounting (or occasionally fraction) formats + if ((substr($pFormatCode,0,1) == '_') || (substr($pFormatCode,0,2) == '0 ')) { + return FALSE; + } + // Try checking for any of the date formatting characters that don't appear within square braces + if (preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i',$pFormatCode)) { + // We might also have a format mask containing quoted strings... + // we don't want to test for any of our characters within the quoted blocks + if (strpos($pFormatCode,'"') !== FALSE) { + $segMatcher = FALSE; + foreach(explode('"',$pFormatCode) as $subVal) { + // Only test in alternate array entries (the non-quoted blocks) + if (($segMatcher = !$segMatcher) && + (preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i',$subVal))) { + return TRUE; + } + } + return FALSE; + } + return TRUE; + } + + // No date... + return FALSE; + } // function isDateTimeFormatCode() + + + /** + * Convert a date/time string to Excel time + * + * @param string $dateValue Examples: '2009-12-31', '2009-12-31 15:59', '2009-12-31 15:59:10' + * @return float|FALSE Excel date/time serial value + */ + public static function stringToExcel($dateValue = '') { + if (strlen($dateValue) < 2) + return FALSE; + if (!preg_match('/^(\d{1,4}[ \.\/\-][A-Z]{3,9}([ \.\/\-]\d{1,4})?|[A-Z]{3,9}[ \.\/\-]\d{1,4}([ \.\/\-]\d{1,4})?|\d{1,4}[ \.\/\-]\d{1,4}([ \.\/\-]\d{1,4})?)( \d{1,2}:\d{1,2}(:\d{1,2})?)?$/iu', $dateValue)) + return FALSE; + + $dateValueNew = PHPExcel_Calculation_DateTime::DATEVALUE($dateValue); + + if ($dateValueNew === PHPExcel_Calculation_Functions::VALUE()) { + return FALSE; + } else { + if (strpos($dateValue, ':') !== FALSE) { + $timeValue = PHPExcel_Calculation_DateTime::TIMEVALUE($dateValue); + if ($timeValue === PHPExcel_Calculation_Functions::VALUE()) { + return FALSE; + } + $dateValueNew += $timeValue; + } + return $dateValueNew; + } + + + } + + public static function monthStringToNumber($month) { + $monthIndex = 1; + foreach(self::$_monthNames as $shortMonthName => $longMonthName) { + if (($month === $longMonthName) || ($month === $shortMonthName)) { + return $monthIndex; + } + ++$monthIndex; + } + return $month; + } + + public static function dayStringToNumber($day) { + $strippedDayValue = (str_replace(self::$_numberSuffixes,'',$day)); + if (is_numeric($strippedDayValue)) { + return $strippedDayValue; + } + return $day; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Drawing.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Drawing.php new file mode 100755 index 0000000..b8b59fd --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Drawing.php @@ -0,0 +1,272 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Shared_Drawing + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Drawing +{ + /** + * Convert pixels to EMU + * + * @param int $pValue Value in pixels + * @return int Value in EMU + */ + public static function pixelsToEMU($pValue = 0) { + return round($pValue * 9525); + } + + /** + * Convert EMU to pixels + * + * @param int $pValue Value in EMU + * @return int Value in pixels + */ + public static function EMUToPixels($pValue = 0) { + if ($pValue != 0) { + return round($pValue / 9525); + } else { + return 0; + } + } + + /** + * Convert pixels to column width. Exact algorithm not known. + * By inspection of a real Excel file using Calibri 11, one finds 1000px ~ 142.85546875 + * This gives a conversion factor of 7. Also, we assume that pixels and font size are proportional. + * + * @param int $pValue Value in pixels + * @param PHPExcel_Style_Font $pDefaultFont Default font of the workbook + * @return int Value in cell dimension + */ + public static function pixelsToCellDimension($pValue = 0, PHPExcel_Style_Font $pDefaultFont) { + // Font name and size + $name = $pDefaultFont->getName(); + $size = $pDefaultFont->getSize(); + + if (isset(PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size])) { + // Exact width can be determined + $colWidth = $pValue + * PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['width'] + / PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['px']; + } else { + // We don't have data for this particular font and size, use approximation by + // extrapolating from Calibri 11 + $colWidth = $pValue * 11 + * PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['width'] + / PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['px'] / $size; + } + + return $colWidth; + } + + /** + * Convert column width from (intrinsic) Excel units to pixels + * + * @param float $pValue Value in cell dimension + * @param PHPExcel_Style_Font $pDefaultFont Default font of the workbook + * @return int Value in pixels + */ + public static function cellDimensionToPixels($pValue = 0, PHPExcel_Style_Font $pDefaultFont) { + // Font name and size + $name = $pDefaultFont->getName(); + $size = $pDefaultFont->getSize(); + + if (isset(PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size])) { + // Exact width can be determined + $colWidth = $pValue + * PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['px'] + / PHPExcel_Shared_Font::$defaultColumnWidths[$name][$size]['width']; + + } else { + // We don't have data for this particular font and size, use approximation by + // extrapolating from Calibri 11 + $colWidth = $pValue * $size + * PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['px'] + / PHPExcel_Shared_Font::$defaultColumnWidths['Calibri'][11]['width'] / 11; + } + + // Round pixels to closest integer + $colWidth = (int) round($colWidth); + + return $colWidth; + } + + /** + * Convert pixels to points + * + * @param int $pValue Value in pixels + * @return int Value in points + */ + public static function pixelsToPoints($pValue = 0) { + return $pValue * 0.67777777; + } + + /** + * Convert points to pixels + * + * @param int $pValue Value in points + * @return int Value in pixels + */ + public static function pointsToPixels($pValue = 0) { + if ($pValue != 0) { + return (int) ceil($pValue * 1.333333333); + } else { + return 0; + } + } + + /** + * Convert degrees to angle + * + * @param int $pValue Degrees + * @return int Angle + */ + public static function degreesToAngle($pValue = 0) { + return (int)round($pValue * 60000); + } + + /** + * Convert angle to degrees + * + * @param int $pValue Angle + * @return int Degrees + */ + public static function angleToDegrees($pValue = 0) { + if ($pValue != 0) { + return round($pValue / 60000); + } else { + return 0; + } + } + + /** + * Create a new image from file. By alexander at alexauto dot nl + * + * @link http://www.php.net/manual/en/function.imagecreatefromwbmp.php#86214 + * @param string $filename Path to Windows DIB (BMP) image + * @return resource + */ + public static function imagecreatefrombmp($p_sFile) + { + // Load the image into a string + $file = fopen($p_sFile,"rb"); + $read = fread($file,10); + while(!feof($file)&&($read<>"")) + $read .= fread($file,1024); + + $temp = unpack("H*",$read); + $hex = $temp[1]; + $header = substr($hex,0,108); + + // Process the header + // Structure: http://www.fastgraph.com/help/bmp_header_format.html + if (substr($header,0,4)=="424d") + { + // Cut it in parts of 2 bytes + $header_parts = str_split($header,2); + + // Get the width 4 bytes + $width = hexdec($header_parts[19].$header_parts[18]); + + // Get the height 4 bytes + $height = hexdec($header_parts[23].$header_parts[22]); + + // Unset the header params + unset($header_parts); + } + + // Define starting X and Y + $x = 0; + $y = 1; + + // Create newimage + $image = imagecreatetruecolor($width,$height); + + // Grab the body from the image + $body = substr($hex,108); + + // Calculate if padding at the end-line is needed + // Divided by two to keep overview. + // 1 byte = 2 HEX-chars + $body_size = (strlen($body)/2); + $header_size = ($width*$height); + + // Use end-line padding? Only when needed + $usePadding = ($body_size>($header_size*3)+4); + + // Using a for-loop with index-calculation instaid of str_split to avoid large memory consumption + // Calculate the next DWORD-position in the body + for ($i=0;$i<$body_size;$i+=3) + { + // Calculate line-ending and padding + if ($x>=$width) + { + // If padding needed, ignore image-padding + // Shift i to the ending of the current 32-bit-block + if ($usePadding) + $i += $width%4; + + // Reset horizontal position + $x = 0; + + // Raise the height-position (bottom-up) + $y++; + + // Reached the image-height? Break the for-loop + if ($y>$height) + break; + } + + // Calculation of the RGB-pixel (defined as BGR in image-data) + // Define $i_pos as absolute position in the body + $i_pos = $i*2; + $r = hexdec($body[$i_pos+4].$body[$i_pos+5]); + $g = hexdec($body[$i_pos+2].$body[$i_pos+3]); + $b = hexdec($body[$i_pos].$body[$i_pos+1]); + + // Calculate and draw the pixel + $color = imagecolorallocate($image,$r,$g,$b); + imagesetpixel($image,$x,$height-$y,$color); + + // Raise the horizontal position + $x++; + } + + // Unset the body / free the memory + unset($body); + + // Return image-object + return $image; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher.php new file mode 100755 index 0000000..cf75a0f --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher.php @@ -0,0 +1,91 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** + * PHPExcel_Shared_Escher + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Escher +{ + /** + * Drawing Group Container + * + * @var PHPExcel_Shared_Escher_DggContainer + */ + private $_dggContainer; + + /** + * Drawing Container + * + * @var PHPExcel_Shared_Escher_DgContainer + */ + private $_dgContainer; + + /** + * Get Drawing Group Container + * + * @return PHPExcel_Shared_Escher_DgContainer + */ + public function getDggContainer() + { + return $this->_dggContainer; + } + + /** + * Set Drawing Group Container + * + * @param PHPExcel_Shared_Escher_DggContainer $dggContainer + */ + public function setDggContainer($dggContainer) + { + return $this->_dggContainer = $dggContainer; + } + + /** + * Get Drawing Container + * + * @return PHPExcel_Shared_Escher_DgContainer + */ + public function getDgContainer() + { + return $this->_dgContainer; + } + + /** + * Set Drawing Container + * + * @param PHPExcel_Shared_Escher_DgContainer $dgContainer + */ + public function setDgContainer($dgContainer) + { + return $this->_dgContainer = $dgContainer; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer.php new file mode 100755 index 0000000..d816e41 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer.php @@ -0,0 +1,83 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** + * PHPExcel_Shared_Escher_DgContainer + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Escher_DgContainer +{ + /** + * Drawing index, 1-based. + * + * @var int + */ + private $_dgId; + + /** + * Last shape index in this drawing + * + * @var int + */ + private $_lastSpId; + + private $_spgrContainer = null; + + public function getDgId() + { + return $this->_dgId; + } + + public function setDgId($value) + { + $this->_dgId = $value; + } + + public function getLastSpId() + { + return $this->_lastSpId; + } + + public function setLastSpId($value) + { + $this->_lastSpId = $value; + } + + public function getSpgrContainer() + { + return $this->_spgrContainer; + } + + public function setSpgrContainer($spgrContainer) + { + return $this->_spgrContainer = $spgrContainer; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php new file mode 100755 index 0000000..c0c404f --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer/SpgrContainer.php @@ -0,0 +1,109 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** + * PHPExcel_Shared_Escher_DgContainer_SpgrContainer + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Escher_DgContainer_SpgrContainer +{ + /** + * Parent Shape Group Container + * + * @var PHPExcel_Shared_Escher_DgContainer_SpgrContainer + */ + private $_parent; + + /** + * Shape Container collection + * + * @var array + */ + private $_children = array(); + + /** + * Set parent Shape Group Container + * + * @param PHPExcel_Shared_Escher_DgContainer_SpgrContainer $parent + */ + public function setParent($parent) + { + $this->_parent = $parent; + } + + /** + * Get the parent Shape Group Container if any + * + * @return PHPExcel_Shared_Escher_DgContainer_SpgrContainer|null + */ + public function getParent() + { + return $this->_parent; + } + + /** + * Add a child. This will be either spgrContainer or spContainer + * + * @param mixed $child + */ + public function addChild($child) + { + $this->_children[] = $child; + $child->setParent($this); + } + + /** + * Get collection of Shape Containers + */ + public function getChildren() + { + return $this->_children; + } + + /** + * Recursively get all spContainers within this spgrContainer + * + * @return PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer[] + */ + public function getAllSpContainers() + { + $allSpContainers = array(); + + foreach ($this->_children as $child) { + if ($child instanceof PHPExcel_Shared_Escher_DgContainer_SpgrContainer) { + $allSpContainers = array_merge($allSpContainers, $child->getAllSpContainers()); + } else { + $allSpContainers[] = $child; + } + } + + return $allSpContainers; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php new file mode 100755 index 0000000..f786aba --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DgContainer/SpgrContainer/SpContainer.php @@ -0,0 +1,395 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** + * PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer +{ + /** + * Parent Shape Group Container + * + * @var PHPExcel_Shared_Escher_DgContainer_SpgrContainer + */ + private $_parent; + + /** + * Is this a group shape? + * + * @var boolean + */ + private $_spgr = false; + + /** + * Shape type + * + * @var int + */ + private $_spType; + + /** + * Shape flag + * + * @var int + */ + private $_spFlag; + + /** + * Shape index (usually group shape has index 0, and the rest: 1,2,3...) + * + * @var boolean + */ + private $_spId; + + /** + * Array of options + * + * @var array + */ + private $_OPT; + + /** + * Cell coordinates of upper-left corner of shape, e.g. 'A1' + * + * @var string + */ + private $_startCoordinates; + + /** + * Horizontal offset of upper-left corner of shape measured in 1/1024 of column width + * + * @var int + */ + private $_startOffsetX; + + /** + * Vertical offset of upper-left corner of shape measured in 1/256 of row height + * + * @var int + */ + private $_startOffsetY; + + /** + * Cell coordinates of bottom-right corner of shape, e.g. 'B2' + * + * @var string + */ + private $_endCoordinates; + + /** + * Horizontal offset of bottom-right corner of shape measured in 1/1024 of column width + * + * @var int + */ + private $_endOffsetX; + + /** + * Vertical offset of bottom-right corner of shape measured in 1/256 of row height + * + * @var int + */ + private $_endOffsetY; + + /** + * Set parent Shape Group Container + * + * @param PHPExcel_Shared_Escher_DgContainer_SpgrContainer $parent + */ + public function setParent($parent) + { + $this->_parent = $parent; + } + + /** + * Get the parent Shape Group Container + * + * @return PHPExcel_Shared_Escher_DgContainer_SpgrContainer + */ + public function getParent() + { + return $this->_parent; + } + + /** + * Set whether this is a group shape + * + * @param boolean $value + */ + public function setSpgr($value = false) + { + $this->_spgr = $value; + } + + /** + * Get whether this is a group shape + * + * @return boolean + */ + public function getSpgr() + { + return $this->_spgr; + } + + /** + * Set the shape type + * + * @param int $value + */ + public function setSpType($value) + { + $this->_spType = $value; + } + + /** + * Get the shape type + * + * @return int + */ + public function getSpType() + { + return $this->_spType; + } + + /** + * Set the shape flag + * + * @param int $value + */ + public function setSpFlag($value) + { + $this->_spFlag = $value; + } + + /** + * Get the shape flag + * + * @return int + */ + public function getSpFlag() + { + return $this->_spFlag; + } + + /** + * Set the shape index + * + * @param int $value + */ + public function setSpId($value) + { + $this->_spId = $value; + } + + /** + * Get the shape index + * + * @return int + */ + public function getSpId() + { + return $this->_spId; + } + + /** + * Set an option for the Shape Group Container + * + * @param int $property The number specifies the option + * @param mixed $value + */ + public function setOPT($property, $value) + { + $this->_OPT[$property] = $value; + } + + /** + * Get an option for the Shape Group Container + * + * @param int $property The number specifies the option + * @return mixed + */ + public function getOPT($property) + { + if (isset($this->_OPT[$property])) { + return $this->_OPT[$property]; + } + return null; + } + + /** + * Get the collection of options + * + * @return array + */ + public function getOPTCollection() + { + return $this->_OPT; + } + + /** + * Set cell coordinates of upper-left corner of shape + * + * @param string $value + */ + public function setStartCoordinates($value = 'A1') + { + $this->_startCoordinates = $value; + } + + /** + * Get cell coordinates of upper-left corner of shape + * + * @return string + */ + public function getStartCoordinates() + { + return $this->_startCoordinates; + } + + /** + * Set offset in x-direction of upper-left corner of shape measured in 1/1024 of column width + * + * @param int $startOffsetX + */ + public function setStartOffsetX($startOffsetX = 0) + { + $this->_startOffsetX = $startOffsetX; + } + + /** + * Get offset in x-direction of upper-left corner of shape measured in 1/1024 of column width + * + * @return int + */ + public function getStartOffsetX() + { + return $this->_startOffsetX; + } + + /** + * Set offset in y-direction of upper-left corner of shape measured in 1/256 of row height + * + * @param int $startOffsetY + */ + public function setStartOffsetY($startOffsetY = 0) + { + $this->_startOffsetY = $startOffsetY; + } + + /** + * Get offset in y-direction of upper-left corner of shape measured in 1/256 of row height + * + * @return int + */ + public function getStartOffsetY() + { + return $this->_startOffsetY; + } + + /** + * Set cell coordinates of bottom-right corner of shape + * + * @param string $value + */ + public function setEndCoordinates($value = 'A1') + { + $this->_endCoordinates = $value; + } + + /** + * Get cell coordinates of bottom-right corner of shape + * + * @return string + */ + public function getEndCoordinates() + { + return $this->_endCoordinates; + } + + /** + * Set offset in x-direction of bottom-right corner of shape measured in 1/1024 of column width + * + * @param int $startOffsetX + */ + public function setEndOffsetX($endOffsetX = 0) + { + $this->_endOffsetX = $endOffsetX; + } + + /** + * Get offset in x-direction of bottom-right corner of shape measured in 1/1024 of column width + * + * @return int + */ + public function getEndOffsetX() + { + return $this->_endOffsetX; + } + + /** + * Set offset in y-direction of bottom-right corner of shape measured in 1/256 of row height + * + * @param int $endOffsetY + */ + public function setEndOffsetY($endOffsetY = 0) + { + $this->_endOffsetY = $endOffsetY; + } + + /** + * Get offset in y-direction of bottom-right corner of shape measured in 1/256 of row height + * + * @return int + */ + public function getEndOffsetY() + { + return $this->_endOffsetY; + } + + /** + * Get the nesting level of this spContainer. This is the number of spgrContainers between this spContainer and + * the dgContainer. A value of 1 = immediately within first spgrContainer + * Higher nesting level occurs if and only if spContainer is part of a shape group + * + * @return int Nesting level + */ + public function getNestingLevel() + { + $nestingLevel = 0; + + $parent = $this->getParent(); + while ($parent instanceof PHPExcel_Shared_Escher_DgContainer_SpgrContainer) { + ++$nestingLevel; + $parent = $parent->getParent(); + } + + return $nestingLevel; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer.php new file mode 100755 index 0000000..323af59 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer.php @@ -0,0 +1,203 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** + * PHPExcel_Shared_Escher_DggContainer + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Escher_DggContainer +{ + /** + * Maximum shape index of all shapes in all drawings increased by one + * + * @var int + */ + private $_spIdMax; + + /** + * Total number of drawings saved + * + * @var int + */ + private $_cDgSaved; + + /** + * Total number of shapes saved (including group shapes) + * + * @var int + */ + private $_cSpSaved; + + /** + * BLIP Store Container + * + * @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer + */ + private $_bstoreContainer; + + /** + * Array of options for the drawing group + * + * @var array + */ + private $_OPT = array(); + + /** + * Array of identifier clusters containg information about the maximum shape identifiers + * + * @var array + */ + private $_IDCLs = array(); + + /** + * Get maximum shape index of all shapes in all drawings (plus one) + * + * @return int + */ + public function getSpIdMax() + { + return $this->_spIdMax; + } + + /** + * Set maximum shape index of all shapes in all drawings (plus one) + * + * @param int + */ + public function setSpIdMax($value) + { + $this->_spIdMax = $value; + } + + /** + * Get total number of drawings saved + * + * @return int + */ + public function getCDgSaved() + { + return $this->_cDgSaved; + } + + /** + * Set total number of drawings saved + * + * @param int + */ + public function setCDgSaved($value) + { + $this->_cDgSaved = $value; + } + + /** + * Get total number of shapes saved (including group shapes) + * + * @return int + */ + public function getCSpSaved() + { + return $this->_cSpSaved; + } + + /** + * Set total number of shapes saved (including group shapes) + * + * @param int + */ + public function setCSpSaved($value) + { + $this->_cSpSaved = $value; + } + + /** + * Get BLIP Store Container + * + * @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer + */ + public function getBstoreContainer() + { + return $this->_bstoreContainer; + } + + /** + * Set BLIP Store Container + * + * @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer $bstoreContainer + */ + public function setBstoreContainer($bstoreContainer) + { + $this->_bstoreContainer = $bstoreContainer; + } + + /** + * Set an option for the drawing group + * + * @param int $property The number specifies the option + * @param mixed $value + */ + public function setOPT($property, $value) + { + $this->_OPT[$property] = $value; + } + + /** + * Get an option for the drawing group + * + * @param int $property The number specifies the option + * @return mixed + */ + public function getOPT($property) + { + if (isset($this->_OPT[$property])) { + return $this->_OPT[$property]; + } + return null; + } + + /** + * Get identifier clusters + * + * @return array + */ + public function getIDCLs() + { + return $this->_IDCLs; + } + + /** + * Set identifier clusters. array(<drawingId> => <max shape id>, ...) + * + * @param array $pValue + */ + public function setIDCLs($pValue) + { + $this->_IDCLs = $pValue; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php new file mode 100755 index 0000000..76288b9 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer.php @@ -0,0 +1,65 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** + * PHPExcel_Shared_Escher_DggContainer_BstoreContainer + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Escher_DggContainer_BstoreContainer +{ + /** + * BLIP Store Entries. Each of them holds one BLIP (Big Large Image or Picture) + * + * @var array + */ + private $_BSECollection = array(); + + /** + * Add a BLIP Store Entry + * + * @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE $BSE + */ + public function addBSE($BSE) + { + $this->_BSECollection[] = $BSE; + $BSE->setParent($this); + } + + /** + * Get the collection of BLIP Store Entries + * + * @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE[] + */ + public function getBSECollection() + { + return $this->_BSECollection; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php new file mode 100755 index 0000000..adff1b4 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE.php @@ -0,0 +1,120 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** + * PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE +{ + const BLIPTYPE_ERROR = 0x00; + const BLIPTYPE_UNKNOWN = 0x01; + const BLIPTYPE_EMF = 0x02; + const BLIPTYPE_WMF = 0x03; + const BLIPTYPE_PICT = 0x04; + const BLIPTYPE_JPEG = 0x05; + const BLIPTYPE_PNG = 0x06; + const BLIPTYPE_DIB = 0x07; + const BLIPTYPE_TIFF = 0x11; + const BLIPTYPE_CMYKJPEG = 0x12; + + /** + * The parent BLIP Store Entry Container + * + * @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer + */ + private $_parent; + + /** + * The BLIP (Big Large Image or Picture) + * + * @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip + */ + private $_blip; + + /** + * The BLIP type + * + * @var int + */ + private $_blipType; + + /** + * Set parent BLIP Store Entry Container + * + * @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer $parent + */ + public function setParent($parent) + { + $this->_parent = $parent; + } + + /** + * Get the BLIP + * + * @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip + */ + public function getBlip() + { + return $this->_blip; + } + + /** + * Set the BLIP + * + * @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip $blip + */ + public function setBlip($blip) + { + $this->_blip = $blip; + $blip->setParent($this); + } + + /** + * Get the BLIP type + * + * @return int + */ + public function getBlipType() + { + return $this->_blipType; + } + + /** + * Set the BLIP type + * + * @param int + */ + public function setBlipType($blipType) + { + $this->_blipType = $blipType; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php new file mode 100755 index 0000000..7ba4985 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Escher/DggContainer/BstoreContainer/BSE/Blip.php @@ -0,0 +1,91 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** + * PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip + * + * @category PHPExcel + * @package PHPExcel_Shared_Escher + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip +{ + /** + * The parent BSE + * + * @var PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE + */ + private $_parent; + + /** + * Raw image data + * + * @var string + */ + private $_data; + + /** + * Get the raw image data + * + * @return string + */ + public function getData() + { + return $this->_data; + } + + /** + * Set the raw image data + * + * @param string + */ + public function setData($data) + { + $this->_data = $data; + } + + /** + * Set parent BSE + * + * @param PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE $parent + */ + public function setParent($parent) + { + $this->_parent = $parent; + } + + /** + * Get parent BSE + * + * @return PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE $parent + */ + public function getParent() + { + return $this->_parent; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Excel5.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Excel5.php new file mode 100755 index 0000000..b96cb1c --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Excel5.php @@ -0,0 +1,317 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** + * PHPExcel_Shared_Excel5 + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Excel5 +{ + /** + * Get the width of a column in pixels. We use the relationship y = ceil(7x) where + * x is the width in intrinsic Excel units (measuring width in number of normal characters) + * This holds for Arial 10 + * + * @param PHPExcel_Worksheet $sheet The sheet + * @param string $col The column + * @return integer The width in pixels + */ + public static function sizeCol($sheet, $col = 'A') + { + // default font of the workbook + $font = $sheet->getParent()->getDefaultStyle()->getFont(); + + $columnDimensions = $sheet->getColumnDimensions(); + + // first find the true column width in pixels (uncollapsed and unhidden) + if ( isset($columnDimensions[$col]) and $columnDimensions[$col]->getWidth() != -1 ) { + + // then we have column dimension with explicit width + $columnDimension = $columnDimensions[$col]; + $width = $columnDimension->getWidth(); + $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $font); + + } else if ($sheet->getDefaultColumnDimension()->getWidth() != -1) { + + // then we have default column dimension with explicit width + $defaultColumnDimension = $sheet->getDefaultColumnDimension(); + $width = $defaultColumnDimension->getWidth(); + $pixelWidth = PHPExcel_Shared_Drawing::cellDimensionToPixels($width, $font); + + } else { + + // we don't even have any default column dimension. Width depends on default font + $pixelWidth = PHPExcel_Shared_Font::getDefaultColumnWidthByFont($font, true); + } + + // now find the effective column width in pixels + if (isset($columnDimensions[$col]) and !$columnDimensions[$col]->getVisible()) { + $effectivePixelWidth = 0; + } else { + $effectivePixelWidth = $pixelWidth; + } + + return $effectivePixelWidth; + } + + /** + * Convert the height of a cell from user's units to pixels. By interpolation + * the relationship is: y = 4/3x. If the height hasn't been set by the user we + * use the default value. If the row is hidden we use a value of zero. + * + * @param PHPExcel_Worksheet $sheet The sheet + * @param integer $row The row index (1-based) + * @return integer The width in pixels + */ + public static function sizeRow($sheet, $row = 1) + { + // default font of the workbook + $font = $sheet->getParent()->getDefaultStyle()->getFont(); + + $rowDimensions = $sheet->getRowDimensions(); + + // first find the true row height in pixels (uncollapsed and unhidden) + if ( isset($rowDimensions[$row]) and $rowDimensions[$row]->getRowHeight() != -1) { + + // then we have a row dimension + $rowDimension = $rowDimensions[$row]; + $rowHeight = $rowDimension->getRowHeight(); + $pixelRowHeight = (int) ceil(4 * $rowHeight / 3); // here we assume Arial 10 + + } else if ($sheet->getDefaultRowDimension()->getRowHeight() != -1) { + + // then we have a default row dimension with explicit height + $defaultRowDimension = $sheet->getDefaultRowDimension(); + $rowHeight = $defaultRowDimension->getRowHeight(); + $pixelRowHeight = PHPExcel_Shared_Drawing::pointsToPixels($rowHeight); + + } else { + + // we don't even have any default row dimension. Height depends on default font + $pointRowHeight = PHPExcel_Shared_Font::getDefaultRowHeightByFont($font); + $pixelRowHeight = PHPExcel_Shared_Font::fontSizeToPixels($pointRowHeight); + + } + + // now find the effective row height in pixels + if ( isset($rowDimensions[$row]) and !$rowDimensions[$row]->getVisible() ) { + $effectivePixelRowHeight = 0; + } else { + $effectivePixelRowHeight = $pixelRowHeight; + } + + return $effectivePixelRowHeight; + } + + /** + * Get the horizontal distance in pixels between two anchors + * The distanceX is found as sum of all the spanning columns widths minus correction for the two offsets + * + * @param PHPExcel_Worksheet $sheet + * @param string $startColumn + * @param integer $startOffsetX Offset within start cell measured in 1/1024 of the cell width + * @param string $endColumn + * @param integer $endOffsetX Offset within end cell measured in 1/1024 of the cell width + * @return integer Horizontal measured in pixels + */ + public static function getDistanceX(PHPExcel_Worksheet $sheet, $startColumn = 'A', $startOffsetX = 0, $endColumn = 'A', $endOffsetX = 0) + { + $distanceX = 0; + + // add the widths of the spanning columns + $startColumnIndex = PHPExcel_Cell::columnIndexFromString($startColumn) - 1; // 1-based + $endColumnIndex = PHPExcel_Cell::columnIndexFromString($endColumn) - 1; // 1-based + for ($i = $startColumnIndex; $i <= $endColumnIndex; ++$i) { + $distanceX += self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($i)); + } + + // correct for offsetX in startcell + $distanceX -= (int) floor(self::sizeCol($sheet, $startColumn) * $startOffsetX / 1024); + + // correct for offsetX in endcell + $distanceX -= (int) floor(self::sizeCol($sheet, $endColumn) * (1 - $endOffsetX / 1024)); + + return $distanceX; + } + + /** + * Get the vertical distance in pixels between two anchors + * The distanceY is found as sum of all the spanning rows minus two offsets + * + * @param PHPExcel_Worksheet $sheet + * @param integer $startRow (1-based) + * @param integer $startOffsetY Offset within start cell measured in 1/256 of the cell height + * @param integer $endRow (1-based) + * @param integer $endOffsetY Offset within end cell measured in 1/256 of the cell height + * @return integer Vertical distance measured in pixels + */ + public static function getDistanceY(PHPExcel_Worksheet $sheet, $startRow = 1, $startOffsetY = 0, $endRow = 1, $endOffsetY = 0) + { + $distanceY = 0; + + // add the widths of the spanning rows + for ($row = $startRow; $row <= $endRow; ++$row) { + $distanceY += self::sizeRow($sheet, $row); + } + + // correct for offsetX in startcell + $distanceY -= (int) floor(self::sizeRow($sheet, $startRow) * $startOffsetY / 256); + + // correct for offsetX in endcell + $distanceY -= (int) floor(self::sizeRow($sheet, $endRow) * (1 - $endOffsetY / 256)); + + return $distanceY; + } + + /** + * Convert 1-cell anchor coordinates to 2-cell anchor coordinates + * This function is ported from PEAR Spreadsheet_Writer_Excel with small modifications + * + * Calculate the vertices that define the position of the image as required by + * the OBJ record. + * + * +------------+------------+ + * | A | B | + * +-----+------------+------------+ + * | |(x1,y1) | | + * | 1 |(A1)._______|______ | + * | | | | | + * | | | | | + * +-----+----| BITMAP |-----+ + * | | | | | + * | 2 | |______________. | + * | | | (B2)| + * | | | (x2,y2)| + * +---- +------------+------------+ + * + * Example of a bitmap that covers some of the area from cell A1 to cell B2. + * + * Based on the width and height of the bitmap we need to calculate 8 vars: + * $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2. + * The width and height of the cells are also variable and have to be taken into + * account. + * The values of $col_start and $row_start are passed in from the calling + * function. The values of $col_end and $row_end are calculated by subtracting + * the width and height of the bitmap from the width and height of the + * underlying cells. + * The vertices are expressed as a percentage of the underlying cell width as + * follows (rhs values are in pixels): + * + * x1 = X / W *1024 + * y1 = Y / H *256 + * x2 = (X-1) / W *1024 + * y2 = (Y-1) / H *256 + * + * Where: X is distance from the left side of the underlying cell + * Y is distance from the top of the underlying cell + * W is the width of the cell + * H is the height of the cell + * + * @param PHPExcel_Worksheet $sheet + * @param string $coordinates E.g. 'A1' + * @param integer $offsetX Horizontal offset in pixels + * @param integer $offsetY Vertical offset in pixels + * @param integer $width Width in pixels + * @param integer $height Height in pixels + * @return array + */ + public static function oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height) + { + list($column, $row) = PHPExcel_Cell::coordinateFromString($coordinates); + $col_start = PHPExcel_Cell::columnIndexFromString($column) - 1; + $row_start = $row - 1; + + $x1 = $offsetX; + $y1 = $offsetY; + + // Initialise end cell to the same as the start cell + $col_end = $col_start; // Col containing lower right corner of object + $row_end = $row_start; // Row containing bottom right corner of object + + // Zero the specified offset if greater than the cell dimensions + if ($x1 >= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start))) { + $x1 = 0; + } + if ($y1 >= self::sizeRow($sheet, $row_start + 1)) { + $y1 = 0; + } + + $width = $width + $x1 -1; + $height = $height + $y1 -1; + + // Subtract the underlying cell widths to find the end cell of the image + while ($width >= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end))) { + $width -= self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)); + ++$col_end; + } + + // Subtract the underlying cell heights to find the end cell of the image + while ($height >= self::sizeRow($sheet, $row_end + 1)) { + $height -= self::sizeRow($sheet, $row_end + 1); + ++$row_end; + } + + // Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell + // with zero height or width. + if (self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) == 0) { + return; + } + if (self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) == 0) { + return; + } + if (self::sizeRow($sheet, $row_start + 1) == 0) { + return; + } + if (self::sizeRow($sheet, $row_end + 1) == 0) { + return; + } + + // Convert the pixel values to the percentage value expected by Excel + $x1 = $x1 / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) * 1024; + $y1 = $y1 / self::sizeRow($sheet, $row_start + 1) * 256; + $x2 = ($width + 1) / self::sizeCol($sheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object + $y2 = ($height + 1) / self::sizeRow($sheet, $row_end + 1) * 256; // Distance to bottom of object + + $startCoordinates = PHPExcel_Cell::stringFromColumnIndex($col_start) . ($row_start + 1); + $endCoordinates = PHPExcel_Cell::stringFromColumnIndex($col_end) . ($row_end + 1); + + $twoAnchor = array( + 'startCoordinates' => $startCoordinates, + 'startOffsetX' => $x1, + 'startOffsetY' => $y1, + 'endCoordinates' => $endCoordinates, + 'endOffsetX' => $x2, + 'endOffsetY' => $y2, + ); + + return $twoAnchor; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/File.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/File.php new file mode 100755 index 0000000..2b55dd8 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/File.php @@ -0,0 +1,178 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Shared_File + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_File +{ + /* + * Use Temp or File Upload Temp for temporary files + * + * @protected + * @var boolean + */ + protected static $_useUploadTempDirectory = FALSE; + + + /** + * Set the flag indicating whether the File Upload Temp directory should be used for temporary files + * + * @param boolean $useUploadTempDir Use File Upload Temporary directory (true or false) + */ + public static function setUseUploadTempDirectory($useUploadTempDir = FALSE) { + self::$_useUploadTempDirectory = (boolean) $useUploadTempDir; + } // function setUseUploadTempDirectory() + + + /** + * Get the flag indicating whether the File Upload Temp directory should be used for temporary files + * + * @return boolean Use File Upload Temporary directory (true or false) + */ + public static function getUseUploadTempDirectory() { + return self::$_useUploadTempDirectory; + } // function getUseUploadTempDirectory() + + + /** + * Verify if a file exists + * + * @param string $pFilename Filename + * @return bool + */ + public static function file_exists($pFilename) { + // Sick construction, but it seems that + // file_exists returns strange values when + // doing the original file_exists on ZIP archives... + if ( strtolower(substr($pFilename, 0, 3)) == 'zip' ) { + // Open ZIP file and verify if the file exists + $zipFile = substr($pFilename, 6, strpos($pFilename, '#') - 6); + $archiveFile = substr($pFilename, strpos($pFilename, '#') + 1); + + $zip = new ZipArchive(); + if ($zip->open($zipFile) === true) { + $returnValue = ($zip->getFromName($archiveFile) !== false); + $zip->close(); + return $returnValue; + } else { + return false; + } + } else { + // Regular file_exists + return file_exists($pFilename); + } + } + + /** + * Returns canonicalized absolute pathname, also for ZIP archives + * + * @param string $pFilename + * @return string + */ + public static function realpath($pFilename) { + // Returnvalue + $returnValue = ''; + + // Try using realpath() + if (file_exists($pFilename)) { + $returnValue = realpath($pFilename); + } + + // Found something? + if ($returnValue == '' || ($returnValue === NULL)) { + $pathArray = explode('/' , $pFilename); + while(in_array('..', $pathArray) && $pathArray[0] != '..') { + for ($i = 0; $i < count($pathArray); ++$i) { + if ($pathArray[$i] == '..' && $i > 0) { + unset($pathArray[$i]); + unset($pathArray[$i - 1]); + break; + } + } + } + $returnValue = implode('/', $pathArray); + } + + // Return + return $returnValue; + } + + /** + * Get the systems temporary directory. + * + * @return string + */ + public static function sys_get_temp_dir() + { + if (self::$_useUploadTempDirectory) { + // use upload-directory when defined to allow running on environments having very restricted + // open_basedir configs + if (ini_get('upload_tmp_dir') !== FALSE) { + if ($temp = ini_get('upload_tmp_dir')) { + if (file_exists($temp)) + return realpath($temp); + } + } + } + + // sys_get_temp_dir is only available since PHP 5.2.1 + // http://php.net/manual/en/function.sys-get-temp-dir.php#94119 + if ( !function_exists('sys_get_temp_dir')) { + if ($temp = getenv('TMP') ) { + if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); } + } + if ($temp = getenv('TEMP') ) { + if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); } + } + if ($temp = getenv('TMPDIR') ) { + if ((!empty($temp)) && (file_exists($temp))) { return realpath($temp); } + } + + // trick for creating a file in system's temporary dir + // without knowing the path of the system's temporary dir + $temp = tempnam(__FILE__, ''); + if (file_exists($temp)) { + unlink($temp); + return realpath(dirname($temp)); + } + + return null; + } + + // use ordinary built-in PHP function + // There should be no problem with the 5.2.4 Suhosin realpath() bug, because this line should only + // be called if we're running 5.2.1 or earlier + return realpath(sys_get_temp_dir()); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Font.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Font.php new file mode 100755 index 0000000..dcdafdd --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/Font.php @@ -0,0 +1,775 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Shared_Font + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_Font +{ + /* Methods for resolving autosize value */ + const AUTOSIZE_METHOD_APPROX = 'approx'; + const AUTOSIZE_METHOD_EXACT = 'exact'; + + private static $_autoSizeMethods = array( + self::AUTOSIZE_METHOD_APPROX, + self::AUTOSIZE_METHOD_EXACT, + ); + + /** Character set codes used by BIFF5-8 in Font records */ + const CHARSET_ANSI_LATIN = 0x00; + const CHARSET_SYSTEM_DEFAULT = 0x01; + const CHARSET_SYMBOL = 0x02; + const CHARSET_APPLE_ROMAN = 0x4D; + const CHARSET_ANSI_JAPANESE_SHIFTJIS = 0x80; + const CHARSET_ANSI_KOREAN_HANGUL = 0x81; + const CHARSET_ANSI_KOREAN_JOHAB = 0x82; + const CHARSET_ANSI_CHINESE_SIMIPLIFIED = 0x86; // gb2312 + const CHARSET_ANSI_CHINESE_TRADITIONAL = 0x88; // big5 + const CHARSET_ANSI_GREEK = 0xA1; + const CHARSET_ANSI_TURKISH = 0xA2; + const CHARSET_ANSI_VIETNAMESE = 0xA3; + const CHARSET_ANSI_HEBREW = 0xB1; + const CHARSET_ANSI_ARABIC = 0xB2; + const CHARSET_ANSI_BALTIC = 0xBA; + const CHARSET_ANSI_CYRILLIC = 0xCC; + const CHARSET_ANSI_THAI = 0xDD; + const CHARSET_ANSI_LATIN_II = 0xEE; + const CHARSET_OEM_LATIN_I = 0xFF; + + // XXX: Constants created! + /** Font filenames */ + const ARIAL = 'arial.ttf'; + const ARIAL_BOLD = 'arialbd.ttf'; + const ARIAL_ITALIC = 'ariali.ttf'; + const ARIAL_BOLD_ITALIC = 'arialbi.ttf'; + + const CALIBRI = 'CALIBRI.TTF'; + const CALIBRI_BOLD = 'CALIBRIB.TTF'; + const CALIBRI_ITALIC = 'CALIBRII.TTF'; + const CALIBRI_BOLD_ITALIC = 'CALIBRIZ.TTF'; + + const COMIC_SANS_MS = 'comic.ttf'; + const COMIC_SANS_MS_BOLD = 'comicbd.ttf'; + + const COURIER_NEW = 'cour.ttf'; + const COURIER_NEW_BOLD = 'courbd.ttf'; + const COURIER_NEW_ITALIC = 'couri.ttf'; + const COURIER_NEW_BOLD_ITALIC = 'courbi.ttf'; + + const GEORGIA = 'georgia.ttf'; + const GEORGIA_BOLD = 'georgiab.ttf'; + const GEORGIA_ITALIC = 'georgiai.ttf'; + const GEORGIA_BOLD_ITALIC = 'georgiaz.ttf'; + + const IMPACT = 'impact.ttf'; + + const LIBERATION_SANS = 'LiberationSans-Regular.ttf'; + const LIBERATION_SANS_BOLD = 'LiberationSans-Bold.ttf'; + const LIBERATION_SANS_ITALIC = 'LiberationSans-Italic.ttf'; + const LIBERATION_SANS_BOLD_ITALIC = 'LiberationSans-BoldItalic.ttf'; + + const LUCIDA_CONSOLE = 'lucon.ttf'; + const LUCIDA_SANS_UNICODE = 'l_10646.ttf'; + + const MICROSOFT_SANS_SERIF = 'micross.ttf'; + + const PALATINO_LINOTYPE = 'pala.ttf'; + const PALATINO_LINOTYPE_BOLD = 'palab.ttf'; + const PALATINO_LINOTYPE_ITALIC = 'palai.ttf'; + const PALATINO_LINOTYPE_BOLD_ITALIC = 'palabi.ttf'; + + const SYMBOL = 'symbol.ttf'; + + const TAHOMA = 'tahoma.ttf'; + const TAHOMA_BOLD = 'tahomabd.ttf'; + + const TIMES_NEW_ROMAN = 'times.ttf'; + const TIMES_NEW_ROMAN_BOLD = 'timesbd.ttf'; + const TIMES_NEW_ROMAN_ITALIC = 'timesi.ttf'; + const TIMES_NEW_ROMAN_BOLD_ITALIC = 'timesbi.ttf'; + + const TREBUCHET_MS = 'trebuc.ttf'; + const TREBUCHET_MS_BOLD = 'trebucbd.ttf'; + const TREBUCHET_MS_ITALIC = 'trebucit.ttf'; + const TREBUCHET_MS_BOLD_ITALIC = 'trebucbi.ttf'; + + const VERDANA = 'verdana.ttf'; + const VERDANA_BOLD = 'verdanab.ttf'; + const VERDANA_ITALIC = 'verdanai.ttf'; + const VERDANA_BOLD_ITALIC = 'verdanaz.ttf'; + + /** + * AutoSize method + * + * @var string + */ + private static $autoSizeMethod = self::AUTOSIZE_METHOD_APPROX; + + /** + * Path to folder containing TrueType font .ttf files + * + * @var string + */ + private static $trueTypeFontPath = null; + + /** + * How wide is a default column for a given default font and size? + * Empirical data found by inspecting real Excel files and reading off the pixel width + * in Microsoft Office Excel 2007. + * + * @var array + */ + public static $defaultColumnWidths = array( + 'Arial' => array( + 1 => array('px' => 24, 'width' => 12.00000000), + 2 => array('px' => 24, 'width' => 12.00000000), + 3 => array('px' => 32, 'width' => 10.66406250), + 4 => array('px' => 32, 'width' => 10.66406250), + 5 => array('px' => 40, 'width' => 10.00000000), + 6 => array('px' => 48, 'width' => 9.59765625), + 7 => array('px' => 48, 'width' => 9.59765625), + 8 => array('px' => 56, 'width' => 9.33203125), + 9 => array('px' => 64, 'width' => 9.14062500), + 10 => array('px' => 64, 'width' => 9.14062500), + ), + 'Calibri' => array( + 1 => array('px' => 24, 'width' => 12.00000000), + 2 => array('px' => 24, 'width' => 12.00000000), + 3 => array('px' => 32, 'width' => 10.66406250), + 4 => array('px' => 32, 'width' => 10.66406250), + 5 => array('px' => 40, 'width' => 10.00000000), + 6 => array('px' => 48, 'width' => 9.59765625), + 7 => array('px' => 48, 'width' => 9.59765625), + 8 => array('px' => 56, 'width' => 9.33203125), + 9 => array('px' => 56, 'width' => 9.33203125), + 10 => array('px' => 64, 'width' => 9.14062500), + 11 => array('px' => 64, 'width' => 9.14062500), + ), + 'Verdana' => array( + 1 => array('px' => 24, 'width' => 12.00000000), + 2 => array('px' => 24, 'width' => 12.00000000), + 3 => array('px' => 32, 'width' => 10.66406250), + 4 => array('px' => 32, 'width' => 10.66406250), + 5 => array('px' => 40, 'width' => 10.00000000), + 6 => array('px' => 48, 'width' => 9.59765625), + 7 => array('px' => 48, 'width' => 9.59765625), + 8 => array('px' => 64, 'width' => 9.14062500), + 9 => array('px' => 72, 'width' => 9.00000000), + 10 => array('px' => 72, 'width' => 9.00000000), + ), + ); + + /** + * Set autoSize method + * + * @param string $pValue + * @return boolean Success or failure + */ + public static function setAutoSizeMethod($pValue = self::AUTOSIZE_METHOD_APPROX) + { + if (!in_array($pValue,self::$_autoSizeMethods)) { + return FALSE; + } + + self::$autoSizeMethod = $pValue; + + return TRUE; + } + + /** + * Get autoSize method + * + * @return string + */ + public static function getAutoSizeMethod() + { + return self::$autoSizeMethod; + } + + /** + * Set the path to the folder containing .ttf files. There should be a trailing slash. + * Typical locations on variout some platforms: + * <ul> + * <li>C:/Windows/Fonts/</li> + * <li>/usr/share/fonts/truetype/</li> + * <li>~/.fonts/</li> + * </ul> + * + * @param string $pValue + */ + public static function setTrueTypeFontPath($pValue = '') + { + self::$trueTypeFontPath = $pValue; + } + + /** + * Get the path to the folder containing .ttf files. + * + * @return string + */ + public static function getTrueTypeFontPath() + { + return self::$trueTypeFontPath; + } + + /** + * Calculate an (approximate) OpenXML column width, based on font size and text contained + * + * @param PHPExcel_Style_Font $font Font object + * @param PHPExcel_RichText|string $cellText Text to calculate width + * @param integer $rotation Rotation angle + * @param PHPExcel_Style_Font|NULL $defaultFont Font object + * @return integer Column width + */ + public static function calculateColumnWidth(PHPExcel_Style_Font $font, $cellText = '', $rotation = 0, PHPExcel_Style_Font $defaultFont = null) { + + // If it is rich text, use plain text + if ($cellText instanceof PHPExcel_RichText) { + $cellText = $cellText->getPlainText(); + } + + // Special case if there are one or more newline characters ("\n") + if (strpos($cellText, "\n") !== false) { + $lineTexts = explode("\n", $cellText); + $lineWitdhs = array(); + foreach ($lineTexts as $lineText) { + $lineWidths[] = self::calculateColumnWidth($font, $lineText, $rotation = 0, $defaultFont); + } + return max($lineWidths); // width of longest line in cell + } + + // Try to get the exact text width in pixels + try { + // If autosize method is set to 'approx', use approximation + if (self::$autoSizeMethod == self::AUTOSIZE_METHOD_APPROX) { + throw new PHPExcel_Exception('AutoSize method is set to approx'); + } + + // Width of text in pixels excl. padding + $columnWidth = self::getTextWidthPixelsExact($cellText, $font, $rotation); + + // Excel adds some padding, use 1.07 of the width of an 'n' glyph + $columnWidth += ceil(self::getTextWidthPixelsExact('0', $font, 0) * 1.07); // pixels incl. padding + + } catch (PHPExcel_Exception $e) { + // Width of text in pixels excl. padding, approximation + $columnWidth = self::getTextWidthPixelsApprox($cellText, $font, $rotation); + + // Excel adds some padding, just use approx width of 'n' glyph + $columnWidth += self::getTextWidthPixelsApprox('n', $font, 0); + } + + // Convert from pixel width to column width + $columnWidth = PHPExcel_Shared_Drawing::pixelsToCellDimension($columnWidth, $defaultFont); + + // Return + return round($columnWidth, 6); + } + + /** + * Get GD text width in pixels for a string of text in a certain font at a certain rotation angle + * + * @param string $text + * @param PHPExcel_Style_Font + * @param int $rotation + * @return int + * @throws PHPExcel_Exception + */ + public static function getTextWidthPixelsExact($text, PHPExcel_Style_Font $font, $rotation = 0) { + if (!function_exists('imagettfbbox')) { + throw new PHPExcel_Exception('GD library needs to be enabled'); + } + + // font size should really be supplied in pixels in GD2, + // but since GD2 seems to assume 72dpi, pixels and points are the same + $fontFile = self::getTrueTypeFontFileFromFont($font); + $textBox = imagettfbbox($font->getSize(), $rotation, $fontFile, $text); + + // Get corners positions + $lowerLeftCornerX = $textBox[0]; + $lowerLeftCornerY = $textBox[1]; + $lowerRightCornerX = $textBox[2]; + $lowerRightCornerY = $textBox[3]; + $upperRightCornerX = $textBox[4]; + $upperRightCornerY = $textBox[5]; + $upperLeftCornerX = $textBox[6]; + $upperLeftCornerY = $textBox[7]; + + // Consider the rotation when calculating the width + $textWidth = max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX); + + return $textWidth; + } + + /** + * Get approximate width in pixels for a string of text in a certain font at a certain rotation angle + * + * @param string $columnText + * @param PHPExcel_Style_Font $font + * @param int $rotation + * @return int Text width in pixels (no padding added) + */ + public static function getTextWidthPixelsApprox($columnText, PHPExcel_Style_Font $font = null, $rotation = 0) + { + $fontName = $font->getName(); + $fontSize = $font->getSize(); + + // Calculate column width in pixels. We assume fixed glyph width. Result varies with font name and size. + switch ($fontName) { + case 'Calibri': + // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font. + $columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size + break; + + case 'Arial': + // value 7 was found via interpolation by inspecting real Excel files with Arial 10 font. + $columnWidth = (int) (7 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size + break; + + case 'Verdana': + // value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font. + $columnWidth = (int) (8 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size + break; + + default: + // just assume Calibri + $columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText)); + $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size + break; + } + + // Calculate approximate rotated column width + if ($rotation !== 0) { + if ($rotation == -165) { + // stacked text + $columnWidth = 4; // approximation + } else { + // rotated text + $columnWidth = $columnWidth * cos(deg2rad($rotation)) + + $fontSize * abs(sin(deg2rad($rotation))) / 5; // approximation + } + } + + // pixel width is an integer + $columnWidth = (int) $columnWidth; + return $columnWidth; + } + + /** + * Calculate an (approximate) pixel size, based on a font points size + * + * @param int $fontSizeInPoints Font size (in points) + * @return int Font size (in pixels) + */ + public static function fontSizeToPixels($fontSizeInPoints = 11) { + return (int) ((4 / 3) * $fontSizeInPoints); + } + + /** + * Calculate an (approximate) pixel size, based on inch size + * + * @param int $sizeInInch Font size (in inch) + * @return int Size (in pixels) + */ + public static function inchSizeToPixels($sizeInInch = 1) { + return ($sizeInInch * 96); + } + + /** + * Calculate an (approximate) pixel size, based on centimeter size + * + * @param int $sizeInCm Font size (in centimeters) + * @return int Size (in pixels) + */ + public static function centimeterSizeToPixels($sizeInCm = 1) { + return ($sizeInCm * 37.795275591); + } + + /** + * Returns the font path given the font + * + * @param PHPExcel_Style_Font + * @return string Path to TrueType font file + */ + public static function getTrueTypeFontFileFromFont($font) { + if (!file_exists(self::$trueTypeFontPath) || !is_dir(self::$trueTypeFontPath)) { + throw new PHPExcel_Exception('Valid directory to TrueType Font files not specified'); + } + + $name = $font->getName(); + $bold = $font->getBold(); + $italic = $font->getItalic(); + + // Check if we can map font to true type font file + switch ($name) { + case 'Arial': + $fontFile = ( + $bold ? ($italic ? self::ARIAL_BOLD_ITALIC : self::ARIAL_BOLD) + : ($italic ? self::ARIAL_ITALIC : self::ARIAL) + ); + break; + + case 'Calibri': + $fontFile = ( + $bold ? ($italic ? self::CALIBRI_BOLD_ITALIC : self::CALIBRI_BOLD) + : ($italic ? self::CALIBRI_ITALIC : self::CALIBRI) + ); + break; + + case 'Courier New': + $fontFile = ( + $bold ? ($italic ? self::COURIER_NEW_BOLD_ITALIC : self::COURIER_NEW_BOLD) + : ($italic ? self::COURIER_NEW_ITALIC : self::COURIER_NEW) + ); + break; + + case 'Comic Sans MS': + $fontFile = ( + $bold ? self::COMIC_SANS_MS_BOLD : self::COMIC_SANS_MS + ); + break; + + case 'Georgia': + $fontFile = ( + $bold ? ($italic ? self::GEORGIA_BOLD_ITALIC : self::GEORGIA_BOLD) + : ($italic ? self::GEORGIA_ITALIC : self::GEORGIA) + ); + break; + + case 'Impact': + $fontFile = self::IMPACT; + break; + + case 'Liberation Sans': + $fontFile = ( + $bold ? ($italic ? self::LIBERATION_SANS_BOLD_ITALIC : self::LIBERATION_SANS_BOLD) + : ($italic ? self::LIBERATION_SANS_ITALIC : self::LIBERATION_SANS) + ); + break; + + case 'Lucida Console': + $fontFile = self::LUCIDA_CONSOLE; + break; + + case 'Lucida Sans Unicode': + $fontFile = self::LUCIDA_SANS_UNICODE; + break; + + case 'Microsoft Sans Serif': + $fontFile = self::MICROSOFT_SANS_SERIF; + break; + + case 'Palatino Linotype': + $fontFile = ( + $bold ? ($italic ? self::PALATINO_LINOTYPE_BOLD_ITALIC : self::PALATINO_LINOTYPE_BOLD) + : ($italic ? self::PALATINO_LINOTYPE_ITALIC : self::PALATINO_LINOTYPE) + ); + break; + + case 'Symbol': + $fontFile = self::SYMBOL; + break; + + case 'Tahoma': + $fontFile = ( + $bold ? self::TAHOMA_BOLD : self::TAHOMA + ); + break; + + case 'Times New Roman': + $fontFile = ( + $bold ? ($italic ? self::TIMES_NEW_ROMAN_BOLD_ITALIC : self::TIMES_NEW_ROMAN_BOLD) + : ($italic ? self::TIMES_NEW_ROMAN_ITALIC : self::TIMES_NEW_ROMAN) + ); + break; + + case 'Trebuchet MS': + $fontFile = ( + $bold ? ($italic ? self::TREBUCHET_MS_BOLD_ITALIC : self::TREBUCHET_MS_BOLD) + : ($italic ? self::TREBUCHET_MS_ITALIC : self::TREBUCHET_MS) + ); + break; + + case 'Verdana': + $fontFile = ( + $bold ? ($italic ? self::VERDANA_BOLD_ITALIC : self::VERDANA_BOLD) + : ($italic ? self::VERDANA_ITALIC : self::VERDANA) + ); + break; + + default: + throw new PHPExcel_Exception('Unknown font name "'. $name .'". Cannot map to TrueType font file'); + break; + } + + $fontFile = self::$trueTypeFontPath . $fontFile; + + // Check if file actually exists + if (!file_exists($fontFile)) { + throw New PHPExcel_Exception('TrueType Font file not found'); + } + + return $fontFile; + } + + /** + * Returns the associated charset for the font name. + * + * @param string $name Font name + * @return int Character set code + */ + public static function getCharsetFromFontName($name) + { + switch ($name) { + // Add more cases. Check FONT records in real Excel files. + case 'EucrosiaUPC': return self::CHARSET_ANSI_THAI; + case 'Wingdings': return self::CHARSET_SYMBOL; + case 'Wingdings 2': return self::CHARSET_SYMBOL; + case 'Wingdings 3': return self::CHARSET_SYMBOL; + default: return self::CHARSET_ANSI_LATIN; + } + } + + /** + * Get the effective column width for columns without a column dimension or column with width -1 + * For example, for Calibri 11 this is 9.140625 (64 px) + * + * @param PHPExcel_Style_Font $font The workbooks default font + * @param boolean $pPixels true = return column width in pixels, false = return in OOXML units + * @return mixed Column width + */ + public static function getDefaultColumnWidthByFont(PHPExcel_Style_Font $font, $pPixels = false) + { + if (isset(self::$defaultColumnWidths[$font->getName()][$font->getSize()])) { + // Exact width can be determined + $columnWidth = $pPixels ? + self::$defaultColumnWidths[$font->getName()][$font->getSize()]['px'] + : self::$defaultColumnWidths[$font->getName()][$font->getSize()]['width']; + + } else { + // We don't have data for this particular font and size, use approximation by + // extrapolating from Calibri 11 + $columnWidth = $pPixels ? + self::$defaultColumnWidths['Calibri'][11]['px'] + : self::$defaultColumnWidths['Calibri'][11]['width']; + $columnWidth = $columnWidth * $font->getSize() / 11; + + // Round pixels to closest integer + if ($pPixels) { + $columnWidth = (int) round($columnWidth); + } + } + + return $columnWidth; + } + + /** + * Get the effective row height for rows without a row dimension or rows with height -1 + * For example, for Calibri 11 this is 15 points + * + * @param PHPExcel_Style_Font $font The workbooks default font + * @return float Row height in points + */ + public static function getDefaultRowHeightByFont(PHPExcel_Style_Font $font) + { + switch ($font->getName()) { + case 'Arial': + switch ($font->getSize()) { + case 10: + // inspection of Arial 10 workbook says 12.75pt ~17px + $rowHeight = 12.75; + break; + + case 9: + // inspection of Arial 9 workbook says 12.00pt ~16px + $rowHeight = 12; + break; + + case 8: + // inspection of Arial 8 workbook says 11.25pt ~15px + $rowHeight = 11.25; + break; + + case 7: + // inspection of Arial 7 workbook says 9.00pt ~12px + $rowHeight = 9; + break; + + case 6: + case 5: + // inspection of Arial 5,6 workbook says 8.25pt ~11px + $rowHeight = 8.25; + break; + + case 4: + // inspection of Arial 4 workbook says 6.75pt ~9px + $rowHeight = 6.75; + break; + + case 3: + // inspection of Arial 3 workbook says 6.00pt ~8px + $rowHeight = 6; + break; + + case 2: + case 1: + // inspection of Arial 1,2 workbook says 5.25pt ~7px + $rowHeight = 5.25; + break; + + default: + // use Arial 10 workbook as an approximation, extrapolation + $rowHeight = 12.75 * $font->getSize() / 10; + break; + } + break; + + case 'Calibri': + switch ($font->getSize()) { + case 11: + // inspection of Calibri 11 workbook says 15.00pt ~20px + $rowHeight = 15; + break; + + case 10: + // inspection of Calibri 10 workbook says 12.75pt ~17px + $rowHeight = 12.75; + break; + + case 9: + // inspection of Calibri 9 workbook says 12.00pt ~16px + $rowHeight = 12; + break; + + case 8: + // inspection of Calibri 8 workbook says 11.25pt ~15px + $rowHeight = 11.25; + break; + + case 7: + // inspection of Calibri 7 workbook says 9.00pt ~12px + $rowHeight = 9; + break; + + case 6: + case 5: + // inspection of Calibri 5,6 workbook says 8.25pt ~11px + $rowHeight = 8.25; + break; + + case 4: + // inspection of Calibri 4 workbook says 6.75pt ~9px + $rowHeight = 6.75; + break; + + case 3: + // inspection of Calibri 3 workbook says 6.00pt ~8px + $rowHeight = 6.00; + break; + + case 2: + case 1: + // inspection of Calibri 1,2 workbook says 5.25pt ~7px + $rowHeight = 5.25; + break; + + default: + // use Calibri 11 workbook as an approximation, extrapolation + $rowHeight = 15 * $font->getSize() / 11; + break; + } + break; + + case 'Verdana': + switch ($font->getSize()) { + case 10: + // inspection of Verdana 10 workbook says 12.75pt ~17px + $rowHeight = 12.75; + break; + + case 9: + // inspection of Verdana 9 workbook says 11.25pt ~15px + $rowHeight = 11.25; + break; + + case 8: + // inspection of Verdana 8 workbook says 10.50pt ~14px + $rowHeight = 10.50; + break; + + case 7: + // inspection of Verdana 7 workbook says 9.00pt ~12px + $rowHeight = 9.00; + break; + + case 6: + case 5: + // inspection of Verdana 5,6 workbook says 8.25pt ~11px + $rowHeight = 8.25; + break; + + case 4: + // inspection of Verdana 4 workbook says 6.75pt ~9px + $rowHeight = 6.75; + break; + + case 3: + // inspection of Verdana 3 workbook says 6.00pt ~8px + $rowHeight = 6; + break; + + case 2: + case 1: + // inspection of Verdana 1,2 workbook says 5.25pt ~7px + $rowHeight = 5.25; + break; + + default: + // use Verdana 10 workbook as an approximation, extrapolation + $rowHeight = 12.75 * $font->getSize() / 10; + break; + } + break; + + default: + // just use Calibri as an approximation + $rowHeight = 15 * $font->getSize() / 11; + break; + } + + return $rowHeight; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/CHANGELOG.TXT b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/CHANGELOG.TXT new file mode 100755 index 0000000..1c18a5d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/CHANGELOG.TXT @@ -0,0 +1,16 @@ +Mar 1, 2005 11:15 AST by PM + ++ For consistency, renamed Math.php to Maths.java, utils to util, + tests to test, docs to doc - + ++ Removed conditional logic from top of Matrix class. + ++ Switched to using hypo function in Maths.php for all php-hypot calls. + NOTE TO SELF: Need to make sure that all decompositions have been + switched over to using the bundled hypo. + +Feb 25, 2005 at 10:00 AST by PM + ++ Recommend using simpler Error.php instead of JAMA_Error.php but + can be persuaded otherwise. + diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/CholeskyDecomposition.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/CholeskyDecomposition.php new file mode 100755 index 0000000..cfbaa53 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/CholeskyDecomposition.php @@ -0,0 +1,149 @@ +<?php +/** + * @package JAMA + * + * Cholesky decomposition class + * + * For a symmetric, positive definite matrix A, the Cholesky decomposition + * is an lower triangular matrix L so that A = L*L'. + * + * If the matrix is not symmetric or positive definite, the constructor + * returns a partial decomposition and sets an internal flag that may + * be queried by the isSPD() method. + * + * @author Paul Meagher + * @author Michael Bommarito + * @version 1.2 + */ +class CholeskyDecomposition { + + /** + * Decomposition storage + * @var array + * @access private + */ + private $L = array(); + + /** + * Matrix row and column dimension + * @var int + * @access private + */ + private $m; + + /** + * Symmetric positive definite flag + * @var boolean + * @access private + */ + private $isspd = true; + + + /** + * CholeskyDecomposition + * + * Class constructor - decomposes symmetric positive definite matrix + * @param mixed Matrix square symmetric positive definite matrix + */ + public function __construct($A = null) { + if ($A instanceof Matrix) { + $this->L = $A->getArray(); + $this->m = $A->getRowDimension(); + + for($i = 0; $i < $this->m; ++$i) { + for($j = $i; $j < $this->m; ++$j) { + for($sum = $this->L[$i][$j], $k = $i - 1; $k >= 0; --$k) { + $sum -= $this->L[$i][$k] * $this->L[$j][$k]; + } + if ($i == $j) { + if ($sum >= 0) { + $this->L[$i][$i] = sqrt($sum); + } else { + $this->isspd = false; + } + } else { + if ($this->L[$i][$i] != 0) { + $this->L[$j][$i] = $sum / $this->L[$i][$i]; + } + } + } + + for ($k = $i+1; $k < $this->m; ++$k) { + $this->L[$i][$k] = 0.0; + } + } + } else { + throw new PHPExcel_Calculation_Exception(JAMAError(ArgumentTypeException)); + } + } // function __construct() + + + /** + * Is the matrix symmetric and positive definite? + * + * @return boolean + */ + public function isSPD() { + return $this->isspd; + } // function isSPD() + + + /** + * getL + * + * Return triangular factor. + * @return Matrix Lower triangular matrix + */ + public function getL() { + return new Matrix($this->L); + } // function getL() + + + /** + * Solve A*X = B + * + * @param $B Row-equal matrix + * @return Matrix L * L' * X = B + */ + public function solve($B = null) { + if ($B instanceof Matrix) { + if ($B->getRowDimension() == $this->m) { + if ($this->isspd) { + $X = $B->getArrayCopy(); + $nx = $B->getColumnDimension(); + + for ($k = 0; $k < $this->m; ++$k) { + for ($i = $k + 1; $i < $this->m; ++$i) { + for ($j = 0; $j < $nx; ++$j) { + $X[$i][$j] -= $X[$k][$j] * $this->L[$i][$k]; + } + } + for ($j = 0; $j < $nx; ++$j) { + $X[$k][$j] /= $this->L[$k][$k]; + } + } + + for ($k = $this->m - 1; $k >= 0; --$k) { + for ($j = 0; $j < $nx; ++$j) { + $X[$k][$j] /= $this->L[$k][$k]; + } + for ($i = 0; $i < $k; ++$i) { + for ($j = 0; $j < $nx; ++$j) { + $X[$i][$j] -= $X[$k][$j] * $this->L[$k][$i]; + } + } + } + + return new Matrix($X, $this->m, $nx); + } else { + throw new PHPExcel_Calculation_Exception(JAMAError(MatrixSPDException)); + } + } else { + throw new PHPExcel_Calculation_Exception(JAMAError(MatrixDimensionException)); + } + } else { + throw new PHPExcel_Calculation_Exception(JAMAError(ArgumentTypeException)); + } + } // function solve() + +} // class CholeskyDecomposition diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php new file mode 100755 index 0000000..2a696d0 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/EigenvalueDecomposition.php @@ -0,0 +1,862 @@ +<?php +/** + * @package JAMA + * + * Class to obtain eigenvalues and eigenvectors of a real matrix. + * + * If A is symmetric, then A = V*D*V' where the eigenvalue matrix D + * is diagonal and the eigenvector matrix V is orthogonal (i.e. + * A = V.times(D.times(V.transpose())) and V.times(V.transpose()) + * equals the identity matrix). + * + * If A is not symmetric, then the eigenvalue matrix D is block diagonal + * with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues, + * lambda + i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda]. The + * columns of V represent the eigenvectors in the sense that A*V = V*D, + * i.e. A.times(V) equals V.times(D). The matrix V may be badly + * conditioned, or even singular, so the validity of the equation + * A = V*D*inverse(V) depends upon V.cond(). + * + * @author Paul Meagher + * @license PHP v3.0 + * @version 1.1 + */ +class EigenvalueDecomposition { + + /** + * Row and column dimension (square matrix). + * @var int + */ + private $n; + + /** + * Internal symmetry flag. + * @var int + */ + private $issymmetric; + + /** + * Arrays for internal storage of eigenvalues. + * @var array + */ + private $d = array(); + private $e = array(); + + /** + * Array for internal storage of eigenvectors. + * @var array + */ + private $V = array(); + + /** + * Array for internal storage of nonsymmetric Hessenberg form. + * @var array + */ + private $H = array(); + + /** + * Working storage for nonsymmetric algorithm. + * @var array + */ + private $ort; + + /** + * Used for complex scalar division. + * @var float + */ + private $cdivr; + private $cdivi; + + + /** + * Symmetric Householder reduction to tridiagonal form. + * + * @access private + */ + private function tred2 () { + // This is derived from the Algol procedures tred2 by + // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for + // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding + // Fortran subroutine in EISPACK. + $this->d = $this->V[$this->n-1]; + // Householder reduction to tridiagonal form. + for ($i = $this->n-1; $i > 0; --$i) { + $i_ = $i -1; + // Scale to avoid under/overflow. + $h = $scale = 0.0; + $scale += array_sum(array_map(abs, $this->d)); + if ($scale == 0.0) { + $this->e[$i] = $this->d[$i_]; + $this->d = array_slice($this->V[$i_], 0, $i_); + for ($j = 0; $j < $i; ++$j) { + $this->V[$j][$i] = $this->V[$i][$j] = 0.0; + } + } else { + // Generate Householder vector. + for ($k = 0; $k < $i; ++$k) { + $this->d[$k] /= $scale; + $h += pow($this->d[$k], 2); + } + $f = $this->d[$i_]; + $g = sqrt($h); + if ($f > 0) { + $g = -$g; + } + $this->e[$i] = $scale * $g; + $h = $h - $f * $g; + $this->d[$i_] = $f - $g; + for ($j = 0; $j < $i; ++$j) { + $this->e[$j] = 0.0; + } + // Apply similarity transformation to remaining columns. + for ($j = 0; $j < $i; ++$j) { + $f = $this->d[$j]; + $this->V[$j][$i] = $f; + $g = $this->e[$j] + $this->V[$j][$j] * $f; + for ($k = $j+1; $k <= $i_; ++$k) { + $g += $this->V[$k][$j] * $this->d[$k]; + $this->e[$k] += $this->V[$k][$j] * $f; + } + $this->e[$j] = $g; + } + $f = 0.0; + for ($j = 0; $j < $i; ++$j) { + $this->e[$j] /= $h; + $f += $this->e[$j] * $this->d[$j]; + } + $hh = $f / (2 * $h); + for ($j=0; $j < $i; ++$j) { + $this->e[$j] -= $hh * $this->d[$j]; + } + for ($j = 0; $j < $i; ++$j) { + $f = $this->d[$j]; + $g = $this->e[$j]; + for ($k = $j; $k <= $i_; ++$k) { + $this->V[$k][$j] -= ($f * $this->e[$k] + $g * $this->d[$k]); + } + $this->d[$j] = $this->V[$i-1][$j]; + $this->V[$i][$j] = 0.0; + } + } + $this->d[$i] = $h; + } + + // Accumulate transformations. + for ($i = 0; $i < $this->n-1; ++$i) { + $this->V[$this->n-1][$i] = $this->V[$i][$i]; + $this->V[$i][$i] = 1.0; + $h = $this->d[$i+1]; + if ($h != 0.0) { + for ($k = 0; $k <= $i; ++$k) { + $this->d[$k] = $this->V[$k][$i+1] / $h; + } + for ($j = 0; $j <= $i; ++$j) { + $g = 0.0; + for ($k = 0; $k <= $i; ++$k) { + $g += $this->V[$k][$i+1] * $this->V[$k][$j]; + } + for ($k = 0; $k <= $i; ++$k) { + $this->V[$k][$j] -= $g * $this->d[$k]; + } + } + } + for ($k = 0; $k <= $i; ++$k) { + $this->V[$k][$i+1] = 0.0; + } + } + + $this->d = $this->V[$this->n-1]; + $this->V[$this->n-1] = array_fill(0, $j, 0.0); + $this->V[$this->n-1][$this->n-1] = 1.0; + $this->e[0] = 0.0; + } + + + /** + * Symmetric tridiagonal QL algorithm. + * + * This is derived from the Algol procedures tql2, by + * Bowdler, Martin, Reinsch, and Wilkinson, Handbook for + * Auto. Comp., Vol.ii-Linear Algebra, and the corresponding + * Fortran subroutine in EISPACK. + * + * @access private + */ + private function tql2() { + for ($i = 1; $i < $this->n; ++$i) { + $this->e[$i-1] = $this->e[$i]; + } + $this->e[$this->n-1] = 0.0; + $f = 0.0; + $tst1 = 0.0; + $eps = pow(2.0,-52.0); + + for ($l = 0; $l < $this->n; ++$l) { + // Find small subdiagonal element + $tst1 = max($tst1, abs($this->d[$l]) + abs($this->e[$l])); + $m = $l; + while ($m < $this->n) { + if (abs($this->e[$m]) <= $eps * $tst1) + break; + ++$m; + } + // If m == l, $this->d[l] is an eigenvalue, + // otherwise, iterate. + if ($m > $l) { + $iter = 0; + do { + // Could check iteration count here. + $iter += 1; + // Compute implicit shift + $g = $this->d[$l]; + $p = ($this->d[$l+1] - $g) / (2.0 * $this->e[$l]); + $r = hypo($p, 1.0); + if ($p < 0) + $r *= -1; + $this->d[$l] = $this->e[$l] / ($p + $r); + $this->d[$l+1] = $this->e[$l] * ($p + $r); + $dl1 = $this->d[$l+1]; + $h = $g - $this->d[$l]; + for ($i = $l + 2; $i < $this->n; ++$i) + $this->d[$i] -= $h; + $f += $h; + // Implicit QL transformation. + $p = $this->d[$m]; + $c = 1.0; + $c2 = $c3 = $c; + $el1 = $this->e[$l + 1]; + $s = $s2 = 0.0; + for ($i = $m-1; $i >= $l; --$i) { + $c3 = $c2; + $c2 = $c; + $s2 = $s; + $g = $c * $this->e[$i]; + $h = $c * $p; + $r = hypo($p, $this->e[$i]); + $this->e[$i+1] = $s * $r; + $s = $this->e[$i] / $r; + $c = $p / $r; + $p = $c * $this->d[$i] - $s * $g; + $this->d[$i+1] = $h + $s * ($c * $g + $s * $this->d[$i]); + // Accumulate transformation. + for ($k = 0; $k < $this->n; ++$k) { + $h = $this->V[$k][$i+1]; + $this->V[$k][$i+1] = $s * $this->V[$k][$i] + $c * $h; + $this->V[$k][$i] = $c * $this->V[$k][$i] - $s * $h; + } + } + $p = -$s * $s2 * $c3 * $el1 * $this->e[$l] / $dl1; + $this->e[$l] = $s * $p; + $this->d[$l] = $c * $p; + // Check for convergence. + } while (abs($this->e[$l]) > $eps * $tst1); + } + $this->d[$l] = $this->d[$l] + $f; + $this->e[$l] = 0.0; + } + + // Sort eigenvalues and corresponding vectors. + for ($i = 0; $i < $this->n - 1; ++$i) { + $k = $i; + $p = $this->d[$i]; + for ($j = $i+1; $j < $this->n; ++$j) { + if ($this->d[$j] < $p) { + $k = $j; + $p = $this->d[$j]; + } + } + if ($k != $i) { + $this->d[$k] = $this->d[$i]; + $this->d[$i] = $p; + for ($j = 0; $j < $this->n; ++$j) { + $p = $this->V[$j][$i]; + $this->V[$j][$i] = $this->V[$j][$k]; + $this->V[$j][$k] = $p; + } + } + } + } + + + /** + * Nonsymmetric reduction to Hessenberg form. + * + * This is derived from the Algol procedures orthes and ortran, + * by Martin and Wilkinson, Handbook for Auto. Comp., + * Vol.ii-Linear Algebra, and the corresponding + * Fortran subroutines in EISPACK. + * + * @access private + */ + private function orthes () { + $low = 0; + $high = $this->n-1; + + for ($m = $low+1; $m <= $high-1; ++$m) { + // Scale column. + $scale = 0.0; + for ($i = $m; $i <= $high; ++$i) { + $scale = $scale + abs($this->H[$i][$m-1]); + } + if ($scale != 0.0) { + // Compute Householder transformation. + $h = 0.0; + for ($i = $high; $i >= $m; --$i) { + $this->ort[$i] = $this->H[$i][$m-1] / $scale; + $h += $this->ort[$i] * $this->ort[$i]; + } + $g = sqrt($h); + if ($this->ort[$m] > 0) { + $g *= -1; + } + $h -= $this->ort[$m] * $g; + $this->ort[$m] -= $g; + // Apply Householder similarity transformation + // H = (I -u * u' / h) * H * (I -u * u') / h) + for ($j = $m; $j < $this->n; ++$j) { + $f = 0.0; + for ($i = $high; $i >= $m; --$i) { + $f += $this->ort[$i] * $this->H[$i][$j]; + } + $f /= $h; + for ($i = $m; $i <= $high; ++$i) { + $this->H[$i][$j] -= $f * $this->ort[$i]; + } + } + for ($i = 0; $i <= $high; ++$i) { + $f = 0.0; + for ($j = $high; $j >= $m; --$j) { + $f += $this->ort[$j] * $this->H[$i][$j]; + } + $f = $f / $h; + for ($j = $m; $j <= $high; ++$j) { + $this->H[$i][$j] -= $f * $this->ort[$j]; + } + } + $this->ort[$m] = $scale * $this->ort[$m]; + $this->H[$m][$m-1] = $scale * $g; + } + } + + // Accumulate transformations (Algol's ortran). + for ($i = 0; $i < $this->n; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + $this->V[$i][$j] = ($i == $j ? 1.0 : 0.0); + } + } + for ($m = $high-1; $m >= $low+1; --$m) { + if ($this->H[$m][$m-1] != 0.0) { + for ($i = $m+1; $i <= $high; ++$i) { + $this->ort[$i] = $this->H[$i][$m-1]; + } + for ($j = $m; $j <= $high; ++$j) { + $g = 0.0; + for ($i = $m; $i <= $high; ++$i) { + $g += $this->ort[$i] * $this->V[$i][$j]; + } + // Double division avoids possible underflow + $g = ($g / $this->ort[$m]) / $this->H[$m][$m-1]; + for ($i = $m; $i <= $high; ++$i) { + $this->V[$i][$j] += $g * $this->ort[$i]; + } + } + } + } + } + + + /** + * Performs complex division. + * + * @access private + */ + private function cdiv($xr, $xi, $yr, $yi) { + if (abs($yr) > abs($yi)) { + $r = $yi / $yr; + $d = $yr + $r * $yi; + $this->cdivr = ($xr + $r * $xi) / $d; + $this->cdivi = ($xi - $r * $xr) / $d; + } else { + $r = $yr / $yi; + $d = $yi + $r * $yr; + $this->cdivr = ($r * $xr + $xi) / $d; + $this->cdivi = ($r * $xi - $xr) / $d; + } + } + + + /** + * Nonsymmetric reduction from Hessenberg to real Schur form. + * + * Code is derived from the Algol procedure hqr2, + * by Martin and Wilkinson, Handbook for Auto. Comp., + * Vol.ii-Linear Algebra, and the corresponding + * Fortran subroutine in EISPACK. + * + * @access private + */ + private function hqr2 () { + // Initialize + $nn = $this->n; + $n = $nn - 1; + $low = 0; + $high = $nn - 1; + $eps = pow(2.0, -52.0); + $exshift = 0.0; + $p = $q = $r = $s = $z = 0; + // Store roots isolated by balanc and compute matrix norm + $norm = 0.0; + + for ($i = 0; $i < $nn; ++$i) { + if (($i < $low) OR ($i > $high)) { + $this->d[$i] = $this->H[$i][$i]; + $this->e[$i] = 0.0; + } + for ($j = max($i-1, 0); $j < $nn; ++$j) { + $norm = $norm + abs($this->H[$i][$j]); + } + } + + // Outer loop over eigenvalue index + $iter = 0; + while ($n >= $low) { + // Look for single small sub-diagonal element + $l = $n; + while ($l > $low) { + $s = abs($this->H[$l-1][$l-1]) + abs($this->H[$l][$l]); + if ($s == 0.0) { + $s = $norm; + } + if (abs($this->H[$l][$l-1]) < $eps * $s) { + break; + } + --$l; + } + // Check for convergence + // One root found + if ($l == $n) { + $this->H[$n][$n] = $this->H[$n][$n] + $exshift; + $this->d[$n] = $this->H[$n][$n]; + $this->e[$n] = 0.0; + --$n; + $iter = 0; + // Two roots found + } else if ($l == $n-1) { + $w = $this->H[$n][$n-1] * $this->H[$n-1][$n]; + $p = ($this->H[$n-1][$n-1] - $this->H[$n][$n]) / 2.0; + $q = $p * $p + $w; + $z = sqrt(abs($q)); + $this->H[$n][$n] = $this->H[$n][$n] + $exshift; + $this->H[$n-1][$n-1] = $this->H[$n-1][$n-1] + $exshift; + $x = $this->H[$n][$n]; + // Real pair + if ($q >= 0) { + if ($p >= 0) { + $z = $p + $z; + } else { + $z = $p - $z; + } + $this->d[$n-1] = $x + $z; + $this->d[$n] = $this->d[$n-1]; + if ($z != 0.0) { + $this->d[$n] = $x - $w / $z; + } + $this->e[$n-1] = 0.0; + $this->e[$n] = 0.0; + $x = $this->H[$n][$n-1]; + $s = abs($x) + abs($z); + $p = $x / $s; + $q = $z / $s; + $r = sqrt($p * $p + $q * $q); + $p = $p / $r; + $q = $q / $r; + // Row modification + for ($j = $n-1; $j < $nn; ++$j) { + $z = $this->H[$n-1][$j]; + $this->H[$n-1][$j] = $q * $z + $p * $this->H[$n][$j]; + $this->H[$n][$j] = $q * $this->H[$n][$j] - $p * $z; + } + // Column modification + for ($i = 0; $i <= n; ++$i) { + $z = $this->H[$i][$n-1]; + $this->H[$i][$n-1] = $q * $z + $p * $this->H[$i][$n]; + $this->H[$i][$n] = $q * $this->H[$i][$n] - $p * $z; + } + // Accumulate transformations + for ($i = $low; $i <= $high; ++$i) { + $z = $this->V[$i][$n-1]; + $this->V[$i][$n-1] = $q * $z + $p * $this->V[$i][$n]; + $this->V[$i][$n] = $q * $this->V[$i][$n] - $p * $z; + } + // Complex pair + } else { + $this->d[$n-1] = $x + $p; + $this->d[$n] = $x + $p; + $this->e[$n-1] = $z; + $this->e[$n] = -$z; + } + $n = $n - 2; + $iter = 0; + // No convergence yet + } else { + // Form shift + $x = $this->H[$n][$n]; + $y = 0.0; + $w = 0.0; + if ($l < $n) { + $y = $this->H[$n-1][$n-1]; + $w = $this->H[$n][$n-1] * $this->H[$n-1][$n]; + } + // Wilkinson's original ad hoc shift + if ($iter == 10) { + $exshift += $x; + for ($i = $low; $i <= $n; ++$i) { + $this->H[$i][$i] -= $x; + } + $s = abs($this->H[$n][$n-1]) + abs($this->H[$n-1][$n-2]); + $x = $y = 0.75 * $s; + $w = -0.4375 * $s * $s; + } + // MATLAB's new ad hoc shift + if ($iter == 30) { + $s = ($y - $x) / 2.0; + $s = $s * $s + $w; + if ($s > 0) { + $s = sqrt($s); + if ($y < $x) { + $s = -$s; + } + $s = $x - $w / (($y - $x) / 2.0 + $s); + for ($i = $low; $i <= $n; ++$i) { + $this->H[$i][$i] -= $s; + } + $exshift += $s; + $x = $y = $w = 0.964; + } + } + // Could check iteration count here. + $iter = $iter + 1; + // Look for two consecutive small sub-diagonal elements + $m = $n - 2; + while ($m >= $l) { + $z = $this->H[$m][$m]; + $r = $x - $z; + $s = $y - $z; + $p = ($r * $s - $w) / $this->H[$m+1][$m] + $this->H[$m][$m+1]; + $q = $this->H[$m+1][$m+1] - $z - $r - $s; + $r = $this->H[$m+2][$m+1]; + $s = abs($p) + abs($q) + abs($r); + $p = $p / $s; + $q = $q / $s; + $r = $r / $s; + if ($m == $l) { + break; + } + if (abs($this->H[$m][$m-1]) * (abs($q) + abs($r)) < + $eps * (abs($p) * (abs($this->H[$m-1][$m-1]) + abs($z) + abs($this->H[$m+1][$m+1])))) { + break; + } + --$m; + } + for ($i = $m + 2; $i <= $n; ++$i) { + $this->H[$i][$i-2] = 0.0; + if ($i > $m+2) { + $this->H[$i][$i-3] = 0.0; + } + } + // Double QR step involving rows l:n and columns m:n + for ($k = $m; $k <= $n-1; ++$k) { + $notlast = ($k != $n-1); + if ($k != $m) { + $p = $this->H[$k][$k-1]; + $q = $this->H[$k+1][$k-1]; + $r = ($notlast ? $this->H[$k+2][$k-1] : 0.0); + $x = abs($p) + abs($q) + abs($r); + if ($x != 0.0) { + $p = $p / $x; + $q = $q / $x; + $r = $r / $x; + } + } + if ($x == 0.0) { + break; + } + $s = sqrt($p * $p + $q * $q + $r * $r); + if ($p < 0) { + $s = -$s; + } + if ($s != 0) { + if ($k != $m) { + $this->H[$k][$k-1] = -$s * $x; + } elseif ($l != $m) { + $this->H[$k][$k-1] = -$this->H[$k][$k-1]; + } + $p = $p + $s; + $x = $p / $s; + $y = $q / $s; + $z = $r / $s; + $q = $q / $p; + $r = $r / $p; + // Row modification + for ($j = $k; $j < $nn; ++$j) { + $p = $this->H[$k][$j] + $q * $this->H[$k+1][$j]; + if ($notlast) { + $p = $p + $r * $this->H[$k+2][$j]; + $this->H[$k+2][$j] = $this->H[$k+2][$j] - $p * $z; + } + $this->H[$k][$j] = $this->H[$k][$j] - $p * $x; + $this->H[$k+1][$j] = $this->H[$k+1][$j] - $p * $y; + } + // Column modification + for ($i = 0; $i <= min($n, $k+3); ++$i) { + $p = $x * $this->H[$i][$k] + $y * $this->H[$i][$k+1]; + if ($notlast) { + $p = $p + $z * $this->H[$i][$k+2]; + $this->H[$i][$k+2] = $this->H[$i][$k+2] - $p * $r; + } + $this->H[$i][$k] = $this->H[$i][$k] - $p; + $this->H[$i][$k+1] = $this->H[$i][$k+1] - $p * $q; + } + // Accumulate transformations + for ($i = $low; $i <= $high; ++$i) { + $p = $x * $this->V[$i][$k] + $y * $this->V[$i][$k+1]; + if ($notlast) { + $p = $p + $z * $this->V[$i][$k+2]; + $this->V[$i][$k+2] = $this->V[$i][$k+2] - $p * $r; + } + $this->V[$i][$k] = $this->V[$i][$k] - $p; + $this->V[$i][$k+1] = $this->V[$i][$k+1] - $p * $q; + } + } // ($s != 0) + } // k loop + } // check convergence + } // while ($n >= $low) + + // Backsubstitute to find vectors of upper triangular form + if ($norm == 0.0) { + return; + } + + for ($n = $nn-1; $n >= 0; --$n) { + $p = $this->d[$n]; + $q = $this->e[$n]; + // Real vector + if ($q == 0) { + $l = $n; + $this->H[$n][$n] = 1.0; + for ($i = $n-1; $i >= 0; --$i) { + $w = $this->H[$i][$i] - $p; + $r = 0.0; + for ($j = $l; $j <= $n; ++$j) { + $r = $r + $this->H[$i][$j] * $this->H[$j][$n]; + } + if ($this->e[$i] < 0.0) { + $z = $w; + $s = $r; + } else { + $l = $i; + if ($this->e[$i] == 0.0) { + if ($w != 0.0) { + $this->H[$i][$n] = -$r / $w; + } else { + $this->H[$i][$n] = -$r / ($eps * $norm); + } + // Solve real equations + } else { + $x = $this->H[$i][$i+1]; + $y = $this->H[$i+1][$i]; + $q = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i]; + $t = ($x * $s - $z * $r) / $q; + $this->H[$i][$n] = $t; + if (abs($x) > abs($z)) { + $this->H[$i+1][$n] = (-$r - $w * $t) / $x; + } else { + $this->H[$i+1][$n] = (-$s - $y * $t) / $z; + } + } + // Overflow control + $t = abs($this->H[$i][$n]); + if (($eps * $t) * $t > 1) { + for ($j = $i; $j <= $n; ++$j) { + $this->H[$j][$n] = $this->H[$j][$n] / $t; + } + } + } + } + // Complex vector + } else if ($q < 0) { + $l = $n-1; + // Last vector component imaginary so matrix is triangular + if (abs($this->H[$n][$n-1]) > abs($this->H[$n-1][$n])) { + $this->H[$n-1][$n-1] = $q / $this->H[$n][$n-1]; + $this->H[$n-1][$n] = -($this->H[$n][$n] - $p) / $this->H[$n][$n-1]; + } else { + $this->cdiv(0.0, -$this->H[$n-1][$n], $this->H[$n-1][$n-1] - $p, $q); + $this->H[$n-1][$n-1] = $this->cdivr; + $this->H[$n-1][$n] = $this->cdivi; + } + $this->H[$n][$n-1] = 0.0; + $this->H[$n][$n] = 1.0; + for ($i = $n-2; $i >= 0; --$i) { + // double ra,sa,vr,vi; + $ra = 0.0; + $sa = 0.0; + for ($j = $l; $j <= $n; ++$j) { + $ra = $ra + $this->H[$i][$j] * $this->H[$j][$n-1]; + $sa = $sa + $this->H[$i][$j] * $this->H[$j][$n]; + } + $w = $this->H[$i][$i] - $p; + if ($this->e[$i] < 0.0) { + $z = $w; + $r = $ra; + $s = $sa; + } else { + $l = $i; + if ($this->e[$i] == 0) { + $this->cdiv(-$ra, -$sa, $w, $q); + $this->H[$i][$n-1] = $this->cdivr; + $this->H[$i][$n] = $this->cdivi; + } else { + // Solve complex equations + $x = $this->H[$i][$i+1]; + $y = $this->H[$i+1][$i]; + $vr = ($this->d[$i] - $p) * ($this->d[$i] - $p) + $this->e[$i] * $this->e[$i] - $q * $q; + $vi = ($this->d[$i] - $p) * 2.0 * $q; + if ($vr == 0.0 & $vi == 0.0) { + $vr = $eps * $norm * (abs($w) + abs($q) + abs($x) + abs($y) + abs($z)); + } + $this->cdiv($x * $r - $z * $ra + $q * $sa, $x * $s - $z * $sa - $q * $ra, $vr, $vi); + $this->H[$i][$n-1] = $this->cdivr; + $this->H[$i][$n] = $this->cdivi; + if (abs($x) > (abs($z) + abs($q))) { + $this->H[$i+1][$n-1] = (-$ra - $w * $this->H[$i][$n-1] + $q * $this->H[$i][$n]) / $x; + $this->H[$i+1][$n] = (-$sa - $w * $this->H[$i][$n] - $q * $this->H[$i][$n-1]) / $x; + } else { + $this->cdiv(-$r - $y * $this->H[$i][$n-1], -$s - $y * $this->H[$i][$n], $z, $q); + $this->H[$i+1][$n-1] = $this->cdivr; + $this->H[$i+1][$n] = $this->cdivi; + } + } + // Overflow control + $t = max(abs($this->H[$i][$n-1]),abs($this->H[$i][$n])); + if (($eps * $t) * $t > 1) { + for ($j = $i; $j <= $n; ++$j) { + $this->H[$j][$n-1] = $this->H[$j][$n-1] / $t; + $this->H[$j][$n] = $this->H[$j][$n] / $t; + } + } + } // end else + } // end for + } // end else for complex case + } // end for + + // Vectors of isolated roots + for ($i = 0; $i < $nn; ++$i) { + if ($i < $low | $i > $high) { + for ($j = $i; $j < $nn; ++$j) { + $this->V[$i][$j] = $this->H[$i][$j]; + } + } + } + + // Back transformation to get eigenvectors of original matrix + for ($j = $nn-1; $j >= $low; --$j) { + for ($i = $low; $i <= $high; ++$i) { + $z = 0.0; + for ($k = $low; $k <= min($j,$high); ++$k) { + $z = $z + $this->V[$i][$k] * $this->H[$k][$j]; + } + $this->V[$i][$j] = $z; + } + } + } // end hqr2 + + + /** + * Constructor: Check for symmetry, then construct the eigenvalue decomposition + * + * @access public + * @param A Square matrix + * @return Structure to access D and V. + */ + public function __construct($Arg) { + $this->A = $Arg->getArray(); + $this->n = $Arg->getColumnDimension(); + + $issymmetric = true; + for ($j = 0; ($j < $this->n) & $issymmetric; ++$j) { + for ($i = 0; ($i < $this->n) & $issymmetric; ++$i) { + $issymmetric = ($this->A[$i][$j] == $this->A[$j][$i]); + } + } + + if ($issymmetric) { + $this->V = $this->A; + // Tridiagonalize. + $this->tred2(); + // Diagonalize. + $this->tql2(); + } else { + $this->H = $this->A; + $this->ort = array(); + // Reduce to Hessenberg form. + $this->orthes(); + // Reduce Hessenberg to real Schur form. + $this->hqr2(); + } + } + + + /** + * Return the eigenvector matrix + * + * @access public + * @return V + */ + public function getV() { + return new Matrix($this->V, $this->n, $this->n); + } + + + /** + * Return the real parts of the eigenvalues + * + * @access public + * @return real(diag(D)) + */ + public function getRealEigenvalues() { + return $this->d; + } + + + /** + * Return the imaginary parts of the eigenvalues + * + * @access public + * @return imag(diag(D)) + */ + public function getImagEigenvalues() { + return $this->e; + } + + + /** + * Return the block diagonal eigenvalue matrix + * + * @access public + * @return D + */ + public function getD() { + for ($i = 0; $i < $this->n; ++$i) { + $D[$i] = array_fill(0, $this->n, 0.0); + $D[$i][$i] = $this->d[$i]; + if ($this->e[$i] == 0) { + continue; + } + $o = ($this->e[$i] > 0) ? $i + 1 : $i - 1; + $D[$i][$o] = $this->e[$i]; + } + return new Matrix($D); + } + +} // class EigenvalueDecomposition diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/LUDecomposition.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/LUDecomposition.php new file mode 100755 index 0000000..08e500c --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/LUDecomposition.php @@ -0,0 +1,258 @@ +<?php +/** + * @package JAMA + * + * For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n + * unit lower triangular matrix L, an n-by-n upper triangular matrix U, + * and a permutation vector piv of length m so that A(piv,:) = L*U. + * If m < n, then L is m-by-m and U is m-by-n. + * + * The LU decompostion with pivoting always exists, even if the matrix is + * singular, so the constructor will never fail. The primary use of the + * LU decomposition is in the solution of square systems of simultaneous + * linear equations. This will fail if isNonsingular() returns false. + * + * @author Paul Meagher + * @author Bartosz Matosiuk + * @author Michael Bommarito + * @version 1.1 + * @license PHP v3.0 + */ +class PHPExcel_Shared_JAMA_LUDecomposition { + + const MatrixSingularException = "Can only perform operation on singular matrix."; + const MatrixSquareException = "Mismatched Row dimension"; + + /** + * Decomposition storage + * @var array + */ + private $LU = array(); + + /** + * Row dimension. + * @var int + */ + private $m; + + /** + * Column dimension. + * @var int + */ + private $n; + + /** + * Pivot sign. + * @var int + */ + private $pivsign; + + /** + * Internal storage of pivot vector. + * @var array + */ + private $piv = array(); + + + /** + * LU Decomposition constructor. + * + * @param $A Rectangular matrix + * @return Structure to access L, U and piv. + */ + public function __construct($A) { + if ($A instanceof PHPExcel_Shared_JAMA_Matrix) { + // Use a "left-looking", dot-product, Crout/Doolittle algorithm. + $this->LU = $A->getArray(); + $this->m = $A->getRowDimension(); + $this->n = $A->getColumnDimension(); + for ($i = 0; $i < $this->m; ++$i) { + $this->piv[$i] = $i; + } + $this->pivsign = 1; + $LUrowi = $LUcolj = array(); + + // Outer loop. + for ($j = 0; $j < $this->n; ++$j) { + // Make a copy of the j-th column to localize references. + for ($i = 0; $i < $this->m; ++$i) { + $LUcolj[$i] = &$this->LU[$i][$j]; + } + // Apply previous transformations. + for ($i = 0; $i < $this->m; ++$i) { + $LUrowi = $this->LU[$i]; + // Most of the time is spent in the following dot product. + $kmax = min($i,$j); + $s = 0.0; + for ($k = 0; $k < $kmax; ++$k) { + $s += $LUrowi[$k] * $LUcolj[$k]; + } + $LUrowi[$j] = $LUcolj[$i] -= $s; + } + // Find pivot and exchange if necessary. + $p = $j; + for ($i = $j+1; $i < $this->m; ++$i) { + if (abs($LUcolj[$i]) > abs($LUcolj[$p])) { + $p = $i; + } + } + if ($p != $j) { + for ($k = 0; $k < $this->n; ++$k) { + $t = $this->LU[$p][$k]; + $this->LU[$p][$k] = $this->LU[$j][$k]; + $this->LU[$j][$k] = $t; + } + $k = $this->piv[$p]; + $this->piv[$p] = $this->piv[$j]; + $this->piv[$j] = $k; + $this->pivsign = $this->pivsign * -1; + } + // Compute multipliers. + if (($j < $this->m) && ($this->LU[$j][$j] != 0.0)) { + for ($i = $j+1; $i < $this->m; ++$i) { + $this->LU[$i][$j] /= $this->LU[$j][$j]; + } + } + } + } else { + throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::ArgumentTypeException); + } + } // function __construct() + + + /** + * Get lower triangular factor. + * + * @return array Lower triangular factor + */ + public function getL() { + for ($i = 0; $i < $this->m; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + if ($i > $j) { + $L[$i][$j] = $this->LU[$i][$j]; + } elseif ($i == $j) { + $L[$i][$j] = 1.0; + } else { + $L[$i][$j] = 0.0; + } + } + } + return new PHPExcel_Shared_JAMA_Matrix($L); + } // function getL() + + + /** + * Get upper triangular factor. + * + * @return array Upper triangular factor + */ + public function getU() { + for ($i = 0; $i < $this->n; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + if ($i <= $j) { + $U[$i][$j] = $this->LU[$i][$j]; + } else { + $U[$i][$j] = 0.0; + } + } + } + return new PHPExcel_Shared_JAMA_Matrix($U); + } // function getU() + + + /** + * Return pivot permutation vector. + * + * @return array Pivot vector + */ + public function getPivot() { + return $this->piv; + } // function getPivot() + + + /** + * Alias for getPivot + * + * @see getPivot + */ + public function getDoublePivot() { + return $this->getPivot(); + } // function getDoublePivot() + + + /** + * Is the matrix nonsingular? + * + * @return true if U, and hence A, is nonsingular. + */ + public function isNonsingular() { + for ($j = 0; $j < $this->n; ++$j) { + if ($this->LU[$j][$j] == 0) { + return false; + } + } + return true; + } // function isNonsingular() + + + /** + * Count determinants + * + * @return array d matrix deterninat + */ + public function det() { + if ($this->m == $this->n) { + $d = $this->pivsign; + for ($j = 0; $j < $this->n; ++$j) { + $d *= $this->LU[$j][$j]; + } + return $d; + } else { + throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException); + } + } // function det() + + + /** + * Solve A*X = B + * + * @param $B A Matrix with as many rows as A and any number of columns. + * @return X so that L*U*X = B(piv,:) + * @PHPExcel_Calculation_Exception IllegalArgumentException Matrix row dimensions must agree. + * @PHPExcel_Calculation_Exception RuntimeException Matrix is singular. + */ + public function solve($B) { + if ($B->getRowDimension() == $this->m) { + if ($this->isNonsingular()) { + // Copy right hand side with pivoting + $nx = $B->getColumnDimension(); + $X = $B->getMatrix($this->piv, 0, $nx-1); + // Solve L*Y = B(piv,:) + for ($k = 0; $k < $this->n; ++$k) { + for ($i = $k+1; $i < $this->n; ++$i) { + for ($j = 0; $j < $nx; ++$j) { + $X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k]; + } + } + } + // Solve U*X = Y; + for ($k = $this->n-1; $k >= 0; --$k) { + for ($j = 0; $j < $nx; ++$j) { + $X->A[$k][$j] /= $this->LU[$k][$k]; + } + for ($i = 0; $i < $k; ++$i) { + for ($j = 0; $j < $nx; ++$j) { + $X->A[$i][$j] -= $X->A[$k][$j] * $this->LU[$i][$k]; + } + } + } + return $X; + } else { + throw new PHPExcel_Calculation_Exception(self::MatrixSingularException); + } + } else { + throw new PHPExcel_Calculation_Exception(self::MatrixSquareException); + } + } // function solve() + +} // class PHPExcel_Shared_JAMA_LUDecomposition diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/Matrix.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/Matrix.php new file mode 100755 index 0000000..b893a44 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/Matrix.php @@ -0,0 +1,1059 @@ +<?php +/** + * @package JAMA + */ + +/** PHPExcel root directory */ +if (!defined('PHPEXCEL_ROOT')) { + /** + * @ignore + */ + define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../../'); + require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php'); +} + + +/* + * Matrix class + * + * @author Paul Meagher + * @author Michael Bommarito + * @author Lukasz Karapuda + * @author Bartek Matosiuk + * @version 1.8 + * @license PHP v3.0 + * @see http://math.nist.gov/javanumerics/jama/ + */ +class PHPExcel_Shared_JAMA_Matrix { + + + const PolymorphicArgumentException = "Invalid argument pattern for polymorphic function."; + const ArgumentTypeException = "Invalid argument type."; + const ArgumentBoundsException = "Invalid argument range."; + const MatrixDimensionException = "Matrix dimensions are not equal."; + const ArrayLengthException = "Array length must be a multiple of m."; + + /** + * Matrix storage + * + * @var array + * @access public + */ + public $A = array(); + + /** + * Matrix row dimension + * + * @var int + * @access private + */ + private $m; + + /** + * Matrix column dimension + * + * @var int + * @access private + */ + private $n; + + + /** + * Polymorphic constructor + * + * As PHP has no support for polymorphic constructors, we hack our own sort of polymorphism using func_num_args, func_get_arg, and gettype. In essence, we're just implementing a simple RTTI filter and calling the appropriate constructor. + */ + public function __construct() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + //Rectangular matrix - m x n initialized from 2D array + case 'array': + $this->m = count($args[0]); + $this->n = count($args[0][0]); + $this->A = $args[0]; + break; + //Square matrix - n x n + case 'integer': + $this->m = $args[0]; + $this->n = $args[0]; + $this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0)); + break; + //Rectangular matrix - m x n + case 'integer,integer': + $this->m = $args[0]; + $this->n = $args[1]; + $this->A = array_fill(0, $this->m, array_fill(0, $this->n, 0)); + break; + //Rectangular matrix - m x n initialized from packed array + case 'array,integer': + $this->m = $args[1]; + if ($this->m != 0) { + $this->n = count($args[0]) / $this->m; + } else { + $this->n = 0; + } + if (($this->m * $this->n) == count($args[0])) { + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $this->A[$i][$j] = $args[0][$i + $j * $this->m]; + } + } + } else { + throw new PHPExcel_Calculation_Exception(self::ArrayLengthException); + } + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function __construct() + + + /** + * getArray + * + * @return array Matrix array + */ + public function getArray() { + return $this->A; + } // function getArray() + + + /** + * getRowDimension + * + * @return int Row dimension + */ + public function getRowDimension() { + return $this->m; + } // function getRowDimension() + + + /** + * getColumnDimension + * + * @return int Column dimension + */ + public function getColumnDimension() { + return $this->n; + } // function getColumnDimension() + + + /** + * get + * + * Get the i,j-th element of the matrix. + * @param int $i Row position + * @param int $j Column position + * @return mixed Element (int/float/double) + */ + public function get($i = null, $j = null) { + return $this->A[$i][$j]; + } // function get() + + + /** + * getMatrix + * + * Get a submatrix + * @param int $i0 Initial row index + * @param int $iF Final row index + * @param int $j0 Initial column index + * @param int $jF Final column index + * @return Matrix Submatrix + */ + public function getMatrix() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + //A($i0...; $j0...) + case 'integer,integer': + list($i0, $j0) = $args; + if ($i0 >= 0) { $m = $this->m - $i0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if ($j0 >= 0) { $n = $this->n - $j0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + $R = new PHPExcel_Shared_JAMA_Matrix($m, $n); + for($i = $i0; $i < $this->m; ++$i) { + for($j = $j0; $j < $this->n; ++$j) { + $R->set($i, $j, $this->A[$i][$j]); + } + } + return $R; + break; + //A($i0...$iF; $j0...$jF) + case 'integer,integer,integer,integer': + list($i0, $iF, $j0, $jF) = $args; + if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if (($jF > $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + $R = new PHPExcel_Shared_JAMA_Matrix($m+1, $n+1); + for($i = $i0; $i <= $iF; ++$i) { + for($j = $j0; $j <= $jF; ++$j) { + $R->set($i - $i0, $j - $j0, $this->A[$i][$j]); + } + } + return $R; + break; + //$R = array of row indices; $C = array of column indices + case 'array,array': + list($RL, $CL) = $args; + if (count($RL) > 0) { $m = count($RL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + $R = new PHPExcel_Shared_JAMA_Matrix($m, $n); + for($i = 0; $i < $m; ++$i) { + for($j = 0; $j < $n; ++$j) { + $R->set($i - $i0, $j - $j0, $this->A[$RL[$i]][$CL[$j]]); + } + } + return $R; + break; + //$RL = array of row indices; $CL = array of column indices + case 'array,array': + list($RL, $CL) = $args; + if (count($RL) > 0) { $m = count($RL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + $R = new PHPExcel_Shared_JAMA_Matrix($m, $n); + for($i = 0; $i < $m; ++$i) { + for($j = 0; $j < $n; ++$j) { + $R->set($i, $j, $this->A[$RL[$i]][$CL[$j]]); + } + } + return $R; + break; + //A($i0...$iF); $CL = array of column indices + case 'integer,integer,array': + list($i0, $iF, $CL) = $args; + if (($iF > $i0) && ($this->m >= $iF) && ($i0 >= 0)) { $m = $iF - $i0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if (count($CL) > 0) { $n = count($CL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + $R = new PHPExcel_Shared_JAMA_Matrix($m, $n); + for($i = $i0; $i < $iF; ++$i) { + for($j = 0; $j < $n; ++$j) { + $R->set($i - $i0, $j, $this->A[$RL[$i]][$j]); + } + } + return $R; + break; + //$RL = array of row indices + case 'array,integer,integer': + list($RL, $j0, $jF) = $args; + if (count($RL) > 0) { $m = count($RL); } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + if (($jF >= $j0) && ($this->n >= $jF) && ($j0 >= 0)) { $n = $jF - $j0; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentBoundsException); } + $R = new PHPExcel_Shared_JAMA_Matrix($m, $n+1); + for($i = 0; $i < $m; ++$i) { + for($j = $j0; $j <= $jF; ++$j) { + $R->set($i, $j - $j0, $this->A[$RL[$i]][$j]); + } + } + return $R; + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function getMatrix() + + + /** + * checkMatrixDimensions + * + * Is matrix B the same size? + * @param Matrix $B Matrix B + * @return boolean + */ + public function checkMatrixDimensions($B = null) { + if ($B instanceof PHPExcel_Shared_JAMA_Matrix) { + if (($this->m == $B->getRowDimension()) && ($this->n == $B->getColumnDimension())) { + return true; + } else { + throw new PHPExcel_Calculation_Exception(self::MatrixDimensionException); + } + } else { + throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); + } + } // function checkMatrixDimensions() + + + + /** + * set + * + * Set the i,j-th element of the matrix. + * @param int $i Row position + * @param int $j Column position + * @param mixed $c Int/float/double value + * @return mixed Element (int/float/double) + */ + public function set($i = null, $j = null, $c = null) { + // Optimized set version just has this + $this->A[$i][$j] = $c; + } // function set() + + + /** + * identity + * + * Generate an identity matrix. + * @param int $m Row dimension + * @param int $n Column dimension + * @return Matrix Identity matrix + */ + public function identity($m = null, $n = null) { + return $this->diagonal($m, $n, 1); + } // function identity() + + + /** + * diagonal + * + * Generate a diagonal matrix + * @param int $m Row dimension + * @param int $n Column dimension + * @param mixed $c Diagonal value + * @return Matrix Diagonal matrix + */ + public function diagonal($m = null, $n = null, $c = 1) { + $R = new PHPExcel_Shared_JAMA_Matrix($m, $n); + for($i = 0; $i < $m; ++$i) { + $R->set($i, $i, $c); + } + return $R; + } // function diagonal() + + + /** + * getMatrixByRow + * + * Get a submatrix by row index/range + * @param int $i0 Initial row index + * @param int $iF Final row index + * @return Matrix Submatrix + */ + public function getMatrixByRow($i0 = null, $iF = null) { + if (is_int($i0)) { + if (is_int($iF)) { + return $this->getMatrix($i0, 0, $iF + 1, $this->n); + } else { + return $this->getMatrix($i0, 0, $i0 + 1, $this->n); + } + } else { + throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); + } + } // function getMatrixByRow() + + + /** + * getMatrixByCol + * + * Get a submatrix by column index/range + * @param int $i0 Initial column index + * @param int $iF Final column index + * @return Matrix Submatrix + */ + public function getMatrixByCol($j0 = null, $jF = null) { + if (is_int($j0)) { + if (is_int($jF)) { + return $this->getMatrix(0, $j0, $this->m, $jF + 1); + } else { + return $this->getMatrix(0, $j0, $this->m, $j0 + 1); + } + } else { + throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); + } + } // function getMatrixByCol() + + + /** + * transpose + * + * Tranpose matrix + * @return Matrix Transposed matrix + */ + public function transpose() { + $R = new PHPExcel_Shared_JAMA_Matrix($this->n, $this->m); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $R->set($j, $i, $this->A[$i][$j]); + } + } + return $R; + } // function transpose() + + + /** + * trace + * + * Sum of diagonal elements + * @return float Sum of diagonal elements + */ + public function trace() { + $s = 0; + $n = min($this->m, $this->n); + for($i = 0; $i < $n; ++$i) { + $s += $this->A[$i][$i]; + } + return $s; + } // function trace() + + + /** + * uminus + * + * Unary minus matrix -A + * @return Matrix Unary minus matrix + */ + public function uminus() { + } // function uminus() + + + /** + * plus + * + * A + B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function plus() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + break; + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $M->set($i, $j, $M->get($i, $j) + $this->A[$i][$j]); + } + } + return $M; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function plus() + + + /** + * plusEquals + * + * A = A + B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function plusEquals() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + break; + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] += $value; + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } + } + } + return $this; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function plusEquals() + + + /** + * minus + * + * A - B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function minus() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + break; + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $M->set($i, $j, $M->get($i, $j) - $this->A[$i][$j]); + } + } + return $M; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function minus() + + + /** + * minusEquals + * + * A = A - B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function minusEquals() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + break; + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] -= $value; + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } + } + } + return $this; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function minusEquals() + + + /** + * arrayTimes + * + * Element-by-element multiplication + * Cij = Aij * Bij + * @param mixed $B Matrix/Array + * @return Matrix Matrix Cij + */ + public function arrayTimes() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + break; + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $M->set($i, $j, $M->get($i, $j) * $this->A[$i][$j]); + } + } + return $M; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function arrayTimes() + + + /** + * arrayTimesEquals + * + * Element-by-element multiplication + * Aij = Aij * Bij + * @param mixed $B Matrix/Array + * @return Matrix Matrix Aij + */ + public function arrayTimesEquals() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + break; + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] *= $value; + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } + } + } + return $this; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function arrayTimesEquals() + + + /** + * arrayRightDivide + * + * Element-by-element right division + * A / B + * @param Matrix $B Matrix B + * @return Matrix Division result + */ + public function arrayRightDivide() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + break; + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + if ($value == 0) { + // Trap for Divide by Zero error + $M->set($i, $j, '#DIV/0!'); + } else { + $M->set($i, $j, $this->A[$i][$j] / $value); + } + } else { + $M->set($i, $j, PHPExcel_Calculation_Functions::NaN()); + } + } + } + return $M; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function arrayRightDivide() + + + /** + * arrayRightDivideEquals + * + * Element-by-element right division + * Aij = Aij / Bij + * @param mixed $B Matrix/Array + * @return Matrix Matrix Aij + */ + public function arrayRightDivideEquals() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + break; + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $this->A[$i][$j] = $this->A[$i][$j] / $M->get($i, $j); + } + } + return $M; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function arrayRightDivideEquals() + + + /** + * arrayLeftDivide + * + * Element-by-element Left division + * A / B + * @param Matrix $B Matrix B + * @return Matrix Division result + */ + public function arrayLeftDivide() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + break; + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $M->set($i, $j, $M->get($i, $j) / $this->A[$i][$j]); + } + } + return $M; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function arrayLeftDivide() + + + /** + * arrayLeftDivideEquals + * + * Element-by-element Left division + * Aij = Aij / Bij + * @param mixed $B Matrix/Array + * @return Matrix Matrix Aij + */ + public function arrayLeftDivideEquals() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + break; + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $this->A[$i][$j] = $M->get($i, $j) / $this->A[$i][$j]; + } + } + return $M; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function arrayLeftDivideEquals() + + + /** + * times + * + * Matrix multiplication + * @param mixed $n Matrix/Array/Scalar + * @return Matrix Product + */ + public function times() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $B = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + if ($this->n == $B->m) { + $C = new PHPExcel_Shared_JAMA_Matrix($this->m, $B->n); + for($j = 0; $j < $B->n; ++$j) { + for ($k = 0; $k < $this->n; ++$k) { + $Bcolj[$k] = $B->A[$k][$j]; + } + for($i = 0; $i < $this->m; ++$i) { + $Arowi = $this->A[$i]; + $s = 0; + for($k = 0; $k < $this->n; ++$k) { + $s += $Arowi[$k] * $Bcolj[$k]; + } + $C->A[$i][$j] = $s; + } + } + return $C; + } else { + throw new PHPExcel_Calculation_Exception(JAMAError(MatrixDimensionMismatch)); + } + break; + case 'array': + $B = new PHPExcel_Shared_JAMA_Matrix($args[0]); + if ($this->n == $B->m) { + $C = new PHPExcel_Shared_JAMA_Matrix($this->m, $B->n); + for($i = 0; $i < $C->m; ++$i) { + for($j = 0; $j < $C->n; ++$j) { + $s = "0"; + for($k = 0; $k < $C->n; ++$k) { + $s += $this->A[$i][$k] * $B->A[$k][$j]; + } + $C->A[$i][$j] = $s; + } + } + return $C; + } else { + throw new PHPExcel_Calculation_Exception(JAMAError(MatrixDimensionMismatch)); + } + return $M; + break; + case 'integer': + $C = new PHPExcel_Shared_JAMA_Matrix($this->A); + for($i = 0; $i < $C->m; ++$i) { + for($j = 0; $j < $C->n; ++$j) { + $C->A[$i][$j] *= $args[0]; + } + } + return $C; + break; + case 'double': + $C = new PHPExcel_Shared_JAMA_Matrix($this->m, $this->n); + for($i = 0; $i < $C->m; ++$i) { + for($j = 0; $j < $C->n; ++$j) { + $C->A[$i][$j] = $args[0] * $this->A[$i][$j]; + } + } + return $C; + break; + case 'float': + $C = new PHPExcel_Shared_JAMA_Matrix($this->A); + for($i = 0; $i < $C->m; ++$i) { + for($j = 0; $j < $C->n; ++$j) { + $C->A[$i][$j] *= $args[0]; + } + } + return $C; + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function times() + + + /** + * power + * + * A = A ^ B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function power() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + break; + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $validValues = True; + $value = $M->get($i, $j); + if ((is_string($this->A[$i][$j])) && (strlen($this->A[$i][$j]) > 0) && (!is_numeric($this->A[$i][$j]))) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($this->A[$i][$j]); + } + if ((is_string($value)) && (strlen($value) > 0) && (!is_numeric($value))) { + $value = trim($value,'"'); + $validValues &= PHPExcel_Shared_String::convertToNumberIfFraction($value); + } + if ($validValues) { + $this->A[$i][$j] = pow($this->A[$i][$j],$value); + } else { + $this->A[$i][$j] = PHPExcel_Calculation_Functions::NaN(); + } + } + } + return $this; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function power() + + + /** + * concat + * + * A = A & B + * @param mixed $B Matrix/Array + * @return Matrix Sum + */ + public function concat() { + if (func_num_args() > 0) { + $args = func_get_args(); + $match = implode(",", array_map('gettype', $args)); + + switch($match) { + case 'object': + if ($args[0] instanceof PHPExcel_Shared_JAMA_Matrix) { $M = $args[0]; } else { throw new PHPExcel_Calculation_Exception(self::ArgumentTypeException); } + case 'array': + $M = new PHPExcel_Shared_JAMA_Matrix($args[0]); + break; + default: + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + break; + } + $this->checkMatrixDimensions($M); + for($i = 0; $i < $this->m; ++$i) { + for($j = 0; $j < $this->n; ++$j) { + $this->A[$i][$j] = trim($this->A[$i][$j],'"').trim($M->get($i, $j),'"'); + } + } + return $this; + } else { + throw new PHPExcel_Calculation_Exception(self::PolymorphicArgumentException); + } + } // function concat() + + + /** + * Solve A*X = B. + * + * @param Matrix $B Right hand side + * @return Matrix ... Solution if A is square, least squares solution otherwise + */ + public function solve($B) { + if ($this->m == $this->n) { + $LU = new PHPExcel_Shared_JAMA_LUDecomposition($this); + return $LU->solve($B); + } else { + $QR = new QRDecomposition($this); + return $QR->solve($B); + } + } // function solve() + + + /** + * Matrix inverse or pseudoinverse. + * + * @return Matrix ... Inverse(A) if A is square, pseudoinverse otherwise. + */ + public function inverse() { + return $this->solve($this->identity($this->m, $this->m)); + } // function inverse() + + + /** + * det + * + * Calculate determinant + * @return float Determinant + */ + public function det() { + $L = new PHPExcel_Shared_JAMA_LUDecomposition($this); + return $L->det(); + } // function det() + + +} // class PHPExcel_Shared_JAMA_Matrix diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/QRDecomposition.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/QRDecomposition.php new file mode 100755 index 0000000..7538462 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/QRDecomposition.php @@ -0,0 +1,234 @@ +<?php +/** + * @package JAMA + * + * For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n + * orthogonal matrix Q and an n-by-n upper triangular matrix R so that + * A = Q*R. + * + * The QR decompostion always exists, even if the matrix does not have + * full rank, so the constructor will never fail. The primary use of the + * QR decomposition is in the least squares solution of nonsquare systems + * of simultaneous linear equations. This will fail if isFullRank() + * returns false. + * + * @author Paul Meagher + * @license PHP v3.0 + * @version 1.1 + */ +class PHPExcel_Shared_JAMA_QRDecomposition { + + const MatrixRankException = "Can only perform operation on full-rank matrix."; + + /** + * Array for internal storage of decomposition. + * @var array + */ + private $QR = array(); + + /** + * Row dimension. + * @var integer + */ + private $m; + + /** + * Column dimension. + * @var integer + */ + private $n; + + /** + * Array for internal storage of diagonal of R. + * @var array + */ + private $Rdiag = array(); + + + /** + * QR Decomposition computed by Householder reflections. + * + * @param matrix $A Rectangular matrix + * @return Structure to access R and the Householder vectors and compute Q. + */ + public function __construct($A) { + if($A instanceof PHPExcel_Shared_JAMA_Matrix) { + // Initialize. + $this->QR = $A->getArrayCopy(); + $this->m = $A->getRowDimension(); + $this->n = $A->getColumnDimension(); + // Main loop. + for ($k = 0; $k < $this->n; ++$k) { + // Compute 2-norm of k-th column without under/overflow. + $nrm = 0.0; + for ($i = $k; $i < $this->m; ++$i) { + $nrm = hypo($nrm, $this->QR[$i][$k]); + } + if ($nrm != 0.0) { + // Form k-th Householder vector. + if ($this->QR[$k][$k] < 0) { + $nrm = -$nrm; + } + for ($i = $k; $i < $this->m; ++$i) { + $this->QR[$i][$k] /= $nrm; + } + $this->QR[$k][$k] += 1.0; + // Apply transformation to remaining columns. + for ($j = $k+1; $j < $this->n; ++$j) { + $s = 0.0; + for ($i = $k; $i < $this->m; ++$i) { + $s += $this->QR[$i][$k] * $this->QR[$i][$j]; + } + $s = -$s/$this->QR[$k][$k]; + for ($i = $k; $i < $this->m; ++$i) { + $this->QR[$i][$j] += $s * $this->QR[$i][$k]; + } + } + } + $this->Rdiag[$k] = -$nrm; + } + } else { + throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::ArgumentTypeException); + } + } // function __construct() + + + /** + * Is the matrix full rank? + * + * @return boolean true if R, and hence A, has full rank, else false. + */ + public function isFullRank() { + for ($j = 0; $j < $this->n; ++$j) { + if ($this->Rdiag[$j] == 0) { + return false; + } + } + return true; + } // function isFullRank() + + + /** + * Return the Householder vectors + * + * @return Matrix Lower trapezoidal matrix whose columns define the reflections + */ + public function getH() { + for ($i = 0; $i < $this->m; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + if ($i >= $j) { + $H[$i][$j] = $this->QR[$i][$j]; + } else { + $H[$i][$j] = 0.0; + } + } + } + return new PHPExcel_Shared_JAMA_Matrix($H); + } // function getH() + + + /** + * Return the upper triangular factor + * + * @return Matrix upper triangular factor + */ + public function getR() { + for ($i = 0; $i < $this->n; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + if ($i < $j) { + $R[$i][$j] = $this->QR[$i][$j]; + } elseif ($i == $j) { + $R[$i][$j] = $this->Rdiag[$i]; + } else { + $R[$i][$j] = 0.0; + } + } + } + return new PHPExcel_Shared_JAMA_Matrix($R); + } // function getR() + + + /** + * Generate and return the (economy-sized) orthogonal factor + * + * @return Matrix orthogonal factor + */ + public function getQ() { + for ($k = $this->n-1; $k >= 0; --$k) { + for ($i = 0; $i < $this->m; ++$i) { + $Q[$i][$k] = 0.0; + } + $Q[$k][$k] = 1.0; + for ($j = $k; $j < $this->n; ++$j) { + if ($this->QR[$k][$k] != 0) { + $s = 0.0; + for ($i = $k; $i < $this->m; ++$i) { + $s += $this->QR[$i][$k] * $Q[$i][$j]; + } + $s = -$s/$this->QR[$k][$k]; + for ($i = $k; $i < $this->m; ++$i) { + $Q[$i][$j] += $s * $this->QR[$i][$k]; + } + } + } + } + /* + for($i = 0; $i < count($Q); ++$i) { + for($j = 0; $j < count($Q); ++$j) { + if(! isset($Q[$i][$j]) ) { + $Q[$i][$j] = 0; + } + } + } + */ + return new PHPExcel_Shared_JAMA_Matrix($Q); + } // function getQ() + + + /** + * Least squares solution of A*X = B + * + * @param Matrix $B A Matrix with as many rows as A and any number of columns. + * @return Matrix Matrix that minimizes the two norm of Q*R*X-B. + */ + public function solve($B) { + if ($B->getRowDimension() == $this->m) { + if ($this->isFullRank()) { + // Copy right hand side + $nx = $B->getColumnDimension(); + $X = $B->getArrayCopy(); + // Compute Y = transpose(Q)*B + for ($k = 0; $k < $this->n; ++$k) { + for ($j = 0; $j < $nx; ++$j) { + $s = 0.0; + for ($i = $k; $i < $this->m; ++$i) { + $s += $this->QR[$i][$k] * $X[$i][$j]; + } + $s = -$s/$this->QR[$k][$k]; + for ($i = $k; $i < $this->m; ++$i) { + $X[$i][$j] += $s * $this->QR[$i][$k]; + } + } + } + // Solve R*X = Y; + for ($k = $this->n-1; $k >= 0; --$k) { + for ($j = 0; $j < $nx; ++$j) { + $X[$k][$j] /= $this->Rdiag[$k]; + } + for ($i = 0; $i < $k; ++$i) { + for ($j = 0; $j < $nx; ++$j) { + $X[$i][$j] -= $X[$k][$j]* $this->QR[$i][$k]; + } + } + } + $X = new PHPExcel_Shared_JAMA_Matrix($X); + return ($X->getMatrix(0, $this->n-1, 0, $nx)); + } else { + throw new PHPExcel_Calculation_Exception(self::MatrixRankException); + } + } else { + throw new PHPExcel_Calculation_Exception(PHPExcel_Shared_JAMA_Matrix::MatrixDimensionException); + } + } // function solve() + +} // PHPExcel_Shared_JAMA_class QRDecomposition diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/SingularValueDecomposition.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/SingularValueDecomposition.php new file mode 100755 index 0000000..a4b096c --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/SingularValueDecomposition.php @@ -0,0 +1,526 @@ +<?php +/** + * @package JAMA + * + * For an m-by-n matrix A with m >= n, the singular value decomposition is + * an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and + * an n-by-n orthogonal matrix V so that A = U*S*V'. + * + * The singular values, sigma[$k] = S[$k][$k], are ordered so that + * sigma[0] >= sigma[1] >= ... >= sigma[n-1]. + * + * The singular value decompostion always exists, so the constructor will + * never fail. The matrix condition number and the effective numerical + * rank can be computed from this decomposition. + * + * @author Paul Meagher + * @license PHP v3.0 + * @version 1.1 + */ +class SingularValueDecomposition { + + /** + * Internal storage of U. + * @var array + */ + private $U = array(); + + /** + * Internal storage of V. + * @var array + */ + private $V = array(); + + /** + * Internal storage of singular values. + * @var array + */ + private $s = array(); + + /** + * Row dimension. + * @var int + */ + private $m; + + /** + * Column dimension. + * @var int + */ + private $n; + + + /** + * Construct the singular value decomposition + * + * Derived from LINPACK code. + * + * @param $A Rectangular matrix + * @return Structure to access U, S and V. + */ + public function __construct($Arg) { + + // Initialize. + $A = $Arg->getArrayCopy(); + $this->m = $Arg->getRowDimension(); + $this->n = $Arg->getColumnDimension(); + $nu = min($this->m, $this->n); + $e = array(); + $work = array(); + $wantu = true; + $wantv = true; + $nct = min($this->m - 1, $this->n); + $nrt = max(0, min($this->n - 2, $this->m)); + + // Reduce A to bidiagonal form, storing the diagonal elements + // in s and the super-diagonal elements in e. + for ($k = 0; $k < max($nct,$nrt); ++$k) { + + if ($k < $nct) { + // Compute the transformation for the k-th column and + // place the k-th diagonal in s[$k]. + // Compute 2-norm of k-th column without under/overflow. + $this->s[$k] = 0; + for ($i = $k; $i < $this->m; ++$i) { + $this->s[$k] = hypo($this->s[$k], $A[$i][$k]); + } + if ($this->s[$k] != 0.0) { + if ($A[$k][$k] < 0.0) { + $this->s[$k] = -$this->s[$k]; + } + for ($i = $k; $i < $this->m; ++$i) { + $A[$i][$k] /= $this->s[$k]; + } + $A[$k][$k] += 1.0; + } + $this->s[$k] = -$this->s[$k]; + } + + for ($j = $k + 1; $j < $this->n; ++$j) { + if (($k < $nct) & ($this->s[$k] != 0.0)) { + // Apply the transformation. + $t = 0; + for ($i = $k; $i < $this->m; ++$i) { + $t += $A[$i][$k] * $A[$i][$j]; + } + $t = -$t / $A[$k][$k]; + for ($i = $k; $i < $this->m; ++$i) { + $A[$i][$j] += $t * $A[$i][$k]; + } + // Place the k-th row of A into e for the + // subsequent calculation of the row transformation. + $e[$j] = $A[$k][$j]; + } + } + + if ($wantu AND ($k < $nct)) { + // Place the transformation in U for subsequent back + // multiplication. + for ($i = $k; $i < $this->m; ++$i) { + $this->U[$i][$k] = $A[$i][$k]; + } + } + + if ($k < $nrt) { + // Compute the k-th row transformation and place the + // k-th super-diagonal in e[$k]. + // Compute 2-norm without under/overflow. + $e[$k] = 0; + for ($i = $k + 1; $i < $this->n; ++$i) { + $e[$k] = hypo($e[$k], $e[$i]); + } + if ($e[$k] != 0.0) { + if ($e[$k+1] < 0.0) { + $e[$k] = -$e[$k]; + } + for ($i = $k + 1; $i < $this->n; ++$i) { + $e[$i] /= $e[$k]; + } + $e[$k+1] += 1.0; + } + $e[$k] = -$e[$k]; + if (($k+1 < $this->m) AND ($e[$k] != 0.0)) { + // Apply the transformation. + for ($i = $k+1; $i < $this->m; ++$i) { + $work[$i] = 0.0; + } + for ($j = $k+1; $j < $this->n; ++$j) { + for ($i = $k+1; $i < $this->m; ++$i) { + $work[$i] += $e[$j] * $A[$i][$j]; + } + } + for ($j = $k + 1; $j < $this->n; ++$j) { + $t = -$e[$j] / $e[$k+1]; + for ($i = $k + 1; $i < $this->m; ++$i) { + $A[$i][$j] += $t * $work[$i]; + } + } + } + if ($wantv) { + // Place the transformation in V for subsequent + // back multiplication. + for ($i = $k + 1; $i < $this->n; ++$i) { + $this->V[$i][$k] = $e[$i]; + } + } + } + } + + // Set up the final bidiagonal matrix or order p. + $p = min($this->n, $this->m + 1); + if ($nct < $this->n) { + $this->s[$nct] = $A[$nct][$nct]; + } + if ($this->m < $p) { + $this->s[$p-1] = 0.0; + } + if ($nrt + 1 < $p) { + $e[$nrt] = $A[$nrt][$p-1]; + } + $e[$p-1] = 0.0; + // If required, generate U. + if ($wantu) { + for ($j = $nct; $j < $nu; ++$j) { + for ($i = 0; $i < $this->m; ++$i) { + $this->U[$i][$j] = 0.0; + } + $this->U[$j][$j] = 1.0; + } + for ($k = $nct - 1; $k >= 0; --$k) { + if ($this->s[$k] != 0.0) { + for ($j = $k + 1; $j < $nu; ++$j) { + $t = 0; + for ($i = $k; $i < $this->m; ++$i) { + $t += $this->U[$i][$k] * $this->U[$i][$j]; + } + $t = -$t / $this->U[$k][$k]; + for ($i = $k; $i < $this->m; ++$i) { + $this->U[$i][$j] += $t * $this->U[$i][$k]; + } + } + for ($i = $k; $i < $this->m; ++$i ) { + $this->U[$i][$k] = -$this->U[$i][$k]; + } + $this->U[$k][$k] = 1.0 + $this->U[$k][$k]; + for ($i = 0; $i < $k - 1; ++$i) { + $this->U[$i][$k] = 0.0; + } + } else { + for ($i = 0; $i < $this->m; ++$i) { + $this->U[$i][$k] = 0.0; + } + $this->U[$k][$k] = 1.0; + } + } + } + + // If required, generate V. + if ($wantv) { + for ($k = $this->n - 1; $k >= 0; --$k) { + if (($k < $nrt) AND ($e[$k] != 0.0)) { + for ($j = $k + 1; $j < $nu; ++$j) { + $t = 0; + for ($i = $k + 1; $i < $this->n; ++$i) { + $t += $this->V[$i][$k]* $this->V[$i][$j]; + } + $t = -$t / $this->V[$k+1][$k]; + for ($i = $k + 1; $i < $this->n; ++$i) { + $this->V[$i][$j] += $t * $this->V[$i][$k]; + } + } + } + for ($i = 0; $i < $this->n; ++$i) { + $this->V[$i][$k] = 0.0; + } + $this->V[$k][$k] = 1.0; + } + } + + // Main iteration loop for the singular values. + $pp = $p - 1; + $iter = 0; + $eps = pow(2.0, -52.0); + + while ($p > 0) { + // Here is where a test for too many iterations would go. + // This section of the program inspects for negligible + // elements in the s and e arrays. On completion the + // variables kase and k are set as follows: + // kase = 1 if s(p) and e[k-1] are negligible and k<p + // kase = 2 if s(k) is negligible and k<p + // kase = 3 if e[k-1] is negligible, k<p, and + // s(k), ..., s(p) are not negligible (qr step). + // kase = 4 if e(p-1) is negligible (convergence). + for ($k = $p - 2; $k >= -1; --$k) { + if ($k == -1) { + break; + } + if (abs($e[$k]) <= $eps * (abs($this->s[$k]) + abs($this->s[$k+1]))) { + $e[$k] = 0.0; + break; + } + } + if ($k == $p - 2) { + $kase = 4; + } else { + for ($ks = $p - 1; $ks >= $k; --$ks) { + if ($ks == $k) { + break; + } + $t = ($ks != $p ? abs($e[$ks]) : 0.) + ($ks != $k + 1 ? abs($e[$ks-1]) : 0.); + if (abs($this->s[$ks]) <= $eps * $t) { + $this->s[$ks] = 0.0; + break; + } + } + if ($ks == $k) { + $kase = 3; + } else if ($ks == $p-1) { + $kase = 1; + } else { + $kase = 2; + $k = $ks; + } + } + ++$k; + + // Perform the task indicated by kase. + switch ($kase) { + // Deflate negligible s(p). + case 1: + $f = $e[$p-2]; + $e[$p-2] = 0.0; + for ($j = $p - 2; $j >= $k; --$j) { + $t = hypo($this->s[$j],$f); + $cs = $this->s[$j] / $t; + $sn = $f / $t; + $this->s[$j] = $t; + if ($j != $k) { + $f = -$sn * $e[$j-1]; + $e[$j-1] = $cs * $e[$j-1]; + } + if ($wantv) { + for ($i = 0; $i < $this->n; ++$i) { + $t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$p-1]; + $this->V[$i][$p-1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$p-1]; + $this->V[$i][$j] = $t; + } + } + } + break; + // Split at negligible s(k). + case 2: + $f = $e[$k-1]; + $e[$k-1] = 0.0; + for ($j = $k; $j < $p; ++$j) { + $t = hypo($this->s[$j], $f); + $cs = $this->s[$j] / $t; + $sn = $f / $t; + $this->s[$j] = $t; + $f = -$sn * $e[$j]; + $e[$j] = $cs * $e[$j]; + if ($wantu) { + for ($i = 0; $i < $this->m; ++$i) { + $t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$k-1]; + $this->U[$i][$k-1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$k-1]; + $this->U[$i][$j] = $t; + } + } + } + break; + // Perform one qr step. + case 3: + // Calculate the shift. + $scale = max(max(max(max( + abs($this->s[$p-1]),abs($this->s[$p-2])),abs($e[$p-2])), + abs($this->s[$k])), abs($e[$k])); + $sp = $this->s[$p-1] / $scale; + $spm1 = $this->s[$p-2] / $scale; + $epm1 = $e[$p-2] / $scale; + $sk = $this->s[$k] / $scale; + $ek = $e[$k] / $scale; + $b = (($spm1 + $sp) * ($spm1 - $sp) + $epm1 * $epm1) / 2.0; + $c = ($sp * $epm1) * ($sp * $epm1); + $shift = 0.0; + if (($b != 0.0) || ($c != 0.0)) { + $shift = sqrt($b * $b + $c); + if ($b < 0.0) { + $shift = -$shift; + } + $shift = $c / ($b + $shift); + } + $f = ($sk + $sp) * ($sk - $sp) + $shift; + $g = $sk * $ek; + // Chase zeros. + for ($j = $k; $j < $p-1; ++$j) { + $t = hypo($f,$g); + $cs = $f/$t; + $sn = $g/$t; + if ($j != $k) { + $e[$j-1] = $t; + } + $f = $cs * $this->s[$j] + $sn * $e[$j]; + $e[$j] = $cs * $e[$j] - $sn * $this->s[$j]; + $g = $sn * $this->s[$j+1]; + $this->s[$j+1] = $cs * $this->s[$j+1]; + if ($wantv) { + for ($i = 0; $i < $this->n; ++$i) { + $t = $cs * $this->V[$i][$j] + $sn * $this->V[$i][$j+1]; + $this->V[$i][$j+1] = -$sn * $this->V[$i][$j] + $cs * $this->V[$i][$j+1]; + $this->V[$i][$j] = $t; + } + } + $t = hypo($f,$g); + $cs = $f/$t; + $sn = $g/$t; + $this->s[$j] = $t; + $f = $cs * $e[$j] + $sn * $this->s[$j+1]; + $this->s[$j+1] = -$sn * $e[$j] + $cs * $this->s[$j+1]; + $g = $sn * $e[$j+1]; + $e[$j+1] = $cs * $e[$j+1]; + if ($wantu && ($j < $this->m - 1)) { + for ($i = 0; $i < $this->m; ++$i) { + $t = $cs * $this->U[$i][$j] + $sn * $this->U[$i][$j+1]; + $this->U[$i][$j+1] = -$sn * $this->U[$i][$j] + $cs * $this->U[$i][$j+1]; + $this->U[$i][$j] = $t; + } + } + } + $e[$p-2] = $f; + $iter = $iter + 1; + break; + // Convergence. + case 4: + // Make the singular values positive. + if ($this->s[$k] <= 0.0) { + $this->s[$k] = ($this->s[$k] < 0.0 ? -$this->s[$k] : 0.0); + if ($wantv) { + for ($i = 0; $i <= $pp; ++$i) { + $this->V[$i][$k] = -$this->V[$i][$k]; + } + } + } + // Order the singular values. + while ($k < $pp) { + if ($this->s[$k] >= $this->s[$k+1]) { + break; + } + $t = $this->s[$k]; + $this->s[$k] = $this->s[$k+1]; + $this->s[$k+1] = $t; + if ($wantv AND ($k < $this->n - 1)) { + for ($i = 0; $i < $this->n; ++$i) { + $t = $this->V[$i][$k+1]; + $this->V[$i][$k+1] = $this->V[$i][$k]; + $this->V[$i][$k] = $t; + } + } + if ($wantu AND ($k < $this->m-1)) { + for ($i = 0; $i < $this->m; ++$i) { + $t = $this->U[$i][$k+1]; + $this->U[$i][$k+1] = $this->U[$i][$k]; + $this->U[$i][$k] = $t; + } + } + ++$k; + } + $iter = 0; + --$p; + break; + } // end switch + } // end while + + } // end constructor + + + /** + * Return the left singular vectors + * + * @access public + * @return U + */ + public function getU() { + return new Matrix($this->U, $this->m, min($this->m + 1, $this->n)); + } + + + /** + * Return the right singular vectors + * + * @access public + * @return V + */ + public function getV() { + return new Matrix($this->V); + } + + + /** + * Return the one-dimensional array of singular values + * + * @access public + * @return diagonal of S. + */ + public function getSingularValues() { + return $this->s; + } + + + /** + * Return the diagonal matrix of singular values + * + * @access public + * @return S + */ + public function getS() { + for ($i = 0; $i < $this->n; ++$i) { + for ($j = 0; $j < $this->n; ++$j) { + $S[$i][$j] = 0.0; + } + $S[$i][$i] = $this->s[$i]; + } + return new Matrix($S); + } + + + /** + * Two norm + * + * @access public + * @return max(S) + */ + public function norm2() { + return $this->s[0]; + } + + + /** + * Two norm condition number + * + * @access public + * @return max(S)/min(S) + */ + public function cond() { + return $this->s[0] / $this->s[min($this->m, $this->n) - 1]; + } + + + /** + * Effective numerical matrix rank + * + * @access public + * @return Number of nonnegligible singular values. + */ + public function rank() { + $eps = pow(2.0, -52.0); + $tol = max($this->m, $this->n) * $this->s[0] * $eps; + $r = 0; + for ($i = 0; $i < count($this->s); ++$i) { + if ($this->s[$i] > $tol) { + ++$r; + } + } + return $r; + } + +} // class SingularValueDecomposition diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/utils/Error.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/utils/Error.php new file mode 100755 index 0000000..e73252b --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/utils/Error.php @@ -0,0 +1,82 @@ +<?php +/** + * @package JAMA + * + * Error handling + * @author Michael Bommarito + * @version 01292005 + */ + +//Language constant +define('JAMALANG', 'EN'); + + +//All errors may be defined by the following format: +//define('ExceptionName', N); +//$error['lang'][ExceptionName] = 'Error message'; +$error = array(); + +/* +I've used Babelfish and a little poor knowledge of Romance/Germanic languages for the translations here. +Feel free to correct anything that looks amiss to you. +*/ + +define('PolymorphicArgumentException', -1); +$error['EN'][PolymorphicArgumentException] = "Invalid argument pattern for polymorphic function."; +$error['FR'][PolymorphicArgumentException] = "Modèle inadmissible d'argument pour la fonction polymorphe.". +$error['DE'][PolymorphicArgumentException] = "Unzulässiges Argumentmuster für polymorphe Funktion."; + +define('ArgumentTypeException', -2); +$error['EN'][ArgumentTypeException] = "Invalid argument type."; +$error['FR'][ArgumentTypeException] = "Type inadmissible d'argument."; +$error['DE'][ArgumentTypeException] = "Unzulässige Argumentart."; + +define('ArgumentBoundsException', -3); +$error['EN'][ArgumentBoundsException] = "Invalid argument range."; +$error['FR'][ArgumentBoundsException] = "Gamme inadmissible d'argument."; +$error['DE'][ArgumentBoundsException] = "Unzulässige Argumentstrecke."; + +define('MatrixDimensionException', -4); +$error['EN'][MatrixDimensionException] = "Matrix dimensions are not equal."; +$error['FR'][MatrixDimensionException] = "Les dimensions de Matrix ne sont pas égales."; +$error['DE'][MatrixDimensionException] = "Matrixmaße sind nicht gleich."; + +define('PrecisionLossException', -5); +$error['EN'][PrecisionLossException] = "Significant precision loss detected."; +$error['FR'][PrecisionLossException] = "Perte significative de précision détectée."; +$error['DE'][PrecisionLossException] = "Bedeutender Präzision Verlust ermittelte."; + +define('MatrixSPDException', -6); +$error['EN'][MatrixSPDException] = "Can only perform operation on symmetric positive definite matrix."; +$error['FR'][MatrixSPDException] = "Perte significative de précision détectée."; +$error['DE'][MatrixSPDException] = "Bedeutender Präzision Verlust ermittelte."; + +define('MatrixSingularException', -7); +$error['EN'][MatrixSingularException] = "Can only perform operation on singular matrix."; + +define('MatrixRankException', -8); +$error['EN'][MatrixRankException] = "Can only perform operation on full-rank matrix."; + +define('ArrayLengthException', -9); +$error['EN'][ArrayLengthException] = "Array length must be a multiple of m."; + +define('RowLengthException', -10); +$error['EN'][RowLengthException] = "All rows must have the same length."; + +/** + * Custom error handler + * @param int $num Error number + */ +function JAMAError($errorNumber = null) { + global $error; + + if (isset($errorNumber)) { + if (isset($error[JAMALANG][$errorNumber])) { + return $error[JAMALANG][$errorNumber]; + } else { + return $error['EN'][$errorNumber]; + } + } else { + return ("Invalid argument to JAMAError()"); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/utils/Maths.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/utils/Maths.php new file mode 100755 index 0000000..aa09a8b --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/JAMA/utils/Maths.php @@ -0,0 +1,43 @@ +<?php +/** + * @package JAMA + * + * Pythagorean Theorem: + * + * a = 3 + * b = 4 + * r = sqrt(square(a) + square(b)) + * r = 5 + * + * r = sqrt(a^2 + b^2) without under/overflow. + */ +function hypo($a, $b) { + if (abs($a) > abs($b)) { + $r = $b / $a; + $r = abs($a) * sqrt(1 + $r * $r); + } elseif ($b != 0) { + $r = $a / $b; + $r = abs($b) * sqrt(1 + $r * $r); + } else { + $r = 0.0; + } + return $r; +} // function hypo() + + +/** + * Mike Bommarito's version. + * Compute n-dimensional hyotheneuse. + * +function hypot() { + $s = 0; + foreach (func_get_args() as $d) { + if (is_numeric($d)) { + $s += pow($d, 2); + } else { + throw new PHPExcel_Calculation_Exception(JAMAError(ArgumentTypeException)); + } + } + return sqrt($s); +} +*/ diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE.php new file mode 100755 index 0000000..9796282 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE.php @@ -0,0 +1,531 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------+ +// | PHP Version 4 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2002 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 2.02 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available at through the world-wide-web at | +// | http://www.php.net/license/2_02.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Xavier Noguer <xnoguer@php.net> | +// | Based on OLE::Storage_Lite by Kawai, Takanori | +// +----------------------------------------------------------------------+ +// +// $Id: OLE.php,v 1.13 2007/03/07 14:38:25 schmidt Exp $ + + +/** +* Array for storing OLE instances that are accessed from +* OLE_ChainedBlockStream::stream_open(). +* @var array +*/ +$GLOBALS['_OLE_INSTANCES'] = array(); + +/** +* OLE package base class. +* +* @author Xavier Noguer <xnoguer@php.net> +* @author Christian Schmidt <schmidt@php.net> +* @category PHPExcel +* @package PHPExcel_Shared_OLE +*/ +class PHPExcel_Shared_OLE +{ + const OLE_PPS_TYPE_ROOT = 5; + const OLE_PPS_TYPE_DIR = 1; + const OLE_PPS_TYPE_FILE = 2; + const OLE_DATA_SIZE_SMALL = 0x1000; + const OLE_LONG_INT_SIZE = 4; + const OLE_PPS_SIZE = 0x80; + + /** + * The file handle for reading an OLE container + * @var resource + */ + public $_file_handle; + + /** + * Array of PPS's found on the OLE container + * @var array + */ + public $_list = array(); + + /** + * Root directory of OLE container + * @var OLE_PPS_Root + */ + public $root; + + /** + * Big Block Allocation Table + * @var array (blockId => nextBlockId) + */ + public $bbat; + + /** + * Short Block Allocation Table + * @var array (blockId => nextBlockId) + */ + public $sbat; + + /** + * Size of big blocks. This is usually 512. + * @var int number of octets per block. + */ + public $bigBlockSize; + + /** + * Size of small blocks. This is usually 64. + * @var int number of octets per block + */ + public $smallBlockSize; + + /** + * Reads an OLE container from the contents of the file given. + * + * @acces public + * @param string $file + * @return mixed true on success, PEAR_Error on failure + */ + public function read($file) + { + $fh = fopen($file, "r"); + if (!$fh) { + throw new PHPExcel_Reader_Exception("Can't open file $file"); + } + $this->_file_handle = $fh; + + $signature = fread($fh, 8); + if ("\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" != $signature) { + throw new PHPExcel_Reader_Exception("File doesn't seem to be an OLE container."); + } + fseek($fh, 28); + if (fread($fh, 2) != "\xFE\xFF") { + // This shouldn't be a problem in practice + throw new PHPExcel_Reader_Exception("Only Little-Endian encoding is supported."); + } + // Size of blocks and short blocks in bytes + $this->bigBlockSize = pow(2, self::_readInt2($fh)); + $this->smallBlockSize = pow(2, self::_readInt2($fh)); + + // Skip UID, revision number and version number + fseek($fh, 44); + // Number of blocks in Big Block Allocation Table + $bbatBlockCount = self::_readInt4($fh); + + // Root chain 1st block + $directoryFirstBlockId = self::_readInt4($fh); + + // Skip unused bytes + fseek($fh, 56); + // Streams shorter than this are stored using small blocks + $this->bigBlockThreshold = self::_readInt4($fh); + // Block id of first sector in Short Block Allocation Table + $sbatFirstBlockId = self::_readInt4($fh); + // Number of blocks in Short Block Allocation Table + $sbbatBlockCount = self::_readInt4($fh); + // Block id of first sector in Master Block Allocation Table + $mbatFirstBlockId = self::_readInt4($fh); + // Number of blocks in Master Block Allocation Table + $mbbatBlockCount = self::_readInt4($fh); + $this->bbat = array(); + + // Remaining 4 * 109 bytes of current block is beginning of Master + // Block Allocation Table + $mbatBlocks = array(); + for ($i = 0; $i < 109; ++$i) { + $mbatBlocks[] = self::_readInt4($fh); + } + + // Read rest of Master Block Allocation Table (if any is left) + $pos = $this->_getBlockOffset($mbatFirstBlockId); + for ($i = 0; $i < $mbbatBlockCount; ++$i) { + fseek($fh, $pos); + for ($j = 0; $j < $this->bigBlockSize / 4 - 1; ++$j) { + $mbatBlocks[] = self::_readInt4($fh); + } + // Last block id in each block points to next block + $pos = $this->_getBlockOffset(self::_readInt4($fh)); + } + + // Read Big Block Allocation Table according to chain specified by + // $mbatBlocks + for ($i = 0; $i < $bbatBlockCount; ++$i) { + $pos = $this->_getBlockOffset($mbatBlocks[$i]); + fseek($fh, $pos); + for ($j = 0 ; $j < $this->bigBlockSize / 4; ++$j) { + $this->bbat[] = self::_readInt4($fh); + } + } + + // Read short block allocation table (SBAT) + $this->sbat = array(); + $shortBlockCount = $sbbatBlockCount * $this->bigBlockSize / 4; + $sbatFh = $this->getStream($sbatFirstBlockId); + for ($blockId = 0; $blockId < $shortBlockCount; ++$blockId) { + $this->sbat[$blockId] = self::_readInt4($sbatFh); + } + fclose($sbatFh); + + $this->_readPpsWks($directoryFirstBlockId); + + return true; + } + + /** + * @param int block id + * @param int byte offset from beginning of file + * @access public + */ + public function _getBlockOffset($blockId) + { + return 512 + $blockId * $this->bigBlockSize; + } + + /** + * Returns a stream for use with fread() etc. External callers should + * use PHPExcel_Shared_OLE_PPS_File::getStream(). + * @param int|PPS block id or PPS + * @return resource read-only stream + */ + public function getStream($blockIdOrPps) + { + static $isRegistered = false; + if (!$isRegistered) { + stream_wrapper_register('ole-chainedblockstream', + 'PHPExcel_Shared_OLE_ChainedBlockStream'); + $isRegistered = true; + } + + // Store current instance in global array, so that it can be accessed + // in OLE_ChainedBlockStream::stream_open(). + // Object is removed from self::$instances in OLE_Stream::close(). + $GLOBALS['_OLE_INSTANCES'][] = $this; + $instanceId = end(array_keys($GLOBALS['_OLE_INSTANCES'])); + + $path = 'ole-chainedblockstream://oleInstanceId=' . $instanceId; + if ($blockIdOrPps instanceof PHPExcel_Shared_OLE_PPS) { + $path .= '&blockId=' . $blockIdOrPps->_StartBlock; + $path .= '&size=' . $blockIdOrPps->Size; + } else { + $path .= '&blockId=' . $blockIdOrPps; + } + return fopen($path, 'r'); + } + + /** + * Reads a signed char. + * @param resource file handle + * @return int + * @access public + */ + private static function _readInt1($fh) + { + list(, $tmp) = unpack("c", fread($fh, 1)); + return $tmp; + } + + /** + * Reads an unsigned short (2 octets). + * @param resource file handle + * @return int + * @access public + */ + private static function _readInt2($fh) + { + list(, $tmp) = unpack("v", fread($fh, 2)); + return $tmp; + } + + /** + * Reads an unsigned long (4 octets). + * @param resource file handle + * @return int + * @access public + */ + private static function _readInt4($fh) + { + list(, $tmp) = unpack("V", fread($fh, 4)); + return $tmp; + } + + /** + * Gets information about all PPS's on the OLE container from the PPS WK's + * creates an OLE_PPS object for each one. + * + * @access public + * @param integer the block id of the first block + * @return mixed true on success, PEAR_Error on failure + */ + public function _readPpsWks($blockId) + { + $fh = $this->getStream($blockId); + for ($pos = 0; ; $pos += 128) { + fseek($fh, $pos, SEEK_SET); + $nameUtf16 = fread($fh, 64); + $nameLength = self::_readInt2($fh); + $nameUtf16 = substr($nameUtf16, 0, $nameLength - 2); + // Simple conversion from UTF-16LE to ISO-8859-1 + $name = str_replace("\x00", "", $nameUtf16); + $type = self::_readInt1($fh); + switch ($type) { + case self::OLE_PPS_TYPE_ROOT: + $pps = new PHPExcel_Shared_OLE_PPS_Root(null, null, array()); + $this->root = $pps; + break; + case self::OLE_PPS_TYPE_DIR: + $pps = new PHPExcel_Shared_OLE_PPS(null, null, null, null, null, + null, null, null, null, array()); + break; + case self::OLE_PPS_TYPE_FILE: + $pps = new PHPExcel_Shared_OLE_PPS_File($name); + break; + default: + continue; + } + fseek($fh, 1, SEEK_CUR); + $pps->Type = $type; + $pps->Name = $name; + $pps->PrevPps = self::_readInt4($fh); + $pps->NextPps = self::_readInt4($fh); + $pps->DirPps = self::_readInt4($fh); + fseek($fh, 20, SEEK_CUR); + $pps->Time1st = self::OLE2LocalDate(fread($fh, 8)); + $pps->Time2nd = self::OLE2LocalDate(fread($fh, 8)); + $pps->_StartBlock = self::_readInt4($fh); + $pps->Size = self::_readInt4($fh); + $pps->No = count($this->_list); + $this->_list[] = $pps; + + // check if the PPS tree (starting from root) is complete + if (isset($this->root) && + $this->_ppsTreeComplete($this->root->No)) { + + break; + } + } + fclose($fh); + + // Initialize $pps->children on directories + foreach ($this->_list as $pps) { + if ($pps->Type == self::OLE_PPS_TYPE_DIR || $pps->Type == self::OLE_PPS_TYPE_ROOT) { + $nos = array($pps->DirPps); + $pps->children = array(); + while ($nos) { + $no = array_pop($nos); + if ($no != -1) { + $childPps = $this->_list[$no]; + $nos[] = $childPps->PrevPps; + $nos[] = $childPps->NextPps; + $pps->children[] = $childPps; + } + } + } + } + + return true; + } + + /** + * It checks whether the PPS tree is complete (all PPS's read) + * starting with the given PPS (not necessarily root) + * + * @access public + * @param integer $index The index of the PPS from which we are checking + * @return boolean Whether the PPS tree for the given PPS is complete + */ + public function _ppsTreeComplete($index) + { + return isset($this->_list[$index]) && + ($pps = $this->_list[$index]) && + ($pps->PrevPps == -1 || + $this->_ppsTreeComplete($pps->PrevPps)) && + ($pps->NextPps == -1 || + $this->_ppsTreeComplete($pps->NextPps)) && + ($pps->DirPps == -1 || + $this->_ppsTreeComplete($pps->DirPps)); + } + + /** + * Checks whether a PPS is a File PPS or not. + * If there is no PPS for the index given, it will return false. + * + * @access public + * @param integer $index The index for the PPS + * @return bool true if it's a File PPS, false otherwise + */ + public function isFile($index) + { + if (isset($this->_list[$index])) { + return ($this->_list[$index]->Type == self::OLE_PPS_TYPE_FILE); + } + return false; + } + + /** + * Checks whether a PPS is a Root PPS or not. + * If there is no PPS for the index given, it will return false. + * + * @access public + * @param integer $index The index for the PPS. + * @return bool true if it's a Root PPS, false otherwise + */ + public function isRoot($index) + { + if (isset($this->_list[$index])) { + return ($this->_list[$index]->Type == self::OLE_PPS_TYPE_ROOT); + } + return false; + } + + /** + * Gives the total number of PPS's found in the OLE container. + * + * @access public + * @return integer The total number of PPS's found in the OLE container + */ + public function ppsTotal() + { + return count($this->_list); + } + + /** + * Gets data from a PPS + * If there is no PPS for the index given, it will return an empty string. + * + * @access public + * @param integer $index The index for the PPS + * @param integer $position The position from which to start reading + * (relative to the PPS) + * @param integer $length The amount of bytes to read (at most) + * @return string The binary string containing the data requested + * @see OLE_PPS_File::getStream() + */ + public function getData($index, $position, $length) + { + // if position is not valid return empty string + if (!isset($this->_list[$index]) || ($position >= $this->_list[$index]->Size) || ($position < 0)) { + return ''; + } + $fh = $this->getStream($this->_list[$index]); + $data = stream_get_contents($fh, $length, $position); + fclose($fh); + return $data; + } + + /** + * Gets the data length from a PPS + * If there is no PPS for the index given, it will return 0. + * + * @access public + * @param integer $index The index for the PPS + * @return integer The amount of bytes in data the PPS has + */ + public function getDataLength($index) + { + if (isset($this->_list[$index])) { + return $this->_list[$index]->Size; + } + return 0; + } + + /** + * Utility function to transform ASCII text to Unicode + * + * @access public + * @static + * @param string $ascii The ASCII string to transform + * @return string The string in Unicode + */ + public static function Asc2Ucs($ascii) + { + $rawname = ''; + for ($i = 0; $i < strlen($ascii); ++$i) { + $rawname .= $ascii{$i} . "\x00"; + } + return $rawname; + } + + /** + * Utility function + * Returns a string for the OLE container with the date given + * + * @access public + * @static + * @param integer $date A timestamp + * @return string The string for the OLE container + */ + public static function LocalDate2OLE($date = null) + { + if (!isset($date)) { + return "\x00\x00\x00\x00\x00\x00\x00\x00"; + } + + // factor used for separating numbers into 4 bytes parts + $factor = pow(2, 32); + + // days from 1-1-1601 until the beggining of UNIX era + $days = 134774; + // calculate seconds + $big_date = $days*24*3600 + gmmktime(date("H",$date),date("i",$date),date("s",$date), + date("m",$date),date("d",$date),date("Y",$date)); + // multiply just to make MS happy + $big_date *= 10000000; + + $high_part = floor($big_date / $factor); + // lower 4 bytes + $low_part = floor((($big_date / $factor) - $high_part) * $factor); + + // Make HEX string + $res = ''; + + for ($i = 0; $i < 4; ++$i) { + $hex = $low_part % 0x100; + $res .= pack('c', $hex); + $low_part /= 0x100; + } + for ($i = 0; $i < 4; ++$i) { + $hex = $high_part % 0x100; + $res .= pack('c', $hex); + $high_part /= 0x100; + } + return $res; + } + + /** + * Returns a timestamp from an OLE container's date + * + * @access public + * @static + * @param integer $string A binary string with the encoded date + * @return string The timestamp corresponding to the string + */ + public static function OLE2LocalDate($string) + { + if (strlen($string) != 8) { + return new PEAR_Error("Expecting 8 byte string"); + } + + // factor used for separating numbers into 4 bytes parts + $factor = pow(2,32); + list(, $high_part) = unpack('V', substr($string, 4, 4)); + list(, $low_part) = unpack('V', substr($string, 0, 4)); + + $big_date = ($high_part * $factor) + $low_part; + // translate to seconds + $big_date /= 10000000; + + // days from 1-1-1601 until the beggining of UNIX era + $days = 134774; + + // translate to seconds from beggining of UNIX era + $big_date -= $days * 24 * 3600; + return floor($big_date); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/ChainedBlockStream.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/ChainedBlockStream.php new file mode 100755 index 0000000..5fe1edc --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/ChainedBlockStream.php @@ -0,0 +1,229 @@ +<?php +/** + * PHPExcel + * + * Copyright (C) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_OLE + * @copyright Copyright (c) 2006 - 2007 Christian Schmidt + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +/** + * PHPExcel_Shared_OLE_ChainedBlockStream + * + * Stream wrapper for reading data stored in an OLE file. Implements methods + * for PHP's stream_wrapper_register(). For creating streams using this + * wrapper, use PHPExcel_Shared_OLE_PPS_File::getStream(). + * + * @category PHPExcel + * @package PHPExcel_Shared_OLE + */ +class PHPExcel_Shared_OLE_ChainedBlockStream +{ + /** + * The OLE container of the file that is being read. + * @var OLE + */ + public $ole; + + /** + * Parameters specified by fopen(). + * @var array + */ + public $params; + + /** + * The binary data of the file. + * @var string + */ + public $data; + + /** + * The file pointer. + * @var int byte offset + */ + public $pos; + + /** + * Implements support for fopen(). + * For creating streams using this wrapper, use OLE_PPS_File::getStream(). + * + * @param string $path resource name including scheme, e.g. + * ole-chainedblockstream://oleInstanceId=1 + * @param string $mode only "r" is supported + * @param int $options mask of STREAM_REPORT_ERRORS and STREAM_USE_PATH + * @param string &$openedPath absolute path of the opened stream (out parameter) + * @return bool true on success + */ + public function stream_open($path, $mode, $options, &$openedPath) + { + if ($mode != 'r') { + if ($options & STREAM_REPORT_ERRORS) { + trigger_error('Only reading is supported', E_USER_WARNING); + } + return false; + } + + // 25 is length of "ole-chainedblockstream://" + parse_str(substr($path, 25), $this->params); + if (!isset($this->params['oleInstanceId'], + $this->params['blockId'], + $GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']])) { + + if ($options & STREAM_REPORT_ERRORS) { + trigger_error('OLE stream not found', E_USER_WARNING); + } + return false; + } + $this->ole = $GLOBALS['_OLE_INSTANCES'][$this->params['oleInstanceId']]; + + $blockId = $this->params['blockId']; + $this->data = ''; + if (isset($this->params['size']) && + $this->params['size'] < $this->ole->bigBlockThreshold && + $blockId != $this->ole->root->_StartBlock) { + + // Block id refers to small blocks + $rootPos = $this->ole->_getBlockOffset($this->ole->root->_StartBlock); + while ($blockId != -2) { + $pos = $rootPos + $blockId * $this->ole->bigBlockSize; + $blockId = $this->ole->sbat[$blockId]; + fseek($this->ole->_file_handle, $pos); + $this->data .= fread($this->ole->_file_handle, $this->ole->bigBlockSize); + } + } else { + // Block id refers to big blocks + while ($blockId != -2) { + $pos = $this->ole->_getBlockOffset($blockId); + fseek($this->ole->_file_handle, $pos); + $this->data .= fread($this->ole->_file_handle, $this->ole->bigBlockSize); + $blockId = $this->ole->bbat[$blockId]; + } + } + if (isset($this->params['size'])) { + $this->data = substr($this->data, 0, $this->params['size']); + } + + if ($options & STREAM_USE_PATH) { + $openedPath = $path; + } + + return true; + } + + /** + * Implements support for fclose(). + * + */ + public function stream_close() + { + $this->ole = null; + unset($GLOBALS['_OLE_INSTANCES']); + } + + /** + * Implements support for fread(), fgets() etc. + * + * @param int $count maximum number of bytes to read + * @return string + */ + public function stream_read($count) + { + if ($this->stream_eof()) { + return false; + } + $s = substr($this->data, $this->pos, $count); + $this->pos += $count; + return $s; + } + + /** + * Implements support for feof(). + * + * @return bool TRUE if the file pointer is at EOF; otherwise FALSE + */ + public function stream_eof() + { + $eof = $this->pos >= strlen($this->data); + // Workaround for bug in PHP 5.0.x: http://bugs.php.net/27508 + if (version_compare(PHP_VERSION, '5.0', '>=') && + version_compare(PHP_VERSION, '5.1', '<')) { + + $eof = !$eof; + } + return $eof; + } + + /** + * Returns the position of the file pointer, i.e. its offset into the file + * stream. Implements support for ftell(). + * + * @return int + */ + public function stream_tell() + { + return $this->pos; + } + + /** + * Implements support for fseek(). + * + * @param int $offset byte offset + * @param int $whence SEEK_SET, SEEK_CUR or SEEK_END + * @return bool + */ + public function stream_seek($offset, $whence) + { + if ($whence == SEEK_SET && $offset >= 0) { + $this->pos = $offset; + } elseif ($whence == SEEK_CUR && -$offset <= $this->pos) { + $this->pos += $offset; + } elseif ($whence == SEEK_END && -$offset <= sizeof($this->data)) { + $this->pos = strlen($this->data) + $offset; + } else { + return false; + } + return true; + } + + /** + * Implements support for fstat(). Currently the only supported field is + * "size". + * @return array + */ + public function stream_stat() + { + return array( + 'size' => strlen($this->data), + ); + } + + // Methods used by stream_wrapper_register() that are not implemented: + // bool stream_flush ( void ) + // int stream_write ( string data ) + // bool rename ( string path_from, string path_to ) + // bool mkdir ( string path, int mode, int options ) + // bool rmdir ( string path, int options ) + // bool dir_opendir ( string path, int options ) + // array url_stat ( string path, int flags ) + // string dir_readdir ( void ) + // bool dir_rewinddir ( void ) + // bool dir_closedir ( void ) +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS.php new file mode 100755 index 0000000..4db0ae4 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS.php @@ -0,0 +1,230 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------+ +// | PHP Version 4 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2002 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 2.02 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available at through the world-wide-web at | +// | http://www.php.net/license/2_02.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Xavier Noguer <xnoguer@php.net> | +// | Based on OLE::Storage_Lite by Kawai, Takanori | +// +----------------------------------------------------------------------+ +// +// $Id: PPS.php,v 1.7 2007/02/13 21:00:42 schmidt Exp $ + + +/** +* Class for creating PPS's for OLE containers +* +* @author Xavier Noguer <xnoguer@php.net> +* @category PHPExcel +* @package PHPExcel_Shared_OLE +*/ +class PHPExcel_Shared_OLE_PPS +{ + /** + * The PPS index + * @var integer + */ + public $No; + + /** + * The PPS name (in Unicode) + * @var string + */ + public $Name; + + /** + * The PPS type. Dir, Root or File + * @var integer + */ + public $Type; + + /** + * The index of the previous PPS + * @var integer + */ + public $PrevPps; + + /** + * The index of the next PPS + * @var integer + */ + public $NextPps; + + /** + * The index of it's first child if this is a Dir or Root PPS + * @var integer + */ + public $DirPps; + + /** + * A timestamp + * @var integer + */ + public $Time1st; + + /** + * A timestamp + * @var integer + */ + public $Time2nd; + + /** + * Starting block (small or big) for this PPS's data inside the container + * @var integer + */ + public $_StartBlock; + + /** + * The size of the PPS's data (in bytes) + * @var integer + */ + public $Size; + + /** + * The PPS's data (only used if it's not using a temporary file) + * @var string + */ + public $_data; + + /** + * Array of child PPS's (only used by Root and Dir PPS's) + * @var array + */ + public $children = array(); + + /** + * Pointer to OLE container + * @var OLE + */ + public $ole; + + /** + * The constructor + * + * @access public + * @param integer $No The PPS index + * @param string $name The PPS name + * @param integer $type The PPS type. Dir, Root or File + * @param integer $prev The index of the previous PPS + * @param integer $next The index of the next PPS + * @param integer $dir The index of it's first child if this is a Dir or Root PPS + * @param integer $time_1st A timestamp + * @param integer $time_2nd A timestamp + * @param string $data The (usually binary) source data of the PPS + * @param array $children Array containing children PPS for this PPS + */ + public function __construct($No, $name, $type, $prev, $next, $dir, $time_1st, $time_2nd, $data, $children) + { + $this->No = $No; + $this->Name = $name; + $this->Type = $type; + $this->PrevPps = $prev; + $this->NextPps = $next; + $this->DirPps = $dir; + $this->Time1st = $time_1st; + $this->Time2nd = $time_2nd; + $this->_data = $data; + $this->children = $children; + if ($data != '') { + $this->Size = strlen($data); + } else { + $this->Size = 0; + } + } + + /** + * Returns the amount of data saved for this PPS + * + * @access public + * @return integer The amount of data (in bytes) + */ + public function _DataLen() + { + if (!isset($this->_data)) { + return 0; + } + //if (isset($this->_PPS_FILE)) { + // fseek($this->_PPS_FILE, 0); + // $stats = fstat($this->_PPS_FILE); + // return $stats[7]; + //} else { + return strlen($this->_data); + //} + } + + /** + * Returns a string with the PPS's WK (What is a WK?) + * + * @access public + * @return string The binary string + */ + public function _getPpsWk() + { + $ret = str_pad($this->Name,64,"\x00"); + + $ret .= pack("v", strlen($this->Name) + 2) // 66 + . pack("c", $this->Type) // 67 + . pack("c", 0x00) //UK // 68 + . pack("V", $this->PrevPps) //Prev // 72 + . pack("V", $this->NextPps) //Next // 76 + . pack("V", $this->DirPps) //Dir // 80 + . "\x00\x09\x02\x00" // 84 + . "\x00\x00\x00\x00" // 88 + . "\xc0\x00\x00\x00" // 92 + . "\x00\x00\x00\x46" // 96 // Seems to be ok only for Root + . "\x00\x00\x00\x00" // 100 + . PHPExcel_Shared_OLE::LocalDate2OLE($this->Time1st) // 108 + . PHPExcel_Shared_OLE::LocalDate2OLE($this->Time2nd) // 116 + . pack("V", isset($this->_StartBlock)? + $this->_StartBlock:0) // 120 + . pack("V", $this->Size) // 124 + . pack("V", 0); // 128 + return $ret; + } + + /** + * Updates index and pointers to previous, next and children PPS's for this + * PPS. I don't think it'll work with Dir PPS's. + * + * @access public + * @param array &$raList Reference to the array of PPS's for the whole OLE + * container + * @return integer The index for this PPS + */ + public static function _savePpsSetPnt(&$raList, $to_save, $depth = 0) + { + if ( !is_array($to_save) || (empty($to_save)) ) { + return 0xFFFFFFFF; + } elseif( count($to_save) == 1 ) { + $cnt = count($raList); + // If the first entry, it's the root... Don't clone it! + $raList[$cnt] = ( $depth == 0 ) ? $to_save[0] : clone $to_save[0]; + $raList[$cnt]->No = $cnt; + $raList[$cnt]->PrevPps = 0xFFFFFFFF; + $raList[$cnt]->NextPps = 0xFFFFFFFF; + $raList[$cnt]->DirPps = self::_savePpsSetPnt($raList, @$raList[$cnt]->children, $depth++); + } else { + $iPos = floor(count($to_save) / 2); + $aPrev = array_slice($to_save, 0, $iPos); + $aNext = array_slice($to_save, $iPos + 1); + $cnt = count($raList); + // If the first entry, it's the root... Don't clone it! + $raList[$cnt] = ( $depth == 0 ) ? $to_save[$iPos] : clone $to_save[$iPos]; + $raList[$cnt]->No = $cnt; + $raList[$cnt]->PrevPps = self::_savePpsSetPnt($raList, $aPrev, $depth++); + $raList[$cnt]->NextPps = self::_savePpsSetPnt($raList, $aNext, $depth++); + $raList[$cnt]->DirPps = self::_savePpsSetPnt($raList, @$raList[$cnt]->children, $depth++); + + } + return $cnt; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS/File.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS/File.php new file mode 100755 index 0000000..f061f56 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS/File.php @@ -0,0 +1,84 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------+ +// | PHP Version 4 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2002 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 2.02 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available at through the world-wide-web at | +// | http://www.php.net/license/2_02.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Xavier Noguer <xnoguer@php.net> | +// | Based on OLE::Storage_Lite by Kawai, Takanori | +// +----------------------------------------------------------------------+ +// +// $Id: File.php,v 1.11 2007/02/13 21:00:42 schmidt Exp $ + + +/** +* Class for creating File PPS's for OLE containers +* +* @author Xavier Noguer <xnoguer@php.net> +* @category PHPExcel +* @package PHPExcel_Shared_OLE +*/ +class PHPExcel_Shared_OLE_PPS_File extends PHPExcel_Shared_OLE_PPS + { + /** + * The constructor + * + * @access public + * @param string $name The name of the file (in Unicode) + * @see OLE::Asc2Ucs() + */ + public function __construct($name) + { + parent::__construct( + null, + $name, + PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE, + null, + null, + null, + null, + null, + '', + array()); + } + + /** + * Initialization method. Has to be called right after OLE_PPS_File(). + * + * @access public + * @return mixed true on success + */ + public function init() + { + return true; + } + + /** + * Append data to PPS + * + * @access public + * @param string $data The data to append + */ + public function append($data) + { + $this->_data .= $data; + } + + /** + * Returns a stream for reading this file using fread() etc. + * @return resource a read-only stream + */ + public function getStream() + { + $this->ole->getStream($this); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS/Root.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS/Root.php new file mode 100755 index 0000000..eb929d2 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLE/PPS/Root.php @@ -0,0 +1,467 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------+ +// | PHP Version 4 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2002 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 2.02 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available at through the world-wide-web at | +// | http://www.php.net/license/2_02.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Xavier Noguer <xnoguer@php.net> | +// | Based on OLE::Storage_Lite by Kawai, Takanori | +// +----------------------------------------------------------------------+ +// +// $Id: Root.php,v 1.9 2005/04/23 21:53:49 dufuz Exp $ + + +/** +* Class for creating Root PPS's for OLE containers +* +* @author Xavier Noguer <xnoguer@php.net> +* @category PHPExcel +* @package PHPExcel_Shared_OLE +*/ +class PHPExcel_Shared_OLE_PPS_Root extends PHPExcel_Shared_OLE_PPS + { + + /** + * Directory for temporary files + * @var string + */ + protected $_tmp_dir = NULL; + + /** + * @param integer $time_1st A timestamp + * @param integer $time_2nd A timestamp + */ + public function __construct($time_1st, $time_2nd, $raChild) + { + $this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); + + parent::__construct( + null, + PHPExcel_Shared_OLE::Asc2Ucs('Root Entry'), + PHPExcel_Shared_OLE::OLE_PPS_TYPE_ROOT, + null, + null, + null, + $time_1st, + $time_2nd, + null, + $raChild); + } + + /** + * Method for saving the whole OLE container (including files). + * In fact, if called with an empty argument (or '-'), it saves to a + * temporary file and then outputs it's contents to stdout. + * If a resource pointer to a stream created by fopen() is passed + * it will be used, but you have to close such stream by yourself. + * + * @param string|resource $filename The name of the file or stream where to save the OLE container. + * @access public + * @return mixed true on success + */ + public function save($filename) + { + // Initial Setting for saving + $this->_BIG_BLOCK_SIZE = pow(2, + ((isset($this->_BIG_BLOCK_SIZE))? self::_adjust2($this->_BIG_BLOCK_SIZE) : 9)); + $this->_SMALL_BLOCK_SIZE= pow(2, + ((isset($this->_SMALL_BLOCK_SIZE))? self::_adjust2($this->_SMALL_BLOCK_SIZE): 6)); + + if (is_resource($filename)) { + $this->_FILEH_ = $filename; + } else if ($filename == '-' || $filename == '') { + if ($this->_tmp_dir === NULL) + $this->_tmp_dir = PHPExcel_Shared_File::sys_get_temp_dir(); + $this->_tmp_filename = tempnam($this->_tmp_dir, "OLE_PPS_Root"); + $this->_FILEH_ = fopen($this->_tmp_filename,"w+b"); + if ($this->_FILEH_ == false) { + throw new PHPExcel_Writer_Exception("Can't create temporary file."); + } + } else { + $this->_FILEH_ = fopen($filename, "wb"); + } + if ($this->_FILEH_ == false) { + throw new PHPExcel_Writer_Exception("Can't open $filename. It may be in use or protected."); + } + // Make an array of PPS's (for Save) + $aList = array(); + PHPExcel_Shared_OLE_PPS::_savePpsSetPnt($aList, array($this)); + // calculate values for header + list($iSBDcnt, $iBBcnt, $iPPScnt) = $this->_calcSize($aList); //, $rhInfo); + // Save Header + $this->_saveHeader($iSBDcnt, $iBBcnt, $iPPScnt); + + // Make Small Data string (write SBD) + $this->_data = $this->_makeSmallData($aList); + + // Write BB + $this->_saveBigData($iSBDcnt, $aList); + // Write PPS + $this->_savePps($aList); + // Write Big Block Depot and BDList and Adding Header informations + $this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt); + + if (!is_resource($filename)) { + fclose($this->_FILEH_); + } + + return true; + } + + /** + * Calculate some numbers + * + * @access public + * @param array $raList Reference to an array of PPS's + * @return array The array of numbers + */ + public function _calcSize(&$raList) + { + // Calculate Basic Setting + list($iSBDcnt, $iBBcnt, $iPPScnt) = array(0,0,0); + $iSmallLen = 0; + $iSBcnt = 0; + $iCount = count($raList); + for ($i = 0; $i < $iCount; ++$i) { + if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) { + $raList[$i]->Size = $raList[$i]->_DataLen(); + if ($raList[$i]->Size < PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) { + $iSBcnt += floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE) + + (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0); + } else { + $iBBcnt += (floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) + + (($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0)); + } + } + } + $iSmallLen = $iSBcnt * $this->_SMALL_BLOCK_SIZE; + $iSlCnt = floor($this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE); + $iSBDcnt = floor($iSBcnt / $iSlCnt) + (($iSBcnt % $iSlCnt)? 1:0); + $iBBcnt += (floor($iSmallLen / $this->_BIG_BLOCK_SIZE) + + (( $iSmallLen % $this->_BIG_BLOCK_SIZE)? 1: 0)); + $iCnt = count($raList); + $iBdCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_PPS_SIZE; + $iPPScnt = (floor($iCnt/$iBdCnt) + (($iCnt % $iBdCnt)? 1: 0)); + + return array($iSBDcnt, $iBBcnt, $iPPScnt); + } + + /** + * Helper function for caculating a magic value for block sizes + * + * @access public + * @param integer $i2 The argument + * @see save() + * @return integer + */ + private static function _adjust2($i2) + { + $iWk = log($i2)/log(2); + return ($iWk > floor($iWk))? floor($iWk)+1:$iWk; + } + + /** + * Save OLE header + * + * @access public + * @param integer $iSBDcnt + * @param integer $iBBcnt + * @param integer $iPPScnt + */ + public function _saveHeader($iSBDcnt, $iBBcnt, $iPPScnt) + { + $FILE = $this->_FILEH_; + + // Calculate Basic Setting + $iBlCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; + $i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; + + $iBdExL = 0; + $iAll = $iBBcnt + $iPPScnt + $iSBDcnt; + $iAllW = $iAll; + $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0); + $iBdCnt = floor(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0); + + // Calculate BD count + if ($iBdCnt > $i1stBdL) { + while (1) { + ++$iBdExL; + ++$iAllW; + $iBdCntW = floor($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0); + $iBdCnt = floor(($iAllW + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0); + if ($iBdCnt <= ($iBdExL*$iBlCnt+ $i1stBdL)) { + break; + } + } + } + + // Save Header + fwrite($FILE, + "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" + . "\x00\x00\x00\x00" + . "\x00\x00\x00\x00" + . "\x00\x00\x00\x00" + . "\x00\x00\x00\x00" + . pack("v", 0x3b) + . pack("v", 0x03) + . pack("v", -2) + . pack("v", 9) + . pack("v", 6) + . pack("v", 0) + . "\x00\x00\x00\x00" + . "\x00\x00\x00\x00" + . pack("V", $iBdCnt) + . pack("V", $iBBcnt+$iSBDcnt) //ROOT START + . pack("V", 0) + . pack("V", 0x1000) + . pack("V", $iSBDcnt ? 0 : -2) //Small Block Depot + . pack("V", $iSBDcnt) + ); + // Extra BDList Start, Count + if ($iBdCnt < $i1stBdL) { + fwrite($FILE, + pack("V", -2) // Extra BDList Start + . pack("V", 0) // Extra BDList Count + ); + } else { + fwrite($FILE, pack("V", $iAll+$iBdCnt) . pack("V", $iBdExL)); + } + + // BDList + for ($i = 0; $i < $i1stBdL && $i < $iBdCnt; ++$i) { + fwrite($FILE, pack("V", $iAll+$i)); + } + if ($i < $i1stBdL) { + $jB = $i1stBdL - $i; + for ($j = 0; $j < $jB; ++$j) { + fwrite($FILE, (pack("V", -1))); + } + } + } + + /** + * Saving big data (PPS's with data bigger than PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) + * + * @access public + * @param integer $iStBlk + * @param array &$raList Reference to array of PPS's + */ + public function _saveBigData($iStBlk, &$raList) + { + $FILE = $this->_FILEH_; + + // cycle through PPS's + $iCount = count($raList); + for ($i = 0; $i < $iCount; ++$i) { + if ($raList[$i]->Type != PHPExcel_Shared_OLE::OLE_PPS_TYPE_DIR) { + $raList[$i]->Size = $raList[$i]->_DataLen(); + if (($raList[$i]->Size >= PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) || + (($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_ROOT) && isset($raList[$i]->_data))) + { + // Write Data + //if (isset($raList[$i]->_PPS_FILE)) { + // $iLen = 0; + // fseek($raList[$i]->_PPS_FILE, 0); // To The Top + // while($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) { + // $iLen += strlen($sBuff); + // fwrite($FILE, $sBuff); + // } + //} else { + fwrite($FILE, $raList[$i]->_data); + //} + + if ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE) { + fwrite($FILE, str_repeat("\x00", $this->_BIG_BLOCK_SIZE - ($raList[$i]->Size % $this->_BIG_BLOCK_SIZE))); + } + // Set For PPS + $raList[$i]->_StartBlock = $iStBlk; + $iStBlk += + (floor($raList[$i]->Size / $this->_BIG_BLOCK_SIZE) + + (($raList[$i]->Size % $this->_BIG_BLOCK_SIZE)? 1: 0)); + } + // Close file for each PPS, and unlink it + //if (isset($raList[$i]->_PPS_FILE)) { + // fclose($raList[$i]->_PPS_FILE); + // $raList[$i]->_PPS_FILE = null; + // unlink($raList[$i]->_tmp_filename); + //} + } + } + } + + /** + * get small data (PPS's with data smaller than PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) + * + * @access public + * @param array &$raList Reference to array of PPS's + */ + public function _makeSmallData(&$raList) + { + $sRes = ''; + $FILE = $this->_FILEH_; + $iSmBlk = 0; + + $iCount = count($raList); + for ($i = 0; $i < $iCount; ++$i) { + // Make SBD, small data string + if ($raList[$i]->Type == PHPExcel_Shared_OLE::OLE_PPS_TYPE_FILE) { + if ($raList[$i]->Size <= 0) { + continue; + } + if ($raList[$i]->Size < PHPExcel_Shared_OLE::OLE_DATA_SIZE_SMALL) { + $iSmbCnt = floor($raList[$i]->Size / $this->_SMALL_BLOCK_SIZE) + + (($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)? 1: 0); + // Add to SBD + $jB = $iSmbCnt - 1; + for ($j = 0; $j < $jB; ++$j) { + fwrite($FILE, pack("V", $j+$iSmBlk+1)); + } + fwrite($FILE, pack("V", -2)); + + //// Add to Data String(this will be written for RootEntry) + //if ($raList[$i]->_PPS_FILE) { + // fseek($raList[$i]->_PPS_FILE, 0); // To The Top + // while ($sBuff = fread($raList[$i]->_PPS_FILE, 4096)) { + // $sRes .= $sBuff; + // } + //} else { + $sRes .= $raList[$i]->_data; + //} + if ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE) { + $sRes .= str_repeat("\x00",$this->_SMALL_BLOCK_SIZE - ($raList[$i]->Size % $this->_SMALL_BLOCK_SIZE)); + } + // Set for PPS + $raList[$i]->_StartBlock = $iSmBlk; + $iSmBlk += $iSmbCnt; + } + } + } + $iSbCnt = floor($this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE); + if ($iSmBlk % $iSbCnt) { + $iB = $iSbCnt - ($iSmBlk % $iSbCnt); + for ($i = 0; $i < $iB; ++$i) { + fwrite($FILE, pack("V", -1)); + } + } + return $sRes; + } + + /** + * Saves all the PPS's WKs + * + * @access public + * @param array $raList Reference to an array with all PPS's + */ + public function _savePps(&$raList) + { + // Save each PPS WK + $iC = count($raList); + for ($i = 0; $i < $iC; ++$i) { + fwrite($this->_FILEH_, $raList[$i]->_getPpsWk()); + } + // Adjust for Block + $iCnt = count($raList); + $iBCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_PPS_SIZE; + if ($iCnt % $iBCnt) { + fwrite($this->_FILEH_, str_repeat("\x00",($iBCnt - ($iCnt % $iBCnt)) * PHPExcel_Shared_OLE::OLE_PPS_SIZE)); + } + } + + /** + * Saving Big Block Depot + * + * @access public + * @param integer $iSbdSize + * @param integer $iBsize + * @param integer $iPpsCnt + */ + public function _saveBbd($iSbdSize, $iBsize, $iPpsCnt) + { + $FILE = $this->_FILEH_; + // Calculate Basic Setting + $iBbCnt = $this->_BIG_BLOCK_SIZE / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; + $i1stBdL = ($this->_BIG_BLOCK_SIZE - 0x4C) / PHPExcel_Shared_OLE::OLE_LONG_INT_SIZE; + + $iBdExL = 0; + $iAll = $iBsize + $iPpsCnt + $iSbdSize; + $iAllW = $iAll; + $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0); + $iBdCnt = floor(($iAll + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0); + // Calculate BD count + if ($iBdCnt >$i1stBdL) { + while (1) { + ++$iBdExL; + ++$iAllW; + $iBdCntW = floor($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0); + $iBdCnt = floor(($iAllW + $iBdCntW) / $iBbCnt) + ((($iAllW+$iBdCntW) % $iBbCnt)? 1: 0); + if ($iBdCnt <= ($iBdExL*$iBbCnt+ $i1stBdL)) { + break; + } + } + } + + // Making BD + // Set for SBD + if ($iSbdSize > 0) { + for ($i = 0; $i < ($iSbdSize - 1); ++$i) { + fwrite($FILE, pack("V", $i+1)); + } + fwrite($FILE, pack("V", -2)); + } + // Set for B + for ($i = 0; $i < ($iBsize - 1); ++$i) { + fwrite($FILE, pack("V", $i+$iSbdSize+1)); + } + fwrite($FILE, pack("V", -2)); + + // Set for PPS + for ($i = 0; $i < ($iPpsCnt - 1); ++$i) { + fwrite($FILE, pack("V", $i+$iSbdSize+$iBsize+1)); + } + fwrite($FILE, pack("V", -2)); + // Set for BBD itself ( 0xFFFFFFFD : BBD) + for ($i = 0; $i < $iBdCnt; ++$i) { + fwrite($FILE, pack("V", 0xFFFFFFFD)); + } + // Set for ExtraBDList + for ($i = 0; $i < $iBdExL; ++$i) { + fwrite($FILE, pack("V", 0xFFFFFFFC)); + } + // Adjust for Block + if (($iAllW + $iBdCnt) % $iBbCnt) { + $iBlock = ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt)); + for ($i = 0; $i < $iBlock; ++$i) { + fwrite($FILE, pack("V", -1)); + } + } + // Extra BDList + if ($iBdCnt > $i1stBdL) { + $iN=0; + $iNb=0; + for ($i = $i1stBdL;$i < $iBdCnt; $i++, ++$iN) { + if ($iN >= ($iBbCnt - 1)) { + $iN = 0; + ++$iNb; + fwrite($FILE, pack("V", $iAll+$iBdCnt+$iNb)); + } + fwrite($FILE, pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i)); + } + if (($iBdCnt-$i1stBdL) % ($iBbCnt-1)) { + $iB = ($iBbCnt - 1) - (($iBdCnt - $i1stBdL) % ($iBbCnt - 1)); + for ($i = 0; $i < $iB; ++$i) { + fwrite($FILE, pack("V", -1)); + } + } + fwrite($FILE, pack("V", -2)); + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLERead.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLERead.php new file mode 100755 index 0000000..4ad45c0 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/OLERead.php @@ -0,0 +1,317 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +defined('IDENTIFIER_OLE') || + define('IDENTIFIER_OLE', pack('CCCCCCCC', 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1)); + +class PHPExcel_Shared_OLERead { + private $data = ''; + + // OLE identifier + const IDENTIFIER_OLE = IDENTIFIER_OLE; + + // Size of a sector = 512 bytes + const BIG_BLOCK_SIZE = 0x200; + + // Size of a short sector = 64 bytes + const SMALL_BLOCK_SIZE = 0x40; + + // Size of a directory entry always = 128 bytes + const PROPERTY_STORAGE_BLOCK_SIZE = 0x80; + + // Minimum size of a standard stream = 4096 bytes, streams smaller than this are stored as short streams + const SMALL_BLOCK_THRESHOLD = 0x1000; + + // header offsets + const NUM_BIG_BLOCK_DEPOT_BLOCKS_POS = 0x2c; + const ROOT_START_BLOCK_POS = 0x30; + const SMALL_BLOCK_DEPOT_BLOCK_POS = 0x3c; + const EXTENSION_BLOCK_POS = 0x44; + const NUM_EXTENSION_BLOCK_POS = 0x48; + const BIG_BLOCK_DEPOT_BLOCKS_POS = 0x4c; + + // property storage offsets (directory offsets) + const SIZE_OF_NAME_POS = 0x40; + const TYPE_POS = 0x42; + const START_BLOCK_POS = 0x74; + const SIZE_POS = 0x78; + + + + public $wrkbook = null; + public $summaryInformation = null; + public $documentSummaryInformation = null; + + + /** + * Read the file + * + * @param $sFileName string Filename + * @throws PHPExcel_Reader_Exception + */ + public function read($sFileName) + { + // Check if file exists and is readable + if(!is_readable($sFileName)) { + throw new PHPExcel_Reader_Exception("Could not open " . $sFileName . " for reading! File does not exist, or it is not readable."); + } + + // Get the file identifier + // Don't bother reading the whole file until we know it's a valid OLE file + $this->data = file_get_contents($sFileName, FALSE, NULL, 0, 8); + + // Check OLE identifier + if ($this->data != self::IDENTIFIER_OLE) { + throw new PHPExcel_Reader_Exception('The filename ' . $sFileName . ' is not recognised as an OLE file'); + } + + // Get the file data + $this->data = file_get_contents($sFileName); + + // Total number of sectors used for the SAT + $this->numBigBlockDepotBlocks = self::_GetInt4d($this->data, self::NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); + + // SecID of the first sector of the directory stream + $this->rootStartBlock = self::_GetInt4d($this->data, self::ROOT_START_BLOCK_POS); + + // SecID of the first sector of the SSAT (or -2 if not extant) + $this->sbdStartBlock = self::_GetInt4d($this->data, self::SMALL_BLOCK_DEPOT_BLOCK_POS); + + // SecID of the first sector of the MSAT (or -2 if no additional sectors are used) + $this->extensionBlock = self::_GetInt4d($this->data, self::EXTENSION_BLOCK_POS); + + // Total number of sectors used by MSAT + $this->numExtensionBlocks = self::_GetInt4d($this->data, self::NUM_EXTENSION_BLOCK_POS); + + $bigBlockDepotBlocks = array(); + $pos = self::BIG_BLOCK_DEPOT_BLOCKS_POS; + + $bbdBlocks = $this->numBigBlockDepotBlocks; + + if ($this->numExtensionBlocks != 0) { + $bbdBlocks = (self::BIG_BLOCK_SIZE - self::BIG_BLOCK_DEPOT_BLOCKS_POS)/4; + } + + for ($i = 0; $i < $bbdBlocks; ++$i) { + $bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data, $pos); + $pos += 4; + } + + for ($j = 0; $j < $this->numExtensionBlocks; ++$j) { + $pos = ($this->extensionBlock + 1) * self::BIG_BLOCK_SIZE; + $blocksToRead = min($this->numBigBlockDepotBlocks - $bbdBlocks, self::BIG_BLOCK_SIZE / 4 - 1); + + for ($i = $bbdBlocks; $i < $bbdBlocks + $blocksToRead; ++$i) { + $bigBlockDepotBlocks[$i] = self::_GetInt4d($this->data, $pos); + $pos += 4; + } + + $bbdBlocks += $blocksToRead; + if ($bbdBlocks < $this->numBigBlockDepotBlocks) { + $this->extensionBlock = self::_GetInt4d($this->data, $pos); + } + } + + $pos = 0; + $this->bigBlockChain = ''; + $bbs = self::BIG_BLOCK_SIZE / 4; + for ($i = 0; $i < $this->numBigBlockDepotBlocks; ++$i) { + $pos = ($bigBlockDepotBlocks[$i] + 1) * self::BIG_BLOCK_SIZE; + + $this->bigBlockChain .= substr($this->data, $pos, 4*$bbs); + $pos += 4*$bbs; + } + + $pos = 0; + $sbdBlock = $this->sbdStartBlock; + $this->smallBlockChain = ''; + while ($sbdBlock != -2) { + $pos = ($sbdBlock + 1) * self::BIG_BLOCK_SIZE; + + $this->smallBlockChain .= substr($this->data, $pos, 4*$bbs); + $pos += 4*$bbs; + + $sbdBlock = self::_GetInt4d($this->bigBlockChain, $sbdBlock*4); + } + + // read the directory stream + $block = $this->rootStartBlock; + $this->entry = $this->_readData($block); + + $this->_readPropertySets(); + } + + /** + * Extract binary stream data + * + * @return string + */ + public function getStream($stream) + { + if ($stream === NULL) { + return null; + } + + $streamData = ''; + + if ($this->props[$stream]['size'] < self::SMALL_BLOCK_THRESHOLD) { + $rootdata = $this->_readData($this->props[$this->rootentry]['startBlock']); + + $block = $this->props[$stream]['startBlock']; + + while ($block != -2) { + $pos = $block * self::SMALL_BLOCK_SIZE; + $streamData .= substr($rootdata, $pos, self::SMALL_BLOCK_SIZE); + + $block = self::_GetInt4d($this->smallBlockChain, $block*4); + } + + return $streamData; + } else { + $numBlocks = $this->props[$stream]['size'] / self::BIG_BLOCK_SIZE; + if ($this->props[$stream]['size'] % self::BIG_BLOCK_SIZE != 0) { + ++$numBlocks; + } + + if ($numBlocks == 0) return ''; + + $block = $this->props[$stream]['startBlock']; + + while ($block != -2) { + $pos = ($block + 1) * self::BIG_BLOCK_SIZE; + $streamData .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); + $block = self::_GetInt4d($this->bigBlockChain, $block*4); + } + + return $streamData; + } + } + + /** + * Read a standard stream (by joining sectors using information from SAT) + * + * @param int $bl Sector ID where the stream starts + * @return string Data for standard stream + */ + private function _readData($bl) + { + $block = $bl; + $data = ''; + + while ($block != -2) { + $pos = ($block + 1) * self::BIG_BLOCK_SIZE; + $data .= substr($this->data, $pos, self::BIG_BLOCK_SIZE); + $block = self::_GetInt4d($this->bigBlockChain, $block*4); + } + return $data; + } + + /** + * Read entries in the directory stream. + */ + private function _readPropertySets() { + $offset = 0; + + // loop through entires, each entry is 128 bytes + $entryLen = strlen($this->entry); + while ($offset < $entryLen) { + // entry data (128 bytes) + $d = substr($this->entry, $offset, self::PROPERTY_STORAGE_BLOCK_SIZE); + + // size in bytes of name + $nameSize = ord($d[self::SIZE_OF_NAME_POS]) | (ord($d[self::SIZE_OF_NAME_POS+1]) << 8); + + // type of entry + $type = ord($d[self::TYPE_POS]); + + // sectorID of first sector or short sector, if this entry refers to a stream (the case with workbook) + // sectorID of first sector of the short-stream container stream, if this entry is root entry + $startBlock = self::_GetInt4d($d, self::START_BLOCK_POS); + + $size = self::_GetInt4d($d, self::SIZE_POS); + + $name = str_replace("\x00", "", substr($d,0,$nameSize)); + + + $this->props[] = array ( + 'name' => $name, + 'type' => $type, + 'startBlock' => $startBlock, + 'size' => $size); + + // tmp helper to simplify checks + $upName = strtoupper($name); + + // Workbook directory entry (BIFF5 uses Book, BIFF8 uses Workbook) + if (($upName === 'WORKBOOK') || ($upName === 'BOOK')) { + $this->wrkbook = count($this->props) - 1; + } + else if ( $upName === 'ROOT ENTRY' || $upName === 'R') { + // Root entry + $this->rootentry = count($this->props) - 1; + } + + // Summary information + if ($name == chr(5) . 'SummaryInformation') { +// echo 'Summary Information<br />'; + $this->summaryInformation = count($this->props) - 1; + } + + // Additional Document Summary information + if ($name == chr(5) . 'DocumentSummaryInformation') { +// echo 'Document Summary Information<br />'; + $this->documentSummaryInformation = count($this->props) - 1; + } + + $offset += self::PROPERTY_STORAGE_BLOCK_SIZE; + } + + } + + /** + * Read 4 bytes of data at specified position + * + * @param string $data + * @param int $pos + * @return int + */ + private static function _GetInt4d($data, $pos) + { + // FIX: represent numbers correctly on 64-bit system + // http://sourceforge.net/tracker/index.php?func=detail&aid=1487372&group_id=99160&atid=623334 + // Hacked by Andreas Rehm 2006 to ensure correct result of the <<24 block on 32 and 64bit systems + $_or_24 = ord($data[$pos + 3]); + if ($_or_24 >= 128) { + // negative number + $_ord_24 = -abs((256 - $_or_24) << 24); + } else { + $_ord_24 = ($_or_24 & 127) << 24; + } + return ord($data[$pos]) | (ord($data[$pos + 1]) << 8) | (ord($data[$pos + 2]) << 16) | $_ord_24; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/gnu-lgpl.txt b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/gnu-lgpl.txt new file mode 100755 index 0000000..cbee875 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/gnu-lgpl.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/pclzip.lib.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/pclzip.lib.php new file mode 100755 index 0000000..4bf05a5 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/pclzip.lib.php @@ -0,0 +1,5694 @@ +<?php +// -------------------------------------------------------------------------------- +// PhpConcept Library - Zip Module 2.8.2 +// -------------------------------------------------------------------------------- +// License GNU/LGPL - Vincent Blavet - August 2009 +// http://www.phpconcept.net +// -------------------------------------------------------------------------------- +// +// Presentation : +// PclZip is a PHP library that manage ZIP archives. +// So far tests show that archives generated by PclZip are readable by +// WinZip application and other tools. +// +// Description : +// See readme.txt and http://www.phpconcept.net +// +// Warning : +// This library and the associated files are non commercial, non professional +// work. +// It should not have unexpected results. However if any damage is caused by +// this software the author can not be responsible. +// The use of this software is at the risk of the user. +// +// -------------------------------------------------------------------------------- +// $Id: pclzip.lib.php,v 1.60 2009/09/30 21:01:04 vblavet Exp $ +// -------------------------------------------------------------------------------- + + // ----- Constants + if (!defined('PCLZIP_READ_BLOCK_SIZE')) { + define( 'PCLZIP_READ_BLOCK_SIZE', 2048 ); + } + + // ----- File list separator + // In version 1.x of PclZip, the separator for file list is a space + // (which is not a very smart choice, specifically for windows paths !). + // A better separator should be a comma (,). This constant gives you the + // abilty to change that. + // However notice that changing this value, may have impact on existing + // scripts, using space separated filenames. + // Recommanded values for compatibility with older versions : + //define( 'PCLZIP_SEPARATOR', ' ' ); + // Recommanded values for smart separation of filenames. + if (!defined('PCLZIP_SEPARATOR')) { + define( 'PCLZIP_SEPARATOR', ',' ); + } + + // ----- Error configuration + // 0 : PclZip Class integrated error handling + // 1 : PclError external library error handling. By enabling this + // you must ensure that you have included PclError library. + // [2,...] : reserved for futur use + if (!defined('PCLZIP_ERROR_EXTERNAL')) { + define( 'PCLZIP_ERROR_EXTERNAL', 0 ); + } + + // ----- Optional static temporary directory + // By default temporary files are generated in the script current + // path. + // If defined : + // - MUST BE terminated by a '/'. + // - MUST be a valid, already created directory + // Samples : + // define( 'PCLZIP_TEMPORARY_DIR', '/temp/' ); + // define( 'PCLZIP_TEMPORARY_DIR', 'C:/Temp/' ); + if (!defined('PCLZIP_TEMPORARY_DIR')) { + define( 'PCLZIP_TEMPORARY_DIR', '' ); + } + + // ----- Optional threshold ratio for use of temporary files + // Pclzip sense the size of the file to add/extract and decide to + // use or not temporary file. The algorythm is looking for + // memory_limit of PHP and apply a ratio. + // threshold = memory_limit * ratio. + // Recommended values are under 0.5. Default 0.47. + // Samples : + // define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.5 ); + if (!defined('PCLZIP_TEMPORARY_FILE_RATIO')) { + define( 'PCLZIP_TEMPORARY_FILE_RATIO', 0.47 ); + } + +// -------------------------------------------------------------------------------- +// ***** UNDER THIS LINE NOTHING NEEDS TO BE MODIFIED ***** +// -------------------------------------------------------------------------------- + + // ----- Global variables + $g_pclzip_version = "2.8.2"; + + // ----- Error codes + // -1 : Unable to open file in binary write mode + // -2 : Unable to open file in binary read mode + // -3 : Invalid parameters + // -4 : File does not exist + // -5 : Filename is too long (max. 255) + // -6 : Not a valid zip file + // -7 : Invalid extracted file size + // -8 : Unable to create directory + // -9 : Invalid archive extension + // -10 : Invalid archive format + // -11 : Unable to delete file (unlink) + // -12 : Unable to rename file (rename) + // -13 : Invalid header checksum + // -14 : Invalid archive size + define( 'PCLZIP_ERR_USER_ABORTED', 2 ); + define( 'PCLZIP_ERR_NO_ERROR', 0 ); + define( 'PCLZIP_ERR_WRITE_OPEN_FAIL', -1 ); + define( 'PCLZIP_ERR_READ_OPEN_FAIL', -2 ); + define( 'PCLZIP_ERR_INVALID_PARAMETER', -3 ); + define( 'PCLZIP_ERR_MISSING_FILE', -4 ); + define( 'PCLZIP_ERR_FILENAME_TOO_LONG', -5 ); + define( 'PCLZIP_ERR_INVALID_ZIP', -6 ); + define( 'PCLZIP_ERR_BAD_EXTRACTED_FILE', -7 ); + define( 'PCLZIP_ERR_DIR_CREATE_FAIL', -8 ); + define( 'PCLZIP_ERR_BAD_EXTENSION', -9 ); + define( 'PCLZIP_ERR_BAD_FORMAT', -10 ); + define( 'PCLZIP_ERR_DELETE_FILE_FAIL', -11 ); + define( 'PCLZIP_ERR_RENAME_FILE_FAIL', -12 ); + define( 'PCLZIP_ERR_BAD_CHECKSUM', -13 ); + define( 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', -14 ); + define( 'PCLZIP_ERR_MISSING_OPTION_VALUE', -15 ); + define( 'PCLZIP_ERR_INVALID_OPTION_VALUE', -16 ); + define( 'PCLZIP_ERR_ALREADY_A_DIRECTORY', -17 ); + define( 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', -18 ); + define( 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION', -19 ); + define( 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE', -20 ); + define( 'PCLZIP_ERR_DIRECTORY_RESTRICTION', -21 ); + + // ----- Options values + define( 'PCLZIP_OPT_PATH', 77001 ); + define( 'PCLZIP_OPT_ADD_PATH', 77002 ); + define( 'PCLZIP_OPT_REMOVE_PATH', 77003 ); + define( 'PCLZIP_OPT_REMOVE_ALL_PATH', 77004 ); + define( 'PCLZIP_OPT_SET_CHMOD', 77005 ); + define( 'PCLZIP_OPT_EXTRACT_AS_STRING', 77006 ); + define( 'PCLZIP_OPT_NO_COMPRESSION', 77007 ); + define( 'PCLZIP_OPT_BY_NAME', 77008 ); + define( 'PCLZIP_OPT_BY_INDEX', 77009 ); + define( 'PCLZIP_OPT_BY_EREG', 77010 ); + define( 'PCLZIP_OPT_BY_PREG', 77011 ); + define( 'PCLZIP_OPT_COMMENT', 77012 ); + define( 'PCLZIP_OPT_ADD_COMMENT', 77013 ); + define( 'PCLZIP_OPT_PREPEND_COMMENT', 77014 ); + define( 'PCLZIP_OPT_EXTRACT_IN_OUTPUT', 77015 ); + define( 'PCLZIP_OPT_REPLACE_NEWER', 77016 ); + define( 'PCLZIP_OPT_STOP_ON_ERROR', 77017 ); + // Having big trouble with crypt. Need to multiply 2 long int + // which is not correctly supported by PHP ... + //define( 'PCLZIP_OPT_CRYPT', 77018 ); + define( 'PCLZIP_OPT_EXTRACT_DIR_RESTRICTION', 77019 ); + define( 'PCLZIP_OPT_TEMP_FILE_THRESHOLD', 77020 ); + define( 'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD', 77020 ); // alias + define( 'PCLZIP_OPT_TEMP_FILE_ON', 77021 ); + define( 'PCLZIP_OPT_ADD_TEMP_FILE_ON', 77021 ); // alias + define( 'PCLZIP_OPT_TEMP_FILE_OFF', 77022 ); + define( 'PCLZIP_OPT_ADD_TEMP_FILE_OFF', 77022 ); // alias + + // ----- File description attributes + define( 'PCLZIP_ATT_FILE_NAME', 79001 ); + define( 'PCLZIP_ATT_FILE_NEW_SHORT_NAME', 79002 ); + define( 'PCLZIP_ATT_FILE_NEW_FULL_NAME', 79003 ); + define( 'PCLZIP_ATT_FILE_MTIME', 79004 ); + define( 'PCLZIP_ATT_FILE_CONTENT', 79005 ); + define( 'PCLZIP_ATT_FILE_COMMENT', 79006 ); + + // ----- Call backs values + define( 'PCLZIP_CB_PRE_EXTRACT', 78001 ); + define( 'PCLZIP_CB_POST_EXTRACT', 78002 ); + define( 'PCLZIP_CB_PRE_ADD', 78003 ); + define( 'PCLZIP_CB_POST_ADD', 78004 ); + /* For futur use + define( 'PCLZIP_CB_PRE_LIST', 78005 ); + define( 'PCLZIP_CB_POST_LIST', 78006 ); + define( 'PCLZIP_CB_PRE_DELETE', 78007 ); + define( 'PCLZIP_CB_POST_DELETE', 78008 ); + */ + + // -------------------------------------------------------------------------------- + // Class : PclZip + // Description : + // PclZip is the class that represent a Zip archive. + // The public methods allow the manipulation of the archive. + // Attributes : + // Attributes must not be accessed directly. + // Methods : + // PclZip() : Object creator + // create() : Creates the Zip archive + // listContent() : List the content of the Zip archive + // extract() : Extract the content of the archive + // properties() : List the properties of the archive + // -------------------------------------------------------------------------------- + class PclZip + { + // ----- Filename of the zip file + var $zipname = ''; + + // ----- File descriptor of the zip file + var $zip_fd = 0; + + // ----- Internal error handling + var $error_code = 1; + var $error_string = ''; + + // ----- Current status of the magic_quotes_runtime + // This value store the php configuration for magic_quotes + // The class can then disable the magic_quotes and reset it after + var $magic_quotes_status; + + // -------------------------------------------------------------------------------- + // Function : PclZip() + // Description : + // Creates a PclZip object and set the name of the associated Zip archive + // filename. + // Note that no real action is taken, if the archive does not exist it is not + // created. Use create() for that. + // -------------------------------------------------------------------------------- + function PclZip($p_zipname) + { + + // ----- Tests the zlib + if (!function_exists('gzopen')) + { + die('Abort '.basename(__FILE__).' : Missing zlib extensions'); + } + + // ----- Set the attributes + $this->zipname = $p_zipname; + $this->zip_fd = 0; + $this->magic_quotes_status = -1; + + // ----- Return + return; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // create($p_filelist, $p_add_dir="", $p_remove_dir="") + // create($p_filelist, $p_option, $p_option_value, ...) + // Description : + // This method supports two different synopsis. The first one is historical. + // This method creates a Zip Archive. The Zip file is created in the + // filesystem. The files and directories indicated in $p_filelist + // are added in the archive. See the parameters description for the + // supported format of $p_filelist. + // When a directory is in the list, the directory and its content is added + // in the archive. + // In this synopsis, the function takes an optional variable list of + // options. See bellow the supported options. + // Parameters : + // $p_filelist : An array containing file or directory names, or + // a string containing one filename or one directory name, or + // a string containing a list of filenames and/or directory + // names separated by spaces. + // $p_add_dir : A path to add before the real path of the archived file, + // in order to have it memorized in the archive. + // $p_remove_dir : A path to remove from the real path of the file to archive, + // in order to have a shorter path memorized in the archive. + // When $p_add_dir and $p_remove_dir are set, $p_remove_dir + // is removed first, before $p_add_dir is added. + // Options : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_COMMENT : + // PCLZIP_CB_PRE_ADD : + // PCLZIP_CB_POST_ADD : + // Return Values : + // 0 on failure, + // The list of the added files, with a status of the add action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function create($p_filelist) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Set default values + $v_options = array(); + $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove from the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_ADD => 'optional', + PCLZIP_CB_POST_ADD => 'optional', + PCLZIP_OPT_NO_COMPRESSION => 'optional', + PCLZIP_OPT_COMMENT => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + //, PCLZIP_OPT_CRYPT => 'optional' + )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_options[PCLZIP_OPT_ADD_PATH] = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; + } + else if ($v_size > 2) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Invalid number / type of arguments"); + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Init + $v_string_list = array(); + $v_att_list = array(); + $v_filedescr_list = array(); + $p_result_list = array(); + + // ----- Look if the $p_filelist is really an array + if (is_array($p_filelist)) { + + // ----- Look if the first element is also an array + // This will mean that this is a file description entry + if (isset($p_filelist[0]) && is_array($p_filelist[0])) { + $v_att_list = $p_filelist; + } + + // ----- The list is a list of string names + else { + $v_string_list = $p_filelist; + } + } + + // ----- Look if the $p_filelist is a string + else if (is_string($p_filelist)) { + // ----- Create a list from the string + $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); + } + + // ----- Invalid variable type for $p_filelist + else { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_filelist"); + return 0; + } + + // ----- Reformat the string list + if (sizeof($v_string_list) != 0) { + foreach ($v_string_list as $v_string) { + if ($v_string != '') { + $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; + } + else { + } + } + } + + // ----- For each file in the list check the attributes + $v_supported_attributes + = array ( PCLZIP_ATT_FILE_NAME => 'mandatory' + ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' + ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' + ,PCLZIP_ATT_FILE_MTIME => 'optional' + ,PCLZIP_ATT_FILE_CONTENT => 'optional' + ,PCLZIP_ATT_FILE_COMMENT => 'optional' + ); + foreach ($v_att_list as $v_entry) { + $v_result = $this->privFileDescrParseAtt($v_entry, + $v_filedescr_list[], + $v_options, + $v_supported_attributes); + if ($v_result != 1) { + return 0; + } + } + + // ----- Expand the filelist (expand directories) + $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Call the create fct + $v_result = $this->privCreate($v_filedescr_list, $p_result_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Return + return $p_result_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // add($p_filelist, $p_add_dir="", $p_remove_dir="") + // add($p_filelist, $p_option, $p_option_value, ...) + // Description : + // This method supports two synopsis. The first one is historical. + // This methods add the list of files in an existing archive. + // If a file with the same name already exists, it is added at the end of the + // archive, the first one is still present. + // If the archive does not exist, it is created. + // Parameters : + // $p_filelist : An array containing file or directory names, or + // a string containing one filename or one directory name, or + // a string containing a list of filenames and/or directory + // names separated by spaces. + // $p_add_dir : A path to add before the real path of the archived file, + // in order to have it memorized in the archive. + // $p_remove_dir : A path to remove from the real path of the file to archive, + // in order to have a shorter path memorized in the archive. + // When $p_add_dir and $p_remove_dir are set, $p_remove_dir + // is removed first, before $p_add_dir is added. + // Options : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_COMMENT : + // PCLZIP_OPT_ADD_COMMENT : + // PCLZIP_OPT_PREPEND_COMMENT : + // PCLZIP_CB_PRE_ADD : + // PCLZIP_CB_POST_ADD : + // Return Values : + // 0 on failure, + // The list of the added files, with a status of the add action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function add($p_filelist) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Set default values + $v_options = array(); + $v_options[PCLZIP_OPT_NO_COMPRESSION] = FALSE; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove form the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_ADD => 'optional', + PCLZIP_CB_POST_ADD => 'optional', + PCLZIP_OPT_NO_COMPRESSION => 'optional', + PCLZIP_OPT_COMMENT => 'optional', + PCLZIP_OPT_ADD_COMMENT => 'optional', + PCLZIP_OPT_PREPEND_COMMENT => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + //, PCLZIP_OPT_CRYPT => 'optional' + )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_options[PCLZIP_OPT_ADD_PATH] = $v_add_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_options[PCLZIP_OPT_REMOVE_PATH] = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Init + $v_string_list = array(); + $v_att_list = array(); + $v_filedescr_list = array(); + $p_result_list = array(); + + // ----- Look if the $p_filelist is really an array + if (is_array($p_filelist)) { + + // ----- Look if the first element is also an array + // This will mean that this is a file description entry + if (isset($p_filelist[0]) && is_array($p_filelist[0])) { + $v_att_list = $p_filelist; + } + + // ----- The list is a list of string names + else { + $v_string_list = $p_filelist; + } + } + + // ----- Look if the $p_filelist is a string + else if (is_string($p_filelist)) { + // ----- Create a list from the string + $v_string_list = explode(PCLZIP_SEPARATOR, $p_filelist); + } + + // ----- Invalid variable type for $p_filelist + else { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type '".gettype($p_filelist)."' for p_filelist"); + return 0; + } + + // ----- Reformat the string list + if (sizeof($v_string_list) != 0) { + foreach ($v_string_list as $v_string) { + $v_att_list[][PCLZIP_ATT_FILE_NAME] = $v_string; + } + } + + // ----- For each file in the list check the attributes + $v_supported_attributes + = array ( PCLZIP_ATT_FILE_NAME => 'mandatory' + ,PCLZIP_ATT_FILE_NEW_SHORT_NAME => 'optional' + ,PCLZIP_ATT_FILE_NEW_FULL_NAME => 'optional' + ,PCLZIP_ATT_FILE_MTIME => 'optional' + ,PCLZIP_ATT_FILE_CONTENT => 'optional' + ,PCLZIP_ATT_FILE_COMMENT => 'optional' + ); + foreach ($v_att_list as $v_entry) { + $v_result = $this->privFileDescrParseAtt($v_entry, + $v_filedescr_list[], + $v_options, + $v_supported_attributes); + if ($v_result != 1) { + return 0; + } + } + + // ----- Expand the filelist (expand directories) + $v_result = $this->privFileDescrExpand($v_filedescr_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Call the create fct + $v_result = $this->privAdd($v_filedescr_list, $p_result_list, $v_options); + if ($v_result != 1) { + return 0; + } + + // ----- Return + return $p_result_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : listContent() + // Description : + // This public method, gives the list of the files and directories, with their + // properties. + // The properties of each entries in the list are (used also in other functions) : + // filename : Name of the file. For a create or add action it is the filename + // given by the user. For an extract function it is the filename + // of the extracted file. + // stored_filename : Name of the file / directory stored in the archive. + // size : Size of the stored file. + // compressed_size : Size of the file's data compressed in the archive + // (without the headers overhead) + // mtime : Last known modification date of the file (UNIX timestamp) + // comment : Comment associated with the file + // folder : true | false + // index : index of the file in the archive + // status : status of the action (depending of the action) : + // Values are : + // ok : OK ! + // filtered : the file / dir is not extracted (filtered by user) + // already_a_directory : the file can not be extracted because a + // directory with the same name already exists + // write_protected : the file can not be extracted because a file + // with the same name already exists and is + // write protected + // newer_exist : the file was not extracted because a newer file exists + // path_creation_fail : the file is not extracted because the folder + // does not exist and can not be created + // write_error : the file was not extracted because there was a + // error while writing the file + // read_error : the file was not extracted because there was a error + // while reading the file + // invalid_header : the file was not extracted because of an archive + // format error (bad file header) + // Note that each time a method can continue operating when there + // is an action error on a file, the error is only logged in the file status. + // Return Values : + // 0 on an unrecoverable failure, + // The list of the files in the archive. + // -------------------------------------------------------------------------------- + function listContent() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Call the extracting fct + $p_list = array(); + if (($v_result = $this->privList($p_list)) != 1) + { + unset($p_list); + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // extract($p_path="./", $p_remove_path="") + // extract([$p_option, $p_option_value, ...]) + // Description : + // This method supports two synopsis. The first one is historical. + // This method extract all the files / directories from the archive to the + // folder indicated in $p_path. + // If you want to ignore the 'root' part of path of the memorized files + // you can indicate this in the optional $p_remove_path parameter. + // By default, if a newer file with the same name already exists, the + // file is not extracted. + // + // If both PCLZIP_OPT_PATH and PCLZIP_OPT_ADD_PATH aoptions + // are used, the path indicated in PCLZIP_OPT_ADD_PATH is append + // at the end of the path value of PCLZIP_OPT_PATH. + // Parameters : + // $p_path : Path where the files and directories are to be extracted + // $p_remove_path : First part ('root' part) of the memorized path + // (if any similar) to remove while extracting. + // Options : + // PCLZIP_OPT_PATH : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_CB_PRE_EXTRACT : + // PCLZIP_CB_POST_EXTRACT : + // Return Values : + // 0 or a negative value on failure, + // The list of the extracted files, with a status of the action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function extract() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); +// $v_path = "./"; + $v_path = ''; + $v_remove_path = ""; + $v_remove_all_path = false; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Default values for option + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + + // ----- Look for arguments + if ($v_size > 0) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_PATH => 'optional', + PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_EXTRACT => 'optional', + PCLZIP_CB_POST_EXTRACT => 'optional', + PCLZIP_OPT_SET_CHMOD => 'optional', + PCLZIP_OPT_BY_NAME => 'optional', + PCLZIP_OPT_BY_EREG => 'optional', + PCLZIP_OPT_BY_PREG => 'optional', + PCLZIP_OPT_BY_INDEX => 'optional', + PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', + PCLZIP_OPT_EXTRACT_IN_OUTPUT => 'optional', + PCLZIP_OPT_REPLACE_NEWER => 'optional' + ,PCLZIP_OPT_STOP_ON_ERROR => 'optional' + ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + )); + if ($v_result != 1) { + return 0; + } + + // ----- Set the arguments + if (isset($v_options[PCLZIP_OPT_PATH])) { + $v_path = $v_options[PCLZIP_OPT_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { + $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { + // ----- Check for '/' in last path char + if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { + $v_path .= '/'; + } + $v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_remove_path = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Trace + + // ----- Call the extracting fct + $p_list = array(); + $v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, + $v_remove_all_path, $v_options); + if ($v_result < 1) { + unset($p_list); + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + + // -------------------------------------------------------------------------------- + // Function : + // extractByIndex($p_index, $p_path="./", $p_remove_path="") + // extractByIndex($p_index, [$p_option, $p_option_value, ...]) + // Description : + // This method supports two synopsis. The first one is historical. + // This method is doing a partial extract of the archive. + // The extracted files or folders are identified by their index in the + // archive (from 0 to n). + // Note that if the index identify a folder, only the folder entry is + // extracted, not all the files included in the archive. + // Parameters : + // $p_index : A single index (integer) or a string of indexes of files to + // extract. The form of the string is "0,4-6,8-12" with only numbers + // and '-' for range or ',' to separate ranges. No spaces or ';' + // are allowed. + // $p_path : Path where the files and directories are to be extracted + // $p_remove_path : First part ('root' part) of the memorized path + // (if any similar) to remove while extracting. + // Options : + // PCLZIP_OPT_PATH : + // PCLZIP_OPT_ADD_PATH : + // PCLZIP_OPT_REMOVE_PATH : + // PCLZIP_OPT_REMOVE_ALL_PATH : + // PCLZIP_OPT_EXTRACT_AS_STRING : The files are extracted as strings and + // not as files. + // The resulting content is in a new field 'content' in the file + // structure. + // This option must be used alone (any other options are ignored). + // PCLZIP_CB_PRE_EXTRACT : + // PCLZIP_CB_POST_EXTRACT : + // Return Values : + // 0 on failure, + // The list of the extracted files, with a status of the action. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + //function extractByIndex($p_index, options...) + function extractByIndex($p_index) + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); +// $v_path = "./"; + $v_path = ''; + $v_remove_path = ""; + $v_remove_all_path = false; + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Default values for option + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + + // ----- Look for arguments + if ($v_size > 1) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Remove form the options list the first argument + array_shift($v_arg_list); + $v_size--; + + // ----- Look for first arg + if ((is_integer($v_arg_list[0])) && ($v_arg_list[0] > 77000)) { + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_PATH => 'optional', + PCLZIP_OPT_REMOVE_PATH => 'optional', + PCLZIP_OPT_REMOVE_ALL_PATH => 'optional', + PCLZIP_OPT_EXTRACT_AS_STRING => 'optional', + PCLZIP_OPT_ADD_PATH => 'optional', + PCLZIP_CB_PRE_EXTRACT => 'optional', + PCLZIP_CB_POST_EXTRACT => 'optional', + PCLZIP_OPT_SET_CHMOD => 'optional', + PCLZIP_OPT_REPLACE_NEWER => 'optional' + ,PCLZIP_OPT_STOP_ON_ERROR => 'optional' + ,PCLZIP_OPT_EXTRACT_DIR_RESTRICTION => 'optional', + PCLZIP_OPT_TEMP_FILE_THRESHOLD => 'optional', + PCLZIP_OPT_TEMP_FILE_ON => 'optional', + PCLZIP_OPT_TEMP_FILE_OFF => 'optional' + )); + if ($v_result != 1) { + return 0; + } + + // ----- Set the arguments + if (isset($v_options[PCLZIP_OPT_PATH])) { + $v_path = $v_options[PCLZIP_OPT_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_PATH])) { + $v_remove_path = $v_options[PCLZIP_OPT_REMOVE_PATH]; + } + if (isset($v_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $v_remove_all_path = $v_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + if (isset($v_options[PCLZIP_OPT_ADD_PATH])) { + // ----- Check for '/' in last path char + if ((strlen($v_path) > 0) && (substr($v_path, -1) != '/')) { + $v_path .= '/'; + } + $v_path .= $v_options[PCLZIP_OPT_ADD_PATH]; + } + if (!isset($v_options[PCLZIP_OPT_EXTRACT_AS_STRING])) { + $v_options[PCLZIP_OPT_EXTRACT_AS_STRING] = FALSE; + } + else { + } + } + + // ----- Look for 2 args + // Here we need to support the first historic synopsis of the + // method. + else { + + // ----- Get the first argument + $v_path = $v_arg_list[0]; + + // ----- Look for the optional second argument + if ($v_size == 2) { + $v_remove_path = $v_arg_list[1]; + } + else if ($v_size > 2) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid number / type of arguments"); + + // ----- Return + return 0; + } + } + } + + // ----- Trace + + // ----- Trick + // Here I want to reuse extractByRule(), so I need to parse the $p_index + // with privParseOptions() + $v_arg_trick = array (PCLZIP_OPT_BY_INDEX, $p_index); + $v_options_trick = array(); + $v_result = $this->privParseOptions($v_arg_trick, sizeof($v_arg_trick), $v_options_trick, + array (PCLZIP_OPT_BY_INDEX => 'optional' )); + if ($v_result != 1) { + return 0; + } + $v_options[PCLZIP_OPT_BY_INDEX] = $v_options_trick[PCLZIP_OPT_BY_INDEX]; + + // ----- Look for default option values + $this->privOptionDefaultThreshold($v_options); + + // ----- Call the extracting fct + if (($v_result = $this->privExtractByRule($p_list, $v_path, $v_remove_path, $v_remove_all_path, $v_options)) < 1) { + return(0); + } + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : + // delete([$p_option, $p_option_value, ...]) + // Description : + // This method removes files from the archive. + // If no parameters are given, then all the archive is emptied. + // Parameters : + // None or optional arguments. + // Options : + // PCLZIP_OPT_BY_INDEX : + // PCLZIP_OPT_BY_NAME : + // PCLZIP_OPT_BY_EREG : + // PCLZIP_OPT_BY_PREG : + // Return Values : + // 0 on failure, + // The list of the files which are still present in the archive. + // (see PclZip::listContent() for list entry format) + // -------------------------------------------------------------------------------- + function delete() + { + $v_result=1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Set default values + $v_options = array(); + + // ----- Look for variable options arguments + $v_size = func_num_args(); + + // ----- Look for arguments + if ($v_size > 0) { + // ----- Get the arguments + $v_arg_list = func_get_args(); + + // ----- Parse the options + $v_result = $this->privParseOptions($v_arg_list, $v_size, $v_options, + array (PCLZIP_OPT_BY_NAME => 'optional', + PCLZIP_OPT_BY_EREG => 'optional', + PCLZIP_OPT_BY_PREG => 'optional', + PCLZIP_OPT_BY_INDEX => 'optional' )); + if ($v_result != 1) { + return 0; + } + } + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Call the delete fct + $v_list = array(); + if (($v_result = $this->privDeleteByRule($v_list, $v_options)) != 1) { + $this->privSwapBackMagicQuotes(); + unset($v_list); + return(0); + } + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : deleteByIndex() + // Description : + // ***** Deprecated ***** + // delete(PCLZIP_OPT_BY_INDEX, $p_index) should be prefered. + // -------------------------------------------------------------------------------- + function deleteByIndex($p_index) + { + + $p_list = $this->delete(PCLZIP_OPT_BY_INDEX, $p_index); + + // ----- Return + return $p_list; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : properties() + // Description : + // This method gives the properties of the archive. + // The properties are : + // nb : Number of files in the archive + // comment : Comment associated with the archive file + // status : not_exist, ok + // Parameters : + // None + // Return Values : + // 0 on failure, + // An array with the archive properties. + // -------------------------------------------------------------------------------- + function properties() + { + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + $this->privSwapBackMagicQuotes(); + return(0); + } + + // ----- Default properties + $v_prop = array(); + $v_prop['comment'] = ''; + $v_prop['nb'] = 0; + $v_prop['status'] = 'not_exist'; + + // ----- Look if file exists + if (@is_file($this->zipname)) + { + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) + { + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); + + // ----- Return + return 0; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privSwapBackMagicQuotes(); + return 0; + } + + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Set the user attributes + $v_prop['comment'] = $v_central_dir['comment']; + $v_prop['nb'] = $v_central_dir['entries']; + $v_prop['status'] = 'ok'; + } + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_prop; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : duplicate() + // Description : + // This method creates an archive by copying the content of an other one. If + // the archive already exist, it is replaced by the new one without any warning. + // Parameters : + // $p_archive : The filename of a valid archive, or + // a valid PclZip object. + // Return Values : + // 1 on success. + // 0 or a negative value on error (error code). + // -------------------------------------------------------------------------------- + function duplicate($p_archive) + { + $v_result = 1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Look if the $p_archive is a PclZip object + if ((is_object($p_archive)) && (get_class($p_archive) == 'pclzip')) + { + + // ----- Duplicate the archive + $v_result = $this->privDuplicate($p_archive->zipname); + } + + // ----- Look if the $p_archive is a string (so a filename) + else if (is_string($p_archive)) + { + + // ----- Check that $p_archive is a valid zip file + // TBC : Should also check the archive format + if (!is_file($p_archive)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "No file with filename '".$p_archive."'"); + $v_result = PCLZIP_ERR_MISSING_FILE; + } + else { + // ----- Duplicate the archive + $v_result = $this->privDuplicate($p_archive); + } + } + + // ----- Invalid variable + else + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); + $v_result = PCLZIP_ERR_INVALID_PARAMETER; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : merge() + // Description : + // This method merge the $p_archive_to_add archive at the end of the current + // one ($this). + // If the archive ($this) does not exist, the merge becomes a duplicate. + // If the $p_archive_to_add archive does not exist, the merge is a success. + // Parameters : + // $p_archive_to_add : It can be directly the filename of a valid zip archive, + // or a PclZip object archive. + // Return Values : + // 1 on success, + // 0 or negative values on error (see below). + // -------------------------------------------------------------------------------- + function merge($p_archive_to_add) + { + $v_result = 1; + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Check archive + if (!$this->privCheckFormat()) { + return(0); + } + + // ----- Look if the $p_archive_to_add is a PclZip object + if ((is_object($p_archive_to_add)) && (get_class($p_archive_to_add) == 'pclzip')) + { + + // ----- Merge the archive + $v_result = $this->privMerge($p_archive_to_add); + } + + // ----- Look if the $p_archive_to_add is a string (so a filename) + else if (is_string($p_archive_to_add)) + { + + // ----- Create a temporary archive + $v_object_archive = new PclZip($p_archive_to_add); + + // ----- Merge the archive + $v_result = $this->privMerge($v_object_archive); + } + + // ----- Invalid variable + else + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid variable type p_archive_to_add"); + $v_result = PCLZIP_ERR_INVALID_PARAMETER; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + + + // -------------------------------------------------------------------------------- + // Function : errorCode() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorCode() + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + return(PclErrorCode()); + } + else { + return($this->error_code); + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : errorName() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorName($p_with_code=false) + { + $v_name = array ( PCLZIP_ERR_NO_ERROR => 'PCLZIP_ERR_NO_ERROR', + PCLZIP_ERR_WRITE_OPEN_FAIL => 'PCLZIP_ERR_WRITE_OPEN_FAIL', + PCLZIP_ERR_READ_OPEN_FAIL => 'PCLZIP_ERR_READ_OPEN_FAIL', + PCLZIP_ERR_INVALID_PARAMETER => 'PCLZIP_ERR_INVALID_PARAMETER', + PCLZIP_ERR_MISSING_FILE => 'PCLZIP_ERR_MISSING_FILE', + PCLZIP_ERR_FILENAME_TOO_LONG => 'PCLZIP_ERR_FILENAME_TOO_LONG', + PCLZIP_ERR_INVALID_ZIP => 'PCLZIP_ERR_INVALID_ZIP', + PCLZIP_ERR_BAD_EXTRACTED_FILE => 'PCLZIP_ERR_BAD_EXTRACTED_FILE', + PCLZIP_ERR_DIR_CREATE_FAIL => 'PCLZIP_ERR_DIR_CREATE_FAIL', + PCLZIP_ERR_BAD_EXTENSION => 'PCLZIP_ERR_BAD_EXTENSION', + PCLZIP_ERR_BAD_FORMAT => 'PCLZIP_ERR_BAD_FORMAT', + PCLZIP_ERR_DELETE_FILE_FAIL => 'PCLZIP_ERR_DELETE_FILE_FAIL', + PCLZIP_ERR_RENAME_FILE_FAIL => 'PCLZIP_ERR_RENAME_FILE_FAIL', + PCLZIP_ERR_BAD_CHECKSUM => 'PCLZIP_ERR_BAD_CHECKSUM', + PCLZIP_ERR_INVALID_ARCHIVE_ZIP => 'PCLZIP_ERR_INVALID_ARCHIVE_ZIP', + PCLZIP_ERR_MISSING_OPTION_VALUE => 'PCLZIP_ERR_MISSING_OPTION_VALUE', + PCLZIP_ERR_INVALID_OPTION_VALUE => 'PCLZIP_ERR_INVALID_OPTION_VALUE', + PCLZIP_ERR_UNSUPPORTED_COMPRESSION => 'PCLZIP_ERR_UNSUPPORTED_COMPRESSION', + PCLZIP_ERR_UNSUPPORTED_ENCRYPTION => 'PCLZIP_ERR_UNSUPPORTED_ENCRYPTION' + ,PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE => 'PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE' + ,PCLZIP_ERR_DIRECTORY_RESTRICTION => 'PCLZIP_ERR_DIRECTORY_RESTRICTION' + ); + + if (isset($v_name[$this->error_code])) { + $v_value = $v_name[$this->error_code]; + } + else { + $v_value = 'NoName'; + } + + if ($p_with_code) { + return($v_value.' ('.$this->error_code.')'); + } + else { + return($v_value); + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : errorInfo() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function errorInfo($p_full=false) + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + return(PclErrorString()); + } + else { + if ($p_full) { + return($this->errorName(true)." : ".$this->error_string); + } + else { + return($this->error_string." [code ".$this->error_code."]"); + } + } + } + // -------------------------------------------------------------------------------- + + +// -------------------------------------------------------------------------------- +// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS ***** +// ***** ***** +// ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY ***** +// -------------------------------------------------------------------------------- + + + + // -------------------------------------------------------------------------------- + // Function : privCheckFormat() + // Description : + // This method check that the archive exists and is a valid zip archive. + // Several level of check exists. (futur) + // Parameters : + // $p_level : Level of check. Default 0. + // 0 : Check the first bytes (magic codes) (default value)) + // 1 : 0 + Check the central directory (futur) + // 2 : 1 + Check each file header (futur) + // Return Values : + // true on success, + // false on error, the error code is set. + // -------------------------------------------------------------------------------- + function privCheckFormat($p_level=0) + { + $v_result = true; + + // ----- Reset the file system cache + clearstatcache(); + + // ----- Reset the error handler + $this->privErrorReset(); + + // ----- Look if the file exits + if (!is_file($this->zipname)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "Missing archive file '".$this->zipname."'"); + return(false); + } + + // ----- Check that the file is readeable + if (!is_readable($this->zipname)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '".$this->zipname."'"); + return(false); + } + + // ----- Check the magic code + // TBC + + // ----- Check the central header + // TBC + + // ----- Check each file header + // TBC + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privParseOptions() + // Description : + // This internal methods reads the variable list of arguments ($p_options_list, + // $p_size) and generate an array with the options and values ($v_result_list). + // $v_requested_options contains the options that can be present and those that + // must be present. + // $v_requested_options is an array, with the option value as key, and 'optional', + // or 'mandatory' as value. + // Parameters : + // See above. + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privParseOptions(&$p_options_list, $p_size, &$v_result_list, $v_requested_options=false) + { + $v_result=1; + + // ----- Read the options + $i=0; + while ($i<$p_size) { + + // ----- Check if the option is supported + if (!isset($v_requested_options[$p_options_list[$i]])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid optional parameter '".$p_options_list[$i]."' for this method"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for next option + switch ($p_options_list[$i]) { + // ----- Look for options that request a path value + case PCLZIP_OPT_PATH : + case PCLZIP_OPT_REMOVE_PATH : + case PCLZIP_OPT_ADD_PATH : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); + $i++; + break; + + case PCLZIP_OPT_TEMP_FILE_THRESHOLD : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + return PclZip::errorCode(); + } + + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'"); + return PclZip::errorCode(); + } + + // ----- Check the value + $v_value = $p_options_list[$i+1]; + if ((!is_integer($v_value)) || ($v_value<0)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Integer expected for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + return PclZip::errorCode(); + } + + // ----- Get the value (and convert it in bytes) + $v_result_list[$p_options_list[$i]] = $v_value*1048576; + $i++; + break; + + case PCLZIP_OPT_TEMP_FILE_ON : + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_OFF])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_OFF'"); + return PclZip::errorCode(); + } + + $v_result_list[$p_options_list[$i]] = true; + break; + + case PCLZIP_OPT_TEMP_FILE_OFF : + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_ON])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_ON'"); + return PclZip::errorCode(); + } + // ----- Check for incompatible options + if (isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Option '".PclZipUtilOptionText($p_options_list[$i])."' can not be used with option 'PCLZIP_OPT_TEMP_FILE_THRESHOLD'"); + return PclZip::errorCode(); + } + + $v_result_list[$p_options_list[$i]] = true; + break; + + case PCLZIP_OPT_EXTRACT_DIR_RESTRICTION : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if ( is_string($p_options_list[$i+1]) + && ($p_options_list[$i+1] != '')) { + $v_result_list[$p_options_list[$i]] = PclZipUtilTranslateWinPath($p_options_list[$i+1], FALSE); + $i++; + } + else { + } + break; + + // ----- Look for options that request an array of string for value + case PCLZIP_OPT_BY_NAME : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]][0] = $p_options_list[$i+1]; + } + else if (is_array($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that request an EREG or PREG expression + case PCLZIP_OPT_BY_EREG : + // ereg() is deprecated starting with PHP 5.3. Move PCLZIP_OPT_BY_EREG + // to PCLZIP_OPT_BY_PREG + $p_options_list[$i] = PCLZIP_OPT_BY_PREG; + case PCLZIP_OPT_BY_PREG : + //case PCLZIP_OPT_CRYPT : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Wrong parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that takes a string + case PCLZIP_OPT_COMMENT : + case PCLZIP_OPT_ADD_COMMENT : + case PCLZIP_OPT_PREPEND_COMMENT : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, + "Missing parameter value for option '" + .PclZipUtilOptionText($p_options_list[$i]) + ."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + if (is_string($p_options_list[$i+1])) { + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, + "Wrong parameter value for option '" + .PclZipUtilOptionText($p_options_list[$i]) + ."'"); + + // ----- Return + return PclZip::errorCode(); + } + $i++; + break; + + // ----- Look for options that request an array of index + case PCLZIP_OPT_BY_INDEX : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_work_list = array(); + if (is_string($p_options_list[$i+1])) { + + // ----- Remove spaces + $p_options_list[$i+1] = strtr($p_options_list[$i+1], ' ', ''); + + // ----- Parse items + $v_work_list = explode(",", $p_options_list[$i+1]); + } + else if (is_integer($p_options_list[$i+1])) { + $v_work_list[0] = $p_options_list[$i+1].'-'.$p_options_list[$i+1]; + } + else if (is_array($p_options_list[$i+1])) { + $v_work_list = $p_options_list[$i+1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Value must be integer, string or array for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Reduce the index list + // each index item in the list must be a couple with a start and + // an end value : [0,3], [5-5], [8-10], ... + // ----- Check the format of each item + $v_sort_flag=false; + $v_sort_value=0; + for ($j=0; $j<sizeof($v_work_list); $j++) { + // ----- Explode the item + $v_item_list = explode("-", $v_work_list[$j]); + $v_size_item_list = sizeof($v_item_list); + + // ----- TBC : Here we might check that each item is a + // real integer ... + + // ----- Look for single value + if ($v_size_item_list == 1) { + // ----- Set the option value + $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0]; + $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[0]; + } + elseif ($v_size_item_list == 2) { + // ----- Set the option value + $v_result_list[$p_options_list[$i]][$j]['start'] = $v_item_list[0]; + $v_result_list[$p_options_list[$i]][$j]['end'] = $v_item_list[1]; + } + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Too many values in index range for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + + // ----- Look for list sort + if ($v_result_list[$p_options_list[$i]][$j]['start'] < $v_sort_value) { + $v_sort_flag=true; + + // ----- TBC : An automatic sort should be writen ... + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Invalid order of index range for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + $v_sort_value = $v_result_list[$p_options_list[$i]][$j]['start']; + } + + // ----- Sort the items + if ($v_sort_flag) { + // TBC : To Be Completed + } + + // ----- Next option + $i++; + break; + + // ----- Look for options that request no value + case PCLZIP_OPT_REMOVE_ALL_PATH : + case PCLZIP_OPT_EXTRACT_AS_STRING : + case PCLZIP_OPT_NO_COMPRESSION : + case PCLZIP_OPT_EXTRACT_IN_OUTPUT : + case PCLZIP_OPT_REPLACE_NEWER : + case PCLZIP_OPT_STOP_ON_ERROR : + $v_result_list[$p_options_list[$i]] = true; + break; + + // ----- Look for options that request an octal value + case PCLZIP_OPT_SET_CHMOD : + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_result_list[$p_options_list[$i]] = $p_options_list[$i+1]; + $i++; + break; + + // ----- Look for options that request a call-back + case PCLZIP_CB_PRE_EXTRACT : + case PCLZIP_CB_POST_EXTRACT : + case PCLZIP_CB_PRE_ADD : + case PCLZIP_CB_POST_ADD : + /* for futur use + case PCLZIP_CB_PRE_DELETE : + case PCLZIP_CB_POST_DELETE : + case PCLZIP_CB_PRE_LIST : + case PCLZIP_CB_POST_LIST : + */ + // ----- Check the number of parameters + if (($i+1) >= $p_size) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_OPTION_VALUE, "Missing parameter value for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Get the value + $v_function_name = $p_options_list[$i+1]; + + // ----- Check that the value is a valid existing function + if (!function_exists($v_function_name)) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_OPTION_VALUE, "Function '".$v_function_name."()' is not an existing function for option '".PclZipUtilOptionText($p_options_list[$i])."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Set the attribute + $v_result_list[$p_options_list[$i]] = $v_function_name; + $i++; + break; + + default : + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Unknown parameter '" + .$p_options_list[$i]."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Next options + $i++; + } + + // ----- Look for mandatory options + if ($v_requested_options !== false) { + for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { + // ----- Look for mandatory option + if ($v_requested_options[$key] == 'mandatory') { + // ----- Look if present + if (!isset($v_result_list[$key])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); + + // ----- Return + return PclZip::errorCode(); + } + } + } + } + + // ----- Look for default values + if (!isset($v_result_list[PCLZIP_OPT_TEMP_FILE_THRESHOLD])) { + + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privOptionDefaultThreshold() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privOptionDefaultThreshold(&$p_options) + { + $v_result=1; + + if (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + || isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) { + return $v_result; + } + + // ----- Get 'memory_limit' configuration value + $v_memory_limit = ini_get('memory_limit'); + $v_memory_limit = trim($v_memory_limit); + $last = strtolower(substr($v_memory_limit, -1)); + + if($last == 'g') + //$v_memory_limit = $v_memory_limit*1024*1024*1024; + $v_memory_limit = $v_memory_limit*1073741824; + if($last == 'm') + //$v_memory_limit = $v_memory_limit*1024*1024; + $v_memory_limit = $v_memory_limit*1048576; + if($last == 'k') + $v_memory_limit = $v_memory_limit*1024; + + $p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] = floor($v_memory_limit*PCLZIP_TEMPORARY_FILE_RATIO); + + + // ----- Sanity check : No threshold if value lower than 1M + if ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] < 1048576) { + unset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privFileDescrParseAtt() + // Description : + // Parameters : + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privFileDescrParseAtt(&$p_file_list, &$p_filedescr, $v_options, $v_requested_options=false) + { + $v_result=1; + + // ----- For each file in the list check the attributes + foreach ($p_file_list as $v_key => $v_value) { + + // ----- Check if the option is supported + if (!isset($v_requested_options[$v_key])) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file attribute '".$v_key."' for this file"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for attribute + switch ($v_key) { + case PCLZIP_ATT_FILE_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['filename'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['filename'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + break; + + case PCLZIP_ATT_FILE_NEW_SHORT_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['new_short_name'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['new_short_name'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty short filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + break; + + case PCLZIP_ATT_FILE_NEW_FULL_NAME : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['new_full_name'] = PclZipUtilPathReduction($v_value); + + if ($p_filedescr['new_full_name'] == '') { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid empty full filename for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + break; + + // ----- Look for options that takes a string + case PCLZIP_ATT_FILE_COMMENT : + if (!is_string($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". String expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['comment'] = $v_value; + break; + + case PCLZIP_ATT_FILE_MTIME : + if (!is_integer($v_value)) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE, "Invalid type ".gettype($v_value).". Integer expected for attribute '".PclZipUtilOptionText($v_key)."'"); + return PclZip::errorCode(); + } + + $p_filedescr['mtime'] = $v_value; + break; + + case PCLZIP_ATT_FILE_CONTENT : + $p_filedescr['content'] = $v_value; + break; + + default : + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, + "Unknown parameter '".$v_key."'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for mandatory options + if ($v_requested_options !== false) { + for ($key=reset($v_requested_options); $key=key($v_requested_options); $key=next($v_requested_options)) { + // ----- Look for mandatory option + if ($v_requested_options[$key] == 'mandatory') { + // ----- Look if present + if (!isset($p_file_list[$key])) { + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Missing mandatory parameter ".PclZipUtilOptionText($key)."(".$key.")"); + return PclZip::errorCode(); + } + } + } + } + + // end foreach + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privFileDescrExpand() + // Description : + // This method look for each item of the list to see if its a file, a folder + // or a string to be added as file. For any other type of files (link, other) + // just ignore the item. + // Then prepare the information that will be stored for that file. + // When its a folder, expand the folder with all the files that are in that + // folder (recursively). + // Parameters : + // Return Values : + // 1 on success. + // 0 on failure. + // -------------------------------------------------------------------------------- + function privFileDescrExpand(&$p_filedescr_list, &$p_options) + { + $v_result=1; + + // ----- Create a result list + $v_result_list = array(); + + // ----- Look each entry + for ($i=0; $i<sizeof($p_filedescr_list); $i++) { + + // ----- Get filedescr + $v_descr = $p_filedescr_list[$i]; + + // ----- Reduce the filename + $v_descr['filename'] = PclZipUtilTranslateWinPath($v_descr['filename'], false); + $v_descr['filename'] = PclZipUtilPathReduction($v_descr['filename']); + + // ----- Look for real file or folder + if (file_exists($v_descr['filename'])) { + if (@is_file($v_descr['filename'])) { + $v_descr['type'] = 'file'; + } + else if (@is_dir($v_descr['filename'])) { + $v_descr['type'] = 'folder'; + } + else if (@is_link($v_descr['filename'])) { + // skip + continue; + } + else { + // skip + continue; + } + } + + // ----- Look for string added as file + else if (isset($v_descr['content'])) { + $v_descr['type'] = 'virtual_file'; + } + + // ----- Missing file + else { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$v_descr['filename']."' does not exist"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Calculate the stored filename + $this->privCalculateStoredFilename($v_descr, $p_options); + + // ----- Add the descriptor in result list + $v_result_list[sizeof($v_result_list)] = $v_descr; + + // ----- Look for folder + if ($v_descr['type'] == 'folder') { + // ----- List of items in folder + $v_dirlist_descr = array(); + $v_dirlist_nb = 0; + if ($v_folder_handler = @opendir($v_descr['filename'])) { + while (($v_item_handler = @readdir($v_folder_handler)) !== false) { + + // ----- Skip '.' and '..' + if (($v_item_handler == '.') || ($v_item_handler == '..')) { + continue; + } + + // ----- Compose the full filename + $v_dirlist_descr[$v_dirlist_nb]['filename'] = $v_descr['filename'].'/'.$v_item_handler; + + // ----- Look for different stored filename + // Because the name of the folder was changed, the name of the + // files/sub-folders also change + if (($v_descr['stored_filename'] != $v_descr['filename']) + && (!isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]))) { + if ($v_descr['stored_filename'] != '') { + $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_descr['stored_filename'].'/'.$v_item_handler; + } + else { + $v_dirlist_descr[$v_dirlist_nb]['new_full_name'] = $v_item_handler; + } + } + + $v_dirlist_nb++; + } + + @closedir($v_folder_handler); + } + else { + // TBC : unable to open folder in read mode + } + + // ----- Expand each element of the list + if ($v_dirlist_nb != 0) { + // ----- Expand + if (($v_result = $this->privFileDescrExpand($v_dirlist_descr, $p_options)) != 1) { + return $v_result; + } + + // ----- Concat the resulting list + $v_result_list = array_merge($v_result_list, $v_dirlist_descr); + } + else { + } + + // ----- Free local array + unset($v_dirlist_descr); + } + } + + // ----- Get the result list + $p_filedescr_list = $v_result_list; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCreate() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privCreate($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the file in write mode + if (($v_result = $this->privOpenFd('wb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Add the list of files + $v_result = $this->privAddList($p_filedescr_list, $p_result_list, $p_options); + + // ----- Close + $this->privCloseFd(); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAdd() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAdd($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Look if the archive exists or is empty + if ((!is_file($this->zipname)) || (filesize($this->zipname) == 0)) + { + + // ----- Do a create + $v_result = $this->privCreate($p_filedescr_list, $p_result_list, $p_options); + + // ----- Return + return $v_result; + } + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) + { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = $v_central_dir['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Swap the file descriptor + // Here is a trick : I swap the temporary fd with the zip fd, in order to use + // the following methods on the temporary fil and not the real archive + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Add the files + $v_header_list = array(); + if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) + { + fclose($v_zip_temp_fd); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($this->zip_fd); + + // ----- Copy the block of file headers from the old archive + $v_size = $v_central_dir['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_zip_temp_fd, $v_read_size); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Create the Central Dir files header + for ($i=0, $v_count=0; $i<sizeof($v_header_list); $i++) + { + // ----- Create the file header + if ($v_header_list[$i]['status'] == 'ok') { + if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) { + fclose($v_zip_temp_fd); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + $v_count++; + } + + // ----- Transform the header to a 'usable' info + $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + // ----- Zip file comment + $v_comment = $v_central_dir['comment']; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + if (isset($p_options[PCLZIP_OPT_ADD_COMMENT])) { + $v_comment = $v_comment.$p_options[PCLZIP_OPT_ADD_COMMENT]; + } + if (isset($p_options[PCLZIP_OPT_PREPEND_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_PREPEND_COMMENT].$v_comment; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($this->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_count+$v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1) + { + // ----- Reset the file list + unset($v_header_list); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + + // ----- Swap back the file descriptor + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Close + $this->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privOpenFd() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privOpenFd($p_mode) + { + $v_result=1; + + // ----- Look if already open + if ($this->zip_fd != 0) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Zip file \''.$this->zipname.'\' already open'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, $p_mode)) == 0) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in '.$p_mode.' mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCloseFd() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privCloseFd() + { + $v_result=1; + + if ($this->zip_fd != 0) + @fclose($this->zip_fd); + $this->zip_fd = 0; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddList() + // Description : + // $p_add_dir and $p_remove_dir will give the ability to memorize a path which is + // different from the real path of the file. This is usefull if you want to have PclTar + // running in any directory, and memorize relative path from an other directory. + // Parameters : + // $p_list : An array containing the file or directory names to add in the tar + // $p_result_list : list of added files with their properties (specially the status field) + // $p_add_dir : Path to add in the filename path archived + // $p_remove_dir : Path to remove in the filename path archived + // Return Values : + // -------------------------------------------------------------------------------- +// function privAddList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_options) + function privAddList($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + + // ----- Add the files + $v_header_list = array(); + if (($v_result = $this->privAddFileList($p_filedescr_list, $v_header_list, $p_options)) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($this->zip_fd); + + // ----- Create the Central Dir files header + for ($i=0,$v_count=0; $i<sizeof($v_header_list); $i++) + { + // ----- Create the file header + if ($v_header_list[$i]['status'] == 'ok') { + if (($v_result = $this->privWriteCentralFileHeader($v_header_list[$i])) != 1) { + // ----- Return + return $v_result; + } + $v_count++; + } + + // ----- Transform the header to a 'usable' info + $this->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + // ----- Zip file comment + $v_comment = ''; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($this->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1) + { + // ----- Reset the file list + unset($v_header_list); + + // ----- Return + return $v_result; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFileList() + // Description : + // Parameters : + // $p_filedescr_list : An array containing the file description + // or directory names to add in the zip + // $p_result_list : list of added files with their properties (specially the status field) + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFileList($p_filedescr_list, &$p_result_list, &$p_options) + { + $v_result=1; + $v_header = array(); + + // ----- Recuperate the current number of elt in list + $v_nb = sizeof($p_result_list); + + // ----- Loop on the files + for ($j=0; ($j<sizeof($p_filedescr_list)) && ($v_result==1); $j++) { + // ----- Format the filename + $p_filedescr_list[$j]['filename'] + = PclZipUtilTranslateWinPath($p_filedescr_list[$j]['filename'], false); + + + // ----- Skip empty file names + // TBC : Can this be possible ? not checked in DescrParseAtt ? + if ($p_filedescr_list[$j]['filename'] == "") { + continue; + } + + // ----- Check the filename + if ( ($p_filedescr_list[$j]['type'] != 'virtual_file') + && (!file_exists($p_filedescr_list[$j]['filename']))) { + PclZip::privErrorLog(PCLZIP_ERR_MISSING_FILE, "File '".$p_filedescr_list[$j]['filename']."' does not exist"); + return PclZip::errorCode(); + } + + // ----- Look if it is a file or a dir with no all path remove option + // or a dir with all its path removed +// if ( (is_file($p_filedescr_list[$j]['filename'])) +// || ( is_dir($p_filedescr_list[$j]['filename']) + if ( ($p_filedescr_list[$j]['type'] == 'file') + || ($p_filedescr_list[$j]['type'] == 'virtual_file') + || ( ($p_filedescr_list[$j]['type'] == 'folder') + && ( !isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH]) + || !$p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) + ) { + + // ----- Add the file + $v_result = $this->privAddFile($p_filedescr_list[$j], $v_header, + $p_options); + if ($v_result != 1) { + return $v_result; + } + + // ----- Store the file infos + $p_result_list[$v_nb++] = $v_header; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFile($p_filedescr, &$p_header, &$p_options) + { + $v_result=1; + + // ----- Working variable + $p_filename = $p_filedescr['filename']; + + // TBC : Already done in the fileAtt check ... ? + if ($p_filename == "") { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_PARAMETER, "Invalid file list parameter (invalid or empty list)"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for a stored different filename + /* TBC : Removed + if (isset($p_filedescr['stored_filename'])) { + $v_stored_filename = $p_filedescr['stored_filename']; + } + else { + $v_stored_filename = $p_filedescr['stored_filename']; + } + */ + + // ----- Set the file properties + clearstatcache(); + $p_header['version'] = 20; + $p_header['version_extracted'] = 10; + $p_header['flag'] = 0; + $p_header['compression'] = 0; + $p_header['crc'] = 0; + $p_header['compressed_size'] = 0; + $p_header['filename_len'] = strlen($p_filename); + $p_header['extra_len'] = 0; + $p_header['disk'] = 0; + $p_header['internal'] = 0; + $p_header['offset'] = 0; + $p_header['filename'] = $p_filename; +// TBC : Removed $p_header['stored_filename'] = $v_stored_filename; + $p_header['stored_filename'] = $p_filedescr['stored_filename']; + $p_header['extra'] = ''; + $p_header['status'] = 'ok'; + $p_header['index'] = -1; + + // ----- Look for regular file + if ($p_filedescr['type']=='file') { + $p_header['external'] = 0x00000000; + $p_header['size'] = filesize($p_filename); + } + + // ----- Look for regular folder + else if ($p_filedescr['type']=='folder') { + $p_header['external'] = 0x00000010; + $p_header['mtime'] = filemtime($p_filename); + $p_header['size'] = filesize($p_filename); + } + + // ----- Look for virtual file + else if ($p_filedescr['type'] == 'virtual_file') { + $p_header['external'] = 0x00000000; + $p_header['size'] = strlen($p_filedescr['content']); + } + + + // ----- Look for filetime + if (isset($p_filedescr['mtime'])) { + $p_header['mtime'] = $p_filedescr['mtime']; + } + else if ($p_filedescr['type'] == 'virtual_file') { + $p_header['mtime'] = time(); + } + else { + $p_header['mtime'] = filemtime($p_filename); + } + + // ------ Look for file comment + if (isset($p_filedescr['comment'])) { + $p_header['comment_len'] = strlen($p_filedescr['comment']); + $p_header['comment'] = $p_filedescr['comment']; + } + else { + $p_header['comment_len'] = 0; + $p_header['comment'] = ''; + } + + // ----- Look for pre-add callback + if (isset($p_options[PCLZIP_CB_PRE_ADD])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_header, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_ADD].'(PCLZIP_CB_PRE_ADD, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_ADD](PCLZIP_CB_PRE_ADD, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_header['status'] = "skipped"; + $v_result = 1; + } + + // ----- Update the informations + // Only some fields can be modified + if ($p_header['stored_filename'] != $v_local_header['stored_filename']) { + $p_header['stored_filename'] = PclZipUtilPathReduction($v_local_header['stored_filename']); + } + } + + // ----- Look for empty stored filename + if ($p_header['stored_filename'] == "") { + $p_header['status'] = "filtered"; + } + + // ----- Check the path length + if (strlen($p_header['stored_filename']) > 0xFF) { + $p_header['status'] = 'filename_too_long'; + } + + // ----- Look if no error, or file not skipped + if ($p_header['status'] == 'ok') { + + // ----- Look for a file + if ($p_filedescr['type'] == 'file') { + // ----- Look for using temporary file to zip + if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) + && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) + || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_header['size'])) ) ) { + $v_result = $this->privAddFileUsingTempFile($p_filedescr, $p_header, $p_options); + if ($v_result < PCLZIP_ERR_NO_ERROR) { + return $v_result; + } + } + + // ----- Use "in memory" zip algo + else { + + // ----- Open the source file + if (($v_file = @fopen($p_filename, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); + return PclZip::errorCode(); + } + + // ----- Read the file content + $v_content = @fread($v_file, $p_header['size']); + + // ----- Close the file + @fclose($v_file); + + // ----- Calculate the CRC + $p_header['crc'] = @crc32($v_content); + + // ----- Look for no compression + if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) { + // ----- Set header parameters + $p_header['compressed_size'] = $p_header['size']; + $p_header['compression'] = 0; + } + + // ----- Look for normal compression + else { + // ----- Compress the content + $v_content = @gzdeflate($v_content); + + // ----- Set header parameters + $p_header['compressed_size'] = strlen($v_content); + $p_header['compression'] = 8; + } + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + @fclose($v_file); + return $v_result; + } + + // ----- Write the compressed (or not) content + @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']); + + } + + } + + // ----- Look for a virtual file (a file from string) + else if ($p_filedescr['type'] == 'virtual_file') { + + $v_content = $p_filedescr['content']; + + // ----- Calculate the CRC + $p_header['crc'] = @crc32($v_content); + + // ----- Look for no compression + if ($p_options[PCLZIP_OPT_NO_COMPRESSION]) { + // ----- Set header parameters + $p_header['compressed_size'] = $p_header['size']; + $p_header['compression'] = 0; + } + + // ----- Look for normal compression + else { + // ----- Compress the content + $v_content = @gzdeflate($v_content); + + // ----- Set header parameters + $p_header['compressed_size'] = strlen($v_content); + $p_header['compression'] = 8; + } + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + @fclose($v_file); + return $v_result; + } + + // ----- Write the compressed (or not) content + @fwrite($this->zip_fd, $v_content, $p_header['compressed_size']); + } + + // ----- Look for a directory + else if ($p_filedescr['type'] == 'folder') { + // ----- Look for directory last '/' + if (@substr($p_header['stored_filename'], -1) != '/') { + $p_header['stored_filename'] .= '/'; + } + + // ----- Set the file properties + $p_header['size'] = 0; + //$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked + $p_header['external'] = 0x00000010; // Value for a folder : to be checked + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) + { + return $v_result; + } + } + } + + // ----- Look for post-add callback + if (isset($p_options[PCLZIP_CB_POST_ADD])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_header, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_ADD].'(PCLZIP_CB_POST_ADD, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_ADD](PCLZIP_CB_POST_ADD, $v_local_header); + if ($v_result == 0) { + // ----- Ignored + $v_result = 1; + } + + // ----- Update the informations + // Nothing can be modified + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privAddFileUsingTempFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privAddFileUsingTempFile($p_filedescr, &$p_header, &$p_options) + { + $v_result=PCLZIP_ERR_NO_ERROR; + + // ----- Working variable + $p_filename = $p_filedescr['filename']; + + + // ----- Open the source file + if (($v_file = @fopen($p_filename, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); + return PclZip::errorCode(); + } + + // ----- Creates a compressed temporary file + $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz'; + if (($v_file_compressed = @gzopen($v_gzip_temp_name, "wb")) == 0) { + fclose($v_file); + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode'); + return PclZip::errorCode(); + } + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = filesize($p_filename); + while ($v_size != 0) { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_file, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @gzputs($v_file_compressed, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close the file + @fclose($v_file); + @gzclose($v_file_compressed); + + // ----- Check the minimum file size + if (filesize($v_gzip_temp_name) < 18) { + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'gzip temporary file \''.$v_gzip_temp_name.'\' has invalid filesize - should be minimum 18 bytes'); + return PclZip::errorCode(); + } + + // ----- Extract the compressed attributes + if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + // ----- Read the gzip file header + $v_binary_data = @fread($v_file_compressed, 10); + $v_data_header = unpack('a1id1/a1id2/a1cm/a1flag/Vmtime/a1xfl/a1os', $v_binary_data); + + // ----- Check some parameters + $v_data_header['os'] = bin2hex($v_data_header['os']); + + // ----- Read the gzip file footer + @fseek($v_file_compressed, filesize($v_gzip_temp_name)-8); + $v_binary_data = @fread($v_file_compressed, 8); + $v_data_footer = unpack('Vcrc/Vcompressed_size', $v_binary_data); + + // ----- Set the attributes + $p_header['compression'] = ord($v_data_header['cm']); + //$p_header['mtime'] = $v_data_header['mtime']; + $p_header['crc'] = $v_data_footer['crc']; + $p_header['compressed_size'] = filesize($v_gzip_temp_name)-18; + + // ----- Close the file + @fclose($v_file_compressed); + + // ----- Call the header generation + if (($v_result = $this->privWriteFileHeader($p_header)) != 1) { + return $v_result; + } + + // ----- Add the compressed data + if (($v_file_compressed = @fopen($v_gzip_temp_name, "rb")) == 0) + { + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + fseek($v_file_compressed, 10); + $v_size = $p_header['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($v_file_compressed, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close the file + @fclose($v_file_compressed); + + // ----- Unlink the temporary file + @unlink($v_gzip_temp_name); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCalculateStoredFilename() + // Description : + // Based on file descriptor properties and global options, this method + // calculate the filename that will be stored in the archive. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privCalculateStoredFilename(&$p_filedescr, &$p_options) + { + $v_result=1; + + // ----- Working variables + $p_filename = $p_filedescr['filename']; + if (isset($p_options[PCLZIP_OPT_ADD_PATH])) { + $p_add_dir = $p_options[PCLZIP_OPT_ADD_PATH]; + } + else { + $p_add_dir = ''; + } + if (isset($p_options[PCLZIP_OPT_REMOVE_PATH])) { + $p_remove_dir = $p_options[PCLZIP_OPT_REMOVE_PATH]; + } + else { + $p_remove_dir = ''; + } + if (isset($p_options[PCLZIP_OPT_REMOVE_ALL_PATH])) { + $p_remove_all_dir = $p_options[PCLZIP_OPT_REMOVE_ALL_PATH]; + } + else { + $p_remove_all_dir = 0; + } + + + // ----- Look for full name change + if (isset($p_filedescr['new_full_name'])) { + // ----- Remove drive letter if any + $v_stored_filename = PclZipUtilTranslateWinPath($p_filedescr['new_full_name']); + } + + // ----- Look for path and/or short name change + else { + + // ----- Look for short name change + // Its when we cahnge just the filename but not the path + if (isset($p_filedescr['new_short_name'])) { + $v_path_info = pathinfo($p_filename); + $v_dir = ''; + if ($v_path_info['dirname'] != '') { + $v_dir = $v_path_info['dirname'].'/'; + } + $v_stored_filename = $v_dir.$p_filedescr['new_short_name']; + } + else { + // ----- Calculate the stored filename + $v_stored_filename = $p_filename; + } + + // ----- Look for all path to remove + if ($p_remove_all_dir) { + $v_stored_filename = basename($p_filename); + } + // ----- Look for partial path remove + else if ($p_remove_dir != "") { + if (substr($p_remove_dir, -1) != '/') + $p_remove_dir .= "/"; + + if ( (substr($p_filename, 0, 2) == "./") + || (substr($p_remove_dir, 0, 2) == "./")) { + + if ( (substr($p_filename, 0, 2) == "./") + && (substr($p_remove_dir, 0, 2) != "./")) { + $p_remove_dir = "./".$p_remove_dir; + } + if ( (substr($p_filename, 0, 2) != "./") + && (substr($p_remove_dir, 0, 2) == "./")) { + $p_remove_dir = substr($p_remove_dir, 2); + } + } + + $v_compare = PclZipUtilPathInclusion($p_remove_dir, + $v_stored_filename); + if ($v_compare > 0) { + if ($v_compare == 2) { + $v_stored_filename = ""; + } + else { + $v_stored_filename = substr($v_stored_filename, + strlen($p_remove_dir)); + } + } + } + + // ----- Remove drive letter if any + $v_stored_filename = PclZipUtilTranslateWinPath($v_stored_filename); + + // ----- Look for path to add + if ($p_add_dir != "") { + if (substr($p_add_dir, -1) == "/") + $v_stored_filename = $p_add_dir.$v_stored_filename; + else + $v_stored_filename = $p_add_dir."/".$v_stored_filename; + } + } + + // ----- Filename (reduce the path of stored name) + $v_stored_filename = PclZipUtilPathReduction($v_stored_filename); + $p_filedescr['stored_filename'] = $v_stored_filename; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteFileHeader(&$p_header) + { + $v_result=1; + + // ----- Store the offset position of the file + $p_header['offset'] = ftell($this->zip_fd); + + // ----- Transform UNIX mtime to DOS format mdate/mtime + $v_date = getdate($p_header['mtime']); + $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; + $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; + + // ----- Packed data + $v_binary_data = pack("VvvvvvVVVvv", 0x04034b50, + $p_header['version_extracted'], $p_header['flag'], + $p_header['compression'], $v_mtime, $v_mdate, + $p_header['crc'], $p_header['compressed_size'], + $p_header['size'], + strlen($p_header['stored_filename']), + $p_header['extra_len']); + + // ----- Write the first 148 bytes of the header in the archive + fputs($this->zip_fd, $v_binary_data, 30); + + // ----- Write the variable fields + if (strlen($p_header['stored_filename']) != 0) + { + fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); + } + if ($p_header['extra_len'] != 0) + { + fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteCentralFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteCentralFileHeader(&$p_header) + { + $v_result=1; + + // TBC + //for(reset($p_header); $key = key($p_header); next($p_header)) { + //} + + // ----- Transform UNIX mtime to DOS format mdate/mtime + $v_date = getdate($p_header['mtime']); + $v_mtime = ($v_date['hours']<<11) + ($v_date['minutes']<<5) + $v_date['seconds']/2; + $v_mdate = (($v_date['year']-1980)<<9) + ($v_date['mon']<<5) + $v_date['mday']; + + + // ----- Packed data + $v_binary_data = pack("VvvvvvvVVVvvvvvVV", 0x02014b50, + $p_header['version'], $p_header['version_extracted'], + $p_header['flag'], $p_header['compression'], + $v_mtime, $v_mdate, $p_header['crc'], + $p_header['compressed_size'], $p_header['size'], + strlen($p_header['stored_filename']), + $p_header['extra_len'], $p_header['comment_len'], + $p_header['disk'], $p_header['internal'], + $p_header['external'], $p_header['offset']); + + // ----- Write the 42 bytes of the header in the zip file + fputs($this->zip_fd, $v_binary_data, 46); + + // ----- Write the variable fields + if (strlen($p_header['stored_filename']) != 0) + { + fputs($this->zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); + } + if ($p_header['extra_len'] != 0) + { + fputs($this->zip_fd, $p_header['extra'], $p_header['extra_len']); + } + if ($p_header['comment_len'] != 0) + { + fputs($this->zip_fd, $p_header['comment'], $p_header['comment_len']); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privWriteCentralHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privWriteCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment) + { + $v_result=1; + + // ----- Packed data + $v_binary_data = pack("VvvvvVVv", 0x06054b50, 0, 0, $p_nb_entries, + $p_nb_entries, $p_size, + $p_offset, strlen($p_comment)); + + // ----- Write the 22 bytes of the header in the zip file + fputs($this->zip_fd, $v_binary_data, 22); + + // ----- Write the variable fields + if (strlen($p_comment) != 0) + { + fputs($this->zip_fd, $p_comment, strlen($p_comment)); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privList() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privList(&$p_list) + { + $v_result=1; + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Open the zip file + if (($this->zip_fd = @fopen($this->zipname, 'rb')) == 0) + { + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \''.$this->zipname.'\' in binary read mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Go to beginning of Central Dir + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_central_dir['offset'])) + { + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read each entry + for ($i=0; $i<$v_central_dir['entries']; $i++) + { + // ----- Read the file header + if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + $v_header['index'] = $i; + + // ----- Get the only interesting attributes + $this->privConvertHeader2FileInfo($v_header, $p_list[$i]); + unset($v_header); + } + + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Magic quotes trick + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privConvertHeader2FileInfo() + // Description : + // This function takes the file informations from the central directory + // entries and extract the interesting parameters that will be given back. + // The resulting file infos are set in the array $p_info + // $p_info['filename'] : Filename with full path. Given by user (add), + // extracted in the filesystem (extract). + // $p_info['stored_filename'] : Stored filename in the archive. + // $p_info['size'] = Size of the file. + // $p_info['compressed_size'] = Compressed size of the file. + // $p_info['mtime'] = Last modification date of the file. + // $p_info['comment'] = Comment associated with the file. + // $p_info['folder'] = true/false : indicates if the entry is a folder or not. + // $p_info['status'] = status of the action on the file. + // $p_info['crc'] = CRC of the file content. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privConvertHeader2FileInfo($p_header, &$p_info) + { + $v_result=1; + + // ----- Get the interesting attributes + $v_temp_path = PclZipUtilPathReduction($p_header['filename']); + $p_info['filename'] = $v_temp_path; + $v_temp_path = PclZipUtilPathReduction($p_header['stored_filename']); + $p_info['stored_filename'] = $v_temp_path; + $p_info['size'] = $p_header['size']; + $p_info['compressed_size'] = $p_header['compressed_size']; + $p_info['mtime'] = $p_header['mtime']; + $p_info['comment'] = $p_header['comment']; + $p_info['folder'] = (($p_header['external']&0x00000010)==0x00000010); + $p_info['index'] = $p_header['index']; + $p_info['status'] = $p_header['status']; + $p_info['crc'] = $p_header['crc']; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractByRule() + // Description : + // Extract a file or directory depending of rules (by index, by name, ...) + // Parameters : + // $p_file_list : An array where will be placed the properties of each + // extracted file + // $p_path : Path to add while writing the extracted files + // $p_remove_path : Path to remove (from the file memorized path) while writing the + // extracted files. If the path does not match the file path, + // the file is extracted with its memorized path. + // $p_remove_path does not apply to 'list' mode. + // $p_path and $p_remove_path are commulative. + // Return Values : + // 1 on success,0 or less on error (see error code list) + // -------------------------------------------------------------------------------- + function privExtractByRule(&$p_file_list, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) + { + $v_result=1; + + // ----- Magic quotes trick + $this->privDisableMagicQuotes(); + + // ----- Check the path + if ( ($p_path == "") + || ( (substr($p_path, 0, 1) != "/") + && (substr($p_path, 0, 3) != "../") + && (substr($p_path,1,2)!=":/"))) + $p_path = "./".$p_path; + + // ----- Reduce the path last (and duplicated) '/' + if (($p_path != "./") && ($p_path != "/")) + { + // ----- Look for the path end '/' + while (substr($p_path, -1) == "/") + { + $p_path = substr($p_path, 0, strlen($p_path)-1); + } + } + + // ----- Look for path to remove format (should end by /) + if (($p_remove_path != "") && (substr($p_remove_path, -1) != '/')) + { + $p_remove_path .= '/'; + } + $p_remove_path_size = strlen($p_remove_path); + + // ----- Open the zip file + if (($v_result = $this->privOpenFd('rb')) != 1) + { + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Start at beginning of Central Dir + $v_pos_entry = $v_central_dir['offset']; + + // ----- Read each entry + $j_start = 0; + for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) + { + + // ----- Read next Central dir entry + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_pos_entry)) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the file header + $v_header = array(); + if (($v_result = $this->privReadCentralFileHeader($v_header)) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Store the index + $v_header['index'] = $i; + + // ----- Store the file position + $v_pos_entry = ftell($this->zip_fd); + + // ----- Look for the specific extract rules + $v_extract = false; + + // ----- Look for extract by name rule + if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) + && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { + + // ----- Look if the filename is in the list + for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_extract); $j++) { + + // ----- Look for a directory + if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") { + + // ----- Look if the directory is in the filename path + if ( (strlen($v_header['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) + && (substr($v_header['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_extract = true; + } + } + // ----- Look for a filename + elseif ($v_header['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { + $v_extract = true; + } + } + } + + // ----- Look for extract by ereg rule + // ereg() is deprecated with PHP 5.3 + /* + else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) + && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { + + if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header['stored_filename'])) { + $v_extract = true; + } + } + */ + + // ----- Look for extract by preg rule + else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) + && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { + + if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header['stored_filename'])) { + $v_extract = true; + } + } + + // ----- Look for extract by index rule + else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) + && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { + + // ----- Look if the index is in the list + for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_extract); $j++) { + + if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { + $v_extract = true; + } + if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { + $j_start = $j+1; + } + + if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { + break; + } + } + } + + // ----- Look for no rule, which means extract all the archive + else { + $v_extract = true; + } + + // ----- Check compression method + if ( ($v_extract) + && ( ($v_header['compression'] != 8) + && ($v_header['compression'] != 0))) { + $v_header['status'] = 'unsupported_compression'; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_COMPRESSION, + "Filename '".$v_header['stored_filename']."' is " + ."compressed by an unsupported compression " + ."method (".$v_header['compression'].") "); + + return PclZip::errorCode(); + } + } + + // ----- Check encrypted files + if (($v_extract) && (($v_header['flag'] & 1) == 1)) { + $v_header['status'] = 'unsupported_encryption'; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + $this->privSwapBackMagicQuotes(); + + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, + "Unsupported encryption for " + ." filename '".$v_header['stored_filename'] + ."'"); + + return PclZip::errorCode(); + } + } + + // ----- Look for real extraction + if (($v_extract) && ($v_header['status'] != 'ok')) { + $v_result = $this->privConvertHeader2FileInfo($v_header, + $p_file_list[$v_nb_extracted++]); + if ($v_result != 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + $v_extract = false; + } + + // ----- Look for real extraction + if ($v_extract) + { + + // ----- Go to the file position + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_header['offset'])) + { + // ----- Close the zip file + $this->privCloseFd(); + + $this->privSwapBackMagicQuotes(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Look for extraction as string + if ($p_options[PCLZIP_OPT_EXTRACT_AS_STRING]) { + + $v_string = ''; + + // ----- Extracting the file + $v_result1 = $this->privExtractFileAsString($v_header, $v_string, $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Set the file content + $p_file_list[$v_nb_extracted]['content'] = $v_string; + + // ----- Next extracted file + $v_nb_extracted++; + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + // ----- Look for extraction in standard output + elseif ( (isset($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) + && ($p_options[PCLZIP_OPT_EXTRACT_IN_OUTPUT])) { + // ----- Extracting the file in standard output + $v_result1 = $this->privExtractFileInOutput($v_header, $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result; + } + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + // ----- Look for normal extraction + else { + // ----- Extracting the file + $v_result1 = $this->privExtractFile($v_header, + $p_path, $p_remove_path, + $p_remove_all_path, + $p_options); + if ($v_result1 < 1) { + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + return $v_result1; + } + + // ----- Get the only interesting attributes + if (($v_result = $this->privConvertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + return $v_result; + } + + // ----- Look for user callback abort + if ($v_result1 == 2) { + break; + } + } + } + } + + // ----- Close the zip file + $this->privCloseFd(); + $this->privSwapBackMagicQuotes(); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFile() + // Description : + // Parameters : + // Return Values : + // + // 1 : ... ? + // PCLZIP_ERR_USER_ABORTED(2) : User ask for extraction stop in callback + // -------------------------------------------------------------------------------- + function privExtractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_options) + { + $v_result=1; + + // ----- Read the file header + if (($v_result = $this->privReadFileHeader($v_header)) != 1) + { + // ----- Return + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for all path to remove + if ($p_remove_all_path == true) { + // ----- Look for folder entry that not need to be extracted + if (($p_entry['external']&0x00000010)==0x00000010) { + + $p_entry['status'] = "filtered"; + + return $v_result; + } + + // ----- Get the basename of the path + $p_entry['filename'] = basename($p_entry['filename']); + } + + // ----- Look for path to remove + else if ($p_remove_path != "") + { + if (PclZipUtilPathInclusion($p_remove_path, $p_entry['filename']) == 2) + { + + // ----- Change the file status + $p_entry['status'] = "filtered"; + + // ----- Return + return $v_result; + } + + $p_remove_path_size = strlen($p_remove_path); + if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) + { + + // ----- Remove the path + $p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size); + + } + } + + // ----- Add the path + if ($p_path != '') { + $p_entry['filename'] = $p_path."/".$p_entry['filename']; + } + + // ----- Check a base_dir_restriction + if (isset($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION])) { + $v_inclusion + = PclZipUtilPathInclusion($p_options[PCLZIP_OPT_EXTRACT_DIR_RESTRICTION], + $p_entry['filename']); + if ($v_inclusion == 0) { + + PclZip::privErrorLog(PCLZIP_ERR_DIRECTORY_RESTRICTION, + "Filename '".$p_entry['filename']."' is " + ."outside PCLZIP_OPT_EXTRACT_DIR_RESTRICTION"); + + return PclZip::errorCode(); + } + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Look for specific actions while the file exist + if (file_exists($p_entry['filename'])) + { + + // ----- Look if file is a directory + if (is_dir($p_entry['filename'])) + { + + // ----- Change the file status + $p_entry['status'] = "already_a_directory"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_ALREADY_A_DIRECTORY, + "Filename '".$p_entry['filename']."' is " + ."already used by an existing directory"); + + return PclZip::errorCode(); + } + } + // ----- Look if file is write protected + else if (!is_writeable($p_entry['filename'])) + { + + // ----- Change the file status + $p_entry['status'] = "write_protected"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, + "Filename '".$p_entry['filename']."' exists " + ."and is write protected"); + + return PclZip::errorCode(); + } + } + + // ----- Look if the extracted file is older + else if (filemtime($p_entry['filename']) > $p_entry['mtime']) + { + // ----- Change the file status + if ( (isset($p_options[PCLZIP_OPT_REPLACE_NEWER])) + && ($p_options[PCLZIP_OPT_REPLACE_NEWER]===true)) { + } + else { + $p_entry['status'] = "newer_exist"; + + // ----- Look for PCLZIP_OPT_STOP_ON_ERROR + // For historical reason first PclZip implementation does not stop + // when this kind of error occurs. + if ( (isset($p_options[PCLZIP_OPT_STOP_ON_ERROR])) + && ($p_options[PCLZIP_OPT_STOP_ON_ERROR]===true)) { + + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, + "Newer version of '".$p_entry['filename']."' exists " + ."and option PCLZIP_OPT_REPLACE_NEWER is not selected"); + + return PclZip::errorCode(); + } + } + } + else { + } + } + + // ----- Check the directory availability and create it if necessary + else { + if ((($p_entry['external']&0x00000010)==0x00000010) || (substr($p_entry['filename'], -1) == '/')) + $v_dir_to_check = $p_entry['filename']; + else if (!strstr($p_entry['filename'], "/")) + $v_dir_to_check = ""; + else + $v_dir_to_check = dirname($p_entry['filename']); + + if (($v_result = $this->privDirCheck($v_dir_to_check, (($p_entry['external']&0x00000010)==0x00000010))) != 1) { + + // ----- Change the file status + $p_entry['status'] = "path_creation_fail"; + + // ----- Return + //return $v_result; + $v_result = 1; + } + } + } + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) + { + // ----- Look for not compressed file + if ($p_entry['compression'] == 0) { + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) + { + + // ----- Change the file status + $p_entry['status'] = "write_error"; + + // ----- Return + return $v_result; + } + + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + /* Try to speed up the code + $v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_binary_data, $v_read_size); + */ + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Closing the destination file + fclose($v_dest_file); + + // ----- Change the file mtime + touch($p_entry['filename'], $p_entry['mtime']); + + + } + else { + // ----- TBC + // Need to be finished + if (($p_entry['flag'] & 1) == 1) { + PclZip::privErrorLog(PCLZIP_ERR_UNSUPPORTED_ENCRYPTION, 'File \''.$p_entry['filename'].'\' is encrypted. Encrypted files are not supported.'); + return PclZip::errorCode(); + } + + + // ----- Look for using temporary file to unzip + if ( (!isset($p_options[PCLZIP_OPT_TEMP_FILE_OFF])) + && (isset($p_options[PCLZIP_OPT_TEMP_FILE_ON]) + || (isset($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD]) + && ($p_options[PCLZIP_OPT_TEMP_FILE_THRESHOLD] <= $p_entry['size'])) ) ) { + $v_result = $this->privExtractFileUsingTempFile($p_entry, $p_options); + if ($v_result < PCLZIP_ERR_NO_ERROR) { + return $v_result; + } + } + + // ----- Look for extract in memory + else { + + + // ----- Read the compressed file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + $v_file_content = @gzinflate($v_buffer); + unset($v_buffer); + if ($v_file_content === FALSE) { + + // ----- Change the file status + // TBC + $p_entry['status'] = "error"; + + return $v_result; + } + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { + + // ----- Change the file status + $p_entry['status'] = "write_error"; + + return $v_result; + } + + // ----- Write the uncompressed data + @fwrite($v_dest_file, $v_file_content, $p_entry['size']); + unset($v_file_content); + + // ----- Closing the destination file + @fclose($v_dest_file); + + } + + // ----- Change the file mtime + @touch($p_entry['filename'], $p_entry['mtime']); + } + + // ----- Look for chmod option + if (isset($p_options[PCLZIP_OPT_SET_CHMOD])) { + + // ----- Change the mode of the file + @chmod($p_entry['filename'], $p_options[PCLZIP_OPT_SET_CHMOD]); + } + + } + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileUsingTempFile() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileUsingTempFile(&$p_entry, &$p_options) + { + $v_result=1; + + // ----- Creates a temporary file + $v_gzip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.gz'; + if (($v_dest_file = @fopen($v_gzip_temp_name, "wb")) == 0) { + fclose($v_file); + PclZip::privErrorLog(PCLZIP_ERR_WRITE_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary write mode'); + return PclZip::errorCode(); + } + + + // ----- Write gz file format header + $v_binary_data = pack('va1a1Va1a1', 0x8b1f, Chr($p_entry['compression']), Chr(0x00), time(), Chr(0x00), Chr(3)); + @fwrite($v_dest_file, $v_binary_data, 10); + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['compressed_size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Write gz file format footer + $v_binary_data = pack('VV', $p_entry['crc'], $p_entry['size']); + @fwrite($v_dest_file, $v_binary_data, 8); + + // ----- Close the temporary file + @fclose($v_dest_file); + + // ----- Opening destination file + if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { + $p_entry['status'] = "write_error"; + return $v_result; + } + + // ----- Open the temporary gz file + if (($v_src_file = @gzopen($v_gzip_temp_name, 'rb')) == 0) { + @fclose($v_dest_file); + $p_entry['status'] = "read_error"; + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_gzip_temp_name.'\' in binary read mode'); + return PclZip::errorCode(); + } + + + // ----- Read the file by PCLZIP_READ_BLOCK_SIZE octets blocks + $v_size = $p_entry['size']; + while ($v_size != 0) { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($v_src_file, $v_read_size); + //$v_binary_data = pack('a'.$v_read_size, $v_buffer); + @fwrite($v_dest_file, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + @fclose($v_dest_file); + @gzclose($v_src_file); + + // ----- Delete the temporary file + @unlink($v_gzip_temp_name); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileInOutput() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileInOutput(&$p_entry, &$p_options) + { + $v_result=1; + + // ----- Read the file header + if (($v_result = $this->privReadFileHeader($v_header)) != 1) { + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + // ----- Trace + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) { + // ----- Look for not compressed file + if ($p_entry['compressed_size'] == $p_entry['size']) { + + // ----- Read the file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Send the file to the output + echo $v_buffer; + unset($v_buffer); + } + else { + + // ----- Read the compressed file in a buffer (one shot) + $v_buffer = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + $v_file_content = gzinflate($v_buffer); + unset($v_buffer); + + // ----- Send the file to the output + echo $v_file_content; + unset($v_file_content); + } + } + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privExtractFileAsString() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privExtractFileAsString(&$p_entry, &$p_string, &$p_options) + { + $v_result=1; + + // ----- Read the file header + $v_header = array(); + if (($v_result = $this->privReadFileHeader($v_header)) != 1) + { + // ----- Return + return $v_result; + } + + + // ----- Check that the file header is coherent with $p_entry info + if ($this->privCheckFileHeaders($v_header, $p_entry) != 1) { + // TBC + } + + // ----- Look for pre-extract callback + if (isset($p_options[PCLZIP_CB_PRE_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_PRE_EXTRACT].'(PCLZIP_CB_PRE_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_PRE_EXTRACT](PCLZIP_CB_PRE_EXTRACT, $v_local_header); + if ($v_result == 0) { + // ----- Change the file status + $p_entry['status'] = "skipped"; + $v_result = 1; + } + + // ----- Look for abort result + if ($v_result == 2) { + // ----- This status is internal and will be changed in 'skipped' + $p_entry['status'] = "aborted"; + $v_result = PCLZIP_ERR_USER_ABORTED; + } + + // ----- Update the informations + // Only some fields can be modified + $p_entry['filename'] = $v_local_header['filename']; + } + + + // ----- Look if extraction should be done + if ($p_entry['status'] == 'ok') { + + // ----- Do the extraction (if not a folder) + if (!(($p_entry['external']&0x00000010)==0x00000010)) { + // ----- Look for not compressed file + // if ($p_entry['compressed_size'] == $p_entry['size']) + if ($p_entry['compression'] == 0) { + + // ----- Reading the file + $p_string = @fread($this->zip_fd, $p_entry['compressed_size']); + } + else { + + // ----- Reading the file + $v_data = @fread($this->zip_fd, $p_entry['compressed_size']); + + // ----- Decompress the file + if (($p_string = @gzinflate($v_data)) === FALSE) { + // TBC + } + } + + // ----- Trace + } + else { + // TBC : error : can not extract a folder in a string + } + + } + + // ----- Change abort status + if ($p_entry['status'] == "aborted") { + $p_entry['status'] = "skipped"; + } + + // ----- Look for post-extract callback + elseif (isset($p_options[PCLZIP_CB_POST_EXTRACT])) { + + // ----- Generate a local information + $v_local_header = array(); + $this->privConvertHeader2FileInfo($p_entry, $v_local_header); + + // ----- Swap the content to header + $v_local_header['content'] = $p_string; + $p_string = ''; + + // ----- Call the callback + // Here I do not use call_user_func() because I need to send a reference to the + // header. +// eval('$v_result = '.$p_options[PCLZIP_CB_POST_EXTRACT].'(PCLZIP_CB_POST_EXTRACT, $v_local_header);'); + $v_result = $p_options[PCLZIP_CB_POST_EXTRACT](PCLZIP_CB_POST_EXTRACT, $v_local_header); + + // ----- Swap back the content to header + $p_string = $v_local_header['content']; + unset($v_local_header['content']); + + // ----- Look for abort result + if ($v_result == 2) { + $v_result = PCLZIP_ERR_USER_ABORTED; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadFileHeader(&$p_header) + { + $v_result=1; + + // ----- Read the 4 bytes signature + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] != 0x04034b50) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the first 42 bytes of the header + $v_binary_data = fread($this->zip_fd, 26); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 26) + { + $p_header['filename'] = ""; + $p_header['status'] = "invalid_header"; + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data); + + // ----- Get filename + $p_header['filename'] = fread($this->zip_fd, $v_data['filename_len']); + + // ----- Get extra_fields + if ($v_data['extra_len'] != 0) { + $p_header['extra'] = fread($this->zip_fd, $v_data['extra_len']); + } + else { + $p_header['extra'] = ''; + } + + // ----- Extract properties + $p_header['version_extracted'] = $v_data['version']; + $p_header['compression'] = $v_data['compression']; + $p_header['size'] = $v_data['size']; + $p_header['compressed_size'] = $v_data['compressed_size']; + $p_header['crc'] = $v_data['crc']; + $p_header['flag'] = $v_data['flag']; + $p_header['filename_len'] = $v_data['filename_len']; + + // ----- Recuperate date in UNIX format + $p_header['mdate'] = $v_data['mdate']; + $p_header['mtime'] = $v_data['mtime']; + if ($p_header['mdate'] && $p_header['mtime']) + { + // ----- Extract time + $v_hour = ($p_header['mtime'] & 0xF800) >> 11; + $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; + $v_seconde = ($p_header['mtime'] & 0x001F)*2; + + // ----- Extract date + $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; + $v_month = ($p_header['mdate'] & 0x01E0) >> 5; + $v_day = $p_header['mdate'] & 0x001F; + + // ----- Get UNIX date format + $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); + + } + else + { + $p_header['mtime'] = time(); + } + + // TBC + //for(reset($v_data); $key = key($v_data); next($v_data)) { + //} + + // ----- Set the stored filename + $p_header['stored_filename'] = $p_header['filename']; + + // ----- Set the status field + $p_header['status'] = "ok"; + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadCentralFileHeader() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadCentralFileHeader(&$p_header) + { + $v_result=1; + + // ----- Read the 4 bytes signature + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] != 0x02014b50) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the first 42 bytes of the header + $v_binary_data = fread($this->zip_fd, 42); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 42) + { + $p_header['filename'] = ""; + $p_header['status'] = "invalid_header"; + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid block size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $p_header = unpack('vversion/vversion_extracted/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len/vcomment_len/vdisk/vinternal/Vexternal/Voffset', $v_binary_data); + + // ----- Get filename + if ($p_header['filename_len'] != 0) + $p_header['filename'] = fread($this->zip_fd, $p_header['filename_len']); + else + $p_header['filename'] = ''; + + // ----- Get extra + if ($p_header['extra_len'] != 0) + $p_header['extra'] = fread($this->zip_fd, $p_header['extra_len']); + else + $p_header['extra'] = ''; + + // ----- Get comment + if ($p_header['comment_len'] != 0) + $p_header['comment'] = fread($this->zip_fd, $p_header['comment_len']); + else + $p_header['comment'] = ''; + + // ----- Extract properties + + // ----- Recuperate date in UNIX format + //if ($p_header['mdate'] && $p_header['mtime']) + // TBC : bug : this was ignoring time with 0/0/0 + if (1) + { + // ----- Extract time + $v_hour = ($p_header['mtime'] & 0xF800) >> 11; + $v_minute = ($p_header['mtime'] & 0x07E0) >> 5; + $v_seconde = ($p_header['mtime'] & 0x001F)*2; + + // ----- Extract date + $v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; + $v_month = ($p_header['mdate'] & 0x01E0) >> 5; + $v_day = $p_header['mdate'] & 0x001F; + + // ----- Get UNIX date format + $p_header['mtime'] = @mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); + + } + else + { + $p_header['mtime'] = time(); + } + + // ----- Set the stored filename + $p_header['stored_filename'] = $p_header['filename']; + + // ----- Set default status to ok + $p_header['status'] = 'ok'; + + // ----- Look if it is a directory + if (substr($p_header['filename'], -1) == '/') { + //$p_header['external'] = 0x41FF0010; + $p_header['external'] = 0x00000010; + } + + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privCheckFileHeaders() + // Description : + // Parameters : + // Return Values : + // 1 on success, + // 0 on error; + // -------------------------------------------------------------------------------- + function privCheckFileHeaders(&$p_local_header, &$p_central_header) + { + $v_result=1; + + // ----- Check the static values + // TBC + if ($p_local_header['filename'] != $p_central_header['filename']) { + } + if ($p_local_header['version_extracted'] != $p_central_header['version_extracted']) { + } + if ($p_local_header['flag'] != $p_central_header['flag']) { + } + if ($p_local_header['compression'] != $p_central_header['compression']) { + } + if ($p_local_header['mtime'] != $p_central_header['mtime']) { + } + if ($p_local_header['filename_len'] != $p_central_header['filename_len']) { + } + + // ----- Look for flag bit 3 + if (($p_local_header['flag'] & 8) == 8) { + $p_local_header['size'] = $p_central_header['size']; + $p_local_header['compressed_size'] = $p_central_header['compressed_size']; + $p_local_header['crc'] = $p_central_header['crc']; + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privReadEndCentralDir() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privReadEndCentralDir(&$p_central_dir) + { + $v_result=1; + + // ----- Go to the end of the zip file + $v_size = filesize($this->zipname); + @fseek($this->zip_fd, $v_size); + if (@ftell($this->zip_fd) != $v_size) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- First try : look if this is an archive with no commentaries (most of the time) + // in this case the end of central dir is at 22 bytes of the file end + $v_found = 0; + if ($v_size > 26) { + @fseek($this->zip_fd, $v_size-22); + if (($v_pos = @ftell($this->zip_fd)) != ($v_size-22)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read for bytes + $v_binary_data = @fread($this->zip_fd, 4); + $v_data = @unpack('Vid', $v_binary_data); + + // ----- Check signature + if ($v_data['id'] == 0x06054b50) { + $v_found = 1; + } + + $v_pos = ftell($this->zip_fd); + } + + // ----- Go back to the maximum possible size of the Central Dir End Record + if (!$v_found) { + $v_maximum_size = 65557; // 0xFFFF + 22; + if ($v_maximum_size > $v_size) + $v_maximum_size = $v_size; + @fseek($this->zip_fd, $v_size-$v_maximum_size); + if (@ftell($this->zip_fd) != ($v_size-$v_maximum_size)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \''.$this->zipname.'\''); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read byte per byte in order to find the signature + $v_pos = ftell($this->zip_fd); + $v_bytes = 0x00000000; + while ($v_pos < $v_size) + { + // ----- Read a byte + $v_byte = @fread($this->zip_fd, 1); + + // ----- Add the byte + //$v_bytes = ($v_bytes << 8) | Ord($v_byte); + // Note we mask the old value down such that once shifted we can never end up with more than a 32bit number + // Otherwise on systems where we have 64bit integers the check below for the magic number will fail. + $v_bytes = ( ($v_bytes & 0xFFFFFF) << 8) | Ord($v_byte); + + // ----- Compare the bytes + if ($v_bytes == 0x504b0506) + { + $v_pos++; + break; + } + + $v_pos++; + } + + // ----- Look if not found end of central dir + if ($v_pos == $v_size) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Unable to find End of Central Dir Record signature"); + + // ----- Return + return PclZip::errorCode(); + } + } + + // ----- Read the first 18 bytes of the header + $v_binary_data = fread($this->zip_fd, 18); + + // ----- Look for invalid block size + if (strlen($v_binary_data) != 18) + { + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, "Invalid End of Central Dir Record size : ".strlen($v_binary_data)); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Extract the values + $v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data); + + // ----- Check the global size + if (($v_pos + $v_data['comment_size'] + 18) != $v_size) { + + // ----- Removed in release 2.2 see readme file + // The check of the file size is a little too strict. + // Some bugs where found when a zip is encrypted/decrypted with 'crypt'. + // While decrypted, zip has training 0 bytes + if (0) { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_BAD_FORMAT, + 'The central dir is not at the end of the archive.' + .' Some trailing bytes exists after the archive.'); + + // ----- Return + return PclZip::errorCode(); + } + } + + // ----- Get comment + if ($v_data['comment_size'] != 0) { + $p_central_dir['comment'] = fread($this->zip_fd, $v_data['comment_size']); + } + else + $p_central_dir['comment'] = ''; + + $p_central_dir['entries'] = $v_data['entries']; + $p_central_dir['disk_entries'] = $v_data['disk_entries']; + $p_central_dir['offset'] = $v_data['offset']; + $p_central_dir['size'] = $v_data['size']; + $p_central_dir['disk'] = $v_data['disk']; + $p_central_dir['disk_start'] = $v_data['disk_start']; + + // TBC + //for(reset($p_central_dir); $key = key($p_central_dir); next($p_central_dir)) { + //} + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDeleteByRule() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDeleteByRule(&$p_result_list, &$p_options) + { + $v_result=1; + $v_list_detail = array(); + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Scan all the files + // ----- Start at beginning of Central Dir + $v_pos_entry = $v_central_dir['offset']; + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_pos_entry)) + { + // ----- Close the zip file + $this->privCloseFd(); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read each entry + $v_header_list = array(); + $j_start = 0; + for ($i=0, $v_nb_extracted=0; $i<$v_central_dir['entries']; $i++) + { + + // ----- Read the file header + $v_header_list[$v_nb_extracted] = array(); + if (($v_result = $this->privReadCentralFileHeader($v_header_list[$v_nb_extracted])) != 1) + { + // ----- Close the zip file + $this->privCloseFd(); + + return $v_result; + } + + + // ----- Store the index + $v_header_list[$v_nb_extracted]['index'] = $i; + + // ----- Look for the specific extract rules + $v_found = false; + + // ----- Look for extract by name rule + if ( (isset($p_options[PCLZIP_OPT_BY_NAME])) + && ($p_options[PCLZIP_OPT_BY_NAME] != 0)) { + + // ----- Look if the filename is in the list + for ($j=0; ($j<sizeof($p_options[PCLZIP_OPT_BY_NAME])) && (!$v_found); $j++) { + + // ----- Look for a directory + if (substr($p_options[PCLZIP_OPT_BY_NAME][$j], -1) == "/") { + + // ----- Look if the directory is in the filename path + if ( (strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) + && (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_options[PCLZIP_OPT_BY_NAME][$j])) == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_found = true; + } + elseif ( (($v_header_list[$v_nb_extracted]['external']&0x00000010)==0x00000010) /* Indicates a folder */ + && ($v_header_list[$v_nb_extracted]['stored_filename'].'/' == $p_options[PCLZIP_OPT_BY_NAME][$j])) { + $v_found = true; + } + } + // ----- Look for a filename + elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_options[PCLZIP_OPT_BY_NAME][$j]) { + $v_found = true; + } + } + } + + // ----- Look for extract by ereg rule + // ereg() is deprecated with PHP 5.3 + /* + else if ( (isset($p_options[PCLZIP_OPT_BY_EREG])) + && ($p_options[PCLZIP_OPT_BY_EREG] != "")) { + + if (ereg($p_options[PCLZIP_OPT_BY_EREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { + $v_found = true; + } + } + */ + + // ----- Look for extract by preg rule + else if ( (isset($p_options[PCLZIP_OPT_BY_PREG])) + && ($p_options[PCLZIP_OPT_BY_PREG] != "")) { + + if (preg_match($p_options[PCLZIP_OPT_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { + $v_found = true; + } + } + + // ----- Look for extract by index rule + else if ( (isset($p_options[PCLZIP_OPT_BY_INDEX])) + && ($p_options[PCLZIP_OPT_BY_INDEX] != 0)) { + + // ----- Look if the index is in the list + for ($j=$j_start; ($j<sizeof($p_options[PCLZIP_OPT_BY_INDEX])) && (!$v_found); $j++) { + + if (($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['start']) && ($i<=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end'])) { + $v_found = true; + } + if ($i>=$p_options[PCLZIP_OPT_BY_INDEX][$j]['end']) { + $j_start = $j+1; + } + + if ($p_options[PCLZIP_OPT_BY_INDEX][$j]['start']>$i) { + break; + } + } + } + else { + $v_found = true; + } + + // ----- Look for deletion + if ($v_found) + { + unset($v_header_list[$v_nb_extracted]); + } + else + { + $v_nb_extracted++; + } + } + + // ----- Look if something need to be deleted + if ($v_nb_extracted > 0) { + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Creates a temporary zip archive + $v_temp_zip = new PclZip($v_zip_temp_name); + + // ----- Open the temporary zip file in write mode + if (($v_result = $v_temp_zip->privOpenFd('wb')) != 1) { + $this->privCloseFd(); + + // ----- Return + return $v_result; + } + + // ----- Look which file need to be kept + for ($i=0; $i<sizeof($v_header_list); $i++) { + + // ----- Calculate the position of the header + @rewind($this->zip_fd); + if (@fseek($this->zip_fd, $v_header_list[$i]['offset'])) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Read the file header + $v_local_header = array(); + if (($v_result = $this->privReadFileHeader($v_local_header)) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Check that local file header is same as central file header + if ($this->privCheckFileHeaders($v_local_header, + $v_header_list[$i]) != 1) { + // TBC + } + unset($v_local_header); + + // ----- Write the file header + if (($v_result = $v_temp_zip->privWriteFileHeader($v_header_list[$i])) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Read/write the data block + if (($v_result = PclZipUtilCopyBlock($this->zip_fd, $v_temp_zip->zip_fd, $v_header_list[$i]['compressed_size'])) != 1) { + // ----- Close the zip file + $this->privCloseFd(); + $v_temp_zip->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($v_temp_zip->zip_fd); + + // ----- Re-Create the Central Dir files header + for ($i=0; $i<sizeof($v_header_list); $i++) { + // ----- Create the file header + if (($v_result = $v_temp_zip->privWriteCentralFileHeader($v_header_list[$i])) != 1) { + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Transform the header to a 'usable' info + $v_temp_zip->privConvertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); + } + + + // ----- Zip file comment + $v_comment = ''; + if (isset($p_options[PCLZIP_OPT_COMMENT])) { + $v_comment = $p_options[PCLZIP_OPT_COMMENT]; + } + + // ----- Calculate the size of the central header + $v_size = @ftell($v_temp_zip->zip_fd)-$v_offset; + + // ----- Create the central dir footer + if (($v_result = $v_temp_zip->privWriteCentralHeader(sizeof($v_header_list), $v_size, $v_offset, $v_comment)) != 1) { + // ----- Reset the file list + unset($v_header_list); + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + @unlink($v_zip_temp_name); + + // ----- Return + return $v_result; + } + + // ----- Close + $v_temp_zip->privCloseFd(); + $this->privCloseFd(); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Destroy the temporary archive + unset($v_temp_zip); + } + + // ----- Remove every files : reset the file + else if ($v_central_dir['entries'] != 0) { + $this->privCloseFd(); + + if (($v_result = $this->privOpenFd('wb')) != 1) { + return $v_result; + } + + if (($v_result = $this->privWriteCentralHeader(0, 0, 0, '')) != 1) { + return $v_result; + } + + $this->privCloseFd(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDirCheck() + // Description : + // Check if a directory exists, if not it creates it and all the parents directory + // which may be useful. + // Parameters : + // $p_dir : Directory path to check. + // Return Values : + // 1 : OK + // -1 : Unable to create directory + // -------------------------------------------------------------------------------- + function privDirCheck($p_dir, $p_is_dir=false) + { + $v_result = 1; + + + // ----- Remove the final '/' + if (($p_is_dir) && (substr($p_dir, -1)=='/')) + { + $p_dir = substr($p_dir, 0, strlen($p_dir)-1); + } + + // ----- Check the directory availability + if ((is_dir($p_dir)) || ($p_dir == "")) + { + return 1; + } + + // ----- Extract parent directory + $p_parent_dir = dirname($p_dir); + + // ----- Just a check + if ($p_parent_dir != $p_dir) + { + // ----- Look for parent directory + if ($p_parent_dir != "") + { + if (($v_result = $this->privDirCheck($p_parent_dir)) != 1) + { + return $v_result; + } + } + } + + // ----- Create the directory + if (!@mkdir($p_dir, 0777)) + { + // ----- Error log + PclZip::privErrorLog(PCLZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'"); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privMerge() + // Description : + // If $p_archive_to_add does not exist, the function exit with a success result. + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privMerge(&$p_archive_to_add) + { + $v_result=1; + + // ----- Look if the archive_to_add exists + if (!is_file($p_archive_to_add->zipname)) + { + + // ----- Nothing to merge, so merge is a success + $v_result = 1; + + // ----- Return + return $v_result; + } + + // ----- Look if the archive exists + if (!is_file($this->zipname)) + { + + // ----- Do a duplicate + $v_result = $this->privDuplicate($p_archive_to_add->zipname); + + // ----- Return + return $v_result; + } + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('rb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir = array(); + if (($v_result = $this->privReadEndCentralDir($v_central_dir)) != 1) + { + $this->privCloseFd(); + return $v_result; + } + + // ----- Go to beginning of File + @rewind($this->zip_fd); + + // ----- Open the archive_to_add file + if (($v_result=$p_archive_to_add->privOpenFd('rb')) != 1) + { + $this->privCloseFd(); + + // ----- Return + return $v_result; + } + + // ----- Read the central directory informations + $v_central_dir_to_add = array(); + if (($v_result = $p_archive_to_add->privReadEndCentralDir($v_central_dir_to_add)) != 1) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + return $v_result; + } + + // ----- Go to beginning of File + @rewind($p_archive_to_add->zip_fd); + + // ----- Creates a temporay file + $v_zip_temp_name = PCLZIP_TEMPORARY_DIR.uniqid('pclzip-').'.tmp'; + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \''.$v_zip_temp_name.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = $v_central_dir['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Copy the files from the archive_to_add into the temporary file + $v_size = $v_central_dir_to_add['offset']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($p_archive_to_add->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Store the offset of the central dir + $v_offset = @ftell($v_zip_temp_fd); + + // ----- Copy the block of file headers from the old archive + $v_size = $v_central_dir['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($this->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Copy the block of file headers from the archive_to_add + $v_size = $v_central_dir_to_add['size']; + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_archive_to_add->zip_fd, $v_read_size); + @fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Merge the file comments + $v_comment = $v_central_dir['comment'].' '.$v_central_dir_to_add['comment']; + + // ----- Calculate the size of the (new) central header + $v_size = @ftell($v_zip_temp_fd)-$v_offset; + + // ----- Swap the file descriptor + // Here is a trick : I swap the temporary fd with the zip fd, in order to use + // the following methods on the temporary fil and not the real archive fd + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Create the central dir footer + if (($v_result = $this->privWriteCentralHeader($v_central_dir['entries']+$v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1) + { + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + @fclose($v_zip_temp_fd); + $this->zip_fd = null; + + // ----- Reset the file list + unset($v_header_list); + + // ----- Return + return $v_result; + } + + // ----- Swap back the file descriptor + $v_swap = $this->zip_fd; + $this->zip_fd = $v_zip_temp_fd; + $v_zip_temp_fd = $v_swap; + + // ----- Close + $this->privCloseFd(); + $p_archive_to_add->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Delete the zip file + // TBC : I should test the result ... + @unlink($this->zipname); + + // ----- Rename the temporary file + // TBC : I should test the result ... + //@rename($v_zip_temp_name, $this->zipname); + PclZipUtilRename($v_zip_temp_name, $this->zipname); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDuplicate() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDuplicate($p_archive_filename) + { + $v_result=1; + + // ----- Look if the $p_archive_filename exists + if (!is_file($p_archive_filename)) + { + + // ----- Nothing to duplicate, so duplicate is a success. + $v_result = 1; + + // ----- Return + return $v_result; + } + + // ----- Open the zip file + if (($v_result=$this->privOpenFd('wb')) != 1) + { + // ----- Return + return $v_result; + } + + // ----- Open the temporary file in write mode + if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) + { + $this->privCloseFd(); + + PclZip::privErrorLog(PCLZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \''.$p_archive_filename.'\' in binary write mode'); + + // ----- Return + return PclZip::errorCode(); + } + + // ----- Copy the files from the archive to the temporary file + // TBC : Here I should better append the file and go back to erase the central dir + $v_size = filesize($p_archive_filename); + while ($v_size != 0) + { + $v_read_size = ($v_size < PCLZIP_READ_BLOCK_SIZE ? $v_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = fread($v_zip_temp_fd, $v_read_size); + @fwrite($this->zip_fd, $v_buffer, $v_read_size); + $v_size -= $v_read_size; + } + + // ----- Close + $this->privCloseFd(); + + // ----- Close the temporary file + @fclose($v_zip_temp_fd); + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privErrorLog() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privErrorLog($p_error_code=0, $p_error_string='') + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + PclError($p_error_code, $p_error_string); + } + else { + $this->error_code = $p_error_code; + $this->error_string = $p_error_string; + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privErrorReset() + // Description : + // Parameters : + // -------------------------------------------------------------------------------- + function privErrorReset() + { + if (PCLZIP_ERROR_EXTERNAL == 1) { + PclErrorReset(); + } + else { + $this->error_code = 0; + $this->error_string = ''; + } + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privDisableMagicQuotes() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privDisableMagicQuotes() + { + $v_result=1; + + // ----- Look if function exists + if ( (!function_exists("get_magic_quotes_runtime")) + || (!function_exists("set_magic_quotes_runtime"))) { + return $v_result; + } + + // ----- Look if already done + if ($this->magic_quotes_status != -1) { + return $v_result; + } + + // ----- Get and memorize the magic_quote value + $this->magic_quotes_status = @get_magic_quotes_runtime(); + + // ----- Disable magic_quotes + if ($this->magic_quotes_status == 1) { + @set_magic_quotes_runtime(0); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : privSwapBackMagicQuotes() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function privSwapBackMagicQuotes() + { + $v_result=1; + + // ----- Look if function exists + if ( (!function_exists("get_magic_quotes_runtime")) + || (!function_exists("set_magic_quotes_runtime"))) { + return $v_result; + } + + // ----- Look if something to do + if ($this->magic_quotes_status != -1) { + return $v_result; + } + + // ----- Swap back magic_quotes + if ($this->magic_quotes_status == 1) { + @set_magic_quotes_runtime($this->magic_quotes_status); + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + } + // End of class + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilPathReduction() + // Description : + // Parameters : + // Return Values : + // -------------------------------------------------------------------------------- + function PclZipUtilPathReduction($p_dir) + { + $v_result = ""; + + // ----- Look for not empty path + if ($p_dir != "") { + // ----- Explode path by directory names + $v_list = explode("/", $p_dir); + + // ----- Study directories from last to first + $v_skip = 0; + for ($i=sizeof($v_list)-1; $i>=0; $i--) { + // ----- Look for current path + if ($v_list[$i] == ".") { + // ----- Ignore this directory + // Should be the first $i=0, but no check is done + } + else if ($v_list[$i] == "..") { + $v_skip++; + } + else if ($v_list[$i] == "") { + // ----- First '/' i.e. root slash + if ($i == 0) { + $v_result = "/".$v_result; + if ($v_skip > 0) { + // ----- It is an invalid path, so the path is not modified + // TBC + $v_result = $p_dir; + $v_skip = 0; + } + } + // ----- Last '/' i.e. indicates a directory + else if ($i == (sizeof($v_list)-1)) { + $v_result = $v_list[$i]; + } + // ----- Double '/' inside the path + else { + // ----- Ignore only the double '//' in path, + // but not the first and last '/' + } + } + else { + // ----- Look for item to skip + if ($v_skip > 0) { + $v_skip--; + } + else { + $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?"/".$v_result:""); + } + } + } + + // ----- Look for skip + if ($v_skip > 0) { + while ($v_skip > 0) { + $v_result = '../'.$v_result; + $v_skip--; + } + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilPathInclusion() + // Description : + // This function indicates if the path $p_path is under the $p_dir tree. Or, + // said in an other way, if the file or sub-dir $p_path is inside the dir + // $p_dir. + // The function indicates also if the path is exactly the same as the dir. + // This function supports path with duplicated '/' like '//', but does not + // support '.' or '..' statements. + // Parameters : + // Return Values : + // 0 if $p_path is not inside directory $p_dir + // 1 if $p_path is inside directory $p_dir + // 2 if $p_path is exactly the same as $p_dir + // -------------------------------------------------------------------------------- + function PclZipUtilPathInclusion($p_dir, $p_path) + { + $v_result = 1; + + // ----- Look for path beginning by ./ + if ( ($p_dir == '.') + || ((strlen($p_dir) >=2) && (substr($p_dir, 0, 2) == './'))) { + $p_dir = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_dir, 1); + } + if ( ($p_path == '.') + || ((strlen($p_path) >=2) && (substr($p_path, 0, 2) == './'))) { + $p_path = PclZipUtilTranslateWinPath(getcwd(), FALSE).'/'.substr($p_path, 1); + } + + // ----- Explode dir and path by directory separator + $v_list_dir = explode("/", $p_dir); + $v_list_dir_size = sizeof($v_list_dir); + $v_list_path = explode("/", $p_path); + $v_list_path_size = sizeof($v_list_path); + + // ----- Study directories paths + $i = 0; + $j = 0; + while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && ($v_result)) { + + // ----- Look for empty dir (path reduction) + if ($v_list_dir[$i] == '') { + $i++; + continue; + } + if ($v_list_path[$j] == '') { + $j++; + continue; + } + + // ----- Compare the items + if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ( $v_list_path[$j] != '')) { + $v_result = 0; + } + + // ----- Next items + $i++; + $j++; + } + + // ----- Look if everything seems to be the same + if ($v_result) { + // ----- Skip all the empty items + while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) $j++; + while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) $i++; + + if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) { + // ----- There are exactly the same + $v_result = 2; + } + else if ($i < $v_list_dir_size) { + // ----- The path is shorter than the dir + $v_result = 0; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilCopyBlock() + // Description : + // Parameters : + // $p_mode : read/write compression mode + // 0 : src & dest normal + // 1 : src gzip, dest normal + // 2 : src normal, dest gzip + // 3 : src & dest gzip + // Return Values : + // -------------------------------------------------------------------------------- + function PclZipUtilCopyBlock($p_src, $p_dest, $p_size, $p_mode=0) + { + $v_result = 1; + + if ($p_mode==0) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_src, $v_read_size); + @fwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==1) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($p_src, $v_read_size); + @fwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==2) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @fread($p_src, $v_read_size); + @gzwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + else if ($p_mode==3) + { + while ($p_size != 0) + { + $v_read_size = ($p_size < PCLZIP_READ_BLOCK_SIZE ? $p_size : PCLZIP_READ_BLOCK_SIZE); + $v_buffer = @gzread($p_src, $v_read_size); + @gzwrite($p_dest, $v_buffer, $v_read_size); + $p_size -= $v_read_size; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilRename() + // Description : + // This function tries to do a simple rename() function. If it fails, it + // tries to copy the $p_src file in a new $p_dest file and then unlink the + // first one. + // Parameters : + // $p_src : Old filename + // $p_dest : New filename + // Return Values : + // 1 on success, 0 on failure. + // -------------------------------------------------------------------------------- + function PclZipUtilRename($p_src, $p_dest) + { + $v_result = 1; + + // ----- Try to rename the files + if (!@rename($p_src, $p_dest)) { + + // ----- Try to copy & unlink the src + if (!@copy($p_src, $p_dest)) { + $v_result = 0; + } + else if (!@unlink($p_src)) { + $v_result = 0; + } + } + + // ----- Return + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilOptionText() + // Description : + // Translate option value in text. Mainly for debug purpose. + // Parameters : + // $p_option : the option value. + // Return Values : + // The option text value. + // -------------------------------------------------------------------------------- + function PclZipUtilOptionText($p_option) + { + + $v_list = get_defined_constants(); + for (reset($v_list); $v_key = key($v_list); next($v_list)) { + $v_prefix = substr($v_key, 0, 10); + if (( ($v_prefix == 'PCLZIP_OPT') + || ($v_prefix == 'PCLZIP_CB_') + || ($v_prefix == 'PCLZIP_ATT')) + && ($v_list[$v_key] == $p_option)) { + return $v_key; + } + } + + $v_result = 'Unknown'; + + return $v_result; + } + // -------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------- + // Function : PclZipUtilTranslateWinPath() + // Description : + // Translate windows path by replacing '\' by '/' and optionally removing + // drive letter. + // Parameters : + // $p_path : path to translate. + // $p_remove_disk_letter : true | false + // Return Values : + // The path translated. + // -------------------------------------------------------------------------------- + function PclZipUtilTranslateWinPath($p_path, $p_remove_disk_letter=true) + { + if (stristr(php_uname(), 'windows')) { + // ----- Look for potential disk letter + if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) { + $p_path = substr($p_path, $v_position+1); + } + // ----- Change potential windows directory separator + if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { + $p_path = strtr($p_path, '\\', '/'); + } + } + return $p_path; + } + // -------------------------------------------------------------------------------- + + +?> diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/readme.txt b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/readme.txt new file mode 100755 index 0000000..6ed8839 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PCLZip/readme.txt @@ -0,0 +1,421 @@ +// -------------------------------------------------------------------------------- +// PclZip 2.8.2 - readme.txt +// -------------------------------------------------------------------------------- +// License GNU/LGPL - August 2009 +// Vincent Blavet - vincent@phpconcept.net +// http://www.phpconcept.net +// -------------------------------------------------------------------------------- +// $Id: readme.txt,v 1.60 2009/09/30 20:35:21 vblavet Exp $ +// -------------------------------------------------------------------------------- + + + +0 - Sommaire +============ + 1 - Introduction + 2 - What's new + 3 - Corrected bugs + 4 - Known bugs or limitations + 5 - License + 6 - Warning + 7 - Documentation + 8 - Author + 9 - Contribute + +1 - Introduction +================ + + PclZip is a library that allow you to manage a Zip archive. + + Full documentation about PclZip can be found here : http://www.phpconcept.net/pclzip + +2 - What's new +============== + + Version 2.8.2 : + - PCLZIP_CB_PRE_EXTRACT and PCLZIP_CB_POST_EXTRACT are now supported with + extraction as a string (PCLZIP_OPT_EXTRACT_AS_STRING). The string + can also be modified in the post-extract call back. + **Bugs correction : + - PCLZIP_OPT_REMOVE_ALL_PATH was not working correctly + - Remove use of eval() and do direct call to callback functions + - Correct support of 64bits systems (Thanks to WordPress team) + + Version 2.8.1 : + - Move option PCLZIP_OPT_BY_EREG to PCLZIP_OPT_BY_PREG because ereg() is + deprecated in PHP 5.3. When using option PCLZIP_OPT_BY_EREG, PclZip will + automatically replace it by PCLZIP_OPT_BY_PREG. + + Version 2.8 : + - Improve extraction of zip archive for large files by using temporary files + This feature is working like the one defined in r2.7. + Options are renamed : PCLZIP_OPT_TEMP_FILE_ON, PCLZIP_OPT_TEMP_FILE_OFF, + PCLZIP_OPT_TEMP_FILE_THRESHOLD + - Add a ratio constant PCLZIP_TEMPORARY_FILE_RATIO to configure the auto + sense of temporary file use. + - Bug correction : Reduce filepath in returned file list to remove ennoying + './/' preambule in file path. + + Version 2.7 : + - Improve creation of zip archive for large files : + PclZip will now autosense the configured memory and use temporary files + when large file is suspected. + This feature can also ne triggered by manual options in create() and add() + methods. 'PCLZIP_OPT_ADD_TEMP_FILE_ON' force the use of temporary files, + 'PCLZIP_OPT_ADD_TEMP_FILE_OFF' disable the autosense technic, + 'PCLZIP_OPT_ADD_TEMP_FILE_THRESHOLD' allow for configuration of a size + threshold to use temporary files. + Using "temporary files" rather than "memory" might take more time, but + might give the ability to zip very large files : + Tested on my win laptop with a 88Mo file : + Zip "in-memory" : 18sec (max_execution_time=30, memory_limit=180Mo) + Zip "tmporary-files" : 23sec (max_execution_time=30, memory_limit=30Mo) + - Replace use of mktime() by time() to limit the E_STRICT error messages. + - Bug correction : When adding files with full windows path (drive letter) + PclZip is now working. Before, if the drive letter is not the default + path, PclZip was not able to add the file. + + Version 2.6 : + - Code optimisation + - New attributes PCLZIP_ATT_FILE_COMMENT gives the ability to + add a comment for a specific file. (Don't really know if this is usefull) + - New attribute PCLZIP_ATT_FILE_CONTENT gives the ability to add a string + as a file. + - New attribute PCLZIP_ATT_FILE_MTIME modify the timestamp associated with + a file. + - Correct a bug. Files archived with a timestamp with 0h0m0s were extracted + with current time + - Add CRC value in the informations returned back for each file after an + action. + - Add missing closedir() statement. + - When adding a folder, and removing the path of this folder, files were + incorrectly added with a '/' at the beginning. Which means files are + related to root in unix systems. Corrected. + - Add conditional if before constant definition. This will allow users + to redefine constants without changing the file, and then improve + upgrade of pclzip code for new versions. + + Version 2.5 : + - Introduce the ability to add file/folder with individual properties (file descriptor). + This gives for example the ability to change the filename of a zipped file. + . Able to add files individually + . Able to change full name + . Able to change short name + . Compatible with global options + - New attributes : PCLZIP_ATT_FILE_NAME, PCLZIP_ATT_FILE_NEW_SHORT_NAME, PCLZIP_ATT_FILE_NEW_FULL_NAME + - New error code : PCLZIP_ERR_INVALID_ATTRIBUTE_VALUE + - Add a security control feature. PclZip can extract any file in any folder + of a system. People may use this to upload a zip file and try to override + a system file. The PCLZIP_OPT_EXTRACT_DIR_RESTRICTION will give the + ability to forgive any directory transversal behavior. + - New PCLZIP_OPT_EXTRACT_DIR_RESTRICTION : check extraction path + - New error code : PCLZIP_ERR_DIRECTORY_RESTRICTION + - Modification in PclZipUtilPathInclusion() : dir and path beginning with ./ will be prepend + by current path (getcwd()) + + Version 2.4 : + - Code improvment : try to speed up the code by removing unusefull call to pack() + - Correct bug in delete() : delete() should be called with no argument. This was not + the case in 2.3. This is corrected in 2.4. + - Correct a bug in path_inclusion function. When the path has several '../../', the + result was bad. + - Add a check for magic_quotes_runtime configuration. If enabled, PclZip will + disable it while working and det it back to its original value. + This resolve a lots of bad formated archive errors. + - Bug correction : PclZip now correctly unzip file in some specific situation, + when compressed content has same size as uncompressed content. + - Bug correction : When selecting option 'PCLZIP_OPT_REMOVE_ALL_PATH', + directories are not any more created. + - Code improvment : correct unclosed opendir(), better handling of . and .. in + loops. + + + Version 2.3 : + - Correct a bug with PHP5 : affecting the value 0xFE49FFE0 to a variable does not + give the same result in PHP4 and PHP5 .... + + Version 2.2 : + - Try development of PCLZIP_OPT_CRYPT ..... + However this becomes to a stop. To crypt/decrypt I need to multiply 2 long integers, + the result (greater than a long) is not supported by PHP. Even the use of bcmath + functions does not help. I did not find yet a solution ...; + - Add missing '/' at end of directory entries + - Check is a file is encrypted or not. Returns status 'unsupported_encryption' and/or + error code PCLZIP_ERR_UNSUPPORTED_ENCRYPTION. + - Corrected : Bad "version need to extract" field in local file header + - Add private method privCheckFileHeaders() in order to check local and central + file headers. PclZip is now supporting purpose bit flag bit 3. Purpose bit flag bit 3 gives + the ability to have a local file header without size, compressed size and crc filled. + - Add a generic status 'error' for file status + - Add control of compression type. PclZip only support deflate compression method. + Before v2.2, PclZip does not check the compression method used in an archive while + extracting. With v2.2 PclZip returns a new error status for a file using an unsupported + compression method. New status is "unsupported_compression". New error code is + PCLZIP_ERR_UNSUPPORTED_COMPRESSION. + - Add optional attribute PCLZIP_OPT_STOP_ON_ERROR. This will stop the extract of files + when errors like 'a folder with same name exists' or 'a newer file exists' or + 'a write protected file' exists, rather than set a status for the concerning file + and resume the extract of the zip. + - Add optional attribute PCLZIP_OPT_REPLACE_NEWER. This will force, during an extract' the + replacement of the file, even if a newer version of the file exists. + Note that today if a file with the same name already exists but is older it will be + replaced by the extracted one. + - Improve PclZipUtilOption() + - Support of zip archive with trailing bytes. Before 2.2, PclZip checks that the central + directory structure is the last data in the archive. Crypt encryption/decryption of + zip archive put trailing 0 bytes after decryption. PclZip is now supporting this. + + Version 2.1 : + - Add the ability to abort the extraction by using a user callback function. + The user can now return the value '2' in its callback which indicates to stop the + extraction. For a pre call-back extract is stopped before the extration of the current + file. For a post call back, the extraction is stopped after. + - Add the ability to extract a file (or several files) directly in the standard output. + This is done by the new parameter PCLZIP_OPT_EXTRACT_IN_OUTPUT with method extract(). + - Add support for parameters PCLZIP_OPT_COMMENT, PCLZIP_OPT_ADD_COMMENT, + PCLZIP_OPT_PREPEND_COMMENT. This will create, replace, add, or prepend comments + in the zip archive. + - When merging two archives, the comments are not any more lost, but merged, with a + blank space separator. + - Corrected bug : Files are not deleted when all files are asked to be deleted. + - Corrected bug : Folders with name '0' made PclZip to abort the create or add feature. + + + Version 2.0 : + ***** Warning : Some new features may break the backward compatibility for your scripts. + Please carefully read the readme file. + - Add the ability to delete by Index, name and regular expression. This feature is + performed by the method delete(), which uses the optional parameters + PCLZIP_OPT_BY_INDEX, PCLZIP_OPT_BY_NAME, PCLZIP_OPT_BY_EREG or PCLZIP_OPT_BY_PREG. + - Add the ability to extract by regular expression. To extract by regexp you must use the method + extract(), with the option PCLZIP_OPT_BY_EREG or PCLZIP_OPT_BY_PREG + (depending if you want to use ereg() or preg_match() syntax) followed by the + regular expression pattern. + - Add the ability to extract by index, directly with the extract() method. This is a + code improvment of the extractByIndex() method. + - Add the ability to extract by name. To extract by name you must use the method + extract(), with the option PCLZIP_OPT_BY_NAME followed by the filename to + extract or an array of filenames to extract. To extract all a folder, use the folder + name rather than the filename with a '/' at the end. + - Add the ability to add files without compression. This is done with a new attribute + which is PCLZIP_OPT_NO_COMPRESSION. + - Add the attribute PCLZIP_OPT_EXTRACT_AS_STRING, which allow to extract a file directly + in a string without using any file (or temporary file). + - Add constant PCLZIP_SEPARATOR for static configuration of filename separators in a single string. + The default separator is now a comma (,) and not any more a blank space. + THIS BREAK THE BACKWARD COMPATIBILITY : Please check if this may have an impact with + your script. + - Improve algorythm performance by removing the use of temporary files when adding or + extracting files in an archive. + - Add (correct) detection of empty filename zipping. This can occurs when the removed + path is the same + as a zipped dir. The dir is not zipped (['status'] = filtered), only its content. + - Add better support for windows paths (thanks for help from manus@manusfreedom.com). + - Corrected bug : When the archive file already exists with size=0, the add() method + fails. Corrected in 2.0. + - Remove the use of OS_WINDOWS constant. Use php_uname() function rather. + - Control the order of index ranges in extract by index feature. + - Change the internal management of folders (better handling of internal flag). + + + Version 1.3 : + - Removing the double include check. This is now done by include_once() and require_once() + PHP directives. + - Changing the error handling mecanism : Remove the use of an external error library. + The former PclError...() functions are replaced by internal equivalent methods. + By changing the environment variable PCLZIP_ERROR_EXTERNAL you can still use the former library. + Introducing the use of constants for error codes rather than integer values. This will help + in futur improvment. + Introduction of error handling functions like errorCode(), errorName() and errorInfo(). + - Remove the deprecated use of calling function with arguments passed by reference. + - Add the calling of extract(), extractByIndex(), create() and add() functions + with variable options rather than fixed arguments. + - Add the ability to remove all the file path while extracting or adding, + without any need to specify the path to remove. + This is available for extract(), extractByIndex(), create() and add() functionS by using + the new variable options parameters : + - PCLZIP_OPT_REMOVE_ALL_PATH : by indicating this option while calling the fct. + - Ability to change the mode of a file after the extraction (chmod()). + This is available for extract() and extractByIndex() functionS by using + the new variable options parameters. + - PCLZIP_OPT_SET_CHMOD : by setting the value of this option. + - Ability to definition call-back options. These call-back will be called during the adding, + or the extracting of file (extract(), extractByIndex(), create() and add() functions) : + - PCLZIP_CB_PRE_EXTRACT : will be called before each extraction of a file. The user + can trigerred the change the filename of the extracted file. The user can triggered the + skip of the extraction. This is adding a 'skipped' status in the file list result value. + - PCLZIP_CB_POST_EXTRACT : will be called after each extraction of a file. + Nothing can be triggered from that point. + - PCLZIP_CB_PRE_ADD : will be called before each add of a file. The user + can trigerred the change the stored filename of the added file. The user can triggered the + skip of the add. This is adding a 'skipped' status in the file list result value. + - PCLZIP_CB_POST_ADD : will be called after each add of a file. + Nothing can be triggered from that point. + - Two status are added in the file list returned as function result : skipped & filename_too_long + 'skipped' is used when a call-back function ask for skipping the file. + 'filename_too_long' is used while adding a file with a too long filename to archive (the file is + not added) + - Adding the function PclZipUtilPathInclusion(), that check the inclusion of a path into + a directory. + - Add a check of the presence of the archive file before some actions (like list, ...) + - Add the initialisation of field "index" in header array. This means that by + default index will be -1 when not explicitly set by the methods. + + Version 1.2 : + - Adding a duplicate function. + - Adding a merge function. The merge function is a "quick merge" function, + it just append the content of an archive at the end of the first one. There + is no check for duplicate files or more recent files. + - Improve the search of the central directory end. + + Version 1.1.2 : + + - Changing the license of PclZip. PclZip is now released under the GNU / LGPL license + (see License section). + - Adding the optional support of a static temporary directory. You will need to configure + the constant PCLZIP_TEMPORARY_DIR if you want to use this feature. + - Improving the rename() function. In some cases rename() does not work (different + Filesystems), so it will be replaced by a copy() + unlink() functions. + + Version 1.1.1 : + + - Maintenance release, no new feature. + + Version 1.1 : + + - New method Add() : adding files in the archive + - New method ExtractByIndex() : partial extract of the archive, files are identified by + their index in the archive + - New method DeleteByIndex() : delete some files/folder entries from the archive, + files are identified by their index in the archive. + - Adding a test of the zlib extension presence. If not present abort the script. + + Version 1.0.1 : + + - No new feature + + +3 - Corrected bugs +================== + + Corrected in Version 2.0 : + - Corrected : During an extraction, if a call-back fucntion is used and try to skip + a file, all the extraction process is stopped. + + Corrected in Version 1.3 : + - Corrected : Support of static synopsis for method extract() is broken. + - Corrected : invalid size of archive content field (0xFF) should be (0xFFFF). + - Corrected : When an extract is done with a remove_path parameter, the entry for + the directory with exactly the same path is not skipped/filtered. + - Corrected : extractByIndex() and deleteByIndex() were not managing index in the + right way. For example indexes '1,3-5,11' will only extract files 1 and 11. This + is due to a sort of the index resulting table that puts 11 before 3-5 (sort on + string and not interger). The sort is temporarilly removed, this means that + you must provide a sorted list of index ranges. + + Corrected in Version 1.2 : + + - Nothing. + + Corrected in Version 1.1.2 : + + - Corrected : Winzip is unable to delete or add new files in a PclZip created archives. + + Corrected in Version 1.1.1 : + + - Corrected : When archived file is not compressed (0% compression), the + extract method fails. + + Corrected in Version 1.1 : + + - Corrected : Adding a complete tree of folder may result in a bad archive + creation. + + Corrected in Version 1.0.1 : + + - Corrected : Error while compressing files greater than PCLZIP_READ_BLOCK_SIZE (default=1024). + + +4 - Known bugs or limitations +============================= + + Please publish bugs reports in SourceForge : + http://sourceforge.net/tracker/?group_id=40254&atid=427564 + + In Version 2.x : + - PclZip does only support file uncompressed or compressed with deflate (compression method 8) + - PclZip does not support password protected zip archive + - Some concern were seen when changing mtime of a file while archiving. + Seems to be linked to Daylight Saving Time (PclTest_changing_mtime). + + In Version 1.2 : + + - merge() methods does not check for duplicate files or last date of modifications. + + In Version 1.1 : + + - Limitation : Using 'extract' fields in the file header in the zip archive is not supported. + - WinZip is unable to delete a single file in a PclZip created archive. It is also unable to + add a file in a PclZip created archive. (Corrected in v.1.2) + + In Version 1.0.1 : + + - Adding a complete tree of folder may result in a bad archive + creation. (Corrected in V.1.1). + - Path given to methods must be in the unix format (/) and not the Windows format (\). + Workaround : Use only / directory separators. + - PclZip is using temporary files that are sometime the name of the file with a .tmp or .gz + added suffix. Files with these names may already exist and may be overwritten. + Workaround : none. + - PclZip does not check if the zlib extension is present. If it is absent, the zip + file is not created and the lib abort without warning. + Workaround : enable the zlib extension on the php install + + In Version 1.0 : + + - Error while compressing files greater than PCLZIP_READ_BLOCK_SIZE (default=1024). + (Corrected in v.1.0.1) + - Limitation : Multi-disk zip archive are not supported. + + +5 - License +=========== + + Since version 1.1.2, PclZip Library is released under GNU/LGPL license. + This library is free, so you can use it at no cost. + + HOWEVER, if you release a script, an application, a library or any kind of + code using PclZip library (or a part of it), YOU MUST : + - Indicate in the documentation (or a readme file), that your work + uses PclZip Library, and make a reference to the author and the web site + http://www.phpconcept.net + - Gives the ability to the final user to update the PclZip libary. + + I will also appreciate that you send me a mail (vincent@phpconcept.net), just to + be aware that someone is using PclZip. + + For more information about GNU/LGPL license : http://www.gnu.org + +6 - Warning +================= + + This library and the associated files are non commercial, non professional work. + It should not have unexpected results. However if any damage is caused by this software + the author can not be responsible. + The use of this software is at the risk of the user. + +7 - Documentation +================= + PclZip User Manuel is available in English on PhpConcept : http://www.phpconcept.net/pclzip/man/en/index.php + A Russian translation was done by Feskov Kuzma : http://php.russofile.ru/ru/authors/unsort/zip/ + +8 - Author +========== + + This software was written by Vincent Blavet (vincent@phpconcept.net) on its leasure time. + +9 - Contribute +============== + If you want to contribute to the development of PclZip, please contact vincent@phpconcept.net. + If you can help in financing PhpConcept hosting service, please go to + http://www.phpconcept.net/soutien.php diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PasswordHasher.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PasswordHasher.php new file mode 100755 index 0000000..38f3843 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/PasswordHasher.php @@ -0,0 +1,66 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Shared_PasswordHasher + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_PasswordHasher +{ + /** + * Create a password hash from a given string. + * + * This method is based on the algorithm provided by + * Daniel Rentz of OpenOffice and the PEAR package + * Spreadsheet_Excel_Writer by Xavier Noguer <xnoguer@rezebra.com>. + * + * @param string $pPassword Password to hash + * @return string Hashed password + */ + public static function hashPassword($pPassword = '') { + $password = 0x0000; + $charPos = 1; // char position + + // split the plain text password in its component characters + $chars = preg_split('//', $pPassword, -1, PREG_SPLIT_NO_EMPTY); + foreach ($chars as $char) { + $value = ord($char) << $charPos++; // shifted ASCII value + $rotated_bits = $value >> 15; // rotated bits beyond bit 15 + $value &= 0x7fff; // first 15 bits + $password ^= ($value | $rotated_bits); + } + + $password ^= strlen($pPassword); + $password ^= 0xCE4B; + + return(strtoupper(dechex($password))); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/String.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/String.php new file mode 100755 index 0000000..3a66970 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/String.php @@ -0,0 +1,776 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Shared_String + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_String +{ + /** Constants */ + /** Regular Expressions */ + // Fraction + const STRING_REGEXP_FRACTION = '(-?)(\d+)\s+(\d+\/\d+)'; + + + /** + * Control characters array + * + * @var string[] + */ + private static $_controlCharacters = array(); + + /** + * SYLK Characters array + * + * $var array + */ + private static $_SYLKCharacters = array(); + + /** + * Decimal separator + * + * @var string + */ + private static $_decimalSeparator; + + /** + * Thousands separator + * + * @var string + */ + private static $_thousandsSeparator; + + /** + * Currency code + * + * @var string + */ + private static $_currencyCode; + + /** + * Is mbstring extension avalable? + * + * @var boolean + */ + private static $_isMbstringEnabled; + + /** + * Is iconv extension avalable? + * + * @var boolean + */ + private static $_isIconvEnabled; + + /** + * Build control characters array + */ + private static function _buildControlCharacters() { + for ($i = 0; $i <= 31; ++$i) { + if ($i != 9 && $i != 10 && $i != 13) { + $find = '_x' . sprintf('%04s' , strtoupper(dechex($i))) . '_'; + $replace = chr($i); + self::$_controlCharacters[$find] = $replace; + } + } + } + + /** + * Build SYLK characters array + */ + private static function _buildSYLKCharacters() + { + self::$_SYLKCharacters = array( + "\x1B 0" => chr(0), + "\x1B 1" => chr(1), + "\x1B 2" => chr(2), + "\x1B 3" => chr(3), + "\x1B 4" => chr(4), + "\x1B 5" => chr(5), + "\x1B 6" => chr(6), + "\x1B 7" => chr(7), + "\x1B 8" => chr(8), + "\x1B 9" => chr(9), + "\x1B :" => chr(10), + "\x1B ;" => chr(11), + "\x1B <" => chr(12), + "\x1B :" => chr(13), + "\x1B >" => chr(14), + "\x1B ?" => chr(15), + "\x1B!0" => chr(16), + "\x1B!1" => chr(17), + "\x1B!2" => chr(18), + "\x1B!3" => chr(19), + "\x1B!4" => chr(20), + "\x1B!5" => chr(21), + "\x1B!6" => chr(22), + "\x1B!7" => chr(23), + "\x1B!8" => chr(24), + "\x1B!9" => chr(25), + "\x1B!:" => chr(26), + "\x1B!;" => chr(27), + "\x1B!<" => chr(28), + "\x1B!=" => chr(29), + "\x1B!>" => chr(30), + "\x1B!?" => chr(31), + "\x1B'?" => chr(127), + "\x1B(0" => '€', // 128 in CP1252 + "\x1B(2" => '‚', // 130 in CP1252 + "\x1B(3" => 'Æ’', // 131 in CP1252 + "\x1B(4" => '„', // 132 in CP1252 + "\x1B(5" => '…', // 133 in CP1252 + "\x1B(6" => '†', // 134 in CP1252 + "\x1B(7" => '‡', // 135 in CP1252 + "\x1B(8" => 'ˆ', // 136 in CP1252 + "\x1B(9" => '‰', // 137 in CP1252 + "\x1B(:" => 'Å ', // 138 in CP1252 + "\x1B(;" => '‹', // 139 in CP1252 + "\x1BNj" => 'Å’', // 140 in CP1252 + "\x1B(>" => 'Ž', // 142 in CP1252 + "\x1B)1" => '‘', // 145 in CP1252 + "\x1B)2" => '’', // 146 in CP1252 + "\x1B)3" => '“', // 147 in CP1252 + "\x1B)4" => 'â€', // 148 in CP1252 + "\x1B)5" => '•', // 149 in CP1252 + "\x1B)6" => '–', // 150 in CP1252 + "\x1B)7" => '—', // 151 in CP1252 + "\x1B)8" => 'Ëœ', // 152 in CP1252 + "\x1B)9" => 'â„¢', // 153 in CP1252 + "\x1B):" => 'Å¡', // 154 in CP1252 + "\x1B);" => '›', // 155 in CP1252 + "\x1BNz" => 'Å“', // 156 in CP1252 + "\x1B)>" => 'ž', // 158 in CP1252 + "\x1B)?" => 'Ÿ', // 159 in CP1252 + "\x1B*0" => ' ', // 160 in CP1252 + "\x1BN!" => '¡', // 161 in CP1252 + "\x1BN\"" => '¢', // 162 in CP1252 + "\x1BN#" => '£', // 163 in CP1252 + "\x1BN(" => '¤', // 164 in CP1252 + "\x1BN%" => 'Â¥', // 165 in CP1252 + "\x1B*6" => '¦', // 166 in CP1252 + "\x1BN'" => '§', // 167 in CP1252 + "\x1BNH " => '¨', // 168 in CP1252 + "\x1BNS" => '©', // 169 in CP1252 + "\x1BNc" => 'ª', // 170 in CP1252 + "\x1BN+" => '«', // 171 in CP1252 + "\x1B*<" => '¬', // 172 in CP1252 + "\x1B*=" => '­', // 173 in CP1252 + "\x1BNR" => '®', // 174 in CP1252 + "\x1B*?" => '¯', // 175 in CP1252 + "\x1BN0" => '°', // 176 in CP1252 + "\x1BN1" => '±', // 177 in CP1252 + "\x1BN2" => '²', // 178 in CP1252 + "\x1BN3" => '³', // 179 in CP1252 + "\x1BNB " => '´', // 180 in CP1252 + "\x1BN5" => 'µ', // 181 in CP1252 + "\x1BN6" => '¶', // 182 in CP1252 + "\x1BN7" => '·', // 183 in CP1252 + "\x1B+8" => '¸', // 184 in CP1252 + "\x1BNQ" => '¹', // 185 in CP1252 + "\x1BNk" => 'º', // 186 in CP1252 + "\x1BN;" => '»', // 187 in CP1252 + "\x1BN<" => '¼', // 188 in CP1252 + "\x1BN=" => '½', // 189 in CP1252 + "\x1BN>" => '¾', // 190 in CP1252 + "\x1BN?" => '¿', // 191 in CP1252 + "\x1BNAA" => 'À', // 192 in CP1252 + "\x1BNBA" => 'Ã', // 193 in CP1252 + "\x1BNCA" => 'Â', // 194 in CP1252 + "\x1BNDA" => 'Ã', // 195 in CP1252 + "\x1BNHA" => 'Ä', // 196 in CP1252 + "\x1BNJA" => 'Ã…', // 197 in CP1252 + "\x1BNa" => 'Æ', // 198 in CP1252 + "\x1BNKC" => 'Ç', // 199 in CP1252 + "\x1BNAE" => 'È', // 200 in CP1252 + "\x1BNBE" => 'É', // 201 in CP1252 + "\x1BNCE" => 'Ê', // 202 in CP1252 + "\x1BNHE" => 'Ë', // 203 in CP1252 + "\x1BNAI" => 'ÃŒ', // 204 in CP1252 + "\x1BNBI" => 'Ã', // 205 in CP1252 + "\x1BNCI" => 'ÃŽ', // 206 in CP1252 + "\x1BNHI" => 'Ã', // 207 in CP1252 + "\x1BNb" => 'Ã', // 208 in CP1252 + "\x1BNDN" => 'Ñ', // 209 in CP1252 + "\x1BNAO" => 'Ã’', // 210 in CP1252 + "\x1BNBO" => 'Ó', // 211 in CP1252 + "\x1BNCO" => 'Ô', // 212 in CP1252 + "\x1BNDO" => 'Õ', // 213 in CP1252 + "\x1BNHO" => 'Ö', // 214 in CP1252 + "\x1B-7" => '×', // 215 in CP1252 + "\x1BNi" => 'Ø', // 216 in CP1252 + "\x1BNAU" => 'Ù', // 217 in CP1252 + "\x1BNBU" => 'Ú', // 218 in CP1252 + "\x1BNCU" => 'Û', // 219 in CP1252 + "\x1BNHU" => 'Ãœ', // 220 in CP1252 + "\x1B-=" => 'Ã', // 221 in CP1252 + "\x1BNl" => 'Þ', // 222 in CP1252 + "\x1BN{" => 'ß', // 223 in CP1252 + "\x1BNAa" => 'à', // 224 in CP1252 + "\x1BNBa" => 'á', // 225 in CP1252 + "\x1BNCa" => 'â', // 226 in CP1252 + "\x1BNDa" => 'ã', // 227 in CP1252 + "\x1BNHa" => 'ä', // 228 in CP1252 + "\x1BNJa" => 'Ã¥', // 229 in CP1252 + "\x1BNq" => 'æ', // 230 in CP1252 + "\x1BNKc" => 'ç', // 231 in CP1252 + "\x1BNAe" => 'è', // 232 in CP1252 + "\x1BNBe" => 'é', // 233 in CP1252 + "\x1BNCe" => 'ê', // 234 in CP1252 + "\x1BNHe" => 'ë', // 235 in CP1252 + "\x1BNAi" => 'ì', // 236 in CP1252 + "\x1BNBi" => 'í', // 237 in CP1252 + "\x1BNCi" => 'î', // 238 in CP1252 + "\x1BNHi" => 'ï', // 239 in CP1252 + "\x1BNs" => 'ð', // 240 in CP1252 + "\x1BNDn" => 'ñ', // 241 in CP1252 + "\x1BNAo" => 'ò', // 242 in CP1252 + "\x1BNBo" => 'ó', // 243 in CP1252 + "\x1BNCo" => 'ô', // 244 in CP1252 + "\x1BNDo" => 'õ', // 245 in CP1252 + "\x1BNHo" => 'ö', // 246 in CP1252 + "\x1B/7" => '÷', // 247 in CP1252 + "\x1BNy" => 'ø', // 248 in CP1252 + "\x1BNAu" => 'ù', // 249 in CP1252 + "\x1BNBu" => 'ú', // 250 in CP1252 + "\x1BNCu" => 'û', // 251 in CP1252 + "\x1BNHu" => 'ü', // 252 in CP1252 + "\x1B/=" => 'ý', // 253 in CP1252 + "\x1BN|" => 'þ', // 254 in CP1252 + "\x1BNHy" => 'ÿ', // 255 in CP1252 + ); + } + + /** + * Get whether mbstring extension is available + * + * @return boolean + */ + public static function getIsMbstringEnabled() + { + if (isset(self::$_isMbstringEnabled)) { + return self::$_isMbstringEnabled; + } + + self::$_isMbstringEnabled = function_exists('mb_convert_encoding') ? + true : false; + + return self::$_isMbstringEnabled; + } + + /** + * Get whether iconv extension is available + * + * @return boolean + */ + public static function getIsIconvEnabled() + { + if (isset(self::$_isIconvEnabled)) { + return self::$_isIconvEnabled; + } + + // Fail if iconv doesn't exist + if (!function_exists('iconv')) { + self::$_isIconvEnabled = false; + return false; + } + + // Sometimes iconv is not working, and e.g. iconv('UTF-8', 'UTF-16LE', 'x') just returns false, + if (!@iconv('UTF-8', 'UTF-16LE', 'x')) { + self::$_isIconvEnabled = false; + return false; + } + + // Sometimes iconv_substr('A', 0, 1, 'UTF-8') just returns false in PHP 5.2.0 + // we cannot use iconv in that case either (http://bugs.php.net/bug.php?id=37773) + if (!@iconv_substr('A', 0, 1, 'UTF-8')) { + self::$_isIconvEnabled = false; + return false; + } + + // CUSTOM: IBM AIX iconv() does not work + if ( defined('PHP_OS') && @stristr(PHP_OS, 'AIX') + && defined('ICONV_IMPL') && (@strcasecmp(ICONV_IMPL, 'unknown') == 0) + && defined('ICONV_VERSION') && (@strcasecmp(ICONV_VERSION, 'unknown') == 0) ) + { + self::$_isIconvEnabled = false; + return false; + } + + // If we reach here no problems were detected with iconv + self::$_isIconvEnabled = true; + return true; + } + + public static function buildCharacterSets() { + if(empty(self::$_controlCharacters)) { + self::_buildControlCharacters(); + } + if(empty(self::$_SYLKCharacters)) { + self::_buildSYLKCharacters(); + } + } + + /** + * Convert from OpenXML escaped control character to PHP control character + * + * Excel 2007 team: + * ---------------- + * That's correct, control characters are stored directly in the shared-strings table. + * We do encode characters that cannot be represented in XML using the following escape sequence: + * _xHHHH_ where H represents a hexadecimal character in the character's value... + * So you could end up with something like _x0008_ in a string (either in a cell value (<v>) + * element or in the shared string <t> element. + * + * @param string $value Value to unescape + * @return string + */ + public static function ControlCharacterOOXML2PHP($value = '') { + return str_replace( array_keys(self::$_controlCharacters), array_values(self::$_controlCharacters), $value ); + } + + /** + * Convert from PHP control character to OpenXML escaped control character + * + * Excel 2007 team: + * ---------------- + * That's correct, control characters are stored directly in the shared-strings table. + * We do encode characters that cannot be represented in XML using the following escape sequence: + * _xHHHH_ where H represents a hexadecimal character in the character's value... + * So you could end up with something like _x0008_ in a string (either in a cell value (<v>) + * element or in the shared string <t> element. + * + * @param string $value Value to escape + * @return string + */ + public static function ControlCharacterPHP2OOXML($value = '') { + return str_replace( array_values(self::$_controlCharacters), array_keys(self::$_controlCharacters), $value ); + } + + /** + * Try to sanitize UTF8, stripping invalid byte sequences. Not perfect. Does not surrogate characters. + * + * @param string $value + * @return string + */ + public static function SanitizeUTF8($value) + { + if (self::getIsIconvEnabled()) { + $value = @iconv('UTF-8', 'UTF-8', $value); + return $value; + } + + if (self::getIsMbstringEnabled()) { + $value = mb_convert_encoding($value, 'UTF-8', 'UTF-8'); + return $value; + } + + // else, no conversion + return $value; + } + + /** + * Check if a string contains UTF8 data + * + * @param string $value + * @return boolean + */ + public static function IsUTF8($value = '') { + return utf8_encode(utf8_decode($value)) === $value; + } + + /** + * Formats a numeric value as a string for output in various output writers forcing + * point as decimal separator in case locale is other than English. + * + * @param mixed $value + * @return string + */ + public static function FormatNumber($value) { + if (is_float($value)) { + return str_replace(',', '.', $value); + } + return (string) $value; + } + + /** + * Converts a UTF-8 string into BIFF8 Unicode string data (8-bit string length) + * Writes the string using uncompressed notation, no rich text, no Asian phonetics + * If mbstring extension is not available, ASCII is assumed, and compressed notation is used + * although this will give wrong results for non-ASCII strings + * see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3 + * + * @param string $value UTF-8 encoded string + * @param mixed[] $arrcRuns Details of rich text runs in $value + * @return string + */ + public static function UTF8toBIFF8UnicodeShort($value, $arrcRuns = array()) + { + // character count + $ln = self::CountCharacters($value, 'UTF-8'); + // option flags + if(empty($arrcRuns)){ + $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? + 0x0001 : 0x0000; + $data = pack('CC', $ln, $opt); + // characters + $data .= self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8'); + } + else { + $data = pack('vC', $ln, 0x09); + $data .= pack('v', count($arrcRuns)); + // characters + $data .= self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8'); + foreach ($arrcRuns as $cRun){ + $data .= pack('v', $cRun['strlen']); + $data .= pack('v', $cRun['fontidx']); + } + } + return $data; + } + + /** + * Converts a UTF-8 string into BIFF8 Unicode string data (16-bit string length) + * Writes the string using uncompressed notation, no rich text, no Asian phonetics + * If mbstring extension is not available, ASCII is assumed, and compressed notation is used + * although this will give wrong results for non-ASCII strings + * see OpenOffice.org's Documentation of the Microsoft Excel File Format, sect. 2.5.3 + * + * @param string $value UTF-8 encoded string + * @return string + */ + public static function UTF8toBIFF8UnicodeLong($value) + { + // character count + $ln = self::CountCharacters($value, 'UTF-8'); + + // option flags + $opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? + 0x0001 : 0x0000; + + // characters + $chars = self::ConvertEncoding($value, 'UTF-16LE', 'UTF-8'); + + $data = pack('vC', $ln, $opt) . $chars; + return $data; + } + + /** + * Convert string from one encoding to another. First try mbstring, then iconv, finally strlen + * + * @param string $value + * @param string $to Encoding to convert to, e.g. 'UTF-8' + * @param string $from Encoding to convert from, e.g. 'UTF-16LE' + * @return string + */ + public static function ConvertEncoding($value, $to, $from) + { + if (self::getIsIconvEnabled()) { + return iconv($from, $to, $value); + } + + if (self::getIsMbstringEnabled()) { + return mb_convert_encoding($value, $to, $from); + } + + if($from == 'UTF-16LE'){ + return self::utf16_decode($value, false); + }else if($from == 'UTF-16BE'){ + return self::utf16_decode($value); + } + // else, no conversion + return $value; + } + + /** + * Decode UTF-16 encoded strings. + * + * Can handle both BOM'ed data and un-BOM'ed data. + * Assumes Big-Endian byte order if no BOM is available. + * This function was taken from http://php.net/manual/en/function.utf8-decode.php + * and $bom_be parameter added. + * + * @param string $str UTF-16 encoded data to decode. + * @return string UTF-8 / ISO encoded data. + * @access public + * @version 0.2 / 2010-05-13 + * @author Rasmus Andersson {@link http://rasmusandersson.se/} + * @author vadik56 + */ + public static function utf16_decode($str, $bom_be = TRUE) { + if( strlen($str) < 2 ) return $str; + $c0 = ord($str{0}); + $c1 = ord($str{1}); + if( $c0 == 0xfe && $c1 == 0xff ) { $str = substr($str,2); } + elseif( $c0 == 0xff && $c1 == 0xfe ) { $str = substr($str,2); $bom_be = false; } + $len = strlen($str); + $newstr = ''; + for($i=0;$i<$len;$i+=2) { + if( $bom_be ) { $val = ord($str{$i}) << 4; $val += ord($str{$i+1}); } + else { $val = ord($str{$i+1}) << 4; $val += ord($str{$i}); } + $newstr .= ($val == 0x228) ? "\n" : chr($val); + } + return $newstr; + } + + /** + * Get character count. First try mbstring, then iconv, finally strlen + * + * @param string $value + * @param string $enc Encoding + * @return int Character count + */ + public static function CountCharacters($value, $enc = 'UTF-8') + { + if (self::getIsMbstringEnabled()) { + return mb_strlen($value, $enc); + } + + if (self::getIsIconvEnabled()) { + return iconv_strlen($value, $enc); + } + + // else strlen + return strlen($value); + } + + /** + * Get a substring of a UTF-8 encoded string. First try mbstring, then iconv, finally strlen + * + * @param string $pValue UTF-8 encoded string + * @param int $pStart Start offset + * @param int $pLength Maximum number of characters in substring + * @return string + */ + public static function Substring($pValue = '', $pStart = 0, $pLength = 0) + { + if (self::getIsMbstringEnabled()) { + return mb_substr($pValue, $pStart, $pLength, 'UTF-8'); + } + + if (self::getIsIconvEnabled()) { + return iconv_substr($pValue, $pStart, $pLength, 'UTF-8'); + } + + // else substr + return substr($pValue, $pStart, $pLength); + } + + /** + * Convert a UTF-8 encoded string to upper case + * + * @param string $pValue UTF-8 encoded string + * @return string + */ + public static function StrToUpper($pValue = '') + { + if (function_exists('mb_convert_case')) { + return mb_convert_case($pValue, MB_CASE_UPPER, "UTF-8"); + } + return strtoupper($pValue); + } + + /** + * Convert a UTF-8 encoded string to lower case + * + * @param string $pValue UTF-8 encoded string + * @return string + */ + public static function StrToLower($pValue = '') + { + if (function_exists('mb_convert_case')) { + return mb_convert_case($pValue, MB_CASE_LOWER, "UTF-8"); + } + return strtolower($pValue); + } + + /** + * Convert a UTF-8 encoded string to title/proper case + * (uppercase every first character in each word, lower case all other characters) + * + * @param string $pValue UTF-8 encoded string + * @return string + */ + public static function StrToTitle($pValue = '') + { + if (function_exists('mb_convert_case')) { + return mb_convert_case($pValue, MB_CASE_TITLE, "UTF-8"); + } + return ucwords($pValue); + } + + /** + * Identify whether a string contains a fractional numeric value, + * and convert it to a numeric if it is + * + * @param string &$operand string value to test + * @return boolean + */ + public static function convertToNumberIfFraction(&$operand) { + if (preg_match('/^'.self::STRING_REGEXP_FRACTION.'$/i', $operand, $match)) { + $sign = ($match[1] == '-') ? '-' : '+'; + $fractionFormula = '='.$sign.$match[2].$sign.$match[3]; + $operand = PHPExcel_Calculation::getInstance()->_calculateFormulaValue($fractionFormula); + return true; + } + return false; + } // function convertToNumberIfFraction() + + /** + * Get the decimal separator. If it has not yet been set explicitly, try to obtain number + * formatting information from locale. + * + * @return string + */ + public static function getDecimalSeparator() + { + if (!isset(self::$_decimalSeparator)) { + $localeconv = localeconv(); + self::$_decimalSeparator = ($localeconv['decimal_point'] != '') + ? $localeconv['decimal_point'] : $localeconv['mon_decimal_point']; + + if (self::$_decimalSeparator == '') { + // Default to . + self::$_decimalSeparator = '.'; + } + } + return self::$_decimalSeparator; + } + + /** + * Set the decimal separator. Only used by PHPExcel_Style_NumberFormat::toFormattedString() + * to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF + * + * @param string $pValue Character for decimal separator + */ + public static function setDecimalSeparator($pValue = '.') + { + self::$_decimalSeparator = $pValue; + } + + /** + * Get the thousands separator. If it has not yet been set explicitly, try to obtain number + * formatting information from locale. + * + * @return string + */ + public static function getThousandsSeparator() + { + if (!isset(self::$_thousandsSeparator)) { + $localeconv = localeconv(); + self::$_thousandsSeparator = ($localeconv['thousands_sep'] != '') + ? $localeconv['thousands_sep'] : $localeconv['mon_thousands_sep']; + + if (self::$_thousandsSeparator == '') { + // Default to . + self::$_thousandsSeparator = ','; + } + } + return self::$_thousandsSeparator; + } + + /** + * Set the thousands separator. Only used by PHPExcel_Style_NumberFormat::toFormattedString() + * to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF + * + * @param string $pValue Character for thousands separator + */ + public static function setThousandsSeparator($pValue = ',') + { + self::$_thousandsSeparator = $pValue; + } + + /** + * Get the currency code. If it has not yet been set explicitly, try to obtain the + * symbol information from locale. + * + * @return string + */ + public static function getCurrencyCode() + { + if (!isset(self::$_currencyCode)) { + $localeconv = localeconv(); + self::$_currencyCode = ($localeconv['currency_symbol'] != '') + ? $localeconv['currency_symbol'] : $localeconv['int_curr_symbol']; + + if (self::$_currencyCode == '') { + // Default to $ + self::$_currencyCode = '$'; + } + } + return self::$_currencyCode; + } + + /** + * Set the currency code. Only used by PHPExcel_Style_NumberFormat::toFormattedString() + * to format output by PHPExcel_Writer_HTML and PHPExcel_Writer_PDF + * + * @param string $pValue Character for currency code + */ + public static function setCurrencyCode($pValue = '$') + { + self::$_currencyCode = $pValue; + } + + /** + * Convert SYLK encoded string to UTF-8 + * + * @param string $pValue + * @return string UTF-8 encoded string + */ + public static function SYLKtoUTF8($pValue = '') + { + // If there is no escape character in the string there is nothing to do + if (strpos($pValue, '') === false) { + return $pValue; + } + + foreach (self::$_SYLKCharacters as $k => $v) { + $pValue = str_replace($k, $v, $pValue); + } + + return $pValue; + } + + /** + * Retrieve any leading numeric part of a string, or return the full string if no leading numeric + * (handles basic integer or float, but not exponent or non decimal) + * + * @param string $value + * @return mixed string or only the leading numeric part of the string + */ + public static function testStringAsNumeric($value) + { + if (is_numeric($value)) + return $value; + $v = floatval($value); + return (is_numeric(substr($value,0,strlen($v)))) ? $v : $value; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/TimeZone.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/TimeZone.php new file mode 100755 index 0000000..bc92a46 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/TimeZone.php @@ -0,0 +1,140 @@ +<?php + +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Shared_TimeZone + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_TimeZone +{ + /* + * Default Timezone used for date/time conversions + * + * @private + * @var string + */ + protected static $_timezone = 'UTC'; + + /** + * Validate a Timezone name + * + * @param string $timezone Time zone (e.g. 'Europe/London') + * @return boolean Success or failure + */ + public static function _validateTimeZone($timezone) { + if (in_array($timezone, DateTimeZone::listIdentifiers())) { + return TRUE; + } + return FALSE; + } + + /** + * Set the Default Timezone used for date/time conversions + * + * @param string $timezone Time zone (e.g. 'Europe/London') + * @return boolean Success or failure + */ + public static function setTimeZone($timezone) { + if (self::_validateTimezone($timezone)) { + self::$_timezone = $timezone; + return TRUE; + } + return FALSE; + } // function setTimezone() + + + /** + * Return the Default Timezone used for date/time conversions + * + * @return string Timezone (e.g. 'Europe/London') + */ + public static function getTimeZone() { + return self::$_timezone; + } // function getTimezone() + + + /** + * Return the Timezone transition for the specified timezone and timestamp + * + * @param DateTimeZone $objTimezone The timezone for finding the transitions + * @param integer $timestamp PHP date/time value for finding the current transition + * @return array The current transition details + */ + private static function _getTimezoneTransitions($objTimezone, $timestamp) { + $allTransitions = $objTimezone->getTransitions(); + $transitions = array(); + foreach($allTransitions as $key => $transition) { + if ($transition['ts'] > $timestamp) { + $transitions[] = ($key > 0) ? $allTransitions[$key - 1] : $transition; + break; + } + if (empty($transitions)) { + $transitions[] = end($allTransitions); + } + } + + return $transitions; + } + + /** + * Return the Timezone offset used for date/time conversions to/from UST + * This requires both the timezone and the calculated date/time to allow for local DST + * + * @param string $timezone The timezone for finding the adjustment to UST + * @param integer $timestamp PHP date/time value + * @return integer Number of seconds for timezone adjustment + * @throws PHPExcel_Exception + */ + public static function getTimeZoneAdjustment($timezone, $timestamp) { + if ($timezone !== NULL) { + if (!self::_validateTimezone($timezone)) { + throw new PHPExcel_Exception("Invalid timezone " . $timezone); + } + } else { + $timezone = self::$_timezone; + } + + if ($timezone == 'UST') { + return 0; + } + + $objTimezone = new DateTimeZone($timezone); + if (version_compare(PHP_VERSION, '5.3.0') >= 0) { + $transitions = $objTimezone->getTransitions($timestamp,$timestamp); + } else { + $transitions = self::_getTimezoneTransitions($objTimezone, $timestamp); + } + + return (count($transitions) > 0) ? $transitions[0]['offset'] : 0; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/XMLWriter.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/XMLWriter.php new file mode 100755 index 0000000..86476fa --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/XMLWriter.php @@ -0,0 +1,127 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +if (!defined('DATE_W3C')) { + define('DATE_W3C', 'Y-m-d\TH:i:sP'); +} + +if (!defined('DEBUGMODE_ENABLED')) { + define('DEBUGMODE_ENABLED', false); +} + + +/** + * PHPExcel_Shared_XMLWriter + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_XMLWriter extends XMLWriter { + /** Temporary storage method */ + const STORAGE_MEMORY = 1; + const STORAGE_DISK = 2; + + /** + * Temporary filename + * + * @var string + */ + private $_tempFileName = ''; + + /** + * Create a new PHPExcel_Shared_XMLWriter instance + * + * @param int $pTemporaryStorage Temporary storage location + * @param string $pTemporaryStorageFolder Temporary storage folder + */ + public function __construct($pTemporaryStorage = self::STORAGE_MEMORY, $pTemporaryStorageFolder = NULL) { + // Open temporary storage + if ($pTemporaryStorage == self::STORAGE_MEMORY) { + $this->openMemory(); + } else { + // Create temporary filename + if ($pTemporaryStorageFolder === NULL) + $pTemporaryStorageFolder = PHPExcel_Shared_File::sys_get_temp_dir(); + $this->_tempFileName = @tempnam($pTemporaryStorageFolder, 'xml'); + + // Open storage + if ($this->openUri($this->_tempFileName) === false) { + // Fallback to memory... + $this->openMemory(); + } + } + + // Set default values + if (DEBUGMODE_ENABLED) { + $this->setIndent(true); + } + } + + /** + * Destructor + */ + public function __destruct() { + // Unlink temporary files + if ($this->_tempFileName != '') { + @unlink($this->_tempFileName); + } + } + + /** + * Get written data + * + * @return $data + */ + public function getData() { + if ($this->_tempFileName == '') { + return $this->outputMemory(true); + } else { + $this->flush(); + return file_get_contents($this->_tempFileName); + } + } + + /** + * Fallback method for writeRaw, introduced in PHP 5.2 + * + * @param string $text + * @return string + */ + public function writeRawData($text) + { + if (is_array($text)) { + $text = implode("\n",$text); + } + + if (method_exists($this, 'writeRaw')) { + return $this->writeRaw(htmlspecialchars($text)); + } + + return $this->text($text); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/ZipArchive.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/ZipArchive.php new file mode 100755 index 0000000..06afc90 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/ZipArchive.php @@ -0,0 +1,114 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_ZipArchive + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +if (!defined('PCLZIP_TEMPORARY_DIR')) { + define('PCLZIP_TEMPORARY_DIR', PHPExcel_Shared_File::sys_get_temp_dir()); +} +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/PCLZip/pclzip.lib.php'; + + +/** + * PHPExcel_Shared_ZipArchive + * + * @category PHPExcel + * @package PHPExcel_Shared_ZipArchive + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_ZipArchive +{ + + /** constants */ + const OVERWRITE = 'OVERWRITE'; + const CREATE = 'CREATE'; + + + /** + * Temporary storage directory + * + * @var string + */ + private $_tempDir; + + /** + * Zip Archive Stream Handle + * + * @var string + */ + private $_zip; + + + /** + * Open a new zip archive + * + * @param string $fileName Filename for the zip archive + * @return boolean + */ + public function open($fileName) + { + $this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); + + $this->_zip = new PclZip($fileName); + + return true; + } + + + /** + * Close this zip archive + * + */ + public function close() + { + } + + + /** + * Add a new file to the zip archive from a string of raw data. + * + * @param string $localname Directory/Name of the file to add to the zip archive + * @param string $contents String of data to add to the zip archive + */ + public function addFromString($localname, $contents) + { + $filenameParts = pathinfo($localname); + + $handle = fopen($this->_tempDir.'/'.$filenameParts["basename"], "wb"); + fwrite($handle, $contents); + fclose($handle); + + $res = $this->_zip->add($this->_tempDir.'/'.$filenameParts["basename"], + PCLZIP_OPT_REMOVE_PATH, $this->_tempDir, + PCLZIP_OPT_ADD_PATH, $filenameParts["dirname"] + ); + if ($res == 0) { + throw new PHPExcel_Writer_Exception("Error zipping files : " . $this->_zip->errorInfo(true)); + } + + unlink($this->_tempDir.'/'.$filenameParts["basename"]); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/ZipStreamWrapper.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/ZipStreamWrapper.php new file mode 100755 index 0000000..cbd893d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/ZipStreamWrapper.php @@ -0,0 +1,201 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Shared_ZipStreamWrapper + * + * @category PHPExcel + * @package PHPExcel_Shared + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Shared_ZipStreamWrapper { + /** + * Internal ZipAcrhive + * + * @var ZipAcrhive + */ + private $_archive; + + /** + * Filename in ZipAcrhive + * + * @var string + */ + private $_fileNameInArchive = ''; + + /** + * Position in file + * + * @var int + */ + private $_position = 0; + + /** + * Data + * + * @var mixed + */ + private $_data = ''; + + /** + * Register wrapper + */ + public static function register() { + @stream_wrapper_unregister("zip"); + @stream_wrapper_register("zip", __CLASS__); + } + + /** + * Implements support for fopen(). + * + * @param string $path resource name including scheme, e.g. + * @param string $mode only "r" is supported + * @param int $options mask of STREAM_REPORT_ERRORS and STREAM_USE_PATH + * @param string &$openedPath absolute path of the opened stream (out parameter) + * @return bool true on success + */ + public function stream_open($path, $mode, $options, &$opened_path) { + // Check for mode + if ($mode{0} != 'r') { + throw new PHPExcel_Reader_Exception('Mode ' . $mode . ' is not supported. Only read mode is supported.'); + } + + $pos = strrpos($path, '#'); + $url['host'] = substr($path, 6, $pos - 6); // 6: strlen('zip://') + $url['fragment'] = substr($path, $pos + 1); + + // Open archive + $this->_archive = new ZipArchive(); + $this->_archive->open($url['host']); + + $this->_fileNameInArchive = $url['fragment']; + $this->_position = 0; + $this->_data = $this->_archive->getFromName( $this->_fileNameInArchive ); + + return true; + } + + /** + * Implements support for fstat(). + * + * @return boolean + */ + public function statName() { + return $this->_fileNameInArchive; + } + + /** + * Implements support for fstat(). + * + * @return boolean + */ + public function url_stat() { + return $this->statName( $this->_fileNameInArchive ); + } + + /** + * Implements support for fstat(). + * + * @return boolean + */ + public function stream_stat() { + return $this->_archive->statName( $this->_fileNameInArchive ); + } + + /** + * Implements support for fread(), fgets() etc. + * + * @param int $count maximum number of bytes to read + * @return string + */ + function stream_read($count) { + $ret = substr($this->_data, $this->_position, $count); + $this->_position += strlen($ret); + return $ret; + } + + /** + * Returns the position of the file pointer, i.e. its offset into the file + * stream. Implements support for ftell(). + * + * @return int + */ + public function stream_tell() { + return $this->_position; + } + + /** + * EOF stream + * + * @return bool + */ + public function stream_eof() { + return $this->_position >= strlen($this->_data); + } + + /** + * Seek stream + * + * @param int $offset byte offset + * @param int $whence SEEK_SET, SEEK_CUR or SEEK_END + * @return bool + */ + public function stream_seek($offset, $whence) { + switch ($whence) { + case SEEK_SET: + if ($offset < strlen($this->_data) && $offset >= 0) { + $this->_position = $offset; + return true; + } else { + return false; + } + break; + + case SEEK_CUR: + if ($offset >= 0) { + $this->_position += $offset; + return true; + } else { + return false; + } + break; + + case SEEK_END: + if (strlen($this->_data) + $offset >= 0) { + $this->_position = strlen($this->_data) + $offset; + return true; + } else { + return false; + } + break; + + default: + return false; + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/bestFitClass.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/bestFitClass.php new file mode 100755 index 0000000..067cf35 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/bestFitClass.php @@ -0,0 +1,432 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Best_Fit + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Best_Fit +{ + /** + * Indicator flag for a calculation error + * + * @var boolean + **/ + protected $_error = False; + + /** + * Algorithm type to use for best-fit + * + * @var string + **/ + protected $_bestFitType = 'undetermined'; + + /** + * Number of entries in the sets of x- and y-value arrays + * + * @var int + **/ + protected $_valueCount = 0; + + /** + * X-value dataseries of values + * + * @var float[] + **/ + protected $_xValues = array(); + + /** + * Y-value dataseries of values + * + * @var float[] + **/ + protected $_yValues = array(); + + /** + * Flag indicating whether values should be adjusted to Y=0 + * + * @var boolean + **/ + protected $_adjustToZero = False; + + /** + * Y-value series of best-fit values + * + * @var float[] + **/ + protected $_yBestFitValues = array(); + + protected $_goodnessOfFit = 1; + + protected $_stdevOfResiduals = 0; + + protected $_covariance = 0; + + protected $_correlation = 0; + + protected $_SSRegression = 0; + + protected $_SSResiduals = 0; + + protected $_DFResiduals = 0; + + protected $_F = 0; + + protected $_slope = 0; + + protected $_slopeSE = 0; + + protected $_intersect = 0; + + protected $_intersectSE = 0; + + protected $_Xoffset = 0; + + protected $_Yoffset = 0; + + + public function getError() { + return $this->_error; + } // function getBestFitType() + + + public function getBestFitType() { + return $this->_bestFitType; + } // function getBestFitType() + + + /** + * Return the Y-Value for a specified value of X + * + * @param float $xValue X-Value + * @return float Y-Value + */ + public function getValueOfYForX($xValue) { + return False; + } // function getValueOfYForX() + + + /** + * Return the X-Value for a specified value of Y + * + * @param float $yValue Y-Value + * @return float X-Value + */ + public function getValueOfXForY($yValue) { + return False; + } // function getValueOfXForY() + + + /** + * Return the original set of X-Values + * + * @return float[] X-Values + */ + public function getXValues() { + return $this->_xValues; + } // function getValueOfXForY() + + + /** + * Return the Equation of the best-fit line + * + * @param int $dp Number of places of decimal precision to display + * @return string + */ + public function getEquation($dp=0) { + return False; + } // function getEquation() + + + /** + * Return the Slope of the line + * + * @param int $dp Number of places of decimal precision to display + * @return string + */ + public function getSlope($dp=0) { + if ($dp != 0) { + return round($this->_slope,$dp); + } + return $this->_slope; + } // function getSlope() + + + /** + * Return the standard error of the Slope + * + * @param int $dp Number of places of decimal precision to display + * @return string + */ + public function getSlopeSE($dp=0) { + if ($dp != 0) { + return round($this->_slopeSE,$dp); + } + return $this->_slopeSE; + } // function getSlopeSE() + + + /** + * Return the Value of X where it intersects Y = 0 + * + * @param int $dp Number of places of decimal precision to display + * @return string + */ + public function getIntersect($dp=0) { + if ($dp != 0) { + return round($this->_intersect,$dp); + } + return $this->_intersect; + } // function getIntersect() + + + /** + * Return the standard error of the Intersect + * + * @param int $dp Number of places of decimal precision to display + * @return string + */ + public function getIntersectSE($dp=0) { + if ($dp != 0) { + return round($this->_intersectSE,$dp); + } + return $this->_intersectSE; + } // function getIntersectSE() + + + /** + * Return the goodness of fit for this regression + * + * @param int $dp Number of places of decimal precision to return + * @return float + */ + public function getGoodnessOfFit($dp=0) { + if ($dp != 0) { + return round($this->_goodnessOfFit,$dp); + } + return $this->_goodnessOfFit; + } // function getGoodnessOfFit() + + + public function getGoodnessOfFitPercent($dp=0) { + if ($dp != 0) { + return round($this->_goodnessOfFit * 100,$dp); + } + return $this->_goodnessOfFit * 100; + } // function getGoodnessOfFitPercent() + + + /** + * Return the standard deviation of the residuals for this regression + * + * @param int $dp Number of places of decimal precision to return + * @return float + */ + public function getStdevOfResiduals($dp=0) { + if ($dp != 0) { + return round($this->_stdevOfResiduals,$dp); + } + return $this->_stdevOfResiduals; + } // function getStdevOfResiduals() + + + public function getSSRegression($dp=0) { + if ($dp != 0) { + return round($this->_SSRegression,$dp); + } + return $this->_SSRegression; + } // function getSSRegression() + + + public function getSSResiduals($dp=0) { + if ($dp != 0) { + return round($this->_SSResiduals,$dp); + } + return $this->_SSResiduals; + } // function getSSResiduals() + + + public function getDFResiduals($dp=0) { + if ($dp != 0) { + return round($this->_DFResiduals,$dp); + } + return $this->_DFResiduals; + } // function getDFResiduals() + + + public function getF($dp=0) { + if ($dp != 0) { + return round($this->_F,$dp); + } + return $this->_F; + } // function getF() + + + public function getCovariance($dp=0) { + if ($dp != 0) { + return round($this->_covariance,$dp); + } + return $this->_covariance; + } // function getCovariance() + + + public function getCorrelation($dp=0) { + if ($dp != 0) { + return round($this->_correlation,$dp); + } + return $this->_correlation; + } // function getCorrelation() + + + public function getYBestFitValues() { + return $this->_yBestFitValues; + } // function getYBestFitValues() + + + protected function _calculateGoodnessOfFit($sumX,$sumY,$sumX2,$sumY2,$sumXY,$meanX,$meanY, $const) { + $SSres = $SScov = $SScor = $SStot = $SSsex = 0.0; + foreach($this->_xValues as $xKey => $xValue) { + $bestFitY = $this->_yBestFitValues[$xKey] = $this->getValueOfYForX($xValue); + + $SSres += ($this->_yValues[$xKey] - $bestFitY) * ($this->_yValues[$xKey] - $bestFitY); + if ($const) { + $SStot += ($this->_yValues[$xKey] - $meanY) * ($this->_yValues[$xKey] - $meanY); + } else { + $SStot += $this->_yValues[$xKey] * $this->_yValues[$xKey]; + } + $SScov += ($this->_xValues[$xKey] - $meanX) * ($this->_yValues[$xKey] - $meanY); + if ($const) { + $SSsex += ($this->_xValues[$xKey] - $meanX) * ($this->_xValues[$xKey] - $meanX); + } else { + $SSsex += $this->_xValues[$xKey] * $this->_xValues[$xKey]; + } + } + + $this->_SSResiduals = $SSres; + $this->_DFResiduals = $this->_valueCount - 1 - $const; + + if ($this->_DFResiduals == 0.0) { + $this->_stdevOfResiduals = 0.0; + } else { + $this->_stdevOfResiduals = sqrt($SSres / $this->_DFResiduals); + } + if (($SStot == 0.0) || ($SSres == $SStot)) { + $this->_goodnessOfFit = 1; + } else { + $this->_goodnessOfFit = 1 - ($SSres / $SStot); + } + + $this->_SSRegression = $this->_goodnessOfFit * $SStot; + $this->_covariance = $SScov / $this->_valueCount; + $this->_correlation = ($this->_valueCount * $sumXY - $sumX * $sumY) / sqrt(($this->_valueCount * $sumX2 - pow($sumX,2)) * ($this->_valueCount * $sumY2 - pow($sumY,2))); + $this->_slopeSE = $this->_stdevOfResiduals / sqrt($SSsex); + $this->_intersectSE = $this->_stdevOfResiduals * sqrt(1 / ($this->_valueCount - ($sumX * $sumX) / $sumX2)); + if ($this->_SSResiduals != 0.0) { + if ($this->_DFResiduals == 0.0) { + $this->_F = 0.0; + } else { + $this->_F = $this->_SSRegression / ($this->_SSResiduals / $this->_DFResiduals); + } + } else { + if ($this->_DFResiduals == 0.0) { + $this->_F = 0.0; + } else { + $this->_F = $this->_SSRegression / $this->_DFResiduals; + } + } + } // function _calculateGoodnessOfFit() + + + protected function _leastSquareFit($yValues, $xValues, $const) { + // calculate sums + $x_sum = array_sum($xValues); + $y_sum = array_sum($yValues); + $meanX = $x_sum / $this->_valueCount; + $meanY = $y_sum / $this->_valueCount; + $mBase = $mDivisor = $xx_sum = $xy_sum = $yy_sum = 0.0; + for($i = 0; $i < $this->_valueCount; ++$i) { + $xy_sum += $xValues[$i] * $yValues[$i]; + $xx_sum += $xValues[$i] * $xValues[$i]; + $yy_sum += $yValues[$i] * $yValues[$i]; + + if ($const) { + $mBase += ($xValues[$i] - $meanX) * ($yValues[$i] - $meanY); + $mDivisor += ($xValues[$i] - $meanX) * ($xValues[$i] - $meanX); + } else { + $mBase += $xValues[$i] * $yValues[$i]; + $mDivisor += $xValues[$i] * $xValues[$i]; + } + } + + // calculate slope +// $this->_slope = (($this->_valueCount * $xy_sum) - ($x_sum * $y_sum)) / (($this->_valueCount * $xx_sum) - ($x_sum * $x_sum)); + $this->_slope = $mBase / $mDivisor; + + // calculate intersect +// $this->_intersect = ($y_sum - ($this->_slope * $x_sum)) / $this->_valueCount; + if ($const) { + $this->_intersect = $meanY - ($this->_slope * $meanX); + } else { + $this->_intersect = 0; + } + + $this->_calculateGoodnessOfFit($x_sum,$y_sum,$xx_sum,$yy_sum,$xy_sum,$meanX,$meanY,$const); + } // function _leastSquareFit() + + + /** + * Define the regression + * + * @param float[] $yValues The set of Y-values for this regression + * @param float[] $xValues The set of X-values for this regression + * @param boolean $const + */ + function __construct($yValues, $xValues=array(), $const=True) { + // Calculate number of points + $nY = count($yValues); + $nX = count($xValues); + + // Define X Values if necessary + if ($nX == 0) { + $xValues = range(1,$nY); + $nX = $nY; + } elseif ($nY != $nX) { + // Ensure both arrays of points are the same size + $this->_error = True; + return False; + } + + $this->_valueCount = $nY; + $this->_xValues = $xValues; + $this->_yValues = $yValues; + } // function __construct() + +} // class bestFit diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/exponentialBestFitClass.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/exponentialBestFitClass.php new file mode 100755 index 0000000..df8eeda --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/exponentialBestFitClass.php @@ -0,0 +1,148 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); + + +/** + * PHPExcel_Exponential_Best_Fit + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Exponential_Best_Fit extends PHPExcel_Best_Fit +{ + /** + * Algorithm type to use for best-fit + * (Name of this trend class) + * + * @var string + **/ + protected $_bestFitType = 'exponential'; + + + /** + * Return the Y-Value for a specified value of X + * + * @param float $xValue X-Value + * @return float Y-Value + **/ + public function getValueOfYForX($xValue) { + return $this->getIntersect() * pow($this->getSlope(),($xValue - $this->_Xoffset)); + } // function getValueOfYForX() + + + /** + * Return the X-Value for a specified value of Y + * + * @param float $yValue Y-Value + * @return float X-Value + **/ + public function getValueOfXForY($yValue) { + return log(($yValue + $this->_Yoffset) / $this->getIntersect()) / log($this->getSlope()); + } // function getValueOfXForY() + + + /** + * Return the Equation of the best-fit line + * + * @param int $dp Number of places of decimal precision to display + * @return string + **/ + public function getEquation($dp=0) { + $slope = $this->getSlope($dp); + $intersect = $this->getIntersect($dp); + + return 'Y = '.$intersect.' * '.$slope.'^X'; + } // function getEquation() + + + /** + * Return the Slope of the line + * + * @param int $dp Number of places of decimal precision to display + * @return string + **/ + public function getSlope($dp=0) { + if ($dp != 0) { + return round(exp($this->_slope),$dp); + } + return exp($this->_slope); + } // function getSlope() + + + /** + * Return the Value of X where it intersects Y = 0 + * + * @param int $dp Number of places of decimal precision to display + * @return string + **/ + public function getIntersect($dp=0) { + if ($dp != 0) { + return round(exp($this->_intersect),$dp); + } + return exp($this->_intersect); + } // function getIntersect() + + + /** + * Execute the regression and calculate the goodness of fit for a set of X and Y data values + * + * @param float[] $yValues The set of Y-values for this regression + * @param float[] $xValues The set of X-values for this regression + * @param boolean $const + */ + private function _exponential_regression($yValues, $xValues, $const) { + foreach($yValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); + + $this->_leastSquareFit($yValues, $xValues, $const); + } // function _exponential_regression() + + + /** + * Define the regression and calculate the goodness of fit for a set of X and Y data values + * + * @param float[] $yValues The set of Y-values for this regression + * @param float[] $xValues The set of X-values for this regression + * @param boolean $const + */ + function __construct($yValues, $xValues=array(), $const=True) { + if (parent::__construct($yValues, $xValues) !== False) { + $this->_exponential_regression($yValues, $xValues, $const); + } + } // function __construct() + +} // class exponentialBestFit \ No newline at end of file diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/linearBestFitClass.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/linearBestFitClass.php new file mode 100755 index 0000000..635b6bd --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/linearBestFitClass.php @@ -0,0 +1,111 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); + + +/** + * PHPExcel_Linear_Best_Fit + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Linear_Best_Fit extends PHPExcel_Best_Fit +{ + /** + * Algorithm type to use for best-fit + * (Name of this trend class) + * + * @var string + **/ + protected $_bestFitType = 'linear'; + + + /** + * Return the Y-Value for a specified value of X + * + * @param float $xValue X-Value + * @return float Y-Value + **/ + public function getValueOfYForX($xValue) { + return $this->getIntersect() + $this->getSlope() * $xValue; + } // function getValueOfYForX() + + + /** + * Return the X-Value for a specified value of Y + * + * @param float $yValue Y-Value + * @return float X-Value + **/ + public function getValueOfXForY($yValue) { + return ($yValue - $this->getIntersect()) / $this->getSlope(); + } // function getValueOfXForY() + + + /** + * Return the Equation of the best-fit line + * + * @param int $dp Number of places of decimal precision to display + * @return string + **/ + public function getEquation($dp=0) { + $slope = $this->getSlope($dp); + $intersect = $this->getIntersect($dp); + + return 'Y = '.$intersect.' + '.$slope.' * X'; + } // function getEquation() + + + /** + * Execute the regression and calculate the goodness of fit for a set of X and Y data values + * + * @param float[] $yValues The set of Y-values for this regression + * @param float[] $xValues The set of X-values for this regression + * @param boolean $const + */ + private function _linear_regression($yValues, $xValues, $const) { + $this->_leastSquareFit($yValues, $xValues,$const); + } // function _linear_regression() + + + /** + * Define the regression and calculate the goodness of fit for a set of X and Y data values + * + * @param float[] $yValues The set of Y-values for this regression + * @param float[] $xValues The set of X-values for this regression + * @param boolean $const + */ + function __construct($yValues, $xValues=array(), $const=True) { + if (parent::__construct($yValues, $xValues) !== False) { + $this->_linear_regression($yValues, $xValues, $const); + } + } // function __construct() + +} // class linearBestFit \ No newline at end of file diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/logarithmicBestFitClass.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/logarithmicBestFitClass.php new file mode 100755 index 0000000..e89c240 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/logarithmicBestFitClass.php @@ -0,0 +1,120 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +require_once(PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'); + + +/** + * PHPExcel_Logarithmic_Best_Fit + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Logarithmic_Best_Fit extends PHPExcel_Best_Fit +{ + /** + * Algorithm type to use for best-fit + * (Name of this trend class) + * + * @var string + **/ + protected $_bestFitType = 'logarithmic'; + + + /** + * Return the Y-Value for a specified value of X + * + * @param float $xValue X-Value + * @return float Y-Value + **/ + public function getValueOfYForX($xValue) { + return $this->getIntersect() + $this->getSlope() * log($xValue - $this->_Xoffset); + } // function getValueOfYForX() + + + /** + * Return the X-Value for a specified value of Y + * + * @param float $yValue Y-Value + * @return float X-Value + **/ + public function getValueOfXForY($yValue) { + return exp(($yValue - $this->getIntersect()) / $this->getSlope()); + } // function getValueOfXForY() + + + /** + * Return the Equation of the best-fit line + * + * @param int $dp Number of places of decimal precision to display + * @return string + **/ + public function getEquation($dp=0) { + $slope = $this->getSlope($dp); + $intersect = $this->getIntersect($dp); + + return 'Y = '.$intersect.' + '.$slope.' * log(X)'; + } // function getEquation() + + + /** + * Execute the regression and calculate the goodness of fit for a set of X and Y data values + * + * @param float[] $yValues The set of Y-values for this regression + * @param float[] $xValues The set of X-values for this regression + * @param boolean $const + */ + private function _logarithmic_regression($yValues, $xValues, $const) { + foreach($xValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); + + $this->_leastSquareFit($yValues, $xValues, $const); + } // function _logarithmic_regression() + + + /** + * Define the regression and calculate the goodness of fit for a set of X and Y data values + * + * @param float[] $yValues The set of Y-values for this regression + * @param float[] $xValues The set of X-values for this regression + * @param boolean $const + */ + function __construct($yValues, $xValues=array(), $const=True) { + if (parent::__construct($yValues, $xValues) !== False) { + $this->_logarithmic_regression($yValues, $xValues, $const); + } + } // function __construct() + +} // class logarithmicBestFit \ No newline at end of file diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/polynomialBestFitClass.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/polynomialBestFitClass.php new file mode 100755 index 0000000..73a5208 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/polynomialBestFitClass.php @@ -0,0 +1,224 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/JAMA/Matrix.php'; + + +/** + * PHPExcel_Polynomial_Best_Fit + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Polynomial_Best_Fit extends PHPExcel_Best_Fit +{ + /** + * Algorithm type to use for best-fit + * (Name of this trend class) + * + * @var string + **/ + protected $_bestFitType = 'polynomial'; + + /** + * Polynomial order + * + * @protected + * @var int + **/ + protected $_order = 0; + + + /** + * Return the order of this polynomial + * + * @return int + **/ + public function getOrder() { + return $this->_order; + } // function getOrder() + + + /** + * Return the Y-Value for a specified value of X + * + * @param float $xValue X-Value + * @return float Y-Value + **/ + public function getValueOfYForX($xValue) { + $retVal = $this->getIntersect(); + $slope = $this->getSlope(); + foreach($slope as $key => $value) { + if ($value != 0.0) { + $retVal += $value * pow($xValue, $key + 1); + } + } + return $retVal; + } // function getValueOfYForX() + + + /** + * Return the X-Value for a specified value of Y + * + * @param float $yValue Y-Value + * @return float X-Value + **/ + public function getValueOfXForY($yValue) { + return ($yValue - $this->getIntersect()) / $this->getSlope(); + } // function getValueOfXForY() + + + /** + * Return the Equation of the best-fit line + * + * @param int $dp Number of places of decimal precision to display + * @return string + **/ + public function getEquation($dp=0) { + $slope = $this->getSlope($dp); + $intersect = $this->getIntersect($dp); + + $equation = 'Y = '.$intersect; + foreach($slope as $key => $value) { + if ($value != 0.0) { + $equation .= ' + '.$value.' * X'; + if ($key > 0) { + $equation .= '^'.($key + 1); + } + } + } + return $equation; + } // function getEquation() + + + /** + * Return the Slope of the line + * + * @param int $dp Number of places of decimal precision to display + * @return string + **/ + public function getSlope($dp=0) { + if ($dp != 0) { + $coefficients = array(); + foreach($this->_slope as $coefficient) { + $coefficients[] = round($coefficient,$dp); + } + return $coefficients; + } + return $this->_slope; + } // function getSlope() + + + public function getCoefficients($dp=0) { + return array_merge(array($this->getIntersect($dp)),$this->getSlope($dp)); + } // function getCoefficients() + + + /** + * Execute the regression and calculate the goodness of fit for a set of X and Y data values + * + * @param int $order Order of Polynomial for this regression + * @param float[] $yValues The set of Y-values for this regression + * @param float[] $xValues The set of X-values for this regression + * @param boolean $const + */ + private function _polynomial_regression($order, $yValues, $xValues, $const) { + // calculate sums + $x_sum = array_sum($xValues); + $y_sum = array_sum($yValues); + $xx_sum = $xy_sum = 0; + for($i = 0; $i < $this->_valueCount; ++$i) { + $xy_sum += $xValues[$i] * $yValues[$i]; + $xx_sum += $xValues[$i] * $xValues[$i]; + $yy_sum += $yValues[$i] * $yValues[$i]; + } + /* + * This routine uses logic from the PHP port of polyfit version 0.1 + * written by Michael Bommarito and Paul Meagher + * + * The function fits a polynomial function of order $order through + * a series of x-y data points using least squares. + * + */ + for ($i = 0; $i < $this->_valueCount; ++$i) { + for ($j = 0; $j <= $order; ++$j) { + $A[$i][$j] = pow($xValues[$i], $j); + } + } + for ($i=0; $i < $this->_valueCount; ++$i) { + $B[$i] = array($yValues[$i]); + } + $matrixA = new Matrix($A); + $matrixB = new Matrix($B); + $C = $matrixA->solve($matrixB); + + $coefficients = array(); + for($i = 0; $i < $C->m; ++$i) { + $r = $C->get($i, 0); + if (abs($r) <= pow(10, -9)) { + $r = 0; + } + $coefficients[] = $r; + } + + $this->_intersect = array_shift($coefficients); + $this->_slope = $coefficients; + + $this->_calculateGoodnessOfFit($x_sum,$y_sum,$xx_sum,$yy_sum,$xy_sum); + foreach($this->_xValues as $xKey => $xValue) { + $this->_yBestFitValues[$xKey] = $this->getValueOfYForX($xValue); + } + } // function _polynomial_regression() + + + /** + * Define the regression and calculate the goodness of fit for a set of X and Y data values + * + * @param int $order Order of Polynomial for this regression + * @param float[] $yValues The set of Y-values for this regression + * @param float[] $xValues The set of X-values for this regression + * @param boolean $const + */ + function __construct($order, $yValues, $xValues=array(), $const=True) { + if (parent::__construct($yValues, $xValues) !== False) { + if ($order < $this->_valueCount) { + $this->_bestFitType .= '_'.$order; + $this->_order = $order; + $this->_polynomial_regression($order, $yValues, $xValues, $const); + if (($this->getGoodnessOfFit() < 0.0) || ($this->getGoodnessOfFit() > 1.0)) { + $this->_error = True; + } + } else { + $this->_error = True; + } + } + } // function __construct() + +} // class polynomialBestFit \ No newline at end of file diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/powerBestFitClass.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/powerBestFitClass.php new file mode 100755 index 0000000..e9b8e21 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/powerBestFitClass.php @@ -0,0 +1,142 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/bestFitClass.php'; + + +/** + * PHPExcel_Power_Best_Fit + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Power_Best_Fit extends PHPExcel_Best_Fit +{ + /** + * Algorithm type to use for best-fit + * (Name of this trend class) + * + * @var string + **/ + protected $_bestFitType = 'power'; + + + /** + * Return the Y-Value for a specified value of X + * + * @param float $xValue X-Value + * @return float Y-Value + **/ + public function getValueOfYForX($xValue) { + return $this->getIntersect() * pow(($xValue - $this->_Xoffset),$this->getSlope()); + } // function getValueOfYForX() + + + /** + * Return the X-Value for a specified value of Y + * + * @param float $yValue Y-Value + * @return float X-Value + **/ + public function getValueOfXForY($yValue) { + return pow((($yValue + $this->_Yoffset) / $this->getIntersect()),(1 / $this->getSlope())); + } // function getValueOfXForY() + + + /** + * Return the Equation of the best-fit line + * + * @param int $dp Number of places of decimal precision to display + * @return string + **/ + public function getEquation($dp=0) { + $slope = $this->getSlope($dp); + $intersect = $this->getIntersect($dp); + + return 'Y = '.$intersect.' * X^'.$slope; + } // function getEquation() + + + /** + * Return the Value of X where it intersects Y = 0 + * + * @param int $dp Number of places of decimal precision to display + * @return string + **/ + public function getIntersect($dp=0) { + if ($dp != 0) { + return round(exp($this->_intersect),$dp); + } + return exp($this->_intersect); + } // function getIntersect() + + + /** + * Execute the regression and calculate the goodness of fit for a set of X and Y data values + * + * @param float[] $yValues The set of Y-values for this regression + * @param float[] $xValues The set of X-values for this regression + * @param boolean $const + */ + private function _power_regression($yValues, $xValues, $const) { + foreach($xValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); + foreach($yValues as &$value) { + if ($value < 0.0) { + $value = 0 - log(abs($value)); + } elseif ($value > 0.0) { + $value = log($value); + } + } + unset($value); + + $this->_leastSquareFit($yValues, $xValues, $const); + } // function _power_regression() + + + /** + * Define the regression and calculate the goodness of fit for a set of X and Y data values + * + * @param float[] $yValues The set of Y-values for this regression + * @param float[] $xValues The set of X-values for this regression + * @param boolean $const + */ + function __construct($yValues, $xValues=array(), $const=True) { + if (parent::__construct($yValues, $xValues) !== False) { + $this->_power_regression($yValues, $xValues, $const); + } + } // function __construct() + +} // class powerBestFit \ No newline at end of file diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/trendClass.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/trendClass.php new file mode 100755 index 0000000..1c52885 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Shared/trend/trendClass.php @@ -0,0 +1,156 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/linearBestFitClass.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/logarithmicBestFitClass.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/exponentialBestFitClass.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/powerBestFitClass.php'; +require_once PHPEXCEL_ROOT . 'PHPExcel/Shared/trend/polynomialBestFitClass.php'; + + +/** + * PHPExcel_trendClass + * + * @category PHPExcel + * @package PHPExcel_Shared_Trend + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class trendClass +{ + const TREND_LINEAR = 'Linear'; + const TREND_LOGARITHMIC = 'Logarithmic'; + const TREND_EXPONENTIAL = 'Exponential'; + const TREND_POWER = 'Power'; + const TREND_POLYNOMIAL_2 = 'Polynomial_2'; + const TREND_POLYNOMIAL_3 = 'Polynomial_3'; + const TREND_POLYNOMIAL_4 = 'Polynomial_4'; + const TREND_POLYNOMIAL_5 = 'Polynomial_5'; + const TREND_POLYNOMIAL_6 = 'Polynomial_6'; + const TREND_BEST_FIT = 'Bestfit'; + const TREND_BEST_FIT_NO_POLY = 'Bestfit_no_Polynomials'; + + /** + * Names of the best-fit trend analysis methods + * + * @var string[] + **/ + private static $_trendTypes = array( self::TREND_LINEAR, + self::TREND_LOGARITHMIC, + self::TREND_EXPONENTIAL, + self::TREND_POWER + ); + /** + * Names of the best-fit trend polynomial orders + * + * @var string[] + **/ + private static $_trendTypePolyOrders = array( self::TREND_POLYNOMIAL_2, + self::TREND_POLYNOMIAL_3, + self::TREND_POLYNOMIAL_4, + self::TREND_POLYNOMIAL_5, + self::TREND_POLYNOMIAL_6 + ); + + /** + * Cached results for each method when trying to identify which provides the best fit + * + * @var PHPExcel_Best_Fit[] + **/ + private static $_trendCache = array(); + + + public static function calculate($trendType=self::TREND_BEST_FIT, $yValues, $xValues=array(), $const=True) { + // Calculate number of points in each dataset + $nY = count($yValues); + $nX = count($xValues); + + // Define X Values if necessary + if ($nX == 0) { + $xValues = range(1,$nY); + $nX = $nY; + } elseif ($nY != $nX) { + // Ensure both arrays of points are the same size + trigger_error("trend(): Number of elements in coordinate arrays do not match.", E_USER_ERROR); + } + + $key = md5($trendType.$const.serialize($yValues).serialize($xValues)); + // Determine which trend method has been requested + switch ($trendType) { + // Instantiate and return the class for the requested trend method + case self::TREND_LINEAR : + case self::TREND_LOGARITHMIC : + case self::TREND_EXPONENTIAL : + case self::TREND_POWER : + if (!isset(self::$_trendCache[$key])) { + $className = 'PHPExcel_'.$trendType.'_Best_Fit'; + self::$_trendCache[$key] = new $className($yValues,$xValues,$const); + } + return self::$_trendCache[$key]; + break; + case self::TREND_POLYNOMIAL_2 : + case self::TREND_POLYNOMIAL_3 : + case self::TREND_POLYNOMIAL_4 : + case self::TREND_POLYNOMIAL_5 : + case self::TREND_POLYNOMIAL_6 : + if (!isset(self::$_trendCache[$key])) { + $order = substr($trendType,-1); + self::$_trendCache[$key] = new PHPExcel_Polynomial_Best_Fit($order,$yValues,$xValues,$const); + } + return self::$_trendCache[$key]; + break; + case self::TREND_BEST_FIT : + case self::TREND_BEST_FIT_NO_POLY : + // If the request is to determine the best fit regression, then we test each trend line in turn + // Start by generating an instance of each available trend method + foreach(self::$_trendTypes as $trendMethod) { + $className = 'PHPExcel_'.$trendMethod.'BestFit'; + $bestFit[$trendMethod] = new $className($yValues,$xValues,$const); + $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit(); + } + if ($trendType != self::TREND_BEST_FIT_NO_POLY) { + foreach(self::$_trendTypePolyOrders as $trendMethod) { + $order = substr($trendMethod,-1); + $bestFit[$trendMethod] = new PHPExcel_Polynomial_Best_Fit($order,$yValues,$xValues,$const); + if ($bestFit[$trendMethod]->getError()) { + unset($bestFit[$trendMethod]); + } else { + $bestFitValue[$trendMethod] = $bestFit[$trendMethod]->getGoodnessOfFit(); + } + } + } + // Determine which of our trend lines is the best fit, and then we return the instance of that trend class + arsort($bestFitValue); + $bestFitType = key($bestFitValue); + return $bestFit[$bestFitType]; + break; + default : + return false; + } + } // function calculate() + +} // class trendClass \ No newline at end of file diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style.php new file mode 100755 index 0000000..4961968 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style.php @@ -0,0 +1,613 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Style + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Style extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable +{ + /** + * Font + * + * @var PHPExcel_Style_Font + */ + protected $_font; + + /** + * Fill + * + * @var PHPExcel_Style_Fill + */ + protected $_fill; + + /** + * Borders + * + * @var PHPExcel_Style_Borders + */ + protected $_borders; + + /** + * Alignment + * + * @var PHPExcel_Style_Alignment + */ + protected $_alignment; + + /** + * Number Format + * + * @var PHPExcel_Style_NumberFormat + */ + protected $_numberFormat; + + /** + * Conditional styles + * + * @var PHPExcel_Style_Conditional[] + */ + protected $_conditionalStyles; + + /** + * Protection + * + * @var PHPExcel_Style_Protection + */ + protected $_protection; + + /** + * Index of style in collection. Only used for real style. + * + * @var int + */ + protected $_index; + + /** + * Create a new PHPExcel_Style + * + * @param boolean $isSupervisor Flag indicating if this is a supervisor or not + * Leave this value at default unless you understand exactly what + * its ramifications are + * @param boolean $isConditional Flag indicating if this is a conditional style or not + * Leave this value at default unless you understand exactly what + * its ramifications are + */ + public function __construct($isSupervisor = false, $isConditional = false) + { + // Supervisor? + $this->_isSupervisor = $isSupervisor; + + // Initialise values + $this->_conditionalStyles = array(); + $this->_font = new PHPExcel_Style_Font($isSupervisor, $isConditional); + $this->_fill = new PHPExcel_Style_Fill($isSupervisor, $isConditional); + $this->_borders = new PHPExcel_Style_Borders($isSupervisor, $isConditional); + $this->_alignment = new PHPExcel_Style_Alignment($isSupervisor, $isConditional); + $this->_numberFormat = new PHPExcel_Style_NumberFormat($isSupervisor, $isConditional); + $this->_protection = new PHPExcel_Style_Protection($isSupervisor, $isConditional); + + // bind parent if we are a supervisor + if ($isSupervisor) { + $this->_font->bindParent($this); + $this->_fill->bindParent($this); + $this->_borders->bindParent($this); + $this->_alignment->bindParent($this); + $this->_numberFormat->bindParent($this); + $this->_protection->bindParent($this); + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style + */ + public function getSharedComponent() + { + $activeSheet = $this->getActiveSheet(); + $selectedCell = $this->getActiveCell(); // e.g. 'A1' + + if ($activeSheet->cellExists($selectedCell)) { + $xfIndex = $activeSheet->getCell($selectedCell)->getXfIndex(); + } else { + $xfIndex = 0; + } + + return $this->_parent->getCellXfByIndex($xfIndex); + } + + /** + * Get parent. Only used for style supervisor + * + * @return PHPExcel + */ + public function getParent() + { + return $this->_parent; + } + + /** + * Apply styles from array + * + * <code> + * $objPHPExcel->getActiveSheet()->getStyle('B2')->applyFromArray( + * array( + * 'font' => array( + * 'name' => 'Arial', + * 'bold' => true, + * 'italic' => false, + * 'underline' => PHPExcel_Style_Font::UNDERLINE_DOUBLE, + * 'strike' => false, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ), + * 'borders' => array( + * 'bottom' => array( + * 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ), + * 'top' => array( + * 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ) + * ) + * ) + * ); + * </code> + * + * @param array $pStyles Array containing style information + * @param boolean $pAdvanced Advanced mode for setting borders. + * @throws PHPExcel_Exception + * @return PHPExcel_Style + */ + public function applyFromArray($pStyles = null, $pAdvanced = true) + { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + + $pRange = $this->getSelectedCells(); + + // Uppercase coordinate + $pRange = strtoupper($pRange); + + // Is it a cell range or a single cell? + if (strpos($pRange, ':') === false) { + $rangeA = $pRange; + $rangeB = $pRange; + } else { + list($rangeA, $rangeB) = explode(':', $pRange); + } + + // Calculate range outer borders + $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); + $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); + + // Translate column into index + $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; + $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; + + // Make sure we can loop upwards on rows and columns + if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { + $tmp = $rangeStart; + $rangeStart = $rangeEnd; + $rangeEnd = $tmp; + } + + // ADVANCED MODE: + + if ($pAdvanced && isset($pStyles['borders'])) { + + // 'allborders' is a shorthand property for 'outline' and 'inside' and + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['allborders'])) { + foreach (array('outline', 'inside') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['allborders']; + } + } + unset($pStyles['borders']['allborders']); // not needed any more + } + + // 'outline' is a shorthand property for 'top', 'right', 'bottom', 'left' + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['outline'])) { + foreach (array('top', 'right', 'bottom', 'left') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['outline']; + } + } + unset($pStyles['borders']['outline']); // not needed any more + } + + // 'inside' is a shorthand property for 'vertical' and 'horizontal' + // it applies to components that have not been set explicitly + if (isset($pStyles['borders']['inside'])) { + foreach (array('vertical', 'horizontal') as $component) { + if (!isset($pStyles['borders'][$component])) { + $pStyles['borders'][$component] = $pStyles['borders']['inside']; + } + } + unset($pStyles['borders']['inside']); // not needed any more + } + + // width and height characteristics of selection, 1, 2, or 3 (for 3 or more) + $xMax = min($rangeEnd[0] - $rangeStart[0] + 1, 3); + $yMax = min($rangeEnd[1] - $rangeStart[1] + 1, 3); + + // loop through up to 3 x 3 = 9 regions + for ($x = 1; $x <= $xMax; ++$x) { + // start column index for region + $colStart = ($x == 3) ? + PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]) + : PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $x - 1); + + // end column index for region + $colEnd = ($x == 1) ? + PHPExcel_Cell::stringFromColumnIndex($rangeStart[0]) + : PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] - $xMax + $x); + + for ($y = 1; $y <= $yMax; ++$y) { + + // which edges are touching the region + $edges = array(); + + // are we at left edge + if ($x == 1) { + $edges[] = 'left'; + } + + // are we at right edge + if ($x == $xMax) { + $edges[] = 'right'; + } + + // are we at top edge? + if ($y == 1) { + $edges[] = 'top'; + } + + // are we at bottom edge? + if ($y == $yMax) { + $edges[] = 'bottom'; + } + + // start row index for region + $rowStart = ($y == 3) ? + $rangeEnd[1] : $rangeStart[1] + $y - 1; + + // end row index for region + $rowEnd = ($y == 1) ? + $rangeStart[1] : $rangeEnd[1] - $yMax + $y; + + // build range for region + $range = $colStart . $rowStart . ':' . $colEnd . $rowEnd; + + // retrieve relevant style array for region + $regionStyles = $pStyles; + unset($regionStyles['borders']['inside']); + + // what are the inner edges of the region when looking at the selection + $innerEdges = array_diff( array('top', 'right', 'bottom', 'left'), $edges ); + + // inner edges that are not touching the region should take the 'inside' border properties if they have been set + foreach ($innerEdges as $innerEdge) { + switch ($innerEdge) { + case 'top': + case 'bottom': + // should pick up 'horizontal' border property if set + if (isset($pStyles['borders']['horizontal'])) { + $regionStyles['borders'][$innerEdge] = $pStyles['borders']['horizontal']; + } else { + unset($regionStyles['borders'][$innerEdge]); + } + break; + case 'left': + case 'right': + // should pick up 'vertical' border property if set + if (isset($pStyles['borders']['vertical'])) { + $regionStyles['borders'][$innerEdge] = $pStyles['borders']['vertical']; + } else { + unset($regionStyles['borders'][$innerEdge]); + } + break; + } + } + + // apply region style to region by calling applyFromArray() in simple mode + $this->getActiveSheet()->getStyle($range)->applyFromArray($regionStyles, false); + } + } + return $this; + } + + // SIMPLE MODE: + + // Selection type, inspect + if (preg_match('/^[A-Z]+1:[A-Z]+1048576$/', $pRange)) { + $selectionType = 'COLUMN'; + } else if (preg_match('/^A[0-9]+:XFD[0-9]+$/', $pRange)) { + $selectionType = 'ROW'; + } else { + $selectionType = 'CELL'; + } + + // First loop through columns, rows, or cells to find out which styles are affected by this operation + switch ($selectionType) { + case 'COLUMN': + $oldXfIndexes = array(); + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + $oldXfIndexes[$this->getActiveSheet()->getColumnDimensionByColumn($col)->getXfIndex()] = true; + } + break; + + case 'ROW': + $oldXfIndexes = array(); + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + if ($this->getActiveSheet()->getRowDimension($row)->getXfIndex() == null) { + $oldXfIndexes[0] = true; // row without explicit style should be formatted based on default style + } else { + $oldXfIndexes[$this->getActiveSheet()->getRowDimension($row)->getXfIndex()] = true; + } + } + break; + + case 'CELL': + $oldXfIndexes = array(); + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $oldXfIndexes[$this->getActiveSheet()->getCellByColumnAndRow($col, $row)->getXfIndex()] = true; + } + } + break; + } + + // clone each of the affected styles, apply the style array, and add the new styles to the workbook + $workbook = $this->getActiveSheet()->getParent(); + foreach ($oldXfIndexes as $oldXfIndex => $dummy) { + $style = $workbook->getCellXfByIndex($oldXfIndex); + $newStyle = clone $style; + $newStyle->applyFromArray($pStyles); + + if ($workbook->cellXfExists($newStyle)) { + // there is already such cell Xf in our collection + $newXfIndexes[$oldXfIndex] = $existingStyle->getIndex(); + } else { + // we don't have such a cell Xf, need to add + $workbook->addCellXf($newStyle); + $newXfIndexes[$oldXfIndex] = $newStyle->getIndex(); + } + } + + // Loop through columns, rows, or cells again and update the XF index + switch ($selectionType) { + case 'COLUMN': + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + $columnDimension = $this->getActiveSheet()->getColumnDimensionByColumn($col); + $oldXfIndex = $columnDimension->getXfIndex(); + $columnDimension->setXfIndex($newXfIndexes[$oldXfIndex]); + } + break; + + case 'ROW': + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $rowDimension = $this->getActiveSheet()->getRowDimension($row); + $oldXfIndex = $rowDimension->getXfIndex() === null ? + 0 : $rowDimension->getXfIndex(); // row without explicit style should be formatted based on default style + $rowDimension->setXfIndex($newXfIndexes[$oldXfIndex]); + } + break; + + case 'CELL': + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $cell = $this->getActiveSheet()->getCellByColumnAndRow($col, $row); + $oldXfIndex = $cell->getXfIndex(); + $cell->setXfIndex($newXfIndexes[$oldXfIndex]); + } + } + break; + } + + } else { + // not a supervisor, just apply the style array directly on style object + if (array_key_exists('fill', $pStyles)) { + $this->getFill()->applyFromArray($pStyles['fill']); + } + if (array_key_exists('font', $pStyles)) { + $this->getFont()->applyFromArray($pStyles['font']); + } + if (array_key_exists('borders', $pStyles)) { + $this->getBorders()->applyFromArray($pStyles['borders']); + } + if (array_key_exists('alignment', $pStyles)) { + $this->getAlignment()->applyFromArray($pStyles['alignment']); + } + if (array_key_exists('numberformat', $pStyles)) { + $this->getNumberFormat()->applyFromArray($pStyles['numberformat']); + } + if (array_key_exists('protection', $pStyles)) { + $this->getProtection()->applyFromArray($pStyles['protection']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get Fill + * + * @return PHPExcel_Style_Fill + */ + public function getFill() + { + return $this->_fill; + } + + /** + * Get Font + * + * @return PHPExcel_Style_Font + */ + public function getFont() + { + return $this->_font; + } + + /** + * Set font + * + * @param PHPExcel_Style_Font $font + * @return PHPExcel_Style + */ + public function setFont(PHPExcel_Style_Font $font) + { + $this->_font = $font; + return $this; + } + + /** + * Get Borders + * + * @return PHPExcel_Style_Borders + */ + public function getBorders() + { + return $this->_borders; + } + + /** + * Get Alignment + * + * @return PHPExcel_Style_Alignment + */ + public function getAlignment() + { + return $this->_alignment; + } + + /** + * Get Number Format + * + * @return PHPExcel_Style_NumberFormat + */ + public function getNumberFormat() + { + return $this->_numberFormat; + } + + /** + * Get Conditional Styles. Only used on supervisor. + * + * @return PHPExcel_Style_Conditional[] + */ + public function getConditionalStyles() + { + return $this->getActiveSheet()->getConditionalStyles($this->getActiveCell()); + } + + /** + * Set Conditional Styles. Only used on supervisor. + * + * @param PHPExcel_Style_Conditional[] $pValue Array of condtional styles + * @return PHPExcel_Style + */ + public function setConditionalStyles($pValue = null) + { + if (is_array($pValue)) { + $this->getActiveSheet()->setConditionalStyles($this->getSelectedCells(), $pValue); + } + return $this; + } + + /** + * Get Protection + * + * @return PHPExcel_Style_Protection + */ + public function getProtection() + { + return $this->_protection; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() + { + $hashConditionals = ''; + foreach ($this->_conditionalStyles as $conditional) { + $hashConditionals .= $conditional->getHashCode(); + } + + return md5( + $this->_fill->getHashCode() + . $this->_font->getHashCode() + . $this->_borders->getHashCode() + . $this->_alignment->getHashCode() + . $this->_numberFormat->getHashCode() + . $hashConditionals + . $this->_protection->getHashCode() + . __CLASS__ + ); + } + + /** + * Get own index in style collection + * + * @return int + */ + public function getIndex() + { + return $this->_index; + } + + /** + * Set own index in style collection + * + * @param int $pValue + */ + public function setIndex($pValue) + { + $this->_index = $pValue; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Alignment.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Alignment.php new file mode 100755 index 0000000..6554252 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Alignment.php @@ -0,0 +1,409 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Style_Alignment + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Style_Alignment extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable +{ + /* Horizontal alignment styles */ + const HORIZONTAL_GENERAL = 'general'; + const HORIZONTAL_LEFT = 'left'; + const HORIZONTAL_RIGHT = 'right'; + const HORIZONTAL_CENTER = 'center'; + const HORIZONTAL_CENTER_CONTINUOUS = 'centerContinuous'; + const HORIZONTAL_JUSTIFY = 'justify'; + + /* Vertical alignment styles */ + const VERTICAL_BOTTOM = 'bottom'; + const VERTICAL_TOP = 'top'; + const VERTICAL_CENTER = 'center'; + const VERTICAL_JUSTIFY = 'justify'; + + /** + * Horizontal + * + * @var string + */ + protected $_horizontal = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; + + /** + * Vertical + * + * @var string + */ + protected $_vertical = PHPExcel_Style_Alignment::VERTICAL_BOTTOM; + + /** + * Text rotation + * + * @var int + */ + protected $_textRotation = 0; + + /** + * Wrap text + * + * @var boolean + */ + protected $_wrapText = FALSE; + + /** + * Shrink to fit + * + * @var boolean + */ + protected $_shrinkToFit = FALSE; + + /** + * Indent - only possible with horizontal alignment left and right + * + * @var int + */ + protected $_indent = 0; + + /** + * Create a new PHPExcel_Style_Alignment + * + * @param boolean $isSupervisor Flag indicating if this is a supervisor or not + * Leave this value at default unless you understand exactly what + * its ramifications are + * @param boolean $isConditional Flag indicating if this is a conditional style or not + * Leave this value at default unless you understand exactly what + * its ramifications are + */ + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) + { + // Supervisor? + parent::__construct($isSupervisor); + + if ($isConditional) { + $this->_horizontal = NULL; + $this->_vertical = NULL; + $this->_textRotation = NULL; + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_Alignment + */ + public function getSharedComponent() + { + return $this->_parent->getSharedComponent()->getAlignment(); + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + return array('alignment' => $array); + } + + /** + * Apply styles from array + * + * <code> + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getAlignment()->applyFromArray( + * array( + * 'horizontal' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER, + * 'vertical' => PHPExcel_Style_Alignment::VERTICAL_CENTER, + * 'rotation' => 0, + * 'wrap' => TRUE + * ) + * ); + * </code> + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Alignment + */ + public function applyFromArray($pStyles = NULL) { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells()) + ->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (isset($pStyles['horizontal'])) { + $this->setHorizontal($pStyles['horizontal']); + } + if (isset($pStyles['vertical'])) { + $this->setVertical($pStyles['vertical']); + } + if (isset($pStyles['rotation'])) { + $this->setTextRotation($pStyles['rotation']); + } + if (isset($pStyles['wrap'])) { + $this->setWrapText($pStyles['wrap']); + } + if (isset($pStyles['shrinkToFit'])) { + $this->setShrinkToFit($pStyles['shrinkToFit']); + } + if (isset($pStyles['indent'])) { + $this->setIndent($pStyles['indent']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get Horizontal + * + * @return string + */ + public function getHorizontal() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHorizontal(); + } + return $this->_horizontal; + } + + /** + * Set Horizontal + * + * @param string $pValue + * @return PHPExcel_Style_Alignment + */ + public function setHorizontal($pValue = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL) { + if ($pValue == '') { + $pValue = PHPExcel_Style_Alignment::HORIZONTAL_GENERAL; + } + + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('horizontal' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } + else { + $this->_horizontal = $pValue; + } + return $this; + } + + /** + * Get Vertical + * + * @return string + */ + public function getVertical() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getVertical(); + } + return $this->_vertical; + } + + /** + * Set Vertical + * + * @param string $pValue + * @return PHPExcel_Style_Alignment + */ + public function setVertical($pValue = PHPExcel_Style_Alignment::VERTICAL_BOTTOM) { + if ($pValue == '') { + $pValue = PHPExcel_Style_Alignment::VERTICAL_BOTTOM; + } + + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('vertical' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_vertical = $pValue; + } + return $this; + } + + /** + * Get TextRotation + * + * @return int + */ + public function getTextRotation() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getTextRotation(); + } + return $this->_textRotation; + } + + /** + * Set TextRotation + * + * @param int $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Alignment + */ + public function setTextRotation($pValue = 0) { + // Excel2007 value 255 => PHPExcel value -165 + if ($pValue == 255) { + $pValue = -165; + } + + // Set rotation + if ( ($pValue >= -90 && $pValue <= 90) || $pValue == -165 ) { + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('rotation' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_textRotation = $pValue; + } + } else { + throw new PHPExcel_Exception("Text rotation should be a value between -90 and 90."); + } + + return $this; + } + + /** + * Get Wrap Text + * + * @return boolean + */ + public function getWrapText() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getWrapText(); + } + return $this->_wrapText; + } + + /** + * Set Wrap Text + * + * @param boolean $pValue + * @return PHPExcel_Style_Alignment + */ + public function setWrapText($pValue = FALSE) { + if ($pValue == '') { + $pValue = FALSE; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('wrap' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_wrapText = $pValue; + } + return $this; + } + + /** + * Get Shrink to fit + * + * @return boolean + */ + public function getShrinkToFit() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getShrinkToFit(); + } + return $this->_shrinkToFit; + } + + /** + * Set Shrink to fit + * + * @param boolean $pValue + * @return PHPExcel_Style_Alignment + */ + public function setShrinkToFit($pValue = FALSE) { + if ($pValue == '') { + $pValue = FALSE; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('shrinkToFit' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_shrinkToFit = $pValue; + } + return $this; + } + + /** + * Get indent + * + * @return int + */ + public function getIndent() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getIndent(); + } + return $this->_indent; + } + + /** + * Set indent + * + * @param int $pValue + * @return PHPExcel_Style_Alignment + */ + public function setIndent($pValue = 0) { + if ($pValue > 0) { + if ($this->getHorizontal() != self::HORIZONTAL_GENERAL && + $this->getHorizontal() != self::HORIZONTAL_LEFT && + $this->getHorizontal() != self::HORIZONTAL_RIGHT) { + $pValue = 0; // indent not supported + } + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('indent' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_indent = $pValue; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashCode(); + } + return md5( + $this->_horizontal + . $this->_vertical + . $this->_textRotation + . ($this->_wrapText ? 't' : 'f') + . ($this->_shrinkToFit ? 't' : 'f') + . $this->_indent + . __CLASS__ + ); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Border.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Border.php new file mode 100755 index 0000000..cadfdc5 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Border.php @@ -0,0 +1,294 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Style_Border + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Style_Border extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable +{ + /* Border style */ + const BORDER_NONE = 'none'; + const BORDER_DASHDOT = 'dashDot'; + const BORDER_DASHDOTDOT = 'dashDotDot'; + const BORDER_DASHED = 'dashed'; + const BORDER_DOTTED = 'dotted'; + const BORDER_DOUBLE = 'double'; + const BORDER_HAIR = 'hair'; + const BORDER_MEDIUM = 'medium'; + const BORDER_MEDIUMDASHDOT = 'mediumDashDot'; + const BORDER_MEDIUMDASHDOTDOT = 'mediumDashDotDot'; + const BORDER_MEDIUMDASHED = 'mediumDashed'; + const BORDER_SLANTDASHDOT = 'slantDashDot'; + const BORDER_THICK = 'thick'; + const BORDER_THIN = 'thin'; + + /** + * Border style + * + * @var string + */ + protected $_borderStyle = PHPExcel_Style_Border::BORDER_NONE; + + /** + * Border color + * + * @var PHPExcel_Style_Color + */ + protected $_color; + + /** + * Parent property name + * + * @var string + */ + protected $_parentPropertyName; + + /** + * Create a new PHPExcel_Style_Border + * + * @param boolean $isSupervisor Flag indicating if this is a supervisor or not + * Leave this value at default unless you understand exactly what + * its ramifications are + * @param boolean $isConditional Flag indicating if this is a conditional style or not + * Leave this value at default unless you understand exactly what + * its ramifications are + */ + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) + { + // Supervisor? + parent::__construct($isSupervisor); + + // Initialise values + $this->_color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor); + + // bind parent if we are a supervisor + if ($isSupervisor) { + $this->_color->bindParent($this, '_color'); + } + } + + /** + * Bind parent. Only used for supervisor + * + * @param PHPExcel_Style_Borders $parent + * @param string $parentPropertyName + * @return PHPExcel_Style_Border + */ + public function bindParent($parent, $parentPropertyName=NULL) + { + $this->_parent = $parent; + $this->_parentPropertyName = $parentPropertyName; + return $this; + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_Border + * @throws PHPExcel_Exception + */ + public function getSharedComponent() + { + switch ($this->_parentPropertyName) { + case '_allBorders': + case '_horizontal': + case '_inside': + case '_outline': + case '_vertical': + throw new PHPExcel_Exception('Cannot get shared component for a pseudo-border.'); + break; + case '_bottom': + return $this->_parent->getSharedComponent()->getBottom(); break; + case '_diagonal': + return $this->_parent->getSharedComponent()->getDiagonal(); break; + case '_left': + return $this->_parent->getSharedComponent()->getLeft(); break; + case '_right': + return $this->_parent->getSharedComponent()->getRight(); break; + case '_top': + return $this->_parent->getSharedComponent()->getTop(); break; + + } + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + switch ($this->_parentPropertyName) { + case '_allBorders': + $key = 'allborders'; break; + case '_bottom': + $key = 'bottom'; break; + case '_diagonal': + $key = 'diagonal'; break; + case '_horizontal': + $key = 'horizontal'; break; + case '_inside': + $key = 'inside'; break; + case '_left': + $key = 'left'; break; + case '_outline': + $key = 'outline'; break; + case '_right': + $key = 'right'; break; + case '_top': + $key = 'top'; break; + case '_vertical': + $key = 'vertical'; break; + } + return $this->_parent->getStyleArray(array($key => $array)); + } + + /** + * Apply styles from array + * + * <code> + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getBorders()->getTop()->applyFromArray( + * array( + * 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ) + * ); + * </code> + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Border + */ + public function applyFromArray($pStyles = null) { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (isset($pStyles['style'])) { + $this->setBorderStyle($pStyles['style']); + } + if (isset($pStyles['color'])) { + $this->getColor()->applyFromArray($pStyles['color']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get Border style + * + * @return string + */ + public function getBorderStyle() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getBorderStyle(); + } + return $this->_borderStyle; + } + + /** + * Set Border style + * + * @param string|boolean $pValue + * When passing a boolean, FALSE equates PHPExcel_Style_Border::BORDER_NONE + * and TRUE to PHPExcel_Style_Border::BORDER_MEDIUM + * @return PHPExcel_Style_Border + */ + public function setBorderStyle($pValue = PHPExcel_Style_Border::BORDER_NONE) { + + if (empty($pValue)) { + $pValue = PHPExcel_Style_Border::BORDER_NONE; + } elseif(is_bool($pValue) && $pValue) { + $pValue = PHPExcel_Style_Border::BORDER_MEDIUM; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('style' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_borderStyle = $pValue; + } + return $this; + } + + /** + * Get Border Color + * + * @return PHPExcel_Style_Color + */ + public function getColor() { + return $this->_color; + } + + /** + * Set Border Color + * + * @param PHPExcel_Style_Color $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Border + */ + public function setColor(PHPExcel_Style_Color $pValue = null) { + // make sure parameter is a real color and not a supervisor + $color = $pValue->getIsSupervisor() ? $pValue->getSharedComponent() : $pValue; + + if ($this->_isSupervisor) { + $styleArray = $this->getColor()->getStyleArray(array('argb' => $color->getARGB())); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_color = $color; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashCode(); + } + return md5( + $this->_borderStyle + . $this->_color->getHashCode() + . __CLASS__ + ); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Borders.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Borders.php new file mode 100755 index 0000000..ce25ad8 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Borders.php @@ -0,0 +1,424 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Style_Borders + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Style_Borders extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable +{ + /* Diagonal directions */ + const DIAGONAL_NONE = 0; + const DIAGONAL_UP = 1; + const DIAGONAL_DOWN = 2; + const DIAGONAL_BOTH = 3; + + /** + * Left + * + * @var PHPExcel_Style_Border + */ + protected $_left; + + /** + * Right + * + * @var PHPExcel_Style_Border + */ + protected $_right; + + /** + * Top + * + * @var PHPExcel_Style_Border + */ + protected $_top; + + /** + * Bottom + * + * @var PHPExcel_Style_Border + */ + protected $_bottom; + + /** + * Diagonal + * + * @var PHPExcel_Style_Border + */ + protected $_diagonal; + + /** + * DiagonalDirection + * + * @var int + */ + protected $_diagonalDirection; + + /** + * All borders psedo-border. Only applies to supervisor. + * + * @var PHPExcel_Style_Border + */ + protected $_allBorders; + + /** + * Outline psedo-border. Only applies to supervisor. + * + * @var PHPExcel_Style_Border + */ + protected $_outline; + + /** + * Inside psedo-border. Only applies to supervisor. + * + * @var PHPExcel_Style_Border + */ + protected $_inside; + + /** + * Vertical pseudo-border. Only applies to supervisor. + * + * @var PHPExcel_Style_Border + */ + protected $_vertical; + + /** + * Horizontal pseudo-border. Only applies to supervisor. + * + * @var PHPExcel_Style_Border + */ + protected $_horizontal; + + /** + * Create a new PHPExcel_Style_Borders + * + * @param boolean $isSupervisor Flag indicating if this is a supervisor or not + * Leave this value at default unless you understand exactly what + * its ramifications are + * @param boolean $isConditional Flag indicating if this is a conditional style or not + * Leave this value at default unless you understand exactly what + * its ramifications are + */ + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) + { + // Supervisor? + parent::__construct($isSupervisor); + + // Initialise values + $this->_left = new PHPExcel_Style_Border($isSupervisor, $isConditional); + $this->_right = new PHPExcel_Style_Border($isSupervisor, $isConditional); + $this->_top = new PHPExcel_Style_Border($isSupervisor, $isConditional); + $this->_bottom = new PHPExcel_Style_Border($isSupervisor, $isConditional); + $this->_diagonal = new PHPExcel_Style_Border($isSupervisor, $isConditional); + $this->_diagonalDirection = PHPExcel_Style_Borders::DIAGONAL_NONE; + + // Specially for supervisor + if ($isSupervisor) { + // Initialize pseudo-borders + $this->_allBorders = new PHPExcel_Style_Border(TRUE); + $this->_outline = new PHPExcel_Style_Border(TRUE); + $this->_inside = new PHPExcel_Style_Border(TRUE); + $this->_vertical = new PHPExcel_Style_Border(TRUE); + $this->_horizontal = new PHPExcel_Style_Border(TRUE); + + // bind parent if we are a supervisor + $this->_left->bindParent($this, '_left'); + $this->_right->bindParent($this, '_right'); + $this->_top->bindParent($this, '_top'); + $this->_bottom->bindParent($this, '_bottom'); + $this->_diagonal->bindParent($this, '_diagonal'); + $this->_allBorders->bindParent($this, '_allBorders'); + $this->_outline->bindParent($this, '_outline'); + $this->_inside->bindParent($this, '_inside'); + $this->_vertical->bindParent($this, '_vertical'); + $this->_horizontal->bindParent($this, '_horizontal'); + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_Borders + */ + public function getSharedComponent() + { + return $this->_parent->getSharedComponent()->getBorders(); + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + return array('borders' => $array); + } + + /** + * Apply styles from array + * + * <code> + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getBorders()->applyFromArray( + * array( + * 'bottom' => array( + * 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ), + * 'top' => array( + * 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ) + * ) + * ); + * </code> + * <code> + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getBorders()->applyFromArray( + * array( + * 'allborders' => array( + * 'style' => PHPExcel_Style_Border::BORDER_DASHDOT, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ) + * ) + * ); + * </code> + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Borders + */ + public function applyFromArray($pStyles = null) { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (array_key_exists('left', $pStyles)) { + $this->getLeft()->applyFromArray($pStyles['left']); + } + if (array_key_exists('right', $pStyles)) { + $this->getRight()->applyFromArray($pStyles['right']); + } + if (array_key_exists('top', $pStyles)) { + $this->getTop()->applyFromArray($pStyles['top']); + } + if (array_key_exists('bottom', $pStyles)) { + $this->getBottom()->applyFromArray($pStyles['bottom']); + } + if (array_key_exists('diagonal', $pStyles)) { + $this->getDiagonal()->applyFromArray($pStyles['diagonal']); + } + if (array_key_exists('diagonaldirection', $pStyles)) { + $this->setDiagonalDirection($pStyles['diagonaldirection']); + } + if (array_key_exists('allborders', $pStyles)) { + $this->getLeft()->applyFromArray($pStyles['allborders']); + $this->getRight()->applyFromArray($pStyles['allborders']); + $this->getTop()->applyFromArray($pStyles['allborders']); + $this->getBottom()->applyFromArray($pStyles['allborders']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get Left + * + * @return PHPExcel_Style_Border + */ + public function getLeft() { + return $this->_left; + } + + /** + * Get Right + * + * @return PHPExcel_Style_Border + */ + public function getRight() { + return $this->_right; + } + + /** + * Get Top + * + * @return PHPExcel_Style_Border + */ + public function getTop() { + return $this->_top; + } + + /** + * Get Bottom + * + * @return PHPExcel_Style_Border + */ + public function getBottom() { + return $this->_bottom; + } + + /** + * Get Diagonal + * + * @return PHPExcel_Style_Border + */ + public function getDiagonal() { + return $this->_diagonal; + } + + /** + * Get AllBorders (pseudo-border). Only applies to supervisor. + * + * @return PHPExcel_Style_Border + * @throws PHPExcel_Exception + */ + public function getAllBorders() { + if (!$this->_isSupervisor) { + throw new PHPExcel_Exception('Can only get pseudo-border for supervisor.'); + } + return $this->_allBorders; + } + + /** + * Get Outline (pseudo-border). Only applies to supervisor. + * + * @return boolean + * @throws PHPExcel_Exception + */ + public function getOutline() { + if (!$this->_isSupervisor) { + throw new PHPExcel_Exception('Can only get pseudo-border for supervisor.'); + } + return $this->_outline; + } + + /** + * Get Inside (pseudo-border). Only applies to supervisor. + * + * @return boolean + * @throws PHPExcel_Exception + */ + public function getInside() { + if (!$this->_isSupervisor) { + throw new PHPExcel_Exception('Can only get pseudo-border for supervisor.'); + } + return $this->_inside; + } + + /** + * Get Vertical (pseudo-border). Only applies to supervisor. + * + * @return PHPExcel_Style_Border + * @throws PHPExcel_Exception + */ + public function getVertical() { + if (!$this->_isSupervisor) { + throw new PHPExcel_Exception('Can only get pseudo-border for supervisor.'); + } + return $this->_vertical; + } + + /** + * Get Horizontal (pseudo-border). Only applies to supervisor. + * + * @return PHPExcel_Style_Border + * @throws PHPExcel_Exception + */ + public function getHorizontal() { + if (!$this->_isSupervisor) { + throw new PHPExcel_Exception('Can only get pseudo-border for supervisor.'); + } + return $this->_horizontal; + } + + /** + * Get DiagonalDirection + * + * @return int + */ + public function getDiagonalDirection() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getDiagonalDirection(); + } + return $this->_diagonalDirection; + } + + /** + * Set DiagonalDirection + * + * @param int $pValue + * @return PHPExcel_Style_Borders + */ + public function setDiagonalDirection($pValue = PHPExcel_Style_Borders::DIAGONAL_NONE) { + if ($pValue == '') { + $pValue = PHPExcel_Style_Borders::DIAGONAL_NONE; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('diagonaldirection' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_diagonalDirection = $pValue; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashcode(); + } + return md5( + $this->getLeft()->getHashCode() + . $this->getRight()->getHashCode() + . $this->getTop()->getHashCode() + . $this->getBottom()->getHashCode() + . $this->getDiagonal()->getHashCode() + . $this->getDiagonalDirection() + . __CLASS__ + ); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Color.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Color.php new file mode 100755 index 0000000..f473209 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Color.php @@ -0,0 +1,429 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Style_Color + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Style_Color extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable +{ + /* Colors */ + const COLOR_BLACK = 'FF000000'; + const COLOR_WHITE = 'FFFFFFFF'; + const COLOR_RED = 'FFFF0000'; + const COLOR_DARKRED = 'FF800000'; + const COLOR_BLUE = 'FF0000FF'; + const COLOR_DARKBLUE = 'FF000080'; + const COLOR_GREEN = 'FF00FF00'; + const COLOR_DARKGREEN = 'FF008000'; + const COLOR_YELLOW = 'FFFFFF00'; + const COLOR_DARKYELLOW = 'FF808000'; + + /** + * Indexed colors array + * + * @var array + */ + protected static $_indexedColors; + + /** + * ARGB - Alpha RGB + * + * @var string + */ + protected $_argb = NULL; + + /** + * Parent property name + * + * @var string + */ + protected $_parentPropertyName; + + + /** + * Create a new PHPExcel_Style_Color + * + * @param string $pARGB ARGB value for the colour + * @param boolean $isSupervisor Flag indicating if this is a supervisor or not + * Leave this value at default unless you understand exactly what + * its ramifications are + * @param boolean $isConditional Flag indicating if this is a conditional style or not + * Leave this value at default unless you understand exactly what + * its ramifications are + */ + public function __construct($pARGB = PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor = FALSE, $isConditional = FALSE) + { + // Supervisor? + parent::__construct($isSupervisor); + + // Initialise values + if (!$isConditional) { + $this->_argb = $pARGB; + } + } + + /** + * Bind parent. Only used for supervisor + * + * @param mixed $parent + * @param string $parentPropertyName + * @return PHPExcel_Style_Color + */ + public function bindParent($parent, $parentPropertyName=NULL) + { + $this->_parent = $parent; + $this->_parentPropertyName = $parentPropertyName; + return $this; + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_Color + */ + public function getSharedComponent() + { + switch ($this->_parentPropertyName) { + case '_endColor': + return $this->_parent->getSharedComponent()->getEndColor(); break; + case '_color': + return $this->_parent->getSharedComponent()->getColor(); break; + case '_startColor': + return $this->_parent->getSharedComponent()->getStartColor(); break; + } + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + switch ($this->_parentPropertyName) { + case '_endColor': + $key = 'endcolor'; + break; + case '_color': + $key = 'color'; + break; + case '_startColor': + $key = 'startcolor'; + break; + + } + return $this->_parent->getStyleArray(array($key => $array)); + } + + /** + * Apply styles from array + * + * <code> + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getFont()->getColor()->applyFromArray( array('rgb' => '808080') ); + * </code> + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Color + */ + public function applyFromArray($pStyles = NULL) { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (array_key_exists('rgb', $pStyles)) { + $this->setRGB($pStyles['rgb']); + } + if (array_key_exists('argb', $pStyles)) { + $this->setARGB($pStyles['argb']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get ARGB + * + * @return string + */ + public function getARGB() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getARGB(); + } + return $this->_argb; + } + + /** + * Set ARGB + * + * @param string $pValue + * @return PHPExcel_Style_Color + */ + public function setARGB($pValue = PHPExcel_Style_Color::COLOR_BLACK) { + if ($pValue == '') { + $pValue = PHPExcel_Style_Color::COLOR_BLACK; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('argb' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_argb = $pValue; + } + return $this; + } + + /** + * Get RGB + * + * @return string + */ + public function getRGB() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getRGB(); + } + return substr($this->_argb, 2); + } + + /** + * Set RGB + * + * @param string $pValue RGB value + * @return PHPExcel_Style_Color + */ + public function setRGB($pValue = '000000') { + if ($pValue == '') { + $pValue = '000000'; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('argb' => 'FF' . $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_argb = 'FF' . $pValue; + } + return $this; + } + + /** + * Get a specified colour component of an RGB value + * + * @private + * @param string $RGB The colour as an RGB value (e.g. FF00CCCC or CCDDEE + * @param int $offset Position within the RGB value to extract + * @param boolean $hex Flag indicating whether the component should be returned as a hex or a + * decimal value + * @return string The extracted colour component + */ + private static function _getColourComponent($RGB,$offset,$hex=TRUE) { + $colour = substr($RGB, $offset, 2); + if (!$hex) + $colour = hexdec($colour); + return $colour; + } + + /** + * Get the red colour component of an RGB value + * + * @param string $RGB The colour as an RGB value (e.g. FF00CCCC or CCDDEE + * @param boolean $hex Flag indicating whether the component should be returned as a hex or a + * decimal value + * @return string The red colour component + */ + public static function getRed($RGB,$hex=TRUE) { + return self::_getColourComponent($RGB, strlen($RGB) - 6, $hex); + } + + /** + * Get the green colour component of an RGB value + * + * @param string $RGB The colour as an RGB value (e.g. FF00CCCC or CCDDEE + * @param boolean $hex Flag indicating whether the component should be returned as a hex or a + * decimal value + * @return string The green colour component + */ + public static function getGreen($RGB,$hex=TRUE) { + return self::_getColourComponent($RGB, strlen($RGB) - 4, $hex); + } + + /** + * Get the blue colour component of an RGB value + * + * @param string $RGB The colour as an RGB value (e.g. FF00CCCC or CCDDEE + * @param boolean $hex Flag indicating whether the component should be returned as a hex or a + * decimal value + * @return string The blue colour component + */ + public static function getBlue($RGB,$hex=TRUE) { + return self::_getColourComponent($RGB, strlen($RGB) - 2, $hex); + } + + /** + * Adjust the brightness of a color + * + * @param string $hex The colour as an RGBA or RGB value (e.g. FF00CCCC or CCDDEE) + * @param float $adjustPercentage The percentage by which to adjust the colour as a float from -1 to 1 + * @return string The adjusted colour as an RGBA or RGB value (e.g. FF00CCCC or CCDDEE) + */ + public static function changeBrightness($hex, $adjustPercentage) { + $rgba = (strlen($hex) == 8); + + $red = self::getRed($hex, FALSE); + $green = self::getGreen($hex, FALSE); + $blue = self::getBlue($hex, FALSE); + if ($adjustPercentage > 0) { + $red += (255 - $red) * $adjustPercentage; + $green += (255 - $green) * $adjustPercentage; + $blue += (255 - $blue) * $adjustPercentage; + } else { + $red += $red * $adjustPercentage; + $green += $green * $adjustPercentage; + $blue += $blue * $adjustPercentage; + } + + if ($red < 0) $red = 0; + elseif ($red > 255) $red = 255; + if ($green < 0) $green = 0; + elseif ($green > 255) $green = 255; + if ($blue < 0) $blue = 0; + elseif ($blue > 255) $blue = 255; + + $rgb = strtoupper( str_pad(dechex($red), 2, '0', 0) . + str_pad(dechex($green), 2, '0', 0) . + str_pad(dechex($blue), 2, '0', 0) + ); + return (($rgba) ? 'FF' : '') . $rgb; + } + + /** + * Get indexed color + * + * @param int $pIndex Index entry point into the colour array + * @param boolean $background Flag to indicate whether default background or foreground colour + * should be returned if the indexed colour doesn't exist + * @return PHPExcel_Style_Color + */ + public static function indexedColor($pIndex, $background=FALSE) { + // Clean parameter + $pIndex = intval($pIndex); + + // Indexed colors + if (is_null(self::$_indexedColors)) { + self::$_indexedColors = array( + 1 => 'FF000000', // System Colour #1 - Black + 2 => 'FFFFFFFF', // System Colour #2 - White + 3 => 'FFFF0000', // System Colour #3 - Red + 4 => 'FF00FF00', // System Colour #4 - Green + 5 => 'FF0000FF', // System Colour #5 - Blue + 6 => 'FFFFFF00', // System Colour #6 - Yellow + 7 => 'FFFF00FF', // System Colour #7- Magenta + 8 => 'FF00FFFF', // System Colour #8- Cyan + 9 => 'FF800000', // Standard Colour #9 + 10 => 'FF008000', // Standard Colour #10 + 11 => 'FF000080', // Standard Colour #11 + 12 => 'FF808000', // Standard Colour #12 + 13 => 'FF800080', // Standard Colour #13 + 14 => 'FF008080', // Standard Colour #14 + 15 => 'FFC0C0C0', // Standard Colour #15 + 16 => 'FF808080', // Standard Colour #16 + 17 => 'FF9999FF', // Chart Fill Colour #17 + 18 => 'FF993366', // Chart Fill Colour #18 + 19 => 'FFFFFFCC', // Chart Fill Colour #19 + 20 => 'FFCCFFFF', // Chart Fill Colour #20 + 21 => 'FF660066', // Chart Fill Colour #21 + 22 => 'FFFF8080', // Chart Fill Colour #22 + 23 => 'FF0066CC', // Chart Fill Colour #23 + 24 => 'FFCCCCFF', // Chart Fill Colour #24 + 25 => 'FF000080', // Chart Line Colour #25 + 26 => 'FFFF00FF', // Chart Line Colour #26 + 27 => 'FFFFFF00', // Chart Line Colour #27 + 28 => 'FF00FFFF', // Chart Line Colour #28 + 29 => 'FF800080', // Chart Line Colour #29 + 30 => 'FF800000', // Chart Line Colour #30 + 31 => 'FF008080', // Chart Line Colour #31 + 32 => 'FF0000FF', // Chart Line Colour #32 + 33 => 'FF00CCFF', // Standard Colour #33 + 34 => 'FFCCFFFF', // Standard Colour #34 + 35 => 'FFCCFFCC', // Standard Colour #35 + 36 => 'FFFFFF99', // Standard Colour #36 + 37 => 'FF99CCFF', // Standard Colour #37 + 38 => 'FFFF99CC', // Standard Colour #38 + 39 => 'FFCC99FF', // Standard Colour #39 + 40 => 'FFFFCC99', // Standard Colour #40 + 41 => 'FF3366FF', // Standard Colour #41 + 42 => 'FF33CCCC', // Standard Colour #42 + 43 => 'FF99CC00', // Standard Colour #43 + 44 => 'FFFFCC00', // Standard Colour #44 + 45 => 'FFFF9900', // Standard Colour #45 + 46 => 'FFFF6600', // Standard Colour #46 + 47 => 'FF666699', // Standard Colour #47 + 48 => 'FF969696', // Standard Colour #48 + 49 => 'FF003366', // Standard Colour #49 + 50 => 'FF339966', // Standard Colour #50 + 51 => 'FF003300', // Standard Colour #51 + 52 => 'FF333300', // Standard Colour #52 + 53 => 'FF993300', // Standard Colour #53 + 54 => 'FF993366', // Standard Colour #54 + 55 => 'FF333399', // Standard Colour #55 + 56 => 'FF333333' // Standard Colour #56 + ); + } + + if (array_key_exists($pIndex, self::$_indexedColors)) { + return new PHPExcel_Style_Color(self::$_indexedColors[$pIndex]); + } + + if ($background) { + return new PHPExcel_Style_Color('FFFFFFFF'); + } + return new PHPExcel_Style_Color('FF000000'); + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashCode(); + } + return md5( + $this->_argb + . __CLASS__ + ); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Conditional.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Conditional.php new file mode 100755 index 0000000..6411b4f --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Conditional.php @@ -0,0 +1,277 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Style_Conditional + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Style_Conditional implements PHPExcel_IComparable +{ + /* Condition types */ + const CONDITION_NONE = 'none'; + const CONDITION_CELLIS = 'cellIs'; + const CONDITION_CONTAINSTEXT = 'containsText'; + const CONDITION_EXPRESSION = 'expression'; + + /* Operator types */ + const OPERATOR_NONE = ''; + const OPERATOR_BEGINSWITH = 'beginsWith'; + const OPERATOR_ENDSWITH = 'endsWith'; + const OPERATOR_EQUAL = 'equal'; + const OPERATOR_GREATERTHAN = 'greaterThan'; + const OPERATOR_GREATERTHANOREQUAL = 'greaterThanOrEqual'; + const OPERATOR_LESSTHAN = 'lessThan'; + const OPERATOR_LESSTHANOREQUAL = 'lessThanOrEqual'; + const OPERATOR_NOTEQUAL = 'notEqual'; + const OPERATOR_CONTAINSTEXT = 'containsText'; + const OPERATOR_NOTCONTAINS = 'notContains'; + const OPERATOR_BETWEEN = 'between'; + + /** + * Condition type + * + * @var int + */ + private $_conditionType; + + /** + * Operator type + * + * @var int + */ + private $_operatorType; + + /** + * Text + * + * @var string + */ + private $_text; + + /** + * Condition + * + * @var string[] + */ + private $_condition = array(); + + /** + * Style + * + * @var PHPExcel_Style + */ + private $_style; + + /** + * Create a new PHPExcel_Style_Conditional + */ + public function __construct() + { + // Initialise values + $this->_conditionType = PHPExcel_Style_Conditional::CONDITION_NONE; + $this->_operatorType = PHPExcel_Style_Conditional::OPERATOR_NONE; + $this->_text = null; + $this->_condition = array(); + $this->_style = new PHPExcel_Style(FALSE, TRUE); + } + + /** + * Get Condition type + * + * @return string + */ + public function getConditionType() { + return $this->_conditionType; + } + + /** + * Set Condition type + * + * @param string $pValue PHPExcel_Style_Conditional condition type + * @return PHPExcel_Style_Conditional + */ + public function setConditionType($pValue = PHPExcel_Style_Conditional::CONDITION_NONE) { + $this->_conditionType = $pValue; + return $this; + } + + /** + * Get Operator type + * + * @return string + */ + public function getOperatorType() { + return $this->_operatorType; + } + + /** + * Set Operator type + * + * @param string $pValue PHPExcel_Style_Conditional operator type + * @return PHPExcel_Style_Conditional + */ + public function setOperatorType($pValue = PHPExcel_Style_Conditional::OPERATOR_NONE) { + $this->_operatorType = $pValue; + return $this; + } + + /** + * Get text + * + * @return string + */ + public function getText() { + return $this->_text; + } + + /** + * Set text + * + * @param string $value + * @return PHPExcel_Style_Conditional + */ + public function setText($value = null) { + $this->_text = $value; + return $this; + } + + /** + * Get Condition + * + * @deprecated Deprecated, use getConditions instead + * @return string + */ + public function getCondition() { + if (isset($this->_condition[0])) { + return $this->_condition[0]; + } + + return ''; + } + + /** + * Set Condition + * + * @deprecated Deprecated, use setConditions instead + * @param string $pValue Condition + * @return PHPExcel_Style_Conditional + */ + public function setCondition($pValue = '') { + if (!is_array($pValue)) + $pValue = array($pValue); + + return $this->setConditions($pValue); + } + + /** + * Get Conditions + * + * @return string[] + */ + public function getConditions() { + return $this->_condition; + } + + /** + * Set Conditions + * + * @param string[] $pValue Condition + * @return PHPExcel_Style_Conditional + */ + public function setConditions($pValue) { + if (!is_array($pValue)) + $pValue = array($pValue); + + $this->_condition = $pValue; + return $this; + } + + /** + * Add Condition + * + * @param string $pValue Condition + * @return PHPExcel_Style_Conditional + */ + public function addCondition($pValue = '') { + $this->_condition[] = $pValue; + return $this; + } + + /** + * Get Style + * + * @return PHPExcel_Style + */ + public function getStyle() { + return $this->_style; + } + + /** + * Set Style + * + * @param PHPExcel_Style $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Conditional + */ + public function setStyle(PHPExcel_Style $pValue = null) { + $this->_style = $pValue; + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_conditionType + . $this->_operatorType + . implode(';', $this->_condition) + . $this->_style->getHashCode() + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Fill.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Fill.php new file mode 100755 index 0000000..3c42242 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Fill.php @@ -0,0 +1,321 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Style_Fill + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Style_Fill extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable +{ + /* Fill types */ + const FILL_NONE = 'none'; + const FILL_SOLID = 'solid'; + const FILL_GRADIENT_LINEAR = 'linear'; + const FILL_GRADIENT_PATH = 'path'; + const FILL_PATTERN_DARKDOWN = 'darkDown'; + const FILL_PATTERN_DARKGRAY = 'darkGray'; + const FILL_PATTERN_DARKGRID = 'darkGrid'; + const FILL_PATTERN_DARKHORIZONTAL = 'darkHorizontal'; + const FILL_PATTERN_DARKTRELLIS = 'darkTrellis'; + const FILL_PATTERN_DARKUP = 'darkUp'; + const FILL_PATTERN_DARKVERTICAL = 'darkVertical'; + const FILL_PATTERN_GRAY0625 = 'gray0625'; + const FILL_PATTERN_GRAY125 = 'gray125'; + const FILL_PATTERN_LIGHTDOWN = 'lightDown'; + const FILL_PATTERN_LIGHTGRAY = 'lightGray'; + const FILL_PATTERN_LIGHTGRID = 'lightGrid'; + const FILL_PATTERN_LIGHTHORIZONTAL = 'lightHorizontal'; + const FILL_PATTERN_LIGHTTRELLIS = 'lightTrellis'; + const FILL_PATTERN_LIGHTUP = 'lightUp'; + const FILL_PATTERN_LIGHTVERTICAL = 'lightVertical'; + const FILL_PATTERN_MEDIUMGRAY = 'mediumGray'; + + /** + * Fill type + * + * @var string + */ + protected $_fillType = PHPExcel_Style_Fill::FILL_NONE; + + /** + * Rotation + * + * @var double + */ + protected $_rotation = 0; + + /** + * Start color + * + * @var PHPExcel_Style_Color + */ + protected $_startColor; + + /** + * End color + * + * @var PHPExcel_Style_Color + */ + protected $_endColor; + + /** + * Create a new PHPExcel_Style_Fill + * + * @param boolean $isSupervisor Flag indicating if this is a supervisor or not + * Leave this value at default unless you understand exactly what + * its ramifications are + * @param boolean $isConditional Flag indicating if this is a conditional style or not + * Leave this value at default unless you understand exactly what + * its ramifications are + */ + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) + { + // Supervisor? + parent::__construct($isSupervisor); + + // Initialise values + if ($isConditional) { + $this->_fillType = NULL; + } + $this->_startColor = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_WHITE, $isSupervisor, $isConditional); + $this->_endColor = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor, $isConditional); + + // bind parent if we are a supervisor + if ($isSupervisor) { + $this->_startColor->bindParent($this, '_startColor'); + $this->_endColor->bindParent($this, '_endColor'); + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_Fill + */ + public function getSharedComponent() + { + return $this->_parent->getSharedComponent()->getFill(); + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + return array('fill' => $array); + } + + /** + * Apply styles from array + * + * <code> + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getFill()->applyFromArray( + * array( + * 'type' => PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR, + * 'rotation' => 0, + * 'startcolor' => array( + * 'rgb' => '000000' + * ), + * 'endcolor' => array( + * 'argb' => 'FFFFFFFF' + * ) + * ) + * ); + * </code> + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Fill + */ + public function applyFromArray($pStyles = null) { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (array_key_exists('type', $pStyles)) { + $this->setFillType($pStyles['type']); + } + if (array_key_exists('rotation', $pStyles)) { + $this->setRotation($pStyles['rotation']); + } + if (array_key_exists('startcolor', $pStyles)) { + $this->getStartColor()->applyFromArray($pStyles['startcolor']); + } + if (array_key_exists('endcolor', $pStyles)) { + $this->getEndColor()->applyFromArray($pStyles['endcolor']); + } + if (array_key_exists('color', $pStyles)) { + $this->getStartColor()->applyFromArray($pStyles['color']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get Fill Type + * + * @return string + */ + public function getFillType() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getFillType(); + } + return $this->_fillType; + } + + /** + * Set Fill Type + * + * @param string $pValue PHPExcel_Style_Fill fill type + * @return PHPExcel_Style_Fill + */ + public function setFillType($pValue = PHPExcel_Style_Fill::FILL_NONE) { + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('type' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_fillType = $pValue; + } + return $this; + } + + /** + * Get Rotation + * + * @return double + */ + public function getRotation() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getRotation(); + } + return $this->_rotation; + } + + /** + * Set Rotation + * + * @param double $pValue + * @return PHPExcel_Style_Fill + */ + public function setRotation($pValue = 0) { + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('rotation' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_rotation = $pValue; + } + return $this; + } + + /** + * Get Start Color + * + * @return PHPExcel_Style_Color + */ + public function getStartColor() { + return $this->_startColor; + } + + /** + * Set Start Color + * + * @param PHPExcel_Style_Color $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Fill + */ + public function setStartColor(PHPExcel_Style_Color $pValue = null) { + // make sure parameter is a real color and not a supervisor + $color = $pValue->getIsSupervisor() ? $pValue->getSharedComponent() : $pValue; + + if ($this->_isSupervisor) { + $styleArray = $this->getStartColor()->getStyleArray(array('argb' => $color->getARGB())); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_startColor = $color; + } + return $this; + } + + /** + * Get End Color + * + * @return PHPExcel_Style_Color + */ + public function getEndColor() { + return $this->_endColor; + } + + /** + * Set End Color + * + * @param PHPExcel_Style_Color $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Fill + */ + public function setEndColor(PHPExcel_Style_Color $pValue = null) { + // make sure parameter is a real color and not a supervisor + $color = $pValue->getIsSupervisor() ? $pValue->getSharedComponent() : $pValue; + + if ($this->_isSupervisor) { + $styleArray = $this->getEndColor()->getStyleArray(array('argb' => $color->getARGB())); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_endColor = $color; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashCode(); + } + return md5( + $this->getFillType() + . $this->getRotation() + . $this->getStartColor()->getHashCode() + . $this->getEndColor()->getHashCode() + . __CLASS__ + ); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Font.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Font.php new file mode 100755 index 0000000..33dca2a --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Font.php @@ -0,0 +1,532 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Style_Font + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Style_Font extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable +{ + /* Underline types */ + const UNDERLINE_NONE = 'none'; + const UNDERLINE_DOUBLE = 'double'; + const UNDERLINE_DOUBLEACCOUNTING = 'doubleAccounting'; + const UNDERLINE_SINGLE = 'single'; + const UNDERLINE_SINGLEACCOUNTING = 'singleAccounting'; + + /** + * Font Name + * + * @var string + */ + protected $_name = 'Calibri'; + + /** + * Font Size + * + * @var float + */ + protected $_size = 11; + + /** + * Bold + * + * @var boolean + */ + protected $_bold = FALSE; + + /** + * Italic + * + * @var boolean + */ + protected $_italic = FALSE; + + /** + * Superscript + * + * @var boolean + */ + protected $_superScript = FALSE; + + /** + * Subscript + * + * @var boolean + */ + protected $_subScript = FALSE; + + /** + * Underline + * + * @var string + */ + protected $_underline = self::UNDERLINE_NONE; + + /** + * Strikethrough + * + * @var boolean + */ + protected $_strikethrough = FALSE; + + /** + * Foreground color + * + * @var PHPExcel_Style_Color + */ + protected $_color; + + /** + * Create a new PHPExcel_Style_Font + * + * @param boolean $isSupervisor Flag indicating if this is a supervisor or not + * Leave this value at default unless you understand exactly what + * its ramifications are + * @param boolean $isConditional Flag indicating if this is a conditional style or not + * Leave this value at default unless you understand exactly what + * its ramifications are + */ + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) + { + // Supervisor? + parent::__construct($isSupervisor); + + // Initialise values + if ($isConditional) { + $this->_name = NULL; + $this->_size = NULL; + $this->_bold = NULL; + $this->_italic = NULL; + $this->_superScript = NULL; + $this->_subScript = NULL; + $this->_underline = NULL; + $this->_strikethrough = NULL; + $this->_color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor, $isConditional); + } else { + $this->_color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_BLACK, $isSupervisor); + } + // bind parent if we are a supervisor + if ($isSupervisor) { + $this->_color->bindParent($this, '_color'); + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_Font + */ + public function getSharedComponent() + { + return $this->_parent->getSharedComponent()->getFont(); + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + return array('font' => $array); + } + + /** + * Apply styles from array + * + * <code> + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getFont()->applyFromArray( + * array( + * 'name' => 'Arial', + * 'bold' => TRUE, + * 'italic' => FALSE, + * 'underline' => PHPExcel_Style_Font::UNDERLINE_DOUBLE, + * 'strike' => FALSE, + * 'color' => array( + * 'rgb' => '808080' + * ) + * ) + * ); + * </code> + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Font + */ + public function applyFromArray($pStyles = null) { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (array_key_exists('name', $pStyles)) { + $this->setName($pStyles['name']); + } + if (array_key_exists('bold', $pStyles)) { + $this->setBold($pStyles['bold']); + } + if (array_key_exists('italic', $pStyles)) { + $this->setItalic($pStyles['italic']); + } + if (array_key_exists('superScript', $pStyles)) { + $this->setSuperScript($pStyles['superScript']); + } + if (array_key_exists('subScript', $pStyles)) { + $this->setSubScript($pStyles['subScript']); + } + if (array_key_exists('underline', $pStyles)) { + $this->setUnderline($pStyles['underline']); + } + if (array_key_exists('strike', $pStyles)) { + $this->setStrikethrough($pStyles['strike']); + } + if (array_key_exists('color', $pStyles)) { + $this->getColor()->applyFromArray($pStyles['color']); + } + if (array_key_exists('size', $pStyles)) { + $this->setSize($pStyles['size']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get Name + * + * @return string + */ + public function getName() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getName(); + } + return $this->_name; + } + + /** + * Set Name + * + * @param string $pValue + * @return PHPExcel_Style_Font + */ + public function setName($pValue = 'Calibri') { + if ($pValue == '') { + $pValue = 'Calibri'; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('name' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_name = $pValue; + } + return $this; + } + + /** + * Get Size + * + * @return double + */ + public function getSize() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getSize(); + } + return $this->_size; + } + + /** + * Set Size + * + * @param double $pValue + * @return PHPExcel_Style_Font + */ + public function setSize($pValue = 10) { + if ($pValue == '') { + $pValue = 10; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('size' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_size = $pValue; + } + return $this; + } + + /** + * Get Bold + * + * @return boolean + */ + public function getBold() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getBold(); + } + return $this->_bold; + } + + /** + * Set Bold + * + * @param boolean $pValue + * @return PHPExcel_Style_Font + */ + public function setBold($pValue = false) { + if ($pValue == '') { + $pValue = false; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('bold' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_bold = $pValue; + } + return $this; + } + + /** + * Get Italic + * + * @return boolean + */ + public function getItalic() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getItalic(); + } + return $this->_italic; + } + + /** + * Set Italic + * + * @param boolean $pValue + * @return PHPExcel_Style_Font + */ + public function setItalic($pValue = false) { + if ($pValue == '') { + $pValue = false; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('italic' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_italic = $pValue; + } + return $this; + } + + /** + * Get SuperScript + * + * @return boolean + */ + public function getSuperScript() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getSuperScript(); + } + return $this->_superScript; + } + + /** + * Set SuperScript + * + * @param boolean $pValue + * @return PHPExcel_Style_Font + */ + public function setSuperScript($pValue = false) { + if ($pValue == '') { + $pValue = false; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('superScript' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_superScript = $pValue; + $this->_subScript = !$pValue; + } + return $this; + } + + /** + * Get SubScript + * + * @return boolean + */ + public function getSubScript() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getSubScript(); + } + return $this->_subScript; + } + + /** + * Set SubScript + * + * @param boolean $pValue + * @return PHPExcel_Style_Font + */ + public function setSubScript($pValue = false) { + if ($pValue == '') { + $pValue = false; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('subScript' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_subScript = $pValue; + $this->_superScript = !$pValue; + } + return $this; + } + + /** + * Get Underline + * + * @return string + */ + public function getUnderline() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getUnderline(); + } + return $this->_underline; + } + + /** + * Set Underline + * + * @param string|boolean $pValue PHPExcel_Style_Font underline type + * If a boolean is passed, then TRUE equates to UNDERLINE_SINGLE, + * false equates to UNDERLINE_NONE + * @return PHPExcel_Style_Font + */ + public function setUnderline($pValue = self::UNDERLINE_NONE) { + if (is_bool($pValue)) { + $pValue = ($pValue) ? self::UNDERLINE_SINGLE : self::UNDERLINE_NONE; + } elseif ($pValue == '') { + $pValue = self::UNDERLINE_NONE; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('underline' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_underline = $pValue; + } + return $this; + } + + /** + * Get Strikethrough + * + * @return boolean + */ + public function getStrikethrough() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getStrikethrough(); + } + return $this->_strikethrough; + } + + /** + * Set Strikethrough + * + * @param boolean $pValue + * @return PHPExcel_Style_Font + */ + public function setStrikethrough($pValue = false) { + if ($pValue == '') { + $pValue = false; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('strike' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_strikethrough = $pValue; + } + return $this; + } + + /** + * Get Color + * + * @return PHPExcel_Style_Color + */ + public function getColor() { + return $this->_color; + } + + /** + * Set Color + * + * @param PHPExcel_Style_Color $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Font + */ + public function setColor(PHPExcel_Style_Color $pValue = null) { + // make sure parameter is a real color and not a supervisor + $color = $pValue->getIsSupervisor() ? $pValue->getSharedComponent() : $pValue; + + if ($this->_isSupervisor) { + $styleArray = $this->getColor()->getStyleArray(array('argb' => $color->getARGB())); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_color = $color; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashCode(); + } + return md5( + $this->_name + . $this->_size + . ($this->_bold ? 't' : 'f') + . ($this->_italic ? 't' : 'f') + . ($this->_superScript ? 't' : 'f') + . ($this->_subScript ? 't' : 'f') + . $this->_underline + . ($this->_strikethrough ? 't' : 'f') + . $this->_color->getHashCode() + . __CLASS__ + ); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/NumberFormat.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/NumberFormat.php new file mode 100755 index 0000000..a381f4f --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/NumberFormat.php @@ -0,0 +1,708 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Style_NumberFormat + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Style_NumberFormat extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable +{ + /* Pre-defined formats */ + const FORMAT_GENERAL = 'General'; + + const FORMAT_TEXT = '@'; + + const FORMAT_NUMBER = '0'; + const FORMAT_NUMBER_00 = '0.00'; + const FORMAT_NUMBER_COMMA_SEPARATED1 = '#,##0.00'; + const FORMAT_NUMBER_COMMA_SEPARATED2 = '#,##0.00_-'; + + const FORMAT_PERCENTAGE = '0%'; + const FORMAT_PERCENTAGE_00 = '0.00%'; + + const FORMAT_DATE_YYYYMMDD2 = 'yyyy-mm-dd'; + const FORMAT_DATE_YYYYMMDD = 'yy-mm-dd'; + const FORMAT_DATE_DDMMYYYY = 'dd/mm/yy'; + const FORMAT_DATE_DMYSLASH = 'd/m/y'; + const FORMAT_DATE_DMYMINUS = 'd-m-y'; + const FORMAT_DATE_DMMINUS = 'd-m'; + const FORMAT_DATE_MYMINUS = 'm-y'; + const FORMAT_DATE_XLSX14 = 'mm-dd-yy'; + const FORMAT_DATE_XLSX15 = 'd-mmm-yy'; + const FORMAT_DATE_XLSX16 = 'd-mmm'; + const FORMAT_DATE_XLSX17 = 'mmm-yy'; + const FORMAT_DATE_XLSX22 = 'm/d/yy h:mm'; + const FORMAT_DATE_DATETIME = 'd/m/y h:mm'; + const FORMAT_DATE_TIME1 = 'h:mm AM/PM'; + const FORMAT_DATE_TIME2 = 'h:mm:ss AM/PM'; + const FORMAT_DATE_TIME3 = 'h:mm'; + const FORMAT_DATE_TIME4 = 'h:mm:ss'; + const FORMAT_DATE_TIME5 = 'mm:ss'; + const FORMAT_DATE_TIME6 = 'h:mm:ss'; + const FORMAT_DATE_TIME7 = 'i:s.S'; + const FORMAT_DATE_TIME8 = 'h:mm:ss;@'; + const FORMAT_DATE_YYYYMMDDSLASH = 'yy/mm/dd;@'; + + const FORMAT_CURRENCY_USD_SIMPLE = '"$"#,##0.00_-'; + const FORMAT_CURRENCY_USD = '$#,##0_-'; + const FORMAT_CURRENCY_EUR_SIMPLE = '[$EUR ]#,##0.00_-'; + + /** + * Excel built-in number formats + * + * @var array + */ + protected static $_builtInFormats; + + /** + * Excel built-in number formats (flipped, for faster lookups) + * + * @var array + */ + protected static $_flippedBuiltInFormats; + + /** + * Format Code + * + * @var string + */ + protected $_formatCode = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + + /** + * Built-in format Code + * + * @var string + */ + protected $_builtInFormatCode = 0; + + /** + * Create a new PHPExcel_Style_NumberFormat + * + * @param boolean $isSupervisor Flag indicating if this is a supervisor or not + * Leave this value at default unless you understand exactly what + * its ramifications are + * @param boolean $isConditional Flag indicating if this is a conditional style or not + * Leave this value at default unless you understand exactly what + * its ramifications are + */ + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) + { + // Supervisor? + parent::__construct($isSupervisor); + + if ($isConditional) { + $this->_formatCode = NULL; + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_NumberFormat + */ + public function getSharedComponent() + { + return $this->_parent->getSharedComponent()->getNumberFormat(); + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + return array('numberformat' => $array); + } + + /** + * Apply styles from array + * + * <code> + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getNumberFormat()->applyFromArray( + * array( + * 'code' => PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_EUR_SIMPLE + * ) + * ); + * </code> + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_NumberFormat + */ + public function applyFromArray($pStyles = null) + { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (array_key_exists('code', $pStyles)) { + $this->setFormatCode($pStyles['code']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get Format Code + * + * @return string + */ + public function getFormatCode() + { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getFormatCode(); + } + if ($this->_builtInFormatCode !== false) + { + return self::builtInFormatCode($this->_builtInFormatCode); + } + return $this->_formatCode; + } + + /** + * Set Format Code + * + * @param string $pValue + * @return PHPExcel_Style_NumberFormat + */ + public function setFormatCode($pValue = PHPExcel_Style_NumberFormat::FORMAT_GENERAL) + { + if ($pValue == '') { + $pValue = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + } + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('code' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_formatCode = $pValue; + $this->_builtInFormatCode = self::builtInFormatCodeIndex($pValue); + } + return $this; + } + + /** + * Get Built-In Format Code + * + * @return int + */ + public function getBuiltInFormatCode() + { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getBuiltInFormatCode(); + } + return $this->_builtInFormatCode; + } + + /** + * Set Built-In Format Code + * + * @param int $pValue + * @return PHPExcel_Style_NumberFormat + */ + public function setBuiltInFormatCode($pValue = 0) + { + + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('code' => self::builtInFormatCode($pValue))); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_builtInFormatCode = $pValue; + $this->_formatCode = self::builtInFormatCode($pValue); + } + return $this; + } + + /** + * Fill built-in format codes + */ + private static function fillBuiltInFormatCodes() + { + // Built-in format codes + if (is_null(self::$_builtInFormats)) { + self::$_builtInFormats = array(); + + // General + self::$_builtInFormats[0] = PHPExcel_Style_NumberFormat::FORMAT_GENERAL; + self::$_builtInFormats[1] = '0'; + self::$_builtInFormats[2] = '0.00'; + self::$_builtInFormats[3] = '#,##0'; + self::$_builtInFormats[4] = '#,##0.00'; + + self::$_builtInFormats[9] = '0%'; + self::$_builtInFormats[10] = '0.00%'; + self::$_builtInFormats[11] = '0.00E+00'; + self::$_builtInFormats[12] = '# ?/?'; + self::$_builtInFormats[13] = '# ??/??'; + self::$_builtInFormats[14] = 'mm-dd-yy'; + self::$_builtInFormats[15] = 'd-mmm-yy'; + self::$_builtInFormats[16] = 'd-mmm'; + self::$_builtInFormats[17] = 'mmm-yy'; + self::$_builtInFormats[18] = 'h:mm AM/PM'; + self::$_builtInFormats[19] = 'h:mm:ss AM/PM'; + self::$_builtInFormats[20] = 'h:mm'; + self::$_builtInFormats[21] = 'h:mm:ss'; + self::$_builtInFormats[22] = 'm/d/yy h:mm'; + + self::$_builtInFormats[37] = '#,##0 ;(#,##0)'; + self::$_builtInFormats[38] = '#,##0 ;[Red](#,##0)'; + self::$_builtInFormats[39] = '#,##0.00;(#,##0.00)'; + self::$_builtInFormats[40] = '#,##0.00;[Red](#,##0.00)'; + + self::$_builtInFormats[44] = '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)'; + self::$_builtInFormats[45] = 'mm:ss'; + self::$_builtInFormats[46] = '[h]:mm:ss'; + self::$_builtInFormats[47] = 'mmss.0'; + self::$_builtInFormats[48] = '##0.0E+0'; + self::$_builtInFormats[49] = '@'; + + // CHT + self::$_builtInFormats[27] = '[$-404]e/m/d'; + self::$_builtInFormats[30] = 'm/d/yy'; + self::$_builtInFormats[36] = '[$-404]e/m/d'; + self::$_builtInFormats[50] = '[$-404]e/m/d'; + self::$_builtInFormats[57] = '[$-404]e/m/d'; + + // THA + self::$_builtInFormats[59] = 't0'; + self::$_builtInFormats[60] = 't0.00'; + self::$_builtInFormats[61] = 't#,##0'; + self::$_builtInFormats[62] = 't#,##0.00'; + self::$_builtInFormats[67] = 't0%'; + self::$_builtInFormats[68] = 't0.00%'; + self::$_builtInFormats[69] = 't# ?/?'; + self::$_builtInFormats[70] = 't# ??/??'; + + // Flip array (for faster lookups) + self::$_flippedBuiltInFormats = array_flip(self::$_builtInFormats); + } + } + + /** + * Get built-in format code + * + * @param int $pIndex + * @return string + */ + public static function builtInFormatCode($pIndex) + { + // Clean parameter + $pIndex = intval($pIndex); + + // Ensure built-in format codes are available + self::fillBuiltInFormatCodes(); + + // Lookup format code + if (isset(self::$_builtInFormats[$pIndex])) { + return self::$_builtInFormats[$pIndex]; + } + + return ''; + } + + /** + * Get built-in format code index + * + * @param string $formatCode + * @return int|boolean + */ + public static function builtInFormatCodeIndex($formatCode) + { + // Ensure built-in format codes are available + self::fillBuiltInFormatCodes(); + + // Lookup format code + if (isset(self::$_flippedBuiltInFormats[$formatCode])) { + return self::$_flippedBuiltInFormats[$formatCode]; + } + + return false; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() + { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashCode(); + } + return md5( + $this->_formatCode + . $this->_builtInFormatCode + . __CLASS__ + ); + } + + /** + * Search/replace values to convert Excel date/time format masks to PHP format masks + * + * @var array + */ + private static $_dateFormatReplacements = array( + // first remove escapes related to non-format characters + '\\' => '', + // 12-hour suffix + 'am/pm' => 'A', + // 4-digit year + 'e' => 'Y', + 'yyyy' => 'Y', + // 2-digit year + 'yy' => 'y', + // first letter of month - no php equivalent + 'mmmmm' => 'M', + // full month name + 'mmmm' => 'F', + // short month name + 'mmm' => 'M', + // mm is minutes if time, but can also be month w/leading zero + // so we try to identify times be the inclusion of a : separator in the mask + // It isn't perfect, but the best way I know how + ':mm' => ':i', + 'mm:' => 'i:', + // month leading zero + 'mm' => 'm', + // month no leading zero + 'm' => 'n', + // full day of week name + 'dddd' => 'l', + // short day of week name + 'ddd' => 'D', + // days leading zero + 'dd' => 'd', + // days no leading zero + 'd' => 'j', + // seconds + 'ss' => 's', + // fractional seconds - no php equivalent + '.s' => '' + ); + /** + * Search/replace values to convert Excel date/time format masks hours to PHP format masks (24 hr clock) + * + * @var array + */ + private static $_dateFormatReplacements24 = array( + 'hh' => 'H', + 'h' => 'G' + ); + /** + * Search/replace values to convert Excel date/time format masks hours to PHP format masks (12 hr clock) + * + * @var array + */ + private static $_dateFormatReplacements12 = array( + 'hh' => 'h', + 'h' => 'g' + ); + + private static function _formatAsDate(&$value, &$format) + { + // dvc: convert Excel formats to PHP date formats + + // strip off first part containing e.g. [$-F800] or [$USD-409] + // general syntax: [$<Currency string>-<language info>] + // language info is in hexadecimal + $format = preg_replace('/^(\[\$[A-Z]*-[0-9A-F]*\])/i', '', $format); + + // OpenOffice.org uses upper-case number formats, e.g. 'YYYY', convert to lower-case + $format = strtolower($format); + + $format = strtr($format,self::$_dateFormatReplacements); + if (!strpos($format,'A')) { // 24-hour time format + $format = strtr($format,self::$_dateFormatReplacements24); + } else { // 12-hour time format + $format = strtr($format,self::$_dateFormatReplacements12); + } + + $dateObj = PHPExcel_Shared_Date::ExcelToPHPObject($value); + $value = $dateObj->format($format); + } + + private static function _formatAsPercentage(&$value, &$format) + { + if ($format === self::FORMAT_PERCENTAGE) { + $value = round( (100 * $value), 0) . '%'; + } else { + if (preg_match('/\.[#0]+/i', $format, $m)) { + $s = substr($m[0], 0, 1) . (strlen($m[0]) - 1); + $format = str_replace($m[0], $s, $format); + } + if (preg_match('/^[#0]+/', $format, $m)) { + $format = str_replace($m[0], strlen($m[0]), $format); + } + $format = '%' . str_replace('%', 'f%%', $format); + + $value = sprintf($format, 100 * $value); + } + } + + private static function _formatAsFraction(&$value, &$format) + { + $sign = ($value < 0) ? '-' : ''; + + $integerPart = floor(abs($value)); + $decimalPart = trim(fmod(abs($value),1),'0.'); + $decimalLength = strlen($decimalPart); + $decimalDivisor = pow(10,$decimalLength); + + $GCD = PHPExcel_Calculation_MathTrig::GCD($decimalPart,$decimalDivisor); + + $adjustedDecimalPart = $decimalPart/$GCD; + $adjustedDecimalDivisor = $decimalDivisor/$GCD; + + if ((strpos($format,'0') !== false) || (strpos($format,'#') !== false) || (substr($format,0,3) == '? ?')) { + if ($integerPart == 0) { + $integerPart = ''; + } + $value = "$sign$integerPart $adjustedDecimalPart/$adjustedDecimalDivisor"; + } else { + $adjustedDecimalPart += $integerPart * $adjustedDecimalDivisor; + $value = "$sign$adjustedDecimalPart/$adjustedDecimalDivisor"; + } + } + + private static function _complexNumberFormatMask($number, $mask) { + if (strpos($mask,'.') !== false) { + $numbers = explode('.', $number . '.0'); + $masks = explode('.', $mask . '.0'); + $result1 = self::_complexNumberFormatMask($numbers[0], $masks[0]); + $result2 = strrev(self::_complexNumberFormatMask(strrev($numbers[1]), strrev($masks[1]))); + return $result1 . '.' . $result2; + } + + $r = preg_match_all('/0+/', $mask, $result, PREG_OFFSET_CAPTURE); + if ($r > 1) { + $result = array_reverse($result[0]); + + foreach($result as $block) { + $divisor = 1 . $block[0]; + $size = strlen($block[0]); + $offset = $block[1]; + + $blockValue = sprintf( + '%0' . $size . 'd', + fmod($number, $divisor) + ); + $number = floor($number / $divisor); + $mask = substr_replace($mask,$blockValue, $offset, $size); + } + if ($number > 0) { + $mask = substr_replace($mask, $number, $offset, 0); + } + $result = $mask; + } else { + $result = $number; + } + + return $result; + } + + /** + * Convert a value in a pre-defined format to a PHP string + * + * @param mixed $value Value to format + * @param string $format Format code + * @param array $callBack Callback function for additional formatting of string + * @return string Formatted string + */ + public static function toFormattedString($value = '0', $format = PHPExcel_Style_NumberFormat::FORMAT_GENERAL, $callBack = null) + { + // For now we do not treat strings although section 4 of a format code affects strings + if (!is_numeric($value)) return $value; + + // For 'General' format code, we just pass the value although this is not entirely the way Excel does it, + // it seems to round numbers to a total of 10 digits. + if (($format === PHPExcel_Style_NumberFormat::FORMAT_GENERAL) || ($format === PHPExcel_Style_NumberFormat::FORMAT_TEXT)) { + return $value; + } + + // Get the sections, there can be up to four sections + $sections = explode(';', $format); + + // Fetch the relevant section depending on whether number is positive, negative, or zero? + // Text not supported yet. + // Here is how the sections apply to various values in Excel: + // 1 section: [POSITIVE/NEGATIVE/ZERO/TEXT] + // 2 sections: [POSITIVE/ZERO/TEXT] [NEGATIVE] + // 3 sections: [POSITIVE/TEXT] [NEGATIVE] [ZERO] + // 4 sections: [POSITIVE] [NEGATIVE] [ZERO] [TEXT] + switch (count($sections)) { + case 1: + $format = $sections[0]; + break; + + case 2: + $format = ($value >= 0) ? $sections[0] : $sections[1]; + $value = abs($value); // Use the absolute value + break; + + case 3: + $format = ($value > 0) ? + $sections[0] : ( ($value < 0) ? + $sections[1] : $sections[2]); + $value = abs($value); // Use the absolute value + break; + + case 4: + $format = ($value > 0) ? + $sections[0] : ( ($value < 0) ? + $sections[1] : $sections[2]); + $value = abs($value); // Use the absolute value + break; + + default: + // something is wrong, just use first section + $format = $sections[0]; + break; + } + + // Save format with color information for later use below + $formatColor = $format; + + // Strip color information + $color_regex = '/^\\[[a-zA-Z]+\\]/'; + $format = preg_replace($color_regex, '', $format); + + // Let's begin inspecting the format and converting the value to a formatted string + if (preg_match('/^(\[\$[A-Z]*-[0-9A-F]*\])*[hmsdy]/i', $format)) { // datetime format + self::_formatAsDate($value, $format); + } else if (preg_match('/%$/', $format)) { // % number format + self::_formatAsPercentage($value, $format); + } else { + if ($format === self::FORMAT_CURRENCY_EUR_SIMPLE) { + $value = 'EUR ' . sprintf('%1.2f', $value); + } else { + // In Excel formats, "_" is used to add spacing, which we can't do in HTML + $format = preg_replace('/_./', '', $format); + + // Some non-number characters are escaped with \, which we don't need + $format = preg_replace("/\\\\/", '', $format); + + // Some non-number strings are quoted, so we'll get rid of the quotes, likewise any positional * symbols + $format = str_replace(array('"','*'), '', $format); + + // Find out if we need thousands separator + // This is indicated by a comma enclosed by a digit placeholder: + // #,# or 0,0 + $useThousands = preg_match('/(#,#|0,0)/', $format); + if ($useThousands) { + $format = preg_replace('/0,0/', '00', $format); + $format = preg_replace('/#,#/', '##', $format); + } + + // Scale thousands, millions,... + // This is indicated by a number of commas after a digit placeholder: + // #, or 0.0,, + $scale = 1; // same as no scale + $matches = array(); + if (preg_match('/(#|0)(,+)/', $format, $matches)) { + $scale = pow(1000, strlen($matches[2])); + + // strip the commas + $format = preg_replace('/0,+/', '0', $format); + $format = preg_replace('/#,+/', '#', $format); + } + + if (preg_match('/#?.*\?\/\?/', $format, $m)) { + //echo 'Format mask is fractional '.$format.' <br />'; + if ($value != (int)$value) { + self::_formatAsFraction($value, $format); + } + + } else { + // Handle the number itself + + // scale number + $value = $value / $scale; + + // Strip # + $format = preg_replace('/\\#/', '0', $format); + + $n = "/\[[^\]]+\]/"; + $m = preg_replace($n, '', $format); + $number_regex = "/(0+)(\.?)(0*)/"; + if (preg_match($number_regex, $m, $matches)) { + $left = $matches[1]; + $dec = $matches[2]; + $right = $matches[3]; + + // minimun width of formatted number (including dot) + $minWidth = strlen($left) + strlen($dec) + strlen($right); + if ($useThousands) { + $value = number_format( + $value + , strlen($right) + , PHPExcel_Shared_String::getDecimalSeparator() + , PHPExcel_Shared_String::getThousandsSeparator() + ); + $value = preg_replace($number_regex, $value, $format); + } else { + if (preg_match('/0([^\d\.]+)0/', $format, $matches)) { + $value = self::_complexNumberFormatMask($value, $format); + } else { + $sprintf_pattern = "%0$minWidth." . strlen($right) . "f"; + $value = sprintf($sprintf_pattern, $value); + $value = preg_replace($number_regex, $value, $format); + } + } + } + } + if (preg_match('/\[\$(.*)\]/u', $format, $m)) { + // Currency or Accounting + $currencyFormat = $m[0]; + $currencyCode = $m[1]; + list($currencyCode) = explode('-',$currencyCode); + if ($currencyCode == '') { + $currencyCode = PHPExcel_Shared_String::getCurrencyCode(); + } + $value = preg_replace('/\[\$([^\]]*)\]/u',$currencyCode,$value); + } + } + } + + // Additional formatting provided by callback function + if ($callBack !== null) { + list($writerInstance, $function) = $callBack; + $value = $writerInstance->$function($value, $formatColor); + } + + return $value; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Protection.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Protection.php new file mode 100755 index 0000000..a8f65ce --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Protection.php @@ -0,0 +1,207 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.4.5, 2007-08-23 + */ + + +/** + * PHPExcel_Style_Protection + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Style_Protection extends PHPExcel_Style_Supervisor implements PHPExcel_IComparable +{ + /** Protection styles */ + const PROTECTION_INHERIT = 'inherit'; + const PROTECTION_PROTECTED = 'protected'; + const PROTECTION_UNPROTECTED = 'unprotected'; + + /** + * Locked + * + * @var string + */ + protected $_locked; + + /** + * Hidden + * + * @var string + */ + protected $_hidden; + + /** + * Create a new PHPExcel_Style_Protection + * + * @param boolean $isSupervisor Flag indicating if this is a supervisor or not + * Leave this value at default unless you understand exactly what + * its ramifications are + * @param boolean $isConditional Flag indicating if this is a conditional style or not + * Leave this value at default unless you understand exactly what + * its ramifications are + */ + public function __construct($isSupervisor = FALSE, $isConditional = FALSE) + { + // Supervisor? + parent::__construct($isSupervisor); + + // Initialise values + if (!$isConditional) { + $this->_locked = self::PROTECTION_INHERIT; + $this->_hidden = self::PROTECTION_INHERIT; + } + } + + /** + * Get the shared style component for the currently active cell in currently active sheet. + * Only used for style supervisor + * + * @return PHPExcel_Style_Protection + */ + public function getSharedComponent() + { + return $this->_parent->getSharedComponent()->getProtection(); + } + + /** + * Build style array from subcomponents + * + * @param array $array + * @return array + */ + public function getStyleArray($array) + { + return array('protection' => $array); + } + + /** + * Apply styles from array + * + * <code> + * $objPHPExcel->getActiveSheet()->getStyle('B2')->getLocked()->applyFromArray( + * array( + * 'locked' => TRUE, + * 'hidden' => FALSE + * ) + * ); + * </code> + * + * @param array $pStyles Array containing style information + * @throws PHPExcel_Exception + * @return PHPExcel_Style_Protection + */ + public function applyFromArray($pStyles = NULL) { + if (is_array($pStyles)) { + if ($this->_isSupervisor) { + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($this->getStyleArray($pStyles)); + } else { + if (isset($pStyles['locked'])) { + $this->setLocked($pStyles['locked']); + } + if (isset($pStyles['hidden'])) { + $this->setHidden($pStyles['hidden']); + } + } + } else { + throw new PHPExcel_Exception("Invalid style array passed."); + } + return $this; + } + + /** + * Get locked + * + * @return string + */ + public function getLocked() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getLocked(); + } + return $this->_locked; + } + + /** + * Set locked + * + * @param string $pValue + * @return PHPExcel_Style_Protection + */ + public function setLocked($pValue = self::PROTECTION_INHERIT) { + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('locked' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_locked = $pValue; + } + return $this; + } + + /** + * Get hidden + * + * @return string + */ + public function getHidden() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHidden(); + } + return $this->_hidden; + } + + /** + * Set hidden + * + * @param string $pValue + * @return PHPExcel_Style_Protection + */ + public function setHidden($pValue = self::PROTECTION_INHERIT) { + if ($this->_isSupervisor) { + $styleArray = $this->getStyleArray(array('hidden' => $pValue)); + $this->getActiveSheet()->getStyle($this->getSelectedCells())->applyFromArray($styleArray); + } else { + $this->_hidden = $pValue; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_isSupervisor) { + return $this->getSharedComponent()->getHashCode(); + } + return md5( + $this->_locked + . $this->_hidden + . __CLASS__ + ); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Supervisor.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Supervisor.php new file mode 100755 index 0000000..24ff189 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Style/Supervisor.php @@ -0,0 +1,132 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Style_Supervisor + * + * @category PHPExcel + * @package PHPExcel_Style + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +abstract class PHPExcel_Style_Supervisor +{ + /** + * Supervisor? + * + * @var boolean + */ + protected $_isSupervisor; + + /** + * Parent. Only used for supervisor + * + * @var PHPExcel_Style + */ + protected $_parent; + + /** + * Create a new PHPExcel_Style_Alignment + * + * @param boolean $isSupervisor Flag indicating if this is a supervisor or not + * Leave this value at default unless you understand exactly what + * its ramifications are + */ + public function __construct($isSupervisor = FALSE) + { + // Supervisor? + $this->_isSupervisor = $isSupervisor; + } + + /** + * Bind parent. Only used for supervisor + * + * @param PHPExcel $parent + * @return PHPExcel_Style_Supervisor + */ + public function bindParent($parent, $parentPropertyName=NULL) + { + $this->_parent = $parent; + return $this; + } + + /** + * Is this a supervisor or a cell style component? + * + * @return boolean + */ + public function getIsSupervisor() + { + return $this->_isSupervisor; + } + + /** + * Get the currently active sheet. Only used for supervisor + * + * @return PHPExcel_Worksheet + */ + public function getActiveSheet() + { + return $this->_parent->getActiveSheet(); + } + + /** + * Get the currently active cell coordinate in currently active sheet. + * Only used for supervisor + * + * @return string E.g. 'A1' + */ + public function getSelectedCells() + { + return $this->getActiveSheet()->getSelectedCells(); + } + + /** + * Get the currently active cell coordinate in currently active sheet. + * Only used for supervisor + * + * @return string E.g. 'A1' + */ + public function getActiveCell() + { + return $this->getActiveSheet()->getActiveCell(); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if ((is_object($value)) && ($key != '_parent')) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet.php new file mode 100755 index 0000000..7d3f378 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet.php @@ -0,0 +1,2818 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet implements PHPExcel_IComparable +{ + /* Break types */ + const BREAK_NONE = 0; + const BREAK_ROW = 1; + const BREAK_COLUMN = 2; + + /* Sheet state */ + const SHEETSTATE_VISIBLE = 'visible'; + const SHEETSTATE_HIDDEN = 'hidden'; + const SHEETSTATE_VERYHIDDEN = 'veryHidden'; + + /** + * Invalid characters in sheet title + * + * @var array + */ + private static $_invalidCharacters = array('*', ':', '/', '\\', '?', '[', ']'); + + /** + * Parent spreadsheet + * + * @var PHPExcel + */ + private $_parent; + + /** + * Cacheable collection of cells + * + * @var PHPExcel_CachedObjectStorage_xxx + */ + private $_cellCollection = null; + + /** + * Collection of row dimensions + * + * @var PHPExcel_Worksheet_RowDimension[] + */ + private $_rowDimensions = array(); + + /** + * Default row dimension + * + * @var PHPExcel_Worksheet_RowDimension + */ + private $_defaultRowDimension = null; + + /** + * Collection of column dimensions + * + * @var PHPExcel_Worksheet_ColumnDimension[] + */ + private $_columnDimensions = array(); + + /** + * Default column dimension + * + * @var PHPExcel_Worksheet_ColumnDimension + */ + private $_defaultColumnDimension = null; + + /** + * Collection of drawings + * + * @var PHPExcel_Worksheet_BaseDrawing[] + */ + private $_drawingCollection = null; + + /** + * Collection of Chart objects + * + * @var PHPExcel_Chart[] + */ + private $_chartCollection = array(); + + /** + * Worksheet title + * + * @var string + */ + private $_title; + + /** + * Sheet state + * + * @var string + */ + private $_sheetState; + + /** + * Page setup + * + * @var PHPExcel_Worksheet_PageSetup + */ + private $_pageSetup; + + /** + * Page margins + * + * @var PHPExcel_Worksheet_PageMargins + */ + private $_pageMargins; + + /** + * Page header/footer + * + * @var PHPExcel_Worksheet_HeaderFooter + */ + private $_headerFooter; + + /** + * Sheet view + * + * @var PHPExcel_Worksheet_SheetView + */ + private $_sheetView; + + /** + * Protection + * + * @var PHPExcel_Worksheet_Protection + */ + private $_protection; + + /** + * Collection of styles + * + * @var PHPExcel_Style[] + */ + private $_styles = array(); + + /** + * Conditional styles. Indexed by cell coordinate, e.g. 'A1' + * + * @var array + */ + private $_conditionalStylesCollection = array(); + + /** + * Is the current cell collection sorted already? + * + * @var boolean + */ + private $_cellCollectionIsSorted = false; + + /** + * Collection of breaks + * + * @var array + */ + private $_breaks = array(); + + /** + * Collection of merged cell ranges + * + * @var array + */ + private $_mergeCells = array(); + + /** + * Collection of protected cell ranges + * + * @var array + */ + private $_protectedCells = array(); + + /** + * Autofilter Range and selection + * + * @var PHPExcel_Worksheet_AutoFilter + */ + private $_autoFilter = NULL; + + /** + * Freeze pane + * + * @var string + */ + private $_freezePane = ''; + + /** + * Show gridlines? + * + * @var boolean + */ + private $_showGridlines = true; + + /** + * Print gridlines? + * + * @var boolean + */ + private $_printGridlines = false; + + /** + * Show row and column headers? + * + * @var boolean + */ + private $_showRowColHeaders = true; + + /** + * Show summary below? (Row/Column outline) + * + * @var boolean + */ + private $_showSummaryBelow = true; + + /** + * Show summary right? (Row/Column outline) + * + * @var boolean + */ + private $_showSummaryRight = true; + + /** + * Collection of comments + * + * @var PHPExcel_Comment[] + */ + private $_comments = array(); + + /** + * Active cell. (Only one!) + * + * @var string + */ + private $_activeCell = 'A1'; + + /** + * Selected cells + * + * @var string + */ + private $_selectedCells = 'A1'; + + /** + * Cached highest column + * + * @var string + */ + private $_cachedHighestColumn = 'A'; + + /** + * Cached highest row + * + * @var int + */ + private $_cachedHighestRow = 1; + + /** + * Right-to-left? + * + * @var boolean + */ + private $_rightToLeft = false; + + /** + * Hyperlinks. Indexed by cell coordinate, e.g. 'A1' + * + * @var array + */ + private $_hyperlinkCollection = array(); + + /** + * Data validation objects. Indexed by cell coordinate, e.g. 'A1' + * + * @var array + */ + private $_dataValidationCollection = array(); + + /** + * Tab color + * + * @var PHPExcel_Style_Color + */ + private $_tabColor; + + /** + * Dirty flag + * + * @var boolean + */ + private $_dirty = true; + + /** + * Hash + * + * @var string + */ + private $_hash = null; + + /** + * Create a new worksheet + * + * @param PHPExcel $pParent + * @param string $pTitle + */ + public function __construct(PHPExcel $pParent = null, $pTitle = 'Worksheet') + { + // Set parent and title + $this->_parent = $pParent; + $this->setTitle($pTitle, FALSE); + $this->setSheetState(PHPExcel_Worksheet::SHEETSTATE_VISIBLE); + + $this->_cellCollection = PHPExcel_CachedObjectStorageFactory::getInstance($this); + + // Set page setup + $this->_pageSetup = new PHPExcel_Worksheet_PageSetup(); + + // Set page margins + $this->_pageMargins = new PHPExcel_Worksheet_PageMargins(); + + // Set page header/footer + $this->_headerFooter = new PHPExcel_Worksheet_HeaderFooter(); + + // Set sheet view + $this->_sheetView = new PHPExcel_Worksheet_SheetView(); + + // Drawing collection + $this->_drawingCollection = new ArrayObject(); + + // Chart collection + $this->_chartCollection = new ArrayObject(); + + // Protection + $this->_protection = new PHPExcel_Worksheet_Protection(); + + // Default row dimension + $this->_defaultRowDimension = new PHPExcel_Worksheet_RowDimension(NULL); + + // Default column dimension + $this->_defaultColumnDimension = new PHPExcel_Worksheet_ColumnDimension(NULL); + + $this->_autoFilter = new PHPExcel_Worksheet_AutoFilter(NULL, $this); + } + + + /** + * Disconnect all cells from this PHPExcel_Worksheet object, + * typically so that the worksheet object can be unset + * + */ + public function disconnectCells() { + if ( $this->_cellCollection !== NULL){ + $this->_cellCollection->unsetWorksheetCells(); + $this->_cellCollection = NULL; + } + // detach ourself from the workbook, so that it can then delete this worksheet successfully + $this->_parent = null; + } + + /** + * Code to execute when this worksheet is unset() + * + */ + function __destruct() { + PHPExcel_Calculation::getInstance($this->_parent) + ->clearCalculationCacheForWorksheet($this->_title); + + $this->disconnectCells(); + } + + /** + * Return the cache controller for the cell collection + * + * @return PHPExcel_CachedObjectStorage_xxx + */ + public function getCellCacheController() { + return $this->_cellCollection; + } // function getCellCacheController() + + + /** + * Get array of invalid characters for sheet title + * + * @return array + */ + public static function getInvalidCharacters() + { + return self::$_invalidCharacters; + } + + /** + * Check sheet title for valid Excel syntax + * + * @param string $pValue The string to check + * @return string The valid string + * @throws PHPExcel_Exception + */ + private static function _checkSheetTitle($pValue) + { + // Some of the printable ASCII characters are invalid: * : / \ ? [ ] + if (str_replace(self::$_invalidCharacters, '', $pValue) !== $pValue) { + throw new PHPExcel_Exception('Invalid character found in sheet title'); + } + + // Maximum 31 characters allowed for sheet title + if (PHPExcel_Shared_String::CountCharacters($pValue) > 31) { + throw new PHPExcel_Exception('Maximum 31 characters allowed in sheet title.'); + } + + return $pValue; + } + + /** + * Get collection of cells + * + * @param boolean $pSorted Also sort the cell collection? + * @return PHPExcel_Cell[] + */ + public function getCellCollection($pSorted = true) + { + if ($pSorted) { + // Re-order cell collection + return $this->sortCellCollection(); + } + if ($this->_cellCollection !== NULL) { + return $this->_cellCollection->getCellList(); + } + return array(); + } + + /** + * Sort collection of cells + * + * @return PHPExcel_Worksheet + */ + public function sortCellCollection() + { + if ($this->_cellCollection !== NULL) { + return $this->_cellCollection->getSortedCellList(); + } + return array(); + } + + /** + * Get collection of row dimensions + * + * @return PHPExcel_Worksheet_RowDimension[] + */ + public function getRowDimensions() + { + return $this->_rowDimensions; + } + + /** + * Get default row dimension + * + * @return PHPExcel_Worksheet_RowDimension + */ + public function getDefaultRowDimension() + { + return $this->_defaultRowDimension; + } + + /** + * Get collection of column dimensions + * + * @return PHPExcel_Worksheet_ColumnDimension[] + */ + public function getColumnDimensions() + { + return $this->_columnDimensions; + } + + /** + * Get default column dimension + * + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function getDefaultColumnDimension() + { + return $this->_defaultColumnDimension; + } + + /** + * Get collection of drawings + * + * @return PHPExcel_Worksheet_BaseDrawing[] + */ + public function getDrawingCollection() + { + return $this->_drawingCollection; + } + + /** + * Get collection of charts + * + * @return PHPExcel_Chart[] + */ + public function getChartCollection() + { + return $this->_chartCollection; + } + + /** + * Add chart + * + * @param PHPExcel_Chart $pChart + * @param int|null $iChartIndex Index where chart should go (0,1,..., or null for last) + * @return PHPExcel_Chart + */ + public function addChart(PHPExcel_Chart $pChart = null, $iChartIndex = null) + { + $pChart->setWorksheet($this); + if (is_null($iChartIndex)) { + $this->_chartCollection[] = $pChart; + } else { + // Insert the chart at the requested index + array_splice($this->_chartCollection, $iChartIndex, 0, array($pChart)); + } + + return $pChart; + } + + /** + * Return the count of charts on this worksheet + * + * @return int The number of charts + */ + public function getChartCount() + { + return count($this->_chartCollection); + } + + /** + * Get a chart by its index position + * + * @param string $index Chart index position + * @return false|PHPExcel_Chart + * @throws PHPExcel_Exception + */ + public function getChartByIndex($index = null) + { + $chartCount = count($this->_chartCollection); + if ($chartCount == 0) { + return false; + } + if (is_null($index)) { + $index = --$chartCount; + } + if (!isset($this->_chartCollection[$index])) { + return false; + } + + return $this->_chartCollection[$index]; + } + + /** + * Return an array of the names of charts on this worksheet + * + * @return string[] The names of charts + * @throws PHPExcel_Exception + */ + public function getChartNames() + { + $chartNames = array(); + foreach($this->_chartCollection as $chart) { + $chartNames[] = $chart->getName(); + } + return $chartNames; + } + + /** + * Get a chart by name + * + * @param string $chartName Chart name + * @return false|PHPExcel_Chart + * @throws PHPExcel_Exception + */ + public function getChartByName($chartName = '') + { + $chartCount = count($this->_chartCollection); + if ($chartCount == 0) { + return false; + } + foreach($this->_chartCollection as $index => $chart) { + if ($chart->getName() == $chartName) { + return $this->_chartCollection[$index]; + } + } + return false; + } + + /** + * Refresh column dimensions + * + * @return PHPExcel_Worksheet + */ + public function refreshColumnDimensions() + { + $currentColumnDimensions = $this->getColumnDimensions(); + $newColumnDimensions = array(); + + foreach ($currentColumnDimensions as $objColumnDimension) { + $newColumnDimensions[$objColumnDimension->getColumnIndex()] = $objColumnDimension; + } + + $this->_columnDimensions = $newColumnDimensions; + + return $this; + } + + /** + * Refresh row dimensions + * + * @return PHPExcel_Worksheet + */ + public function refreshRowDimensions() + { + $currentRowDimensions = $this->getRowDimensions(); + $newRowDimensions = array(); + + foreach ($currentRowDimensions as $objRowDimension) { + $newRowDimensions[$objRowDimension->getRowIndex()] = $objRowDimension; + } + + $this->_rowDimensions = $newRowDimensions; + + return $this; + } + + /** + * Calculate worksheet dimension + * + * @return string String containing the dimension of this worksheet + */ + public function calculateWorksheetDimension() + { + // Return + return 'A1' . ':' . $this->getHighestColumn() . $this->getHighestRow(); + } + + /** + * Calculate worksheet data dimension + * + * @return string String containing the dimension of this worksheet that actually contain data + */ + public function calculateWorksheetDataDimension() + { + // Return + return 'A1' . ':' . $this->getHighestDataColumn() . $this->getHighestDataRow(); + } + + /** + * Calculate widths for auto-size columns + * + * @param boolean $calculateMergeCells Calculate merge cell width + * @return PHPExcel_Worksheet; + */ + public function calculateColumnWidths($calculateMergeCells = false) + { + // initialize $autoSizes array + $autoSizes = array(); + foreach ($this->getColumnDimensions() as $colDimension) { + if ($colDimension->getAutoSize()) { + $autoSizes[$colDimension->getColumnIndex()] = -1; + } + } + + // There is only something to do if there are some auto-size columns + if (!empty($autoSizes)) { + + // build list of cells references that participate in a merge + $isMergeCell = array(); + foreach ($this->getMergeCells() as $cells) { + foreach (PHPExcel_Cell::extractAllCellReferencesInRange($cells) as $cellReference) { + $isMergeCell[$cellReference] = true; + } + } + + // loop through all cells in the worksheet + foreach ($this->getCellCollection(false) as $cellID) { + $cell = $this->getCell($cellID); + if (isset($autoSizes[$this->_cellCollection->getCurrentColumn()])) { + // Determine width if cell does not participate in a merge + if (!isset($isMergeCell[$this->_cellCollection->getCurrentAddress()])) { + // Calculated value + // To formatted string + $cellValue = PHPExcel_Style_NumberFormat::toFormattedString( + $cell->getCalculatedValue(), + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getNumberFormat()->getFormatCode() + ); + + $autoSizes[$this->_cellCollection->getCurrentColumn()] = max( + (float) $autoSizes[$this->_cellCollection->getCurrentColumn()], + (float)PHPExcel_Shared_Font::calculateColumnWidth( + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getFont(), + $cellValue, + $this->getParent()->getCellXfByIndex($cell->getXfIndex())->getAlignment()->getTextRotation(), + $this->getDefaultStyle()->getFont() + ) + ); + } + } + } + + // adjust column widths + foreach ($autoSizes as $columnIndex => $width) { + if ($width == -1) $width = $this->getDefaultColumnDimension()->getWidth(); + $this->getColumnDimension($columnIndex)->setWidth($width); + } + } + + return $this; + } + + /** + * Get parent + * + * @return PHPExcel + */ + public function getParent() { + return $this->_parent; + } + + /** + * Re-bind parent + * + * @param PHPExcel $parent + * @return PHPExcel_Worksheet + */ + public function rebindParent(PHPExcel $parent) { + $namedRanges = $this->_parent->getNamedRanges(); + foreach ($namedRanges as $namedRange) { + $parent->addNamedRange($namedRange); + } + + $this->_parent->removeSheetByIndex( + $this->_parent->getIndex($this) + ); + $this->_parent = $parent; + + return $this; + } + + /** + * Get title + * + * @return string + */ + public function getTitle() + { + return $this->_title; + } + + /** + * Set title + * + * @param string $pValue String containing the dimension of this worksheet + * @param string $updateFormulaCellReferences boolean Flag indicating whether cell references in formulae should + * be updated to reflect the new sheet name. + * This should be left as the default true, unless you are + * certain that no formula cells on any worksheet contain + * references to this worksheet + * @return PHPExcel_Worksheet + */ + public function setTitle($pValue = 'Worksheet', $updateFormulaCellReferences = true) + { + // Is this a 'rename' or not? + if ($this->getTitle() == $pValue) { + return $this; + } + + // Syntax check + self::_checkSheetTitle($pValue); + + // Old title + $oldTitle = $this->getTitle(); + + if ($this->_parent) { + // Is there already such sheet name? + if ($this->_parent->sheetNameExists($pValue)) { + // Use name, but append with lowest possible integer + + if (PHPExcel_Shared_String::CountCharacters($pValue) > 29) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,29); + } + $i = 1; + while ($this->_parent->sheetNameExists($pValue . ' ' . $i)) { + ++$i; + if ($i == 10) { + if (PHPExcel_Shared_String::CountCharacters($pValue) > 28) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,28); + } + } elseif ($i == 100) { + if (PHPExcel_Shared_String::CountCharacters($pValue) > 27) { + $pValue = PHPExcel_Shared_String::Substring($pValue,0,27); + } + } + } + + $altTitle = $pValue . ' ' . $i; + return $this->setTitle($altTitle,$updateFormulaCellReferences); + } + } + + // Set title + $this->_title = $pValue; + $this->_dirty = true; + + if ($this->_parent) { + // New title + $newTitle = $this->getTitle(); + PHPExcel_Calculation::getInstance($this->_parent) + ->renameCalculationCacheForWorksheet($oldTitle, $newTitle); + if ($updateFormulaCellReferences) + PHPExcel_ReferenceHelper::getInstance()->updateNamedFormulas($this->_parent, $oldTitle, $newTitle); + } + + return $this; + } + + /** + * Get sheet state + * + * @return string Sheet state (visible, hidden, veryHidden) + */ + public function getSheetState() { + return $this->_sheetState; + } + + /** + * Set sheet state + * + * @param string $value Sheet state (visible, hidden, veryHidden) + * @return PHPExcel_Worksheet + */ + public function setSheetState($value = PHPExcel_Worksheet::SHEETSTATE_VISIBLE) { + $this->_sheetState = $value; + return $this; + } + + /** + * Get page setup + * + * @return PHPExcel_Worksheet_PageSetup + */ + public function getPageSetup() + { + return $this->_pageSetup; + } + + /** + * Set page setup + * + * @param PHPExcel_Worksheet_PageSetup $pValue + * @return PHPExcel_Worksheet + */ + public function setPageSetup(PHPExcel_Worksheet_PageSetup $pValue) + { + $this->_pageSetup = $pValue; + return $this; + } + + /** + * Get page margins + * + * @return PHPExcel_Worksheet_PageMargins + */ + public function getPageMargins() + { + return $this->_pageMargins; + } + + /** + * Set page margins + * + * @param PHPExcel_Worksheet_PageMargins $pValue + * @return PHPExcel_Worksheet + */ + public function setPageMargins(PHPExcel_Worksheet_PageMargins $pValue) + { + $this->_pageMargins = $pValue; + return $this; + } + + /** + * Get page header/footer + * + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function getHeaderFooter() + { + return $this->_headerFooter; + } + + /** + * Set page header/footer + * + * @param PHPExcel_Worksheet_HeaderFooter $pValue + * @return PHPExcel_Worksheet + */ + public function setHeaderFooter(PHPExcel_Worksheet_HeaderFooter $pValue) + { + $this->_headerFooter = $pValue; + return $this; + } + + /** + * Get sheet view + * + * @return PHPExcel_Worksheet_SheetView + */ + public function getSheetView() + { + return $this->_sheetView; + } + + /** + * Set sheet view + * + * @param PHPExcel_Worksheet_SheetView $pValue + * @return PHPExcel_Worksheet + */ + public function setSheetView(PHPExcel_Worksheet_SheetView $pValue) + { + $this->_sheetView = $pValue; + return $this; + } + + /** + * Get Protection + * + * @return PHPExcel_Worksheet_Protection + */ + public function getProtection() + { + return $this->_protection; + } + + /** + * Set Protection + * + * @param PHPExcel_Worksheet_Protection $pValue + * @return PHPExcel_Worksheet + */ + public function setProtection(PHPExcel_Worksheet_Protection $pValue) + { + $this->_protection = $pValue; + $this->_dirty = true; + + return $this; + } + + /** + * Get highest worksheet column + * + * @return string Highest column name + */ + public function getHighestColumn() + { + return $this->_cachedHighestColumn; + } + + /** + * Get highest worksheet column that contains data + * + * @return string Highest column name that contains data + */ + public function getHighestDataColumn() + { + return $this->_cellCollection->getHighestColumn(); + } + + /** + * Get highest worksheet row + * + * @return int Highest row number + */ + public function getHighestRow() + { + return $this->_cachedHighestRow; + } + + /** + * Get highest worksheet row that contains data + * + * @return string Highest row number that contains data + */ + public function getHighestDataRow() + { + return $this->_cellCollection->getHighestRow(); + } + + /** + * Get highest worksheet column and highest row that have cell records + * + * @return array Highest column name and highest row number + */ + public function getHighestRowAndColumn() + { + return $this->_cellCollection->getHighestRowAndColumn(); + } + + /** + * Set a cell value + * + * @param string $pCoordinate Coordinate of the cell + * @param mixed $pValue Value of the cell + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValue($pCoordinate = 'A1', $pValue = null, $returnCell = false) + { + $cell = $this->getCell($pCoordinate)->setValue($pValue); + return ($returnCell) ? $cell : $this; + } + + /** + * Set a cell value by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell (A = 0) + * @param string $pRow Numeric row coordinate of the cell + * @param mixed $pValue Value of the cell + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValueByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $returnCell = false) + { + $cell = $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValue($pValue); + return ($returnCell) ? $cell : $this; + } + + /** + * Set a cell value + * + * @param string $pCoordinate Coordinate of the cell + * @param mixed $pValue Value of the cell + * @param string $pDataType Explicit data type + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValueExplicit($pCoordinate = 'A1', $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false) + { + // Set value + $cell = $this->getCell($pCoordinate)->setValueExplicit($pValue, $pDataType); + return ($returnCell) ? $cell : $this; + } + + /** + * Set a cell value by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell + * @param string $pRow Numeric row coordinate of the cell + * @param mixed $pValue Value of the cell + * @param string $pDataType Explicit data type + * @param bool $returnCell Return the worksheet (false, default) or the cell (true) + * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified + */ + public function setCellValueExplicitByColumnAndRow($pColumn = 0, $pRow = 1, $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false) + { + $cell = $this->getCell(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow)->setValueExplicit($pValue, $pDataType); + return ($returnCell) ? $cell : $this; + } + + /** + * Get cell at a specific coordinate + * + * @param string $pCoordinate Coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Cell Cell that was found + */ + public function getCell($pCoordinate = 'A1') + { + // Check cell collection + if ($this->_cellCollection->isDataSet($pCoordinate)) { + return $this->_cellCollection->getCacheData($pCoordinate); + } + + // Worksheet reference? + if (strpos($pCoordinate, '!') !== false) { + $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); + return $this->_parent->getSheetByName($worksheetReference[0])->getCell($worksheetReference[1]); + } + + // Named range? + if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches)) && + (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $pCoordinate, $matches))) { + $namedRange = PHPExcel_NamedRange::resolveRange($pCoordinate, $this); + if ($namedRange !== NULL) { + $pCoordinate = $namedRange->getRange(); + return $namedRange->getWorksheet()->getCell($pCoordinate); + } + } + + // Uppercase coordinate + $pCoordinate = strtoupper($pCoordinate); + + if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { + throw new PHPExcel_Exception('Cell coordinate can not be a range of cells.'); + } elseif (strpos($pCoordinate,'$') !== false) { + throw new PHPExcel_Exception('Cell coordinate must not be absolute.'); + } else { + // Create new cell object + + // Coordinates + $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); + + $cell = $this->_cellCollection->addCacheData($pCoordinate,new PHPExcel_Cell(NULL, PHPExcel_Cell_DataType::TYPE_NULL, $this)); + $this->_cellCollectionIsSorted = false; + + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($aCoordinates[0])) + $this->_cachedHighestColumn = $aCoordinates[0]; + + $this->_cachedHighestRow = max($this->_cachedHighestRow,$aCoordinates[1]); + + // Cell needs appropriate xfIndex + $rowDimensions = $this->getRowDimensions(); + $columnDimensions = $this->getColumnDimensions(); + + if ( isset($rowDimensions[$aCoordinates[1]]) && $rowDimensions[$aCoordinates[1]]->getXfIndex() !== null ) { + // then there is a row dimension with explicit style, assign it to the cell + $cell->setXfIndex($rowDimensions[$aCoordinates[1]]->getXfIndex()); + } else if ( isset($columnDimensions[$aCoordinates[0]]) ) { + // then there is a column dimension, assign it to the cell + $cell->setXfIndex($columnDimensions[$aCoordinates[0]]->getXfIndex()); + } else { + // set to default index + $cell->setXfIndex(0); + } + + return $cell; + } + } + + /** + * Get cell at a specific coordinate by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell + * @param string $pRow Numeric row coordinate of the cell + * @return PHPExcel_Cell Cell that was found + */ + public function getCellByColumnAndRow($pColumn = 0, $pRow = 1) + { + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($pColumn); + $coordinate = $columnLetter . $pRow; + + if (!$this->_cellCollection->isDataSet($coordinate)) { + $cell = $this->_cellCollection->addCacheData($coordinate, new PHPExcel_Cell(NULL, PHPExcel_Cell_DataType::TYPE_NULL, $this)); + $this->_cellCollectionIsSorted = false; + + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < $pColumn) + $this->_cachedHighestColumn = $columnLetter; + + $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow); + + return $cell; + } + + return $this->_cellCollection->getCacheData($coordinate); + } + + /** + * Cell at a specific coordinate exists? + * + * @param string $pCoordinate Coordinate of the cell + * @throws PHPExcel_Exception + * @return boolean + */ + public function cellExists($pCoordinate = 'A1') + { + // Worksheet reference? + if (strpos($pCoordinate, '!') !== false) { + $worksheetReference = PHPExcel_Worksheet::extractSheetTitle($pCoordinate, true); + return $this->_parent->getSheetByName($worksheetReference[0])->cellExists($worksheetReference[1]); + } + + // Named range? + if ((!preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_CELLREF.'$/i', $pCoordinate, $matches)) && + (preg_match('/^'.PHPExcel_Calculation::CALCULATION_REGEXP_NAMEDRANGE.'$/i', $pCoordinate, $matches))) { + $namedRange = PHPExcel_NamedRange::resolveRange($pCoordinate, $this); + if ($namedRange !== NULL) { + $pCoordinate = $namedRange->getRange(); + if ($this->getHashCode() != $namedRange->getWorksheet()->getHashCode()) { + if (!$namedRange->getLocalOnly()) { + return $namedRange->getWorksheet()->cellExists($pCoordinate); + } else { + throw new PHPExcel_Exception('Named range ' . $namedRange->getName() . ' is not accessible from within sheet ' . $this->getTitle()); + } + } + } + else { return false; } + } + + // Uppercase coordinate + $pCoordinate = strtoupper($pCoordinate); + + if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { + throw new PHPExcel_Exception('Cell coordinate can not be a range of cells.'); + } elseif (strpos($pCoordinate,'$') !== false) { + throw new PHPExcel_Exception('Cell coordinate must not be absolute.'); + } else { + // Coordinates + $aCoordinates = PHPExcel_Cell::coordinateFromString($pCoordinate); + + // Cell exists? + return $this->_cellCollection->isDataSet($pCoordinate); + } + } + + /** + * Cell at a specific coordinate by using numeric cell coordinates exists? + * + * @param string $pColumn Numeric column coordinate of the cell + * @param string $pRow Numeric row coordinate of the cell + * @return boolean + */ + public function cellExistsByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->cellExists(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } + + /** + * Get row dimension at a specific row + * + * @param int $pRow Numeric index of the row + * @return PHPExcel_Worksheet_RowDimension + */ + public function getRowDimension($pRow = 1) + { + // Found + $found = null; + + // Get row dimension + if (!isset($this->_rowDimensions[$pRow])) { + $this->_rowDimensions[$pRow] = new PHPExcel_Worksheet_RowDimension($pRow); + + $this->_cachedHighestRow = max($this->_cachedHighestRow,$pRow); + } + return $this->_rowDimensions[$pRow]; + } + + /** + * Get column dimension at a specific column + * + * @param string $pColumn String index of the column + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function getColumnDimension($pColumn = 'A') + { + // Uppercase coordinate + $pColumn = strtoupper($pColumn); + + // Fetch dimensions + if (!isset($this->_columnDimensions[$pColumn])) { + $this->_columnDimensions[$pColumn] = new PHPExcel_Worksheet_ColumnDimension($pColumn); + + if (PHPExcel_Cell::columnIndexFromString($this->_cachedHighestColumn) < PHPExcel_Cell::columnIndexFromString($pColumn)) + $this->_cachedHighestColumn = $pColumn; + } + return $this->_columnDimensions[$pColumn]; + } + + /** + * Get column dimension at a specific column by using numeric cell coordinates + * + * @param string $pColumn Numeric column coordinate of the cell + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function getColumnDimensionByColumn($pColumn = 0) + { + return $this->getColumnDimension(PHPExcel_Cell::stringFromColumnIndex($pColumn)); + } + + /** + * Get styles + * + * @return PHPExcel_Style[] + */ + public function getStyles() + { + return $this->_styles; + } + + /** + * Get default style of workbook. + * + * @deprecated + * @return PHPExcel_Style + * @throws PHPExcel_Exception + */ + public function getDefaultStyle() + { + return $this->_parent->getDefaultStyle(); + } + + /** + * Set default style - should only be used by PHPExcel_IReader implementations! + * + * @deprecated + * @param PHPExcel_Style $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setDefaultStyle(PHPExcel_Style $pValue) + { + $this->_parent->getDefaultStyle()->applyFromArray(array( + 'font' => array( + 'name' => $pValue->getFont()->getName(), + 'size' => $pValue->getFont()->getSize(), + ), + )); + return $this; + } + + /** + * Get style for cell + * + * @param string $pCellCoordinate Cell coordinate to get style for + * @return PHPExcel_Style + * @throws PHPExcel_Exception + */ + public function getStyle($pCellCoordinate = 'A1') + { + // set this sheet as active + $this->_parent->setActiveSheetIndex($this->_parent->getIndex($this)); + + // set cell coordinate as active + $this->setSelectedCells($pCellCoordinate); + + return $this->_parent->getCellXfSupervisor(); + } + + /** + * Get conditional styles for a cell + * + * @param string $pCoordinate + * @return PHPExcel_Style_Conditional[] + */ + public function getConditionalStyles($pCoordinate = 'A1') + { + if (!isset($this->_conditionalStylesCollection[$pCoordinate])) { + $this->_conditionalStylesCollection[$pCoordinate] = array(); + } + return $this->_conditionalStylesCollection[$pCoordinate]; + } + + /** + * Do conditional styles exist for this cell? + * + * @param string $pCoordinate + * @return boolean + */ + public function conditionalStylesExists($pCoordinate = 'A1') + { + if (isset($this->_conditionalStylesCollection[$pCoordinate])) { + return true; + } + return false; + } + + /** + * Removes conditional styles for a cell + * + * @param string $pCoordinate + * @return PHPExcel_Worksheet + */ + public function removeConditionalStyles($pCoordinate = 'A1') + { + unset($this->_conditionalStylesCollection[$pCoordinate]); + return $this; + } + + /** + * Get collection of conditional styles + * + * @return array + */ + public function getConditionalStylesCollection() + { + return $this->_conditionalStylesCollection; + } + + /** + * Set conditional styles + * + * @param $pCoordinate string E.g. 'A1' + * @param $pValue PHPExcel_Style_Conditional[] + * @return PHPExcel_Worksheet + */ + public function setConditionalStyles($pCoordinate = 'A1', $pValue) + { + $this->_conditionalStylesCollection[$pCoordinate] = $pValue; + return $this; + } + + /** + * Get style for cell by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @return PHPExcel_Style + */ + public function getStyleByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->getStyle(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } + + /** + * Set shared cell style to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range! + * + * @deprecated + * @param PHPExcel_Style $pSharedCellStyle Cell style to share + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setSharedStyle(PHPExcel_Style $pSharedCellStyle = null, $pRange = '') + { + $this->duplicateStyle($pSharedCellStyle, $pRange); + return $this; + } + + /** + * Duplicate cell style to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range! + * + * @param PHPExcel_Style $pCellStyle Cell style to duplicate + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function duplicateStyle(PHPExcel_Style $pCellStyle = null, $pRange = '') + { + // make sure we have a real style and not supervisor + $style = $pCellStyle->getIsSupervisor() ? $pCellStyle->getSharedComponent() : $pCellStyle; + + // Add the style to the workbook if necessary + $workbook = $this->_parent; + if ($this->_parent->cellXfExists($pCellStyle)) { + // there is already this cell Xf in our collection + $xfIndex = $pCellStyle->getIndex(); + } else { + // we don't have such a cell Xf, need to add + $workbook->addCellXf($pCellStyle); + $xfIndex = $pCellStyle->getIndex(); + } + + // Uppercase coordinate + $pRange = strtoupper($pRange); + + // Is it a cell range or a single cell? + $rangeA = ''; + $rangeB = ''; + if (strpos($pRange, ':') === false) { + $rangeA = $pRange; + $rangeB = $pRange; + } else { + list($rangeA, $rangeB) = explode(':', $pRange); + } + + // Calculate range outer borders + $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); + $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); + + // Translate column into index + $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; + $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; + + // Make sure we can loop upwards on rows and columns + if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { + $tmp = $rangeStart; + $rangeStart = $rangeEnd; + $rangeEnd = $tmp; + } + + // Loop through cells and apply styles + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $this->getCell(PHPExcel_Cell::stringFromColumnIndex($col) . $row)->setXfIndex($xfIndex); + } + } + + return $this; + } + + /** + * Duplicate conditional style to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range! + * + * @param array of PHPExcel_Style_Conditional $pCellStyle Cell style to duplicate + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function duplicateConditionalStyle(array $pCellStyle = null, $pRange = '') + { + foreach($pCellStyle as $cellStyle) { + if (!($cellStyle instanceof PHPExcel_Style_Conditional)) { + throw new PHPExcel_Exception('Style is not a conditional style'); + } + } + + // Uppercase coordinate + $pRange = strtoupper($pRange); + + // Is it a cell range or a single cell? + $rangeA = ''; + $rangeB = ''; + if (strpos($pRange, ':') === false) { + $rangeA = $pRange; + $rangeB = $pRange; + } else { + list($rangeA, $rangeB) = explode(':', $pRange); + } + + // Calculate range outer borders + $rangeStart = PHPExcel_Cell::coordinateFromString($rangeA); + $rangeEnd = PHPExcel_Cell::coordinateFromString($rangeB); + + // Translate column into index + $rangeStart[0] = PHPExcel_Cell::columnIndexFromString($rangeStart[0]) - 1; + $rangeEnd[0] = PHPExcel_Cell::columnIndexFromString($rangeEnd[0]) - 1; + + // Make sure we can loop upwards on rows and columns + if ($rangeStart[0] > $rangeEnd[0] && $rangeStart[1] > $rangeEnd[1]) { + $tmp = $rangeStart; + $rangeStart = $rangeEnd; + $rangeEnd = $tmp; + } + + // Loop through cells and apply styles + for ($col = $rangeStart[0]; $col <= $rangeEnd[0]; ++$col) { + for ($row = $rangeStart[1]; $row <= $rangeEnd[1]; ++$row) { + $this->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($col) . $row, $pCellStyle); + } + } + + return $this; + } + + /** + * Duplicate cell style array to a range of cells + * + * Please note that this will overwrite existing cell styles for cells in range, + * if they are in the styles array. For example, if you decide to set a range of + * cells to font bold, only include font bold in the styles array. + * + * @deprecated + * @param array $pStyles Array containing style information + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @param boolean $pAdvanced Advanced mode for setting borders. + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function duplicateStyleArray($pStyles = null, $pRange = '', $pAdvanced = true) + { + $this->getStyle($pRange)->applyFromArray($pStyles, $pAdvanced); + return $this; + } + + /** + * Set break on a cell + * + * @param string $pCell Cell coordinate (e.g. A1) + * @param int $pBreak Break type (type of PHPExcel_Worksheet::BREAK_*) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setBreak($pCell = 'A1', $pBreak = PHPExcel_Worksheet::BREAK_NONE) + { + // Uppercase coordinate + $pCell = strtoupper($pCell); + + if ($pCell != '') { + if ($pBreak == PHPExcel_Worksheet::BREAK_NONE) { + if (isset($this->_breaks[$pCell])) { + unset($this->_breaks[$pCell]); + } + } else { + $this->_breaks[$pCell] = $pBreak; + } + } else { + throw new PHPExcel_Exception('No cell coordinate specified.'); + } + + return $this; + } + + /** + * Set break on a cell by using numeric cell coordinates + * + * @param integer $pColumn Numeric column coordinate of the cell + * @param integer $pRow Numeric row coordinate of the cell + * @param integer $pBreak Break type (type of PHPExcel_Worksheet::BREAK_*) + * @return PHPExcel_Worksheet + */ + public function setBreakByColumnAndRow($pColumn = 0, $pRow = 1, $pBreak = PHPExcel_Worksheet::BREAK_NONE) + { + return $this->setBreak(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow, $pBreak); + } + + /** + * Get breaks + * + * @return array[] + */ + public function getBreaks() + { + return $this->_breaks; + } + + /** + * Set merge on a cell range + * + * @param string $pRange Cell range (e.g. A1:E1) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function mergeCells($pRange = 'A1:A1') + { + // Uppercase coordinate + $pRange = strtoupper($pRange); + + if (strpos($pRange,':') !== false) { + $this->_mergeCells[$pRange] = $pRange; + + // make sure cells are created + + // get the cells in the range + $aReferences = PHPExcel_Cell::extractAllCellReferencesInRange($pRange); + + // create upper left cell if it does not already exist + $upperLeft = $aReferences[0]; + if (!$this->cellExists($upperLeft)) { + $this->getCell($upperLeft)->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); + } + + // create or blank out the rest of the cells in the range + $count = count($aReferences); + for ($i = 1; $i < $count; $i++) { + $this->getCell($aReferences[$i])->setValueExplicit(null, PHPExcel_Cell_DataType::TYPE_NULL); + } + + } else { + throw new PHPExcel_Exception('Merge must be set on a range of cells.'); + } + + return $this; + } + + /** + * Set merge on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function mergeCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->mergeCells($cellRange); + } + + /** + * Remove merge on a cell range + * + * @param string $pRange Cell range (e.g. A1:E1) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unmergeCells($pRange = 'A1:A1') + { + // Uppercase coordinate + $pRange = strtoupper($pRange); + + if (strpos($pRange,':') !== false) { + if (isset($this->_mergeCells[$pRange])) { + unset($this->_mergeCells[$pRange]); + } else { + throw new PHPExcel_Exception('Cell range ' . $pRange . ' not known as merged.'); + } + } else { + throw new PHPExcel_Exception('Merge can only be removed from a range of cells.'); + } + + return $this; + } + + /** + * Remove merge on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unmergeCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->unmergeCells($cellRange); + } + + /** + * Get merge cells array. + * + * @return array[] + */ + public function getMergeCells() + { + return $this->_mergeCells; + } + + /** + * Set merge cells array for the entire sheet. Use instead mergeCells() to merge + * a single cell range. + * + * @param array + */ + public function setMergeCells($pValue = array()) + { + $this->_mergeCells = $pValue; + + return $this; + } + + /** + * Set protection on a cell range + * + * @param string $pRange Cell (e.g. A1) or cell range (e.g. A1:E1) + * @param string $pPassword Password to unlock the protection + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function protectCells($pRange = 'A1', $pPassword = '', $pAlreadyHashed = false) + { + // Uppercase coordinate + $pRange = strtoupper($pRange); + + if (!$pAlreadyHashed) { + $pPassword = PHPExcel_Shared_PasswordHasher::hashPassword($pPassword); + } + $this->_protectedCells[$pRange] = $pPassword; + + return $this; + } + + /** + * Set protection on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @param string $pPassword Password to unlock the protection + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function protectCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1, $pPassword = '', $pAlreadyHashed = false) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->protectCells($cellRange, $pPassword, $pAlreadyHashed); + } + + /** + * Remove protection on a cell range + * + * @param string $pRange Cell (e.g. A1) or cell range (e.g. A1:E1) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unprotectCells($pRange = 'A1') + { + // Uppercase coordinate + $pRange = strtoupper($pRange); + + if (isset($this->_protectedCells[$pRange])) { + unset($this->_protectedCells[$pRange]); + } else { + throw new PHPExcel_Exception('Cell range ' . $pRange . ' not known as protected.'); + } + return $this; + } + + /** + * Remove protection on a cell range by using numeric cell coordinates + * + * @param int $pColumn1 Numeric column coordinate of the first cell + * @param int $pRow1 Numeric row coordinate of the first cell + * @param int $pColumn2 Numeric column coordinate of the last cell + * @param int $pRow2 Numeric row coordinate of the last cell + * @param string $pPassword Password to unlock the protection + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function unprotectCellsByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1, $pPassword = '', $pAlreadyHashed = false) + { + $cellRange = PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 . ':' . PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2; + return $this->unprotectCells($cellRange, $pPassword, $pAlreadyHashed); + } + + /** + * Get protected cells + * + * @return array[] + */ + public function getProtectedCells() + { + return $this->_protectedCells; + } + + /** + * Get Autofilter + * + * @return PHPExcel_Worksheet_AutoFilter + */ + public function getAutoFilter() + { + return $this->_autoFilter; + } + + /** + * Set AutoFilter + * + * @param PHPExcel_Worksheet_AutoFilter|string $pValue + * A simple string containing a Cell range like 'A1:E10' is permitted for backward compatibility + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setAutoFilter($pValue) + { + if (is_string($pValue)) { + $this->_autoFilter->setRange($pValue); + } elseif(is_object($pValue) && ($pValue instanceof PHPExcel_Worksheet_AutoFilter)) { + $this->_autoFilter = $pValue; + } + return $this; + } + + /** + * Set Autofilter Range by using numeric cell coordinates + * + * @param integer $pColumn1 Numeric column coordinate of the first cell + * @param integer $pRow1 Numeric row coordinate of the first cell + * @param integer $pColumn2 Numeric column coordinate of the second cell + * @param integer $pRow2 Numeric row coordinate of the second cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setAutoFilterByColumnAndRow($pColumn1 = 0, $pRow1 = 1, $pColumn2 = 0, $pRow2 = 1) + { + return $this->setAutoFilter( + PHPExcel_Cell::stringFromColumnIndex($pColumn1) . $pRow1 + . ':' . + PHPExcel_Cell::stringFromColumnIndex($pColumn2) . $pRow2 + ); + } + + /** + * Remove autofilter + * + * @return PHPExcel_Worksheet + */ + public function removeAutoFilter() + { + $this->_autoFilter->setRange(NULL); + return $this; + } + + /** + * Get Freeze Pane + * + * @return string + */ + public function getFreezePane() + { + return $this->_freezePane; + } + + /** + * Freeze Pane + * + * @param string $pCell Cell (i.e. A2) + * Examples: + * A2 will freeze the rows above cell A2 (i.e row 1) + * B1 will freeze the columns to the left of cell B1 (i.e column A) + * B2 will freeze the rows above and to the left of cell A2 + * (i.e row 1 and column A) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function freezePane($pCell = '') + { + // Uppercase coordinate + $pCell = strtoupper($pCell); + + if (strpos($pCell,':') === false && strpos($pCell,',') === false) { + $this->_freezePane = $pCell; + } else { + throw new PHPExcel_Exception('Freeze pane can not be set on a range of cells.'); + } + return $this; + } + + /** + * Freeze Pane by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function freezePaneByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->freezePane(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } + + /** + * Unfreeze Pane + * + * @return PHPExcel_Worksheet + */ + public function unfreezePane() + { + return $this->freezePane(''); + } + + /** + * Insert a new row, updating all possible related data + * + * @param int $pBefore Insert before this one + * @param int $pNumRows Number of rows to insert + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function insertNewRowBefore($pBefore = 1, $pNumRows = 1) { + if ($pBefore >= 1) { + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore('A' . $pBefore, 0, $pNumRows, $this); + } else { + throw new PHPExcel_Exception("Rows can only be inserted before at least row 1."); + } + return $this; + } + + /** + * Insert a new column, updating all possible related data + * + * @param int $pBefore Insert before this one + * @param int $pNumCols Number of columns to insert + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function insertNewColumnBefore($pBefore = 'A', $pNumCols = 1) { + if (!is_numeric($pBefore)) { + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore($pBefore . '1', $pNumCols, 0, $this); + } else { + throw new PHPExcel_Exception("Column references should not be numeric."); + } + return $this; + } + + /** + * Insert a new column, updating all possible related data + * + * @param int $pBefore Insert before this one (numeric column coordinate of the cell) + * @param int $pNumCols Number of columns to insert + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function insertNewColumnBeforeByIndex($pBefore = 0, $pNumCols = 1) { + if ($pBefore >= 0) { + return $this->insertNewColumnBefore(PHPExcel_Cell::stringFromColumnIndex($pBefore), $pNumCols); + } else { + throw new PHPExcel_Exception("Columns can only be inserted before at least column A (0)."); + } + } + + /** + * Delete a row, updating all possible related data + * + * @param int $pRow Remove starting with this one + * @param int $pNumRows Number of rows to remove + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function removeRow($pRow = 1, $pNumRows = 1) { + if ($pRow >= 1) { + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore('A' . ($pRow + $pNumRows), 0, -$pNumRows, $this); + } else { + throw new PHPExcel_Exception("Rows to be deleted should at least start from row 1."); + } + return $this; + } + + /** + * Remove a column, updating all possible related data + * + * @param int $pColumn Remove starting with this one + * @param int $pNumCols Number of columns to remove + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function removeColumn($pColumn = 'A', $pNumCols = 1) { + if (!is_numeric($pColumn)) { + $pColumn = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($pColumn) - 1 + $pNumCols); + $objReferenceHelper = PHPExcel_ReferenceHelper::getInstance(); + $objReferenceHelper->insertNewBefore($pColumn . '1', -$pNumCols, 0, $this); + } else { + throw new PHPExcel_Exception("Column references should not be numeric."); + } + return $this; + } + + /** + * Remove a column, updating all possible related data + * + * @param int $pColumn Remove starting with this one (numeric column coordinate of the cell) + * @param int $pNumCols Number of columns to remove + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function removeColumnByIndex($pColumn = 0, $pNumCols = 1) { + if ($pColumn >= 0) { + return $this->removeColumn(PHPExcel_Cell::stringFromColumnIndex($pColumn), $pNumCols); + } else { + throw new PHPExcel_Exception("Columns to be deleted should at least start from column 0"); + } + } + + /** + * Show gridlines? + * + * @return boolean + */ + public function getShowGridlines() { + return $this->_showGridlines; + } + + /** + * Set show gridlines + * + * @param boolean $pValue Show gridlines (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowGridlines($pValue = false) { + $this->_showGridlines = $pValue; + return $this; + } + + /** + * Print gridlines? + * + * @return boolean + */ + public function getPrintGridlines() { + return $this->_printGridlines; + } + + /** + * Set print gridlines + * + * @param boolean $pValue Print gridlines (true/false) + * @return PHPExcel_Worksheet + */ + public function setPrintGridlines($pValue = false) { + $this->_printGridlines = $pValue; + return $this; + } + + /** + * Show row and column headers? + * + * @return boolean + */ + public function getShowRowColHeaders() { + return $this->_showRowColHeaders; + } + + /** + * Set show row and column headers + * + * @param boolean $pValue Show row and column headers (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowRowColHeaders($pValue = false) { + $this->_showRowColHeaders = $pValue; + return $this; + } + + /** + * Show summary below? (Row/Column outlining) + * + * @return boolean + */ + public function getShowSummaryBelow() { + return $this->_showSummaryBelow; + } + + /** + * Set show summary below + * + * @param boolean $pValue Show summary below (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowSummaryBelow($pValue = true) { + $this->_showSummaryBelow = $pValue; + return $this; + } + + /** + * Show summary right? (Row/Column outlining) + * + * @return boolean + */ + public function getShowSummaryRight() { + return $this->_showSummaryRight; + } + + /** + * Set show summary right + * + * @param boolean $pValue Show summary right (true/false) + * @return PHPExcel_Worksheet + */ + public function setShowSummaryRight($pValue = true) { + $this->_showSummaryRight = $pValue; + return $this; + } + + /** + * Get comments + * + * @return PHPExcel_Comment[] + */ + public function getComments() + { + return $this->_comments; + } + + /** + * Set comments array for the entire sheet. + * + * @param array of PHPExcel_Comment + * @return PHPExcel_Worksheet + */ + public function setComments($pValue = array()) + { + $this->_comments = $pValue; + + return $this; + } + + /** + * Get comment for cell + * + * @param string $pCellCoordinate Cell coordinate to get comment for + * @return PHPExcel_Comment + * @throws PHPExcel_Exception + */ + public function getComment($pCellCoordinate = 'A1') + { + // Uppercase coordinate + $pCellCoordinate = strtoupper($pCellCoordinate); + + if (strpos($pCellCoordinate,':') !== false || strpos($pCellCoordinate,',') !== false) { + throw new PHPExcel_Exception('Cell coordinate string can not be a range of cells.'); + } else if (strpos($pCellCoordinate,'$') !== false) { + throw new PHPExcel_Exception('Cell coordinate string must not be absolute.'); + } else if ($pCellCoordinate == '') { + throw new PHPExcel_Exception('Cell coordinate can not be zero-length string.'); + } else { + // Check if we already have a comment for this cell. + // If not, create a new comment. + if (isset($this->_comments[$pCellCoordinate])) { + return $this->_comments[$pCellCoordinate]; + } else { + $newComment = new PHPExcel_Comment(); + $this->_comments[$pCellCoordinate] = $newComment; + return $newComment; + } + } + } + + /** + * Get comment for cell by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @return PHPExcel_Comment + */ + public function getCommentByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->getComment(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } + + /** + * Get selected cell + * + * @deprecated + * @return string + */ + public function getSelectedCell() + { + return $this->getSelectedCells(); + } + + /** + * Get active cell + * + * @return string Example: 'A1' + */ + public function getActiveCell() + { + return $this->_activeCell; + } + + /** + * Get selected cells + * + * @return string + */ + public function getSelectedCells() + { + return $this->_selectedCells; + } + + /** + * Selected cell + * + * @param string $pCoordinate Cell (i.e. A1) + * @return PHPExcel_Worksheet + */ + public function setSelectedCell($pCoordinate = 'A1') + { + return $this->setSelectedCells($pCoordinate); + } + + /** + * Select a range of cells. + * + * @param string $pCoordinate Cell range, examples: 'A1', 'B2:G5', 'A:C', '3:6' + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setSelectedCells($pCoordinate = 'A1') + { + // Uppercase coordinate + $pCoordinate = strtoupper($pCoordinate); + + // Convert 'A' to 'A:A' + $pCoordinate = preg_replace('/^([A-Z]+)$/', '${1}:${1}', $pCoordinate); + + // Convert '1' to '1:1' + $pCoordinate = preg_replace('/^([0-9]+)$/', '${1}:${1}', $pCoordinate); + + // Convert 'A:C' to 'A1:C1048576' + $pCoordinate = preg_replace('/^([A-Z]+):([A-Z]+)$/', '${1}1:${2}1048576', $pCoordinate); + + // Convert '1:3' to 'A1:XFD3' + $pCoordinate = preg_replace('/^([0-9]+):([0-9]+)$/', 'A${1}:XFD${2}', $pCoordinate); + + if (strpos($pCoordinate,':') !== false || strpos($pCoordinate,',') !== false) { + list($first, ) = PHPExcel_Cell::splitRange($pCoordinate); + $this->_activeCell = $first[0]; + } else { + $this->_activeCell = $pCoordinate; + } + $this->_selectedCells = $pCoordinate; + return $this; + } + + /** + * Selected cell by using numeric cell coordinates + * + * @param int $pColumn Numeric column coordinate of the cell + * @param int $pRow Numeric row coordinate of the cell + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function setSelectedCellByColumnAndRow($pColumn = 0, $pRow = 1) + { + return $this->setSelectedCells(PHPExcel_Cell::stringFromColumnIndex($pColumn) . $pRow); + } + + /** + * Get right-to-left + * + * @return boolean + */ + public function getRightToLeft() { + return $this->_rightToLeft; + } + + /** + * Set right-to-left + * + * @param boolean $value Right-to-left true/false + * @return PHPExcel_Worksheet + */ + public function setRightToLeft($value = false) { + $this->_rightToLeft = $value; + return $this; + } + + /** + * Fill worksheet from values in array + * + * @param array $source Source array + * @param mixed $nullValue Value in source array that stands for blank cell + * @param string $startCell Insert array starting from this cell address as the top left coordinate + * @param boolean $strictNullComparison Apply strict comparison when testing for null values in the array + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet + */ + public function fromArray($source = null, $nullValue = null, $startCell = 'A1', $strictNullComparison = false) { + if (is_array($source)) { + // Convert a 1-D array to 2-D (for ease of looping) + if (!is_array(end($source))) { + $source = array($source); + } + + // start coordinate + list ($startColumn, $startRow) = PHPExcel_Cell::coordinateFromString($startCell); + + // Loop through $source + foreach ($source as $rowData) { + $currentColumn = $startColumn; + foreach($rowData as $cellValue) { + if ($strictNullComparison) { + if ($cellValue !== $nullValue) { + // Set cell value + $this->getCell($currentColumn . $startRow)->setValue($cellValue); + } + } else { + if ($cellValue != $nullValue) { + // Set cell value + $this->getCell($currentColumn . $startRow)->setValue($cellValue); + } + } + ++$currentColumn; + } + ++$startRow; + } + } else { + throw new PHPExcel_Exception("Parameter \$source should be an array."); + } + return $this; + } + + /** + * Create array from a range of cells + * + * @param string $pRange Range of cells (i.e. "A1:B10"), or just one cell (i.e. "A1") + * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist + * @param boolean $calculateFormulas Should formulas be calculated? + * @param boolean $formatData Should formatting be applied to cell values? + * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero + * True - Return rows and columns indexed by their actual row and column IDs + * @return array + */ + public function rangeToArray($pRange = 'A1', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { + // Returnvalue + $returnValue = array(); + // Identify the range that we need to extract from the worksheet + list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($pRange); + $minCol = PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] -1); + $minRow = $rangeStart[1]; + $maxCol = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0] -1); + $maxRow = $rangeEnd[1]; + + $maxCol++; + // Loop through rows + $r = -1; + for ($row = $minRow; $row <= $maxRow; ++$row) { + $rRef = ($returnCellRef) ? $row : ++$r; + $c = -1; + // Loop through columns in the current row + for ($col = $minCol; $col != $maxCol; ++$col) { + $cRef = ($returnCellRef) ? $col : ++$c; + // Using getCell() will create a new cell if it doesn't already exist. We don't want that to happen + // so we test and retrieve directly against _cellCollection + if ($this->_cellCollection->isDataSet($col.$row)) { + // Cell exists + $cell = $this->_cellCollection->getCacheData($col.$row); + if ($cell->getValue() !== null) { + if ($cell->getValue() instanceof PHPExcel_RichText) { + $returnValue[$rRef][$cRef] = $cell->getValue()->getPlainText(); + } else { + if ($calculateFormulas) { + $returnValue[$rRef][$cRef] = $cell->getCalculatedValue(); + } else { + $returnValue[$rRef][$cRef] = $cell->getValue(); + } + } + + if ($formatData) { + $style = $this->_parent->getCellXfByIndex($cell->getXfIndex()); + $returnValue[$rRef][$cRef] = PHPExcel_Style_NumberFormat::toFormattedString( + $returnValue[$rRef][$cRef], + ($style->getNumberFormat()) ? + $style->getNumberFormat()->getFormatCode() : + PHPExcel_Style_NumberFormat::FORMAT_GENERAL + ); + } + } else { + // Cell holds a NULL + $returnValue[$rRef][$cRef] = $nullValue; + } + } else { + // Cell doesn't exist + $returnValue[$rRef][$cRef] = $nullValue; + } + } + } + + // Return + return $returnValue; + } + + + /** + * Create array from a range of cells + * + * @param string $pNamedRange Name of the Named Range + * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist + * @param boolean $calculateFormulas Should formulas be calculated? + * @param boolean $formatData Should formatting be applied to cell values? + * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero + * True - Return rows and columns indexed by their actual row and column IDs + * @return array + * @throws PHPExcel_Exception + */ + public function namedRangeToArray($pNamedRange = '', $nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { + $namedRange = PHPExcel_NamedRange::resolveRange($pNamedRange, $this); + if ($namedRange !== NULL) { + $pWorkSheet = $namedRange->getWorksheet(); + $pCellRange = $namedRange->getRange(); + + return $pWorkSheet->rangeToArray( $pCellRange, + $nullValue, $calculateFormulas, $formatData, $returnCellRef); + } + + throw new PHPExcel_Exception('Named Range '.$pNamedRange.' does not exist.'); + } + + + /** + * Create array from worksheet + * + * @param mixed $nullValue Value returned in the array entry if a cell doesn't exist + * @param boolean $calculateFormulas Should formulas be calculated? + * @param boolean $formatData Should formatting be applied to cell values? + * @param boolean $returnCellRef False - Return a simple array of rows and columns indexed by number counting from zero + * True - Return rows and columns indexed by their actual row and column IDs + * @return array + */ + public function toArray($nullValue = null, $calculateFormulas = true, $formatData = true, $returnCellRef = false) { + // Garbage collect... + $this->garbageCollect(); + + // Identify the range that we need to extract from the worksheet + $maxCol = $this->getHighestColumn(); + $maxRow = $this->getHighestRow(); + // Return + return $this->rangeToArray( 'A1:'.$maxCol.$maxRow, + $nullValue, $calculateFormulas, $formatData, $returnCellRef); + } + + /** + * Get row iterator + * + * @param integer $startRow The row number at which to start iterating + * @return PHPExcel_Worksheet_RowIterator + */ + public function getRowIterator($startRow = 1) { + return new PHPExcel_Worksheet_RowIterator($this,$startRow); + } + + /** + * Run PHPExcel garabage collector. + * + * @return PHPExcel_Worksheet + */ + public function garbageCollect() { + // Flush cache + $this->_cellCollection->getCacheData('A1'); + // Build a reference table from images +// $imageCoordinates = array(); +// $iterator = $this->getDrawingCollection()->getIterator(); +// while ($iterator->valid()) { +// $imageCoordinates[$iterator->current()->getCoordinates()] = true; +// +// $iterator->next(); +// } +// + // Lookup highest column and highest row if cells are cleaned + $colRow = $this->_cellCollection->getHighestRowAndColumn(); + $highestRow = $colRow['row']; + $highestColumn = PHPExcel_Cell::columnIndexFromString($colRow['column']); + + // Loop through column dimensions + foreach ($this->_columnDimensions as $dimension) { + $highestColumn = max($highestColumn,PHPExcel_Cell::columnIndexFromString($dimension->getColumnIndex())); + } + + // Loop through row dimensions + foreach ($this->_rowDimensions as $dimension) { + $highestRow = max($highestRow,$dimension->getRowIndex()); + } + + // Cache values + if ($highestColumn < 0) { + $this->_cachedHighestColumn = 'A'; + } else { + $this->_cachedHighestColumn = PHPExcel_Cell::stringFromColumnIndex(--$highestColumn); + } + $this->_cachedHighestRow = $highestRow; + + // Return + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + if ($this->_dirty) { + $this->_hash = md5( $this->_title . + $this->_autoFilter . + ($this->_protection->isProtectionEnabled() ? 't' : 'f') . + __CLASS__ + ); + $this->_dirty = false; + } + return $this->_hash; + } + + /** + * Extract worksheet title from range. + * + * Example: extractSheetTitle("testSheet!A1") ==> 'A1' + * Example: extractSheetTitle("'testSheet 1'!A1", true) ==> array('testSheet 1', 'A1'); + * + * @param string $pRange Range to extract title from + * @param bool $returnRange Return range? (see example) + * @return mixed + */ + public static function extractSheetTitle($pRange, $returnRange = false) { + // Sheet title included? + if (($sep = strpos($pRange, '!')) === false) { + return ''; + } + + if ($returnRange) { + return array( trim(substr($pRange, 0, $sep),"'"), + substr($pRange, $sep + 1) + ); + } + + return substr($pRange, $sep + 1); + } + + /** + * Get hyperlink + * + * @param string $pCellCoordinate Cell coordinate to get hyperlink for + */ + public function getHyperlink($pCellCoordinate = 'A1') + { + // return hyperlink if we already have one + if (isset($this->_hyperlinkCollection[$pCellCoordinate])) { + return $this->_hyperlinkCollection[$pCellCoordinate]; + } + + // else create hyperlink + $this->_hyperlinkCollection[$pCellCoordinate] = new PHPExcel_Cell_Hyperlink(); + return $this->_hyperlinkCollection[$pCellCoordinate]; + } + + /** + * Set hyperlnk + * + * @param string $pCellCoordinate Cell coordinate to insert hyperlink + * @param PHPExcel_Cell_Hyperlink $pHyperlink + * @return PHPExcel_Worksheet + */ + public function setHyperlink($pCellCoordinate = 'A1', PHPExcel_Cell_Hyperlink $pHyperlink = null) + { + if ($pHyperlink === null) { + unset($this->_hyperlinkCollection[$pCellCoordinate]); + } else { + $this->_hyperlinkCollection[$pCellCoordinate] = $pHyperlink; + } + return $this; + } + + /** + * Hyperlink at a specific coordinate exists? + * + * @param string $pCoordinate + * @return boolean + */ + public function hyperlinkExists($pCoordinate = 'A1') + { + return isset($this->_hyperlinkCollection[$pCoordinate]); + } + + /** + * Get collection of hyperlinks + * + * @return PHPExcel_Cell_Hyperlink[] + */ + public function getHyperlinkCollection() + { + return $this->_hyperlinkCollection; + } + + /** + * Get data validation + * + * @param string $pCellCoordinate Cell coordinate to get data validation for + */ + public function getDataValidation($pCellCoordinate = 'A1') + { + // return data validation if we already have one + if (isset($this->_dataValidationCollection[$pCellCoordinate])) { + return $this->_dataValidationCollection[$pCellCoordinate]; + } + + // else create data validation + $this->_dataValidationCollection[$pCellCoordinate] = new PHPExcel_Cell_DataValidation(); + return $this->_dataValidationCollection[$pCellCoordinate]; + } + + /** + * Set data validation + * + * @param string $pCellCoordinate Cell coordinate to insert data validation + * @param PHPExcel_Cell_DataValidation $pDataValidation + * @return PHPExcel_Worksheet + */ + public function setDataValidation($pCellCoordinate = 'A1', PHPExcel_Cell_DataValidation $pDataValidation = null) + { + if ($pDataValidation === null) { + unset($this->_dataValidationCollection[$pCellCoordinate]); + } else { + $this->_dataValidationCollection[$pCellCoordinate] = $pDataValidation; + } + return $this; + } + + /** + * Data validation at a specific coordinate exists? + * + * @param string $pCoordinate + * @return boolean + */ + public function dataValidationExists($pCoordinate = 'A1') + { + return isset($this->_dataValidationCollection[$pCoordinate]); + } + + /** + * Get collection of data validations + * + * @return PHPExcel_Cell_DataValidation[] + */ + public function getDataValidationCollection() + { + return $this->_dataValidationCollection; + } + + /** + * Accepts a range, returning it as a range that falls within the current highest row and column of the worksheet + * + * @param string $range + * @return string Adjusted range value + */ + public function shrinkRangeToFit($range) { + $maxCol = $this->getHighestColumn(); + $maxRow = $this->getHighestRow(); + $maxCol = PHPExcel_Cell::columnIndexFromString($maxCol); + + $rangeBlocks = explode(' ',$range); + foreach ($rangeBlocks as &$rangeSet) { + $rangeBoundaries = PHPExcel_Cell::getRangeBoundaries($rangeSet); + + if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[0][0]) > $maxCol) { $rangeBoundaries[0][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } + if ($rangeBoundaries[0][1] > $maxRow) { $rangeBoundaries[0][1] = $maxRow; } + if (PHPExcel_Cell::columnIndexFromString($rangeBoundaries[1][0]) > $maxCol) { $rangeBoundaries[1][0] = PHPExcel_Cell::stringFromColumnIndex($maxCol); } + if ($rangeBoundaries[1][1] > $maxRow) { $rangeBoundaries[1][1] = $maxRow; } + $rangeSet = $rangeBoundaries[0][0].$rangeBoundaries[0][1].':'.$rangeBoundaries[1][0].$rangeBoundaries[1][1]; + } + unset($rangeSet); + $stRange = implode(' ',$rangeBlocks); + + return $stRange; + } + + /** + * Get tab color + * + * @return PHPExcel_Style_Color + */ + public function getTabColor() + { + if ($this->_tabColor === NULL) + $this->_tabColor = new PHPExcel_Style_Color(); + + return $this->_tabColor; + } + + /** + * Reset tab color + * + * @return PHPExcel_Worksheet + */ + public function resetTabColor() + { + $this->_tabColor = null; + unset($this->_tabColor); + + return $this; + } + + /** + * Tab color set? + * + * @return boolean + */ + public function isTabColorSet() + { + return ($this->_tabColor !== NULL); + } + + /** + * Copy worksheet (!= clone!) + * + * @return PHPExcel_Worksheet + */ + public function copy() { + $copied = clone $this; + + return $copied; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + foreach ($this as $key => $val) { + if ($key == '_parent') { + continue; + } + + if (is_object($val) || (is_array($val))) { + if ($key == '_cellCollection') { + $newCollection = clone $this->_cellCollection; + $newCollection->copyCellCollection($this); + $this->_cellCollection = $newCollection; + } elseif ($key == '_drawingCollection') { + $newCollection = clone $this->_drawingCollection; + $this->_drawingCollection = $newCollection; + } elseif (($key == '_autoFilter') && ($this->_autoFilter instanceof PHPExcel_Worksheet_AutoFilter)) { + $newAutoFilter = clone $this->_autoFilter; + $this->_autoFilter = $newAutoFilter; + $this->_autoFilter->setParent($this); + } else { + $this->{$key} = unserialize(serialize($val)); + } + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter.php new file mode 100755 index 0000000..5d253fb --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter.php @@ -0,0 +1,858 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_AutoFilter + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_AutoFilter +{ + /** + * Autofilter Worksheet + * + * @var PHPExcel_Worksheet + */ + private $_workSheet = NULL; + + + /** + * Autofilter Range + * + * @var string + */ + private $_range = ''; + + + /** + * Autofilter Column Ruleset + * + * @var array of PHPExcel_Worksheet_AutoFilter_Column + */ + private $_columns = array(); + + + /** + * Create a new PHPExcel_Worksheet_AutoFilter + * + * @param string $pRange Cell range (i.e. A1:E10) + * @param PHPExcel_Worksheet $pSheet + */ + public function __construct($pRange = '', PHPExcel_Worksheet $pSheet = NULL) + { + $this->_range = $pRange; + $this->_workSheet = $pSheet; + } + + /** + * Get AutoFilter Parent Worksheet + * + * @return PHPExcel_Worksheet + */ + public function getParent() { + return $this->_workSheet; + } + + /** + * Set AutoFilter Parent Worksheet + * + * @param PHPExcel_Worksheet $pSheet + * @return PHPExcel_Worksheet_AutoFilter + */ + public function setParent(PHPExcel_Worksheet $pSheet = NULL) { + $this->_workSheet = $pSheet; + + return $this; + } + + /** + * Get AutoFilter Range + * + * @return string + */ + public function getRange() { + return $this->_range; + } + + /** + * Set AutoFilter Range + * + * @param string $pRange Cell range (i.e. A1:E10) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter + */ + public function setRange($pRange = '') { + // Uppercase coordinate + $cellAddress = explode('!',strtoupper($pRange)); + if (count($cellAddress) > 1) { + list($worksheet,$pRange) = $cellAddress; + } + + if (strpos($pRange,':') !== FALSE) { + $this->_range = $pRange; + } elseif(empty($pRange)) { + $this->_range = ''; + } else { + throw new PHPExcel_Exception('Autofilter must be set on a range of cells.'); + } + + if (empty($pRange)) { + // Discard all column rules + $this->_columns = array(); + } else { + // Discard any column rules that are no longer valid within this range + list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->_range); + foreach($this->_columns as $key => $value) { + $colIndex = PHPExcel_Cell::columnIndexFromString($key); + if (($rangeStart[0] > $colIndex) || ($rangeEnd[0] < $colIndex)) { + unset($this->_columns[$key]); + } + } + } + + return $this; + } + + /** + * Get all AutoFilter Columns + * + * @throws PHPExcel_Exception + * @return array of PHPExcel_Worksheet_AutoFilter_Column + */ + public function getColumns() { + return $this->_columns; + } + + /** + * Validate that the specified column is in the AutoFilter range + * + * @param string $column Column name (e.g. A) + * @throws PHPExcel_Exception + * @return integer The column offset within the autofilter range + */ + public function testColumnInRange($column) { + if (empty($this->_range)) { + throw new PHPExcel_Exception("No autofilter range is defined."); + } + + $columnIndex = PHPExcel_Cell::columnIndexFromString($column); + list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->_range); + if (($rangeStart[0] > $columnIndex) || ($rangeEnd[0] < $columnIndex)) { + throw new PHPExcel_Exception("Column is outside of current autofilter range."); + } + + return $columnIndex - $rangeStart[0]; + } + + /** + * Get a specified AutoFilter Column Offset within the defined AutoFilter range + * + * @param string $pColumn Column name (e.g. A) + * @throws PHPExcel_Exception + * @return integer The offset of the specified column within the autofilter range + */ + public function getColumnOffset($pColumn) { + return $this->testColumnInRange($pColumn); + } + + /** + * Get a specified AutoFilter Column + * + * @param string $pColumn Column name (e.g. A) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function getColumn($pColumn) { + $this->testColumnInRange($pColumn); + + if (!isset($this->_columns[$pColumn])) { + $this->_columns[$pColumn] = new PHPExcel_Worksheet_AutoFilter_Column($pColumn, $this); + } + + return $this->_columns[$pColumn]; + } + + /** + * Get a specified AutoFilter Column by it's offset + * + * @param integer $pColumnOffset Column offset within range (starting from 0) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function getColumnByOffset($pColumnOffset = 0) { + list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->_range); + $pColumn = PHPExcel_Cell::stringFromColumnIndex($rangeStart[0] + $pColumnOffset - 1); + + return $this->getColumn($pColumn); + } + + /** + * Set AutoFilter + * + * @param PHPExcel_Worksheet_AutoFilter_Column|string $pColumn + * A simple string containing a Column ID like 'A' is permitted + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter + */ + public function setColumn($pColumn) + { + if ((is_string($pColumn)) && (!empty($pColumn))) { + $column = $pColumn; + } elseif(is_object($pColumn) && ($pColumn instanceof PHPExcel_Worksheet_AutoFilter_Column)) { + $column = $pColumn->getColumnIndex(); + } else { + throw new PHPExcel_Exception("Column is not within the autofilter range."); + } + $this->testColumnInRange($column); + + if (is_string($pColumn)) { + $this->_columns[$pColumn] = new PHPExcel_Worksheet_AutoFilter_Column($pColumn, $this); + } elseif(is_object($pColumn) && ($pColumn instanceof PHPExcel_Worksheet_AutoFilter_Column)) { + $pColumn->setParent($this); + $this->_columns[$column] = $pColumn; + } + ksort($this->_columns); + + return $this; + } + + /** + * Clear a specified AutoFilter Column + * + * @param string $pColumn Column name (e.g. A) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter + */ + public function clearColumn($pColumn) { + $this->testColumnInRange($pColumn); + + if (isset($this->_columns[$pColumn])) { + unset($this->_columns[$pColumn]); + } + + return $this; + } + + /** + * Shift an AutoFilter Column Rule to a different column + * + * Note: This method bypasses validation of the destination column to ensure it is within this AutoFilter range. + * Nor does it verify whether any column rule already exists at $toColumn, but will simply overrideany existing value. + * Use with caution. + * + * @param string $fromColumn Column name (e.g. A) + * @param string $toColumn Column name (e.g. B) + * @return PHPExcel_Worksheet_AutoFilter + */ + public function shiftColumn($fromColumn=NULL,$toColumn=NULL) { + $fromColumn = strtoupper($fromColumn); + $toColumn = strtoupper($toColumn); + + if (($fromColumn !== NULL) && (isset($this->_columns[$fromColumn])) && ($toColumn !== NULL)) { + $this->_columns[$fromColumn]->setParent(); + $this->_columns[$fromColumn]->setColumnIndex($toColumn); + $this->_columns[$toColumn] = $this->_columns[$fromColumn]; + $this->_columns[$toColumn]->setParent($this); + unset($this->_columns[$fromColumn]); + + ksort($this->_columns); + } + + return $this; + } + + + /** + * Test if cell value is in the defined set of values + * + * @param mixed $cellValue + * @param mixed[] $dataSet + * @return boolean + */ + private static function _filterTestInSimpleDataSet($cellValue,$dataSet) + { + $dataSetValues = $dataSet['filterValues']; + $blanks = $dataSet['blanks']; + if (($cellValue == '') || ($cellValue === NULL)) { + return $blanks; + } + return in_array($cellValue,$dataSetValues); + } + + /** + * Test if cell value is in the defined set of Excel date values + * + * @param mixed $cellValue + * @param mixed[] $dataSet + * @return boolean + */ + private static function _filterTestInDateGroupSet($cellValue,$dataSet) + { + $dateSet = $dataSet['filterValues']; + $blanks = $dataSet['blanks']; + if (($cellValue == '') || ($cellValue === NULL)) { + return $blanks; + } + + if (is_numeric($cellValue)) { + $dateValue = PHPExcel_Shared_Date::ExcelToPHP($cellValue); + if ($cellValue < 1) { + // Just the time part + $dtVal = date('His',$dateValue); + $dateSet = $dateSet['time']; + } elseif($cellValue == floor($cellValue)) { + // Just the date part + $dtVal = date('Ymd',$dateValue); + $dateSet = $dateSet['date']; + } else { + // date and time parts + $dtVal = date('YmdHis',$dateValue); + $dateSet = $dateSet['dateTime']; + } + foreach($dateSet as $dateValue) { + // Use of substr to extract value at the appropriate group level + if (substr($dtVal,0,strlen($dateValue)) == $dateValue) + return TRUE; + } + } + + return FALSE; + } + + /** + * Test if cell value is within a set of values defined by a ruleset + * + * @param mixed $cellValue + * @param mixed[] $ruleSet + * @return boolean + */ + private static function _filterTestInCustomDataSet($cellValue, $ruleSet) + { + $dataSet = $ruleSet['filterRules']; + $join = $ruleSet['join']; + $customRuleForBlanks = isset($ruleSet['customRuleForBlanks']) ? $ruleSet['customRuleForBlanks'] : FALSE; + + if (!$customRuleForBlanks) { + // Blank cells are always ignored, so return a FALSE + if (($cellValue == '') || ($cellValue === NULL)) { + return FALSE; + } + } + $returnVal = ($join == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND); + foreach($dataSet as $rule) { + if (is_numeric($rule['value'])) { + // Numeric values are tested using the appropriate operator + switch ($rule['operator']) { + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL : + $retVal = ($cellValue == $rule['value']); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL : + $retVal = ($cellValue != $rule['value']); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN : + $retVal = ($cellValue > $rule['value']); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL : + $retVal = ($cellValue >= $rule['value']); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN : + $retVal = ($cellValue < $rule['value']); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL : + $retVal = ($cellValue <= $rule['value']); + break; + } + } elseif($rule['value'] == '') { + switch ($rule['operator']) { + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL : + $retVal = (($cellValue == '') || ($cellValue === NULL)); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_NOTEQUAL : + $retVal = (($cellValue != '') && ($cellValue !== NULL)); + break; + default : + $retVal = TRUE; + break; + } + } else { + // String values are always tested for equality, factoring in for wildcards (hence a regexp test) + $retVal = preg_match('/^'.$rule['value'].'$/i',$cellValue); + } + // If there are multiple conditions, then we need to test both using the appropriate join operator + switch ($join) { + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR : + $returnVal = $returnVal || $retVal; + // Break as soon as we have a TRUE match for OR joins, + // to avoid unnecessary additional code execution + if ($returnVal) + return $returnVal; + break; + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND : + $returnVal = $returnVal && $retVal; + break; + } + } + + return $returnVal; + } + + /** + * Test if cell date value is matches a set of values defined by a set of months + * + * @param mixed $cellValue + * @param mixed[] $monthSet + * @return boolean + */ + private static function _filterTestInPeriodDateSet($cellValue, $monthSet) + { + // Blank cells are always ignored, so return a FALSE + if (($cellValue == '') || ($cellValue === NULL)) { + return FALSE; + } + + if (is_numeric($cellValue)) { + $dateValue = date('m',PHPExcel_Shared_Date::ExcelToPHP($cellValue)); + if (in_array($dateValue,$monthSet)) { + return TRUE; + } + } + + return FALSE; + } + + /** + * Search/Replace arrays to convert Excel wildcard syntax to a regexp syntax for preg_matching + * + * @var array + */ + private static $_fromReplace = array('\*', '\?', '~~', '~.*', '~.?'); + private static $_toReplace = array('.*', '.', '~', '\*', '\?'); + + + /** + * Convert a dynamic rule daterange to a custom filter range expression for ease of calculation + * + * @param string $dynamicRuleType + * @param PHPExcel_Worksheet_AutoFilter_Column &$filterColumn + * @return mixed[] + */ + private function _dynamicFilterDateRange($dynamicRuleType, &$filterColumn) + { + $rDateType = PHPExcel_Calculation_Functions::getReturnDateType(); + PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_PHP_NUMERIC); + $val = $maxVal = NULL; + + $ruleValues = array(); + $baseDate = PHPExcel_Calculation_DateTime::DATENOW(); + // Calculate start/end dates for the required date range based on current date + switch ($dynamicRuleType) { + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK : + $baseDate = strtotime('-7 days',$baseDate); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK : + $baseDate = strtotime('-7 days',$baseDate); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH : + $baseDate = strtotime('-1 month',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate))); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH : + $baseDate = strtotime('+1 month',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate))); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER : + $baseDate = strtotime('-3 month',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate))); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER : + $baseDate = strtotime('+3 month',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate))); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR : + $baseDate = strtotime('-1 year',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate))); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR : + $baseDate = strtotime('+1 year',gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate))); + break; + } + + switch ($dynamicRuleType) { + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TODAY : + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY : + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW : + $maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(strtotime('+1 day',$baseDate)); + $val = (int) PHPExcel_Shared_Date::PHPToExcel($baseDate); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE : + $maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(strtotime('+1 day',$baseDate)); + $val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0,0,0,1,1,date('Y',$baseDate))); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR : + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR : + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR : + $maxVal = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0,0,0,31,12,date('Y',$baseDate))); + ++$maxVal; + $val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0,0,0,1,1,date('Y',$baseDate))); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER : + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER : + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER : + $thisMonth = date('m',$baseDate); + $thisQuarter = floor(--$thisMonth / 3); + $maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(gmmktime(0,0,0,date('t',$baseDate),(1+$thisQuarter)*3,date('Y',$baseDate))); + ++$maxVal; + $val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0,0,0,1,1+$thisQuarter*3,date('Y',$baseDate))); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH : + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH : + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH : + $maxVal = (int) PHPExcel_Shared_Date::PHPtoExcel(gmmktime(0,0,0,date('t',$baseDate),date('m',$baseDate),date('Y',$baseDate))); + ++$maxVal; + $val = (int) PHPExcel_Shared_Date::PHPToExcel(gmmktime(0,0,0,1,date('m',$baseDate),date('Y',$baseDate))); + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK : + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK : + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK : + $dayOfWeek = date('w',$baseDate); + $val = (int) PHPExcel_Shared_Date::PHPToExcel($baseDate) - $dayOfWeek; + $maxVal = $val + 7; + break; + } + + switch ($dynamicRuleType) { + // Adjust Today dates for Yesterday and Tomorrow + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY : + --$maxVal; + --$val; + break; + case PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW : + ++$maxVal; + ++$val; + break; + } + + // Set the filter column rule attributes ready for writing + $filterColumn->setAttributes(array( 'val' => $val, + 'maxVal' => $maxVal + ) + ); + + // Set the rules for identifying rows for hide/show + $ruleValues[] = array( 'operator' => PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL, + 'value' => $val + ); + $ruleValues[] = array( 'operator' => PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN, + 'value' => $maxVal + ); + PHPExcel_Calculation_Functions::setReturnDateType($rDateType); + + return array( + 'method' => '_filterTestInCustomDataSet', + 'arguments' => array( 'filterRules' => $ruleValues, + 'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND + ) + ); + } + + private function _calculateTopTenValue($columnID,$startRow,$endRow,$ruleType,$ruleValue) { + $range = $columnID.$startRow.':'.$columnID.$endRow; + $dataValues = PHPExcel_Calculation_Functions::flattenArray( + $this->_workSheet->rangeToArray($range,NULL,TRUE,FALSE) + ); + + $dataValues = array_filter($dataValues); + if ($ruleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) { + rsort($dataValues); + } else { + sort($dataValues); + } + + return array_pop(array_slice($dataValues,0,$ruleValue)); + } + + /** + * Apply the AutoFilter rules to the AutoFilter Range + * + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter + */ + public function showHideRows() + { + list($rangeStart,$rangeEnd) = PHPExcel_Cell::rangeBoundaries($this->_range); + + // The heading row should always be visible +// echo 'AutoFilter Heading Row ',$rangeStart[1],' is always SHOWN',PHP_EOL; + $this->_workSheet->getRowDimension($rangeStart[1])->setVisible(TRUE); + + $columnFilterTests = array(); + foreach($this->_columns as $columnID => $filterColumn) { + $rules = $filterColumn->getRules(); + switch ($filterColumn->getFilterType()) { + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER : + $ruleValues = array(); + // Build a list of the filter value selections + foreach($rules as $rule) { + $ruleType = $rule->getRuleType(); + $ruleValues[] = $rule->getValue(); + } + // Test if we want to include blanks in our filter criteria + $blanks = FALSE; + $ruleDataSet = array_filter($ruleValues); + if (count($ruleValues) != count($ruleDataSet)) + $blanks = TRUE; + if ($ruleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_FILTER) { + // Filter on absolute values + $columnFilterTests[$columnID] = array( + 'method' => '_filterTestInSimpleDataSet', + 'arguments' => array( 'filterValues' => $ruleDataSet, + 'blanks' => $blanks + ) + ); + } else { + // Filter on date group values + $arguments = array(); + foreach($ruleDataSet as $ruleValue) { + $date = $time = ''; + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR] !== '')) + $date .= sprintf('%04d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_YEAR]); + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH] != '')) + $date .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MONTH]); + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY] !== '')) + $date .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_DAY]); + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR] !== '')) + $time .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_HOUR]); + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE] !== '')) + $time .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE]); + if ((isset($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND])) && + ($ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND] !== '')) + $time .= sprintf('%02d',$ruleValue[PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP_SECOND]); + $dateTime = $date . $time; + $arguments['date'][] = $date; + $arguments['time'][] = $time; + $arguments['dateTime'][] = $dateTime; + } + // Remove empty elements + $arguments['date'] = array_filter($arguments['date']); + $arguments['time'] = array_filter($arguments['time']); + $arguments['dateTime'] = array_filter($arguments['dateTime']); + $columnFilterTests[$columnID] = array( + 'method' => '_filterTestInDateGroupSet', + 'arguments' => array( 'filterValues' => $arguments, + 'blanks' => $blanks + ) + ); + } + break; + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_CUSTOMFILTER : + $customRuleForBlanks = FALSE; + $ruleValues = array(); + // Build a list of the filter value selections + foreach($rules as $rule) { + $ruleType = $rule->getRuleType(); + $ruleValue = $rule->getValue(); + if (!is_numeric($ruleValue)) { + // Convert to a regexp allowing for regexp reserved characters, wildcards and escaped wildcards + $ruleValue = preg_quote($ruleValue); + $ruleValue = str_replace(self::$_fromReplace,self::$_toReplace,$ruleValue); + if (trim($ruleValue) == '') { + $customRuleForBlanks = TRUE; + $ruleValue = trim($ruleValue); + } + } + $ruleValues[] = array( 'operator' => $rule->getOperator(), + 'value' => $ruleValue + ); + } + $join = $filterColumn->getJoin(); + $columnFilterTests[$columnID] = array( + 'method' => '_filterTestInCustomDataSet', + 'arguments' => array( 'filterRules' => $ruleValues, + 'join' => $join, + 'customRuleForBlanks' => $customRuleForBlanks + ) + ); + break; + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_DYNAMICFILTER : + $ruleValues = array(); + foreach($rules as $rule) { + // We should only ever have one Dynamic Filter Rule anyway + $dynamicRuleType = $rule->getGrouping(); + if (($dynamicRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE) || + ($dynamicRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE)) { + // Number (Average) based + // Calculate the average + $averageFormula = '=AVERAGE('.$columnID.($rangeStart[1]+1).':'.$columnID.$rangeEnd[1].')'; + $average = PHPExcel_Calculation::getInstance()->calculateFormula($averageFormula,NULL,$this->_workSheet->getCell('A1')); + // Set above/below rule based on greaterThan or LessTan + $operator = ($dynamicRuleType === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE) + ? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHAN + : PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHAN; + $ruleValues[] = array( 'operator' => $operator, + 'value' => $average + ); + $columnFilterTests[$columnID] = array( + 'method' => '_filterTestInCustomDataSet', + 'arguments' => array( 'filterRules' => $ruleValues, + 'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR + ) + ); + } else { + // Date based + if ($dynamicRuleType{0} == 'M' || $dynamicRuleType{0} == 'Q') { + // Month or Quarter + sscanf($dynamicRuleType,'%[A-Z]%d', $periodType, $period); + if ($periodType == 'M') { + $ruleValues = array($period); + } else { + --$period; + $periodEnd = (1+$period)*3; + $periodStart = 1+$period*3; + $ruleValues = range($periodStart,periodEnd); + } + $columnFilterTests[$columnID] = array( + 'method' => '_filterTestInPeriodDateSet', + 'arguments' => $ruleValues + ); + $filterColumn->setAttributes(array()); + } else { + // Date Range + $columnFilterTests[$columnID] = $this->_dynamicFilterDateRange($dynamicRuleType, $filterColumn); + break; + } + } + } + break; + case PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_TOPTENFILTER : + $ruleValues = array(); + $dataRowCount = $rangeEnd[1] - $rangeStart[1]; + foreach($rules as $rule) { + // We should only ever have one Dynamic Filter Rule anyway + $toptenRuleType = $rule->getGrouping(); + $ruleValue = $rule->getValue(); + $ruleOperator = $rule->getOperator(); + } + if ($ruleOperator === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) { + $ruleValue = floor($ruleValue * ($dataRowCount / 100)); + } + if ($ruleValue < 1) $ruleValue = 1; + if ($ruleValue > 500) $ruleValue = 500; + + $maxVal = $this->_calculateTopTenValue($columnID,$rangeStart[1]+1,$rangeEnd[1],$toptenRuleType,$ruleValue); + + $operator = ($toptenRuleType == PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) + ? PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL + : PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL; + $ruleValues[] = array( 'operator' => $operator, + 'value' => $maxVal + ); + $columnFilterTests[$columnID] = array( + 'method' => '_filterTestInCustomDataSet', + 'arguments' => array( 'filterRules' => $ruleValues, + 'join' => PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_OR + ) + ); + $filterColumn->setAttributes( + array('maxVal' => $maxVal) + ); + break; + } + } + +// echo 'Column Filter Test CRITERIA',PHP_EOL; +// var_dump($columnFilterTests); +// + // Execute the column tests for each row in the autoFilter range to determine show/hide, + for ($row = $rangeStart[1]+1; $row <= $rangeEnd[1]; ++$row) { +// echo 'Testing Row = ',$row,PHP_EOL; + $result = TRUE; + foreach($columnFilterTests as $columnID => $columnFilterTest) { +// echo 'Testing cell ',$columnID.$row,PHP_EOL; + $cellValue = $this->_workSheet->getCell($columnID.$row)->getCalculatedValue(); +// echo 'Value is ',$cellValue,PHP_EOL; + // Execute the filter test + $result = $result && + call_user_func_array( + array('PHPExcel_Worksheet_AutoFilter',$columnFilterTest['method']), + array( + $cellValue, + $columnFilterTest['arguments'] + ) + ); +// echo (($result) ? 'VALID' : 'INVALID'),PHP_EOL; + // If filter test has resulted in FALSE, exit the loop straightaway rather than running any more tests + if (!$result) + break; + } + // Set show/hide for the row based on the result of the autoFilter result +// echo (($result) ? 'SHOW' : 'HIDE'),PHP_EOL; + $this->_workSheet->getRowDimension($row)->setVisible($result); + } + + return $this; + } + + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + if ($key == '_workSheet') { + // Detach from worksheet + $this->{$key} = NULL; + } else { + $this->{$key} = clone $value; + } + } elseif ((is_array($value)) && ($key == '_columns')) { + // The columns array of PHPExcel_Worksheet_AutoFilter objects + $this->{$key} = array(); + foreach ($value as $k => $v) { + $this->{$key}[$k] = clone $v; + // attach the new cloned Column to this new cloned Autofilter object + $this->{$key}[$k]->setParent($this); + } + } else { + $this->{$key} = $value; + } + } + } + + /** + * toString method replicates previous behavior by returning the range if object is + * referenced as a property of its parent. + */ + public function __toString() { + return (string) $this->_range; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter/Column.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter/Column.php new file mode 100755 index 0000000..393388b --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter/Column.php @@ -0,0 +1,394 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_AutoFilter_Column + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_AutoFilter_Column +{ + const AUTOFILTER_FILTERTYPE_FILTER = 'filters'; + const AUTOFILTER_FILTERTYPE_CUSTOMFILTER = 'customFilters'; + // Supports no more than 2 rules, with an And/Or join criteria + // if more than 1 rule is defined + const AUTOFILTER_FILTERTYPE_DYNAMICFILTER = 'dynamicFilter'; + // Even though the filter rule is constant, the filtered data can vary + // e.g. filtered by date = TODAY + const AUTOFILTER_FILTERTYPE_TOPTENFILTER = 'top10'; + + /** + * Types of autofilter rules + * + * @var string[] + */ + private static $_filterTypes = array( + // Currently we're not handling + // colorFilter + // extLst + // iconFilter + self::AUTOFILTER_FILTERTYPE_FILTER, + self::AUTOFILTER_FILTERTYPE_CUSTOMFILTER, + self::AUTOFILTER_FILTERTYPE_DYNAMICFILTER, + self::AUTOFILTER_FILTERTYPE_TOPTENFILTER, + ); + + /* Multiple Rule Connections */ + const AUTOFILTER_COLUMN_JOIN_AND = 'and'; + const AUTOFILTER_COLUMN_JOIN_OR = 'or'; + + /** + * Join options for autofilter rules + * + * @var string[] + */ + private static $_ruleJoins = array( + self::AUTOFILTER_COLUMN_JOIN_AND, + self::AUTOFILTER_COLUMN_JOIN_OR, + ); + + /** + * Autofilter + * + * @var PHPExcel_Worksheet_AutoFilter + */ + private $_parent = NULL; + + + /** + * Autofilter Column Index + * + * @var string + */ + private $_columnIndex = ''; + + + /** + * Autofilter Column Filter Type + * + * @var string + */ + private $_filterType = self::AUTOFILTER_FILTERTYPE_FILTER; + + + /** + * Autofilter Multiple Rules And/Or + * + * @var string + */ + private $_join = self::AUTOFILTER_COLUMN_JOIN_OR; + + + /** + * Autofilter Column Rules + * + * @var array of PHPExcel_Worksheet_AutoFilter_Column_Rule + */ + private $_ruleset = array(); + + + /** + * Autofilter Column Dynamic Attributes + * + * @var array of mixed + */ + private $_attributes = array(); + + + /** + * Create a new PHPExcel_Worksheet_AutoFilter_Column + * + * @param string $pColumn Column (e.g. A) + * @param PHPExcel_Worksheet_AutoFilter $pParent Autofilter for this column + */ + public function __construct($pColumn, PHPExcel_Worksheet_AutoFilter $pParent = NULL) + { + $this->_columnIndex = $pColumn; + $this->_parent = $pParent; + } + + /** + * Get AutoFilter Column Index + * + * @return string + */ + public function getColumnIndex() { + return $this->_columnIndex; + } + + /** + * Set AutoFilter Column Index + * + * @param string $pColumn Column (e.g. A) + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function setColumnIndex($pColumn) { + // Uppercase coordinate + $pColumn = strtoupper($pColumn); + if ($this->_parent !== NULL) { + $this->_parent->testColumnInRange($pColumn); + } + + $this->_columnIndex = $pColumn; + + return $this; + } + + /** + * Get this Column's AutoFilter Parent + * + * @return PHPExcel_Worksheet_AutoFilter + */ + public function getParent() { + return $this->_parent; + } + + /** + * Set this Column's AutoFilter Parent + * + * @param PHPExcel_Worksheet_AutoFilter + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function setParent(PHPExcel_Worksheet_AutoFilter $pParent = NULL) { + $this->_parent = $pParent; + + return $this; + } + + /** + * Get AutoFilter Type + * + * @return string + */ + public function getFilterType() { + return $this->_filterType; + } + + /** + * Set AutoFilter Type + * + * @param string $pFilterType + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function setFilterType($pFilterType = self::AUTOFILTER_FILTERTYPE_FILTER) { + if (!in_array($pFilterType,self::$_filterTypes)) { + throw new PHPExcel_Exception('Invalid filter type for column AutoFilter.'); + } + + $this->_filterType = $pFilterType; + + return $this; + } + + /** + * Get AutoFilter Multiple Rules And/Or Join + * + * @return string + */ + public function getJoin() { + return $this->_join; + } + + /** + * Set AutoFilter Multiple Rules And/Or + * + * @param string $pJoin And/Or + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function setJoin($pJoin = self::AUTOFILTER_COLUMN_JOIN_OR) { + // Lowercase And/Or + $pJoin = strtolower($pJoin); + if (!in_array($pJoin,self::$_ruleJoins)) { + throw new PHPExcel_Exception('Invalid rule connection for column AutoFilter.'); + } + + $this->_join = $pJoin; + + return $this; + } + + /** + * Set AutoFilter Attributes + * + * @param string[] $pAttributes + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function setAttributes($pAttributes = array()) { + $this->_attributes = $pAttributes; + + return $this; + } + + /** + * Set An AutoFilter Attribute + * + * @param string $pName Attribute Name + * @param string $pValue Attribute Value + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function setAttribute($pName, $pValue) { + $this->_attributes[$pName] = $pValue; + + return $this; + } + + /** + * Get AutoFilter Column Attributes + * + * @return string + */ + public function getAttributes() { + return $this->_attributes; + } + + /** + * Get specific AutoFilter Column Attribute + * + * @param string $pName Attribute Name + * @return string + */ + public function getAttribute($pName) { + if (isset($this->_attributes[$pName])) + return $this->_attributes[$pName]; + return NULL; + } + + /** + * Get all AutoFilter Column Rules + * + * @throws PHPExcel_Exception + * @return array of PHPExcel_Worksheet_AutoFilter_Column_Rule + */ + public function getRules() { + return $this->_ruleset; + } + + /** + * Get a specified AutoFilter Column Rule + * + * @param integer $pIndex Rule index in the ruleset array + * @return PHPExcel_Worksheet_AutoFilter_Column_Rule + */ + public function getRule($pIndex) { + if (!isset($this->_ruleset[$pIndex])) { + $this->_ruleset[$pIndex] = new PHPExcel_Worksheet_AutoFilter_Column_Rule($this); + } + return $this->_ruleset[$pIndex]; + } + + /** + * Create a new AutoFilter Column Rule in the ruleset + * + * @return PHPExcel_Worksheet_AutoFilter_Column_Rule + */ + public function createRule() { + $this->_ruleset[] = new PHPExcel_Worksheet_AutoFilter_Column_Rule($this); + + return end($this->_ruleset); + } + + /** + * Add a new AutoFilter Column Rule to the ruleset + * + * @param PHPExcel_Worksheet_AutoFilter_Column_Rule $pRule + * @param boolean $returnRule Flag indicating whether the rule object or the column object should be returned + * @return PHPExcel_Worksheet_AutoFilter_Column|PHPExcel_Worksheet_AutoFilter_Column_Rule + */ + public function addRule(PHPExcel_Worksheet_AutoFilter_Column_Rule $pRule, $returnRule=TRUE) { + $pRule->setParent($this); + $this->_ruleset[] = $pRule; + + return ($returnRule) ? $pRule : $this; + } + + /** + * Delete a specified AutoFilter Column Rule + * If the number of rules is reduced to 1, then we reset And/Or logic to Or + * + * @param integer $pIndex Rule index in the ruleset array + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function deleteRule($pIndex) { + if (isset($this->_ruleset[$pIndex])) { + unset($this->_ruleset[$pIndex]); + // If we've just deleted down to a single rule, then reset And/Or joining to Or + if (count($this->_ruleset) <= 1) { + $this->setJoin(self::AUTOFILTER_COLUMN_JOIN_OR); + } + } + + return $this; + } + + /** + * Delete all AutoFilter Column Rules + * + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function clearRules() { + $this->_ruleset = array(); + $this->setJoin(self::AUTOFILTER_COLUMN_JOIN_OR); + + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + if ($key == '_parent') { + // Detach from autofilter parent + $this->$key = NULL; + } else { + $this->$key = clone $value; + } + } elseif ((is_array($value)) && ($key == '_ruleset')) { + // The columns array of PHPExcel_Worksheet_AutoFilter objects + $this->$key = array(); + foreach ($value as $k => $v) { + $this->$key[$k] = clone $v; + // attach the new cloned Rule to this new cloned Autofilter Cloned object + $this->$key[$k]->setParent($this); + } + } else { + $this->$key = $value; + } + } + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter/Column/Rule.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter/Column/Rule.php new file mode 100755 index 0000000..b9d0674 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/AutoFilter/Column/Rule.php @@ -0,0 +1,464 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_AutoFilter_Column_Rule + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_AutoFilter_Column_Rule +{ + const AUTOFILTER_RULETYPE_FILTER = 'filter'; + const AUTOFILTER_RULETYPE_DATEGROUP = 'dateGroupItem'; + const AUTOFILTER_RULETYPE_CUSTOMFILTER = 'customFilter'; + const AUTOFILTER_RULETYPE_DYNAMICFILTER = 'dynamicFilter'; + const AUTOFILTER_RULETYPE_TOPTENFILTER = 'top10Filter'; + + private static $_ruleTypes = array( + // Currently we're not handling + // colorFilter + // extLst + // iconFilter + self::AUTOFILTER_RULETYPE_FILTER, + self::AUTOFILTER_RULETYPE_DATEGROUP, + self::AUTOFILTER_RULETYPE_CUSTOMFILTER, + self::AUTOFILTER_RULETYPE_DYNAMICFILTER, + self::AUTOFILTER_RULETYPE_TOPTENFILTER, + ); + + const AUTOFILTER_RULETYPE_DATEGROUP_YEAR = 'year'; + const AUTOFILTER_RULETYPE_DATEGROUP_MONTH = 'month'; + const AUTOFILTER_RULETYPE_DATEGROUP_DAY = 'day'; + const AUTOFILTER_RULETYPE_DATEGROUP_HOUR = 'hour'; + const AUTOFILTER_RULETYPE_DATEGROUP_MINUTE = 'minute'; + const AUTOFILTER_RULETYPE_DATEGROUP_SECOND = 'second'; + + private static $_dateTimeGroups = array( + self::AUTOFILTER_RULETYPE_DATEGROUP_YEAR, + self::AUTOFILTER_RULETYPE_DATEGROUP_MONTH, + self::AUTOFILTER_RULETYPE_DATEGROUP_DAY, + self::AUTOFILTER_RULETYPE_DATEGROUP_HOUR, + self::AUTOFILTER_RULETYPE_DATEGROUP_MINUTE, + self::AUTOFILTER_RULETYPE_DATEGROUP_SECOND, + ); + + const AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY = 'yesterday'; + const AUTOFILTER_RULETYPE_DYNAMIC_TODAY = 'today'; + const AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW = 'tomorrow'; + const AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE = 'yearToDate'; + const AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR = 'thisYear'; + const AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER = 'thisQuarter'; + const AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH = 'thisMonth'; + const AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK = 'thisWeek'; + const AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR = 'lastYear'; + const AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER = 'lastQuarter'; + const AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH = 'lastMonth'; + const AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK = 'lastWeek'; + const AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR = 'nextYear'; + const AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER = 'nextQuarter'; + const AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH = 'nextMonth'; + const AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK = 'nextWeek'; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_1 = 'M1'; + const AUTOFILTER_RULETYPE_DYNAMIC_JANUARY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_1; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2 = 'M2'; + const AUTOFILTER_RULETYPE_DYNAMIC_FEBRUARY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_3 = 'M3'; + const AUTOFILTER_RULETYPE_DYNAMIC_MARCH = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_3; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_4 = 'M4'; + const AUTOFILTER_RULETYPE_DYNAMIC_APRIL = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_4; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_5 = 'M5'; + const AUTOFILTER_RULETYPE_DYNAMIC_MAY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_5; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_6 = 'M6'; + const AUTOFILTER_RULETYPE_DYNAMIC_JUNE = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_6; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_7 = 'M7'; + const AUTOFILTER_RULETYPE_DYNAMIC_JULY = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_7; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_8 = 'M8'; + const AUTOFILTER_RULETYPE_DYNAMIC_AUGUST = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_8; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_9 = 'M9'; + const AUTOFILTER_RULETYPE_DYNAMIC_SEPTEMBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_9; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_10 = 'M10'; + const AUTOFILTER_RULETYPE_DYNAMIC_OCTOBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_10; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_11 = 'M11'; + const AUTOFILTER_RULETYPE_DYNAMIC_NOVEMBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_11; + const AUTOFILTER_RULETYPE_DYNAMIC_MONTH_12 = 'M12'; + const AUTOFILTER_RULETYPE_DYNAMIC_DECEMBER = self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_12; + const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_1 = 'Q1'; + const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_2 = 'Q2'; + const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_3 = 'Q3'; + const AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_4 = 'Q4'; + const AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE = 'aboveAverage'; + const AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE = 'belowAverage'; + + private static $_dynamicTypes = array( + self::AUTOFILTER_RULETYPE_DYNAMIC_YESTERDAY, + self::AUTOFILTER_RULETYPE_DYNAMIC_TODAY, + self::AUTOFILTER_RULETYPE_DYNAMIC_TOMORROW, + self::AUTOFILTER_RULETYPE_DYNAMIC_YEARTODATE, + self::AUTOFILTER_RULETYPE_DYNAMIC_THISYEAR, + self::AUTOFILTER_RULETYPE_DYNAMIC_THISQUARTER, + self::AUTOFILTER_RULETYPE_DYNAMIC_THISMONTH, + self::AUTOFILTER_RULETYPE_DYNAMIC_THISWEEK, + self::AUTOFILTER_RULETYPE_DYNAMIC_LASTYEAR, + self::AUTOFILTER_RULETYPE_DYNAMIC_LASTQUARTER, + self::AUTOFILTER_RULETYPE_DYNAMIC_LASTMONTH, + self::AUTOFILTER_RULETYPE_DYNAMIC_LASTWEEK, + self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTYEAR, + self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTQUARTER, + self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTMONTH, + self::AUTOFILTER_RULETYPE_DYNAMIC_NEXTWEEK, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_1, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_2, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_3, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_4, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_5, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_6, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_7, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_8, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_9, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_10, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_11, + self::AUTOFILTER_RULETYPE_DYNAMIC_MONTH_12, + self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_1, + self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_2, + self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_3, + self::AUTOFILTER_RULETYPE_DYNAMIC_QUARTER_4, + self::AUTOFILTER_RULETYPE_DYNAMIC_ABOVEAVERAGE, + self::AUTOFILTER_RULETYPE_DYNAMIC_BELOWAVERAGE, + ); + + /* + * The only valid filter rule operators for filter and customFilter types are: + * <xsd:enumeration value="equal"/> + * <xsd:enumeration value="lessThan"/> + * <xsd:enumeration value="lessThanOrEqual"/> + * <xsd:enumeration value="notEqual"/> + * <xsd:enumeration value="greaterThanOrEqual"/> + * <xsd:enumeration value="greaterThan"/> + */ + const AUTOFILTER_COLUMN_RULE_EQUAL = 'equal'; + const AUTOFILTER_COLUMN_RULE_NOTEQUAL = 'notEqual'; + const AUTOFILTER_COLUMN_RULE_GREATERTHAN = 'greaterThan'; + const AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL = 'greaterThanOrEqual'; + const AUTOFILTER_COLUMN_RULE_LESSTHAN = 'lessThan'; + const AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL = 'lessThanOrEqual'; + + private static $_operators = array( + self::AUTOFILTER_COLUMN_RULE_EQUAL, + self::AUTOFILTER_COLUMN_RULE_NOTEQUAL, + self::AUTOFILTER_COLUMN_RULE_GREATERTHAN, + self::AUTOFILTER_COLUMN_RULE_GREATERTHANOREQUAL, + self::AUTOFILTER_COLUMN_RULE_LESSTHAN, + self::AUTOFILTER_COLUMN_RULE_LESSTHANOREQUAL, + ); + + const AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE = 'byValue'; + const AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT = 'byPercent'; + + private static $_topTenValue = array( + self::AUTOFILTER_COLUMN_RULE_TOPTEN_BY_VALUE, + self::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT, + ); + + const AUTOFILTER_COLUMN_RULE_TOPTEN_TOP = 'top'; + const AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM = 'bottom'; + + private static $_topTenType = array( + self::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP, + self::AUTOFILTER_COLUMN_RULE_TOPTEN_BOTTOM, + ); + + + /* Rule Operators (Numeric, Boolean etc) */ +// const AUTOFILTER_COLUMN_RULE_BETWEEN = 'between'; // greaterThanOrEqual 1 && lessThanOrEqual 2 + /* Rule Operators (Numeric Special) which are translated to standard numeric operators with calculated values */ +// const AUTOFILTER_COLUMN_RULE_TOPTEN = 'topTen'; // greaterThan calculated value +// const AUTOFILTER_COLUMN_RULE_TOPTENPERCENT = 'topTenPercent'; // greaterThan calculated value +// const AUTOFILTER_COLUMN_RULE_ABOVEAVERAGE = 'aboveAverage'; // Value is calculated as the average +// const AUTOFILTER_COLUMN_RULE_BELOWAVERAGE = 'belowAverage'; // Value is calculated as the average + /* Rule Operators (String) which are set as wild-carded values */ +// const AUTOFILTER_COLUMN_RULE_BEGINSWITH = 'beginsWith'; // A* +// const AUTOFILTER_COLUMN_RULE_ENDSWITH = 'endsWith'; // *Z +// const AUTOFILTER_COLUMN_RULE_CONTAINS = 'contains'; // *B* +// const AUTOFILTER_COLUMN_RULE_DOESNTCONTAIN = 'notEqual'; // notEqual *B* + /* Rule Operators (Date Special) which are translated to standard numeric operators with calculated values */ +// const AUTOFILTER_COLUMN_RULE_BEFORE = 'lessThan'; +// const AUTOFILTER_COLUMN_RULE_AFTER = 'greaterThan'; +// const AUTOFILTER_COLUMN_RULE_YESTERDAY = 'yesterday'; +// const AUTOFILTER_COLUMN_RULE_TODAY = 'today'; +// const AUTOFILTER_COLUMN_RULE_TOMORROW = 'tomorrow'; +// const AUTOFILTER_COLUMN_RULE_LASTWEEK = 'lastWeek'; +// const AUTOFILTER_COLUMN_RULE_THISWEEK = 'thisWeek'; +// const AUTOFILTER_COLUMN_RULE_NEXTWEEK = 'nextWeek'; +// const AUTOFILTER_COLUMN_RULE_LASTMONTH = 'lastMonth'; +// const AUTOFILTER_COLUMN_RULE_THISMONTH = 'thisMonth'; +// const AUTOFILTER_COLUMN_RULE_NEXTMONTH = 'nextMonth'; +// const AUTOFILTER_COLUMN_RULE_LASTQUARTER = 'lastQuarter'; +// const AUTOFILTER_COLUMN_RULE_THISQUARTER = 'thisQuarter'; +// const AUTOFILTER_COLUMN_RULE_NEXTQUARTER = 'nextQuarter'; +// const AUTOFILTER_COLUMN_RULE_LASTYEAR = 'lastYear'; +// const AUTOFILTER_COLUMN_RULE_THISYEAR = 'thisYear'; +// const AUTOFILTER_COLUMN_RULE_NEXTYEAR = 'nextYear'; +// const AUTOFILTER_COLUMN_RULE_YEARTODATE = 'yearToDate'; // <dynamicFilter val="40909" type="yearToDate" maxVal="41113"/> +// const AUTOFILTER_COLUMN_RULE_ALLDATESINMONTH = 'allDatesInMonth'; // <dynamicFilter type="M2"/> for Month/February +// const AUTOFILTER_COLUMN_RULE_ALLDATESINQUARTER = 'allDatesInQuarter'; // <dynamicFilter type="Q2"/> for Quarter 2 + + /** + * Autofilter Column + * + * @var PHPExcel_Worksheet_AutoFilter_Column + */ + private $_parent = NULL; + + + /** + * Autofilter Rule Type + * + * @var string + */ + private $_ruleType = self::AUTOFILTER_RULETYPE_FILTER; + + + /** + * Autofilter Rule Value + * + * @var string + */ + private $_value = ''; + + /** + * Autofilter Rule Operator + * + * @var string + */ + private $_operator = ''; + + /** + * DateTimeGrouping Group Value + * + * @var string + */ + private $_grouping = ''; + + + /** + * Create a new PHPExcel_Worksheet_AutoFilter_Column_Rule + * + * @param PHPExcel_Worksheet_AutoFilter_Column $pParent + */ + public function __construct(PHPExcel_Worksheet_AutoFilter_Column $pParent = NULL) + { + $this->_parent = $pParent; + } + + /** + * Get AutoFilter Rule Type + * + * @return string + */ + public function getRuleType() { + return $this->_ruleType; + } + + /** + * Set AutoFilter Rule Type + * + * @param string $pRuleType + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function setRuleType($pRuleType = self::AUTOFILTER_RULETYPE_FILTER) { + if (!in_array($pRuleType,self::$_ruleTypes)) { + throw new PHPExcel_Exception('Invalid rule type for column AutoFilter Rule.'); + } + + $this->_ruleType = $pRuleType; + + return $this; + } + + /** + * Get AutoFilter Rule Value + * + * @return string + */ + public function getValue() { + return $this->_value; + } + + /** + * Set AutoFilter Rule Value + * + * @param string|string[] $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column_Rule + */ + public function setValue($pValue = '') { + if (is_array($pValue)) { + $grouping = -1; + foreach($pValue as $key => $value) { + // Validate array entries + if (!in_array($key,self::$_dateTimeGroups)) { + // Remove any invalid entries from the value array + unset($pValue[$key]); + } else { + // Work out what the dateTime grouping will be + $grouping = max($grouping,array_search($key,self::$_dateTimeGroups)); + } + } + if (count($pValue) == 0) { + throw new PHPExcel_Exception('Invalid rule value for column AutoFilter Rule.'); + } + // Set the dateTime grouping that we've anticipated + $this->setGrouping(self::$_dateTimeGroups[$grouping]); + } + $this->_value = $pValue; + + return $this; + } + + /** + * Get AutoFilter Rule Operator + * + * @return string + */ + public function getOperator() { + return $this->_operator; + } + + /** + * Set AutoFilter Rule Operator + * + * @param string $pOperator + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column_Rule + */ + public function setOperator($pOperator = self::AUTOFILTER_COLUMN_RULE_EQUAL) { + if (empty($pOperator)) + $pOperator = self::AUTOFILTER_COLUMN_RULE_EQUAL; + if ((!in_array($pOperator,self::$_operators)) && + (!in_array($pOperator,self::$_topTenValue))) { + throw new PHPExcel_Exception('Invalid operator for column AutoFilter Rule.'); + } + $this->_operator = $pOperator; + + return $this; + } + + /** + * Get AutoFilter Rule Grouping + * + * @return string + */ + public function getGrouping() { + return $this->_grouping; + } + + /** + * Set AutoFilter Rule Grouping + * + * @param string $pGrouping + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column_Rule + */ + public function setGrouping($pGrouping = NULL) { + if (($pGrouping !== NULL) && + (!in_array($pGrouping,self::$_dateTimeGroups)) && + (!in_array($pGrouping,self::$_dynamicTypes)) && + (!in_array($pGrouping,self::$_topTenType))) { + throw new PHPExcel_Exception('Invalid rule type for column AutoFilter Rule.'); + } + + $this->_grouping = $pGrouping; + + return $this; + } + + /** + * Set AutoFilter Rule + * + * @param string $pOperator + * @param string|string[] $pValue + * @param string $pGrouping + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_AutoFilter_Column_Rule + */ + public function setRule($pOperator = self::AUTOFILTER_COLUMN_RULE_EQUAL, $pValue = '', $pGrouping = NULL) { + $this->setOperator($pOperator); + $this->setValue($pValue); + // Only set grouping if it's been passed in as a user-supplied argument, + // otherwise we're calculating it when we setValue() and don't want to overwrite that + // If the user supplies an argumnet for grouping, then on their own head be it + if ($pGrouping !== NULL) + $this->setGrouping($pGrouping); + + return $this; + } + + /** + * Get this Rule's AutoFilter Column Parent + * + * @return PHPExcel_Worksheet_AutoFilter_Column + */ + public function getParent() { + return $this->_parent; + } + + /** + * Set this Rule's AutoFilter Column Parent + * + * @param PHPExcel_Worksheet_AutoFilter_Column + * @return PHPExcel_Worksheet_AutoFilter_Column_Rule + */ + public function setParent(PHPExcel_Worksheet_AutoFilter_Column $pParent = NULL) { + $this->_parent = $pParent; + + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + if ($key == '_parent') { + // Detach from autofilter column parent + $this->$key = NULL; + } else { + $this->$key = clone $value; + } + } else { + $this->$key = $value; + } + } + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/BaseDrawing.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/BaseDrawing.php new file mode 100755 index 0000000..dc598ab --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/BaseDrawing.php @@ -0,0 +1,485 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_BaseDrawing + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable +{ + /** + * Image counter + * + * @var int + */ + private static $_imageCounter = 0; + + /** + * Image index + * + * @var int + */ + private $_imageIndex = 0; + + /** + * Name + * + * @var string + */ + protected $_name; + + /** + * Description + * + * @var string + */ + protected $_description; + + /** + * Worksheet + * + * @var PHPExcel_Worksheet + */ + protected $_worksheet; + + /** + * Coordinates + * + * @var string + */ + protected $_coordinates; + + /** + * Offset X + * + * @var int + */ + protected $_offsetX; + + /** + * Offset Y + * + * @var int + */ + protected $_offsetY; + + /** + * Width + * + * @var int + */ + protected $_width; + + /** + * Height + * + * @var int + */ + protected $_height; + + /** + * Proportional resize + * + * @var boolean + */ + protected $_resizeProportional; + + /** + * Rotation + * + * @var int + */ + protected $_rotation; + + /** + * Shadow + * + * @var PHPExcel_Worksheet_Drawing_Shadow + */ + protected $_shadow; + + /** + * Create a new PHPExcel_Worksheet_BaseDrawing + */ + public function __construct() + { + // Initialise values + $this->_name = ''; + $this->_description = ''; + $this->_worksheet = null; + $this->_coordinates = 'A1'; + $this->_offsetX = 0; + $this->_offsetY = 0; + $this->_width = 0; + $this->_height = 0; + $this->_resizeProportional = true; + $this->_rotation = 0; + $this->_shadow = new PHPExcel_Worksheet_Drawing_Shadow(); + + // Set image index + self::$_imageCounter++; + $this->_imageIndex = self::$_imageCounter; + } + + /** + * Get image index + * + * @return int + */ + public function getImageIndex() { + return $this->_imageIndex; + } + + /** + * Get Name + * + * @return string + */ + public function getName() { + return $this->_name; + } + + /** + * Set Name + * + * @param string $pValue + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setName($pValue = '') { + $this->_name = $pValue; + return $this; + } + + /** + * Get Description + * + * @return string + */ + public function getDescription() { + return $this->_description; + } + + /** + * Set Description + * + * @param string $pValue + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setDescription($pValue = '') { + $this->_description = $pValue; + return $this; + } + + /** + * Get Worksheet + * + * @return PHPExcel_Worksheet + */ + public function getWorksheet() { + return $this->_worksheet; + } + + /** + * Set Worksheet + * + * @param PHPExcel_Worksheet $pValue + * @param bool $pOverrideOld If a Worksheet has already been assigned, overwrite it and remove image from old Worksheet? + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setWorksheet(PHPExcel_Worksheet $pValue = null, $pOverrideOld = false) { + if (is_null($this->_worksheet)) { + // Add drawing to PHPExcel_Worksheet + $this->_worksheet = $pValue; + $this->_worksheet->getCell($this->_coordinates); + $this->_worksheet->getDrawingCollection()->append($this); + } else { + if ($pOverrideOld) { + // Remove drawing from old PHPExcel_Worksheet + $iterator = $this->_worksheet->getDrawingCollection()->getIterator(); + + while ($iterator->valid()) { + if ($iterator->current()->getHashCode() == $this->getHashCode()) { + $this->_worksheet->getDrawingCollection()->offsetUnset( $iterator->key() ); + $this->_worksheet = null; + break; + } + } + + // Set new PHPExcel_Worksheet + $this->setWorksheet($pValue); + } else { + throw new PHPExcel_Exception("A PHPExcel_Worksheet has already been assigned. Drawings can only exist on one PHPExcel_Worksheet."); + } + } + return $this; + } + + /** + * Get Coordinates + * + * @return string + */ + public function getCoordinates() { + return $this->_coordinates; + } + + /** + * Set Coordinates + * + * @param string $pValue + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setCoordinates($pValue = 'A1') { + $this->_coordinates = $pValue; + return $this; + } + + /** + * Get OffsetX + * + * @return int + */ + public function getOffsetX() { + return $this->_offsetX; + } + + /** + * Set OffsetX + * + * @param int $pValue + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setOffsetX($pValue = 0) { + $this->_offsetX = $pValue; + return $this; + } + + /** + * Get OffsetY + * + * @return int + */ + public function getOffsetY() { + return $this->_offsetY; + } + + /** + * Set OffsetY + * + * @param int $pValue + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setOffsetY($pValue = 0) { + $this->_offsetY = $pValue; + return $this; + } + + /** + * Get Width + * + * @return int + */ + public function getWidth() { + return $this->_width; + } + + /** + * Set Width + * + * @param int $pValue + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setWidth($pValue = 0) { + // Resize proportional? + if ($this->_resizeProportional && $pValue != 0) { + $ratio = $this->_height / $this->_width; + $this->_height = round($ratio * $pValue); + } + + // Set width + $this->_width = $pValue; + + return $this; + } + + /** + * Get Height + * + * @return int + */ + public function getHeight() { + return $this->_height; + } + + /** + * Set Height + * + * @param int $pValue + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setHeight($pValue = 0) { + // Resize proportional? + if ($this->_resizeProportional && $pValue != 0) { + $ratio = $this->_width / $this->_height; + $this->_width = round($ratio * $pValue); + } + + // Set height + $this->_height = $pValue; + + return $this; + } + + /** + * Set width and height with proportional resize + * Example: + * <code> + * $objDrawing->setResizeProportional(true); + * $objDrawing->setWidthAndHeight(160,120); + * </code> + * + * @author Vincent@luo MSN:kele_100@hotmail.com + * @param int $width + * @param int $height + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setWidthAndHeight($width = 0, $height = 0) { + $xratio = $width / $this->_width; + $yratio = $height / $this->_height; + if ($this->_resizeProportional && !($width == 0 || $height == 0)) { + if (($xratio * $this->_height) < $height) { + $this->_height = ceil($xratio * $this->_height); + $this->_width = $width; + } else { + $this->_width = ceil($yratio * $this->_width); + $this->_height = $height; + } + } + return $this; + } + + /** + * Get ResizeProportional + * + * @return boolean + */ + public function getResizeProportional() { + return $this->_resizeProportional; + } + + /** + * Set ResizeProportional + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setResizeProportional($pValue = true) { + $this->_resizeProportional = $pValue; + return $this; + } + + /** + * Get Rotation + * + * @return int + */ + public function getRotation() { + return $this->_rotation; + } + + /** + * Set Rotation + * + * @param int $pValue + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setRotation($pValue = 0) { + $this->_rotation = $pValue; + return $this; + } + + /** + * Get Shadow + * + * @return PHPExcel_Worksheet_Drawing_Shadow + */ + public function getShadow() { + return $this->_shadow; + } + + /** + * Set Shadow + * + * @param PHPExcel_Worksheet_Drawing_Shadow $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_BaseDrawing + */ + public function setShadow(PHPExcel_Worksheet_Drawing_Shadow $pValue = null) { + $this->_shadow = $pValue; + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_name + . $this->_description + . $this->_worksheet->getHashCode() + . $this->_coordinates + . $this->_offsetX + . $this->_offsetY + . $this->_width + . $this->_height + . $this->_rotation + . $this->_shadow->getHashCode() + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/CellIterator.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/CellIterator.php new file mode 100755 index 0000000..57a14e4 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/CellIterator.php @@ -0,0 +1,161 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_CellIterator + * + * Used to iterate rows in a PHPExcel_Worksheet + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_CellIterator implements Iterator +{ + /** + * PHPExcel_Worksheet to iterate + * + * @var PHPExcel_Worksheet + */ + private $_subject; + + /** + * Row index + * + * @var int + */ + private $_rowIndex; + + /** + * Current iterator position + * + * @var int + */ + private $_position = 0; + + /** + * Loop only existing cells + * + * @var boolean + */ + private $_onlyExistingCells = true; + + /** + * Create a new cell iterator + * + * @param PHPExcel_Worksheet $subject + * @param int $rowIndex + */ + public function __construct(PHPExcel_Worksheet $subject = null, $rowIndex = 1) { + // Set subject and row index + $this->_subject = $subject; + $this->_rowIndex = $rowIndex; + } + + /** + * Destructor + */ + public function __destruct() { + unset($this->_subject); + } + + /** + * Rewind iterator + */ + public function rewind() { + $this->_position = 0; + } + + /** + * Current PHPExcel_Cell + * + * @return PHPExcel_Cell + */ + public function current() { + return $this->_subject->getCellByColumnAndRow($this->_position, $this->_rowIndex); + } + + /** + * Current key + * + * @return int + */ + public function key() { + return $this->_position; + } + + /** + * Next value + */ + public function next() { + ++$this->_position; + } + + /** + * Are there any more PHPExcel_Cell instances available? + * + * @return boolean + */ + public function valid() { + // columnIndexFromString() returns an index based at one, + // treat it as a count when comparing it to the base zero + // position. + $columnCount = PHPExcel_Cell::columnIndexFromString($this->_subject->getHighestColumn()); + + if ($this->_onlyExistingCells) { + // If we aren't looking at an existing cell, either + // because the first column doesn't exist or next() has + // been called onto a nonexistent cell, then loop until we + // find one, or pass the last column. + while ($this->_position < $columnCount && + !$this->_subject->cellExistsByColumnAndRow($this->_position, $this->_rowIndex)) { + ++$this->_position; + } + } + + return $this->_position < $columnCount; + } + + /** + * Get loop only existing cells + * + * @return boolean + */ + public function getIterateOnlyExistingCells() { + return $this->_onlyExistingCells; + } + + /** + * Set the iterator to loop only existing cells + * + * @param boolean $value + */ + public function setIterateOnlyExistingCells($value = true) { + $this->_onlyExistingCells = $value; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/ColumnDimension.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/ColumnDimension.php new file mode 100755 index 0000000..202c0f4 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/ColumnDimension.php @@ -0,0 +1,266 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_ColumnDimension + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_ColumnDimension +{ + /** + * Column index + * + * @var int + */ + private $_columnIndex; + + /** + * Column width + * + * When this is set to a negative value, the column width should be ignored by IWriter + * + * @var double + */ + private $_width = -1; + + /** + * Auto size? + * + * @var bool + */ + private $_autoSize = false; + + /** + * Visible? + * + * @var bool + */ + private $_visible = true; + + /** + * Outline level + * + * @var int + */ + private $_outlineLevel = 0; + + /** + * Collapsed + * + * @var bool + */ + private $_collapsed = false; + + /** + * Index to cellXf + * + * @var int + */ + private $_xfIndex; + + /** + * Create a new PHPExcel_Worksheet_ColumnDimension + * + * @param string $pIndex Character column index + */ + public function __construct($pIndex = 'A') + { + // Initialise values + $this->_columnIndex = $pIndex; + + // set default index to cellXf + $this->_xfIndex = 0; + } + + /** + * Get ColumnIndex + * + * @return string + */ + public function getColumnIndex() { + return $this->_columnIndex; + } + + /** + * Set ColumnIndex + * + * @param string $pValue + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function setColumnIndex($pValue) { + $this->_columnIndex = $pValue; + return $this; + } + + /** + * Get Width + * + * @return double + */ + public function getWidth() { + return $this->_width; + } + + /** + * Set Width + * + * @param double $pValue + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function setWidth($pValue = -1) { + $this->_width = $pValue; + return $this; + } + + /** + * Get Auto Size + * + * @return bool + */ + public function getAutoSize() { + return $this->_autoSize; + } + + /** + * Set Auto Size + * + * @param bool $pValue + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function setAutoSize($pValue = false) { + $this->_autoSize = $pValue; + return $this; + } + + /** + * Get Visible + * + * @return bool + */ + public function getVisible() { + return $this->_visible; + } + + /** + * Set Visible + * + * @param bool $pValue + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function setVisible($pValue = true) { + $this->_visible = $pValue; + return $this; + } + + /** + * Get Outline Level + * + * @return int + */ + public function getOutlineLevel() { + return $this->_outlineLevel; + } + + /** + * Set Outline Level + * + * Value must be between 0 and 7 + * + * @param int $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function setOutlineLevel($pValue) { + if ($pValue < 0 || $pValue > 7) { + throw new PHPExcel_Exception("Outline level must range between 0 and 7."); + } + + $this->_outlineLevel = $pValue; + return $this; + } + + /** + * Get Collapsed + * + * @return bool + */ + public function getCollapsed() { + return $this->_collapsed; + } + + /** + * Set Collapsed + * + * @param bool $pValue + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function setCollapsed($pValue = true) { + $this->_collapsed = $pValue; + return $this; + } + + /** + * Get index to cellXf + * + * @return int + */ + public function getXfIndex() + { + return $this->_xfIndex; + } + + /** + * Set index to cellXf + * + * @param int $pValue + * @return PHPExcel_Worksheet_ColumnDimension + */ + public function setXfIndex($pValue = 0) + { + $this->_xfIndex = $pValue; + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Drawing.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Drawing.php new file mode 100755 index 0000000..45086ce --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Drawing.php @@ -0,0 +1,148 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet_Drawing + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_Drawing + * + * @category PHPExcel + * @package PHPExcel_Worksheet_Drawing + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_Drawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable +{ + /** + * Path + * + * @var string + */ + private $_path; + + /** + * Create a new PHPExcel_Worksheet_Drawing + */ + public function __construct() + { + // Initialise values + $this->_path = ''; + + // Initialize parent + parent::__construct(); + } + + /** + * Get Filename + * + * @return string + */ + public function getFilename() { + return basename($this->_path); + } + + /** + * Get indexed filename (using image index) + * + * @return string + */ + public function getIndexedFilename() { + $fileName = $this->getFilename(); + $fileName = str_replace(' ', '_', $fileName); + return str_replace('.' . $this->getExtension(), '', $fileName) . $this->getImageIndex() . '.' . $this->getExtension(); + } + + /** + * Get Extension + * + * @return string + */ + public function getExtension() { + $exploded = explode(".", basename($this->_path)); + return $exploded[count($exploded) - 1]; + } + + /** + * Get Path + * + * @return string + */ + public function getPath() { + return $this->_path; + } + + /** + * Set Path + * + * @param string $pValue File path + * @param boolean $pVerifyFile Verify file + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_Drawing + */ + public function setPath($pValue = '', $pVerifyFile = true) { + if ($pVerifyFile) { + if (file_exists($pValue)) { + $this->_path = $pValue; + + if ($this->_width == 0 && $this->_height == 0) { + // Get width/height + list($this->_width, $this->_height) = getimagesize($pValue); + } + } else { + throw new PHPExcel_Exception("File $pValue not found!"); + } + } else { + $this->_path = $pValue; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_path + . parent::getHashCode() + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Drawing/Shadow.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Drawing/Shadow.php new file mode 100755 index 0000000..88d0ae5 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Drawing/Shadow.php @@ -0,0 +1,288 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet_Drawing + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_Drawing_Shadow + * + * @category PHPExcel + * @package PHPExcel_Worksheet_Drawing + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_Drawing_Shadow implements PHPExcel_IComparable +{ + /* Shadow alignment */ + const SHADOW_BOTTOM = 'b'; + const SHADOW_BOTTOM_LEFT = 'bl'; + const SHADOW_BOTTOM_RIGHT = 'br'; + const SHADOW_CENTER = 'ctr'; + const SHADOW_LEFT = 'l'; + const SHADOW_TOP = 't'; + const SHADOW_TOP_LEFT = 'tl'; + const SHADOW_TOP_RIGHT = 'tr'; + + /** + * Visible + * + * @var boolean + */ + private $_visible; + + /** + * Blur radius + * + * Defaults to 6 + * + * @var int + */ + private $_blurRadius; + + /** + * Shadow distance + * + * Defaults to 2 + * + * @var int + */ + private $_distance; + + /** + * Shadow direction (in degrees) + * + * @var int + */ + private $_direction; + + /** + * Shadow alignment + * + * @var int + */ + private $_alignment; + + /** + * Color + * + * @var PHPExcel_Style_Color + */ + private $_color; + + /** + * Alpha + * + * @var int + */ + private $_alpha; + + /** + * Create a new PHPExcel_Worksheet_Drawing_Shadow + */ + public function __construct() + { + // Initialise values + $this->_visible = false; + $this->_blurRadius = 6; + $this->_distance = 2; + $this->_direction = 0; + $this->_alignment = PHPExcel_Worksheet_Drawing_Shadow::SHADOW_BOTTOM_RIGHT; + $this->_color = new PHPExcel_Style_Color(PHPExcel_Style_Color::COLOR_BLACK); + $this->_alpha = 50; + } + + /** + * Get Visible + * + * @return boolean + */ + public function getVisible() { + return $this->_visible; + } + + /** + * Set Visible + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Drawing_Shadow + */ + public function setVisible($pValue = false) { + $this->_visible = $pValue; + return $this; + } + + /** + * Get Blur radius + * + * @return int + */ + public function getBlurRadius() { + return $this->_blurRadius; + } + + /** + * Set Blur radius + * + * @param int $pValue + * @return PHPExcel_Worksheet_Drawing_Shadow + */ + public function setBlurRadius($pValue = 6) { + $this->_blurRadius = $pValue; + return $this; + } + + /** + * Get Shadow distance + * + * @return int + */ + public function getDistance() { + return $this->_distance; + } + + /** + * Set Shadow distance + * + * @param int $pValue + * @return PHPExcel_Worksheet_Drawing_Shadow + */ + public function setDistance($pValue = 2) { + $this->_distance = $pValue; + return $this; + } + + /** + * Get Shadow direction (in degrees) + * + * @return int + */ + public function getDirection() { + return $this->_direction; + } + + /** + * Set Shadow direction (in degrees) + * + * @param int $pValue + * @return PHPExcel_Worksheet_Drawing_Shadow + */ + public function setDirection($pValue = 0) { + $this->_direction = $pValue; + return $this; + } + + /** + * Get Shadow alignment + * + * @return int + */ + public function getAlignment() { + return $this->_alignment; + } + + /** + * Set Shadow alignment + * + * @param int $pValue + * @return PHPExcel_Worksheet_Drawing_Shadow + */ + public function setAlignment($pValue = 0) { + $this->_alignment = $pValue; + return $this; + } + + /** + * Get Color + * + * @return PHPExcel_Style_Color + */ + public function getColor() { + return $this->_color; + } + + /** + * Set Color + * + * @param PHPExcel_Style_Color $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_Drawing_Shadow + */ + public function setColor(PHPExcel_Style_Color $pValue = null) { + $this->_color = $pValue; + return $this; + } + + /** + * Get Alpha + * + * @return int + */ + public function getAlpha() { + return $this->_alpha; + } + + /** + * Set Alpha + * + * @param int $pValue + * @return PHPExcel_Worksheet_Drawing_Shadow + */ + public function setAlpha($pValue = 0) { + $this->_alpha = $pValue; + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + ($this->_visible ? 't' : 'f') + . $this->_blurRadius + . $this->_distance + . $this->_direction + . $this->_alignment + . $this->_color->getHashCode() + . $this->_alpha + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/HeaderFooter.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/HeaderFooter.php new file mode 100755 index 0000000..ef118f2 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/HeaderFooter.php @@ -0,0 +1,465 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_HeaderFooter + * + * <code> + * Header/Footer Formatting Syntax taken from Office Open XML Part 4 - Markup Language Reference, page 1970: + * + * There are a number of formatting codes that can be written inline with the actual header / footer text, which + * affect the formatting in the header or footer. + * + * Example: This example shows the text "Center Bold Header" on the first line (center section), and the date on + * the second line (center section). + * &CCenter &"-,Bold"Bold&"-,Regular"Header_x000A_&D + * + * General Rules: + * There is no required order in which these codes must appear. + * + * The first occurrence of the following codes turns the formatting ON, the second occurrence turns it OFF again: + * - strikethrough + * - superscript + * - subscript + * Superscript and subscript cannot both be ON at same time. Whichever comes first wins and the other is ignored, + * while the first is ON. + * &L - code for "left section" (there are three header / footer locations, "left", "center", and "right"). When + * two or more occurrences of this section marker exist, the contents from all markers are concatenated, in the + * order of appearance, and placed into the left section. + * &P - code for "current page #" + * &N - code for "total pages" + * &font size - code for "text font size", where font size is a font size in points. + * &K - code for "text font color" + * RGB Color is specified as RRGGBB + * Theme Color is specifed as TTSNN where TT is the theme color Id, S is either "+" or "-" of the tint/shade + * value, NN is the tint/shade value. + * &S - code for "text strikethrough" on / off + * &X - code for "text super script" on / off + * &Y - code for "text subscript" on / off + * &C - code for "center section". When two or more occurrences of this section marker exist, the contents + * from all markers are concatenated, in the order of appearance, and placed into the center section. + * + * &D - code for "date" + * &T - code for "time" + * &G - code for "picture as background" + * &U - code for "text single underline" + * &E - code for "double underline" + * &R - code for "right section". When two or more occurrences of this section marker exist, the contents + * from all markers are concatenated, in the order of appearance, and placed into the right section. + * &Z - code for "this workbook's file path" + * &F - code for "this workbook's file name" + * &A - code for "sheet tab name" + * &+ - code for add to page #. + * &- - code for subtract from page #. + * &"font name,font type" - code for "text font name" and "text font type", where font name and font type + * are strings specifying the name and type of the font, separated by a comma. When a hyphen appears in font + * name, it means "none specified". Both of font name and font type can be localized values. + * &"-,Bold" - code for "bold font style" + * &B - also means "bold font style". + * &"-,Regular" - code for "regular font style" + * &"-,Italic" - code for "italic font style" + * &I - also means "italic font style" + * &"-,Bold Italic" code for "bold italic font style" + * &O - code for "outline style" + * &H - code for "shadow style" + * </code> + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_HeaderFooter +{ + /* Header/footer image location */ + const IMAGE_HEADER_LEFT = 'LH'; + const IMAGE_HEADER_CENTER = 'CH'; + const IMAGE_HEADER_RIGHT = 'RH'; + const IMAGE_FOOTER_LEFT = 'LF'; + const IMAGE_FOOTER_CENTER = 'CF'; + const IMAGE_FOOTER_RIGHT = 'RF'; + + /** + * OddHeader + * + * @var string + */ + private $_oddHeader = ''; + + /** + * OddFooter + * + * @var string + */ + private $_oddFooter = ''; + + /** + * EvenHeader + * + * @var string + */ + private $_evenHeader = ''; + + /** + * EvenFooter + * + * @var string + */ + private $_evenFooter = ''; + + /** + * FirstHeader + * + * @var string + */ + private $_firstHeader = ''; + + /** + * FirstFooter + * + * @var string + */ + private $_firstFooter = ''; + + /** + * Different header for Odd/Even, defaults to false + * + * @var boolean + */ + private $_differentOddEven = false; + + /** + * Different header for first page, defaults to false + * + * @var boolean + */ + private $_differentFirst = false; + + /** + * Scale with document, defaults to true + * + * @var boolean + */ + private $_scaleWithDocument = true; + + /** + * Align with margins, defaults to true + * + * @var boolean + */ + private $_alignWithMargins = true; + + /** + * Header/footer images + * + * @var PHPExcel_Worksheet_HeaderFooterDrawing[] + */ + private $_headerFooterImages = array(); + + /** + * Create a new PHPExcel_Worksheet_HeaderFooter + */ + public function __construct() + { + } + + /** + * Get OddHeader + * + * @return string + */ + public function getOddHeader() { + return $this->_oddHeader; + } + + /** + * Set OddHeader + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setOddHeader($pValue) { + $this->_oddHeader = $pValue; + return $this; + } + + /** + * Get OddFooter + * + * @return string + */ + public function getOddFooter() { + return $this->_oddFooter; + } + + /** + * Set OddFooter + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setOddFooter($pValue) { + $this->_oddFooter = $pValue; + return $this; + } + + /** + * Get EvenHeader + * + * @return string + */ + public function getEvenHeader() { + return $this->_evenHeader; + } + + /** + * Set EvenHeader + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setEvenHeader($pValue) { + $this->_evenHeader = $pValue; + return $this; + } + + /** + * Get EvenFooter + * + * @return string + */ + public function getEvenFooter() { + return $this->_evenFooter; + } + + /** + * Set EvenFooter + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setEvenFooter($pValue) { + $this->_evenFooter = $pValue; + return $this; + } + + /** + * Get FirstHeader + * + * @return string + */ + public function getFirstHeader() { + return $this->_firstHeader; + } + + /** + * Set FirstHeader + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setFirstHeader($pValue) { + $this->_firstHeader = $pValue; + return $this; + } + + /** + * Get FirstFooter + * + * @return string + */ + public function getFirstFooter() { + return $this->_firstFooter; + } + + /** + * Set FirstFooter + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setFirstFooter($pValue) { + $this->_firstFooter = $pValue; + return $this; + } + + /** + * Get DifferentOddEven + * + * @return boolean + */ + public function getDifferentOddEven() { + return $this->_differentOddEven; + } + + /** + * Set DifferentOddEven + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setDifferentOddEven($pValue = false) { + $this->_differentOddEven = $pValue; + return $this; + } + + /** + * Get DifferentFirst + * + * @return boolean + */ + public function getDifferentFirst() { + return $this->_differentFirst; + } + + /** + * Set DifferentFirst + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setDifferentFirst($pValue = false) { + $this->_differentFirst = $pValue; + return $this; + } + + /** + * Get ScaleWithDocument + * + * @return boolean + */ + public function getScaleWithDocument() { + return $this->_scaleWithDocument; + } + + /** + * Set ScaleWithDocument + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setScaleWithDocument($pValue = true) { + $this->_scaleWithDocument = $pValue; + return $this; + } + + /** + * Get AlignWithMargins + * + * @return boolean + */ + public function getAlignWithMargins() { + return $this->_alignWithMargins; + } + + /** + * Set AlignWithMargins + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setAlignWithMargins($pValue = true) { + $this->_alignWithMargins = $pValue; + return $this; + } + + /** + * Add header/footer image + * + * @param PHPExcel_Worksheet_HeaderFooterDrawing $image + * @param string $location + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function addImage(PHPExcel_Worksheet_HeaderFooterDrawing $image = null, $location = self::IMAGE_HEADER_LEFT) { + $this->_headerFooterImages[$location] = $image; + return $this; + } + + /** + * Remove header/footer image + * + * @param string $location + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function removeImage($location = self::IMAGE_HEADER_LEFT) { + if (isset($this->_headerFooterImages[$location])) { + unset($this->_headerFooterImages[$location]); + } + return $this; + } + + /** + * Set header/footer images + * + * @param PHPExcel_Worksheet_HeaderFooterDrawing[] $images + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setImages($images) { + if (!is_array($images)) { + throw new PHPExcel_Exception('Invalid parameter!'); + } + + $this->_headerFooterImages = $images; + return $this; + } + + /** + * Get header/footer images + * + * @return PHPExcel_Worksheet_HeaderFooterDrawing[] + */ + public function getImages() { + // Sort array + $images = array(); + if (isset($this->_headerFooterImages[self::IMAGE_HEADER_LEFT])) $images[self::IMAGE_HEADER_LEFT] = $this->_headerFooterImages[self::IMAGE_HEADER_LEFT]; + if (isset($this->_headerFooterImages[self::IMAGE_HEADER_CENTER])) $images[self::IMAGE_HEADER_CENTER] = $this->_headerFooterImages[self::IMAGE_HEADER_CENTER]; + if (isset($this->_headerFooterImages[self::IMAGE_HEADER_RIGHT])) $images[self::IMAGE_HEADER_RIGHT] = $this->_headerFooterImages[self::IMAGE_HEADER_RIGHT]; + if (isset($this->_headerFooterImages[self::IMAGE_FOOTER_LEFT])) $images[self::IMAGE_FOOTER_LEFT] = $this->_headerFooterImages[self::IMAGE_FOOTER_LEFT]; + if (isset($this->_headerFooterImages[self::IMAGE_FOOTER_CENTER])) $images[self::IMAGE_FOOTER_CENTER] = $this->_headerFooterImages[self::IMAGE_FOOTER_CENTER]; + if (isset($this->_headerFooterImages[self::IMAGE_FOOTER_RIGHT])) $images[self::IMAGE_FOOTER_RIGHT] = $this->_headerFooterImages[self::IMAGE_FOOTER_RIGHT]; + $this->_headerFooterImages = $images; + + return $this->_headerFooterImages; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/HeaderFooterDrawing.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/HeaderFooterDrawing.php new file mode 100755 index 0000000..512887e --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/HeaderFooterDrawing.php @@ -0,0 +1,350 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_HeaderFooterDrawing + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_HeaderFooterDrawing extends PHPExcel_Worksheet_Drawing implements PHPExcel_IComparable +{ + /** + * Path + * + * @var string + */ + private $_path; + + /** + * Name + * + * @var string + */ + protected $_name; + + /** + * Offset X + * + * @var int + */ + protected $_offsetX; + + /** + * Offset Y + * + * @var int + */ + protected $_offsetY; + + /** + * Width + * + * @var int + */ + protected $_width; + + /** + * Height + * + * @var int + */ + protected $_height; + + /** + * Proportional resize + * + * @var boolean + */ + protected $_resizeProportional; + + /** + * Create a new PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function __construct() + { + // Initialise values + $this->_path = ''; + $this->_name = ''; + $this->_offsetX = 0; + $this->_offsetY = 0; + $this->_width = 0; + $this->_height = 0; + $this->_resizeProportional = true; + } + + /** + * Get Name + * + * @return string + */ + public function getName() { + return $this->_name; + } + + /** + * Set Name + * + * @param string $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setName($pValue = '') { + $this->_name = $pValue; + return $this; + } + + /** + * Get OffsetX + * + * @return int + */ + public function getOffsetX() { + return $this->_offsetX; + } + + /** + * Set OffsetX + * + * @param int $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setOffsetX($pValue = 0) { + $this->_offsetX = $pValue; + return $this; + } + + /** + * Get OffsetY + * + * @return int + */ + public function getOffsetY() { + return $this->_offsetY; + } + + /** + * Set OffsetY + * + * @param int $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setOffsetY($pValue = 0) { + $this->_offsetY = $pValue; + return $this; + } + + /** + * Get Width + * + * @return int + */ + public function getWidth() { + return $this->_width; + } + + /** + * Set Width + * + * @param int $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setWidth($pValue = 0) { + // Resize proportional? + if ($this->_resizeProportional && $pValue != 0) { + $ratio = $this->_width / $this->_height; + $this->_height = round($ratio * $pValue); + } + + // Set width + $this->_width = $pValue; + + return $this; + } + + /** + * Get Height + * + * @return int + */ + public function getHeight() { + return $this->_height; + } + + /** + * Set Height + * + * @param int $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setHeight($pValue = 0) { + // Resize proportional? + if ($this->_resizeProportional && $pValue != 0) { + $ratio = $this->_width / $this->_height; + $this->_width = round($ratio * $pValue); + } + + // Set height + $this->_height = $pValue; + + return $this; + } + + /** + * Set width and height with proportional resize + * Example: + * <code> + * $objDrawing->setResizeProportional(true); + * $objDrawing->setWidthAndHeight(160,120); + * </code> + * + * @author Vincent@luo MSN:kele_100@hotmail.com + * @param int $width + * @param int $height + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setWidthAndHeight($width = 0, $height = 0) { + $xratio = $width / $this->_width; + $yratio = $height / $this->_height; + if ($this->_resizeProportional && !($width == 0 || $height == 0)) { + if (($xratio * $this->_height) < $height) { + $this->_height = ceil($xratio * $this->_height); + $this->_width = $width; + } else { + $this->_width = ceil($yratio * $this->_width); + $this->_height = $height; + } + } + return $this; + } + + /** + * Get ResizeProportional + * + * @return boolean + */ + public function getResizeProportional() { + return $this->_resizeProportional; + } + + /** + * Set ResizeProportional + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setResizeProportional($pValue = true) { + $this->_resizeProportional = $pValue; + return $this; + } + + /** + * Get Filename + * + * @return string + */ + public function getFilename() { + return basename($this->_path); + } + + /** + * Get Extension + * + * @return string + */ + public function getExtension() { + $parts = explode(".", basename($this->_path)); + return end($parts); + } + + /** + * Get Path + * + * @return string + */ + public function getPath() { + return $this->_path; + } + + /** + * Set Path + * + * @param string $pValue File path + * @param boolean $pVerifyFile Verify file + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_HeaderFooterDrawing + */ + public function setPath($pValue = '', $pVerifyFile = true) { + if ($pVerifyFile) { + if (file_exists($pValue)) { + $this->_path = $pValue; + + if ($this->_width == 0 && $this->_height == 0) { + // Get width/height + list($this->_width, $this->_height) = getimagesize($pValue); + } + } else { + throw new PHPExcel_Exception("File $pValue not found!"); + } + } else { + $this->_path = $pValue; + } + return $this; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_path + . $this->_name + . $this->_offsetX + . $this->_offsetY + . $this->_width + . $this->_height + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/MemoryDrawing.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/MemoryDrawing.php new file mode 100755 index 0000000..e2dce98 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/MemoryDrawing.php @@ -0,0 +1,200 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_MemoryDrawing + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_MemoryDrawing extends PHPExcel_Worksheet_BaseDrawing implements PHPExcel_IComparable +{ + /* Rendering functions */ + const RENDERING_DEFAULT = 'imagepng'; + const RENDERING_PNG = 'imagepng'; + const RENDERING_GIF = 'imagegif'; + const RENDERING_JPEG = 'imagejpeg'; + + /* MIME types */ + const MIMETYPE_DEFAULT = 'image/png'; + const MIMETYPE_PNG = 'image/png'; + const MIMETYPE_GIF = 'image/gif'; + const MIMETYPE_JPEG = 'image/jpeg'; + + /** + * Image resource + * + * @var resource + */ + private $_imageResource; + + /** + * Rendering function + * + * @var string + */ + private $_renderingFunction; + + /** + * Mime type + * + * @var string + */ + private $_mimeType; + + /** + * Unique name + * + * @var string + */ + private $_uniqueName; + + /** + * Create a new PHPExcel_Worksheet_MemoryDrawing + */ + public function __construct() + { + // Initialise values + $this->_imageResource = null; + $this->_renderingFunction = self::RENDERING_DEFAULT; + $this->_mimeType = self::MIMETYPE_DEFAULT; + $this->_uniqueName = md5(rand(0, 9999). time() . rand(0, 9999)); + + // Initialize parent + parent::__construct(); + } + + /** + * Get image resource + * + * @return resource + */ + public function getImageResource() { + return $this->_imageResource; + } + + /** + * Set image resource + * + * @param $value resource + * @return PHPExcel_Worksheet_MemoryDrawing + */ + public function setImageResource($value = null) { + $this->_imageResource = $value; + + if (!is_null($this->_imageResource)) { + // Get width/height + $this->_width = imagesx($this->_imageResource); + $this->_height = imagesy($this->_imageResource); + } + return $this; + } + + /** + * Get rendering function + * + * @return string + */ + public function getRenderingFunction() { + return $this->_renderingFunction; + } + + /** + * Set rendering function + * + * @param string $value + * @return PHPExcel_Worksheet_MemoryDrawing + */ + public function setRenderingFunction($value = PHPExcel_Worksheet_MemoryDrawing::RENDERING_DEFAULT) { + $this->_renderingFunction = $value; + return $this; + } + + /** + * Get mime type + * + * @return string + */ + public function getMimeType() { + return $this->_mimeType; + } + + /** + * Set mime type + * + * @param string $value + * @return PHPExcel_Worksheet_MemoryDrawing + */ + public function setMimeType($value = PHPExcel_Worksheet_MemoryDrawing::MIMETYPE_DEFAULT) { + $this->_mimeType = $value; + return $this; + } + + /** + * Get indexed filename (using image index) + * + * @return string + */ + public function getIndexedFilename() { + $extension = strtolower($this->getMimeType()); + $extension = explode('/', $extension); + $extension = $extension[1]; + + return $this->_uniqueName . $this->getImageIndex() . '.' . $extension; + } + + /** + * Get hash code + * + * @return string Hash code + */ + public function getHashCode() { + return md5( + $this->_renderingFunction + . $this->_mimeType + . $this->_uniqueName + . parent::getHashCode() + . __CLASS__ + ); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/PageMargins.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/PageMargins.php new file mode 100755 index 0000000..339815d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/PageMargins.php @@ -0,0 +1,220 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_PageMargins + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_PageMargins +{ + /** + * Left + * + * @var double + */ + private $_left = 0.7; + + /** + * Right + * + * @var double + */ + private $_right = 0.7; + + /** + * Top + * + * @var double + */ + private $_top = 0.75; + + /** + * Bottom + * + * @var double + */ + private $_bottom = 0.75; + + /** + * Header + * + * @var double + */ + private $_header = 0.3; + + /** + * Footer + * + * @var double + */ + private $_footer = 0.3; + + /** + * Create a new PHPExcel_Worksheet_PageMargins + */ + public function __construct() + { + } + + /** + * Get Left + * + * @return double + */ + public function getLeft() { + return $this->_left; + } + + /** + * Set Left + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setLeft($pValue) { + $this->_left = $pValue; + return $this; + } + + /** + * Get Right + * + * @return double + */ + public function getRight() { + return $this->_right; + } + + /** + * Set Right + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setRight($pValue) { + $this->_right = $pValue; + return $this; + } + + /** + * Get Top + * + * @return double + */ + public function getTop() { + return $this->_top; + } + + /** + * Set Top + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setTop($pValue) { + $this->_top = $pValue; + return $this; + } + + /** + * Get Bottom + * + * @return double + */ + public function getBottom() { + return $this->_bottom; + } + + /** + * Set Bottom + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setBottom($pValue) { + $this->_bottom = $pValue; + return $this; + } + + /** + * Get Header + * + * @return double + */ + public function getHeader() { + return $this->_header; + } + + /** + * Set Header + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setHeader($pValue) { + $this->_header = $pValue; + return $this; + } + + /** + * Get Footer + * + * @return double + */ + public function getFooter() { + return $this->_footer; + } + + /** + * Set Footer + * + * @param double $pValue + * @return PHPExcel_Worksheet_PageMargins + */ + public function setFooter($pValue) { + $this->_footer = $pValue; + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/PageSetup.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/PageSetup.php new file mode 100755 index 0000000..1508eea --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/PageSetup.php @@ -0,0 +1,798 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_PageSetup + * + * <code> + * Paper size taken from Office Open XML Part 4 - Markup Language Reference, page 1988: + * + * 1 = Letter paper (8.5 in. by 11 in.) + * 2 = Letter small paper (8.5 in. by 11 in.) + * 3 = Tabloid paper (11 in. by 17 in.) + * 4 = Ledger paper (17 in. by 11 in.) + * 5 = Legal paper (8.5 in. by 14 in.) + * 6 = Statement paper (5.5 in. by 8.5 in.) + * 7 = Executive paper (7.25 in. by 10.5 in.) + * 8 = A3 paper (297 mm by 420 mm) + * 9 = A4 paper (210 mm by 297 mm) + * 10 = A4 small paper (210 mm by 297 mm) + * 11 = A5 paper (148 mm by 210 mm) + * 12 = B4 paper (250 mm by 353 mm) + * 13 = B5 paper (176 mm by 250 mm) + * 14 = Folio paper (8.5 in. by 13 in.) + * 15 = Quarto paper (215 mm by 275 mm) + * 16 = Standard paper (10 in. by 14 in.) + * 17 = Standard paper (11 in. by 17 in.) + * 18 = Note paper (8.5 in. by 11 in.) + * 19 = #9 envelope (3.875 in. by 8.875 in.) + * 20 = #10 envelope (4.125 in. by 9.5 in.) + * 21 = #11 envelope (4.5 in. by 10.375 in.) + * 22 = #12 envelope (4.75 in. by 11 in.) + * 23 = #14 envelope (5 in. by 11.5 in.) + * 24 = C paper (17 in. by 22 in.) + * 25 = D paper (22 in. by 34 in.) + * 26 = E paper (34 in. by 44 in.) + * 27 = DL envelope (110 mm by 220 mm) + * 28 = C5 envelope (162 mm by 229 mm) + * 29 = C3 envelope (324 mm by 458 mm) + * 30 = C4 envelope (229 mm by 324 mm) + * 31 = C6 envelope (114 mm by 162 mm) + * 32 = C65 envelope (114 mm by 229 mm) + * 33 = B4 envelope (250 mm by 353 mm) + * 34 = B5 envelope (176 mm by 250 mm) + * 35 = B6 envelope (176 mm by 125 mm) + * 36 = Italy envelope (110 mm by 230 mm) + * 37 = Monarch envelope (3.875 in. by 7.5 in.). + * 38 = 6 3/4 envelope (3.625 in. by 6.5 in.) + * 39 = US standard fanfold (14.875 in. by 11 in.) + * 40 = German standard fanfold (8.5 in. by 12 in.) + * 41 = German legal fanfold (8.5 in. by 13 in.) + * 42 = ISO B4 (250 mm by 353 mm) + * 43 = Japanese double postcard (200 mm by 148 mm) + * 44 = Standard paper (9 in. by 11 in.) + * 45 = Standard paper (10 in. by 11 in.) + * 46 = Standard paper (15 in. by 11 in.) + * 47 = Invite envelope (220 mm by 220 mm) + * 50 = Letter extra paper (9.275 in. by 12 in.) + * 51 = Legal extra paper (9.275 in. by 15 in.) + * 52 = Tabloid extra paper (11.69 in. by 18 in.) + * 53 = A4 extra paper (236 mm by 322 mm) + * 54 = Letter transverse paper (8.275 in. by 11 in.) + * 55 = A4 transverse paper (210 mm by 297 mm) + * 56 = Letter extra transverse paper (9.275 in. by 12 in.) + * 57 = SuperA/SuperA/A4 paper (227 mm by 356 mm) + * 58 = SuperB/SuperB/A3 paper (305 mm by 487 mm) + * 59 = Letter plus paper (8.5 in. by 12.69 in.) + * 60 = A4 plus paper (210 mm by 330 mm) + * 61 = A5 transverse paper (148 mm by 210 mm) + * 62 = JIS B5 transverse paper (182 mm by 257 mm) + * 63 = A3 extra paper (322 mm by 445 mm) + * 64 = A5 extra paper (174 mm by 235 mm) + * 65 = ISO B5 extra paper (201 mm by 276 mm) + * 66 = A2 paper (420 mm by 594 mm) + * 67 = A3 transverse paper (297 mm by 420 mm) + * 68 = A3 extra transverse paper (322 mm by 445 mm) + * </code> + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_PageSetup +{ + /* Paper size */ + const PAPERSIZE_LETTER = 1; + const PAPERSIZE_LETTER_SMALL = 2; + const PAPERSIZE_TABLOID = 3; + const PAPERSIZE_LEDGER = 4; + const PAPERSIZE_LEGAL = 5; + const PAPERSIZE_STATEMENT = 6; + const PAPERSIZE_EXECUTIVE = 7; + const PAPERSIZE_A3 = 8; + const PAPERSIZE_A4 = 9; + const PAPERSIZE_A4_SMALL = 10; + const PAPERSIZE_A5 = 11; + const PAPERSIZE_B4 = 12; + const PAPERSIZE_B5 = 13; + const PAPERSIZE_FOLIO = 14; + const PAPERSIZE_QUARTO = 15; + const PAPERSIZE_STANDARD_1 = 16; + const PAPERSIZE_STANDARD_2 = 17; + const PAPERSIZE_NOTE = 18; + const PAPERSIZE_NO9_ENVELOPE = 19; + const PAPERSIZE_NO10_ENVELOPE = 20; + const PAPERSIZE_NO11_ENVELOPE = 21; + const PAPERSIZE_NO12_ENVELOPE = 22; + const PAPERSIZE_NO14_ENVELOPE = 23; + const PAPERSIZE_C = 24; + const PAPERSIZE_D = 25; + const PAPERSIZE_E = 26; + const PAPERSIZE_DL_ENVELOPE = 27; + const PAPERSIZE_C5_ENVELOPE = 28; + const PAPERSIZE_C3_ENVELOPE = 29; + const PAPERSIZE_C4_ENVELOPE = 30; + const PAPERSIZE_C6_ENVELOPE = 31; + const PAPERSIZE_C65_ENVELOPE = 32; + const PAPERSIZE_B4_ENVELOPE = 33; + const PAPERSIZE_B5_ENVELOPE = 34; + const PAPERSIZE_B6_ENVELOPE = 35; + const PAPERSIZE_ITALY_ENVELOPE = 36; + const PAPERSIZE_MONARCH_ENVELOPE = 37; + const PAPERSIZE_6_3_4_ENVELOPE = 38; + const PAPERSIZE_US_STANDARD_FANFOLD = 39; + const PAPERSIZE_GERMAN_STANDARD_FANFOLD = 40; + const PAPERSIZE_GERMAN_LEGAL_FANFOLD = 41; + const PAPERSIZE_ISO_B4 = 42; + const PAPERSIZE_JAPANESE_DOUBLE_POSTCARD = 43; + const PAPERSIZE_STANDARD_PAPER_1 = 44; + const PAPERSIZE_STANDARD_PAPER_2 = 45; + const PAPERSIZE_STANDARD_PAPER_3 = 46; + const PAPERSIZE_INVITE_ENVELOPE = 47; + const PAPERSIZE_LETTER_EXTRA_PAPER = 48; + const PAPERSIZE_LEGAL_EXTRA_PAPER = 49; + const PAPERSIZE_TABLOID_EXTRA_PAPER = 50; + const PAPERSIZE_A4_EXTRA_PAPER = 51; + const PAPERSIZE_LETTER_TRANSVERSE_PAPER = 52; + const PAPERSIZE_A4_TRANSVERSE_PAPER = 53; + const PAPERSIZE_LETTER_EXTRA_TRANSVERSE_PAPER = 54; + const PAPERSIZE_SUPERA_SUPERA_A4_PAPER = 55; + const PAPERSIZE_SUPERB_SUPERB_A3_PAPER = 56; + const PAPERSIZE_LETTER_PLUS_PAPER = 57; + const PAPERSIZE_A4_PLUS_PAPER = 58; + const PAPERSIZE_A5_TRANSVERSE_PAPER = 59; + const PAPERSIZE_JIS_B5_TRANSVERSE_PAPER = 60; + const PAPERSIZE_A3_EXTRA_PAPER = 61; + const PAPERSIZE_A5_EXTRA_PAPER = 62; + const PAPERSIZE_ISO_B5_EXTRA_PAPER = 63; + const PAPERSIZE_A2_PAPER = 64; + const PAPERSIZE_A3_TRANSVERSE_PAPER = 65; + const PAPERSIZE_A3_EXTRA_TRANSVERSE_PAPER = 66; + + /* Page orientation */ + const ORIENTATION_DEFAULT = 'default'; + const ORIENTATION_LANDSCAPE = 'landscape'; + const ORIENTATION_PORTRAIT = 'portrait'; + + /* Print Range Set Method */ + const SETPRINTRANGE_OVERWRITE = 'O'; + const SETPRINTRANGE_INSERT = 'I'; + + + /** + * Paper size + * + * @var int + */ + private $_paperSize = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER; + + /** + * Orientation + * + * @var string + */ + private $_orientation = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT; + + /** + * Scale (Print Scale) + * + * Print scaling. Valid values range from 10 to 400 + * This setting is overridden when fitToWidth and/or fitToHeight are in use + * + * @var int? + */ + private $_scale = 100; + + /** + * Fit To Page + * Whether scale or fitToWith / fitToHeight applies + * + * @var boolean + */ + private $_fitToPage = FALSE; + + /** + * Fit To Height + * Number of vertical pages to fit on + * + * @var int? + */ + private $_fitToHeight = 1; + + /** + * Fit To Width + * Number of horizontal pages to fit on + * + * @var int? + */ + private $_fitToWidth = 1; + + /** + * Columns to repeat at left + * + * @var array Containing start column and end column, empty array if option unset + */ + private $_columnsToRepeatAtLeft = array('', ''); + + /** + * Rows to repeat at top + * + * @var array Containing start row number and end row number, empty array if option unset + */ + private $_rowsToRepeatAtTop = array(0, 0); + + /** + * Center page horizontally + * + * @var boolean + */ + private $_horizontalCentered = FALSE; + + /** + * Center page vertically + * + * @var boolean + */ + private $_verticalCentered = FALSE; + + /** + * Print area + * + * @var string + */ + private $_printArea = NULL; + + /** + * First page number + * + * @var int + */ + private $_firstPageNumber = NULL; + + /** + * Create a new PHPExcel_Worksheet_PageSetup + */ + public function __construct() + { + } + + /** + * Get Paper Size + * + * @return int + */ + public function getPaperSize() { + return $this->_paperSize; + } + + /** + * Set Paper Size + * + * @param int $pValue + * @return PHPExcel_Worksheet_PageSetup + */ + public function setPaperSize($pValue = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER) { + $this->_paperSize = $pValue; + return $this; + } + + /** + * Get Orientation + * + * @return string + */ + public function getOrientation() { + return $this->_orientation; + } + + /** + * Set Orientation + * + * @param string $pValue + * @return PHPExcel_Worksheet_PageSetup + */ + public function setOrientation($pValue = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) { + $this->_orientation = $pValue; + return $this; + } + + /** + * Get Scale + * + * @return int? + */ + public function getScale() { + return $this->_scale; + } + + /** + * Set Scale + * + * Print scaling. Valid values range from 10 to 400 + * This setting is overridden when fitToWidth and/or fitToHeight are in use + * + * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so scaling applies rather than fitToHeight / fitToWidth + * @return PHPExcel_Worksheet_PageSetup + * @throws PHPExcel_Exception + */ + public function setScale($pValue = 100, $pUpdate = true) { + // Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface, + // but it is apparently still able to handle any scale >= 0, where 0 results in 100 + if (($pValue >= 0) || is_null($pValue)) { + $this->_scale = $pValue; + if ($pUpdate) { + $this->_fitToPage = false; + } + } else { + throw new PHPExcel_Exception("Scale must not be negative"); + } + return $this; + } + + /** + * Get Fit To Page + * + * @return boolean + */ + public function getFitToPage() { + return $this->_fitToPage; + } + + /** + * Set Fit To Page + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_PageSetup + */ + public function setFitToPage($pValue = TRUE) { + $this->_fitToPage = $pValue; + return $this; + } + + /** + * Get Fit To Height + * + * @return int? + */ + public function getFitToHeight() { + return $this->_fitToHeight; + } + + /** + * Set Fit To Height + * + * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so it applies rather than scaling + * @return PHPExcel_Worksheet_PageSetup + */ + public function setFitToHeight($pValue = 1, $pUpdate = TRUE) { + $this->_fitToHeight = $pValue; + if ($pUpdate) { + $this->_fitToPage = TRUE; + } + return $this; + } + + /** + * Get Fit To Width + * + * @return int? + */ + public function getFitToWidth() { + return $this->_fitToWidth; + } + + /** + * Set Fit To Width + * + * @param int? $pValue + * @param boolean $pUpdate Update fitToPage so it applies rather than scaling + * @return PHPExcel_Worksheet_PageSetup + */ + public function setFitToWidth($pValue = 1, $pUpdate = TRUE) { + $this->_fitToWidth = $pValue; + if ($pUpdate) { + $this->_fitToPage = TRUE; + } + return $this; + } + + /** + * Is Columns to repeat at left set? + * + * @return boolean + */ + public function isColumnsToRepeatAtLeftSet() { + if (is_array($this->_columnsToRepeatAtLeft)) { + if ($this->_columnsToRepeatAtLeft[0] != '' && $this->_columnsToRepeatAtLeft[1] != '') { + return true; + } + } + + return false; + } + + /** + * Get Columns to repeat at left + * + * @return array Containing start column and end column, empty array if option unset + */ + public function getColumnsToRepeatAtLeft() { + return $this->_columnsToRepeatAtLeft; + } + + /** + * Set Columns to repeat at left + * + * @param array $pValue Containing start column and end column, empty array if option unset + * @return PHPExcel_Worksheet_PageSetup + */ + public function setColumnsToRepeatAtLeft($pValue = null) { + if (is_array($pValue)) { + $this->_columnsToRepeatAtLeft = $pValue; + } + return $this; + } + + /** + * Set Columns to repeat at left by start and end + * + * @param string $pStart + * @param string $pEnd + * @return PHPExcel_Worksheet_PageSetup + */ + public function setColumnsToRepeatAtLeftByStartAndEnd($pStart = 'A', $pEnd = 'A') { + $this->_columnsToRepeatAtLeft = array($pStart, $pEnd); + return $this; + } + + /** + * Is Rows to repeat at top set? + * + * @return boolean + */ + public function isRowsToRepeatAtTopSet() { + if (is_array($this->_rowsToRepeatAtTop)) { + if ($this->_rowsToRepeatAtTop[0] != 0 && $this->_rowsToRepeatAtTop[1] != 0) { + return true; + } + } + + return false; + } + + /** + * Get Rows to repeat at top + * + * @return array Containing start column and end column, empty array if option unset + */ + public function getRowsToRepeatAtTop() { + return $this->_rowsToRepeatAtTop; + } + + /** + * Set Rows to repeat at top + * + * @param array $pValue Containing start column and end column, empty array if option unset + * @return PHPExcel_Worksheet_PageSetup + */ + public function setRowsToRepeatAtTop($pValue = null) { + if (is_array($pValue)) { + $this->_rowsToRepeatAtTop = $pValue; + } + return $this; + } + + /** + * Set Rows to repeat at top by start and end + * + * @param int $pStart + * @param int $pEnd + * @return PHPExcel_Worksheet_PageSetup + */ + public function setRowsToRepeatAtTopByStartAndEnd($pStart = 1, $pEnd = 1) { + $this->_rowsToRepeatAtTop = array($pStart, $pEnd); + return $this; + } + + /** + * Get center page horizontally + * + * @return bool + */ + public function getHorizontalCentered() { + return $this->_horizontalCentered; + } + + /** + * Set center page horizontally + * + * @param bool $value + * @return PHPExcel_Worksheet_PageSetup + */ + public function setHorizontalCentered($value = false) { + $this->_horizontalCentered = $value; + return $this; + } + + /** + * Get center page vertically + * + * @return bool + */ + public function getVerticalCentered() { + return $this->_verticalCentered; + } + + /** + * Set center page vertically + * + * @param bool $value + * @return PHPExcel_Worksheet_PageSetup + */ + public function setVerticalCentered($value = false) { + $this->_verticalCentered = $value; + return $this; + } + + /** + * Get print area + * + * @param int $index Identifier for a specific print area range if several ranges have been set + * Default behaviour, or a index value of 0, will return all ranges as a comma-separated string + * Otherwise, the specific range identified by the value of $index will be returned + * Print areas are numbered from 1 + * @throws PHPExcel_Exception + * @return string + */ + public function getPrintArea($index = 0) { + if ($index == 0) { + return $this->_printArea; + } + $printAreas = explode(',',$this->_printArea); + if (isset($printAreas[$index-1])) { + return $printAreas[$index-1]; + } + throw new PHPExcel_Exception("Requested Print Area does not exist"); + } + + /** + * Is print area set? + * + * @param int $index Identifier for a specific print area range if several ranges have been set + * Default behaviour, or an index value of 0, will identify whether any print range is set + * Otherwise, existence of the range identified by the value of $index will be returned + * Print areas are numbered from 1 + * @return boolean + */ + public function isPrintAreaSet($index = 0) { + if ($index == 0) { + return !is_null($this->_printArea); + } + $printAreas = explode(',',$this->_printArea); + return isset($printAreas[$index-1]); + } + + /** + * Clear a print area + * + * @param int $index Identifier for a specific print area range if several ranges have been set + * Default behaviour, or an index value of 0, will clear all print ranges that are set + * Otherwise, the range identified by the value of $index will be removed from the series + * Print areas are numbered from 1 + * @return PHPExcel_Worksheet_PageSetup + */ + public function clearPrintArea($index = 0) { + if ($index == 0) { + $this->_printArea = NULL; + } else { + $printAreas = explode(',',$this->_printArea); + if (isset($printAreas[$index-1])) { + unset($printAreas[$index-1]); + $this->_printArea = implode(',',$printAreas); + } + } + + return $this; + } + + /** + * Set print area. e.g. 'A1:D10' or 'A1:D10,G5:M20' + * + * @param string $value + * @param int $index Identifier for a specific print area range allowing several ranges to be set + * When the method is "O"verwrite, then a positive integer index will overwrite that indexed + * entry in the print areas list; a negative index value will identify which entry to + * overwrite working bacward through the print area to the list, with the last entry as -1. + * Specifying an index value of 0, will overwrite <b>all</b> existing print ranges. + * When the method is "I"nsert, then a positive index will insert after that indexed entry in + * the print areas list, while a negative index will insert before the indexed entry. + * Specifying an index value of 0, will always append the new print range at the end of the + * list. + * Print areas are numbered from 1 + * @param string $method Determines the method used when setting multiple print areas + * Default behaviour, or the "O" method, overwrites existing print area + * The "I" method, inserts the new print area before any specified index, or at the end of the list + * @return PHPExcel_Worksheet_PageSetup + * @throws PHPExcel_Exception + */ + public function setPrintArea($value, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE) { + if (strpos($value,'!') !== false) { + throw new PHPExcel_Exception('Cell coordinate must not specify a worksheet.'); + } elseif (strpos($value,':') === false) { + throw new PHPExcel_Exception('Cell coordinate must be a range of cells.'); + } elseif (strpos($value,'$') !== false) { + throw new PHPExcel_Exception('Cell coordinate must not be absolute.'); + } + $value = strtoupper($value); + + if ($method == self::SETPRINTRANGE_OVERWRITE) { + if ($index == 0) { + $this->_printArea = $value; + } else { + $printAreas = explode(',',$this->_printArea); + if($index < 0) { + $index = count($printAreas) - abs($index) + 1; + } + if (($index <= 0) || ($index > count($printAreas))) { + throw new PHPExcel_Exception('Invalid index for setting print range.'); + } + $printAreas[$index-1] = $value; + $this->_printArea = implode(',',$printAreas); + } + } elseif($method == self::SETPRINTRANGE_INSERT) { + if ($index == 0) { + $this->_printArea .= ($this->_printArea == '') ? $value : ','.$value; + } else { + $printAreas = explode(',',$this->_printArea); + if($index < 0) { + $index = abs($index) - 1; + } + if ($index > count($printAreas)) { + throw new PHPExcel_Exception('Invalid index for setting print range.'); + } + $printAreas = array_merge(array_slice($printAreas,0,$index),array($value),array_slice($printAreas,$index)); + $this->_printArea = implode(',',$printAreas); + } + } else { + throw new PHPExcel_Exception('Invalid method for setting print range.'); + } + + return $this; + } + + /** + * Add a new print area (e.g. 'A1:D10' or 'A1:D10,G5:M20') to the list of print areas + * + * @param string $value + * @param int $index Identifier for a specific print area range allowing several ranges to be set + * A positive index will insert after that indexed entry in the print areas list, while a + * negative index will insert before the indexed entry. + * Specifying an index value of 0, will always append the new print range at the end of the + * list. + * Print areas are numbered from 1 + * @return PHPExcel_Worksheet_PageSetup + * @throws PHPExcel_Exception + */ + public function addPrintArea($value, $index = -1) { + return $this->setPrintArea($value, $index, self::SETPRINTRANGE_INSERT); + } + + /** + * Set print area + * + * @param int $column1 Column 1 + * @param int $row1 Row 1 + * @param int $column2 Column 2 + * @param int $row2 Row 2 + * @param int $index Identifier for a specific print area range allowing several ranges to be set + * When the method is "O"verwrite, then a positive integer index will overwrite that indexed + * entry in the print areas list; a negative index value will identify which entry to + * overwrite working bacward through the print area to the list, with the last entry as -1. + * Specifying an index value of 0, will overwrite <b>all</b> existing print ranges. + * When the method is "I"nsert, then a positive index will insert after that indexed entry in + * the print areas list, while a negative index will insert before the indexed entry. + * Specifying an index value of 0, will always append the new print range at the end of the + * list. + * Print areas are numbered from 1 + * @param string $method Determines the method used when setting multiple print areas + * Default behaviour, or the "O" method, overwrites existing print area + * The "I" method, inserts the new print area before any specified index, or at the end of the list + * @return PHPExcel_Worksheet_PageSetup + * @throws PHPExcel_Exception + */ + public function setPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = 0, $method = self::SETPRINTRANGE_OVERWRITE) + { + return $this->setPrintArea(PHPExcel_Cell::stringFromColumnIndex($column1) . $row1 . ':' . PHPExcel_Cell::stringFromColumnIndex($column2) . $row2, $index, $method); + } + + /** + * Add a new print area to the list of print areas + * + * @param int $column1 Start Column for the print area + * @param int $row1 Start Row for the print area + * @param int $column2 End Column for the print area + * @param int $row2 End Row for the print area + * @param int $index Identifier for a specific print area range allowing several ranges to be set + * A positive index will insert after that indexed entry in the print areas list, while a + * negative index will insert before the indexed entry. + * Specifying an index value of 0, will always append the new print range at the end of the + * list. + * Print areas are numbered from 1 + * @return PHPExcel_Worksheet_PageSetup + * @throws PHPExcel_Exception + */ + public function addPrintAreaByColumnAndRow($column1, $row1, $column2, $row2, $index = -1) + { + return $this->setPrintArea(PHPExcel_Cell::stringFromColumnIndex($column1) . $row1 . ':' . PHPExcel_Cell::stringFromColumnIndex($column2) . $row2, $index, self::SETPRINTRANGE_INSERT); + } + + /** + * Get first page number + * + * @return int + */ + public function getFirstPageNumber() { + return $this->_firstPageNumber; + } + + /** + * Set first page number + * + * @param int $value + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function setFirstPageNumber($value = null) { + $this->_firstPageNumber = $value; + return $this; + } + + /** + * Reset first page number + * + * @return PHPExcel_Worksheet_HeaderFooter + */ + public function resetFirstPageNumber() { + return $this->setFirstPageNumber(null); + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Protection.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Protection.php new file mode 100755 index 0000000..e9d6bb6 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Protection.php @@ -0,0 +1,545 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_Protection + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_Protection +{ + /** + * Sheet + * + * @var boolean + */ + private $_sheet = false; + + /** + * Objects + * + * @var boolean + */ + private $_objects = false; + + /** + * Scenarios + * + * @var boolean + */ + private $_scenarios = false; + + /** + * Format cells + * + * @var boolean + */ + private $_formatCells = false; + + /** + * Format columns + * + * @var boolean + */ + private $_formatColumns = false; + + /** + * Format rows + * + * @var boolean + */ + private $_formatRows = false; + + /** + * Insert columns + * + * @var boolean + */ + private $_insertColumns = false; + + /** + * Insert rows + * + * @var boolean + */ + private $_insertRows = false; + + /** + * Insert hyperlinks + * + * @var boolean + */ + private $_insertHyperlinks = false; + + /** + * Delete columns + * + * @var boolean + */ + private $_deleteColumns = false; + + /** + * Delete rows + * + * @var boolean + */ + private $_deleteRows = false; + + /** + * Select locked cells + * + * @var boolean + */ + private $_selectLockedCells = false; + + /** + * Sort + * + * @var boolean + */ + private $_sort = false; + + /** + * AutoFilter + * + * @var boolean + */ + private $_autoFilter = false; + + /** + * Pivot tables + * + * @var boolean + */ + private $_pivotTables = false; + + /** + * Select unlocked cells + * + * @var boolean + */ + private $_selectUnlockedCells = false; + + /** + * Password + * + * @var string + */ + private $_password = ''; + + /** + * Create a new PHPExcel_Worksheet_Protection + */ + public function __construct() + { + } + + /** + * Is some sort of protection enabled? + * + * @return boolean + */ + function isProtectionEnabled() { + return $this->_sheet || + $this->_objects || + $this->_scenarios || + $this->_formatCells || + $this->_formatColumns || + $this->_formatRows || + $this->_insertColumns || + $this->_insertRows || + $this->_insertHyperlinks || + $this->_deleteColumns || + $this->_deleteRows || + $this->_selectLockedCells || + $this->_sort || + $this->_autoFilter || + $this->_pivotTables || + $this->_selectUnlockedCells; + } + + /** + * Get Sheet + * + * @return boolean + */ + function getSheet() { + return $this->_sheet; + } + + /** + * Set Sheet + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setSheet($pValue = false) { + $this->_sheet = $pValue; + return $this; + } + + /** + * Get Objects + * + * @return boolean + */ + function getObjects() { + return $this->_objects; + } + + /** + * Set Objects + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setObjects($pValue = false) { + $this->_objects = $pValue; + return $this; + } + + /** + * Get Scenarios + * + * @return boolean + */ + function getScenarios() { + return $this->_scenarios; + } + + /** + * Set Scenarios + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setScenarios($pValue = false) { + $this->_scenarios = $pValue; + return $this; + } + + /** + * Get FormatCells + * + * @return boolean + */ + function getFormatCells() { + return $this->_formatCells; + } + + /** + * Set FormatCells + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setFormatCells($pValue = false) { + $this->_formatCells = $pValue; + return $this; + } + + /** + * Get FormatColumns + * + * @return boolean + */ + function getFormatColumns() { + return $this->_formatColumns; + } + + /** + * Set FormatColumns + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setFormatColumns($pValue = false) { + $this->_formatColumns = $pValue; + return $this; + } + + /** + * Get FormatRows + * + * @return boolean + */ + function getFormatRows() { + return $this->_formatRows; + } + + /** + * Set FormatRows + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setFormatRows($pValue = false) { + $this->_formatRows = $pValue; + return $this; + } + + /** + * Get InsertColumns + * + * @return boolean + */ + function getInsertColumns() { + return $this->_insertColumns; + } + + /** + * Set InsertColumns + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setInsertColumns($pValue = false) { + $this->_insertColumns = $pValue; + return $this; + } + + /** + * Get InsertRows + * + * @return boolean + */ + function getInsertRows() { + return $this->_insertRows; + } + + /** + * Set InsertRows + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setInsertRows($pValue = false) { + $this->_insertRows = $pValue; + return $this; + } + + /** + * Get InsertHyperlinks + * + * @return boolean + */ + function getInsertHyperlinks() { + return $this->_insertHyperlinks; + } + + /** + * Set InsertHyperlinks + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setInsertHyperlinks($pValue = false) { + $this->_insertHyperlinks = $pValue; + return $this; + } + + /** + * Get DeleteColumns + * + * @return boolean + */ + function getDeleteColumns() { + return $this->_deleteColumns; + } + + /** + * Set DeleteColumns + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setDeleteColumns($pValue = false) { + $this->_deleteColumns = $pValue; + return $this; + } + + /** + * Get DeleteRows + * + * @return boolean + */ + function getDeleteRows() { + return $this->_deleteRows; + } + + /** + * Set DeleteRows + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setDeleteRows($pValue = false) { + $this->_deleteRows = $pValue; + return $this; + } + + /** + * Get SelectLockedCells + * + * @return boolean + */ + function getSelectLockedCells() { + return $this->_selectLockedCells; + } + + /** + * Set SelectLockedCells + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setSelectLockedCells($pValue = false) { + $this->_selectLockedCells = $pValue; + return $this; + } + + /** + * Get Sort + * + * @return boolean + */ + function getSort() { + return $this->_sort; + } + + /** + * Set Sort + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setSort($pValue = false) { + $this->_sort = $pValue; + return $this; + } + + /** + * Get AutoFilter + * + * @return boolean + */ + function getAutoFilter() { + return $this->_autoFilter; + } + + /** + * Set AutoFilter + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setAutoFilter($pValue = false) { + $this->_autoFilter = $pValue; + return $this; + } + + /** + * Get PivotTables + * + * @return boolean + */ + function getPivotTables() { + return $this->_pivotTables; + } + + /** + * Set PivotTables + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setPivotTables($pValue = false) { + $this->_pivotTables = $pValue; + return $this; + } + + /** + * Get SelectUnlockedCells + * + * @return boolean + */ + function getSelectUnlockedCells() { + return $this->_selectUnlockedCells; + } + + /** + * Set SelectUnlockedCells + * + * @param boolean $pValue + * @return PHPExcel_Worksheet_Protection + */ + function setSelectUnlockedCells($pValue = false) { + $this->_selectUnlockedCells = $pValue; + return $this; + } + + /** + * Get Password (hashed) + * + * @return string + */ + function getPassword() { + return $this->_password; + } + + /** + * Set Password + * + * @param string $pValue + * @param boolean $pAlreadyHashed If the password has already been hashed, set this to true + * @return PHPExcel_Worksheet_Protection + */ + function setPassword($pValue = '', $pAlreadyHashed = false) { + if (!$pAlreadyHashed) { + $pValue = PHPExcel_Shared_PasswordHasher::hashPassword($pValue); + } + $this->_password = $pValue; + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Row.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Row.php new file mode 100755 index 0000000..b02f37f --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/Row.php @@ -0,0 +1,90 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_Row + * + * Represents a row in PHPExcel_Worksheet, used by PHPExcel_Worksheet_RowIterator + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_Row +{ + /** + * PHPExcel_Worksheet + * + * @var PHPExcel_Worksheet + */ + private $_parent; + + /** + * Row index + * + * @var int + */ + private $_rowIndex = 0; + + /** + * Create a new row + * + * @param PHPExcel_Worksheet $parent + * @param int $rowIndex + */ + public function __construct(PHPExcel_Worksheet $parent = null, $rowIndex = 1) { + // Set parent and row index + $this->_parent = $parent; + $this->_rowIndex = $rowIndex; + } + + /** + * Destructor + */ + public function __destruct() { + unset($this->_parent); + } + + /** + * Get row index + * + * @return int + */ + public function getRowIndex() { + return $this->_rowIndex; + } + + /** + * Get cell iterator + * + * @return PHPExcel_Worksheet_CellIterator + */ + public function getCellIterator() { + return new PHPExcel_Worksheet_CellIterator($this->_parent, $this->_rowIndex); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/RowDimension.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/RowDimension.php new file mode 100755 index 0000000..9cec333 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/RowDimension.php @@ -0,0 +1,265 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_RowDimension + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_RowDimension +{ + /** + * Row index + * + * @var int + */ + private $_rowIndex; + + /** + * Row height (in pt) + * + * When this is set to a negative value, the row height should be ignored by IWriter + * + * @var double + */ + private $_rowHeight = -1; + + /** + * ZeroHeight for Row? + * + * @var bool + */ + private $_zeroHeight = false; + + /** + * Visible? + * + * @var bool + */ + private $_visible = true; + + /** + * Outline level + * + * @var int + */ + private $_outlineLevel = 0; + + /** + * Collapsed + * + * @var bool + */ + private $_collapsed = false; + + /** + * Index to cellXf. Null value means row has no explicit cellXf format. + * + * @var int|null + */ + private $_xfIndex; + + /** + * Create a new PHPExcel_Worksheet_RowDimension + * + * @param int $pIndex Numeric row index + */ + public function __construct($pIndex = 0) + { + // Initialise values + $this->_rowIndex = $pIndex; + + // set row dimension as unformatted by default + $this->_xfIndex = null; + } + + /** + * Get Row Index + * + * @return int + */ + public function getRowIndex() { + return $this->_rowIndex; + } + + /** + * Set Row Index + * + * @param int $pValue + * @return PHPExcel_Worksheet_RowDimension + */ + public function setRowIndex($pValue) { + $this->_rowIndex = $pValue; + return $this; + } + + /** + * Get Row Height + * + * @return double + */ + public function getRowHeight() { + return $this->_rowHeight; + } + + /** + * Set Row Height + * + * @param double $pValue + * @return PHPExcel_Worksheet_RowDimension + */ + public function setRowHeight($pValue = -1) { + $this->_rowHeight = $pValue; + return $this; + } + + /** + * Get ZeroHeight + * + * @return bool + */ + public function getzeroHeight() { + return $this->_zeroHeight; + } + + /** + * Set ZeroHeight + * + * @param bool $pValue + * @return PHPExcel_Worksheet_RowDimension + */ + public function setzeroHeight($pValue = false) { + $this->_zeroHeight = $pValue; + return $this; + } + + /** + * Get Visible + * + * @return bool + */ + public function getVisible() { + return $this->_visible; + } + + /** + * Set Visible + * + * @param bool $pValue + * @return PHPExcel_Worksheet_RowDimension + */ + public function setVisible($pValue = true) { + $this->_visible = $pValue; + return $this; + } + + /** + * Get Outline Level + * + * @return int + */ + public function getOutlineLevel() { + return $this->_outlineLevel; + } + + /** + * Set Outline Level + * + * Value must be between 0 and 7 + * + * @param int $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_RowDimension + */ + public function setOutlineLevel($pValue) { + if ($pValue < 0 || $pValue > 7) { + throw new PHPExcel_Exception("Outline level must range between 0 and 7."); + } + + $this->_outlineLevel = $pValue; + return $this; + } + + /** + * Get Collapsed + * + * @return bool + */ + public function getCollapsed() { + return $this->_collapsed; + } + + /** + * Set Collapsed + * + * @param bool $pValue + * @return PHPExcel_Worksheet_RowDimension + */ + public function setCollapsed($pValue = true) { + $this->_collapsed = $pValue; + return $this; + } + + /** + * Get index to cellXf + * + * @return int + */ + public function getXfIndex() + { + return $this->_xfIndex; + } + + /** + * Set index to cellXf + * + * @param int $pValue + * @return PHPExcel_Worksheet_RowDimension + */ + public function setXfIndex($pValue = 0) + { + $this->_xfIndex = $pValue; + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/RowIterator.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/RowIterator.php new file mode 100755 index 0000000..72eca7d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/RowIterator.php @@ -0,0 +1,148 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_RowIterator + * + * Used to iterate rows in a PHPExcel_Worksheet + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_RowIterator implements Iterator +{ + /** + * PHPExcel_Worksheet to iterate + * + * @var PHPExcel_Worksheet + */ + private $_subject; + + /** + * Current iterator position + * + * @var int + */ + private $_position = 1; + + /** + * Start position + * + * @var int + */ + private $_startRow = 1; + + + /** + * Create a new row iterator + * + * @param PHPExcel_Worksheet $subject The worksheet to iterate over + * @param integer $startRow The row number at which to start iterating + */ + public function __construct(PHPExcel_Worksheet $subject = null, $startRow = 1) { + // Set subject + $this->_subject = $subject; + $this->resetStart($startRow); + } + + /** + * Destructor + */ + public function __destruct() { + unset($this->_subject); + } + + /** + * (Re)Set the start row and the current row pointer + * + * @param integer $startRow The row number at which to start iterating + */ + public function resetStart($startRow = 1) { + $this->_startRow = $startRow; + $this->seek($startRow); + } + + /** + * Set the row pointer to the selected row + * + * @param integer $row The row number to set the current pointer at + */ + public function seek($row = 1) { + $this->_position = $row; + } + + /** + * Rewind the iterator to the starting row + */ + public function rewind() { + $this->_position = $this->_startRow; + } + + /** + * Return the current row in this worksheet + * + * @return PHPExcel_Worksheet_Row + */ + public function current() { + return new PHPExcel_Worksheet_Row($this->_subject, $this->_position); + } + + /** + * Return the current iterator key + * + * @return int + */ + public function key() { + return $this->_position; + } + + /** + * Set the iterator to its next value + */ + public function next() { + ++$this->_position; + } + + /** + * Set the iterator to its previous value + */ + public function prev() { + if ($this->_position > 1) + --$this->_position; + } + + /** + * Indicate if more rows exist in the worksheet + * + * @return boolean + */ + public function valid() { + return $this->_position <= $this->_subject->getHighestRow(); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/SheetView.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/SheetView.php new file mode 100755 index 0000000..96d5b43 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Worksheet/SheetView.php @@ -0,0 +1,188 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Worksheet_SheetView + * + * @category PHPExcel + * @package PHPExcel_Worksheet + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Worksheet_SheetView +{ + + /* Sheet View types */ + const SHEETVIEW_NORMAL = 'normal'; + const SHEETVIEW_PAGE_LAYOUT = 'pageLayout'; + const SHEETVIEW_PAGE_BREAK_PREVIEW = 'pageBreakPreview'; + + private static $_sheetViewTypes = array( + self::SHEETVIEW_NORMAL, + self::SHEETVIEW_PAGE_LAYOUT, + self::SHEETVIEW_PAGE_BREAK_PREVIEW, + ); + + /** + * ZoomScale + * + * Valid values range from 10 to 400. + * + * @var int + */ + private $_zoomScale = 100; + + /** + * ZoomScaleNormal + * + * Valid values range from 10 to 400. + * + * @var int + */ + private $_zoomScaleNormal = 100; + + /** + * View + * + * Valid values range from 10 to 400. + * + * @var string + */ + private $_sheetviewType = self::SHEETVIEW_NORMAL; + + /** + * Create a new PHPExcel_Worksheet_SheetView + */ + public function __construct() + { + } + + /** + * Get ZoomScale + * + * @return int + */ + public function getZoomScale() { + return $this->_zoomScale; + } + + /** + * Set ZoomScale + * + * Valid values range from 10 to 400. + * + * @param int $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_SheetView + */ + public function setZoomScale($pValue = 100) { + // Microsoft Office Excel 2007 only allows setting a scale between 10 and 400 via the user interface, + // but it is apparently still able to handle any scale >= 1 + if (($pValue >= 1) || is_null($pValue)) { + $this->_zoomScale = $pValue; + } else { + throw new PHPExcel_Exception("Scale must be greater than or equal to 1."); + } + return $this; + } + + /** + * Get ZoomScaleNormal + * + * @return int + */ + public function getZoomScaleNormal() { + return $this->_zoomScaleNormal; + } + + /** + * Set ZoomScale + * + * Valid values range from 10 to 400. + * + * @param int $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_SheetView + */ + public function setZoomScaleNormal($pValue = 100) { + if (($pValue >= 1) || is_null($pValue)) { + $this->_zoomScaleNormal = $pValue; + } else { + throw new PHPExcel_Exception("Scale must be greater than or equal to 1."); + } + return $this; + } + + /** + * Get View + * + * @return string + */ + public function getView() { + return $this->_sheetviewType; + } + + /** + * Set View + * + * Valid values are + * 'normal' self::SHEETVIEW_NORMAL + * 'pageLayout' self::SHEETVIEW_PAGE_LAYOUT + * 'pageBreakPreview' self::SHEETVIEW_PAGE_BREAK_PREVIEW + * + * @param string $pValue + * @throws PHPExcel_Exception + * @return PHPExcel_Worksheet_SheetView + */ + public function setView($pValue = NULL) { + // MS Excel 2007 allows setting the view to 'normal', 'pageLayout' or 'pageBreakPreview' + // via the user interface + if ($pValue === NULL) + $pValue = self::SHEETVIEW_NORMAL; + if (in_array($pValue, self::$_sheetViewTypes)) { + $this->_sheetviewType = $pValue; + } else { + throw new PHPExcel_Exception("Invalid sheetview layout type."); + } + + return $this; + } + + /** + * Implement PHP __clone to create a deep clone, not just a shallow copy. + */ + public function __clone() { + $vars = get_object_vars($this); + foreach ($vars as $key => $value) { + if (is_object($value)) { + $this->$key = clone $value; + } else { + $this->$key = $value; + } + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/WorksheetIterator.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/WorksheetIterator.php new file mode 100755 index 0000000..0260357 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/WorksheetIterator.php @@ -0,0 +1,118 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_WorksheetIterator + * + * Used to iterate worksheets in PHPExcel + * + * @category PHPExcel + * @package PHPExcel + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_WorksheetIterator implements Iterator +{ + /** + * Spreadsheet to iterate + * + * @var PHPExcel + */ + private $_subject; + + /** + * Current iterator position + * + * @var int + */ + private $_position = 0; + + /** + * Create a new worksheet iterator + * + * @param PHPExcel $subject + */ + public function __construct(PHPExcel $subject = null) + { + // Set subject + $this->_subject = $subject; + } + + /** + * Destructor + */ + public function __destruct() + { + unset($this->_subject); + } + + /** + * Rewind iterator + */ + public function rewind() + { + $this->_position = 0; + } + + /** + * Current PHPExcel_Worksheet + * + * @return PHPExcel_Worksheet + */ + public function current() + { + return $this->_subject->getSheet($this->_position); + } + + /** + * Current key + * + * @return int + */ + public function key() + { + return $this->_position; + } + + /** + * Next value + */ + public function next() + { + ++$this->_position; + } + + /** + * More PHPExcel_Worksheet instances available? + * + * @return boolean + */ + public function valid() + { + return $this->_position < $this->_subject->getSheetCount(); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Abstract.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Abstract.php new file mode 100755 index 0000000..ec19aa0 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Abstract.php @@ -0,0 +1,158 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Abstract + * + * @category PHPExcel + * @package PHPExcel_Writer + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +abstract class PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter +{ + /** + * Write charts that are defined in the workbook? + * Identifies whether the Writer should write definitions for any charts that exist in the PHPExcel object; + * + * @var boolean + */ + protected $_includeCharts = FALSE; + + /** + * Pre-calculate formulas + * Forces PHPExcel to recalculate all formulae in a workbook when saving, so that the pre-calculated values are + * immediately available to MS Excel or other office spreadsheet viewer when opening the file + * + * @var boolean + */ + protected $_preCalculateFormulas = TRUE; + + /** + * Use disk caching where possible? + * + * @var boolean + */ + protected $_useDiskCaching = FALSE; + + /** + * Disk caching directory + * + * @var string + */ + protected $_diskCachingDirectory = './'; + + /** + * Write charts in workbook? + * If this is true, then the Writer will write definitions for any charts that exist in the PHPExcel object. + * If false (the default) it will ignore any charts defined in the PHPExcel object. + * + * @return boolean + */ + public function getIncludeCharts() { + return $this->_includeCharts; + } + + /** + * Set write charts in workbook + * Set to true, to advise the Writer to include any charts that exist in the PHPExcel object. + * Set to false (the default) to ignore charts. + * + * @param boolean $pValue + * @return PHPExcel_Writer_IWriter + */ + public function setIncludeCharts($pValue = FALSE) { + $this->_includeCharts = (boolean) $pValue; + return $this; + } + + /** + * Get Pre-Calculate Formulas flag + * If this is true (the default), then the writer will recalculate all formulae in a workbook when saving, + * so that the pre-calculated values are immediately available to MS Excel or other office spreadsheet + * viewer when opening the file + * If false, then formulae are not calculated on save. This is faster for saving in PHPExcel, but slower + * when opening the resulting file in MS Excel, because Excel has to recalculate the formulae itself + * + * @return boolean + */ + public function getPreCalculateFormulas() { + return $this->_preCalculateFormulas; + } + + /** + * Set Pre-Calculate Formulas + * Set to true (the default) to advise the Writer to calculate all formulae on save + * Set to false to prevent precalculation of formulae on save. + * + * @param boolean $pValue Pre-Calculate Formulas? + * @return PHPExcel_Writer_IWriter + */ + public function setPreCalculateFormulas($pValue = TRUE) { + $this->_preCalculateFormulas = (boolean) $pValue; + return $this; + } + + /** + * Get use disk caching where possible? + * + * @return boolean + */ + public function getUseDiskCaching() { + return $this->_useDiskCaching; + } + + /** + * Set use disk caching where possible? + * + * @param boolean $pValue + * @param string $pDirectory Disk caching directory + * @throws PHPExcel_Writer_Exception when directory does not exist + * @return PHPExcel_Writer_Excel2007 + */ + public function setUseDiskCaching($pValue = FALSE, $pDirectory = NULL) { + $this->_useDiskCaching = $pValue; + + if ($pDirectory !== NULL) { + if (is_dir($pDirectory)) { + $this->_diskCachingDirectory = $pDirectory; + } else { + throw new PHPExcel_Writer_Exception("Directory does not exist: $pDirectory"); + } + } + return $this; + } + + /** + * Get disk caching directory + * + * @return string + */ + public function getDiskCachingDirectory() { + return $this->_diskCachingDirectory; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/CSV.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/CSV.php new file mode 100755 index 0000000..0770c1d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/CSV.php @@ -0,0 +1,313 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_CSV + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_CSV + * + * @category PHPExcel + * @package PHPExcel_Writer_CSV + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_CSV extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { + /** + * PHPExcel object + * + * @var PHPExcel + */ + private $_phpExcel; + + /** + * Delimiter + * + * @var string + */ + private $_delimiter = ','; + + /** + * Enclosure + * + * @var string + */ + private $_enclosure = '"'; + + /** + * Line ending + * + * @var string + */ + private $_lineEnding = PHP_EOL; + + /** + * Sheet index to write + * + * @var int + */ + private $_sheetIndex = 0; + + /** + * Whether to write a BOM (for UTF8). + * + * @var boolean + */ + private $_useBOM = false; + + /** + * Whether to write a fully Excel compatible CSV file. + * + * @var boolean + */ + private $_excelCompatibility = false; + + /** + * Create a new PHPExcel_Writer_CSV + * + * @param PHPExcel $phpExcel PHPExcel object + */ + public function __construct(PHPExcel $phpExcel) { + $this->_phpExcel = $phpExcel; + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) { + // Fetch sheet + $sheet = $this->_phpExcel->getSheet($this->_sheetIndex); + + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); + $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); + PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); + + // Open file + $fileHandle = fopen($pFilename, 'wb+'); + if ($fileHandle === false) { + throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing."); + } + + if ($this->_excelCompatibility) { + // Write the UTF-16LE BOM code + fwrite($fileHandle, "\xFF\xFE"); // Excel uses UTF-16LE encoding + $this->setEnclosure(); // Default enclosure is " + $this->setDelimiter("\t"); // Excel delimiter is a TAB + } elseif ($this->_useBOM) { + // Write the UTF-8 BOM code + fwrite($fileHandle, "\xEF\xBB\xBF"); + } + + // Identify the range that we need to extract from the worksheet + $maxCol = $sheet->getHighestColumn(); + $maxRow = $sheet->getHighestRow(); + + // Write rows to file + for($row = 1; $row <= $maxRow; ++$row) { + // Convert the row to an array... + $cellsArray = $sheet->rangeToArray('A'.$row.':'.$maxCol.$row,'', $this->_preCalculateFormulas); + // ... and write to the file + $this->_writeLine($fileHandle, $cellsArray[0]); + } + + // Close file + fclose($fileHandle); + + PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); + } + + /** + * Get delimiter + * + * @return string + */ + public function getDelimiter() { + return $this->_delimiter; + } + + /** + * Set delimiter + * + * @param string $pValue Delimiter, defaults to , + * @return PHPExcel_Writer_CSV + */ + public function setDelimiter($pValue = ',') { + $this->_delimiter = $pValue; + return $this; + } + + /** + * Get enclosure + * + * @return string + */ + public function getEnclosure() { + return $this->_enclosure; + } + + /** + * Set enclosure + * + * @param string $pValue Enclosure, defaults to " + * @return PHPExcel_Writer_CSV + */ + public function setEnclosure($pValue = '"') { + if ($pValue == '') { + $pValue = null; + } + $this->_enclosure = $pValue; + return $this; + } + + /** + * Get line ending + * + * @return string + */ + public function getLineEnding() { + return $this->_lineEnding; + } + + /** + * Set line ending + * + * @param string $pValue Line ending, defaults to OS line ending (PHP_EOL) + * @return PHPExcel_Writer_CSV + */ + public function setLineEnding($pValue = PHP_EOL) { + $this->_lineEnding = $pValue; + return $this; + } + + /** + * Get whether BOM should be used + * + * @return boolean + */ + public function getUseBOM() { + return $this->_useBOM; + } + + /** + * Set whether BOM should be used + * + * @param boolean $pValue Use UTF-8 byte-order mark? Defaults to false + * @return PHPExcel_Writer_CSV + */ + public function setUseBOM($pValue = false) { + $this->_useBOM = $pValue; + return $this; + } + + /** + * Get whether the file should be saved with full Excel Compatibility + * + * @return boolean + */ + public function getExcelCompatibility() { + return $this->_excelCompatibility; + } + + /** + * Set whether the file should be saved with full Excel Compatibility + * + * @param boolean $pValue Set the file to be written as a fully Excel compatible csv file + * Note that this overrides other settings such as useBOM, enclosure and delimiter + * @return PHPExcel_Writer_CSV + */ + public function setExcelCompatibility($pValue = false) { + $this->_excelCompatibility = $pValue; + return $this; + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Writer_CSV + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } + + /** + * Write line to CSV file + * + * @param mixed $pFileHandle PHP filehandle + * @param array $pValues Array containing values in a row + * @throws PHPExcel_Writer_Exception + */ + private function _writeLine($pFileHandle = null, $pValues = null) { + if (is_array($pValues)) { + // No leading delimiter + $writeDelimiter = false; + + // Build the line + $line = ''; + + foreach ($pValues as $element) { + // Escape enclosures + $element = str_replace($this->_enclosure, $this->_enclosure . $this->_enclosure, $element); + + // Add delimiter + if ($writeDelimiter) { + $line .= $this->_delimiter; + } else { + $writeDelimiter = true; + } + + // Add enclosed string + $line .= $this->_enclosure . $element . $this->_enclosure; + } + + // Add line ending + $line .= $this->_lineEnding; + + // Write to file + if ($this->_excelCompatibility) { + fwrite($pFileHandle, mb_convert_encoding($line,"UTF-16LE","UTF-8")); + } else { + fwrite($pFileHandle, $line); + } + } else { + throw new PHPExcel_Writer_Exception("Invalid data row passed to CSV writer."); + } + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007.php new file mode 100755 index 0000000..47de168 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007.php @@ -0,0 +1,472 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007 + * + * @category PHPExcel + * @package PHPExcel_Writer_2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007 extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter +{ + /** + * Office2003 compatibility + * + * @var boolean + */ + private $_office2003compatibility = false; + + /** + * Private writer parts + * + * @var PHPExcel_Writer_Excel2007_WriterPart[] + */ + private $_writerParts = array(); + + /** + * Private PHPExcel + * + * @var PHPExcel + */ + private $_spreadSheet; + + /** + * Private string table + * + * @var string[] + */ + private $_stringTable = array(); + + /** + * Private unique PHPExcel_Style_Conditional HashTable + * + * @var PHPExcel_HashTable + */ + private $_stylesConditionalHashTable; + + /** + * Private unique PHPExcel_Style_Fill HashTable + * + * @var PHPExcel_HashTable + */ + private $_fillHashTable; + + /** + * Private unique PHPExcel_Style_Font HashTable + * + * @var PHPExcel_HashTable + */ + private $_fontHashTable; + + /** + * Private unique PHPExcel_Style_Borders HashTable + * + * @var PHPExcel_HashTable + */ + private $_bordersHashTable ; + + /** + * Private unique PHPExcel_Style_NumberFormat HashTable + * + * @var PHPExcel_HashTable + */ + private $_numFmtHashTable; + + /** + * Private unique PHPExcel_Worksheet_BaseDrawing HashTable + * + * @var PHPExcel_HashTable + */ + private $_drawingHashTable; + + /** + * Create a new PHPExcel_Writer_Excel2007 + * + * @param PHPExcel $pPHPExcel + */ + public function __construct(PHPExcel $pPHPExcel = null) + { + // Assign PHPExcel + $this->setPHPExcel($pPHPExcel); + + $writerPartsArray = array( 'stringtable' => 'PHPExcel_Writer_Excel2007_StringTable', + 'contenttypes' => 'PHPExcel_Writer_Excel2007_ContentTypes', + 'docprops' => 'PHPExcel_Writer_Excel2007_DocProps', + 'rels' => 'PHPExcel_Writer_Excel2007_Rels', + 'theme' => 'PHPExcel_Writer_Excel2007_Theme', + 'style' => 'PHPExcel_Writer_Excel2007_Style', + 'workbook' => 'PHPExcel_Writer_Excel2007_Workbook', + 'worksheet' => 'PHPExcel_Writer_Excel2007_Worksheet', + 'drawing' => 'PHPExcel_Writer_Excel2007_Drawing', + 'comments' => 'PHPExcel_Writer_Excel2007_Comments', + 'chart' => 'PHPExcel_Writer_Excel2007_Chart', + ); + + // Initialise writer parts + // and Assign their parent IWriters + foreach ($writerPartsArray as $writer => $class) { + $this->_writerParts[$writer] = new $class($this); + } + + $hashTablesArray = array( '_stylesConditionalHashTable', '_fillHashTable', '_fontHashTable', + '_bordersHashTable', '_numFmtHashTable', '_drawingHashTable' + ); + + // Set HashTable variables + foreach ($hashTablesArray as $tableName) { + $this->$tableName = new PHPExcel_HashTable(); + } + } + + /** + * Get writer part + * + * @param string $pPartName Writer part name + * @return PHPExcel_Writer_Excel2007_WriterPart + */ + public function getWriterPart($pPartName = '') { + if ($pPartName != '' && isset($this->_writerParts[strtolower($pPartName)])) { + return $this->_writerParts[strtolower($pPartName)]; + } else { + return null; + } + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) + { + if ($this->_spreadSheet !== NULL) { + // garbage collect + $this->_spreadSheet->garbageCollect(); + + // If $pFilename is php://output or php://stdout, make it a temporary file... + $originalFilename = $pFilename; + if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') { + $pFilename = @tempnam(PHPExcel_Shared_File::sys_get_temp_dir(), 'phpxltmp'); + if ($pFilename == '') { + $pFilename = $originalFilename; + } + } + + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog(FALSE); + $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); + PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); + + // Create string lookup table + $this->_stringTable = array(); + for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { + $this->_stringTable = $this->getWriterPart('StringTable')->createStringTable($this->_spreadSheet->getSheet($i), $this->_stringTable); + } + + // Create styles dictionaries + $this->_stylesConditionalHashTable->addFromSource( $this->getWriterPart('Style')->allConditionalStyles($this->_spreadSheet) ); + $this->_fillHashTable->addFromSource( $this->getWriterPart('Style')->allFills($this->_spreadSheet) ); + $this->_fontHashTable->addFromSource( $this->getWriterPart('Style')->allFonts($this->_spreadSheet) ); + $this->_bordersHashTable->addFromSource( $this->getWriterPart('Style')->allBorders($this->_spreadSheet) ); + $this->_numFmtHashTable->addFromSource( $this->getWriterPart('Style')->allNumberFormats($this->_spreadSheet) ); + + // Create drawing dictionary + $this->_drawingHashTable->addFromSource( $this->getWriterPart('Drawing')->allDrawings($this->_spreadSheet) ); + + // Create new ZIP file and open it for writing + $zipClass = PHPExcel_Settings::getZipClass(); + $objZip = new $zipClass(); + + // Retrieve OVERWRITE and CREATE constants from the instantiated zip class + // This method of accessing constant values from a dynamic class should work with all appropriate versions of PHP + $ro = new ReflectionObject($objZip); + $zipOverWrite = $ro->getConstant('OVERWRITE'); + $zipCreate = $ro->getConstant('CREATE'); + + if (file_exists($pFilename)) { + unlink($pFilename); + } + // Try opening the ZIP file + if ($objZip->open($pFilename, $zipOverWrite) !== true) { + if ($objZip->open($pFilename, $zipCreate) !== true) { + throw new PHPExcel_Writer_Exception("Could not open " . $pFilename . " for writing."); + } + } + + // Add [Content_Types].xml to ZIP file + $objZip->addFromString('[Content_Types].xml', $this->getWriterPart('ContentTypes')->writeContentTypes($this->_spreadSheet, $this->_includeCharts)); + + // Add relationships to ZIP file + $objZip->addFromString('_rels/.rels', $this->getWriterPart('Rels')->writeRelationships($this->_spreadSheet)); + $objZip->addFromString('xl/_rels/workbook.xml.rels', $this->getWriterPart('Rels')->writeWorkbookRelationships($this->_spreadSheet)); + + // Add document properties to ZIP file + $objZip->addFromString('docProps/app.xml', $this->getWriterPart('DocProps')->writeDocPropsApp($this->_spreadSheet)); + $objZip->addFromString('docProps/core.xml', $this->getWriterPart('DocProps')->writeDocPropsCore($this->_spreadSheet)); + $customPropertiesPart = $this->getWriterPart('DocProps')->writeDocPropsCustom($this->_spreadSheet); + if ($customPropertiesPart !== NULL) { + $objZip->addFromString('docProps/custom.xml', $customPropertiesPart); + } + + // Add theme to ZIP file + $objZip->addFromString('xl/theme/theme1.xml', $this->getWriterPart('Theme')->writeTheme($this->_spreadSheet)); + + // Add string table to ZIP file + $objZip->addFromString('xl/sharedStrings.xml', $this->getWriterPart('StringTable')->writeStringTable($this->_stringTable)); + + // Add styles to ZIP file + $objZip->addFromString('xl/styles.xml', $this->getWriterPart('Style')->writeStyles($this->_spreadSheet)); + + // Add workbook to ZIP file + $objZip->addFromString('xl/workbook.xml', $this->getWriterPart('Workbook')->writeWorkbook($this->_spreadSheet, $this->_preCalculateFormulas)); + + $chartCount = 0; + // Add worksheets + for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { + $objZip->addFromString('xl/worksheets/sheet' . ($i + 1) . '.xml', $this->getWriterPart('Worksheet')->writeWorksheet($this->_spreadSheet->getSheet($i), $this->_stringTable, $this->_includeCharts)); + if ($this->_includeCharts) { + $charts = $this->_spreadSheet->getSheet($i)->getChartCollection(); + if (count($charts) > 0) { + foreach($charts as $chart) { + $objZip->addFromString('xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPart('Chart')->writeChart($chart)); + $chartCount++; + } + } + } + } + + $chartRef1 = $chartRef2 = 0; + // Add worksheet relationships (drawings, ...) + for ($i = 0; $i < $this->_spreadSheet->getSheetCount(); ++$i) { + + // Add relationships + $objZip->addFromString('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeWorksheetRelationships($this->_spreadSheet->getSheet($i), ($i + 1), $this->_includeCharts)); + + $drawings = $this->_spreadSheet->getSheet($i)->getDrawingCollection(); + $drawingCount = count($drawings); + if ($this->_includeCharts) { + $chartCount = $this->_spreadSheet->getSheet($i)->getChartCount(); + } + + // Add drawing and image relationship parts + if (($drawingCount > 0) || ($chartCount > 0)) { + // Drawing relationships + $objZip->addFromString('xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeDrawingRelationships($this->_spreadSheet->getSheet($i),$chartRef1, $this->_includeCharts)); + + // Drawings + $objZip->addFromString('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->_spreadSheet->getSheet($i),$chartRef2,$this->_includeCharts)); + } + + // Add comment relationship parts + if (count($this->_spreadSheet->getSheet($i)->getComments()) > 0) { + // VML Comments + $objZip->addFromString('xl/drawings/vmlDrawing' . ($i + 1) . '.vml', $this->getWriterPart('Comments')->writeVMLComments($this->_spreadSheet->getSheet($i))); + + // Comments + $objZip->addFromString('xl/comments' . ($i + 1) . '.xml', $this->getWriterPart('Comments')->writeComments($this->_spreadSheet->getSheet($i))); + } + + // Add header/footer relationship parts + if (count($this->_spreadSheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) { + // VML Drawings + $objZip->addFromString('xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml', $this->getWriterPart('Drawing')->writeVMLHeaderFooterImages($this->_spreadSheet->getSheet($i))); + + // VML Drawing relationships + $objZip->addFromString('xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels', $this->getWriterPart('Rels')->writeHeaderFooterDrawingRelationships($this->_spreadSheet->getSheet($i))); + + // Media + foreach ($this->_spreadSheet->getSheet($i)->getHeaderFooter()->getImages() as $image) { + $objZip->addFromString('xl/media/' . $image->getIndexedFilename(), file_get_contents($image->getPath())); + } + } + } + + // Add media + for ($i = 0; $i < $this->getDrawingHashTable()->count(); ++$i) { + if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_Drawing) { + $imageContents = null; + $imagePath = $this->getDrawingHashTable()->getByIndex($i)->getPath(); + if (strpos($imagePath, 'zip://') !== false) { + $imagePath = substr($imagePath, 6); + $imagePathSplitted = explode('#', $imagePath); + + $imageZip = new ZipArchive(); + $imageZip->open($imagePathSplitted[0]); + $imageContents = $imageZip->getFromName($imagePathSplitted[1]); + $imageZip->close(); + unset($imageZip); + } else { + $imageContents = file_get_contents($imagePath); + } + + $objZip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); + } else if ($this->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_MemoryDrawing) { + ob_start(); + call_user_func( + $this->getDrawingHashTable()->getByIndex($i)->getRenderingFunction(), + $this->getDrawingHashTable()->getByIndex($i)->getImageResource() + ); + $imageContents = ob_get_contents(); + ob_end_clean(); + + $objZip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents); + } + } + + PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType); + PHPExcel_Calculation::getInstance($this->_spreadSheet)->getDebugLog()->setWriteDebugLog($saveDebugLog); + + // Close file + if ($objZip->close() === false) { + throw new PHPExcel_Writer_Exception("Could not close zip file $pFilename."); + } + + // If a temporary file was used, copy it to the correct file stream + if ($originalFilename != $pFilename) { + if (copy($pFilename, $originalFilename) === false) { + throw new PHPExcel_Writer_Exception("Could not copy temporary zip file $pFilename to $originalFilename."); + } + @unlink($pFilename); + } + } else { + throw new PHPExcel_Writer_Exception("PHPExcel object unassigned."); + } + } + + /** + * Get PHPExcel object + * + * @return PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function getPHPExcel() { + if ($this->_spreadSheet !== null) { + return $this->_spreadSheet; + } else { + throw new PHPExcel_Writer_Exception("No PHPExcel assigned."); + } + } + + /** + * Set PHPExcel object + * + * @param PHPExcel $pPHPExcel PHPExcel object + * @throws PHPExcel_Writer_Exception + * @return PHPExcel_Writer_Excel2007 + */ + public function setPHPExcel(PHPExcel $pPHPExcel = null) { + $this->_spreadSheet = $pPHPExcel; + return $this; + } + + /** + * Get string table + * + * @return string[] + */ + public function getStringTable() { + return $this->_stringTable; + } + + /** + * Get PHPExcel_Style_Conditional HashTable + * + * @return PHPExcel_HashTable + */ + public function getStylesConditionalHashTable() { + return $this->_stylesConditionalHashTable; + } + + /** + * Get PHPExcel_Style_Fill HashTable + * + * @return PHPExcel_HashTable + */ + public function getFillHashTable() { + return $this->_fillHashTable; + } + + /** + * Get PHPExcel_Style_Font HashTable + * + * @return PHPExcel_HashTable + */ + public function getFontHashTable() { + return $this->_fontHashTable; + } + + /** + * Get PHPExcel_Style_Borders HashTable + * + * @return PHPExcel_HashTable + */ + public function getBordersHashTable() { + return $this->_bordersHashTable; + } + + /** + * Get PHPExcel_Style_NumberFormat HashTable + * + * @return PHPExcel_HashTable + */ + public function getNumFmtHashTable() { + return $this->_numFmtHashTable; + } + + /** + * Get PHPExcel_Worksheet_BaseDrawing HashTable + * + * @return PHPExcel_HashTable + */ + public function getDrawingHashTable() { + return $this->_drawingHashTable; + } + + /** + * Get Office2003 compatibility + * + * @return boolean + */ + public function getOffice2003Compatibility() { + return $this->_office2003compatibility; + } + + /** + * Set Office2003 compatibility + * + * @param boolean $pValue Office2003 compatibility? + * @return PHPExcel_Writer_Excel2007 + */ + public function setOffice2003Compatibility($pValue = false) { + $this->_office2003compatibility = $pValue; + return $this; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Chart.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Chart.php new file mode 100755 index 0000000..5adfb7c --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Chart.php @@ -0,0 +1,1184 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_Chart + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007_Chart extends PHPExcel_Writer_Excel2007_WriterPart +{ + /** + * Write charts to XML format + * + * @param PHPExcel_Chart $pChart + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeChart(PHPExcel_Chart $pChart = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + // Ensure that data series values are up-to-date before we save + $pChart->refresh(); + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // c:chartSpace + $objWriter->startElement('c:chartSpace'); + $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + + $objWriter->startElement('c:date1904'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + $objWriter->startElement('c:lang'); + $objWriter->writeAttribute('val', "en-GB"); + $objWriter->endElement(); + $objWriter->startElement('c:roundedCorners'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $this->_writeAlternateContent($objWriter); + + $objWriter->startElement('c:chart'); + + $this->_writeTitle($pChart->getTitle(), $objWriter); + + $objWriter->startElement('c:autoTitleDeleted'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $this->_writePlotArea($pChart->getPlotArea(), + $pChart->getXAxisLabel(), + $pChart->getYAxisLabel(), + $objWriter, + $pChart->getWorksheet() + ); + + $this->_writeLegend($pChart->getLegend(), $objWriter); + + + $objWriter->startElement('c:plotVisOnly'); + $objWriter->writeAttribute('val', 1); + $objWriter->endElement(); + + $objWriter->startElement('c:dispBlanksAs'); + $objWriter->writeAttribute('val', "gap"); + $objWriter->endElement(); + + $objWriter->startElement('c:showDLblsOverMax'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->endElement(); + + $this->_writePrintSettings($objWriter); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write Chart Title + * + * @param PHPExcel_Chart_Title $title + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writeTitle(PHPExcel_Chart_Title $title = null, $objWriter) + { + if (is_null($title)) { + return; + } + + $objWriter->startElement('c:title'); + $objWriter->startElement('c:tx'); + $objWriter->startElement('c:rich'); + + $objWriter->startElement('a:bodyPr'); + $objWriter->endElement(); + + $objWriter->startElement('a:lstStyle'); + $objWriter->endElement(); + + $objWriter->startElement('a:p'); + + $caption = $title->getCaption(); + if ((is_array($caption)) && (count($caption) > 0)) + $caption = $caption[0]; + $this->getParentWriter()->getWriterPart('stringtable')->writeRichTextForCharts($objWriter, $caption, 'a'); + + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + + $layout = $title->getLayout(); + $this->_writeLayout($layout, $objWriter); + + $objWriter->startElement('c:overlay'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write Chart Legend + * + * @param PHPExcel_Chart_Legend $legend + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writeLegend(PHPExcel_Chart_Legend $legend = null, $objWriter) + { + if (is_null($legend)) { + return; + } + + $objWriter->startElement('c:legend'); + + $objWriter->startElement('c:legendPos'); + $objWriter->writeAttribute('val', $legend->getPosition()); + $objWriter->endElement(); + + $layout = $legend->getLayout(); + $this->_writeLayout($layout, $objWriter); + + $objWriter->startElement('c:overlay'); + $objWriter->writeAttribute('val', ($legend->getOverlay()) ? '1' : '0'); + $objWriter->endElement(); + + $objWriter->startElement('c:txPr'); + $objWriter->startElement('a:bodyPr'); + $objWriter->endElement(); + + $objWriter->startElement('a:lstStyle'); + $objWriter->endElement(); + + $objWriter->startElement('a:p'); + $objWriter->startElement('a:pPr'); + $objWriter->writeAttribute('rtl', 0); + + $objWriter->startElement('a:defRPr'); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('a:endParaRPr'); + $objWriter->writeAttribute('lang', "en-US"); + $objWriter->endElement(); + + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write Chart Plot Area + * + * @param PHPExcel_Chart_PlotArea $plotArea + * @param PHPExcel_Chart_Title $xAxisLabel + * @param PHPExcel_Chart_Title $yAxisLabel + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writePlotArea(PHPExcel_Chart_PlotArea $plotArea, + PHPExcel_Chart_Title $xAxisLabel = NULL, + PHPExcel_Chart_Title $yAxisLabel = NULL, + $objWriter, + PHPExcel_Worksheet $pSheet) + { + if (is_null($plotArea)) { + return; + } + + $id1 = $id2 = 0; + $this->_seriesIndex = 0; + $objWriter->startElement('c:plotArea'); + + $layout = $plotArea->getLayout(); + + $this->_writeLayout($layout, $objWriter); + + $chartTypes = self::_getChartType($plotArea); + $catIsMultiLevelSeries = $valIsMultiLevelSeries = FALSE; + $plotGroupingType = ''; + foreach($chartTypes as $chartType) { + $objWriter->startElement('c:'.$chartType); + + $groupCount = $plotArea->getPlotGroupCount(); + for($i = 0; $i < $groupCount; ++$i) { + $plotGroup = $plotArea->getPlotGroupByIndex($i); + $groupType = $plotGroup->getPlotType(); + if ($groupType == $chartType) { + + $plotStyle = $plotGroup->getPlotStyle(); + if ($groupType === PHPExcel_Chart_DataSeries::TYPE_RADARCHART) { + $objWriter->startElement('c:radarStyle'); + $objWriter->writeAttribute('val', $plotStyle ); + $objWriter->endElement(); + } elseif ($groupType === PHPExcel_Chart_DataSeries::TYPE_SCATTERCHART) { + $objWriter->startElement('c:scatterStyle'); + $objWriter->writeAttribute('val', $plotStyle ); + $objWriter->endElement(); + } + + $this->_writePlotGroup($plotGroup, $chartType, $objWriter, $catIsMultiLevelSeries, $valIsMultiLevelSeries, $plotGroupingType, $pSheet); + } + } + + $this->_writeDataLbls($objWriter, $layout); + + if ($chartType === PHPExcel_Chart_DataSeries::TYPE_LINECHART) { + // Line only, Line3D can't be smoothed + + $objWriter->startElement('c:smooth'); + $objWriter->writeAttribute('val', (integer) $plotGroup->getSmoothLine() ); + $objWriter->endElement(); + } elseif (($chartType === PHPExcel_Chart_DataSeries::TYPE_BARCHART) || + ($chartType === PHPExcel_Chart_DataSeries::TYPE_BARCHART_3D)) { + + $objWriter->startElement('c:gapWidth'); + $objWriter->writeAttribute('val', 150 ); + $objWriter->endElement(); + + if ($plotGroupingType == 'percentStacked' || + $plotGroupingType == 'stacked') { + + $objWriter->startElement('c:overlap'); + $objWriter->writeAttribute('val', 100 ); + $objWriter->endElement(); + } + } elseif ($chartType === PHPExcel_Chart_DataSeries::TYPE_BUBBLECHART) { + + $objWriter->startElement('c:bubbleScale'); + $objWriter->writeAttribute('val', 25 ); + $objWriter->endElement(); + + $objWriter->startElement('c:showNegBubbles'); + $objWriter->writeAttribute('val', 0 ); + $objWriter->endElement(); + } elseif ($chartType === PHPExcel_Chart_DataSeries::TYPE_STOCKCHART) { + + $objWriter->startElement('c:hiLowLines'); + $objWriter->endElement(); + } + + // Generate 2 unique numbers to use for axId values +// $id1 = $id2 = rand(10000000,99999999); +// do { +// $id2 = rand(10000000,99999999); +// } while ($id1 == $id2); + $id1 = '75091328'; + $id2 = '75089408'; + + if (($chartType !== PHPExcel_Chart_DataSeries::TYPE_PIECHART) && + ($chartType !== PHPExcel_Chart_DataSeries::TYPE_PIECHART_3D) && + ($chartType !== PHPExcel_Chart_DataSeries::TYPE_DONUTCHART)) { + + $objWriter->startElement('c:axId'); + $objWriter->writeAttribute('val', $id1 ); + $objWriter->endElement(); + $objWriter->startElement('c:axId'); + $objWriter->writeAttribute('val', $id2 ); + $objWriter->endElement(); + } else { + $objWriter->startElement('c:firstSliceAng'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + if ($chartType === PHPExcel_Chart_DataSeries::TYPE_DONUTCHART) { + + $objWriter->startElement('c:holeSize'); + $objWriter->writeAttribute('val', 50); + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + } + + if (($chartType !== PHPExcel_Chart_DataSeries::TYPE_PIECHART) && + ($chartType !== PHPExcel_Chart_DataSeries::TYPE_PIECHART_3D) && + ($chartType !== PHPExcel_Chart_DataSeries::TYPE_DONUTCHART)) { + + if ($chartType === PHPExcel_Chart_DataSeries::TYPE_BUBBLECHART) { + $this->_writeValAx($objWriter,$plotArea,$xAxisLabel,$chartType,$id1,$id2,$catIsMultiLevelSeries); + } else { + $this->_writeCatAx($objWriter,$plotArea,$xAxisLabel,$chartType,$id1,$id2,$catIsMultiLevelSeries); + } + + $this->_writeValAx($objWriter,$plotArea,$yAxisLabel,$chartType,$id1,$id2,$valIsMultiLevelSeries); + } + + $objWriter->endElement(); + } + + /** + * Write Data Labels + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Chart_Layout $chartLayout Chart layout + * @throws PHPExcel_Writer_Exception + */ + private function _writeDataLbls($objWriter, $chartLayout) + { + $objWriter->startElement('c:dLbls'); + + $objWriter->startElement('c:showLegendKey'); + $showLegendKey = (empty($chartLayout)) ? 0 : $chartLayout->getShowLegendKey(); + $objWriter->writeAttribute('val', ((empty($showLegendKey)) ? 0 : 1) ); + $objWriter->endElement(); + + + $objWriter->startElement('c:showVal'); + $showVal = (empty($chartLayout)) ? 0 : $chartLayout->getShowVal(); + $objWriter->writeAttribute('val', ((empty($showVal)) ? 0 : 1) ); + $objWriter->endElement(); + + $objWriter->startElement('c:showCatName'); + $showCatName = (empty($chartLayout)) ? 0 : $chartLayout->getShowCatName(); + $objWriter->writeAttribute('val', ((empty($showCatName)) ? 0 : 1) ); + $objWriter->endElement(); + + $objWriter->startElement('c:showSerName'); + $showSerName = (empty($chartLayout)) ? 0 : $chartLayout->getShowSerName(); + $objWriter->writeAttribute('val', ((empty($showSerName)) ? 0 : 1) ); + $objWriter->endElement(); + + $objWriter->startElement('c:showPercent'); + $showPercent = (empty($chartLayout)) ? 0 : $chartLayout->getShowPercent(); + $objWriter->writeAttribute('val', ((empty($showPercent)) ? 0 : 1) ); + $objWriter->endElement(); + + $objWriter->startElement('c:showBubbleSize'); + $showBubbleSize = (empty($chartLayout)) ? 0 : $chartLayout->getShowBubbleSize(); + $objWriter->writeAttribute('val', ((empty($showBubbleSize)) ? 0 : 1) ); + $objWriter->endElement(); + + $objWriter->startElement('c:showLeaderLines'); + $showLeaderLines = (empty($chartLayout)) ? 1 : $chartLayout->getShowLeaderLines(); + $objWriter->writeAttribute('val', ((empty($showLeaderLines)) ? 0 : 1) ); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write Category Axis + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Chart_PlotArea $plotArea + * @param PHPExcel_Chart_Title $xAxisLabel + * @param string $groupType Chart type + * @param string $id1 + * @param string $id2 + * @param boolean $isMultiLevelSeries + * @throws PHPExcel_Writer_Exception + */ + private function _writeCatAx($objWriter, PHPExcel_Chart_PlotArea $plotArea, $xAxisLabel, $groupType, $id1, $id2, $isMultiLevelSeries) + { + $objWriter->startElement('c:catAx'); + + if ($id1 > 0) { + $objWriter->startElement('c:axId'); + $objWriter->writeAttribute('val', $id1); + $objWriter->endElement(); + } + + $objWriter->startElement('c:scaling'); + $objWriter->startElement('c:orientation'); + $objWriter->writeAttribute('val', "minMax"); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('c:delete'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:axPos'); + $objWriter->writeAttribute('val', "b"); + $objWriter->endElement(); + + if (!is_null($xAxisLabel)) { + $objWriter->startElement('c:title'); + $objWriter->startElement('c:tx'); + $objWriter->startElement('c:rich'); + + $objWriter->startElement('a:bodyPr'); + $objWriter->endElement(); + + $objWriter->startElement('a:lstStyle'); + $objWriter->endElement(); + + $objWriter->startElement('a:p'); + $objWriter->startElement('a:r'); + + $caption = $xAxisLabel->getCaption(); + if (is_array($caption)) + $caption = $caption[0]; + $objWriter->startElement('a:t'); +// $objWriter->writeAttribute('xml:space', 'preserve'); + $objWriter->writeRawData(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $caption )); + $objWriter->endElement(); + + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + + $layout = $xAxisLabel->getLayout(); + $this->_writeLayout($layout, $objWriter); + + $objWriter->startElement('c:overlay'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->endElement(); + + } + + $objWriter->startElement('c:numFmt'); + $objWriter->writeAttribute('formatCode', "General"); + $objWriter->writeAttribute('sourceLinked', 1); + $objWriter->endElement(); + + $objWriter->startElement('c:majorTickMark'); + $objWriter->writeAttribute('val', "out"); + $objWriter->endElement(); + + $objWriter->startElement('c:minorTickMark'); + $objWriter->writeAttribute('val', "none"); + $objWriter->endElement(); + + $objWriter->startElement('c:tickLblPos'); + $objWriter->writeAttribute('val', "nextTo"); + $objWriter->endElement(); + + if ($id2 > 0) { + $objWriter->startElement('c:crossAx'); + $objWriter->writeAttribute('val', $id2); + $objWriter->endElement(); + + $objWriter->startElement('c:crosses'); + $objWriter->writeAttribute('val', "autoZero"); + $objWriter->endElement(); + } + + $objWriter->startElement('c:auto'); + $objWriter->writeAttribute('val', 1); + $objWriter->endElement(); + + $objWriter->startElement('c:lblAlgn'); + $objWriter->writeAttribute('val', "ctr"); + $objWriter->endElement(); + + $objWriter->startElement('c:lblOffset'); + $objWriter->writeAttribute('val', 100); + $objWriter->endElement(); + + if ($isMultiLevelSeries) { + $objWriter->startElement('c:noMultiLvlLbl'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + } + $objWriter->endElement(); + + } + + + /** + * Write Value Axis + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Chart_PlotArea $plotArea + * @param PHPExcel_Chart_Title $yAxisLabel + * @param string $groupType Chart type + * @param string $id1 + * @param string $id2 + * @param boolean $isMultiLevelSeries + * @throws PHPExcel_Writer_Exception + */ + private function _writeValAx($objWriter, PHPExcel_Chart_PlotArea $plotArea, $yAxisLabel, $groupType, $id1, $id2, $isMultiLevelSeries) + { + $objWriter->startElement('c:valAx'); + + if ($id2 > 0) { + $objWriter->startElement('c:axId'); + $objWriter->writeAttribute('val', $id2); + $objWriter->endElement(); + } + + $objWriter->startElement('c:scaling'); + $objWriter->startElement('c:orientation'); + $objWriter->writeAttribute('val', "minMax"); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('c:delete'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:axPos'); + $objWriter->writeAttribute('val', "l"); + $objWriter->endElement(); + + $objWriter->startElement('c:majorGridlines'); + $objWriter->endElement(); + + if (!is_null($yAxisLabel)) { + $objWriter->startElement('c:title'); + $objWriter->startElement('c:tx'); + $objWriter->startElement('c:rich'); + + $objWriter->startElement('a:bodyPr'); + $objWriter->endElement(); + + $objWriter->startElement('a:lstStyle'); + $objWriter->endElement(); + + $objWriter->startElement('a:p'); + $objWriter->startElement('a:r'); + + $caption = $yAxisLabel->getCaption(); + if (is_array($caption)) + $caption = $caption[0]; + $objWriter->startElement('a:t'); +// $objWriter->writeAttribute('xml:space', 'preserve'); + $objWriter->writeRawData(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $caption )); + $objWriter->endElement(); + + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + + if ($groupType !== PHPExcel_Chart_DataSeries::TYPE_BUBBLECHART) { + $layout = $yAxisLabel->getLayout(); + $this->_writeLayout($layout, $objWriter); + } + + $objWriter->startElement('c:overlay'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + $objWriter->startElement('c:numFmt'); + $objWriter->writeAttribute('formatCode', "General"); + $objWriter->writeAttribute('sourceLinked', 1); + $objWriter->endElement(); + + $objWriter->startElement('c:majorTickMark'); + $objWriter->writeAttribute('val', "out"); + $objWriter->endElement(); + + $objWriter->startElement('c:minorTickMark'); + $objWriter->writeAttribute('val', "none"); + $objWriter->endElement(); + + $objWriter->startElement('c:tickLblPos'); + $objWriter->writeAttribute('val', "nextTo"); + $objWriter->endElement(); + + if ($id1 > 0) { + $objWriter->startElement('c:crossAx'); + $objWriter->writeAttribute('val', $id2); + $objWriter->endElement(); + + $objWriter->startElement('c:crosses'); + $objWriter->writeAttribute('val', "autoZero"); + $objWriter->endElement(); + + $objWriter->startElement('c:crossBetween'); + $objWriter->writeAttribute('val', "midCat"); + $objWriter->endElement(); + } + + if ($isMultiLevelSeries) { + if ($groupType !== PHPExcel_Chart_DataSeries::TYPE_BUBBLECHART) { + $objWriter->startElement('c:noMultiLvlLbl'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + } + } + $objWriter->endElement(); + + } + + + /** + * Get the data series type(s) for a chart plot series + * + * @param PHPExcel_Chart_PlotArea $plotArea + * @return string|array + * @throws PHPExcel_Writer_Exception + */ + private static function _getChartType($plotArea) + { + $groupCount = $plotArea->getPlotGroupCount(); + + if ($groupCount == 1) { + $chartType = array($plotArea->getPlotGroupByIndex(0)->getPlotType()); + } else { + $chartTypes = array(); + for($i = 0; $i < $groupCount; ++$i) { + $chartTypes[] = $plotArea->getPlotGroupByIndex($i)->getPlotType(); + } + $chartType = array_unique($chartTypes); + if (count($chartTypes) == 0) { + throw new PHPExcel_Writer_Exception('Chart is not yet implemented'); + } + } + + return $chartType; + } + + /** + * Write Plot Group (series of related plots) + * + * @param PHPExcel_Chart_DataSeries $plotGroup + * @param string $groupType Type of plot for dataseries + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param boolean &$catIsMultiLevelSeries Is category a multi-series category + * @param boolean &$valIsMultiLevelSeries Is value set a multi-series set + * @param string &$plotGroupingType Type of grouping for multi-series values + * @param PHPExcel_Worksheet $pSheet + * @throws PHPExcel_Writer_Exception + */ + private function _writePlotGroup( $plotGroup, + $groupType, + $objWriter, + &$catIsMultiLevelSeries, + &$valIsMultiLevelSeries, + &$plotGroupingType, + PHPExcel_Worksheet $pSheet + ) + { + if (is_null($plotGroup)) { + return; + } + + if (($groupType == PHPExcel_Chart_DataSeries::TYPE_BARCHART) || + ($groupType == PHPExcel_Chart_DataSeries::TYPE_BARCHART_3D)) { + $objWriter->startElement('c:barDir'); + $objWriter->writeAttribute('val', $plotGroup->getPlotDirection()); + $objWriter->endElement(); + } + + if (!is_null($plotGroup->getPlotGrouping())) { + $plotGroupingType = $plotGroup->getPlotGrouping(); + $objWriter->startElement('c:grouping'); + $objWriter->writeAttribute('val', $plotGroupingType); + $objWriter->endElement(); + } + + // Get these details before the loop, because we can use the count to check for varyColors + $plotSeriesOrder = $plotGroup->getPlotOrder(); + $plotSeriesCount = count($plotSeriesOrder); + + if (($groupType !== PHPExcel_Chart_DataSeries::TYPE_RADARCHART) && + ($groupType !== PHPExcel_Chart_DataSeries::TYPE_STOCKCHART)) { + + if ($groupType !== PHPExcel_Chart_DataSeries::TYPE_LINECHART) { + if (($groupType == PHPExcel_Chart_DataSeries::TYPE_PIECHART) || + ($groupType == PHPExcel_Chart_DataSeries::TYPE_PIECHART_3D) || + ($groupType == PHPExcel_Chart_DataSeries::TYPE_DONUTCHART) || + ($plotSeriesCount > 1)) { + $objWriter->startElement('c:varyColors'); + $objWriter->writeAttribute('val', 1); + $objWriter->endElement(); + } else { + $objWriter->startElement('c:varyColors'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + } + } + } + + foreach($plotSeriesOrder as $plotSeriesIdx => $plotSeriesRef) { + $objWriter->startElement('c:ser'); + + $objWriter->startElement('c:idx'); + $objWriter->writeAttribute('val', $this->_seriesIndex + $plotSeriesIdx); + $objWriter->endElement(); + + $objWriter->startElement('c:order'); + $objWriter->writeAttribute('val', $this->_seriesIndex + $plotSeriesRef); + $objWriter->endElement(); + + if (($groupType == PHPExcel_Chart_DataSeries::TYPE_PIECHART) || + ($groupType == PHPExcel_Chart_DataSeries::TYPE_PIECHART_3D) || + ($groupType == PHPExcel_Chart_DataSeries::TYPE_DONUTCHART)) { + + $objWriter->startElement('c:dPt'); + $objWriter->startElement('c:idx'); + $objWriter->writeAttribute('val', 3); + $objWriter->endElement(); + + $objWriter->startElement('c:bubble3D'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + + $objWriter->startElement('c:spPr'); + $objWriter->startElement('a:solidFill'); + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', 'FF9900'); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + } + + // Labels + $plotSeriesLabel = $plotGroup->getPlotLabelByIndex($plotSeriesRef); + if ($plotSeriesLabel && ($plotSeriesLabel->getPointCount() > 0)) { + $objWriter->startElement('c:tx'); + $objWriter->startElement('c:strRef'); + $this->_writePlotSeriesLabel($plotSeriesLabel, $objWriter); + $objWriter->endElement(); + $objWriter->endElement(); + } + + // Formatting for the points + if ($groupType == PHPExcel_Chart_DataSeries::TYPE_LINECHART) { + $objWriter->startElement('c:spPr'); + $objWriter->startElement('a:ln'); + $objWriter->writeAttribute('w', 12700); + $objWriter->endElement(); + $objWriter->endElement(); + } + + $plotSeriesValues = $plotGroup->getPlotValuesByIndex($plotSeriesRef); + if ($plotSeriesValues) { + $plotSeriesMarker = $plotSeriesValues->getPointMarker(); + if ($plotSeriesMarker) { + $objWriter->startElement('c:marker'); + $objWriter->startElement('c:symbol'); + $objWriter->writeAttribute('val', $plotSeriesMarker); + $objWriter->endElement(); + + if ($plotSeriesMarker !== 'none') { + $objWriter->startElement('c:size'); + $objWriter->writeAttribute('val', 3); + $objWriter->endElement(); + } + $objWriter->endElement(); + } + } + + if (($groupType === PHPExcel_Chart_DataSeries::TYPE_BARCHART) || + ($groupType === PHPExcel_Chart_DataSeries::TYPE_BARCHART_3D) || + ($groupType === PHPExcel_Chart_DataSeries::TYPE_BUBBLECHART)) { + + $objWriter->startElement('c:invertIfNegative'); + $objWriter->writeAttribute('val', 0); + $objWriter->endElement(); + } + + // Category Labels + $plotSeriesCategory = $plotGroup->getPlotCategoryByIndex($plotSeriesRef); + if ($plotSeriesCategory && ($plotSeriesCategory->getPointCount() > 0)) { + $catIsMultiLevelSeries = $catIsMultiLevelSeries || $plotSeriesCategory->isMultiLevelSeries(); + + if (($groupType == PHPExcel_Chart_DataSeries::TYPE_PIECHART) || + ($groupType == PHPExcel_Chart_DataSeries::TYPE_PIECHART_3D) || + ($groupType == PHPExcel_Chart_DataSeries::TYPE_DONUTCHART)) { + + if (!is_null($plotGroup->getPlotStyle())) { + $plotStyle = $plotGroup->getPlotStyle(); + if ($plotStyle) { + $objWriter->startElement('c:explosion'); + $objWriter->writeAttribute('val', 25); + $objWriter->endElement(); + } + } + } + + if (($groupType === PHPExcel_Chart_DataSeries::TYPE_BUBBLECHART) || + ($groupType === PHPExcel_Chart_DataSeries::TYPE_SCATTERCHART)) { + $objWriter->startElement('c:xVal'); + } else { + $objWriter->startElement('c:cat'); + } + + $this->_writePlotSeriesValues($plotSeriesCategory, $objWriter, $groupType, 'str', $pSheet); + $objWriter->endElement(); + } + + // Values + if ($plotSeriesValues) { + $valIsMultiLevelSeries = $valIsMultiLevelSeries || $plotSeriesValues->isMultiLevelSeries(); + + if (($groupType === PHPExcel_Chart_DataSeries::TYPE_BUBBLECHART) || + ($groupType === PHPExcel_Chart_DataSeries::TYPE_SCATTERCHART)) { + $objWriter->startElement('c:yVal'); + } else { + $objWriter->startElement('c:val'); + } + + $this->_writePlotSeriesValues($plotSeriesValues, $objWriter, $groupType, 'num', $pSheet); + $objWriter->endElement(); + } + + if ($groupType === PHPExcel_Chart_DataSeries::TYPE_BUBBLECHART) { + $this->_writeBubbles($plotSeriesValues, $objWriter, $pSheet); + } + + $objWriter->endElement(); + + } + + $this->_seriesIndex += $plotSeriesIdx + 1; + } + + /** + * Write Plot Series Label + * + * @param PHPExcel_Chart_DataSeriesValues $plotSeriesLabel + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writePlotSeriesLabel($plotSeriesLabel, $objWriter) + { + if (is_null($plotSeriesLabel)) { + return; + } + + $objWriter->startElement('c:f'); + $objWriter->writeRawData($plotSeriesLabel->getDataSource()); + $objWriter->endElement(); + + $objWriter->startElement('c:strCache'); + $objWriter->startElement('c:ptCount'); + $objWriter->writeAttribute('val', $plotSeriesLabel->getPointCount() ); + $objWriter->endElement(); + + foreach($plotSeriesLabel->getDataValues() as $plotLabelKey => $plotLabelValue) { + $objWriter->startElement('c:pt'); + $objWriter->writeAttribute('idx', $plotLabelKey ); + + $objWriter->startElement('c:v'); + $objWriter->writeRawData( $plotLabelValue ); + $objWriter->endElement(); + $objWriter->endElement(); + } + $objWriter->endElement(); + + } + + /** + * Write Plot Series Values + * + * @param PHPExcel_Chart_DataSeriesValues $plotSeriesValues + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $groupType Type of plot for dataseries + * @param string $dataType Datatype of series values + * @param PHPExcel_Worksheet $pSheet + * @throws PHPExcel_Writer_Exception + */ + private function _writePlotSeriesValues( $plotSeriesValues, + $objWriter, + $groupType, + $dataType='str', + PHPExcel_Worksheet $pSheet + ) + { + if (is_null($plotSeriesValues)) { + return; + } + + if ($plotSeriesValues->isMultiLevelSeries()) { + $levelCount = $plotSeriesValues->multiLevelCount(); + + $objWriter->startElement('c:multiLvlStrRef'); + + $objWriter->startElement('c:f'); + $objWriter->writeRawData( $plotSeriesValues->getDataSource() ); + $objWriter->endElement(); + + $objWriter->startElement('c:multiLvlStrCache'); + + $objWriter->startElement('c:ptCount'); + $objWriter->writeAttribute('val', $plotSeriesValues->getPointCount() ); + $objWriter->endElement(); + + for ($level = 0; $level < $levelCount; ++$level) { + $objWriter->startElement('c:lvl'); + + foreach($plotSeriesValues->getDataValues() as $plotSeriesKey => $plotSeriesValue) { + if (isset($plotSeriesValue[$level])) { + $objWriter->startElement('c:pt'); + $objWriter->writeAttribute('idx', $plotSeriesKey ); + + $objWriter->startElement('c:v'); + $objWriter->writeRawData( $plotSeriesValue[$level] ); + $objWriter->endElement(); + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + } + + $objWriter->endElement(); + + $objWriter->endElement(); + } else { + $objWriter->startElement('c:'.$dataType.'Ref'); + + $objWriter->startElement('c:f'); + $objWriter->writeRawData( $plotSeriesValues->getDataSource() ); + $objWriter->endElement(); + + $objWriter->startElement('c:'.$dataType.'Cache'); + + if (($groupType != PHPExcel_Chart_DataSeries::TYPE_PIECHART) && + ($groupType != PHPExcel_Chart_DataSeries::TYPE_PIECHART_3D) && + ($groupType != PHPExcel_Chart_DataSeries::TYPE_DONUTCHART)) { + + if (($plotSeriesValues->getFormatCode() !== NULL) && + ($plotSeriesValues->getFormatCode() !== '')) { + $objWriter->startElement('c:formatCode'); + $objWriter->writeRawData( $plotSeriesValues->getFormatCode() ); + $objWriter->endElement(); + } + } + + $objWriter->startElement('c:ptCount'); + $objWriter->writeAttribute('val', $plotSeriesValues->getPointCount() ); + $objWriter->endElement(); + + $dataValues = $plotSeriesValues->getDataValues(); + if (!empty($dataValues)) { + if (is_array($dataValues)) { + foreach($dataValues as $plotSeriesKey => $plotSeriesValue) { + $objWriter->startElement('c:pt'); + $objWriter->writeAttribute('idx', $plotSeriesKey ); + + $objWriter->startElement('c:v'); + $objWriter->writeRawData( $plotSeriesValue ); + $objWriter->endElement(); + $objWriter->endElement(); + } + } + } + + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + + /** + * Write Bubble Chart Details + * + * @param PHPExcel_Chart_DataSeriesValues $plotSeriesValues + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writeBubbles($plotSeriesValues, $objWriter, PHPExcel_Worksheet $pSheet) + { + if (is_null($plotSeriesValues)) { + return; + } + + $objWriter->startElement('c:bubbleSize'); + $objWriter->startElement('c:numLit'); + + $objWriter->startElement('c:formatCode'); + $objWriter->writeRawData( 'General' ); + $objWriter->endElement(); + + $objWriter->startElement('c:ptCount'); + $objWriter->writeAttribute('val', $plotSeriesValues->getPointCount() ); + $objWriter->endElement(); + + $dataValues = $plotSeriesValues->getDataValues(); + if (!empty($dataValues)) { + if (is_array($dataValues)) { + foreach($dataValues as $plotSeriesKey => $plotSeriesValue) { + $objWriter->startElement('c:pt'); + $objWriter->writeAttribute('idx', $plotSeriesKey ); + $objWriter->startElement('c:v'); + $objWriter->writeRawData( 1 ); + $objWriter->endElement(); + $objWriter->endElement(); + } + } + } + + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('c:bubble3D'); + $objWriter->writeAttribute('val', 0 ); + $objWriter->endElement(); + } + + /** + * Write Layout + * + * @param PHPExcel_Chart_Layout $layout + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writeLayout(PHPExcel_Chart_Layout $layout = NULL, $objWriter) + { + $objWriter->startElement('c:layout'); + + if (!is_null($layout)) { + $objWriter->startElement('c:manualLayout'); + + $layoutTarget = $layout->getLayoutTarget(); + if (!is_null($layoutTarget)) { + $objWriter->startElement('c:layoutTarget'); + $objWriter->writeAttribute('val', $layoutTarget); + $objWriter->endElement(); + } + + $xMode = $layout->getXMode(); + if (!is_null($xMode)) { + $objWriter->startElement('c:xMode'); + $objWriter->writeAttribute('val', $xMode); + $objWriter->endElement(); + } + + $yMode = $layout->getYMode(); + if (!is_null($yMode)) { + $objWriter->startElement('c:yMode'); + $objWriter->writeAttribute('val', $yMode); + $objWriter->endElement(); + } + + $x = $layout->getXPosition(); + if (!is_null($x)) { + $objWriter->startElement('c:x'); + $objWriter->writeAttribute('val', $x); + $objWriter->endElement(); + } + + $y = $layout->getYPosition(); + if (!is_null($y)) { + $objWriter->startElement('c:y'); + $objWriter->writeAttribute('val', $y); + $objWriter->endElement(); + } + + $w = $layout->getWidth(); + if (!is_null($w)) { + $objWriter->startElement('c:w'); + $objWriter->writeAttribute('val', $w); + $objWriter->endElement(); + } + + $h = $layout->getHeight(); + if (!is_null($h)) { + $objWriter->startElement('c:h'); + $objWriter->writeAttribute('val', $h); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + + /** + * Write Alternate Content block + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writeAlternateContent($objWriter) + { + $objWriter->startElement('mc:AlternateContent'); + $objWriter->writeAttribute('xmlns:mc', 'http://schemas.openxmlformats.org/markup-compatibility/2006'); + + $objWriter->startElement('mc:Choice'); + $objWriter->writeAttribute('xmlns:c14', 'http://schemas.microsoft.com/office/drawing/2007/8/2/chart'); + $objWriter->writeAttribute('Requires', 'c14'); + + $objWriter->startElement('c14:style'); + $objWriter->writeAttribute('val', '102'); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('mc:Fallback'); + $objWriter->startElement('c:style'); + $objWriter->writeAttribute('val', '2'); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write Printer Settings + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writePrintSettings($objWriter) + { + $objWriter->startElement('c:printSettings'); + + $objWriter->startElement('c:headerFooter'); + $objWriter->endElement(); + + $objWriter->startElement('c:pageMargins'); + $objWriter->writeAttribute('footer', 0.3); + $objWriter->writeAttribute('header', 0.3); + $objWriter->writeAttribute('r', 0.7); + $objWriter->writeAttribute('l', 0.7); + $objWriter->writeAttribute('t', 0.75); + $objWriter->writeAttribute('b', 0.75); + $objWriter->endElement(); + + $objWriter->startElement('c:pageSetup'); + $objWriter->writeAttribute('orientation', "portrait"); + $objWriter->endElement(); + + $objWriter->endElement(); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Comments.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Comments.php new file mode 100755 index 0000000..e7b9c99 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Comments.php @@ -0,0 +1,268 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_Comments + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007_Comments extends PHPExcel_Writer_Excel2007_WriterPart +{ + /** + * Write comments to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeComments(PHPExcel_Worksheet $pWorksheet = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Comments cache + $comments = $pWorksheet->getComments(); + + // Authors cache + $authors = array(); + $authorId = 0; + foreach ($comments as $comment) { + if (!isset($authors[$comment->getAuthor()])) { + $authors[$comment->getAuthor()] = $authorId++; + } + } + + // comments + $objWriter->startElement('comments'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); + + // Loop through authors + $objWriter->startElement('authors'); + foreach ($authors as $author => $index) { + $objWriter->writeElement('author', $author); + } + $objWriter->endElement(); + + // Loop through comments + $objWriter->startElement('commentList'); + foreach ($comments as $key => $value) { + $this->_writeComment($objWriter, $key, $value, $authors); + } + $objWriter->endElement(); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write comment to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pCellReference Cell reference + * @param PHPExcel_Comment $pComment Comment + * @param array $pAuthors Array of authors + * @throws PHPExcel_Writer_Exception + */ + public function _writeComment(PHPExcel_Shared_XMLWriter $objWriter = null, $pCellReference = 'A1', PHPExcel_Comment $pComment = null, $pAuthors = null) + { + // comment + $objWriter->startElement('comment'); + $objWriter->writeAttribute('ref', $pCellReference); + $objWriter->writeAttribute('authorId', $pAuthors[$pComment->getAuthor()]); + + // text + $objWriter->startElement('text'); + $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $pComment->getText()); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write VML comments to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeVMLComments(PHPExcel_Worksheet $pWorksheet = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Comments cache + $comments = $pWorksheet->getComments(); + + // xml + $objWriter->startElement('xml'); + $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); + $objWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office'); + $objWriter->writeAttribute('xmlns:x', 'urn:schemas-microsoft-com:office:excel'); + + // o:shapelayout + $objWriter->startElement('o:shapelayout'); + $objWriter->writeAttribute('v:ext', 'edit'); + + // o:idmap + $objWriter->startElement('o:idmap'); + $objWriter->writeAttribute('v:ext', 'edit'); + $objWriter->writeAttribute('data', '1'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // v:shapetype + $objWriter->startElement('v:shapetype'); + $objWriter->writeAttribute('id', '_x0000_t202'); + $objWriter->writeAttribute('coordsize', '21600,21600'); + $objWriter->writeAttribute('o:spt', '202'); + $objWriter->writeAttribute('path', 'm,l,21600r21600,l21600,xe'); + + // v:stroke + $objWriter->startElement('v:stroke'); + $objWriter->writeAttribute('joinstyle', 'miter'); + $objWriter->endElement(); + + // v:path + $objWriter->startElement('v:path'); + $objWriter->writeAttribute('gradientshapeok', 't'); + $objWriter->writeAttribute('o:connecttype', 'rect'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // Loop through comments + foreach ($comments as $key => $value) { + $this->_writeVMLComment($objWriter, $key, $value); + } + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write VML comment to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pCellReference Cell reference + * @param PHPExcel_Comment $pComment Comment + * @throws PHPExcel_Writer_Exception + */ + public function _writeVMLComment(PHPExcel_Shared_XMLWriter $objWriter = null, $pCellReference = 'A1', PHPExcel_Comment $pComment = null) + { + // Metadata + list($column, $row) = PHPExcel_Cell::coordinateFromString($pCellReference); + $column = PHPExcel_Cell::columnIndexFromString($column); + $id = 1024 + $column + $row; + $id = substr($id, 0, 4); + + // v:shape + $objWriter->startElement('v:shape'); + $objWriter->writeAttribute('id', '_x0000_s' . $id); + $objWriter->writeAttribute('type', '#_x0000_t202'); + $objWriter->writeAttribute('style', 'position:absolute;margin-left:' . $pComment->getMarginLeft() . ';margin-top:' . $pComment->getMarginTop() . ';width:' . $pComment->getWidth() . ';height:' . $pComment->getHeight() . ';z-index:1;visibility:' . ($pComment->getVisible() ? 'visible' : 'hidden')); + $objWriter->writeAttribute('fillcolor', '#' . $pComment->getFillColor()->getRGB()); + $objWriter->writeAttribute('o:insetmode', 'auto'); + + // v:fill + $objWriter->startElement('v:fill'); + $objWriter->writeAttribute('color2', '#' . $pComment->getFillColor()->getRGB()); + $objWriter->endElement(); + + // v:shadow + $objWriter->startElement('v:shadow'); + $objWriter->writeAttribute('on', 't'); + $objWriter->writeAttribute('color', 'black'); + $objWriter->writeAttribute('obscured', 't'); + $objWriter->endElement(); + + // v:path + $objWriter->startElement('v:path'); + $objWriter->writeAttribute('o:connecttype', 'none'); + $objWriter->endElement(); + + // v:textbox + $objWriter->startElement('v:textbox'); + $objWriter->writeAttribute('style', 'mso-direction-alt:auto'); + + // div + $objWriter->startElement('div'); + $objWriter->writeAttribute('style', 'text-align:left'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // x:ClientData + $objWriter->startElement('x:ClientData'); + $objWriter->writeAttribute('ObjectType', 'Note'); + + // x:MoveWithCells + $objWriter->writeElement('x:MoveWithCells', ''); + + // x:SizeWithCells + $objWriter->writeElement('x:SizeWithCells', ''); + + // x:Anchor + //$objWriter->writeElement('x:Anchor', $column . ', 15, ' . ($row - 2) . ', 10, ' . ($column + 4) . ', 15, ' . ($row + 5) . ', 18'); + + // x:AutoFill + $objWriter->writeElement('x:AutoFill', 'False'); + + // x:Row + $objWriter->writeElement('x:Row', ($row - 1)); + + // x:Column + $objWriter->writeElement('x:Column', ($column - 1)); + + $objWriter->endElement(); + + $objWriter->endElement(); + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php new file mode 100755 index 0000000..c50c73d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/ContentTypes.php @@ -0,0 +1,261 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_ContentTypes + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007_ContentTypes extends PHPExcel_Writer_Excel2007_WriterPart +{ + /** + * Write content types to XML format + * + * @param PHPExcel $pPHPExcel + * @param boolean $includeCharts Flag indicating if we should include drawing details for charts + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeContentTypes(PHPExcel $pPHPExcel = null, $includeCharts = FALSE) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Types + $objWriter->startElement('Types'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/content-types'); + + // Theme + $this->_writeOverrideContentType( + $objWriter, '/xl/theme/theme1.xml', 'application/vnd.openxmlformats-officedocument.theme+xml' + ); + + // Styles + $this->_writeOverrideContentType( + $objWriter, '/xl/styles.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml' + ); + + // Rels + $this->_writeDefaultContentType( + $objWriter, 'rels', 'application/vnd.openxmlformats-package.relationships+xml' + ); + + // XML + $this->_writeDefaultContentType( + $objWriter, 'xml', 'application/xml' + ); + + // VML + $this->_writeDefaultContentType( + $objWriter, 'vml', 'application/vnd.openxmlformats-officedocument.vmlDrawing' + ); + + // Workbook + $this->_writeOverrideContentType( + $objWriter, '/xl/workbook.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml' + ); + + // DocProps + $this->_writeOverrideContentType( + $objWriter, '/docProps/app.xml', 'application/vnd.openxmlformats-officedocument.extended-properties+xml' + ); + + $this->_writeOverrideContentType( + $objWriter, '/docProps/core.xml', 'application/vnd.openxmlformats-package.core-properties+xml' + ); + + $customPropertyList = $pPHPExcel->getProperties()->getCustomProperties(); + if (!empty($customPropertyList)) { + $this->_writeOverrideContentType( + $objWriter, '/docProps/custom.xml', 'application/vnd.openxmlformats-officedocument.custom-properties+xml' + ); + } + + // Worksheets + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + $this->_writeOverrideContentType( + $objWriter, '/xl/worksheets/sheet' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml' + ); + } + + // Shared strings + $this->_writeOverrideContentType( + $objWriter, '/xl/sharedStrings.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml' + ); + + // Add worksheet relationship content types + $chart = 1; + for ($i = 0; $i < $sheetCount; ++$i) { + $drawings = $pPHPExcel->getSheet($i)->getDrawingCollection(); + $drawingCount = count($drawings); + $chartCount = ($includeCharts) ? $pPHPExcel->getSheet($i)->getChartCount() : 0; + + // We need a drawing relationship for the worksheet if we have either drawings or charts + if (($drawingCount > 0) || ($chartCount > 0)) { + $this->_writeOverrideContentType( + $objWriter, '/xl/drawings/drawing' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.drawing+xml' + ); + } + + // If we have charts, then we need a chart relationship for every individual chart + if ($chartCount > 0) { + for ($c = 0; $c < $chartCount; ++$c) { + $this->_writeOverrideContentType( + $objWriter, '/xl/charts/chart' . $chart++ . '.xml', 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml' + ); + } + } + } + + // Comments + for ($i = 0; $i < $sheetCount; ++$i) { + if (count($pPHPExcel->getSheet($i)->getComments()) > 0) { + $this->_writeOverrideContentType( + $objWriter, '/xl/comments' . ($i + 1) . '.xml', 'application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml' + ); + } + } + + // Add media content-types + $aMediaContentTypes = array(); + $mediaCount = $this->getParentWriter()->getDrawingHashTable()->count(); + for ($i = 0; $i < $mediaCount; ++$i) { + $extension = ''; + $mimeType = ''; + + if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_Drawing) { + $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getExtension()); + $mimeType = $this->_getImageMimeType( $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getPath() ); + } else if ($this->getParentWriter()->getDrawingHashTable()->getByIndex($i) instanceof PHPExcel_Worksheet_MemoryDrawing) { + $extension = strtolower($this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType()); + $extension = explode('/', $extension); + $extension = $extension[1]; + + $mimeType = $this->getParentWriter()->getDrawingHashTable()->getByIndex($i)->getMimeType(); + } + + if (!isset( $aMediaContentTypes[$extension]) ) { + $aMediaContentTypes[$extension] = $mimeType; + + $this->_writeDefaultContentType( + $objWriter, $extension, $mimeType + ); + } + } + + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + if (count($pPHPExcel->getSheet()->getHeaderFooter()->getImages()) > 0) { + foreach ($pPHPExcel->getSheet()->getHeaderFooter()->getImages() as $image) { + if (!isset( $aMediaContentTypes[strtolower($image->getExtension())]) ) { + $aMediaContentTypes[strtolower($image->getExtension())] = $this->_getImageMimeType( $image->getPath() ); + + $this->_writeDefaultContentType( + $objWriter, strtolower($image->getExtension()), $aMediaContentTypes[strtolower($image->getExtension())] + ); + } + } + } + } + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Get image mime type + * + * @param string $pFile Filename + * @return string Mime Type + * @throws PHPExcel_Writer_Exception + */ + private function _getImageMimeType($pFile = '') + { + if (PHPExcel_Shared_File::file_exists($pFile)) { + $image = getimagesize($pFile); + return image_type_to_mime_type($image[2]); + } else { + throw new PHPExcel_Writer_Exception("File $pFile does not exist"); + } + } + + /** + * Write Default content type + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pPartname Part name + * @param string $pContentType Content type + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefaultContentType(PHPExcel_Shared_XMLWriter $objWriter = null, $pPartname = '', $pContentType = '') + { + if ($pPartname != '' && $pContentType != '') { + // Write content type + $objWriter->startElement('Default'); + $objWriter->writeAttribute('Extension', $pPartname); + $objWriter->writeAttribute('ContentType', $pContentType); + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } + + /** + * Write Override content type + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pPartname Part name + * @param string $pContentType Content type + * @throws PHPExcel_Writer_Exception + */ + private function _writeOverrideContentType(PHPExcel_Shared_XMLWriter $objWriter = null, $pPartname = '', $pContentType = '') + { + if ($pPartname != '' && $pContentType != '') { + // Write content type + $objWriter->startElement('Override'); + $objWriter->writeAttribute('PartName', $pPartname); + $objWriter->writeAttribute('ContentType', $pContentType); + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/DocProps.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/DocProps.php new file mode 100755 index 0000000..37cd54b --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/DocProps.php @@ -0,0 +1,272 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_DocProps + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007_DocProps extends PHPExcel_Writer_Excel2007_WriterPart +{ +/** + * Write docProps/app.xml to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDocPropsApp(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Properties + $objWriter->startElement('Properties'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/extended-properties'); + $objWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); + + // Application + $objWriter->writeElement('Application', 'Microsoft Excel'); + + // DocSecurity + $objWriter->writeElement('DocSecurity', '0'); + + // ScaleCrop + $objWriter->writeElement('ScaleCrop', 'false'); + + // HeadingPairs + $objWriter->startElement('HeadingPairs'); + + // Vector + $objWriter->startElement('vt:vector'); + $objWriter->writeAttribute('size', '2'); + $objWriter->writeAttribute('baseType', 'variant'); + + // Variant + $objWriter->startElement('vt:variant'); + $objWriter->writeElement('vt:lpstr', 'Worksheets'); + $objWriter->endElement(); + + // Variant + $objWriter->startElement('vt:variant'); + $objWriter->writeElement('vt:i4', $pPHPExcel->getSheetCount()); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // TitlesOfParts + $objWriter->startElement('TitlesOfParts'); + + // Vector + $objWriter->startElement('vt:vector'); + $objWriter->writeAttribute('size', $pPHPExcel->getSheetCount()); + $objWriter->writeAttribute('baseType', 'lpstr'); + + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + $objWriter->writeElement('vt:lpstr', $pPHPExcel->getSheet($i)->getTitle()); + } + + $objWriter->endElement(); + + $objWriter->endElement(); + + // Company + $objWriter->writeElement('Company', $pPHPExcel->getProperties()->getCompany()); + + // Company + $objWriter->writeElement('Manager', $pPHPExcel->getProperties()->getManager()); + + // LinksUpToDate + $objWriter->writeElement('LinksUpToDate', 'false'); + + // SharedDoc + $objWriter->writeElement('SharedDoc', 'false'); + + // HyperlinksChanged + $objWriter->writeElement('HyperlinksChanged', 'false'); + + // AppVersion + $objWriter->writeElement('AppVersion', '12.0000'); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write docProps/core.xml to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDocPropsCore(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // cp:coreProperties + $objWriter->startElement('cp:coreProperties'); + $objWriter->writeAttribute('xmlns:cp', 'http://schemas.openxmlformats.org/package/2006/metadata/core-properties'); + $objWriter->writeAttribute('xmlns:dc', 'http://purl.org/dc/elements/1.1/'); + $objWriter->writeAttribute('xmlns:dcterms', 'http://purl.org/dc/terms/'); + $objWriter->writeAttribute('xmlns:dcmitype', 'http://purl.org/dc/dcmitype/'); + $objWriter->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance'); + + // dc:creator + $objWriter->writeElement('dc:creator', $pPHPExcel->getProperties()->getCreator()); + + // cp:lastModifiedBy + $objWriter->writeElement('cp:lastModifiedBy', $pPHPExcel->getProperties()->getLastModifiedBy()); + + // dcterms:created + $objWriter->startElement('dcterms:created'); + $objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); + $objWriter->writeRawData(date(DATE_W3C, $pPHPExcel->getProperties()->getCreated())); + $objWriter->endElement(); + + // dcterms:modified + $objWriter->startElement('dcterms:modified'); + $objWriter->writeAttribute('xsi:type', 'dcterms:W3CDTF'); + $objWriter->writeRawData(date(DATE_W3C, $pPHPExcel->getProperties()->getModified())); + $objWriter->endElement(); + + // dc:title + $objWriter->writeElement('dc:title', $pPHPExcel->getProperties()->getTitle()); + + // dc:description + $objWriter->writeElement('dc:description', $pPHPExcel->getProperties()->getDescription()); + + // dc:subject + $objWriter->writeElement('dc:subject', $pPHPExcel->getProperties()->getSubject()); + + // cp:keywords + $objWriter->writeElement('cp:keywords', $pPHPExcel->getProperties()->getKeywords()); + + // cp:category + $objWriter->writeElement('cp:category', $pPHPExcel->getProperties()->getCategory()); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write docProps/custom.xml to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDocPropsCustom(PHPExcel $pPHPExcel = null) + { + $customPropertyList = $pPHPExcel->getProperties()->getCustomProperties(); + if (empty($customPropertyList)) { + return; + } + + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // cp:coreProperties + $objWriter->startElement('Properties'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/officeDocument/2006/custom-properties'); + $objWriter->writeAttribute('xmlns:vt', 'http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'); + + + foreach($customPropertyList as $key => $customProperty) { + $propertyValue = $pPHPExcel->getProperties()->getCustomPropertyValue($customProperty); + $propertyType = $pPHPExcel->getProperties()->getCustomPropertyType($customProperty); + + $objWriter->startElement('property'); + $objWriter->writeAttribute('fmtid', '{D5CDD505-2E9C-101B-9397-08002B2CF9AE}'); + $objWriter->writeAttribute('pid', $key+2); + $objWriter->writeAttribute('name', $customProperty); + + switch($propertyType) { + case 'i' : + $objWriter->writeElement('vt:i4', $propertyValue); + break; + case 'f' : + $objWriter->writeElement('vt:r8', $propertyValue); + break; + case 'b' : + $objWriter->writeElement('vt:bool', ($propertyValue) ? 'true' : 'false'); + break; + case 'd' : + $objWriter->startElement('vt:filetime'); + $objWriter->writeRawData(date(DATE_W3C, $propertyValue)); + $objWriter->endElement(); + break; + default : + $objWriter->writeElement('vt:lpwstr', $propertyValue); + break; + } + + $objWriter->endElement(); + } + + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Drawing.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Drawing.php new file mode 100755 index 0000000..d410c5d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Drawing.php @@ -0,0 +1,598 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_Drawing + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007_Drawing extends PHPExcel_Writer_Excel2007_WriterPart +{ + /** + * Write drawings to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @param int &$chartRef Chart ID + * @param boolean $includeCharts Flag indicating if we should include drawing details for charts + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDrawings(PHPExcel_Worksheet $pWorksheet = null, &$chartRef, $includeCharts = FALSE) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // xdr:wsDr + $objWriter->startElement('xdr:wsDr'); + $objWriter->writeAttribute('xmlns:xdr', 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing'); + $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + + // Loop through images and write drawings + $i = 1; + $iterator = $pWorksheet->getDrawingCollection()->getIterator(); + while ($iterator->valid()) { + $this->_writeDrawing($objWriter, $iterator->current(), $i); + + $iterator->next(); + ++$i; + } + + if ($includeCharts) { + $chartCount = $pWorksheet->getChartCount(); + // Loop through charts and write the chart position + if ($chartCount > 0) { + for ($c = 0; $c < $chartCount; ++$c) { + $this->_writeChart($objWriter, $pWorksheet->getChartByIndex($c), $c+$i); + } + } + } + + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write drawings to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Chart $pChart + * @param int $pRelationId + * @throws PHPExcel_Writer_Exception + */ + public function _writeChart(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Chart $pChart = null, $pRelationId = -1) + { + $tl = $pChart->getTopLeftPosition(); + $tl['colRow'] = PHPExcel_Cell::coordinateFromString($tl['cell']); + $br = $pChart->getBottomRightPosition(); + $br['colRow'] = PHPExcel_Cell::coordinateFromString($br['cell']); + + $objWriter->startElement('xdr:twoCellAnchor'); + + $objWriter->startElement('xdr:from'); + $objWriter->writeElement('xdr:col', PHPExcel_Cell::columnIndexFromString($tl['colRow'][0]) - 1); + $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($tl['xOffset'])); + $objWriter->writeElement('xdr:row', $tl['colRow'][1] - 1); + $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($tl['yOffset'])); + $objWriter->endElement(); + $objWriter->startElement('xdr:to'); + $objWriter->writeElement('xdr:col', PHPExcel_Cell::columnIndexFromString($br['colRow'][0]) - 1); + $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($br['xOffset'])); + $objWriter->writeElement('xdr:row', $br['colRow'][1] - 1); + $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($br['yOffset'])); + $objWriter->endElement(); + + $objWriter->startElement('xdr:graphicFrame'); + $objWriter->writeAttribute('macro', ''); + $objWriter->startElement('xdr:nvGraphicFramePr'); + $objWriter->startElement('xdr:cNvPr'); + $objWriter->writeAttribute('name', 'Chart '.$pRelationId); + $objWriter->writeAttribute('id', 1025 * $pRelationId); + $objWriter->endElement(); + $objWriter->startElement('xdr:cNvGraphicFramePr'); + $objWriter->startElement('a:graphicFrameLocks'); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('xdr:xfrm'); + $objWriter->startElement('a:off'); + $objWriter->writeAttribute('x', '0'); + $objWriter->writeAttribute('y', '0'); + $objWriter->endElement(); + $objWriter->startElement('a:ext'); + $objWriter->writeAttribute('cx', '0'); + $objWriter->writeAttribute('cy', '0'); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('a:graphic'); + $objWriter->startElement('a:graphicData'); + $objWriter->writeAttribute('uri', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $objWriter->startElement('c:chart'); + $objWriter->writeAttribute('xmlns:c', 'http://schemas.openxmlformats.org/drawingml/2006/chart'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $objWriter->writeAttribute('r:id', 'rId'.$pRelationId); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + $objWriter->endElement(); + + $objWriter->startElement('xdr:clientData'); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write drawings to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet_BaseDrawing $pDrawing + * @param int $pRelationId + * @throws PHPExcel_Writer_Exception + */ + public function _writeDrawing(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet_BaseDrawing $pDrawing = null, $pRelationId = -1) + { + if ($pRelationId >= 0) { + // xdr:oneCellAnchor + $objWriter->startElement('xdr:oneCellAnchor'); + // Image location + $aCoordinates = PHPExcel_Cell::coordinateFromString($pDrawing->getCoordinates()); + $aCoordinates[0] = PHPExcel_Cell::columnIndexFromString($aCoordinates[0]); + + // xdr:from + $objWriter->startElement('xdr:from'); + $objWriter->writeElement('xdr:col', $aCoordinates[0] - 1); + $objWriter->writeElement('xdr:colOff', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getOffsetX())); + $objWriter->writeElement('xdr:row', $aCoordinates[1] - 1); + $objWriter->writeElement('xdr:rowOff', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getOffsetY())); + $objWriter->endElement(); + + // xdr:ext + $objWriter->startElement('xdr:ext'); + $objWriter->writeAttribute('cx', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getWidth())); + $objWriter->writeAttribute('cy', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getHeight())); + $objWriter->endElement(); + + // xdr:pic + $objWriter->startElement('xdr:pic'); + + // xdr:nvPicPr + $objWriter->startElement('xdr:nvPicPr'); + + // xdr:cNvPr + $objWriter->startElement('xdr:cNvPr'); + $objWriter->writeAttribute('id', $pRelationId); + $objWriter->writeAttribute('name', $pDrawing->getName()); + $objWriter->writeAttribute('descr', $pDrawing->getDescription()); + $objWriter->endElement(); + + // xdr:cNvPicPr + $objWriter->startElement('xdr:cNvPicPr'); + + // a:picLocks + $objWriter->startElement('a:picLocks'); + $objWriter->writeAttribute('noChangeAspect', '1'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // xdr:blipFill + $objWriter->startElement('xdr:blipFill'); + + // a:blip + $objWriter->startElement('a:blip'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + $objWriter->writeAttribute('r:embed', 'rId' . $pRelationId); + $objWriter->endElement(); + + // a:stretch + $objWriter->startElement('a:stretch'); + $objWriter->writeElement('a:fillRect', null); + $objWriter->endElement(); + + $objWriter->endElement(); + + // xdr:spPr + $objWriter->startElement('xdr:spPr'); + + // a:xfrm + $objWriter->startElement('a:xfrm'); + $objWriter->writeAttribute('rot', PHPExcel_Shared_Drawing::degreesToAngle($pDrawing->getRotation())); + $objWriter->endElement(); + + // a:prstGeom + $objWriter->startElement('a:prstGeom'); + $objWriter->writeAttribute('prst', 'rect'); + + // a:avLst + $objWriter->writeElement('a:avLst', null); + + $objWriter->endElement(); + +// // a:solidFill +// $objWriter->startElement('a:solidFill'); + +// // a:srgbClr +// $objWriter->startElement('a:srgbClr'); +// $objWriter->writeAttribute('val', 'FFFFFF'); + +///* SHADE +// // a:shade +// $objWriter->startElement('a:shade'); +// $objWriter->writeAttribute('val', '85000'); +// $objWriter->endElement(); +//*/ + +// $objWriter->endElement(); + +// $objWriter->endElement(); +/* + // a:ln + $objWriter->startElement('a:ln'); + $objWriter->writeAttribute('w', '88900'); + $objWriter->writeAttribute('cap', 'sq'); + + // a:solidFill + $objWriter->startElement('a:solidFill'); + + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', 'FFFFFF'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:miter + $objWriter->startElement('a:miter'); + $objWriter->writeAttribute('lim', '800000'); + $objWriter->endElement(); + + $objWriter->endElement(); +*/ + + if ($pDrawing->getShadow()->getVisible()) { + // a:effectLst + $objWriter->startElement('a:effectLst'); + + // a:outerShdw + $objWriter->startElement('a:outerShdw'); + $objWriter->writeAttribute('blurRad', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getShadow()->getBlurRadius())); + $objWriter->writeAttribute('dist', PHPExcel_Shared_Drawing::pixelsToEMU($pDrawing->getShadow()->getDistance())); + $objWriter->writeAttribute('dir', PHPExcel_Shared_Drawing::degreesToAngle($pDrawing->getShadow()->getDirection())); + $objWriter->writeAttribute('algn', $pDrawing->getShadow()->getAlignment()); + $objWriter->writeAttribute('rotWithShape', '0'); + + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', $pDrawing->getShadow()->getColor()->getRGB()); + + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', $pDrawing->getShadow()->getAlpha() * 1000); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + } +/* + + // a:scene3d + $objWriter->startElement('a:scene3d'); + + // a:camera + $objWriter->startElement('a:camera'); + $objWriter->writeAttribute('prst', 'orthographicFront'); + $objWriter->endElement(); + + // a:lightRig + $objWriter->startElement('a:lightRig'); + $objWriter->writeAttribute('rig', 'twoPt'); + $objWriter->writeAttribute('dir', 't'); + + // a:rot + $objWriter->startElement('a:rot'); + $objWriter->writeAttribute('lat', '0'); + $objWriter->writeAttribute('lon', '0'); + $objWriter->writeAttribute('rev', '0'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); +*/ +/* + // a:sp3d + $objWriter->startElement('a:sp3d'); + + // a:bevelT + $objWriter->startElement('a:bevelT'); + $objWriter->writeAttribute('w', '25400'); + $objWriter->writeAttribute('h', '19050'); + $objWriter->endElement(); + + // a:contourClr + $objWriter->startElement('a:contourClr'); + + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', 'FFFFFF'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); +*/ + $objWriter->endElement(); + + $objWriter->endElement(); + + // xdr:clientData + $objWriter->writeElement('xdr:clientData', null); + + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } + + /** + * Write VML header/footer images to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeVMLHeaderFooterImages(PHPExcel_Worksheet $pWorksheet = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Header/footer images + $images = $pWorksheet->getHeaderFooter()->getImages(); + + // xml + $objWriter->startElement('xml'); + $objWriter->writeAttribute('xmlns:v', 'urn:schemas-microsoft-com:vml'); + $objWriter->writeAttribute('xmlns:o', 'urn:schemas-microsoft-com:office:office'); + $objWriter->writeAttribute('xmlns:x', 'urn:schemas-microsoft-com:office:excel'); + + // o:shapelayout + $objWriter->startElement('o:shapelayout'); + $objWriter->writeAttribute('v:ext', 'edit'); + + // o:idmap + $objWriter->startElement('o:idmap'); + $objWriter->writeAttribute('v:ext', 'edit'); + $objWriter->writeAttribute('data', '1'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // v:shapetype + $objWriter->startElement('v:shapetype'); + $objWriter->writeAttribute('id', '_x0000_t75'); + $objWriter->writeAttribute('coordsize', '21600,21600'); + $objWriter->writeAttribute('o:spt', '75'); + $objWriter->writeAttribute('o:preferrelative', 't'); + $objWriter->writeAttribute('path', 'm@4@5l@4@11@9@11@9@5xe'); + $objWriter->writeAttribute('filled', 'f'); + $objWriter->writeAttribute('stroked', 'f'); + + // v:stroke + $objWriter->startElement('v:stroke'); + $objWriter->writeAttribute('joinstyle', 'miter'); + $objWriter->endElement(); + + // v:formulas + $objWriter->startElement('v:formulas'); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'if lineDrawn pixelLineWidth 0'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @0 1 0'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum 0 0 @1'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @2 1 2'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelWidth'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelHeight'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @0 0 1'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @6 1 2'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelWidth'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @8 21600 0'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelHeight'); + $objWriter->endElement(); + + // v:f + $objWriter->startElement('v:f'); + $objWriter->writeAttribute('eqn', 'sum @10 21600 0'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // v:path + $objWriter->startElement('v:path'); + $objWriter->writeAttribute('o:extrusionok', 'f'); + $objWriter->writeAttribute('gradientshapeok', 't'); + $objWriter->writeAttribute('o:connecttype', 'rect'); + $objWriter->endElement(); + + // o:lock + $objWriter->startElement('o:lock'); + $objWriter->writeAttribute('v:ext', 'edit'); + $objWriter->writeAttribute('aspectratio', 't'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // Loop through images + foreach ($images as $key => $value) { + $this->_writeVMLHeaderFooterImage($objWriter, $key, $value); + } + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write VML comment to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pReference Reference + * @param PHPExcel_Worksheet_HeaderFooterDrawing $pImage Image + * @throws PHPExcel_Writer_Exception + */ + public function _writeVMLHeaderFooterImage(PHPExcel_Shared_XMLWriter $objWriter = null, $pReference = '', PHPExcel_Worksheet_HeaderFooterDrawing $pImage = null) + { + // Calculate object id + preg_match('{(\d+)}', md5($pReference), $m); + $id = 1500 + (substr($m[1], 0, 2) * 1); + + // Calculate offset + $width = $pImage->getWidth(); + $height = $pImage->getHeight(); + $marginLeft = $pImage->getOffsetX(); + $marginTop = $pImage->getOffsetY(); + + // v:shape + $objWriter->startElement('v:shape'); + $objWriter->writeAttribute('id', $pReference); + $objWriter->writeAttribute('o:spid', '_x0000_s' . $id); + $objWriter->writeAttribute('type', '#_x0000_t75'); + $objWriter->writeAttribute('style', "position:absolute;margin-left:{$marginLeft}px;margin-top:{$marginTop}px;width:{$width}px;height:{$height}px;z-index:1"); + + // v:imagedata + $objWriter->startElement('v:imagedata'); + $objWriter->writeAttribute('o:relid', 'rId' . $pReference); + $objWriter->writeAttribute('o:title', $pImage->getName()); + $objWriter->endElement(); + + // o:lock + $objWriter->startElement('o:lock'); + $objWriter->writeAttribute('v:ext', 'edit'); + $objWriter->writeAttribute('rotation', 't'); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + + /** + * Get an array of all drawings + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Worksheet_Drawing[] All drawings in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allDrawings(PHPExcel $pPHPExcel = null) + { + // Get an array of all drawings + $aDrawings = array(); + + // Loop through PHPExcel + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + // Loop through images and add to array + $iterator = $pPHPExcel->getSheet($i)->getDrawingCollection()->getIterator(); + while ($iterator->valid()) { + $aDrawings[] = $iterator->current(); + + $iterator->next(); + } + } + + return $aDrawings; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Rels.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Rels.php new file mode 100755 index 0000000..4795c2f --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Rels.php @@ -0,0 +1,417 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_Rels + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007_Rels extends PHPExcel_Writer_Excel2007_WriterPart +{ + /** + * Write relationships to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeRelationships(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + + $customPropertyList = $pPHPExcel->getProperties()->getCustomProperties(); + if (!empty($customPropertyList)) { + // Relationship docProps/app.xml + $this->_writeRelationship( + $objWriter, + 4, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties', + 'docProps/custom.xml' + ); + + } + + // Relationship docProps/app.xml + $this->_writeRelationship( + $objWriter, + 3, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties', + 'docProps/app.xml' + ); + + // Relationship docProps/core.xml + $this->_writeRelationship( + $objWriter, + 2, + 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties', + 'docProps/core.xml' + ); + + // Relationship xl/workbook.xml + $this->_writeRelationship( + $objWriter, + 1, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument', + 'xl/workbook.xml' + ); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write workbook relationships to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeWorkbookRelationships(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + + // Relationship styles.xml + $this->_writeRelationship( + $objWriter, + 1, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles', + 'styles.xml' + ); + + // Relationship theme/theme1.xml + $this->_writeRelationship( + $objWriter, + 2, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme', + 'theme/theme1.xml' + ); + + // Relationship sharedStrings.xml + $this->_writeRelationship( + $objWriter, + 3, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings', + 'sharedStrings.xml' + ); + + // Relationships with sheets + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + $this->_writeRelationship( + $objWriter, + ($i + 1 + 3), + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet', + 'worksheets/sheet' . ($i + 1) . '.xml' + ); + } + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write worksheet relationships to XML format + * + * Numbering is as follows: + * rId1 - Drawings + * rId_hyperlink_x - Hyperlinks + * + * @param PHPExcel_Worksheet $pWorksheet + * @param int $pWorksheetId + * @param boolean $includeCharts Flag indicating if we should write charts + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeWorksheetRelationships(PHPExcel_Worksheet $pWorksheet = null, $pWorksheetId = 1, $includeCharts = FALSE) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + + // Write drawing relationships? + $d = 0; + if ($includeCharts) { + $charts = $pWorksheet->getChartCollection(); + } else { + $charts = array(); + } + if (($pWorksheet->getDrawingCollection()->count() > 0) || + (count($charts) > 0)) { + $this->_writeRelationship( + $objWriter, + ++$d, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing', + '../drawings/drawing' . $pWorksheetId . '.xml' + ); + } + + // Write chart relationships? +// $chartCount = 0; +// $charts = $pWorksheet->getChartCollection(); +// echo 'Chart Rels: ' , count($charts) , '<br />'; +// if (count($charts) > 0) { +// foreach($charts as $chart) { +// $this->_writeRelationship( +// $objWriter, +// ++$d, +// 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', +// '../charts/chart' . ++$chartCount . '.xml' +// ); +// } +// } +// + // Write hyperlink relationships? + $i = 1; + foreach ($pWorksheet->getHyperlinkCollection() as $hyperlink) { + if (!$hyperlink->isInternal()) { + $this->_writeRelationship( + $objWriter, + '_hyperlink_' . $i, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink', + $hyperlink->getUrl(), + 'External' + ); + + ++$i; + } + } + + // Write comments relationship? + $i = 1; + if (count($pWorksheet->getComments()) > 0) { + $this->_writeRelationship( + $objWriter, + '_comments_vml' . $i, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing', + '../drawings/vmlDrawing' . $pWorksheetId . '.vml' + ); + + $this->_writeRelationship( + $objWriter, + '_comments' . $i, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments', + '../comments' . $pWorksheetId . '.xml' + ); + } + + // Write header/footer relationship? + $i = 1; + if (count($pWorksheet->getHeaderFooter()->getImages()) > 0) { + $this->_writeRelationship( + $objWriter, + '_headerfooter_vml' . $i, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing', + '../drawings/vmlDrawingHF' . $pWorksheetId . '.vml' + ); + } + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write drawing relationships to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @param int &$chartRef Chart ID + * @param boolean $includeCharts Flag indicating if we should write charts + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeDrawingRelationships(PHPExcel_Worksheet $pWorksheet = null, &$chartRef, $includeCharts = FALSE) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + + // Loop through images and write relationships + $i = 1; + $iterator = $pWorksheet->getDrawingCollection()->getIterator(); + while ($iterator->valid()) { + if ($iterator->current() instanceof PHPExcel_Worksheet_Drawing + || $iterator->current() instanceof PHPExcel_Worksheet_MemoryDrawing) { + // Write relationship for image drawing + $this->_writeRelationship( + $objWriter, + $i, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', + '../media/' . str_replace(' ', '', $iterator->current()->getIndexedFilename()) + ); + } + + $iterator->next(); + ++$i; + } + + if ($includeCharts) { + // Loop through charts and write relationships + $chartCount = $pWorksheet->getChartCount(); + if ($chartCount > 0) { + for ($c = 0; $c < $chartCount; ++$c) { + $this->_writeRelationship( + $objWriter, + $i++, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', + '../charts/chart' . ++$chartRef . '.xml' + ); + } + } + } + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write header/footer drawing relationships to XML format + * + * @param PHPExcel_Worksheet $pWorksheet + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeHeaderFooterDrawingRelationships(PHPExcel_Worksheet $pWorksheet = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Relationships + $objWriter->startElement('Relationships'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/package/2006/relationships'); + + // Loop through images and write relationships + foreach ($pWorksheet->getHeaderFooter()->getImages() as $key => $value) { + // Write relationship for image drawing + $this->_writeRelationship( + $objWriter, + $key, + 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image', + '../media/' . $value->getIndexedFilename() + ); + } + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write Override content type + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param int $pId Relationship ID. rId will be prepended! + * @param string $pType Relationship type + * @param string $pTarget Relationship target + * @param string $pTargetMode Relationship target mode + * @throws PHPExcel_Writer_Exception + */ + private function _writeRelationship(PHPExcel_Shared_XMLWriter $objWriter = null, $pId = 1, $pType = '', $pTarget = '', $pTargetMode = '') + { + if ($pType != '' && $pTarget != '') { + // Write relationship + $objWriter->startElement('Relationship'); + $objWriter->writeAttribute('Id', 'rId' . $pId); + $objWriter->writeAttribute('Type', $pType); + $objWriter->writeAttribute('Target', $pTarget); + + if ($pTargetMode != '') { + $objWriter->writeAttribute('TargetMode', $pTargetMode); + } + + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/StringTable.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/StringTable.php new file mode 100755 index 0000000..6ac31c6 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/StringTable.php @@ -0,0 +1,319 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_StringTable + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007_StringTable extends PHPExcel_Writer_Excel2007_WriterPart +{ + /** + * Create worksheet stringtable + * + * @param PHPExcel_Worksheet $pSheet Worksheet + * @param string[] $pExistingTable Existing table to eventually merge with + * @return string[] String table for worksheet + * @throws PHPExcel_Writer_Exception + */ + public function createStringTable($pSheet = null, $pExistingTable = null) + { + if ($pSheet !== NULL) { + // Create string lookup table + $aStringTable = array(); + $cellCollection = null; + $aFlippedStringTable = null; // For faster lookup + + // Is an existing table given? + if (($pExistingTable !== NULL) && is_array($pExistingTable)) { + $aStringTable = $pExistingTable; + } + + // Fill index array + $aFlippedStringTable = $this->flipStringTable($aStringTable); + + // Loop through cells + foreach ($pSheet->getCellCollection() as $cellID) { + $cell = $pSheet->getCell($cellID); + $cellValue = $cell->getValue(); + if (!is_object($cellValue) && + ($cellValue !== NULL) && + $cellValue !== '' && + !isset($aFlippedStringTable[$cellValue]) && + ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_STRING || $cell->getDataType() == PHPExcel_Cell_DataType::TYPE_STRING2 || $cell->getDataType() == PHPExcel_Cell_DataType::TYPE_NULL)) { + $aStringTable[] = $cellValue; + $aFlippedStringTable[$cellValue] = true; + } elseif ($cellValue instanceof PHPExcel_RichText && + ($cellValue !== NULL) && + !isset($aFlippedStringTable[$cellValue->getHashCode()])) { + $aStringTable[] = $cellValue; + $aFlippedStringTable[$cellValue->getHashCode()] = true; + } + } + + // Return + return $aStringTable; + } else { + throw new PHPExcel_Writer_Exception("Invalid PHPExcel_Worksheet object passed."); + } + } + + /** + * Write string table to XML format + * + * @param string[] $pStringTable + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeStringTable($pStringTable = null) + { + if ($pStringTable !== NULL) { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // String table + $objWriter->startElement('sst'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); + $objWriter->writeAttribute('uniqueCount', count($pStringTable)); + + // Loop through string table + foreach ($pStringTable as $textElement) { + $objWriter->startElement('si'); + + if (! $textElement instanceof PHPExcel_RichText) { + $textToWrite = PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $textElement ); + $objWriter->startElement('t'); + if ($textToWrite !== trim($textToWrite)) { + $objWriter->writeAttribute('xml:space', 'preserve'); + } + $objWriter->writeRawData($textToWrite); + $objWriter->endElement(); + } else if ($textElement instanceof PHPExcel_RichText) { + $this->writeRichText($objWriter, $textElement); + } + + $objWriter->endElement(); + } + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } else { + throw new PHPExcel_Writer_Exception("Invalid string table array passed."); + } + } + + /** + * Write Rich Text + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_RichText $pRichText Rich text + * @param string $prefix Optional Namespace prefix + * @throws PHPExcel_Writer_Exception + */ + public function writeRichText(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_RichText $pRichText = null, $prefix=NULL) + { + if ($prefix !== NULL) + $prefix .= ':'; + // Loop through rich text elements + $elements = $pRichText->getRichTextElements(); + foreach ($elements as $element) { + // r + $objWriter->startElement($prefix.'r'); + + // rPr + if ($element instanceof PHPExcel_RichText_Run) { + // rPr + $objWriter->startElement($prefix.'rPr'); + + // rFont + $objWriter->startElement($prefix.'rFont'); + $objWriter->writeAttribute('val', $element->getFont()->getName()); + $objWriter->endElement(); + + // Bold + $objWriter->startElement($prefix.'b'); + $objWriter->writeAttribute('val', ($element->getFont()->getBold() ? 'true' : 'false')); + $objWriter->endElement(); + + // Italic + $objWriter->startElement($prefix.'i'); + $objWriter->writeAttribute('val', ($element->getFont()->getItalic() ? 'true' : 'false')); + $objWriter->endElement(); + + // Superscript / subscript + if ($element->getFont()->getSuperScript() || $element->getFont()->getSubScript()) { + $objWriter->startElement($prefix.'vertAlign'); + if ($element->getFont()->getSuperScript()) { + $objWriter->writeAttribute('val', 'superscript'); + } else if ($element->getFont()->getSubScript()) { + $objWriter->writeAttribute('val', 'subscript'); + } + $objWriter->endElement(); + } + + // Strikethrough + $objWriter->startElement($prefix.'strike'); + $objWriter->writeAttribute('val', ($element->getFont()->getStrikethrough() ? 'true' : 'false')); + $objWriter->endElement(); + + // Color + $objWriter->startElement($prefix.'color'); + $objWriter->writeAttribute('rgb', $element->getFont()->getColor()->getARGB()); + $objWriter->endElement(); + + // Size + $objWriter->startElement($prefix.'sz'); + $objWriter->writeAttribute('val', $element->getFont()->getSize()); + $objWriter->endElement(); + + // Underline + $objWriter->startElement($prefix.'u'); + $objWriter->writeAttribute('val', $element->getFont()->getUnderline()); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + // t + $objWriter->startElement($prefix.'t'); + $objWriter->writeAttribute('xml:space', 'preserve'); + $objWriter->writeRawData(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $element->getText() )); + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + + /** + * Write Rich Text + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string|PHPExcel_RichText $pRichText text string or Rich text + * @param string $prefix Optional Namespace prefix + * @throws PHPExcel_Writer_Exception + */ + public function writeRichTextForCharts(PHPExcel_Shared_XMLWriter $objWriter = null, $pRichText = null, $prefix=NULL) + { + if (!$pRichText instanceof PHPExcel_RichText) { + $textRun = $pRichText; + $pRichText = new PHPExcel_RichText(); + $pRichText->createTextRun($textRun); + } + + if ($prefix !== NULL) + $prefix .= ':'; + // Loop through rich text elements + $elements = $pRichText->getRichTextElements(); + foreach ($elements as $element) { + // r + $objWriter->startElement($prefix.'r'); + + // rPr + $objWriter->startElement($prefix.'rPr'); + + // Bold + $objWriter->writeAttribute('b', ($element->getFont()->getBold() ? 1 : 0)); + // Italic + $objWriter->writeAttribute('i', ($element->getFont()->getItalic() ? 1 : 0)); + // Underline + $underlineType = $element->getFont()->getUnderline(); + switch($underlineType) { + case 'single' : + $underlineType = 'sng'; + break; + case 'double' : + $underlineType = 'dbl'; + break; + } + $objWriter->writeAttribute('u', $underlineType); + // Strikethrough + $objWriter->writeAttribute('strike', ($element->getFont()->getStrikethrough() ? 'sngStrike' : 'noStrike')); + + // rFont + $objWriter->startElement($prefix.'latin'); + $objWriter->writeAttribute('typeface', $element->getFont()->getName()); + $objWriter->endElement(); + + // Superscript / subscript +// if ($element->getFont()->getSuperScript() || $element->getFont()->getSubScript()) { +// $objWriter->startElement($prefix.'vertAlign'); +// if ($element->getFont()->getSuperScript()) { +// $objWriter->writeAttribute('val', 'superscript'); +// } else if ($element->getFont()->getSubScript()) { +// $objWriter->writeAttribute('val', 'subscript'); +// } +// $objWriter->endElement(); +// } +// + $objWriter->endElement(); + + // t + $objWriter->startElement($prefix.'t'); +// $objWriter->writeAttribute('xml:space', 'preserve'); // Excel2010 accepts, Excel2007 complains + $objWriter->writeRawData(PHPExcel_Shared_String::ControlCharacterPHP2OOXML( $element->getText() )); + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + + /** + * Flip string table (for index searching) + * + * @param array $stringTable Stringtable + * @return array + */ + public function flipStringTable($stringTable = array()) { + // Return value + $returnValue = array(); + + // Loop through stringtable and add flipped items to $returnValue + foreach ($stringTable as $key => $value) { + if (! $value instanceof PHPExcel_RichText) { + $returnValue[$value] = $key; + } else if ($value instanceof PHPExcel_RichText) { + $returnValue[$value->getHashCode()] = $key; + } + } + + // Return + return $returnValue; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Style.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Style.php new file mode 100755 index 0000000..f80b41a --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Style.php @@ -0,0 +1,701 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_Style + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007_Style extends PHPExcel_Writer_Excel2007_WriterPart +{ + /** + * Write styles to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeStyles(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // styleSheet + $objWriter->startElement('styleSheet'); + $objWriter->writeAttribute('xml:space', 'preserve'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); + + // numFmts + $objWriter->startElement('numFmts'); + $objWriter->writeAttribute('count', $this->getParentWriter()->getNumFmtHashTable()->count()); + + // numFmt + for ($i = 0; $i < $this->getParentWriter()->getNumFmtHashTable()->count(); ++$i) { + $this->_writeNumFmt($objWriter, $this->getParentWriter()->getNumFmtHashTable()->getByIndex($i), $i); + } + + $objWriter->endElement(); + + // fonts + $objWriter->startElement('fonts'); + $objWriter->writeAttribute('count', $this->getParentWriter()->getFontHashTable()->count()); + + // font + for ($i = 0; $i < $this->getParentWriter()->getFontHashTable()->count(); ++$i) { + $this->_writeFont($objWriter, $this->getParentWriter()->getFontHashTable()->getByIndex($i)); + } + + $objWriter->endElement(); + + // fills + $objWriter->startElement('fills'); + $objWriter->writeAttribute('count', $this->getParentWriter()->getFillHashTable()->count()); + + // fill + for ($i = 0; $i < $this->getParentWriter()->getFillHashTable()->count(); ++$i) { + $this->_writeFill($objWriter, $this->getParentWriter()->getFillHashTable()->getByIndex($i)); + } + + $objWriter->endElement(); + + // borders + $objWriter->startElement('borders'); + $objWriter->writeAttribute('count', $this->getParentWriter()->getBordersHashTable()->count()); + + // border + for ($i = 0; $i < $this->getParentWriter()->getBordersHashTable()->count(); ++$i) { + $this->_writeBorder($objWriter, $this->getParentWriter()->getBordersHashTable()->getByIndex($i)); + } + + $objWriter->endElement(); + + // cellStyleXfs + $objWriter->startElement('cellStyleXfs'); + $objWriter->writeAttribute('count', 1); + + // xf + $objWriter->startElement('xf'); + $objWriter->writeAttribute('numFmtId', 0); + $objWriter->writeAttribute('fontId', 0); + $objWriter->writeAttribute('fillId', 0); + $objWriter->writeAttribute('borderId', 0); + $objWriter->endElement(); + + $objWriter->endElement(); + + // cellXfs + $objWriter->startElement('cellXfs'); + $objWriter->writeAttribute('count', count($pPHPExcel->getCellXfCollection())); + + // xf + foreach ($pPHPExcel->getCellXfCollection() as $cellXf) { + $this->_writeCellStyleXf($objWriter, $cellXf, $pPHPExcel); + } + + $objWriter->endElement(); + + // cellStyles + $objWriter->startElement('cellStyles'); + $objWriter->writeAttribute('count', 1); + + // cellStyle + $objWriter->startElement('cellStyle'); + $objWriter->writeAttribute('name', 'Normal'); + $objWriter->writeAttribute('xfId', 0); + $objWriter->writeAttribute('builtinId', 0); + $objWriter->endElement(); + + $objWriter->endElement(); + + // dxfs + $objWriter->startElement('dxfs'); + $objWriter->writeAttribute('count', $this->getParentWriter()->getStylesConditionalHashTable()->count()); + + // dxf + for ($i = 0; $i < $this->getParentWriter()->getStylesConditionalHashTable()->count(); ++$i) { + $this->_writeCellStyleDxf($objWriter, $this->getParentWriter()->getStylesConditionalHashTable()->getByIndex($i)->getStyle()); + } + + $objWriter->endElement(); + + // tableStyles + $objWriter->startElement('tableStyles'); + $objWriter->writeAttribute('defaultTableStyle', 'TableStyleMedium9'); + $objWriter->writeAttribute('defaultPivotStyle', 'PivotTableStyle1'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write Fill + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_Fill $pFill Fill style + * @throws PHPExcel_Writer_Exception + */ + private function _writeFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) + { + // Check if this is a pattern type or gradient type + if ($pFill->getFillType() === PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR || + $pFill->getFillType() === PHPExcel_Style_Fill::FILL_GRADIENT_PATH) { + // Gradient fill + $this->_writeGradientFill($objWriter, $pFill); + } elseif($pFill->getFillType() !== NULL) { + // Pattern fill + $this->_writePatternFill($objWriter, $pFill); + } + } + + /** + * Write Gradient Fill + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_Fill $pFill Fill style + * @throws PHPExcel_Writer_Exception + */ + private function _writeGradientFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) + { + // fill + $objWriter->startElement('fill'); + + // gradientFill + $objWriter->startElement('gradientFill'); + $objWriter->writeAttribute('type', $pFill->getFillType()); + $objWriter->writeAttribute('degree', $pFill->getRotation()); + + // stop + $objWriter->startElement('stop'); + $objWriter->writeAttribute('position', '0'); + + // color + $objWriter->startElement('color'); + $objWriter->writeAttribute('rgb', $pFill->getStartColor()->getARGB()); + $objWriter->endElement(); + + $objWriter->endElement(); + + // stop + $objWriter->startElement('stop'); + $objWriter->writeAttribute('position', '1'); + + // color + $objWriter->startElement('color'); + $objWriter->writeAttribute('rgb', $pFill->getEndColor()->getARGB()); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write Pattern Fill + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_Fill $pFill Fill style + * @throws PHPExcel_Writer_Exception + */ + private function _writePatternFill(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Fill $pFill = null) + { + // fill + $objWriter->startElement('fill'); + + // patternFill + $objWriter->startElement('patternFill'); + $objWriter->writeAttribute('patternType', $pFill->getFillType()); + + if ($pFill->getFillType() !== PHPExcel_Style_Fill::FILL_NONE) { + // fgColor + if ($pFill->getStartColor()->getARGB()) { + $objWriter->startElement('fgColor'); + $objWriter->writeAttribute('rgb', $pFill->getStartColor()->getARGB()); + $objWriter->endElement(); + } + } + if ($pFill->getFillType() !== PHPExcel_Style_Fill::FILL_NONE) { + // bgColor + if ($pFill->getEndColor()->getARGB()) { + $objWriter->startElement('bgColor'); + $objWriter->writeAttribute('rgb', $pFill->getEndColor()->getARGB()); + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write Font + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_Font $pFont Font style + * @throws PHPExcel_Writer_Exception + */ + private function _writeFont(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Font $pFont = null) + { + // font + $objWriter->startElement('font'); + // Weird! The order of these elements actually makes a difference when opening Excel2007 + // files in Excel2003 with the compatibility pack. It's not documented behaviour, + // and makes for a real WTF! + + // Bold. We explicitly write this element also when false (like MS Office Excel 2007 does + // for conditional formatting). Otherwise it will apparently not be picked up in conditional + // formatting style dialog + if ($pFont->getBold() !== NULL) { + $objWriter->startElement('b'); + $objWriter->writeAttribute('val', $pFont->getBold() ? '1' : '0'); + $objWriter->endElement(); + } + + // Italic + if ($pFont->getItalic() !== NULL) { + $objWriter->startElement('i'); + $objWriter->writeAttribute('val', $pFont->getItalic() ? '1' : '0'); + $objWriter->endElement(); + } + + // Strikethrough + if ($pFont->getStrikethrough() !== NULL) { + $objWriter->startElement('strike'); + $objWriter->writeAttribute('val', $pFont->getStrikethrough() ? '1' : '0'); + $objWriter->endElement(); + } + + // Underline + if ($pFont->getUnderline() !== NULL) { + $objWriter->startElement('u'); + $objWriter->writeAttribute('val', $pFont->getUnderline()); + $objWriter->endElement(); + } + + // Superscript / subscript + if ($pFont->getSuperScript() === TRUE || $pFont->getSubScript() === TRUE) { + $objWriter->startElement('vertAlign'); + if ($pFont->getSuperScript() === TRUE) { + $objWriter->writeAttribute('val', 'superscript'); + } else if ($pFont->getSubScript() === TRUE) { + $objWriter->writeAttribute('val', 'subscript'); + } + $objWriter->endElement(); + } + + // Size + if ($pFont->getSize() !== NULL) { + $objWriter->startElement('sz'); + $objWriter->writeAttribute('val', $pFont->getSize()); + $objWriter->endElement(); + } + + // Foreground color + if ($pFont->getColor()->getARGB() !== NULL) { + $objWriter->startElement('color'); + $objWriter->writeAttribute('rgb', $pFont->getColor()->getARGB()); + $objWriter->endElement(); + } + + // Name + if ($pFont->getName() !== NULL) { + $objWriter->startElement('name'); + $objWriter->writeAttribute('val', $pFont->getName()); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + + /** + * Write Border + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_Borders $pBorders Borders style + * @throws PHPExcel_Writer_Exception + */ + private function _writeBorder(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_Borders $pBorders = null) + { + // Write border + $objWriter->startElement('border'); + // Diagonal? + switch ($pBorders->getDiagonalDirection()) { + case PHPExcel_Style_Borders::DIAGONAL_UP: + $objWriter->writeAttribute('diagonalUp', 'true'); + $objWriter->writeAttribute('diagonalDown', 'false'); + break; + case PHPExcel_Style_Borders::DIAGONAL_DOWN: + $objWriter->writeAttribute('diagonalUp', 'false'); + $objWriter->writeAttribute('diagonalDown', 'true'); + break; + case PHPExcel_Style_Borders::DIAGONAL_BOTH: + $objWriter->writeAttribute('diagonalUp', 'true'); + $objWriter->writeAttribute('diagonalDown', 'true'); + break; + } + + // BorderPr + $this->_writeBorderPr($objWriter, 'left', $pBorders->getLeft()); + $this->_writeBorderPr($objWriter, 'right', $pBorders->getRight()); + $this->_writeBorderPr($objWriter, 'top', $pBorders->getTop()); + $this->_writeBorderPr($objWriter, 'bottom', $pBorders->getBottom()); + $this->_writeBorderPr($objWriter, 'diagonal', $pBorders->getDiagonal()); + $objWriter->endElement(); + } + + /** + * Write Cell Style Xf + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style $pStyle Style + * @param PHPExcel $pPHPExcel Workbook + * @throws PHPExcel_Writer_Exception + */ + private function _writeCellStyleXf(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style $pStyle = null, PHPExcel $pPHPExcel = null) + { + // xf + $objWriter->startElement('xf'); + $objWriter->writeAttribute('xfId', 0); + $objWriter->writeAttribute('fontId', (int)$this->getParentWriter()->getFontHashTable()->getIndexForHashCode($pStyle->getFont()->getHashCode())); + + if ($pStyle->getNumberFormat()->getBuiltInFormatCode() === false) { + $objWriter->writeAttribute('numFmtId', (int)($this->getParentWriter()->getNumFmtHashTable()->getIndexForHashCode($pStyle->getNumberFormat()->getHashCode()) + 164) ); + } else { + $objWriter->writeAttribute('numFmtId', (int)$pStyle->getNumberFormat()->getBuiltInFormatCode()); + } + + $objWriter->writeAttribute('fillId', (int)$this->getParentWriter()->getFillHashTable()->getIndexForHashCode($pStyle->getFill()->getHashCode())); + $objWriter->writeAttribute('borderId', (int)$this->getParentWriter()->getBordersHashTable()->getIndexForHashCode($pStyle->getBorders()->getHashCode())); + + // Apply styles? + $objWriter->writeAttribute('applyFont', ($pPHPExcel->getDefaultStyle()->getFont()->getHashCode() != $pStyle->getFont()->getHashCode()) ? '1' : '0'); + $objWriter->writeAttribute('applyNumberFormat', ($pPHPExcel->getDefaultStyle()->getNumberFormat()->getHashCode() != $pStyle->getNumberFormat()->getHashCode()) ? '1' : '0'); + $objWriter->writeAttribute('applyFill', ($pPHPExcel->getDefaultStyle()->getFill()->getHashCode() != $pStyle->getFill()->getHashCode()) ? '1' : '0'); + $objWriter->writeAttribute('applyBorder', ($pPHPExcel->getDefaultStyle()->getBorders()->getHashCode() != $pStyle->getBorders()->getHashCode()) ? '1' : '0'); + $objWriter->writeAttribute('applyAlignment', ($pPHPExcel->getDefaultStyle()->getAlignment()->getHashCode() != $pStyle->getAlignment()->getHashCode()) ? '1' : '0'); + if ($pStyle->getProtection()->getLocked() != PHPExcel_Style_Protection::PROTECTION_INHERIT || $pStyle->getProtection()->getHidden() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { + $objWriter->writeAttribute('applyProtection', 'true'); + } + + // alignment + $objWriter->startElement('alignment'); + $objWriter->writeAttribute('horizontal', $pStyle->getAlignment()->getHorizontal()); + $objWriter->writeAttribute('vertical', $pStyle->getAlignment()->getVertical()); + + $textRotation = 0; + if ($pStyle->getAlignment()->getTextRotation() >= 0) { + $textRotation = $pStyle->getAlignment()->getTextRotation(); + } else if ($pStyle->getAlignment()->getTextRotation() < 0) { + $textRotation = 90 - $pStyle->getAlignment()->getTextRotation(); + } + $objWriter->writeAttribute('textRotation', $textRotation); + + $objWriter->writeAttribute('wrapText', ($pStyle->getAlignment()->getWrapText() ? 'true' : 'false')); + $objWriter->writeAttribute('shrinkToFit', ($pStyle->getAlignment()->getShrinkToFit() ? 'true' : 'false')); + + if ($pStyle->getAlignment()->getIndent() > 0) { + $objWriter->writeAttribute('indent', $pStyle->getAlignment()->getIndent()); + } + $objWriter->endElement(); + + // protection + if ($pStyle->getProtection()->getLocked() != PHPExcel_Style_Protection::PROTECTION_INHERIT || $pStyle->getProtection()->getHidden() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { + $objWriter->startElement('protection'); + if ($pStyle->getProtection()->getLocked() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { + $objWriter->writeAttribute('locked', ($pStyle->getProtection()->getLocked() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); + } + if ($pStyle->getProtection()->getHidden() != PHPExcel_Style_Protection::PROTECTION_INHERIT) { + $objWriter->writeAttribute('hidden', ($pStyle->getProtection()->getHidden() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); + } + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + + /** + * Write Cell Style Dxf + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style $pStyle Style + * @throws PHPExcel_Writer_Exception + */ + private function _writeCellStyleDxf(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style $pStyle = null) + { + // dxf + $objWriter->startElement('dxf'); + + // font + $this->_writeFont($objWriter, $pStyle->getFont()); + + // numFmt + $this->_writeNumFmt($objWriter, $pStyle->getNumberFormat()); + + // fill + $this->_writeFill($objWriter, $pStyle->getFill()); + + // alignment + $objWriter->startElement('alignment'); + if ($pStyle->getAlignment()->getHorizontal() !== NULL) { + $objWriter->writeAttribute('horizontal', $pStyle->getAlignment()->getHorizontal()); + } + if ($pStyle->getAlignment()->getVertical() !== NULL) { + $objWriter->writeAttribute('vertical', $pStyle->getAlignment()->getVertical()); + } + + if ($pStyle->getAlignment()->getTextRotation() !== NULL) { + $textRotation = 0; + if ($pStyle->getAlignment()->getTextRotation() >= 0) { + $textRotation = $pStyle->getAlignment()->getTextRotation(); + } else if ($pStyle->getAlignment()->getTextRotation() < 0) { + $textRotation = 90 - $pStyle->getAlignment()->getTextRotation(); + } + $objWriter->writeAttribute('textRotation', $textRotation); + } + $objWriter->endElement(); + + // border + $this->_writeBorder($objWriter, $pStyle->getBorders()); + + // protection + if (($pStyle->getProtection()->getLocked() !== NULL) || + ($pStyle->getProtection()->getHidden() !== NULL)) { + if ($pStyle->getProtection()->getLocked() !== PHPExcel_Style_Protection::PROTECTION_INHERIT || + $pStyle->getProtection()->getHidden() !== PHPExcel_Style_Protection::PROTECTION_INHERIT) { + $objWriter->startElement('protection'); + if (($pStyle->getProtection()->getLocked() !== NULL) && + ($pStyle->getProtection()->getLocked() !== PHPExcel_Style_Protection::PROTECTION_INHERIT)) { + $objWriter->writeAttribute('locked', ($pStyle->getProtection()->getLocked() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); + } + if (($pStyle->getProtection()->getHidden() !== NULL) && + ($pStyle->getProtection()->getHidden() !== PHPExcel_Style_Protection::PROTECTION_INHERIT)) { + $objWriter->writeAttribute('hidden', ($pStyle->getProtection()->getHidden() == PHPExcel_Style_Protection::PROTECTION_PROTECTED ? 'true' : 'false')); + } + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + } + + /** + * Write BorderPr + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pName Element name + * @param PHPExcel_Style_Border $pBorder Border style + * @throws PHPExcel_Writer_Exception + */ + private function _writeBorderPr(PHPExcel_Shared_XMLWriter $objWriter = null, $pName = 'left', PHPExcel_Style_Border $pBorder = null) + { + // Write BorderPr + if ($pBorder->getBorderStyle() != PHPExcel_Style_Border::BORDER_NONE) { + $objWriter->startElement($pName); + $objWriter->writeAttribute('style', $pBorder->getBorderStyle()); + + // color + $objWriter->startElement('color'); + $objWriter->writeAttribute('rgb', $pBorder->getColor()->getARGB()); + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + + /** + * Write NumberFormat + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Style_NumberFormat $pNumberFormat Number Format + * @param int $pId Number Format identifier + * @throws PHPExcel_Writer_Exception + */ + private function _writeNumFmt(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Style_NumberFormat $pNumberFormat = null, $pId = 0) + { + // Translate formatcode + $formatCode = $pNumberFormat->getFormatCode(); + + // numFmt + if ($formatCode !== NULL) { + $objWriter->startElement('numFmt'); + $objWriter->writeAttribute('numFmtId', ($pId + 164)); + $objWriter->writeAttribute('formatCode', $formatCode); + $objWriter->endElement(); + } + } + + /** + * Get an array of all styles + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style[] All styles in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allStyles(PHPExcel $pPHPExcel = null) + { + $aStyles = $pPHPExcel->getCellXfCollection(); + + return $aStyles; + } + + /** + * Get an array of all conditional styles + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style_Conditional[] All conditional styles in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allConditionalStyles(PHPExcel $pPHPExcel = null) + { + // Get an array of all styles + $aStyles = array(); + + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + foreach ($pPHPExcel->getSheet($i)->getConditionalStylesCollection() as $conditionalStyles) { + foreach ($conditionalStyles as $conditionalStyle) { + $aStyles[] = $conditionalStyle; + } + } + } + + return $aStyles; + } + + /** + * Get an array of all fills + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style_Fill[] All fills in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allFills(PHPExcel $pPHPExcel = null) + { + // Get an array of unique fills + $aFills = array(); + + // Two first fills are predefined + $fill0 = new PHPExcel_Style_Fill(); + $fill0->setFillType(PHPExcel_Style_Fill::FILL_NONE); + $aFills[] = $fill0; + + $fill1 = new PHPExcel_Style_Fill(); + $fill1->setFillType(PHPExcel_Style_Fill::FILL_PATTERN_GRAY125); + $aFills[] = $fill1; + // The remaining fills + $aStyles = $this->allStyles($pPHPExcel); + foreach ($aStyles as $style) { + if (!array_key_exists($style->getFill()->getHashCode(), $aFills)) { + $aFills[ $style->getFill()->getHashCode() ] = $style->getFill(); + } + } + + return $aFills; + } + + /** + * Get an array of all fonts + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style_Font[] All fonts in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allFonts(PHPExcel $pPHPExcel = null) + { + // Get an array of unique fonts + $aFonts = array(); + $aStyles = $this->allStyles($pPHPExcel); + + foreach ($aStyles as $style) { + if (!array_key_exists($style->getFont()->getHashCode(), $aFonts)) { + $aFonts[ $style->getFont()->getHashCode() ] = $style->getFont(); + } + } + + return $aFonts; + } + + /** + * Get an array of all borders + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style_Borders[] All borders in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allBorders(PHPExcel $pPHPExcel = null) + { + // Get an array of unique borders + $aBorders = array(); + $aStyles = $this->allStyles($pPHPExcel); + + foreach ($aStyles as $style) { + if (!array_key_exists($style->getBorders()->getHashCode(), $aBorders)) { + $aBorders[ $style->getBorders()->getHashCode() ] = $style->getBorders(); + } + } + + return $aBorders; + } + + /** + * Get an array of all number formats + * + * @param PHPExcel $pPHPExcel + * @return PHPExcel_Style_NumberFormat[] All number formats in PHPExcel + * @throws PHPExcel_Writer_Exception + */ + public function allNumberFormats(PHPExcel $pPHPExcel = null) + { + // Get an array of unique number formats + $aNumFmts = array(); + $aStyles = $this->allStyles($pPHPExcel); + + foreach ($aStyles as $style) { + if ($style->getNumberFormat()->getBuiltInFormatCode() === false && !array_key_exists($style->getNumberFormat()->getHashCode(), $aNumFmts)) { + $aNumFmts[ $style->getNumberFormat()->getHashCode() ] = $style->getNumberFormat(); + } + } + + return $aNumFmts; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Theme.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Theme.php new file mode 100755 index 0000000..5ece733 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Theme.php @@ -0,0 +1,871 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_Theme + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007_Theme extends PHPExcel_Writer_Excel2007_WriterPart +{ + /** + * Map of Major fonts to write + * @static array of string + * + */ + private static $_majorFonts = array( + 'Jpan' => 'ï¼­ï¼³ Pゴシック', + 'Hang' => 'ë§‘ì€ ê³ ë”•', + 'Hans' => '宋体', + 'Hant' => '新細明體', + 'Arab' => 'Times New Roman', + 'Hebr' => 'Times New Roman', + 'Thai' => 'Tahoma', + 'Ethi' => 'Nyala', + 'Beng' => 'Vrinda', + 'Gujr' => 'Shruti', + 'Khmr' => 'MoolBoran', + 'Knda' => 'Tunga', + 'Guru' => 'Raavi', + 'Cans' => 'Euphemia', + 'Cher' => 'Plantagenet Cherokee', + 'Yiii' => 'Microsoft Yi Baiti', + 'Tibt' => 'Microsoft Himalaya', + 'Thaa' => 'MV Boli', + 'Deva' => 'Mangal', + 'Telu' => 'Gautami', + 'Taml' => 'Latha', + 'Syrc' => 'Estrangelo Edessa', + 'Orya' => 'Kalinga', + 'Mlym' => 'Kartika', + 'Laoo' => 'DokChampa', + 'Sinh' => 'Iskoola Pota', + 'Mong' => 'Mongolian Baiti', + 'Viet' => 'Times New Roman', + 'Uigh' => 'Microsoft Uighur', + 'Geor' => 'Sylfaen', + ); + + /** + * Map of Minor fonts to write + * @static array of string + * + */ + private static $_minorFonts = array( + 'Jpan' => 'ï¼­ï¼³ Pゴシック', + 'Hang' => 'ë§‘ì€ ê³ ë”•', + 'Hans' => '宋体', + 'Hant' => '新細明體', + 'Arab' => 'Arial', + 'Hebr' => 'Arial', + 'Thai' => 'Tahoma', + 'Ethi' => 'Nyala', + 'Beng' => 'Vrinda', + 'Gujr' => 'Shruti', + 'Khmr' => 'DaunPenh', + 'Knda' => 'Tunga', + 'Guru' => 'Raavi', + 'Cans' => 'Euphemia', + 'Cher' => 'Plantagenet Cherokee', + 'Yiii' => 'Microsoft Yi Baiti', + 'Tibt' => 'Microsoft Himalaya', + 'Thaa' => 'MV Boli', + 'Deva' => 'Mangal', + 'Telu' => 'Gautami', + 'Taml' => 'Latha', + 'Syrc' => 'Estrangelo Edessa', + 'Orya' => 'Kalinga', + 'Mlym' => 'Kartika', + 'Laoo' => 'DokChampa', + 'Sinh' => 'Iskoola Pota', + 'Mong' => 'Mongolian Baiti', + 'Viet' => 'Arial', + 'Uigh' => 'Microsoft Uighur', + 'Geor' => 'Sylfaen', + ); + + /** + * Map of core colours + * @static array of string + * + */ + private static $_colourScheme = array( + 'dk2' => '1F497D', + 'lt2' => 'EEECE1', + 'accent1' => '4F81BD', + 'accent2' => 'C0504D', + 'accent3' => '9BBB59', + 'accent4' => '8064A2', + 'accent5' => '4BACC6', + 'accent6' => 'F79646', + 'hlink' => '0000FF', + 'folHlink' => '800080', + ); + + /** + * Write theme to XML format + * + * @param PHPExcel $pPHPExcel + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeTheme(PHPExcel $pPHPExcel = null) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // a:theme + $objWriter->startElement('a:theme'); + $objWriter->writeAttribute('xmlns:a', 'http://schemas.openxmlformats.org/drawingml/2006/main'); + $objWriter->writeAttribute('name', 'Office Theme'); + + // a:themeElements + $objWriter->startElement('a:themeElements'); + + // a:clrScheme + $objWriter->startElement('a:clrScheme'); + $objWriter->writeAttribute('name', 'Office'); + + // a:dk1 + $objWriter->startElement('a:dk1'); + + // a:sysClr + $objWriter->startElement('a:sysClr'); + $objWriter->writeAttribute('val', 'windowText'); + $objWriter->writeAttribute('lastClr', '000000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:lt1 + $objWriter->startElement('a:lt1'); + + // a:sysClr + $objWriter->startElement('a:sysClr'); + $objWriter->writeAttribute('val', 'window'); + $objWriter->writeAttribute('lastClr', 'FFFFFF'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:dk2 + $this->_writeColourScheme($objWriter); + + $objWriter->endElement(); + + // a:fontScheme + $objWriter->startElement('a:fontScheme'); + $objWriter->writeAttribute('name', 'Office'); + + // a:majorFont + $objWriter->startElement('a:majorFont'); + $this->_writeFonts($objWriter, 'Cambria', self::$_majorFonts); + $objWriter->endElement(); + + // a:minorFont + $objWriter->startElement('a:minorFont'); + $this->_writeFonts($objWriter, 'Calibri', self::$_minorFonts); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:fmtScheme + $objWriter->startElement('a:fmtScheme'); + $objWriter->writeAttribute('name', 'Office'); + + // a:fillStyleLst + $objWriter->startElement('a:fillStyleLst'); + + // a:solidFill + $objWriter->startElement('a:solidFill'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gradFill + $objWriter->startElement('a:gradFill'); + $objWriter->writeAttribute('rotWithShape', '1'); + + // a:gsLst + $objWriter->startElement('a:gsLst'); + + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '0'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '50000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '300000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '35000'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '37000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '300000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '100000'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '15000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '350000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:lin + $objWriter->startElement('a:lin'); + $objWriter->writeAttribute('ang', '16200000'); + $objWriter->writeAttribute('scaled', '1'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gradFill + $objWriter->startElement('a:gradFill'); + $objWriter->writeAttribute('rotWithShape', '1'); + + // a:gsLst + $objWriter->startElement('a:gsLst'); + + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '0'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '51000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '130000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '80000'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '93000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '130000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '100000'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '94000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '135000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:lin + $objWriter->startElement('a:lin'); + $objWriter->writeAttribute('ang', '16200000'); + $objWriter->writeAttribute('scaled', '0'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:lnStyleLst + $objWriter->startElement('a:lnStyleLst'); + + // a:ln + $objWriter->startElement('a:ln'); + $objWriter->writeAttribute('w', '9525'); + $objWriter->writeAttribute('cap', 'flat'); + $objWriter->writeAttribute('cmpd', 'sng'); + $objWriter->writeAttribute('algn', 'ctr'); + + // a:solidFill + $objWriter->startElement('a:solidFill'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '95000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '105000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:prstDash + $objWriter->startElement('a:prstDash'); + $objWriter->writeAttribute('val', 'solid'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:ln + $objWriter->startElement('a:ln'); + $objWriter->writeAttribute('w', '25400'); + $objWriter->writeAttribute('cap', 'flat'); + $objWriter->writeAttribute('cmpd', 'sng'); + $objWriter->writeAttribute('algn', 'ctr'); + + // a:solidFill + $objWriter->startElement('a:solidFill'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:prstDash + $objWriter->startElement('a:prstDash'); + $objWriter->writeAttribute('val', 'solid'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:ln + $objWriter->startElement('a:ln'); + $objWriter->writeAttribute('w', '38100'); + $objWriter->writeAttribute('cap', 'flat'); + $objWriter->writeAttribute('cmpd', 'sng'); + $objWriter->writeAttribute('algn', 'ctr'); + + // a:solidFill + $objWriter->startElement('a:solidFill'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:prstDash + $objWriter->startElement('a:prstDash'); + $objWriter->writeAttribute('val', 'solid'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + + + // a:effectStyleLst + $objWriter->startElement('a:effectStyleLst'); + + // a:effectStyle + $objWriter->startElement('a:effectStyle'); + + // a:effectLst + $objWriter->startElement('a:effectLst'); + + // a:outerShdw + $objWriter->startElement('a:outerShdw'); + $objWriter->writeAttribute('blurRad', '40000'); + $objWriter->writeAttribute('dist', '20000'); + $objWriter->writeAttribute('dir', '5400000'); + $objWriter->writeAttribute('rotWithShape', '0'); + + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', '000000'); + + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', '38000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:effectStyle + $objWriter->startElement('a:effectStyle'); + + // a:effectLst + $objWriter->startElement('a:effectLst'); + + // a:outerShdw + $objWriter->startElement('a:outerShdw'); + $objWriter->writeAttribute('blurRad', '40000'); + $objWriter->writeAttribute('dist', '23000'); + $objWriter->writeAttribute('dir', '5400000'); + $objWriter->writeAttribute('rotWithShape', '0'); + + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', '000000'); + + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', '35000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:effectStyle + $objWriter->startElement('a:effectStyle'); + + // a:effectLst + $objWriter->startElement('a:effectLst'); + + // a:outerShdw + $objWriter->startElement('a:outerShdw'); + $objWriter->writeAttribute('blurRad', '40000'); + $objWriter->writeAttribute('dist', '23000'); + $objWriter->writeAttribute('dir', '5400000'); + $objWriter->writeAttribute('rotWithShape', '0'); + + // a:srgbClr + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', '000000'); + + // a:alpha + $objWriter->startElement('a:alpha'); + $objWriter->writeAttribute('val', '35000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:scene3d + $objWriter->startElement('a:scene3d'); + + // a:camera + $objWriter->startElement('a:camera'); + $objWriter->writeAttribute('prst', 'orthographicFront'); + + // a:rot + $objWriter->startElement('a:rot'); + $objWriter->writeAttribute('lat', '0'); + $objWriter->writeAttribute('lon', '0'); + $objWriter->writeAttribute('rev', '0'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:lightRig + $objWriter->startElement('a:lightRig'); + $objWriter->writeAttribute('rig', 'threePt'); + $objWriter->writeAttribute('dir', 't'); + + // a:rot + $objWriter->startElement('a:rot'); + $objWriter->writeAttribute('lat', '0'); + $objWriter->writeAttribute('lon', '0'); + $objWriter->writeAttribute('rev', '1200000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:sp3d + $objWriter->startElement('a:sp3d'); + + // a:bevelT + $objWriter->startElement('a:bevelT'); + $objWriter->writeAttribute('w', '63500'); + $objWriter->writeAttribute('h', '25400'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:bgFillStyleLst + $objWriter->startElement('a:bgFillStyleLst'); + + // a:solidFill + $objWriter->startElement('a:solidFill'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gradFill + $objWriter->startElement('a:gradFill'); + $objWriter->writeAttribute('rotWithShape', '1'); + + // a:gsLst + $objWriter->startElement('a:gsLst'); + + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '0'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '40000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '350000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '40000'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '45000'); + $objWriter->endElement(); + + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '99000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '350000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '100000'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '20000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '255000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:path + $objWriter->startElement('a:path'); + $objWriter->writeAttribute('path', 'circle'); + + // a:fillToRect + $objWriter->startElement('a:fillToRect'); + $objWriter->writeAttribute('l', '50000'); + $objWriter->writeAttribute('t', '-80000'); + $objWriter->writeAttribute('r', '50000'); + $objWriter->writeAttribute('b', '180000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gradFill + $objWriter->startElement('a:gradFill'); + $objWriter->writeAttribute('rotWithShape', '1'); + + // a:gsLst + $objWriter->startElement('a:gsLst'); + + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '0'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:tint + $objWriter->startElement('a:tint'); + $objWriter->writeAttribute('val', '80000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '300000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:gs + $objWriter->startElement('a:gs'); + $objWriter->writeAttribute('pos', '100000'); + + // a:schemeClr + $objWriter->startElement('a:schemeClr'); + $objWriter->writeAttribute('val', 'phClr'); + + // a:shade + $objWriter->startElement('a:shade'); + $objWriter->writeAttribute('val', '30000'); + $objWriter->endElement(); + + // a:satMod + $objWriter->startElement('a:satMod'); + $objWriter->writeAttribute('val', '200000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:path + $objWriter->startElement('a:path'); + $objWriter->writeAttribute('path', 'circle'); + + // a:fillToRect + $objWriter->startElement('a:fillToRect'); + $objWriter->writeAttribute('l', '50000'); + $objWriter->writeAttribute('t', '50000'); + $objWriter->writeAttribute('r', '50000'); + $objWriter->writeAttribute('b', '50000'); + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + $objWriter->endElement(); + + // a:objectDefaults + $objWriter->writeElement('a:objectDefaults', null); + + // a:extraClrSchemeLst + $objWriter->writeElement('a:extraClrSchemeLst', null); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write fonts to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter + * @param string $latinFont + * @param array of string $fontSet + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + private function _writeFonts($objWriter, $latinFont, $fontSet) + { + // a:latin + $objWriter->startElement('a:latin'); + $objWriter->writeAttribute('typeface', $latinFont); + $objWriter->endElement(); + + // a:ea + $objWriter->startElement('a:ea'); + $objWriter->writeAttribute('typeface', ''); + $objWriter->endElement(); + + // a:cs + $objWriter->startElement('a:cs'); + $objWriter->writeAttribute('typeface', ''); + $objWriter->endElement(); + + foreach($fontSet as $fontScript => $typeface) { + $objWriter->startElement('a:font'); + $objWriter->writeAttribute('script', $fontScript); + $objWriter->writeAttribute('typeface', $typeface); + $objWriter->endElement(); + } + + } + + /** + * Write colour scheme to XML format + * + * @param PHPExcel_Shared_XMLWriter $objWriter + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + private function _writeColourScheme($objWriter) + { + foreach(self::$_colourScheme as $colourName => $colourValue) { + $objWriter->startElement('a:'.$colourName); + + $objWriter->startElement('a:srgbClr'); + $objWriter->writeAttribute('val', $colourValue); + $objWriter->endElement(); + + $objWriter->endElement(); + } + + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Workbook.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Workbook.php new file mode 100755 index 0000000..8c0babe --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Workbook.php @@ -0,0 +1,452 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_Workbook + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007_Workbook extends PHPExcel_Writer_Excel2007_WriterPart +{ + /** + * Write workbook to XML format + * + * @param PHPExcel $pPHPExcel + * @param boolean $recalcRequired Indicate whether formulas should be recalculated before writing + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeWorkbook(PHPExcel $pPHPExcel = null, $recalcRequired = FALSE) + { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // workbook + $objWriter->startElement('workbook'); + $objWriter->writeAttribute('xml:space', 'preserve'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + + // fileVersion + $this->_writeFileVersion($objWriter); + + // workbookPr + $this->_writeWorkbookPr($objWriter); + + // workbookProtection + $this->_writeWorkbookProtection($objWriter, $pPHPExcel); + + // bookViews + if ($this->getParentWriter()->getOffice2003Compatibility() === false) { + $this->_writeBookViews($objWriter, $pPHPExcel); + } + + // sheets + $this->_writeSheets($objWriter, $pPHPExcel); + + // definedNames + $this->_writeDefinedNames($objWriter, $pPHPExcel); + + // calcPr + $this->_writeCalcPr($objWriter,$recalcRequired); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } + + /** + * Write file version + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writeFileVersion(PHPExcel_Shared_XMLWriter $objWriter = null) + { + $objWriter->startElement('fileVersion'); + $objWriter->writeAttribute('appName', 'xl'); + $objWriter->writeAttribute('lastEdited', '4'); + $objWriter->writeAttribute('lowestEdited', '4'); + $objWriter->writeAttribute('rupBuild', '4505'); + $objWriter->endElement(); + } + + /** + * Write WorkbookPr + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @throws PHPExcel_Writer_Exception + */ + private function _writeWorkbookPr(PHPExcel_Shared_XMLWriter $objWriter = null) + { + $objWriter->startElement('workbookPr'); + + if (PHPExcel_Shared_Date::getExcelCalendar() == PHPExcel_Shared_Date::CALENDAR_MAC_1904) { + $objWriter->writeAttribute('date1904', '1'); + } + + $objWriter->writeAttribute('codeName', 'ThisWorkbook'); + + $objWriter->endElement(); + } + + /** + * Write BookViews + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel $pPHPExcel + * @throws PHPExcel_Writer_Exception + */ + private function _writeBookViews(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) + { + // bookViews + $objWriter->startElement('bookViews'); + + // workbookView + $objWriter->startElement('workbookView'); + + $objWriter->writeAttribute('activeTab', $pPHPExcel->getActiveSheetIndex()); + $objWriter->writeAttribute('autoFilterDateGrouping', '1'); + $objWriter->writeAttribute('firstSheet', '0'); + $objWriter->writeAttribute('minimized', '0'); + $objWriter->writeAttribute('showHorizontalScroll', '1'); + $objWriter->writeAttribute('showSheetTabs', '1'); + $objWriter->writeAttribute('showVerticalScroll', '1'); + $objWriter->writeAttribute('tabRatio', '600'); + $objWriter->writeAttribute('visibility', 'visible'); + + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write WorkbookProtection + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel $pPHPExcel + * @throws PHPExcel_Writer_Exception + */ + private function _writeWorkbookProtection(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) + { + if ($pPHPExcel->getSecurity()->isSecurityEnabled()) { + $objWriter->startElement('workbookProtection'); + $objWriter->writeAttribute('lockRevision', ($pPHPExcel->getSecurity()->getLockRevision() ? 'true' : 'false')); + $objWriter->writeAttribute('lockStructure', ($pPHPExcel->getSecurity()->getLockStructure() ? 'true' : 'false')); + $objWriter->writeAttribute('lockWindows', ($pPHPExcel->getSecurity()->getLockWindows() ? 'true' : 'false')); + + if ($pPHPExcel->getSecurity()->getRevisionsPassword() != '') { + $objWriter->writeAttribute('revisionsPassword', $pPHPExcel->getSecurity()->getRevisionsPassword()); + } + + if ($pPHPExcel->getSecurity()->getWorkbookPassword() != '') { + $objWriter->writeAttribute('workbookPassword', $pPHPExcel->getSecurity()->getWorkbookPassword()); + } + + $objWriter->endElement(); + } + } + + /** + * Write calcPr + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param boolean $recalcRequired Indicate whether formulas should be recalculated before writing + * @throws PHPExcel_Writer_Exception + */ + private function _writeCalcPr(PHPExcel_Shared_XMLWriter $objWriter = null, $recalcRequired = TRUE) + { + $objWriter->startElement('calcPr'); + + $objWriter->writeAttribute('calcId', '124519'); + $objWriter->writeAttribute('calcMode', 'auto'); + // fullCalcOnLoad isn't needed if we've recalculating for the save + $objWriter->writeAttribute('fullCalcOnLoad', ($recalcRequired) ? '0' : '1'); + + $objWriter->endElement(); + } + + /** + * Write sheets + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel $pPHPExcel + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheets(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) + { + // Write sheets + $objWriter->startElement('sheets'); + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + // sheet + $this->_writeSheet( + $objWriter, + $pPHPExcel->getSheet($i)->getTitle(), + ($i + 1), + ($i + 1 + 3), + $pPHPExcel->getSheet($i)->getSheetState() + ); + } + + $objWriter->endElement(); + } + + /** + * Write sheet + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param string $pSheetname Sheet name + * @param int $pSheetId Sheet id + * @param int $pRelId Relationship ID + * @param string $sheetState Sheet state (visible, hidden, veryHidden) + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheet(PHPExcel_Shared_XMLWriter $objWriter = null, $pSheetname = '', $pSheetId = 1, $pRelId = 1, $sheetState = 'visible') + { + if ($pSheetname != '') { + // Write sheet + $objWriter->startElement('sheet'); + $objWriter->writeAttribute('name', $pSheetname); + $objWriter->writeAttribute('sheetId', $pSheetId); + if ($sheetState != 'visible' && $sheetState != '') { + $objWriter->writeAttribute('state', $sheetState); + } + $objWriter->writeAttribute('r:id', 'rId' . $pRelId); + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } + + /** + * Write Defined Names + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel $pPHPExcel + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefinedNames(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel = null) + { + // Write defined names + $objWriter->startElement('definedNames'); + + // Named ranges + if (count($pPHPExcel->getNamedRanges()) > 0) { + // Named ranges + $this->_writeNamedRanges($objWriter, $pPHPExcel); + } + + // Other defined names + $sheetCount = $pPHPExcel->getSheetCount(); + for ($i = 0; $i < $sheetCount; ++$i) { + // definedName for autoFilter + $this->_writeDefinedNameForAutofilter($objWriter, $pPHPExcel->getSheet($i), $i); + + // definedName for Print_Titles + $this->_writeDefinedNameForPrintTitles($objWriter, $pPHPExcel->getSheet($i), $i); + + // definedName for Print_Area + $this->_writeDefinedNameForPrintArea($objWriter, $pPHPExcel->getSheet($i), $i); + } + + $objWriter->endElement(); + } + + /** + * Write named ranges + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel $pPHPExcel + * @throws PHPExcel_Writer_Exception + */ + private function _writeNamedRanges(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel $pPHPExcel) + { + // Loop named ranges + $namedRanges = $pPHPExcel->getNamedRanges(); + foreach ($namedRanges as $namedRange) { + $this->_writeDefinedNameForNamedRange($objWriter, $namedRange); + } + } + + /** + * Write Defined Name for named range + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_NamedRange $pNamedRange + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefinedNameForNamedRange(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_NamedRange $pNamedRange) + { + // definedName for named range + $objWriter->startElement('definedName'); + $objWriter->writeAttribute('name', $pNamedRange->getName()); + if ($pNamedRange->getLocalOnly()) { + $objWriter->writeAttribute('localSheetId', $pNamedRange->getScope()->getParent()->getIndex($pNamedRange->getScope())); + } + + // Create absolute coordinate and write as raw text + $range = PHPExcel_Cell::splitRange($pNamedRange->getRange()); + for ($i = 0; $i < count($range); $i++) { + $range[$i][0] = '\'' . str_replace("'", "''", $pNamedRange->getWorksheet()->getTitle()) . '\'!' . PHPExcel_Cell::absoluteReference($range[$i][0]); + if (isset($range[$i][1])) { + $range[$i][1] = PHPExcel_Cell::absoluteReference($range[$i][1]); + } + } + $range = PHPExcel_Cell::buildRange($range); + + $objWriter->writeRawData($range); + + $objWriter->endElement(); + } + + /** + * Write Defined Name for autoFilter + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet + * @param int $pSheetId + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefinedNameForAutofilter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) + { + // definedName for autoFilter + $autoFilterRange = $pSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { + $objWriter->startElement('definedName'); + $objWriter->writeAttribute('name', '_xlnm._FilterDatabase'); + $objWriter->writeAttribute('localSheetId', $pSheetId); + $objWriter->writeAttribute('hidden', '1'); + + // Create absolute coordinate and write as raw text + $range = PHPExcel_Cell::splitRange($autoFilterRange); + $range = $range[0]; + // Strip any worksheet ref so we can make the cell ref absolute + if (strpos($range[0],'!') !== false) { + list($ws,$range[0]) = explode('!',$range[0]); + } + + $range[0] = PHPExcel_Cell::absoluteCoordinate($range[0]); + $range[1] = PHPExcel_Cell::absoluteCoordinate($range[1]); + $range = implode(':', $range); + + $objWriter->writeRawData('\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . $range); + + $objWriter->endElement(); + } + } + + /** + * Write Defined Name for PrintTitles + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet + * @param int $pSheetId + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefinedNameForPrintTitles(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) + { + // definedName for PrintTitles + if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet() || $pSheet->getPageSetup()->isRowsToRepeatAtTopSet()) { + $objWriter->startElement('definedName'); + $objWriter->writeAttribute('name', '_xlnm.Print_Titles'); + $objWriter->writeAttribute('localSheetId', $pSheetId); + + // Setting string + $settingString = ''; + + // Columns to repeat + if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) { + $repeat = $pSheet->getPageSetup()->getColumnsToRepeatAtLeft(); + + $settingString .= '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1]; + } + + // Rows to repeat + if ($pSheet->getPageSetup()->isRowsToRepeatAtTopSet()) { + if ($pSheet->getPageSetup()->isColumnsToRepeatAtLeftSet()) { + $settingString .= ','; + } + + $repeat = $pSheet->getPageSetup()->getRowsToRepeatAtTop(); + + $settingString .= '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!$' . $repeat[0] . ':$' . $repeat[1]; + } + + $objWriter->writeRawData($settingString); + + $objWriter->endElement(); + } + } + + /** + * Write Defined Name for PrintTitles + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet + * @param int $pSheetId + * @throws PHPExcel_Writer_Exception + */ + private function _writeDefinedNameForPrintArea(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pSheetId = 0) + { + // definedName for PrintArea + if ($pSheet->getPageSetup()->isPrintAreaSet()) { + $objWriter->startElement('definedName'); + $objWriter->writeAttribute('name', '_xlnm.Print_Area'); + $objWriter->writeAttribute('localSheetId', $pSheetId); + + // Setting string + $settingString = ''; + + // Print area + $printArea = PHPExcel_Cell::splitRange($pSheet->getPageSetup()->getPrintArea()); + + $chunks = array(); + foreach ($printArea as $printAreaRect) { + $printAreaRect[0] = PHPExcel_Cell::absoluteReference($printAreaRect[0]); + $printAreaRect[1] = PHPExcel_Cell::absoluteReference($printAreaRect[1]); + $chunks[] = '\'' . str_replace("'", "''", $pSheet->getTitle()) . '\'!' . implode(':', $printAreaRect); + } + + $objWriter->writeRawData(implode(',', $chunks)); + + $objWriter->endElement(); + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Worksheet.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Worksheet.php new file mode 100755 index 0000000..309e176 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/Worksheet.php @@ -0,0 +1,1214 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_Worksheet + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel2007_Worksheet extends PHPExcel_Writer_Excel2007_WriterPart +{ + /** + * Write worksheet to XML format + * + * @param PHPExcel_Worksheet $pSheet + * @param string[] $pStringTable + * @param boolean $includeCharts Flag indicating if we should write charts + * @return string XML Output + * @throws PHPExcel_Writer_Exception + */ + public function writeWorksheet($pSheet = null, $pStringTable = null, $includeCharts = FALSE) + { + if (!is_null($pSheet)) { + // Create XML writer + $objWriter = null; + if ($this->getParentWriter()->getUseDiskCaching()) { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory()); + } else { + $objWriter = new PHPExcel_Shared_XMLWriter(PHPExcel_Shared_XMLWriter::STORAGE_MEMORY); + } + + // XML header + $objWriter->startDocument('1.0','UTF-8','yes'); + + // Worksheet + $objWriter->startElement('worksheet'); + $objWriter->writeAttribute('xml:space', 'preserve'); + $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'); + $objWriter->writeAttribute('xmlns:r', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships'); + + // sheetPr + $this->_writeSheetPr($objWriter, $pSheet); + + // Dimension + $this->_writeDimension($objWriter, $pSheet); + + // sheetViews + $this->_writeSheetViews($objWriter, $pSheet); + + // sheetFormatPr + $this->_writeSheetFormatPr($objWriter, $pSheet); + + // cols + $this->_writeCols($objWriter, $pSheet); + + // sheetData + $this->_writeSheetData($objWriter, $pSheet, $pStringTable); + + // sheetProtection + $this->_writeSheetProtection($objWriter, $pSheet); + + // protectedRanges + $this->_writeProtectedRanges($objWriter, $pSheet); + + // autoFilter + $this->_writeAutoFilter($objWriter, $pSheet); + + // mergeCells + $this->_writeMergeCells($objWriter, $pSheet); + + // conditionalFormatting + $this->_writeConditionalFormatting($objWriter, $pSheet); + + // dataValidations + $this->_writeDataValidations($objWriter, $pSheet); + + // hyperlinks + $this->_writeHyperlinks($objWriter, $pSheet); + + // Print options + $this->_writePrintOptions($objWriter, $pSheet); + + // Page margins + $this->_writePageMargins($objWriter, $pSheet); + + // Page setup + $this->_writePageSetup($objWriter, $pSheet); + + // Header / footer + $this->_writeHeaderFooter($objWriter, $pSheet); + + // Breaks + $this->_writeBreaks($objWriter, $pSheet); + + // Drawings and/or Charts + $this->_writeDrawings($objWriter, $pSheet, $includeCharts); + + // LegacyDrawing + $this->_writeLegacyDrawing($objWriter, $pSheet); + + // LegacyDrawingHF + $this->_writeLegacyDrawingHF($objWriter, $pSheet); + + $objWriter->endElement(); + + // Return + return $objWriter->getData(); + } else { + throw new PHPExcel_Writer_Exception("Invalid PHPExcel_Worksheet object passed."); + } + } + + /** + * Write SheetPr + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheetPr(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // sheetPr + $objWriter->startElement('sheetPr'); + //$objWriter->writeAttribute('codeName', $pSheet->getTitle()); + $autoFilterRange = $pSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { + $objWriter->writeAttribute('filterMode', 1); + $pSheet->getAutoFilter()->showHideRows(); + } + + // tabColor + if ($pSheet->isTabColorSet()) { + $objWriter->startElement('tabColor'); + $objWriter->writeAttribute('rgb', $pSheet->getTabColor()->getARGB()); + $objWriter->endElement(); + } + + // outlinePr + $objWriter->startElement('outlinePr'); + $objWriter->writeAttribute('summaryBelow', ($pSheet->getShowSummaryBelow() ? '1' : '0')); + $objWriter->writeAttribute('summaryRight', ($pSheet->getShowSummaryRight() ? '1' : '0')); + $objWriter->endElement(); + + // pageSetUpPr + if ($pSheet->getPageSetup()->getFitToPage()) { + $objWriter->startElement('pageSetUpPr'); + $objWriter->writeAttribute('fitToPage', '1'); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + + /** + * Write Dimension + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeDimension(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // dimension + $objWriter->startElement('dimension'); + $objWriter->writeAttribute('ref', $pSheet->calculateWorksheetDimension()); + $objWriter->endElement(); + } + + /** + * Write SheetViews + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheetViews(PHPExcel_Shared_XMLWriter $objWriter = NULL, PHPExcel_Worksheet $pSheet = NULL) + { + // sheetViews + $objWriter->startElement('sheetViews'); + + // Sheet selected? + $sheetSelected = false; + if ($this->getParentWriter()->getPHPExcel()->getIndex($pSheet) == $this->getParentWriter()->getPHPExcel()->getActiveSheetIndex()) + $sheetSelected = true; + + + // sheetView + $objWriter->startElement('sheetView'); + $objWriter->writeAttribute('tabSelected', $sheetSelected ? '1' : '0'); + $objWriter->writeAttribute('workbookViewId', '0'); + + // Zoom scales + if ($pSheet->getSheetView()->getZoomScale() != 100) { + $objWriter->writeAttribute('zoomScale', $pSheet->getSheetView()->getZoomScale()); + } + if ($pSheet->getSheetView()->getZoomScaleNormal() != 100) { + $objWriter->writeAttribute('zoomScaleNormal', $pSheet->getSheetView()->getZoomScaleNormal()); + } + + // View Layout Type + if ($pSheet->getSheetView()->getView() !== PHPExcel_Worksheet_SheetView::SHEETVIEW_NORMAL) { + $objWriter->writeAttribute('view', $pSheet->getSheetView()->getView()); + } + + // Gridlines + if ($pSheet->getShowGridlines()) { + $objWriter->writeAttribute('showGridLines', 'true'); + } else { + $objWriter->writeAttribute('showGridLines', 'false'); + } + + // Row and column headers + if ($pSheet->getShowRowColHeaders()) { + $objWriter->writeAttribute('showRowColHeaders', '1'); + } else { + $objWriter->writeAttribute('showRowColHeaders', '0'); + } + + // Right-to-left + if ($pSheet->getRightToLeft()) { + $objWriter->writeAttribute('rightToLeft', 'true'); + } + + $activeCell = $pSheet->getActiveCell(); + + // Pane + $pane = ''; + $topLeftCell = $pSheet->getFreezePane(); + if (($topLeftCell != '') && ($topLeftCell != 'A1')) { + $activeCell = $topLeftCell; + // Calculate freeze coordinates + $xSplit = $ySplit = 0; + + list($xSplit, $ySplit) = PHPExcel_Cell::coordinateFromString($topLeftCell); + $xSplit = PHPExcel_Cell::columnIndexFromString($xSplit); + + // pane + $pane = 'topRight'; + $objWriter->startElement('pane'); + if ($xSplit > 1) + $objWriter->writeAttribute('xSplit', $xSplit - 1); + if ($ySplit > 1) { + $objWriter->writeAttribute('ySplit', $ySplit - 1); + $pane = ($xSplit > 1) ? 'bottomRight' : 'bottomLeft'; + } + $objWriter->writeAttribute('topLeftCell', $topLeftCell); + $objWriter->writeAttribute('activePane', $pane); + $objWriter->writeAttribute('state', 'frozen'); + $objWriter->endElement(); + + if (($xSplit > 1) && ($ySplit > 1)) { + // Write additional selections if more than two panes (ie both an X and a Y split) + $objWriter->startElement('selection'); $objWriter->writeAttribute('pane', 'topRight'); $objWriter->endElement(); + $objWriter->startElement('selection'); $objWriter->writeAttribute('pane', 'bottomLeft'); $objWriter->endElement(); + } + } + + // Selection +// if ($pane != '') { + // Only need to write selection element if we have a split pane + // We cheat a little by over-riding the active cell selection, setting it to the split cell + $objWriter->startElement('selection'); + if ($pane != '') { + $objWriter->writeAttribute('pane', $pane); + } + $objWriter->writeAttribute('activeCell', $activeCell); + $objWriter->writeAttribute('sqref', $activeCell); + $objWriter->endElement(); +// } + + $objWriter->endElement(); + + $objWriter->endElement(); + } + + /** + * Write SheetFormatPr + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheetFormatPr(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // sheetFormatPr + $objWriter->startElement('sheetFormatPr'); + + // Default row height + if ($pSheet->getDefaultRowDimension()->getRowHeight() >= 0) { + $objWriter->writeAttribute('customHeight', 'true'); + $objWriter->writeAttribute('defaultRowHeight', PHPExcel_Shared_String::FormatNumber($pSheet->getDefaultRowDimension()->getRowHeight())); + } else { + $objWriter->writeAttribute('defaultRowHeight', '14.4'); + } + + // Set Zero Height row + if ((string)$pSheet->getDefaultRowDimension()->getzeroHeight() == '1' || + strtolower((string)$pSheet->getDefaultRowDimension()->getzeroHeight()) == 'true' ) { + $objWriter->writeAttribute('zeroHeight', '1'); + } + + // Default column width + if ($pSheet->getDefaultColumnDimension()->getWidth() >= 0) { + $objWriter->writeAttribute('defaultColWidth', PHPExcel_Shared_String::FormatNumber($pSheet->getDefaultColumnDimension()->getWidth())); + } + + // Outline level - row + $outlineLevelRow = 0; + foreach ($pSheet->getRowDimensions() as $dimension) { + if ($dimension->getOutlineLevel() > $outlineLevelRow) { + $outlineLevelRow = $dimension->getOutlineLevel(); + } + } + $objWriter->writeAttribute('outlineLevelRow', (int)$outlineLevelRow); + + // Outline level - column + $outlineLevelCol = 0; + foreach ($pSheet->getColumnDimensions() as $dimension) { + if ($dimension->getOutlineLevel() > $outlineLevelCol) { + $outlineLevelCol = $dimension->getOutlineLevel(); + } + } + $objWriter->writeAttribute('outlineLevelCol', (int)$outlineLevelCol); + + $objWriter->endElement(); + } + + /** + * Write Cols + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeCols(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // cols + if (count($pSheet->getColumnDimensions()) > 0) { + $objWriter->startElement('cols'); + + $pSheet->calculateColumnWidths(); + + // Loop through column dimensions + foreach ($pSheet->getColumnDimensions() as $colDimension) { + // col + $objWriter->startElement('col'); + $objWriter->writeAttribute('min', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); + $objWriter->writeAttribute('max', PHPExcel_Cell::columnIndexFromString($colDimension->getColumnIndex())); + + if ($colDimension->getWidth() < 0) { + // No width set, apply default of 10 + $objWriter->writeAttribute('width', '9.10'); + } else { + // Width set + $objWriter->writeAttribute('width', PHPExcel_Shared_String::FormatNumber($colDimension->getWidth())); + } + + // Column visibility + if ($colDimension->getVisible() == false) { + $objWriter->writeAttribute('hidden', 'true'); + } + + // Auto size? + if ($colDimension->getAutoSize()) { + $objWriter->writeAttribute('bestFit', 'true'); + } + + // Custom width? + if ($colDimension->getWidth() != $pSheet->getDefaultColumnDimension()->getWidth()) { + $objWriter->writeAttribute('customWidth', 'true'); + } + + // Collapsed + if ($colDimension->getCollapsed() == true) { + $objWriter->writeAttribute('collapsed', 'true'); + } + + // Outline level + if ($colDimension->getOutlineLevel() > 0) { + $objWriter->writeAttribute('outlineLevel', $colDimension->getOutlineLevel()); + } + + // Style + $objWriter->writeAttribute('style', $colDimension->getXfIndex()); + + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write SheetProtection + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheetProtection(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // sheetProtection + $objWriter->startElement('sheetProtection'); + + if ($pSheet->getProtection()->getPassword() != '') { + $objWriter->writeAttribute('password', $pSheet->getProtection()->getPassword()); + } + + $objWriter->writeAttribute('sheet', ($pSheet->getProtection()->getSheet() ? 'true' : 'false')); + $objWriter->writeAttribute('objects', ($pSheet->getProtection()->getObjects() ? 'true' : 'false')); + $objWriter->writeAttribute('scenarios', ($pSheet->getProtection()->getScenarios() ? 'true' : 'false')); + $objWriter->writeAttribute('formatCells', ($pSheet->getProtection()->getFormatCells() ? 'true' : 'false')); + $objWriter->writeAttribute('formatColumns', ($pSheet->getProtection()->getFormatColumns() ? 'true' : 'false')); + $objWriter->writeAttribute('formatRows', ($pSheet->getProtection()->getFormatRows() ? 'true' : 'false')); + $objWriter->writeAttribute('insertColumns', ($pSheet->getProtection()->getInsertColumns() ? 'true' : 'false')); + $objWriter->writeAttribute('insertRows', ($pSheet->getProtection()->getInsertRows() ? 'true' : 'false')); + $objWriter->writeAttribute('insertHyperlinks', ($pSheet->getProtection()->getInsertHyperlinks() ? 'true' : 'false')); + $objWriter->writeAttribute('deleteColumns', ($pSheet->getProtection()->getDeleteColumns() ? 'true' : 'false')); + $objWriter->writeAttribute('deleteRows', ($pSheet->getProtection()->getDeleteRows() ? 'true' : 'false')); + $objWriter->writeAttribute('selectLockedCells', ($pSheet->getProtection()->getSelectLockedCells() ? 'true' : 'false')); + $objWriter->writeAttribute('sort', ($pSheet->getProtection()->getSort() ? 'true' : 'false')); + $objWriter->writeAttribute('autoFilter', ($pSheet->getProtection()->getAutoFilter() ? 'true' : 'false')); + $objWriter->writeAttribute('pivotTables', ($pSheet->getProtection()->getPivotTables() ? 'true' : 'false')); + $objWriter->writeAttribute('selectUnlockedCells', ($pSheet->getProtection()->getSelectUnlockedCells() ? 'true' : 'false')); + $objWriter->endElement(); + } + + /** + * Write ConditionalFormatting + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeConditionalFormatting(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // Conditional id + $id = 1; + + // Loop through styles in the current worksheet + foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) { + foreach ($conditionalStyles as $conditional) { + // WHY was this again? + // if ($this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode( $conditional->getHashCode() ) == '') { + // continue; + // } + if ($conditional->getConditionType() != PHPExcel_Style_Conditional::CONDITION_NONE) { + // conditionalFormatting + $objWriter->startElement('conditionalFormatting'); + $objWriter->writeAttribute('sqref', $cellCoordinate); + + // cfRule + $objWriter->startElement('cfRule'); + $objWriter->writeAttribute('type', $conditional->getConditionType()); + $objWriter->writeAttribute('dxfId', $this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode( $conditional->getHashCode() )); + $objWriter->writeAttribute('priority', $id++); + + if (($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS + || + $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT) + && $conditional->getOperatorType() != PHPExcel_Style_Conditional::OPERATOR_NONE) { + $objWriter->writeAttribute('operator', $conditional->getOperatorType()); + } + + if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && !is_null($conditional->getText())) { + $objWriter->writeAttribute('text', $conditional->getText()); + } + + if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_CONTAINSTEXT + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'NOT(ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . ')))'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_BEGINSWITH + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'LEFT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_ENDSWITH + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'RIGHT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + && $conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_NOTCONTAINS + && !is_null($conditional->getText())) { + $objWriter->writeElement('formula', 'ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . '))'); + } else if ($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS + || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CONTAINSTEXT + || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION) { + foreach ($conditional->getConditions() as $formula) { + // Formula + $objWriter->writeElement('formula', $formula); + } + } + + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + } + } + + /** + * Write DataValidations + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeDataValidations(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // Datavalidation collection + $dataValidationCollection = $pSheet->getDataValidationCollection(); + + // Write data validations? + if (!empty($dataValidationCollection)) { + $objWriter->startElement('dataValidations'); + $objWriter->writeAttribute('count', count($dataValidationCollection)); + + foreach ($dataValidationCollection as $coordinate => $dv) { + $objWriter->startElement('dataValidation'); + + if ($dv->getType() != '') { + $objWriter->writeAttribute('type', $dv->getType()); + } + + if ($dv->getErrorStyle() != '') { + $objWriter->writeAttribute('errorStyle', $dv->getErrorStyle()); + } + + if ($dv->getOperator() != '') { + $objWriter->writeAttribute('operator', $dv->getOperator()); + } + + $objWriter->writeAttribute('allowBlank', ($dv->getAllowBlank() ? '1' : '0')); + $objWriter->writeAttribute('showDropDown', (!$dv->getShowDropDown() ? '1' : '0')); + $objWriter->writeAttribute('showInputMessage', ($dv->getShowInputMessage() ? '1' : '0')); + $objWriter->writeAttribute('showErrorMessage', ($dv->getShowErrorMessage() ? '1' : '0')); + + if ($dv->getErrorTitle() !== '') { + $objWriter->writeAttribute('errorTitle', $dv->getErrorTitle()); + } + if ($dv->getError() !== '') { + $objWriter->writeAttribute('error', $dv->getError()); + } + if ($dv->getPromptTitle() !== '') { + $objWriter->writeAttribute('promptTitle', $dv->getPromptTitle()); + } + if ($dv->getPrompt() !== '') { + $objWriter->writeAttribute('prompt', $dv->getPrompt()); + } + + $objWriter->writeAttribute('sqref', $coordinate); + + if ($dv->getFormula1() !== '') { + $objWriter->writeElement('formula1', $dv->getFormula1()); + } + if ($dv->getFormula2() !== '') { + $objWriter->writeElement('formula2', $dv->getFormula2()); + } + + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write Hyperlinks + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeHyperlinks(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // Hyperlink collection + $hyperlinkCollection = $pSheet->getHyperlinkCollection(); + + // Relation ID + $relationId = 1; + + // Write hyperlinks? + if (!empty($hyperlinkCollection)) { + $objWriter->startElement('hyperlinks'); + + foreach ($hyperlinkCollection as $coordinate => $hyperlink) { + $objWriter->startElement('hyperlink'); + + $objWriter->writeAttribute('ref', $coordinate); + if (!$hyperlink->isInternal()) { + $objWriter->writeAttribute('r:id', 'rId_hyperlink_' . $relationId); + ++$relationId; + } else { + $objWriter->writeAttribute('location', str_replace('sheet://', '', $hyperlink->getUrl())); + } + + if ($hyperlink->getTooltip() != '') { + $objWriter->writeAttribute('tooltip', $hyperlink->getTooltip()); + } + + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write ProtectedRanges + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeProtectedRanges(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + if (count($pSheet->getProtectedCells()) > 0) { + // protectedRanges + $objWriter->startElement('protectedRanges'); + + // Loop protectedRanges + foreach ($pSheet->getProtectedCells() as $protectedCell => $passwordHash) { + // protectedRange + $objWriter->startElement('protectedRange'); + $objWriter->writeAttribute('name', 'p' . md5($protectedCell)); + $objWriter->writeAttribute('sqref', $protectedCell); + if (!empty($passwordHash)) { + $objWriter->writeAttribute('password', $passwordHash); + } + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write MergeCells + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeMergeCells(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + if (count($pSheet->getMergeCells()) > 0) { + // mergeCells + $objWriter->startElement('mergeCells'); + + // Loop mergeCells + foreach ($pSheet->getMergeCells() as $mergeCell) { + // mergeCell + $objWriter->startElement('mergeCell'); + $objWriter->writeAttribute('ref', $mergeCell); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write PrintOptions + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writePrintOptions(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // printOptions + $objWriter->startElement('printOptions'); + + $objWriter->writeAttribute('gridLines', ($pSheet->getPrintGridlines() ? 'true': 'false')); + $objWriter->writeAttribute('gridLinesSet', 'true'); + + if ($pSheet->getPageSetup()->getHorizontalCentered()) { + $objWriter->writeAttribute('horizontalCentered', 'true'); + } + + if ($pSheet->getPageSetup()->getVerticalCentered()) { + $objWriter->writeAttribute('verticalCentered', 'true'); + } + + $objWriter->endElement(); + } + + /** + * Write PageMargins + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writePageMargins(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // pageMargins + $objWriter->startElement('pageMargins'); + $objWriter->writeAttribute('left', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getLeft())); + $objWriter->writeAttribute('right', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getRight())); + $objWriter->writeAttribute('top', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getTop())); + $objWriter->writeAttribute('bottom', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getBottom())); + $objWriter->writeAttribute('header', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getHeader())); + $objWriter->writeAttribute('footer', PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getFooter())); + $objWriter->endElement(); + } + + /** + * Write AutoFilter + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeAutoFilter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + $autoFilterRange = $pSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { + // autoFilter + $objWriter->startElement('autoFilter'); + + // Strip any worksheet reference from the filter coordinates + $range = PHPExcel_Cell::splitRange($autoFilterRange); + $range = $range[0]; + // Strip any worksheet ref + if (strpos($range[0],'!') !== false) { + list($ws,$range[0]) = explode('!',$range[0]); + } + $range = implode(':', $range); + + $objWriter->writeAttribute('ref', str_replace('$','',$range)); + + $columns = $pSheet->getAutoFilter()->getColumns(); + if (count($columns > 0)) { + foreach($columns as $columnID => $column) { + $rules = $column->getRules(); + if (count($rules > 0)) { + $objWriter->startElement('filterColumn'); + $objWriter->writeAttribute('colId', $pSheet->getAutoFilter()->getColumnOffset($columnID)); + + $objWriter->startElement( $column->getFilterType()); + if ($column->getJoin() == PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_COLUMN_JOIN_AND) { + $objWriter->writeAttribute('and', 1); + } + + foreach ($rules as $rule) { + if (($column->getFilterType() === PHPExcel_Worksheet_AutoFilter_Column::AUTOFILTER_FILTERTYPE_FILTER) && + ($rule->getOperator() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL) && + ($rule->getValue() === '')) { + // Filter rule for Blanks + $objWriter->writeAttribute('blank', 1); + } elseif($rule->getRuleType() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DYNAMICFILTER) { + // Dynamic Filter Rule + $objWriter->writeAttribute('type', $rule->getGrouping()); + $val = $column->getAttribute('val'); + if ($val !== NULL) { + $objWriter->writeAttribute('val', $val); + } + $maxVal = $column->getAttribute('maxVal'); + if ($maxVal !== NULL) { + $objWriter->writeAttribute('maxVal', $maxVal); + } + } elseif($rule->getRuleType() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_TOPTENFILTER) { + // Top 10 Filter Rule + $objWriter->writeAttribute('val', $rule->getValue()); + $objWriter->writeAttribute('percent', (($rule->getOperator() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_PERCENT) ? '1' : '0')); + $objWriter->writeAttribute('top', (($rule->getGrouping() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_TOPTEN_TOP) ? '1': '0')); + } else { + // Filter, DateGroupItem or CustomFilter + $objWriter->startElement($rule->getRuleType()); + + if ($rule->getOperator() !== PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_COLUMN_RULE_EQUAL) { + $objWriter->writeAttribute('operator', $rule->getOperator()); + } + if ($rule->getRuleType() === PHPExcel_Worksheet_AutoFilter_Column_Rule::AUTOFILTER_RULETYPE_DATEGROUP) { + // Date Group filters + foreach($rule->getValue() as $key => $value) { + if ($value > '') $objWriter->writeAttribute($key, $value); + } + $objWriter->writeAttribute('dateTimeGrouping', $rule->getGrouping()); + } else { + $objWriter->writeAttribute('val', $rule->getValue()); + } + + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + + $objWriter->endElement(); + } + } + } + + $objWriter->endElement(); + } + } + + /** + * Write PageSetup + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writePageSetup(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // pageSetup + $objWriter->startElement('pageSetup'); + $objWriter->writeAttribute('paperSize', $pSheet->getPageSetup()->getPaperSize()); + $objWriter->writeAttribute('orientation', $pSheet->getPageSetup()->getOrientation()); + + if (!is_null($pSheet->getPageSetup()->getScale())) { + $objWriter->writeAttribute('scale', $pSheet->getPageSetup()->getScale()); + } + if (!is_null($pSheet->getPageSetup()->getFitToHeight())) { + $objWriter->writeAttribute('fitToHeight', $pSheet->getPageSetup()->getFitToHeight()); + } else { + $objWriter->writeAttribute('fitToHeight', '0'); + } + if (!is_null($pSheet->getPageSetup()->getFitToWidth())) { + $objWriter->writeAttribute('fitToWidth', $pSheet->getPageSetup()->getFitToWidth()); + } else { + $objWriter->writeAttribute('fitToWidth', '0'); + } + if (!is_null($pSheet->getPageSetup()->getFirstPageNumber())) { + $objWriter->writeAttribute('firstPageNumber', $pSheet->getPageSetup()->getFirstPageNumber()); + $objWriter->writeAttribute('useFirstPageNumber', '1'); + } + + $objWriter->endElement(); + } + + /** + * Write Header / Footer + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeHeaderFooter(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // headerFooter + $objWriter->startElement('headerFooter'); + $objWriter->writeAttribute('differentOddEven', ($pSheet->getHeaderFooter()->getDifferentOddEven() ? 'true' : 'false')); + $objWriter->writeAttribute('differentFirst', ($pSheet->getHeaderFooter()->getDifferentFirst() ? 'true' : 'false')); + $objWriter->writeAttribute('scaleWithDoc', ($pSheet->getHeaderFooter()->getScaleWithDocument() ? 'true' : 'false')); + $objWriter->writeAttribute('alignWithMargins', ($pSheet->getHeaderFooter()->getAlignWithMargins() ? 'true' : 'false')); + + $objWriter->writeElement('oddHeader', $pSheet->getHeaderFooter()->getOddHeader()); + $objWriter->writeElement('oddFooter', $pSheet->getHeaderFooter()->getOddFooter()); + $objWriter->writeElement('evenHeader', $pSheet->getHeaderFooter()->getEvenHeader()); + $objWriter->writeElement('evenFooter', $pSheet->getHeaderFooter()->getEvenFooter()); + $objWriter->writeElement('firstHeader', $pSheet->getHeaderFooter()->getFirstHeader()); + $objWriter->writeElement('firstFooter', $pSheet->getHeaderFooter()->getFirstFooter()); + $objWriter->endElement(); + } + + /** + * Write Breaks + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeBreaks(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // Get row and column breaks + $aRowBreaks = array(); + $aColumnBreaks = array(); + foreach ($pSheet->getBreaks() as $cell => $breakType) { + if ($breakType == PHPExcel_Worksheet::BREAK_ROW) { + $aRowBreaks[] = $cell; + } else if ($breakType == PHPExcel_Worksheet::BREAK_COLUMN) { + $aColumnBreaks[] = $cell; + } + } + + // rowBreaks + if (!empty($aRowBreaks)) { + $objWriter->startElement('rowBreaks'); + $objWriter->writeAttribute('count', count($aRowBreaks)); + $objWriter->writeAttribute('manualBreakCount', count($aRowBreaks)); + + foreach ($aRowBreaks as $cell) { + $coords = PHPExcel_Cell::coordinateFromString($cell); + + $objWriter->startElement('brk'); + $objWriter->writeAttribute('id', $coords[1]); + $objWriter->writeAttribute('man', '1'); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + + // Second, write column breaks + if (!empty($aColumnBreaks)) { + $objWriter->startElement('colBreaks'); + $objWriter->writeAttribute('count', count($aColumnBreaks)); + $objWriter->writeAttribute('manualBreakCount', count($aColumnBreaks)); + + foreach ($aColumnBreaks as $cell) { + $coords = PHPExcel_Cell::coordinateFromString($cell); + + $objWriter->startElement('brk'); + $objWriter->writeAttribute('id', PHPExcel_Cell::columnIndexFromString($coords[0]) - 1); + $objWriter->writeAttribute('man', '1'); + $objWriter->endElement(); + } + + $objWriter->endElement(); + } + } + + /** + * Write SheetData + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @param string[] $pStringTable String table + * @throws PHPExcel_Writer_Exception + */ + private function _writeSheetData(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pStringTable = null) + { + if (is_array($pStringTable)) { + // Flipped stringtable, for faster index searching + $aFlippedStringTable = $this->getParentWriter()->getWriterPart('stringtable')->flipStringTable($pStringTable); + + // sheetData + $objWriter->startElement('sheetData'); + + // Get column count + $colCount = PHPExcel_Cell::columnIndexFromString($pSheet->getHighestColumn()); + + // Highest row number + $highestRow = $pSheet->getHighestRow(); + + // Loop through cells + $cellsByRow = array(); + foreach ($pSheet->getCellCollection() as $cellID) { + $cellAddress = PHPExcel_Cell::coordinateFromString($cellID); + $cellsByRow[$cellAddress[1]][] = $cellID; + } + + $currentRow = 0; + while($currentRow++ < $highestRow) { + // Get row dimension + $rowDimension = $pSheet->getRowDimension($currentRow); + + // Write current row? + $writeCurrentRow = isset($cellsByRow[$currentRow]) || + $rowDimension->getRowHeight() >= 0 || + $rowDimension->getVisible() == false || + $rowDimension->getCollapsed() == true || + $rowDimension->getOutlineLevel() > 0 || + $rowDimension->getXfIndex() !== null; + + if ($writeCurrentRow) { + // Start a new row + $objWriter->startElement('row'); + $objWriter->writeAttribute('r', $currentRow); + $objWriter->writeAttribute('spans', '1:' . $colCount); + + // Row dimensions + if ($rowDimension->getRowHeight() >= 0) { + $objWriter->writeAttribute('customHeight', '1'); + $objWriter->writeAttribute('ht', PHPExcel_Shared_String::FormatNumber($rowDimension->getRowHeight())); + } + + // Row visibility + if ($rowDimension->getVisible() == false) { + $objWriter->writeAttribute('hidden', 'true'); + } + + // Collapsed + if ($rowDimension->getCollapsed() == true) { + $objWriter->writeAttribute('collapsed', 'true'); + } + + // Outline level + if ($rowDimension->getOutlineLevel() > 0) { + $objWriter->writeAttribute('outlineLevel', $rowDimension->getOutlineLevel()); + } + + // Style + if ($rowDimension->getXfIndex() !== null) { + $objWriter->writeAttribute('s', $rowDimension->getXfIndex()); + $objWriter->writeAttribute('customFormat', '1'); + } + + // Write cells + if (isset($cellsByRow[$currentRow])) { + foreach($cellsByRow[$currentRow] as $cellAddress) { + // Write cell + $this->_writeCell($objWriter, $pSheet, $cellAddress, $pStringTable, $aFlippedStringTable); + } + } + + // End row + $objWriter->endElement(); + } + } + + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } + + /** + * Write Cell + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @param PHPExcel_Cell $pCellAddress Cell Address + * @param string[] $pStringTable String table + * @param string[] $pFlippedStringTable String table (flipped), for faster index searching + * @throws PHPExcel_Writer_Exception + */ + private function _writeCell(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $pCellAddress = null, $pStringTable = null, $pFlippedStringTable = null) + { + if (is_array($pStringTable) && is_array($pFlippedStringTable)) { + // Cell + $pCell = $pSheet->getCell($pCellAddress); + $objWriter->startElement('c'); + $objWriter->writeAttribute('r', $pCellAddress); + + // Sheet styles + if ($pCell->getXfIndex() != '') { + $objWriter->writeAttribute('s', $pCell->getXfIndex()); + } + + // If cell value is supplied, write cell value + $cellValue = $pCell->getValue(); + if (is_object($cellValue) || $cellValue !== '') { + // Map type + $mappedType = $pCell->getDataType(); + + // Write data type depending on its type + switch (strtolower($mappedType)) { + case 'inlinestr': // Inline string + case 's': // String + case 'b': // Boolean + $objWriter->writeAttribute('t', $mappedType); + break; + case 'f': // Formula + $calculatedValue = ($this->getParentWriter()->getPreCalculateFormulas()) ? + $pCell->getCalculatedValue() : + $cellValue; + if (is_string($calculatedValue)) { + $objWriter->writeAttribute('t', 'str'); + } + break; + case 'e': // Error + $objWriter->writeAttribute('t', $mappedType); + } + + // Write data depending on its type + switch (strtolower($mappedType)) { + case 'inlinestr': // Inline string + if (! $cellValue instanceof PHPExcel_RichText) { + $objWriter->writeElement('t', PHPExcel_Shared_String::ControlCharacterPHP2OOXML( htmlspecialchars($cellValue) ) ); + } else if ($cellValue instanceof PHPExcel_RichText) { + $objWriter->startElement('is'); + $this->getParentWriter()->getWriterPart('stringtable')->writeRichText($objWriter, $cellValue); + $objWriter->endElement(); + } + + break; + case 's': // String + if (! $cellValue instanceof PHPExcel_RichText) { + if (isset($pFlippedStringTable[$cellValue])) { + $objWriter->writeElement('v', $pFlippedStringTable[$cellValue]); + } + } else if ($cellValue instanceof PHPExcel_RichText) { + $objWriter->writeElement('v', $pFlippedStringTable[$cellValue->getHashCode()]); + } + + break; + case 'f': // Formula + $attributes = $pCell->getFormulaAttributes(); + if($attributes['t'] == 'array') { + $objWriter->startElement('f'); + $objWriter->writeAttribute('t', 'array'); + $objWriter->writeAttribute('ref', $pCellAddress); + $objWriter->writeAttribute('aca', '1'); + $objWriter->writeAttribute('ca', '1'); + $objWriter->text(substr($cellValue, 1)); + $objWriter->endElement(); + } else { + $objWriter->writeElement('f', substr($cellValue, 1)); + } + if ($this->getParentWriter()->getOffice2003Compatibility() === false) { + if ($this->getParentWriter()->getPreCalculateFormulas()) { +// $calculatedValue = $pCell->getCalculatedValue(); + if (!is_array($calculatedValue) && substr($calculatedValue, 0, 1) != '#') { + $objWriter->writeElement('v', PHPExcel_Shared_String::FormatNumber($calculatedValue)); + } else { + $objWriter->writeElement('v', '0'); + } + } else { + $objWriter->writeElement('v', '0'); + } + } + break; + case 'n': // Numeric + // force point as decimal separator in case current locale uses comma + $objWriter->writeElement('v', str_replace(',', '.', $cellValue)); + break; + case 'b': // Boolean + $objWriter->writeElement('v', ($cellValue ? '1' : '0')); + break; + case 'e': // Error + if (substr($cellValue, 0, 1) == '=') { + $objWriter->writeElement('f', substr($cellValue, 1)); + $objWriter->writeElement('v', substr($cellValue, 1)); + } else { + $objWriter->writeElement('v', $cellValue); + } + + break; + } + } + + $objWriter->endElement(); + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } + + /** + * Write Drawings + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @param boolean $includeCharts Flag indicating if we should include drawing details for charts + * @throws PHPExcel_Writer_Exception + */ + private function _writeDrawings(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null, $includeCharts = FALSE) + { + $chartCount = ($includeCharts) ? $pSheet->getChartCollection()->count() : 0; + // If sheet contains drawings, add the relationships + if (($pSheet->getDrawingCollection()->count() > 0) || + ($chartCount > 0)) { + $objWriter->startElement('drawing'); + $objWriter->writeAttribute('r:id', 'rId1'); + $objWriter->endElement(); + } + } + + /** + * Write LegacyDrawing + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeLegacyDrawing(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // If sheet contains comments, add the relationships + if (count($pSheet->getComments()) > 0) { + $objWriter->startElement('legacyDrawing'); + $objWriter->writeAttribute('r:id', 'rId_comments_vml1'); + $objWriter->endElement(); + } + } + + /** + * Write LegacyDrawingHF + * + * @param PHPExcel_Shared_XMLWriter $objWriter XML Writer + * @param PHPExcel_Worksheet $pSheet Worksheet + * @throws PHPExcel_Writer_Exception + */ + private function _writeLegacyDrawingHF(PHPExcel_Shared_XMLWriter $objWriter = null, PHPExcel_Worksheet $pSheet = null) + { + // If sheet contains images, add the relationships + if (count($pSheet->getHeaderFooter()->getImages()) > 0) { + $objWriter->startElement('legacyDrawingHF'); + $objWriter->writeAttribute('r:id', 'rId_headerfooter_vml1'); + $objWriter->endElement(); + } + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/WriterPart.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/WriterPart.php new file mode 100755 index 0000000..0e5958c --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel2007/WriterPart.php @@ -0,0 +1,81 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel2007_WriterPart + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel2007 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +abstract class PHPExcel_Writer_Excel2007_WriterPart +{ + /** + * Parent IWriter object + * + * @var PHPExcel_Writer_IWriter + */ + private $_parentWriter; + + /** + * Set parent IWriter object + * + * @param PHPExcel_Writer_IWriter $pWriter + * @throws PHPExcel_Writer_Exception + */ + public function setParentWriter(PHPExcel_Writer_IWriter $pWriter = null) { + $this->_parentWriter = $pWriter; + } + + /** + * Get parent IWriter object + * + * @return PHPExcel_Writer_IWriter + * @throws PHPExcel_Writer_Exception + */ + public function getParentWriter() { + if (!is_null($this->_parentWriter)) { + return $this->_parentWriter; + } else { + throw new PHPExcel_Writer_Exception("No parent PHPExcel_Writer_IWriter assigned."); + } + } + + /** + * Set parent IWriter object + * + * @param PHPExcel_Writer_IWriter $pWriter + * @throws PHPExcel_Writer_Exception + */ + public function __construct(PHPExcel_Writer_IWriter $pWriter = null) { + if (!is_null($pWriter)) { + $this->_parentWriter = $pWriter; + } + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5.php new file mode 100755 index 0000000..f556067 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5.php @@ -0,0 +1,935 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel5 + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel5 extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter +{ + /** + * PHPExcel object + * + * @var PHPExcel + */ + private $_phpExcel; + + /** + * Total number of shared strings in workbook + * + * @var int + */ + private $_str_total = 0; + + /** + * Number of unique shared strings in workbook + * + * @var int + */ + private $_str_unique = 0; + + /** + * Array of unique shared strings in workbook + * + * @var array + */ + private $_str_table = array(); + + /** + * Color cache. Mapping between RGB value and color index. + * + * @var array + */ + private $_colors; + + /** + * Formula parser + * + * @var PHPExcel_Writer_Excel5_Parser + */ + private $_parser; + + /** + * Identifier clusters for drawings. Used in MSODRAWINGGROUP record. + * + * @var array + */ + private $_IDCLs; + + /** + * Basic OLE object summary information + * + * @var array + */ + private $_summaryInformation; + + /** + * Extended OLE object document summary information + * + * @var array + */ + private $_documentSummaryInformation; + + /** + * Create a new PHPExcel_Writer_Excel5 + * + * @param PHPExcel $phpExcel PHPExcel object + */ + public function __construct(PHPExcel $phpExcel) { + $this->_phpExcel = $phpExcel; + + $this->_parser = new PHPExcel_Writer_Excel5_Parser(); + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) { + + // garbage collect + $this->_phpExcel->garbageCollect(); + + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); + $saveDateReturnType = PHPExcel_Calculation_Functions::getReturnDateType(); + PHPExcel_Calculation_Functions::setReturnDateType(PHPExcel_Calculation_Functions::RETURNDATE_EXCEL); + + // initialize colors array + $this->_colors = array(); + + // Initialise workbook writer + $this->_writerWorkbook = new PHPExcel_Writer_Excel5_Workbook($this->_phpExcel, + $this->_str_total, $this->_str_unique, $this->_str_table, + $this->_colors, $this->_parser); + + // Initialise worksheet writers + $countSheets = $this->_phpExcel->getSheetCount(); + for ($i = 0; $i < $countSheets; ++$i) { + $this->_writerWorksheets[$i] = new PHPExcel_Writer_Excel5_Worksheet($this->_str_total, $this->_str_unique, + $this->_str_table, $this->_colors, + $this->_parser, + $this->_preCalculateFormulas, + $this->_phpExcel->getSheet($i)); + } + + // build Escher objects. Escher objects for workbooks needs to be build before Escher object for workbook. + $this->_buildWorksheetEschers(); + $this->_buildWorkbookEscher(); + + // add 15 identical cell style Xfs + // for now, we use the first cellXf instead of cellStyleXf + $cellXfCollection = $this->_phpExcel->getCellXfCollection(); + for ($i = 0; $i < 15; ++$i) { + $this->_writerWorkbook->addXfWriter($cellXfCollection[0], true); + } + + // add all the cell Xfs + foreach ($this->_phpExcel->getCellXfCollection() as $style) { + $this->_writerWorkbook->addXfWriter($style, false); + } + + // add fonts from rich text eleemnts + for ($i = 0; $i < $countSheets; ++$i) { + foreach ($this->_writerWorksheets[$i]->_phpSheet->getCellCollection() as $cellID) { + $cell = $this->_writerWorksheets[$i]->_phpSheet->getCell($cellID); + $cVal = $cell->getValue(); + if ($cVal instanceof PHPExcel_RichText) { + $elements = $cVal->getRichTextElements(); + foreach ($elements as $element) { + if ($element instanceof PHPExcel_RichText_Run) { + $font = $element->getFont(); + $this->_writerWorksheets[$i]->_fntHashIndex[$font->getHashCode()] = $this->_writerWorkbook->_addFont($font); + } + } + } + } + } + + // initialize OLE file + $workbookStreamName = 'Workbook'; + $OLE = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs($workbookStreamName)); + + // Write the worksheet streams before the global workbook stream, + // because the byte sizes of these are needed in the global workbook stream + $worksheetSizes = array(); + for ($i = 0; $i < $countSheets; ++$i) { + $this->_writerWorksheets[$i]->close(); + $worksheetSizes[] = $this->_writerWorksheets[$i]->_datasize; + } + + // add binary data for global workbook stream + $OLE->append($this->_writerWorkbook->writeWorkbook($worksheetSizes)); + + // add binary data for sheet streams + for ($i = 0; $i < $countSheets; ++$i) { + $OLE->append($this->_writerWorksheets[$i]->getData()); + } + + $this->_documentSummaryInformation = $this->_writeDocumentSummaryInformation(); + // initialize OLE Document Summary Information + if(isset($this->_documentSummaryInformation) && !empty($this->_documentSummaryInformation)){ + $OLE_DocumentSummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'DocumentSummaryInformation')); + $OLE_DocumentSummaryInformation->append($this->_documentSummaryInformation); + } + + $this->_summaryInformation = $this->_writeSummaryInformation(); + // initialize OLE Summary Information + if(isset($this->_summaryInformation) && !empty($this->_summaryInformation)){ + $OLE_SummaryInformation = new PHPExcel_Shared_OLE_PPS_File(PHPExcel_Shared_OLE::Asc2Ucs(chr(5) . 'SummaryInformation')); + $OLE_SummaryInformation->append($this->_summaryInformation); + } + + // define OLE Parts + $arrRootData = array($OLE); + // initialize OLE Properties file + if(isset($OLE_SummaryInformation)){ + $arrRootData[] = $OLE_SummaryInformation; + } + // initialize OLE Extended Properties file + if(isset($OLE_DocumentSummaryInformation)){ + $arrRootData[] = $OLE_DocumentSummaryInformation; + } + + $root = new PHPExcel_Shared_OLE_PPS_Root(time(), time(), $arrRootData); + // save the OLE file + $res = $root->save($pFilename); + + PHPExcel_Calculation_Functions::setReturnDateType($saveDateReturnType); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); + } + + /** + * Set temporary storage directory + * + * @deprecated + * @param string $pValue Temporary storage directory + * @throws PHPExcel_Writer_Exception when directory does not exist + * @return PHPExcel_Writer_Excel5 + */ + public function setTempDir($pValue = '') { + return $this; + } + + /** + * Build the Worksheet Escher objects + * + */ + private function _buildWorksheetEschers() + { + // 1-based index to BstoreContainer + $blipIndex = 0; + $lastReducedSpId = 0; + $lastSpId = 0; + + foreach ($this->_phpExcel->getAllsheets() as $sheet) { + // sheet index + $sheetIndex = $sheet->getParent()->getIndex($sheet); + + $escher = null; + + // check if there are any shapes for this sheet + $filterRange = $sheet->getAutoFilter()->getRange(); + if (count($sheet->getDrawingCollection()) == 0 && empty($filterRange)) { + continue; + } + + // create intermediate Escher object + $escher = new PHPExcel_Shared_Escher(); + + // dgContainer + $dgContainer = new PHPExcel_Shared_Escher_DgContainer(); + + // set the drawing index (we use sheet index + 1) + $dgId = $sheet->getParent()->getIndex($sheet) + 1; + $dgContainer->setDgId($dgId); + $escher->setDgContainer($dgContainer); + + // spgrContainer + $spgrContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer(); + $dgContainer->setSpgrContainer($spgrContainer); + + // add one shape which is the group shape + $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); + $spContainer->setSpgr(true); + $spContainer->setSpType(0); + $spContainer->setSpId(($sheet->getParent()->getIndex($sheet) + 1) << 10); + $spgrContainer->addChild($spContainer); + + // add the shapes + + $countShapes[$sheetIndex] = 0; // count number of shapes (minus group shape), in sheet + + foreach ($sheet->getDrawingCollection() as $drawing) { + ++$blipIndex; + + ++$countShapes[$sheetIndex]; + + // add the shape + $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); + + // set the shape type + $spContainer->setSpType(0x004B); + // set the shape flag + $spContainer->setSpFlag(0x02); + + // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index) + $reducedSpId = $countShapes[$sheetIndex]; + $spId = $reducedSpId + | ($sheet->getParent()->getIndex($sheet) + 1) << 10; + $spContainer->setSpId($spId); + + // keep track of last reducedSpId + $lastReducedSpId = $reducedSpId; + + // keep track of last spId + $lastSpId = $spId; + + // set the BLIP index + $spContainer->setOPT(0x4104, $blipIndex); + + // set coordinates and offsets, client anchor + $coordinates = $drawing->getCoordinates(); + $offsetX = $drawing->getOffsetX(); + $offsetY = $drawing->getOffsetY(); + $width = $drawing->getWidth(); + $height = $drawing->getHeight(); + + $twoAnchor = PHPExcel_Shared_Excel5::oneAnchor2twoAnchor($sheet, $coordinates, $offsetX, $offsetY, $width, $height); + + $spContainer->setStartCoordinates($twoAnchor['startCoordinates']); + $spContainer->setStartOffsetX($twoAnchor['startOffsetX']); + $spContainer->setStartOffsetY($twoAnchor['startOffsetY']); + $spContainer->setEndCoordinates($twoAnchor['endCoordinates']); + $spContainer->setEndOffsetX($twoAnchor['endOffsetX']); + $spContainer->setEndOffsetY($twoAnchor['endOffsetY']); + + $spgrContainer->addChild($spContainer); + } + + // AutoFilters + if(!empty($filterRange)){ + $rangeBounds = PHPExcel_Cell::rangeBoundaries($filterRange); + $iNumColStart = $rangeBounds[0][0]; + $iNumColEnd = $rangeBounds[1][0]; + + $iInc = $iNumColStart; + while($iInc <= $iNumColEnd){ + ++$countShapes[$sheetIndex]; + + // create an Drawing Object for the dropdown + $oDrawing = new PHPExcel_Worksheet_BaseDrawing(); + // get the coordinates of drawing + $cDrawing = PHPExcel_Cell::stringFromColumnIndex($iInc - 1) . $rangeBounds[0][1]; + $oDrawing->setCoordinates($cDrawing); + $oDrawing->setWorksheet($sheet); + + // add the shape + $spContainer = new PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer(); + // set the shape type + $spContainer->setSpType(0x00C9); + // set the shape flag + $spContainer->setSpFlag(0x01); + + // set the shape index (we combine 1-based sheet index and $countShapes to create unique shape index) + $reducedSpId = $countShapes[$sheetIndex]; + $spId = $reducedSpId + | ($sheet->getParent()->getIndex($sheet) + 1) << 10; + $spContainer->setSpId($spId); + + // keep track of last reducedSpId + $lastReducedSpId = $reducedSpId; + + // keep track of last spId + $lastSpId = $spId; + + $spContainer->setOPT(0x007F, 0x01040104); // Protection -> fLockAgainstGrouping + $spContainer->setOPT(0x00BF, 0x00080008); // Text -> fFitTextToShape + $spContainer->setOPT(0x01BF, 0x00010000); // Fill Style -> fNoFillHitTest + $spContainer->setOPT(0x01FF, 0x00080000); // Line Style -> fNoLineDrawDash + $spContainer->setOPT(0x03BF, 0x000A0000); // Group Shape -> fPrint + + // set coordinates and offsets, client anchor + $endCoordinates = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::stringFromColumnIndex($iInc - 1)); + $endCoordinates .= $rangeBounds[0][1] + 1; + + $spContainer->setStartCoordinates($cDrawing); + $spContainer->setStartOffsetX(0); + $spContainer->setStartOffsetY(0); + $spContainer->setEndCoordinates($endCoordinates); + $spContainer->setEndOffsetX(0); + $spContainer->setEndOffsetY(0); + + $spgrContainer->addChild($spContainer); + $iInc++; + } + } + + // identifier clusters, used for workbook Escher object + $this->_IDCLs[$dgId] = $lastReducedSpId; + + // set last shape index + $dgContainer->setLastSpId($lastSpId); + + // set the Escher object + $this->_writerWorksheets[$sheetIndex]->setEscher($escher); + } + } + + /** + * Build the Escher object corresponding to the MSODRAWINGGROUP record + */ + private function _buildWorkbookEscher() + { + $escher = null; + + // any drawings in this workbook? + $found = false; + foreach ($this->_phpExcel->getAllSheets() as $sheet) { + if (count($sheet->getDrawingCollection()) > 0) { + $found = true; + break; + } + } + + // nothing to do if there are no drawings + if (!$found) { + return; + } + + // if we reach here, then there are drawings in the workbook + $escher = new PHPExcel_Shared_Escher(); + + // dggContainer + $dggContainer = new PHPExcel_Shared_Escher_DggContainer(); + $escher->setDggContainer($dggContainer); + + // set IDCLs (identifier clusters) + $dggContainer->setIDCLs($this->_IDCLs); + + // this loop is for determining maximum shape identifier of all drawing + $spIdMax = 0; + $totalCountShapes = 0; + $countDrawings = 0; + + foreach ($this->_phpExcel->getAllsheets() as $sheet) { + $sheetCountShapes = 0; // count number of shapes (minus group shape), in sheet + + if (count($sheet->getDrawingCollection()) > 0) { + ++$countDrawings; + + foreach ($sheet->getDrawingCollection() as $drawing) { + ++$sheetCountShapes; + ++$totalCountShapes; + + $spId = $sheetCountShapes + | ($this->_phpExcel->getIndex($sheet) + 1) << 10; + $spIdMax = max($spId, $spIdMax); + } + } + } + + $dggContainer->setSpIdMax($spIdMax + 1); + $dggContainer->setCDgSaved($countDrawings); + $dggContainer->setCSpSaved($totalCountShapes + $countDrawings); // total number of shapes incl. one group shapes per drawing + + // bstoreContainer + $bstoreContainer = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer(); + $dggContainer->setBstoreContainer($bstoreContainer); + + // the BSE's (all the images) + foreach ($this->_phpExcel->getAllsheets() as $sheet) { + foreach ($sheet->getDrawingCollection() as $drawing) { + if ($drawing instanceof PHPExcel_Worksheet_Drawing) { + + $filename = $drawing->getPath(); + + list($imagesx, $imagesy, $imageFormat) = getimagesize($filename); + + switch ($imageFormat) { + + case 1: // GIF, not supported by BIFF8, we convert to PNG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + ob_start(); + imagepng(imagecreatefromgif($filename)); + $blipData = ob_get_contents(); + ob_end_clean(); + break; + + case 2: // JPEG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG; + $blipData = file_get_contents($filename); + break; + + case 3: // PNG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + $blipData = file_get_contents($filename); + break; + + case 6: // Windows DIB (BMP), we convert to PNG + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + ob_start(); + imagepng(PHPExcel_Shared_Drawing::imagecreatefrombmp($filename)); + $blipData = ob_get_contents(); + ob_end_clean(); + break; + + default: continue 2; + + } + + $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); + $blip->setData($blipData); + + $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); + $BSE->setBlipType($blipType); + $BSE->setBlip($blip); + + $bstoreContainer->addBSE($BSE); + + } else if ($drawing instanceof PHPExcel_Worksheet_MemoryDrawing) { + + switch ($drawing->getRenderingFunction()) { + + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_JPEG: + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG; + $renderingFunction = 'imagejpeg'; + break; + + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_GIF: + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_PNG: + case PHPExcel_Worksheet_MemoryDrawing::RENDERING_DEFAULT: + $blipType = PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG; + $renderingFunction = 'imagepng'; + break; + + } + + ob_start(); + call_user_func($renderingFunction, $drawing->getImageResource()); + $blipData = ob_get_contents(); + ob_end_clean(); + + $blip = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip(); + $blip->setData($blipData); + + $BSE = new PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE(); + $BSE->setBlipType($blipType); + $BSE->setBlip($blip); + + $bstoreContainer->addBSE($BSE); + } + } + } + + // Set the Escher object + $this->_writerWorkbook->setEscher($escher); + } + + /** + * Build the OLE Part for DocumentSummary Information + * @return string + */ + private function _writeDocumentSummaryInformation(){ + + // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) + $data = pack('v', 0xFFFE); + // offset: 2; size: 2; + $data .= pack('v', 0x0000); + // offset: 4; size: 2; OS version + $data .= pack('v', 0x0106); + // offset: 6; size: 2; OS indicator + $data .= pack('v', 0x0002); + // offset: 8; size: 16 + $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00); + // offset: 24; size: 4; section count + $data .= pack('V', 0x0001); + + // offset: 28; size: 16; first section's class id: 02 d5 cd d5 9c 2e 1b 10 93 97 08 00 2b 2c f9 ae + $data .= pack('vvvvvvvv', 0xD502, 0xD5CD, 0x2E9C, 0x101B, 0x9793, 0x0008, 0x2C2B, 0xAEF9); + // offset: 44; size: 4; offset of the start + $data .= pack('V', 0x30); + + // SECTION + $dataSection = array(); + $dataSection_NumProps = 0; + $dataSection_Summary = ''; + $dataSection_Content = ''; + + // GKPIDDSI_CODEPAGE: CodePage + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x01), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x02), // 2 byte signed integer + 'data' => array('data' => 1252)); + $dataSection_NumProps++; + + // GKPIDDSI_CATEGORY : Category + if($this->_phpExcel->getProperties()->getCategory()){ + $dataProp = $this->_phpExcel->getProperties()->getCategory(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // GKPIDDSI_VERSION :Version of the application that wrote the property storage + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x17), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x03), + 'data' => array('pack' => 'V', 'data' => 0x000C0000)); + $dataSection_NumProps++; + // GKPIDDSI_SCALE : FALSE + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0B), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; + // GKPIDDSI_LINKSDIRTY : True if any of the values for the linked properties have changed outside of the application + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x10), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; + // GKPIDDSI_SHAREDOC : FALSE + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x13), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; + // GKPIDDSI_HYPERLINKSCHANGED : True if any of the values for the _PID_LINKS (hyperlink text) have changed outside of the application + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x16), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x0B), + 'data' => array('data' => false)); + $dataSection_NumProps++; + + // GKPIDDSI_DOCSPARTS + // MS-OSHARED p75 (2.3.3.2.2.1) + // Structure is VtVecUnalignedLpstrValue (2.3.3.1.9) + // cElements + $dataProp = pack('v', 0x0001); + $dataProp .= pack('v', 0x0000); + // array of UnalignedLpstr + // cch + $dataProp .= pack('v', 0x000A); + $dataProp .= pack('v', 0x0000); + // value + $dataProp .= 'Worksheet'.chr(0); + + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0D), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x101E), + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + + // GKPIDDSI_HEADINGPAIR + // VtVecHeadingPairValue + // cElements + $dataProp = pack('v', 0x0002); + $dataProp .= pack('v', 0x0000); + // Array of vtHeadingPair + // vtUnalignedString - headingString + // stringType + $dataProp .= pack('v', 0x001E); + // padding + $dataProp .= pack('v', 0x0000); + // UnalignedLpstr + // cch + $dataProp .= pack('v', 0x0013); + $dataProp .= pack('v', 0x0000); + // value + $dataProp .= 'Feuilles de calcul'; + // vtUnalignedString - headingParts + // wType : 0x0003 = 32 bit signed integer + $dataProp .= pack('v', 0x0300); + // padding + $dataProp .= pack('v', 0x0000); + // value + $dataProp .= pack('v', 0x0100); + $dataProp .= pack('v', 0x0000); + $dataProp .= pack('v', 0x0000); + $dataProp .= pack('v', 0x0000); + + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0C), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x100C), + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + + // 4 Section Length + // 4 Property count + // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4)) + $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8; + foreach ($dataSection as $dataProp){ + // Summary + $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']); + // Offset + $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset); + // DataType + $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']); + // Data + if($dataProp['type']['data'] == 0x02){ // 2 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); + + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x03){ // 4 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); + + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x0B){ // Boolean + if($dataProp['data']['data'] == false){ + $dataSection_Content .= pack('V', 0x0000); + } else { + $dataSection_Content .= pack('V', 0x0001); + } + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x1E){ // null-terminated string prepended by dword string length + // Null-terminated string + $dataProp['data']['data'] .= chr(0); + $dataProp['data']['length'] += 1; + // Complete the string with null string for being a %4 + $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4)==4 ? 0 : (4 - $dataProp['data']['length'] % 4)); + $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT); + + $dataSection_Content .= pack('V', $dataProp['data']['length']); + $dataSection_Content .= $dataProp['data']['data']; + + $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']); + } + elseif($dataProp['type']['data'] == 0x40){ // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + $dataSection_Content .= $dataProp['data']['data']; + + $dataSection_Content_Offset += 4 + 8; + } + else { + // Data Type Not Used at the moment + $dataSection_Content .= $dataProp['data']['data']; + + $dataSection_Content_Offset += 4 + $dataProp['data']['length']; + } + } + // Now $dataSection_Content_Offset contains the size of the content + + // section header + // offset: $secOffset; size: 4; section length + // + x Size of the content (summary + content) + $data .= pack('V', $dataSection_Content_Offset); + // offset: $secOffset+4; size: 4; property count + $data .= pack('V', $dataSection_NumProps); + // Section Summary + $data .= $dataSection_Summary; + // Section Content + $data .= $dataSection_Content; + + return $data; + } + + /** + * Build the OLE Part for Summary Information + * @return string + */ + private function _writeSummaryInformation(){ + // offset: 0; size: 2; must be 0xFE 0xFF (UTF-16 LE byte order mark) + $data = pack('v', 0xFFFE); + // offset: 2; size: 2; + $data .= pack('v', 0x0000); + // offset: 4; size: 2; OS version + $data .= pack('v', 0x0106); + // offset: 6; size: 2; OS indicator + $data .= pack('v', 0x0002); + // offset: 8; size: 16 + $data .= pack('VVVV', 0x00, 0x00, 0x00, 0x00); + // offset: 24; size: 4; section count + $data .= pack('V', 0x0001); + + // offset: 28; size: 16; first section's class id: e0 85 9f f2 f9 4f 68 10 ab 91 08 00 2b 27 b3 d9 + $data .= pack('vvvvvvvv', 0x85E0, 0xF29F, 0x4FF9, 0x1068, 0x91AB, 0x0008, 0x272B, 0xD9B3); + // offset: 44; size: 4; offset of the start + $data .= pack('V', 0x30); + + // SECTION + $dataSection = array(); + $dataSection_NumProps = 0; + $dataSection_Summary = ''; + $dataSection_Content = ''; + + // CodePage : CP-1252 + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x01), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x02), // 2 byte signed integer + 'data' => array('data' => 1252)); + $dataSection_NumProps++; + + // Title + if($this->_phpExcel->getProperties()->getTitle()){ + $dataProp = $this->_phpExcel->getProperties()->getTitle(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x02), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Subject + if($this->_phpExcel->getProperties()->getSubject()){ + $dataProp = $this->_phpExcel->getProperties()->getSubject(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x03), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Author (Creator) + if($this->_phpExcel->getProperties()->getCreator()){ + $dataProp = $this->_phpExcel->getProperties()->getCreator(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x04), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Keywords + if($this->_phpExcel->getProperties()->getKeywords()){ + $dataProp = $this->_phpExcel->getProperties()->getKeywords(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x05), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Comments (Description) + if($this->_phpExcel->getProperties()->getDescription()){ + $dataProp = $this->_phpExcel->getProperties()->getDescription(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x06), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Last Saved By (LastModifiedBy) + if($this->_phpExcel->getProperties()->getLastModifiedBy()){ + $dataProp = $this->_phpExcel->getProperties()->getLastModifiedBy(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x08), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x1E), // null-terminated string prepended by dword string length + 'data' => array('data' => $dataProp, 'length' => strlen($dataProp))); + $dataSection_NumProps++; + } + // Created Date/Time + if($this->_phpExcel->getProperties()->getCreated()){ + $dataProp = $this->_phpExcel->getProperties()->getCreated(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0C), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x40), // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + 'data' => array('data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp))); + $dataSection_NumProps++; + } + // Modified Date/Time + if($this->_phpExcel->getProperties()->getModified()){ + $dataProp = $this->_phpExcel->getProperties()->getModified(); + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x0D), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x40), // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + 'data' => array('data' => PHPExcel_Shared_OLE::LocalDate2OLE($dataProp))); + $dataSection_NumProps++; + } + // Security + $dataSection[] = array('summary'=> array('pack' => 'V', 'data' => 0x13), + 'offset' => array('pack' => 'V'), + 'type' => array('pack' => 'V', 'data' => 0x03), // 4 byte signed integer + 'data' => array('data' => 0x00)); + $dataSection_NumProps++; + + + // 4 Section Length + // 4 Property count + // 8 * $dataSection_NumProps (8 = ID (4) + OffSet(4)) + $dataSection_Content_Offset = 8 + $dataSection_NumProps * 8; + foreach ($dataSection as $dataProp){ + // Summary + $dataSection_Summary .= pack($dataProp['summary']['pack'], $dataProp['summary']['data']); + // Offset + $dataSection_Summary .= pack($dataProp['offset']['pack'], $dataSection_Content_Offset); + // DataType + $dataSection_Content .= pack($dataProp['type']['pack'], $dataProp['type']['data']); + // Data + if($dataProp['type']['data'] == 0x02){ // 2 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); + + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x03){ // 4 byte signed integer + $dataSection_Content .= pack('V', $dataProp['data']['data']); + + $dataSection_Content_Offset += 4 + 4; + } + elseif($dataProp['type']['data'] == 0x1E){ // null-terminated string prepended by dword string length + // Null-terminated string + $dataProp['data']['data'] .= chr(0); + $dataProp['data']['length'] += 1; + // Complete the string with null string for being a %4 + $dataProp['data']['length'] = $dataProp['data']['length'] + ((4 - $dataProp['data']['length'] % 4)==4 ? 0 : (4 - $dataProp['data']['length'] % 4)); + $dataProp['data']['data'] = str_pad($dataProp['data']['data'], $dataProp['data']['length'], chr(0), STR_PAD_RIGHT); + + $dataSection_Content .= pack('V', $dataProp['data']['length']); + $dataSection_Content .= $dataProp['data']['data']; + + $dataSection_Content_Offset += 4 + 4 + strlen($dataProp['data']['data']); + } + elseif($dataProp['type']['data'] == 0x40){ // Filetime (64-bit value representing the number of 100-nanosecond intervals since January 1, 1601) + $dataSection_Content .= $dataProp['data']['data']; + + $dataSection_Content_Offset += 4 + 8; + } + else { + // Data Type Not Used at the moment + } + } + // Now $dataSection_Content_Offset contains the size of the content + + // section header + // offset: $secOffset; size: 4; section length + // + x Size of the content (summary + content) + $data .= pack('V', $dataSection_Content_Offset); + // offset: $secOffset+4; size: 4; property count + $data .= pack('V', $dataSection_NumProps); + // Section Summary + $data .= $dataSection_Summary; + // Section Content + $data .= $dataSection_Content; + + return $data; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/BIFFwriter.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/BIFFwriter.php new file mode 100755 index 0000000..02a06ad --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/BIFFwriter.php @@ -0,0 +1,255 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +// Original file header of PEAR::Spreadsheet_Excel_Writer_BIFFwriter (used as the base for this class): +// ----------------------------------------------------------------------------------------- +// * Module written/ported by Xavier Noguer <xnoguer@rezebra.com> +// * +// * The majority of this is _NOT_ my code. I simply ported it from the +// * PERL Spreadsheet::WriteExcel module. +// * +// * The author of the Spreadsheet::WriteExcel module is John McNamara +// * <jmcnamara@cpan.org> +// * +// * I _DO_ maintain this code, and John McNamara has nothing to do with the +// * porting of this code to PHP. Any questions directly related to this +// * class library should be directed to me. +// * +// * License Information: +// * +// * Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets +// * Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com +// * +// * This library is free software; you can redistribute it and/or +// * modify it under the terms of the GNU Lesser General Public +// * License as published by the Free Software Foundation; either +// * version 2.1 of the License, or (at your option) any later version. +// * +// * This library is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// * Lesser General Public License for more details. +// * +// * You should have received a copy of the GNU Lesser General Public +// * License along with this library; if not, write to the Free Software +// * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// */ + + +/** + * PHPExcel_Writer_Excel5_BIFFwriter + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel5_BIFFwriter +{ + /** + * The byte order of this architecture. 0 => little endian, 1 => big endian + * @var integer + */ + private static $_byte_order; + + /** + * The string containing the data of the BIFF stream + * @var string + */ + public $_data; + + /** + * The size of the data in bytes. Should be the same as strlen($this->_data) + * @var integer + */ + public $_datasize; + + /** + * The maximum length for a BIFF record (excluding record header and length field). See _addContinue() + * @var integer + * @see _addContinue() + */ + public $_limit = 8224; + + /** + * Constructor + */ + public function __construct() + { + $this->_data = ''; + $this->_datasize = 0; +// $this->_limit = 8224; + } + + /** + * Determine the byte order and store it as class data to avoid + * recalculating it for each call to new(). + * + * @return int + */ + public static function getByteOrder() + { + if (!isset(self::$_byte_order)) { + // Check if "pack" gives the required IEEE 64bit float + $teststr = pack("d", 1.2345); + $number = pack("C8", 0x8D, 0x97, 0x6E, 0x12, 0x83, 0xC0, 0xF3, 0x3F); + if ($number == $teststr) { + $byte_order = 0; // Little Endian + } elseif ($number == strrev($teststr)){ + $byte_order = 1; // Big Endian + } else { + // Give up. I'll fix this in a later version. + throw new PHPExcel_Writer_Exception("Required floating point format not supported on this platform."); + } + self::$_byte_order = $byte_order; + } + + return self::$_byte_order; + } + + /** + * General storage function + * + * @param string $data binary data to append + * @access private + */ + function _append($data) + { + if (strlen($data) - 4 > $this->_limit) { + $data = $this->_addContinue($data); + } + $this->_data .= $data; + $this->_datasize += strlen($data); + } + + /** + * General storage function like _append, but returns string instead of modifying $this->_data + * + * @param string $data binary data to write + * @return string + */ + public function writeData($data) + { + if (strlen($data) - 4 > $this->_limit) { + $data = $this->_addContinue($data); + } + $this->_datasize += strlen($data); + + return $data; + } + + /** + * Writes Excel BOF record to indicate the beginning of a stream or + * sub-stream in the BIFF file. + * + * @param integer $type Type of BIFF file to write: 0x0005 Workbook, + * 0x0010 Worksheet. + * @access private + */ + function _storeBof($type) + { + $record = 0x0809; // Record identifier (BIFF5-BIFF8) + $length = 0x0010; + + // by inspection of real files, MS Office Excel 2007 writes the following + $unknown = pack("VV", 0x000100D1, 0x00000406); + + $build = 0x0DBB; // Excel 97 + $year = 0x07CC; // Excel 97 + + $version = 0x0600; // BIFF8 + + $header = pack("vv", $record, $length); + $data = pack("vvvv", $version, $type, $build, $year); + $this->_append($header . $data . $unknown); + } + + /** + * Writes Excel EOF record to indicate the end of a BIFF stream. + * + * @access private + */ + function _storeEof() + { + $record = 0x000A; // Record identifier + $length = 0x0000; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $this->_append($header); + } + + /** + * Writes Excel EOF record to indicate the end of a BIFF stream. + * + * @access private + */ + public function writeEof() + { + $record = 0x000A; // Record identifier + $length = 0x0000; // Number of bytes to follow + $header = pack("vv", $record, $length); + return $this->writeData($header); + } + + /** + * Excel limits the size of BIFF records. In Excel 5 the limit is 2084 bytes. In + * Excel 97 the limit is 8228 bytes. Records that are longer than these limits + * must be split up into CONTINUE blocks. + * + * This function takes a long BIFF record and inserts CONTINUE records as + * necessary. + * + * @param string $data The original binary data to be written + * @return string A very convenient string of continue blocks + * @access private + */ + function _addContinue($data) + { + $limit = $this->_limit; + $record = 0x003C; // Record identifier + + // The first 2080/8224 bytes remain intact. However, we have to change + // the length field of the record. + $tmp = substr($data, 0, 2) . pack("v", $limit) . substr($data, 4, $limit); + + $header = pack("vv", $record, $limit); // Headers for continue records + + // Retrieve chunks of 2080/8224 bytes +4 for the header. + $data_length = strlen($data); + for ($i = $limit + 4; $i < ($data_length - $limit); $i += $limit) { + $tmp .= $header; + $tmp .= substr($data, $i, $limit); + } + + // Retrieve the last chunk of data + $header = pack("vv", $record, strlen($data) - $i); + $tmp .= $header; + $tmp .= substr($data, $i, strlen($data) - $i); + + return $tmp; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Escher.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Escher.php new file mode 100755 index 0000000..0624e04 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Escher.php @@ -0,0 +1,537 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Shared_Escher_DggContainer_BstoreContainer + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel5_Escher +{ + /** + * The object we are writing + */ + private $_object; + + /** + * The written binary data + */ + private $_data; + + /** + * Shape offsets. Positions in binary stream where a new shape record begins + * + * @var array + */ + private $_spOffsets; + + /** + * Shape types. + * + * @var array + */ + private $_spTypes; + + /** + * Constructor + * + * @param mixed + */ + public function __construct($object) + { + $this->_object = $object; + } + + /** + * Process the object to be written + */ + public function close() + { + // initialize + $this->_data = ''; + + switch (get_class($this->_object)) { + + case 'PHPExcel_Shared_Escher': + if ($dggContainer = $this->_object->getDggContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($dggContainer); + $this->_data = $writer->close(); + } else if ($dgContainer = $this->_object->getDgContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($dgContainer); + $this->_data = $writer->close(); + $this->_spOffsets = $writer->getSpOffsets(); + $this->_spTypes = $writer->getSpTypes(); + } + break; + + case 'PHPExcel_Shared_Escher_DggContainer': + // this is a container record + + // initialize + $innerData = ''; + + // write the dgg + $recVer = 0x0; + $recInstance = 0x0000; + $recType = 0xF006; + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + // dgg data + $dggData = + pack('VVVV' + , $this->_object->getSpIdMax() // maximum shape identifier increased by one + , $this->_object->getCDgSaved() + 1 // number of file identifier clusters increased by one + , $this->_object->getCSpSaved() + , $this->_object->getCDgSaved() // count total number of drawings saved + ); + + // add file identifier clusters (one per drawing) + $IDCLs = $this->_object->getIDCLs(); + + foreach ($IDCLs as $dgId => $maxReducedSpId) { + $dggData .= pack('VV', $dgId, $maxReducedSpId + 1); + } + + $header = pack('vvV', $recVerInstance, $recType, strlen($dggData)); + $innerData .= $header . $dggData; + + // write the bstoreContainer + if ($bstoreContainer = $this->_object->getBstoreContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($bstoreContainer); + $innerData .= $writer->close(); + } + + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF000; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header . $innerData; + break; + + case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer': + // this is a container record + + // initialize + $innerData = ''; + + // treat the inner data + if ($BSECollection = $this->_object->getBSECollection()) { + foreach ($BSECollection as $BSE) { + $writer = new PHPExcel_Writer_Excel5_Escher($BSE); + $innerData .= $writer->close(); + } + } + + // write the record + $recVer = 0xF; + $recInstance = count($this->_object->getBSECollection()); + $recType = 0xF001; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header . $innerData; + break; + + case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE': + // this is a semi-container record + + // initialize + $innerData = ''; + + // here we treat the inner data + if ($blip = $this->_object->getBlip()) { + $writer = new PHPExcel_Writer_Excel5_Escher($blip); + $innerData .= $writer->close(); + } + + // initialize + $data = ''; + + $btWin32 = $this->_object->getBlipType(); + $btMacOS = $this->_object->getBlipType(); + $data .= pack('CC', $btWin32, $btMacOS); + + $rgbUid = pack('VVVV', 0,0,0,0); // todo + $data .= $rgbUid; + + $tag = 0; + $size = strlen($innerData); + $cRef = 1; + $foDelay = 0; //todo + $unused1 = 0x0; + $cbName = 0x0; + $unused2 = 0x0; + $unused3 = 0x0; + $data .= pack('vVVVCCCC', $tag, $size, $cRef, $foDelay, $unused1, $cbName, $unused2, $unused3); + + $data .= $innerData; + + // write the record + $recVer = 0x2; + $recInstance = $this->_object->getBlipType(); + $recType = 0xF007; + $length = strlen($data); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header; + + $this->_data .= $data; + break; + + case 'PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE_Blip': + // this is an atom record + + // write the record + switch ($this->_object->getParent()->getBlipType()) { + + case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_JPEG: + // initialize + $innerData = ''; + + $rgbUid1 = pack('VVVV', 0,0,0,0); // todo + $innerData .= $rgbUid1; + + $tag = 0xFF; // todo + $innerData .= pack('C', $tag); + + $innerData .= $this->_object->getData(); + + $recVer = 0x0; + $recInstance = 0x46A; + $recType = 0xF01D; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header; + + $this->_data .= $innerData; + break; + + case PHPExcel_Shared_Escher_DggContainer_BstoreContainer_BSE::BLIPTYPE_PNG: + // initialize + $innerData = ''; + + $rgbUid1 = pack('VVVV', 0,0,0,0); // todo + $innerData .= $rgbUid1; + + $tag = 0xFF; // todo + $innerData .= pack('C', $tag); + + $innerData .= $this->_object->getData(); + + $recVer = 0x0; + $recInstance = 0x6E0; + $recType = 0xF01E; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header; + + $this->_data .= $innerData; + break; + + } + break; + + case 'PHPExcel_Shared_Escher_DgContainer': + // this is a container record + + // initialize + $innerData = ''; + + // write the dg + $recVer = 0x0; + $recInstance = $this->_object->getDgId(); + $recType = 0xF008; + $length = 8; + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + // number of shapes in this drawing (including group shape) + $countShapes = count($this->_object->getSpgrContainer()->getChildren()); + $innerData .= $header . pack('VV', $countShapes, $this->_object->getLastSpId()); + //$innerData .= $header . pack('VV', 0, 0); + + // write the spgrContainer + if ($spgrContainer = $this->_object->getSpgrContainer()) { + $writer = new PHPExcel_Writer_Excel5_Escher($spgrContainer); + $innerData .= $writer->close(); + + // get the shape offsets relative to the spgrContainer record + $spOffsets = $writer->getSpOffsets(); + $spTypes = $writer->getSpTypes(); + + // save the shape offsets relative to dgContainer + foreach ($spOffsets as & $spOffset) { + $spOffset += 24; // add length of dgContainer header data (8 bytes) plus dg data (16 bytes) + } + + $this->_spOffsets = $spOffsets; + $this->_spTypes = $spTypes; + } + + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF002; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header . $innerData; + break; + + case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer': + // this is a container record + + // initialize + $innerData = ''; + + // initialize spape offsets + $totalSize = 8; + $spOffsets = array(); + $spTypes = array(); + + // treat the inner data + foreach ($this->_object->getChildren() as $spContainer) { + $writer = new PHPExcel_Writer_Excel5_Escher($spContainer); + $spData = $writer->close(); + $innerData .= $spData; + + // save the shape offsets (where new shape records begin) + $totalSize += strlen($spData); + $spOffsets[] = $totalSize; + + $spTypes = array_merge($spTypes, $writer->getSpTypes()); + } + + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF003; + $length = strlen($innerData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header . $innerData; + $this->_spOffsets = $spOffsets; + $this->_spTypes = $spTypes; + break; + + case 'PHPExcel_Shared_Escher_DgContainer_SpgrContainer_SpContainer': + // initialize + $data = ''; + + // build the data + + // write group shape record, if necessary? + if ($this->_object->getSpgr()) { + $recVer = 0x1; + $recInstance = 0x0000; + $recType = 0xF009; + $length = 0x00000010; + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $data .= $header . pack('VVVV', 0,0,0,0); + } + $this->_spTypes[] = ($this->_object->getSpType()); + + // write the shape record + $recVer = 0x2; + $recInstance = $this->_object->getSpType(); // shape type + $recType = 0xF00A; + $length = 0x00000008; + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $data .= $header . pack('VV', $this->_object->getSpId(), $this->_object->getSpgr() ? 0x0005 : 0x0A00); + + + // the options + if ($this->_object->getOPTCollection()) { + $optData = ''; + + $recVer = 0x3; + $recInstance = count($this->_object->getOPTCollection()); + $recType = 0xF00B; + foreach ($this->_object->getOPTCollection() as $property => $value) { + $optData .= pack('vV', $property, $value); + } + $length = strlen($optData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + $data .= $header . $optData; + } + + // the client anchor + if ($this->_object->getStartCoordinates()) { + $clientAnchorData = ''; + + $recVer = 0x0; + $recInstance = 0x0; + $recType = 0xF010; + + // start coordinates + list($column, $row) = PHPExcel_Cell::coordinateFromString($this->_object->getStartCoordinates()); + $c1 = PHPExcel_Cell::columnIndexFromString($column) - 1; + $r1 = $row - 1; + + // start offsetX + $startOffsetX = $this->_object->getStartOffsetX(); + + // start offsetY + $startOffsetY = $this->_object->getStartOffsetY(); + + // end coordinates + list($column, $row) = PHPExcel_Cell::coordinateFromString($this->_object->getEndCoordinates()); + $c2 = PHPExcel_Cell::columnIndexFromString($column) - 1; + $r2 = $row - 1; + + // end offsetX + $endOffsetX = $this->_object->getEndOffsetX(); + + // end offsetY + $endOffsetY = $this->_object->getEndOffsetY(); + + $clientAnchorData = pack('vvvvvvvvv', $this->_object->getSpFlag(), + $c1, $startOffsetX, $r1, $startOffsetY, + $c2, $endOffsetX, $r2, $endOffsetY); + + $length = strlen($clientAnchorData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + $data .= $header . $clientAnchorData; + } + + // the client data, just empty for now + if (!$this->_object->getSpgr()) { + $clientDataData = ''; + + $recVer = 0x0; + $recInstance = 0x0; + $recType = 0xF011; + + $length = strlen($clientDataData); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + $data .= $header . $clientDataData; + } + + // write the record + $recVer = 0xF; + $recInstance = 0x0000; + $recType = 0xF004; + $length = strlen($data); + + $recVerInstance = $recVer; + $recVerInstance |= $recInstance << 4; + + $header = pack('vvV', $recVerInstance, $recType, $length); + + $this->_data = $header . $data; + break; + + } + + return $this->_data; + } + + /** + * Gets the shape offsets + * + * @return array + */ + public function getSpOffsets() + { + return $this->_spOffsets; + } + + /** + * Gets the shape types + * + * @return array + */ + public function getSpTypes() + { + return $this->_spTypes; + } + + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Font.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Font.php new file mode 100755 index 0000000..da1c9c1 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Font.php @@ -0,0 +1,165 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Excel5_Font + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel5_Font +{ + /** + * Color index + * + * @var int + */ + private $_colorIndex; + + /** + * Font + * + * @var PHPExcel_Style_Font + */ + private $_font; + + /** + * Constructor + * + * @param PHPExcel_Style_Font $font + */ + public function __construct(PHPExcel_Style_Font $font = null) + { + $this->_colorIndex = 0x7FFF; + $this->_font = $font; + } + + /** + * Set the color index + * + * @param int $colorIndex + */ + public function setColorIndex($colorIndex) + { + $this->_colorIndex = $colorIndex; + } + + /** + * Get font record data + * + * @return string + */ + public function writeFont() + { + $font_outline = 0; + $font_shadow = 0; + + $icv = $this->_colorIndex; // Index to color palette + if ($this->_font->getSuperScript()) { + $sss = 1; + } else if ($this->_font->getSubScript()) { + $sss = 2; + } else { + $sss = 0; + } + $bFamily = 0; // Font family + $bCharSet = PHPExcel_Shared_Font::getCharsetFromFontName($this->_font->getName()); // Character set + + $record = 0x31; // Record identifier + $reserved = 0x00; // Reserved + $grbit = 0x00; // Font attributes + if ($this->_font->getItalic()) { + $grbit |= 0x02; + } + if ($this->_font->getStrikethrough()) { + $grbit |= 0x08; + } + if ($font_outline) { + $grbit |= 0x10; + } + if ($font_shadow) { + $grbit |= 0x20; + } + + $data = pack("vvvvvCCCC", + $this->_font->getSize() * 20, // Fontsize (in twips) + $grbit, + $icv, // Colour + self::_mapBold($this->_font->getBold()), // Font weight + $sss, // Superscript/Subscript + self::_mapUnderline($this->_font->getUnderline()), + $bFamily, + $bCharSet, + $reserved + ); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($this->_font->getName()); + + $length = strlen($data); + $header = pack("vv", $record, $length); + + return($header . $data); + } + + /** + * Map to BIFF5-BIFF8 codes for bold + * + * @param boolean $bold + * @return int + */ + private static function _mapBold($bold) { + if ($bold) { + return 0x2BC; // 700 = Bold font weight + } + return 0x190; // 400 = Normal font weight + } + + /** + * Map of BIFF2-BIFF8 codes for underline styles + * @static array of int + * + */ + private static $_mapUnderline = array( PHPExcel_Style_Font::UNDERLINE_NONE => 0x00, + PHPExcel_Style_Font::UNDERLINE_SINGLE => 0x01, + PHPExcel_Style_Font::UNDERLINE_DOUBLE => 0x02, + PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING => 0x21, + PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING => 0x22, + ); + /** + * Map underline + * + * @param string + * @return int + */ + private static function _mapUnderline($underline) { + if (isset(self::$_mapUnderline[$underline])) + return self::$_mapUnderline[$underline]; + return 0x00; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Parser.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Parser.php new file mode 100755 index 0000000..443fefc --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Parser.php @@ -0,0 +1,1582 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +// Original file header of PEAR::Spreadsheet_Excel_Writer_Parser (used as the base for this class): +// ----------------------------------------------------------------------------------------- +// * Class for parsing Excel formulas +// * +// * License Information: +// * +// * Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets +// * Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com +// * +// * This library is free software; you can redistribute it and/or +// * modify it under the terms of the GNU Lesser General Public +// * License as published by the Free Software Foundation; either +// * version 2.1 of the License, or (at your option) any later version. +// * +// * This library is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// * Lesser General Public License for more details. +// * +// * You should have received a copy of the GNU Lesser General Public +// * License along with this library; if not, write to the Free Software +// * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// */ + + +/** + * PHPExcel_Writer_Excel5_Parser + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel5_Parser +{ + /** Constants */ + // Sheet title in unquoted form + // Invalid sheet title characters cannot occur in the sheet title: + // *:/\?[] + // Moreover, there are valid sheet title characters that cannot occur in unquoted form (there may be more?) + // +-% '^&<>=,;#()"{} + const REGEX_SHEET_TITLE_UNQUOTED = '[^\*\:\/\\\\\?\[\]\+\-\% \\\'\^\&\<\>\=\,\;\#\(\)\"\{\}]+'; + + // Sheet title in quoted form (without surrounding quotes) + // Invalid sheet title characters cannot occur in the sheet title: + // *:/\?[] (usual invalid sheet title characters) + // Single quote is represented as a pair '' + const REGEX_SHEET_TITLE_QUOTED = '(([^\*\:\/\\\\\?\[\]\\\'])+|(\\\'\\\')+)+'; + + /** + * The index of the character we are currently looking at + * @var integer + */ + public $_current_char; + + /** + * The token we are working on. + * @var string + */ + public $_current_token; + + /** + * The formula to parse + * @var string + */ + public $_formula; + + /** + * The character ahead of the current char + * @var string + */ + public $_lookahead; + + /** + * The parse tree to be generated + * @var string + */ + public $_parse_tree; + + /** + * Array of external sheets + * @var array + */ + public $_ext_sheets; + + /** + * Array of sheet references in the form of REF structures + * @var array + */ + public $_references; + + /** + * The class constructor + * + */ + public function __construct() + { + $this->_current_char = 0; + $this->_current_token = ''; // The token we are working on. + $this->_formula = ''; // The formula to parse. + $this->_lookahead = ''; // The character ahead of the current char. + $this->_parse_tree = ''; // The parse tree to be generated. + $this->_initializeHashes(); // Initialize the hashes: ptg's and function's ptg's + $this->_ext_sheets = array(); + $this->_references = array(); + } + + /** + * Initialize the ptg and function hashes. + * + * @access private + */ + function _initializeHashes() + { + // The Excel ptg indices + $this->ptg = array( + 'ptgExp' => 0x01, + 'ptgTbl' => 0x02, + 'ptgAdd' => 0x03, + 'ptgSub' => 0x04, + 'ptgMul' => 0x05, + 'ptgDiv' => 0x06, + 'ptgPower' => 0x07, + 'ptgConcat' => 0x08, + 'ptgLT' => 0x09, + 'ptgLE' => 0x0A, + 'ptgEQ' => 0x0B, + 'ptgGE' => 0x0C, + 'ptgGT' => 0x0D, + 'ptgNE' => 0x0E, + 'ptgIsect' => 0x0F, + 'ptgUnion' => 0x10, + 'ptgRange' => 0x11, + 'ptgUplus' => 0x12, + 'ptgUminus' => 0x13, + 'ptgPercent' => 0x14, + 'ptgParen' => 0x15, + 'ptgMissArg' => 0x16, + 'ptgStr' => 0x17, + 'ptgAttr' => 0x19, + 'ptgSheet' => 0x1A, + 'ptgEndSheet' => 0x1B, + 'ptgErr' => 0x1C, + 'ptgBool' => 0x1D, + 'ptgInt' => 0x1E, + 'ptgNum' => 0x1F, + 'ptgArray' => 0x20, + 'ptgFunc' => 0x21, + 'ptgFuncVar' => 0x22, + 'ptgName' => 0x23, + 'ptgRef' => 0x24, + 'ptgArea' => 0x25, + 'ptgMemArea' => 0x26, + 'ptgMemErr' => 0x27, + 'ptgMemNoMem' => 0x28, + 'ptgMemFunc' => 0x29, + 'ptgRefErr' => 0x2A, + 'ptgAreaErr' => 0x2B, + 'ptgRefN' => 0x2C, + 'ptgAreaN' => 0x2D, + 'ptgMemAreaN' => 0x2E, + 'ptgMemNoMemN' => 0x2F, + 'ptgNameX' => 0x39, + 'ptgRef3d' => 0x3A, + 'ptgArea3d' => 0x3B, + 'ptgRefErr3d' => 0x3C, + 'ptgAreaErr3d' => 0x3D, + 'ptgArrayV' => 0x40, + 'ptgFuncV' => 0x41, + 'ptgFuncVarV' => 0x42, + 'ptgNameV' => 0x43, + 'ptgRefV' => 0x44, + 'ptgAreaV' => 0x45, + 'ptgMemAreaV' => 0x46, + 'ptgMemErrV' => 0x47, + 'ptgMemNoMemV' => 0x48, + 'ptgMemFuncV' => 0x49, + 'ptgRefErrV' => 0x4A, + 'ptgAreaErrV' => 0x4B, + 'ptgRefNV' => 0x4C, + 'ptgAreaNV' => 0x4D, + 'ptgMemAreaNV' => 0x4E, + 'ptgMemNoMemN' => 0x4F, + 'ptgFuncCEV' => 0x58, + 'ptgNameXV' => 0x59, + 'ptgRef3dV' => 0x5A, + 'ptgArea3dV' => 0x5B, + 'ptgRefErr3dV' => 0x5C, + 'ptgAreaErr3d' => 0x5D, + 'ptgArrayA' => 0x60, + 'ptgFuncA' => 0x61, + 'ptgFuncVarA' => 0x62, + 'ptgNameA' => 0x63, + 'ptgRefA' => 0x64, + 'ptgAreaA' => 0x65, + 'ptgMemAreaA' => 0x66, + 'ptgMemErrA' => 0x67, + 'ptgMemNoMemA' => 0x68, + 'ptgMemFuncA' => 0x69, + 'ptgRefErrA' => 0x6A, + 'ptgAreaErrA' => 0x6B, + 'ptgRefNA' => 0x6C, + 'ptgAreaNA' => 0x6D, + 'ptgMemAreaNA' => 0x6E, + 'ptgMemNoMemN' => 0x6F, + 'ptgFuncCEA' => 0x78, + 'ptgNameXA' => 0x79, + 'ptgRef3dA' => 0x7A, + 'ptgArea3dA' => 0x7B, + 'ptgRefErr3dA' => 0x7C, + 'ptgAreaErr3d' => 0x7D + ); + + // Thanks to Michael Meeks and Gnumeric for the initial arg values. + // + // The following hash was generated by "function_locale.pl" in the distro. + // Refer to function_locale.pl for non-English function names. + // + // The array elements are as follow: + // ptg: The Excel function ptg code. + // args: The number of arguments that the function takes: + // >=0 is a fixed number of arguments. + // -1 is a variable number of arguments. + // class: The reference, value or array class of the function args. + // vol: The function is volatile. + // + $this->_functions = array( + // function ptg args class vol + 'COUNT' => array( 0, -1, 0, 0 ), + 'IF' => array( 1, -1, 1, 0 ), + 'ISNA' => array( 2, 1, 1, 0 ), + 'ISERROR' => array( 3, 1, 1, 0 ), + 'SUM' => array( 4, -1, 0, 0 ), + 'AVERAGE' => array( 5, -1, 0, 0 ), + 'MIN' => array( 6, -1, 0, 0 ), + 'MAX' => array( 7, -1, 0, 0 ), + 'ROW' => array( 8, -1, 0, 0 ), + 'COLUMN' => array( 9, -1, 0, 0 ), + 'NA' => array( 10, 0, 0, 0 ), + 'NPV' => array( 11, -1, 1, 0 ), + 'STDEV' => array( 12, -1, 0, 0 ), + 'DOLLAR' => array( 13, -1, 1, 0 ), + 'FIXED' => array( 14, -1, 1, 0 ), + 'SIN' => array( 15, 1, 1, 0 ), + 'COS' => array( 16, 1, 1, 0 ), + 'TAN' => array( 17, 1, 1, 0 ), + 'ATAN' => array( 18, 1, 1, 0 ), + 'PI' => array( 19, 0, 1, 0 ), + 'SQRT' => array( 20, 1, 1, 0 ), + 'EXP' => array( 21, 1, 1, 0 ), + 'LN' => array( 22, 1, 1, 0 ), + 'LOG10' => array( 23, 1, 1, 0 ), + 'ABS' => array( 24, 1, 1, 0 ), + 'INT' => array( 25, 1, 1, 0 ), + 'SIGN' => array( 26, 1, 1, 0 ), + 'ROUND' => array( 27, 2, 1, 0 ), + 'LOOKUP' => array( 28, -1, 0, 0 ), + 'INDEX' => array( 29, -1, 0, 1 ), + 'REPT' => array( 30, 2, 1, 0 ), + 'MID' => array( 31, 3, 1, 0 ), + 'LEN' => array( 32, 1, 1, 0 ), + 'VALUE' => array( 33, 1, 1, 0 ), + 'TRUE' => array( 34, 0, 1, 0 ), + 'FALSE' => array( 35, 0, 1, 0 ), + 'AND' => array( 36, -1, 0, 0 ), + 'OR' => array( 37, -1, 0, 0 ), + 'NOT' => array( 38, 1, 1, 0 ), + 'MOD' => array( 39, 2, 1, 0 ), + 'DCOUNT' => array( 40, 3, 0, 0 ), + 'DSUM' => array( 41, 3, 0, 0 ), + 'DAVERAGE' => array( 42, 3, 0, 0 ), + 'DMIN' => array( 43, 3, 0, 0 ), + 'DMAX' => array( 44, 3, 0, 0 ), + 'DSTDEV' => array( 45, 3, 0, 0 ), + 'VAR' => array( 46, -1, 0, 0 ), + 'DVAR' => array( 47, 3, 0, 0 ), + 'TEXT' => array( 48, 2, 1, 0 ), + 'LINEST' => array( 49, -1, 0, 0 ), + 'TREND' => array( 50, -1, 0, 0 ), + 'LOGEST' => array( 51, -1, 0, 0 ), + 'GROWTH' => array( 52, -1, 0, 0 ), + 'PV' => array( 56, -1, 1, 0 ), + 'FV' => array( 57, -1, 1, 0 ), + 'NPER' => array( 58, -1, 1, 0 ), + 'PMT' => array( 59, -1, 1, 0 ), + 'RATE' => array( 60, -1, 1, 0 ), + 'MIRR' => array( 61, 3, 0, 0 ), + 'IRR' => array( 62, -1, 0, 0 ), + 'RAND' => array( 63, 0, 1, 1 ), + 'MATCH' => array( 64, -1, 0, 0 ), + 'DATE' => array( 65, 3, 1, 0 ), + 'TIME' => array( 66, 3, 1, 0 ), + 'DAY' => array( 67, 1, 1, 0 ), + 'MONTH' => array( 68, 1, 1, 0 ), + 'YEAR' => array( 69, 1, 1, 0 ), + 'WEEKDAY' => array( 70, -1, 1, 0 ), + 'HOUR' => array( 71, 1, 1, 0 ), + 'MINUTE' => array( 72, 1, 1, 0 ), + 'SECOND' => array( 73, 1, 1, 0 ), + 'NOW' => array( 74, 0, 1, 1 ), + 'AREAS' => array( 75, 1, 0, 1 ), + 'ROWS' => array( 76, 1, 0, 1 ), + 'COLUMNS' => array( 77, 1, 0, 1 ), + 'OFFSET' => array( 78, -1, 0, 1 ), + 'SEARCH' => array( 82, -1, 1, 0 ), + 'TRANSPOSE' => array( 83, 1, 1, 0 ), + 'TYPE' => array( 86, 1, 1, 0 ), + 'ATAN2' => array( 97, 2, 1, 0 ), + 'ASIN' => array( 98, 1, 1, 0 ), + 'ACOS' => array( 99, 1, 1, 0 ), + 'CHOOSE' => array( 100, -1, 1, 0 ), + 'HLOOKUP' => array( 101, -1, 0, 0 ), + 'VLOOKUP' => array( 102, -1, 0, 0 ), + 'ISREF' => array( 105, 1, 0, 0 ), + 'LOG' => array( 109, -1, 1, 0 ), + 'CHAR' => array( 111, 1, 1, 0 ), + 'LOWER' => array( 112, 1, 1, 0 ), + 'UPPER' => array( 113, 1, 1, 0 ), + 'PROPER' => array( 114, 1, 1, 0 ), + 'LEFT' => array( 115, -1, 1, 0 ), + 'RIGHT' => array( 116, -1, 1, 0 ), + 'EXACT' => array( 117, 2, 1, 0 ), + 'TRIM' => array( 118, 1, 1, 0 ), + 'REPLACE' => array( 119, 4, 1, 0 ), + 'SUBSTITUTE' => array( 120, -1, 1, 0 ), + 'CODE' => array( 121, 1, 1, 0 ), + 'FIND' => array( 124, -1, 1, 0 ), + 'CELL' => array( 125, -1, 0, 1 ), + 'ISERR' => array( 126, 1, 1, 0 ), + 'ISTEXT' => array( 127, 1, 1, 0 ), + 'ISNUMBER' => array( 128, 1, 1, 0 ), + 'ISBLANK' => array( 129, 1, 1, 0 ), + 'T' => array( 130, 1, 0, 0 ), + 'N' => array( 131, 1, 0, 0 ), + 'DATEVALUE' => array( 140, 1, 1, 0 ), + 'TIMEVALUE' => array( 141, 1, 1, 0 ), + 'SLN' => array( 142, 3, 1, 0 ), + 'SYD' => array( 143, 4, 1, 0 ), + 'DDB' => array( 144, -1, 1, 0 ), + 'INDIRECT' => array( 148, -1, 1, 1 ), + 'CALL' => array( 150, -1, 1, 0 ), + 'CLEAN' => array( 162, 1, 1, 0 ), + 'MDETERM' => array( 163, 1, 2, 0 ), + 'MINVERSE' => array( 164, 1, 2, 0 ), + 'MMULT' => array( 165, 2, 2, 0 ), + 'IPMT' => array( 167, -1, 1, 0 ), + 'PPMT' => array( 168, -1, 1, 0 ), + 'COUNTA' => array( 169, -1, 0, 0 ), + 'PRODUCT' => array( 183, -1, 0, 0 ), + 'FACT' => array( 184, 1, 1, 0 ), + 'DPRODUCT' => array( 189, 3, 0, 0 ), + 'ISNONTEXT' => array( 190, 1, 1, 0 ), + 'STDEVP' => array( 193, -1, 0, 0 ), + 'VARP' => array( 194, -1, 0, 0 ), + 'DSTDEVP' => array( 195, 3, 0, 0 ), + 'DVARP' => array( 196, 3, 0, 0 ), + 'TRUNC' => array( 197, -1, 1, 0 ), + 'ISLOGICAL' => array( 198, 1, 1, 0 ), + 'DCOUNTA' => array( 199, 3, 0, 0 ), + 'USDOLLAR' => array( 204, -1, 1, 0 ), + 'FINDB' => array( 205, -1, 1, 0 ), + 'SEARCHB' => array( 206, -1, 1, 0 ), + 'REPLACEB' => array( 207, 4, 1, 0 ), + 'LEFTB' => array( 208, -1, 1, 0 ), + 'RIGHTB' => array( 209, -1, 1, 0 ), + 'MIDB' => array( 210, 3, 1, 0 ), + 'LENB' => array( 211, 1, 1, 0 ), + 'ROUNDUP' => array( 212, 2, 1, 0 ), + 'ROUNDDOWN' => array( 213, 2, 1, 0 ), + 'ASC' => array( 214, 1, 1, 0 ), + 'DBCS' => array( 215, 1, 1, 0 ), + 'RANK' => array( 216, -1, 0, 0 ), + 'ADDRESS' => array( 219, -1, 1, 0 ), + 'DAYS360' => array( 220, -1, 1, 0 ), + 'TODAY' => array( 221, 0, 1, 1 ), + 'VDB' => array( 222, -1, 1, 0 ), + 'MEDIAN' => array( 227, -1, 0, 0 ), + 'SUMPRODUCT' => array( 228, -1, 2, 0 ), + 'SINH' => array( 229, 1, 1, 0 ), + 'COSH' => array( 230, 1, 1, 0 ), + 'TANH' => array( 231, 1, 1, 0 ), + 'ASINH' => array( 232, 1, 1, 0 ), + 'ACOSH' => array( 233, 1, 1, 0 ), + 'ATANH' => array( 234, 1, 1, 0 ), + 'DGET' => array( 235, 3, 0, 0 ), + 'INFO' => array( 244, 1, 1, 1 ), + 'DB' => array( 247, -1, 1, 0 ), + 'FREQUENCY' => array( 252, 2, 0, 0 ), + 'ERROR.TYPE' => array( 261, 1, 1, 0 ), + 'REGISTER.ID' => array( 267, -1, 1, 0 ), + 'AVEDEV' => array( 269, -1, 0, 0 ), + 'BETADIST' => array( 270, -1, 1, 0 ), + 'GAMMALN' => array( 271, 1, 1, 0 ), + 'BETAINV' => array( 272, -1, 1, 0 ), + 'BINOMDIST' => array( 273, 4, 1, 0 ), + 'CHIDIST' => array( 274, 2, 1, 0 ), + 'CHIINV' => array( 275, 2, 1, 0 ), + 'COMBIN' => array( 276, 2, 1, 0 ), + 'CONFIDENCE' => array( 277, 3, 1, 0 ), + 'CRITBINOM' => array( 278, 3, 1, 0 ), + 'EVEN' => array( 279, 1, 1, 0 ), + 'EXPONDIST' => array( 280, 3, 1, 0 ), + 'FDIST' => array( 281, 3, 1, 0 ), + 'FINV' => array( 282, 3, 1, 0 ), + 'FISHER' => array( 283, 1, 1, 0 ), + 'FISHERINV' => array( 284, 1, 1, 0 ), + 'FLOOR' => array( 285, 2, 1, 0 ), + 'GAMMADIST' => array( 286, 4, 1, 0 ), + 'GAMMAINV' => array( 287, 3, 1, 0 ), + 'CEILING' => array( 288, 2, 1, 0 ), + 'HYPGEOMDIST' => array( 289, 4, 1, 0 ), + 'LOGNORMDIST' => array( 290, 3, 1, 0 ), + 'LOGINV' => array( 291, 3, 1, 0 ), + 'NEGBINOMDIST' => array( 292, 3, 1, 0 ), + 'NORMDIST' => array( 293, 4, 1, 0 ), + 'NORMSDIST' => array( 294, 1, 1, 0 ), + 'NORMINV' => array( 295, 3, 1, 0 ), + 'NORMSINV' => array( 296, 1, 1, 0 ), + 'STANDARDIZE' => array( 297, 3, 1, 0 ), + 'ODD' => array( 298, 1, 1, 0 ), + 'PERMUT' => array( 299, 2, 1, 0 ), + 'POISSON' => array( 300, 3, 1, 0 ), + 'TDIST' => array( 301, 3, 1, 0 ), + 'WEIBULL' => array( 302, 4, 1, 0 ), + 'SUMXMY2' => array( 303, 2, 2, 0 ), + 'SUMX2MY2' => array( 304, 2, 2, 0 ), + 'SUMX2PY2' => array( 305, 2, 2, 0 ), + 'CHITEST' => array( 306, 2, 2, 0 ), + 'CORREL' => array( 307, 2, 2, 0 ), + 'COVAR' => array( 308, 2, 2, 0 ), + 'FORECAST' => array( 309, 3, 2, 0 ), + 'FTEST' => array( 310, 2, 2, 0 ), + 'INTERCEPT' => array( 311, 2, 2, 0 ), + 'PEARSON' => array( 312, 2, 2, 0 ), + 'RSQ' => array( 313, 2, 2, 0 ), + 'STEYX' => array( 314, 2, 2, 0 ), + 'SLOPE' => array( 315, 2, 2, 0 ), + 'TTEST' => array( 316, 4, 2, 0 ), + 'PROB' => array( 317, -1, 2, 0 ), + 'DEVSQ' => array( 318, -1, 0, 0 ), + 'GEOMEAN' => array( 319, -1, 0, 0 ), + 'HARMEAN' => array( 320, -1, 0, 0 ), + 'SUMSQ' => array( 321, -1, 0, 0 ), + 'KURT' => array( 322, -1, 0, 0 ), + 'SKEW' => array( 323, -1, 0, 0 ), + 'ZTEST' => array( 324, -1, 0, 0 ), + 'LARGE' => array( 325, 2, 0, 0 ), + 'SMALL' => array( 326, 2, 0, 0 ), + 'QUARTILE' => array( 327, 2, 0, 0 ), + 'PERCENTILE' => array( 328, 2, 0, 0 ), + 'PERCENTRANK' => array( 329, -1, 0, 0 ), + 'MODE' => array( 330, -1, 2, 0 ), + 'TRIMMEAN' => array( 331, 2, 0, 0 ), + 'TINV' => array( 332, 2, 1, 0 ), + 'CONCATENATE' => array( 336, -1, 1, 0 ), + 'POWER' => array( 337, 2, 1, 0 ), + 'RADIANS' => array( 342, 1, 1, 0 ), + 'DEGREES' => array( 343, 1, 1, 0 ), + 'SUBTOTAL' => array( 344, -1, 0, 0 ), + 'SUMIF' => array( 345, -1, 0, 0 ), + 'COUNTIF' => array( 346, 2, 0, 0 ), + 'COUNTBLANK' => array( 347, 1, 0, 0 ), + 'ISPMT' => array( 350, 4, 1, 0 ), + 'DATEDIF' => array( 351, 3, 1, 0 ), + 'DATESTRING' => array( 352, 1, 1, 0 ), + 'NUMBERSTRING' => array( 353, 2, 1, 0 ), + 'ROMAN' => array( 354, -1, 1, 0 ), + 'GETPIVOTDATA' => array( 358, -1, 0, 0 ), + 'HYPERLINK' => array( 359, -1, 1, 0 ), + 'PHONETIC' => array( 360, 1, 0, 0 ), + 'AVERAGEA' => array( 361, -1, 0, 0 ), + 'MAXA' => array( 362, -1, 0, 0 ), + 'MINA' => array( 363, -1, 0, 0 ), + 'STDEVPA' => array( 364, -1, 0, 0 ), + 'VARPA' => array( 365, -1, 0, 0 ), + 'STDEVA' => array( 366, -1, 0, 0 ), + 'VARA' => array( 367, -1, 0, 0 ), + 'BAHTTEXT' => array( 368, 1, 0, 0 ), + ); + } + + /** + * Convert a token to the proper ptg value. + * + * @access private + * @param mixed $token The token to convert. + * @return mixed the converted token on success + */ + function _convert($token) + { + if (preg_match("/\"([^\"]|\"\"){0,255}\"/", $token)) { + return $this->_convertString($token); + + } elseif (is_numeric($token)) { + return $this->_convertNumber($token); + + // match references like A1 or $A$1 + } elseif (preg_match('/^\$?([A-Ia-i]?[A-Za-z])\$?(\d+)$/',$token)) { + return $this->_convertRef2d($token); + + // match external references like Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1 + } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { + return $this->_convertRef3d($token); + + // match external references like 'Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1 + } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?(\d+)$/u",$token)) { + return $this->_convertRef3d($token); + + // match ranges like A1:B2 or $A$1:$B$2 + } elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)\:(\$)?[A-Ia-i]?[A-Za-z](\$)?(\d+)$/', $token)) { + return $this->_convertRange2d($token); + + // match external ranges like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 + } elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { + return $this->_convertRange3d($token); + + // match external ranges like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 + } elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)\:\\$?([A-Ia-i]?[A-Za-z])?\\$?(\d+)$/u",$token)) { + return $this->_convertRange3d($token); + + // operators (including parentheses) + } elseif (isset($this->ptg[$token])) { + return pack("C", $this->ptg[$token]); + + // match error codes + } elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $token) or $token == '#N/A') { + return $this->_convertError($token); + + // commented so argument number can be processed correctly. See toReversePolish(). + /*elseif (preg_match("/[A-Z0-9\xc0-\xdc\.]+/",$token)) + { + return($this->_convertFunction($token,$this->_func_args)); + }*/ + + // if it's an argument, ignore the token (the argument remains) + } elseif ($token == 'arg') { + return ''; + } + + // TODO: use real error codes + throw new PHPExcel_Writer_Exception("Unknown token $token"); + } + + /** + * Convert a number token to ptgInt or ptgNum + * + * @access private + * @param mixed $num an integer or double for conversion to its ptg value + */ + function _convertNumber($num) + { + // Integer in the range 0..2**16-1 + if ((preg_match("/^\d+$/", $num)) and ($num <= 65535)) { + return pack("Cv", $this->ptg['ptgInt'], $num); + } else { // A float + if (PHPExcel_Writer_Excel5_BIFFwriter::getByteOrder()) { // if it's Big Endian + $num = strrev($num); + } + return pack("Cd", $this->ptg['ptgNum'], $num); + } + } + + /** + * Convert a string token to ptgStr + * + * @access private + * @param string $string A string for conversion to its ptg value. + * @return mixed the converted token on success + */ + function _convertString($string) + { + // chop away beggining and ending quotes + $string = substr($string, 1, strlen($string) - 2); + if (strlen($string) > 255) { + throw new PHPExcel_Writer_Exception("String is too long"); + } + + return pack('C', $this->ptg['ptgStr']) . PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($string); + } + + /** + * Convert a function to a ptgFunc or ptgFuncVarV depending on the number of + * args that it takes. + * + * @access private + * @param string $token The name of the function for convertion to ptg value. + * @param integer $num_args The number of arguments the function receives. + * @return string The packed ptg for the function + */ + function _convertFunction($token, $num_args) + { + $args = $this->_functions[$token][1]; +// $volatile = $this->_functions[$token][3]; + + // Fixed number of args eg. TIME($i,$j,$k). + if ($args >= 0) { + return pack("Cv", $this->ptg['ptgFuncV'], $this->_functions[$token][0]); + } + // Variable number of args eg. SUM($i,$j,$k, ..). + if ($args == -1) { + return pack("CCv", $this->ptg['ptgFuncVarV'], $num_args, $this->_functions[$token][0]); + } + } + + /** + * Convert an Excel range such as A1:D4 to a ptgRefV. + * + * @access private + * @param string $range An Excel range in the A1:A2 + * @param int $class + */ + function _convertRange2d($range, $class=0) + { + + // TODO: possible class value 0,1,2 check Formula.pm + // Split the range into 2 cell refs + if (preg_match('/^(\$)?([A-Ia-i]?[A-Za-z])(\$)?(\d+)\:(\$)?([A-Ia-i]?[A-Za-z])(\$)?(\d+)$/', $range)) { + list($cell1, $cell2) = explode(':', $range); + } else { + // TODO: use real error codes + throw new PHPExcel_Writer_Exception("Unknown range separator"); + } + + // Convert the cell references + list($row1, $col1) = $this->_cellToPackedRowcol($cell1); + list($row2, $col2) = $this->_cellToPackedRowcol($cell2); + + // The ptg value depends on the class of the ptg. + if ($class == 0) { + $ptgArea = pack("C", $this->ptg['ptgArea']); + } elseif ($class == 1) { + $ptgArea = pack("C", $this->ptg['ptgAreaV']); + } elseif ($class == 2) { + $ptgArea = pack("C", $this->ptg['ptgAreaA']); + } else { + // TODO: use real error codes + throw new PHPExcel_Writer_Exception("Unknown class $class"); + } + return $ptgArea . $row1 . $row2 . $col1. $col2; + } + + /** + * Convert an Excel 3d range such as "Sheet1!A1:D4" or "Sheet1:Sheet2!A1:D4" to + * a ptgArea3d. + * + * @access private + * @param string $token An Excel range in the Sheet1!A1:A2 format. + * @return mixed The packed ptgArea3d token on success. + */ + function _convertRange3d($token) + { +// $class = 0; // formulas like Sheet1!$A$1:$A$2 in list type data validation need this class (0x3B) + + // Split the ref at the ! symbol + list($ext_ref, $range) = explode('!', $token); + + // Convert the external reference part (different for BIFF8) + $ext_ref = $this->_getRefIndex($ext_ref); + + // Split the range into 2 cell refs + list($cell1, $cell2) = explode(':', $range); + + // Convert the cell references + if (preg_match("/^(\\$)?[A-Ia-i]?[A-Za-z](\\$)?(\d+)$/", $cell1)) { + list($row1, $col1) = $this->_cellToPackedRowcol($cell1); + list($row2, $col2) = $this->_cellToPackedRowcol($cell2); + } else { // It's a rows range (like 26:27) + list($row1, $col1, $row2, $col2) = $this->_rangeToPackedRange($cell1.':'.$cell2); + } + + // The ptg value depends on the class of the ptg. +// if ($class == 0) { + $ptgArea = pack("C", $this->ptg['ptgArea3d']); +// } elseif ($class == 1) { +// $ptgArea = pack("C", $this->ptg['ptgArea3dV']); +// } elseif ($class == 2) { +// $ptgArea = pack("C", $this->ptg['ptgArea3dA']); +// } else { +// throw new PHPExcel_Writer_Exception("Unknown class $class"); +// } + + return $ptgArea . $ext_ref . $row1 . $row2 . $col1. $col2; + } + + /** + * Convert an Excel reference such as A1, $B2, C$3 or $D$4 to a ptgRefV. + * + * @access private + * @param string $cell An Excel cell reference + * @return string The cell in packed() format with the corresponding ptg + */ + function _convertRef2d($cell) + { +// $class = 2; // as far as I know, this is magick. + + // Convert the cell reference + $cell_array = $this->_cellToPackedRowcol($cell); + list($row, $col) = $cell_array; + + // The ptg value depends on the class of the ptg. +// if ($class == 0) { +// $ptgRef = pack("C", $this->ptg['ptgRef']); +// } elseif ($class == 1) { +// $ptgRef = pack("C", $this->ptg['ptgRefV']); +// } elseif ($class == 2) { + $ptgRef = pack("C", $this->ptg['ptgRefA']); +// } else { +// // TODO: use real error codes +// throw new PHPExcel_Writer_Exception("Unknown class $class"); +// } + return $ptgRef.$row.$col; + } + + /** + * Convert an Excel 3d reference such as "Sheet1!A1" or "Sheet1:Sheet2!A1" to a + * ptgRef3d. + * + * @access private + * @param string $cell An Excel cell reference + * @return mixed The packed ptgRef3d token on success. + */ + function _convertRef3d($cell) + { +// $class = 2; // as far as I know, this is magick. + + // Split the ref at the ! symbol + list($ext_ref, $cell) = explode('!', $cell); + + // Convert the external reference part (different for BIFF8) + $ext_ref = $this->_getRefIndex($ext_ref); + + // Convert the cell reference part + list($row, $col) = $this->_cellToPackedRowcol($cell); + + // The ptg value depends on the class of the ptg. +// if ($class == 0) { +// $ptgRef = pack("C", $this->ptg['ptgRef3d']); +// } elseif ($class == 1) { +// $ptgRef = pack("C", $this->ptg['ptgRef3dV']); +// } elseif ($class == 2) { + $ptgRef = pack("C", $this->ptg['ptgRef3dA']); +// } else { +// throw new PHPExcel_Writer_Exception("Unknown class $class"); +// } + + return $ptgRef . $ext_ref. $row . $col; + } + + /** + * Convert an error code to a ptgErr + * + * @access private + * @param string $errorCode The error code for conversion to its ptg value + * @return string The error code ptgErr + */ + function _convertError($errorCode) + { + switch ($errorCode) { + case '#NULL!': return pack("C", 0x00); + case '#DIV/0!': return pack("C", 0x07); + case '#VALUE!': return pack("C", 0x0F); + case '#REF!': return pack("C", 0x17); + case '#NAME?': return pack("C", 0x1D); + case '#NUM!': return pack("C", 0x24); + case '#N/A': return pack("C", 0x2A); + } + return pack("C", 0xFF); + } + + /** + * Convert the sheet name part of an external reference, for example "Sheet1" or + * "Sheet1:Sheet2", to a packed structure. + * + * @access private + * @param string $ext_ref The name of the external reference + * @return string The reference index in packed() format + */ + function _packExtRef($ext_ref) + { + $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any. + $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any. + + // Check if there is a sheet range eg., Sheet1:Sheet2. + if (preg_match("/:/", $ext_ref)) { + list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); + + $sheet1 = $this->_getSheetIndex($sheet_name1); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula"); + } + $sheet2 = $this->_getSheetIndex($sheet_name2); + if ($sheet2 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula"); + } + + // Reverse max and min sheet numbers if necessary + if ($sheet1 > $sheet2) { + list($sheet1, $sheet2) = array($sheet2, $sheet1); + } + } else { // Single sheet name only. + $sheet1 = $this->_getSheetIndex($ext_ref); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula"); + } + $sheet2 = $sheet1; + } + + // References are stored relative to 0xFFFF. + $offset = -1 - $sheet1; + + return pack('vdvv', $offset, 0x00, $sheet1, $sheet2); + } + + /** + * Look up the REF index that corresponds to an external sheet name + * (or range). If it doesn't exist yet add it to the workbook's references + * array. It assumes all sheet names given must exist. + * + * @access private + * @param string $ext_ref The name of the external reference + * @return mixed The reference index in packed() format on success + */ + function _getRefIndex($ext_ref) + { + $ext_ref = preg_replace("/^'/", '', $ext_ref); // Remove leading ' if any. + $ext_ref = preg_replace("/'$/", '', $ext_ref); // Remove trailing ' if any. + $ext_ref = str_replace('\'\'', '\'', $ext_ref); // Replace escaped '' with ' + + // Check if there is a sheet range eg., Sheet1:Sheet2. + if (preg_match("/:/", $ext_ref)) { + list($sheet_name1, $sheet_name2) = explode(':', $ext_ref); + + $sheet1 = $this->_getSheetIndex($sheet_name1); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name1 in formula"); + } + $sheet2 = $this->_getSheetIndex($sheet_name2); + if ($sheet2 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $sheet_name2 in formula"); + } + + // Reverse max and min sheet numbers if necessary + if ($sheet1 > $sheet2) { + list($sheet1, $sheet2) = array($sheet2, $sheet1); + } + } else { // Single sheet name only. + $sheet1 = $this->_getSheetIndex($ext_ref); + if ($sheet1 == -1) { + throw new PHPExcel_Writer_Exception("Unknown sheet name $ext_ref in formula"); + } + $sheet2 = $sheet1; + } + + // assume all references belong to this document + $supbook_index = 0x00; + $ref = pack('vvv', $supbook_index, $sheet1, $sheet2); + $total_references = count($this->_references); + $index = -1; + for ($i = 0; $i < $total_references; ++$i) { + if ($ref == $this->_references[$i]) { + $index = $i; + break; + } + } + // if REF was not found add it to references array + if ($index == -1) { + $this->_references[$total_references] = $ref; + $index = $total_references; + } + + return pack('v', $index); + } + + /** + * Look up the index that corresponds to an external sheet name. The hash of + * sheet names is updated by the addworksheet() method of the + * PHPExcel_Writer_Excel5_Workbook class. + * + * @access private + * @param string $sheet_name Sheet name + * @return integer The sheet index, -1 if the sheet was not found + */ + function _getSheetIndex($sheet_name) + { + if (!isset($this->_ext_sheets[$sheet_name])) { + return -1; + } else { + return $this->_ext_sheets[$sheet_name]; + } + } + + /** + * This method is used to update the array of sheet names. It is + * called by the addWorksheet() method of the + * PHPExcel_Writer_Excel5_Workbook class. + * + * @access public + * @see PHPExcel_Writer_Excel5_Workbook::addWorksheet() + * @param string $name The name of the worksheet being added + * @param integer $index The index of the worksheet being added + */ + function setExtSheet($name, $index) + { + $this->_ext_sheets[$name] = $index; + } + + /** + * pack() row and column into the required 3 or 4 byte format. + * + * @access private + * @param string $cell The Excel cell reference to be packed + * @return array Array containing the row and column in packed() format + */ + function _cellToPackedRowcol($cell) + { + $cell = strtoupper($cell); + list($row, $col, $row_rel, $col_rel) = $this->_cellToRowcol($cell); + if ($col >= 256) { + throw new PHPExcel_Writer_Exception("Column in: $cell greater than 255"); + } + if ($row >= 65536) { + throw new PHPExcel_Writer_Exception("Row in: $cell greater than 65536 "); + } + + // Set the high bits to indicate if row or col are relative. + $col |= $col_rel << 14; + $col |= $row_rel << 15; + $col = pack('v', $col); + + $row = pack('v', $row); + + return array($row, $col); + } + + /** + * pack() row range into the required 3 or 4 byte format. + * Just using maximum col/rows, which is probably not the correct solution + * + * @access private + * @param string $range The Excel range to be packed + * @return array Array containing (row1,col1,row2,col2) in packed() format + */ + function _rangeToPackedRange($range) + { + preg_match('/(\$)?(\d+)\:(\$)?(\d+)/', $range, $match); + // return absolute rows if there is a $ in the ref + $row1_rel = empty($match[1]) ? 1 : 0; + $row1 = $match[2]; + $row2_rel = empty($match[3]) ? 1 : 0; + $row2 = $match[4]; + // Convert 1-index to zero-index + --$row1; + --$row2; + // Trick poor inocent Excel + $col1 = 0; + $col2 = 65535; // FIXME: maximum possible value for Excel 5 (change this!!!) + + // FIXME: this changes for BIFF8 + if (($row1 >= 65536) or ($row2 >= 65536)) { + throw new PHPExcel_Writer_Exception("Row in: $range greater than 65536 "); + } + + // Set the high bits to indicate if rows are relative. + $col1 |= $row1_rel << 15; + $col2 |= $row2_rel << 15; + $col1 = pack('v', $col1); + $col2 = pack('v', $col2); + + $row1 = pack('v', $row1); + $row2 = pack('v', $row2); + + return array($row1, $col1, $row2, $col2); + } + + /** + * Convert an Excel cell reference such as A1 or $B2 or C$3 or $D$4 to a zero + * indexed row and column number. Also returns two (0,1) values to indicate + * whether the row or column are relative references. + * + * @access private + * @param string $cell The Excel cell reference in A1 format. + * @return array + */ + function _cellToRowcol($cell) + { + preg_match('/(\$)?([A-I]?[A-Z])(\$)?(\d+)/',$cell,$match); + // return absolute column if there is a $ in the ref + $col_rel = empty($match[1]) ? 1 : 0; + $col_ref = $match[2]; + $row_rel = empty($match[3]) ? 1 : 0; + $row = $match[4]; + + // Convert base26 column string to a number. + $expn = strlen($col_ref) - 1; + $col = 0; + $col_ref_length = strlen($col_ref); + for ($i = 0; $i < $col_ref_length; ++$i) { + $col += (ord($col_ref{$i}) - 64) * pow(26, $expn); + --$expn; + } + + // Convert 1-index to zero-index + --$row; + --$col; + + return array($row, $col, $row_rel, $col_rel); + } + + /** + * Advance to the next valid token. + * + * @access private + */ + function _advance() + { + $i = $this->_current_char; + $formula_length = strlen($this->_formula); + // eat up white spaces + if ($i < $formula_length) { + while ($this->_formula{$i} == " ") { + ++$i; + } + + if ($i < ($formula_length - 1)) { + $this->_lookahead = $this->_formula{$i+1}; + } + $token = ''; + } + + while ($i < $formula_length) { + $token .= $this->_formula{$i}; + + if ($i < ($formula_length - 1)) { + $this->_lookahead = $this->_formula{$i+1}; + } else { + $this->_lookahead = ''; + } + + if ($this->_match($token) != '') { + //if ($i < strlen($this->_formula) - 1) { + // $this->_lookahead = $this->_formula{$i+1}; + //} + $this->_current_char = $i + 1; + $this->_current_token = $token; + return 1; + } + + if ($i < ($formula_length - 2)) { + $this->_lookahead = $this->_formula{$i+2}; + } else { // if we run out of characters _lookahead becomes empty + $this->_lookahead = ''; + } + ++$i; + } + //die("Lexical error ".$this->_current_char); + } + + /** + * Checks if it's a valid token. + * + * @access private + * @param mixed $token The token to check. + * @return mixed The checked token or false on failure + */ + function _match($token) + { + switch($token) { + case "+": + case "-": + case "*": + case "/": + case "(": + case ")": + case ",": + case ";": + case ">=": + case "<=": + case "=": + case "<>": + case "^": + case "&": + case "%": + return $token; + break; + case ">": + if ($this->_lookahead == '=') { // it's a GE token + break; + } + return $token; + break; + case "<": + // it's a LE or a NE token + if (($this->_lookahead == '=') or ($this->_lookahead == '>')) { + break; + } + return $token; + break; + default: + // if it's a reference A1 or $A$1 or $A1 or A$1 + if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$token) and + !preg_match("/[0-9]/",$this->_lookahead) and + ($this->_lookahead != ':') and ($this->_lookahead != '.') and + ($this->_lookahead != '!')) + { + return $token; + } + // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead) and + ($this->_lookahead != ':') and ($this->_lookahead != '.')) + { + return $token; + } + // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead) and + ($this->_lookahead != ':') and ($this->_lookahead != '.')) + { + return $token; + } + // if it's a range A1:A2 or $A$1:$A$2 + elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/', $token) and + !preg_match("/[0-9]/",$this->_lookahead)) + { + return $token; + } + // If it's an external range like Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2 + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead)) + { + return $token; + } + // If it's an external range like 'Sheet1'!A1:B2 or 'Sheet1:Sheet2'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1:Sheet2'!$A$1:$B$2 + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$token) and + !preg_match("/[0-9]/",$this->_lookahead)) + { + return $token; + } + // If it's a number (check that it's not a sheet name or range) + elseif (is_numeric($token) and + (!is_numeric($token.$this->_lookahead) or ($this->_lookahead == '')) and + ($this->_lookahead != '!') and ($this->_lookahead != ':')) + { + return $token; + } + // If it's a string (of maximum 255 characters) + elseif (preg_match("/\"([^\"]|\"\"){0,255}\"/",$token) and $this->_lookahead != '"' and (substr_count($token, '"')%2 == 0)) + { + return $token; + } + // If it's an error code + elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $token) or $token == '#N/A') + { + return $token; + } + // if it's a function call + elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$token) and ($this->_lookahead == "(")) + { + return $token; + } + // It's an argument of some description (e.g. a named range), + // precise nature yet to be determined + elseif(substr($token,-1) == ')') { + return $token; + } + return ''; + } + } + + /** + * The parsing method. It parses a formula. + * + * @access public + * @param string $formula The formula to parse, without the initial equal + * sign (=). + * @return mixed true on success + */ + function parse($formula) + { + $this->_current_char = 0; + $this->_formula = $formula; + $this->_lookahead = isset($formula{1}) ? $formula{1} : ''; + $this->_advance(); + $this->_parse_tree = $this->_condition(); + return true; + } + + /** + * It parses a condition. It assumes the following rule: + * Cond -> Expr [(">" | "<") Expr] + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _condition() + { + $result = $this->_expression(); + if ($this->_current_token == "<") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgLT', $result, $result2); + } elseif ($this->_current_token == ">") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgGT', $result, $result2); + } elseif ($this->_current_token == "<=") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgLE', $result, $result2); + } elseif ($this->_current_token == ">=") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgGE', $result, $result2); + } elseif ($this->_current_token == "=") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgEQ', $result, $result2); + } elseif ($this->_current_token == "<>") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgNE', $result, $result2); + } elseif ($this->_current_token == "&") { + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgConcat', $result, $result2); + } + return $result; + } + + /** + * It parses a expression. It assumes the following rule: + * Expr -> Term [("+" | "-") Term] + * -> "string" + * -> "-" Term : Negative value + * -> "+" Term : Positive value + * -> Error code + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _expression() + { + // If it's a string return a string node + if (preg_match("/\"([^\"]|\"\"){0,255}\"/", $this->_current_token)) { + $tmp = str_replace('""', '"', $this->_current_token); + if (($tmp == '"') || ($tmp == '')) $tmp = '""'; // Trap for "" that has been used for an empty string + $result = $this->_createTree($tmp, '', ''); + $this->_advance(); + return $result; + // If it's an error code + } elseif (preg_match("/^#[A-Z0\/]{3,5}[!?]{1}$/", $this->_current_token) or $this->_current_token == '#N/A'){ + $result = $this->_createTree($this->_current_token, 'ptgErr', ''); + $this->_advance(); + return $result; + // If it's a negative value + } elseif ($this->_current_token == "-") { + // catch "-" Term + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgUminus', $result2, ''); + return $result; + // If it's a positive value + } elseif ($this->_current_token == "+") { + // catch "+" Term + $this->_advance(); + $result2 = $this->_expression(); + $result = $this->_createTree('ptgUplus', $result2, ''); + return $result; + } + $result = $this->_term(); + while (($this->_current_token == "+") or + ($this->_current_token == "-") or + ($this->_current_token == "^")) { + /**/ + if ($this->_current_token == "+") { + $this->_advance(); + $result2 = $this->_term(); + $result = $this->_createTree('ptgAdd', $result, $result2); + } elseif ($this->_current_token == "-") { + $this->_advance(); + $result2 = $this->_term(); + $result = $this->_createTree('ptgSub', $result, $result2); + } else { + $this->_advance(); + $result2 = $this->_term(); + $result = $this->_createTree('ptgPower', $result, $result2); + } + } + return $result; + } + + /** + * This function just introduces a ptgParen element in the tree, so that Excel + * doesn't get confused when working with a parenthesized formula afterwards. + * + * @access private + * @see _fact() + * @return array The parsed ptg'd tree + */ + function _parenthesizedExpression() + { + $result = $this->_createTree('ptgParen', $this->_expression(), ''); + return $result; + } + + /** + * It parses a term. It assumes the following rule: + * Term -> Fact [("*" | "/") Fact] + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _term() + { + $result = $this->_fact(); + while (($this->_current_token == "*") or + ($this->_current_token == "/")) { + /**/ + if ($this->_current_token == "*") { + $this->_advance(); + $result2 = $this->_fact(); + $result = $this->_createTree('ptgMul', $result, $result2); + } else { + $this->_advance(); + $result2 = $this->_fact(); + $result = $this->_createTree('ptgDiv', $result, $result2); + } + } + return $result; + } + + /** + * It parses a factor. It assumes the following rule: + * Fact -> ( Expr ) + * | CellRef + * | CellRange + * | Number + * | Function + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _fact() + { + if ($this->_current_token == "(") { + $this->_advance(); // eat the "(" + $result = $this->_parenthesizedExpression(); + if ($this->_current_token != ")") { + throw new PHPExcel_Writer_Exception("')' token expected."); + } + $this->_advance(); // eat the ")" + return $result; + } + // if it's a reference + if (preg_match('/^\$?[A-Ia-i]?[A-Za-z]\$?[0-9]+$/',$this->_current_token)) + { + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external reference (Sheet1!A1 or Sheet1:Sheet2!A1 or Sheet1!$A$1 or Sheet1:Sheet2!$A$1) + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) + { + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external reference ('Sheet1'!A1 or 'Sheet1:Sheet2'!A1 or 'Sheet1'!$A$1 or 'Sheet1:Sheet2'!$A$1) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?[A-Ia-i]?[A-Za-z]\\$?[0-9]+$/u",$this->_current_token)) + { + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // if it's a range A1:B2 or $A$1:$B$2 + elseif (preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+:(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token) or + preg_match('/^(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+\.\.(\$)?[A-Ia-i]?[A-Za-z](\$)?[0-9]+$/',$this->_current_token)) + { + // must be an error? + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external range (Sheet1!A1:B2 or Sheet1:Sheet2!A1:B2 or Sheet1!$A$1:$B$2 or Sheet1:Sheet2!$A$1:$B$2) + elseif (preg_match("/^" . self::REGEX_SHEET_TITLE_UNQUOTED . "(\:" . self::REGEX_SHEET_TITLE_UNQUOTED . ")?\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) + { + // must be an error? + //$result = $this->_current_token; + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's an external range ('Sheet1'!A1:B2 or 'Sheet1'!A1:B2 or 'Sheet1'!$A$1:$B$2 or 'Sheet1'!$A$1:$B$2) + elseif (preg_match("/^'" . self::REGEX_SHEET_TITLE_QUOTED . "(\:" . self::REGEX_SHEET_TITLE_QUOTED . ")?'\!\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+:\\$?([A-Ia-i]?[A-Za-z])?\\$?[0-9]+$/u",$this->_current_token)) + { + // must be an error? + //$result = $this->_current_token; + $result = $this->_createTree($this->_current_token, '', ''); + $this->_advance(); + return $result; + } + // If it's a number or a percent + elseif (is_numeric($this->_current_token)) + { + if($this->_lookahead == '%'){ + $result = $this->_createTree('ptgPercent', $this->_current_token, ''); + } else { + $result = $this->_createTree($this->_current_token, '', ''); + } + $this->_advance(); + return $result; + } + // if it's a function call + elseif (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/i",$this->_current_token)) + { + $result = $this->_func(); + return $result; + } + throw new PHPExcel_Writer_Exception("Syntax error: ".$this->_current_token. + ", lookahead: ".$this->_lookahead. + ", current char: ".$this->_current_char); + } + + /** + * It parses a function call. It assumes the following rule: + * Func -> ( Expr [,Expr]* ) + * + * @access private + * @return mixed The parsed ptg'd tree on success + */ + function _func() + { + $num_args = 0; // number of arguments received + $function = strtoupper($this->_current_token); + $result = ''; // initialize result + $this->_advance(); + $this->_advance(); // eat the "(" + while ($this->_current_token != ')') { + /**/ + if ($num_args > 0) { + if ($this->_current_token == "," or + $this->_current_token == ";") + { + $this->_advance(); // eat the "," or ";" + } else { + throw new PHPExcel_Writer_Exception("Syntax error: comma expected in ". + "function $function, arg #{$num_args}"); + } + $result2 = $this->_condition(); + $result = $this->_createTree('arg', $result, $result2); + } else { // first argument + $result2 = $this->_condition(); + $result = $this->_createTree('arg', '', $result2); + } + ++$num_args; + } + if (!isset($this->_functions[$function])) { + throw new PHPExcel_Writer_Exception("Function $function() doesn't exist"); + } + $args = $this->_functions[$function][1]; + // If fixed number of args eg. TIME($i,$j,$k). Check that the number of args is valid. + if (($args >= 0) and ($args != $num_args)) { + throw new PHPExcel_Writer_Exception("Incorrect number of arguments in function $function() "); + } + + $result = $this->_createTree($function, $result, $num_args); + $this->_advance(); // eat the ")" + return $result; + } + + /** + * Creates a tree. In fact an array which may have one or two arrays (sub-trees) + * as elements. + * + * @access private + * @param mixed $value The value of this node. + * @param mixed $left The left array (sub-tree) or a final node. + * @param mixed $right The right array (sub-tree) or a final node. + * @return array A tree + */ + function _createTree($value, $left, $right) + { + return array('value' => $value, 'left' => $left, 'right' => $right); + } + + /** + * Builds a string containing the tree in reverse polish notation (What you + * would use in a HP calculator stack). + * The following tree: + * + * + + * / \ + * 2 3 + * + * produces: "23+" + * + * The following tree: + * + * + + * / \ + * 3 * + * / \ + * 6 A1 + * + * produces: "36A1*+" + * + * In fact all operands, functions, references, etc... are written as ptg's + * + * @access public + * @param array $tree The optional tree to convert. + * @return string The tree in reverse polish notation + */ + function toReversePolish($tree = array()) + { + $polish = ""; // the string we are going to return + if (empty($tree)) { // If it's the first call use _parse_tree + $tree = $this->_parse_tree; + } + + if (is_array($tree['left'])) { + $converted_tree = $this->toReversePolish($tree['left']); + $polish .= $converted_tree; + } elseif ($tree['left'] != '') { // It's a final node + $converted_tree = $this->_convert($tree['left']); + $polish .= $converted_tree; + } + if (is_array($tree['right'])) { + $converted_tree = $this->toReversePolish($tree['right']); + $polish .= $converted_tree; + } elseif ($tree['right'] != '') { // It's a final node + $converted_tree = $this->_convert($tree['right']); + $polish .= $converted_tree; + } + // if it's a function convert it here (so we can set it's arguments) + if (preg_match("/^[A-Z0-9\xc0-\xdc\.]+$/",$tree['value']) and + !preg_match('/^([A-Ia-i]?[A-Za-z])(\d+)$/',$tree['value']) and + !preg_match("/^[A-Ia-i]?[A-Za-z](\d+)\.\.[A-Ia-i]?[A-Za-z](\d+)$/",$tree['value']) and + !is_numeric($tree['value']) and + !isset($this->ptg[$tree['value']])) + { + // left subtree for a function is always an array. + if ($tree['left'] != '') { + $left_tree = $this->toReversePolish($tree['left']); + } else { + $left_tree = ''; + } + // add it's left subtree and return. + return $left_tree.$this->_convertFunction($tree['value'], $tree['right']); + } else { + $converted_tree = $this->_convert($tree['value']); + } + $polish .= $converted_tree; + return $polish; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Workbook.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Workbook.php new file mode 100755 index 0000000..b41d0b0 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Workbook.php @@ -0,0 +1,1450 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +// Original file header of PEAR::Spreadsheet_Excel_Writer_Workbook (used as the base for this class): +// ----------------------------------------------------------------------------------------- +// /* +// * Module written/ported by Xavier Noguer <xnoguer@rezebra.com> +// * +// * The majority of this is _NOT_ my code. I simply ported it from the +// * PERL Spreadsheet::WriteExcel module. +// * +// * The author of the Spreadsheet::WriteExcel module is John McNamara +// * <jmcnamara@cpan.org> +// * +// * I _DO_ maintain this code, and John McNamara has nothing to do with the +// * porting of this code to PHP. Any questions directly related to this +// * class library should be directed to me. +// * +// * License Information: +// * +// * Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets +// * Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com +// * +// * This library is free software; you can redistribute it and/or +// * modify it under the terms of the GNU Lesser General Public +// * License as published by the Free Software Foundation; either +// * version 2.1 of the License, or (at your option) any later version. +// * +// * This library is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// * Lesser General Public License for more details. +// * +// * You should have received a copy of the GNU Lesser General Public +// * License along with this library; if not, write to the Free Software +// * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// */ + + +/** + * PHPExcel_Writer_Excel5_Workbook + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel5_Workbook extends PHPExcel_Writer_Excel5_BIFFwriter +{ + /** + * Formula parser + * + * @var PHPExcel_Writer_Excel5_Parser + */ + private $_parser; + + /** + * The BIFF file size for the workbook. + * @var integer + * @see _calcSheetOffsets() + */ + public $_biffsize; + + /** + * XF Writers + * @var PHPExcel_Writer_Excel5_Xf[] + */ + private $_xfWriters = array(); + + /** + * Array containing the colour palette + * @var array + */ + public $_palette; + + /** + * The codepage indicates the text encoding used for strings + * @var integer + */ + public $_codepage; + + /** + * The country code used for localization + * @var integer + */ + public $_country_code; + + /** + * Workbook + * @var PHPExcel + */ + private $_phpExcel; + + /** + * Fonts writers + * + * @var PHPExcel_Writer_Excel5_Font[] + */ + private $_fontWriters = array(); + + /** + * Added fonts. Maps from font's hash => index in workbook + * + * @var array + */ + private $_addedFonts = array(); + + /** + * Shared number formats + * + * @var array + */ + private $_numberFormats = array(); + + /** + * Added number formats. Maps from numberFormat's hash => index in workbook + * + * @var array + */ + private $_addedNumberFormats = array(); + + /** + * Sizes of the binary worksheet streams + * + * @var array + */ + private $_worksheetSizes = array(); + + /** + * Offsets of the binary worksheet streams relative to the start of the global workbook stream + * + * @var array + */ + private $_worksheetOffsets = array(); + + /** + * Total number of shared strings in workbook + * + * @var int + */ + private $_str_total; + + /** + * Number of unique shared strings in workbook + * + * @var int + */ + private $_str_unique; + + /** + * Array of unique shared strings in workbook + * + * @var array + */ + private $_str_table; + + /** + * Color cache + */ + private $_colors; + + /** + * Escher object corresponding to MSODRAWINGGROUP + * + * @var PHPExcel_Shared_Escher + */ + private $_escher; + + + /** + * Class constructor + * + * @param PHPExcel $phpExcel The Workbook + * @param int &$str_total Total number of strings + * @param int &$str_unique Total number of unique strings + * @param array &$str_table String Table + * @param array &$colors Colour Table + * @param mixed $parser The formula parser created for the Workbook + */ + public function __construct(PHPExcel $phpExcel = null, + &$str_total, &$str_unique, &$str_table, &$colors, + $parser ) + { + // It needs to call its parent's constructor explicitly + parent::__construct(); + + $this->_parser = $parser; + $this->_biffsize = 0; + $this->_palette = array(); + $this->_country_code = -1; + + $this->_str_total = &$str_total; + $this->_str_unique = &$str_unique; + $this->_str_table = &$str_table; + $this->_colors = &$colors; + $this->_setPaletteXl97(); + + $this->_phpExcel = $phpExcel; + + // set BIFFwriter limit for CONTINUE records + // $this->_limit = 8224; + $this->_codepage = 0x04B0; + + // Add empty sheets and Build color cache + $countSheets = $phpExcel->getSheetCount(); + for ($i = 0; $i < $countSheets; ++$i) { + $phpSheet = $phpExcel->getSheet($i); + + $this->_parser->setExtSheet($phpSheet->getTitle(), $i); // Register worksheet name with parser + + $supbook_index = 0x00; + $ref = pack('vvv', $supbook_index, $i, $i); + $this->_parser->_references[] = $ref; // Register reference with parser + + // Sheet tab colors? + if ($phpSheet->isTabColorSet()) { + $this->_addColor($phpSheet->getTabColor()->getRGB()); + } + } + + } + + /** + * Add a new XF writer + * + * @param PHPExcel_Style + * @param boolean Is it a style XF? + * @return int Index to XF record + */ + public function addXfWriter($style, $isStyleXf = false) + { + $xfWriter = new PHPExcel_Writer_Excel5_Xf($style); + $xfWriter->setIsStyleXf($isStyleXf); + + // Add the font if not already added + $fontIndex = $this->_addFont($style->getFont()); + + // Assign the font index to the xf record + $xfWriter->setFontIndex($fontIndex); + + // Background colors, best to treat these after the font so black will come after white in custom palette + $xfWriter->setFgColor($this->_addColor($style->getFill()->getStartColor()->getRGB())); + $xfWriter->setBgColor($this->_addColor($style->getFill()->getEndColor()->getRGB())); + $xfWriter->setBottomColor($this->_addColor($style->getBorders()->getBottom()->getColor()->getRGB())); + $xfWriter->setTopColor($this->_addColor($style->getBorders()->getTop()->getColor()->getRGB())); + $xfWriter->setRightColor($this->_addColor($style->getBorders()->getRight()->getColor()->getRGB())); + $xfWriter->setLeftColor($this->_addColor($style->getBorders()->getLeft()->getColor()->getRGB())); + $xfWriter->setDiagColor($this->_addColor($style->getBorders()->getDiagonal()->getColor()->getRGB())); + + // Add the number format if it is not a built-in one and not already added + if ($style->getNumberFormat()->getBuiltInFormatCode() === false) { + $numberFormatHashCode = $style->getNumberFormat()->getHashCode(); + + if (isset($this->_addedNumberFormats[$numberFormatHashCode])) { + $numberFormatIndex = $this->_addedNumberFormats[$numberFormatHashCode]; + } else { + $numberFormatIndex = 164 + count($this->_numberFormats); + $this->_numberFormats[$numberFormatIndex] = $style->getNumberFormat(); + $this->_addedNumberFormats[$numberFormatHashCode] = $numberFormatIndex; + } + } else { + $numberFormatIndex = (int) $style->getNumberFormat()->getBuiltInFormatCode(); + } + + // Assign the number format index to xf record + $xfWriter->setNumberFormatIndex($numberFormatIndex); + + $this->_xfWriters[] = $xfWriter; + + $xfIndex = count($this->_xfWriters) - 1; + return $xfIndex; + } + + /** + * Add a font to added fonts + * + * @param PHPExcel_Style_Font $font + * @return int Index to FONT record + */ + public function _addFont(PHPExcel_Style_Font $font) + { + $fontHashCode = $font->getHashCode(); + if(isset($this->_addedFonts[$fontHashCode])){ + $fontIndex = $this->_addedFonts[$fontHashCode]; + } else { + $countFonts = count($this->_fontWriters); + $fontIndex = ($countFonts < 4) ? $countFonts : $countFonts + 1; + + $fontWriter = new PHPExcel_Writer_Excel5_Font($font); + $fontWriter->setColorIndex($this->_addColor($font->getColor()->getRGB())); + $this->_fontWriters[] = $fontWriter; + + $this->_addedFonts[$fontHashCode] = $fontIndex; + } + return $fontIndex; + } + + /** + * Alter color palette adding a custom color + * + * @param string $rgb E.g. 'FF00AA' + * @return int Color index + */ + private function _addColor($rgb) { + if (!isset($this->_colors[$rgb])) { + if (count($this->_colors) < 57) { + // then we add a custom color altering the palette + $colorIndex = 8 + count($this->_colors); + $this->_palette[$colorIndex] = + array( + hexdec(substr($rgb, 0, 2)), + hexdec(substr($rgb, 2, 2)), + hexdec(substr($rgb, 4)), + 0 + ); + $this->_colors[$rgb] = $colorIndex; + } else { + // no room for more custom colors, just map to black + $colorIndex = 0; + } + } else { + // fetch already added custom color + $colorIndex = $this->_colors[$rgb]; + } + + return $colorIndex; + } + + /** + * Sets the colour palette to the Excel 97+ default. + * + * @access private + */ + function _setPaletteXl97() + { + $this->_palette = array( + 0x08 => array(0x00, 0x00, 0x00, 0x00), + 0x09 => array(0xff, 0xff, 0xff, 0x00), + 0x0A => array(0xff, 0x00, 0x00, 0x00), + 0x0B => array(0x00, 0xff, 0x00, 0x00), + 0x0C => array(0x00, 0x00, 0xff, 0x00), + 0x0D => array(0xff, 0xff, 0x00, 0x00), + 0x0E => array(0xff, 0x00, 0xff, 0x00), + 0x0F => array(0x00, 0xff, 0xff, 0x00), + 0x10 => array(0x80, 0x00, 0x00, 0x00), + 0x11 => array(0x00, 0x80, 0x00, 0x00), + 0x12 => array(0x00, 0x00, 0x80, 0x00), + 0x13 => array(0x80, 0x80, 0x00, 0x00), + 0x14 => array(0x80, 0x00, 0x80, 0x00), + 0x15 => array(0x00, 0x80, 0x80, 0x00), + 0x16 => array(0xc0, 0xc0, 0xc0, 0x00), + 0x17 => array(0x80, 0x80, 0x80, 0x00), + 0x18 => array(0x99, 0x99, 0xff, 0x00), + 0x19 => array(0x99, 0x33, 0x66, 0x00), + 0x1A => array(0xff, 0xff, 0xcc, 0x00), + 0x1B => array(0xcc, 0xff, 0xff, 0x00), + 0x1C => array(0x66, 0x00, 0x66, 0x00), + 0x1D => array(0xff, 0x80, 0x80, 0x00), + 0x1E => array(0x00, 0x66, 0xcc, 0x00), + 0x1F => array(0xcc, 0xcc, 0xff, 0x00), + 0x20 => array(0x00, 0x00, 0x80, 0x00), + 0x21 => array(0xff, 0x00, 0xff, 0x00), + 0x22 => array(0xff, 0xff, 0x00, 0x00), + 0x23 => array(0x00, 0xff, 0xff, 0x00), + 0x24 => array(0x80, 0x00, 0x80, 0x00), + 0x25 => array(0x80, 0x00, 0x00, 0x00), + 0x26 => array(0x00, 0x80, 0x80, 0x00), + 0x27 => array(0x00, 0x00, 0xff, 0x00), + 0x28 => array(0x00, 0xcc, 0xff, 0x00), + 0x29 => array(0xcc, 0xff, 0xff, 0x00), + 0x2A => array(0xcc, 0xff, 0xcc, 0x00), + 0x2B => array(0xff, 0xff, 0x99, 0x00), + 0x2C => array(0x99, 0xcc, 0xff, 0x00), + 0x2D => array(0xff, 0x99, 0xcc, 0x00), + 0x2E => array(0xcc, 0x99, 0xff, 0x00), + 0x2F => array(0xff, 0xcc, 0x99, 0x00), + 0x30 => array(0x33, 0x66, 0xff, 0x00), + 0x31 => array(0x33, 0xcc, 0xcc, 0x00), + 0x32 => array(0x99, 0xcc, 0x00, 0x00), + 0x33 => array(0xff, 0xcc, 0x00, 0x00), + 0x34 => array(0xff, 0x99, 0x00, 0x00), + 0x35 => array(0xff, 0x66, 0x00, 0x00), + 0x36 => array(0x66, 0x66, 0x99, 0x00), + 0x37 => array(0x96, 0x96, 0x96, 0x00), + 0x38 => array(0x00, 0x33, 0x66, 0x00), + 0x39 => array(0x33, 0x99, 0x66, 0x00), + 0x3A => array(0x00, 0x33, 0x00, 0x00), + 0x3B => array(0x33, 0x33, 0x00, 0x00), + 0x3C => array(0x99, 0x33, 0x00, 0x00), + 0x3D => array(0x99, 0x33, 0x66, 0x00), + 0x3E => array(0x33, 0x33, 0x99, 0x00), + 0x3F => array(0x33, 0x33, 0x33, 0x00), + ); + } + + /** + * Assemble worksheets into a workbook and send the BIFF data to an OLE + * storage. + * + * @param array $pWorksheetSizes The sizes in bytes of the binary worksheet streams + * @return string Binary data for workbook stream + */ + public function writeWorkbook($pWorksheetSizes = null) + { + $this->_worksheetSizes = $pWorksheetSizes; + + // Calculate the number of selected worksheet tabs and call the finalization + // methods for each worksheet + $total_worksheets = $this->_phpExcel->getSheetCount(); + + // Add part 1 of the Workbook globals, what goes before the SHEET records + $this->_storeBof(0x0005); + $this->_writeCodepage(); + $this->_writeWindow1(); + + $this->_writeDatemode(); + $this->_writeAllFonts(); + $this->_writeAllNumFormats(); + $this->_writeAllXfs(); + $this->_writeAllStyles(); + $this->_writePalette(); + + // Prepare part 3 of the workbook global stream, what goes after the SHEET records + $part3 = ''; + if ($this->_country_code != -1) { + $part3 .= $this->_writeCountry(); + } + $part3 .= $this->_writeRecalcId(); + + $part3 .= $this->_writeSupbookInternal(); + /* TODO: store external SUPBOOK records and XCT and CRN records + in case of external references for BIFF8 */ + $part3 .= $this->_writeExternsheetBiff8(); + $part3 .= $this->_writeAllDefinedNamesBiff8(); + $part3 .= $this->_writeMsoDrawingGroup(); + $part3 .= $this->_writeSharedStringsTable(); + + $part3 .= $this->writeEof(); + + // Add part 2 of the Workbook globals, the SHEET records + $this->_calcSheetOffsets(); + for ($i = 0; $i < $total_worksheets; ++$i) { + $this->_writeBoundsheet($this->_phpExcel->getSheet($i), $this->_worksheetOffsets[$i]); + } + + // Add part 3 of the Workbook globals + $this->_data .= $part3; + + return $this->_data; + } + + /** + * Calculate offsets for Worksheet BOF records. + * + * @access private + */ + function _calcSheetOffsets() + { + $boundsheet_length = 10; // fixed length for a BOUNDSHEET record + + // size of Workbook globals part 1 + 3 + $offset = $this->_datasize; + + // add size of Workbook globals part 2, the length of the SHEET records + $total_worksheets = count($this->_phpExcel->getAllSheets()); + foreach ($this->_phpExcel->getWorksheetIterator() as $sheet) { + $offset += $boundsheet_length + strlen(PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($sheet->getTitle())); + } + + // add the sizes of each of the Sheet substreams, respectively + for ($i = 0; $i < $total_worksheets; ++$i) { + $this->_worksheetOffsets[$i] = $offset; + $offset += $this->_worksheetSizes[$i]; + } + $this->_biffsize = $offset; + } + + /** + * Store the Excel FONT records. + */ + private function _writeAllFonts() + { + foreach ($this->_fontWriters as $fontWriter) { + $this->_append($fontWriter->writeFont()); + } + } + + /** + * Store user defined numerical formats i.e. FORMAT records + */ + private function _writeAllNumFormats() + { + foreach ($this->_numberFormats as $numberFormatIndex => $numberFormat) { + $this->_writeNumFormat($numberFormat->getFormatCode(), $numberFormatIndex); + } + } + + /** + * Write all XF records. + */ + private function _writeAllXfs() + { + foreach ($this->_xfWriters as $xfWriter) { + $this->_append($xfWriter->writeXf()); + } + } + + /** + * Write all STYLE records. + */ + private function _writeAllStyles() + { + $this->_writeStyle(); + } + + /** + * Write the EXTERNCOUNT and EXTERNSHEET records. These are used as indexes for + * the NAME records. + */ + private function _writeExterns() + { + $countSheets = $this->_phpExcel->getSheetCount(); + // Create EXTERNCOUNT with number of worksheets + $this->_writeExterncount($countSheets); + + // Create EXTERNSHEET for each worksheet + for ($i = 0; $i < $countSheets; ++$i) { + $this->_writeExternsheet($this->_phpExcel->getSheet($i)->getTitle()); + } + } + + /** + * Write the NAME record to define the print area and the repeat rows and cols. + */ + private function _writeNames() + { + // total number of sheets + $total_worksheets = $this->_phpExcel->getSheetCount(); + + // Create the print area NAME records + for ($i = 0; $i < $total_worksheets; ++$i) { + $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); + // Write a Name record if the print area has been defined + if ($sheetSetup->isPrintAreaSet()) { + // Print area + $printArea = PHPExcel_Cell::splitRange($sheetSetup->getPrintArea()); + $printArea = $printArea[0]; + $printArea[0] = PHPExcel_Cell::coordinateFromString($printArea[0]); + $printArea[1] = PHPExcel_Cell::coordinateFromString($printArea[1]); + + $print_rowmin = $printArea[0][1] - 1; + $print_rowmax = $printArea[1][1] - 1; + $print_colmin = PHPExcel_Cell::columnIndexFromString($printArea[0][0]) - 1; + $print_colmax = PHPExcel_Cell::columnIndexFromString($printArea[1][0]) - 1; + + $this->_writeNameShort( + $i, // sheet index + 0x06, // NAME type + $print_rowmin, + $print_rowmax, + $print_colmin, + $print_colmax + ); + } + } + + // Create the print title NAME records + for ($i = 0; $i < $total_worksheets; ++$i) { + $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); + + // simultaneous repeatColumns repeatRows + if ($sheetSetup->isColumnsToRepeatAtLeftSet() && $sheetSetup->isRowsToRepeatAtTopSet()) { + $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); + $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; + $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; + + $repeat = $sheetSetup->getRowsToRepeatAtTop(); + $rowmin = $repeat[0] - 1; + $rowmax = $repeat[1] - 1; + + $this->_writeNameLong( + $i, // sheet index + 0x07, // NAME type + $rowmin, + $rowmax, + $colmin, + $colmax + ); + + // (exclusive) either repeatColumns or repeatRows + } else if ($sheetSetup->isColumnsToRepeatAtLeftSet() || $sheetSetup->isRowsToRepeatAtTopSet()) { + + // Columns to repeat + if ($sheetSetup->isColumnsToRepeatAtLeftSet()) { + $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); + $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; + $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; + } else { + $colmin = 0; + $colmax = 255; + } + + // Rows to repeat + if ($sheetSetup->isRowsToRepeatAtTopSet()) { + $repeat = $sheetSetup->getRowsToRepeatAtTop(); + $rowmin = $repeat[0] - 1; + $rowmax = $repeat[1] - 1; + } else { + $rowmin = 0; + $rowmax = 65535; + } + + $this->_writeNameShort( + $i, // sheet index + 0x07, // NAME type + $rowmin, + $rowmax, + $colmin, + $colmax + ); + } + } + } + + /** + * Writes all the DEFINEDNAME records (BIFF8). + * So far this is only used for repeating rows/columns (print titles) and print areas + */ + private function _writeAllDefinedNamesBiff8() + { + $chunk = ''; + + // Named ranges + if (count($this->_phpExcel->getNamedRanges()) > 0) { + // Loop named ranges + $namedRanges = $this->_phpExcel->getNamedRanges(); + foreach ($namedRanges as $namedRange) { + + // Create absolute coordinate + $range = PHPExcel_Cell::splitRange($namedRange->getRange()); + for ($i = 0; $i < count($range); $i++) { + $range[$i][0] = '\'' . str_replace("'", "''", $namedRange->getWorksheet()->getTitle()) . '\'!' . PHPExcel_Cell::absoluteCoordinate($range[$i][0]); + if (isset($range[$i][1])) { + $range[$i][1] = PHPExcel_Cell::absoluteCoordinate($range[$i][1]); + } + } + $range = PHPExcel_Cell::buildRange($range); // e.g. Sheet1!$A$1:$B$2 + + // parse formula + try { + $error = $this->_parser->parse($range); + $formulaData = $this->_parser->toReversePolish(); + + // make sure tRef3d is of type tRef3dR (0x3A) + if (isset($formulaData{0}) and ($formulaData{0} == "\x7A" or $formulaData{0} == "\x5A")) { + $formulaData = "\x3A" . substr($formulaData, 1); + } + + if ($namedRange->getLocalOnly()) { + // local scope + $scope = $this->_phpExcel->getIndex($namedRange->getScope()) + 1; + } else { + // global scope + $scope = 0; + } + $chunk .= $this->writeData($this->_writeDefinedNameBiff8($namedRange->getName(), $formulaData, $scope, false)); + + } catch(PHPExcel_Exception $e) { + // do nothing + } + } + } + + // total number of sheets + $total_worksheets = $this->_phpExcel->getSheetCount(); + + // write the print titles (repeating rows, columns), if any + for ($i = 0; $i < $total_worksheets; ++$i) { + $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); + // simultaneous repeatColumns repeatRows + if ($sheetSetup->isColumnsToRepeatAtLeftSet() && $sheetSetup->isRowsToRepeatAtTopSet()) { + $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); + $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; + $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; + + $repeat = $sheetSetup->getRowsToRepeatAtTop(); + $rowmin = $repeat[0] - 1; + $rowmax = $repeat[1] - 1; + + // construct formula data manually + $formulaData = pack('Cv', 0x29, 0x17); // tMemFunc + $formulaData .= pack('Cvvvvv', 0x3B, $i, 0, 65535, $colmin, $colmax); // tArea3d + $formulaData .= pack('Cvvvvv', 0x3B, $i, $rowmin, $rowmax, 0, 255); // tArea3d + $formulaData .= pack('C', 0x10); // tList + + // store the DEFINEDNAME record + $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x07), $formulaData, $i + 1, true)); + + // (exclusive) either repeatColumns or repeatRows + } else if ($sheetSetup->isColumnsToRepeatAtLeftSet() || $sheetSetup->isRowsToRepeatAtTopSet()) { + + // Columns to repeat + if ($sheetSetup->isColumnsToRepeatAtLeftSet()) { + $repeat = $sheetSetup->getColumnsToRepeatAtLeft(); + $colmin = PHPExcel_Cell::columnIndexFromString($repeat[0]) - 1; + $colmax = PHPExcel_Cell::columnIndexFromString($repeat[1]) - 1; + } else { + $colmin = 0; + $colmax = 255; + } + // Rows to repeat + if ($sheetSetup->isRowsToRepeatAtTopSet()) { + $repeat = $sheetSetup->getRowsToRepeatAtTop(); + $rowmin = $repeat[0] - 1; + $rowmax = $repeat[1] - 1; + } else { + $rowmin = 0; + $rowmax = 65535; + } + + // construct formula data manually because parser does not recognize absolute 3d cell references + $formulaData = pack('Cvvvvv', 0x3B, $i, $rowmin, $rowmax, $colmin, $colmax); + + // store the DEFINEDNAME record + $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x07), $formulaData, $i + 1, true)); + } + } + + // write the print areas, if any + for ($i = 0; $i < $total_worksheets; ++$i) { + $sheetSetup = $this->_phpExcel->getSheet($i)->getPageSetup(); + if ($sheetSetup->isPrintAreaSet()) { + // Print area, e.g. A3:J6,H1:X20 + $printArea = PHPExcel_Cell::splitRange($sheetSetup->getPrintArea()); + $countPrintArea = count($printArea); + + $formulaData = ''; + for ($j = 0; $j < $countPrintArea; ++$j) { + $printAreaRect = $printArea[$j]; // e.g. A3:J6 + $printAreaRect[0] = PHPExcel_Cell::coordinateFromString($printAreaRect[0]); + $printAreaRect[1] = PHPExcel_Cell::coordinateFromString($printAreaRect[1]); + + $print_rowmin = $printAreaRect[0][1] - 1; + $print_rowmax = $printAreaRect[1][1] - 1; + $print_colmin = PHPExcel_Cell::columnIndexFromString($printAreaRect[0][0]) - 1; + $print_colmax = PHPExcel_Cell::columnIndexFromString($printAreaRect[1][0]) - 1; + + // construct formula data manually because parser does not recognize absolute 3d cell references + $formulaData .= pack('Cvvvvv', 0x3B, $i, $print_rowmin, $print_rowmax, $print_colmin, $print_colmax); + + if ($j > 0) { + $formulaData .= pack('C', 0x10); // list operator token ',' + } + } + + // store the DEFINEDNAME record + $chunk .= $this->writeData($this->_writeDefinedNameBiff8(pack('C', 0x06), $formulaData, $i + 1, true)); + } + } + + // write autofilters, if any + for ($i = 0; $i < $total_worksheets; ++$i) { + $sheetAutoFilter = $this->_phpExcel->getSheet($i)->getAutoFilter(); + $autoFilterRange = $sheetAutoFilter->getRange(); + if(!empty($autoFilterRange)) { + $rangeBounds = PHPExcel_Cell::rangeBoundaries($autoFilterRange); + + //Autofilter built in name + $name = pack('C', 0x0D); + + $chunk .= $this->writeData($this->_writeShortNameBiff8($name, $i + 1, $rangeBounds, true)); + } + } + + return $chunk; + } + + /** + * Write a DEFINEDNAME record for BIFF8 using explicit binary formula data + * + * @param string $name The name in UTF-8 + * @param string $formulaData The binary formula data + * @param string $sheetIndex 1-based sheet index the defined name applies to. 0 = global + * @param boolean $isBuiltIn Built-in name? + * @return string Complete binary record data + */ + private function _writeDefinedNameBiff8($name, $formulaData, $sheetIndex = 0, $isBuiltIn = false) + { + $record = 0x0018; + + // option flags + $options = $isBuiltIn ? 0x20 : 0x00; + + // length of the name, character count + $nlen = PHPExcel_Shared_String::CountCharacters($name); + + // name with stripped length field + $name = substr(PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($name), 2); + + // size of the formula (in bytes) + $sz = strlen($formulaData); + + // combine the parts + $data = pack('vCCvvvCCCC', $options, 0, $nlen, $sz, 0, $sheetIndex, 0, 0, 0, 0) + . $name . $formulaData; + $length = strlen($data); + + $header = pack('vv', $record, $length); + + return $header . $data; + } + + /** + * Write a short NAME record + * + * @param string $name + * @param string $sheetIndex 1-based sheet index the defined name applies to. 0 = global + * @param integer[][] $rangeBounds range boundaries + * @param boolean $isHidden + * @return string Complete binary record data + * */ + private function _writeShortNameBiff8($name, $sheetIndex = 0, $rangeBounds, $isHidden = false){ + $record = 0x0018; + + // option flags + $options = ($isHidden ? 0x21 : 0x00); + + $extra = pack('Cvvvvv', + 0x3B, + $sheetIndex - 1, + $rangeBounds[0][1] - 1, + $rangeBounds[1][1] - 1, + $rangeBounds[0][0] - 1, + $rangeBounds[1][0] - 1); + + // size of the formula (in bytes) + $sz = strlen($extra); + + // combine the parts + $data = pack('vCCvvvCCCCC', $options, 0, 1, $sz, 0, $sheetIndex, 0, 0, 0, 0, 0) + . $name . $extra; + $length = strlen($data); + + $header = pack('vv', $record, $length); + + return $header . $data; + } + + /** + * Stores the CODEPAGE biff record. + */ + private function _writeCodepage() + { + $record = 0x0042; // Record identifier + $length = 0x0002; // Number of bytes to follow + $cv = $this->_codepage; // The code page + + $header = pack('vv', $record, $length); + $data = pack('v', $cv); + + $this->_append($header . $data); + } + + /** + * Write Excel BIFF WINDOW1 record. + */ + private function _writeWindow1() + { + $record = 0x003D; // Record identifier + $length = 0x0012; // Number of bytes to follow + + $xWn = 0x0000; // Horizontal position of window + $yWn = 0x0000; // Vertical position of window + $dxWn = 0x25BC; // Width of window + $dyWn = 0x1572; // Height of window + + $grbit = 0x0038; // Option flags + + // not supported by PHPExcel, so there is only one selected sheet, the active + $ctabsel = 1; // Number of workbook tabs selected + + $wTabRatio = 0x0258; // Tab to scrollbar ratio + + // not supported by PHPExcel, set to 0 + $itabFirst = 0; // 1st displayed worksheet + $itabCur = $this->_phpExcel->getActiveSheetIndex(); // Active worksheet + + $header = pack("vv", $record, $length); + $data = pack("vvvvvvvvv", $xWn, $yWn, $dxWn, $dyWn, + $grbit, + $itabCur, $itabFirst, + $ctabsel, $wTabRatio); + $this->_append($header . $data); + } + + /** + * Writes Excel BIFF BOUNDSHEET record. + * + * @param PHPExcel_Worksheet $sheet Worksheet name + * @param integer $offset Location of worksheet BOF + */ + private function _writeBoundsheet($sheet, $offset) + { + $sheetname = $sheet->getTitle(); + $record = 0x0085; // Record identifier + + // sheet state + switch ($sheet->getSheetState()) { + case PHPExcel_Worksheet::SHEETSTATE_VISIBLE: $ss = 0x00; break; + case PHPExcel_Worksheet::SHEETSTATE_HIDDEN: $ss = 0x01; break; + case PHPExcel_Worksheet::SHEETSTATE_VERYHIDDEN: $ss = 0x02; break; + default: $ss = 0x00; break; + } + + // sheet type + $st = 0x00; + + $grbit = 0x0000; // Visibility and sheet type + + $data = pack("VCC", $offset, $ss, $st); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($sheetname); + + $length = strlen($data); + $header = pack("vv", $record, $length); + $this->_append($header . $data); + } + + /** + * Write Internal SUPBOOK record + */ + private function _writeSupbookInternal() + { + $record = 0x01AE; // Record identifier + $length = 0x0004; // Bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("vv", $this->_phpExcel->getSheetCount(), 0x0401); + return $this->writeData($header . $data); + } + + /** + * Writes the Excel BIFF EXTERNSHEET record. These references are used by + * formulas. + * + */ + private function _writeExternsheetBiff8() + { + $total_references = count($this->_parser->_references); + $record = 0x0017; // Record identifier + $length = 2 + 6 * $total_references; // Number of bytes to follow + + $supbook_index = 0; // FIXME: only using internal SUPBOOK record + $header = pack("vv", $record, $length); + $data = pack('v', $total_references); + for ($i = 0; $i < $total_references; ++$i) { + $data .= $this->_parser->_references[$i]; + } + return $this->writeData($header . $data); + } + + /** + * Write Excel BIFF STYLE records. + */ + private function _writeStyle() + { + $record = 0x0293; // Record identifier + $length = 0x0004; // Bytes to follow + + $ixfe = 0x8000; // Index to cell style XF + $BuiltIn = 0x00; // Built-in style + $iLevel = 0xff; // Outline style level + + $header = pack("vv", $record, $length); + $data = pack("vCC", $ixfe, $BuiltIn, $iLevel); + $this->_append($header . $data); + } + + /** + * Writes Excel FORMAT record for non "built-in" numerical formats. + * + * @param string $format Custom format string + * @param integer $ifmt Format index code + */ + private function _writeNumFormat($format, $ifmt) + { + $record = 0x041E; // Record identifier + + $numberFormatString = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($format); + $length = 2 + strlen($numberFormatString); // Number of bytes to follow + + + $header = pack("vv", $record, $length); + $data = pack("v", $ifmt) . $numberFormatString; + $this->_append($header . $data); + } + + /** + * Write DATEMODE record to indicate the date system in use (1904 or 1900). + */ + private function _writeDatemode() + { + $record = 0x0022; // Record identifier + $length = 0x0002; // Bytes to follow + + $f1904 = (PHPExcel_Shared_Date::getExcelCalendar() == PHPExcel_Shared_Date::CALENDAR_MAC_1904) ? + 1 : 0; // Flag for 1904 date system + + $header = pack("vv", $record, $length); + $data = pack("v", $f1904); + $this->_append($header . $data); + } + + /** + * Write BIFF record EXTERNCOUNT to indicate the number of external sheet + * references in the workbook. + * + * Excel only stores references to external sheets that are used in NAME. + * The workbook NAME record is required to define the print area and the repeat + * rows and columns. + * + * A similar method is used in Worksheet.php for a slightly different purpose. + * + * @param integer $cxals Number of external references + */ + private function _writeExterncount($cxals) + { + $record = 0x0016; // Record identifier + $length = 0x0002; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("v", $cxals); + $this->_append($header . $data); + } + + /** + * Writes the Excel BIFF EXTERNSHEET record. These references are used by + * formulas. NAME record is required to define the print area and the repeat + * rows and columns. + * + * A similar method is used in Worksheet.php for a slightly different purpose. + * + * @param string $sheetname Worksheet name + */ + private function _writeExternsheet($sheetname) + { + $record = 0x0017; // Record identifier + $length = 0x02 + strlen($sheetname); // Number of bytes to follow + + $cch = strlen($sheetname); // Length of sheet name + $rgch = 0x03; // Filename encoding + + $header = pack("vv", $record, $length); + $data = pack("CC", $cch, $rgch); + $this->_append($header . $data . $sheetname); + } + + /** + * Store the NAME record in the short format that is used for storing the print + * area, repeat rows only and repeat columns only. + * + * @param integer $index Sheet index + * @param integer $type Built-in name type + * @param integer $rowmin Start row + * @param integer $rowmax End row + * @param integer $colmin Start colum + * @param integer $colmax End column + */ + private function _writeNameShort($index, $type, $rowmin, $rowmax, $colmin, $colmax) + { + $record = 0x0018; // Record identifier + $length = 0x0024; // Number of bytes to follow + + $grbit = 0x0020; // Option flags + $chKey = 0x00; // Keyboard shortcut + $cch = 0x01; // Length of text name + $cce = 0x0015; // Length of text definition + $ixals = $index + 1; // Sheet index + $itab = $ixals; // Equal to ixals + $cchCustMenu = 0x00; // Length of cust menu text + $cchDescription = 0x00; // Length of description text + $cchHelptopic = 0x00; // Length of help topic text + $cchStatustext = 0x00; // Length of status bar text + $rgch = $type; // Built-in name type + + $unknown03 = 0x3b; + $unknown04 = 0xffff-$index; + $unknown05 = 0x0000; + $unknown06 = 0x0000; + $unknown07 = 0x1087; + $unknown08 = 0x8005; + + $header = pack("vv", $record, $length); + $data = pack("v", $grbit); + $data .= pack("C", $chKey); + $data .= pack("C", $cch); + $data .= pack("v", $cce); + $data .= pack("v", $ixals); + $data .= pack("v", $itab); + $data .= pack("C", $cchCustMenu); + $data .= pack("C", $cchDescription); + $data .= pack("C", $cchHelptopic); + $data .= pack("C", $cchStatustext); + $data .= pack("C", $rgch); + $data .= pack("C", $unknown03); + $data .= pack("v", $unknown04); + $data .= pack("v", $unknown05); + $data .= pack("v", $unknown06); + $data .= pack("v", $unknown07); + $data .= pack("v", $unknown08); + $data .= pack("v", $index); + $data .= pack("v", $index); + $data .= pack("v", $rowmin); + $data .= pack("v", $rowmax); + $data .= pack("C", $colmin); + $data .= pack("C", $colmax); + $this->_append($header . $data); + } + + /** + * Store the NAME record in the long format that is used for storing the repeat + * rows and columns when both are specified. This shares a lot of code with + * _writeNameShort() but we use a separate method to keep the code clean. + * Code abstraction for reuse can be carried too far, and I should know. ;-) + * + * @param integer $index Sheet index + * @param integer $type Built-in name type + * @param integer $rowmin Start row + * @param integer $rowmax End row + * @param integer $colmin Start colum + * @param integer $colmax End column + */ + private function _writeNameLong($index, $type, $rowmin, $rowmax, $colmin, $colmax) + { + $record = 0x0018; // Record identifier + $length = 0x003d; // Number of bytes to follow + $grbit = 0x0020; // Option flags + $chKey = 0x00; // Keyboard shortcut + $cch = 0x01; // Length of text name + $cce = 0x002e; // Length of text definition + $ixals = $index + 1; // Sheet index + $itab = $ixals; // Equal to ixals + $cchCustMenu = 0x00; // Length of cust menu text + $cchDescription = 0x00; // Length of description text + $cchHelptopic = 0x00; // Length of help topic text + $cchStatustext = 0x00; // Length of status bar text + $rgch = $type; // Built-in name type + + $unknown01 = 0x29; + $unknown02 = 0x002b; + $unknown03 = 0x3b; + $unknown04 = 0xffff-$index; + $unknown05 = 0x0000; + $unknown06 = 0x0000; + $unknown07 = 0x1087; + $unknown08 = 0x8008; + + $header = pack("vv", $record, $length); + $data = pack("v", $grbit); + $data .= pack("C", $chKey); + $data .= pack("C", $cch); + $data .= pack("v", $cce); + $data .= pack("v", $ixals); + $data .= pack("v", $itab); + $data .= pack("C", $cchCustMenu); + $data .= pack("C", $cchDescription); + $data .= pack("C", $cchHelptopic); + $data .= pack("C", $cchStatustext); + $data .= pack("C", $rgch); + $data .= pack("C", $unknown01); + $data .= pack("v", $unknown02); + // Column definition + $data .= pack("C", $unknown03); + $data .= pack("v", $unknown04); + $data .= pack("v", $unknown05); + $data .= pack("v", $unknown06); + $data .= pack("v", $unknown07); + $data .= pack("v", $unknown08); + $data .= pack("v", $index); + $data .= pack("v", $index); + $data .= pack("v", 0x0000); + $data .= pack("v", 0x3fff); + $data .= pack("C", $colmin); + $data .= pack("C", $colmax); + // Row definition + $data .= pack("C", $unknown03); + $data .= pack("v", $unknown04); + $data .= pack("v", $unknown05); + $data .= pack("v", $unknown06); + $data .= pack("v", $unknown07); + $data .= pack("v", $unknown08); + $data .= pack("v", $index); + $data .= pack("v", $index); + $data .= pack("v", $rowmin); + $data .= pack("v", $rowmax); + $data .= pack("C", 0x00); + $data .= pack("C", 0xff); + // End of data + $data .= pack("C", 0x10); + $this->_append($header . $data); + } + + /** + * Stores the COUNTRY record for localization + * + * @return string + */ + private function _writeCountry() + { + $record = 0x008C; // Record identifier + $length = 4; // Number of bytes to follow + + $header = pack('vv', $record, $length); + /* using the same country code always for simplicity */ + $data = pack('vv', $this->_country_code, $this->_country_code); + //$this->_append($header . $data); + return $this->writeData($header . $data); + } + + /** + * Write the RECALCID record + * + * @return string + */ + private function _writeRecalcId() + { + $record = 0x01C1; // Record identifier + $length = 8; // Number of bytes to follow + + $header = pack('vv', $record, $length); + + // by inspection of real Excel files, MS Office Excel 2007 writes this + $data = pack('VV', 0x000001C1, 0x00001E667); + + return $this->writeData($header . $data); + } + + /** + * Stores the PALETTE biff record. + */ + private function _writePalette() + { + $aref = $this->_palette; + + $record = 0x0092; // Record identifier + $length = 2 + 4 * count($aref); // Number of bytes to follow + $ccv = count($aref); // Number of RGB values to follow + $data = ''; // The RGB data + + // Pack the RGB data + foreach ($aref as $color) { + foreach ($color as $byte) { + $data .= pack("C",$byte); + } + } + + $header = pack("vvv", $record, $length, $ccv); + $this->_append($header . $data); + } + + /** + * Handling of the SST continue blocks is complicated by the need to include an + * additional continuation byte depending on whether the string is split between + * blocks or whether it starts at the beginning of the block. (There are also + * additional complications that will arise later when/if Rich Strings are + * supported). + * + * The Excel documentation says that the SST record should be followed by an + * EXTSST record. The EXTSST record is a hash table that is used to optimise + * access to SST. However, despite the documentation it doesn't seem to be + * required so we will ignore it. + * + * @return string Binary data + */ + private function _writeSharedStringsTable() + { + // maximum size of record data (excluding record header) + $continue_limit = 8224; + + // initialize array of record data blocks + $recordDatas = array(); + + // start SST record data block with total number of strings, total number of unique strings + $recordData = pack("VV", $this->_str_total, $this->_str_unique); + + // loop through all (unique) strings in shared strings table + foreach (array_keys($this->_str_table) as $string) { + + // here $string is a BIFF8 encoded string + + // length = character count + $headerinfo = unpack("vlength/Cencoding", $string); + + // currently, this is always 1 = uncompressed + $encoding = $headerinfo["encoding"]; + + // initialize finished writing current $string + $finished = false; + + while ($finished === false) { + + // normally, there will be only one cycle, but if string cannot immediately be written as is + // there will be need for more than one cylcle, if string longer than one record data block, there + // may be need for even more cycles + + if (strlen($recordData) + strlen($string) <= $continue_limit) { + // then we can write the string (or remainder of string) without any problems + $recordData .= $string; + + if (strlen($recordData) + strlen($string) == $continue_limit) { + // we close the record data block, and initialize a new one + $recordDatas[] = $recordData; + $recordData = ''; + } + + // we are finished writing this string + $finished = true; + } else { + // special treatment writing the string (or remainder of the string) + // If the string is very long it may need to be written in more than one CONTINUE record. + + // check how many bytes more there is room for in the current record + $space_remaining = $continue_limit - strlen($recordData); + + // minimum space needed + // uncompressed: 2 byte string length length field + 1 byte option flags + 2 byte character + // compressed: 2 byte string length length field + 1 byte option flags + 1 byte character + $min_space_needed = ($encoding == 1) ? 5 : 4; + + // We have two cases + // 1. space remaining is less than minimum space needed + // here we must waste the space remaining and move to next record data block + // 2. space remaining is greater than or equal to minimum space needed + // here we write as much as we can in the current block, then move to next record data block + + // 1. space remaining is less than minimum space needed + if ($space_remaining < $min_space_needed) { + // we close the block, store the block data + $recordDatas[] = $recordData; + + // and start new record data block where we start writing the string + $recordData = ''; + + // 2. space remaining is greater than or equal to minimum space needed + } else { + // initialize effective remaining space, for Unicode strings this may need to be reduced by 1, see below + $effective_space_remaining = $space_remaining; + + // for uncompressed strings, sometimes effective space remaining is reduced by 1 + if ( $encoding == 1 && (strlen($string) - $space_remaining) % 2 == 1 ) { + --$effective_space_remaining; + } + + // one block fininshed, store the block data + $recordData .= substr($string, 0, $effective_space_remaining); + + $string = substr($string, $effective_space_remaining); // for next cycle in while loop + $recordDatas[] = $recordData; + + // start new record data block with the repeated option flags + $recordData = pack('C', $encoding); + } + } + } + } + + // Store the last record data block unless it is empty + // if there was no need for any continue records, this will be the for SST record data block itself + if (strlen($recordData) > 0) { + $recordDatas[] = $recordData; + } + + // combine into one chunk with all the blocks SST, CONTINUE,... + $chunk = ''; + foreach ($recordDatas as $i => $recordData) { + // first block should have the SST record header, remaing should have CONTINUE header + $record = ($i == 0) ? 0x00FC : 0x003C; + + $header = pack("vv", $record, strlen($recordData)); + $data = $header . $recordData; + + $chunk .= $this->writeData($data); + } + + return $chunk; + } + + /** + * Writes the MSODRAWINGGROUP record if needed. Possibly split using CONTINUE records. + */ + private function _writeMsoDrawingGroup() + { + // write the Escher stream if necessary + if (isset($this->_escher)) { + $writer = new PHPExcel_Writer_Excel5_Escher($this->_escher); + $data = $writer->close(); + + $record = 0x00EB; + $length = strlen($data); + $header = pack("vv", $record, $length); + + return $this->writeData($header . $data); + + } else { + return ''; + } + } + + /** + * Get Escher object + * + * @return PHPExcel_Shared_Escher + */ + public function getEscher() + { + return $this->_escher; + } + + /** + * Set Escher object + * + * @param PHPExcel_Shared_Escher $pValue + */ + public function setEscher(PHPExcel_Shared_Escher $pValue = null) + { + $this->_escher = $pValue; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Worksheet.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Worksheet.php new file mode 100755 index 0000000..f8945f5 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Worksheet.php @@ -0,0 +1,3681 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +// Original file header of PEAR::Spreadsheet_Excel_Writer_Worksheet (used as the base for this class): +// ----------------------------------------------------------------------------------------- +// /* +// * Module written/ported by Xavier Noguer <xnoguer@rezebra.com> +// * +// * The majority of this is _NOT_ my code. I simply ported it from the +// * PERL Spreadsheet::WriteExcel module. +// * +// * The author of the Spreadsheet::WriteExcel module is John McNamara +// * <jmcnamara@cpan.org> +// * +// * I _DO_ maintain this code, and John McNamara has nothing to do with the +// * porting of this code to PHP. Any questions directly related to this +// * class library should be directed to me. +// * +// * License Information: +// * +// * Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets +// * Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com +// * +// * This library is free software; you can redistribute it and/or +// * modify it under the terms of the GNU Lesser General Public +// * License as published by the Free Software Foundation; either +// * version 2.1 of the License, or (at your option) any later version. +// * +// * This library is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// * Lesser General Public License for more details. +// * +// * You should have received a copy of the GNU Lesser General Public +// * License along with this library; if not, write to the Free Software +// * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// */ + + +/** + * PHPExcel_Writer_Excel5_Worksheet + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel5_Worksheet extends PHPExcel_Writer_Excel5_BIFFwriter +{ + /** + * Formula parser + * + * @var PHPExcel_Writer_Excel5_Parser + */ + private $_parser; + + /** + * Maximum number of characters for a string (LABEL record in BIFF5) + * @var integer + */ + public $_xls_strmax; + + /** + * Array containing format information for columns + * @var array + */ + public $_colinfo; + + /** + * Array containing the selected area for the worksheet + * @var array + */ + public $_selection; + + /** + * The active pane for the worksheet + * @var integer + */ + public $_active_pane; + + /** + * Whether to use outline. + * @var integer + */ + public $_outline_on; + + /** + * Auto outline styles. + * @var bool + */ + public $_outline_style; + + /** + * Whether to have outline summary below. + * @var bool + */ + public $_outline_below; + + /** + * Whether to have outline summary at the right. + * @var bool + */ + public $_outline_right; + + /** + * Reference to the total number of strings in the workbook + * @var integer + */ + public $_str_total; + + /** + * Reference to the number of unique strings in the workbook + * @var integer + */ + public $_str_unique; + + /** + * Reference to the array containing all the unique strings in the workbook + * @var array + */ + public $_str_table; + + /** + * Color cache + */ + private $_colors; + + /** + * Index of first used row (at least 0) + * @var int + */ + private $_firstRowIndex; + + /** + * Index of last used row. (no used rows means -1) + * @var int + */ + private $_lastRowIndex; + + /** + * Index of first used column (at least 0) + * @var int + */ + private $_firstColumnIndex; + + /** + * Index of last used column (no used columns means -1) + * @var int + */ + private $_lastColumnIndex; + + /** + * Sheet object + * @var PHPExcel_Worksheet + */ + public $_phpSheet; + + /** + * Count cell style Xfs + * + * @var int + */ + private $_countCellStyleXfs; + + /** + * Escher object corresponding to MSODRAWING + * + * @var PHPExcel_Shared_Escher + */ + private $_escher; + + /** + * Array of font hashes associated to FONT records index + * + * @var array + */ + public $_fntHashIndex; + + /** + * Constructor + * + * @param int &$str_total Total number of strings + * @param int &$str_unique Total number of unique strings + * @param array &$str_table String Table + * @param array &$colors Colour Table + * @param mixed $parser The formula parser created for the Workbook + * @param boolean $preCalculateFormulas Flag indicating whether formulas should be calculated or just written + * @param string $phpSheet The worksheet to write + * @param PHPExcel_Worksheet $phpSheet + */ + public function __construct(&$str_total, &$str_unique, &$str_table, &$colors, + $parser, $preCalculateFormulas, $phpSheet) + { + // It needs to call its parent's constructor explicitly + parent::__construct(); + + // change BIFFwriter limit for CONTINUE records +// $this->_limit = 8224; + + + $this->_preCalculateFormulas = $preCalculateFormulas; + $this->_str_total = &$str_total; + $this->_str_unique = &$str_unique; + $this->_str_table = &$str_table; + $this->_colors = &$colors; + $this->_parser = $parser; + + $this->_phpSheet = $phpSheet; + + //$this->ext_sheets = array(); + //$this->offset = 0; + $this->_xls_strmax = 255; + $this->_colinfo = array(); + $this->_selection = array(0,0,0,0); + $this->_active_pane = 3; + + $this->_print_headers = 0; + + $this->_outline_style = 0; + $this->_outline_below = 1; + $this->_outline_right = 1; + $this->_outline_on = 1; + + $this->_fntHashIndex = array(); + + // calculate values for DIMENSIONS record + $minR = 1; + $minC = 'A'; + + $maxR = $this->_phpSheet->getHighestRow(); + $maxC = $this->_phpSheet->getHighestColumn(); + + // Determine lowest and highest column and row +// $this->_firstRowIndex = ($minR > 65535) ? 65535 : $minR; + $this->_lastRowIndex = ($maxR > 65535) ? 65535 : $maxR ; + + $this->_firstColumnIndex = PHPExcel_Cell::columnIndexFromString($minC); + $this->_lastColumnIndex = PHPExcel_Cell::columnIndexFromString($maxC); + +// if ($this->_firstColumnIndex > 255) $this->_firstColumnIndex = 255; + if ($this->_lastColumnIndex > 255) $this->_lastColumnIndex = 255; + + $this->_countCellStyleXfs = count($phpSheet->getParent()->getCellStyleXfCollection()); + } + + /** + * Add data to the beginning of the workbook (note the reverse order) + * and to the end of the workbook. + * + * @access public + * @see PHPExcel_Writer_Excel5_Workbook::storeWorkbook() + */ + function close() + { + $_phpSheet = $this->_phpSheet; + + $num_sheets = $_phpSheet->getParent()->getSheetCount(); + + // Write BOF record + $this->_storeBof(0x0010); + + // Write PRINTHEADERS + $this->_writePrintHeaders(); + + // Write PRINTGRIDLINES + $this->_writePrintGridlines(); + + // Write GRIDSET + $this->_writeGridset(); + + // Calculate column widths + $_phpSheet->calculateColumnWidths(); + + // Column dimensions + if (($defaultWidth = $_phpSheet->getDefaultColumnDimension()->getWidth()) < 0) { + $defaultWidth = PHPExcel_Shared_Font::getDefaultColumnWidthByFont($_phpSheet->getParent()->getDefaultStyle()->getFont()); + } + + $columnDimensions = $_phpSheet->getColumnDimensions(); + $maxCol = $this->_lastColumnIndex -1; + for ($i = 0; $i <= $maxCol; ++$i) { + $hidden = 0; + $level = 0; + $xfIndex = 15; // there are 15 cell style Xfs + + $width = $defaultWidth; + + $columnLetter = PHPExcel_Cell::stringFromColumnIndex($i); + if (isset($columnDimensions[$columnLetter])) { + $columnDimension = $columnDimensions[$columnLetter]; + if ($columnDimension->getWidth() >= 0) { + $width = $columnDimension->getWidth(); + } + $hidden = $columnDimension->getVisible() ? 0 : 1; + $level = $columnDimension->getOutlineLevel(); + $xfIndex = $columnDimension->getXfIndex() + 15; // there are 15 cell style Xfs + } + + // Components of _colinfo: + // $firstcol first column on the range + // $lastcol last column on the range + // $width width to set + // $xfIndex The optional cell style Xf index to apply to the columns + // $hidden The optional hidden atribute + // $level The optional outline level + $this->_colinfo[] = array($i, $i, $width, $xfIndex, $hidden, $level); + } + + // Write GUTS + $this->_writeGuts(); + + // Write DEFAULTROWHEIGHT + $this->_writeDefaultRowHeight(); + + // Write WSBOOL + $this->_writeWsbool(); + + // Write horizontal and vertical page breaks + $this->_writeBreaks(); + + // Write page header + $this->_writeHeader(); + + // Write page footer + $this->_writeFooter(); + + // Write page horizontal centering + $this->_writeHcenter(); + + // Write page vertical centering + $this->_writeVcenter(); + + // Write left margin + $this->_writeMarginLeft(); + + // Write right margin + $this->_writeMarginRight(); + + // Write top margin + $this->_writeMarginTop(); + + // Write bottom margin + $this->_writeMarginBottom(); + + // Write page setup + $this->_writeSetup(); + + // Write sheet protection + $this->_writeProtect(); + + // Write SCENPROTECT + $this->_writeScenProtect(); + + // Write OBJECTPROTECT + $this->_writeObjectProtect(); + + // Write sheet password + $this->_writePassword(); + + // Write DEFCOLWIDTH record + $this->_writeDefcol(); + + // Write the COLINFO records if they exist + if (!empty($this->_colinfo)) { + $colcount = count($this->_colinfo); + for ($i = 0; $i < $colcount; ++$i) { + $this->_writeColinfo($this->_colinfo[$i]); + } + } + $autoFilterRange = $_phpSheet->getAutoFilter()->getRange(); + if (!empty($autoFilterRange)) { + // Write AUTOFILTERINFO + $this->_writeAutoFilterInfo(); + } + + // Write sheet dimensions + $this->_writeDimensions(); + + // Row dimensions + foreach ($_phpSheet->getRowDimensions() as $rowDimension) { + $xfIndex = $rowDimension->getXfIndex() + 15; // there are 15 cellXfs + $this->_writeRow( $rowDimension->getRowIndex() - 1, $rowDimension->getRowHeight(), $xfIndex, ($rowDimension->getVisible() ? '0' : '1'), $rowDimension->getOutlineLevel() ); + } + + // Write Cells + foreach ($_phpSheet->getCellCollection() as $cellID) { + $cell = $_phpSheet->getCell($cellID); + $row = $cell->getRow() - 1; + $column = PHPExcel_Cell::columnIndexFromString($cell->getColumn()) - 1; + + // Don't break Excel! +// if ($row + 1 > 65536 or $column + 1 > 256) { + if ($row > 65535 || $column > 255) { + break; + } + + // Write cell value + $xfIndex = $cell->getXfIndex() + 15; // there are 15 cell style Xfs + + $cVal = $cell->getValue(); + if ($cVal instanceof PHPExcel_RichText) { + // $this->_writeString($row, $column, $cVal->getPlainText(), $xfIndex); + $arrcRun = array(); + $str_len = PHPExcel_Shared_String::CountCharacters($cVal->getPlainText(), 'UTF-8'); + $str_pos = 0; + $elements = $cVal->getRichTextElements(); + foreach ($elements as $element) { + // FONT Index + if ($element instanceof PHPExcel_RichText_Run) { + $str_fontidx = $this->_fntHashIndex[$element->getFont()->getHashCode()]; + } + else { + $str_fontidx = 0; + } + $arrcRun[] = array('strlen' => $str_pos, 'fontidx' => $str_fontidx); + // Position FROM + $str_pos += PHPExcel_Shared_String::CountCharacters($element->getText(), 'UTF-8'); + } + $this->_writeRichTextString($row, $column, $cVal->getPlainText(), $xfIndex, $arrcRun); + } else { + switch ($cell->getDatatype()) { + case PHPExcel_Cell_DataType::TYPE_STRING: + case PHPExcel_Cell_DataType::TYPE_NULL: + if ($cVal === '' || $cVal === null) { + $this->_writeBlank($row, $column, $xfIndex); + } else { + $this->_writeString($row, $column, $cVal, $xfIndex); + } + break; + + case PHPExcel_Cell_DataType::TYPE_NUMERIC: + $this->_writeNumber($row, $column, $cVal, $xfIndex); + break; + + case PHPExcel_Cell_DataType::TYPE_FORMULA: + $calculatedValue = $this->_preCalculateFormulas ? + $cell->getCalculatedValue() : null; + $this->_writeFormula($row, $column, $cVal, $xfIndex, $calculatedValue); + break; + + case PHPExcel_Cell_DataType::TYPE_BOOL: + $this->_writeBoolErr($row, $column, $cVal, 0, $xfIndex); + break; + + case PHPExcel_Cell_DataType::TYPE_ERROR: + $this->_writeBoolErr($row, $column, self::_mapErrorCode($cVal), 1, $xfIndex); + break; + + } + } + } + + // Append + $this->_writeMsoDrawing(); + + // Write WINDOW2 record + $this->_writeWindow2(); + + // Write PLV record + $this->_writePageLayoutView(); + + // Write ZOOM record + $this->_writeZoom(); + if ($_phpSheet->getFreezePane()) { + $this->_writePanes(); + } + + // Write SELECTION record + $this->_writeSelection(); + + // Write MergedCellsTable Record + $this->_writeMergedCells(); + + // Hyperlinks + foreach ($_phpSheet->getHyperLinkCollection() as $coordinate => $hyperlink) { + list($column, $row) = PHPExcel_Cell::coordinateFromString($coordinate); + + $url = $hyperlink->getUrl(); + + if ( strpos($url, 'sheet://') !== false ) { + // internal to current workbook + $url = str_replace('sheet://', 'internal:', $url); + + } else if ( preg_match('/^(http:|https:|ftp:|mailto:)/', $url) ) { + // URL + // $url = $url; + + } else { + // external (local file) + $url = 'external:' . $url; + } + + $this->_writeUrl($row - 1, PHPExcel_Cell::columnIndexFromString($column) - 1, $url); + } + + $this->_writeDataValidity(); + $this->_writeSheetLayout(); + + // Write SHEETPROTECTION record + $this->_writeSheetProtection(); + $this->_writeRangeProtection(); + + $arrConditionalStyles = $_phpSheet->getConditionalStylesCollection(); + if(!empty($arrConditionalStyles)){ + $arrConditional = array(); + // @todo CFRule & CFHeader + // Write CFHEADER record + $this->_writeCFHeader(); + // Write ConditionalFormattingTable records + foreach ($arrConditionalStyles as $cellCoordinate => $conditionalStyles) { + foreach ($conditionalStyles as $conditional) { + if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION + || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ + if(!in_array($conditional->getHashCode(), $arrConditional)){ + $arrConditional[] = $conditional->getHashCode(); + // Write CFRULE record + $this->_writeCFRule($conditional); + } + } + } + } + } + + $this->_storeEof(); + } + + /** + * Write a cell range address in BIFF8 + * always fixed range + * See section 2.5.14 in OpenOffice.org's Documentation of the Microsoft Excel File Format + * + * @param string $range E.g. 'A1' or 'A1:B6' + * @return string Binary data + */ + private function _writeBIFF8CellRangeAddressFixed($range = 'A1') + { + $explodes = explode(':', $range); + + // extract first cell, e.g. 'A1' + $firstCell = $explodes[0]; + + // extract last cell, e.g. 'B6' + if (count($explodes) == 1) { + $lastCell = $firstCell; + } else { + $lastCell = $explodes[1]; + } + + $firstCellCoordinates = PHPExcel_Cell::coordinateFromString($firstCell); // e.g. array(0, 1) + $lastCellCoordinates = PHPExcel_Cell::coordinateFromString($lastCell); // e.g. array(1, 6) + + return(pack('vvvv', + $firstCellCoordinates[1] - 1, + $lastCellCoordinates[1] - 1, + PHPExcel_Cell::columnIndexFromString($firstCellCoordinates[0]) - 1, + PHPExcel_Cell::columnIndexFromString($lastCellCoordinates[0]) - 1 + )); + } + + /** + * Retrieves data from memory in one chunk, or from disk in $buffer + * sized chunks. + * + * @return string The data + */ + function getData() + { + $buffer = 4096; + + // Return data stored in memory + if (isset($this->_data)) { + $tmp = $this->_data; + unset($this->_data); + return $tmp; + } + // No data to return + return false; + } + + /** + * Set the option to print the row and column headers on the printed page. + * + * @access public + * @param integer $print Whether to print the headers or not. Defaults to 1 (print). + */ + function printRowColHeaders($print = 1) + { + $this->_print_headers = $print; + } + + /** + * This method sets the properties for outlining and grouping. The defaults + * correspond to Excel's defaults. + * + * @param bool $visible + * @param bool $symbols_below + * @param bool $symbols_right + * @param bool $auto_style + */ + function setOutline($visible = true, $symbols_below = true, $symbols_right = true, $auto_style = false) + { + $this->_outline_on = $visible; + $this->_outline_below = $symbols_below; + $this->_outline_right = $symbols_right; + $this->_outline_style = $auto_style; + + // Ensure this is a boolean vale for Window2 + if ($this->_outline_on) { + $this->_outline_on = 1; + } + } + + /** + * Write a double to the specified row and column (zero indexed). + * An integer can be written as a double. Excel will display an + * integer. $format is optional. + * + * Returns 0 : normal termination + * -2 : row or column out of range + * + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param float $num The number to write + * @param mixed $xfIndex The optional XF format + * @return integer + */ + private function _writeNumber($row, $col, $num, $xfIndex) + { + $record = 0x0203; // Record identifier + $length = 0x000E; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("vvv", $row, $col, $xfIndex); + $xl_double = pack("d", $num); + if (self::getByteOrder()) { // if it's Big Endian + $xl_double = strrev($xl_double); + } + + $this->_append($header.$data.$xl_double); + return(0); + } + + /** + * Write a LABELSST record or a LABEL record. Which one depends on BIFF version + * + * @param int $row Row index (0-based) + * @param int $col Column index (0-based) + * @param string $str The string + * @param int $xfIndex Index to XF record + */ + private function _writeString($row, $col, $str, $xfIndex) + { + $this->_writeLabelSst($row, $col, $str, $xfIndex); + } + + /** + * Write a LABELSST record or a LABEL record. Which one depends on BIFF version + * It differs from _writeString by the writing of rich text strings. + * @param int $row Row index (0-based) + * @param int $col Column index (0-based) + * @param string $str The string + * @param mixed $xfIndex The XF format index for the cell + * @param array $arrcRun Index to Font record and characters beginning + */ + private function _writeRichTextString($row, $col, $str, $xfIndex, $arrcRun){ + $record = 0x00FD; // Record identifier + $length = 0x000A; // Bytes to follow + $str = PHPExcel_Shared_String::UTF8toBIFF8UnicodeShort($str, $arrcRun); + + /* check if string is already present */ + if (!isset($this->_str_table[$str])) { + $this->_str_table[$str] = $this->_str_unique++; + } + $this->_str_total++; + + $header = pack('vv', $record, $length); + $data = pack('vvvV', $row, $col, $xfIndex, $this->_str_table[$str]); + $this->_append($header.$data); + } + + /** + * Write a string to the specified row and column (zero indexed). + * NOTE: there is an Excel 5 defined limit of 255 characters. + * $format is optional. + * Returns 0 : normal termination + * -2 : row or column out of range + * -3 : long string truncated to 255 chars + * + * @access public + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param string $str The string to write + * @param mixed $xfIndex The XF format index for the cell + * @return integer + */ + private function _writeLabel($row, $col, $str, $xfIndex) + { + $strlen = strlen($str); + $record = 0x0204; // Record identifier + $length = 0x0008 + $strlen; // Bytes to follow + + $str_error = 0; + + if ($strlen > $this->_xls_strmax) { // LABEL must be < 255 chars + $str = substr($str, 0, $this->_xls_strmax); + $length = 0x0008 + $this->_xls_strmax; + $strlen = $this->_xls_strmax; + $str_error = -3; + } + + $header = pack("vv", $record, $length); + $data = pack("vvvv", $row, $col, $xfIndex, $strlen); + $this->_append($header . $data . $str); + return($str_error); + } + + /** + * Write a string to the specified row and column (zero indexed). + * This is the BIFF8 version (no 255 chars limit). + * $format is optional. + * Returns 0 : normal termination + * -2 : row or column out of range + * -3 : long string truncated to 255 chars + * + * @access public + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param string $str The string to write + * @param mixed $xfIndex The XF format index for the cell + * @return integer + */ + private function _writeLabelSst($row, $col, $str, $xfIndex) + { + $record = 0x00FD; // Record identifier + $length = 0x000A; // Bytes to follow + + $str = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($str); + + /* check if string is already present */ + if (!isset($this->_str_table[$str])) { + $this->_str_table[$str] = $this->_str_unique++; + } + $this->_str_total++; + + $header = pack('vv', $record, $length); + $data = pack('vvvV', $row, $col, $xfIndex, $this->_str_table[$str]); + $this->_append($header.$data); + } + + /** + * Writes a note associated with the cell given by the row and column. + * NOTE records don't have a length limit. + * + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param string $note The note to write + */ + private function _writeNote($row, $col, $note) + { + $note_length = strlen($note); + $record = 0x001C; // Record identifier + $max_length = 2048; // Maximun length for a NOTE record + + // Length for this record is no more than 2048 + 6 + $length = 0x0006 + min($note_length, 2048); + $header = pack("vv", $record, $length); + $data = pack("vvv", $row, $col, $note_length); + $this->_append($header . $data . substr($note, 0, 2048)); + + for ($i = $max_length; $i < $note_length; $i += $max_length) { + $chunk = substr($note, $i, $max_length); + $length = 0x0006 + strlen($chunk); + $header = pack("vv", $record, $length); + $data = pack("vvv", -1, 0, strlen($chunk)); + $this->_append($header.$data.$chunk); + } + return(0); + } + + /** + * Write a blank cell to the specified row and column (zero indexed). + * A blank cell is used to specify formatting without adding a string + * or a number. + * + * A blank cell without a format serves no purpose. Therefore, we don't write + * a BLANK record unless a format is specified. + * + * Returns 0 : normal termination (including no format) + * -1 : insufficient number of arguments + * -2 : row or column out of range + * + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param mixed $xfIndex The XF format index + */ + function _writeBlank($row, $col, $xfIndex) + { + $record = 0x0201; // Record identifier + $length = 0x0006; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("vvv", $row, $col, $xfIndex); + $this->_append($header . $data); + return 0; + } + + /** + * Write a boolean or an error type to the specified row and column (zero indexed) + * + * @param int $row Row index (0-based) + * @param int $col Column index (0-based) + * @param int $value + * @param boolean $isError Error or Boolean? + * @param int $xfIndex + */ + private function _writeBoolErr($row, $col, $value, $isError, $xfIndex) + { + $record = 0x0205; + $length = 8; + + $header = pack("vv", $record, $length); + $data = pack("vvvCC", $row, $col, $xfIndex, $value, $isError); + $this->_append($header . $data); + return 0; + } + + /** + * Write a formula to the specified row and column (zero indexed). + * The textual representation of the formula is passed to the parser in + * Parser.php which returns a packed binary string. + * + * Returns 0 : normal termination + * -1 : formula errors (bad formula) + * -2 : row or column out of range + * + * @param integer $row Zero indexed row + * @param integer $col Zero indexed column + * @param string $formula The formula text string + * @param mixed $xfIndex The XF format index + * @param mixed $calculatedValue Calculated value + * @return integer + */ + private function _writeFormula($row, $col, $formula, $xfIndex, $calculatedValue) + { + $record = 0x0006; // Record identifier + + // Initialize possible additional value for STRING record that should be written after the FORMULA record? + $stringValue = null; + + // calculated value + if (isset($calculatedValue)) { + // Since we can't yet get the data type of the calculated value, + // we use best effort to determine data type + if (is_bool($calculatedValue)) { + // Boolean value + $num = pack('CCCvCv', 0x01, 0x00, (int)$calculatedValue, 0x00, 0x00, 0xFFFF); + } elseif (is_int($calculatedValue) || is_float($calculatedValue)) { + // Numeric value + $num = pack('d', $calculatedValue); + } elseif (is_string($calculatedValue)) { + if (array_key_exists($calculatedValue, PHPExcel_Cell_DataType::getErrorCodes())) { + // Error value + $num = pack('CCCvCv', 0x02, 0x00, self::_mapErrorCode($calculatedValue), 0x00, 0x00, 0xFFFF); + } elseif ($calculatedValue === '') { + // Empty string (and BIFF8) + $num = pack('CCCvCv', 0x03, 0x00, 0x00, 0x00, 0x00, 0xFFFF); + } else { + // Non-empty string value (or empty string BIFF5) + $stringValue = $calculatedValue; + $num = pack('CCCvCv', 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFF); + } + } else { + // We are really not supposed to reach here + $num = pack('d', 0x00); + } + } else { + $num = pack('d', 0x00); + } + + $grbit = 0x03; // Option flags + $unknown = 0x0000; // Must be zero + + // Strip the '=' or '@' sign at the beginning of the formula string + if ($formula{0} == '=') { + $formula = substr($formula,1); + } else { + // Error handling + $this->_writeString($row, $col, 'Unrecognised character for formula'); + return -1; + } + + // Parse the formula using the parser in Parser.php + try { + $error = $this->_parser->parse($formula); + $formula = $this->_parser->toReversePolish(); + + $formlen = strlen($formula); // Length of the binary string + $length = 0x16 + $formlen; // Length of the record data + + $header = pack("vv", $record, $length); + + $data = pack("vvv", $row, $col, $xfIndex) + . $num + . pack("vVv", $grbit, $unknown, $formlen); + $this->_append($header . $data . $formula); + + // Append also a STRING record if necessary + if ($stringValue !== null) { + $this->_writeStringRecord($stringValue); + } + + return 0; + + } catch (PHPExcel_Exception $e) { + // do nothing + } + + } + + /** + * Write a STRING record. This + * + * @param string $stringValue + */ + private function _writeStringRecord($stringValue) + { + $record = 0x0207; // Record identifier + $data = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($stringValue); + + $length = strlen($data); + $header = pack('vv', $record, $length); + + $this->_append($header . $data); + } + + /** + * Write a hyperlink. + * This is comprised of two elements: the visible label and + * the invisible link. The visible label is the same as the link unless an + * alternative string is specified. The label is written using the + * _writeString() method. Therefore the 255 characters string limit applies. + * $string and $format are optional. + * + * The hyperlink can be to a http, ftp, mail, internal sheet (not yet), or external + * directory url. + * + * Returns 0 : normal termination + * -2 : row or column out of range + * -3 : long string truncated to 255 chars + * + * @param integer $row Row + * @param integer $col Column + * @param string $url URL string + * @return integer + */ + private function _writeUrl($row, $col, $url) + { + // Add start row and col to arg list + return($this->_writeUrlRange($row, $col, $row, $col, $url)); + } + + /** + * This is the more general form of _writeUrl(). It allows a hyperlink to be + * written to a range of cells. This function also decides the type of hyperlink + * to be written. These are either, Web (http, ftp, mailto), Internal + * (Sheet1!A1) or external ('c:\temp\foo.xls#Sheet1!A1'). + * + * @access private + * @see _writeUrl() + * @param integer $row1 Start row + * @param integer $col1 Start column + * @param integer $row2 End row + * @param integer $col2 End column + * @param string $url URL string + * @return integer + */ + function _writeUrlRange($row1, $col1, $row2, $col2, $url) + { + // Check for internal/external sheet links or default to web link + if (preg_match('[^internal:]', $url)) { + return($this->_writeUrlInternal($row1, $col1, $row2, $col2, $url)); + } + if (preg_match('[^external:]', $url)) { + return($this->_writeUrlExternal($row1, $col1, $row2, $col2, $url)); + } + return($this->_writeUrlWeb($row1, $col1, $row2, $col2, $url)); + } + + /** + * Used to write http, ftp and mailto hyperlinks. + * The link type ($options) is 0x03 is the same as absolute dir ref without + * sheet. However it is differentiated by the $unknown2 data stream. + * + * @access private + * @see _writeUrl() + * @param integer $row1 Start row + * @param integer $col1 Start column + * @param integer $row2 End row + * @param integer $col2 End column + * @param string $url URL string + * @return integer + */ + function _writeUrlWeb($row1, $col1, $row2, $col2, $url) + { + $record = 0x01B8; // Record identifier + $length = 0x00000; // Bytes to follow + + // Pack the undocumented parts of the hyperlink stream + $unknown1 = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000"); + $unknown2 = pack("H*", "E0C9EA79F9BACE118C8200AA004BA90B"); + + // Pack the option flags + $options = pack("V", 0x03); + + // Convert URL to a null terminated wchar string + $url = join("\0", preg_split("''", $url, -1, PREG_SPLIT_NO_EMPTY)); + $url = $url . "\0\0\0"; + + // Pack the length of the URL + $url_len = pack("V", strlen($url)); + + // Calculate the data length + $length = 0x34 + strlen($url); + + // Pack the header data + $header = pack("vv", $record, $length); + $data = pack("vvvv", $row1, $row2, $col1, $col2); + + // Write the packed data + $this->_append($header . $data . + $unknown1 . $options . + $unknown2 . $url_len . $url); + return 0; + } + + /** + * Used to write internal reference hyperlinks such as "Sheet1!A1". + * + * @access private + * @see _writeUrl() + * @param integer $row1 Start row + * @param integer $col1 Start column + * @param integer $row2 End row + * @param integer $col2 End column + * @param string $url URL string + * @return integer + */ + function _writeUrlInternal($row1, $col1, $row2, $col2, $url) + { + $record = 0x01B8; // Record identifier + $length = 0x00000; // Bytes to follow + + // Strip URL type + $url = preg_replace('/^internal:/', '', $url); + + // Pack the undocumented parts of the hyperlink stream + $unknown1 = pack("H*", "D0C9EA79F9BACE118C8200AA004BA90B02000000"); + + // Pack the option flags + $options = pack("V", 0x08); + + // Convert the URL type and to a null terminated wchar string + $url .= "\0"; + + // character count + $url_len = PHPExcel_Shared_String::CountCharacters($url); + $url_len = pack('V', $url_len); + + $url = PHPExcel_Shared_String::ConvertEncoding($url, 'UTF-16LE', 'UTF-8'); + + // Calculate the data length + $length = 0x24 + strlen($url); + + // Pack the header data + $header = pack("vv", $record, $length); + $data = pack("vvvv", $row1, $row2, $col1, $col2); + + // Write the packed data + $this->_append($header . $data . + $unknown1 . $options . + $url_len . $url); + return 0; + } + + /** + * Write links to external directory names such as 'c:\foo.xls', + * c:\foo.xls#Sheet1!A1', '../../foo.xls'. and '../../foo.xls#Sheet1!A1'. + * + * Note: Excel writes some relative links with the $dir_long string. We ignore + * these cases for the sake of simpler code. + * + * @access private + * @see _writeUrl() + * @param integer $row1 Start row + * @param integer $col1 Start column + * @param integer $row2 End row + * @param integer $col2 End column + * @param string $url URL string + * @return integer + */ + function _writeUrlExternal($row1, $col1, $row2, $col2, $url) + { + // Network drives are different. We will handle them separately + // MS/Novell network drives and shares start with \\ + if (preg_match('[^external:\\\\]', $url)) { + return; //($this->_writeUrlExternal_net($row1, $col1, $row2, $col2, $url, $str, $format)); + } + + $record = 0x01B8; // Record identifier + $length = 0x00000; // Bytes to follow + + // Strip URL type and change Unix dir separator to Dos style (if needed) + // + $url = preg_replace('/^external:/', '', $url); + $url = preg_replace('/\//', "\\", $url); + + // Determine if the link is relative or absolute: + // relative if link contains no dir separator, "somefile.xls" + // relative if link starts with up-dir, "..\..\somefile.xls" + // otherwise, absolute + + $absolute = 0x00; // relative path + if ( preg_match('/^[A-Z]:/', $url) ) { + $absolute = 0x02; // absolute path on Windows, e.g. C:\... + } + $link_type = 0x01 | $absolute; + + // Determine if the link contains a sheet reference and change some of the + // parameters accordingly. + // Split the dir name and sheet name (if it exists) + $dir_long = $url; + if (preg_match("/\#/", $url)) { + $link_type |= 0x08; + } + + + // Pack the link type + $link_type = pack("V", $link_type); + + // Calculate the up-level dir count e.g.. (..\..\..\ == 3) + $up_count = preg_match_all("/\.\.\\\/", $dir_long, $useless); + $up_count = pack("v", $up_count); + + // Store the short dos dir name (null terminated) + $dir_short = preg_replace("/\.\.\\\/", '', $dir_long) . "\0"; + + // Store the long dir name as a wchar string (non-null terminated) + $dir_long = $dir_long . "\0"; + + // Pack the lengths of the dir strings + $dir_short_len = pack("V", strlen($dir_short) ); + $dir_long_len = pack("V", strlen($dir_long) ); + $stream_len = pack("V", 0);//strlen($dir_long) + 0x06); + + // Pack the undocumented parts of the hyperlink stream + $unknown1 = pack("H*",'D0C9EA79F9BACE118C8200AA004BA90B02000000' ); + $unknown2 = pack("H*",'0303000000000000C000000000000046' ); + $unknown3 = pack("H*",'FFFFADDE000000000000000000000000000000000000000'); + $unknown4 = pack("v", 0x03 ); + + // Pack the main data stream + $data = pack("vvvv", $row1, $row2, $col1, $col2) . + $unknown1 . + $link_type . + $unknown2 . + $up_count . + $dir_short_len. + $dir_short . + $unknown3 . + $stream_len ;/*. + $dir_long_len . + $unknown4 . + $dir_long . + $sheet_len . + $sheet ;*/ + + // Pack the header data + $length = strlen($data); + $header = pack("vv", $record, $length); + + // Write the packed data + $this->_append($header. $data); + return 0; + } + + /** + * This method is used to set the height and format for a row. + * + * @param integer $row The row to set + * @param integer $height Height we are giving to the row. + * Use null to set XF without setting height + * @param integer $xfIndex The optional cell style Xf index to apply to the columns + * @param bool $hidden The optional hidden attribute + * @param integer $level The optional outline level for row, in range [0,7] + */ + private function _writeRow($row, $height, $xfIndex, $hidden = false, $level = 0) + { + $record = 0x0208; // Record identifier + $length = 0x0010; // Number of bytes to follow + + $colMic = 0x0000; // First defined column + $colMac = 0x0000; // Last defined column + $irwMac = 0x0000; // Used by Excel to optimise loading + $reserved = 0x0000; // Reserved + $grbit = 0x0000; // Option flags + $ixfe = $xfIndex; + + if ( $height < 0 ){ + $height = null; + } + + // Use _writeRow($row, null, $XF) to set XF format without setting height + if ($height != null) { + $miyRw = $height * 20; // row height + } else { + $miyRw = 0xff; // default row height is 256 + } + + // Set the options flags. fUnsynced is used to show that the font and row + // heights are not compatible. This is usually the case for WriteExcel. + // The collapsed flag 0x10 doesn't seem to be used to indicate that a row + // is collapsed. Instead it is used to indicate that the previous row is + // collapsed. The zero height flag, 0x20, is used to collapse a row. + + $grbit |= $level; + if ($hidden) { + $grbit |= 0x0020; + } + if ($height !== null) { + $grbit |= 0x0040; // fUnsynced + } + if ($xfIndex !== 0xF) { + $grbit |= 0x0080; + } + $grbit |= 0x0100; + + $header = pack("vv", $record, $length); + $data = pack("vvvvvvvv", $row, $colMic, $colMac, $miyRw, + $irwMac,$reserved, $grbit, $ixfe); + $this->_append($header.$data); + } + + /** + * Writes Excel DIMENSIONS to define the area in which there is data. + */ + private function _writeDimensions() + { + $record = 0x0200; // Record identifier + + $length = 0x000E; + $data = pack('VVvvv' + , $this->_firstRowIndex + , $this->_lastRowIndex + 1 + , $this->_firstColumnIndex + , $this->_lastColumnIndex + 1 + , 0x0000 // reserved + ); + + $header = pack("vv", $record, $length); + $this->_append($header.$data); + } + + /** + * Write BIFF record Window2. + */ + private function _writeWindow2() + { + $record = 0x023E; // Record identifier + $length = 0x0012; + + $grbit = 0x00B6; // Option flags + $rwTop = 0x0000; // Top row visible in window + $colLeft = 0x0000; // Leftmost column visible in window + + + // The options flags that comprise $grbit + $fDspFmla = 0; // 0 - bit + $fDspGrid = $this->_phpSheet->getShowGridlines() ? 1 : 0; // 1 + $fDspRwCol = $this->_phpSheet->getShowRowColHeaders() ? 1 : 0; // 2 + $fFrozen = $this->_phpSheet->getFreezePane() ? 1 : 0; // 3 + $fDspZeros = 1; // 4 + $fDefaultHdr = 1; // 5 + $fArabic = $this->_phpSheet->getRightToLeft() ? 1 : 0; // 6 + $fDspGuts = $this->_outline_on; // 7 + $fFrozenNoSplit = 0; // 0 - bit + // no support in PHPExcel for selected sheet, therefore sheet is only selected if it is the active sheet + $fSelected = ($this->_phpSheet === $this->_phpSheet->getParent()->getActiveSheet()) ? 1 : 0; + $fPaged = 1; // 2 + $fPageBreakPreview = $this->_phpSheet->getSheetView()->getView() === PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_BREAK_PREVIEW; + + $grbit = $fDspFmla; + $grbit |= $fDspGrid << 1; + $grbit |= $fDspRwCol << 2; + $grbit |= $fFrozen << 3; + $grbit |= $fDspZeros << 4; + $grbit |= $fDefaultHdr << 5; + $grbit |= $fArabic << 6; + $grbit |= $fDspGuts << 7; + $grbit |= $fFrozenNoSplit << 8; + $grbit |= $fSelected << 9; + $grbit |= $fPaged << 10; + $grbit |= $fPageBreakPreview << 11; + + $header = pack("vv", $record, $length); + $data = pack("vvv", $grbit, $rwTop, $colLeft); + + // FIXME !!! + $rgbHdr = 0x0040; // Row/column heading and gridline color index + $zoom_factor_page_break = ($fPageBreakPreview? $this->_phpSheet->getSheetView()->getZoomScale() : 0x0000); + $zoom_factor_normal = $this->_phpSheet->getSheetView()->getZoomScaleNormal(); + + $data .= pack("vvvvV", $rgbHdr, 0x0000, $zoom_factor_page_break, $zoom_factor_normal, 0x00000000); + + $this->_append($header.$data); + } + + /** + * Write BIFF record DEFAULTROWHEIGHT. + */ + private function _writeDefaultRowHeight() + { + $defaultRowHeight = $this->_phpSheet->getDefaultRowDimension()->getRowHeight(); + + if ($defaultRowHeight < 0) { + return; + } + + // convert to twips + $defaultRowHeight = (int) 20 * $defaultRowHeight; + + $record = 0x0225; // Record identifier + $length = 0x0004; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("vv", 1, $defaultRowHeight); + $this->_append($header . $data); + } + + /** + * Write BIFF record DEFCOLWIDTH if COLINFO records are in use. + */ + private function _writeDefcol() + { + $defaultColWidth = 8; + + $record = 0x0055; // Record identifier + $length = 0x0002; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("v", $defaultColWidth); + $this->_append($header . $data); + } + + /** + * Write BIFF record COLINFO to define column widths + * + * Note: The SDK says the record length is 0x0B but Excel writes a 0x0C + * length record. + * + * @param array $col_array This is the only parameter received and is composed of the following: + * 0 => First formatted column, + * 1 => Last formatted column, + * 2 => Col width (8.43 is Excel default), + * 3 => The optional XF format of the column, + * 4 => Option flags. + * 5 => Optional outline level + */ + private function _writeColinfo($col_array) + { + if (isset($col_array[0])) { + $colFirst = $col_array[0]; + } + if (isset($col_array[1])) { + $colLast = $col_array[1]; + } + if (isset($col_array[2])) { + $coldx = $col_array[2]; + } else { + $coldx = 8.43; + } + if (isset($col_array[3])) { + $xfIndex = $col_array[3]; + } else { + $xfIndex = 15; + } + if (isset($col_array[4])) { + $grbit = $col_array[4]; + } else { + $grbit = 0; + } + if (isset($col_array[5])) { + $level = $col_array[5]; + } else { + $level = 0; + } + $record = 0x007D; // Record identifier + $length = 0x000C; // Number of bytes to follow + + $coldx *= 256; // Convert to units of 1/256 of a char + + $ixfe = $xfIndex; + $reserved = 0x0000; // Reserved + + $level = max(0, min($level, 7)); + $grbit |= $level << 8; + + $header = pack("vv", $record, $length); + $data = pack("vvvvvv", $colFirst, $colLast, $coldx, + $ixfe, $grbit, $reserved); + $this->_append($header.$data); + } + + /** + * Write BIFF record SELECTION. + */ + private function _writeSelection() + { + // look up the selected cell range + $selectedCells = $this->_phpSheet->getSelectedCells(); + $selectedCells = PHPExcel_Cell::splitRange($this->_phpSheet->getSelectedCells()); + $selectedCells = $selectedCells[0]; + if (count($selectedCells) == 2) { + list($first, $last) = $selectedCells; + } else { + $first = $selectedCells[0]; + $last = $selectedCells[0]; + } + + list($colFirst, $rwFirst) = PHPExcel_Cell::coordinateFromString($first); + $colFirst = PHPExcel_Cell::columnIndexFromString($colFirst) - 1; // base 0 column index + --$rwFirst; // base 0 row index + + list($colLast, $rwLast) = PHPExcel_Cell::coordinateFromString($last); + $colLast = PHPExcel_Cell::columnIndexFromString($colLast) - 1; // base 0 column index + --$rwLast; // base 0 row index + + // make sure we are not out of bounds + $colFirst = min($colFirst, 255); + $colLast = min($colLast, 255); + + $rwFirst = min($rwFirst, 65535); + $rwLast = min($rwLast, 65535); + + $record = 0x001D; // Record identifier + $length = 0x000F; // Number of bytes to follow + + $pnn = $this->_active_pane; // Pane position + $rwAct = $rwFirst; // Active row + $colAct = $colFirst; // Active column + $irefAct = 0; // Active cell ref + $cref = 1; // Number of refs + + if (!isset($rwLast)) { + $rwLast = $rwFirst; // Last row in reference + } + if (!isset($colLast)) { + $colLast = $colFirst; // Last col in reference + } + + // Swap last row/col for first row/col as necessary + if ($rwFirst > $rwLast) { + list($rwFirst, $rwLast) = array($rwLast, $rwFirst); + } + + if ($colFirst > $colLast) { + list($colFirst, $colLast) = array($colLast, $colFirst); + } + + $header = pack("vv", $record, $length); + $data = pack("CvvvvvvCC", $pnn, $rwAct, $colAct, + $irefAct, $cref, + $rwFirst, $rwLast, + $colFirst, $colLast); + $this->_append($header . $data); + } + + /** + * Store the MERGEDCELLS records for all ranges of merged cells + */ + private function _writeMergedCells() + { + $mergeCells = $this->_phpSheet->getMergeCells(); + $countMergeCells = count($mergeCells); + + if ($countMergeCells == 0) { + return; + } + + // maximum allowed number of merged cells per record + $maxCountMergeCellsPerRecord = 1027; + + // record identifier + $record = 0x00E5; + + // counter for total number of merged cells treated so far by the writer + $i = 0; + + // counter for number of merged cells written in record currently being written + $j = 0; + + // initialize record data + $recordData = ''; + + // loop through the merged cells + foreach ($mergeCells as $mergeCell) { + ++$i; + ++$j; + + // extract the row and column indexes + $range = PHPExcel_Cell::splitRange($mergeCell); + list($first, $last) = $range[0]; + list($firstColumn, $firstRow) = PHPExcel_Cell::coordinateFromString($first); + list($lastColumn, $lastRow) = PHPExcel_Cell::coordinateFromString($last); + + $recordData .= pack('vvvv', $firstRow - 1, $lastRow - 1, PHPExcel_Cell::columnIndexFromString($firstColumn) - 1, PHPExcel_Cell::columnIndexFromString($lastColumn) - 1); + + // flush record if we have reached limit for number of merged cells, or reached final merged cell + if ($j == $maxCountMergeCellsPerRecord or $i == $countMergeCells) { + $recordData = pack('v', $j) . $recordData; + $length = strlen($recordData); + $header = pack('vv', $record, $length); + $this->_append($header . $recordData); + + // initialize for next record, if any + $recordData = ''; + $j = 0; + } + } + } + + /** + * Write SHEETLAYOUT record + */ + private function _writeSheetLayout() + { + if (!$this->_phpSheet->isTabColorSet()) { + return; + } + + $recordData = pack( + 'vvVVVvv' + , 0x0862 + , 0x0000 // unused + , 0x00000000 // unused + , 0x00000000 // unused + , 0x00000014 // size of record data + , $this->_colors[$this->_phpSheet->getTabColor()->getRGB()] // color index + , 0x0000 // unused + ); + + $length = strlen($recordData); + + $record = 0x0862; // Record identifier + $header = pack('vv', $record, $length); + $this->_append($header . $recordData); + } + + /** + * Write SHEETPROTECTION + */ + private function _writeSheetProtection() + { + // record identifier + $record = 0x0867; + + // prepare options + $options = (int) !$this->_phpSheet->getProtection()->getObjects() + | (int) !$this->_phpSheet->getProtection()->getScenarios() << 1 + | (int) !$this->_phpSheet->getProtection()->getFormatCells() << 2 + | (int) !$this->_phpSheet->getProtection()->getFormatColumns() << 3 + | (int) !$this->_phpSheet->getProtection()->getFormatRows() << 4 + | (int) !$this->_phpSheet->getProtection()->getInsertColumns() << 5 + | (int) !$this->_phpSheet->getProtection()->getInsertRows() << 6 + | (int) !$this->_phpSheet->getProtection()->getInsertHyperlinks() << 7 + | (int) !$this->_phpSheet->getProtection()->getDeleteColumns() << 8 + | (int) !$this->_phpSheet->getProtection()->getDeleteRows() << 9 + | (int) !$this->_phpSheet->getProtection()->getSelectLockedCells() << 10 + | (int) !$this->_phpSheet->getProtection()->getSort() << 11 + | (int) !$this->_phpSheet->getProtection()->getAutoFilter() << 12 + | (int) !$this->_phpSheet->getProtection()->getPivotTables() << 13 + | (int) !$this->_phpSheet->getProtection()->getSelectUnlockedCells() << 14 ; + + // record data + $recordData = pack( + 'vVVCVVvv' + , 0x0867 // repeated record identifier + , 0x0000 // not used + , 0x0000 // not used + , 0x00 // not used + , 0x01000200 // unknown data + , 0xFFFFFFFF // unknown data + , $options // options + , 0x0000 // not used + ); + + $length = strlen($recordData); + $header = pack('vv', $record, $length); + + $this->_append($header . $recordData); + } + + /** + * Write BIFF record RANGEPROTECTION + * + * Openoffice.org's Documentaion of the Microsoft Excel File Format uses term RANGEPROTECTION for these records + * Microsoft Office Excel 97-2007 Binary File Format Specification uses term FEAT for these records + */ + private function _writeRangeProtection() + { + foreach ($this->_phpSheet->getProtectedCells() as $range => $password) { + // number of ranges, e.g. 'A1:B3 C20:D25' + $cellRanges = explode(' ', $range); + $cref = count($cellRanges); + + $recordData = pack( + 'vvVVvCVvVv', + 0x0868, + 0x00, + 0x0000, + 0x0000, + 0x02, + 0x0, + 0x0000, + $cref, + 0x0000, + 0x00 + ); + + foreach ($cellRanges as $cellRange) { + $recordData .= $this->_writeBIFF8CellRangeAddressFixed($cellRange); + } + + // the rgbFeat structure + $recordData .= pack( + 'VV', + 0x0000, + hexdec($password) + ); + + $recordData .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong('p' . md5($recordData)); + + $length = strlen($recordData); + + $record = 0x0868; // Record identifier + $header = pack("vv", $record, $length); + $this->_append($header . $recordData); + } + } + + /** + * Write BIFF record EXTERNCOUNT to indicate the number of external sheet + * references in a worksheet. + * + * Excel only stores references to external sheets that are used in formulas. + * For simplicity we store references to all the sheets in the workbook + * regardless of whether they are used or not. This reduces the overall + * complexity and eliminates the need for a two way dialogue between the formula + * parser the worksheet objects. + * + * @param integer $count The number of external sheet references in this worksheet + */ + private function _writeExterncount($count) + { + $record = 0x0016; // Record identifier + $length = 0x0002; // Number of bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("v", $count); + $this->_append($header . $data); + } + + /** + * Writes the Excel BIFF EXTERNSHEET record. These references are used by + * formulas. A formula references a sheet name via an index. Since we store a + * reference to all of the external worksheets the EXTERNSHEET index is the same + * as the worksheet index. + * + * @param string $sheetname The name of a external worksheet + */ + private function _writeExternsheet($sheetname) + { + $record = 0x0017; // Record identifier + + // References to the current sheet are encoded differently to references to + // external sheets. + // + if ($this->_phpSheet->getTitle() == $sheetname) { + $sheetname = ''; + $length = 0x02; // The following 2 bytes + $cch = 1; // The following byte + $rgch = 0x02; // Self reference + } else { + $length = 0x02 + strlen($sheetname); + $cch = strlen($sheetname); + $rgch = 0x03; // Reference to a sheet in the current workbook + } + + $header = pack("vv", $record, $length); + $data = pack("CC", $cch, $rgch); + $this->_append($header . $data . $sheetname); + } + + /** + * Writes the Excel BIFF PANE record. + * The panes can either be frozen or thawed (unfrozen). + * Frozen panes are specified in terms of an integer number of rows and columns. + * Thawed panes are specified in terms of Excel's units for rows and columns. + */ + private function _writePanes() + { + $panes = array(); + if ($freezePane = $this->_phpSheet->getFreezePane()) { + list($column, $row) = PHPExcel_Cell::coordinateFromString($freezePane); + $panes[0] = $row - 1; + $panes[1] = PHPExcel_Cell::columnIndexFromString($column) - 1; + } else { + // thaw panes + return; + } + + $y = isset($panes[0]) ? $panes[0] : null; + $x = isset($panes[1]) ? $panes[1] : null; + $rwTop = isset($panes[2]) ? $panes[2] : null; + $colLeft = isset($panes[3]) ? $panes[3] : null; + if (count($panes) > 4) { // if Active pane was received + $pnnAct = $panes[4]; + } else { + $pnnAct = null; + } + $record = 0x0041; // Record identifier + $length = 0x000A; // Number of bytes to follow + + // Code specific to frozen or thawed panes. + if ($this->_phpSheet->getFreezePane()) { + // Set default values for $rwTop and $colLeft + if (!isset($rwTop)) { + $rwTop = $y; + } + if (!isset($colLeft)) { + $colLeft = $x; + } + } else { + // Set default values for $rwTop and $colLeft + if (!isset($rwTop)) { + $rwTop = 0; + } + if (!isset($colLeft)) { + $colLeft = 0; + } + + // Convert Excel's row and column units to the internal units. + // The default row height is 12.75 + // The default column width is 8.43 + // The following slope and intersection values were interpolated. + // + $y = 20*$y + 255; + $x = 113.879*$x + 390; + } + + + // Determine which pane should be active. There is also the undocumented + // option to override this should it be necessary: may be removed later. + // + if (!isset($pnnAct)) { + if ($x != 0 && $y != 0) { + $pnnAct = 0; // Bottom right + } + if ($x != 0 && $y == 0) { + $pnnAct = 1; // Top right + } + if ($x == 0 && $y != 0) { + $pnnAct = 2; // Bottom left + } + if ($x == 0 && $y == 0) { + $pnnAct = 3; // Top left + } + } + + $this->_active_pane = $pnnAct; // Used in _writeSelection + + $header = pack("vv", $record, $length); + $data = pack("vvvvv", $x, $y, $rwTop, $colLeft, $pnnAct); + $this->_append($header . $data); + } + + /** + * Store the page setup SETUP BIFF record. + */ + private function _writeSetup() + { + $record = 0x00A1; // Record identifier + $length = 0x0022; // Number of bytes to follow + + $iPaperSize = $this->_phpSheet->getPageSetup()->getPaperSize(); // Paper size + + $iScale = $this->_phpSheet->getPageSetup()->getScale() ? + $this->_phpSheet->getPageSetup()->getScale() : 100; // Print scaling factor + + $iPageStart = 0x01; // Starting page number + $iFitWidth = (int) $this->_phpSheet->getPageSetup()->getFitToWidth(); // Fit to number of pages wide + $iFitHeight = (int) $this->_phpSheet->getPageSetup()->getFitToHeight(); // Fit to number of pages high + $grbit = 0x00; // Option flags + $iRes = 0x0258; // Print resolution + $iVRes = 0x0258; // Vertical print resolution + + $numHdr = $this->_phpSheet->getPageMargins()->getHeader(); // Header Margin + + $numFtr = $this->_phpSheet->getPageMargins()->getFooter(); // Footer Margin + $iCopies = 0x01; // Number of copies + + $fLeftToRight = 0x0; // Print over then down + + // Page orientation + $fLandscape = ($this->_phpSheet->getPageSetup()->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) ? + 0x0 : 0x1; + + $fNoPls = 0x0; // Setup not read from printer + $fNoColor = 0x0; // Print black and white + $fDraft = 0x0; // Print draft quality + $fNotes = 0x0; // Print notes + $fNoOrient = 0x0; // Orientation not set + $fUsePage = 0x0; // Use custom starting page + + $grbit = $fLeftToRight; + $grbit |= $fLandscape << 1; + $grbit |= $fNoPls << 2; + $grbit |= $fNoColor << 3; + $grbit |= $fDraft << 4; + $grbit |= $fNotes << 5; + $grbit |= $fNoOrient << 6; + $grbit |= $fUsePage << 7; + + $numHdr = pack("d", $numHdr); + $numFtr = pack("d", $numFtr); + if (self::getByteOrder()) { // if it's Big Endian + $numHdr = strrev($numHdr); + $numFtr = strrev($numFtr); + } + + $header = pack("vv", $record, $length); + $data1 = pack("vvvvvvvv", $iPaperSize, + $iScale, + $iPageStart, + $iFitWidth, + $iFitHeight, + $grbit, + $iRes, + $iVRes); + $data2 = $numHdr.$numFtr; + $data3 = pack("v", $iCopies); + $this->_append($header . $data1 . $data2 . $data3); + } + + /** + * Store the header caption BIFF record. + */ + private function _writeHeader() + { + $record = 0x0014; // Record identifier + + /* removing for now + // need to fix character count (multibyte!) + if (strlen($this->_phpSheet->getHeaderFooter()->getOddHeader()) <= 255) { + $str = $this->_phpSheet->getHeaderFooter()->getOddHeader(); // header string + } else { + $str = ''; + } + */ + + $recordData = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddHeader()); + $length = strlen($recordData); + + $header = pack("vv", $record, $length); + + $this->_append($header . $recordData); + } + + /** + * Store the footer caption BIFF record. + */ + private function _writeFooter() + { + $record = 0x0015; // Record identifier + + /* removing for now + // need to fix character count (multibyte!) + if (strlen($this->_phpSheet->getHeaderFooter()->getOddFooter()) <= 255) { + $str = $this->_phpSheet->getHeaderFooter()->getOddFooter(); + } else { + $str = ''; + } + */ + + $recordData = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($this->_phpSheet->getHeaderFooter()->getOddFooter()); + $length = strlen($recordData); + + $header = pack("vv", $record, $length); + + $this->_append($header . $recordData); + } + + /** + * Store the horizontal centering HCENTER BIFF record. + * + * @access private + */ + private function _writeHcenter() + { + $record = 0x0083; // Record identifier + $length = 0x0002; // Bytes to follow + + $fHCenter = $this->_phpSheet->getPageSetup()->getHorizontalCentered() ? 1 : 0; // Horizontal centering + + $header = pack("vv", $record, $length); + $data = pack("v", $fHCenter); + + $this->_append($header.$data); + } + + /** + * Store the vertical centering VCENTER BIFF record. + */ + private function _writeVcenter() + { + $record = 0x0084; // Record identifier + $length = 0x0002; // Bytes to follow + + $fVCenter = $this->_phpSheet->getPageSetup()->getVerticalCentered() ? 1 : 0; // Horizontal centering + + $header = pack("vv", $record, $length); + $data = pack("v", $fVCenter); + $this->_append($header . $data); + } + + /** + * Store the LEFTMARGIN BIFF record. + */ + private function _writeMarginLeft() + { + $record = 0x0026; // Record identifier + $length = 0x0008; // Bytes to follow + + $margin = $this->_phpSheet->getPageMargins()->getLeft(); // Margin in inches + + $header = pack("vv", $record, $length); + $data = pack("d", $margin); + if (self::getByteOrder()) { // if it's Big Endian + $data = strrev($data); + } + + $this->_append($header . $data); + } + + /** + * Store the RIGHTMARGIN BIFF record. + */ + private function _writeMarginRight() + { + $record = 0x0027; // Record identifier + $length = 0x0008; // Bytes to follow + + $margin = $this->_phpSheet->getPageMargins()->getRight(); // Margin in inches + + $header = pack("vv", $record, $length); + $data = pack("d", $margin); + if (self::getByteOrder()) { // if it's Big Endian + $data = strrev($data); + } + + $this->_append($header . $data); + } + + /** + * Store the TOPMARGIN BIFF record. + */ + private function _writeMarginTop() + { + $record = 0x0028; // Record identifier + $length = 0x0008; // Bytes to follow + + $margin = $this->_phpSheet->getPageMargins()->getTop(); // Margin in inches + + $header = pack("vv", $record, $length); + $data = pack("d", $margin); + if (self::getByteOrder()) { // if it's Big Endian + $data = strrev($data); + } + + $this->_append($header . $data); + } + + /** + * Store the BOTTOMMARGIN BIFF record. + */ + private function _writeMarginBottom() + { + $record = 0x0029; // Record identifier + $length = 0x0008; // Bytes to follow + + $margin = $this->_phpSheet->getPageMargins()->getBottom(); // Margin in inches + + $header = pack("vv", $record, $length); + $data = pack("d", $margin); + if (self::getByteOrder()) { // if it's Big Endian + $data = strrev($data); + } + + $this->_append($header . $data); + } + + /** + * Write the PRINTHEADERS BIFF record. + */ + private function _writePrintHeaders() + { + $record = 0x002a; // Record identifier + $length = 0x0002; // Bytes to follow + + $fPrintRwCol = $this->_print_headers; // Boolean flag + + $header = pack("vv", $record, $length); + $data = pack("v", $fPrintRwCol); + $this->_append($header . $data); + } + + /** + * Write the PRINTGRIDLINES BIFF record. Must be used in conjunction with the + * GRIDSET record. + */ + private function _writePrintGridlines() + { + $record = 0x002b; // Record identifier + $length = 0x0002; // Bytes to follow + + $fPrintGrid = $this->_phpSheet->getPrintGridlines() ? 1 : 0; // Boolean flag + + $header = pack("vv", $record, $length); + $data = pack("v", $fPrintGrid); + $this->_append($header . $data); + } + + /** + * Write the GRIDSET BIFF record. Must be used in conjunction with the + * PRINTGRIDLINES record. + */ + private function _writeGridset() + { + $record = 0x0082; // Record identifier + $length = 0x0002; // Bytes to follow + + $fGridSet = !$this->_phpSheet->getPrintGridlines(); // Boolean flag + + $header = pack("vv", $record, $length); + $data = pack("v", $fGridSet); + $this->_append($header . $data); + } + + /** + * Write the AUTOFILTERINFO BIFF record. This is used to configure the number of autofilter select used in the sheet. + */ + private function _writeAutoFilterInfo(){ + $record = 0x009D; // Record identifier + $length = 0x0002; // Bytes to follow + + $rangeBounds = PHPExcel_Cell::rangeBoundaries($this->_phpSheet->getAutoFilter()->getRange()); + $iNumFilters = 1 + $rangeBounds[1][0] - $rangeBounds[0][0]; + + $header = pack("vv", $record, $length); + $data = pack("v", $iNumFilters); + $this->_append($header . $data); + } + + /** + * Write the GUTS BIFF record. This is used to configure the gutter margins + * where Excel outline symbols are displayed. The visibility of the gutters is + * controlled by a flag in WSBOOL. + * + * @see _writeWsbool() + */ + private function _writeGuts() + { + $record = 0x0080; // Record identifier + $length = 0x0008; // Bytes to follow + + $dxRwGut = 0x0000; // Size of row gutter + $dxColGut = 0x0000; // Size of col gutter + + // determine maximum row outline level + $maxRowOutlineLevel = 0; + foreach ($this->_phpSheet->getRowDimensions() as $rowDimension) { + $maxRowOutlineLevel = max($maxRowOutlineLevel, $rowDimension->getOutlineLevel()); + } + + $col_level = 0; + + // Calculate the maximum column outline level. The equivalent calculation + // for the row outline level is carried out in _writeRow(). + $colcount = count($this->_colinfo); + for ($i = 0; $i < $colcount; ++$i) { + $col_level = max($this->_colinfo[$i][5], $col_level); + } + + // Set the limits for the outline levels (0 <= x <= 7). + $col_level = max(0, min($col_level, 7)); + + // The displayed level is one greater than the max outline levels + if ($maxRowOutlineLevel) { + ++$maxRowOutlineLevel; + } + if ($col_level) { + ++$col_level; + } + + $header = pack("vv", $record, $length); + $data = pack("vvvv", $dxRwGut, $dxColGut, $maxRowOutlineLevel, $col_level); + + $this->_append($header.$data); + } + + /** + * Write the WSBOOL BIFF record, mainly for fit-to-page. Used in conjunction + * with the SETUP record. + */ + private function _writeWsbool() + { + $record = 0x0081; // Record identifier + $length = 0x0002; // Bytes to follow + $grbit = 0x0000; + + // The only option that is of interest is the flag for fit to page. So we + // set all the options in one go. + // + // Set the option flags + $grbit |= 0x0001; // Auto page breaks visible + if ($this->_outline_style) { + $grbit |= 0x0020; // Auto outline styles + } + if ($this->_phpSheet->getShowSummaryBelow()) { + $grbit |= 0x0040; // Outline summary below + } + if ($this->_phpSheet->getShowSummaryRight()) { + $grbit |= 0x0080; // Outline summary right + } + if ($this->_phpSheet->getPageSetup()->getFitToPage()) { + $grbit |= 0x0100; // Page setup fit to page + } + if ($this->_outline_on) { + $grbit |= 0x0400; // Outline symbols displayed + } + + $header = pack("vv", $record, $length); + $data = pack("v", $grbit); + $this->_append($header . $data); + } + + /** + * Write the HORIZONTALPAGEBREAKS and VERTICALPAGEBREAKS BIFF records. + */ + private function _writeBreaks() + { + // initialize + $vbreaks = array(); + $hbreaks = array(); + + foreach ($this->_phpSheet->getBreaks() as $cell => $breakType) { + // Fetch coordinates + $coordinates = PHPExcel_Cell::coordinateFromString($cell); + + // Decide what to do by the type of break + switch ($breakType) { + case PHPExcel_Worksheet::BREAK_COLUMN: + // Add to list of vertical breaks + $vbreaks[] = PHPExcel_Cell::columnIndexFromString($coordinates[0]) - 1; + break; + + case PHPExcel_Worksheet::BREAK_ROW: + // Add to list of horizontal breaks + $hbreaks[] = $coordinates[1]; + break; + + case PHPExcel_Worksheet::BREAK_NONE: + default: + // Nothing to do + break; + } + } + + //horizontal page breaks + if (!empty($hbreaks)) { + + // Sort and filter array of page breaks + sort($hbreaks, SORT_NUMERIC); + if ($hbreaks[0] == 0) { // don't use first break if it's 0 + array_shift($hbreaks); + } + + $record = 0x001b; // Record identifier + $cbrk = count($hbreaks); // Number of page breaks + $length = 2 + 6 * $cbrk; // Bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("v", $cbrk); + + // Append each page break + foreach ($hbreaks as $hbreak) { + $data .= pack("vvv", $hbreak, 0x0000, 0x00ff); + } + + $this->_append($header . $data); + } + + // vertical page breaks + if (!empty($vbreaks)) { + + // 1000 vertical pagebreaks appears to be an internal Excel 5 limit. + // It is slightly higher in Excel 97/200, approx. 1026 + $vbreaks = array_slice($vbreaks, 0, 1000); + + // Sort and filter array of page breaks + sort($vbreaks, SORT_NUMERIC); + if ($vbreaks[0] == 0) { // don't use first break if it's 0 + array_shift($vbreaks); + } + + $record = 0x001a; // Record identifier + $cbrk = count($vbreaks); // Number of page breaks + $length = 2 + 6 * $cbrk; // Bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("v", $cbrk); + + // Append each page break + foreach ($vbreaks as $vbreak) { + $data .= pack("vvv", $vbreak, 0x0000, 0xffff); + } + + $this->_append($header . $data); + } + } + + /** + * Set the Biff PROTECT record to indicate that the worksheet is protected. + */ + private function _writeProtect() + { + // Exit unless sheet protection has been specified + if (!$this->_phpSheet->getProtection()->getSheet()) { + return; + } + + $record = 0x0012; // Record identifier + $length = 0x0002; // Bytes to follow + + $fLock = 1; // Worksheet is protected + + $header = pack("vv", $record, $length); + $data = pack("v", $fLock); + + $this->_append($header.$data); + } + + /** + * Write SCENPROTECT + */ + private function _writeScenProtect() + { + // Exit if sheet protection is not active + if (!$this->_phpSheet->getProtection()->getSheet()) { + return; + } + + // Exit if scenarios are not protected + if (!$this->_phpSheet->getProtection()->getScenarios()) { + return; + } + + $record = 0x00DD; // Record identifier + $length = 0x0002; // Bytes to follow + + $header = pack('vv', $record, $length); + $data = pack('v', 1); + + $this->_append($header . $data); + } + + /** + * Write OBJECTPROTECT + */ + private function _writeObjectProtect() + { + // Exit if sheet protection is not active + if (!$this->_phpSheet->getProtection()->getSheet()) { + return; + } + + // Exit if objects are not protected + if (!$this->_phpSheet->getProtection()->getObjects()) { + return; + } + + $record = 0x0063; // Record identifier + $length = 0x0002; // Bytes to follow + + $header = pack('vv', $record, $length); + $data = pack('v', 1); + + $this->_append($header . $data); + } + + /** + * Write the worksheet PASSWORD record. + */ + private function _writePassword() + { + // Exit unless sheet protection and password have been specified + if (!$this->_phpSheet->getProtection()->getSheet() || !$this->_phpSheet->getProtection()->getPassword()) { + return; + } + + $record = 0x0013; // Record identifier + $length = 0x0002; // Bytes to follow + + $wPassword = hexdec($this->_phpSheet->getProtection()->getPassword()); // Encoded password + + $header = pack("vv", $record, $length); + $data = pack("v", $wPassword); + + $this->_append($header . $data); + } + + /** + * Insert a 24bit bitmap image in a worksheet. + * + * @access public + * @param integer $row The row we are going to insert the bitmap into + * @param integer $col The column we are going to insert the bitmap into + * @param mixed $bitmap The bitmap filename or GD-image resource + * @param integer $x The horizontal position (offset) of the image inside the cell. + * @param integer $y The vertical position (offset) of the image inside the cell. + * @param float $scale_x The horizontal scale + * @param float $scale_y The vertical scale + */ + function insertBitmap($row, $col, $bitmap, $x = 0, $y = 0, $scale_x = 1, $scale_y = 1) + { + $bitmap_array = (is_resource($bitmap) ? $this->_processBitmapGd($bitmap) : $this->_processBitmap($bitmap)); + list($width, $height, $size, $data) = $bitmap_array; //$this->_processBitmap($bitmap); + + // Scale the frame of the image. + $width *= $scale_x; + $height *= $scale_y; + + // Calculate the vertices of the image and write the OBJ record + $this->_positionImage($col, $row, $x, $y, $width, $height); + + // Write the IMDATA record to store the bitmap data + $record = 0x007f; + $length = 8 + $size; + $cf = 0x09; + $env = 0x01; + $lcb = $size; + + $header = pack("vvvvV", $record, $length, $cf, $env, $lcb); + $this->_append($header.$data); + } + + /** + * Calculate the vertices that define the position of the image as required by + * the OBJ record. + * + * +------------+------------+ + * | A | B | + * +-----+------------+------------+ + * | |(x1,y1) | | + * | 1 |(A1)._______|______ | + * | | | | | + * | | | | | + * +-----+----| BITMAP |-----+ + * | | | | | + * | 2 | |______________. | + * | | | (B2)| + * | | | (x2,y2)| + * +---- +------------+------------+ + * + * Example of a bitmap that covers some of the area from cell A1 to cell B2. + * + * Based on the width and height of the bitmap we need to calculate 8 vars: + * $col_start, $row_start, $col_end, $row_end, $x1, $y1, $x2, $y2. + * The width and height of the cells are also variable and have to be taken into + * account. + * The values of $col_start and $row_start are passed in from the calling + * function. The values of $col_end and $row_end are calculated by subtracting + * the width and height of the bitmap from the width and height of the + * underlying cells. + * The vertices are expressed as a percentage of the underlying cell width as + * follows (rhs values are in pixels): + * + * x1 = X / W *1024 + * y1 = Y / H *256 + * x2 = (X-1) / W *1024 + * y2 = (Y-1) / H *256 + * + * Where: X is distance from the left side of the underlying cell + * Y is distance from the top of the underlying cell + * W is the width of the cell + * H is the height of the cell + * The SDK incorrectly states that the height should be expressed as a + * percentage of 1024. + * + * @access private + * @param integer $col_start Col containing upper left corner of object + * @param integer $row_start Row containing top left corner of object + * @param integer $x1 Distance to left side of object + * @param integer $y1 Distance to top of object + * @param integer $width Width of image frame + * @param integer $height Height of image frame + */ + function _positionImage($col_start, $row_start, $x1, $y1, $width, $height) + { + // Initialise end cell to the same as the start cell + $col_end = $col_start; // Col containing lower right corner of object + $row_end = $row_start; // Row containing bottom right corner of object + + // Zero the specified offset if greater than the cell dimensions + if ($x1 >= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_start))) { + $x1 = 0; + } + if ($y1 >= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_start + 1)) { + $y1 = 0; + } + + $width = $width + $x1 -1; + $height = $height + $y1 -1; + + // Subtract the underlying cell widths to find the end cell of the image + while ($width >= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end))) { + $width -= PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end)); + ++$col_end; + } + + // Subtract the underlying cell heights to find the end cell of the image + while ($height >= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1)) { + $height -= PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1); + ++$row_end; + } + + // Bitmap isn't allowed to start or finish in a hidden cell, i.e. a cell + // with zero eight or width. + // + if (PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) == 0) { + return; + } + if (PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) == 0) { + return; + } + if (PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_start + 1) == 0) { + return; + } + if (PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1) == 0) { + return; + } + + // Convert the pixel values to the percentage value expected by Excel + $x1 = $x1 / PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_start)) * 1024; + $y1 = $y1 / PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_start + 1) * 256; + $x2 = $width / PHPExcel_Shared_Excel5::sizeCol($this->_phpSheet, PHPExcel_Cell::stringFromColumnIndex($col_end)) * 1024; // Distance to right side of object + $y2 = $height / PHPExcel_Shared_Excel5::sizeRow($this->_phpSheet, $row_end + 1) * 256; // Distance to bottom of object + + $this->_writeObjPicture($col_start, $x1, + $row_start, $y1, + $col_end, $x2, + $row_end, $y2); + } + + /** + * Store the OBJ record that precedes an IMDATA record. This could be generalise + * to support other Excel objects. + * + * @param integer $colL Column containing upper left corner of object + * @param integer $dxL Distance from left side of cell + * @param integer $rwT Row containing top left corner of object + * @param integer $dyT Distance from top of cell + * @param integer $colR Column containing lower right corner of object + * @param integer $dxR Distance from right of cell + * @param integer $rwB Row containing bottom right corner of object + * @param integer $dyB Distance from bottom of cell + */ + private function _writeObjPicture($colL,$dxL,$rwT,$dyT,$colR,$dxR,$rwB,$dyB) + { + $record = 0x005d; // Record identifier + $length = 0x003c; // Bytes to follow + + $cObj = 0x0001; // Count of objects in file (set to 1) + $OT = 0x0008; // Object type. 8 = Picture + $id = 0x0001; // Object ID + $grbit = 0x0614; // Option flags + + $cbMacro = 0x0000; // Length of FMLA structure + $Reserved1 = 0x0000; // Reserved + $Reserved2 = 0x0000; // Reserved + + $icvBack = 0x09; // Background colour + $icvFore = 0x09; // Foreground colour + $fls = 0x00; // Fill pattern + $fAuto = 0x00; // Automatic fill + $icv = 0x08; // Line colour + $lns = 0xff; // Line style + $lnw = 0x01; // Line weight + $fAutoB = 0x00; // Automatic border + $frs = 0x0000; // Frame style + $cf = 0x0009; // Image format, 9 = bitmap + $Reserved3 = 0x0000; // Reserved + $cbPictFmla = 0x0000; // Length of FMLA structure + $Reserved4 = 0x0000; // Reserved + $grbit2 = 0x0001; // Option flags + $Reserved5 = 0x0000; // Reserved + + + $header = pack("vv", $record, $length); + $data = pack("V", $cObj); + $data .= pack("v", $OT); + $data .= pack("v", $id); + $data .= pack("v", $grbit); + $data .= pack("v", $colL); + $data .= pack("v", $dxL); + $data .= pack("v", $rwT); + $data .= pack("v", $dyT); + $data .= pack("v", $colR); + $data .= pack("v", $dxR); + $data .= pack("v", $rwB); + $data .= pack("v", $dyB); + $data .= pack("v", $cbMacro); + $data .= pack("V", $Reserved1); + $data .= pack("v", $Reserved2); + $data .= pack("C", $icvBack); + $data .= pack("C", $icvFore); + $data .= pack("C", $fls); + $data .= pack("C", $fAuto); + $data .= pack("C", $icv); + $data .= pack("C", $lns); + $data .= pack("C", $lnw); + $data .= pack("C", $fAutoB); + $data .= pack("v", $frs); + $data .= pack("V", $cf); + $data .= pack("v", $Reserved3); + $data .= pack("v", $cbPictFmla); + $data .= pack("v", $Reserved4); + $data .= pack("v", $grbit2); + $data .= pack("V", $Reserved5); + + $this->_append($header . $data); + } + + /** + * Convert a GD-image into the internal format. + * + * @access private + * @param resource $image The image to process + * @return array Array with data and properties of the bitmap + */ + function _processBitmapGd($image) { + $width = imagesx($image); + $height = imagesy($image); + + $data = pack("Vvvvv", 0x000c, $width, $height, 0x01, 0x18); + for ($j=$height; $j--; ) { + for ($i=0; $i < $width; ++$i) { + $color = imagecolorsforindex($image, imagecolorat($image, $i, $j)); + foreach (array("red", "green", "blue") as $key) { + $color[$key] = $color[$key] + round((255 - $color[$key]) * $color["alpha"] / 127); + } + $data .= chr($color["blue"]) . chr($color["green"]) . chr($color["red"]); + } + if (3*$width % 4) { + $data .= str_repeat("\x00", 4 - 3*$width % 4); + } + } + + return array($width, $height, strlen($data), $data); + } + + /** + * Convert a 24 bit bitmap into the modified internal format used by Windows. + * This is described in BITMAPCOREHEADER and BITMAPCOREINFO structures in the + * MSDN library. + * + * @access private + * @param string $bitmap The bitmap to process + * @return array Array with data and properties of the bitmap + */ + function _processBitmap($bitmap) + { + // Open file. + $bmp_fd = @fopen($bitmap,"rb"); + if (!$bmp_fd) { + throw new PHPExcel_Writer_Exception("Couldn't import $bitmap"); + } + + // Slurp the file into a string. + $data = fread($bmp_fd, filesize($bitmap)); + + // Check that the file is big enough to be a bitmap. + if (strlen($data) <= 0x36) { + throw new PHPExcel_Writer_Exception("$bitmap doesn't contain enough data.\n"); + } + + // The first 2 bytes are used to identify the bitmap. + $identity = unpack("A2ident", $data); + if ($identity['ident'] != "BM") { + throw new PHPExcel_Writer_Exception("$bitmap doesn't appear to be a valid bitmap image.\n"); + } + + // Remove bitmap data: ID. + $data = substr($data, 2); + + // Read and remove the bitmap size. This is more reliable than reading + // the data size at offset 0x22. + // + $size_array = unpack("Vsa", substr($data, 0, 4)); + $size = $size_array['sa']; + $data = substr($data, 4); + $size -= 0x36; // Subtract size of bitmap header. + $size += 0x0C; // Add size of BIFF header. + + // Remove bitmap data: reserved, offset, header length. + $data = substr($data, 12); + + // Read and remove the bitmap width and height. Verify the sizes. + $width_and_height = unpack("V2", substr($data, 0, 8)); + $width = $width_and_height[1]; + $height = $width_and_height[2]; + $data = substr($data, 8); + if ($width > 0xFFFF) { + throw new PHPExcel_Writer_Exception("$bitmap: largest image width supported is 65k.\n"); + } + if ($height > 0xFFFF) { + throw new PHPExcel_Writer_Exception("$bitmap: largest image height supported is 65k.\n"); + } + + // Read and remove the bitmap planes and bpp data. Verify them. + $planes_and_bitcount = unpack("v2", substr($data, 0, 4)); + $data = substr($data, 4); + if ($planes_and_bitcount[2] != 24) { // Bitcount + throw new PHPExcel_Writer_Exception("$bitmap isn't a 24bit true color bitmap.\n"); + } + if ($planes_and_bitcount[1] != 1) { + throw new PHPExcel_Writer_Exception("$bitmap: only 1 plane supported in bitmap image.\n"); + } + + // Read and remove the bitmap compression. Verify compression. + $compression = unpack("Vcomp", substr($data, 0, 4)); + $data = substr($data, 4); + + //$compression = 0; + if ($compression['comp'] != 0) { + throw new PHPExcel_Writer_Exception("$bitmap: compression not supported in bitmap image.\n"); + } + + // Remove bitmap data: data size, hres, vres, colours, imp. colours. + $data = substr($data, 20); + + // Add the BITMAPCOREHEADER data + $header = pack("Vvvvv", 0x000c, $width, $height, 0x01, 0x18); + $data = $header . $data; + + return (array($width, $height, $size, $data)); + } + + /** + * Store the window zoom factor. This should be a reduced fraction but for + * simplicity we will store all fractions with a numerator of 100. + */ + private function _writeZoom() + { + // If scale is 100 we don't need to write a record + if ($this->_phpSheet->getSheetView()->getZoomScale() == 100) { + return; + } + + $record = 0x00A0; // Record identifier + $length = 0x0004; // Bytes to follow + + $header = pack("vv", $record, $length); + $data = pack("vv", $this->_phpSheet->getSheetView()->getZoomScale(), 100); + $this->_append($header . $data); + } + + /** + * Get Escher object + * + * @return PHPExcel_Shared_Escher + */ + public function getEscher() + { + return $this->_escher; + } + + /** + * Set Escher object + * + * @param PHPExcel_Shared_Escher $pValue + */ + public function setEscher(PHPExcel_Shared_Escher $pValue = null) + { + $this->_escher = $pValue; + } + + /** + * Write MSODRAWING record + */ + private function _writeMsoDrawing() + { + // write the Escher stream if necessary + if (isset($this->_escher)) { + $writer = new PHPExcel_Writer_Excel5_Escher($this->_escher); + $data = $writer->close(); + $spOffsets = $writer->getSpOffsets(); + $spTypes = $writer->getSpTypes(); + // write the neccesary MSODRAWING, OBJ records + + // split the Escher stream + $spOffsets[0] = 0; + $nm = count($spOffsets) - 1; // number of shapes excluding first shape + for ($i = 1; $i <= $nm; ++$i) { + // MSODRAWING record + $record = 0x00EC; // Record identifier + + // chunk of Escher stream for one shape + $dataChunk = substr($data, $spOffsets[$i -1], $spOffsets[$i] - $spOffsets[$i - 1]); + + $length = strlen($dataChunk); + $header = pack("vv", $record, $length); + + $this->_append($header . $dataChunk); + + // OBJ record + $record = 0x005D; // record identifier + $objData = ''; + + // ftCmo + if($spTypes[$i] == 0x00C9){ + // Add ftCmo (common object data) subobject + $objData .= + pack('vvvvvVVV' + , 0x0015 // 0x0015 = ftCmo + , 0x0012 // length of ftCmo data + , 0x0014 // object type, 0x0014 = filter + , $i // object id number, Excel seems to use 1-based index, local for the sheet + , 0x2101 // option flags, 0x2001 is what OpenOffice.org uses + , 0 // reserved + , 0 // reserved + , 0 // reserved + ); + + // Add ftSbs Scroll bar subobject + $objData .= pack('vv', 0x00C, 0x0014); + $objData .= pack('H*', '0000000000000000640001000A00000010000100'); + // Add ftLbsData (List box data) subobject + $objData .= pack('vv', 0x0013, 0x1FEE); + $objData .= pack('H*', '00000000010001030000020008005700'); + } + else { + // Add ftCmo (common object data) subobject + $objData .= + pack('vvvvvVVV' + , 0x0015 // 0x0015 = ftCmo + , 0x0012 // length of ftCmo data + , 0x0008 // object type, 0x0008 = picture + , $i // object id number, Excel seems to use 1-based index, local for the sheet + , 0x6011 // option flags, 0x6011 is what OpenOffice.org uses + , 0 // reserved + , 0 // reserved + , 0 // reserved + ); + } + + // ftEnd + $objData .= + pack('vv' + , 0x0000 // 0x0000 = ftEnd + , 0x0000 // length of ftEnd data + ); + + $length = strlen($objData); + $header = pack('vv', $record, $length); + $this->_append($header . $objData); + } + } + } + + /** + * Store the DATAVALIDATIONS and DATAVALIDATION records. + */ + private function _writeDataValidity() + { + // Datavalidation collection + $dataValidationCollection = $this->_phpSheet->getDataValidationCollection(); + + // Write data validations? + if (!empty($dataValidationCollection)) { + + // DATAVALIDATIONS record + $record = 0x01B2; // Record identifier + $length = 0x0012; // Bytes to follow + + $grbit = 0x0000; // Prompt box at cell, no cached validity data at DV records + $horPos = 0x00000000; // Horizontal position of prompt box, if fixed position + $verPos = 0x00000000; // Vertical position of prompt box, if fixed position + $objId = 0xFFFFFFFF; // Object identifier of drop down arrow object, or -1 if not visible + + $header = pack('vv', $record, $length); + $data = pack('vVVVV', $grbit, $horPos, $verPos, $objId, + count($dataValidationCollection)); + $this->_append($header.$data); + + // DATAVALIDATION records + $record = 0x01BE; // Record identifier + + foreach ($dataValidationCollection as $cellCoordinate => $dataValidation) { + // initialize record data + $data = ''; + + // options + $options = 0x00000000; + + // data type + $type = $dataValidation->getType(); + switch ($type) { + case PHPExcel_Cell_DataValidation::TYPE_NONE: $type = 0x00; break; + case PHPExcel_Cell_DataValidation::TYPE_WHOLE: $type = 0x01; break; + case PHPExcel_Cell_DataValidation::TYPE_DECIMAL: $type = 0x02; break; + case PHPExcel_Cell_DataValidation::TYPE_LIST: $type = 0x03; break; + case PHPExcel_Cell_DataValidation::TYPE_DATE: $type = 0x04; break; + case PHPExcel_Cell_DataValidation::TYPE_TIME: $type = 0x05; break; + case PHPExcel_Cell_DataValidation::TYPE_TEXTLENGTH: $type = 0x06; break; + case PHPExcel_Cell_DataValidation::TYPE_CUSTOM: $type = 0x07; break; + } + $options |= $type << 0; + + // error style + $errorStyle = $dataValidation->getType(); + switch ($errorStyle) { + case PHPExcel_Cell_DataValidation::STYLE_STOP: $errorStyle = 0x00; break; + case PHPExcel_Cell_DataValidation::STYLE_WARNING: $errorStyle = 0x01; break; + case PHPExcel_Cell_DataValidation::STYLE_INFORMATION: $errorStyle = 0x02; break; + } + $options |= $errorStyle << 4; + + // explicit formula? + if ($type == 0x03 && preg_match('/^\".*\"$/', $dataValidation->getFormula1())) { + $options |= 0x01 << 7; + } + + // empty cells allowed + $options |= $dataValidation->getAllowBlank() << 8; + + // show drop down + $options |= (!$dataValidation->getShowDropDown()) << 9; + + // show input message + $options |= $dataValidation->getShowInputMessage() << 18; + + // show error message + $options |= $dataValidation->getShowErrorMessage() << 19; + + // condition operator + $operator = $dataValidation->getOperator(); + switch ($operator) { + case PHPExcel_Cell_DataValidation::OPERATOR_BETWEEN: $operator = 0x00 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_NOTBETWEEN: $operator = 0x01 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_EQUAL: $operator = 0x02 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_NOTEQUAL: $operator = 0x03 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHAN: $operator = 0x04 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_LESSTHAN: $operator = 0x05 ; break; + case PHPExcel_Cell_DataValidation::OPERATOR_GREATERTHANOREQUAL: $operator = 0x06; break; + case PHPExcel_Cell_DataValidation::OPERATOR_LESSTHANOREQUAL: $operator = 0x07 ; break; + } + $options |= $operator << 20; + + $data = pack('V', $options); + + // prompt title + $promptTitle = $dataValidation->getPromptTitle() !== '' ? + $dataValidation->getPromptTitle() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($promptTitle); + + // error title + $errorTitle = $dataValidation->getErrorTitle() !== '' ? + $dataValidation->getErrorTitle() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($errorTitle); + + // prompt text + $prompt = $dataValidation->getPrompt() !== '' ? + $dataValidation->getPrompt() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($prompt); + + // error text + $error = $dataValidation->getError() !== '' ? + $dataValidation->getError() : chr(0); + $data .= PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($error); + + // formula 1 + try { + $formula1 = $dataValidation->getFormula1(); + if ($type == 0x03) { // list type + $formula1 = str_replace(',', chr(0), $formula1); + } + $this->_parser->parse($formula1); + $formula1 = $this->_parser->toReversePolish(); + $sz1 = strlen($formula1); + + } catch(PHPExcel_Exception $e) { + $sz1 = 0; + $formula1 = ''; + } + $data .= pack('vv', $sz1, 0x0000); + $data .= $formula1; + + // formula 2 + try { + $formula2 = $dataValidation->getFormula2(); + if ($formula2 === '') { + throw new PHPExcel_Writer_Exception('No formula2'); + } + $this->_parser->parse($formula2); + $formula2 = $this->_parser->toReversePolish(); + $sz2 = strlen($formula2); + + } catch(PHPExcel_Exception $e) { + $sz2 = 0; + $formula2 = ''; + } + $data .= pack('vv', $sz2, 0x0000); + $data .= $formula2; + + // cell range address list + $data .= pack('v', 0x0001); + $data .= $this->_writeBIFF8CellRangeAddressFixed($cellCoordinate); + + $length = strlen($data); + $header = pack("vv", $record, $length); + + $this->_append($header . $data); + } + } + } + + /** + * Map Error code + * + * @param string $errorCode + * @return int + */ + private static function _mapErrorCode($errorCode) { + switch ($errorCode) { + case '#NULL!': return 0x00; + case '#DIV/0!': return 0x07; + case '#VALUE!': return 0x0F; + case '#REF!': return 0x17; + case '#NAME?': return 0x1D; + case '#NUM!': return 0x24; + case '#N/A': return 0x2A; + } + + return 0; + } + + /** + * Write PLV Record + */ + private function _writePageLayoutView(){ + $record = 0x088B; // Record identifier + $length = 0x0010; // Bytes to follow + + $rt = 0x088B; // 2 + $grbitFrt = 0x0000; // 2 + $reserved = 0x0000000000000000; // 8 + $wScalvePLV = $this->_phpSheet->getSheetView()->getZoomScale(); // 2 + + // The options flags that comprise $grbit + if($this->_phpSheet->getSheetView()->getView() == PHPExcel_Worksheet_SheetView::SHEETVIEW_PAGE_LAYOUT){ + $fPageLayoutView = 1; + } else { + $fPageLayoutView = 0; + } + $fRulerVisible = 0; + $fWhitespaceHidden = 0; + + $grbit = $fPageLayoutView; // 2 + $grbit |= $fRulerVisible << 1; + $grbit |= $fWhitespaceHidden << 3; + + $header = pack("vv", $record, $length); + $data = pack("vvVVvv", $rt, $grbitFrt, 0x00000000, 0x00000000, $wScalvePLV, $grbit); + $this->_append($header . $data); + } + + /** + * Write CFRule Record + * @param PHPExcel_Style_Conditional $conditional + */ + private function _writeCFRule(PHPExcel_Style_Conditional $conditional){ + $record = 0x01B1; // Record identifier + + // $type : Type of the CF + // $operatorType : Comparison operator + if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION){ + $type = 0x02; + $operatorType = 0x00; + } else if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ + $type = 0x01; + + switch ($conditional->getOperatorType()){ + case PHPExcel_Style_Conditional::OPERATOR_NONE: + $operatorType = 0x00; + break; + case PHPExcel_Style_Conditional::OPERATOR_EQUAL: + $operatorType = 0x03; + break; + case PHPExcel_Style_Conditional::OPERATOR_GREATERTHAN: + $operatorType = 0x05; + break; + case PHPExcel_Style_Conditional::OPERATOR_GREATERTHANOREQUAL: + $operatorType = 0x07; + break; + case PHPExcel_Style_Conditional::OPERATOR_LESSTHAN: + $operatorType = 0x06; + break; + case PHPExcel_Style_Conditional::OPERATOR_LESSTHANOREQUAL: + $operatorType = 0x08; + break; + case PHPExcel_Style_Conditional::OPERATOR_NOTEQUAL: + $operatorType = 0x04; + break; + case PHPExcel_Style_Conditional::OPERATOR_BETWEEN: + $operatorType = 0x01; + break; + // not OPERATOR_NOTBETWEEN 0x02 + } + } + + // $szValue1 : size of the formula data for first value or formula + // $szValue2 : size of the formula data for second value or formula + $arrConditions = $conditional->getConditions(); + $numConditions = sizeof($arrConditions); + if($numConditions == 1){ + $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000); + $szValue2 = 0x0000; + $operand1 = pack('Cv', 0x1E, $arrConditions[0]); + $operand2 = null; + } else if($numConditions == 2 && ($conditional->getOperatorType() == PHPExcel_Style_Conditional::OPERATOR_BETWEEN)){ + $szValue1 = ($arrConditions[0] <= 65535 ? 3 : 0x0000); + $szValue2 = ($arrConditions[1] <= 65535 ? 3 : 0x0000); + $operand1 = pack('Cv', 0x1E, $arrConditions[0]); + $operand2 = pack('Cv', 0x1E, $arrConditions[1]); + } else { + $szValue1 = 0x0000; + $szValue2 = 0x0000; + $operand1 = null; + $operand2 = null; + } + + // $flags : Option flags + // Alignment + $bAlignHz = ($conditional->getStyle()->getAlignment()->getHorizontal() == null ? 1 : 0); + $bAlignVt = ($conditional->getStyle()->getAlignment()->getVertical() == null ? 1 : 0); + $bAlignWrapTx = ($conditional->getStyle()->getAlignment()->getWrapText() == false ? 1 : 0); + $bTxRotation = ($conditional->getStyle()->getAlignment()->getTextRotation() == null ? 1 : 0); + $bIndent = ($conditional->getStyle()->getAlignment()->getIndent() == 0 ? 1 : 0); + $bShrinkToFit = ($conditional->getStyle()->getAlignment()->getShrinkToFit() == false ? 1 : 0); + if($bAlignHz == 0 || $bAlignVt == 0 || $bAlignWrapTx == 0 || $bTxRotation == 0 || $bIndent == 0 || $bShrinkToFit == 0){ + $bFormatAlign = 1; + } else { + $bFormatAlign = 0; + } + // Protection + $bProtLocked = ($conditional->getStyle()->getProtection()->getLocked() == null ? 1 : 0); + $bProtHidden = ($conditional->getStyle()->getProtection()->getHidden() == null ? 1 : 0); + if($bProtLocked == 0 || $bProtHidden == 0){ + $bFormatProt = 1; + } else { + $bFormatProt = 0; + } + // Border + $bBorderLeft = ($conditional->getStyle()->getBorders()->getLeft()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getLeft()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + $bBorderRight = ($conditional->getStyle()->getBorders()->getRight()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getRight()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + $bBorderTop = ($conditional->getStyle()->getBorders()->getTop()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getTop()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + $bBorderBottom = ($conditional->getStyle()->getBorders()->getBottom()->getColor()->getARGB() == PHPExcel_Style_Color::COLOR_BLACK + && $conditional->getStyle()->getBorders()->getBottom()->getBorderStyle() == PHPExcel_Style_Border::BORDER_NONE ? 1 : 0); + if($bBorderLeft == 0 || $bBorderRight == 0 || $bBorderTop == 0 || $bBorderBottom == 0){ + $bFormatBorder = 1; + } else { + $bFormatBorder = 0; + } + // Pattern + $bFillStyle = ($conditional->getStyle()->getFill()->getFillType() == null ? 0 : 1); + $bFillColor = ($conditional->getStyle()->getFill()->getStartColor()->getARGB() == null ? 0 : 1); + $bFillColorBg = ($conditional->getStyle()->getFill()->getEndColor()->getARGB() == null ? 0 : 1); + if($bFillStyle == 0 || $bFillColor == 0 || $bFillColorBg == 0){ + $bFormatFill = 1; + } else { + $bFormatFill = 0; + } + // Font + if($conditional->getStyle()->getFont()->getName() != null + || $conditional->getStyle()->getFont()->getSize() != null + || $conditional->getStyle()->getFont()->getBold() != null + || $conditional->getStyle()->getFont()->getItalic() != null + || $conditional->getStyle()->getFont()->getSuperScript() != null + || $conditional->getStyle()->getFont()->getSubScript() != null + || $conditional->getStyle()->getFont()->getUnderline() != null + || $conditional->getStyle()->getFont()->getStrikethrough() != null + || $conditional->getStyle()->getFont()->getColor()->getARGB() != null){ + $bFormatFont = 1; + } else { + $bFormatFont = 0; + } + // Alignment + $flags = 0; + $flags |= (1 == $bAlignHz ? 0x00000001 : 0); + $flags |= (1 == $bAlignVt ? 0x00000002 : 0); + $flags |= (1 == $bAlignWrapTx ? 0x00000004 : 0); + $flags |= (1 == $bTxRotation ? 0x00000008 : 0); + // Justify last line flag + $flags |= (1 == 1 ? 0x00000010 : 0); + $flags |= (1 == $bIndent ? 0x00000020 : 0); + $flags |= (1 == $bShrinkToFit ? 0x00000040 : 0); + // Default + $flags |= (1 == 1 ? 0x00000080 : 0); + // Protection + $flags |= (1 == $bProtLocked ? 0x00000100 : 0); + $flags |= (1 == $bProtHidden ? 0x00000200 : 0); + // Border + $flags |= (1 == $bBorderLeft ? 0x00000400 : 0); + $flags |= (1 == $bBorderRight ? 0x00000800 : 0); + $flags |= (1 == $bBorderTop ? 0x00001000 : 0); + $flags |= (1 == $bBorderBottom ? 0x00002000 : 0); + $flags |= (1 == 1 ? 0x00004000 : 0); // Top left to Bottom right border + $flags |= (1 == 1 ? 0x00008000 : 0); // Bottom left to Top right border + // Pattern + $flags |= (1 == $bFillStyle ? 0x00010000 : 0); + $flags |= (1 == $bFillColor ? 0x00020000 : 0); + $flags |= (1 == $bFillColorBg ? 0x00040000 : 0); + $flags |= (1 == 1 ? 0x00380000 : 0); + // Font + $flags |= (1 == $bFormatFont ? 0x04000000 : 0); + // Alignment : + $flags |= (1 == $bFormatAlign ? 0x08000000 : 0); + // Border + $flags |= (1 == $bFormatBorder ? 0x10000000 : 0); + // Pattern + $flags |= (1 == $bFormatFill ? 0x20000000 : 0); + // Protection + $flags |= (1 == $bFormatProt ? 0x40000000 : 0); + // Text direction + $flags |= (1 == 0 ? 0x80000000 : 0); + + // Data Blocks + if($bFormatFont == 1){ + // Font Name + if($conditional->getStyle()->getFont()->getName() == null){ + $dataBlockFont = pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + $dataBlockFont .= pack('VVVVVVVV', 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000); + } else { + $dataBlockFont = PHPExcel_Shared_String::UTF8toBIFF8UnicodeLong($conditional->getStyle()->getFont()->getName()); + } + // Font Size + if($conditional->getStyle()->getFont()->getSize() == null){ + $dataBlockFont .= pack('V', 20 * 11); + } else { + $dataBlockFont .= pack('V', 20 * $conditional->getStyle()->getFont()->getSize()); + } + // Font Options + $dataBlockFont .= pack('V', 0); + // Font weight + if($conditional->getStyle()->getFont()->getBold() == true){ + $dataBlockFont .= pack('v', 0x02BC); + } else { + $dataBlockFont .= pack('v', 0x0190); + } + // Escapement type + if($conditional->getStyle()->getFont()->getSubScript() == true){ + $dataBlockFont .= pack('v', 0x02); + $fontEscapement = 0; + } else if($conditional->getStyle()->getFont()->getSuperScript() == true){ + $dataBlockFont .= pack('v', 0x01); + $fontEscapement = 0; + } else { + $dataBlockFont .= pack('v', 0x00); + $fontEscapement = 1; + } + // Underline type + switch ($conditional->getStyle()->getFont()->getUnderline()){ + case PHPExcel_Style_Font::UNDERLINE_NONE : $dataBlockFont .= pack('C', 0x00); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_DOUBLE : $dataBlockFont .= pack('C', 0x02); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING : $dataBlockFont .= pack('C', 0x22); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_SINGLE : $dataBlockFont .= pack('C', 0x01); $fontUnderline = 0; break; + case PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING : $dataBlockFont .= pack('C', 0x21); $fontUnderline = 0; break; + default : $dataBlockFont .= pack('C', 0x00); $fontUnderline = 1; break; + } + // Not used (3) + $dataBlockFont .= pack('vC', 0x0000, 0x00); + // Font color index + switch ($conditional->getStyle()->getFont()->getColor()->getRGB()) { + case '000000': $colorIdx = 0x08; break; + case 'FFFFFF': $colorIdx = 0x09; break; + case 'FF0000': $colorIdx = 0x0A; break; + case '00FF00': $colorIdx = 0x0B; break; + case '0000FF': $colorIdx = 0x0C; break; + case 'FFFF00': $colorIdx = 0x0D; break; + case 'FF00FF': $colorIdx = 0x0E; break; + case '00FFFF': $colorIdx = 0x0F; break; + case '800000': $colorIdx = 0x10; break; + case '008000': $colorIdx = 0x11; break; + case '000080': $colorIdx = 0x12; break; + case '808000': $colorIdx = 0x13; break; + case '800080': $colorIdx = 0x14; break; + case '008080': $colorIdx = 0x15; break; + case 'C0C0C0': $colorIdx = 0x16; break; + case '808080': $colorIdx = 0x17; break; + case '9999FF': $colorIdx = 0x18; break; + case '993366': $colorIdx = 0x19; break; + case 'FFFFCC': $colorIdx = 0x1A; break; + case 'CCFFFF': $colorIdx = 0x1B; break; + case '660066': $colorIdx = 0x1C; break; + case 'FF8080': $colorIdx = 0x1D; break; + case '0066CC': $colorIdx = 0x1E; break; + case 'CCCCFF': $colorIdx = 0x1F; break; + case '000080': $colorIdx = 0x20; break; + case 'FF00FF': $colorIdx = 0x21; break; + case 'FFFF00': $colorIdx = 0x22; break; + case '00FFFF': $colorIdx = 0x23; break; + case '800080': $colorIdx = 0x24; break; + case '800000': $colorIdx = 0x25; break; + case '008080': $colorIdx = 0x26; break; + case '0000FF': $colorIdx = 0x27; break; + case '00CCFF': $colorIdx = 0x28; break; + case 'CCFFFF': $colorIdx = 0x29; break; + case 'CCFFCC': $colorIdx = 0x2A; break; + case 'FFFF99': $colorIdx = 0x2B; break; + case '99CCFF': $colorIdx = 0x2C; break; + case 'FF99CC': $colorIdx = 0x2D; break; + case 'CC99FF': $colorIdx = 0x2E; break; + case 'FFCC99': $colorIdx = 0x2F; break; + case '3366FF': $colorIdx = 0x30; break; + case '33CCCC': $colorIdx = 0x31; break; + case '99CC00': $colorIdx = 0x32; break; + case 'FFCC00': $colorIdx = 0x33; break; + case 'FF9900': $colorIdx = 0x34; break; + case 'FF6600': $colorIdx = 0x35; break; + case '666699': $colorIdx = 0x36; break; + case '969696': $colorIdx = 0x37; break; + case '003366': $colorIdx = 0x38; break; + case '339966': $colorIdx = 0x39; break; + case '003300': $colorIdx = 0x3A; break; + case '333300': $colorIdx = 0x3B; break; + case '993300': $colorIdx = 0x3C; break; + case '993366': $colorIdx = 0x3D; break; + case '333399': $colorIdx = 0x3E; break; + case '333333': $colorIdx = 0x3F; break; + default: $colorIdx = 0x00; break; + } + $dataBlockFont .= pack('V', $colorIdx); + // Not used (4) + $dataBlockFont .= pack('V', 0x00000000); + // Options flags for modified font attributes + $optionsFlags = 0; + $optionsFlagsBold = ($conditional->getStyle()->getFont()->getBold() == null ? 1 : 0); + $optionsFlags |= (1 == $optionsFlagsBold ? 0x00000002 : 0); + $optionsFlags |= (1 == 1 ? 0x00000008 : 0); + $optionsFlags |= (1 == 1 ? 0x00000010 : 0); + $optionsFlags |= (1 == 0 ? 0x00000020 : 0); + $optionsFlags |= (1 == 1 ? 0x00000080 : 0); + $dataBlockFont .= pack('V', $optionsFlags); + // Escapement type + $dataBlockFont .= pack('V', $fontEscapement); + // Underline type + $dataBlockFont .= pack('V', $fontUnderline); + // Always + $dataBlockFont .= pack('V', 0x00000000); + // Always + $dataBlockFont .= pack('V', 0x00000000); + // Not used (8) + $dataBlockFont .= pack('VV', 0x00000000, 0x00000000); + // Always + $dataBlockFont .= pack('v', 0x0001); + } + if($bFormatAlign == 1){ + $blockAlign = 0; + // Alignment and text break + switch ($conditional->getStyle()->getAlignment()->getHorizontal()){ + case PHPExcel_Style_Alignment::HORIZONTAL_GENERAL : $blockAlign = 0; break; + case PHPExcel_Style_Alignment::HORIZONTAL_LEFT : $blockAlign = 1; break; + case PHPExcel_Style_Alignment::HORIZONTAL_RIGHT : $blockAlign = 3; break; + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER : $blockAlign = 2; break; + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS : $blockAlign = 6; break; + case PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY : $blockAlign = 5; break; + } + if($conditional->getStyle()->getAlignment()->getWrapText() == true){ + $blockAlign |= 1 << 3; + } else { + $blockAlign |= 0 << 3; + } + switch ($conditional->getStyle()->getAlignment()->getVertical()){ + case PHPExcel_Style_Alignment::VERTICAL_BOTTOM : $blockAlign = 2 << 4; break; + case PHPExcel_Style_Alignment::VERTICAL_TOP : $blockAlign = 0 << 4; break; + case PHPExcel_Style_Alignment::VERTICAL_CENTER : $blockAlign = 1 << 4; break; + case PHPExcel_Style_Alignment::VERTICAL_JUSTIFY : $blockAlign = 3 << 4; break; + } + $blockAlign |= 0 << 7; + + // Text rotation angle + $blockRotation = $conditional->getStyle()->getAlignment()->getTextRotation(); + + // Indentation + $blockIndent = $conditional->getStyle()->getAlignment()->getIndent(); + if($conditional->getStyle()->getAlignment()->getShrinkToFit() == true){ + $blockIndent |= 1 << 4; + } else { + $blockIndent |= 0 << 4; + } + $blockIndent |= 0 << 6; + + // Relative indentation + $blockIndentRelative = 255; + + $dataBlockAlign = pack('CCvvv', $blockAlign, $blockRotation, $blockIndent, $blockIndentRelative, 0x0000); + } + if($bFormatBorder == 1){ + $blockLineStyle = 0; + switch ($conditional->getStyle()->getBorders()->getLeft()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D; break; + } + switch ($conditional->getStyle()->getBorders()->getRight()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 4; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 4; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 4; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 4; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 4; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 4; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 4; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 4; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 4; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 4; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 4; break; + } + switch ($conditional->getStyle()->getBorders()->getTop()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 8; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 8; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 8; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 8; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 8; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 8; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 8; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 8; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 8; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 8; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 8; break; + } + switch ($conditional->getStyle()->getBorders()->getBottom()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockLineStyle |= 0x00 << 12; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockLineStyle |= 0x01 << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockLineStyle |= 0x02 << 12; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockLineStyle |= 0x03 << 12; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockLineStyle |= 0x04 << 12; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockLineStyle |= 0x05 << 12; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockLineStyle |= 0x06 << 12; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockLineStyle |= 0x07 << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockLineStyle |= 0x08 << 12; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockLineStyle |= 0x09 << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockLineStyle |= 0x0A << 12; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockLineStyle |= 0x0B << 12; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockLineStyle |= 0x0C << 12; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockLineStyle |= 0x0D << 12; break; + } + //@todo _writeCFRule() => $blockLineStyle => Index Color for left line + //@todo _writeCFRule() => $blockLineStyle => Index Color for right line + //@todo _writeCFRule() => $blockLineStyle => Top-left to bottom-right on/off + //@todo _writeCFRule() => $blockLineStyle => Bottom-left to top-right on/off + $blockColor = 0; + //@todo _writeCFRule() => $blockColor => Index Color for top line + //@todo _writeCFRule() => $blockColor => Index Color for bottom line + //@todo _writeCFRule() => $blockColor => Index Color for diagonal line + switch ($conditional->getStyle()->getBorders()->getDiagonal()->getBorderStyle()){ + case PHPExcel_Style_Border::BORDER_NONE : $blockColor |= 0x00 << 21; break; + case PHPExcel_Style_Border::BORDER_THIN : $blockColor |= 0x01 << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUM : $blockColor |= 0x02 << 21; break; + case PHPExcel_Style_Border::BORDER_DASHED : $blockColor |= 0x03 << 21; break; + case PHPExcel_Style_Border::BORDER_DOTTED : $blockColor |= 0x04 << 21; break; + case PHPExcel_Style_Border::BORDER_THICK : $blockColor |= 0x05 << 21; break; + case PHPExcel_Style_Border::BORDER_DOUBLE : $blockColor |= 0x06 << 21; break; + case PHPExcel_Style_Border::BORDER_HAIR : $blockColor |= 0x07 << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED : $blockColor |= 0x08 << 21; break; + case PHPExcel_Style_Border::BORDER_DASHDOT : $blockColor |= 0x09 << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT : $blockColor |= 0x0A << 21; break; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT : $blockColor |= 0x0B << 21; break; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT : $blockColor |= 0x0C << 21; break; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT : $blockColor |= 0x0D << 21; break; + } + $dataBlockBorder = pack('vv', $blockLineStyle, $blockColor); + } + if($bFormatFill == 1){ + // Fill Patern Style + $blockFillPatternStyle = 0; + switch ($conditional->getStyle()->getFill()->getFillType()){ + case PHPExcel_Style_Fill::FILL_NONE : $blockFillPatternStyle = 0x00; break; + case PHPExcel_Style_Fill::FILL_SOLID : $blockFillPatternStyle = 0x01; break; + case PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY : $blockFillPatternStyle = 0x02; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY : $blockFillPatternStyle = 0x03; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY : $blockFillPatternStyle = 0x04; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL : $blockFillPatternStyle = 0x05; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL : $blockFillPatternStyle = 0x06; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN : $blockFillPatternStyle = 0x07; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKUP : $blockFillPatternStyle = 0x08; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID : $blockFillPatternStyle = 0x09; break; + case PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS : $blockFillPatternStyle = 0x0A; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL : $blockFillPatternStyle = 0x0B; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL : $blockFillPatternStyle = 0x0C; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN : $blockFillPatternStyle = 0x0D; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP : $blockFillPatternStyle = 0x0E; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID : $blockFillPatternStyle = 0x0F; break; + case PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS : $blockFillPatternStyle = 0x10; break; + case PHPExcel_Style_Fill::FILL_PATTERN_GRAY125 : $blockFillPatternStyle = 0x11; break; + case PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625 : $blockFillPatternStyle = 0x12; break; + case PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR : $blockFillPatternStyle = 0x00; break; // does not exist in BIFF8 + case PHPExcel_Style_Fill::FILL_GRADIENT_PATH : $blockFillPatternStyle = 0x00; break; // does not exist in BIFF8 + default : $blockFillPatternStyle = 0x00; break; + } + // Color + switch ($conditional->getStyle()->getFill()->getStartColor()->getRGB()) { + case '000000': $colorIdxBg = 0x08; break; + case 'FFFFFF': $colorIdxBg = 0x09; break; + case 'FF0000': $colorIdxBg = 0x0A; break; + case '00FF00': $colorIdxBg = 0x0B; break; + case '0000FF': $colorIdxBg = 0x0C; break; + case 'FFFF00': $colorIdxBg = 0x0D; break; + case 'FF00FF': $colorIdxBg = 0x0E; break; + case '00FFFF': $colorIdxBg = 0x0F; break; + case '800000': $colorIdxBg = 0x10; break; + case '008000': $colorIdxBg = 0x11; break; + case '000080': $colorIdxBg = 0x12; break; + case '808000': $colorIdxBg = 0x13; break; + case '800080': $colorIdxBg = 0x14; break; + case '008080': $colorIdxBg = 0x15; break; + case 'C0C0C0': $colorIdxBg = 0x16; break; + case '808080': $colorIdxBg = 0x17; break; + case '9999FF': $colorIdxBg = 0x18; break; + case '993366': $colorIdxBg = 0x19; break; + case 'FFFFCC': $colorIdxBg = 0x1A; break; + case 'CCFFFF': $colorIdxBg = 0x1B; break; + case '660066': $colorIdxBg = 0x1C; break; + case 'FF8080': $colorIdxBg = 0x1D; break; + case '0066CC': $colorIdxBg = 0x1E; break; + case 'CCCCFF': $colorIdxBg = 0x1F; break; + case '000080': $colorIdxBg = 0x20; break; + case 'FF00FF': $colorIdxBg = 0x21; break; + case 'FFFF00': $colorIdxBg = 0x22; break; + case '00FFFF': $colorIdxBg = 0x23; break; + case '800080': $colorIdxBg = 0x24; break; + case '800000': $colorIdxBg = 0x25; break; + case '008080': $colorIdxBg = 0x26; break; + case '0000FF': $colorIdxBg = 0x27; break; + case '00CCFF': $colorIdxBg = 0x28; break; + case 'CCFFFF': $colorIdxBg = 0x29; break; + case 'CCFFCC': $colorIdxBg = 0x2A; break; + case 'FFFF99': $colorIdxBg = 0x2B; break; + case '99CCFF': $colorIdxBg = 0x2C; break; + case 'FF99CC': $colorIdxBg = 0x2D; break; + case 'CC99FF': $colorIdxBg = 0x2E; break; + case 'FFCC99': $colorIdxBg = 0x2F; break; + case '3366FF': $colorIdxBg = 0x30; break; + case '33CCCC': $colorIdxBg = 0x31; break; + case '99CC00': $colorIdxBg = 0x32; break; + case 'FFCC00': $colorIdxBg = 0x33; break; + case 'FF9900': $colorIdxBg = 0x34; break; + case 'FF6600': $colorIdxBg = 0x35; break; + case '666699': $colorIdxBg = 0x36; break; + case '969696': $colorIdxBg = 0x37; break; + case '003366': $colorIdxBg = 0x38; break; + case '339966': $colorIdxBg = 0x39; break; + case '003300': $colorIdxBg = 0x3A; break; + case '333300': $colorIdxBg = 0x3B; break; + case '993300': $colorIdxBg = 0x3C; break; + case '993366': $colorIdxBg = 0x3D; break; + case '333399': $colorIdxBg = 0x3E; break; + case '333333': $colorIdxBg = 0x3F; break; + default: $colorIdxBg = 0x41; break; + } + // Fg Color + switch ($conditional->getStyle()->getFill()->getEndColor()->getRGB()) { + case '000000': $colorIdxFg = 0x08; break; + case 'FFFFFF': $colorIdxFg = 0x09; break; + case 'FF0000': $colorIdxFg = 0x0A; break; + case '00FF00': $colorIdxFg = 0x0B; break; + case '0000FF': $colorIdxFg = 0x0C; break; + case 'FFFF00': $colorIdxFg = 0x0D; break; + case 'FF00FF': $colorIdxFg = 0x0E; break; + case '00FFFF': $colorIdxFg = 0x0F; break; + case '800000': $colorIdxFg = 0x10; break; + case '008000': $colorIdxFg = 0x11; break; + case '000080': $colorIdxFg = 0x12; break; + case '808000': $colorIdxFg = 0x13; break; + case '800080': $colorIdxFg = 0x14; break; + case '008080': $colorIdxFg = 0x15; break; + case 'C0C0C0': $colorIdxFg = 0x16; break; + case '808080': $colorIdxFg = 0x17; break; + case '9999FF': $colorIdxFg = 0x18; break; + case '993366': $colorIdxFg = 0x19; break; + case 'FFFFCC': $colorIdxFg = 0x1A; break; + case 'CCFFFF': $colorIdxFg = 0x1B; break; + case '660066': $colorIdxFg = 0x1C; break; + case 'FF8080': $colorIdxFg = 0x1D; break; + case '0066CC': $colorIdxFg = 0x1E; break; + case 'CCCCFF': $colorIdxFg = 0x1F; break; + case '000080': $colorIdxFg = 0x20; break; + case 'FF00FF': $colorIdxFg = 0x21; break; + case 'FFFF00': $colorIdxFg = 0x22; break; + case '00FFFF': $colorIdxFg = 0x23; break; + case '800080': $colorIdxFg = 0x24; break; + case '800000': $colorIdxFg = 0x25; break; + case '008080': $colorIdxFg = 0x26; break; + case '0000FF': $colorIdxFg = 0x27; break; + case '00CCFF': $colorIdxFg = 0x28; break; + case 'CCFFFF': $colorIdxFg = 0x29; break; + case 'CCFFCC': $colorIdxFg = 0x2A; break; + case 'FFFF99': $colorIdxFg = 0x2B; break; + case '99CCFF': $colorIdxFg = 0x2C; break; + case 'FF99CC': $colorIdxFg = 0x2D; break; + case 'CC99FF': $colorIdxFg = 0x2E; break; + case 'FFCC99': $colorIdxFg = 0x2F; break; + case '3366FF': $colorIdxFg = 0x30; break; + case '33CCCC': $colorIdxFg = 0x31; break; + case '99CC00': $colorIdxFg = 0x32; break; + case 'FFCC00': $colorIdxFg = 0x33; break; + case 'FF9900': $colorIdxFg = 0x34; break; + case 'FF6600': $colorIdxFg = 0x35; break; + case '666699': $colorIdxFg = 0x36; break; + case '969696': $colorIdxFg = 0x37; break; + case '003366': $colorIdxFg = 0x38; break; + case '339966': $colorIdxFg = 0x39; break; + case '003300': $colorIdxFg = 0x3A; break; + case '333300': $colorIdxFg = 0x3B; break; + case '993300': $colorIdxFg = 0x3C; break; + case '993366': $colorIdxFg = 0x3D; break; + case '333399': $colorIdxFg = 0x3E; break; + case '333333': $colorIdxFg = 0x3F; break; + default: $colorIdxFg = 0x40; break; + } + $dataBlockFill = pack('v', $blockFillPatternStyle); + $dataBlockFill .= pack('v', $colorIdxFg | ($colorIdxBg << 7)); + } + if($bFormatProt == 1){ + $dataBlockProtection = 0; + if($conditional->getStyle()->getProtection()->getLocked() == PHPExcel_Style_Protection::PROTECTION_PROTECTED){ + $dataBlockProtection = 1; + } + if($conditional->getStyle()->getProtection()->getHidden() == PHPExcel_Style_Protection::PROTECTION_PROTECTED){ + $dataBlockProtection = 1 << 1; + } + } + + $data = pack('CCvvVv', $type, $operatorType, $szValue1, $szValue2, $flags, 0x0000); + if($bFormatFont == 1){ // Block Formatting : OK + $data .= $dataBlockFont; + } + if($bFormatAlign == 1){ + $data .= $dataBlockAlign; + } + if($bFormatBorder == 1){ + $data .= $dataBlockBorder; + } + if($bFormatFill == 1){ // Block Formatting : OK + $data .= $dataBlockFill; + } + if($bFormatProt == 1){ + $data .= $dataBlockProtection; + } + if(!is_null($operand1)){ + $data .= $operand1; + } + if(!is_null($operand2)){ + $data .= $operand2; + } + $header = pack('vv', $record, strlen($data)); + $this->_append($header . $data); + } + + /** + * Write CFHeader record + */ + private function _writeCFHeader(){ + $record = 0x01B0; // Record identifier + $length = 0x0016; // Bytes to follow + + $numColumnMin = null; + $numColumnMax = null; + $numRowMin = null; + $numRowMax = null; + $arrConditional = array(); + foreach ($this->_phpSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) { + foreach ($conditionalStyles as $conditional) { + if($conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_EXPRESSION + || $conditional->getConditionType() == PHPExcel_Style_Conditional::CONDITION_CELLIS){ + if(!in_array($conditional->getHashCode(), $arrConditional)){ + $arrConditional[] = $conditional->getHashCode(); + } + // Cells + $arrCoord = PHPExcel_Cell::coordinateFromString($cellCoordinate); + if(!is_numeric($arrCoord[0])){ + $arrCoord[0] = PHPExcel_Cell::columnIndexFromString($arrCoord[0]); + } + if(is_null($numColumnMin) || ($numColumnMin > $arrCoord[0])){ + $numColumnMin = $arrCoord[0]; + } + if(is_null($numColumnMax) || ($numColumnMax < $arrCoord[0])){ + $numColumnMax = $arrCoord[0]; + } + if(is_null($numRowMin) || ($numRowMin > $arrCoord[1])){ + $numRowMin = $arrCoord[1]; + } + if(is_null($numRowMax) || ($numRowMax < $arrCoord[1])){ + $numRowMax = $arrCoord[1]; + } + } + } + } + $needRedraw = 1; + $cellRange = pack('vvvv', $numRowMin-1, $numRowMax-1, $numColumnMin-1, $numColumnMax-1); + + $header = pack('vv', $record, $length); + $data = pack('vv', count($arrConditional), $needRedraw); + $data .= $cellRange; + $data .= pack('v', 0x0001); + $data .= $cellRange; + $this->_append($header . $data); + } +} \ No newline at end of file diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Xf.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Xf.php new file mode 100755 index 0000000..b0fc9c3 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Excel5/Xf.php @@ -0,0 +1,546 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + +// Original file header of PEAR::Spreadsheet_Excel_Writer_Format (used as the base for this class): +// ----------------------------------------------------------------------------------------- +// /* +// * Module written/ported by Xavier Noguer <xnoguer@rezebra.com> +// * +// * The majority of this is _NOT_ my code. I simply ported it from the +// * PERL Spreadsheet::WriteExcel module. +// * +// * The author of the Spreadsheet::WriteExcel module is John McNamara +// * <jmcnamara@cpan.org> +// * +// * I _DO_ maintain this code, and John McNamara has nothing to do with the +// * porting of this code to PHP. Any questions directly related to this +// * class library should be directed to me. +// * +// * License Information: +// * +// * Spreadsheet_Excel_Writer: A library for generating Excel Spreadsheets +// * Copyright (c) 2002-2003 Xavier Noguer xnoguer@rezebra.com +// * +// * This library is free software; you can redistribute it and/or +// * modify it under the terms of the GNU Lesser General Public +// * License as published by the Free Software Foundation; either +// * version 2.1 of the License, or (at your option) any later version. +// * +// * This library is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// * Lesser General Public License for more details. +// * +// * You should have received a copy of the GNU Lesser General Public +// * License along with this library; if not, write to the Free Software +// * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// */ + + +/** + * PHPExcel_Writer_Excel5_Xf + * + * @category PHPExcel + * @package PHPExcel_Writer_Excel5 + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Excel5_Xf +{ + /** + * Style XF or a cell XF ? + * + * @var boolean + */ + private $_isStyleXf; + + /** + * Index to the FONT record. Index 4 does not exist + * @var integer + */ + private $_fontIndex; + + /** + * An index (2 bytes) to a FORMAT record (number format). + * @var integer + */ + public $_numberFormatIndex; + + /** + * 1 bit, apparently not used. + * @var integer + */ + public $_text_justlast; + + /** + * The cell's foreground color. + * @var integer + */ + public $_fg_color; + + /** + * The cell's background color. + * @var integer + */ + public $_bg_color; + + /** + * Color of the bottom border of the cell. + * @var integer + */ + public $_bottom_color; + + /** + * Color of the top border of the cell. + * @var integer + */ + public $_top_color; + + /** + * Color of the left border of the cell. + * @var integer + */ + public $_left_color; + + /** + * Color of the right border of the cell. + * @var integer + */ + public $_right_color; + + /** + * Constructor + * + * @access public + * @param PHPExcel_Style The XF format + */ + public function __construct(PHPExcel_Style $style = null) + { + $this->_isStyleXf = false; + $this->_fontIndex = 0; + + $this->_numberFormatIndex = 0; + + $this->_text_justlast = 0; + + $this->_fg_color = 0x40; + $this->_bg_color = 0x41; + + $this->_diag = 0; + + $this->_bottom_color = 0x40; + $this->_top_color = 0x40; + $this->_left_color = 0x40; + $this->_right_color = 0x40; + $this->_diag_color = 0x40; + $this->_style = $style; + + } + + + /** + * Generate an Excel BIFF XF record (style or cell). + * + * @return string The XF record + */ + function writeXf() + { + // Set the type of the XF record and some of the attributes. + if ($this->_isStyleXf) { + $style = 0xFFF5; + } else { + $style = self::_mapLocked($this->_style->getProtection()->getLocked()); + $style |= self::_mapHidden($this->_style->getProtection()->getHidden()) << 1; + } + + // Flags to indicate if attributes have been set. + $atr_num = ($this->_numberFormatIndex != 0)?1:0; + $atr_fnt = ($this->_fontIndex != 0)?1:0; + $atr_alc = ((int) $this->_style->getAlignment()->getWrapText())?1:0; + $atr_bdr = (self::_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) || + self::_mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) || + self::_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()) || + self::_mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle()))?1:0; + $atr_pat = (($this->_fg_color != 0x40) || + ($this->_bg_color != 0x41) || + self::_mapFillType($this->_style->getFill()->getFillType()))?1:0; + $atr_prot = self::_mapLocked($this->_style->getProtection()->getLocked()) + | self::_mapHidden($this->_style->getProtection()->getHidden()); + + // Zero the default border colour if the border has not been set. + if (self::_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) == 0) { + $this->_bottom_color = 0; + } + if (self::_mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) == 0) { + $this->_top_color = 0; + } + if (self::_mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle()) == 0) { + $this->_right_color = 0; + } + if (self::_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()) == 0) { + $this->_left_color = 0; + } + if (self::_mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) == 0) { + $this->_diag_color = 0; + } + + $record = 0x00E0; // Record identifier + $length = 0x0014; // Number of bytes to follow + + $ifnt = $this->_fontIndex; // Index to FONT record + $ifmt = $this->_numberFormatIndex; // Index to FORMAT record + + $align = $this->_mapHAlign($this->_style->getAlignment()->getHorizontal()); // Alignment + $align |= (int) $this->_style->getAlignment()->getWrapText() << 3; + $align |= self::_mapVAlign($this->_style->getAlignment()->getVertical()) << 4; + $align |= $this->_text_justlast << 7; + + $used_attrib = $atr_num << 2; + $used_attrib |= $atr_fnt << 3; + $used_attrib |= $atr_alc << 4; + $used_attrib |= $atr_bdr << 5; + $used_attrib |= $atr_pat << 6; + $used_attrib |= $atr_prot << 7; + + $icv = $this->_fg_color; // fg and bg pattern colors + $icv |= $this->_bg_color << 7; + + $border1 = self::_mapBorderStyle($this->_style->getBorders()->getLeft()->getBorderStyle()); // Border line style and color + $border1 |= self::_mapBorderStyle($this->_style->getBorders()->getRight()->getBorderStyle()) << 4; + $border1 |= self::_mapBorderStyle($this->_style->getBorders()->getTop()->getBorderStyle()) << 8; + $border1 |= self::_mapBorderStyle($this->_style->getBorders()->getBottom()->getBorderStyle()) << 12; + $border1 |= $this->_left_color << 16; + $border1 |= $this->_right_color << 23; + + $diagonalDirection = $this->_style->getBorders()->getDiagonalDirection(); + $diag_tl_to_rb = $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_BOTH + || $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_DOWN; + $diag_tr_to_lb = $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_BOTH + || $diagonalDirection == PHPExcel_Style_Borders::DIAGONAL_UP; + $border1 |= $diag_tl_to_rb << 30; + $border1 |= $diag_tr_to_lb << 31; + + $border2 = $this->_top_color; // Border color + $border2 |= $this->_bottom_color << 7; + $border2 |= $this->_diag_color << 14; + $border2 |= self::_mapBorderStyle($this->_style->getBorders()->getDiagonal()->getBorderStyle()) << 21; + $border2 |= self::_mapFillType($this->_style->getFill()->getFillType()) << 26; + + $header = pack("vv", $record, $length); + + //BIFF8 options: identation, shrinkToFit and text direction + $biff8_options = $this->_style->getAlignment()->getIndent(); + $biff8_options |= (int) $this->_style->getAlignment()->getShrinkToFit() << 4; + + $data = pack("vvvC", $ifnt, $ifmt, $style, $align); + $data .= pack("CCC" + , self::_mapTextRotation($this->_style->getAlignment()->getTextRotation()) + , $biff8_options + , $used_attrib + ); + $data .= pack("VVv", $border1, $border2, $icv); + + return($header . $data); + } + + /** + * Is this a style XF ? + * + * @param boolean $value + */ + public function setIsStyleXf($value) + { + $this->_isStyleXf = $value; + } + + /** + * Sets the cell's bottom border color + * + * @access public + * @param int $colorIndex Color index + */ + function setBottomColor($colorIndex) + { + $this->_bottom_color = $colorIndex; + } + + /** + * Sets the cell's top border color + * + * @access public + * @param int $colorIndex Color index + */ + function setTopColor($colorIndex) + { + $this->_top_color = $colorIndex; + } + + /** + * Sets the cell's left border color + * + * @access public + * @param int $colorIndex Color index + */ + function setLeftColor($colorIndex) + { + $this->_left_color = $colorIndex; + } + + /** + * Sets the cell's right border color + * + * @access public + * @param int $colorIndex Color index + */ + function setRightColor($colorIndex) + { + $this->_right_color = $colorIndex; + } + + /** + * Sets the cell's diagonal border color + * + * @access public + * @param int $colorIndex Color index + */ + function setDiagColor($colorIndex) + { + $this->_diag_color = $colorIndex; + } + + + /** + * Sets the cell's foreground color + * + * @access public + * @param int $colorIndex Color index + */ + function setFgColor($colorIndex) + { + $this->_fg_color = $colorIndex; + } + + /** + * Sets the cell's background color + * + * @access public + * @param int $colorIndex Color index + */ + function setBgColor($colorIndex) + { + $this->_bg_color = $colorIndex; + } + + /** + * Sets the index to the number format record + * It can be date, time, currency, etc... + * + * @access public + * @param integer $numberFormatIndex Index to format record + */ + function setNumberFormatIndex($numberFormatIndex) + { + $this->_numberFormatIndex = $numberFormatIndex; + } + + /** + * Set the font index. + * + * @param int $value Font index, note that value 4 does not exist + */ + public function setFontIndex($value) + { + $this->_fontIndex = $value; + } + + /** + * Map of BIFF2-BIFF8 codes for border styles + * @static array of int + * + */ + private static $_mapBorderStyle = array ( PHPExcel_Style_Border::BORDER_NONE => 0x00, + PHPExcel_Style_Border::BORDER_THIN => 0x01, + PHPExcel_Style_Border::BORDER_MEDIUM => 0x02, + PHPExcel_Style_Border::BORDER_DASHED => 0x03, + PHPExcel_Style_Border::BORDER_DOTTED => 0x04, + PHPExcel_Style_Border::BORDER_THICK => 0x05, + PHPExcel_Style_Border::BORDER_DOUBLE => 0x06, + PHPExcel_Style_Border::BORDER_HAIR => 0x07, + PHPExcel_Style_Border::BORDER_MEDIUMDASHED => 0x08, + PHPExcel_Style_Border::BORDER_DASHDOT => 0x09, + PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT => 0x0A, + PHPExcel_Style_Border::BORDER_DASHDOTDOT => 0x0B, + PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT => 0x0C, + PHPExcel_Style_Border::BORDER_SLANTDASHDOT => 0x0D, + ); + + /** + * Map border style + * + * @param string $borderStyle + * @return int + */ + private static function _mapBorderStyle($borderStyle) { + if (isset(self::$_mapBorderStyle[$borderStyle])) + return self::$_mapBorderStyle[$borderStyle]; + return 0x00; + } + + /** + * Map of BIFF2-BIFF8 codes for fill types + * @static array of int + * + */ + private static $_mapFillType = array( PHPExcel_Style_Fill::FILL_NONE => 0x00, + PHPExcel_Style_Fill::FILL_SOLID => 0x01, + PHPExcel_Style_Fill::FILL_PATTERN_MEDIUMGRAY => 0x02, + PHPExcel_Style_Fill::FILL_PATTERN_DARKGRAY => 0x03, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRAY => 0x04, + PHPExcel_Style_Fill::FILL_PATTERN_DARKHORIZONTAL => 0x05, + PHPExcel_Style_Fill::FILL_PATTERN_DARKVERTICAL => 0x06, + PHPExcel_Style_Fill::FILL_PATTERN_DARKDOWN => 0x07, + PHPExcel_Style_Fill::FILL_PATTERN_DARKUP => 0x08, + PHPExcel_Style_Fill::FILL_PATTERN_DARKGRID => 0x09, + PHPExcel_Style_Fill::FILL_PATTERN_DARKTRELLIS => 0x0A, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTHORIZONTAL => 0x0B, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTVERTICAL => 0x0C, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTDOWN => 0x0D, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTUP => 0x0E, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTGRID => 0x0F, + PHPExcel_Style_Fill::FILL_PATTERN_LIGHTTRELLIS => 0x10, + PHPExcel_Style_Fill::FILL_PATTERN_GRAY125 => 0x11, + PHPExcel_Style_Fill::FILL_PATTERN_GRAY0625 => 0x12, + PHPExcel_Style_Fill::FILL_GRADIENT_LINEAR => 0x00, // does not exist in BIFF8 + PHPExcel_Style_Fill::FILL_GRADIENT_PATH => 0x00, // does not exist in BIFF8 + ); + /** + * Map fill type + * + * @param string $fillType + * @return int + */ + private static function _mapFillType($fillType) { + if (isset(self::$_mapFillType[$fillType])) + return self::$_mapFillType[$fillType]; + return 0x00; + } + + /** + * Map of BIFF2-BIFF8 codes for horizontal alignment + * @static array of int + * + */ + private static $_mapHAlign = array( PHPExcel_Style_Alignment::HORIZONTAL_GENERAL => 0, + PHPExcel_Style_Alignment::HORIZONTAL_LEFT => 1, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER => 2, + PHPExcel_Style_Alignment::HORIZONTAL_RIGHT => 3, + PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY => 5, + PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS => 6, + ); + /** + * Map to BIFF2-BIFF8 codes for horizontal alignment + * + * @param string $hAlign + * @return int + */ + private function _mapHAlign($hAlign) + { + if (isset(self::$_mapHAlign[$hAlign])) + return self::$_mapHAlign[$hAlign]; + return 0; + } + + /** + * Map of BIFF2-BIFF8 codes for vertical alignment + * @static array of int + * + */ + private static $_mapVAlign = array( PHPExcel_Style_Alignment::VERTICAL_TOP => 0, + PHPExcel_Style_Alignment::VERTICAL_CENTER => 1, + PHPExcel_Style_Alignment::VERTICAL_BOTTOM => 2, + PHPExcel_Style_Alignment::VERTICAL_JUSTIFY => 3, + ); + /** + * Map to BIFF2-BIFF8 codes for vertical alignment + * + * @param string $vAlign + * @return int + */ + private static function _mapVAlign($vAlign) { + if (isset(self::$_mapVAlign[$vAlign])) + return self::$_mapVAlign[$vAlign]; + return 2; + } + + /** + * Map to BIFF8 codes for text rotation angle + * + * @param int $textRotation + * @return int + */ + private static function _mapTextRotation($textRotation) { + if ($textRotation >= 0) { + return $textRotation; + } + if ($textRotation == -165) { + return 255; + } + if ($textRotation < 0) { + return 90 - $textRotation; + } + } + + /** + * Map locked + * + * @param string + * @return int + */ + private static function _mapLocked($locked) { + switch ($locked) { + case PHPExcel_Style_Protection::PROTECTION_INHERIT: return 1; + case PHPExcel_Style_Protection::PROTECTION_PROTECTED: return 1; + case PHPExcel_Style_Protection::PROTECTION_UNPROTECTED: return 0; + default: return 1; + } + } + + /** + * Map hidden + * + * @param string + * @return int + */ + private static function _mapHidden($hidden) { + switch ($hidden) { + case PHPExcel_Style_Protection::PROTECTION_INHERIT: return 0; + case PHPExcel_Style_Protection::PROTECTION_PROTECTED: return 1; + case PHPExcel_Style_Protection::PROTECTION_UNPROTECTED: return 0; + default: return 0; + } + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Exception.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Exception.php new file mode 100755 index 0000000..495c61e --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/Exception.php @@ -0,0 +1,52 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_Exception + * + * @category PHPExcel + * @package PHPExcel_Writer + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_Exception extends PHPExcel_Exception { + /** + * Error handler callback + * + * @param mixed $code + * @param mixed $string + * @param mixed $file + * @param mixed $line + * @param mixed $context + */ + public static function errorHandlerCallback($code, $string, $file, $line, $context) { + $e = new self($string, $code); + $e->line = $line; + $e->file = $file; + throw $e; + } +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/HTML.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/HTML.php new file mode 100755 index 0000000..af4635c --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/HTML.php @@ -0,0 +1,1527 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_HTML + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_HTML + * + * @category PHPExcel + * @package PHPExcel_Writer_HTML + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_HTML extends PHPExcel_Writer_Abstract implements PHPExcel_Writer_IWriter { + /** + * PHPExcel object + * + * @var PHPExcel + */ + protected $_phpExcel; + + /** + * Sheet index to write + * + * @var int + */ + private $_sheetIndex = 0; + + /** + * Images root + * + * @var string + */ + private $_imagesRoot = '.'; + + /** + * embed images, or link to images + * + * @var boolean + */ + private $_embedImages = FALSE; + + /** + * Use inline CSS? + * + * @var boolean + */ + private $_useInlineCss = false; + + /** + * Array of CSS styles + * + * @var array + */ + private $_cssStyles = null; + + /** + * Array of column widths in points + * + * @var array + */ + private $_columnWidths = null; + + /** + * Default font + * + * @var PHPExcel_Style_Font + */ + private $_defaultFont; + + /** + * Flag whether spans have been calculated + * + * @var boolean + */ + private $_spansAreCalculated = false; + + /** + * Excel cells that should not be written as HTML cells + * + * @var array + */ + private $_isSpannedCell = array(); + + /** + * Excel cells that are upper-left corner in a cell merge + * + * @var array + */ + private $_isBaseCell = array(); + + /** + * Excel rows that should not be written as HTML rows + * + * @var array + */ + private $_isSpannedRow = array(); + + /** + * Is the current writer creating PDF? + * + * @var boolean + */ + protected $_isPdf = false; + + /** + * Generate the Navigation block + * + * @var boolean + */ + private $_generateSheetNavigationBlock = true; + + /** + * Create a new PHPExcel_Writer_HTML + * + * @param PHPExcel $phpExcel PHPExcel object + */ + public function __construct(PHPExcel $phpExcel) { + $this->_phpExcel = $phpExcel; + $this->_defaultFont = $this->_phpExcel->getDefaultStyle()->getFont(); + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = null) { + // garbage collect + $this->_phpExcel->garbageCollect(); + + $saveDebugLog = PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->getWriteDebugLog(); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog(FALSE); + $saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); + PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); + + // Build CSS + $this->buildCSS(!$this->_useInlineCss); + + // Open file + $fileHandle = fopen($pFilename, 'wb+'); + if ($fileHandle === false) { + throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing."); + } + + // Write headers + fwrite($fileHandle, $this->generateHTMLHeader(!$this->_useInlineCss)); + + // Write navigation (tabs) + if ((!$this->_isPdf) && ($this->_generateSheetNavigationBlock)) { + fwrite($fileHandle, $this->generateNavigation()); + } + + // Write data + fwrite($fileHandle, $this->generateSheetData()); + + // Write footer + fwrite($fileHandle, $this->generateHTMLFooter()); + + // Close file + fclose($fileHandle); + + PHPExcel_Calculation::setArrayReturnType($saveArrayReturnType); + PHPExcel_Calculation::getInstance($this->_phpExcel)->getDebugLog()->setWriteDebugLog($saveDebugLog); + } + + /** + * Map VAlign + * + * @param string $vAlign Vertical alignment + * @return string + */ + private function _mapVAlign($vAlign) { + switch ($vAlign) { + case PHPExcel_Style_Alignment::VERTICAL_BOTTOM: return 'bottom'; + case PHPExcel_Style_Alignment::VERTICAL_TOP: return 'top'; + case PHPExcel_Style_Alignment::VERTICAL_CENTER: + case PHPExcel_Style_Alignment::VERTICAL_JUSTIFY: return 'middle'; + default: return 'baseline'; + } + } + + /** + * Map HAlign + * + * @param string $hAlign Horizontal alignment + * @return string|false + */ + private function _mapHAlign($hAlign) { + switch ($hAlign) { + case PHPExcel_Style_Alignment::HORIZONTAL_GENERAL: return false; + case PHPExcel_Style_Alignment::HORIZONTAL_LEFT: return 'left'; + case PHPExcel_Style_Alignment::HORIZONTAL_RIGHT: return 'right'; + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER: + case PHPExcel_Style_Alignment::HORIZONTAL_CENTER_CONTINUOUS: return 'center'; + case PHPExcel_Style_Alignment::HORIZONTAL_JUSTIFY: return 'justify'; + default: return false; + } + } + + /** + * Map border style + * + * @param int $borderStyle Sheet index + * @return string + */ + private function _mapBorderStyle($borderStyle) { + switch ($borderStyle) { + case PHPExcel_Style_Border::BORDER_NONE: return 'none'; + case PHPExcel_Style_Border::BORDER_DASHDOT: return '1px dashed'; + case PHPExcel_Style_Border::BORDER_DASHDOTDOT: return '1px dotted'; + case PHPExcel_Style_Border::BORDER_DASHED: return '1px dashed'; + case PHPExcel_Style_Border::BORDER_DOTTED: return '1px dotted'; + case PHPExcel_Style_Border::BORDER_DOUBLE: return '3px double'; + case PHPExcel_Style_Border::BORDER_HAIR: return '1px solid'; + case PHPExcel_Style_Border::BORDER_MEDIUM: return '2px solid'; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOT: return '2px dashed'; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHDOTDOT: return '2px dotted'; + case PHPExcel_Style_Border::BORDER_MEDIUMDASHED: return '2px dashed'; + case PHPExcel_Style_Border::BORDER_SLANTDASHDOT: return '2px dashed'; + case PHPExcel_Style_Border::BORDER_THICK: return '3px solid'; + case PHPExcel_Style_Border::BORDER_THIN: return '1px solid'; + default: return '1px solid'; // map others to thin + } + } + + /** + * Get sheet index + * + * @return int + */ + public function getSheetIndex() { + return $this->_sheetIndex; + } + + /** + * Set sheet index + * + * @param int $pValue Sheet index + * @return PHPExcel_Writer_HTML + */ + public function setSheetIndex($pValue = 0) { + $this->_sheetIndex = $pValue; + return $this; + } + + /** + * Get sheet index + * + * @return boolean + */ + public function getGenerateSheetNavigationBlock() { + return $this->_generateSheetNavigationBlock; + } + + /** + * Set sheet index + * + * @param boolean $pValue Flag indicating whether the sheet navigation block should be generated or not + * @return PHPExcel_Writer_HTML + */ + public function setGenerateSheetNavigationBlock($pValue = true) { + $this->_generateSheetNavigationBlock = (bool) $pValue; + return $this; + } + + /** + * Write all sheets (resets sheetIndex to NULL) + */ + public function writeAllSheets() { + $this->_sheetIndex = null; + return $this; + } + + /** + * Generate HTML header + * + * @param boolean $pIncludeStyles Include styles? + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateHTMLHeader($pIncludeStyles = false) { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Construct HTML + $properties = $this->_phpExcel->getProperties(); + $html = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">' . PHP_EOL; + $html .= '<!-- Generated by PHPExcel - http://www.phpexcel.net -->' . PHP_EOL; + $html .= '<html>' . PHP_EOL; + $html .= ' <head>' . PHP_EOL; + $html .= ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . PHP_EOL; + if ($properties->getTitle() > '') + $html .= ' <title>' . htmlspecialchars($properties->getTitle()) . '</title>' . PHP_EOL; + + if ($properties->getCreator() > '') + $html .= ' <meta name="author" content="' . htmlspecialchars($properties->getCreator()) . '" />' . PHP_EOL; + if ($properties->getTitle() > '') + $html .= ' <meta name="title" content="' . htmlspecialchars($properties->getTitle()) . '" />' . PHP_EOL; + if ($properties->getDescription() > '') + $html .= ' <meta name="description" content="' . htmlspecialchars($properties->getDescription()) . '" />' . PHP_EOL; + if ($properties->getSubject() > '') + $html .= ' <meta name="subject" content="' . htmlspecialchars($properties->getSubject()) . '" />' . PHP_EOL; + if ($properties->getKeywords() > '') + $html .= ' <meta name="keywords" content="' . htmlspecialchars($properties->getKeywords()) . '" />' . PHP_EOL; + if ($properties->getCategory() > '') + $html .= ' <meta name="category" content="' . htmlspecialchars($properties->getCategory()) . '" />' . PHP_EOL; + if ($properties->getCompany() > '') + $html .= ' <meta name="company" content="' . htmlspecialchars($properties->getCompany()) . '" />' . PHP_EOL; + if ($properties->getManager() > '') + $html .= ' <meta name="manager" content="' . htmlspecialchars($properties->getManager()) . '" />' . PHP_EOL; + + if ($pIncludeStyles) { + $html .= $this->generateStyles(true); + } + + $html .= ' </head>' . PHP_EOL; + $html .= '' . PHP_EOL; + $html .= ' <body>' . PHP_EOL; + + // Return + return $html; + } + + /** + * Generate sheet data + * + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateSheetData() { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Ensure that Spans have been calculated? + if (!$this->_spansAreCalculated) { + $this->_calculateSpans(); + } + + // Fetch sheets + $sheets = array(); + if (is_null($this->_sheetIndex)) { + $sheets = $this->_phpExcel->getAllSheets(); + } else { + $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); + } + + // Construct HTML + $html = ''; + + // Loop all sheets + $sheetId = 0; + foreach ($sheets as $sheet) { + // Write table header + $html .= $this->_generateTableHeader($sheet); + + // Get worksheet dimension + $dimension = explode(':', $sheet->calculateWorksheetDimension()); + $dimension[0] = PHPExcel_Cell::coordinateFromString($dimension[0]); + $dimension[0][0] = PHPExcel_Cell::columnIndexFromString($dimension[0][0]) - 1; + $dimension[1] = PHPExcel_Cell::coordinateFromString($dimension[1]); + $dimension[1][0] = PHPExcel_Cell::columnIndexFromString($dimension[1][0]) - 1; + + // row min,max + $rowMin = $dimension[0][1]; + $rowMax = $dimension[1][1]; + + // calculate start of <tbody>, <thead> + $tbodyStart = $rowMin; + $theadStart = $theadEnd = 0; // default: no <thead> no </thead> + if ($sheet->getPageSetup()->isRowsToRepeatAtTopSet()) { + $rowsToRepeatAtTop = $sheet->getPageSetup()->getRowsToRepeatAtTop(); + + // we can only support repeating rows that start at top row + if ($rowsToRepeatAtTop[0] == 1) { + $theadStart = $rowsToRepeatAtTop[0]; + $theadEnd = $rowsToRepeatAtTop[1]; + $tbodyStart = $rowsToRepeatAtTop[1] + 1; + } + } + + // Loop through cells + $row = $rowMin-1; + while($row++ < $rowMax) { + // <thead> ? + if ($row == $theadStart) { + $html .= ' <thead>' . PHP_EOL; + } + + // <tbody> ? + if ($row == $tbodyStart) { + $html .= ' <tbody>' . PHP_EOL; + } + + // Write row if there are HTML table cells in it + if ( !isset($this->_isSpannedRow[$sheet->getParent()->getIndex($sheet)][$row]) ) { + // Start a new rowData + $rowData = array(); + // Loop through columns + $column = $dimension[0][0] - 1; + while($column++ < $dimension[1][0]) { + // Cell exists? + if ($sheet->cellExistsByColumnAndRow($column, $row)) { + $rowData[$column] = $sheet->getCellByColumnAndRow($column, $row); + } else { + $rowData[$column] = ''; + } + } + $html .= $this->_generateRow($sheet, $rowData, $row - 1); + } + + // </thead> ? + if ($row == $theadEnd) { + $html .= ' </thead>' . PHP_EOL; + } + } + $html .= $this->_extendRowsForChartsAndImages($sheet, $row); + + // Close table body. + $html .= ' </tbody>' . PHP_EOL; + + // Write table footer + $html .= $this->_generateTableFooter(); + + // Writing PDF? + if ($this->_isPdf) { + if (is_null($this->_sheetIndex) && $sheetId + 1 < $this->_phpExcel->getSheetCount()) { + $html .= '<div style="page-break-before:always" />'; + } + } + + // Next sheet + ++$sheetId; + } + + // Return + return $html; + } + + /** + * Generate sheet tabs + * + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateNavigation() + { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Fetch sheets + $sheets = array(); + if (is_null($this->_sheetIndex)) { + $sheets = $this->_phpExcel->getAllSheets(); + } else { + $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); + } + + // Construct HTML + $html = ''; + + // Only if there are more than 1 sheets + if (count($sheets) > 1) { + // Loop all sheets + $sheetId = 0; + + $html .= '<ul class="navigation">' . PHP_EOL; + + foreach ($sheets as $sheet) { + $html .= ' <li class="sheet' . $sheetId . '"><a href="#sheet' . $sheetId . '">' . $sheet->getTitle() . '</a></li>' . PHP_EOL; + ++$sheetId; + } + + $html .= '</ul>' . PHP_EOL; + } + + return $html; + } + + private function _extendRowsForChartsAndImages(PHPExcel_Worksheet $pSheet, $row) { + $rowMax = $row; + $colMax = 'A'; + if ($this->_includeCharts) { + foreach ($pSheet->getChartCollection() as $chart) { + if ($chart instanceof PHPExcel_Chart) { + $chartCoordinates = $chart->getTopLeftPosition(); + $chartTL = PHPExcel_Cell::coordinateFromString($chartCoordinates['cell']); + $chartCol = PHPExcel_Cell::columnIndexFromString($chartTL[0]); + if ($chartTL[1] > $rowMax) { + $rowMax = $chartTL[1]; + if ($chartCol > PHPExcel_Cell::columnIndexFromString($colMax)) { + $colMax = $chartTL[0]; + } + } + } + } + } + + foreach ($pSheet->getDrawingCollection() as $drawing) { + if ($drawing instanceof PHPExcel_Worksheet_Drawing) { + $imageTL = PHPExcel_Cell::coordinateFromString($drawing->getCoordinates()); + $imageCol = PHPExcel_Cell::columnIndexFromString($imageTL[0]); + if ($imageTL[1] > $rowMax) { + $rowMax = $imageTL[1]; + if ($imageCol > PHPExcel_Cell::columnIndexFromString($colMax)) { + $colMax = $imageTL[0]; + } + } + } + } + $html = ''; + $colMax++; + while ($row < $rowMax) { + $html .= '<tr>'; + for ($col = 'A'; $col != $colMax; ++$col) { + $html .= '<td>'; + $html .= $this->_writeImageInCell($pSheet, $col.$row); + if ($this->_includeCharts) { + $html .= $this->_writeChartInCell($pSheet, $col.$row); + } + $html .= '</td>'; + } + ++$row; + $html .= '</tr>'; + } + return $html; + } + + + /** + * Generate image tag in cell + * + * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet + * @param string $coordinates Cell coordinates + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _writeImageInCell(PHPExcel_Worksheet $pSheet, $coordinates) { + // Construct HTML + $html = ''; + + // Write images + foreach ($pSheet->getDrawingCollection() as $drawing) { + if ($drawing instanceof PHPExcel_Worksheet_Drawing) { + if ($drawing->getCoordinates() == $coordinates) { + $filename = $drawing->getPath(); + + // Strip off eventual '.' + if (substr($filename, 0, 1) == '.') { + $filename = substr($filename, 1); + } + + // Prepend images root + $filename = $this->getImagesRoot() . $filename; + + // Strip off eventual '.' + if (substr($filename, 0, 1) == '.' && substr($filename, 0, 2) != './') { + $filename = substr($filename, 1); + } + + // Convert UTF8 data to PCDATA + $filename = htmlspecialchars($filename); + + $html .= PHP_EOL; + if ((!$this->_embedImages) || ($this->_isPdf)) { + $imageData = $filename; + } else { + $imageDetails = getimagesize($filename); + if ($fp = fopen($filename,"rb", 0)) { + $picture = fread($fp,filesize($filename)); + fclose($fp); + // base64 encode the binary data, then break it + // into chunks according to RFC 2045 semantics + $base64 = chunk_split(base64_encode($picture)); + $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64; + } else { + $imageData = $filename; + } + } + + $html .= '<div style="position: relative;">'; + $html .= '<img style="position: absolute; z-index: 1; left: ' . $drawing->getOffsetX() . 'px; top: ' . $drawing->getOffsetY() . 'px; width: ' . $drawing->getWidth() . 'px; height: ' . $drawing->getHeight() . 'px;" src="' . $imageData . '" border="0" />' . PHP_EOL; + $html .= '</div>'; + } + } + } + + // Return + return $html; + } + + /** + * Generate chart tag in cell + * + * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet + * @param string $coordinates Cell coordinates + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _writeChartInCell(PHPExcel_Worksheet $pSheet, $coordinates) { + // Construct HTML + $html = ''; + + // Write charts + foreach ($pSheet->getChartCollection() as $chart) { + if ($chart instanceof PHPExcel_Chart) { + $chartCoordinates = $chart->getTopLeftPosition(); + if ($chartCoordinates['cell'] == $coordinates) { + $chartFileName = PHPExcel_Shared_File::sys_get_temp_dir().'/'.uniqid().'.png'; + if (!$chart->render($chartFileName)) { + return; + } + + $html .= PHP_EOL; + $imageDetails = getimagesize($chartFileName); + if ($fp = fopen($chartFileName,"rb", 0)) { + $picture = fread($fp,filesize($chartFileName)); + fclose($fp); + // base64 encode the binary data, then break it + // into chunks according to RFC 2045 semantics + $base64 = chunk_split(base64_encode($picture)); + $imageData = 'data:'.$imageDetails['mime'].';base64,' . $base64; + + $html .= '<div style="position: relative;">'; + $html .= '<img style="position: absolute; z-index: 1; left: ' . $chartCoordinates['xOffset'] . 'px; top: ' . $chartCoordinates['yOffset'] . 'px; width: ' . $imageDetails[0] . 'px; height: ' . $imageDetails[1] . 'px;" src="' . $imageData . '" border="0" />' . PHP_EOL; + $html .= '</div>'; + + unlink($chartFileName); + } + } + } + } + + // Return + return $html; + } + + /** + * Generate CSS styles + * + * @param boolean $generateSurroundingHTML Generate surrounding HTML tags? (<style> and </style>) + * @return string + * @throws PHPExcel_Writer_Exception + */ + public function generateStyles($generateSurroundingHTML = true) { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Build CSS + $css = $this->buildCSS($generateSurroundingHTML); + + // Construct HTML + $html = ''; + + // Start styles + if ($generateSurroundingHTML) { + $html .= ' <style type="text/css">' . PHP_EOL; + $html .= ' html { ' . $this->_assembleCSS($css['html']) . ' }' . PHP_EOL; + } + + // Write all other styles + foreach ($css as $styleName => $styleDefinition) { + if ($styleName != 'html') { + $html .= ' ' . $styleName . ' { ' . $this->_assembleCSS($styleDefinition) . ' }' . PHP_EOL; + } + } + + // End styles + if ($generateSurroundingHTML) { + $html .= ' </style>' . PHP_EOL; + } + + // Return + return $html; + } + + /** + * Build CSS styles + * + * @param boolean $generateSurroundingHTML Generate surrounding HTML style? (html { }) + * @return array + * @throws PHPExcel_Writer_Exception + */ + public function buildCSS($generateSurroundingHTML = true) { + // PHPExcel object known? + if (is_null($this->_phpExcel)) { + throw new PHPExcel_Writer_Exception('Internal PHPExcel object not set to an instance of an object.'); + } + + // Cached? + if (!is_null($this->_cssStyles)) { + return $this->_cssStyles; + } + + // Ensure that spans have been calculated + if (!$this->_spansAreCalculated) { + $this->_calculateSpans(); + } + + // Construct CSS + $css = array(); + + // Start styles + if ($generateSurroundingHTML) { + // html { } + $css['html']['font-family'] = 'Calibri, Arial, Helvetica, sans-serif'; + $css['html']['font-size'] = '11pt'; + $css['html']['background-color'] = 'white'; + } + + + // table { } + $css['table']['border-collapse'] = 'collapse'; + if (!$this->_isPdf) { + $css['table']['page-break-after'] = 'always'; + } + + // .gridlines td { } + $css['.gridlines td']['border'] = '1px dotted black'; + + // .b {} + $css['.b']['text-align'] = 'center'; // BOOL + + // .e {} + $css['.e']['text-align'] = 'center'; // ERROR + + // .f {} + $css['.f']['text-align'] = 'right'; // FORMULA + + // .inlineStr {} + $css['.inlineStr']['text-align'] = 'left'; // INLINE + + // .n {} + $css['.n']['text-align'] = 'right'; // NUMERIC + + // .s {} + $css['.s']['text-align'] = 'left'; // STRING + + // Calculate cell style hashes + foreach ($this->_phpExcel->getCellXfCollection() as $index => $style) { + $css['td.style' . $index] = $this->_createCSSStyle( $style ); + } + + // Fetch sheets + $sheets = array(); + if (is_null($this->_sheetIndex)) { + $sheets = $this->_phpExcel->getAllSheets(); + } else { + $sheets[] = $this->_phpExcel->getSheet($this->_sheetIndex); + } + + // Build styles per sheet + foreach ($sheets as $sheet) { + // Calculate hash code + $sheetIndex = $sheet->getParent()->getIndex($sheet); + + // Build styles + // Calculate column widths + $sheet->calculateColumnWidths(); + + // col elements, initialize + $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()) - 1; + $column = -1; + while($column++ < $highestColumnIndex) { + $this->_columnWidths[$sheetIndex][$column] = 42; // approximation + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = '42pt'; + } + + // col elements, loop through columnDimensions and set width + foreach ($sheet->getColumnDimensions() as $columnDimension) { + if (($width = PHPExcel_Shared_Drawing::cellDimensionToPixels($columnDimension->getWidth(), $this->_defaultFont)) >= 0) { + $width = PHPExcel_Shared_Drawing::pixelsToPoints($width); + $column = PHPExcel_Cell::columnIndexFromString($columnDimension->getColumnIndex()) - 1; + $this->_columnWidths[$sheetIndex][$column] = $width; + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['width'] = $width . 'pt'; + + if ($columnDimension->getVisible() === false) { + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['visibility'] = 'collapse'; + $css['table.sheet' . $sheetIndex . ' col.col' . $column]['*display'] = 'none'; // target IE6+7 + } + } + } + + // Default row height + $rowDimension = $sheet->getDefaultRowDimension(); + + // table.sheetN tr { } + $css['table.sheet' . $sheetIndex . ' tr'] = array(); + + if ($rowDimension->getRowHeight() == -1) { + $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); + } else { + $pt_height = $rowDimension->getRowHeight(); + } + $css['table.sheet' . $sheetIndex . ' tr']['height'] = $pt_height . 'pt'; + if ($rowDimension->getVisible() === false) { + $css['table.sheet' . $sheetIndex . ' tr']['display'] = 'none'; + $css['table.sheet' . $sheetIndex . ' tr']['visibility'] = 'hidden'; + } + + // Calculate row heights + foreach ($sheet->getRowDimensions() as $rowDimension) { + $row = $rowDimension->getRowIndex() - 1; + + // table.sheetN tr.rowYYYYYY { } + $css['table.sheet' . $sheetIndex . ' tr.row' . $row] = array(); + + if ($rowDimension->getRowHeight() == -1) { + $pt_height = PHPExcel_Shared_Font::getDefaultRowHeightByFont($this->_phpExcel->getDefaultStyle()->getFont()); + } else { + $pt_height = $rowDimension->getRowHeight(); + } + $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['height'] = $pt_height . 'pt'; + if ($rowDimension->getVisible() === false) { + $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['display'] = 'none'; + $css['table.sheet' . $sheetIndex . ' tr.row' . $row]['visibility'] = 'hidden'; + } + } + } + + // Cache + if (is_null($this->_cssStyles)) { + $this->_cssStyles = $css; + } + + // Return + return $css; + } + + /** + * Create CSS style + * + * @param PHPExcel_Style $pStyle PHPExcel_Style + * @return array + */ + private function _createCSSStyle(PHPExcel_Style $pStyle) { + // Construct CSS + $css = ''; + + // Create CSS + $css = array_merge( + $this->_createCSSStyleAlignment($pStyle->getAlignment()) + , $this->_createCSSStyleBorders($pStyle->getBorders()) + , $this->_createCSSStyleFont($pStyle->getFont()) + , $this->_createCSSStyleFill($pStyle->getFill()) + ); + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Alignment) + * + * @param PHPExcel_Style_Alignment $pStyle PHPExcel_Style_Alignment + * @return array + */ + private function _createCSSStyleAlignment(PHPExcel_Style_Alignment $pStyle) { + // Construct CSS + $css = array(); + + // Create CSS + $css['vertical-align'] = $this->_mapVAlign($pStyle->getVertical()); + if ($textAlign = $this->_mapHAlign($pStyle->getHorizontal())) { + $css['text-align'] = $textAlign; + if(in_array($textAlign,array('left','right'))) + $css['padding-'.$textAlign] = (string)((int)$pStyle->getIndent() * 9).'px'; + } + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Font) + * + * @param PHPExcel_Style_Font $pStyle PHPExcel_Style_Font + * @return array + */ + private function _createCSSStyleFont(PHPExcel_Style_Font $pStyle) { + // Construct CSS + $css = array(); + + // Create CSS + if ($pStyle->getBold()) { + $css['font-weight'] = 'bold'; + } + if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE && $pStyle->getStrikethrough()) { + $css['text-decoration'] = 'underline line-through'; + } else if ($pStyle->getUnderline() != PHPExcel_Style_Font::UNDERLINE_NONE) { + $css['text-decoration'] = 'underline'; + } else if ($pStyle->getStrikethrough()) { + $css['text-decoration'] = 'line-through'; + } + if ($pStyle->getItalic()) { + $css['font-style'] = 'italic'; + } + + $css['color'] = '#' . $pStyle->getColor()->getRGB(); + $css['font-family'] = '\'' . $pStyle->getName() . '\''; + $css['font-size'] = $pStyle->getSize() . 'pt'; + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Borders) + * + * @param PHPExcel_Style_Borders $pStyle PHPExcel_Style_Borders + * @return array + */ + private function _createCSSStyleBorders(PHPExcel_Style_Borders $pStyle) { + // Construct CSS + $css = array(); + + // Create CSS + $css['border-bottom'] = $this->_createCSSStyleBorder($pStyle->getBottom()); + $css['border-top'] = $this->_createCSSStyleBorder($pStyle->getTop()); + $css['border-left'] = $this->_createCSSStyleBorder($pStyle->getLeft()); + $css['border-right'] = $this->_createCSSStyleBorder($pStyle->getRight()); + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Border) + * + * @param PHPExcel_Style_Border $pStyle PHPExcel_Style_Border + * @return string + */ + private function _createCSSStyleBorder(PHPExcel_Style_Border $pStyle) { + // Create CSS +// $css = $this->_mapBorderStyle($pStyle->getBorderStyle()) . ' #' . $pStyle->getColor()->getRGB(); + // Create CSS - add !important to non-none border styles for merged cells + $borderStyle = $this->_mapBorderStyle($pStyle->getBorderStyle()); + $css = $borderStyle . ' #' . $pStyle->getColor()->getRGB() . (($borderStyle == 'none') ? '' : ' !important'); + + // Return + return $css; + } + + /** + * Create CSS style (PHPExcel_Style_Fill) + * + * @param PHPExcel_Style_Fill $pStyle PHPExcel_Style_Fill + * @return array + */ + private function _createCSSStyleFill(PHPExcel_Style_Fill $pStyle) { + // Construct HTML + $css = array(); + + // Create CSS + $value = $pStyle->getFillType() == PHPExcel_Style_Fill::FILL_NONE ? + 'white' : '#' . $pStyle->getStartColor()->getRGB(); + $css['background-color'] = $value; + + // Return + return $css; + } + + /** + * Generate HTML footer + */ + public function generateHTMLFooter() { + // Construct HTML + $html = ''; + $html .= ' </body>' . PHP_EOL; + $html .= '</html>' . PHP_EOL; + + // Return + return $html; + } + + /** + * Generate table header + * + * @param PHPExcel_Worksheet $pSheet The worksheet for the table we are writing + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _generateTableHeader($pSheet) { + $sheetIndex = $pSheet->getParent()->getIndex($pSheet); + + // Construct HTML + $html = ''; + $html .= $this->_setMargins($pSheet); + + if (!$this->_useInlineCss) { + $gridlines = $pSheet->getShowGridLines() ? ' gridlines' : ''; + $html .= ' <table border="0" cellpadding="0" cellspacing="0" id="sheet' . $sheetIndex . '" class="sheet' . $sheetIndex . $gridlines . '">' . PHP_EOL; + } else { + $style = isset($this->_cssStyles['table']) ? + $this->_assembleCSS($this->_cssStyles['table']) : ''; + + if ($this->_isPdf && $pSheet->getShowGridLines()) { + $html .= ' <table border="1" cellpadding="1" id="sheet' . $sheetIndex . '" cellspacing="1" style="' . $style . '">' . PHP_EOL; + } else { + $html .= ' <table border="0" cellpadding="1" id="sheet' . $sheetIndex . '" cellspacing="0" style="' . $style . '">' . PHP_EOL; + } + } + + // Write <col> elements + $highestColumnIndex = PHPExcel_Cell::columnIndexFromString($pSheet->getHighestColumn()) - 1; + $i = -1; + while($i++ < $highestColumnIndex) { + if (!$this->_isPdf) { + if (!$this->_useInlineCss) { + $html .= ' <col class="col' . $i . '">' . PHP_EOL; + } else { + $style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) ? + $this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' col.col' . $i]) : ''; + $html .= ' <col style="' . $style . '">' . PHP_EOL; + } + } + } + + // Return + return $html; + } + + /** + * Generate table footer + * + * @throws PHPExcel_Writer_Exception + */ + private function _generateTableFooter() { + // Construct HTML + $html = ''; + $html .= ' </table>' . PHP_EOL; + + // Return + return $html; + } + + /** + * Generate row + * + * @param PHPExcel_Worksheet $pSheet PHPExcel_Worksheet + * @param array $pValues Array containing cells in a row + * @param int $pRow Row number (0-based) + * @return string + * @throws PHPExcel_Writer_Exception + */ + private function _generateRow(PHPExcel_Worksheet $pSheet, $pValues = null, $pRow = 0) { + if (is_array($pValues)) { + // Construct HTML + $html = ''; + + // Sheet index + $sheetIndex = $pSheet->getParent()->getIndex($pSheet); + + // DomPDF and breaks + if ($this->_isPdf && count($pSheet->getBreaks()) > 0) { + $breaks = $pSheet->getBreaks(); + + // check if a break is needed before this row + if (isset($breaks['A' . $pRow])) { + // close table: </table> + $html .= $this->_generateTableFooter(); + + // insert page break + $html .= '<div style="page-break-before:always" />'; + + // open table again: <table> + <col> etc. + $html .= $this->_generateTableHeader($pSheet); + } + } + + // Write row start + if (!$this->_useInlineCss) { + $html .= ' <tr class="row' . $pRow . '">' . PHP_EOL; + } else { + $style = isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]) + ? $this->_assembleCSS($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]) : ''; + + $html .= ' <tr style="' . $style . '">' . PHP_EOL; + } + + // Write cells + $colNum = 0; + foreach ($pValues as $cell) { + $coordinate = PHPExcel_Cell::stringFromColumnIndex($colNum) . ($pRow + 1); + + if (!$this->_useInlineCss) { + $cssClass = ''; + $cssClass = 'column' . $colNum; + } else { + $cssClass = array(); + if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum])) { + $this->_cssStyles['table.sheet' . $sheetIndex . ' td.column' . $colNum]; + } + } + $colSpan = 1; + $rowSpan = 1; + + // initialize + $cellData = '&nbsp;'; + + // PHPExcel_Cell + if ($cell instanceof PHPExcel_Cell) { + $cellData = ''; + if (is_null($cell->getParent())) { + $cell->attach($pSheet); + } + // Value + if ($cell->getValue() instanceof PHPExcel_RichText) { + // Loop through rich text elements + $elements = $cell->getValue()->getRichTextElements(); + foreach ($elements as $element) { + // Rich text start? + if ($element instanceof PHPExcel_RichText_Run) { + $cellData .= '<span style="' . $this->_assembleCSS($this->_createCSSStyleFont($element->getFont())) . '">'; + + if ($element->getFont()->getSuperScript()) { + $cellData .= '<sup>'; + } else if ($element->getFont()->getSubScript()) { + $cellData .= '<sub>'; + } + } + + // Convert UTF8 data to PCDATA + $cellText = $element->getText(); + $cellData .= htmlspecialchars($cellText); + + if ($element instanceof PHPExcel_RichText_Run) { + if ($element->getFont()->getSuperScript()) { + $cellData .= '</sup>'; + } else if ($element->getFont()->getSubScript()) { + $cellData .= '</sub>'; + } + + $cellData .= '</span>'; + } + } + } else { + if ($this->_preCalculateFormulas) { + $cellData = PHPExcel_Style_NumberFormat::toFormattedString( + $cell->getCalculatedValue(), + $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), + array($this, 'formatColor') + ); + } else { + $cellData = PHPExcel_Style_NumberFormat::ToFormattedString( + $cell->getValue(), + $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getNumberFormat()->getFormatCode(), + array($this, 'formatColor') + ); + } + $cellData = htmlspecialchars($cellData); + if ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSuperScript()) { + $cellData = '<sup>'.$cellData.'</sup>'; + } elseif ($pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() )->getFont()->getSubScript()) { + $cellData = '<sub>'.$cellData.'</sub>'; + } + } + + // Converts the cell content so that spaces occuring at beginning of each new line are replaced by &nbsp; + // Example: " Hello\n to the world" is converted to "&nbsp;&nbsp;Hello\n&nbsp;to the world" + $cellData = preg_replace("/(?m)(?:^|\\G) /", '&nbsp;', $cellData); + + // convert newline "\n" to '<br>' + $cellData = nl2br($cellData); + + // Extend CSS class? + if (!$this->_useInlineCss) { + $cssClass .= ' style' . $cell->getXfIndex(); + $cssClass .= ' ' . $cell->getDataType(); + } else { + if (isset($this->_cssStyles['td.style' . $cell->getXfIndex()])) { + $cssClass = array_merge($cssClass, $this->_cssStyles['td.style' . $cell->getXfIndex()]); + } + + // General horizontal alignment: Actual horizontal alignment depends on dataType + $sharedStyle = $pSheet->getParent()->getCellXfByIndex( $cell->getXfIndex() ); + if ($sharedStyle->getAlignment()->getHorizontal() == PHPExcel_Style_Alignment::HORIZONTAL_GENERAL + && isset($this->_cssStyles['.' . $cell->getDataType()]['text-align'])) + { + $cssClass['text-align'] = $this->_cssStyles['.' . $cell->getDataType()]['text-align']; + } + } + } + + // Hyperlink? + if ($pSheet->hyperlinkExists($coordinate) && !$pSheet->getHyperlink($coordinate)->isInternal()) { + $cellData = '<a href="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getUrl()) . '" title="' . htmlspecialchars($pSheet->getHyperlink($coordinate)->getTooltip()) . '">' . $cellData . '</a>'; + } + + // Should the cell be written or is it swallowed by a rowspan or colspan? + $writeCell = ! ( isset($this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]) + && $this->_isSpannedCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum] ); + + // Colspan and Rowspan + $colspan = 1; + $rowspan = 1; + if (isset($this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum])) { + $spans = $this->_isBaseCell[$pSheet->getParent()->getIndex($pSheet)][$pRow + 1][$colNum]; + $rowSpan = $spans['rowspan']; + $colSpan = $spans['colspan']; + + // Also apply style from last cell in merge to fix borders - + // relies on !important for non-none border declarations in _createCSSStyleBorder + $endCellCoord = PHPExcel_Cell::stringFromColumnIndex($colNum + $colSpan - 1) . ($pRow + $rowSpan); + $cssClass .= ' style' . $pSheet->getCell($endCellCoord)->getXfIndex(); + } + + // Write + if ($writeCell) { + // Column start + $html .= ' <td'; + if (!$this->_useInlineCss) { + $html .= ' class="' . $cssClass . '"'; + } else { + //** Necessary redundant code for the sake of PHPExcel_Writer_PDF ** + // We must explicitly write the width of the <td> element because TCPDF + // does not recognize e.g. <col style="width:42pt"> + $width = 0; + $i = $colNum - 1; + $e = $colNum + $colSpan - 1; + while($i++ < $e) { + if (isset($this->_columnWidths[$sheetIndex][$i])) { + $width += $this->_columnWidths[$sheetIndex][$i]; + } + } + $cssClass['width'] = $width . 'pt'; + + // We must also explicitly write the height of the <td> element because TCPDF + // does not recognize e.g. <tr style="height:50pt"> + if (isset($this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height'])) { + $height = $this->_cssStyles['table.sheet' . $sheetIndex . ' tr.row' . $pRow]['height']; + $cssClass['height'] = $height; + } + //** end of redundant code ** + + $html .= ' style="' . $this->_assembleCSS($cssClass) . '"'; + } + if ($colSpan > 1) { + $html .= ' colspan="' . $colSpan . '"'; + } + if ($rowSpan > 1) { + $html .= ' rowspan="' . $rowSpan . '"'; + } + $html .= '>'; + + // Image? + $html .= $this->_writeImageInCell($pSheet, $coordinate); + + // Chart? + if ($this->_includeCharts) { + $html .= $this->_writeChartInCell($pSheet, $coordinate); + } + + // Cell data + $html .= $cellData; + + // Column end + $html .= '</td>' . PHP_EOL; + } + + // Next column + ++$colNum; + } + + // Write row end + $html .= ' </tr>' . PHP_EOL; + + // Return + return $html; + } else { + throw new PHPExcel_Writer_Exception("Invalid parameters passed."); + } + } + + /** + * Takes array where of CSS properties / values and converts to CSS string + * + * @param array + * @return string + */ + private function _assembleCSS($pValue = array()) + { + $pairs = array(); + foreach ($pValue as $property => $value) { + $pairs[] = $property . ':' . $value; + } + $string = implode('; ', $pairs); + + return $string; + } + + /** + * Get images root + * + * @return string + */ + public function getImagesRoot() { + return $this->_imagesRoot; + } + + /** + * Set images root + * + * @param string $pValue + * @return PHPExcel_Writer_HTML + */ + public function setImagesRoot($pValue = '.') { + $this->_imagesRoot = $pValue; + return $this; + } + + /** + * Get embed images + * + * @return boolean + */ + public function getEmbedImages() { + return $this->_embedImages; + } + + /** + * Set embed images + * + * @param boolean $pValue + * @return PHPExcel_Writer_HTML + */ + public function setEmbedImages($pValue = '.') { + $this->_embedImages = $pValue; + return $this; + } + + /** + * Get use inline CSS? + * + * @return boolean + */ + public function getUseInlineCss() { + return $this->_useInlineCss; + } + + /** + * Set use inline CSS? + * + * @param boolean $pValue + * @return PHPExcel_Writer_HTML + */ + public function setUseInlineCss($pValue = false) { + $this->_useInlineCss = $pValue; + return $this; + } + + /** + * Add color to formatted string as inline style + * + * @param string $pValue Plain formatted value without color + * @param string $pFormat Format code + * @return string + */ + public function formatColor($pValue, $pFormat) + { + // Color information, e.g. [Red] is always at the beginning + $color = null; // initialize + $matches = array(); + + $color_regex = '/^\\[[a-zA-Z]+\\]/'; + if (preg_match($color_regex, $pFormat, $matches)) { + $color = str_replace('[', '', $matches[0]); + $color = str_replace(']', '', $color); + $color = strtolower($color); + } + + // convert to PCDATA + $value = htmlspecialchars($pValue); + + // color span tag + if ($color !== null) { + $value = '<span style="color:' . $color . '">' . $value . '</span>'; + } + + return $value; + } + + /** + * Calculate information about HTML colspan and rowspan which is not always the same as Excel's + */ + private function _calculateSpans() + { + // Identify all cells that should be omitted in HTML due to cell merge. + // In HTML only the upper-left cell should be written and it should have + // appropriate rowspan / colspan attribute + $sheetIndexes = $this->_sheetIndex !== null ? + array($this->_sheetIndex) : range(0, $this->_phpExcel->getSheetCount() - 1); + + foreach ($sheetIndexes as $sheetIndex) { + $sheet = $this->_phpExcel->getSheet($sheetIndex); + + $candidateSpannedRow = array(); + + // loop through all Excel merged cells + foreach ($sheet->getMergeCells() as $cells) { + list($cells, ) = PHPExcel_Cell::splitRange($cells); + $first = $cells[0]; + $last = $cells[1]; + + list($fc, $fr) = PHPExcel_Cell::coordinateFromString($first); + $fc = PHPExcel_Cell::columnIndexFromString($fc) - 1; + + list($lc, $lr) = PHPExcel_Cell::coordinateFromString($last); + $lc = PHPExcel_Cell::columnIndexFromString($lc) - 1; + + // loop through the individual cells in the individual merge + $r = $fr - 1; + while($r++ < $lr) { + // also, flag this row as a HTML row that is candidate to be omitted + $candidateSpannedRow[$r] = $r; + + $c = $fc - 1; + while($c++ < $lc) { + if ( !($c == $fc && $r == $fr) ) { + // not the upper-left cell (should not be written in HTML) + $this->_isSpannedCell[$sheetIndex][$r][$c] = array( + 'baseCell' => array($fr, $fc), + ); + } else { + // upper-left is the base cell that should hold the colspan/rowspan attribute + $this->_isBaseCell[$sheetIndex][$r][$c] = array( + 'xlrowspan' => $lr - $fr + 1, // Excel rowspan + 'rowspan' => $lr - $fr + 1, // HTML rowspan, value may change + 'xlcolspan' => $lc - $fc + 1, // Excel colspan + 'colspan' => $lc - $fc + 1, // HTML colspan, value may change + ); + } + } + } + } + + // Identify which rows should be omitted in HTML. These are the rows where all the cells + // participate in a merge and the where base cells are somewhere above. + $countColumns = PHPExcel_Cell::columnIndexFromString($sheet->getHighestColumn()); + foreach ($candidateSpannedRow as $rowIndex) { + if (isset($this->_isSpannedCell[$sheetIndex][$rowIndex])) { + if (count($this->_isSpannedCell[$sheetIndex][$rowIndex]) == $countColumns) { + $this->_isSpannedRow[$sheetIndex][$rowIndex] = $rowIndex; + }; + } + } + + // For each of the omitted rows we found above, the affected rowspans should be subtracted by 1 + if ( isset($this->_isSpannedRow[$sheetIndex]) ) { + foreach ($this->_isSpannedRow[$sheetIndex] as $rowIndex) { + $adjustedBaseCells = array(); + $c = -1; + $e = $countColumns - 1; + while($c++ < $e) { + $baseCell = $this->_isSpannedCell[$sheetIndex][$rowIndex][$c]['baseCell']; + + if ( !in_array($baseCell, $adjustedBaseCells) ) { + // subtract rowspan by 1 + --$this->_isBaseCell[$sheetIndex][ $baseCell[0] ][ $baseCell[1] ]['rowspan']; + $adjustedBaseCells[] = $baseCell; + } + } + } + } + + // TODO: Same for columns + } + + // We have calculated the spans + $this->_spansAreCalculated = true; + } + + private function _setMargins(PHPExcel_Worksheet $pSheet) { + $htmlPage = '@page { '; + $htmlBody = 'body { '; + + $left = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getLeft()) . 'in; '; + $htmlPage .= 'left-margin: ' . $left; + $htmlBody .= 'left-margin: ' . $left; + $right = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getRight()) . 'in; '; + $htmlPage .= 'right-margin: ' . $right; + $htmlBody .= 'right-margin: ' . $right; + $top = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getTop()) . 'in; '; + $htmlPage .= 'top-margin: ' . $top; + $htmlBody .= 'top-margin: ' . $top; + $bottom = PHPExcel_Shared_String::FormatNumber($pSheet->getPageMargins()->getBottom()) . 'in; '; + $htmlPage .= 'bottom-margin: ' . $bottom; + $htmlBody .= 'bottom-margin: ' . $bottom; + + $htmlPage .= "}\n"; + $htmlBody .= "}\n"; + + return "<style>\n" . $htmlPage . $htmlBody . "</style>\n"; + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/IWriter.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/IWriter.php new file mode 100755 index 0000000..4f6a597 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/IWriter.php @@ -0,0 +1,46 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_IWriter + * + * @category PHPExcel + * @package PHPExcel_Writer + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +interface PHPExcel_Writer_IWriter +{ + /** + * Save PHPExcel to file + * + * @param string $pFilename Name of the file to save + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = NULL); + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF.php new file mode 100755 index 0000000..ed31195 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF.php @@ -0,0 +1,90 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_PDF + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_PDF + * + * @category PHPExcel + * @package PHPExcel_Writer_PDF + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_PDF +{ + + /** + * The wrapper for the requested PDF rendering engine + * + * @var PHPExcel_Writer_PDF_Core + */ + private $_renderer = NULL; + + /** + * Instantiate a new renderer of the configured type within this container class + * + * @param PHPExcel $phpExcel PHPExcel object + * @throws PHPExcel_Writer_Exception when PDF library is not configured + */ + public function __construct(PHPExcel $phpExcel) + { + $pdfLibraryName = PHPExcel_Settings::getPdfRendererName(); + if (is_null($pdfLibraryName)) { + throw new PHPExcel_Writer_Exception("PDF Rendering library has not been defined."); + } + + $pdfLibraryPath = PHPExcel_Settings::getPdfRendererPath(); + if (is_null($pdfLibraryName)) { + throw new PHPExcel_Writer_Exception("PDF Rendering library path has not been defined."); + } + $includePath = str_replace('\\', '/', get_include_path()); + $rendererPath = str_replace('\\', '/', $pdfLibraryPath); + if (strpos($rendererPath, $includePath) === false) { + set_include_path(get_include_path() . PATH_SEPARATOR . $pdfLibraryPath); + } + + $rendererName = 'PHPExcel_Writer_PDF_' . $pdfLibraryName; + $this->_renderer = new $rendererName($phpExcel); + } + + + /** + * Magic method to handle direct calls to the configured PDF renderer wrapper class. + * + * @param string $name Renderer library method name + * @param mixed[] $arguments Array of arguments to pass to the renderer method + * @return mixed Returned data from the PDF renderer wrapper method + */ + public function __call($name, $arguments) + { + if ($this->_renderer === NULL) { + throw new PHPExcel_Writer_Exception("PDF Rendering library has not been defined."); + } + + return call_user_func_array(array($this->_renderer, $name), $arguments); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/Core.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/Core.php new file mode 100755 index 0000000..f058b59 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/Core.php @@ -0,0 +1,364 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_PDF + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** + * PHPExcel_Writer_PDF_Core + * + * @category PHPExcel + * @package PHPExcel_Writer_PDF + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +abstract class PHPExcel_Writer_PDF_Core extends PHPExcel_Writer_HTML +{ + /** + * Temporary storage directory + * + * @var string + */ + protected $_tempDir = ''; + + /** + * Font + * + * @var string + */ + protected $_font = 'freesans'; + + /** + * Orientation (Over-ride) + * + * @var string + */ + protected $_orientation = NULL; + + /** + * Paper size (Over-ride) + * + * @var int + */ + protected $_paperSize = NULL; + + + /** + * Temporary storage for Save Array Return type + * + * @var string + */ + private $_saveArrayReturnType; + + /** + * Paper Sizes xRef List + * + * @var array + */ + protected static $_paperSizes = array( + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER + => 'LETTER', // (8.5 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_SMALL + => 'LETTER', // (8.5 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_TABLOID + => array(792.00, 1224.00), // (11 in. by 17 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LEDGER + => array(1224.00, 792.00), // (17 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LEGAL + => 'LEGAL', // (8.5 in. by 14 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STATEMENT + => array(396.00, 612.00), // (5.5 in. by 8.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_EXECUTIVE + => 'EXECUTIVE', // (7.25 in. by 10.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3 + => 'A3', // (297 mm by 420 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4 + => 'A4', // (210 mm by 297 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_SMALL + => 'A4', // (210 mm by 297 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A5 + => 'A5', // (148 mm by 210 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_B4 + => 'B4', // (250 mm by 353 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_B5 + => 'B5', // (176 mm by 250 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_FOLIO + => 'FOLIO', // (8.5 in. by 13 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_QUARTO + => array(609.45, 779.53), // (215 mm by 275 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_1 + => array(720.00, 1008.00), // (10 in. by 14 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_2 + => array(792.00, 1224.00), // (11 in. by 17 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NOTE + => 'LETTER', // (8.5 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO9_ENVELOPE + => array(279.00, 639.00), // (3.875 in. by 8.875 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO10_ENVELOPE + => array(297.00, 684.00), // (4.125 in. by 9.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO11_ENVELOPE + => array(324.00, 747.00), // (4.5 in. by 10.375 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO12_ENVELOPE + => array(342.00, 792.00), // (4.75 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_NO14_ENVELOPE + => array(360.00, 828.00), // (5 in. by 11.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C + => array(1224.00, 1584.00), // (17 in. by 22 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_D + => array(1584.00, 2448.00), // (22 in. by 34 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_E + => array(2448.00, 3168.00), // (34 in. by 44 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_DL_ENVELOPE + => array(311.81, 623.62), // (110 mm by 220 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C5_ENVELOPE + => 'C5', // (162 mm by 229 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C3_ENVELOPE + => 'C3', // (324 mm by 458 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C4_ENVELOPE + => 'C4', // (229 mm by 324 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C6_ENVELOPE + => 'C6', // (114 mm by 162 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_C65_ENVELOPE + => array(323.15, 649.13), // (114 mm by 229 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_B4_ENVELOPE + => 'B4', // (250 mm by 353 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_B5_ENVELOPE + => 'B5', // (176 mm by 250 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_B6_ENVELOPE + => array(498.90, 354.33), // (176 mm by 125 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_ITALY_ENVELOPE + => array(311.81, 651.97), // (110 mm by 230 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_MONARCH_ENVELOPE + => array(279.00, 540.00), // (3.875 in. by 7.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_6_3_4_ENVELOPE + => array(261.00, 468.00), // (3.625 in. by 6.5 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_US_STANDARD_FANFOLD + => array(1071.00, 792.00), // (14.875 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_GERMAN_STANDARD_FANFOLD + => array(612.00, 864.00), // (8.5 in. by 12 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_GERMAN_LEGAL_FANFOLD + => 'FOLIO', // (8.5 in. by 13 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_ISO_B4 + => 'B4', // (250 mm by 353 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_JAPANESE_DOUBLE_POSTCARD + => array(566.93, 419.53), // (200 mm by 148 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_PAPER_1 + => array(648.00, 792.00), // (9 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_PAPER_2 + => array(720.00, 792.00), // (10 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_STANDARD_PAPER_3 + => array(1080.00, 792.00), // (15 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_INVITE_ENVELOPE + => array(623.62, 623.62), // (220 mm by 220 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_EXTRA_PAPER + => array(667.80, 864.00), // (9.275 in. by 12 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LEGAL_EXTRA_PAPER + => array(667.80, 1080.00), // (9.275 in. by 15 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_TABLOID_EXTRA_PAPER + => array(841.68, 1296.00), // (11.69 in. by 18 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_EXTRA_PAPER + => array(668.98, 912.76), // (236 mm by 322 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_TRANSVERSE_PAPER + => array(595.80, 792.00), // (8.275 in. by 11 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_TRANSVERSE_PAPER + => 'A4', // (210 mm by 297 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_EXTRA_TRANSVERSE_PAPER + => array(667.80, 864.00), // (9.275 in. by 12 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_SUPERA_SUPERA_A4_PAPER + => array(643.46, 1009.13), // (227 mm by 356 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_SUPERB_SUPERB_A3_PAPER + => array(864.57, 1380.47), // (305 mm by 487 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER_PLUS_PAPER + => array(612.00, 913.68), // (8.5 in. by 12.69 in.) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4_PLUS_PAPER + => array(595.28, 935.43), // (210 mm by 330 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A5_TRANSVERSE_PAPER + => 'A5', // (148 mm by 210 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_JIS_B5_TRANSVERSE_PAPER + => array(515.91, 728.50), // (182 mm by 257 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3_EXTRA_PAPER + => array(912.76, 1261.42), // (322 mm by 445 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A5_EXTRA_PAPER + => array(493.23, 666.14), // (174 mm by 235 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_ISO_B5_EXTRA_PAPER + => array(569.76, 782.36), // (201 mm by 276 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A2_PAPER + => 'A2', // (420 mm by 594 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3_TRANSVERSE_PAPER + => 'A3', // (297 mm by 420 mm) + PHPExcel_Worksheet_PageSetup::PAPERSIZE_A3_EXTRA_TRANSVERSE_PAPER + => array(912.76, 1261.42) // (322 mm by 445 mm) + ); + + /** + * Create a new PHPExcel_Writer_PDF + * + * @param PHPExcel $phpExcel PHPExcel object + */ + public function __construct(PHPExcel $phpExcel) + { + parent::__construct($phpExcel); + $this->setUseInlineCss(TRUE); + $this->_tempDir = PHPExcel_Shared_File::sys_get_temp_dir(); + } + + /** + * Get Font + * + * @return string + */ + public function getFont() + { + return $this->_font; + } + + /** + * Set font. Examples: + * 'arialunicid0-chinese-simplified' + * 'arialunicid0-chinese-traditional' + * 'arialunicid0-korean' + * 'arialunicid0-japanese' + * + * @param string $fontName + */ + public function setFont($fontName) + { + $this->_font = $fontName; + return $this; + } + + /** + * Get Paper Size + * + * @return int + */ + public function getPaperSize() + { + return $this->_paperSize; + } + + /** + * Set Paper Size + * + * @param string $pValue Paper size + * @return PHPExcel_Writer_PDF + */ + public function setPaperSize($pValue = PHPExcel_Worksheet_PageSetup::PAPERSIZE_LETTER) + { + $this->_paperSize = $pValue; + return $this; + } + + /** + * Get Orientation + * + * @return string + */ + public function getOrientation() + { + return $this->_orientation; + } + + /** + * Set Orientation + * + * @param string $pValue Page orientation + * @return PHPExcel_Writer_PDF + */ + public function setOrientation($pValue = PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) + { + $this->_orientation = $pValue; + return $this; + } + + /** + * Get temporary storage directory + * + * @return string + */ + public function getTempDir() + { + return $this->_tempDir; + } + + /** + * Set temporary storage directory + * + * @param string $pValue Temporary storage directory + * @throws PHPExcel_Writer_Exception when directory does not exist + * @return PHPExcel_Writer_PDF + */ + public function setTempDir($pValue = '') + { + if (is_dir($pValue)) { + $this->_tempDir = $pValue; + } else { + throw new PHPExcel_Writer_Exception("Directory does not exist: $pValue"); + } + return $this; + } + + /** + * Save PHPExcel to PDF file, pre-save + * + * @param string $pFilename Name of the file to save as + * @throws PHPExcel_Writer_Exception + */ + protected function prepareForSave($pFilename = NULL) + { + // garbage collect + $this->_phpExcel->garbageCollect(); + + $this->_saveArrayReturnType = PHPExcel_Calculation::getArrayReturnType(); + PHPExcel_Calculation::setArrayReturnType(PHPExcel_Calculation::RETURN_ARRAY_AS_VALUE); + + // Open file + $fileHandle = fopen($pFilename, 'w'); + if ($fileHandle === FALSE) { + throw new PHPExcel_Writer_Exception("Could not open file $pFilename for writing."); + } + + // Set PDF + $this->_isPdf = TRUE; + // Build CSS + $this->buildCSS(TRUE); + + return $fileHandle; + } + + /** + * Save PHPExcel to PDF file, post-save + * + * @param resource $fileHandle + * @throws PHPExcel_Writer_Exception + */ + protected function restoreStateAfterSave($fileHandle) + { + // Close file + fclose($fileHandle); + + PHPExcel_Calculation::setArrayReturnType($this->_saveArrayReturnType); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/DomPDF.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/DomPDF.php new file mode 100755 index 0000000..2edc2d0 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/DomPDF.php @@ -0,0 +1,120 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_PDF + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** Require DomPDF library */ +$pdfRendererClassFile = PHPExcel_Settings::getPdfRendererPath() . '/dompdf_config.inc.php'; +if (file_exists($pdfRendererClassFile)) { + require_once $pdfRendererClassFile; +} else { + throw new PHPExcel_Writer_Exception('Unable to load PDF Rendering library'); +} + +/** + * PHPExcel_Writer_PDF_DomPDF + * + * @category PHPExcel + * @package PHPExcel_Writer_PDF + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_PDF_DomPDF extends PHPExcel_Writer_PDF_Core implements PHPExcel_Writer_IWriter +{ + /** + * Create a new PHPExcel_Writer_PDF + * + * @param PHPExcel $phpExcel PHPExcel object + */ + public function __construct(PHPExcel $phpExcel) + { + parent::__construct($phpExcel); + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename Name of the file to save as + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = NULL) + { + $fileHandle = parent::prepareForSave($pFilename); + + // Default PDF paper size + $paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.) + + // Check for paper size and page orientation + if (is_null($this->getSheetIndex())) { + $orientation = ($this->_phpExcel->getSheet(0)->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet(0)->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet(0)->getPageMargins(); + } else { + $orientation = ($this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageMargins(); + } + + // Override Page Orientation + if (!is_null($this->getOrientation())) { + $orientation = ($this->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) + ? PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT + : $this->getOrientation(); + } + // Override Paper Size + if (!is_null($this->getPaperSize())) { + $printPaperSize = $this->getPaperSize(); + } + + if (isset(self::$_paperSizes[$printPaperSize])) { + $paperSize = self::$_paperSizes[$printPaperSize]; + } + + $orientation = ($orientation == 'L') ? 'landscape' : 'portrait'; + + // Create PDF + $pdf = new DOMPDF(); + $pdf->set_paper(strtolower($paperSize), $orientation); + + $pdf->load_html( + $this->generateHTMLHeader(FALSE) . + $this->generateSheetData() . + $this->generateHTMLFooter() + ); + $pdf->render(); + + // Write to file + fwrite($fileHandle, $pdf->output()); + + parent::restoreStateAfterSave($fileHandle); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/mPDF.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/mPDF.php new file mode 100755 index 0000000..e050814 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/mPDF.php @@ -0,0 +1,130 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_PDF + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** Require mPDF library */ +$pdfRendererClassFile = PHPExcel_Settings::getPdfRendererPath() . '/mpdf.php'; +if (file_exists($pdfRendererClassFile)) { + require_once $pdfRendererClassFile; +} else { + throw new PHPExcel_Writer_Exception('Unable to load PDF Rendering library'); +} + +/** + * PHPExcel_Writer_PDF_mPDF + * + * @category PHPExcel + * @package PHPExcel_Writer_PDF + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_PDF_mPDF extends PHPExcel_Writer_PDF_Core implements PHPExcel_Writer_IWriter +{ + /** + * Create a new PHPExcel_Writer_PDF + * + * @param PHPExcel $phpExcel PHPExcel object + */ + public function __construct(PHPExcel $phpExcel) + { + parent::__construct($phpExcel); + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename Name of the file to save as + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = NULL) + { + $fileHandle = parent::prepareForSave($pFilename); + + // Default PDF paper size + $paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.) + + // Check for paper size and page orientation + if (is_null($this->getSheetIndex())) { + $orientation = ($this->_phpExcel->getSheet(0)->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet(0)->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet(0)->getPageMargins(); + } else { + $orientation = ($this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageMargins(); + } + $this->setOrientation($orientation); + + // Override Page Orientation + if (!is_null($this->getOrientation())) { + $orientation = ($this->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_DEFAULT) + ? PHPExcel_Worksheet_PageSetup::ORIENTATION_PORTRAIT + : $this->getOrientation(); + } + $orientation = strtoupper($orientation); + + // Override Paper Size + if (!is_null($this->getPaperSize())) { + $printPaperSize = $this->getPaperSize(); + } + + if (isset(self::$_paperSizes[$printPaperSize])) { + $paperSize = self::$_paperSizes[$printPaperSize]; + } + + // Create PDF + $pdf = new mpdf(); + $ortmp = $orientation; + $pdf->_setPageSize(strtoupper($paperSize), $ortmp); + $pdf->DefOrientation = $orientation; + $pdf->AddPage($orientation); + + // Document info + $pdf->SetTitle($this->_phpExcel->getProperties()->getTitle()); + $pdf->SetAuthor($this->_phpExcel->getProperties()->getCreator()); + $pdf->SetSubject($this->_phpExcel->getProperties()->getSubject()); + $pdf->SetKeywords($this->_phpExcel->getProperties()->getKeywords()); + $pdf->SetCreator($this->_phpExcel->getProperties()->getCreator()); + + $pdf->WriteHTML( + $this->generateHTMLHeader(FALSE) . + $this->generateSheetData() . + $this->generateHTMLFooter() + ); + + // Write to file + fwrite($fileHandle, $pdf->Output('', 'S')); + + parent::restoreStateAfterSave($fileHandle); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/tcPDF.php b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/tcPDF.php new file mode 100755 index 0000000..1046dae --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/Writer/PDF/tcPDF.php @@ -0,0 +1,136 @@ +<?php +/** + * PHPExcel + * + * Copyright (c) 2006 - 2013 PHPExcel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * @category PHPExcel + * @package PHPExcel_Writer_PDF + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL + * @version 1.7.9, 2013-06-02 + */ + + +/** Require tcPDF library */ +$pdfRendererClassFile = PHPExcel_Settings::getPdfRendererPath() . '/tcpdf.php'; +if (file_exists($pdfRendererClassFile)) { + $k_path_url = PHPExcel_Settings::getPdfRendererPath(); + require_once $pdfRendererClassFile; +} else { + throw new PHPExcel_Writer_Exception('Unable to load PDF Rendering library'); +} + +/** + * PHPExcel_Writer_PDF_tcPDF + * + * @category PHPExcel + * @package PHPExcel_Writer_PDF + * @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) + */ +class PHPExcel_Writer_PDF_tcPDF extends PHPExcel_Writer_PDF_Core implements PHPExcel_Writer_IWriter +{ + /** + * Create a new PHPExcel_Writer_PDF + * + * @param PHPExcel $phpExcel PHPExcel object + */ + public function __construct(PHPExcel $phpExcel) + { + parent::__construct($phpExcel); + } + + /** + * Save PHPExcel to file + * + * @param string $pFilename Name of the file to save as + * @throws PHPExcel_Writer_Exception + */ + public function save($pFilename = NULL) + { + $fileHandle = parent::prepareForSave($pFilename); + + // Default PDF paper size + $paperSize = 'LETTER'; // Letter (8.5 in. by 11 in.) + + // Check for paper size and page orientation + if (is_null($this->getSheetIndex())) { + $orientation = ($this->_phpExcel->getSheet(0)->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet(0)->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet(0)->getPageMargins(); + } else { + $orientation = ($this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getOrientation() + == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + $printPaperSize = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageSetup()->getPaperSize(); + $printMargins = $this->_phpExcel->getSheet($this->getSheetIndex())->getPageMargins(); + } + + // Override Page Orientation + if (!is_null($this->getOrientation())) { + $orientation = ($this->getOrientation() == PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE) + ? 'L' + : 'P'; + } + // Override Paper Size + if (!is_null($this->getPaperSize())) { + $printPaperSize = $this->getPaperSize(); + } + + if (isset(self::$_paperSizes[$printPaperSize])) { + $paperSize = self::$_paperSizes[$printPaperSize]; + } + + + // Create PDF + $pdf = new TCPDF($orientation, 'pt', $paperSize); + $pdf->setFontSubsetting(FALSE); + // Set margins, converting inches to points (using 72 dpi) + $pdf->SetMargins($printMargins->getLeft() * 72, $printMargins->getTop() * 72, $printMargins->getRight() * 72); + $pdf->SetAutoPageBreak(TRUE, $printMargins->getBottom() * 72); + + $pdf->setPrintHeader(FALSE); + $pdf->setPrintFooter(FALSE); + + $pdf->AddPage(); + + // Set the appropriate font + $pdf->SetFont($this->getFont()); + $pdf->writeHTML( + $this->generateHTMLHeader(FALSE) . + $this->generateSheetData() . + $this->generateHTMLFooter() + ); + + // Document info + $pdf->SetTitle($this->_phpExcel->getProperties()->getTitle()); + $pdf->SetAuthor($this->_phpExcel->getProperties()->getCreator()); + $pdf->SetSubject($this->_phpExcel->getProperties()->getSubject()); + $pdf->SetKeywords($this->_phpExcel->getProperties()->getKeywords()); + $pdf->SetCreator($this->_phpExcel->getProperties()->getCreator()); + + // Write to file + fwrite($fileHandle, $pdf->output($pFilename, 'S')); + + parent::restoreStateAfterSave($fileHandle); + } + +} diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/cs/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/cs/config new file mode 100755 index 0000000..c6cfd86 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/cs/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = KÄ + + +## +## Excel Error Codes (For future use) +## +NULL = #NULL! +DIV0 = #DIV/0! +VALUE = #HODNOTA! +REF = #REF! +NAME = #NÃZEV? +NUM = #NUM! +NA = #N/A diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/cs/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/cs/functions new file mode 100755 index 0000000..40cfa16 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/cs/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions Funkce doplňků a automatizace +## +GETPIVOTDATA = ZÃSKATKONTDATA ## Vrátí data uložená v kontingenÄní tabulce. Pomocí funkce ZÃSKATKONTDATA můžete naÄíst souhrnná data z kontingenÄní tabulky, pokud jsou tato data v kontingenÄní sestavÄ› zobrazena. + + +## +## Cube functions Funkce pro práci s krychlemi +## +CUBEKPIMEMBER = CUBEKPIMEMBER ## Vrátí název, vlastnost a velikost klíÄového ukazatele výkonu (KUV) a zobrazí v buňce název a vlastnost. KlíÄový ukazatel výkonu je kvantifikovatelná veliÄina, například hrubý mÄ›síÄní zisk nebo Ätvrtletní obrat na zamÄ›stnance, která se používá pro sledování výkonnosti organizace. +CUBEMEMBER = CUBEMEMBER ## Vrátí Älen nebo n-tici v hierarchii krychle. Slouží k ověření, zda v krychli existuje Älen nebo n-tice. +CUBEMEMBERPROPERTY = CUBEMEMBERPROPERTY ## Vrátí hodnotu vlastnosti Älena v krychli. Slouží k ověření, zda v krychli existuje Älen s daným názvem, a k vrácení konkrétní vlastnosti tohoto Älena. +CUBERANKEDMEMBER = CUBERANKEDMEMBER ## Vrátí n-tý nebo poÅ™adový Älen sady. Použijte ji pro vrácení jednoho nebo více prvků sady, například obchodníka s nejvyšším obratem nebo deseti nejlepších studentů. +CUBESET = CUBESET ## Definuje vypoÄtenou sadu Älenů nebo n-tic odesláním výrazu sady do krychle na serveru, který vytvoří sadu a potom ji vrátí do aplikace Microsoft Office Excel. +CUBESETCOUNT = CUBESETCOUNT ## Vrátí poÄet položek v množinÄ› +CUBEVALUE = CUBEVALUE ## Vrátí úhrnnou hodnotu z krychle. + + +## +## Database functions Funkce databáze +## +DAVERAGE = DPRÅ®MÄšR ## Vrátí průmÄ›r vybraných položek databáze. +DCOUNT = DPOÄŒET ## SpoÄítá buňky databáze obsahující Äísla. +DCOUNTA = DPOÄŒET2 ## SpoÄítá buňky databáze, které nejsou prázdné. +DGET = DZÃSKAT ## Extrahuje z databáze jeden záznam splňující zadaná kritéria. +DMAX = DMAX ## Vrátí maximální hodnotu z vybraných položek databáze. +DMIN = DMIN ## Vrátí minimální hodnotu z vybraných položek databáze. +DPRODUCT = DSOUÄŒIN ## Vynásobí hodnoty urÄitého pole záznamů v databázi, které splňují daná kritéria. +DSTDEV = DSMODCH.VÃBÄšR ## Odhadne smÄ›rodatnou odchylku výbÄ›ru vybraných položek databáze. +DSTDEVP = DSMODCH ## VypoÄte smÄ›rodatnou odchylku základního souboru vybraných položek databáze. +DSUM = DSUMA ## SeÄte Äísla ve sloupcovém poli záznamů databáze, která splňují daná kritéria. +DVAR = DVAR.VÃBÄšR ## Odhadne rozptyl výbÄ›ru vybraných položek databáze. +DVARP = DVAR ## VypoÄte rozptyl základního souboru vybraných položek databáze. + + +## +## Date and time functions Funkce data a Äasu +## +DATE = DATUM ## Vrátí poÅ™adové Äíslo urÄitého data. +DATEVALUE = DATUMHODN ## PÅ™evede datum ve formÄ› textu na poÅ™adové Äíslo. +DAY = DEN ## PÅ™evede poÅ™adové Äíslo na den v mÄ›síci. +DAYS360 = ROK360 ## Vrátí poÄet dní mezi dvÄ›ma daty na základÄ› roku s 360 dny. +EDATE = EDATE ## Vrátí poÅ™adové Äíslo data, které oznaÄuje urÄený poÄet mÄ›síců pÅ™ed nebo po poÄáteÄním datu. +EOMONTH = EOMONTH ## Vrátí poÅ™adové Äíslo posledního dne mÄ›síce pÅ™ed nebo po zadaném poÄtu mÄ›síců. +HOUR = HODINA ## PÅ™evede poÅ™adové Äíslo na hodinu. +MINUTE = MINUTA ## PÅ™evede poÅ™adové Äíslo na minutu. +MONTH = MÄšSÃC ## PÅ™evede poÅ™adové Äíslo na mÄ›síc. +NETWORKDAYS = NETWORKDAYS ## Vrátí poÄet celých pracovních dní mezi dvÄ›ma daty. +NOW = NYNà ## Vrátí poÅ™adové Äíslo aktuálního data a Äasu. +SECOND = SEKUNDA ## PÅ™evede poÅ™adové Äíslo na sekundu. +TIME = ÄŒAS ## Vrátí poÅ™adové Äíslo urÄitého Äasu. +TIMEVALUE = ÄŒASHODN ## PÅ™evede Äas ve formÄ› textu na poÅ™adové Äíslo. +TODAY = DNES ## Vrátí poÅ™adové Äíslo dneÅ¡ního data. +WEEKDAY = DENTÃDNE ## PÅ™evede poÅ™adové Äíslo na den v týdnu. +WEEKNUM = WEEKNUM ## PÅ™evede poÅ™adové Äíslo na Äíslo pÅ™edstavující Äíselnou pozici týdne v roce. +WORKDAY = WORKDAY ## Vrátí poÅ™adové Äíslo data pÅ™ed nebo po zadaném poÄtu pracovních dní. +YEAR = ROK ## PÅ™evede poÅ™adové Äíslo na rok. +YEARFRAC = YEARFRAC ## Vrátí Äást roku vyjádÅ™enou zlomkem a pÅ™edstavující poÄet celých dní mezi poÄáteÄním a koncovým datem. + + +## +## Engineering functions Inženýrské funkce (Technické funkce) +## +BESSELI = BESSELI ## Vrátí modifikovanou Besselovu funkci In(x). +BESSELJ = BESSELJ ## Vrátí modifikovanou Besselovu funkci Jn(x). +BESSELK = BESSELK ## Vrátí modifikovanou Besselovu funkci Kn(x). +BESSELY = BESSELY ## Vrátí Besselovu funkci Yn(x). +BIN2DEC = BIN2DEC ## PÅ™evede binární Äíslo na desítkové. +BIN2HEX = BIN2HEX ## PÅ™evede binární Äíslo na Å¡estnáctkové. +BIN2OCT = BIN2OCT ## PÅ™evede binární Äíslo na osmiÄkové. +COMPLEX = COMPLEX ## PÅ™evede reálnou a imaginární Äást na komplexní Äíslo. +CONVERT = CONVERT ## PÅ™evede Äíslo do jiného jednotkového mÄ›rného systému. +DEC2BIN = DEC2BIN ## PÅ™evede desítkového Äísla na dvojkové +DEC2HEX = DEC2HEX ## PÅ™evede desítkové Äíslo na Å¡estnáctkové. +DEC2OCT = DEC2OCT ## PÅ™evede desítkové Äíslo na osmiÄkové. +DELTA = DELTA ## Testuje rovnost dvou hodnot. +ERF = ERF ## Vrátí chybovou funkci. +ERFC = ERFC ## Vrátí doplňkovou chybovou funkci. +GESTEP = GESTEP ## Testuje, zda je Äíslo vÄ›tší než mezní hodnota. +HEX2BIN = HEX2BIN ## PÅ™evede Å¡estnáctkové Äíslo na binární. +HEX2DEC = HEX2DEC ## PÅ™evede Å¡estnáctkové Äíslo na desítkové. +HEX2OCT = HEX2OCT ## PÅ™evede Å¡estnáctkové Äíslo na osmiÄkové. +IMABS = IMABS ## Vrátí absolutní hodnotu (modul) komplexního Äísla. +IMAGINARY = IMAGINARY ## Vrátí imaginární Äást komplexního Äísla. +IMARGUMENT = IMARGUMENT ## Vrátí argument théta, úhel vyjádÅ™ený v radiánech. +IMCONJUGATE = IMCONJUGATE ## Vrátí komplexnÄ› sdružené Äíslo ke komplexnímu Äíslu. +IMCOS = IMCOS ## Vrátí kosinus komplexního Äísla. +IMDIV = IMDIV ## Vrátí podíl dvou komplexních Äísel. +IMEXP = IMEXP ## Vrátí exponenciální tvar komplexního Äísla. +IMLN = IMLN ## Vrátí pÅ™irozený logaritmus komplexního Äísla. +IMLOG10 = IMLOG10 ## Vrátí dekadický logaritmus komplexního Äísla. +IMLOG2 = IMLOG2 ## Vrátí logaritmus komplexního Äísla pÅ™i základu 2. +IMPOWER = IMPOWER ## Vrátí komplexní Äíslo umocnÄ›né na celé Äíslo. +IMPRODUCT = IMPRODUCT ## Vrátí souÄin komplexních Äísel. +IMREAL = IMREAL ## Vrátí reálnou Äást komplexního Äísla. +IMSIN = IMSIN ## Vrátí sinus komplexního Äísla. +IMSQRT = IMSQRT ## Vrátí druhou odmocninu komplexního Äísla. +IMSUB = IMSUB ## Vrátí rozdíl mezi dvÄ›ma komplexními Äísly. +IMSUM = IMSUM ## Vrátí souÄet dvou komplexních Äísel. +OCT2BIN = OCT2BIN ## PÅ™evede osmiÄkové Äíslo na binární. +OCT2DEC = OCT2DEC ## PÅ™evede osmiÄkové Äíslo na desítkové. +OCT2HEX = OCT2HEX ## PÅ™evede osmiÄkové Äíslo na Å¡estnáctkové. + + +## +## Financial functions FinanÄní funkce +## +ACCRINT = ACCRINT ## Vrátí nahromadÄ›ný úrok z cenného papíru, ze kterého je úrok placen v pravidelných termínech. +ACCRINTM = ACCRINTM ## Vrátí nahromadÄ›ný úrok z cenného papíru, ze kterého je úrok placen k datu splatnosti. +AMORDEGRC = AMORDEGRC ## Vrátí lineární amortizaci v každém úÄetním období pomocí koeficientu amortizace. +AMORLINC = AMORLINC ## Vrátí lineární amortizaci v každém úÄetním období. +COUPDAYBS = COUPDAYBS ## Vrátí poÄet dnů od zaÄátku období placení kupónů do data splatnosti. +COUPDAYS = COUPDAYS ## Vrátí poÄet dnů v období placení kupónů, které obsahuje den zúÄtování. +COUPDAYSNC = COUPDAYSNC ## Vrátí poÄet dnů od data zúÄtování do následujícího data placení kupónu. +COUPNCD = COUPNCD ## Vrátí následující datum placení kupónu po datu zúÄtování. +COUPNUM = COUPNUM ## Vrátí poÄet kupónů splatných mezi datem zúÄtování a datem splatnosti. +COUPPCD = COUPPCD ## Vrátí pÅ™edchozí datum placení kupónu pÅ™ed datem zúÄtování. +CUMIPMT = CUMIPMT ## Vrátí kumulativní úrok splacený mezi dvÄ›ma obdobími. +CUMPRINC = CUMPRINC ## Vrátí kumulativní jistinu splacenou mezi dvÄ›ma obdobími půjÄky. +DB = ODPIS.ZRYCH ## Vrátí odpis aktiva za urÄité období pomocí degresivní metody odpisu s pevným zůstatkem. +DDB = ODPIS.ZRYCH2 ## Vrátí odpis aktiva za urÄité období pomocí dvojité degresivní metody odpisu nebo jiné metody, kterou zadáte. +DISC = DISC ## Vrátí diskontní sazbu cenného papíru. +DOLLARDE = DOLLARDE ## PÅ™evede Äástku v korunách vyjádÅ™enou zlomkem na Äástku v korunách vyjádÅ™enou desetinným Äíslem. +DOLLARFR = DOLLARFR ## PÅ™evede Äástku v korunách vyjádÅ™enou desetinným Äíslem na Äástku v korunách vyjádÅ™enou zlomkem. +DURATION = DURATION ## Vrátí roÄní dobu cenného papíru s pravidelnými úrokovými sazbami. +EFFECT = EFFECT ## Vrátí efektivní roÄní úrokovou sazbu. +FV = BUDHODNOTA ## Vrátí budoucí hodnotu investice. +FVSCHEDULE = FVSCHEDULE ## Vrátí budoucí hodnotu poÄáteÄní jistiny po použití série sazeb složitého úroku. +INTRATE = INTRATE ## Vrátí úrokovou sazbu plnÄ› investovaného cenného papíru. +IPMT = PLATBA.ÚROK ## Vrátí výšku úroku investice za dané období. +IRR = MÃRA.VÃNOSNOSTI ## Vrátí vnitÅ™ní výnosové procento série peněžních toků. +ISPMT = ISPMT ## VypoÄte výši úroku z investice zaplaceného bÄ›hem urÄitého období. +MDURATION = MDURATION ## Vrátí Macauleyho modifikovanou dobu cenného papíru o nominální hodnotÄ› 100 KÄ. +MIRR = MOD.MÃRA.VÃNOSNOSTI ## Vrátí vnitÅ™ní sazbu výnosu, pÅ™iÄemž kladné a záporné hodnoty peněžních prostÅ™edků jsou financovány podle různých sazeb. +NOMINAL = NOMINAL ## Vrátí nominální roÄní úrokovou sazbu. +NPER = POÄŒET.OBDOBà ## Vrátí poÄet období pro investici. +NPV = ÄŒISTÃ.SOUÄŒHODNOTA ## Vrátí Äistou souÄasnou hodnotu investice vypoÄítanou na základÄ› série pravidelných peněžních toků a diskontní sazby. +ODDFPRICE = ODDFPRICE ## Vrátí cenu cenného papíru o nominální hodnotÄ› 100 KÄ s odliÅ¡ným prvním obdobím. +ODDFYIELD = ODDFYIELD ## Vrátí výnos cenného papíru s odliÅ¡ným prvním obdobím. +ODDLPRICE = ODDLPRICE ## Vrátí cenu cenného papíru o nominální hodnotÄ› 100 KÄ s odliÅ¡ným posledním obdobím. +ODDLYIELD = ODDLYIELD ## Vrátí výnos cenného papíru s odliÅ¡ným posledním obdobím. +PMT = PLATBA ## Vrátí hodnotu pravidelné splátky anuity. +PPMT = PLATBA.ZÃKLAD ## Vrátí hodnotu splátky jistiny pro zadanou investici za dané období. +PRICE = PRICE ## Vrátí cenu cenného papíru o nominální hodnotÄ› 100 KÄ, ze kterého je úrok placen v pravidelných termínech. +PRICEDISC = PRICEDISC ## Vrátí cenu diskontního cenného papíru o nominální hodnotÄ› 100 KÄ. +PRICEMAT = PRICEMAT ## Vrátí cenu cenného papíru o nominální hodnotÄ› 100 KÄ, ze kterého je úrok placen k datu splatnosti. +PV = SOUÄŒHODNOTA ## Vrátí souÄasnou hodnotu investice. +RATE = ÚROKOVÃ.MÃRA ## Vrátí úrokovou sazbu vztaženou na období anuity. +RECEIVED = RECEIVED ## Vrátí Äástku obdrženou k datu splatnosti plnÄ› investovaného cenného papíru. +SLN = ODPIS.LIN ## Vrátí přímé odpisy aktiva pro jedno období. +SYD = ODPIS.NELIN ## Vrátí smÄ›rné Äíslo roÄních odpisů aktiva pro zadané období. +TBILLEQ = TBILLEQ ## Vrátí výnos smÄ›nky státní pokladny ekvivalentní výnosu obligace. +TBILLPRICE = TBILLPRICE ## Vrátí cenu smÄ›nky státní pokladny o nominální hodnotÄ› 100 KÄ. +TBILLYIELD = TBILLYIELD ## Vrátí výnos smÄ›nky státní pokladny. +VDB = ODPIS.ZA.INT ## Vrátí odpis aktiva pro urÄité období nebo Äást období pomocí degresivní metody odpisu. +XIRR = XIRR ## Vrátí vnitÅ™ní výnosnost pro harmonogram peněžních toků, který nemusí být nutnÄ› periodický. +XNPV = XNPV ## Vrátí Äistou souÄasnou hodnotu pro harmonogram peněžních toků, který nemusí být nutnÄ› periodický. +YIELD = YIELD ## Vrátí výnos cenného papíru, ze kterého je úrok placen v pravidelných termínech. +YIELDDISC = YIELDDISC ## Vrátí roÄní výnos diskontního cenného papíru, například smÄ›nky státní pokladny. +YIELDMAT = YIELDMAT ## Vrátí roÄní výnos cenného papíru, ze kterého je úrok placen k datu splatnosti. + + +## +## Information functions InformaÄní funkce +## +CELL = POLÃÄŒKO ## Vrátí informace o formátování, umístÄ›ní nebo obsahu buňky. +ERROR.TYPE = CHYBA.TYP ## Vrátí Äíslo odpovídající typu chyby. +INFO = O.PROSTŘEDà ## Vrátí informace o aktuálním pracovním prostÅ™edí. +ISBLANK = JE.PRÃZDNÉ ## Vrátí hodnotu PRAVDA, pokud se argument hodnota odkazuje na prázdnou buňku. +ISERR = JE.CHYBA ## Vrátí hodnotu PRAVDA, pokud je argument hodnota libovolná chybová hodnota (kromÄ› #N/A). +ISERROR = JE.CHYBHODN ## Vrátí hodnotu PRAVDA, pokud je argument hodnota libovolná chybová hodnota. +ISEVEN = ISEVEN ## Vrátí hodnotu PRAVDA, pokud je Äíslo sudé. +ISLOGICAL = JE.LOGHODN ## Vrátí hodnotu PRAVDA, pokud je argument hodnota logická hodnota. +ISNA = JE.NEDEF ## Vrátí hodnotu PRAVDA, pokud je argument hodnota chybová hodnota #N/A. +ISNONTEXT = JE.NETEXT ## Vrátí hodnotu PRAVDA, pokud argument hodnota není text. +ISNUMBER = JE.ÄŒÃSLO ## Vrátí hodnotu PRAVDA, pokud je argument hodnota Äíslo. +ISODD = ISODD ## Vrátí hodnotu PRAVDA, pokud je Äíslo liché. +ISREF = JE.ODKAZ ## Vrátí hodnotu PRAVDA, pokud je argument hodnota odkaz. +ISTEXT = JE.TEXT ## Vrátí hodnotu PRAVDA, pokud je argument hodnota text. +N = N ## Vrátí hodnotu pÅ™evedenou na Äíslo. +NA = NEDEF ## Vrátí chybovou hodnotu #N/A. +TYPE = TYP ## Vrátí Äíslo oznaÄující datový typ hodnoty. + + +## +## Logical functions Logické funkce +## +AND = A ## Vrátí hodnotu PRAVDA, mají-li vÅ¡echny argumenty hodnotu PRAVDA. +FALSE = NEPRAVDA ## Vrátí logickou hodnotu NEPRAVDA. +IF = KDYŽ ## UrÄí, který logický test má probÄ›hnout. +IFERROR = IFERROR ## Pokud je vzorec vyhodnocen jako chyba, vrátí zadanou hodnotu. V opaÄném případÄ› vrátí výsledek vzorce. +NOT = NE ## Provede logickou negaci argumentu funkce. +OR = NEBO ## Vrátí hodnotu PRAVDA, je-li alespoň jeden argument roven hodnotÄ› PRAVDA. +TRUE = PRAVDA ## Vrátí logickou hodnotu PRAVDA. + + +## +## Lookup and reference functions Vyhledávací funkce +## +ADDRESS = ODKAZ ## Vrátí textový odkaz na jednu buňku listu. +AREAS = POÄŒET.BLOKÅ® ## Vrátí poÄet oblastí v odkazu. +CHOOSE = ZVOLIT ## Zvolí hodnotu ze seznamu hodnot. +COLUMN = SLOUPEC ## Vrátí Äíslo sloupce odkazu. +COLUMNS = SLOUPCE ## Vrátí poÄet sloupců v odkazu. +HLOOKUP = VVYHLEDAT ## Prohledá horní řádek matice a vrátí hodnotu urÄené buňky. +HYPERLINK = HYPERTEXTOVÃ.ODKAZ ## Vytvoří zástupce nebo odkaz, který otevÅ™e dokument uložený na síťovém serveru, v síti intranet nebo Internet. +INDEX = INDEX ## Pomocí rejstříku zvolí hodnotu z odkazu nebo matice. +INDIRECT = NEPŘÃMÃ.ODKAZ ## Vrátí odkaz urÄený textovou hodnotou. +LOOKUP = VYHLEDAT ## Vyhledá hodnoty ve vektoru nebo matici. +MATCH = POZVYHLEDAT ## Vyhledá hodnoty v odkazu nebo matici. +OFFSET = POSUN ## Vrátí posun odkazu od zadaného odkazu. +ROW = ŘÃDEK ## Vrátí Äíslo řádku odkazu. +ROWS = ŘÃDKY ## Vrátí poÄet řádků v odkazu. +RTD = RTD ## NaÄte data reálného Äasu z programu, který podporuje automatizaci modelu COM (Automatizace: Způsob práce s objekty urÄité aplikace z jiné aplikace nebo nástroje pro vývoj. Automatizace (dříve nazývaná automatizace OLE) je poÄítaÄovým standardem a je funkcí modelu COM (Component Object Model).). +TRANSPOSE = TRANSPOZICE ## Vrátí transponovanou matici. +VLOOKUP = SVYHLEDAT ## Prohledá první sloupec matice, pÅ™esune kurzor v řádku a vrátí hodnotu buňky. + + +## +## Math and trigonometry functions Matematické a trigonometrické funkce +## +ABS = ABS ## Vrátí absolutní hodnotu Äísla. +ACOS = ARCCOS ## Vrátí arkuskosinus Äísla. +ACOSH = ARCCOSH ## Vrátí hyperbolický arkuskosinus Äísla. +ASIN = ARCSIN ## Vrátí arkussinus Äísla. +ASINH = ARCSINH ## Vrátí hyperbolický arkussinus Äísla. +ATAN = ARCTG ## Vrátí arkustangens Äísla. +ATAN2 = ARCTG2 ## Vrátí arkustangens x-ové a y-ové souÅ™adnice. +ATANH = ARCTGH ## Vrátí hyperbolický arkustangens Äísla. +CEILING = ZAOKR.NAHORU ## Zaokrouhlí Äíslo na nejbližší celé Äíslo nebo na nejbližší násobek zadané hodnoty. +COMBIN = KOMBINACE ## Vrátí poÄet kombinací pro daný poÄet položek. +COS = COS ## Vrátí kosinus Äísla. +COSH = COSH ## Vrátí hyperbolický kosinus Äísla. +DEGREES = DEGREES ## PÅ™evede radiány na stupnÄ›. +EVEN = ZAOKROUHLIT.NA.SUDÉ ## Zaokrouhlí Äíslo nahoru na nejbližší celé sudé Äíslo. +EXP = EXP ## Vrátí základ pÅ™irozeného logaritmu e umocnÄ›ný na zadané Äíslo. +FACT = FAKTORIÃL ## Vrátí faktoriál Äísla. +FACTDOUBLE = FACTDOUBLE ## Vrátí dvojitý faktoriál Äísla. +FLOOR = ZAOKR.DOLÅ® ## Zaokrouhlí Äíslo dolů, smÄ›rem k nule. +GCD = GCD ## Vrátí nejvÄ›tší spoleÄný dÄ›litel. +INT = CELÃ.ÄŒÃST ## Zaokrouhlí Äíslo dolů na nejbližší celé Äíslo. +LCM = LCM ## Vrátí nejmenší spoleÄný násobek. +LN = LN ## Vrátí pÅ™irozený logaritmus Äísla. +LOG = LOGZ ## Vrátí logaritmus Äísla pÅ™i zadaném základu. +LOG10 = LOG ## Vrátí dekadický logaritmus Äísla. +MDETERM = DETERMINANT ## Vrátí determinant matice. +MINVERSE = INVERZE ## Vrátí inverzní matici. +MMULT = SOUÄŒIN.MATIC ## Vrátí souÄin dvou matic. +MOD = MOD ## Vrátí zbytek po dÄ›lení. +MROUND = MROUND ## Vrátí Äíslo zaokrouhlené na požadovaný násobek. +MULTINOMIAL = MULTINOMIAL ## Vrátí mnohoÄlen z množiny Äísel. +ODD = ZAOKROUHLIT.NA.LICHÉ ## Zaokrouhlí Äíslo nahoru na nejbližší celé liché Äíslo. +PI = PI ## Vrátí hodnotu Äísla pí. +POWER = POWER ## Umocní Äíslo na zadanou mocninu. +PRODUCT = SOUÄŒIN ## Vynásobí argumenty funkce. +QUOTIENT = QUOTIENT ## Vrátí celou Äást dÄ›lení. +RADIANS = RADIANS ## PÅ™evede stupnÄ› na radiány. +RAND = NÃHÄŒÃSLO ## Vrátí náhodné Äíslo mezi 0 a 1. +RANDBETWEEN = RANDBETWEEN ## Vrátí náhodné Äíslo mezi zadanými Äísly. +ROMAN = ROMAN ## PÅ™evede arabskou Äíslici na římskou ve formátu textu. +ROUND = ZAOKROUHLIT ## Zaokrouhlí Äíslo na zadaný poÄet Äíslic. +ROUNDDOWN = ROUNDDOWN ## Zaokrouhlí Äíslo dolů, smÄ›rem k nule. +ROUNDUP = ROUNDUP ## Zaokrouhlí Äíslo nahoru, smÄ›rem od nuly. +SERIESSUM = SERIESSUM ## Vrátí souÄet mocninné Å™ady urÄené podle vzorce. +SIGN = SIGN ## Vrátí znaménko Äísla. +SIN = SIN ## Vrátí sinus daného úhlu. +SINH = SINH ## Vrátí hyperbolický sinus Äísla. +SQRT = ODMOCNINA ## Vrátí kladnou druhou odmocninu. +SQRTPI = SQRTPI ## Vrátí druhou odmocninu výrazu (Äíslo * pí). +SUBTOTAL = SUBTOTAL ## Vrátí souhrn v seznamu nebo databázi. +SUM = SUMA ## SeÄte argumenty funkce. +SUMIF = SUMIF ## SeÄte buňky vybrané podle zadaných kritérií. +SUMIFS = SUMIFS ## SeÄte buňky urÄené více zadanými podmínkami. +SUMPRODUCT = SOUÄŒIN.SKALÃRNà ## Vrátí souÄet souÄinů odpovídajících prvků matic. +SUMSQ = SUMA.ÄŒTVERCÅ® ## Vrátí souÄet Ätverců argumentů. +SUMX2MY2 = SUMX2MY2 ## Vrátí souÄet rozdílu Ätverců odpovídajících hodnot ve dvou maticích. +SUMX2PY2 = SUMX2PY2 ## Vrátí souÄet souÄtu Ätverců odpovídajících hodnot ve dvou maticích. +SUMXMY2 = SUMXMY2 ## Vrátí souÄet Ätverců rozdílů odpovídajících hodnot ve dvou maticích. +TAN = TGTG ## Vrátí tangens Äísla. +TANH = TGH ## Vrátí hyperbolický tangens Äísla. +TRUNC = USEKNOUT ## Zkrátí Äíslo na celé Äíslo. + + +## +## Statistical functions Statistické funkce +## +AVEDEV = PRÅ®MODCHYLKA ## Vrátí průmÄ›rnou hodnotu absolutních odchylek datových bodů od jejich stÅ™ední hodnoty. +AVERAGE = PRÅ®MÄšR ## Vrátí průmÄ›rnou hodnotu argumentů. +AVERAGEA = AVERAGEA ## Vrátí průmÄ›rnou hodnotu argumentů vÄetnÄ› Äísel, textu a logických hodnot. +AVERAGEIF = AVERAGEIF ## Vrátí průmÄ›rnou hodnotu (aritmetický průmÄ›r) vÅ¡ech bunÄ›k v oblasti, které vyhovují přísluÅ¡né podmínce. +AVERAGEIFS = AVERAGEIFS ## Vrátí průmÄ›rnou hodnotu (aritmetický průmÄ›r) vÅ¡ech bunÄ›k vyhovujících nÄ›kolika podmínkám. +BETADIST = BETADIST ## Vrátí hodnotu souÄtového rozdÄ›lení beta. +BETAINV = BETAINV ## Vrátí inverzní hodnotu souÄtového rozdÄ›lení pro zadané rozdÄ›lení beta. +BINOMDIST = BINOMDIST ## Vrátí hodnotu binomického rozdÄ›lení pravdÄ›podobnosti jednotlivých veliÄin. +CHIDIST = CHIDIST ## Vrátí jednostrannou pravdÄ›podobnost rozdÄ›lení chí-kvadrát. +CHIINV = CHIINV ## Vrátí hodnotu funkce inverzní k distribuÄní funkci jednostranné pravdÄ›podobnosti rozdÄ›lení chí-kvadrát. +CHITEST = CHITEST ## Vrátí test nezávislosti. +CONFIDENCE = CONFIDENCE ## Vrátí interval spolehlivosti pro stÅ™ední hodnotu základního souboru. +CORREL = CORREL ## Vrátí korelaÄní koeficient mezi dvÄ›ma množinami dat. +COUNT = POÄŒET ## Vrátí poÄet Äísel v seznamu argumentů. +COUNTA = POÄŒET2 ## Vrátí poÄet hodnot v seznamu argumentů. +COUNTBLANK = COUNTBLANK ## SpoÄítá poÄet prázdných bunÄ›k v oblasti. +COUNTIF = COUNTIF ## SpoÄítá buňky v oblasti, které odpovídají zadaným kritériím. +COUNTIFS = COUNTIFS ## SpoÄítá buňky v oblasti, které odpovídají více kritériím. +COVAR = COVAR ## Vrátí hodnotu kovariance, průmÄ›rnou hodnotu souÄinů párových odchylek +CRITBINOM = CRITBINOM ## Vrátí nejmenší hodnotu, pro kterou má souÄtové binomické rozdÄ›lení hodnotu vÄ›tší nebo rovnu hodnotÄ› kritéria. +DEVSQ = DEVSQ ## Vrátí souÄet Ätverců odchylek. +EXPONDIST = EXPONDIST ## Vrátí hodnotu exponenciálního rozdÄ›lení. +FDIST = FDIST ## Vrátí hodnotu rozdÄ›lení pravdÄ›podobnosti F. +FINV = FINV ## Vrátí hodnotu inverzní funkce k distribuÄní funkci rozdÄ›lení F. +FISHER = FISHER ## Vrátí hodnotu Fisherovy transformace. +FISHERINV = FISHERINV ## Vrátí hodnotu inverzní funkce k FisherovÄ› transformaci. +FORECAST = FORECAST ## Vrátí hodnotu lineárního trendu. +FREQUENCY = ÄŒETNOSTI ## Vrátí Äetnost rozdÄ›lení jako svislou matici. +FTEST = FTEST ## Vrátí výsledek F-testu. +GAMMADIST = GAMMADIST ## Vrátí hodnotu rozdÄ›lení gama. +GAMMAINV = GAMMAINV ## Vrátí hodnotu inverzní funkce k distribuÄní funkci souÄtového rozdÄ›lení gama. +GAMMALN = GAMMALN ## Vrátí pÅ™irozený logaritmus funkce gama, Γ(x). +GEOMEAN = GEOMEAN ## Vrátí geometrický průmÄ›r. +GROWTH = LOGLINTREND ## Vrátí hodnoty exponenciálního trendu. +HARMEAN = HARMEAN ## Vrátí harmonický průmÄ›r. +HYPGEOMDIST = HYPGEOMDIST ## Vrátí hodnotu hypergeometrického rozdÄ›lení. +INTERCEPT = INTERCEPT ## Vrátí úsek lineární regresní Äáry. +KURT = KURT ## Vrátí hodnotu excesu množiny dat. +LARGE = LARGE ## Vrátí k-tou nejvÄ›tší hodnotu množiny dat. +LINEST = LINREGRESE ## Vrátí parametry lineárního trendu. +LOGEST = LOGLINREGRESE ## Vrátí parametry exponenciálního trendu. +LOGINV = LOGINV ## Vrátí inverzní funkci k distribuÄní funkci logaritmicko-normálního rozdÄ›lení. +LOGNORMDIST = LOGNORMDIST ## Vrátí hodnotu souÄtového logaritmicko-normálního rozdÄ›lení. +MAX = MAX ## Vrátí maximální hodnotu seznamu argumentů. +MAXA = MAXA ## Vrátí maximální hodnotu seznamu argumentů vÄetnÄ› Äísel, textu a logických hodnot. +MEDIAN = MEDIAN ## Vrátí stÅ™ední hodnotu zadaných Äísel. +MIN = MIN ## Vrátí minimální hodnotu seznamu argumentů. +MINA = MINA ## Vrátí nejmenší hodnotu v seznamu argumentů vÄetnÄ› Äísel, textu a logických hodnot. +MODE = MODE ## Vrátí hodnotu, která se v množinÄ› dat vyskytuje nejÄastÄ›ji. +NEGBINOMDIST = NEGBINOMDIST ## Vrátí hodnotu negativního binomického rozdÄ›lení. +NORMDIST = NORMDIST ## Vrátí hodnotu normálního souÄtového rozdÄ›lení. +NORMINV = NORMINV ## Vrátí inverzní funkci k funkci normálního souÄtového rozdÄ›lení. +NORMSDIST = NORMSDIST ## Vrátí hodnotu standardního normálního souÄtového rozdÄ›lení. +NORMSINV = NORMSINV ## Vrátí inverzní funkci k funkci standardního normálního souÄtového rozdÄ›lení. +PEARSON = PEARSON ## Vrátí Pearsonův výsledný momentový korelaÄní koeficient. +PERCENTILE = PERCENTIL ## Vrátí hodnotu k-tého percentilu hodnot v oblasti. +PERCENTRANK = PERCENTRANK ## Vrátí poÅ™adí hodnoty v množinÄ› dat vyjádÅ™ené procentuální Äástí množiny dat. +PERMUT = PERMUTACE ## Vrátí poÄet permutací pro zadaný poÄet objektů. +POISSON = POISSON ## Vrátí hodnotu distribuÄní funkce Poissonova rozdÄ›lení. +PROB = PROB ## Vrátí pravdÄ›podobnost výskytu hodnot v oblasti mezi dvÄ›ma mezními hodnotami. +QUARTILE = QUARTIL ## Vrátí hodnotu kvartilu množiny dat. +RANK = RANK ## Vrátí poÅ™adí Äísla v seznamu Äísel. +RSQ = RKQ ## Vrátí druhou mocninu Pearsonova výsledného momentového korelaÄního koeficientu. +SKEW = SKEW ## Vrátí zeÅ¡ikmení rozdÄ›lení. +SLOPE = SLOPE ## Vrátí smÄ›rnici lineární regresní Äáry. +SMALL = SMALL ## Vrátí k-tou nejmenší hodnotu množiny dat. +STANDARDIZE = STANDARDIZE ## Vrátí normalizovanou hodnotu. +STDEV = SMODCH.VÃBÄšR ## VypoÄte smÄ›rodatnou odchylku výbÄ›ru. +STDEVA = STDEVA ## VypoÄte smÄ›rodatnou odchylku výbÄ›ru vÄetnÄ› Äísel, textu a logických hodnot. +STDEVP = SMODCH ## VypoÄte smÄ›rodatnou odchylku základního souboru. +STDEVPA = STDEVPA ## VypoÄte smÄ›rodatnou odchylku základního souboru vÄetnÄ› Äísel, textu a logických hodnot. +STEYX = STEYX ## Vrátí standardní chybu pÅ™edpovÄ›zené hodnoty y pro každou hodnotu x v regresi. +TDIST = TDIST ## Vrátí hodnotu Studentova t-rozdÄ›lení. +TINV = TINV ## Vrátí inverzní funkci k distribuÄní funkci Studentova t-rozdÄ›lení. +TREND = LINTREND ## Vrátí hodnoty lineárního trendu. +TRIMMEAN = TRIMMEAN ## Vrátí stÅ™ední hodnotu vnitÅ™ní Äásti množiny dat. +TTEST = TTEST ## Vrátí pravdÄ›podobnost spojenou se Studentovým t-testem. +VAR = VAR.VÃBÄšR ## VypoÄte rozptyl výbÄ›ru. +VARA = VARA ## VypoÄte rozptyl výbÄ›ru vÄetnÄ› Äísel, textu a logických hodnot. +VARP = VAR ## VypoÄte rozptyl základního souboru. +VARPA = VARPA ## VypoÄte rozptyl základního souboru vÄetnÄ› Äísel, textu a logických hodnot. +WEIBULL = WEIBULL ## Vrátí hodnotu Weibullova rozdÄ›lení. +ZTEST = ZTEST ## Vrátí jednostrannou P-hodnotu z-testu. + + +## +## Text functions Textové funkce +## +ASC = ASC ## ZmÄ›ní znaky s plnou šířkou (dvoubajtové)v Å™etÄ›zci znaků na znaky s poloviÄní šířkou (jednobajtové). +BAHTTEXT = BAHTTEXT ## PÅ™evede Äíslo na text ve formátu, mÄ›ny ß (baht). +CHAR = ZNAK ## Vrátí znak urÄený Äíslem kódu. +CLEAN = VYÄŒISTIT ## Odebere z textu vÅ¡echny netisknutelné znaky. +CODE = KÓD ## Vrátí Äíselný kód prvního znaku zadaného textového Å™etÄ›zce. +CONCATENATE = CONCATENATE ## Spojí nÄ›kolik textových položek do jedné. +DOLLAR = KÄŒ ## PÅ™evede Äíslo na text ve formátu mÄ›ny KÄ (Äeská koruna). +EXACT = STEJNÉ ## Zkontroluje, zda jsou dvÄ› textové hodnoty shodné. +FIND = NAJÃT ## Nalezne textovou hodnotu uvnitÅ™ jiné (rozliÅ¡uje malá a velká písmena). +FINDB = FINDB ## Nalezne textovou hodnotu uvnitÅ™ jiné (rozliÅ¡uje malá a velká písmena). +FIXED = ZAOKROUHLIT.NA.TEXT ## Zformátuje Äíslo jako text s pevným poÄtem desetinných míst. +JIS = JIS ## ZmÄ›ní znaky s poloviÄní šířkou (jednobajtové) v Å™etÄ›zci znaků na znaky s plnou šířkou (dvoubajtové). +LEFT = ZLEVA ## Vrátí první znaky textové hodnoty umístÄ›né nejvíce vlevo. +LEFTB = LEFTB ## Vrátí první znaky textové hodnoty umístÄ›né nejvíce vlevo. +LEN = DÉLKA ## Vrátí poÄet znaků textového Å™etÄ›zce. +LENB = LENB ## Vrátí poÄet znaků textového Å™etÄ›zce. +LOWER = MALà ## PÅ™evede text na malá písmena. +MID = ÄŒÃST ## Vrátí urÄitý poÄet znaků textového Å™etÄ›zce poÄínaje zadaným místem. +MIDB = MIDB ## Vrátí urÄitý poÄet znaků textového Å™etÄ›zce poÄínaje zadaným místem. +PHONETIC = ZVUKOVÉ ## Extrahuje fonetické znaky (furigana) z textového Å™etÄ›zce. +PROPER = VELKÃ2 ## PÅ™evede první písmeno každého slova textové hodnoty na velké. +REPLACE = NAHRADIT ## Nahradí znaky uvnitÅ™ textu. +REPLACEB = NAHRADITB ## Nahradí znaky uvnitÅ™ textu. +REPT = OPAKOVAT ## Zopakuje text podle zadaného poÄtu opakování. +RIGHT = ZPRAVA ## Vrátí první znaky textové hodnoty umístÄ›né nejvíce vpravo. +RIGHTB = RIGHTB ## Vrátí první znaky textové hodnoty umístÄ›né nejvíce vpravo. +SEARCH = HLEDAT ## Nalezne textovou hodnotu uvnitÅ™ jiné (malá a velká písmena nejsou rozliÅ¡ována). +SEARCHB = SEARCHB ## Nalezne textovou hodnotu uvnitÅ™ jiné (malá a velká písmena nejsou rozliÅ¡ována). +SUBSTITUTE = DOSADIT ## V textovém Å™etÄ›zci nahradí starý text novým. +T = T ## PÅ™evede argumenty na text. +TEXT = HODNOTA.NA.TEXT ## Zformátuje Äíslo a pÅ™evede ho na text. +TRIM = PROÄŒISTIT ## Odstraní z textu mezery. +UPPER = VELKà ## PÅ™evede text na velká písmena. +VALUE = HODNOTA ## PÅ™evede textový argument na Äíslo. diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/da/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/da/config new file mode 100755 index 0000000..20496cf --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/da/config @@ -0,0 +1,48 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = kr + + + +## +## Excel Error Codes (For future use) +## +NULL = #NUL! +DIV0 = #DIVISION/0! +VALUE = #VÆRDI! +REF = #REFERENCE! +NAME = #NAVN? +NUM = #NUM! +NA = #I/T diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/da/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/da/functions new file mode 100755 index 0000000..eff78cc --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/da/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions Tilføjelsesprogram- og automatiseringsfunktioner +## +GETPIVOTDATA = HENTPIVOTDATA ## Returnerer data, der er lagret i en pivottabelrapport + + +## +## Cube functions Kubefunktioner +## +CUBEKPIMEMBER = KUBE.KPI.MEDLEM ## Returnerer navn, egenskab og mÃ¥l for en KPI-indikator og viser navnet og egenskaben i cellen. En KPI-indikator er en mÃ¥lbar størrelse, f.eks. bruttooverskud pr. mÃ¥ned eller personaleudskiftning pr. kvartal, der bruges til at overvÃ¥ge en organisations præstationer. +CUBEMEMBER = KUBE.MEDLEM ## Returnerer et medlem eller en tupel fra kubehierarkiet. Bruges til at validere, om et medlem eller en tupel findes i kuben. +CUBEMEMBERPROPERTY = KUBEMEDLEM.EGENSKAB ## Returnerer værdien af en egenskab for et medlem i kuben. Bruges til at validere, om et medlemsnavn findes i kuben, og returnere den angivne egenskab for medlemmet. +CUBERANKEDMEMBER = KUBEMEDLEM.RANG ## Returnerer det n'te eller rangordnede medlem i et sæt. Bruges til at returnere et eller flere elementer i et sæt, f.eks. topsælgere eller de 10 bedste elever. +CUBESET = KUBESÆT ## Definerer et beregnet sæt medlemmer eller tupler ved at sende et sætudtryk til kuben pÃ¥ serveren, som opretter sættet og returnerer det til Microsoft Office Excel. +CUBESETCOUNT = KUBESÆT.TÆL ## Returnerer antallet af elementer i et sæt. +CUBEVALUE = KUBEVÆRDI ## Returnerer en sammenlagt (aggregeret) værdi fra en kube. + + +## +## Database functions Databasefunktioner +## +DAVERAGE = DMIDDEL ## Returnerer gennemsnittet af markerede databaseposter +DCOUNT = DTÆL ## Tæller de celler, der indeholder tal, i en database +DCOUNTA = DTÆLV ## Tæller udfyldte celler i en database +DGET = DHENT ## Uddrager en enkelt post, der opfylder de angivne kriterier, fra en database +DMAX = DMAKS ## Returnerer den største værdi blandt markerede databaseposter +DMIN = DMIN ## Returnerer den mindste værdi blandt markerede databaseposter +DPRODUCT = DPRODUKT ## Ganger værdierne i et bestemt felt med poster, der opfylder kriterierne i en database +DSTDEV = DSTDAFV ## Beregner et skøn over standardafvigelsen baseret pÃ¥ en stikprøve af markerede databaseposter +DSTDEVP = DSTDAFVP ## Beregner standardafvigelsen baseret pÃ¥ hele populationen af markerede databaseposter +DSUM = DSUM ## Sammenlægger de tal i feltkolonnen i databasen, der opfylder kriterierne +DVAR = DVARIANS ## Beregner varians baseret pÃ¥ en stikprøve af markerede databaseposter +DVARP = DVARIANSP ## Beregner varians baseret pÃ¥ hele populationen af markerede databaseposter + + +## +## Date and time functions Dato- og klokkeslætsfunktioner +## +DATE = DATO ## Returnerer serienummeret for en bestemt dato +DATEVALUE = DATOVÆRDI ## Konverterer en dato i form af tekst til et serienummer +DAY = DAG ## Konverterer et serienummer til en dag i mÃ¥neden +DAYS360 = DAGE360 ## Beregner antallet af dage mellem to datoer pÃ¥ grundlag af et Ã¥r med 360 dage +EDATE = EDATO ## Returnerer serienummeret for den dato, der ligger det angivne antal mÃ¥neder før eller efter startdatoen +EOMONTH = SLUT.PÃ….MÃ…NED ## Returnerer serienummeret pÃ¥ den sidste dag i mÃ¥neden før eller efter et angivet antal mÃ¥neder +HOUR = TIME ## Konverterer et serienummer til en time +MINUTE = MINUT ## Konverterer et serienummer til et minut +MONTH = MÃ…NED ## Konverterer et serienummer til en mÃ¥ned +NETWORKDAYS = ANTAL.ARBEJDSDAGE ## Returnerer antallet af hele arbejdsdage mellem to datoer +NOW = NU ## Returnerer serienummeret for den aktuelle dato eller det aktuelle klokkeslæt +SECOND = SEKUND ## Konverterer et serienummer til et sekund +TIME = KLOKKESLÆT ## Returnerer serienummeret for et bestemt klokkeslæt +TIMEVALUE = TIDSVÆRDI ## Konverterer et klokkeslæt i form af tekst til et serienummer +TODAY = IDAG ## Returnerer serienummeret for dags dato +WEEKDAY = UGEDAG ## Konverterer et serienummer til en ugedag +WEEKNUM = UGE.NR ## Konverterer et serienummer til et tal, der angiver ugenummeret i Ã¥ret +WORKDAY = ARBEJDSDAG ## Returnerer serienummeret for dagen før eller efter det angivne antal arbejdsdage +YEAR = Ã…R ## Konverterer et serienummer til et Ã¥r +YEARFRAC = Ã…R.BRØK ## Returnerer Ã¥rsbrøken, der repræsenterer antallet af hele dage mellem startdato og slutdato + + +## +## Engineering functions Tekniske funktioner +## +BESSELI = BESSELI ## Returnerer den modificerede Bessel-funktion In(x) +BESSELJ = BESSELJ ## Returnerer Bessel-funktionen Jn(x) +BESSELK = BESSELK ## Returnerer den modificerede Bessel-funktion Kn(x) +BESSELY = BESSELY ## Returnerer Bessel-funktionen Yn(x) +BIN2DEC = BIN.TIL.DEC ## Konverterer et binært tal til et decimaltal +BIN2HEX = BIN.TIL.HEX ## Konverterer et binært tal til et heksadecimalt tal +BIN2OCT = BIN.TIL.OKT ## Konverterer et binært tal til et oktaltal. +COMPLEX = KOMPLEKS ## Konverterer reelle og imaginære koefficienter til et komplekst tal +CONVERT = KONVERTER ## Konverterer et tal fra én mÃ¥leenhed til en anden +DEC2BIN = DEC.TIL.BIN ## Konverterer et decimaltal til et binært tal +DEC2HEX = DEC.TIL.HEX ## Konverterer et decimaltal til et heksadecimalt tal +DEC2OCT = DEC.TIL.OKT ## Konverterer et decimaltal til et oktaltal +DELTA = DELTA ## Tester, om to værdier er ens +ERF = FEJLFUNK ## Returner fejlfunktionen +ERFC = FEJLFUNK.KOMP ## Returnerer den komplementære fejlfunktion +GESTEP = GETRIN ## Tester, om et tal er større end en grænseværdi +HEX2BIN = HEX.TIL.BIN ## Konverterer et heksadecimalt tal til et binært tal +HEX2DEC = HEX.TIL.DEC ## Konverterer et decimaltal til et heksadecimalt tal +HEX2OCT = HEX.TIL.OKT ## Konverterer et heksadecimalt tal til et oktaltal +IMABS = IMAGABS ## Returnerer den absolutte værdi (modulus) for et komplekst tal +IMAGINARY = IMAGINÆR ## Returnerer den imaginære koefficient for et komplekst tal +IMARGUMENT = IMAGARGUMENT ## Returnerer argumentet theta, en vinkel udtrykt i radianer +IMCONJUGATE = IMAGKONJUGERE ## Returnerer den komplekse konjugation af et komplekst tal +IMCOS = IMAGCOS ## Returnerer et komplekst tals cosinus +IMDIV = IMAGDIV ## Returnerer kvotienten for to komplekse tal +IMEXP = IMAGEKSP ## Returnerer et komplekst tals eksponentialfunktion +IMLN = IMAGLN ## Returnerer et komplekst tals naturlige logaritme +IMLOG10 = IMAGLOG10 ## Returnerer et komplekst tals sædvanlige logaritme (titalslogaritme) +IMLOG2 = IMAGLOG2 ## Returnerer et komplekst tals sædvanlige logaritme (totalslogaritme) +IMPOWER = IMAGPOTENS ## Returnerer et komplekst tal opløftet i en heltalspotens +IMPRODUCT = IMAGPRODUKT ## Returnerer produktet af komplekse tal +IMREAL = IMAGREELT ## Returnerer den reelle koefficient for et komplekst tal +IMSIN = IMAGSIN ## Returnerer et komplekst tals sinus +IMSQRT = IMAGKVROD ## Returnerer et komplekst tals kvadratrod +IMSUB = IMAGSUB ## Returnerer forskellen mellem to komplekse tal +IMSUM = IMAGSUM ## Returnerer summen af komplekse tal +OCT2BIN = OKT.TIL.BIN ## Konverterer et oktaltal til et binært tal +OCT2DEC = OKT.TIL.DEC ## Konverterer et oktaltal til et decimaltal +OCT2HEX = OKT.TIL.HEX ## Konverterer et oktaltal til et heksadecimalt tal + + +## +## Financial functions Finansielle funktioner +## +ACCRINT = PÃ…LØBRENTE ## Returnerer den pÃ¥løbne rente for et værdipapir med periodiske renteudbetalinger +ACCRINTM = PÃ…LØBRENTE.UDLØB ## Returnerer den pÃ¥løbne rente for et værdipapir, hvor renteudbetalingen finder sted ved papirets udløb +AMORDEGRC = AMORDEGRC ## Returnerer afskrivningsbeløbet for hver regnskabsperiode ved hjælp af en afskrivningskoefficient +AMORLINC = AMORLINC ## Returnerer afskrivningsbeløbet for hver regnskabsperiode +COUPDAYBS = KUPONDAGE.SA ## Returnerer antallet af dage fra starten af kuponperioden til afregningsdatoen +COUPDAYS = KUPONDAGE.A ## Returnerer antallet af dage fra begyndelsen af kuponperioden til afregningsdatoen +COUPDAYSNC = KUPONDAGE.ANK ## Returnerer antallet af dage i den kuponperiode, der indeholder afregningsdatoen +COUPNCD = KUPONDAG.NÆSTE ## Returnerer den næste kupondato efter afregningsdatoen +COUPNUM = KUPONBETALINGER ## Returnerer antallet af kuponudbetalinger mellem afregnings- og udløbsdatoen +COUPPCD = KUPONDAG.FORRIGE ## Returnerer den forrige kupondato før afregningsdatoen +CUMIPMT = AKKUM.RENTE ## Returnerer den akkumulerede rente, der betales pÃ¥ et lÃ¥n mellem to perioder +CUMPRINC = AKKUM.HOVEDSTOL ## Returnerer den akkumulerede nedbringelse af hovedstol mellem to perioder +DB = DB ## Returnerer afskrivningen pÃ¥ et aktiv i en angivet periode ved anvendelse af saldometoden +DDB = DSA ## Returnerer afskrivningsbeløbet for et aktiv over en bestemt periode ved anvendelse af dobbeltsaldometoden eller en anden afskrivningsmetode, som du angiver +DISC = DISKONTO ## Returnerer et værdipapirs diskonto +DOLLARDE = KR.DECIMAL ## Konverterer en kronepris udtrykt som brøk til en kronepris udtrykt som decimaltal +DOLLARFR = KR.BRØK ## Konverterer en kronepris udtrykt som decimaltal til en kronepris udtrykt som brøk +DURATION = VARIGHED ## Returnerer den Ã¥rlige løbetid for et værdipapir med periodiske renteudbetalinger +EFFECT = EFFEKTIV.RENTE ## Returnerer den Ã¥rlige effektive rente +FV = FV ## Returnerer fremtidsværdien af en investering +FVSCHEDULE = FVTABEL ## Returnerer den fremtidige værdi af en hovedstol, nÃ¥r der er tilskrevet rente og rentes rente efter forskellige rentesatser +INTRATE = RENTEFOD ## Returnerer renten pÃ¥ et fuldt ud investeret værdipapir +IPMT = R.YDELSE ## Returnerer renten fra en investering for en given periode +IRR = IA ## Returnerer den interne rente for en række pengestrømme +ISPMT = ISPMT ## Beregner den betalte rente i løbet af en bestemt investeringsperiode +MDURATION = MVARIGHED ## Returnerer Macauleys modificerede løbetid for et værdipapir med en formodet pari pÃ¥ kr. 100 +MIRR = MIA ## Returnerer den interne forrentning, hvor positive og negative pengestrømme finansieres til forskellig rente +NOMINAL = NOMINEL ## Returnerer den Ã¥rlige nominelle rente +NPER = NPER ## Returnerer antallet af perioder for en investering +NPV = NUTIDSVÆRDI ## Returnerer nettonutidsværdien for en investering baseret pÃ¥ en række periodiske pengestrømme og en diskonteringssats +ODDFPRICE = ULIGE.KURS.PÃ…LYDENDE ## Returnerer kursen pr. kr. 100 nominel værdi for et værdipapir med en ulige (kort eller lang) første periode +ODDFYIELD = ULIGE.FØRSTE.AFKAST ## Returnerer afkastet for et værdipapir med ulige første periode +ODDLPRICE = ULIGE.SIDSTE.KURS ## Returnerer kursen pr. kr. 100 nominel værdi for et værdipapir med ulige sidste periode +ODDLYIELD = ULIGE.SIDSTE.AFKAST ## Returnerer afkastet for et værdipapir med ulige sidste periode +PMT = YDELSE ## Returnerer renten fra en investering for en given periode +PPMT = H.YDELSE ## Returnerer ydelsen pÃ¥ hovedstolen for en investering i en given periode +PRICE = KURS ## Returnerer kursen pr. kr 100 nominel værdi for et værdipapir med periodiske renteudbetalinger +PRICEDISC = KURS.DISKONTO ## Returnerer kursen pr. kr 100 nominel værdi for et diskonteret værdipapir +PRICEMAT = KURS.UDLØB ## Returnerer kursen pr. kr 100 nominel værdi for et værdipapir, hvor renten udbetales ved papirets udløb +PV = NV ## Returnerer den nuværende værdi af en investering +RATE = RENTE ## Returnerer renten i hver periode for en annuitet +RECEIVED = MODTAGET.VED.UDLØB ## Returnerer det beløb, der modtages ved udløbet af et fuldt ud investeret værdipapir +SLN = LA ## Returnerer den lineære afskrivning for et aktiv i en enkelt periode +SYD = Ã…RSAFSKRIVNING ## Returnerer den Ã¥rlige afskrivning pÃ¥ et aktiv i en bestemt periode +TBILLEQ = STATSOBLIGATION ## Returnerer det obligationsækvivalente afkast for en statsobligation +TBILLPRICE = STATSOBLIGATION.KURS ## Returnerer kursen pr. kr 100 nominel værdi for en statsobligation +TBILLYIELD = STATSOBLIGATION.AFKAST ## Returnerer en afkastet pÃ¥ en statsobligation +VDB = VSA ## Returnerer afskrivningen pÃ¥ et aktiv i en angivet periode, herunder delperioder, ved brug af dobbeltsaldometoden +XIRR = INTERN.RENTE ## Returnerer den interne rente for en plan over pengestrømme, der ikke behøver at være periodiske +XNPV = NETTO.NUTIDSVÆRDI ## Returnerer nutidsværdien for en plan over pengestrømme, der ikke behøver at være periodiske +YIELD = AFKAST ## Returnerer afkastet for et værdipapir med periodiske renteudbetalinger +YIELDDISC = AFKAST.DISKONTO ## Returnerer det Ã¥rlige afkast for et diskonteret værdipapir, f.eks. en statsobligation +YIELDMAT = AFKAST.UDLØBSDATO ## Returnerer det Ã¥rlige afkast for et værdipapir, hvor renten udbetales ved papirets udløb + + +## +## Information functions Informationsfunktioner +## +CELL = CELLE ## Returnerer oplysninger om formatering, placering eller indhold af en celle +ERROR.TYPE = FEJLTYPE ## Returnerer et tal, der svarer til en fejltype +INFO = INFO ## Returnerer oplysninger om det aktuelle operativmiljø +ISBLANK = ER.TOM ## Returnerer SAND, hvis værdien er tom +ISERR = ER.FJL ## Returnerer SAND, hvis værdien er en fejlværdi undtagen #I/T +ISERROR = ER.FEJL ## Returnerer SAND, hvis værdien er en fejlværdi +ISEVEN = ER.LIGE ## Returnerer SAND, hvis tallet er lige +ISLOGICAL = ER.LOGISK ## Returnerer SAND, hvis værdien er en logisk værdi +ISNA = ER.IKKE.TILGÆNGELIG ## Returnerer SAND, hvis værdien er fejlværdien #I/T +ISNONTEXT = ER.IKKE.TEKST ## Returnerer SAND, hvis værdien ikke er tekst +ISNUMBER = ER.TAL ## Returnerer SAND, hvis værdien er et tal +ISODD = ER.ULIGE ## Returnerer SAND, hvis tallet er ulige +ISREF = ER.REFERENCE ## Returnerer SAND, hvis værdien er en reference +ISTEXT = ER.TEKST ## Returnerer SAND, hvis værdien er tekst +N = TAL ## Returnerer en værdi konverteret til et tal +NA = IKKE.TILGÆNGELIG ## Returnerer fejlværdien #I/T +TYPE = VÆRDITYPE ## Returnerer et tal, der angiver datatypen for en værdi + + +## +## Logical functions Logiske funktioner +## +AND = OG ## Returnerer SAND, hvis alle argumenterne er sande +FALSE = FALSK ## Returnerer den logiske værdi FALSK +IF = HVIS ## Angiver en logisk test, der skal udføres +IFERROR = HVIS.FEJL ## Returnerer en værdi, du angiver, hvis en formel evauleres som en fejl. Returnerer i modsat fald resultatet af formlen +NOT = IKKE ## Vender argumentets logik om +OR = ELLER ## Returneret værdien SAND, hvis mindst ét argument er sandt +TRUE = SAND ## Returnerer den logiske værdi SAND + + +## +## Lookup and reference functions Opslags- og referencefunktioner +## +ADDRESS = ADRESSE ## Returnerer en reference som tekst til en enkelt celle i et regneark +AREAS = OMRÃ…DER ## Returnerer antallet af omrÃ¥der i en reference +CHOOSE = VÆLG ## Vælger en værdi pÃ¥ en liste med værdier +COLUMN = KOLONNE ## Returnerer kolonnenummeret i en reference +COLUMNS = KOLONNER ## Returnerer antallet af kolonner i en reference +HLOOKUP = VOPSLAG ## Søger i den øverste række af en matrix og returnerer værdien af den angivne celle +HYPERLINK = HYPERLINK ## Opretter en genvej kaldet et hyperlink, der Ã¥bner et dokument, som er lagret pÃ¥ en netværksserver, pÃ¥ et intranet eller pÃ¥ internettet +INDEX = INDEKS ## Anvender et indeks til at vælge en værdi fra en reference eller en matrix +INDIRECT = INDIREKTE ## Returnerer en reference, der er angivet af en tekstværdi +LOOKUP = SLÃ….OP ## Søger værdier i en vektor eller en matrix +MATCH = SAMMENLIGN ## Søger værdier i en reference eller en matrix +OFFSET = FORSKYDNING ## Returnerer en reference forskudt i forhold til en given reference +ROW = RÆKKE ## Returnerer rækkenummeret for en reference +ROWS = RÆKKER ## Returnerer antallet af rækker i en reference +RTD = RTD ## Henter realtidsdata fra et program, der understøtter COM-automatisering (Automation: En metode til at arbejde med objekter fra et andet program eller udviklingsværktøj. Automation, som tidligere blev kaldt OLE Automation, er en industristandard og en funktion i COM (Component Object Model).) +TRANSPOSE = TRANSPONER ## Returnerer en transponeret matrix +VLOOKUP = LOPSLAG ## Søger i øverste række af en matrix og flytter pÃ¥ tværs af rækken for at returnere en celleværdi + + +## +## Math and trigonometry functions Matematiske og trigonometriske funktioner +## +ABS = ABS ## Returnerer den absolutte værdi af et tal +ACOS = ARCCOS ## Returnerer et tals arcus cosinus +ACOSH = ARCCOSH ## Returnerer den inverse hyperbolske cosinus af tal +ASIN = ARCSIN ## Returnerer et tals arcus sinus +ASINH = ARCSINH ## Returnerer den inverse hyperbolske sinus for tal +ATAN = ARCTAN ## Returnerer et tals arcus tangens +ATAN2 = ARCTAN2 ## Returnerer de angivne x- og y-koordinaters arcus tangens +ATANH = ARCTANH ## Returnerer et tals inverse hyperbolske tangens +CEILING = AFRUND.LOFT ## Afrunder et tal til nærmeste heltal eller til nærmeste multiplum af betydning +COMBIN = KOMBIN ## Returnerer antallet af kombinationer for et givet antal objekter +COS = COS ## Returnerer et tals cosinus +COSH = COSH ## Returnerer den inverse hyperbolske cosinus af et tal +DEGREES = GRADER ## Konverterer radianer til grader +EVEN = LIGE ## Runder et tal op til nærmeste lige heltal +EXP = EKSP ## Returnerer e opløftet til en potens af et angivet tal +FACT = FAKULTET ## Returnerer et tals fakultet +FACTDOUBLE = DOBBELT.FAKULTET ## Returnerer et tals dobbelte fakultet +FLOOR = AFRUND.GULV ## Runder et tal ned mod nul +GCD = STØRSTE.FÆLLES.DIVISOR ## Returnerer den største fælles divisor +INT = HELTAL ## Nedrunder et tal til det nærmeste heltal +LCM = MINDSTE.FÆLLES.MULTIPLUM ## Returnerer det mindste fælles multiplum +LN = LN ## Returnerer et tals naturlige logaritme +LOG = LOG ## Returnerer logaritmen for et tal pÃ¥ grundlag af et angivet grundtal +LOG10 = LOG10 ## Returnerer titalslogaritmen af et tal +MDETERM = MDETERM ## Returnerer determinanten for en matrix +MINVERSE = MINVERT ## Returnerer den inverse matrix for en matrix +MMULT = MPRODUKT ## Returnerer matrixproduktet af to matrixer +MOD = REST ## Returnerer restværdien fra division +MROUND = MAFRUND ## Returnerer et tal afrundet til det ønskede multiplum +MULTINOMIAL = MULTINOMIAL ## Returnerer et multinomialt talsæt +ODD = ULIGE ## Runder et tal op til nærmeste ulige heltal +PI = PI ## Returnerer værdien af pi +POWER = POTENS ## Returnerer resultatet af et tal opløftet til en potens +PRODUCT = PRODUKT ## Multiplicerer argumenterne +QUOTIENT = KVOTIENT ## Returnerer heltalsdelen ved division +RADIANS = RADIANER ## Konverterer grader til radianer +RAND = SLUMP ## Returnerer et tilfældigt tal mellem 0 og 1 +RANDBETWEEN = SLUMP.MELLEM ## Returnerer et tilfældigt tal mellem de tal, der angives +ROMAN = ROMERTAL ## Konverterer et arabertal til romertal som tekst +ROUND = AFRUND ## Afrunder et tal til et angivet antal decimaler +ROUNDDOWN = RUND.NED ## Runder et tal ned mod nul +ROUNDUP = RUND.OP ## Runder et tal op, væk fra 0 (nul) +SERIESSUM = SERIESUM ## Returnerer summen af en potensserie baseret pÃ¥ en formel +SIGN = FORTEGN ## Returnerer et tals fortegn +SIN = SIN ## Returnerer en given vinkels sinusværdi +SINH = SINH ## Returnerer den hyperbolske sinus af et tal +SQRT = KVROD ## Returnerer en positiv kvadratrod +SQRTPI = KVRODPI ## Returnerer kvadratroden af (tal * pi;) +SUBTOTAL = SUBTOTAL ## Returnerer en subtotal pÃ¥ en liste eller i en database +SUM = SUM ## Lægger argumenterne sammen +SUMIF = SUM.HVIS ## Lægger de celler sammen, der er specificeret af et givet kriterium. +SUMIFS = SUM.HVISER ## Lægger de celler i et omrÃ¥de sammen, der opfylder flere kriterier. +SUMPRODUCT = SUMPRODUKT ## Returnerer summen af produkter af ens matrixkomponenter +SUMSQ = SUMKV ## Returnerer summen af argumenternes kvadrater +SUMX2MY2 = SUMX2MY2 ## Returnerer summen af differensen mellem kvadrater af ens værdier i to matrixer +SUMX2PY2 = SUMX2PY2 ## Returnerer summen af summen af kvadrater af tilsvarende værdier i to matrixer +SUMXMY2 = SUMXMY2 ## Returnerer summen af kvadrater af differenser mellem ens værdier i to matrixer +TAN = TAN ## Returnerer et tals tangens +TANH = TANH ## Returnerer et tals hyperbolske tangens +TRUNC = AFKORT ## Afkorter et tal til et heltal + + +## +## Statistical functions Statistiske funktioner +## +AVEDEV = MAD ## Returnerer den gennemsnitlige numeriske afvigelse fra stikprøvens middelværdi +AVERAGE = MIDDEL ## Returnerer middelværdien af argumenterne +AVERAGEA = MIDDELV ## Returnerer middelværdien af argumenterne og medtager tal, tekst og logiske værdier +AVERAGEIF = MIDDEL.HVIS ## Returnerer gennemsnittet (den aritmetiske middelværdi) af alle de celler, der opfylder et givet kriterium, i et omrÃ¥de +AVERAGEIFS = MIDDEL.HVISER ## Returnerer gennemsnittet (den aritmetiske middelværdi) af alle de celler, der opfylder flere kriterier. +BETADIST = BETAFORDELING ## Returnerer den kumulative betafordelingsfunktion +BETAINV = BETAINV ## Returnerer den inverse kumulative fordelingsfunktion for en angivet betafordeling +BINOMDIST = BINOMIALFORDELING ## Returnerer punktsandsynligheden for binomialfordelingen +CHIDIST = CHIFORDELING ## Returnerer fraktilsandsynligheden for en chi2-fordeling +CHIINV = CHIINV ## Returnerer den inverse fraktilsandsynlighed for en chi2-fordeling +CHITEST = CHITEST ## Foretager en test for uafhængighed +CONFIDENCE = KONFIDENSINTERVAL ## Returnerer et konfidensinterval for en population +CORREL = KORRELATION ## Returnerer korrelationskoefficienten mellem to datasæt +COUNT = TÆL ## Tæller antallet af tal pÃ¥ en liste med argumenter +COUNTA = TÆLV ## Tæller antallet af værdier pÃ¥ en liste med argumenter +COUNTBLANK = ANTAL.BLANKE ## Tæller antallet af tomme celler i et omrÃ¥de +COUNTIF = TÆLHVIS ## Tæller antallet af celler, som opfylder de givne kriterier, i et omrÃ¥de +COUNTIFS = TÆL.HVISER ## Tæller antallet af de celler, som opfylder flere kriterier, i et omrÃ¥de +COVAR = KOVARIANS ## Beregner kovariansen mellem to stokastiske variabler +CRITBINOM = KRITBINOM ## Returnerer den mindste værdi for x, for hvilken det gælder, at fordelingsfunktionen er mindre end eller lig med kriterieværdien. +DEVSQ = SAK ## Returnerer summen af de kvadrerede afvigelser fra middelværdien +EXPONDIST = EKSPFORDELING ## Returnerer eksponentialfordelingen +FDIST = FFORDELING ## Returnerer fraktilsandsynligheden for F-fordelingen +FINV = FINV ## Returnerer den inverse fraktilsandsynlighed for F-fordelingen +FISHER = FISHER ## Returnerer Fisher-transformationen +FISHERINV = FISHERINV ## Returnerer den inverse Fisher-transformation +FORECAST = PROGNOSE ## Returnerer en prognoseværdi baseret pÃ¥ lineær tendens +FREQUENCY = FREKVENS ## Returnerer en frekvensfordeling i en søjlevektor +FTEST = FTEST ## Returnerer resultatet af en F-test til sammenligning af varians +GAMMADIST = GAMMAFORDELING ## Returnerer fordelingsfunktionen for gammafordelingen +GAMMAINV = GAMMAINV ## Returnerer den inverse fordelingsfunktion for gammafordelingen +GAMMALN = GAMMALN ## Returnerer den naturlige logaritme til gammafordelingen, G(x) +GEOMEAN = GEOMIDDELVÆRDI ## Returnerer det geometriske gennemsnit +GROWTH = FORØGELSE ## Returnerer værdier langs en eksponentiel tendens +HARMEAN = HARMIDDELVÆRDI ## Returnerer det harmoniske gennemsnit +HYPGEOMDIST = HYPGEOFORDELING ## Returnerer punktsandsynligheden i en hypergeometrisk fordeling +INTERCEPT = SKÆRING ## Returnerer afskæringsværdien pÃ¥ y-aksen i en lineær regression +KURT = TOPSTEJL ## Returnerer kurtosisværdien for en stokastisk variabel +LARGE = STOR ## Returnerer den k'te største værdi i et datasæt +LINEST = LINREGR ## Returnerer parameterestimaterne for en lineær tendens +LOGEST = LOGREGR ## Returnerer parameterestimaterne for en eksponentiel tendens +LOGINV = LOGINV ## Returnerer den inverse fordelingsfunktion for lognormalfordelingen +LOGNORMDIST = LOGNORMFORDELING ## Returnerer fordelingsfunktionen for lognormalfordelingen +MAX = MAKS ## Returnerer den maksimale værdi pÃ¥ en liste med argumenter. +MAXA = MAKSV ## Returnerer den maksimale værdi pÃ¥ en liste med argumenter og medtager tal, tekst og logiske værdier +MEDIAN = MEDIAN ## Returnerer medianen for de angivne tal +MIN = MIN ## Returnerer den mindste værdi pÃ¥ en liste med argumenter. +MINA = MINV ## Returnerer den mindste værdi pÃ¥ en liste med argumenter og medtager tal, tekst og logiske værdier +MODE = HYPPIGST ## Returnerer den hyppigste værdi i et datasæt +NEGBINOMDIST = NEGBINOMFORDELING ## Returnerer den negative binomialfordeling +NORMDIST = NORMFORDELING ## Returnerer fordelingsfunktionen for normalfordelingen +NORMINV = NORMINV ## Returnerer den inverse fordelingsfunktion for normalfordelingen +NORMSDIST = STANDARDNORMFORDELING ## Returnerer fordelingsfunktionen for standardnormalfordelingen +NORMSINV = STANDARDNORMINV ## Returnerer den inverse fordelingsfunktion for standardnormalfordelingen +PEARSON = PEARSON ## Returnerer Pearsons korrelationskoefficient +PERCENTILE = FRAKTIL ## Returnerer den k'te fraktil for datasættet +PERCENTRANK = PROCENTPLADS ## Returnerer den procentuelle rang for en given værdi i et datasæt +PERMUT = PERMUT ## Returnerer antallet af permutationer for et givet sæt objekter +POISSON = POISSON ## Returnerer fordelingsfunktionen for en Poisson-fordeling +PROB = SANDSYNLIGHED ## Returnerer intervalsandsynligheden +QUARTILE = KVARTIL ## Returnerer kvartilen i et givet datasæt +RANK = PLADS ## Returnerer rangen for et tal pÃ¥ en liste med tal +RSQ = FORKLARINGSGRAD ## Returnerer R2-værdien fra en simpel lineær regression +SKEW = SKÆVHED ## Returnerer skævheden for en stokastisk variabel +SLOPE = HÆLDNING ## Returnerer estimatet pÃ¥ hældningen fra en simpel lineær regression +SMALL = MINDSTE ## Returnerer den k'te mindste værdi i datasættet +STANDARDIZE = STANDARDISER ## Returnerer en standardiseret værdi +STDEV = STDAFV ## Estimerer standardafvigelsen pÃ¥ basis af en stikprøve +STDEVA = STDAFVV ## Beregner standardafvigelsen pÃ¥ basis af en prøve og medtager tal, tekst og logiske værdier +STDEVP = STDAFVP ## Beregner standardafvigelsen pÃ¥ basis af en hel population +STDEVPA = STDAFVPV ## Beregner standardafvigelsen pÃ¥ basis af en hel population og medtager tal, tekst og logiske værdier +STEYX = STFYX ## Returnerer standardafvigelsen for de estimerede y-værdier i den simple lineære regression +TDIST = TFORDELING ## Returnerer fordelingsfunktionen for Student's t-fordeling +TINV = TINV ## Returnerer den inverse fordelingsfunktion for Student's t-fordeling +TREND = TENDENS ## Returnerer værdi under antagelse af en lineær tendens +TRIMMEAN = TRIMMIDDELVÆRDI ## Returnerer den trimmede middelværdi for datasættet +TTEST = TTEST ## Returnerer den sandsynlighed, der er forbundet med Student's t-test +VAR = VARIANS ## Beregner variansen pÃ¥ basis af en prøve +VARA = VARIANSV ## Beregner variansen pÃ¥ basis af en prøve og medtager tal, tekst og logiske værdier +VARP = VARIANSP ## Beregner variansen pÃ¥ basis af hele populationen +VARPA = VARIANSPV ## Beregner variansen pÃ¥ basis af hele populationen og medtager tal, tekst og logiske værdier +WEIBULL = WEIBULL ## Returnerer fordelingsfunktionen for Weibull-fordelingen +ZTEST = ZTEST ## Returnerer sandsynlighedsværdien ved en en-sidet z-test + + +## +## Text functions Tekstfunktioner +## +ASC = ASC ## Ændrer engelske tegn i fuld bredde (dobbelt-byte) eller katakana i en tegnstreng til tegn i halv bredde (enkelt-byte) +BAHTTEXT = BAHTTEKST ## Konverterer et tal til tekst ved hjælp af valutaformatet ß (baht) +CHAR = TEGN ## Returnerer det tegn, der svarer til kodenummeret +CLEAN = RENS ## Fjerner alle tegn, der ikke kan udskrives, fra tekst +CODE = KODE ## Returnerer en numerisk kode for det første tegn i en tekststreng +CONCATENATE = SAMMENKÆDNING ## Sammenkæder adskillige tekstelementer til ét tekstelement +DOLLAR = KR ## Konverterer et tal til tekst ved hjælp af valutaformatet kr. (kroner) +EXACT = EKSAKT ## Kontrollerer, om to tekstværdier er identiske +FIND = FIND ## Søger efter en tekstværdi i en anden tekstværdi (der skelnes mellem store og smÃ¥ bogstaver) +FINDB = FINDB ## Søger efter en tekstværdi i en anden tekstværdi (der skelnes mellem store og smÃ¥ bogstaver) +FIXED = FAST ## Formaterer et tal som tekst med et fast antal decimaler +JIS = JIS ## Ændrer engelske tegn i halv bredde (enkelt-byte) eller katakana i en tegnstreng til tegn i fuld bredde (dobbelt-byte) +LEFT = VENSTRE ## Returnerer tegnet længst til venstre i en tekstværdi +LEFTB = VENSTREB ## Returnerer tegnet længst til venstre i en tekstværdi +LEN = LÆNGDE ## Returnerer antallet af tegn i en tekststreng +LENB = LÆNGDEB ## Returnerer antallet af tegn i en tekststreng +LOWER = SMÃ….BOGSTAVER ## Konverterer tekst til smÃ¥ bogstaver +MID = MIDT ## Returnerer et bestemt antal tegn fra en tekststreng fra og med den angivne startposition +MIDB = MIDTB ## Returnerer et bestemt antal tegn fra en tekststreng fra og med den angivne startposition +PHONETIC = FONETISK ## Uddrager de fonetiske (furigana) tegn fra en tekststreng +PROPER = STORT.FORBOGSTAV ## Konverterer første bogstav i hvert ord i teksten til stort bogstav +REPLACE = ERSTAT ## Erstatter tegn i tekst +REPLACEB = ERSTATB ## Erstatter tegn i tekst +REPT = GENTAG ## Gentager tekst et givet antal gange +RIGHT = HØJRE ## Returnerer tegnet længste til højre i en tekstværdi +RIGHTB = HØJREB ## Returnerer tegnet længste til højre i en tekstværdi +SEARCH = SØG ## Søger efter en tekstværdi i en anden tekstværdi (der skelnes ikke mellem store og smÃ¥ bogstaver) +SEARCHB = SØGB ## Søger efter en tekstværdi i en anden tekstværdi (der skelnes ikke mellem store og smÃ¥ bogstaver) +SUBSTITUTE = UDSKIFT ## Udskifter gammel tekst med ny tekst i en tekststreng +T = T ## Konverterer argumenterne til tekst +TEXT = TEKST ## Formaterer et tal og konverterer det til tekst +TRIM = FJERN.OVERFLØDIGE.BLANKE ## Fjerner mellemrum fra tekst +UPPER = STORE.BOGSTAVER ## Konverterer tekst til store bogstaver +VALUE = VÆRDI ## Konverterer et tekstargument til et tal diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/de/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/de/config new file mode 100755 index 0000000..810779d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/de/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = € + + +## +## Excel Error Codes (For future use) +## +NULL = #NULL! +DIV0 = #DIV/0! +VALUE = #WERT! +REF = #BEZUG! +NAME = #NAME? +NUM = #ZAHL! +NA = #NV diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/de/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/de/functions new file mode 100755 index 0000000..56f641d --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/de/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions Add-In- und Automatisierungsfunktionen +## +GETPIVOTDATA = PIVOTDATENZUORDNEN ## In einem PivotTable-Bericht gespeicherte Daten werden zurückgegeben. + + +## +## Cube functions Cubefunktionen +## +CUBEKPIMEMBER = CUBEKPIELEMENT ## Gibt Name, Eigenschaft und Measure eines Key Performance Indicators (KPI) zurück und zeigt den Namen und die Eigenschaft in der Zelle an. Ein KPI ist ein quantifizierbares Maß, wie z. B. der monatliche Bruttogewinn oder die vierteljährliche Mitarbeiterfluktuation, mit dessen Hilfe das Leistungsverhalten eines Unternehmens überwacht werden kann. +CUBEMEMBER = CUBEELEMENT ## Gibt ein Element oder ein Tuple in einer Cubehierarchie zurück. Wird verwendet, um zu überprüfen, ob das Element oder Tuple im Cube vorhanden ist. +CUBEMEMBERPROPERTY = CUBEELEMENTEIGENSCHAFT ## Gibt den Wert einer Elementeigenschaft im Cube zurück. Wird verwendet, um zu überprüfen, ob ein Elementname im Cube vorhanden ist, und um die für dieses Element angegebene Eigenschaft zurückzugeben. +CUBERANKEDMEMBER = CUBERANGELEMENT ## Gibt das n-te oder n-rangige Element in einer Menge zurück. Wird verwendet, um mindestens ein Element in einer Menge zurückzugeben, wie z. B. bester Vertriebsmitarbeiter oder 10 beste Kursteilnehmer. +CUBESET = CUBEMENGE ## Definiert eine berechnete Menge Elemente oder Tuples durch Senden eines Mengenausdrucks an den Cube auf dem Server, der die Menge erstellt und an Microsoft Office Excel zurückgibt. +CUBESETCOUNT = CUBEMENGENANZAHL ## Gibt die Anzahl der Elemente in einer Menge zurück. +CUBEVALUE = CUBEWERT ## Gibt einen Aggregatwert aus einem Cube zurück. + + +## +## Database functions Datenbankfunktionen +## +DAVERAGE = DBMITTELWERT ## Gibt den Mittelwert der ausgewählten Datenbankeinträge zurück +DCOUNT = DBANZAHL ## Zählt die Zellen mit Zahlen in einer Datenbank +DCOUNTA = DBANZAHL2 ## Zählt nicht leere Zellen in einer Datenbank +DGET = DBAUSZUG ## Extrahiert aus einer Datenbank einen einzelnen Datensatz, der den angegebenen Kriterien entspricht +DMAX = DBMAX ## Gibt den größten Wert aus ausgewählten Datenbankeinträgen zurück +DMIN = DBMIN ## Gibt den kleinsten Wert aus ausgewählten Datenbankeinträgen zurück +DPRODUCT = DBPRODUKT ## Multipliziert die Werte in einem bestimmten Feld mit Datensätzen, die den Kriterien in einer Datenbank entsprechen +DSTDEV = DBSTDABW ## Schätzt die Standardabweichung auf der Grundlage einer Stichprobe aus ausgewählten Datenbankeinträgen +DSTDEVP = DBSTDABWN ## Berechnet die Standardabweichung auf der Grundlage der Grundgesamtheit ausgewählter Datenbankeinträge +DSUM = DBSUMME ## Addiert die Zahlen in der Feldspalte mit Datensätzen in der Datenbank, die den Kriterien entsprechen +DVAR = DBVARIANZ ## Schätzt die Varianz auf der Grundlage ausgewählter Datenbankeinträge +DVARP = DBVARIANZEN ## Berechnet die Varianz auf der Grundlage der Grundgesamtheit ausgewählter Datenbankeinträge + + +## +## Date and time functions Datums- und Zeitfunktionen +## +DATE = DATUM ## Gibt die fortlaufende Zahl eines bestimmten Datums zurück +DATEVALUE = DATWERT ## Wandelt ein Datum in Form von Text in eine fortlaufende Zahl um +DAY = TAG ## Wandelt eine fortlaufende Zahl in den Tag des Monats um +DAYS360 = TAGE360 ## Berechnet die Anzahl der Tage zwischen zwei Datumsangaben ausgehend von einem Jahr, das 360 Tage hat +EDATE = EDATUM ## Gibt die fortlaufende Zahl des Datums zurück, bei dem es sich um die angegebene Anzahl von Monaten vor oder nach dem Anfangstermin handelt +EOMONTH = MONATSENDE ## Gibt die fortlaufende Zahl des letzten Tags des Monats vor oder nach einer festgelegten Anzahl von Monaten zurück +HOUR = STUNDE ## Wandelt eine fortlaufende Zahl in eine Stunde um +MINUTE = MINUTE ## Wandelt eine fortlaufende Zahl in eine Minute um +MONTH = MONAT ## Wandelt eine fortlaufende Zahl in einen Monat um +NETWORKDAYS = NETTOARBEITSTAGE ## Gibt die Anzahl von ganzen Arbeitstagen zwischen zwei Datumswerten zurück +NOW = JETZT ## Gibt die fortlaufende Zahl des aktuellen Datums und der aktuellen Uhrzeit zurück +SECOND = SEKUNDE ## Wandelt eine fortlaufende Zahl in eine Sekunde um +TIME = ZEIT ## Gibt die fortlaufende Zahl einer bestimmten Uhrzeit zurück +TIMEVALUE = ZEITWERT ## Wandelt eine Uhrzeit in Form von Text in eine fortlaufende Zahl um +TODAY = HEUTE ## Gibt die fortlaufende Zahl des heutigen Datums zurück +WEEKDAY = WOCHENTAG ## Wandelt eine fortlaufende Zahl in den Wochentag um +WEEKNUM = KALENDERWOCHE ## Wandelt eine fortlaufende Zahl in eine Zahl um, die angibt, in welche Woche eines Jahres das angegebene Datum fällt +WORKDAY = ARBEITSTAG ## Gibt die fortlaufende Zahl des Datums vor oder nach einer bestimmten Anzahl von Arbeitstagen zurück +YEAR = JAHR ## Wandelt eine fortlaufende Zahl in ein Jahr um +YEARFRAC = BRTEILJAHRE ## Gibt die Anzahl der ganzen Tage zwischen Ausgangsdatum und Enddatum in Bruchteilen von Jahren zurück + + +## +## Engineering functions Konstruktionsfunktionen +## +BESSELI = BESSELI ## Gibt die geänderte Besselfunktion In(x) zurück +BESSELJ = BESSELJ ## Gibt die Besselfunktion Jn(x) zurück +BESSELK = BESSELK ## Gibt die geänderte Besselfunktion Kn(x) zurück +BESSELY = BESSELY ## Gibt die Besselfunktion Yn(x) zurück +BIN2DEC = BININDEZ ## Wandelt eine binäre Zahl (Dualzahl) in eine dezimale Zahl um +BIN2HEX = BININHEX ## Wandelt eine binäre Zahl (Dualzahl) in eine hexadezimale Zahl um +BIN2OCT = BININOKT ## Wandelt eine binäre Zahl (Dualzahl) in eine oktale Zahl um +COMPLEX = KOMPLEXE ## Wandelt den Real- und Imaginärteil in eine komplexe Zahl um +CONVERT = UMWANDELN ## Wandelt eine Zahl von einem Maßsystem in ein anderes um +DEC2BIN = DEZINBIN ## Wandelt eine dezimale Zahl in eine binäre Zahl (Dualzahl) um +DEC2HEX = DEZINHEX ## Wandelt eine dezimale Zahl in eine hexadezimale Zahl um +DEC2OCT = DEZINOKT ## Wandelt eine dezimale Zahl in eine oktale Zahl um +DELTA = DELTA ## Ãœberprüft, ob zwei Werte gleich sind +ERF = GAUSSFEHLER ## Gibt die Gauss'sche Fehlerfunktion zurück +ERFC = GAUSSFKOMPL ## Gibt das Komplement zur Gauss'schen Fehlerfunktion zurück +GESTEP = GGANZZAHL ## Ãœberprüft, ob eine Zahl größer als ein gegebener Schwellenwert ist +HEX2BIN = HEXINBIN ## Wandelt eine hexadezimale Zahl in eine Binärzahl um +HEX2DEC = HEXINDEZ ## Wandelt eine hexadezimale Zahl in eine dezimale Zahl um +HEX2OCT = HEXINOKT ## Wandelt eine hexadezimale Zahl in eine Oktalzahl um +IMABS = IMABS ## Gibt den Absolutbetrag (Modulo) einer komplexen Zahl zurück +IMAGINARY = IMAGINÄRTEIL ## Gibt den Imaginärteil einer komplexen Zahl zurück +IMARGUMENT = IMARGUMENT ## Gibt das Argument Theta zurück, einen Winkel, der als Bogenmaß ausgedrückt wird +IMCONJUGATE = IMKONJUGIERTE ## Gibt die konjugierte komplexe Zahl zu einer komplexen Zahl zurück +IMCOS = IMCOS ## Gibt den Kosinus einer komplexen Zahl zurück +IMDIV = IMDIV ## Gibt den Quotienten zweier komplexer Zahlen zurück +IMEXP = IMEXP ## Gibt die algebraische Form einer in exponentieller Schreibweise vorliegenden komplexen Zahl zurück +IMLN = IMLN ## Gibt den natürlichen Logarithmus einer komplexen Zahl zurück +IMLOG10 = IMLOG10 ## Gibt den Logarithmus einer komplexen Zahl zur Basis 10 zurück +IMLOG2 = IMLOG2 ## Gibt den Logarithmus einer komplexen Zahl zur Basis 2 zurück +IMPOWER = IMAPOTENZ ## Potenziert eine komplexe Zahl mit einer ganzen Zahl +IMPRODUCT = IMPRODUKT ## Gibt das Produkt von komplexen Zahlen zurück +IMREAL = IMREALTEIL ## Gibt den Realteil einer komplexen Zahl zurück +IMSIN = IMSIN ## Gibt den Sinus einer komplexen Zahl zurück +IMSQRT = IMWURZEL ## Gibt die Quadratwurzel einer komplexen Zahl zurück +IMSUB = IMSUB ## Gibt die Differenz zwischen zwei komplexen Zahlen zurück +IMSUM = IMSUMME ## Gibt die Summe von komplexen Zahlen zurück +OCT2BIN = OKTINBIN ## Wandelt eine oktale Zahl in eine binäre Zahl (Dualzahl) um +OCT2DEC = OKTINDEZ ## Wandelt eine oktale Zahl in eine dezimale Zahl um +OCT2HEX = OKTINHEX ## Wandelt eine oktale Zahl in eine hexadezimale Zahl um + + +## +## Financial functions Finanzmathematische Funktionen +## +ACCRINT = AUFGELZINS ## Gibt die aufgelaufenen Zinsen (Stückzinsen) eines Wertpapiers mit periodischen Zinszahlungen zurück +ACCRINTM = AUFGELZINSF ## Gibt die aufgelaufenen Zinsen (Stückzinsen) eines Wertpapiers zurück, die bei Fälligkeit ausgezahlt werden +AMORDEGRC = AMORDEGRK ## Gibt die Abschreibung für die einzelnen Abschreibungszeiträume mithilfe eines Abschreibungskoeffizienten zurück +AMORLINC = AMORLINEARK ## Gibt die Abschreibung für die einzelnen Abschreibungszeiträume zurück +COUPDAYBS = ZINSTERMTAGVA ## Gibt die Anzahl der Tage vom Anfang des Zinstermins bis zum Abrechnungstermin zurück +COUPDAYS = ZINSTERMTAGE ## Gibt die Anzahl der Tage der Zinsperiode zurück, die den Abrechnungstermin einschließt +COUPDAYSNC = ZINSTERMTAGNZ ## Gibt die Anzahl der Tage vom Abrechnungstermin bis zum nächsten Zinstermin zurück +COUPNCD = ZINSTERMNZ ## Gibt das Datum des ersten Zinstermins nach dem Abrechnungstermin zurück +COUPNUM = ZINSTERMZAHL ## Gibt die Anzahl der Zinstermine zwischen Abrechnungs- und Fälligkeitsdatum zurück +COUPPCD = ZINSTERMVZ ## Gibt das Datum des letzten Zinstermins vor dem Abrechnungstermin zurück +CUMIPMT = KUMZINSZ ## Berechnet die kumulierten Zinsen, die zwischen zwei Perioden zu zahlen sind +CUMPRINC = KUMKAPITAL ## Berechnet die aufgelaufene Tilgung eines Darlehens, die zwischen zwei Perioden zu zahlen ist +DB = GDA2 ## Gibt die geometrisch-degressive Abschreibung eines Wirtschaftsguts für eine bestimmte Periode zurück +DDB = GDA ## Gibt die Abschreibung eines Anlageguts für einen angegebenen Zeitraum unter Verwendung der degressiven Doppelraten-Abschreibung oder eines anderen von Ihnen angegebenen Abschreibungsverfahrens zurück +DISC = DISAGIO ## Gibt den in Prozent ausgedrückten Abzinsungssatz eines Wertpapiers zurück +DOLLARDE = NOTIERUNGDEZ ## Wandelt eine Notierung, die als Dezimalbruch ausgedrückt wurde, in eine Dezimalzahl um +DOLLARFR = NOTIERUNGBRU ## Wandelt eine Notierung, die als Dezimalzahl ausgedrückt wurde, in einen Dezimalbruch um +DURATION = DURATION ## Gibt die jährliche Duration eines Wertpapiers mit periodischen Zinszahlungen zurück +EFFECT = EFFEKTIV ## Gibt die jährliche Effektivverzinsung zurück +FV = ZW ## Gibt den zukünftigen Wert (Endwert) einer Investition zurück +FVSCHEDULE = ZW2 ## Gibt den aufgezinsten Wert des Anfangskapitals für eine Reihe periodisch unterschiedlicher Zinssätze zurück +INTRATE = ZINSSATZ ## Gibt den Zinssatz eines voll investierten Wertpapiers zurück +IPMT = ZINSZ ## Gibt die Zinszahlung einer Investition für die angegebene Periode zurück +IRR = IKV ## Gibt den internen Zinsfuß einer Investition ohne Finanzierungskosten oder Reinvestitionsgewinne zurück +ISPMT = ISPMT ## Berechnet die während eines bestimmten Zeitraums für eine Investition gezahlten Zinsen +MDURATION = MDURATION ## Gibt die geänderte Dauer für ein Wertpapier mit einem angenommenen Nennwert von 100 € zurück +MIRR = QIKV ## Gibt den internen Zinsfuß zurück, wobei positive und negative Zahlungen zu unterschiedlichen Sätzen finanziert werden +NOMINAL = NOMINAL ## Gibt die jährliche Nominalverzinsung zurück +NPER = ZZR ## Gibt die Anzahl der Zahlungsperioden einer Investition zurück +NPV = NBW ## Gibt den Nettobarwert einer Investition auf Basis periodisch anfallender Zahlungen und eines Abzinsungsfaktors zurück +ODDFPRICE = UNREGER.KURS ## Gibt den Kurs pro 100 € Nennwert eines Wertpapiers mit einem unregelmäßigen ersten Zinstermin zurück +ODDFYIELD = UNREGER.REND ## Gibt die Rendite eines Wertpapiers mit einem unregelmäßigen ersten Zinstermin zurück +ODDLPRICE = UNREGLE.KURS ## Gibt den Kurs pro 100 € Nennwert eines Wertpapiers mit einem unregelmäßigen letzten Zinstermin zurück +ODDLYIELD = UNREGLE.REND ## Gibt die Rendite eines Wertpapiers mit einem unregelmäßigen letzten Zinstermin zurück +PMT = RMZ ## Gibt die periodische Zahlung für eine Annuität zurück +PPMT = KAPZ ## Gibt die Kapitalrückzahlung einer Investition für eine angegebene Periode zurück +PRICE = KURS ## Gibt den Kurs pro 100 € Nennwert eines Wertpapiers zurück, das periodisch Zinsen auszahlt +PRICEDISC = KURSDISAGIO ## Gibt den Kurs pro 100 € Nennwert eines unverzinslichen Wertpapiers zurück +PRICEMAT = KURSFÄLLIG ## Gibt den Kurs pro 100 € Nennwert eines Wertpapiers zurück, das Zinsen am Fälligkeitsdatum auszahlt +PV = BW ## Gibt den Barwert einer Investition zurück +RATE = ZINS ## Gibt den Zinssatz pro Zeitraum einer Annuität zurück +RECEIVED = AUSZAHLUNG ## Gibt den Auszahlungsbetrag eines voll investierten Wertpapiers am Fälligkeitstermin zurück +SLN = LIA ## Gibt die lineare Abschreibung eines Wirtschaftsguts pro Periode zurück +SYD = DIA ## Gibt die arithmetisch-degressive Abschreibung eines Wirtschaftsguts für eine bestimmte Periode zurück +TBILLEQ = TBILLÄQUIV ## Gibt die Rendite für ein Wertpapier zurück +TBILLPRICE = TBILLKURS ## Gibt den Kurs pro 100 € Nennwert eines Wertpapiers zurück +TBILLYIELD = TBILLRENDITE ## Gibt die Rendite für ein Wertpapier zurück +VDB = VDB ## Gibt die degressive Abschreibung eines Wirtschaftsguts für eine bestimmte Periode oder Teilperiode zurück +XIRR = XINTZINSFUSS ## Gibt den internen Zinsfuß einer Reihe nicht periodisch anfallender Zahlungen zurück +XNPV = XKAPITALWERT ## Gibt den Nettobarwert (Kapitalwert) einer Reihe nicht periodisch anfallender Zahlungen zurück +YIELD = RENDITE ## Gibt die Rendite eines Wertpapiers zurück, das periodisch Zinsen auszahlt +YIELDDISC = RENDITEDIS ## Gibt die jährliche Rendite eines unverzinslichen Wertpapiers zurück +YIELDMAT = RENDITEFÄLL ## Gibt die jährliche Rendite eines Wertpapiers zurück, das Zinsen am Fälligkeitsdatum auszahlt + + +## +## Information functions Informationsfunktionen +## +CELL = ZELLE ## Gibt Informationen zu Formatierung, Position oder Inhalt einer Zelle zurück +ERROR.TYPE = FEHLER.TYP ## Gibt eine Zahl zurück, die einem Fehlertyp entspricht +INFO = INFO ## Gibt Informationen zur aktuellen Betriebssystemumgebung zurück +ISBLANK = ISTLEER ## Gibt WAHR zurück, wenn der Wert leer ist +ISERR = ISTFEHL ## Gibt WAHR zurück, wenn der Wert ein beliebiger Fehlerwert außer #N/V ist +ISERROR = ISTFEHLER ## Gibt WAHR zurück, wenn der Wert ein beliebiger Fehlerwert ist +ISEVEN = ISTGERADE ## Gibt WAHR zurück, wenn es sich um eine gerade Zahl handelt +ISLOGICAL = ISTLOG ## Gibt WAHR zurück, wenn der Wert ein Wahrheitswert ist +ISNA = ISTNV ## Gibt WAHR zurück, wenn der Wert der Fehlerwert #N/V ist +ISNONTEXT = ISTKTEXT ## Gibt WAHR zurück, wenn der Wert ein Element ist, das keinen Text enthält +ISNUMBER = ISTZAHL ## Gibt WAHR zurück, wenn der Wert eine Zahl ist +ISODD = ISTUNGERADE ## Gibt WAHR zurück, wenn es sich um eine ungerade Zahl handelt +ISREF = ISTBEZUG ## Gibt WAHR zurück, wenn der Wert ein Bezug ist +ISTEXT = ISTTEXT ## Gibt WAHR zurück, wenn der Wert ein Element ist, das Text enthält +N = N ## Gibt den in eine Zahl umgewandelten Wert zurück +NA = NV ## Gibt den Fehlerwert #NV zurück +TYPE = TYP ## Gibt eine Zahl zurück, die den Datentyp des angegebenen Werts anzeigt + + +## +## Logical functions Logische Funktionen +## +AND = UND ## Gibt WAHR zurück, wenn alle zugehörigen Argumente WAHR sind +FALSE = FALSCH ## Gibt den Wahrheitswert FALSCH zurück +IF = WENN ## Gibt einen logischen Test zum Ausführen an +IFERROR = WENNFEHLER ## Gibt einen von Ihnen festgelegten Wert zurück, wenn die Auswertung der Formel zu einem Fehler führt; andernfalls wird das Ergebnis der Formel zurückgegeben +NOT = NICHT ## Kehrt den Wahrheitswert der zugehörigen Argumente um +OR = ODER ## Gibt WAHR zurück, wenn ein Argument WAHR ist +TRUE = WAHR ## Gibt den Wahrheitswert WAHR zurück + + +## +## Lookup and reference functions Nachschlage- und Verweisfunktionen +## +ADDRESS = ADRESSE ## Gibt einen Bezug auf eine einzelne Zelle in einem Tabellenblatt als Text zurück +AREAS = BEREICHE ## Gibt die Anzahl der innerhalb eines Bezugs aufgeführten Bereiche zurück +CHOOSE = WAHL ## Wählt einen Wert aus eine Liste mit Werten aus +COLUMN = SPALTE ## Gibt die Spaltennummer eines Bezugs zurück +COLUMNS = SPALTEN ## Gibt die Anzahl der Spalten in einem Bezug zurück +HLOOKUP = HVERWEIS ## Sucht in der obersten Zeile einer Matrix und gibt den Wert der angegebenen Zelle zurück +HYPERLINK = HYPERLINK ## Erstellt eine Verknüpfung, über die ein auf einem Netzwerkserver, in einem Intranet oder im Internet gespeichertes Dokument geöffnet wird +INDEX = INDEX ## Verwendet einen Index, um einen Wert aus einem Bezug oder einer Matrix auszuwählen +INDIRECT = INDIREKT ## Gibt einen Bezug zurück, der von einem Textwert angegeben wird +LOOKUP = LOOKUP ## Sucht Werte in einem Vektor oder einer Matrix +MATCH = VERGLEICH ## Sucht Werte in einem Bezug oder einer Matrix +OFFSET = BEREICH.VERSCHIEBEN ## Gibt einen Bezugoffset aus einem gegebenen Bezug zurück +ROW = ZEILE ## Gibt die Zeilennummer eines Bezugs zurück +ROWS = ZEILEN ## Gibt die Anzahl der Zeilen in einem Bezug zurück +RTD = RTD ## Ruft Echtzeitdaten von einem Programm ab, das die COM-Automatisierung (Automatisierung: Ein Verfahren, bei dem aus einer Anwendung oder einem Entwicklungstool heraus mit den Objekten einer anderen Anwendung gearbeitet wird. Die früher als OLE-Automatisierung bezeichnete Automatisierung ist ein Industriestandard und eine Funktion von COM (Component Object Model).) unterstützt +TRANSPOSE = MTRANS ## Gibt die transponierte Matrix einer Matrix zurück +VLOOKUP = SVERWEIS ## Sucht in der ersten Spalte einer Matrix und arbeitet sich durch die Zeile, um den Wert einer Zelle zurückzugeben + + +## +## Math and trigonometry functions Mathematische und trigonometrische Funktionen +## +ABS = ABS ## Gibt den Absolutwert einer Zahl zurück +ACOS = ARCCOS ## Gibt den Arkuskosinus einer Zahl zurück +ACOSH = ARCCOSHYP ## Gibt den umgekehrten hyperbolischen Kosinus einer Zahl zurück +ASIN = ARCSIN ## Gibt den Arkussinus einer Zahl zurück +ASINH = ARCSINHYP ## Gibt den umgekehrten hyperbolischen Sinus einer Zahl zurück +ATAN = ARCTAN ## Gibt den Arkustangens einer Zahl zurück +ATAN2 = ARCTAN2 ## Gibt den Arkustangens einer x- und einer y-Koordinate zurück +ATANH = ARCTANHYP ## Gibt den umgekehrten hyperbolischen Tangens einer Zahl zurück +CEILING = OBERGRENZE ## Rundet eine Zahl auf die nächste ganze Zahl oder das nächste Vielfache von Schritt +COMBIN = KOMBINATIONEN ## Gibt die Anzahl der Kombinationen für eine bestimmte Anzahl von Objekten zurück +COS = COS ## Gibt den Kosinus einer Zahl zurück +COSH = COSHYP ## Gibt den hyperbolischen Kosinus einer Zahl zurück +DEGREES = GRAD ## Wandelt Bogenmaß (Radiant) in Grad um +EVEN = GERADE ## Rundet eine Zahl auf die nächste gerade ganze Zahl auf +EXP = EXP ## Potenziert die Basis e mit der als Argument angegebenen Zahl +FACT = FAKULTÄT ## Gibt die Fakultät einer Zahl zurück +FACTDOUBLE = ZWEIFAKULTÄT ## Gibt die Fakultät zu Zahl mit Schrittlänge 2 zurück +FLOOR = UNTERGRENZE ## Rundet die Zahl auf Anzahl_Stellen ab +GCD = GGT ## Gibt den größten gemeinsamen Teiler zurück +INT = GANZZAHL ## Rundet eine Zahl auf die nächstkleinere ganze Zahl ab +LCM = KGV ## Gibt das kleinste gemeinsame Vielfache zurück +LN = LN ## Gibt den natürlichen Logarithmus einer Zahl zurück +LOG = LOG ## Gibt den Logarithmus einer Zahl zu der angegebenen Basis zurück +LOG10 = LOG10 ## Gibt den Logarithmus einer Zahl zur Basis 10 zurück +MDETERM = MDET ## Gibt die Determinante einer Matrix zurück +MINVERSE = MINV ## Gibt die inverse Matrix einer Matrix zurück +MMULT = MMULT ## Gibt das Produkt zweier Matrizen zurück +MOD = REST ## Gibt den Rest einer Division zurück +MROUND = VRUNDEN ## Gibt eine auf das gewünschte Vielfache gerundete Zahl zurück +MULTINOMIAL = POLYNOMIAL ## Gibt den Polynomialkoeffizienten einer Gruppe von Zahlen zurück +ODD = UNGERADE ## Rundet eine Zahl auf die nächste ungerade ganze Zahl auf +PI = PI ## Gibt den Wert Pi zurück +POWER = POTENZ ## Gibt als Ergebnis eine potenzierte Zahl zurück +PRODUCT = PRODUKT ## Multipliziert die zugehörigen Argumente +QUOTIENT = QUOTIENT ## Gibt den ganzzahligen Anteil einer Division zurück +RADIANS = BOGENMASS ## Wandelt Grad in Bogenmaß (Radiant) um +RAND = ZUFALLSZAHL ## Gibt eine Zufallszahl zwischen 0 und 1 zurück +RANDBETWEEN = ZUFALLSBEREICH ## Gibt eine Zufallszahl aus dem festgelegten Bereich zurück +ROMAN = RÖMISCH ## Wandelt eine arabische Zahl in eine römische Zahl als Text um +ROUND = RUNDEN ## Rundet eine Zahl auf eine bestimmte Anzahl von Dezimalstellen +ROUNDDOWN = ABRUNDEN ## Rundet die Zahl auf Anzahl_Stellen ab +ROUNDUP = AUFRUNDEN ## Rundet die Zahl auf Anzahl_Stellen auf +SERIESSUM = POTENZREIHE ## Gibt die Summe von Potenzen (zur Berechnung von Potenzreihen und dichotomen Wahrscheinlichkeiten) zurück +SIGN = VORZEICHEN ## Gibt das Vorzeichen einer Zahl zurück +SIN = SIN ## Gibt den Sinus einer Zahl zurück +SINH = SINHYP ## Gibt den hyperbolischen Sinus einer Zahl zurück +SQRT = WURZEL ## Gibt die Quadratwurzel einer Zahl zurück +SQRTPI = WURZELPI ## Gibt die Wurzel aus der mit Pi (pi) multiplizierten Zahl zurück +SUBTOTAL = TEILERGEBNIS ## Gibt ein Teilergebnis in einer Liste oder Datenbank zurück +SUM = SUMME ## Addiert die zugehörigen Argumente +SUMIF = SUMMEWENN ## Addiert Zahlen, die mit den Suchkriterien übereinstimmen +SUMIFS = SUMMEWENNS ## Die Zellen, die mehrere Kriterien erfüllen, werden in einem Bereich hinzugefügt +SUMPRODUCT = SUMMENPRODUKT ## Gibt die Summe der Produkte zusammengehöriger Matrixkomponenten zurück +SUMSQ = QUADRATESUMME ## Gibt die Summe der quadrierten Argumente zurück +SUMX2MY2 = SUMMEX2MY2 ## Gibt die Summe der Differenzen der Quadrate für zusammengehörige Komponenten zweier Matrizen zurück +SUMX2PY2 = SUMMEX2PY2 ## Gibt die Summe der Quadrate für zusammengehörige Komponenten zweier Matrizen zurück +SUMXMY2 = SUMMEXMY2 ## Gibt die Summe der quadrierten Differenzen für zusammengehörige Komponenten zweier Matrizen zurück +TAN = TAN ## Gibt den Tangens einer Zahl zurück +TANH = TANHYP ## Gibt den hyperbolischen Tangens einer Zahl zurück +TRUNC = KÃœRZEN ## Schneidet die Kommastellen einer Zahl ab und gibt als Ergebnis eine ganze Zahl zurück + + +## +## Statistical functions Statistische Funktionen +## +AVEDEV = MITTELABW ## Gibt die durchschnittliche absolute Abweichung einer Reihe von Merkmalsausprägungen und ihrem Mittelwert zurück +AVERAGE = MITTELWERT ## Gibt den Mittelwert der zugehörigen Argumente zurück +AVERAGEA = MITTELWERTA ## Gibt den Mittelwert der zugehörigen Argumente, die Zahlen, Text und Wahrheitswerte enthalten, zurück +AVERAGEIF = MITTELWERTWENN ## Der Durchschnittswert (arithmetisches Mittel) für alle Zellen in einem Bereich, die einem angegebenen Kriterium entsprechen, wird zurückgegeben +AVERAGEIFS = MITTELWERTWENNS ## Gibt den Durchschnittswert (arithmetisches Mittel) aller Zellen zurück, die mehreren Kriterien entsprechen +BETADIST = BETAVERT ## Gibt die Werte der kumulierten Betaverteilungsfunktion zurück +BETAINV = BETAINV ## Gibt das Quantil der angegebenen Betaverteilung zurück +BINOMDIST = BINOMVERT ## Gibt Wahrscheinlichkeiten einer binomialverteilten Zufallsvariablen zurück +CHIDIST = CHIVERT ## Gibt Werte der Verteilungsfunktion (1-Alpha) einer Chi-Quadrat-verteilten Zufallsgröße zurück +CHIINV = CHIINV ## Gibt Quantile der Verteilungsfunktion (1-Alpha) der Chi-Quadrat-Verteilung zurück +CHITEST = CHITEST ## Gibt die Teststatistik eines Unabhängigkeitstests zurück +CONFIDENCE = KONFIDENZ ## Ermöglicht die Berechnung des 1-Alpha Konfidenzintervalls für den Erwartungswert einer Zufallsvariablen +CORREL = KORREL ## Gibt den Korrelationskoeffizienten zweier Reihen von Merkmalsausprägungen zurück +COUNT = ANZAHL ## Gibt die Anzahl der Zahlen in der Liste mit Argumenten an +COUNTA = ANZAHL2 ## Gibt die Anzahl der Werte in der Liste mit Argumenten an +COUNTBLANK = ANZAHLLEEREZELLEN ## Gibt die Anzahl der leeren Zellen in einem Bereich an +COUNTIF = ZÄHLENWENN ## Gibt die Anzahl der Zellen in einem Bereich an, deren Inhalte mit den Suchkriterien übereinstimmen +COUNTIFS = ZÄHLENWENNS ## Gibt die Anzahl der Zellen in einem Bereich an, deren Inhalte mit mehreren Suchkriterien übereinstimmen +COVAR = KOVAR ## Gibt die Kovarianz zurück, den Mittelwert der für alle Datenpunktpaare gebildeten Produkte der Abweichungen +CRITBINOM = KRITBINOM ## Gibt den kleinsten Wert zurück, für den die kumulierten Wahrscheinlichkeiten der Binomialverteilung kleiner oder gleich einer Grenzwahrscheinlichkeit sind +DEVSQ = SUMQUADABW ## Gibt die Summe der quadrierten Abweichungen der Datenpunkte von ihrem Stichprobenmittelwert zurück +EXPONDIST = EXPONVERT ## Gibt Wahrscheinlichkeiten einer exponential verteilten Zufallsvariablen zurück +FDIST = FVERT ## Gibt Werte der Verteilungsfunktion (1-Alpha) einer F-verteilten Zufallsvariablen zurück +FINV = FINV ## Gibt Quantile der F-Verteilung zurück +FISHER = FISHER ## Gibt die Fisher-Transformation zurück +FISHERINV = FISHERINV ## Gibt die Umkehrung der Fisher-Transformation zurück +FORECAST = PROGNOSE ## Gibt einen Wert zurück, der sich aus einem linearen Trend ergibt +FREQUENCY = HÄUFIGKEIT ## Gibt eine Häufigkeitsverteilung als vertikale Matrix zurück +FTEST = FTEST ## Gibt die Teststatistik eines F-Tests zurück +GAMMADIST = GAMMAVERT ## Gibt Wahrscheinlichkeiten einer gammaverteilten Zufallsvariablen zurück +GAMMAINV = GAMMAINV ## Gibt Quantile der Gammaverteilung zurück +GAMMALN = GAMMALN ## Gibt den natürlichen Logarithmus der Gammafunktion zurück, Γ(x) +GEOMEAN = GEOMITTEL ## Gibt das geometrische Mittel zurück +GROWTH = VARIATION ## Gibt Werte zurück, die sich aus einem exponentiellen Trend ergeben +HARMEAN = HARMITTEL ## Gibt das harmonische Mittel zurück +HYPGEOMDIST = HYPGEOMVERT ## Gibt Wahrscheinlichkeiten einer hypergeometrisch-verteilten Zufallsvariablen zurück +INTERCEPT = ACHSENABSCHNITT ## Gibt den Schnittpunkt der Regressionsgeraden zurück +KURT = KURT ## Gibt die Kurtosis (Exzess) einer Datengruppe zurück +LARGE = KGRÖSSTE ## Gibt den k-größten Wert einer Datengruppe zurück +LINEST = RGP ## Gibt die Parameter eines linearen Trends zurück +LOGEST = RKP ## Gibt die Parameter eines exponentiellen Trends zurück +LOGINV = LOGINV ## Gibt Quantile der Lognormalverteilung zurück +LOGNORMDIST = LOGNORMVERT ## Gibt Werte der Verteilungsfunktion einer lognormalverteilten Zufallsvariablen zurück +MAX = MAX ## Gibt den Maximalwert einer Liste mit Argumenten zurück +MAXA = MAXA ## Gibt den Maximalwert einer Liste mit Argumenten zurück, die Zahlen, Text und Wahrheitswerte enthalten +MEDIAN = MEDIAN ## Gibt den Median der angegebenen Zahlen zurück +MIN = MIN ## Gibt den Minimalwert einer Liste mit Argumenten zurück +MINA = MINA ## Gibt den kleinsten Wert einer Liste mit Argumenten zurück, die Zahlen, Text und Wahrheitswerte enthalten +MODE = MODALWERT ## Gibt den am häufigsten vorkommenden Wert in einer Datengruppe zurück +NEGBINOMDIST = NEGBINOMVERT ## Gibt Wahrscheinlichkeiten einer negativen, binominal verteilten Zufallsvariablen zurück +NORMDIST = NORMVERT ## Gibt Wahrscheinlichkeiten einer normal verteilten Zufallsvariablen zurück +NORMINV = NORMINV ## Gibt Quantile der Normalverteilung zurück +NORMSDIST = STANDNORMVERT ## Gibt Werte der Verteilungsfunktion einer standardnormalverteilten Zufallsvariablen zurück +NORMSINV = STANDNORMINV ## Gibt Quantile der Standardnormalverteilung zurück +PEARSON = PEARSON ## Gibt den Pearsonschen Korrelationskoeffizienten zurück +PERCENTILE = QUANTIL ## Gibt das Alpha-Quantil einer Gruppe von Daten zurück +PERCENTRANK = QUANTILSRANG ## Gibt den prozentualen Rang (Alpha) eines Werts in einer Datengruppe zurück +PERMUT = VARIATIONEN ## Gibt die Anzahl der Möglichkeiten zurück, um k Elemente aus einer Menge von n Elementen ohne Zurücklegen zu ziehen +POISSON = POISSON ## Gibt Wahrscheinlichkeiten einer poissonverteilten Zufallsvariablen zurück +PROB = WAHRSCHBEREICH ## Gibt die Wahrscheinlichkeit für ein von zwei Werten eingeschlossenes Intervall zurück +QUARTILE = QUARTILE ## Gibt die Quartile der Datengruppe zurück +RANK = RANG ## Gibt den Rang zurück, den eine Zahl innerhalb einer Liste von Zahlen einnimmt +RSQ = BESTIMMTHEITSMASS ## Gibt das Quadrat des Pearsonschen Korrelationskoeffizienten zurück +SKEW = SCHIEFE ## Gibt die Schiefe einer Verteilung zurück +SLOPE = STEIGUNG ## Gibt die Steigung der Regressionsgeraden zurück +SMALL = KKLEINSTE ## Gibt den k-kleinsten Wert einer Datengruppe zurück +STANDARDIZE = STANDARDISIERUNG ## Gibt den standardisierten Wert zurück +STDEV = STABW ## Schätzt die Standardabweichung ausgehend von einer Stichprobe +STDEVA = STABWA ## Schätzt die Standardabweichung ausgehend von einer Stichprobe, die Zahlen, Text und Wahrheitswerte enthält +STDEVP = STABWN ## Berechnet die Standardabweichung ausgehend von der Grundgesamtheit +STDEVPA = STABWNA ## Berechnet die Standardabweichung ausgehend von der Grundgesamtheit, die Zahlen, Text und Wahrheitswerte enthält +STEYX = STFEHLERYX ## Gibt den Standardfehler der geschätzten y-Werte für alle x-Werte der Regression zurück +TDIST = TVERT ## Gibt Werte der Verteilungsfunktion (1-Alpha) einer (Student) t-verteilten Zufallsvariablen zurück +TINV = TINV ## Gibt Quantile der t-Verteilung zurück +TREND = TREND ## Gibt Werte zurück, die sich aus einem linearen Trend ergeben +TRIMMEAN = GESTUTZTMITTEL ## Gibt den Mittelwert einer Datengruppe zurück, ohne die Randwerte zu berücksichtigen +TTEST = TTEST ## Gibt die Teststatistik eines Student'schen t-Tests zurück +VAR = VARIANZ ## Schätzt die Varianz ausgehend von einer Stichprobe +VARA = VARIANZA ## Schätzt die Varianz ausgehend von einer Stichprobe, die Zahlen, Text und Wahrheitswerte enthält +VARP = VARIANZEN ## Berechnet die Varianz ausgehend von der Grundgesamtheit +VARPA = VARIANZENA ## Berechnet die Varianz ausgehend von der Grundgesamtheit, die Zahlen, Text und Wahrheitswerte enthält +WEIBULL = WEIBULL ## Gibt Wahrscheinlichkeiten einer weibullverteilten Zufallsvariablen zurück +ZTEST = GTEST ## Gibt den einseitigen Wahrscheinlichkeitswert für einen Gausstest (Normalverteilung) zurück + + +## +## Text functions Textfunktionen +## +ASC = ASC ## Konvertiert DB-Text in einer Zeichenfolge (lateinische Buchstaben oder Katakana) in SB-Text +BAHTTEXT = BAHTTEXT ## Wandelt eine Zahl in Text im Währungsformat ß (Baht) um +CHAR = ZEICHEN ## Gibt das der Codezahl entsprechende Zeichen zurück +CLEAN = SÄUBERN ## Löscht alle nicht druckbaren Zeichen aus einem Text +CODE = CODE ## Gibt die Codezahl des ersten Zeichens in einem Text zurück +CONCATENATE = VERKETTEN ## Verknüpft mehrere Textelemente zu einem Textelement +DOLLAR = DM ## Wandelt eine Zahl in Text im Währungsformat € (Euro) um +EXACT = IDENTISCH ## Prüft, ob zwei Textwerte identisch sind +FIND = FINDEN ## Sucht nach einem Textwert, der in einem anderen Textwert enthalten ist (Groß-/Kleinschreibung wird unterschieden) +FINDB = FINDENB ## Sucht nach einem Textwert, der in einem anderen Textwert enthalten ist (Groß-/Kleinschreibung wird unterschieden) +FIXED = FEST ## Formatiert eine Zahl als Text mit einer festen Anzahl von Dezimalstellen +JIS = JIS ## Konvertiert SB-Text in einer Zeichenfolge (lateinische Buchstaben oder Katakana) in DB-Text +LEFT = LINKS ## Gibt die Zeichen ganz links in einem Textwert zurück +LEFTB = LINKSB ## Gibt die Zeichen ganz links in einem Textwert zurück +LEN = LÄNGE ## Gibt die Anzahl der Zeichen in einer Zeichenfolge zurück +LENB = LÄNGEB ## Gibt die Anzahl der Zeichen in einer Zeichenfolge zurück +LOWER = KLEIN ## Wandelt Text in Kleinbuchstaben um +MID = TEIL ## Gibt eine bestimmte Anzahl Zeichen aus einer Zeichenfolge ab der von Ihnen angegebenen Stelle zurück +MIDB = TEILB ## Gibt eine bestimmte Anzahl Zeichen aus einer Zeichenfolge ab der von Ihnen angegebenen Stelle zurück +PHONETIC = PHONETIC ## Extrahiert die phonetischen (Furigana-)Zeichen aus einer Textzeichenfolge +PROPER = GROSS2 ## Wandelt den ersten Buchstaben aller Wörter eines Textwerts in Großbuchstaben um +REPLACE = ERSETZEN ## Ersetzt Zeichen in Text +REPLACEB = ERSETZENB ## Ersetzt Zeichen in Text +REPT = WIEDERHOLEN ## Wiederholt einen Text so oft wie angegeben +RIGHT = RECHTS ## Gibt die Zeichen ganz rechts in einem Textwert zurück +RIGHTB = RECHTSB ## Gibt die Zeichen ganz rechts in einem Textwert zurück +SEARCH = SUCHEN ## Sucht nach einem Textwert, der in einem anderen Textwert enthalten ist (Groß-/Kleinschreibung wird nicht unterschieden) +SEARCHB = SUCHENB ## Sucht nach einem Textwert, der in einem anderen Textwert enthalten ist (Groß-/Kleinschreibung wird nicht unterschieden) +SUBSTITUTE = WECHSELN ## Ersetzt in einer Zeichenfolge neuen Text gegen alten +T = T ## Wandelt die zugehörigen Argumente in Text um +TEXT = TEXT ## Formatiert eine Zahl und wandelt sie in Text um +TRIM = GLÄTTEN ## Entfernt Leerzeichen aus Text +UPPER = GROSS ## Wandelt Text in Großbuchstaben um +VALUE = WERT ## Wandelt ein Textargument in eine Zahl um diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/en/uk/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/en/uk/config new file mode 100755 index 0000000..829c53b --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/en/uk/config @@ -0,0 +1,32 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +## +## (For future use) +## +currencySymbol = £ diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/es/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/es/config new file mode 100755 index 0000000..4f5ef30 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/es/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = $ ## I'm surprised that the Excel Documentation suggests $ rather than € + + +## +## Excel Error Codes (For future use) +## +NULL = #¡NULO! +DIV0 = #¡DIV/0! +VALUE = #¡VALOR! +REF = #¡REF! +NAME = #¿NOMBRE? +NUM = #¡NÚM! +NA = #N/A diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/es/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/es/functions new file mode 100755 index 0000000..cd47ee9 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/es/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions Funciones de complementos y automatización +## +GETPIVOTDATA = IMPORTARDATOSDINAMICOS ## Devuelve los datos almacenados en un informe de tabla dinámica. + + +## +## Cube functions Funciones de cubo +## +CUBEKPIMEMBER = MIEMBROKPICUBO ## Devuelve un nombre, propiedad y medida de indicador de rendimiento clave (KPI) y muestra el nombre y la propiedad en la celda. Un KPI es una medida cuantificable, como los beneficios brutos mensuales o la facturación trimestral por empleado, que se usa para supervisar el rendimiento de una organización. +CUBEMEMBER = MIEMBROCUBO ## Devuelve un miembro o tupla en una jerarquía de cubo. Se usa para validar la existencia del miembro o la tupla en el cubo. +CUBEMEMBERPROPERTY = PROPIEDADMIEMBROCUBO ## Devuelve el valor de una propiedad de miembro del cubo Se usa para validar la existencia de un nombre de miembro en el cubo y para devolver la propiedad especificada para este miembro. +CUBERANKEDMEMBER = MIEMBRORANGOCUBO ## Devuelve el miembro n, o clasificado, de un conjunto. Se usa para devolver uno o más elementos de un conjunto, por ejemplo, el representante con mejores ventas o los diez mejores alumnos. +CUBESET = CONJUNTOCUBO ## Define un conjunto calculado de miembros o tuplas mediante el envío de una expresión de conjunto al cubo en el servidor, lo que crea el conjunto y, después, devuelve dicho conjunto a Microsoft Office Excel. +CUBESETCOUNT = RECUENTOCONJUNTOCUBO ## Devuelve el número de elementos de un conjunto. +CUBEVALUE = VALORCUBO ## Devuelve un valor agregado de un cubo. + + +## +## Database functions Funciones de base de datos +## +DAVERAGE = BDPROMEDIO ## Devuelve el promedio de las entradas seleccionadas en la base de datos. +DCOUNT = BDCONTAR ## Cuenta el número de celdas que contienen números en una base de datos. +DCOUNTA = BDCONTARA ## Cuenta el número de celdas no vacías en una base de datos. +DGET = BDEXTRAER ## Extrae de una base de datos un único registro que cumple los criterios especificados. +DMAX = BDMAX ## Devuelve el valor máximo de las entradas seleccionadas de la base de datos. +DMIN = BDMIN ## Devuelve el valor mínimo de las entradas seleccionadas de la base de datos. +DPRODUCT = BDPRODUCTO ## Multiplica los valores de un campo concreto de registros de una base de datos que cumplen los criterios especificados. +DSTDEV = BDDESVEST ## Calcula la desviación estándar a partir de una muestra de entradas seleccionadas en la base de datos. +DSTDEVP = BDDESVESTP ## Calcula la desviación estándar en función de la población total de las entradas seleccionadas de la base de datos. +DSUM = BDSUMA ## Suma los números de la columna de campo de los registros de la base de datos que cumplen los criterios. +DVAR = BDVAR ## Calcula la varianza a partir de una muestra de entradas seleccionadas de la base de datos. +DVARP = BDVARP ## Calcula la varianza a partir de la población total de entradas seleccionadas de la base de datos. + + +## +## Date and time functions Funciones de fecha y hora +## +DATE = FECHA ## Devuelve el número de serie correspondiente a una fecha determinada. +DATEVALUE = FECHANUMERO ## Convierte una fecha con formato de texto en un valor de número de serie. +DAY = DIA ## Convierte un número de serie en un valor de día del mes. +DAYS360 = DIAS360 ## Calcula el número de días entre dos fechas a partir de un año de 360 días. +EDATE = FECHA.MES ## Devuelve el número de serie de la fecha equivalente al número indicado de meses anteriores o posteriores a la fecha inicial. +EOMONTH = FIN.MES ## Devuelve el número de serie correspondiente al último día del mes anterior o posterior a un número de meses especificado. +HOUR = HORA ## Convierte un número de serie en un valor de hora. +MINUTE = MINUTO ## Convierte un número de serie en un valor de minuto. +MONTH = MES ## Convierte un número de serie en un valor de mes. +NETWORKDAYS = DIAS.LAB ## Devuelve el número de todos los días laborables existentes entre dos fechas. +NOW = AHORA ## Devuelve el número de serie correspondiente a la fecha y hora actuales. +SECOND = SEGUNDO ## Convierte un número de serie en un valor de segundo. +TIME = HORA ## Devuelve el número de serie correspondiente a una hora determinada. +TIMEVALUE = HORANUMERO ## Convierte una hora con formato de texto en un valor de número de serie. +TODAY = HOY ## Devuelve el número de serie correspondiente al día actual. +WEEKDAY = DIASEM ## Convierte un número de serie en un valor de día de la semana. +WEEKNUM = NUM.DE.SEMANA ## Convierte un número de serie en un número que representa el lugar numérico correspondiente a una semana de un año. +WORKDAY = DIA.LAB ## Devuelve el número de serie de la fecha que tiene lugar antes o después de un número determinado de días laborables. +YEAR = AÑO ## Convierte un número de serie en un valor de año. +YEARFRAC = FRAC.AÑO ## Devuelve la fracción de año que representa el número total de días existentes entre el valor de fecha_inicial y el de fecha_final. + + +## +## Engineering functions Funciones de ingeniería +## +BESSELI = BESSELI ## Devuelve la función Bessel In(x) modificada. +BESSELJ = BESSELJ ## Devuelve la función Bessel Jn(x). +BESSELK = BESSELK ## Devuelve la función Bessel Kn(x) modificada. +BESSELY = BESSELY ## Devuelve la función Bessel Yn(x). +BIN2DEC = BIN.A.DEC ## Convierte un número binario en decimal. +BIN2HEX = BIN.A.HEX ## Convierte un número binario en hexadecimal. +BIN2OCT = BIN.A.OCT ## Convierte un número binario en octal. +COMPLEX = COMPLEJO ## Convierte coeficientes reales e imaginarios en un número complejo. +CONVERT = CONVERTIR ## Convierte un número de un sistema de medida a otro. +DEC2BIN = DEC.A.BIN ## Convierte un número decimal en binario. +DEC2HEX = DEC.A.HEX ## Convierte un número decimal en hexadecimal. +DEC2OCT = DEC.A.OCT ## Convierte un número decimal en octal. +DELTA = DELTA ## Comprueba si dos valores son iguales. +ERF = FUN.ERROR ## Devuelve la función de error. +ERFC = FUN.ERROR.COMPL ## Devuelve la función de error complementario. +GESTEP = MAYOR.O.IGUAL ## Comprueba si un número es mayor que un valor de umbral. +HEX2BIN = HEX.A.BIN ## Convierte un número hexadecimal en binario. +HEX2DEC = HEX.A.DEC ## Convierte un número hexadecimal en decimal. +HEX2OCT = HEX.A.OCT ## Convierte un número hexadecimal en octal. +IMABS = IM.ABS ## Devuelve el valor absoluto (módulo) de un número complejo. +IMAGINARY = IMAGINARIO ## Devuelve el coeficiente imaginario de un número complejo. +IMARGUMENT = IM.ANGULO ## Devuelve el argumento theta, un ángulo expresado en radianes. +IMCONJUGATE = IM.CONJUGADA ## Devuelve la conjugada compleja de un número complejo. +IMCOS = IM.COS ## Devuelve el coseno de un número complejo. +IMDIV = IM.DIV ## Devuelve el cociente de dos números complejos. +IMEXP = IM.EXP ## Devuelve el valor exponencial de un número complejo. +IMLN = IM.LN ## Devuelve el logaritmo natural (neperiano) de un número complejo. +IMLOG10 = IM.LOG10 ## Devuelve el logaritmo en base 10 de un número complejo. +IMLOG2 = IM.LOG2 ## Devuelve el logaritmo en base 2 de un número complejo. +IMPOWER = IM.POT ## Devuelve un número complejo elevado a una potencia entera. +IMPRODUCT = IM.PRODUCT ## Devuelve el producto de números complejos. +IMREAL = IM.REAL ## Devuelve el coeficiente real de un número complejo. +IMSIN = IM.SENO ## Devuelve el seno de un número complejo. +IMSQRT = IM.RAIZ2 ## Devuelve la raíz cuadrada de un número complejo. +IMSUB = IM.SUSTR ## Devuelve la diferencia entre dos números complejos. +IMSUM = IM.SUM ## Devuelve la suma de números complejos. +OCT2BIN = OCT.A.BIN ## Convierte un número octal en binario. +OCT2DEC = OCT.A.DEC ## Convierte un número octal en decimal. +OCT2HEX = OCT.A.HEX ## Convierte un número octal en hexadecimal. + + +## +## Financial functions Funciones financieras +## +ACCRINT = INT.ACUM ## Devuelve el interés acumulado de un valor bursátil con pagos de interés periódicos. +ACCRINTM = INT.ACUM.V ## Devuelve el interés acumulado de un valor bursátil con pagos de interés al vencimiento. +AMORDEGRC = AMORTIZ.PROGRE ## Devuelve la amortización de cada período contable mediante el uso de un coeficiente de amortización. +AMORLINC = AMORTIZ.LIN ## Devuelve la amortización de cada uno de los períodos contables. +COUPDAYBS = CUPON.DIAS.L1 ## Devuelve el número de días desde el principio del período de un cupón hasta la fecha de liquidación. +COUPDAYS = CUPON.DIAS ## Devuelve el número de días del período (entre dos cupones) donde se encuentra la fecha de liquidación. +COUPDAYSNC = CUPON.DIAS.L2 ## Devuelve el número de días desde la fecha de liquidación hasta la fecha del próximo cupón. +COUPNCD = CUPON.FECHA.L2 ## Devuelve la fecha del próximo cupón después de la fecha de liquidación. +COUPNUM = CUPON.NUM ## Devuelve el número de pagos de cupón entre la fecha de liquidación y la fecha de vencimiento. +COUPPCD = CUPON.FECHA.L1 ## Devuelve la fecha de cupón anterior a la fecha de liquidación. +CUMIPMT = PAGO.INT.ENTRE ## Devuelve el interés acumulado pagado entre dos períodos. +CUMPRINC = PAGO.PRINC.ENTRE ## Devuelve el capital acumulado pagado de un préstamo entre dos períodos. +DB = DB ## Devuelve la amortización de un bien durante un período específico a través del método de amortización de saldo fijo. +DDB = DDB ## Devuelve la amortización de un bien durante un período específico a través del método de amortización por doble disminución de saldo u otro método que se especifique. +DISC = TASA.DESC ## Devuelve la tasa de descuento de un valor bursátil. +DOLLARDE = MONEDA.DEC ## Convierte una cotización de un valor bursátil expresada en forma fraccionaria en una cotización de un valor bursátil expresada en forma decimal. +DOLLARFR = MONEDA.FRAC ## Convierte una cotización de un valor bursátil expresada en forma decimal en una cotización de un valor bursátil expresada en forma fraccionaria. +DURATION = DURACION ## Devuelve la duración anual de un valor bursátil con pagos de interés periódico. +EFFECT = INT.EFECTIVO ## Devuelve la tasa de interés anual efectiva. +FV = VF ## Devuelve el valor futuro de una inversión. +FVSCHEDULE = VF.PLAN ## Devuelve el valor futuro de un capital inicial después de aplicar una serie de tasas de interés compuesto. +INTRATE = TASA.INT ## Devuelve la tasa de interés para la inversión total de un valor bursátil. +IPMT = PAGOINT ## Devuelve el pago de intereses de una inversión durante un período determinado. +IRR = TIR ## Devuelve la tasa interna de retorno para una serie de flujos de efectivo periódicos. +ISPMT = INT.PAGO.DIR ## Calcula el interés pagado durante un período específico de una inversión. +MDURATION = DURACION.MODIF ## Devuelve la duración de Macauley modificada de un valor bursátil con un valor nominal supuesto de 100 $. +MIRR = TIRM ## Devuelve la tasa interna de retorno donde se financian flujos de efectivo positivos y negativos a tasas diferentes. +NOMINAL = TASA.NOMINAL ## Devuelve la tasa nominal de interés anual. +NPER = NPER ## Devuelve el número de períodos de una inversión. +NPV = VNA ## Devuelve el valor neto actual de una inversión en función de una serie de flujos periódicos de efectivo y una tasa de descuento. +ODDFPRICE = PRECIO.PER.IRREGULAR.1 ## Devuelve el precio por un valor nominal de 100 $ de un valor bursátil con un primer período impar. +ODDFYIELD = RENDTO.PER.IRREGULAR.1 ## Devuelve el rendimiento de un valor bursátil con un primer período impar. +ODDLPRICE = PRECIO.PER.IRREGULAR.2 ## Devuelve el precio por un valor nominal de 100 $ de un valor bursátil con un último período impar. +ODDLYIELD = RENDTO.PER.IRREGULAR.2 ## Devuelve el rendimiento de un valor bursátil con un último período impar. +PMT = PAGO ## Devuelve el pago periódico de una anualidad. +PPMT = PAGOPRIN ## Devuelve el pago de capital de una inversión durante un período determinado. +PRICE = PRECIO ## Devuelve el precio por un valor nominal de 100 $ de un valor bursátil que paga una tasa de interés periódico. +PRICEDISC = PRECIO.DESCUENTO ## Devuelve el precio por un valor nominal de 100 $ de un valor bursátil con descuento. +PRICEMAT = PRECIO.VENCIMIENTO ## Devuelve el precio por un valor nominal de 100 $ de un valor bursátil que paga interés a su vencimiento. +PV = VALACT ## Devuelve el valor actual de una inversión. +RATE = TASA ## Devuelve la tasa de interés por período de una anualidad. +RECEIVED = CANTIDAD.RECIBIDA ## Devuelve la cantidad recibida al vencimiento de un valor bursátil completamente invertido. +SLN = SLN ## Devuelve la amortización por método directo de un bien en un período dado. +SYD = SYD ## Devuelve la amortización por suma de dígitos de los años de un bien durante un período especificado. +TBILLEQ = LETRA.DE.TES.EQV.A.BONO ## Devuelve el rendimiento de un bono equivalente a una letra del Tesoro (de EE.UU.) +TBILLPRICE = LETRA.DE.TES.PRECIO ## Devuelve el precio por un valor nominal de 100 $ de una letra del Tesoro (de EE.UU.) +TBILLYIELD = LETRA.DE.TES.RENDTO ## Devuelve el rendimiento de una letra del Tesoro (de EE.UU.) +VDB = DVS ## Devuelve la amortización de un bien durante un período específico o parcial a través del método de cálculo del saldo en disminución. +XIRR = TIR.NO.PER ## Devuelve la tasa interna de retorno para un flujo de efectivo que no es necesariamente periódico. +XNPV = VNA.NO.PER ## Devuelve el valor neto actual para un flujo de efectivo que no es necesariamente periódico. +YIELD = RENDTO ## Devuelve el rendimiento de un valor bursátil que paga intereses periódicos. +YIELDDISC = RENDTO.DESC ## Devuelve el rendimiento anual de un valor bursátil con descuento; por ejemplo, una letra del Tesoro (de EE.UU.) +YIELDMAT = RENDTO.VENCTO ## Devuelve el rendimiento anual de un valor bursátil que paga intereses al vencimiento. + + +## +## Information functions Funciones de información +## +CELL = CELDA ## Devuelve información acerca del formato, la ubicación o el contenido de una celda. +ERROR.TYPE = TIPO.DE.ERROR ## Devuelve un número que corresponde a un tipo de error. +INFO = INFO ## Devuelve información acerca del entorno operativo en uso. +ISBLANK = ESBLANCO ## Devuelve VERDADERO si el valor está en blanco. +ISERR = ESERR ## Devuelve VERDADERO si el valor es cualquier valor de error excepto #N/A. +ISERROR = ESERROR ## Devuelve VERDADERO si el valor es cualquier valor de error. +ISEVEN = ES.PAR ## Devuelve VERDADERO si el número es par. +ISLOGICAL = ESLOGICO ## Devuelve VERDADERO si el valor es un valor lógico. +ISNA = ESNOD ## Devuelve VERDADERO si el valor es el valor de error #N/A. +ISNONTEXT = ESNOTEXTO ## Devuelve VERDADERO si el valor no es texto. +ISNUMBER = ESNUMERO ## Devuelve VERDADERO si el valor es un número. +ISODD = ES.IMPAR ## Devuelve VERDADERO si el número es impar. +ISREF = ESREF ## Devuelve VERDADERO si el valor es una referencia. +ISTEXT = ESTEXTO ## Devuelve VERDADERO si el valor es texto. +N = N ## Devuelve un valor convertido en un número. +NA = ND ## Devuelve el valor de error #N/A. +TYPE = TIPO ## Devuelve un número que indica el tipo de datos de un valor. + + +## +## Logical functions Funciones lógicas +## +AND = Y ## Devuelve VERDADERO si todos sus argumentos son VERDADERO. +FALSE = FALSO ## Devuelve el valor lógico FALSO. +IF = SI ## Especifica una prueba lógica que realizar. +IFERROR = SI.ERROR ## Devuelve un valor que se especifica si una fórmula lo evalúa como un error; de lo contrario, devuelve el resultado de la fórmula. +NOT = NO ## Invierte el valor lógico del argumento. +OR = O ## Devuelve VERDADERO si cualquier argumento es VERDADERO. +TRUE = VERDADERO ## Devuelve el valor lógico VERDADERO. + + +## +## Lookup and reference functions Funciones de búsqueda y referencia +## +ADDRESS = DIRECCION ## Devuelve una referencia como texto a una sola celda de una hoja de cálculo. +AREAS = AREAS ## Devuelve el número de áreas de una referencia. +CHOOSE = ELEGIR ## Elige un valor de una lista de valores. +COLUMN = COLUMNA ## Devuelve el número de columna de una referencia. +COLUMNS = COLUMNAS ## Devuelve el número de columnas de una referencia. +HLOOKUP = BUSCARH ## Busca en la fila superior de una matriz y devuelve el valor de la celda indicada. +HYPERLINK = HIPERVINCULO ## Crea un acceso directo o un salto que abre un documento almacenado en un servidor de red, en una intranet o en Internet. +INDEX = INDICE ## Usa un índice para elegir un valor de una referencia o matriz. +INDIRECT = INDIRECTO ## Devuelve una referencia indicada por un valor de texto. +LOOKUP = BUSCAR ## Busca valores de un vector o una matriz. +MATCH = COINCIDIR ## Busca valores de una referencia o matriz. +OFFSET = DESREF ## Devuelve un desplazamiento de referencia respecto a una referencia dada. +ROW = FILA ## Devuelve el número de fila de una referencia. +ROWS = FILAS ## Devuelve el número de filas de una referencia. +RTD = RDTR ## Recupera datos en tiempo real desde un programa compatible con la automatización COM (automatización: modo de trabajar con los objetos de una aplicación desde otra aplicación o herramienta de entorno. La automatización, antes denominada automatización OLE, es un estándar de la industria y una función del Modelo de objetos componentes (COM).). +TRANSPOSE = TRANSPONER ## Devuelve la transposición de una matriz. +VLOOKUP = BUSCARV ## Busca en la primera columna de una matriz y se mueve en horizontal por la fila para devolver el valor de una celda. + + +## +## Math and trigonometry functions Funciones matemáticas y trigonométricas +## +ABS = ABS ## Devuelve el valor absoluto de un número. +ACOS = ACOS ## Devuelve el arcocoseno de un número. +ACOSH = ACOSH ## Devuelve el coseno hiperbólico inverso de un número. +ASIN = ASENO ## Devuelve el arcoseno de un número. +ASINH = ASENOH ## Devuelve el seno hiperbólico inverso de un número. +ATAN = ATAN ## Devuelve la arcotangente de un número. +ATAN2 = ATAN2 ## Devuelve la arcotangente de las coordenadas "x" e "y". +ATANH = ATANH ## Devuelve la tangente hiperbólica inversa de un número. +CEILING = MULTIPLO.SUPERIOR ## Redondea un número al entero más próximo o al múltiplo significativo más cercano. +COMBIN = COMBINAT ## Devuelve el número de combinaciones para un número determinado de objetos. +COS = COS ## Devuelve el coseno de un número. +COSH = COSH ## Devuelve el coseno hiperbólico de un número. +DEGREES = GRADOS ## Convierte radianes en grados. +EVEN = REDONDEA.PAR ## Redondea un número hasta el entero par más próximo. +EXP = EXP ## Devuelve e elevado a la potencia de un número dado. +FACT = FACT ## Devuelve el factorial de un número. +FACTDOUBLE = FACT.DOBLE ## Devuelve el factorial doble de un número. +FLOOR = MULTIPLO.INFERIOR ## Redondea un número hacia abajo, en dirección hacia cero. +GCD = M.C.D ## Devuelve el máximo común divisor. +INT = ENTERO ## Redondea un número hacia abajo hasta el entero más próximo. +LCM = M.C.M ## Devuelve el mínimo común múltiplo. +LN = LN ## Devuelve el logaritmo natural (neperiano) de un número. +LOG = LOG ## Devuelve el logaritmo de un número en una base especificada. +LOG10 = LOG10 ## Devuelve el logaritmo en base 10 de un número. +MDETERM = MDETERM ## Devuelve la determinante matricial de una matriz. +MINVERSE = MINVERSA ## Devuelve la matriz inversa de una matriz. +MMULT = MMULT ## Devuelve el producto de matriz de dos matrices. +MOD = RESIDUO ## Devuelve el resto de la división. +MROUND = REDOND.MULT ## Devuelve un número redondeado al múltiplo deseado. +MULTINOMIAL = MULTINOMIAL ## Devuelve el polinomio de un conjunto de números. +ODD = REDONDEA.IMPAR ## Redondea un número hacia arriba hasta el entero impar más próximo. +PI = PI ## Devuelve el valor de pi. +POWER = POTENCIA ## Devuelve el resultado de elevar un número a una potencia. +PRODUCT = PRODUCTO ## Multiplica sus argumentos. +QUOTIENT = COCIENTE ## Devuelve la parte entera de una división. +RADIANS = RADIANES ## Convierte grados en radianes. +RAND = ALEATORIO ## Devuelve un número aleatorio entre 0 y 1. +RANDBETWEEN = ALEATORIO.ENTRE ## Devuelve un número aleatorio entre los números que especifique. +ROMAN = NUMERO.ROMANO ## Convierte un número arábigo en número romano, con formato de texto. +ROUND = REDONDEAR ## Redondea un número al número de decimales especificado. +ROUNDDOWN = REDONDEAR.MENOS ## Redondea un número hacia abajo, en dirección hacia cero. +ROUNDUP = REDONDEAR.MAS ## Redondea un número hacia arriba, en dirección contraria a cero. +SERIESSUM = SUMA.SERIES ## Devuelve la suma de una serie de potencias en función de la fórmula. +SIGN = SIGNO ## Devuelve el signo de un número. +SIN = SENO ## Devuelve el seno de un ángulo determinado. +SINH = SENOH ## Devuelve el seno hiperbólico de un número. +SQRT = RAIZ ## Devuelve la raíz cuadrada positiva de un número. +SQRTPI = RAIZ2PI ## Devuelve la raíz cuadrada de un número multiplicado por PI (número * pi). +SUBTOTAL = SUBTOTALES ## Devuelve un subtotal en una lista o base de datos. +SUM = SUMA ## Suma sus argumentos. +SUMIF = SUMAR.SI ## Suma las celdas especificadas que cumplen unos criterios determinados. +SUMIFS = SUMAR.SI.CONJUNTO ## Suma las celdas de un rango que cumplen varios criterios. +SUMPRODUCT = SUMAPRODUCTO ## Devuelve la suma de los productos de los correspondientes componentes de matriz. +SUMSQ = SUMA.CUADRADOS ## Devuelve la suma de los cuadrados de los argumentos. +SUMX2MY2 = SUMAX2MENOSY2 ## Devuelve la suma de la diferencia de los cuadrados de los valores correspondientes de dos matrices. +SUMX2PY2 = SUMAX2MASY2 ## Devuelve la suma de la suma de los cuadrados de los valores correspondientes de dos matrices. +SUMXMY2 = SUMAXMENOSY2 ## Devuelve la suma de los cuadrados de las diferencias de los valores correspondientes de dos matrices. +TAN = TAN ## Devuelve la tangente de un número. +TANH = TANH ## Devuelve la tangente hiperbólica de un número. +TRUNC = TRUNCAR ## Trunca un número a un entero. + + +## +## Statistical functions Funciones estadísticas +## +AVEDEV = DESVPROM ## Devuelve el promedio de las desviaciones absolutas de la media de los puntos de datos. +AVERAGE = PROMEDIO ## Devuelve el promedio de sus argumentos. +AVERAGEA = PROMEDIOA ## Devuelve el promedio de sus argumentos, incluidos números, texto y valores lógicos. +AVERAGEIF = PROMEDIO.SI ## Devuelve el promedio (media aritmética) de todas las celdas de un rango que cumplen unos criterios determinados. +AVERAGEIFS = PROMEDIO.SI.CONJUNTO ## Devuelve el promedio (media aritmética) de todas las celdas que cumplen múltiples criterios. +BETADIST = DISTR.BETA ## Devuelve la función de distribución beta acumulativa. +BETAINV = DISTR.BETA.INV ## Devuelve la función inversa de la función de distribución acumulativa de una distribución beta especificada. +BINOMDIST = DISTR.BINOM ## Devuelve la probabilidad de una variable aleatoria discreta siguiendo una distribución binomial. +CHIDIST = DISTR.CHI ## Devuelve la probabilidad de una variable aleatoria continua siguiendo una distribución chi cuadrado de una sola cola. +CHIINV = PRUEBA.CHI.INV ## Devuelve la función inversa de la probabilidad de una variable aleatoria continua siguiendo una distribución chi cuadrado de una sola cola. +CHITEST = PRUEBA.CHI ## Devuelve la prueba de independencia. +CONFIDENCE = INTERVALO.CONFIANZA ## Devuelve el intervalo de confianza de la media de una población. +CORREL = COEF.DE.CORREL ## Devuelve el coeficiente de correlación entre dos conjuntos de datos. +COUNT = CONTAR ## Cuenta cuántos números hay en la lista de argumentos. +COUNTA = CONTARA ## Cuenta cuántos valores hay en la lista de argumentos. +COUNTBLANK = CONTAR.BLANCO ## Cuenta el número de celdas en blanco de un rango. +COUNTIF = CONTAR.SI ## Cuenta el número de celdas, dentro del rango, que cumplen el criterio especificado. +COUNTIFS = CONTAR.SI.CONJUNTO ## Cuenta el número de celdas, dentro del rango, que cumplen varios criterios. +COVAR = COVAR ## Devuelve la covarianza, que es el promedio de los productos de las desviaciones para cada pareja de puntos de datos. +CRITBINOM = BINOM.CRIT ## Devuelve el menor valor cuya distribución binomial acumulativa es menor o igual a un valor de criterio. +DEVSQ = DESVIA2 ## Devuelve la suma de los cuadrados de las desviaciones. +EXPONDIST = DISTR.EXP ## Devuelve la distribución exponencial. +FDIST = DISTR.F ## Devuelve la distribución de probabilidad F. +FINV = DISTR.F.INV ## Devuelve la función inversa de la distribución de probabilidad F. +FISHER = FISHER ## Devuelve la transformación Fisher. +FISHERINV = PRUEBA.FISHER.INV ## Devuelve la función inversa de la transformación Fisher. +FORECAST = PRONOSTICO ## Devuelve un valor en una tendencia lineal. +FREQUENCY = FRECUENCIA ## Devuelve una distribución de frecuencia como una matriz vertical. +FTEST = PRUEBA.F ## Devuelve el resultado de una prueba F. +GAMMADIST = DISTR.GAMMA ## Devuelve la distribución gamma. +GAMMAINV = DISTR.GAMMA.INV ## Devuelve la función inversa de la distribución gamma acumulativa. +GAMMALN = GAMMA.LN ## Devuelve el logaritmo natural de la función gamma, G(x). +GEOMEAN = MEDIA.GEOM ## Devuelve la media geométrica. +GROWTH = CRECIMIENTO ## Devuelve valores en una tendencia exponencial. +HARMEAN = MEDIA.ARMO ## Devuelve la media armónica. +HYPGEOMDIST = DISTR.HIPERGEOM ## Devuelve la distribución hipergeométrica. +INTERCEPT = INTERSECCION.EJE ## Devuelve la intersección de la línea de regresión lineal. +KURT = CURTOSIS ## Devuelve la curtosis de un conjunto de datos. +LARGE = K.ESIMO.MAYOR ## Devuelve el k-ésimo mayor valor de un conjunto de datos. +LINEST = ESTIMACION.LINEAL ## Devuelve los parámetros de una tendencia lineal. +LOGEST = ESTIMACION.LOGARITMICA ## Devuelve los parámetros de una tendencia exponencial. +LOGINV = DISTR.LOG.INV ## Devuelve la función inversa de la distribución logarítmico-normal. +LOGNORMDIST = DISTR.LOG.NORM ## Devuelve la distribución logarítmico-normal acumulativa. +MAX = MAX ## Devuelve el valor máximo de una lista de argumentos. +MAXA = MAXA ## Devuelve el valor máximo de una lista de argumentos, incluidos números, texto y valores lógicos. +MEDIAN = MEDIANA ## Devuelve la mediana de los números dados. +MIN = MIN ## Devuelve el valor mínimo de una lista de argumentos. +MINA = MINA ## Devuelve el valor mínimo de una lista de argumentos, incluidos números, texto y valores lógicos. +MODE = MODA ## Devuelve el valor más común de un conjunto de datos. +NEGBINOMDIST = NEGBINOMDIST ## Devuelve la distribución binomial negativa. +NORMDIST = DISTR.NORM ## Devuelve la distribución normal acumulativa. +NORMINV = DISTR.NORM.INV ## Devuelve la función inversa de la distribución normal acumulativa. +NORMSDIST = DISTR.NORM.ESTAND ## Devuelve la distribución normal estándar acumulativa. +NORMSINV = DISTR.NORM.ESTAND.INV ## Devuelve la función inversa de la distribución normal estándar acumulativa. +PEARSON = PEARSON ## Devuelve el coeficiente de momento de correlación de producto Pearson. +PERCENTILE = PERCENTIL ## Devuelve el k-ésimo percentil de los valores de un rango. +PERCENTRANK = RANGO.PERCENTIL ## Devuelve el rango porcentual de un valor de un conjunto de datos. +PERMUT = PERMUTACIONES ## Devuelve el número de permutaciones de un número determinado de objetos. +POISSON = POISSON ## Devuelve la distribución de Poisson. +PROB = PROBABILIDAD ## Devuelve la probabilidad de que los valores de un rango se encuentren entre dos límites. +QUARTILE = CUARTIL ## Devuelve el cuartil de un conjunto de datos. +RANK = JERARQUIA ## Devuelve la jerarquía de un número en una lista de números. +RSQ = COEFICIENTE.R2 ## Devuelve el cuadrado del coeficiente de momento de correlación de producto Pearson. +SKEW = COEFICIENTE.ASIMETRIA ## Devuelve la asimetría de una distribución. +SLOPE = PENDIENTE ## Devuelve la pendiente de la línea de regresión lineal. +SMALL = K.ESIMO.MENOR ## Devuelve el k-ésimo menor valor de un conjunto de datos. +STANDARDIZE = NORMALIZACION ## Devuelve un valor normalizado. +STDEV = DESVEST ## Calcula la desviación estándar a partir de una muestra. +STDEVA = DESVESTA ## Calcula la desviación estándar a partir de una muestra, incluidos números, texto y valores lógicos. +STDEVP = DESVESTP ## Calcula la desviación estándar en función de toda la población. +STDEVPA = DESVESTPA ## Calcula la desviación estándar en función de toda la población, incluidos números, texto y valores lógicos. +STEYX = ERROR.TIPICO.XY ## Devuelve el error estándar del valor de "y" previsto para cada "x" de la regresión. +TDIST = DISTR.T ## Devuelve la distribución de t de Student. +TINV = DISTR.T.INV ## Devuelve la función inversa de la distribución de t de Student. +TREND = TENDENCIA ## Devuelve valores en una tendencia lineal. +TRIMMEAN = MEDIA.ACOTADA ## Devuelve la media del interior de un conjunto de datos. +TTEST = PRUEBA.T ## Devuelve la probabilidad asociada a una prueba t de Student. +VAR = VAR ## Calcula la varianza en función de una muestra. +VARA = VARA ## Calcula la varianza en función de una muestra, incluidos números, texto y valores lógicos. +VARP = VARP ## Calcula la varianza en función de toda la población. +VARPA = VARPA ## Calcula la varianza en función de toda la población, incluidos números, texto y valores lógicos. +WEIBULL = DIST.WEIBULL ## Devuelve la distribución de Weibull. +ZTEST = PRUEBA.Z ## Devuelve el valor de una probabilidad de una cola de una prueba z. + + +## +## Text functions Funciones de texto +## +ASC = ASC ## Convierte las letras inglesas o katakana de ancho completo (de dos bytes) dentro de una cadena de caracteres en caracteres de ancho medio (de un byte). +BAHTTEXT = TEXTOBAHT ## Convierte un número en texto, con el formato de moneda ß (Baht). +CHAR = CARACTER ## Devuelve el carácter especificado por el número de código. +CLEAN = LIMPIAR ## Quita del texto todos los caracteres no imprimibles. +CODE = CODIGO ## Devuelve un código numérico del primer carácter de una cadena de texto. +CONCATENATE = CONCATENAR ## Concatena varios elementos de texto en uno solo. +DOLLAR = MONEDA ## Convierte un número en texto, con el formato de moneda $ (dólar). +EXACT = IGUAL ## Comprueba si dos valores de texto son idénticos. +FIND = ENCONTRAR ## Busca un valor de texto dentro de otro (distingue mayúsculas de minúsculas). +FINDB = ENCONTRARB ## Busca un valor de texto dentro de otro (distingue mayúsculas de minúsculas). +FIXED = DECIMAL ## Da formato a un número como texto con un número fijo de decimales. +JIS = JIS ## Convierte las letras inglesas o katakana de ancho medio (de un byte) dentro de una cadena de caracteres en caracteres de ancho completo (de dos bytes). +LEFT = IZQUIERDA ## Devuelve los caracteres del lado izquierdo de un valor de texto. +LEFTB = IZQUIERDAB ## Devuelve los caracteres del lado izquierdo de un valor de texto. +LEN = LARGO ## Devuelve el número de caracteres de una cadena de texto. +LENB = LARGOB ## Devuelve el número de caracteres de una cadena de texto. +LOWER = MINUSC ## Pone el texto en minúsculas. +MID = EXTRAE ## Devuelve un número específico de caracteres de una cadena de texto que comienza en la posición que se especifique. +MIDB = EXTRAEB ## Devuelve un número específico de caracteres de una cadena de texto que comienza en la posición que se especifique. +PHONETIC = FONETICO ## Extrae los caracteres fonéticos (furigana) de una cadena de texto. +PROPER = NOMPROPIO ## Pone en mayúscula la primera letra de cada palabra de un valor de texto. +REPLACE = REEMPLAZAR ## Reemplaza caracteres de texto. +REPLACEB = REEMPLAZARB ## Reemplaza caracteres de texto. +REPT = REPETIR ## Repite el texto un número determinado de veces. +RIGHT = DERECHA ## Devuelve los caracteres del lado derecho de un valor de texto. +RIGHTB = DERECHAB ## Devuelve los caracteres del lado derecho de un valor de texto. +SEARCH = HALLAR ## Busca un valor de texto dentro de otro (no distingue mayúsculas de minúsculas). +SEARCHB = HALLARB ## Busca un valor de texto dentro de otro (no distingue mayúsculas de minúsculas). +SUBSTITUTE = SUSTITUIR ## Sustituye texto nuevo por texto antiguo en una cadena de texto. +T = T ## Convierte sus argumentos a texto. +TEXT = TEXTO ## Da formato a un número y lo convierte en texto. +TRIM = ESPACIOS ## Quita los espacios del texto. +UPPER = MAYUSC ## Pone el texto en mayúsculas. +VALUE = VALOR ## Convierte un argumento de texto en un número. diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fi/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fi/config new file mode 100755 index 0000000..04c5075 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fi/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = $ # Symbol not known, should it be a € (Euro)? + + +## +## Excel Error Codes (For future use) +## +NULL = #TYHJÄ! +DIV0 = #JAKO/0! +VALUE = #ARVO! +REF = #VIITTAUS! +NAME = #NIMI? +NUM = #LUKU! +NA = #PUUTTUU diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fi/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fi/functions new file mode 100755 index 0000000..becc06e --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fi/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions Apuohjelma- ja automaatiofunktiot +## +GETPIVOTDATA = NOUDA.PIVOT.TIEDOT ## Palauttaa pivot-taulukkoraporttiin tallennettuja tietoja. + + +## +## Cube functions Kuutiofunktiot +## +CUBEKPIMEMBER = KUUTIOKPIJÄSEN ## Palauttaa suorituskykyilmaisimen (KPI) nimen, ominaisuuden sekä mitan ja näyttää nimen sekä ominaisuuden solussa. KPI on mitattavissa oleva suure, kuten kuukauden bruttotuotto tai vuosineljänneksen työntekijäkohtainen liikevaihto, joiden avulla tarkkaillaan organisaation suorituskykyä. +CUBEMEMBER = KUUTIONJÄSEN ## Palauttaa kuutiohierarkian jäsenen tai monikon. Tällä funktiolla voit tarkistaa, että jäsen tai monikko on olemassa kuutiossa. +CUBEMEMBERPROPERTY = KUUTIONJÄSENENOMINAISUUS ## Palauttaa kuution jäsenominaisuuden arvon. Tällä funktiolla voit tarkistaa, että nimi on olemassa kuutiossa, ja palauttaa tämän jäsenen määritetyn ominaisuuden. +CUBERANKEDMEMBER = KUUTIONLUOKITELTUJÄSEN ## Palauttaa joukon n:nnen jäsenen. Tällä funktiolla voit palauttaa joukosta elementtejä, kuten parhaan myyjän tai 10 parasta opiskelijaa. +CUBESET = KUUTIOJOUKKO ## Määrittää lasketun jäsen- tai monikkojoukon lähettämällä joukon lausekkeita palvelimessa olevalle kuutiolle. Palvelin luo joukon ja palauttaa sen Microsoft Office Excelille. +CUBESETCOUNT = KUUTIOJOUKKOJENMÄÄRÄ ## Palauttaa joukon kohteiden määrän. +CUBEVALUE = KUUTIONARVO ## Palauttaa koostetun arvon kuutiosta. + + +## +## Database functions Tietokantafunktiot +## +DAVERAGE = TKESKIARVO ## Palauttaa valittujen tietokantamerkintöjen keskiarvon. +DCOUNT = TLASKE ## Laskee tietokannan lukuja sisältävien solujen määrän. +DCOUNTA = TLASKEA ## Laskee tietokannan tietoja sisältävien solujen määrän. +DGET = TNOUDA ## Hakee määritettyjä ehtoja vastaavan tietueen tietokannasta. +DMAX = TMAKS ## Palauttaa suurimman arvon tietokannasta valittujen arvojen joukosta. +DMIN = TMIN ## Palauttaa pienimmän arvon tietokannasta valittujen arvojen joukosta. +DPRODUCT = TTULO ## Kertoo määritetyn ehdon täyttävien tietokannan tietueiden tietyssä kentässä olevat arvot. +DSTDEV = TKESKIHAJONTA ## Laskee keskihajonnan tietokannasta valituista arvoista muodostuvan otoksen perusteella. +DSTDEVP = TKESKIHAJONTAP ## Laskee keskihajonnan tietokannasta valittujen arvojen koko populaation perusteella. +DSUM = TSUMMA ## Lisää luvut määritetyn ehdon täyttävien tietokannan tietueiden kenttäsarakkeeseen. +DVAR = TVARIANSSI ## Laskee varianssin tietokannasta valittujen arvojen otoksen perusteella. +DVARP = TVARIANSSIP ## Laskee varianssin tietokannasta valittujen arvojen koko populaation perusteella. + + +## +## Date and time functions Päivämäärä- ja aikafunktiot +## +DATE = PÄIVÄYS ## Palauttaa annetun päivämäärän järjestysluvun. +DATEVALUE = PÄIVÄYSARVO ## Muuntaa tekstimuodossa olevan päivämäärän järjestysluvuksi. +DAY = PÄIVÄ ## Muuntaa järjestysluvun kuukauden päiväksi. +DAYS360 = PÄIVÄT360 ## Laskee kahden päivämäärän välisten päivien määrän käyttäen perustana 360-päiväistä vuotta. +EDATE = PÄIVÄ.KUUKAUSI ## Palauttaa järjestyslukuna päivämäärän, joka poikkeaa aloituspäivän päivämäärästä annetun kuukausimäärän verran joko eteen- tai taaksepäin. +EOMONTH = KUUKAUSI.LOPPU ## Palauttaa järjestyslukuna sen kuukauden viimeisen päivämäärän, joka poikkeaa annetun kuukausimäärän verran eteen- tai taaksepäin. +HOUR = TUNNIT ## Muuntaa järjestysluvun tunneiksi. +MINUTE = MINUUTIT ## Muuntaa järjestysluvun minuuteiksi. +MONTH = KUUKAUSI ## Muuntaa järjestysluvun kuukausiksi. +NETWORKDAYS = TYÖPÄIVÄT ## Palauttaa kahden päivämäärän välissä olevien täysien työpäivien määrän. +NOW = NYT ## Palauttaa kuluvan päivämäärän ja ajan järjestysnumeron. +SECOND = SEKUNNIT ## Muuntaa järjestysluvun sekunneiksi. +TIME = AIKA ## Palauttaa annetun kellonajan järjestysluvun. +TIMEVALUE = AIKA_ARVO ## Muuntaa tekstimuodossa olevan kellonajan järjestysluvuksi. +TODAY = TÄMÄ.PÄIVÄ ## Palauttaa kuluvan päivän päivämäärän järjestysluvun. +WEEKDAY = VIIKONPÄIVÄ ## Muuntaa järjestysluvun viikonpäiväksi. +WEEKNUM = VIIKKO.NRO ## Muuntaa järjestysluvun luvuksi, joka ilmaisee viikon järjestysluvun vuoden alusta laskettuna. +WORKDAY = TYÖPÄIVÄ ## Palauttaa järjestysluvun päivämäärälle, joka sijaitsee annettujen työpäivien verran eteen tai taaksepäin. +YEAR = VUOSI ## Muuntaa järjestysluvun vuosiksi. +YEARFRAC = VUOSI.OSA ## Palauttaa määritettyjen päivämäärien (aloituspäivä ja lopetuspäivä) välisen osan vuodesta. + + +## +## Engineering functions Tekniset funktiot +## +BESSELI = BESSELI ## Palauttaa muunnetun Bessel-funktion In(x). +BESSELJ = BESSELJ ## Palauttaa Bessel-funktion Jn(x). +BESSELK = BESSELK ## Palauttaa muunnetun Bessel-funktion Kn(x). +BESSELY = BESSELY ## Palauttaa Bessel-funktion Yn(x). +BIN2DEC = BINDES ## Muuntaa binaariluvun desimaaliluvuksi. +BIN2HEX = BINHEKSA ## Muuntaa binaariluvun heksadesimaaliluvuksi. +BIN2OCT = BINOKT ## Muuntaa binaariluvun oktaaliluvuksi. +COMPLEX = KOMPLEKSI ## Muuntaa reaali- ja imaginaariosien kertoimet kompleksiluvuksi. +CONVERT = MUUNNA ## Muuntaa luvun toisen mittajärjestelmän mukaiseksi. +DEC2BIN = DESBIN ## Muuntaa desimaaliluvun binaariluvuksi. +DEC2HEX = DESHEKSA ## Muuntaa kymmenjärjestelmän luvun heksadesimaaliluvuksi. +DEC2OCT = DESOKT ## Muuntaa kymmenjärjestelmän luvun oktaaliluvuksi. +DELTA = SAMA.ARVO ## Tarkistaa, ovatko kaksi arvoa yhtä suuria. +ERF = VIRHEFUNKTIO ## Palauttaa virhefunktion. +ERFC = VIRHEFUNKTIO.KOMPLEMENTTI ## Palauttaa komplementtivirhefunktion. +GESTEP = RAJA ## Testaa, onko luku suurempi kuin kynnysarvo. +HEX2BIN = HEKSABIN ## Muuntaa heksadesimaaliluvun binaariluvuksi. +HEX2DEC = HEKSADES ## Muuntaa heksadesimaaliluvun desimaaliluvuksi. +HEX2OCT = HEKSAOKT ## Muuntaa heksadesimaaliluvun oktaaliluvuksi. +IMABS = KOMPLEKSI.ITSEISARVO ## Palauttaa kompleksiluvun itseisarvon (moduluksen). +IMAGINARY = KOMPLEKSI.IMAG ## Palauttaa kompleksiluvun imaginaariosan kertoimen. +IMARGUMENT = KOMPLEKSI.ARG ## Palauttaa theeta-argumentin, joka on radiaaneina annettu kulma. +IMCONJUGATE = KOMPLEKSI.KONJ ## Palauttaa kompleksiluvun konjugaattiluvun. +IMCOS = KOMPLEKSI.COS ## Palauttaa kompleksiluvun kosinin. +IMDIV = KOMPLEKSI.OSAM ## Palauttaa kahden kompleksiluvun osamäärän. +IMEXP = KOMPLEKSI.EKSP ## Palauttaa kompleksiluvun eksponentin. +IMLN = KOMPLEKSI.LN ## Palauttaa kompleksiluvun luonnollisen logaritmin. +IMLOG10 = KOMPLEKSI.LOG10 ## Palauttaa kompleksiluvun kymmenkantaisen logaritmin. +IMLOG2 = KOMPLEKSI.LOG2 ## Palauttaa kompleksiluvun kaksikantaisen logaritmin. +IMPOWER = KOMPLEKSI.POT ## Palauttaa kokonaislukupotenssiin korotetun kompleksiluvun. +IMPRODUCT = KOMPLEKSI.TULO ## Palauttaa kompleksilukujen tulon. +IMREAL = KOMPLEKSI.REAALI ## Palauttaa kompleksiluvun reaaliosan kertoimen. +IMSIN = KOMPLEKSI.SIN ## Palauttaa kompleksiluvun sinin. +IMSQRT = KOMPLEKSI.NELIÖJ ## Palauttaa kompleksiluvun neliöjuuren. +IMSUB = KOMPLEKSI.EROTUS ## Palauttaa kahden kompleksiluvun erotuksen. +IMSUM = KOMPLEKSI.SUM ## Palauttaa kompleksilukujen summan. +OCT2BIN = OKTBIN ## Muuntaa oktaaliluvun binaariluvuksi. +OCT2DEC = OKTDES ## Muuntaa oktaaliluvun desimaaliluvuksi. +OCT2HEX = OKTHEKSA ## Muuntaa oktaaliluvun heksadesimaaliluvuksi. + + +## +## Financial functions Rahoitusfunktiot +## +ACCRINT = KERTYNYT.KORKO ## Laskee arvopaperille kertyneen koron, kun korko kertyy säännöllisin väliajoin. +ACCRINTM = KERTYNYT.KORKO.LOPUSSA ## Laskee arvopaperille kertyneen koron, kun korko maksetaan eräpäivänä. +AMORDEGRC = AMORDEGRC ## Laskee kunkin laskentakauden poiston poistokerrointa käyttämällä. +AMORLINC = AMORLINC ## Palauttaa kunkin laskentakauden poiston. +COUPDAYBS = KORKOPÄIVÄT.ALUSTA ## Palauttaa koronmaksukauden aloituspäivän ja tilityspäivän välisen ajanjakson päivien määrän. +COUPDAYS = KORKOPÄIVÄT ## Palauttaa päivien määrän koronmaksukaudelta, johon tilityspäivä kuuluu. +COUPDAYSNC = KORKOPÄIVÄT.SEURAAVA ## Palauttaa tilityspäivän ja seuraavan koronmaksupäivän välisen ajanjakson päivien määrän. +COUPNCD = KORKOMAKSU.SEURAAVA ## Palauttaa tilityspäivän jälkeisen seuraavan koronmaksupäivän. +COUPNUM = KORKOPÄIVÄJAKSOT ## Palauttaa arvopaperin ostopäivän ja erääntymispäivän välisten koronmaksupäivien määrän. +COUPPCD = KORKOPÄIVÄ.EDELLINEN ## Palauttaa tilityspäivää edeltävän koronmaksupäivän. +CUMIPMT = MAKSETTU.KORKO ## Palauttaa kahden jakson välisenä aikana kertyneen koron. +CUMPRINC = MAKSETTU.LYHENNYS ## Palauttaa lainalle kahden jakson välisenä aikana kertyneen lyhennyksen. +DB = DB ## Palauttaa kauden kirjanpidollisen poiston amerikkalaisen DB-menetelmän (Fixed-declining balance) mukaan. +DDB = DDB ## Palauttaa kauden kirjanpidollisen poiston amerikkalaisen DDB-menetelmän (Double-Declining Balance) tai jonkin muun määrittämäsi menetelmän mukaan. +DISC = DISKONTTOKORKO ## Palauttaa arvopaperin diskonttokoron. +DOLLARDE = VALUUTTA.DES ## Muuntaa murtolukuna ilmoitetun valuuttamäärän desimaaliluvuksi. +DOLLARFR = VALUUTTA.MURTO ## Muuntaa desimaalilukuna ilmaistun valuuttamäärän murtoluvuksi. +DURATION = KESTO ## Palauttaa keston arvopaperille, jonka koronmaksu tapahtuu säännöllisesti. +EFFECT = KORKO.EFEKT ## Palauttaa todellisen vuosikoron. +FV = TULEVA.ARVO ## Palauttaa sijoituksen tulevan arvon. +FVSCHEDULE = TULEVA.ARVO.ERIKORKO ## Palauttaa pääoman tulevan arvon, kun pääomalle on kertynyt korkoa vaihtelevasti. +INTRATE = KORKO.ARVOPAPERI ## Palauttaa arvopaperin korkokannan täysin sijoitetulle arvopaperille. +IPMT = IPMT ## Laskee sijoitukselle tai lainalle tiettynä ajanjaksona kertyvän koron. +IRR = SISÄINEN.KORKO ## Laskee sisäisen korkokannan kassavirrasta muodostuvalle sarjalle. +ISPMT = ONMAKSU ## Laskee sijoituksen maksetun koron tietyllä jaksolla. +MDURATION = KESTO.MUUNN ## Palauttaa muunnetun Macauley-keston arvopaperille, jonka oletettu nimellisarvo on 100 euroa. +MIRR = MSISÄINEN ## Palauttaa sisäisen korkokannan, kun positiivisten ja negatiivisten kassavirtojen rahoituskorko on erilainen. +NOMINAL = KORKO.VUOSI ## Palauttaa vuosittaisen nimelliskoron. +NPER = NJAKSO ## Palauttaa sijoituksen jaksojen määrän. +NPV = NNA ## Palauttaa sijoituksen nykyarvon toistuvista kassavirroista muodostuvan sarjan ja diskonttokoron perusteella. +ODDFPRICE = PARITON.ENS.NIMELLISARVO ## Palauttaa arvopaperin hinnan tilanteessa, jossa ensimmäinen jakso on pariton. +ODDFYIELD = PARITON.ENS.TUOTTO ## Palauttaa arvopaperin tuoton tilanteessa, jossa ensimmäinen jakso on pariton. +ODDLPRICE = PARITON.VIIM.NIMELLISARVO ## Palauttaa arvopaperin hinnan tilanteessa, jossa viimeinen jakso on pariton. +ODDLYIELD = PARITON.VIIM.TUOTTO ## Palauttaa arvopaperin tuoton tilanteessa, jossa viimeinen jakso on pariton. +PMT = MAKSU ## Palauttaa annuiteetin kausittaisen maksuerän. +PPMT = PPMT ## Laskee sijoitukselle tai lainalle tiettynä ajanjaksona maksettavan lyhennyksen. +PRICE = HINTA ## Palauttaa hinnan 100 euron nimellisarvoa kohden arvopaperille, jonka korko maksetaan säännöllisin väliajoin. +PRICEDISC = HINTA.DISK ## Palauttaa diskontatun arvopaperin hinnan 100 euron nimellisarvoa kohden. +PRICEMAT = HINTA.LUNASTUS ## Palauttaa hinnan 100 euron nimellisarvoa kohden arvopaperille, jonka korko maksetaan erääntymispäivänä. +PV = NA ## Palauttaa sijoituksen nykyarvon. +RATE = KORKO ## Palauttaa annuiteetin kausittaisen korkokannan. +RECEIVED = SAATU.HINTA ## Palauttaa arvopaperin tuoton erääntymispäivänä kokonaan maksetulle sijoitukselle. +SLN = STP ## Palauttaa sijoituksen tasapoiston yhdeltä jaksolta. +SYD = VUOSIPOISTO ## Palauttaa sijoituksen vuosipoiston annettuna kautena amerikkalaisen SYD-menetelmän (Sum-of-Year's Digits) avulla. +TBILLEQ = OBLIG.TUOTTOPROS ## Palauttaa valtion obligaation tuoton vastaavana joukkovelkakirjan tuottona. +TBILLPRICE = OBLIG.HINTA ## Palauttaa obligaation hinnan 100 euron nimellisarvoa kohden. +TBILLYIELD = OBLIG.TUOTTO ## Palauttaa obligaation tuoton. +VDB = VDB ## Palauttaa annetun kauden tai kauden osan kirjanpidollisen poiston amerikkalaisen DB-menetelmän (Fixed-declining balance) mukaan. +XIRR = SISÄINEN.KORKO.JAKSOTON ## Palauttaa sisäisen korkokannan kassavirtojen sarjoille, jotka eivät välttämättä ole säännöllisiä. +XNPV = NNA.JAKSOTON ## Palauttaa nettonykyarvon kassavirtasarjalle, joka ei välttämättä ole kausittainen. +YIELD = TUOTTO ## Palauttaa tuoton arvopaperille, jonka korko maksetaan säännöllisin väliajoin. +YIELDDISC = TUOTTO.DISK ## Palauttaa diskontatun arvopaperin, kuten obligaation, vuosittaisen tuoton. +YIELDMAT = TUOTTO.ERÄP ## Palauttaa erääntymispäivänään korkoa tuottavan arvopaperin vuosittaisen tuoton. + + +## +## Information functions Erikoisfunktiot +## +CELL = SOLU ## Palauttaa tietoja solun muotoilusta, sijainnista ja sisällöstä. +ERROR.TYPE = VIRHEEN.LAJI ## Palauttaa virhetyyppiä vastaavan luvun. +INFO = KUVAUS ## Palauttaa tietoja nykyisestä käyttöympäristöstä. +ISBLANK = ONTYHJÄ ## Palauttaa arvon TOSI, jos arvo on tyhjä. +ISERR = ONVIRH ## Palauttaa arvon TOSI, jos arvo on mikä tahansa virhearvo paitsi arvo #PUUTTUU!. +ISERROR = ONVIRHE ## Palauttaa arvon TOSI, jos arvo on mikä tahansa virhearvo. +ISEVEN = ONPARILLINEN ## Palauttaa arvon TOSI, jos arvo on parillinen. +ISLOGICAL = ONTOTUUS ## Palauttaa arvon TOSI, jos arvo on mikä tahansa looginen arvo. +ISNA = ONPUUTTUU ## Palauttaa arvon TOSI, jos virhearvo on #PUUTTUU!. +ISNONTEXT = ONEI_TEKSTI ## Palauttaa arvon TOSI, jos arvo ei ole teksti. +ISNUMBER = ONLUKU ## Palauttaa arvon TOSI, jos arvo on luku. +ISODD = ONPARITON ## Palauttaa arvon TOSI, jos arvo on pariton. +ISREF = ONVIITT ## Palauttaa arvon TOSI, jos arvo on viittaus. +ISTEXT = ONTEKSTI ## Palauttaa arvon TOSI, jos arvo on teksti. +N = N ## Palauttaa arvon luvuksi muunnettuna. +NA = PUUTTUU ## Palauttaa virhearvon #PUUTTUU!. +TYPE = TYYPPI ## Palauttaa luvun, joka ilmaisee arvon tietotyypin. + + +## +## Logical functions Loogiset funktiot +## +AND = JA ## Palauttaa arvon TOSI, jos kaikkien argumenttien arvo on TOSI. +FALSE = EPÄTOSI ## Palauttaa totuusarvon EPÄTOSI. +IF = JOS ## Määrittää suoritettavan loogisen testin. +IFERROR = JOSVIRHE ## Palauttaa määrittämäsi arvon, jos kaavan tulos on virhe; muussa tapauksessa palauttaa kaavan tuloksen. +NOT = EI ## Kääntää argumentin loogisen arvon. +OR = TAI ## Palauttaa arvon TOSI, jos minkä tahansa argumentin arvo on TOSI. +TRUE = TOSI ## Palauttaa totuusarvon TOSI. + + +## +## Lookup and reference functions Haku- ja viitefunktiot +## +ADDRESS = OSOITE ## Palauttaa laskentataulukon soluun osoittavan viittauksen tekstinä. +AREAS = ALUEET ## Palauttaa viittauksessa olevien alueiden määrän. +CHOOSE = VALITSE.INDEKSI ## Valitsee arvon arvoluettelosta. +COLUMN = SARAKE ## Palauttaa viittauksen sarakenumeron. +COLUMNS = SARAKKEET ## Palauttaa viittauksessa olevien sarakkeiden määrän. +HLOOKUP = VHAKU ## Suorittaa haun matriisin ylimmältä riviltä ja palauttaa määritetyn solun arvon. +HYPERLINK = HYPERLINKKI ## Luo pikakuvakkeen tai tekstin, joka avaa verkkopalvelimeen, intranetiin tai Internetiin tallennetun tiedoston. +INDEX = INDEKSI ## Valitsee arvon viittauksesta tai matriisista indeksin mukaan. +INDIRECT = EPÄSUORA ## Palauttaa tekstiarvona ilmaistun viittauksen. +LOOKUP = HAKU ## Etsii arvoja vektorista tai matriisista. +MATCH = VASTINE ## Etsii arvoja viittauksesta tai matriisista. +OFFSET = SIIRTYMÄ ## Palauttaa annetun viittauksen siirtymän. +ROW = RIVI ## Palauttaa viittauksen rivinumeron. +ROWS = RIVIT ## Palauttaa viittauksessa olevien rivien määrän. +RTD = RTD ## Noutaa COM-automaatiota (automaatio: Tapa käsitellä sovelluksen objekteja toisesta sovelluksesta tai kehitystyökalusta. Automaatio, jota aiemmin kutsuttiin OLE-automaatioksi, on teollisuusstandardi ja COM-mallin (Component Object Model) ominaisuus.) tukevasta ohjelmasta reaaliaikaisia tietoja. +TRANSPOSE = TRANSPONOI ## Palauttaa matriisin käänteismatriisin. +VLOOKUP = PHAKU ## Suorittaa haun matriisin ensimmäisestä sarakkeesta ja palauttaa rivillä olevan solun arvon. + + +## +## Math and trigonometry functions Matemaattiset ja trigonometriset funktiot +## +ABS = ITSEISARVO ## Palauttaa luvun itseisarvon. +ACOS = ACOS ## Palauttaa luvun arkuskosinin. +ACOSH = ACOSH ## Palauttaa luvun käänteisen hyperbolisen kosinin. +ASIN = ASIN ## Palauttaa luvun arkussinin. +ASINH = ASINH ## Palauttaa luvun käänteisen hyperbolisen sinin. +ATAN = ATAN ## Palauttaa luvun arkustangentin. +ATAN2 = ATAN2 ## Palauttaa arkustangentin x- ja y-koordinaatin perusteella. +ATANH = ATANH ## Palauttaa luvun käänteisen hyperbolisen tangentin. +CEILING = PYÖRISTÄ.KERR.YLÖS ## Pyöristää luvun lähimpään kokonaislukuun tai tarkkuusargumentin lähimpään kerrannaiseen. +COMBIN = KOMBINAATIO ## Palauttaa mahdollisten kombinaatioiden määrän annetulle objektien määrälle. +COS = COS ## Palauttaa luvun kosinin. +COSH = COSH ## Palauttaa luvun hyperbolisen kosinin. +DEGREES = ASTEET ## Muuntaa radiaanit asteiksi. +EVEN = PARILLINEN ## Pyöristää luvun ylöspäin lähimpään parilliseen kokonaislukuun. +EXP = EKSPONENTTI ## Palauttaa e:n korotettuna annetun luvun osoittamaan potenssiin. +FACT = KERTOMA ## Palauttaa luvun kertoman. +FACTDOUBLE = KERTOMA.OSA ## Palauttaa luvun osakertoman. +FLOOR = PYÖRISTÄ.KERR.ALAS ## Pyöristää luvun alaspäin (nollaa kohti). +GCD = SUURIN.YHT.TEKIJÄ ## Palauttaa suurimman yhteisen tekijän. +INT = KOKONAISLUKU ## Pyöristää luvun alaspäin lähimpään kokonaislukuun. +LCM = PIENIN.YHT.JAETTAVA ## Palauttaa pienimmän yhteisen tekijän. +LN = LUONNLOG ## Palauttaa luvun luonnollisen logaritmin. +LOG = LOG ## Laskee luvun logaritmin käyttämällä annettua kantalukua. +LOG10 = LOG10 ## Palauttaa luvun kymmenkantaisen logaritmin. +MDETERM = MDETERM ## Palauttaa matriisin matriisideterminantin. +MINVERSE = MKÄÄNTEINEN ## Palauttaa matriisin käänteismatriisin. +MMULT = MKERRO ## Palauttaa kahden matriisin tulon. +MOD = JAKOJ ## Palauttaa jakolaskun jäännöksen. +MROUND = PYÖRISTÄ.KERR ## Palauttaa luvun pyöristettynä annetun luvun kerrannaiseen. +MULTINOMIAL = MULTINOMI ## Palauttaa lukujoukon multinomin. +ODD = PARITON ## Pyöristää luvun ylöspäin lähimpään parittomaan kokonaislukuun. +PI = PII ## Palauttaa piin arvon. +POWER = POTENSSI ## Palauttaa luvun korotettuna haluttuun potenssiin. +PRODUCT = TULO ## Kertoo annetut argumentit. +QUOTIENT = OSAMÄÄRÄ ## Palauttaa osamäärän kokonaislukuosan. +RADIANS = RADIAANIT ## Muuntaa asteet radiaaneiksi. +RAND = SATUNNAISLUKU ## Palauttaa satunnaisluvun väliltä 0–1. +RANDBETWEEN = SATUNNAISLUKU.VÄLILTÄ ## Palauttaa satunnaisluvun määritettyjen lukujen väliltä. +ROMAN = ROMAN ## Muuntaa arabialaisen numeron tekstimuotoiseksi roomalaiseksi numeroksi. +ROUND = PYÖRISTÄ ## Pyöristää luvun annettuun määrään desimaaleja. +ROUNDDOWN = PYÖRISTÄ.DES.ALAS ## Pyöristää luvun alaspäin (nollaa kohti). +ROUNDUP = PYÖRISTÄ.DES.YLÖS ## Pyöristää luvun ylöspäin (poispäin nollasta). +SERIESSUM = SARJA.SUMMA ## Palauttaa kaavaan perustuvan potenssisarjan arvon. +SIGN = ETUMERKKI ## Palauttaa luvun etumerkin. +SIN = SIN ## Palauttaa annetun kulman sinin. +SINH = SINH ## Palauttaa luvun hyperbolisen sinin. +SQRT = NELIÖJUURI ## Palauttaa positiivisen neliöjuuren. +SQRTPI = NELIÖJUURI.PII ## Palauttaa tulon (luku * pii) neliöjuuren. +SUBTOTAL = VÄLISUMMA ## Palauttaa luettelon tai tietokannan välisumman. +SUM = SUMMA ## Laskee yhteen annetut argumentit. +SUMIF = SUMMA.JOS ## Laskee ehdot täyttävien solujen summan. +SUMIFS = SUMMA.JOS.JOUKKO ## Laskee yhteen solualueen useita ehtoja vastaavat solut. +SUMPRODUCT = TULOJEN.SUMMA ## Palauttaa matriisin toisiaan vastaavien osien tulojen summan. +SUMSQ = NELIÖSUMMA ## Palauttaa argumenttien neliöiden summan. +SUMX2MY2 = NELIÖSUMMIEN.EROTUS ## Palauttaa kahden matriisin toisiaan vastaavien arvojen laskettujen neliösummien erotuksen. +SUMX2PY2 = NELIÖSUMMIEN.SUMMA ## Palauttaa kahden matriisin toisiaan vastaavien arvojen neliösummien summan. +SUMXMY2 = EROTUSTEN.NELIÖSUMMA ## Palauttaa kahden matriisin toisiaan vastaavien arvojen erotusten neliösumman. +TAN = TAN ## Palauttaa luvun tangentin. +TANH = TANH ## Palauttaa luvun hyperbolisen tangentin. +TRUNC = KATKAISE ## Katkaisee luvun kokonaisluvuksi. + + +## +## Statistical functions Tilastolliset funktiot +## +AVEDEV = KESKIPOIKKEAMA ## Palauttaa hajontojen itseisarvojen keskiarvon. +AVERAGE = KESKIARVO ## Palauttaa argumenttien keskiarvon. +AVERAGEA = KESKIARVOA ## Palauttaa argumenttien, mukaan lukien lukujen, tekstin ja loogisten arvojen, keskiarvon. +AVERAGEIF = KESKIARVO.JOS ## Palauttaa alueen niiden solujen keskiarvon (aritmeettisen keskiarvon), jotka täyttävät annetut ehdot. +AVERAGEIFS = KESKIARVO.JOS.JOUKKO ## Palauttaa niiden solujen keskiarvon (aritmeettisen keskiarvon), jotka vastaavat useita ehtoja. +BETADIST = BEETAJAKAUMA ## Palauttaa kumulatiivisen beetajakaumafunktion arvon. +BETAINV = BEETAJAKAUMA.KÄÄNT ## Palauttaa määritetyn beetajakauman käänteisen kumulatiivisen jakaumafunktion arvon. +BINOMDIST = BINOMIJAKAUMA ## Palauttaa yksittäisen termin binomijakaumatodennäköisyyden. +CHIDIST = CHIJAKAUMA ## Palauttaa yksisuuntaisen chi-neliön jakauman todennäköisyyden. +CHIINV = CHIJAKAUMA.KÄÄNT ## Palauttaa yksisuuntaisen chi-neliön jakauman todennäköisyyden käänteisarvon. +CHITEST = CHITESTI ## Palauttaa riippumattomuustestin tuloksen. +CONFIDENCE = LUOTTAMUSVÄLI ## Palauttaa luottamusvälin populaation keskiarvolle. +CORREL = KORRELAATIO ## Palauttaa kahden arvojoukon korrelaatiokertoimen. +COUNT = LASKE ## Laskee argumenttiluettelossa olevien lukujen määrän. +COUNTA = LASKE.A ## Laskee argumenttiluettelossa olevien arvojen määrän. +COUNTBLANK = LASKE.TYHJÄT ## Laskee alueella olevien tyhjien solujen määrän. +COUNTIF = LASKE.JOS ## Laskee alueella olevien sellaisten solujen määrän, joiden sisältö vastaa annettuja ehtoja. +COUNTIFS = LASKE.JOS.JOUKKO ## Laskee alueella olevien sellaisten solujen määrän, joiden sisältö vastaa useita ehtoja. +COVAR = KOVARIANSSI ## Palauttaa kovarianssin, joka on keskiarvo havaintoaineiston kunkin pisteparin poikkeamien tuloista. +CRITBINOM = BINOMIJAKAUMA.KRIT ## Palauttaa pienimmän arvon, jossa binomijakauman kertymäfunktion arvo on pienempi tai yhtä suuri kuin vertailuarvo. +DEVSQ = OIKAISTU.NELIÖSUMMA ## Palauttaa keskipoikkeamien neliösumman. +EXPONDIST = EKSPONENTIAALIJAKAUMA ## Palauttaa eksponentiaalijakauman. +FDIST = FJAKAUMA ## Palauttaa F-todennäköisyysjakauman. +FINV = FJAKAUMA.KÄÄNT ## Palauttaa F-todennäköisyysjakauman käänteisfunktion. +FISHER = FISHER ## Palauttaa Fisher-muunnoksen. +FISHERINV = FISHER.KÄÄNT ## Palauttaa käänteisen Fisher-muunnoksen. +FORECAST = ENNUSTE ## Palauttaa lineaarisen trendin arvon. +FREQUENCY = TAAJUUS ## Palauttaa frekvenssijakautuman pystysuuntaisena matriisina. +FTEST = FTESTI ## Palauttaa F-testin tuloksen. +GAMMADIST = GAMMAJAKAUMA ## Palauttaa gammajakauman. +GAMMAINV = GAMMAJAKAUMA.KÄÄNT ## Palauttaa käänteisen gammajakauman kertymäfunktion. +GAMMALN = GAMMALN ## Palauttaa gammafunktion luonnollisen logaritmin G(x). +GEOMEAN = KESKIARVO.GEOM ## Palauttaa geometrisen keskiarvon. +GROWTH = KASVU ## Palauttaa eksponentiaalisen trendin arvon. +HARMEAN = KESKIARVO.HARM ## Palauttaa harmonisen keskiarvon. +HYPGEOMDIST = HYPERGEOM.JAKAUMA ## Palauttaa hypergeometrisen jakauman. +INTERCEPT = LEIKKAUSPISTE ## Palauttaa lineaarisen regressiosuoran leikkauspisteen. +KURT = KURT ## Palauttaa tietoalueen vinous-arvon eli huipukkuuden. +LARGE = SUURI ## Palauttaa tietojoukon k:nneksi suurimman arvon. +LINEST = LINREGR ## Palauttaa lineaarisen trendin parametrit. +LOGEST = LOGREGR ## Palauttaa eksponentiaalisen trendin parametrit. +LOGINV = LOGNORM.JAKAUMA.KÄÄNT ## Palauttaa lognormeeratun jakauman käänteisfunktion. +LOGNORMDIST = LOGNORM.JAKAUMA ## Palauttaa lognormaalisen jakauman kertymäfunktion. +MAX = MAKS ## Palauttaa suurimman arvon argumenttiluettelosta. +MAXA = MAKSA ## Palauttaa argumenttien, mukaan lukien lukujen, tekstin ja loogisten arvojen, suurimman arvon. +MEDIAN = MEDIAANI ## Palauttaa annettujen lukujen mediaanin. +MIN = MIN ## Palauttaa pienimmän arvon argumenttiluettelosta. +MINA = MINA ## Palauttaa argumenttien, mukaan lukien lukujen, tekstin ja loogisten arvojen, pienimmän arvon. +MODE = MOODI ## Palauttaa tietojoukossa useimmin esiintyvän arvon. +NEGBINOMDIST = BINOMIJAKAUMA.NEG ## Palauttaa negatiivisen binomijakauman. +NORMDIST = NORM.JAKAUMA ## Palauttaa normaalijakauman kertymäfunktion. +NORMINV = NORM.JAKAUMA.KÄÄNT ## Palauttaa käänteisen normaalijakauman kertymäfunktion. +NORMSDIST = NORM.JAKAUMA.NORMIT ## Palauttaa normitetun normaalijakauman kertymäfunktion. +NORMSINV = NORM.JAKAUMA.NORMIT.KÄÄNT ## Palauttaa normitetun normaalijakauman kertymäfunktion käänteisarvon. +PEARSON = PEARSON ## Palauttaa Pearsonin tulomomenttikorrelaatiokertoimen. +PERCENTILE = PROSENTTIPISTE ## Palauttaa alueen arvojen k:nnen prosenttipisteen. +PERCENTRANK = PROSENTTIJÄRJESTYS ## Palauttaa tietojoukon arvon prosentuaalisen järjestysluvun. +PERMUT = PERMUTAATIO ## Palauttaa mahdollisten permutaatioiden määrän annetulle objektien määrälle. +POISSON = POISSON ## Palauttaa Poissonin todennäköisyysjakauman. +PROB = TODENNÄKÖISYYS ## Palauttaa todennäköisyyden sille, että arvot ovat tietyltä väliltä. +QUARTILE = NELJÄNNES ## Palauttaa tietoalueen neljänneksen. +RANK = ARVON.MUKAAN ## Palauttaa luvun paikan lukuarvoluettelossa. +RSQ = PEARSON.NELIÖ ## Palauttaa Pearsonin tulomomenttikorrelaatiokertoimen neliön. +SKEW = JAKAUMAN.VINOUS ## Palauttaa jakauman vinouden. +SLOPE = KULMAKERROIN ## Palauttaa lineaarisen regressiosuoran kulmakertoimen. +SMALL = PIENI ## Palauttaa tietojoukon k:nneksi pienimmän arvon. +STANDARDIZE = NORMITA ## Palauttaa normitetun arvon. +STDEV = KESKIHAJONTA ## Laskee populaation keskihajonnan otoksen perusteella. +STDEVA = KESKIHAJONTAA ## Laskee populaation keskihajonnan otoksen perusteella, mukaan lukien luvut, tekstin ja loogiset arvot. +STDEVP = KESKIHAJONTAP ## Laskee normaalijakautuman koko populaation perusteella. +STDEVPA = KESKIHAJONTAPA ## Laskee populaation keskihajonnan koko populaation perusteella, mukaan lukien luvut, tekstin ja totuusarvot. +STEYX = KESKIVIRHE ## Palauttaa regression kutakin x-arvoa vastaavan ennustetun y-arvon keskivirheen. +TDIST = TJAKAUMA ## Palauttaa t-jakautuman. +TINV = TJAKAUMA.KÄÄNT ## Palauttaa käänteisen t-jakauman. +TREND = SUUNTAUS ## Palauttaa lineaarisen trendin arvoja. +TRIMMEAN = KESKIARVO.TASATTU ## Palauttaa tietojoukon tasatun keskiarvon. +TTEST = TTESTI ## Palauttaa t-testiin liittyvän todennäköisyyden. +VAR = VAR ## Arvioi populaation varianssia otoksen perusteella. +VARA = VARA ## Laskee populaation varianssin otoksen perusteella, mukaan lukien luvut, tekstin ja loogiset arvot. +VARP = VARP ## Laskee varianssin koko populaation perusteella. +VARPA = VARPA ## Laskee populaation varianssin koko populaation perusteella, mukaan lukien luvut, tekstin ja totuusarvot. +WEIBULL = WEIBULL ## Palauttaa Weibullin jakauman. +ZTEST = ZTESTI ## Palauttaa z-testin yksisuuntaisen todennäköisyysarvon. + + +## +## Text functions Tekstifunktiot +## +ASC = ASC ## Muuntaa merkkijonossa olevat englanninkieliset DBCS- tai katakana-merkit SBCS-merkeiksi. +BAHTTEXT = BAHTTEKSTI ## Muuntaa luvun tekstiksi ß (baht) -valuuttamuotoa käyttämällä. +CHAR = MERKKI ## Palauttaa koodin lukua vastaavan merkin. +CLEAN = SIIVOA ## Poistaa tekstistä kaikki tulostumattomat merkit. +CODE = KOODI ## Palauttaa tekstimerkkijonon ensimmäisen merkin numerokoodin. +CONCATENATE = KETJUTA ## Yhdistää useat merkkijonot yhdeksi merkkijonoksi. +DOLLAR = VALUUTTA ## Muuntaa luvun tekstiksi $ (dollari) -valuuttamuotoa käyttämällä. +EXACT = VERTAA ## Tarkistaa, ovatko kaksi tekstiarvoa samanlaiset. +FIND = ETSI ## Etsii tekstiarvon toisen tekstin sisältä (tunnistaa isot ja pienet kirjaimet). +FINDB = ETSIB ## Etsii tekstiarvon toisen tekstin sisältä (tunnistaa isot ja pienet kirjaimet). +FIXED = KIINTEÄ ## Muotoilee luvun tekstiksi, jossa on kiinteä määrä desimaaleja. +JIS = JIS ## Muuntaa merkkijonossa olevat englanninkieliset SBCS- tai katakana-merkit DBCS-merkeiksi. +LEFT = VASEN ## Palauttaa tekstiarvon vasemmanpuoliset merkit. +LEFTB = VASENB ## Palauttaa tekstiarvon vasemmanpuoliset merkit. +LEN = PITUUS ## Palauttaa tekstimerkkijonon merkkien määrän. +LENB = PITUUSB ## Palauttaa tekstimerkkijonon merkkien määrän. +LOWER = PIENET ## Muuntaa tekstin pieniksi kirjaimiksi. +MID = POIMI.TEKSTI ## Palauttaa määritetyn määrän merkkejä merkkijonosta alkaen annetusta kohdasta. +MIDB = POIMI.TEKSTIB ## Palauttaa määritetyn määrän merkkejä merkkijonosta alkaen annetusta kohdasta. +PHONETIC = FONEETTINEN ## Hakee foneettiset (furigana) merkit merkkijonosta. +PROPER = ERISNIMI ## Muuttaa merkkijonon kunkin sanan ensimmäisen kirjaimen isoksi. +REPLACE = KORVAA ## Korvaa tekstissä olevat merkit. +REPLACEB = KORVAAB ## Korvaa tekstissä olevat merkit. +REPT = TOISTA ## Toistaa tekstin annetun määrän kertoja. +RIGHT = OIKEA ## Palauttaa tekstiarvon oikeanpuoliset merkit. +RIGHTB = OIKEAB ## Palauttaa tekstiarvon oikeanpuoliset merkit. +SEARCH = KÄY.LÄPI ## Etsii tekstiarvon toisen tekstin sisältä (isot ja pienet kirjaimet tulkitaan samoiksi merkeiksi). +SEARCHB = KÄY.LÄPIB ## Etsii tekstiarvon toisen tekstin sisältä (isot ja pienet kirjaimet tulkitaan samoiksi merkeiksi). +SUBSTITUTE = VAIHDA ## Korvaa merkkijonossa olevan tekstin toisella. +T = T ## Muuntaa argumentit tekstiksi. +TEXT = TEKSTI ## Muotoilee luvun ja muuntaa sen tekstiksi. +TRIM = POISTA.VÄLIT ## Poistaa välilyönnit tekstistä. +UPPER = ISOT ## Muuntaa tekstin isoiksi kirjaimiksi. +VALUE = ARVO ## Muuntaa tekstiargumentin luvuksi. diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fr/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fr/config new file mode 100755 index 0000000..36d731a --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fr/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = € + + +## +## Excel Error Codes (For future use) +## +NULL = #NUL! +DIV0 = #DIV/0! +VALUE = #VALEUR! +REF = #REF! +NAME = #NOM? +NUM = #NOMBRE! +NA = #N/A diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fr/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fr/functions new file mode 100755 index 0000000..31c787a --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/fr/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions Fonctions de complément et d’automatisation +## +GETPIVOTDATA = LIREDONNEESTABCROISDYNAMIQUE ## Renvoie les données stockées dans un rapport de tableau croisé dynamique. + + +## +## Cube functions Fonctions Cube +## +CUBEKPIMEMBER = MEMBREKPICUBE ## Renvoie un nom, une propriété et une mesure d’indicateur de performance clé et affiche le nom et la propriété dans la cellule. Un indicateur de performance clé est une mesure quantifiable, telle que la marge bénéficiaire brute mensuelle ou la rotation trimestrielle du personnel, utilisée pour évaluer les performances d’une entreprise. +CUBEMEMBER = MEMBRECUBE ## Renvoie un membre ou un uplet dans une hiérarchie de cubes. Utilisez cette fonction pour valider l’existence du membre ou de l’uplet dans le cube. +CUBEMEMBERPROPERTY = PROPRIETEMEMBRECUBE ## Renvoie la valeur d’une propriété de membre du cube. Utilisez cette fonction pour valider l’existence d’un nom de membre dans le cube et pour renvoyer la propriété spécifiée pour ce membre. +CUBERANKEDMEMBER = RANGMEMBRECUBE ## Renvoie le nième membre ou le membre placé à un certain rang dans un ensemble. Utilisez cette fonction pour renvoyer un ou plusieurs éléments d’un ensemble, tels que les meilleurs vendeurs ou les 10 meilleurs étudiants. +CUBESET = JEUCUBE ## Définit un ensemble calculé de membres ou d’uplets en envoyant une expression définie au cube sur le serveur qui crée l’ensemble et le renvoie à Microsoft Office Excel. +CUBESETCOUNT = NBJEUCUBE ## Renvoie le nombre d’éléments dans un jeu. +CUBEVALUE = VALEURCUBE ## Renvoie une valeur d’agrégation issue d’un cube. + + +## +## Database functions Fonctions de base de données +## +DAVERAGE = BDMOYENNE ## Renvoie la moyenne des entrées de base de données sélectionnées. +DCOUNT = BCOMPTE ## Compte le nombre de cellules d’une base de données qui contiennent des nombres. +DCOUNTA = BDNBVAL ## Compte les cellules non vides d’une base de données. +DGET = BDLIRE ## Extrait d’une base de données un enregistrement unique répondant aux critères spécifiés. +DMAX = BDMAX ## Renvoie la valeur maximale des entrées de base de données sélectionnées. +DMIN = BDMIN ## Renvoie la valeur minimale des entrées de base de données sélectionnées. +DPRODUCT = BDPRODUIT ## Multiplie les valeurs d’un champ particulier des enregistrements d’une base de données, qui répondent aux critères spécifiés. +DSTDEV = BDECARTYPE ## Calcule l’écart type pour un échantillon d’entrées de base de données sélectionnées. +DSTDEVP = BDECARTYPEP ## Calcule l’écart type pour l’ensemble d’une population d’entrées de base de données sélectionnées. +DSUM = BDSOMME ## Ajoute les nombres dans la colonne de champ des enregistrements de la base de données, qui répondent aux critères. +DVAR = BDVAR ## Calcule la variance pour un échantillon d’entrées de base de données sélectionnées. +DVARP = BDVARP ## Calcule la variance pour l’ensemble d’une population d’entrées de base de données sélectionnées. + + +## +## Date and time functions Fonctions de date et d’heure +## +DATE = DATE ## Renvoie le numéro de série d’une date précise. +DATEVALUE = DATEVAL ## Convertit une date représentée sous forme de texte en numéro de série. +DAY = JOUR ## Convertit un numéro de série en jour du mois. +DAYS360 = JOURS360 ## Calcule le nombre de jours qui séparent deux dates sur la base d’une année de 360 jours. +EDATE = MOIS.DECALER ## Renvoie le numéro séquentiel de la date qui représente une date spécifiée (l’argument date_départ), corrigée en plus ou en moins du nombre de mois indiqué. +EOMONTH = FIN.MOIS ## Renvoie le numéro séquentiel de la date du dernier jour du mois précédant ou suivant la date_départ du nombre de mois indiqué. +HOUR = HEURE ## Convertit un numéro de série en heure. +MINUTE = MINUTE ## Convertit un numéro de série en minute. +MONTH = MOIS ## Convertit un numéro de série en mois. +NETWORKDAYS = NB.JOURS.OUVRES ## Renvoie le nombre de jours ouvrés entiers compris entre deux dates. +NOW = MAINTENANT ## Renvoie le numéro de série de la date et de l’heure du jour. +SECOND = SECONDE ## Convertit un numéro de série en seconde. +TIME = TEMPS ## Renvoie le numéro de série d’une heure précise. +TIMEVALUE = TEMPSVAL ## Convertit une date représentée sous forme de texte en numéro de série. +TODAY = AUJOURDHUI ## Renvoie le numéro de série de la date du jour. +WEEKDAY = JOURSEM ## Convertit un numéro de série en jour de la semaine. +WEEKNUM = NO.SEMAINE ## Convertit un numéro de série en un numéro représentant l’ordre de la semaine dans l’année. +WORKDAY = SERIE.JOUR.OUVRE ## Renvoie le numéro de série de la date avant ou après le nombre de jours ouvrés spécifiés. +YEAR = ANNEE ## Convertit un numéro de série en année. +YEARFRAC = FRACTION.ANNEE ## Renvoie la fraction de l’année représentant le nombre de jours entre la date de début et la date de fin. + + +## +## Engineering functions Fonctions d’ingénierie +## +BESSELI = BESSELI ## Renvoie la fonction Bessel modifiée In(x). +BESSELJ = BESSELJ ## Renvoie la fonction Bessel Jn(x). +BESSELK = BESSELK ## Renvoie la fonction Bessel modifiée Kn(x). +BESSELY = BESSELY ## Renvoie la fonction Bessel Yn(x). +BIN2DEC = BINDEC ## Convertit un nombre binaire en nombre décimal. +BIN2HEX = BINHEX ## Convertit un nombre binaire en nombre hexadécimal. +BIN2OCT = BINOCT ## Convertit un nombre binaire en nombre octal. +COMPLEX = COMPLEXE ## Convertit des coefficients réel et imaginaire en un nombre complexe. +CONVERT = CONVERT ## Convertit un nombre d’une unité de mesure à une autre. +DEC2BIN = DECBIN ## Convertit un nombre décimal en nombre binaire. +DEC2HEX = DECHEX ## Convertit un nombre décimal en nombre hexadécimal. +DEC2OCT = DECOCT ## Convertit un nombre décimal en nombre octal. +DELTA = DELTA ## Teste l’égalité de deux nombres. +ERF = ERF ## Renvoie la valeur de la fonction d’erreur. +ERFC = ERFC ## Renvoie la valeur de la fonction d’erreur complémentaire. +GESTEP = SUP.SEUIL ## Teste si un nombre est supérieur à une valeur de seuil. +HEX2BIN = HEXBIN ## Convertit un nombre hexadécimal en nombre binaire. +HEX2DEC = HEXDEC ## Convertit un nombre hexadécimal en nombre décimal. +HEX2OCT = HEXOCT ## Convertit un nombre hexadécimal en nombre octal. +IMABS = COMPLEXE.MODULE ## Renvoie la valeur absolue (module) d’un nombre complexe. +IMAGINARY = COMPLEXE.IMAGINAIRE ## Renvoie le coefficient imaginaire d’un nombre complexe. +IMARGUMENT = COMPLEXE.ARGUMENT ## Renvoie l’argument thêta, un angle exprimé en radians. +IMCONJUGATE = COMPLEXE.CONJUGUE ## Renvoie le nombre complexe conjugué d’un nombre complexe. +IMCOS = IMCOS ## Renvoie le cosinus d’un nombre complexe. +IMDIV = COMPLEXE.DIV ## Renvoie le quotient de deux nombres complexes. +IMEXP = COMPLEXE.EXP ## Renvoie la fonction exponentielle d’un nombre complexe. +IMLN = COMPLEXE.LN ## Renvoie le logarithme népérien d’un nombre complexe. +IMLOG10 = COMPLEXE.LOG10 ## Calcule le logarithme en base 10 d’un nombre complexe. +IMLOG2 = COMPLEXE.LOG2 ## Calcule le logarithme en base 2 d’un nombre complexe. +IMPOWER = COMPLEXE.PUISSANCE ## Renvoie un nombre complexe élevé à une puissance entière. +IMPRODUCT = COMPLEXE.PRODUIT ## Renvoie le produit de plusieurs nombres complexes. +IMREAL = COMPLEXE.REEL ## Renvoie le coefficient réel d’un nombre complexe. +IMSIN = COMPLEXE.SIN ## Renvoie le sinus d’un nombre complexe. +IMSQRT = COMPLEXE.RACINE ## Renvoie la racine carrée d’un nombre complexe. +IMSUB = COMPLEXE.DIFFERENCE ## Renvoie la différence entre deux nombres complexes. +IMSUM = COMPLEXE.SOMME ## Renvoie la somme de plusieurs nombres complexes. +OCT2BIN = OCTBIN ## Convertit un nombre octal en nombre binaire. +OCT2DEC = OCTDEC ## Convertit un nombre octal en nombre décimal. +OCT2HEX = OCTHEX ## Convertit un nombre octal en nombre hexadécimal. + + +## +## Financial functions Fonctions financières +## +ACCRINT = INTERET.ACC ## Renvoie l’intérêt couru non échu d’un titre dont l’intérêt est perçu périodiquement. +ACCRINTM = INTERET.ACC.MAT ## Renvoie l’intérêt couru non échu d’un titre dont l’intérêt est perçu à l’échéance. +AMORDEGRC = AMORDEGRC ## Renvoie l’amortissement correspondant à chaque période comptable en utilisant un coefficient d’amortissement. +AMORLINC = AMORLINC ## Renvoie l’amortissement d’un bien à la fin d’une période fiscale donnée. +COUPDAYBS = NB.JOURS.COUPON.PREC ## Renvoie le nombre de jours entre le début de la période de coupon et la date de liquidation. +COUPDAYS = NB.JOURS.COUPONS ## Renvoie le nombre de jours pour la période du coupon contenant la date de liquidation. +COUPDAYSNC = NB.JOURS.COUPON.SUIV ## Renvoie le nombre de jours entre la date de liquidation et la date du coupon suivant la date de liquidation. +COUPNCD = DATE.COUPON.SUIV ## Renvoie la première date de coupon ultérieure à la date de règlement. +COUPNUM = NB.COUPONS ## Renvoie le nombre de coupons dus entre la date de règlement et la date d’échéance. +COUPPCD = DATE.COUPON.PREC ## Renvoie la date de coupon précédant la date de règlement. +CUMIPMT = CUMUL.INTER ## Renvoie l’intérêt cumulé payé sur un emprunt entre deux périodes. +CUMPRINC = CUMUL.PRINCPER ## Renvoie le montant cumulé des remboursements du capital d’un emprunt effectués entre deux périodes. +DB = DB ## Renvoie l’amortissement d’un bien pour une période spécifiée en utilisant la méthode de l’amortissement dégressif à taux fixe. +DDB = DDB ## Renvoie l’amortissement d’un bien pour toute période spécifiée, en utilisant la méthode de l’amortissement dégressif à taux double ou selon un coefficient à spécifier. +DISC = TAUX.ESCOMPTE ## Calcule le taux d’escompte d’une transaction. +DOLLARDE = PRIX.DEC ## Convertit un prix en euros, exprimé sous forme de fraction, en un prix en euros exprimé sous forme de nombre décimal. +DOLLARFR = PRIX.FRAC ## Convertit un prix en euros, exprimé sous forme de nombre décimal, en un prix en euros exprimé sous forme de fraction. +DURATION = DUREE ## Renvoie la durée, en années, d’un titre dont l’intérêt est perçu périodiquement. +EFFECT = TAUX.EFFECTIF ## Renvoie le taux d’intérêt annuel effectif. +FV = VC ## Renvoie la valeur future d’un investissement. +FVSCHEDULE = VC.PAIEMENTS ## Calcule la valeur future d’un investissement en appliquant une série de taux d’intérêt composites. +INTRATE = TAUX.INTERET ## Affiche le taux d’intérêt d’un titre totalement investi. +IPMT = INTPER ## Calcule le montant des intérêts d’un investissement pour une période donnée. +IRR = TRI ## Calcule le taux de rentabilité interne d’un investissement pour une succession de trésoreries. +ISPMT = ISPMT ## Calcule le montant des intérêts d’un investissement pour une période donnée. +MDURATION = DUREE.MODIFIEE ## Renvoie la durée de Macauley modifiée pour un titre ayant une valeur nominale hypothétique de 100_euros. +MIRR = TRIM ## Calcule le taux de rentabilité interne lorsque les paiements positifs et négatifs sont financés à des taux différents. +NOMINAL = TAUX.NOMINAL ## Calcule le taux d’intérêt nominal annuel. +NPER = NPM ## Renvoie le nombre de versements nécessaires pour rembourser un emprunt. +NPV = VAN ## Calcule la valeur actuelle nette d’un investissement basé sur une série de décaissements et un taux d’escompte. +ODDFPRICE = PRIX.PCOUPON.IRREG ## Renvoie le prix par tranche de valeur nominale de 100 euros d’un titre dont la première période de coupon est irrégulière. +ODDFYIELD = REND.PCOUPON.IRREG ## Renvoie le taux de rendement d’un titre dont la première période de coupon est irrégulière. +ODDLPRICE = PRIX.DCOUPON.IRREG ## Renvoie le prix par tranche de valeur nominale de 100 euros d’un titre dont la première période de coupon est irrégulière. +ODDLYIELD = REND.DCOUPON.IRREG ## Renvoie le taux de rendement d’un titre dont la dernière période de coupon est irrégulière. +PMT = VPM ## Calcule le paiement périodique d’un investissement donné. +PPMT = PRINCPER ## Calcule, pour une période donnée, la part de remboursement du principal d’un investissement. +PRICE = PRIX.TITRE ## Renvoie le prix d’un titre rapportant des intérêts périodiques, pour une valeur nominale de 100 euros. +PRICEDISC = VALEUR.ENCAISSEMENT ## Renvoie la valeur d’encaissement d’un escompte commercial, pour une valeur nominale de 100 euros. +PRICEMAT = PRIX.TITRE.ECHEANCE ## Renvoie le prix d’un titre dont la valeur nominale est 100 euros et qui rapporte des intérêts à l’échéance. +PV = PV ## Calcule la valeur actuelle d’un investissement. +RATE = TAUX ## Calcule le taux d’intérêt par période pour une annuité. +RECEIVED = VALEUR.NOMINALE ## Renvoie la valeur nominale à échéance d’un effet de commerce. +SLN = AMORLIN ## Calcule l’amortissement linéaire d’un bien pour une période donnée. +SYD = SYD ## Calcule l’amortissement d’un bien pour une période donnée sur la base de la méthode américaine Sum-of-Years Digits (amortissement dégressif à taux décroissant appliqué à une valeur constante). +TBILLEQ = TAUX.ESCOMPTE.R ## Renvoie le taux d’escompte rationnel d’un bon du Trésor. +TBILLPRICE = PRIX.BON.TRESOR ## Renvoie le prix d’un bon du Trésor d’une valeur nominale de 100 euros. +TBILLYIELD = RENDEMENT.BON.TRESOR ## Calcule le taux de rendement d’un bon du Trésor. +VDB = VDB ## Renvoie l’amortissement d’un bien pour une période spécifiée ou partielle en utilisant une méthode de l’amortissement dégressif à taux fixe. +XIRR = TRI.PAIEMENTS ## Calcule le taux de rentabilité interne d’un ensemble de paiements non périodiques. +XNPV = VAN.PAIEMENTS ## Renvoie la valeur actuelle nette d’un ensemble de paiements non périodiques. +YIELD = RENDEMENT.TITRE ## Calcule le rendement d’un titre rapportant des intérêts périodiquement. +YIELDDISC = RENDEMENT.SIMPLE ## Calcule le taux de rendement d’un emprunt à intérêt simple (par exemple, un bon du Trésor). +YIELDMAT = RENDEMENT.TITRE.ECHEANCE ## Renvoie le rendement annuel d’un titre qui rapporte des intérêts à l’échéance. + + +## +## Information functions Fonctions d’information +## +CELL = CELLULE ## Renvoie des informations sur la mise en forme, l’emplacement et le contenu d’une cellule. +ERROR.TYPE = TYPE.ERREUR ## Renvoie un nombre correspondant à un type d’erreur. +INFO = INFORMATIONS ## Renvoie des informations sur l’environnement d’exploitation actuel. +ISBLANK = ESTVIDE ## Renvoie VRAI si l’argument valeur est vide. +ISERR = ESTERR ## Renvoie VRAI si l’argument valeur fait référence à une valeur d’erreur, sauf #N/A. +ISERROR = ESTERREUR ## Renvoie VRAI si l’argument valeur fait référence à une valeur d’erreur. +ISEVEN = EST.PAIR ## Renvoie VRAI si le chiffre est pair. +ISLOGICAL = ESTLOGIQUE ## Renvoie VRAI si l’argument valeur fait référence à une valeur logique. +ISNA = ESTNA ## Renvoie VRAI si l’argument valeur fait référence à la valeur d’erreur #N/A. +ISNONTEXT = ESTNONTEXTE ## Renvoie VRAI si l’argument valeur ne se présente pas sous forme de texte. +ISNUMBER = ESTNUM ## Renvoie VRAI si l’argument valeur représente un nombre. +ISODD = EST.IMPAIR ## Renvoie VRAI si le chiffre est impair. +ISREF = ESTREF ## Renvoie VRAI si l’argument valeur est une référence. +ISTEXT = ESTTEXTE ## Renvoie VRAI si l’argument valeur se présente sous forme de texte. +N = N ## Renvoie une valeur convertie en nombre. +NA = NA ## Renvoie la valeur d’erreur #N/A. +TYPE = TYPE ## Renvoie un nombre indiquant le type de données d’une valeur. + + +## +## Logical functions Fonctions logiques +## +AND = ET ## Renvoie VRAI si tous ses arguments sont VRAI. +FALSE = FAUX ## Renvoie la valeur logique FAUX. +IF = SI ## Spécifie un test logique à effectuer. +IFERROR = SIERREUR ## Renvoie une valeur que vous spécifiez si une formule génère une erreur ; sinon, elle renvoie le résultat de la formule. +NOT = NON ## Inverse la logique de cet argument. +OR = OU ## Renvoie VRAI si un des arguments est VRAI. +TRUE = VRAI ## Renvoie la valeur logique VRAI. + + +## +## Lookup and reference functions Fonctions de recherche et de référence +## +ADDRESS = ADRESSE ## Renvoie une référence sous forme de texte à une seule cellule d’une feuille de calcul. +AREAS = ZONES ## Renvoie le nombre de zones dans une référence. +CHOOSE = CHOISIR ## Choisit une valeur dans une liste. +COLUMN = COLONNE ## Renvoie le numéro de colonne d’une référence. +COLUMNS = COLONNES ## Renvoie le nombre de colonnes dans une référence. +HLOOKUP = RECHERCHEH ## Effectue une recherche dans la première ligne d’une matrice et renvoie la valeur de la cellule indiquée. +HYPERLINK = LIEN_HYPERTEXTE ## Crée un raccourci ou un renvoi qui ouvre un document stocké sur un serveur réseau, sur un réseau Intranet ou sur Internet. +INDEX = INDEX ## Utilise un index pour choisir une valeur provenant d’une référence ou d’une matrice. +INDIRECT = INDIRECT ## Renvoie une référence indiquée par une valeur de texte. +LOOKUP = RECHERCHE ## Recherche des valeurs dans un vecteur ou une matrice. +MATCH = EQUIV ## Recherche des valeurs dans une référence ou une matrice. +OFFSET = DECALER ## Renvoie une référence décalée par rapport à une référence donnée. +ROW = LIGNE ## Renvoie le numéro de ligne d’une référence. +ROWS = LIGNES ## Renvoie le nombre de lignes dans une référence. +RTD = RTD ## Extrait les données en temps réel à partir d’un programme prenant en charge l’automation COM (Automation : utilisation des objets d'une application à partir d'une autre application ou d'un autre outil de développement. Autrefois appelée OLE Automation, Automation est une norme industrielle et une fonctionnalité du modèle d'objet COM (Component Object Model).). +TRANSPOSE = TRANSPOSE ## Renvoie la transposition d’une matrice. +VLOOKUP = RECHERCHEV ## Effectue une recherche dans la première colonne d’une matrice et se déplace sur la ligne pour renvoyer la valeur d’une cellule. + + +## +## Math and trigonometry functions Fonctions mathématiques et trigonométriques +## +ABS = ABS ## Renvoie la valeur absolue d’un nombre. +ACOS = ACOS ## Renvoie l’arccosinus d’un nombre. +ACOSH = ACOSH ## Renvoie le cosinus hyperbolique inverse d’un nombre. +ASIN = ASIN ## Renvoie l’arcsinus d’un nombre. +ASINH = ASINH ## Renvoie le sinus hyperbolique inverse d’un nombre. +ATAN = ATAN ## Renvoie l’arctangente d’un nombre. +ATAN2 = ATAN2 ## Renvoie l’arctangente des coordonnées x et y. +ATANH = ATANH ## Renvoie la tangente hyperbolique inverse d’un nombre. +CEILING = PLAFOND ## Arrondit un nombre au nombre entier le plus proche ou au multiple le plus proche de l’argument précision en s’éloignant de zéro. +COMBIN = COMBIN ## Renvoie le nombre de combinaisons que l’on peut former avec un nombre donné d’objets. +COS = COS ## Renvoie le cosinus d’un nombre. +COSH = COSH ## Renvoie le cosinus hyperbolique d’un nombre. +DEGREES = DEGRES ## Convertit des radians en degrés. +EVEN = PAIR ## Arrondit un nombre au nombre entier pair le plus proche en s’éloignant de zéro. +EXP = EXP ## Renvoie e élevé à la puissance d’un nombre donné. +FACT = FACT ## Renvoie la factorielle d’un nombre. +FACTDOUBLE = FACTDOUBLE ## Renvoie la factorielle double d’un nombre. +FLOOR = PLANCHER ## Arrondit un nombre en tendant vers 0 (zéro). +GCD = PGCD ## Renvoie le plus grand commun diviseur. +INT = ENT ## Arrondit un nombre à l’entier immédiatement inférieur. +LCM = PPCM ## Renvoie le plus petit commun multiple. +LN = LN ## Renvoie le logarithme népérien d’un nombre. +LOG = LOG ## Renvoie le logarithme d’un nombre dans la base spécifiée. +LOG10 = LOG10 ## Calcule le logarithme en base 10 d’un nombre. +MDETERM = DETERMAT ## Renvoie le déterminant d’une matrice. +MINVERSE = INVERSEMAT ## Renvoie la matrice inverse d’une matrice. +MMULT = PRODUITMAT ## Renvoie le produit de deux matrices. +MOD = MOD ## Renvoie le reste d’une division. +MROUND = ARRONDI.AU.MULTIPLE ## Donne l’arrondi d’un nombre au multiple spécifié. +MULTINOMIAL = MULTINOMIALE ## Calcule la multinomiale d’un ensemble de nombres. +ODD = IMPAIR ## Renvoie le nombre, arrondi à la valeur du nombre entier impair le plus proche en s’éloignant de zéro. +PI = PI ## Renvoie la valeur de pi. +POWER = PUISSANCE ## Renvoie la valeur du nombre élevé à une puissance. +PRODUCT = PRODUIT ## Multiplie ses arguments. +QUOTIENT = QUOTIENT ## Renvoie la partie entière du résultat d’une division. +RADIANS = RADIANS ## Convertit des degrés en radians. +RAND = ALEA ## Renvoie un nombre aléatoire compris entre 0 et 1. +RANDBETWEEN = ALEA.ENTRE.BORNES ## Renvoie un nombre aléatoire entre les nombres que vous spécifiez. +ROMAN = ROMAIN ## Convertit des chiffres arabes en chiffres romains, sous forme de texte. +ROUND = ARRONDI ## Arrondit un nombre au nombre de chiffres indiqué. +ROUNDDOWN = ARRONDI.INF ## Arrondit un nombre en tendant vers 0 (zéro). +ROUNDUP = ARRONDI.SUP ## Arrondit un nombre à l’entier supérieur, en s’éloignant de zéro. +SERIESSUM = SOMME.SERIES ## Renvoie la somme d’une série géométrique en s’appuyant sur la formule suivante : +SIGN = SIGNE ## Renvoie le signe d’un nombre. +SIN = SIN ## Renvoie le sinus d’un angle donné. +SINH = SINH ## Renvoie le sinus hyperbolique d’un nombre. +SQRT = RACINE ## Renvoie la racine carrée d’un nombre. +SQRTPI = RACINE.PI ## Renvoie la racine carrée de (nombre * pi). +SUBTOTAL = SOUS.TOTAL ## Renvoie un sous-total dans une liste ou une base de données. +SUM = SOMME ## Calcule la somme de ses arguments. +SUMIF = SOMME.SI ## Additionne les cellules spécifiées si elles répondent à un critère donné. +SUMIFS = SOMME.SI.ENS ## Ajoute les cellules d’une plage qui répondent à plusieurs critères. +SUMPRODUCT = SOMMEPROD ## Multiplie les valeurs correspondantes des matrices spécifiées et calcule la somme de ces produits. +SUMSQ = SOMME.CARRES ## Renvoie la somme des carrés des arguments. +SUMX2MY2 = SOMME.X2MY2 ## Renvoie la somme de la différence des carrés des valeurs correspondantes de deux matrices. +SUMX2PY2 = SOMME.X2PY2 ## Renvoie la somme de la somme des carrés des valeurs correspondantes de deux matrices. +SUMXMY2 = SOMME.XMY2 ## Renvoie la somme des carrés des différences entre les valeurs correspondantes de deux matrices. +TAN = TAN ## Renvoie la tangente d’un nombre. +TANH = TANH ## Renvoie la tangente hyperbolique d’un nombre. +TRUNC = TRONQUE ## Renvoie la partie entière d’un nombre. + + +## +## Statistical functions Fonctions statistiques +## +AVEDEV = ECART.MOYEN ## Renvoie la moyenne des écarts absolus observés dans la moyenne des points de données. +AVERAGE = MOYENNE ## Renvoie la moyenne de ses arguments. +AVERAGEA = AVERAGEA ## Renvoie la moyenne de ses arguments, nombres, texte et valeurs logiques inclus. +AVERAGEIF = MOYENNE.SI ## Renvoie la moyenne (arithmétique) de toutes les cellules d’une plage qui répondent à des critères donnés. +AVERAGEIFS = MOYENNE.SI.ENS ## Renvoie la moyenne (arithmétique) de toutes les cellules qui répondent à plusieurs critères. +BETADIST = LOI.BETA ## Renvoie la fonction de distribution cumulée. +BETAINV = BETA.INVERSE ## Renvoie l’inverse de la fonction de distribution cumulée pour une distribution bêta spécifiée. +BINOMDIST = LOI.BINOMIALE ## Renvoie la probabilité d’une variable aléatoire discrète suivant la loi binomiale. +CHIDIST = LOI.KHIDEUX ## Renvoie la probabilité unilatérale de la distribution khi-deux. +CHIINV = KHIDEUX.INVERSE ## Renvoie l’inverse de la probabilité unilatérale de la distribution khi-deux. +CHITEST = TEST.KHIDEUX ## Renvoie le test d’indépendance. +CONFIDENCE = INTERVALLE.CONFIANCE ## Renvoie l’intervalle de confiance pour une moyenne de population. +CORREL = COEFFICIENT.CORRELATION ## Renvoie le coefficient de corrélation entre deux séries de données. +COUNT = NB ## Détermine les nombres compris dans la liste des arguments. +COUNTA = NBVAL ## Détermine le nombre de valeurs comprises dans la liste des arguments. +COUNTBLANK = NB.VIDE ## Compte le nombre de cellules vides dans une plage. +COUNTIF = NB.SI ## Compte le nombre de cellules qui répondent à un critère donné dans une plage. +COUNTIFS = NB.SI.ENS ## Compte le nombre de cellules à l’intérieur d’une plage qui répondent à plusieurs critères. +COVAR = COVARIANCE ## Renvoie la covariance, moyenne des produits des écarts pour chaque série d’observations. +CRITBINOM = CRITERE.LOI.BINOMIALE ## Renvoie la plus petite valeur pour laquelle la distribution binomiale cumulée est inférieure ou égale à une valeur de critère. +DEVSQ = SOMME.CARRES.ECARTS ## Renvoie la somme des carrés des écarts. +EXPONDIST = LOI.EXPONENTIELLE ## Renvoie la distribution exponentielle. +FDIST = LOI.F ## Renvoie la distribution de probabilité F. +FINV = INVERSE.LOI.F ## Renvoie l’inverse de la distribution de probabilité F. +FISHER = FISHER ## Renvoie la transformation de Fisher. +FISHERINV = FISHER.INVERSE ## Renvoie l’inverse de la transformation de Fisher. +FORECAST = PREVISION ## Calcule une valeur par rapport à une tendance linéaire. +FREQUENCY = FREQUENCE ## Calcule la fréquence d’apparition des valeurs dans une plage de valeurs, puis renvoie des nombres sous forme de matrice verticale. +FTEST = TEST.F ## Renvoie le résultat d’un test F. +GAMMADIST = LOI.GAMMA ## Renvoie la probabilité d’une variable aléatoire suivant une loi Gamma. +GAMMAINV = LOI.GAMMA.INVERSE ## Renvoie, pour une probabilité donnée, la valeur d’une variable aléatoire suivant une loi Gamma. +GAMMALN = LNGAMMA ## Renvoie le logarithme népérien de la fonction Gamma, G(x) +GEOMEAN = MOYENNE.GEOMETRIQUE ## Renvoie la moyenne géométrique. +GROWTH = CROISSANCE ## Calcule des valeurs par rapport à une tendance exponentielle. +HARMEAN = MOYENNE.HARMONIQUE ## Renvoie la moyenne harmonique. +HYPGEOMDIST = LOI.HYPERGEOMETRIQUE ## Renvoie la probabilité d’une variable aléatoire discrète suivant une loi hypergéométrique. +INTERCEPT = ORDONNEE.ORIGINE ## Renvoie l’ordonnée à l’origine d’une droite de régression linéaire. +KURT = KURTOSIS ## Renvoie le kurtosis d’une série de données. +LARGE = GRANDE.VALEUR ## Renvoie la k-ième plus grande valeur d’une série de données. +LINEST = DROITEREG ## Renvoie les paramètres d’une tendance linéaire. +LOGEST = LOGREG ## Renvoie les paramètres d’une tendance exponentielle. +LOGINV = LOI.LOGNORMALE.INVERSE ## Renvoie l’inverse de la probabilité pour une variable aléatoire suivant la loi lognormale. +LOGNORMDIST = LOI.LOGNORMALE ## Renvoie la probabilité d’une variable aléatoire continue suivant une loi lognormale. +MAX = MAX ## Renvoie la valeur maximale contenue dans une liste d’arguments. +MAXA = MAXA ## Renvoie la valeur maximale d’une liste d’arguments, nombres, texte et valeurs logiques inclus. +MEDIAN = MEDIANE ## Renvoie la valeur médiane des nombres donnés. +MIN = MIN ## Renvoie la valeur minimale contenue dans une liste d’arguments. +MINA = MINA ## Renvoie la plus petite valeur d’une liste d’arguments, nombres, texte et valeurs logiques inclus. +MODE = MODE ## Renvoie la valeur la plus courante d’une série de données. +NEGBINOMDIST = LOI.BINOMIALE.NEG ## Renvoie la probabilité d’une variable aléatoire discrète suivant une loi binomiale négative. +NORMDIST = LOI.NORMALE ## Renvoie la probabilité d’une variable aléatoire continue suivant une loi normale. +NORMINV = LOI.NORMALE.INVERSE ## Renvoie, pour une probabilité donnée, la valeur d’une variable aléatoire suivant une loi normale standard. +NORMSDIST = LOI.NORMALE.STANDARD ## Renvoie la probabilité d’une variable aléatoire continue suivant une loi normale standard. +NORMSINV = LOI.NORMALE.STANDARD.INVERSE ## Renvoie l’inverse de la distribution cumulée normale standard. +PEARSON = PEARSON ## Renvoie le coefficient de corrélation d’échantillonnage de Pearson. +PERCENTILE = CENTILE ## Renvoie le k-ième centile des valeurs d’une plage. +PERCENTRANK = RANG.POURCENTAGE ## Renvoie le rang en pourcentage d’une valeur d’une série de données. +PERMUT = PERMUTATION ## Renvoie le nombre de permutations pour un nombre donné d’objets. +POISSON = LOI.POISSON ## Renvoie la probabilité d’une variable aléatoire suivant une loi de Poisson. +PROB = PROBABILITE ## Renvoie la probabilité que des valeurs d’une plage soient comprises entre deux limites. +QUARTILE = QUARTILE ## Renvoie le quartile d’une série de données. +RANK = RANG ## Renvoie le rang d’un nombre contenu dans une liste. +RSQ = COEFFICIENT.DETERMINATION ## Renvoie la valeur du coefficient de détermination R^2 d’une régression linéaire. +SKEW = COEFFICIENT.ASYMETRIE ## Renvoie l’asymétrie d’une distribution. +SLOPE = PENTE ## Renvoie la pente d’une droite de régression linéaire. +SMALL = PETITE.VALEUR ## Renvoie la k-ième plus petite valeur d’une série de données. +STANDARDIZE = CENTREE.REDUITE ## Renvoie une valeur centrée réduite. +STDEV = ECARTYPE ## Évalue l’écart type d’une population en se basant sur un échantillon de cette population. +STDEVA = STDEVA ## Évalue l’écart type d’une population en se basant sur un échantillon de cette population, nombres, texte et valeurs logiques inclus. +STDEVP = ECARTYPEP ## Calcule l’écart type d’une population à partir de la population entière. +STDEVPA = STDEVPA ## Calcule l’écart type d’une population à partir de l’ensemble de la population, nombres, texte et valeurs logiques inclus. +STEYX = ERREUR.TYPE.XY ## Renvoie l’erreur type de la valeur y prévue pour chaque x de la régression. +TDIST = LOI.STUDENT ## Renvoie la probabilité d’une variable aléatoire suivant une loi T de Student. +TINV = LOI.STUDENT.INVERSE ## Renvoie, pour une probabilité donnée, la valeur d’une variable aléatoire suivant une loi T de Student. +TREND = TENDANCE ## Renvoie des valeurs par rapport à une tendance linéaire. +TRIMMEAN = MOYENNE.REDUITE ## Renvoie la moyenne de l’intérieur d’une série de données. +TTEST = TEST.STUDENT ## Renvoie la probabilité associée à un test T de Student. +VAR = VAR ## Calcule la variance sur la base d’un échantillon. +VARA = VARA ## Estime la variance d’une population en se basant sur un échantillon de cette population, nombres, texte et valeurs logiques incluses. +VARP = VAR.P ## Calcule la variance sur la base de l’ensemble de la population. +VARPA = VARPA ## Calcule la variance d’une population en se basant sur la population entière, nombres, texte et valeurs logiques inclus. +WEIBULL = LOI.WEIBULL ## Renvoie la probabilité d’une variable aléatoire suivant une loi de Weibull. +ZTEST = TEST.Z ## Renvoie la valeur de probabilité unilatérale d’un test z. + + +## +## Text functions Fonctions de texte +## +ASC = ASC ## Change les caractères anglais ou katakana à pleine chasse (codés sur deux octets) à l’intérieur d’une chaîne de caractères en caractères à demi-chasse (codés sur un octet). +BAHTTEXT = BAHTTEXT ## Convertit un nombre en texte en utilisant le format monétaire ß (baht). +CHAR = CAR ## Renvoie le caractère spécifié par le code numérique. +CLEAN = EPURAGE ## Supprime tous les caractères de contrôle du texte. +CODE = CODE ## Renvoie le numéro de code du premier caractère du texte. +CONCATENATE = CONCATENER ## Assemble plusieurs éléments textuels de façon à n’en former qu’un seul. +DOLLAR = EURO ## Convertit un nombre en texte en utilisant le format monétaire € (euro). +EXACT = EXACT ## Vérifie si deux valeurs de texte sont identiques. +FIND = TROUVE ## Trouve un valeur textuelle dans une autre, en respectant la casse. +FINDB = TROUVERB ## Trouve un valeur textuelle dans une autre, en respectant la casse. +FIXED = CTXT ## Convertit un nombre au format texte avec un nombre de décimales spécifié. +JIS = JIS ## Change les caractères anglais ou katakana à demi-chasse (codés sur un octet) à l’intérieur d’une chaîne de caractères en caractères à à pleine chasse (codés sur deux octets). +LEFT = GAUCHE ## Renvoie des caractères situés à l’extrême gauche d’une chaîne de caractères. +LEFTB = GAUCHEB ## Renvoie des caractères situés à l’extrême gauche d’une chaîne de caractères. +LEN = NBCAR ## Renvoie le nombre de caractères contenus dans une chaîne de texte. +LENB = LENB ## Renvoie le nombre de caractères contenus dans une chaîne de texte. +LOWER = MINUSCULE ## Convertit le texte en minuscules. +MID = STXT ## Renvoie un nombre déterminé de caractères d’une chaîne de texte à partir de la position que vous indiquez. +MIDB = STXTB ## Renvoie un nombre déterminé de caractères d’une chaîne de texte à partir de la position que vous indiquez. +PHONETIC = PHONETIQUE ## Extrait les caractères phonétiques (furigana) d’une chaîne de texte. +PROPER = NOMPROPRE ## Met en majuscules la première lettre de chaque mot dans une chaîne textuelle. +REPLACE = REMPLACER ## Remplace des caractères dans un texte. +REPLACEB = REMPLACERB ## Remplace des caractères dans un texte. +REPT = REPT ## Répète un texte un certain nombre de fois. +RIGHT = DROITE ## Renvoie des caractères situés à l’extrême droite d’une chaîne de caractères. +RIGHTB = DROITEB ## Renvoie des caractères situés à l’extrême droite d’une chaîne de caractères. +SEARCH = CHERCHE ## Trouve un texte dans un autre texte (sans respecter la casse). +SEARCHB = CHERCHERB ## Trouve un texte dans un autre texte (sans respecter la casse). +SUBSTITUTE = SUBSTITUE ## Remplace l’ancien texte d’une chaîne de caractères par un nouveau. +T = T ## Convertit ses arguments en texte. +TEXT = TEXTE ## Convertit un nombre au format texte. +TRIM = SUPPRESPACE ## Supprime les espaces du texte. +UPPER = MAJUSCULE ## Convertit le texte en majuscules. +VALUE = CNUM ## Convertit un argument textuel en nombre diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/hu/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/hu/config new file mode 100755 index 0000000..f350f1f --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/hu/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = Ft + + +## +## Excel Error Codes (For future use) +## +NULL = #NULLA! +DIV0 = #ZÉRÓOSZTÓ! +VALUE = #ÉRTÉK! +REF = #HIV! +NAME = #NÉV? +NUM = #SZÃM! +NA = #HIÃNYZIK diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/hu/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/hu/functions new file mode 100755 index 0000000..12a64b9 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/hu/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions BÅ‘vítmények és automatizálási függvények +## +GETPIVOTDATA = KIMUTATÃSADATOT.VESZ ## A kimutatásokban tárolt adatok visszaadására használható. + + +## +## Cube functions Kockafüggvények +## +CUBEKPIMEMBER = KOCKA.FÅTELJMUT ## Egy fÅ‘ teljesítménymutató (KPI) nevét, tulajdonságát és mértékegységét adja eredményül, a nevet és a tulajdonságot megjeleníti a cellában. A KPI-k számszerűsíthetÅ‘ mérési lehetÅ‘séget jelentenek – ilyen mutató például a havi bruttó nyereség vagy az egy alkalmazottra jutó negyedéves forgalom –, egy szervezet teljesítményének nyomonkövetésére használhatók. +CUBEMEMBER = KOCKA.TAG ## Kockahierachia tagját vagy rekordját adja eredményül. EllenÅ‘rizhetÅ‘ vele, hogy szerepel-e a kockában az adott tag vagy rekord. +CUBEMEMBERPROPERTY = KOCKA.TAG.TUL ## A kocka egyik tagtulajdonságának értékét adja eredményül. Használatával ellenÅ‘rizhetÅ‘, hogy szerepel-e egy tagnév a kockában, eredménye pedig az erre a tagra vonatkozó, megadott tulajdonság. +CUBERANKEDMEMBER = KOCKA.HALM.ELEM ## Egy halmaz rangsor szerinti n-edik tagját adja eredményül. Használatával egy halmaz egy vagy több elemét kaphatja meg, például a legnagyobb teljesítményű üzletkötÅ‘t vagy a 10 legjobb tanulót. +CUBESET = KOCKA.HALM ## Számított tagok vagy rekordok halmazát adja eredményül, ehhez egy beállított kifejezést elküld a kiszolgálón található kockának, majd ezt a halmazt adja vissza a Microsoft Office Excel alkalmazásnak. +CUBESETCOUNT = KOCKA.HALM.DB ## Egy halmaz elemszámát adja eredményül. +CUBEVALUE = KOCKA.ÉRTÉK ## Kockából összesített értéket ad eredményül. + + +## +## Database functions Adatbázis-kezelÅ‘ függvények +## +DAVERAGE = AB.ÃTLAG ## A kijelölt adatbáziselemek átlagát számítja ki. +DCOUNT = AB.DARAB ## Megszámolja, hogy az adatbázisban hány cella tartalmaz számokat. +DCOUNTA = AB.DARAB2 ## Megszámolja az adatbázisban lévÅ‘ nem üres cellákat. +DGET = AB.MEZÅ ## Egy adatbázisból egyetlen olyan rekordot ad vissza, amely megfelel a megadott feltételeknek. +DMAX = AB.MAX ## A kiválasztott adatbáziselemek közül a legnagyobb értéket adja eredményül. +DMIN = AB.MIN ## A kijelölt adatbáziselemek közül a legkisebb értéket adja eredményül. +DPRODUCT = AB.SZORZAT ## Az adatbázis megadott feltételeknek eleget tevÅ‘ rekordjaira összeszorozza a megadott mezÅ‘ben található számértékeket, és eredményül ezt a szorzatot adja. +DSTDEV = AB.SZÓRÃS ## A kijelölt adatbáziselemek egy mintája alapján megbecsüli a szórást. +DSTDEVP = AB.SZÓRÃS2 ## A kijelölt adatbáziselemek teljes sokasága alapján kiszámítja a szórást. +DSUM = AB.SZUM ## Összeadja a feltételnek megfelelÅ‘ adatbázisrekordok mezÅ‘oszlopában a számokat. +DVAR = AB.VAR ## A kijelölt adatbáziselemek mintája alapján becslést ad a szórásnégyzetre. +DVARP = AB.VAR2 ## A kijelölt adatbáziselemek teljes sokasága alapján kiszámítja a szórásnégyzetet. + + +## +## Date and time functions Dátumfüggvények +## +DATE = DÃTUM ## Adott dátum dátumértékét adja eredményül. +DATEVALUE = DÃTUMÉRTÉK ## Szövegként megadott dátumot dátumértékké alakít át. +DAY = NAP ## Dátumértéket a hónap egy napjává (0-31) alakít. +DAYS360 = NAP360 ## Két dátum közé esÅ‘ napok számát számítja ki a 360 napos év alapján. +EDATE = EDATE ## Adott dátumnál adott számú hónappal korábbi vagy késÅ‘bbi dátum dátumértékét adja eredményül. +EOMONTH = EOMONTH ## Adott dátumnál adott számú hónappal korábbi vagy késÅ‘bbi hónap utolsó napjának dátumértékét adja eredményül. +HOUR = ÓRA ## Időértéket órákká alakít. +MINUTE = PERC ## Időértéket percekké alakít. +MONTH = HÓNAP ## Időértéket hónapokká alakít. +NETWORKDAYS = NETWORKDAYS ## Két dátum között a teljes munkanapok számát adja meg. +NOW = MOST ## A napi dátum dátumértékét és a pontos idÅ‘ időértékét adja eredményül. +SECOND = MPERC ## Időértéket másodpercekké alakít át. +TIME = IDÅ ## Adott idÅ‘pont időértékét adja meg. +TIMEVALUE = IDÅÉRTÉK ## Szövegként megadott idÅ‘pontot időértékké alakít át. +TODAY = MA ## A napi dátum dátumértékét adja eredményül. +WEEKDAY = HÉT.NAPJA ## Dátumértéket a hét napjává alakítja át. +WEEKNUM = WEEKNUM ## Visszatérési értéke egy szám, amely azt mutatja meg, hogy a megadott dátum az év hányadik hetére esik. +WORKDAY = WORKDAY ## Adott dátumnál adott munkanappal korábbi vagy késÅ‘bbi dátum dátumértékét adja eredményül. +YEAR = ÉV ## Sorszámot évvé alakít át. +YEARFRAC = YEARFRAC ## Az adott dátumok közötti teljes napok számát törtévként adja meg. + + +## +## Engineering functions Mérnöki függvények +## +BESSELI = BESSELI ## Az In(x) módosított Bessel-függvény értékét adja eredményül. +BESSELJ = BESSELJ ## A Jn(x) Bessel-függvény értékét adja eredményül. +BESSELK = BESSELK ## A Kn(x) módosított Bessel-függvény értékét adja eredményül. +BESSELY = BESSELY ## Az Yn(x) módosított Bessel-függvény értékét adja eredményül. +BIN2DEC = BIN2DEC ## Bináris számot decimálissá alakít át. +BIN2HEX = BIN2HEX ## Bináris számot hexadecimálissá alakít át. +BIN2OCT = BIN2OCT ## Bináris számot oktálissá alakít át. +COMPLEX = COMPLEX ## Valós és képzetes részbÅ‘l komplex számot képez. +CONVERT = CONVERT ## Mértékegységeket vált át. +DEC2BIN = DEC2BIN ## Decimális számot binárissá alakít át. +DEC2HEX = DEC2HEX ## Decimális számot hexadecimálissá alakít át. +DEC2OCT = DEC2OCT ## Decimális számot oktálissá alakít át. +DELTA = DELTA ## Azt vizsgálja, hogy két érték egyenlÅ‘-e. +ERF = ERF ## A hibafüggvény értékét adja eredményül. +ERFC = ERFC ## A kiegészített hibafüggvény értékét adja eredményül. +GESTEP = GESTEP ## Azt vizsgálja, hogy egy szám nagyobb-e adott küszöbértéknél. +HEX2BIN = HEX2BIN ## Hexadecimális számot binárissá alakít át. +HEX2DEC = HEX2DEC ## Hexadecimális számot decimálissá alakít át. +HEX2OCT = HEX2OCT ## Hexadecimális számot oktálissá alakít át. +IMABS = IMABS ## Komplex szám abszolút értékét (modulusát) adja eredményül. +IMAGINARY = IMAGINARY ## Komplex szám képzetes részét adja eredményül. +IMARGUMENT = IMARGUMENT ## A komplex szám radiánban kifejezett théta argumentumát adja eredményül. +IMCONJUGATE = IMCONJUGATE ## Komplex szám komplex konjugáltját adja eredményül. +IMCOS = IMCOS ## Komplex szám koszinuszát adja eredményül. +IMDIV = IMDIV ## Két komplex szám hányadosát adja eredményül. +IMEXP = IMEXP ## Az e szám komplex kitevÅ‘jű hatványát adja eredményül. +IMLN = IMLN ## Komplex szám természetes logaritmusát adja eredményül. +IMLOG10 = IMLOG10 ## Komplex szám tízes alapú logaritmusát adja eredményül. +IMLOG2 = IMLOG2 ## Komplex szám kettes alapú logaritmusát adja eredményül. +IMPOWER = IMPOWER ## Komplex szám hatványát adja eredményül. +IMPRODUCT = IMPRODUCT ## Komplex számok szorzatát adja eredményül. +IMREAL = IMREAL ## Komplex szám valós részét adja eredményül. +IMSIN = IMSIN ## Komplex szám szinuszát adja eredményül. +IMSQRT = IMSQRT ## Komplex szám négyzetgyökét adja eredményül. +IMSUB = IMSUB ## Két komplex szám különbségét adja eredményül. +IMSUM = IMSUM ## Komplex számok összegét adja eredményül. +OCT2BIN = OCT2BIN ## Oktális számot binárissá alakít át. +OCT2DEC = OCT2DEC ## Oktális számot decimálissá alakít át. +OCT2HEX = OCT2HEX ## Oktális számot hexadecimálissá alakít át. + + +## +## Financial functions Pénzügyi függvények +## +ACCRINT = ACCRINT ## Periodikusan kamatozó értékpapír felszaporodott kamatát adja eredményül. +ACCRINTM = ACCRINTM ## Lejáratkor kamatozó értékpapír felszaporodott kamatát adja eredményül. +AMORDEGRC = AMORDEGRC ## Ãllóeszköz lineáris értékcsökkenését adja meg az egyes könyvelési idÅ‘szakokra vonatkozóan. +AMORLINC = AMORLINC ## Az egyes könyvelési idÅ‘szakokban az értékcsökkenést adja meg. +COUPDAYBS = COUPDAYBS ## A szelvényidÅ‘szak kezdetétÅ‘l a kifizetés idÅ‘pontjáig eltelt napokat adja vissza. +COUPDAYS = COUPDAYS ## A kifizetés idÅ‘pontját magában foglaló szelvényperiódus hosszát adja meg napokban. +COUPDAYSNC = COUPDAYSNC ## A kifizetés idÅ‘pontja és a legközelebbi szelvénydátum közötti napok számát adja meg. +COUPNCD = COUPNCD ## A kifizetést követÅ‘ legelsÅ‘ szelvénydátumot adja eredményül. +COUPNUM = COUPNUM ## A kifizetés és a lejárat idÅ‘pontja között kifizetendÅ‘ szelvények számát adja eredményül. +COUPPCD = COUPPCD ## A kifizetés elÅ‘tti utolsó szelvénydátumot adja eredményül. +CUMIPMT = CUMIPMT ## Két fizetési idÅ‘szak között kifizetett kamat halmozott értékét adja eredményül. +CUMPRINC = CUMPRINC ## Két fizetési idÅ‘szak között kifizetett részletek halmozott (kamatot nem tartalmazó) értékét adja eredményül. +DB = KCS2 ## Eszköz adott idÅ‘szak alatti értékcsökkenését számítja ki a lineáris leírási modell alkalmazásával. +DDB = KCSA ## Eszköz értékcsökkenését számítja ki adott idÅ‘szakra vonatkozóan a progresszív vagy egyéb megadott leírási modell alkalmazásával. +DISC = DISC ## Értékpapír leszámítolási kamatlábát adja eredményül. +DOLLARDE = DOLLARDE ## Egy közönséges törtként megadott számot tizedes törtté alakít át. +DOLLARFR = DOLLARFR ## Tizedes törtként megadott számot közönséges törtté alakít át. +DURATION = DURATION ## Periodikus kamatfizetésű értékpapír éves kamatérzékenységét adja eredményül. +EFFECT = EFFECT ## Az éves tényleges kamatláb értékét adja eredményül. +FV = JBÉ ## Befektetés jövÅ‘beli értékét számítja ki. +FVSCHEDULE = FVSCHEDULE ## A kezdÅ‘tÅ‘ke adott kamatlábak szerint megnövelt jövÅ‘beli értékét adja eredményül. +INTRATE = INTRATE ## A lejáratig teljesen lekötött értékpapír kamatrátáját adja eredményül. +IPMT = RRÉSZLET ## Hiteltörlesztésen belül a tÅ‘ketörlesztés nagyságát számítja ki adott idÅ‘szakra. +IRR = BMR ## A befektetés belsÅ‘ megtérülési rátáját számítja ki pénzáramláshoz. +ISPMT = LRÉSZLETKAMAT ## A befektetés adott idÅ‘szakára fizetett kamatot számítja ki. +MDURATION = MDURATION ## Egy 100 Ft névértékű értékpapír Macauley-féle módosított kamatérzékenységét adja eredményül. +MIRR = MEGTÉRÃœLÉS ## A befektetés belsÅ‘ megtérülési rátáját számítja ki a költségek és a bevételek különbözÅ‘ kamatlába mellett. +NOMINAL = NOMINAL ## Az éves névleges kamatláb értékét adja eredményül. +NPER = PER.SZÃM ## A törlesztési idÅ‘szakok számát adja meg. +NPV = NMÉ ## Befektetéshez kapcsolódó pénzáramlás nettó jelenértékét számítja ki ismert pénzáramlás és kamatláb mellett. +ODDFPRICE = ODDFPRICE ## Egy 100 Ft névértékű, a futamidÅ‘ elején töredék-idÅ‘szakos értékpapír árát adja eredményül. +ODDFYIELD = ODDFYIELD ## A futamidÅ‘ elején töredék-idÅ‘szakos értékpapír hozamát adja eredményül. +ODDLPRICE = ODDLPRICE ## Egy 100 Ft névértékű, a futamidÅ‘ végén töredék-idÅ‘szakos értékpapír árát adja eredményül. +ODDLYIELD = ODDLYIELD ## A futamidÅ‘ végén töredék-idÅ‘szakos értékpapír hozamát adja eredményül. +PMT = RÉSZLET ## A törlesztési idÅ‘szakra vonatkozó törlesztési összeget számítja ki. +PPMT = PRÉSZLET ## Hiteltörlesztésen belül a tÅ‘ketörlesztés nagyságát számítja ki adott idÅ‘szakra. +PRICE = PRICE ## Egy 100 Ft névértékű, periodikusan kamatozó értékpapír árát adja eredményül. +PRICEDISC = PRICEDISC ## Egy 100 Ft névértékű leszámítolt értékpapír árát adja eredményül. +PRICEMAT = PRICEMAT ## Egy 100 Ft névértékű, a lejáratkor kamatozó értékpapír árát adja eredményül. +PV = MÉ ## Befektetés jelenlegi értékét számítja ki. +RATE = RÃTA ## Egy törlesztési idÅ‘szakban az egy idÅ‘szakra esÅ‘ kamatláb nagyságát számítja ki. +RECEIVED = RECEIVED ## A lejáratig teljesen lekötött értékpapír lejáratakor kapott összegét adja eredményül. +SLN = LCSA ## Tárgyi eszköz egy idÅ‘szakra esÅ‘ amortizációját adja meg bruttó érték szerinti lineáris leírási kulcsot alkalmazva. +SYD = SYD ## Tárgyi eszköz értékcsökkenését számítja ki adott idÅ‘szakra az évek számjegyösszegével dolgozó módszer alapján. +TBILLEQ = TBILLEQ ## Kincstárjegy kötvény-egyenértékű hozamát adja eredményül. +TBILLPRICE = TBILLPRICE ## Egy 100 Ft névértékű kincstárjegy árát adja eredményül. +TBILLYIELD = TBILLYIELD ## Kincstárjegy hozamát adja eredményül. +VDB = ÉCSRI ## Tárgyi eszköz amortizációját számítja ki megadott vagy részidÅ‘szakra a csökkenÅ‘ egyenleg módszerének alkalmazásával. +XIRR = XIRR ## Ãœtemezett készpénzforgalom (cash flow) belsÅ‘ megtérülési kamatrátáját adja eredményül. +XNPV = XNPV ## Ãœtemezett készpénzforgalom (cash flow) nettó jelenlegi értékét adja eredményül. +YIELD = YIELD ## Periodikusan kamatozó értékpapír hozamát adja eredményül. +YIELDDISC = YIELDDISC ## Leszámítolt értékpapír (például kincstárjegy) éves hozamát adja eredményül. +YIELDMAT = YIELDMAT ## Lejáratkor kamatozó értékpapír éves hozamát adja eredményül. + + +## +## Information functions Információs függvények +## +CELL = CELLA ## Egy cella formátumára, elhelyezkedésére vagy tartalmára vonatkozó adatokat ad eredményül. +ERROR.TYPE = HIBA.TÃPUS ## Egy hibatípushoz tartozó számot ad eredményül. +INFO = INFÓ ## A rendszer- és munkakörnyezet pillanatnyi állapotáról ad felvilágosítást. +ISBLANK = ÃœRES ## Eredménye IGAZ, ha az érték üres. +ISERR = HIBA ## Eredménye IGAZ, ha az érték valamelyik hibaérték a #HIÃNYZIK kivételével. +ISERROR = HIBÃS ## Eredménye IGAZ, ha az érték valamelyik hibaérték. +ISEVEN = ISEVEN ## Eredménye IGAZ, ha argumentuma páros szám. +ISLOGICAL = LOGIKAI ## Eredménye IGAZ, ha az érték logikai érték. +ISNA = NINCS ## Eredménye IGAZ, ha az érték a #HIÃNYZIK hibaérték. +ISNONTEXT = NEM.SZÖVEG ## Eredménye IGAZ, ha az érték nem szöveg. +ISNUMBER = SZÃM ## Eredménye IGAZ, ha az érték szám. +ISODD = ISODD ## Eredménye IGAZ, ha argumentuma páratlan szám. +ISREF = HIVATKOZÃS ## Eredménye IGAZ, ha az érték hivatkozás. +ISTEXT = SZÖVEG.E ## Eredménye IGAZ, ha az érték szöveg. +N = N ## Argumentumának értékét számmá alakítja. +NA = HIÃNYZIK ## Eredménye a #HIÃNYZIK hibaérték. +TYPE = TÃPUS ## Érték adattípusának azonosítószámát adja eredményül. + + +## +## Logical functions Logikai függvények +## +AND = ÉS ## Eredménye IGAZ, ha minden argumentuma IGAZ. +FALSE = HAMIS ## A HAMIS logikai értéket adja eredményül. +IF = HA ## Logikai vizsgálatot hajt végre. +IFERROR = HAHIBA ## A megadott értéket adja vissza, ha egy képlet hibához vezet; más esetben a képlet értékét adja eredményül. +NOT = NEM ## Argumentuma értékének ellentettjét adja eredményül. +OR = VAGY ## Eredménye IGAZ, ha bármely argumentuma IGAZ. +TRUE = IGAZ ## Az IGAZ logikai értéket adja eredményül. + + +## +## Lookup and reference functions Keresési és hivatkozási függvények +## +ADDRESS = CÃM ## A munkalap egy cellájára való hivatkozást adja szövegként eredményül. +AREAS = TERÃœLET ## Hivatkozásban a területek számát adja eredményül. +CHOOSE = VÃLASZT ## Értékek listájából választ ki egy elemet. +COLUMN = OSZLOP ## Egy hivatkozás oszlopszámát adja eredményül. +COLUMNS = OSZLOPOK ## A hivatkozásban található oszlopok számát adja eredményül. +HLOOKUP = VKERES ## A megadott tömb felsÅ‘ sorában adott értékű elemet keres, és a megtalált elem oszlopából adott sorban elhelyezkedÅ‘ értékkel tér vissza. +HYPERLINK = HIPERHIVATKOZÃS ## Hálózati kiszolgálón, intraneten vagy az interneten tárolt dokumentumot megnyitó parancsikont vagy hivatkozást hoz létre. +INDEX = INDEX ## Tömb- vagy hivatkozás indexszel megadott értékét adja vissza. +INDIRECT = INDIREKT ## Szöveg megadott hivatkozást ad eredményül. +LOOKUP = KERES ## Vektorban vagy tömbben keres meg értékeket. +MATCH = HOL.VAN ## Hivatkozásban vagy tömbben értékeket keres. +OFFSET = OFSZET ## Hivatkozás egy másik hivatkozástól számított távolságát adja meg. +ROW = SOR ## Egy hivatkozás sorának számát adja meg. +ROWS = SOROK ## Egy hivatkozás sorainak számát adja meg. +RTD = RTD ## Valós idejű adatokat keres vissza a COM automatizmust (automatizálás: Egy alkalmazás objektumaival való munka másik alkalmazásból vagy fejlesztÅ‘eszközbÅ‘l. A korábban OLE automatizmusnak nevezett automatizálás iparági szabvány, a Component Object Model (COM) szolgáltatása.) támogató programból. +TRANSPOSE = TRANSZPONÃLÃS ## Egy tömb transzponáltját adja eredményül. +VLOOKUP = FKERES ## A megadott tömb bal szélsÅ‘ oszlopában megkeres egy értéket, majd annak sora és a megadott oszlop metszéspontjában levÅ‘ értéked adja eredményül. + + +## +## Math and trigonometry functions Matematikai és trigonometrikus függvények +## +ABS = ABS ## Egy szám abszolút értékét adja eredményül. +ACOS = ARCCOS ## Egy szám arkusz koszinuszát számítja ki. +ACOSH = ACOSH ## Egy szám inverz koszinusz hiperbolikuszát számítja ki. +ASIN = ARCSIN ## Egy szám arkusz szinuszát számítja ki. +ASINH = ASINH ## Egy szám inverz szinusz hiperbolikuszát számítja ki. +ATAN = ARCTAN ## Egy szám arkusz tangensét számítja ki. +ATAN2 = ARCTAN2 ## X és y koordináták alapján számítja ki az arkusz tangens értéket. +ATANH = ATANH ## A szám inverz tangens hiperbolikuszát számítja ki. +CEILING = PLAFON ## Egy számot a legközelebbi egészre vagy a pontosságként megadott érték legközelebb esÅ‘ többszörösére kerekít. +COMBIN = KOMBINÃCIÓK ## Adott számú objektum összes lehetséges kombinációinak számát számítja ki. +COS = COS ## Egy szám koszinuszát számítja ki. +COSH = COSH ## Egy szám koszinusz hiperbolikuszát számítja ki. +DEGREES = FOK ## Radiánt fokká alakít át. +EVEN = PÃROS ## Egy számot a legközelebbi páros egész számra kerekít. +EXP = KITEVÅ ## Az e adott kitevÅ‘jű hatványát adja eredményül. +FACT = FAKT ## Egy szám faktoriálisát számítja ki. +FACTDOUBLE = FACTDOUBLE ## Egy szám dupla faktoriálisát adja eredményül. +FLOOR = PADLÓ ## Egy számot lefelé, a nulla felé kerekít. +GCD = GCD ## A legnagyobb közös osztót adja eredményül. +INT = INT ## Egy számot lefelé kerekít a legközelebbi egészre. +LCM = LCM ## A legkisebb közös többszöröst adja eredményül. +LN = LN ## Egy szám természetes logaritmusát számítja ki. +LOG = LOG ## Egy szám adott alapú logaritmusát számítja ki. +LOG10 = LOG10 ## Egy szám 10-es alapú logaritmusát számítja ki. +MDETERM = MDETERM ## Egy tömb mátrix-determinánsát számítja ki. +MINVERSE = INVERZ.MÃTRIX ## Egy tömb mátrix inverzét adja eredményül. +MMULT = MSZORZAT ## Két tömb mátrix-szorzatát adja meg. +MOD = MARADÉK ## Egy szám osztási maradékát adja eredményül. +MROUND = MROUND ## A kívánt többszörösére kerekített értéket ad eredményül. +MULTINOMIAL = MULTINOMIAL ## Számhalmaz multinomiálisát adja eredményül. +ODD = PÃRATLAN ## Egy számot a legközelebbi páratlan számra kerekít. +PI = PI ## A pi matematikai állandót adja vissza. +POWER = HATVÃNY ## Egy szám adott kitevÅ‘jű hatványát számítja ki. +PRODUCT = SZORZAT ## Argumentumai szorzatát számítja ki. +QUOTIENT = QUOTIENT ## Egy hányados egész részét adja eredményül. +RADIANS = RADIÃN ## Fokot radiánná alakít át. +RAND = VÉL ## Egy 0 és 1 közötti véletlen számot ad eredményül. +RANDBETWEEN = RANDBETWEEN ## Megadott számok közé esÅ‘ véletlen számot állít elÅ‘. +ROMAN = RÓMAI ## Egy számot római számokkal kifejezve szövegként ad eredményül. +ROUND = KEREKÃTÉS ## Egy számot adott számú számjegyre kerekít. +ROUNDDOWN = KEREKÃTÉS.LE ## Egy számot lefelé, a nulla felé kerekít. +ROUNDUP = KEREKÃTÉS.FEL ## Egy számot felfelé, a nullától távolabbra kerekít. +SERIESSUM = SERIESSUM ## Hatványsor összegét adja eredményül. +SIGN = ELÅJEL ## Egy szám elÅ‘jelét adja meg. +SIN = SIN ## Egy szög szinuszát számítja ki. +SINH = SINH ## Egy szám szinusz hiperbolikuszát számítja ki. +SQRT = GYÖK ## Egy szám pozitív négyzetgyökét számítja ki. +SQRTPI = SQRTPI ## A (szám*pi) négyzetgyökét adja eredményül. +SUBTOTAL = RÉSZÖSSZEG ## Lista vagy adatbázis részösszegét adja eredményül. +SUM = SZUM ## Összeadja az argumentumlistájában lévÅ‘ számokat. +SUMIF = SZUMHA ## A megadott feltételeknek eleget tevÅ‘ cellákban található értékeket adja össze. +SUMIFS = SZUMHATÖBB ## Több megadott feltételnek eleget tévÅ‘ tartománycellák összegét adja eredményül. +SUMPRODUCT = SZORZATÖSSZEG ## A megfelelÅ‘ tömbelemek szorzatának összegét számítja ki. +SUMSQ = NÉGYZETÖSSZEG ## Argumentumai négyzetének összegét számítja ki. +SUMX2MY2 = SZUMX2BÅLY2 ## Két tömb megfelelÅ‘ elemei négyzetének különbségét összegzi. +SUMX2PY2 = SZUMX2MEGY2 ## Két tömb megfelelÅ‘ elemei négyzetének összegét összegzi. +SUMXMY2 = SZUMXBÅLY2 ## Két tömb megfelelÅ‘ elemei különbségének négyzetösszegét számítja ki. +TAN = TAN ## Egy szám tangensét számítja ki. +TANH = TANH ## Egy szám tangens hiperbolikuszát számítja ki. +TRUNC = CSONK ## Egy számot egésszé csonkít. + + +## +## Statistical functions Statisztikai függvények +## +AVEDEV = ÃTL.ELTÉRÉS ## Az adatpontoknak átlaguktól való átlagos abszolút eltérését számítja ki. +AVERAGE = ÃTLAG ## Argumentumai átlagát számítja ki. +AVERAGEA = ÃTLAGA ## Argumentumai átlagát számítja ki (beleértve a számokat, szöveget és logikai értékeket). +AVERAGEIF = ÃTLAGHA ## A megadott feltételnek eleget tévÅ‘ tartomány celláinak átlagát (számtani közepét) adja eredményül. +AVERAGEIFS = ÃTLAGHATÖBB ## A megadott feltételeknek eleget tévÅ‘ cellák átlagát (számtani közepét) adja eredményül. +BETADIST = BÉTA.ELOSZLÃS ## A béta-eloszlás függvényt számítja ki. +BETAINV = INVERZ.BÉTA ## Adott béta-eloszláshoz kiszámítja a béta eloszlásfüggvény inverzét. +BINOMDIST = BINOM.ELOSZLÃS ## A diszkrét binomiális eloszlás valószínűségértékét számítja ki. +CHIDIST = KHI.ELOSZLÃS ## A khi-négyzet-eloszlás egyszélű valószínűségértékét számítja ki. +CHIINV = INVERZ.KHI ## A khi-négyzet-eloszlás egyszélű valószínűségértékének inverzét számítja ki. +CHITEST = KHI.PRÓBA ## Függetlenségvizsgálatot hajt végre. +CONFIDENCE = MEGBÃZHATÓSÃG ## Egy statisztikai sokaság várható értékének megbízhatósági intervallumát adja eredményül. +CORREL = KORREL ## Két adathalmaz korrelációs együtthatóját számítja ki. +COUNT = DARAB ## Megszámolja, hogy argumentumlistájában hány szám található. +COUNTA = DARAB2 ## Megszámolja, hogy argumentumlistájában hány érték található. +COUNTBLANK = DARABÃœRES ## Egy tartományban összeszámolja az üres cellákat. +COUNTIF = DARABTELI ## Egy tartományban összeszámolja azokat a cellákat, amelyek eleget tesznek a megadott feltételnek. +COUNTIFS = DARABHATÖBB ## Egy tartományban összeszámolja azokat a cellákat, amelyek eleget tesznek több feltételnek. +COVAR = KOVAR ## A kovarianciát, azaz a páronkénti eltérések szorzatának átlagát számítja ki. +CRITBINOM = KRITBINOM ## Azt a legkisebb számot adja eredményül, amelyre a binomiális eloszlásfüggvény értéke nem kisebb egy adott határértéknél. +DEVSQ = SQ ## Az átlagtól való eltérések négyzetének összegét számítja ki. +EXPONDIST = EXP.ELOSZLÃS ## Az exponenciális eloszlás értékét számítja ki. +FDIST = F.ELOSZLÃS ## Az F-eloszlás értékét számítja ki. +FINV = INVERZ.F ## Az F-eloszlás inverzének értékét számítja ki. +FISHER = FISHER ## Fisher-transzformációt hajt végre. +FISHERINV = INVERZ.FISHER ## A Fisher-transzformáció inverzét hajtja végre. +FORECAST = ELÅREJELZÉS ## Az ismert értékek alapján lineáris regresszióval becsült értéket ad eredményül. +FREQUENCY = GYAKORISÃG ## A gyakorisági vagy empirikus eloszlás értékét függÅ‘leges tömbként adja eredményül. +FTEST = F.PRÓBA ## Az F-próba értékét adja eredményül. +GAMMADIST = GAMMA.ELOSZLÃS ## A gamma-eloszlás értékét számítja ki. +GAMMAINV = INVERZ.GAMMA ## A gamma-eloszlás eloszlásfüggvénye inverzének értékét számítja ki. +GAMMALN = GAMMALN ## A gamma-függvény természetes logaritmusát számítja ki. +GEOMEAN = MÉRTANI.KÖZÉP ## Argumentumai mértani középértékét számítja ki. +GROWTH = NÖV ## Exponenciális regresszió alapján ad becslést. +HARMEAN = HARM.KÖZÉP ## Argumentumai harmonikus átlagát számítja ki. +HYPGEOMDIST = HIPERGEOM.ELOSZLÃS ## A hipergeometriai eloszlás értékét számítja ki. +INTERCEPT = METSZ ## A regressziós egyenes y tengellyel való metszéspontját határozza meg. +KURT = CSÚCSOSSÃG ## Egy adathalmaz csúcsosságát számítja ki. +LARGE = NAGY ## Egy adathalmaz k-adik legnagyobb elemét adja eredményül. +LINEST = LIN.ILL ## A legkisebb négyzetek módszerével az adatokra illesztett egyenes paramétereit határozza meg. +LOGEST = LOG.ILL ## Az adatokra illesztett exponenciális görbe paramétereit határozza meg. +LOGINV = INVERZ.LOG.ELOSZLÃS ## A lognormális eloszlás inverzét számítja ki. +LOGNORMDIST = LOG.ELOSZLÃS ## A lognormális eloszlásfüggvény értékét számítja ki. +MAX = MAX ## Az argumentumai között szereplÅ‘ legnagyobb számot adja meg. +MAXA = MAX2 ## Az argumentumai között szereplÅ‘ legnagyobb számot adja meg (beleértve a számokat, szöveget és logikai értékeket). +MEDIAN = MEDIÃN ## Adott számhalmaz mediánját számítja ki. +MIN = MIN ## Az argumentumai között szereplÅ‘ legkisebb számot adja meg. +MINA = MIN2 ## Az argumentumai között szereplÅ‘ legkisebb számot adja meg, beleértve a számokat, szöveget és logikai értékeket. +MODE = MÓDUSZ ## Egy adathalmazból kiválasztja a leggyakrabban elÅ‘forduló számot. +NEGBINOMDIST = NEGBINOM.ELOSZL ## A negatív binomiális eloszlás értékét számítja ki. +NORMDIST = NORM.ELOSZL ## A normális eloszlás értékét számítja ki. +NORMINV = INVERZ.NORM ## A normális eloszlás eloszlásfüggvénye inverzének értékét számítja ki. +NORMSDIST = STNORMELOSZL ## A standard normális eloszlás eloszlásfüggvényének értékét számítja ki. +NORMSINV = INVERZ.STNORM ## A standard normális eloszlás eloszlásfüggvénye inverzének értékét számítja ki. +PEARSON = PEARSON ## A Pearson-féle korrelációs együtthatót számítja ki. +PERCENTILE = PERCENTILIS ## Egy tartományban található értékek k-adik percentilisét, azaz százalékosztályát adja eredményül. +PERCENTRANK = SZÃZALÉKRANG ## Egy értéknek egy adathalmazon belül vett százalékos rangját (elhelyezkedését) számítja ki. +PERMUT = VARIÃCIÓK ## Adott számú objektum k-ad osztályú ismétlés nélküli variációinak számát számítja ki. +POISSON = POISSON ## A Poisson-eloszlás értékét számítja ki. +PROB = VALÓSZÃNÅ°SÉG ## Annak valószínűségét számítja ki, hogy adott értékek két határérték közé esnek. +QUARTILE = KVARTILIS ## Egy adathalmaz kvartilisét (negyedszintjét) számítja ki. +RANK = SORSZÃM ## Kiszámítja, hogy egy szám hányadik egy számsorozatban. +RSQ = RNÉGYZET ## Kiszámítja a Pearson-féle szorzatmomentum korrelációs együtthatójának négyzetét. +SKEW = FERDESÉG ## Egy eloszlás ferdeségét határozza meg. +SLOPE = MEREDEKSÉG ## Egy lineáris regressziós egyenes meredekségét számítja ki. +SMALL = KICSI ## Egy adathalmaz k-adik legkisebb elemét adja meg. +STANDARDIZE = NORMALIZÃLÃS ## Normalizált értéket ad eredményül. +STDEV = SZÓRÃS ## Egy statisztikai sokaság mintájából kiszámítja annak szórását. +STDEVA = SZÓRÃSA ## Egy statisztikai sokaság mintájából kiszámítja annak szórását (beleértve a számokat, szöveget és logikai értékeket). +STDEVP = SZÓRÃSP ## Egy statisztikai sokaság egészébÅ‘l kiszámítja annak szórását. +STDEVPA = SZÓRÃSPA ## Egy statisztikai sokaság egészébÅ‘l kiszámítja annak szórását (beleértve számokat, szöveget és logikai értékeket). +STEYX = STHIBAYX ## Egy regresszió esetén az egyes x-értékek alapján meghatározott y-értékek standard hibáját számítja ki. +TDIST = T.ELOSZLÃS ## A Student-féle t-eloszlás értékét számítja ki. +TINV = INVERZ.T ## A Student-féle t-eloszlás inverzét számítja ki. +TREND = TREND ## Lineáris trend értékeit számítja ki. +TRIMMEAN = RÉSZÃTLAG ## Egy adathalmaz középsÅ‘ részének átlagát számítja ki. +TTEST = T.PRÓBA ## A Student-féle t-próbához tartozó valószínűséget számítja ki. +VAR = VAR ## Minta alapján becslést ad a varianciára. +VARA = VARA ## Minta alapján becslést ad a varianciára (beleértve számokat, szöveget és logikai értékeket). +VARP = VARP ## Egy statisztikai sokaság varianciáját számítja ki. +VARPA = VARPA ## Egy statisztikai sokaság varianciáját számítja ki (beleértve számokat, szöveget és logikai értékeket). +WEIBULL = WEIBULL ## A Weibull-féle eloszlás értékét számítja ki. +ZTEST = Z.PRÓBA ## Az egyszélű z-próbával kapott valószínűségértéket számítja ki. + + +## +## Text functions Szövegműveletekhez használható függvények +## +ASC = ASC ## Szöveg teljes szélességű (kétbájtos) latin és katakana karaktereit félszélességű (egybájtos) karakterekké alakítja. +BAHTTEXT = BAHTSZÖVEG ## Számot szöveggé alakít a ß (baht) pénznemformátum használatával. +CHAR = KARAKTER ## A kódszámmal meghatározott karaktert adja eredményül. +CLEAN = TISZTÃT ## A szövegbÅ‘l eltávolítja az összes nem nyomtatható karaktert. +CODE = KÓD ## Karaktersorozat elsÅ‘ karakterének numerikus kódját adja eredményül. +CONCATENATE = ÖSSZEFÅ°Z ## Több szövegelemet egyetlen szöveges elemmé fűz össze. +DOLLAR = FORINT ## Számot pénznem formátumú szöveggé alakít át. +EXACT = AZONOS ## Megvizsgálja, hogy két érték azonos-e. +FIND = SZÖVEG.TALÃL ## Karaktersorozatot keres egy másikban (a kis- és nagybetűk megkülönböztetésével). +FINDB = SZÖVEG.TALÃL2 ## Karaktersorozatot keres egy másikban (a kis- és nagybetűk megkülönböztetésével). +FIXED = FIX ## Számot szöveges formátumúra alakít adott számú tizedesjegyre kerekítve. +JIS = JIS ## A félszélességű (egybájtos) latin és a katakana karaktereket teljes szélességű (kétbájtos) karakterekké alakítja. +LEFT = BAL ## Szöveg bal szélsÅ‘ karaktereit adja eredményül. +LEFTB = BAL2 ## Szöveg bal szélsÅ‘ karaktereit adja eredményül. +LEN = HOSSZ ## Szöveg karakterekben mért hosszát adja eredményül. +LENB = HOSSZ2 ## Szöveg karakterekben mért hosszát adja eredményül. +LOWER = KISBETÅ° ## Szöveget kisbetűssé alakít át. +MID = KÖZÉP ## A szöveg adott pozíciójától kezdve megadott számú karaktert ad vissza eredményként. +MIDB = KÖZÉP2 ## A szöveg adott pozíciójától kezdve megadott számú karaktert ad vissza eredményként. +PHONETIC = PHONETIC ## Szöveg furigana (fonetikus) karaktereit adja vissza. +PROPER = TNÉV ## Szöveg minden szavának kezdÅ‘betűjét nagybetűsre cseréli. +REPLACE = CSERE ## A szövegen belül karaktereket cserél. +REPLACEB = CSERE2 ## A szövegen belül karaktereket cserél. +REPT = SOKSZOR ## Megadott számú alkalommal megismétel egy szövegrészt. +RIGHT = JOBB ## Szövegrész jobb szélsÅ‘ karaktereit adja eredményül. +RIGHTB = JOBB2 ## Szövegrész jobb szélsÅ‘ karaktereit adja eredményül. +SEARCH = SZÖVEG.KERES ## Karaktersorozatot keres egy másikban (a kis- és nagybetűk között nem tesz különbséget). +SEARCHB = SZÖVEG.KERES2 ## Karaktersorozatot keres egy másikban (a kis- és nagybetűk között nem tesz különbséget). +SUBSTITUTE = HELYETTE ## Szövegben adott karaktereket másikra cserél. +T = T ## Argumentumát szöveggé alakítja át. +TEXT = SZÖVEG ## Számértéket alakít át adott számformátumú szöveggé. +TRIM = TRIM ## A szövegbÅ‘l eltávolítja a szóközöket. +UPPER = NAGYBETÅ°S ## Szöveget nagybetűssé alakít át. +VALUE = ÉRTÉK ## Szöveget számmá alakít át. diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/it/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/it/config new file mode 100755 index 0000000..bc81a77 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/it/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = € + + +## +## Excel Error Codes (For future use) +## +NULL = #NULLO! +DIV0 = #DIV/0! +VALUE = #VALORE! +REF = #RIF! +NAME = #NOME? +NUM = #NUM! +NA = #N/D diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/it/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/it/functions new file mode 100755 index 0000000..e7bf536 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/it/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions Funzioni di automazione e dei componenti aggiuntivi +## +GETPIVOTDATA = INFO.DATI.TAB.PIVOT ## Restituisce i dati memorizzati in un rapporto di tabella pivot + + +## +## Cube functions Funzioni cubo +## +CUBEKPIMEMBER = MEMBRO.KPI.CUBO ## Restituisce il nome, la proprietà e la misura di un indicatore di prestazioni chiave (KPI) e visualizza il nome e la proprietà nella cella. Un KPI è una misura quantificabile, ad esempio l'utile lordo mensile o il fatturato trimestrale dei dipendenti, utilizzata per il monitoraggio delle prestazioni di un'organizzazione. +CUBEMEMBER = MEMBRO.CUBO ## Restituisce un membro o una tupla in una gerarchia di cubi. Consente di verificare l'esistenza del membro o della tupla nel cubo. +CUBEMEMBERPROPERTY = PROPRIETÀ.MEMBRO.CUBO ## Restituisce il valore di una proprietà di un membro del cubo. Consente di verificare l'esistenza di un nome di membro all'interno del cubo e di restituire la proprietà specificata per tale membro. +CUBERANKEDMEMBER = MEMBRO.CUBO.CON.RANGO ## Restituisce l'n-esimo membro o il membro ordinato di un insieme. Consente di restituire uno o più elementi in un insieme, ad esempio l'agente di vendita migliore o i primi 10 studenti. +CUBESET = SET.CUBO ## Definisce un insieme di tuple o membri calcolati mediante l'invio di un'espressione di insieme al cubo sul server. In questo modo l'insieme viene creato e restituito a Microsoft Office Excel. +CUBESETCOUNT = CONTA.SET.CUBO ## Restituisce il numero di elementi di un insieme. +CUBEVALUE = VALORE.CUBO ## Restituisce un valore aggregato da un cubo. + + +## +## Database functions Funzioni di database +## +DAVERAGE = DB.MEDIA ## Restituisce la media di voci del database selezionate +DCOUNT = DB.CONTA.NUMERI ## Conta le celle di un database contenenti numeri +DCOUNTA = DB.CONTA.VALORI ## Conta le celle non vuote in un database +DGET = DB.VALORI ## Estrae da un database un singolo record che soddisfa i criteri specificati +DMAX = DB.MAX ## Restituisce il valore massimo dalle voci selezionate in un database +DMIN = DB.MIN ## Restituisce il valore minimo dalle voci di un database selezionate +DPRODUCT = DB.PRODOTTO ## Moltiplica i valori in un determinato campo di record che soddisfano i criteri del database +DSTDEV = DB.DEV.ST ## Restituisce una stima della deviazione standard sulla base di un campione di voci di un database selezionate +DSTDEVP = DB.DEV.ST.POP ## Calcola la deviazione standard sulla base di tutte le voci di un database selezionate +DSUM = DB.SOMMA ## Aggiunge i numeri nel campo colonna di record del database che soddisfa determinati criteri +DVAR = DB.VAR ## Restituisce una stima della varianza sulla base di un campione da voci di un database selezionate +DVARP = DB.VAR.POP ## Calcola la varianza sulla base di tutte le voci di un database selezionate + + +## +## Date and time functions Funzioni data e ora +## +DATE = DATA ## Restituisce il numero seriale di una determinata data +DATEVALUE = DATA.VALORE ## Converte una data sotto forma di testo in un numero seriale +DAY = GIORNO ## Converte un numero seriale in un giorno del mese +DAYS360 = GIORNO360 ## Calcola il numero di giorni compreso tra due date basandosi su un anno di 360 giorni +EDATE = DATA.MESE ## Restituisce il numero seriale della data che rappresenta il numero di mesi prima o dopo la data di inizio +EOMONTH = FINE.MESE ## Restituisce il numero seriale dell'ultimo giorno del mese, prima o dopo un determinato numero di mesi +HOUR = ORA ## Converte un numero seriale in un'ora +MINUTE = MINUTO ## Converte un numero seriale in un minuto +MONTH = MESE ## Converte un numero seriale in un mese +NETWORKDAYS = GIORNI.LAVORATIVI.TOT ## Restituisce il numero di tutti i giorni lavorativi compresi fra due date +NOW = ADESSO ## Restituisce il numero seriale della data e dell'ora corrente +SECOND = SECONDO ## Converte un numero seriale in un secondo +TIME = ORARIO ## Restituisce il numero seriale di una determinata ora +TIMEVALUE = ORARIO.VALORE ## Converte un orario in forma di testo in un numero seriale +TODAY = OGGI ## Restituisce il numero seriale relativo alla data odierna +WEEKDAY = GIORNO.SETTIMANA ## Converte un numero seriale in un giorno della settimana +WEEKNUM = NUM.SETTIMANA ## Converte un numero seriale in un numero che rappresenta la posizione numerica di una settimana nell'anno +WORKDAY = GIORNO.LAVORATIVO ## Restituisce il numero della data prima o dopo un determinato numero di giorni lavorativi +YEAR = ANNO ## Converte un numero seriale in un anno +YEARFRAC = FRAZIONE.ANNO ## Restituisce la frazione dell'anno che rappresenta il numero dei giorni compresi tra una data_ iniziale e una data_finale + + +## +## Engineering functions Funzioni ingegneristiche +## +BESSELI = BESSEL.I ## Restituisce la funzione di Bessel modificata In(x) +BESSELJ = BESSEL.J ## Restituisce la funzione di Bessel Jn(x) +BESSELK = BESSEL.K ## Restituisce la funzione di Bessel modificata Kn(x) +BESSELY = BESSEL.Y ## Restituisce la funzione di Bessel Yn(x) +BIN2DEC = BINARIO.DECIMALE ## Converte un numero binario in decimale +BIN2HEX = BINARIO.HEX ## Converte un numero binario in esadecimale +BIN2OCT = BINARIO.OCT ## Converte un numero binario in ottale +COMPLEX = COMPLESSO ## Converte i coefficienti reali e immaginari in numeri complessi +CONVERT = CONVERTI ## Converte un numero da un sistema di misura in un altro +DEC2BIN = DECIMALE.BINARIO ## Converte un numero decimale in binario +DEC2HEX = DECIMALE.HEX ## Converte un numero decimale in esadecimale +DEC2OCT = DECIMALE.OCT ## Converte un numero decimale in ottale +DELTA = DELTA ## Verifica se due valori sono uguali +ERF = FUNZ.ERRORE ## Restituisce la funzione di errore +ERFC = FUNZ.ERRORE.COMP ## Restituisce la funzione di errore complementare +GESTEP = SOGLIA ## Verifica se un numero è maggiore del valore di soglia +HEX2BIN = HEX.BINARIO ## Converte un numero esadecimale in binario +HEX2DEC = HEX.DECIMALE ## Converte un numero esadecimale in decimale +HEX2OCT = HEX.OCT ## Converte un numero esadecimale in ottale +IMABS = COMP.MODULO ## Restituisce il valore assoluto (modulo) di un numero complesso +IMAGINARY = COMP.IMMAGINARIO ## Restituisce il coefficiente immaginario di un numero complesso +IMARGUMENT = COMP.ARGOMENTO ## Restituisce l'argomento theta, un angolo espresso in radianti +IMCONJUGATE = COMP.CONIUGATO ## Restituisce il complesso coniugato del numero complesso +IMCOS = COMP.COS ## Restituisce il coseno di un numero complesso +IMDIV = COMP.DIV ## Restituisce il quoziente di due numeri complessi +IMEXP = COMP.EXP ## Restituisce il valore esponenziale di un numero complesso +IMLN = COMP.LN ## Restituisce il logaritmo naturale di un numero complesso +IMLOG10 = COMP.LOG10 ## Restituisce il logaritmo in base 10 di un numero complesso +IMLOG2 = COMP.LOG2 ## Restituisce un logaritmo in base 2 di un numero complesso +IMPOWER = COMP.POTENZA ## Restituisce il numero complesso elevato a una potenza intera +IMPRODUCT = COMP.PRODOTTO ## Restituisce il prodotto di numeri complessi compresi tra 2 e 29 +IMREAL = COMP.PARTE.REALE ## Restituisce il coefficiente reale di un numero complesso +IMSIN = COMP.SEN ## Restituisce il seno di un numero complesso +IMSQRT = COMP.RADQ ## Restituisce la radice quadrata di un numero complesso +IMSUB = COMP.DIFF ## Restituisce la differenza fra due numeri complessi +IMSUM = COMP.SOMMA ## Restituisce la somma di numeri complessi +OCT2BIN = OCT.BINARIO ## Converte un numero ottale in binario +OCT2DEC = OCT.DECIMALE ## Converte un numero ottale in decimale +OCT2HEX = OCT.HEX ## Converte un numero ottale in esadecimale + + +## +## Financial functions Funzioni finanziarie +## +ACCRINT = INT.MATURATO.PER ## Restituisce l'interesse maturato di un titolo che paga interessi periodici +ACCRINTM = INT.MATURATO.SCAD ## Restituisce l'interesse maturato di un titolo che paga interessi alla scadenza +AMORDEGRC = AMMORT.DEGR ## Restituisce l'ammortamento per ogni periodo contabile utilizzando un coefficiente di ammortamento +AMORLINC = AMMORT.PER ## Restituisce l'ammortamento per ogni periodo contabile +COUPDAYBS = GIORNI.CED.INIZ.LIQ ## Restituisce il numero dei giorni che vanno dall'inizio del periodo di durata della cedola alla data di liquidazione +COUPDAYS = GIORNI.CED ## Restituisce il numero dei giorni relativi al periodo della cedola che contiene la data di liquidazione +COUPDAYSNC = GIORNI.CED.NUOVA ## Restituisce il numero di giorni che vanno dalla data di liquidazione alla data della cedola successiva +COUPNCD = DATA.CED.SUCC ## Restituisce un numero che rappresenta la data della cedola successiva alla data di liquidazione +COUPNUM = NUM.CED ## Restituisce il numero di cedole pagabili fra la data di liquidazione e la data di scadenza +COUPPCD = DATA.CED.PREC ## Restituisce un numero che rappresenta la data della cedola precedente alla data di liquidazione +CUMIPMT = INT.CUMUL ## Restituisce l'interesse cumulativo pagato fra due periodi +CUMPRINC = CAP.CUM ## Restituisce il capitale cumulativo pagato per estinguere un debito fra due periodi +DB = DB ## Restituisce l'ammortamento di un bene per un periodo specificato utilizzando il metodo di ammortamento a quote fisse decrescenti +DDB = AMMORT ## Restituisce l'ammortamento di un bene per un periodo specificato utilizzando il metodo di ammortamento a doppie quote decrescenti o altri metodi specificati +DISC = TASSO.SCONTO ## Restituisce il tasso di sconto per un titolo +DOLLARDE = VALUTA.DEC ## Converte un prezzo valuta, espresso come frazione, in prezzo valuta, espresso come numero decimale +DOLLARFR = VALUTA.FRAZ ## Converte un prezzo valuta, espresso come numero decimale, in prezzo valuta, espresso come frazione +DURATION = DURATA ## Restituisce la durata annuale di un titolo con i pagamenti di interesse periodico +EFFECT = EFFETTIVO ## Restituisce l'effettivo tasso di interesse annuo +FV = VAL.FUT ## Restituisce il valore futuro di un investimento +FVSCHEDULE = VAL.FUT.CAPITALE ## Restituisce il valore futuro di un capitale iniziale dopo aver applicato una serie di tassi di interesse composti +INTRATE = TASSO.INT ## Restituisce il tasso di interesse per un titolo interamente investito +IPMT = INTERESSI ## Restituisce il valore degli interessi per un investimento relativo a un periodo specifico +IRR = TIR.COST ## Restituisce il tasso di rendimento interno per una serie di flussi di cassa +ISPMT = INTERESSE.RATA ## Calcola l'interesse di un investimento pagato durante un periodo specifico +MDURATION = DURATA.M ## Restituisce la durata Macauley modificata per un titolo con un valore presunto di € 100 +MIRR = TIR.VAR ## Restituisce il tasso di rendimento interno in cui i flussi di cassa positivi e negativi sono finanziati a tassi differenti +NOMINAL = NOMINALE ## Restituisce il tasso di interesse nominale annuale +NPER = NUM.RATE ## Restituisce un numero di periodi relativi a un investimento +NPV = VAN ## Restituisce il valore attuale netto di un investimento basato su una serie di flussi di cassa periodici e sul tasso di sconto +ODDFPRICE = PREZZO.PRIMO.IRR ## Restituisce il prezzo di un titolo dal valore nominale di € 100 avente il primo periodo di durata irregolare +ODDFYIELD = REND.PRIMO.IRR ## Restituisce il rendimento di un titolo avente il primo periodo di durata irregolare +ODDLPRICE = PREZZO.ULTIMO.IRR ## Restituisce il prezzo di un titolo dal valore nominale di € 100 avente l'ultimo periodo di durata irregolare +ODDLYIELD = REND.ULTIMO.IRR ## Restituisce il rendimento di un titolo avente l'ultimo periodo di durata irregolare +PMT = RATA ## Restituisce il pagamento periodico di una rendita annua +PPMT = P.RATA ## Restituisce il pagamento sul capitale di un investimento per un dato periodo +PRICE = PREZZO ## Restituisce il prezzo di un titolo dal valore nominale di € 100 che paga interessi periodici +PRICEDISC = PREZZO.SCONT ## Restituisce il prezzo di un titolo scontato dal valore nominale di € 100 +PRICEMAT = PREZZO.SCAD ## Restituisce il prezzo di un titolo dal valore nominale di € 100 che paga gli interessi alla scadenza +PV = VA ## Restituisce il valore attuale di un investimento +RATE = TASSO ## Restituisce il tasso di interesse per un periodo di un'annualità +RECEIVED = RICEV.SCAD ## Restituisce l'ammontare ricevuto alla scadenza di un titolo interamente investito +SLN = AMMORT.COST ## Restituisce l'ammortamento a quote costanti di un bene per un singolo periodo +SYD = AMMORT.ANNUO ## Restituisce l'ammortamento a somma degli anni di un bene per un periodo specificato +TBILLEQ = BOT.EQUIV ## Restituisce il rendimento equivalente ad un'obbligazione per un Buono ordinario del Tesoro +TBILLPRICE = BOT.PREZZO ## Restituisce il prezzo di un Buono del Tesoro dal valore nominale di € 100 +TBILLYIELD = BOT.REND ## Restituisce il rendimento di un Buono del Tesoro +VDB = AMMORT.VAR ## Restituisce l'ammortamento di un bene per un periodo specificato o parziale utilizzando il metodo a doppie quote proporzionali ai valori residui +XIRR = TIR.X ## Restituisce il tasso di rendimento interno di un impiego di flussi di cassa +XNPV = VAN.X ## Restituisce il valore attuale netto di un impiego di flussi di cassa non necessariamente periodici +YIELD = REND ## Restituisce il rendimento di un titolo che frutta interessi periodici +YIELDDISC = REND.TITOLI.SCONT ## Restituisce il rendimento annuale di un titolo scontato, ad esempio un Buono del Tesoro +YIELDMAT = REND.SCAD ## Restituisce il rendimento annuo di un titolo che paga interessi alla scadenza + + +## +## Information functions Funzioni relative alle informazioni +## +CELL = CELLA ## Restituisce le informazioni sulla formattazione, la posizione o i contenuti di una cella +ERROR.TYPE = ERRORE.TIPO ## Restituisce un numero che corrisponde a un tipo di errore +INFO = INFO ## Restituisce le informazioni sull'ambiente operativo corrente +ISBLANK = VAL.VUOTO ## Restituisce VERO se il valore è vuoto +ISERR = VAL.ERR ## Restituisce VERO se il valore è un valore di errore qualsiasi tranne #N/D +ISERROR = VAL.ERRORE ## Restituisce VERO se il valore è un valore di errore qualsiasi +ISEVEN = VAL.PARI ## Restituisce VERO se il numero è pari +ISLOGICAL = VAL.LOGICO ## Restituisce VERO se il valore è un valore logico +ISNA = VAL.NON.DISP ## Restituisce VERO se il valore è un valore di errore #N/D +ISNONTEXT = VAL.NON.TESTO ## Restituisce VERO se il valore non è in formato testo +ISNUMBER = VAL.NUMERO ## Restituisce VERO se il valore è un numero +ISODD = VAL.DISPARI ## Restituisce VERO se il numero è dispari +ISREF = VAL.RIF ## Restituisce VERO se il valore è un riferimento +ISTEXT = VAL.TESTO ## Restituisce VERO se il valore è in formato testo +N = NUM ## Restituisce un valore convertito in numero +NA = NON.DISP ## Restituisce il valore di errore #N/D +TYPE = TIPO ## Restituisce un numero che indica il tipo di dati relativi a un valore + + +## +## Logical functions Funzioni logiche +## +AND = E ## Restituisce VERO se tutti gli argomenti sono VERO +FALSE = FALSO ## Restituisce il valore logico FALSO +IF = SE ## Specifica un test logico da eseguire +IFERROR = SE.ERRORE ## Restituisce un valore specificato se una formula fornisce un errore come risultato; in caso contrario, restituisce il risultato della formula +NOT = NON ## Inverte la logica degli argomenti +OR = O ## Restituisce VERO se un argomento qualsiasi è VERO +TRUE = VERO ## Restituisce il valore logico VERO + + +## +## Lookup and reference functions Funzioni di ricerca e di riferimento +## +ADDRESS = INDIRIZZO ## Restituisce un riferimento come testo in una singola cella di un foglio di lavoro +AREAS = AREE ## Restituisce il numero di aree in un riferimento +CHOOSE = SCEGLI ## Sceglie un valore da un elenco di valori +COLUMN = RIF.COLONNA ## Restituisce il numero di colonna di un riferimento +COLUMNS = COLONNE ## Restituisce il numero di colonne in un riferimento +HLOOKUP = CERCA.ORIZZ ## Effettua una ricerca nella riga superiore di una matrice e restituisce il valore della cella specificata +HYPERLINK = COLLEG.IPERTESTUALE ## Crea un collegamento che apre un documento memorizzato in un server di rete, una rete Intranet o Internet +INDEX = INDICE ## Utilizza un indice per scegliere un valore da un riferimento o da una matrice +INDIRECT = INDIRETTO ## Restituisce un riferimento specificato da un valore testo +LOOKUP = CERCA ## Ricerca i valori in un vettore o in una matrice +MATCH = CONFRONTA ## Ricerca i valori in un riferimento o in una matrice +OFFSET = SCARTO ## Restituisce uno scarto di riferimento da un riferimento dato +ROW = RIF.RIGA ## Restituisce il numero di riga di un riferimento +ROWS = RIGHE ## Restituisce il numero delle righe in un riferimento +RTD = DATITEMPOREALE ## Recupera dati in tempo reale da un programma che supporta l'automazione COM (automazione: Metodo per utilizzare gli oggetti di un'applicazione da un'altra applicazione o da un altro strumento di sviluppo. Precedentemente nota come automazione OLE, l'automazione è uno standard del settore e una caratteristica del modello COM (Component Object Model).) +TRANSPOSE = MATR.TRASPOSTA ## Restituisce la trasposizione di una matrice +VLOOKUP = CERCA.VERT ## Effettua una ricerca nella prima colonna di una matrice e si sposta attraverso la riga per restituire il valore di una cella + + +## +## Math and trigonometry functions Funzioni matematiche e trigonometriche +## +ABS = ASS ## Restituisce il valore assoluto di un numero. +ACOS = ARCCOS ## Restituisce l'arcocoseno di un numero +ACOSH = ARCCOSH ## Restituisce l'inverso del coseno iperbolico di un numero +ASIN = ARCSEN ## Restituisce l'arcoseno di un numero +ASINH = ARCSENH ## Restituisce l'inverso del seno iperbolico di un numero +ATAN = ARCTAN ## Restituisce l'arcotangente di un numero +ATAN2 = ARCTAN.2 ## Restituisce l'arcotangente delle coordinate x e y specificate +ATANH = ARCTANH ## Restituisce l'inverso della tangente iperbolica di un numero +CEILING = ARROTONDA.ECCESSO ## Arrotonda un numero per eccesso all'intero più vicino o al multiplo più vicino a peso +COMBIN = COMBINAZIONE ## Restituisce il numero di combinazioni possibili per un numero assegnato di elementi +COS = COS ## Restituisce il coseno dell'angolo specificato +COSH = COSH ## Restituisce il coseno iperbolico di un numero +DEGREES = GRADI ## Converte i radianti in gradi +EVEN = PARI ## Arrotonda il valore assoluto di un numero per eccesso al più vicino intero pari +EXP = ESP ## Restituisce il numero e elevato alla potenza di num +FACT = FATTORIALE ## Restituisce il fattoriale di un numero +FACTDOUBLE = FATT.DOPPIO ## Restituisce il fattoriale doppio di un numero +FLOOR = ARROTONDA.DIFETTO ## Arrotonda un numero per difetto al multiplo più vicino a zero +GCD = MCD ## Restituisce il massimo comune divisore +INT = INT ## Arrotonda un numero per difetto al numero intero più vicino +LCM = MCM ## Restituisce il minimo comune multiplo +LN = LN ## Restituisce il logaritmo naturale di un numero +LOG = LOG ## Restituisce il logaritmo di un numero in una specificata base +LOG10 = LOG10 ## Restituisce il logaritmo in base 10 di un numero +MDETERM = MATR.DETERM ## Restituisce il determinante di una matrice +MINVERSE = MATR.INVERSA ## Restituisce l'inverso di una matrice +MMULT = MATR.PRODOTTO ## Restituisce il prodotto di due matrici +MOD = RESTO ## Restituisce il resto della divisione +MROUND = ARROTONDA.MULTIPLO ## Restituisce un numero arrotondato al multiplo desiderato +MULTINOMIAL = MULTINOMIALE ## Restituisce il multinomiale di un insieme di numeri +ODD = DISPARI ## Arrotonda un numero per eccesso al più vicino intero dispari +PI = PI.GRECO ## Restituisce il valore di pi greco +POWER = POTENZA ## Restituisce il risultato di un numero elevato a potenza +PRODUCT = PRODOTTO ## Moltiplica i suoi argomenti +QUOTIENT = QUOZIENTE ## Restituisce la parte intera di una divisione +RADIANS = RADIANTI ## Converte i gradi in radianti +RAND = CASUALE ## Restituisce un numero casuale compreso tra 0 e 1 +RANDBETWEEN = CASUALE.TRA ## Restituisce un numero casuale compreso tra i numeri specificati +ROMAN = ROMANO ## Restituisce il numero come numero romano sotto forma di testo +ROUND = ARROTONDA ## Arrotonda il numero al numero di cifre specificato +ROUNDDOWN = ARROTONDA.PER.DIF ## Arrotonda il valore assoluto di un numero per difetto +ROUNDUP = ARROTONDA.PER.ECC ## Arrotonda il valore assoluto di un numero per eccesso +SERIESSUM = SOMMA.SERIE ## Restituisce la somma di una serie di potenze in base alla formula +SIGN = SEGNO ## Restituisce il segno di un numero +SIN = SEN ## Restituisce il seno di un dato angolo +SINH = SENH ## Restituisce il seno iperbolico di un numero +SQRT = RADQ ## Restituisce una radice quadrata +SQRTPI = RADQ.PI.GRECO ## Restituisce la radice quadrata di un numero (numero * pi greco) +SUBTOTAL = SUBTOTALE ## Restituisce un subtotale in un elenco o in un database +SUM = SOMMA ## Somma i suoi argomenti +SUMIF = SOMMA.SE ## Somma le celle specificate da un dato criterio +SUMIFS = SOMMA.PIÙ.SE ## Somma le celle in un intervallo che soddisfano più criteri +SUMPRODUCT = MATR.SOMMA.PRODOTTO ## Restituisce la somma dei prodotti dei componenti corrispondenti della matrice +SUMSQ = SOMMA.Q ## Restituisce la somma dei quadrati degli argomenti +SUMX2MY2 = SOMMA.DIFF.Q ## Restituisce la somma della differenza dei quadrati dei corrispondenti elementi in due matrici +SUMX2PY2 = SOMMA.SOMMA.Q ## Restituisce la somma della somma dei quadrati dei corrispondenti elementi in due matrici +SUMXMY2 = SOMMA.Q.DIFF ## Restituisce la somma dei quadrati delle differenze dei corrispondenti elementi in due matrici +TAN = TAN ## Restituisce la tangente di un numero +TANH = TANH ## Restituisce la tangente iperbolica di un numero +TRUNC = TRONCA ## Tronca la parte decimale di un numero + + +## +## Statistical functions Funzioni statistiche +## +AVEDEV = MEDIA.DEV ## Restituisce la media delle deviazioni assolute delle coordinate rispetto alla loro media +AVERAGE = MEDIA ## Restituisce la media degli argomenti +AVERAGEA = MEDIA.VALORI ## Restituisce la media degli argomenti, inclusi i numeri, il testo e i valori logici +AVERAGEIF = MEDIA.SE ## Restituisce la media aritmetica di tutte le celle in un intervallo che soddisfano un determinato criterio +AVERAGEIFS = MEDIA.PIÙ.SE ## Restituisce la media aritmetica di tutte le celle che soddisfano più criteri +BETADIST = DISTRIB.BETA ## Restituisce la funzione di distribuzione cumulativa beta +BETAINV = INV.BETA ## Restituisce l'inverso della funzione di distribuzione cumulativa per una distribuzione beta specificata +BINOMDIST = DISTRIB.BINOM ## Restituisce la distribuzione binomiale per il termine individuale +CHIDIST = DISTRIB.CHI ## Restituisce la probabilità a una coda per la distribuzione del chi quadrato +CHIINV = INV.CHI ## Restituisce l'inverso della probabilità ad una coda per la distribuzione del chi quadrato +CHITEST = TEST.CHI ## Restituisce il test per l'indipendenza +CONFIDENCE = CONFIDENZA ## Restituisce l'intervallo di confidenza per una popolazione +CORREL = CORRELAZIONE ## Restituisce il coefficiente di correlazione tra due insiemi di dati +COUNT = CONTA.NUMERI ## Conta la quantità di numeri nell'elenco di argomenti +COUNTA = CONTA.VALORI ## Conta il numero di valori nell'elenco di argomenti +COUNTBLANK = CONTA.VUOTE ## Conta il numero di celle vuote all'interno di un intervallo +COUNTIF = CONTA.SE ## Conta il numero di celle all'interno di un intervallo che soddisfa i criteri specificati +COUNTIFS = CONTA.PIÙ.SE ## Conta il numero di celle in un intervallo che soddisfano più criteri. +COVAR = COVARIANZA ## Calcola la covarianza, la media dei prodotti delle deviazioni accoppiate +CRITBINOM = CRIT.BINOM ## Restituisce il più piccolo valore per il quale la distribuzione cumulativa binomiale risulta maggiore o uguale ad un valore di criterio +DEVSQ = DEV.Q ## Restituisce la somma dei quadrati delle deviazioni +EXPONDIST = DISTRIB.EXP ## Restituisce la distribuzione esponenziale +FDIST = DISTRIB.F ## Restituisce la distribuzione di probabilità F +FINV = INV.F ## Restituisce l'inverso della distribuzione della probabilità F +FISHER = FISHER ## Restituisce la trasformazione di Fisher +FISHERINV = INV.FISHER ## Restituisce l'inverso della trasformazione di Fisher +FORECAST = PREVISIONE ## Restituisce i valori lungo una tendenza lineare +FREQUENCY = FREQUENZA ## Restituisce la distribuzione di frequenza come matrice verticale +FTEST = TEST.F ## Restituisce il risultato di un test F +GAMMADIST = DISTRIB.GAMMA ## Restituisce la distribuzione gamma +GAMMAINV = INV.GAMMA ## Restituisce l'inverso della distribuzione cumulativa gamma +GAMMALN = LN.GAMMA ## Restituisce il logaritmo naturale della funzione gamma, G(x) +GEOMEAN = MEDIA.GEOMETRICA ## Restituisce la media geometrica +GROWTH = CRESCITA ## Restituisce i valori lungo una linea di tendenza esponenziale +HARMEAN = MEDIA.ARMONICA ## Restituisce la media armonica +HYPGEOMDIST = DISTRIB.IPERGEOM ## Restituisce la distribuzione ipergeometrica +INTERCEPT = INTERCETTA ## Restituisce l'intercetta della retta di regressione lineare +KURT = CURTOSI ## Restituisce la curtosi di un insieme di dati +LARGE = GRANDE ## Restituisce il k-esimo valore più grande in un insieme di dati +LINEST = REGR.LIN ## Restituisce i parametri di una tendenza lineare +LOGEST = REGR.LOG ## Restituisce i parametri di una linea di tendenza esponenziale +LOGINV = INV.LOGNORM ## Restituisce l'inverso di una distribuzione lognormale +LOGNORMDIST = DISTRIB.LOGNORM ## Restituisce la distribuzione lognormale cumulativa +MAX = MAX ## Restituisce il valore massimo in un elenco di argomenti +MAXA = MAX.VALORI ## Restituisce il valore massimo in un elenco di argomenti, inclusi i numeri, il testo e i valori logici +MEDIAN = MEDIANA ## Restituisce la mediana dei numeri specificati +MIN = MIN ## Restituisce il valore minimo in un elenco di argomenti +MINA = MIN.VALORI ## Restituisce il più piccolo valore in un elenco di argomenti, inclusi i numeri, il testo e i valori logici +MODE = MODA ## Restituisce il valore più comune in un insieme di dati +NEGBINOMDIST = DISTRIB.BINOM.NEG ## Restituisce la distribuzione binomiale negativa +NORMDIST = DISTRIB.NORM ## Restituisce la distribuzione cumulativa normale +NORMINV = INV.NORM ## Restituisce l'inverso della distribuzione cumulativa normale standard +NORMSDIST = DISTRIB.NORM.ST ## Restituisce la distribuzione cumulativa normale standard +NORMSINV = INV.NORM.ST ## Restituisce l'inverso della distribuzione cumulativa normale +PEARSON = PEARSON ## Restituisce il coefficiente del momento di correlazione di Pearson +PERCENTILE = PERCENTILE ## Restituisce il k-esimo dato percentile di valori in un intervallo +PERCENTRANK = PERCENT.RANGO ## Restituisce il rango di un valore in un insieme di dati come percentuale +PERMUT = PERMUTAZIONE ## Restituisce il numero delle permutazioni per un determinato numero di oggetti +POISSON = POISSON ## Restituisce la distribuzione di Poisson +PROB = PROBABILITÀ ## Calcola la probabilità che dei valori in un intervallo siano compresi tra due limiti +QUARTILE = QUARTILE ## Restituisce il quartile di un insieme di dati +RANK = RANGO ## Restituisce il rango di un numero in un elenco di numeri +RSQ = RQ ## Restituisce la radice quadrata del coefficiente di momento di correlazione di Pearson +SKEW = ASIMMETRIA ## Restituisce il grado di asimmetria di una distribuzione +SLOPE = PENDENZA ## Restituisce la pendenza di una retta di regressione lineare +SMALL = PICCOLO ## Restituisce il k-esimo valore più piccolo in un insieme di dati +STANDARDIZE = NORMALIZZA ## Restituisce un valore normalizzato +STDEV = DEV.ST ## Restituisce una stima della deviazione standard sulla base di un campione +STDEVA = DEV.ST.VALORI ## Restituisce una stima della deviazione standard sulla base di un campione, inclusi i numeri, il testo e i valori logici +STDEVP = DEV.ST.POP ## Calcola la deviazione standard sulla base di un'intera popolazione +STDEVPA = DEV.ST.POP.VALORI ## Calcola la deviazione standard sulla base sull'intera popolazione, inclusi i numeri, il testo e i valori logici +STEYX = ERR.STD.YX ## Restituisce l'errore standard del valore previsto per y per ogni valore x nella regressione +TDIST = DISTRIB.T ## Restituisce la distribuzione t di Student +TINV = INV.T ## Restituisce l'inversa della distribuzione t di Student +TREND = TENDENZA ## Restituisce i valori lungo una linea di tendenza lineare +TRIMMEAN = MEDIA.TRONCATA ## Restituisce la media della parte interna di un insieme di dati +TTEST = TEST.T ## Restituisce la probabilità associata ad un test t di Student +VAR = VAR ## Stima la varianza sulla base di un campione +VARA = VAR.VALORI ## Stima la varianza sulla base di un campione, inclusi i numeri, il testo e i valori logici +VARP = VAR.POP ## Calcola la varianza sulla base dell'intera popolazione +VARPA = VAR.POP.VALORI ## Calcola la deviazione standard sulla base sull'intera popolazione, inclusi i numeri, il testo e i valori logici +WEIBULL = WEIBULL ## Restituisce la distribuzione di Weibull +ZTEST = TEST.Z ## Restituisce il valore di probabilità a una coda per un test z + + +## +## Text functions Funzioni di testo +## +ASC = ASC ## Modifica le lettere inglesi o il katakana a doppio byte all'interno di una stringa di caratteri in caratteri a singolo byte +BAHTTEXT = BAHTTESTO ## Converte un numero in testo, utilizzando il formato valuta ß (baht) +CHAR = CODICE.CARATT ## Restituisce il carattere specificato dal numero di codice +CLEAN = LIBERA ## Elimina dal testo tutti i caratteri che non è possibile stampare +CODE = CODICE ## Restituisce il codice numerico del primo carattere di una stringa di testo +CONCATENATE = CONCATENA ## Unisce diversi elementi di testo in un unico elemento di testo +DOLLAR = VALUTA ## Converte un numero in testo, utilizzando il formato valuta € (euro) +EXACT = IDENTICO ## Verifica se due valori di testo sono uguali +FIND = TROVA ## Rileva un valore di testo all'interno di un altro (distinzione tra maiuscole e minuscole) +FINDB = TROVA.B ## Rileva un valore di testo all'interno di un altro (distinzione tra maiuscole e minuscole) +FIXED = FISSO ## Formatta un numero come testo con un numero fisso di decimali +JIS = ORDINAMENTO.JIS ## Modifica le lettere inglesi o i caratteri katakana a byte singolo all'interno di una stringa di caratteri in caratteri a byte doppio. +LEFT = SINISTRA ## Restituisce il carattere più a sinistra di un valore di testo +LEFTB = SINISTRA.B ## Restituisce il carattere più a sinistra di un valore di testo +LEN = LUNGHEZZA ## Restituisce il numero di caratteri di una stringa di testo +LENB = LUNB ## Restituisce il numero di caratteri di una stringa di testo +LOWER = MINUSC ## Converte il testo in lettere minuscole +MID = MEDIA ## Restituisce un numero specifico di caratteri di una stringa di testo a partire dalla posizione specificata +MIDB = MEDIA.B ## Restituisce un numero specifico di caratteri di una stringa di testo a partire dalla posizione specificata +PHONETIC = FURIGANA ## Estrae i caratteri fonetici (furigana) da una stringa di testo. +PROPER = MAIUSC.INIZ ## Converte in maiuscolo la prima lettera di ogni parola di un valore di testo +REPLACE = RIMPIAZZA ## Sostituisce i caratteri all'interno di un testo +REPLACEB = SOSTITUISCI.B ## Sostituisce i caratteri all'interno di un testo +REPT = RIPETI ## Ripete un testo per un dato numero di volte +RIGHT = DESTRA ## Restituisce il carattere più a destra di un valore di testo +RIGHTB = DESTRA.B ## Restituisce il carattere più a destra di un valore di testo +SEARCH = RICERCA ## Rileva un valore di testo all'interno di un altro (non è sensibile alle maiuscole e minuscole) +SEARCHB = CERCA.B ## Rileva un valore di testo all'interno di un altro (non è sensibile alle maiuscole e minuscole) +SUBSTITUTE = SOSTITUISCI ## Sostituisce il nuovo testo al testo contenuto in una stringa +T = T ## Converte gli argomenti in testo +TEXT = TESTO ## Formatta un numero e lo converte in testo +TRIM = ANNULLA.SPAZI ## Elimina gli spazi dal testo +UPPER = MAIUSC ## Converte il testo in lettere maiuscole +VALUE = VALORE ## Converte un argomento di testo in numero diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/nl/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/nl/config new file mode 100755 index 0000000..5d1b155 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/nl/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = € + + +## +## Excel Error Codes (For future use) +## +NULL = #LEEG! +DIV0 = #DEEL/0! +VALUE = #WAARDE! +REF = #VERW! +NAME = #NAAM? +NUM = #GETAL! +NA = #N/B diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/nl/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/nl/functions new file mode 100755 index 0000000..62a38c4 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/nl/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions Automatiseringsfuncties en functies in invoegtoepassingen +## +GETPIVOTDATA = DRAAITABEL.OPHALEN ## Geeft gegevens uit een draaitabelrapport als resultaat + + +## +## Cube functions Kubusfuncties +## +CUBEKPIMEMBER = KUBUSKPILID ## Retourneert de naam, eigenschap en waarde van een KPI (prestatie-indicator) en geeft de naam en de eigenschap in de cel weer. Een KPI is een meetbare waarde, zoals de maandelijkse brutowinst of de omzet per kwartaal per werknemer, die wordt gebruikt om de prestaties van een organisatie te bewaken +CUBEMEMBER = KUBUSLID ## Retourneert een lid of tupel in een kubushiërarchie. Wordt gebruikt om te controleren of het lid of de tupel in de kubus aanwezig is +CUBEMEMBERPROPERTY = KUBUSLIDEIGENSCHAP ## Retourneert de waarde van een lideigenschap in de kubus. Wordt gebruikt om te controleren of de lidnaam in de kubus bestaat en retourneert de opgegeven eigenschap voor dit lid +CUBERANKEDMEMBER = KUBUSGERANGCHIKTLID ## Retourneert het zoveelste, gerangschikte lid in een set. Wordt gebruikt om een of meer elementen in een set te retourneren, zoals de tien beste verkopers of de tien beste studenten +CUBESET = KUBUSSET ## Definieert een berekende set leden of tupels door een ingestelde expressie naar de kubus op de server te sturen, alwaar de set wordt gemaakt en vervolgens wordt geretourneerd naar Microsoft Office Excel +CUBESETCOUNT = KUBUSSETAANTAL ## Retourneert het aantal onderdelen in een set +CUBEVALUE = KUBUSWAARDE ## Retourneert een samengestelde waarde van een kubus + + +## +## Database functions Databasefuncties +## +DAVERAGE = DBGEMIDDELDE ## Berekent de gemiddelde waarde in geselecteerde databasegegevens +DCOUNT = DBAANTAL ## Telt de cellen met getallen in een database +DCOUNTA = DBAANTALC ## Telt de niet-lege cellen in een database +DGET = DBLEZEN ## Retourneert één record dat voldoet aan de opgegeven criteria uit een database +DMAX = DBMAX ## Retourneert de maximumwaarde in de geselecteerde databasegegevens +DMIN = DBMIN ## Retourneert de minimumwaarde in de geselecteerde databasegegevens +DPRODUCT = DBPRODUCT ## Vermenigvuldigt de waarden in een bepaald veld van de records die voldoen aan de criteria in een database +DSTDEV = DBSTDEV ## Maakt een schatting van de standaarddeviatie op basis van een steekproef uit geselecteerde databasegegevens +DSTDEVP = DBSTDEVP ## Berekent de standaarddeviatie op basis van de volledige populatie van geselecteerde databasegegevens +DSUM = DBSOM ## Telt de getallen uit een kolom records in de database op die voldoen aan de criteria +DVAR = DBVAR ## Maakt een schatting van de variantie op basis van een steekproef uit geselecteerde databasegegevens +DVARP = DBVARP ## Berekent de variantie op basis van de volledige populatie van geselecteerde databasegegevens + + +## +## Date and time functions Datum- en tijdfuncties +## +DATE = DATUM ## Geeft als resultaat het seriële getal van een opgegeven datum +DATEVALUE = DATUMWAARDE ## Converteert een datum in de vorm van tekst naar een serieel getal +DAY = DAG ## Converteert een serieel getal naar een dag van de maand +DAYS360 = DAGEN360 ## Berekent het aantal dagen tussen twee datums op basis van een jaar met 360 dagen +EDATE = ZELFDE.DAG ## Geeft als resultaat het seriële getal van een datum die het opgegeven aantal maanden voor of na de begindatum ligt +EOMONTH = LAATSTE.DAG ## Geeft als resultaat het seriële getal van de laatste dag van de maand voor of na het opgegeven aantal maanden +HOUR = UUR ## Converteert een serieel getal naar uren +MINUTE = MINUUT ## Converteert een serieel naar getal minuten +MONTH = MAAND ## Converteert een serieel getal naar een maand +NETWORKDAYS = NETTO.WERKDAGEN ## Geeft als resultaat het aantal hele werkdagen tussen twee datums +NOW = NU ## Geeft als resultaat het seriële getal van de huidige datum en tijd +SECOND = SECONDE ## Converteert een serieel getal naar seconden +TIME = TIJD ## Geeft als resultaat het seriële getal van een bepaald tijdstip +TIMEVALUE = TIJDWAARDE ## Converteert de tijd in de vorm van tekst naar een serieel getal +TODAY = VANDAAG ## Geeft als resultaat het seriële getal van de huidige datum +WEEKDAY = WEEKDAG ## Converteert een serieel getal naar een weekdag +WEEKNUM = WEEKNUMMER ## Converteert een serieel getal naar een weeknummer +WORKDAY = WERKDAG ## Geeft als resultaat het seriële getal van de datum voor of na een bepaald aantal werkdagen +YEAR = JAAR ## Converteert een serieel getal naar een jaar +YEARFRAC = JAAR.DEEL ## Geeft als resultaat het gedeelte van het jaar, uitgedrukt in het aantal hele dagen tussen begindatum en einddatum + + +## +## Engineering functions Technische functies +## +BESSELI = BESSEL.Y ## Geeft als resultaat de gewijzigde Bessel-functie In(x) +BESSELJ = BESSEL.J ## Geeft als resultaat de Bessel-functie Jn(x) +BESSELK = BESSEL.K ## Geeft als resultaat de gewijzigde Bessel-functie Kn(x) +BESSELY = BESSEL.Y ## Geeft als resultaat de gewijzigde Bessel-functie Yn(x) +BIN2DEC = BIN.N.DEC ## Converteert een binair getal naar een decimaal getal +BIN2HEX = BIN.N.HEX ## Converteert een binair getal naar een hexadecimaal getal +BIN2OCT = BIN.N.OCT ## Converteert een binair getal naar een octaal getal +COMPLEX = COMPLEX ## Converteert reële en imaginaire coëfficiënten naar een complex getal +CONVERT = CONVERTEREN ## Converteert een getal in de ene maateenheid naar een getal in een andere maateenheid +DEC2BIN = DEC.N.BIN ## Converteert een decimaal getal naar een binair getal +DEC2HEX = DEC.N.HEX ## Converteert een decimaal getal naar een hexadecimaal getal +DEC2OCT = DEC.N.OCT ## Converteert een decimaal getal naar een octaal getal +DELTA = DELTA ## Test of twee waarden gelijk zijn +ERF = FOUTFUNCTIE ## Geeft als resultaat de foutfunctie +ERFC = FOUT.COMPLEMENT ## Geeft als resultaat de complementaire foutfunctie +GESTEP = GROTER.DAN ## Test of een getal groter is dan de drempelwaarde +HEX2BIN = HEX.N.BIN ## Converteert een hexadecimaal getal naar een binair getal +HEX2DEC = HEX.N.DEC ## Converteert een hexadecimaal getal naar een decimaal getal +HEX2OCT = HEX.N.OCT ## Converteert een hexadecimaal getal naar een octaal getal +IMABS = C.ABS ## Geeft als resultaat de absolute waarde (modulus) van een complex getal +IMAGINARY = C.IM.DEEL ## Geeft als resultaat de imaginaire coëfficiënt van een complex getal +IMARGUMENT = C.ARGUMENT ## Geeft als resultaat het argument thèta, een hoek uitgedrukt in radialen +IMCONJUGATE = C.TOEGEVOEGD ## Geeft als resultaat het complexe toegevoegde getal van een complex getal +IMCOS = C.COS ## Geeft als resultaat de cosinus van een complex getal +IMDIV = C.QUOTIENT ## Geeft als resultaat het quotiënt van twee complexe getallen +IMEXP = C.EXP ## Geeft als resultaat de exponent van een complex getal +IMLN = C.LN ## Geeft als resultaat de natuurlijke logaritme van een complex getal +IMLOG10 = C.LOG10 ## Geeft als resultaat de logaritme met grondtal 10 van een complex getal +IMLOG2 = C.LOG2 ## Geeft als resultaat de logaritme met grondtal 2 van een complex getal +IMPOWER = C.MACHT ## Geeft als resultaat een complex getal dat is verheven tot de macht van een geheel getal +IMPRODUCT = C.PRODUCT ## Geeft als resultaat het product van complexe getallen +IMREAL = C.REEEL.DEEL ## Geeft als resultaat de reële coëfficiënt van een complex getal +IMSIN = C.SIN ## Geeft als resultaat de sinus van een complex getal +IMSQRT = C.WORTEL ## Geeft als resultaat de vierkantswortel van een complex getal +IMSUB = C.VERSCHIL ## Geeft als resultaat het verschil tussen twee complexe getallen +IMSUM = C.SOM ## Geeft als resultaat de som van complexe getallen +OCT2BIN = OCT.N.BIN ## Converteert een octaal getal naar een binair getal +OCT2DEC = OCT.N.DEC ## Converteert een octaal getal naar een decimaal getal +OCT2HEX = OCT.N.HEX ## Converteert een octaal getal naar een hexadecimaal getal + + +## +## Financial functions Financiële functies +## +ACCRINT = SAMENG.RENTE ## Berekent de opgelopen rente voor een waardepapier waarvan de rente periodiek wordt uitgekeerd +ACCRINTM = SAMENG.RENTE.V ## Berekent de opgelopen rente voor een waardepapier waarvan de rente op de vervaldatum wordt uitgekeerd +AMORDEGRC = AMORDEGRC ## Geeft als resultaat de afschrijving voor elke boekingsperiode door een afschrijvingscoëfficiënt toe te passen +AMORLINC = AMORLINC ## Berekent de afschrijving voor elke boekingsperiode +COUPDAYBS = COUP.DAGEN.BB ## Berekent het aantal dagen vanaf het begin van de coupontermijn tot de stortingsdatum +COUPDAYS = COUP.DAGEN ## Geeft als resultaat het aantal dagen in de coupontermijn waarin de stortingsdatum valt +COUPDAYSNC = COUP.DAGEN.VV ## Geeft als resultaat het aantal dagen vanaf de stortingsdatum tot de volgende couponvervaldatum +COUPNCD = COUP.DATUM.NB ## Geeft als resultaat de volgende coupondatum na de stortingsdatum +COUPNUM = COUP.AANTAL ## Geeft als resultaat het aantal coupons dat nog moet worden uitbetaald tussen de stortingsdatum en de vervaldatum +COUPPCD = COUP.DATUM.VB ## Geeft als resultaat de vorige couponvervaldatum vóór de stortingsdatum +CUMIPMT = CUM.RENTE ## Geeft als resultaat de cumulatieve rente die tussen twee termijnen is uitgekeerd +CUMPRINC = CUM.HOOFDSOM ## Geeft als resultaat de cumulatieve hoofdsom van een lening die tussen twee termijnen is terugbetaald +DB = DB ## Geeft als resultaat de afschrijving van activa voor een bepaalde periode met behulp van de 'fixed declining balance'-methode +DDB = DDB ## Geeft als resultaat de afschrijving van activa over een bepaalde termijn met behulp van de 'double declining balance'-methode of een andere methode die u opgeeft +DISC = DISCONTO ## Geeft als resultaat het discontopercentage voor een waardepapier +DOLLARDE = EURO.DE ## Converteert een prijs in euro's, uitgedrukt in een breuk, naar een prijs in euro's, uitgedrukt in een decimaal getal +DOLLARFR = EURO.BR ## Converteert een prijs in euro's, uitgedrukt in een decimaal getal, naar een prijs in euro's, uitgedrukt in een breuk +DURATION = DUUR ## Geeft als resultaat de gewogen gemiddelde looptijd voor een waardepapier met periodieke rentebetalingen +EFFECT = EFFECT.RENTE ## Geeft als resultaat het effectieve jaarlijkse rentepercentage +FV = TW ## Geeft als resultaat de toekomstige waarde van een investering +FVSCHEDULE = TOEK.WAARDE2 ## Geeft als resultaat de toekomstige waarde van een bepaalde hoofdsom na het toepassen van een reeks samengestelde rentepercentages +INTRATE = RENTEPERCENTAGE ## Geeft als resultaat het rentepercentage voor een volgestort waardepapier +IPMT = IBET ## Geeft als resultaat de te betalen rente voor een investering over een bepaalde termijn +IRR = IR ## Geeft als resultaat de interne rentabiliteit voor een reeks cashflows +ISPMT = ISBET ## Geeft als resultaat de rente die is betaald tijdens een bepaalde termijn van een investering +MDURATION = AANG.DUUR ## Geeft als resultaat de aangepaste Macauley-looptijd voor een waardepapier, aangenomen dat de nominale waarde € 100 bedraagt +MIRR = GIR ## Geeft als resultaat de interne rentabiliteit voor een serie cashflows, waarbij voor betalingen een ander rentepercentage geldt dan voor inkomsten +NOMINAL = NOMINALE.RENTE ## Geeft als resultaat het nominale jaarlijkse rentepercentage +NPER = NPER ## Geeft als resultaat het aantal termijnen van een investering +NPV = NHW ## Geeft als resultaat de netto huidige waarde van een investering op basis van een reeks periodieke cashflows en een discontopercentage +ODDFPRICE = AFW.ET.PRIJS ## Geeft als resultaat de prijs per € 100 nominale waarde voor een waardepapier met een afwijkende eerste termijn +ODDFYIELD = AFW.ET.REND ## Geeft als resultaat het rendement voor een waardepapier met een afwijkende eerste termijn +ODDLPRICE = AFW.LT.PRIJS ## Geeft als resultaat de prijs per € 100 nominale waarde voor een waardepapier met een afwijkende laatste termijn +ODDLYIELD = AFW.LT.REND ## Geeft als resultaat het rendement voor een waardepapier met een afwijkende laatste termijn +PMT = BET ## Geeft als resultaat de periodieke betaling voor een annuïteit +PPMT = PBET ## Geeft als resultaat de afbetaling op de hoofdsom voor een bepaalde termijn +PRICE = PRIJS.NOM ## Geeft als resultaat de prijs per € 100 nominale waarde voor een waardepapier waarvan de rente periodiek wordt uitgekeerd +PRICEDISC = PRIJS.DISCONTO ## Geeft als resultaat de prijs per € 100 nominale waarde voor een verdisconteerd waardepapier +PRICEMAT = PRIJS.VERVALDAG ## Geeft als resultaat de prijs per € 100 nominale waarde voor een waardepapier waarvan de rente wordt uitgekeerd op de vervaldatum +PV = HW ## Geeft als resultaat de huidige waarde van een investering +RATE = RENTE ## Geeft als resultaat het periodieke rentepercentage voor een annuïteit +RECEIVED = OPBRENGST ## Geeft als resultaat het bedrag dat op de vervaldatum wordt uitgekeerd voor een volgestort waardepapier +SLN = LIN.AFSCHR ## Geeft als resultaat de lineaire afschrijving van activa over één termijn +SYD = SYD ## Geeft als resultaat de afschrijving van activa over een bepaalde termijn met behulp van de 'Sum-Of-Years-Digits'-methode +TBILLEQ = SCHATK.OBL ## Geeft als resultaat het rendement op schatkistpapier, dat op dezelfde manier wordt berekend als het rendement op obligaties +TBILLPRICE = SCHATK.PRIJS ## Bepaalt de prijs per € 100 nominale waarde voor schatkistpapier +TBILLYIELD = SCHATK.REND ## Berekent het rendement voor schatkistpapier +VDB = VDB ## Geeft als resultaat de afschrijving van activa over een gehele of gedeeltelijke termijn met behulp van de 'declining balance'-methode +XIRR = IR.SCHEMA ## Berekent de interne rentabiliteit voor een betalingsschema van cashflows +XNPV = NHW2 ## Berekent de huidige nettowaarde voor een betalingsschema van cashflows +YIELD = RENDEMENT ## Geeft als resultaat het rendement voor een waardepapier waarvan de rente periodiek wordt uitgekeerd +YIELDDISC = REND.DISCONTO ## Geeft als resultaat het jaarlijkse rendement voor een verdisconteerd waardepapier, bijvoorbeeld schatkistpapier +YIELDMAT = REND.VERVAL ## Geeft als resultaat het jaarlijkse rendement voor een waardepapier waarvan de rente wordt uitgekeerd op de vervaldatum + + +## +## Information functions Informatiefuncties +## +CELL = CEL ## Geeft als resultaat informatie over de opmaak, locatie of inhoud van een cel +ERROR.TYPE = TYPE.FOUT ## Geeft als resultaat een getal dat overeenkomt met een van de foutwaarden van Microsoft Excel +INFO = INFO ## Geeft als resultaat informatie over de huidige besturingsomgeving +ISBLANK = ISLEEG ## Geeft als resultaat WAAR als de waarde leeg is +ISERR = ISFOUT2 ## Geeft als resultaat WAAR als de waarde een foutwaarde is, met uitzondering van #N/B +ISERROR = ISFOUT ## Geeft als resultaat WAAR als de waarde een foutwaarde is +ISEVEN = IS.EVEN ## Geeft als resultaat WAAR als het getal even is +ISLOGICAL = ISLOGISCH ## Geeft als resultaat WAAR als de waarde een logische waarde is +ISNA = ISNB ## Geeft als resultaat WAAR als de waarde de foutwaarde #N/B is +ISNONTEXT = ISGEENTEKST ## Geeft als resultaat WAAR als de waarde geen tekst is +ISNUMBER = ISGETAL ## Geeft als resultaat WAAR als de waarde een getal is +ISODD = IS.ONEVEN ## Geeft als resultaat WAAR als het getal oneven is +ISREF = ISVERWIJZING ## Geeft als resultaat WAAR als de waarde een verwijzing is +ISTEXT = ISTEKST ## Geeft als resultaat WAAR als de waarde tekst is +N = N ## Geeft als resultaat een waarde die is geconverteerd naar een getal +NA = NB ## Geeft als resultaat de foutwaarde #N/B +TYPE = TYPE ## Geeft als resultaat een getal dat het gegevenstype van een waarde aangeeft + + +## +## Logical functions Logische functies +## +AND = EN ## Geeft als resultaat WAAR als alle argumenten WAAR zijn +FALSE = ONWAAR ## Geeft als resultaat de logische waarde ONWAAR +IF = ALS ## Geeft een logische test aan +IFERROR = ALS.FOUT ## Retourneert een waarde die u opgeeft als een formule een fout oplevert, anders wordt het resultaat van de formule geretourneerd +NOT = NIET ## Keert de logische waarde van het argument om +OR = OF ## Geeft als resultaat WAAR als minimaal een van de argumenten WAAR is +TRUE = WAAR ## Geeft als resultaat de logische waarde WAAR + + +## +## Lookup and reference functions Zoek- en verwijzingsfuncties +## +ADDRESS = ADRES ## Geeft als resultaat een verwijzing, in de vorm van tekst, naar één bepaalde cel in een werkblad +AREAS = BEREIKEN ## Geeft als resultaat het aantal bereiken in een verwijzing +CHOOSE = KIEZEN ## Kiest een waarde uit een lijst met waarden +COLUMN = KOLOM ## Geeft als resultaat het kolomnummer van een verwijzing +COLUMNS = KOLOMMEN ## Geeft als resultaat het aantal kolommen in een verwijzing +HLOOKUP = HORIZ.ZOEKEN ## Zoekt in de bovenste rij van een matrix naar een bepaalde waarde en geeft als resultaat de gevonden waarde in de opgegeven cel +HYPERLINK = HYPERLINK ## Maakt een snelkoppeling of een sprong waarmee een document wordt geopend dat is opgeslagen op een netwerkserver, een intranet of op internet +INDEX = INDEX ## Kiest met een index een waarde uit een verwijzing of een matrix +INDIRECT = INDIRECT ## Geeft als resultaat een verwijzing die wordt aangegeven met een tekstwaarde +LOOKUP = ZOEKEN ## Zoekt naar bepaalde waarden in een vector of een matrix +MATCH = VERGELIJKEN ## Zoekt naar bepaalde waarden in een verwijzing of een matrix +OFFSET = VERSCHUIVING ## Geeft als resultaat een nieuwe verwijzing die is verschoven ten opzichte van een bepaalde verwijzing +ROW = RIJ ## Geeft als resultaat het rijnummer van een verwijzing +ROWS = RIJEN ## Geeft als resultaat het aantal rijen in een verwijzing +RTD = RTG ## Haalt realtimegegevens op uit een programma dat COM-automatisering (automatisering: een methode waarmee de ene toepassing objecten van een andere toepassing of ontwikkelprogramma kan besturen. Automatisering werd vroeger OLE-automatisering genoemd. Automatisering is een industrienorm die deel uitmaakt van het Component Object Model (COM).) ondersteunt +TRANSPOSE = TRANSPONEREN ## Geeft als resultaat de getransponeerde van een matrix +VLOOKUP = VERT.ZOEKEN ## Zoekt in de meest linkse kolom van een matrix naar een bepaalde waarde en geeft als resultaat de waarde in de opgegeven cel + + +## +## Math and trigonometry functions Wiskundige en trigonometrische functies +## +ABS = ABS ## Geeft als resultaat de absolute waarde van een getal +ACOS = BOOGCOS ## Geeft als resultaat de boogcosinus van een getal +ACOSH = BOOGCOSH ## Geeft als resultaat de inverse cosinus hyperbolicus van een getal +ASIN = BOOGSIN ## Geeft als resultaat de boogsinus van een getal +ASINH = BOOGSINH ## Geeft als resultaat de inverse sinus hyperbolicus van een getal +ATAN = BOOGTAN ## Geeft als resultaat de boogtangens van een getal +ATAN2 = BOOGTAN2 ## Geeft als resultaat de boogtangens van de x- en y-coördinaten +ATANH = BOOGTANH ## Geeft als resultaat de inverse tangens hyperbolicus van een getal +CEILING = AFRONDEN.BOVEN ## Rondt de absolute waarde van een getal naar boven af op het dichtstbijzijnde gehele getal of het dichtstbijzijnde significante veelvoud +COMBIN = COMBINATIES ## Geeft als resultaat het aantal combinaties voor een bepaald aantal objecten +COS = COS ## Geeft als resultaat de cosinus van een getal +COSH = COSH ## Geeft als resultaat de cosinus hyperbolicus van een getal +DEGREES = GRADEN ## Converteert radialen naar graden +EVEN = EVEN ## Rondt het getal af op het dichtstbijzijnde gehele even getal +EXP = EXP ## Verheft e tot de macht van een bepaald getal +FACT = FACULTEIT ## Geeft als resultaat de faculteit van een getal +FACTDOUBLE = DUBBELE.FACULTEIT ## Geeft als resultaat de dubbele faculteit van een getal +FLOOR = AFRONDEN.BENEDEN ## Rondt de absolute waarde van een getal naar beneden af +GCD = GGD ## Geeft als resultaat de grootste gemene deler +INT = INTEGER ## Rondt een getal naar beneden af op het dichtstbijzijnde gehele getal +LCM = KGV ## Geeft als resultaat het kleinste gemene veelvoud +LN = LN ## Geeft als resultaat de natuurlijke logaritme van een getal +LOG = LOG ## Geeft als resultaat de logaritme met het opgegeven grondtal van een getal +LOG10 = LOG10 ## Geeft als resultaat de logaritme met grondtal 10 van een getal +MDETERM = DETERMINANTMAT ## Geeft als resultaat de determinant van een matrix +MINVERSE = INVERSEMAT ## Geeft als resultaat de inverse van een matrix +MMULT = PRODUCTMAT ## Geeft als resultaat het product van twee matrices +MOD = REST ## Geeft als resultaat het restgetal van een deling +MROUND = AFRONDEN.N.VEELVOUD ## Geeft als resultaat een getal afgerond op het gewenste veelvoud +MULTINOMIAL = MULTINOMIAAL ## Geeft als resultaat de multinomiaalcoëfficiënt van een reeks getallen +ODD = ONEVEN ## Rondt de absolute waarde van het getal naar boven af op het dichtstbijzijnde gehele oneven getal +PI = PI ## Geeft als resultaat de waarde van pi +POWER = MACHT ## Verheft een getal tot een macht +PRODUCT = PRODUCT ## Vermenigvuldigt de argumenten met elkaar +QUOTIENT = QUOTIENT ## Geeft als resultaat de uitkomst van een deling als geheel getal +RADIANS = RADIALEN ## Converteert graden naar radialen +RAND = ASELECT ## Geeft als resultaat een willekeurig getal tussen 0 en 1 +RANDBETWEEN = ASELECTTUSSEN ## Geeft een willekeurig getal tussen de getallen die u hebt opgegeven +ROMAN = ROMEINS ## Converteert een Arabisch getal naar een Romeins getal en geeft het resultaat weer in de vorm van tekst +ROUND = AFRONDEN ## Rondt een getal af op het opgegeven aantal decimalen +ROUNDDOWN = AFRONDEN.NAAR.BENEDEN ## Rondt de absolute waarde van een getal naar beneden af +ROUNDUP = AFRONDEN.NAAR.BOVEN ## Rondt de absolute waarde van een getal naar boven af +SERIESSUM = SOM.MACHTREEKS ## Geeft als resultaat de som van een machtreeks die is gebaseerd op de formule +SIGN = POS.NEG ## Geeft als resultaat het teken van een getal +SIN = SIN ## Geeft als resultaat de sinus van de opgegeven hoek +SINH = SINH ## Geeft als resultaat de sinus hyperbolicus van een getal +SQRT = WORTEL ## Geeft als resultaat de positieve vierkantswortel van een getal +SQRTPI = WORTEL.PI ## Geeft als resultaat de vierkantswortel van (getal * pi) +SUBTOTAL = SUBTOTAAL ## Geeft als resultaat een subtotaal voor een bereik +SUM = SOM ## Telt de argumenten op +SUMIF = SOM.ALS ## Telt de getallen bij elkaar op die voldoen aan een bepaald criterium +SUMIFS = SOMMEN.ALS ## Telt de cellen in een bereik op die aan meerdere criteria voldoen +SUMPRODUCT = SOMPRODUCT ## Geeft als resultaat de som van de producten van de corresponderende matrixelementen +SUMSQ = KWADRATENSOM ## Geeft als resultaat de som van de kwadraten van de argumenten +SUMX2MY2 = SOM.X2MINY2 ## Geeft als resultaat de som van het verschil tussen de kwadraten van corresponderende waarden in twee matrices +SUMX2PY2 = SOM.X2PLUSY2 ## Geeft als resultaat de som van de kwadratensom van corresponderende waarden in twee matrices +SUMXMY2 = SOM.XMINY.2 ## Geeft als resultaat de som van de kwadraten van de verschillen tussen de corresponderende waarden in twee matrices +TAN = TAN ## Geeft als resultaat de tangens van een getal +TANH = TANH ## Geeft als resultaat de tangens hyperbolicus van een getal +TRUNC = GEHEEL ## Kapt een getal af tot een geheel getal + + +## +## Statistical functions Statistische functies +## +AVEDEV = GEM.DEVIATIE ## Geeft als resultaat het gemiddelde van de absolute deviaties van gegevenspunten ten opzichte van hun gemiddelde waarde +AVERAGE = GEMIDDELDE ## Geeft als resultaat het gemiddelde van de argumenten +AVERAGEA = GEMIDDELDEA ## Geeft als resultaat het gemiddelde van de argumenten, inclusief getallen, tekst en logische waarden +AVERAGEIF = GEMIDDELDE.ALS ## Geeft het gemiddelde (rekenkundig gemiddelde) als resultaat van alle cellen in een bereik die voldoen aan de opgegeven criteria +AVERAGEIFS = GEMIDDELDEN.ALS ## Geeft het gemiddelde (rekenkundig gemiddelde) als resultaat van alle cellen die aan meerdere criteria voldoen +BETADIST = BETA.VERD ## Geeft als resultaat de cumulatieve bèta-verdelingsfunctie +BETAINV = BETA.INV ## Geeft als resultaat de inverse van de cumulatieve verdelingsfunctie voor een gegeven bèta-verdeling +BINOMDIST = BINOMIALE.VERD ## Geeft als resultaat de binomiale verdeling +CHIDIST = CHI.KWADRAAT ## Geeft als resultaat de eenzijdige kans van de chi-kwadraatverdeling +CHIINV = CHI.KWADRAAT.INV ## Geeft als resultaat de inverse van een eenzijdige kans van de chi-kwadraatverdeling +CHITEST = CHI.TOETS ## Geeft als resultaat de onafhankelijkheidstoets +CONFIDENCE = BETROUWBAARHEID ## Geeft als resultaat het betrouwbaarheidsinterval van een gemiddelde waarde voor de elementen van een populatie +CORREL = CORRELATIE ## Geeft als resultaat de correlatiecoëfficiënt van twee gegevensverzamelingen +COUNT = AANTAL ## Telt het aantal getallen in de argumentenlijst +COUNTA = AANTALARG ## Telt het aantal waarden in de argumentenlijst +COUNTBLANK = AANTAL.LEGE.CELLEN ## Telt het aantal lege cellen in een bereik +COUNTIF = AANTAL.ALS ## Telt in een bereik het aantal cellen die voldoen aan een bepaald criterium +COUNTIFS = AANTALLEN.ALS ## Telt in een bereik het aantal cellen die voldoen aan meerdere criteria +COVAR = COVARIANTIE ## Geeft als resultaat de covariantie, het gemiddelde van de producten van de gepaarde deviaties +CRITBINOM = CRIT.BINOM ## Geeft als resultaat de kleinste waarde waarvoor de binomiale verdeling kleiner is dan of gelijk is aan het criterium +DEVSQ = DEV.KWAD ## Geeft als resultaat de som van de deviaties in het kwadraat +EXPONDIST = EXPON.VERD ## Geeft als resultaat de exponentiële verdeling +FDIST = F.VERDELING ## Geeft als resultaat de F-verdeling +FINV = F.INVERSE ## Geeft als resultaat de inverse van de F-verdeling +FISHER = FISHER ## Geeft als resultaat de Fisher-transformatie +FISHERINV = FISHER.INV ## Geeft als resultaat de inverse van de Fisher-transformatie +FORECAST = VOORSPELLEN ## Geeft als resultaat een waarde op basis van een lineaire trend +FREQUENCY = FREQUENTIE ## Geeft als resultaat een frequentieverdeling in de vorm van een verticale matrix +FTEST = F.TOETS ## Geeft als resultaat een F-toets +GAMMADIST = GAMMA.VERD ## Geeft als resultaat de gamma-verdeling +GAMMAINV = GAMMA.INV ## Geeft als resultaat de inverse van de cumulatieve gamma-verdeling +GAMMALN = GAMMA.LN ## Geeft als resultaat de natuurlijke logaritme van de gamma-functie, G(x) +GEOMEAN = MEETK.GEM ## Geeft als resultaat het meetkundige gemiddelde +GROWTH = GROEI ## Geeft als resultaat de waarden voor een exponentiële trend +HARMEAN = HARM.GEM ## Geeft als resultaat het harmonische gemiddelde +HYPGEOMDIST = HYPERGEO.VERD ## Geeft als resultaat de hypergeometrische verdeling +INTERCEPT = SNIJPUNT ## Geeft als resultaat het snijpunt van de lineaire regressielijn met de y-as +KURT = KURTOSIS ## Geeft als resultaat de kurtosis van een gegevensverzameling +LARGE = GROOTSTE ## Geeft als resultaat de op k-1 na grootste waarde in een gegevensverzameling +LINEST = LIJNSCH ## Geeft als resultaat de parameters van een lineaire trend +LOGEST = LOGSCH ## Geeft als resultaat de parameters van een exponentiële trend +LOGINV = LOG.NORM.INV ## Geeft als resultaat de inverse van de logaritmische normale verdeling +LOGNORMDIST = LOG.NORM.VERD ## Geeft als resultaat de cumulatieve logaritmische normale verdeling +MAX = MAX ## Geeft als resultaat de maximumwaarde in een lijst met argumenten +MAXA = MAXA ## Geeft als resultaat de maximumwaarde in een lijst met argumenten, inclusief getallen, tekst en logische waarden +MEDIAN = MEDIAAN ## Geeft als resultaat de mediaan van de opgegeven getallen +MIN = MIN ## Geeft als resultaat de minimumwaarde in een lijst met argumenten +MINA = MINA ## Geeft als resultaat de minimumwaarde in een lijst met argumenten, inclusief getallen, tekst en logische waarden +MODE = MODUS ## Geeft als resultaat de meest voorkomende waarde in een gegevensverzameling +NEGBINOMDIST = NEG.BINOM.VERD ## Geeft als resultaat de negatieve binomiaalverdeling +NORMDIST = NORM.VERD ## Geeft als resultaat de cumulatieve normale verdeling +NORMINV = NORM.INV ## Geeft als resultaat de inverse van de cumulatieve standaardnormale verdeling +NORMSDIST = STAND.NORM.VERD ## Geeft als resultaat de cumulatieve standaardnormale verdeling +NORMSINV = STAND.NORM.INV ## Geeft als resultaat de inverse van de cumulatieve normale verdeling +PEARSON = PEARSON ## Geeft als resultaat de correlatiecoëfficiënt van Pearson +PERCENTILE = PERCENTIEL ## Geeft als resultaat het k-de percentiel van waarden in een bereik +PERCENTRANK = PERCENT.RANG ## Geeft als resultaat de positie, in procenten uitgedrukt, van een waarde in de rangorde van een gegevensverzameling +PERMUT = PERMUTATIES ## Geeft als resultaat het aantal permutaties voor een gegeven aantal objecten +POISSON = POISSON ## Geeft als resultaat de Poisson-verdeling +PROB = KANS ## Geeft als resultaat de kans dat waarden zich tussen twee grenzen bevinden +QUARTILE = KWARTIEL ## Geeft als resultaat het kwartiel van een gegevensverzameling +RANK = RANG ## Geeft als resultaat het rangnummer van een getal in een lijst getallen +RSQ = R.KWADRAAT ## Geeft als resultaat het kwadraat van de Pearson-correlatiecoëfficiënt +SKEW = SCHEEFHEID ## Geeft als resultaat de mate van asymmetrie van een verdeling +SLOPE = RICHTING ## Geeft als resultaat de richtingscoëfficiënt van een lineaire regressielijn +SMALL = KLEINSTE ## Geeft als resultaat de op k-1 na kleinste waarde in een gegevensverzameling +STANDARDIZE = NORMALISEREN ## Geeft als resultaat een genormaliseerde waarde +STDEV = STDEV ## Maakt een schatting van de standaarddeviatie op basis van een steekproef +STDEVA = STDEVA ## Maakt een schatting van de standaarddeviatie op basis van een steekproef, inclusief getallen, tekst en logische waarden +STDEVP = STDEVP ## Berekent de standaarddeviatie op basis van de volledige populatie +STDEVPA = STDEVPA ## Berekent de standaarddeviatie op basis van de volledige populatie, inclusief getallen, tekst en logische waarden +STEYX = STAND.FOUT.YX ## Geeft als resultaat de standaardfout in de voorspelde y-waarde voor elke x in een regressie +TDIST = T.VERD ## Geeft als resultaat de Student T-verdeling +TINV = T.INV ## Geeft als resultaat de inverse van de Student T-verdeling +TREND = TREND ## Geeft als resultaat de waarden voor een lineaire trend +TRIMMEAN = GETRIMD.GEM ## Geeft als resultaat het gemiddelde van waarden in een gegevensverzameling +TTEST = T.TOETS ## Geeft als resultaat de kans met behulp van de Student T-toets +VAR = VAR ## Maakt een schatting van de variantie op basis van een steekproef +VARA = VARA ## Maakt een schatting van de variantie op basis van een steekproef, inclusief getallen, tekst en logische waarden +VARP = VARP ## Berekent de variantie op basis van de volledige populatie +VARPA = VARPA ## Berekent de standaarddeviatie op basis van de volledige populatie, inclusief getallen, tekst en logische waarden +WEIBULL = WEIBULL ## Geeft als resultaat de Weibull-verdeling +ZTEST = Z.TOETS ## Geeft als resultaat de eenzijdige kanswaarde van een Z-toets + + +## +## Text functions Tekstfuncties +## +ASC = ASC ## Wijzigt Nederlandse letters of katakanatekens over de volle breedte (dubbel-bytetekens) binnen een tekenreeks in tekens over de halve breedte (enkel-bytetekens) +BAHTTEXT = BAHT.TEKST ## Converteert een getal naar tekst met de valutanotatie ß (baht) +CHAR = TEKEN ## Geeft als resultaat het teken dat hoort bij de opgegeven code +CLEAN = WISSEN.CONTROL ## Verwijdert alle niet-afdrukbare tekens uit een tekst +CODE = CODE ## Geeft als resultaat de numerieke code voor het eerste teken in een tekenreeks +CONCATENATE = TEKST.SAMENVOEGEN ## Voegt verschillende tekstfragmenten samen tot één tekstfragment +DOLLAR = EURO ## Converteert een getal naar tekst met de valutanotatie € (euro) +EXACT = GELIJK ## Controleert of twee tekenreeksen identiek zijn +FIND = VIND.ALLES ## Zoekt een bepaalde tekenreeks in een tekst (waarbij onderscheid wordt gemaakt tussen hoofdletters en kleine letters) +FINDB = VIND.ALLES.B ## Zoekt een bepaalde tekenreeks in een tekst (waarbij onderscheid wordt gemaakt tussen hoofdletters en kleine letters) +FIXED = VAST ## Maakt een getal als tekst met een vast aantal decimalen op +JIS = JIS ## Wijzigt Nederlandse letters of katakanatekens over de halve breedte (enkel-bytetekens) binnen een tekenreeks in tekens over de volle breedte (dubbel-bytetekens) +LEFT = LINKS ## Geeft als resultaat de meest linkse tekens in een tekenreeks +LEFTB = LINKSB ## Geeft als resultaat de meest linkse tekens in een tekenreeks +LEN = LENGTE ## Geeft als resultaat het aantal tekens in een tekenreeks +LENB = LENGTEB ## Geeft als resultaat het aantal tekens in een tekenreeks +LOWER = KLEINE.LETTERS ## Zet tekst om in kleine letters +MID = MIDDEN ## Geeft als resultaat een bepaald aantal tekens van een tekenreeks vanaf de positie die u opgeeft +MIDB = DEELB ## Geeft als resultaat een bepaald aantal tekens van een tekenreeks vanaf de positie die u opgeeft +PHONETIC = FONETISCH ## Haalt de fonetische tekens (furigana) uit een tekenreeks op +PROPER = BEGINLETTERS ## Zet de eerste letter van elk woord in een tekst om in een hoofdletter +REPLACE = VERVANG ## Vervangt tekens binnen een tekst +REPLACEB = VERVANGENB ## Vervangt tekens binnen een tekst +REPT = HERHALING ## Herhaalt een tekst een aantal malen +RIGHT = RECHTS ## Geeft als resultaat de meest rechtse tekens in een tekenreeks +RIGHTB = RECHTSB ## Geeft als resultaat de meest rechtse tekens in een tekenreeks +SEARCH = VIND.SPEC ## Zoekt een bepaalde tekenreeks in een tekst (waarbij geen onderscheid wordt gemaakt tussen hoofdletters en kleine letters) +SEARCHB = VIND.SPEC.B ## Zoekt een bepaalde tekenreeks in een tekst (waarbij geen onderscheid wordt gemaakt tussen hoofdletters en kleine letters) +SUBSTITUTE = SUBSTITUEREN ## Vervangt oude tekst door nieuwe tekst in een tekenreeks +T = T ## Converteert de argumenten naar tekst +TEXT = TEKST ## Maakt een getal op en converteert het getal naar tekst +TRIM = SPATIES.WISSEN ## Verwijdert de spaties uit een tekst +UPPER = HOOFDLETTERS ## Zet tekst om in hoofdletters +VALUE = WAARDE ## Converteert tekst naar een getal diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/no/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/no/config new file mode 100755 index 0000000..d878784 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/no/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = kr + + +## +## Excel Error Codes (For future use) +## +NULL = #NULL! +DIV0 = #DIV/0! +VALUE = #VERDI! +REF = #REF! +NAME = #NAVN? +NUM = #NUM! +NA = #I/T diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/no/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/no/functions new file mode 100755 index 0000000..6772862 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/no/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions Funksjonene Tillegg og Automatisering +## +GETPIVOTDATA = HENTPIVOTDATA ## Returnerer data som er lagret i en pivottabellrapport + + +## +## Cube functions Kubefunksjoner +## +CUBEKPIMEMBER = KUBEKPIMEDLEM ## Returnerer navnet, egenskapen og mÃ¥let for en viktig ytelsesindikator (KPI), og viser navnet og egenskapen i cellen. En KPI er en mÃ¥lbar enhet, for eksempel mÃ¥nedlig bruttoinntjening eller kvartalsvis inntjening per ansatt, og brukes til Ã¥ overvÃ¥ke ytelsen i en organisasjon. +CUBEMEMBER = KUBEMEDLEM ## Returnerer et medlem eller en tuppel i et kubehierarki. Brukes til Ã¥ validere at medlemmet eller tuppelen finnes i kuben. +CUBEMEMBERPROPERTY = KUBEMEDLEMEGENSKAP ## Returnerer verdien til en medlemsegenskap i kuben. Brukes til Ã¥ validere at et medlemsnavn finnes i kuben, og til Ã¥ returnere den angitte egenskapen for dette medlemmet. +CUBERANKEDMEMBER = KUBERANGERTMEDLEM ## Returnerer det n-te, eller rangerte, medlemmet i et sett. Brukes til Ã¥ returnere ett eller flere elementer i et sett, for eksempel de 10 beste studentene. +CUBESET = KUBESETT ## Definerer et beregnet sett av medlemmer eller tuppeler ved Ã¥ sende et settuttrykk til kuben pÃ¥ serveren, noe som oppretter settet og deretter returnerer dette settet til Microsoft Office Excel. +CUBESETCOUNT = KUBESETTANTALL ## Returnerer antallet elementer i et sett. +CUBEVALUE = KUBEVERDI ## Returnerer en aggregert verdi fra en kube. + + +## +## Database functions Databasefunksjoner +## +DAVERAGE = DGJENNOMSNITT ## Returnerer gjennomsnittet av merkede databaseposter +DCOUNT = DANTALL ## Teller celler som inneholder tall i en database +DCOUNTA = DANTALLA ## Teller celler som ikke er tomme i en database +DGET = DHENT ## Trekker ut fra en database en post som oppfyller angitte vilkÃ¥r +DMAX = DMAKS ## Returnerer maksimumsverdien fra merkede databaseposter +DMIN = DMIN ## Returnerer minimumsverdien fra merkede databaseposter +DPRODUCT = DPRODUKT ## Multipliserer verdiene i et bestemt felt med poster som oppfyller vilkÃ¥rene i en database +DSTDEV = DSTDAV ## Estimerer standardavviket basert pÃ¥ et utvalg av merkede databaseposter +DSTDEVP = DSTAVP ## Beregner standardavviket basert pÃ¥ at merkede databaseposter utgjør hele populasjonen +DSUM = DSUMMER ## Legger til tallene i feltkolonnen med poster, i databasen som oppfyller vilkÃ¥rene +DVAR = DVARIANS ## Estimerer variansen basert pÃ¥ et utvalg av merkede databaseposter +DVARP = DVARIANSP ## Beregner variansen basert pÃ¥ at merkede databaseposter utgjør hele populasjonen + + +## +## Date and time functions Dato- og tidsfunksjoner +## +DATE = DATO ## Returnerer serienummeret som svarer til en bestemt dato +DATEVALUE = DATOVERDI ## Konverterer en dato med tekstformat til et serienummer +DAY = DAG ## Konverterer et serienummer til en dag i mÃ¥neden +DAYS360 = DAGER360 ## Beregner antall dager mellom to datoer basert pÃ¥ et Ã¥r med 360 dager +EDATE = DAG.ETTER ## Returnerer serienummeret som svarer til datoen som er det indikerte antall mÃ¥neder før eller etter startdatoen +EOMONTH = MÃ…NEDSSLUTT ## Returnerer serienummeret som svarer til siste dag i mÃ¥neden, før eller etter et angitt antall mÃ¥neder +HOUR = TIME ## Konverterer et serienummer til en time +MINUTE = MINUTT ## Konverterer et serienummer til et minutt +MONTH = MÃ…NED ## Konverterer et serienummer til en mÃ¥ned +NETWORKDAYS = NETT.ARBEIDSDAGER ## Returnerer antall hele arbeidsdager mellom to datoer +NOW = NÃ… ## Returnerer serienummeret som svarer til gjeldende dato og klokkeslett +SECOND = SEKUND ## Konverterer et serienummer til et sekund +TIME = TID ## Returnerer serienummeret som svarer til et bestemt klokkeslett +TIMEVALUE = TIDSVERDI ## Konverterer et klokkeslett i tekstformat til et serienummer +TODAY = IDAG ## Returnerer serienummeret som svarer til dagens dato +WEEKDAY = UKEDAG ## Konverterer et serienummer til en ukedag +WEEKNUM = UKENR ## Konverterer et serienummer til et tall som representerer hvilket nummer uken har i et Ã¥r +WORKDAY = ARBEIDSDAG ## Returnerer serienummeret som svarer til datoen før eller etter et angitt antall arbeidsdager +YEAR = Ã…R ## Konverterer et serienummer til et Ã¥r +YEARFRAC = Ã…RDEL ## Returnerer brøkdelen for Ã¥ret, som svarer til antall hele dager mellom startdato og sluttdato + + +## +## Engineering functions Tekniske funksjoner +## +BESSELI = BESSELI ## Returnerer den endrede Bessel-funksjonen In(x) +BESSELJ = BESSELJ ## Returnerer Bessel-funksjonen Jn(x) +BESSELK = BESSELK ## Returnerer den endrede Bessel-funksjonen Kn(x) +BESSELY = BESSELY ## Returnerer Bessel-funksjonen Yn(x) +BIN2DEC = BINTILDES ## Konverterer et binært tall til et desimaltall +BIN2HEX = BINTILHEKS ## Konverterer et binært tall til et heksadesimaltall +BIN2OCT = BINTILOKT ## Konverterer et binært tall til et oktaltall +COMPLEX = KOMPLEKS ## Konverterer reelle og imaginære koeffisienter til et komplekst tall +CONVERT = KONVERTER ## Konverterer et tall fra ett mÃ¥lsystem til et annet +DEC2BIN = DESTILBIN ## Konverterer et desimaltall til et binærtall +DEC2HEX = DESTILHEKS ## Konverterer et heltall i 10-tallsystemet til et heksadesimalt tall +DEC2OCT = DESTILOKT ## Konverterer et heltall i 10-tallsystemet til et oktaltall +DELTA = DELTA ## Undersøker om to verdier er like +ERF = FEILF ## Returnerer feilfunksjonen +ERFC = FEILFK ## Returnerer den komplementære feilfunksjonen +GESTEP = GRENSEVERDI ## Tester om et tall er større enn en terskelverdi +HEX2BIN = HEKSTILBIN ## Konverterer et heksadesimaltall til et binært tall +HEX2DEC = HEKSTILDES ## Konverterer et heksadesimalt tall til et heltall i 10-tallsystemet +HEX2OCT = HEKSTILOKT ## Konverterer et heksadesimalt tall til et oktaltall +IMABS = IMABS ## Returnerer absoluttverdien (koeffisienten) til et komplekst tall +IMAGINARY = IMAGINÆR ## Returnerer den imaginære koeffisienten til et komplekst tall +IMARGUMENT = IMARGUMENT ## Returnerer argumentet theta, som er en vinkel uttrykt i radianer +IMCONJUGATE = IMKONJUGERT ## Returnerer den komplekse konjugaten til et komplekst tall +IMCOS = IMCOS ## Returnerer cosinus til et komplekst tall +IMDIV = IMDIV ## Returnerer kvotienten til to komplekse tall +IMEXP = IMEKSP ## Returnerer eksponenten til et komplekst tall +IMLN = IMLN ## Returnerer den naturlige logaritmen for et komplekst tall +IMLOG10 = IMLOG10 ## Returnerer logaritmen med grunntall 10 for et komplekst tall +IMLOG2 = IMLOG2 ## Returnerer logaritmen med grunntall 2 for et komplekst tall +IMPOWER = IMOPPHØY ## Returnerer et komplekst tall opphøyd til en heltallspotens +IMPRODUCT = IMPRODUKT ## Returnerer produktet av komplekse tall +IMREAL = IMREELL ## Returnerer den reelle koeffisienten til et komplekst tall +IMSIN = IMSIN ## Returnerer sinus til et komplekst tall +IMSQRT = IMROT ## Returnerer kvadratroten av et komplekst tall +IMSUB = IMSUB ## Returnerer differansen mellom to komplekse tall +IMSUM = IMSUMMER ## Returnerer summen av komplekse tall +OCT2BIN = OKTTILBIN ## Konverterer et oktaltall til et binært tall +OCT2DEC = OKTTILDES ## Konverterer et oktaltall til et desimaltall +OCT2HEX = OKTTILHEKS ## Konverterer et oktaltall til et heksadesimaltall + + +## +## Financial functions Økonomiske funksjoner +## +ACCRINT = PÃ…LØPT.PERIODISK.RENTE ## Returnerer pÃ¥løpte renter for et verdipapir som betaler periodisk rente +ACCRINTM = PÃ…LØPT.FORFALLSRENTE ## Returnerer den pÃ¥løpte renten for et verdipapir som betaler rente ved forfall +AMORDEGRC = AMORDEGRC ## Returnerer avskrivningen for hver regnskapsperiode ved hjelp av en avskrivingskoeffisient +AMORLINC = AMORLINC ## Returnerer avskrivingen for hver regnskapsperiode +COUPDAYBS = OBLIG.DAGER.FF ## Returnerer antall dager fra begynnelsen av den rentebærende perioden til innløsningsdatoen +COUPDAYS = OBLIG.DAGER ## Returnerer antall dager i den rentebærende perioden som inneholder innløsningsdatoen +COUPDAYSNC = OBLIG.DAGER.NF ## Returnerer antall dager fra betalingsdato til neste renteinnbetalingsdato +COUPNCD = OBLIG.DAGER.EF ## Returnerer obligasjonsdatoen som kommer etter oppgjørsdatoen +COUPNUM = OBLIG.ANTALL ## Returnerer antall obligasjoner som skal betales mellom oppgjørsdatoen og forfallsdatoen +COUPPCD = OBLIG.DAG.FORRIGE ## Returnerer obligasjonsdatoen som kommer før oppgjørsdatoen +CUMIPMT = SAMLET.RENTE ## Returnerer den kumulative renten som er betalt mellom to perioder +CUMPRINC = SAMLET.HOVEDSTOL ## Returnerer den kumulative hovedstolen som er betalt for et lÃ¥n mellom to perioder +DB = DAVSKR ## Returnerer avskrivningen for et aktivum i en angitt periode, foretatt med fast degressiv avskrivning +DDB = DEGRAVS ## Returnerer avskrivningen for et aktivum for en gitt periode, ved hjelp av dobbel degressiv avskrivning eller en metode som du selv angir +DISC = DISKONTERT ## Returnerer diskonteringsraten for et verdipapir +DOLLARDE = DOLLARDE ## Konverterer en valutapris uttrykt som en brøk, til en valutapris uttrykt som et desimaltall +DOLLARFR = DOLLARBR ## Konverterer en valutapris uttrykt som et desimaltall, til en valutapris uttrykt som en brøk +DURATION = VARIGHET ## Returnerer Ã¥rlig varighet for et verdipapir med renter som betales periodisk +EFFECT = EFFEKTIV.RENTE ## Returnerer den effektive Ã¥rlige rentesatsen +FV = SLUTTVERDI ## Returnerer fremtidig verdi for en investering +FVSCHEDULE = SVPLAN ## Returnerer den fremtidige verdien av en inngÃ¥ende hovedstol etter Ã¥ ha anvendt en serie med sammensatte rentesatser +INTRATE = RENTESATS ## Returnerer rentefoten av et fullfinansiert verdipapir +IPMT = RAVDRAG ## Returnerer betalte renter pÃ¥ en investering for en gitt periode +IRR = IR ## Returnerer internrenten for en serie kontantstrømmer +ISPMT = ER.AVDRAG ## Beregner renten som er betalt for en investering i løpet av en bestemt periode +MDURATION = MVARIGHET ## Returnerer Macauleys modifiserte varighet for et verdipapir med en antatt pÃ¥lydende verdi pÃ¥ kr 100,00 +MIRR = MODIR ## Returnerer internrenten der positive og negative kontantstrømmer finansieres med forskjellige satser +NOMINAL = NOMINELL ## Returnerer Ã¥rlig nominell rentesats +NPER = PERIODER ## Returnerer antall perioder for en investering +NPV = NNV ## Returnerer netto nÃ¥verdi for en investering, basert pÃ¥ en serie periodiske kontantstrømmer og en rentesats +ODDFPRICE = AVVIKFP.PRIS ## Returnerer pris pÃ¥lydende kr 100 for et verdipapir med en odde første periode +ODDFYIELD = AVVIKFP.AVKASTNING ## Returnerer avkastingen for et verdipapir med en odde første periode +ODDLPRICE = AVVIKSP.PRIS ## Returnerer pris pÃ¥lydende kr 100 for et verdipapir med en odde siste periode +ODDLYIELD = AVVIKSP.AVKASTNING ## Returnerer avkastingen for et verdipapir med en odde siste periode +PMT = AVDRAG ## Returnerer periodisk betaling for en annuitet +PPMT = AMORT ## Returnerer betalingen pÃ¥ hovedstolen for en investering i en gitt periode +PRICE = PRIS ## Returnerer prisen per pÃ¥lydende kr 100 for et verdipapir som gir periodisk avkastning +PRICEDISC = PRIS.DISKONTERT ## Returnerer prisen per pÃ¥lydende kr 100 for et diskontert verdipapir +PRICEMAT = PRIS.FORFALL ## Returnerer prisen per pÃ¥lydende kr 100 av et verdipapir som betaler rente ved forfall +PV = NÃ…VERDI ## Returnerer nÃ¥verdien av en investering +RATE = RENTE ## Returnerer rentesatsen per periode for en annuitet +RECEIVED = MOTTATT.AVKAST ## Returnerer summen som mottas ved forfallsdato for et fullinvestert verdipapir +SLN = LINAVS ## Returnerer den lineære avskrivningen for et aktivum i én periode +SYD = Ã…RSAVS ## Returnerer Ã¥rsavskrivningen for et aktivum i en angitt periode +TBILLEQ = TBILLEKV ## Returnerer den obligasjonsekvivalente avkastningen for en statsobligasjon +TBILLPRICE = TBILLPRIS ## Returnerer prisen per pÃ¥lydende kr 100 for en statsobligasjon +TBILLYIELD = TBILLAVKASTNING ## Returnerer avkastningen til en statsobligasjon +VDB = VERDIAVS ## Returnerer avskrivningen for et aktivum i en angitt periode eller delperiode, ved hjelp av degressiv avskrivning +XIRR = XIR ## Returnerer internrenten for en serie kontantstrømmer som ikke nødvendigvis er periodiske +XNPV = XNNV ## Returnerer netto nÃ¥verdi for en serie kontantstrømmer som ikke nødvendigvis er periodiske +YIELD = AVKAST ## Returnerer avkastningen pÃ¥ et verdipapir som betaler periodisk rente +YIELDDISC = AVKAST.DISKONTERT ## Returnerer Ã¥rlig avkastning for et diskontert verdipapir, for eksempel en statskasseveksel +YIELDMAT = AVKAST.FORFALL ## Returnerer den Ã¥rlige avkastningen for et verdipapir som betaler rente ved forfallsdato + + +## +## Information functions Informasjonsfunksjoner +## +CELL = CELLE ## Returnerer informasjon om formatering, plassering eller innholdet til en celle +ERROR.TYPE = FEIL.TYPE ## Returnerer et tall som svarer til en feiltype +INFO = INFO ## Returnerer informasjon om gjeldende operativmiljø +ISBLANK = ERTOM ## Returnerer SANN hvis verdien er tom +ISERR = ERFEIL ## Returnerer SANN hvis verdien er en hvilken som helst annen feilverdi enn #I/T +ISERROR = ERFEIL ## Returnerer SANN hvis verdien er en hvilken som helst feilverdi +ISEVEN = ERPARTALL ## Returnerer SANN hvis tallet er et partall +ISLOGICAL = ERLOGISK ## Returnerer SANN hvis verdien er en logisk verdi +ISNA = ERIT ## Returnerer SANN hvis verdien er feilverdien #I/T +ISNONTEXT = ERIKKETEKST ## Returnerer SANN hvis verdien ikke er tekst +ISNUMBER = ERTALL ## Returnerer SANN hvis verdien er et tall +ISODD = ERODDETALL ## Returnerer SANN hvis tallet er et oddetall +ISREF = ERREF ## Returnerer SANN hvis verdien er en referanse +ISTEXT = ERTEKST ## Returnerer SANN hvis verdien er tekst +N = N ## Returnerer en verdi som er konvertert til et tall +NA = IT ## Returnerer feilverdien #I/T +TYPE = VERDITYPE ## Returnerer et tall som indikerer datatypen til en verdi + + +## +## Logical functions Logiske funksjoner +## +AND = OG ## Returnerer SANN hvis alle argumentene er lik SANN +FALSE = USANN ## Returnerer den logiske verdien USANN +IF = HVIS ## Angir en logisk test som skal utføres +IFERROR = HVISFEIL ## Returnerer en verdi du angir hvis en formel evaluerer til en feil. Ellers returnerer den resultatet av formelen. +NOT = IKKE ## Reverserer logikken til argumentet +OR = ELLER ## Returnerer SANN hvis ett eller flere argumenter er lik SANN +TRUE = SANN ## Returnerer den logiske verdien SANN + + +## +## Lookup and reference functions Oppslag- og referansefunksjoner +## +ADDRESS = ADRESSE ## Returnerer en referanse som tekst til en enkelt celle i et regneark +AREAS = OMRÃ…DER ## Returnerer antall omrÃ¥der i en referanse +CHOOSE = VELG ## Velger en verdi fra en liste med verdier +COLUMN = KOLONNE ## Returnerer kolonnenummeret for en referanse +COLUMNS = KOLONNER ## Returnerer antall kolonner i en referanse +HLOOKUP = FINN.KOLONNE ## Leter i den øverste raden i en matrise og returnerer verdien for den angitte cellen +HYPERLINK = HYPERKOBLING ## Oppretter en snarvei eller et hopp som Ã¥pner et dokument som er lagret pÃ¥ en nettverksserver, et intranett eller Internett +INDEX = INDEKS ## Bruker en indeks til Ã¥ velge en verdi fra en referanse eller matrise +INDIRECT = INDIREKTE ## Returnerer en referanse angitt av en tekstverdi +LOOKUP = SLÃ….OPP ## SlÃ¥r opp verdier i en vektor eller matrise +MATCH = SAMMENLIGNE ## SlÃ¥r opp verdier i en referanse eller matrise +OFFSET = FORSKYVNING ## Returnerer en referanseforskyvning fra en gitt referanse +ROW = RAD ## Returnerer radnummeret for en referanse +ROWS = RADER ## Returnerer antall rader i en referanse +RTD = RTD ## Henter sanntidsdata fra et program som støtter COM-automatisering (automatisering: En mÃ¥te Ã¥ arbeide pÃ¥ med programobjekter fra et annet program- eller utviklingsverktøy. Tidligere kalt OLE-automatisering. Automatisering er en bransjestandard og en funksjon i Component Object Model (COM).) +TRANSPOSE = TRANSPONER ## Returnerer transponeringen av en matrise +VLOOKUP = FINN.RAD ## Leter i den første kolonnen i en matrise og flytter bortover raden for Ã¥ returnere verdien til en celle + + +## +## Math and trigonometry functions Matematikk- og trigonometrifunksjoner +## +ABS = ABS ## Returnerer absoluttverdien til et tall +ACOS = ARCCOS ## Returnerer arcus cosinus til et tall +ACOSH = ARCCOSH ## Returnerer den inverse hyperbolske cosinus til et tall +ASIN = ARCSIN ## Returnerer arcus sinus til et tall +ASINH = ARCSINH ## Returnerer den inverse hyperbolske sinus til et tall +ATAN = ARCTAN ## Returnerer arcus tangens til et tall +ATAN2 = ARCTAN2 ## Returnerer arcus tangens fra x- og y-koordinater +ATANH = ARCTANH ## Returnerer den inverse hyperbolske tangens til et tall +CEILING = AVRUND.GJELDENDE.MULTIPLUM ## Runder av et tall til nærmeste heltall eller til nærmeste signifikante multiplum +COMBIN = KOMBINASJON ## Returnerer antall kombinasjoner for ett gitt antall objekter +COS = COS ## Returnerer cosinus til et tall +COSH = COSH ## Returnerer den hyperbolske cosinus til et tall +DEGREES = GRADER ## Konverterer radianer til grader +EVEN = AVRUND.TIL.PARTALL ## Runder av et tall oppover til nærmeste heltall som er et partall +EXP = EKSP ## Returnerer e opphøyd i en angitt potens +FACT = FAKULTET ## Returnerer fakultet til et tall +FACTDOUBLE = DOBBELFAKT ## Returnerer et talls doble fakultet +FLOOR = AVRUND.GJELDENDE.MULTIPLUM.NED ## Avrunder et tall nedover, mot null +GCD = SFF ## Returnerer høyeste felles divisor +INT = HELTALL ## Avrunder et tall nedover til nærmeste heltall +LCM = MFM ## Returnerer minste felles multiplum +LN = LN ## Returnerer den naturlige logaritmen til et tall +LOG = LOG ## Returnerer logaritmen for et tall til et angitt grunntall +LOG10 = LOG10 ## Returnerer logaritmen med grunntall 10 for et tall +MDETERM = MDETERM ## Returnerer matrisedeterminanten til en matrise +MINVERSE = MINVERS ## Returnerer den inverse matrisen til en matrise +MMULT = MMULT ## Returnerer matriseproduktet av to matriser +MOD = REST ## Returnerer resten fra en divisjon +MROUND = MRUND ## Returnerer et tall avrundet til det ønskede multiplum +MULTINOMIAL = MULTINOMINELL ## Returnerer det multinominelle for et sett med tall +ODD = AVRUND.TIL.ODDETALL ## Runder av et tall oppover til nærmeste heltall som er et oddetall +PI = PI ## Returnerer verdien av pi +POWER = OPPHØYD.I ## Returnerer resultatet av et tall opphøyd i en potens +PRODUCT = PRODUKT ## Multipliserer argumentene +QUOTIENT = KVOTIENT ## Returnerer heltallsdelen av en divisjon +RADIANS = RADIANER ## Konverterer grader til radianer +RAND = TILFELDIG ## Returnerer et tilfeldig tall mellom 0 og 1 +RANDBETWEEN = TILFELDIGMELLOM ## Returnerer et tilfeldig tall innenfor et angitt omrÃ¥de +ROMAN = ROMERTALL ## Konverterer vanlige tall til romertall, som tekst +ROUND = AVRUND ## Avrunder et tall til et angitt antall sifre +ROUNDDOWN = AVRUND.NED ## Avrunder et tall nedover, mot null +ROUNDUP = AVRUND.OPP ## Runder av et tall oppover, bort fra null +SERIESSUM = SUMMER.REKKE ## Returnerer summen av en geometrisk rekke, basert pÃ¥ formelen +SIGN = FORTEGN ## Returnerer fortegnet for et tall +SIN = SIN ## Returnerer sinus til en gitt vinkel +SINH = SINH ## Returnerer den hyperbolske sinus til et tall +SQRT = ROT ## Returnerer en positiv kvadratrot +SQRTPI = ROTPI ## Returnerer kvadratroten av (tall * pi) +SUBTOTAL = DELSUM ## Returnerer en delsum i en liste eller database +SUM = SUMMER ## Legger sammen argumentene +SUMIF = SUMMERHVIS ## Legger sammen cellene angitt ved et gitt vilkÃ¥r +SUMIFS = SUMMER.HVIS.SETT ## Legger sammen cellene i et omrÃ¥de som oppfyller flere vilkÃ¥r +SUMPRODUCT = SUMMERPRODUKT ## Returnerer summen av produktene av tilsvarende matrisekomponenter +SUMSQ = SUMMERKVADRAT ## Returnerer kvadratsummen av argumentene +SUMX2MY2 = SUMMERX2MY2 ## Returnerer summen av differansen av kvadratene for tilsvarende verdier i to matriser +SUMX2PY2 = SUMMERX2PY2 ## Returnerer summen av kvadratsummene for tilsvarende verdier i to matriser +SUMXMY2 = SUMMERXMY2 ## Returnerer summen av kvadratene av differansen for tilsvarende verdier i to matriser +TAN = TAN ## Returnerer tangens for et tall +TANH = TANH ## Returnerer den hyperbolske tangens for et tall +TRUNC = AVKORT ## Korter av et tall til et heltall + + +## +## Statistical functions Statistiske funksjoner +## +AVEDEV = GJENNOMSNITTSAVVIK ## Returnerer datapunktenes gjennomsnittlige absoluttavvik fra middelverdien +AVERAGE = GJENNOMSNITT ## Returnerer gjennomsnittet for argumentene +AVERAGEA = GJENNOMSNITTA ## Returnerer gjennomsnittet for argumentene, inkludert tall, tekst og logiske verdier +AVERAGEIF = GJENNOMSNITTHVIS ## Returnerer gjennomsnittet (aritmetisk gjennomsnitt) av alle cellene i et omrÃ¥de som oppfyller et bestemt vilkÃ¥r +AVERAGEIFS = GJENNOMSNITT.HVIS.SETT ## Returnerer gjennomsnittet (aritmetisk middelverdi) av alle celler som oppfyller flere vilkÃ¥r. +BETADIST = BETA.FORDELING ## Returnerer den kumulative betafordelingsfunksjonen +BETAINV = INVERS.BETA.FORDELING ## Returnerer den inverse verdien til fordelingsfunksjonen for en angitt betafordeling +BINOMDIST = BINOM.FORDELING ## Returnerer den individuelle binomiske sannsynlighetsfordelingen +CHIDIST = KJI.FORDELING ## Returnerer den ensidige sannsynligheten for en kjikvadrert fordeling +CHIINV = INVERS.KJI.FORDELING ## Returnerer den inverse av den ensidige sannsynligheten for den kjikvadrerte fordelingen +CHITEST = KJI.TEST ## Utfører testen for uavhengighet +CONFIDENCE = KONFIDENS ## Returnerer konfidensintervallet til gjennomsnittet for en populasjon +CORREL = KORRELASJON ## Returnerer korrelasjonskoeffisienten mellom to datasett +COUNT = ANTALL ## Teller hvor mange tall som er i argumentlisten +COUNTA = ANTALLA ## Teller hvor mange verdier som er i argumentlisten +COUNTBLANK = TELLBLANKE ## Teller antall tomme celler i et omrÃ¥de. +COUNTIF = ANTALL.HVIS ## Teller antall celler i et omrÃ¥de som oppfyller gitte vilkÃ¥r +COUNTIFS = ANTALL.HVIS.SETT ## Teller antallet ikke-tomme celler i et omrÃ¥de som oppfyller flere vilkÃ¥r +COVAR = KOVARIANS ## Returnerer kovariansen, gjennomsnittet av produktene av parvise avvik +CRITBINOM = GRENSE.BINOM ## Returnerer den minste verdien der den kumulative binomiske fordelingen er mindre enn eller lik en vilkÃ¥rsverdi +DEVSQ = AVVIK.KVADRERT ## Returnerer summen av kvadrerte avvik +EXPONDIST = EKSP.FORDELING ## Returnerer eksponentialfordelingen +FDIST = FFORDELING ## Returnerer F-sannsynlighetsfordelingen +FINV = FFORDELING.INVERS ## Returnerer den inverse av den sannsynlige F-fordelingen +FISHER = FISHER ## Returnerer Fisher-transformasjonen +FISHERINV = FISHERINV ## Returnerer den inverse av Fisher-transformasjonen +FORECAST = PROGNOSE ## Returnerer en verdi langs en lineær trend +FREQUENCY = FREKVENS ## Returnerer en frekvensdistribusjon som en loddrett matrise +FTEST = FTEST ## Returnerer resultatet av en F-test +GAMMADIST = GAMMAFORDELING ## Returnerer gammafordelingen +GAMMAINV = GAMMAINV ## Returnerer den inverse av den gammakumulative fordelingen +GAMMALN = GAMMALN ## Returnerer den naturlige logaritmen til gammafunksjonen G(x) +GEOMEAN = GJENNOMSNITT.GEOMETRISK ## Returnerer den geometriske middelverdien +GROWTH = VEKST ## Returnerer verdier langs en eksponentiell trend +HARMEAN = GJENNOMSNITT.HARMONISK ## Returnerer den harmoniske middelverdien +HYPGEOMDIST = HYPGEOM.FORDELING ## Returnerer den hypergeometriske fordelingen +INTERCEPT = SKJÆRINGSPUNKT ## Returnerer skjæringspunktet til den lineære regresjonslinjen +KURT = KURT ## Returnerer kurtosen til et datasett +LARGE = N.STØRST ## Returnerer den n-te største verdien i et datasett +LINEST = RETTLINJE ## Returnerer parameterne til en lineær trend +LOGEST = KURVE ## Returnerer parameterne til en eksponentiell trend +LOGINV = LOGINV ## Returnerer den inverse lognormale fordelingen +LOGNORMDIST = LOGNORMFORD ## Returnerer den kumulative lognormale fordelingen +MAX = STØRST ## Returnerer maksimumsverdien i en argumentliste +MAXA = MAKSA ## Returnerer maksimumsverdien i en argumentliste, inkludert tall, tekst og logiske verdier +MEDIAN = MEDIAN ## Returnerer medianen til tallene som er gitt +MIN = MIN ## Returnerer minimumsverdien i en argumentliste +MINA = MINA ## Returnerer den minste verdien i en argumentliste, inkludert tall, tekst og logiske verdier +MODE = MODUS ## Returnerer den vanligste verdien i et datasett +NEGBINOMDIST = NEGBINOM.FORDELING ## Returnerer den negative binomiske fordelingen +NORMDIST = NORMALFORDELING ## Returnerer den kumulative normalfordelingen +NORMINV = NORMINV ## Returnerer den inverse kumulative normalfordelingen +NORMSDIST = NORMSFORDELING ## Returnerer standard kumulativ normalfordeling +NORMSINV = NORMSINV ## Returnerer den inverse av den den kumulative standard normalfordelingen +PEARSON = PEARSON ## Returnerer produktmomentkorrelasjonskoeffisienten, Pearson +PERCENTILE = PERSENTIL ## Returnerer den n-te persentil av verdiene i et omrÃ¥de +PERCENTRANK = PROSENTDEL ## Returnerer prosentrangeringen av en verdi i et datasett +PERMUT = PERMUTER ## Returnerer antall permutasjoner for et gitt antall objekter +POISSON = POISSON ## Returnerer Poissons sannsynlighetsfordeling +PROB = SANNSYNLIG ## Returnerer sannsynligheten for at verdier i et omrÃ¥de ligger mellom to grenser +QUARTILE = KVARTIL ## Returnerer kvartilen til et datasett +RANK = RANG ## Returnerer rangeringen av et tall, eller plassen tallet har i en rekke +RSQ = RKVADRAT ## Returnerer kvadratet av produktmomentkorrelasjonskoeffisienten (Pearsons r) +SKEW = SKJEVFORDELING ## Returnerer skjevheten i en fordeling +SLOPE = STIGNINGSTALL ## Returnerer stigningtallet for den lineære regresjonslinjen +SMALL = N.MINST ## Returnerer den n-te minste verdien i et datasett +STANDARDIZE = NORMALISER ## Returnerer en normalisert verdi +STDEV = STDAV ## Estimere standardavvik pÃ¥ grunnlag av et utvalg +STDEVA = STDAVVIKA ## Estimerer standardavvik basert pÃ¥ et utvalg, inkludert tall, tekst og logiske verdier +STDEVP = STDAVP ## Beregner standardavvik basert pÃ¥ hele populasjonen +STDEVPA = STDAVVIKPA ## Beregner standardavvik basert pÃ¥ hele populasjonen, inkludert tall, tekst og logiske verdier +STEYX = STANDARDFEIL ## Returnerer standardfeilen for den predikerte y-verdien for hver x i regresjonen +TDIST = TFORDELING ## Returnerer en Student t-fordeling +TINV = TINV ## Returnerer den inverse Student t-fordelingen +TREND = TREND ## Returnerer verdier langs en lineær trend +TRIMMEAN = TRIMMET.GJENNOMSNITT ## Returnerer den interne middelverdien til et datasett +TTEST = TTEST ## Returnerer sannsynligheten assosiert med en Student t-test +VAR = VARIANS ## Estimerer varians basert pÃ¥ et utvalg +VARA = VARIANSA ## Estimerer varians basert pÃ¥ et utvalg, inkludert tall, tekst og logiske verdier +VARP = VARIANSP ## Beregner varians basert pÃ¥ hele populasjonen +VARPA = VARIANSPA ## Beregner varians basert pÃ¥ hele populasjonen, inkludert tall, tekst og logiske verdier +WEIBULL = WEIBULL.FORDELING ## Returnerer Weibull-fordelingen +ZTEST = ZTEST ## Returnerer den ensidige sannsynlighetsverdien for en z-test + + +## +## Text functions Tekstfunksjoner +## +ASC = STIGENDE ## Endrer fullbreddes (dobbeltbyte) engelske bokstaver eller katakana i en tegnstreng, til halvbreddes (enkeltbyte) tegn +BAHTTEXT = BAHTTEKST ## Konverterer et tall til tekst, og bruker valutaformatet ß (baht) +CHAR = TEGNKODE ## Returnerer tegnet som svarer til kodenummeret +CLEAN = RENSK ## Fjerner alle tegn som ikke kan skrives ut, fra teksten +CODE = KODE ## Returnerer en numerisk kode for det første tegnet i en tekststreng +CONCATENATE = KJEDE.SAMMEN ## SlÃ¥r sammen flere tekstelementer til ett tekstelement +DOLLAR = VALUTA ## Konverterer et tall til tekst, og bruker valutaformatet $ (dollar) +EXACT = EKSAKT ## Kontrollerer om to tekstverdier er like +FIND = FINN ## Finner en tekstverdi inne i en annen (skiller mellom store og smÃ¥ bokstaver) +FINDB = FINNB ## Finner en tekstverdi inne i en annen (skiller mellom store og smÃ¥ bokstaver) +FIXED = FASTSATT ## Formaterer et tall som tekst med et bestemt antall desimaler +JIS = JIS ## Endrer halvbreddes (enkeltbyte) engelske bokstaver eller katakana i en tegnstreng, til fullbreddes (dobbeltbyte) tegn +LEFT = VENSTRE ## Returnerer tegnene lengst til venstre i en tekstverdi +LEFTB = VENSTREB ## Returnerer tegnene lengst til venstre i en tekstverdi +LEN = LENGDE ## Returnerer antall tegn i en tekststreng +LENB = LENGDEB ## Returnerer antall tegn i en tekststreng +LOWER = SMÃ… ## Konverterer tekst til smÃ¥ bokstaver +MID = DELTEKST ## Returnerer et angitt antall tegn fra en tekststreng, og begynner fra posisjonen du angir +MIDB = DELTEKSTB ## Returnerer et angitt antall tegn fra en tekststreng, og begynner fra posisjonen du angir +PHONETIC = FURIGANA ## Trekker ut fonetiske tegn (furigana) fra en tekststreng +PROPER = STOR.FORBOKSTAV ## Gir den første bokstaven i hvert ord i en tekstverdi stor forbokstav +REPLACE = ERSTATT ## Erstatter tegn i en tekst +REPLACEB = ERSTATTB ## Erstatter tegn i en tekst +REPT = GJENTA ## Gjentar tekst et gitt antall ganger +RIGHT = HØYRE ## Returnerer tegnene lengst til høyre i en tekstverdi +RIGHTB = HØYREB ## Returnerer tegnene lengst til høyre i en tekstverdi +SEARCH = SØK ## Finner en tekstverdi inne i en annen (skiller ikke mellom store og smÃ¥ bokstaver) +SEARCHB = SØKB ## Finner en tekstverdi inne i en annen (skiller ikke mellom store og smÃ¥ bokstaver) +SUBSTITUTE = BYTT.UT ## Bytter ut gammel tekst med ny tekst i en tekststreng +T = T ## Konverterer argumentene til tekst +TEXT = TEKST ## Formaterer et tall og konverterer det til tekst +TRIM = TRIMME ## Fjerner mellomrom fra tekst +UPPER = STORE ## Konverterer tekst til store bokstaver +VALUE = VERDI ## Konverterer et tekstargument til et tall diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pl/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pl/config new file mode 100755 index 0000000..f59a149 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pl/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = zÅ‚ + + +## +## Excel Error Codes (For future use) +## +NULL = #ZERO! +DIV0 = #DZIEL/0! +VALUE = #ARG! +REF = #ADR! +NAME = #NAZWA? +NUM = #LICZBA! +NA = #N/D! diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pl/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pl/functions new file mode 100755 index 0000000..b3f0941 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pl/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions Funkcje dodatków i automatyzacji +## +GETPIVOTDATA = WEŹDANETABELI ## Zwraca dane przechowywane w raporcie tabeli przestawnej. + + +## +## Cube functions Funkcje modułów +## +CUBEKPIMEMBER = ELEMENT.KPI.MODUÅU ## Zwraca nazwÄ™, wÅ‚aÅ›ciwość i miarÄ™ kluczowego wskaźnika wydajnoÅ›ci (KPI) oraz wyÅ›wietla nazwÄ™ i wÅ‚aÅ›ciwość w komórce. Wskaźnik KPI jest miarÄ… iloÅ›ciowÄ…, takÄ… jak miesiÄ™czny zysk brutto lub kwartalna fluktuacja pracowników, używanÄ… do monitorowania wydajnoÅ›ci organizacji. +CUBEMEMBER = ELEMENT.MODUÅU ## Zwraca element lub krotkÄ™ z hierarchii moduÅ‚u. SÅ‚uży do sprawdzania, czy element lub krotka istnieje w module. +CUBEMEMBERPROPERTY = WÅAÅšCIWOŚĆ.ELEMENTU.MODUÅU ## Zwraca wartość wÅ‚aÅ›ciwoÅ›ci elementu w module. SÅ‚uży do sprawdzania, czy nazwa elementu istnieje w module, i zwracania okreÅ›lonej wÅ‚aÅ›ciwoÅ›ci dla tego elementu. +CUBERANKEDMEMBER = USZEREGOWANY.ELEMENT.MODUÅU ## Zwraca n-ty (albo uszeregowany) element zestawu. SÅ‚uży do zwracania elementu lub elementów zestawu, na przykÅ‚ad najlepszego sprzedawcy lub 10 najlepszych studentów. +CUBESET = ZESTAW.MODUÅÓW ## Definiuje obliczony zestaw elementów lub krotek, wysyÅ‚ajÄ…c wyrażenie zestawu do serwera moduÅ‚u, który tworzy zestaw i zwraca go do programu Microsoft Office Excel. +CUBESETCOUNT = LICZNIK.MODUÅÓW.ZESTAWU ## Zwraca liczbÄ™ elementów zestawu. +CUBEVALUE = WARTOŚĆ.MODUÅU ## Zwraca zagregowanÄ… wartość z moduÅ‚u. + + +## +## Database functions Funkcje baz danych +## +DAVERAGE = BD.ÅšREDNIA ## Zwraca wartość Å›redniej wybranych wpisów bazy danych. +DCOUNT = BD.ILE.REKORDÓW ## Zlicza komórki zawierajÄ…ce liczby w bazie danych. +DCOUNTA = BD.ILE.REKORDÓW.A ## Zlicza niepuste komórki w bazie danych. +DGET = BD.POLE ## WyodrÄ™bnia z bazy danych jeden rekord speÅ‚niajÄ…cy okreÅ›lone kryteria. +DMAX = BD.MAX ## Zwraca wartość maksymalnÄ… z wybranych wpisów bazy danych. +DMIN = BD.MIN ## Zwraca wartość minimalnÄ… z wybranych wpisów bazy danych. +DPRODUCT = BD.ILOCZYN ## Mnoży wartoÅ›ci w konkretnym, speÅ‚niajÄ…cym kryteria polu rekordów bazy danych. +DSTDEV = BD.ODCH.STANDARD ## Szacuje odchylenie standardowe na podstawie próbki z wybranych wpisów bazy danych. +DSTDEVP = BD.ODCH.STANDARD.POPUL ## Oblicza odchylenie standardowe na podstawie caÅ‚ej populacji wybranych wpisów bazy danych. +DSUM = BD.SUMA ## Dodaje liczby w kolumnie pól rekordów bazy danych, które speÅ‚niajÄ… kryteria. +DVAR = BD.WARIANCJA ## Szacuje wariancjÄ™ na podstawie próbki z wybranych wpisów bazy danych. +DVARP = BD.WARIANCJA.POPUL ## Oblicza wariancjÄ™ na podstawie caÅ‚ej populacji wybranych wpisów bazy danych. + + +## +## Date and time functions Funkcje dat, godzin i czasu +## +DATE = DATA ## Zwraca liczbÄ™ seryjnÄ… dla wybranej daty. +DATEVALUE = DATA.WARTOŚĆ ## Konwertuje datÄ™ w formie tekstu na liczbÄ™ seryjnÄ…. +DAY = DZIEŃ ## Konwertuje liczbÄ™ seryjnÄ… na dzieÅ„ miesiÄ…ca. +DAYS360 = DNI.360 ## Oblicza liczbÄ™ dni miÄ™dzy dwiema datami na podstawie roku 360-dniowego. +EDATE = UPÅDNI ## Zwraca liczbÄ™ seryjnÄ… daty jako wskazanÄ… liczbÄ™ miesiÄ™cy przed okreÅ›lonÄ… datÄ… poczÄ…tkowÄ… lub po niej. +EOMONTH = EOMONTH ## Zwraca liczbÄ™ seryjnÄ… ostatniego dnia miesiÄ…ca przed okreÅ›lonÄ… liczbÄ… miesiÄ™cy lub po niej. +HOUR = GODZINA ## Konwertuje liczbÄ™ seryjnÄ… na godzinÄ™. +MINUTE = MINUTA ## Konwertuje liczbÄ™ seryjnÄ… na minutÄ™. +MONTH = MIESIÄ„C ## Konwertuje liczbÄ™ seryjnÄ… na miesiÄ…c. +NETWORKDAYS = NETWORKDAYS ## Zwraca liczbÄ™ peÅ‚nych dni roboczych miÄ™dzy dwiema datami. +NOW = TERAZ ## Zwraca liczbÄ™ seryjnÄ… bieżącej daty i godziny. +SECOND = SEKUNDA ## Konwertuje liczbÄ™ seryjnÄ… na sekundÄ™. +TIME = CZAS ## Zwraca liczbÄ™ seryjnÄ… okreÅ›lonego czasu. +TIMEVALUE = CZAS.WARTOŚĆ ## Konwertuje czas w formie tekstu na liczbÄ™ seryjnÄ…. +TODAY = DZIÅš ## Zwraca liczbÄ™ seryjnÄ… dla daty bieżącej. +WEEKDAY = DZIEŃ.TYG ## Konwertuje liczbÄ™ seryjnÄ… na dzieÅ„ tygodnia. +WEEKNUM = WEEKNUM ## Konwertuje liczbÄ™ seryjnÄ… na liczbÄ™ reprezentujÄ…cÄ… numer tygodnia w roku. +WORKDAY = WORKDAY ## Zwraca liczbÄ™ seryjnÄ… dla daty przed okreÅ›lonÄ… liczbÄ… dni roboczych lub po niej. +YEAR = ROK ## Konwertuje liczbÄ™ seryjnÄ… na rok. +YEARFRAC = YEARFRAC ## Zwraca część roku reprezentowanÄ… przez peÅ‚nÄ… liczbÄ™ dni miÄ™dzy datÄ… poczÄ…tkowÄ… a datÄ… koÅ„cowÄ…. + + +## +## Engineering functions Funkcje inżynierskie +## +BESSELI = BESSELI ## Zwraca wartość zmodyfikowanej funkcji Bessela In(x). +BESSELJ = BESSELJ ## Zwraca wartość funkcji Bessela Jn(x). +BESSELK = BESSELK ## Zwraca wartość zmodyfikowanej funkcji Bessela Kn(x). +BESSELY = BESSELY ## Zwraca wartość funkcji Bessela Yn(x). +BIN2DEC = BIN2DEC ## Konwertuje liczbÄ™ w postaci dwójkowej na liczbÄ™ w postaci dziesiÄ™tnej. +BIN2HEX = BIN2HEX ## Konwertuje liczbÄ™ w postaci dwójkowej na liczbÄ™ w postaci szesnastkowej. +BIN2OCT = BIN2OCT ## Konwertuje liczbÄ™ w postaci dwójkowej na liczbÄ™ w postaci ósemkowej. +COMPLEX = COMPLEX ## Konwertuje część rzeczywistÄ… i urojonÄ… na liczbÄ™ zespolonÄ…. +CONVERT = CONVERT ## Konwertuje liczbÄ™ z jednego systemu miar na inny. +DEC2BIN = DEC2BIN ## Konwertuje liczbÄ™ w postaci dziesiÄ™tnej na postać dwójkowÄ…. +DEC2HEX = DEC2HEX ## Konwertuje liczbÄ™ w postaci dziesiÄ™tnej na liczbÄ™ w postaci szesnastkowej. +DEC2OCT = DEC2OCT ## Konwertuje liczbÄ™ w postaci dziesiÄ™tnej na liczbÄ™ w postaci ósemkowej. +DELTA = DELTA ## Sprawdza, czy dwie wartoÅ›ci sÄ… równe. +ERF = ERF ## Zwraca wartość funkcji bÅ‚Ä™du. +ERFC = ERFC ## Zwraca wartość komplementarnej funkcji bÅ‚Ä™du. +GESTEP = GESTEP ## Sprawdza, czy liczba jest wiÄ™ksza niż wartość progowa. +HEX2BIN = HEX2BIN ## Konwertuje liczbÄ™ w postaci szesnastkowej na liczbÄ™ w postaci dwójkowej. +HEX2DEC = HEX2DEC ## Konwertuje liczbÄ™ w postaci szesnastkowej na liczbÄ™ w postaci dziesiÄ™tnej. +HEX2OCT = HEX2OCT ## Konwertuje liczbÄ™ w postaci szesnastkowej na liczbÄ™ w postaci ósemkowej. +IMABS = IMABS ## Zwraca wartość bezwzglÄ™dnÄ… (moduÅ‚) liczby zespolonej. +IMAGINARY = IMAGINARY ## Zwraca wartość części urojonej liczby zespolonej. +IMARGUMENT = IMARGUMENT ## Zwraca wartość argumentu liczby zespolonej, przy czym kÄ…t wyrażony jest w radianach. +IMCONJUGATE = IMCONJUGATE ## Zwraca wartość liczby sprzężonej danej liczby zespolonej. +IMCOS = IMCOS ## Zwraca wartość cosinusa liczby zespolonej. +IMDIV = IMDIV ## Zwraca wartość ilorazu dwóch liczb zespolonych. +IMEXP = IMEXP ## Zwraca postać wykÅ‚adniczÄ… liczby zespolonej. +IMLN = IMLN ## Zwraca wartość logarytmu naturalnego liczby zespolonej. +IMLOG10 = IMLOG10 ## Zwraca wartość logarytmu dziesiÄ™tnego liczby zespolonej. +IMLOG2 = IMLOG2 ## Zwraca wartość logarytmu liczby zespolonej przy podstawie 2. +IMPOWER = IMPOWER ## Zwraca wartość liczby zespolonej podniesionej do potÄ™gi caÅ‚kowitej. +IMPRODUCT = IMPRODUCT ## Zwraca wartość iloczynu liczb zespolonych. +IMREAL = IMREAL ## Zwraca wartość części rzeczywistej liczby zespolonej. +IMSIN = IMSIN ## Zwraca wartość sinusa liczby zespolonej. +IMSQRT = IMSQRT ## Zwraca wartość pierwiastka kwadratowego z liczby zespolonej. +IMSUB = IMSUB ## Zwraca wartość różnicy dwóch liczb zespolonych. +IMSUM = IMSUM ## Zwraca wartość sumy liczb zespolonych. +OCT2BIN = OCT2BIN ## Konwertuje liczbÄ™ w postaci ósemkowej na liczbÄ™ w postaci dwójkowej. +OCT2DEC = OCT2DEC ## Konwertuje liczbÄ™ w postaci ósemkowej na liczbÄ™ w postaci dziesiÄ™tnej. +OCT2HEX = OCT2HEX ## Konwertuje liczbÄ™ w postaci ósemkowej na liczbÄ™ w postaci szesnastkowej. + + +## +## Financial functions Funkcje finansowe +## +ACCRINT = ACCRINT ## Zwraca narosÅ‚e odsetki dla papieru wartoÅ›ciowego z oprocentowaniem okresowym. +ACCRINTM = ACCRINTM ## Zwraca narosÅ‚e odsetki dla papieru wartoÅ›ciowego z oprocentowaniem w terminie wykupu. +AMORDEGRC = AMORDEGRC ## Zwraca amortyzacjÄ™ dla każdego okresu rozliczeniowego z wykorzystaniem współczynnika amortyzacji. +AMORLINC = AMORLINC ## Zwraca amortyzacjÄ™ dla każdego okresu rozliczeniowego. +COUPDAYBS = COUPDAYBS ## Zwraca liczbÄ™ dni od poczÄ…tku okresu dywidendy do dnia rozliczeniowego. +COUPDAYS = COUPDAYS ## Zwraca liczbÄ™ dni w okresie dywidendy, z uwzglÄ™dnieniem dnia rozliczeniowego. +COUPDAYSNC = COUPDAYSNC ## Zwraca liczbÄ™ dni od dnia rozliczeniowego do daty nastÄ™pnego dnia dywidendy. +COUPNCD = COUPNCD ## Zwraca dzieÅ„ nastÄ™pnej dywidendy po dniu rozliczeniowym. +COUPNUM = COUPNUM ## Zwraca liczbÄ™ dywidend pÅ‚atnych miÄ™dzy dniem rozliczeniowym a dniem wykupu. +COUPPCD = COUPPCD ## Zwraca dzieÅ„ poprzedniej dywidendy przed dniem rozliczeniowym. +CUMIPMT = CUMIPMT ## Zwraca wartość procentu skÅ‚adanego pÅ‚atnego miÄ™dzy dwoma okresami. +CUMPRINC = CUMPRINC ## Zwraca wartość kapitaÅ‚u skumulowanego spÅ‚aty pożyczki miÄ™dzy dwoma okresami. +DB = DB ## Zwraca amortyzacjÄ™ Å›rodka trwaÅ‚ego w danym okresie metodÄ… degresywnÄ… z zastosowaniem staÅ‚ej bazowej. +DDB = DDB ## Zwraca amortyzacjÄ™ Å›rodka trwaÅ‚ego za podany okres metodÄ… degresywnÄ… z zastosowaniem podwójnej bazowej lub metodÄ… okreÅ›lonÄ… przez użytkownika. +DISC = DISC ## Zwraca wartość stopy dyskontowej papieru wartoÅ›ciowego. +DOLLARDE = DOLLARDE ## Konwertuje cenÄ™ w postaci uÅ‚amkowej na cenÄ™ wyrażonÄ… w postaci dziesiÄ™tnej. +DOLLARFR = DOLLARFR ## Konwertuje cenÄ™ wyrażonÄ… w postaci dziesiÄ™tnej na cenÄ™ wyrażonÄ… w postaci uÅ‚amkowej. +DURATION = DURATION ## Zwraca wartość rocznego przychodu z papieru wartoÅ›ciowego o okresowych wypÅ‚atach oprocentowania. +EFFECT = EFFECT ## Zwraca wartość efektywnej rocznej stopy procentowej. +FV = FV ## Zwraca przyszÅ‚Ä… wartość lokaty. +FVSCHEDULE = FVSCHEDULE ## Zwraca przyszÅ‚Ä… wartość kapitaÅ‚u poczÄ…tkowego wraz z szeregiem procentów skÅ‚adanych. +INTRATE = INTRATE ## Zwraca wartość stopy procentowej papieru wartoÅ›ciowego caÅ‚kowicie ulokowanego. +IPMT = IPMT ## Zwraca wysokość spÅ‚aty oprocentowania lokaty za dany okres. +IRR = IRR ## Zwraca wartość wewnÄ™trznej stopy zwrotu dla serii przepÅ‚ywów gotówkowych. +ISPMT = ISPMT ## Oblicza wysokość spÅ‚aty oprocentowania za dany okres lokaty. +MDURATION = MDURATION ## Zwraca wartość zmodyfikowanego okresu Macauleya dla papieru wartoÅ›ciowego o zaÅ‚ożonej wartoÅ›ci nominalnej 100 zÅ‚. +MIRR = MIRR ## Zwraca wartość wewnÄ™trznej stopy zwrotu dla przypadku, gdy dodatnie i ujemne przepÅ‚ywy gotówkowe majÄ… różne stopy. +NOMINAL = NOMINAL ## Zwraca wysokość nominalnej rocznej stopy procentowej. +NPER = NPER ## Zwraca liczbÄ™ okresów dla lokaty. +NPV = NPV ## Zwraca wartość bieżącÄ… netto lokaty na podstawie szeregu okresowych przepÅ‚ywów gotówkowych i stopy dyskontowej. +ODDFPRICE = ODDFPRICE ## Zwraca cenÄ™ za 100 zÅ‚ wartoÅ›ci nominalnej papieru wartoÅ›ciowego z nietypowym pierwszym okresem. +ODDFYIELD = ODDFYIELD ## Zwraca rentowność papieru wartoÅ›ciowego z nietypowym pierwszym okresem. +ODDLPRICE = ODDLPRICE ## Zwraca cenÄ™ za 100 zÅ‚ wartoÅ›ci nominalnej papieru wartoÅ›ciowego z nietypowym ostatnim okresem. +ODDLYIELD = ODDLYIELD ## Zwraca rentowność papieru wartoÅ›ciowego z nietypowym ostatnim okresem. +PMT = PMT ## Zwraca wartość okresowej pÅ‚atnoÅ›ci raty rocznej. +PPMT = PPMT ## Zwraca wysokość spÅ‚aty kapitaÅ‚u w przypadku lokaty dla danego okresu. +PRICE = PRICE ## Zwraca cenÄ™ za 100 zÅ‚ wartoÅ›ci nominalnej papieru wartoÅ›ciowego z oprocentowaniem okresowym. +PRICEDISC = PRICEDISC ## Zwraca cenÄ™ za 100 zÅ‚ wartoÅ›ci nominalnej papieru wartoÅ›ciowego zdyskontowanego. +PRICEMAT = PRICEMAT ## Zwraca cenÄ™ za 100 zÅ‚ wartoÅ›ci nominalnej papieru wartoÅ›ciowego z oprocentowaniem w terminie wykupu. +PV = PV ## Zwraca wartość bieżącÄ… lokaty. +RATE = RATE ## Zwraca wysokość stopy procentowej w okresie raty rocznej. +RECEIVED = RECEIVED ## Zwraca wartość kapitaÅ‚u otrzymanego przy wykupie papieru wartoÅ›ciowego caÅ‚kowicie ulokowanego. +SLN = SLN ## Zwraca amortyzacjÄ™ Å›rodka trwaÅ‚ego za jeden okres metodÄ… liniowÄ…. +SYD = SYD ## Zwraca amortyzacjÄ™ Å›rodka trwaÅ‚ego za dany okres metodÄ… sumy cyfr lat amortyzacji. +TBILLEQ = TBILLEQ ## Zwraca rentowność ekwiwalentu obligacji dla bonu skarbowego. +TBILLPRICE = TBILLPRICE ## Zwraca cenÄ™ za 100 zÅ‚ wartoÅ›ci nominalnej bonu skarbowego. +TBILLYIELD = TBILLYIELD ## Zwraca rentowność bonu skarbowego. +VDB = VDB ## Oblicza amortyzacjÄ™ Å›rodka trwaÅ‚ego w danym okresie lub jego części metodÄ… degresywnÄ…. +XIRR = XIRR ## Zwraca wartość wewnÄ™trznej stopy zwrotu dla serii rozÅ‚ożonych w czasie przepÅ‚ywów gotówkowych, niekoniecznie okresowych. +XNPV = XNPV ## Zwraca wartość bieżącÄ… netto dla serii rozÅ‚ożonych w czasie przepÅ‚ywów gotówkowych, niekoniecznie okresowych. +YIELD = YIELD ## Zwraca rentowność papieru wartoÅ›ciowego z oprocentowaniem okresowym. +YIELDDISC = YIELDDISC ## Zwraca rocznÄ… rentowność zdyskontowanego papieru wartoÅ›ciowego, na przykÅ‚ad bonu skarbowego. +YIELDMAT = YIELDMAT ## Zwraca rocznÄ… rentowność papieru wartoÅ›ciowego oprocentowanego przy wykupie. + + +## +## Information functions Funkcje informacyjne +## +CELL = KOMÓRKA ## Zwraca informacje o formacie, poÅ‚ożeniu lub zawartoÅ›ci komórki. +ERROR.TYPE = NR.BÅĘDU ## Zwraca liczbÄ™ odpowiadajÄ…cÄ… typowi bÅ‚Ä™du. +INFO = INFO ## Zwraca informacjÄ™ o aktualnym Å›rodowisku pracy. +ISBLANK = CZY.PUSTA ## Zwraca wartość PRAWDA, jeÅ›li wartość jest pusta. +ISERR = CZY.BÅ ## Zwraca wartość PRAWDA, jeÅ›li wartość jest dowolnÄ… wartoÅ›ciÄ… bÅ‚Ä™du, z wyjÄ…tkiem #N/D!. +ISERROR = CZY.BÅÄ„D ## Zwraca wartość PRAWDA, jeÅ›li wartość jest dowolnÄ… wartoÅ›ciÄ… bÅ‚Ä™du. +ISEVEN = ISEVEN ## Zwraca wartość PRAWDA, jeÅ›li liczba jest parzysta. +ISLOGICAL = CZY.LOGICZNA ## Zwraca wartość PRAWDA, jeÅ›li wartość jest wartoÅ›ciÄ… logicznÄ…. +ISNA = CZY.BRAK ## Zwraca wartość PRAWDA, jeÅ›li wartość jest wartoÅ›ciÄ… bÅ‚Ä™du #N/D!. +ISNONTEXT = CZY.NIE.TEKST ## Zwraca wartość PRAWDA, jeÅ›li wartość nie jest tekstem. +ISNUMBER = CZY.LICZBA ## Zwraca wartość PRAWDA, jeÅ›li wartość jest liczbÄ…. +ISODD = ISODD ## Zwraca wartość PRAWDA, jeÅ›li liczba jest nieparzysta. +ISREF = CZY.ADR ## Zwraca wartość PRAWDA, jeÅ›li wartość jest odwoÅ‚aniem. +ISTEXT = CZY.TEKST ## Zwraca wartość PRAWDA, jeÅ›li wartość jest tekstem. +N = L ## Zwraca wartość przekonwertowanÄ… na postać liczbowÄ…. +NA = BRAK ## Zwraca wartość bÅ‚Ä™du #N/D!. +TYPE = TYP ## Zwraca liczbÄ™ wskazujÄ…cÄ… typ danych wartoÅ›ci. + + +## +## Logical functions Funkcje logiczne +## +AND = ORAZ ## Zwraca wartość PRAWDA, jeÅ›li wszystkie argumenty majÄ… wartość PRAWDA. +FALSE = FAÅSZ ## Zwraca wartość logicznÄ… FAÅSZ. +IF = JEÅ»ELI ## OkreÅ›la warunek logiczny do sprawdzenia. +IFERROR = JEÅ»ELI.BÅÄ„D ## Zwraca okreÅ›lonÄ… wartość, jeÅ›li wynikiem obliczenia formuÅ‚y jest bÅ‚Ä…d; w przeciwnym przypadku zwraca wynik formuÅ‚y. +NOT = NIE ## Odwraca wartość logicznÄ… argumentu. +OR = LUB ## Zwraca wartość PRAWDA, jeÅ›li co najmniej jeden z argumentów ma wartość PRAWDA. +TRUE = PRAWDA ## Zwraca wartość logicznÄ… PRAWDA. + + +## +## Lookup and reference functions Funkcje wyszukiwania i odwoÅ‚aÅ„ +## +ADDRESS = ADRES ## Zwraca odwoÅ‚anie do jednej komórki w arkuszu jako wartość tekstowÄ…. +AREAS = OBSZARY ## Zwraca liczbÄ™ obszarów wystÄ™pujÄ…cych w odwoÅ‚aniu. +CHOOSE = WYBIERZ ## Wybiera wartość z listy wartoÅ›ci. +COLUMN = NR.KOLUMNY ## Zwraca numer kolumny z odwoÅ‚ania. +COLUMNS = LICZBA.KOLUMN ## Zwraca liczbÄ™ kolumn dla danego odwoÅ‚ania. +HLOOKUP = WYSZUKAJ.POZIOMO ## PrzeglÄ…da górny wiersz tablicy i zwraca wartość wskazanej komórki. +HYPERLINK = HIPERÅÄ„CZE ## Tworzy skrót lub skok, który pozwala otwierać dokument przechowywany na serwerze sieciowym, w sieci intranet lub w Internecie. +INDEX = INDEKS ## Używa indeksu do wybierania wartoÅ›ci z odwoÅ‚ania lub tablicy. +INDIRECT = ADR.POÅšR ## Zwraca odwoÅ‚anie okreÅ›lone przez wartość tekstowÄ…. +LOOKUP = WYSZUKAJ ## Wyszukuje wartoÅ›ci w wektorze lub tablicy. +MATCH = PODAJ.POZYCJĘ ## Wyszukuje wartoÅ›ci w odwoÅ‚aniu lub w tablicy. +OFFSET = PRZESUNIĘCIE ## Zwraca adres przesuniÄ™ty od danego odwoÅ‚ania. +ROW = WIERSZ ## Zwraca numer wiersza odwoÅ‚ania. +ROWS = ILE.WIERSZY ## Zwraca liczbÄ™ wierszy dla danego odwoÅ‚ania. +RTD = RTD ## Pobiera dane w czasie rzeczywistym z programu obsÅ‚ugujÄ…cego automatyzacjÄ™ COM (Automatyzacja: Sposób pracy z obiektami aplikacji pochodzÄ…cymi z innej aplikacji lub narzÄ™dzia projektowania. Nazywana wczeÅ›niej AutomatyzacjÄ… OLE, Automatyzacja jest standardem przemysÅ‚owym i funkcjÄ… obiektowego modelu skÅ‚adników (COM, Component Object Model).). +TRANSPOSE = TRANSPONUJ ## Zwraca transponowanÄ… tablicÄ™. +VLOOKUP = WYSZUKAJ.PIONOWO ## Przeszukuje pierwszÄ… kolumnÄ™ tablicy i przechodzi wzdÅ‚uż wiersza, aby zwrócić wartość komórki. + + +## +## Math and trigonometry functions Funkcje matematyczne i trygonometryczne +## +ABS = MODUÅ.LICZBY ## Zwraca wartość absolutnÄ… liczby. +ACOS = ACOS ## Zwraca arcus cosinus liczby. +ACOSH = ACOSH ## Zwraca arcus cosinus hiperboliczny liczby. +ASIN = ASIN ## Zwraca arcus sinus liczby. +ASINH = ASINH ## Zwraca arcus sinus hiperboliczny liczby. +ATAN = ATAN ## Zwraca arcus tangens liczby. +ATAN2 = ATAN2 ## Zwraca arcus tangens liczby na podstawie współrzÄ™dnych x i y. +ATANH = ATANH ## Zwraca arcus tangens hiperboliczny liczby. +CEILING = ZAOKR.W.GÓRĘ ## ZaokrÄ…gla liczbÄ™ do najbliższej liczby caÅ‚kowitej lub do najbliższej wielokrotnoÅ›ci dokÅ‚adnoÅ›ci. +COMBIN = KOMBINACJE ## Zwraca liczbÄ™ kombinacji dla danej liczby obiektów. +COS = COS ## Zwraca cosinus liczby. +COSH = COSH ## Zwraca cosinus hiperboliczny liczby. +DEGREES = STOPNIE ## Konwertuje radiany na stopnie. +EVEN = ZAOKR.DO.PARZ ## ZaokrÄ…gla liczbÄ™ w górÄ™ do najbliższej liczby parzystej. +EXP = EXP ## Zwraca wartość liczby e podniesionej do potÄ™gi okreÅ›lonej przez podanÄ… liczbÄ™. +FACT = SILNIA ## Zwraca silniÄ™ liczby. +FACTDOUBLE = FACTDOUBLE ## Zwraca podwójnÄ… silniÄ™ liczby. +FLOOR = ZAOKR.W.DÓŠ## ZaokrÄ…gla liczbÄ™ w dół, w kierunku zera. +GCD = GCD ## Zwraca najwiÄ™kszy wspólny dzielnik. +INT = ZAOKR.DO.CAÅK ## ZaokrÄ…gla liczbÄ™ w dół do najbliższej liczby caÅ‚kowitej. +LCM = LCM ## Zwraca najmniejszÄ… wspólnÄ… wielokrotność. +LN = LN ## Zwraca logarytm naturalny podanej liczby. +LOG = LOG ## Zwraca logarytm danej liczby przy zadanej podstawie. +LOG10 = LOG10 ## Zwraca logarytm dziesiÄ™tny liczby. +MDETERM = WYZNACZNIK.MACIERZY ## Zwraca wyznacznik macierzy tablicy. +MINVERSE = MACIERZ.ODW ## Zwraca odwrotność macierzy tablicy. +MMULT = MACIERZ.ILOCZYN ## Zwraca iloczyn macierzy dwóch tablic. +MOD = MOD ## Zwraca resztÄ™ z dzielenia. +MROUND = MROUND ## Zwraca liczbÄ™ zaokrÄ…glonÄ… do żądanej wielokrotnoÅ›ci. +MULTINOMIAL = MULTINOMIAL ## Zwraca wielomian dla zbioru liczb. +ODD = ZAOKR.DO.NPARZ ## ZaokrÄ…gla liczbÄ™ w górÄ™ do najbliższej liczby nieparzystej. +PI = PI ## Zwraca wartość liczby Pi. +POWER = POTĘGA ## Zwraca liczbÄ™ podniesionÄ… do potÄ™gi. +PRODUCT = ILOCZYN ## Mnoży argumenty. +QUOTIENT = QUOTIENT ## Zwraca iloraz (caÅ‚kowity). +RADIANS = RADIANY ## Konwertuje stopnie na radiany. +RAND = LOS ## Zwraca liczbÄ™ pseudolosowÄ… z zakresu od 0 do 1. +RANDBETWEEN = RANDBETWEEN ## Zwraca liczbÄ™ pseudolosowÄ… z zakresu okreÅ›lonego przez podane argumenty. +ROMAN = RZYMSKIE ## Konwertuje liczbÄ™ arabskÄ… na rzymskÄ… jako tekst. +ROUND = ZAOKR ## ZaokrÄ…gla liczbÄ™ do okreÅ›lonej liczby cyfr. +ROUNDDOWN = ZAOKR.DÓŠ## ZaokrÄ…gla liczbÄ™ w dół, w kierunku zera. +ROUNDUP = ZAOKR.GÓRA ## ZaokrÄ…gla liczbÄ™ w górÄ™, w kierunku od zera. +SERIESSUM = SERIESSUM ## Zwraca sumÄ™ szeregu potÄ™gowego na podstawie wzoru. +SIGN = ZNAK.LICZBY ## Zwraca znak liczby. +SIN = SIN ## Zwraca sinus danego kÄ…ta. +SINH = SINH ## Zwraca sinus hiperboliczny liczby. +SQRT = PIERWIASTEK ## Zwraca dodatni pierwiastek kwadratowy. +SQRTPI = SQRTPI ## Zwraca pierwiastek kwadratowy iloczynu (liczba * Pi). +SUBTOTAL = SUMY.POÅšREDNIE ## Zwraca sumÄ™ częściowÄ… listy lub bazy danych. +SUM = SUMA ## Dodaje argumenty. +SUMIF = SUMA.JEÅ»ELI ## Dodaje komórki okreÅ›lone przez podane kryterium. +SUMIFS = SUMA.WARUNKÓW ## Dodaje komórki w zakresie, które speÅ‚niajÄ… wiele kryteriów. +SUMPRODUCT = SUMA.ILOCZYNÓW ## Zwraca sumÄ™ iloczynów odpowiednich elementów tablicy. +SUMSQ = SUMA.KWADRATÓW ## Zwraca sumÄ™ kwadratów argumentów. +SUMX2MY2 = SUMA.X2.M.Y2 ## Zwraca sumÄ™ różnic kwadratów odpowiednich wartoÅ›ci w dwóch tablicach. +SUMX2PY2 = SUMA.X2.P.Y2 ## Zwraca sumÄ™ sum kwadratów odpowiednich wartoÅ›ci w dwóch tablicach. +SUMXMY2 = SUMA.XMY.2 ## Zwraca sumÄ™ kwadratów różnic odpowiednich wartoÅ›ci w dwóch tablicach. +TAN = TAN ## Zwraca tangens liczby. +TANH = TANH ## Zwraca tangens hiperboliczny liczby. +TRUNC = LICZBA.CAÅK ## Przycina liczbÄ™ do wartoÅ›ci caÅ‚kowitej. + + +## +## Statistical functions Funkcje statystyczne +## +AVEDEV = ODCH.ÅšREDNIE ## Zwraca Å›redniÄ… wartość odchyleÅ„ absolutnych punktów danych od ich wartoÅ›ci Å›redniej. +AVERAGE = ÅšREDNIA ## Zwraca wartość Å›redniÄ… argumentów. +AVERAGEA = ÅšREDNIA.A ## Zwraca wartość Å›redniÄ… argumentów, z uwzglÄ™dnieniem liczb, tekstów i wartoÅ›ci logicznych. +AVERAGEIF = ÅšREDNIA.JEÅ»ELI ## Zwraca Å›redniÄ… (Å›redniÄ… arytmetycznÄ…) wszystkich komórek w zakresie, które speÅ‚niajÄ… podane kryteria. +AVERAGEIFS = ÅšREDNIA.WARUNKÓW ## Zwraca Å›redniÄ… (Å›redniÄ… arytmetycznÄ…) wszystkich komórek, które speÅ‚niajÄ… jedno lub wiÄ™cej kryteriów. +BETADIST = ROZKÅAD.BETA ## Zwraca skumulowanÄ… funkcjÄ™ gÄ™stoÅ›ci prawdopodobieÅ„stwa beta. +BETAINV = ROZKÅAD.BETA.ODW ## Zwraca odwrotność skumulowanej funkcji gÄ™stoÅ›ci prawdopodobieÅ„stwa beta. +BINOMDIST = ROZKÅAD.DWUM ## Zwraca pojedynczy skÅ‚adnik dwumianowego rozkÅ‚adu prawdopodobieÅ„stwa. +CHIDIST = ROZKÅAD.CHI ## Zwraca wartość jednostronnego prawdopodobieÅ„stwa rozkÅ‚adu chi-kwadrat. +CHIINV = ROZKÅAD.CHI.ODW ## Zwraca odwrotność wartoÅ›ci jednostronnego prawdopodobieÅ„stwa rozkÅ‚adu chi-kwadrat. +CHITEST = TEST.CHI ## Zwraca test niezależnoÅ›ci. +CONFIDENCE = UFNOŚĆ ## Zwraca interwaÅ‚ ufnoÅ›ci dla Å›redniej populacji. +CORREL = WSP.KORELACJI ## Zwraca współczynnik korelacji dwóch zbiorów danych. +COUNT = ILE.LICZB ## Zlicza liczby znajdujÄ…ce siÄ™ na liÅ›cie argumentów. +COUNTA = ILE.NIEPUSTYCH ## Zlicza wartoÅ›ci znajdujÄ…ce siÄ™ na liÅ›cie argumentów. +COUNTBLANK = LICZ.PUSTE ## Zwraca liczbÄ™ pustych komórek w pewnym zakresie. +COUNTIF = LICZ.JEÅ»ELI ## Zlicza komórki wewnÄ…trz zakresu, które speÅ‚niajÄ… podane kryteria. +COUNTIFS = LICZ.WARUNKI ## Zlicza komórki wewnÄ…trz zakresu, które speÅ‚niajÄ… wiele kryteriów. +COVAR = KOWARIANCJA ## Zwraca kowariancjÄ™, czyli Å›redniÄ… wartość iloczynów odpowiednich odchyleÅ„. +CRITBINOM = PRÓG.ROZKÅAD.DWUM ## Zwraca najmniejszÄ… wartość, dla której skumulowany rozkÅ‚ad dwumianowy jest mniejszy niż wartość kryterium lub równy jej. +DEVSQ = ODCH.KWADRATOWE ## Zwraca sumÄ™ kwadratów odchyleÅ„. +EXPONDIST = ROZKÅAD.EXP ## Zwraca rozkÅ‚ad wykÅ‚adniczy. +FDIST = ROZKÅAD.F ## Zwraca rozkÅ‚ad prawdopodobieÅ„stwa F. +FINV = ROZKÅAD.F.ODW ## Zwraca odwrotność rozkÅ‚adu prawdopodobieÅ„stwa F. +FISHER = ROZKÅAD.FISHER ## Zwraca transformacjÄ™ Fishera. +FISHERINV = ROZKÅAD.FISHER.ODW ## Zwraca odwrotność transformacji Fishera. +FORECAST = REGLINX ## Zwraca wartość trendu liniowego. +FREQUENCY = CZĘSTOŚĆ ## Zwraca rozkÅ‚ad czÄ™stotliwoÅ›ci jako tablicÄ™ pionowÄ…. +FTEST = TEST.F ## Zwraca wynik testu F. +GAMMADIST = ROZKÅAD.GAMMA ## Zwraca rozkÅ‚ad gamma. +GAMMAINV = ROZKÅAD.GAMMA.ODW ## Zwraca odwrotność skumulowanego rozkÅ‚adu gamma. +GAMMALN = ROZKÅAD.LIN.GAMMA ## Zwraca logarytm naturalny funkcji gamma, Γ(x). +GEOMEAN = ÅšREDNIA.GEOMETRYCZNA ## Zwraca Å›redniÄ… geometrycznÄ…. +GROWTH = REGEXPW ## Zwraca wartoÅ›ci trendu wykÅ‚adniczego. +HARMEAN = ÅšREDNIA.HARMONICZNA ## Zwraca Å›redniÄ… harmonicznÄ…. +HYPGEOMDIST = ROZKÅAD.HIPERGEOM ## Zwraca rozkÅ‚ad hipergeometryczny. +INTERCEPT = ODCIĘTA ## Zwraca punkt przeciÄ™cia osi pionowej z liniÄ… regresji liniowej. +KURT = KURTOZA ## Zwraca kurtozÄ™ zbioru danych. +LARGE = MAX.K ## Zwraca k-tÄ… najwiÄ™kszÄ… wartość ze zbioru danych. +LINEST = REGLINP ## Zwraca parametry trendu liniowego. +LOGEST = REGEXPP ## Zwraca parametry trendu wykÅ‚adniczego. +LOGINV = ROZKÅAD.LOG.ODW ## Zwraca odwrotność rozkÅ‚adu logarytmu naturalnego. +LOGNORMDIST = ROZKÅAD.LOG ## Zwraca skumulowany rozkÅ‚ad logarytmu naturalnego. +MAX = MAX ## Zwraca maksymalnÄ… wartość listy argumentów. +MAXA = MAX.A ## Zwraca maksymalnÄ… wartość listy argumentów, z uwzglÄ™dnieniem liczb, tekstów i wartoÅ›ci logicznych. +MEDIAN = MEDIANA ## Zwraca medianÄ™ podanych liczb. +MIN = MIN ## Zwraca minimalnÄ… wartość listy argumentów. +MINA = MIN.A ## Zwraca najmniejszÄ… wartość listy argumentów, z uwzglÄ™dnieniem liczb, tekstów i wartoÅ›ci logicznych. +MODE = WYST.NAJCZĘŚCIEJ ## Zwraca wartość najczęściej wystÄ™pujÄ…cÄ… w zbiorze danych. +NEGBINOMDIST = ROZKÅAD.DWUM.PRZEC ## Zwraca ujemny rozkÅ‚ad dwumianowy. +NORMDIST = ROZKÅAD.NORMALNY ## Zwraca rozkÅ‚ad normalny skumulowany. +NORMINV = ROZKÅAD.NORMALNY.ODW ## Zwraca odwrotność rozkÅ‚adu normalnego skumulowanego. +NORMSDIST = ROZKÅAD.NORMALNY.S ## Zwraca standardowy rozkÅ‚ad normalny skumulowany. +NORMSINV = ROZKÅAD.NORMALNY.S.ODW ## Zwraca odwrotność standardowego rozkÅ‚adu normalnego skumulowanego. +PEARSON = PEARSON ## Zwraca współczynnik korelacji momentu iloczynu Pearsona. +PERCENTILE = PERCENTYL ## Wyznacza k-ty percentyl wartoÅ›ci w zakresie. +PERCENTRANK = PROCENT.POZYCJA ## Zwraca procentowÄ… pozycjÄ™ wartoÅ›ci w zbiorze danych. +PERMUT = PERMUTACJE ## Zwraca liczbÄ™ permutacji dla danej liczby obiektów. +POISSON = ROZKÅAD.POISSON ## Zwraca rozkÅ‚ad Poissona. +PROB = PRAWDPD ## Zwraca prawdopodobieÅ„stwo, że wartoÅ›ci w zakresie leżą pomiÄ™dzy dwiema granicami. +QUARTILE = KWARTYL ## Wyznacza kwartyl zbioru danych. +RANK = POZYCJA ## Zwraca pozycjÄ™ liczby na liÅ›cie liczb. +RSQ = R.KWADRAT ## Zwraca kwadrat współczynnika korelacji momentu iloczynu Pearsona. +SKEW = SKOÅšNOŚĆ ## Zwraca skoÅ›ność rozkÅ‚adu. +SLOPE = NACHYLENIE ## Zwraca nachylenie linii regresji liniowej. +SMALL = MIN.K ## Zwraca k-tÄ… najmniejszÄ… wartość ze zbioru danych. +STANDARDIZE = NORMALIZUJ ## Zwraca wartość znormalizowanÄ…. +STDEV = ODCH.STANDARDOWE ## Szacuje odchylenie standardowe na podstawie próbki. +STDEVA = ODCH.STANDARDOWE.A ## Szacuje odchylenie standardowe na podstawie próbki, z uwzglÄ™dnieniem liczb, tekstów i wartoÅ›ci logicznych. +STDEVP = ODCH.STANDARD.POPUL ## Oblicza odchylenie standardowe na podstawie caÅ‚ej populacji. +STDEVPA = ODCH.STANDARD.POPUL.A ## Oblicza odchylenie standardowe na podstawie caÅ‚ej populacji, z uwzglÄ™dnieniem liczb, teksów i wartoÅ›ci logicznych. +STEYX = REGBÅSTD ## Zwraca bÅ‚Ä…d standardowy przewidzianej wartoÅ›ci y dla każdej wartoÅ›ci x w regresji. +TDIST = ROZKÅAD.T ## Zwraca rozkÅ‚ad t-Studenta. +TINV = ROZKÅAD.T.ODW ## Zwraca odwrotność rozkÅ‚adu t-Studenta. +TREND = REGLINW ## Zwraca wartoÅ›ci trendu liniowego. +TRIMMEAN = ÅšREDNIA.WEWN ## Zwraca Å›redniÄ… wartość dla wnÄ™trza zbioru danych. +TTEST = TEST.T ## Zwraca prawdopodobieÅ„stwo zwiÄ…zane z testem t-Studenta. +VAR = WARIANCJA ## Szacuje wariancjÄ™ na podstawie próbki. +VARA = WARIANCJA.A ## Szacuje wariancjÄ™ na podstawie próbki, z uwzglÄ™dnieniem liczb, tekstów i wartoÅ›ci logicznych. +VARP = WARIANCJA.POPUL ## Oblicza wariancjÄ™ na podstawie caÅ‚ej populacji. +VARPA = WARIANCJA.POPUL.A ## Oblicza wariancjÄ™ na podstawie caÅ‚ej populacji, z uwzglÄ™dnieniem liczb, tekstów i wartoÅ›ci logicznych. +WEIBULL = ROZKÅAD.WEIBULL ## Zwraca rozkÅ‚ad Weibulla. +ZTEST = TEST.Z ## Zwraca wartość jednostronnego prawdopodobieÅ„stwa testu z. + + +## +## Text functions Funkcje tekstowe +## +ASC = ASC ## Zamienia litery angielskie lub katakana o peÅ‚nej szerokoÅ›ci (dwubajtowe) w ciÄ…gu znaków na znaki o szerokoÅ›ci połówkowej (jednobajtowe). +BAHTTEXT = BAHTTEXT ## Konwertuje liczbÄ™ na tekst, stosujÄ…c format walutowy ß (baht). +CHAR = ZNAK ## Zwraca znak o podanym numerze kodu. +CLEAN = OCZYŚĆ ## Usuwa z tekstu wszystkie znaki, które nie mogÄ… być drukowane. +CODE = KOD ## Zwraca kod numeryczny pierwszego znaku w ciÄ…gu tekstowym. +CONCATENATE = ZÅÄ„CZ.TEKSTY ## ÅÄ…czy kilka oddzielnych tekstów w jeden tekst. +DOLLAR = KWOTA ## Konwertuje liczbÄ™ na tekst, stosujÄ…c format walutowy $ (dolar). +EXACT = PORÓWNAJ ## Sprawdza identyczność dwóch wartoÅ›ci tekstowych. +FIND = ZNAJDŹ ## Znajduje jednÄ… wartość tekstowÄ… wewnÄ…trz innej (z uwzglÄ™dnieniem wielkich i maÅ‚ych liter). +FINDB = ZNAJDŹB ## Znajduje jednÄ… wartość tekstowÄ… wewnÄ…trz innej (z uwzglÄ™dnieniem wielkich i maÅ‚ych liter). +FIXED = ZAOKR.DO.TEKST ## Formatuje liczbÄ™ jako tekst przy staÅ‚ej liczbie miejsc dziesiÄ™tnych. +JIS = JIS ## Zmienia litery angielskie lub katakana o szerokoÅ›ci połówkowej (jednobajtowe) w ciÄ…gu znaków na znaki o peÅ‚nej szerokoÅ›ci (dwubajtowe). +LEFT = LEWY ## Zwraca skrajne lewe znaki z wartoÅ›ci tekstowej. +LEFTB = LEWYB ## Zwraca skrajne lewe znaki z wartoÅ›ci tekstowej. +LEN = DÅ ## Zwraca liczbÄ™ znaków ciÄ…gu tekstowego. +LENB = DÅ.B ## Zwraca liczbÄ™ znaków ciÄ…gu tekstowego. +LOWER = LITERY.MAÅE ## Konwertuje wielkie litery tekstu na maÅ‚e litery. +MID = FRAGMENT.TEKSTU ## Zwraca okreÅ›lonÄ… liczbÄ™ znaków z ciÄ…gu tekstowego, zaczynajÄ…c od zadanej pozycji. +MIDB = FRAGMENT.TEKSTU.B ## Zwraca okreÅ›lonÄ… liczbÄ™ znaków z ciÄ…gu tekstowego, zaczynajÄ…c od zadanej pozycji. +PHONETIC = PHONETIC ## Wybiera znaki fonetyczne (furigana) z ciÄ…gu tekstowego. +PROPER = Z.WIELKIEJ.LITERY ## ZastÄ™puje pierwszÄ… literÄ™ każdego wyrazu tekstu wielkÄ… literÄ…. +REPLACE = ZASTÄ„P ## ZastÄ™puje znaki w tekÅ›cie. +REPLACEB = ZASTÄ„P.B ## ZastÄ™puje znaki w tekÅ›cie. +REPT = POWT ## Powiela tekst danÄ… liczbÄ™ razy. +RIGHT = PRAWY ## Zwraca skrajne prawe znaki z wartoÅ›ci tekstowej. +RIGHTB = PRAWYB ## Zwraca skrajne prawe znaki z wartoÅ›ci tekstowej. +SEARCH = SZUKAJ.TEKST ## Wyszukuje jednÄ… wartość tekstowÄ… wewnÄ…trz innej (bez uwzglÄ™dniania wielkoÅ›ci liter). +SEARCHB = SZUKAJ.TEKST.B ## Wyszukuje jednÄ… wartość tekstowÄ… wewnÄ…trz innej (bez uwzglÄ™dniania wielkoÅ›ci liter). +SUBSTITUTE = PODSTAW ## Podstawia nowy tekst w miejsce poprzedniego tekstu w ciÄ…gu tekstowym. +T = T ## Konwertuje argumenty na tekst. +TEXT = TEKST ## Formatuje liczbÄ™ i konwertuje jÄ… na tekst. +TRIM = USUŃ.ZBĘDNE.ODSTĘPY ## Usuwa spacje z tekstu. +UPPER = LITERY.WIELKIE ## Konwertuje znaki tekstu na wielkie litery. +VALUE = WARTOŚĆ ## Konwertuje argument tekstowy na liczbÄ™. diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/br/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/br/config new file mode 100755 index 0000000..8069df2 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/br/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = R$ + + +## +## Excel Error Codes (For future use) +## +NULL = #NULO! +DIV0 = #DIV/0! +VALUE = #VALOR! +REF = #REF! +NAME = #NOME? +NUM = #NÚM! +NA = #N/D diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/br/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/br/functions new file mode 100755 index 0000000..f3ba3a3 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/br/functions @@ -0,0 +1,408 @@ +## +## Add-in and Automation functions Funções Suplemento e Automação +## +GETPIVOTDATA = INFODADOSTABELADINÂMICA ## Retorna os dados armazenados em um relatório de tabela dinâmica + + +## +## Cube functions Funções de Cubo +## +CUBEKPIMEMBER = MEMBROKPICUBO ## Retorna o nome de um KPI (indicador de desempenho-chave), uma propriedade e uma medida e exibe o nome e a propriedade na célula. Um KPI é uma medida quantificável, como o lucro bruto mensal ou a rotatividade trimestral dos funcionários, usada para monitorar o desempenho de uma organização. +CUBEMEMBER = MEMBROCUBO ## Retorna um membro ou tupla em uma hierarquia de cubo. Use para validar se o membro ou tupla existe no cubo. +CUBEMEMBERPROPERTY = PROPRIEDADEMEMBROCUBO ## Retorna o valor da propriedade de um membro no cubo. Usada para validar a existência do nome do membro no cubo e para retornar a propriedade especificada para esse membro. +CUBERANKEDMEMBER = MEMBROCLASSIFICADOCUBO ## Retorna o enésimo membro, ou o membro ordenado, em um conjunto. Use para retornar um ou mais elementos em um conjunto, assim como o melhor vendedor ou os dez melhores alunos. +CUBESET = CONJUNTOCUBO ## Define um conjunto calculado de membros ou tuplas enviando uma expressão do conjunto para o cubo no servidor, que cria o conjunto e o retorna para o Microsoft Office Excel. +CUBESETCOUNT = CONTAGEMCONJUNTOCUBO ## Retorna o número de itens em um conjunto. +CUBEVALUE = VALORCUBO ## Retorna um valor agregado de um cubo. + + +## +## Database functions Funções de banco de dados +## +DAVERAGE = BDMÉDIA ## Retorna a média das entradas selecionadas de um banco de dados +DCOUNT = BDCONTAR ## Conta as células que contêm números em um banco de dados +DCOUNTA = BDCONTARA ## Conta células não vazias em um banco de dados +DGET = BDEXTRAIR ## Extrai de um banco de dados um único registro que corresponde a um critério específico +DMAX = BDMÃX ## Retorna o valor máximo de entradas selecionadas de um banco de dados +DMIN = BDMÃN ## Retorna o valor mínimo de entradas selecionadas de um banco de dados +DPRODUCT = BDMULTIPL ## Multiplica os valores em um campo específico de registros que correspondem ao critério em um banco de dados +DSTDEV = BDEST ## Estima o desvio padrão com base em uma amostra de entradas selecionadas de um banco de dados +DSTDEVP = BDDESVPA ## Calcula o desvio padrão com base na população inteira de entradas selecionadas de um banco de dados +DSUM = BDSOMA ## Adiciona os números à coluna de campos de registros do banco de dados que correspondem ao critério +DVAR = BDVAREST ## Estima a variância com base em uma amostra de entradas selecionadas de um banco de dados +DVARP = BDVARP ## Calcula a variância com base na população inteira de entradas selecionadas de um banco de dados + + +## +## Date and time functions Funções de data e hora +## +DATE = DATA ## Retorna o número de série de uma data específica +DATEVALUE = DATA.VALOR ## Converte uma data na forma de texto para um número de série +DAY = DIA ## Converte um número de série em um dia do mês +DAYS360 = DIAS360 ## Calcula o número de dias entre duas datas com base em um ano de 360 dias +EDATE = DATAM ## Retorna o número de série da data que é o número indicado de meses antes ou depois da data inicial +EOMONTH = FIMMÊS ## Retorna o número de série do último dia do mês antes ou depois de um número especificado de meses +HOUR = HORA ## Converte um número de série em uma hora +MINUTE = MINUTO ## Converte um número de série em um minuto +MONTH = MÊS ## Converte um número de série em um mês +NETWORKDAYS = DIATRABALHOTOTAL ## Retorna o número de dias úteis inteiros entre duas datas +NOW = AGORA ## Retorna o número de série seqüencial da data e hora atuais +SECOND = SEGUNDO ## Converte um número de série em um segundo +TIME = HORA ## Retorna o número de série de uma hora específica +TIMEVALUE = VALOR.TEMPO ## Converte um horário na forma de texto para um número de série +TODAY = HOJE ## Retorna o número de série da data de hoje +WEEKDAY = DIA.DA.SEMANA ## Converte um número de série em um dia da semana +WEEKNUM = NÚMSEMANA ## Converte um número de série em um número que representa onde a semana cai numericamente em um ano +WORKDAY = DIATRABALHO ## Retorna o número de série da data antes ou depois de um número específico de dias úteis +YEAR = ANO ## Converte um número de série em um ano +YEARFRAC = FRAÇÃOANO ## Retorna a fração do ano que representa o número de dias entre data_inicial e data_final + + +## +## Engineering functions Funções de engenharia +## +BESSELI = BESSELI ## Retorna a função de Bessel In(x) modificada +BESSELJ = BESSELJ ## Retorna a função de Bessel Jn(x) +BESSELK = BESSELK ## Retorna a função de Bessel Kn(x) modificada +BESSELY = BESSELY ## Retorna a função de Bessel Yn(x) +BIN2DEC = BIN2DEC ## Converte um número binário em decimal +BIN2HEX = BIN2HEX ## Converte um número binário em hexadecimal +BIN2OCT = BIN2OCT ## Converte um número binário em octal +COMPLEX = COMPLEX ## Converte coeficientes reais e imaginários e um número complexo +CONVERT = CONVERTER ## Converte um número de um sistema de medida para outro +DEC2BIN = DECABIN ## Converte um número decimal em binário +DEC2HEX = DECAHEX ## Converte um número decimal em hexadecimal +DEC2OCT = DECAOCT ## Converte um número decimal em octal +DELTA = DELTA ## Testa se dois valores são iguais +ERF = FUNERRO ## Retorna a função de erro +ERFC = FUNERROCOMPL ## Retorna a função de erro complementar +GESTEP = DEGRAU ## Testa se um número é maior do que um valor limite +HEX2BIN = HEXABIN ## Converte um número hexadecimal em binário +HEX2DEC = HEXADEC ## Converte um número hexadecimal em decimal +HEX2OCT = HEXAOCT ## Converte um número hexadecimal em octal +IMABS = IMABS ## Retorna o valor absoluto (módulo) de um número complexo +IMAGINARY = IMAGINÃRIO ## Retorna o coeficiente imaginário de um número complexo +IMARGUMENT = IMARG ## Retorna o argumento teta, um ângulo expresso em radianos +IMCONJUGATE = IMCONJ ## Retorna o conjugado complexo de um número complexo +IMCOS = IMCOS ## Retorna o cosseno de um número complexo +IMDIV = IMDIV ## Retorna o quociente de dois números complexos +IMEXP = IMEXP ## Retorna o exponencial de um número complexo +IMLN = IMLN ## Retorna o logaritmo natural de um número complexo +IMLOG10 = IMLOG10 ## Retorna o logaritmo de base 10 de um número complexo +IMLOG2 = IMLOG2 ## Retorna o logaritmo de base 2 de um número complexo +IMPOWER = IMPOT ## Retorna um número complexo elevado a uma potência inteira +IMPRODUCT = IMPROD ## Retorna o produto de números complexos +IMREAL = IMREAL ## Retorna o coeficiente real de um número complexo +IMSIN = IMSENO ## Retorna o seno de um número complexo +IMSQRT = IMRAIZ ## Retorna a raiz quadrada de um número complexo +IMSUB = IMSUBTR ## Retorna a diferença entre dois números complexos +IMSUM = IMSOMA ## Retorna a soma de números complexos +OCT2BIN = OCTABIN ## Converte um número octal em binário +OCT2DEC = OCTADEC ## Converte um número octal em decimal +OCT2HEX = OCTAHEX ## Converte um número octal em hexadecimal + + +## +## Financial functions Funções financeiras +## +ACCRINT = JUROSACUM ## Retorna a taxa de juros acumulados de um título que paga uma taxa periódica de juros +ACCRINTM = JUROSACUMV ## Retorna os juros acumulados de um título que paga juros no vencimento +AMORDEGRC = AMORDEGRC ## Retorna a depreciação para cada período contábil usando o coeficiente de depreciação +AMORLINC = AMORLINC ## Retorna a depreciação para cada período contábil +COUPDAYBS = CUPDIASINLIQ ## Retorna o número de dias do início do período de cupom até a data de liquidação +COUPDAYS = CUPDIAS ## Retorna o número de dias no período de cupom que contém a data de quitação +COUPDAYSNC = CUPDIASPRÓX ## Retorna o número de dias da data de liquidação até a data do próximo cupom +COUPNCD = CUPDATAPRÓX ## Retorna a próxima data de cupom após a data de quitação +COUPNUM = CUPNÚM ## Retorna o número de cupons pagáveis entre as datas de quitação e vencimento +COUPPCD = CUPDATAANT ## Retorna a data de cupom anterior à data de quitação +CUMIPMT = PGTOJURACUM ## Retorna os juros acumulados pagos entre dois períodos +CUMPRINC = PGTOCAPACUM ## Retorna o capital acumulado pago sobre um empréstimo entre dois períodos +DB = BD ## Retorna a depreciação de um ativo para um período especificado, usando o método de balanço de declínio fixo +DDB = BDD ## Retorna a depreciação de um ativo com relação a um período especificado usando o método de saldos decrescentes duplos ou qualquer outro método especificado por você +DISC = DESC ## Retorna a taxa de desconto de um título +DOLLARDE = MOEDADEC ## Converte um preço em formato de moeda, na forma fracionária, em um preço na forma decimal +DOLLARFR = MOEDAFRA ## Converte um preço, apresentado na forma decimal, em um preço apresentado na forma fracionária +DURATION = DURAÇÃO ## Retorna a duração anual de um título com pagamentos de juros periódicos +EFFECT = EFETIVA ## Retorna a taxa de juros anual efetiva +FV = VF ## Retorna o valor futuro de um investimento +FVSCHEDULE = VFPLANO ## Retorna o valor futuro de um capital inicial após a aplicação de uma série de taxas de juros compostas +INTRATE = TAXAJUROS ## Retorna a taxa de juros de um título totalmente investido +IPMT = IPGTO ## Retorna o pagamento de juros para um investimento em um determinado período +IRR = TIR ## Retorna a taxa interna de retorno de uma série de fluxos de caixa +ISPMT = ÉPGTO ## Calcula os juros pagos durante um período específico de um investimento +MDURATION = MDURAÇÃO ## Retorna a duração de Macauley modificada para um título com um valor de paridade equivalente a R$ 100 +MIRR = MTIR ## Calcula a taxa interna de retorno em que fluxos de caixa positivos e negativos são financiados com diferentes taxas +NOMINAL = NOMINAL ## Retorna a taxa de juros nominal anual +NPER = NPER ## Retorna o número de períodos de um investimento +NPV = VPL ## Retorna o valor líquido atual de um investimento com base em uma série de fluxos de caixa periódicos e em uma taxa de desconto +ODDFPRICE = PREÇOPRIMINC ## Retorna o preço por R$ 100 de valor nominal de um título com um primeiro período indefinido +ODDFYIELD = LUCROPRIMINC ## Retorna o rendimento de um título com um primeiro período indefinido +ODDLPRICE = PREÇOÚLTINC ## Retorna o preço por R$ 100 de valor nominal de um título com um último período de cupom indefinido +ODDLYIELD = LUCROÚLTINC ## Retorna o rendimento de um título com um último período indefinido +PMT = PGTO ## Retorna o pagamento periódico de uma anuidade +PPMT = PPGTO ## Retorna o pagamento de capital para determinado período de investimento +PRICE = PREÇO ## Retorna a preço por R$ 100,00 de valor nominal de um título que paga juros periódicos +PRICEDISC = PREÇODESC ## Retorna o preço por R$ 100,00 de valor nominal de um título descontado +PRICEMAT = PREÇOVENC ## Retorna o preço por R$ 100,00 de valor nominal de um título que paga juros no vencimento +PV = VP ## Retorna o valor presente de um investimento +RATE = TAXA ## Retorna a taxa de juros por período de uma anuidade +RECEIVED = RECEBER ## Retorna a quantia recebida no vencimento de um título totalmente investido +SLN = DPD ## Retorna a depreciação em linha reta de um ativo durante um período +SYD = SDA ## Retorna a depreciação dos dígitos da soma dos anos de um ativo para um período especificado +TBILLEQ = OTN ## Retorna o rendimento de um título equivalente a uma obrigação do Tesouro +TBILLPRICE = OTNVALOR ## Retorna o preço por R$ 100,00 de valor nominal de uma obrigação do Tesouro +TBILLYIELD = OTNLUCRO ## Retorna o rendimento de uma obrigação do Tesouro +VDB = BDV ## Retorna a depreciação de um ativo para um período especificado ou parcial usando um método de balanço declinante +XIRR = XTIR ## Fornece a taxa interna de retorno para um programa de fluxos de caixa que não é necessariamente periódico +XNPV = XVPL ## Retorna o valor presente líquido de um programa de fluxos de caixa que não é necessariamente periódico +YIELD = LUCRO ## Retorna o lucro de um título que paga juros periódicos +YIELDDISC = LUCRODESC ## Retorna o rendimento anual de um título descontado. Por exemplo, uma obrigação do Tesouro +YIELDMAT = LUCROVENC ## Retorna o lucro anual de um título que paga juros no vencimento + + +## +## Information functions Funções de informação +## +CELL = CÉL ## Retorna informações sobre formatação, localização ou conteúdo de uma célula +ERROR.TYPE = TIPO.ERRO ## Retorna um número correspondente a um tipo de erro +INFO = INFORMAÇÃO ## Retorna informações sobre o ambiente operacional atual +ISBLANK = ÉCÉL.VAZIA ## Retorna VERDADEIRO se o valor for vazio +ISERR = ÉERRO ## Retorna VERDADEIRO se o valor for um valor de erro diferente de #N/D +ISERROR = ÉERROS ## Retorna VERDADEIRO se o valor for um valor de erro +ISEVEN = ÉPAR ## Retorna VERDADEIRO se o número for par +ISLOGICAL = ÉLÓGICO ## Retorna VERDADEIRO se o valor for um valor lógico +ISNA = É.NÃO.DISP ## Retorna VERDADEIRO se o valor for o valor de erro #N/D +ISNONTEXT = É.NÃO.TEXTO ## Retorna VERDADEIRO se o valor for diferente de texto +ISNUMBER = ÉNÚM ## Retorna VERDADEIRO se o valor for um número +ISODD = ÉIMPAR ## Retorna VERDADEIRO se o número for ímpar +ISREF = ÉREF ## Retorna VERDADEIRO se o valor for uma referência +ISTEXT = ÉTEXTO ## Retorna VERDADEIRO se o valor for texto +N = N ## Retorna um valor convertido em um número +NA = NÃO.DISP ## Retorna o valor de erro #N/D +TYPE = TIPO ## Retorna um número indicando o tipo de dados de um valor + + +## +## Logical functions Funções lógicas +## +AND = E ## Retorna VERDADEIRO se todos os seus argumentos forem VERDADEIROS +FALSE = FALSO ## Retorna o valor lógico FALSO +IF = SE ## Especifica um teste lógico a ser executado +IFERROR = SEERRO ## Retornará um valor que você especifica se uma fórmula for avaliada para um erro; do contrário, retornará o resultado da fórmula +NOT = NÃO ## Inverte o valor lógico do argumento +OR = OU ## Retorna VERDADEIRO se um dos argumentos for VERDADEIRO +TRUE = VERDADEIRO ## Retorna o valor lógico VERDADEIRO + + +## +## Lookup and reference functions Funções de pesquisa e referência +## +ADDRESS = ENDEREÇO ## Retorna uma referência como texto para uma única célula em uma planilha +AREAS = ÃREAS ## Retorna o número de áreas em uma referência +CHOOSE = ESCOLHER ## Escolhe um valor a partir de uma lista de valores +COLUMN = COL ## Retorna o número da coluna de uma referência +COLUMNS = COLS ## Retorna o número de colunas em uma referência +HLOOKUP = PROCH ## Procura na linha superior de uma matriz e retorna o valor da célula especificada +HYPERLINK = HYPERLINK ## Cria um atalho ou salto que abre um documento armazenado em um servidor de rede, uma intranet ou na Internet +INDEX = ÃNDICE ## Usa um índice para escolher um valor de uma referência ou matriz +INDIRECT = INDIRETO ## Retorna uma referência indicada por um valor de texto +LOOKUP = PROC ## Procura valores em um vetor ou em uma matriz +MATCH = CORRESP ## Procura valores em uma referência ou em uma matriz +OFFSET = DESLOC ## Retorna um deslocamento de referência com base em uma determinada referência +ROW = LIN ## Retorna o número da linha de uma referência +ROWS = LINS ## Retorna o número de linhas em uma referência +RTD = RTD ## Recupera dados em tempo real de um programa que ofereça suporte a automação COM (automação: uma forma de trabalhar com objetos de um aplicativo a partir de outro aplicativo ou ferramenta de desenvolvimento. Chamada inicialmente de automação OLE, a automação é um padrão industrial e um recurso do modelo de objeto componente (COM).) +TRANSPOSE = TRANSPOR ## Retorna a transposição de uma matriz +VLOOKUP = PROCV ## Procura na primeira coluna de uma matriz e move ao longo da linha para retornar o valor de uma célula + + +## +## Math and trigonometry functions Funções matemáticas e trigonométricas +## +ABS = ABS ## Retorna o valor absoluto de um número +ACOS = ACOS ## Retorna o arco cosseno de um número +ACOSH = ACOSH ## Retorna o cosseno hiperbólico inverso de um número +ASIN = ASEN ## Retorna o arco seno de um número +ASINH = ASENH ## Retorna o seno hiperbólico inverso de um número +ATAN = ATAN ## Retorna o arco tangente de um número +ATAN2 = ATAN2 ## Retorna o arco tangente das coordenadas x e y especificadas +ATANH = ATANH ## Retorna a tangente hiperbólica inversa de um número +CEILING = TETO ## Arredonda um número para o inteiro mais próximo ou para o múltiplo mais próximo de significância +COMBIN = COMBIN ## Retorna o número de combinações de um determinado número de objetos +COS = COS ## Retorna o cosseno de um número +COSH = COSH ## Retorna o cosseno hiperbólico de um número +DEGREES = GRAUS ## Converte radianos em graus +EVEN = PAR ## Arredonda um número para cima até o inteiro par mais próximo +EXP = EXP ## Retorna e elevado à potência de um número especificado +FACT = FATORIAL ## Retorna o fatorial de um número +FACTDOUBLE = FATDUPLO ## Retorna o fatorial duplo de um número +FLOOR = ARREDMULTB ## Arredonda um número para baixo até zero +GCD = MDC ## Retorna o máximo divisor comum +INT = INT ## Arredonda um número para baixo até o número inteiro mais próximo +LCM = MMC ## Retorna o mínimo múltiplo comum +LN = LN ## Retorna o logaritmo natural de um número +LOG = LOG ## Retorna o logaritmo de um número de uma base especificada +LOG10 = LOG10 ## Retorna o logaritmo de base 10 de um número +MDETERM = MATRIZ.DETERM ## Retorna o determinante de uma matriz de uma variável do tipo matriz +MINVERSE = MATRIZ.INVERSO ## Retorna a matriz inversa de uma matriz +MMULT = MATRIZ.MULT ## Retorna o produto de duas matrizes +MOD = RESTO ## Retorna o resto da divisão +MROUND = MARRED ## Retorna um número arredondado ao múltiplo desejado +MULTINOMIAL = MULTINOMIAL ## Retorna o multinomial de um conjunto de números +ODD = ÃMPAR ## Arredonda um número para cima até o inteiro ímpar mais próximo +PI = PI ## Retorna o valor de Pi +POWER = POTÊNCIA ## Fornece o resultado de um número elevado a uma potência +PRODUCT = MULT ## Multiplica seus argumentos +QUOTIENT = QUOCIENTE ## Retorna a parte inteira de uma divisão +RADIANS = RADIANOS ## Converte graus em radianos +RAND = ALEATÓRIO ## Retorna um número aleatório entre 0 e 1 +RANDBETWEEN = ALEATÓRIOENTRE ## Retorna um número aleatório entre os números especificados +ROMAN = ROMANO ## Converte um algarismo arábico em romano, como texto +ROUND = ARRED ## Arredonda um número até uma quantidade especificada de dígitos +ROUNDDOWN = ARREDONDAR.PARA.BAIXO ## Arredonda um número para baixo até zero +ROUNDUP = ARREDONDAR.PARA.CIMA ## Arredonda um número para cima, afastando-o de zero +SERIESSUM = SOMASEQÜÊNCIA ## Retorna a soma de uma série polinomial baseada na fórmula +SIGN = SINAL ## Retorna o sinal de um número +SIN = SEN ## Retorna o seno de um ângulo dado +SINH = SENH ## Retorna o seno hiperbólico de um número +SQRT = RAIZ ## Retorna uma raiz quadrada positiva +SQRTPI = RAIZPI ## Retorna a raiz quadrada de (núm* pi) +SUBTOTAL = SUBTOTAL ## Retorna um subtotal em uma lista ou em um banco de dados +SUM = SOMA ## Soma seus argumentos +SUMIF = SOMASE ## Adiciona as células especificadas por um determinado critério +SUMIFS = SOMASE ## Adiciona as células em um intervalo que atende a vários critérios +SUMPRODUCT = SOMARPRODUTO ## Retorna a soma dos produtos de componentes correspondentes de matrizes +SUMSQ = SOMAQUAD ## Retorna a soma dos quadrados dos argumentos +SUMX2MY2 = SOMAX2DY2 ## Retorna a soma da diferença dos quadrados dos valores correspondentes em duas matrizes +SUMX2PY2 = SOMAX2SY2 ## Retorna a soma da soma dos quadrados dos valores correspondentes em duas matrizes +SUMXMY2 = SOMAXMY2 ## Retorna a soma dos quadrados das diferenças dos valores correspondentes em duas matrizes +TAN = TAN ## Retorna a tangente de um número +TANH = TANH ## Retorna a tangente hiperbólica de um número +TRUNC = TRUNCAR ## Trunca um número para um inteiro + + +## +## Statistical functions Funções estatísticas +## +AVEDEV = DESV.MÉDIO ## Retorna a média aritmética dos desvios médios dos pontos de dados a partir de sua média +AVERAGE = MÉDIA ## Retorna a média dos argumentos +AVERAGEA = MÉDIAA ## Retorna a média dos argumentos, inclusive números, texto e valores lógicos +AVERAGEIF = MÉDIASE ## Retorna a média (média aritmética) de todas as células em um intervalo que atendem a um determinado critério +AVERAGEIFS = MÉDIASES ## Retorna a média (média aritmética) de todas as células que atendem a múltiplos critérios. +BETADIST = DISTBETA ## Retorna a função de distribuição cumulativa beta +BETAINV = BETA.ACUM.INV ## Retorna o inverso da função de distribuição cumulativa para uma distribuição beta especificada +BINOMDIST = DISTRBINOM ## Retorna a probabilidade de distribuição binomial do termo individual +CHIDIST = DIST.QUI ## Retorna a probabilidade unicaudal da distribuição qui-quadrada +CHIINV = INV.QUI ## Retorna o inverso da probabilidade uni-caudal da distribuição qui-quadrada +CHITEST = TESTE.QUI ## Retorna o teste para independência +CONFIDENCE = INT.CONFIANÇA ## Retorna o intervalo de confiança para uma média da população +CORREL = CORREL ## Retorna o coeficiente de correlação entre dois conjuntos de dados +COUNT = CONT.NÚM ## Calcula quantos números há na lista de argumentos +COUNTA = CONT.VALORES ## Calcula quantos valores há na lista de argumentos +COUNTBLANK = CONTAR.VAZIO ## Conta o número de células vazias no intervalo especificado +COUNTIF = CONT.SE ## Calcula o número de células não vazias em um intervalo que corresponde a determinados critérios +COUNTIFS = CONT.SES ## Conta o número de células dentro de um intervalo que atende a múltiplos critérios +COVAR = COVAR ## Retorna a covariância, a média dos produtos dos desvios pares +CRITBINOM = CRIT.BINOM ## Retorna o menor valor para o qual a distribuição binomial cumulativa é menor ou igual ao valor padrão +DEVSQ = DESVQ ## Retorna a soma dos quadrados dos desvios +EXPONDIST = DISTEXPON ## Retorna a distribuição exponencial +FDIST = DISTF ## Retorna a distribuição de probabilidade F +FINV = INVF ## Retorna o inverso da distribuição de probabilidades F +FISHER = FISHER ## Retorna a transformação Fisher +FISHERINV = FISHERINV ## Retorna o inverso da transformação Fisher +FORECAST = PREVISÃO ## Retorna um valor ao longo de uma linha reta +FREQUENCY = FREQÜÊNCIA ## Retorna uma distribuição de freqüência como uma matriz vertical +FTEST = TESTEF ## Retorna o resultado de um teste F +GAMMADIST = DISTGAMA ## Retorna a distribuição gama +GAMMAINV = INVGAMA ## Retorna o inverso da distribuição cumulativa gama +GAMMALN = LNGAMA ## Retorna o logaritmo natural da função gama, G(x) +GEOMEAN = MÉDIA.GEOMÉTRICA ## Retorna a média geométrica +GROWTH = CRESCIMENTO ## Retorna valores ao longo de uma tendência exponencial +HARMEAN = MÉDIA.HARMÔNICA ## Retorna a média harmônica +HYPGEOMDIST = DIST.HIPERGEOM ## Retorna a distribuição hipergeométrica +INTERCEPT = INTERCEPÇÃO ## Retorna a intercepção da linha de regressão linear +KURT = CURT ## Retorna a curtose de um conjunto de dados +LARGE = MAIOR ## Retorna o maior valor k-ésimo de um conjunto de dados +LINEST = PROJ.LIN ## Retorna os parâmetros de uma tendência linear +LOGEST = PROJ.LOG ## Retorna os parâmetros de uma tendência exponencial +LOGINV = INVLOG ## Retorna o inverso da distribuição lognormal +LOGNORMDIST = DIST.LOGNORMAL ## Retorna a distribuição lognormal cumulativa +MAX = MÃXIMO ## Retorna o valor máximo em uma lista de argumentos +MAXA = MÃXIMOA ## Retorna o maior valor em uma lista de argumentos, inclusive números, texto e valores lógicos +MEDIAN = MED ## Retorna a mediana dos números indicados +MIN = MÃNIMO ## Retorna o valor mínimo em uma lista de argumentos +MINA = MÃNIMOA ## Retorna o menor valor em uma lista de argumentos, inclusive números, texto e valores lógicos +MODE = MODO ## Retorna o valor mais comum em um conjunto de dados +NEGBINOMDIST = DIST.BIN.NEG ## Retorna a distribuição binomial negativa +NORMDIST = DIST.NORM ## Retorna a distribuição cumulativa normal +NORMINV = INV.NORM ## Retorna o inverso da distribuição cumulativa normal +NORMSDIST = DIST.NORMP ## Retorna a distribuição cumulativa normal padrão +NORMSINV = INV.NORMP ## Retorna o inverso da distribuição cumulativa normal padrão +PEARSON = PEARSON ## Retorna o coeficiente de correlação do momento do produto Pearson +PERCENTILE = PERCENTIL ## Retorna o k-ésimo percentil de valores em um intervalo +PERCENTRANK = ORDEM.PORCENTUAL ## Retorna a ordem percentual de um valor em um conjunto de dados +PERMUT = PERMUT ## Retorna o número de permutações de um determinado número de objetos +POISSON = POISSON ## Retorna a distribuição Poisson +PROB = PROB ## Retorna a probabilidade de valores em um intervalo estarem entre dois limites +QUARTILE = QUARTIL ## Retorna o quartil do conjunto de dados +RANK = ORDEM ## Retorna a posição de um número em uma lista de números +RSQ = RQUAD ## Retorna o quadrado do coeficiente de correlação do momento do produto de Pearson +SKEW = DISTORÇÃO ## Retorna a distorção de uma distribuição +SLOPE = INCLINAÇÃO ## Retorna a inclinação da linha de regressão linear +SMALL = MENOR ## Retorna o menor valor k-ésimo do conjunto de dados +STANDARDIZE = PADRONIZAR ## Retorna um valor normalizado +STDEV = DESVPAD ## Estima o desvio padrão com base em uma amostra +STDEVA = DESVPADA ## Estima o desvio padrão com base em uma amostra, inclusive números, texto e valores lógicos +STDEVP = DESVPADP ## Calcula o desvio padrão com base na população total +STDEVPA = DESVPADPA ## Calcula o desvio padrão com base na população total, inclusive números, texto e valores lógicos +STEYX = EPADYX ## Retorna o erro padrão do valor-y previsto para cada x da regressão +TDIST = DISTT ## Retorna a distribuição t de Student +TINV = INVT ## Retorna o inverso da distribuição t de Student +TREND = TENDÊNCIA ## Retorna valores ao longo de uma tendência linear +TRIMMEAN = MÉDIA.INTERNA ## Retorna a média do interior de um conjunto de dados +TTEST = TESTET ## Retorna a probabilidade associada ao teste t de Student +VAR = VAR ## Estima a variância com base em uma amostra +VARA = VARA ## Estima a variância com base em uma amostra, inclusive números, texto e valores lógicos +VARP = VARP ## Calcula a variância com base na população inteira +VARPA = VARPA ## Calcula a variância com base na população total, inclusive números, texto e valores lógicos +WEIBULL = WEIBULL ## Retorna a distribuição Weibull +ZTEST = TESTEZ ## Retorna o valor de probabilidade uni-caudal de um teste-z + + +## +## Text functions Funções de texto +## +ASC = ASC ## Altera letras do inglês ou katakana de largura total (bytes duplos) dentro de uma seqüência de caracteres para caracteres de meia largura (byte único) +BAHTTEXT = BAHTTEXT ## Converte um número em um texto, usando o formato de moeda ß (baht) +CHAR = CARACT ## Retorna o caractere especificado pelo número de código +CLEAN = TIRAR ## Remove todos os caracteres do texto que não podem ser impressos +CODE = CÓDIGO ## Retorna um código numérico para o primeiro caractere de uma seqüência de caracteres de texto +CONCATENATE = CONCATENAR ## Agrupa vários itens de texto em um único item de texto +DOLLAR = MOEDA ## Converte um número em texto, usando o formato de moeda $ (dólar) +EXACT = EXATO ## Verifica se dois valores de texto são idênticos +FIND = PROCURAR ## Procura um valor de texto dentro de outro (diferencia maiúsculas de minúsculas) +FINDB = PROCURARB ## Procura um valor de texto dentro de outro (diferencia maiúsculas de minúsculas) +FIXED = DEF.NÚM.DEC ## Formata um número como texto com um número fixo de decimais +JIS = JIS ## Altera letras do inglês ou katakana de meia largura (byte único) dentro de uma seqüência de caracteres para caracteres de largura total (bytes duplos) +LEFT = ESQUERDA ## Retorna os caracteres mais à esquerda de um valor de texto +LEFTB = ESQUERDAB ## Retorna os caracteres mais à esquerda de um valor de texto +LEN = NÚM.CARACT ## Retorna o número de caracteres em uma seqüência de texto +LENB = NÚM.CARACTB ## Retorna o número de caracteres em uma seqüência de texto +LOWER = MINÚSCULA ## Converte texto para minúsculas +MID = EXT.TEXTO ## Retorna um número específico de caracteres de uma seqüência de texto começando na posição especificada +MIDB = EXT.TEXTOB ## Retorna um número específico de caracteres de uma seqüência de texto começando na posição especificada +PHONETIC = FONÉTICA ## Extrai os caracteres fonéticos (furigana) de uma seqüência de caracteres de texto +PROPER = PRI.MAIÚSCULA ## Coloca a primeira letra de cada palavra em maiúscula em um valor de texto +REPLACE = MUDAR ## Muda os caracteres dentro do texto +REPLACEB = MUDARB ## Muda os caracteres dentro do texto +REPT = REPT ## Repete o texto um determinado número de vezes +RIGHT = DIREITA ## Retorna os caracteres mais à direita de um valor de texto +RIGHTB = DIREITAB ## Retorna os caracteres mais à direita de um valor de texto +SEARCH = LOCALIZAR ## Localiza um valor de texto dentro de outro (não diferencia maiúsculas de minúsculas) +SEARCHB = LOCALIZARB ## Localiza um valor de texto dentro de outro (não diferencia maiúsculas de minúsculas) +SUBSTITUTE = SUBSTITUIR ## Substitui um novo texto por um texto antigo em uma seqüência de texto +T = T ## Converte os argumentos em texto +TEXT = TEXTO ## Formata um número e o converte em texto +TRIM = ARRUMAR ## Remove espaços do texto +UPPER = MAIÚSCULA ## Converte o texto em maiúsculas +VALUE = VALOR ## Converte um argumento de texto em um número diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/config new file mode 100755 index 0000000..b6d2bfb --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = € + + +## +## Excel Error Codes (For future use) +## +NULL = #NULO! +DIV0 = #DIV/0! +VALUE = #VALOR! +REF = #REF! +NAME = #NOME? +NUM = #NÚM! +NA = #N/D diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/functions new file mode 100755 index 0000000..7fe9e3b --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/pt/functions @@ -0,0 +1,408 @@ +## +## Add-in and Automation functions Funções de Suplemento e Automatização +## +GETPIVOTDATA = OBTERDADOSDIN ## Devolve dados armazenados num relatório de Tabela Dinâmica + + +## +## Cube functions Funções de cubo +## +CUBEKPIMEMBER = MEMBROKPICUBO ## Devolve o nome, propriedade e medição de um KPI (key performance indicator) e apresenta o nome e a propriedade na célula. Um KPI é uma medida quantificável, como, por exemplo, o lucro mensal bruto ou a rotatividade trimestral de pessoal, utilizada para monitorizar o desempenho de uma organização. +CUBEMEMBER = MEMBROCUBO ## Devolve um membro ou cadeia de identificação numa hierarquia de cubo. Utilizada para validar a existência do membro ou cadeia de identificação no cubo. +CUBEMEMBERPROPERTY = PROPRIEDADEMEMBROCUBO ## Devolve o valor de uma propriedade de membro no cubo. Utilizada para validar a existência de um nome de membro no cubo e para devolver a propriedade especificada para esse membro. +CUBERANKEDMEMBER = MEMBROCLASSIFICADOCUBO ## Devolve o enésimo ou a classificação mais alta num conjunto. Utilizada para devolver um ou mais elementos num conjunto, tal como o melhor vendedor ou os 10 melhores alunos. +CUBESET = CONJUNTOCUBO ## Define um conjunto calculado de membros ou cadeias de identificação enviando uma expressão de conjunto para o cubo no servidor, que cria o conjunto e, em seguida, devolve o conjunto ao Microsoft Office Excel. +CUBESETCOUNT = CONTARCONJUNTOCUBO ## Devolve o número de itens num conjunto. +CUBEVALUE = VALORCUBO ## Devolve um valor agregado do cubo. + + +## +## Database functions Funções de base de dados +## +DAVERAGE = BDMÉDIA ## Devolve a média das entradas da base de dados seleccionadas +DCOUNT = BDCONTAR ## Conta as células que contêm números numa base de dados +DCOUNTA = BDCONTAR.VAL ## Conta as células que não estejam em branco numa base de dados +DGET = BDOBTER ## Extrai de uma base de dados um único registo que corresponde aos critérios especificados +DMAX = BDMÃX ## Devolve o valor máximo das entradas da base de dados seleccionadas +DMIN = BDMÃN ## Devolve o valor mínimo das entradas da base de dados seleccionadas +DPRODUCT = BDMULTIPL ## Multiplica os valores de um determinado campo de registos que correspondem aos critérios numa base de dados +DSTDEV = BDDESVPAD ## Calcula o desvio-padrão com base numa amostra de entradas da base de dados seleccionadas +DSTDEVP = BDDESVPADP ## Calcula o desvio-padrão com base na população total das entradas da base de dados seleccionadas +DSUM = BDSOMA ## Adiciona os números na coluna de campo dos registos de base de dados que correspondem aos critérios +DVAR = BDVAR ## Calcula a variância com base numa amostra das entradas de base de dados seleccionadas +DVARP = BDVARP ## Calcula a variância com base na população total das entradas de base de dados seleccionadas + + +## +## Date and time functions Funções de data e hora +## +DATE = DATA ## Devolve o número de série de uma determinada data +DATEVALUE = DATA.VALOR ## Converte uma data em forma de texto num número de série +DAY = DIA ## Converte um número de série num dia do mês +DAYS360 = DIAS360 ## Calcula o número de dias entre duas datas com base num ano com 360 dias +EDATE = DATAM ## Devolve um número de série de data que corresponde ao número de meses indicado antes ou depois da data de início +EOMONTH = FIMMÊS ## Devolve o número de série do último dia do mês antes ou depois de um número de meses especificado +HOUR = HORA ## Converte um número de série numa hora +MINUTE = MINUTO ## Converte um número de série num minuto +MONTH = MÊS ## Converte um número de série num mês +NETWORKDAYS = DIATRABALHOTOTAL ## Devolve o número total de dias úteis entre duas datas +NOW = AGORA ## Devolve o número de série da data e hora actuais +SECOND = SEGUNDO ## Converte um número de série num segundo +TIME = TEMPO ## Devolve o número de série de um determinado tempo +TIMEVALUE = VALOR.TEMPO ## Converte um tempo em forma de texto num número de série +TODAY = HOJE ## Devolve o número de série da data actual +WEEKDAY = DIA.SEMANA ## Converte um número de série num dia da semana +WEEKNUM = NÚMSEMANA ## Converte um número de série num número que representa o número da semana num determinado ano +WORKDAY = DIA.TRABALHO ## Devolve o número de série da data antes ou depois de um número de dias úteis especificado +YEAR = ANO ## Converte um número de série num ano +YEARFRAC = FRACÇÃOANO ## Devolve a fracção de ano que representa o número de dias inteiros entre a data_de_início e a data_de_fim + + +## +## Engineering functions Funções de engenharia +## +BESSELI = BESSELI ## Devolve a função de Bessel modificada In(x) +BESSELJ = BESSELJ ## Devolve a função de Bessel Jn(x) +BESSELK = BESSELK ## Devolve a função de Bessel modificada Kn(x) +BESSELY = BESSELY ## Devolve a função de Bessel Yn(x) +BIN2DEC = BINADEC ## Converte um número binário em decimal +BIN2HEX = BINAHEX ## Converte um número binário em hexadecimal +BIN2OCT = BINAOCT ## Converte um número binário em octal +COMPLEX = COMPLEXO ## Converte coeficientes reais e imaginários num número complexo +CONVERT = CONVERTER ## Converte um número de um sistema de medida noutro +DEC2BIN = DECABIN ## Converte um número decimal em binário +DEC2HEX = DECAHEX ## Converte um número decimal em hexadecimal +DEC2OCT = DECAOCT ## Converte um número decimal em octal +DELTA = DELTA ## Testa se dois valores são iguais +ERF = FUNCERRO ## Devolve a função de erro +ERFC = FUNCERROCOMPL ## Devolve a função de erro complementar +GESTEP = DEGRAU ## Testa se um número é maior do que um valor limite +HEX2BIN = HEXABIN ## Converte um número hexadecimal em binário +HEX2DEC = HEXADEC ## Converte um número hexadecimal em decimal +HEX2OCT = HEXAOCT ## Converte um número hexadecimal em octal +IMABS = IMABS ## Devolve o valor absoluto (módulo) de um número complexo +IMAGINARY = IMAGINÃRIO ## Devolve o coeficiente imaginário de um número complexo +IMARGUMENT = IMARG ## Devolve o argumento Teta, um ângulo expresso em radianos +IMCONJUGATE = IMCONJ ## Devolve o conjugado complexo de um número complexo +IMCOS = IMCOS ## Devolve o co-seno de um número complexo +IMDIV = IMDIV ## Devolve o quociente de dois números complexos +IMEXP = IMEXP ## Devolve o exponencial de um número complexo +IMLN = IMLN ## Devolve o logaritmo natural de um número complexo +IMLOG10 = IMLOG10 ## Devolve o logaritmo de base 10 de um número complexo +IMLOG2 = IMLOG2 ## Devolve o logaritmo de base 2 de um número complexo +IMPOWER = IMPOT ## Devolve um número complexo elevado a uma potência inteira +IMPRODUCT = IMPROD ## Devolve o produto de números complexos +IMREAL = IMREAL ## Devolve o coeficiente real de um número complexo +IMSIN = IMSENO ## Devolve o seno de um número complexo +IMSQRT = IMRAIZ ## Devolve a raiz quadrada de um número complexo +IMSUB = IMSUBTR ## Devolve a diferença entre dois números complexos +IMSUM = IMSOMA ## Devolve a soma de números complexos +OCT2BIN = OCTABIN ## Converte um número octal em binário +OCT2DEC = OCTADEC ## Converte um número octal em decimal +OCT2HEX = OCTAHEX ## Converte um número octal em hexadecimal + + +## +## Financial functions Funções financeiras +## +ACCRINT = JUROSACUM ## Devolve os juros acumulados de um título que paga juros periódicos +ACCRINTM = JUROSACUMV ## Devolve os juros acumulados de um título que paga juros no vencimento +AMORDEGRC = AMORDEGRC ## Devolve a depreciação correspondente a cada período contabilístico utilizando um coeficiente de depreciação +AMORLINC = AMORLINC ## Devolve a depreciação correspondente a cada período contabilístico +COUPDAYBS = CUPDIASINLIQ ## Devolve o número de dias entre o início do período do cupão e a data de regularização +COUPDAYS = CUPDIAS ## Devolve o número de dias no período do cupão que contém a data de regularização +COUPDAYSNC = CUPDIASPRÓX ## Devolve o número de dias entre a data de regularização e a data do cupão seguinte +COUPNCD = CUPDATAPRÓX ## Devolve a data do cupão seguinte após a data de regularização +COUPNUM = CUPNÚM ## Devolve o número de cupões a serem pagos entre a data de regularização e a data de vencimento +COUPPCD = CUPDATAANT ## Devolve a data do cupão anterior antes da data de regularização +CUMIPMT = PGTOJURACUM ## Devolve os juros cumulativos pagos entre dois períodos +CUMPRINC = PGTOCAPACUM ## Devolve o capital cumulativo pago a título de empréstimo entre dois períodos +DB = BD ## Devolve a depreciação de um activo relativo a um período especificado utilizando o método das quotas degressivas fixas +DDB = BDD ## Devolve a depreciação de um activo relativo a um período especificado utilizando o método das quotas degressivas duplas ou qualquer outro método especificado +DISC = DESC ## Devolve a taxa de desconto de um título +DOLLARDE = MOEDADEC ## Converte um preço em unidade monetária, expresso como uma fracção, num preço em unidade monetária, expresso como um número decimal +DOLLARFR = MOEDAFRA ## Converte um preço em unidade monetária, expresso como um número decimal, num preço em unidade monetária, expresso como uma fracção +DURATION = DURAÇÃO ## Devolve a duração anual de um título com pagamentos de juros periódicos +EFFECT = EFECTIVA ## Devolve a taxa de juros anual efectiva +FV = VF ## Devolve o valor futuro de um investimento +FVSCHEDULE = VFPLANO ## Devolve o valor futuro de um capital inicial após a aplicação de uma série de taxas de juro compostas +INTRATE = TAXAJUROS ## Devolve a taxa de juros de um título investido na totalidade +IPMT = IPGTO ## Devolve o pagamento dos juros de um investimento durante um determinado período +IRR = TIR ## Devolve a taxa de rentabilidade interna para uma série de fluxos monetários +ISPMT = É.PGTO ## Calcula os juros pagos durante um período específico de um investimento +MDURATION = MDURAÇÃO ## Devolve a duração modificada de Macauley de um título com um valor de paridade equivalente a € 100 +MIRR = MTIR ## Devolve a taxa interna de rentabilidade em que os fluxos monetários positivos e negativos são financiados com taxas diferentes +NOMINAL = NOMINAL ## Devolve a taxa de juros nominal anual +NPER = NPER ## Devolve o número de períodos de um investimento +NPV = VAL ## Devolve o valor actual líquido de um investimento com base numa série de fluxos monetários periódicos e numa taxa de desconto +ODDFPRICE = PREÇOPRIMINC ## Devolve o preço por € 100 do valor nominal de um título com um período inicial incompleto +ODDFYIELD = LUCROPRIMINC ## Devolve o lucro de um título com um período inicial incompleto +ODDLPRICE = PREÇOÚLTINC ## Devolve o preço por € 100 do valor nominal de um título com um período final incompleto +ODDLYIELD = LUCROÚLTINC ## Devolve o lucro de um título com um período final incompleto +PMT = PGTO ## Devolve o pagamento periódico de uma anuidade +PPMT = PPGTO ## Devolve o pagamento sobre o capital de um investimento num determinado período +PRICE = PREÇO ## Devolve o preço por € 100 do valor nominal de um título que paga juros periódicos +PRICEDISC = PREÇODESC ## Devolve o preço por € 100 do valor nominal de um título descontado +PRICEMAT = PREÇOVENC ## Devolve o preço por € 100 do valor nominal de um título que paga juros no vencimento +PV = VA ## Devolve o valor actual de um investimento +RATE = TAXA ## Devolve a taxa de juros por período de uma anuidade +RECEIVED = RECEBER ## Devolve o montante recebido no vencimento de um título investido na totalidade +SLN = AMORT ## Devolve uma depreciação linear de um activo durante um período +SYD = AMORTD ## Devolve a depreciação por algarismos da soma dos anos de um activo durante um período especificado +TBILLEQ = OTN ## Devolve o lucro de um título equivalente a uma Obrigação do Tesouro +TBILLPRICE = OTNVALOR ## Devolve o preço por € 100 de valor nominal de uma Obrigação do Tesouro +TBILLYIELD = OTNLUCRO ## Devolve o lucro de uma Obrigação do Tesouro +VDB = BDV ## Devolve a depreciação de um activo relativo a um período específico ou parcial utilizando um método de quotas degressivas +XIRR = XTIR ## Devolve a taxa interna de rentabilidade de um plano de fluxos monetários que não seja necessariamente periódica +XNPV = XVAL ## Devolve o valor actual líquido de um plano de fluxos monetários que não seja necessariamente periódico +YIELD = LUCRO ## Devolve o lucro de um título que paga juros periódicos +YIELDDISC = LUCRODESC ## Devolve o lucro anual de um título emitido abaixo do valor nominal, por exemplo, uma Obrigação do Tesouro +YIELDMAT = LUCROVENC ## Devolve o lucro anual de um título que paga juros na data de vencimento + + +## +## Information functions Funções de informação +## +CELL = CÉL ## Devolve informações sobre a formatação, localização ou conteúdo de uma célula +ERROR.TYPE = TIPO.ERRO ## Devolve um número correspondente a um tipo de erro +INFO = INFORMAÇÃO ## Devolve informações sobre o ambiente de funcionamento actual +ISBLANK = É.CÉL.VAZIA ## Devolve VERDADEIRO se o valor estiver em branco +ISERR = É.ERROS ## Devolve VERDADEIRO se o valor for um valor de erro diferente de #N/D +ISERROR = É.ERRO ## Devolve VERDADEIRO se o valor for um valor de erro +ISEVEN = ÉPAR ## Devolve VERDADEIRO se o número for par +ISLOGICAL = É.LÓGICO ## Devolve VERDADEIRO se o valor for lógico +ISNA = É.NÃO.DISP ## Devolve VERDADEIRO se o valor for o valor de erro #N/D +ISNONTEXT = É.NÃO.TEXTO ## Devolve VERDADEIRO se o valor não for texto +ISNUMBER = É.NÚM ## Devolve VERDADEIRO se o valor for um número +ISODD = ÉÃMPAR ## Devolve VERDADEIRO se o número for ímpar +ISREF = É.REF ## Devolve VERDADEIRO se o valor for uma referência +ISTEXT = É.TEXTO ## Devolve VERDADEIRO se o valor for texto +N = N ## Devolve um valor convertido num número +NA = NÃO.DISP ## Devolve o valor de erro #N/D +TYPE = TIPO ## Devolve um número que indica o tipo de dados de um valor + + +## +## Logical functions Funções lógicas +## +AND = E ## Devolve VERDADEIRO se todos os respectivos argumentos corresponderem a VERDADEIRO +FALSE = FALSO ## Devolve o valor lógico FALSO +IF = SE ## Especifica um teste lógico a ser executado +IFERROR = SE.ERRO ## Devolve um valor definido pelo utilizador se ocorrer um erro na fórmula, e devolve o resultado da fórmula se não ocorrer nenhum erro +NOT = NÃO ## Inverte a lógica do respectivo argumento +OR = OU ## Devolve VERDADEIRO se qualquer argumento for VERDADEIRO +TRUE = VERDADEIRO ## Devolve o valor lógico VERDADEIRO + + +## +## Lookup and reference functions Funções de pesquisa e referência +## +ADDRESS = ENDEREÇO ## Devolve uma referência a uma única célula numa folha de cálculo como texto +AREAS = ÃREAS ## Devolve o número de áreas numa referência +CHOOSE = SELECCIONAR ## Selecciona um valor a partir de uma lista de valores +COLUMN = COL ## Devolve o número da coluna de uma referência +COLUMNS = COLS ## Devolve o número de colunas numa referência +HLOOKUP = PROCH ## Procura na linha superior de uma matriz e devolve o valor da célula indicada +HYPERLINK = HIPERLIGAÇÃO ## Cria um atalho ou hiperligação que abre um documento armazenado num servidor de rede, numa intranet ou na Internet +INDEX = ÃNDICE ## Utiliza um índice para escolher um valor de uma referência ou de uma matriz +INDIRECT = INDIRECTO ## Devolve uma referência indicada por um valor de texto +LOOKUP = PROC ## Procura valores num vector ou numa matriz +MATCH = CORRESP ## Procura valores numa referência ou numa matriz +OFFSET = DESLOCAMENTO ## Devolve o deslocamento de referência de uma determinada referência +ROW = LIN ## Devolve o número da linha de uma referência +ROWS = LINS ## Devolve o número de linhas numa referência +RTD = RTD ## Obtém dados em tempo real a partir de um programa que suporte automatização COM (automatização: modo de trabalhar com objectos de uma aplicação a partir de outra aplicação ou ferramenta de desenvolvimento. Anteriormente conhecida como automatização OLE, a automatização é uma norma da indústria de software e uma funcionalidade COM (Component Object Model).) +TRANSPOSE = TRANSPOR ## Devolve a transposição de uma matriz +VLOOKUP = PROCV ## Procura na primeira coluna de uma matriz e percorre a linha para devolver o valor de uma célula + + +## +## Math and trigonometry functions Funções matemáticas e trigonométricas +## +ABS = ABS ## Devolve o valor absoluto de um número +ACOS = ACOS ## Devolve o arco de co-seno de um número +ACOSH = ACOSH ## Devolve o co-seno hiperbólico inverso de um número +ASIN = ASEN ## Devolve o arco de seno de um número +ASINH = ASENH ## Devolve o seno hiperbólico inverso de um número +ATAN = ATAN ## Devolve o arco de tangente de um número +ATAN2 = ATAN2 ## Devolve o arco de tangente das coordenadas x e y +ATANH = ATANH ## Devolve a tangente hiperbólica inversa de um número +CEILING = ARRED.EXCESSO ## Arredonda um número para o número inteiro mais próximo ou para o múltiplo de significância mais próximo +COMBIN = COMBIN ## Devolve o número de combinações de um determinado número de objectos +COS = COS ## Devolve o co-seno de um número +COSH = COSH ## Devolve o co-seno hiperbólico de um número +DEGREES = GRAUS ## Converte radianos em graus +EVEN = PAR ## Arredonda um número por excesso para o número inteiro mais próximo +EXP = EXP ## Devolve e elevado à potência de um determinado número +FACT = FACTORIAL ## Devolve o factorial de um número +FACTDOUBLE = FACTDUPLO ## Devolve o factorial duplo de um número +FLOOR = ARRED.DEFEITO ## Arredonda um número por defeito até zero +GCD = MDC ## Devolve o maior divisor comum +INT = INT ## Arredonda um número por defeito para o número inteiro mais próximo +LCM = MMC ## Devolve o mínimo múltiplo comum +LN = LN ## Devolve o logaritmo natural de um número +LOG = LOG ## Devolve o logaritmo de um número com uma base especificada +LOG10 = LOG10 ## Devolve o logaritmo de base 10 de um número +MDETERM = MATRIZ.DETERM ## Devolve o determinante matricial de uma matriz +MINVERSE = MATRIZ.INVERSA ## Devolve o inverso matricial de uma matriz +MMULT = MATRIZ.MULT ## Devolve o produto matricial de duas matrizes +MOD = RESTO ## Devolve o resto da divisão +MROUND = MARRED ## Devolve um número arredondado para o múltiplo pretendido +MULTINOMIAL = POLINOMIAL ## Devolve o polinomial de um conjunto de números +ODD = ÃMPAR ## Arredonda por excesso um número para o número inteiro ímpar mais próximo +PI = PI ## Devolve o valor de pi +POWER = POTÊNCIA ## Devolve o resultado de um número elevado a uma potência +PRODUCT = PRODUTO ## Multiplica os respectivos argumentos +QUOTIENT = QUOCIENTE ## Devolve a parte inteira de uma divisão +RADIANS = RADIANOS ## Converte graus em radianos +RAND = ALEATÓRIO ## Devolve um número aleatório entre 0 e 1 +RANDBETWEEN = ALEATÓRIOENTRE ## Devolve um número aleatório entre os números especificados +ROMAN = ROMANO ## Converte um número árabe em romano, como texto +ROUND = ARRED ## Arredonda um número para um número de dígitos especificado +ROUNDDOWN = ARRED.PARA.BAIXO ## Arredonda um número por defeito até zero +ROUNDUP = ARRED.PARA.CIMA ## Arredonda um número por excesso, afastando-o de zero +SERIESSUM = SOMASÉRIE ## Devolve a soma de uma série de potências baseada na fórmula +SIGN = SINAL ## Devolve o sinal de um número +SIN = SEN ## Devolve o seno de um determinado ângulo +SINH = SENH ## Devolve o seno hiperbólico de um número +SQRT = RAIZQ ## Devolve uma raiz quadrada positiva +SQRTPI = RAIZPI ## Devolve a raiz quadrada de (núm * pi) +SUBTOTAL = SUBTOTAL ## Devolve um subtotal numa lista ou base de dados +SUM = SOMA ## Adiciona os respectivos argumentos +SUMIF = SOMA.SE ## Adiciona as células especificadas por um determinado critério +SUMIFS = SOMA.SE.S ## Adiciona as células num intervalo que cumpre vários critérios +SUMPRODUCT = SOMARPRODUTO ## Devolve a soma dos produtos de componentes de matrizes correspondentes +SUMSQ = SOMARQUAD ## Devolve a soma dos quadrados dos argumentos +SUMX2MY2 = SOMAX2DY2 ## Devolve a soma da diferença dos quadrados dos valores correspondentes em duas matrizes +SUMX2PY2 = SOMAX2SY2 ## Devolve a soma da soma dos quadrados dos valores correspondentes em duas matrizes +SUMXMY2 = SOMAXMY2 ## Devolve a soma dos quadrados da diferença dos valores correspondentes em duas matrizes +TAN = TAN ## Devolve a tangente de um número +TANH = TANH ## Devolve a tangente hiperbólica de um número +TRUNC = TRUNCAR ## Trunca um número para um número inteiro + + +## +## Statistical functions Funções estatísticas +## +AVEDEV = DESV.MÉDIO ## Devolve a média aritmética dos desvios absolutos à média dos pontos de dados +AVERAGE = MÉDIA ## Devolve a média dos respectivos argumentos +AVERAGEA = MÉDIAA ## Devolve uma média dos respectivos argumentos, incluindo números, texto e valores lógicos +AVERAGEIF = MÉDIA.SE ## Devolve a média aritmética de todas as células num intervalo que cumprem determinado critério +AVERAGEIFS = MÉDIA.SE.S ## Devolve a média aritmética de todas as células que cumprem múltiplos critérios +BETADIST = DISTBETA ## Devolve a função de distribuição cumulativa beta +BETAINV = BETA.ACUM.INV ## Devolve o inverso da função de distribuição cumulativa relativamente a uma distribuição beta específica +BINOMDIST = DISTRBINOM ## Devolve a probabilidade de distribuição binomial de termo individual +CHIDIST = DIST.CHI ## Devolve a probabilidade unicaudal da distribuição qui-quadrada +CHIINV = INV.CHI ## Devolve o inverso da probabilidade unicaudal da distribuição qui-quadrada +CHITEST = TESTE.CHI ## Devolve o teste para independência +CONFIDENCE = INT.CONFIANÇA ## Devolve o intervalo de confiança correspondente a uma média de população +CORREL = CORREL ## Devolve o coeficiente de correlação entre dois conjuntos de dados +COUNT = CONTAR ## Conta os números que existem na lista de argumentos +COUNTA = CONTAR.VAL ## Conta os valores que existem na lista de argumentos +COUNTBLANK = CONTAR.VAZIO ## Conta o número de células em branco num intervalo +COUNTIF = CONTAR.SE ## Calcula o número de células num intervalo que corresponde aos critérios determinados +COUNTIFS = CONTAR.SE.S ## Conta o número de células num intervalo que cumprem múltiplos critérios +COVAR = COVAR ## Devolve a covariância, que é a média dos produtos de desvios de pares +CRITBINOM = CRIT.BINOM ## Devolve o menor valor em que a distribuição binomial cumulativa é inferior ou igual a um valor de critério +DEVSQ = DESVQ ## Devolve a soma dos quadrados dos desvios +EXPONDIST = DISTEXPON ## Devolve a distribuição exponencial +FDIST = DISTF ## Devolve a distribuição da probabilidade F +FINV = INVF ## Devolve o inverso da distribuição da probabilidade F +FISHER = FISHER ## Devolve a transformação Fisher +FISHERINV = FISHERINV ## Devolve o inverso da transformação Fisher +FORECAST = PREVISÃO ## Devolve um valor ao longo de uma tendência linear +FREQUENCY = FREQUÊNCIA ## Devolve uma distribuição de frequência como uma matriz vertical +FTEST = TESTEF ## Devolve o resultado de um teste F +GAMMADIST = DISTGAMA ## Devolve a distribuição gama +GAMMAINV = INVGAMA ## Devolve o inverso da distribuição gama cumulativa +GAMMALN = LNGAMA ## Devolve o logaritmo natural da função gama, Γ(x) +GEOMEAN = MÉDIA.GEOMÉTRICA ## Devolve a média geométrica +GROWTH = CRESCIMENTO ## Devolve valores ao longo de uma tendência exponencial +HARMEAN = MÉDIA.HARMÓNICA ## Devolve a média harmónica +HYPGEOMDIST = DIST.HIPERGEOM ## Devolve a distribuição hipergeométrica +INTERCEPT = INTERCEPTAR ## Devolve a intercepção da linha de regressão linear +KURT = CURT ## Devolve a curtose de um conjunto de dados +LARGE = MAIOR ## Devolve o maior valor k-ésimo de um conjunto de dados +LINEST = PROJ.LIN ## Devolve os parâmetros de uma tendência linear +LOGEST = PROJ.LOG ## Devolve os parâmetros de uma tendência exponencial +LOGINV = INVLOG ## Devolve o inverso da distribuição normal logarítmica +LOGNORMDIST = DIST.NORMALLOG ## Devolve a distribuição normal logarítmica cumulativa +MAX = MÃXIMO ## Devolve o valor máximo numa lista de argumentos +MAXA = MÃXIMOA ## Devolve o valor máximo numa lista de argumentos, incluindo números, texto e valores lógicos +MEDIAN = MED ## Devolve a mediana dos números indicados +MIN = MÃNIMO ## Devolve o valor mínimo numa lista de argumentos +MINA = MÃNIMOA ## Devolve o valor mínimo numa lista de argumentos, incluindo números, texto e valores lógicos +MODE = MODA ## Devolve o valor mais comum num conjunto de dados +NEGBINOMDIST = DIST.BIN.NEG ## Devolve a distribuição binominal negativa +NORMDIST = DIST.NORM ## Devolve a distribuição cumulativa normal +NORMINV = INV.NORM ## Devolve o inverso da distribuição cumulativa normal +NORMSDIST = DIST.NORMP ## Devolve a distribuição cumulativa normal padrão +NORMSINV = INV.NORMP ## Devolve o inverso da distribuição cumulativa normal padrão +PEARSON = PEARSON ## Devolve o coeficiente de correlação momento/produto de Pearson +PERCENTILE = PERCENTIL ## Devolve o k-ésimo percentil de valores num intervalo +PERCENTRANK = ORDEM.PERCENTUAL ## Devolve a ordem percentual de um valor num conjunto de dados +PERMUT = PERMUTAR ## Devolve o número de permutações de um determinado número de objectos +POISSON = POISSON ## Devolve a distribuição de Poisson +PROB = PROB ## Devolve a probabilidade dos valores num intervalo se encontrarem entre dois limites +QUARTILE = QUARTIL ## Devolve o quartil de um conjunto de dados +RANK = ORDEM ## Devolve a ordem de um número numa lista numérica +RSQ = RQUAD ## Devolve o quadrado do coeficiente de correlação momento/produto de Pearson +SKEW = DISTORÇÃO ## Devolve a distorção de uma distribuição +SLOPE = DECLIVE ## Devolve o declive da linha de regressão linear +SMALL = MENOR ## Devolve o menor valor de k-ésimo de um conjunto de dados +STANDARDIZE = NORMALIZAR ## Devolve um valor normalizado +STDEV = DESVPAD ## Calcula o desvio-padrão com base numa amostra +STDEVA = DESVPADA ## Calcula o desvio-padrão com base numa amostra, incluindo números, texto e valores lógicos +STDEVP = DESVPADP ## Calcula o desvio-padrão com base na população total +STDEVPA = DESVPADPA ## Calcula o desvio-padrão com base na população total, incluindo números, texto e valores lógicos +STEYX = EPADYX ## Devolve o erro-padrão do valor de y previsto para cada x na regressão +TDIST = DISTT ## Devolve a distribuição t de Student +TINV = INVT ## Devolve o inverso da distribuição t de Student +TREND = TENDÊNCIA ## Devolve valores ao longo de uma tendência linear +TRIMMEAN = MÉDIA.INTERNA ## Devolve a média do interior de um conjunto de dados +TTEST = TESTET ## Devolve a probabilidade associada ao teste t de Student +VAR = VAR ## Calcula a variância com base numa amostra +VARA = VARA ## Calcula a variância com base numa amostra, incluindo números, texto e valores lógicos +VARP = VARP ## Calcula a variância com base na população total +VARPA = VARPA ## Calcula a variância com base na população total, incluindo números, texto e valores lógicos +WEIBULL = WEIBULL ## Devolve a distribuição Weibull +ZTEST = TESTEZ ## Devolve o valor de probabilidade unicaudal de um teste-z + + +## +## Text functions Funções de texto +## +ASC = ASC ## Altera letras ou katakana de largura total (byte duplo) numa cadeia de caracteres para caracteres de largura média (byte único) +BAHTTEXT = TEXTO.BAHT ## Converte um número em texto, utilizando o formato monetário ß (baht) +CHAR = CARÃCT ## Devolve o carácter especificado pelo número de código +CLEAN = LIMPAR ## Remove do texto todos os caracteres não imprimíveis +CODE = CÓDIGO ## Devolve um código numérico correspondente ao primeiro carácter numa cadeia de texto +CONCATENATE = CONCATENAR ## Agrupa vários itens de texto num único item de texto +DOLLAR = MOEDA ## Converte um número em texto, utilizando o formato monetário € (Euro) +EXACT = EXACTO ## Verifica se dois valores de texto são idênticos +FIND = LOCALIZAR ## Localiza um valor de texto dentro de outro (sensível às maiúsculas e minúsculas) +FINDB = LOCALIZARB ## Localiza um valor de texto dentro de outro (sensível às maiúsculas e minúsculas) +FIXED = FIXA ## Formata um número como texto com um número fixo de decimais +JIS = JIS ## Altera letras ou katakana de largura média (byte único) numa cadeia de caracteres para caracteres de largura total (byte duplo) +LEFT = ESQUERDA ## Devolve os caracteres mais à esquerda de um valor de texto +LEFTB = ESQUERDAB ## Devolve os caracteres mais à esquerda de um valor de texto +LEN = NÚM.CARACT ## Devolve o número de caracteres de uma cadeia de texto +LENB = NÚM.CARACTB ## Devolve o número de caracteres de uma cadeia de texto +LOWER = MINÚSCULAS ## Converte o texto em minúsculas +MID = SEG.TEXTO ## Devolve um número específico de caracteres de uma cadeia de texto, a partir da posição especificada +MIDB = SEG.TEXTOB ## Devolve um número específico de caracteres de uma cadeia de texto, a partir da posição especificada +PHONETIC = FONÉTICA ## Retira os caracteres fonéticos (furigana) de uma cadeia de texto +PROPER = INICIAL.MAIÚSCULA ## Coloca em maiúsculas a primeira letra de cada palavra de um valor de texto +REPLACE = SUBSTITUIR ## Substitui caracteres no texto +REPLACEB = SUBSTITUIRB ## Substitui caracteres no texto +REPT = REPETIR ## Repete texto um determinado número de vezes +RIGHT = DIREITA ## Devolve os caracteres mais à direita de um valor de texto +RIGHTB = DIREITAB ## Devolve os caracteres mais à direita de um valor de texto +SEARCH = PROCURAR ## Localiza um valor de texto dentro de outro (não sensível a maiúsculas e minúsculas) +SEARCHB = PROCURARB ## Localiza um valor de texto dentro de outro (não sensível a maiúsculas e minúsculas) +SUBSTITUTE = SUBST ## Substitui texto novo por texto antigo numa cadeia de texto +T = T ## Converte os respectivos argumentos em texto +TEXT = TEXTO ## Formata um número e converte-o em texto +TRIM = COMPACTAR ## Remove espaços do texto +UPPER = MAIÚSCULAS ## Converte texto em maiúsculas +VALUE = VALOR ## Converte um argumento de texto num número diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/ru/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/ru/config new file mode 100755 index 0000000..ee72465 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/ru/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = Ñ€ + + +## +## Excel Error Codes (For future use) +## +NULL = #ПУСТО! +DIV0 = #ДЕЛ/0! +VALUE = #ЗÐÐЧ! +REF = #ССЫЛ! +NAME = #ИМЯ? +NUM = #ЧИСЛО! +NA = #Ð/Д diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/ru/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/ru/functions new file mode 100755 index 0000000..5636f56 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/ru/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from information provided by web-junior (http://www.web-junior.net/) +## +## + + +## +## Add-in and Automation functions Функции надÑтроек и автоматизации +## +GETPIVOTDATA = ПОЛУЧИТЬ.ДÐÐÐЫЕ.СВОДÐОЙ.ТÐБЛИЦЫ ## Возвращает данные, хранÑщиеÑÑ Ð² отчете Ñводной таблицы. + + +## +## Cube functions Функции Куб +## +CUBEKPIMEMBER = КУБЭЛЕМЕÐТКИП ## Возвращает ÑвойÑтво ключевого индикатора производительноÑти «(КИП)» и отображает Ð¸Ð¼Ñ Â«ÐšÐ˜ÐŸÂ» в Ñчейке. «КИП» предÑтавлÑет Ñобой количеÑтвенную величину, такую как ежемеÑÑÑ‡Ð½Ð°Ñ Ð²Ð°Ð»Ð¾Ð²Ð°Ñ Ð¿Ñ€Ð¸Ð±Ñ‹Ð»ÑŒ или ÐµÐ¶ÐµÐºÐ²Ð°Ñ€Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ Ñ‚ÐµÐºÑƒÑ‡ÐµÑÑ‚ÑŒ кадров, иÑпользуемой Ð´Ð»Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ñ ÑффективноÑти работы организации. +CUBEMEMBER = КУБЭЛЕМЕÐТ ## Возвращает Ñлемент или кортеж из куба. ИÑпользуетÑÑ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ ÑущеÑÑ‚Ð²Ð¾Ð²Ð°Ð½Ð¸Ñ Ñлемента или кортежа в кубе. +CUBEMEMBERPROPERTY = КУБСВОЙСТВОЭЛЕМЕÐТР## Возвращает значение ÑвойÑтва Ñлемента из куба. ИÑпользуетÑÑ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ¸ ÑущеÑÑ‚Ð²Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð¼ÐµÐ½Ð¸ Ñлемента в кубе и возвращает указанное ÑвойÑтво Ð´Ð»Ñ Ñтого Ñлемента. +CUBERANKEDMEMBER = КУБПОРЭЛЕМЕÐТ ## Возвращает n-ый или ранжированный Ñлемент в множеÑтво. ИÑпользуетÑÑ Ð´Ð»Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ или неÑкольких Ñлементов в множеÑтво, например, лучшего продавца или 10 лучших Ñтудентов. +CUBESET = КУБМÐОЖ ## ОпределÑет вычиÑлительное множеÑтво Ñлементов или кортежей, отправлÑÑ Ð½Ð° Ñервер выражение, которое Ñоздает множеÑтво, а затем возвращает его в Microsoft Office Excel. +CUBESETCOUNT = КУБЧИСЛОЭЛМÐОЖ ## Возвращает чиÑло Ñлементов множеÑтва. +CUBEVALUE = КУБЗÐÐЧЕÐИЕ ## Возвращает обобщенное значение из куба. + + +## +## Database functions Функции Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñ Ð±Ð°Ð·Ð°Ð¼Ð¸ данных +## +DAVERAGE = ДСРЗÐÐЧ ## Возвращает Ñреднее значение выбранных запиÑей базы данных. +DCOUNT = БСЧÐТ ## ПодÑчитывает количеÑтво чиÑловых Ñчеек в базе данных. +DCOUNTA = БСЧÐТР## ПодÑчитывает количеÑтво непуÑÑ‚Ñ‹Ñ… Ñчеек в базе данных. +DGET = БИЗВЛЕЧЬ ## Извлекает из базы данных одну запиÑÑŒ, удовлетворÑющую заданному уÑловию. +DMAX = ДМÐКС ## Возвращает макÑимальное значение Ñреди выделенных запиÑей базы данных. +DMIN = ДМИР## Возвращает минимальное значение Ñреди выделенных запиÑей базы данных. +DPRODUCT = БДПРОИЗВЕД ## Перемножает Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð½Ð¾Ð³Ð¾ Ð¿Ð¾Ð»Ñ Ð² запиÑÑÑ… базы данных, удовлетворÑющих уÑловию. +DSTDEV = ДСТÐÐДОТКЛ ## Оценивает Ñтандартное отклонение по выборке Ð´Ð»Ñ Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ñ… запиÑей базы данных. +DSTDEVP = ДСТÐÐДОТКЛП ## ВычиÑлÑет Ñтандартное отклонение по генеральной ÑовокупноÑти Ð´Ð»Ñ Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ñ… запиÑей базы данных +DSUM = БДСУММ ## Суммирует чиÑла в поле Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñей базы данных, удовлетворÑющих уÑловию. +DVAR = БДДИСП ## Оценивает диÑперÑию по выборке из выделенных запиÑей базы данных +DVARP = БДДИСПП ## ВычиÑлÑет диÑперÑию по генеральной ÑовокупноÑти Ð´Ð»Ñ Ð²Ñ‹Ð´ÐµÐ»ÐµÐ½Ð½Ñ‹Ñ… запиÑей базы данных + + +## +## Date and time functions Функции даты и времени +## +DATE = ДÐТР## Возвращает заданную дату в чиÑловом формате. +DATEVALUE = ДÐТÐЗÐÐЧ ## Преобразует дату из текÑтового формата в чиÑловой формат. +DAY = ДЕÐЬ ## Преобразует дату в чиÑловом формате в день меÑÑца. +DAYS360 = ДÐЕЙ360 ## ВычиÑлÑет количеÑтво дней между Ð´Ð²ÑƒÐ¼Ñ Ð´Ð°Ñ‚Ð°Ð¼Ð¸ на оÑнове 360-дневного года. +EDATE = ДÐТÐМЕС ## Возвращает дату в чиÑловом формате, отÑтоÑщую на заданное чиÑло меÑÑцев вперед или назад от начальной даты. +EOMONTH = КОÐМЕСЯЦР## Возвращает дату в чиÑловом формате Ð´Ð»Ñ Ð¿Ð¾Ñледнего Ð´Ð½Ñ Ð¼ÐµÑÑца, отÑтоÑщего вперед или назад на заданное чиÑло меÑÑцев. +HOUR = ЧÐС ## Преобразует дату в чиÑловом формате в чаÑÑ‹. +MINUTE = МИÐУТЫ ## Преобразует дату в чиÑловом формате в минуты. +MONTH = МЕСЯЦ ## Преобразует дату в чиÑловом формате в меÑÑцы. +NETWORKDAYS = ЧИСТРÐБДÐИ ## Возвращает количеÑтво рабочих дней между Ð´Ð²ÑƒÐ¼Ñ Ð´Ð°Ñ‚Ð°Ð¼Ð¸. +NOW = ТДÐТР## Возвращает текущую дату и Ð²Ñ€ÐµÐ¼Ñ Ð² чиÑловом формате. +SECOND = СЕКУÐДЫ ## Преобразует дату в чиÑловом формате в Ñекунды. +TIME = ВРЕМЯ ## Возвращает заданное Ð²Ñ€ÐµÐ¼Ñ Ð² чиÑловом формате. +TIMEVALUE = ВРЕМЗÐÐЧ ## Преобразует Ð²Ñ€ÐµÐ¼Ñ Ð¸Ð· текÑтового формата в чиÑловой формат. +TODAY = СЕГОДÐЯ ## Возвращает текущую дату в чиÑловом формате. +WEEKDAY = ДЕÐЬÐЕД ## Преобразует дату в чиÑловом формате в день недели. +WEEKNUM = ÐОМÐЕДЕЛИ ## Преобразует чиÑловое предÑтавление в чиÑло, которое указывает, на какую неделю года приходитÑÑ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð°Ñ Ð´Ð°Ñ‚Ð°. +WORKDAY = РÐБДЕÐЬ ## Возвращает дату в чиÑловом формате, отÑтоÑщую вперед или назад на заданное количеÑтво рабочих дней. +YEAR = ГОД ## Преобразует дату в чиÑловом формате в год. +YEARFRAC = ДОЛЯГОДР## Возвращает долю года, которую ÑоÑтавлÑет количеÑтво дней между начальной и конечной датами. + + +## +## Engineering functions Инженерные функции +## +BESSELI = БЕССЕЛЬ.I ## Возвращает модифицированную функцию БеÑÑÐµÐ»Ñ In(x). +BESSELJ = БЕССЕЛЬ.J ## Возвращает функцию БеÑÑÐµÐ»Ñ Jn(x). +BESSELK = БЕССЕЛЬ.K ## Возвращает модифицированную функцию БеÑÑÐµÐ»Ñ Kn(x). +BESSELY = БЕССЕЛЬ.Y ## Возвращает функцию БеÑÑÐµÐ»Ñ Yn(x). +BIN2DEC = ДВ.Ð’.ДЕС ## Преобразует двоичное чиÑло в деÑÑтичное. +BIN2HEX = ДВ.Ð’.ШЕСТР## Преобразует двоичное чиÑло в шеÑтнадцатеричное. +BIN2OCT = ДВ.Ð’.ВОСЬМ ## Преобразует двоичное чиÑло в воÑьмеричное. +COMPLEX = КОМПЛЕКСР## Преобразует коÑффициенты при вещеÑтвенной и мнимой чаÑÑ‚ÑÑ… комплекÑного чиÑла в комплекÑное чиÑло. +CONVERT = ПРЕОБР ## Преобразует чиÑло из одной ÑиÑтемы единиц Ð¸Ð·Ð¼ÐµÑ€ÐµÐ½Ð¸Ñ Ð² другую. +DEC2BIN = ДЕС.Ð’.ДВ ## Преобразует деÑÑтичное чиÑло в двоичное. +DEC2HEX = ДЕС.Ð’.ШЕСТР## Преобразует деÑÑтичное чиÑло в шеÑтнадцатеричное. +DEC2OCT = ДЕС.Ð’.ВОСЬМ ## Преобразует деÑÑтичное чиÑло в воÑьмеричное. +DELTA = ДЕЛЬТР## ПроверÑет равенÑтво двух значений. +ERF = ФОШ ## Возвращает функцию ошибки. +ERFC = ДФОШ ## Возвращает дополнительную функцию ошибки. +GESTEP = ПОРОГ ## ПроверÑет, не превышает ли данное чиÑло порогового значениÑ. +HEX2BIN = ШЕСТÐ.Ð’.ДВ ## Преобразует шеÑтнадцатеричное чиÑло в двоичное. +HEX2DEC = ШЕСТÐ.Ð’.ДЕС ## Преобразует шеÑтнадцатеричное чиÑло в деÑÑтичное. +HEX2OCT = ШЕСТÐ.Ð’.ВОСЬМ ## Преобразует шеÑтнадцатеричное чиÑло в воÑьмеричное. +IMABS = ÐœÐИМ.ABS ## Возвращает абÑолютную величину (модуль) комплекÑного чиÑла. +IMAGINARY = ÐœÐИМ.ЧÐСТЬ ## Возвращает коÑффициент при мнимой чаÑти комплекÑного чиÑла. +IMARGUMENT = ÐœÐИМ.ÐРГУМЕÐТ ## Возвращает значение аргумента комплекÑного чиÑла (тета) — угол, выраженный в радианах. +IMCONJUGATE = ÐœÐИМ.СОПРЯЖ ## Возвращает комплекÑно-ÑопрÑженное комплекÑное чиÑло. +IMCOS = ÐœÐИМ.COS ## Возвращает коÑÐ¸Ð½ÑƒÑ ÐºÐ¾Ð¼Ð¿Ð»ÐµÐºÑного чиÑла. +IMDIV = ÐœÐИМ.ДЕЛ ## Возвращает чаÑтное от Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð´Ð²ÑƒÑ… комплекÑных чиÑел. +IMEXP = ÐœÐИМ.EXP ## Возвращает ÑкÑпоненту комплекÑного чиÑла. +IMLN = ÐœÐИМ.LN ## Возвращает натуральный логарифм комплекÑного чиÑла. +IMLOG10 = ÐœÐИМ.LOG10 ## Возвращает обычный (деÑÑтичный) логарифм комплекÑного чиÑла. +IMLOG2 = ÐœÐИМ.LOG2 ## Возвращает двоичный логарифм комплекÑного чиÑла. +IMPOWER = ÐœÐИМ.СТЕПЕÐЬ ## Возвращает комплекÑное чиÑло, возведенное в целую Ñтепень. +IMPRODUCT = ÐœÐИМ.ПРОИЗВЕД ## Возвращает произведение от 2 до 29 комплекÑных чиÑел. +IMREAL = ÐœÐИМ.ВЕЩ ## Возвращает коÑффициент при вещеÑтвенной чаÑти комплекÑного чиÑла. +IMSIN = ÐœÐИМ.SIN ## Возвращает ÑÐ¸Ð½ÑƒÑ ÐºÐ¾Ð¼Ð¿Ð»ÐµÐºÑного чиÑла. +IMSQRT = ÐœÐИМ.КОРЕÐЬ ## Возвращает значение квадратного ÐºÐ¾Ñ€Ð½Ñ Ð¸Ð· комплекÑного чиÑла. +IMSUB = ÐœÐИМ.РÐЗР## Возвращает разноÑÑ‚ÑŒ двух комплекÑных чиÑел. +IMSUM = ÐœÐИМ.СУММ ## Возвращает Ñумму комплекÑных чиÑел. +OCT2BIN = ВОСЬМ.Ð’.ДВ ## Преобразует воÑьмеричное чиÑло в двоичное. +OCT2DEC = ВОСЬМ.Ð’.ДЕС ## Преобразует воÑьмеричное чиÑло в деÑÑтичное. +OCT2HEX = ВОСЬМ.Ð’.ШЕСТР## Преобразует воÑьмеричное чиÑло в шеÑтнадцатеричное. + + +## +## Financial functions ФинанÑовые функции +## +ACCRINT = ÐÐКОПДОХОД ## Возвращает накопленный процент по ценным бумагам Ñ Ð¿ÐµÑ€Ð¸Ð¾Ð´Ð¸Ñ‡ÐµÑкой выплатой процентов. +ACCRINTM = ÐÐКОПДОХОДПОГÐШ ## Возвращает накопленный процент по ценным бумагам, проценты по которым выплачиваютÑÑ Ð² Ñрок погашениÑ. +AMORDEGRC = ÐМОРУМ ## Возвращает величину амортизации Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ периода, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ ÐºÐ¾Ñффициент амортизации. +AMORLINC = ÐМОРУВ ## Возвращает величину амортизации Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ периода. +COUPDAYBS = ДÐЕЙКУПОÐДО ## Возвращает количеÑтво дней от начала дейÑÑ‚Ð²Ð¸Ñ ÐºÑƒÐ¿Ð¾Ð½Ð° до даты ÑоглашениÑ. +COUPDAYS = ДÐЕЙКУПОР## Возвращает чиÑло дней в периоде купона, Ñодержащем дату ÑоглашениÑ. +COUPDAYSNC = ДÐЕЙКУПОÐПОСЛЕ ## Возвращает чиÑло дней от даты ÑÐ¾Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð´Ð¾ Ñрока Ñледующего купона. +COUPNCD = ДÐТÐКУПОÐПОСЛЕ ## Возвращает Ñледующую дату купона поÑле даты ÑоглашениÑ. +COUPNUM = ЧИСЛКУПОР## Возвращает количеÑтво купонов, которые могут быть оплачены между датой ÑÐ¾Ð³Ð»Ð°ÑˆÐµÐ½Ð¸Ñ Ð¸ Ñроком вÑÑ‚ÑƒÐ¿Ð»ÐµÐ½Ð¸Ñ Ð² Ñилу. +COUPPCD = ДÐТÐКУПОÐДО ## Возвращает предыдущую дату купона перед датой ÑоглашениÑ. +CUMIPMT = ОБЩПЛÐТ ## Возвращает общую выплату, произведенную между Ð´Ð²ÑƒÐ¼Ñ Ð¿ÐµÑ€Ð¸Ð¾Ð´Ð¸Ñ‡ÐµÑкими выплатами. +CUMPRINC = ОБЩДОХОД ## Возвращает общую выплату по займу между Ð´Ð²ÑƒÐ¼Ñ Ð¿ÐµÑ€Ð¸Ð¾Ð´Ð°Ð¼Ð¸. +DB = ФУО ## Возвращает величину амортизации актива Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ периода, раÑÑчитанную методом фикÑированного ÑƒÐ¼ÐµÐ½ÑŒÑˆÐµÐ½Ð¸Ñ Ð¾Ñтатка. +DDB = ДДОБ ## Возвращает величину амортизации актива за данный период, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð¼ÐµÑ‚Ð¾Ð´ двойного ÑƒÐ¼ÐµÐ½ÑŒÑˆÐµÐ½Ð¸Ñ Ð¾Ñтатка или иной Ñвно указанный метод. +DISC = СКИДКР## Возвращает норму Ñкидки Ð´Ð»Ñ Ñ†ÐµÐ½Ð½Ñ‹Ñ… бумаг. +DOLLARDE = РУБЛЬ.ДЕС ## Преобразует цену в рублÑÑ…, выраженную в виде дроби, в цену в рублÑÑ…, выраженную деÑÑтичным чиÑлом. +DOLLARFR = РУБЛЬ.ДРОБЬ ## Преобразует цену в рублÑÑ…, выраженную деÑÑтичным чиÑлом, в цену в рублÑÑ…, выраженную в виде дроби. +DURATION = ДЛИТ ## Возвращает ежегодную продолжительноÑÑ‚ÑŒ дейÑÑ‚Ð²Ð¸Ñ Ñ†ÐµÐ½Ð½Ñ‹Ñ… бумаг Ñ Ð¿ÐµÑ€Ð¸Ð¾Ð´Ð¸Ñ‡ÐµÑкими выплатами по процентам. +EFFECT = ЭФФЕКТ ## Возвращает дейÑтвующие ежегодные процентные Ñтавки. +FV = БС ## Возвращает будущую ÑтоимоÑÑ‚ÑŒ инвеÑтиции. +FVSCHEDULE = БЗРÐСПИС ## Возвращает будущую ÑтоимоÑÑ‚ÑŒ первоначальной оÑновной Ñуммы поÑле начиÑÐ»ÐµÐ½Ð¸Ñ Ñ€Ñда Ñложных процентов. +INTRATE = ИÐОРМР## Возвращает процентную Ñтавку Ð´Ð»Ñ Ð¿Ð¾Ð»Ð½Ð¾Ñтью инвеÑтированных ценных бумаг. +IPMT = ПРПЛТ ## Возвращает величину выплаты прибыли на Ð²Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð·Ð° данный период. +IRR = ВСД ## Возвращает внутреннюю Ñтавку доходноÑти Ð´Ð»Ñ Ñ€Ñда потоков денежных ÑредÑтв. +ISPMT = ПРОЦПЛÐТ ## ВычиÑлÑет выплаты за указанный период инвеÑтиции. +MDURATION = МДЛИТ ## Возвращает модифицированную длительноÑÑ‚ÑŒ ÐœÐ°ÐºÐ¾Ð»ÐµÑ Ð´Ð»Ñ Ñ†ÐµÐ½Ð½Ñ‹Ñ… бумаг Ñ Ð¿Ñ€ÐµÐ´Ð¿Ð¾Ð»Ð°Ð³Ð°ÐµÐ¼Ð¾Ð¹ номинальной ÑтоимоÑтью 100 рублей. +MIRR = МВСД ## Возвращает внутреннюю Ñтавку доходноÑти, при которой положительные и отрицательные денежные потоки имеют разные Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñтавки. +NOMINAL = ÐОМИÐÐЛ ## Возвращает номинальную годовую процентную Ñтавку. +NPER = КПЕР ## Возвращает общее количеÑтво периодов выплаты Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ вклада. +NPV = ЧПС ## Возвращает чиÑтую приведенную ÑтоимоÑÑ‚ÑŒ инвеÑтиции, оÑнованной на Ñерии периодичеÑких денежных потоков и Ñтавке диÑконтированиÑ. +ODDFPRICE = ЦЕÐÐПЕРВÐЕРЕГ ## Возвращает цену за 100 рублей нарицательной ÑтоимоÑти ценных бумаг Ñ Ð½ÐµÑ€ÐµÐ³ÑƒÐ»Ñрным первым периодом. +ODDFYIELD = ДОХОДПЕРВÐЕРЕГ ## Возвращает доход по ценным бумагам Ñ Ð½ÐµÑ€ÐµÐ³ÑƒÐ»Ñрным первым периодом. +ODDLPRICE = ЦЕÐÐПОСЛÐЕРЕГ ## Возвращает цену за 100 рублей нарицательной ÑтоимоÑти ценных бумаг Ñ Ð½ÐµÑ€ÐµÐ³ÑƒÐ»Ñрным поÑледним периодом. +ODDLYIELD = ДОХОДПОСЛÐЕРЕГ ## Возвращает доход по ценным бумагам Ñ Ð½ÐµÑ€ÐµÐ³ÑƒÐ»Ñрным поÑледним периодом. +PMT = ПЛТ ## Возвращает величину выплаты за один период аннуитета. +PPMT = ОСПЛТ ## Возвращает величину выплат в погашение оÑновной Ñуммы по инвеÑтиции за заданный период. +PRICE = ЦЕÐÐ ## Возвращает цену за 100 рублей нарицательной ÑтоимоÑти ценных бумаг, по которым производитÑÑ Ð¿ÐµÑ€Ð¸Ð¾Ð´Ð¸Ñ‡ÐµÑÐºÐ°Ñ Ð²Ñ‹Ð¿Ð»Ð°Ñ‚Ð° процентов. +PRICEDISC = ЦЕÐÐСКИДКР## Возвращает цену за 100 рублей номинальной ÑтоимоÑти ценных бумаг, на которые Ñделана Ñкидка. +PRICEMAT = ЦЕÐÐПОГÐШ ## Возвращает цену за 100 рублей номинальной ÑтоимоÑти ценных бумаг, проценты по которым выплачиваютÑÑ Ð² Ñрок погашениÑ. +PV = ПС ## Возвращает приведенную (к текущему моменту) ÑтоимоÑÑ‚ÑŒ инвеÑтиции. +RATE = СТÐВКР## Возвращает процентную Ñтавку по аннуитету за один период. +RECEIVED = ПОЛУЧЕÐО ## Возвращает Ñумму, полученную к Ñроку Ð¿Ð¾Ð³Ð°ÑˆÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð½Ð¾Ñтью обеÑпеченных ценных бумаг. +SLN = ÐПЛ ## Возвращает величину линейной амортизации актива за один период. +SYD = ÐСЧ ## Возвращает величину амортизации актива за данный период, раÑÑчитанную методом Ñуммы годовых чиÑел. +TBILLEQ = РÐÐ’ÐОКЧЕК ## Возвращает Ñквивалентный облигации доход по казначейÑкому чеку. +TBILLPRICE = ЦЕÐÐКЧЕК ## Возвращает цену за 100 рублей нарицательной ÑтоимоÑти Ð´Ð»Ñ ÐºÐ°Ð·Ð½Ð°Ñ‡ÐµÐ¹Ñкого чека. +TBILLYIELD = ДОХОДКЧЕК ## Возвращает доход по казначейÑкому чеку. +VDB = ПУО ## Возвращает величину амортизации актива Ð´Ð»Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð¾Ð³Ð¾ или чаÑтичного периода при иÑпользовании метода ÑокращающегоÑÑ Ð±Ð°Ð»Ð°Ð½Ñа. +XIRR = ЧИСТВÐДОХ ## Возвращает внутреннюю Ñтавку доходноÑти Ð´Ð»Ñ Ð³Ñ€Ð°Ñ„Ð¸ÐºÐ° денежных потоков, которые не обÑзательно ноÑÑÑ‚ периодичеÑкий характер. +XNPV = ЧИСТÐЗ ## Возвращает чиÑтую приведенную ÑтоимоÑÑ‚ÑŒ Ð´Ð»Ñ Ð´ÐµÐ½ÐµÐ¶Ð½Ñ‹Ñ… потоков, которые не обÑзательно ÑвлÑÑŽÑ‚ÑÑ Ð¿ÐµÑ€Ð¸Ð¾Ð´Ð¸Ñ‡ÐµÑкими. +YIELD = ДОХОД ## Возвращает доход от ценных бумаг, по которым производÑÑ‚ÑÑ Ð¿ÐµÑ€Ð¸Ð¾Ð´Ð¸Ñ‡ÐµÑкие выплаты процентов. +YIELDDISC = ДОХОДСКИДКР## Возвращает годовой доход по ценным бумагам, на которые Ñделана Ñкидка (пример — казначейÑкие чеки). +YIELDMAT = ДОХОДПОГÐШ ## Возвращает годовой доход от ценных бумаг, проценты по которым выплачиваютÑÑ Ð² Ñрок погашениÑ. + + +## +## Information functions Информационные функции +## +CELL = ЯЧЕЙКР## Возвращает информацию о формате, раÑположении или Ñодержимом Ñчейки. +ERROR.TYPE = ТИП.ОШИБКИ ## Возвращает чиÑловой код, ÑоответÑтвующий типу ошибки. +INFO = ИÐФОРМ ## Возвращает информацию о текущей операционной Ñреде. +ISBLANK = ЕПУСТО ## Возвращает значение ИСТИÐÐ, еÑли аргумент ÑвлÑетÑÑ ÑÑылкой на пуÑтую Ñчейку. +ISERR = ЕОШ ## Возвращает значение ИСТИÐÐ, еÑли аргумент ÑÑылаетÑÑ Ð½Ð° любое значение ошибки, кроме #Ð/Д. +ISERROR = ЕОШИБКР## Возвращает значение ИСТИÐÐ, еÑли аргумент ÑÑылаетÑÑ Ð½Ð° любое значение ошибки. +ISEVEN = ЕЧÐТР## Возвращает значение ИСТИÐÐ, еÑли значение аргумента ÑвлÑетÑÑ Ñ‡ÐµÑ‚Ð½Ñ‹Ð¼ чиÑлом. +ISLOGICAL = ЕЛОГИЧ ## Возвращает значение ИСТИÐÐ, еÑли аргумент ÑÑылаетÑÑ Ð½Ð° логичеÑкое значение. +ISNA = ЕÐД ## Возвращает значение ИСТИÐÐ, еÑли аргумент ÑÑылаетÑÑ Ð½Ð° значение ошибки #Ð/Д. +ISNONTEXT = ЕÐЕТЕКСТ ## Возвращает значение ИСТИÐÐ, еÑли значение аргумента не ÑвлÑетÑÑ Ñ‚ÐµÐºÑтом. +ISNUMBER = ЕЧИСЛО ## Возвращает значение ИСТИÐÐ, еÑли аргумент ÑÑылаетÑÑ Ð½Ð° чиÑло. +ISODD = ЕÐЕЧÐТ ## Возвращает значение ИСТИÐÐ, еÑли значение аргумента ÑвлÑетÑÑ Ð½ÐµÑ‡ÐµÑ‚Ð½Ñ‹Ð¼ чиÑлом. +ISREF = ЕССЫЛКР## Возвращает значение ИСТИÐÐ, еÑли значение аргумента ÑвлÑетÑÑ ÑÑылкой. +ISTEXT = ЕТЕКСТ ## Возвращает значение ИСТИÐÐ, еÑли значение аргумента ÑвлÑетÑÑ Ñ‚ÐµÐºÑтом. +N = Ч ## Возвращает значение, преобразованное в чиÑло. +NA = ÐД ## Возвращает значение ошибки #Ð/Д. +TYPE = ТИП ## Возвращает чиÑло, обозначающее тип данных значениÑ. + + +## +## Logical functions ЛогичеÑкие функции +## +AND = И ## Renvoie VRAI si tous ses arguments sont VRAI. +FALSE = ЛОЖЬ ## Возвращает логичеÑкое значение ЛОЖЬ. +IF = ЕСЛИ ## ВыполнÑет проверку уÑловиÑ. +IFERROR = ЕСЛИОШИБКР## Возвращает введённое значение, еÑли вычиÑление по формуле вызывает ошибку; в противном Ñлучае Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‰Ð°ÐµÑ‚ результат вычиÑлениÑ. +NOT = ÐЕ ## МенÑет логичеÑкое значение Ñвоего аргумента на противоположное. +OR = ИЛИ ## Возвращает значение ИСТИÐÐ, еÑли Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один аргумент имеет значение ИСТИÐÐ. +TRUE = ИСТИÐÐ ## Возвращает логичеÑкое значение ИСТИÐÐ. + + +## +## Lookup and reference functions Функции ÑÑылки и поиÑка +## +ADDRESS = ÐДРЕС ## Возвращает ÑÑылку на отдельную Ñчейку лиÑта в виде текÑта. +AREAS = ОБЛÐСТИ ## Возвращает количеÑтво облаÑтей в ÑÑылке. +CHOOSE = ВЫБОР ## Выбирает значение из ÑпиÑка значений по индекÑу. +COLUMN = СТОЛБЕЦ ## Возвращает номер Ñтолбца, на который указывает ÑÑылка. +COLUMNS = ЧИСЛСТОЛБ ## Возвращает количеÑтво Ñтолбцов в ÑÑылке. +HLOOKUP = ГПР ## Ищет в первой Ñтроке маÑÑива и возвращает значение отмеченной Ñчейки +HYPERLINK = ГИПЕРССЫЛКР## Создает ÑÑылку, открывающую документ, который находитÑÑ Ð½Ð° Ñервере Ñети, в интраÑети или в Интернете. +INDEX = ИÐДЕКС ## ИÑпользует Ð¸Ð½Ð´ÐµÐºÑ Ð´Ð»Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¸Ð· ÑÑылки или маÑÑива. +INDIRECT = ДВССЫЛ ## Возвращает ÑÑылку, заданную текÑтовым значением. +LOOKUP = ПРОСМОТР ## Ищет Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² векторе или маÑÑиве. +MATCH = ПОИСКПОЗ ## Ищет Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² ÑÑылке или маÑÑиве. +OFFSET = СМЕЩ ## Возвращает Ñмещение ÑÑылки отноÑительно заданной ÑÑылки. +ROW = СТРОКР## Возвращает номер Ñтроки, определÑемой ÑÑылкой. +ROWS = ЧСТРОК ## Возвращает количеÑтво Ñтрок в ÑÑылке. +RTD = ДРВ ## Извлекает данные реального времени из программ, поддерживающих автоматизацию COM (Программирование объектов. Стандартное ÑредÑтво Ð´Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð°Ð¼Ð¸ некоторого Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸Ð· другого Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ ÑредÑтва разработки. Программирование объектов (ранее называемое программированием OLE) ÑвлÑетÑÑ Ñ„ÑƒÐ½ÐºÑ†Ð¸ÐµÐ¹ модели COM (Component Object Model, модель компонентных объектов).). +TRANSPOSE = ТРÐÐСП ## Возвращает транÑпонированный маÑÑив. +VLOOKUP = ВПР ## Ищет значение в первом Ñтолбце маÑÑива и возвращает значение из Ñчейки в найденной Ñтроке и указанном Ñтолбце. + + +## +## Math and trigonometry functions МатематичеÑкие и тригонометричеÑкие функции +## +ABS = ABS ## Возвращает модуль (абÑолютную величину) чиÑла. +ACOS = ACOS ## Возвращает арккоÑÐ¸Ð½ÑƒÑ Ñ‡Ð¸Ñла. +ACOSH = ACOSH ## Возвращает гиперболичеÑкий арккоÑÐ¸Ð½ÑƒÑ Ñ‡Ð¸Ñла. +ASIN = ASIN ## Возвращает аркÑÐ¸Ð½ÑƒÑ Ñ‡Ð¸Ñла. +ASINH = ASINH ## Возвращает гиперболичеÑкий аркÑÐ¸Ð½ÑƒÑ Ñ‡Ð¸Ñла. +ATAN = ATAN ## Возвращает Ð°Ñ€ÐºÑ‚Ð°Ð½Ð³ÐµÐ½Ñ Ñ‡Ð¸Ñла. +ATAN2 = ATAN2 ## Возвращает Ð°Ñ€ÐºÑ‚Ð°Ð½Ð³ÐµÐ½Ñ Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ñ‹Ñ… координат x и y. +ATANH = ATANH ## Возвращает гиперболичеÑкий Ð°Ñ€ÐºÑ‚Ð°Ð½Ð³ÐµÐ½Ñ Ñ‡Ð¸Ñла. +CEILING = ОКРВВЕРХ ## ОкруглÑет чиÑло до ближайшего целого или до ближайшего кратного указанному значению. +COMBIN = ЧИСЛКОМБ ## Возвращает количеÑтво комбинаций Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ чиÑла объектов. +COS = COS ## Возвращает коÑÐ¸Ð½ÑƒÑ Ñ‡Ð¸Ñла. +COSH = COSH ## Возвращает гиперболичеÑкий коÑÐ¸Ð½ÑƒÑ Ñ‡Ð¸Ñла. +DEGREES = ГРÐДУСЫ ## Преобразует радианы в градуÑÑ‹. +EVEN = ЧÐТР## ОкруглÑет чиÑло до ближайшего четного целого. +EXP = EXP ## Возвращает чиÑло e, возведенное в указанную Ñтепень. +FACT = ФÐКТР ## Возвращает факториал чиÑла. +FACTDOUBLE = ДВФÐКТР ## Возвращает двойной факториал чиÑла. +FLOOR = ОКРВÐИЗ ## ОкруглÑет чиÑло до ближайшего меньшего по модулю значениÑ. +GCD = ÐОД ## Возвращает наибольший общий делитель. +INT = ЦЕЛОЕ ## ОкруглÑет чиÑло до ближайшего меньшего целого. +LCM = ÐОК ## Возвращает наименьшее общее кратное. +LN = LN ## Возвращает натуральный логарифм чиÑла. +LOG = LOG ## Возвращает логарифм чиÑла по заданному оÑнованию. +LOG10 = LOG10 ## Возвращает деÑÑтичный логарифм чиÑла. +MDETERM = МОПРЕД ## Возвращает определитель матрицы маÑÑива. +MINVERSE = МОБР ## Возвращает обратную матрицу маÑÑива. +MMULT = МУМÐОЖ ## Возвращает произведение матриц двух маÑÑивов. +MOD = ОСТÐТ ## Возвращает оÑтаток от делениÑ. +MROUND = ОКРУГЛТ ## Возвращает чиÑло, округленное Ñ Ñ‚Ñ€ÐµÐ±ÑƒÐµÐ¼Ð¾Ð¹ точноÑтью. +MULTINOMIAL = МУЛЬТИÐОМ ## Возвращает мультиномиальный коÑффициент множеÑтва чиÑел. +ODD = ÐЕЧÐТ ## ОкруглÑет чиÑло до ближайшего нечетного целого. +PI = ПИ ## Возвращает чиÑло пи. +POWER = СТЕПЕÐЬ ## Возвращает результат Ð²Ð¾Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ñ‡Ð¸Ñла в Ñтепень. +PRODUCT = ПРОИЗВЕД ## Возвращает произведение аргументов. +QUOTIENT = ЧÐСТÐОЕ ## Возвращает целую чаÑÑ‚ÑŒ чаÑтного при делении. +RADIANS = РÐДИÐÐЫ ## Преобразует градуÑÑ‹ в радианы. +RAND = СЛЧИС ## Возвращает Ñлучайное чиÑло в интервале от 0 до 1. +RANDBETWEEN = СЛУЧМЕЖДУ ## Возвращает Ñлучайное чиÑло в интервале между Ð´Ð²ÑƒÐ¼Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸ чиÑлами. +ROMAN = РИМСКОЕ ## Преобразует арабÑкие цифры в римÑкие в виде текÑта. +ROUND = ОКРУГЛ ## ОкруглÑет чиÑло до указанного количеÑтва деÑÑтичных разрÑдов. +ROUNDDOWN = ОКРУГЛВÐИЗ ## ОкруглÑет чиÑло до ближайшего меньшего по модулю значениÑ. +ROUNDUP = ОКРУГЛВВЕРХ ## ОкруглÑет чиÑло до ближайшего большего по модулю значениÑ. +SERIESSUM = РЯД.СУММ ## Возвращает Ñумму Ñтепенного Ñ€Ñда, вычиÑленную по формуле. +SIGN = ЗÐÐК ## Возвращает знак чиÑла. +SIN = SIN ## Возвращает ÑÐ¸Ð½ÑƒÑ Ð·Ð°Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ угла. +SINH = SINH ## Возвращает гиперболичеÑкий ÑÐ¸Ð½ÑƒÑ Ñ‡Ð¸Ñла. +SQRT = КОРЕÐЬ ## Возвращает положительное значение квадратного корнÑ. +SQRTPI = КОРЕÐЬПИ ## Возвращает квадратный корень из Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð²Ñ‹Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ (чиÑло * ПИ). +SUBTOTAL = ПРОМЕЖУТОЧÐЫЕ.ИТОГИ ## Возвращает промежуточный итог в ÑпиÑке или базе данных. +SUM = СУММ ## Суммирует аргументы. +SUMIF = СУММЕСЛИ ## Суммирует Ñчейки, удовлетворÑющие заданному уÑловию. +SUMIFS = СУММЕСЛИМР## Суммирует диапазон Ñчеек, удовлетворÑющих неÑкольким уÑловиÑм. +SUMPRODUCT = СУММПРОИЗВ ## Возвращает Ñумму произведений ÑоответÑтвующих Ñлементов маÑÑивов. +SUMSQ = СУММКВ ## Возвращает Ñумму квадратов аргументов. +SUMX2MY2 = СУММРÐЗÐКВ ## Возвращает Ñумму разноÑтей квадратов ÑоответÑтвующих значений в двух маÑÑивах. +SUMX2PY2 = СУММСУММКВ ## Возвращает Ñумму Ñумм квадратов ÑоответÑтвующих Ñлементов двух маÑÑивов. +SUMXMY2 = СУММКВРÐЗР## Возвращает Ñумму квадратов разноÑтей ÑоответÑтвующих значений в двух маÑÑивах. +TAN = TAN ## Возвращает Ñ‚Ð°Ð½Ð³ÐµÐ½Ñ Ñ‡Ð¸Ñла. +TANH = TANH ## Возвращает гиперболичеÑкий Ñ‚Ð°Ð½Ð³ÐµÐ½Ñ Ñ‡Ð¸Ñла. +TRUNC = ОТБР ## ОтбраÑывает дробную чаÑÑ‚ÑŒ чиÑла. + + +## +## Statistical functions СтатиÑтичеÑкие функции +## +AVEDEV = СРОТКЛ ## Возвращает Ñреднее арифметичеÑкое абÑолютных значений отклонений точек данных от Ñреднего. +AVERAGE = СРЗÐÐЧ ## Возвращает Ñреднее арифметичеÑкое аргументов. +AVERAGEA = СРЗÐÐЧР## Возвращает Ñреднее арифметичеÑкое аргументов, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ‡Ð¸Ñла, текÑÑ‚ и логичеÑкие значениÑ. +AVERAGEIF = СРЗÐÐЧЕСЛИ ## Возвращает Ñреднее значение (Ñреднее арифметичеÑкое) вÑех Ñчеек в диапазоне, которые удовлетворÑÑŽÑ‚ данному уÑловию. +AVERAGEIFS = СРЗÐÐЧЕСЛИМР## Возвращает Ñреднее значение (Ñреднее арифметичеÑкое) вÑех Ñчеек, которые удовлетворÑÑŽÑ‚ неÑкольким уÑловиÑм. +BETADIST = БЕТÐРÐСП ## Возвращает интегральную функцию бета-раÑпределениÑ. +BETAINV = БЕТÐОБР ## Возвращает обратную интегральную функцию указанного бета-раÑпределениÑ. +BINOMDIST = БИÐОМРÐСП ## Возвращает отдельное значение биномиального раÑпределениÑ. +CHIDIST = ХИ2РÐСП ## Возвращает одноÑтороннюю вероÑтноÑÑ‚ÑŒ раÑÐ¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ…Ð¸-квадрат. +CHIINV = ХИ2ОБР ## Возвращает обратное значение одноÑторонней вероÑтноÑти раÑÐ¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ñ…Ð¸-квадрат. +CHITEST = ХИ2ТЕСТ ## Возвращает теÑÑ‚ на незавиÑимоÑÑ‚ÑŒ. +CONFIDENCE = ДОВЕРИТ ## Возвращает доверительный интервал Ð´Ð»Ñ Ñреднего Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð¿Ð¾ генеральной ÑовокупноÑти. +CORREL = КОРРЕЛ ## Возвращает коÑффициент коррелÑции между Ð´Ð²ÑƒÐ¼Ñ Ð¼Ð½Ð¾Ð¶ÐµÑтвами данных. +COUNT = СЧÐТ ## ПодÑчитывает количеÑтво чиÑел в ÑпиÑке аргументов. +COUNTA = СЧÐТЗ ## ПодÑчитывает количеÑтво значений в ÑпиÑке аргументов. +COUNTBLANK = СЧИТÐТЬПУСТОТЫ ## ПодÑчитывает количеÑтво пуÑÑ‚Ñ‹Ñ… Ñчеек в диапазоне +COUNTIF = СЧÐТЕСЛИ ## ПодÑчитывает количеÑтво Ñчеек в диапазоне, удовлетворÑющих заданному уÑловию +COUNTIFS = СЧÐТЕСЛИМР## ПодÑчитывает количеÑтво Ñчеек внутри диапазона, удовлетворÑющих неÑкольким уÑловиÑм. +COVAR = КОВÐР ## Возвращает ковариацию, Ñреднее произведений парных отклонений +CRITBINOM = КРИТБИÐОМ ## Возвращает наименьшее значение, Ð´Ð»Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ интегральное биномиальное раÑпределение меньше или равно заданному критерию. +DEVSQ = КВÐДРОТКЛ ## Возвращает Ñумму квадратов отклонений. +EXPONDIST = ЭКСПРÐСП ## Возвращает ÑкÑпоненциальное раÑпределение. +FDIST = FРÐСП ## Возвращает F-раÑпределение вероÑтноÑти. +FINV = FРÐСПОБР ## Возвращает обратное значение Ð´Ð»Ñ F-раÑÐ¿Ñ€ÐµÐ´ÐµÐ»ÐµÐ½Ð¸Ñ Ð²ÐµÑ€Ð¾ÑтноÑти. +FISHER = ФИШЕР ## Возвращает преобразование Фишера. +FISHERINV = ФИШЕРОБР ## Возвращает обратное преобразование Фишера. +FORECAST = ПРЕДСКÐЗ ## Возвращает значение линейного тренда. +FREQUENCY = ЧÐСТОТР## Возвращает раÑпределение чаÑтот в виде вертикального маÑÑива. +FTEST = ФТЕСТ ## Возвращает результат F-теÑта. +GAMMADIST = ГÐММÐРÐСП ## Возвращает гамма-раÑпределение. +GAMMAINV = ГÐММÐОБР ## Возвращает обратное гамма-раÑпределение. +GAMMALN = ГÐММÐÐЛОГ ## Возвращает натуральный логарифм гамма функции, Γ(x). +GEOMEAN = СРГЕОМ ## Возвращает Ñреднее геометричеÑкое. +GROWTH = РОСТ ## Возвращает Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² ÑоответÑтвии Ñ ÑкÑпоненциальным трендом. +HARMEAN = СРГÐРМ ## Возвращает Ñреднее гармоничеÑкое. +HYPGEOMDIST = ГИПЕРГЕОМЕТ ## Возвращает гипергеометричеÑкое раÑпределение. +INTERCEPT = ОТРЕЗОК ## Возвращает отрезок, отÑекаемый на оÑи линией линейной регреÑÑии. +KURT = ЭКСЦЕСС ## Возвращает ÑкÑцеÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑтва данных. +LARGE = ÐÐИБОЛЬШИЙ ## Возвращает k-ое наибольшее значение в множеÑтве данных. +LINEST = ЛИÐЕЙР## Возвращает параметры линейного тренда. +LOGEST = ЛГРФПРИБЛ ## Возвращает параметры ÑкÑпоненциального тренда. +LOGINV = ЛОГÐОРМОБР ## Возвращает обратное логарифмичеÑкое нормальное раÑпределение. +LOGNORMDIST = ЛОГÐОРМРÐСП ## Возвращает интегральное логарифмичеÑкое нормальное раÑпределение. +MAX = ÐœÐКС ## Возвращает наибольшее значение в ÑпиÑке аргументов. +MAXA = ÐœÐКСР## Возвращает наибольшее значение в ÑпиÑке аргументов, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ‡Ð¸Ñла, текÑÑ‚ и логичеÑкие значениÑ. +MEDIAN = МЕДИÐÐÐ ## Возвращает медиану заданных чиÑел. +MIN = МИР## Возвращает наименьшее значение в ÑпиÑке аргументов. +MINA = МИÐÐ ## Возвращает наименьшее значение в ÑпиÑке аргументов, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ‡Ð¸Ñла, текÑÑ‚ и логичеÑкие значениÑ. +MODE = МОДР## Возвращает значение моды множеÑтва данных. +NEGBINOMDIST = ОТРБИÐОМРÐСП ## Возвращает отрицательное биномиальное раÑпределение. +NORMDIST = ÐОРМРÐСП ## Возвращает нормальную функцию раÑпределениÑ. +NORMINV = ÐОРМОБР ## Возвращает обратное нормальное раÑпределение. +NORMSDIST = ÐОРМСТРÐСП ## Возвращает Ñтандартное нормальное интегральное раÑпределение. +NORMSINV = ÐОРМСТОБР ## Возвращает обратное значение Ñтандартного нормального раÑпределениÑ. +PEARSON = ПИРСОР## Возвращает коÑффициент коррелÑции ПирÑона. +PERCENTILE = ПЕРСЕÐТИЛЬ ## Возвращает k-ую перÑентиль Ð´Ð»Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ð¹ диапазона. +PERCENTRANK = ПРОЦЕÐТРÐÐГ ## Возвращает процентную норму Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² множеÑтве данных. +PERMUT = ПЕРЕСТ ## Возвращает количеÑтво переÑтановок Ð´Ð»Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ чиÑла объектов. +POISSON = ПУÐССОР## Возвращает раÑпределение ПуаÑÑона. +PROB = ВЕРОЯТÐОСТЬ ## Возвращает вероÑтноÑÑ‚ÑŒ того, что значение из диапазона находитÑÑ Ð²Ð½ÑƒÑ‚Ñ€Ð¸ заданных пределов. +QUARTILE = КВÐРТИЛЬ ## Возвращает квартиль множеÑтва данных. +RANK = РÐÐГ ## Возвращает ранг чиÑла в ÑпиÑке чиÑел. +RSQ = КВПИРСОР## Возвращает квадрат коÑффициента коррелÑции ПирÑона. +SKEW = СКОС ## Возвращает аÑимметрию раÑпределениÑ. +SLOPE = ÐÐКЛОР## Возвращает наклон линии линейной регреÑÑии. +SMALL = ÐÐИМЕÐЬШИЙ ## Возвращает k-ое наименьшее значение в множеÑтве данных. +STANDARDIZE = ÐОРМÐЛИЗÐЦИЯ ## Возвращает нормализованное значение. +STDEV = СТÐÐДОТКЛОР## Оценивает Ñтандартное отклонение по выборке. +STDEVA = СТÐÐДОТКЛОÐÐ ## Оценивает Ñтандартное отклонение по выборке, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ‡Ð¸Ñла, текÑÑ‚ и логичеÑкие значениÑ. +STDEVP = СТÐÐДОТКЛОÐП ## ВычиÑлÑет Ñтандартное отклонение по генеральной ÑовокупноÑти. +STDEVPA = СТÐÐДОТКЛОÐПР## ВычиÑлÑет Ñтандартное отклонение по генеральной ÑовокупноÑти, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ‡Ð¸Ñла, текÑÑ‚ и логичеÑкие значениÑ. +STEYX = СТОШYX ## Возвращает Ñтандартную ошибку предÑказанных значений y Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ x в регреÑÑии. +TDIST = СТЬЮДРÐСП ## Возвращает t-раÑпределение Стьюдента. +TINV = СТЬЮДРÐСПОБР ## Возвращает обратное t-раÑпределение Стьюдента. +TREND = ТЕÐДЕÐЦИЯ ## Возвращает Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² ÑоответÑтвии Ñ Ð»Ð¸Ð½ÐµÐ¹Ð½Ñ‹Ð¼ трендом. +TRIMMEAN = УРЕЗСРЕДÐЕЕ ## Возвращает Ñреднее внутренноÑти множеÑтва данных. +TTEST = ТТЕСТ ## Возвращает вероÑтноÑÑ‚ÑŒ, ÑоответÑтвующую критерию Стьюдента. +VAR = ДИСП ## Оценивает диÑперÑию по выборке. +VARA = ДИСПР## Оценивает диÑперÑию по выборке, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ‡Ð¸Ñла, текÑÑ‚ и логичеÑкие значениÑ. +VARP = ДИСПР ## ВычиÑлÑет диÑперÑию Ð´Ð»Ñ Ð³ÐµÐ½ÐµÑ€Ð°Ð»ÑŒÐ½Ð¾Ð¹ ÑовокупноÑти. +VARPA = ДИСПРР## ВычиÑлÑет диÑперÑию Ð´Ð»Ñ Ð³ÐµÐ½ÐµÑ€Ð°Ð»ÑŒÐ½Ð¾Ð¹ ÑовокупноÑти, Ð²ÐºÐ»ÑŽÑ‡Ð°Ñ Ñ‡Ð¸Ñла, текÑÑ‚ и логичеÑкие значениÑ. +WEIBULL = ВЕЙБУЛЛ ## Возвращает раÑпределение Вейбулла. +ZTEST = ZТЕСТ ## Возвращает двуÑтороннее P-значение z-теÑта. + + +## +## Text functions ТекÑтовые функции +## +ASC = ASC ## Ð”Ð»Ñ Ñзыков Ñ Ð´Ð²ÑƒÑ…Ð±Ð°Ð¹Ñ‚Ð¾Ð²Ñ‹Ð¼Ð¸ наборами знаков (например, катакана) преобразует полноширинные (двухбайтовые) знаки в полуширинные (однобайтовые). +BAHTTEXT = БÐТТЕКСТ ## Преобразует чиÑло в текÑÑ‚, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð´ÐµÐ½ÐµÐ¶Ð½Ñ‹Ð¹ формат ß (БÐТ). +CHAR = СИМВОЛ ## Возвращает знак Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ñ‹Ð¼ кодом. +CLEAN = ПЕЧСИМВ ## УдалÑет вÑе непечатаемые знаки из текÑта. +CODE = КОДСИМВ ## Возвращает чиÑловой код первого знака в текÑтовой Ñтроке. +CONCATENATE = СЦЕПИТЬ ## ОбъединÑет неÑколько текÑтовых Ñлементов в один. +DOLLAR = РУБЛЬ ## Преобразует чиÑло в текÑÑ‚, иÑÐ¿Ð¾Ð»ÑŒÐ·ÑƒÑ Ð´ÐµÐ½ÐµÐ¶Ð½Ñ‹Ð¹ формат. +EXACT = СОВПÐД ## ПроверÑет идентичноÑÑ‚ÑŒ двух текÑтовых значений. +FIND = ÐÐЙТИ ## Ищет Ð²Ñ…Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ текÑтового Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² другом (Ñ ÑƒÑ‡ÐµÑ‚Ð¾Ð¼ региÑтра). +FINDB = ÐÐЙТИБ ## Ищет Ð²Ñ…Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ текÑтового Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² другом (Ñ ÑƒÑ‡ÐµÑ‚Ð¾Ð¼ региÑтра). +FIXED = ФИКСИРОВÐÐÐЫЙ ## Форматирует чиÑло и преобразует его в текÑÑ‚ Ñ Ð·Ð°Ð´Ð°Ð½Ð½Ñ‹Ð¼ чиÑлом деÑÑтичных знаков. +JIS = JIS ## Ð”Ð»Ñ Ñзыков Ñ Ð´Ð²ÑƒÑ…Ð±Ð°Ð¹Ñ‚Ð¾Ð²Ñ‹Ð¼Ð¸ наборами знаков (например, катакана) преобразует полуширинные (однобайтовые) знаки в текÑтовой Ñтроке в полноширинные (двухбайтовые). +LEFT = ЛЕВСИМВ ## Возвращает крайние Ñлева знаки текÑтового значениÑ. +LEFTB = ЛЕВБ ## Возвращает крайние Ñлева знаки текÑтового значениÑ. +LEN = ДЛСТР ## Возвращает количеÑтво знаков в текÑтовой Ñтроке. +LENB = ДЛИÐБ ## Возвращает количеÑтво знаков в текÑтовой Ñтроке. +LOWER = СТРОЧР## Преобразует вÑе буквы текÑта в Ñтрочные. +MID = ПСТР ## Возвращает заданное чиÑло знаков из Ñтроки текÑта, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð¾Ð¹ позиции. +MIDB = ПСТРБ ## Возвращает заданное чиÑло знаков из Ñтроки текÑта, Ð½Ð°Ñ‡Ð¸Ð½Ð°Ñ Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ð¾Ð¹ позиции. +PHONETIC = PHONETIC ## Извлекает фонетичеÑкие (фуригана) знаки из текÑтовой Ñтроки. +PROPER = ПРОПÐÐЧ ## Преобразует первую букву в каждом Ñлове текÑта в пропиÑную. +REPLACE = ЗÐМЕÐИТЬ ## ЗаменÑет знаки в текÑте. +REPLACEB = ЗÐМЕÐИТЬБ ## ЗаменÑет знаки в текÑте. +REPT = ПОВТОР ## ПовторÑет текÑÑ‚ заданное чиÑло раз. +RIGHT = ПРÐВСИМВ ## Возвращает крайние Ñправа знаки текÑтовой Ñтроки. +RIGHTB = ПРÐВБ ## Возвращает крайние Ñправа знаки текÑтовой Ñтроки. +SEARCH = ПОИСК ## Ищет Ð²Ñ…Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ текÑтового Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² другом (без учета региÑтра). +SEARCHB = ПОИСКБ ## Ищет Ð²Ñ…Ð¾Ð¶Ð´ÐµÐ½Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ текÑтового Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² другом (без учета региÑтра). +SUBSTITUTE = ПОДСТÐВИТЬ ## ЗаменÑет в текÑтовой Ñтроке Ñтарый текÑÑ‚ новым. +T = Т ## Преобразует аргументы в текÑÑ‚. +TEXT = ТЕКСТ ## Форматирует чиÑло и преобразует его в текÑÑ‚. +TRIM = СЖПРОБЕЛЫ ## УдалÑет из текÑта пробелы. +UPPER = ПРОПИСР## Преобразует вÑе буквы текÑта в пропиÑные. +VALUE = ЗÐÐЧЕР## Преобразует текÑтовый аргумент в чиÑло. diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/sv/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/sv/config new file mode 100755 index 0000000..d305b27 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/sv/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = kr + + +## +## Excel Error Codes (For future use) +## +NULL = #Skärning! +DIV0 = #Division/0! +VALUE = #Värdefel! +REF = #Referens! +NAME = #Namn? +NUM = #Ogiltigt! +NA = #Saknas! diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/sv/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/sv/functions new file mode 100755 index 0000000..9af37d8 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/sv/functions @@ -0,0 +1,408 @@ +## +## Add-in and Automation functions Tilläggs- och automatiseringsfunktioner +## +GETPIVOTDATA = HÄMTA.PIVOTDATA ## Returnerar data som lagrats i en pivottabellrapport + + +## +## Cube functions Kubfunktioner +## +CUBEKPIMEMBER = KUBKPIMEDLEM ## Returnerar namn, egenskap och mÃ¥tt för en KPI och visar namnet och egenskapen i cellen. En KPI, eller prestandaindikator, är ett kvantifierbart mÃ¥tt, t.ex. mÃ¥natlig bruttovinst eller personalomsättning per kvartal, som används för att analysera ett företags resultat. +CUBEMEMBER = KUBMEDLEM ## Returnerar en medlem eller ett par i en kubhierarki. Används för att verifiera att medlemmen eller paret finns i kuben. +CUBEMEMBERPROPERTY = KUBMEDLEMSEGENSKAP ## Returnerar värdet för en medlemsegenskap i kuben. Används för att verifiera att ett medlemsnamn finns i kuben, samt för att returnera den angivna egenskapen för medlemmen. +CUBERANKEDMEMBER = KUBRANGORDNADMEDLEM ## Returnerar den n:te, eller rangordnade, medlemmen i en uppsättning. Används för att returnera ett eller flera element i en uppsättning, till exempelvis den bästa försäljaren eller de tio bästa eleverna. +CUBESET = KUBINSTÄLLNING ## Definierar en beräknad uppsättning medlemmar eller par genom att skicka ett bestämt uttryck till kuben pÃ¥ servern, som skapar uppsättningen och sedan returnerar den till Microsoft Office Excel. +CUBESETCOUNT = KUBINSTÄLLNINGANTAL ## Returnerar antalet objekt i en uppsättning. +CUBEVALUE = KUBVÄRDE ## Returnerar ett mängdvärde frÃ¥n en kub. + + +## +## Database functions Databasfunktioner +## +DAVERAGE = DMEDEL ## Returnerar medelvärdet av databasposterna +DCOUNT = DANTAL ## Räknar antalet celler som innehÃ¥ller tal i en databas +DCOUNTA = DANTALV ## Räknar ifyllda celler i en databas +DGET = DHÄMTA ## Hämtar en enstaka post frÃ¥n en databas som uppfyller de angivna villkoren +DMAX = DMAX ## Returnerar det största värdet frÃ¥n databasposterna +DMIN = DMIN ## Returnerar det minsta värdet frÃ¥n databasposterna +DPRODUCT = DPRODUKT ## Multiplicerar värdena i ett visst fält i poster som uppfyller villkoret +DSTDEV = DSTDAV ## Uppskattar standardavvikelsen baserat pÃ¥ ett urval av databasposterna +DSTDEVP = DSTDAVP ## Beräknar standardavvikelsen utifrÃ¥n hela populationen av valda databasposter +DSUM = DSUMMA ## Summerar talen i kolumnfält i databasposter som uppfyller villkoret +DVAR = DVARIANS ## Uppskattar variansen baserat pÃ¥ ett urval av databasposterna +DVARP = DVARIANSP ## Beräknar variansen utifrÃ¥n hela populationen av valda databasposter + + +## +## Date and time functions Tid- och datumfunktioner +## +DATE = DATUM ## Returnerar ett serienummer för ett visst datum +DATEVALUE = DATUMVÄRDE ## Konverterar ett datum i textformat till ett serienummer +DAY = DAG ## Konverterar ett serienummer till dag i mÃ¥naden +DAYS360 = DAGAR360 ## Beräknar antalet dagar mellan tvÃ¥ datum baserat pÃ¥ ett 360-dagarsÃ¥r +EDATE = EDATUM ## Returnerar serienumret för ett datum som infaller ett visst antal mÃ¥nader före eller efter startdatumet +EOMONTH = SLUTMÃ…NAD ## Returnerar serienumret för sista dagen i mÃ¥naden ett visst antal mÃ¥nader tidigare eller senare +HOUR = TIMME ## Konverterar ett serienummer till en timme +MINUTE = MINUT ## Konverterar ett serienummer till en minut +MONTH = MÃ…NAD ## Konverterar ett serienummer till en mÃ¥nad +NETWORKDAYS = NETTOARBETSDAGAR ## Returnerar antalet hela arbetsdagar mellan tvÃ¥ datum +NOW = NU ## Returnerar serienumret för dagens datum och aktuell tid +SECOND = SEKUND ## Konverterar ett serienummer till en sekund +TIME = KLOCKSLAG ## Returnerar serienumret för en viss tid +TIMEVALUE = TIDVÄRDE ## Konverterar en tid i textformat till ett serienummer +TODAY = IDAG ## Returnerar serienumret för dagens datum +WEEKDAY = VECKODAG ## Konverterar ett serienummer till en dag i veckan +WEEKNUM = VECKONR ## Konverterar ett serienummer till ett veckonummer +WORKDAY = ARBETSDAGAR ## Returnerar serienumret för ett datum ett visst antal arbetsdagar tidigare eller senare +YEAR = Ã…R ## Konverterar ett serienummer till ett Ã¥r +YEARFRAC = Ã…RDEL ## Returnerar en del av ett Ã¥r som representerar antalet hela dagar mellan start- och slutdatum + + +## +## Engineering functions Tekniska funktioner +## +BESSELI = BESSELI ## Returnerar den modifierade Bessel-funktionen In(x) +BESSELJ = BESSELJ ## Returnerar Bessel-funktionen Jn(x) +BESSELK = BESSELK ## Returnerar den modifierade Bessel-funktionen Kn(x) +BESSELY = BESSELY ## Returnerar Bessel-funktionen Yn(x) +BIN2DEC = BIN.TILL.DEC ## Omvandlar ett binärt tal till decimalt +BIN2HEX = BIN.TILL.HEX ## Omvandlar ett binärt tal till hexadecimalt +BIN2OCT = BIN.TILL.OKT ## Omvandlar ett binärt tal till oktalt +COMPLEX = KOMPLEX ## Omvandlar reella och imaginära koefficienter till ett komplext tal +CONVERT = KONVERTERA ## Omvandlar ett tal frÃ¥n ett mÃ¥ttsystem till ett annat +DEC2BIN = DEC.TILL.BIN ## Omvandlar ett decimalt tal till binärt +DEC2HEX = DEC.TILL.HEX ## Omvandlar ett decimalt tal till hexadecimalt +DEC2OCT = DEC.TILL.OKT ## Omvandlar ett decimalt tal till oktalt +DELTA = DELTA ## Testar om tvÃ¥ värden är lika +ERF = FELF ## Returnerar felfunktionen +ERFC = FELFK ## Returnerar den komplementära felfunktionen +GESTEP = SLSTEG ## Testar om ett tal är större än ett tröskelvärde +HEX2BIN = HEX.TILL.BIN ## Omvandlar ett hexadecimalt tal till binärt +HEX2DEC = HEX.TILL.DEC ## Omvandlar ett hexadecimalt tal till decimalt +HEX2OCT = HEX.TILL.OKT ## Omvandlar ett hexadecimalt tal till oktalt +IMABS = IMABS ## Returnerar absolutvärdet (modulus) för ett komplext tal +IMAGINARY = IMAGINÄR ## Returnerar den imaginära koefficienten för ett komplext tal +IMARGUMENT = IMARGUMENT ## Returnerar det komplexa talets argument, en vinkel uttryckt i radianer +IMCONJUGATE = IMKONJUGAT ## Returnerar det komplexa talets konjugat +IMCOS = IMCOS ## Returnerar cosinus för ett komplext tal +IMDIV = IMDIV ## Returnerar kvoten för tvÃ¥ komplexa tal +IMEXP = IMEUPPHÖJT ## Returnerar exponenten för ett komplext tal +IMLN = IMLN ## Returnerar den naturliga logaritmen för ett komplext tal +IMLOG10 = IMLOG10 ## Returnerar 10-logaritmen för ett komplext tal +IMLOG2 = IMLOG2 ## Returnerar 2-logaritmen för ett komplext tal +IMPOWER = IMUPPHÖJT ## Returnerar ett komplext tal upphöjt till en exponent +IMPRODUCT = IMPRODUKT ## Returnerar produkten av komplexa tal +IMREAL = IMREAL ## Returnerar den reella koefficienten för ett komplext tal +IMSIN = IMSIN ## Returnerar sinus för ett komplext tal +IMSQRT = IMROT ## Returnerar kvadratroten av ett komplext tal +IMSUB = IMDIFF ## Returnerar differensen mellan tvÃ¥ komplexa tal +IMSUM = IMSUM ## Returnerar summan av komplexa tal +OCT2BIN = OKT.TILL.BIN ## Omvandlar ett oktalt tal till binärt +OCT2DEC = OKT.TILL.DEC ## Omvandlar ett oktalt tal till decimalt +OCT2HEX = OKT.TILL.HEX ## Omvandlar ett oktalt tal till hexadecimalt + + +## +## Financial functions Finansiella funktioner +## +ACCRINT = UPPLRÄNTA ## Returnerar den upplupna räntan för värdepapper med periodisk ränta +ACCRINTM = UPPLOBLRÄNTA ## Returnerar den upplupna räntan för ett värdepapper som ger avkastning pÃ¥ förfallodagen +AMORDEGRC = AMORDEGRC ## Returnerar avskrivningen för varje redovisningsperiod med hjälp av en avskrivningskoefficient +AMORLINC = AMORLINC ## Returnerar avskrivningen för varje redovisningsperiod +COUPDAYBS = KUPDAGBB ## Returnerar antal dagar frÃ¥n början av kupongperioden till likviddagen +COUPDAYS = KUPDAGARS ## Returnerar antalet dagar i kupongperioden som innehÃ¥ller betalningsdatumet +COUPDAYSNC = KUPDAGNK ## Returnerar antalet dagar frÃ¥n betalningsdatumet till nästa kupongdatum +COUPNCD = KUPNKD ## Returnerar nästa kupongdatum efter likviddagen +COUPNUM = KUPANT ## Returnerar kuponger som förfaller till betalning mellan likviddagen och förfallodagen +COUPPCD = KUPFKD ## Returnerar föregÃ¥ende kupongdatum före likviddagen +CUMIPMT = KUMRÄNTA ## Returnerar den ackumulerade räntan som betalats mellan tvÃ¥ perioder +CUMPRINC = KUMPRIS ## Returnerar det ackumulerade kapitalbeloppet som betalats pÃ¥ ett lÃ¥n mellan tvÃ¥ perioder +DB = DB ## Returnerar avskrivningen för en tillgÃ¥ng under en angiven tid enligt metoden för fast degressiv avskrivning +DDB = DEGAVSKR ## Returnerar en tillgÃ¥ngs värdeminskning under en viss period med hjälp av dubbel degressiv avskrivning eller nÃ¥gon annan metod som du anger +DISC = DISK ## Returnerar diskonteringsräntan för ett värdepapper +DOLLARDE = DECTAL ## Omvandlar ett pris uttryckt som ett brÃ¥k till ett decimaltal +DOLLARFR = BRÃ…K ## Omvandlar ett pris i kronor uttryckt som ett decimaltal till ett brÃ¥k +DURATION = LÖPTID ## Returnerar den Ã¥rliga löptiden för en säkerhet med periodiska räntebetalningar +EFFECT = EFFRÄNTA ## Returnerar den Ã¥rliga effektiva räntesatsen +FV = SLUTVÄRDE ## Returnerar det framtida värdet pÃ¥ en investering +FVSCHEDULE = FÖRRÄNTNING ## Returnerar det framtida värdet av ett begynnelsekapital beräknat pÃ¥ olika räntenivÃ¥er +INTRATE = Ã…RSRÄNTA ## Returnerar räntesatsen för ett betalt värdepapper +IPMT = RBETALNING ## Returnerar räntedelen av en betalning för en given period +IRR = IR ## Returnerar internräntan för en serie betalningar +ISPMT = RALÃ…N ## Beräknar räntan som har betalats under en specifik betalningsperiod +MDURATION = MLÖPTID ## Returnerar den modifierade Macauley-löptiden för ett värdepapper med det antagna nominella värdet 100 kr +MIRR = MODIR ## Returnerar internräntan där positiva och negativa betalningar finansieras med olika räntor +NOMINAL = NOMRÄNTA ## Returnerar den Ã¥rliga nominella räntesatsen +NPER = PERIODER ## Returnerar antalet perioder för en investering +NPV = NETNUVÄRDE ## Returnerar nuvärdet av en serie periodiska betalningar vid en given diskonteringsränta +ODDFPRICE = UDDAFPRIS ## Returnerar priset per 100 kr nominellt värde för ett värdepapper med en udda första period +ODDFYIELD = UDDAFAVKASTNING ## Returnerar avkastningen för en säkerhet med en udda första period +ODDLPRICE = UDDASPRIS ## Returnerar priset per 100 kr nominellt värde för ett värdepapper med en udda sista period +ODDLYIELD = UDDASAVKASTNING ## Returnerar avkastningen för en säkerhet med en udda sista period +PMT = BETALNING ## Returnerar den periodiska betalningen för en annuitet +PPMT = AMORT ## Returnerar amorteringsdelen av en annuitetsbetalning för en given period +PRICE = PRIS ## Returnerar priset per 100 kr nominellt värde för ett värdepapper som ger periodisk ränta +PRICEDISC = PRISDISK ## Returnerar priset per 100 kr nominellt värde för ett diskonterat värdepapper +PRICEMAT = PRISFÖRF ## Returnerar priset per 100 kr nominellt värde för ett värdepapper som ger ränta pÃ¥ förfallodagen +PV = PV ## Returnerar nuvärdet av en serie lika stora periodiska betalningar +RATE = RÄNTA ## Returnerar räntesatsen per period i en annuitet +RECEIVED = BELOPP ## Returnerar beloppet som utdelas pÃ¥ förfallodagen för ett betalat värdepapper +SLN = LINAVSKR ## Returnerar den linjära avskrivningen för en tillgÃ¥ng under en period +SYD = Ã…RSAVSKR ## Returnerar den Ã¥rliga avskrivningssumman för en tillgÃ¥ng under en angiven period +TBILLEQ = SSVXEKV ## Returnerar avkastningen motsvarande en obligation för en statsskuldväxel +TBILLPRICE = SSVXPRIS ## Returnerar priset per 100 kr nominellt värde för en statsskuldväxel +TBILLYIELD = SSVXRÄNTA ## Returnerar avkastningen för en statsskuldväxel +VDB = VDEGRAVSKR ## Returnerar avskrivningen för en tillgÃ¥ng under en angiven period (med degressiv avskrivning) +XIRR = XIRR ## Returnerar internräntan för en serie betalningar som inte nödvändigtvis är periodiska +XNPV = XNUVÄRDE ## Returnerar det nuvarande nettovärdet för en serie betalningar som inte nödvändigtvis är periodiska +YIELD = NOMAVK ## Returnerar avkastningen för ett värdepapper som ger periodisk ränta +YIELDDISC = NOMAVKDISK ## Returnerar den Ã¥rliga avkastningen för diskonterade värdepapper, exempelvis en statsskuldväxel +YIELDMAT = NOMAVKFÖRF ## Returnerar den Ã¥rliga avkastningen för ett värdepapper som ger ränta pÃ¥ förfallodagen + + +## +## Information functions Informationsfunktioner +## +CELL = CELL ## Returnerar information om formatering, plats och innehÃ¥ll i en cell +ERROR.TYPE = FEL.TYP ## Returnerar ett tal som motsvarar ett felvärde +INFO = INFO ## Returnerar information om operativsystemet +ISBLANK = ÄRREF ## Returnerar SANT om värdet är tomt +ISERR = Ä ## Returnerar SANT om värdet är ett felvärde annat än #SAKNAS! +ISERROR = ÄRFEL ## Returnerar SANT om värdet är ett felvärde +ISEVEN = ÄRJÄMN ## Returnerar SANT om talet är jämnt +ISLOGICAL = ÄREJTEXT ## Returnerar SANT om värdet är ett logiskt värde +ISNA = ÄRLOGISK ## Returnerar SANT om värdet är felvärdet #SAKNAS! +ISNONTEXT = ÄRSAKNAD ## Returnerar SANT om värdet inte är text +ISNUMBER = ÄRTAL ## Returnerar SANT om värdet är ett tal +ISODD = ÄRUDDA ## Returnerar SANT om talet är udda +ISREF = ÄRTOM ## Returnerar SANT om värdet är en referens +ISTEXT = ÄRTEXT ## Returnerar SANT om värdet är text +N = N ## Returnerar ett värde omvandlat till ett tal +NA = SAKNAS ## Returnerar felvärdet #SAKNAS! +TYPE = VÄRDETYP ## Returnerar ett tal som anger värdets datatyp + + +## +## Logical functions Logiska funktioner +## +AND = OCH ## Returnerar SANT om alla argument är sanna +FALSE = FALSKT ## Returnerar det logiska värdet FALSKT +IF = OM ## Anger vilket logiskt test som ska utföras +IFERROR = OMFEL ## Returnerar ett värde som du anger om en formel utvärderar till ett fel; annars returneras resultatet av formeln +NOT = ICKE ## Inverterar logiken för argumenten +OR = ELLER ## Returnerar SANT om nÃ¥got argument är SANT +TRUE = SANT ## Returnerar det logiska värdet SANT + + +## +## Lookup and reference functions Sök- och referensfunktioner +## +ADDRESS = ADRESS ## Returnerar en referens som text till en enstaka cell i ett kalkylblad +AREAS = OMRÃ…DEN ## Returnerar antalet omrÃ¥den i en referens +CHOOSE = VÄLJ ## Väljer ett värde i en lista över värden +COLUMN = KOLUMN ## Returnerar kolumnnumret för en referens +COLUMNS = KOLUMNER ## Returnerar antalet kolumner i en referens +HLOOKUP = LETAKOLUMN ## Söker i den översta raden i en matris och returnerar värdet för angiven cell +HYPERLINK = HYPERLÄNK ## Skapar en genväg eller ett hopp till ett dokument i nätverket, i ett intranät eller pÃ¥ Internet +INDEX = INDEX ## Använder ett index för ett välja ett värde i en referens eller matris +INDIRECT = INDIREKT ## Returnerar en referens som anges av ett textvärde +LOOKUP = LETAUPP ## Letar upp värden i en vektor eller matris +MATCH = PASSA ## Letar upp värden i en referens eller matris +OFFSET = FÖRSKJUTNING ## Returnerar en referens förskjuten i förhÃ¥llande till en given referens +ROW = RAD ## Returnerar radnumret för en referens +ROWS = RADER ## Returnerar antalet rader i en referens +RTD = RTD ## Hämtar realtidsdata frÃ¥n ett program som stöder COM-automation (Automation: Ett sätt att arbeta med ett programs objekt frÃ¥n ett annat program eller utvecklingsverktyg. Detta kallades tidigare för OLE Automation, och är en branschstandard och ingÃ¥r i Component Object Model (COM).) +TRANSPOSE = TRANSPONERA ## Transponerar en matris +VLOOKUP = LETARAD ## Letar i den första kolumnen i en matris och flyttar över raden för att returnera värdet för en cell + + +## +## Math and trigonometry functions Matematiska och trigonometriska funktioner +## +ABS = ABS ## Returnerar absolutvärdet av ett tal +ACOS = ARCCOS ## Returnerar arcus cosinus för ett tal +ACOSH = ARCCOSH ## Returnerar inverterad hyperbolisk cosinus för ett tal +ASIN = ARCSIN ## Returnerar arcus cosinus för ett tal +ASINH = ARCSINH ## Returnerar hyperbolisk arcus sinus för ett tal +ATAN = ARCTAN ## Returnerar arcus tangens för ett tal +ATAN2 = ARCTAN2 ## Returnerar arcus tangens för en x- och en y- koordinat +ATANH = ARCTANH ## Returnerar hyperbolisk arcus tangens för ett tal +CEILING = RUNDA.UPP ## Avrundar ett tal till närmaste heltal eller närmaste signifikanta multipel +COMBIN = KOMBIN ## Returnerar antalet kombinationer för ett givet antal objekt +COS = COS ## Returnerar cosinus för ett tal +COSH = COSH ## Returnerar hyperboliskt cosinus för ett tal +DEGREES = GRADER ## Omvandlar radianer till grader +EVEN = JÄMN ## Avrundar ett tal uppÃ¥t till närmaste heltal +EXP = EXP ## Returnerar e upphöjt till ett givet tal +FACT = FAKULTET ## Returnerar fakulteten för ett tal +FACTDOUBLE = DUBBELFAKULTET ## Returnerar dubbelfakulteten för ett tal +FLOOR = RUNDA.NED ## Avrundar ett tal nedÃ¥t mot noll +GCD = SGD ## Returnerar den största gemensamma nämnaren +INT = HELTAL ## Avrundar ett tal nedÃ¥t till närmaste heltal +LCM = MGM ## Returnerar den minsta gemensamma multipeln +LN = LN ## Returnerar den naturliga logaritmen för ett tal +LOG = LOG ## Returnerar logaritmen för ett tal för en given bas +LOG10 = LOG10 ## Returnerar 10-logaritmen för ett tal +MDETERM = MDETERM ## Returnerar matrisen som är avgörandet av en matris +MINVERSE = MINVERT ## Returnerar matrisinversen av en matris +MMULT = MMULT ## Returnerar matrisprodukten av tvÃ¥ matriser +MOD = REST ## Returnerar resten vid en division +MROUND = MAVRUNDA ## Returnerar ett tal avrundat till en given multipel +MULTINOMIAL = MULTINOMIAL ## Returnerar multinomialen för en uppsättning tal +ODD = UDDA ## Avrundar ett tal uppÃ¥t till närmaste udda heltal +PI = PI ## Returnerar värdet pi +POWER = UPPHÖJT.TILL ## Returnerar resultatet av ett tal upphöjt till en exponent +PRODUCT = PRODUKT ## Multiplicerar argumenten +QUOTIENT = KVOT ## Returnerar heltalsdelen av en division +RADIANS = RADIANER ## Omvandlar grader till radianer +RAND = SLUMP ## Returnerar ett slumptal mellan 0 och 1 +RANDBETWEEN = SLUMP.MELLAN ## Returnerar ett slumptal mellan de tal som du anger +ROMAN = ROMERSK ## Omvandlar vanliga (arabiska) siffror till romerska som text +ROUND = AVRUNDA ## Avrundar ett tal till ett angivet antal siffror +ROUNDDOWN = AVRUNDA.NEDÃ…T ## Avrundar ett tal nedÃ¥t mot noll +ROUNDUP = AVRUNDA.UPPÃ…T ## Avrundar ett tal uppÃ¥t, frÃ¥n noll +SERIESSUM = SERIESUMMA ## Returnerar summan av en potensserie baserat pÃ¥ formeln +SIGN = TECKEN ## Returnerar tecknet för ett tal +SIN = SIN ## Returnerar sinus för en given vinkel +SINH = SINH ## Returnerar hyperbolisk sinus för ett tal +SQRT = ROT ## Returnerar den positiva kvadratroten +SQRTPI = ROTPI ## Returnerar kvadratroten för (tal * pi) +SUBTOTAL = DELSUMMA ## Returnerar en delsumma i en lista eller databas +SUM = SUMMA ## Summerar argumenten +SUMIF = SUMMA.OM ## Summerar celler enligt ett angivet villkor +SUMIFS = SUMMA.OMF ## Lägger till cellerna i ett omrÃ¥de som uppfyller flera kriterier +SUMPRODUCT = PRODUKTSUMMA ## Returnerar summan av produkterna i motsvarande matriskomponenter +SUMSQ = KVADRATSUMMA ## Returnerar summan av argumentens kvadrater +SUMX2MY2 = SUMMAX2MY2 ## Returnerar summan av differensen mellan kvadraterna för motsvarande värden i tvÃ¥ matriser +SUMX2PY2 = SUMMAX2PY2 ## Returnerar summan av summan av kvadraterna av motsvarande värden i tvÃ¥ matriser +SUMXMY2 = SUMMAXMY2 ## Returnerar summan av kvadraten av skillnaden mellan motsvarande värden i tvÃ¥ matriser +TAN = TAN ## Returnerar tangens för ett tal +TANH = TANH ## Returnerar hyperbolisk tangens för ett tal +TRUNC = AVKORTA ## Avkortar ett tal till ett heltal + + +## +## Statistical functions Statistiska funktioner +## +AVEDEV = MEDELAVV ## Returnerar medelvärdet för datapunkters absoluta avvikelse frÃ¥n deras medelvärde +AVERAGE = MEDEL ## Returnerar medelvärdet av argumenten +AVERAGEA = AVERAGEA ## Returnerar medelvärdet av argumenten, inklusive tal, text och logiska värden +AVERAGEIF = MEDELOM ## Returnerar medelvärdet (aritmetiskt medelvärde) för alla celler i ett omrÃ¥de som uppfyller ett givet kriterium +AVERAGEIFS = MEDELOMF ## Returnerar medelvärdet (det aritmetiska medelvärdet) för alla celler som uppfyller flera villkor. +BETADIST = BETAFÖRD ## Returnerar den kumulativa betafördelningsfunktionen +BETAINV = BETAINV ## Returnerar inversen till den kumulativa fördelningsfunktionen för en viss betafördelning +BINOMDIST = BINOMFÖRD ## Returnerar den individuella binomialfördelningen +CHIDIST = CHI2FÖRD ## Returnerar den ensidiga sannolikheten av c2-fördelningen +CHIINV = CHI2INV ## Returnerar inversen av chi2-fördelningen +CHITEST = CHI2TEST ## Returnerar oberoendetesten +CONFIDENCE = KONFIDENS ## Returnerar konfidensintervallet för en populations medelvärde +CORREL = KORREL ## Returnerar korrelationskoefficienten mellan tvÃ¥ datamängder +COUNT = ANTAL ## Räknar hur mÃ¥nga tal som finns bland argumenten +COUNTA = ANTALV ## Räknar hur mÃ¥nga värden som finns bland argumenten +COUNTBLANK = ANTAL.TOMMA ## Räknar antalet tomma celler i ett omrÃ¥de +COUNTIF = ANTAL.OM ## Räknar antalet celler i ett omrÃ¥de som uppfyller angivna villkor. +COUNTIFS = ANTAL.OMF ## Räknar antalet celler i ett omrÃ¥de som uppfyller flera villkor. +COVAR = KOVAR ## Returnerar kovariansen, d.v.s. medelvärdet av produkterna för parade avvikelser +CRITBINOM = KRITBINOM ## Returnerar det minsta värdet för vilket den kumulativa binomialfördelningen är mindre än eller lika med ett villkorsvärde +DEVSQ = KVADAVV ## Returnerar summan av kvadrater pÃ¥ avvikelser +EXPONDIST = EXPONFÖRD ## Returnerar exponentialfördelningen +FDIST = FFÖRD ## Returnerar F-sannolikhetsfördelningen +FINV = FINV ## Returnerar inversen till F-sannolikhetsfördelningen +FISHER = FISHER ## Returnerar Fisher-transformationen +FISHERINV = FISHERINV ## Returnerar inversen till Fisher-transformationen +FORECAST = PREDIKTION ## Returnerar ett värde längs en linjär trendlinje +FREQUENCY = FREKVENS ## Returnerar en frekvensfördelning som en lodrät matris +FTEST = FTEST ## Returnerar resultatet av en F-test +GAMMADIST = GAMMAFÖRD ## Returnerar gammafördelningen +GAMMAINV = GAMMAINV ## Returnerar inversen till den kumulativa gammafördelningen +GAMMALN = GAMMALN ## Returnerar den naturliga logaritmen för gammafunktionen, G(x) +GEOMEAN = GEOMEDEL ## Returnerar det geometriska medelvärdet +GROWTH = EXPTREND ## Returnerar värden längs en exponentiell trend +HARMEAN = HARMMEDEL ## Returnerar det harmoniska medelvärdet +HYPGEOMDIST = HYPGEOMFÖRD ## Returnerar den hypergeometriska fördelningen +INTERCEPT = SKÄRNINGSPUNKT ## Returnerar skärningspunkten för en linjär regressionslinje +KURT = TOPPIGHET ## Returnerar toppigheten av en mängd data +LARGE = STÖRSTA ## Returnerar det n:te största värdet i en mängd data +LINEST = REGR ## Returnerar parametrar till en linjär trendlinje +LOGEST = EXPREGR ## Returnerar parametrarna i en exponentiell trend +LOGINV = LOGINV ## Returnerar inversen till den lognormala fördelningen +LOGNORMDIST = LOGNORMFÖRD ## Returnerar den kumulativa lognormala fördelningen +MAX = MAX ## Returnerar det största värdet i en lista av argument +MAXA = MAXA ## Returnerar det största värdet i en lista av argument, inklusive tal, text och logiska värden +MEDIAN = MEDIAN ## Returnerar medianen för angivna tal +MIN = MIN ## Returnerar det minsta värdet i en lista med argument +MINA = MINA ## Returnerar det minsta värdet i en lista över argument, inklusive tal, text och logiska värden +MODE = TYPVÄRDE ## Returnerar det vanligaste värdet i en datamängd +NEGBINOMDIST = NEGBINOMFÖRD ## Returnerar den negativa binomialfördelningen +NORMDIST = NORMFÖRD ## Returnerar den kumulativa normalfördelningen +NORMINV = NORMINV ## Returnerar inversen till den kumulativa normalfördelningen +NORMSDIST = NORMSFÖRD ## Returnerar den kumulativa standardnormalfördelningen +NORMSINV = NORMSINV ## Returnerar inversen till den kumulativa standardnormalfördelningen +PEARSON = PEARSON ## Returnerar korrelationskoefficienten till Pearsons momentprodukt +PERCENTILE = PERCENTIL ## Returnerar den n:te percentilen av värden i ett omrÃ¥de +PERCENTRANK = PROCENTRANG ## Returnerar procentrangen för ett värde i en datamängd +PERMUT = PERMUT ## Returnerar antal permutationer för ett givet antal objekt +POISSON = POISSON ## Returnerar Poisson-fördelningen +PROB = SANNOLIKHET ## Returnerar sannolikheten att värden i ett omrÃ¥de ligger mellan tvÃ¥ gränser +QUARTILE = KVARTIL ## Returnerar kvartilen av en mängd data +RANK = RANG ## Returnerar rangordningen för ett tal i en lista med tal +RSQ = RKV ## Returnerar kvadraten av Pearsons produktmomentkorrelationskoefficient +SKEW = SNEDHET ## Returnerar snedheten för en fördelning +SLOPE = LUTNING ## Returnerar lutningen pÃ¥ en linjär regressionslinje +SMALL = MINSTA ## Returnerar det n:te minsta värdet i en mängd data +STANDARDIZE = STANDARDISERA ## Returnerar ett normaliserat värde +STDEV = STDAV ## Uppskattar standardavvikelsen baserat pÃ¥ ett urval +STDEVA = STDEVA ## Uppskattar standardavvikelsen baserat pÃ¥ ett urval, inklusive tal, text och logiska värden +STDEVP = STDAVP ## Beräknar standardavvikelsen baserat pÃ¥ hela populationen +STDEVPA = STDEVPA ## Beräknar standardavvikelsen baserat pÃ¥ hela populationen, inklusive tal, text och logiska värden +STEYX = STDFELYX ## Returnerar standardfelet för ett förutspÃ¥tt y-värde för varje x-värde i regressionen +TDIST = TFÖRD ## Returnerar Students t-fördelning +TINV = TINV ## Returnerar inversen till Students t-fördelning +TREND = TREND ## Returnerar värden längs en linjär trend +TRIMMEAN = TRIMMEDEL ## Returnerar medelvärdet av mittpunkterna i en datamängd +TTEST = TTEST ## Returnerar sannolikheten beräknad ur Students t-test +VAR = VARIANS ## Uppskattar variansen baserat pÃ¥ ett urval +VARA = VARA ## Uppskattar variansen baserat pÃ¥ ett urval, inklusive tal, text och logiska värden +VARP = VARIANSP ## Beräknar variansen baserat pÃ¥ hela populationen +VARPA = VARPA ## Beräknar variansen baserat pÃ¥ hela populationen, inklusive tal, text och logiska värden +WEIBULL = WEIBULL ## Returnerar Weibull-fördelningen +ZTEST = ZTEST ## Returnerar det ensidiga sannolikhetsvärdet av ett z-test + + +## +## Text functions Textfunktioner +## +ASC = ASC ## Ändrar helbredds (dubbel byte) engelska bokstäver eller katakana inom en teckensträng till tecken med halvt breddsteg (enkel byte) +BAHTTEXT = BAHTTEXT ## Omvandlar ett tal till text med valutaformatet ß (baht) +CHAR = TECKENKOD ## Returnerar tecknet som anges av kod +CLEAN = STÄDA ## Tar bort alla icke utskrivbara tecken i en text +CODE = KOD ## Returnerar en numerisk kod för det första tecknet i en textsträng +CONCATENATE = SAMMANFOGA ## Sammanfogar flera textdelar till en textsträng +DOLLAR = VALUTA ## Omvandlar ett tal till text med valutaformat +EXACT = EXAKT ## Kontrollerar om tvÃ¥ textvärden är identiska +FIND = HITTA ## Hittar en text i en annan (skiljer pÃ¥ gemener och versaler) +FINDB = HITTAB ## Hittar en text i en annan (skiljer pÃ¥ gemener och versaler) +FIXED = FASTTAL ## Formaterar ett tal som text med ett fast antal decimaler +JIS = JIS ## Ändrar halvbredds (enkel byte) engelska bokstäver eller katakana inom en teckensträng till tecken med helt breddsteg (dubbel byte) +LEFT = VÄNSTER ## Returnerar tecken längst till vänster i en sträng +LEFTB = VÄNSTERB ## Returnerar tecken längst till vänster i en sträng +LEN = LÄNGD ## Returnerar antalet tecken i en textsträng +LENB = LÄNGDB ## Returnerar antalet tecken i en textsträng +LOWER = GEMENER ## Omvandlar text till gemener +MID = EXTEXT ## Returnerar angivet antal tecken frÃ¥n en text med början vid den position som du anger +MIDB = EXTEXTB ## Returnerar angivet antal tecken frÃ¥n en text med början vid den position som du anger +PHONETIC = PHONETIC ## Returnerar de fonetiska (furigana) tecknen i en textsträng +PROPER = INITIAL ## Ändrar första bokstaven i varje ord i ett textvärde till versal +REPLACE = ERSÄTT ## Ersätter tecken i text +REPLACEB = ERSÄTTB ## Ersätter tecken i text +REPT = REP ## Upprepar en text ett bestämt antal gÃ¥nger +RIGHT = HÖGER ## Returnerar tecken längst till höger i en sträng +RIGHTB = HÖGERB ## Returnerar tecken längst till höger i en sträng +SEARCH = SÖK ## Hittar ett textvärde i ett annat (skiljer inte pÃ¥ gemener och versaler) +SEARCHB = SÖKB ## Hittar ett textvärde i ett annat (skiljer inte pÃ¥ gemener och versaler) +SUBSTITUTE = BYT.UT ## Ersätter gammal text med ny text i en textsträng +T = T ## Omvandlar argumenten till text +TEXT = TEXT ## Formaterar ett tal och omvandlar det till text +TRIM = RENSA ## Tar bort blanksteg frÃ¥n text +UPPER = VERSALER ## Omvandlar text till versaler +VALUE = TEXTNUM ## Omvandlar ett textargument till ett tal diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/tr/config b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/tr/config new file mode 100755 index 0000000..c36e941 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/tr/config @@ -0,0 +1,47 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Settings +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## + + +ArgumentSeparator = ; + + +## +## (For future use) +## +currencySymbol = YTL + + +## +## Excel Error Codes (For future use) +## +NULL = #BOÅž! +DIV0 = #SAYI/0! +VALUE = #DEÄžER! +REF = #BAÅžV! +NAME = #AD? +NUM = #SAYI! +NA = #YOK diff --git a/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/tr/functions b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/tr/functions new file mode 100755 index 0000000..1a4a8a1 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/Classes/PHPExcel/locale/tr/functions @@ -0,0 +1,438 @@ +## +## PHPExcel +## +## Copyright (c) 2006 - 2013 PHPExcel +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Lesser General Public +## License as published by the Free Software Foundation; either +## version 2.1 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public +## License along with this library; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +## +## @category PHPExcel +## @package PHPExcel_Calculation +## @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +## @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +## @version 1.7.9, 2013-06-02 +## +## Data in this file derived from http://www.piuha.fi/excel-function-name-translation/ +## +## + + +## +## Add-in and Automation functions Eklenti ve Otomasyon fonksiyonları +## +GETPIVOTDATA = ÖZETVERÄ°AL ## Bir Özet Tablo raporunda saklanan verileri verir. + + +## +## Cube functions Küp iÅŸlevleri +## +CUBEKPIMEMBER = KÃœPKPIÃœYE ## Kilit performans göstergesi (KPI-Key Performance Indicator) adını, özelliÄŸini ve ölçüsünü verir ve hücredeki ad ve özelliÄŸi gösterir. KPI, bir kurumun performansını izlemek için kullanılan aylık brüt kâr ya da üç aylık çalışan giriÅŸ çıkışları gibi ölçülebilen bir birimdir. +CUBEMEMBER = KÃœPÃœYE ## Bir küp hiyerarÅŸisinde bir üyeyi veya kaydı verir. Ãœye veya kaydın küpte varolduÄŸunu doÄŸrulamak için kullanılır. +CUBEMEMBERPROPERTY = KÃœPÃœYEÖZELLİĞİ ## Bir küpte bir üyenin özelliÄŸinin deÄŸerini verir. Küp içinde üye adının varlığını doÄŸrulamak ve bu üyenin belli özelliklerini getirmek için kullanılır. +CUBERANKEDMEMBER = KÃœPÃœYESIRASI ## Bir küme içindeki üyenin derecesini veya kaçıncı olduÄŸunu verir. En iyi satış elemanı, veya en iyi on öğrenci gibi bir kümedeki bir veya daha fazla öğeyi getirmek için kullanılır. +CUBESET = KÃœPKÃœME ## Kümeyi oluÅŸturan ve ardından bu kümeyi Microsoft Office Excel'e getiren sunucudaki küpe küme ifadelerini göndererek hesaplanan üye veya kayıt kümesini tanımlar. +CUBESETCOUNT = KÃœPKÃœMESAY ## Bir kümedeki öğelerin sayısını getirir. +CUBEVALUE = KÃœPDEÄžER ## Bir küpten toplam deÄŸeri getirir. + + +## +## Database functions Veritabanı iÅŸlevleri +## +DAVERAGE = VSEÇORT ## Seçili veritabanı girdilerinin ortalamasını verir. +DCOUNT = VSEÇSAY ## Veritabanında sayı içeren hücre sayısını hesaplar. +DCOUNTA = VSEÇSAYDOLU ## Veritabanındaki boÅŸ olmayan hücreleri sayar. +DGET = VAL ## Veritabanından, belirtilen ölçütlerle eÅŸleÅŸen tek bir rapor çıkarır. +DMAX = VSEÇMAK ## Seçili veritabanı giriÅŸlerinin en yüksek deÄŸerini verir. +DMIN = VSEÇMÄ°N ## Seçili veritabanı giriÅŸlerinin en düşük deÄŸerini verir. +DPRODUCT = VSEÇÇARP ## Kayıtların belli bir alanında bulunan, bir veritabanındaki ölçütlerle eÅŸleÅŸen deÄŸerleri çarpar. +DSTDEV = VSEÇSTDSAPMA ## Seçili veritabanı giriÅŸlerinden oluÅŸan bir örneÄŸe dayanarak, standart sapmayı tahmin eder. +DSTDEVP = VSEÇSTDSAPMAS ## Standart sapmayı, seçili veritabanı giriÅŸlerinin tüm popülasyonunu esas alarak hesaplar. +DSUM = VSEÇTOPLA ## Kayıtların alan sütununda bulunan, ölçütle eÅŸleÅŸen sayıları toplar. +DVAR = VSEÇVAR ## Seçili veritabanı giriÅŸlerinden oluÅŸan bir örneÄŸi esas alarak farkı tahmin eder. +DVARP = VSEÇVARS ## Seçili veritabanı giriÅŸlerinin tüm popülasyonunu esas alarak farkı hesaplar. + + +## +## Date and time functions Tarih ve saat iÅŸlevleri +## +DATE = TARÄ°H ## Belirli bir tarihin seri numarasını verir. +DATEVALUE = TARÄ°HSAYISI ## Metin biçimindeki bir tarihi seri numarasına dönüştürür. +DAY = GÃœN ## Seri numarasını, ayın bir gününe dönüştürür. +DAYS360 = GÃœN360 ## Ä°ki tarih arasındaki gün sayısını, 360 günlük yılı esas alarak hesaplar. +EDATE = SERÄ°TARÄ°H ## BaÅŸlangıç tarihinden itibaren, belirtilen ay sayısından önce veya sonraki tarihin seri numarasını verir. +EOMONTH = SERÄ°AY ## Belirtilen sayıda ay önce veya sonraki ayın son gününün seri numarasını verir. +HOUR = SAAT ## Bir seri numarasını saate dönüştürür. +MINUTE = DAKÄ°KA ## Bir seri numarasını dakikaya dönüştürür. +MONTH = AY ## Bir seri numarasını aya dönüştürür. +NETWORKDAYS = TAMÄ°ÅžGÃœNÃœ ## Ä°ki tarih arasındaki tam çalışma günlerinin sayısını verir. +NOW = ŞİMDÄ° ## Geçerli tarihin ve saatin seri numarasını verir. +SECOND = SANÄ°YE ## Bir seri numarasını saniyeye dönüştürür. +TIME = ZAMAN ## Belirli bir zamanın seri numarasını verir. +TIMEVALUE = ZAMANSAYISI ## Metin biçimindeki zamanı seri numarasına dönüştürür. +TODAY = BUGÃœN ## Bugünün tarihini seri numarasına dönüştürür. +WEEKDAY = HAFTANINGÃœNÃœ ## Bir seri numarasını, haftanın gününe dönüştürür. +WEEKNUM = HAFTASAY ## Dizisel deÄŸerini, haftanın yıl içinde bulunduÄŸu konumu sayısal olarak gösteren sayıya dönüştürür. +WORKDAY = Ä°ÅžGÃœNÃœ ## Belirtilen sayıda çalışma günü öncesinin ya da sonrasının tarihinin seri numarasını verir. +YEAR = YIL ## Bir seri numarasını yıla dönüştürür. +YEARFRAC = YILORAN ## BaÅŸlangıç_tarihi ve bitiÅŸ_tarihi arasındaki tam günleri gösteren yıl kesrini verir. + + +## +## Engineering functions Mühendislik iÅŸlevleri +## +BESSELI = BESSELI ## DeÄŸiÅŸtirilmiÅŸ Bessel fonksiyonu In(x)'i verir. +BESSELJ = BESSELJ ## Bessel fonksiyonu Jn(x)'i verir. +BESSELK = BESSELK ## DeÄŸiÅŸtirilmiÅŸ Bessel fonksiyonu Kn(x)'i verir. +BESSELY = BESSELY ## Bessel fonksiyonu Yn(x)'i verir. +BIN2DEC = BIN2DEC ## Ä°kili bir sayıyı, ondalık sayıya dönüştürür. +BIN2HEX = BIN2HEX ## Ä°kili bir sayıyı, onaltılıya dönüştürür. +BIN2OCT = BIN2OCT ## Ä°kili bir sayıyı, sekizliye dönüştürür. +COMPLEX = KARMAÅžIK ## Gerçek ve sanal katsayıları, karmaşık sayıya dönüştürür. +CONVERT = ÇEVÄ°R ## Bir sayıyı, bir ölçüm sisteminden bir baÅŸka ölçüm sistemine dönüştürür. +DEC2BIN = DEC2BIN ## Ondalık bir sayıyı, ikiliye dönüştürür. +DEC2HEX = DEC2HEX ## Ondalık bir sayıyı, onaltılıya dönüştürür. +DEC2OCT = DEC2OCT ## Ondalık bir sayıyı sekizliÄŸe dönüştürür. +DELTA = DELTA ## Ä°ki deÄŸerin eÅŸit olup olmadığını sınar. +ERF = HATAÄ°ÅžLEV ## Hata iÅŸlevini verir. +ERFC = TÃœMHATAÄ°ÅžLEV ## Tümleyici hata iÅŸlevini verir. +GESTEP = BESINIR ## Bir sayının eÅŸik deÄŸerinden büyük olup olmadığını sınar. +HEX2BIN = HEX2BIN ## Onaltılı bir sayıyı ikiliye dönüştürür. +HEX2DEC = HEX2DEC ## Onaltılı bir sayıyı ondalığa dönüştürür. +HEX2OCT = HEX2OCT ## Onaltılı bir sayıyı sekizliÄŸe dönüştürür. +IMABS = SANMUTLAK ## Karmaşık bir sayının mutlak deÄŸerini (modül) verir. +IMAGINARY = SANAL ## Karmaşık bir sayının sanal katsayısını verir. +IMARGUMENT = SANBAÄž_DEĞİŞKEN ## Radyanlarla belirtilen bir açı olan teta bağımsız deÄŸiÅŸkenini verir. +IMCONJUGATE = SANEÅžLENEK ## Karmaşık bir sayının karmaşık eÅŸleniÄŸini verir. +IMCOS = SANCOS ## Karmaşık bir sayının kosinüsünü verir. +IMDIV = SANBÖL ## Ä°ki karmaşık sayının bölümünü verir. +IMEXP = SANÃœS ## Karmaşık bir sayının üssünü verir. +IMLN = SANLN ## Karmaşık bir sayının doÄŸal logaritmasını verir. +IMLOG10 = SANLOG10 ## Karmaşık bir sayının, 10 tabanında logaritmasını verir. +IMLOG2 = SANLOG2 ## Karmaşık bir sayının 2 tabanında logaritmasını verir. +IMPOWER = SANÃœSSÃœ ## Karmaşık bir sayıyı, bir tamsayı üssüne yükseltilmiÅŸ olarak verir. +IMPRODUCT = SANÇARP ## Karmaşık sayıların çarpımını verir. +IMREAL = SANGERÇEK ## Karmaşık bir sayının, gerçek katsayısını verir. +IMSIN = SANSIN ## Karmaşık bir sayının sinüsünü verir. +IMSQRT = SANKAREKÖK ## Karmaşık bir sayının karekökünü verir. +IMSUB = SANÇIKAR ## Ä°ki karmaşık sayının farkını verir. +IMSUM = SANTOPLA ## Karmaşık sayıların toplamını verir. +OCT2BIN = OCT2BIN ## Sekizli bir sayıyı ikiliye dönüştürür. +OCT2DEC = OCT2DEC ## Sekizli bir sayıyı ondalığa dönüştürür. +OCT2HEX = OCT2HEX ## Sekizli bir sayıyı onaltılıya dönüştürür. + + +## +## Financial functions Finansal fonksiyonlar +## +ACCRINT = GERÇEKFAÄ°Z ## Dönemsel faiz ödeyen hisse senedine iliÅŸkin tahakkuk eden faizi getirir. +ACCRINTM = GERÇEKFAÄ°ZV ## Vadesinde ödeme yapan bir tahvilin tahakkuk etmiÅŸ faizini verir. +AMORDEGRC = AMORDEGRC ## Yıpranma katsayısı kullanarak her hesap döneminin deÄŸer kaybını verir. +AMORLINC = AMORLINC ## Her hesap dönemi içindeki yıpranmayı verir. +COUPDAYBS = KUPONGÃœNBD ## Kupon süresinin baÅŸlangıcından alış tarihine kadar olan süredeki gün sayısını verir. +COUPDAYS = KUPONGÃœN ## Kupon süresindeki, gün sayısını, alış tarihini de içermek üzere, verir. +COUPDAYSNC = KUPONGÃœNDSK ## Alış tarihinden bir sonraki kupon tarihine kadar olan gün sayısını verir. +COUPNCD = KUPONGÃœNSKT ## Alış tarihinden bir sonraki kupon tarihini verir. +COUPNUM = KUPONSAYI ## Alış tarihiyle vade tarihi arasında ödenecek kuponların sayısını verir. +COUPPCD = KUPONGÃœNÖKT ## Alış tarihinden bir önceki kupon tarihini verir. +CUMIPMT = AİÇVERÄ°MORANI ## Ä°ki dönem arasında ödenen kümülatif faizi verir. +CUMPRINC = ANA_PARA_ÖDEMESÄ° ## Ä°ki dönem arasında bir borç üzerine ödenen birikimli temeli verir. +DB = AZALANBAKÄ°YE ## Bir malın belirtilen bir süre içindeki yıpranmasını, sabit azalan bakiye yöntemini kullanarak verir. +DDB = ÇİFTAZALANBAKÄ°YE ## Bir malın belirtilen bir süre içindeki yıpranmasını, çift azalan bakiye yöntemi ya da sizin belirttiÄŸiniz baÅŸka bir yöntemi kullanarak verir. +DISC = Ä°NDÄ°RÄ°M ## Bir tahvilin indirim oranını verir. +DOLLARDE = LÄ°RAON ## Kesir olarak tanımlanmış lira fiyatını, ondalık sayı olarak tanımlanmış lira fiyatına dönüştürür. +DOLLARFR = LÄ°RAKES ## Ondalık sayı olarak tanımlanmış lira fiyatını, kesir olarak tanımlanmış lira fiyatına dönüştürür. +DURATION = SÃœRE ## Belli aralıklarla faiz ödemesi yapan bir tahvilin yıllık süresini verir. +EFFECT = ETKÄ°N ## Efektif yıllık faiz oranını verir. +FV = ANBD ## Bir yatırımın gelecekteki deÄŸerini verir. +FVSCHEDULE = GDPROGRAM ## Bir seri birleÅŸik faiz oranı uyguladıktan sonra, bir baÅŸlangıçtaki anaparanın gelecekteki deÄŸerini verir. +INTRATE = FAÄ°ZORANI ## Tam olarak yatırım yapılmış bir tahvilin faiz oranını verir. +IPMT = FAÄ°ZTUTARI ## Bir yatırımın verilen bir süre için faiz ödemesini verir. +IRR = İÇ_VERÄ°M_ORANI ## Bir para akışı serisi için, iç verim oranını verir. +ISPMT = ISPMT ## Yatırımın belirli bir dönemi boyunca ödenen faizi hesaplar. +MDURATION = MSÃœRE ## Varsayılan par deÄŸeri 10.000.000 lira olan bir tahvil için Macauley deÄŸiÅŸtirilmiÅŸ süreyi verir. +MIRR = D_İÇ_VERÄ°M_ORANI ## Pozitif ve negatif para akışlarının farklı oranlarda finanse edildiÄŸi durumlarda, iç verim oranını verir. +NOMINAL = NOMÄ°NAL ## Yıllık nominal faiz oranını verir. +NPER = DÖNEM_SAYISI ## Bir yatırımın dönem sayısını verir. +NPV = NBD ## Bir yatırımın bugünkü net deÄŸerini, bir dönemsel para akışları serisine ve bir indirim oranına baÄŸlı olarak verir. +ODDFPRICE = TEKYDEÄžER ## Tek bir ilk dönemi olan bir tahvilin deÄŸerini, her 100.000.000 lirada bir verir. +ODDFYIELD = TEKYÖDEME ## Tek bir ilk dönemi olan bir tahvilin ödemesini verir. +ODDLPRICE = TEKSDEÄžER ## Tek bir son dönemi olan bir tahvilin fiyatını her 10.000.000 lirada bir verir. +ODDLYIELD = TEKSÖDEME ## Tek bir son dönemi olan bir tahvilin ödemesini verir. +PMT = DEVRESEL_ÖDEME ## Bir yıllık dönemsel ödemeyi verir. +PPMT = ANA_PARA_ÖDEMESÄ° ## Verilen bir süre için, bir yatırımın anaparasına dayanan ödemeyi verir. +PRICE = DEÄžER ## Dönemsel faiz ödeyen bir tahvilin fiyatını 10.000.00 liralık deÄŸer başına verir. +PRICEDISC = DEÄžERÄ°ND ## Ä°ndirimli bir tahvilin fiyatını 10.000.000 liralık nominal deÄŸer başına verir. +PRICEMAT = DEÄžERVADE ## Faizini vade sonunda ödeyen bir tahvilin fiyatını 10.000.000 nominal deÄŸer başına verir. +PV = BD ## Bir yatırımın bugünkü deÄŸerini verir. +RATE = FAÄ°Z_ORANI ## Bir yıllık dönem başına düşen faiz oranını verir. +RECEIVED = GETÄ°RÄ° ## Tam olarak yatırılmış bir tahvilin vadesinin bitiminde alınan miktarı verir. +SLN = DA ## Bir malın bir dönem içindeki doÄŸrusal yıpranmasını verir. +SYD = YAT ## Bir malın belirli bir dönem için olan amortismanını verir. +TBILLEQ = HTAHEÅž ## Bir Hazine bonosunun bono eÅŸdeÄŸeri ödemesini verir. +TBILLPRICE = HTAHDEÄžER ## Bir Hazine bonosunun deÄŸerini, 10.000.000 liralık nominal deÄŸer başına verir. +TBILLYIELD = HTAHÖDEME ## Bir Hazine bonosunun ödemesini verir. +VDB = DAB ## Bir malın amortismanını, belirlenmiÅŸ ya da kısmi bir dönem için, bir azalan bakiye yöntemi kullanarak verir. +XIRR = AİÇVERÄ°MORANI ## Dönemsel olması gerekmeyen bir para akışları programı için, iç verim oranını verir. +XNPV = ANBD ## Dönemsel olması gerekmeyen bir para akışları programı için, bugünkü net deÄŸeri verir. +YIELD = ÖDEME ## Belirli aralıklarla faiz ödeyen bir tahvilin ödemesini verir. +YIELDDISC = ÖDEMEÄ°ND ## Ä°ndirimli bir tahvilin yıllık ödemesini verir; örneÄŸin, bir Hazine bonosunun. +YIELDMAT = ÖDEMEVADE ## Vadesinin bitiminde faiz ödeyen bir tahvilin yıllık ödemesini verir. + + +## +## Information functions Bilgi fonksiyonları +## +CELL = HÃœCRE ## Bir hücrenin biçimlendirmesi, konumu ya da içeriÄŸi hakkında bilgi verir. +ERROR.TYPE = HATA.TÄ°PÄ° ## Bir hata türüne iliÅŸkin sayıları verir. +INFO = BÄ°LGÄ° ## Geçerli iÅŸletim ortamı hakkında bilgi verir. +ISBLANK = EBOÅžSA ## DeÄŸer boÅŸsa, DOÄžRU verir. +ISERR = EHATA ## DeÄŸer, #YOK dışındaki bir hata deÄŸeriyse, DOÄžRU verir. +ISERROR = EHATALIYSA ## DeÄŸer, herhangi bir hata deÄŸeriyse, DOÄžRU verir. +ISEVEN = ÇİFTTÄ°R ## Sayı çiftse, DOÄžRU verir. +ISLOGICAL = EMANTIKSALSA ## DeÄŸer, mantıksal bir deÄŸerse, DOÄžRU verir. +ISNA = EYOKSA ## DeÄŸer, #YOK hata deÄŸeriyse, DOÄžRU verir. +ISNONTEXT = EMETÄ°NDEĞİLSE ## DeÄŸer, metin deÄŸilse, DOÄžRU verir. +ISNUMBER = ESAYIYSA ## DeÄŸer, bir sayıysa, DOÄžRU verir. +ISODD = TEKTÄ°R ## Sayı tekse, DOÄžRU verir. +ISREF = EREFSE ## DeÄŸer bir baÅŸvuruysa, DOÄžRU verir. +ISTEXT = EMETÄ°NSE ## DeÄŸer bir metinse DOÄžRU verir. +N = N ## Sayıya dönüştürülmüş bir deÄŸer verir. +NA = YOKSAY ## #YOK hata deÄŸerini verir. +TYPE = TÄ°P ## Bir deÄŸerin veri türünü belirten bir sayı verir. + + +## +## Logical functions Mantıksal fonksiyonlar +## +AND = VE ## Bütün bağımsız deÄŸiÅŸkenleri DOÄžRU ise, DOÄžRU verir. +FALSE = YANLIÅž ## YANLIÅž mantıksal deÄŸerini verir. +IF = EÄžER ## GerçekleÅŸtirilecek bir mantıksal sınama belirtir. +IFERROR = EÄžERHATA ## Formül hatalıysa belirttiÄŸiniz deÄŸeri verir; bunun dışındaki durumlarda formülün sonucunu verir. +NOT = DEĞİL ## Bağımsız deÄŸiÅŸkeninin mantığını tersine çevirir. +OR = YADA ## Bağımsız deÄŸiÅŸkenlerden herhangi birisi DOÄžRU ise, DOÄžRU verir. +TRUE = DOÄžRU ## DOÄžRU mantıksal deÄŸerini verir. + + +## +## Lookup and reference functions Arama ve BaÅŸvuru fonksiyonları +## +ADDRESS = ADRES ## Bir baÅŸvuruyu, çalışma sayfasındaki tek bir hücreye metin olarak verir. +AREAS = ALANSAY ## Renvoie le nombre de zones dans une référence. +CHOOSE = ELEMAN ## DeÄŸerler listesinden bir deÄŸer seçer. +COLUMN = SÃœTUN ## Bir baÅŸvurunun sütun sayısını verir. +COLUMNS = SÃœTUNSAY ## Bir baÅŸvurudaki sütunların sayısını verir. +HLOOKUP = YATAYARA ## Bir dizinin en üst satırına bakar ve belirtilen hücrenin deÄŸerini verir. +HYPERLINK = KÖPRÃœ ## Bir aÄŸ sunucusunda, bir intranette ya da Internet'te depolanan bir belgeyi açan bir kısayol ya da atlama oluÅŸturur. +INDEX = Ä°NDÄ°S ## BaÅŸvurudan veya diziden bir deÄŸer seçmek için, bir dizin kullanır. +INDIRECT = DOLAYLI ## Metin deÄŸeriyle belirtilen bir baÅŸvuru verir. +LOOKUP = ARA ## Bir vektördeki veya dizideki deÄŸerleri arar. +MATCH = KAÇINCI ## Bir baÅŸvurudaki veya dizideki deÄŸerleri arar. +OFFSET = KAYDIR ## Verilen bir baÅŸvurudan, bir baÅŸvuru kaydırmayı verir. +ROW = SATIR ## Bir baÅŸvurunun satır sayısını verir. +ROWS = SATIRSAY ## Bir baÅŸvurudaki satırların sayısını verir. +RTD = RTD ## COM otomasyonunu destekleyen programdan gerçek zaman verileri alır. +TRANSPOSE = DEVRÄ°K_DÖNÜŞÜM ## Bir dizinin devrik dönüşümünü verir. +VLOOKUP = DÜŞEYARA ## Bir dizinin ilk sütununa bakar ve bir hücrenin deÄŸerini vermek için satır boyunca hareket eder. + + +## +## Math and trigonometry functions Matematik ve trigonometri fonksiyonları +## +ABS = MUTLAK ## Bir sayının mutlak deÄŸerini verir. +ACOS = ACOS ## Bir sayının ark kosinüsünü verir. +ACOSH = ACOSH ## Bir sayının ters hiperbolik kosinüsünü verir. +ASIN = ASÄ°N ## Bir sayının ark sinüsünü verir. +ASINH = ASÄ°NH ## Bir sayının ters hiperbolik sinüsünü verir. +ATAN = ATAN ## Bir sayının ark tanjantını verir. +ATAN2 = ATAN2 ## Ark tanjantı, x- ve y- koordinatlarından verir. +ATANH = ATANH ## Bir sayının ters hiperbolik tanjantını verir. +CEILING = TAVANAYUVARLA ## Bir sayıyı, en yakın tamsayıya ya da en yakın katına yuvarlar. +COMBIN = KOMBÄ°NASYON ## Verilen sayıda öğenin kombinasyon sayısını verir. +COS = COS ## Bir sayının kosinüsünü verir. +COSH = COSH ## Bir sayının hiperbolik kosinüsünü verir. +DEGREES = DERECE ## Radyanları dereceye dönüştürür. +EVEN = ÇİFT ## Bir sayıyı, en yakın daha büyük çift tamsayıya yuvarlar. +EXP = ÃœS ## e'yi, verilen bir sayının üssüne yükseltilmiÅŸ olarak verir. +FACT = ÇARPINIM ## Bir sayının faktörünü verir. +FACTDOUBLE = ÇİFTFAKTÖR ## Bir sayının çift çarpınımını verir. +FLOOR = TABANAYUVARLA ## Bir sayıyı, daha küçük sayıya, sıfıra yakınsayarak yuvarlar. +GCD = OBEB ## En büyük ortak böleni verir. +INT = TAMSAYI ## Bir sayıyı aÅŸağıya doÄŸru en yakın tamsayıya yuvarlar. +LCM = OKEK ## En küçük ortak katı verir. +LN = LN ## Bir sayının doÄŸal logaritmasını verir. +LOG = LOG ## Bir sayının, belirtilen bir tabandaki logaritmasını verir. +LOG10 = LOG10 ## Bir sayının 10 tabanında logaritmasını verir. +MDETERM = DETERMÄ°NANT ## Bir dizinin dizey determinantını verir. +MINVERSE = DÄ°ZEY_TERS ## Bir dizinin dizey tersini verir. +MMULT = DÇARP ## Ä°ki dizinin dizey çarpımını verir. +MOD = MODÃœLO ## Bölmeden kalanı verir. +MROUND = KYUVARLA ## Ä°stenen kata yuvarlanmış bir sayı verir. +MULTINOMIAL = ÇOKTERÄ°MLÄ° ## Bir sayılar kümesinin çok terimlisini verir. +ODD = TEK ## Bir sayıyı en yakın daha büyük tek sayıya yuvarlar. +PI = PÄ° ## Pi deÄŸerini verir. +POWER = KUVVET ## Bir üsse yükseltilmiÅŸ sayının sonucunu verir. +PRODUCT = ÇARPIM ## Bağımsız deÄŸiÅŸkenlerini çarpar. +QUOTIENT = BÖLÃœM ## Bir bölme iÅŸleminin tamsayı kısmını verir. +RADIANS = RADYAN ## Dereceleri radyanlara dönüştürür. +RAND = S_SAYI_ÃœRET ## 0 ile 1 arasında rastgele bir sayı verir. +RANDBETWEEN = RASTGELEARALIK ## BelirttiÄŸiniz sayılar arasında rastgele bir sayı verir. +ROMAN = ROMEN ## Bir normal rakamı, metin olarak, romen rakamına çevirir. +ROUND = YUVARLA ## Bir sayıyı, belirtilen basamak sayısına yuvarlar. +ROUNDDOWN = AÅžAÄžIYUVARLA ## Bir sayıyı, daha küçük sayıya, sıfıra yakınsayarak yuvarlar. +ROUNDUP = YUKARIYUVARLA ## Bir sayıyı daha büyük sayıya, sıfırdan ıraksayarak yuvarlar. +SERIESSUM = SERÄ°TOPLA ## Bir üs serisinin toplamını, formüle baÄŸlı olarak verir. +SIGN = Ä°ÅžARET ## Bir sayının iÅŸaretini verir. +SIN = SÄ°N ## Verilen bir açının sinüsünü verir. +SINH = SÄ°NH ## Bir sayının hiperbolik sinüsünü verir. +SQRT = KAREKÖK ## Pozitif bir karekök verir. +SQRTPI = KAREKÖKPÄ° ## (* Pi sayısının) kare kökünü verir. +SUBTOTAL = ALTTOPLAM ## Bir listedeki ya da veritabanındaki bir alt toplamı verir. +SUM = TOPLA ## Bağımsız deÄŸiÅŸkenlerini toplar. +SUMIF = ETOPLA ## Verilen ölçütle belirlenen hücreleri toplar. +SUMIFS = SUMIFS ## Bir aralıktaki, birden fazla ölçüte uyan hücreleri ekler. +SUMPRODUCT = TOPLA.ÇARPIM ## Ä°liÅŸkili dizi bileÅŸenlerinin çarpımlarının toplamını verir. +SUMSQ = TOPKARE ## Bağımsız deÄŸiÅŸkenlerin karelerinin toplamını verir. +SUMX2MY2 = TOPX2EY2 ## Ä°ki dizideki iliÅŸkili deÄŸerlerin farkının toplamını verir. +SUMX2PY2 = TOPX2AY2 ## Ä°ki dizideki iliÅŸkili deÄŸerlerin karelerinin toplamının toplamını verir. +SUMXMY2 = TOPXEY2 ## Ä°ki dizideki iliÅŸkili deÄŸerlerin farklarının karelerinin toplamını verir. +TAN = TAN ## Bir sayının tanjantını verir. +TANH = TANH ## Bir sayının hiperbolik tanjantını verir. +TRUNC = NSAT ## Bir sayının, tamsayı durumuna gelecek ÅŸekilde, fazlalıklarını atar. + + +## +## Statistical functions Ä°statistiksel fonksiyonlar +## +AVEDEV = ORTSAP ## Veri noktalarının ortalamalarından mutlak sapmalarının ortalamasını verir. +AVERAGE = ORTALAMA ## Bağımsız deÄŸiÅŸkenlerinin ortalamasını verir. +AVERAGEA = ORTALAMAA ## Bağımsız deÄŸiÅŸkenlerinin, sayılar, metin ve mantıksal deÄŸerleri içermek üzere ortalamasını verir. +AVERAGEIF = EÄžERORTALAMA ## Verili ölçütü karşılayan bir aralıktaki bütün hücrelerin ortalamasını (aritmetik ortalama) hesaplar. +AVERAGEIFS = EÄžERLERORTALAMA ## Birden çok ölçüte uyan tüm hücrelerin ortalamasını (aritmetik ortalama) hesaplar. +BETADIST = BETADAÄž ## Beta birikimli dağılım fonksiyonunu verir. +BETAINV = BETATERS ## Belirli bir beta dağılımı için birikimli dağılım fonksiyonunun tersini verir. +BINOMDIST = BÄ°NOMDAÄž ## Tek terimli binom dağılımı olasılığını verir. +CHIDIST = KÄ°KAREDAÄž ## Kikare dağılımın tek kuyruklu olasılığını verir. +CHIINV = KÄ°KARETERS ## Kikare dağılımın kuyruklu olasılığının tersini verir. +CHITEST = KÄ°KARETEST ## Bağımsızlık sınamalarını verir. +CONFIDENCE = GÃœVENÄ°RLÄ°K ## Bir popülasyon ortalaması için güvenirlik aralığını verir. +CORREL = KORELASYON ## Ä°ki veri kümesi arasındaki baÄŸlantı katsayısını verir. +COUNT = BAÄž_DEÄž_SAY ## Bağımsız deÄŸiÅŸkenler listesinde kaç tane sayı bulunduÄŸunu sayar. +COUNTA = BAÄž_DEÄž_DOLU_SAY ## Bağımsız deÄŸiÅŸkenler listesinde kaç tane deÄŸer bulunduÄŸunu sayar. +COUNTBLANK = BOÅžLUKSAY ## Aralıktaki boÅŸ hücre sayısını hesaplar. +COUNTIF = EÄžERSAY ## Verilen ölçütlere uyan bir aralık içindeki hücreleri sayar. +COUNTIFS = ÇOKEÄžERSAY ## Birden çok ölçüte uyan bir aralık içindeki hücreleri sayar. +COVAR = KOVARYANS ## EÅŸleÅŸtirilmiÅŸ sapmaların ortalaması olan kovaryansı verir. +CRITBINOM = KRÄ°TÄ°KBÄ°NOM ## Birikimli binom dağılımının bir ölçüt deÄŸerinden küçük veya ölçüt deÄŸerine eÅŸit olduÄŸu en küçük deÄŸeri verir. +DEVSQ = SAPKARE ## Sapmaların karelerinin toplamını verir. +EXPONDIST = ÃœSTELDAÄž ## Ãœstel dağılımı verir. +FDIST = FDAÄž ## F olasılık dağılımını verir. +FINV = FTERS ## F olasılık dağılımının tersini verir. +FISHER = FISHER ## Fisher dönüşümünü verir. +FISHERINV = FISHERTERS ## Fisher dönüşümünün tersini verir. +FORECAST = TAHMÄ°N ## Bir doÄŸrusal eÄŸilim boyunca bir deÄŸer verir. +FREQUENCY = SIKLIK ## Bir sıklık dağılımını, dikey bir dizi olarak verir. +FTEST = FTEST ## Bir F-test'in sonucunu verir. +GAMMADIST = GAMADAÄž ## Gama dağılımını verir. +GAMMAINV = GAMATERS ## Gama kümülatif dağılımının tersini verir. +GAMMALN = GAMALN ## Gama fonksiyonunun (?(x)) doÄŸal logaritmasını verir. +GEOMEAN = GEOORT ## Geometrik ortayı verir. +GROWTH = BÃœYÃœME ## Ãœstel bir eÄŸilim boyunca deÄŸerler verir. +HARMEAN = HARORT ## Harmonik ortayı verir. +HYPGEOMDIST = HÄ°PERGEOMDAÄž ## Hipergeometrik dağılımı verir. +INTERCEPT = KESMENOKTASI ## DoÄŸrusal çakıştırma çizgisinin kesiÅŸme noktasını verir. +KURT = BASIKLIK ## Bir veri kümesinin basıklığını verir. +LARGE = BÃœYÃœK ## Bir veri kümesinde k. en büyük deÄŸeri verir. +LINEST = DOT ## DoÄŸrusal bir eÄŸilimin parametrelerini verir. +LOGEST = LOT ## Ãœstel bir eÄŸilimin parametrelerini verir. +LOGINV = LOGTERS ## Bir lognormal dağılımının tersini verir. +LOGNORMDIST = LOGNORMDAÄž ## Birikimli lognormal dağılımını verir. +MAX = MAK ## Bir bağımsız deÄŸiÅŸkenler listesindeki en büyük deÄŸeri verir. +MAXA = MAKA ## Bir bağımsız deÄŸiÅŸkenler listesindeki, sayılar, metin ve mantıksal deÄŸerleri içermek üzere, en büyük deÄŸeri verir. +MEDIAN = ORTANCA ## Belirtilen sayıların orta deÄŸerini verir. +MIN = MÄ°N ## Bir bağımsız deÄŸiÅŸkenler listesindeki en küçük deÄŸeri verir. +MINA = MÄ°NA ## Bir bağımsız deÄŸiÅŸkenler listesindeki, sayılar, metin ve mantıksal deÄŸerleri de içermek üzere, en küçük deÄŸeri verir. +MODE = ENÇOK_OLAN ## Bir veri kümesindeki en sık rastlanan deÄŸeri verir. +NEGBINOMDIST = NEGBÄ°NOMDAÄž ## Negatif binom dağılımını verir. +NORMDIST = NORMDAÄž ## Normal birikimli dağılımı verir. +NORMINV = NORMTERS ## Normal kümülatif dağılımın tersini verir. +NORMSDIST = NORMSDAÄž ## Standart normal birikimli dağılımı verir. +NORMSINV = NORMSTERS ## Standart normal birikimli dağılımın tersini verir. +PEARSON = PEARSON ## Pearson çarpım moment korelasyon katsayısını verir. +PERCENTILE = YÃœZDEBÄ°RLÄ°K ## Bir aralık içerisinde bulunan deÄŸerlerin k. frekans toplamını verir. +PERCENTRANK = YÃœZDERANK ## Bir veri kümesindeki bir deÄŸerin yüzde mertebesini verir. +PERMUT = PERMÃœTASYON ## Verilen sayıda nesne için permütasyon sayısını verir. +POISSON = POISSON ## Poisson dağılımını verir. +PROB = OLASILIK ## Bir aralıktaki deÄŸerlerin iki sınır arasında olması olasılığını verir. +QUARTILE = DÖRTTEBÄ°RLÄ°K ## Bir veri kümesinin dörtte birliÄŸini verir. +RANK = RANK ## Bir sayılar listesinde bir sayının mertebesini verir. +RSQ = RKARE ## Pearson çarpım moment korelasyon katsayısının karesini verir. +SKEW = ÇARPIKLIK ## Bir dağılımın çarpıklığını verir. +SLOPE = EĞİM ## DoÄŸrusal çakışma çizgisinin eÄŸimini verir. +SMALL = KÜÇÜK ## Bir veri kümesinde k. en küçük deÄŸeri verir. +STANDARDIZE = STANDARTLAÅžTIRMA ## NormalleÅŸtirilmiÅŸ bir deÄŸer verir. +STDEV = STDSAPMA ## Bir örneÄŸe dayanarak standart sapmayı tahmin eder. +STDEVA = STDSAPMAA ## Standart sapmayı, sayılar, metin ve mantıksal deÄŸerleri içermek üzere, bir örneÄŸe baÄŸlı olarak tahmin eder. +STDEVP = STDSAPMAS ## Standart sapmayı, tüm popülasyona baÄŸlı olarak hesaplar. +STDEVPA = STDSAPMASA ## Standart sapmayı, sayılar, metin ve mantıksal deÄŸerleri içermek üzere, tüm popülasyona baÄŸlı olarak hesaplar. +STEYX = STHYX ## Regresyondaki her x için tahmini y deÄŸerinin standart hatasını verir. +TDIST = TDAÄž ## T-dağılımını verir. +TINV = TTERS ## T-dağılımının tersini verir. +TREND = EĞİLÄ°M ## DoÄŸrusal bir eÄŸilim boyunca deÄŸerler verir. +TRIMMEAN = KIRPORTALAMA ## Bir veri kümesinin içinin ortalamasını verir. +TTEST = TTEST ## T-test'le iliÅŸkilendirilmiÅŸ olasılığı verir. +VAR = VAR ## Varyansı, bir örneÄŸe baÄŸlı olarak tahmin eder. +VARA = VARA ## Varyansı, sayılar, metin ve mantıksal deÄŸerleri içermek üzere, bir örneÄŸe baÄŸlı olarak tahmin eder. +VARP = VARS ## Varyansı, tüm popülasyona dayanarak hesaplar. +VARPA = VARSA ## Varyansı, sayılar, metin ve mantıksal deÄŸerleri içermek üzere, tüm popülasyona baÄŸlı olarak hesaplar. +WEIBULL = WEIBULL ## Weibull dağılımını hesaplar. +ZTEST = ZTEST ## Z-testinin tek kuyruklu olasılık deÄŸerini hesaplar. + + +## +## Text functions Metin fonksiyonları +## +ASC = ASC ## Bir karakter dizesindeki çift enli (iki bayt) Ä°ngilizce harfleri veya katakanayı yarım enli (tek bayt) karakterlerle deÄŸiÅŸtirir. +BAHTTEXT = BAHTTEXT ## Sayıyı, ß (baht) para birimi biçimini kullanarak metne dönüştürür. +CHAR = DAMGA ## Kod sayısıyla belirtilen karakteri verir. +CLEAN = TEMÄ°Z ## Metindeki bütün yazdırılamaz karakterleri kaldırır. +CODE = KOD ## Bir metin dizesindeki ilk karakter için sayısal bir kod verir. +CONCATENATE = BÄ°RLEÅžTÄ°R ## Pek çok metin öğesini bir metin öğesi olarak birleÅŸtirir. +DOLLAR = LÄ°RA ## Bir sayıyı YTL (yeni Türk lirası) para birimi biçimini kullanarak metne dönüştürür. +EXACT = ÖZDEÅž ## Ä°ki metin deÄŸerinin özdeÅŸ olup olmadığını anlamak için, deÄŸerleri denetler. +FIND = BUL ## Bir metin deÄŸerini, bir baÅŸkasının içinde bulur (büyük küçük harf duyarlıdır). +FINDB = BULB ## Bir metin deÄŸerini, bir baÅŸkasının içinde bulur (büyük küçük harf duyarlıdır). +FIXED = SAYIDÃœZENLE ## Bir sayıyı, sabit sayıda ondalıkla, metin olarak biçimlendirir. +JIS = JIS ## Bir karakter dizesindeki tek enli (tek bayt) Ä°ngilizce harfleri veya katakanayı çift enli (iki bayt) karakterlerle deÄŸiÅŸtirir. +LEFT = SOL ## Bir metin deÄŸerinden en soldaki karakterleri verir. +LEFTB = SOLB ## Bir metin deÄŸerinden en soldaki karakterleri verir. +LEN = UZUNLUK ## Bir metin dizesindeki karakter sayısını verir. +LENB = UZUNLUKB ## Bir metin dizesindeki karakter sayısını verir. +LOWER = KÜÇÜKHARF ## Metni küçük harfe çevirir. +MID = ORTA ## Bir metin dizesinden belirli sayıda karakteri, belirttiÄŸiniz konumdan baÅŸlamak üzere verir. +MIDB = ORTAB ## Bir metin dizesinden belirli sayıda karakteri, belirttiÄŸiniz konumdan baÅŸlamak üzere verir. +PHONETIC = SES ## Metin dizesinden ses (furigana) karakterlerini ayıklar. +PROPER = YAZIM.DÃœZENÄ° ## Bir metin deÄŸerinin her bir sözcüğünün ilk harfini büyük harfe çevirir. +REPLACE = DEĞİŞTÄ°R ## Metnin içindeki karakterleri deÄŸiÅŸtirir. +REPLACEB = DEĞİŞTÄ°RB ## Metnin içindeki karakterleri deÄŸiÅŸtirir. +REPT = YÄ°NELE ## Metni belirtilen sayıda yineler. +RIGHT = SAÄž ## Bir metin deÄŸerinden en saÄŸdaki karakterleri verir. +RIGHTB = SAÄžB ## Bir metin deÄŸerinden en saÄŸdaki karakterleri verir. +SEARCH = BUL ## Bir metin deÄŸerini, bir baÅŸkasının içinde bulur (büyük küçük harf duyarlı deÄŸildir). +SEARCHB = BULB ## Bir metin deÄŸerini, bir baÅŸkasının içinde bulur (büyük küçük harf duyarlı deÄŸildir). +SUBSTITUTE = YERÄ°NEKOY ## Bir metin dizesinde, eski metnin yerine yeni metin koyar. +T = M ## Bağımsız deÄŸerlerini metne dönüştürür. +TEXT = METNEÇEVÄ°R ## Bir sayıyı biçimlendirir ve metne dönüştürür. +TRIM = KIRP ## Metindeki boÅŸlukları kaldırır. +UPPER = BÃœYÃœKHARF ## Metni büyük harfe çevirir. +VALUE = SAYIYAÇEVÄ°R ## Bir metin bağımsız deÄŸiÅŸkenini sayıya dönüştürür. diff --git a/src/admin/application/libs/PHPExcel/changelog.txt b/src/admin/application/libs/PHPExcel/changelog.txt new file mode 100755 index 0000000..19fb810 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/changelog.txt @@ -0,0 +1,1394 @@ +************************************************************************************** +* PHPExcel +* +* Copyright (c) 2006 - 2013 PHPExcel +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +* @version 1.7.9, 2013-06-02 +************************************************************************************** + + +2013-06-02 (v1.7.9): +- Feature: (MBaker) Include charts option for HTML Writer +- Feature: (MBaker) Added composer file +- Feature: (MBaker) Added getStyle() method to Cell object +- Bugfix: (Asker) Work item 18777 - Error in PHPEXCEL/Calculation.php script on line 2976 (stack pop check) +- Bugfix: (MBaker) Work item 18794 - CSV files without a file extension being identified as HTML +- Bugfix: (AndreKR) Work item GH-66 - Wrong check for maximum number of rows in Excel5 Writer +- Bugfix: (MBaker) Work item GH-67 - Cache directory for DiscISAM cache storage cannot be set +- Bugfix: (MBaker) Work item 17976 - Fix to Excel2007 Reader for hyperlinks with an anchor fragment (following a #), otherwise they were treated as sheet references +- Bugfix: (MBaker) Work item 18963 - getSheetNames() fails on numeric (floating point style) names with trailing zeroes +- Bugfix: (MBaker) Work item GH-130 - Single cell print area +- General: (kea) Work item GH-69 - Improved AdvancedValueBinder for currency +- General: (MBaker) Work items 17936 and 17840 - Fix for environments where there is no access to /tmp but to upload_tmp_dir + Provided an option to set the sys_get_temp_dir() call to use the upload_tmp_dir; though by default the standard temp directory will still be used +- General: (amironov ) Work item GH-84 - Search style by identity in PHPExcel_Worksheet::duplicateStyle() +- General: (karak) Work item GH-85 - Fill SheetView IO in Excel5 +- General: (cfhay) Work item 18958 - Memory and Speed improvements in PHPExcel_Reader_Excel5 +- General: (MBaker) Work item GH-78 - Modify listWorksheetNames() and listWorksheetInfo to use XMLReader with streamed XML rather than SimpleXML +- General: (dbonsch) Restructuring of PHPExcel Exceptions +- General: (MBaker) Work items 16926 and 15145 - Refactor Calculation Engine from singleton to a Multiton + Ensures that calculation cache is maintained independently for different workbooks +- General: (MBaker) Modify cell's getCalculatedValue() method to return the content of RichText objects rather than the RichText object itself +- Bugfix: (techhead) Work item GH-70 - Fixed formula/formatting bug when removing rows +- Bugfix: (alexgann) Work item GH-63 - Fix to cellExists for non-existent namedRanges +- Bugfix: (MBaker) Work item 18844 - cache_in_memory_gzip "eats" last worksheet line, cache_in_memory doesn't +- Feature: (Progi1984) Work item GH-22 - Sheet View in Excel5 Writer +- Bugfix: (amironov) Work item GH-82 - PHPExcel_Worksheet::getCellCollection() may not return last cached cell +- Bugfix: (teso) Work item 18551 - Rich Text containing UTF-8 characters creating unreadable content with Excel5 Writer +- Bugfix: (MBaker) Work item GH-104 - echo statements in HTML.php +- Feature: (Progi1984) Work item GH-8/CP11704 : Conditional formatting in Excel 5 Writer +- Bugfix: (MBaker) Work item GH-113 - canRead() Error for GoogleDocs ODS files: in ODS files from Google Docs there is no mimetype file +- Bugfix: (MBaker) Work item GH-80 - "Sheet index is out of bounds." Exception +- Bugfix: (ccorliss) Work item GH-105 - Fixed number format fatal error +- Bugfix: (MBaker) - Add DROP TABLE in destructor for SQLite and SQLite3 cache controllers +- Bugfix: (alexgann) Work item GH-154 - Fix merged-cell borders on HTML/PDF output +- Bugfix: (Shanto) Work item GH-161 - Fix: Hyperlinks break when removing rows +- Bugfix: (neclimdul) Work item GH-166 - Fix Extra Table Row From Images and Charts + + +-------------------------------------------------------------------------------- +BREAKING CHANGE! As part of the planned changes for handling array formulae in +workbooks, there are some changes that will affect the PHPExcel_Cell object +methods. + +The following methods are now deprecated, and will be removed in or after version 1.8.0: + getCalculatedValue() The getValue() method will return calculated + values for cells containing formulae instead. + setCalculatedValue() The cell value will always contain the result of a + any formula calculation. + setFormulaAttributes() Will now be determined by the arguments to the + setFormula() method. + getFormulaAttributes() This will be replaced by the getArrayFormulaRange() + method. + +The following methods will be added in version 1.8.0 + getFormula() Use to retrieve a cell formula, will return the cell + value if the cell doesn't contain a formula, or + is not part of an array formula range. + setFormula() Use to set a cell formula. It will still be possible + to set formulae using the setValue() and + setValueExplicit() methods. + calculate() Use to execute a formula calculation to update the + cell value. + isFormula() Use to determine if a cell contains a formula, or is + part of an array formula range or not. + isArrayFormula() Use to determine if a cell contains an array formula, + or is part of an array formula range or not. + getArrayFormulaRange() Use to retrieve an array formula range. + +The following methods will be changed in version 1.8.0 + setValue() The logic behind this will be modified to store + formula values in the new cell property structure, + but it will still perform the same function. + setValueExplicit() The logic behind this will be modified to store + formula values in the new cell property structure, + but it will still perform the same function. + getValue() Will no longer return a formula if the cell contains + a formula, but will return the calculated value + instead. For cells that don't contain a formula, + it will still return the stored value. + getDataType() Will return the datatype of the calculated value for + cells that contain formulae. + setDataType() Error handling will be added to prevent setting a + cell datatype to an inappropriate value. +-------------------------------------------------------------------------------- + + +2012-10-12 (v1.7.8): +- Special: (kkamkou) Phar builder script to add phar file as a distribution option +- Feature: (MBaker) Refactor PDF Writer to allow use with a choice of PDF Rendering library + rather than restricting to tcPDF + Current options are tcPDF, mPDF, DomPDF + tcPDF Library has now been removed from the deployment bundle +- Feature: (MBaker) Initial version of HTML Reader +- Feature: (Progi1984) & (blazzy) Work items 9605 - Implement support for AutoFilter in PHPExcel_Writer_Excel5 +- Feature: (MBaker) Modified ERF and ERFC Engineering functions to accept Excel 2010's modified acceptance of negative arguments +- Feature: (k1LoW) Support SheetView `view` attribute (Excel2007) +- Feature: (MBaker) Excel compatibility option added for writing CSV files + While Excel 2010 can read CSV files with a simple UTF-8 BOM, Excel2007 and earlier require UTF-16LE encoded tab-separated files. + The new setExcelCompatibility(TRUE) option for the CSV Writer will generate files with this formatting for easy import into Excel2007 and below. +- Feature: (MBaker) Language implementations for Turkish (tr) +- Feature: (MBaker) Added fraction tests to advanced value binder +- Feature: (MBaker) Allow call to font setUnderline() for underline format to specify a simple boolean for UNDERLINE_NONE or UNDERLINE_SINGLE +- General: (alexgann) Add Currency detection to the Advanced Value Binder +- General: (MBaker) Work item 18404 - setCellValueExplicitByColumnAndRow() do not return PHPExcel_Worksheet +- General: (MBaker) Work item 18324 - Reader factory doesn't read anymore XLTX and XLT files +- General: (MBaker) Magic __toString() method added to Cell object to return raw data value as a string +- General: (alexgann) Add cell indent to html rendering +- General: (Raghav1981) ZeroHeight for rows in sheet format +- Bugfix: (cyberconte) Patch 12318 - OOCalc cells containing <text:span> inside the <text:p> tag +- Bugfix: (schir1964) Fix to listWorksheetInfo() method for OOCalc Reader +- Bugfix: (MBaker) Support for "e" (epoch) date format mask + Rendered as a 4-digit CE year in non-Excel outputs +- Bugfix: (MBaker) Work items 15799 and 18278 - Background color cell is always black when editing cell +- Bugfix: (MBaker) Work items 15905 and 18183 - Allow "no impact" to formats on Conditional Formatting +- Bugfix: (wackonline) OOCalc Reader fix for NULL cells +- Bugfix: (seltzlab) Fix to excel2007 Chart Writer when a $plotSeriesValues is empty +- Bugfix: (MBaker) Various fixes to Chart handling +- Bugfix: (MBaker) Work item 18370 - Error loading xlsx file with column breaks +- Bugfix: (MBaker) OOCalc Reader now handles percentage and currency data types +- Bugfix: (MBaker) Work Item 18415 - mb_stripos empty delimiter +- Bugfix: (takaakik) Work Item 15455 - getNestingLevel() Error on Excel5 Read +- Bugfix: (MBaker) Fix to Excel5 Reader when cell annotations are defined before their referenced text objects +- Bugfix: (MBaker) OOCalc Reader modified to process number-rows-repeated +- Bugfix: (MBaker) Work item 18377 - Chart Title compatibility on Excel 2007 +- Bugfix: (MBaker) Work item 18146 - Chart Refresh returning cell reference rather than values +- Bugfix: (MBaker) Work item 18145 - Autoshape being identified in twoCellAnchor when includeCharts is TRUE triggering load error +- Bugfix: (MBaker) Work item 18325 - v-type texts for series labels now recognised and parsed correctly +- Bugfix: (wolf5x) Work item 18492 - load file failed if the file has no extensionType +- Bugfix: (dverspui) Pattern fill colours in Excel2007 Style Writer +- Bugfix: (MBaker) Excel2007 Writer order of font style elements to conform with Excel2003 using compatibility pack +- Bugfix: (MBaker) Work item 18425 - Problems with $_activeSheetIndex when decreased below 0. +- Bugfix: (MBaker) Work item 18597 - PHPExcel_CachedObjectStorage_SQLite3::cacheMethodIsAvailable() uses class_exists - autoloader throws error +- Bugfix: (MBaker) Work item 18598 - Cannot access private property PHPExcel_CachedObjectStorageFactory::$_cacheStorageMethod +- Bugfix: (MBaker) Work item 18397 - Data titles for charts + PHPExcel_Chart_Layout now has methods for getting/setting switches for displaying/hiding chart data labels +- Bugfix: (MBaker) Discard single cell merge ranges when reading (stupid that Excel allows them in the first place) +- Bugfix: (MBaker) Discard hidden autoFilter named ranges + + +2012-05-19 (v1.7.7): +- Bugfix: (Progi1984) Work item 8916 - Support for Rich-Text in PHPExcel_Writer_Excel5 +- Bugfix: (cyberconte) Work item 17471 - OOCalc cells contain same data bug? +- Feature: (schir1964) listWorksheetInfo() method added to Readers... courtesy of Christopher Mullins +- Feature: (MBaker) Options for cell caching using Igbinary and SQLite/SQlite3. +- Feature: (MBaker) Additional row iterator options: allow a start row to be defined in the constructor; seek(), and prev() methods added. +- Feature: (Progi1984) Work item 9759 - Implement document properties in Excel5 writer +- Feature: (MBaker) Work item 16 - Implement chart functionality (EXPERIMENTAL) + Initial definition of chart objects. + Reading Chart definitions through the Excel2007 Reader + Facility to render charts to images using the 3rd-party jpgraph library + Writing Charts using the Excel2007 Writer +- General: (MBaker) Fix to build to ensure that Examples are included with the documentation +- General: (MBaker) Reduce cell caching overhead using dirty flag to ensure that cells are only rewritten to the cache if they have actually been changed +- General: (MBaker) Improved memory usage in CSV Writer +- General: (MBaker) Improved speed and memory usage in Excel5 Writer +- General: (MBaker) Experimental - + Added getHighestDataColumn(), getHighestDataRow(), getHighestRowAndColumn() and calculateWorksheetDataDimension() methods for the worksheet that return the highest row and column that have cell records +- General: (MBaker) Change iterators to implement Iterator rather than extend CachingIterator, as a fix for PHP 5.4. changes in SPL +- Bugfix: (MBaker) Work item 15459 - Invalid cell coordinate in Autofilter for Excel2007 Writer +- Bugfix: (MBaker) Work item 15518 - PCLZip library issue +- Bugfix: (MBaker) Work item 15537 - Excel2007 Reader canRead function bug +- Bugfix: (MBaker) Support for Excel functions whose return can be used as either a value or as a cell reference depending on its context within a formula +- Bugfix: (gilles06) Work item 15707 - ini_set() call in Calculation class destructor +- Bugfix: (MBaker) Work item 15786 - RangeToArray strange array keys +- Bugfix: (MBaker) Work item 15762 - INDIRECT() function doesn't work with named ranges +- Bugfix: (MBaker) Locale-specific fix to text functions when passing a boolean argument instead of a string +- Bugfix: (MBaker) Work item 16246 - reader/CSV fails on this file + auto_detect_line_endings now set in CSV reader +- Bugfix: (MBaker) Work item 16212 - $arguments improperly used in CachedObjectStorage/PHPTemp.php +- Bugfix: (MBaker) Work item 16643 - Bug In Cache System (cell reference when throwing caching errors) +- Bugfix: (MBaker) Work item 16895 - PHP Invalid index notice on writing excel file when active sheet has been deleted +- Bugfix: (MBaker) Work item 16956 - External links in Excel2010 files cause Fatal error +- Bugfix: (MBaker) Work item 16960 - Previous calculation engine error conditions trigger cyclic reference errors +- Bugfix: (mkopinsky) Work item 16266 - PHPExcel_Style::applyFromArray() returns null rather than style object in advanced mode +- Bugfix: (fauvel) Work item 16958 - Cell::getFormattedValue returns RichText object instead of string +- Bugfix: (MBaker) Work item 17166 - Indexed colors do not refer to Excel's indexed colors? +- Bugfix: (MBaker) Work item 17199 - Indexed colors should be consistent with Excel and start from 1 (current index starts at 0) +- Bugfix: (MBaker) Work item 17262 - Named Range definition in .xls when sheet reeference is quote wrapped +- Bugfix: (MBaker) Work item 17403 - duplicateStyle() method doesn't duplicate conditional formats + Added an equivalent duplicateConditionalStyle() method for duplicating conditional styles +- Bugfix: (bnr) Work item 17501 - =sumproduct(A,B) <> =sumproduct(B,A) in xlsx +- Bugfix: (Progi1984) Work item 8916 - Support for Rich-Text in PHPExcel_Writer_Excel5 +- General: (MBaker) Work item 15405 - Two easy to fix Issues concerning PHPExcel_Token_Stack (l10n/UC) +- General: (MBaker) Work item 15461 - Locale file paths not fit for windows +- General: (MBaker) Work item 16643 - Add file directory as a cache option for cache_to_discISAM +- General: (MBaker) Work item 16923 - Datatype.php & constant TYPE_NULL +- General: (MBaker) Ensure use of system temp directory for all temporary work files, unless explicitly specified +- General: (char101) Work item 16359 - [Patch] faster stringFromColumnIndex() +- General: (whit1206) Work item 16028 - Fix for projects that still use old autoloaders +- General: (atz) Work item 17024 - Unknown codepage: 10007 + Additional Mac codepages + + +2011-02-27 (v1.7.6): +- Feature: (MBaker) Provide option to use PCLZip as an alternative to ZipArchive. + This allows the writing of Excel2007 files, even without ZipArchive enabled (it does require zlib), or when php_zip is one of the buggy PHP 5.2.6 or 5.2.8 versions + It can be enabled using PHPExcel_Settings::setZipClass(PHPExcel_Settings::PCLZIP); + Note that it is not yet implemented as an alternative to ZipArchive for those Readers that are extracting from zips +- Feature: (MBaker) Work item 14979 - Added listWorksheetNames() method to Readers that support multiple worksheets in a workbook, allowing a user to extract a list of all the worksheet names from a file without parsing/loading the whole file. +- Feature: (MBaker) Speed boost and memory reduction in the Worksheet toArray() method. +- Feature: (MBaker) Added new rangeToArray() and namedRangeToArray() methods to the PHPExcel_Worksheet object. + Functionally, these are identical to the toArray() method, except that they take an additional first parameter of a Range (e.g. 'B2:C3') or a Named Range name. + Modified the toArray() method so that it actually uses rangeToArray(). +- Feature: (MBaker) Added support for cell comments in the OOCalc, Gnumeric and Excel2003XML Readers, and in the Excel5 Reader +- Feature: (MBaker) Improved toFormattedString() handling for Currency and Accounting formats to render currency symbols +- Feature: (MBaker) Work Item 2346 - Implement more Excel calculation functions + Implemented the DAVERAGE(), DCOUNT(), DCOUNTA(), DGET(), DMAX(), DMIN(), DPRODUCT(), DSTDEV(), DSTDEVP(), DSUM(), DVAR() and DVARP() Database functions +- Bugfix: (MBaker) Work item 14888 - Simple =IF() formula disappears +- Bugfix: (MBaker) Work item 14898 - PHP Warning: preg_match(): Compilation failed: PCRE does not support \\L, \\l, \\N, \\P, \\p, \\U, \\u, or \\X +- Bugfix: (MBaker) Work item 14901 - VLOOKUP choking on parameters in PHPExcel.1.7.5/PHPExcel_Writer_Excel2007 +- Bugfix: (MBaker) Work item 14973 - PHPExcel_Cell::isInRange() incorrect results - offset by one column +- Bugfix: (MBaker) Treat CodePage of 0 as CP1251 (for .xls files written by applications that don't set the CodePage correctly, such as Apple Numbers) +- Bugfix: (MB) Work item 11583 - Need method for removing autoFilter +- Bugfix: (MBaker) Work item 15029 - coordinateFromString throws exception for rows greater than 99,999 +- Bugfix: (MBaker) Work item 14999 - PHPExcel Excel2007 Reader colour problems with solidfill +- Bugfix: (MBaker) Work item 13215 - Formatting get lost and edit a template XLSX file +- Bugfix: (MBaker) Work item 14029 - Excel 2007 Reader /writer lost fontcolor +- Bugfix: (MBaker) Work item 13374 - file that makes cells go black +- Bugfix: (MBaker) Minor patchfix for Excel2003XML Reader when XML is defined with a charset attribute +- Bugfix: (MBaker) Work item 15089 - PHPExcel_Worksheet->toArray() index problem +- Bugfix: (MBaker) Work item 15094 - Merge cells 'un-merge' when using an existing spreadsheet +- Bugfix: (MBaker) Work item 15129 - Worksheet fromArray() only working with 2-D arrays +- Bugfix: (xkeshav) Work item 15172 - rangeToarray function modified for non-existent cells +- Bugfix: (MBaker) Work item 14980 - Images not getting copyied with the ->clone function +- Bugfix: (MBaker) Work item 11576 - AdvancedValueBinder.php: String sometimes becomes a date when it shouldn't +- Bugfix: (MBaker) Fix Excel5 Writer so that it only writes column dimensions for columns that are actually used rather than the full range (A to IV) +- Bugfix: (MBaker) Work item 15198 - FreezePane causing damaged or modified error + The freezePaneByColumnAndRow() method row argument should default to 1 rather than 0. + Default row argument for all __ByColumnAndRow() methods should be 1 +- Bugfix: (MBaker) Work item 15121 - Column reference rather than cell reference in Print Area definition + Fix Excel2007 Writer to handle print areas that are defined as row or column ranges rather than just as cell ranges +- Bugfix: (MBaker) Reduced false positives from isDateTimeFormatCode() method by suppressing testing within quoted strings +- Bugfix: (MBaker) Work item 15312 - Caching and tmp partition exhaustion +- Bugfix: (MBaker) Work item 15308 - Writing to Variable No Longer Works. $_tmp_dir Missing in PHPExcel\PHPExcel\Shared\OLE\PPS\Root.php +- Bugfix: (MBaker) Work item 15379 - Named ranges with dot don't get parsed properly +- Bugfix: (MBaker) Work item 15096 - insertNewRowBefore fails to consistently update references +- Bugfix: (MBaker) "i" is not a valid character for Excel date format masks (in isDateTimeFormatCode() method) +- Bugfix: (MKunert) Work item 15421 - PHPExcel_ReferenceHelper::insertNewBefore() is missing an 'Update worksheet: comments' section +- Bugfix: (MBaker) Work item 15409 - Full column/row references in named ranges not supported by updateCellReference() +- General: (MBaker) Improved performance (speed), for building the Shared Strings table in the Excel2007 Writer. +- General: (MBaker) Improved performance (speed), for PHP to Excel date conversions +- General: (MBaker) Enhanced SheetViews element structures in the Excel2007 Writer for frozen panes. +- General: (MBaker) Removed Serialized Reader/Writer as these no longer work. + + +2010-12-10 (v1.7.5): +- Feature: (MBaker) Work item 8769 - Implement Gnumeric File Format + Initial work on Gnumeric Reader (Worksheet Data, Document Properties and basic Formatting) +- Feature: (MBaker) (incorporating part of Workitem 9759) - Support for Extended Workbook Properties in Excel2007, Excel5 and OOCalc Readers; support for User-defined Workbook Properties in Excel2007 and OOCalc Readers +- Feature: (MBaker) Support for Extended and User-defined Workbook Properties in Excel2007 Writer +- Feature: (MBaker) Provided a setGenerateSheetNavigationBlock(false); option to suppress generation of the sheet navigation block when writing multiple worksheets to HTML +- Feature: (MBaker) Advanced Value Binder now recognises TRUE/FALSE strings (locale-specific) and converts to boolean +- Feature: (MBaker) Work item 14301 - PHPExcel_Worksheet->toArray() is returning truncated values +- Feature: (MBaker) Configure PDF Writer margins based on Excel Worksheet Margin Settings value +- Feature: (MBaker) Added Contiguous flag for the CSV Reader, when working with Read Filters +- Feature: (MBaker) Added getFormattedValue() method for cell object +- Feature: (MBaker) Added strictNullComparison argument to the worksheet fromArray() method +- Feature: (MBaker) Fix to toFormattedString() method in PHPExcel_Style_NumberFormat to handle fractions with a # code for the integer part +- Bugfix: (MB) Work item 14143 - NA() doesn't propagate in matrix calc - quick fix in JAMA/Matrix.php +- Bugfix: (Progi1984) Work item 7895 - Excel5 : Formula : String constant containing double quotation mark +- Bugfix: (Progi1984) Work item 7895 - Excel5 : Formula : Percent +- Bugfix: (Progi1984) Work item 7895 - Excel5 : Formula : Error constant +- Bugfix: (Progi1984) Work item 7895 - Excel5 : Formula : Concatenation operator +- Bugfix: (MBaker) Work item 14146 - Worksheet clone broken for CachedObjectStorage_Memory +- Bugfix: (MBaker) Work item 12998 - PHPExcel_Reader_Excel2007 fails when gradient fill without type is present in a file +- Bugfix: (MBaker) Work item 14176 - @ format for numeric strings in XLSX to CSV conversion +- Bugfix: (MBaker) Work item 14223 - Advanced Value Binder Not Working? +- Bugfix: (MBaker) Work item 14226 - unassigned object variable in PHPExcel->removeCellXfByIndex +- Bugfix: (MBaker) Work item 14236 - problem with getting cell values from another worksheet... (if cell doesn't exist) +- Bugfix: (MBaker) Work items 14260 & 14233 - Setting cell values to one char strings & Trouble reading one character string (thanks gorfou) +- Bugfix: (MBaker) Work item 14256 - Worksheet title exception when duplicate worksheet is being renamed but exceeds the 31 character limit +- Bugfix: (MBaker) Work item 14086 - Named range with sheet name that contains the $ throws exception when getting the cell +- Bugfix: (MBaker) Added autoloader to DefaultValueBinder and AdvancedValueBinder +- Bugfix: (MBaker) Modified PHPExcel_Shared_Date::isDateTimeFormatCode() to return false if format code begins with "_" or with "0 " to prevent false positives + These leading characters are most commonly associated with number, currency or accounting (or occasionally fraction) formats +- Bugfix: (MBaker) Work item 14374 - BUG : Excel5 and setReadFilter ? +- Bugfix: (MBaker) Work item 14425 - Wrong exception message while deleting column +- Bugfix: (MBaker) Work item 14679 - Formula evaluation fails with Japanese sheet refs +- Bugfix: (MBaker) Work item 13559 - PHPExcel_Writer_PDF does not handle cell borders correctly +- Bugfix: (MBaker) Work item 14831 - Style : applyFromArray() for 'allborders' not working +- Bugfix: (MBaker) Work item 14837 - Using $this when not in object context in Excel5 Reader +- General: (MBaker) Applied patch 6609 - Removes a unnecessary loop through each cell when applying conditional formatting to a range. +- General: (MBaker) Applied patch 7169 - Removed spurious PHP end tags (?>) +- General: (MBaker) Improved performance (speed) and reduced memory overheads, particularly for the Writers, but across the whole library. + + +2010-08-26 (v1.7.4): +- Bugfix: (Progi1984) Work item 7895 - Excel5 : Formula : Power +- Bugfix: (Progi1984) Work item 7895 - Excel5 : Formula : Unary plus +- Bugfix: (Progi1984) Excel5 : Just write the Escher stream if necessary in Worksheet +- Bugfix: (MBaker) Work item 13433 - Syntax errors in memcache.php 1.7.3c +- Bugfix: (MBaker) Work item 13450 - Standard Deviation functions returning DIV/0 Error when Standard Deviation is zero +- Feature: (MBaker) Support for print area with several ranges in the Excel2007 reader, and improved features for editing print area with several ranges +- Feature: (MBaker) Work item 13769 - Improved Cell Exception Reporting +- Feature: (MBaker) Support for row or column ranges in the calculation engine, e.g. =SUM(C:C) or =SUM(1:2) + Also support in the calculation engine for absolute row or column ranges e.g. =SUM($C:$E) or =SUM($3:5) +- Bugfix: (ET) Work item 13455 - Picture problem with Excel 2003 +- Bugfix: (MBaker) Work item 13484 - Wrong variable used in addExternalSheet in PHPExcel.php +- Bugfix: (MBaker) Work item 13515 - "Invalid cell coordinate" error when formula access data from an other sheet +- Bugfix: (MBaker) (related to Work item 13515) Calculation engine confusing cell range worksheet when referencing cells in a different worksheet to the formula +- Bugfix: (MBaker) Work item 13752 - Wrong var naming in Worksheet->garbageCollect() +- Bugfix: (MBaker) Work item 13764 - PHPExcel_Style_*::__clone() methods cause cloning loops? +- Bugfix: (MBaker) Work item 11488 - Recent builds causing problems loading xlsx files? (ZipArchive issue?) +- Bugfix: (MBaker) Work item 13856 - cache_to_apc causes fatal error when processing large data sets +- Bugfix: (MBaker) Work item 13880 - OOCalc reader misses first line if it's a 'table-header-row' +- Bugfix: (MBaker) Work item 14011 - using cache with copy or clone bug? + Fixed $worksheet->copy() or clone $worksheet when using cache_in_memory, cache_in_memory_gzip, cache_in_memory_serialized, cache_to_discISAM, cache_to_phpTemp, cache_to_apc and cache_to_memcache; + Fixed but untested when using cache_to_wincache. +- Bugfix: (MBaker) Fixed problems with reading Excel2007 Properties +- General: (MB) Applied patch 6324 - PHP Strict Standards: Non-static method PHPExcel_Shared_String::utf16_decode() should not be called statically +- General: (MBaker) Applied patch 6360 - Array functions were ignored when loading an existing file containing them, and as a result, they would lose their 'cse' status. +- General: (MBaker) Minor memory tweaks to Excel2007 Writer +- General: (MBaker) Modified ReferenceHelper updateFormulaReferences() method to handle updates to row and column cell ranges (including absolute references e.g. =SUM(A:$E) or =SUM($5:5), and range/cell references that reference a worksheet by name), and to provide both performance and memory improvements. +- General: (MBaker) Modified Excel2007 Reader so that ReferenceHelper class is instantiated only once rather than for every shared formula in a workbook. +- General: (MBaker) Correct handling for additional (synonym) formula tokens in Excel5 Reader +- General: (MBaker) Additional reading of some Excel2007 Extended Properties (Company, Manager) + + +2010-06-01 (v1.7.3c): +- Bugfix: (MB) Work item 13012 - Fatal error: Class 'ZipArchive' not found... ...Reader/Excel2007.php on line 217 +- Bugfix: (MBaker) Work item 13398 - PHPExcel_Writer_Excel2007 error after 1.7.3b + + +2010-05-31 (v1.7.3b): +- Bugfix: (MBaker) Work item 12903 - Infinite loop when reading +- Bugfix: (MB) Work item 13381 - Wrong method chaining on PHPExcel_Worksheet class + + +2010-05-17 (v1.7.3): +- General: (ET) Applied patch 4990 (modified) +- General: (MB) Applied patch 5568 (modified) +- General: (MB) Applied patch 5943 +- General: (MB) Work item 13042 - Upgrade build script to use Phing +- General: (ET) Work item 11586 - Replacing var with public/private +- General: (MBaker) Applied Anthony's Sterling's Class Autoloader to reduce memory overhead by "Lazy Loading" of classes +- General: (MBaker) Modification to functions that accept a date parameter to support string values containing ordinals as per Excel (English language only) +- General: (MBaker) Modify PHPExcel_Style_NumberFormat::toFormattedString() to handle dates that fall outside of PHP's 32-bit date range +- General: (MBaker) Applied patch 5207 +- General: (ET) Work item 11970 - PHPExcel developer documentation: Set page margins +- Feature: (ET) Work item 11038 - Special characters and accents in SYLK reader +- Feature: (MBaker) Work Item 2346 - Implement more Excel calculation functions + - Implemented the COUPDAYS(), COUPDAYBS(), COUPDAYSNC(), COUPNCD(), COUPPCD() and PRICE() Financial functions + - Implemented the N() and TYPE() Information functions + - Implemented the HYPERLINK() Lookup and Reference function +- Feature: (ET) Work item 11526 - Horizontal page break support in PHPExcel_Writer_PDF +- Feature: (ET) Work item 11529 - Introduce method setActiveSheetIndexByName() +- Feature: (ET) Work item 11550 - AdvancedValueBinder.php: Automatically wrap text when there is new line in string (ALT+"Enter") +- Feature: (ET) Work item 10300 - Data validation support in PHPExcel_Reader_Excel5 and PHPExcel_Writer_Excel5 +- Feature: (MB) Work item 11616 - Improve autosize calculation +- Feature: (MBaker) Methods to translate locale-specific function names in formulae + - Language implementations for Czech (cs), Danish (da), German (de), English (uk), Spanish (es), Finnish (fi), French (fr), Hungarian (hu), Italian (it), Dutch (nl), Norwegian (no), Polish (pl), Portuguese (pt), Brazilian Portuguese (pt_br), Russian (ru) and Swedish (sv) +- Feature: (ET) Work item 9759 - Implement document properties in Excel5 reader/writer + - Fixed so far for PHPExcel_Reader_Excel5 +- Feature: (ET) Work item 11849 - Show/hide row and column headers in worksheet +- Feature: (ET) Work item 11919 - Can't set font on writing PDF (by key) +- Feature: (ET) Work item 12096 - Thousands scale (1000^n) support in PHPExcel_Style_NumberFormat::toFormattedString +- Feature: (ET) Work item 6911 - Implement repeating rows in PDF and HTML writer +- Feature: (ET) Work item 12289 - Sheet tabs in PHPExcel_Writer_HTML +- Feature: (MB) Work item 13041 - Add Wincache CachedObjectProvider +- Feature: (MBaker) Configure PDF Writer paper size based on Excel Page Settings value, and provided methods to override paper size and page orientation with the writer + - Note PHPExcel defaults to Letter size, while the previous PDF writer enforced A4 size, so PDF writer will now default to Letter +- Feature: (MBaker) Initial implementation of cell caching: allowing larger workbooks to be managed, but at a cost in speed +- Feature: (MBaker) Added an identify() method to the IO Factory that identifies the reader which will be used to load a particular file without actually loading it. +- Bugfix: (MBaker) Work item 10979 - Warning messages with INDEX function having 2 arguments +- Bugfix: (ET) Work item 11473 - setValue('=') should result in string instead of formula +- Bugfix: (MBaker) Work item 11471 - method _raiseFormulaError should no be private +- Bugfix: (ET) Work item 11485 - Fatal error: Call to undefined function mb_substr() in ...Classes\PHPExcel\Reader\Excel5.php on line 2903 +- Bugfix: (ET) Work item 11487 - getBold(), getItallic(), getStrikeThrough() not always working with PHPExcel_Reader_Excel2007 +- Bugfix: (ET) Work item 11492 - AdvancedValueBinder.php not working correctly for $cell->setValue('hh:mm:ss') +- Bugfix: (MBaker) Fixed leap year handling for the YEARFRAC() Date/Time function when basis ia 1 (Actual/actual) +- Bugfix: (MBaker) Work item 11490 - Warning messages + - Calculation Engine code modified to enforce strict standards for pass by reference +- Bugfix: (ET) Work item 11483 - PHPExcel_Cell_AdvancedValueBinder doesnt work for dates in far future +- Bugfix: (ET) Work item 11528 - MSODRAWING bug with long CONTINUE record in PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 11571 - PHPExcel_Reader_Excel2007 reads print titles as named range when there is more than one sheet +- Bugfix: (ET) Work item 11561 - missing @return in phpdocblock in reader classes +- Bugfix: (ET) Work item 11576 - AdvancedValueBinder.php: String sometimes becomes a date when it shouldn't +- Bugfix: (ET) Work item 11588 - Small numbers escape treatment in PHPExcel_Style_NumberFormat::toFormattedString() +- Bugfix: (ET) Work item 11590 - Blank styled cells are not blank in output by HTML writer due to &nbsp; +- Bugfix: (MBaker) Work item 11587 - Calculation engine bug: Existing, blank cell + number gives #NUM +- Bugfix: (ET) Work item 11608 - AutoSize only measures length of first line in cell with multiple lines (ALT+Enter) +- Bugfix: (ET) Work item 11608 - Fatal error running Tests/12serializedfileformat.php (PHPExcel 1.7.2) +- Bugfix: (MBaker) Fixed various errors in the WORKDAY() and NETWORKDAYS() Date/Time functions (particularly related to holidays) +- Bugfix: (ET) Work item 11660 - Uncaught exception 'Exception' with message 'Valid scale is between 10 and 400.' in Classes/PHPExcel/Worksheet/SheetView.php:115 +- Bugfix: (ET) Work item 11551 - "Unrecognized token 39 in formula" with PHPExcel_Reader_Excel5 (occuring with add-in functions) +- Bugfix: (ET) Work item 11668 - Excel2007 reader not reading PHPExcel_Style_Conditional::CONDITION_EXPRESSION +- Bugfix: (MBaker) Fix to the BESSELI(), BESSELJ(), BESSELK(), BESSELY() and COMPLEX() Engineering functions to use correct default values for parameters +- Bugfix: (MBaker) Work item 11525 - DATEVALUE function not working for pure time values + allow DATEVALUE() function to handle partial dates (e.g. "1-Jun" or "12/2010") +- Bugfix: (MBaker) Fix for empty quoted strings in formulae +- Bugfix: (MBaker) Trap for division by zero in Bessel functions +- Bugfix: (MBaker) Fix to OOCalc Reader to convert semi-colon (;) argument separator in formulae to a comma (,) +- Bugfix: (ET) Work item 11693 - PHPExcel_Writer_Excel5_Parser cannot parse formula like =SUM(C$5:C5) +- Bugfix: (MBaker) Fix to OOCalc Reader to handle dates that fall outside 32-bit PHP's date range +- Bugfix: (ET) Work item 11692 - File->sys_get_temp_dir() can fail in safe mode +- Bugfix: (ET) Work item 11727 - Sheet references in Excel5 writer do not work when referenced sheet title contains non-Latin symbols +- Bugfix: (ET) Work item 11743 - Bug in HTML writer can result in missing rows in output +- Bugfix: (ET) Work item 11674 - setShowGridLines(true) not working with PHPExcel_Writer_PDF +- Bugfix: (ET) Work item 11836 - PHPExcel_Worksheet_RowIterator initial position incorrect +- Bugfix: (ET) Work item 11835 - PHPExcel_Worksheet_HeaderFooterDrawing Strict Exception thrown (by jshaw86) +- Bugfix: (ET) Work item 11850 - Parts of worksheet lost when there are embedded charts (Excel5 reader) +- Bugfix: (MBaker) VLOOKUP() function error when lookup value is passed as a cell reference rather than an absolute value +- Bugfix: (ET) Work item 12041 - First segment of Rich-Text not read correctly by PHPExcel_Reader_Excel2007 +- Bugfix: (MBaker) Work item 12048 - Fatal Error with getCell('name') when name matches the pattern for a cell reference +- Bugfix: (ET) Work item 12039 - excel5 writer appears to be swapping image locations +- Bugfix: (ET) Work item 11954 - Undefined index: host in ZipStreamWrapper.php, line 94 and line 101 +- Bugfix: (ET) Work item 11672 - BIFF8 File Format problem (too short COLINFO record) +- Bugfix: (ET) Work item 12121 - Column width sometimes changed after read/write with Excel2007 reader/writer +- Bugfix: (ET) Work item 11964 - Worksheet.php throws a fatal error when styling is turned off via setReadDataOnly on the reader +- Bugfix: (MBaker) Work item 11851 - Checking for Circular References in Formulae + - Calculation Engine code now traps for cyclic references, raising an error or throwing an exception, or allows 1 or more iterations through cyclic references, based on a configuration setting +- Bugfix: (ET) Work item 12244 - PNG transparency using Excel2007 writer +- Bugfix: (ET) Work item 12221 - Custom readfilter error when cell formulas reference excluded cells (Excel5 reader) +- Bugfix: (ET) Work item 12288 - Protection problem in XLS +- Bugfix: (ET) Work item 12300 - getColumnDimension()->setAutoSize() incorrect on cells with Number Formatting +- Bugfix: (ET) Work item 12378 - Notices reading Excel file with Add-in funcitons (PHPExcel_Reader_Excel5) +- Bugfix: (ET) Work item 12380 - Excel5 reader not reading formulas with deleted sheet references +- Bugfix: (ET) Work item 12404 - Named range (defined name) scope problems for in PHPExcel +- Bugfix: (ET) Work item 12423 - PHP Parse error: syntax error, unexpected T_PUBLIC in PHPExcel/Calculation.php on line 3482 +- Bugfix: (ET) Work item 12505 - Named ranges don't appear in name box using Excel5 writer +- Bugfix: (ET) Work item 12509 - Many merged cells + autoSize column -> slows down the writer +- Bugfix: (ET) Work item 12539 - Incorrect fallback order comment in Shared/Strings.php ConvertEncoding() +- Bugfix: (ET) Work item 12538 - IBM AIX iconv() will not work, should revert to mbstring etc. instead +- Bugfix: (ET) Work item 12568 - Excel5 writer and mbstring functions overload +- Bugfix: (MBaker) Work item 12672 - OFFSET needs to flattenSingleValue the $rows and $columns args +- Bugfix: (MBaker) Work item 12546 - Formula with DMAX(): Notice: Undefined offset: 2 in ...\PHPExcel\Calculation.php on line 2365 + - Note that the Database functions have not yet been implemented +- Bugfix: (MBaker) Work item 12839 - Call to a member function getParent() on a non-object in Classes\\PHPExcel\\Calculation.php Title is required +- Bugfix: (MBaker) Work item 12935 - Cyclic Reference in Formula +- Bugfix: (MBaker) Work item 13025 - Memory error...data validation? + + +2010/01/11 (v1.7.2): +- General: (ET) Applied patch 4362 +- General: (ET) Applied patch 4363 (modified) +- General: (MBaker) Work item 10874 - 1.7.1 Extremely Slow - Refactored PHPExcel_Calculation_Functions::flattenArray() method and set calculation cache timer default to 2.5 seconds +- General: (MBaker) Allow formulae to contain line breaks +- General: (ET) Work item 10910 - split() function deprecated in PHP 5.3.0 +- General: (ET) sys_get_temp_dir() requires PHP 5.2.1, not PHP 5.2 [provide fallback function for PHP 5.2.0] +- General: (MBaker) Applied patch 4640 - Implementation of the ISPMT() Financial function by Matt Groves +- General: (MBaker) Work item 11052 - Put the example of formula with more arguments in documentation +- General: (MBaker) Improved accuracy for the GAMMAINV() Statistical Function +- Feature: (ET) Work item 10409 - XFEXT record support to fix colors change from Excel5 reader, and copy/paste color change with Excel5 writer + - Excel5 reader reads RGB color information in XFEXT records for borders, font color and fill color +- Feature: (MBaker) Work Item 2346 - Implement more Excel calculation functions + - Implemented the FVSCHEDULE(), XNPV(), IRR(), MIRR(), XIRR() and RATE() Financial functions + - Implemented the SUMPRODUCT() Mathematical function + - Implemented the ZTEST() Statistical Function +- Feature: (ET) Work item 10919 - Multiple print areas in one sheet +- Feature: (ET) Work item 10930 - Store calculated values in output by PHPExcel_Writer_Excel5 +- Feature: (ET) Work item 10939 - Sheet protection options in Excel5 reader/writer +- Feature: (MBaker) Modification of the COUNT(), AVERAGE(), AVERAGEA(), DEVSQ, AVEDEV(), STDEV(), STDEVA(), STDEVP(), STDEVPA(), VARA() and VARPA() SKEW() and KURT() functions to correctly handle boolean values depending on whether they're passed in as values, values within a matrix or values within a range of cells. +- Feature: (ET) Work item 9932 - Cell range selection +- Feature: (MB) Work item 10266 - Root-relative path handling +- Feature: (ET) Work item 11315 - Named Ranges not working with PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 11206 - Excel2007 Reader fails to load Apache POI generated Excel +- Bugfix: (MB) Work item 11154 - Number format is broken when system's thousands separator is empty +- Bugfix: (MB) Work item 11401 - ReferenceHelper::updateNamedFormulas throws errors if oldName is empty +- Bugfix: (MB) Work item 11296 - parse_url() fails to parse path to an image in xlsx +- Bugfix: (ET) Work item 10876 - Workaround for iconv_substr() bug in PHP 5.2.0 +- Bugfix: (ET) Work item 10877 - 1 pixel error for image width and height with PHPExcel_Writer_Excel5 +- Bugfix: (MBaker) Fix to GEOMEAN() Statistical function +- Bugfix: (ET) Work item 10884 - setValue('-') and setValue('.') sets numeric 0 instead of 1-character string +- Bugfix: (ET) Work item 10885 - Row height sometimes much too low after read with PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 10888 - Diagonal border. Miscellaneous missing support. + - Constant PHPExcel_Style_Borders::DIAGONAL_BOTH added to support double-diagonal (cross) + - PHPExcel_Reader_Excel2007 not always reading diagonal borders (only recognizes 'true' and not '1') + - PHPExcel_Reader_Excel5 support for diagonal borders + - PHPExcel_Writer_Excel5 support for diagonal borders +- Bugfix: (ET) Work item 10894 - Session bug: Fatal error: Call to a member function bindValue() on a non-object in ...\Classes\PHPExcel\Cell.php on line 217 +- Bugfix: (ET) Work item 10896 - Colors messed up saving twice with same instance of PHPExcel_Writer_Excel5 (regression since 1.7.0) +- Bugfix: (ET) Work item 10917 - Method PHPExcel_Worksheet::setDefaultStyle is not working +- Bugfix: (ET) Work item 10897 - PHPExcel_Reader_CSV::canRead() sometimes says false when it shouldn't +- Bugfix: (ET) Work item 10922 - Changes in workbook not picked up between two saves with PHPExcel_Writer_Excel2007 +- Bugfix: (ET) Work item 10913 - Decimal and thousands separators missing in HTML and PDF output +- Bugfix: (ET) Work item 10936 - Notices with PHPExcel_Reader_Excel5 and named array constants +- Bugfix: (MBaker) Work item 10938 - Calculation engine limitation on 32-bit platform with integers > 2147483647 +- Bugfix: (ET) Work item 10959 - Shared(?) formulae containing absolute cell references not read correctly using Excel5 Reader +- Bugfix: (MBaker) Work item 10962 - Warning messages with intersection operator involving single cell +- Bugfix: (ET) Work item 10980 - Infinite loop in Excel5 reader caused by zero-length string in SST +- Bugfix: (ET) Work item 10983 - Remove unnecessary cell sorting to improve speed by approx. 18% in HTML and PDF writers +- Bugfix: (MBaker) Work item 10977 - Cannot read A1 cell content - OO_Reader +- Bugfix: (ET) Work item 11000 - Transliteration failed, invalid encoding + + +2009/11/02 (v1.7.1): +- General: (ET) Work item 10687 - ereg() function deprecated in PHP 5.3.0 +- General: (MB) Work item 10739 - Writer Interface Inconsequence - setTempDir and setUseDiskCaching +- General: (ET) Upgrade to TCPDF 4.8.009 +- Feature: (ET) Work item 7333 - Support for row and column styles (feature request) + - Basic implementation for Excel2007/Excel5 reader/writer +- Feature: (ET) Work item 10459 - Hyperlink to local file in Excel5 reader/writer +- Feature: (MB) Work item 10472 - Color Tab (Color Sheet's name) +- Feature: (ET) Work item 10488 - Border style "double" support in PHPExcel_Writer_HTML +- Feature: (ET) Work item 10492 - Multi-section number format support in HTML/PDF/CSV writers +- Feature: (MBaker) - Some additional performance tweaks in the calculation engine +- Feature: (MBaker) - Fix result of DB() and DDB() Financial functions to 2dp when in Gnumeric Compatibility mode +- Feature: (MBaker) - Added AMORDEGRC(), AMORLINC() and COUPNUM() Financial function (no validation of parameters yet) +- Feature: (MBaker) - Improved accuracy of TBILLEQ(), TBILLPRICE() and TBILLYIELD() Financial functions when in Excel or Gnumeric mode +- Feature: (MBaker) - Added INDIRECT() Lookup/Reference function (only supports full addresses at the moment) +- Feature: (MB) Work item 10498 - PHPExcel_Reader_CSV::canRead() improvements +- Feature: (ET) Work item 10500 - Input encoding option for PHPExcel_Reader_CSV +- Feature: (ET) Work item 10493 - Colored number format support, e.g. [Red], in HTML/PDF output +- Feature: (ET) Work item 10559 - Color Tab (Color Sheet's name) [Excel5 reader/writer support] +- Feature: (MBaker) Initial version of SYLK (slk) and Excel 2003 XML Readers (Cell data and basic cell formatting) +- Feature: (MBaker) Initial version of Open Office Calc (ods) Reader (Cell data only) +- Feature: (MBaker) Initial use of "pass by reference" in the calculation engine for ROW() and COLUMN() Lookup/Reference functions +- Feature: (MBaker) Work item 2346 - COLUMNS() and ROWS() Lookup/Reference functions, and SUBSTITUTE() Text function +- Feature: (ET) Work item 10502 - AdvancedValueBinder(): Re-enable zero-padded string-to-number conversion, e.g '0004' -> 4 +- Feature: (ET) Work item 10600 - Make PHP type match Excel datatype +- Feature: (MB) Work item 10630 - Change first page number on header +- Feature: (MB) Applied patch 3941 +- Feature: (MB,ET) Work item 10745 - Hidden sheets +- Feature: (ET) Work item 10761 - mbstring fallback when iconv is broken +- Feature: (MBaker) Added support for matrix/value comparisons (e.g. ={1,2;3,4}>=3 or 2<>{1,2;3,4}) - Note, can't yet handle comparison of two matrices +- Feature: (MBaker) Improved handling for validation and error trapping in a number of functions +- Feature: (MBaker) Improved support for fraction number formatting +- Feature: (ET) Work item 10455 - Support Reading CSV with Byte Order Mark (BOM) +- Feature: (ET) Work item 10860 - addExternalSheet() at specified index +- Bugfix: (MBaker) Work item 10684 - Named range can no longer be passed to worksheet->getCell() +- Bugfix: (ET) Work item 10455 - RichText HTML entities no longer working in PHPExcel 1.7.0 +- Bugfix: (ET) Work item 7610 - Fit-to-width value of 1 is lost after read/write of Excel2007 spreadsheet [+ support for simultaneous scale/fitToPage] +- Bugfix: (MB) Work item 10469 - Performance issue identified by profiling +- Bugfix: (ET) Work item 10473 - setSelectedCell is wrong +- Bugfix: (ET) Work item 10481 - Images get squeezed/stretched with (Mac) Verdana 10 Excel files using Excel5 reader/writer +- Bugfix: (MBaker) Work item 10482 - Error in argument count for DATEDIF() function +- Bugfix: (MBaker) Work item 10452 - updateFormulaReferences is buggy +- Bugfix: (MB) Work item 10485 - CellIterator returns null Cell if onlyExistingCells is set and key() is in use +- Bugfix: (MBaker) Work item 10453 - Wrong RegEx for parsing cell references in formulas +- Bugfix: (MB) Work item 10486 - Optimisation subverted to devastating effect if IterateOnlyExistingCells is clear +- Bugfix: (ET) Work item 10494 - Fatal error: Uncaught exception 'Exception' with message 'Unrecognized token 6C in formula'... with PHPExcel_Reader_Excel5 +- Bugfix: (MBaker) Work item 10490 - Fractions stored as text are not treated as numbers by PHPExcel's calculation engine +- Bugfix: (ET) Work item 10503 - AutoFit (autosize) row height not working in PHPExcel_Writer_Excel5 +- Bugfix: (MBaker) Fixed problem with null values breaking the calculation stack +- Bugfix: (ET) Work item 10524 - Date number formats sometimes fail with PHPExcel_Style_NumberFormat::toFormattedString, e.g. [$-40047]mmmm d yyyy +- Bugfix: (MBaker) Fixed minor problem with DATEDIFF YM calculation +- Bugfix: (MB) Applied patch 3695 +- Bugfix: (ET) Work item 10536 - setAutosize() and Date cells not working properly +- Bugfix: (ET) Work item 10556 - Time value hour offset in output by HTML/PDF/CSV writers (system timezone problem) +- Bugfix: (ET) Work item 10558 - Control characters 0x14-0x1F are not treated by PHPExcel +- Bugfix: (ET) Work item 10560 - PHPExcel_Writer_Excel5 not working when open_basedir restriction is in effect +- Bugfix: (MBaker) Work item 10563 - IF formula calculation problem in PHPExcel 1.7.0 (string comparisons) +- Bugfix: (MBaker) Improved CODE() Text function result for UTF-8 characters +- Bugfix: (ET) Work item 10568 - Empty rows are collapsed with HTML/PDF writer +- Bugfix: (ET) Work item 10569 - Gaps between rows in output by PHPExcel_Writer_PDF (Upgrading to TCPDF 4.7.003) +- Bugfix: (ET) Work item 10575 - Problem reading formulas (Excel5 reader problem with "fake" shared formulas) +- Bugfix: (MBaker) Work item 10588 - Error type in formula: "_raiseFormulaError message is Formula Error: An unexpected error occured" +- Bugfix: (ET) Work item 10599 - Miscellaneous column width problems in Excel5/Excel2007 writer +- Bugfix: (ET) Work item 10615 - Reader/Excel5 'Unrecognized token 2D in formula' in latest version +- Bugfix: (ET) Work item 10623 - on php 5.3 PHPExcel 1.7 Excel 5 reader fails in _getNextToken, token = 2C, throws exception +- Bugfix: (ET) Work item 10617 - Fatal error when altering styles after workbook has been saved +- Bugfix: (ET) Work item 10661 - Images vertically stretched or squeezed when default font size is changed (PHPExcel_Writer_Excel5) +- Bugfix: (ET) Work item 10676 - Styles not read in "manipulated" Excel2007 workbook +- Bugfix: (ET) Work item 10059 - Windows 7 says corrupt file by PHPExcel_Writer_Excel5 when opening in Excel +- Bugfix: (MBaker) Work item 10708 - Calculations sometimes not working with cell references to other sheets +- Bugfix: (ET) Work item 10706 - Problem with merged cells after insertNewRowBefore() +- Bugfix: (MBaker) Applied patch 4023 +- Bugfix: (MBaker) Fix to SUMIF() and COUNTIF() Statistical functions for when condition is a match against a string value +- Bugfix: (ET) Work item 10721 - PHPExcel_Cell::coordinateFromString should throw exception for bad string parameter +- Bugfix: (ET) Work item 10723 - EucrosiaUPC (Thai font) not working with PHPExcel_Writer_Excel5 +- Bugfix: (MBaker) Improved the return of calculated results when the result value is an array +- Bugfix: (MBaker) Allow calculation engine to support Functions prefixed with @ within formulae +- Bugfix: (MBaker) Work item 10632 - Intersection operator (space operator) fatal error with calculation engine +- Bugfix: (ET) Work item 10742 - Chinese, Japanese, Korean characters show as squares in PDF +- Bugfix: (ET) Work item 10756 - sheet title allows invalid characters +- Bugfix: (ET) Work item 10757 - Sheet!$A$1 as function argument in formula causes infinite loop in Excel5 writer +- Bugfix: (MBaker) Work item 10740 - Cell range involving name not working with calculation engine - Modified calculation parser to handle range operator (:), but doesn't currently handle worksheet references with spaces or other non-alphameric characters, or trap erroneous references +- Bugfix: (MBaker) Work item 10798 - DATE function problem with calculation engine (says too few arguments given) +- Bugfix: (MBaker) Work item 10799 - Blank cell can cause wrong calculated value +- Bugfix: (MBaker) Modified ROW() and COLUMN() Lookup/Reference Functions to return an array when passed a cell range, plus some additional work on INDEX() +- Bugfix: (ET) Work item 10817 - Images not showing in Excel 97 using PHPExcel_Writer_Excel5 (patch by Jordi Gutiérrez Hermoso) +- Bugfix: (ET) Work item 10785 - When figures are contained in the excel sheet, Reader was stopped +- Bugfix: (MBaker) Work item 10818 - Formulas changed after insertNewRowBefore() +- Bugfix: (ET) Work item 10825 - Cell range row offset problem with shared formulas using PHPExcel_Reader_Excel5 +- Bugfix: (MBaker) Work item 10832 - Warning: Call-time pass-by-reference has been deprecated +- Bugfix: (ET) Work item 10849 - Image should "Move but don't size with cells" instead of "Move and size with cells" with PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 10856 - Opening a Excel5 generated XLS in Excel 2007 results in header/footer entry not showing on input +- Bugfix: (ET) Work item 10859 - addExternalSheet() not returning worksheet +- Bugfix: (MBaker) Work item 10629 - Invalid results in formulas with named ranges + + +2009/08/10 (v1.7.0): +- General: (ET) Work item 9893 - Expand documentation: Number formats +- General: (ET) Work item 9941 - Class 'PHPExcel_Cell_AdvancedValueBinder' not found +- General: (MB) Work item 9960 - Change return type of date functions to PHPExcel_Calculation_Functions::RETURNDATE_EXCEL +- Feature: (MBaker) - New RPN and stack-based calculation engine for improved performance of formula calculation + - Faster (anything between 2 and 12 times faster than the old parser, depending on the complexity and nature of the formula) + - Significantly more memory efficient when formulae reference cells across worksheets + - Correct behaviour when referencing Named Ranges that exist on several worksheets + - Support for Excel ^ (Exponential) and % (Percentage) operators + - Support for matrices within basic arithmetic formulae (e.g. ={1,2,3;4,5,6;7,8,9}/2) + - Better trapping/handling of NaN and infinity results (return #NUM! error) + - Improved handling of empty parameters for Excel functions + - Optional logging of calculation steps +- Feature: (MBaker) - New calculation engine can be accessed independently of workbooks (for use as a standalone calculator) +- Feature: (MBaker) Work Item 2346 - Implement more Excel calculation functions + - Initial implementation of the COUNTIF() and SUMIF() Statistical functions + - Added ACCRINT() Financial function +- Feature: (MBaker) - Modifications to number format handling for dddd and ddd masks in dates, use of thousand separators even when locale only implements it for money, and basic fraction masks (0 ?/? and ?/?) +- Feature: (ET) Work item 9794 - Support arbitrary fixed number of decimals in PHPExcel_Style_NumberFormat::toFormattedString() +- Feature: (ET) Work item 6857 - Improving performance and memory on data dumps + - Various style optimizations (merging from branch wi6857-memory) + - Moving hyperlink and dataValidation properties from cell to worksheet for lower PHP memory usage +- Feature: (MB) Work item 9869 - Provide fluent interfaces where possible +- Feature: (ET) Work item 9899 - Make easy way to apply a border to a rectangular selection +- Feature: (ET) Work item 9906 - Support for system window colors in PHPExcel_Reader_Excel5 +- Feature: (ET) Work item 9911 - Horizontal center across selection +- Feature: (ET) Work item 9919 - Merged cells record, write to full record size in PHPExcel_Writer_Excel5 +- Feature: (MB) Work item 9895 - Add page break between sheets in exported PDF +- Feature: (ET) Work item 9902 - Sanitization of UTF-8 input for cell values +- Feature: (ET) Work item 9930 - Read cached calculated value with PHPExcel_Reader_Excel5 +- Feature: (ET) Work item 9896 - Miscellaneous CSS improvements for PHPExcel_Writer_HTML +- Feature: (ET) Work item 9947 - getProperties: setCompany feature request +- Feature: (MB) Patch 2981 - Insert worksheet at a specified index +- Feature: (MB) Patch 3018 - Change worksheet index +- Feature: (MB) Patch 3039 - Readfilter for CSV reader +- Feature: (ET) Work item 10172 - Check value of mbstring.func_overload when saving with PHPExcel_Writer_Excel5 +- Feature: (ET) Work item 10251 - Eliminate dependency of an include path pointing to class directory +- Feature: (ET) Work item 10292 - Method for getting the correct reader for a certain file (contribution) +- Feature: (ET) Work item 10287 - Choosing specific row in fromArray method +- Feature: (ET) Work item 10319 - Shared formula support in PHPExcel_Reader_Excel5 +- Feature: (MB,ET) Work item 10345 - Right-to-left column direction in worksheet +- Bugfix: (ET) Work item 9824 - PHPExcel_Reader_Excel5 not reading PHPExcel_Style_NumberFormat::FORMAT_NUMBER ('0') +- Bugfix: (ET) Work item 9858 - Fractional row height in locale other than English results in corrupt output using PHPExcel_Writer_Excel2007 +- Bugfix: (ET) Work item 9846 - Fractional (decimal) numbers not inserted correctly when locale is other than English +- Bugfix: (ET) Work item 9863 - Fractional calculated value in locale other than English results in corrupt output using PHPExcel_Writer_Excel2007 +- Bugfix: (ET) Work item 9830 - Locale aware decimal and thousands separator in exported formats HTML, CSV, PDF +- Bugfix: (MB) Work item 9819 - Cannot Add Image with Space on its Name +- Bugfix: (ET) Work item 9884 - Black line at top of every page in output by PHPExcel_Writer_PDF +- Bugfix: (ET) Work item 9885 - Border styles and border colors not showing in HTML output (regression since 1.6.4) +- Bugfix: (ET) Work item 9888 - Hidden screen gridlines setting in worksheet not read by PHPExcel_Reader_Excel2007 +- Bugfix: (MB) Work item 9913 - Some valid sheet names causes corrupt output using PHPExcel_Writer_Excel2007 +- Bugfix: (ET) Work item 9934 - More than 32,767 characters in a cell gives corrupt Excel file +- Bugfix: (ET) Work item 9937 - Images not getting copyied with the ->copy() function +- Bugfix: (ET) Work item 9940 - Bad calculation of column width setAutoSize(true) function +- Bugfix: (ET) Work item 9968 - Dates are sometimes offset by 1 day in output by HTML and PDF writers depending on system timezone setting +- Bugfix: (ET) Work item 10003 - Wingdings symbol fonts not working with PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 10010 - White space string prefix stripped by PHPExcel_Writer_Excel2007 +- Bugfix: (ET) Work item 10023 - The name of the Workbook stream MUST be "Workbook", not "Book" +- Bugfix: (ET) Work item 10030 - Avoid message "Microsoft Excel recalculates formulas..." when closing xls file from Excel +- Bugfix: (ET) Work item 10031 - Non-unique newline representation causes problems with LEN formula +- Bugfix: (ET) Work item 10033 - Newline in cell not showing with PHPExcel_Writer_HTML and PHPExcel_Writer_PDF +- Bugfix: (ET) Work item 10046 - Rich-Text strings get prefixed by &nbsp; when output by HTML writer +- Bugfix: (ET) Work item 10052 - Leading spaces do not appear in output by HTML/PDF writers +- Bugfix: (MB) Work item 10061 - Empty Apache POI-generated file can not be read +- Bugfix: (ET) Work item 10068 - Column width not scaling correctly with font size in HTML and PDF writers +- Bugfix: (ET) Work item 10069 - Inaccurate row heights with HTML writer +- Bugfix: (MB) Patch 2992 - Reference helper +- Bugfix: (MBaker) - Excel 5 Named ranges should not be local to the worksheet, but accessible from all worksheets +- Bugfix: (ET) Work item 10088 - Row heights are ignored by PHPExcel_Writer_PDF +- Bugfix: (MB) Patch 3003 - Write raw XML +- Bugfix: (ET) Work item 10098 - removeRow(), removeColumn() not always clearing cell values +- Bugfix: (ET) Work item 10142 - Problem reading certain hyperlink records with PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 10143 - Hyperlink cell range read failure with PHPExcel_Reader_Excel2007 +- Bugfix: (MB) Work item 10149 - 'Column string index can not be empty.' +- Bugfix: (ET) Work item 10204 - getHighestColumn() sometimes says there are 256 columns with PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 10220 - extractSheetTitle fails when sheet title contains exclamation mark (!) +- Bugfix: (ET) Work item 10221 - setTitle() sometimes erroneously appends integer to sheet name +- Bugfix: (ET) Work item 10229 - Mac BIFF5 Excel file read failure (missing support for Mac OS Roman character set) +- Bugfix: (ET) Work item 10230 - BIFF5 header and footer incorrectly read by PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 10259 - iconv notices when reading hyperlinks with PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 10252 - Excel5 reader OLE read failure with small Mac BIFF5 Excel files +- Bugfix: (ET) Work item 10272 - Problem in reading formula : IF( IF ) with PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 10274 - Error reading formulas referencing external sheets with PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 10291 - Image horizontally stretched when default font size is increased (PHPExcel_Writer_Excel5) +- Bugfix: (ET) Work item 10333 - Undefined offset in Reader\Excel5.php on line 3572 +- Bugfix: (MB) Work item 10340 - PDF output different then XLS (copied data) +- Bugfix: (ET) Work item 10352 - Internal hyperlinks with UTF-8 sheet names not working in PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 10361 - String shared formula result read error with PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 10363 - Uncaught exception 'Exception' with message 'Valid scale is between 10 and 400.' in Classes/PHPExcel/Worksheet/PageSetup.php:338 +- Bugfix: (ET) Work item 10355 - Using setLoadSheetsOnly fails if you do not use setReadDataOnly(true) and sheet is not the first sheet +- Bugfix: (MB) Work item 10362 - getCalculatedValue() sometimes incorrect with IF formula and 0-values +- Bugfix: (MBaker) Work Item 10198 - Excel Reader 2007 problem with "shared" formulae when "master" is an error +- Bugfix: (MBaker) Work Item 10106 - Named Range Bug, using the same range name on different worksheets +- Bugfix: (MBaker) Work Item 10004 - Java code in JAMA classes +- Bugfix: (MBaker) Work Item 9659 - getCalculatedValue() not working with some formulas involving error types +- Bugfix: (MBaker) Work Item 9447 - evaluation of both return values in an IF() statement returning an error if either result was an error, irrespective of the IF evaluation +- Bugfix: (MBaker) Work Item 6203 - Power in formulas: new calculation engine no longer treats ^ as a bitwise XOR operator +- Bugfix: (MBaker) - Bugfixes and improvements to many of the Excel functions in PHPExcel + - Added optional "places" parameter in the BIN2HEX(), BIN2OCT, DEC2BIN(), DEC2OCT(), DEC2HEX(), HEX2BIN(), HEX2OCT(), OCT2BIN() and OCT2HEX() Engineering Functions + - Trap for unbalanced matrix sizes in MDETERM() and MINVERSE() Mathematic and Trigonometric functions + - Fix for default characters parameter value for LEFT() and RIGHT() Text functions + - Fix for GCD() and LCB() Mathematical functions when the parameters include a zero (0) value + - Fix for BIN2OCT() Engineering Function for 2s complement values (which were returning hex values) + - Fix for BESSELK() and BESSELY() Engineering functions + - Fix for IMDIV() Engineering Function when result imaginary component is positive (wasn't setting the sign) + - Fix for ERF() Engineering Function when called with an upper limit value for the integration + - Fix to DATE() Date/Time Function for year value of 0 + - Set ISPMT() function as category FINANCIAL + - Fix for DOLLARDE() and DOLLARFR() Financial functions + - Fix to EFFECT() Financial function (treating $nominal_rate value as a variable name rather than a value) + - Fix to CRITBINOM() Statistical function (CurrentValue and EssentiallyZero treated as constants rather than variables) + Note that an Error in the function logic can still lead to a permanent loop + - Fix to MOD() Mathematical function to work with floating point results + - Fix for QUOTIENT() Mathematical function + - Fix to HOUR(), MINUTE() and SECOND() Date/Time functions to return an error when passing in a floating point value of 1.0 or greater, or less than 0 + - LOG() Function now correctly returns base-10 log when called with only one parameter, rather than the natural log as the default base + - Modified text functions to handle multibyte character set (UTF-8). + + +2009/04/22 (v1.6.7): +- General: (MB) Work item 9416 - Deprecate misspelled setStriketrough() and getStriketrough() methods +- General: (MB) Work item 9526 - Performance improvement when saving file +- Feature: (MB) Work item 9598 - Check that sheet title has maximum 31 characters +- Feature: (MB, ET) Work item 9631 - True support for Excel built-in number format codes +- Feature: (ET) Work item 9683 - Ability to read defect BIFF5 Excel file without CODEPAGE record +- Feature: (MB) Work item 9701 - Auto-detect which reader to invoke +- Feature: (ET) Work item 9214 - Deprecate insertion of dates using PHP-time (Unix time) [request for removal of feature] +- Feature: (ET) Work item 9747 - Support for entering time values like '9:45', '09:45' using AdvancedValueBinder +- Feature: (ET) Work item 9797 - DataType dependent horizontal alignment in HTML and PDF writer +- Bugfix: (MB) Work item 9375 - Cloning data validation object causes script to stop +- Bugfix: (ET) Work item 9400 - Simultaneous repeating rows and repeating columns not working with PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 9399 - Simultaneous repeating rows and repeating columns not working with PHPExcel_Writer_Excel2007 +- Bugfix: (ET) Work item 9437 - Row outline level not working with PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 9452 - Occasional notices with PHPExcel_Reader_Excel5 when Excel file contains drawing elements +- Bugfix: (ET) Work item 9453 - PHPExcel_Reader_Excel5 fails as a whole when workbook contains images other than JPEG/PNG +- Bugfix: (ET) Work item 9444 - Excel5 writer checks for iconv but does not necessarily use it +- Bugfix: (ET) Work item 9463 - Altering a style on copied worksheet alters also the original +- Bugfix: (MB) Work item 9480 - Formulas are incorrectly updated when a sheet is renamed +- Bugfix: (MB) Work item 9513 - PHPExcel_Worksheet::extractSheetTitle not treating single quotes correctly +- Bugfix: (MB) Work item 9477 - PHP Warning raised in function array_key_exists +- Bugfix: (MB) Work item 9599 - getAlignWithMargins() gives wrong value when using PHPExcel_Reader_Excel2007 +- Bugfix: (MB) Work item 9600 - getScaleWithDocument() gives wrong value when using PHPExcel_Reader_Excel2007 +- Bugfix: (MB) Work item 9630 - PHPExcel_Reader_Excel2007 not reading the first user-defined number format +- Bugfix: (MB) Work item 9647 - Print area converted to uppercase after read with PHPExcel_Reader_Excel2007 +- Bugfix: (MB) Work item 9661 - Incorrect reading of scope for named range using PHPExcel_Reader_Excel2007 +- Bugfix: (MB) Work item 9690 - Error with pattern (getFillType) and rbg (getRGB) +- Bugfix: (ET) Work item 9712 - AdvancedValueBinder affected by system timezone setting when inserting date values +- Bugfix: (ET) Work item 9743 - PHPExcel_Reader_Excel2007 not reading value of active sheet index +- Bugfix: (ET) Work item 9742 - getARGB() sometimes returns SimpleXMLElement object instead of string with PHPExcel_Reader_Excel2007 +- Bugfix: (ET) Work item 9731 - Negative image offset causes defects in 14excel5.xls and 20readexcel5.xlsx +- Bugfix: (ET) Work item 9758 - HTML & PDF Writer not working with mergeCells (regression since 1.6.5) +- Bugfix: (ET) Work item 9774 - Too wide columns with HTML and PDF writer +- Bugfix: (MB) Work item 9775 - PDF and cyrillic fonts +- Bugfix: (ET) Work item 9793 - Percentages not working correctly with HTML and PDF writers (shows 0.25% instead of 25%) +- Bugfix: (ET) Work item 9791 - PHPExcel_Writer_HTML creates extra borders around cell contents using setUseInlineCss(true) +- Bugfix: (ET) Work item 9784 - Problem with text wrap + merged cells in HTML and PDF writer +- Bugfix: (ET) Work item 9814 - Adjacent path separators in include_path causing IOFactory to violate open_basedir restriction + + +-------------------------------------------------------------------------------- +BREAKING CHANGE! In previous versions of PHPExcel up to and including 1.6.6, +when a cell had a date-like number format code, it was possible to enter a date +directly using an integer PHP-time without converting to Excel date format. + +Starting with PHPExcel 1.6.7 this is no longer supported. Refer to the developer +documentation for more information on entering dates into a cell. +-------------------------------------------------------------------------------- + + +2009/03/02 (v1.6.6): +- General: (MB) Work item 9102 - Improve support for built-in number formats in PHPExcel_Reader_Excel2007 +- General: (ET) Work item 9281 - Source files are in both UNIX and DOS formats - changed to UNIX +- General: (MB) Work item 9338 - Update documentation: Which language to write formulas in? +- Feature: (ET) Work item 8817 - Ignore DEFCOLWIDTH records with value 8 in PHPExcel_Reader_Excel5 +- Feature: (ET) Work item 8847 - Support for width, height, offsetX, offsetY for images in PHPExcel_Reader_Excel5 +- Feature: (MB) Work item 8870 - Disk Caching in specific folder +- Feature: (MBaker) Work item 2346 - Added SUMX2MY2, SUMX2PY2, SUMXMY2, MDETERM and MINVERSE Mathematical and Trigonometric Functions +- Feature: (MBaker) Work item 2346 - Added CONVERT Engineering Function +- Feature: (MBaker) Work item 2346 - Added DB, DDB, DISC, DOLLARDE, DOLLARFR, INTRATE, IPMT, PPMT, PRICEDISC, PRICEMAT and RECEIVED Financial Functions +- Feature: (MBaker) Work item 2346 - Added ACCRINTM, CUMIPMT, CUMPRINC, TBILLEQ, TBILLPRICE, TBILLYIELD, YIELDDISC and YIELDMAT Financial Functions +- Feature: (MBaker) Work item 2346 - Added DOLLAR Text Function +- Feature: (MBaker) Work item 2346 - Added CORREL, COVAR, FORECAST, INTERCEPT, RSQ, SLOPE and STEYX Statistical Functions +- Feature: (MBaker) Work item 2346 - Added PEARSON Statistical Functions as a synonym for CORREL +- Feature: (MBaker) Work item 2346 - Added LINEST, LOGEST (currently only valid for stats = false), TREND and GROWTH Statistical Functions +- Feature: (MBaker) Work item 2346 - Added RANK and PERCENTRANK Statistical Functions +- Feature: (MBaker) Work item 2346 - Added ROMAN Mathematical Function (Classic form only) +- Feature: (MB) Work item 8931 - Update documentation to show example of getCellByColumnAndRow($col, $row) +- Feature: (MB) Work item 8770 - Implement worksheet, row and cell iterators +- Feature: (MB) Work item 9001 - Support for arbitrary defined names (named range) +- Feature: (MB, ET) Work item 9016 - Update formulas when sheet title / named range title changes +- Feature: (MB) Work item 9103 - Ability to read cached calculated value +- Feature: (MBaker, ET) Work item 8483 - Support for Excel 1904 calendar date mode (Mac) +- Feature: (ET) Work item 9194 - PHPExcel_Writer_Excel5 improvements writing shared strings table +- Feature: (ET) Work item 9248 - PHPExcel_Writer_Excel5 iconv fallback when mbstring extension is not enabled +- Feature: (ET) Work item 9253 - UTF-8 support in font names in PHPExcel_Writer_Excel5 +- Feature: (MB) Work item 9215 - Implement value binding architecture +- Feature: (MB) Work item 6742 - PDF writer not working with UTF-8 +- Feature: (ET) Work item 9355 - Eliminate duplicate style entries in multisheet workbook written by PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 8810 - Redirect to client browser fails due to trailing white space in class definitions +- Bugfix: (MB) Work item 8816 - Spurious column dimension element introduced in blank worksheet after using PHPExcel_Writer_Excel2007 +- Bugfix: (ET) Work item 8830 - Image gets slightly narrower than expected when using PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 8831 - Image laid over non-visible row gets squeezed in height when using PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 8860 - PHPExcel_Reader_Excel5 fails when there are 10 or more images in the workbook +- Bugfix: (MB) Work item 8909 - Different header/footer images in different sheets not working with PHPExcel_Writer_Excel2007 +- Bugfix: (MB, ET) Work item 8924 - Fractional seconds disappear when using PHPExcel_Reader_Excel2007 and PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 7994 - Images not showing in OpenOffice when using PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 9047 - Images not showing on print using PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 9085 - PHPExcel_Writer_Excel5 maximum allowed record size 4 bytes too short +- Bugfix: (MB) Work item 9119 - Not numeric strings are formatted as dates and numbers using worksheet's toArray method +- Bugfix: (ET) Work item 9132 - Excel5 simple formula parsing error +- Bugfix: (ET) Work item 9206 - Problems writing dates with CSV +- Bugfix: (ET) Work item 9203 - PHPExcel_Reader_Excel5 reader fails with fatal error when reading group shapes +- Bugfix: (ET) Work item 9231 - PHPExcel_Writer_Excel5 fails completely when workbook contains more than 57 colors +- Bugfix: (ET) Work item 9244 - PHPExcel_Writer_PDF not compatible with autoload +- Bugfix: (ET) Work item 9250 - Fatal error: Call to a member function getNestingLevel() on a non-object in PHPExcel/Reader/Excel5.php on line 690 +- Bugfix: (MB) Work item 9246 - Notices when running test 04printing.php on PHP 5.2.8 +- Bugfix: (MB) Work item 9294 - insertColumn() spawns creation of spurious RowDimension +- BugFix: (MBaker) Work item 9296 - Fix declarations for methods in extended Trend classes +- Bugfix: (MBaker) Work item 2346 - Fix to parameters for the FORECAST Statistical Function +- Bugfix: (MB) Work item 7083 - PDF writer problems with cell height and text wrapping +- Bugfix: (MBaker) Work Item 9337 - Fix test for calculated value in case the returned result is an array +- Bugfix: (ET) Work Item 9354 - Column greater than 256 results in corrupt Excel file using PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 9351 - Excel Numberformat 0.00 results in non internal decimal places values in toArray() Method +- Bugfix: (MB,ET) Work item 9356 - setAutoSize not taking into account text rotation +- Bugfix: (ET) Work item 9372 - Call to undefined method PHPExcel_Worksheet_MemoryDrawing::getPath() in PHPExcel/Writer/HTML.php + + +2009/01/05 (v1.6.5): +- General: (MB) Applied patch 2063 +- General: (MB) Applied patch from work item 8073 - Optimise Shared Strings +- General: (MB) Applied patch from work item 8074 - Optimise Cell Sorting +- General: (MB) Applied patch from work item 8075 - Optimise Style Hashing +- General: (ET) Applied patch from work item 8245 - UTF-8 enhancements +- General: (ET) Applied patch from work item 8283 - PHPExcel_Writer_HTML validation errors against strict HTML 4.01 / CSS 2.1 +- General: (MB) Documented work items 6203 and 8110 in manual +- General: (ET) Restructure package hierachy so classes can be found more easily in auto-generated API (from work item 8468) +- General: (MB) Work item 8806 - Redirect output to a client's browser: Update recommendation in documentation +- Feature: (ET) Work item 7897 - PHPExcel_Reader_Excel5 support for print gridlines +- Feature: (ET) Work item 7899 - Screen gridlines support in Excel5 reader/writer +- Feature: (MB, ET) Work item 7552 - Option for adding image to spreadsheet from image resource in memory +- Feature: (ET) Work item 7862 - PHPExcel_Reader_Excel5 style support for BIFF5 files (Excel 5.0 - Excel 95) +- Feature: (ET) Work item 7918 - PHPExcel_Reader_Excel5 support for user-defined colors and special built-in colors +- Feature: (ET) Work item 7992 - Support for freeze panes in PHPExcel_Reader_Excel5 +- Feature: (ET) Work item 7996 - Support for header and footer margins in PHPExcel_Reader_Excel5 +- Feature: (ET) Work item 7997 - Support for active sheet index in Excel5 reader/writer +- Feature: (MB) Work item 7991 - Freeze panes not read by PHPExcel_Reader_Excel2007 +- Feature: (MB, ET) Work item 7993 - Support for screen zoom level (feature request) +- Feature: (ET) Work item 8012 - Support for default style in PHPExcel_Reader_Excel5 +- Feature: (MB) Work item 8094 - Apple iWork / Numbers.app incompatibility +- Feature: (MB) Work item 7931 - Support "between rule" in conditional formatting +- Feature: (MB) Work item 8308 - Comment size, width and height control (feature request) +- Feature: (ET) Work item 8418 - Improve method for storing MERGEDCELLS records in PHPExcel_Writer_Excel5 +- Feature: (ET) Work item 8435 - Support for protectCells() in Excel5 reader/writer +- Feature: (ET) Work item 8472 - Support for fitToWidth and fitToHeight pagesetup properties in PHPExcel_Reader_Excel5 +- Feature: (ET) Work item 8489 - Support for setShowSummaryBelow() and setShowSummaryRight() in PHPExcel_Writer_Excel5 +- Feature: (MB) Work item 8483 - Support for Excel 1904 calendar date mode (Mac) +- Feature: (ET) Work item 7538 - Excel5 reader: Support for reading images (bitmaps) +- Feature: (ET) Work item 8787 - Support for default style in PHPExcel_Writer_Excel5 +- Feature: (MBaker) Modified calculate() method to return either an array or the first value from the array for those functions that return arrays rather than single values (e.g the MMULT and TRANSPOSE function). This performance can be modified based on the $returnArrayAsType which can be set/retrieved by calling the setArrayReturnType() and getArrayReturnType() methods of the PHPExcel_Calculation class. +- Feature: (MBaker) Work item 2346 - Added ERROR.TYPE Information Function, MMULT Mathematical and Trigonometry Function, and TRANSPOSE Lookup and Reference Function +- Bugfix: (ET) Work item 7896 - setPrintGridlines(true) not working with PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 7907 - Incorrect mapping of fill patterns in PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 7898 - setShowGridlines(false) not working with PHPExcel_Writer_Excel2007 +- Bugfix: (MB) Work item 7905 - getShowGridlines() gives inverted value when reading sheet with PHPExcel_Reader_Excel2007 +- Bugfix: (ET) Work item 7944 - User-defined column width becomes slightly larger after read/write with Excel5 +- Bugfix: (ET) Work item 7949 - Incomplete border style support in PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 7928 - Conditional formatting "containsText" read/write results in MS Office Excel 2007 crash +- Bugfix: (MB) Work item 7995 - All sheets are always selected in output when using PHPExcel_Writer_Excel2007 +- Bugfix: (MB) Work item 8013 - COLUMN function warning message during plain read/write +- Bugfix: (MB) Work item 8155 - setValue(0) results in string data type '0' +- Bugfix: (MB) Work item 8226 - Styles not removed when removing rows from sheet +- Bugfix: (MB) Work item 8301 - =IF formula causes fatal error during $objWriter->save() in Excel2007 format +- Bugfix: (ET) Work item 8333 - Exception thrown reading valid xls file: "Excel file is corrupt. Didn't find CONTINUE record while reading shared strings" +- Bugfix: (ET) Work item 8320 - MS Outlook corrupts files generated by PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 8351 - Undefined method PHPExcel_Worksheet::setFreezePane() in ReferenceHelper.php on line 271 +- Bugfix: (MB) Work item 8401 - Ampersands (&), left and right angles (<, >) in Rich-Text strings leads to corrupt output using PHPExcel_Writer_Excel2007 +- Bugfix: (ET) Work item 8408 - Print header and footer not supporting UTF-8 in PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 8463 - Vertical page breaks not working with PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 8476 - Missing support for accounting underline types in PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 8482 - Infinite loops when reading corrupt xls file using PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 8566 - Sheet protection password not working with PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 8596 - PHPExcel_Style_NumberFormat::FORMAT_NUMBER ignored by PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 8781 - PHPExcel_Reader_Excel5 fails a whole when workbook contains a chart +- Bugfix: (ET) Work item 8788 - Occasional loss of column widths using PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 8795 - Notices while reading formulas with deleted sheet references using PHPExcel_Reader_Excel5 +- Bugfix: (MB) Work item 8807 - Default style not read by PHPExcel_Reader_Excel2007 +- Bugfix: (MB) Work item 9341 - Blank rows occupy too much space in file generated by PHPExcel_Writer_Excel2007 + + +2008/10/27 (v1.6.4): +- General: (ET) Work item 7882 - RK record number error in MS developer documentation: 0x007E should be 0x027E +- Feature: (MBaker) Work item 7878 - getHighestColumn() returning "@" for blank worksheet causes corrupt output +- Feature: (MBaker) Work item 2346 - Implement ROW and COLUMN Lookup/Reference Functions (when specified with a parameter) +- Feature: (MBaker) Work item 2346 - Implement initial work on OFFSET Lookup/Reference Function (returning address rather than value at address) +- Feature: (ET) Work item 7416 - Excel5 reader: Page margins +- Feature: (ET) Work item 7417 - Excel5 reader: Header & Footer +- Feature: (ET) Work item 7449 - Excel5 reader support for page setup (paper size etc.) +- Feature: (MB) Work item 7445 - Improve speed and memory consumption of PHPExcel_Writer_CSV +- Feature: (MB) Work item 7432 - Better recognition of number format in HTML, CSV, and PDF writer +- Feature: (MB) Work item 7485 - Font support: Superscript and Subscript +- Feature: (ET) Work item 7509 - Excel5 reader font support: Super- and subscript +- Feature: (ET) Work item 7521 - Excel5 reader style support: Text rotation and stacked text +- Feature: (ET) Work item 7530 - Excel5 reader: Support for hyperlinks +- Feature: (MB, ET) Work item 7557 - Import sheet by request +- Feature: (ET) Work item 7607 - PHPExcel_Reader_Excel5 support for page breaks +- Feature: (ET) Work item 7622 - PHPExcel_Reader_Excel5 support for shrink-to-fit +- Feature: (MB, ET) Work item 7675 - Support for error types +- Feature: (ET) Work item 7388 - Excel5 reader true formula support +- Feature: (ET) Work item 7701 - Support for named ranges (defined names) in PHPExcel_Reader_Excel5 +- Feature: (ET) Work item 7781 - Support for repeating rows and repeating columns (print titles) in PHPExcel_Reader_Excel5 +- Feature: (ET) Work item 7783 - Support for print area in PHPExcel_Reader_Excel5 +- Feature: (ET) Work item 7795 - Excel5 reader and writer support for horizontal and vertical centering of page +- Feature: (MB) Applied patch 1962 +- Feature: (ET) Work item 7866 - Excel5 reader and writer support for hidden cells (formulas) +- Feature: (MB, ET) Work item 7612 - Support for indentation in cells (feature request) +- Feature: (MB, ET) Work item 7828 - Option for reading only specified interval of rows in a sheet +- Bugfix: (MBaker) Work item 7367 - PHPExcel_Calculation_Functions::DATETIMENOW() and PHPExcel_Calculation_Functions::DATENOW() to force UTC +- Bugfix: (MBaker) Work item 7395 - Modified PHPExcel_Shared_Date::FormattedPHPToExcel() and PHPExcel_Shared_Date::ExcelToPHP to force datatype for return values +- Bugfix: (ET) Work item 7450 - Excel5 reader not producing UTF-8 strings with BIFF5 files +- Bugfix: (MB) Work item 7470 - Array constant in formula gives run-time notice with Excel2007 writer +- Bugfix: (MB) Work item 7494 - PHPExcel_Reader_Excel2007 setReadDataOnly(true) returns Rich-Text +- Bugfix: (ET) Work item 7496 - PHPExcel_Reader_Excel5 setReadDataOnly(true) returns Rich-Text +- Bugfix: (MB) Work item 7497 - Characters before superscript or subscript losing style +- Bugfix: (MB) Work item 7507 - Subscript not working with HTML writer +- Bugfix: (MB) Work item 7508 - DefaultColumnDimension not working on first column (A) +- Bugfix: (MB) Work item 7527 - Negative numbers are stored as text in PHPExcel_Writer_2007 +- Bugfix: (ET) Work item 7531 - Text rotation and stacked text not working with PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 7536 - PHPExcel_Shared_Date::isDateTimeFormatCode erroneously says true +- Bugfix: (MB) Work item 7559 - Different images with same filename in separate directories become duplicates +- Bugfix: (ET) Work item 7568 - PHPExcel_Reader_Excel5 not returning sheet names as UTF-8 using for Excel 95 files +- Bugfix: (MB) Work item 7575 - setAutoSize(true) on empty column gives column width of 10 using PHPExcel_Writer_Excel2007 +- Bugfix: (MB, ET) Work item 7573 - setAutoSize(true) on empty column gives column width of 255 using PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 7514 - Worksheet_Drawing bug +- Bugfix: (MB) Work item 7593 - getCalculatedValue() with REPT function causes script to stop +- Bugfix: (MB) Work item 7594 - getCalculatedValue() with LEN function causes script to stop +- Bugfix: (MB) Work item 7600 - Explicit fit-to-width (page setup) results in fit-to-height becoming 1 +- Bugfix: (MB) Work item 7610 - Fit-to-width value of 1 is lost after read/write of Excel2007 spreadsheet +- Bugfix: (MB) Work item 7516 - Conditional styles not read properly using PHPExcel_Reader_Excel2007 +- Bugfix: (MB) Work item 7611 - PHPExcel_Writer_2007: Default worksheet style works only for first sheet +- Bugfix: (ET) Work item 6940 - Cannot Lock Cells using PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 7621 - Incorrect cell protection values found when using Excel5 reader +- Bugfix: (ET) Work item 7623 - Default row height not working above highest row using PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 7637 - Default column width does not get applied when using PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 7642 - Broken support for UTF-8 string formula results in PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 7643 - UTF-8 sheet names not working with PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 7631 - getCalculatedValue() with ISNONTEXT function causes script to stop +- Bugfix: (ET) Work item 7652 - Missing BIFF3 functions in PHPExcel_Writer_Excel5: USDOLLAR (YEN), FINDB, SEARCHB, REPLACEB, LEFTB, RIGHTB, MIDB, LENB, ASC, DBCS (JIS) +- Bugfix: (ET) Work item 7663 - Excel5 reader doesn't read numbers correctly in 64-bit systems +- Bugfix: (ET) Work item 7667 - Missing BIFF5 functions in PHPExcel_Writer_Excel5: ISPMT, DATEDIF, DATESTRING, NUMBERSTRING +- Bugfix: (ET) Work item 7668 - Missing BIFF8 functions in PHPExcel_Writer_Excel5: GETPIVOTDATA, HYPERLINK, PHONETIC, AVERAGEA, MAXA, MINA, STDEVPA, VARPA, STDEVA, VARA +- Bugfix: (MB) Work item 7657 - Wrong host value in PHPExcel_Shared_ZipStreamWrapper::stream_open() +- Bugfix: (ET) Work item 7676 - PHPExcel_Reader_Excel5 not reading explicitly entered error types in cells +- Bugfix: (ET) Work item 7678 - Boolean and error data types not preserved for formula results in PHPExcel_Reader_Excel5 +- Bugfix: (MB) Work item 7695 - PHPExcel_Reader_Excel2007 ignores cell data type +- Bugfix: (ET) Work item 7712 - PHPExcel_Reader_Excel5 ignores cell data type +- Bugfix: (ET) Work item 7587 - PHPExcel_Writer_Excel5 not aware of data type +- Bugfix: (ET) Work item 7713 - Long strings sometimes truncated when using PHPExcel_Reader_Excel5 +- Bugfix: (ET) Work item 7727 - Direct entry of boolean or error type in cell not supported by PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 7714 - PHPExcel_Reader_Excel2007: Error reading cell with data type string, date number format, and numeric-like cell value +- Bugfix: (ET) Work item 7735 - Row and column outlines (group indent level) not showing after using PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 7737 - Missing UTF-8 support in number format codes for PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 7750 - Missing UTF-8 support with PHPExcel_Writer_Excel5 for explicit string in formula +- Bugfix: (MB) Work item 7726 - Problem with class constants in PHPExcel_Style_NumberFormat +- Bugfix: (ET) Work item 7758 - Sometimes errors with PHPExcel_Reader_Excel5 reading hyperlinks +- Bugfix: (ET) Work item 7759 - Hyperlink in cell always results in string data type when using PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 7771 - Excel file with blank sheet seen as broken in MS Office Excel 2007 when created by PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 7785 - PHPExcel_Reader_Excel5: Incorrect reading of formula with explicit string containing (escaped) double-quote +- Bugfix: (MB) Work item 7787 - getCalculatedValue() fails on formula with sheet name containing (escaped) single-quote +- Bugfix: (MB) Work item 7786 - getCalculatedValue() fails on formula with explicit string containing (escaped) double-quote +- Bugfix: (MB) Work item 7780 - Problems with simultaneous repeatRowsAtTop and repeatColumnsAtLeft using Excel2007 reader and writer +- Bugfix: (ET) Work item 7802 - PHPExcel_Reader_Excel5: Error reading formulas with sheet reference containing special characters +- Bugfix: (ET) Work item 7831 - Off-sheet references sheet!A1 not working with PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 7834 - Repeating rows/columns (print titles), print area not working with PHPExcel_Writer_Excel5 +- Bugfix: (ET) Work item 7849 - Formula having datetime number format shows as text when using PHPExcel_Writer_Excel5 +- Bugfix: (MBaker) Work item 7863 - Cannot set formula to hidden using applyFromArray() +- Bugfix: (MBaker) Work item 7805 - HTML/PDF Writers limited to 26 columns by calculateWorksheetDimension (erroneous comparison in getHighestColumn() method) +- Bugfix: (MB) Work item 7873 - Formula returning error type is lost when read by PHPExcel_Reader_Excel2007 +- Bugfix: (ET) Work item 7883 - PHPExcel_Reader_Excel5: Cell style lost for last column in group of blank cells +- Bugfix: (MB) Work item 7886 - Column width sometimes collapses to auto size using Excel2007 reader/writer +- Bugfix: (MB) Work item 9343 - Data Validation Formula = 0 crashes Excel + + +2008/08/25 (v1.6.3): +- Bugfix: (MBaker) Work item 7367 - Modified PHPExcel_Shared_Date::PHPToExcel() to force UTC +- General: (MB) Applied patch 1629 +- General: (MB) Applied patch 1644 +- General: (MB) Work item 6485 - Implement repeatRow and repeatColumn in Excel5 writer +- General: (MB) Work item 6838 - Remove scene3d filter in Excel2007 drawing +- Feature: (MBaker) Work item 2346 - Implement CHOOSE and INDEX Lookup/Reference Functions +- Feature: (MBaker) Work item 2346 - Implement CLEAN Text Functions +- Feature: (MBaker) Work item 2346 - Implement YEARFRAC Date/Time Functions +- Feature: (MB) Work item 6508 - Implement 2 options for print/show gridlines +- Feature: (MB) Work item 7270 - Add VLOOKUP function (contribution) +- Feature: (MB) Work item 7182 - Implemented: ShrinkToFit +- Feature: (MB) Work item 7218 - Row heights not updated correctly when inserting new rows +- Feature: (MB) Work item 7157 - Copy worksheets within the same workbook +- Feature: (ET) Work item 7290 - Excel5 reader style support: horizontal and vertical alignment plus text wrap +- Feature: (ET) Work item 7294 - Excel5 reader support for merged cells +- Feature: (ET) Work item 7296 - Excel5 reader: Sheet Protection +- Feature: (ET) Work item 7297 - Excel5 reader: Password for sheet protection +- Feature: (ET) Work item 7299 - Excel5 reader: Column width +- Feature: (ET) Work item 7301 - Excel5 reader: Row height +- Feature: (ET) Work item 7304 - Excel5 reader: Font support +- Feature: (ET) Work item 7324 - Excel5 reader: support for locked cells +- Feature: (ET) Work item 7330 - Excel5 reader style support: Fill (background colors and patterns) +- Feature: (ET) Work item 7332 - Excel5 reader style support: Borders (style and color) +- Feature: (ET) Work item 7346 - Excel5 reader: Rich-Text support +- Feature: (MB) Work item 7313 - Read Excel built-in number formats with Excel 2007 reader +- Feature: (ET) Work item 7317 - Excel5 reader: Number format support +- Feature: (MB) Work item 7362 - Creating a copy of PHPExcel object +- Feature: (ET) Work item 7373 - Excel5 reader: support for row / column outline (group) +- Feature: (MB) Work item 7380 - Implement default row/column sizes +- Feature: (MB) Work item 7364 - Writer HTML - option to return styles and table separately +- Feature: (ET) Work item 7393 - Excel5 reader: Support for remaining built-in number formats +- Bugfix: (MBaker) Fixed rounding in HOUR MINUTE and SECOND Time functions, and improved performance for these +- Bugfix: (MBaker) Fix to TRIM function +- Bugfix: (MBaker) Fixed range validation in TIME Functions.php +- Bugfix: (MBaker) EDATE and EOMONTH functions now return date values based on the returnDateType flag +- Bugfix: (MBaker) Write date values that are the result of a calculation function correctly as Excel serialized dates rather than PHP serialized date values +- Bugfix: (MB) Work item 6690 - Excel2007 reader not always reading boolean correctly +- Bugfix: (MB) Work item 6275 - Columns above IZ +- Bugfix: (MB) Work item 6853 - Other locale than English causes Excel2007 writer to produce broken xlsx +- Bugfix: (MB) Work item 7061 - Typo: Number_fromat in NumberFormat.php +- Bugfix: (MB) Work item 6865 - Bug in Worksheet_BaseDrawing setWidth() +- Bugfix: (MB) Work item 6891 - PDF writer collapses column width for merged cells +- Bugfix: (MB) Work item 6867 - Issues with drawings filenames +- Bugfix: (MB) Work item 7073 - fromArray() local variable isn't defined +- Bugfix: (MB) Work item 7276 - PHPExcel_Writer_Excel5->setTempDir() not passed to all classes involved in writing to a file +- Bugfix: (MB) Work item 7277 - Excel5 reader not handling UTF-8 properly +- Bugfix: (MB) Work item 7327 - If you write a 0 value in cell, cell shows as empty +- Bugfix: (MB) Work item 7302 - Excel2007 writer: Row height ignored for empty rows +- Bugfix: (MB) Work item 7281 - Excel2007 (comments related error) +- Bugfix: (MB) Work item 7345 - Column width in other locale +- Bugfix: (MB) Work item 7347 - Excel2007 reader not reading underlined Rich-Text +- Bugfix: (ET) Work item 7357 - Excel5 reader converting booleans to strings +- Bugfix: (MB) Work item 7365 - Recursive Object Memory Leak +- Bugfix: (MB) Work item 7372 - Excel2007 writer ignoring row dimensions without cells +- Bugfix: (ET) Work item 7382 - Excel5 reader is converting formatted numbers / dates to strings + + +2008/06/23 (v1.6.2): +- General: (MB) Work item 6088 - Document style array values +- General: (MB) Applied patch 1195 +- General: (MB) Work item 6178 - Redirecting output to a client’s web browser - http headers +- General: (MB) Work item 6187 - Improve worksheet garbage collection +- General: (MBaker) Functions that return date values can now be configured to return as Excel serialized date/time, PHP serialized date/time, or a PHP date/time object. +- General: (MBaker) Functions that explicitly accept dates as parameters now permit values as Excel serialized date/time, PHP serialized date/time, a valid date string, or a PHP date/time object. +- General: (MBaker) Implement ACOSH, ASINH and ATANH functions for those operating platforms/PHP versions that don't include these functions +- General: (MBaker) Implement ATAN2 logic reversing the arguments as per Excel +- General: (MBaker) Additional validation of parameters for COMBIN +- General: (MBaker) Fixed validation for CEILING and FLOOR when the value and significance parameters have different signs; and allowed default value of 1 or -1 for significance when in GNUMERIC compatibility mode +- Feature: (MBaker) Work item 2346 - Implement ADDRESS, ISLOGICAL, ISTEXT and ISNONTEXT functions +- Feature: (MBaker) Work item 2346 - Implement COMPLEX, IMAGINARY, IMREAL, IMARGUMENT, IMCONJUGATE, IMABS, IMSUB, IMDIV, IMSUM, IMPRODUCT, IMSQRT, IMEXP, IMLN, IMLOG10, IMLOG2, IMPOWER IMCOS and IMSIN Engineering functions +- Feature: (MBaker) Work item 2346 - Implement NETWORKDAYS and WORKDAY Date/Time functions +- Feature: (MB) Work item 6100 - Make cell column AAA available +- Feature: (MB) Work item 6095 - Mark particular cell as selected when opening Excel +- Feature: (MB) Work item 6120 - Multiple sheets in PDF and HTML +- Feature: (MB) Work item 6227 - Implement PHPExcel_ReaderFactory and PHPExcel_WriterFactory +- Feature: (MB) Work item 6249 - Set image root of PHPExcel_Writer_HTML +- Feature: (MB) Work item 6264 - Enable/disable calculation cache +- Feature: (MB) Work item 6259 - PDF writer and multi-line text +- Feature: (MB) Work item 6350 - Feature request - setCacheExpirationTime() +- Feature: (JB) Work item 6370 - Implement late-binding mechanisms to reduce memory footprint +- Feature: (JB) Work item 6430 - Implement shared styles +- Feature: (MB) Work item 6391 - Copy sheet from external Workbook to active Workbook +- Feature: (MB) Work item 6428 - Functions in Conditional Formatting +- Bugfix: (MB) Work item 6096 - Default Style in Excel5 +- Bugfix: (MB) Work item 6150 - Numbers starting with '+' cause Excel 2007 errors +- Bugfix: (MB) Work item 6092 - ExcelWriter5 is not PHP5 compatible, using it with E_STRICT results in a bunch of errors (applied patches) +- Bugfix: (MB) Work item 6179 - Error Reader Excel2007 line 653 foreach ($relsDrawing->Relationship as $ele) +- Bugfix: (MB) Work item 6229 - Worksheet toArray() screws up DATE +- Bugfix: (MB) Work item 6253 - References to a Richtext cell in a formula +- Bugfix: (MB) Work item 6285 - insertNewColumnBefore Bug +- Bugfix: (MB) Work item 6319 - Error reading Excel2007 file with shapes +- Bugfix: (MBaker) Work item 6302 - Determine whether date values need conversion from PHP dates to Excel dates before writing to file, based on the data type (float or integer) +- Bugfix: (MBaker) Fixes to DATE function when it is given negative input parameters +- Bugfix: (MB) Work item 6347 - PHPExcel handles empty cells other than Excel +- Bugfix: (MB) Work item 6348 - PHPExcel handles 0 and "" as being the same +- Bugfix: (MB) Work item 6357 - Problem Using Excel2007 Reader for Spreadsheets containing images +- Bugfix: (MB) Work item 6359 - ShowGridLines ignored when reading/writing Excel 2007 +- Bugfix: (MB) Work item 6426 - Bug With Word Wrap in Excel 2007 Reader + + +2008/04/28 (v1.6.1): +- General: (MB) Work item 5532 - Fix documentation printing +- General: (MB) Work item 5586 - Memory usage improvements +- General: (MB) Applied patch 990 +- General: (MB) Applied patch 991 +- Feature: (BM) Work item 2841 - Implement PHPExcel_Reader_Excel5 +- Feature: (MB) Work item 5564 - Implement "toArray" and "fromArray" method +- Feature: (MB) Work item 5665 - Read shared formula +- Feature: (MB) Work item 5681 - Read image twoCellAnchor +- Feature: (MB) Work item 4446 - &G Image as bg for headerfooter +- Feature: (MB) Work item 5834 - Implement page layout functionality for Excel5 format +- Feature: (MB) Work item 6039 - Feature request: PHPExcel_Writer_PDF +- Bugfix: (MB) Work item 5517 - DefinedNames null check +- Bugfix: (MB) Work item 5463 - Hyperlinks should not always have trailing slash +- Bugfix: (MB) Work item 5592 - Saving Error - Uncaught exception (#REF! named range) +- Bugfix: (MB) Work item 5634 - Error when creating Zip file on Linux System (Not Windows) +- Bugfix: (MB) Work item 5876 - Time incorrecly formated +- Bugfix: (MB) Work item 5914 - Conditional formatting - second rule not applied +- Bugfix: (MB) Work item 5978 - PHPExcel_Reader_Excel2007 cannot load PHPExcel_Shared_File +- Bugfix: (MB) Work item 6020 - Output redirection to web browser + + +2008/02/14 (v1.6.0): +- General: (MB) Work item 3156 - Use PHPExcel datatypes in formula calculation +- Feature: (MB) Work item 5019 - Center on page when printing +- Feature: (MB) Work item 5099 - Hyperlink to other spreadsheet +- Feature: (MB) Work item 5104 - Set the print area of a worksheet +- Feature: (MB) Work item 5118 - Read "definedNames" property of worksheet +- Feature: (MB) Work item 5338 - Set default style for all cells +- Feature: (MB) Work item 4216 - Named Ranges +- Feature: (MB) Work item 5398 - Implement worksheet references (Sheet1!A1) +- Bugfix: (MB) Work item 4967 - Redirect output to a client's web browser +- Bugfix: (MB) Work item 5008 - "File Error: data may have been lost." seen in Excel 2007 and Excel 2003 SP3 when opening XLS file +- Bugfix: (MB) Work item 5165 - Bug in style's getHashCode() +- Bugfix: (MB) Work item 5165 - PHPExcel_Reader not correctly reading numeric values +- Bugfix: (MB) Work item 5324 - Text rotation is read incorrectly +- Bugfix: (MB) Work item 5326 - Enclosure " and data " result a bad data : \" instead of "" +- Bugfix: (MB) Work item 5332 - Formula parser - IF statement returning array instead of scalar +- Bugfix: (MB) Work item 5351 - setFitToWidth(nbpage) & setFitToWidth(nbpage) work partially +- Bugfix: (MB) Work item 5361 - Worksheet::setTitle() causes unwanted renaming +- Bugfix: (MB) Work item 5407 - Hyperlinks not working. Results in broken xlsx file. + + +2007/12/24 (v1.5.5): +- General: (MB) Work item 4135 - Grouping Rows +- General: (MB) Work item 4427 - Semi-nightly builds +- Feature: (MB) Work item 3155 - Implement "date" datatype +- Feature: (MB) Work item 4150 - Date format not honored in CSV writer +- Feature: (MB) Work item 4199 - RichText and sharedStrings +- Feature: (MB) Work item 2346 - Implement more Excel calculation functions + - Addition of DATE, DATEDIF, DATEVALUE, DAY, DAYS360 +- Feature: (MBaker) Work item 2346 - Implement more Excel calculation functions + - Addition of AVEDEV, HARMEAN and GEOMEAN + - Addition of the BINOMDIST (Non-cumulative only), COUNTBLANK, EXPONDIST, FISHER, FISHERINV, NORMDIST, NORMSDIST, PERMUT, POISSON (Non-cumulative only) and STANDARDIZE Statistical Functions + - Addition of the CEILING, COMBIN, EVEN, FACT, FACTDOUBLE, FLOOR, MULTINOMIAL, ODD, ROUNDDOWN, ROUNDUP, SIGN, SQRTPI and SUMSQ Mathematical Functions + - Addition of the NORMINV, NORMSINV, CONFIDENCE and SKEW Statistical Functions + - Addition of the CRITBINOM, HYPGEOMDIST, KURT, LOGINV, LOGNORMDIST, NEGBINOMDIST and WEIBULL Statistical Functions + - Addition of the LARGE, PERCENTILE, QUARTILE, SMALL and TRIMMEAN Statistical Functions + - Addition of the BIN2HEX, BIN2OCT, DELTA, ERF, ERFC, GESTEP, HEX2BIN, HEX2DEC, HEX2OCT, OCT2BIN and OCT2HEX Engineering Functions + - Addition of the CHIDIST, GAMMADIST and GAMMALN Statistical Functions + - Addition of the GCD, LCM, MROUND and SUBTOTAL Mathematical Functions + - Addition of the LOWER, PROPER and UPPER Text Functions + - Addition of the BETADIST and BETAINV Statistical Functions + - Addition of the CHIINV and GAMMAINV Statistical Functions + - Addition of the SERIESSUM Mathematical Function + - Addition of the CHAR, CODE, FIND, LEN, REPT, SEARCH, T, TRIM Text Functions + - Addition of the FALSE and TRUE Boolean Functions + - Addition of the TDIST and TINV Statistical Functions + - Addition of the EDATE, EOMONTH, YEAR, MONTH, TIME, TIMEVALUE, HOUR, MINUTE, SECOND, WEEKDAY, WEEKNUM, NOW, TODAY and Date/Time Function + - Addition of the BESSELI, BESSELJ, BESSELK and BESSELY Engineering Functions + - Addition of the SLN and SYD Financial Functions + - reworked MODE calculation to handle floating point numbers + - Improved error trapping for invalid input values + - Fix to SMALL, LARGE, PERCENTILE and TRIMMEAN to eliminate non-numeric values + - Added CDF to BINOMDIST and POISSON + - Fix to a potential endless loop in CRITBINOM, together with other bugfixes to the algorithm + - Fix to SQRTPI so that it will work with a real value parameter rather than just integers + - Trap for passing negative values to FACT + - Improved accuracy of the NORMDIST cumulative function, and of the ERF and ERFC functions + - Replicated Excel data-type and error handling for BIN, DEC, OCT and HEX conversion functions + - Replicated Excel data-type and error handling for AND and OR Boolean functions + - Bugfix to MROUND + - Rework of the DATE, DATEVALUE, DAY, DAYS360 and DATEDIF date/Time functions to use Excel dates rather than straight PHP dates + - Rework of the AND, OR Boolean functions to ignore string values + - Rework of the BIN2DEC, BIN2HEX, BIN2OCT, DEC2BIN, DEC2HEX, DEC2OCT Engineering functions to handle two's complement + - Excel, Gnumeric and OpenOffice Calc compatibility flag for functions + Note, not all functions have yet been written to work with the Gnumeric and OpenOffice Calc compatibility flags + - 1900 or 1904 Calendar flag for date functions + - Reworked ExcelToPHP date method to handle the Excel 1900 leap year + Note that this will not correctly return values prior to 13-Dec-1901 20:45:52 as this is the minimum value that PHP date serial values can handle. If you need to work with dates prior to this, then an ExcelToPHPObject method has been added which will work correctly with values between Excel's 1900 calendar base date of 1-Jan-1900, and 13-Dec-1901 + - Addition of ExcelToPHPObject date method to return a PHP DateTime object from an Excel date serial value + - PHPToExcel method modified to accept either PHP date serial numbers or PHP DateTime objects + - Addition of FormattedPHPToExcel which will accept a date and time broken to into year, month, day, hour, minute, second and return an Excel date serial value +- Feature: (MB) Work item 4485 - Control characters in Excel 2007 +- Feature: (MB) Work item 4796 - BaseDrawing::setWidthAndHeight method request +- Feature: (MB) Work item 4798 - Page Setup -> Print Titles -> Sheet -> 'Rows to repeat at top' +- Feature: (MB) Work item 4433 - Comment functionality +- Bugfix: (MB) Work item 4124 - Undefined variable in PHPExcel_Writer_Serialized +- Bugfix: (MB) Work item 4125 - Notice: Object of class PHPExcel_RichText could not be converted to int +- Bugfix: (MB) Work item 4126 - Excel5Writer: utf8 string not converted to utf16 +- Bugfix: (MB) Work item 4180 - PHPExcel_RichText and autosize +- Bugfix: (MB) Work item 4574 - Excel5Writer produces broken xls files after change mentioned in work item 4126 +- Bugfix: (MB) Work item 4797 - Small bug in PHPExcel_Reader_Excel2007 function _readStyle + + +2007/10/23 (v 1.5.0): +- General: (MB) Work item 3265 - Refactor PHPExcel Drawing +- Feature: (CS) Work item 3079 - Update Shared/OLE.php to latest version from PEAR +- Feature: (MB) Work item 3217 - Excel2007 vs Excel2003 compatibility pack +- Feature: (MB) Work item 3234 - Cell protection (lock/unlock) +- Feature: (MB) Work item 3543 - Create clickable links (hyperlinks) +- Feature: (MB) Work item 3241 - Additional page setup parameters +- Feature: (MB) Work item 3300 - Make temporary file path configurable (Excel5) +- Feature: (MB) Work item 3306 - Small addition to applyFromArray for font +- Feature: (MB) Work item 3373 - Better feedback when save of file is not possible +- Bugfix: (MB) Work item 3181 - Text Rotation +- Bugfix: (MB) Work item 3237 - Small bug in Page Orientation +- Bugfix: (MB) Work item 3812 - insertNewColumnBeforeByColumn undefined +- Bugfix: (MB) Work item 3893 - Sheet references not working in formula (Excel5 Writer) + + +2007/08/23 (v 1.4.5): +- General: (MB) Work item 3003 - Class file endings +- General: (MB) Work item 3081 - Different calculation engine improvements +- General: (MB) Work item 3082 - Different improvements in PHPExcel_Reader_Excel2007 +- General: (MB) Work item 3146 - Set XML indentation in PHPExcel_Writer_Excel2007 +- Feature: (MB) Work item 3159 - Optionally store temporary Excel2007 writer data in file instead of memory +- Feature: (MB) Work item 3063 - Implement show/hide gridlines +- Feature: (MB) Work item 3064 - Implement option to read only data +- Feature: (MB) Work item 3080 - Optionally disable formula precalculation +- Feature: (MB) Work item 3154 - Explicitly set cell datatype +- Feature: (MBaker) Work item 2346 - Implement more Excel calculation functions + - Addition of MINA, MAXA, COUNTA, AVERAGEA, MEDIAN, MODE, DEVSQ, STDEV, STDEVA, STDEVP, STDEVPA, VAR, VARA, VARP and VARPA Excel Functions + - Fix to SUM, PRODUCT, QUOTIENT, MIN, MAX, COUNT and AVERAGE functions when cell contains a numeric value in a string datatype, bringing it in line with MS Excel behaviour +- Bugfix: (MB) Work item 2881 - File_exists on ZIP fails on some installations +- Bugfix: (MB) Work item 2879 - Argument in textRotation should be -90..90 +- Bugfix: (MB) Work item 2883 - Excel2007 reader/writer not implementing OpenXML/SpreadsheetML styles 100% correct +- Bugfix: (MB) Work item 2513 - Active sheet index not read/saved +- Bugfix: (MB) Work item 2935 - Print and print preview of generated XLSX causes Excel2007 to crash +- Bugfix: (MB) Work item 2952 - Error in Calculations - COUNT() function +- Bugfix: (MB) Work item 3002 - HTML and CSV writer not writing last row +- Bugfix: (MB) Work item 3017 - Memory leak in Excel5 writer +- Bugfix: (MB) Work item 3044 - Printing (PHPExcel_Writer_Excel5) +- Bugfix: (MB) Work item 3046 - Problems reading zip:// +- Bugfix: (MB) Work item 3047 - Error reading conditional formatting +- Bugfix: (MB) Work item 3067 - Bug in Excel5 writer (storePanes) +- Bugfix: (MB) Work item 3077 - Memory leak in PHPExcel_Style_Color + + +2007/07/23 (v 1.4.0): +- General: (MB) Work item 2687 - Coding convention / code cleanup +- General: (MB) Work item 2717 - Use set_include_path in tests +- General: (MB) Work item 2812 - Move PHPExcel_Writer_Excel5 OLE to PHPExcel_Shared_OLE +- Feature: (MB) Work item 2679 - Hide/Unhide Column or Row +- Feature: (MB) Work item 2271 - Implement multi-cell styling +- Feature: (MB) Work item 2720 - Implement CSV file format (reader/writer) +- Feature: (MB) Work item 2845 - Implement HTML file format +- Bugfix: (MB) Work item 2513 - Active sheet index not read/saved +- Bugfix: (MB) Work item 2678 - Freeze Panes with PHPExcel_Writer_Excel5 +- Bugfix: (MB) Work item 2680 - OLE.php +- Bugfix: (MB) Work item 2736 - Copy and pasting multiple drop-down list cells breaks reader +- Bugfix: (MB) Work item 2775 - Function setAutoFilterByColumnAndRow takes wrong arguments +- Bugfix: (MB) Work item 2858 - Simplexml_load_file fails on ZipArchive + + +2007/06/27 (v 1.3.5): +- General: (MB) Work item 15 - Documentation +- Feature: (JV) PHPExcel_Writer_Excel5 +- Feature: (JV) PHPExcel_Reader_Excel2007: Image shadows +- Feature: (MB) Work item 2385 - Data validation +- Feature: (MB) Work item 187 - Implement richtext strings +- Bugfix: (MB) Work item 2443 - Empty relations when adding image to any sheet but the first one +- Bugfix: (MB) Work item 2536 - Excel2007 crashes on print preview + + +2007/06/05 (v 1.3.0): +- General: (MB) Work item 1942 - Create PEAR package +- General: (MB) Work item 2331 - Replace *->duplicate() by __clone() +- Feature: (JV) PHPExcel_Reader_Excel2007: Column auto-size, Protection, Merged cells, Wrap text, Page breaks, Auto filter, Images +- Feature: (MB) Work item 245 - Implement "freezing" panes +- Feature: (MB) Work item 2273 - Cell addressing alternative +- Feature: (MB) Work item 2270 - Implement cell word-wrap attribute +- Feature: (MB) Work item 2282 - Auto-size column +- Feature: (MB) Work item 241 - Implement formula calculation +- Feature: (MB) Work item 2375 - Insert/remove row/column +- Bugfix: (MB) Work item 1931 - PHPExcel_Worksheet::getCell() should not accept absolute coordinates +- Bugfix: (MB) Work item 2272 - Cell reference without row number +- Bugfix: (MB) Work item 2276 - Styles with same coordinate but different worksheet +- Bugfix: (MB) Work item 2290 - PHPExcel_Worksheet->getCellCollection() usort error +- Bugfix: (SS) Work item 2353 - Bug in PHPExcel_Cell::stringFromColumnIndex +- Bugfix: (JV) Work item 2353 - Reader: numFmts can be missing, use cellStyleXfs instead of cellXfs in styles + + +2007/04/26 (v 1.2.0): +- General: (MB) Stringtable attribute "count" not necessary, provides wrong info to Excel sometimes... +- General: (MB) Updated tests to address more document properties +- General: (MB) Some refactoring in PHPExcel_Writer_Excel2007_Workbook +- General: (MB) New package: PHPExcel_Shared +- General: (MB) Password hashing algorithm implemented in PHPExcel_Shared_PasswordHasher +- General: (MB) Moved pixel conversion functions to PHPExcel_Shared_Drawing +- General: (MB) Work item 244 - Switch over to LGPL license +- General: (MB) Work item 5 - Include PHPExcel version in file headers +- Feature: (MB) Work item 6 - Autofilter +- Feature: (MB) Work item 7 - Extra document property: keywords +- Feature: (MB) Work item 8 - Extra document property: category +- Feature: (MB) Work item 9 - Document security +- Feature: (MB) Work item 10 - PHPExcel_Writer_Serialized and PHPExcel_Reader_Serialized +- Feature: (MB) Work item 11 - Alternative syntax: Addressing a cell +- Feature: (MB) Work item 12 - Merge cells +- Feature: (MB) Work item 13 - Protect ranges of cells with a password +- Bugfix: (JV) Work item 14 - (style/fill/patternFill/fgColor or bgColor can be empty) + + +2007/03/26 (v 1.1.1): +- Bugfix: (MB) Work item 1250 - Syntax error in "Classes/PHPExcel/Writer/Excel2007.php" on line 243 +- General: (MB) Work item 1282 - Reader should check if file exists and throws an exception when it doesn't + + +2007/03/22 (v 1.1.0): +- Changed filenames of tests +- Bugfix: (MB) Work item 836 - Style information lost after passing trough Excel2007_Reader +- Bugfix: (MB) Work item 913 - Number of columns > AZ fails fixed in PHPExcel_Cell::columnIndexFromString +- General: (MB) Added a brief file with installation instructions +- Feature: (MB) Page breaks (horizontal and vertical) +- Feature: (MB) Image shadows + + + +2007/02/22 (v 1.0.0): +- Changelog now includes developer initials +- Bugfix: (JV) PHPExcel->removeSheetByIndex now re-orders sheets after deletion, so no array indexes are lost +- Bugfix: (JV) PHPExcel_Writer_Excel2007_Worksheet::_writeCols() used direct assignment to $pSheet->getColumnDimension('A')->Width instead of $pSheet->getColumnDimension('A')->setWidth() +- Bugfix: (JV) DocumentProperties used $this->LastModifiedBy instead of $this->_lastModifiedBy. +- Bugfix: (JV) Only first = should be removed when writing formula in PHPExcel_Writer_Excel2007_Worksheet. +- General: (JV) Consistency of method names to camelCase +- General: (JV) Updated tests to match consistency changes +- General: (JV) Detection of mime-types now with image_type_to_mime_type() +- General: (JV) Constants now hold string value used in Excel 2007 +- General: (MB) Fixed folder name case (WorkSheet -> Worksheet) +- Feature: (MB) PHPExcel classes (not the Writer classes) can be duplicated, using a duplicate() method. +- Feature: (MB) Cell styles can now be duplicated to a range of cells using PHPExcel_Worksheet->duplicateStyle() +- Feature: (MB) Conditional formatting +- Feature: (JV) Reader for Excel 2007 (not supporting full specification yet!) + + + +2007/01/31 (v 1.0.0 RC): +- Project name has been changed to PHPExcel +- Project homepage is now http://www.codeplex.com/PHPExcel +- Started versioning at number: PHPExcel 1.0.0 RC + + + +2007/01/22: +- Fixed some performance issues on large-scale worksheets (mainly loops vs. indexed arrays) +- Performance on creating StringTable has been increased +- Performance on writing Excel2007 worksheet has been increased + + + +2007/01/18: +- Images can now be rotated +- Fixed bug: When drawings have full path specified, no mime type can be deducted +- Fixed bug: Only one drawing can be added to a worksheet + + + +2007/01/12: +- Refactoring of some classes to use ArrayObject instead of array() +- Cell style now has support for number format (i.e. #,##0) +- Implemented embedding images + + + +2007/01/02: +- Cell style now has support for fills, including gradient fills +- Cell style now has support for fonts +- Cell style now has support for border colors +- Cell style now has support for font colors +- Cell style now has support for alignment + + + +2006/12/21: +- Support for cell style borders +- Support for cell styles +- Refactoring of Excel2007 Writer into multiple classes in package SpreadSheet_Writer_Excel2007 +- Refactoring of all classes, changed public members to public properties using getter/setter +- Worksheet names are now unique. On duplicate worksheet names, a number is appended. +- Worksheet now has parent SpreadSheet object +- Worksheet now has support for page header and footer +- Worksheet now has support for page margins +- Worksheet now has support for page setup (only Paper size and Orientation) +- Worksheet properties now accessible by using getProperties() +- Worksheet now has support for row and column dimensions (height / width) +- Exceptions thrown have a more clear description + + + +Initial version: +- Create a Spreadsheet object +- Add one or more Worksheet objects +- Add cells to Worksheet objects +- Export Spreadsheet object to Excel 2007 OpenXML format +- Each cell supports the following data formats: string, number, formula, boolean. \ No newline at end of file diff --git a/src/admin/application/libs/PHPExcel/install.txt b/src/admin/application/libs/PHPExcel/install.txt new file mode 100755 index 0000000..6737905 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/install.txt @@ -0,0 +1,75 @@ +************************************************************************************** +* PHPExcel +* +* Copyright (c) 2006 - 2011 PHPExcel +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* @copyright Copyright (c) 2006 - 2013 PHPExcel (http://www.codeplex.com/PHPExcel) +* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL +* @version 1.7.9, 2013-06-02 +************************************************************************************** + +Requirements +------------ + +The following requirements should be met prior to using PHPExcel: +* PHP version 5.2.0 or higher +* PHP extension php_zip enabled *) +* PHP extension php_xml enabled +* PHP extension php_gd2 enabled (if not compiled in) + +*) php_zip is only needed by PHPExcel_Reader_Excel2007, PHPExcel_Writer_Excel2007, + PHPExcel_Reader_OOCalc. In other words, if you need PHPExcel to handle .xlsx or .ods + files you will need the zip extension, but otherwise not. + + + +Installation instructions +------------------------- + +Installation is quite easy: copy the contents of the Classes folder to any location +in your application required. + +Example: + +If your web root folder is /var/www/ you may want to create a subfolder called +/var/www/Classes/ and copy the files into that folder so you end up with files: + +/var/www/Classes/PHPExcel.php +/var/www/Classes/PHPExcel/Calculation.php +/var/www/Classes/PHPExcel/Cell.php +... + + + +Getting started +--------------- + +A good way to get started is to run some of the tests included in the download. +Copy the "Examples" folder next to your "Classes" folder from above so you end up with: + +/var/www/Examples/01simple.php +/var/www/Examples/02types.php +... + +Start running the test by pointing your browser to the test scripts: + +http://example.com/Examples/01simple.php +http://example.com/Examples/02types.php +... + +Note: It may be necessary to modify the include/require statements at the beginning of +each of the test scripts if your "Classes" folder from above is named differently. diff --git a/src/admin/application/libs/PHPExcel/license.txt b/src/admin/application/libs/PHPExcel/license.txt new file mode 100755 index 0000000..57b74d4 --- /dev/null +++ b/src/admin/application/libs/PHPExcel/license.txt @@ -0,0 +1,345 @@ +GNU LESSER GENERAL PUBLIC LICENSE + + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + +NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/src/admin/application/libs/dUnzip2.inc.php b/src/admin/application/libs/dUnzip2.inc.php new file mode 100644 index 0000000..1986fd1 --- /dev/null +++ b/src/admin/application/libs/dUnzip2.inc.php @@ -0,0 +1,517 @@ +<?php +// 15/07/2006 (2.6) +// - Changed the algorithm to parse the ZIP file.. Now, the script will try to mount the compressed +// list, searching on the 'Central Dir' records. If it fails, the script will try to search by +// checking every signature. Thanks to Jayson Cruz for pointing it. +// 25/01/2006 (2.51) +// - Fixed bug when calling 'unzip' without calling 'getList' first. Thanks to Bala Murthu for pointing it. +// 01/12/2006 (2.5) +// - Added optional parameter "applyChmod" for the "unzip()" method. It auto applies the given chmod for +// extracted files. +// - Permission 777 (all read-write-exec) is default. If you want to change it, you'll need to make it +// explicit. (If you want the OS to determine, set "false" as "applyChmod" parameter) +// 28/11/2005 (2.4) +// - dUnzip2 is now compliant with old-style "Data Description", made by some compressors, +// like the classes ZipLib and ZipLib2 by 'Hasin Hayder'. Thanks to Ricardo Parreno for pointing it. +// 09/11/2005 (2.3) +// - Added optional parameter '$stopOnFile' on method 'getList()'. +// If given, file listing will stop when find given filename. (Useful to open and unzip an exact file) +// 06/11/2005 (2.21) +// - Added support to PK00 file format (Packed to Removable Disk) (thanks to Lito [PHPfileNavigator]) +// - Method 'getExtraInfo': If requested file doesn't exist, return FALSE instead of Array() +// 31/10/2005 (2.2) +// - Removed redundant 'file_name' on centralDirs declaration (thanks to Lito [PHPfileNavigator]) +// - Fixed redeclaration of file_put_contents when in PHP4 (not returning true) + +############################################################## +# Class dUnzip2 v2.6 +# +# Author: Alexandre Tedeschi (d) +# E-Mail: alexandrebr at gmail dot com +# Londrina - PR / Brazil +# +# Objective: +# This class allows programmer to easily unzip files on the fly. +# +# Requirements: +# This class requires extension ZLib Enabled. It is default +# for most site hosts around the world, and for the PHP Win32 dist. +# +# To do: +# * Error handling +# * Write a PHP-Side gzinflate, to completely avoid any external extensions +# * Write other decompress algorithms +# +# If you modify this class, or have any ideas to improve it, please contact me! +# You are allowed to redistribute this class, if you keep my name and contact e-mail on it. +# +# PLEASE! IF YOU USE THIS CLASS IN ANY OF YOUR PROJECTS, PLEASE LET ME KNOW! +# If you have problems using it, don't think twice before contacting me! +# +############################################################## + +if(!function_exists('file_put_contents')){ + // If not PHP5, creates a compatible function + Function file_put_contents($file, $data){ + if($tmp = fopen($file, "w")){ + fwrite($tmp, $data); + fclose($tmp); + + return true; + } + echo "<b>file_put_contents:</b> Cannot create file $file<br>"; + return false; + } +} + +class dUnzip2{ + Function getVersion(){ + return "2.6"; + } + // Public + var $fileName; + var $compressedList; // You will problably use only this one! + var $centralDirList; // Central dir list... It's a kind of 'extra attributes' for a set of files + var $endOfCentral; // End of central dir, contains ZIP Comments + var $debug; + + // Private + var $fh; + var $zipSignature = "\x50\x4b\x03\x04"; // local file header signature + var $dirSignature = "\x50\x4b\x01\x02"; // central dir header signature + var $dirSignatureE= "\x50\x4b\x05\x06"; // end of central dir signature + + // Public + Function dUnzip2($fileName){ + $this->fileName = $fileName; + $this->compressedList = + $this->centralDirList = + $this->endOfCentral = Array(); + } + + Function getList($stopOnFile=false){ + if(sizeof($this->compressedList)){ + $this->debugMsg(1, "Returning already loaded file list."); + return $this->compressedList; + } + + // Open file, and set file handler + $fh = fopen($this->fileName, "r"); + $this->fh = &$fh; + if(!$fh){ + $this->debugMsg(2, "Failed to load file."); + return false; + } + + $this->debugMsg(1, "Loading list from 'End of Central Dir' index list..."); + if(!$this->_loadFileListByEOF($fh, $stopOnFile)){ + $this->debugMsg(1, "Failed! Trying to load list looking for signatures..."); + if(!$this->_loadFileListBySignatures($fh, $stopOnFile)){ + $this->debugMsg(1, "Failed! Could not find any valid header."); + $this->debugMsg(2, "ZIP File is corrupted or empty"); + return false; + } + } + + if($this->debug){ + #------- Debug compressedList + $kkk = 0; + echo "<table border='0' style='font: 11px Verdana; border: 1px solid #000'>"; + foreach($this->compressedList as $fileName=>$item){ + if(!$kkk && $kkk=1){ + echo "<tr style='background: #ADA'>"; + foreach($item as $fieldName=>$value) + echo "<td>$fieldName</td>"; + echo '</tr>'; + } + echo "<tr style='background: #CFC'>"; + foreach($item as $fieldName=>$value){ + if($fieldName == 'lastmod_datetime') + echo "<td title='$fieldName' nowrap='nowrap'>".date("d/m/Y H:i:s", $value)."</td>"; + else + echo "<td title='$fieldName' nowrap='nowrap'>$value</td>"; + } + echo "</tr>"; + } + echo "</table>"; + + #------- Debug centralDirList + $kkk = 0; + if(sizeof($this->centralDirList)){ + echo "<table border='0' style='font: 11px Verdana; border: 1px solid #000'>"; + foreach($this->centralDirList as $fileName=>$item){ + if(!$kkk && $kkk=1){ + echo "<tr style='background: #AAD'>"; + foreach($item as $fieldName=>$value) + echo "<td>$fieldName</td>"; + echo '</tr>'; + } + echo "<tr style='background: #CCF'>"; + foreach($item as $fieldName=>$value){ + if($fieldName == 'lastmod_datetime') + echo "<td title='$fieldName' nowrap='nowrap'>".date("d/m/Y H:i:s", $value)."</td>"; + else + echo "<td title='$fieldName' nowrap='nowrap'>$value</td>"; + } + echo "</tr>"; + } + echo "</table>"; + } + + #------- Debug endOfCentral + $kkk = 0; + if(sizeof($this->endOfCentral)){ + echo "<table border='0' style='font: 11px Verdana' style='border: 1px solid #000'>"; + echo "<tr style='background: #DAA'><td colspan='2'>dUnzip - End of file</td></tr>"; + foreach($this->endOfCentral as $field=>$value){ + echo "<tr>"; + echo "<td style='background: #FCC'>$field</td>"; + echo "<td style='background: #FDD'>$value</td>"; + echo "</tr>"; + } + echo "</table>"; + } + } + + return $this->compressedList; + } + Function getExtraInfo($compressedFileName){ + return + isset($this->centralDirList[$compressedFileName])? + $this->centralDirList[$compressedFileName]: + false; + } + Function getZipInfo($detail=false){ + return $detail? + $this->endOfCentral[$detail]: + $this->endOfCentral; + } + + Function unzip($compressedFileName, $targetFileName=false, $applyChmod=0777){ + if(!sizeof($this->compressedList)){ + $this->debugMsg(1, "Trying to unzip before loading file list... Loading it!"); + $this->getList(false, $compressedFileName); + } + + $fdetails = &$this->compressedList[$compressedFileName]; + if(!isset($this->compressedList[$compressedFileName])){ + $this->debugMsg(2, "File '<b>$compressedFileName</b>' is not compressed in the zip."); + return false; + } + if(substr($compressedFileName, -1) == "/"){ + $this->debugMsg(2, "Trying to unzip a folder name '<b>$compressedFileName</b>'."); + return false; + } + if(!$fdetails['uncompressed_size']){ + $this->debugMsg(1, "File '<b>$compressedFileName</b>' is empty."); + return $targetFileName? + file_put_contents($targetFileName, ""): + ""; + } + + fseek($this->fh, $fdetails['contents-startOffset']); + $ret = $this->uncompress( + fread($this->fh, $fdetails['compressed_size']), + $fdetails['compression_method'], + $fdetails['uncompressed_size'], + $targetFileName + ); + if($applyChmod && $targetFileName) + chmod($targetFileName, 0777); + $this->debugMsg(1, "File '<b>$compressedFileName</b>' unzippato."); + return $ret; + } + Function unzipAll($targetDir=false, $baseDir="", $maintainStructure=true, $applyChmod=0777){ + if($targetDir === false) + $targetDir = dirname(__FILE__)."/"; + + $lista = $this->getList(); + if(sizeof($lista)) foreach($lista as $fileName=>$trash){ + $dirname = dirname($fileName); + $outDN = "$targetDir/$dirname"; + + if(substr($dirname, 0, strlen($baseDir)) != $baseDir) + continue; + + if(!is_dir($outDN) && $maintainStructure){ + $str = ""; + $folders = explode("/", $dirname); + foreach($folders as $folder){ + $str = $str?"$str/$folder":$folder; + if(!is_dir("$targetDir/$str")){ + $this->debugMsg(1, "Creating folder: $targetDir/$str"); + mkdir("$targetDir/$str"); + if($applyChmod) + chmod("$targetDir/$str", $applyChmod); + } + } + } + if(substr($fileName, -1, 1) == "/") + continue; + + $maintainStructure? + $this->unzip($fileName, "$targetDir/$fileName", $applyChmod): + $this->unzip($fileName, "$targetDir/".basename($fileName), $applyChmod); + } + } + + Function close(){ // Free the file resource + if($this->fh) + fclose($this->fh); + } + Function __destroy(){ + $this->close(); + } + + // Private (you should NOT call these methods): + Function uncompress($content, $mode, $uncompressedSize, $targetFileName=false){ + switch($mode){ + case 0: + // Not compressed + return $targetFileName? + file_put_contents($targetFileName, $content): + $content; + case 1: + $this->debugMsg(2, "Shrunk mode is not supported... yet?"); + return false; + case 2: + case 3: + case 4: + case 5: + $this->debugMsg(2, "Compression factor ".($mode-1)." is not supported... yet?"); + return false; + case 6: + $this->debugMsg(2, "Implode is not supported... yet?"); + return false; + case 7: + $this->debugMsg(2, "Tokenizing compression algorithm is not supported... yet?"); + return false; + case 8: + // Deflate + return $targetFileName? + file_put_contents($targetFileName, gzinflate($content, $uncompressedSize)): + gzinflate($content, $uncompressedSize); + case 9: + $this->debugMsg(2, "Enhanced Deflating is not supported... yet?"); + return false; + case 10: + $this->debugMsg(2, "PKWARE Date Compression Library Impoloding is not supported... yet?"); + return false; + case 12: + // Bzip2 + return $targetFileName? + file_put_contents($targetFileName, bzdecompress($content)): + bzdecompress($content); + case 18: + $this->debugMsg(2, "IBM TERSE is not supported... yet?"); + return false; + default: + $this->debugMsg(2, "Unknown uncompress method: $mode"); + return false; + } + } + Function debugMsg($level, $string){ + if($this->debug) + if($level == 1) + echo "<b style='color: #777'>dUnzip2:</b> $string<br>"; + if($level == 2) + echo "<b style='color: #F00'>dUnzip2:</b> $string<br>"; + } + + Function _loadFileListByEOF(&$fh, $stopOnFile=false){ + // Check if there's a valid Central Dir signature. + // Let's consider a file comment smaller than 1024 characters... + // Actually, it length can be 65536.. But we're not going to support it. + + for($x = 0; $x < 1024; $x++){ + fseek($fh, -22-$x, SEEK_END); + + $signature = fread($fh, 4); + if($signature == $this->dirSignatureE){ + // If found EOF Central Dir + $eodir['disk_number_this'] = unpack("v", fread($fh, 2)); // number of this disk + $eodir['disk_number'] = unpack("v", fread($fh, 2)); // number of the disk with the start of the central directory + $eodir['total_entries_this'] = unpack("v", fread($fh, 2)); // total number of entries in the central dir on this disk + $eodir['total_entries'] = unpack("v", fread($fh, 2)); // total number of entries in + $eodir['size_of_cd'] = unpack("V", fread($fh, 4)); // size of the central directory + $eodir['offset_start_cd'] = unpack("V", fread($fh, 4)); // offset of start of central directory with respect to the starting disk number + $zipFileCommentLenght = unpack("v", fread($fh, 2)); // zipfile comment length + $eodir['zipfile_comment'] = $zipFileCommentLenght[1]?fread($fh, $zipFileCommentLenght[1]):''; // zipfile comment + $this->endOfCentral = Array( + 'disk_number_this'=>$eodir['disk_number_this'][1], + 'disk_number'=>$eodir['disk_number'][1], + 'total_entries_this'=>$eodir['total_entries_this'][1], + 'total_entries'=>$eodir['total_entries'][1], + 'size_of_cd'=>$eodir['size_of_cd'][1], + 'offset_start_cd'=>$eodir['offset_start_cd'][1], + 'zipfile_comment'=>$eodir['zipfile_comment'], + ); + + // Then, load file list + fseek($fh, $this->endOfCentral['offset_start_cd']); + $signature = fread($fh, 4); + + while($signature == $this->dirSignature){ + $dir['version_madeby'] = unpack("v", fread($fh, 2)); // version made by + $dir['version_needed'] = unpack("v", fread($fh, 2)); // version needed to extract + $dir['general_bit_flag'] = unpack("v", fread($fh, 2)); // general purpose bit flag + $dir['compression_method'] = unpack("v", fread($fh, 2)); // compression method + $dir['lastmod_time'] = unpack("v", fread($fh, 2)); // last mod file time + $dir['lastmod_date'] = unpack("v", fread($fh, 2)); // last mod file date + $dir['crc-32'] = fread($fh, 4); // crc-32 + $dir['compressed_size'] = unpack("V", fread($fh, 4)); // compressed size + $dir['uncompressed_size'] = unpack("V", fread($fh, 4)); // uncompressed size + $fileNameLength = unpack("v", fread($fh, 2)); // filename length + $extraFieldLength = unpack("v", fread($fh, 2)); // extra field length + $fileCommentLength = unpack("v", fread($fh, 2)); // file comment length + $dir['disk_number_start'] = unpack("v", fread($fh, 2)); // disk number start + $dir['internal_attributes'] = unpack("v", fread($fh, 2)); // internal file attributes-byte1 + $dir['external_attributes1']= unpack("v", fread($fh, 2)); // external file attributes-byte2 + $dir['external_attributes2']= unpack("v", fread($fh, 2)); // external file attributes + $dir['relative_offset'] = unpack("V", fread($fh, 4)); // relative offset of local header + $dir['file_name'] = fread($fh, $fileNameLength[1]); // filename + $dir['extra_field'] = $extraFieldLength[1] ?fread($fh, $extraFieldLength[1]) :''; // extra field + $dir['file_comment'] = $fileCommentLength[1]?fread($fh, $fileCommentLength[1]):''; // file comment + + // Convert the date and time, from MS-DOS format to UNIX Timestamp + $BINlastmod_date = str_pad(decbin($dir['lastmod_date'][1]), 16, '0', STR_PAD_LEFT); + $BINlastmod_time = str_pad(decbin($dir['lastmod_time'][1]), 16, '0', STR_PAD_LEFT); + $lastmod_dateY = bindec(substr($BINlastmod_date, 0, 7))+1980; + $lastmod_dateM = bindec(substr($BINlastmod_date, 7, 4)); + $lastmod_dateD = bindec(substr($BINlastmod_date, 11, 5)); + $lastmod_timeH = bindec(substr($BINlastmod_time, 0, 5)); + $lastmod_timeM = bindec(substr($BINlastmod_time, 5, 6)); + $lastmod_timeS = bindec(substr($BINlastmod_time, 11, 5)); + + $this->centralDirList[$dir['file_name']] = Array( + 'version_madeby'=>$dir['version_madeby'][1], + 'version_needed'=>$dir['version_needed'][1], + 'general_bit_flag'=>str_pad(decbin($dir['general_bit_flag'][1]), 8, '0', STR_PAD_LEFT), + 'compression_method'=>$dir['compression_method'][1], + 'lastmod_datetime' =>mktime($lastmod_timeH, $lastmod_timeM, $lastmod_timeS, $lastmod_dateM, $lastmod_dateD, $lastmod_dateY), + 'crc-32' =>str_pad(dechex(ord($dir['crc-32'][3])), 2, '0', STR_PAD_LEFT). + str_pad(dechex(ord($dir['crc-32'][2])), 2, '0', STR_PAD_LEFT). + str_pad(dechex(ord($dir['crc-32'][1])), 2, '0', STR_PAD_LEFT). + str_pad(dechex(ord($dir['crc-32'][0])), 2, '0', STR_PAD_LEFT), + 'compressed_size'=>$dir['compressed_size'][1], + 'uncompressed_size'=>$dir['uncompressed_size'][1], + 'disk_number_start'=>$dir['disk_number_start'][1], + 'internal_attributes'=>$dir['internal_attributes'][1], + 'external_attributes1'=>$dir['external_attributes1'][1], + 'external_attributes2'=>$dir['external_attributes2'][1], + 'relative_offset'=>$dir['relative_offset'][1], + 'file_name'=>$dir['file_name'], + 'extra_field'=>$dir['extra_field'], + 'file_comment'=>$dir['file_comment'], + ); + $signature = fread($fh, 4); + } + + // If loaded centralDirs, then try to identify the offsetPosition of the compressed data. + if($this->centralDirList) foreach($this->centralDirList as $filename=>$details){ + $i = $this->_getFileHeaderInformation($fh, $details['relative_offset']); + $this->compressedList[$filename]['file_name'] = $filename; + $this->compressedList[$filename]['compression_method'] = $details['compression_method']; + $this->compressedList[$filename]['version_needed'] = $details['version_needed']; + $this->compressedList[$filename]['lastmod_datetime'] = $details['lastmod_datetime']; + $this->compressedList[$filename]['crc-32'] = $details['crc-32']; + $this->compressedList[$filename]['compressed_size'] = $details['compressed_size']; + $this->compressedList[$filename]['uncompressed_size'] = $details['uncompressed_size']; + $this->compressedList[$filename]['lastmod_datetime'] = $details['lastmod_datetime']; + $this->compressedList[$filename]['extra_field'] = $i['extra_field']; + $this->compressedList[$filename]['contents-startOffset']=$i['contents-startOffset']; + if(strtolower($stopOnFile) == strtolower($filename)) + break; + } + return true; + } + } + return false; + } + Function _loadFileListBySignatures(&$fh, $stopOnFile=false){ + fseek($fh, 0); + + $return = false; + for(;;){ + $details = $this->_getFileHeaderInformation($fh); + if(!$details){ + $this->debugMsg(1, "Invalid signature. Trying to verify if is old style Data Descriptor..."); + fseek($fh, 12 - 4, SEEK_CUR); // 12: Data descriptor - 4: Signature (that will be read again) + $details = $this->_getFileHeaderInformation($fh); + } + if(!$details){ + $this->debugMsg(1, "Still invalid signature. Probably reached the end of the file."); + break; + } + $filename = $details['file_name']; + $this->compressedList[$filename] = $details; + $return = true; + if(strtolower($stopOnFile) == strtolower($filename)) + break; + } + + return $return; + } + Function _getFileHeaderInformation(&$fh, $startOffset=false){ + if($startOffset !== false) + fseek($fh, $startOffset); + + $signature = fread($fh, 4); + if($signature == $this->zipSignature){ + # $this->debugMsg(1, "Zip Signature!"); + + // Get information about the zipped file + $file['version_needed'] = unpack("v", fread($fh, 2)); // version needed to extract + $file['general_bit_flag'] = unpack("v", fread($fh, 2)); // general purpose bit flag + $file['compression_method'] = unpack("v", fread($fh, 2)); // compression method + $file['lastmod_time'] = unpack("v", fread($fh, 2)); // last mod file time + $file['lastmod_date'] = unpack("v", fread($fh, 2)); // last mod file date + $file['crc-32'] = fread($fh, 4); // crc-32 + $file['compressed_size'] = unpack("V", fread($fh, 4)); // compressed size + $file['uncompressed_size'] = unpack("V", fread($fh, 4)); // uncompressed size + $fileNameLength = unpack("v", fread($fh, 2)); // filename length + $extraFieldLength = unpack("v", fread($fh, 2)); // extra field length + $file['file_name'] = fread($fh, $fileNameLength[1]); // filename + $file['extra_field'] = $extraFieldLength[1]?fread($fh, $extraFieldLength[1]):''; // extra field + $file['contents-startOffset']= ftell($fh); + + // Bypass the whole compressed contents, and look for the next file + fseek($fh, $file['compressed_size'][1], SEEK_CUR); + + // Convert the date and time, from MS-DOS format to UNIX Timestamp + $BINlastmod_date = str_pad(decbin($file['lastmod_date'][1]), 16, '0', STR_PAD_LEFT); + $BINlastmod_time = str_pad(decbin($file['lastmod_time'][1]), 16, '0', STR_PAD_LEFT); + $lastmod_dateY = bindec(substr($BINlastmod_date, 0, 7))+1980; + $lastmod_dateM = bindec(substr($BINlastmod_date, 7, 4)); + $lastmod_dateD = bindec(substr($BINlastmod_date, 11, 5)); + $lastmod_timeH = bindec(substr($BINlastmod_time, 0, 5)); + $lastmod_timeM = bindec(substr($BINlastmod_time, 5, 6)); + $lastmod_timeS = bindec(substr($BINlastmod_time, 11, 5)); + + // Mount file table + $i = Array( + 'file_name' =>$file['file_name'], + 'compression_method'=>$file['compression_method'][1], + 'version_needed' =>$file['version_needed'][1], + 'lastmod_datetime' =>mktime($lastmod_timeH, $lastmod_timeM, $lastmod_timeS, $lastmod_dateM, $lastmod_dateD, $lastmod_dateY), + 'crc-32' =>str_pad(dechex(ord($file['crc-32'][3])), 2, '0', STR_PAD_LEFT). + str_pad(dechex(ord($file['crc-32'][2])), 2, '0', STR_PAD_LEFT). + str_pad(dechex(ord($file['crc-32'][1])), 2, '0', STR_PAD_LEFT). + str_pad(dechex(ord($file['crc-32'][0])), 2, '0', STR_PAD_LEFT), + 'compressed_size' =>$file['compressed_size'][1], + 'uncompressed_size' =>$file['uncompressed_size'][1], + 'extra_field' =>$file['extra_field'], + 'general_bit_flag' =>str_pad(decbin($file['general_bit_flag'][1]), 8, '0', STR_PAD_LEFT), + 'contents-startOffset'=>$file['contents-startOffset'] + ); + return $i; + } + return false; + } +} + + + + + + diff --git a/src/admin/application/libs/dZip.inc.php b/src/admin/application/libs/dZip.inc.php new file mode 100644 index 0000000..08d4612 --- /dev/null +++ b/src/admin/application/libs/dZip.inc.php @@ -0,0 +1,146 @@ +<?php +class dZip{ + var $filename; + var $overwrite; + + var $zipSignature = "\x50\x4b\x03\x04"; // local file header signature + var $dirSignature = "\x50\x4b\x01\x02"; // central dir header signature + var $dirSignatureE= "\x50\x4b\x05\x06"; // end of central dir signature + var $files_count = 0; + var $fh; + + Function dZip($filename, $overwrite=true){ + $this->filename = $filename; + $this->overwrite = $overwrite; + } + Function addDir($dirname, $fileComments=''){ + if(substr($dirname, -1) != '/') + $dirname .= '/'; + $this->addFile(false, $dirname, $fileComments); + } + Function addFile($filename, $cfilename, $fileComments='', $data=false){ + if(!($fh = &$this->fh)) + $fh = fopen($this->filename, $this->overwrite?'wb':'a+b'); + + // $filename can be a local file OR the data wich will be compressed + if(substr($cfilename, -1)=='/'){ + $details['uncsize'] = 0; + $data = ''; + } + elseif(file_exists($filename)){ + $details['uncsize'] = filesize($filename); + $data = file_get_contents($filename); + } + elseif($filename){ + echo "<b>Cannot add $filename. File not found</b><br>"; + return false; + } + else{ + $details['uncsize'] = strlen($filename); + // DATA is given.. use it! :| + } + + // if data to compress is too small, just store it + if($details['uncsize'] < 256){ + $details['comsize'] = $details['uncsize']; + $details['vneeded'] = 10; + $details['cmethod'] = 0; + $zdata = &$data; + } + else{ // otherwise, compress it + $zdata = gzcompress($data); + $zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug (thanks to Eric Mueller) + $details['comsize'] = strlen($zdata); + $details['vneeded'] = 10; + $details['cmethod'] = 8; + } + + $details['bitflag'] = 0; + $details['crc_32'] = crc32($data); + + // Convert date and time to DOS Format, and set then + $lastmod_timeS = str_pad(decbin(date('s')>=32?date('s')-32:date('s')), 5, '0', STR_PAD_LEFT); + $lastmod_timeM = str_pad(decbin(date('i')), 6, '0', STR_PAD_LEFT); + $lastmod_timeH = str_pad(decbin(date('H')), 5, '0', STR_PAD_LEFT); + $lastmod_dateD = str_pad(decbin(date('d')), 5, '0', STR_PAD_LEFT); + $lastmod_dateM = str_pad(decbin(date('m')), 4, '0', STR_PAD_LEFT); + $lastmod_dateY = str_pad(decbin(date('Y')-1980), 7, '0', STR_PAD_LEFT); + + # echo "ModTime: $lastmod_timeS-$lastmod_timeM-$lastmod_timeH (".date("s H H").")\n"; + # echo "ModDate: $lastmod_dateD-$lastmod_dateM-$lastmod_dateY (".date("d m Y").")\n"; + $details['modtime'] = bindec("$lastmod_timeH$lastmod_timeM$lastmod_timeS"); + $details['moddate'] = bindec("$lastmod_dateY$lastmod_dateM$lastmod_dateD"); + + $details['offset'] = ftell($fh); + fwrite($fh, $this->zipSignature); + fwrite($fh, pack('s', $details['vneeded'])); // version_needed + fwrite($fh, pack('s', $details['bitflag'])); // general_bit_flag + fwrite($fh, pack('s', $details['cmethod'])); // compression_method + fwrite($fh, pack('s', $details['modtime'])); // lastmod_time + fwrite($fh, pack('s', $details['moddate'])); // lastmod_date + fwrite($fh, pack('V', $details['crc_32'])); // crc-32 + fwrite($fh, pack('I', $details['comsize'])); // compressed_size + fwrite($fh, pack('I', $details['uncsize'])); // uncompressed_size + fwrite($fh, pack('s', strlen($cfilename))); // file_name_length + fwrite($fh, pack('s', 0)); // extra_field_length + fwrite($fh, $cfilename); // file_name + // ignoring extra_field + fwrite($fh, $zdata); + + // Append it to central dir + $details['external_attributes'] = (substr($cfilename, -1)=='/'&&!$zdata)?16:32; // Directory or file name + $details['comments'] = $fileComments; + $this->appendCentralDir($cfilename, $details); + $this->files_count++; + } + Function setExtra($filename, $property, $value){ + $this->centraldirs[$filename][$property] = $value; + } + Function save($zipComments=''){ + if(!($fh = &$this->fh)) + $fh = fopen($this->filename, $this->overwrite?'w':'a+'); + + $cdrec = ""; + foreach($this->centraldirs as $filename=>$cd){ + $cdrec .= $this->dirSignature; + $cdrec .= "\x0\x0"; // version made by + $cdrec .= pack('v', $cd['vneeded']); // version needed to extract + $cdrec .= "\x0\x0"; // general bit flag + $cdrec .= pack('v', $cd['cmethod']); // compression method + $cdrec .= pack('v', $cd['modtime']); // lastmod time + $cdrec .= pack('v', $cd['moddate']); // lastmod date + $cdrec .= pack('V', $cd['crc_32']); // crc32 + $cdrec .= pack('V', $cd['comsize']); // compressed filesize + $cdrec .= pack('V', $cd['uncsize']); // uncompressed filesize + $cdrec .= pack('v', strlen($filename)); // file comment length + $cdrec .= pack('v', 0); // extra field length + $cdrec .= pack('v', strlen($cd['comments'])); // file comment length + $cdrec .= pack('v', 0); // disk number start + $cdrec .= pack('v', 0); // internal file attributes + $cdrec .= pack('V', $cd['external_attributes']); // internal file attributes + $cdrec .= pack('V', $cd['offset']); // relative offset of local header + $cdrec .= $filename; + $cdrec .= $cd['comments']; + } + $before_cd = ftell($fh); + fwrite($fh, $cdrec); + + // end of central dir + fwrite($fh, $this->dirSignatureE); + fwrite($fh, pack('v', 0)); // number of this disk + fwrite($fh, pack('v', 0)); // number of the disk with the start of the central directory + fwrite($fh, pack('v', $this->files_count)); // total # of entries "on this disk" + fwrite($fh, pack('v', $this->files_count)); // total # of entries overall + fwrite($fh, pack('V', strlen($cdrec))); // size of central dir + fwrite($fh, pack('V', $before_cd)); // offset to start of central dir + fwrite($fh, pack('v', strlen($zipComments))); // .zip file comment length + fwrite($fh, $zipComments); + + fclose($fh); + } + + // Private + Function appendCentralDir($filename,$properties){ + $this->centraldirs[$filename] = $properties; + } +} diff --git a/src/admin/application/libs/phpqrcode/CHANGELOG b/src/admin/application/libs/phpqrcode/CHANGELOG new file mode 100755 index 0000000..1088530 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/CHANGELOG @@ -0,0 +1,38 @@ +* 1.0.0 build 2010031920 + + - first public release + - help in readme, install + - cleanup ans separation of QRtools and QRspec + - now TCPDF binding requires minimal changes in TCPDF, having most of job + done in QRtools tcpdfBarcodeArray + - nicer QRtools::timeBenchmark output + - license and copyright notices in files + - indent cleanup - from tab to 4spc, keep it that way please :) + - sf project, repository, wiki + - simple code generator in index.php + +* 1.1.0 build 2010032113 + + - added merge tool wich generate merged version of code + located in phpqrcode.php + - splited qrconst.php from qrlib.php + +* 1.1.1 build 2010032405 + + - patch by Rick Seymour allowing saving PNG and displaying it at the same time + - added version info in VERSION file + - modified merge tool to include version info into generated file + - fixed e-mail in almost all head comments + +* 1.1.2 build 2010032722 + + - full integration with TCPDF thanks to Nicola Asuni, it's author + - fixed bug with alphanumeric encoding detection + +* 1.1.3 build 2010081807 + + - short opening tags replaced with standard ones + +* 1.1.4 build 2010100721 + + - added missing static keyword QRinput::check (found by Luke Brookhart, Onjax LLC) diff --git a/src/admin/application/libs/phpqrcode/INSTALL b/src/admin/application/libs/phpqrcode/INSTALL new file mode 100755 index 0000000..eac6b07 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/INSTALL @@ -0,0 +1,67 @@ +== REQUIREMENTS == + + * PHP5 + * PHP GD2 extension with JPEG and PNG support + +== INSTALLATION == + +If you want to recreate cache by yourself make sure cache directory is +writable and you have permisions to write into it. Also make sure you are +able to read files in it if you have cache option enabled + +== CONFIGURATION == + +Feel free to modify config constants in qrconfig.php file. Read about it in +provided comments and project wiki page (links in README file) + +== QUICK START == + +Notice: probably you should'nt use all of this in same script :) + +<?phpb + +//include only that one, rest required files will be included from it +include "qrlib.php" + +//write code into file, Error corection lecer is lowest, L (one form: L,M,Q,H) +//each code square will be 4x4 pixels (4x zoom) +//code will have 2 code squares white boundary around + +QRcode::png('PHP QR Code :)', 'test.png', 'L', 4, 2); + +//same as above but outputs file directly into browser (with appr. header etc.) +//all other settings are default +//WARNING! it should be FIRST and ONLY output generated by script, otherwise +//rest of output will land inside PNG binary, breaking it for sure +QRcode::png('PHP QR Code :)'); + +//show benchmark +QRtools::timeBenchmark(); + +//rebuild cache +QRtools::buildCache(); + +//code generated in text mode - as a binary table +//then displayed out as HTML using Unicode block building chars :) +$tab = $qr->encode('PHP QR Code :)'); +QRspec::debug($tab, true); + +== TCPDF INTEGRATION == + +Inside bindings/tcpdf you will find slightly modified 2dbarcodes.php. +Instal phpqrcode liblaty inside tcpdf folder, then overwrite (or merge) +2dbarcodes.php + +Then use similar as example #50 from TCPDF examples: + +<?php + +$style = array( + 'border' => true, + 'padding' => 4, + 'fgcolor' => array(0,0,0), + 'bgcolor' => false, //array(255,255,255) +); + +//code name: QR, specify error correction level after semicolon (L,M,Q,H) +$pdf->write2DBarcode('PHP QR Code :)', 'QR,L', '', '', 30, 30, $style, 'N'); diff --git a/src/admin/application/libs/phpqrcode/LICENSE b/src/admin/application/libs/phpqrcode/LICENSE new file mode 100755 index 0000000..1883303 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/src/admin/application/libs/phpqrcode/README b/src/admin/application/libs/phpqrcode/README new file mode 100755 index 0000000..a022fb5 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/README @@ -0,0 +1,45 @@ +This is PHP implementation of QR Code 2-D barcode generator. It is pure-php +LGPL-licensed implementation based on C libqrencode by Kentaro Fukuchi. + +== LICENSING == + +Copyright (C) 2010 by Dominik Dzienia + +This library is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the Free +Software Foundation; either version 3 of the License, or any later version. + +This library is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU Lesser General Public License (LICENSE file) +for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this library; if not, write to the Free Software Foundation, Inc., 51 +Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +== INSTALATION AND USAGE == + + * INSTALL file + * http://sourceforge.net/apps/mediawiki/phpqrcode/index.php?title=Main_Page + +== CONTACT == + +Fell free to contact me via e-mail (deltalab at poczta dot fm) or using +folowing project pages: + + * http://sourceforge.net/projects/phpqrcode/ + * http://phpqrcode.sourceforge.net/ + +== ACKNOWLEDGMENTS == + +Based on C libqrencode library (ver. 3.1.1) +Copyright (C) 2006-2010 by Kentaro Fukuchi +http://megaui.net/fukuchi/works/qrencode/index.en.html + +QR Code is registered trademarks of DENSO WAVE INCORPORATED in JAPAN and other +countries. + +Reed-Solomon code encoder is written by Phil Karn, KA9Q. +Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/VERSION b/src/admin/application/libs/phpqrcode/VERSION new file mode 100755 index 0000000..9f99279 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/VERSION @@ -0,0 +1,2 @@ +1.1.4 +2010100721 \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/bindings/tcpdf/qrcode.php b/src/admin/application/libs/phpqrcode/bindings/tcpdf/qrcode.php new file mode 100755 index 0000000..7995460 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/bindings/tcpdf/qrcode.php @@ -0,0 +1,2875 @@ +<?php +//============================================================+ +// File name : qrcode.php +// Begin : 2010-03-22 +// Last Update : 2010-03-29 +// Version : 1.0.002 +// License : GNU LGPL v.3 (http://www.gnu.org/copyleft/lesser.html) +// ---------------------------------------------------------------------------- +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// or browse http://www.gnu.org/copyleft/lesser.html +// +// ---------------------------------------------------------------------------- +// +// DESCRIPTION : +// +// Class to create QR-code arrays for TCPDF class. +// QR Code symbol is a 2D barcode that can be scanned by +// handy terminals such as a mobile phone with CCD. +// The capacity of QR Code is up to 7000 digits or 4000 +// characters, and has high robustness. +// This class supports QR Code model 2, described in +// JIS (Japanese Industrial Standards) X0510:2004 +// or ISO/IEC 18004. +// Currently the following features are not supported: +// ECI and FNC1 mode, Micro QR Code, QR Code model 1, +// Structured mode. +// +// This class is derived from the following projects: +// --------------------------------------------------------- +// "PHP QR Code encoder" +// License: GNU-LGPLv3 +// Copyright (C) 2010 by Dominik Dzienia <deltalab at poczta dot fm> +// http://phpqrcode.sourceforge.net/ +// https://sourceforge.net/projects/phpqrcode/ +// +// The "PHP QR Code encoder" is based on +// "C libqrencode library" (ver. 3.1.1) +// License: GNU-LGPL 2.1 +// Copyright (C) 2006-2010 by Kentaro Fukuchi +// http://megaui.net/fukuchi/works/qrencode/index.en.html +// +// Reed-Solomon code encoder is written by Phil Karn, KA9Q. +// Copyright (C) 2002-2006 Phil Karn, KA9Q +// +// QR Code is registered trademark of DENSO WAVE INCORPORATED +// http://www.denso-wave.com/qrcode/index-e.html +// --------------------------------------------------------- +// +// Author: Nicola Asuni +// +// (c) Copyright 2010: +// Nicola Asuni +// Tecnick.com S.r.l. +// Via della Pace, 11 +// 09044 Quartucciu (CA) +// ITALY +// www.tecnick.com +// info@tecnick.com +//============================================================+ + +/** + * Class to create QR-code arrays for TCPDF class. + * QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD. + * The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness. + * This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004. + * Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode. + * + * This class is derived from "PHP QR Code encoder" by Dominik Dzienia (http://phpqrcode.sourceforge.net/) based on "libqrencode C library 3.1.1." by Kentaro Fukuchi (http://megaui.net/fukuchi/works/qrencode/index.en.html), contains Reed-Solomon code written by Phil Karn, KA9Q. QR Code is registered trademark of DENSO WAVE INCORPORATED (http://www.denso-wave.com/qrcode/index-e.html). + * Please read comments on this class source file for full copyright and license information. + * + * @package com.tecnick.tcpdf + * @abstract Class for generating QR-code array for TCPDF. + * @author Nicola Asuni + * @copyright 2010 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com + * @link http://www.tcpdf.org + * @license http://www.gnu.org/copyleft/lesser.html LGPL + * @version 1.0.002 + */ + +// definitions +if (!defined('QRCODEDEFS')) { + + /** + * Indicate that definitions for this class are set + */ + define('QRCODEDEFS', true); + + // ----------------------------------------------------- + + // Encoding modes (characters which can be encoded in QRcode) + + /** + * Encoding mode + */ + define('QR_MODE_NL', -1); + + /** + * Encoding mode numeric (0-9). 3 characters are encoded to 10bit length. In theory, 7089 characters or less can be stored in a QRcode. + */ + define('QR_MODE_NM', 0); + + /** + * Encoding mode alphanumeric (0-9A-Z $%*+-./:) 45characters. 2 characters are encoded to 11bit length. In theory, 4296 characters or less can be stored in a QRcode. + */ + define('QR_MODE_AN', 1); + + /** + * Encoding mode 8bit byte data. In theory, 2953 characters or less can be stored in a QRcode. + */ + define('QR_MODE_8B', 2); + + /** + * Encoding mode KANJI. A KANJI character (multibyte character) is encoded to 13bit length. In theory, 1817 characters or less can be stored in a QRcode. + */ + define('QR_MODE_KJ', 3); + + /** + * Encoding mode STRUCTURED (currently unsupported) + */ + define('QR_MODE_ST', 4); + + // ----------------------------------------------------- + + // Levels of error correction. + // QRcode has a function of an error correcting for miss reading that white is black. + // Error correcting is defined in 4 level as below. + + /** + * Error correction level L : About 7% or less errors can be corrected. + */ + define('QR_ECLEVEL_L', 0); + + /** + * Error correction level M : About 15% or less errors can be corrected. + */ + define('QR_ECLEVEL_M', 1); + + /** + * Error correction level Q : About 25% or less errors can be corrected. + */ + define('QR_ECLEVEL_Q', 2); + + /** + * Error correction level H : About 30% or less errors can be corrected. + */ + define('QR_ECLEVEL_H', 3); + + // ----------------------------------------------------- + + // Version. Size of QRcode is defined as version. + // Version is from 1 to 40. + // Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases. + // So version 40 is 177*177 matrix. + + /** + * Maximum QR Code version. + */ + define('QRSPEC_VERSION_MAX', 40); + + /** + * Maximum matrix size for maximum version (version 40 is 177*177 matrix). + */ + define('QRSPEC_WIDTH_MAX', 177); + + // ----------------------------------------------------- + + /** + * Matrix index to get width from $capacity array. + */ + define('QRCAP_WIDTH', 0); + + /** + * Matrix index to get number of words from $capacity array. + */ + define('QRCAP_WORDS', 1); + + /** + * Matrix index to get remainder from $capacity array. + */ + define('QRCAP_REMINDER', 2); + + /** + * Matrix index to get error correction level from $capacity array. + */ + define('QRCAP_EC', 3); + + // ----------------------------------------------------- + + // Structure (currently usupported) + + /** + * Number of header bits for structured mode + */ + define('STRUCTURE_HEADER_BITS', 20); + + /** + * Max number of symbols for structured mode + */ + define('MAX_STRUCTURED_SYMBOLS', 16); + + // ----------------------------------------------------- + + // Masks + + /** + * Down point base value for case 1 mask pattern (concatenation of same color in a line or a column) + */ + define('N1', 3); + + /** + * Down point base value for case 2 mask pattern (module block of same color) + */ + define('N2', 3); + + /** + * Down point base value for case 3 mask pattern (1:1:3:1:1(dark:bright:dark:bright:dark)pattern in a line or a column) + */ + define('N3', 40); + + /** + * Down point base value for case 4 mask pattern (ration of dark modules in whole) + */ + define('N4', 10); + + // ----------------------------------------------------- + + // Optimization settings + + /** + * if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code + */ + define('QR_FIND_BEST_MASK', true); + + /** + * if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly + */ + define('QR_FIND_FROM_RANDOM', 2); + + /** + * when QR_FIND_BEST_MASK === false + */ + define('QR_DEFAULT_MASK', 2); + + // ----------------------------------------------------- + +} // end of definitions + +// #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# + +if (!class_exists('QRcode', false)) { + + // for compaibility with PHP4 + if (!function_exists('str_split')) { + /** + * Convert a string to an array (needed for PHP4 compatibility) + * @param string $string The input string. + * @param int $split_length Maximum length of the chunk. + * @return If the optional split_length parameter is specified, the returned array will be broken down into chunks with each being split_length in length, otherwise each chunk will be one character in length. FALSE is returned if split_length is less than 1. If the split_length length exceeds the length of string , the entire string is returned as the first (and only) array element. + */ + function str_split($string, $split_length=1) { + if ((strlen($string) > $split_length) OR (!$split_length)) { + do { + $c = strlen($string); + $parts[] = substr($string, 0, $split_length); + $string = substr($string, $split_length); + } while ($string !== false); + } else { + $parts = array($string); + } + return $parts; + } + } + + // ##################################################### + + /** + * Class to create QR-code arrays for TCPDF class. + * QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD. + * The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness. + * This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004. + * Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode. + * + * This class is derived from "PHP QR Code encoder" by Dominik Dzienia (http://phpqrcode.sourceforge.net/) based on "libqrencode C library 3.1.1." by Kentaro Fukuchi (http://megaui.net/fukuchi/works/qrencode/index.en.html), contains Reed-Solomon code written by Phil Karn, KA9Q. QR Code is registered trademark of DENSO WAVE INCORPORATED (http://www.denso-wave.com/qrcode/index-e.html). + * Please read comments on this class source file for full copyright and license information. + * + * @name QRcode + * @package com.tecnick.tcpdf + * @abstract Class for generating QR-code array for TCPDF. + * @author Nicola Asuni + * @copyright 2010 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com + * @link http://www.tcpdf.org + * @license http://www.gnu.org/copyleft/lesser.html LGPL + * @version 1.0.002 + */ + class QRcode { + + /** + * @var barcode array to be returned which is readable by TCPDF + * @access protected + */ + protected $barcode_array = array(); + + /** + * @var QR code version. Size of QRcode is defined as version. Version is from 1 to 40. Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases. So version 40 is 177*177 matrix. + * @access protected + */ + protected $version = 0; + + /** + * @var Levels of error correction. See definitions for possible values. + * @access protected + */ + protected $level = QR_ECLEVEL_L; + + /** + * @var Encoding mode + * @access protected + */ + protected $hint = QR_MODE_8B; + + /** + * @var if true the input string will be converted to uppercase + * @access protected + */ + protected $casesensitive = true; + + /** + * @var structured QR code (not supported yet) + * @access protected + */ + protected $structured = 0; + + /** + * @var mask data + * @access protected + */ + protected $data; + + // FrameFiller + + /** + * @var width + * @access protected + */ + protected $width; + + /** + * @var frame + * @access protected + */ + protected $frame; + + /** + * @var X position of bit + * @access protected + */ + protected $x; + + /** + * @var Y position of bit + * @access protected + */ + protected $y; + + /** + * @var direction + * @access protected + */ + protected $dir; + + /** + * @var single bit + * @access protected + */ + protected $bit; + + // ---- QRrawcode ---- + + /** + * @var data code + * @access protected + */ + protected $datacode = array(); + + /** + * @var error correction code + * @access protected + */ + protected $ecccode = array(); + + /** + * @var blocks + * @access protected + */ + protected $blocks; + + /** + * @var Reed-Solomon blocks + * @access protected + */ + protected $rsblocks = array(); //of RSblock + + /** + * @var counter + * @access protected + */ + protected $count; + + /** + * @var data length + * @access protected + */ + protected $dataLength; + + /** + * @var error correction length + * @access protected + */ + protected $eccLength; + + /** + * @var b1 + * @access protected + */ + protected $b1; + + // ---- QRmask ---- + + /** + * @var run length + * @access protected + */ + protected $runLength = array(); + + // ---- QRsplit ---- + + /** + * @var input data string + * @access protected + */ + protected $dataStr = ''; + + /** + * @var input items + * @access protected + */ + protected $items; + + // Reed-Solomon items + + /** + * @var Reed-Solomon items + * @access protected + */ + protected $rsitems = array(); + + /** + * @var array of frames + * @access protected + */ + protected $frames = array(); + + /** + * @var alphabet-numeric convesion table + * @access protected + */ + protected $anTable = array( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // + ); + + /** + * @var array Table of the capacity of symbols + * See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004. + * @access protected + */ + protected $capacity = array( + array( 0, 0, 0, array( 0, 0, 0, 0)), // + array( 21, 26, 0, array( 7, 10, 13, 17)), // 1 + array( 25, 44, 7, array( 10, 16, 22, 28)), // + array( 29, 70, 7, array( 15, 26, 36, 44)), // + array( 33, 100, 7, array( 20, 36, 52, 64)), // + array( 37, 134, 7, array( 26, 48, 72, 88)), // 5 + array( 41, 172, 7, array( 36, 64, 96, 112)), // + array( 45, 196, 0, array( 40, 72, 108, 130)), // + array( 49, 242, 0, array( 48, 88, 132, 156)), // + array( 53, 292, 0, array( 60, 110, 160, 192)), // + array( 57, 346, 0, array( 72, 130, 192, 224)), // 10 + array( 61, 404, 0, array( 80, 150, 224, 264)), // + array( 65, 466, 0, array( 96, 176, 260, 308)), // + array( 69, 532, 0, array( 104, 198, 288, 352)), // + array( 73, 581, 3, array( 120, 216, 320, 384)), // + array( 77, 655, 3, array( 132, 240, 360, 432)), // 15 + array( 81, 733, 3, array( 144, 280, 408, 480)), // + array( 85, 815, 3, array( 168, 308, 448, 532)), // + array( 89, 901, 3, array( 180, 338, 504, 588)), // + array( 93, 991, 3, array( 196, 364, 546, 650)), // + array( 97, 1085, 3, array( 224, 416, 600, 700)), // 20 + array(101, 1156, 4, array( 224, 442, 644, 750)), // + array(105, 1258, 4, array( 252, 476, 690, 816)), // + array(109, 1364, 4, array( 270, 504, 750, 900)), // + array(113, 1474, 4, array( 300, 560, 810, 960)), // + array(117, 1588, 4, array( 312, 588, 870, 1050)), // 25 + array(121, 1706, 4, array( 336, 644, 952, 1110)), // + array(125, 1828, 4, array( 360, 700, 1020, 1200)), // + array(129, 1921, 3, array( 390, 728, 1050, 1260)), // + array(133, 2051, 3, array( 420, 784, 1140, 1350)), // + array(137, 2185, 3, array( 450, 812, 1200, 1440)), // 30 + array(141, 2323, 3, array( 480, 868, 1290, 1530)), // + array(145, 2465, 3, array( 510, 924, 1350, 1620)), // + array(149, 2611, 3, array( 540, 980, 1440, 1710)), // + array(153, 2761, 3, array( 570, 1036, 1530, 1800)), // + array(157, 2876, 0, array( 570, 1064, 1590, 1890)), // 35 + array(161, 3034, 0, array( 600, 1120, 1680, 1980)), // + array(165, 3196, 0, array( 630, 1204, 1770, 2100)), // + array(169, 3362, 0, array( 660, 1260, 1860, 2220)), // + array(173, 3532, 0, array( 720, 1316, 1950, 2310)), // + array(177, 3706, 0, array( 750, 1372, 2040, 2430)) // 40 + ); + + /** + * @var array Length indicator + * @access protected + */ + protected $lengthTableBits = array( + array(10, 12, 14), + array( 9, 11, 13), + array( 8, 16, 16), + array( 8, 10, 12) + ); + + /** + * @var array Table of the error correction code (Reed-Solomon block) + * See Table 12-16 (pp.30-36), JIS X0510:2004. + * @access protected + */ + protected $eccTable = array( + array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)), // + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1 + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // + array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)), // + array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)), // + array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5 + array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)), // + array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)), // + array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)), // + array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)), // + array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), // 10 + array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)), // + array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)), // + array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)), // + array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)), // + array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), // 15 + array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)), // + array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)), // + array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)), // + array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)), // + array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), // 20 + array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)), // + array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)), // + array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)), // + array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)), // + array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), // 25 + array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)), // + array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)), // + array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)), // + array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)), // + array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), // 30 + array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)), // + array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)), // + array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)), // + array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)), // + array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), // 35 + array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)), // + array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)), // + array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)), // + array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)), // + array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)) // 40 + ); + + /** + * @var array Positions of alignment patterns. + * This array includes only the second and the third position of the alignment patterns. Rest of them can be calculated from the distance between them. + * See Table 1 in Appendix E (pp.71) of JIS X0510:2004. + * @access protected + */ + protected $alignmentPattern = array( + array( 0, 0), + array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5 + array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10 + array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), // 11-15 + array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), // 16-20 + array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), // 21-25 + array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), // 26-30 + array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), // 31-35 + array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58) // 35-40 + ); + + /** + * @var array Version information pattern (BCH coded). + * See Table 1 in Appendix D (pp.68) of JIS X0510:2004. + * size: [QRSPEC_VERSION_MAX - 6] + * @access protected + */ + protected $versionPattern = array( + 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, // + 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, // + 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, // + 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, // + 0x27541, 0x28c69 + ); + + /** + * @var array Format information + * @access protected + */ + protected $formatInfo = array( + array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), // + array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0), // + array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed), // + array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b) // + ); + + + // ------------------------------------------------- + // ------------------------------------------------- + + + /** + * This is the class constructor. + * Creates a QRcode object + * @param string $code code to represent using QRcode + * @param string $eclevel error level: <ul><li>L : About 7% or less errors can be corrected.</li><li>M : About 15% or less errors can be corrected.</li><li>Q : About 25% or less errors can be corrected.</li><li>H : About 30% or less errors can be corrected.</li></ul> + * @access public + * @since 1.0.000 + */ + public function __construct($code, $eclevel = 'L') { + $barcode_array = array(); + if ((is_null($code)) OR ($code == '\0') OR ($code == '')) { + return false; + } + // set error correction level + $this->level = array_search($eclevel, array('L', 'M', 'Q', 'H')); + if ($this->level === false) { + $this->level = QR_ECLEVEL_L; + } + if (($this->hint != QR_MODE_8B) AND ($this->hint != QR_MODE_KJ)) { + return false; + } + if (($this->version < 0) OR ($this->version > QRSPEC_VERSION_MAX)) { + return false; + } + $this->items = array(); + $this->encodeString($code); + $qrTab = $this->binarize($this->data); + $size = count($qrTab); + $barcode_array['num_rows'] = $size; + $barcode_array['num_cols'] = $size; + $barcode_array['bcode'] = array(); + foreach ($qrTab as $line) { + $arrAdd = array(); + foreach (str_split($line) as $char) { + $arrAdd[] = ($char=='1')?1:0; + } + $barcode_array['bcode'][] = $arrAdd; + } + $this->barcode_array = $barcode_array; + } + + /** + * Returns a barcode array which is readable by TCPDF + * @return array barcode array readable by TCPDF; + * @access public + */ + public function getBarcodeArray() { + return $this->barcode_array; + } + + /** + * Convert the frame in binary form + * @param array $frame array to binarize + * @return array frame in binary form + */ + protected function binarize($frame) { + $len = count($frame); + // the frame is square (width = height) + foreach ($frame as &$frameLine) { + for ($i=0; $i<$len; $i++) { + $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0'; + } + } + return $frame; + } + + /** + * Encode the input string to QR code + * @param string $string input string to encode + */ + protected function encodeString($string) { + $this->dataStr = $string; + if (!$this->casesensitive) { + $this->toUpper(); + } + $ret = $this->splitString(); + if ($ret < 0) { + return NULL; + } + $this->encodeMask(-1); + } + + /** + * Encode mask + * @param int $mask masking mode + */ + protected function encodeMask($mask) { + $spec = array(0, 0, 0, 0, 0); + $this->datacode = $this->getByteStream($this->items); + if (is_null($this->datacode)) { + return NULL; + } + $spec = $this->getEccSpec($this->version, $this->level, $spec); + $this->b1 = $this->rsBlockNum1($spec); + $this->dataLength = $this->rsDataLength($spec); + $this->eccLength = $this->rsEccLength($spec); + $this->ecccode = array_fill(0, $this->eccLength, 0); + $this->blocks = $this->rsBlockNum($spec); + $ret = $this->init($spec); + if ($ret < 0) { + return NULL; + } + $this->count = 0; + $this->width = $this->getWidth($this->version); + $this->frame = $this->newFrame($this->version); + $this->x = $this->width - 1; + $this->y = $this->width - 1; + $this->dir = -1; + $this->bit = -1; + // inteleaved data and ecc codes + for ($i=0; $i < ($this->dataLength + $this->eccLength); $i++) { + $code = $this->getCode(); + $bit = 0x80; + for ($j=0; $j<8; $j++) { + $addr = $this->getNextPosition(); + $this->setFrameAt($addr, 0x02 | (($bit & $code) != 0)); + $bit = $bit >> 1; + } + } + // remainder bits + $j = $this->getRemainder($this->version); + for ($i=0; $i<$j; $i++) { + $addr = $this->getNextPosition(); + $this->setFrameAt($addr, 0x02); + } + // masking + $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0); + if ($mask < 0) { + if (QR_FIND_BEST_MASK) { + $masked = $this->mask($this->width, $this->frame, $this->level); + } else { + $masked = $this->makeMask($this->width, $this->frame, (intval(QR_DEFAULT_MASK) % 8), $this->level); + } + } else { + $masked = $this->makeMask($this->width, $this->frame, $mask, $this->level); + } + if ($masked == NULL) { + return NULL; + } + $this->data = $masked; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // FrameFiller + + /** + * Set frame value at specified position + * @param array $at x,y position + * @param int $val value of the character to set + */ + protected function setFrameAt($at, $val) { + $this->frame[$at['y']][$at['x']] = chr($val); + } + + /** + * Get frame value at specified position + * @param array $at x,y position + * @return value at specified position + */ + protected function getFrameAt($at) { + return ord($this->frame[$at['y']][$at['x']]); + } + + /** + * Return the next frame position + * @return array of x,y coordinates + */ + protected function getNextPosition() { + do { + if ($this->bit == -1) { + $this->bit = 0; + return array('x'=>$this->x, 'y'=>$this->y); + } + $x = $this->x; + $y = $this->y; + $w = $this->width; + if ($this->bit == 0) { + $x--; + $this->bit++; + } else { + $x++; + $y += $this->dir; + $this->bit--; + } + if ($this->dir < 0) { + if ($y < 0) { + $y = 0; + $x -= 2; + $this->dir = 1; + if ($x == 6) { + $x--; + $y = 9; + } + } + } else { + if ($y == $w) { + $y = $w - 1; + $x -= 2; + $this->dir = -1; + if ($x == 6) { + $x--; + $y -= 8; + } + } + } + if (($x < 0) OR ($y < 0)) { + return NULL; + } + $this->x = $x; + $this->y = $y; + } while(ord($this->frame[$y][$x]) & 0x80); + return array('x'=>$x, 'y'=>$y); + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRrawcode + + /** + * Initialize code. + * @param array $spec array of ECC specification + * @return 0 in case of success, -1 in case of error + */ + protected function init($spec) { + $dl = $this->rsDataCodes1($spec); + $el = $this->rsEccCodes1($spec); + $rs = $this->init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + $blockNo = 0; + $dataPos = 0; + $eccPos = 0; + $endfor = $this->rsBlockNum1($spec); + for ($i=0; $i < $endfor; ++$i) { + $ecc = array_slice($this->ecccode, $eccPos); + $this->rsblocks[$blockNo] = array(); + $this->rsblocks[$blockNo]['dataLength'] = $dl; + $this->rsblocks[$blockNo]['data'] = array_slice($this->datacode, $dataPos); + $this->rsblocks[$blockNo]['eccLength'] = $el; + $ecc = $this->encode_rs_char($rs, $this->rsblocks[$blockNo]['data'], $ecc); + $this->rsblocks[$blockNo]['ecc'] = $ecc; + $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + if ($this->rsBlockNum2($spec) == 0) { + return 0; + } + $dl = $this->rsDataCodes2($spec); + $el = $this->rsEccCodes2($spec); + $rs = $this->init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + if ($rs == NULL) { + return -1; + } + $endfor = $this->rsBlockNum2($spec); + for ($i=0; $i < $endfor; ++$i) { + $ecc = array_slice($this->ecccode, $eccPos); + $this->rsblocks[$blockNo] = array(); + $this->rsblocks[$blockNo]['dataLength'] = $dl; + $this->rsblocks[$blockNo]['data'] = array_slice($this->datacode, $dataPos); + $this->rsblocks[$blockNo]['eccLength'] = $el; + $ecc = $this->encode_rs_char($rs, $this->rsblocks[$blockNo]['data'], $ecc); + $this->rsblocks[$blockNo]['ecc'] = $ecc; + $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc); + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + return 0; + } + + /** + * Return Reed-Solomon block code. + * @return array rsblocks + */ + protected function getCode() { + if ($this->count < $this->dataLength) { + $row = $this->count % $this->blocks; + $col = $this->count / $this->blocks; + if ($col >= $this->rsblocks[0]['dataLength']) { + $row += $this->b1; + } + $ret = $this->rsblocks[$row]['data'][$col]; + } elseif ($this->count < $this->dataLength + $this->eccLength) { + $row = ($this->count - $this->dataLength) % $this->blocks; + $col = ($this->count - $this->dataLength) / $this->blocks; + $ret = $this->rsblocks[$row]['ecc'][$col]; + } else { + return 0; + } + $this->count++; + return $ret; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRmask + + /** + * Write Format Information on frame and returns the number of black bits + * @param int $width frame width + * @param array $frame frame + * @param array $mask masking mode + * @param int $level error correction level + * @return int blacks + */ + protected function writeFormatInformation($width, &$frame, $mask, $level) { + $blacks = 0; + $format = $this->getFormatInfo($mask, $level); + for ($i=0; $i<8; ++$i) { + if ($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + $frame[8][$width - 1 - $i] = chr($v); + if ($i < 6) { + $frame[$i][8] = chr($v); + } else { + $frame[$i + 1][8] = chr($v); + } + $format = $format >> 1; + } + for ($i=0; $i<7; ++$i) { + if ($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + $frame[$width - 7 + $i][8] = chr($v); + if ($i == 0) { + $frame[8][7] = chr($v); + } else { + $frame[8][6 - $i] = chr($v); + } + $format = $format >> 1; + } + return $blacks; + } + + /** + * mask0 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask0($x, $y) { + return ($x + $y) & 1; + } + + /** + * mask1 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask1($x, $y) { + return ($y & 1); + } + + /** + * mask2 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask2($x, $y) { + return ($x % 3); + } + + /** + * mask3 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask3($x, $y) { + return ($x + $y) % 3; + } + + /** + * mask4 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask4($x, $y) { + return (((int)($y / 2)) + ((int)($x / 3))) & 1; + } + + /** + * mask5 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask5($x, $y) { + return (($x * $y) & 1) + ($x * $y) % 3; + } + + /** + * mask6 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask6($x, $y) { + return ((($x * $y) & 1) + ($x * $y) % 3) & 1; + } + + /** + * mask7 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask7($x, $y) { + return ((($x * $y) % 3) + (($x + $y) & 1)) & 1; + } + + /** + * Return bitmask + * @param int $maskNo mask number + * @param int $width width + * @param array $frame frame + * @return array bitmask + */ + protected function generateMaskNo($maskNo, $width, $frame) { + $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); + for ($y=0; $y<$width; ++$y) { + for ($x=0; $x<$width; ++$x) { + if (ord($frame[$y][$x]) & 0x80) { + $bitMask[$y][$x] = 0; + } else { + $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y); + $bitMask[$y][$x] = ($maskFunc == 0)?1:0; + } + } + } + return $bitMask; + } + + /** + * makeMaskNo + * @param int $maskNo + * @param int $width + * @param int $s + * @param int $d + * @param boolean $maskGenOnly + * @return int b + */ + protected function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly=false) { + $b = 0; + $bitMask = array(); + $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); + if ($maskGenOnly) { + return; + } + $d = $s; + for ($y=0; $y<$width; ++$y) { + for ($x=0; $x<$width; ++$x) { + if ($bitMask[$y][$x] == 1) { + $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]); + } + $b += (int)(ord($d[$y][$x]) & 1); + } + } + return $b; + } + + /** + * makeMask + * @param int $width + * @param array $frame + * @param int $maskNo + * @param int $level + * @return array mask + */ + protected function makeMask($width, $frame, $maskNo, $level) { + $masked = array_fill(0, $width, str_repeat("\0", $width)); + $this->makeMaskNo($maskNo, $width, $frame, $masked); + $this->writeFormatInformation($width, $masked, $maskNo, $level); + return $masked; + } + + /** + * calcN1N3 + * @param int $length + * @return int demerit + */ + protected function calcN1N3($length) { + $demerit = 0; + for ($i=0; $i<$length; ++$i) { + if ($this->runLength[$i] >= 5) { + $demerit += (N1 + ($this->runLength[$i] - 5)); + } + if ($i & 1) { + if (($i >= 3) AND ($i < ($length-2)) AND ($this->runLength[$i] % 3 == 0)) { + $fact = (int)($this->runLength[$i] / 3); + if (($this->runLength[$i-2] == $fact) + AND ($this->runLength[$i-1] == $fact) + AND ($this->runLength[$i+1] == $fact) + AND ($this->runLength[$i+2] == $fact)) { + if (($this->runLength[$i-3] < 0) OR ($this->runLength[$i-3] >= (4 * $fact))) { + $demerit += N3; + } elseif ((($i+3) >= $length) OR ($this->runLength[$i+3] >= (4 * $fact))) { + $demerit += N3; + } + } + } + } + } + return $demerit; + } + + /** + * evaluateSymbol + * @param int $width + * @param array $frame + * @return int demerit + */ + protected function evaluateSymbol($width, $frame) { + $head = 0; + $demerit = 0; + for ($y=0; $y<$width; ++$y) { + $head = 0; + $this->runLength[0] = 1; + $frameY = $frame[$y]; + if ($y > 0) { + $frameYM = $frame[$y-1]; + } + for ($x=0; $x<$width; ++$x) { + if (($x > 0) AND ($y > 0)) { + $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]); + $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]); + if (($b22 | ($w22 ^ 1)) & 1) { + $demerit += N2; + } + } + if (($x == 0) AND (ord($frameY[$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } elseif ($x > 0) { + if ((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + $demerit += $this->calcN1N3($head+1); + } + for ($x=0; $x<$width; ++$x) { + $head = 0; + $this->runLength[0] = 1; + for ($y=0; $y<$width; ++$y) { + if (($y == 0) AND (ord($frame[$y][$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } elseif ($y > 0) { + if ((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + $demerit += $this->calcN1N3($head+1); + } + return $demerit; + } + + /** + * mask + * @param int $width + * @param array $frame + * @param int $level + * @return array best mask + */ + protected function mask($width, $frame, $level) { + $minDemerit = PHP_INT_MAX; + $bestMaskNum = 0; + $bestMask = array(); + $checked_masks = array(0, 1, 2, 3, 4, 5, 6, 7); + if (QR_FIND_FROM_RANDOM !== false) { + $howManuOut = 8 - (QR_FIND_FROM_RANDOM % 9); + for ($i = 0; $i < $howManuOut; ++$i) { + $remPos = rand (0, count($checked_masks)-1); + unset($checked_masks[$remPos]); + $checked_masks = array_values($checked_masks); + } + } + $bestMask = $frame; + foreach ($checked_masks as $i) { + $mask = array_fill(0, $width, str_repeat("\0", $width)); + $demerit = 0; + $blacks = 0; + $blacks = $this->makeMaskNo($i, $width, $frame, $mask); + $blacks += $this->writeFormatInformation($width, $mask, $i, $level); + $blacks = (int)(100 * $blacks / ($width * $width)); + $demerit = (int)((int)(abs($blacks - 50) / 5) * N4); + $demerit += $this->evaluateSymbol($width, $mask); + if ($demerit < $minDemerit) { + $minDemerit = $demerit; + $bestMask = $mask; + $bestMaskNum = $i; + } + } + return $bestMask; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRsplit + + /** + * Return true if the character at specified position is a number + * @param string $str string + * @param int $pos characted position + * @return boolean true of false + */ + protected function isdigitat($str, $pos) { + if ($pos >= strlen($str)) { + return false; + } + return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9'))); + } + + /** + * Return true if the character at specified position is an alphanumeric character + * @param string $str string + * @param int $pos characted position + * @return boolean true of false + */ + protected function isalnumat($str, $pos) { + if ($pos >= strlen($str)) { + return false; + } + return ($this->lookAnTable(ord($str[$pos])) >= 0); + } + + /** + * identifyMode + * @param int $pos + * @return int mode + */ + protected function identifyMode($pos) { + if ($pos >= strlen($this->dataStr)) { + return QR_MODE_NL; + } + $c = $this->dataStr[$pos]; + if ($this->isdigitat($this->dataStr, $pos)) { + return QR_MODE_NM; + } elseif ($this->isalnumat($this->dataStr, $pos)) { + return QR_MODE_AN; + } elseif ($this->hint == QR_MODE_KJ) { + if ($pos+1 < strlen($this->dataStr)) { + $d = $this->dataStr[$pos+1]; + $word = (ord($c) << 8) | ord($d); + if (($word >= 0x8140 && $word <= 0x9ffc) OR ($word >= 0xe040 && $word <= 0xebbf)) { + return QR_MODE_KJ; + } + } + } + return QR_MODE_8B; + } + + /** + * eatNum + * @return int run + */ + protected function eatNum() { + $ln = $this->lengthIndicator(QR_MODE_NM, $this->version); + $p = 0; + while($this->isdigitat($this->dataStr, $p)) { + $p++; + } + $run = $p; + $mode = $this->identifyMode($p); + if ($mode == QR_MODE_8B) { + $dif = $this->estimateBitsModeNum($run) + 4 + $ln + + $this->estimateBitsMode8(1) // + 4 + l8 + - $this->estimateBitsMode8($run + 1); // - 4 - l8 + if ($dif > 0) { + return $this->eat8(); + } + } + if ($mode == QR_MODE_AN) { + $dif = $this->estimateBitsModeNum($run) + 4 + $ln + + $this->estimateBitsModeAn(1) // + 4 + la + - $this->estimateBitsModeAn($run + 1);// - 4 - la + if ($dif > 0) { + return $this->eatAn(); + } + } + $this->items = $this->appendNewInputItem($this->items, QR_MODE_NM, $run, str_split($this->dataStr)); + return $run; + } + + /** + * eatAn + * @return int run + */ + protected function eatAn() { + $la = $this->lengthIndicator(QR_MODE_AN, $this->version); + $ln = $this->lengthIndicator(QR_MODE_NM, $this->version); + $p = 0; + while($this->isalnumat($this->dataStr, $p)) { + if ($this->isdigitat($this->dataStr, $p)) { + $q = $p; + while($this->isdigitat($this->dataStr, $q)) { + $q++; + } + $dif = $this->estimateBitsModeAn($p) // + 4 + la + + $this->estimateBitsModeNum($q - $p) + 4 + $ln + - $this->estimateBitsModeAn($q); // - 4 - la + if ($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + $run = $p; + if (!$this->isalnumat($this->dataStr, $p)) { + $dif = $this->estimateBitsModeAn($run) + 4 + $la + + $this->estimateBitsMode8(1) // + 4 + l8 + - $this->estimateBitsMode8($run + 1); // - 4 - l8 + if ($dif > 0) { + return $this->eat8(); + } + } + $this->items = $this->appendNewInputItem($this->items, QR_MODE_AN, $run, str_split($this->dataStr)); + return $run; + } + + /** + * eatKanji + * @return int run + */ + protected function eatKanji() { + $p = 0; + while($this->identifyMode($p) == QR_MODE_KJ) { + $p += 2; + } + $this->items = $this->appendNewInputItem($this->items, QR_MODE_KJ, $p, str_split($this->dataStr)); + return $run; + } + + /** + * eat8 + * @return int run + */ + protected function eat8() { + $la = $this->lengthIndicator(QR_MODE_AN, $this->version); + $ln = $this->lengthIndicator(QR_MODE_NM, $this->version); + $p = 1; + $dataStrLen = strlen($this->dataStr); + while($p < $dataStrLen) { + $mode = $this->identifyMode($p); + if ($mode == QR_MODE_KJ) { + break; + } + if ($mode == QR_MODE_NM) { + $q = $p; + while($this->isdigitat($this->dataStr, $q)) { + $q++; + } + $dif = $this->estimateBitsMode8($p) // + 4 + l8 + + $this->estimateBitsModeNum($q - $p) + 4 + $ln + - $this->estimateBitsMode8($q); // - 4 - l8 + if ($dif < 0) { + break; + } else { + $p = $q; + } + } elseif ($mode == QR_MODE_AN) { + $q = $p; + while($this->isalnumat($this->dataStr, $q)) { + $q++; + } + $dif = $this->estimateBitsMode8($p) // + 4 + l8 + + $this->estimateBitsModeAn($q - $p) + 4 + $la + - $this->estimateBitsMode8($q); // - 4 - l8 + if ($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + $run = $p; + $this->items = $this->appendNewInputItem($this->items, QR_MODE_8B, $run, str_split($this->dataStr)); + return $run; + } + + /** + * splitString + */ + protected function splitString() { + while (strlen($this->dataStr) > 0) { + if ($this->dataStr == '') { + return 0; + } + $mode = $this->identifyMode(0); + switch ($mode) { + case QR_MODE_NM: { + $length = $this->eatNum(); + break; + } + case QR_MODE_AN: { + $length = $this->eatAn(); + break; + } + case QR_MODE_KJ: { + if ($hint == QR_MODE_KJ) { + $length = $this->eatKanji(); + } else { + $length = $this->eat8(); + } + break; + } + default: { + $length = $this->eat8(); + break; + } + } + if ($length == 0) { + return 0; + } + if ($length < 0) { + return -1; + } + $this->dataStr = substr($this->dataStr, $length); + } + } + + /** + * toUpper + */ + protected function toUpper() { + $stringLen = strlen($this->dataStr); + $p = 0; + while ($p < $stringLen) { + $mode = $this->identifyMode(substr($this->dataStr, $p), $this->hint); + if ($mode == QR_MODE_KJ) { + $p += 2; + } else { + if ((ord($this->dataStr[$p]) >= ord('a')) AND (ord($this->dataStr[$p]) <= ord('z'))) { + $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32); + } + $p++; + } + } + return $this->dataStr; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRinputItem + + /** + * newInputItem + * @param int $mode + * @param int $size + * @param array $data + * @param array $bstream + * @return array input item + */ + protected function newInputItem($mode, $size, $data, $bstream=null) { + $setData = array_slice($data, 0, $size); + if (count($setData) < $size) { + $setData = array_merge($setData, array_fill(0, ($size - count($setData)), 0)); + } + if (!$this->check($mode, $size, $setData)) { + return NULL; + } + $inputitem = array(); + $inputitem['mode'] = $mode; + $inputitem['size'] = $size; + $inputitem['data'] = $setData; + $inputitem['bstream'] = $bstream; + return $inputitem; + } + + /** + * encodeModeNum + * @param array $inputitem + * @param int $version + * @return array input item + */ + protected function encodeModeNum($inputitem, $version) { + $words = (int)($inputitem['size'] / 3); + $inputitem['bstream'] = array(); + $val = 0x1; + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, $val); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_NM, $version), $inputitem['size']); + for ($i=0; $i < $words; ++$i) { + $val = (ord($inputitem['data'][$i*3 ]) - ord('0')) * 100; + $val += (ord($inputitem['data'][$i*3+1]) - ord('0')) * 10; + $val += (ord($inputitem['data'][$i*3+2]) - ord('0')); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 10, $val); + } + if ($inputitem['size'] - $words * 3 == 1) { + $val = ord($inputitem['data'][$words*3]) - ord('0'); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, $val); + } elseif (($inputitem['size'] - ($words * 3)) == 2) { + $val = (ord($inputitem['data'][$words*3 ]) - ord('0')) * 10; + $val += (ord($inputitem['data'][$words*3+1]) - ord('0')); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 7, $val); + } + return $inputitem; + } + + /** + * encodeModeAn + * @param array $inputitem + * @param int $version + * @return array input item + */ + protected function encodeModeAn($inputitem, $version) { + $words = (int)($inputitem['size'] / 2); + $inputitem['bstream'] = array(); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x02); + $inputitem['bstream'] = $this->appendNum(v, $this->lengthIndicator(QR_MODE_AN, $version), $inputitem['size']); + for ($i=0; $i < $words; ++$i) { + $val = (int)$this->lookAnTable(ord($inputitem['data'][$i*2 ])) * 45; + $val += (int)$this->lookAnTable(ord($inputitem['data'][$i*2+1])); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 11, $val); + } + if ($inputitem['size'] & 1) { + $val = $this->lookAnTable(ord($inputitem['data'][($words * 2)])); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 6, $val); + } + return $inputitem; + } + + /** + * encodeMode8 + * @param array $inputitem + * @param int $version + * @return array input item + */ + protected function encodeMode8($inputitem, $version) { + $inputitem['bstream'] = array(); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x4); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_8B, $version), $inputitem['size']); + for ($i=0; $i < $inputitem['size']; ++$i) { + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 8, ord($inputitem['data'][$i])); + } + return $inputitem; + } + + /** + * encodeModeKanji + * @param array $inputitem + * @param int $version + * @return array input item + */ + protected function encodeModeKanji($inputitem, $version) { + $inputitem['bstream'] = array(); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x8); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_KJ, $version), (int)($inputitem['size'] / 2)); + for ($i=0; $i<$inputitem['size']; $i+=2) { + $val = (ord($inputitem['data'][$i]) << 8) | ord($inputitem['data'][$i+1]); + if ($val <= 0x9ffc) { + $val -= 0x8140; + } else { + $val -= 0xc140; + } + $h = ($val >> 8) * 0xc0; + $val = ($val & 0xff) + $h; + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 13, $val); + } + return $inputitem; + } + + /** + * encodeModeStructure + * @param array $inputitem + * @return array input item + */ + protected function encodeModeStructure($inputitem) { + $inputitem['bstream'] = array(); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x03); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, ord($inputitem['data'][1]) - 1); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, ord($inputitem['data'][0]) - 1); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 8, ord($inputitem['data'][2])); + return $inputitem; + } + + /** + * encodeBitStream + * @param array $inputitem + * @param int $version + * @return array input item + */ + protected function encodeBitStream($inputitem, $version) { + $inputitem['bstream'] = array(); + $words = $this->maximumWords($inputitem['mode'], $version); + if ($inputitem['size'] > $words) { + $st1 = $this->newInputItem($inputitem['mode'], $words, $inputitem['data']); + $st2 = $this->newInputItem($inputitem['mode'], $inputitem['size'] - $words, array_slice($inputitem['data'], $words)); + $st1 = $this->encodeBitStream($st1, $version); + $st2 = $this->encodeBitStream($st2, $version); + $inputitem['bstream'] = array(); + $inputitem['bstream'] = $this->appendBitstream($inputitem['bstream'], $st1['bstream']); + $inputitem['bstream'] = $this->appendBitstream($inputitem['bstream'], $st2['bstream']); + } else { + switch($inputitem['mode']) { + case QR_MODE_NM: { + $inputitem = $this->encodeModeNum($inputitem, $version); + break; + } + case QR_MODE_AN: { + $inputitem = $this->encodeModeAn($inputitem, $version); + break; + } + case QR_MODE_8B: { + $inputitem = $this->encodeMode8($inputitem, $version); + break; + } + case QR_MODE_KJ: { + $inputitem = $this->encodeModeKanji($inputitem, $version); + break; + } + case QR_MODE_ST: { + $inputitem = $this->encodeModeStructure($inputitem); + break; + } + default: { + break; + } + } + } + return $inputitem; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRinput + + /** + * Append data to an input object. + * The data is copied and appended to the input object. + * @param array items input items + * @param int $mode encoding mode. + * @param int $size size of data (byte). + * @param array $data array of input data. + * @return items + * + */ + protected function appendNewInputItem($items, $mode, $size, $data) { + $items[] = $this->newInputItem($mode, $size, $data); + return $items; + } + + /** + * insertStructuredAppendHeader + * @param array $items + * @param int $size + * @param int $index + * @param int $parity + * @return array items + */ + protected function insertStructuredAppendHeader($items, $size, $index, $parity) { + if ($size > MAX_STRUCTURED_SYMBOLS) { + return -1; + } + if (($index <= 0) OR ($index > MAX_STRUCTURED_SYMBOLS)) { + return -1; + } + $buf = array($size, $index, $parity); + $entry = $this->newInputItem(QR_MODE_ST, 3, buf); + array_unshift($items, $entry); + return $items; + } + + /** + * calcParity + * @param array $items + * @return int parity + */ + protected function calcParity($items) { + $parity = 0; + foreach ($items as $item) { + if ($item['mode'] != QR_MODE_ST) { + for ($i=$item['size']-1; $i>=0; --$i) { + $parity ^= $item['data'][$i]; + } + } + } + return $parity; + } + + /** + * checkModeNum + * @param int $size + * @param array $data + * @return boolean true or false + */ + protected function checkModeNum($size, $data) { + for ($i=0; $i<$size; ++$i) { + if ((ord($data[$i]) < ord('0')) OR (ord($data[$i]) > ord('9'))){ + return false; + } + } + return true; + } + + /** + * estimateBitsModeNum + * @param int $size + * @return int number of bits + */ + protected function estimateBitsModeNum($size) { + $w = (int)$size / 3; + $bits = $w * 10; + switch($size - $w * 3) { + case 1: { + $bits += 4; + break; + } + case 2: { + $bits += 7; + break; + } + default: { + break; + } + } + return $bits; + } + + /** + * Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19). + * @param int $c character value + * @return value + */ + protected function lookAnTable($c) { + return (($c > 127)?-1:$this->anTable[$c]); + } + + /** + * checkModeAn + * @param int $size + * @param array $data + * @return boolean true or false + */ + protected function checkModeAn($size, $data) { + for ($i=0; $i<$size; ++$i) { + if ($this->lookAnTable(ord($data[$i])) == -1) { + return false; + } + } + return true; + } + + /** + * estimateBitsModeAn + * @param int $size + * @return int number of bits + */ + protected function estimateBitsModeAn($size) { + $w = (int)($size / 2); + $bits = $w * 11; + if ($size & 1) { + $bits += 6; + } + return $bits; + } + + /** + * estimateBitsMode8 + * @param int $size + * @return int number of bits + */ + protected function estimateBitsMode8($size) { + return $size * 8; + } + + /** + * estimateBitsModeKanji + * @param int $size + * @return int number of bits + */ + protected function estimateBitsModeKanji($size) { + return (int)(($size / 2) * 13); + } + + /** + * checkModeKanji + * @param int $size + * @param array $data + * @return boolean true or false + */ + protected function checkModeKanji($size, $data) { + if ($size & 1) { + return false; + } + for ($i=0; $i<$size; $i+=2) { + $val = (ord($data[$i]) << 8) | ord($data[$i+1]); + if (($val < 0x8140) OR (($val > 0x9ffc) AND ($val < 0xe040)) OR ($val > 0xebbf)) { + return false; + } + } + return true; + } + + /** + * Validate the input data. + * @param int $mode encoding mode. + * @param int $size size of data (byte). + * @param array data data to validate + * @return boolean true in case of valid data, false otherwise + */ + protected function check($mode, $size, $data) { + if ($size <= 0) { + return false; + } + switch($mode) { + case QR_MODE_NM: { + return $this->checkModeNum($size, $data); + } + case QR_MODE_AN: { + return $this->checkModeAn($size, $data); + } + case QR_MODE_KJ: { + return $this->checkModeKanji($size, $data); + } + case QR_MODE_8B: { + return true; + } + case QR_MODE_ST: { + return true; + } + default: { + break; + } + } + return false; + } + + /** + * estimateBitStreamSize + * @param array $items + * @param int $version + * @return int bits + */ + protected function estimateBitStreamSize($items, $version) { + $bits = 0; + if ($version == 0) { + $version = 1; + } + foreach ($items as $item) { + switch($item['mode']) { + case QR_MODE_NM: { + $bits = $this->estimateBitsModeNum($item['size']); + break; + } + case QR_MODE_AN: { + $bits = $this->estimateBitsModeAn($item['size']); + break; + } + case QR_MODE_8B: { + $bits = $this->estimateBitsMode8($item['size']); + break; + } + case QR_MODE_KJ: { + $bits = $this->estimateBitsModeKanji($item['size']); + break; + } + case QR_MODE_ST: { + return STRUCTURE_HEADER_BITS; + } + default: { + return 0; + } + } + $l = $this->lengthIndicator($item['mode'], $version); + $m = 1 << $l; + $num = (int)(($item['size'] + $m - 1) / $m); + $bits += $num * (4 + $l); + } + return $bits; + } + + /** + * estimateVersion + * @param array $items + * @return int version + */ + protected function estimateVersion($items) { + $version = 0; + $prev = 0; + do { + $prev = $version; + $bits = $this->estimateBitStreamSize($items, $prev); + $version = $this->getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if ($version < 0) { + return -1; + } + } while ($version > $prev); + return $version; + } + + /** + * lengthOfCode + * @param int $mode + * @param int $version + * @param int $bits + * @return int size + */ + protected function lengthOfCode($mode, $version, $bits) { + $payload = $bits - 4 - $this->lengthIndicator($mode, $version); + switch($mode) { + case QR_MODE_NM: { + $chunks = (int)($payload / 10); + $remain = $payload - $chunks * 10; + $size = $chunks * 3; + if ($remain >= 7) { + $size += 2; + } elseif ($remain >= 4) { + $size += 1; + } + break; + } + case QR_MODE_AN: { + $chunks = (int)($payload / 11); + $remain = $payload - $chunks * 11; + $size = $chunks * 2; + if ($remain >= 6) { + ++$size; + } + break; + } + case QR_MODE_8B: { + $size = (int)($payload / 8); + break; + } + case QR_MODE_KJ: { + $size = (int)(($payload / 13) * 2); + break; + } + case QR_MODE_ST: { + $size = (int)($payload / 8); + break; + } + default: { + $size = 0; + break; + } + } + $maxsize = $this->maximumWords($mode, $version); + if ($size < 0) { + $size = 0; + } + if ($size > $maxsize) { + $size = $maxsize; + } + return $size; + } + + /** + * createBitStream + * @param array $items + * @return array of items and total bits + */ + protected function createBitStream($items) { + $total = 0; + foreach ($items as $key => $item) { + $items[$key] = $this->encodeBitStream($item, $this->version); + $bits = count($items[$key]['bstream']); + $total += $bits; + } + return array($items, $total); + } + + /** + * convertData + * @param array $items + * @return array items + */ + protected function convertData($items) { + $ver = $this->estimateVersion($items); + if ($ver > $this->version) { + $this->version = $ver; + } + for (;;) { + $cbs = $this->createBitStream($items); + $items = $cbs[0]; + $bits = $cbs[1]; + if ($bits < 0) { + return -1; + } + $ver = $this->getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if ($ver < 0) { + return -1; + } elseif ($ver > $this->version) { + $this->version = $ver; + } else { + break; + } + } + return $items; + } + + /** + * Append Padding Bit to bitstream + * @param array $bstream + * @return array bitstream + */ + protected function appendPaddingBit($bstream) { + $bits = count($bstream); + $maxwords = $this->getDataLength($this->version, $this->level); + $maxbits = $maxwords * 8; + if ($maxbits == $bits) { + return 0; + } + if ($maxbits - $bits < 5) { + return $this->appendNum($bstream, $maxbits - $bits, 0); + } + $bits += 4; + $words = (int)(($bits + 7) / 8); + $padding = array(); + $padding = $this->appendNum($padding, $words * 8 - $bits + 4, 0); + $padlen = $maxwords - $words; + if ($padlen > 0) { + $padbuf = array(); + for ($i=0; $i<$padlen; ++$i) { + $padbuf[$i] = ($i&1)?0x11:0xec; + } + $padding = $this->appendBytes($padding, $padlen, $padbuf); + } + return $this->appendBitstream($bstream, $padding); + } + + /** + * mergeBitStream + * @param array $bstream + * @return array bitstream + */ + protected function mergeBitStream($items) { + $items = $this->convertData($items); + $bstream = array(); + foreach ($items as $item) { + $bstream = $this->appendBitstream($bstream, $item['bstream']); + } + return $bstream; + } + + /** + * Returns a stream of bits. + * @param int $items + * @return array padded merged byte stream + */ + protected function getBitStream($items) { + $bstream = $this->mergeBitStream($items); + return $this->appendPaddingBit($bstream); + } + + /** + * Pack all bit streams padding bits into a byte array. + * @param int $items + * @return array padded merged byte stream + */ + protected function getByteStream($items) { + $bstream = $this->getBitStream($items); + return $this->bitstreamToByte($bstream); + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRbitstream + + /** + * Return an array with zeros + * @param int $setLength array size + * @return array + */ + protected function allocate($setLength) { + return array_fill(0, $setLength, 0); + } + + /** + * Return new bitstream from number + * @param int $bits number of bits + * @param int $num number + * @return array bitstream + */ + protected function newFromNum($bits, $num) { + $bstream = $this->allocate($bits); + $mask = 1 << ($bits - 1); + for ($i=0; $i<$bits; ++$i) { + if ($num & $mask) { + $bstream[$i] = 1; + } else { + $bstream[$i] = 0; + } + $mask = $mask >> 1; + } + return $bstream; + } + + /** + * Return new bitstream from bytes + * @param int $size size + * @param array $data bytes + * @return array bitstream + */ + protected function newFromBytes($size, $data) { + $bstream = $this->allocate($size * 8); + $p=0; + for ($i=0; $i<$size; ++$i) { + $mask = 0x80; + for ($j=0; $j<8; ++$j) { + if ($data[$i] & $mask) { + $bstream[$p] = 1; + } else { + $bstream[$p] = 0; + } + $p++; + $mask = $mask >> 1; + } + } + return $bstream; + } + + /** + * Append one bitstream to another + * @param array $bitstream original bitstream + * @param array $append bitstream to append + * @return array bitstream + */ + protected function appendBitstream($bitstream, $append) { + if ((!is_array($append)) OR (count($append) == 0)) { + return $bitstream; + } + if (count($bitstream) == 0) { + return $append; + } + return array_values(array_merge($bitstream, $append)); + } + + /** + * Append one bitstream created from number to another + * @param array $bitstream original bitstream + * @param int $bits number of bits + * @param int $num number + * @return array bitstream + */ + protected function appendNum($bitstream, $bits, $num) { + if ($bits == 0) { + return 0; + } + $b = $this->newFromNum($bits, $num); + return $this->appendBitstream($bitstream, $b); + } + + /** + * Append one bitstream created from bytes to another + * @param array $bitstream original bitstream + * @param int $size size + * @param array $data bytes + * @return array bitstream + */ + protected function appendBytes($bitstream, $size, $data) { + if ($size == 0) { + return 0; + } + $b = $this->newFromBytes($size, $data); + return $this->appendBitstream($bitstream, $b); + } + + /** + * Convert bitstream to bytes + * @param array $bitstream original bitstream + * @return array of bytes + */ + protected function bitstreamToByte($bstream) { + $size = count($bstream); + if ($size == 0) { + return array(); + } + $data = array_fill(0, (int)(($size + 7) / 8), 0); + $bytes = (int)($size / 8); + $p = 0; + for ($i=0; $i<$bytes; $i++) { + $v = 0; + for ($j=0; $j<8; $j++) { + $v = $v << 1; + $v |= $bstream[$p]; + $p++; + } + $data[$i] = $v; + } + if ($size & 7) { + $v = 0; + for ($j=0; $j<($size & 7); $j++) { + $v = $v << 1; + $v |= $bstream[$p]; + $p++; + } + $data[$bytes] = $v; + } + return $data; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRspec + + /** + * Replace a value on the array at the specified position + * @param array $srctab + * @param int $x X position + * @param int $y Y position + * @param string $repl value to replace + * @param int $replLen length of the repl string + * @return array srctab + */ + protected function qrstrset($srctab, $x, $y, $repl, $replLen=false) { + $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl)); + return $srctab; + } + + /** + * Return maximum data code length (bytes) for the version. + * @param int $version version + * @param int $level error correction level + * @return int maximum size (bytes) + */ + protected function getDataLength($version, $level) { + return $this->capacity[$version][QRCAP_WORDS] - $this->capacity[$version][QRCAP_EC][$level]; + } + + /** + * Return maximum error correction code length (bytes) for the version. + * @param int $version version + * @param int $level error correction level + * @return int ECC size (bytes) + */ + protected function getECCLength($version, $level){ + return $this->capacity[$version][QRCAP_EC][$level]; + } + + /** + * Return the width of the symbol for the version. + * @param int $version version + * @return int width + */ + protected function getWidth($version) { + return $this->capacity[$version][QRCAP_WIDTH]; + } + + /** + * Return the numer of remainder bits. + * @param int $version version + * @return int number of remainder bits + */ + protected function getRemainder($version) { + return $this->capacity[$version][QRCAP_REMINDER]; + } + + /** + * Return a version number that satisfies the input code length. + * @param int $size input code length (byte) + * @param int $level error correction level + * @return int version number + */ + protected function getMinimumVersion($size, $level) { + for ($i=1; $i <= QRSPEC_VERSION_MAX; ++$i) { + $words = $this->capacity[$i][QRCAP_WORDS] - $this->capacity[$i][QRCAP_EC][$level]; + if ($words >= $size) { + return $i; + } + } + return -1; + } + + /** + * Return the size of length indicator for the mode and version. + * @param int $mode encoding mode + * @param int $version version + * @return int the size of the appropriate length indicator (bits). + */ + protected function lengthIndicator($mode, $version) { + if ($mode == QR_MODE_ST) { + return 0; + } + if ($version <= 9) { + $l = 0; + } elseif ($version <= 26) { + $l = 1; + } else { + $l = 2; + } + return $this->lengthTableBits[$mode][$l]; + } + + /** + * Return the maximum length for the mode and version. + * @param int $mode encoding mode + * @param int $version version + * @return int the maximum length (bytes) + */ + protected function maximumWords($mode, $version) { + if ($mode == QR_MODE_ST) { + return 3; + } + if ($version <= 9) { + $l = 0; + } else if ($version <= 26) { + $l = 1; + } else { + $l = 2; + } + $bits = $this->lengthTableBits[$mode][$l]; + $words = (1 << $bits) - 1; + if ($mode == QR_MODE_KJ) { + $words *= 2; // the number of bytes is required + } + return $words; + } + + /** + * Return an array of ECC specification. + * @param int $version version + * @param int $level error correction level + * @param array $spec an array of ECC specification contains as following: {# of type1 blocks, # of data code, # of ecc code, # of type2 blocks, # of data code} + * @return array spec + */ + protected function getEccSpec($version, $level, $spec) { + if (count($spec) < 5) { + $spec = array(0, 0, 0, 0, 0); + } + $b1 = $this->eccTable[$version][$level][0]; + $b2 = $this->eccTable[$version][$level][1]; + $data = $this->getDataLength($version, $level); + $ecc = $this->getECCLength($version, $level); + if ($b2 == 0) { + $spec[0] = $b1; + $spec[1] = (int)($data / $b1); + $spec[2] = (int)($ecc / $b1); + $spec[3] = 0; + $spec[4] = 0; + } else { + $spec[0] = $b1; + $spec[1] = (int)($data / ($b1 + $b2)); + $spec[2] = (int)($ecc / ($b1 + $b2)); + $spec[3] = $b2; + $spec[4] = $spec[1] + 1; + } + return $spec; + } + + /** + * Put an alignment marker. + * @param array $frame frame + * @param int $width width + * @param int $ox X center coordinate of the pattern + * @param int $oy Y center coordinate of the pattern + * @return array frame + */ + protected function putAlignmentMarker($frame, $ox, $oy) { + $finder = array( + "\xa1\xa1\xa1\xa1\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa0\xa1\xa0\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa1\xa1\xa1\xa1" + ); + $yStart = $oy - 2; + $xStart = $ox - 2; + for ($y=0; $y < 5; $y++) { + $frame = $this->qrstrset($frame, $xStart, $yStart+$y, $finder[$y]); + } + return $frame; + } + + /** + * Put an alignment pattern. + * @param int $version version + * @param array $fram frame + * @param int $width width + * @return array frame + */ + protected function putAlignmentPattern($version, $frame, $width) { + if ($version < 2) { + return $frame; + } + $d = $this->alignmentPattern[$version][1] - $this->alignmentPattern[$version][0]; + if ($d < 0) { + $w = 2; + } else { + $w = (int)(($width - $this->alignmentPattern[$version][0]) / $d + 2); + } + if ($w * $w - 3 == 1) { + $x = $this->alignmentPattern[$version][0]; + $y = $this->alignmentPattern[$version][0]; + $frame = $this->putAlignmentMarker($frame, $x, $y); + return $frame; + } + $cx = $this->alignmentPattern[$version][0]; + $wo = $w - 1; + for ($x=1; $x < $wo; ++$x) { + $frame = $this->putAlignmentMarker($frame, 6, $cx); + $frame = $this->putAlignmentMarker($frame, $cx, 6); + $cx += $d; + } + $cy = $this->alignmentPattern[$version][0]; + for ($y=0; $y < $wo; ++$y) { + $cx = $this->alignmentPattern[$version][0]; + for ($x=0; $x < $wo; ++$x) { + $frame = $this->putAlignmentMarker($frame, $cx, $cy); + $cx += $d; + } + $cy += $d; + } + return $frame; + } + + /** + * Return BCH encoded version information pattern that is used for the symbol of version 7 or greater. Use lower 18 bits. + * @param int $version version + * @return BCH encoded version information pattern + */ + protected function getVersionPattern($version) { + if (($version < 7) OR ($version > QRSPEC_VERSION_MAX)) { + return 0; + } + return $this->versionPattern[($version - 7)]; + } + + /** + * Return BCH encoded format information pattern. + * @param array $mask + * @param int $level error correction level + * @return BCH encoded format information pattern + */ + protected function getFormatInfo($mask, $level) { + if (($mask < 0) OR ($mask > 7)) { + return 0; + } + if (($level < 0) OR ($level > 3)) { + return 0; + } + return $this->formatInfo[$level][$mask]; + } + + /** + * Put a finder pattern. + * @param array $frame frame + * @param int $width width + * @param int $ox X center coordinate of the pattern + * @param int $oy Y center coordinate of the pattern + * @return array frame + */ + protected function putFinderPattern($frame, $ox, $oy) { + $finder = array( + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" + ); + for ($y=0; $y < 7; $y++) { + $frame = $this->qrstrset($frame, $ox, ($oy + $y), $finder[$y]); + } + return $frame; + } + + /** + * Return a copy of initialized frame. + * @param int $version version + * @return Array of unsigned char. + */ + protected function createFrame($version) { + $width = $this->capacity[$version][QRCAP_WIDTH]; + $frameLine = str_repeat ("\0", $width); + $frame = array_fill(0, $width, $frameLine); + // Finder pattern + $frame = $this->putFinderPattern($frame, 0, 0); + $frame = $this->putFinderPattern($frame, $width - 7, 0); + $frame = $this->putFinderPattern($frame, 0, $width - 7); + // Separator + $yOffset = $width - 7; + for ($y=0; $y < 7; ++$y) { + $frame[$y][7] = "\xc0"; + $frame[$y][$width - 8] = "\xc0"; + $frame[$yOffset][7] = "\xc0"; + ++$yOffset; + } + $setPattern = str_repeat("\xc0", 8); + $frame = $this->qrstrset($frame, 0, 7, $setPattern); + $frame = $this->qrstrset($frame, $width-8, 7, $setPattern); + $frame = $this->qrstrset($frame, 0, $width - 8, $setPattern); + // Format info + $setPattern = str_repeat("\x84", 9); + $frame = $this->qrstrset($frame, 0, 8, $setPattern); + $frame = $this->qrstrset($frame, $width - 8, 8, $setPattern, 8); + $yOffset = $width - 8; + for ($y=0; $y < 8; ++$y,++$yOffset) { + $frame[$y][8] = "\x84"; + $frame[$yOffset][8] = "\x84"; + } + // Timing pattern + $wo = $width - 15; + for ($i=1; $i < $wo; ++$i) { + $frame[6][7+$i] = chr(0x90 | ($i & 1)); + $frame[7+$i][6] = chr(0x90 | ($i & 1)); + } + // Alignment pattern + $frame = $this->putAlignmentPattern($version, $frame, $width); + // Version information + if ($version >= 7) { + $vinf = $this->getVersionPattern($version); + $v = $vinf; + for ($x=0; $x<6; ++$x) { + for ($y=0; $y<3; ++$y) { + $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + $v = $vinf; + for ($y=0; $y<6; ++$y) { + for ($x=0; $x<3; ++$x) { + $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + } + // and a little bit... + $frame[$width - 8][8] = "\x81"; + return $frame; + } + + /** + * Set new frame for the specified version. + * @param int $version version + * @return Array of unsigned char. + */ + protected function newFrame($version) { + if (($version < 1) OR ($version > QRSPEC_VERSION_MAX)) { + return NULL; + } + if (!isset($this->frames[$version])) { + $this->frames[$version] = $this->createFrame($version); + } + if (is_null($this->frames[$version])) { + return NULL; + } + return $this->frames[$version]; + } + + /** + * Return block number 0 + * @param array $spec + * @return int value + */ + protected function rsBlockNum($spec) { + return ($spec[0] + $spec[3]); + } + + /** + * Return block number 1 + * @param array $spec + * @return int value + */ + protected function rsBlockNum1($spec) { + return $spec[0]; + } + + /** + * Return data codes 1 + * @param array $spec + * @return int value + */ + protected function rsDataCodes1($spec) { + return $spec[1]; + } + + /** + * Return ecc codes 1 + * @param array $spec + * @return int value + */ + protected function rsEccCodes1($spec) { + return $spec[2]; + } + + /** + * Return block number 2 + * @param array $spec + * @return int value + */ + protected function rsBlockNum2($spec) { + return $spec[3]; + } + + /** + * Return data codes 2 + * @param array $spec + * @return int value + */ + protected function rsDataCodes2($spec) { + return $spec[4]; + } + + /** + * Return ecc codes 2 + * @param array $spec + * @return int value + */ + protected function rsEccCodes2($spec) { + return $spec[2]; + } + + /** + * Return data length + * @param array $spec + * @return int value + */ + protected function rsDataLength($spec) { + return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); + } + + /** + * Return ecc length + * @param array $spec + * @return int value + */ + protected function rsEccLength($spec) { + return ($spec[0] + $spec[3]) * $spec[2]; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRrs + + /** + * Initialize a Reed-Solomon codec and add it to existing rsitems + * @param int $symsize symbol size, bits + * @param int $gfpoly Field generator polynomial coefficients + * @param int $fcr first root of RS code generator polynomial, index form + * @param int $prim primitive element to generate polynomial roots + * @param int $nroots RS code generator polynomial degree (number of roots) + * @param int $pad padding bytes at front of shortened block + * @return array Array of RS values:<ul><li>mm = Bits per symbol;</li><li>nn = Symbols per block;</li><li>alpha_to = log lookup table array;</li><li>index_of = Antilog lookup table array;</li><li>genpoly = Generator polynomial array;</li><li>nroots = Number of generator;</li><li>roots = number of parity symbols;</li><li>fcr = First consecutive root, index form;</li><li>prim = Primitive element, index form;</li><li>iprim = prim-th root of 1, index form;</li><li>pad = Padding bytes in shortened block;</li><li>gfpoly</ul>. + */ + protected function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) { + foreach ($this->rsitems as $rs) { + if (($rs['pad'] != $pad) OR ($rs['nroots'] != $nroots) OR ($rs['mm'] != $symsize) + OR ($rs['gfpoly'] != $gfpoly) OR ($rs['fcr'] != $fcr) OR ($rs['prim'] != $prim)) { + continue; + } + return $rs; + } + $rs = $this->init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad); + array_unshift($this->rsitems, $rs); + return $rs; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRrsItem + + /** + * modnn + * @param array RS values + * @param int $x X position + * @return int X osition + */ + protected function modnn($rs, $x) { + while ($x >= $rs['nn']) { + $x -= $rs['nn']; + $x = ($x >> $rs['mm']) + ($x & $rs['nn']); + } + return $x; + } + + /** + * Initialize a Reed-Solomon codec and returns an array of values. + * @param int $symsize symbol size, bits + * @param int $gfpoly Field generator polynomial coefficients + * @param int $fcr first root of RS code generator polynomial, index form + * @param int $prim primitive element to generate polynomial roots + * @param int $nroots RS code generator polynomial degree (number of roots) + * @param int $pad padding bytes at front of shortened block + * @return array Array of RS values:<ul><li>mm = Bits per symbol;</li><li>nn = Symbols per block;</li><li>alpha_to = log lookup table array;</li><li>index_of = Antilog lookup table array;</li><li>genpoly = Generator polynomial array;</li><li>nroots = Number of generator;</li><li>roots = number of parity symbols;</li><li>fcr = First consecutive root, index form;</li><li>prim = Primitive element, index form;</li><li>iprim = prim-th root of 1, index form;</li><li>pad = Padding bytes in shortened block;</li><li>gfpoly</ul>. + */ + protected function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) { + // Based on Reed solomon encoder by Phil Karn, KA9Q (GNU-LGPLv2) + $rs = null; + // Check parameter ranges + if (($symsize < 0) OR ($symsize > 8)) { + return $rs; + } + if (($fcr < 0) OR ($fcr >= (1<<$symsize))) { + return $rs; + } + if (($prim <= 0) OR ($prim >= (1<<$symsize))) { + return $rs; + } + if (($nroots < 0) OR ($nroots >= (1<<$symsize))) { + return $rs; + } + if (($pad < 0) OR ($pad >= ((1<<$symsize) -1 - $nroots))) { + return $rs; + } + $rs = array(); + $rs['mm'] = $symsize; + $rs['nn'] = (1 << $symsize) - 1; + $rs['pad'] = $pad; + $rs['alpha_to'] = array_fill(0, ($rs['nn'] + 1), 0); + $rs['index_of'] = array_fill(0, ($rs['nn'] + 1), 0); + // PHP style macro replacement ;) + $NN =& $rs['nn']; + $A0 =& $NN; + // Generate Galois field lookup tables + $rs['index_of'][0] = $A0; // log(zero) = -inf + $rs['alpha_to'][$A0] = 0; // alpha**-inf = 0 + $sr = 1; + for ($i=0; $i<$rs['nn']; ++$i) { + $rs['index_of'][$sr] = $i; + $rs['alpha_to'][$i] = $sr; + $sr <<= 1; + if ($sr & (1 << $symsize)) { + $sr ^= $gfpoly; + } + $sr &= $rs['nn']; + } + if ($sr != 1) { + // field generator polynomial is not primitive! + return NULL; + } + // Form RS code generator polynomial from its roots + $rs['genpoly'] = array_fill(0, ($nroots + 1), 0); + $rs['fcr'] = $fcr; + $rs['prim'] = $prim; + $rs['nroots'] = $nroots; + $rs['gfpoly'] = $gfpoly; + // Find prim-th root of 1, used in decoding + for ($iprim=1; ($iprim % $prim) != 0; $iprim += $rs['nn']) { + ; // intentional empty-body loop! + } + $rs['iprim'] = (int)($iprim / $prim); + $rs['genpoly'][0] = 1; + + + for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) { + $rs['genpoly'][$i+1] = 1; + // Multiply rs->genpoly[] by @**(root + x) + for ($j = $i; $j > 0; --$j) { + if ($rs['genpoly'][$j] != 0) { + $rs['genpoly'][$j] = $rs['genpoly'][$j-1] ^ $rs['alpha_to'][$this->modnn($rs, $rs['index_of'][$rs['genpoly'][$j]] + $root)]; + } else { + $rs['genpoly'][$j] = $rs['genpoly'][$j-1]; + } + } + // rs->genpoly[0] can never be zero + $rs['genpoly'][0] = $rs['alpha_to'][$this->modnn($rs, $rs['index_of'][$rs['genpoly'][0]] + $root)]; + } + // convert rs->genpoly[] to index form for quicker encoding + for ($i = 0; $i <= $nroots; ++$i) { + $rs['genpoly'][$i] = $rs['index_of'][$rs['genpoly'][$i]]; + } + return $rs; + } + + /** + * Encode a Reed-Solomon codec and returns the parity array + * @param array $rs RS values + * @param array $data data + * @param array $parity parity + * @return parity array + */ + protected function encode_rs_char($rs, $data, $parity) { + $MM =& $rs['mm']; // bits per symbol + $NN =& $rs['nn']; // the total number of symbols in a RS block + $ALPHA_TO =& $rs['alpha_to']; // the address of an array of NN elements to convert Galois field elements in index (log) form to polynomial form + $INDEX_OF =& $rs['index_of']; // the address of an array of NN elements to convert Galois field elements in polynomial form to index (log) form + $GENPOLY =& $rs['genpoly']; // an array of NROOTS+1 elements containing the generator polynomial in index form + $NROOTS =& $rs['nroots']; // the number of roots in the RS code generator polynomial, which is the same as the number of parity symbols in a block + $FCR =& $rs['fcr']; // first consecutive root, index form + $PRIM =& $rs['prim']; // primitive element, index form + $IPRIM =& $rs['iprim']; // prim-th root of 1, index form + $PAD =& $rs['pad']; // the number of pad symbols in a block + $A0 =& $NN; + $parity = array_fill(0, $NROOTS, 0); + for ($i=0; $i < ($NN - $NROOTS - $PAD); $i++) { + $feedback = $INDEX_OF[$data[$i] ^ $parity[0]]; + if ($feedback != $A0) { + // feedback term is non-zero + // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must + // always be for the polynomials constructed by init_rs() + $feedback = $this->modnn($rs, $NN - $GENPOLY[$NROOTS] + $feedback); + for ($j=1; $j < $NROOTS; ++$j) { + $parity[$j] ^= $ALPHA_TO[$this->modnn($rs, $feedback + $GENPOLY[($NROOTS - $j)])]; + } + } + // Shift + array_shift($parity); + if ($feedback != $A0) { + array_push($parity, $ALPHA_TO[$this->modnn($rs, $feedback + $GENPOLY[0])]); + } else { + array_push($parity, 0); + } + } + return $parity; + } + + } // end QRcode class + +} // END OF "class_exists QRcode" +?> diff --git a/src/admin/application/libs/phpqrcode/index.php b/src/admin/application/libs/phpqrcode/index.php new file mode 100755 index 0000000..9e14b7e --- /dev/null +++ b/src/admin/application/libs/phpqrcode/index.php @@ -0,0 +1,94 @@ +<?php +/* + * PHP QR Code encoder + * + * Exemplatory usage + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + echo "<h1>PHP QR Code</h1><hr/>"; + + //set it to writable location, a place for temp generated PNG files + $PNG_TEMP_DIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR; + + //html PNG location prefix + $PNG_WEB_DIR = 'temp/'; + + include "qrlib.php"; + + //ofcourse we need rights to create temp dir + if (!file_exists($PNG_TEMP_DIR)) + mkdir($PNG_TEMP_DIR); + + + $filename = $PNG_TEMP_DIR.'test.png'; + + //processing form input + //remember to sanitize user input in real-life solution !!! + $errorCorrectionLevel = 'L'; + if (isset($_REQUEST['level']) && in_array($_REQUEST['level'], array('L','M','Q','H'))) + $errorCorrectionLevel = $_REQUEST['level']; + + $matrixPointSize = 4; + if (isset($_REQUEST['size'])) + $matrixPointSize = min(max((int)$_REQUEST['size'], 1), 10); + + + if (isset($_REQUEST['data'])) { + + //it's very important! + if (trim($_REQUEST['data']) == '') + die('data cannot be empty! <a href="?">back</a>'); + + // user data + $filename = $PNG_TEMP_DIR.'test'.md5($_REQUEST['data'].'|'.$errorCorrectionLevel.'|'.$matrixPointSize).'.png'; + QRcode::png($_REQUEST['data'], $filename, $errorCorrectionLevel, $matrixPointSize, 2); + + } else { + + //default data + echo 'You can provide data in GET parameter: <a href="?data=like_that">like that</a><hr/>'; + QRcode::png('PHP QR Code :)', $filename, $errorCorrectionLevel, $matrixPointSize, 2); + + } + + //display generated file + echo '<img src="'.$PNG_WEB_DIR.basename($filename).'" /><hr/>'; + + //config form + echo '<form action="index.php" method="post"> + Data:&nbsp;<input name="data" value="'.(isset($_REQUEST['data'])?htmlspecialchars($_REQUEST['data']):'PHP QR Code :)').'" />&nbsp; + ECC:&nbsp;<select name="level"> + <option value="L"'.(($errorCorrectionLevel=='L')?' selected':'').'>L - smallest</option> + <option value="M"'.(($errorCorrectionLevel=='M')?' selected':'').'>M</option> + <option value="Q"'.(($errorCorrectionLevel=='Q')?' selected':'').'>Q</option> + <option value="H"'.(($errorCorrectionLevel=='H')?' selected':'').'>H - best</option> + </select>&nbsp; + Size:&nbsp;<select name="size">'; + + for($i=1;$i<=10;$i++) + echo '<option value="'.$i.'"'.(($matrixPointSize==$i)?' selected':'').'>'.$i.'</option>'; + + echo '</select>&nbsp; + <input type="submit" value="GENERATE"></form><hr/>'; + + // benchmark + QRtools::timeBenchmark(); + + \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/phpqrcode.php b/src/admin/application/libs/phpqrcode/phpqrcode.php new file mode 100755 index 0000000..80adb9d --- /dev/null +++ b/src/admin/application/libs/phpqrcode/phpqrcode.php @@ -0,0 +1,3312 @@ +<?php + +/* + * PHP QR Code encoder + * + * This file contains MERGED version of PHP QR Code library. + * It was auto-generated from full version for your convenience. + * + * This merged version was configured to not requre any external files, + * with disabled cache, error loging and weker but faster mask matching. + * If you need tune it up please use non-merged version. + * + * For full version, documentation, examples of use please visit: + * + * http://phpqrcode.sourceforge.net/ + * https://sourceforge.net/projects/phpqrcode/ + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + + +/* + * Version: 1.1.4 + * Build: 2010100721 + */ + + + +//---- qrconst.php ----------------------------- + + + + + +/* + * PHP QR Code encoder + * + * Common constants + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + // Encoding modes + + define('QR_MODE_NUL', -1); + define('QR_MODE_NUM', 0); + define('QR_MODE_AN', 1); + define('QR_MODE_8', 2); + define('QR_MODE_KANJI', 3); + define('QR_MODE_STRUCTURE', 4); + + // Levels of error correction. + + define('QR_ECLEVEL_L', 0); + define('QR_ECLEVEL_M', 1); + define('QR_ECLEVEL_Q', 2); + define('QR_ECLEVEL_H', 3); + + // Supported output formats + + define('QR_FORMAT_TEXT', 0); + define('QR_FORMAT_PNG', 1); + + class qrstr { + public static function set(&$srctab, $x, $y, $repl, $replLen = false) { + $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl)); + } + } + + + +//---- merged_config.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Config file, tuned-up for merged verion + */ + + define('QR_CACHEABLE', false); // use cache - more disk reads but less CPU power, masks and format templates are stored there + define('QR_CACHE_DIR', false); // used when QR_CACHEABLE === true + define('QR_LOG_DIR', false); // default error logs dir + + define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code + define('QR_FIND_FROM_RANDOM', 2); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly + define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false + + define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images + + + + +//---- qrtools.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Toolset, handy and debug utilites. + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRtools { + + //---------------------------------------------------------------------- + public static function binarize($frame) + { + $len = count($frame); + foreach ($frame as &$frameLine) { + + for($i=0; $i<$len; $i++) { + $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0'; + } + } + + return $frame; + } + + //---------------------------------------------------------------------- + public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037') + { + $barcode_array = array(); + + if (!is_array($mode)) + $mode = explode(',', $mode); + + $eccLevel = 'L'; + + if (count($mode) > 1) { + $eccLevel = $mode[1]; + } + + $qrTab = QRcode::text($code, false, $eccLevel); + $size = count($qrTab); + + $barcode_array['num_rows'] = $size; + $barcode_array['num_cols'] = $size; + $barcode_array['bcode'] = array(); + + foreach ($qrTab as $line) { + $arrAdd = array(); + foreach(str_split($line) as $char) + $arrAdd[] = ($char=='1')?1:0; + $barcode_array['bcode'][] = $arrAdd; + } + + return $barcode_array; + } + + //---------------------------------------------------------------------- + public static function clearCache() + { + self::$frames = array(); + } + + //---------------------------------------------------------------------- + public static function buildCache() + { + QRtools::markTime('before_build_cache'); + + $mask = new QRmask(); + for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) { + $frame = QRspec::newFrame($a); + if (QR_IMAGE) { + $fileName = QR_CACHE_DIR.'frame_'.$a.'.png'; + QRimage::png(self::binarize($frame), $fileName, 1, 0); + } + + $width = count($frame); + $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); + for ($maskNo=0; $maskNo<8; $maskNo++) + $mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true); + } + + QRtools::markTime('after_build_cache'); + } + + //---------------------------------------------------------------------- + public static function log($outfile, $err) + { + if (QR_LOG_DIR !== false) { + if ($err != '') { + if ($outfile !== false) { + file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); + } else { + file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); + } + } + } + } + + //---------------------------------------------------------------------- + public static function dumpMask($frame) + { + $width = count($frame); + for($y=0;$y<$width;$y++) { + for($x=0;$x<$width;$x++) { + echo ord($frame[$y][$x]).','; + } + } + } + + //---------------------------------------------------------------------- + public static function markTime($markerId) + { + list($usec, $sec) = explode(" ", microtime()); + $time = ((float)$usec + (float)$sec); + + if (!isset($GLOBALS['qr_time_bench'])) + $GLOBALS['qr_time_bench'] = array(); + + $GLOBALS['qr_time_bench'][$markerId] = $time; + } + + //---------------------------------------------------------------------- + public static function timeBenchmark() + { + self::markTime('finish'); + + $lastTime = 0; + $startTime = 0; + $p = 0; + + echo '<table cellpadding="3" cellspacing="1"> + <thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead> + <tbody>'; + + foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) { + if ($p > 0) { + echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime-$lastTime, 6).'s</td></tr>'; + } else { + $startTime = $thisTime; + } + + $p++; + $lastTime = $thisTime; + } + + echo '</tbody><tfoot> + <tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime-$startTime, 6).'s</td></tr> + </tfoot> + </table>'; + } + + } + + //########################################################################## + + QRtools::markTime('start'); + + + + +//---- qrspec.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * QR Code specifications + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('QRSPEC_VERSION_MAX', 40); + define('QRSPEC_WIDTH_MAX', 177); + + define('QRCAP_WIDTH', 0); + define('QRCAP_WORDS', 1); + define('QRCAP_REMINDER', 2); + define('QRCAP_EC', 3); + + class QRspec { + + public static $capacity = array( + array( 0, 0, 0, array( 0, 0, 0, 0)), + array( 21, 26, 0, array( 7, 10, 13, 17)), // 1 + array( 25, 44, 7, array( 10, 16, 22, 28)), + array( 29, 70, 7, array( 15, 26, 36, 44)), + array( 33, 100, 7, array( 20, 36, 52, 64)), + array( 37, 134, 7, array( 26, 48, 72, 88)), // 5 + array( 41, 172, 7, array( 36, 64, 96, 112)), + array( 45, 196, 0, array( 40, 72, 108, 130)), + array( 49, 242, 0, array( 48, 88, 132, 156)), + array( 53, 292, 0, array( 60, 110, 160, 192)), + array( 57, 346, 0, array( 72, 130, 192, 224)), //10 + array( 61, 404, 0, array( 80, 150, 224, 264)), + array( 65, 466, 0, array( 96, 176, 260, 308)), + array( 69, 532, 0, array( 104, 198, 288, 352)), + array( 73, 581, 3, array( 120, 216, 320, 384)), + array( 77, 655, 3, array( 132, 240, 360, 432)), //15 + array( 81, 733, 3, array( 144, 280, 408, 480)), + array( 85, 815, 3, array( 168, 308, 448, 532)), + array( 89, 901, 3, array( 180, 338, 504, 588)), + array( 93, 991, 3, array( 196, 364, 546, 650)), + array( 97, 1085, 3, array( 224, 416, 600, 700)), //20 + array(101, 1156, 4, array( 224, 442, 644, 750)), + array(105, 1258, 4, array( 252, 476, 690, 816)), + array(109, 1364, 4, array( 270, 504, 750, 900)), + array(113, 1474, 4, array( 300, 560, 810, 960)), + array(117, 1588, 4, array( 312, 588, 870, 1050)), //25 + array(121, 1706, 4, array( 336, 644, 952, 1110)), + array(125, 1828, 4, array( 360, 700, 1020, 1200)), + array(129, 1921, 3, array( 390, 728, 1050, 1260)), + array(133, 2051, 3, array( 420, 784, 1140, 1350)), + array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30 + array(141, 2323, 3, array( 480, 868, 1290, 1530)), + array(145, 2465, 3, array( 510, 924, 1350, 1620)), + array(149, 2611, 3, array( 540, 980, 1440, 1710)), + array(153, 2761, 3, array( 570, 1036, 1530, 1800)), + array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35 + array(161, 3034, 0, array( 600, 1120, 1680, 1980)), + array(165, 3196, 0, array( 630, 1204, 1770, 2100)), + array(169, 3362, 0, array( 660, 1260, 1860, 2220)), + array(173, 3532, 0, array( 720, 1316, 1950, 2310)), + array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40 + ); + + //---------------------------------------------------------------------- + public static function getDataLength($version, $level) + { + return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level]; + } + + //---------------------------------------------------------------------- + public static function getECCLength($version, $level) + { + return self::$capacity[$version][QRCAP_EC][$level]; + } + + //---------------------------------------------------------------------- + public static function getWidth($version) + { + return self::$capacity[$version][QRCAP_WIDTH]; + } + + //---------------------------------------------------------------------- + public static function getRemainder($version) + { + return self::$capacity[$version][QRCAP_REMINDER]; + } + + //---------------------------------------------------------------------- + public static function getMinimumVersion($size, $level) + { + + for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) { + $words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level]; + if($words >= $size) + return $i; + } + + return -1; + } + + //###################################################################### + + public static $lengthTableBits = array( + array(10, 12, 14), + array( 9, 11, 13), + array( 8, 16, 16), + array( 8, 10, 12) + ); + + //---------------------------------------------------------------------- + public static function lengthIndicator($mode, $version) + { + if ($mode == QR_MODE_STRUCTURE) + return 0; + + if ($version <= 9) { + $l = 0; + } else if ($version <= 26) { + $l = 1; + } else { + $l = 2; + } + + return self::$lengthTableBits[$mode][$l]; + } + + //---------------------------------------------------------------------- + public static function maximumWords($mode, $version) + { + if($mode == QR_MODE_STRUCTURE) + return 3; + + if($version <= 9) { + $l = 0; + } else if($version <= 26) { + $l = 1; + } else { + $l = 2; + } + + $bits = self::$lengthTableBits[$mode][$l]; + $words = (1 << $bits) - 1; + + if($mode == QR_MODE_KANJI) { + $words *= 2; // the number of bytes is required + } + + return $words; + } + + // Error correction code ----------------------------------------------- + // Table of the error correction code (Reed-Solomon block) + // See Table 12-16 (pp.30-36), JIS X0510:2004. + + public static $eccTable = array( + array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)), + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1 + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), + array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)), + array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)), + array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5 + array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)), + array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)), + array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)), + array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)), + array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10 + array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)), + array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)), + array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)), + array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)), + array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15 + array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)), + array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)), + array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)), + array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)), + array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20 + array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)), + array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)), + array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)), + array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)), + array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25 + array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)), + array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)), + array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)), + array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)), + array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30 + array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)), + array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)), + array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)), + array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)), + array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35 + array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)), + array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)), + array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)), + array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)), + array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)),//40 + ); + + //---------------------------------------------------------------------- + // CACHEABLE!!! + + public static function getEccSpec($version, $level, array &$spec) + { + if (count($spec) < 5) { + $spec = array(0,0,0,0,0); + } + + $b1 = self::$eccTable[$version][$level][0]; + $b2 = self::$eccTable[$version][$level][1]; + $data = self::getDataLength($version, $level); + $ecc = self::getECCLength($version, $level); + + if($b2 == 0) { + $spec[0] = $b1; + $spec[1] = (int)($data / $b1); + $spec[2] = (int)($ecc / $b1); + $spec[3] = 0; + $spec[4] = 0; + } else { + $spec[0] = $b1; + $spec[1] = (int)($data / ($b1 + $b2)); + $spec[2] = (int)($ecc / ($b1 + $b2)); + $spec[3] = $b2; + $spec[4] = $spec[1] + 1; + } + } + + // Alignment pattern --------------------------------------------------- + + // Positions of alignment patterns. + // This array includes only the second and the third position of the + // alignment patterns. Rest of them can be calculated from the distance + // between them. + + // See Table 1 in Appendix E (pp.71) of JIS X0510:2004. + + public static $alignmentPattern = array( + array( 0, 0), + array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5 + array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10 + array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15 + array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20 + array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25 + array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30 + array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35 + array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40 + ); + + + /** -------------------------------------------------------------------- + * Put an alignment marker. + * @param frame + * @param width + * @param ox,oy center coordinate of the pattern + */ + public static function putAlignmentMarker(array &$frame, $ox, $oy) + { + $finder = array( + "\xa1\xa1\xa1\xa1\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa0\xa1\xa0\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa1\xa1\xa1\xa1" + ); + + $yStart = $oy-2; + $xStart = $ox-2; + + for($y=0; $y<5; $y++) { + QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]); + } + } + + //---------------------------------------------------------------------- + public static function putAlignmentPattern($version, &$frame, $width) + { + if($version < 2) + return; + + $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0]; + if($d < 0) { + $w = 2; + } else { + $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2); + } + + if($w * $w - 3 == 1) { + $x = self::$alignmentPattern[$version][0]; + $y = self::$alignmentPattern[$version][0]; + self::putAlignmentMarker($frame, $x, $y); + return; + } + + $cx = self::$alignmentPattern[$version][0]; + for($x=1; $x<$w - 1; $x++) { + self::putAlignmentMarker($frame, 6, $cx); + self::putAlignmentMarker($frame, $cx, 6); + $cx += $d; + } + + $cy = self::$alignmentPattern[$version][0]; + for($y=0; $y<$w-1; $y++) { + $cx = self::$alignmentPattern[$version][0]; + for($x=0; $x<$w-1; $x++) { + self::putAlignmentMarker($frame, $cx, $cy); + $cx += $d; + } + $cy += $d; + } + } + + // Version information pattern ----------------------------------------- + + // Version information pattern (BCH coded). + // See Table 1 in Appendix D (pp.68) of JIS X0510:2004. + + // size: [QRSPEC_VERSION_MAX - 6] + + public static $versionPattern = array( + 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, + 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, + 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, + 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, + 0x27541, 0x28c69 + ); + + //---------------------------------------------------------------------- + public static function getVersionPattern($version) + { + if($version < 7 || $version > QRSPEC_VERSION_MAX) + return 0; + + return self::$versionPattern[$version -7]; + } + + // Format information -------------------------------------------------- + // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib) + + public static $formatInfo = array( + array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), + array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0), + array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed), + array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b) + ); + + public static function getFormatInfo($mask, $level) + { + if($mask < 0 || $mask > 7) + return 0; + + if($level < 0 || $level > 3) + return 0; + + return self::$formatInfo[$level][$mask]; + } + + // Frame --------------------------------------------------------------- + // Cache of initial frames. + + public static $frames = array(); + + /** -------------------------------------------------------------------- + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ + public static function putFinderPattern(&$frame, $ox, $oy) + { + $finder = array( + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" + ); + + for($y=0; $y<7; $y++) { + QRstr::set($frame, $ox, $oy+$y, $finder[$y]); + } + } + + //---------------------------------------------------------------------- + public static function createFrame($version) + { + $width = self::$capacity[$version][QRCAP_WIDTH]; + $frameLine = str_repeat ("\0", $width); + $frame = array_fill(0, $width, $frameLine); + + // Finder pattern + self::putFinderPattern($frame, 0, 0); + self::putFinderPattern($frame, $width - 7, 0); + self::putFinderPattern($frame, 0, $width - 7); + + // Separator + $yOffset = $width - 7; + + for($y=0; $y<7; $y++) { + $frame[$y][7] = "\xc0"; + $frame[$y][$width - 8] = "\xc0"; + $frame[$yOffset][7] = "\xc0"; + $yOffset++; + } + + $setPattern = str_repeat("\xc0", 8); + + QRstr::set($frame, 0, 7, $setPattern); + QRstr::set($frame, $width-8, 7, $setPattern); + QRstr::set($frame, 0, $width - 8, $setPattern); + + // Format info + $setPattern = str_repeat("\x84", 9); + QRstr::set($frame, 0, 8, $setPattern); + QRstr::set($frame, $width - 8, 8, $setPattern, 8); + + $yOffset = $width - 8; + + for($y=0; $y<8; $y++,$yOffset++) { + $frame[$y][8] = "\x84"; + $frame[$yOffset][8] = "\x84"; + } + + // Timing pattern + + for($i=1; $i<$width-15; $i++) { + $frame[6][7+$i] = chr(0x90 | ($i & 1)); + $frame[7+$i][6] = chr(0x90 | ($i & 1)); + } + + // Alignment pattern + self::putAlignmentPattern($version, $frame, $width); + + // Version information + if($version >= 7) { + $vinf = self::getVersionPattern($version); + + $v = $vinf; + + for($x=0; $x<6; $x++) { + for($y=0; $y<3; $y++) { + $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + + $v = $vinf; + for($y=0; $y<6; $y++) { + for($x=0; $x<3; $x++) { + $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + } + + // and a little bit... + $frame[$width - 8][8] = "\x81"; + + return $frame; + } + + //---------------------------------------------------------------------- + public static function debug($frame, $binary_mode = false) + { + if ($binary_mode) { + + foreach ($frame as &$frameLine) { + $frameLine = join('<span class="m">&nbsp;&nbsp;</span>', explode('0', $frameLine)); + $frameLine = join('&#9608;&#9608;', explode('1', $frameLine)); + } + + ?> + <style> + .m { background-color: white; } + </style> + <?php + echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'; + echo join("<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $frame); + echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >'; + + } else { + + foreach ($frame as &$frameLine) { + $frameLine = join('<span class="m">&nbsp;</span>', explode("\xc0", $frameLine)); + $frameLine = join('<span class="m">&#9618;</span>', explode("\xc1", $frameLine)); + $frameLine = join('<span class="p">&nbsp;</span>', explode("\xa0", $frameLine)); + $frameLine = join('<span class="p">&#9618;</span>', explode("\xa1", $frameLine)); + $frameLine = join('<span class="s">&#9671;</span>', explode("\x84", $frameLine)); //format 0 + $frameLine = join('<span class="s">&#9670;</span>', explode("\x85", $frameLine)); //format 1 + $frameLine = join('<span class="x">&#9762;</span>', explode("\x81", $frameLine)); //special bit + $frameLine = join('<span class="c">&nbsp;</span>', explode("\x90", $frameLine)); //clock 0 + $frameLine = join('<span class="c">&#9719;</span>', explode("\x91", $frameLine)); //clock 1 + $frameLine = join('<span class="f">&nbsp;</span>', explode("\x88", $frameLine)); //version + $frameLine = join('<span class="f">&#9618;</span>', explode("\x89", $frameLine)); //version + $frameLine = join('&#9830;', explode("\x01", $frameLine)); + $frameLine = join('&#8901;', explode("\0", $frameLine)); + } + + ?> + <style> + .p { background-color: yellow; } + .m { background-color: #00FF00; } + .s { background-color: #FF0000; } + .c { background-color: aqua; } + .x { background-color: pink; } + .f { background-color: gold; } + </style> + <?php + echo "<pre><tt>"; + echo join("<br/ >", $frame); + echo "</tt></pre>"; + + } + } + + //---------------------------------------------------------------------- + public static function serial($frame) + { + return gzcompress(join("\n", $frame), 9); + } + + //---------------------------------------------------------------------- + public static function unserial($code) + { + return explode("\n", gzuncompress($code)); + } + + //---------------------------------------------------------------------- + public static function newFrame($version) + { + if($version < 1 || $version > QRSPEC_VERSION_MAX) + return null; + + if(!isset(self::$frames[$version])) { + + $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat'; + + if (QR_CACHEABLE) { + if (file_exists($fileName)) { + self::$frames[$version] = self::unserial(file_get_contents($fileName)); + } else { + self::$frames[$version] = self::createFrame($version); + file_put_contents($fileName, self::serial(self::$frames[$version])); + } + } else { + self::$frames[$version] = self::createFrame($version); + } + } + + if(is_null(self::$frames[$version])) + return null; + + return self::$frames[$version]; + } + + //---------------------------------------------------------------------- + public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; } + public static function rsBlockNum1($spec) { return $spec[0]; } + public static function rsDataCodes1($spec) { return $spec[1]; } + public static function rsEccCodes1($spec) { return $spec[2]; } + public static function rsBlockNum2($spec) { return $spec[3]; } + public static function rsDataCodes2($spec) { return $spec[4]; } + public static function rsEccCodes2($spec) { return $spec[2]; } + public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); } + public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; } + + } + + + +//---- qrimage.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Image output of code using GD2 + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('QR_IMAGE', true); + + class QRimage { + + //---------------------------------------------------------------------- + public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE) + { + $image = self::image($frame, $pixelPerPoint, $outerFrame); + + if ($filename === false) { + Header("Content-type: image/png"); + ImagePng($image); + } else { + if($saveandprint===TRUE){ + ImagePng($image, $filename); + header("Content-type: image/png"); + ImagePng($image); + }else{ + ImagePng($image, $filename); + } + } + + ImageDestroy($image); + } + + //---------------------------------------------------------------------- + public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85) + { + $image = self::image($frame, $pixelPerPoint, $outerFrame); + + if ($filename === false) { + Header("Content-type: image/jpeg"); + ImageJpeg($image, null, $q); + } else { + ImageJpeg($image, $filename, $q); + } + + ImageDestroy($image); + } + + //---------------------------------------------------------------------- + private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4) + { + $h = count($frame); + $w = strlen($frame[0]); + + $imgW = $w + 2*$outerFrame; + $imgH = $h + 2*$outerFrame; + + $base_image =ImageCreate($imgW, $imgH); + + $col[0] = ImageColorAllocate($base_image,255,255,255); + $col[1] = ImageColorAllocate($base_image,0,0,0); + + imagefill($base_image, 0, 0, $col[0]); + + for($y=0; $y<$h; $y++) { + for($x=0; $x<$w; $x++) { + if ($frame[$y][$x] == '1') { + ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]); + } + } + } + + $target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint); + ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH); + ImageDestroy($base_image); + + return $target_image; + } + } + + + +//---- qrinput.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Input encoding class + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('STRUCTURE_HEADER_BITS', 20); + define('MAX_STRUCTURED_SYMBOLS', 16); + + class QRinputItem { + + public $mode; + public $size; + public $data; + public $bstream; + + public function __construct($mode, $size, $data, $bstream = null) + { + $setData = array_slice($data, 0, $size); + + if (count($setData) < $size) { + $setData = array_merge($setData, array_fill(0,$size-count($setData),0)); + } + + if(!QRinput::check($mode, $size, $setData)) { + throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData)); + return null; + } + + $this->mode = $mode; + $this->size = $size; + $this->data = $setData; + $this->bstream = $bstream; + } + + //---------------------------------------------------------------------- + public function encodeModeNum($version) + { + try { + + $words = (int)($this->size / 3); + $bs = new QRbitstream(); + + $val = 0x1; + $bs->appendNum(4, $val); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size); + + for($i=0; $i<$words; $i++) { + $val = (ord($this->data[$i*3 ]) - ord('0')) * 100; + $val += (ord($this->data[$i*3+1]) - ord('0')) * 10; + $val += (ord($this->data[$i*3+2]) - ord('0')); + $bs->appendNum(10, $val); + } + + if($this->size - $words * 3 == 1) { + $val = ord($this->data[$words*3]) - ord('0'); + $bs->appendNum(4, $val); + } else if($this->size - $words * 3 == 2) { + $val = (ord($this->data[$words*3 ]) - ord('0')) * 10; + $val += (ord($this->data[$words*3+1]) - ord('0')); + $bs->appendNum(7, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeAn($version) + { + try { + $words = (int)($this->size / 2); + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x02); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size); + + for($i=0; $i<$words; $i++) { + $val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45; + $val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1])); + + $bs->appendNum(11, $val); + } + + if($this->size & 1) { + $val = QRinput::lookAnTable(ord($this->data[$words * 2])); + $bs->appendNum(6, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeMode8($version) + { + try { + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x4); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size); + + for($i=0; $i<$this->size; $i++) { + $bs->appendNum(8, ord($this->data[$i])); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeKanji($version) + { + try { + + $bs = new QRbitrtream(); + + $bs->appendNum(4, 0x8); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2)); + + for($i=0; $i<$this->size; $i+=2) { + $val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]); + if($val <= 0x9ffc) { + $val -= 0x8140; + } else { + $val -= 0xc140; + } + + $h = ($val >> 8) * 0xc0; + $val = ($val & 0xff) + $h; + + $bs->appendNum(13, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeStructure() + { + try { + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x03); + $bs->appendNum(4, ord($this->data[1]) - 1); + $bs->appendNum(4, ord($this->data[0]) - 1); + $bs->appendNum(8, ord($this->data[2])); + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function estimateBitStreamSizeOfEntry($version) + { + $bits = 0; + + if($version == 0) + $version = 1; + + switch($this->mode) { + case QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size); break; + case QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size); break; + case QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size); break; + case QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break; + case QR_MODE_STRUCTURE: return STRUCTURE_HEADER_BITS; + default: + return 0; + } + + $l = QRspec::lengthIndicator($this->mode, $version); + $m = 1 << $l; + $num = (int)(($this->size + $m - 1) / $m); + + $bits += $num * (4 + $l); + + return $bits; + } + + //---------------------------------------------------------------------- + public function encodeBitStream($version) + { + try { + + unset($this->bstream); + $words = QRspec::maximumWords($this->mode, $version); + + if($this->size > $words) { + + $st1 = new QRinputItem($this->mode, $words, $this->data); + $st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words)); + + $st1->encodeBitStream($version); + $st2->encodeBitStream($version); + + $this->bstream = new QRbitstream(); + $this->bstream->append($st1->bstream); + $this->bstream->append($st2->bstream); + + unset($st1); + unset($st2); + + } else { + + $ret = 0; + + switch($this->mode) { + case QR_MODE_NUM: $ret = $this->encodeModeNum($version); break; + case QR_MODE_AN: $ret = $this->encodeModeAn($version); break; + case QR_MODE_8: $ret = $this->encodeMode8($version); break; + case QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break; + case QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure(); break; + + default: + break; + } + + if($ret < 0) + return -1; + } + + return $this->bstream->size(); + + } catch (Exception $e) { + return -1; + } + } + }; + + //########################################################################## + + class QRinput { + + public $items; + + private $version; + private $level; + + //---------------------------------------------------------------------- + public function __construct($version = 0, $level = QR_ECLEVEL_L) + { + if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) { + throw new Exception('Invalid version no'); + return NULL; + } + + $this->version = $version; + $this->level = $level; + } + + //---------------------------------------------------------------------- + public function getVersion() + { + return $this->version; + } + + //---------------------------------------------------------------------- + public function setVersion($version) + { + if($version < 0 || $version > QRSPEC_VERSION_MAX) { + throw new Exception('Invalid version no'); + return -1; + } + + $this->version = $version; + + return 0; + } + + //---------------------------------------------------------------------- + public function getErrorCorrectionLevel() + { + return $this->level; + } + + //---------------------------------------------------------------------- + public function setErrorCorrectionLevel($level) + { + if($level > QR_ECLEVEL_H) { + throw new Exception('Invalid ECLEVEL'); + return -1; + } + + $this->level = $level; + + return 0; + } + + //---------------------------------------------------------------------- + public function appendEntry(QRinputItem $entry) + { + $this->items[] = $entry; + } + + //---------------------------------------------------------------------- + public function append($mode, $size, $data) + { + try { + $entry = new QRinputItem($mode, $size, $data); + $this->items[] = $entry; + return 0; + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + + public function insertStructuredAppendHeader($size, $index, $parity) + { + if( $size > MAX_STRUCTURED_SYMBOLS ) { + throw new Exception('insertStructuredAppendHeader wrong size'); + } + + if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) { + throw new Exception('insertStructuredAppendHeader wrong index'); + } + + $buf = array($size, $index, $parity); + + try { + $entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf); + array_unshift($this->items, $entry); + return 0; + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function calcParity() + { + $parity = 0; + + foreach($this->items as $item) { + if($item->mode != QR_MODE_STRUCTURE) { + for($i=$item->size-1; $i>=0; $i--) { + $parity ^= $item->data[$i]; + } + } + } + + return $parity; + } + + //---------------------------------------------------------------------- + public static function checkModeNum($size, $data) + { + for($i=0; $i<$size; $i++) { + if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){ + return false; + } + } + + return true; + } + + //---------------------------------------------------------------------- + public static function estimateBitsModeNum($size) + { + $w = (int)$size / 3; + $bits = $w * 10; + + switch($size - $w * 3) { + case 1: + $bits += 4; + break; + case 2: + $bits += 7; + break; + default: + break; + } + + return $bits; + } + + //---------------------------------------------------------------------- + public static $anTable = array( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + ); + + //---------------------------------------------------------------------- + public static function lookAnTable($c) + { + return (($c > 127)?-1:self::$anTable[$c]); + } + + //---------------------------------------------------------------------- + public static function checkModeAn($size, $data) + { + for($i=0; $i<$size; $i++) { + if (self::lookAnTable(ord($data[$i])) == -1) { + return false; + } + } + + return true; + } + + //---------------------------------------------------------------------- + public static function estimateBitsModeAn($size) + { + $w = (int)($size / 2); + $bits = $w * 11; + + if($size & 1) { + $bits += 6; + } + + return $bits; + } + + //---------------------------------------------------------------------- + public static function estimateBitsMode8($size) + { + return $size * 8; + } + + //---------------------------------------------------------------------- + public function estimateBitsModeKanji($size) + { + return (int)(($size / 2) * 13); + } + + //---------------------------------------------------------------------- + public static function checkModeKanji($size, $data) + { + if($size & 1) + return false; + + for($i=0; $i<$size; $i+=2) { + $val = (ord($data[$i]) << 8) | ord($data[$i+1]); + if( $val < 0x8140 + || ($val > 0x9ffc && $val < 0xe040) + || $val > 0xebbf) { + return false; + } + } + + return true; + } + + /*********************************************************************** + * Validation + **********************************************************************/ + + public static function check($mode, $size, $data) + { + if($size <= 0) + return false; + + switch($mode) { + case QR_MODE_NUM: return self::checkModeNum($size, $data); break; + case QR_MODE_AN: return self::checkModeAn($size, $data); break; + case QR_MODE_KANJI: return self::checkModeKanji($size, $data); break; + case QR_MODE_8: return true; break; + case QR_MODE_STRUCTURE: return true; break; + + default: + break; + } + + return false; + } + + + //---------------------------------------------------------------------- + public function estimateBitStreamSize($version) + { + $bits = 0; + + foreach($this->items as $item) { + $bits += $item->estimateBitStreamSizeOfEntry($version); + } + + return $bits; + } + + //---------------------------------------------------------------------- + public function estimateVersion() + { + $version = 0; + $prev = 0; + do { + $prev = $version; + $bits = $this->estimateBitStreamSize($prev); + $version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if ($version < 0) { + return -1; + } + } while ($version > $prev); + + return $version; + } + + //---------------------------------------------------------------------- + public static function lengthOfCode($mode, $version, $bits) + { + $payload = $bits - 4 - QRspec::lengthIndicator($mode, $version); + switch($mode) { + case QR_MODE_NUM: + $chunks = (int)($payload / 10); + $remain = $payload - $chunks * 10; + $size = $chunks * 3; + if($remain >= 7) { + $size += 2; + } else if($remain >= 4) { + $size += 1; + } + break; + case QR_MODE_AN: + $chunks = (int)($payload / 11); + $remain = $payload - $chunks * 11; + $size = $chunks * 2; + if($remain >= 6) + $size++; + break; + case QR_MODE_8: + $size = (int)($payload / 8); + break; + case QR_MODE_KANJI: + $size = (int)(($payload / 13) * 2); + break; + case QR_MODE_STRUCTURE: + $size = (int)($payload / 8); + break; + default: + $size = 0; + break; + } + + $maxsize = QRspec::maximumWords($mode, $version); + if($size < 0) $size = 0; + if($size > $maxsize) $size = $maxsize; + + return $size; + } + + //---------------------------------------------------------------------- + public function createBitStream() + { + $total = 0; + + foreach($this->items as $item) { + $bits = $item->encodeBitStream($this->version); + + if($bits < 0) + return -1; + + $total += $bits; + } + + return $total; + } + + //---------------------------------------------------------------------- + public function convertData() + { + $ver = $this->estimateVersion(); + if($ver > $this->getVersion()) { + $this->setVersion($ver); + } + + for(;;) { + $bits = $this->createBitStream(); + + if($bits < 0) + return -1; + + $ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if($ver < 0) { + throw new Exception('WRONG VERSION'); + return -1; + } else if($ver > $this->getVersion()) { + $this->setVersion($ver); + } else { + break; + } + } + + return 0; + } + + //---------------------------------------------------------------------- + public function appendPaddingBit(&$bstream) + { + $bits = $bstream->size(); + $maxwords = QRspec::getDataLength($this->version, $this->level); + $maxbits = $maxwords * 8; + + if ($maxbits == $bits) { + return 0; + } + + if ($maxbits - $bits < 5) { + return $bstream->appendNum($maxbits - $bits, 0); + } + + $bits += 4; + $words = (int)(($bits + 7) / 8); + + $padding = new QRbitstream(); + $ret = $padding->appendNum($words * 8 - $bits + 4, 0); + + if($ret < 0) + return $ret; + + $padlen = $maxwords - $words; + + if($padlen > 0) { + + $padbuf = array(); + for($i=0; $i<$padlen; $i++) { + $padbuf[$i] = ($i&1)?0x11:0xec; + } + + $ret = $padding->appendBytes($padlen, $padbuf); + + if($ret < 0) + return $ret; + + } + + $ret = $bstream->append($padding); + + return $ret; + } + + //---------------------------------------------------------------------- + public function mergeBitStream() + { + if($this->convertData() < 0) { + return null; + } + + $bstream = new QRbitstream(); + + foreach($this->items as $item) { + $ret = $bstream->append($item->bstream); + if($ret < 0) { + return null; + } + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function getBitStream() + { + + $bstream = $this->mergeBitStream(); + + if($bstream == null) { + return null; + } + + $ret = $this->appendPaddingBit($bstream); + if($ret < 0) { + return null; + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function getByteStream() + { + $bstream = $this->getBitStream(); + if($bstream == null) { + return null; + } + + return $bstream->toByte(); + } + } + + + + + + +//---- qrbitstream.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Bitstream class + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRbitstream { + + public $data = array(); + + //---------------------------------------------------------------------- + public function size() + { + return count($this->data); + } + + //---------------------------------------------------------------------- + public function allocate($setLength) + { + $this->data = array_fill(0, $setLength, 0); + return 0; + } + + //---------------------------------------------------------------------- + public static function newFromNum($bits, $num) + { + $bstream = new QRbitstream(); + $bstream->allocate($bits); + + $mask = 1 << ($bits - 1); + for($i=0; $i<$bits; $i++) { + if($num & $mask) { + $bstream->data[$i] = 1; + } else { + $bstream->data[$i] = 0; + } + $mask = $mask >> 1; + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public static function newFromBytes($size, $data) + { + $bstream = new QRbitstream(); + $bstream->allocate($size * 8); + $p=0; + + for($i=0; $i<$size; $i++) { + $mask = 0x80; + for($j=0; $j<8; $j++) { + if($data[$i] & $mask) { + $bstream->data[$p] = 1; + } else { + $bstream->data[$p] = 0; + } + $p++; + $mask = $mask >> 1; + } + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function append(QRbitstream $arg) + { + if (is_null($arg)) { + return -1; + } + + if($arg->size() == 0) { + return 0; + } + + if($this->size() == 0) { + $this->data = $arg->data; + return 0; + } + + $this->data = array_values(array_merge($this->data, $arg->data)); + + return 0; + } + + //---------------------------------------------------------------------- + public function appendNum($bits, $num) + { + if ($bits == 0) + return 0; + + $b = QRbitstream::newFromNum($bits, $num); + + if(is_null($b)) + return -1; + + $ret = $this->append($b); + unset($b); + + return $ret; + } + + //---------------------------------------------------------------------- + public function appendBytes($size, $data) + { + if ($size == 0) + return 0; + + $b = QRbitstream::newFromBytes($size, $data); + + if(is_null($b)) + return -1; + + $ret = $this->append($b); + unset($b); + + return $ret; + } + + //---------------------------------------------------------------------- + public function toByte() + { + + $size = $this->size(); + + if($size == 0) { + return array(); + } + + $data = array_fill(0, (int)(($size + 7) / 8), 0); + $bytes = (int)($size / 8); + + $p = 0; + + for($i=0; $i<$bytes; $i++) { + $v = 0; + for($j=0; $j<8; $j++) { + $v = $v << 1; + $v |= $this->data[$p]; + $p++; + } + $data[$i] = $v; + } + + if($size & 7) { + $v = 0; + for($j=0; $j<($size & 7); $j++) { + $v = $v << 1; + $v |= $this->data[$p]; + $p++; + } + $data[$bytes] = $v; + } + + return $data; + } + + } + + + + +//---- qrsplit.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Input splitting classes + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + class QRsplit { + + public $dataStr = ''; + public $input; + public $modeHint; + + //---------------------------------------------------------------------- + public function __construct($dataStr, $input, $modeHint) + { + $this->dataStr = $dataStr; + $this->input = $input; + $this->modeHint = $modeHint; + } + + //---------------------------------------------------------------------- + public static function isdigitat($str, $pos) + { + if ($pos >= strlen($str)) + return false; + + return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9'))); + } + + //---------------------------------------------------------------------- + public static function isalnumat($str, $pos) + { + if ($pos >= strlen($str)) + return false; + + return (QRinput::lookAnTable(ord($str[$pos])) >= 0); + } + + //---------------------------------------------------------------------- + public function identifyMode($pos) + { + if ($pos >= strlen($this->dataStr)) + return QR_MODE_NUL; + + $c = $this->dataStr[$pos]; + + if(self::isdigitat($this->dataStr, $pos)) { + return QR_MODE_NUM; + } else if(self::isalnumat($this->dataStr, $pos)) { + return QR_MODE_AN; + } else if($this->modeHint == QR_MODE_KANJI) { + + if ($pos+1 < strlen($this->dataStr)) + { + $d = $this->dataStr[$pos+1]; + $word = (ord($c) << 8) | ord($d); + if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) { + return QR_MODE_KANJI; + } + } + } + + return QR_MODE_8; + } + + //---------------------------------------------------------------------- + public function eatNum() + { + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 0; + while(self::isdigitat($this->dataStr, $p)) { + $p++; + } + + $run = $p; + $mode = $this->identifyMode($p); + + if($mode == QR_MODE_8) { + $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln + + QRinput::estimateBitsMode8(1) // + 4 + l8 + - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 + if($dif > 0) { + return $this->eat8(); + } + } + if($mode == QR_MODE_AN) { + $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln + + QRinput::estimateBitsModeAn(1) // + 4 + la + - QRinput::estimateBitsModeAn($run + 1);// - 4 - la + if($dif > 0) { + return $this->eatAn(); + } + } + + $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eatAn() + { + $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 0; + + while(self::isalnumat($this->dataStr, $p)) { + if(self::isdigitat($this->dataStr, $p)) { + $q = $p; + while(self::isdigitat($this->dataStr, $q)) { + $q++; + } + + $dif = QRinput::estimateBitsModeAn($p) // + 4 + la + + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln + - QRinput::estimateBitsModeAn($q); // - 4 - la + + if($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + + $run = $p; + + if(!self::isalnumat($this->dataStr, $p)) { + $dif = QRinput::estimateBitsModeAn($run) + 4 + $la + + QRinput::estimateBitsMode8(1) // + 4 + l8 + - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 + if($dif > 0) { + return $this->eat8(); + } + } + + $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eatKanji() + { + $p = 0; + + while($this->identifyMode($p) == QR_MODE_KANJI) { + $p += 2; + } + + $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eat8() + { + $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 1; + $dataStrLen = strlen($this->dataStr); + + while($p < $dataStrLen) { + + $mode = $this->identifyMode($p); + if($mode == QR_MODE_KANJI) { + break; + } + if($mode == QR_MODE_NUM) { + $q = $p; + while(self::isdigitat($this->dataStr, $q)) { + $q++; + } + $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 + + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln + - QRinput::estimateBitsMode8($q); // - 4 - l8 + if($dif < 0) { + break; + } else { + $p = $q; + } + } else if($mode == QR_MODE_AN) { + $q = $p; + while(self::isalnumat($this->dataStr, $q)) { + $q++; + } + $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 + + QRinput::estimateBitsModeAn($q - $p) + 4 + $la + - QRinput::estimateBitsMode8($q); // - 4 - l8 + if($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + + $run = $p; + $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr)); + + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function splitString() + { + while (strlen($this->dataStr) > 0) + { + if($this->dataStr == '') + return 0; + + $mode = $this->identifyMode(0); + + switch ($mode) { + case QR_MODE_NUM: $length = $this->eatNum(); break; + case QR_MODE_AN: $length = $this->eatAn(); break; + case QR_MODE_KANJI: + if ($hint == QR_MODE_KANJI) + $length = $this->eatKanji(); + else $length = $this->eat8(); + break; + default: $length = $this->eat8(); break; + + } + + if($length == 0) return 0; + if($length < 0) return -1; + + $this->dataStr = substr($this->dataStr, $length); + } + } + + //---------------------------------------------------------------------- + public function toUpper() + { + $stringLen = strlen($this->dataStr); + $p = 0; + + while ($p<$stringLen) { + $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint); + if($mode == QR_MODE_KANJI) { + $p += 2; + } else { + if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) { + $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32); + } + $p++; + } + } + + return $this->dataStr; + } + + //---------------------------------------------------------------------- + public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true) + { + if(is_null($string) || $string == '\0' || $string == '') { + throw new Exception('empty string!!!'); + } + + $split = new QRsplit($string, $input, $modeHint); + + if(!$casesensitive) + $split->toUpper(); + + return $split->splitString(); + } + } + + + +//---- qrrscode.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Reed-Solomon error correction support + * + * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + * (libfec is released under the GNU Lesser General Public License.) + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRrsItem { + + public $mm; // Bits per symbol + public $nn; // Symbols per block (= (1<<mm)-1) + public $alpha_to = array(); // log lookup table + public $index_of = array(); // Antilog lookup table + public $genpoly = array(); // Generator polynomial + public $nroots; // Number of generator roots = number of parity symbols + public $fcr; // First consecutive root, index form + public $prim; // Primitive element, index form + public $iprim; // prim-th root of 1, index form + public $pad; // Padding bytes in shortened block + public $gfpoly; + + //---------------------------------------------------------------------- + public function modnn($x) + { + while ($x >= $this->nn) { + $x -= $this->nn; + $x = ($x >> $this->mm) + ($x & $this->nn); + } + + return $x; + } + + //---------------------------------------------------------------------- + public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) + { + // Common code for intializing a Reed-Solomon control block (char or int symbols) + // Copyright 2004 Phil Karn, KA9Q + // May be used under the terms of the GNU Lesser General Public License (LGPL) + + $rs = null; + + // Check parameter ranges + if($symsize < 0 || $symsize > 8) return $rs; + if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs; + if($prim <= 0 || $prim >= (1<<$symsize)) return $rs; + if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values! + if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding + + $rs = new QRrsItem(); + $rs->mm = $symsize; + $rs->nn = (1<<$symsize)-1; + $rs->pad = $pad; + + $rs->alpha_to = array_fill(0, $rs->nn+1, 0); + $rs->index_of = array_fill(0, $rs->nn+1, 0); + + // PHP style macro replacement ;) + $NN =& $rs->nn; + $A0 =& $NN; + + // Generate Galois field lookup tables + $rs->index_of[0] = $A0; // log(zero) = -inf + $rs->alpha_to[$A0] = 0; // alpha**-inf = 0 + $sr = 1; + + for($i=0; $i<$rs->nn; $i++) { + $rs->index_of[$sr] = $i; + $rs->alpha_to[$i] = $sr; + $sr <<= 1; + if($sr & (1<<$symsize)) { + $sr ^= $gfpoly; + } + $sr &= $rs->nn; + } + + if($sr != 1){ + // field generator polynomial is not primitive! + $rs = NULL; + return $rs; + } + + /* Form RS code generator polynomial from its roots */ + $rs->genpoly = array_fill(0, $nroots+1, 0); + + $rs->fcr = $fcr; + $rs->prim = $prim; + $rs->nroots = $nroots; + $rs->gfpoly = $gfpoly; + + /* Find prim-th root of 1, used in decoding */ + for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn) + ; // intentional empty-body loop! + + $rs->iprim = (int)($iprim / $prim); + $rs->genpoly[0] = 1; + + for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) { + $rs->genpoly[$i+1] = 1; + + // Multiply rs->genpoly[] by @**(root + x) + for ($j = $i; $j > 0; $j--) { + if ($rs->genpoly[$j] != 0) { + $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)]; + } else { + $rs->genpoly[$j] = $rs->genpoly[$j-1]; + } + } + // rs->genpoly[0] can never be zero + $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)]; + } + + // convert rs->genpoly[] to index form for quicker encoding + for ($i = 0; $i <= $nroots; $i++) + $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]]; + + return $rs; + } + + //---------------------------------------------------------------------- + public function encode_rs_char($data, &$parity) + { + $MM =& $this->mm; + $NN =& $this->nn; + $ALPHA_TO =& $this->alpha_to; + $INDEX_OF =& $this->index_of; + $GENPOLY =& $this->genpoly; + $NROOTS =& $this->nroots; + $FCR =& $this->fcr; + $PRIM =& $this->prim; + $IPRIM =& $this->iprim; + $PAD =& $this->pad; + $A0 =& $NN; + + $parity = array_fill(0, $NROOTS, 0); + + for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) { + + $feedback = $INDEX_OF[$data[$i] ^ $parity[0]]; + if($feedback != $A0) { + // feedback term is non-zero + + // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must + // always be for the polynomials constructed by init_rs() + $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback); + + for($j=1;$j<$NROOTS;$j++) { + $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])]; + } + } + + // Shift + array_shift($parity); + if($feedback != $A0) { + array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]); + } else { + array_push($parity, 0); + } + } + } + } + + //########################################################################## + + class QRrs { + + public static $items = array(); + + //---------------------------------------------------------------------- + public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) + { + foreach(self::$items as $rs) { + if($rs->pad != $pad) continue; + if($rs->nroots != $nroots) continue; + if($rs->mm != $symsize) continue; + if($rs->gfpoly != $gfpoly) continue; + if($rs->fcr != $fcr) continue; + if($rs->prim != $prim) continue; + + return $rs; + } + + $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad); + array_unshift(self::$items, $rs); + + return $rs; + } + } + + + +//---- qrmask.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Masking + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('N1', 3); + define('N2', 3); + define('N3', 40); + define('N4', 10); + + class QRmask { + + public $runLength = array(); + + //---------------------------------------------------------------------- + public function __construct() + { + $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0); + } + + //---------------------------------------------------------------------- + public function writeFormatInformation($width, &$frame, $mask, $level) + { + $blacks = 0; + $format = QRspec::getFormatInfo($mask, $level); + + for($i=0; $i<8; $i++) { + if($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + + $frame[8][$width - 1 - $i] = chr($v); + if($i < 6) { + $frame[$i][8] = chr($v); + } else { + $frame[$i + 1][8] = chr($v); + } + $format = $format >> 1; + } + + for($i=0; $i<7; $i++) { + if($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + + $frame[$width - 7 + $i][8] = chr($v); + if($i == 0) { + $frame[8][7] = chr($v); + } else { + $frame[8][6 - $i] = chr($v); + } + + $format = $format >> 1; + } + + return $blacks; + } + + //---------------------------------------------------------------------- + public function mask0($x, $y) { return ($x+$y)&1; } + public function mask1($x, $y) { return ($y&1); } + public function mask2($x, $y) { return ($x%3); } + public function mask3($x, $y) { return ($x+$y)%3; } + public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; } + public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; } + public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; } + public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; } + + //---------------------------------------------------------------------- + private function generateMaskNo($maskNo, $width, $frame) + { + $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); + + for($y=0; $y<$width; $y++) { + for($x=0; $x<$width; $x++) { + if(ord($frame[$y][$x]) & 0x80) { + $bitMask[$y][$x] = 0; + } else { + $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y); + $bitMask[$y][$x] = ($maskFunc == 0)?1:0; + } + + } + } + + return $bitMask; + } + + //---------------------------------------------------------------------- + public static function serial($bitFrame) + { + $codeArr = array(); + + foreach ($bitFrame as $line) + $codeArr[] = join('', $line); + + return gzcompress(join("\n", $codeArr), 9); + } + + //---------------------------------------------------------------------- + public static function unserial($code) + { + $codeArr = array(); + + $codeLines = explode("\n", gzuncompress($code)); + foreach ($codeLines as $line) + $codeArr[] = str_split($line); + + return $codeArr; + } + + //---------------------------------------------------------------------- + public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false) + { + $b = 0; + $bitMask = array(); + + $fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat'; + + if (QR_CACHEABLE) { + if (file_exists($fileName)) { + $bitMask = self::unserial(file_get_contents($fileName)); + } else { + $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); + if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo)) + mkdir(QR_CACHE_DIR.'mask_'.$maskNo); + file_put_contents($fileName, self::serial($bitMask)); + } + } else { + $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); + } + + if ($maskGenOnly) + return; + + $d = $s; + + for($y=0; $y<$width; $y++) { + for($x=0; $x<$width; $x++) { + if($bitMask[$y][$x] == 1) { + $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]); + } + $b += (int)(ord($d[$y][$x]) & 1); + } + } + + return $b; + } + + //---------------------------------------------------------------------- + public function makeMask($width, $frame, $maskNo, $level) + { + $masked = array_fill(0, $width, str_repeat("\0", $width)); + $this->makeMaskNo($maskNo, $width, $frame, $masked); + $this->writeFormatInformation($width, $masked, $maskNo, $level); + + return $masked; + } + + //---------------------------------------------------------------------- + public function calcN1N3($length) + { + $demerit = 0; + + for($i=0; $i<$length; $i++) { + + if($this->runLength[$i] >= 5) { + $demerit += (N1 + ($this->runLength[$i] - 5)); + } + if($i & 1) { + if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) { + $fact = (int)($this->runLength[$i] / 3); + if(($this->runLength[$i-2] == $fact) && + ($this->runLength[$i-1] == $fact) && + ($this->runLength[$i+1] == $fact) && + ($this->runLength[$i+2] == $fact)) { + if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) { + $demerit += N3; + } else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) { + $demerit += N3; + } + } + } + } + } + return $demerit; + } + + //---------------------------------------------------------------------- + public function evaluateSymbol($width, $frame) + { + $head = 0; + $demerit = 0; + + for($y=0; $y<$width; $y++) { + $head = 0; + $this->runLength[0] = 1; + + $frameY = $frame[$y]; + + if ($y>0) + $frameYM = $frame[$y-1]; + + for($x=0; $x<$width; $x++) { + if(($x > 0) && ($y > 0)) { + $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]); + $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]); + + if(($b22 | ($w22 ^ 1))&1) { + $demerit += N2; + } + } + if(($x == 0) && (ord($frameY[$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } else if($x > 0) { + if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + + $demerit += $this->calcN1N3($head+1); + } + + for($x=0; $x<$width; $x++) { + $head = 0; + $this->runLength[0] = 1; + + for($y=0; $y<$width; $y++) { + if($y == 0 && (ord($frame[$y][$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } else if($y > 0) { + if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + + $demerit += $this->calcN1N3($head+1); + } + + return $demerit; + } + + + //---------------------------------------------------------------------- + public function mask($width, $frame, $level) + { + $minDemerit = PHP_INT_MAX; + $bestMaskNum = 0; + $bestMask = array(); + + $checked_masks = array(0,1,2,3,4,5,6,7); + + if (QR_FIND_FROM_RANDOM !== false) { + + $howManuOut = 8-(QR_FIND_FROM_RANDOM % 9); + for ($i = 0; $i < $howManuOut; $i++) { + $remPos = rand (0, count($checked_masks)-1); + unset($checked_masks[$remPos]); + $checked_masks = array_values($checked_masks); + } + + } + + $bestMask = $frame; + + foreach($checked_masks as $i) { + $mask = array_fill(0, $width, str_repeat("\0", $width)); + + $demerit = 0; + $blacks = 0; + $blacks = $this->makeMaskNo($i, $width, $frame, $mask); + $blacks += $this->writeFormatInformation($width, $mask, $i, $level); + $blacks = (int)(100 * $blacks / ($width * $width)); + $demerit = (int)((int)(abs($blacks - 50) / 5) * N4); + $demerit += $this->evaluateSymbol($width, $mask); + + if($demerit < $minDemerit) { + $minDemerit = $demerit; + $bestMask = $mask; + $bestMaskNum = $i; + } + } + + return $bestMask; + } + + //---------------------------------------------------------------------- + } + + + + +//---- qrencode.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Main encoder classes. + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRrsblock { + public $dataLength; + public $data = array(); + public $eccLength; + public $ecc = array(); + + public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs) + { + $rs->encode_rs_char($data, $ecc); + + $this->dataLength = $dl; + $this->data = $data; + $this->eccLength = $el; + $this->ecc = $ecc; + } + }; + + //########################################################################## + + class QRrawcode { + public $version; + public $datacode = array(); + public $ecccode = array(); + public $blocks; + public $rsblocks = array(); //of RSblock + public $count; + public $dataLength; + public $eccLength; + public $b1; + + //---------------------------------------------------------------------- + public function __construct(QRinput $input) + { + $spec = array(0,0,0,0,0); + + $this->datacode = $input->getByteStream(); + if(is_null($this->datacode)) { + throw new Exception('null imput string'); + } + + QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec); + + $this->version = $input->getVersion(); + $this->b1 = QRspec::rsBlockNum1($spec); + $this->dataLength = QRspec::rsDataLength($spec); + $this->eccLength = QRspec::rsEccLength($spec); + $this->ecccode = array_fill(0, $this->eccLength, 0); + $this->blocks = QRspec::rsBlockNum($spec); + + $ret = $this->init($spec); + if($ret < 0) { + throw new Exception('block alloc error'); + return null; + } + + $this->count = 0; + } + + //---------------------------------------------------------------------- + public function init(array $spec) + { + $dl = QRspec::rsDataCodes1($spec); + $el = QRspec::rsEccCodes1($spec); + $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + + + $blockNo = 0; + $dataPos = 0; + $eccPos = 0; + for($i=0; $i<QRspec::rsBlockNum1($spec); $i++) { + $ecc = array_slice($this->ecccode,$eccPos); + $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); + $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); + + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + + if(QRspec::rsBlockNum2($spec) == 0) + return 0; + + $dl = QRspec::rsDataCodes2($spec); + $el = QRspec::rsEccCodes2($spec); + $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + + if($rs == NULL) return -1; + + for($i=0; $i<QRspec::rsBlockNum2($spec); $i++) { + $ecc = array_slice($this->ecccode,$eccPos); + $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); + $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); + + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + + return 0; + } + + //---------------------------------------------------------------------- + public function getCode() + { + $ret; + + if($this->count < $this->dataLength) { + $row = $this->count % $this->blocks; + $col = $this->count / $this->blocks; + if($col >= $this->rsblocks[0]->dataLength) { + $row += $this->b1; + } + $ret = $this->rsblocks[$row]->data[$col]; + } else if($this->count < $this->dataLength + $this->eccLength) { + $row = ($this->count - $this->dataLength) % $this->blocks; + $col = ($this->count - $this->dataLength) / $this->blocks; + $ret = $this->rsblocks[$row]->ecc[$col]; + } else { + return 0; + } + $this->count++; + + return $ret; + } + } + + //########################################################################## + + class QRcode { + + public $version; + public $width; + public $data; + + //---------------------------------------------------------------------- + public function encodeMask(QRinput $input, $mask) + { + if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) { + throw new Exception('wrong version'); + } + if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) { + throw new Exception('wrong level'); + } + + $raw = new QRrawcode($input); + + QRtools::markTime('after_raw'); + + $version = $raw->version; + $width = QRspec::getWidth($version); + $frame = QRspec::newFrame($version); + + $filler = new FrameFiller($width, $frame); + if(is_null($filler)) { + return NULL; + } + + // inteleaved data and ecc codes + for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) { + $code = $raw->getCode(); + $bit = 0x80; + for($j=0; $j<8; $j++) { + $addr = $filler->next(); + $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0)); + $bit = $bit >> 1; + } + } + + QRtools::markTime('after_filler'); + + unset($raw); + + // remainder bits + $j = QRspec::getRemainder($version); + for($i=0; $i<$j; $i++) { + $addr = $filler->next(); + $filler->setFrameAt($addr, 0x02); + } + + $frame = $filler->frame; + unset($filler); + + + // masking + $maskObj = new QRmask(); + if($mask < 0) { + + if (QR_FIND_BEST_MASK) { + $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel()); + } else { + $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel()); + } + } else { + $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel()); + } + + if($masked == NULL) { + return NULL; + } + + QRtools::markTime('after_mask'); + + $this->version = $version; + $this->width = $width; + $this->data = $masked; + + return $this; + } + + //---------------------------------------------------------------------- + public function encodeInput(QRinput $input) + { + return $this->encodeMask($input, -1); + } + + //---------------------------------------------------------------------- + public function encodeString8bit($string, $version, $level) + { + if(string == NULL) { + throw new Exception('empty string!'); + return NULL; + } + + $input = new QRinput($version, $level); + if($input == NULL) return NULL; + + $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string)); + if($ret < 0) { + unset($input); + return NULL; + } + return $this->encodeInput($input); + } + + //---------------------------------------------------------------------- + public function encodeString($string, $version, $level, $hint, $casesensitive) + { + + if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) { + throw new Exception('bad hint'); + return NULL; + } + + $input = new QRinput($version, $level); + if($input == NULL) return NULL; + + $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive); + if($ret < 0) { + return NULL; + } + + return $this->encodeInput($input); + } + + //---------------------------------------------------------------------- + public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encodePNG($text, $outfile, $saveandprint=false); + } + + //---------------------------------------------------------------------- + public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encode($text, $outfile); + } + + //---------------------------------------------------------------------- + public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encodeRAW($text, $outfile); + } + } + + //########################################################################## + + class FrameFiller { + + public $width; + public $frame; + public $x; + public $y; + public $dir; + public $bit; + + //---------------------------------------------------------------------- + public function __construct($width, &$frame) + { + $this->width = $width; + $this->frame = $frame; + $this->x = $width - 1; + $this->y = $width - 1; + $this->dir = -1; + $this->bit = -1; + } + + //---------------------------------------------------------------------- + public function setFrameAt($at, $val) + { + $this->frame[$at['y']][$at['x']] = chr($val); + } + + //---------------------------------------------------------------------- + public function getFrameAt($at) + { + return ord($this->frame[$at['y']][$at['x']]); + } + + //---------------------------------------------------------------------- + public function next() + { + do { + + if($this->bit == -1) { + $this->bit = 0; + return array('x'=>$this->x, 'y'=>$this->y); + } + + $x = $this->x; + $y = $this->y; + $w = $this->width; + + if($this->bit == 0) { + $x--; + $this->bit++; + } else { + $x++; + $y += $this->dir; + $this->bit--; + } + + if($this->dir < 0) { + if($y < 0) { + $y = 0; + $x -= 2; + $this->dir = 1; + if($x == 6) { + $x--; + $y = 9; + } + } + } else { + if($y == $w) { + $y = $w - 1; + $x -= 2; + $this->dir = -1; + if($x == 6) { + $x--; + $y -= 8; + } + } + } + if($x < 0 || $y < 0) return null; + + $this->x = $x; + $this->y = $y; + + } while(ord($this->frame[$y][$x]) & 0x80); + + return array('x'=>$x, 'y'=>$y); + } + + } ; + + //########################################################################## + + class QRencode { + + public $casesensitive = true; + public $eightbit = false; + + public $version = 0; + public $size = 3; + public $margin = 4; + + public $structured = 0; // not supported yet + + public $level = QR_ECLEVEL_L; + public $hint = QR_MODE_8; + + //---------------------------------------------------------------------- + public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = new QRencode(); + $enc->size = $size; + $enc->margin = $margin; + + switch ($level.'') { + case '0': + case '1': + case '2': + case '3': + $enc->level = $level; + break; + case 'l': + case 'L': + $enc->level = QR_ECLEVEL_L; + break; + case 'm': + case 'M': + $enc->level = QR_ECLEVEL_M; + break; + case 'q': + case 'Q': + $enc->level = QR_ECLEVEL_Q; + break; + case 'h': + case 'H': + $enc->level = QR_ECLEVEL_H; + break; + } + + return $enc; + } + + //---------------------------------------------------------------------- + public function encodeRAW($intext, $outfile = false) + { + $code = new QRcode(); + + if($this->eightbit) { + $code->encodeString8bit($intext, $this->version, $this->level); + } else { + $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); + } + + return $code->data; + } + + //---------------------------------------------------------------------- + public function encode($intext, $outfile = false) + { + $code = new QRcode(); + + if($this->eightbit) { + $code->encodeString8bit($intext, $this->version, $this->level); + } else { + $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); + } + + QRtools::markTime('after_encode'); + + if ($outfile!== false) { + file_put_contents($outfile, join("\n", QRtools::binarize($code->data))); + } else { + return QRtools::binarize($code->data); + } + } + + //---------------------------------------------------------------------- + public function encodePNG($intext, $outfile = false,$saveandprint=false) + { + try { + + ob_start(); + $tab = $this->encode($intext); + $err = ob_get_contents(); + ob_end_clean(); + + if ($err != '') + QRtools::log($outfile, $err); + + $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin)); + + QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint); + + } catch (Exception $e) { + + QRtools::log($outfile, $e->getMessage()); + + } + } + } + + diff --git a/src/admin/application/libs/phpqrcode/qrbitstream.php b/src/admin/application/libs/phpqrcode/qrbitstream.php new file mode 100755 index 0000000..7d4ec4a --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrbitstream.php @@ -0,0 +1,180 @@ +<?php +/* + * PHP QR Code encoder + * + * Bitstream class + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRbitstream { + + public $data = array(); + + //---------------------------------------------------------------------- + public function size() + { + return count($this->data); + } + + //---------------------------------------------------------------------- + public function allocate($setLength) + { + $this->data = array_fill(0, $setLength, 0); + return 0; + } + + //---------------------------------------------------------------------- + public static function newFromNum($bits, $num) + { + $bstream = new QRbitstream(); + $bstream->allocate($bits); + + $mask = 1 << ($bits - 1); + for($i=0; $i<$bits; $i++) { + if($num & $mask) { + $bstream->data[$i] = 1; + } else { + $bstream->data[$i] = 0; + } + $mask = $mask >> 1; + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public static function newFromBytes($size, $data) + { + $bstream = new QRbitstream(); + $bstream->allocate($size * 8); + $p=0; + + for($i=0; $i<$size; $i++) { + $mask = 0x80; + for($j=0; $j<8; $j++) { + if($data[$i] & $mask) { + $bstream->data[$p] = 1; + } else { + $bstream->data[$p] = 0; + } + $p++; + $mask = $mask >> 1; + } + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function append(QRbitstream $arg) + { + if (is_null($arg)) { + return -1; + } + + if($arg->size() == 0) { + return 0; + } + + if($this->size() == 0) { + $this->data = $arg->data; + return 0; + } + + $this->data = array_values(array_merge($this->data, $arg->data)); + + return 0; + } + + //---------------------------------------------------------------------- + public function appendNum($bits, $num) + { + if ($bits == 0) + return 0; + + $b = QRbitstream::newFromNum($bits, $num); + + if(is_null($b)) + return -1; + + $ret = $this->append($b); + unset($b); + + return $ret; + } + + //---------------------------------------------------------------------- + public function appendBytes($size, $data) + { + if ($size == 0) + return 0; + + $b = QRbitstream::newFromBytes($size, $data); + + if(is_null($b)) + return -1; + + $ret = $this->append($b); + unset($b); + + return $ret; + } + + //---------------------------------------------------------------------- + public function toByte() + { + + $size = $this->size(); + + if($size == 0) { + return array(); + } + + $data = array_fill(0, (int)(($size + 7) / 8), 0); + $bytes = (int)($size / 8); + + $p = 0; + + for($i=0; $i<$bytes; $i++) { + $v = 0; + for($j=0; $j<8; $j++) { + $v = $v << 1; + $v |= $this->data[$p]; + $p++; + } + $data[$i] = $v; + } + + if($size & 7) { + $v = 0; + for($j=0; $j<($size & 7); $j++) { + $v = $v << 1; + $v |= $this->data[$p]; + $p++; + } + $data[$bytes] = $v; + } + + return $data; + } + + } diff --git a/src/admin/application/libs/phpqrcode/qrconfig.php b/src/admin/application/libs/phpqrcode/qrconfig.php new file mode 100755 index 0000000..450a8cb --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrconfig.php @@ -0,0 +1,16 @@ +<?php +/* + * PHP QR Code encoder + * + * Config file, feel free to modify + */ + + define('QR_CACHEABLE', true); // use cache - more disk reads but less CPU power, masks and format templates are stored there + define('QR_CACHE_DIR', dirname(__FILE__).'/../../..'.DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR); // used when QR_CACHEABLE === true + define('QR_LOG_DIR', dirname(__FILE__).'/../../application/'.DIRECTORY_SEPARATOR); // default error logs dir + + define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code + define('QR_FIND_FROM_RANDOM', false); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly + define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false + + define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images diff --git a/src/admin/application/libs/phpqrcode/qrconst.php b/src/admin/application/libs/phpqrcode/qrconst.php new file mode 100755 index 0000000..9fac9fd --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrconst.php @@ -0,0 +1,54 @@ +<?php + +/* + * PHP QR Code encoder + * + * Common constants + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + // Encoding modes + + define('QR_MODE_NUL', -1); + define('QR_MODE_NUM', 0); + define('QR_MODE_AN', 1); + define('QR_MODE_8', 2); + define('QR_MODE_KANJI', 3); + define('QR_MODE_STRUCTURE', 4); + + // Levels of error correction. + + define('QR_ECLEVEL_L', 0); + define('QR_ECLEVEL_M', 1); + define('QR_ECLEVEL_Q', 2); + define('QR_ECLEVEL_H', 3); + + // Supported output formats + + define('QR_FORMAT_TEXT', 0); + define('QR_FORMAT_PNG', 1); + + class qrstr { + public static function set(&$srctab, $x, $y, $repl, $replLen = false) { + $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl)); + } + } \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/qrencode.php b/src/admin/application/libs/phpqrcode/qrencode.php new file mode 100755 index 0000000..4b77a5b --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrencode.php @@ -0,0 +1,502 @@ +<?php +/* + * PHP QR Code encoder + * + * Main encoder classes. + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRrsblock { + public $dataLength; + public $data = array(); + public $eccLength; + public $ecc = array(); + + public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs) + { + $rs->encode_rs_char($data, $ecc); + + $this->dataLength = $dl; + $this->data = $data; + $this->eccLength = $el; + $this->ecc = $ecc; + } + }; + + //########################################################################## + + class QRrawcode { + public $version; + public $datacode = array(); + public $ecccode = array(); + public $blocks; + public $rsblocks = array(); //of RSblock + public $count; + public $dataLength; + public $eccLength; + public $b1; + + //---------------------------------------------------------------------- + public function __construct(QRinput $input) + { + $spec = array(0,0,0,0,0); + + $this->datacode = $input->getByteStream(); + if(is_null($this->datacode)) { + throw new Exception('null imput string'); + } + + QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec); + + $this->version = $input->getVersion(); + $this->b1 = QRspec::rsBlockNum1($spec); + $this->dataLength = QRspec::rsDataLength($spec); + $this->eccLength = QRspec::rsEccLength($spec); + $this->ecccode = array_fill(0, $this->eccLength, 0); + $this->blocks = QRspec::rsBlockNum($spec); + + $ret = $this->init($spec); + if($ret < 0) { + throw new Exception('block alloc error'); + return null; + } + + $this->count = 0; + } + + //---------------------------------------------------------------------- + public function init(array $spec) + { + $dl = QRspec::rsDataCodes1($spec); + $el = QRspec::rsEccCodes1($spec); + $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + + + $blockNo = 0; + $dataPos = 0; + $eccPos = 0; + for($i=0; $i<QRspec::rsBlockNum1($spec); $i++) { + $ecc = array_slice($this->ecccode,$eccPos); + $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); + $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); + + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + + if(QRspec::rsBlockNum2($spec) == 0) + return 0; + + $dl = QRspec::rsDataCodes2($spec); + $el = QRspec::rsEccCodes2($spec); + $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + + if($rs == NULL) return -1; + + for($i=0; $i<QRspec::rsBlockNum2($spec); $i++) { + $ecc = array_slice($this->ecccode,$eccPos); + $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); + $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); + + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + + return 0; + } + + //---------------------------------------------------------------------- + public function getCode() + { + $ret; + + if($this->count < $this->dataLength) { + $row = $this->count % $this->blocks; + $col = $this->count / $this->blocks; + if($col >= $this->rsblocks[0]->dataLength) { + $row += $this->b1; + } + $ret = $this->rsblocks[$row]->data[$col]; + } else if($this->count < $this->dataLength + $this->eccLength) { + $row = ($this->count - $this->dataLength) % $this->blocks; + $col = ($this->count - $this->dataLength) / $this->blocks; + $ret = $this->rsblocks[$row]->ecc[$col]; + } else { + return 0; + } + $this->count++; + + return $ret; + } + } + + //########################################################################## + + class QRcode { + + public $version; + public $width; + public $data; + + //---------------------------------------------------------------------- + public function encodeMask(QRinput $input, $mask) + { + if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) { + throw new Exception('wrong version'); + } + if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) { + throw new Exception('wrong level'); + } + + $raw = new QRrawcode($input); + + QRtools::markTime('after_raw'); + + $version = $raw->version; + $width = QRspec::getWidth($version); + $frame = QRspec::newFrame($version); + + $filler = new FrameFiller($width, $frame); + if(is_null($filler)) { + return NULL; + } + + // inteleaved data and ecc codes + for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) { + $code = $raw->getCode(); + $bit = 0x80; + for($j=0; $j<8; $j++) { + $addr = $filler->next(); + $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0)); + $bit = $bit >> 1; + } + } + + QRtools::markTime('after_filler'); + + unset($raw); + + // remainder bits + $j = QRspec::getRemainder($version); + for($i=0; $i<$j; $i++) { + $addr = $filler->next(); + $filler->setFrameAt($addr, 0x02); + } + + $frame = $filler->frame; + unset($filler); + + + // masking + $maskObj = new QRmask(); + if($mask < 0) { + + if (QR_FIND_BEST_MASK) { + $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel()); + } else { + $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel()); + } + } else { + $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel()); + } + + if($masked == NULL) { + return NULL; + } + + QRtools::markTime('after_mask'); + + $this->version = $version; + $this->width = $width; + $this->data = $masked; + + return $this; + } + + //---------------------------------------------------------------------- + public function encodeInput(QRinput $input) + { + return $this->encodeMask($input, -1); + } + + //---------------------------------------------------------------------- + public function encodeString8bit($string, $version, $level) + { + if(string == NULL) { + throw new Exception('empty string!'); + return NULL; + } + + $input = new QRinput($version, $level); + if($input == NULL) return NULL; + + $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string)); + if($ret < 0) { + unset($input); + return NULL; + } + return $this->encodeInput($input); + } + + //---------------------------------------------------------------------- + public function encodeString($string, $version, $level, $hint, $casesensitive) + { + + if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) { + throw new Exception('bad hint'); + return NULL; + } + + $input = new QRinput($version, $level); + if($input == NULL) return NULL; + + $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive); + if($ret < 0) { + return NULL; + } + + return $this->encodeInput($input); + } + + //---------------------------------------------------------------------- + public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encodePNG($text, $outfile, $saveandprint=false); + } + + //---------------------------------------------------------------------- + public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encode($text, $outfile); + } + + //---------------------------------------------------------------------- + public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encodeRAW($text, $outfile); + } + } + + //########################################################################## + + class FrameFiller { + + public $width; + public $frame; + public $x; + public $y; + public $dir; + public $bit; + + //---------------------------------------------------------------------- + public function __construct($width, &$frame) + { + $this->width = $width; + $this->frame = $frame; + $this->x = $width - 1; + $this->y = $width - 1; + $this->dir = -1; + $this->bit = -1; + } + + //---------------------------------------------------------------------- + public function setFrameAt($at, $val) + { + $this->frame[$at['y']][$at['x']] = chr($val); + } + + //---------------------------------------------------------------------- + public function getFrameAt($at) + { + return ord($this->frame[$at['y']][$at['x']]); + } + + //---------------------------------------------------------------------- + public function next() + { + do { + + if($this->bit == -1) { + $this->bit = 0; + return array('x'=>$this->x, 'y'=>$this->y); + } + + $x = $this->x; + $y = $this->y; + $w = $this->width; + + if($this->bit == 0) { + $x--; + $this->bit++; + } else { + $x++; + $y += $this->dir; + $this->bit--; + } + + if($this->dir < 0) { + if($y < 0) { + $y = 0; + $x -= 2; + $this->dir = 1; + if($x == 6) { + $x--; + $y = 9; + } + } + } else { + if($y == $w) { + $y = $w - 1; + $x -= 2; + $this->dir = -1; + if($x == 6) { + $x--; + $y -= 8; + } + } + } + if($x < 0 || $y < 0) return null; + + $this->x = $x; + $this->y = $y; + + } while(ord($this->frame[$y][$x]) & 0x80); + + return array('x'=>$x, 'y'=>$y); + } + + } ; + + //########################################################################## + + class QRencode { + + public $casesensitive = true; + public $eightbit = false; + + public $version = 0; + public $size = 3; + public $margin = 4; + + public $structured = 0; // not supported yet + + public $level = QR_ECLEVEL_L; + public $hint = QR_MODE_8; + + //---------------------------------------------------------------------- + public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = new QRencode(); + $enc->size = $size; + $enc->margin = $margin; + + switch ($level.'') { + case '0': + case '1': + case '2': + case '3': + $enc->level = $level; + break; + case 'l': + case 'L': + $enc->level = QR_ECLEVEL_L; + break; + case 'm': + case 'M': + $enc->level = QR_ECLEVEL_M; + break; + case 'q': + case 'Q': + $enc->level = QR_ECLEVEL_Q; + break; + case 'h': + case 'H': + $enc->level = QR_ECLEVEL_H; + break; + } + + return $enc; + } + + //---------------------------------------------------------------------- + public function encodeRAW($intext, $outfile = false) + { + $code = new QRcode(); + + if($this->eightbit) { + $code->encodeString8bit($intext, $this->version, $this->level); + } else { + $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); + } + + return $code->data; + } + + //---------------------------------------------------------------------- + public function encode($intext, $outfile = false) + { + $code = new QRcode(); + + if($this->eightbit) { + $code->encodeString8bit($intext, $this->version, $this->level); + } else { + $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); + } + + QRtools::markTime('after_encode'); + + if ($outfile!== false) { + file_put_contents($outfile, join("\n", QRtools::binarize($code->data))); + } else { + return QRtools::binarize($code->data); + } + } + + //---------------------------------------------------------------------- + public function encodePNG($intext, $outfile = false,$saveandprint=false) + { + try { + + ob_start(); + $tab = $this->encode($intext); + $err = ob_get_contents(); + ob_end_clean(); + + if ($err != '') + QRtools::log($outfile, $err); + + $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin)); + + QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint); + + } catch (Exception $e) { + + QRtools::log($outfile, $e->getMessage()); + + } + } + } diff --git a/src/admin/application/libs/phpqrcode/qrimage.php b/src/admin/application/libs/phpqrcode/qrimage.php new file mode 100755 index 0000000..10b0a6e --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrimage.php @@ -0,0 +1,95 @@ +<?php +/* + * PHP QR Code encoder + * + * Image output of code using GD2 + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('QR_IMAGE', true); + + class QRimage { + + //---------------------------------------------------------------------- + public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE) + { + $image = self::image($frame, $pixelPerPoint, $outerFrame); + + if ($filename === false) { + Header("Content-type: image/png"); + ImagePng($image); + } else { + if($saveandprint===TRUE){ + ImagePng($image, $filename); + header("Content-type: image/png"); + ImagePng($image); + }else{ + ImagePng($image, $filename); + } + } + + ImageDestroy($image); + } + + //---------------------------------------------------------------------- + public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85) + { + $image = self::image($frame, $pixelPerPoint, $outerFrame); + + if ($filename === false) { + Header("Content-type: image/jpeg"); + ImageJpeg($image, null, $q); + } else { + ImageJpeg($image, $filename, $q); + } + + ImageDestroy($image); + } + + //---------------------------------------------------------------------- + private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4) + { + $h = count($frame); + $w = strlen($frame[0]); + + $imgW = $w + 2*$outerFrame; + $imgH = $h + 2*$outerFrame; + + $base_image =ImageCreate($imgW, $imgH); + + $col[0] = ImageColorAllocate($base_image,255,255,255); + $col[1] = ImageColorAllocate($base_image,0,0,0); + + imagefill($base_image, 0, 0, $col[0]); + + for($y=0; $y<$h; $y++) { + for($x=0; $x<$w; $x++) { + if ($frame[$y][$x] == '1') { + ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]); + } + } + } + + $target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint); + ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH); + ImageDestroy($base_image); + + return $target_image; + } + } \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/qrinput.php b/src/admin/application/libs/phpqrcode/qrinput.php new file mode 100755 index 0000000..0f6d7f9 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrinput.php @@ -0,0 +1,729 @@ +<?php +/* + * PHP QR Code encoder + * + * Input encoding class + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('STRUCTURE_HEADER_BITS', 20); + define('MAX_STRUCTURED_SYMBOLS', 16); + + class QRinputItem { + + public $mode; + public $size; + public $data; + public $bstream; + + public function __construct($mode, $size, $data, $bstream = null) + { + $setData = array_slice($data, 0, $size); + + if (count($setData) < $size) { + $setData = array_merge($setData, array_fill(0,$size-count($setData),0)); + } + + if(!QRinput::check($mode, $size, $setData)) { + throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData)); + return null; + } + + $this->mode = $mode; + $this->size = $size; + $this->data = $setData; + $this->bstream = $bstream; + } + + //---------------------------------------------------------------------- + public function encodeModeNum($version) + { + try { + + $words = (int)($this->size / 3); + $bs = new QRbitstream(); + + $val = 0x1; + $bs->appendNum(4, $val); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size); + + for($i=0; $i<$words; $i++) { + $val = (ord($this->data[$i*3 ]) - ord('0')) * 100; + $val += (ord($this->data[$i*3+1]) - ord('0')) * 10; + $val += (ord($this->data[$i*3+2]) - ord('0')); + $bs->appendNum(10, $val); + } + + if($this->size - $words * 3 == 1) { + $val = ord($this->data[$words*3]) - ord('0'); + $bs->appendNum(4, $val); + } else if($this->size - $words * 3 == 2) { + $val = (ord($this->data[$words*3 ]) - ord('0')) * 10; + $val += (ord($this->data[$words*3+1]) - ord('0')); + $bs->appendNum(7, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeAn($version) + { + try { + $words = (int)($this->size / 2); + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x02); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size); + + for($i=0; $i<$words; $i++) { + $val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45; + $val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1])); + + $bs->appendNum(11, $val); + } + + if($this->size & 1) { + $val = QRinput::lookAnTable(ord($this->data[$words * 2])); + $bs->appendNum(6, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeMode8($version) + { + try { + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x4); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size); + + for($i=0; $i<$this->size; $i++) { + $bs->appendNum(8, ord($this->data[$i])); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeKanji($version) + { + try { + + $bs = new QRbitrtream(); + + $bs->appendNum(4, 0x8); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2)); + + for($i=0; $i<$this->size; $i+=2) { + $val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]); + if($val <= 0x9ffc) { + $val -= 0x8140; + } else { + $val -= 0xc140; + } + + $h = ($val >> 8) * 0xc0; + $val = ($val & 0xff) + $h; + + $bs->appendNum(13, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeStructure() + { + try { + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x03); + $bs->appendNum(4, ord($this->data[1]) - 1); + $bs->appendNum(4, ord($this->data[0]) - 1); + $bs->appendNum(8, ord($this->data[2])); + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function estimateBitStreamSizeOfEntry($version) + { + $bits = 0; + + if($version == 0) + $version = 1; + + switch($this->mode) { + case QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size); break; + case QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size); break; + case QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size); break; + case QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break; + case QR_MODE_STRUCTURE: return STRUCTURE_HEADER_BITS; + default: + return 0; + } + + $l = QRspec::lengthIndicator($this->mode, $version); + $m = 1 << $l; + $num = (int)(($this->size + $m - 1) / $m); + + $bits += $num * (4 + $l); + + return $bits; + } + + //---------------------------------------------------------------------- + public function encodeBitStream($version) + { + try { + + unset($this->bstream); + $words = QRspec::maximumWords($this->mode, $version); + + if($this->size > $words) { + + $st1 = new QRinputItem($this->mode, $words, $this->data); + $st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words)); + + $st1->encodeBitStream($version); + $st2->encodeBitStream($version); + + $this->bstream = new QRbitstream(); + $this->bstream->append($st1->bstream); + $this->bstream->append($st2->bstream); + + unset($st1); + unset($st2); + + } else { + + $ret = 0; + + switch($this->mode) { + case QR_MODE_NUM: $ret = $this->encodeModeNum($version); break; + case QR_MODE_AN: $ret = $this->encodeModeAn($version); break; + case QR_MODE_8: $ret = $this->encodeMode8($version); break; + case QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break; + case QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure(); break; + + default: + break; + } + + if($ret < 0) + return -1; + } + + return $this->bstream->size(); + + } catch (Exception $e) { + return -1; + } + } + }; + + //########################################################################## + + class QRinput { + + public $items; + + private $version; + private $level; + + //---------------------------------------------------------------------- + public function __construct($version = 0, $level = QR_ECLEVEL_L) + { + if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) { + throw new Exception('Invalid version no'); + return NULL; + } + + $this->version = $version; + $this->level = $level; + } + + //---------------------------------------------------------------------- + public function getVersion() + { + return $this->version; + } + + //---------------------------------------------------------------------- + public function setVersion($version) + { + if($version < 0 || $version > QRSPEC_VERSION_MAX) { + throw new Exception('Invalid version no'); + return -1; + } + + $this->version = $version; + + return 0; + } + + //---------------------------------------------------------------------- + public function getErrorCorrectionLevel() + { + return $this->level; + } + + //---------------------------------------------------------------------- + public function setErrorCorrectionLevel($level) + { + if($level > QR_ECLEVEL_H) { + throw new Exception('Invalid ECLEVEL'); + return -1; + } + + $this->level = $level; + + return 0; + } + + //---------------------------------------------------------------------- + public function appendEntry(QRinputItem $entry) + { + $this->items[] = $entry; + } + + //---------------------------------------------------------------------- + public function append($mode, $size, $data) + { + try { + $entry = new QRinputItem($mode, $size, $data); + $this->items[] = $entry; + return 0; + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + + public function insertStructuredAppendHeader($size, $index, $parity) + { + if( $size > MAX_STRUCTURED_SYMBOLS ) { + throw new Exception('insertStructuredAppendHeader wrong size'); + } + + if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) { + throw new Exception('insertStructuredAppendHeader wrong index'); + } + + $buf = array($size, $index, $parity); + + try { + $entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf); + array_unshift($this->items, $entry); + return 0; + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function calcParity() + { + $parity = 0; + + foreach($this->items as $item) { + if($item->mode != QR_MODE_STRUCTURE) { + for($i=$item->size-1; $i>=0; $i--) { + $parity ^= $item->data[$i]; + } + } + } + + return $parity; + } + + //---------------------------------------------------------------------- + public static function checkModeNum($size, $data) + { + for($i=0; $i<$size; $i++) { + if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){ + return false; + } + } + + return true; + } + + //---------------------------------------------------------------------- + public static function estimateBitsModeNum($size) + { + $w = (int)$size / 3; + $bits = $w * 10; + + switch($size - $w * 3) { + case 1: + $bits += 4; + break; + case 2: + $bits += 7; + break; + default: + break; + } + + return $bits; + } + + //---------------------------------------------------------------------- + public static $anTable = array( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + ); + + //---------------------------------------------------------------------- + public static function lookAnTable($c) + { + return (($c > 127)?-1:self::$anTable[$c]); + } + + //---------------------------------------------------------------------- + public static function checkModeAn($size, $data) + { + for($i=0; $i<$size; $i++) { + if (self::lookAnTable(ord($data[$i])) == -1) { + return false; + } + } + + return true; + } + + //---------------------------------------------------------------------- + public static function estimateBitsModeAn($size) + { + $w = (int)($size / 2); + $bits = $w * 11; + + if($size & 1) { + $bits += 6; + } + + return $bits; + } + + //---------------------------------------------------------------------- + public static function estimateBitsMode8($size) + { + return $size * 8; + } + + //---------------------------------------------------------------------- + public function estimateBitsModeKanji($size) + { + return (int)(($size / 2) * 13); + } + + //---------------------------------------------------------------------- + public static function checkModeKanji($size, $data) + { + if($size & 1) + return false; + + for($i=0; $i<$size; $i+=2) { + $val = (ord($data[$i]) << 8) | ord($data[$i+1]); + if( $val < 0x8140 + || ($val > 0x9ffc && $val < 0xe040) + || $val > 0xebbf) { + return false; + } + } + + return true; + } + + /*********************************************************************** + * Validation + **********************************************************************/ + + public static function check($mode, $size, $data) + { + if($size <= 0) + return false; + + switch($mode) { + case QR_MODE_NUM: return self::checkModeNum($size, $data); break; + case QR_MODE_AN: return self::checkModeAn($size, $data); break; + case QR_MODE_KANJI: return self::checkModeKanji($size, $data); break; + case QR_MODE_8: return true; break; + case QR_MODE_STRUCTURE: return true; break; + + default: + break; + } + + return false; + } + + + //---------------------------------------------------------------------- + public function estimateBitStreamSize($version) + { + $bits = 0; + + foreach($this->items as $item) { + $bits += $item->estimateBitStreamSizeOfEntry($version); + } + + return $bits; + } + + //---------------------------------------------------------------------- + public function estimateVersion() + { + $version = 0; + $prev = 0; + do { + $prev = $version; + $bits = $this->estimateBitStreamSize($prev); + $version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if ($version < 0) { + return -1; + } + } while ($version > $prev); + + return $version; + } + + //---------------------------------------------------------------------- + public static function lengthOfCode($mode, $version, $bits) + { + $payload = $bits - 4 - QRspec::lengthIndicator($mode, $version); + switch($mode) { + case QR_MODE_NUM: + $chunks = (int)($payload / 10); + $remain = $payload - $chunks * 10; + $size = $chunks * 3; + if($remain >= 7) { + $size += 2; + } else if($remain >= 4) { + $size += 1; + } + break; + case QR_MODE_AN: + $chunks = (int)($payload / 11); + $remain = $payload - $chunks * 11; + $size = $chunks * 2; + if($remain >= 6) + $size++; + break; + case QR_MODE_8: + $size = (int)($payload / 8); + break; + case QR_MODE_KANJI: + $size = (int)(($payload / 13) * 2); + break; + case QR_MODE_STRUCTURE: + $size = (int)($payload / 8); + break; + default: + $size = 0; + break; + } + + $maxsize = QRspec::maximumWords($mode, $version); + if($size < 0) $size = 0; + if($size > $maxsize) $size = $maxsize; + + return $size; + } + + //---------------------------------------------------------------------- + public function createBitStream() + { + $total = 0; + + foreach($this->items as $item) { + $bits = $item->encodeBitStream($this->version); + + if($bits < 0) + return -1; + + $total += $bits; + } + + return $total; + } + + //---------------------------------------------------------------------- + public function convertData() + { + $ver = $this->estimateVersion(); + if($ver > $this->getVersion()) { + $this->setVersion($ver); + } + + for(;;) { + $bits = $this->createBitStream(); + + if($bits < 0) + return -1; + + $ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if($ver < 0) { + throw new Exception('WRONG VERSION'); + return -1; + } else if($ver > $this->getVersion()) { + $this->setVersion($ver); + } else { + break; + } + } + + return 0; + } + + //---------------------------------------------------------------------- + public function appendPaddingBit(&$bstream) + { + $bits = $bstream->size(); + $maxwords = QRspec::getDataLength($this->version, $this->level); + $maxbits = $maxwords * 8; + + if ($maxbits == $bits) { + return 0; + } + + if ($maxbits - $bits < 5) { + return $bstream->appendNum($maxbits - $bits, 0); + } + + $bits += 4; + $words = (int)(($bits + 7) / 8); + + $padding = new QRbitstream(); + $ret = $padding->appendNum($words * 8 - $bits + 4, 0); + + if($ret < 0) + return $ret; + + $padlen = $maxwords - $words; + + if($padlen > 0) { + + $padbuf = array(); + for($i=0; $i<$padlen; $i++) { + $padbuf[$i] = ($i&1)?0x11:0xec; + } + + $ret = $padding->appendBytes($padlen, $padbuf); + + if($ret < 0) + return $ret; + + } + + $ret = $bstream->append($padding); + + return $ret; + } + + //---------------------------------------------------------------------- + public function mergeBitStream() + { + if($this->convertData() < 0) { + return null; + } + + $bstream = new QRbitstream(); + + foreach($this->items as $item) { + $ret = $bstream->append($item->bstream); + if($ret < 0) { + return null; + } + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function getBitStream() + { + + $bstream = $this->mergeBitStream(); + + if($bstream == null) { + return null; + } + + $ret = $this->appendPaddingBit($bstream); + if($ret < 0) { + return null; + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function getByteStream() + { + $bstream = $this->getBitStream(); + if($bstream == null) { + return null; + } + + return $bstream->toByte(); + } + } + + + \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/qrlib.php b/src/admin/application/libs/phpqrcode/qrlib.php new file mode 100755 index 0000000..d55c4af --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrlib.php @@ -0,0 +1,43 @@ +<?php +/* + * PHP QR Code encoder + * + * Root library file, prepares environment and includes dependencies + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + $QR_BASEDIR = dirname(__FILE__).DIRECTORY_SEPARATOR; + + // Required libs + + include $QR_BASEDIR."qrconst.php"; + include $QR_BASEDIR."qrconfig.php"; + include $QR_BASEDIR."qrtools.php"; + include $QR_BASEDIR."qrspec.php"; + include $QR_BASEDIR."qrimage.php"; + include $QR_BASEDIR."qrinput.php"; + include $QR_BASEDIR."qrbitstream.php"; + include $QR_BASEDIR."qrsplit.php"; + include $QR_BASEDIR."qrrscode.php"; + include $QR_BASEDIR."qrmask.php"; + include $QR_BASEDIR."qrencode.php"; + diff --git a/src/admin/application/libs/phpqrcode/qrmask.php b/src/admin/application/libs/phpqrcode/qrmask.php new file mode 100755 index 0000000..b14d7ae --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrmask.php @@ -0,0 +1,328 @@ +<?php +/* + * PHP QR Code encoder + * + * Masking + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('N1', 3); + define('N2', 3); + define('N3', 40); + define('N4', 10); + + class QRmask { + + public $runLength = array(); + + //---------------------------------------------------------------------- + public function __construct() + { + $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0); + } + + //---------------------------------------------------------------------- + public function writeFormatInformation($width, &$frame, $mask, $level) + { + $blacks = 0; + $format = QRspec::getFormatInfo($mask, $level); + + for($i=0; $i<8; $i++) { + if($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + + $frame[8][$width - 1 - $i] = chr($v); + if($i < 6) { + $frame[$i][8] = chr($v); + } else { + $frame[$i + 1][8] = chr($v); + } + $format = $format >> 1; + } + + for($i=0; $i<7; $i++) { + if($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + + $frame[$width - 7 + $i][8] = chr($v); + if($i == 0) { + $frame[8][7] = chr($v); + } else { + $frame[8][6 - $i] = chr($v); + } + + $format = $format >> 1; + } + + return $blacks; + } + + //---------------------------------------------------------------------- + public function mask0($x, $y) { return ($x+$y)&1; } + public function mask1($x, $y) { return ($y&1); } + public function mask2($x, $y) { return ($x%3); } + public function mask3($x, $y) { return ($x+$y)%3; } + public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; } + public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; } + public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; } + public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; } + + //---------------------------------------------------------------------- + private function generateMaskNo($maskNo, $width, $frame) + { + $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); + + for($y=0; $y<$width; $y++) { + for($x=0; $x<$width; $x++) { + if(ord($frame[$y][$x]) & 0x80) { + $bitMask[$y][$x] = 0; + } else { + $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y); + $bitMask[$y][$x] = ($maskFunc == 0)?1:0; + } + + } + } + + return $bitMask; + } + + //---------------------------------------------------------------------- + public static function serial($bitFrame) + { + $codeArr = array(); + + foreach ($bitFrame as $line) + $codeArr[] = join('', $line); + + return gzcompress(join("\n", $codeArr), 9); + } + + //---------------------------------------------------------------------- + public static function unserial($code) + { + $codeArr = array(); + + $codeLines = explode("\n", gzuncompress($code)); + foreach ($codeLines as $line) + $codeArr[] = str_split($line); + + return $codeArr; + } + + //---------------------------------------------------------------------- + public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false) + { + $b = 0; + $bitMask = array(); + + $fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat'; + + if (QR_CACHEABLE) { + if (file_exists($fileName)) { + $bitMask = self::unserial(file_get_contents($fileName)); + } else { + $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); + if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo)) + mkdir(QR_CACHE_DIR.'mask_'.$maskNo); + file_put_contents($fileName, self::serial($bitMask)); + } + } else { + $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); + } + + if ($maskGenOnly) + return; + + $d = $s; + + for($y=0; $y<$width; $y++) { + for($x=0; $x<$width; $x++) { + if($bitMask[$y][$x] == 1) { + $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]); + } + $b += (int)(ord($d[$y][$x]) & 1); + } + } + + return $b; + } + + //---------------------------------------------------------------------- + public function makeMask($width, $frame, $maskNo, $level) + { + $masked = array_fill(0, $width, str_repeat("\0", $width)); + $this->makeMaskNo($maskNo, $width, $frame, $masked); + $this->writeFormatInformation($width, $masked, $maskNo, $level); + + return $masked; + } + + //---------------------------------------------------------------------- + public function calcN1N3($length) + { + $demerit = 0; + + for($i=0; $i<$length; $i++) { + + if($this->runLength[$i] >= 5) { + $demerit += (N1 + ($this->runLength[$i] - 5)); + } + if($i & 1) { + if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) { + $fact = (int)($this->runLength[$i] / 3); + if(($this->runLength[$i-2] == $fact) && + ($this->runLength[$i-1] == $fact) && + ($this->runLength[$i+1] == $fact) && + ($this->runLength[$i+2] == $fact)) { + if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) { + $demerit += N3; + } else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) { + $demerit += N3; + } + } + } + } + } + return $demerit; + } + + //---------------------------------------------------------------------- + public function evaluateSymbol($width, $frame) + { + $head = 0; + $demerit = 0; + + for($y=0; $y<$width; $y++) { + $head = 0; + $this->runLength[0] = 1; + + $frameY = $frame[$y]; + + if ($y>0) + $frameYM = $frame[$y-1]; + + for($x=0; $x<$width; $x++) { + if(($x > 0) && ($y > 0)) { + $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]); + $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]); + + if(($b22 | ($w22 ^ 1))&1) { + $demerit += N2; + } + } + if(($x == 0) && (ord($frameY[$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } else if($x > 0) { + if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + + $demerit += $this->calcN1N3($head+1); + } + + for($x=0; $x<$width; $x++) { + $head = 0; + $this->runLength[0] = 1; + + for($y=0; $y<$width; $y++) { + if($y == 0 && (ord($frame[$y][$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } else if($y > 0) { + if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + + $demerit += $this->calcN1N3($head+1); + } + + return $demerit; + } + + + //---------------------------------------------------------------------- + public function mask($width, $frame, $level) + { + $minDemerit = PHP_INT_MAX; + $bestMaskNum = 0; + $bestMask = array(); + + $checked_masks = array(0,1,2,3,4,5,6,7); + + if (QR_FIND_FROM_RANDOM !== false) { + + $howManuOut = 8-(QR_FIND_FROM_RANDOM % 9); + for ($i = 0; $i < $howManuOut; $i++) { + $remPos = rand (0, count($checked_masks)-1); + unset($checked_masks[$remPos]); + $checked_masks = array_values($checked_masks); + } + + } + + $bestMask = $frame; + + foreach($checked_masks as $i) { + $mask = array_fill(0, $width, str_repeat("\0", $width)); + + $demerit = 0; + $blacks = 0; + $blacks = $this->makeMaskNo($i, $width, $frame, $mask); + $blacks += $this->writeFormatInformation($width, $mask, $i, $level); + $blacks = (int)(100 * $blacks / ($width * $width)); + $demerit = (int)((int)(abs($blacks - 50) / 5) * N4); + $demerit += $this->evaluateSymbol($width, $mask); + + if($demerit < $minDemerit) { + $minDemerit = $demerit; + $bestMask = $mask; + $bestMaskNum = $i; + } + } + + return $bestMask; + } + + //---------------------------------------------------------------------- + } diff --git a/src/admin/application/libs/phpqrcode/qrrscode.php b/src/admin/application/libs/phpqrcode/qrrscode.php new file mode 100755 index 0000000..591129a --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrrscode.php @@ -0,0 +1,210 @@ +<?php +/* + * PHP QR Code encoder + * + * Reed-Solomon error correction support + * + * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + * (libfec is released under the GNU Lesser General Public License.) + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRrsItem { + + public $mm; // Bits per symbol + public $nn; // Symbols per block (= (1<<mm)-1) + public $alpha_to = array(); // log lookup table + public $index_of = array(); // Antilog lookup table + public $genpoly = array(); // Generator polynomial + public $nroots; // Number of generator roots = number of parity symbols + public $fcr; // First consecutive root, index form + public $prim; // Primitive element, index form + public $iprim; // prim-th root of 1, index form + public $pad; // Padding bytes in shortened block + public $gfpoly; + + //---------------------------------------------------------------------- + public function modnn($x) + { + while ($x >= $this->nn) { + $x -= $this->nn; + $x = ($x >> $this->mm) + ($x & $this->nn); + } + + return $x; + } + + //---------------------------------------------------------------------- + public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) + { + // Common code for intializing a Reed-Solomon control block (char or int symbols) + // Copyright 2004 Phil Karn, KA9Q + // May be used under the terms of the GNU Lesser General Public License (LGPL) + + $rs = null; + + // Check parameter ranges + if($symsize < 0 || $symsize > 8) return $rs; + if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs; + if($prim <= 0 || $prim >= (1<<$symsize)) return $rs; + if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values! + if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding + + $rs = new QRrsItem(); + $rs->mm = $symsize; + $rs->nn = (1<<$symsize)-1; + $rs->pad = $pad; + + $rs->alpha_to = array_fill(0, $rs->nn+1, 0); + $rs->index_of = array_fill(0, $rs->nn+1, 0); + + // PHP style macro replacement ;) + $NN =& $rs->nn; + $A0 =& $NN; + + // Generate Galois field lookup tables + $rs->index_of[0] = $A0; // log(zero) = -inf + $rs->alpha_to[$A0] = 0; // alpha**-inf = 0 + $sr = 1; + + for($i=0; $i<$rs->nn; $i++) { + $rs->index_of[$sr] = $i; + $rs->alpha_to[$i] = $sr; + $sr <<= 1; + if($sr & (1<<$symsize)) { + $sr ^= $gfpoly; + } + $sr &= $rs->nn; + } + + if($sr != 1){ + // field generator polynomial is not primitive! + $rs = NULL; + return $rs; + } + + /* Form RS code generator polynomial from its roots */ + $rs->genpoly = array_fill(0, $nroots+1, 0); + + $rs->fcr = $fcr; + $rs->prim = $prim; + $rs->nroots = $nroots; + $rs->gfpoly = $gfpoly; + + /* Find prim-th root of 1, used in decoding */ + for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn) + ; // intentional empty-body loop! + + $rs->iprim = (int)($iprim / $prim); + $rs->genpoly[0] = 1; + + for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) { + $rs->genpoly[$i+1] = 1; + + // Multiply rs->genpoly[] by @**(root + x) + for ($j = $i; $j > 0; $j--) { + if ($rs->genpoly[$j] != 0) { + $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)]; + } else { + $rs->genpoly[$j] = $rs->genpoly[$j-1]; + } + } + // rs->genpoly[0] can never be zero + $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)]; + } + + // convert rs->genpoly[] to index form for quicker encoding + for ($i = 0; $i <= $nroots; $i++) + $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]]; + + return $rs; + } + + //---------------------------------------------------------------------- + public function encode_rs_char($data, &$parity) + { + $MM =& $this->mm; + $NN =& $this->nn; + $ALPHA_TO =& $this->alpha_to; + $INDEX_OF =& $this->index_of; + $GENPOLY =& $this->genpoly; + $NROOTS =& $this->nroots; + $FCR =& $this->fcr; + $PRIM =& $this->prim; + $IPRIM =& $this->iprim; + $PAD =& $this->pad; + $A0 =& $NN; + + $parity = array_fill(0, $NROOTS, 0); + + for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) { + + $feedback = $INDEX_OF[$data[$i] ^ $parity[0]]; + if($feedback != $A0) { + // feedback term is non-zero + + // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must + // always be for the polynomials constructed by init_rs() + $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback); + + for($j=1;$j<$NROOTS;$j++) { + $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])]; + } + } + + // Shift + array_shift($parity); + if($feedback != $A0) { + array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]); + } else { + array_push($parity, 0); + } + } + } + } + + //########################################################################## + + class QRrs { + + public static $items = array(); + + //---------------------------------------------------------------------- + public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) + { + foreach(self::$items as $rs) { + if($rs->pad != $pad) continue; + if($rs->nroots != $nroots) continue; + if($rs->mm != $symsize) continue; + if($rs->gfpoly != $gfpoly) continue; + if($rs->fcr != $fcr) continue; + if($rs->prim != $prim) continue; + + return $rs; + } + + $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad); + array_unshift(self::$items, $rs); + + return $rs; + } + } \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/qrspec.php b/src/admin/application/libs/phpqrcode/qrspec.php new file mode 100755 index 0000000..92aea0c --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrspec.php @@ -0,0 +1,592 @@ +<?php +/* + * PHP QR Code encoder + * + * QR Code specifications + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('QRSPEC_VERSION_MAX', 40); + define('QRSPEC_WIDTH_MAX', 177); + + define('QRCAP_WIDTH', 0); + define('QRCAP_WORDS', 1); + define('QRCAP_REMINDER', 2); + define('QRCAP_EC', 3); + + class QRspec { + + public static $capacity = array( + array( 0, 0, 0, array( 0, 0, 0, 0)), + array( 21, 26, 0, array( 7, 10, 13, 17)), // 1 + array( 25, 44, 7, array( 10, 16, 22, 28)), + array( 29, 70, 7, array( 15, 26, 36, 44)), + array( 33, 100, 7, array( 20, 36, 52, 64)), + array( 37, 134, 7, array( 26, 48, 72, 88)), // 5 + array( 41, 172, 7, array( 36, 64, 96, 112)), + array( 45, 196, 0, array( 40, 72, 108, 130)), + array( 49, 242, 0, array( 48, 88, 132, 156)), + array( 53, 292, 0, array( 60, 110, 160, 192)), + array( 57, 346, 0, array( 72, 130, 192, 224)), //10 + array( 61, 404, 0, array( 80, 150, 224, 264)), + array( 65, 466, 0, array( 96, 176, 260, 308)), + array( 69, 532, 0, array( 104, 198, 288, 352)), + array( 73, 581, 3, array( 120, 216, 320, 384)), + array( 77, 655, 3, array( 132, 240, 360, 432)), //15 + array( 81, 733, 3, array( 144, 280, 408, 480)), + array( 85, 815, 3, array( 168, 308, 448, 532)), + array( 89, 901, 3, array( 180, 338, 504, 588)), + array( 93, 991, 3, array( 196, 364, 546, 650)), + array( 97, 1085, 3, array( 224, 416, 600, 700)), //20 + array(101, 1156, 4, array( 224, 442, 644, 750)), + array(105, 1258, 4, array( 252, 476, 690, 816)), + array(109, 1364, 4, array( 270, 504, 750, 900)), + array(113, 1474, 4, array( 300, 560, 810, 960)), + array(117, 1588, 4, array( 312, 588, 870, 1050)), //25 + array(121, 1706, 4, array( 336, 644, 952, 1110)), + array(125, 1828, 4, array( 360, 700, 1020, 1200)), + array(129, 1921, 3, array( 390, 728, 1050, 1260)), + array(133, 2051, 3, array( 420, 784, 1140, 1350)), + array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30 + array(141, 2323, 3, array( 480, 868, 1290, 1530)), + array(145, 2465, 3, array( 510, 924, 1350, 1620)), + array(149, 2611, 3, array( 540, 980, 1440, 1710)), + array(153, 2761, 3, array( 570, 1036, 1530, 1800)), + array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35 + array(161, 3034, 0, array( 600, 1120, 1680, 1980)), + array(165, 3196, 0, array( 630, 1204, 1770, 2100)), + array(169, 3362, 0, array( 660, 1260, 1860, 2220)), + array(173, 3532, 0, array( 720, 1316, 1950, 2310)), + array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40 + ); + + //---------------------------------------------------------------------- + public static function getDataLength($version, $level) + { + return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level]; + } + + //---------------------------------------------------------------------- + public static function getECCLength($version, $level) + { + return self::$capacity[$version][QRCAP_EC][$level]; + } + + //---------------------------------------------------------------------- + public static function getWidth($version) + { + return self::$capacity[$version][QRCAP_WIDTH]; + } + + //---------------------------------------------------------------------- + public static function getRemainder($version) + { + return self::$capacity[$version][QRCAP_REMINDER]; + } + + //---------------------------------------------------------------------- + public static function getMinimumVersion($size, $level) + { + + for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) { + $words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level]; + if($words >= $size) + return $i; + } + + return -1; + } + + //###################################################################### + + public static $lengthTableBits = array( + array(10, 12, 14), + array( 9, 11, 13), + array( 8, 16, 16), + array( 8, 10, 12) + ); + + //---------------------------------------------------------------------- + public static function lengthIndicator($mode, $version) + { + if ($mode == QR_MODE_STRUCTURE) + return 0; + + if ($version <= 9) { + $l = 0; + } else if ($version <= 26) { + $l = 1; + } else { + $l = 2; + } + + return self::$lengthTableBits[$mode][$l]; + } + + //---------------------------------------------------------------------- + public static function maximumWords($mode, $version) + { + if($mode == QR_MODE_STRUCTURE) + return 3; + + if($version <= 9) { + $l = 0; + } else if($version <= 26) { + $l = 1; + } else { + $l = 2; + } + + $bits = self::$lengthTableBits[$mode][$l]; + $words = (1 << $bits) - 1; + + if($mode == QR_MODE_KANJI) { + $words *= 2; // the number of bytes is required + } + + return $words; + } + + // Error correction code ----------------------------------------------- + // Table of the error correction code (Reed-Solomon block) + // See Table 12-16 (pp.30-36), JIS X0510:2004. + + public static $eccTable = array( + array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)), + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1 + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), + array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)), + array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)), + array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5 + array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)), + array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)), + array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)), + array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)), + array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10 + array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)), + array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)), + array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)), + array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)), + array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15 + array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)), + array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)), + array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)), + array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)), + array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20 + array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)), + array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)), + array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)), + array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)), + array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25 + array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)), + array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)), + array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)), + array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)), + array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30 + array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)), + array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)), + array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)), + array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)), + array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35 + array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)), + array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)), + array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)), + array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)), + array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)),//40 + ); + + //---------------------------------------------------------------------- + // CACHEABLE!!! + + public static function getEccSpec($version, $level, array &$spec) + { + if (count($spec) < 5) { + $spec = array(0,0,0,0,0); + } + + $b1 = self::$eccTable[$version][$level][0]; + $b2 = self::$eccTable[$version][$level][1]; + $data = self::getDataLength($version, $level); + $ecc = self::getECCLength($version, $level); + + if($b2 == 0) { + $spec[0] = $b1; + $spec[1] = (int)($data / $b1); + $spec[2] = (int)($ecc / $b1); + $spec[3] = 0; + $spec[4] = 0; + } else { + $spec[0] = $b1; + $spec[1] = (int)($data / ($b1 + $b2)); + $spec[2] = (int)($ecc / ($b1 + $b2)); + $spec[3] = $b2; + $spec[4] = $spec[1] + 1; + } + } + + // Alignment pattern --------------------------------------------------- + + // Positions of alignment patterns. + // This array includes only the second and the third position of the + // alignment patterns. Rest of them can be calculated from the distance + // between them. + + // See Table 1 in Appendix E (pp.71) of JIS X0510:2004. + + public static $alignmentPattern = array( + array( 0, 0), + array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5 + array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10 + array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15 + array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20 + array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25 + array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30 + array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35 + array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40 + ); + + + /** -------------------------------------------------------------------- + * Put an alignment marker. + * @param frame + * @param width + * @param ox,oy center coordinate of the pattern + */ + public static function putAlignmentMarker(array &$frame, $ox, $oy) + { + $finder = array( + "\xa1\xa1\xa1\xa1\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa0\xa1\xa0\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa1\xa1\xa1\xa1" + ); + + $yStart = $oy-2; + $xStart = $ox-2; + + for($y=0; $y<5; $y++) { + QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]); + } + } + + //---------------------------------------------------------------------- + public static function putAlignmentPattern($version, &$frame, $width) + { + if($version < 2) + return; + + $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0]; + if($d < 0) { + $w = 2; + } else { + $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2); + } + + if($w * $w - 3 == 1) { + $x = self::$alignmentPattern[$version][0]; + $y = self::$alignmentPattern[$version][0]; + self::putAlignmentMarker($frame, $x, $y); + return; + } + + $cx = self::$alignmentPattern[$version][0]; + for($x=1; $x<$w - 1; $x++) { + self::putAlignmentMarker($frame, 6, $cx); + self::putAlignmentMarker($frame, $cx, 6); + $cx += $d; + } + + $cy = self::$alignmentPattern[$version][0]; + for($y=0; $y<$w-1; $y++) { + $cx = self::$alignmentPattern[$version][0]; + for($x=0; $x<$w-1; $x++) { + self::putAlignmentMarker($frame, $cx, $cy); + $cx += $d; + } + $cy += $d; + } + } + + // Version information pattern ----------------------------------------- + + // Version information pattern (BCH coded). + // See Table 1 in Appendix D (pp.68) of JIS X0510:2004. + + // size: [QRSPEC_VERSION_MAX - 6] + + public static $versionPattern = array( + 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, + 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, + 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, + 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, + 0x27541, 0x28c69 + ); + + //---------------------------------------------------------------------- + public static function getVersionPattern($version) + { + if($version < 7 || $version > QRSPEC_VERSION_MAX) + return 0; + + return self::$versionPattern[$version -7]; + } + + // Format information -------------------------------------------------- + // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib) + + public static $formatInfo = array( + array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), + array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0), + array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed), + array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b) + ); + + public static function getFormatInfo($mask, $level) + { + if($mask < 0 || $mask > 7) + return 0; + + if($level < 0 || $level > 3) + return 0; + + return self::$formatInfo[$level][$mask]; + } + + // Frame --------------------------------------------------------------- + // Cache of initial frames. + + public static $frames = array(); + + /** -------------------------------------------------------------------- + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ + public static function putFinderPattern(&$frame, $ox, $oy) + { + $finder = array( + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" + ); + + for($y=0; $y<7; $y++) { + QRstr::set($frame, $ox, $oy+$y, $finder[$y]); + } + } + + //---------------------------------------------------------------------- + public static function createFrame($version) + { + $width = self::$capacity[$version][QRCAP_WIDTH]; + $frameLine = str_repeat ("\0", $width); + $frame = array_fill(0, $width, $frameLine); + + // Finder pattern + self::putFinderPattern($frame, 0, 0); + self::putFinderPattern($frame, $width - 7, 0); + self::putFinderPattern($frame, 0, $width - 7); + + // Separator + $yOffset = $width - 7; + + for($y=0; $y<7; $y++) { + $frame[$y][7] = "\xc0"; + $frame[$y][$width - 8] = "\xc0"; + $frame[$yOffset][7] = "\xc0"; + $yOffset++; + } + + $setPattern = str_repeat("\xc0", 8); + + QRstr::set($frame, 0, 7, $setPattern); + QRstr::set($frame, $width-8, 7, $setPattern); + QRstr::set($frame, 0, $width - 8, $setPattern); + + // Format info + $setPattern = str_repeat("\x84", 9); + QRstr::set($frame, 0, 8, $setPattern); + QRstr::set($frame, $width - 8, 8, $setPattern, 8); + + $yOffset = $width - 8; + + for($y=0; $y<8; $y++,$yOffset++) { + $frame[$y][8] = "\x84"; + $frame[$yOffset][8] = "\x84"; + } + + // Timing pattern + + for($i=1; $i<$width-15; $i++) { + $frame[6][7+$i] = chr(0x90 | ($i & 1)); + $frame[7+$i][6] = chr(0x90 | ($i & 1)); + } + + // Alignment pattern + self::putAlignmentPattern($version, $frame, $width); + + // Version information + if($version >= 7) { + $vinf = self::getVersionPattern($version); + + $v = $vinf; + + for($x=0; $x<6; $x++) { + for($y=0; $y<3; $y++) { + $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + + $v = $vinf; + for($y=0; $y<6; $y++) { + for($x=0; $x<3; $x++) { + $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + } + + // and a little bit... + $frame[$width - 8][8] = "\x81"; + + return $frame; + } + + //---------------------------------------------------------------------- + public static function debug($frame, $binary_mode = false) + { + if ($binary_mode) { + + foreach ($frame as &$frameLine) { + $frameLine = join('<span class="m">&nbsp;&nbsp;</span>', explode('0', $frameLine)); + $frameLine = join('&#9608;&#9608;', explode('1', $frameLine)); + } + + ?> + <style> + .m { background-color: white; } + </style> + <?php + echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'; + echo join("<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $frame); + echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >'; + + } else { + + foreach ($frame as &$frameLine) { + $frameLine = join('<span class="m">&nbsp;</span>', explode("\xc0", $frameLine)); + $frameLine = join('<span class="m">&#9618;</span>', explode("\xc1", $frameLine)); + $frameLine = join('<span class="p">&nbsp;</span>', explode("\xa0", $frameLine)); + $frameLine = join('<span class="p">&#9618;</span>', explode("\xa1", $frameLine)); + $frameLine = join('<span class="s">&#9671;</span>', explode("\x84", $frameLine)); //format 0 + $frameLine = join('<span class="s">&#9670;</span>', explode("\x85", $frameLine)); //format 1 + $frameLine = join('<span class="x">&#9762;</span>', explode("\x81", $frameLine)); //special bit + $frameLine = join('<span class="c">&nbsp;</span>', explode("\x90", $frameLine)); //clock 0 + $frameLine = join('<span class="c">&#9719;</span>', explode("\x91", $frameLine)); //clock 1 + $frameLine = join('<span class="f">&nbsp;</span>', explode("\x88", $frameLine)); //version + $frameLine = join('<span class="f">&#9618;</span>', explode("\x89", $frameLine)); //version + $frameLine = join('&#9830;', explode("\x01", $frameLine)); + $frameLine = join('&#8901;', explode("\0", $frameLine)); + } + + ?> + <style> + .p { background-color: yellow; } + .m { background-color: #00FF00; } + .s { background-color: #FF0000; } + .c { background-color: aqua; } + .x { background-color: pink; } + .f { background-color: gold; } + </style> + <?php + echo "<pre><tt>"; + echo join("<br/ >", $frame); + echo "</tt></pre>"; + + } + } + + //---------------------------------------------------------------------- + public static function serial($frame) + { + return gzcompress(join("\n", $frame), 9); + } + + //---------------------------------------------------------------------- + public static function unserial($code) + { + return explode("\n", gzuncompress($code)); + } + + //---------------------------------------------------------------------- + public static function newFrame($version) + { + if($version < 1 || $version > QRSPEC_VERSION_MAX) + return null; + + if(!isset(self::$frames[$version])) { + + $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat'; + + if (QR_CACHEABLE) { + if (file_exists($fileName)) { + self::$frames[$version] = self::unserial(file_get_contents($fileName)); + } else { + self::$frames[$version] = self::createFrame($version); + file_put_contents($fileName, self::serial(self::$frames[$version])); + } + } else { + self::$frames[$version] = self::createFrame($version); + } + } + + if(is_null(self::$frames[$version])) + return null; + + return self::$frames[$version]; + } + + //---------------------------------------------------------------------- + public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; } + public static function rsBlockNum1($spec) { return $spec[0]; } + public static function rsDataCodes1($spec) { return $spec[1]; } + public static function rsEccCodes1($spec) { return $spec[2]; } + public static function rsBlockNum2($spec) { return $spec[3]; } + public static function rsDataCodes2($spec) { return $spec[4]; } + public static function rsEccCodes2($spec) { return $spec[2]; } + public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); } + public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; } + + } \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/qrsplit.php b/src/admin/application/libs/phpqrcode/qrsplit.php new file mode 100755 index 0000000..d75b827 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrsplit.php @@ -0,0 +1,311 @@ +<?php +/* + * PHP QR Code encoder + * + * Input splitting classes + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net> + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + class QRsplit { + + public $dataStr = ''; + public $input; + public $modeHint; + + //---------------------------------------------------------------------- + public function __construct($dataStr, $input, $modeHint) + { + $this->dataStr = $dataStr; + $this->input = $input; + $this->modeHint = $modeHint; + } + + //---------------------------------------------------------------------- + public static function isdigitat($str, $pos) + { + if ($pos >= strlen($str)) + return false; + + return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9'))); + } + + //---------------------------------------------------------------------- + public static function isalnumat($str, $pos) + { + if ($pos >= strlen($str)) + return false; + + return (QRinput::lookAnTable(ord($str[$pos])) >= 0); + } + + //---------------------------------------------------------------------- + public function identifyMode($pos) + { + if ($pos >= strlen($this->dataStr)) + return QR_MODE_NUL; + + $c = $this->dataStr[$pos]; + + if(self::isdigitat($this->dataStr, $pos)) { + return QR_MODE_NUM; + } else if(self::isalnumat($this->dataStr, $pos)) { + return QR_MODE_AN; + } else if($this->modeHint == QR_MODE_KANJI) { + + if ($pos+1 < strlen($this->dataStr)) + { + $d = $this->dataStr[$pos+1]; + $word = (ord($c) << 8) | ord($d); + if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) { + return QR_MODE_KANJI; + } + } + } + + return QR_MODE_8; + } + + //---------------------------------------------------------------------- + public function eatNum() + { + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 0; + while(self::isdigitat($this->dataStr, $p)) { + $p++; + } + + $run = $p; + $mode = $this->identifyMode($p); + + if($mode == QR_MODE_8) { + $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln + + QRinput::estimateBitsMode8(1) // + 4 + l8 + - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 + if($dif > 0) { + return $this->eat8(); + } + } + if($mode == QR_MODE_AN) { + $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln + + QRinput::estimateBitsModeAn(1) // + 4 + la + - QRinput::estimateBitsModeAn($run + 1);// - 4 - la + if($dif > 0) { + return $this->eatAn(); + } + } + + $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eatAn() + { + $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 0; + + while(self::isalnumat($this->dataStr, $p)) { + if(self::isdigitat($this->dataStr, $p)) { + $q = $p; + while(self::isdigitat($this->dataStr, $q)) { + $q++; + } + + $dif = QRinput::estimateBitsModeAn($p) // + 4 + la + + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln + - QRinput::estimateBitsModeAn($q); // - 4 - la + + if($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + + $run = $p; + + if(!self::isalnumat($this->dataStr, $p)) { + $dif = QRinput::estimateBitsModeAn($run) + 4 + $la + + QRinput::estimateBitsMode8(1) // + 4 + l8 + - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 + if($dif > 0) { + return $this->eat8(); + } + } + + $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eatKanji() + { + $p = 0; + + while($this->identifyMode($p) == QR_MODE_KANJI) { + $p += 2; + } + + $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eat8() + { + $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 1; + $dataStrLen = strlen($this->dataStr); + + while($p < $dataStrLen) { + + $mode = $this->identifyMode($p); + if($mode == QR_MODE_KANJI) { + break; + } + if($mode == QR_MODE_NUM) { + $q = $p; + while(self::isdigitat($this->dataStr, $q)) { + $q++; + } + $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 + + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln + - QRinput::estimateBitsMode8($q); // - 4 - l8 + if($dif < 0) { + break; + } else { + $p = $q; + } + } else if($mode == QR_MODE_AN) { + $q = $p; + while(self::isalnumat($this->dataStr, $q)) { + $q++; + } + $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 + + QRinput::estimateBitsModeAn($q - $p) + 4 + $la + - QRinput::estimateBitsMode8($q); // - 4 - l8 + if($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + + $run = $p; + $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr)); + + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function splitString() + { + while (strlen($this->dataStr) > 0) + { + if($this->dataStr == '') + return 0; + + $mode = $this->identifyMode(0); + + switch ($mode) { + case QR_MODE_NUM: $length = $this->eatNum(); break; + case QR_MODE_AN: $length = $this->eatAn(); break; + case QR_MODE_KANJI: + if ($hint == QR_MODE_KANJI) + $length = $this->eatKanji(); + else $length = $this->eat8(); + break; + default: $length = $this->eat8(); break; + + } + + if($length == 0) return 0; + if($length < 0) return -1; + + $this->dataStr = substr($this->dataStr, $length); + } + } + + //---------------------------------------------------------------------- + public function toUpper() + { + $stringLen = strlen($this->dataStr); + $p = 0; + + while ($p<$stringLen) { + $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint); + if($mode == QR_MODE_KANJI) { + $p += 2; + } else { + if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) { + $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32); + } + $p++; + } + } + + return $this->dataStr; + } + + //---------------------------------------------------------------------- + public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true) + { + if(is_null($string) || $string == '\0' || $string == '') { + throw new Exception('empty string!!!'); + } + + $split = new QRsplit($string, $input, $modeHint); + + if(!$casesensitive) + $split->toUpper(); + + return $split->splitString(); + } + } \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/qrtools.php b/src/admin/application/libs/phpqrcode/qrtools.php new file mode 100755 index 0000000..3012db4 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/qrtools.php @@ -0,0 +1,172 @@ +<?php +/* + * PHP QR Code encoder + * + * Toolset, handy and debug utilites. + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRtools { + + //---------------------------------------------------------------------- + public static function binarize($frame) + { + $len = count($frame); + foreach ($frame as &$frameLine) { + + for($i=0; $i<$len; $i++) { + $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0'; + } + } + + return $frame; + } + + //---------------------------------------------------------------------- + public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037') + { + $barcode_array = array(); + + if (!is_array($mode)) + $mode = explode(',', $mode); + + $eccLevel = 'L'; + + if (count($mode) > 1) { + $eccLevel = $mode[1]; + } + + $qrTab = QRcode::text($code, false, $eccLevel); + $size = count($qrTab); + + $barcode_array['num_rows'] = $size; + $barcode_array['num_cols'] = $size; + $barcode_array['bcode'] = array(); + + foreach ($qrTab as $line) { + $arrAdd = array(); + foreach(str_split($line) as $char) + $arrAdd[] = ($char=='1')?1:0; + $barcode_array['bcode'][] = $arrAdd; + } + + return $barcode_array; + } + + //---------------------------------------------------------------------- + public static function clearCache() + { + self::$frames = array(); + } + + //---------------------------------------------------------------------- + public static function buildCache() + { + QRtools::markTime('before_build_cache'); + + $mask = new QRmask(); + for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) { + $frame = QRspec::newFrame($a); + if (QR_IMAGE) { + $fileName = QR_CACHE_DIR.'frame_'.$a.'.png'; + QRimage::png(self::binarize($frame), $fileName, 1, 0); + } + + $width = count($frame); + $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); + for ($maskNo=0; $maskNo<8; $maskNo++) + $mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true); + } + + QRtools::markTime('after_build_cache'); + } + + //---------------------------------------------------------------------- + public static function log($outfile, $err) + { + if (QR_LOG_DIR !== false) { + if ($err != '') { + if ($outfile !== false) { + file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); + } else { + file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); + } + } + } + } + + //---------------------------------------------------------------------- + public static function dumpMask($frame) + { + $width = count($frame); + for($y=0;$y<$width;$y++) { + for($x=0;$x<$width;$x++) { + echo ord($frame[$y][$x]).','; + } + } + } + + //---------------------------------------------------------------------- + public static function markTime($markerId) + { + list($usec, $sec) = explode(" ", microtime()); + $time = ((float)$usec + (float)$sec); + + if (!isset($GLOBALS['qr_time_bench'])) + $GLOBALS['qr_time_bench'] = array(); + + $GLOBALS['qr_time_bench'][$markerId] = $time; + } + + //---------------------------------------------------------------------- + public static function timeBenchmark() + { + self::markTime('finish'); + + $lastTime = 0; + $startTime = 0; + $p = 0; + + echo '<table cellpadding="3" cellspacing="1"> + <thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead> + <tbody>'; + + foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) { + if ($p > 0) { + echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime-$lastTime, 6).'s</td></tr>'; + } else { + $startTime = $thisTime; + } + + $p++; + $lastTime = $thisTime; + } + + echo '</tbody><tfoot> + <tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime-$startTime, 6).'s</td></tr> + </tfoot> + </table>'; + } + + } + + //########################################################################## + + QRtools::markTime('start'); + \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/tools/merge.bat b/src/admin/application/libs/phpqrcode/tools/merge.bat new file mode 100755 index 0000000..b60a485 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/tools/merge.bat @@ -0,0 +1,2 @@ +php ./merge.php +pause \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/tools/merge.php b/src/admin/application/libs/phpqrcode/tools/merge.php new file mode 100755 index 0000000..19d338b --- /dev/null +++ b/src/admin/application/libs/phpqrcode/tools/merge.php @@ -0,0 +1,70 @@ +<?php + +/* + * PHP QR Code encoder + * + * Tool for merging all library files into one, simpler to incorporate. + * + * MAKE SURE THAT RESULTING PHPQRCode.php (and its dir) ARE WRITABLE! + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + $QR_BASEDIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR; + $QR_TOOLSDIR = dirname(__FILE__).DIRECTORY_SEPARATOR; + + $outputFile = $QR_BASEDIR.'phpqrcode.php'; + + // Required libs + + $fileList = array( + $QR_BASEDIR.'qrconst.php', + $QR_TOOLSDIR.'merged_config.php', + $QR_BASEDIR.'qrtools.php', + $QR_BASEDIR.'qrspec.php', + $QR_BASEDIR.'qrimage.php', + $QR_BASEDIR.'qrinput.php', + $QR_BASEDIR.'qrbitstream.php', + $QR_BASEDIR.'qrsplit.php', + $QR_BASEDIR.'qrrscode.php', + $QR_BASEDIR.'qrmask.php', + $QR_BASEDIR.'qrencode.php' + ); + + $headerFile = $QR_TOOLSDIR.'merged_header.php'; + $versionFile = $QR_BASEDIR.'VERSION'; + + $outputCode = ''; + + foreach($fileList as $fileName) { + $outputCode .= "\n\n".'//---- '.basename($fileName).' -----------------------------'."\n\n"; + $anotherCode = file_get_contents($fileName); + $anotherCode = preg_replace ('/^<\?php/', '', $anotherCode); + $anotherCode = preg_replace ('/\?>\*$/', '', $anotherCode); + $outputCode .= "\n\n".$anotherCode."\n\n"; + } + + $versionDataEx = explode("\n", file_get_contents($versionFile)); + + $outputContents = file_get_contents($headerFile); + $outputContents .= "\n\n/*\n * Version: ".trim($versionDataEx[0])."\n * Build: ".trim($versionDataEx[1])."\n */\n\n"; + $outputContents .= $outputCode; + + file_put_contents($outputFile, $outputContents); + + \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/tools/merge.sh b/src/admin/application/libs/phpqrcode/tools/merge.sh new file mode 100755 index 0000000..e4c2fbc --- /dev/null +++ b/src/admin/application/libs/phpqrcode/tools/merge.sh @@ -0,0 +1,2 @@ +#!/bin/sh +php ./merge.php \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/tools/merged_config.php b/src/admin/application/libs/phpqrcode/tools/merged_config.php new file mode 100755 index 0000000..55ddb45 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/tools/merged_config.php @@ -0,0 +1,17 @@ +<?php +/* + * PHP QR Code encoder + * + * Config file, tuned-up for merged verion + */ + + define('QR_CACHEABLE', false); // use cache - more disk reads but less CPU power, masks and format templates are stored there + define('QR_CACHE_DIR', false); // used when QR_CACHEABLE === true + define('QR_LOG_DIR', false); // default error logs dir + + define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code + define('QR_FIND_FROM_RANDOM', 2); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly + define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false + + define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images + \ No newline at end of file diff --git a/src/admin/application/libs/phpqrcode/tools/merged_header.php b/src/admin/application/libs/phpqrcode/tools/merged_header.php new file mode 100755 index 0000000..25805e5 --- /dev/null +++ b/src/admin/application/libs/phpqrcode/tools/merged_header.php @@ -0,0 +1,36 @@ +<?php + +/* + * PHP QR Code encoder + * + * This file contains MERGED version of PHP QR Code library. + * It was auto-generated from full version for your convenience. + * + * This merged version was configured to not requre any external files, + * with disabled cache, error loging and weker but faster mask matching. + * If you need tune it up please use non-merged version. + * + * For full version, documentation, examples of use please visit: + * + * http://phpqrcode.sourceforge.net/ + * https://sourceforge.net/projects/phpqrcode/ + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + \ No newline at end of file diff --git a/src/admin/application/pageTypes/Dashboard.xml b/src/admin/application/pageTypes/Dashboard.xml new file mode 100644 index 0000000..f407bfd --- /dev/null +++ b/src/admin/application/pageTypes/Dashboard.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Page.php"> + <glz:Import src="_common.xml" /> + + +</mvc:Page> \ No newline at end of file diff --git a/src/admin/application/pageTypes/Login.xml b/src/admin/application/pageTypes/Login.xml new file mode 100644 index 0000000..8fa0ce0 --- /dev/null +++ b/src/admin/application/pageTypes/Login.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Login.php"> + + <glz:Login accessPageId="glizycms_ContentsEdit_alias" + userField="loginform_LoginId" + passwordField="loginform_Password" + languageField="loginform_Language" + editableRegion="error" /> +</mvc:Page> \ No newline at end of file diff --git a/src/admin/application/pageTypes/Logout.xml b/src/admin/application/pageTypes/Logout.xml new file mode 100644 index 0000000..f824ce2 --- /dev/null +++ b/src/admin/application/pageTypes/Logout.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Page.php"> + + <glz:Logout/> +</mvc:Page> \ No newline at end of file diff --git a/src/admin/application/pageTypes/_common.xml b/src/admin/application/pageTypes/_common.xml new file mode 100644 index 0000000..9e94f72 --- /dev/null +++ b/src/admin/application/pageTypes/_common.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:EmptyComponent + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*"> + + <glz:Authenticator accessPageId="Login" logoutPageId="Logout" cssClass="logout" editableRegion="logout" /> + + <glz:NavigationMenu id="menu" startFrom="home" depth="+3" forceLink="true" drawAllChilds="false" selectParent="false" showOnlyChilds="true" editableRegion="leftSidebar" showPath="true" attributeToSelect="class" cssCurrent="active" /> + <glz:MessageBox type="SUCCESS" cssClass="alert welcome alert-info" /> + <glz:MessageBox type="ERROR" cssClass="alert alert-error"/> + + <cms:EditLanguage id="language-menu" editableRegion="languageMenu" cssClass="pull-left" /> + <glz:PageTitle id="pageTitle" wrap="true" wrapCssClass="section-title" drawIcon="true" /> + + <glz:JSscript src="application/templates/js/bootstrap.min.js" editableRegion="head" /> +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/admin/application/startup/index.php b/src/admin/application/startup/index.php new file mode 100644 index 0000000..22b6e22 --- /dev/null +++ b/src/admin/application/startup/index.php @@ -0,0 +1,10 @@ +<?php +org_glizycms_Glizycms::init(); +$application = org_glizy_ObjectValues::get('org.glizy', 'application' ); +if ($application && $application instanceof org_glizycms_core_application_AdminApplication) { + $application->registerProxy('movio.modules.ontologybuilder.service.FieldTypeService'); + $application->registerProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $application->registerProxy('movio.modules.ontologybuilder.service.LocaleService'); + + $application->registerProxy('movio.modules.publishApp.service.PublishAppService'); +} diff --git a/src/admin/application/startup/modules_custom.php b/src/admin/application/startup/modules_custom.php new file mode 100644 index 0000000..97a4929 --- /dev/null +++ b/src/admin/application/startup/modules_custom.php @@ -0,0 +1,7 @@ +<?php + +if ( file_exists( '../application/startup/modules_custom.php' ) ) +{ + __Paths::addClassSearchPath( __Paths::get( 'APPLICATION_TO_ADMIN' ).'classes/userModules/' ); + include('../application/startup/modules_custom.php'); +} \ No newline at end of file diff --git a/src/admin/application/startup/movio.php b/src/admin/application/startup/movio.php new file mode 100644 index 0000000..200bf47 --- /dev/null +++ b/src/admin/application/startup/movio.php @@ -0,0 +1,4 @@ +<?php +if (__Paths::get('APPLICATION_TO_ADMIN')) { + require __Paths::get('APPLICATION_TO_ADMIN').'startup/movio.php'; +} diff --git a/src/admin/application/templates/Login.php b/src/admin/application/templates/Login.php new file mode 100755 index 0000000..6e14728 --- /dev/null +++ b/src/admin/application/templates/Login.php @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <title><?php print($docTitle); ?></title> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <link rel="stylesheet" href="css/styles.css" /> + <?php print($head); ?> +</head> +<body id="LoginPage"> + <div id="outer"> + <div id="loginbox"> + <div class="container-fluid"> + <div class="row-fluid"> + <div class="span12"> + <form id="login" method="post" action=""> + <img id="logo" src="img/logo/logo-login.png" alt="<?php echo __Config::get('APP_NAME')?>" /> + <hr class="separator" /> + <?php if ($error) {?> + <div class="alert alert-error"><?php print($error) ?></div> + <?php } else {?> + <span class="text">Inserisci username e password.</span> + <?php }?> + <div class="input-prepend"> + <span class="add-on"><i class="icon-user"></i></span> + <input class="span11" name="loginform_LoginId" type="text" placeholder="Username" /> + </div> + <div class="input-prepend"> + <span class="add-on"><i class="icon-lock"></i></span> + <input class="span11" name="loginform_Password" type="password" placeholder="Password" /> + </div> + <div class="input-prepend"> + <span class="add-on"><i class="icon-asterisk"></i></span> + <select name="loginform_Language" class="span11"> + <option value="en">English</option> + <option value="it">Italiano</option> + </select> + </div> + <br /> + <input type="hidden" name="action" value="login"> + <input type="submit" id="submit" class="pull-right btn btn-inverse" value="Login" /> + </form> + </div> + </div> + </div> + </div> + + </div> + <footer> + <p><?php echo __Config::get('APP_NAME').' v'.__Config::get('APP_VERSION') ?></p> + </footer> + <?php print(@$tail); ?> + </body> +</html> \ No newline at end of file diff --git a/src/admin/application/templates/Page.php b/src/admin/application/templates/Page.php new file mode 100644 index 0000000..4e4bb60 --- /dev/null +++ b/src/admin/application/templates/Page.php @@ -0,0 +1,76 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <title><?php print($docTitle); ?></title> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <?php print($head); ?> + <link rel="stylesheet" href="css/styles.css" /> + </head> + <body class="with-sidebar"> + <div id="outer"> + <div id="topbar"> + <div class="pull-left"> + <div id="dummy-logo"><img src="img/logo/logo-top.png" alt="<?php print( __Config::get( 'APP_NAME' ) ) ?>"></div> + <div id="dummy-text"><?php print( __Config::get( 'APP_NAME' ) ) ?></div> + </div> + + <div class="pull-right"> + + <!-- show-nav-for-iphone --> + <button type="button" class="show-nav-for-iphone" data-toggle="collapse" data-target="#nav-collapse"></button> + <!-- show-nav-for-iphone --> + + <?php print($languageMenu); ?> + <div class="pull-left"> + <div id="exit-menu" class="pull-left"><?php print($logout); ?></div> + </div> + </div> + </div> + <div id="sidebar"> + <div id="sidebar-inner"> + <?php print($leftSidebar); ?> + </div> + </div> + + <?php if (isset($treeview)) {?> + <?php print($treeview); ?> + <div id="container" class="with-treeview"> + <div id="container-inner" class="container-fluid"> + <?php print($content); ?> + </div> + </div> + <?php } else {?> + <div id="container"> + <?php + $showBreadcrumbsBar = (isset($breadcrumbs) && $breadcrumbs) || (isset($actions) && $actions); + $cssClass = $showBreadcrumbsBar ? 'with-breadcrumb' : ''; + ?> + <div id="container-inner" class="container-fluid <?php print($cssClass);?>"> + <?php if ($showBreadcrumbsBar) {?> + <div id="breadcrumb-bar"> + <div id="breadcrumb"> + <?php print(@$breadcrumbs); ?> + </div> + <div id="breadcrumb-actions"> + <?php print(@$actions); ?> + </div> + </div> + <?php }?> + <div class="box-content"> + <div class="row-fluid"> + <div class="span12"> + <div id="admincontent" class="box"> + <div id="message-box"></div> + <?php print($content); ?> + </div> + </div> + </div> + </div> + </div> + </div> + <?php } ?> + </div> + <?php print(@$tail); ?> + </body> +</html> \ No newline at end of file diff --git a/src/admin/application/templates/Popup.php b/src/admin/application/templates/Popup.php new file mode 100755 index 0000000..dd5bc28 --- /dev/null +++ b/src/admin/application/templates/Popup.php @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html lang="it"> +<head> + <meta charset="utf-8"> + <title><?php print($docTitle); ?></title> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <link rel="stylesheet" href="css/styles.css" /> + <?php print($head); ?> +</head> +<body> + <div class="box-content box-padding"> + <?php print($content); ?> + </div> + <?php print(@$tail); ?> +</body> +</html> \ No newline at end of file diff --git a/src/admin/application/templates/css/styles.css b/src/admin/application/templates/css/styles.css new file mode 100644 index 0000000..1fb12f2 --- /dev/null +++ b/src/admin/application/templates/css/styles.css @@ -0,0 +1,91 @@ +@import url(http://fonts.googleapis.com/css?family=PT+Sans:400,700,400italic);html,button,input,select,textarea{color:#222}body{font-size:1em;line-height:1.4}::-moz-selection{background:#b3d4fc;text-shadow:none}::selection{background:#b3d4fc;text-shadow:none}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:1em 0;padding:0}img{vertical-align:middle}fieldset{border:0;margin:0;padding:0}textarea{resize:vertical}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{background-color:transparent;border:0;overflow:hidden;*text-indent:-9999px}.ir:before{content:"";display:block;width:0;height:100%}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.clearfix:before,.clearfix:after{content:" ";display:table}.clearfix:after{clear:both}.clearfix{*zoom:1}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-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}}/*! + * Bootstrap v2.2.2 + * + * 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. + */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}}.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}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{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{color:#808080}.text-warning{color:#c09853}a.text-warning:hover{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover{color:#2d6987}.text-success{color:#468847}a.text-success:hover{color:#356635}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;padding-right:5px;padding-left:5px}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:16px;font-weight:300;line-height:25px}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{margin-bottom:5px;font-size:0;white-space:nowrap}.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{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{-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{-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 tfoot:last-child tr:last-child>td: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 tfoot:last-child tr:last-child>td: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:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>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{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{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{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{color:#999}.dropdown-menu .disabled>a:hover{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{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 #bbb;*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:#a2a2a2;-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:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#cccccc \9}.btn:first-child{*margin-left:0}.btn:hover{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{border-color:#c5c5c5;border-color:rgba(0,0,0,0.15) rgba(0,0,0,0.15) rgba(0,0,0,0.25)}.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: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:#003399 \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: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: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: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: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: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{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover{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-mini .caret,.btn-small .caret,.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.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{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{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{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover{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{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{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{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{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{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{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover{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{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{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{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{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{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover{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{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover{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{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: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:#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 #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{border-top-color:#555;border-bottom-color:#555}.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{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{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{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: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:#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 #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>.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{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{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>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: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 .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;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{margin-top:-3px}.tooltip.right{margin-left:3px}.tooltip.bottom{margin-top:3px}.tooltip.left{margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 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;width:236px;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-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{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.badge:hover{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(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.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(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.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(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.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(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.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(.25, rgba(255,255,255,0.15)), color-stop(.25, transparent), color-stop(.5, transparent), color-stop(.5, rgba(255,255,255,0.15)), color-stop(.75, rgba(255,255,255,0.15)), color-stop(.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{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{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.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}/*! + * Bootstrap Responsive v2.2.2 + * + * 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. + */@-ms-viewport{width:device-width}.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}.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}}@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:481px) 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: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 .dropdown-menu a:hover{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 .dropdown-menu a:hover{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: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:#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}}/*! + * Font Awesome 3.0.2 + * the iconic font designed for use with Twitter Bootstrap + * ------------------------------------------------------- + * The full suite of pictographic icons, examples, and documentation + * can be found at: http://fortawesome.github.com/Font-Awesome/ + * + * License + * ------------------------------------------------------- + * - The Font Awesome font is licensed under the SIL Open Font License - http://scripts.sil.org/OFL + * - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License - + * http://opensource.org/licenses/mit-license.html + * - The Font Awesome pictograms are licensed under the CC BY 3.0 License - http://creativecommons.org/licenses/by/3.0/ + * - Attribution is no longer required in Font Awesome 3.0, but much appreciated: + * "Font Awesome by Dave Gandy - http://fortawesome.github.com/Font-Awesome" + + * Contact + * ------------------------------------------------------- + * Email: dave@davegandy.com + * Twitter: http://twitter.com/fortaweso_me + * Work: Lead Product Designer @ http://kyruus.com + */@font-face{font-family:'FontAwesome';src:url('../font/fontawesome-webfont.eot?v=3.0.1');src:url('../font/fontawesome-webfont.eot?#iefix&v=3.0.1') format('embedded-opentype'),url('../font/fontawesome-webfont.woff?v=3.0.1') format('woff'),url('../font/fontawesome-webfont.ttf?v=3.0.1') format('truetype');font-weight:normal;font-style:normal}[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0 0;background-repeat:repeat;margin-top:0}.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:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none}[class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none}a [class^="icon-"],a [class*=" icon-"]{display:inline-block}.icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em}.btn [class^="icon-"],.nav [class^="icon-"],.btn [class*=" icon-"],.nav [class*=" icon-"]{display:inline}.btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em}.btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block}.nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em}li [class^="icon-"],.nav li [class^="icon-"],li [class*=" icon-"],.nav li [class*=" icon-"]{display:inline-block;width:1.25em;text-align:center}li [class^="icon-"].icon-large,.nav li [class^="icon-"].icon-large,li [class*=" icon-"].icon-large,.nav li [class*=" icon-"].icon-large{width:1.5625em}ul.icons{list-style-type:none;text-indent:-0.75em}ul.icons li [class^="icon-"],ul.icons li [class*=" icon-"]{width:.75em}.icon-muted{color:#eee}.icon-border{border:solid 1px #eee;padding:.2em .25em .15em;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.icon-2x{font-size:2em}.icon-2x.icon-border{border-width:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.icon-3x{font-size:3em}.icon-3x.icon-border{border-width:3px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.icon-4x{font-size:4em}.icon-4x.icon-border{border-width:4px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.pull-right{float:right}.pull-left{float:left}[class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em}[class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em}.btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon-"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em}.btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em}.btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em}.btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em}.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em}.icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}@-moz-document url-prefix(){.icon-spin{height:.9em}.btn .icon-spin{height:auto}.icon-spin.icon-large{height:1.25em}.btn .icon-spin.icon-large{height:.75em}}.icon-glass:before{content:"\f000"}.icon-music:before{content:"\f001"}.icon-search:before{content:"\f002"}.icon-envelope:before{content:"\f003"}.icon-heart:before{content:"\f004"}.icon-star:before{content:"\f005"}.icon-star-empty:before{content:"\f006"}.icon-user:before{content:"\f007"}.icon-film:before{content:"\f008"}.icon-th-large:before{content:"\f009"}.icon-th:before{content:"\f00a"}.icon-th-list:before{content:"\f00b"}.icon-ok:before{content:"\f00c"}.icon-remove:before{content:"\f00d"}.icon-zoom-in:before{content:"\f00e"}.icon-zoom-out:before{content:"\f010"}.icon-off:before{content:"\f011"}.icon-signal:before{content:"\f012"}.icon-cog:before{content:"\f013"}.icon-trash:before{content:"\f014"}.icon-home:before{content:"\f015"}.icon-file:before{content:"\f016"}.icon-time:before{content:"\f017"}.icon-road:before{content:"\f018"}.icon-download-alt:before{content:"\f019"}.icon-download:before{content:"\f01a"}.icon-upload:before{content:"\f01b"}.icon-inbox:before{content:"\f01c"}.icon-play-circle:before{content:"\f01d"}.icon-repeat:before{content:"\f01e"}.icon-refresh:before{content:"\f021"}.icon-list-alt:before{content:"\f022"}.icon-lock:before{content:"\f023"}.icon-flag:before{content:"\f024"}.icon-headphones:before{content:"\f025"}.icon-volume-off:before{content:"\f026"}.icon-volume-down:before{content:"\f027"}.icon-volume-up:before{content:"\f028"}.icon-qrcode:before{content:"\f029"}.icon-barcode:before{content:"\f02a"}.icon-tag:before{content:"\f02b"}.icon-tags:before{content:"\f02c"}.icon-book:before{content:"\f02d"}.icon-bookmark:before{content:"\f02e"}.icon-print:before{content:"\f02f"}.icon-camera:before{content:"\f030"}.icon-font:before{content:"\f031"}.icon-bold:before{content:"\f032"}.icon-italic:before{content:"\f033"}.icon-text-height:before{content:"\f034"}.icon-text-width:before{content:"\f035"}.icon-align-left:before{content:"\f036"}.icon-align-center:before{content:"\f037"}.icon-align-right:before{content:"\f038"}.icon-align-justify:before{content:"\f039"}.icon-list:before{content:"\f03a"}.icon-indent-left:before{content:"\f03b"}.icon-indent-right:before{content:"\f03c"}.icon-facetime-video:before{content:"\f03d"}.icon-picture:before{content:"\f03e"}.icon-pencil:before{content:"\f040"}.icon-map-marker:before{content:"\f041"}.icon-adjust:before{content:"\f042"}.icon-tint:before{content:"\f043"}.icon-edit:before{content:"\f044"}.icon-share:before{content:"\f045"}.icon-check:before{content:"\f046"}.icon-move:before{content:"\f047"}.icon-step-backward:before{content:"\f048"}.icon-fast-backward:before{content:"\f049"}.icon-backward:before{content:"\f04a"}.icon-play:before{content:"\f04b"}.icon-pause:before{content:"\f04c"}.icon-stop:before{content:"\f04d"}.icon-forward:before{content:"\f04e"}.icon-fast-forward:before{content:"\f050"}.icon-step-forward:before{content:"\f051"}.icon-eject:before{content:"\f052"}.icon-chevron-left:before{content:"\f053"}.icon-chevron-right:before{content:"\f054"}.icon-plus-sign:before{content:"\f055"}.icon-minus-sign:before{content:"\f056"}.icon-remove-sign:before{content:"\f057"}.icon-ok-sign:before{content:"\f058"}.icon-question-sign:before{content:"\f059"}.icon-info-sign:before{content:"\f05a"}.icon-screenshot:before{content:"\f05b"}.icon-remove-circle:before{content:"\f05c"}.icon-ok-circle:before{content:"\f05d"}.icon-ban-circle:before{content:"\f05e"}.icon-arrow-left:before{content:"\f060"}.icon-arrow-right:before{content:"\f061"}.icon-arrow-up:before{content:"\f062"}.icon-arrow-down:before{content:"\f063"}.icon-share-alt:before{content:"\f064"}.icon-resize-full:before{content:"\f065"}.icon-resize-small:before{content:"\f066"}.icon-plus:before{content:"\f067"}.icon-minus:before{content:"\f068"}.icon-asterisk:before{content:"\f069"}.icon-exclamation-sign:before{content:"\f06a"}.icon-gift:before{content:"\f06b"}.icon-leaf:before{content:"\f06c"}.icon-fire:before{content:"\f06d"}.icon-eye-open:before{content:"\f06e"}.icon-eye-close:before{content:"\f070"}.icon-warning-sign:before{content:"\f071"}.icon-plane:before{content:"\f072"}.icon-calendar:before{content:"\f073"}.icon-random:before{content:"\f074"}.icon-comment:before{content:"\f075"}.icon-magnet:before{content:"\f076"}.icon-chevron-up:before{content:"\f077"}.icon-chevron-down:before{content:"\f078"}.icon-retweet:before{content:"\f079"}.icon-shopping-cart:before{content:"\f07a"}.icon-folder-close:before{content:"\f07b"}.icon-folder-open:before{content:"\f07c"}.icon-resize-vertical:before{content:"\f07d"}.icon-resize-horizontal:before{content:"\f07e"}.icon-bar-chart:before{content:"\f080"}.icon-twitter-sign:before{content:"\f081"}.icon-facebook-sign:before{content:"\f082"}.icon-camera-retro:before{content:"\f083"}.icon-key:before{content:"\f084"}.icon-cogs:before{content:"\f085"}.icon-comments:before{content:"\f086"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-star-half:before{content:"\f089"}.icon-heart-empty:before{content:"\f08a"}.icon-signout:before{content:"\f08b"}.icon-linkedin-sign:before{content:"\f08c"}.icon-pushpin:before{content:"\f08d"}.icon-external-link:before{content:"\f08e"}.icon-signin:before{content:"\f090"}.icon-trophy:before{content:"\f091"}.icon-github-sign:before{content:"\f092"}.icon-upload-alt:before{content:"\f093"}.icon-lemon:before{content:"\f094"}.icon-phone:before{content:"\f095"}.icon-check-empty:before{content:"\f096"}.icon-bookmark-empty:before{content:"\f097"}.icon-phone-sign:before{content:"\f098"}.icon-twitter:before{content:"\f099"}.icon-facebook:before{content:"\f09a"}.icon-github:before{content:"\f09b"}.icon-unlock:before{content:"\f09c"}.icon-credit-card:before{content:"\f09d"}.icon-rss:before{content:"\f09e"}.icon-hdd:before{content:"\f0a0"}.icon-bullhorn:before{content:"\f0a1"}.icon-bell:before{content:"\f0a2"}.icon-certificate:before{content:"\f0a3"}.icon-hand-right:before{content:"\f0a4"}.icon-hand-left:before{content:"\f0a5"}.icon-hand-up:before{content:"\f0a6"}.icon-hand-down:before{content:"\f0a7"}.icon-circle-arrow-left:before{content:"\f0a8"}.icon-circle-arrow-right:before{content:"\f0a9"}.icon-circle-arrow-up:before{content:"\f0aa"}.icon-circle-arrow-down:before{content:"\f0ab"}.icon-globe:before{content:"\f0ac"}.icon-wrench:before{content:"\f0ad"}.icon-tasks:before{content:"\f0ae"}.icon-filter:before{content:"\f0b0"}.icon-briefcase:before{content:"\f0b1"}.icon-fullscreen:before{content:"\f0b2"}.icon-group:before{content:"\f0c0"}.icon-link:before{content:"\f0c1"}.icon-cloud:before{content:"\f0c2"}.icon-beaker:before{content:"\f0c3"}.icon-cut:before{content:"\f0c4"}.icon-copy:before{content:"\f0c5"}.icon-paper-clip:before{content:"\f0c6"}.icon-save:before{content:"\f0c7"}.icon-sign-blank:before{content:"\f0c8"}.icon-reorder:before{content:"\f0c9"}.icon-list-ul:before{content:"\f0ca"}.icon-list-ol:before{content:"\f0cb"}.icon-strikethrough:before{content:"\f0cc"}.icon-underline:before{content:"\f0cd"}.icon-table:before{content:"\f0ce"}.icon-magic:before{content:"\f0d0"}.icon-truck:before{content:"\f0d1"}.icon-pinterest:before{content:"\f0d2"}.icon-pinterest-sign:before{content:"\f0d3"}.icon-google-plus-sign:before{content:"\f0d4"}.icon-google-plus:before{content:"\f0d5"}.icon-money:before{content:"\f0d6"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-columns:before{content:"\f0db"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-envelope-alt:before{content:"\f0e0"}.icon-linkedin:before{content:"\f0e1"}.icon-undo:before{content:"\f0e2"}.icon-legal:before{content:"\f0e3"}.icon-dashboard:before{content:"\f0e4"}.icon-comment-alt:before{content:"\f0e5"}.icon-comments-alt:before{content:"\f0e6"}.icon-bolt:before{content:"\f0e7"}.icon-sitemap:before{content:"\f0e8"}.icon-umbrella:before{content:"\f0e9"}.icon-paste:before{content:"\f0ea"}.icon-lightbulb:before{content:"\f0eb"}.icon-exchange:before{content:"\f0ec"}.icon-cloud-download:before{content:"\f0ed"}.icon-cloud-upload:before{content:"\f0ee"}.icon-user-md:before{content:"\f0f0"}.icon-stethoscope:before{content:"\f0f1"}.icon-suitcase:before{content:"\f0f2"}.icon-bell-alt:before{content:"\f0f3"}.icon-coffee:before{content:"\f0f4"}.icon-food:before{content:"\f0f5"}.icon-file-alt:before{content:"\f0f6"}.icon-building:before{content:"\f0f7"}.icon-hospital:before{content:"\f0f8"}.icon-ambulance:before{content:"\f0f9"}.icon-medkit:before{content:"\f0fa"}.icon-fighter-jet:before{content:"\f0fb"}.icon-beer:before{content:"\f0fc"}.icon-h-sign:before{content:"\f0fd"}.icon-plus-sign-alt:before{content:"\f0fe"}.icon-double-angle-left:before{content:"\f100"}.icon-double-angle-right:before{content:"\f101"}.icon-double-angle-up:before{content:"\f102"}.icon-double-angle-down:before{content:"\f103"}.icon-angle-left:before{content:"\f104"}.icon-angle-right:before{content:"\f105"}.icon-angle-up:before{content:"\f106"}.icon-angle-down:before{content:"\f107"}.icon-desktop:before{content:"\f108"}.icon-laptop:before{content:"\f109"}.icon-tablet:before{content:"\f10a"}.icon-mobile-phone:before{content:"\f10b"}.icon-circle-blank:before{content:"\f10c"}.icon-quote-left:before{content:"\f10d"}.icon-quote-right:before{content:"\f10e"}.icon-spinner:before{content:"\f110"}.icon-circle:before{content:"\f111"}.icon-reply:before{content:"\f112"}.icon-github-alt:before{content:"\f113"}.icon-folder-close-alt:before{content:"\f114"}.icon-folder-open-alt:before{content:"\f115"}html,body{margin:0;padding:0;height:100%;width:100%;font-family:'PT Sans',sans-serif;padding:0 !important}body>#outer{height:auto;min-height:100%;width:100%;position:relative}label,select,button,input[type="text"],input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{font-family:'PT Sans',sans-serif}input[type="search"]{font-family:'PT Sans',sans-serif}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{font-family:'PT Sans',sans-serif}a{color:#c04416}a:hover{color:#af4600;text-decoration:underline}footer{position:absolute;text-align:right;color:#999;font-size:13px;padding-top:0;height:34px;right:10px;padding-bottom:15px !important;margin-right:0}footer p{margin:0;padding:0;font-style:italic;padding-top:10px;position:relative}.form-vertical .control-group{padding-bottom:0;margin-bottom:0}.form-vertical .control-group input[type="text"]{padding:0 !important;font-size:12px;margin-bottom:0}.form-vertical .control-group input[type="text"][class*="span"]{min-height:0}.btn{font-size:13px}a.thumbnail:hover{border-color:#c04416}.alert{border-radius:0}.alert .close{margin-top:2px}.alert.welcome{border-color:#bce8f1;background-color:#d9edf7}.alert.welcome.alert-info{color:#3e89ae}.alert.alert-info{color:#333}.label{font-weight:lighter}.box.margin-top{margin-top:10px}a.action-link{float:left;display:block;color:#666;font-weight:normal;padding:2px 10px 1px 10px;margin-right:10px;margin-top:6px;font-size:13px;font-style:normal}a.action-link.btn{border:0;background:none;box-shadow:none;font-size:13px;text-shadow:0 1px 1px rgba(255,255,255,0.75)}a.action-link.btnBig{font-size:15px}a.action-link i{margin-top:0}a.action-link:hover{text-decoration:none;background-color:#f6f6f6;color:#000 !important;background:none !important}a.action-link:focus{outline:0}a.action-link.with-background{background-color:#eee}a.action-link.with-background:hover{background-color:#bbb !important;text-decoration:none;color:#fff !important}.action-link.btn-primary.btn{border:0;background:none;box-shadow:none;float:left;display:block;color:#666;font-weight:400;padding:3px 10px 1px 10px;margin-right:10px;margin-top:6px;font-size:13px;text-shadow:0 1px 1px rgba(255,255,255,0.75)}div.afterTableActions{margin:20px 0;text-align:center}div.afterTableActions a.action-link{float:none}#topbar a.action-link.btn{text-shadow:none}#topbar .dropdown-menu li a{color:#black2}#language-menu .btn-group a.action-link.btn{margin:0;margin-top:-3px}#language-menu .btn-group .dropdown-menu li a{color:#333;text-indent:0;font-size:13px;padding-left:10px !important}#language-menu .btn-group .dropdown-menu li a:hover{color:#fff}.show-nav-for-iphone{display:none}#nav-collapse.collapse{height:auto}@media (max-width:768px){#nav-collapse.collapse{height:0}}@media (max-width:768px){.show-nav-for-iphone{display:block;position:absolute;right:7px;top:7px;background:#ff8243 url("../img/glyphicons-halflings-white.png") -332px -44px no-repeat;width:24px;height:24px;border:0;border:1px solid #e55c00;padding:0;z-index:9999}}.thumbnail{min-height:130px}#LoginPage{background:#fff url('../img/login-bkg.png') top center repeat-x scroll}#LoginPage footer{position:absolute;bottom:0}#LoginPage a,#LoginPage #loginbox .text{text-shadow:0 1px 0 #fff}#LoginPage a{font-size:12px;color:#004489}#LoginPage hr.separator{width:100%;height:1px;border-top:1px solid #eee;border-bottom:1px solid #fff;border-left:none;border-right:none;margin:15px 0}#LoginPage #loginbox{position:absolute;top:50%;left:50%;margin:0;margin-top:-155px;margin-left:-200px;width:400px;background-color:#f5f5f5;border:1px solid #ccc;border-radius:5px;box-shadow:0 0 15px #d4d4d4 inset}#LoginPage #loginbox div[class*="span"]{margin:30px 0;text-align:center}#LoginPage #loginbox div[class*="span"] .text{display:block;color:#333;font-size:14px;font-weight:normal;margin-bottom:20px}#LoginPage #loginbox div[class*="span"] .alert{color:#000;padding-right:0;padding-left:0;text-align:center;font-size:12px}#LoginPage #loginbox div[class*="span"] .alert .alert-error{background-color:#ffebe8;border:1px solid #c33}#LoginPage #loginbox div[class*="span"] .alert a{text-decoration:underline}#LoginPage #loginbox div[class*="span"] .alert a:hover{text-decoration:none}.pagination{text-align:center}.pagination ul{border-radius:0 !important}.pagination ul>li>a,.pagination ul>li>span{border-radius:0 !important}.pagination span{float:left}#topbar{min-height:36px;background:#82992d;position:fixed;width:100%;z-index:3;top:0}#topbar>.pull-left{height:100%;width:auto;position:relative}#topbar .pull-right{margin-right:10px}@media (max-width:767px){#topbar .pull-right{float:left;width:100%;margin-top:1px;background-color:#e55c00;margin-left:-2px}}#topbar #dummy-logo{padding:0;float:left;height:25px}#topbar #dummy-text{font-weight:lighter;color:#fff;padding:8px 0 0 10px;float:left;font-size:22px;height:26px}#language-menu,#user-menu,#exit-menu{padding:8px 13px 4px 13px;color:#fff;height:25px}#language-menu a,#user-menu>a,#exit-menu a{color:#fff}#language-menu a:hover,#user-menu>a:hover,#exit-menu a:hover{color:#fff !important;text-decoration:none}#language-menu strong{margin-left:10px}#language-menu{border-left:1px solid #9db936}#user-menu{border-left:1px solid #9db936}#exit-menu{border-left:1px solid #9db936}#language-menu .dropdown-menu:before,#user-menu .dropdown-menu:before{border-bottom:7px solid rgba(0,0,0,0.2);border-left:7px solid transparent;border-right:7px solid transparent;content:"";display:inline-block;left:19px;position:absolute;top:-7px}#language-menu .dropdown-menu:after,#user-menu .dropdown-menu:after{border-bottom:6px solid #fff;border-left:6px solid transparent;border-right:6px solid transparent;content:"";display:inline-block;left:20px;position:absolute;top:-6px}#sidebar,#treeview{z-index:2;position:absolute;min-height:100%;float:left;top:0;width:200px;background-color:#f6f6f6;border-right:1px solid #ddd;box-shadow:-7px 0 10px rgba(0,0,0,0.03) inset}#sidebar-inner{padding-top:42px}#sidebar-inner .quick-link-block{position:absolute;top:0;right:0;width:200px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:-2px -201px 0 0;background-color:#ddd;border:1px solid #ddd;display:none}#sidebar-inner .quick-link-block:before{content:'';display:inline-block;border-top:7px solid transparent;border-bottom:7px solid transparent;border-right:7px solid #000;position:absolute;left:-8px;top:7px;opacity:.1}#sidebar-inner .quick-link-block .quick-link-list{background:#fff;padding:0;margin:0;padding-left:10px}#sidebar-inner .quick-link-block .quick-link-list:before{content:'';display:inline-block;border-top:7px solid transparent;border-bottom:7px solid transparent;border-right:7px solid #fff;position:absolute;left:-7px;top:5px}#sidebar-inner ul{margin:0;padding:0;list-style:none;position:relative}#sidebar-inner ul li{position:relative}#sidebar-inner ul li:hover .quick-link-block{display:block}#sidebar-inner>ul{border-bottom:1px solid #fcfcfc}#sidebar-inner>ul>li{border-top:1px solid #fcfcfc;border-bottom:1px solid #ddd}#sidebar-inner>ul>li:first-child{border-top:none}#sidebar-inner>ul>li>a{display:block;padding:3px 10px 3px 7px;color:#505050;text-shadow:0 1px 0 #fff;position:relative;font-size:15px}#sidebar-inner>ul>li.open>a{padding:10px 10px 0 5px;border-left:10px solid #ddd}#sidebar-inner>ul>li.active>a{font-weight:bold}#sidebar-inner>ul>li.active>a:before{content:'';display:inline-block;border-top:7px solid transparent;border-bottom:7px solid transparent;border-right:7px solid #000;position:absolute;right:0;top:5px;opacity:.1}#sidebar-inner>ul>li.active>a:after{content:'';display:inline-block;border-top:6px solid transparent;border-bottom:6px solid transparent;border-right:6px solid #fff;position:absolute;right:-1px;top:5px}#sidebar-inner>ul>li>a>span.badge{float:right;margin-right:5px}#sidebar-inner>ul>li>a>i{margin-right:5px}#sidebar-inner ul ul{padding:0 0 0 35px}#sidebar-inner>ul>li>ul{border-left:10px solid #ddd;padding-bottom:5px}#sidebar-inner ul li ul{display:none}#sidebar-inner ul li.open>ul{display:block}#sidebar-inner ul ul li a{display:block;color:#505050;line-height:24px;position:relative}#sidebar-inner ul ul li a [class^="icon-"]{display:none}#sidebar-inner ul ul li.active>a{font-weight:bold}#sidebar-inner ul ul li.active>a:before{content:'';display:inline-block;border-top:7px solid transparent;border-bottom:7px solid transparent;border-right:7px solid #000;position:absolute;right:0;top:4.6px;opacity:.1}#sidebar-inner ul ul li.active>a:after{content:'';display:inline-block;border-top:6px solid transparent;border-bottom:6px solid transparent;border-right:6px solid #fff;position:absolute;right:-1px;top:5px}#sidebar-inner ul ul ul{padding:0 0 0 20px}#sidebar-inner a:hover i{text-decoration:none}#treeview{margin-left:201px;width:229px;background-color:#fff;box-shadow:-60px 0 20px rgba(0,0,0,0.03) inset}#treeview #page-detail{min-height:98px;width:229px;margin-top:-10px;position:relative}#treeview #page-detail img{float:left;margin-right:12px;width:62px}#treeview #page-detail h2{font-size:16px;font-weight:lighter;line-height:1em;padding-top:12px}#treeview #page-detail .actions{position:absolute;bottom:0;right:0;font-size:12px;margin:0 8px 8px 0}#treeview #page-detail .actions i{color:#000}#treeview #page-detail .actions a:last-child{border-left:1px solid #ccc;padding-left:5px;margin-left:2px}#treeview-title{margin-top:36px;background-color:#f6f6f6;border-bottom:1px solid #ddd;display:block}#treeview-title h3{font-size:14px;color:#666;padding:9px 15px;line-height:14px;margin:0}#treeview-title a{float:right;display:block;color:#666;font-size:11px;font-weight:bold;margin:6px 8px 0 0}#treeview-title a i{margin-top:-1px}#treeview #openclose{width:10px;height:50px;background-color:#d8d8d8;position:absolute;right:0;top:200px}#treeview #openclose:hover{cursor:pointer}#treeview #openclose i{position:absolute;top:19px;opacity:.6}#treeview #openclose:hover i{opacity:1}.with-sidebar #container{margin-left:201px}.with-sidebar #container.with-treeview{margin-left:420px}.with-sidebar #container.with-treeview #container-inner{padding-right:0}.menu-horizontal #treeview{margin-left:-20px;margin-top:97px;padding-top:0}.menu-horizontal #treeview h3{margin-top:-36px}#container-inner{padding-top:36px}.menu-horizontal #container.with-treeview{margin-left:190px;margin-right:-40px;margin-top:-13px}.menu-horizontal #container.with-treeview #container-inner{padding-top:0}#container-inner.with-breadcrumb{padding-top:90px}#container-inner iframe{border:0;width:100%;height:600px}#breadcrumb-bar{height:33px;width:100%;padding:0;margin:-55px 0 0 0;border-bottom:1px solid #ddd;position:relative;background-color:#fff;z-index:1;display:block}#breadcrumb{float:left;margin-left:0;height:33px}#breadcrumb ul{margin:0 0 0 0;padding:0;list-style:none}#breadcrumb ul li{float:left}#breadcrumb ul li a{background-image:url("../img/breadcrumb.png");background-position:right center;background-repeat:no-repeat;color:#666;display:inline-block;font-size:12px;padding:8px 20px 8px 10px}#breadcrumb ul li:last-child a{font-weight:bold;background-image:none}#breadcrumb ul li a i{margin-top:-1px;margin-right:5px;opacity:.6}#breadcrumb-actions{float:right}#breadcrumb-actions a{font-weight:lighter !important}.navigation,.subnavigation{background-color:#f6f6f6;margin:0 -20px 15px !important;padding-right:40px;height:35px;box-shadow:-10px 0 10px rgba(0,0,0,0.1) inset;border-bottom:1px solid #ccc}.navigation.with-sub{margin-bottom:0 !important;box-shadow:0 -3px 10px rgba(0,0,0,0.1) inset}.navigation ul,.subnavigation ul{margin:0;padding:0;list-style:none}.navigation ul li,.subnavigation ul li{float:left}.navigation ul li.active{border-bottom:3px solid #c00}.navigation ul li a,.subnavigation ul li a{border-right:1px solid #ccc;display:block;color:#666;font-size:16px;padding:2px 15px 2px 15px;margin:5px 0 3px}.navigation ul li:last-child a,.subnavigation ul li:last-child a{border-right:0}.navigation ul li a:hover i{text-decoration:none}.subnavigation{background-color:#eee;height:23px;box-shadow:none}.subnavigation ul{margin-left:10px}.subnavigation ul li a{font-size:14px;padding:3px 10px;line-height:12px;margin:3px 0 0}.subnavigation ul li.active a{font-weight:bold}.subnavigation #breadcrumb-actions{margin-right:-40px}.subnavigation #breadcrumb-actions a{float:left;display:block;color:#666;font-weight:bold;padding:2px 10px 1px;margin-right:10px;margin-top:0;font-size:13px}.subnavigation #breadcrumb-actions a:hover{background-color:#e6e6e6}.subnavigation #breadcrumb-actions a.with-background{background-color:#dcdcdc}.subnavigation #breadcrumb-actions a.with-background:hover{background-color:#bbb;text-decoration:none;color:#fff}.page-title{padding:7px 5px 7px 5px;font-weight:bold;font-size:20px;line-height:26px;color:#505050;border-bottom:1px solid #ddd;margin:0}.page-title span{color:#999}.page-title .nav{float:right}.nav-tabs{margin-top:2px;display:block;position:relative}.nav-tabs li a{font-size:14px;padding:5px 10px;font-weight:normal;border-radius:0 !important;background-color:#666;color:#fff}.nav-tabs li a:hover{background-color:#bbb;border-color:#bbb}.nav-tabs li.active a{color:#666;background-color:#fff}.page-title .help-text{float:right;font-size:14px;font-weight:normal;margin:5px 10px 0 0}.box-content{padding:15px 0}.box-content.iframe{padding:15px}.box-padding{padding:15px 30px}.widget-box{margin:20px 0;border:1px solid #ccc}.widget-box h3.widget-title{font-size:13px;background-image:-moz-linear-gradient(top center, #f1f1f1 0, #e2e2e2 100%);border-bottom:1px solid #ccc;padding:4px 8px;margin:0;font-weight:normal;line-height:20px}.widget-box .widget-content{padding:10px;background-color:#fdfdfd;position:relative}.widget-box .widget-content.nopadding{padding:0}.widget-box form{margin-bottom:0}.widget-title .widget-icon{float:left;border-right:1px solid #ccc;padding:5px 7px;margin:-5px 10px 0 -5px}.widget-title .badge,.widget-title .label{float:right;margin-top:1px}.widget-actions{float:right;font-weight:normal;font-size:13px}.widget-actions.neg-margin{margin-top:-40px}.widget-actions .order-link{margin:0 8px}.widget-actions .order-link.active{color:#fff;background-color:#c04416;padding:3px 7px;border-radius:4px}.row-fluid [class*="span"] .widget-box:first-child{margin-top:0}.recent-posts,.recent-comments{margin:0;padding:0}.recent-posts li,.recent-comments li,.article-post li{border-bottom:1px dotted #aebdc8;list-style:none outside none;padding:10px}.recent-comments li{min-height:60px}.recent-comments li.show-all{min-height:20px}.recent-posts li .article-title{font-size:16px;font-weight:bold}.recent-posts li .user-info{font-size:12px;color:#777}.recent-posts li:last-child,.recent-comments li:last-child,.recent-users li:last-child{border-bottom:none !important}.recent-posts li .article-links,.recent-comments li .article-links{display:none;float:right}.recent-posts li:hover .article-links,.recent-comments li:hover .article-links{display:block}.recent-posts li.show-all,.recent-comments li.show-all{background-image:-moz-linear-gradient(top center, #fff 0, #efefef 100%);text-align:right;height:20px}.user-thumb{background:none repeat scroll 0 0 #fff;border:0;float:left;height:50px;margin-right:10px;margin-top:5px;padding:0;width:50px}.entities{display:inline-block;list-style:none outside none;margin:20px 0 10px;text-align:center;width:100%;position:relative;z-index:0}form .entities{margin-top:0;text-align:left}.entities li{background-color:#f6f6f6;background-image:-moz-linear-gradient(center top, #f9f9f9 0, #ededed 100%);border:1px solid #d5d5d5;box-shadow:0 1px 0 0 #fff inset,0 1px 0 rgba(255,255,255,0.4);display:inline-block;line-height:18px;margin:0 10px 10px;padding:0 10px;width:19.5%;position:relative;-moz-transition:all .2s ease-in-out;cursor:pointer;height:100px;overflow:hidden}.entities li:hover,.entities li.button-selected{border:1px solid #c04416;box-shadow:0 1px 0 0 #fff inset,0 0 6px rgba(0,0,0,0.1)}.entities li h5{font-size:18px;text-align:left}.entities li .description{float:left;margin-bottom:5px}.entities.publication{text-align:left}.entities.publication li{background-color:#fff;background-image:none;box-shadow:0 1px 0 0 #fff inset,0 0 6px rgba(0,0,0,0.1);height:148px;padding:0;position:relative;width:255px}.entities.publication li h5{font-size:16px;font-weight:normal;margin-bottom:0;padding-bottom:0}.entities.publication li small{color:#999}.entities.publication li img{float:left;margin-right:10px}.entities.publication li .description{position:absolute;top:0;left:100px}.entities.publication li .state{width:91px;display:inline-block;position:absolute;bottom:0;left:50%;color:#666;font-size:12px;text-align:center;margin-left:-25px}.entities.publication li .state.public{background:#d4f1be}.entities.publication li .state.no-public{background:#f99}.entities.ico-box li{background-color:#fff;background-image:none;width:10%;min-width:120px;padding:0}.entities.ico-box li a{display:inline-block;text-align:center;color:#333;min-height:26px;width:100%}.entities.ico-box li a:hover{text-decoration:none}.entities.ico-box li a.button-article{background:url(../img/article.png) center 10px no-repeat;padding-top:65px}.entities.ico-box li a.button-attach{background:url(../img/attach.png) center 10px no-repeat;padding-top:65px}.entities.ico-box li a.button-exercise{background:url(../img/exercise.png) center 10px no-repeat;padding-top:65px}.entities .actions{background:#333;padding:2px 7px;border-radius:5px;position:absolute;bottom:5px;right:5px}.entities .actions a{color:#fff}form.stickyForm .formButtons{position:fixed;bottom:0;left:50%;padding:10px 0;width:100%;left:0;z-index:9;text-align:center;height:20px;border:0;border-bottom:10px solid #82992d}form.stickyForm .formButtons .content{min-width:430px;background:#82992d;position:absolute;top:0;left:50%;margin-left:-215px;padding:10px 0}form.stickyForm .formButtons .content input{margin:0 3px;font-size:14px}.dropdown-menu{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.dropdown-menu.forced-left-position{margin-left:-90px}.dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{background-image:none;background-color:#c00}.input-append{width:100%}.input-append .btn{width:8.5%}label,input,button,select,textarea{font-size:15px;line-height:20px}.form-horizontal .control-label{width:180px;white-space:nowrap}.form-horizontal .controls{margin-left:200px}.vertical .control-label{text-align:left}.vertical .controls{margin-left:0}form fieldset{border:1px solid #f0f0f0;width:97%;margin:0 auto 20px}form fieldset .content{padding:10px;width:97.6%}form fieldset .content p{padding:0;margin:0 0 5px 0}form fieldset .content p input[type=checkbox]{margin:0;padding:0}form fieldset legend{padding:0;margin:0 0 10px 0;line-height:1em;width:99%;font-weight:bold;font-size:14px;padding:4px;padding-top:6px;background-color:#f0f0f0}.box-relations{min-width:910px}.box-relations h2{font-size:16px;margin:0;padding:0;line-height:1em;color:#999;font-weight:lighter;margin-bottom:10px}.box-relations .relation{background:#f5f5f5 url(../img/relation.png) 0 0 repeat-y;padding:8px 10px 0 15px;height:74px;font-size:14px;border-bottom:1px solid #fff}.box-relations .relation.light-bg{background:#fafafa url(../img/relation.png) 0 0 repeat-y}.box-relations .relation label{display:inline-block;margin-right:8px}.box-relations .relation span{display:inline-block;margin-top:5px}.box-relations .relation input[type=checkbox]{margin:-2px 5px 0 0;padding:0}.box-relations .relation input[type=text]{margin-left:8px;margin-right:8px}.box-relations .relation p{margin:0 0 6px 0;padding:0}.box-relations .relation select{font-size:14px;font-family:'PT Sans',sans-serif}.btn,input,textarea{border-radius:0 !important}.tab-content{width:100%}.tabs-left .tab-content,.tabs-right .tab-content{width:auto}.tabs-left .nav-tabs{margin-right:-1px}.tabs-left .tab-content{border-left:1px solid #ddd;padding-left:19px}.tabs-right .nav-tabs{margin-left:-1px}.tabs-right .tab-content{border-right:1px solid #ddd;padding-right:19px}.row-fluid{margin-bottom:0}.table,.table-bordered{border-radius:0}.table thead th{font-size:13px;background-color:#f1f1f1;background-image:-moz-linear-gradient(top center, #f1f1f1 0, #e2e2e2 100%);border-bottom:1px solid #ccc;padding:4px 8px}.table .table-links{font-size:12px}.table tr:hover .table-links{display:block}.table-bordered{border:0;border-top:1px solid #ccc}.table-bordered thead th,.table-bordered thead td{border-left:1px solid #ccc}.table-bordered 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{border-top-left-radius:0}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child{border-top-right-radius:0}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child{border-bottom-left-radius:0}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child{border-bottom-right-radius:0}.table-bordered thead tr td:first-child,.table-bordered thead tr th:first-child,.table-bordered tbody tr td:first-child{border-left:1px solid #ccc}.table-bordered thead tr td:last-child,.table-bordered thead tr th:last-child,.table-bordered tbody tr td:last-child{border-right:1px solid #ccc}.table-bordered tbody tr:last-child>td{border-bottom:1px solid #ccc}.table-bordered>tfoot>tr>td{border:0;color:#888;text-align:right;padding-right:15px;margin-top:0 !important;font-style:italic;padding:0}.form-actions{margin:20px -10px -10px;padding:10px;text-align:center;background-image:-moz-linear-gradient(top center, #fff 0, #efefef 100%)}.search-inputs{margin-bottom:30px;text-align:right;width:100%}.search-inputs .btn.calendar{background:#fff;border-left:0;margin-left:0}.search-inputs input[type=text],.search-inputs button{margin-bottom:0;margin-right:-5px}.search-inputs .search-input{border-radius:20px 0 0 20px !important}.search-inputs button.search{float:right;margin-top:5px}.search-inputs div.control-group{float:right}.search-inputs div.control-group input[type=text]{width:400px}.from-input,.to-input{background:url(../img/calendar.png) 90% 8px no-repeat}.table{font-size:15px}.dataTable span.sorting-arrow{display:inline-block;width:9px;height:9px;margin-left:5px}.dataTable thead th.sorting_asc span.sorting-arrow{background:no-repeat scroll 0 0 url('../img/up-arrow.png')}.dataTable thead th.sorting_desc span.sorting-arrow{background:no-repeat scroll 0 0 url('../img/down-arrow.png');margin-top:-1px}td.actions{text-align:right}td.actions a,td.actions a:hover,td.actions a:link{text-decoration:none}.dataTables_length,.dataTables_filter{position:relative;float:right}.dataTables_length label,.dataTables_filter label{font-size:13px}.dataTables_length{margin-left:5px}.dataTables_filter{margin-right:5px}.dataTables_length select,.dataTables_filter input{margin-bottom:4px;padding:1px 3px}.dataTables_length select{width:55px;padding:2px}.dataTables_info{color:#888;font-style:italic;text-align:right;margin-top:-10px;padding-right:10px;margin-bottom:10px}.dataTables_paginate{text-align:center;margin-bottom:20px}.dataTables_paginate .paginate_button,.dataTables_paginate .paginate_active,.paginate_disabled_previous,.paginate_enabled_previous,.paginate_disabled_next,.paginate_enabled_next,.paginate_disabled_next:hover,.paginate_disabled_previous:hover{background-color:#fff;border-color:#ddd;border-image:none;border-style:solid;border-width:1px 1px 1px 0;line-height:20px;padding:6px 12px;box-shadow:0 1px 2px rgba(0,0,0,0.05);text-decoration:none;color:#c00}.dataTables_paginate>a:first-child{border-left:1px solid #ddd}.dataTables_paginate .paginate_button:hover,.paginate_enabled_next:hover,.paginate_enabled_previous:hover{cursor:pointer;background-color:#f7f7f7;text-decoration:none}.paginate_disabled_next,.paginate_disabled_previous,.paginate_disabled_next:hover,.paginate_disabled_previous:hover,.paginate_button_disabled{color:#bbb !important}.paginate_button_disabled:hover{background:#fff !important;cursor:normal !important}.dataTables_paginate .paginate_active,.dataTables_paginate .paginate_active:hover{font-weight:bold;color:#000;padding:6px 12px 5px}.table-options{float:right;margin-top:-5px;margin-right:15px;height:18px;vertical-align:text-top;white-space:nowrap;font-weight:normal}.table-options .divider-horizontal{border-left:1px solid #ccc;border-right:1px solid #fff;display:inline-block;height:20px;margin:0 5px}.table-options input,.table-options select{font-size:12px;height:16px;vertical-align:baseline}.table-options select{margin-bottom:0;min-height:26px !important}.thumbnails{margin-left:-2.12766% !important}.thumbnails [class*="span"]{margin-left:2.12766% !important;position:relative}.thumbnails .title{position:absolute;width:100%;background:rgba(0,0,0,0.6);color:#fff;font-weight:bold;bottom:0;border-radius:0 0 0 0}.thumbnails .title .inner{padding:2px 10px}.thumbnails .actions{background-color:#000;border-radius:0;height:20px;right:0;margin-right:5px;opacity:0;padding:0 3px;position:absolute;bottom:2px;transition:opacity .3s ease-in-out 0s}.thumbnails .actions a{color:#fff;margin-top:-2px !important;display:inline-block}.thumbnails .actions a:hover{text-decoration:none}.thumbnail{-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important}.thumbnails .actions i{margin-top:0}.thumbnails li:hover .actions{opacity:1}.dropdown-menu.left{left:-110px}.section-title{font-size:20px;border-bottom:1px solid #ddd;padding-bottom:15px;margin-bottom:30px}.section-title h1{font-size:22px;line-height:1em;font-weight:400;padding:0;margin:0}.dataTables_wrapper .row-fluid .filter-box{float:left;margin-right:10px}.dataTables_wrapper .row-fluid .filter-box.pull-right{float:right;margin-right:0}.dataTables_wrapper .row-fluid .filter-box select{height:30px}.dataTables_wrapper .row-fluid .filter-box .dataTables_length{padding-top:3px;font-size:13px}.dataTables_wrapper .row-fluid .filter-box .dataTables_length select{margin-top:-3px}.dataTable th span.ui-icon,.table th span.ui-icon{float:left;margin-right:5px;margin-top:2px}.table th a{color:#333;text-decoration:none !important}.btn-icon{background:#666;display:inline-block;width:26px;height:26px;padding:0 0 0 1px;text-align:center;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;line-height:26px;font-size:18px;font-weight:lighter !important;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;color:#fff;-moz-transition:all .4s ease-in-out;-webkit-transition:all .4s ease-in-out;-o-transition:all .4s ease-in-out;transition:all .4s ease-in-out;backface-visibility:hidden;webkit-backface-visibility:hidden;margin-right:5px !important;text-decoration:none !important}.btn-icon:hover{opacity:.5;filter:alpha(opacity=.5);text-decoration:none !important}.btn-icon.icon-edit,.btn-icon.icon-pencil{background:#090}.btn-icon.icon-remove,.btn-icon.icon-trash{background:#c33}.btn-icon.icon-check-empty{padding:0 0 0 2px}.pull-right .btn-icon,.pull-left .btn-icon{float:left}.entities.select-theme li{border:1px solid #d5d5d5;box-shadow:0 1px 0 0 #fff inset,0 1px 0 rgba(255,255,255,0.4);display:inline-block;line-height:18px;margin:0 10px 10px;width:23% !important;position:relative;-moz-transition:all .2s ease-in-out;cursor:pointer}.entities.select-theme li a:hover,.entities.select-theme li a.button-selected{box-shadow:0 1px 0 0 #fff inset,0 0 6px !important}.choose-theme .control-group label{margin-left:-40px}.current-theme{padding-bottom:50px}.current-theme img{border:1px solid #d5d5d5}.current-theme i{padding:0;margin:0}.current-theme h3{padding:0;margin:0;line-height:1em;padding-bottom:15px}.table-bordered caption+thead tr:first-child th:first-child{border-top-left-radius:0}.control-group.small-width .control-label{width:auto}.control-group.small-width .controls{margin-left:80px}.nav-pills>.active>a,.nav-pills>.active>a:hover{background-color:#82992d;color:#fff}.nav-pills>li>a{color:#333}.my-filters{margin-bottom:15px}.my-filters .btn{margin-top:1px !important}input[type="text"],input[type="password"]{color:#333 !important}.ui-pnotify.stack-bar-top{right:0;top:0}form.stickyForm{margin-bottom:60px}.btn-icon{cursor:pointer}fieldset.GFEFieldset{margin-left:0 !important;padding:0 !important;overflow-x:hidden;border:0;margin-bottom:40px;border-bottom:1px solid #e5e5e5}fieldset.GFEFieldset legend{width:100%;font-size:17px;padding-left:6px;background:#fff;color:#666}fieldset.GFEFieldset .btn-icon{cursor:pointer}.GFEFooter{width:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:8px;margin:0 0 0 10px}.GFEButtonContainer{float:left}.GFEStatusContainer{float:right;font-size:13px;margin-top:9px}input.GFEAddRow{font-size:13px}.GFERowContainer{position:relative;padding:4px;background-color:#f0f0f0;margin-bottom:2px;-moz-user-select:-moz-none;-khtml-user-select:none;-webkit-user-select:none;user-select:none;width:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:0 0 0 10px}.GFERowContainer.GFERowContainerOdd{background-color:#e0e0e0}.GFERowContainer.GFEEditingRow{position:relative;z-index:101}.GFERowHeader{float:left}.GFERowHandler{float:left;cursor:move;height:95%}.GFERowHandler img{height:auto}.GFERowPreview div.GFEPreviewItem{display:none}.GFERowPreview div.GFEPreviewItem:nth-child(1){display:inline}.GFERowPreview div.GFEPreviewItem:nth-child(2){display:inline}.GFERowHandler.GFERowHandlerExpanded{position:absolute;top:3px}.GFERecordTitle{display:inline-block;font-weight:bold;margin:9px 12px}.GFERowPanel{float:right;margin:7px 5px}.GFEPreviewItem{display:inline-block;padding:2px 3px;margin:1px 5px;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;background:#fff}.GFESideClearer{clear:both}.GFEEmptyMessage{text-align:center;margin:6px}.GFERowContainer .icon{cursor:pointer}.GFERightIcon{position:absolute;top:5px;right:5px}.GFERowButtonContainer{text-align:center;clear:both;margin-top:14px}.GButtonDisabled{opacity:.5}.GFETranslucentCover{position:fixed;display:none;background-color:#000;top:0;bottom:0;left:0;right:0;z-index:100;opacity:.5}.GFEValidationError{border-left:3px solid #f00}.GFEValidationError>label{color:#f00}.GFEcomments{width:100%;height:150px;border:0 !important}.glizy-dropzone,.glizy-dropzone *,.dropzone-previews,.dropzone-previews *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.glizy-dropzone{position:relative;border:1px solid rgba(0,0,0,0.08);background:rgba(0,0,0,0.02);padding:1em}.glizy-dropzone p{margin:60px 0;text-align:center}.glizy-dropzone.dz-clickable{cursor:pointer}.glizy-dropzone.dz-clickable .dz-message,.glizy-dropzone.dz-clickable .dz-message span{cursor:pointer}.glizy-dropzone.dz-clickable *{cursor:default}.glizy-dropzone .dz-message{opacity:1;-ms-filter:none;filter:none}.glizy-dropzone.dz-drag-hover{border-color:rgba(0,0,0,0.15);background:rgba(0,0,0,0.04)}.glizy-dropzone.dz-started .dz-message{display:none}.glizy-dropzone .dz-preview,.dropzone-previews .dz-preview{background:rgba(255,255,255,0.8);position:relative;display:inline-block;margin:17px;vertical-align:top;border:1px solid #acacac;padding:6px 6px 6px 6px}.glizy-dropzone .dz-preview.dz-file-preview [data-dz-thumbnail],.dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail]{display:none}.glizy-dropzone .dz-preview .dz-details,.dropzone-previews .dz-preview .dz-details{width:100px;height:100px;position:relative;background:#ebebeb;padding:5px;margin-bottom:22px}.glizy-dropzone .dz-preview .dz-details .dz-filename,.dropzone-previews .dz-preview .dz-details .dz-filename{overflow:hidden;height:100%}.glizy-dropzone .dz-preview .dz-details img,.dropzone-previews .dz-preview .dz-details img{position:absolute;top:0;left:0;width:100px;height:100px}.glizy-dropzone .dz-preview .dz-details .dz-size,.dropzone-previews .dz-preview .dz-details .dz-size{position:absolute;bottom:-28px;left:3px;height:28px;line-height:28px}.glizy-dropzone .dz-preview.dz-error .dz-error-mark,.dropzone-previews .dz-preview.dz-error .dz-error-mark{display:block}.glizy-dropzone .dz-preview.dz-success .dz-success-mark,.dropzone-previews .dz-preview.dz-success .dz-success-mark{display:block}.glizy-dropzone .dz-preview:hover .dz-details img,.dropzone-previews .dz-preview:hover .dz-details img{display:none}.glizy-dropzone .dz-preview .dz-success-mark,.dropzone-previews .dz-preview .dz-success-mark,.glizy-dropzone .dz-preview .dz-error-mark,.dropzone-previews .dz-preview .dz-error-mark{display:none;position:absolute;width:40px;height:40px;font-size:30px;text-align:center;right:-10px;top:-10px}.glizy-dropzone .dz-preview .dz-success-mark,.dropzone-previews .dz-preview .dz-success-mark{color:#8cc657}.glizy-dropzone .dz-preview .dz-error-mark,.dropzone-previews .dz-preview .dz-error-mark{color:#ee162d}.glizy-dropzone .dz-preview .dz-progress,.dropzone-previews .dz-preview .dz-progress{position:absolute;top:100px;left:6px;right:6px;height:6px;background:#d7d7d7;display:none}.glizy-dropzone .dz-preview .dz-progress .dz-upload,.dropzone-previews .dz-preview .dz-progress .dz-upload{display:block;position:absolute;top:0;bottom:0;left:0;width:0;background-color:#8cc657}.glizy-dropzone .dz-preview.dz-processing .dz-progress,.dropzone-previews .dz-preview.dz-processing .dz-progress{display:block}.glizy-dropzone .dz-preview .dz-error-message,.dropzone-previews .dz-preview .dz-error-message{display:none;position:absolute;top:-5px;left:-20px;background:rgba(245,245,245,0.8);padding:8px 10px;color:#800;min-width:140px;max-width:500px;z-index:500}.glizy-dropzone .dz-preview:hover.dz-error .dz-error-message,.dropzone-previews .dz-preview:hover.dz-error .dz-error-message{display:block}.GFERowContainer .dropzone-previews{width:100px;position:absolute;top:-10px;right:50px}.GFERowContainer .dropzone-previews .dz-progress,.GFERowContainer .dropzone-previews .dz-success-mark{display:none}.GFERowWithPreview .span11{width:78%}.GFERowContainer .dropzone-previews .dz-preview .dz-details{width:80px;height:80px}.form-horizontal #medias .control-label{width:120px}.form-horizontal #medias .controls{margin-left:130px}.mediaPickerField{position:relative}.mediaPickerSelector{position:relative;width:150px;height:150px;display:inline-block;background-color:#f0f0f0;border:1px solid #fff;cursor:pointer;display:table-cell;text-align:center;vertical-align:middle}.mediaPickerInfo{position:relative;top:0;left:20px;float:left}.mediaPickerInfo input,.mediaPickerInfo textarea{width:100%;margin:0 0 10px 0}.mediaPickerSelector.mediaPickerElement{float:left}#treeview-inner .jstree-default.jstree-focused{background:transparent}#treeview-inner .jstree-clicked{padding:0}#treeview-inner .jstree-hovered{padding:0 !important}#treeview-inner .jstree a{white-space:normal !important;height:auto;width:80%}#treeview-inner .jstree li>ins{vertical-align:top}li.glizycmsSiteTree-nodeSystem>a{font-style:italic}li.glizycmsSiteTree-nodeHide a{color:#909090}#openclose{display:none}div.formButtons{border-top:1px solid #eee;margin-top:20px;padding-top:20px}div.formButtons .btn{margin:0 4px}.thumbnail li{height:150px}.thumbnails .title{font-weight:normal;font-size:11px}div.formButtonsTop{background:#f0f0f0;margin-bottom:10px;padding:5px;text-align:right}div.formButtonsTop .btn{margin:0 4px}#filtersForm select,#filtersForm input[type="text"]{width:150px}#sidebar-inner ul li ul{display:block}div.dataTables_length label{float:left;text-align:left}div.dataTables_length select{width:75px}div.dataTables_filter label{float:right;margin:0 0 0 10px}div.dataTables_info{padding-top:8px}div.dataTables_paginate{float:right;margin:0}table.table{clear:both;margin-bottom:6px !important;max-width:none !important}table.table thead .sorting,table.table thead .sorting_asc,table.table thead .sorting_desc,table.table thead .sorting_asc_disabled,table.table thead .sorting_desc_disabled{cursor:pointer;*cursor:hand}table.table thead .sorting{background:url('images/sort_both.png') no-repeat center right}table.table thead .sorting_asc{background:url('images/sort_asc.png') no-repeat center right}table.table thead .sorting_desc{background:url('images/sort_desc.png') no-repeat center right}table.table thead .sorting_asc_disabled{background:url('images/sort_asc_disabled.png') no-repeat center right}table.table thead .sorting_desc_disabled{background:url('images/sort_desc_disabled.png') no-repeat center right}table.dataTable th:active{outline:none}div.dataTables_scrollHead table{margin-bottom:0 !important;border-bottom-left-radius:0;border-bottom-right-radius:0}div.dataTables_scrollHead table thead tr:last-child th:first-child,div.dataTables_scrollHead table thead tr:last-child td:first-child{border-bottom-left-radius:0 !important;border-bottom-right-radius:0 !important}div.dataTables_scrollBody table{border-top:none;margin-bottom:0 !important}div.dataTables_scrollBody tbody tr:first-child th,div.dataTables_scrollBody tbody tr:first-child td{border-top:none}div.dataTables_scrollFoot table{border-top:none}.table tbody tr.active td,.table tbody tr.active th{background-color:#08c;color:#fff}.table tbody tr.active:hover td,.table tbody tr.active:hover th{background-color:#0075b0 !important}.table-striped tbody tr.active:nth-child(odd) td,.table-striped tbody tr.active:nth-child(odd) th{background-color:#017ebc}table.DTTT_selectable tbody tr{cursor:pointer;*cursor:hand}div.DTTT .btn{color:#333 !important;font-size:12px}div.DTTT .btn:hover{text-decoration:none !important}ul.DTTT_dropdown.dropdown-menu a{color:#333 !important}ul.DTTT_dropdown.dropdown-menu li:hover a{background-color:#08c;color:#fff !important}div.DTTT_print_info.modal{height:150px;margin-top:-75px;text-align:center}div.DTTT_print_info h6{font-weight:normal;font-size:28px;line-height:28px;margin:1em}div.DTTT_print_info p{font-size:14px;line-height:20px}div.DTFC_LeftHeadWrapper table,div.DTFC_LeftFootWrapper table,table.DTFC_Cloned tr.even{background-color:#fff}div.DTFC_LeftHeadWrapper table{margin-bottom:0 !important;border-top-right-radius:0 !important;border-bottom-left-radius:0 !important;border-bottom-right-radius:0 !important}div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child,div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child{border-bottom-left-radius:0 !important;border-bottom-right-radius:0 !important}div.DTFC_LeftBodyWrapper table{border-top:none;margin-bottom:0 !important}div.DTFC_LeftBodyWrapper tbody tr:first-child th,div.DTFC_LeftBodyWrapper tbody tr:first-child td{border-top:none}div.DTFC_LeftFootWrapper table{border-top:none}caption{display:none}.required{font-weight:bold}.form-horizontal .control-label{white-space:normal;width:160px;margin:0 10px 0 0}.mapPicker img{max-width:none}.ui-front{position:fixed !important;z-index:110 !important}table.storageBrowser{width:100%}table.storageBrowser .icon{width:18px}table.storageBrowser td.folder{background:url('../icons/folder.png') no-repeat 4px 4px}table.storageBrowser td.image{background:url('../icons/image.png') no-repeat 4px 4px}table.storageBrowser td.audio{background:url('../icons/audio.png') no-repeat 4px 4px}table.storageBrowser td.other{background:url('../icons/other.png') no-repeat 4px 4px}table.storageBrowser td.pdf{background:url('../icons/pdf.png') no-repeat 4px 4px}table.storageBrowser .filename{font-weight:bold}table.storageBrowser .size{text-align:right;width:100px}table.storageBrowser .date{text-align:right;width:150px}table.storageBrowser tbody tr{cursor:pointer}table#dataGrid.storageBrowser tbody tr.ruled td{background-color:#fff}div.addMedia input.mediaFilePicker{margin-left:10px}.VS-search .ui-menu{width:auto}.VS-search{margin-bottom:20px}#filters_visualsearch{margin:0 0 0 0 !important}#filters_visualsearch .VS-search-box-wrapper{width:80%;float:left;margin-right:7px}#filters_visualsearch .VS-search-box{box-shadow:none !important;-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important;border:1px solid #ccc !important}#filters_visualsearch .VS-search input{border:0;background-color:transparent;box-shadow:0 0 0 0}.glizyVisualSearch{margin-left:0 !important}.glizyVisualSearch .VS-search-box{box-shadow:none !important;-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important;border:1px solid #ccc !important}.glizyVisualSearch .VS-search input{border:0;background-color:transparent;box-shadow:0 0 0 0}.jstree-default a ins.jstree-icon.home{background:transparent url(../images/treeIcons.png) no-repeat 0 0}.jstree-default a ins.jstree-icon.page{background:transparent url(../images/treeIcons.png) no-repeat -19px 0}.jstree-default a ins.jstree-icon.alias{background:transparent url(../images/treeIcons.png) no-repeat -36px 0}.jstree-default a ins.jstree-icon.folder{background:transparent url(../images/treeIcons.png) no-repeat -56px 0}.jstree-default a ins.jstree-icon.system{background:transparent url(../images/treeIcons.png) no-repeat -73px 0}.jstree-default a ins.jstree-icon.home.lock{background:transparent url(../images/treeIcons.png) no-repeat 0 -18px}.jstree-default a ins.jstree-icon.page.lock{background:transparent url(../images/treeIcons.png) no-repeat -19px -18px}.jstree-default a ins.jstree-icon.alias.lock{background:transparent url(../images/treeIcons.png) no-repeat -36px -18px}.jstree-default a ins.jstree-icon.folder.lock{background:transparent url(../images/treeIcons.png) no-repeat -56px -18px}.jstree-default a ins.jstree-icon.system.lock{background:transparent url(../images/treeIcons.png) no-repeat -73px -18px}.jstree-default a ins.jstree-icon.hide{opacity:.5}.jstree-default-context li ins{padding:3px 0 0 5px;color:#505050}.thesaurus{width:610px;border:1px solid #ccc;float:left;padding:5px;margin-bottom:3px;min-height:20px;margin-left:30px}.thesaurusItem{display:inline;margin-right:1em;padding:2px;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;border:1px solid #cad8f3;background:#dee7f8;position:relative;padding-right:20px;margin-bottom:2px;float:left}.thesaurusItem a{position:absolute;right:4px;top:6px;display:block;width:7px;height:7px;background:url(../images/thesaurusDelete.gif);cursor:pointer}.thesaurusAdd{width:16px;height:16px;display:inline-block;background:url(../images/icon_addThesaurus.gif);cursor:pointer}div.addMedia input.mediaFilePicker{margin-left:10px}.pageTypeSelect li{border:1px solid #d5d5d5;box-shadow:0 1px 0 0 #fff inset,0 1px 0 rgba(255,255,255,0.4);display:inline-block;line-height:18px;margin:0 10px 10px;padding:0 10px;width:19.5%;position:relative;-moz-transition:all .2s ease-in-out;cursor:pointer}.pageTypeSelect li:hover,.pageTypeSelect li.button-selected{border:1px solid #c04416;box-shadow:0 1px 0 0 #fff inset,0 0 6px rgba(0,0,0,0.1);background-color:#fff}.pageTypeSelect li a{display:inline-block;text-align:center;color:#333;min-height:26px;width:100%}.pageTypeSelect li a:hover{text-decoration:none}.pageTypeSelect li a.button-generic{background:url(../img/article.png) center 10px no-repeat;padding-top:65px}.pageTypeSelect li a.button-article{background:url(../img/article.png) center 10px no-repeat;padding-top:65px}.pageTypeSelect li a.button-attach{background:url(../img/attach.png) center 10px no-repeat;padding-top:65px}.pageTypeSelect li a.button-exercise{background:url(../img/exercise.png) center 10px no-repeat;padding-top:65px}.hotspots-container #selectionMarquee{z-index:1000;position:absolute;border:1px dashed #cc0001;display:none}.hotspots-container .selected-box{z-index:999;position:absolute;background-color:rgba(255,255,1,0.3)}.hotspots-container .hotspot-circle{-webkit-border-radius:50%;border-radius:50%}.hotspots-container .hotspot{position:relative;margin:4px;border:1px solid #999;clear:both;height:182px}.hotspots-container .selected{border:2px solid #ff0}.hotspots-container .hotspots-container{clear:both;border:1px solid #999;padding:2px;margin:40px}.hotspots-container .btn-container{clear:both;border:1px solid #999;padding:4px;margin:2px}.hotspots-container .hotspots-list{position:relative;float:left;border:1px solid #999;width:310px;margin:2px;overflow:auto}.hotspots-container .hotspots-image{float:left;border:1px solid #999;padding:4px;margin:2px;position:relative}.hotspots-container .list-label{float:left;width:50px}.hotspots-container .list-container{padding:4px}.hotspots-container .print-check{float:left;margin-left:10px}.hotspots-container .list-select{float:left;margin-left:10px;width:210px;height:auto;padding:0}.hotspots-container .list-description{clear:both;margin:4px;width:270px}.hotspots-container .list-url{float:left;margin-left:10px;height:auto;width:200px}.hotspots-container .delete{position:absolute;top:6px;right:5px}._drsElement{position:absolute;border:1px solid #333}.drsElement{position:absolute}._drsMoveHandle{height:20px;background-color:#ccc;border-bottom:1px solid #666;cursor:move}.drsMoveHandle{cursor:move}.dragresize{position:absolute;width:5px;height:5px;font-size:1px;background:#ff0;border:1px solid #333}.dragresize-tl{top:-8px;left:-8px;cursor:nw-resize}.dragresize-tm{top:-8px;left:50%;margin-left:-4px;cursor:n-resize}.dragresize-tr{top:-8px;right:-8px;cursor:ne-resize}.dragresize-ml{top:50%;margin-top:-4px;left:-8px;cursor:w-resize}.dragresize-mr{top:50%;margin-top:-4px;right:-8px;cursor:e-resize}.dragresize-bl{bottom:-8px;left:-8px;cursor:sw-resize}.dragresize-bm{bottom:-8px;left:50%;margin-left:-4px;cursor:s-resize}.dragresize-br{bottom:-8px;right:-8px;cursor:se-resize}#diff .Differences{width:100%;border-collapse:collapse;border-spacing:0;empty-cells:show}#diff .Differences thead th{text-align:left;border-bottom:1px solid #000;background:#aaa;color:#000;padding:4px}#diff .Differences tbody th{text-align:right;background:#ccc;width:4em;padding:1px 2px;border-right:1px solid #000;vertical-align:top;font-size:13px}#diff .Differences td{padding:1px 2px;font-family:Consolas,monospace;font-size:13px}#diff .DifferencesSideBySide .ChangeInsert td.Left{background:#dfd}#diff .DifferencesSideBySide .ChangeInsert td.Right{background:#cfc}#diff .DifferencesSideBySide .ChangeDelete td.Left{background:#f88}#diff .DifferencesSideBySide .ChangeDelete td.Right{background:#faa}#diff .DifferencesSideBySide .ChangeReplace .Left{background:#fe9}#diff .DifferencesSideBySide .ChangeReplace .Right{background:#fd8}#diff .Differences ins,#diff .Differences del{text-decoration:none}#diff .DifferencesSideBySide .ChangeReplace ins,#diff .DifferencesSideBySide .ChangeReplace del{background:#fc0}#diff .Differences .Skipped{background:#f7f7f7}#diff .DifferencesInline .ChangeReplace .Left,#diff .DifferencesInline .ChangeDelete .Left{background:#fdd}#diff .DifferencesInline .ChangeReplace .Right,#diff .DifferencesInline .ChangeInsert .Right{background:#dfd}#diff .DifferencesInline .ChangeReplace ins{background:#9e9}#diff .DifferencesInline .ChangeReplace del{background:#e99}#diff pre{width:100%;overflow:auto}ul.mediaArchive.nav-pills{margin-bottom:0}.modulesBuilderStep1Panel{border-bottom:1px solid #ccc;margin-bottom:1em;overflow:hidden}.modulesBuilderStep1Panel p{float:left;width:80%}.modulesBuilderStep1Panel input{float:right;margin-top:1.5em}.modulesBuilderTable{margin-top:2em}.modulesBuilderTable td.dragHandler{padding-left:20px;background:url(../images/common/dragHandler.gif) no-repeat}.modulesBuilderTable td.newTableFoot{text-align:center;height:50px}.modulesBuilderTable #newTableBtnAdd{padding:5px;background:#328be5;color:#fff;width:100px;text-decoration:none}.modulesBuilderTable .delete{cursor:pointer}#loading{width:100%;height:80px;margin-top:120px;background:url(../images/ajax-loader.gif) no-repeat top center}.splitDiv{width:100%;overflow:auto;position:absolute;padding-bottom:0}#searchForm{padding-top:10px}body>#outer.splitDiv{min-height:0}.resizeDiv{position:fixed;background-color:#fff}#handle{height:22px;width:100%;background:url("../images/resize.png") no-repeat scroll center center #eee;background-size:37px 8px;z-index:9}#handle:hover{cursor:n-resize}.contentSearch{margin-left:15px !important}#searchText{width:60%}#searchSubmit{margin-left:5px;cursor:pointer}#searchResultFrame{border:2px solid #ccc;border-left:0;border-right:0}#input-menu .btn-group a.action-link.btn{padding-right:5px !important}#input-menu .btn-group .dropdown-menu li a{color:#333;text-indent:0;font-size:13px}#input-menu{background-color:#fff}#searchResultContextmenu{position:absolute !important}#loadingFrame{background:url("../images/ajax-loader.gif") no-repeat scroll center center rgba(0,0,0,0);height:80px;width:100%}.js-closeDiv{cursor:pointer;padding-right:5px}.europeana-group{margin-left:200px !important;margin-top:10px}.europeana-group label,input,select{font-size:13px !important}.europeana-group input[type="text"]{width:80% !important}.europeana-group select{width:84% !important}.europeana-group input.btn{margin-top:15px !important;margin-right:5px !important}.europeana-group ul{margin-left:0 !important;margin-top:20px}.europeana-group.firstDiv{margin-top:-20px}.europeana-group div.js-imageRemove{cursor:pointer !important}.europeana-group div.js-imageRemove i{margin-bottom:2px}.europeana-group div.imgPreview{height:210px;width:111px}.europeana-group div.imgPreview img{height:130px;width:111px}.europeana-group div.maxResDiv input{width:106px !important}.europeana-group input.titleInput{width:90% !important}.europeana-group.div-btn{width:79%}.sortable{list-style-type:none;margin:auto;padding:auto;float:left;background:#eee;padding:5px;width:100%;cursor:pointer;min-height:175px}.sortable li{margin:0 3px 3px 3px;padding:.4em;text-align:center;font-size:.9em;height:14px}.sortableNote{padding-top:5px;clear:both;font-style:italic;font-size:15px;color:#888}input.delete-media{float:left;margin:5px} + +svg { + overflow: hidden; + margin: auto auto; +} + +/* Stile testo delle entità */ +g.nodes tspan { + font-family: Helvetica, sans-serif; + font-size: 14px; +} +/* Stile testo delle entità in HTML */ +g.nodes div { + white-space: nowrap; + padding: 4px; + font-family: Helvetica, sans-serif; + font-size: 14px; +} + +/* Stile testo delle entità principali */ +g.nodes tspan.main-node { + fill: white; +} +/* Stile testo delle entità principali in HTML */ +div.main-node { + padding: 2px 7px 2px 7px; + font-family: Helvetica, sans-serif; + font-size: 14px; +} + +/* Stile testo delle relazioni */ +g.edgeLabels tspan { + +} + +/* Stile riquadro delle entità */ +.node rect { + stroke: #cfced3; + stroke-width: 2px; + fill: none; +} + +/* Stile riquadro delle entità principali */ +.node rect.main-node { + fill: lightgray; +} + +/* Stile delle frecce */ +.edgePath path { + stroke: black; + stroke-width: 1.5px; + fill: none; +} \ No newline at end of file diff --git a/src/admin/application/templates/font/FontAwesome.otf b/src/admin/application/templates/font/FontAwesome.otf new file mode 100755 index 0000000000000000000000000000000000000000..64049bf2e79940063b59be135872baadc37df6f6 GIT binary patch literal 48748 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 literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/font/fontawesome-webfont.eot b/src/admin/application/templates/font/fontawesome-webfont.eot new file mode 100755 index 0000000000000000000000000000000000000000..7d81019e4f174caaf5ccd785fc361f6bff196b53 GIT binary patch literal 25395 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 literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/font/fontawesome-webfont.svg b/src/admin/application/templates/font/fontawesome-webfont.svg new file mode 100755 index 0000000..ba0afe5 --- /dev/null +++ b/src/admin/application/templates/font/fontawesome-webfont.svg @@ -0,0 +1,284 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata></metadata> +<defs> +<font id="fontawesomeregular" horiz-adv-x="1536" > +<font-face units-per-em="1792" ascent="1536" descent="-256" /> +<missing-glyph horiz-adv-x="448" /> +<glyph unicode=" " horiz-adv-x="448" /> +<glyph unicode="&#x09;" horiz-adv-x="448" /> +<glyph unicode="&#xa0;" horiz-adv-x="448" /> +<glyph unicode="&#xa8;" horiz-adv-x="1792" /> +<glyph unicode="&#xa9;" horiz-adv-x="1792" /> +<glyph unicode="&#xae;" horiz-adv-x="1792" /> +<glyph unicode="&#xb4;" horiz-adv-x="1792" /> +<glyph unicode="&#xc6;" horiz-adv-x="1792" /> +<glyph unicode="&#x2000;" horiz-adv-x="768" /> +<glyph unicode="&#x2001;" /> +<glyph unicode="&#x2002;" horiz-adv-x="768" /> +<glyph unicode="&#x2003;" /> +<glyph unicode="&#x2004;" horiz-adv-x="512" /> +<glyph unicode="&#x2005;" horiz-adv-x="384" /> +<glyph unicode="&#x2006;" horiz-adv-x="256" /> +<glyph unicode="&#x2007;" horiz-adv-x="256" /> +<glyph unicode="&#x2008;" horiz-adv-x="192" /> +<glyph unicode="&#x2009;" horiz-adv-x="307" /> +<glyph unicode="&#x200a;" horiz-adv-x="85" /> +<glyph unicode="&#x202f;" horiz-adv-x="307" /> +<glyph unicode="&#x205f;" horiz-adv-x="384" /> +<glyph unicode="&#x2122;" horiz-adv-x="1792" /> +<glyph unicode="&#x221e;" horiz-adv-x="1792" /> +<glyph unicode="&#x2260;" horiz-adv-x="1792" /> +<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" /> +<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" /> +<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" /> +<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" /> +<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" /> +<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" /> +<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" /> +<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" /> +<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" /> +<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " /> +<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" /> +<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" /> +<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" /> +<glyph unicode="&#xf016;" horiz-adv-x="1280" d="M128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280zM768 896h299l-299 299v-299zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544q40 0 88 -20t76 -48l408 -408q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf017;" d="M1088 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-384q-13 0 -22.5 9.5t-9.5 22.5v448q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-352h288q13 0 22.5 -9.5t9.5 -22.5zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5 t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5 t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" /> +<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1339 729q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39zM1632 512q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-1600q-14 0 -23 9t-9 23v576q0 14 9 23 t23 9h192q14 0 23 -9t9 -23v-352h1152v352q0 14 9 23t23 9h192z" /> +<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-9 -9 -23 -9t-23 9l-320 320q-9 9 -9 23q0 13 9.5 22.5t22.5 9.5h192v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352h192q14 0 23 -9t9 -23zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5 t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5 t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01b;" d="M1120 672q0 -13 -9.5 -22.5t-22.5 -9.5h-192v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q9 9 23 9t23 -9l320 -320q9 -9 9 -23zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" /> +<glyph unicode="&#xf01d;" d="M1152 640q0 -37 -33 -56l-512 -288q-14 -8 -31 -8t-32 9q-32 18 -32 55v576q0 37 32 55q31 20 63 1l512 -288q33 -19 33 -56zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5 t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q169 0 304 99.5t185 261.5q7 23 30 23h199 q16 0 25 -12q10 -13 7 -27q-39 -175 -147.5 -312t-266 -213t-336.5 -76q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" /> +<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" /> +<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M704 512q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5q0 -37 19 -67t51 -47l-69 -229q-5 -15 5 -28t26 -13h192q16 0 26 13t5 28l-69 229q32 17 51 47t19 67zM320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68 t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" /> +<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" /> +<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" /> +<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" /> +<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M672 1408v-1536h-64v1536h64zM1408 1408v-1536h-64v1536h64zM1568 1408v-1536h-64v1536h64zM576 1408v-1536h-64v1536h64zM1280 1408v-1536h-256v1536h256zM896 1408v-1536h-128v1536h128zM448 1408v-1536h-128v1536h128zM1792 1408v-1536h-128v1536h128zM256 1408v-1536 h-256v1536h256z" /> +<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" /> +<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" /> +<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" /> +<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" /> +<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" /> +<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" /> +<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q73 -1 153.5 -2t119 -1.5t52.5 -0.5l29 2q-32 95 -92 241q-53 132 -92 211zM21 -128h-21l2 79q22 7 80 18q89 16 110 31q20 16 48 68l237 616l280 724h75h53l11 -21l205 -480q103 -242 124 -297q39 -102 96 -235q26 -58 65 -164q24 -67 65 -149 q22 -49 35 -57q22 -19 69 -23q47 -6 103 -27q6 -39 6 -57q0 -14 -1 -26q-80 0 -192 8q-93 8 -189 8q-79 0 -135 -2l-200 -11l-58 -2q0 45 4 78l131 28q56 13 68 23q12 12 12 27t-6 32l-47 114l-92 228l-450 2q-29 -65 -104 -274q-23 -64 -23 -84q0 -31 17 -43 q26 -21 103 -32q3 0 13.5 -2t30 -5t40.5 -6q1 -28 1 -58q0 -17 -2 -27q-66 0 -349 20l-48 -8q-81 -14 -167 -14z" /> +<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q76 -32 140 -32q131 0 216 41t122 113q38 70 38 181q0 114 -41 180q-58 94 -141 126q-80 32 -247 32q-74 0 -101 -10v-144l-1 -173l3 -270q0 -15 12 -44zM541 761q43 -7 109 -7q175 0 264 65t89 224q0 112 -85 187q-84 75 -255 75q-52 0 -130 -13q0 -44 2 -77 q7 -122 6 -279l-1 -98q0 -43 1 -77zM0 -128l2 94q45 9 68 12q77 12 123 31q17 27 21 51q9 66 9 194l-2 497q-5 256 -9 404q-1 87 -11 109q-1 4 -12 12q-18 12 -69 15q-30 2 -114 13l-4 83l260 6l380 13l45 1q5 0 14 0.5t14 0.5q1 0 21.5 -0.5t40.5 -0.5h74q88 0 191 -27 q43 -13 96 -39q57 -29 102 -76q44 -47 65 -104t21 -122q0 -70 -32 -128t-95 -105q-26 -20 -150 -77q177 -41 267 -146q92 -106 92 -236q0 -76 -29 -161q-21 -62 -71 -117q-66 -72 -140 -108q-73 -36 -203 -60q-82 -15 -198 -11l-197 4q-84 2 -298 -11q-33 -3 -272 -11z" /> +<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q4 1 77 20q76 19 116 39q29 37 41 101l27 139l56 268l12 64q8 44 17 84.5t16 67t12.5 46.5t9 30.5t3.5 11.5l29 157l16 63l22 135l8 50v38q-41 22 -144 28q-28 2 -38 4l19 103l317 -14q39 -2 73 -2q66 0 214 9q33 2 68 4.5t36 2.5q-2 -19 -6 -38 q-7 -29 -13 -51q-55 -19 -109 -31q-64 -16 -101 -31q-12 -31 -24 -88q-9 -44 -13 -82q-44 -199 -66 -306l-61 -311l-38 -158l-43 -235l-12 -45q-2 -7 1 -27q64 -15 119 -21q36 -5 66 -10q-1 -29 -7 -58q-7 -31 -9 -41q-18 0 -23 -1q-24 -2 -42 -2q-9 0 -28 3q-19 4 -145 17 l-198 2q-41 1 -174 -11q-74 -7 -98 -9z" /> +<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l215 -1h293l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -42.5 2t-103.5 -1t-111 -1 q-34 0 -67 -5q-10 -97 -8 -136l1 -152v-332l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-88 0 -233 -14q-48 -4 -70 -4q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q8 192 6 433l-5 428q-1 62 -0.5 118.5t0.5 102.5t-2 57t-6 15q-6 5 -14 6q-38 6 -148 6q-43 0 -100 -13.5t-73 -24.5q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1744 128q33 0 42 -18.5t-11 -44.5 l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80z" /> +<glyph unicode="&#xf035;" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l446 -1h318l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -58.5 2t-138.5 -1t-128 -1 q-94 0 -127 -5q-10 -97 -8 -136l1 -152v52l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-82 0 -233 -13q-45 -5 -70 -5q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q6 137 6 433l-5 44q0 265 -2 278q-2 11 -6 15q-6 5 -14 6q-38 6 -148 6q-50 0 -168.5 -14t-132.5 -24q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1505 113q26 -20 26 -49t-26 -49l-162 -126 q-26 -20 -44.5 -11t-18.5 42v80h-1024v-80q0 -33 -18.5 -42t-44.5 11l-162 126q-26 20 -26 49t26 49l162 126q26 20 44.5 11t18.5 -42v-80h1024v80q0 33 18.5 42t44.5 -11z" /> +<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03d;" horiz-adv-x="1920" d="M1900 1278q20 -8 20 -30v-1216q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-585 586v-307q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-307l585 586q16 15 35 7z" /> +<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" /> +<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" /> +<glyph unicode="&#xf042;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM256 640q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5v1024q-104 0 -198.5 -40.5 t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5z" /> +<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" /> +<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" /> +<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" /> +<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" /> +<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" /> +<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" /> +<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" /> +<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" /> +<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" /> +<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" /> +<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" /> +<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" /> +<glyph unicode="&#xf053;" horiz-adv-x="1152" d="M742 -37l-652 651q-37 37 -37 90.5t37 90.5l652 651q37 37 90.5 37t90.5 -37l75 -75q37 -37 37 -90.5t-37 -90.5l-486 -486l486 -485q37 -38 37 -91t-37 -90l-75 -75q-37 -37 -90.5 -37t-90.5 37z" /> +<glyph unicode="&#xf054;" horiz-adv-x="1152" d="M1099 704q0 -52 -37 -91l-652 -651q-37 -37 -90 -37t-90 37l-76 75q-37 39 -37 91q0 53 37 90l486 486l-486 485q-37 39 -37 91q0 53 37 90l76 75q36 38 90 38t90 -38l652 -651q37 -37 37 -90z" /> +<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" /> +<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf059;" d="M896 160v192q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-192q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1152 832q0 97 -58.5 172t-144.5 111.5t-181 36.5t-181 -36.5t-144.5 -111.5t-58.5 -172v-11v-13t1 -11.5t3 -11.5t5.5 -8t9 -7 t13.5 -2h192q14 0 23 9t9 23q0 12 11 27q19 31 50.5 50t66.5 19q39 0 83 -21.5t44 -57.5q0 -33 -26.5 -58t-63.5 -44t-74.5 -41.5t-64 -63.5t-26.5 -98v-11v-13t1 -11.5t3 -11.5t5.5 -8t9 -7t13.5 -2h192q17 0 24 10.5t8 24.5t13.5 33t37.5 32q60 33 70 39q62 44 98.5 108 t36.5 137zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05a;" d="M1024 160v64q0 14 -9 23t-23 9h-96v480q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h96v-384h-96q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 928v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf05c;" d="M1125 448q0 -27 -18 -45l-102 -102q-18 -18 -45 -18t-45 18l-147 147l-147 -147q-18 -18 -45 -18t-45 18l-102 102q-18 18 -18 45t18 45l147 147l-147 147q-18 18 -18 45t18 45l102 102q18 18 45 18t45 -18l147 -147l147 147q18 18 45 18t45 -18l102 -102q18 -18 18 -45 t-18 -45l-147 -147l147 -147q18 -18 18 -45zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5 t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05d;" d="M1189 768q0 -27 -18 -45l-320 -320l-102 -102q-18 -18 -45 -18t-45 18l-102 102l-192 192q-18 18 -18 45t18 45l102 102q18 18 45 18t45 -18l147 -147l275 275q18 18 45 18t45 -18l102 -102q18 -18 18 -45zM1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05e;" d="M1280 640q0 139 -71 260l-701 -701q121 -71 260 -71q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM327 380l701 701q-121 71 -260 71q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5q0 -139 71 -260zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" /> +<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" /> +<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" /> +<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" /> +<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" /> +<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" /> +<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" /> +<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" /> +<glyph unicode="&#xf06b;" d="M928 180v716h-320v-716q0 -25 18.5 -38.5t45.5 -13.5h192q27 0 45.5 13.5t18.5 38.5zM472 1024h195l-126 161q-24 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-45 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -10 -22t-27 -10.5t-32 -2.5t-34.5 1.5t-24.5 1.5v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416q-5 0 -24.5 -1.5t-34.5 -1.5t-32 2.5t-27 10.5t-10 22v320q0 13 9.5 22.5t22.5 9.5h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5 q108 0 168 -77l128 -165l128 165q60 77 168 77q93 0 158.5 -65.5t65.5 -158.5t-65.5 -158.5t-158.5 -65.5h440q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" /> +<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" /> +<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" /> +<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " /> +<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" /> +<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1397 1324q0 -87 -149 -236l-240 -240l143 -746l1 -6q0 -14 -9 -23l-64 -64q-9 -9 -23 -9q-21 0 -29 18l-274 575l-245 -245q68 -238 68 -252t-9 -23l-64 -64q-9 -9 -23 -9q-18 0 -28 16l-155 280l-280 155q-17 9 -17 28q0 14 9 23l64 65q9 9 23 9t252 -68l245 245 l-575 274q-18 8 -18 29q0 14 9 23l64 64q9 9 23 9q4 0 6 -1l746 -143l240 240q149 149 236 149q32 0 52.5 -20.5t20.5 -52.5z" /> +<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" /> +<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" /> +<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf077;" horiz-adv-x="1664" d="M1611 320q0 -53 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-486 485l-486 -485q-36 -38 -90 -38t-90 38l-75 75q-38 36 -38 90q0 53 38 91l651 651q37 37 90 37q52 0 91 -37l650 -651q38 -38 38 -91z" /> +<glyph unicode="&#xf078;" horiz-adv-x="1664" d="M1611 832q0 -53 -37 -90l-651 -651q-38 -38 -91 -38q-54 0 -90 38l-651 651q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l486 -486l486 486q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" /> +<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " /> +<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf080;" horiz-adv-x="1920" d="M512 512v-384h-256v384h256zM896 1024v-896h-256v896h256zM1280 768v-640h-256v640h256zM1664 1152v-1024h-256v1024h256zM1792 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5z M1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf081;" d="M1280 958q0 13 -9.5 22.5t-22.5 9.5q-5 0 -15 -4q20 34 20 55q0 13 -9.5 22.5t-22.5 9.5q-7 0 -17 -5q-60 -34 -97 -43q-65 63 -154 63q-98 0 -164.5 -72.5t-64.5 -169.5v-12q-107 14 -187.5 64t-156.5 139q-10 12 -28 12q-26 0 -41 -50.5t-15 -86.5q0 -62 29 -117 q-13 -2 -21.5 -11.5t-8.5 -22.5q0 -112 81 -185q-12 -8 -12 -25q0 -6 1 -9q15 -51 50.5 -91.5t84.5 -60.5q-77 -43 -165 -43q-8 0 -24 1.5t-23 1.5q-13 0 -22.5 -9.5t-9.5 -22.5q0 -17 14 -26q63 -47 150 -73.5t170 -26.5q130 0 248 58q166 79 256 232.5t88 339.5v12 q27 22 62.5 63t35.5 61zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf082;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-350q-2 0 -2 1v671h177q31 0 32 23l12 164q2 15 -8 25q-10 12 -24 12h-189v72q0 44 11.5 57t54.5 13q57 0 117 -13q13 -3 26 5q11 8 13 22l23 166q2 12 -5.5 22.5t-19.5 13.5 q-93 26 -197 26q-311 0 -311 -299v-85h-95q-13 0 -23 -10.5t-10 -24.5v-172q0 -8 5.5 -12t10 -4.5t17.5 -0.5h95v-671l10 -1h-330q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" /> +<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" /> +<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" /> +<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" /> +<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" /> +<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" /> +<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" /> +<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" /> +<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" /> +<glyph unicode="&#xf08c;" d="M512 160v640q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-640q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM503 1028q0 51 -36 87.5t-88 36.5q-51 0 -87 -36.5t-36 -87.5t36 -87.5t87 -36.5q52 0 88 36.5t36 87.5zM1280 160v435 q0 127 -73.5 192.5t-202.5 65.5q-90 0 -158 -45q-12 -8 -14 -12q0 36 -35 36h-176q-14 0 -29.5 -7.5t-15.5 -20.5v-644q0 -13 15.5 -22.5t29.5 -9.5h182q12 0 20.5 9.5t8.5 22.5v349q0 140 114 140q49 0 63.5 -22.5t14.5 -73.5v-393q0 -13 12 -22.5t26 -9.5h186 q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" /> +<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf092;" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -26t19 -63zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -52 41 -77v-3q-113 -37 -113 -139q0 -60 36 -98t84 -51t107 -13q224 0 224 187q0 48 -25.5 78t-62.5 42.5t-74 21.5t-62.5 23.5t-25.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q30 7 49 13zM771 350h137q-2 20 -2 90v372q0 59 2 76h-137q3 -26 3 -79v-377 q0 -55 -3 -82zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q4 0 11.5 -0.5t11.5 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1664 480v-576q0 -13 -9.5 -22.5t-22.5 -9.5h-1600q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352h1152v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1344 832q0 -26 -19 -45t-45 -19h-256v-448 q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" /> +<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" /> +<glyph unicode="&#xf096;" horiz-adv-x="1664" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" /> +<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf099;" horiz-adv-x="1920" d="M1875 1202q0 -10 -5 -18q-64 -104 -179 -190v-33q4 -227 -100 -457q-134 -297 -397.5 -464.5t-591.5 -167.5q-265 0 -500 122q-64 33 -87 50q-15 12 -15 27q0 13 9.5 22.5t22.5 9.5q14 0 44 -2.5t45 -2.5q204 0 375 106q-103 24 -181 96t-111 173q-2 8 -2 11q0 12 9 21.5 t22 9.5q5 0 14 -2t12 -2q-89 55 -142 147t-53 196q0 15 11.5 25.5t27.5 10.5q10 0 35 -11.5t30 -13.5q-92 110 -92 256q0 51 14.5 108t40.5 95q10 16 25 16q16 0 27 -12q76 -84 110 -115q123 -111 276 -177.5t317 -80.5q-4 21 -4 49q0 167 118.5 285.5t285.5 118.5 q163 0 282 -114q95 20 209 82q8 5 16 5q13 0 22.5 -9.5t9.5 -22.5q0 -24 -28 -73t-51 -76q7 2 30 10.5t43 16t24 7.5q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf09a;" horiz-adv-x="768" d="M560 1125q-49 0 -62 -15.5t-13 -66.5v-88h217q16 0 27 -12q11 -13 10 -29l-14 -200q-2 -15 -12.5 -25.5t-25.5 -10.5h-202v-768q0 -16 -11 -27t-26 -11h-250q-16 0 -27 11t-11 27v768h-122q-16 0 -27 11.5t-11 27.5v200q0 16 11 27t27 11h122v103q0 177 88 263.5 t267 86.5q120 0 225 -30q14 -4 22 -16t6 -26l-27 -195q-2 -16 -16 -26q-14 -9 -30 -6q-76 16 -135 16z" /> +<glyph unicode="&#xf09b;" d="M1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5q0 -209 124.5 -378.5t323.5 -231.5v169q-54 -7 -69 -7q-110 0 -153 100q-15 38 -36 63q-5 6 -21 19t-28.5 24t-12.5 16q0 12 28 12q29 0 51.5 -14.5t38 -35 t31.5 -41.5t40.5 -35.5t56.5 -14.5q42 0 81 14q16 57 63 89q-166 16 -246 83.5t-80 224.5q0 118 73 198q-14 42 -14 84q0 58 27 109q57 0 101 -19.5t101 -60.5q76 18 169 18q80 0 153 -16q57 40 100.5 59t99.5 19q27 -51 27 -109q0 -43 -14 -83q73 -82 73 -199 q0 -157 -80 -225.5t-245 -83.5q69 -47 69 -131v-226q199 62 323.5 231.5t124.5 378.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M704 160q0 6 -15 57t-35 115.5t-20 65.5q32 16 51 47t19 67q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5q0 -36 19 -66.5t51 -47.5q0 -2 -20 -66t-35 -115t-15 -57q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1664 960v-256q0 -26 -19 -45t-45 -19 h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5z" /> +<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" /> +<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" /> +<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" /> +<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" /> +<glyph unicode="&#xf0a2;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM183 128h1298q-164 181 -246.5 411.5t-82.5 484.5q0 256 -320 256t-320 -256q0 -254 -82.5 -484.5t-246.5 -411.5zM1664 128q0 -52 -38 -90t-90 -38 h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" /> +<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" /> +<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" /> +<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67 11.5t-64 38.5t-48 44t-50 55q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" /> +<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -46 -25 -91t-52 -72t-72 -66q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33t55 33 t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580q0 -142 -77.5 -230 t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100q3 2 17 14t21.5 19 t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" /> +<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0ac;" d="M1193 993q11 7 25 22v-1q0 -2 -9.5 -10t-11.5 -12q-1 1 -4 1zM1187 992q-1 1 -2.5 3t-1.5 3q3 -2 10 -5q-6 -4 -6 -1zM728 1175q-16 2 -26 5q1 0 6.5 -1t10.5 -2t9 -2zM773 1212q7 4 13.5 2.5t7.5 -7.5q-5 3 -21 5zM765 1206l-3 2q-2 3 -5.5 5t-4.5 2q2 -1 21 -3 q-6 -4 -8 -6zM663 1290v2q1 -2 3 -5.5t3 -5.5zM558 1250q0 -2 -1 -2l-1 2h2zM933 206v-1v1zM768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1240 162 l5 5q-7 10 -29 12q1 12 -14 26.5t-27 15.5q0 4 -10.5 11t-17.5 8q-9 2 -27 -9q-7 -3 -4 -5q-3 3 -12 11t-16 11q-2 1 -7.5 1t-8.5 2q-1 1 -6 4.5t-7 4.5t-6.5 3t-7.5 1.5t-7.5 -2.5t-8.5 -6t-4.5 -15.5t-2.5 -14.5q-8 6 -0.5 20t1.5 20q-7 7 -21 0.5t-21 -15.5 q-1 -1 -9.5 -5.5t-11.5 -7.5q-4 -6 -9 -17.5t-6 -13.5q0 2 -2.5 6.5t-2.5 6.5q-12 -2 -16 3q5 -16 8 -17l-4 2q-1 -6 3 -15t4 -11q1 -5 -1.5 -13t-2.5 -11q0 -2 5 -11q4 -19 -2 -32q0 -1 -3.5 -7t-6.5 -11l-2 -5l-2 1q-1 1 -2 0q-1 -6 -9 -13t-10 -11q-15 -23 -9 -38 q3 -8 10 -10q3 -1 3 2q1 -9 -11 -27q1 -1 4 -3q-17 0 -10 -14q202 36 352 181h-3zM680 347q16 3 30.5 -16t22.5 -23q41 -20 59 -11q0 -9 14 -28q3 -4 6.5 -11.5t5.5 -10.5q5 -7 19 -16t19 -16q6 3 9 9q13 -35 24 -34q5 0 8 8q0 -1 -0.5 -3t-1.5 -3q7 15 5 26l6 4q5 4 5 5 q-6 6 -9 -3q-30 -14 -48 22q-2 3 -4.5 8t-5 12t-1.5 11.5t6 4.5q11 0 12.5 1.5t-2.5 6t-4 7.5q-1 4 -1.5 12.5t-1.5 12.5l-5 6q-5 6 -11.5 13.5t-7.5 9.5q-4 -10 -16.5 -8.5t-18.5 9.5q1 -2 -0.5 -6.5t-1.5 -6.5q-14 0 -17 1q1 6 3 21t4 22q1 5 5.5 13.5t8 15.5t4.5 14 t-4.5 10.5t-18.5 2.5q-20 -1 -29 -22q-1 -3 -3 -11.5t-5 -12.5t-9 -7q-8 -3 -27 -2t-26 5q-14 8 -24 30.5t-11 41.5q0 10 3 27.5t3 27t-6 26.5q3 2 10 10.5t11 11.5q2 2 5 2h5t4 2t3 6q-1 1 -4 3q-3 3 -4 3q4 -3 19 -1t19 2q0 1 22 0q17 -13 24 2q0 1 -2.5 10.5t-0.5 14.5 q5 -29 32 -10q3 -4 16.5 -6t18.5 -5q3 -2 7 -5.5t6 -5t6 -0.5t9 7q11 -17 13 -25q11 -43 20 -48q8 -2 12.5 -2t5 10.5t0 15.5t-1.5 13l-2 37q-16 3 -20 12.5t1.5 20t16.5 19.5q1 1 16.5 8t21.5 12q24 19 17 39q9 -2 11 9l-5 3q-4 3 -8 5.5t-5 1.5q11 7 2 18q5 3 8 11.5 t9 11.5q9 -14 22 -3q8 9 2 18q5 8 22 11.5t20 9.5q5 -1 7 0t2 4.5v7.5t1 8.5t3 7.5q4 6 16 10.5t14 5.5l19 12q4 4 0 4q18 -2 32 11q13 12 -5 23q2 7 -4 10.5t-16 5.5q3 1 12 0.5t12 1.5q15 11 -7 17q-20 5 -47 -13q-3 -2 -13 -12t-17 -11q15 18 5 22q8 -1 22.5 9t15.5 11 q4 2 10.5 2.5t8.5 1.5q71 25 92 -1q8 11 11 15t9.5 9t15.5 8q21 7 23 9l1 23q-12 -1 -18 8t-7 22l-6 -8q0 6 -3.5 7.5t-7.5 0.5t-9.5 -2t-7.5 0q-9 2 -19.5 15.5t-14.5 16.5q9 0 9 5q-2 5 -10 8q1 6 -2 8t-9 0q-2 12 -1 13q-6 1 -11 11t-8 10q-2 0 -4.5 -2t-5 -5.5l-5 -7 t-3.5 -5.5l-2 -2q-12 6 -24 -10q-9 1 -17 -2q15 6 2 13q-11 5 -21 2q12 5 10 14t-12 16q1 0 4 -1t4 -1q-1 5 -9.5 9.5t-19.5 9t-14 6.5q-7 5 -36 10.5t-36 1.5q-5 -3 -6 -6t1.5 -8.5t3.5 -8.5q6 -23 5 -27q-1 -3 -8.5 -8t-5.5 -12q1 -4 11.5 -10t12.5 -12q5 -13 -4 -25 q-4 -5 -15 -11t-14 -10q-5 -5 -3.5 -11.5t0.5 -9.5q1 1 1 2.5t1 2.5q0 -13 11 -22q8 -6 -16 -18q-20 -11 -20 -4q1 8 -7.5 16t-10.5 12t-3.5 19t-9.5 21q-6 4 -19 4t-18 -5q0 10 -49 30q-17 8 -58 4q7 1 0 17q-8 16 -21 12q-8 25 -4 35q2 5 9 14t9 15q1 3 15.5 6t16.5 8 q1 4 -2.5 6.5t-9.5 4.5q53 -6 63 18q5 9 3 14q0 -1 2 -1t2 -1q12 3 7 17q19 8 26 8q5 -1 11 -6t10 -5q17 -3 21.5 10t-9.5 23q7 -4 7 6q-1 13 -7 19q-3 2 -6.5 2.5t-6.5 0t-7 0.5q-1 0 -8 2q-1 -1 -2 -1h-8q-4 -2 -4 -5v-1q-1 -3 4 -6l5 -1l3 -2q-1 0 -2.5 -2.5t-2.5 -2.5 q0 -3 3 -5q-2 -1 -14 -7.5t-17 -10.5q-1 -1 -4 -2.5t-4 -2.5q-2 -1 -4 2t-4 9t-4 11.5t-4.5 10t-5.5 4.5q-12 0 -18 -17q3 10 -13 17.5t-25 7.5q20 15 -9 30l-1 1q-30 -4 -45 -7q-2 -6 3 -12q-1 -7 6 -9q0 -1 0.5 -1t0.5 -1q0 1 -0.5 1t-0.5 1q3 -1 10.5 -1.5t9.5 -1.5 q3 -1 4.5 -2l7.5 -5t5.5 -6t-2.5 -5q-2 -1 -9 -4t-12.5 -5.5t-6.5 -3.5q-3 -5 0 -16t-2 -15q-5 5 -10 18.5t-8 17.5q8 -9 -30 -6l-8 1q-4 0 -15 -2t-16 -1q-7 0 -29 6q7 17 5 25q5 0 7 2l-6 3q-3 -1 -25 -9q2 -3 8 -9.5t9 -11.5q-22 6 -27 -2q0 -1 -9 0q-25 1 -24 -7 q1 -4 9 -12q0 -9 -1 -9q-27 22 -30 23q-172 -83 -276 -248q1 -2 2.5 -11t3.5 -8.5t11 4.5q9 -9 3 -21q2 2 36 -21q56 -40 22 -53v5.5t1 6.5q-9 -1 -19 5q-3 -6 0.5 -20t11.5 -14q-8 0 -10.5 -17t-2.5 -38.5t-1 -25.5l2 -1q-3 -13 6 -37.5t24 -20.5q-4 -18 5 -21q-1 -4 0 -8 t4.5 -8.5t6 -7l7.5 -7.5l6 -6q28 -11 41 -29q4 -6 10.5 -24.5t15.5 -25.5q-2 -6 10 -21.5t11 -25.5q-1 0 -2.5 -0.5t-2.5 -0.5q3 -8 16.5 -16t16.5 -14q2 -3 2.5 -10.5t3 -12t8.5 -2.5q3 24 -26 68q-16 27 -18 31q-3 5 -5.5 16.5t-4.5 15.5q27 -9 26 -13q-5 -10 26 -52 q2 -3 10 -10t11 -12q3 -4 9.5 -14.5t10.5 -15.5q-1 0 -3 -2l-3 -3q4 -2 9 -5t8 -4.5t7.5 -5t7.5 -7.5q16 -18 20 -33q1 -4 0.5 -15.5t1.5 -16.5q2 -6 6 -11t11.5 -10t11.5 -7t14.5 -6.5t11.5 -5.5q2 -1 18 -11t25 -14q10 -4 16.5 -4.5t16 2.5t15.5 4z" /> +<glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" /> +<glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" /> +<glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM1792 512v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 512v-128h-256v128h256zM1792 992v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf0b2;" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z " /> +<glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75 t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5 t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" /> +<glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15 t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207 q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" /> +<glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " /> +<glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" /> +<glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148 q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108 q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6 q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" /> +<glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" /> +<glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235 z" /> +<glyph unicode="&#xf0c7;" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0c8;" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf0c9;" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5 t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23 l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" /> +<glyph unicode="&#xf0cd;" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41 q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472 q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" /> +<glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192 q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192 q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113 z" /> +<glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" /> +<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" /> +<glyph unicode="&#xf0d4;" d="M678 -57q0 -38 -10 -71h-380q-95 0 -171.5 56.5t-103.5 147.5q24 45 69 77.5t100 49.5t107 24t107 7q32 0 49 -2q6 -4 30.5 -21t33 -23t31 -23t32 -25.5t27.5 -25.5t26.5 -29.5t21 -30.5t17.5 -34.5t9.5 -36t4.5 -40.5zM385 294q-234 -7 -385 -85v433q103 -118 273 -118 q32 0 70 5q-21 -61 -21 -86q0 -67 63 -149zM558 805q0 -100 -43.5 -160.5t-140.5 -60.5q-51 0 -97 26t-78 67.5t-56 93.5t-35.5 104t-11.5 99q0 96 51.5 165t144.5 69q66 0 119 -41t84 -104t47 -130t16 -128zM1536 896v-736q0 -119 -84.5 -203.5t-203.5 -84.5h-468 q39 73 39 157q0 66 -22 122.5t-55.5 93t-72 71t-72 59.5t-55.5 54.5t-22 59.5q0 36 23 68t56 61.5t65.5 64.5t55.5 93t23 131t-26.5 145.5t-75.5 118.5q-6 6 -14 11t-12.5 7.5t-10 9.5t-10.5 17h135l135 64h-437q-138 0 -244.5 -38.5t-182.5 -133.5q0 126 81 213t207 87h960 q119 0 203.5 -84.5t84.5 -203.5v-96h-256v256h-128v-256h-256v-128h256v-256h128v256h256z" /> +<glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M876 71q0 21 -4.5 40.5t-9.5 36t-17.5 34.5t-21 30.5t-26.5 29.5t-27.5 25.5t-32 25.5t-31 23t-33 23t-30.5 21q-17 2 -50 2q-54 0 -106 -7t-108 -25t-98 -46t-69 -75t-27 -107q0 -68 35.5 -121.5t93 -84t120.5 -45.5t127 -15q59 0 112.5 12.5t100.5 39t74.5 73.5 t27.5 110zM756 933q0 60 -16.5 127.5t-47 130.5t-84 104t-119.5 41q-93 0 -144 -69t-51 -165q0 -47 11.5 -99t35.5 -104t56 -93.5t78 -67.5t97 -26q97 0 140.5 60.5t43.5 160.5zM625 1408h437l-135 -79h-135q71 -45 110 -126t39 -169q0 -74 -23 -131.5t-56 -92.5t-66 -64.5 t-56 -61t-23 -67.5q0 -26 16.5 -51t43 -48t58.5 -48t64 -55.5t58.5 -66t43 -85t16.5 -106.5q0 -160 -140 -282q-152 -131 -420 -131q-59 0 -119.5 10t-122 33.5t-108.5 58t-77 89t-30 121.5q0 61 37 135q32 64 96 110.5t145 71t155 36t150 13.5q-64 83 -64 149q0 12 2 23.5 t5 19.5t8 21.5t7 21.5q-40 -5 -70 -5q-149 0 -255.5 98t-106.5 246q0 140 95 250.5t234 141.5q94 20 187 20zM1664 1152v-128h-256v-256h-128v256h-256v128h256v256h128v-256h256z" /> +<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf0da;" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" /> +<glyph unicode="&#xf0e1;" horiz-adv-x="1379" d="M1014 961q171 0 268 -85.5t97 -254.5v-586q0 -14 -10.5 -24.5t-24.5 -10.5h-252q-14 0 -24.5 10.5t-10.5 24.5v529q0 71 -26.5 104t-95.5 33q-88 0 -123.5 -51.5t-35.5 -143.5v-471q0 -14 -10.5 -24.5t-25.5 -10.5h-246q-14 0 -24.5 10.5t-10.5 24.5v868q0 14 10.5 24.5 t24.5 10.5h239q13 0 21 -5t10.5 -18.5t3 -18t0.5 -22.5q93 87 246 87zM290 938q14 0 24.5 -10.5t10.5 -24.5v-868q0 -14 -10.5 -24.5t-24.5 -10.5h-246q-14 0 -24.5 10.5t-10.5 24.5v868q0 14 10.5 24.5t24.5 10.5h246zM167 1371q69 0 118 -49t49 -118t-49 -118t-118 -49 t-118 49t-49 118t49 118t118 49z" /> +<glyph unicode="&#xf0e2;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-179 0 -336.5 76t-266 213t-147.5 312q-3 14 7 27q9 12 25 12h199q23 0 30 -23q50 -162 185 -261.5t304 -99.5q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5 t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" /> +<glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14 q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28 q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" /> +<glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5 t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29 q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" /> +<glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5 t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" /> +<glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5 t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129 q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" /> +<glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" /> +<glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68 z" /> +<glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69 q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47 q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5 t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" /> +<glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" /> +<glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" /> +<glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" /> +<glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68 t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252 t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" /> +<glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" /> +<glyph unicode="&#xf0f3;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1664 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5 q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" /> +<glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f6;" horiz-adv-x="1280" d="M1024 352v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1024 608v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280z M768 896h299l-299 299v-299zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544q40 0 88 -20t76 -48l408 -408q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5 t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320 v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152 q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M1632 800q261 -58 287 -93l1 -3q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416 h-64v32h64h160h96q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64z" /> +<glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M640 640v384h-256v-160q0 -45 2 -76t7.5 -56.5t14.5 -40t23 -26.5t33.5 -15.5t45 -7.5t58 -2.5t72.5 0.5zM1664 192v-192h-1152v192l128 192h-97q-211 0 -313 102.5t-102 314.5v287l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" /> +<glyph unicode="&#xf0fd;" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf0fe;" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf100;" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" /> +<glyph unicode="&#xf101;" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf102;" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf103;" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf104;" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf105;" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf106;" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf107;" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf108;" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf109;" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" /> +<glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf10b;" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf10c;" d="M1280 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" /> +<glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" /> +<glyph unicode="&#xf110;" horiz-adv-x="1568" d="M496 192q0 -60 -42.5 -102t-101.5 -42q-60 0 -102 42t-42 102t42 102t102 42q59 0 101.5 -42t42.5 -102zM928 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -66 -47 -113t-113 -47t-113 47t-47 113 t47 113t113 47t113 -47t47 -113zM1360 192q0 -46 -33 -79t-79 -33t-79 33t-33 79t33 79t79 33t79 -33t33 -79zM528 1088q0 -73 -51.5 -124.5t-124.5 -51.5t-124.5 51.5t-51.5 124.5t51.5 124.5t124.5 51.5t124.5 -51.5t51.5 -124.5zM992 1280q0 -80 -56 -136t-136 -56 t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1536 640q0 -40 -28 -68t-68 -28t-68 28t-28 68t28 68t68 28t68 -28t28 -68zM1328 1088q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5z" /> +<glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" /> +<glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" /> +<glyph unicode="&#xf114;" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf115;" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z " /> +</font> +</defs></svg> \ No newline at end of file diff --git a/src/admin/application/templates/font/fontawesome-webfont.ttf b/src/admin/application/templates/font/fontawesome-webfont.ttf new file mode 100755 index 0000000000000000000000000000000000000000..d46172476a3c7caf4f44946e3c40218559f3edfa GIT binary patch literal 55096 zcmd44349#InFrccea(Fz(r6^jNOS10WlN(O$+j$y<=c{tFTfbv2!ju74s)2p;TXUi z#)LCCgai-}2u?^sII;<eStVH@7i_Xil1;*9MH1NT5?JNfB-onv`+wCl(nz);$=l!i zJzLY=Rb5?O$5&r{cS}r?B$rf>WNC2m;&m&|{p<@x<op)D=#qtt7PI-1B1z1GbnKM1 zGdd3N%cmpVg!JG!7o5F2-0)vnq;HiZ-m?AdOLrsRBT4deI9s-#f7P~~f1E8N{dGxt z(XwOf+2=~Hz899HZ~PPP=XM~&d82+Y(ql*`c3g1Tm8-vFd0&#g8IvSs)%h2lbM|ju z|A%#w^fKz@Ef<`9<!-i<e?pSJ{V9}>U3m5dTj#Gk=MAJ$KmY#ji!Qya=ebRfNYeMv z9{ZD5Y~8Z$QTM9fNzzYdqP&J5^;Y`++(-YJ&fh!rr6D@M8ea2JamR&373D}AX~z6G zqW4Il3+jKeyChXol-rdI(l?uDeyOxUq>**vf4i@`<Weaw#eNsmq+=+eNvshk(UQ^= zF_FSJVHPm%<~^1`ib_Q#MT~#16hmw3a2%2jNnenjlU|P5Vl!fA#Ty#x8U{zCQP*hQ zXz%FC(aob5j$S)@$LK?&Ul@I6^tI7njJ`K&{Lb~e;4x|dJ^y6sd1=z~(x_)NKAIn0 zH99!Dd$cfm*XYpb)1$+qKNuYu9sQm3JI}FW$9{F}++&-LopEg4u>~Wx|9Ja9{^1w@ z`|n5o{j0Hvr^XZURC&UlkSFK~c>Erp$LsNUWDoZ+kK{h)Hq3sZ1%LNHhB>4mp?{2K zg?^R)aFd4c{}2CkEo@P%ttEguQHuz){;q$3P0XYly~nzcJs1>O(j}=Y?v2adxOapN z8~NRQXtx?WvRjjmh<B8SO(fcB7&jf0w8zwfREtDFXWn>6D4;dQ8&aLQOx(*-+0I^; ziFed7?XlM4tt=l&r6OYmI<kE6*49K*SS^H`66)ec+%8I~&J_M+iC@{;7_PBcYQ$9G z9TMKrii9`d;tg%QvzKQ&!d`W9vNPAka+!{hCN12teZ%%03vrr$-s#23$yA-3cX*n* z)!5OYj+L#!VC%|raZ2;*cZ+i>Gvrt5Gd3*VZh{cBp@25%QXHN4NHO{`bhRPPa7d)M z$CpdQl#nloVF)P&<9*`}<9(*HOJseZGnX(9J^RL;#?iwUU38eKtd6ONFS?qYp5!RN zbhEHg=p0C~)2^N<anWJp=$&soYaB`nkUUn<fjp#$G*?<7NlCA!E4qufVnA3rl}x3* zfe^+z=k4KbGUh-F2Ew6moic}a^vYeiu3pyVH76(QrRl*y6=F%_j}K+?7tCaA<^}o8 zL&hJIF~3tCcKVsBIV?x=PXE2%_<=UNp{p&xSfH(|VYc>zZ{#)=HuoLL_if(Xrw;dR zj>%G@?zMfbGuzu|w(fhaE>V=6e!tSheO9l<ruv;vUUvWEYI`K<^Cctg>f`sf-aU8} z&u#8gs19?Esc!|~DM`VQwkcV(u%nKLdu2>0jj8-Vr>}UIt#P1dhB4B6{Y9%1iB%U} z-#cQwRlK|4;~OlAv(CL^!5e>RU6xNI^2=KP^2WcvReaK{`}3H)5vc(QROCl>G;c{2 zM*wJ-pTM*$>Cbh9{VK*JV%&Ec3kLi_W1cY&6B^{F86T_eW`BCq-{XIi{i$2NDikpu zG90=ySnK%hZymKk&Bgx6w$ucZ)@AIK=4NBoGApeSf*bSQR)StDOWHB{a#Ag~<K)dy zE@mCZhQo)A4Xk4s+sm$EuZVUvpS)Q-z?ys6wZ;v-#!rkhUwK8gm7Ce|0j;Dq0<tmo z^->y8Rf3StUX{kbgBDtyDtWY6%9D$!g?p|VJ9yPSdN7t-ymhX%Z|zMt-?X;RI(O^h zTr8*?!*3ejeDh7#d*hV{4qTbty64=p7BsbHTk+Sl;H-1^Y?c4hy#FS)R$5a!z1NL5 z&yeOxr$}c>7fIJicS;XSUz8*@+nH)*4O%S=gyt}S^@pUHw=*T6zO)S3l=8==KcxJJ zy>IGbVue&hV78MS6e$%cN`(4k9LJC<7gQ^rG;lpp>ci^9GJIbwBn=BGU#>639yrlu zF~afURK%d8GEwB{#HCzW#F)rGafL4&5${&TA{HBwz>($oBy27Af-<_PCWMK-p`8A( z`?569X-J&|1D#wPC$8nf$?kB8(C9!Xqa*)*MPjTnG3kyZ7OTKN<+e}2q6AbRT0NJU zNYgtdJ@x+ob$aUixYXTb3^#RmH?ce&C$4#+GF6<EntX3^>VryF*2rSwwRB+rHhx*0 zxRfU@D{?C?Ph6m)GLyo_Hai6`{GZRlUq7lU#(PYRw2VF<oizHB?^TxjJI89$P)JO= zN^)tpD9=bC>?YW|bgf|qW2w%044ah|hkB;n5-m=<HM%N#t8p+Ir3;qgcTrmY{VH)Q zdMn#W>1fpWDZd+KQ16Au-cx<bJrcNxM8M6ohO`xj8K}C;I=TK(K({j0Cu%l+X8g>o ziKTE=dK*iXYX2E>#d}V6*L;F%G3gnTrfS6AxDb0Y)>W%{Xh_Xv*qdp^%>mlRp(9kw zun~a?5R{jMC3!;1OOgD}5x)~;%Lqu2iOWg!Sbz3p^cWvG?n$cT?Fu68`JMeIA<`=Q z<d(t`_{Ax>;IC_cahRIU(UQNV)uPjXbxTd!q@aPamYOBvz5`rSVxVKQoxZMIC>+vs z7g{eU0Boe`HU|1J9P$y)HZeHS*?V6zer<f)`1NahAGxRXy!x2CWy`MBw;le$;oDa4 z+S1~V)$eS%=aFJzV8;Odc;Qo2a_?&_`l&Coz6)Zm)|T^P%YS^;4iv{zJFfci^4NJT zt*+Pw#*2J;QQ&b-N1~-b_zL>Bl3tLK0%ppP(h*9cb)Xr<4nsgQHBGIrynkF;^0|gx zK5<}$zwLUk{Gjg=LtL^vYWjUqTywf+myFTLB~upr{SlE+DN&*oF(1Htx^yAZov8*b z5b7WZ!ur%PBLU1vBi5*<<3IHR%QdajLP({Ff(3n#tTsl=1_+|7oSOlb$btSB%c!1( z!d)P(!5I))?P7YU9_)xB9en-Z!PoggkK?QUK;u%IwdSsn!*$!V86Kxz`wLf)McbP{ zYID2n*QRxgd#SI+^$$*u$Nqw=x@m#U8o4{<bWSdOht=(LT%QnyBW@JtA$r3>cEK+k zAs)>oJJvfQw&Wew^TY02JEC6aS3JR8R{JG6o6}(ro>|?|Uc-Y<QMRpZ)@p~t=1kma z+f`ZEc16bGG7Ha)@}Sr|O0=xGkI#`7NZSG1Q)V4(<0L4Un)ZYL4b&0e+RIoRqZ`+B zRX`dZGzpjzcFM#t>cmOaGaNXeN6aY>>?GHPv4YDj%X!)DDh{&YnYzvRmQ9y0^0@{# z_l<#`8YBo|*~RXaw7;)(FJ@VnPmWc9k?SPa#X9-9u>rumH>oV&W98g>9~v??u=c7w zYvr$qrhO*a*_r$dfg5;}2nKAMDocK`{zcc&@e+NOwX#qb01eQEogq!IM%*<(sf3S% z-Y~dWP^(7a7-+6Yit%}T9{Z18i&J)5iUY*~hr?;<wQw8%=h*t#AH`z&xsCIf5kuhu z5xQ)IDUAKhNb&j0tz75xi~ne0+`8OWW8tSqBH#ZOjfJt}%OnSYNCtCD>%#)xp<a?8 zUl47Lv$&OJxRSCA1EdRzWDGWS8xk+DR^vxRHXRj23y(DoM%n$*CK*|5$e`P&j*Sp4 zrRJNuo1(^!=%D#Nu^t0bq7s)A^-8!U2w_JZ>ulo<E-vsSlRO+K6p{c40+hVpX%q;N z1CO(q(?49oi{^=~e$9B;*laxf+H34=_9#1>52Bpk$%g4@4Eawb96J68`%`7v*IpCz z*C9#zN}xqApj={Exs4IKq{~4qMEnv9G(s4VMmBLpx~xGs&;T^S2x1!usfc2PF;FlR zhScKpDi(0Q;0&-T=5zef;p2a5E9RX(7C^Q!iu?fcIg9zW2z$hm2(Y!taU<sm6mg>n zTN_AN*dq}hRha0FF|0T|9&p3xm_!{rhU2nauM+S_{mx;UUGz8VKl<BV!7CTQKS<a) zNwgHwi7H_!Agg#uTtOo)27Y3)OA|o_)H&XIBk#-kjC{S<+rlKk7dRazwXht$>3#Ek zE}sI#&VSlmYvlcYHeB1BX2XIl${)j;tz28i5W{N3SPR$_uuxszElaHvi(wofh(b9j zKn&W9Z&;&NW7vwW;}0O=@(qnoF>RVBfC`5LPgz;s>H-)In!w>Z?L&a$1nmXF8^?O4 z*n>z&ER&PBx1yOgHV;ilD?Y5fLr%YeALe_|=W;mk7<KsIhqM<m2twYNdnZw(EDnK| z9G9^<#lvyh!%J(s%Wq=aus<XpV?9h}uNQk>$BFfv#qxYG6*&S#RQ;YU8<F#otnIyO zo|kPh8#O%K!G|9;>S&_bFMH?mrs{@<>f*o6t(aRE<l-%82<U7;9?=k8IjoA44p1R( zNUjEVELI=m(jy--k&iF;8zUC0FUj*sUjWxbA2KG4@ST7;XbMXBEuEUjQjI3Q$#f*d zjvfx_8dt_ekeLnz`#Z=tfWMJ%@p|iT``CBN1lA$u>d?clc&s)#{Zr$mXD8^fdzpXN z4Oj}QWaJ~MrgYtH`%4{q<<YRi>H4Da-u*<lv2GT9ZSO@}ug4M_ry+rp6Vej2GN5xQ z-jD!MGQs47yTDf3F;0N^OVbG+23;AaW#%%U6c=sp2tiAdH+C5B-DCXEuIv2}2}fv! z`u8t+?(Ca?v)JBZ31RV6Q~!{Q?v*lMar)=82bljJ7T9$I9%CaaH~wfmd*Qb0{bm)Z zPXGSCr8ivSJvZ!^{q#6;Zrg8WICbV=E6_E6ionrAhvWEAl24U5l?kddJB13Jnx4W1 zgy=p&bXlS>HSM1wnJN$2xZI>*68p5Zoajoy{V{P*#z39y8ih!_Yf5`3$#a>x7tzf> zh!T^piYLmP$SY=K@zB^Xo>x{>3VMN;Am1$jUi?yxL~u=1ZZHrE>*dXeC@%0D$gSMd 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 literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/font/fontawesome-webfont.woff b/src/admin/application/templates/font/fontawesome-webfont.woff new file mode 100755 index 0000000000000000000000000000000000000000..3c89ae09b88b38d3bc8563ca69f7f401b7301f45 GIT binary patch literal 29380 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 literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/icons/audio.png b/src/admin/application/templates/icons/audio.png new file mode 100644 index 0000000000000000000000000000000000000000..7215d1e8b0604a904ae4a217708ebce05c3b9bd8 GIT binary patch literal 669 zcmV;O0%HA%P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!FG)l}R5;6x zlgn!pQ51)(i2r~)v7qjBSE`L@f`Wo8L0gIs5W5ngK8keVCJQx+r7DpoLQug)7X=k* zL8_uyEm~WvsV!+5G-+v?nM`ITlX+(Hs6X$$nrUiU?7+9U-1&Wnb1tV2KplmATL_JW zrvI>&u-?g42^wwN&Xr1~#d5ifl_2*B1OoS}CDno^8a50ArfE8;stQF>AP54J@H~%T zFz84s;dO!QJKD36(~!QOg!t_^gfFcSKDU4yK0+Ypg$NT^mIYcQ6bk*3P(lBLh7Df_ zTu=2xC#+-_%)|{Cv8zz0t|0y4D5M`xAc{gwOKc`ou<*&VjUREFHs1qd<_xSkKeTBt zgyCi=@jj;&Ns^GsWWaIUl0Y2azcDlF@u{(P*!+EH;lnU~b|Lv{4|4Hdkh!qoQHiE$ zY#y>KFA0QEw=4Z|uV{0A<db)xO}4>^`Y=D}hB$GP&<$bi8q(u;p^0(my3Rz7fP}|# zGZ&#uor4@c3q9r|f?H6-UZmfgKx(iV(MQ`MPWB>iC~SxnN5H*zb*A3#zWwgu&c|}3 zn^g87H{pdeasl%Lhmab&jC?lES}7C?4BFDNA<}20hoY@w_IU%i*T;}}wh!589}7~7 z#Ug`-R~4j&+K_y4kW@X7qLr-)S5qVKU)tO;+kXJ++{<NeU6K4tji94-(<w`u{<Yd3 ztiYlp_$%2(24vEUwS>vPI@{hVK|PhMVVx_`)vx~zUs}c9O-Ok{00000NkvXXu0mjf DS5_-g literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/icons/folder.png b/src/admin/application/templates/icons/folder.png new file mode 100644 index 0000000000000000000000000000000000000000..784e8fa48234f4f64b6922a6758f254ee0ca08ec GIT binary patch literal 537 zcmV+!0_OdRP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzt4TybR5;7U zle>x(K@^6+>g^d@v4;gkbWsEoXE%32*i1tcpTNXd5CcIl)ECgqz|2rE6EW}s7R?kl za1q`0GCkMruC6-2LANtwVlsgzsp4?{@7$`KBv!G66>Vie3h?3OmEEkjwdLG0PgLVi z`!N((f$A@n17Ldj#`};0I3@iHJ5M{#IZz|UIYRm4(!uV7eYIYIwQf&}_2J~}>pQ^n z6o8--^T(=hkBNQ_k{-_GWE<Dm*nZeW0t{q;aLLKDA7AX;UjS;C$UM<^kqJBcOg%kd za`=W$b`Dg7d87aY^8Vc}vWxQ>;FMW7!p}f{N<AKt_ivG%+H4#CQ-PWa(shVQx&YJ( z>G3nHZ{D5<3d8&tLh%a4AqqnjMkr3m&fkMdECD3N5}Unig5wy40;>lo4j~k+e}v)` zR6)J8Mk*u=SpB`p6o)7j?S0T@9?bz#m@l>gc*zk__|*!FMcHwP!gwLJvS~9c0px8E zW<O8VlWvaXiPQnhL8noy0FRR9bV($ZrR1$z0Ltpo-jkc#i0e4=f4*G-?ybl4tXbgy b{*Au@zK9=x;oF){00000NkvXXu0mjfJ%;Z& literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/icons/icon_loading.gif b/src/admin/application/templates/icons/icon_loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..40a65e2ff42afc17de2e1bf336f242e98b0c1c3b GIT binary patch literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nno-y4@G=zbl%52FU1Ke`VqRyK9d>RQxC9T$GwvlA5AW zo>`KikeHQNk&~a8qL-PMmd~L0lZAncfq_BsKewN2NU*bGfUA+70W%{|NC$|4Mhh@7 zFdK91y7SNAlxMbZGKUq1<Q#Ut8EKrZ8x0Tb5}A2$n_j|^LxmS~qa`fwE@QWp;9>X5 ze(nJ@5^OXhvN<LobNqS~6{K5uc5isr<x=Pr7?NNpsgU5~8ZEV=MrLd2{kMq{><tRn zB_6doOKwtC(Gr3h#Dr{+8OJUoW$jarCnlVk5~k1Ank>WjMbhu1r&HpL)deyixXx_e zD|2jxHdEwV@jr~shxv_Grbx}-&jK}y8QCbH-;z|dPZ_mMd^0C3zO{Q9XR9I)i=j(< zqKx1wx26pj<(ZR$Vn5r;8(8Q_^`BT$Wa$I*8w;{IMjX3})U~~yr-*!z`0UfjqgHk} zAtotgN^8qbxr|6B&GV-m1eoPs+Q=VP1Dg{x31$o{vN1sCC>)w#DgL<R`JP+z3?z@s zJW$kg+BWx8_?ktAJZ#(|#fiH&n0}wi*l4hUvvc?STum>SIc&)00G)H^-v>^?n{z^A zXEDCJRah`Jq2q4ioVzB|S{>bv8i-6tn7xgWm*tRyz-+^YL)Xqtgc-w*VGJ<lSEo8% znWK4Kj)UW{Lf`R1J{CiRm8UkW3y?SjjIOX-OPLf(lO&qvMGH<~V6X-y954U?wc*%y literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/icons/image.png b/src/admin/application/templates/icons/image.png new file mode 100644 index 0000000000000000000000000000000000000000..fc3c393caa3bc4371d12d0c67ffd6d333ecf1d8e GIT binary patch literal 516 zcmV+f0{i`mP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzmPtfGR2Uhh z!9QzLVHn2Y-}9a~o}4PJgQuV<2;!!bi-MoP&B?(IB8cLay_0Ac(al-JNd$KXKZO)J z76W1<wnS>0oSgT$J*kO*Aq9I~CW*s{G*(t$KS{OS+#aO%?udUme<*TTEO`Fr@r_QT zk=#}u-n~>Vm!+9S1PE{@3<)G~CPb<$Za;W?3+O}|+q)?*Pn355=}S(XIZmEANjZci zf<Z6{!N`K~VdFiII`<eSGa8Y`U<4sV&YwHWh09mTLWY#UBA5}(FbjkbXk`I+eu_*v zkmqgM#W9eWM+guTktqkp)sXRU56qApSHeADfFv?Y)YSmVnTbqE@VWnyFTFlvuW=>5 zj<%@MX^bD1^BwlS^+AD|$dm-1wial0hwPI;CDM?Y9SXW#@w-UF0SQ8OgplRTleOB2 zUjkDS|0U9pI|lSN*EvXUa~*UIclJdZ#)Npbwh9>YT?Z;=B8|l&^t~P~om?<5Lre$+ z;%`P>SL7`djY#8Y9$wv9dv|3p)<t&?l((RWyr5x{IE?Sp@~c)9n%N2f0000<MNUMn GLSTZ`ao24C literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/icons/other.png b/src/admin/application/templates/icons/other.png new file mode 100644 index 0000000000000000000000000000000000000000..8b8b1ca0000bc8fa8d0379926736029f8fabe364 GIT binary patch literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6SkfJR9T^zbpD<_bdI{u9mbgZg z1m~xflqVLYGB~E>C#5QQ<|d}62BjvZR2H60wE-&H;pyTSqH(@-Vl>|&1p(LP>kg~E zYiz5X^`c$+%8#zC{u)<aJH%g`Hs@ixWul%W)5U2lC+*9&Fj~fNPMviv$?4$+d6Do- zTUfo$OY6r(?tE}V+eOf`TWXenuZ(7%PKZW9QmV+7<<H#Oep_^HcG;Wor}g2>yfe-5 zmgid={Z3k(ERKCKrE7DF;=x4^O+<x7did8|V|kn@Au2X&;sJfNy4LeHuKwPeZo4k> pzO8rLO8p|Ip=x)jHOtWj`bJBmKdh_V<`47(gQu&X%Q~loCIFbEay|e6 literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/icons/pdf.png b/src/admin/application/templates/icons/pdf.png new file mode 100644 index 0000000000000000000000000000000000000000..8f8095e46fa4965700afe1f9d065d8a37b101676 GIT binary patch literal 591 zcmV-V0<iswP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz;Ymb6R5;6x zlgmpRQ51*OWfxY9N(BY~fvyyB<<ga4p}4fTQL0!MK4KLm2!iWELJ5{C6m%i(y3mzE zyJ=Mvd>~O9lw>B8WRlD)Gm}Jrz31u-X&&gn2lvjs=i{7nIaL6v2==uw+8Lcs(8j27 z;|c`rmSv@Lx!heopGP^^Ieb3f=R!%Lpp$}iMS-&P3EJ)s48wrJ_Ni0~k|c47D2nj= z{jS6bt|kFpFf|p5cM`_&0Zh|`rfEp0(}=}lT#(6RpzAsUfxv^LSYX>WlAaN$>)*J5 z0#sE+JRUD8iT9*fz{)_<I|XfPov*2Gr<6n@!7~vAp|XI8eHcK(GX_WKNGKEPhb+sL z1=imy2=Ct^IywmR{PaHwl|wxtQAL3`{SorlFEFn!5gB2Ut02Fe&1QLjNJ5kq*pi4) ze=n>^7@6P&!sEjTcD+I9Z4YjT1`wH@fV{cEvneYGFU%maIEU2s55&K(LixD|{p<w7 z@*-}=h7g|jKw4WV75r*`RUc@m^<MV(!A{EVGg0jXrB9er6gKMttzE(4>-uiS@?KNj zk-Go8<gFb^F|OcGW9<rK$M^Dum;Jo2GzVq4b4z&aLkH`!K?lzXW_L9{y#<0+l00La d9cc7h{{bX9v)}>G$hH6g002ovPDHLkV1hVj1#|!a literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/images/ajax-loader.gif b/src/admin/application/templates/images/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..0ca7ada960568fff04400cda966fbdcb106abfa2 GIT binary patch literal 6820 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 literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/images/dragHandler.gif b/src/admin/application/templates/images/dragHandler.gif new file mode 100644 index 0000000000000000000000000000000000000000..927c8117da2f4cb0aeca791f5ce3051c6e5621d1 GIT binary patch literal 113 zcmZ?wbhEHb<YSOyn8?5|Z{EBcH*Op_aNzds+loI~7}y#9Gw3h?0Z5*K$*HGb{p7Z} zaSX{}ulVkndgP_DbyVJJ?NZF>%lx@FcF(!=wUf4WZ?~vPzSwebivRS<s@2ZP#w8(c RGbeb6D(*~M-NeLT4FI&&Esy{J literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/images/icon_delete.gif b/src/admin/application/templates/images/icon_delete.gif new file mode 100644 index 0000000000000000000000000000000000000000..8a43c33e129201737b41641605ab04825097b615 GIT binary patch literal 323 zcmZ?wbhEHb6krfwxXQrLB_j0t_3N24XFf47JgTGjv7_~Ubo5&Xr^AMZ-=|LbUR3-e zB)DBv^qh^&w~VykWtI2Uls~3sytA?C5f%S2bL!{TmTpnO=hoI|jEzs(*?*3Yeedq_ zwZHd!X2v}=jjwZOe@)9^pe0cJ$-*kaz{sEjvIOKO2DXF)4Fw)LQvD~M1R5xE>6|{v zt|(%lG4oMyp{4>$!||p|7no$GbGdDdn9}RhuCnQ7!lZ<sja^%^^u*a^YNB}9<iyj3 kI9o!+xC8{4!xY4OqJ+8RLV09aym|Z>yp}9=c4V*y00JLZNdN!< literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/images/icon_edit.gif b/src/admin/application/templates/images/icon_edit.gif new file mode 100755 index 0000000000000000000000000000000000000000..66ba8940ca4360d6d95b3c079bde50cdc8bfc013 GIT binary patch literal 198 zcmZ?wbhEHb6krfwIKlt|uV26Ze}>`AOosnwX3jKb=;-M9pO)t0;&R5=_{_|-yLa#Y z2TG(d7&9>Z|Id(SZ2bQWkZZhZ)he)V0)*mE7FH1kMg|>_I*^?Vtj-AveJPpqR&cI; z$>DnO;g*g<nUg(Y$C^}j%06zKp-{5yP=J92m;4#FO-ow%mRL85c25%ExW1CpAwc6u OGK0gVtlhzi4Aub26F`dq literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/images/noimage.jpg b/src/admin/application/templates/images/noimage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e91748bf0119b668fab3e5dd999991f8ae42d471 GIT binary patch literal 1315 zcmex=<NpH&0WUXCHwH!~28I+MWcdGvLC~c%IlGd9k%5JQfgu1W^p1hgF(p4Kl_BK- zP=xXSZH5*GCOBXQvY1(bBr^*u3ka~Xv4Q~`8#_A(J3AXECl?ndCl4xMWM*b&WntxH zW8>uI=H%w(=K}(Mey}1a#RK7?>VxzCA7BvV0J)i&QILU2kdaxC@&6Hq44|`_m>C&? z?t}q0cA&#JI8nsFasmvDEKE#bhd|VVv;ti(D5Pj8%&sINYNRaYnCPS`E{JR#Sn2;; z3_Q$0<$}zD4E7Aae>6}Enxoz}ht1vXxc6*E$`pfnmM<>7v;6l*VW~m9(VX+gBy}JD zu-|Yl@zwRs6R$0u{bkc*<#}s*Czwx`xp3<G*1NTp`K!G+v$xgGx14tN@s~GgmRC$q ztF<{BPn(ryRK2!$k|%4$!rmj>3_i#!&;7MCBlGbT*<S06$*HR+_kFYe@bhln?~m1N z8eVECVG+l?WJUHy#EVQkb$sK|wJP$uECNmI&ec3rQ(7whpW)cySF+bNS3i~gZZjkE zk*wwB3G&-6KGJ$OVZ$$e+5T0WeRn@8f8BfD?TXf;{mN=r6VINEF)GQG@V_j4;=#9) z^?bbf{k(<$I*j6f3QpPQa_ptLRDAz-k%HUjr%&6&Gj+!DjbZcS_6YsRI`OFT<7xKQ zO+269+?Go>oqZ&8i{T~5wO*%Y_M8igoGrX=pPK)-3+~J^v6n0*QYs60)mLQq=Pf*Y z;=Q%4j~bhM)`rL5V)h-lTbGmi+Q@9Nitfz&g}iM}u{!>OOvkGeCe$=IIvO1E-f=Q1 zaZ}*o&{fKR+aKpfY*d^)@!{E7dldLAKXE#$IXE~joz&$m@%n?yy-#POA|B-{6g@X+ zu(aV1YCiK@{OIrcKbL*_V~-y*=i0SSJMvCJ-YhY*s}YOZH+=8@yI9roR?P9T2U|{D zsN2wVW`UWkxc262X{+ng4?O?0IjzuqBmc^G2X(h?y`~-6b+zkB-RqcVwoA{xdMA6O zU-9n64KuCePj0?>>&^1ncZ!y)=F7`81%^qiKJ2%K&8^|O<%a8-mHB;7?+7tyXzh}h ze!eE=c=(xzhc^nnzugzCbJ>PZzVpoGla6tIEG_fP-$ht8-YEWRQc%Go^{;uac!JSw zT`}Le$KLGd+U#@kVfil`S#8lrTl{yp8=tqCEXKd0x}o%mh~%1@#H~+C&o-yl`K$Kd zH>#{Gn-z6n-ppmUuPl-8U9Ympe7@*|F7=7#@mK$;v<Owac(y^z?AP=yXZkL#e|P;@ z(jJSOtGGqe=j|~(?{{I^)jEqwa%U%*Tkf%L7d-Gp;r@Yb?O7MDoXa?S_FDfF{&Ty1 zQ&*MGGI+Nt>O}MU^CJ3&I}fhQo@2MbyE31pb^GGS1wU?w&+h!ud0&R}QRc>q@Iwx_ eZDqe4s~0aid{VYk_7?m4c>$3eR0j6{Zvp^uEBSW- literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/images/resize.png b/src/admin/application/templates/images/resize.png new file mode 100644 index 0000000000000000000000000000000000000000..542d01af59f44b428eb88d2e9540ef01194e8f1f GIT binary patch literal 348 zcmV-i0i*tjP)<h;3K|Lk000e1NJLTq001HY000{Z1^@s688Tg`0003aNkl<Zc-rii zF-t;G7>2(aCn9cew{X-}mq2Lg7hIRJ#U*ewbainHT%4Sm`U8!n_ydA+NgSjf&?1PN zL0v<F>-)mFtK<33a6fqNaF_St@ST@q;y8{(<N?$`C~oH$JcG8uX8>+RXTmJ|0NjZF zR4MZ9fykO7U63kDFuTVcc>)V?4Ne?O{McoEH}=PyMQwsKO~r@tM+AlDg-Es|$KV1S zI?msMDcDe?491|SbQoXYiaqkED8VVwfg%+TR^*%_GY>@O6uAQ{MTsS7a#=sYnY}f} zvBW?407({{fY-cP^NQb7@t15j5IN50>u?Ar6sg<CQJ{1f9nfHp^c5w<X5Ulf)Pof% uP-NtR$cwQRAK1t9kz;{BN`Tf*fB^uSAUT)AoZ+ef0000<MNUMnLSTZhE0<sZ literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/images/treeIcons.png b/src/admin/application/templates/images/treeIcons.png new file mode 100644 index 0000000000000000000000000000000000000000..e8728bce7860b0e8954ffe42287adcebc28ac6d7 GIT binary patch literal 2680 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 literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/article.png b/src/admin/application/templates/img/article.png new file mode 100644 index 0000000000000000000000000000000000000000..117a53a24df1329c0935a3e0e4ab31c13024cf77 GIT binary patch literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^DnM+&!VDz4GmokPDdu7)&kzm{j@u9Y9{{;30X`wF zE-o&&ZryTobNm1Q|I(#P)6&v5Y}l}J<;tBqcdlEvZp)S}%a<?jsJ1u;RL@!95n0T@ zz%2yAjF;}#{Q(L}l(<HeI2WZRmSpDVDTHL^rZO0r=^7g78W|WGg>R|&2~;BoQWKn? zR#Ki=l*-_klAn~S;FejGTAp8&U98|7Y^rCtTHfO|P^Gu0i(`n!#N-4A#<Rzc9b2Kq z6Enk!r`xdg#sQ~e1q?#7do+*qX&%`i8Qj4d+`;IoA;NK?<$;!_K$3x5L~C@$m1Bar gixs#M7HBarT(}f#H$f`yE6`X5Pgg&ebxsLQ0Kxxc(f|Me literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/attach.png b/src/admin/application/templates/img/attach.png new file mode 100644 index 0000000000000000000000000000000000000000..2ae626438d9c7ce0ff283b4725366d71f53e63dd GIT binary patch literal 1370 zcmV-g1*Q6lP)<h;3K|Lk000e1NJLTq0027x001}$0{{R3bZ>Ak00003b3#c}2nYz< z;ZNWI008z-OjJcgL`2%!+Gb{Esi~=oii-dL|3*ee#>U3&?d^AWcT-bSprD|+xw+-# z<&~9{&(F_raBzKneOg*t_V)HmOG~n{vZbY^%*@P)h=`Gqk*=<;^z`&*W@hQ>>EPht z)6>&lUS6D>oK{v=a&mILy}d|CNb>UXgoK3q`}<E%PkVcN$jHc#kB@F{Zlj~4baZsp z)z#wS;_&eBzrVkknVEuug0{A{VPRoPN=obN>uhXnTwGlF`T2T!dgtfoSXfxm(a}y$ zPLq?9p`oGO-QBCJtH;O3r>Cc}v9We`c8Q6J<KyGIySvxd*SEK~!NI{}V`GhtjW1kG zT>t<832;bRa{vGf5&!@T5&_cPe*6Fc02p*dSad^jWnpw_Z*Cw|X>DZyGBzzSFfB4L zF)~-Qc=-ST03LKjSaefwW^{L9a%BKPWN%_+AVz6&Wp{6KYjYq&Q#CFzs~<?~000B6 zNkl<ZNQsS>*K*=86oy3+5E~Lq32mq`oisvr$H9~^Fy<neWZ(Z~R_92vWn(+}FF;88 zjC7h0p?=-eCNxw>XHyJJk-+aF8E%|oVA9HuHNrHCWm_58L$ud?Th3&!dql{LW#`1z z`jBnmE%bXiwTNXOh)?(W4gc@M8V+5GWs7V__4aD$;gwmcgG+y2HS!$8mNS`*#=h-Z zKdJovU~F2joY=;&aNU_0FJIC-h3~DhW&asfc5BfC99dZ{G>xgk-#zR@*yYz^O|}#c z+6g?p`|zmXQ{&`D4`V0dawXcnv?VvgeDzo1hgY{x$evuIHmJ!y(;+O#GV23{*Nk(4 z+_^u$XkCe&#ORWLPR-s`_dEO;7{u`4CGMJQL^Cg8s)kvTe1ZY^^^Y)t8(R4IZp86f zm_d~F3572n_$M}6;i!fW)+1OZFz%jE!}aNmjpjJ|M79};j#&IvY(lGSR~;rM6&AfV zU)(?>wIW#)<B!k+SR5w0Y#>X+<h;;B3@x<)BSUPI*Z?X;A15M}zwyQ#A@U(S|DGaI zM+x+2epDh4kN4LC!1mknPU)Fln21QD(JY%V#G=jb+8J;wQhOr}iUQZ<c^)M(4jM}S z84dXS)PyB+Z$z;pl_5cdk=nG!J_~%Ufyn+{5QR0mdneJZh(BO!FjVr-L1bRxVQY3Z z5x_EU9ZWjT+7&j0`|}!V;>Nm6O|2r+Mpmn$h(D|wk8J4XUri~JehCNL%(j`9WSvYI z?+@0sc2Ovp7BrW3LpD)V@{c~<K4wB$;oxgFd~jKM#{2hOC)o4V_a!UJ5qGJ}PUsbz zI8#-*mwMp%cQ_9YnNp7hQ-ev3s=x9VPKHvT)~*|7DqHh5EVBOO+v~C%4)HfQq^h!g z-{Ic$nh$SfS3Q`=(gYXjsBDr1RN18bZ-47!JOB%ULqxi9b`<KA!T7`S@eq_v_qu{L zL;VTrU1$AeYvx{8u!~3*eWQD?KPZUub;sFKEX(w6oOpgh{>j%Jvd5oL)UN)LLx-eQ z*7+3+N<tYhRkrwR7L`+2J2GR#|C{>m8+fnAYvp4>`+q+gTc~@%G8N9gt|mfLddZeC zef(Wbm}Vhtn<RC7{|CC7psFD(=2As8&z3nJM6jJO_8=Bz^V~@p>q}JWzZ6#Komumo z;1_}J)u(hQTXvIp${H_kKH;c6u^GyW&<r%3sEOATFT+_qtkHGFd*Y-rqq0jYxId^u cQ*HMC1J~qfszUZ~JOBUy07*qoM6N<$f-Quh761SM literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/breadcrumb.png b/src/admin/application/templates/img/breadcrumb.png new file mode 100755 index 0000000000000000000000000000000000000000..d3462402e4f803860a6b11fdc9bff76f7e3a955d GIT binary patch literal 1118 zcmaJ=KTH!*9KH$?sDe}-@K56Nh!eDT*V2|=sBrXJsPV8VO{f!G?;h=i-o4}Ql@?-* z)CDF?(8a+xGLbl$=pczCXksurIpN}<gE3ArIQXu##liZL_c!17{eJKFzPFy5n&@_4 zbW;@7otzZYWIjo{yR(CgcOnm2GP&&Z#5lFRfB75PwC4p$pr~gXr+&*0vdf&jZBtaw zYp1*R(3VOLFW`6<PosHUmMusLD#}5S)a5)(Ls?y3d<#b?ststFEY3<dc?Ib{*}?cK zx=Gj+H8NT;Wn}?kkb`;6h|)h^zM_GqM(LTL#7bri7PQF~3r??0Wt5c#C8E-!*TG1I zCjvUeGN|Z9!{#edx~9vMwR6nSpa#JUQTiyUtds&VWI+)0v0jA@u^`0xxWG_293BLI zmSY*#&v1S(7v=+go@GJ3(IlFs&hu$8QIAD-QM!P!$ums3T=ta%K4j$?E)t128h*c* zAiVanf#r(Vu=^VdBD57tGqHvY;3&#DRKii3WO{T3-E7JlcD+obU`$0e8P3N#S84zy z>Hkn&Z=!9ShR6B-Q`pWdn~+IE8<i}DJluT06UyXc7L+lvG6)qLRZJBSMs@+2AT}KY zGn%2IvRy+<5}!0|EE@_;icy;IeVV57ela9Q;<0!z6yi88&Iw!~Fw7=`fsi0@F(K06 zibyHx(7+9@ddy9<<T^&sO%hpzmbL`dgoSiayD+b{&L!4Tug+Cl=OVV`G9($sdDg$4 zxp73i<1Cw|C7Y)0p+UTE5mUcE?DUWian<=ywaPm_$!I#Hh&zcRhj}gpI5GzKA$Ie| zwE+SyB}F0AH=`60n%&#kVLfYSPH=s!>*p*u=-hqrrn)$`FM)%e-H+^}&#R}efQ}EK z>+XZ4-b(lGld(b9?!a6XtZ$?S-RHivyNj+|@Aorj)eg;-D{Xmh3DwQjPi<@W?;ZNz hEnNcrp0!_s7gE&I@$+A|pDT}@|C@|YiQD6I)jy!GSD*j@ literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/calendar.png b/src/admin/application/templates/img/calendar.png new file mode 100644 index 0000000000000000000000000000000000000000..df64d3c70c0896186d3c09c61e3db0c7ddb64dfa GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^+(693!3HF^taP6Tq*#ibJVQ8upoSx*1IXtr@Q5r1 zsuKcX#!GkW{s0B#N?apKg7ec#$`gxH85~pclTsDjGK*5n^NX^J6`X@j^$b_bd%Om! zjP!JI4AGc)w(lV40RtXpeMRph*%ggxpY$eJ?rHn&sSqIk=S^)(s}4)|z1_kEzjEc3 zm_Afl{9UvvG1;Z?ySD7VTT&OVEfWz<IA>`T#pv?nTn4Mb=7|^Qo7lTBxtDV{as2{X O!r<xZ=d#Wzp$P!>zeuhC literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/down-arrow.png b/src/admin/application/templates/img/down-arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..ec347830035a25c0d42e3d0f79e689c003159915 GIT binary patch literal 4046 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 Ji*#&*{|#e;+6Vvu literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/dummy-logo.jpg b/src/admin/application/templates/img/dummy-logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94d098a26a0fcf50978c3bc2539cbe5d0890e97d GIT binary patch literal 10971 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 R?31zo2%MvA_@@k-{tKOOY!Lte literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/exercise.png b/src/admin/application/templates/img/exercise.png new file mode 100644 index 0000000000000000000000000000000000000000..2b0181cfb49e3d75332a54a46b93048d4a878d3b GIT binary patch literal 1096 zcmV-O1h@N%P)<h;3K|Lk000e1NJLTq002|~001%w0{{R3^%xAa00003b3#c}2nYz< z;ZNWI008z-OjJcgL`2%!+E!LpprD|1baem!|GmAv^z`(PkB??%X0WiZMn*==%*^HG z<${8OY;0^#PfwMVm8Ykt#>U26TwLw#?bFlK_V)I+wzi0fh~D1bdwYAUtE)&zNSvIU zVPRo%a&qhI>-qWlOG`_%w6xF9&rwlPqobqn@bJjU$gZxg;Nakqk&$L*X4lu(cXxMM zT3VTznd#~2ySuw^aBz){jfRGXeSLlP_4U8Mzx(_9OiWBuQ&W?ZlgY`+(b3VRrKQ!? z)nj90<KyGGxw(ITe{ODW=jZ2kc6OhipI%;Gsi~>6v$I%OSl{2@!NI|Yhlh)ciye<6 zO8@`>32;bRa{vGf5&!@T5&_cPe*6Fc02p*dSad^jWnpw_Z*Cw|X>DZyGBzzSFfB4L zF)~-Qc=-ST03LKjSaefwW^{L9a%BKPWN%_+AVz6&Wp{6KYjYq&Q#CFzs~<?~0007; zNkl<ZScTo!?Q@zi90%|)MU1r83Ti7_5%Hnwwc<lPaa!Bj_PWj6?f?I0mJm@OK%(Q- zzAv~Fl8+dYUl54g$w2LeuO;9VrP>If@UeX8___f0(K%Qi^x;Vcp6Jj2jw(|S42xx; z#;+d~iSyAu8|~e7LP>{RpM_Ru^++<FjYQjzv7!@re+p`EA)9nqg%_2I-}%TWmPRj! zOMcQ}f3whX{xp%WnK*QDbp}bZ9<<UQok`*}CLw6kDzJOTv)ceF+{)};+^mBtdIF*o z^@gB^*<iLUXxC;&5QMEcOf!CxYT6>mMb`|HWj;6XK3e-C6~Ek66Nn4CUV5TsD%A2o zW&2Mnx=a27k7+e(4HfQ6A)*s072apG>A6o|%DvLpcm1%NJft_IE93jxKTq3%^|{;_ z?xo9xm4<j6>kw*R%J?t{{wF-zxWCJ@q5$v|rzf}TdPbG3omD2+D%s=7xu>>z(SkkM zuYLI9j$FjtaEC@A*LPjt;QLT?5N0jVs_k#YiYbDfqK(^((XeR24Iqf(cab;pS@{-C z;xwF%S}HchU}$t7dl*mRq$rMorr9O{v(r$C#{{GQ2kir}Ng7pfqpyTfX9mH9(IRg2 zo-iuuXpOujjEYSFddKqzv@^|`&w@aTmVx%E$=$rcjphK@9?ugL)_Ng*P?UU~3;h7# z(U0oY@IItLSC(ZK`iZ~!Sa77s+c+e}zS9jxYd$n~ixNePjXHyWoTmobgJIl1o6^eH zJ{%3^LB*X?Wh3n3;AV~<R6Q%5h>DdJ*@9KgGAC#%4a5>U-kZf+@`BP@(IuaWqGxAC zzY@K6BPJUQMSF@eRB5m?|2c^5#{O^mxz1&$5JFi-2R++Y;z2(2jQj<sNM1E2z^MTM O0000<MNUMnLSTXfMjm1S literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/glyphicons-halflings-white.png b/src/admin/application/templates/img/glyphicons-halflings-white.png new file mode 100644 index 0000000000000000000000000000000000000000..3bf6484a29d8da269f9bc874b25493a45fae3bae GIT binary patch literal 8777 zcmZvC1yGz#v+m*$LXcp=A$ZWB0fL7wNbp_U*$~{_gL`my3oP#L!5tQYy99Ta`+g_q zKlj|KJ2f@c)ARJx{q*b<Rc{fZDE|-E3z8Qg5C}{9v!pTzga8NZOmrk*O`5892Z0dh z6y;PuJwHDK9$?(w-u|_L_3`o1($W%e0`}kWUyy&dCnqOQPfu4@SAgf?;o*P$z|s8t zJh1KR>bkhN_!|Wn*Vos8{TEhUT@5e;_WJsIMMcG5%>DiS&dv_N`4@J0cnAQ-#>RjZ z00W5t&tJ^l-QC*ST1-p~00u^9XJ=AUl7oW-;2a+x2k__T=grN{+1c4XK0ZL~^z^i$ zp&>vEhr@4fZWb380S18T&!0cQ3IKpHF)?v=b_NIm0Q>v<fKgXh*W25>wY7D0baZ)n z31Fa5sELUQARIVaU0nqf0XzT+fB_63aA;@<$l~wse|mcA;^G1TmX?-)e)jkGPfkuA z92@|!<>h5S_4f8QP-JRq>d&7)^Yin8l7K8gED$&_FaV?gY+wLjpoW%~7NDe=nHfMG z5DO3j{R9kv5GbssrUpO)<pElNvVjx;Inad7%}rnn)BtoiIXM{s0C>Oyv<s*i2m!7M zNCXUk1jq|?5|99_k&%%AIlu-a0ty3=KxY8j%*;&S3IIajE_Qc!f%*X_5DScgf&xH0 zumu>Vrlx>u0UKD0i;Dpm5S5dY16(DL5l{ixz|mhJU@&-OWCTb7_%}8-fE(P~+XIRO zJU|wp1|S>|J3KrLcz^+v1f&BDpd>&MAaibR4#5A_4(MucZwG9E1h4@u0P@C8;oo+g zIVj7kfJi{oV~E(NZ*h(@^<JQ`7oGGHtP>-(Q(C`Psb3KZ{N;^GB(a8NE*Vwc715!9 zr-H4Ao|T_c6+VT_JH9H+P3>iXSt!a$F`>s`jn`w9GZ_~B!{<w2b}Uz=xRP0Noee!5 zHGxHKH;uZjouChSB9)ldcOm@{14~ct04{b8>0soaiV|O_c^R2aWa%}O3jUE)WO=pa zs~_Wz08z|ieY5A%$@FcBF9^!1a}m5ks@7gjn;67N>}S~Hrm`4sM5Hh`q7&5-N{|31 z6x1{ol7Bn<k_m&K*9NkB7ANp6;_WSmra!UL^eY+pz_w5LlB(g$UY9|-AP@zsw4|7- zi|#>skoViZ<brlX21G1wL@^v%v2P&MSTZc8SKT&&Tq!~%Uw%k^(D<O<S;ewoH)@(b zb2Z<#wBV6y-?HHFVJFRg^me&@Reg!dys6F1>0GqbLa#kW`Z<Hy>)VCjt1MysKg|rT zi!?s#<KsBd5lg=VLu4^|xo0%enAx0mMXMSpk0KF_*gOS;jx!zP=@5TPN+S>#Ck>8c zpi|>$lGlw#@yMNi&V4`6OBGJ(H&7lqLlcTQ&1zWriG_fL>BnFcr~?;E93{M-xIozQ zO=EHQ#+?<}%@wbWWv23#!V70h9MOuUVaU>3kpTvYfc|LBw?&b*89~Gc9i&8tlT#kF ztpbZoAzkdB+UTy=tx%L3Z4)I{zY(Kb)eg{InobSJmNwPZt$14aS-uc4eKuY<?xyi! z`TeGpun(kP^7#~<fX0r^ExRQwveWDF;DOQbL}?LBzt>8h$dtfyxu^a%zA)<y|4;I# zFU8x7%0eT|Hd@3!T6Anh3IoHrN%@H8e6ge;3u)_$N2H&Rv2`ml6;kL~xS07C5Nzt< z>>fYI&)@ZXky?^{5>xSC?;w4r&td6vBdi%vHm4=XJH!3yL3?Ep+T5aU_>i;yr_XGq zxZfCzUU@GvnoIk+_Nd`aky>S&H!b*{A%L>?*XPAgWL(Vf(k7qUS}>Zn=U(ZfcOc{B z3*tOHH@t5Ub5D~#N7!Fxx}P2)sy{vE_l(R7$aW&CX>c|&HY+7};vUIietK%}!ph<X z*_6&Ee=)&D@nDa!y{$f<(Q`UdM+|H2ksGEhG7utFYl`Y6pD#+4LC8Hw@6|1H-x{D` zE$uaNS!i^Rx(%B(My5}1#H73>rCuh+;C@1usp;XLU<8Gq8P!rEI3<U)y>ieg#W$!= zQcZr{hp>8sF?k&Yl0?B84OneiQxef-4TEFrq3O~JAZR}yEJHA|Xkqd49tR&8oq{zP zY@>J^HBV*(gJvJZc_0VFN7Sx?H7#75E3#?N8<p*btH>Z!C+_f53YU}py<FUNWgSuj zi^M}p>ggxx1?wQi5Yb-_`I`_V*SMx5+*P^b=ec5RON-k1cIlsBLk}(HiaJyab0`CI zo0{<v3Q5P3@oM!6@v&t6RJy0OS}M??mGqk1x;(pa`FWA#n+2z37<uPHl{#HvB!^?r zm9?WOv;Tt(gt*?Pw;;%nF3|I0gDBXPM>=1_LO$~oE2%Tl_}KURuX<`+mQN_sTdM&* zkFf!Xtl^e^gTy6ON=&gTn6)$JHQq2)33R@_!#9?BLNq-Wi{U|rVX7Vny$l6#+S<va z%-r+y8D)Cm{5=IM8|<{prj)kZfIZ$NiW0)fE9{-SR)@-;NBJtHk@DI_v*mK(N0#s# z?S8~jyotdcJJAAUt_;Tr)fa|*cT)~*JZ!c_7yVpSb{r2MllfJDbfI~-7n_#K6lw4G z^Eyhsh^z8eZs2;adrfk9ip%h;IP|>Z@KvQt@VYb%<9JfapI^b9j=wa+Tqb4ei;8c5 z&1>Uz@lVFv6T4Z*YU$r4G`g=91lSeA<=GRZ!*KTWKDPR}NPUW%peCUj`Ix_LDq!8| zMH-V`Pv!a~QkTL||L@cqiTz)*G-0=ytr1KqTuFPan9y4gYD5>PleK`NZB$ev@W%t= zkp)_=lBUTLZJpAtZg;pjI;7r2y|26-N7&a(h<zryrg`J^oeC|8V|qszB+|*eQ-(Dy zbn*nJ1W|b4-1y?dTI6}3IPMw+-O0;Q@eMMtjjQ+G6QfN3ae61Yd9LfQx_UREWecK4 zMn7A~fOz)be1)Yg{2Ysl9G%s8-h-~@C;ALAL0r=<JP2uCe!T|wAywH1r;F|f_q8N( zYp^0FkyL9uj<8bK@fyTtgo+DT)14B^<SigcSJotgDV02O!M(CS6_B&^bILwyV?Ng4 zm7WQp?{l<Obhuy=22?5<oQDiM22&u4rZrRVG|L9ABfY{=95aTyd~@a$o~1P#ji`=w zBKmQqX}r3Nlk9Q|gR7)~#n6AzYk`#!R*d5x`A)hU(!1R1%^zXxNJ(kPCw4htU9^(O zP4cYV^F(I>X|`1YNM9N8{>8JAu<en5+94bD>v}hp1v`3JHT-=5lbXpbMq7X~2J5Kl zh7tyU`_AusMFZ{ej9D;Uyy;SQ!4nwgSnngsYBwdS&EO3NS*o04)*j<g2BLf;iAZ2( z7Key$cc6ey>uAYl;57c2Ly0(DEZ8IY?zSph-kyxu+D`tt@oU{32J#I{vmy=#0ySPK zA+i(A3yl)qmTz*$dZi#y9FS;$;h%bY+;StNx{_R56Otq+?pGe^T^{5d7Gs&?`_r`8 zD&dzOA|j8@3<oPyCd}SOX6AZj_;pT>A&FR5U3*eQNBf<4^4W_iS_()*8b4aaUzfk2 zzIcMWSEjm;EPZPk{j{1>oXd}pXAj!NaRm8{Sjz!D=~q3WJ@vmt6ND_?HI~|wUS1j5 z9!S1MKr7%nxoJ3k`GB^7yV~*{n~O~n6($~x5Bu{7s|JyXbAyKI4+tO(zZYMslK;Zc zzeHGVl{`iP@jfSKq>R;{+djJ9n%$%EL()Uw+sykjNQdflkJZSjqV_QDWivbZS~S{K zkE@T^Jcv)Dfm93!mf$XYnCT--_A$zo9MOkPB6&diM8MwOfV?+ApNv`moV@nqn>&lv zYbN1-M|jc~sG|yLN^1R2=`+1ih3jCshg`iP&mY$GMTcY^W^T`WOCX!{-KHmZ#GiRH zYl{|+KLn5!PCLtBy~9i}`#d^gCDDx$+GQb~uc;V#K3OgbbOG0j5{BRG-si%Bo{@lB zGIt+Ain8^C`!*S0d0OSWVO+Z8<kqm;qPrHIJ!qB8;9h5*>9}}O8aFTZ>p&k}2gGCV zh#<$gswePFxWGT$4DC^8@84_e*^KT74?7n8!$8cg=sL$OlKr&HMh@Rr5%*Wr!xoOl zo7jItnj-xYgVTX)H1=A2bD(tle<tL7^Z!nJ*fwgn&QUe>EH57#V{xAeW_ezISg5OC zg=k>hOLA^urTH_e6*vSYRqCm$J{xo}-x3@HH;bsHD1Z`Pzvsn}%cvfw%Q(}h`Dgtb z0_J^niUmoCM5$*f)6}}qi(u;cPgxfyeV<wtcQgsqG?QDyA@6XXM7siU#+0#mP~AnX z9f=bMes~9>aaVmOsG<)5`6tzU4wyhF;k|~|x>7-2hXpVBpc5k{L4M`Wbe6Q?tr^*B z`Y*>6*&R#~%JlBIitlZ^qGe3s21~h3U|&k%%jeMM;6!~UH|+0+<5V-_zDqZQN7<fD zM2vP&&BMr(%$M51tLpycNES^{gnGn-o~t&>9?n?!Aj!Nj`YMO9?j>uqI9-Tex+nJD z%e0#Yca6(zqGUR|KITa?9x-#C0!JKJHO(+fy@1!B$%ZwJwncQW7vGYv?~!^`#L~Um zOL++>4qmqW`0Chc0T23G8|vO)tK=Z2`gvS4*qpqhIJCEv9i&&$09VO8YOz|oZ+ubd zNXVdLc&p=KsSgtmIPLN69P7xYkYQ1vJ?u1g)T!6Ru`k2wkdj*wDC)VryGu2=yb0?F z>q~~e>KZ0d<sP$M^)hrN7IC)eGuv*?pAk#*4fxII<8rIx545@9E}-};{IJdo*}!V1 zkUgWQp<TD%7(QQhWkf*vd;SiT1P@}N?jaoKEV?lzqfa1pG1Y^}ikjNMM*Kb?m5(n& zOz8{+G2z7JatI<J95R%#%#ATAzlwPl$?6)w6WH~ku?(FhO)k1eRlF4I5UqR?T`Iy= z_bVtkxqs3lQGny-BS%nkzwrXhI_M|P4l_VNVoMjVRoZ*0(JkMQ#AdJLFBj%$oTBx9 z_5|g_ll0@cfLf<j;&lJ>_#7f3UgV%9MY1}vMgF{B8yfE{HL*pMyhYF)WDZ^^3vS8F zGlOhs%g_~pS3=WQ#494@jAXwOtr^Y|TnQ5zki>qRG)(oPY*f}U_=ip_{qB0!%w7~G zWE!P4p3khyW-JJnE>eECuYfI?^d366Shq!Wm#x&jA<tFBO~aWRutYg|6S!-V%dvXb zjpm3-7^fYCzbWmx*ts$8ECu=f{D#|=T{2_Q?C-SVQTSi8ey{G^D$8U&*bY{vQ$kGG zq$8)>o>=HdCllE$>DPO0N;y#4G)D2y#B@5=N=+F%Xo2n{gKcPcK2!hP*^WSXl+ut; zyLvVoY>VL{H%Kd9^i~lsb8j4>$EllrparEOJNT?Ym>vJa$(P^tOG)5aVb_5w^*&M0 zYOJ`I`}<NkH4X@iCc57jNSqY3D>9}UoSnYg#E(&yyK(tqr^@n}qU2H2DhkK-`2He% zgXr_4kpXoQHxAO9S`wEdmqGU4j=1JdG!OixdqB4PPP6<nq;ZS)73s_@N{54U_<mt# zR{@UUroZJ1=lVB~3y%RbLLE=9Mh=pj4wNruVxXLk8pKH)JVr{Hbx`P1XQ>RXA}>GM zumruUUH|ZG2$bBj)Qluj&uB=dRb)?^qomw?Z$X%#D+Q*O97eHrgVB2*mR$bFBU`*} zIem?dM)i}raTFDn@5^caxE^XFXVhBePmH9fqcTi`TLaXiueH=@06sl}>F%}h9H_e9 z>^O?LxM1EjX}NVppaO@NNQr=AtHcH-BU{yBT_vejJ#J)l^cl69Z7$sk`82Zyw7Wxt z=~J?hZm{f@W}|96FUJfy65Gk8?^{^yjhOahUMCNNpt5DJw}ZKH7b!bGiFY9y6OY&T z_N)?Jj(MuLTN36ZCJ6<obtKS{VOOSzs>I5Xy7uVlrb$o*Z%=-)kPo9s?<^Yqz~!Z* z_mP<Y8YDC3(vm~>8(unFq65XSi!$@YtieSQ!<7IEOaA9VkKI?lA`*(nURv<D`3vIl zzk?RMHDq|}aqs!Q7n{<V(L>fKL8cX}-+~uw9|_5)uC2`ZHca<BJSyCJ7L7R3^ezpJ zixdU%^Arizo-zh;Lga89_J>eX7L8aG6Ghleg@F9aG%X$#g6^yP5apnB>YTz&EfS{q z9UVfSyEIczebC)qlVu5cOoMzS_jrC|)rQlAzK7sfiW0`M8mVIohazPE9Jzn*qPt%6 zZL8RELY@L09B83@Be;x5V-IHnn$}{RAT#<2JA%ttlk#^(%u}CGze|1JY5MPhbfnYG zIw%$XfBmA-<_pKLpGKwbRF$#P;@_)ech#>vj25sv25VM$ouo)?BXdRcO{)*OwTw)G zv43W~T6ekBMtUD%5Bm>`<n0ehww;K9t*_z=^iZoM2Gjm6Wx6QTWDzOX28g|i7p-G( znPo(pGb2-Hja^(5g>^Ltv!w4~65N!Ut5twl!Agrzyq4O2Fi3pUMtCU~>9gt_=h-f% z;1&OuSu?A_sJvIvQ+dZNo3?m1%b1+s&UAx?8sUHEe_sB7zkm4R%6)<@oYB_i5>3Ip zIA+?jVdX|zL{)?TGpx+=Ta>G80}0}Ax+722$XFNJsC1gcH56{8B)*)eU#r~HrC&}` z|EWW92&;6y;3}!L5zXa385@?-D%>dSvyK;?jqU2t_R3wvBW;$!j45uQ7tyEIQv<v( zw)qBpyRhiKBMR9HV)v2ZJdk>a;Db}r&bR3kqNSh)Q_$MJ#Uj3Gj1F;)sO|%6z#@<+ zi{pbYsYS#u`X$Nf($OS+lhw>xgjos1OnF^$-I$u;qhJswhH~p|ab*nO>zBrtb0ndn zxV0uh!LN`&xckTP+JW}gznSpU492)u+`f{9Yr)js`NmfYH#Wdtradc0TnKNz@Su!e zu$9}G_=ku;%4xk}eXl>)KgpuT>_<`Ud(A^a++K&pm3LbN;gI}ku@YVrA%FJBZ5$;m zobR8}OLtW4-i+qPPLS-(7<>M{)rhiPoi@?&vDeVq5%fmZk=mDdRV>Pb-l7pP1y6|J z8I>sF+TypKV=_<SBxSgNFy@5`t70+_4F<*(g54PNEt&4u%OoVR^n+$TL)qKdP6c)n z-CoP*_kXZ4vBsj8M^2Y0nDq-^4r-wgu2Y-3fmi6ooPIXTI%UdJhw@7KgR=N+Vl3NO zcl8-&i~^e%3E1G+u&^#M&5!sI)la$uQ2y&KsaZjx^r8D68BTZd^NrAV{0u$=#SH#4 zLE2)q%<UADH&I$um|>^NwBU^>4JJq<*14GLfM2*XQzYdlqqjnE)gZsPW^E@mp&ww* zW9i>XL=uwLVZ9pO*8K>t>vdL~Ek_NUL$?LQi5sc#1Q-f6-ywKcIT8Kw?C<o*=Aa~- z*eA0Mgmu5-j8rTh^;={1$#X=Ck5Gk;@KK#haYa^sXr0^_^Q84%+WOl3?#Mc#{{d}B z>(_3pbR`e|)%9S-({if|E+hR2W!&qfQ&UiF^I!|M#xhdWsen<tq75@@WHX{+T3S~F znoMw2v{^ia4`fkd=3p<6XkL)!lsI%8iq@>v^wpKCBiuxXbnp85`{i|;BM?Ba`lqTA zyRm=UWJl&E{8JzYDHFu>*Z10-?#A8D|5jW9Ho0*CAs0fAy~MqbwYuOq9jjt9*nuHI zbDwKvh)5Ir$r!fS5|;?Dt>V+@F*v8=TJJF)TdnC#Mk>+tGDGCw;A~^PC`gUt*<(|i zB{{g{`uFehu`$fm4)&k7`u{xIV)yvA(%5SxX9MS80p2EKnL<HSdiWFiAy=3UmV-rj zc%^|o`X!t!vuYErrUzbG?ostY(qs7GE^=Z33k*P+F6r($h_?W-bHJ|GUK@Wlv9++M zG}?Z?8{_X${_c9aOXw4qfk0vTaVRH6FMOnFD?w|zo{zKKg$8wzW&yufWk&idB=+9! z^dTI@g=>t<HJ%Cd%{u~X`lRpMFg&X{m?Nw#T4cg*?z{+rC($M4z9RHV@8KoueD7_) z8T@i-6RG$5%_Y`lSjj|?wSvITK5c4g0!Uq49VAn-H<9~;vn7~hBdYuDOt2$gtNuBm zo8$Y{2lwMxZNbfb$Hm0T528Og7Jfl!35edSr>CZ>tlX>*Z6nd&6-<c}7z{sZ9V^Ux zMNgR3$iH97>Mv$5rHD*<Fmux@1NkgiA%VmyOAwal{&*L*?*@Cl?&!jtcf3KL{{|8z z_($$R;SoAei#gUO@=7)M7s~2aAxJ>db;&IBK3KH&M<+ArlGXDRdX1VVO4)&R$f4<g z`M~bg9+=(|cc^a3vB10?3GZiq$o|Zromh?lE2%m!alG4CIrvmRZHZVSM>NxXI>GBh zSv|h>5GDAI(4E`@F?En<q4iBUtn-fux#Jt=qU6#PBE4-GhP)}OK!CI;i(sJ6^VIJF zwJMEAeGKMb_^`VbA1hFYio)roSCrLG-NL5Yqhb{sh3_zt(Zg93UP*;!m?}k&V`1AB zNYPri&yVkXW8uO1geXM3Oj&$G%~#Jd%h;?JDKwrq;P+!t&4W1Z^1?Ikguvk#bK?Bx z$w5M*LxgRe=jz?UiDBbfC1I3!cjeMD*ueh4W0S*z6=TAf+ZYkG$}FGti`ipjpIK>W zS>#c&Gw6~_XL`qQG4bK`W*>hek4LX*efn6|_MY+rXkNyAuu?NxS%L7~9tD3cn7&p( zCtfqe6sjB&Q-Vs7BP5+%;#Gk};4xtwU!KY0XXbmkUy$kR9)!~?*v)qw00!+Yg^#H> zc#8*z6zZo>+(bud?K<*!QO<vKd$8TBt^HLIw%iB>4ehiTCK&PD4G&n)Tr9X_3r-we z?fI+}-G~Yn93gI6F{}Dw_SC*FLZ)5(85zp4%uubtD)J)UELLkvGk4#tw&Tuss<g@J zd3(n+h;=s-joD7pea}*kl|?T5<3W!rK}V)#HpvFL3uRc{oe_mV<z1l~^m1_TkJDu3 z;JtNs6#g&&@E09TG{#Z`zh|EKwRTiJr)s50$5?Nrhn68HAr=rV#m>a)mTD$R2&O~{ zCI3>fr-!-b@EGRI%g0L8UU%%u_<;e9439JNV;4KSxd|78v+I+8^rmM<g+mx0&Si$a zgf1uYC03KcCN)Lz!>f3f40Jb}wEszROD?xBZu>Ll3;sUIoNxDK3|j3*sam2tC@@e$ z^!;+AK>efeBJB%ALsQ{uFui)oD<x}JL&L^@dTz{b&_?*nsS;lNnoJ@(k9d5xVq$|w z<ejC>oq()2USi?n=6C3#eetz?wPswc={I<8x=(8lE4EIsUfyGNZ{|KYn1IR|=E==f z(;!A5(-2y^2xRFCSPqzHAZn5RCN_bp22T(KEtjA(rFZ%>a4@STrHZflxKoqe9Z4@^ zM*scx_y73<sFS1_?6+u!sT9fvjld*kU~edMy>?Q{<Kw(x)TAd1JfBpLz7(Nk)Jsdz zj7#eyM{0^=a(C#N_pwZ(&^&zZP@5Qw`oUBRW0i<S2ql<0tEs~>vt6?~WEl?2q*;@8 z3M*&@%l)SQmXkcUm)d@GT2#JdzhfSAP9|n#C;$E8X|pwD!r#X?0P>0ZisQ~TNqupW z*lUY~+ikD`vQb?@SAWX#r*Y+;=_|oacL$2CL$^(mV}aKO77pg}O+-=T1oLBT5sL2i z42Qth<Jh0Ysw=K%u7GarF`3bIM1>2+0@C`c+*D0*5!qy26sis<9a7>LN2{z%Qj49t z=L@x`4$ALHb*3COHoT?5S_c(Hs}g!V>W^=6Q0}zaubkDn)(lTax0+!+%B}9Vqw6{H zvL|BRM`O<@;eVi1DzM!tXtBrA20Ce@^Jz|>%X-t`vi-%WweXCh_LhI#bUg2*pcP~R z*RuTUzBKLXO~~uMd&o$v3@d0shHfUjC6c539PE6rF&;Ufa(Rw@K1*m7?f5)t`MjH0 z)_V(cajV5Am>f!kWcI@5rE8t6$S>5M=k=aRZROH6fA^jJp~2NlR4;Q2>L$7F#RT#9 z>4@1RhWG`Khy>P2j1Yx^BBL{S`niMaxlSWV-JBU0-T9zZ%>7mR3l$~QV$({o0;jTI ze5=cN^!Bc2bT|BcojXp~K#2cM>OTe*cM{Kg-j*CkiW)EGQot^}s;cy8_1_@JA0Whq zlrNr+R;Efa+`6N)s5rH*|E)nYZ3uqkk2C(E7@A|3YI`ozP~9Lexx#*1(r8luq+YPk z{J}c$<WQa$CfVIhsE>s`<i2`cEPYHzF!ZIy?L$}MhAPFqQe@_8Lh#cQAH~-zZ5p$u zZauEKr<oluR2T6z2A|B^#roi2jr3F<X4&!ZjiXo?9nIbJ4iAii=A_@&#n$TqH^#R& z{$qMQO7u^&7KEB6l{H~A;ylPsJw2kA4#E2@7dO%lsi+3{VJ4?~e4(Bz-tw&^YR9P1 zTlpCH(W_%+@#|?%RN0HM=U?pU5$E2f<RPK1fw%3KLs--hd|lj})1h|Y<6CA3NsuSI zl=<<g*vcJW=6yZY`aXe5QUB~awgg5fxlu%7u#A8=UXt61U-7wGtR{L&XvKbUf-}PL z<eXA6<<r^;=`XwtFN1~2J^$Y${#Q0Tyev?j!*Z4q^mjQ4ah)uW_s=JkrRS%l*Ut`> zPM35Fx(YWB3Z5IYnN+L_4|jaR(5iWJi2~l&xy}aU7kW?o-V*6Av2wyZTG!E2KSW2* zGRLQkQU;Oz##ie-Z4fI)WSRxn$(ZcD;TL+;^r=a4(G~H3ZhK$lSXZj?cvyY8%d9JM zzc3#pD^W_QnWy#rx#;<pgDoauRid_B6w$J6XKKeAcZHU9rH9=s!y`%~e@hGc<c#A7 zRRTR`&dt`*;~VYcVGk-~aNB!?q#4B&%52?dI@=%LQ>c&N@sqHhrnHRmj<I9Tx4aSD zVUQ}9lh=Kd&QIx0uCqYm3pFs_*L;b|$xyZks(AAwgYsH85PAL~ndH7DNUoZKBHCWu z_<;@&ed^tpoO=DG4Hem|2>#i;s%zLm6SE(n&BWpd&f7>XnjV}OlZntI70fq%8~9<7 zMYaw`E-rp49-oC1N_uZTo)Cu%RR2QWdHpzQIcNsoDp`3xfP+`gI?tVQZ4X={qU?(n zV>0ASES^Xuc;9JBji{)RnFL(Lez;8XbB1uWaMp@p?7xhXk6V#!6B@aP4Rz7-K%a>i z?fvf}va_DGUXlI#4--`A3qK7J?-HwnG7O~H2;zR~RLW)_^#La!=}+>KW#anZ{|^D3 B7G?kd literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/glyphicons-halflings.png b/src/admin/application/templates/img/glyphicons-halflings.png new file mode 100644 index 0000000000000000000000000000000000000000..a9969993201f9cee63cf9f49217646347297b643 GIT binary patch literal 12799 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 literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/login-bkg.png b/src/admin/application/templates/img/login-bkg.png new file mode 100644 index 0000000000000000000000000000000000000000..28609645fdfa088d05e17bbfd6fa39c1a7ad02fe GIT binary patch literal 634 zcmeAS@N?(olHy`uVBq!ia0vp^M;RCxJ2`+12Kjv}`hgT@fk$L90|U1Z2s2)~TlWVj zsF3Ut<jcTNrOLq2(9FQ_^FNS&$-q!*z`*b-fq}tl1_Oh5{-pS$ZVU`e44y8IAr-gY z+;QwXWWd83AkLKZu0BG5$H3e}>E^<uFaK_N{XVdJeMz<ZA2<EnqzBhzcl7vs>^r3R z&shT-_;&W&xA=gNWk+33Ub??)?SkW;`<i+eEx-a!xN|!P&K48A{_cqX(bSoN{g3r{ zSh0Yk?=Bt+xRUlt@64~$M(+*<U;}UDba`BJ?Y_8f`Vu>1HFo<VWI$?`Ma@Vre;`r# zo^Q@^b)NYjwgie`1Ko>T7q0N_?&N!F`b%+=>Z!sQmc2P5SX{??^if8lM%HDeM;GT> z_=YGPZoDXd@{|7t?8cr1t9>M_diq1l6JhKIy4poablvjVYVdNBYQ6Zg#KqWxSwjpG zdO(wYH9lc9>uSORl;lA^&U$w!BN3}rN54PMXV`Q-?0wyZDUQH&!{F)a=d#Wzp$Pzr CTh}B2 literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/logo/logo-login.png b/src/admin/application/templates/img/logo/logo-login.png new file mode 100644 index 0000000000000000000000000000000000000000..460242da61078a00b91f30d63c808a171f3859ea GIT binary patch literal 4671 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 Bta|_e literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/logo/logo-metacms.png b/src/admin/application/templates/img/logo/logo-metacms.png new file mode 100644 index 0000000000000000000000000000000000000000..de912a2009c3c03332507f2a0f489306d308651a GIT binary patch literal 1343 zcmV-F1;F}=P)<h;3K|Lk000e1NJLTq002Y)000^Y1^@s64ww2h00004b3#c}2nYxW zd<bNS00009a7bBm000W`000W`0Ya=am;e9(9CSrkbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gGnm#!0{{R37<5HgbVG7wVRUJ4ZXi@?ZDjy5H7zhQEiy1MGxCAn6#xJP zl}SWFR9J=On9pk(X&A>p6GNjVVaIWkB`J1=-HkRCDx}w>)Bj)&IZUCjHn*fu`~w1s zkaH6X_RvG?(L-Q8^wfj33ON}%0kg!iP}yZ0aGTMtA&F^&dr+quXA&*VCT+hU`22WZ zpZ7cO`@COA$Uv2^7k92hw3`7vr&P#!!IKOGyBYAc69Qe5@+}YoU6Asv5CSz)mQP9& z%$n-R!U6z#EXMxkW}DC9_v7&Ujr_fAmc48iNmX0s*~?}ruB-siKRJoR@8_R~4?k@= zpAXUNaK|cWO2~M%<~l4E(Ikof$w|B~UI4Ha4&zi+>|U>tzn{zTW^Rs=#YMxvpUY8B zB=~c7wq?$Bmx~X&{<#+Ssjwua_qb6ur;{GLoxzzI)A*VowAjU!6|Qb>V)uI4@c9hC zb85=??v6xwed|`|rJoLh8NiGb%N}xAECS$~o<>qt!*0fSwaR$4%GLU@vciv#9&uPK zqQ_!w$Lb6b%)pbQPD?`G7Ygj8(_D^30Qh@ut}SOP9A+yV=8Z|LfnG_%=5+GDP~gI) zO8^YkkI^|m8!5-$GKB{Z0H{_floJWdyygab6z)2q0KG#)HQ)XF9n|{2p@o!V33>PQ zDFAODKQ@gI&(9klD@dx!PCCto&&P(($5uFu(AP)*<m4w+e@ZY&F}-EJL=4C>hous` znr0fm;PKGs@lZ}CkDDg?#S1f=C^DvL49GIW3k$fH+qIXdDEu6cBPt4G7KGIiJXVJ^ zuGOP9fZgXqQdL8IHEe)4brEOgb52d+@cUat-$@vdW#h@(M3Fv^$8sl(SF3GuU`*5a zLs2-$=kY|NY)7M(JLOm%Vg+w1MgPQvVeh2VloJV~m;9SZu#-yRTV2KGbOJR(0=jP4 z!}IfOT)EN_DemQEV?m;#a4`^IHxz2i8<1tnbphE7$F*x5<nsU=<nt{AABE|WSrdd7 zmYeOt*;)E0CeULs)&zmvjT_{SG|0i38G7t?WAX6u`fZF`cey&=A#bBmL`4B=+kZP6 zZHZqD1Q<;waW5}ZFgY^apz9tobnhO3p*D9?sh0R*v52IqxTdEK8{mVkv!BZ$sVV_o z$JvEIE5+k{9}HR^mt9Tcl`QjnAi&7N0v7{;)|%eE>-e`!2^k877;4&*&Gzogmq6`_ zo1r1#E=MBlq|>}F6pYx0&&RsUg&vD>ITGnupdIA%RPuR#2!(iiWOvv^@x<}vWRd|{ z2B2S-DaGTKxu%4;mzHoZEdjObs@eYQ?p*+`ZErJD?+e~k$`D=UM1pFi0(=y94Fq(Z zk;O$r$n9mbCoZOeQap|;7;IZipU1<PrZJjKGNx&i;&FC0jiFG8pX#|=_1kAm)7aBA z%Z3a!9r7EXG&@J1KL_B|&6}onuO#7JUB&M8Qms^Yefu^Jzu#z-!}Ie<s>+%m7=QL& zIvo7+?3vMwx58oL<~a@6L=l@P8qKs*2pRa5E?>lc%@6=G@EY)(Z7JsijUJ)^rL!#L zyr2i*I;;aSkUz^}&I4LBZU(-i_I6sKM$k8h{{Tpz(~ZU%$FKkZ002ovPDHLkV1gQD BbT0q^ literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/logo/logo-top.png b/src/admin/application/templates/img/logo/logo-top.png new file mode 100644 index 0000000000000000000000000000000000000000..1e019f69d244cbdce996d825b58300c8fbbf3c62 GIT binary patch literal 3099 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 P|HFWtl@p=Z!aMRmT`$l~ literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/menu-active.png b/src/admin/application/templates/img/menu-active.png new file mode 100644 index 0000000000000000000000000000000000000000..c96f7134e7188a4046f8fe35a00116c565e84a40 GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^96&6<!3HF?yX<O#6kC$Fy9>jA5L~c#`DCC7XMsm# zF#`kNVGw3Kp1&dmD9B#o>FdgVmr;;W$Z}$n-glsov!{z=h{pNeiH>{>3LJ+!{{L6X zUun+Vb-FB9IKibOMNNpw!-7lH?hx;6gM-R{6dGC>wC9`<yf*3D%&@?)tJgNK+QPUY W{3oZGTS7k2I0jEwKbLh*2~7aL);B!> literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/pool.png b/src/admin/application/templates/img/pool.png new file mode 100644 index 0000000000000000000000000000000000000000..a718b628e3f80db28f0a1de4d9a22d11ff4e4e7d GIT binary patch literal 1188 zcmeAS@N?(olHy`uVBq!ia0vp^atsVi5gcqlR_VI1UqFhb*vT`50|;t3QaXTq&H|6f zVg?3oArNM~bhqvgP*9@8HKN41C^fMpGe1uuBr`Xa!N^qCz)07~z|i<p<2_NJ8aa@f z;QX|b^2DN42FH~Aq*MjB%%art{G#k)1?ON>J;T-V9<Lb~n16V>IEGZrd3)18Lnc+? z_{aOwRhk_pAsSgn9VS+sNaTKWbT)hL#|gpN3opDmD8V1c6eghJseNO%?U$fi!TdoP zx_OtUe0#RFs&lH$7TYTc9T%L#g%k}{etzBXJ}1q5xAErPH=91xCP<Xsx1V1*ul&C3 zjET9b?%NZq?|hqF(Ubn=_QtB#-1_9|tJWK{e%Hh&-adZE&hA7L`z{Y7*<{Jw^i6Ev zxc1Mx_$|u*;nkjPQ|k`xFS~ioxJG?(u3qsIxt!(4b?Ywfe;!rMFg^N!ZvES8-u)@n zyE*GD`QK&s=E_eg2@J}}`gQJ`c4f2msT<!EZ%^L#eAYj$*~zBgW^Sp?n0}Qr=XdSx z(~=RpBl?nGhh;G2`@~(<zhA$|K%w>7tGBzjPTsz>()*INytwAIMN1Zzi1AAPzIHRe zHZSFL@$)xZr{2B3@8^75>s<f+x%zkBtGxbtC#bsYRm<|W?SBu8f2+!pG{5%d_59nx zhreCQ|9@*;S%J=W-BORK*T3uSS=hR}KI4DmU#r^4Teqg<)$7{+F7{QH=WTx+|2K5W zzTVZ7H{Ci|`sZZx{H>q9gy!aYG`Ii1Hu3vCUirG6S2S-4#>f{ueWH9*(dSOhYH0)U zx``KG-{q7*1wZQf+XbZfJX1YIJwrYFo_8%N+O6)EtNeG%+Mga@B{$j5ud<2Q`Zw4{ z-BA8_>baYrCMIcH_)TN5zolmyTcKGuKPEtN567GotGU5DUxqx}dvM$FNj}_q(UX2g ztS>MM)SSO|x^3j7Gdn-aX@;q4wirYRtm~gR#ZoO_UVg%t4IHz&+6!aSL{3_?2)q*h z8NBo1*2c93OTUS!o%`CKRc*7|Ywo&@>P^x~N*1Q!4^7W$m#WT7FZ!iA@yqIz(o<(G zwyFQFP}5GnZTxZez3+u{KKQ=>Qydy~aGUnWVAF5sTZ`ZODYm$Js$RXv-oNdonbd9X zReR%4^*U`oDsU)?<Kc>|^5tQHeQ#SY#O!c=xqj=*D&5FgwvE3fe_P2Vde7%Ise7kX i@t2ur1cE!IHtY$WnF=Nggk}Is3kFYDKbLh*2~7aBQ@!Z` literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/relation.png b/src/admin/application/templates/img/relation.png new file mode 100644 index 0000000000000000000000000000000000000000..6b445e54b3339f0a332ecd6ef502f643ee6ef6cd GIT binary patch literal 208 zcmeAS@N?(olHy`uVBq!ia0vp^oIo7J$P6U+h~=aMDdu7)&kzm{j@u9Y9{{;*0X`wF zXU?2?@Zdqq(oX?E5zYdS$YKTtZXpn6ymYtj4^U8|#5JPCxhOTUBr`uxAtW<5mBGkN z*U&)M$iUDjd`rbopc*-ln&AAjlJdl&R0hYC{G?O`x6Go{^8BLgVg=`5Q$54g@*b~& uDuq2=978x}CjYp9fWal)ormeSIK$n}+{ZZ=7bF6u89ZJ6T-G@yGywqQ;yzvg literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/up-arrow.png b/src/admin/application/templates/img/up-arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..9431f55c3870ba82c5bf0be99e86cba02d7bfb9e GIT binary patch literal 4047 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 F{7=0e*y;cP literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/img/up-down-arrow.png b/src/admin/application/templates/img/up-down-arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..f85343474dc9ef8e1d56e6d55fb8654f0fa24f41 GIT binary patch literal 4066 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 Z1Sr%ga_<nyVA~j+D1(#wMSAu@{{n~o-}3+f literal 0 HcmV?d00001 diff --git a/src/admin/application/templates/js/bootstrap.js b/src/admin/application/templates/js/bootstrap.js new file mode 100644 index 0000000..6c15a58 --- /dev/null +++ b/src/admin/application/templates/js/bootstrap.js @@ -0,0 +1,2159 @@ +/* =================================================== + * bootstrap-transition.js v2.2.2 + * 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.2.2 + * 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.2.2 + * 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.2.2 + * 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.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 + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + return this + } + + , to: function (pos) { + var $active = this.$element.find('.item.active') + , children = $active.parent().children() + , activePos = children.index($active) + , that = this + + if (pos > (children.length - 1) || pos < 0) return + + if (this.sliding) { + return this.$element.one('slid', function () { + that.to(pos) + }) + } + + if (activePos == pos) { + return this.pause().cycle() + } + + return this.slide(pos > activePos ? 'next' : 'prev', $(children[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] + }) + + if ($next.hasClass('active')) return + + 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.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]', 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()) + $target.carousel(options) + e.preventDefault() + }) + +}(window.jQuery);/* ============================================================= + * bootstrap-collapse.js v2.2.2 + * 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) 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) 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 = 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.2.2 + * 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)) 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) + $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 touchstart.dropdown.data-api', clearMenus) + .on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('touchstart.dropdown.data-api', '.dropdown-menu', function (e) { e.stopPropagation() }) + .on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle) + .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) + +}(window.jQuery);/* ========================================================= + * bootstrap-modal.js v2.2.2 + * 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 (that) { + this.$element + .hide() + .trigger('hidden') + + this.backdrop() + } + + , 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 = $('<div class="modal-backdrop ' + animate + '" />') + .appendTo(document.body) + + this.$backdrop.click( + this.options.backdrop == 'static' ? + $.proxy(this.$element[0].focus, this.$element[0]) + : $.proxy(this.hide, this) + ) + + if (doAnimate) this.$backdrop[0].offsetWidth // force reflow + + this.$backdrop.addClass('in') + + doAnimate ? + this.$backdrop.one($.support.transition.end, callback) : + callback() + + } else if (!this.isShown && this.$backdrop) { + this.$backdrop.removeClass('in') + + $.support.transition && this.$element.hasClass('fade')? + this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) : + this.removeBackdrop() + + } else if (callback) { + callback() + } + } + } + + + /* MODAL PLUGIN DEFINITION + * ======================= */ + + var old = $.fn.modal + + $.fn.modal = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('modal') + , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('modal', (data = new Modal(this, options))) + if (typeof option == 'string') data[option]() + else if (options.show) data.show() + }) + } + + $.fn.modal.defaults = { + backdrop: true + , keyboard: true + , show: true + } + + $.fn.modal.Constructor = Modal + + + /* MODAL NO CONFLICT + * ================= */ + + $.fn.modal.noConflict = function () { + $.fn.modal = old + return this + } + + + /* MODAL DATA-API + * ============== */ + + $(document).on('click.modal.data-api', '[data-toggle="modal"]', function (e) { + var $this = $(this) + , href = $this.attr('href') + , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7 + , option = $target.data('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data()) + + e.preventDefault() + + $target + .modal(option) + .one('hide', function () { + $this.focus() + }) + }) + +}(window.jQuery); +/* =========================================================== + * bootstrap-tooltip.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#tooltips + * Inspired by the original jQuery.tipsy by Jason Frame + * =========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* TOOLTIP PUBLIC CLASS DEFINITION + * =============================== */ + + var Tooltip = function (element, options) { + this.init('tooltip', element, options) + } + + Tooltip.prototype = { + + constructor: Tooltip + + , init: function (type, element, options) { + var eventIn + , eventOut + + this.type = type + this.$element = $(element) + this.options = this.getOptions(options) + this.enabled = true + + if (this.options.trigger == 'click') { + this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) + } else if (this.options.trigger != 'manual') { + eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus' + eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur' + this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + } + + this.options.selector ? + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : + this.fixTitle() + } + + , getOptions: function (options) { + options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data()) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { + show: options.delay + , hide: options.delay + } + } + + return options + } + + , enter: function (e) { + var self = $(e.currentTarget)[this.type](this._options).data(this.type) + + if (!self.options.delay || !self.options.delay.show) return self.show() + + clearTimeout(this.timeout) + self.hoverState = 'in' + this.timeout = setTimeout(function() { + if (self.hoverState == 'in') self.show() + }, self.options.delay.show) + } + + , leave: function (e) { + var self = $(e.currentTarget)[this.type](this._options).data(this.type) + + if (this.timeout) clearTimeout(this.timeout) + if (!self.options.delay || !self.options.delay.hide) return self.hide() + + self.hoverState = 'out' + this.timeout = setTimeout(function() { + if (self.hoverState == 'out') self.hide() + }, self.options.delay.hide) + } + + , show: function () { + var $tip + , inside + , pos + , actualWidth + , actualHeight + , placement + , tp + + if (this.hasContent() && this.enabled) { + $tip = this.tip() + this.setContent() + + if (this.options.animation) { + $tip.addClass('fade') + } + + placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + inside = /in/.test(placement) + + $tip + .detach() + .css({ top: 0, left: 0, display: 'block' }) + .insertAfter(this.$element) + + pos = this.getPosition(inside) + + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + + switch (inside ? placement.split(' ')[1] : placement) { + case 'bottom': + tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'top': + tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'left': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth} + break + case 'right': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} + break + } + + $tip + .offset(tp) + .addClass(placement) + .addClass('in') + } + } + + , setContent: function () { + var $tip = this.tip() + , title = this.getTitle() + + $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) + $tip.removeClass('fade in top bottom left right') + } + + , hide: function () { + var that = this + , $tip = this.tip() + + $tip.removeClass('in') + + function removeWithAnimation() { + var timeout = setTimeout(function () { + $tip.off($.support.transition.end).detach() + }, 500) + + $tip.one($.support.transition.end, function () { + clearTimeout(timeout) + $tip.detach() + }) + } + + $.support.transition && this.$tip.hasClass('fade') ? + removeWithAnimation() : + $tip.detach() + + return this + } + + , fixTitle: function () { + var $e = this.$element + if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title') + } + } + + , hasContent: function () { + return this.getTitle() + } + + , getPosition: function (inside) { + return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), { + width: this.$element[0].offsetWidth + , height: this.$element[0].offsetHeight + }) + } + + , getTitle: function () { + var title + , $e = this.$element + , o = this.options + + title = $e.attr('data-original-title') + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) + + return title + } + + , tip: function () { + return this.$tip = this.$tip || $(this.options.template) + } + + , validate: function () { + if (!this.$element[0].parentNode) { + this.hide() + this.$element = null + this.options = null + } + } + + , enable: function () { + this.enabled = true + } + + , disable: function () { + this.enabled = false + } + + , toggleEnabled: function () { + this.enabled = !this.enabled + } + + , toggle: function (e) { + var self = $(e.currentTarget)[this.type](this._options).data(this.type) + self[self.tip().hasClass('in') ? 'hide' : 'show']() + } + + , destroy: function () { + this.hide().$element.off('.' + this.type).removeData(this.type) + } + + } + + + /* TOOLTIP PLUGIN DEFINITION + * ========================= */ + + var old = $.fn.tooltip + + $.fn.tooltip = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('tooltip') + , options = typeof option == 'object' && option + if (!data) $this.data('tooltip', (data = new Tooltip(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.tooltip.Constructor = Tooltip + + $.fn.tooltip.defaults = { + animation: true + , placement: 'top' + , selector: false + , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' + , trigger: 'hover' + , title: '' + , delay: 0 + , html: false + } + + + /* TOOLTIP NO CONFLICT + * =================== */ + + $.fn.tooltip.noConflict = function () { + $.fn.tooltip = old + return this + } + +}(window.jQuery);/* =========================================================== + * bootstrap-popover.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#popovers + * =========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * =========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* POPOVER PUBLIC CLASS DEFINITION + * =============================== */ + + var Popover = function (element, options) { + this.init('popover', element, options) + } + + + /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js + ========================================== */ + + Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, { + + constructor: Popover + + , setContent: function () { + var $tip = this.tip() + , title = this.getTitle() + , content = this.getContent() + + $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) + $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content) + + $tip.removeClass('fade top bottom left right in') + } + + , hasContent: function () { + return this.getTitle() || this.getContent() + } + + , getContent: function () { + var content + , $e = this.$element + , o = this.options + + content = $e.attr('data-content') + || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content) + + return content + } + + , tip: function () { + if (!this.$tip) { + this.$tip = $(this.options.template) + } + return this.$tip + } + + , destroy: function () { + this.hide().$element.off('.' + this.type).removeData(this.type) + } + + }) + + + /* POPOVER PLUGIN DEFINITION + * ======================= */ + + var old = $.fn.popover + + $.fn.popover = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('popover') + , options = typeof option == 'object' && option + if (!data) $this.data('popover', (data = new Popover(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.popover.Constructor = Popover + + $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, { + placement: 'right' + , trigger: 'click' + , content: '' + , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"></div></div></div>' + }) + + + /* POPOVER NO CONFLICT + * =================== */ + + $.fn.popover.noConflict = function () { + $.fn.popover = old + return this + } + +}(window.jQuery);/* ============================================================= + * bootstrap-scrollspy.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#scrollspy + * ============================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* SCROLLSPY CLASS DEFINITION + * ========================== */ + + function ScrollSpy(element, options) { + var process = $.proxy(this.process, this) + , $element = $(element).is('body') ? $(window) : $(element) + , href + this.options = $.extend({}, $.fn.scrollspy.defaults, options) + this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process) + this.selector = (this.options.target + || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + || '') + ' .nav li > a' + this.$body = $('body') + this.refresh() + this.process() + } + + ScrollSpy.prototype = { + + constructor: ScrollSpy + + , refresh: function () { + var self = this + , $targets + + this.offsets = $([]) + this.targets = $([]) + + $targets = this.$body + .find(this.selector) + .map(function () { + var $el = $(this) + , href = $el.data('target') || $el.attr('href') + , $href = /^#\w/.test(href) && $(href) + return ( $href + && $href.length + && [[ $href.position().top + self.$scrollElement.scrollTop(), href ]] ) || null + }) + .sort(function (a, b) { return a[0] - b[0] }) + .each(function () { + self.offsets.push(this[0]) + self.targets.push(this[1]) + }) + } + + , process: function () { + var scrollTop = this.$scrollElement.scrollTop() + this.options.offset + , scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight + , maxScroll = scrollHeight - this.$scrollElement.height() + , offsets = this.offsets + , targets = this.targets + , activeTarget = this.activeTarget + , i + + if (scrollTop >= maxScroll) { + return activeTarget != (i = targets.last()[0]) + && this.activate ( i ) + } + + for (i = offsets.length; i--;) { + activeTarget != targets[i] + && scrollTop >= offsets[i] + && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) + && this.activate( targets[i] ) + } + } + + , activate: function (target) { + var active + , selector + + this.activeTarget = target + + $(this.selector) + .parent('.active') + .removeClass('active') + + selector = this.selector + + '[data-target="' + target + '"],' + + this.selector + '[href="' + target + '"]' + + active = $(selector) + .parent('li') + .addClass('active') + + if (active.parent('.dropdown-menu').length) { + active = active.closest('li.dropdown').addClass('active') + } + + active.trigger('activate') + } + + } + + + /* SCROLLSPY PLUGIN DEFINITION + * =========================== */ + + var old = $.fn.scrollspy + + $.fn.scrollspy = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('scrollspy') + , options = typeof option == 'object' && option + if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.scrollspy.Constructor = ScrollSpy + + $.fn.scrollspy.defaults = { + offset: 10 + } + + + /* SCROLLSPY NO CONFLICT + * ===================== */ + + $.fn.scrollspy.noConflict = function () { + $.fn.scrollspy = old + return this + } + + + /* SCROLLSPY DATA-API + * ================== */ + + $(window).on('load', function () { + $('[data-spy="scroll"]').each(function () { + var $spy = $(this) + $spy.scrollspy($spy.data()) + }) + }) + +}(window.jQuery);/* ======================================================== + * bootstrap-tab.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#tabs + * ======================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* TAB CLASS DEFINITION + * ==================== */ + + var Tab = function (element) { + this.element = $(element) + } + + Tab.prototype = { + + constructor: Tab + + , show: function () { + var $this = this.element + , $ul = $this.closest('ul:not(.dropdown-menu)') + , selector = $this.attr('data-target') + , previous + , $target + , e + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + if ( $this.parent('li').hasClass('active') ) return + + previous = $ul.find('.active:last a')[0] + + e = $.Event('show', { + relatedTarget: previous + }) + + $this.trigger(e) + + if (e.isDefaultPrevented()) return + + $target = $(selector) + + this.activate($this.parent('li'), $ul) + this.activate($target, $target.parent(), function () { + $this.trigger({ + type: 'shown' + , relatedTarget: previous + }) + }) + } + + , activate: function ( element, container, callback) { + var $active = container.find('> .active') + , transition = callback + && $.support.transition + && $active.hasClass('fade') + + function next() { + $active + .removeClass('active') + .find('> .dropdown-menu > .active') + .removeClass('active') + + element.addClass('active') + + if (transition) { + element[0].offsetWidth // reflow for transition + element.addClass('in') + } else { + element.removeClass('fade') + } + + if ( element.parent('.dropdown-menu') ) { + element.closest('li.dropdown').addClass('active') + } + + callback && callback() + } + + transition ? + $active.one($.support.transition.end, next) : + next() + + $active.removeClass('in') + } + } + + + /* TAB PLUGIN DEFINITION + * ===================== */ + + var old = $.fn.tab + + $.fn.tab = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('tab') + if (!data) $this.data('tab', (data = new Tab(this))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.tab.Constructor = Tab + + + /* TAB NO CONFLICT + * =============== */ + + $.fn.tab.noConflict = function () { + $.fn.tab = old + return this + } + + + /* TAB DATA-API + * ============ */ + + $(document).on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { + e.preventDefault() + $(this).tab('show') + }) + +}(window.jQuery);/* ============================================================= + * bootstrap-typeahead.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#typeahead + * ============================================================= + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function($){ + + "use strict"; // jshint ;_; + + + /* TYPEAHEAD PUBLIC CLASS DEFINITION + * ================================= */ + + var Typeahead = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, $.fn.typeahead.defaults, options) + this.matcher = this.options.matcher || this.matcher + this.sorter = this.options.sorter || this.sorter + this.highlighter = this.options.highlighter || this.highlighter + this.updater = this.options.updater || this.updater + this.source = this.options.source + this.$menu = $(this.options.menu) + this.shown = false + this.listen() + } + + Typeahead.prototype = { + + constructor: Typeahead + + , select: function () { + var val = this.$menu.find('.active').attr('data-value') + this.$element + .val(this.updater(val)) + .change() + return this.hide() + } + + , updater: function (item) { + return item + } + + , show: function () { + var pos = $.extend({}, this.$element.position(), { + height: this.$element[0].offsetHeight + }) + + this.$menu + .insertAfter(this.$element) + .css({ + top: pos.top + pos.height + , left: pos.left + }) + .show() + + this.shown = true + return this + } + + , hide: function () { + this.$menu.hide() + this.shown = false + return this + } + + , lookup: function (event) { + var items + + this.query = this.$element.val() + + if (!this.query || this.query.length < this.options.minLength) { + return this.shown ? this.hide() : this + } + + items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source + + return items ? this.process(items) : this + } + + , process: function (items) { + var that = this + + items = $.grep(items, function (item) { + return that.matcher(item) + }) + + items = this.sorter(items) + + if (!items.length) { + return this.shown ? this.hide() : this + } + + return this.render(items.slice(0, this.options.items)).show() + } + + , matcher: function (item) { + return ~item.toLowerCase().indexOf(this.query.toLowerCase()) + } + + , sorter: function (items) { + var beginswith = [] + , caseSensitive = [] + , caseInsensitive = [] + , item + + while (item = items.shift()) { + if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item) + else if (~item.indexOf(this.query)) caseSensitive.push(item) + else caseInsensitive.push(item) + } + + return beginswith.concat(caseSensitive, caseInsensitive) + } + + , highlighter: function (item) { + var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&') + return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) { + return '<strong>' + match + '</strong>' + }) + } + + , render: function (items) { + var that = this + + items = $(items).map(function (i, item) { + i = $(that.options.item).attr('data-value', item) + i.find('a').html(that.highlighter(item)) + return i[0] + }) + + items.first().addClass('active') + this.$menu.html(items) + return this + } + + , next: function (event) { + var active = this.$menu.find('.active').removeClass('active') + , next = active.next() + + if (!next.length) { + next = $(this.$menu.find('li')[0]) + } + + next.addClass('active') + } + + , prev: function (event) { + var active = this.$menu.find('.active').removeClass('active') + , prev = active.prev() + + if (!prev.length) { + prev = this.$menu.find('li').last() + } + + prev.addClass('active') + } + + , listen: function () { + this.$element + .on('blur', $.proxy(this.blur, this)) + .on('keypress', $.proxy(this.keypress, this)) + .on('keyup', $.proxy(this.keyup, this)) + + if (this.eventSupported('keydown')) { + this.$element.on('keydown', $.proxy(this.keydown, this)) + } + + this.$menu + .on('click', $.proxy(this.click, this)) + .on('mouseenter', 'li', $.proxy(this.mouseenter, this)) + } + + , eventSupported: function(eventName) { + var isSupported = eventName in this.$element + if (!isSupported) { + this.$element.setAttribute(eventName, 'return;') + isSupported = typeof this.$element[eventName] === 'function' + } + return isSupported + } + + , move: function (e) { + if (!this.shown) return + + switch(e.keyCode) { + case 9: // tab + case 13: // enter + case 27: // escape + e.preventDefault() + break + + case 38: // up arrow + e.preventDefault() + this.prev() + break + + case 40: // down arrow + e.preventDefault() + this.next() + break + } + + e.stopPropagation() + } + + , keydown: function (e) { + this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27]) + this.move(e) + } + + , keypress: function (e) { + if (this.suppressKeyPressRepeat) return + this.move(e) + } + + , keyup: function (e) { + switch(e.keyCode) { + case 40: // down arrow + case 38: // up arrow + case 16: // shift + case 17: // ctrl + case 18: // alt + break + + case 9: // tab + case 13: // enter + if (!this.shown) return + this.select() + break + + case 27: // escape + if (!this.shown) return + this.hide() + break + + default: + this.lookup() + } + + e.stopPropagation() + e.preventDefault() + } + + , blur: function (e) { + var that = this + setTimeout(function () { that.hide() }, 150) + } + + , click: function (e) { + e.stopPropagation() + e.preventDefault() + this.select() + } + + , mouseenter: function (e) { + this.$menu.find('.active').removeClass('active') + $(e.currentTarget).addClass('active') + } + + } + + + /* TYPEAHEAD PLUGIN DEFINITION + * =========================== */ + + var old = $.fn.typeahead + + $.fn.typeahead = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('typeahead') + , options = typeof option == 'object' && option + if (!data) $this.data('typeahead', (data = new Typeahead(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.typeahead.defaults = { + source: [] + , items: 8 + , menu: '<ul class="typeahead dropdown-menu"></ul>' + , item: '<li><a href="#"></a></li>' + , minLength: 1 + } + + $.fn.typeahead.Constructor = Typeahead + + + /* TYPEAHEAD NO CONFLICT + * =================== */ + + $.fn.typeahead.noConflict = function () { + $.fn.typeahead = old + return this + } + + + /* TYPEAHEAD DATA-API + * ================== */ + + $(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) { + var $this = $(this) + if ($this.data('typeahead')) return + e.preventDefault() + $this.typeahead($this.data()) + }) + +}(window.jQuery); +/* ========================================================== + * bootstrap-affix.js v2.2.2 + * http://twitter.github.com/bootstrap/javascript.html#affix + * ========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* AFFIX CLASS DEFINITION + * ====================== */ + + var Affix = function (element, options) { + this.options = $.extend({}, $.fn.affix.defaults, options) + this.$window = $(window) + .on('scroll.affix.data-api', $.proxy(this.checkPosition, this)) + .on('click.affix.data-api', $.proxy(function () { setTimeout($.proxy(this.checkPosition, this), 1) }, this)) + this.$element = $(element) + this.checkPosition() + } + + Affix.prototype.checkPosition = function () { + if (!this.$element.is(':visible')) return + + var scrollHeight = $(document).height() + , scrollTop = this.$window.scrollTop() + , position = this.$element.offset() + , offset = this.options.offset + , offsetBottom = offset.bottom + , offsetTop = offset.top + , reset = 'affix affix-top affix-bottom' + , affix + + if (typeof offset != 'object') offsetBottom = offsetTop = offset + if (typeof offsetTop == 'function') offsetTop = offset.top() + if (typeof offsetBottom == 'function') offsetBottom = offset.bottom() + + affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? + false : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? + 'bottom' : offsetTop != null && scrollTop <= offsetTop ? + 'top' : false + + if (this.affixed === affix) return + + this.affixed = affix + this.unpin = affix == 'bottom' ? position.top - scrollTop : null + + this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : '')) + } + + + /* AFFIX PLUGIN DEFINITION + * ======================= */ + + var old = $.fn.affix + + $.fn.affix = function (option) { + return this.each(function () { + var $this = $(this) + , data = $this.data('affix') + , options = typeof option == 'object' && option + if (!data) $this.data('affix', (data = new Affix(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.affix.Constructor = Affix + + $.fn.affix.defaults = { + offset: 0 + } + + + /* AFFIX NO CONFLICT + * ================= */ + + $.fn.affix.noConflict = function () { + $.fn.affix = old + return this + } + + + /* AFFIX DATA-API + * ============== */ + + $(window).on('load', function () { + $('[data-spy="affix"]').each(function () { + var $spy = $(this) + , data = $spy.data() + + data.offset = data.offset || {} + + data.offsetBottom && (data.offset.bottom = data.offsetBottom) + data.offsetTop && (data.offset.top = data.offsetTop) + + $spy.affix(data) + }) + }) + + +}(window.jQuery); \ No newline at end of file diff --git a/src/admin/application/templates/js/bootstrap.min.js b/src/admin/application/templates/js/bootstrap.min.js new file mode 100644 index 0000000..f1ddfd8 --- /dev/null +++ b/src/admin/application/templates/js/bootstrap.min.js @@ -0,0 +1,7 @@ +/** +* Bootstrap.js by @fat & @mdo +* plugins: bootstrap-transition.js, bootstrap-modal.js, bootstrap-dropdown.js, bootstrap-scrollspy.js, bootstrap-tab.js, bootstrap-tooltip.js, bootstrap-popover.js, bootstrap-affix.js, bootstrap-alert.js, bootstrap-button.js, bootstrap-collapse.js, bootstrap-carousel.js, bootstrap-typeahead.js +* Copyright 2012 Twitter, Inc. +* http://www.apache.org/licenses/LICENSE-2.0.txt +*/ +!function(a){a(function(){a.support.transition=function(){var a=function(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},c;for(c in b)if(a.style[c]!==undefined)return b[c]}();return a&&{end:a}}()})}(window.jQuery),!function(a){var b=function(b,c){this.options=c,this.$element=a(b).delegate('[data-dismiss="modal"]',"click.dismiss.modal",a.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};b.prototype={constructor:b,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var b=this,c=a.Event("show");this.$element.trigger(c);if(this.isShown||c.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var c=a.support.transition&&b.$element.hasClass("fade");b.$element.parent().length||b.$element.appendTo(document.body),b.$element.show(),c&&b.$element[0].offsetWidth,b.$element.addClass("in").attr("aria-hidden",!1),b.enforceFocus(),c?b.$element.one(a.support.transition.end,function(){b.$element.focus().trigger("shown")}):b.$element.focus().trigger("shown")})},hide:function(b){b&&b.preventDefault();var c=this;b=a.Event("hide"),this.$element.trigger(b);if(!this.isShown||b.isDefaultPrevented())return;this.isShown=!1,this.escape(),a(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),a.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var b=this;a(document).on("focusin.modal",function(a){b.$element[0]!==a.target&&!b.$element.has(a.target).length&&b.$element.focus()})},escape:function(){var a=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(b){b.which==27&&a.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var b=this,c=setTimeout(function(){b.$element.off(a.support.transition.end),b.hideModal()},500);this.$element.one(a.support.transition.end,function(){clearTimeout(c),b.hideModal()})},hideModal:function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop.remove(),this.$backdrop=null},backdrop:function(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('<div class="modal-backdrop '+d+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?a.proxy(this.$element[0].focus,this.$element[0]):a.proxy(this.hide,this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!b)return;e?this.$backdrop.one(a.support.transition.end,b):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b):b()):b&&b()}};var c=a.fn.modal;a.fn.modal=function(c){return this.each(function(){var d=a(this),e=d.data("modal"),f=a.extend({},a.fn.modal.defaults,d.data(),typeof c=="object"&&c);e||d.data("modal",e=new b(this,f)),typeof c=="string"?e[c]():f.show&&e.show()})},a.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f).one("hide",function(){c.focus()})})}(window.jQuery),!function(a){function d(){a(b).each(function(){e(a(this)).removeClass("open")})}function e(b){var c=b.attr("data-target"),d;c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,"")),d=c&&a(c);if(!d||!d.length)d=b.parent();return d}var b="[data-toggle=dropdown]",c=function(b){var c=a(b).on("click.dropdown.data-api",this.toggle);a("html").on("click.dropdown.data-api",function(){c.parent().removeClass("open")})};c.prototype={constructor:c,toggle:function(b){var c=a(this),f,g;if(c.is(".disabled, :disabled"))return;return f=e(c),g=f.hasClass("open"),d(),g||f.toggleClass("open"),c.focus(),!1},keydown:function(c){var d,f,g,h,i,j;if(!/(38|40|27)/.test(c.keyCode))return;d=a(this),c.preventDefault(),c.stopPropagation();if(d.is(".disabled, :disabled"))return;h=e(d),i=h.hasClass("open");if(!i||i&&c.keyCode==27)return c.which==27&&h.find(b).focus(),d.click();f=a("[role=menu] li:not(.divider):visible a",h);if(!f.length)return;j=f.index(f.filter(":focus")),c.keyCode==38&&j>0&&j--,c.keyCode==40&&j<f.length-1&&j++,~j||(j=0),f.eq(j).focus()}};var f=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var d=a(this),e=d.data("dropdown");e||d.data("dropdown",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.dropdown.Constructor=c,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=f,this},a(document).on("click.dropdown.data-api",d).on("click.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on(".dropdown-menu",function(a){a.stopPropagation()}).on("click.dropdown.data-api",b,c.prototype.toggle).on("keydown.dropdown.data-api",b+", [role=menu]",c.prototype.keydown)}(window.jQuery),!function(a){function b(b,c){var d=a.proxy(this.process,this),e=a(b).is("body")?a(window):a(b),f;this.options=a.extend({},a.fn.scrollspy.defaults,c),this.$scrollElement=e.on("scroll.scroll-spy.data-api",d),this.selector=(this.options.target||(f=a(b).attr("href"))&&f.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=a("body"),this.refresh(),this.process()}b.prototype={constructor:b,refresh:function(){var b=this,c;this.offsets=a([]),this.targets=a([]),c=this.$body.find(this.selector).map(function(){var c=a(this),d=c.data("target")||c.attr("href"),e=/^#\w/.test(d)&&a(d);return e&&e.length&&[[e.position().top+(!a.isWindow(b.$scrollElement.get(0))&&b.$scrollElement.scrollTop()),d]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},process:function(){var a=this.$scrollElement.scrollTop()+this.options.offset,b=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,c=b-this.$scrollElement.height(),d=this.offsets,e=this.targets,f=this.activeTarget,g;if(a>=c)return f!=(g=e.last()[0])&&this.activate(g);for(g=d.length;g--;)f!=e[g]&&a>=d[g]&&(!d[g+1]||a<=d[g+1])&&this.activate(e[g])},activate:function(b){var c,d;this.activeTarget=b,a(this.selector).parent(".active").removeClass("active"),d=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',c=a(d).parent("li").addClass("active"),c.parent(".dropdown-menu").length&&(c=c.closest("li.dropdown").addClass("active")),c.trigger("activate")}};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("scrollspy"),f=typeof c=="object"&&c;e||d.data("scrollspy",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.defaults={offset:10},a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),!function(a){var b=function(b){this.element=a(b)};b.prototype={constructor:b,show:function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target"),e,f,g;d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));if(b.parent("li").hasClass("active"))return;e=c.find(".active:last a")[0],g=a.Event("show",{relatedTarget:e}),b.trigger(g);if(g.isDefaultPrevented())return;f=a(d),this.activate(b.parent("li"),c),this.activate(f,f.parent(),function(){b.trigger({type:"shown",relatedTarget:e})})},activate:function(b,c,d){function g(){e.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),f?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var e=c.find("> .active"),f=d&&a.support.transition&&e.hasClass("fade");f?e.one(a.support.transition.end,g):g(),e.removeClass("in")}};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("tab");e||d.data("tab",e=new b(this)),typeof c=="string"&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery),!function(a){var b=function(a,b){this.init("tooltip",a,b)};b.prototype={constructor:b,init:function(b,c,d){var e,f,g,h,i;this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.enabled=!0,g=this.options.trigger.split(" ");for(i=g.length;i--;)h=g[i],h=="click"?this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this)):h!="manual"&&(e=h=="hover"?"mouseenter":"focus",f=h=="hover"?"mouseleave":"blur",this.$element.on(e+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(f+"."+this.type,this.options.selector,a.proxy(this.leave,this)));this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(b){return b=a.extend({},a.fn[this.type].defaults,this.$element.data(),b),b.delay&&typeof b.delay=="number"&&(b.delay={show:b.delay,hide:b.delay}),b},enter:function(b){var c=a(b.currentTarget)[this.type](this._options).data(this.type);if(!c.options.delay||!c.options.delay.show)return c.show();clearTimeout(this.timeout),c.hoverState="in",this.timeout=setTimeout(function(){c.hoverState=="in"&&c.show()},c.options.delay.show)},leave:function(b){var c=a(b.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!c.options.delay||!c.options.delay.hide)return c.hide();c.hoverState="out",this.timeout=setTimeout(function(){c.hoverState=="out"&&c.hide()},c.options.delay.hide)},show:function(){var b,c,d,e,f,g,h=a.Event("show");if(this.hasContent()&&this.enabled){this.$element.trigger(h);if(h.isDefaultPrevented())return;b=this.tip(),this.setContent(),this.options.animation&&b.addClass("fade"),f=typeof this.options.placement=="function"?this.options.placement.call(this,b[0],this.$element[0]):this.options.placement,b.detach().css({top:0,left:0,display:"block"}),this.options.container?b.appendTo(this.options.container):b.insertAfter(this.$element),c=this.getPosition(),d=b[0].offsetWidth,e=b[0].offsetHeight;switch(f){case"bottom":g={top:c.top+c.height,left:c.left+c.width/2-d/2};break;case"top":g={top:c.top-e,left:c.left+c.width/2-d/2};break;case"left":g={top:c.top+c.height/2-e/2,left:c.left-d};break;case"right":g={top:c.top+c.height/2-e/2,left:c.left+c.width}}this.applyPlacement(g,f),this.$element.trigger("shown")}},applyPlacement:function(a,b){var c=this.tip(),d=c[0].offsetWidth,e=c[0].offsetHeight,f,g,h,i;c.offset(a).addClass(b).addClass("in"),f=c[0].offsetWidth,g=c[0].offsetHeight,b=="top"&&g!=e&&(a.top=a.top+e-g,i=!0),b=="bottom"||b=="top"?(h=0,a.left<0&&(h=a.left*-2,a.left=0,c.offset(a),f=c[0].offsetWidth,g=c[0].offsetHeight),this.replaceArrow(h-d+f,f,"left")):this.replaceArrow(g-e,g,"top"),i&&c.offset(a)},replaceArrow:function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},setContent:function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},hide:function(){function e(){var b=setTimeout(function(){c.off(a.support.transition.end).detach()},500);c.one(a.support.transition.end,function(){clearTimeout(b),c.detach()})}var b=this,c=this.tip(),d=a.Event("hide");this.$element.trigger(d);if(d.isDefaultPrevented())return;return c.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?e():c.detach(),this.$element.trigger("hidden"),this},fixTitle:function(){var a=this.$element;(a.attr("title")||typeof a.attr("data-original-title")!="string")&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},hasContent:function(){return this.getTitle()},getPosition:function(){var b=this.$element[0];return a.extend({},typeof b.getBoundingClientRect=="function"?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},getTitle:function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||(typeof c.title=="function"?c.title.call(b[0]):c.title),a},tip:function(){return this.$tip=this.$tip||a(this.options.template)},arrow:function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(b){var c=b?a(b.currentTarget)[this.type](this._options).data(this.type):this;c.tip().hasClass("in")?c.hide():c.show()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("tooltip"),f=typeof c=="object"&&c;e||d.data("tooltip",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(window.jQuery),!function(a){var b=function(a,b){this.init("popover",a,b)};b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype,{constructor:b,setContent:function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var a,b=this.$element,c=this.options;return a=(typeof c.content=="function"?c.content.call(b[0]):c.content)||b.attr("data-content"),a},tip:function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("popover"),f=typeof c=="object"&&c;e||d.data("popover",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.defaults=a.extend({},a.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery),!function(a){var b=function(b,c){this.options=a.extend({},a.fn.affix.defaults,c),this.$window=a(window).on("scroll.affix.data-api",a.proxy(this.checkPosition,this)).on("click.affix.data-api",a.proxy(function(){setTimeout(a.proxy(this.checkPosition,this),1)},this)),this.$element=a(b),this.checkPosition()};b.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var b=a(document).height(),c=this.$window.scrollTop(),d=this.$element.offset(),e=this.options.offset,f=e.bottom,g=e.top,h="affix affix-top affix-bottom",i;typeof e!="object"&&(f=g=e),typeof g=="function"&&(g=e.top()),typeof f=="function"&&(f=e.bottom()),i=this.unpin!=null&&c+this.unpin<=d.top?!1:f!=null&&d.top+this.$element.height()>=b-f?"bottom":g!=null&&c<=g?"top":!1;if(this.affixed===i)return;this.affixed=i,this.unpin=i=="bottom"?d.top-c:null,this.$element.removeClass(h).addClass("affix"+(i?"-"+i:""))};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("affix"),f=typeof c=="object"&&c;e||d.data("affix",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.defaults={offset:0},a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery),!function(a){var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function f(){e.trigger("closed").remove()}var c=a(this),d=c.attr("data-target"),e;d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),e=a(d),b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.trigger(b=a.Event("close"));if(b.isDefaultPrevented())return;e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.on(a.support.transition.end,f):f()};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("alert");e||d.data("alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.alert.data-api",b,c.prototype.close)}(window.jQuery),!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a+="Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle")})}(window.jQuery),!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.collapse.defaults,c),this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.prototype={constructor:b,dimension:function(){var a=this.$element.hasClass("width");return a?"width":"height"},show:function(){var b,c,d,e;if(this.transitioning||this.$element.hasClass("in"))return;b=this.dimension(),c=a.camelCase(["scroll",b].join("-")),d=this.$parent&&this.$parent.find("> .accordion-group > .in");if(d&&d.length){e=d.data("collapse");if(e&&e.transitioning)return;d.collapse("hide"),e||d.data("collapse",null)}this.$element[b](0),this.transition("addClass",a.Event("show"),"shown"),a.support.transition&&this.$element[b](this.$element[0][c])},hide:function(){var b;if(this.transitioning||!this.$element.hasClass("in"))return;b=this.dimension(),this.reset(this.$element[b]()),this.transition("removeClass",a.Event("hide"),"hidden"),this.$element[b](0)},reset:function(a){var b=this.dimension();return this.$element.removeClass("collapse")[b](a||"auto")[0].offsetWidth,this.$element[a!==null?"addClass":"removeClass"]("collapse"),this},transition:function(b,c,d){var e=this,f=function(){c.type=="show"&&e.reset(),e.transitioning=0,e.$element.trigger(d)};this.$element.trigger(c);if(c.isDefaultPrevented())return;this.transitioning=1,this.$element[b]("in"),a.support.transition&&this.$element.hasClass("collapse")?this.$element.one(a.support.transition.end,f):f()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("collapse"),f=a.extend({},a.fn.collapse.defaults,d.data(),typeof c=="object"&&c);e||d.data("collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.defaults={toggle:!0},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e).data("collapse")?"toggle":c.data();c[a(e).hasClass("in")?"addClass":"removeClass"]("collapsed"),a(e).collapse(f)})}(window.jQuery),!function(a){var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.options.pause=="hover"&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.prototype={cycle:function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(b){var c=this.getActiveIndex(),d=this;if(b>this.$items.length-1||b<0)return;return this.sliding?this.$element.one("slid",function(){d.to(b)}):c==b?this.pause().cycle():this.slide(b>c?"next":"prev",a(this.$items[b]))},pause:function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this,j;this.sliding=!0,f&&this.pause(),e=e.length?e:this.$element.find(".item")[h](),j=a.Event("slide",{relatedTarget:e[0],direction:g});if(e.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")}));if(a.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(j);if(j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),this.$element.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)})}else{this.$element.trigger(j);if(j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("carousel"),f=a.extend({},a.fn.carousel.defaults,typeof c=="object"&&c),g=typeof c=="string"?c:f.slide;e||d.data("carousel",e=new b(this,f)),typeof c=="number"?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.defaults={interval:5e3,pause:"hover"},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),c.data()),g;e.carousel(f),(g=c.attr("data-slide-to"))&&e.data("carousel").pause().to(g).cycle(),b.preventDefault()})}(window.jQuery),!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.typeahead.defaults,c),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=a(this.options.menu),this.shown=!1,this.listen()};b.prototype={constructor:b,select:function(){var a=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(a)).change(),this.hide()},updater:function(a){return a},show:function(){var b=a.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:b.top+b.height,left:b.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(b){var c;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(c=a.isFunction(this.source)?this.source(this.query,a.proxy(this.process,this)):this.source,c?this.process(c):this)},process:function(b){var c=this;return b=a.grep(b,function(a){return c.matcher(a)}),b=this.sorter(b),b.length?this.render(b.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(a){return~a.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(a){var b=[],c=[],d=[],e;while(e=a.shift())e.toLowerCase().indexOf(this.query.toLowerCase())?~e.indexOf(this.query)?c.push(e):d.push(e):b.push(e);return b.concat(c,d)},highlighter:function(a){var b=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return a.replace(new RegExp("("+b+")","ig"),function(a,b){return"<strong>"+b+"</strong>"})},render:function(b){var c=this;return b=a(b).map(function(b,d){return b=a(c.options.item).attr("data-value",d),b.find("a").html(c.highlighter(d)),b[0]}),b.first().addClass("active"),this.$menu.html(b),this},next:function(b){var c=this.$menu.find(".active").removeClass("active"),d=c.next();d.length||(d=a(this.$menu.find("li")[0])),d.addClass("active")},prev:function(a){var b=this.$menu.find(".active").removeClass("active"),c=b.prev();c.length||(c=this.$menu.find("li").last()),c.addClass("active")},listen:function(){this.$element.on("focus",a.proxy(this.focus,this)).on("blur",a.proxy(this.blur,this)).on("keypress",a.proxy(this.keypress,this)).on("keyup",a.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",a.proxy(this.keydown,this)),this.$menu.on("click",a.proxy(this.click,this)).on("mouseenter","li",a.proxy(this.mouseenter,this)).on("mouseleave","li",a.proxy(this.mouseleave,this))},eventSupported:function(a){var b=a in this.$element;return b||(this.$element.setAttribute(a,"return;"),b=typeof this.$element[a]=="function"),b},move:function(a){if(!this.shown)return;switch(a.keyCode){case 9:case 13:case 27:a.preventDefault();break;case 38:a.preventDefault(),this.prev();break;case 40:a.preventDefault(),this.next()}a.stopPropagation()},keydown:function(b){this.suppressKeyPressRepeat=~a.inArray(b.keyCode,[40,38,9,13,27]),this.move(b)},keypress:function(a){if(this.suppressKeyPressRepeat)return;this.move(a)},keyup:function(a){switch(a.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}a.stopPropagation(),a.preventDefault()},focus:function(a){this.focused=!0},blur:function(a){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(a){a.stopPropagation(),a.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(b){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),a(b.currentTarget).addClass("active")},mouseleave:function(a){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var c=a.fn.typeahead;a.fn.typeahead=function(c){return this.each(function(){var d=a(this),e=d.data("typeahead"),f=typeof c=="object"&&c;e||d.data("typeahead",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},a.fn.typeahead.Constructor=b,a.fn.typeahead.noConflict=function(){return a.fn.typeahead=c,this},a(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(b){var c=a(this);if(c.data("typeahead"))return;c.typeahead(c.data())})}(window.jQuery) \ No newline at end of file diff --git a/src/admin/application/templates/js/jqBootstrapValidation.js b/src/admin/application/templates/js/jqBootstrapValidation.js new file mode 100644 index 0000000..29cbb08 --- /dev/null +++ b/src/admin/application/templates/js/jqBootstrapValidation.js @@ -0,0 +1,912 @@ +/* jqBootstrapValidation + * A plugin for automating validation on Twitter Bootstrap formatted forms. + * + * v1.3.6 + * + * License: MIT <http://opensource.org/licenses/mit-license.php> - see LICENSE file + * + * http://ReactiveRaven.github.com/jqBootstrapValidation/ + */ + +(function( $ ){ + + var createdElements = []; + + var defaults = { + options: { + prependExistingHelpBlock: false, + sniffHtml: true, // sniff for 'required', 'maxlength', etc + preventSubmit: true, // stop the form submit event from firing if validation fails + submitError: false, // function called if there is an error when trying to submit + submitSuccess: false, // function called just before a successful submit event is sent to the server + semanticallyStrict: false, // set to true to tidy up generated HTML output + autoAdd: { + helpBlocks: true + }, + filter: function () { + // return $(this).is(":visible"); // only validate elements you can see + return true; // validate everything + } + }, + methods: { + init : function( options ) { + + var settings = $.extend(true, {}, defaults); + + settings.options = $.extend(true, settings.options, options); + + var $siblingElements = this; + + var uniqueForms = $.unique( + $siblingElements.map( function () { + return $(this).parents("form")[0]; + }).toArray() + ); + + $(uniqueForms).bind("submit", function (e) { + var $form = $(this); + var warningsFound = 0; + var $inputs = $form.find("input,textarea,select").not("[type=submit],[type=image]").filter(settings.options.filter); + $inputs.trigger("submit.validation").trigger("validationLostFocus.validation"); + + $inputs.each(function (i, el) { + var $this = $(el), + $controlGroup = $this.parents(".control-group").first(); + if ( + $controlGroup.hasClass("warning") + ) { + $controlGroup.removeClass("warning").addClass("error"); + warningsFound++; + } + }); + + $inputs.trigger("validationLostFocus.validation"); + + if (warningsFound) { + if (settings.options.preventSubmit) { + e.preventDefault(); + } + $form.addClass("error"); + if ($.isFunction(settings.options.submitError)) { + settings.options.submitError($form, e, $inputs.jqBootstrapValidation("collectErrors", true)); + } + } else { + $form.removeClass("error"); + if ($.isFunction(settings.options.submitSuccess)) { + settings.options.submitSuccess($form, e); + } + } + }); + + return this.each(function(){ + + // Get references to everything we're interested in + var $this = $(this), + $controlGroup = $this.parents(".control-group").first(), + $helpBlock = $controlGroup.find(".help-block").first(), + $form = $this.parents("form").first(), + validatorNames = []; + + // create message container if not exists + if (!$helpBlock.length && settings.options.autoAdd && settings.options.autoAdd.helpBlocks) { + $helpBlock = $('<div class="help-block" />'); + $controlGroup.find('.controls').append($helpBlock); + createdElements.push($helpBlock[0]); + } + + // ============================================================= + // SNIFF HTML FOR VALIDATORS + // ============================================================= + + // *snort sniff snuffle* + + if (settings.options.sniffHtml) { + var message = ""; + // --------------------------------------------------------- + // PATTERN + // --------------------------------------------------------- + if ($this.attr("pattern") !== undefined) { + message = "Not in the expected format<!-- data-validation-pattern-message to override -->"; + if ($this.data("validationPatternMessage")) { + message = $this.data("validationPatternMessage"); + } + $this.data("validationPatternMessage", message); + $this.data("validationPatternRegex", $this.attr("pattern")); + } + // --------------------------------------------------------- + // MAX + // --------------------------------------------------------- + if ($this.attr("max") !== undefined || $this.attr("aria-valuemax") !== undefined) { + var max = ($this.attr("max") !== undefined ? $this.attr("max") : $this.attr("aria-valuemax")); + message = "Too high: Maximum of '" + max + "'<!-- data-validation-max-message to override -->"; + if ($this.data("validationMaxMessage")) { + message = $this.data("validationMaxMessage"); + } + $this.data("validationMaxMessage", message); + $this.data("validationMaxMax", max); + } + // --------------------------------------------------------- + // MIN + // --------------------------------------------------------- + if ($this.attr("min") !== undefined || $this.attr("aria-valuemin") !== undefined) { + var min = ($this.attr("min") !== undefined ? $this.attr("min") : $this.attr("aria-valuemin")); + message = "Too low: Minimum of '" + min + "'<!-- data-validation-min-message to override -->"; + if ($this.data("validationMinMessage")) { + message = $this.data("validationMinMessage"); + } + $this.data("validationMinMessage", message); + $this.data("validationMinMin", min); + } + // --------------------------------------------------------- + // MAXLENGTH + // --------------------------------------------------------- + if ($this.attr("maxlength") !== undefined) { + message = "Too long: Maximum of '" + $this.attr("maxlength") + "' characters<!-- data-validation-maxlength-message to override -->"; + if ($this.data("validationMaxlengthMessage")) { + message = $this.data("validationMaxlengthMessage"); + } + $this.data("validationMaxlengthMessage", message); + $this.data("validationMaxlengthMaxlength", $this.attr("maxlength")); + } + // --------------------------------------------------------- + // MINLENGTH + // --------------------------------------------------------- + if ($this.attr("minlength") !== undefined) { + message = "Too short: Minimum of '" + $this.attr("minlength") + "' characters<!-- data-validation-minlength-message to override -->"; + if ($this.data("validationMinlengthMessage")) { + message = $this.data("validationMinlengthMessage"); + } + $this.data("validationMinlengthMessage", message); + $this.data("validationMinlengthMinlength", $this.attr("minlength")); + } + // --------------------------------------------------------- + // REQUIRED + // --------------------------------------------------------- + if ($this.attr("required") !== undefined || $this.attr("aria-required") !== undefined) { + message = settings.builtInValidators.required.message; + if ($this.data("validationRequiredMessage")) { + message = $this.data("validationRequiredMessage"); + } + $this.data("validationRequiredMessage", message); + } + // --------------------------------------------------------- + // NUMBER + // --------------------------------------------------------- + if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "number") { + message = settings.builtInValidators.number.message; + if ($this.data("validationNumberMessage")) { + message = $this.data("validationNumberMessage"); + } + $this.data("validationNumberMessage", message); + } + // --------------------------------------------------------- + // EMAIL + // --------------------------------------------------------- + if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "email") { + message = "Not a valid email address<!-- data-validator-validemail-message to override -->"; + if ($this.data("validationValidemailMessage")) { + message = $this.data("validationValidemailMessage"); + } else if ($this.data("validationEmailMessage")) { + message = $this.data("validationEmailMessage"); + } + $this.data("validationValidemailMessage", message); + } + // --------------------------------------------------------- + // MINCHECKED + // --------------------------------------------------------- + if ($this.attr("minchecked") !== undefined) { + message = "Not enough options checked; Minimum of '" + $this.attr("minchecked") + "' required<!-- data-validation-minchecked-message to override -->"; + if ($this.data("validationMincheckedMessage")) { + message = $this.data("validationMincheckedMessage"); + } + $this.data("validationMincheckedMessage", message); + $this.data("validationMincheckedMinchecked", $this.attr("minchecked")); + } + // --------------------------------------------------------- + // MAXCHECKED + // --------------------------------------------------------- + if ($this.attr("maxchecked") !== undefined) { + message = "Too many options checked; Maximum of '" + $this.attr("maxchecked") + "' required<!-- data-validation-maxchecked-message to override -->"; + if ($this.data("validationMaxcheckedMessage")) { + message = $this.data("validationMaxcheckedMessage"); + } + $this.data("validationMaxcheckedMessage", message); + $this.data("validationMaxcheckedMaxchecked", $this.attr("maxchecked")); + } + } + + // ============================================================= + // COLLECT VALIDATOR NAMES + // ============================================================= + + // Get named validators + if ($this.data("validation") !== undefined) { + validatorNames = $this.data("validation").split(","); + } + + // Get extra ones defined on the element's data attributes + $.each($this.data(), function (i, el) { + var parts = i.replace(/([A-Z])/g, ",$1").split(","); + if (parts[0] === "validation" && parts[1]) { + validatorNames.push(parts[1]); + } + }); + + // ============================================================= + // NORMALISE VALIDATOR NAMES + // ============================================================= + + var validatorNamesToInspect = validatorNames; + var newValidatorNamesToInspect = []; + + do // repeatedly expand 'shortcut' validators into their real validators + { + // Uppercase only the first letter of each name + $.each(validatorNames, function (i, el) { + validatorNames[i] = formatValidatorName(el); + }); + + // Remove duplicate validator names + validatorNames = $.unique(validatorNames); + + // Pull out the new validator names from each shortcut + newValidatorNamesToInspect = []; + $.each(validatorNamesToInspect, function(i, el) { + if ($this.data("validation" + el + "Shortcut") !== undefined) { + // Are these custom validators? + // Pull them out! + $.each($this.data("validation" + el + "Shortcut").split(","), function(i2, el2) { + newValidatorNamesToInspect.push(el2); + }); + } else if (settings.builtInValidators[el.toLowerCase()]) { + // Is this a recognised built-in? + // Pull it out! + var validator = settings.builtInValidators[el.toLowerCase()]; + if (validator.type.toLowerCase() === "shortcut") { + $.each(validator.shortcut.split(","), function (i, el) { + el = formatValidatorName(el); + newValidatorNamesToInspect.push(el); + validatorNames.push(el); + }); + } + } + }); + + validatorNamesToInspect = newValidatorNamesToInspect; + + } while (validatorNamesToInspect.length > 0) + + // ============================================================= + // SET UP VALIDATOR ARRAYS + // ============================================================= + + var validators = {}; + + $.each(validatorNames, function (i, el) { + // Set up the 'override' message + var message = $this.data("validation" + el + "Message"); + var hasOverrideMessage = (message !== undefined); + var foundValidator = false; + message = + ( + message + ? message + : "'" + el + "' validation failed <!-- Add attribute 'data-validation-" + el.toLowerCase() + "-message' to input to change this message -->" + ) + ; + + $.each( + settings.validatorTypes, + function (validatorType, validatorTemplate) { + if (validators[validatorType] === undefined) { + validators[validatorType] = []; + } + if (!foundValidator && $this.data("validation" + el + formatValidatorName(validatorTemplate.name)) !== undefined) { + validators[validatorType].push( + $.extend( + true, + { + name: formatValidatorName(validatorTemplate.name), + message: message + }, + validatorTemplate.init($this, el) + ) + ); + foundValidator = true; + } + } + ); + + if (!foundValidator && settings.builtInValidators[el.toLowerCase()]) { + + var validator = $.extend(true, {}, settings.builtInValidators[el.toLowerCase()]); + if (hasOverrideMessage) { + validator.message = message; + } + var validatorType = validator.type.toLowerCase(); + + if (validatorType === "shortcut") { + foundValidator = true; + } else { + $.each( + settings.validatorTypes, + function (validatorTemplateType, validatorTemplate) { + if (validators[validatorTemplateType] === undefined) { + validators[validatorTemplateType] = []; + } + if (!foundValidator && validatorType === validatorTemplateType.toLowerCase()) { + $this.data("validation" + el + formatValidatorName(validatorTemplate.name), validator[validatorTemplate.name.toLowerCase()]); + validators[validatorType].push( + $.extend( + validator, + validatorTemplate.init($this, el) + ) + ); + foundValidator = true; + } + } + ); + } + } + + if (! foundValidator) { + $.error("Cannot find validation info for '" + el + "'"); + } + }); + + // ============================================================= + // STORE FALLBACK VALUES + // ============================================================= + + $helpBlock.data( + "original-contents", + ( + $helpBlock.data("original-contents") + ? $helpBlock.data("original-contents") + : $helpBlock.html() + ) + ); + + $helpBlock.data( + "original-role", + ( + $helpBlock.data("original-role") + ? $helpBlock.data("original-role") + : $helpBlock.attr("role") + ) + ); + + $controlGroup.data( + "original-classes", + ( + $controlGroup.data("original-clases") + ? $controlGroup.data("original-classes") + : $controlGroup.attr("class") + ) + ); + + $this.data( + "original-aria-invalid", + ( + $this.data("original-aria-invalid") + ? $this.data("original-aria-invalid") + : $this.attr("aria-invalid") + ) + ); + + // ============================================================= + // VALIDATION + // ============================================================= + + $this.bind( + "validation.validation", + function (event, params) { + + var value = getValue($this); + + // Get a list of the errors to apply + var errorsFound = []; + + $.each(validators, function (validatorType, validatorTypeArray) { + if (value || value.length || (params && params.includeEmpty) || (!!settings.validatorTypes[validatorType].blockSubmit && params && !!params.submitting)) { + $.each(validatorTypeArray, function (i, validator) { + if (settings.validatorTypes[validatorType].validate($this, value, validator)) { + errorsFound.push(validator.message); + } + }); + } + }); + + return errorsFound; + } + ); + + $this.bind( + "getValidators.validation", + function () { + return validators; + } + ); + + // ============================================================= + // WATCH FOR CHANGES + // ============================================================= + $this.bind( + "submit.validation", + function () { + return $this.triggerHandler("change.validation", {submitting: true}); + } + ); + $this.bind( + [ + "keyup", + "focus", + "blur", + "click", + "keydown", + "keypress", + "change" + ].join(".validation ") + ".validation", + function (e, params) { + + var value = getValue($this); + + var errorsFound = []; + + $controlGroup.find("input,textarea,select").each(function (i, el) { + var oldCount = errorsFound.length; + $.each($(el).triggerHandler("validation.validation", params), function (j, message) { + errorsFound.push(message); + }); + if (errorsFound.length > oldCount) { + $(el).attr("aria-invalid", "true"); + } else { + var original = $this.data("original-aria-invalid"); + $(el).attr("aria-invalid", (original !== undefined ? original : false)); + } + }); + + $form.find("input,select,textarea").not($this).not("[name=\"" + $this.attr("name") + "\"]").trigger("validationLostFocus.validation"); + + errorsFound = $.unique(errorsFound.sort()); + + // Were there any errors? + if (errorsFound.length) { + // Better flag it up as a warning. + $controlGroup.removeClass("success error").addClass("warning"); + + // How many errors did we find? + if (settings.options.semanticallyStrict && errorsFound.length === 1) { + // Only one? Being strict? Just output it. + $helpBlock.html(errorsFound[0] + + ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" )); + } else { + // Multiple? Being sloppy? Glue them together into an UL. + $helpBlock.html("<ul role=\"alert\"><li>" + errorsFound.join("</li><li>") + "</li></ul>" + + ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" )); + } + } else { + $controlGroup.removeClass("warning error success"); + if (value.length > 0) { + $controlGroup.addClass("success"); + } + $helpBlock.html($helpBlock.data("original-contents")); + } + + if (e.type === "blur") { + $controlGroup.removeClass("success"); + } + } + ); + $this.bind("validationLostFocus.validation", function () { + $controlGroup.removeClass("success"); + }); + }); + }, + destroy : function( ) { + + return this.each( + function() { + + var + $this = $(this), + $controlGroup = $this.parents(".control-group").first(), + $helpBlock = $controlGroup.find(".help-block").first(); + + // remove our events + $this.unbind('.validation'); // events are namespaced. + // reset help text + $helpBlock.html($helpBlock.data("original-contents")); + // reset classes + $controlGroup.attr("class", $controlGroup.data("original-classes")); + // reset aria + $this.attr("aria-invalid", $this.data("original-aria-invalid")); + // reset role + $helpBlock.attr("role", $this.data("original-role")); + // remove all elements we created + if (createdElements.indexOf($helpBlock[0]) > -1) { + $helpBlock.remove(); + } + + } + ); + + }, + collectErrors : function(includeEmpty) { + + var errorMessages = {}; + this.each(function (i, el) { + var $el = $(el); + var name = $el.attr("name"); + var errors = $el.triggerHandler("validation.validation", {includeEmpty: true}); + errorMessages[name] = $.extend(true, errors, errorMessages[name]); + }); + + $.each(errorMessages, function (i, el) { + if (el.length === 0) { + delete errorMessages[i]; + } + }); + + return errorMessages; + + }, + hasErrors: function() { + + var errorMessages = []; + + this.each(function (i, el) { + errorMessages = errorMessages.concat( + $(el).triggerHandler("getValidators.validation") ? $(el).triggerHandler("validation.validation", {submitting: true}) : [] + ); + }); + + return (errorMessages.length > 0); + }, + override : function (newDefaults) { + defaults = $.extend(true, defaults, newDefaults); + } + }, + validatorTypes: { + callback: { + name: "callback", + init: function ($this, name) { + return { + validatorName: name, + callback: $this.data("validation" + name + "Callback"), + lastValue: $this.val(), + lastValid: true, + lastFinished: true + }; + }, + validate: function ($this, value, validator) { + if (validator.lastValue === value && validator.lastFinished) { + return !validator.lastValid; + } + + if (validator.lastFinished === true) + { + validator.lastValue = value; + validator.lastValid = true; + validator.lastFinished = false; + + var rrjqbvValidator = validator; + var rrjqbvThis = $this; + executeFunctionByName( + validator.callback, + window, + $this, + value, + function (data) { + if (rrjqbvValidator.lastValue === data.value) { + rrjqbvValidator.lastValid = data.valid; + if (data.message) { + rrjqbvValidator.message = data.message; + } + rrjqbvValidator.lastFinished = true; + rrjqbvThis.data("validation" + rrjqbvValidator.validatorName + "Message", rrjqbvValidator.message); + // Timeout is set to avoid problems with the events being considered 'already fired' + setTimeout(function () { + rrjqbvThis.trigger("change.validation"); + }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst + } + } + ); + } + + return false; + + } + }, + ajax: { + name: "ajax", + init: function ($this, name) { + return { + validatorName: name, + url: $this.data("validation" + name + "Ajax"), + lastValue: $this.val(), + lastValid: true, + lastFinished: true + }; + }, + validate: function ($this, value, validator) { + if (""+validator.lastValue === ""+value && validator.lastFinished === true) { + return validator.lastValid === false; + } + + if (validator.lastFinished === true) + { + validator.lastValue = value; + validator.lastValid = true; + validator.lastFinished = false; + $.ajax({ + url: validator.url, + data: "value=" + value + "&field=" + $this.attr("name"), + dataType: "json", + success: function (data) { + if (""+validator.lastValue === ""+data.value) { + validator.lastValid = !!(data.valid); + if (data.message) { + validator.message = data.message; + } + validator.lastFinished = true; + $this.data("validation" + validator.validatorName + "Message", validator.message); + // Timeout is set to avoid problems with the events being considered 'already fired' + setTimeout(function () { + $this.trigger("change.validation"); + }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst + } + }, + failure: function () { + validator.lastValid = true; + validator.message = "ajax call failed"; + validator.lastFinished = true; + $this.data("validation" + validator.validatorName + "Message", validator.message); + // Timeout is set to avoid problems with the events being considered 'already fired' + setTimeout(function () { + $this.trigger("change.validation"); + }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst + } + }); + } + + return false; + + } + }, + regex: { + name: "regex", + init: function ($this, name) { + return {regex: regexFromString($this.data("validation" + name + "Regex"))}; + }, + validate: function ($this, value, validator) { + return (!validator.regex.test(value) && ! validator.negative) + || (validator.regex.test(value) && validator.negative); + } + }, + required: { + name: "required", + init: function ($this, name) { + return {}; + }, + validate: function ($this, value, validator) { + return !!(value.length === 0 && ! validator.negative) + || !!(value.length > 0 && validator.negative); + }, + blockSubmit: true + }, + match: { + name: "match", + init: function ($this, name) { + var element = $this.parents("form").first().find("[name=\"" + $this.data("validation" + name + "Match") + "\"]").first(); + element.bind("validation.validation", function () { + $this.trigger("change.validation", {submitting: true}); + }); + return {"element": element}; + }, + validate: function ($this, value, validator) { + return (value !== validator.element.val() && ! validator.negative) + || (value === validator.element.val() && validator.negative); + }, + blockSubmit: true + }, + max: { + name: "max", + init: function ($this, name) { + return {max: $this.data("validation" + name + "Max")}; + }, + validate: function ($this, value, validator) { + return (parseFloat(value, 10) > parseFloat(validator.max, 10) && ! validator.negative) + || (parseFloat(value, 10) <= parseFloat(validator.max, 10) && validator.negative); + } + }, + min: { + name: "min", + init: function ($this, name) { + return {min: $this.data("validation" + name + "Min")}; + }, + validate: function ($this, value, validator) { + return (parseFloat(value) < parseFloat(validator.min) && ! validator.negative) + || (parseFloat(value) >= parseFloat(validator.min) && validator.negative); + } + }, + maxlength: { + name: "maxlength", + init: function ($this, name) { + return {maxlength: $this.data("validation" + name + "Maxlength")}; + }, + validate: function ($this, value, validator) { + return ((value.length > validator.maxlength) && ! validator.negative) + || ((value.length <= validator.maxlength) && validator.negative); + } + }, + minlength: { + name: "minlength", + init: function ($this, name) { + return {minlength: $this.data("validation" + name + "Minlength")}; + }, + validate: function ($this, value, validator) { + return ((value.length < validator.minlength) && ! validator.negative) + || ((value.length >= validator.minlength) && validator.negative); + } + }, + maxchecked: { + name: "maxchecked", + init: function ($this, name) { + var elements = $this.parents("form").first().find("[name=\"" + $this.attr("name") + "\"]"); + elements.bind("click.validation", function () { + $this.trigger("change.validation", {includeEmpty: true}); + }); + return {maxchecked: $this.data("validation" + name + "Maxchecked"), elements: elements}; + }, + validate: function ($this, value, validator) { + return (validator.elements.filter(":checked").length > validator.maxchecked && ! validator.negative) + || (validator.elements.filter(":checked").length <= validator.maxchecked && validator.negative); + }, + blockSubmit: true + }, + minchecked: { + name: "minchecked", + init: function ($this, name) { + var elements = $this.parents("form").first().find("[name=\"" + $this.attr("name") + "\"]"); + elements.bind("click.validation", function () { + $this.trigger("change.validation", {includeEmpty: true}); + }); + return {minchecked: $this.data("validation" + name + "Minchecked"), elements: elements}; + }, + validate: function ($this, value, validator) { + return (validator.elements.filter(":checked").length < validator.minchecked && ! validator.negative) + || (validator.elements.filter(":checked").length >= validator.minchecked && validator.negative); + }, + blockSubmit: true + } + }, + builtInValidators: { + email: { + name: "Email", + type: "shortcut", + shortcut: "validemail" + }, + validemail: { + name: "Validemail", + type: "regex", + regex: "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\.[A-Za-z]{2,4}", + message: "Not a valid email address<!-- data-validator-validemail-message to override -->" + }, + passwordagain: { + name: "Passwordagain", + type: "match", + match: "password", + message: "Does not match the given password<!-- data-validator-paswordagain-message to override -->" + }, + positive: { + name: "Positive", + type: "shortcut", + shortcut: "number,positivenumber" + }, + negative: { + name: "Negative", + type: "shortcut", + shortcut: "number,negativenumber" + }, + number: { + name: "Number", + type: "regex", + regex: "([+-]?\\\d+(\\\.\\\d*)?([eE][+-]?[0-9]+)?)?", + message: "Must be a number<!-- data-validator-number-message to override -->" + }, + integer: { + name: "Integer", + type: "regex", + regex: "[+-]?\\\d+", + message: "No decimal places allowed<!-- data-validator-integer-message to override -->" + }, + positivenumber: { + name: "Positivenumber", + type: "min", + min: 0, + message: "Must be a positive number<!-- data-validator-positivenumber-message to override -->" + }, + negativenumber: { + name: "Negativenumber", + type: "max", + max: 0, + message: "Must be a negative number<!-- data-validator-negativenumber-message to override -->" + }, + required: { + name: "Required", + type: "required", + message: "This is required<!-- data-validator-required-message to override -->" + }, + checkone: { + name: "Checkone", + type: "minchecked", + minchecked: 1, + message: "Check at least one option<!-- data-validation-checkone-message to override -->" + } + } + }; + + var formatValidatorName = function (name) { + return name + .toLowerCase() + .replace( + /(^|\s)([a-z])/g , + function(m,p1,p2) { + return p1+p2.toUpperCase(); + } + ) + ; + }; + + var getValue = function ($this) { + // Extract the value we're talking about + var value = $this.val(); + var type = $this.attr("type"); + if (type === "checkbox") { + value = ($this.is(":checked") ? value : ""); + } + if (type === "radio") { + value = ($('input[name="' + $this.attr("name") + '"]:checked').length > 0 ? value : ""); + } + return value; + }; + + function regexFromString(inputstring) { + return new RegExp("^" + inputstring + "$"); + } + + /** + * Thanks to Jason Bunting via StackOverflow.com + * + * http://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string#answer-359910 + * Short link: http://tinyurl.com/executeFunctionByName + **/ + function executeFunctionByName(functionName, context /*, args*/) { + var args = Array.prototype.slice.call(arguments).splice(2); + var namespaces = functionName.split("."); + var func = namespaces.pop(); + for(var i = 0; i < namespaces.length; i++) { + context = context[namespaces[i]]; + } + return context[func].apply(this, args); + } + + $.fn.jqBootstrapValidation = function( method ) { + + if ( defaults.methods[method] ) { + return defaults.methods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === 'object' || ! method ) { + return defaults.methods.init.apply( this, arguments ); + } else { + $.error( 'Method ' + method + ' does not exist on jQuery.jqBootstrapValidation' ); + return null; + } + + }; + + $.jqBootstrapValidation = function (options) { + $(":input").not("[type=image],[type=submit]").jqBootstrapValidation.apply(this,arguments); + }; + +})( jQuery ); diff --git a/src/admin/application/templates/js/jquery.js b/src/admin/application/templates/js/jquery.js new file mode 100644 index 0000000..14ba636 --- /dev/null +++ b/src/admin/application/templates/js/jquery.js @@ -0,0 +1,9472 @@ +/*! + * jQuery JavaScript Library v1.8.3 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: Tue Nov 13 2012 08:20:33 GMT-0500 (Eastern Standard Time) + */ +(function( window, undefined ) { +var + // A central reference to the root jQuery(document) + rootjQuery, + + // The deferred used on DOM ready + readyList, + + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + location = window.location, + navigator = window.navigator, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // Save a reference to some core methods + core_push = Array.prototype.push, + core_slice = Array.prototype.slice, + core_indexOf = Array.prototype.indexOf, + core_toString = Object.prototype.toString, + core_hasOwn = Object.prototype.hasOwnProperty, + core_trim = String.prototype.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source, + + // Used for detecting and trimming whitespace + core_rnotwhite = /\S/, + core_rspace = /\s+/, + + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // A simple way to check for HTML strings + // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) + rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return ( letter + "" ).toUpperCase(); + }, + + // The ready event handler and self cleanup method + DOMContentLoaded = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + } else if ( document.readyState === "complete" ) { + // we're here because readyState === "complete" in oldIE + // which is good enough for us to call the dom ready! + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = ( context && context.nodeType ? context.ownerDocument || context : document ); + + // scripts is true for back-compat + selector = jQuery.parseHTML( match[1], doc, true ); + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + this.attr.call( selector, context, true ); + } + + return jQuery.merge( this, selector ); + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.8.3", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + eq: function( i ) { + i = +i; + return i === -1 ? + this.slice( i ) : + this.slice( i, i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ), + "slice", core_slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ core_toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // scripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, scripts ) { + var parsed; + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + scripts = context; + context = 0; + } + context = context || document; + + // Single tag + if ( (parsed = rsingleTag.exec( data )) ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] ); + return jQuery.merge( [], + (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes ); + }, + + parseJSON: function( data ) { + if ( !data || typeof data !== "string") { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && core_rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var name, + i = 0, + length = obj.length, + isObj = length === undefined || jQuery.isFunction( obj ); + + if ( args ) { + if ( isObj ) { + for ( name in obj ) { + if ( callback.apply( obj[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( obj[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in obj ) { + if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var type, + ret = results || []; + + if ( arr != null ) { + // The window, strings (and functions) also have 'length' + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + type = jQuery.type( arr ); + + if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) { + core_push.call( ret, arr ); + } else { + jQuery.merge( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return -1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, + ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, pass ) { + var exec, + bulk = key == null, + i = 0, + length = elems.length; + + // Sets many values + if ( key && typeof key === "object" ) { + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], 1, emptyGet, value ); + } + chainable = 1; + + // Sets one value + } else if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = pass === undefined && jQuery.isFunction( value ); + + if ( bulk ) { + // Bulk operations only iterate when executing function values + if ( exec ) { + exec = fn; + fn = function( elem, key, value ) { + return exec.call( jQuery( elem ), value ); + }; + + // Otherwise they run against the entire set + } else { + fn.call( elems, value ); + fn = null; + } + } + + if ( fn ) { + for (; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + } + + chainable = 1; + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready, 1 ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch(e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch(e) { + return setTimeout( doScrollCheck, 50 ); + } + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.split( core_rspace ), function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Control if a given callback is in the list + has: function( fn ) { + return jQuery.inArray( fn, list ) > -1; + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( list && ( !fired || stack ) ) { + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ]( jQuery.isFunction( fn ) ? + function() { + var returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); + } + } : + newDefer[ action ] + ); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] = list.fire + deferred[ tuple[0] ] = list.fire; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); +jQuery.support = (function() { + + var support, + all, + a, + select, + opt, + input, + fragment, + eventName, + i, + isSupported, + clickFn, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>"; + + // Support tests won't run in some limited or non-browser environments + all = div.getElementsByTagName("*"); + a = div.getElementsByTagName("a")[ 0 ]; + if ( !all || !a || !all.length ) { + return {}; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute("href") === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.5/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Tests for enctype support on a form (#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>", + + // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode + boxModel: ( document.compatMode === "CSS1Compat" ), + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true, + boxSizingReliable: true, + pixelPosition: false + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", clickFn = function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent("onclick"); + div.detachEvent( "onclick", clickFn ); + } + + // Check if a radio maintains its value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + input.setAttribute( "checked", "checked" ); + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.lastChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + fragment.removeChild( input ); + fragment.appendChild( div ); + + // Technique from Juriy Zaytsev + // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for ( i in { + submit: true, + change: true, + focusin: true + }) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + // Run tests that need a body at doc ready + jQuery(function() { + var container, div, tds, marginDiv, + divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px"; + body.insertBefore( container, body.firstChild ); + + // Construct the test element + div = document.createElement("div"); + container.appendChild( div ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>"; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE <= 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + support.boxSizing = ( div.offsetWidth === 4 ); + support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 ); + + // NOTE: To any future maintainer, we've window.getComputedStyle + // because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = document.createElement("div"); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + if ( typeof div.style.zoom !== "undefined" ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = "block"; + div.style.overflow = "visible"; + div.innerHTML = "<div></div>"; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + container.style.zoom = 1; + } + + // Null elements to avoid leaks in IE + body.removeChild( container ); + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + fragment.removeChild( div ); + all = a = select = opt = input = fragment = div = null; + + return support; +})(); +var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +jQuery.extend({ + cache: {}, + + deletedIds: [], + + // Remove at next major release (1.9/2.0) + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, i, l, + + isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var parts, part, attr, name, l, + elem = this[0], + i = 0, + data = null; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attr = elem.attributes; + for ( l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( !name.indexOf( "data-" ) ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + parts = key.split( ".", 2 ); + parts[1] = parts[1] ? "." + parts[1] : ""; + part = parts[1] + "!"; + + return jQuery.access( this, function( value ) { + + if ( value === undefined ) { + data = this.triggerHandler( "getData" + part, [ parts[0] ] ); + + // Try to fetch any internally stored data first + if ( data === undefined && elem ) { + data = jQuery.data( elem, key ); + data = dataAttr( elem, key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + } + + parts[1] = value; + this.each(function() { + var self = jQuery( this ); + + self.triggerHandler( "setData" + part, parts ); + jQuery.data( this, key, value ); + self.triggerHandler( "changeData" + part, parts ); + }); + }, null, value, arguments.length > 1, null, false ); + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// checks a cache object for emptiness +function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery.removeData( elem, type + "queue", true ); + jQuery.removeData( elem, key, true ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); +var nodeHook, boolHook, fixSpecified, + rclass = /[\t\r\n]/g, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea|)$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( core_rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var removes, className, elem, c, cl, i, l; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + if ( (value && typeof value === "string") || value === undefined ) { + removes = ( value || "" ).split( core_rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + if ( elem.nodeType === 1 && elem.className ) { + + className = (" " + elem.className + " ").replace( rclass, " " ); + + // loop over each item in the removal list + for ( c = 0, cl = removes.length; c < cl; c++ ) { + // Remove until there is nothing to remove, + while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) { + className = className.replace( " " + removes[ c ] + " " , " " ); + } + } + elem.className = value ? jQuery.trim( className ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( core_rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val, + self = jQuery(this); + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9 + attrFn: {}, + + attr: function( elem, name, value, pass ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var propName, attrNames, name, isBool, + i = 0; + + if ( value && elem.nodeType === 1 ) { + + attrNames = value.split( core_rspace ); + + for ( ; i < attrNames.length; i++ ) { + name = attrNames[ i ]; + + if ( name ) { + propName = jQuery.propFix[ name ] || name; + isBool = rboolean.test( name ); + + // See #9699 for explanation of this approach (setting first, then removal) + // Do not do this for boolean attributes (see #10870) + if ( !isBool ) { + jQuery.attr( elem, name, "" ); + } + elem.removeAttribute( getSetAttribute ? name : propName ); + + // Set corresponding property to false for boolean attributes + if ( isBool && propName in elem ) { + elem[ propName ] = false; + } + } + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + // Use the value property for back compat + // Use the nodeHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { + return nodeHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } +}); + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + // Fall back to attribute presence where some booleans are not supported + var attrNode, + property = jQuery.prop( elem, name ); + return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !getSetAttribute ) { + + fixSpecified = { + name: true, + id: true, + coords: true + }; + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ? + ret.value : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + ret = document.createAttribute( name ); + elem.setAttributeNode( ret ); + } + return ( ret.value = value + "" ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + if ( value === "" ) { + value = "false"; + } + nodeHook.set( elem, value, name ); + } + }; +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); +} + +// IE6/7 call enctype encoding +if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); +}); +var rformElems = /^(?:textarea|input|select)$/i, + rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/, + rhoverHack = /(?:^|\s)hover(\.\S+|)\b/, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + hoverHack = function( events ) { + return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); + }; + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + add: function( elem, types, handler, data, selector ) { + + var elemData, eventHandle, events, + t, tns, type, namespaces, handleObj, + handleObjIn, handlers, special; + + // Don't attach events to noData or text/comment nodes (allow plain objects tho) + if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + events = elemData.events; + if ( !events ) { + elemData.events = events = {}; + } + eventHandle = elemData.handle; + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = jQuery.trim( hoverHack(types) ).split( " " ); + for ( t = 0; t < types.length; t++ ) { + + tns = rtypenamespace.exec( types[t] ) || []; + type = tns[1]; + namespaces = ( tns[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: tns[1], + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + handlers = events[ type ]; + if ( !handlers ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var t, tns, type, origType, namespaces, origCount, + j, events, special, eventType, handleObj, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = jQuery.trim( hoverHack( types || "" ) ).split(" "); + for ( t = 0; t < types.length; t++ ) { + tns = rtypenamespace.exec( types[t] ) || []; + type = origType = tns[1]; + namespaces = tns[2]; + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector? special.delegateType : special.bindType ) || type; + eventType = events[ type ] || []; + origCount = eventType.length; + namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null; + + // Remove matching events + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !namespaces || namespaces.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + eventType.splice( j--, 1 ); + + if ( handleObj.selector ) { + eventType.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( eventType.length === 0 && origCount !== eventType.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery.removeData( elem, "events", true ); + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Don't do events on text and comment nodes + if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { + return; + } + + // Event object or event type + var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType, + type = event.type || event, + namespaces = []; + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "!" ) >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf( "." ) >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.isTrigger = true; + event.exclusive = exclusive; + event.namespace = namespaces.join( "." ); + event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null; + ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; + + // Handle a global trigger + if ( !elem ) { + + // TODO: Stop taunting the data cache; remove global events and always attach to document + cache = jQuery.cache; + for ( i in cache ) { + if ( cache[ i ].events && cache[ i ].events[ type ] ) { + jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); + } + } + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + eventPath = [[ elem, special.bindType || type ]]; + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; + for ( old = elem; cur; cur = cur.parentNode ) { + eventPath.push([ cur, bubbleType ]); + old = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( old === (elem.ownerDocument || document) ) { + eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); + } + } + + // Fire handlers on the event path + for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { + + cur = eventPath[i][0]; + event.type = eventPath[i][1]; + + handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + // Note that this is a bare JS function and not a jQuery handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + // IE<9 dies on focus/blur to hidden element (#1486) + if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( old ) { + elem[ ontype ] = old; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event || window.event ); + + var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related, + handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), + delegateCount = handlers.delegateCount, + args = core_slice.call( arguments ), + run_all = !event.exclusive && !event.namespace, + special = jQuery.event.special[ event.type ] || {}, + handlerQueue = []; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers that should run if there are delegated events + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && !(event.button && event.type === "click") ) { + + for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { + + // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.disabled !== true || event.type !== "click" ) { + selMatch = {}; + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + sel = handleObj.selector; + + if ( selMatch[ sel ] === undefined ) { + selMatch[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( selMatch[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, matches: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( handlers.length > delegateCount ) { + handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); + } + + // Run delegates first; they may want to stop propagation beneath us + for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { + matched = handlerQueue[ i ]; + event.currentTarget = matched.elem; + + for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { + handleObj = matched.matches[ j ]; + + // Triggered event must either 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { + + event.data = handleObj.data; + event.handleObj = handleObj; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** + props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, + originalEvent = event, + fixHook = jQuery.event.fixHooks[ event.type ] || {}, + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = jQuery.Event( originalEvent ); + + for ( i = copy.length; i; ) { + prop = copy[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Target should not be a text node (#504, Safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8) + event.metaKey = !!event.metaKey; + + return fixHook.filter? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + + focus: { + delegateType: "focusin" + }, + blur: { + delegateType: "focusout" + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +// Some plugins are using, but it's undocumented/deprecated and will be removed. +// The 1.7 special event interface should provide all the hooks needed now. +jQuery.event.handle = jQuery.event.dispatch; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === "undefined" ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj, + selector = handleObj.selector; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// IE submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "_submit_attached" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "_submit_attached", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; +} + +// IE change delegation and checkbox/radio fix +if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "_change_attached" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "_change_attached", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { // && selector != null + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + live: function( types, data, fn ) { + jQuery( this.context ).on( types, this.selector, data, fn ); + return this; + }, + die: function( types, fn ) { + jQuery( this.context ).off( types, this.selector || "**", fn ); + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; + + if ( rkeyEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; + } + + if ( rmouseEvent.test( name ) ) { + jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; + } +}); +/*! + * Sizzle CSS Selector Engine + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license + * http://sizzlejs.com/ + */ +(function( window, undefined ) { + +var cachedruns, + assertGetIdNotName, + Expr, + getText, + isXML, + contains, + compile, + sortOrder, + hasDuplicate, + outermostContext, + + baseHasDuplicate = true, + strundefined = "undefined", + + expando = ( "sizcache" + Math.random() ).replace( ".", "" ), + + Token = String, + document = window.document, + docElem = document.documentElement, + dirruns = 0, + done = 0, + pop = [].pop, + push = [].push, + slice = [].slice, + // Use a stripped-down indexOf if a native one is unavailable + indexOf = [].indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return -1; + }, + + // Augment a function for special use by Sizzle + markFunction = function( fn, value ) { + fn[ expando ] = value == null || value; + return fn; + }, + + createCache = function() { + var cache = {}, + keys = []; + + return markFunction(function( key, value ) { + // Only keep the most recent entries + if ( keys.push( key ) > Expr.cacheLength ) { + delete cache[ keys.shift() ]; + } + + // Retrieve with (key + " ") to avoid collision with native Object.prototype properties (see Issue #157) + return (cache[ key + " " ] = value); + }, cache ); + }, + + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + + // Regex + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", + + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + operators = "([*^$|!~]?=)", + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + + // Prefer arguments not in parens/brackets, + // then attribute selectors and non-pseudos (denoted by :), + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)", + + // For matchExpr.POS and matchExpr.needsContext + pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), + rpseudo = new RegExp( pseudos ), + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, + + rnot = /^:not/, + rsibling = /[\x20\t\r\n\f]*[+~]/, + rendsWithNot = /:not\($/, + + rheader = /h\d/i, + rinputs = /input|select|textarea|button/i, + + rbackslash = /\\(?!\\)/g, + + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "POS": new RegExp( pos, "i" ), + "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + // For use in libraries implementing .is() + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) + }, + + // Support + + // Used for testing something on an element + assert = function( fn ) { + var div = document.createElement("div"); + + try { + return fn( div ); + } catch (e) { + return false; + } finally { + // release memory in IE + div = null; + } + }, + + // Check if getElementsByTagName("*") returns only elements + assertTagNameNoComments = assert(function( div ) { + div.appendChild( document.createComment("") ); + return !div.getElementsByTagName("*").length; + }), + + // Check if getAttribute returns normalized href attributes + assertHrefNotNormalized = assert(function( div ) { + div.innerHTML = "<a href='#'></a>"; + return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && + div.firstChild.getAttribute("href") === "#"; + }), + + // Check if attributes should be retrieved by attribute nodes + assertAttributes = assert(function( div ) { + div.innerHTML = "<select></select>"; + var type = typeof div.lastChild.getAttribute("multiple"); + // IE8 returns a string for some attributes even when not present + return type !== "boolean" && type !== "string"; + }), + + // Check if getElementsByClassName can be trusted + assertUsableClassName = assert(function( div ) { + // Opera can't find a second classname (in 9.6) + div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>"; + if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { + return false; + } + + // Safari 3.2 caches class attributes and doesn't catch changes + div.lastChild.className = "e"; + return div.getElementsByClassName("e").length === 2; + }), + + // Check if getElementById returns elements by name + // Check if getElementsByName privileges form controls or returns elements by ID + assertUsableName = assert(function( div ) { + // Inject content + div.id = expando + 0; + div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>"; + docElem.insertBefore( div, docElem.firstChild ); + + // Test + var pass = document.getElementsByName && + // buggy browsers will return fewer than the correct 2 + document.getElementsByName( expando ).length === 2 + + // buggy browsers will return more than the correct 0 + document.getElementsByName( expando + 0 ).length; + assertGetIdNotName = !document.getElementById( expando ); + + // Cleanup + docElem.removeChild( div ); + + return pass; + }); + +// If slice is not available, provide a backup +try { + slice.call( docElem.childNodes, 0 )[0].nodeType; +} catch ( e ) { + slice = function( i ) { + var elem, + results = []; + for ( ; (elem = this[i]); i++ ) { + results.push( elem ); + } + return results; + }; +} + +function Sizzle( selector, context, results, seed ) { + results = results || []; + context = context || document; + var match, elem, xml, m, + nodeType = context.nodeType; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( nodeType !== 1 && nodeType !== 9 ) { + return []; + } + + xml = isXML( context ); + + if ( !xml && !seed ) { + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { + push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); + return results; + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed, xml ); +} + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + return Sizzle( expr, null, null, [ elem ] ).length > 0; +}; + +// Returns a function to use in pseudos for input types +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +// Returns a function to use in pseudos for buttons +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +// Returns a function to use in pseudos for positionals +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( nodeType ) { + if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + } else { + + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } + return ret; +}; + +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +// Element contains another +contains = Sizzle.contains = docElem.contains ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); + } : + docElem.compareDocumentPosition ? + function( a, b ) { + return b && !!( a.compareDocumentPosition( b ) & 16 ); + } : + function( a, b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + return false; + }; + +Sizzle.attr = function( elem, name ) { + var val, + xml = isXML( elem ); + + if ( !xml ) { + name = name.toLowerCase(); + } + if ( (val = Expr.attrHandle[ name ]) ) { + return val( elem ); + } + if ( xml || assertAttributes ) { + return elem.getAttribute( name ); + } + val = elem.getAttributeNode( name ); + return val ? + typeof elem[ name ] === "boolean" ? + elem[ name ] ? name : null : + val.specified ? val.value : null : + null; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + // IE6/7 return a modified href + attrHandle: assertHrefNotNormalized ? + {} : + { + "href": function( elem ) { + return elem.getAttribute( "href", 2 ); + }, + "type": function( elem ) { + return elem.getAttribute("type"); + } + }, + + find: { + "ID": assertGetIdNotName ? + function( id, context, xml ) { + if ( typeof context.getElementById !== strundefined && !xml ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + } : + function( id, context, xml ) { + if ( typeof context.getElementById !== strundefined && !xml ) { + var m = context.getElementById( id ); + + return m ? + m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? + [m] : + undefined : + []; + } + }, + + "TAG": assertTagNameNoComments ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + var elem, + tmp = [], + i = 0; + + for ( ; (elem = results[i]); i++ ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }, + + "NAME": assertUsableName && function( tag, context ) { + if ( typeof context.getElementsByName !== strundefined ) { + return context.getElementsByName( name ); + } + }, + + "CLASS": assertUsableClassName && function( className, context, xml ) { + if ( typeof context.getElementsByClassName !== strundefined && !xml ) { + return context.getElementsByClassName( className ); + } + } + }, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( rbackslash, "" ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 3 xn-component of xn+y argument ([+-]?\d*n|) + 4 sign of xn-component + 5 x of xn-component + 6 sign of y-component + 7 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1] === "nth" ) { + // nth-child requires argument + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); + match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); + + // other types prohibit arguments + } else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var unquoted, excess; + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + if ( match[3] ) { + match[2] = match[3]; + } else if ( (unquoted = match[4]) ) { + // Only check arguments that contain a pseudo + if ( rpseudo.test(unquoted) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + unquoted = unquoted.slice( 0, excess ); + match[0] = match[0].slice( 0, excess ); + } + match[2] = unquoted; + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + "ID": assertGetIdNotName ? + function( id ) { + id = id.replace( rbackslash, "" ); + return function( elem ) { + return elem.getAttribute("id") === id; + }; + } : + function( id ) { + id = id.replace( rbackslash, "" ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === id; + }; + }, + + "TAG": function( nodeName ) { + if ( nodeName === "*" ) { + return function() { return true; }; + } + nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); + + return function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ expando ][ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem, context ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.substr( result.length - check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, argument, first, last ) { + + if ( type === "nth" ) { + return function( elem ) { + var node, diff, + parent = elem.parentNode; + + if ( first === 1 && last === 0 ) { + return true; + } + + if ( parent ) { + diff = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + diff++; + if ( elem === node ) { + break; + } + } + } + } + + // Incorporate the offset (or cast to NaN), then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + }; + } + + return function( elem ) { + var node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + /* falls through */ + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + var nodeType; + elem = elem.firstChild; + while ( elem ) { + if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { + return false; + } + elem = elem.nextSibling; + } + return true; + }, + + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "text": function( elem ) { + var type, attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + (type = elem.type) === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); + }, + + // Input types + "radio": createInputPseudo("radio"), + "checkbox": createInputPseudo("checkbox"), + "file": createInputPseudo("file"), + "password": createInputPseudo("password"), + "image": createInputPseudo("image"), + + "submit": createButtonPseudo("submit"), + "reset": createButtonPseudo("reset"), + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "focus": function( elem ) { + var doc = elem.ownerDocument; + return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + "active": function( elem ) { + return elem === elem.ownerDocument.activeElement; + }, + + // Positional types + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + for ( var i = 0; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + for ( var i = 1; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +function siblingCheck( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; +} + +sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? + a.compareDocumentPosition : + a.compareDocumentPosition(b) & 4 + ) ? -1 : 1; + } : + function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + +// Always assume the presence of duplicates if sort doesn't +// pass them to our comparison function (as in Google Chrome). +[0, 0].sort( sortOrder ); +baseHasDuplicate = !hasDuplicate; + +// Document sorting and removing duplicates +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + i = 1, + j = 0; + + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( ; (elem = results[i]); i++ ) { + if ( elem === results[ i - 1 ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ expando ][ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + tokens.push( matched = new Token( match.shift() ) ); + soFar = soFar.slice( matched.length ); + + // Cast descendant combinators to space + matched.type = match[0].replace( rtrim, " " ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + + tokens.push( matched = new Token( match.shift() ) ); + soFar = soFar.slice( matched.length ); + matched.type = type; + matched.matches = match; + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && combinator.dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( checkNonElements || elem.nodeType === 1 ) { + return matcher( elem, context, xml ); + } + } + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( !xml ) { + var cache, + dirkey = dirruns + " " + doneName + " ", + cachedkey = dirkey + cachedruns; + while ( (elem = elem[ dir ]) ) { + if ( checkNonElements || elem.nodeType === 1 ) { + if ( (cache = elem[ expando ]) === cachedkey ) { + return elem.sizset; + } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { + if ( elem.sizset ) { + return elem; + } + } else { + elem[ expando ] = cachedkey; + if ( matcher( elem, context, xml ) ) { + elem.sizset = true; + return elem; + } + elem.sizset = false; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( checkNonElements || elem.nodeType === 1 ) { + if ( matcher( elem, context, xml ) ) { + return elem; + } + } + } + } + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && tokens.join("") + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Nested matchers should use non-integer dirruns + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = superMatcher.el; + } + + // Add elements passing elementMatchers directly to results + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + for ( j = 0; (matcher = elementMatchers[j]); j++ ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++superMatcher.el; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + for ( j = 0; (matcher = setMatchers[j]); j++ ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + superMatcher.el = 0; + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ expando ][ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; +}; + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function select( selector, context, results, seed, xml ) { + var i, tokens, token, type, find, + match = tokenize( selector ), + j = match.length; + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && !xml && + Expr.relative[ tokens[1].type ] ) { + + context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0]; + if ( !context ) { + return results; + } + + selector = selector.slice( tokens.shift().length ); + } + + // Fetch a seed set for right-to-left matching + for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( rbackslash, "" ), + rsibling.test( tokens[0].type ) && context.parentNode || context, + xml + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && tokens.join(""); + if ( !selector ) { + push.apply( results, slice.call( seed, 0 ) ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + xml, + results, + rsibling.test( selector ) + ); + return results; +} + +if ( document.querySelectorAll ) { + (function() { + var disconnectedMatch, + oldSelect = select, + rescape = /'|\\/g, + rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, + + // qSa(:focus) reports false when true (Chrome 21), no need to also add to buggyMatches since matches checks buggyQSA + // A support test would require too much code (would include document ready) + rbuggyQSA = [ ":focus" ], + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + // A support test would require too much code (would include document ready) + // just skip matchesSelector for :active + rbuggyMatches = [ ":active" ], + matches = docElem.matchesSelector || + docElem.mozMatchesSelector || + docElem.webkitMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector; + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explictly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = "<select><option selected=''></option></select>"; + + // IE8 - Some boolean attributes are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here (do not put tests after this one) + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Opera 10-12/IE9 - ^= $= *= and empty values + // Should not select anything + div.innerHTML = "<p test=''></p>"; + if ( div.querySelectorAll("[test^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here (do not put tests after this one) + div.innerHTML = "<input type='hidden'/>"; + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push(":enabled", ":disabled"); + } + }); + + // rbuggyQSA always contains :focus, so no need for a length check + rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") ); + + select = function( selector, context, results, seed, xml ) { + // Only use querySelectorAll when not filtering, + // when this is not xml, + // and when no QSA bugs apply + if ( !seed && !xml && !rbuggyQSA.test( selector ) ) { + var groups, i, + old = true, + nid = expando, + newContext = context, + newSelector = context.nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + groups[i].join(""); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, slice.call( newContext.querySelectorAll( + newSelector + ), 0 ) ); + return results; + } catch(qsaError) { + } finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + + return oldSelect( selector, context, results, seed, xml ); + }; + + if ( matches ) { + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + try { + matches.call( div, "[test!='']:sizzle" ); + rbuggyMatches.push( "!=", pseudos ); + } catch ( e ) {} + }); + + // rbuggyMatches always contains :active and :focus, so no need for a length check + rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); + + Sizzle.matchesSelector = function( elem, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + // rbuggyMatches always contains :active, so no need for an existence check + if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && !rbuggyQSA.test( expr ) ) { + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch(e) {} + } + + return Sizzle( expr, null, null, [ elem ] ).length > 0; + }; + } + })(); +} + +// Deprecated +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Back-compat +function setFilters() {} +Expr.filters = setFilters.prototype = Expr.pseudos; +Expr.setFilters = new setFilters(); + +// Override sizzle attribute retrieval +Sizzle.attr = jQuery.attr; +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})( window ); +var runtil = /Until$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + isSimple = /^.[^:#\[\.,]*$/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, l, length, n, r, ret, + self = this; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + ret = this.pushStack( "", "find", selector ); + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + rneedsContext.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + cur = this[i]; + + while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + } + cur = cur.parentNode; + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +jQuery.fn.andSelf = jQuery.fn.addBack; + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } while ( cur && cur.nodeType !== 1 ); + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( this.length > 1 && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, core_slice.call( arguments ).join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); +} +function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; +} + +var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /<tbody/i, + rhtml = /<|&#?\w+;/, + rnoInnerhtml = /<(?:script|style|link)/i, + rnocache = /<(?:script|object|embed|option|style)/i, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rcheckableType = /^(?:checkbox|radio)$/, + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rscriptType = /\/(java|ecma)script/i, + rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g, + wrapMap = { + option: [ 1, "<select multiple='multiple'>", "</select>" ], + legend: [ 1, "<fieldset>", "</fieldset>" ], + thead: [ 1, "<table>", "</table>" ], + tr: [ 2, "<table><tbody>", "</tbody></table>" ], + td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], + col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ], + area: [ 1, "<map>", "</map>" ], + _default: [ 0, "", "" ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, +// unless wrapped in a div with non-breaking characters in front of it. +if ( !jQuery.support.htmlSerialize ) { + wrapMap._default = [ 1, "X<div>", "</div>" ]; +} + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + }, + + append: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 ) { + this.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 ) { + this.insertBefore( elem, this.firstChild ); + } + }); + }, + + before: function() { + if ( !isDisconnected( this[0] ) ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this ); + }); + } + + if ( arguments.length ) { + var set = jQuery.clean( arguments ); + return this.pushStack( jQuery.merge( set, this ), "before", this.selector ); + } + }, + + after: function() { + if ( !isDisconnected( this[0] ) ) { + return this.domManip(arguments, false, function( elem ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + } + + if ( arguments.length ) { + var set = jQuery.clean( arguments ); + return this.pushStack( jQuery.merge( this, set ), "after", this.selector ); + } + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + jQuery.cleanData( [ elem ] ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName("*") ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1></$2>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( elem.getElementsByTagName( "*" ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch(e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function( value ) { + if ( !isDisconnected( this[0] ) ) { + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( jQuery.isFunction( value ) ) { + return this.each(function(i) { + var self = jQuery(this), old = self.html(); + self.replaceWith( value.call( this, i, old ) ); + }); + } + + if ( typeof value !== "string" ) { + value = jQuery( value ).detach(); + } + + return this.each(function() { + var next = this.nextSibling, + parent = this.parentNode; + + jQuery( this ).remove(); + + if ( next ) { + jQuery(next).before( value ); + } else { + jQuery(parent).append( value ); + } + }); + } + + return this.length ? + this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : + this; + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, table, callback ) { + + // Flatten any nested arrays + args = [].concat.apply( [], args ); + + var results, first, fragment, iNoClone, + i = 0, + value = args[0], + scripts = [], + l = this.length; + + // We can't cloneNode fragments that contain checked, in WebKit + if ( !jQuery.support.checkClone && l > 1 && typeof value === "string" && rchecked.test( value ) ) { + return this.each(function() { + jQuery(this).domManip( args, table, callback ); + }); + } + + if ( jQuery.isFunction(value) ) { + return this.each(function(i) { + var self = jQuery(this); + args[0] = value.call( this, i, table ? self.html() : undefined ); + self.domManip( args, table, callback ); + }); + } + + if ( this[0] ) { + results = jQuery.buildFragment( args, this, scripts ); + fragment = results.fragment; + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + // Fragments from the fragment cache must always be cloned and never used in place. + for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) { + callback.call( + table && jQuery.nodeName( this[i], "table" ) ? + findOrAppend( this[i], "tbody" ) : + this[i], + i === iNoClone ? + fragment : + jQuery.clone( fragment, true, true ) + ); + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + + if ( scripts.length ) { + jQuery.each( scripts, function( i, elem ) { + if ( elem.src ) { + if ( jQuery.ajax ) { + jQuery.ajax({ + url: elem.src, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } else { + jQuery.error("no ajax"); + } + } else { + jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + + if ( elem.parentNode ) { + elem.parentNode.removeChild( elem ); + } + }); + } + } + + return this; + } +}); + +function findOrAppend( elem, tag ) { + return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) ); +} + +function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } +} + +function cloneFixAttributes( src, dest ) { + var nodeName; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + // clearAttributes removes the attributes, which we don't want, + // but also removes the attachEvent events, which we *do* want + if ( dest.clearAttributes ) { + dest.clearAttributes(); + } + + // mergeAttributes, in contrast, only merges back on the + // original attributes, not the events + if ( dest.mergeAttributes ) { + dest.mergeAttributes( src ); + } + + nodeName = dest.nodeName.toLowerCase(); + + if ( nodeName === "object" ) { + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + + // IE blanks contents when cloning scripts + } else if ( nodeName === "script" && dest.text !== src.text ) { + dest.text = src.text; + } + + // Event data gets referenced instead of copied if the expando + // gets copied too + dest.removeAttribute( jQuery.expando ); +} + +jQuery.buildFragment = function( args, context, scripts ) { + var fragment, cacheable, cachehit, + first = args[ 0 ]; + + // Set context from what may come in as undefined or a jQuery collection or a node + // Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 & + // also doubles as fix for #8950 where plain objects caused createDocumentFragment exception + context = context || document; + context = !context.nodeType && context[0] || context; + context = context.ownerDocument || context; + + // Only cache "small" (1/2 KB) HTML strings that are associated with the main document + // Cloning options loses the selected state, so don't cache them + // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment + // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache + // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501 + if ( args.length === 1 && typeof first === "string" && first.length < 512 && context === document && + first.charAt(0) === "<" && !rnocache.test( first ) && + (jQuery.support.checkClone || !rchecked.test( first )) && + (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) { + + // Mark cacheable and look for a hit + cacheable = true; + fragment = jQuery.fragments[ first ]; + cachehit = fragment !== undefined; + } + + if ( !fragment ) { + fragment = context.createDocumentFragment(); + jQuery.clean( args, context, fragment, scripts ); + + // Update the cache, but only store false + // unless this is a second parsing of the same content + if ( cacheable ) { + jQuery.fragments[ first ] = cachehit && fragment; + } + } + + return { fragment: fragment, cacheable: cacheable }; +}; + +jQuery.fragments = {}; + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + l = insert.length, + parent = this.length === 1 && this[0].parentNode; + + if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) { + insert[ original ]( this[0] ); + return this; + } else { + for ( ; i < l; i++ ) { + elems = ( i > 0 ? this.clone(true) : this ).get(); + jQuery( insert[i] )[ original ]( elems ); + ret = ret.concat( elems ); + } + + return this.pushStack( ret, name, insert.selector ); + } + }; +}); + +function getAll( elem ) { + if ( typeof elem.getElementsByTagName !== "undefined" ) { + return elem.getElementsByTagName( "*" ); + + } else if ( typeof elem.querySelectorAll !== "undefined" ) { + return elem.querySelectorAll( "*" ); + + } else { + return []; + } +} + +// Used in clean, fixes the defaultChecked property +function fixDefaultChecked( elem ) { + if ( rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } +} + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var srcElements, + destElements, + i, + clone; + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + // IE copies events bound via attachEvent when using cloneNode. + // Calling detachEvent on the clone will also remove the events + // from the original. In order to get around this, we use some + // proprietary methods to clear the events. Thanks to MooTools + // guys for this hotness. + + cloneFixAttributes( elem, clone ); + + // Using Sizzle here is crazy slow, so we use getElementsByTagName instead + srcElements = getAll( elem ); + destElements = getAll( clone ); + + // Weird iteration because IE will replace the length property + // with an element if you are cloning the body and one of the + // elements on the page has a name or id of "length" + for ( i = 0; srcElements[i]; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + cloneFixAttributes( srcElements[i], destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + cloneCopyEvent( elem, clone ); + + if ( deepDataAndEvents ) { + srcElements = getAll( elem ); + destElements = getAll( clone ); + + for ( i = 0; srcElements[i]; ++i ) { + cloneCopyEvent( srcElements[i], destElements[i] ); + } + } + } + + srcElements = destElements = null; + + // Return the cloned set + return clone; + }, + + clean: function( elems, context, fragment, scripts ) { + var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags, + safe = context === document && safeFragment, + ret = []; + + // Ensure that context is a document + if ( !context || typeof context.createDocumentFragment === "undefined" ) { + context = document; + } + + // Use the already-created safe fragment if context permits + for ( i = 0; (elem = elems[i]) != null; i++ ) { + if ( typeof elem === "number" ) { + elem += ""; + } + + if ( !elem ) { + continue; + } + + // Convert html string into DOM nodes + if ( typeof elem === "string" ) { + if ( !rhtml.test( elem ) ) { + elem = context.createTextNode( elem ); + } else { + // Ensure a safe container in which to render the html + safe = safe || createSafeFragment( context ); + div = context.createElement("div"); + safe.appendChild( div ); + + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(rxhtmlTag, "<$1></$2>"); + + // Go to html and back, then peel off extra wrappers + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + depth = wrap[0]; + div.innerHTML = wrap[1] + elem + wrap[2]; + + // Move to the right depth + while ( depth-- ) { + div = div.lastChild; + } + + // Remove IE's autoinserted <tbody> from table fragments + if ( !jQuery.support.tbody ) { + + // String was a <table>, *may* have spurious <tbody> + hasBody = rtbody.test(elem); + tbody = tag === "table" && !hasBody ? + div.firstChild && div.firstChild.childNodes : + + // String was a bare <thead> or <tfoot> + wrap[1] === "<table>" && !hasBody ? + div.childNodes : + []; + + for ( j = tbody.length - 1; j >= 0 ; --j ) { + if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { + tbody[ j ].parentNode.removeChild( tbody[ j ] ); + } + } + } + + // IE completely kills leading whitespace when innerHTML is used + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); + } + + elem = div.childNodes; + + // Take out of fragment container (we need a fresh div each time) + div.parentNode.removeChild( div ); + } + } + + if ( elem.nodeType ) { + ret.push( elem ); + } else { + jQuery.merge( ret, elem ); + } + } + + // Fix #11356: Clear elements from safeFragment + if ( div ) { + elem = div = safe = null; + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + for ( i = 0; (elem = ret[i]) != null; i++ ) { + if ( jQuery.nodeName( elem, "input" ) ) { + fixDefaultChecked( elem ); + } else if ( typeof elem.getElementsByTagName !== "undefined" ) { + jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked ); + } + } + } + + // Append elements to a provided document fragment + if ( fragment ) { + // Special handling of each script element + handleScript = function( elem ) { + // Check if we consider it executable + if ( !elem.type || rscriptType.test( elem.type ) ) { + // Detach the script and store it in the scripts array (if provided) or the fragment + // Return truthy to indicate that it has been handled + return scripts ? + scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) : + fragment.appendChild( elem ); + } + }; + + for ( i = 0; (elem = ret[i]) != null; i++ ) { + // Check if we're done after handling an executable script + if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) { + // Append to fragment and handle embedded scripts + fragment.appendChild( elem ); + if ( typeof elem.getElementsByTagName !== "undefined" ) { + // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration + jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript ); + + // Splice the scripts into ret after their former ancestor and advance our index beyond them + ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) ); + i += jsTags.length; + } + } + } + } + + return ret; + }, + + cleanData: function( elems, /* internal */ acceptData ) { + var data, id, elem, type, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( elem.removeAttribute ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + jQuery.deletedIds.push( id ); + } + } + } + } + } +}); +// Limit scope pollution from any deprecated API +(function() { + +var matched, browser; + +// Use of jQuery.browser is frowned upon. +// More details: http://api.jquery.com/jQuery.browser +// jQuery.uaMatch maintained for back-compat +jQuery.uaMatch = function( ua ) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) || + /(webkit)[ \/]([\w.]+)/.exec( ua ) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) || + /(msie) ([\w.]+)/.exec( ua ) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; +}; + +matched = jQuery.uaMatch( navigator.userAgent ); +browser = {}; + +if ( matched.browser ) { + browser[ matched.browser ] = true; + browser.version = matched.version; +} + +// Chrome is Webkit, but Webkit is also Safari. +if ( browser.chrome ) { + browser.webkit = true; +} else if ( browser.webkit ) { + browser.safari = true; +} + +jQuery.browser = browser; + +jQuery.sub = function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; +}; + +})(); +var curCSS, iframe, iframeDoc, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity=([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ], + + eventsToggle = jQuery.fn.toggle; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +function showHide( elements, show ) { + var elem, display, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + values[ index ] = jQuery._data( elem, "olddisplay" ); + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && elem.style.display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + display = curCSS( elem, "display" ); + + if ( !values[ index ] && display !== "none" ) { + jQuery._data( elem, "olddisplay", display ); + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state, fn2 ) { + var bool = typeof state === "boolean"; + + if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) { + return eventsToggle.apply( this, arguments ); + } + + return this.each(function() { + if ( bool ? state : isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + + } + } + } + }, + + // Exclude the following css properties to add px + cssNumber: { + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch(e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, numeric, extra ) { + var val, num, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( numeric || extra !== undefined ) { + num = parseFloat( val ); + return numeric || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +// NOTE: To any future maintainer, we've window.getComputedStyle +// because jsdom on node.js will break without it. +if ( window.getComputedStyle ) { + curCSS = function( elem, name ) { + var ret, width, minWidth, maxWidth, + computed = window.getComputedStyle( elem, null ), + style = elem.style; + + if ( computed ) { + + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; +} else if ( document.documentElement.currentStyle ) { + curCSS = function( elem, name ) { + var left, rsLeft, + ret = elem.currentStyle && elem.currentStyle[ name ], + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rsLeft = elem.runtimeStyle && elem.runtimeStyle.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + elem.runtimeStyle.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + elem.runtimeStyle.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; +} + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + // we use jQuery.css instead of curCSS here + // because of the reliableMarginRight CSS hook! + val += jQuery.css( elem, extra + cssExpand[ i ], true ); + } + + // From this point on we use curCSS for maximum performance (relevant in animations) + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0; + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; + } + } else { + // at this point, extra isn't content, so add padding + val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0; + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + valueIsBorderBox = true, + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox + ) + ) + "px"; +} + + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + if ( elemdisplay[ nodeName ] ) { + return elemdisplay[ nodeName ]; + } + + var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ), + display = elem.css("display"); + elem.remove(); + + // If the simple way fails, + // get element's real default display by attaching it to a temp iframe + if ( display === "none" || display === "" ) { + // Use the already-created iframe if possible + iframe = document.body.appendChild( + iframe || jQuery.extend( document.createElement("iframe"), { + frameBorder: 0, + width: 0, + height: 0 + }) + ); + + // Create a cacheable copy of the iframe document on first call. + // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML + // document to it; WebKit & Firefox won't allow reusing the iframe document. + if ( !iframeDoc || !iframe.createElement ) { + iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document; + iframeDoc.write("<!doctype html><html><body>"); + iframeDoc.close(); + } + + elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) ); + + display = curCSS( elem, "display" ); + document.body.removeChild( iframe ); + } + + // Store the correct default display + elemdisplay[ nodeName ] = display; + + return display; +} + +jQuery.each([ "height", "width" ], function( i, name ) { + jQuery.cssHooks[ name ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + // certain elements can have dimension info if we invisibly show them + // however, it must have a current display style that would benefit from this + if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, "display" ) ) ) { + return jQuery.swap( elem, cssShow, function() { + return getWidthOrHeight( elem, name, extra ); + }); + } else { + return getWidthOrHeight( elem, name, extra ); + } + } + }, + + set: function( elem, value, extra ) { + return setPositiveNumber( elem, value, extra ? + augmentWidthOrHeight( + elem, + name, + extra, + jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box" + ) : 0 + ); + } + }; +}); + +if ( !jQuery.support.opacity ) { + jQuery.cssHooks.opacity = { + get: function( elem, computed ) { + // IE uses filters for opacity + return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ? + ( 0.01 * parseFloat( RegExp.$1 ) ) + "" : + computed ? "1" : ""; + }, + + set: function( elem, value ) { + var style = elem.style, + currentStyle = elem.currentStyle, + opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "", + filter = currentStyle && currentStyle.filter || style.filter || ""; + + // IE has trouble with opacity if it does not have layout + // Force it by setting the zoom level + style.zoom = 1; + + // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652 + if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" && + style.removeAttribute ) { + + // Setting style.filter to null, "" & " " still leave "filter:" in the cssText + // if "filter:" is present at all, clearType is disabled, we want to avoid this + // style.removeAttribute is IE Only, but so apparently is this code path... + style.removeAttribute( "filter" ); + + // if there there is no filter style applied in a css rule, we are done + if ( currentStyle && !currentStyle.filter ) { + return; + } + } + + // otherwise, set new filter values + style.filter = ralpha.test( filter ) ? + filter.replace( ralpha, opacity ) : + filter + " " + opacity; + } + }; +} + +// These hooks cannot be added until DOM ready because the support test +// for it is not run until after DOM ready +jQuery(function() { + if ( !jQuery.support.reliableMarginRight ) { + jQuery.cssHooks.marginRight = { + get: function( elem, computed ) { + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + // Work around by temporarily setting element display to inline-block + return jQuery.swap( elem, { "display": "inline-block" }, function() { + if ( computed ) { + return curCSS( elem, "marginRight" ); + } + }); + } + }; + } + + // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 + // getComputedStyle returns percent when specified for top/left/bottom/right + // rather than make the css module depend on the offset module, we just check for it here + if ( !jQuery.support.pixelPosition && jQuery.fn.position ) { + jQuery.each( [ "top", "left" ], function( i, prop ) { + jQuery.cssHooks[ prop ] = { + get: function( elem, computed ) { + if ( computed ) { + var ret = curCSS( elem, prop ); + // if curCSS returns percentage, fallback to offset + return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + "px" : ret; + } + } + }; + }); + } + +}); + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.hidden = function( elem ) { + return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none"); + }; + + jQuery.expr.filters.visible = function( elem ) { + return !jQuery.expr.filters.hidden( elem ); + }; +} + +// These hooks are used by animate to expand properties +jQuery.each({ + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i, + + // assumes a single number if not a string + parts = typeof value === "string" ? value.split(" ") : [ value ], + expanded = {}; + + for ( i = 0; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( !rmargin.test( prefix ) ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +}); +var r20 = /%20/g, + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, + rselectTextarea = /^(?:select|textarea)/i; + +jQuery.fn.extend({ + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map(function(){ + return this.elements ? jQuery.makeArray( this.elements ) : this; + }) + .filter(function(){ + return this.name && !this.disabled && + ( this.checked || rselectTextarea.test( this.nodeName ) || + rinput.test( this.type ) ); + }) + .map(function( i, elem ){ + var val = jQuery( this ).val(); + + return val == null ? + null : + jQuery.isArray( val ) ? + jQuery.map( val, function( val, i ){ + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }) : + { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }).get(); + } +}); + +//Serialize an array of form elements or a set of +//key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, value ) { + // If value is a function, invoke it and return its value + value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); + s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); + }; + + // Set traditional to true for jQuery <= 1.3.2 behavior. + if ( traditional === undefined ) { + traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + }); + + } else { + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ).replace( r20, "+" ); +}; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( jQuery.isArray( obj ) ) { + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + // If array item is non-scalar (array or object), encode its + // numeric index to resolve deserialization ambiguity issues. + // Note that rack (as of 1.0.0) can't currently deserialize + // nested arrays properly, and attempting to do so may cause + // a server error. Possible fixes are to modify rack's + // deserialization algorithm or to provide an option or flag + // to force array serialization to be shallow. + buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); + } + }); + + } else if ( !traditional && jQuery.type( obj ) === "object" ) { + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + // Serialize scalar item. + add( prefix, obj ); + } +} +var + // Document location + ajaxLocParts, + ajaxLocation, + + rhash = /#.*$/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + rquery = /\?/, + rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, + rts = /([?&])_=[^&]*/, + rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/, + + // Keep a copy of the old load method + _load = jQuery.fn.load, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = ["*/"] + ["*"]; + +// #8138, IE may throw an exception when accessing +// a field from window.location if document.domain has been set +try { + ajaxLocation = location.href; +} catch( e ) { + // Use the href attribute of an A element + // since IE will modify it given document.location + ajaxLocation = document.createElement( "a" ); + ajaxLocation.href = ""; + ajaxLocation = ajaxLocation.href; +} + +// Segment location into parts +ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, list, placeBefore, + dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ), + i = 0, + length = dataTypes.length; + + if ( jQuery.isFunction( func ) ) { + // For each dataType in the dataTypeExpression + for ( ; i < length; i++ ) { + dataType = dataTypes[ i ]; + // We control if we're asked to add before + // any existing element + placeBefore = /^\+/.test( dataType ); + if ( placeBefore ) { + dataType = dataType.substr( 1 ) || "*"; + } + list = structure[ dataType ] = structure[ dataType ] || []; + // then we add to the structure accordingly + list[ placeBefore ? "unshift" : "push" ]( func ); + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR, + dataType /* internal */, inspected /* internal */ ) { + + dataType = dataType || options.dataTypes[ 0 ]; + inspected = inspected || {}; + + inspected[ dataType ] = true; + + var selection, + list = structure[ dataType ], + i = 0, + length = list ? list.length : 0, + executeOnly = ( structure === prefilters ); + + for ( ; i < length && ( executeOnly || !selection ); i++ ) { + selection = list[ i ]( options, originalOptions, jqXHR ); + // If we got redirected to another dataType + // we try there if executing only and not done already + if ( typeof selection === "string" ) { + if ( !executeOnly || inspected[ selection ] ) { + selection = undefined; + } else { + options.dataTypes.unshift( selection ); + selection = inspectPrefiltersOrTransports( + structure, options, originalOptions, jqXHR, selection, inspected ); + } + } + } + // If we're only executing or nothing was selected + // we try the catchall dataType if not done already + if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) { + selection = inspectPrefiltersOrTransports( + structure, options, originalOptions, jqXHR, "*", inspected ); + } + // unnecessary when only executing (prefilters) + // but it'll be ignored by the caller in that case + return selection; +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } +} + +jQuery.fn.load = function( url, params, callback ) { + if ( typeof url !== "string" && _load ) { + return _load.apply( this, arguments ); + } + + // Don't do a request if no elements are being requested + if ( !this.length ) { + return this; + } + + var selector, type, response, + self = this, + off = url.indexOf(" "); + + if ( off >= 0 ) { + selector = url.slice( off, url.length ); + url = url.slice( 0, off ); + } + + // If it's a function + if ( jQuery.isFunction( params ) ) { + + // We assume that it's the callback + callback = params; + params = undefined; + + // Otherwise, build a param string + } else if ( params && typeof params === "object" ) { + type = "POST"; + } + + // Request the remote document + jQuery.ajax({ + url: url, + + // if "type" variable is undefined, then "GET" method will be used + type: type, + dataType: "html", + data: params, + complete: function( jqXHR, status ) { + if ( callback ) { + self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); + } + } + }).done(function( responseText ) { + + // Save response for use in complete callback + response = arguments; + + // See if a selector was specified + self.html( selector ? + + // Create a dummy div to hold the results + jQuery("<div>") + + // inject the contents of the document in, removing the scripts + // to avoid any 'Permission Denied' errors in IE + .append( responseText.replace( rscript, "" ) ) + + // Locate the specified elements + .find( selector ) : + + // If not, just inject the full result + responseText ); + + }); + + return this; +}; + +// Attach a bunch of functions for handling common AJAX events +jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){ + jQuery.fn[ o ] = function( f ){ + return this.on( o, f ); + }; +}); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + // shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + return jQuery.ajax({ + type: method, + url: url, + data: data, + success: callback, + dataType: type + }); + }; +}); + +jQuery.extend({ + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + if ( settings ) { + // Building a settings object + ajaxExtend( target, jQuery.ajaxSettings ); + } else { + // Extending ajaxSettings + settings = target; + target = jQuery.ajaxSettings; + } + ajaxExtend( target, settings ); + return target; + }, + + ajaxSettings: { + url: ajaxLocation, + isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), + global: true, + type: "GET", + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + processData: true, + async: true, + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + xml: "application/xml, text/xml", + html: "text/html", + text: "text/plain", + json: "application/json, text/javascript", + "*": allTypes + }, + + contents: { + xml: /xml/, + html: /html/, + json: /json/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText" + }, + + // List of data converters + // 1) key format is "source_type destination_type" (a single space in-between) + // 2) the catchall symbol "*" can be used for source_type + converters: { + + // Convert anything to text + "* text": window.String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": jQuery.parseJSON, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + context: true, + url: true + } + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var // ifModified key + ifModifiedKey, + // Response headers + responseHeadersString, + responseHeaders, + // transport + transport, + // timeout handle + timeoutTimer, + // Cross-domain detection vars + parts, + // To know if global events are to be dispatched + fireGlobals, + // Loop variable + i, + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + // Callbacks context + callbackContext = s.context || s, + // Context for global events + // It's the callbackContext if one was provided in the options + // and if it's a DOM node or a jQuery collection + globalEventContext = callbackContext !== s && + ( callbackContext.nodeType || callbackContext instanceof jQuery ) ? + jQuery( callbackContext ) : jQuery.event, + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + // Status-dependent callbacks + statusCode = s.statusCode || {}, + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + // The jqXHR state + state = 0, + // Default abort message + strAbort = "canceled", + // Fake xhr + jqXHR = { + + readyState: 0, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( !state ) { + var lname = name.toLowerCase(); + name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Raw string + getAllResponseHeaders: function() { + return state === 2 ? responseHeadersString : null; + }, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( state === 2 ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match === undefined ? null : match; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( !state ) { + s.mimeType = type; + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + statusText = statusText || strAbort; + if ( transport ) { + transport.abort( statusText ); + } + done( 0, statusText ); + return this; + } + }; + + // Callback for when everything is done + // It is defined here because jslint complains if it is declared + // at the end of the function (which would be more logical and readable) + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Called once + if ( state === 2 ) { + return; + } + + // State is "done" now + state = 2; + + // Clear timeout if it exists + if ( timeoutTimer ) { + clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // If successful, handle type chaining + if ( status >= 200 && status < 300 || status === 304 ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + + modified = jqXHR.getResponseHeader("Last-Modified"); + if ( modified ) { + jQuery.lastModified[ ifModifiedKey ] = modified; + } + modified = jqXHR.getResponseHeader("Etag"); + if ( modified ) { + jQuery.etag[ ifModifiedKey ] = modified; + } + } + + // If not modified + if ( status === 304 ) { + + statusText = "notmodified"; + isSuccess = true; + + // If we have data + } else { + + isSuccess = ajaxConvert( s, response ); + statusText = isSuccess.state; + success = isSuccess.data; + error = isSuccess.error; + isSuccess = !error; + } + } else { + // We extract error from statusText + // then normalize statusText and status for non-aborts + error = statusText; + if ( !statusText || status ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + // Attach deferreds + deferred.promise( jqXHR ); + jqXHR.success = jqXHR.done; + jqXHR.error = jqXHR.fail; + jqXHR.complete = completeDeferred.add; + + // Status-dependent callbacks + jqXHR.statusCode = function( map ) { + if ( map ) { + var tmp; + if ( state < 2 ) { + for ( tmp in map ) { + statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; + } + } else { + tmp = map[ jqXHR.status ]; + jqXHR.always( tmp ); + } + } + return this; + }; + + // Remove hash character (#7531: and string promotion) + // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) + // We also use the url parameter if available + s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); + + // Extract dataTypes list + s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace ); + + // A cross-domain request is in order when we have a protocol:host:port mismatch + if ( s.crossDomain == null ) { + parts = rurl.exec( s.url.toLowerCase() ); + s.crossDomain = !!( parts && + ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || + ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) != + ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) ) + ); + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( state === 2 ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + fireGlobals = s.global; + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // If data is available, append data to url + if ( s.data ) { + s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Get ifModifiedKey before adding the anti-cache parameter + ifModifiedKey = s.url; + + // Add anti-cache in url if needed + if ( s.cache === false ) { + + var ts = jQuery.now(), + // try replacing _= if it is there + ret = s.url.replace( rts, "$1_=" + ts ); + + // if nothing was replaced, add timestamp to the end + s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + ifModifiedKey = ifModifiedKey || s.url; + if ( jQuery.lastModified[ ifModifiedKey ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] ); + } + if ( jQuery.etag[ ifModifiedKey ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] ); + } + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? + s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { + // Abort if not done already and return + return jqXHR.abort(); + + } + + // aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + for ( i in { success: 1, error: 1, complete: 1 } ) { + jqXHR[ i ]( s[ i ] ); + } + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = setTimeout( function(){ + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + state = 1; + transport.send( requestHeaders, done ); + } catch (e) { + // Propagate exception as error if not done + if ( state < 2 ) { + done( -1, e ); + // Simply rethrow otherwise + } else { + throw e; + } + } + } + + return jqXHR; + }, + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {} + +}); + +/* Handles responses to an ajax request: + * - sets all responseXXX fields accordingly + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes, + responseFields = s.responseFields; + + // Fill responseXXX fields + for ( type in responseFields ) { + if ( type in responses ) { + jqXHR[ responseFields[type] ] = responses[ type ]; + } + } + + // Remove auto dataType and get content-type in the process + while( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "content-type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +// Chain conversions given the request and the original response +function ajaxConvert( s, response ) { + + var conv, conv2, current, tmp, + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(), + prev = dataTypes[ 0 ], + converters = {}, + i = 0; + + // Apply the dataFilter if provided + if ( s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + // Convert to each sequential dataType, tolerating list modification + for ( ; (current = dataTypes[++i]); ) { + + // There's only work to do if current dataType is non-auto + if ( current !== "*" ) { + + // Convert response if prev dataType is non-auto and differs from current + if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split(" "); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.splice( i--, 0, current ); + } + + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s["throws"] ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; + } + } + } + } + + // Update prev for next iteration + prev = current; + } + } + + return { state: "success", data: response }; +} +var oldCallbacks = [], + rquestion = /\?/, + rjsonp = /(=)\?(?=&|$)|\?\?/, + nonce = jQuery.now(); + +// Default jsonp settings +jQuery.ajaxSetup({ + jsonp: "callback", + jsonpCallback: function() { + var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); + this[ callback ] = true; + return callback; + } +}); + +// Detect, normalize options and install callbacks for jsonp requests +jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { + + var callbackName, overwritten, responseContainer, + data = s.data, + url = s.url, + hasCallback = s.jsonp !== false, + replaceInUrl = hasCallback && rjsonp.test( url ), + replaceInData = hasCallback && !replaceInUrl && typeof data === "string" && + !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && + rjsonp.test( data ); + + // Handle iff the expected data type is "jsonp" or we have a parameter to set + if ( s.dataTypes[ 0 ] === "jsonp" || replaceInUrl || replaceInData ) { + + // Get callback name, remembering preexisting value associated with it + callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? + s.jsonpCallback() : + s.jsonpCallback; + overwritten = window[ callbackName ]; + + // Insert callback into url or form data + if ( replaceInUrl ) { + s.url = url.replace( rjsonp, "$1" + callbackName ); + } else if ( replaceInData ) { + s.data = data.replace( rjsonp, "$1" + callbackName ); + } else if ( hasCallback ) { + s.url += ( rquestion.test( url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; + } + + // Use data converter to retrieve json after script execution + s.converters["script json"] = function() { + if ( !responseContainer ) { + jQuery.error( callbackName + " was not called" ); + } + return responseContainer[ 0 ]; + }; + + // force json dataType + s.dataTypes[ 0 ] = "json"; + + // Install callback + window[ callbackName ] = function() { + responseContainer = arguments; + }; + + // Clean-up function (fires after converters) + jqXHR.always(function() { + // Restore preexisting value + window[ callbackName ] = overwritten; + + // Save back as free + if ( s[ callbackName ] ) { + // make sure that re-using the options doesn't screw things around + s.jsonpCallback = originalSettings.jsonpCallback; + + // save the callback name for future use + oldCallbacks.push( callbackName ); + } + + // Call if it was a function and we have a response + if ( responseContainer && jQuery.isFunction( overwritten ) ) { + overwritten( responseContainer[ 0 ] ); + } + + responseContainer = overwritten = undefined; + }); + + // Delegate to script + return "script"; + } +}); +// Install script dataType +jQuery.ajaxSetup({ + accepts: { + script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /javascript|ecmascript/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +}); + +// Handle cache's special case and global +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + s.global = false; + } +}); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function(s) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + + var script, + head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement; + + return { + + send: function( _, callback ) { + + script = document.createElement( "script" ); + + script.async = "async"; + + if ( s.scriptCharset ) { + script.charset = s.scriptCharset; + } + + script.src = s.url; + + // Attach handlers for all browsers + script.onload = script.onreadystatechange = function( _, isAbort ) { + + if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { + + // Handle memory leak in IE + script.onload = script.onreadystatechange = null; + + // Remove the script + if ( head && script.parentNode ) { + head.removeChild( script ); + } + + // Dereference the script + script = undefined; + + // Callback if not abort + if ( !isAbort ) { + callback( 200, "success" ); + } + } + }; + // Use insertBefore instead of appendChild to circumvent an IE6 bug. + // This arises when a base node is used (#2709 and #4378). + head.insertBefore( script, head.firstChild ); + }, + + abort: function() { + if ( script ) { + script.onload( 0, 1 ); + } + } + }; + } +}); +var xhrCallbacks, + // #5280: Internet Explorer will keep connections alive if we don't abort on unload + xhrOnUnloadAbort = window.ActiveXObject ? function() { + // Abort all pending requests + for ( var key in xhrCallbacks ) { + xhrCallbacks[ key ]( 0, 1 ); + } + } : false, + xhrId = 0; + +// Functions to create xhrs +function createStandardXHR() { + try { + return new window.XMLHttpRequest(); + } catch( e ) {} +} + +function createActiveXHR() { + try { + return new window.ActiveXObject( "Microsoft.XMLHTTP" ); + } catch( e ) {} +} + +// Create the request object +// (This is still attached to ajaxSettings for backward compatibility) +jQuery.ajaxSettings.xhr = window.ActiveXObject ? + /* Microsoft failed to properly + * implement the XMLHttpRequest in IE7 (can't request local files), + * so we use the ActiveXObject when it is available + * Additionally XMLHttpRequest can be disabled in IE7/IE8 so + * we need a fallback. + */ + function() { + return !this.isLocal && createStandardXHR() || createActiveXHR(); + } : + // For all other browsers, use the standard XMLHttpRequest object + createStandardXHR; + +// Determine support properties +(function( xhr ) { + jQuery.extend( jQuery.support, { + ajax: !!xhr, + cors: !!xhr && ( "withCredentials" in xhr ) + }); +})( jQuery.ajaxSettings.xhr() ); + +// Create transport if the browser can provide an xhr +if ( jQuery.support.ajax ) { + + jQuery.ajaxTransport(function( s ) { + // Cross domain only allowed if supported through XMLHttpRequest + if ( !s.crossDomain || jQuery.support.cors ) { + + var callback; + + return { + send: function( headers, complete ) { + + // Get a new xhr + var handle, i, + xhr = s.xhr(); + + // Open the socket + // Passing null username, generates a login popup on Opera (#2865) + if ( s.username ) { + xhr.open( s.type, s.url, s.async, s.username, s.password ); + } else { + xhr.open( s.type, s.url, s.async ); + } + + // Apply custom fields if provided + if ( s.xhrFields ) { + for ( i in s.xhrFields ) { + xhr[ i ] = s.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( s.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( s.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !s.crossDomain && !headers["X-Requested-With"] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Need an extra try/catch for cross domain requests in Firefox 3 + try { + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + } catch( _ ) {} + + // Do send the request + // This may raise an exception which is actually + // handled in jQuery.ajax (so no try/catch here) + xhr.send( ( s.hasContent && s.data ) || null ); + + // Listener + callback = function( _, isAbort ) { + + var status, + statusText, + responseHeaders, + responses, + xml; + + // Firefox throws exceptions when accessing properties + // of an xhr when a network error occurred + // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE) + try { + + // Was never called and is aborted or complete + if ( callback && ( isAbort || xhr.readyState === 4 ) ) { + + // Only called once + callback = undefined; + + // Do not keep as active anymore + if ( handle ) { + xhr.onreadystatechange = jQuery.noop; + if ( xhrOnUnloadAbort ) { + delete xhrCallbacks[ handle ]; + } + } + + // If it's an abort + if ( isAbort ) { + // Abort it manually if needed + if ( xhr.readyState !== 4 ) { + xhr.abort(); + } + } else { + status = xhr.status; + responseHeaders = xhr.getAllResponseHeaders(); + responses = {}; + xml = xhr.responseXML; + + // Construct response list + if ( xml && xml.documentElement /* #4958 */ ) { + responses.xml = xml; + } + + // When requesting binary data, IE6-9 will throw an exception + // on any attempt to access responseText (#11426) + try { + responses.text = xhr.responseText; + } catch( e ) { + } + + // Firefox throws an exception when accessing + // statusText for faulty cross-domain requests + try { + statusText = xhr.statusText; + } catch( e ) { + // We normalize with Webkit giving an empty statusText + statusText = ""; + } + + // Filter status for non standard behaviors + + // If the request is local and we have data: assume a success + // (success with no data won't get notified, that's the best we + // can do given current implementations) + if ( !status && s.isLocal && !s.crossDomain ) { + status = responses.text ? 200 : 404; + // IE - #1450: sometimes returns 1223 when it should be 204 + } else if ( status === 1223 ) { + status = 204; + } + } + } + } catch( firefoxAccessException ) { + if ( !isAbort ) { + complete( -1, firefoxAccessException ); + } + } + + // Call complete if needed + if ( responses ) { + complete( status, statusText, responses, responseHeaders ); + } + }; + + if ( !s.async ) { + // if we're in sync mode we fire the callback + callback(); + } else if ( xhr.readyState === 4 ) { + // (IE6 & IE7) if it's in cache and has been + // retrieved directly we need to fire the callback + setTimeout( callback, 0 ); + } else { + handle = ++xhrId; + if ( xhrOnUnloadAbort ) { + // Create the active xhrs callbacks list if needed + // and attach the unload handler + if ( !xhrCallbacks ) { + xhrCallbacks = {}; + jQuery( window ).unload( xhrOnUnloadAbort ); + } + // Add to list of active xhrs callbacks + xhrCallbacks[ handle ] = callback; + } + xhr.onreadystatechange = callback; + } + }, + + abort: function() { + if ( callback ) { + callback(0,1); + } + } + }; + } + }); +} +var fxNow, timerId, + rfxtypes = /^(?:toggle|show|hide)$/, + rfxnum = new RegExp( "^(?:([-+])=|)(" + core_pnum + ")([a-z%]*)$", "i" ), + rrun = /queueHooks$/, + animationPrefilters = [ defaultPrefilter ], + tweeners = { + "*": [function( prop, value ) { + var end, unit, + tween = this.createTween( prop, value ), + parts = rfxnum.exec( value ), + target = tween.cur(), + start = +target || 0, + scale = 1, + maxIterations = 20; + + if ( parts ) { + end = +parts[2]; + unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + + // We need to compute starting value + if ( unit !== "px" && start ) { + // Iteratively approximate from a nonzero starting point + // Prefer the current property, because this process will be trivial if it uses the same units + // Fallback to end or a simple constant + start = jQuery.css( tween.elem, prop, true ) || end || 1; + + do { + // If previous iteration zeroed out, double until we get *something* + // Use a string for doubling factor so we don't accidentally see scale as unchanged below + scale = scale || ".5"; + + // Adjust and apply + start = start / scale; + jQuery.style( tween.elem, prop, start + unit ); + + // Update scale, tolerating zero or NaN from tween.cur() + // And breaking the loop if scale is unchanged or perfect, or if we've just had enough + } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); + } + + tween.unit = unit; + tween.start = start; + // If a +=/-= token was provided, we're doing a relative animation + tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end; + } + return tween; + }] + }; + +// Animations created synchronously will run synchronously +function createFxNow() { + setTimeout(function() { + fxNow = undefined; + }, 0 ); + return ( fxNow = jQuery.now() ); +} + +function createTweens( animation, props ) { + jQuery.each( props, function( prop, value ) { + var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( collection[ index ].call( animation, prop, value ) ) { + + // we're done with this property + return; + } + } + }); +} + +function Animation( elem, properties, options ) { + var result, + index = 0, + tweenerIndex = 0, + length = animationPrefilters.length, + deferred = jQuery.Deferred().always( function() { + // don't match elem in the :animated selector + delete tick.elem; + }), + tick = function() { + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length ; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ]); + + if ( percent < 1 && length ) { + return remaining; + } else { + deferred.resolveWith( elem, [ animation ] ); + return false; + } + }, + animation = deferred.promise({ + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { specialEasing: {} }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end, easing ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + // if we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + + for ( ; index < length ; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // resolve when we played the last frame + // otherwise, reject + if ( gotoEnd ) { + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + }), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length ; index++ ) { + result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + return result; + } + } + + createTweens( animation, props ); + + if ( jQuery.isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + jQuery.fx.timer( + jQuery.extend( tick, { + anim: animation, + queue: animation.opts.queue, + elem: elem + }) + ); + + // attach callbacks from options + return animation.progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = jQuery.camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( jQuery.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // not quite $.extend, this wont overwrite keys already present. + // also - reusing 'index' from above because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweener: function( props, callback ) { + if ( jQuery.isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.split(" "); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length ; index++ ) { + prop = props[ index ]; + tweeners[ prop ] = tweeners[ prop ] || []; + tweeners[ prop ].unshift( callback ); + } + }, + + prefilter: function( callback, prepend ) { + if ( prepend ) { + animationPrefilters.unshift( callback ); + } else { + animationPrefilters.push( callback ); + } + } +}); + +function defaultPrefilter( elem, props, opts ) { + var index, prop, value, length, dataShow, toggle, tween, hooks, oldfire, + anim = this, + style = elem.style, + orig = {}, + handled = [], + hidden = elem.nodeType && isHidden( elem ); + + // handle queue: false promises + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always(function() { + // doing this makes sure that the complete handler will be called + // before this completes + anim.always(function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + }); + }); + } + + // height/width overflow pass + if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { + // Make sure that nothing sneaks out + // Record all 3 overflow attributes because IE does not + // change the overflow attribute when overflowX and + // overflowY are set to the same value + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Set display property to inline-block for height/width + // animations on inline elements that are having width/height animated + if ( jQuery.css( elem, "display" ) === "inline" && + jQuery.css( elem, "float" ) === "none" ) { + + // inline-level elements accept inline-block; + // block-level elements need to be inline with layout + if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) { + style.display = "inline-block"; + + } else { + style.zoom = 1; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + if ( !jQuery.support.shrinkWrapBlocks ) { + anim.done(function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + }); + } + } + + + // show/hide pass + for ( index in props ) { + value = props[ index ]; + if ( rfxtypes.exec( value ) ) { + delete props[ index ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + continue; + } + handled.push( index ); + } + } + + length = handled.length; + if ( length ) { + dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} ); + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + + // store state if its toggle - enables .stop().toggle() to "reverse" + if ( toggle ) { + dataShow.hidden = !hidden; + } + if ( hidden ) { + jQuery( elem ).show(); + } else { + anim.done(function() { + jQuery( elem ).hide(); + }); + } + anim.done(function() { + var prop; + jQuery.removeData( elem, "fxshow", true ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + }); + for ( index = 0 ; index < length ; index++ ) { + prop = handled[ index ]; + tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 ); + orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop ); + + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = tween.start; + if ( hidden ) { + tween.end = tween.start; + tween.start = prop === "width" || prop === "height" ? 1 : 0; + } + } + } + } +} + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || "swing"; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + if ( tween.elem[ tween.prop ] != null && + (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { + return tween.elem[ tween.prop ]; + } + + // passing any value as a 4th parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails + // so, simple values such as "10px" are parsed to Float. + // complex values such as "rotate(1rad)" are returned as is. + result = jQuery.css( tween.elem, tween.prop, false, "" ); + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + // use step hook for back compat - use cssHook if its there - use .style if its + // available and use plain properties where available + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Remove in 2.0 - this supports IE8's panic based approach +// to setting things on disconnected nodes + +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" || + // special check for .toggle( handler, handler, ... ) + ( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +}); + +jQuery.fn.extend({ + fadeTo: function( speed, to, easing, callback ) { + + // show any hidden elements after setting opacity to 0 + return this.filter( isHidden ).css( "opacity", 0 ).show() + + // animate to the value specified + .end().animate({ opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations resolve immediately + if ( empty ) { + anim.stop( true ); + } + }; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each(function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = jQuery._data( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // start the next in the queue if the last step wasn't forced + // timers currently will call their complete callbacks, which will dequeue + // but only if they were gotoEnd + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + }); + } +}); + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + attrs = { height: type }, + i = 0; + + // if we include width, step value is 1 to do all cssExpand values, + // if we don't include width, step value is 2 to skip over Left and Right + includeWidth = includeWidth? 1 : 0; + for( ; i < 4 ; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +// Generate shortcuts for custom animations +jQuery.each({ + slideDown: genFx("show"), + slideUp: genFx("hide"), + slideToggle: genFx("toggle"), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +}); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing + }; + + opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : + opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; + + // normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p*Math.PI ) / 2; + } +}; + +jQuery.timers = []; +jQuery.fx = Tween.prototype.init; +jQuery.fx.tick = function() { + var timer, + timers = jQuery.timers, + i = 0; + + fxNow = jQuery.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + // Checks the timer has not already been removed + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + if ( timer() && jQuery.timers.push( timer ) && !timerId ) { + timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); + } +}; + +jQuery.fx.interval = 13; + +jQuery.fx.stop = function() { + clearInterval( timerId ); + timerId = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + // Default speed + _default: 400 +}; + +// Back Compat <1.8 extension point +jQuery.fx.step = {}; + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.animated = function( elem ) { + return jQuery.grep(jQuery.timers, function( fn ) { + return elem === fn.elem; + }).length; + }; +} +var rroot = /^(?:body|html)$/i; + +jQuery.fn.offset = function( options ) { + if ( arguments.length ) { + return options === undefined ? + this : + this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + var docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft, + box = { top: 0, left: 0 }, + elem = this[ 0 ], + doc = elem && elem.ownerDocument; + + if ( !doc ) { + return; + } + + if ( (body = doc.body) === elem ) { + return jQuery.offset.bodyOffset( elem ); + } + + docElem = doc.documentElement; + + // Make sure it's not a disconnected DOM node + if ( !jQuery.contains( docElem, elem ) ) { + return box; + } + + // If we don't have gBCR, just use 0,0 rather than error + // BlackBerry 5, iOS 3 (original iPhone) + if ( typeof elem.getBoundingClientRect !== "undefined" ) { + box = elem.getBoundingClientRect(); + } + win = getWindow( doc ); + clientTop = docElem.clientTop || body.clientTop || 0; + clientLeft = docElem.clientLeft || body.clientLeft || 0; + scrollTop = win.pageYOffset || docElem.scrollTop; + scrollLeft = win.pageXOffset || docElem.scrollLeft; + return { + top: box.top + scrollTop - clientTop, + left: box.left + scrollLeft - clientLeft + }; +}; + +jQuery.offset = { + + bodyOffset: function( body ) { + var top = body.offsetTop, + left = body.offsetLeft; + + if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) { + top += parseFloat( jQuery.css(body, "marginTop") ) || 0; + left += parseFloat( jQuery.css(body, "marginLeft") ) || 0; + } + + return { top: top, left: left }; + }, + + setOffset: function( elem, options, i ) { + var position = jQuery.css( elem, "position" ); + + // set position first, in-case top/left are set even on static elem + if ( position === "static" ) { + elem.style.position = "relative"; + } + + var curElem = jQuery( elem ), + curOffset = curElem.offset(), + curCSSTop = jQuery.css( elem, "top" ), + curCSSLeft = jQuery.css( elem, "left" ), + calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1, + props = {}, curPosition = {}, curTop, curLeft; + + // need to be able to calculate position if either top or left is auto and position is either absolute or fixed + if ( calculatePosition ) { + curPosition = curElem.position(); + curTop = curPosition.top; + curLeft = curPosition.left; + } else { + curTop = parseFloat( curCSSTop ) || 0; + curLeft = parseFloat( curCSSLeft ) || 0; + } + + if ( jQuery.isFunction( options ) ) { + options = options.call( elem, i, curOffset ); + } + + if ( options.top != null ) { + props.top = ( options.top - curOffset.top ) + curTop; + } + if ( options.left != null ) { + props.left = ( options.left - curOffset.left ) + curLeft; + } + + if ( "using" in options ) { + options.using.call( elem, props ); + } else { + curElem.css( props ); + } + } +}; + + +jQuery.fn.extend({ + + position: function() { + if ( !this[0] ) { + return; + } + + var elem = this[0], + + // Get *real* offsetParent + offsetParent = this.offsetParent(), + + // Get correct offsets + offset = this.offset(), + parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); + + // Subtract element margins + // note: when an element has margin: auto the offsetLeft and marginLeft + // are the same in Safari causing offset.left to incorrectly be 0 + offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; + offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; + + // Add offsetParent borders + parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; + parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; + + // Subtract the two offsets + return { + top: offset.top - parentOffset.top, + left: offset.left - parentOffset.left + }; + }, + + offsetParent: function() { + return this.map(function() { + var offsetParent = this.offsetParent || document.body; + while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { + offsetParent = offsetParent.offsetParent; + } + return offsetParent || document.body; + }); + } +}); + + +// Create scrollLeft and scrollTop methods +jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) { + var top = /Y/.test( prop ); + + jQuery.fn[ method ] = function( val ) { + return jQuery.access( this, function( elem, method, val ) { + var win = getWindow( elem ); + + if ( val === undefined ) { + return win ? (prop in win) ? win[ prop ] : + win.document.documentElement[ method ] : + elem[ method ]; + } + + if ( win ) { + win.scrollTo( + !top ? val : jQuery( win ).scrollLeft(), + top ? val : jQuery( win ).scrollTop() + ); + + } else { + elem[ method ] = val; + } + }, method, val, arguments.length, null ); + }; +}); + +function getWindow( elem ) { + return jQuery.isWindow( elem ) ? + elem : + elem.nodeType === 9 ? + elem.defaultView || elem.parentWindow : + false; +} +// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods +jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { + jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { + // margin is only for outerHeight, outerWidth + jQuery.fn[ funcName ] = function( margin, value ) { + var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), + extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); + + return jQuery.access( this, function( elem, type, value ) { + var doc; + + if ( jQuery.isWindow( elem ) ) { + // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there + // isn't a whole lot we can do. See pull request at this URL for discussion: + // https://github.com/jquery/jquery/pull/764 + return elem.document.documentElement[ "client" + name ]; + } + + // Get document width or height + if ( elem.nodeType === 9 ) { + doc = elem.documentElement; + + // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest + // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it. + return Math.max( + elem.body[ "scroll" + name ], doc[ "scroll" + name ], + elem.body[ "offset" + name ], doc[ "offset" + name ], + doc[ "client" + name ] + ); + } + + return value === undefined ? + // Get width or height on the element, requesting but not forcing parseFloat + jQuery.css( elem, type, value, extra ) : + + // Set width or height on the element + jQuery.style( elem, type, value, extra ); + }, type, chainable ? margin : undefined, chainable, null ); + }; + }); +}); +// Expose jQuery to the global object +window.jQuery = window.$ = jQuery; + +// Expose jQuery as an AMD module, but only for AMD loaders that +// understand the issues with loading multiple versions of jQuery +// in a page that all might call define(). The loader will indicate +// they have special allowances for multiple jQuery versions by +// specifying define.amd.jQuery = true. Register as a named module, +// since jQuery can be concatenated with other files that may use define, +// but not use a proper concatenation script that understands anonymous +// AMD modules. A named AMD is safest and most robust way to register. +// Lowercase jquery is used because AMD module names are derived from +// file names, and jQuery is normally delivered in a lowercase file name. +// Do this after creating the global so that if an AMD module wants to call +// noConflict to hide this version of jQuery, it will work. +if ( typeof define === "function" && define.amd && define.amd.jQuery ) { + define( "jquery", [], function () { return jQuery; } ); +} + +})( window ); diff --git a/src/admin/application/templates/js/jquery.min.js b/src/admin/application/templates/js/jquery.min.js new file mode 100644 index 0000000..83589da --- /dev/null +++ b/src/admin/application/templates/js/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.3 jquery.com | jquery.org/license */ +(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r<i;r++)v.event.add(t,n,u[n][r])}o.data&&(o.data=v.extend({},o.data))}function Ot(e,t){var n;if(t.nodeType!==1)return;t.clearAttributes&&t.clearAttributes(),t.mergeAttributes&&t.mergeAttributes(e),n=t.nodeName.toLowerCase(),n==="object"?(t.parentNode&&(t.outerHTML=e.outerHTML),v.support.html5Clone&&e.innerHTML&&!v.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):n==="input"&&Et.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):n==="option"?t.selected=e.defaultSelected:n==="input"||n==="textarea"?t.defaultValue=e.defaultValue:n==="script"&&t.text!==e.text&&(t.text=e.text),t.removeAttribute(v.expando)}function Mt(e){return typeof e.getElementsByTagName!="undefined"?e.getElementsByTagName("*"):typeof e.querySelectorAll!="undefined"?e.querySelectorAll("*"):[]}function _t(e){Et.test(e.type)&&(e.defaultChecked=e.checked)}function Qt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Jt.length;while(i--){t=Jt[i]+n;if(t in e)return t}return r}function Gt(e,t){return e=t||e,v.css(e,"display")==="none"||!v.contains(e.ownerDocument,e)}function Yt(e,t){var n,r,i=[],s=0,o=e.length;for(;s<o;s++){n=e[s];if(!n.style)continue;i[s]=v._data(n,"olddisplay"),t?(!i[s]&&n.style.display==="none"&&(n.style.display=""),n.style.display===""&&Gt(n)&&(i[s]=v._data(n,"olddisplay",nn(n.nodeName)))):(r=Dt(n,"display"),!i[s]&&r!=="none"&&v._data(n,"olddisplay",r))}for(s=0;s<o;s++){n=e[s];if(!n.style)continue;if(!t||n.style.display==="none"||n.style.display==="")n.style.display=t?i[s]||"":"none"}return e}function Zt(e,t,n){var r=Rt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function en(e,t,n,r){var i=n===(r?"border":"content")?4:t==="width"?1:0,s=0;for(;i<4;i+=2)n==="margin"&&(s+=v.css(e,n+$t[i],!0)),r?(n==="content"&&(s-=parseFloat(Dt(e,"padding"+$t[i]))||0),n!=="margin"&&(s-=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0)):(s+=parseFloat(Dt(e,"padding"+$t[i]))||0,n!=="padding"&&(s+=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0));return s}function tn(e,t,n){var r=t==="width"?e.offsetWidth:e.offsetHeight,i=!0,s=v.support.boxSizing&&v.css(e,"boxSizing")==="border-box";if(r<=0||r==null){r=Dt(e,t);if(r<0||r==null)r=e.style[t];if(Ut.test(r))return r;i=s&&(v.support.boxSizingReliable||r===e.style[t]),r=parseFloat(r)||0}return r+en(e,t,n||(s?"border":"content"),i)+"px"}function nn(e){if(Wt[e])return Wt[e];var t=v("<"+e+">").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write("<!doctype html><html><body>"),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u<a;u++)r=o[u],s=/^\+/.test(r),s&&(r=r.substr(1)||"*"),i=e[r]=e[r]||[],i[s?"unshift":"push"](n)}}function kn(e,n,r,i,s,o){s=s||n.dataTypes[0],o=o||{},o[s]=!0;var u,a=e[s],f=0,l=a?a.length:0,c=e===Sn;for(;f<l&&(c||!u);f++)u=a[f](n,r,i),typeof u=="string"&&(!c||o[u]?u=t:(n.dataTypes.unshift(u),u=kn(e,n,r,i,u,o)));return(c||!u)&&!o["*"]&&(u=kn(e,n,r,i,"*",o)),u}function Ln(e,n){var r,i,s=v.ajaxSettings.flatOptions||{};for(r in n)n[r]!==t&&((s[r]?e:i||(i={}))[r]=n[r]);i&&v.extend(!0,e,i)}function An(e,n,r){var i,s,o,u,a=e.contents,f=e.dataTypes,l=e.responseFields;for(s in l)s in r&&(n[l[s]]=r[s]);while(f[0]==="*")f.shift(),i===t&&(i=e.mimeType||n.getResponseHeader("content-type"));if(i)for(s in a)if(a[s]&&a[s].test(i)){f.unshift(s);break}if(f[0]in r)o=f[0];else{for(s in r){if(!f[0]||e.converters[s+" "+f[0]]){o=s;break}u||(u=s)}o=o||u}if(o)return o!==f[0]&&f.unshift(o),r[o]}function On(e,t){var n,r,i,s,o=e.dataTypes.slice(),u=o[0],a={},f=0;e.dataFilter&&(t=e.dataFilter(t,e.dataType));if(o[1])for(n in e.converters)a[n.toLowerCase()]=e.converters[n];for(;i=o[++f];)if(i!=="*"){if(u!=="*"&&u!==i){n=a[u+" "+i]||a["* "+i];if(!n)for(r in a){s=r.split(" ");if(s[1]===i){n=a[u+" "+s[0]]||a["* "+s[0]];if(n){n===!0?n=a[r]:a[r]!==!0&&(i=s[0],o.splice(f--,0,i));break}}}if(n!==!0)if(n&&e["throws"])t=n(t);else try{t=n(t)}catch(l){return{state:"parsererror",error:n?l:"No conversion from "+u+" to "+i}}}u=i}return{state:"success",data:t}}function Fn(){try{return new e.XMLHttpRequest}catch(t){}}function In(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function $n(){return setTimeout(function(){qn=t},0),qn=v.now()}function Jn(e,t){v.each(t,function(t,n){var r=(Vn[t]||[]).concat(Vn["*"]),i=0,s=r.length;for(;i<s;i++)if(r[i].call(e,t,n))return})}function Kn(e,t,n){var r,i=0,s=0,o=Xn.length,u=v.Deferred().always(function(){delete a.elem}),a=function(){var t=qn||$n(),n=Math.max(0,f.startTime+f.duration-t),r=n/f.duration||0,i=1-r,s=0,o=f.tweens.length;for(;s<o;s++)f.tweens[s].run(i);return u.notifyWith(e,[f,i,n]),i<1&&o?n:(u.resolveWith(e,[f]),!1)},f=u.promise({elem:e,props:v.extend({},t),opts:v.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:qn||$n(),duration:n.duration,tweens:[],createTween:function(t,n,r){var i=v.Tween(e,f.opts,t,n,f.opts.specialEasing[t]||f.opts.easing);return f.tweens.push(i),i},stop:function(t){var n=0,r=t?f.tweens.length:0;for(;n<r;n++)f.tweens[n].run(1);return t?u.resolveWith(e,[f,t]):u.rejectWith(e,[f,t]),this}}),l=f.props;Qn(l,f.opts.specialEasing);for(;i<o;i++){r=Xn[i].call(f,e,l,f.opts);if(r)return r}return Jn(f,l),v.isFunction(f.opts.start)&&f.opts.start.call(e,f),v.fx.timer(v.extend(a,{anim:f,queue:f.opts.queue,elem:e})),f.progress(f.opts.progress).done(f.opts.done,f.opts.complete).fail(f.opts.fail).always(f.opts.always)}function Qn(e,t){var n,r,i,s,o;for(n in e){r=v.camelCase(n),i=t[r],s=e[n],v.isArray(s)&&(i=s[1],s=e[n]=s[0]),n!==r&&(e[r]=s,delete e[n]),o=v.cssHooks[r];if(o&&"expand"in o){s=o.expand(s),delete e[r];for(n in s)n in e||(e[n]=s[n],t[n]=i)}else t[r]=i}}function Gn(e,t,n){var r,i,s,o,u,a,f,l,c,h=this,p=e.style,d={},m=[],g=e.nodeType&&Gt(e);n.queue||(l=v._queueHooks(e,"fx"),l.unqueued==null&&(l.unqueued=0,c=l.empty.fire,l.empty.fire=function(){l.unqueued||c()}),l.unqueued++,h.always(function(){h.always(function(){l.unqueued--,v.queue(e,"fx").length||l.empty.fire()})})),e.nodeType===1&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],v.css(e,"display")==="inline"&&v.css(e,"float")==="none"&&(!v.support.inlineBlockNeedsLayout||nn(e.nodeName)==="inline"?p.display="inline-block":p.zoom=1)),n.overflow&&(p.overflow="hidden",v.support.shrinkWrapBlocks||h.done(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t){s=t[r];if(Un.exec(s)){delete t[r],a=a||s==="toggle";if(s===(g?"hide":"show"))continue;m.push(r)}}o=m.length;if(o){u=v._data(e,"fxshow")||v._data(e,"fxshow",{}),"hidden"in u&&(g=u.hidden),a&&(u.hidden=!g),g?v(e).show():h.done(function(){v(e).hide()}),h.done(function(){var t;v.removeData(e,"fxshow",!0);for(t in d)v.style(e,t,d[t])});for(r=0;r<o;r++)i=m[r],f=h.createTween(i,g?u[i]:0),d[i]=u[i]||v.style(e,i),i in u||(u[i]=f.start,g&&(f.end=f.start,f.start=i==="width"||i==="height"?1:0))}}function Yn(e,t,n,r,i){return new Yn.prototype.init(e,t,n,r,i)}function Zn(e,t){var n,r={height:e},i=0;t=t?1:0;for(;i<4;i+=2-t)n=$t[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}function tr(e){return v.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:!1}var n,r,i=e.document,s=e.location,o=e.navigator,u=e.jQuery,a=e.$,f=Array.prototype.push,l=Array.prototype.slice,c=Array.prototype.indexOf,h=Object.prototype.toString,p=Object.prototype.hasOwnProperty,d=String.prototype.trim,v=function(e,t){return new v.fn.init(e,t,n)},m=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,g=/\S/,y=/\s+/,b=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,w=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a<f;a++)if((e=arguments[a])!=null)for(n in e){r=u[n],i=e[n];if(u===i)continue;l&&i&&(v.isPlainObject(i)||(s=v.isArray(i)))?(s?(s=!1,o=r&&v.isArray(r)?r:[]):o=r&&v.isPlainObject(r)?r:{},u[n]=v.extend(l,o,i)):i!==t&&(u[n]=i)}return u},v.extend({noConflict:function(t){return e.$===v&&(e.$=a),t&&e.jQuery===v&&(e.jQuery=u),v},isReady:!1,readyWait:1,holdReady:function(e){e?v.readyWait++:v.ready(!0)},ready:function(e){if(e===!0?--v.readyWait:v.isReady)return;if(!i.body)return setTimeout(v.ready,1);v.isReady=!0;if(e!==!0&&--v.readyWait>0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s<o;)if(n.apply(e[s++],r)===!1)break}else if(u){for(i in e)if(n.call(e[i],i,e[i])===!1)break}else for(;s<o;)if(n.call(e[s],s,e[s++])===!1)break;return e},trim:d&&!d.call("\ufeff\u00a0")?function(e){return e==null?"":d.call(e)}:function(e){return e==null?"":(e+"").replace(b,"")},makeArray:function(e,t){var n,r=t||[];return e!=null&&(n=v.type(e),e.length==null||n==="string"||n==="function"||n==="regexp"||v.isWindow(e)?f.call(r,e):v.merge(r,e)),r},inArray:function(e,t,n){var r;if(t){if(c)return c.call(t,e,n);r=t.length,n=n?n<0?Math.max(0,r+n):n:0;for(;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,s=0;if(typeof r=="number")for(;s<r;s++)e[i++]=n[s];else while(n[s]!==t)e[i++]=n[s++];return e.length=i,e},grep:function(e,t,n){var r,i=[],s=0,o=e.length;n=!!n;for(;s<o;s++)r=!!t(e[s],s),n!==r&&i.push(e[s]);return i},map:function(e,n,r){var i,s,o=[],u=0,a=e.length,f=e instanceof v||a!==t&&typeof a=="number"&&(a>0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u<a;u++)i=n(e[u],u,r),i!=null&&(o[o.length]=i);else for(s in e)i=n(e[s],s,r),i!=null&&(o[o.length]=i);return o.concat.apply([],o)},guid:1,proxy:function(e,n){var r,i,s;return typeof n=="string"&&(r=e[n],n=e,e=r),v.isFunction(e)?(i=l.call(arguments,2),s=function(){return e.apply(n,i.concat(l.call(arguments)))},s.guid=e.guid=e.guid||v.guid++,s):t},access:function(e,n,r,i,s,o,u){var a,f=r==null,l=0,c=e.length;if(r&&typeof r=="object"){for(l in r)v.access(e,n,l,r[l],1,o,i);s=1}else if(i!==t){a=u===t&&v.isFunction(i),f&&(a?(a=n,n=function(e,t,n){return a.call(v(e),n)}):(n.call(e,i),n=null));if(n)for(;l<c;l++)n(e[l],r,a?i.call(e[l],l,n(e[l],r)):i,u);s=1}return s?e:f?n.call(e):c?n(e[0],r):o},now:function(){return(new Date).getTime()}}),v.ready.promise=function(t){if(!r){r=v.Deferred();if(i.readyState==="complete")setTimeout(v.ready,1);else if(i.addEventListener)i.addEventListener("DOMContentLoaded",A,!1),e.addEventListener("load",v.ready,!1);else{i.attachEvent("onreadystatechange",A),e.attachEvent("onload",v.ready);var n=!1;try{n=e.frameElement==null&&i.documentElement}catch(s){}n&&n.doScroll&&function o(){if(!v.isReady){try{n.doScroll("left")}catch(e){return setTimeout(o,50)}v.ready()}}()}}return r.promise(t)},v.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(e,t){O["[object "+t+"]"]=t.toLowerCase()}),n=v(i);var M={};v.Callbacks=function(e){e=typeof e=="string"?M[e]||_(e):v.extend({},e);var n,r,i,s,o,u,a=[],f=!e.once&&[],l=function(t){n=e.memory&&t,r=!0,u=s||0,s=0,o=a.length,i=!0;for(;a&&u<o;u++)if(a[u].apply(t[0],t[1])===!1&&e.stopOnFalse){n=!1;break}i=!1,a&&(f?f.length&&l(f.shift()):n?a=[]:c.disable())},c={add:function(){if(a){var t=a.length;(function r(t){v.each(t,function(t,n){var i=v.type(n);i==="function"?(!e.unique||!c.has(n))&&a.push(n):n&&n.length&&i!=="string"&&r(n)})})(arguments),i?o=a.length:n&&(s=t,l(n))}return this},remove:function(){return a&&v.each(arguments,function(e,t){var n;while((n=v.inArray(t,a,n))>-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t<r;t++)n[t]&&v.isFunction(n[t].promise)?n[t].promise().done(o(t,f,n)).fail(s.reject).progress(o(t,a,u)):--i}return i||s.resolveWith(f,n),s.promise()}}),v.support=function(){var t,n,r,s,o,u,a,f,l,c,h,p=i.createElement("div");p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="<table><tr><td></td><td>t</td></tr></table>",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="<div></div>",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i<s;i++)delete r[t[i]];if(!(n?B:v.isEmptyObject)(r))return}}if(!n){delete u[a].data;if(!B(u[a]))return}o?v.cleanData([e],!0):v.support.deleteExpando||u!=u.window?delete u[a]:u[a]=null},_data:function(e,t,n){return v.data(e,t,n,!0)},acceptData:function(e){var t=e.nodeName&&v.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),v.fn.extend({data:function(e,n){var r,i,s,o,u,a=this[0],f=0,l=null;if(e===t){if(this.length){l=v.data(a);if(a.nodeType===1&&!v._data(a,"parsedAttrs")){s=a.attributes;for(u=s.length;f<u;f++)o=s[f].name,o.indexOf("data-")||(o=v.camelCase(o.substring(5)),H(a,o,l[o]));v._data(a,"parsedAttrs",!0)}}return l}return typeof e=="object"?this.each(function(){v.data(this,e)}):(r=e.split(".",2),r[1]=r[1]?"."+r[1]:"",i=r[1]+"!",v.access(this,function(n){if(n===t)return l=this.triggerHandler("getData"+i,[r[0]]),l===t&&a&&(l=v.data(a,e),l=H(a,e,l)),l===t&&r[1]?this.data(r[0]):l;r[1]=n,this.each(function(){var t=v(this);t.triggerHandler("setData"+i,r),v.data(this,e,n),t.triggerHandler("changeData"+i,r)})},null,n,arguments.length>1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length<r?v.queue(this[0],e):n===t?this:this.each(function(){var t=v.queue(this,e,n);v._queueHooks(this,e),e==="fx"&&t[0]!=="inprogress"&&v.dequeue(this,e)})},dequeue:function(e){return this.each(function(){v.dequeue(this,e)})},delay:function(e,t){return e=v.fx?v.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,s=v.Deferred(),o=this,u=this.length,a=function(){--i||s.resolveWith(o,[o])};typeof e!="string"&&(n=e,e=t),e=e||"fx";while(u--)r=v._data(o[u],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(a));return a(),s.promise(n)}});var j,F,I,q=/[\t\r\n]/g,R=/\r/g,U=/^(?:button|input)$/i,z=/^(?:button|input|object|select|textarea)$/i,W=/^a(?:rea|)$/i,X=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,V=v.support.getSetAttribute;v.fn.extend({attr:function(e,t){return v.access(this,v.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n<r;n++){i=this[n];if(i.nodeType===1)if(!i.className&&t.length===1)i.className=e;else{s=" "+i.className+" ";for(o=0,u=t.length;o<u;o++)s.indexOf(" "+t[o]+" ")<0&&(s+=t[o]+" ");i.className=v.trim(s)}}}return this},removeClass:function(e){var n,r,i,s,o,u,a;if(v.isFunction(e))return this.each(function(t){v(this).removeClass(e.call(this,t,this.className))});if(e&&typeof e=="string"||e===t){n=(e||"").split(y);for(u=0,a=this.length;u<a;u++){i=this[u];if(i.nodeType===1&&i.className){r=(" "+i.className+" ").replace(q," ");for(s=0,o=n.length;s<o;s++)while(r.indexOf(" "+n[s]+" ")>=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n<r;n++)if(this[n].nodeType===1&&(" "+this[n].className+" ").replace(q," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a<u;a++){n=r[a];if((n.selected||a===i)&&(v.support.optDisabled?!n.disabled:n.getAttribute("disabled")===null)&&(!n.parentNode.disabled||!v.nodeName(n.parentNode,"optgroup"))){t=v(n).val();if(s)return t;o.push(t)}}return o},set:function(e,t){var n=v.makeArray(t);return v(e).find("option").each(function(){this.selected=v.inArray(v(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o<r.length;o++)i=r[o],i&&(n=v.propFix[i]||i,s=X.test(i),s||v.attr(e,i,""),e.removeAttribute(V?i:n),s&&n in e&&(e[n]=!1))}},attrHooks:{type:{set:function(e,t){if(U.test(e.nodeName)&&e.parentNode)v.error("type property can't be changed");else if(!v.support.radioValue&&t==="radio"&&v.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}},value:{get:function(e,t){return j&&v.nodeName(e,"button")?j.get(e,t):t in e?e.value:null},set:function(e,t,n){if(j&&v.nodeName(e,"button"))return j.set(e,t,n);e.value=t}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,s,o,u=e.nodeType;if(!e||u===3||u===8||u===2)return;return o=u!==1||!v.isXMLDoc(e),o&&(n=v.propFix[n]||n,s=v.propHooks[n]),r!==t?s&&"set"in s&&(i=s.set(e,r,n))!==t?i:e[n]=r:s&&"get"in s&&(i=s.get(e,n))!==null?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):z.test(e.nodeName)||W.test(e.nodeName)&&e.href?0:t}}}}),F={get:function(e,n){var r,i=v.prop(e,n);return i===!0||typeof i!="boolean"&&(r=e.getAttributeNode(n))&&r.nodeValue!==!1?n.toLowerCase():t},set:function(e,t,n){var r;return t===!1?v.removeAttr(e,n):(r=v.propFix[n]||n,r in e&&(e[r]=!0),e.setAttribute(n,n.toLowerCase())),n}},V||(I={name:!0,id:!0,coords:!0},j=v.valHooks.button={get:function(e,n){var r;return r=e.getAttributeNode(n),r&&(I[n]?r.value!=="":r.specified)?r.value:t},set:function(e,t,n){var r=e.getAttributeNode(n);return r||(r=i.createAttribute(n),e.setAttributeNode(r)),r.value=t+""}},v.each(["width","height"],function(e,t){v.attrHooks[t]=v.extend(v.attrHooks[t],{set:function(e,n){if(n==="")return e.setAttribute(t,"auto"),n}})}),v.attrHooks.contenteditable={get:j.get,set:function(e,t,n){t===""&&(t="false"),j.set(e,t,n)}}),v.support.hrefNormalized||v.each(["href","src","width","height"],function(e,n){v.attrHooks[n]=v.extend(v.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return r===null?t:r}})}),v.support.style||(v.attrHooks.style={get:function(e){return e.style.cssText.toLowerCase()||t},set:function(e,t){return e.style.cssText=t+""}}),v.support.optSelected||(v.propHooks.selected=v.extend(v.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),v.support.enctype||(v.propFix.enctype="encoding"),v.support.checkOn||v.each(["radio","checkbox"],function(){v.valHooks[this]={get:function(e){return e.getAttribute("value")===null?"on":e.value}}}),v.each(["radio","checkbox"],function(){v.valHooks[this]=v.extend(v.valHooks[this],{set:function(e,t){if(v.isArray(t))return e.checked=v.inArray(v(e).val(),t)>=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f<n.length;f++){l=J.exec(n[f])||[],c=l[1],h=(l[2]||"").split(".").sort(),g=v.event.special[c]||{},c=(s?g.delegateType:g.bindType)||c,g=v.event.special[c]||{},p=v.extend({type:c,origType:l[1],data:i,handler:r,guid:r.guid,selector:s,needsContext:s&&v.expr.match.needsContext.test(s),namespace:h.join(".")},d),m=a[c];if(!m){m=a[c]=[],m.delegateCount=0;if(!g.setup||g.setup.call(e,i,h,u)===!1)e.addEventListener?e.addEventListener(c,u,!1):e.attachEvent&&e.attachEvent("on"+c,u)}g.add&&(g.add.call(e,p),p.handler.guid||(p.handler.guid=r.guid)),s?m.splice(m.delegateCount++,0,p):m.push(p),v.event.global[c]=!0}e=null},global:{},remove:function(e,t,n,r,i){var s,o,u,a,f,l,c,h,p,d,m,g=v.hasData(e)&&v._data(e);if(!g||!(h=g.events))return;t=v.trim(Z(t||"")).split(" ");for(s=0;s<t.length;s++){o=J.exec(t[s])||[],u=a=o[1],f=o[2];if(!u){for(u in h)v.event.remove(e,u+t[s],n,r,!0);continue}p=v.event.special[u]||{},u=(r?p.delegateType:p.bindType)||u,d=h[u]||[],l=d.length,f=f?new RegExp("(^|\\.)"+f.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(c=0;c<d.length;c++)m=d[c],(i||a===m.origType)&&(!n||n.guid===m.guid)&&(!f||f.test(m.namespace))&&(!r||r===m.selector||r==="**"&&m.selector)&&(d.splice(c--,1),m.selector&&d.delegateCount--,p.remove&&p.remove.call(e,m));d.length===0&&l!==d.length&&((!p.teardown||p.teardown.call(e,f,g.handle)===!1)&&v.removeEvent(e,u,g.handle),delete h[u])}v.isEmptyObject(h)&&(delete g.handle,v.removeData(e,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(n,r,s,o){if(!s||s.nodeType!==3&&s.nodeType!==8){var u,a,f,l,c,h,p,d,m,g,y=n.type||n,b=[];if(Y.test(y+v.event.triggered))return;y.indexOf("!")>=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f<m.length&&!n.isPropagationStopped();f++)l=m[f][0],n.type=m[f][1],d=(v._data(l,"events")||{})[n.type]&&v._data(l,"handle"),d&&d.apply(l,r),d=h&&l[h],d&&v.acceptData(l)&&d.apply&&d.apply(l,r)===!1&&n.preventDefault();return n.type=y,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(s.ownerDocument,r)===!1)&&(y!=="click"||!v.nodeName(s,"a"))&&v.acceptData(s)&&h&&s[y]&&(y!=="focus"&&y!=="blur"||n.target.offsetWidth!==0)&&!v.isWindow(s)&&(c=s[h],c&&(s[h]=null),v.event.triggered=y,s[y](),v.event.triggered=t,c&&(s[h]=c)),n.result}return},dispatch:function(n){n=v.event.fix(n||e.event);var r,i,s,o,u,a,f,c,h,p,d=(v._data(this,"events")||{})[n.type]||[],m=d.delegateCount,g=l.call(arguments),y=!n.exclusive&&!n.namespace,b=v.event.special[n.type]||{},w=[];g[0]=n,n.delegateTarget=this;if(b.preDispatch&&b.preDispatch.call(this,n)===!1)return;if(m&&(!n.button||n.type!=="click"))for(s=n.target;s!=this;s=s.parentNode||this)if(s.disabled!==!0||n.type!=="click"){u={},f=[];for(r=0;r<m;r++)c=d[r],h=c.selector,u[h]===t&&(u[h]=c.needsContext?v(h,this).index(s)>=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r<w.length&&!n.isPropagationStopped();r++){a=w[r],n.currentTarget=a.elem;for(i=0;i<a.matches.length&&!n.isImmediatePropagationStopped();i++){c=a.matches[i];if(y||!n.namespace&&!c.namespace||n.namespace_re&&n.namespace_re.test(c.namespace))n.data=c.data,n.handleObj=c,o=((v.event.special[c.origType]||{}).handle||c.handler).apply(a.elem,g),o!==t&&(n.result=o,o===!1&&(n.preventDefault(),n.stopPropagation()))}}return b.postDispatch&&b.postDispatch.call(this,n),n.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return e.which==null&&(e.which=t.charCode!=null?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,s,o,u=n.button,a=n.fromElement;return e.pageX==null&&n.clientX!=null&&(r=e.target.ownerDocument||i,s=r.documentElement,o=r.body,e.pageX=n.clientX+(s&&s.scrollLeft||o&&o.scrollLeft||0)-(s&&s.clientLeft||o&&o.clientLeft||0),e.pageY=n.clientY+(s&&s.scrollTop||o&&o.scrollTop||0)-(s&&s.clientTop||o&&o.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?n.toElement:a),!e.which&&u!==t&&(e.which=u&1?1:u&2?3:u&4?2:0),e}},fix:function(e){if(e[v.expando])return e;var t,n,r=e,s=v.event.fixHooks[e.type]||{},o=s.props?this.props.concat(s.props):this.props;e=v.Event(r);for(t=o.length;t;)n=o[--t],e[n]=r[n];return e.target||(e.target=r.srcElement||i),e.target.nodeType===3&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,r):e},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(e,t,n){v.isWindow(this)&&(this.onbeforeunload=n)},teardown:function(e,t){this.onbeforeunload===t&&(this.onbeforeunload=null)}}},simulate:function(e,t,n,r){var i=v.extend(new v.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?v.event.trigger(i,null,t):v.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},v.event.handle=v.event.dispatch,v.removeEvent=i.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]=="undefined"&&(e[r]=null),e.detachEvent(r,n))},v.Event=function(e,t){if(!(this instanceof v.Event))return new v.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?tt:et):this.type=e,t&&v.extend(this,t),this.timeStamp=e&&e.timeStamp||v.now(),this[v.expando]=!0},v.Event.prototype={preventDefault:function(){this.isDefaultPrevented=tt;var e=this.originalEvent;if(!e)return;e.preventDefault?e.preventDefault():e.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=tt;var e=this.originalEvent;if(!e)return;e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=tt,this.stopPropagation()},isDefaultPrevented:et,isPropagationStopped:et,isImmediatePropagationStopped:et},v.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){v.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,s=e.handleObj,o=s.selector;if(!i||i!==r&&!v.contains(r,i))e.type=s.origType,n=s.handler.apply(this,arguments),e.type=t;return n}}}),v.support.submitBubbles||(v.event.special.submit={setup:function(){if(v.nodeName(this,"form"))return!1;v.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=v.nodeName(n,"input")||v.nodeName(n,"button")?n.form:t;r&&!v._data(r,"_submit_attached")&&(v.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),v._data(r,"_submit_attached",!0))})},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&v.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){if(v.nodeName(this,"form"))return!1;v.event.remove(this,"._submit")}}),v.support.changeBubbles||(v.event.special.change={setup:function(){if($.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")v.event.add(this,"propertychange._change",function(e){e.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),v.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),v.event.simulate("change",this,e,!0)});return!1}v.event.add(this,"beforeactivate._change",function(e){var t=e.target;$.test(t.nodeName)&&!v._data(t,"_change_attached")&&(v.event.add(t,"change._change",function(e){this.parentNode&&!e.isSimulated&&!e.isTrigger&&v.event.simulate("change",this.parentNode,e,!0)}),v._data(t,"_change_attached",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||t.type!=="radio"&&t.type!=="checkbox")return e.handleObj.handler.apply(this,arguments)},teardown:function(){return v.event.remove(this,"._change"),!$.test(this.nodeName)}}),v.support.focusinBubbles||v.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){v.event.simulate(t,e.target,v.event.fix(e),!0)};v.event.special[t]={setup:function(){n++===0&&i.addEventListener(e,r,!0)},teardown:function(){--n===0&&i.removeEventListener(e,r,!0)}}}),v.fn.extend({on:function(e,n,r,i,s){var o,u;if(typeof e=="object"){typeof n!="string"&&(r=r||n,n=t);for(u in e)this.on(u,n,r,e[u],s);return this}r==null&&i==null?(i=n,r=n=t):i==null&&(typeof n=="string"?(i=r,r=t):(i=r,r=n,n=t));if(i===!1)i=et;else if(!i)return this;return s===1&&(o=i,i=function(e){return v().off(e),o.apply(this,arguments)},i.guid=o.guid||(o.guid=v.guid++)),this.each(function(){v.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,s;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,v(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if(typeof e=="object"){for(s in e)this.off(s,n,e[s]);return this}if(n===!1||typeof n=="function")r=n,n=t;return r===!1&&(r=et),this.each(function(){v.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},live:function(e,t,n){return v(this.context).on(e,this.selector,t,n),this},die:function(e,t){return v(this.context).off(e,this.selector||"**",t),this},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return arguments.length===1?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){v.event.trigger(e,t,this)})},triggerHandler:function(e,t){if(this[0])return v.event.trigger(e,t,this[0],!0)},toggle:function(e){var t=arguments,n=e.guid||v.guid++,r=0,i=function(n){var i=(v._data(this,"lastToggle"+e.guid)||0)%r;return v._data(this,"lastToggle"+e.guid,i+1),n.preventDefault(),t[i].apply(this,arguments)||!1};i.guid=n;while(r<t.length)t[r++].guid=n;return this.click(i)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),v.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){v.fn[t]=function(e,n){return n==null&&(n=e,e=null),arguments.length>0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u<a;u++)if(s=e[u])if(!n||n(s,r,i))o.push(s),f&&t.push(u);return o}function ct(e,t,n,r,i,s){return r&&!r[d]&&(r=ct(r)),i&&!i[d]&&(i=ct(i,s)),N(function(s,o,u,a){var f,l,c,h=[],p=[],d=o.length,v=s||dt(t||"*",u.nodeType?[u]:u,[]),m=e&&(s||!t)?lt(v,h,e,u,a):v,g=n?i||(s?e:d||r)?[]:o:m;n&&n(m,g,u,a);if(r){f=lt(g,p),r(f,[],u,a),l=f.length;while(l--)if(c=f[l])g[p[l]]=!(m[p[l]]=c)}if(s){if(i||e){if(i){f=[],l=g.length;while(l--)(c=g[l])&&f.push(m[l]=c);i(null,g=[],f,a)}l=g.length;while(l--)(c=g[l])&&(f=i?T.call(s,c):h[l])>-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a<s;a++)if(n=i.relative[e[a].type])h=[at(ft(h),n)];else{n=i.filter[e[a].type].apply(null,e[a].matches);if(n[d]){r=++a;for(;r<s;r++)if(i.relative[e[r].type])break;return ct(a>1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a<r&&ht(e.slice(a,r)),r<s&&ht(e=e.slice(r)),r<s&&e.join(""))}h.push(n)}return ft(h)}function pt(e,t){var r=t.length>0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r<i;r++)nt(e,t[r],n);return n}function vt(e,t,n,r,s){var o,u,f,l,c,h=ut(e),p=h.length;if(!r&&h.length===1){u=h[0]=h[0].slice(0);if(u.length>2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;t<n;t++)if(this[t]===e)return t;return-1},N=function(e,t){return e[d]=t==null||t,e},C=function(){var e={},t=[];return N(function(n,r){return t.push(n)>i.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="<a name='"+d+"'></a><div name='"+d+"'></div>",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:st(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:st(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},f=y.compareDocumentPosition?function(e,t){return e===t?(l=!0,0):(!e.compareDocumentPosition||!t.compareDocumentPosition?e.compareDocumentPosition:e.compareDocumentPosition(t)&4)?-1:1}:function(e,t){if(e===t)return l=!0,0;if(e.sourceIndex&&t.sourceIndex)return e.sourceIndex-t.sourceIndex;var n,r,i=[],s=[],o=e.parentNode,u=t.parentNode,a=o;if(o===u)return ot(e,t);if(!o)return-1;if(!u)return 1;while(a)i.unshift(a),a=a.parentNode;a=u;while(a)s.unshift(a),a=a.parentNode;n=i.length,r=s.length;for(var f=0;f<n&&f<r;f++)if(i[f]!==s[f])return ot(i[f],s[f]);return f===n?ot(e,s[f],-1):ot(i[f],t,1)},[0,0].sort(f),h=!l,nt.uniqueSort=function(e){var t,n=[],r=1,i=0;l=h,e.sort(f);if(l){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e},nt.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},a=nt.compile=function(e,t){var n,r=[],i=[],s=A[d][e+" "];if(!s){t||(t=ut(e)),n=t.length;while(n--)s=ht(t[n]),s[d]?r.push(s):i.push(s);s=A(e,pt(i,r))}return s},g.querySelectorAll&&function(){var e,t=vt,n=/'|\\/g,r=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,i=[":focus"],s=[":active"],u=y.matchesSelector||y.mozMatchesSelector||y.webkitMatchesSelector||y.oMatchesSelector||y.msMatchesSelector;K(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="<p test=''></p>",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="<input type='hidden'/>",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t<n;t++)if(v.contains(u[t],this))return!0});o=this.pushStack("","find",e);for(t=0,n=this.length;t<n;t++){r=o.length,v.find(e,this[t],o);if(t>0)for(i=r;i<o.length;i++)for(s=0;s<r;s++)if(o[s]===o[i]){o.splice(i--,1);break}}return o},has:function(e){var t,n=v(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(v.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1),"not",e)},filter:function(e){return this.pushStack(ft(this,e,!0),"filter",e)},is:function(e){return!!e&&(typeof e=="string"?st.test(e)?v(e,this.context).index(this[0])>=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r<i;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&n.nodeType!==11){if(o?o.index(n)>-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/<tbody/i,gt=/<|&#?\w+;/,yt=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,wt=new RegExp("<(?:"+ct+")[\\s/>]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,Nt={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X<div>","</div>"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1></$2>");try{for(;r<i;r++)n=this[r]||{},n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),n.innerHTML=e);n=0}catch(s){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){return ut(this[0])?this.length?this.pushStack(v(v.isFunction(e)?e():e),"replaceWith",e):this:v.isFunction(e)?this.each(function(t){var n=v(this),r=n.html();n.replaceWith(e.call(this,t,r))}):(typeof e!="string"&&(e=v(e).detach()),this.each(function(){var t=this.nextSibling,n=this.parentNode;v(this).remove(),t?v(t).before(e):v(n).append(e)}))},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=[].concat.apply([],e);var i,s,o,u,a=0,f=e[0],l=[],c=this.length;if(!v.support.checkClone&&c>1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a<c;a++)r.call(n&&v.nodeName(this[a],"table")?Lt(this[a],"tbody"):this[a],a===u?o:v.clone(o,!0,!0))}o=s=null,l.length&&v.each(l,function(e,t){t.src?v.ajax?v.ajax({url:t.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):v.error("no ajax"):v.globalEval((t.text||t.textContent||t.innerHTML||"").replace(Tt,"")),t.parentNode&&t.parentNode.removeChild(t)})}return this}}),v.buildFragment=function(e,n,r){var s,o,u,a=e[0];return n=n||i,n=!n.nodeType&&n[0]||n,n=n.ownerDocument||n,e.length===1&&typeof a=="string"&&a.length<512&&n===i&&a.charAt(0)==="<"&&!bt.test(a)&&(v.support.checkClone||!St.test(a))&&(v.support.html5Clone||!wt.test(a))&&(o=!0,s=v.fragments[a],u=s!==t),s||(s=n.createDocumentFragment(),v.clean(e,n,s,r),o&&(v.fragments[a]=u&&s)),{fragment:s,cacheable:o}},v.fragments={},v.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){v.fn[e]=function(n){var r,i=0,s=[],o=v(n),u=o.length,a=this.length===1&&this[0].parentNode;if((a==null||a&&a.nodeType===11&&a.childNodes.length===1)&&u===1)return o[t](this[0]),this;for(;i<u;i++)r=(i>0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1></$2>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]==="<table>"&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("<div>").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r<i;r++)n=e[r],Vn[n]=Vn[n]||[],Vn[n].unshift(t)},prefilter:function(e,t){t?Xn.unshift(e):Xn.push(e)}}),v.Tween=Yn,Yn.prototype={constructor:Yn,init:function(e,t,n,r,i,s){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=s||(v.cssNumber[n]?"":"px")},cur:function(){var e=Yn.propHooks[this.prop];return e&&e.get?e.get(this):Yn.propHooks._default.get(this)},run:function(e){var t,n=Yn.propHooks[this.prop];return this.options.duration?this.pos=t=v.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):Yn.propHooks._default.set(this),this}},Yn.prototype.init.prototype=Yn.prototype,Yn.propHooks={_default:{get:function(e){var t;return e.elem[e.prop]==null||!!e.elem.style&&e.elem.style[e.prop]!=null?(t=v.css(e.elem,e.prop,!1,""),!t||t==="auto"?0:t):e.elem[e.prop]},set:function(e){v.fx.step[e.prop]?v.fx.step[e.prop](e):e.elem.style&&(e.elem.style[v.cssProps[e.prop]]!=null||v.cssHooks[e.prop])?v.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},Yn.propHooks.scrollTop=Yn.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},v.each(["toggle","show","hide"],function(e,t){var n=v.fn[t];v.fn[t]=function(r,i,s){return r==null||typeof r=="boolean"||!e&&v.isFunction(r)&&v.isFunction(i)?n.apply(this,arguments):this.animate(Zn(t,!0),r,i,s)}}),v.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Gt).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=v.isEmptyObject(e),s=v.speed(t,n,r),o=function(){var t=Kn(this,v.extend({},e),s);i&&t.stop(!0)};return i||s.queue===!1?this.each(o):this.queue(s.queue,o)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return typeof e!="string"&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=e!=null&&e+"queueHooks",s=v.timers,o=v._data(this);if(n)o[n]&&o[n].stop&&i(o[n]);else for(n in o)o[n]&&o[n].stop&&Wn.test(n)&&i(o[n]);for(n=s.length;n--;)s[n].elem===this&&(e==null||s[n].queue===e)&&(s[n].anim.stop(r),t=!1,s.splice(n,1));(t||!r)&&v.dequeue(this,e)})}}),v.each({slideDown:Zn("show"),slideUp:Zn("hide"),slideToggle:Zn("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){v.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),v.speed=function(e,t,n){var r=e&&typeof e=="object"?v.extend({},e):{complete:n||!n&&t||v.isFunction(e)&&e,duration:e,easing:n&&t||t&&!v.isFunction(t)&&t};r.duration=v.fx.off?0:typeof r.duration=="number"?r.duration:r.duration in v.fx.speeds?v.fx.speeds[r.duration]:v.fx.speeds._default;if(r.queue==null||r.queue===!0)r.queue="fx";return r.old=r.complete,r.complete=function(){v.isFunction(r.old)&&r.old.call(this),r.queue&&v.dequeue(this,r.queue)},r},v.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},v.timers=[],v.fx=Yn.prototype.init,v.fx.tick=function(){var e,n=v.timers,r=0;qn=v.now();for(;r<n.length;r++)e=n[r],!e()&&n[r]===e&&n.splice(r--,1);n.length||v.fx.stop(),qn=t},v.fx.timer=function(e){e()&&v.timers.push(e)&&!Rn&&(Rn=setInterval(v.fx.tick,v.fx.interval))},v.fx.interval=13,v.fx.stop=function(){clearInterval(Rn),Rn=null},v.fx.speeds={slow:600,fast:200,_default:400},v.fx.step={},v.expr&&v.expr.filters&&(v.expr.filters.animated=function(e){return v.grep(v.timers,function(t){return e===t.elem}).length});var er=/^(?:body|html)$/i;v.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){v.offset.setOffset(this,e,t)});var n,r,i,s,o,u,a,f={top:0,left:0},l=this[0],c=l&&l.ownerDocument;if(!c)return;return(r=c.body)===l?v.offset.bodyOffset(l):(n=c.documentElement,v.contains(n,l)?(typeof l.getBoundingClientRect!="undefined"&&(f=l.getBoundingClientRect()),i=tr(c),s=n.clientTop||r.clientTop||0,o=n.clientLeft||r.clientLeft||0,u=i.pageYOffset||n.scrollTop,a=i.pageXOffset||n.scrollLeft,{top:f.top+u-s,left:f.left+a-o}):f)},v.offset={bodyOffset:function(e){var t=e.offsetTop,n=e.offsetLeft;return v.support.doesNotIncludeMarginInBodyOffset&&(t+=parseFloat(v.css(e,"marginTop"))||0,n+=parseFloat(v.css(e,"marginLeft"))||0),{top:t,left:n}},setOffset:function(e,t,n){var r=v.css(e,"position");r==="static"&&(e.style.position="relative");var i=v(e),s=i.offset(),o=v.css(e,"top"),u=v.css(e,"left"),a=(r==="absolute"||r==="fixed")&&v.inArray("auto",[o,u])>-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window); \ No newline at end of file diff --git a/src/admin/application/templates/less/custom.less b/src/admin/application/templates/less/custom.less new file mode 100755 index 0000000..cca8b7d --- /dev/null +++ b/src/admin/application/templates/less/custom.less @@ -0,0 +1,205 @@ +#loading { + width: 100%; + height: 80px; + margin-top: 120px; + background: url(../images/ajax-loader.gif) no-repeat top center; +} + +.splitDiv { + width: 100%; + overflow: auto; + position: absolute; + padding-bottom: 0; +} + +#searchForm { + padding-top: 10px; +} + +body > #outer.splitDiv { + min-height: 0; +} + +.resizeDiv { + position: fixed; + background-color: white; +} + +#handle { + height: 22px; + width: 100%; + background: url("../images/resize.png") no-repeat scroll center center rgba(238, 238, 238, 1); + background-size: 37px 8px; + z-index: 9; +} + +#handle:hover { + cursor: n-resize; +} + +.contentSearch { + margin-left: 15px !important; +} + +#searchText { + width: 60%; +} + +#searchSubmit { + margin-left:5px; + cursor: pointer; +} + +#searchResultFrame { + border: 2px solid #ccc; + border-left:0; + border-right:0; +} + +#input-menu .btn-group a.action-link.btn { + padding-right:5px !important +} +#input-menu .btn-group .dropdown-menu li a { + color:#333; + text-indent:0; + font-size:13px; +} +#input-menu { + background-color:#fff +} + +#searchResultContextmenu { + position: absolute !important; +} + +#loadingFrame { + background: url("../images/ajax-loader.gif") no-repeat scroll center center rgba(0, 0, 0, 0); + height: 80px; + width: 100%; +} + +.js-closeDiv { + cursor: pointer; + padding-right: 5px; +} + +.europeana-group { + margin-left: 200px !important; + margin-top: 10px; +} + +.europeana-group label, input, select { + font-size: 13px !important; +} + +.europeana-group input[type="text"] { + width: 80% !important; +} + +.europeana-group select { + width: 84% !important; +} + +.europeana-group input.btn { + margin-top: 15px !important; + margin-right: 5px !important; +} + + +.europeana-group ul { + margin-left: 0 !important; + margin-top: 20px; +} + +.europeana-group.firstDiv { + margin-top: -20px; +} + +.europeana-group div.js-imageRemove { + cursor: pointer !important; +} + +.europeana-group div.js-imageRemove i { + margin-bottom: 2px; +} + +.europeana-group div.imgPreview { + height: 210px; + width: 111px; +} + +.europeana-group div.imgPreview img { + height: 130px; + width: 111px; +} + +.europeana-group div.maxResDiv input{ + width:106px !important; +} + +.europeana-group input.titleInput { + width: 90% !important; +} + +.europeana-group.div-btn { + width: 79%; +} + +.sortable { list-style-type: none; margin: auto; padding: auto; float: left; background: #eee; padding: 5px; width: 100%; cursor: pointer; min-height: 175px;} +.sortable li { margin: 0 3px 3px 3px; padding: 0.4em; text-align: center; font-size: 0.9em; height: 14px; } +.sortableNote {padding-top: 5px; clear:both; font-style:italic; font-size: 15px; color: #888;} + + +/* grafo */ +svg { + overflow: hidden; + margin: auto auto; +} + +/* Stile testo delle entità */ +g.nodes tspan { + font-family: Helvetica, sans-serif; + font-size: 14px; +} +/* Stile testo delle entità in HTML */ +g.nodes div { + white-space: nowrap; + padding: 4px; + font-family: Helvetica, sans-serif; + font-size: 14px; +} + +/* Stile testo delle entità principali */ +g.nodes tspan.main-node { + fill: white; +} +/* Stile testo delle entità principali in HTML */ +div.main-node { + padding: 2px 7px 2px 7px; + font-family: Helvetica, sans-serif; + font-size: 14px; +} + +/* Stile testo delle relazioni */ +g.edgeLabels tspan { + +} + +/* Stile riquadro delle entità */ +.node rect { + stroke: #cfced3; + stroke-width: 2px; + fill: none; +} + +/* Stile riquadro delle entità principali */ +.node rect.main-node { + fill: lightgray; +} + +/* Stile delle frecce */ +.edgePath path { + stroke: black; + stroke-width: 1.5px; + fill: none; +} \ No newline at end of file diff --git a/src/admin/application/templates/less/custom.login.less b/src/admin/application/templates/less/custom.login.less new file mode 100755 index 0000000..9c255d5 --- /dev/null +++ b/src/admin/application/templates/less/custom.login.less @@ -0,0 +1,84 @@ +#LoginPage { + + background: @white url('../img/login-bkg.png') top center repeat-x scroll; + + footer { + position:absolute; + bottom:0; + } + + a, #loginbox .text { + .text-shadow(); + } + + a { + font-size: 12px; + color:@blue; + } + + hr.separator { + width: 100%; + height: 1px; + border-top: 1px solid @grey; + border-bottom: 1px solid @white; + border-left: none; + border-right: none; + margin: 15px 0; + } + + #loginbox { + position: absolute; + top:50%; + left:50%; + margin:0; + margin-top:-155px; + margin-left:-200px; + width: 400px; + background-color: @grey2; + border: 1px solid @grey1; + border-radius: 5px; + .box-shadow(0, 0px, 15px, @grey19, inset); + div[class*="span"] { + margin: 30px 0; + text-align: center; + + .text { + display: block; + color: @black2; + font-size:14px; + font-weight: normal; + margin-bottom: 20px; + } + + .alert { + + color:black; + padding-right:0; + padding-left:0; + text-align:center; + font-size:12px; + + .alert-error { + background-color: @pink; + border: 1px solid @red; + } + + a { + text-decoration:underline; + + &:hover { + text-decoration:none; + } + + } + + } + + + } + + + + } + +} \ No newline at end of file diff --git a/src/admin/application/templates/less/font-awesome.less b/src/admin/application/templates/less/font-awesome.less new file mode 100755 index 0000000..3a60645 --- /dev/null +++ b/src/admin/application/templates/less/font-awesome.less @@ -0,0 +1,537 @@ +/*! + * Font Awesome 3.0.2 + * the iconic font designed for use with Twitter Bootstrap + * ------------------------------------------------------- + * The full suite of pictographic icons, examples, and documentation + * can be found at: http://fortawesome.github.com/Font-Awesome/ + * + * License + * ------------------------------------------------------- + * - The Font Awesome font is licensed under the SIL Open Font License - http://scripts.sil.org/OFL + * - Font Awesome CSS, LESS, and SASS files are licensed under the MIT License - + * http://opensource.org/licenses/mit-license.html + * - The Font Awesome pictograms are licensed under the CC BY 3.0 License - http://creativecommons.org/licenses/by/3.0/ + * - Attribution is no longer required in Font Awesome 3.0, but much appreciated: + * "Font Awesome by Dave Gandy - http://fortawesome.github.com/Font-Awesome" + + * Contact + * ------------------------------------------------------- + * Email: dave@davegandy.com + * Twitter: http://twitter.com/fortaweso_me + * Work: Lead Product Designer @ http://kyruus.com + */ + +@FontAwesomePath: "../font"; +@borderColor: #eee; +@iconMuted: #eee; +.border-radius(@radius) { -webkit-border-radius: @radius; -moz-border-radius: @radius; border-radius: @radius; } + +@font-face { + font-family: 'FontAwesome'; + src: url('@{FontAwesomePath}/fontawesome-webfont.eot?v=3.0.1'); + src: url('@{FontAwesomePath}/fontawesome-webfont.eot?#iefix&v=3.0.1') format('embedded-opentype'), + url('@{FontAwesomePath}/fontawesome-webfont.woff?v=3.0.1') format('woff'), + url('@{FontAwesomePath}/fontawesome-webfont.ttf?v=3.0.1') format('truetype'); +// url('@{FontAwesomePath}/fontawesome-webfont.svg#fontawesomeregular?v=3.0.1') format('svg'); + +// src: url('@{FontAwesomePath}/FontAwesome.otf') format('opentype'); + + font-weight: normal; + font-style: normal; +} + +/* Font Awesome styles + ------------------------------------------------------- */ +[class^="icon-"], +[class*=" icon-"] { + font-family: FontAwesome; + font-weight: normal; + font-style: normal; + text-decoration: inherit; + -webkit-font-smoothing: antialiased; + +/* sprites.less reset */ + display: inline; + width: auto; + height: auto; + line-height: normal; + vertical-align: baseline; + background-image: none; + background-position: 0% 0%; + background-repeat: repeat; + margin-top: 0; +} + +/* more sprites.less reset */ +.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:hover > [class*=" icon-"], +.dropdown-menu > .active > a > [class^="icon-"], +.dropdown-menu > .active > a > [class*=" icon-"], +.dropdown-submenu:hover > a > [class^="icon-"], +.dropdown-submenu:hover > a > [class*=" icon-"] { + background-image: none; +} + +[class^="icon-"]:before, +[class*=" icon-"]:before { + text-decoration: inherit; + display: inline-block; + speak: none; +} + +/* makes sure icons active on rollover in links */ +a { + [class^="icon-"], + [class*=" icon-"] { + display: inline-block; + } +} + +/* makes the font 33% larger relative to the icon container */ +.icon-large:before { + vertical-align: -10%; + font-size: 4/3em; +} + +.btn, .nav { + [class^="icon-"], + [class*=" icon-"] { + display: inline; + /* keeps button heights with and without icons the same */ + &.icon-large { line-height: .9em; } + &.icon-spin { display: inline-block; } + } +} + +.nav-tabs, .nav-pills { + [class^="icon-"], + [class*=" icon-"] { + /* keeps button heights with and without icons the same */ + &, &.icon-large { line-height: .9em; } + } +} + +li, .nav li { + [class^="icon-"], + [class*=" icon-"] { + display: inline-block; + width: 1.25em; + text-align: center; + &.icon-large { + /* increased font size for icon-large */ + width: 1.25*1.25em; + } + } +} + +ul.icons { + list-style-type: none; + text-indent: -.75em; + + li { + [class^="icon-"], + [class*=" icon-"] { + width: .75em; + } + } +} + +.icon-muted { + color: @iconMuted; +} + +// Icon Borders +// ------------------------- + +.icon-border { + border: solid 1px @borderColor; + padding: .2em .25em .15em; + .border-radius(3px); +} + +// Icon Sizes +// ------------------------- + +.icon-2x { + font-size: 2em; + &.icon-border { + border-width: 2px; + .border-radius(4px); + } +} +.icon-3x { + font-size: 3em; + &.icon-border { + border-width: 3px; + .border-radius(5px); + } +} +.icon-4x { + font-size: 4em; + &.icon-border { + border-width: 4px; + .border-radius(6px); + } +} + +// Floats +// ------------------------- + +// Quick floats +.pull-right { float: right; } +.pull-left { float: left; } + +[class^="icon-"], +[class*=" icon-"] { + &.pull-left { + margin-right: .3em; + } + &.pull-right { + margin-left: .3em; + } +} + +.btn { + [class^="icon-"], + [class*=" icon-"] { + &.pull-left, &.pull-right { + &.icon-2x { margin-top: .18em; } + } + &.icon-spin.icon-large { line-height: .8em; } + } +} + +.btn.btn-small { + [class^="icon-"], + [class*=" icon-"] { + &.pull-left, &.pull-right { + &.icon-2x { margin-top: .25em; } + } + } +} + +.btn.btn-large { + [class^="icon-"], + [class*=" icon-"] { + margin-top: 0; // overrides bootstrap default + &.pull-left, &.pull-right { + &.icon-2x { margin-top: .05em; } + } + &.pull-left.icon-2x { margin-right: .2em; } + &.pull-right.icon-2x { margin-left: .2em; } + } +} + + +.icon-spin { + display: inline-block; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + -webkit-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} + +@-moz-keyframes spin { + 0% { -moz-transform: rotate(0deg); } + 100% { -moz-transform: rotate(359deg); } +} +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(359deg); } +} +@-o-keyframes spin { + 0% { -o-transform: rotate(0deg); } + 100% { -o-transform: rotate(359deg); } +} +@-ms-keyframes spin { + 0% { -ms-transform: rotate(0deg); } + 100% { -ms-transform: rotate(359deg); } +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(359deg); } +} + +@-moz-document url-prefix() { + .icon-spin { height: .9em; } + .btn .icon-spin { height: auto; } + .icon-spin.icon-large { height: 1.25em; } + .btn .icon-spin.icon-large { height: .75em; } +} + +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ +.icon-glass:before { content: "\f000"; } +.icon-music:before { content: "\f001"; } +.icon-search:before { content: "\f002"; } +.icon-envelope:before { content: "\f003"; } +.icon-heart:before { content: "\f004"; } +.icon-star:before { content: "\f005"; } +.icon-star-empty:before { content: "\f006"; } +.icon-user:before { content: "\f007"; } +.icon-film:before { content: "\f008"; } +.icon-th-large:before { content: "\f009"; } +.icon-th:before { content: "\f00a"; } +.icon-th-list:before { content: "\f00b"; } +.icon-ok:before { content: "\f00c"; } +.icon-remove:before { content: "\f00d"; } +.icon-zoom-in:before { content: "\f00e"; } + +.icon-zoom-out:before { content: "\f010"; } +.icon-off:before { content: "\f011"; } +.icon-signal:before { content: "\f012"; } +.icon-cog:before { content: "\f013"; } +.icon-trash:before { content: "\f014"; } +.icon-home:before { content: "\f015"; } +.icon-file:before { content: "\f016"; } +.icon-time:before { content: "\f017"; } +.icon-road:before { content: "\f018"; } +.icon-download-alt:before { content: "\f019"; } +.icon-download:before { content: "\f01a"; } +.icon-upload:before { content: "\f01b"; } +.icon-inbox:before { content: "\f01c"; } +.icon-play-circle:before { content: "\f01d"; } +.icon-repeat:before { content: "\f01e"; } + +/* \f020 doesn't work in Safari. all shifted one down */ +.icon-refresh:before { content: "\f021"; } +.icon-list-alt:before { content: "\f022"; } +.icon-lock:before { content: "\f023"; } +.icon-flag:before { content: "\f024"; } +.icon-headphones:before { content: "\f025"; } +.icon-volume-off:before { content: "\f026"; } +.icon-volume-down:before { content: "\f027"; } +.icon-volume-up:before { content: "\f028"; } +.icon-qrcode:before { content: "\f029"; } +.icon-barcode:before { content: "\f02a"; } +.icon-tag:before { content: "\f02b"; } +.icon-tags:before { content: "\f02c"; } +.icon-book:before { content: "\f02d"; } +.icon-bookmark:before { content: "\f02e"; } +.icon-print:before { content: "\f02f"; } + +.icon-camera:before { content: "\f030"; } +.icon-font:before { content: "\f031"; } +.icon-bold:before { content: "\f032"; } +.icon-italic:before { content: "\f033"; } +.icon-text-height:before { content: "\f034"; } +.icon-text-width:before { content: "\f035"; } +.icon-align-left:before { content: "\f036"; } +.icon-align-center:before { content: "\f037"; } +.icon-align-right:before { content: "\f038"; } +.icon-align-justify:before { content: "\f039"; } +.icon-list:before { content: "\f03a"; } +.icon-indent-left:before { content: "\f03b"; } +.icon-indent-right:before { content: "\f03c"; } +.icon-facetime-video:before { content: "\f03d"; } +.icon-picture:before { content: "\f03e"; } + +.icon-pencil:before { content: "\f040"; } +.icon-map-marker:before { content: "\f041"; } +.icon-adjust:before { content: "\f042"; } +.icon-tint:before { content: "\f043"; } +.icon-edit:before { content: "\f044"; } +.icon-share:before { content: "\f045"; } +.icon-check:before { content: "\f046"; } +.icon-move:before { content: "\f047"; } +.icon-step-backward:before { content: "\f048"; } +.icon-fast-backward:before { content: "\f049"; } +.icon-backward:before { content: "\f04a"; } +.icon-play:before { content: "\f04b"; } +.icon-pause:before { content: "\f04c"; } +.icon-stop:before { content: "\f04d"; } +.icon-forward:before { content: "\f04e"; } + +.icon-fast-forward:before { content: "\f050"; } +.icon-step-forward:before { content: "\f051"; } +.icon-eject:before { content: "\f052"; } +.icon-chevron-left:before { content: "\f053"; } +.icon-chevron-right:before { content: "\f054"; } +.icon-plus-sign:before { content: "\f055"; } +.icon-minus-sign:before { content: "\f056"; } +.icon-remove-sign:before { content: "\f057"; } +.icon-ok-sign:before { content: "\f058"; } +.icon-question-sign:before { content: "\f059"; } +.icon-info-sign:before { content: "\f05a"; } +.icon-screenshot:before { content: "\f05b"; } +.icon-remove-circle:before { content: "\f05c"; } +.icon-ok-circle:before { content: "\f05d"; } +.icon-ban-circle:before { content: "\f05e"; } + +.icon-arrow-left:before { content: "\f060"; } +.icon-arrow-right:before { content: "\f061"; } +.icon-arrow-up:before { content: "\f062"; } +.icon-arrow-down:before { content: "\f063"; } +.icon-share-alt:before { content: "\f064"; } +.icon-resize-full:before { content: "\f065"; } +.icon-resize-small:before { content: "\f066"; } +.icon-plus:before { content: "\f067"; } +.icon-minus:before { content: "\f068"; } +.icon-asterisk:before { content: "\f069"; } +.icon-exclamation-sign:before { content: "\f06a"; } +.icon-gift:before { content: "\f06b"; } +.icon-leaf:before { content: "\f06c"; } +.icon-fire:before { content: "\f06d"; } +.icon-eye-open:before { content: "\f06e"; } + +.icon-eye-close:before { content: "\f070"; } +.icon-warning-sign:before { content: "\f071"; } +.icon-plane:before { content: "\f072"; } +.icon-calendar:before { content: "\f073"; } +.icon-random:before { content: "\f074"; } +.icon-comment:before { content: "\f075"; } +.icon-magnet:before { content: "\f076"; } +.icon-chevron-up:before { content: "\f077"; } +.icon-chevron-down:before { content: "\f078"; } +.icon-retweet:before { content: "\f079"; } +.icon-shopping-cart:before { content: "\f07a"; } +.icon-folder-close:before { content: "\f07b"; } +.icon-folder-open:before { content: "\f07c"; } +.icon-resize-vertical:before { content: "\f07d"; } +.icon-resize-horizontal:before { content: "\f07e"; } + +.icon-bar-chart:before { content: "\f080"; } +.icon-twitter-sign:before { content: "\f081"; } +.icon-facebook-sign:before { content: "\f082"; } +.icon-camera-retro:before { content: "\f083"; } +.icon-key:before { content: "\f084"; } +.icon-cogs:before { content: "\f085"; } +.icon-comments:before { content: "\f086"; } +.icon-thumbs-up:before { content: "\f087"; } +.icon-thumbs-down:before { content: "\f088"; } +.icon-star-half:before { content: "\f089"; } +.icon-heart-empty:before { content: "\f08a"; } +.icon-signout:before { content: "\f08b"; } +.icon-linkedin-sign:before { content: "\f08c"; } +.icon-pushpin:before { content: "\f08d"; } +.icon-external-link:before { content: "\f08e"; } + +.icon-signin:before { content: "\f090"; } +.icon-trophy:before { content: "\f091"; } +.icon-github-sign:before { content: "\f092"; } +.icon-upload-alt:before { content: "\f093"; } +.icon-lemon:before { content: "\f094"; } +.icon-phone:before { content: "\f095"; } +.icon-check-empty:before { content: "\f096"; } +.icon-bookmark-empty:before { content: "\f097"; } +.icon-phone-sign:before { content: "\f098"; } +.icon-twitter:before { content: "\f099"; } +.icon-facebook:before { content: "\f09a"; } +.icon-github:before { content: "\f09b"; } +.icon-unlock:before { content: "\f09c"; } +.icon-credit-card:before { content: "\f09d"; } +.icon-rss:before { content: "\f09e"; } + +.icon-hdd:before { content: "\f0a0"; } +.icon-bullhorn:before { content: "\f0a1"; } +.icon-bell:before { content: "\f0a2"; } +.icon-certificate:before { content: "\f0a3"; } +.icon-hand-right:before { content: "\f0a4"; } +.icon-hand-left:before { content: "\f0a5"; } +.icon-hand-up:before { content: "\f0a6"; } +.icon-hand-down:before { content: "\f0a7"; } +.icon-circle-arrow-left:before { content: "\f0a8"; } +.icon-circle-arrow-right:before { content: "\f0a9"; } +.icon-circle-arrow-up:before { content: "\f0aa"; } +.icon-circle-arrow-down:before { content: "\f0ab"; } +.icon-globe:before { content: "\f0ac"; } +.icon-wrench:before { content: "\f0ad"; } +.icon-tasks:before { content: "\f0ae"; } + +.icon-filter:before { content: "\f0b0"; } +.icon-briefcase:before { content: "\f0b1"; } +.icon-fullscreen:before { content: "\f0b2"; } + +.icon-group:before { content: "\f0c0"; } +.icon-link:before { content: "\f0c1"; } +.icon-cloud:before { content: "\f0c2"; } +.icon-beaker:before { content: "\f0c3"; } +.icon-cut:before { content: "\f0c4"; } +.icon-copy:before { content: "\f0c5"; } +.icon-paper-clip:before { content: "\f0c6"; } +.icon-save:before { content: "\f0c7"; } +.icon-sign-blank:before { content: "\f0c8"; } +.icon-reorder:before { content: "\f0c9"; } +.icon-list-ul:before { content: "\f0ca"; } +.icon-list-ol:before { content: "\f0cb"; } +.icon-strikethrough:before { content: "\f0cc"; } +.icon-underline:before { content: "\f0cd"; } +.icon-table:before { content: "\f0ce"; } + +.icon-magic:before { content: "\f0d0"; } +.icon-truck:before { content: "\f0d1"; } +.icon-pinterest:before { content: "\f0d2"; } +.icon-pinterest-sign:before { content: "\f0d3"; } +.icon-google-plus-sign:before { content: "\f0d4"; } +.icon-google-plus:before { content: "\f0d5"; } +.icon-money:before { content: "\f0d6"; } +.icon-caret-down:before { content: "\f0d7"; } +.icon-caret-up:before { content: "\f0d8"; } +.icon-caret-left:before { content: "\f0d9"; } +.icon-caret-right:before { content: "\f0da"; } +.icon-columns:before { content: "\f0db"; } +.icon-sort:before { content: "\f0dc"; } +.icon-sort-down:before { content: "\f0dd"; } +.icon-sort-up:before { content: "\f0de"; } + +.icon-envelope-alt:before { content: "\f0e0"; } +.icon-linkedin:before { content: "\f0e1"; } +.icon-undo:before { content: "\f0e2"; } +.icon-legal:before { content: "\f0e3"; } +.icon-dashboard:before { content: "\f0e4"; } +.icon-comment-alt:before { content: "\f0e5"; } +.icon-comments-alt:before { content: "\f0e6"; } +.icon-bolt:before { content: "\f0e7"; } +.icon-sitemap:before { content: "\f0e8"; } +.icon-umbrella:before { content: "\f0e9"; } +.icon-paste:before { content: "\f0ea"; } +.icon-lightbulb:before { content: "\f0eb"; } +.icon-exchange:before { content: "\f0ec"; } +.icon-cloud-download:before { content: "\f0ed"; } +.icon-cloud-upload:before { content: "\f0ee"; } + +.icon-user-md:before { content: "\f0f0"; } +.icon-stethoscope:before { content: "\f0f1"; } +.icon-suitcase:before { content: "\f0f2"; } +.icon-bell-alt:before { content: "\f0f3"; } +.icon-coffee:before { content: "\f0f4"; } +.icon-food:before { content: "\f0f5"; } +.icon-file-alt:before { content: "\f0f6"; } +.icon-building:before { content: "\f0f7"; } +.icon-hospital:before { content: "\f0f8"; } +.icon-ambulance:before { content: "\f0f9"; } +.icon-medkit:before { content: "\f0fa"; } +.icon-fighter-jet:before { content: "\f0fb"; } +.icon-beer:before { content: "\f0fc"; } +.icon-h-sign:before { content: "\f0fd"; } +.icon-plus-sign-alt:before { content: "\f0fe"; } + +.icon-double-angle-left:before { content: "\f100"; } +.icon-double-angle-right:before { content: "\f101"; } +.icon-double-angle-up:before { content: "\f102"; } +.icon-double-angle-down:before { content: "\f103"; } +.icon-angle-left:before { content: "\f104"; } +.icon-angle-right:before { content: "\f105"; } +.icon-angle-up:before { content: "\f106"; } +.icon-angle-down:before { content: "\f107"; } +.icon-desktop:before { content: "\f108"; } +.icon-laptop:before { content: "\f109"; } +.icon-tablet:before { content: "\f10a"; } +.icon-mobile-phone:before { content: "\f10b"; } +.icon-circle-blank:before { content: "\f10c"; } +.icon-quote-left:before { content: "\f10d"; } +.icon-quote-right:before { content: "\f10e"; } + +.icon-spinner:before { content: "\f110"; } +.icon-circle:before { content: "\f111"; } +.icon-reply:before { content: "\f112"; } +.icon-github-alt:before { content: "\f113"; } +.icon-folder-close-alt:before { content: "\f114"; } +.icon-folder-open-alt:before { content: "\f115"; } diff --git a/src/admin/application/templates/less/glizy.less b/src/admin/application/templates/less/glizy.less new file mode 100755 index 0000000..0807cc5 --- /dev/null +++ b/src/admin/application/templates/less/glizy.less @@ -0,0 +1,1269 @@ + +/* BEGIN GlizyFormEdit */ +fieldset.GFEFieldset { + margin-left:0!important; + padding:0!important; + overflow-x:hidden; + border: 0; + margin-bottom: 40px; + border-bottom: 1px solid #E5E5E5; + + legend { + width:100%; + font-size:17px; + padding-left:6px; + background:@white; + color:@grey14; + } + + .btn-icon { + cursor:pointer; + } +} + +fieldset.GFEFieldset fieldset.GFEFieldset { + margin-left: 20px !important; +} +.GFEFooter { + width:auto; + .box-sizing(); + padding:8px; + margin:0 0 0 10px; +} +.GFEButtonContainer { + float: left; +} +.GFEStatusContainer { + float: right; + font-size: 13px; + margin-top: 9px; +} + +input.GFEAddRow { + font-size: 13px; +} + +.GFERowContainer { + position: relative; + padding: 4px; + background-color: #F0F0F0; + margin-bottom: 2px; + -moz-user-select: -moz-none; + -khtml-user-select: none; + -webkit-user-select: none; + user-select: none; + width:auto; + .box-sizing(); + margin:0 0 0 10px; +} +.GFERowContainer.GFERowContainerOdd { + background-color: #E0E0E0; +} +.GFERowContainer.GFEEditingRow { + position: relative; + z-index: 101; +} +.GFERowCollapsed { +} +.GFERowExpanded { +} +.GFERowHeader { + float: left; +} +.GFERowHandler { + float: left; + cursor: move; + height: 95%; +} +.GFERowHandler img { + height: auto; +} + +.GFERowPreview div.GFEPreviewItem{ + display:none; +} +.GFERowPreview div.GFEPreviewItem:nth-child(1){ + display:inline; +} +.GFERowPreview div.GFEPreviewItem:nth-child(2){ + display:inline; +} + +.GFERowHandler.GFERowHandlerExpanded { + position: absolute; + top: 3px; +} +.GFERecordTitle { + display: inline-block; + font-weight: bold; + margin: 9px 12px; +} +.GFERowPanel { + float: right; + margin: 7px 5px; +} +.GFEPreviewItem { + display: inline-block; + padding: 2px 3px; + margin: 1px 5px; + -moz-border-radius:5px; + -webkit-border-radius:5px; + border-radius: 5px; + background:@white; +} +.GFESideClearer { + clear: both; +} +.GFEEmptyMessage { + text-align: center; + margin: 6px; +} +.GFERowContainer .icon { + cursor: pointer; +} +.GFERightIcon { + position: absolute; + top: 5px; + right: 5px; +} +.GFERowButtonContainer { + text-align: center; + clear: both; + margin-top: 14px; +} +.GButtonDisabled { + opacity: 0.5; + /*filter: alpha(opacity = 50);*/ +} +.GFETranslucentCover { + position: fixed; + display: none; + background-color: black; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 100; + opacity: 0.5; + /*filter: alpha(opacity = 50);*/ +} +.GFEValidationError { + border-left: 3px solid #ff0000 !important; +} +.GFEValidationError > label { + color: #ff0000; +} + +.GFEcomments { + width: 100%; + height: 150px; + border: 0 !important; +} +/* END GlizyFormEdit */ + +/* BEGIN dropzone */ +.glizy-dropzone, +.glizy-dropzone *, +.dropzone-previews, +.dropzone-previews * { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.glizy-dropzone { + position: relative; + border: 1px solid rgba(0,0,0,0.08); + background: rgba(0,0,0,0.02); + padding: 1em; +} +.glizy-dropzone p { + margin:60px 0; + text-align: center; +} +.glizy-dropzone.dz-clickable { + cursor: pointer; +} +.glizy-dropzone.dz-clickable .dz-message, +.glizy-dropzone.dz-clickable .dz-message span { + cursor: pointer; +} +.glizy-dropzone.dz-clickable * { + cursor: default; +} +.glizy-dropzone .dz-message { + opacity: 1; + -ms-filter: none; + filter: none; +} +.glizy-dropzone.dz-drag-hover { + border-color: rgba(0,0,0,0.15); + background: rgba(0,0,0,0.04); +} +.glizy-dropzone.dz-started .dz-message { + display: none; +} +.glizy-dropzone .dz-preview, +.dropzone-previews .dz-preview { + background: rgba(255,255,255,0.8); + position: relative; + display: inline-block; + margin: 17px; + vertical-align: top; + border: 1px solid #acacac; + padding: 6px 6px 6px 6px; +} +.glizy-dropzone .dz-preview.dz-file-preview [data-dz-thumbnail], +.dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail] { + display: none; +} +.glizy-dropzone .dz-preview .dz-details, +.dropzone-previews .dz-preview .dz-details { + width: 100px; + height: 100px; + position: relative; + background: #ebebeb; + padding: 5px; + margin-bottom: 22px; +} +.glizy-dropzone .dz-preview .dz-details .dz-filename, +.dropzone-previews .dz-preview .dz-details .dz-filename { + overflow: hidden; + height: 100%; +} +.glizy-dropzone .dz-preview .dz-details img, +.dropzone-previews .dz-preview .dz-details img { + position: absolute; + top: 0; + left: 0; + width: 100px; + height: 100px; +} +.glizy-dropzone .dz-preview .dz-details .dz-size, +.dropzone-previews .dz-preview .dz-details .dz-size { + position: absolute; + bottom: -28px; + left: 3px; + height: 28px; + line-height: 28px; +} +.glizy-dropzone .dz-preview.dz-error .dz-error-mark, +.dropzone-previews .dz-preview.dz-error .dz-error-mark { + display: block; +} +.glizy-dropzone .dz-preview.dz-success .dz-success-mark, +.dropzone-previews .dz-preview.dz-success .dz-success-mark { + display: block; +} +.glizy-dropzone .dz-preview:hover .dz-details img, +.dropzone-previews .dz-preview:hover .dz-details img { + display: none; +} +.glizy-dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark, +.glizy-dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + display: none; + position: absolute; + width: 40px; + height: 40px; + font-size: 30px; + text-align: center; + right: -10px; + top: -10px; +} +.glizy-dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark { + color: #8cc657; +} +.glizy-dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + color: #ee162d; +} +.glizy-dropzone .dz-preview .dz-progress, +.dropzone-previews .dz-preview .dz-progress { + position: absolute; + top: 100px; + left: 6px; + right: 6px; + height: 6px; + background: #d7d7d7; + display: none; +} +.glizy-dropzone .dz-preview .dz-progress .dz-upload, +.dropzone-previews .dz-preview .dz-progress .dz-upload { + display: block; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 0%; + background-color: #8cc657; +} +.glizy-dropzone .dz-preview.dz-processing .dz-progress, +.dropzone-previews .dz-preview.dz-processing .dz-progress { + display: block; +} +.glizy-dropzone .dz-preview .dz-error-message, +.dropzone-previews .dz-preview .dz-error-message { + display: none; + position: absolute; + top: -5px; + left: -20px; + background: rgba(245,245,245,0.8); + padding: 8px 10px; + color: #800; + min-width: 140px; + max-width: 500px; + z-index: 500; +} +.glizy-dropzone .dz-preview:hover.dz-error .dz-error-message, +.dropzone-previews .dz-preview:hover.dz-error .dz-error-message { + display: block; +} + +.GFERowContainer .dropzone-previews { + width: 100px; + position: absolute; + top: -10px; + right: 50px; +} + +.GFERowContainer .dropzone-previews .dz-progress, +.GFERowContainer .dropzone-previews .dz-success-mark { + display: none; +} + +.GFERowWithPreview .span11 { + width: 78%; +} + +.GFERowContainer .dropzone-previews .dz-preview .dz-details { + width: 80px; + height: 80px; +} + +.form-horizontal #medias .control-label { + width: 120px; +} + +.form-horizontal #medias .controls { + margin-left: 130px; +} + +/* END dropzone */ + +/* BEGIN MediaPicker */ +.mediaPickerField { + position: relative; +} +.mediaPickerSelector { + position: relative; + width: 150px; + height: 150px; + display: inline-block; + background-color: #F0F0F0; + border: 1px solid #fff; + cursor: pointer; + display: table-cell; + text-align: center; + vertical-align: middle; +} +.mediaPickerInfo { + position: relative; + top: 0px; + left: 20px; + float: left; + + input, textarea { + width: 100%; + margin: 0 0 10px 0; + } + } + +.mediaPickerSelector.mediaPickerElement { + float: left; +} +/* END MediaPicker */ + +/* treeview */ +#treeview-inner .jstree-default.jstree-focused { + background: transparent; +} + +#treeview-inner .jstree-clicked { + padding: 0; +} + +#treeview-inner .jstree-hovered { + padding: 0 !important; +} + +#treeview-inner .jstree a { + white-space: normal !important; + height: auto; + width: 80%; +} + +#treeview-inner .jstree li > ins { + vertical-align: top; +} + + + +li.glizycmsSiteTree-nodeSystem > a { + font-style: italic; +} + +li.glizycmsSiteTree-nodeHide > a { + color: #909090; +} +#openclose { + display: none; +} + +div.formButtons { + border-top: 1px solid #EEE; + margin-top: 20px; + padding-top: 20px; +} + +div.formButtons .btn { + margin: 0 4px; +} + + +.thumbnail li { + height: 150px; +} + +.thumbnails .title { + font-weight: normal; + font-size: 11px; +} + +div.formButtonsTop { + background: #f0f0f0; + margin-bottom: 10px; + padding: 5px; + text-align: right; +} + +div.formButtonsTop .btn { + margin: 0 4px; +} + +#filtersForm select, #filtersForm input[type="text"] { + width: 150px; +} + +#sidebar-inner ul li ul { + display: block; +} + +/* datatables */ + +div.dataTables_length label { + float: left; + text-align: left; +} + +div.dataTables_length select { + width: 75px; +} + +div.dataTables_filter label { + float: right; + margin: 0 0 0 10px; +} + +div.dataTables_info { + padding-top: 8px; +} + +div.dataTables_paginate { + float: right; + margin: 0; +} + +table.table { + clear: both; + margin-bottom: 6px !important; + max-width: none !important; +} + +table.table thead .sorting, +table.table thead .sorting_asc, +table.table thead .sorting_desc, +table.table thead .sorting_asc_disabled, +table.table thead .sorting_desc_disabled { + cursor: pointer; + *cursor: hand; +} + +table.table thead .sorting { background: url('images/sort_both.png') no-repeat center right; } +table.table thead .sorting_asc { background: url('images/sort_asc.png') no-repeat center right; } +table.table thead .sorting_desc { background: url('images/sort_desc.png') no-repeat center right; } + +table.table thead .sorting_asc_disabled { background: url('images/sort_asc_disabled.png') no-repeat center right; } +table.table thead .sorting_desc_disabled { background: url('images/sort_desc_disabled.png') no-repeat center right; } + +table.dataTable th:active { + outline: none; +} + +/* Scrolling */ +div.dataTables_scrollHead table { + margin-bottom: 0 !important; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +div.dataTables_scrollHead table thead tr:last-child th:first-child, +div.dataTables_scrollHead table thead tr:last-child td:first-child { + border-bottom-left-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +div.dataTables_scrollBody table { + border-top: none; + margin-bottom: 0 !important; +} + +div.dataTables_scrollBody tbody tr:first-child th, +div.dataTables_scrollBody tbody tr:first-child td { + border-top: none; +} + +div.dataTables_scrollFoot table { + border-top: none; +} + + + + +/* + * TableTools styles + */ +.table tbody tr.active td, +.table tbody tr.active th { + background-color: #08C; + color: white; +} + +.table tbody tr.active:hover td, +.table tbody tr.active:hover th { + background-color: #0075b0 !important; +} + +.table-striped tbody tr.active:nth-child(odd) td, +.table-striped tbody tr.active:nth-child(odd) th { + background-color: #017ebc; +} + +table.DTTT_selectable tbody tr { + cursor: pointer; + *cursor: hand; +} + +div.DTTT .btn { + color: #333 !important; + font-size: 12px; +} + +div.DTTT .btn:hover { + text-decoration: none !important; +} + + +ul.DTTT_dropdown.dropdown-menu a { + color: #333 !important; /* needed only when demo_page.css is included */ +} + +ul.DTTT_dropdown.dropdown-menu li:hover a { + background-color: #0088cc; + color: white !important; +} + +/* TableTools information display */ +div.DTTT_print_info.modal { + height: 150px; + margin-top: -75px; + text-align: center; +} + +div.DTTT_print_info h6 { + font-weight: normal; + font-size: 28px; + line-height: 28px; + margin: 1em; +} + +div.DTTT_print_info p { + font-size: 14px; + line-height: 20px; +} + + + +/* + * FixedColumns styles + */ +div.DTFC_LeftHeadWrapper table, +div.DTFC_LeftFootWrapper table, +table.DTFC_Cloned tr.even { + background-color: white; +} + +div.DTFC_LeftHeadWrapper table { + margin-bottom: 0 !important; + border-top-right-radius: 0 !important; + border-bottom-left-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +div.DTFC_LeftHeadWrapper table thead tr:last-child th:first-child, +div.DTFC_LeftHeadWrapper table thead tr:last-child td:first-child { + border-bottom-left-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +div.DTFC_LeftBodyWrapper table { + border-top: none; + margin-bottom: 0 !important; +} + +div.DTFC_LeftBodyWrapper tbody tr:first-child th, +div.DTFC_LeftBodyWrapper tbody tr:first-child td { + border-top: none; +} + +div.DTFC_LeftFootWrapper table { + border-top: none; +} + + +caption { + display: none; +} + +.required { + font-weight: bold; +} + +.form-horizontal .control-label { + white-space: normal; + width: 160px; + margin: 0 10px 0 0; +} + +.mapPicker img { + max-width: none; +} +/* override jquery UI per compatibilità con Glizy */ +.ui-front { + position: fixed !important; + z-index: 110 !important; +} + + + +/* storege browser */ + +table.storageBrowser{ + width: 100%; +} + +table.storageBrowser .icon { + width: 18px; +} + +table.storageBrowser td.folder { + background: url( '../icons/folder.png') no-repeat 4px 4px; +} + +table.storageBrowser td.image { + background: url( '../icons/image.png') no-repeat 4px 4px; +} + +table.storageBrowser td.audio { + background: url( '../icons/audio.png') no-repeat 4px 4px; +} + +table.storageBrowser td.other { + background: url( '../icons/other.png') no-repeat 4px 4px; +} + +table.storageBrowser td.pdf { + background: url( '../icons/pdf.png') no-repeat 4px 4px; +} + + +table.storageBrowser .filename { + font-weight: bold; +} + + +table.storageBrowser .size { + text-align:right; + width: 100px; +} + +table.storageBrowser .date { + text-align:right; + width: 150px; +} + + +table.storageBrowser tbody tr { + cursor: pointer; +} + + +table#dataGrid.storageBrowser tbody tr.ruled td{ + background-color: #fff; +} + + +div.addMedia input.mediaFilePicker { + margin-left: 10px; +} + + +.VS-search .ui-menu { + width: auto; +} + +.VS-search { + margin-bottom: 20px; +} + +#filters_visualsearch { + margin:0 0 0 0px!important; + + .VS-search-box-wrapper { + width:80%; + float:left; + margin-right:7px; + } + + .VS-search-box { + box-shadow:none!important; + .border-radius(0)!important; + border:1px solid #ccc!important; + } + + .VS-search input { + border: 0; + background-color: transparent; + box-shadow: 0 0 0 0; + } +} + + +.glizyVisualSearch { + margin-left: 0 !important; + + .VS-search-box { + box-shadow:none!important; + .border-radius(0)!important; + border:1px solid #ccc!important; + } + + .VS-search input { + border: 0; + background-color: transparent; + box-shadow: 0 0 0 0; + } +} + + + +/* jstree */ +.jstree-default a ins.jstree-icon.home { + background: transparent url(../images/treeIcons.png) no-repeat 0 0; +} + +.jstree-default a ins.jstree-icon.page { + background: transparent url(../images/treeIcons.png) no-repeat -19px 0; +} + +.jstree-default a ins.jstree-icon.alias { + background: transparent url(../images/treeIcons.png) no-repeat -36px 0; +} + +.jstree-default a ins.jstree-icon.folder { + background: transparent url(../images/treeIcons.png) no-repeat -56px 0; +} + +.jstree-default a ins.jstree-icon.system { + background: transparent url(../images/treeIcons.png) no-repeat -73px 0; +} + +.jstree-default a ins.jstree-icon.home.lock { + background: transparent url(../images/treeIcons.png) no-repeat 0 -18px; +} + +.jstree-default a ins.jstree-icon.page.lock { + background: transparent url(../images/treeIcons.png) no-repeat -19px -18px; +} + +.jstree-default a ins.jstree-icon.alias.lock { + background: transparent url(../images/treeIcons.png) no-repeat -36px -18px; +} + +.jstree-default a ins.jstree-icon.folder.lock { + background: transparent url(../images/treeIcons.png) no-repeat -56px -18px; +} + +.jstree-default a ins.jstree-icon.system.lock { + background: transparent url(../images/treeIcons.png) no-repeat -73px -18px; +} + +.jstree-default a ins.jstree-icon.hide { + opacity: 0.5; +} + +.jstree-default-context li ins { + padding: 3px 0 0 5px; + color: #505050; +} + +div.addMedia input.mediaFilePicker { + margin-left: 10px; +} + +/* add page */ +.pageTypeSelect { + + li { + border: 1px solid #D5D5D5; + box-shadow: 0 1px 0 0 @white inset, 0 1px 0 rgba(255, 255, 255, 0.4); + display: inline-block; + line-height: 18px; + margin: 0 10px 10px; + padding: 0 10px; + width: 19.5%; + position: relative; + -moz-transition: all 0.2s ease-in-out; + cursor: pointer; + + &:hover, &.button-selected { + border: 1px solid @orange8; + box-shadow: 0 1px 0 0 @white inset, 0 0 6px rgba(0,0,0, 0.1); + background-color:@white; + } + + a { + + display:inline-block; + text-align:center; + color:@black2; + min-height:26px; + width:100%; + + &:hover { + text-decoration:none; + } + + &.button-generic { + background:url(../img/article.png) center 10px no-repeat; + + padding-top:65px; + } + + &.button-article { + background:url(../img/article.png) center 10px no-repeat; + + padding-top:65px; + } + + &.button-attach { + background:url(../img/attach.png) center 10px no-repeat; + + padding-top:65px; + } + + &.button-exercise { + background:url(../img/exercise.png) center 10px no-repeat; + + padding-top:65px; + } + + } + + } + + + + } + + +.hotspots-container #selectionMarquee { + z-index: 1000; + position: absolute; + border: 1px dashed #cc0001; + display: none; +} + +.hotspots-container .selected-box { + z-index: 999; + position: absolute; + background-color: rgba(255, 255, 1, 0.3); +} + +.hotspots-container .hotspot-circle { + -webkit-border-radius: 50%; + border-radius: 50%; +} + +.hotspots-container .hotspot { + position: relative; + margin: 4px; + border: 1px solid #999; + clear: both; + height: 182px; +} + +.hotspots-container .selected { + border: 2px solid yellow; +} + +.hotspots-container .hotspots-container { + clear: both; + border: 1px solid #999; + padding: 2px; + margin: 40px; +} + +.hotspots-container .btn-container { + clear: both; + border: 1px solid #999; + padding: 4px; + margin: 2px; +} + +.hotspots-container .hotspots-list { + position: relative; + float: left; + border: 1px solid #999; + width: 310px; + margin: 2px; + overflow: auto; +} + +.hotspots-container .hotspots-image { + float: left; + border: 1px solid #999; + padding: 4px; + margin: 2px; + position: relative; +} + +.hotspots-container .list-label { + float: left; + width: 50px; +} + +.hotspots-container .list-container { + padding: 4px; +} + +.hotspots-container .print-check { + float: left; + margin-left: 10px; +} + +.hotspots-container .list-select { + float: left; + margin-left: 10px; + width: 210px; + height: auto; + padding: 0; +} + +.hotspots-container .list-description { + clear: both; + margin: 4px; + width: 270px; +} + +.hotspots-container .list-url { + float: left; + margin-left: 10px; + height: auto; + width: 200px; +} + + +.hotspots-container .delete { + position: absolute; + top: 6px; + right: 5px; +} + + + + +/* Apply the element you want to drag/resize */ +._drsElement { + position: absolute; + border: 1px solid #333; +} + +.drsElement { + position: absolute; +} + +/* + The main mouse handle that moves the whole element. + You can apply to the same tag as drsElement if you want. +*/ +._drsMoveHandle { + height: 20px; + background-color: #CCC; + border-bottom: 1px solid #666; + cursor: move; +} +.drsMoveHandle { + cursor: move; +} + + +/* + The DragResize object name is automatically applied to all generated + corner resize handles, as well as one of the individual classes below. +*/ + +.dragresize { + position: absolute; + width: 5px; + height: 5px; + font-size: 1px; + background: yellow; + border: 1px solid #333; +} + +/* + Individual corner classes - required for resize support. + These are based on the object name plus the handle ID. +*/ +.dragresize-tl { + top: -8px; + left: -8px; + cursor: nw-resize; +} +.dragresize-tm { + top: -8px; + left: 50%; + margin-left: -4px; + cursor: n-resize; +} +.dragresize-tr { + top: -8px; + right: -8px; + cursor: ne-resize; +} + +.dragresize-ml { + top: 50%; + margin-top: -4px; + left: -8px; + cursor: w-resize; +} +.dragresize-mr { + top: 50%; + margin-top: -4px; + right: -8px; + cursor: e-resize; +} + +.dragresize-bl { + bottom: -8px; + left: -8px; + cursor: sw-resize; +} +.dragresize-bm { + bottom: -8px; + left: 50%; + margin-left: -4px; + cursor: s-resize; +} +.dragresize-br { + bottom: -8px; + right: -8px; + cursor: se-resize; +} + +#diff { + /* + https://github.com/chrisboulton/php-diff + */ + .Differences { + width: 100%; + border-collapse: collapse; + border-spacing: 0; + empty-cells: show; + } + + .Differences thead th { + text-align: left; + border-bottom: 1px solid #000; + background: #aaa; + color: #000; + padding: 4px; + } + .Differences tbody th { + text-align: right; + background: #ccc; + width: 4em; + padding: 1px 2px; + border-right: 1px solid #000; + vertical-align: top; + font-size: 13px; + } + + .Differences td { + padding: 1px 2px; + font-family: Consolas, monospace; + font-size: 13px; + } + + .DifferencesSideBySide .ChangeInsert td.Left { + background: #dfd; + } + + .DifferencesSideBySide .ChangeInsert td.Right { + background: #cfc; + } + + .DifferencesSideBySide .ChangeDelete td.Left { + background: #f88; + } + + .DifferencesSideBySide .ChangeDelete td.Right { + background: #faa; + } + + .DifferencesSideBySide .ChangeReplace .Left { + background: #fe9; + } + + .DifferencesSideBySide .ChangeReplace .Right { + background: #fd8; + } + + .Differences ins, .Differences del { + text-decoration: none; + } + + .DifferencesSideBySide .ChangeReplace ins, .DifferencesSideBySide .ChangeReplace del { + background: #fc0; + } + + .Differences .Skipped { + background: #f7f7f7; + } + + .DifferencesInline .ChangeReplace .Left, + .DifferencesInline .ChangeDelete .Left { + background: #fdd; + } + + .DifferencesInline .ChangeReplace .Right, + .DifferencesInline .ChangeInsert .Right { + background: #dfd; + } + + .DifferencesInline .ChangeReplace ins { + background: #9e9; + } + + .DifferencesInline .ChangeReplace del { + background: #e99; + } + + pre { + width: 100%; + overflow: auto; + } +} + +ul.mediaArchive.nav-pills { + margin-bottom: 0; +} + +.modulesBuilderStep1Panel { border-bottom: 1px solid #ccc; margin-bottom: 1em; overflow: hidden;} +.modulesBuilderStep1Panel p { float: left; width: 80%;} +.modulesBuilderStep1Panel input { float: right; margin-top: 1.5em;} +.modulesBuilderTable { margin-top: 2em;} +.modulesBuilderTable td.dragHandler { padding-left: 20px; background: url( ../images/common/dragHandler.gif) no-repeat;} +.modulesBuilderTable td.newTableFoot { text-align: center; height: 50px;} +.modulesBuilderTable #newTableBtnAdd { padding: 5px; background: #328BE5; color: #fff; width: 100px; text-decoration: none;} +.modulesBuilderTable .delete { cursor: pointer;} + +.GlizycmsBlockEdit { + margin-bottom: 40px; + h2 { + font-size: 20px; + line-height: 1em; + font-weight: normal; + padding: 5px; + background-color: @themeColor; + color: @white; + } + + div.blockItem { + width: 180px; + height: 230px; + float: left; + margin-right: 10px; + margin-bottom: 10px; + padding: 10px; + background-color: @white; + border: 1px solid @grey1; + cursor: grab; + position: relative; + + h3 { + font-size: 18px; + margin: 0; + padding: 0; + line-height: 1.4em; + } + p { + font-size: 13px; + line-height: 1.4em; + margin: 0; + padding: 0; + } + + .actions { + position: absolute; + width: 180px; + bottom: 15px; + text-align: right; + } + } + + div.blockEmpty { + cursor: pointer; + color: @grey1; + + i { + position: absolute; + top: 50px; + left: 50px; + font-size: 120px; + } + + .actions { + text-align: center; + } + } +} + + +input.delete-media { + float: left; + margin: 5px; +} diff --git a/src/admin/application/templates/less/global.less b/src/admin/application/templates/less/global.less new file mode 100755 index 0000000..4116f1d --- /dev/null +++ b/src/admin/application/templates/less/global.less @@ -0,0 +1,310 @@ +@import url(http://fonts.googleapis.com/css?family=PT+Sans:400,700,400italic); + +html, body { + margin: 0; + padding: 0; + height: 100%; + width: 100%; + font-family: 'PT Sans', sans-serif; + padding: 0 !important; +} + + +body>#outer { + height:auto; + min-height:100%; + width:100%; + position:relative; + } + +label, +select, +button, +input[type="text"], +input[type="button"], +input[type="reset"], +input[type="submit"], +input[type="radio"], +input[type="checkbox"] { + font-family: 'PT Sans', sans-serif; +} + +input[type="search"] { + font-family: 'PT Sans', sans-serif; +} + +input[type="search"]::-webkit-search-decoration, +input[type="search"]::-webkit-search-cancel-button { + font-family: 'PT Sans', sans-serif; +} + + +a { + color:@orange8; +} +a:hover { + color: @orange5; + text-decoration: underline; +} + + + +footer { + position: absolute; + text-align:right; + color:@grey20; + font-size:13px; + padding-top:0; + height:34px; + right:10px; + padding-bottom:15px!important; + margin-right:0px; + + p { + .margin-reset(); + .padding-reset(); + font-style:italic; + padding-top:10px; + position:relative; + } + + } + +.form-vertical .control-group { + padding-bottom:0; + margin-bottom:0; + + input[type="text"] { + padding:0!important; + font-size:12px; + margin-bottom:0; + } + + input[type="text"][class*="span"] { + min-height:0px; + } + + + } + +.btn { + font-size:13px; + } + +a.thumbnail:hover { + border-color:@orange8; + } + +.alert { + + .close { + margin-top:2px; + } + + border-radius:0; + + &.welcome { + + border-color:@light-blue; + background-color:@light-blue2; + + &.alert-info { + color:@light-blue3; + } + + } + + &.alert-info { + color:@black2; + } + + } + +.label { + font-weight:lighter; + } + +.box.margin-top { + margin-top:10px; + } + +/* action-link */ + + a.action-link { + float: left; + display: block; + color: @grey14; + font-weight: normal; + padding: 2px 10px 1px 10px; + margin-right: 10px; + margin-top: 6px; + font-size: 13px; + font-style: normal; + + &.btn { + border:0; + background:none; + box-shadow:none; + font-size:13px; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + } + + &.btnBig { + font-size: 15px; + } + + i { + margin-top: 0px; + } + + &:hover { + text-decoration: none; + background-color: @grey9; + color:@black!important; + background:none!important; + } + + &:focus { + outline: 0; + } + + &.with-background { + background-color: @grey; + } + + &.with-background:hover { + background-color: @grey10!important; + text-decoration: none; + color: @white!important; + } + + &.with-background:hover i { + /*background-image: url('../img/glyphicons-halflings-white.png');*/ + } + + } + +.action-link.btn-primary.btn { + border:0; + background:none; + box-shadow:none; + float: left; + display: block; + color: @grey14; + font-weight: 400; + padding:3px 10px 1px 10px; + margin-right: 10px; + margin-top: 6px; + font-size: 13px; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + } + +div.afterTableActions { + margin: 20px 0; + text-align: center; + + a.action-link { + float: none; + } +} + +#topbar { + + a.action-link { + + &.btn { + text-shadow:none; + } + + } + + .dropdown-menu { + + li { + + a { + color:#black2; + } + + } + + } + +} + +#language-menu { + + .btn-group { + + a.action-link { + + &.btn { + margin:0; + margin-top:-3px; + } + + } + + .dropdown-menu { + + + li { + + + a { + color:@black2; + text-indent:0; + font-size:13px; + padding-left:10px!important; + + &:hover { + color:@white; + } + + } + + } + + } + + } + +} + +/* collapse menu */ + +.show-nav-for-iphone { + display:none; + } + +#nav-collapse.collapse { + height:auto; + } + +@media (max-width: 768px) { + #nav-collapse.collapse { + height:0; + } +} + + +@media (max-width: 768px) { + .show-nav-for-iphone { + display:block; + position:absolute; + right:7px; + top:7px; + background:@orange3 url("../img/glyphicons-halflings-white.png") -332px -44px no-repeat; + width:24px; + height:24px; + border:0; + border:1px solid @orange4; + padding:0; + z-index:9999; + } + +} + +.thumbnail { + min-height:130px; +} \ No newline at end of file diff --git a/src/admin/application/templates/less/libs/bootstrap-responsive.less b/src/admin/application/templates/less/libs/bootstrap-responsive.less new file mode 100755 index 0000000..7000438 --- /dev/null +++ b/src/admin/application/templates/less/libs/bootstrap-responsive.less @@ -0,0 +1,1094 @@ +/*! + * Bootstrap Responsive v2.2.2 + * + * 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. + */ + +@-ms-viewport { + width: device-width; +} + +.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; +} + +.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; + } +} + +@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: 481px) 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 .dropdown-menu a:hover { + 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 .dropdown-menu a:hover { + 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/admin/application/templates/less/libs/bootstrap.less b/src/admin/application/templates/less/libs/bootstrap.less new file mode 100755 index 0000000..8ab3cef --- /dev/null +++ b/src/admin/application/templates/less/libs/bootstrap.less @@ -0,0 +1,6039 @@ +/*! + * Bootstrap v2.2.2 + * + * 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. + */ + +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; + } +} + +.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; +} + +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 { + 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 { + color: #808080; +} + +.text-warning { + color: #c09853; +} + +a.text-warning:hover { + color: #a47e3c; +} + +.text-error { + color: #b94a48; +} + +a.text-error:hover { + color: #953b39; +} + +.text-info { + color: #3a87ad; +} + +a.text-info:hover { + color: #2d6987; +} + +.text-success { + color: #468847; +} + +a.text-success:hover { + color: #356635; +} + +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; + padding-right: 5px; + padding-left: 5px; +} + +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: 16px; + font-weight: 300; + line-height: 25px; +} + +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 { + margin-bottom: 5px; + font-size: 0; + white-space: nowrap; +} + +.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 { + 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 { + -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 { + -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 tfoot:last-child tr:last-child > td: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 tfoot:last-child tr:last-child > td: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/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:hover > [class*=" icon-"], +.dropdown-menu > .active > a > [class^="icon-"], +.dropdown-menu > .active > a > [class*=" icon-"], +.dropdown-submenu:hover > a > [class^="icon-"], +.dropdown-submenu:hover > 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 { + 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 { + 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 { + 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 { + color: #999999; +} + +.dropdown-menu .disabled > a:hover { + 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 { + 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 #bbbbbb; + *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: #a2a2a2; + -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: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 { + 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 { + border-color: #c5c5c5; + border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25); +} + +.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: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: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: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: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: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: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 { + color: #005580; + text-decoration: underline; + background-color: transparent; +} + +.btn-link[disabled]:hover { + 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-mini .caret, +.btn-small .caret, +.btn-large .caret { + margin-top: 6px; +} + +.btn-large .caret { + border-top-width: 5px; + border-right-width: 5px; + border-left-width: 5px; +} + +.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 { + 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 { + 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 { + border-color: #eeeeee #eeeeee #dddddd; +} + +.nav-tabs > .active > a, +.nav-tabs > .active > a:hover { + 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 { + 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 { + 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 { + 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 { + cursor: pointer; +} + +.nav-tabs .open .dropdown-toggle, +.nav-pills .open .dropdown-toggle, +.nav > li.dropdown.open.active > a:hover { + 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 { + border-top-color: #ffffff; + border-bottom-color: #ffffff; + opacity: 1; + filter: alpha(opacity=100); +} + +.tabs-stacked .open > a:hover { + 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 { + border-top-color: #ddd; + border-bottom-color: transparent; +} + +.tabs-below > .nav-tabs > .active > a, +.tabs-below > .nav-tabs > .active > a:hover { + 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 { + border-color: #eeeeee #dddddd #eeeeee #eeeeee; +} + +.tabs-left > .nav-tabs .active > a, +.tabs-left > .nav-tabs .active > a:hover { + 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 { + border-color: #eeeeee #eeeeee #eeeeee #dddddd; +} + +.tabs-right > .nav-tabs .active > a, +.tabs-right > .nav-tabs .active > a:hover { + border-color: #ddd #ddd #ddd transparent; + *border-left-color: #ffffff; +} + +.nav > .disabled > a { + color: #999999; +} + +.nav > .disabled > a:hover { + 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 { + text-decoration: none; +} + +.navbar-text { + margin-bottom: 0; + line-height: 40px; + color: #777777; +} + +.navbar-link { + color: #777777; +} + +.navbar-link:hover { + 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 { + 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: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 { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.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 { + 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 { + 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 { + 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: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 > .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 { + 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 { + 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 > 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; + padding: 5px; + font-size: 11px; + opacity: 0; + filter: alpha(opacity=0); + visibility: visible; +} + +.tooltip.in { + opacity: 0.8; + filter: alpha(opacity=80); +} + +.tooltip.top { + margin-top: -3px; +} + +.tooltip.right { + margin-left: 3px; +} + +.tooltip.bottom { + margin-top: 3px; +} + +.tooltip.left { + margin-left: -3px; +} + +.tooltip-inner { + max-width: 200px; + padding: 3px 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; + width: 236px; + 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-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 { + 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.badge:hover { + 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 { + 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 { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} + +.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/admin/application/templates/less/libs/h5bp.less b/src/admin/application/templates/less/libs/h5bp.less new file mode 100755 index 0000000..408752b --- /dev/null +++ b/src/admin/application/templates/less/libs/h5bp.less @@ -0,0 +1,298 @@ +/* + * HTML5 Boilerplate + * + * What follows is the result of much research on cross-browser styling. + * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal, + * Kroc Camen, and the H5BP dev community and team. + */ + +/* ========================================================================== + Base styles: opinionated defaults + ========================================================================== */ + +html, +button, +input, +select, +textarea { + color: #222; +} + +body { + font-size: 1em; + line-height: 1.4; +} + +/* + * Remove text-shadow in selection highlight: h5bp.com/i + * These selection declarations have to be separate. + * Customize the background color to match your design. + */ + +::-moz-selection { + background: #b3d4fc; + text-shadow: none; +} + +::selection { + background: #b3d4fc; + text-shadow: none; +} + +/* + * A better looking default horizontal rule + */ + +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #ccc; + margin: 1em 0; + padding: 0; +} + +/* + * Remove the gap between images and the bottom of their containers: h5bp.com/i/440 + */ + +img { + vertical-align: middle; +} + +/* + * Remove default fieldset styles. + */ + +fieldset { + border: 0; + margin: 0; + padding: 0; +} + +/* + * Allow only vertical resizing of textareas. + */ + +textarea { + resize: vertical; +} + +/* ========================================================================== + Chrome Frame prompt + ========================================================================== */ + +.chromeframe { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; +} + +/* ========================================================================== + Author's custom styles + ========================================================================== */ + + + + + + + + + + + + + + + + + +/* ========================================================================== + Helper classes + ========================================================================== */ + +/* + * Image replacement + */ + +.ir { + background-color: transparent; + border: 0; + overflow: hidden; + /* IE 6/7 fallback */ + *text-indent: -9999px; +} + +.ir:before { + content: ""; + display: block; + width: 0; + height: 100%; +} + +/* + * Hide from both screenreaders and browsers: h5bp.com/u + */ + +.hidden { + display: none !important; + visibility: hidden; +} + +/* + * Hide only visually, but have it available for screenreaders: h5bp.com/v + */ + +.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: h5bp.com/p + */ + +.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; +} + +/* + * Clearfix: contain floats + * + * For modern browsers + * 1. The space content is one way to avoid an Opera bug when the + * `contenteditable` attribute is included anywhere else in the document. + * Otherwise it causes space to appear at the top and bottom of elements + * that receive the `clearfix` class. + * 2. The use of `table` rather than `block` is only necessary if using + * `:before` to contain the top-margins of child elements. + */ + +.clearfix:before, +.clearfix:after { + content: " "; /* 1 */ + display: table; /* 2 */ +} + +.clearfix:after { + clear: both; +} + +/* + * For IE 6/7 only + * Include this rule to trigger hasLayout and contain floats. + */ + +.clearfix { + *zoom: 1; +} + +/* ========================================================================== + EXAMPLE Media Queries for Responsive Design. + Theses examples override the primary ('mobile first') styles. + Modify as content requires. + ========================================================================== */ + +@media only screen and (min-width: 35em) { + /* Style adjustments for viewports that meet the condition */ +} + +@media only screen and (-webkit-min-device-pixel-ratio: 1.5), + only screen and (min-resolution: 144dpi) { + /* Style adjustments for high resolution devices */ +} + +/* ========================================================================== + Print styles. + Inlined to avoid required HTTP connection: h5bp.com/r + ========================================================================== */ + +@media print { + * { + background: transparent !important; + color: #000 !important; /* Black prints faster: h5bp.com/s */ + box-shadow: none !important; + text-shadow: none !important; + } + + a, + a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + /* + * Don't show links for images, or javascript/internal links + */ + + .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; /* h5bp.com/t */ + } + + 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/admin/application/templates/less/libs/mixin.less b/src/admin/application/templates/less/libs/mixin.less new file mode 100755 index 0000000..ede0df9 --- /dev/null +++ b/src/admin/application/templates/less/libs/mixin.less @@ -0,0 +1,53 @@ +/* less define */ + +.margin-reset() { +margin:0; +} + +.padding-reset() { +padding:0; +} + +.padding-margin-reset() { + padding:0; + margin:0; +} + +.box-sizing() { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + +.border-radius (@radius) { + border-radius: @radius; + -moz-border-radius: @radius; + -webkit-border-radius: @radius; +} + +/* text-shaodow */ +.text-shadow (@x: 0, @y: 1px, @blur: 0, @color: #fff) { + text-shadow:@arguments; +} + +/* box-shadow */ +.box-shadow (@x: 0, @y: 1px, @blur: 0, @color: #fff, @where:inset ) { + box-shadow:@arguments; +} + + +.transition (@time:.4s){ + -moz-transition:all @time ease-in-out; + -webkit-transition:all @time ease-in-out; + -o-transition:all @time ease-in-out; + transition:all @time ease-in-out; + backface-visibility: hidden; + webkit-backface-visibility: hidden; + } + +/* define opacity */ + +.opacity (@opacity:.5){ + opacity:@opacity; + filter: alpha(opacity=@opacity); + } \ No newline at end of file diff --git a/src/admin/application/templates/less/structure.less b/src/admin/application/templates/less/structure.less new file mode 100755 index 0000000..10b4e70 --- /dev/null +++ b/src/admin/application/templates/less/structure.less @@ -0,0 +1,1661 @@ +/** GENERAL **/ +.pagination { + text-align: center; +} +.pagination ul { + border-radius: 0 !important; +} +.pagination ul > li > a, .pagination ul > li > span { border-radius: 0 !important;} + +.pagination span { + float: left; +} +/** TOP BAR **/ +#topbar { + min-height: 36px; + background: @themeColor; + position: fixed; + width: 100%; + z-index: 3; + top: 0; + + & > .pull-left { + height: 100%; + width: auto; + position: relative; + } + + .pull-right { + margin-right:10px; + + + @media (max-width: 767px) { + float:left; + width:100%; + margin-top:1px; + background-color:@orange4; + margin-left:-2px; + + } + + } + + #dummy-logo { + padding: 0; + float:left; + /*background: @orange4;*/ + height:25px; + } + + #dummy-text { + font-weight:lighter; + color: @white; + padding:8px 0px 0px 10px; + float:left; + font-size:22px; + height:26px; + + /* + &:before { + content: ''; + display: inline-block; + border-top: 18px solid transparent; + border-bottom: 18px solid transparent; + border-left: 18px solid @orange4; + position:absolute; + margin-left:-22px; + margin-top:-7px; + } + */ + + } + +} + +#language-menu, #user-menu, #exit-menu { + padding: 8px 13px 4px 13px; + color: @white; + height:25px; +} +#language-menu a, #user-menu > a, #exit-menu a { + color: @white; + + &:hover { + color: @white !important; + text-decoration: none; + } +} + +#language-menu strong { + margin-left:10px; + } + +#language-menu { +border-left: 1px solid @orange7; +} + +#user-menu { +border-left: 1px solid @orange7; +} + +#exit-menu { +border-left: 1px solid @orange7; +} + +#language-menu .dropdown-menu:before, #user-menu .dropdown-menu:before { + border-bottom: 7px solid rgba(0, 0, 0, 0.2); + border-left: 7px solid transparent; + border-right: 7px solid transparent; + content: ""; + display: inline-block; + left: 19px; + position: absolute; + top: -7px; +} +#language-menu .dropdown-menu:after, #user-menu .dropdown-menu:after { + border-bottom: 6px solid @white; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + content: ""; + display: inline-block; + left: 20px; + position: absolute; + top: -6px; +} + +/** SIDEBAR **/ +#sidebar, #treeview { + z-index: 2; + position: absolute; + min-height: 100%; + float: left; + top: 0; + width: 200px; + background-color: @grey9; + border-right: 1px solid @grey4; + box-shadow: -7px 0 10px rgba(0,0,0,0.03) inset; +} + +#sidebar { + + &.collapse { + + } + +} + +#sidebar-inner { + padding-top: 42px; + + .quick-link-block { + position:absolute; + top:0; + right:0; + width:200px; + .box-sizing(); + margin:-2px -201px 0 0; + background-color: @grey4; + border:1px solid @grey4; + display:none; + + &:before { + content: ''; + display: inline-block; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + border-right: 7px solid @black; + position: absolute; + left: -8px; + top: 7px; + opacity: 0.1; + } + + .quick-link-list { + background:@white; + + &:before { + content: ''; + display: inline-block; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + border-right: 7px solid @white; + position: absolute; + left: -7px; + top:5px; + } + + .padding-margin-reset(); + + padding-left:10px; + + } + + } + +} +#sidebar-inner ul { + margin: 0; + padding: 0; + list-style: none; + position:relative; + + li { + position:relative; + + &:hover { + + .quick-link-block { + display:block; + } + + } + + } + +} +#sidebar-inner > ul { + border-bottom: 1px solid #fcfcfc; + margin: 0 0 50px 0; +} +#sidebar-inner > ul > li { + border-top: 1px solid #fcfcfc; + border-bottom: 1px solid @grey4; +} +#sidebar-inner > ul > li:first-child { + border-top: none; +} +#sidebar-inner > ul > li > a { + display: block; + padding: 3px 10px 3px 7px; + color: @textNavigation; + text-shadow: 0 1px 0 @white; + position: relative; + font-size: 15px; +} +#sidebar-inner > ul > li.open > a { + padding: 10px 10px 0 5px; + border-left: 10px solid @grey4; +} +#sidebar-inner > ul > li.active > a { + font-weight: bold; + +} +#sidebar-inner > ul > li.active > a:before { + content: ''; + display: inline-block; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + border-right: 7px solid @black; + position: absolute; + right: 0; + top: 5px; + opacity: 0.1; +} +#sidebar-inner > ul > li.active > a:after { + content: ''; + display: inline-block; + border-top: 6px solid transparent; + border-bottom: 6px solid transparent; + border-right: 6px solid @white; + position: absolute; + right: -1px; + top: 5px; +} + +#sidebar-inner > ul > li > a > span.badge { + float: right; + margin-right: 5px; +} +#sidebar-inner > ul > li > a > i { + margin-right: 5px; +} + +#sidebar-inner ul ul { + padding: 0 0 0 35px; +} +#sidebar-inner > ul > li > ul { + border-left: 10px solid @grey4; + padding-bottom: 5px; +} +#sidebar-inner ul li ul { + display: none; +} +#sidebar-inner ul li.open > ul { + display: block; +} +#sidebar-inner ul ul li a { + display: block; + color: @textNavigation; + line-height: 24px; + position: relative; + & [class^="icon-"]{ + display: none; + } +} +#sidebar-inner ul ul li.active > a { + font-weight: bold; + +} +#sidebar-inner ul ul li.active > a:before { + content: ''; + display: inline-block; + border-top: 7px solid transparent; + border-bottom: 7px solid transparent; + border-right: 7px solid @black; + position: absolute; + right: 0; + top: 4.6px; + opacity: 0.1; +} +#sidebar-inner ul ul li.active > a:after { + content: ''; + display: inline-block; + border-top: 6px solid transparent; + border-bottom: 6px solid transparent; + border-right: 6px solid @white; + position: absolute; + right: -1px; + top: 5px; +} +#sidebar-inner ul ul ul { + padding: 0 0 0 20px; +} + +#sidebar-inner a:hover { + + i {text-decoration:none;} + + } + +/** TREEVIEW **/ +#treeview { + margin-left: 201px; + width: 229px; + background-color: @white; + box-shadow: -60px 0 20px rgba(0,0,0,0.03) inset; + + #page-detail { + min-height:98px; + width:229px; + margin-top:-10px; + position:relative; + + img { + float:left; + margin-right:12px; + width:62px; + } + + h2 { + font-size:16px; + font-weight:lighter; + line-height:1em; + padding-top:12px; + } + + .actions { + position:absolute; + bottom:0; + right:0; + font-size:12px; + margin:0 8px 8px 0; + + i {color:@black;} + + a { + + &:last-child { + border-left:1px solid @grey1; + padding-left:5px; + margin-left:2px; + } + + } + + } + + } + +} +#treeview-title { + margin-top: 36px; + background-color: @grey9; + border-bottom: 1px solid @grey4; + display:block; +} +#treeview-title h3 { + font-size: 14px; + color: @grey14; + padding: 9px 15px; + line-height: 14px; + margin: 0; +} +#treeview-title a { + float: right; + display: block; + color: @grey14; + font-size: 11px; + font-weight: bold; + margin: 6px 8px 0 0; +} +#treeview-title a i { + margin-top: -1px; +} + +#treeview #openclose { + width: 10px; + height: 50px; + background-color: @grey13; + position: absolute; + right: 0; + top: 200px; +} +#treeview #openclose:hover { + cursor: pointer; +} +#treeview #openclose i { + position: absolute; + top: 19px; + opacity: .6; +} +#treeview #openclose:hover i { + opacity: 1; +} +/** MAIN CONTAINER **/ +.with-sidebar #container { + margin-left: 201px; +} +.with-sidebar #container.with-treeview { + margin-left: 420px; + + #container-inner {padding-right: 0;} +} + +.menu-horizontal #treeview { + margin-left:-20px; + margin-top:97px; + padding-top:0; + + h3 { + margin-top:-36px; + } + +} + +#container-inner { + padding-top: 36px; +} + +.menu-horizontal #container.with-treeview { + margin-left: 190px; + margin-right: -40px; + margin-top:-13px; + + #container-inner {padding-top: 0;} +} + +#container-inner.with-breadcrumb { + padding-top: 90px; + + +} +#container-inner iframe { + border: 0; + width: 100%; + height: 600px; +} +#breadcrumb-bar { + height: 33px; + width: 100%; + padding: 0; + margin: -55px 0 0 0; + border-bottom: 1px solid @grey4; + position: relative; + background-color: @white; + z-index: 1; + display:block; +} + +#breadcrumb { + float: left; + margin-left:0; + height:33px; +} + +#breadcrumb ul { + margin:0 0 0 0; + padding: 0; + list-style: none; +} + +#breadcrumb ul li { + float: left; +} +#breadcrumb ul li a { + background-image: url("../img/breadcrumb.png"); + background-position: right center; + background-repeat: no-repeat; + color: @grey14; + display: inline-block; + font-size: 12px; + padding: 8px 20px 8px 10px; +} +#breadcrumb ul li:last-child a { + font-weight: bold; + background-image: none; +} +#breadcrumb ul li a i { + margin-top: -1px; + margin-right: 5px; + opacity: 0.6; +} +#breadcrumb-actions { + float: right; + + a {font-weight:lighter!important;} + +} + +.navigation, .subnavigation { + background-color: @grey9; + margin: 0 -20px 15px !important; + padding-right: 40px; + height: 35px; + box-shadow: -10px 0 10px rgba(0,0,0,0.1) inset; + border-bottom: 1px solid @grey1; +} +.navigation.with-sub { + margin-bottom: 0 !important; + /*margin-top:1px!important;*/ + box-shadow: 0 -3px 10px rgba(0,0,0,0.1) inset; +} +.navigation ul, .subnavigation ul { + margin: 0; + padding: 0; + list-style: none; +} + +.navigation ul li, .subnavigation ul li { + float: left; +} +.navigation ul li.active { + border-bottom: 3px solid @orange; +} +.navigation ul li a, .subnavigation ul li a { + border-right: 1px solid @grey1; + display: block; + color: @grey14; + font-size: 16px; + padding: 2px 15px 2px 15px; + margin: 5px 0 3px; +} +.navigation ul li:last-child a, .subnavigation ul li:last-child a { + border-right: 0; +} + +.navigation ul li a:hover i { + text-decoration:none; + } + +.subnavigation { + background-color: @grey; + height: 23px; + box-shadow: none; +} +.subnavigation ul { + margin-left: 10px; +} +.subnavigation ul li a { + font-size: 14px; + padding: 3px 10px; + line-height: 12px; + margin: 3px 0 0; +} +.subnavigation ul li.active a { + font-weight: bold; +} +.subnavigation #breadcrumb-actions { + margin-right: -40px; +} +.subnavigation #breadcrumb-actions a { + float: left; + display: block; + color: @grey14; + font-weight: bold; + padding: 2px 10px 1px; + margin-right: 10px; + margin-top: 0; + font-size: 13px; +} +.subnavigation #breadcrumb-actions a:hover { + background-color: @grey17; +} +.subnavigation #breadcrumb-actions a.with-background { + background-color: @grey18; +} +.subnavigation #breadcrumb-actions a.with-background:hover { + background-color: @grey10; + text-decoration: none; + color: @white; +} +/** BOX STYLES **/ + +.page-title { + padding:7px 5px 7px 5px; + font-weight: bold; + font-size: 20px; + line-height: 26px; + color: @textTitle; + border-bottom: 1px solid @grey4; + margin: 0; + + span { + color:@grey20; + } + +} +.page-title .nav { + float: right; +} + +.nav-tabs { + margin-top:2px; + display:block; + position:relative; + } + +.nav-tabs li a { + font-size: 14px; + padding: 5px 10px; + font-weight: normal; + border-radius: 0 !important; + background-color:@grey14; + color: @white; +} +.nav-tabs li a:hover { + background-color: @grey10; + border-color: @grey10; +} +.nav-tabs li.active a { + color: @grey14; + background-color: @white; +} +.page-title .help-text { + float: right; + font-size: 14px; + font-weight: normal; + margin: 5px 10px 0 0; +} +.box-content { + padding:15px 0; + + &.iframe { + padding:15px; + } + +} + +.box-padding { + padding:15px 30px; +} + +.widget-box { + margin: 20px 0; + border: 1px solid @grey1; +} +.widget-box h3.widget-title { + font-size: 13px; + background-image: -moz-linear-gradient(top center, @grey11 0%, @grey12 100%); + border-bottom: 1px solid @grey1; + padding: 4px 8px; + margin: 0; + font-weight:normal; + line-height: 20px; +} +.widget-box .widget-content { + padding: 10px; + background-color: @white2; + position: relative; +} +.widget-box .widget-content.nopadding { + padding: 0; +} +.widget-box form { + margin-bottom: 0; +} + +.widget-title .widget-icon { + float: left; + border-right: 1px solid @grey1; + padding: 5px 7px; + margin: -5px 10px 0 -5px; +} +.widget-title .badge, .widget-title .label { + float: right; + margin-top: 1px; +} +.widget-actions { + float: right; + font-weight: normal; + font-size: 13px; +} +.widget-actions.neg-margin { + margin-top: -40px; +} + +.widget-actions .order-link { + margin: 0 8px; +} +.widget-actions .order-link.active { + color: @white; + background-color: @orange8; + padding: 3px 7px; + border-radius: 4px; +} + +.row-fluid [class*="span"] .widget-box:first-child { + margin-top: 0; +} + + +.recent-posts, .recent-comments { + margin: 0; + padding: 0; +} +.recent-posts li, .recent-comments li, .article-post li { + border-bottom: 1px dotted @grey5; + list-style: none outside none; + padding: 10px; +} +.recent-comments li { + min-height:60px; + + &.show-all { + min-height:20px; + } + +} +.recent-posts li .article-title { + font-size: 16px; + font-weight: bold; +} +.recent-posts li .user-info { + font-size: 12px; + color: @grey6; +} +.recent-posts li:last-child, .recent-comments li:last-child, .recent-users li:last-child { + border-bottom: none !important; +} +.recent-posts li .article-links, .recent-comments li .article-links { + display: none; + float:right; +} +.recent-posts li:hover .article-links, .recent-comments li:hover .article-links { + display: block; +} +.recent-posts li.show-all, .recent-comments li.show-all { + background-image: -moz-linear-gradient(top center, @white 0%, #efefef 100%); + text-align: right; + height: 20px; +} + +.user-thumb { + background: none repeat scroll 0 0 @white; + border:0; + float: left; + height: 50px; + margin-right: 10px; + margin-top: 5px; + padding:0px; + width: 50px; +} + + + + + +/****/ +.entities { + display: inline-block; + list-style: none outside none; + margin: 20px 0 10px; + text-align: center; + width: 100%; + position: relative; + z-index: 0; +} +form .entities { + margin-top: 0; + text-align: left; +} +.entities { + + li { + background-color: @grey9; + background-image: -moz-linear-gradient(center top , @grey15 0%, @grey16 100%); + border: 1px solid #D5D5D5; + box-shadow: 0 1px 0 0 @white inset, 0 1px 0 rgba(255, 255, 255, 0.4); + display: inline-block; + line-height: 18px; + margin: 0 10px 10px; + padding: 0 10px; + width: 19.5%; + position: relative; + -moz-transition: all 0.2s ease-in-out; + cursor: pointer; + height:100px; + overflow:hidden; + + &:hover, &.button-selected { + border: 1px solid @orange8; + box-shadow: 0 1px 0 0 @white inset, 0 0 6px rgba(0,0,0, 0.1); + } + + h5 { + font-size: 18px; + text-align: left; + } + + .description { + float: left; + margin-bottom: 5px; + } + + } + + &.publication { + text-align:left; + + li { + background-color:@white; + background-image:none; + box-shadow: 0 1px 0 0 @white inset, 0 0 6px rgba(0,0,0, 0.1); + height:148px; + padding:0; + position:relative; + width:255px; + + h5 { + font-size:16px; + font-weight:normal; + margin-bottom:0; + padding-bottom:0; + } + + small { + color:@grey20; + } + + img { + float:left; + margin-right:10px; + } + + .description { + position: absolute; + top: 0; + left: 100px; + } + + .state { + width:91px; + display:inline-block; + position:absolute; + bottom:0; + left:50%; + color:@grey14; + font-size:12px; + text-align:center; + margin-left:-25px; + + &.public { + background:@green; + } + + &.no-public { + background:@red2; + } + + } + + } + + } + + &.ico-box { + + li { + background-color:@white; + background-image:none; + width:10%; + min-width:120px; + padding:0; + + a { + + display:inline-block; + text-align:center; + color:@black2; + min-height:26px; + width:100%; + + &:hover { + text-decoration:none; + } + + &.button-article { + background:url(../img/article.png) center 10px no-repeat; + + padding-top:65px; + } + + &.button-attach { + background:url(../img/attach.png) center 10px no-repeat; + + padding-top:65px; + } + + &.button-exercise { + background:url(../img/exercise.png) center 10px no-repeat; + + padding-top:65px; + } + + } + + } + + + + } + + .actions { + background: @black2; + padding: 2px 7px; + border-radius: 5px; + position: absolute; + bottom: 5px; + right: 5px; + + a { + color:@white; + } + + } + + + + } + +form.stickyForm .formButtons { + position: fixed; + bottom: 0; + left: 50%; + padding: 10px 0; + width:100%; + left:0; + z-index:9; + text-align: center; + height:20px; + border: 0; + border-bottom:10px solid @themeColor; + + .content { + min-width:430px; + background:@themeColor; + position:absolute; + top:0px; + left:50%; + margin-left:-215px; + padding:10px 0; + + input { + margin: 0 3px; + font-size: 14px; + } + } + +} + +/** OTHER **/ +.dropdown-menu { + -webkit-border-radius:0; + -moz-border-radius:0; + border-radius:0; + } + +.dropdown-menu.forced-left-position { + margin-left:-90px; + } + +.dropdown-menu li > a:hover, .dropdown-menu li > a:focus, .dropdown-submenu:hover > a { + background-image: none; + background-color: @orange; +} +.input-append { + width: 100%; +} +.input-append .btn { + width: 8.5%; +} + +label, input, button, select, textarea { + font-size: 15px; + line-height: 20px; +} +.form-horizontal .control-label { + width: 180px; + white-space: nowrap; +} +.form-horizontal .controls { + margin-left: 200px; +} +.vertical .control-label { + text-align: left; +} +.vertical .controls { + margin-left: 0; +} + +form { + + fieldset { + border:1px solid @grey21; + width: 97%; + margin: 0 auto 20px 20px; + + .content { + padding:10px; + width:97.6%; + + p { + padding:0; + margin:0 0 5px 0; + + input[type=checkbox] { + margin:0; + padding:0; + } + + } + + } + + legend { + padding:0; + margin:0 0 10px 0; + line-height:1em; + width:99%; + font-weight:bold; + font-size:14px; + padding:4px; + padding-top:6px; + background-color:@grey21; + + } + + } + + } + +.box-relations { + min-width: 910px; + h2 { + font-size:16px; + margin:0; + padding:0; + line-height:1em; + color:@grey20; + font-weight:lighter; + margin-bottom:10px; + } + + .relation { + background:@grey2 url(../img/relation.png) 0 0 repeat-y; + padding:8px 10px 0 15px; + height:74px; + font-size:14px; + border-bottom:1px solid @white; + + &.light-bg { + background:@grey22 url(../img/relation.png) 0 0 repeat-y; + } + + label { + display:inline-block; + margin-right:8px; + } + + span { + display:inline-block; + margin-top:5px; + } + + input[type=checkbox] { + margin:-2px 5px 0 0; + padding:0; + } + + input[type=text] { + margin-left:8px; + margin-right:8px; + } + + p { + margin:0 0 6px 0; + padding:0; + } + + select { + font-size:14px; + font-family: 'PT Sans', sans-serif; + } + + } + + } + +.btn, input, textarea { + border-radius: 0 !important; +} +.tab-content { + width: 100%; +} + +.tabs-left .tab-content, .tabs-right .tab-content { + width: auto; +} +.tabs-left .nav-tabs { + margin-right: -1px; +} +.tabs-left .tab-content { + border-left: 1px solid @grey4; + padding-left: 19px; +} + +.tabs-right .nav-tabs { + margin-left: -1px; +} +.tabs-right .tab-content { + border-right: 1px solid @grey4; + padding-right: 19px; +} +.row-fluid { + margin-bottom:0px; +} + +/** TABLES **/ +.table, .table-bordered { + border-radius: 0; +} +.table thead th { + font-size: 13px; + background-color: @grey11; + background-image: -moz-linear-gradient(top center, @grey11 0%, @grey12 100%); + border-bottom: 1px solid @grey1; + padding: 4px 8px; +} +.table .table-links { + font-size: 12px; +} +.table tr:hover .table-links { + display: block; +} +.table-bordered { + border: 0; + border-top: 1px solid @grey1; +} +.table-bordered thead th, .table-bordered thead td { + border-left: 1px solid @grey1; +} +.table-bordered 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 { + border-top-left-radius: 0; +} +.table-bordered thead:first-child tr:first-child > th:last-child, .table-bordered tbody:first-child tr:first-child > td:last-child { + border-top-right-radius: 0; +} +.table-bordered thead:last-child tr:last-child > th:first-child, .table-bordered tbody:last-child tr:last-child > td:first-child, .table-bordered tfoot:last-child tr:last-child > td:first-child { + border-bottom-left-radius: 0; +} +.table-bordered thead:last-child tr:last-child > th:last-child, .table-bordered tbody:last-child tr:last-child > td:last-child, .table-bordered tfoot:last-child tr:last-child > td:last-child { + border-bottom-right-radius: 0; +} +.table-bordered thead tr td:first-child, .table-bordered thead tr th:first-child, .table-bordered tbody tr td:first-child { + border-left: 1px solid @grey1; +} +.table-bordered thead tr td:last-child, .table-bordered thead tr th:last-child, .table-bordered tbody tr td:last-child { + border-right: 1px solid @grey1; +} +.table-bordered tbody tr:last-child > td { + border-bottom: 1px solid @grey1; +} +.table-bordered > tfoot > tr > td { + border: 0; + color: @grey7; + text-align: right; + padding-right: 15px; + margin-top:0!important; + font-style: italic; + padding:0; +} +.form-actions { + margin: 20px -10px -10px; + padding: 10px; + text-align: center; + background-image: -moz-linear-gradient(top center, @white 0%, #efefef 100%); +} + +.search-inputs { + margin-bottom: 30px; + text-align: right; + width:100%; + + .btn.calendar { + background:#fff; + border-left:0; + margin-left:0px; + } + +} +.search-inputs input[type=text], .search-inputs button { + margin-bottom: 0; + margin-right: -5px; +} +.search-inputs .search-input { + border-radius: 20px 0 0 20px !important; + + +} + +.search-inputs button.search { + float: right; + margin-top: 5px; +} + +.search-inputs div.control-group { + float: right; +} + +.search-inputs div.control-group input[type=text] { + width: 400px; +} + + + +.from-input, .to-input { + background:url(../img/calendar.png) 90% 8px no-repeat; + } + +.table { + font-size: 15px; +} + +.dataTable span.sorting-arrow { + display: inline-block; + width: 9px; + height: 9px; + margin-left: 5px; +} +.dataTable thead th.sorting_asc span.sorting-arrow { + background: no-repeat scroll 0 0 url('../img/up-arrow.png'); +} +.dataTable thead th.sorting_desc span.sorting-arrow { + background: no-repeat scroll 0 0 url('../img/down-arrow.png'); + margin-top: -1px; +} + +td.actions { + text-align: right; + white-space: nowrap; + a, a:hover, a:link { + text-decoration: none; + } +} + +/* +.dataTable thead th.sorting span.sorting-arrow { + background: no-repeat scroll 0 0 url('../img/up-down-arrow.png'); +} +*/ +.dataTables_length, .dataTables_filter { + position: relative; + float: right; +} +.dataTables_length label, .dataTables_filter label { + font-size: 13px; +} +.dataTables_length { + margin-left: 5px; +} +.dataTables_filter { + margin-right: 5px; +} +.dataTables_length select, .dataTables_filter input { + margin-bottom: 4px; + padding: 1px 3px; +} +.dataTables_length select { + width: 55px; + padding: 2px; +} + +.dataTables_info { + color: @grey7; + font-style: italic; + text-align: right; + margin-top: -10px; + padding-right: 10px; + margin-bottom: 10px; +} +.dataTables_paginate { + text-align: center; + margin-bottom: 20px; +} + +.dataTables_paginate .paginate_button, .dataTables_paginate .paginate_active, .paginate_disabled_previous, .paginate_enabled_previous, .paginate_disabled_next, .paginate_enabled_next, .paginate_disabled_next:hover, .paginate_disabled_previous:hover { + background-color: @white; + border-color: @grey4; + border-image: none; + border-style: solid; + border-width: 1px 1px 1px 0; + line-height: 20px; + padding: 6px 12px; + text-decoration: none; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + text-decoration: none; + color: @orange; +} +.dataTables_paginate > a:first-child { + border-left: 1px solid @grey4; +} +.dataTables_paginate .paginate_button:hover, .paginate_enabled_next:hover, .paginate_enabled_previous:hover { + cursor: pointer; + background-color: @grey3; + text-decoration: none; +} +.paginate_disabled_next, .paginate_disabled_previous, .paginate_disabled_next:hover, .paginate_disabled_previous:hover, .paginate_button_disabled { + color: @grey10 !important; +} +.paginate_button_disabled:hover { + background: @white !important; + cursor: normal !important; +} +.dataTables_paginate .paginate_active, .dataTables_paginate .paginate_active:hover { + font-weight: bold; + color: @black; + padding: 6px 12px 5px; +} +.table-options { + float: right; + margin-top: -5px; + margin-right: 15px; + height: 18px; + vertical-align: text-top; + white-space: nowrap; + font-weight: normal; +} + +.table-options .divider-horizontal { + border-left: 1px solid @grey1; + border-right: 1px solid @white; + display: inline-block; + height: 20px; + margin: 0 5px; +} + +.table-options input, .table-options select { + font-size: 12px; + height: 16px; + vertical-align: baseline; +} +.table-options select { + margin-bottom: 0; + min-height: 26px !important; +} + +.thumbnails { + margin-left: -2.12766% !important; +} +.thumbnails [class*="span"] { + margin-left: 2.12766% !important; + position: relative; +} +.thumbnails .title { + position: absolute; + width: 100%; + background: rgba(0,0,0,0.6); + color: @white; + font-weight: bold; + bottom: 0; + border-radius: 0 0 0 0; +} +.thumbnails .title .inner { + padding: 2px 10px; +} + +.thumbnails .actions { + background-color: @black; + border-radius:0; + height: 20px; + right: 0; + margin-right: 5px; + opacity: 0; + padding: 0px 3px; + position: absolute; + bottom: 2px; + transition: opacity 0.3s ease-in-out 0s; + /* width: 40px;*/ + + + a { + color:@white; + margin-top:-2px!important; + display:inline-block; + + &:hover { + text-decoration: none; + } + } + +} +.thumbnail { + .border-radius(0)!important; +} + +.thumbnails .actions i { + margin-top: 0; +} +.thumbnails li:hover .actions { + opacity: 1; +} +.dropdown-menu.left { + left: -110px; +} + +.section-title { + font-size:20px; + border-bottom:1px solid @grey4; + padding-bottom:15px; + margin-bottom:30px; + + h1 { + font-size:22px; + line-height:1em; + font-weight:400; + .padding-margin-reset(); + } + +} + +.dataTables_wrapper { + + .row-fluid { + + .filter-box { + float:left; + margin-right:10px; + + &.pull-right { + float:right; + margin-right:0; + } + + select, input { + height:30px; + font-size: 14px; + } + + + .dataTables_length { + padding-top:3px; + font-size:13px; + + select { + margin-top:-3px; + } + + } + + } + + } + +} + +.dataTable, .table { + + th { + + span.ui-icon { + float:left; + margin-right:5px; + margin-top:2px; + } + + } + +} + +.table th { + + a { + color:@black2; + text-decoration:none!important; + } + +} + +.btn-icon { + background:@grey14; + display:inline-block; + width:26px; + height:26px; + padding:0px 0 0 1px; + text-align:center; + .box-sizing(); + line-height:26px; + font-size:18px; + font-weight:lighter!important; + .border-radius(3px); + color:@white; + .transition(); + margin-right:5px!important; + text-decoration:none!important; + + + &:hover { + .opacity(); + text-decoration:none!important; + } + + &.icon-edit, &.icon-pencil { + background:@green2; + } + + &.icon-remove, &.icon-trash { + background:@red; + } + + &.icon-check-empty { + padding:0px 0 0 2px; + } + +} + +.pull-right, .pull-left { + + .btn-icon { + float:left; + } +} + +.entities.select-theme { + + li { + + border: 1px solid #D5D5D5; + box-shadow: 0 1px 0 0 @white inset, 0 1px 0 rgba(255, 255, 255, 0.4); + display: inline-block; + line-height: 18px; + margin: 0 10px 10px; + width: 23%!important; + position: relative; + -moz-transition: all 0.2s ease-in-out; + cursor: pointer; + + a { + &:hover, &.button-selected { + box-shadow: 0 1px 0 0 @white inset, 0 0 6px !important; + } + + } + + } + +} + +.choose-theme { + + .control-group { + + label { + margin-left:-40px; + } + + } + +} + +.current-theme { + padding-bottom:50px; + + img { + border: 1px solid #D5D5D5; + } + + i { + .padding-margin-reset(); + } + + h3 { + .padding-margin-reset(); + line-height:1em; + padding-bottom:15px; + } + +} + +.table-bordered caption + thead tr:first-child th:first-child { + border-top-left-radius:0px; +} + +.control-group.small-width { + + .control-label { + width:auto; + } + + .controls { + margin-left:80px; + } + +} + +.nav-pills > .active > a, .nav-pills > .active > a:hover { + background-color:@themeColor; + color: #FFFFFF; +} + +.nav-pills > li > a { + color:@black2; + } + +.my-filters { + margin-bottom:15px; + + .btn { + margin-top:1px!important; + } + +} + + +input[type="text"], input[type="password"] { + color: @black2 !important; +} + +.ui-pnotify.stack-bar-top { + right: 0; + top: 0 +} + +form.stickyForm { + margin-bottom: 60px; +} + +.btn-icon { + cursor: pointer; +} \ No newline at end of file diff --git a/src/admin/application/templates/less/styles.less b/src/admin/application/templates/less/styles.less new file mode 100755 index 0000000..99d4e74 --- /dev/null +++ b/src/admin/application/templates/less/styles.less @@ -0,0 +1,71 @@ +/** + * Import libraries + */ + +@import "libs/h5bp.less"; +@import "libs/mixin.less"; +@import "libs/bootstrap.less"; +@import "libs/bootstrap-responsive.less"; +@import "font-awesome.less"; +/** + * Template files + */ +@import "global.less"; +@import "custom.login.less"; +@import "structure.less"; +@import "glizy.less"; +@import "custom.less"; + +/*define lib colors */ + +@white:#ffffff; +@white2:#FDFDFD; +@grey:#eeeeee; +@grey1:#cccccc; +@grey2:#F5F5F5; +@grey3:#f7f7f7; +@grey4:#DDDDDD; +@grey5:#AEBDC8; +@grey6:#777777; +@grey7:#888888; +@grey8:#B6BCBF; +@grey9:#f6f6f6; +@grey10:#BBBBBB; +@grey11:#F1F1F1; +@grey12:#E2E2E2; +@grey13:#D8D8D8; +@grey14:#666666; +@grey15:#F9F9F9; +@grey16:#EDEDED; +@grey17:#E6E6E6; +@grey18:#DCDCDC; +@grey19:#D4D4D4; +@grey20:#999999; +@grey21:#F0F0F0; +@grey22:#FAFAFA; +@pink:#ffebe8; +@red:#CC0000; +@red1:#FFEBE8; +@red2:#FF9999; +@black:#000000; +@black2:#333333; +@orange:#CC0000; +@orange2:#E55B00; +@orange3:#FF8243; +@orange4:#E55C00; +@orange5:#AF4600; +@orange8:#C04416; +@blue:#004489; +@light-blue:#BCE8F1; +@light-blue2:#D9EDF7; +@light-blue3:#3E89AE; +@green:#D4F1BE; +@green2:#009900; +@red:#CC3333; + +@themeColor: #82992D; +@orange7:lighten(@themeColor, 8); +@orange6:lighten(@themeColor, 8); + +@textTitle: #505050; +@textNavigation: #505050; \ No newline at end of file diff --git a/src/admin/cache/.gitkeep b/src/admin/cache/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/admin/getFile.php b/src/admin/getFile.php new file mode 100644 index 0000000..66f3a02 --- /dev/null +++ b/src/admin/getFile.php @@ -0,0 +1,16 @@ +<?php +if (!defined('GLZ_LOADED')) +{ + require_once('../core/core.inc.php'); + $application = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.Application', '../application', '../'); + org_glizy_Paths::addClassSearchPath('application/classes/'); + + if (file_exists(org_glizy_Paths::get('APPLICATION_STARTUP'))) + { + // if the startup folder is defined all files are included + glz_require_once_dir(org_glizy_Paths::get('APPLICATION_STARTUP')); + } +} + + +include('../getFile.php'); \ No newline at end of file diff --git a/src/admin/getImage.php b/src/admin/getImage.php new file mode 100644 index 0000000..5a60542 --- /dev/null +++ b/src/admin/getImage.php @@ -0,0 +1,16 @@ +<?php +if (!defined('GLZ_LOADED')) +{ + require_once('../core/core.inc.php'); + $application = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.Application', '../application', '../'); + org_glizy_Paths::addClassSearchPath('application/classes/'); + + if (file_exists(org_glizy_Paths::get('APPLICATION_STARTUP'))) + { + // if the startup folder is defined all files are included + glz_require_once_dir(org_glizy_Paths::get('APPLICATION_STARTUP')); + } +} + + +include('../getImage.php'); \ No newline at end of file diff --git a/src/admin/index.php b/src/admin/index.php new file mode 100644 index 0000000..94c55f8 --- /dev/null +++ b/src/admin/index.php @@ -0,0 +1,8 @@ +<?php +require_once("../core/core.inc.php"); + +$application = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.AdminApplication', 'application', '../', '../application/'); +__Paths::set('APPLICATION_TO_ADMIN_TEMPLATE', '../static/movio/templates/'); +$application->useXmlSiteMap = true; +$application->setLanguage('it'); +$application->run(); \ No newline at end of file diff --git a/src/admin/uploader.php b/src/admin/uploader.php new file mode 100644 index 0000000..24db35a --- /dev/null +++ b/src/admin/uploader.php @@ -0,0 +1,38 @@ +<?php +require_once("../core/core.inc.php"); +$application = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.AdminApplication', 'application', '../', '../application/'); +$application->runSoft(); +$user = $application->getCurrentUser(); +if ($user->isLogged()) { + org_glizy_helpers_Files::deleteDirectory('cache/uploads/', 2*24*60); + processUploadFile(); +} else { + header("HTTP/1.0 403 Forbidden"); +} + +function processUploadFile() +{ + $uploadFolder = 'cache/uploads/'; + if (!empty($_FILES)) { + if (!file_exists($uploadFolder)) { + @mkdir($uploadFolder); + } + + $tempFile = $_FILES['file']['tmp_name']; + $uploadedFile = $uploadFolder.md5($_FILES['file']['tmp_name']); + move_uploaded_file($tempFile, $uploadedFile); + sendResponse(array('success'=>true, 'uploadFilename' => $uploadedFile, 'originalFilename' => $_FILES['file']['name'] ), false); + } else { + sendResponse('error', true); + } +} + +function sendResponse($response, $error) +{ + header('HTTP/1.1 '.($error ? '400' : '200 OK')); + header('Content-type: application/json'); + echo json_encode($response); + exit(); + +} + diff --git a/src/ajax.php b/src/ajax.php new file mode 100644 index 0000000..8d68f6d --- /dev/null +++ b/src/ajax.php @@ -0,0 +1,7 @@ +<?php +ob_start(); +require_once("core/core.inc.php"); + +$application = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.Application', 'application'); +org_glizy_Paths::addClassSearchPath('admin/application/classes/'); +$application->runAjax(); diff --git a/src/application/classes/movio/locale/en.php b/src/application/classes/movio/locale/en.php new file mode 100644 index 0000000..01b698b --- /dev/null +++ b/src/application/classes/movio/locale/en.php @@ -0,0 +1,439 @@ +<?php +$strings = array ( + 'Alert' => 'Alert', + 'Read' => 'Read', + 'Breadcrumbs path' => 'Your position:', + 'Entity' => 'Entity', + 'Draw' => 'Draw', + 'Relations' => 'Relations', + 'Subtitle' => 'Subtitle', + 'Entity to show' => 'Entity to show', + 'Show search form' => 'Show search form', + 'Yes' => 'Yes', + 'No' => 'No', + 'Text' => 'Text', + 'Width' => 'Width', + 'Height' => 'Height', + 'MW_FOOTER' => 'Page created %s, last change %s', + 'Text to search' => 'Text to search', + 'Add content' => 'Add content', + 'New content' => 'New content', + 'Edit content' => 'Edit content: <em>%s</em>', + 'Show mode' => 'Show mode', + 'Show links' => 'Show links', + 'Show links and description' => 'Show links and description', + 'Show images' => 'Show images', + 'Show links and images' => 'Show links and images', + 'Search Result' => 'Search Result', + 'Image' => 'Image', + 'Title' => 'Title', + 'Banner' => 'Banner', + 'App image' => 'App image', + 'App color' => 'App color', + 'Presentation video' => 'Presentation video', + 'Users' => 'Users', + 'URL' => 'URL', + 'Identifier' => 'Identifier', + 'Subject' => 'Subject', + 'Physycal alternative' => 'Physycal alternative', + 'Abstract' => 'Abstract', + 'Credits' => 'Credits', + 'Language' => 'Language', + 'Catalog' => 'Catalog', + 'Patronages' => 'Patronages', + 'Promoters' => 'Promoters', + 'Sponsors' => 'Sponsors', + 'Committee of Honor' => 'Committee of Honor', + 'Scientific Committee' => 'Scientific Committee', + 'Dedication' => 'Dedication', + 'Aknowledgements' => 'Aknowledgements', + 'Contacts' => 'Contacts', + 'Services' => 'Services', + 'Image galleries' => 'Image galleries', + 'Download files' => 'Download files', + 'Digital alternative' => 'Digital alternative', + 'Nation, Region, Province' => 'Nation, Region, Province', + 'Town' => 'Town', + 'Venue' => 'Venue', + 'Address' => 'Address', + 'Venue Geolocation' => 'Venue Geolocation', + 'Duration' => 'Duration', + 'Timetable' => 'Timetable', + 'Access' => 'Access', + 'Ticket Office' => 'Ticket Office', + 'Vernissage' => 'Vernissage', + 'Promoting organisations' => 'Promoting organisations', + 'Promotion' => 'Promotion', + 'Press Office' => 'Press Office', + 'Exhibition project' => 'Exhibition project', + 'Reviews' => 'Reviews', + 'Add new entity' => 'Add new entity', + 'Name' => 'Name', + 'Linked page' => 'Linked page', + 'Exhibition url' => 'Exhibition url', + 'Account link on Facebook' => 'Account link on Facebook', + 'From date' => 'From date', + 'To date' => 'To date', + 'Email booking' => 'Email booking', + 'Permanent exhibition' => 'Permanent exhibition', + 'LoadingBackgroundColor' => 'Background color while load', + 'LoadingBorderColor' => 'Border color while load', + 'ErrorTextColor' => 'Color of error messages', + 'disableContextMenu' => 'Disable context menu', + 'disableFullscreen' => 'Disable full screen', + 'attributeList' => 'Attribute list', + 'Key' => 'Chiave', + 'Value' => 'Valore', + 'Locations' => 'Localization data', + 'Country' => 'Country', + 'District' => 'District', + 'Place' => 'Place', + 'Coordinates' => 'Map', + 'Add tourist operator' => 'Add tourist operator', + 'Tourist Operators' => 'Tourist Operators', + 'Data saved correctly' => 'Data saved correctly', + 'Link type' => 'Link type', + 'Internal link' => 'Internal link', + 'External link' => 'External link', + 'Link title' => 'Link title', + 'Connect POI with a path' => 'Connect POI with a path', + 'No connection' => 'No connection', + 'Line' => 'Line', + 'Route car' => 'Route car', + 'Route transit' => 'Route transit', + 'Route bicycling' => 'Route bicycling', + 'Route walking' => 'Route walkings', + 'Markers' => 'Markers', + /* publishApp */ + 'Mobile App' => 'Mobile App', + 'Publish App' => 'Publish App', + 'Export content' => 'Export content', + 'Linked credit page' => 'Linked credit page', + 'Export' => 'Export', + 'Last exportation date' => 'Last exportation date', + 'Languages' => 'Languages', + 'Exhibition active' => 'Exhibition active', + 'Codes' => 'Codes', + /* timeline */ + 'Timeline Start date (yyyy, yyyy/mm, yyyy/mm/dd)' => 'Timeline Start date (yyyy, yyyy/mm, yyyy/mm/dd)', + 'Width (default full width)' => 'Width (default full width)', + 'Height (default 600px)' => 'Height (default 600px)', + 'Google Spreadsheet or other data source URL' => 'Google Spreadsheet or other data source URL', + 'Start at specific slide number' => 'Start at specific slide number', + 'Timeline definition' => 'Timeline definition', + 'Start date (yyyy, yyyy/mm, yyyy/mm/dd)' => 'Start date (yyyy, yyyy/mm, yyyy/mm/dd)', + 'End date (yyyy, yyyy/mm, yyyy/mm/dd)' => 'End date (yyyy, yyyy/mm, yyyy/mm/dd)', + 'Headline' => 'Headline', + 'External Media' => 'External Media', + 'Media caption' => 'Media caption', + /*Storyteller*/ + 'Story' => 'Story', + 'Story item type' => 'Story item type', + 'Text with media' => 'Text with media', + 'External video' => 'External video', + 'Photogallery' => 'Photogallery', + 'Enable comments' => 'Enable comments', + 'Insights' => 'Insights', + 'Write comment' => 'Write comment', + 'Full history' => 'Full history', + 'Audio' => 'Audio', + 'Video' => 'Video', + 'Images' => 'Images', + 'Texts' => 'Texts', + /* gallery */ + 'Gallery type' => 'Gallery type', + 'Gallery' => 'Gallery', + 'Slideshow' => 'Slideshow', + 'Slider' => 'Slider', + 'Page flip' => 'Page flip', + 'Image crop' => 'Image crop', + 'Image pan' => 'Image pan', + 'Images list' => 'Images list', + /* Users and Groups */ + 'Users and Groups' => 'Users and Groups', + 'Show user list' => 'Show user list', + 'Show group list' => 'Show group list', + 'User group' => 'User group', + 'Company' => 'Company', + 'Job title' => 'Job title', + 'Department' => 'Department', + 'City' => 'City', + 'ZIP' => 'ZIP', + 'Office phone' => 'Office phone', + 'Mobile phone' => 'Mobile phone', + 'Home phone' => 'Home phone', + 'Web site' => 'Web site', + 'Receives newsletter' => 'Receives newsletter', + 'Registered to Mailinglist' => 'Registered to Mailinglist', + 'Creation date' => 'Creation date', + /* media archive */ + 'Category' => 'Category', + 'Author' => 'Author', + 'Date' => 'Date', + 'Description' => 'Description', + 'Show zoom' => 'Show zoom', + 'Downloads' => 'Downloads', + 'Text after gallery' => 'Text after gallery', + 'Final text' => 'Final text', + 'Margin top' => 'Margin top', + "MW_EMPTY" => "Select an item", + "MW_SEARCH_RESULT" => "Search results", + "MW_SEARCH" => "Search", + "MW_NEW_SEARCH" => "New search", + "MW_BACK_TO_SEARCH" => "Back to search", + "MW_BACK" => "Back", + 'MW_SM_SITE_PROPERTIES' => 'Site properties', + 'MW_SITE_PROP' => 'Site properties', + 'MW_SITE_PROP_MODIFY' => 'Edit website properties', + 'MW_SITE_TITLE' => 'Site title', + 'MW_SITE_SUBTITLE' => 'Site subtitle', + 'MW_SITE_ADDRESS' => 'Address', + 'MW_SITE_COPYRIGHT' => 'Copyright', + 'MW_SITE_LINK_FOOTER' => 'Link Footer', + 'MW_SITE_SLIDESHOW_SPEED' => 'Slide show speed (seconds)', + 'MW_NEWS' => 'News', + 'MW_NEWS_LIST_TITLE' => 'List of news', + 'MW_NEWS_EDIT_TITLE' => 'Edit news', + 'MW_NEWS_LIST' => 'Search result', + 'MW_NEWS_STARTDATE' => 'Starting date', + 'MW_NEWS_ENDDATE' => 'Expiry date', + 'MW_NEWS_TITLE' => 'Title', + 'MW_NEWS_PLACE' => 'Place', + 'MW_NEWS_BODY' => 'News body text', + 'MW_NEWS_BODYSHORT' => 'News short body text', + 'MW_NEWS_LABELURL' => 'URL label linked to the news', + 'MW_NEWS_URL' => 'URL linked to the news', + 'MW_NEWS_IMAGE' => 'Image', + 'Images' => 'Images', + 'MW_EVENTS' => 'Events', + 'MW_EVENTS_LIST_TITLE' => 'List of events', + 'MW_EVENTS_EDIT_TITLE' => 'Edit event', + 'MW_EVENTS_DATE' => 'Date', + 'MW_EVENTS_REALDATE' => 'Visualized date', + 'MW_EVENTS_LIST' => 'List of events', + 'MW_EVENTS_TITLE' => 'Title', + 'MW_EVENTS_YEAR' => 'Year', + 'MW_EVENTS_PLACE' => 'Place', + 'MW_NEWS_CATEGORY' => 'Categoria', + 'MW_EVENTS_CATEGORY' => 'Category', + 'MW_EVENTS_PROMOTER' => 'Promoter', + 'MW_EVENTS_DESCRIPTION' => 'Description', + 'MW_EVENTS_EMAIL' => 'E-mail', + 'MW_EVENTS_URL' => 'URL', + 'MW_EVENTS_IMAGE' => 'Image', + 'MW_EVENTS_PUBLISHED' => 'Publish in homepage', + 'MW_EVENTS_PUBLICATION_ORDER' => 'Homepage Publication order', + 'MW_SUBMIT' => 'Submit', + 'MW_CANCEL' => 'Cancel', + 'MW_USER_USERNAME' => 'Username', + 'MW_USER_PSW' => 'Password', + 'MW_USER_NAME' => 'Name', + 'MW_USER_SURNAME' => 'Surname', + 'MW_USER_COMPANY' => 'Company', + 'MW_USER_TITLE' => 'Title', + 'MW_USER_JOBTITLE' => 'Job title', + 'MW_USER_DEPARTMENT' => 'Department', + 'MW_USER_ADDRESS' => 'Address', + 'MW_USER_CITY' => 'City', + 'MW_USER_STATE' => 'State', + 'MW_USER_ZIP' => 'ZIP', + 'MW_USER_COUNTRY' => 'Country', + 'MW_USER_EMAIL' => 'E-mail', + 'MW_USER_PHONE' => 'Office phone', + 'MW_USER_MOBILE' => 'Mobile phone', + 'MW_USER_PHONE2' => 'Home phone', + 'MW_USER_FAX' => 'Fax', + 'MW_USER_WEB' => 'Web site', + 'MW_USER_NEWSLETTER' => 'Receives newsletter', + 'MW_USER_MAILINGLIST' => 'Registered to Mailinglist', + 'MW_USER_WANT_NEWSLETTER' => 'I would like to receive the newsletter', + 'MW_USER_WANT_MAILINGLIST' => 'I would like to subscribe the mailinglist', + /* registration */ + 'Check following errors:' => 'Check following errors:', + 'MW_REGISTRATION_REQUIRED' => 'The fields in bold are required', + 'MW_REGISTRATION_PRIVACY' => 'I agree to data processing according to current regulations', + 'MW_REGISTRATION_CONFIRM' => 'Registration confirm', + 'MW_REGISTRATION_PRIVACY_TEXT' => 'Privacy text', + 'MW_LOSTPASSWORD_SEND' => 'Send password', + 'MW_LOSTPASSWORD_TEXT' => 'Testo introduttivo', + 'MW_LOSTPASSWORD_CONFIRM' => 'Testo di conferma', + 'MW_LOSTPASSWORD_ERROR' => 'Wrong user', + 'MW_LOSTPASSWORD_EMAIL_SUBJECT' => 'New password', + 'MW_LOSTPASSWORD_EMAIL_BODY' => '<p>The user account ##USER## has requested the password to have access to the web site ##HOST##.</p> <p>Your Password is: ##PASSWORD##</p>', + 'MW_LOGIN_TITLE' => 'Login', + 'MW_LOGIN_USER' => 'Email:', + 'MW_LOGIN_PSW' => 'Password:', + 'MW_LOGIN_REGISTER' => 'Register now', + 'MW_LOGIN_CONFIRM' => 'Login', + 'MW_LOGIN_ERROR' => 'Wrong username or password.', + 'MW_LOGIN_REMEMBER' => 'Remember me', + 'MW_LOGIN_ASK_PASSWORD' => 'Forgotten your password?', + 'MW_LOGIN_REQUIRED' => 'You are not authorized to view this resource. You need to login.', + 'MW_LOGIN_DESTINATION_PAGE' => 'Destination page after login', + 'MW_LOGOUT' => 'Logout', + 'MW_LOGIN_MYDETAILS' => 'My details', + 'Ontology Builder' => 'Ontology Builder', + 'Labels Translations' => 'Labels Translations', + 'Entities' => 'Entities', + 'Graph' => 'Graph', + 'Physical Exhibition' => 'Physical Exhibition', + 'Digital Exhibition' => 'Digital Exhibition', + 'Template select' => 'Template select', + 'Customize' => 'Customize', + 'Select the template' => 'Select the template', + 'Left title' => 'Left title', + 'Right title' => 'Right title', + 'Font primary' => 'Font primary', + 'Font secondary' => 'Font secondary', + 'Preset' => 'Preset', + 'General' => 'General', + 'Background' => 'Background', + 'Heading' => 'Heading', + 'Link' => 'Link', + 'Colors' => 'Colors', + 'Image border' => 'Image border', + 'Top bar' => 'Top bar', + 'Hover/Selected' => 'Hover/Selected', + 'Slider Home' => 'Slider Home', + 'Navigation' => 'Navigation', + 'Background Hover/Selected' => 'Background Hover/Selected', + 'Text Hover/Selected' => 'Text Hover/Selected', + 'Box' => 'Box', + 'Border' => 'Border', + 'Background Header' => 'Background Header', + 'Icon' => 'Icon', + 'Icon background' => 'Icon background', + 'Collapsible button border' => 'Collapsible button border', + 'Collapsible button background' => 'Collapsible button background', + 'Collapsible button icon' => 'Collapsible button icon', + 'Collapsible button icon hover' => 'Collapsible button icon hover', + 'Forms' => 'Forms', + 'Border required' => 'Border required', + 'Primary button' => 'Primary button', + 'Secondary button' => 'Secondary button', + 'Button text' => 'Button text', + 'Tools' => 'Tools', + 'Timeline theme' => 'Timeline theme', + 'Storyteller background' => 'Storyteller background', + 'Storyteller background items' => 'Storyteller background items', + 'Storyteller border' => 'Storyteller border', + 'Storyteller link' => 'Storyteller link', + 'Footer' => 'Footer', + 'Footer logo' => 'Footer logo', + 'Additional logo' => 'Additional logo', + 'Logo link' => 'Logo link', + 'Logo title' => 'Logo title', + 'Custom css' => 'Custom css', + 'Attachments list' => 'Attachments list', + 'Attachment' => 'Attachment', + 'Layout' => 'Layout', + 'Default' => 'Default', + 'Full page' => 'Full page', + 'Two columns' => 'Two columns', + 'Three columns' => 'Three columns', + 'Boxes' => 'Boxes', + 'Box type' => 'Box type', + 'Image with text' => 'Image with text', + 'Image with link' => 'Image with link', + 'Select dictionary' => 'Select dictionary', + /* pagetype*/ + 'DigitalExhibition' => 'DigitalExhibition', + 'Exhibition' => 'Exhibition', + 'GoogleMap' => 'GoogleMap', + 'ImageHotspot' => 'ImageHotspot', + 'Login' => 'Login', + 'LostPassword' => 'LostPassword', + 'Page' => 'Page', + 'Photogallery_category' => 'Photogallery_category', + 'Registration' => 'Registration', + 'SiteMap' => 'SiteMap', + 'Storyteller' => 'Storyteller', + 'Timeline' => 'Timeline', + 'UserDetails' => 'UserDetails', + 'Video' => 'Video', + 'Empty' => 'Empty', + 'Add news' => 'Add news', + 'movio.modules.news.views.FrontEnd' => 'News', + /*europeana*/ + 'Search mode' => 'Search mode', + 'Select images' => 'Select images', + 'All images' => 'All images', + 'Preview' => 'Preview', + 'Search results' => 'Search results', + 'Results number' => 'Results number', + 'Titles' => 'Titles', + 'Creators' => 'Creators', + 'Subjects' => 'Subjects', + 'Dates' => 'Dates', + 'Places' => 'Places', + 'Media type' => 'Media type', + 'text' => 'text', + 'image' => 'image', + 'video' => 'video', + 'sound' => 'sound', + '3D' => '3D', + 'Make a choice' => 'Make a choice', + /*Search Content*/ + 'Search contents' => 'Search contents', + 'search on europeana' =>'search on europeana', + 'search on wikipedia' =>'search on wikipedia', + 'Copy selection in' => 'Copy selection in', + /*SharingButtons*/ + 'Sharing Buttons' => 'Sharing Buttons', + 'Share on' => 'Share on', + 'Send link' => 'Send link', + 'extra small' =>'extra small', + 'small' =>'small', + 'medium' =>'medium', + 'large' =>'large', + 'Enable sharing buttons' =>'Enable sharing buttons', + 'Available buttons' =>'Available buttons', + 'Enabled buttons' =>'Enabled buttons', + 'Select dimension' =>'Select dimension', + 'Move and sort the buttons' =>'Move and sort the buttons in the right column to activate them', + 'Visit this page' => 'Visit this page', + 'I like it' => 'I like it', + /*touristoperators*/ + 'movio.modules.touristoperators.views.FrontEnd' => 'Tourist operators', + 'Content for you' => 'Content for you', + 'User Profile' => 'User Profile', + 'Address description' => 'Address description', + /*modules builder*/ + 'Creating a new module from file' => 'Creating a new module from file', + 'Creating a new module from database' => 'Creating a new module from a table already existing in the database', + 'Creating a new module' => 'Creating a new module', + 'Next' => 'Next', + 'Back' => 'Back', + 'Select the file to import' => 'Select the file to import and properties that indicate the delimiter characters contained in the CSV file.<br />The table of the database will have the same name as of the CSV file, if the table already exists the new records will be added; if the table already exists and the number of fields is different the file will not be imported.<br />', + 'Show list' => 'Show list', + // TODO: da completare + 'Testo' => 'Text', + 'Testo descrittivo (html)' => 'Descriptive text (html)', + 'Testo lungo' => 'Long text', + 'Data' => 'Date', + 'Data ora' => 'Date/Time', + 'Checkbox' => 'Checkbox', + 'Lista aperta' => 'Open Vocabulary', + 'Link esterno' => 'External link', + 'Immagine' => 'Image', + 'Immagine esterna' => 'External image', + 'Immagine ripetibile' => 'Image list', + 'Media' => 'Media', + 'Media ripetibile' => 'Media list', + 'Nascosto' => 'Hidden', + 'Add field' => 'Add field', + 'Etichetta' => 'Label', + 'Tipologia' => 'Field type', + 'Obbligatorio' => 'Mandatory', + 'Ricerca' => 'Searchable', + 'Lista ricerca' => 'In search results', + 'Lista amm.' => 'In administrative panel', + 'Modifica modulo' => 'Modify module', + 'Cancella modulo' => 'Delete module', + 'Profilo' => 'User profile', + + + + +); +org_glizy_locale_Locale::append($strings); \ No newline at end of file diff --git a/src/application/classes/movio/locale/it.php b/src/application/classes/movio/locale/it.php new file mode 100644 index 0000000..dab30a8 --- /dev/null +++ b/src/application/classes/movio/locale/it.php @@ -0,0 +1,411 @@ +<?php +$strings = array ( + 'Alert' => 'Attenzione', + 'Read' => 'Leggi', + 'Breadcrumbs path' => 'Percorso:', + 'Entity' => 'Entità', + 'Draw' => 'Disegna', + 'Relations' => 'Relazioni', + 'Subtitle' => 'Sottotitolo', + 'Entity to show' => 'Entità da visualizzare', + 'Show search form' => 'Visualizza form di ricerca', + 'Yes' => 'Si', + 'No' => 'No', + 'Text' => 'Testo', + 'Width' => 'Larghezza', + 'Height' => 'Altezza', + 'MW_FOOTER' => 'pagina creata il %s, ultima modifica %s', + 'Text to search' => 'Parola da ricercare', + 'Add content' => 'Aggiungi contenuto', + 'New content' => 'Nuovo contenuto', + 'Edit content' => 'Modifica contenuto: <em>%s</em>', + 'Show mode' => 'Visualizzazione', + 'Show links' => 'Visualizza lista', + 'Show links and description' => 'Visualizza lista e descrizione', + 'Show images' => 'Visualizza immagini', + 'Show links and images' => 'Visualizza lista e immagini', + 'Search Result' => 'Risultati della ricerca', + 'Image' => 'Immagine', + 'Title' => 'Titolo', + 'Banner' => 'Immagine icona', + 'App image' => 'Immagine app', + 'App color' => 'Colore app', + 'Presentation video' => 'Video presentazione', + 'Users' => 'Utenti', + 'URL' => 'URL', + 'Identifier' => 'Identificativo', + 'Subject' => 'Tema', + 'Physycal alternative' => 'Alternativa fisica', + 'Abstract' => 'Breve descrizione', + 'Credits' => 'Crediti', + 'Language' => 'Lingua', + 'Catalog' => 'Catalogo', + 'Patronages' => 'Patrocini', + 'Promoters' => 'Enti promotori', + 'Sponsors' => 'Sponsor', + 'Committee of Honor' => 'Comitato d\'onore', + 'Scientific Committee' => 'Comitato scientifico', + 'Dedication' => 'Dedica', + 'Aknowledgements' => 'Ringraziamenti', + 'Contacts' => 'Contatti', + 'Services' => 'Servizi associati', + 'Image galleries' => 'Selezione d\'immagini', + 'Download files' => 'Allegati', + 'Digital alternative' => 'Alternativa digitale', + 'Nation, Region, Province' => 'Nazione, Regione, Provincia', + 'Town' => 'Città', + 'Venue' => 'Sede', + 'Address' => 'Indirizzo', + 'Venue Geolocation' => 'Coordinate geografiche', + 'Duration' => 'Durata', + 'Timetable' => 'Orario', + 'Access' => 'Accesso', + 'Ticket Office' => 'Biglietteria', + 'Vernissage' => 'Inaugurazione', + 'Promoting organisations' => 'Enti promotori', + 'Promotion' => 'Promozione', + 'Press Office' => 'Ufficio stampa', + 'Exhibition project' => 'Allestimento', + 'Reviews' => 'Recensioni', + 'Add new entity' => 'Aggiungi nuova entità', + 'Name' => 'Nome', + 'Linked page' => 'Pagina collegata', + 'Exhibition url' => 'Url del sito della mostra', + 'Account link on Facebook' => 'Link account Facebook', + 'From date' => 'Data da', + 'To date' => 'Data a', + 'Email booking' => 'Email prenotazione', + 'Permanent exhibition' => 'Mostra permanente', + 'LoadingBackgroundColor' => 'Colore di sfondo in caricamento', + 'LoadingBorderColor' => 'Colore del bordo in caricamento', + 'ErrorTextColor' => 'Colore dei messaggi d\'errore', + 'disableContextMenu' => 'Disabilita menu tasto destro', + 'disableFullscreen' => 'Disabilita schermo intero', + 'attributeList' => 'Lista di attributi', + 'Key' => 'Chiave', + 'Value' => 'Valore', + 'Locations' => 'Dati di localizzazione', + 'Country' => 'Nazione', + 'District' => 'Zona', + 'Place' => 'Località', + 'Coordinates' => 'Mappa', + 'Add tourist operator' => 'Aggiungi operatore turistico', + 'Tourist Operators' => 'Operatori turistici', + 'Data saved correctly' => 'Dati salvati correttamente', + 'Link type' => 'Tipo collegamento', + 'Internal link' => 'Collegamento interno', + 'External link' => 'Collegamento esterno', + 'Link title' => 'Titolo collegamento', + 'Connect POI with a path' => 'Connettere POI con un percorso', + 'No connection' => 'Nessun percorso', + 'Line' => 'Linea', + 'Route car' => 'Percorso in auto', + 'Route transit' => 'Percorso con mezzi pubblici', + 'Route bicycling' => 'Percorso in bicicletta', + 'Route walking' => 'Percorso a piedi', + 'Markers' => 'Segnaposti', + /* publishApp */ + 'Mobile App' => 'Mobile App', + 'Publish App' => 'Pubblica App', + 'Export content' => 'Esporta contenuti', + 'Linked credit page' => 'Pagina crediti collegata', + 'Export' => 'Esporta', + 'Last exportation date' => 'Data ultima esportazione', + 'Languages' => 'Lingue', + 'Exhibition active' => 'Mostra fisica attiva', + 'Codes' => 'Codici', + /* timeline */ + 'Timeline Start date (yyyy, yyyy/mm, yyyy/mm/dd)' => 'Data inizio cronologia (aaaa, mm/aaaa, dd/mm/aaaaa)', + 'Width (default full width)' => 'Larghezza (default massima larghezza)', + 'Height (default 600px)' => 'Altezza (default 600px)', + 'Google Spreadsheet or other data source URL' => 'Google Spreadsheet o url di altra fonte dati', + 'Start at specific slide number' => 'Inizia da slide n.', + 'Timeline definition' => 'Definizione cronologia', + 'Start date (yyyy, yyyy/mm, yyyy/mm/dd)' => 'Data di inizio (aaaa, mm/aaaa, dd/mm/aaaaa)', + 'End date (yyyy, yyyy/mm, yyyy/mm/dd)' => 'Data di fine (aaaa, mm/aaaa, dd/mm/aaaaa)', + 'Headline' => 'Intestazione', + 'External Media' => 'URL di collegamento ad un media esterno', + 'Media caption' => 'Didascalia media', + /*Storyteller*/ + 'Story' => 'Storia', + 'Story item type' => 'Tipo di elemento della storia', + 'Text with media' => 'Testo con media', + 'External video' => 'Video esterno', + 'Photogallery' => 'Galleria fotografica', + 'Enable comments' => 'Abilita commenti', + 'Insights' => 'Approfondimenti', + 'Write comment' => 'Scrivi commento', + 'Full history' => 'Storia completa', + 'Audio' => 'Audio', + 'Video' => 'Video', + 'Images' => 'Immagini', + 'Texts' => 'Testi', + /* gallery */ + 'Gallery type' => 'Tipo di galleria', + 'Gallery' => 'Photogallery', + 'Slideshow' => 'Slideshow', + 'Slider' => 'Slider', + 'Page flip' => 'Sfogliatore', + 'Image crop' => 'Ritaglia immagine', + 'Image pan' => 'Scorri immagine ritagliata', + 'Images list' => 'Lista immagini', + /* Users and Groups */ + 'Users and Groups' => 'Utenti e gruppi', + 'Show user list' => 'Utenti', + 'Show group list' => 'Gruppi', + 'User group' => 'Tipo utente', + 'Company' => 'Istituzione/Azienda', + 'Job title' => 'Posizione', + 'Department' => 'Dipartimento', + 'City' => 'Città', + 'ZIP' => 'CAP', + 'Office phone' => 'Telefono ufficio', + 'Mobile phone' => 'Cellulare', + 'Home phone' => 'Telefono casa', + 'Web site' => 'Sito web', + 'Receives newsletter' => 'Riceve newsletter', + 'Registered to Mailinglist' => 'Iscritto alla mailinglist', + 'Creation date' => 'Data di realizzazione', + /* media archive */ + 'Category' => 'Categoria', + 'Author' => 'Autore', + 'Date' => 'Data', + 'Description' => 'Descrizione', + 'Show zoom' => 'Abilita zoom', + 'Downloads' => 'Numero download', + 'Text after gallery' => 'Testo dopo la galleria', + 'Final text' => 'Testo finale', + 'Margin top' => 'Margine alto', + "MW_EMPTY" => "Selezionare una voce dall'elenco", + "MW_SEARCH_RESULT" => "Risultato della ricerca", + "MW_SEARCH" => "Ricerca", + "MW_NEW_SEARCH" => "Nuova ricerca", + "MW_BACK_TO_SEARCH" => "Vai alla ricerca", + "MW_BACK" => "Torna indietro", + 'MW_SM_SITE_PROPERTIES' => 'Proprietà del sito', + 'MW_SITE_PROP' => 'Proprietà del sito', + 'MW_SITE_PROP_MODIFY' => 'Modifica proprietà del sito', + 'MW_SITE_TITLE' => 'Titolo sito', + 'MW_SITE_SUBTITLE' => 'Sottotitolo sito', + 'MW_SITE_ADDRESS' => 'Indirizzo', + 'MW_SITE_COPYRIGHT' => 'Copyright', + 'MW_SITE_LINK_FOOTER' => 'Link Nota al piede', + 'MW_SITE_SLIDESHOW_SPEED' => 'Velocità slide show (secondi)', + 'MW_NEWS' => 'News', + 'MW_NEWS_LIST_TITLE' => 'Elenco news', + 'MW_NEWS_EDIT_TITLE' => 'Modifica news', + 'MW_NEWS_LIST' => 'Risultato della ricerca', + 'MW_NEWS_STARTDATE' => 'Data inizio', + 'MW_NEWS_ENDDATE' => 'Data scadenza', + 'MW_NEWS_TITLE' => 'Titolo', + 'MW_NEWS_PLACE' => 'Luogo', + 'MW_NEWS_CATEGORY' => 'Categoria', + 'MW_NEWS_BODY' => 'Testo della notizia', + 'MW_NEWS_BODYSHORT' => 'Testo corto della notizia', + 'MW_NEWS_LABELURL' => 'Label URL correlato alla notizia', + 'MW_NEWS_URL' => 'URL correlato alla notizia', + 'MW_NEWS_IMAGE' => 'Immagine', + 'Images' => 'Immagini', + 'MW_EVENTS' => 'Eventi', + 'MW_EVENTS_LIST_TITLE' => 'Elenco eventi', + 'MW_EVENTS_EDIT_TITLE' => 'Modifica evento', + 'MW_EVENTS_DATE' => 'Data', + 'MW_EVENTS_REALDATE' => 'Data da visualizzare', + 'MW_EVENTS_LIST' => 'Elenco eventi', + 'MW_EVENTS_TITLE' => 'Titolo', + 'MW_EVENTS_YEAR' => 'Anno', + 'MW_EVENTS_PLACE' => 'Luogo', + 'MW_EVENTS_CATEGORY' => 'Categoria', + 'MW_EVENTS_PROMOTER' => 'Promotore', + 'MW_EVENTS_DESCRIPTION' => 'Descrizione', + 'MW_EVENTS_EMAIL' => 'Email', + 'MW_EVENTS_URL' => 'Indirizzo Web', + 'MW_EVENTS_IMAGE' => 'Immagine', + 'MW_EVENTS_PUBLISHED' => 'In homepage', + 'MW_EVENTS_PUBLICATION_ORDER' => 'Ordine in home', + 'MW_SUBMIT' => 'Invia', + 'MW_CANCEL' => 'Cancella', + 'MW_USER_USERNAME' => 'Nome utente', + 'MW_USER_PSW' => 'Password', + 'MW_USER_NAME' => 'Nome', + 'MW_USER_SURNAME' => 'Cognome', + 'MW_USER_COMPANY' => 'Istituzione', + 'MW_USER_TITLE' => 'Titolo', + 'MW_USER_JOBTITLE' => 'Posizione', + 'MW_USER_DEPARTMENT' => 'Dipartimento', + 'MW_USER_ADDRESS' => 'Indirizzo', + 'MW_USER_CITY' => 'Città', + 'MW_USER_STATE' => 'Provincia', + 'MW_USER_ZIP' => 'CAP', + 'MW_USER_COUNTRY' => 'Nazione', + 'MW_USER_EMAIL' => 'Email', + 'MW_USER_PHONE' => 'Telefono ufficio', + 'MW_USER_MOBILE' => 'Cellulare', + 'MW_USER_PHONE2' => 'Telefono casa', + 'MW_USER_FAX' => 'Fax', + 'MW_USER_WEB' => 'Sito web', + 'MW_USER_NEWSLETTER' => 'Riceve newsletter', + 'MW_USER_MAILINGLIST' => 'Iscritto alla mailinglist', + 'MW_USER_WANT_NEWSLETTER' => 'Desidero ricevere la newsletter', + 'MW_USER_WANT_MAILINGLIST' => 'Desidero essere iscritto alla mailinglist', + /* registration */ + 'Check following errors:' => 'Controllare i seguenti errori:', + 'MW_REGISTRATION_REQUIRED' => 'I campi in grassetto sono obbligatori', + 'MW_REGISTRATION_PRIVACY' => 'Acconsento al trattamento dei dati secondo la normativa sopra enunciata', + 'MW_REGISTRATION_CONFIRM' => 'Testo di conferma', + 'MW_REGISTRATION_PRIVACY_TEXT' => 'Testo legge privacy', + 'MW_LOSTPASSWORD_SEND' => 'Invia password', + 'MW_LOSTPASSWORD_TEXT' => 'Testo introduttivo', + 'MW_LOSTPASSWORD_CONFIRM' => 'Testo di conferma', + 'MW_LOSTPASSWORD_ERROR' => 'L\'utente specificato non è corretto', + 'MW_LOSTPASSWORD_EMAIL_SUBJECT' => 'Nuova password', + 'MW_LOSTPASSWORD_EMAIL_BODY' => '<p>L\'utente con account ##USER## ha richiesto la password per l\'accesso al sito ##HOST##.</p> <p>La sua password è: ##PASSWORD##</p>', + 'MW_LOGIN_TITLE' => 'Login', + 'MW_LOGIN_USER' => 'Email:', + 'MW_LOGIN_PSW' => 'Password:', + 'MW_LOGIN_REGISTER' => 'Registrati ora', + 'MW_LOGIN_CONFIRM' => 'Conferma', + 'MW_LOGIN_ERROR' => 'Email o password errate.', + 'MW_LOGIN_REMEMBER' => 'Ricorda login', + 'MW_LOGIN_ASK_PASSWORD' => 'Hai dimenticato la password?', + 'MW_LOGIN_REQUIRED' => 'Area protetta, accesso non consentito. Per accedere è necessario effettuare il login.', + 'MW_LOGIN_DESTINATION_PAGE' => 'Pagina di destinazione dopo il login', + 'MW_LOGOUT' => 'Logout', + 'MW_LOGIN_MYDETAILS' => 'I miei dati', + 'Ontology Builder' => 'Gestione Ontologia', + 'Labels Translations' => 'Traduzioni Etichette', + 'Entities' => 'Entità', + 'Graph' => 'Grafo', + 'Physical Exhibition' => 'Mostre fisiche', + 'Digital Exhibition' => 'Mostre digitali', + 'Template select' => 'Selezione template', + 'Customize' => 'Personalizza', + 'Select the template' => 'Seleziona il template', + 'Left title' => 'Titolo di sinistra', + 'Right title' => 'Titolo di destra', + 'Font primary' => 'Font principale', + 'Font secondary' => 'Font secondaria', + 'Preset' => 'Predefiniti', + 'General' => 'Generale', + 'Background' => 'Sfondo', + 'Heading' => 'Intestazione', + 'Link' => 'Link', + 'Colors' => 'Colori', + 'Image border' => 'Cornice immagine ', + 'Top bar' => 'Barra superiore', + 'Hover/Selected' => 'Mouse su/Selezionato ', + 'Slider Home' => 'Slider Home Page', + 'Navigation' => 'Navigazione', + 'Background Hover/Selected' => 'Sfondo Mouse su/Selezionato ', + 'Text Hover/Selected' => 'Testo Mouse su/Selezionato ', + 'Box' => 'Box', + 'Border' => 'Cornice', + 'Background Header' => 'Sfondo intestazione', + 'Icon' => 'Icona', + 'Icon background' => 'Sfondo icona ', + 'Collapsible button border' => 'Cornice del pulsante collassabile', + 'Collapsible button background' => 'Sfondo del pulsante collassabile', + 'Collapsible button icon' => 'Icona del pulsante collassabile', + 'Collapsible button icon hover' => 'Mouse su icona pulsante collassabile ', + 'Forms' => 'Forms', + 'Border required' => 'Cornice se richiesto', + 'Primary button' => 'Pulsante principale', + 'Secondary button' => 'Pulsante secondario', + 'Button text' => 'Testo del pulsante', + 'Tools' => 'Strumenti', + 'Timeline theme' => 'Tema della timeline ', + 'Storyteller background' => 'Sfondo dello Storyteller', + 'Storyteller background items' => 'Sfondo degli elementi dello Storyteller', + 'Storyteller border' => 'Cornice dello Storyteller', + 'Storyteller link' => 'Link dello Storyteller', + 'Footer' => 'Footer', + 'Footer logo' => 'Logo del footer', + 'Additional logo' => 'Logo aggiuntivo', + 'Logo link' => 'Link a cui punta il logo', + 'Logo title' => 'Titolo a cui punta il logo', + 'Custom css' => 'CSS personalizzato', + 'Attachments list' => 'Lista allegati', + 'Attachment' => 'Allegato', + 'Layout' => 'Layout', + 'Default' => 'Default', + 'Full page' => 'Pagina intera', + 'Two columns' => 'Due colonne', + 'Three columns' => 'Tre colonne', + 'Boxes' => 'Riquadri', + 'Box type' => 'Tipo di box', + 'Image with text' => 'Immagine con testo', + 'Image with link' => 'Immagine con link', + 'Select dictionary' => 'Seleziona un dizionario', + /* pagetype*/ + 'DigitalExhibition' => 'Mostra digitale', + 'Exhibition' => 'Mostra fisica', + 'GoogleMap' => 'Mappa di Google', + 'ImageHotspot' => 'Immagine con link', + 'Login' => 'Pagina di login', + 'LostPassword' => 'Richiesta password', + 'Page' => 'Pagina', + 'Photogallery_category' => 'Galleria fotografica cat.', + 'Registration' => 'Registrazione utente', + 'SiteMap' => 'Mappa del sito', + 'Storyteller' => 'Storyteller', + 'Timeline' => 'Timeline', + 'UserDetails' => 'Dati utente', + 'Video' => 'Video', + 'Empty' => 'Separatore', + 'Add news' => 'Aggiungi notizia', + 'movio.modules.news.views.FrontEnd' => 'News', + /*europeana*/ + 'Search mode' => 'Modalità di ricerca', + 'Select images' => 'Seleziona immagini', + 'All images' => 'Tutte le immagini', + 'Preview' => 'Anteprima', + 'Search results' => 'Risultati ricerca', + 'Results number' => 'Numero risultati', + 'Titles' => 'Titolo', + 'Creators' => 'Creatore', + 'Subjects' => 'Soggetto', + 'Dates' => 'Data', + 'Places' => 'Luogo', + 'Media type' => 'Media', + 'text' => 'testo', + 'image' => 'immagine', + 'video' => 'video', + 'sound' => 'audio', + '3D' => '3D', + 'Make a choice' => 'Scegli', + /*Search Content*/ + 'Search contents' => 'Ricerca contenuti', + 'search on europeana' =>'cerca su europeana', + 'search on wikipedia' =>'cerca su wikipedia', + 'Copy selection in' => 'Copia selezione in', + /*SharingButtons*/ + 'Sharing Buttons' => 'Pulsanti condivisione', + 'Share on' => 'Condividi su', + 'Send link' => 'Invia link', + 'extra small' =>'molto piccolo', + 'small' =>'piccolo', + 'medium' =>'medio', + 'large' =>'grande', + 'Enable sharing buttons' =>'Abilita pulsanti condivisione', + 'Available buttons' =>'Pulsanti disponibili', + 'Enabled buttons' =>'Pulsanti attivi', + 'Select dimension' =>'Seleziona dimensione', + 'Move and sort the buttons' =>'Spostare e ordinare i pulsanti da attivare nella colonna destra', + 'Visit this page' => 'Visita questa pagina', + 'I like it' => 'Mi piace', + /*touristoperators*/ + 'movio.modules.touristoperators.views.FrontEnd' => 'Operatori turistici', + 'Content for you' => 'Contenuti scelti per te', + 'User Profile' => 'Profilo utente', + 'Address description' => 'Descrizione indirizzo', + /*modules builder*/ + 'Creating a new module from file' => 'Creazione di un nuovo modulo da un file', + 'Creating a new module from database' => 'Creazione di un nuovo modulo da una tabella già presente nel database', + 'Creating a new module' => 'Creazione di un nuovo modulo', + 'Next' => 'Prosegui', + 'Back' => 'Indietro', + 'Select the file to import' => 'Seleziona il file da importare e le proprietà che indicano i caratteri delimitatori contenuti nel file CSV.<br />La tabella del database avrà lo stesso nome del file CSV, se la tabella è già presente i record verranno aggiunti; se la tabella è presente e il numero dei campi è differente il file non verrà importato.<br />', + 'Show list' => 'Visualizza lista', + +); +org_glizy_locale_Locale::append($strings); \ No newline at end of file diff --git a/src/application/classes/movio/modules/europeana/EuropeanaResponseVO.php b/src/application/classes/movio/modules/europeana/EuropeanaResponseVO.php new file mode 100644 index 0000000..81ed011 --- /dev/null +++ b/src/application/classes/movio/modules/europeana/EuropeanaResponseVO.php @@ -0,0 +1,7 @@ +<?php +class movio_modules_europeana_EuropeanaResponseVO +{ + public $records = array(); + public $error = ''; + public $totalResults = 0; +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/europeana/SendRequest.php b/src/application/classes/movio/modules/europeana/SendRequest.php new file mode 100644 index 0000000..69b3197 --- /dev/null +++ b/src/application/classes/movio/modules/europeana/SendRequest.php @@ -0,0 +1,55 @@ +<?php +class movio_modules_europeana_SendRequest +{ + public function execute($query, $start, $rows) + { + $europeanaResponseVO = org_glizy_objectFactory::createObject('movio.modules.europeana.EuropeanaResponseVO'); + if (__Config::get('DEBUG')) { + error_reporting(E_ERROR | E_WARNING | E_PARSE); + ini_set('display_errors', 1); + } + + $q = array(); + $keySearch = explode(',', __Config::get('movio.europeana.searchFields')); + foreach ($keySearch as $key) { + if ($query[$key]) { + $val = str_replace(' ', '+', trim($query[$key])); + if ($key == "TYPE") { + $val = strtoupper($val); + } else if($key == "LANGUAGE") { + $val = strtolower($val); + } + $q[]= $key.':"'.$val.'"'; + } + } + + $params = array( + 'wskey' => __Config::get('movio.europeana.apiKey'), + 'rows' => $rows ?: $query['maxResult'], + 'start' =>$start ?: 1, + 'query' => implode($q, ' ') + ); + + $request = org_glizy_objectFactory::createObject('org.glizy.rest.core.RestRequest', __Config::get('movio.europeana.apiSearchUrl'), 'GET', $params); + $request->execute(); + $response = $request->getResponseBody(); + $response = json_decode($response); + if ($response && $response->success && $response->itemsCount > 0) { + foreach ($response->items as $item) { + $imgSrc = $item->edmPreview[0] ? $item->edmPreview[0] : __Config::get('movio.noImage.src'); + $europeanaResponseVO->records[] = array( + 'id' => $item->id, + 'image' => $imgSrc, + 'title' => $item->title, + 'url' => $item->guid + ); + } + + $europeanaResponseVO->totalResults = $response->totalResults; + } else { + $europeanaResponseVO->error = $response->error; + } + + return $europeanaResponseVO; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/europeana/views/EuropeanaShowResults.xml b/src/application/classes/movio/modules/europeana/views/EuropeanaShowResults.xml new file mode 100644 index 0000000..27d6186 --- /dev/null +++ b/src/application/classes/movio/modules/europeana/views/EuropeanaShowResults.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> + +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:rc="movio.modules.europeana.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Popup.php"> + + <mvc:State name="index"> + <glz:Panel id="loading" cssClass="row-fluid"></glz:Panel> + <glz:Panel id="imgContainer" cssClass="row-fluid hidden"> + <rc:ShowResults id="europeana" cssClass="odd,even" skin="../../../../application/classes/movio/modules/europeana/views/skin/showresults.html"> + </rc:ShowResults> + <glz:PaginateResult id="paginate" cssClass="pagination" remember="false" pageLength="18" /> + <glz:Panel cssClass="hidden js-controlCheckEnable"> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <glz:HtmlButton label="{i18n:GLZ_CANCEL}" type="button" cssClass="btn js-glizycms-cancel" data="action=cancel" /> + </glz:Panel> + <glz:Panel cssClass="hidden js-controlCheckDisable"> + <glz:HtmlButton label="{i18n:GLZ_CLOSE}" type="button" cssClass="btn js-glizycms-cancel" data="action=cancel" /> + </glz:Panel> + </glz:Panel> + </mvc:State> + +</mvc:Page> diff --git a/src/application/classes/movio/modules/europeana/views/components/RelatedContents.php b/src/application/classes/movio/modules/europeana/views/components/RelatedContents.php new file mode 100644 index 0000000..308d8b7 --- /dev/null +++ b/src/application/classes/movio/modules/europeana/views/components/RelatedContents.php @@ -0,0 +1,67 @@ +<?php + +class movio_modules_europeana_views_components_RelatedContents extends org_glizy_components_ComponentContainer +{ + + public function process() + { + $this->_content = $this->_parent->loadContent($this->getId()); + $query = (array)json_decode($this->_content); + + $this->_content = array( + 'id' => $this->getId(), + 'label' => $this->getAttribute('label'), + 'ajax' => false, + 'ajaxUrl' => GLZ_HOST.'/'.$this->getAjaxUrl().'show&document_id='.__Request::get('document_id'), + + ); + + $this->setAttribute('visible', $query['visible']); + } + + + public function process_ajax() + { + $this->_content = $this->_parent->loadContent($this->getId()); + $query = (array)json_decode($this->_content); + + $this->_content = array( + 'id' => $this->getId(), + 'records' => array(), + 'error' => null, + 'label' => $this->getAttribute('label'), + 'ajax' => true + ); + + if ($query['imgCheckBox'] === "checkBoxEnable" && count($query['savedImage'])) { + $this->loadSelectedImage($query); + } else { + $request = org_glizy_ObjectFactory::createObject('movio.modules.europeana.SendRequest'); + $response = $request->execute($query, null, null); + if (!$response->error) { + $this->_content['records'] = $response->records; + } else { + $this->_content['error'] = $response->error; + } + } + + $template = org_glizy_ObjectFactory::createObject('org.glizy.template.skin.PHPTAL', 'EuropeanaRelatedContents.html'); + $template->set('Component', $this->_content); + $html = $template->execute(); + return array('status' => true, 'content' => $html); + } + + private function loadSelectedImage($query) + { + foreach ($query['savedImage'] as $item) { + $imgSrc = $item->edmPreview[0] ? $item->edmPreview[0] : __Config::get('movio.noImage.src'); + $this->_content['records'][] = array( + 'id' => $item->id, + 'image' => $item->src, + 'title' => $item->title, + 'url' => $item->href + ); + } + } + +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/europeana/views/components/ShowResults.php b/src/application/classes/movio/modules/europeana/views/components/ShowResults.php new file mode 100644 index 0000000..70af242 --- /dev/null +++ b/src/application/classes/movio/modules/europeana/views/components/ShowResults.php @@ -0,0 +1,49 @@ +<?php +class movio_modules_europeana_views_components_ShowResults extends org_glizy_components_Component +{ + function process() + { + $params = __Request::get('params'); + $query = json_decode($params, true); + + $paginateClass = $this->getComponentById( 'paginate' ); + $paginateClass->setRecordsCount(); + $limits = $paginateClass->getLimits(); + $start = $limits['start']+1; + $checkBoxEnable = $query['imgCheckBox'] === "checkBoxEnable"; + $rows = 18; + $diff = 0; + if ($query['maxResult'] && !$checkBoxEnable && ($start + $rows > $query['maxResult'])) { + $rows = $query['maxResult'] - $start+1; + $diff = 18 - $rows; + } + $this->_content = array( + 'id' => $this->getId(), + 'records' => array(), + 'error' => null, + 'params' => $params, + 'rows' => $rows, + 'currentOffset' => $limits['start'] + ); + + $request = org_glizy_ObjectFactory::createObject('movio.modules.europeana.SendRequest'); + $response = $request->execute($query, $start, $rows); + if (!$response->error) { + $this->_content['records'] = $response->records; + if ($checkBoxEnable) { + $this->_content['imgCheckBox'] = true; + $total = $response->totalResults; + } else { + $this->_content['imgCheckBox'] = false; + $total = $response->totalResults ? $query['maxResult'] : 0; + } + + } else { + $this->_content['error'] = $response->error; + } + + $this->_content['imgList'] = $query['imgList'] ? $query['imgList'] : array(); + $paginateClass->setRecordsCount($total -$diff, $rows); + } + +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/europeana/views/js/FormEditEuropeanaRelatedContents.js b/src/application/classes/movio/modules/europeana/views/js/FormEditEuropeanaRelatedContents.js new file mode 100644 index 0000000..0d1f9a7 --- /dev/null +++ b/src/application/classes/movio/modules/europeana/views/js/FormEditEuropeanaRelatedContents.js @@ -0,0 +1,436 @@ +jQuery.GlizyRegisterType('europeanaRelatedContents', { + + __construct: function () { + var self = $(this).data('formEdit'); + self.val = $(this).val(); + var id = $(this).attr('id'); + var searchFields = $(this).data('search_fields').split(','); + var searchFieldsLabels = $(this).data('search_fields_labels').split(','); + var checkList = []; + var params = {}; + var templateData = {}; + var arrParams = []; + var savedImage = []; + var searchMode = ''; + var defaultMaxResult = $(this).data('max_result'); + var isResult = true; + var totalImage = true; + self.element = $(this); + glizyOpt = $(this).data('glizyOpt'); + preview = $("#preview").val(); + + + var language = { 'it' : 'Italiano', + 'de' : 'Deutsch', + 'mul' : 'Multilingue', + 'es' : 'Español', + 'nl' : 'Nederlands', + 'en' : 'English', + 'fr' : 'Français', + 'ro' : 'Română', + 'pl' : 'Polski', + 'lv' : 'LatvieÅ¡u', + 'pt' : 'Português', + 'cs' : 'ÄŒeÅ¡tina', + 'sv' : 'Svenska', + 'hu' : 'Magyar', + 'nb' : 'Norsk', + 'ca' : 'Català', + 'lt' : 'Lietuvių', + 'da' : 'Dansk', + 'bg' : 'БългарÑки', + 'fi' : 'Suomi', + 'et' : 'Eesti', + 'sl' : 'SlovenÅ¡Äina', + 'sk' : 'Slovenský', + 'srp' : 'Serbian', + 'el' : 'Ελληνικά', + 'swe' : 'Swedish', + 'ru' : 'РуÑÑкий', + 'hr' : 'Hrvatski', + 'tr' : 'Turkish' }; + + var mediaType = { 'TEXT' : '{i18n:text}', + 'IMAGE' : '{i18n:image}', + 'VIDEO' : '{i18n:video}', + 'SOUND' : '{i18n:sound}', + '3D' : '{i18n:3D}' }; + + var templateImageList = '<div id="imgList" class="row_fluid span10 europeana-group">' + + '<ul id="sortable" class="thumbnails">'+ + '<% _.each( rc.savedImage, function(image) { %>' + + '<li>' + + '<div class="thumbnail">' + + '<div class="js-imageRemove" >' + + '<i id="<%- image.id %>" class="icon-remove icon-white pull-right"></i>' + + '</div>' + + '<div class="imgPreview">' + + '<div>' + + '<a title="<%- image.title %>" href="<%- image.href %>" target="_blank">' + + '<img title="<%- image.title %>" src="<%- image.src %>">' + + '</a>' + + '</div>' + + '<div>' + + '<span><%- image.title.length >= 30 ? image.title.substring(0, 30) + \'...\' : image.title %></span>' + + '</div>' + + '</div>' + + '</div>'+ + '</li>' + + '<% });%>' + + '</ul>' + + '</div>'; + + var htmlTemplate = + '<div class="row-fluid span10 europeana-group firstDiv" >' + + '<div class="span4">'+ + '<div class="span6">' + + '<label for="searchMode">' + + '{i18n:Search mode}' + + '</label>' + + '<select id="searchMode">' + + '<option value="checkBoxEnable">{i18n:Select images}</option>' + + '<option value="checkBoxDisable">{i18n:All images}</option>' + + '</select>' + + '</div>' + + '<div class="span6 maxResDiv" id="maxImgResultDiv">' + + '<label for="maxImgResult">' + + '{i18n:Results number}' + + '</label>' + + '<input id="maxImgResult" type="number" value="<%- rc.maxResult %>" min="1" max="100"/>' + + '</div>' + + '</div>' + + '<% var i = 2; %>' + + '<% _.each( rc.fields, function(field ){ '+ + 'var spanX = (i==2) ? "span8" : "span4";' + + 'if(i%3 == 0) {%>' + + '</div>' + + '<div class="row-fluid span10 europeana-group" >' + + '<%}%>' + + '<div class="row-fluid <%- spanX %>">' + + '<label for = "<%- rc.id %>_input_<%- field.id %>" >' + + '<%- field.label %>' + + '</label>' + + '<% if(field.id === "TYPE" || field.id === "LANGUAGE") {%>' + + '<select id="<%- rc.id %>_input_<%- field.id %>">' + + '<option value="">{i18n:Make a choice} ...</option>' + + '<% var arrayOption = field.id === "TYPE" ? rc.TYPE : rc.LANGUAGE;%>' + + '<% _.each( arrayOption, function(option, key) { '+ + 'var selected = field.precompiled === key ? \'selected="selected"\' : ""; %>' + + '<option value="<%- key %>" <%- selected %>><%- option %></option>' + + '<%});%>' + + '</select>' + + '<%} else {%>' + + '<input <% if(i==2){%> class="titleInput" <%}%> type="text" id = "<%- rc.id %>_input_<%- field.id %>" value="<%- field.precompiled %>"/>' + + '<%}%>' + + '</div>' + + '<% i++;});%>' + + '</div>' + + '<div class="row-fluid span10 europeana-group div-btn">' + + '<div class="pull-right">' + + '<input id="<%- rc.id %>_previewButton" type="button" class="btn" value="{i18n:Preview}">' + + '</div>' + + '</div>' + + templateImageList; + + + self.init = function() + { + $("label[for="+ id + "]").css('cursor', 'default'); + self.element.parent().hide(); + if (self.val) { + var values = $.parseJSON(self.val); + $.each(values, function(key, value) { + arrParams[key] = value; + }); + } + + var fields = []; + $(searchFields).each(function (i, searchField) { + var obj = { + id: searchField, + label: searchFieldsLabels[i], + precompiled : arrParams[searchField] + }; + fields.push(obj); + }); + + self.initImageParams(); + + searchMode = arrParams['imgCheckBox']; + var maxResult = $.isNumeric(arrParams['maxResult']) ? arrParams['maxResult'] : defaultMaxResult; + + templateData = { 'id' : id, + 'fields': fields, + 'imgList': checkList, + 'savedImage' : savedImage, + 'maxResult' : maxResult, + 'TYPE' : mediaType, + 'LANGUAGE' : language + }; + + self.render(self.element.parent(), templateData, htmlTemplate, true); + self.setSearchMode(); + self.activatePreview( self.checkFormIsFilled()); + + $('#'+id+'_previewButton').on('click', function() { + parms = self.insertSearchParam(self.element); + self.sendRequest( parms ); + }); + + $('#searchMode').on('change', function() { + searchMode = $( "#searchMode option:selected" ).val(); + self.setSearchMode() + }); + + $(document).on('click', '.js-imageRemove', function() { + imgId = $(this).find('i').attr('id'); + self.removeImageFromSavedList(imgId); + self.saveImageList(); + }); + + $('#maxImgResult').on('focus', function(e) { + defaultMaxResult = $(this).val(); + }); + + $('#maxImgResult').on('change', function(e){ + value = $(this).val(); + if(value == parseInt(value)) { + if( value < 1 || value > 100) { + $(this).val() < 1 ? $(this).val(1) : $(this).val(100); + } + } else { + $(this).val(defaultMaxResult); + } + }); + + $('[id^=' + id + '_input_]').on('keyup change', function(e){ + if($(this).val()){ + self.activatePreview(true); + } else { + self.activatePreview( self.checkFormIsFilled()); + } + }); + + } + + self.checkFormIsFilled = function() { + var filled = false; + $('[id^=' + id + '_input_]').each(function() { + if($(this).val()) { + filled = true; + return false; + } + }); + return filled; + } + + self.activatePreview = function(val){ + if (!val) { + $('#'+id+'_previewButton').attr("disabled", "disabled"); + } else { + $('#'+id+'_previewButton').removeAttr("disabled"); + } + } + + self.setSearchMode = function() + { + $("#searchMode").val(searchMode); + if(searchMode == "checkBoxDisable" ){ + $("#maxImgResultDiv").show(); + $("#imgList").hide(); + }else{ + $("#maxImgResultDiv").hide(); + $("#imgList").show(); + } + + } + + self.render = function(targetTag, templateData, html, append) { + _.templateSettings.variable = "rc"; + var template = _.template( html ); + var rendered = template( templateData ) + if(append){ + $(targetTag).after( rendered ); + } + else{ + $(targetTag).replaceWith( rendered ); + } + $( "#sortable" ).sortable({ + cursor: "move", + containment: "parent", + update: function( event, ui ) { + self.reorderSavedImage(); + } + }); + + $( "#sortable" ).disableSelection(); + } + + self.sendRequest = function(data) { + var url = glizyOpt.mediaPicker.replace(/MediaArchive_picker/i, 'EuropeanaShowResults'); + url += '&params=' + encodeURIComponent(data); + title = "{i18n:Search results}"; + Glizy.closeIFrameDialog(true); + Glizy.openIFrameDialog( title, + url, + 900, + 50, + 50, + self.openDialogCallback + ); + } + + self.insertSearchParam = function() { + $(searchFields).each(function (i, searchField) { + var value = $("#" + id +"_input_" + searchField).val() + params[searchField] = value || ''; + }); + + params['imgCheckBox'] = $( "#searchMode option:selected" ).val(); + params['imgList'] = arrParams['imgList']; + params['savedImage'] = arrParams['savedImage']; + params['maxResult'] = $("#maxImgResult").val(); + params['visible'] = self.checkIsResult(); + return JSON.stringify(params); + } + + self.initImageParams = function() { + if(arrParams['imgList']){ + checkList = arrParams['imgList'].slice(); + } + + if(arrParams['savedImage']){ + savedImage = arrParams['savedImage'].slice(); + } + + } + + self.checkIsResult = function() { + if(searchMode == 'checkBoxDisable' && !self.checkFormIsFilled()){ + return false; + } else if(searchMode == 'checkBoxEnable' && !checkList.length) { + return false; + } else if (searchMode == 'checkBoxDisable' && !totalImage ) { + return false; + } + else { + return true; + } + + } + + self.removeImageFromSavedList = function(id) + { + checkList.splice( $.inArray(id, checkList), 1 ); + savedImage = $.grep(savedImage, function(e) { return e.id!=id }); + } + + self.saveImageList = function() { + arrParams['imgList'] = checkList.slice(); + arrParams['savedImage'] = savedImage.slice(); + templateData.savedImage = savedImage; + self.render($("#imgList"), templateData, templateImageList); + } + + self.reorderSavedImage = function(){ + var tmpSavedImage = []; + $("#sortable li").each(function(i, el){ + var imgId = $(el).find('i').attr('id'); + var curImage = $.grep(savedImage, function(e) { return e.id==imgId }); + if($.inArray(curImage[0], tmpSavedImage) == -1 && curImage.length > 0){ + tmpSavedImage.push(curImage[0]); + } + }); + savedImage = tmpSavedImage.slice(); + arrParams['savedImage'] = savedImage.slice(); + } + + self.escapeId = function( idToEscape ) { + return "#" + idToEscape.replace( /(:|\.|\[|\]|\/)/g, "\\$1" ); + } + + self.checkImage = function($frameDocument) { + $.each(checkList, function (index, id) { + $(self.escapeId(id), $frameDocument).prop('checked', true); + }); + } + + self.openDialogCallback = function() { + var $frame = jQuery(this).children(); + + $frame.on("load", function () { + var $frameDocument = $($frame.contents().get(0)); + totalImage = $("img", $frameDocument).length + if( searchMode =='checkBoxEnable') + { + $(".js-controlCheckEnable", $frameDocument).removeClass('hidden'); + self.checkImage($frameDocument); + } else{ + $(".js-controlCheckDisable", $frameDocument).removeClass('hidden'); + } + $("#imgContainer", $frameDocument).removeClass('hidden'); + $("#loading", $frameDocument).addClass('hidden'); + + $frameDocument.on('keyup', function(e) { + var charCode = e.charCode || e.keyCode || e.which; + if (charCode == 27){ + checkList = []; + Glizy.closeIFrameDialog(true); + self.initImageParams(); + } + }); + + $(".js-glizycms-cancel", $frameDocument).on('click', function(e){ + checkList = []; + Glizy.closeIFrameDialog(true); + self.initImageParams(); + }); + + $(".js-glizycms-save", $frameDocument).on('click', function(e){ + self.saveImageList(); + Glizy.closeIFrameDialog(true); + self.initImageParams(); + }); + + $(".js-check", $frameDocument).on('click', function(e){ + var id = $(this).attr('id'); + if($(this).attr('checked')){ + var target = $(this).parent().parent().find('div').find('a'); + var href = target.attr('href'); + var src = target.find('img').attr('src'); + var title =target.attr('title'); + var image = { 'id' : id, + 'title': title, + 'href': href, + 'src' : src + }; + savedImage.push(image); + checkList.push(id); + }else{ + self.removeImageFromSavedList(id); + } + + }); + + }); + } + + self.init(); + + }, + + getValue: function () { + var self = $(this).data('formEdit'); + var val = self.insertSearchParam(); + $(this).val(val); + return val; + }, + + setValue: function (value) { + $(this).val(value); + }, + + destroy: function (field) { + } + +}); diff --git a/src/application/classes/movio/modules/europeana/views/skin/showresults.html b/src/application/classes/movio/modules/europeana/views/skin/showresults.html new file mode 100644 index 0000000..fc95f46 --- /dev/null +++ b/src/application/classes/movio/modules/europeana/views/skin/showresults.html @@ -0,0 +1,25 @@ +<span tal:omit-tag="" tal:condition="php: !Component['error']" > + <input type="hidden" id="keySearch" tal:attributes="value Component/params" /> + <div class="row_fluid" tal:attributes="id php: 'img-' . Component['id']"> + <ul class="thumbnails" > + <li class="span2 thumbnail" tal:repeat="item Component/records" > + <div style="height:190px;"> + <div> + <a target="_blank" tal:attributes="href item/url; title item/title"> + <img tal:attributes="src item/image; title item/title" style="height:130px;"/> + </a> + </div> + <div> + <span tal:omit-tag="" tal:condition="php: Component['imgCheckBox']" > + <input type="checkbox" tal:attributes="class string:js-check; name item/id; value item/title; id item/id" /> + </span> + <span tal:content="php: strlen(item['title'][0]) >= 30 ? substr(item['title'][0],0, 30) . '...' : item['title']" /> + </div> + </div> + </li> + </ul> + </div> +</span> +<span tal:omit-tag="" tal:condition="php: Component['error']" class="wrapper-box-summary no-padding clearfix"> + <h1 tal:content="structure Component/error" /> +</span> diff --git a/src/application/classes/movio/modules/news/Module.php b/src/application/classes/movio/modules/news/Module.php new file mode 100644 index 0000000..728f176 --- /dev/null +++ b/src/application/classes/movio/modules/news/Module.php @@ -0,0 +1,21 @@ +<?php +class movio_modules_news_Module +{ + static function registerModule() + { + $moduleVO = org_glizy_Modules::getModuleVO(); + $moduleVO->id = 'movio_news'; + $moduleVO->name = __T('News'); + $moduleVO->description = ''; + $moduleVO->version = '1.0.0'; + $moduleVO->classPath = 'movio.modules.news'; + $moduleVO->pageType = 'movio.modules.news.views.FrontEnd'; + $moduleVO->author = 'META srl'; + $moduleVO->authorUrl = 'http://www.gruppometa.it'; + $moduleVO->pluginUrl = 'http://movio.beniculturali.it'; + $moduleVO->siteMapAdmin = '<glz:Page pageType="movio.modules.news.views.Admin" id="movio_news" value="{i18n:News}" icon="icon-circle-blank" />'; + $moduleVO->showInOntologyBuilder = true; + + org_glizy_Modules::addModule( $moduleVO ); + } +} diff --git a/src/application/classes/movio/modules/news/UrlResolver.php b/src/application/classes/movio/modules/news/UrlResolver.php new file mode 100644 index 0000000..947fe2d --- /dev/null +++ b/src/application/classes/movio/modules/news/UrlResolver.php @@ -0,0 +1,18 @@ +<?php +class movio_modules_news_UrlResolver extends org_glizycms_speakingUrl_AbstractDocumentResolver implements org_glizycms_speakingUrl_IUrlResolver +{ + public function __construct() + { + parent::__construct(); + $this->type = 'movio.modules.news'; + $this->protocol = 'movioNews:'; + $this->model = 'movio.modules.news.models.Model'; + $this->pageType = 'movio.modules.news.views.FrontEnd'; + $this->modelName = __T('movio.modules.news.views.FrontEnd'); + } + + public function compileRouting($ar) + { + return ''; + } +} diff --git a/src/application/classes/movio/modules/news/config/routing.xml b/src/application/classes/movio/modules/news/config/routing.xml new file mode 100644 index 0000000..e66583c --- /dev/null +++ b/src/application/classes/movio/modules/news/config/routing.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Routing> + <glz:Route name="movio_news" value="{pageId=movio.modules.news.views.FrontEnd}/{static=action=show}/{integer=document_id}/{value=title}" /> +</glz:Routing> \ No newline at end of file diff --git a/src/application/classes/movio/modules/news/models/Model.xml b/src/application/classes/movio/modules/news/models/Model.xml new file mode 100644 index 0000000..e3ee102 --- /dev/null +++ b/src/application/classes/movio/modules/news/models/Model.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="movio.modules.news" model:usePrefix="true" model:type="document"> + + + <model:Define> + <!-- system --> + <model:Field name="title" type="string" length="255" index="true" /> + <model:Field name="fulltext" type="string" index="fulltext" /> + + <!-- custom --> + <model:Field name="startDate" type="date" validator="date,notnull" index="true" /> + <model:Field name="endDate" type="date" validator="date,notnull" index="true" /> + <model:Field name="category" type="string" length="255" index="true" /> + <model:Field name="dateDescription" type="string" /> + <model:Field name="place" type="string" length="255" index="true" /> + <model:Field name="bodyShort" type="text" /> + <model:Field name="body" type="text" /> + <model:Field name="contacts" type="text" /> + <model:Field name="urlLabel" type="string" /> + <model:Field name="urlExternal" type="string" /> + <model:Field name="images" type="object" readFormat="false" /> + <model:Field name="attaches" type="object" readFormat="false" /> + + <model:Field name="year" type="int" onlyIndex="true" /> + <model:Field name="body,bodyShort" type="string" index="fulltext" onlyIndex="true" /> + </model:Define> + + <model:Script parent="model"> + <![CDATA[ + public function save($values=NULL, $forceNew=false, $status='DRAFT') { + $this->createAddictionalIndex(); + return parent::save($values, $forceNew, $status); + } + + public function publish($values = null, $comment='', $forceNew=false) { + $this->createAddictionalIndex(); + return parent::publish($values, $comment, $forceNew); + } + + private function createAddictionalIndex() + { + $startDate = $this->getFieldValueByRegexp('_startDate', true); + if ($startDate) { + $this->year = substr($startDate, 0, strpos($startDate, '-')); + } + + $k = 'body,bodyShort'; + $this->$k = $this->body.$this->bodyShort; + } + ]]> + </model:Script> + + <model:Query name="filterYear" type="function"> + <![CDATA[ + $iterator->selectIndex('year', 'DISTINCT document_index_int_value as k', 'document_index_int_value as v') + ->orderBy('year'); + ]]> + </model:Query> + +</model:Model> \ No newline at end of file diff --git a/src/application/classes/movio/modules/news/views/Admin.xml b/src/application/classes/movio/modules/news/views/Admin.xml new file mode 100644 index 0000000..93f5f1d --- /dev/null +++ b/src/application/classes/movio/modules/news/views/Admin.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:include + xmlns:cms="org.glizycms.views.components.*" + src="movio.views.TemplateModuleAdmin"> + <glz:template name="model" value="movio.modules.news.models.Model" /> + <glz:template name="add_label" value="Add news" /> + + <glz:template name="grid_fields"> + <glz:DataGridColumn columnName="title" headerText="{i18n:Title}" renderCell="org.glizycms.contents.views.renderer.DocumentTitle" /> + <glz:DataGridColumn columnName="place" headerText="{i18n:MW_NEWS_PLACE}" searchable="true" /> + <glz:DataGridColumn columnName="startDate" headerText="{i18n:MW_NEWS_STARTDATE}" searchable="true" /> + <glz:DataGridColumn columnName="endDate" headerText="{i18n:MW_NEWS_ENDDATE}" searchable="true"/> + <!-- + <glz:DataGridColumn columnName="inHome" headerText="{i18n:MW_EVENTS_PUBLISHED}" searchable="false" renderCell="org.glizycms.core.application.renderer.CellUserActive" /> + <glz:DataGridColumn columnName="inHomeOrder" headerText="{i18n:MW_EVENTS_PUBLICATION_ORDER}" sortable="false" searchable="false" /> + --> + </glz:template> + + <glz:template name="form_fields"> + <glz:Input id="title" label="{i18n:Title}" size="90" required="true" /> + <!--glz:Input id="url" label="{i18n:Url}" size="90" required="false" /--> + <glz:Input id="startDate" label="{i18n:MW_NEWS_STARTDATE}" size="40" required="true" data="type=date" /> + <glz:Input id="endDate" label="{i18n:MW_NEWS_ENDDATE}" size="40" required="true" data="type=date" /> + <!-- + <glz:Checkbox id="inHome" label="{i18n:MW_EVENTS_PUBLISHED}" data="type=checkbox" /> + <glz:Input id="inHomeOrder" label="{i18n:MW_EVENTS_PUBLICATION_ORDER}" size="10" /> + --> + <glz:Input id="category" label="{i18n:Category}" data="type=selectfrom;multiple=true;add_new_values=true;model=movio.modules.news.models.Model;query=All" size="255" /> + <glz:Input id="dateDescription" label="{i18n:MW_EVENTS_REALDATE}" size="90" /> + <glz:Input id="place" label="{i18n:MW_EVENTS_PLACE}" data="type=selectfrom;multiple=false;add_new_values=true;model=movio.modules.news.models.Model" size="255" /> + <glz:Input id="bodyShort" label="{i18n:MW_NEWS_BODYSHORT}" size="90" type="multiline" rows="10" cols="70" htmlEditor="true" data="type=tinymce" /> + <glz:Input id="body" label="{i18n:Text}" size="90" type="multiline" rows="10" cols="70" htmlEditor="true" data="type=tinymce" /> + <glz:Input id="contacts" label="{i18n:Contacts}" size="90" type="multiline" rows="10" cols="70" htmlEditor="true" data="type=tinymce" /> + <glz:Input id="urlLabel" label="{i18n:Label URL}" size="90" /> + <glz:Input id="urlExternal" label="{i18n:URL}" size="90" /> + + <glz:Fieldset id="images" label="{i18n:Images}" data="type=repeat;repeatMin=0;repeatMax=5;collapsable=false"> + <glz:Input id="image" label="{i18n:Image}" size="90" data="type=mediapicker;mediatype=IMAGE;preview=true"/> + </glz:Fieldset> + + <glz:Fieldset id="attaches" label="{i18n:Download files}" data="type=repeat;repeatMin=0;repeatMax=5;collapsable=false"> + <glz:Input id="media" label="{i18n:Media}" size="90" data="type=mediapicker;mediatype=ALL;preview=false"/> + </glz:Fieldset> + </glz:template> +</glz:include> \ No newline at end of file diff --git a/src/application/classes/movio/modules/news/views/FrontEnd.xml b/src/application/classes/movio/modules/news/views/FrontEnd.xml new file mode 100644 index 0000000..b1c3ef0 --- /dev/null +++ b/src/application/classes/movio/modules/news/views/FrontEnd.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="2cols.php" + adm:editComponents="filters,text"> + + <glz:Import src="Common.xml" /> + + <glz:DataProvider id="ModuleDP" recordClassName="movio.modules.news.models.Model"/> + + <mvc:State name="index"> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + <cms:SearchFilters id="filters" cssClass="search my-form clearfix" label="{i18n:Show search form}"> + <glz:DataDictionary id="filterYearDP" recordClassName="movio.modules.news.models.Model" field="year" query="filterYear" /> + <glz:DataDictionary id="filterPlaceDP" recordClassName="movio.modules.news.models.Model" field="place" /> + <glz:DataDictionary id="filterCategoryDP" recordClassName="movio.modules.news.models.Model" field="category" /> + <glz:Input id="filterTitle" label="{i18n:MW_NEWS_TITLE}" bindTo="title" value="{filters}"/> + + <glz:List id="filterYear" label="{i18n:MW_EVENTS_YEAR}" bindTo="year" value="{filters}" dataProvider="{filterYearDP}" emptyValue="-" /> + <glz:List id="filterPlace" label="{i18n:MW_NEWS_PLACE}" bindTo="place" value="{filters}" dataProvider="{filterPlaceDP}" emptyValue="-" /> + <glz:List id="filterCategory" label="{i18n:MW_NEWS_CATEGORY}" bindTo="category" value="{filters}" dataProvider="{filterCategoryDP}" emptyValue="-" /> + <glz:Panel cssClass="control-group"> + <glz:HtmlButton label="{i18n:GLZ_SEARCH}" value="SEARCH" target="{filters}" /> + <glz:HtmlButton label="{i18n:GLZ_RESET}" value="RESET" target="{filters}" cssClass="reset" /> + </glz:Panel> + </cms:SearchFilters> + <glz:RecordSetList id="list" dataProvider="{ModuleDP}" routeUrl="movio_news" title="{i18n:Search Result}" filters="{filters}" paginate="{paginate}" removeTitleWithNoFilter="true" skin="News_list.html"> + <glz:Repeater id="images"> + <glz:Image id="image" width="{config:IMG_LIST_WIDTH}" height="{config:IMG_LIST_HEIGHT}" /> + </glz:Repeater> + </glz:RecordSetList> + <glz:PaginateResult id="paginate" cssClass="pagination" /> + </mvc:State> + + <mvc:State name="show"> + <glz:RecordDetail id="entry" dataProvider="{ModuleDP}" idName="document_id" skin="News_entry.html"> + <glz:Repeater id="images"> + <glz:Script extendParent="true"><![CDATA[ +function loadContent($id, $bindTo="") { + if ($this->contentCount>0) { + $c = $this->getComponentById($this->getId()."-image"); + $c->setAttributes(array("width" => __Config::get("THUMB_WIDTH"), + "height" => __Config::get("THUMB_HEIGHT"))); + } + return parent::loadContent($id, $bindTo); +}]]></glz:Script> + <glz:Image id="image" width="{config:IMG_WIDTH}" height="{config:IMG_HEIGHT}" zoom="true" group="slideshow" superZoom="true" /> + </glz:Repeater> + <glz:Repeater id="attaches"> + <glz:Media id="media" /> + </glz:Repeater> + </glz:RecordDetail> + </mvc:State> +</mvc:Page> \ No newline at end of file diff --git a/src/application/classes/movio/modules/sharingButtons/controllers/ajax/Save.php b/src/application/classes/movio/modules/sharingButtons/controllers/ajax/Save.php new file mode 100644 index 0000000..688f33f --- /dev/null +++ b/src/application/classes/movio/modules/sharingButtons/controllers/ajax/Save.php @@ -0,0 +1,14 @@ +<?php +class movio_modules_sharingButtons_controllers_ajax_Save extends org_glizycms_contents_controllers_activeRecordEdit_ajax_SaveClose +{ + + public function execute($data) + { + $data = json_decode($data); + $shareButtons['enable'] = $data ->sharingButtonCheck; + $shareButtons['dim'] = $data ->shareButtonDim; + $shareButtons['buttonList'] = $data->enabledButton; + movio_modules_sharingButtons_views_SharingButton::setSharingButtonList($shareButtons); + return true; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/sharingButtons/js/main.js b/src/application/classes/movio/modules/sharingButtons/js/main.js new file mode 100644 index 0000000..02443df --- /dev/null +++ b/src/application/classes/movio/modules/sharingButtons/js/main.js @@ -0,0 +1,36 @@ +GlizyApp.pages[ 'movio.modules.sharingButtons.views.Admin' ] = function( state, routing ) { + $(function(){ + if ('index'==state) { + var setList = function(){ + $("#enabledButton").val(''); + $('ul.js-sharingEnabled li').each(function(i) + { + if(!$('#enabledButton').val()){ + $("#enabledButton").val($(this).text()); + }else{ + $("#enabledButton").val($("#enabledButton").val() + "," + $(this).text()); + } + }); + } + + $( "ul.js-sharingDisabled" ).sortable({ + connectWith: "ul" + }); + + $( "ul.js-sharingEnabled" ).sortable({ + connectWith: "ul" + }); + + $( "ul.js-sharingDisabled, ul.js-sharingEnabled" ).disableSelection(); + + $("#shareButtonDim").blur(); + + setList(); + + $( "ul.js-sharingEnabled" ).on( "sortchange sortupdate", function( event, ui ) { + setList(); + }); + } + }); +} + diff --git a/src/application/classes/movio/modules/sharingButtons/views/Admin.xml b/src/application/classes/movio/modules/sharingButtons/views/Admin.xml new file mode 100644 index 0000000..32458b7 --- /dev/null +++ b/src/application/classes/movio/modules/sharingButtons/views/Admin.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + xmlns:cmp="movio.modules.sharingButtons.views.components.*" + controllerName="movio.modules.sharingButtons.controllers.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Page.php"> + + <glz:Import src="_common.xml" /> + + <mvc:State name="index"> + <glz:JSscript folder="movio.modules.sharingButtons.js" editableRegion="head" /> + <cms:FormEdit id="shareButtonForm" controllerName="movio.modules.sharingButtons.controllers.*"> + <cmp:GetSharingButtons id="share" /> + <glz:Input id="enabledButton" type="hidden"/> + <cms:FormButtonsPanel> + <glz:HtmlButton id="shareButton" label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + +</mvc:Page> \ No newline at end of file diff --git a/src/application/classes/movio/modules/sharingButtons/views/SharingButton.php b/src/application/classes/movio/modules/sharingButtons/views/SharingButton.php new file mode 100644 index 0000000..d0e6841 --- /dev/null +++ b/src/application/classes/movio/modules/sharingButtons/views/SharingButton.php @@ -0,0 +1,16 @@ +<?php +class movio_modules_sharingButtons_views_SharingButton +{ + CONST REGISTRY_SHAREBUTTONS = '/shareButtons'; + + public static function getSharingButtonList() + { + return unserialize(org_glizy_Registry::get(__Config::get('BASE_REGISTRY_PATH').self::REGISTRY_SHAREBUTTONS, '')); + } + + public static function setSharingButtonList($shareButtons) + { + org_glizy_Registry::set(__Config::get('BASE_REGISTRY_PATH').self::REGISTRY_SHAREBUTTONS, serialize($shareButtons)); + } + +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/sharingButtons/views/components/GetSharingButtons.php b/src/application/classes/movio/modules/sharingButtons/views/components/GetSharingButtons.php new file mode 100644 index 0000000..3532cd2 --- /dev/null +++ b/src/application/classes/movio/modules/sharingButtons/views/components/GetSharingButtons.php @@ -0,0 +1,113 @@ +<?php +class movio_modules_sharingButtons_views_components_GetSharingButtons extends org_glizy_components_Component +{ + private $buttonListBase = array(); + private $dimList = array(); + private $shareButtons = ''; + private $enabledButtons = array(); + private $selectedDim = ''; + private $enableCheck = ''; + + function init() + { + parent::init(); + /* Togliere elemento dall' array per disabilitare nel back-end*/ + $this->buttonListBase = array("Twitter", + "Linkedin", + "Facebook", + "Google-plus", + "E-mail", + "Facebook-like", + /*"Google+1", + "Pinterest"*/); + + $this->dimList = array( "xs" => __T('extra small'), + "sm" => __T('small'), + "md" => __T('medium'), + "lg" => __T('large')); + + $this->shareButtons = movio_modules_sharingButtons_views_SharingButton::getSharingButtonList(); + } + + function process() + { + if ($this->shareButtons) { + $this->enabledButtons = explode(',', $this->shareButtons['buttonList']); + $this->selectedDim = $this->shareButtons['dim']; + $this->enableCheck = $this->shareButtons['enable'] ? 'checked ' : ' '; + } + else { + $this->enabledButtons = array(); + $this->selectedDim = 'md'; + $this->enableCheck = 'unchecked'; + } + } + + function render() + { + $minHeight = count($this->buttonListBase)*29 +2; + $output .= ' + <div class="control-group"> + <label class="control-label " for="sharingButton">'.__T('Enable sharing buttons').'</label> + <div class="controls"> + <input type="checkbox" data-type="checkbox" value ="1"'.$this->enableCheck.'name="sharingButtonCheck" id="sharingButtonCheck"> + </div> + </div> + <div id"shareButtonDrag" class="control-group" style="margin-left:20px;"> + <div class ="span2"> + <div style="font-weight:bold; margin-bottom:5px;"> + <hX>'.__T('Available buttons').'</hX> + </div> + <ul id="shareButtonListOff" class="sortable js-sharingDisabled" style="min-height:'.$minHeight.'px;">'; + + foreach ($this->buttonListBase as $button) { + if (!in_array ($button, $this->enabledButtons)) { + $output .= ' + <li id="shareButton_'.$button.'" class="ui-state-default">'.$button.'</li>'; + } + } + + $output .= ' + </ul> + </div> + <div class ="span2"> + <div style="font-weight:bold; margin-bottom:5px;"> + <hX>'.__T('Enabled buttons').'</hX> + </div> + <ul id="shareButtonListOn" class="sortable js-sharingEnabled " style="min-height:'.$minHeight.'px;">'; + + foreach ($this->buttonListBase as $button) { + if(in_array ($button, $this->enabledButtons)){ + $output .= ' + <li id="shareButton_'.$button.'" class="ui-state-default">'.$button.'</li>'; + } + }; + + $output .= ' + </ul> + </div> + <div class ="sortableNote">'.__T('Move and sort the buttons').'</div> + </div> + <div class="control-group" > + <label class="control-label " for="shareButtonDim">'.__T('Select dimension').'</label> + <div class="controls"> + <select name="shareButtonDim" id="shareButtonDim" class="span3">'; + + foreach ($this->dimList as $key => $dim) { + if ($key == trim($this->selectedDim)) { + $output .= '<option selected="selected" value="'.$key.'">'.$dim.'</option>'; + } + else { + $output .= '<option value="'.$key.'">'.$dim.'</option>'; + } + } + + $output .= ' + </select> + </div> + </div>'; + + $this->addOutputCode($output); + } + +} diff --git a/src/application/classes/movio/modules/sharingButtons/views/components/Share.php b/src/application/classes/movio/modules/sharingButtons/views/components/Share.php new file mode 100644 index 0000000..0ba5282 --- /dev/null +++ b/src/application/classes/movio/modules/sharingButtons/views/components/Share.php @@ -0,0 +1,110 @@ +<?php +class movio_modules_sharingButtons_views_components_Share extends org_glizy_components_Groupbox +{ + function init() + { + parent::init(); + } + + function process() + { + $shareButtons = movio_modules_sharingButtons_views_SharingButton::getSharingButtonList(); + + if (!$shareButtons['enable'] || empty($shareButtons['buttonList'])){ + $this->_content =''; + } + else{ + $dim = $shareButtons['dim']; + $buttonList = explode(',', $shareButtons['buttonList']); + $shareMsg = __T('Share on')." "; + $shareMailMsg = __T('Send link')."!"; + + $buttonArray = array( + "Twitter" => array( "id" => "twitter", + "link" => "https://twitter.com/share"), + "Facebook" => array( "id" => "facebook", + "link" => "https://facebook.com/sharer/sharer.php?u=#url#"), + "Google-plus" => array( "id" => "google-plus", + "link" => "https://plus.google.com/share?url=#url#"), + "Linkedin" => array( "id" => "linkedin", + "link" => "http://www.linkedin.com/shareArticle?mini=true&url=#url#&title=#title#"), + "Pinterest" => array( "id" => "pinterest", + "link" => "http://www.pinterest.com/pin/create/button/?url=#url#&media=#media#"), + "E-mail" => array( "id" => "mail", + "link" => "mailto:?body=".__T('Visit this page').": #url#&subject=#title#"), + "Facebook-like" => array( "id" => "fbLike", + "link" => "http://www.facebook.com/plugins/like.php?href=#url#&width&layout=box_count&action=like&show_faces=false&share=false"), + "Google+1" => array("id" => "google+1", + "link" => " https://apis.google.com/_/+1/fastbutton?usegapi=1&size=large&hl=en&url=#url#") + ); + + $buttonHtml = array(); + foreach ($buttonList as $i => $button) + { + $button = ucfirst(strtolower(trim($button))); + $dimension = is_array($dim) ? $dim[$i] : $dim; + if(!$dimension){ + $dimension = $dim[0]; + } + $span=""; + $id = "btn_".$buttonArray[$button]['id']; + $link = $buttonArray[$button]['link']; + $href = $this->setUrl($link); + if($button=="E-mail"){ + $a_class = "btn btn-adn btn-social-icon btn-".$dimension; + $i_class = "fa fa-envelope-o"; + $title = $shareMailMsg; + $target = "_blank"; + } else if($button=="Facebook-like") { + $i_class = "fb-like btn btn-facebook btn-".$dimension; + $a_class = ""; + $title = ""; + } else{ + $i_class = "fa fa-".$buttonArray[$button]['id']; + $a_class = "btn btn-".$buttonArray[$button]['id']." btn-social-icon btn-".$dimension; + $title = $shareMsg.$button."!"; + } + + $buttonHtml[] = array( + "id" => $id, + "name" => $buttonArray[$button]['id'], + "a_class" => $a_class, + "i_class" => $i_class, + "href" => $href, + "title" => $title); + } + $this->_content = $buttonHtml; + } + + } + + function render($mode) + { + if (!$this->_application->isAdmin()) { + $this->setAttribute('skin', 'Share.html'); + } + parent::render($mode); + } + + private function setUrl($link) + { + $id = strtolower(trim($id)); + $currentUrl = $this->curPageURL(); + $pageTitle = $this->_application->getCurrentMenu()->title; + $media = $this->getImage($currentUrl); + return str_replace(array('#url#', '#title#', '#media#'), array($currentUrl, $pageTitle, $media), $link); + } + + private function getImage($currentUrl){ + //TODO mappatura pagina immagine + $imgToShare = "#"; + return $imgToShare; + } + + private function curPageURL() + { + return urlencode(GLZ_HOST.'/'.__Request::get('__url__')); + } + +} + diff --git a/src/application/classes/movio/modules/storyteller/controllers/PostComment.php b/src/application/classes/movio/modules/storyteller/controllers/PostComment.php new file mode 100644 index 0000000..e312bea --- /dev/null +++ b/src/application/classes/movio/modules/storyteller/controllers/PostComment.php @@ -0,0 +1,51 @@ +<?php +class movio_modules_storyteller_controllers_PostComment extends org_glizy_mvc_core_Command +{ + public function execute($hash, $authorName, $authorEmail, $text, $captcha) + { + $valid = true; + $error = ''; + if (!($hash && $authorName && $authorEmail && $text && $captcha)) { + $valid = false; + $error = 'Wrong input'; + } + + if ($valid && !filter_var($authorEmail, FILTER_VALIDATE_EMAIL)) { + $valid = false; + $error = 'Wrong email'; + } + + $sessionEx = new org_glizy_SessionEx($this->application->getPageId()); + $verCaptcha = $sessionEx->get('captcha'.$hash); + if ($valid && $verCaptcha!=$captcha) { + $valid = false; + $error = 'Wrong verify code'; + } + + if ($valid) { + $ar = org_glizy_ObjectFactory::createModel('movio.modules.storyteller.models.Comment'); + $ar->hash = $hash; + $ar->menuId = $this->application->getPageId(); + $ar->authorName = $authorName; + $ar->authorEmail = $authorEmail; + $ar->approved = 1; + $ar->date = new org_glizy_types_Date(); + $ar->text = nl2br($text); + $ar->save(); + + $sessionEx->remove($hash.'_author'); + $sessionEx->remove($hash.'_email'); + $sessionEx->remove($hash.'_text'); + $sessionEx->remove($hash.'_error'); + $destHash = '#comments_'.$hash; + } else { + $sessionEx->set($hash.'_author', $authorName); + $sessionEx->set($hash.'_email', $authorEmail); + $sessionEx->set($hash.'_text', $text); + $sessionEx->set($hash.'_error', $error); + $destHash = '#form_'.$hash; + } + + $this->goHere(null, $destHash); + } +} diff --git a/src/application/classes/movio/modules/storyteller/controllers/ajax/PagePicker.php b/src/application/classes/movio/modules/storyteller/controllers/ajax/PagePicker.php new file mode 100644 index 0000000..d34a4e0 --- /dev/null +++ b/src/application/classes/movio/modules/storyteller/controllers/ajax/PagePicker.php @@ -0,0 +1,33 @@ +<?php +// questo controller serve per gestire il campo di tipologia del campo Documents +// che è passato da un campo di picker sull'entià +// ad un campo per selezionare le pagine ed i contenuti del cms +// +class movio_modules_storyteller_controllers_ajax_PagePicker extends org_glizy_mvc_core_CommandAjax +{ + function execute($term, $id, $protocol, $filterType) + { + $this->directOutput = true; + + $speakingUrlManager = $this->application->retrieveProxy('org.glizycms.speakingUrl.Manager'); + if ($id && !$term) { + $result = array(); + $json = json_decode($id); + $id = is_array($json) ? $json : array($id); + foreach($id as $v) { + if (is_object($v)) { + $v = 'movioContent:'.$v->id; + } + $tempResult = $speakingUrlManager->searchDocumentsByTerm('', $v, $protocol, $filterType); + if ($tempResult && is_array($tempResult)) { + $result[] = $tempResult[0]; + } + } + + } else { + $result = $speakingUrlManager->searchDocumentsByTerm($term, '', $protocol, $filterType); + + } + return $result; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/storyteller/models/Comment.xml b/src/application/classes/movio/modules/storyteller/models/Comment.xml new file mode 100755 index 0000000..8780ae8 --- /dev/null +++ b/src/application/classes/movio/modules/storyteller/models/Comment.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="movio.modules.storyteller.models.comments" model:usePrefix="true" model:type="simpledocument"> + + <model:Define> + <model:Field name="menuId" type="int" validator="notNull" index="true" /> + <model:Field name="hash" type="string" validator="notNull" index="true" /> + <model:Field name="approved" type="int" index="true" /> + <model:Field name="authorName" type="string" index="false" /> + <model:Field name="authorEmail" type="string" index="false" /> + <model:Field name="date" type="datetime" index="true" /> + <model:Field name="text" type="string" index="false" /> + </model:Define> + + <model:Query name="getCommentFromStory" type="function" arguments="menuId,hash"> + <![CDATA[ + $iterator->where('menuId', $menuId) + ->where('hash', $hash) + ->orderBy('date', 'DESC'); + ]]> + </model:Query> + + +</model:Model> + + + diff --git a/src/application/classes/movio/modules/storyteller/views/components/Storyteller.xml b/src/application/classes/movio/modules/storyteller/views/components/Storyteller.xml new file mode 100644 index 0000000..bbde1fc --- /dev/null +++ b/src/application/classes/movio/modules/storyteller/views/components/Storyteller.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Panel + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:st="movio.modules.storyteller.views.components.*"> + + <st:StorytellerCmp id="story" label="{i18n:Story}" adm:collapsable="true" skin="Storyteller.html" controllerName="movio.modules.storyteller.controllers.*"> + <glz:Input id="title" label="{i18n:Title}" size="50" /> + <glz:List id="type" label="{i18n:Story item type}" data="target=title,subtitle,text,image,video,audio,url,gallery,galleryType,galleryImageCrop,galleryImagePan,documents;val_0=1,1,1,0,0,0,0,0,0,0,0,1;val_1=1,1,1,1,1,1,0,0,0,0,0,1;val_2=1,0,1,0,1,0,0,0,0,0,0,1;val_3=1,0,1,0,0,0,1,0,0,0,0,1;val_4=1,0,1,1,0,0,0,0,0,0,0,1;val_5=1,0,1,0,0,0,0,1,1,1,1,1;val_6=1,0,1,0,0,1,0,0,0,0,0,1"> + <glz:ListItem value="{i18n:Text}" key="text" /> + <glz:ListItem value="{i18n:Text with media}" key="text_media" /> + <glz:ListItem value="{i18n:Video}" key="video" /> + <glz:ListItem value="{i18n:External Video}" key="video_ext" /> + <glz:ListItem value="{i18n:Image}" key="image" /> + <glz:ListItem value="{i18n:Photogallery}" key="photogallery" /> + <glz:ListItem value="{i18n:Audio}" key="audio" /> + </glz:List> + + <glz:Hidden id="hash" data="type=inputguid;base=st" /> + <glz:Checkbox id="commentsEnabled" label="{i18n:Enable comments}" data="type=checkbox" defaultValue="0" /> + <glz:Input id="subtitle" label="{i18n:Subtitle}" size="50" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + <glz:LongText id="textAfter" label="{i18n:Final text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + + <glz:Image id="image" label="{i18n:Image}" /> + <glz:Media id="video" label="{i18n:Video}" adm:mediaType="VIDEO" /> + <glz:Media id="audio" label="{i18n:Audio}" adm:mediaType="AUDIO" /> + <glz:Input id="url" label="{i18n:Video url}" size="50" /> + + <glz:List id="galleryType" label="{i18n:Gallery type}"> + <glz:ListItem value="{i18n:Gallery}" key="gallery" /> + <glz:ListItem value="{i18n:Slideshow}" key="slideshow" /> + <glz:ListItem value="{i18n:Slider}" key="slider" /> + <glz:ListItem value="{i18n:Page flip}" key="pageflip" /> + </glz:List> + <glz:Checkbox id="galleryImageCrop" label="{i18n:Image crop}" defaultValue="1" /> + <glz:Checkbox id="galleryImagePan" label="{i18n:Image pan}" defaultValue="1" /> + <glz:Input id="gallery" label="{i18n:Image category}" data="type=selectfrom;multiple=true;add_new_values=false;model=org.glizycms.models.Media;field=media_category;override=false" /> + + <cms:PagePicker id="documents" label="{i18n:Insights}" required="false" multiple="true" ajaxController="movio.modules.storyteller.controllers.ajax.PagePicker"/> + </st:StorytellerCmp> +</glz:Panel> + diff --git a/src/application/classes/movio/modules/storyteller/views/components/StorytellerCmp.php b/src/application/classes/movio/modules/storyteller/views/components/StorytellerCmp.php new file mode 100644 index 0000000..6e1274f --- /dev/null +++ b/src/application/classes/movio/modules/storyteller/views/components/StorytellerCmp.php @@ -0,0 +1,47 @@ +<?php +class movio_modules_storyteller_views_components_StorytellerCmp extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + $content = org_glizy_helpers_Convert::formEditObjectToStdObject($this->_parent->loadContent($this->getId(), true)); + $this->_content = new movio_modules_storyteller_views_skins_StorytellerSkinIterator($content, + $this->_application->getPageId(), + __Routing::scriptUrl()); + } + + public static function compileAddPrefix($compiler, &$node, $componentId, $idPrefix) + { + return $idPrefix.'\''.$componentId.'-\'.'; + } + + public static function translateForMode_edit($node) { + $min = $node->hasAttribute('adm:min') ? $node->getAttribute('adm:min') : '0'; + $max = $node->hasAttribute('adm:max') ? $node->getAttribute('adm:max') : '100'; + $collapsable = $node->hasAttribute('adm:collapsable') && $node->getAttribute('adm:collapsable') == 'true' ? 'true' : 'false'; + + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['data'] = 'type=repeat;repeatMin='.$min.';repeatMax='.$max.';collapsable='.$collapsable; + if ($node->hasAttribute('adm:data')) { + $attributes['data'] .= ';'.$node->getAttribute('adm:data'); + } + + return org_glizy_helpers_Html::renderTag('glz:Fieldset', $attributes); + } +} diff --git a/src/application/classes/movio/modules/storyteller/views/skins/StorytellerSkinIterator.php b/src/application/classes/movio/modules/storyteller/views/skins/StorytellerSkinIterator.php new file mode 100644 index 0000000..b375707 --- /dev/null +++ b/src/application/classes/movio/modules/storyteller/views/skins/StorytellerSkinIterator.php @@ -0,0 +1,222 @@ +<?php +class movio_modules_storyteller_views_skins_StorytellerSkinIterator extends GlizyObject implements Iterator +{ + private $pos = 0; + private $count = 0; + private $content; + private $pageId; + private $pageUrl; + private $captchaBuilder; + private $sessionEx; + + function __construct( $content, $pageId, $pageUrl ) + { + GlizyClassLoader::addLib('Gregwar\Captcha', __Paths::get('APPLICATION_LIBS').'captcha'); + + $this->content = $content; + $this->pageId = $pageId; + $this->pageUrl = $pageUrl; + $this->count = count($this->content); + + $this->sessionEx = new org_glizy_SessionEx($pageId); + $this->captchaBuilder = new Gregwar\Captcha\CaptchaBuilder; + } + + function current() + { + $value = $this->content[$this->pos]; + if (!property_exists($value, 'commentsEnabled')) { + $value->commentsEnabled = false; + } + if (!property_exists($value, 'textAfter')) { + $value->textAfter = ''; + } + if (!property_exists($value, 'galleryType')) { + $value->galleryType = 'slideshow'; + } + if (!property_exists($value, 'galleryImageCrop')) { + $value->galleryImageCrop = 0; + } + if (!property_exists($value, 'galleryImagePan')) { + $value->galleryImagePan = 0; + } + + $value->showArrow = $this->pos == 0 ? '' : '1'; + $value->externalLink = ''; + $this->prepareText($value); + switch ($value->type) { + case 'text_media': + $this->prepareTextMedia($value); + break; + case 'video': + $this->prepareVideo($value); + break; + case 'video_ext': + $this->prepareVideoExt($value); + break; + case 'image': + $this->prepareImage($value); + break; + case 'photogallery': + $this->preparePhotogallery($value); + break; + case 'audio': + $this->prepareAudio($value); + break; + } + + $this->addDocuments($value); + $this->addComments($value); + $this->addLinks($value); + + + return $value; + } + + function key() + { + return $this->pos; + } + + function next() + { + $this->pos++; + } + + function rewind() + { + $this->pos = 0; + } + + function valid() + { + return $this->pos < $this->count; + } + + function count() + { + return $this->count; + } + + private function prepareText($value) + { + $value->text = org_glizy_helpers_Link::parseInternalLinks($value->text); + $value->textAfter = org_glizy_helpers_Link::parseInternalLinks($value->textAfter); + } + + private function prepareTextMedia($value) + { + $value->type = 'text'; + $this->prepareImage($value); + $this->prepareAudio($value); + $this->prepareVideo($value); + } + + private function prepareVideo($value) + { + if ($value->video && is_string($value->video)) { + $img = json_decode($value->video); + $value->video = $img->id; + } + } + + private function prepareVideoExt($value) + { + preg_match_all('/http(s)?:\/\/(?:www.)?(vimeo|youtube|youtu)(\.\w{2,3})\/(?:watch\?v=)?(.*?)(?:\z|&)/', $value->url, $match); + if (count($match[0])) { + $value->externalLink = $value->url; + if ($match[2][0] == 'vimeo') { + $value->type = 'vimeo'; + $value->url = 'http://player.vimeo.com/video/'.$match[4][0].'?title=0&amp;byline=0&amp;portrait=0'; + } else { + $value->type = 'youtube'; + $value->url = 'http://www.youtube.com/embed/'.$match[4][0].'?rel=0'; + } + } else { + $value->type = ''; + } + } + + private function prepareImage($value) + { + if ($value->image && is_string($value->image)) { + $img = json_decode($value->image); + $value->image = $img->id; + } + } + + private function preparePhotogallery($value) + { + $filter = $value->gallery; + + if (is_array($filter) && count($filter)) { + $value->gallery = org_glizy_ObjectFactory::createModelIterator('org.glizycms.models.Media') + ->load('all') + ->where('media_type', 'IMAGE'); + + foreach($filter as $v) { + $value->gallery->where('media_category', '%"'.$v.'"%', 'LIKE'); + } + + $value->galleryImagePosition = $value->galleryImageCrop == 1 && $value->galleryImagePan == 1 ? 'top right' : '50%'; + $value->galleryImageCrop = $value->galleryImageCrop == 1 ? 'true' : 'false'; + $value->galleryImagePan = $value->galleryImagePan == 1 ? 'true' : 'false'; + } else { + $value->gallery = array(); + } + } + + private function prepareAudio($value) + { + if ($value->audio && is_string($value->audio)) { + $img = json_decode($value->audio); + $value->audio = $img->id; + } + } + + private function addComments($value) + { + $it = org_glizy_ObjectFactory::createModelIterator('movio.modules.storyteller.models.Comment') + ->load('getCommentFromStory', array('menuId' => $this->pageId, 'hash' => $value->hash)); + $value->comments = $it; + $value->numComments = $it->count(); + + // captcha + $this->captchaBuilder->build(); + $this->sessionEx->set('captcha'.$value->hash, $this->captchaBuilder->getPhrase(), GLZ_SESSION_EX_VOLATILE); + $value->captcha = '<img src="'.$this->captchaBuilder->inline().'" />'; + $value->formAuthor = $this->sessionEx->get($value->hash.'_author', ''); + $value->formEmail = $this->sessionEx->get($value->hash.'_email', ''); + $value->formText = $this->sessionEx->get($value->hash.'_text', ''); + $value->formError = $this->sessionEx->get($value->hash.'_error', ''); + } + + private function addLinks($value) + { + $value->urlPermalink = $this->pageUrl.'#'.$value->hash; + $value->urlFacebook = 'http://www.facebook.com/sharer.php?u='.urlencode($value->urlPermalink); + $value->urlTwitter = 'http://twitter.com/home?status=Sto%20leggendo+'.urlencode($value->urlPermalink); + } + + private function addDocuments($value) + { + if (!empty($value->documents)) { + $results = array(); + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $speakingUrlManager = $application->retrieveProxy('org.glizycms.speakingUrl.Manager'); + + foreach($value->documents as $v) { + if (is_object($v)) { + $v = 'movioContent:'.$v->id; + } + $url = $speakingUrlManager->makeLink($v); + if ($url) { + $results[] = $speakingUrlManager->makeLink($v); + } + } + + $value->documents = $results; + } + } +} + diff --git a/src/application/classes/movio/modules/thesaurus/Exception.php b/src/application/classes/movio/modules/thesaurus/Exception.php new file mode 100644 index 0000000..bc22709 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/Exception.php @@ -0,0 +1,24 @@ +<?php +class movio_modules_thesaurus_Exception extends Exception +{ + public static function dictionaryCreationError($name) + { + return new self('Error creating dictionary: '.$name); + } + + public static function termCreationError($term) + { + return new self('Error creating term: '.$term); + } + + public static function termWrongType($type) + { + return new self('Term with wrong type: '.$type); + } + + public static function DictWrongType($type) + { + return new self('Dictionary with wrong type: '.$type); + } + +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/Module.php b/src/application/classes/movio/modules/thesaurus/Module.php new file mode 100644 index 0000000..33b9305 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/Module.php @@ -0,0 +1,21 @@ +<?php +class movio_modules_thesaurus_Module +{ + static function registerModule() + { + glz_loadLocale('movio.modules.thesaurus'); + + $moduleVO = org_glizy_Modules::getModuleVO(); + $moduleVO->id = 'movio_thesaurus'; + $moduleVO->name = __T('movio_thesaurus'); + $moduleVO->description = ''; + $moduleVO->version = '1.0.0'; + $moduleVO->classPath = 'movio.modules.thesaurus'; + $moduleVO->author = 'META srl'; + $moduleVO->authorUrl = 'http://www.gruppometa.it'; + $moduleVO->pluginUrl = 'http://movio.beniculturali.it/'; + $moduleVO->siteMapAdmin = '<glz:Page pageType="movio.modules.thesaurus.views.Admin" id="movio_thesaurus" value="{i18n:'.$moduleVO->name.'}" icon="icon-circle-blank" adm:acl="*" />'; + + org_glizy_Modules::addModule( $moduleVO ); + } +} diff --git a/src/application/classes/movio/modules/thesaurus/controllers/DeleteDictionary.php b/src/application/classes/movio/modules/thesaurus/controllers/DeleteDictionary.php new file mode 100644 index 0000000..d3efafe --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/controllers/DeleteDictionary.php @@ -0,0 +1,11 @@ +<?php +class movio_modules_thesaurus_controllers_DeleteDictionary extends org_glizy_mvc_core_Command +{ + public function execute($dictionaryId) + { + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $thesaurusProxy->deleteDictionary($dictionaryId); + + $this->changeAction('index'); + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/controllers/dictionaryEdit/ajax/Add.php b/src/application/classes/movio/modules/thesaurus/controllers/dictionaryEdit/ajax/Add.php new file mode 100644 index 0000000..28b0245 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/controllers/dictionaryEdit/ajax/Add.php @@ -0,0 +1,17 @@ +<?php +class movio_modules_thesaurus_controllers_dictionaryEdit_ajax_Add extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { + $this->directOutput = true; + + try { + $data = json_decode($data); + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $arTerm = $thesaurusProxy->addDictionary($data->title, $data->type); + return array('url' => $this->changeAction( 'editDictionary/?&dictionaryId='.$arTerm->document_id )); + } catch (Exception $e) { + return array('errors' => array($e->getMessage())); + } + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/controllers/dictionaryEdit/ajax/Save.php b/src/application/classes/movio/modules/thesaurus/controllers/dictionaryEdit/ajax/Save.php new file mode 100644 index 0000000..17eeaab --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/controllers/dictionaryEdit/ajax/Save.php @@ -0,0 +1,19 @@ +<?php +class movio_modules_thesaurus_controllers_dictionaryEdit_ajax_Save extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { + $this->directOutput = true; + + try { + $data = json_decode($data); + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $termVO = $thesaurusProxy->getTermVO($data->type); + $termVO->setFromObject($data); + $thesaurusProxy->saveTerm($termVO); + } catch (Exception $e) { + return array('errors' => array($e->getMessage())); + } + return true; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/controllers/termEdit/Add.php b/src/application/classes/movio/modules/thesaurus/controllers/termEdit/Add.php new file mode 100644 index 0000000..256b90a --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/controllers/termEdit/Add.php @@ -0,0 +1,23 @@ +<?php +class movio_modules_thesaurus_controllers_termEdit_Add extends org_glizy_mvc_core_Command +{ + public function execute() + { + $dictionaryId = __Request::get('dictionaryId'); + $this->setComponentsAttribute('dictionaryId', 'value', $dictionaryId); + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $type = $thesaurusProxy->getTypeByDictionaryId($dictionaryId); + $this->setComponentsAttribute('type', 'value', $type); + $typeEnum = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.TermTypeEnum'); + $typeArray = $typeEnum::getTypes(); + $disabledPanel = array(); + foreach ($typeArray as $currentType) + { + if ($currentType!= $type) { + $disabledPanel[] = $currentType.'Panel'; + } + } + $this->setComponentsVisibility( $disabledPanel , false ); + } + +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/controllers/termEdit/Edit.php b/src/application/classes/movio/modules/thesaurus/controllers/termEdit/Edit.php new file mode 100644 index 0000000..a3cc78a --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/controllers/termEdit/Edit.php @@ -0,0 +1,8 @@ +<?php +class movio_modules_thesaurus_controllers_termEdit_Edit extends movio_modules_thesaurus_controllers_termEdit_Add +{ + public function execute() + { + parent::execute(); + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/controllers/termEdit/ajax/Add.php b/src/application/classes/movio/modules/thesaurus/controllers/termEdit/ajax/Add.php new file mode 100644 index 0000000..62e642d --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/controllers/termEdit/ajax/Add.php @@ -0,0 +1,23 @@ +<?php +class movio_modules_thesaurus_controllers_termEdit_ajax_Add extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { + $this->directOutput = true; + try { + $data = json_decode($data); + $parentId = $data->parentId ?: $data->dictionaryId; + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $termVO = $thesaurusProxy->getTermVO($data->type); + $termVO->setFromObject($data); + $arTerm = $thesaurusProxy->saveTerm($termVO); + } catch (Exception $e) { + return array('errors' => array($e->getMessage())); + } + + return array( + 'evt' => 'thesaurus.termAdded', + 'message' => array('termId' => $arTerm->getId(), 'parentId' => $parentId) + ); + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/controllers/termEdit/ajax/Save.php b/src/application/classes/movio/modules/thesaurus/controllers/termEdit/ajax/Save.php new file mode 100644 index 0000000..ce7be13 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/controllers/termEdit/ajax/Save.php @@ -0,0 +1,23 @@ +<?php +class movio_modules_thesaurus_controllers_termEdit_ajax_Save extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { + $this->directOutput = true; + try { + $data = json_decode($data); + $parentId = $data->parentId ?: $dictionaryId; + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $termVO = $thesaurusProxy->getTermVO($data->type); + $termVO->setFromObject($data); + $arTerm = $thesaurusProxy->saveTerm($termVO); + } catch (Exception $e) { + return array('errors' => array($e->getMessage())); + } + + return array( + 'evt' => 'thesaurus.termAdded', + 'message' => array('termId' => $arTerm->getId(), 'parentId' => $parentId)); + + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/DeleteTerm.php b/src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/DeleteTerm.php new file mode 100644 index 0000000..f0e412f --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/DeleteTerm.php @@ -0,0 +1,11 @@ +<?php +class movio_modules_thesaurus_controllers_treeview_ajax_DeleteTerm extends org_glizy_mvc_core_CommandAjax +{ + function execute($termId) + { + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $thesaurusProxy->deleteTerm($termId); + + return true; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/GetChildren.php b/src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/GetChildren.php new file mode 100644 index 0000000..8b4d92a --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/GetChildren.php @@ -0,0 +1,59 @@ +<?php +class movio_modules_thesaurus_controllers_treeview_ajax_GetChildren extends org_glizy_mvc_core_CommandAjax +{ + private $thesaurusProxy; + private $dictionaryId; + + public function execute($termId) + { + $this->directOutput = true; + $this->thesaurusProxy =org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $this->dictionaryId = __Request::get('dictionaryId'); + $result = array(); + if ($termId==0) { + // root + $dict = $this->thesaurusProxy->getDictionaryById($this->dictionaryId); + $result[] = $this->addNode($dict, true); + return $result; + } + + $terms = $this->thesaurusProxy->getFirstLevelChildrens($this->dictionaryId, $termId); + foreach ($terms as $termObj) { + $result[] = $this->addNode($termObj); + } + + return $result; + } + + protected function addNode($termObj, $isRoot=false) { + $node = array( + 'data' => array( + 'title' => $isRoot ? $termObj->title : $termObj->term, + 'icon' => $isRoot ? 'folder' : 'page', + ), + 'attr' =>array( + 'id' => $termObj->getId(), + 'rel' => $isRoot ? 'root' : 'default', + 'class' => '', + 'title' => $title + ) + ); + + if (!$isRoot) { + $numChild = count((array)$this->thesaurusProxy->getFirstLevelChildrens($this->dictionaryId, $termObj->getId())); + $node['metadata']['edit'] = $this->user->acl($this->application->getPageId(),'edit'); + $node['metadata']['delete'] = $this->user->acl($this->application->getPageId(),'delete'); + $node['metadata']['move'] = $this->user->acl($this->application->getPageId(),'move'); + $node['state'] = $numChild ? 'closed' : ''; + } else { + $node['metadata']['delete'] = false; + $node['metadata']['show'] = false; + $node['metadata']['edit'] = 0; + $node['metadata']['delete'] = 0; + $node['metadata']['move'] = 0; + $node['state'] = 'closed'; + } + + return $node; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/MoveTerm.php b/src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/MoveTerm.php new file mode 100644 index 0000000..e1dd0b8 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/controllers/treeview/ajax/MoveTerm.php @@ -0,0 +1,11 @@ +<?php +class movio_modules_thesaurus_controllers_treeview_ajax_MoveTerm extends org_glizy_mvc_core_CommandAjax +{ + function execute($termId, $parentId) + { + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $thesaurusProxy->moveTerm($termId, $parentId); + + return true; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/js/Admin.js b/src/application/classes/movio/modules/thesaurus/js/Admin.js new file mode 100755 index 0000000..bd10b50 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/js/Admin.js @@ -0,0 +1,9 @@ +GlizyApp.pages[ 'movio.modules.thesaurus.views.Admin' ] = function( state, routing ) { + $(function(){ + if ('editDictionary'==state) { + var tree = new DictionaryTree("#js-glizycmsSiteTree", "#js-glizycmsSiteTreeAdd"); + Glizy.module('thesaurus.TermEditIframe').run(); + } + }); +}; +2 \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/js/DictionaryTree.js b/src/application/classes/movio/modules/thesaurus/js/DictionaryTree.js new file mode 100755 index 0000000..fe3f754 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/js/DictionaryTree.js @@ -0,0 +1,237 @@ +var DictionaryTree = dejavu.Class.declare({ + treeId: null, + tree: null, + ajaxUrl: null, + dictionaryId: null, + treeOffset: null, + + initialize: function(treeId, addPageId) { + var self = this; + this.treeId = treeId; + this.tree = $(this.treeId); + this.ajaxUrl = this.tree.data('ajaxurl'); + this.lastAddPageLink = ''; + + // initialize the tree + this.tree.jstree({ + // List of active plugins + "plugins" : [ "themes","json_data","ui","crrm","cookies","dnd","types","contextmenu"], + "json_data" : { + "ajax" : { + "url" : this.ajaxUrl+"GetChildren", + "data" : function (n) { + self.onResize(); + return { + "termId" : n.attr ? n.attr("id").replace("node_","") : 0 + }; + } + } + }, + "crrm" : { + "move" : { + "check_move" : function (m) { + //console.log(m) + var targetId = parseInt(m.np.attr('id')); + return targetId && m.o.attr('id') != m.np.attr('id') && m.np.attr('id') != m.op.attr('id'); + } + } + }, + "dnd" : { + "drop_target" : false, + "drag_target" : false + }, + "types" : { + "types" : { + "root" : { + "select_node" : function () {return false;} + } + } + }, + "cookies" : { + "save_selected" : false + }, + "contextmenu" : { + "items" : this.customMenu + } + }) + .bind("select_node.jstree", this.onNodeSelect) + .bind("remove.jstree", this.onNodeRemove) + .bind("move_node.jstree", this.onNodeMove) + .bind("loaded.jstree", this.onTreeLoaded); + this.tree.css("overflow", "auto"); + this.treeOffset = this.tree.offset(); + + // add page button + $(addPageId).click(this.onAddPageClick); + + // Listen events + Glizy.events.on("thesaurus.termAdded", this.onPageAdded); + Glizy.events.on("glizycms.refreshTree", this.onRefreshTree); + Glizy.events.on("glizycms.renameTitle", this.onRefreshTree); + Glizy.events.on("glizycms.treeCallAjaxForMenu", this.onTreeAjaxCall); + + $(window).resize(this.onResize); + this.onResize(); + }, + + onResize: function (event) { + var h = $(window).height() - this.treeOffset.top; + this.tree.height(h); + }.$bound(), + + onTreeLoaded: function (event, data) { + this.tree.jstree('open_all'); + //this.tree.jstree('check_all'); + }.$bound(), + + /** + * Tree node selected, dispatch the event with the menuId param + * @param event event DOM event + * @param object data Treeview data object + */ + onNodeSelect: function (event, data) { + this.lastAddPageLink = ''; + if (data.rslt.e) { + Glizy.events.broadcast("thesaurus.termEdit", {"termId": data.rslt.obj.attr("id")}); + } + }.$bound(), + + /** + * Tree node delete, send a ajax request to delete the node, + * after deleted the tree is refreshed. + * The ajax call Delete command with: + * menuId: id to delete + * @param event event DOM event + * @param object data Treeview data object + */ + onNodeRemove: function (event, data) { + var self = this; + //var treeContainer = $.jstree._reference(this.treeId).get_container(); + //var count =treeContainer.find("li").length; + data.rslt.obj.each(function () { + $.ajax({ + async : false, + type: 'POST', + url: self.ajaxUrl+"DeleteTerm", + data : { + "termId" : this.id + }, + success : function (r) { + if(!r.status) { + data.inst.refresh(); + } + Glizy.events.broadcast("thesaurus.termAdd", {"href": ''}); + } + }); + }); + }.$bound(), + + /** + * Tree node move, send a ajax request to move the node, + * after the mode the tree is refreshed. + * The ajax call Move command with: + * menuId: id to move + * parentId: id of parent node + * position: a new position + * @param event event DOM event + * @param object data Treeview data object + */ + onNodeMove: function (event, data) { + var self = this; + data.rslt.o.each(function (i) { + $.ajax({ + async : false, + type: 'POST', + url: self.ajaxUrl+"MoveTerm", + data : { + "termId" : $(this).attr("id"), + "parentId" : data.rslt.cr === -1 ? 0 : data.rslt.np.attr("id"), + }, + success : function (r) { + if(!r.status) { + $.jstree.rollback(data.rlbk); + } + else { + $(data.rslt.oc).attr("id", "node_" + r.id); + if(data.rslt.cy && $(data.rslt.oc).children("UL").length) { + data.inst.refresh(data.inst._get_parent(data.rslt.oc)); + } + } + } + }); + }); + }.$bound(), + + onAddPageClick: function(e){ + e.preventDefault(); + self.lastAddPageLink = e.currentTarget.href+(e.currentTarget.href.indexOf('?') > -1 ? '&' : '?')+'parentId='+this.tree.jstree('get_selected').attr("id"); + Glizy.events.broadcast("thesaurus.termAdd", {"href": self.lastAddPageLink}); + $("#js-glizycmsPageEdit").on('load', function(e){ + $frame = $("#js-glizycmsPageEdit").contents(); + if($('#parentId option', $frame).size() < 2) { + $("#parentId", $frame).prop('disabled', 'disabled'); + } + }) + }.$bound(), + + onPageAdded: function(e){ + Glizy.events.broadcast("thesaurus.termAdd", {"href": self.lastAddPageLink}); + var node = this.tree.find("#"+e.message.parentId); + var tree = jQuery.jstree._reference(this.treeId); + tree.refresh(node); + Glizy.events.broadcast("glizy.message.showSuccess", {"title": "{i18n:Data saved correctly}", "message": ""}); + }.$bound(), + + + onRefreshTree: function(e){ + var tree = jQuery.jstree._reference(this.treeId); + var currentNode = tree._get_node(null, false); + var parentNode = tree._get_parent(currentNode); + tree.refresh(currentNode); + tree.open(currentNode); + }.$bound(), + + onTreeAjaxCall: function(e){ + var self = this; + $.ajax({ + async : false, + type: 'POST', + url: self.ajaxUrl+e.message.action, + data : { + "termId" : e.message.termId + }, + success : function (r) { + Glizy.events.broadcast("glizycms.refreshTree"); + } + }); + }.$bound(), + + customMenu: function(node) { + var self = this; + var menu = {}; + if (node.data("edit") == "1") { + menu.modify = { + "label": "{i18n:Edit}", + "icon": "icon-pencil", + action : function(obj) { + Glizy.events.broadcast("thesaurus.termEdit", {"termId": obj.attr("id")}); + } + }; + } + + if (node.data("delete") == "1") { + menu.remove = { + "label": "{i18n:Delete}", + "icon": "icon-remove", + "action": function(obj) { + Glizy.confirm("{i18n:thesaurus.confirm.termDelete}", [], function(success){ + if (success) { + self.remove(obj); + } + }); + } + }; + } + return menu; + } +}); \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/js/TermEditIframe.js b/src/application/classes/movio/modules/thesaurus/js/TermEditIframe.js new file mode 100755 index 0000000..79c95eb --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/js/TermEditIframe.js @@ -0,0 +1,41 @@ +Glizy.module('thesaurus.TermEditIframe', function(){ + this.iframe = null; + this.emptySrc = null; + this.editSrc = null; + this.iframeOffset = null; + + this.run = function() { + var self = this; + this.iframe = $("#js-glizycmsPageEdit"); + this.iframeOffset = this.iframe.offset(); + this.emptySrc = this.iframe.data("emptysrc"); + this.editSrc = this.iframe.data("editsrc"); + this.changeUrl(null, this.emptySrc); + + Glizy.events.on("thesaurus.termEdit", function(e) { + self.changeUrl(e.message.termId); + }); + + Glizy.events.on("thesaurus.termAdd", function(e){ + self.changeUrl(null, e.message.href); + }); + + $('body').css('overflow', 'hidden'); + $(window).resize(Glizy.responder(this, this.onResize)); + this.onResize(); + }; + + this.changeUrl = function(termId, href) { + if (termId) { + jQuery("#modalDiv").remove(); + this.iframe.attr("src", this.editSrc+termId+"&_"+(new Date()).getTime()); + } else { + this.iframe.attr("src", href); + } + }; + + this.onResize = function() { + var h = $(window).height() - this.iframeOffset.top; + this.iframe.height(h); + }; +}); diff --git a/src/application/classes/movio/modules/thesaurus/locale/en.php b/src/application/classes/movio/modules/thesaurus/locale/en.php new file mode 100644 index 0000000..6865500 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/locale/en.php @@ -0,0 +1,18 @@ +<?php +$strings = array ( + 'movio_thesaurus' => 'Thesaurus', + 'thesaurus.confirm.termDelete' => 'Are you sure you want to delete this term?', + 'Create dictionary' => 'Create dictionary', + 'Dictionary name' => 'Dictionary name', + 'Generic' => 'Generic', + 'Geographical' => 'Geographical', + 'Chronologic' => 'Chronologic', + 'Dictionary structure' => 'Dictionary structure', + 'Add term' => 'Add term', + 'Edit term' => 'Edit term', + 'Term' => 'Term', + 'Parent' => 'Parent', + 'Term source' => 'Term source', + 'Scope note' => 'Scope note', +); +org_glizy_locale_Locale::append($strings); \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/locale/it.php b/src/application/classes/movio/modules/thesaurus/locale/it.php new file mode 100644 index 0000000..5e7ffd8 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/locale/it.php @@ -0,0 +1,18 @@ +<?php +$strings = array ( + 'movio_thesaurus' => 'Thesauri', + 'thesaurus.confirm.termDelete' => 'Siete sicuri di voler cancellare il termine?', + 'Create dictionary' => 'Crea dizionario', + 'Dictionary name' => 'Nome dizionario', + 'Generic' => 'Generico', + 'Geographical' => 'Geografico', + 'Chronologic' => 'Cronologico', + 'Dictionary structure' => 'Struttura dizionario', + 'Add term' => 'Aggiungi termine', + 'Edit term' => 'Modifica termine', + 'Term' => 'Termine', + 'Parent' => 'Padre', + 'Term source' => 'Fonte termine', + 'Scope note' => 'Nota esplicativa', +); +org_glizy_locale_Locale::append($strings); \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/models/ChronologicTermVO.php b/src/application/classes/movio/modules/thesaurus/models/ChronologicTermVO.php new file mode 100644 index 0000000..54f17c2 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/models/ChronologicTermVO.php @@ -0,0 +1,19 @@ +<?php +class movio_modules_thesaurus_models_ChronologicTermVO extends movio_modules_thesaurus_models_TermVO +{ + public $dateFrom; + public $dateTo; + + public static function createFromAr($ar) + { + $vo = new self; + $vo->__id = $ar->getId(); + $vo->term = $ar->term; + $vo->type = movio_modules_thesaurus_models_TermTypeEnum::CHRONOLOGIC; + $vo->parentId = $ar->parentId; + $vo->dictionaryId = $ar->dictionaryId; + $vo->dateFrom = $ar->dateFrom; + $vo->dateTo = $ar->dateTo; + return $vo; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/models/Dictionary.xml b/src/application/classes/movio/modules/thesaurus/models/Dictionary.xml new file mode 100644 index 0000000..e07021a --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/models/Dictionary.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="movio.modules.thesaurus.models.Dictionary" model:usePrefix="true" model:type="document"> + + <model:Define> + <model:Field name="title" type="string" length="255" index="true" /> + <model:Field name="type" type="string" length="255" /> + </model:Define> +</model:Model> \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/models/DictionaryVO.php b/src/application/classes/movio/modules/thesaurus/models/DictionaryVO.php new file mode 100644 index 0000000..fc5e445 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/models/DictionaryVO.php @@ -0,0 +1,21 @@ +<?php +class movio_modules_thesaurus_models_DictionaryVO +{ + public $title; + public $type; + public $id; + + public static function createFromAr($ar) + { + $vo = new self; + $vo->id = $ar->getId(); + $vo->title = $ar->title; + $vo->type = $ar->type; + return $vo; + } + + public function getId() + { + return $this->id; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/models/GenericTermVO.php b/src/application/classes/movio/modules/thesaurus/models/GenericTermVO.php new file mode 100644 index 0000000..ed7925f --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/models/GenericTermVO.php @@ -0,0 +1,19 @@ +<?php +class movio_modules_thesaurus_models_GenericTermVO extends movio_modules_thesaurus_models_TermVO +{ + public $url; + public $note; + + public static function createFromAr($ar) + { + $vo = new self; + $vo->__id = $ar->getId(); + $vo->term = $ar->term; + $vo->type = movio_modules_thesaurus_models_TermTypeEnum::GENERIC; + $vo->parentId = $ar->parentId; + $vo->dictionaryId = $ar->dictionaryId; + $vo->url = $ar->url; + $vo->note = $ar->note; + return $vo; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/models/GeographicalTermVO.php b/src/application/classes/movio/modules/thesaurus/models/GeographicalTermVO.php new file mode 100644 index 0000000..7f9efbb --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/models/GeographicalTermVO.php @@ -0,0 +1,17 @@ +<?php +class movio_modules_thesaurus_models_GeographicalTermVO extends movio_modules_thesaurus_models_TermVO +{ + public $geo; + + public static function createFromAr($ar) + { + $vo = new self; + $vo->__id = $ar->getId(); + $vo->term = $ar->term; + $vo->type = movio_modules_thesaurus_models_TermTypeEnum::GEOGRAPHICAL; + $vo->parentId = $ar->parentId; + $vo->dictionaryId = $ar->dictionaryId; + $vo->geo = $ar->geo; + return $vo; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/models/Term.xml b/src/application/classes/movio/modules/thesaurus/models/Term.xml new file mode 100644 index 0000000..aead8a3 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/models/Term.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="movio.modules.thesaurus.models.Term" model:usePrefix="true" model:type="document"> + + <model:Define> + <model:Field name="term" type="string" length="255" index="true" /> + <model:Field name="type" type="string" length="255" index="true" /> + <model:Field name="parentId" type="int" index="true" /> + <model:Field name="dictionaryId" type="int" index="true" /> + <model:Field name="url" type="string" length="255" index="true" /> + <model:Field name="note" type="text" index="true" /> + <model:Field name="geo" type="string" length="255" index="true" /> + <model:Field name="dateFrom" type="date" index="true" /> + <model:Field name="dateTo" type="date" index="true" /> + </model:Define> +</model:Model> \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/models/TermFactory.php b/src/application/classes/movio/modules/thesaurus/models/TermFactory.php new file mode 100644 index 0000000..8262be7 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/models/TermFactory.php @@ -0,0 +1,44 @@ +<?php +class movio_modules_thesaurus_models_TermFactory +{ + public static function createTermFromId($termId) + { + $ar = org_glizy_ObjectFactory::createModel('movio.modules.thesaurus.models.Term'); + $ar->load($termId); + return self::createTermFromAr($ar); + } + + public static function createTermFromAr($ar) + { + switch ($ar->type) { + case movio_modules_thesaurus_models_TermTypeEnum::GENERIC: + return movio_modules_thesaurus_models_GenericTermVO::createFromAr($ar); + + case movio_modules_thesaurus_models_TermTypeEnum::GEOGRAPHICAL: + return movio_modules_thesaurus_models_GeographicalTermVO::createFromAr($ar); + + case movio_modules_thesaurus_models_TermTypeEnum::CHRONOLOGIC: + return movio_modules_thesaurus_models_ChronologicTermVO::createFromAr($ar); + } + } + + public static function createTermFromType($type) + { + switch ($type) { + case movio_modules_thesaurus_models_TermTypeEnum::GENERIC: + $termVO = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.GenericTermVO'); + break; + + case movio_modules_thesaurus_models_TermTypeEnum::GEOGRAPHICAL: + $termVO = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.GeographicalTermVO'); + break; + + case movio_modules_thesaurus_models_TermTypeEnum::CHRONOLOGIC: + $termVO = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.ChronologicTermVO'); + break; + } + + $termVO->type = $type; + return $termVO; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/models/TermTypeEnum.php b/src/application/classes/movio/modules/thesaurus/models/TermTypeEnum.php new file mode 100644 index 0000000..27cd4d7 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/models/TermTypeEnum.php @@ -0,0 +1,16 @@ +<?php +class movio_modules_thesaurus_models_TermTypeEnum +{ + const GENERIC = 'generic'; + const GEOGRAPHICAL = 'geographical'; + const CHRONOLOGIC = 'chronologic'; + + static public function getTypes() + { + return array( + self::GENERIC, + self::GEOGRAPHICAL, + self::CHRONOLOGIC + ); + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/models/TermVO.php b/src/application/classes/movio/modules/thesaurus/models/TermVO.php new file mode 100644 index 0000000..172ec27 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/models/TermVO.php @@ -0,0 +1,39 @@ +<?php +class movio_modules_thesaurus_models_TermVO +{ + public $__id; + public $term; + public $type; + public $parentId; + public $dictionaryId; + + public function getId() + { + return $this->__id; + } + + public static function createFromAr($ar) + { + $vo = new self; + $vo->__id = $ar->getId(); + $vo->term = $ar->term; + $vo->type = $ar->type; + $vo->parentId = $ar->parentId; + $vo->dictionaryId = $ar->dictionaryId; + return $vo; + } + + public function setFromObject($data) + { + foreach ($data as $k => $v) { + // remove the system values + if (strpos($k, 'pageEdit_command') === 0) continue; + $this->$k = $v; + } + } + + public function setDictionaryId($dictionaryId) + { + $this->dictionaryId = $dictionaryId; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/models/proxy/ThesaurusProxy.php b/src/application/classes/movio/modules/thesaurus/models/proxy/ThesaurusProxy.php new file mode 100644 index 0000000..0ddbe48 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/models/proxy/ThesaurusProxy.php @@ -0,0 +1,249 @@ +<?php +class movio_modules_thesaurus_models_proxy_ThesaurusProxy extends GlizyObject +{ + public function addDictionary($name, $type) + { + $ar = org_glizy_ObjectFactory::createModel('movio.modules.thesaurus.models.Dictionary'); + $ar->title = $name; + $ar->type = $type; + try { + $ar->save(null, false, 'PUBLISHED'); + } catch (movio_modules_thesaurus_Exception $e) { + throw movio_modules_thesaurus_Exception::dictionaryCreationError($name); + } + + return $ar; + } + + public function getTypeByDictionaryId($dictionaryId) + { + $ar = org_glizy_objectFactory::createModel('movio.modules.thesaurus.models.Dictionary'); + $ar->load($dictionaryId); + return $ar->type ?: movio_modules_thesaurus_models_TermTypeEnum::GENERIC; + } + + public function getAllDictionaries() + { + $results = array(); + $it = org_glizy_ObjectFactory::createModelIterator('movio.modules.thesaurus.models.Dictionary') + ->orderBy('title'); + foreach ($it as $ar) { + $results[] = movio_modules_thesaurus_models_DictionaryVO::createFromAr($ar); + } + + return $results; + } + + public function getTermVO($type) + { + return movio_modules_thesaurus_models_TermFactory::createTermFromType($type); + } + + public function saveTerm($termVO) + { + if (!in_array($termVO->type, movio_modules_thesaurus_models_TermTypeEnum::getTypes())) { + throw movio_modules_thesaurus_Exception::termWrongType($termVO->type); + } + $ar = org_glizy_ObjectFactory::createModel('movio.modules.thesaurus.models.Term'); + + if ($termVO->getId()) { + $ar->load($termVO->getId()); + } + + foreach ($termVO as $k => $v) { + $ar->$k = $v; + } + + try { + $ar->save(null, false, 'PUBLISHED'); + } catch (movio_modules_thesaurus_Exception $e) { + throw movio_modules_thesaurus_Exception::termCreationError($termVO->term); + } + + return $ar; + } + + public function loadTerm($termId) + { + return movio_modules_thesaurus_models_TermFactory::createTermFromId($termId); + } + + public function getFirstLevelChildrens($dictionaryId, $parentId=0) + { + $results = array(); + //if ($parentId) { + $it = org_glizy_ObjectFactory::createModelIterator('movio.modules.thesaurus.models.Term') + ->where('dictionaryId', $dictionaryId) + ->where('parentId', $parentId); + /*} else { + $it = org_glizy_ObjectFactory::createModelIterator('movio.modules.thesaurus.models.Term') + ->where('dictionaryId', $dictionaryId); + }*/ + $it->orderBy('term'); + foreach ($it as $ar) { + $results[] = movio_modules_thesaurus_models_TermFactory::createTermFromAr($ar); + } + return $results; + } + + public function getDictionaryById($dictionaryId) + { + $ar = org_glizy_objectFactory::createModel('movio.modules.thesaurus.models.Dictionary'); + $ar->load($dictionaryId); + return movio_modules_thesaurus_models_DictionaryVO::createFromAr($ar); + } + + public function getAllTerms($dictionaryId) + { + $results = array(); + $it = org_glizy_ObjectFactory::createModelIterator('movio.modules.thesaurus.models.Term') + ->where('dictionaryId', $dictionaryId) + ->orderBy('term'); + + foreach ($it as $ar) { + $results[] = movio_modules_thesaurus_models_TermFactory::createTermFromAr($ar); + } + + return $results; + } + + public function deleteTerm($termId) + { + $ar = org_glizy_ObjectFactory::createModel('movio.modules.thesaurus.models.Term'); + $ar->load($termId); + + $childrens = $this->getFirstLevelChildrens($ar->dictionaryId, $termId); + + foreach ($childrens as $child) { + $this->deleteTerm($child->getId()); + } + + $ar->delete(); + } + + public function deleteDictionary($dictionaryId) + { + $ar = org_glizy_ObjectFactory::createModel('movio.modules.thesaurus.models.Dictionary'); + $ar->delete($dictionaryId); + + $it = org_glizy_ObjectFactory::createModelIterator('movio.modules.thesaurus.models.Term') + ->where('dictionaryId', $dictionaryId); + + foreach ($it as $ar) { + $ar->delete(); + } + } + + public function searchTerm($term) + { + return $this->findTerm(null, null, null, $term); + } + + // metodo per selectfrom + public function findTerm($fieldName, $model, $query, $term, $proxyParams = null) + { + $it = org_glizy_ObjectFactory::createModelIterator('movio.modules.thesaurus.models.Term') + ->where('term', '%'.$term.'%', 'ILIKE'); + + if ($proxyParams) { + foreach ($proxyParams as $k => $v) { + $it->where($k, $v); + } + } + + $result = array(); + + foreach ($it as $ar) { + // TODO ottimizzare in una query sola + $ar1 = org_glizy_ObjectFactory::createModel('movio.modules.thesaurus.models.Term'); + $ar1->load($ar->parentId); + + $ar2 = org_glizy_ObjectFactory::createModel('movio.modules.thesaurus.models.Term'); + $ar2->load($ar1->parentId); + + $ar3 = org_glizy_ObjectFactory::createModel('movio.modules.thesaurus.models.Term'); + $ar3->load($ar2->parentId); + + $path = array($ar3->term, $ar2->term, $ar1->term); + + $result[] = array( + 'id' => $ar->getId(), + 'text' => $ar->term, + 'path' => ltrim(implode('/', $path), '/') + ); + } + + return $result; + } + + public function moveTerm($termId, $newParentId) + { + $ar = org_glizy_ObjectFactory::createModel('movio.modules.thesaurus.models.Term'); + $ar->load($termId); + $ar->parentId = $newParentId; + $ar->save(); + } + + // restituisce i documenti che hanno taggato il termine con id uguale a termId + public function getDocumentsWithTerm($termId) + { + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $entityTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $entityResolver = org_glizy_objectFactory::createObject('movio.modules.ontologybuilder.EntityResolver'); + $menuMap = array(); + + // TODO: non va bene l'implementazione perché scorre tutti i documenti + // eseguire un filtro sui documenti del tipo di entità che ha una campo di tipo dizionario + $it = org_glizy_ObjectFactory::createModelIterator('movio.modules.ontologybuilder.models.EntityDocument') + ->load('All'); + + $result = array(); + foreach ($it as $ar) { + $entityTypeId = $entityTypeService->getEntityTypeId($ar->getType()); + if (!isset($menuMap[$entityTypeId])) { + $arMenu = $entityResolver->getMenuVisibleEntity($entityTypeId); + $menuMap[$entityTypeId] = $arMenu; + } else { + $arMenu = $menuMap[$entityTypeId]; + } + + $thesaurusAttribute = $entityTypeService->getAttributeByType($entityTypeId, 'attribute.thesaurus'); + $descriptionAttribute = $entityTypeService->getDescriptionAttribute($entityTypeId); + // se l'entità di questo documento ha un campo di tipo thesaurus + if ($arMenu && $thesaurusAttribute) + { + $thesaurusAttribute = $this->prepareThesaurusAttribute($thesaurusAttribute); + foreach ($thesaurusAttribute as $attribute) { + if ($ar->keyInDataExists($attribute)) { + if (!is_array($ar->$attribute)) continue; + // si cerca nei tag il termine con id uguale a termId + foreach ($ar->$attribute as $term) { + if ($term->id == $termId) { + $document_id = $ar->getId(); + $result[] = array( + 'id' => $document_id, + 'title' => $ar->title, + 'description' => glz_strtrim(($descriptionAttribute && $ar->keyInDataExists($descriptionAttribute)) ? $ar->$descriptionAttribute : '', 300), + 'url' => __Routing::makeUrl('showEntityDetail', array('pageId' => $arMenu->id, 'entityTypeId' => $entityTypeId,'document_id' => $document_id)) + ); + break; + } + } + } + } + } + } + return $result; + } + + private function prepareThesaurusAttribute($thesaurusAttribute) + { + if (!is_array($thesaurusAttribute)) { + $result[] = $thesaurusAttribute; + return $result; + } else { + return $thesaurusAttribute; + } + } + +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/static/FormatThesaurusSelectFrom.js b/src/application/classes/movio/modules/thesaurus/static/FormatThesaurusSelectFrom.js new file mode 100644 index 0000000..d943233 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/static/FormatThesaurusSelectFrom.js @@ -0,0 +1,7 @@ +function formatThesaurusSelection(data) { + return data.text+'<br><small>'+data.path+'</small>'; +} + +function formatThesaurusResult(data) { + return data.text +'<br><small>'+data.path+'</small>'; +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/views/Admin.xml b/src/application/classes/movio/modules/thesaurus/views/Admin.xml new file mode 100644 index 0000000..2d82277 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/views/Admin.xml @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + xmlns:cmp="movio.modules.thesaurus.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Popup.php" + controllerName="movio.modules.thesaurus.controllers.*"> + <glz:Import src="_common.xml" /> + <glz:JSscript folder="movio.modules.thesaurus.js" /> + + <mvc:State name="index"> + <glz:Modifier target="Page" attribute="templateFileName" value="Page.php" /> + + <glz:DataProvider id="dp" recordClassName="movio.modules.thesaurus.models.Dictionary" orderBy="title"/> + <glz:DataGrid id="dataGrid" label="{i18n: Elenco utenti}" dataProvider="{dp}" tableCssClass="table table-striped table-bordered" cssClass="odd,even" controller="{dataGridEdit}" orderStyle="BLACK"> + <glz:DataGridColumn columnName="title" headerText="{i18n:GLZ_USER_FIRST}" /> + <glz:DataGridColumn columnName="type" headerText="{i18n:Type}" renderCell="movio.modules.thesaurus.views.renderer.CellType"/> + <glz:DataGridColumn columnName="document_id" align="right" width="80" renderCell="movio.modules.thesaurus.views.renderer.CellEditDelete" /> + </glz:DataGrid> + <glz:Link label="{i18n:Create dictionary}" cssClass="{config:glizycms.form.actionLink.cssClass}" icon="icon-plus" url="movio_thesaurus/createDictionary" editableRegion="actions" acl="*,new"/> + </mvc:State> + + <mvc:State name="editDictionary"> + <glz:Modifier target="Page" attribute="templateFileName" value="Page.php" /> + <glz:Modifier target="pageTitle" attribute="visible" value="false" /> + <cmp:DictionaryTreeView id="treeview" title="{i18n:Dictionary structure}" addLabel="{i18n:Add term}" editableRegion="treeview" controllerName="movio.modules.thesaurus.controllers.treeview.*" /> + <cmp:TermEdit id="pageEdit" mode="container" /> + </mvc:State> + + <mvc:State name="deleteDictionary"> + <glz:Modifier target="Page" attribute="templateFileName" value="Page.php" /> + <glz:Modifier target="pageTitle" attribute="visible" value="false" /> + </mvc:State> + + <mvc:State name="createDictionary"> + <glz:Modifier target="Page" attribute="templateFileName" value="Page.php" /> + <cms:FormEdit id="dictionaryForm" controllerName="movio.modules.thesaurus.controllers.dictionaryEdit.*"> + <glz:Input id="title" label="{i18n:Dictionary name}" size="90" required="true" /> + <glz:List id="type" label="{i18n:Type}"> + <glz:ListItem value="{i18n:Generic}" key="generic" /> + <glz:ListItem value="{i18n:Geographical}" key="geographical" /> + <glz:ListItem value="{i18n:Chronologic}" key="chronologic" /> + </glz:List> + + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=add" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="add"> + <cms:FormEdit id="myForm" controllerName="movio.modules.thesaurus.controllers.termEdit.*"> + <cms:pageTitleModifier action="add" label="{i18n:Add a new term}" new="true" /> + + <glz:Hidden id="dictionaryId" /> + <glz:Hidden id="type" /> + <glz:Input id="term" label="{i18n:Term}" size="90" required="true" /> + <!--glz:List id="type" label="{i18n:Type}"> + <glz:ListItem value="{i18n:Generic}" key="generic" /> + <glz:ListItem value="{i18n:Geographical}" key="geographical" /> + <glz:ListItem value="{i18n:Chronologic}" key="chronologic" /> + </glz:List --> + <cmp:SelectTerm id="parentId" label="{i18n:Parent}" size="90" emptyValue="-" /> + <glz:Panel id="genericPanel" > + <glz:Input id="url" label="{i18n:Term source}" size="90" data="type=url" /> + <glz:Input id="note" label="{i18n:Scope note}" size="90" type="multiline" rows="10" cols="70" htmlEditor="true" data="type=tinymce" /> + </glz:Panel> + <glz:Panel id="geographicalPanel"> + <glz:Input id="geo" label="{i18n:Address}" size="90" data="type=googlemaps"/> + </glz:Panel> + <glz:Panel id="chronologicPanel"> + <glz:Input id="dateFrom" label="{i18n:Data da}" size="90" /> + <glz:Input id="dateTo" label="{i18n:Data a}" size="90" /> + </glz:Panel> + + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=add" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="edit" label="{i18n:Content}"> + <cmp:TermEdit id="pageEdit" mode="edit" controllerName="movio.modules.thesaurus.controllers.termEdit.*"> + <cms:pageTitleModifier action="edit" label="{i18n:Edit term}" field="__title" /> + + <glz:Hidden id="dictionaryId" /> + <glz:Hidden id="type" /> + <glz:Hidden id="__id"/> + <glz:Input id="term" label="{i18n:Term}" size="90" required="true" /> + <!--glz:List id="type" label="{i18n:Type}" disabled="true"> + <glz:ListItem value="{i18n:Generic}" key="generic" /> + <glz:ListItem value="{i18n:Geographical}" key="geographical" /> + <glz:ListItem value="{i18n:Chronologic}" key="chronologic" /> + </glz:List--> + <cmp:SelectTerm id="parentId" label="{i18n:Parent}" size="90" emptyValue="-" disabled="true"/> + <glz:Panel id="genericPanel" > + <glz:Input id="url" label="{i18n:Term source}" size="90" data="type=url"/> + <glz:Input id="note" label="{i18n:Scope note}" size="90" type="multiline" rows="10" cols="70" htmlEditor="true" data="type=tinymce" /> + </glz:Panel> + <glz:Panel id="geographicalPanel"> + <glz:Input id="geo" label="{i18n:Address}" size="90" data="type=googlemaps"/> + </glz:Panel> + <glz:Panel id="chronologicPanel"> + <glz:Input id="dateFrom" label="{i18n:Data da}" size="90" /> + <glz:Input id="dateTo" label="{i18n:Data a}" size="90" /> + </glz:Panel> + + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <glz:Link id="preview" label="{i18n:GLZ_PREVIEW}" cssClass="btn" visible="false" target="_blank" /> + </cms:FormButtonsPanel> + </cmp:TermEdit> + </mvc:State> +</mvc:Page> \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/views/components/DictionaryList.xml b/src/application/classes/movio/modules/thesaurus/views/components/DictionaryList.xml new file mode 100644 index 0000000..3723d87 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/views/components/DictionaryList.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<m:DictionaryListCmp + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="movio.modules.thesaurus.views.components.*"> + + <m:SelectDictionary id="dictionaryId" label="{i18n:Select dictionary}" size="90" required="true"/> + +</m:DictionaryListCmp> diff --git a/src/application/classes/movio/modules/thesaurus/views/components/DictionaryListCmp.php b/src/application/classes/movio/modules/thesaurus/views/components/DictionaryListCmp.php new file mode 100644 index 0000000..88d36a4 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/views/components/DictionaryListCmp.php @@ -0,0 +1,89 @@ +<?php +class movio_modules_thesaurus_views_components_DictionaryListCmp extends org_glizy_components_ComponentContainer +{ + + private $type; + + function process() { + $dictionaryId = $this->loadContent($this->getId().'-dictionaryId'); + parent::process(); + if (!$this->_application->isAdmin()) { + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $this->type = $thesaurusProxy->getTypeByDictionaryId($dictionaryId); + $this->_content = array('type' => $this->type, 'records' => array()); + $this->readTermsList($dictionaryId, $this->type); + } + } + + function process_ajax() + { + $c = $this->getRootComponent(); + $c->process(); + $content = $this->stripIdFromContent(parent::getContent()); + $timeline = array( 'date' => array(), + 'type' => 'default', + ); + $num = count($content['records']); + if ($this->type == 'chronologic') { + for ($i=0; $i < $num; $i++) { + $term = $content['records'][$i]['term']; + $temp = array('headline' => '', 'text' => '', 'asset' => array('media' => '', 'caption' => '', 'credit' => '')); + $temp['headline'] = $term->term; + if ($term->dateFrom) $temp['startDate'] = $this->formatDate($term->dateFrom); + if ($term->dateTo) $temp['endDate'] = $this->formatDate($term->dateTo); + $temp['text'] = ''; + foreach($content['records'][$i]['taggedDocuments'] as $doc) { + $temp['text'] = __Link::makeSimpleLink($doc['title'], $doc['url']).'<br/>'; + } + $timeline['date'][] = $temp; + } + } + + return array('timeline' => $timeline); + } + + + function render($mode) { + if (!$this->_application->isAdmin()) { + $this->setAttribute('skin', 'DictionaryList.html'); + } + parent::render($mode); + } + + + private function readTermsList($dictionaryId) + { + if ($dictionaryId) { + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $terms = $thesaurusProxy->getAllTerms($dictionaryId); + foreach ($terms as $term) { + $taggedDocuments = $thesaurusProxy->getDocumentsWithTerm($term->getId()); + if ($taggedDocuments) { + $this->_content['records'][] = array ( + 'term' => $term, + 'taggedDocuments' => $taggedDocuments + ); + } + } + } + + if ($this->type == 'geographical') { + $this->_content['records'] = json_encode($this->_content['records']); + } else if ($this->type == 'chronologic') { + + $this->_content['source'] = GLZ_HOST.'/'.$this->getAjaxUrl().'&.json'; + $this->_content['font'] = 'PT'; + $this->_content['lang'] = $this->_application->getLanguage(); + } + } + + // NOTE: codice uguale al componente timeline + private function formatDate($date) + { + $date = preg_replace('/^(\d{1,2})\/(\d{1,2})\/(-?\d{2,4})$/', '$3/$2/$1', $date); + $date = preg_replace('/^(\d{1,2})\/(-?\d{2,4})$/', '$2', $date); + $date = preg_replace('/^(-?\d{2,4})$/', '$1', $date); + $date = str_replace('-', ',', $date); + return str_replace('/', ',', $date); + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/views/components/DictionaryTreeView.php b/src/application/classes/movio/modules/thesaurus/views/components/DictionaryTreeView.php new file mode 100644 index 0000000..2d005c9 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/views/components/DictionaryTreeView.php @@ -0,0 +1,43 @@ +<?php +class movio_modules_thesaurus_views_components_DictionaryTreeView extends org_glizycms_contents_views_components_SiteTreeView +{ + private $dictionaryId; + public function process() { + $this->_content = new org_glizycms_contents_views_components_SiteTreeViewVO(); + $this->dictionaryId = __Request::get('dictionaryId'); + $this->_content->addLabel = $this->getAttribute('addLabel'); + $this->_content->title = $this->getAttribute('title'); + $this->_content->ajaxUrl = $this->getAjaxUrl(); + $this->_content->addUrl = __Routing::makeUrl('linkChangeAction', + array('action' => 'add'), + array('dictionaryId' => $this->dictionaryId) + ); + } + + public function getAjaxUrl() + { + return 'ajax.php?pageId='.$this->_application->getPageId().'&ajaxTarget='.$this->getId().'&dictionaryId='.$this->dictionaryId.'&action='; + } +} + +class movio_modules_thesaurus_views_components_DictionaryTreeView_render extends org_glizycms_contents_views_components_SiteTreeView_render +{ + function getDefaultSkin() + { + $skin = <<<EOD +<div id="treeview"> + <div id="treeview-title"> + <a id="js-glizycmsSiteTreeAdd" tal:attributes="href Component/addUrl"><i class="icon-plus"></i> <span tal:omit-tag="" tal:content="Component/addLabel" /></a> + <h3 tal:content="Component/title"></h3> + </div> + <div id="treeview-inner"> + <div id="js-glizycmsSiteTree" tal:attributes="data-ajaxurl Component/ajaxUrl"></div> + </div> + <div id="openclose"> + <i class="icon-chevron-left"></i> + </div> +</div> +EOD; + return $skin; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/views/components/SelectDictionary.php b/src/application/classes/movio/modules/thesaurus/views/components/SelectDictionary.php new file mode 100755 index 0000000..614e892 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/views/components/SelectDictionary.php @@ -0,0 +1,27 @@ +<?php +class movio_modules_thesaurus_views_components_SelectDictionary extends org_glizy_components_List +{ + function process() + { + $this->_content = $this->_parent->loadContent($this->getId()); + if (!$this->_content) { + $this->_content = $this->getAttribute('value'); + } + + $this->_items = array(); + if ($this->_application->isAdmin()) { + $this->addItem( '', '-' ); + $this->getItems(); + } + } + + + function getItems() + { + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $dictionaries = $thesaurusProxy->getAllDictionaries(); + foreach ($dictionaries as $dictionary) { + $this->addItem( $dictionary->getId(), $dictionary->title ); + } + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/views/components/SelectTerm.php b/src/application/classes/movio/modules/thesaurus/views/components/SelectTerm.php new file mode 100755 index 0000000..cd57c5a --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/views/components/SelectTerm.php @@ -0,0 +1,53 @@ +<?php +class movio_modules_thesaurus_views_components_SelectTerm extends org_glizy_components_List +{ + protected $dictionaryId; + + function init() + { + // define the custom attributes + $this->defineAttribute('value', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('emptyValue', false, 0, COMPONENT_TYPE_INTEGER); + // $this->defineAttribute('emptyValueKey', false, 0, COMPONENT_TYPE_INTEGER); + + // call the superclass for validate the attributes + parent::init(); + } + + + function process() + { + $this->dictionaryId = __Request::get('dictionaryId'); + + $this->_content = $this->_parent->loadContent($this->getId()); + if (!$this->_content) { + $this->_content = $this->getAttribute('value'); + } + + $this->_items = array(); + if ($this->_application->isAdmin()) { + if (!is_null($this->getAttribute('emptyValue'))) { + $this->addItem( $this->dictionaryId, html_entity_decode( $this->getAttributeString('emptyValue') ) ); + } + + $this->getItems(); + } + } + + + function getItems() + { + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $this->getChildren($thesaurusProxy, $this->dictionaryId); + } + + function getChildren($thesaurusProxy, $parentId, $level=0) + { + $childrens = $thesaurusProxy->getFirstLevelChildrens($this->dictionaryId, $parentId); + foreach ($childrens as $child) { + $pad = str_repeat('. ', $level); + $this->_items[] = array('key' => $child->getId(), 'value' => $pad.$child->term, 'selected' => $child->getId() == $this->_content ? 1 : 0); + $this->getChildren($thesaurusProxy, $child->getId(), $level+1); + } + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/views/components/ShowTaggedContents.php b/src/application/classes/movio/modules/thesaurus/views/components/ShowTaggedContents.php new file mode 100755 index 0000000..fd7d5f5 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/views/components/ShowTaggedContents.php @@ -0,0 +1,33 @@ +<?php +class movio_modules_thesaurus_views_components_ShowTaggedContents extends org_glizy_components_ComponentContainer +{ + function process() + { + $this->_content = array(); + $termId = __Request::get('termId'); + if ($termId) { + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $term = $thesaurusProxy->loadTerm($termId); + $this->_content = $thesaurusProxy->getDocumentsWithTerm($termId); + } + } +} + +class movio_modules_thesaurus_views_components_ShowTaggedContents_render extends org_glizy_components_render_Render +{ + function getDefaultSkin() + { + $skin = <<<EOD +<div class="results-content" tal:condition="php: count(Component)"> + <div class="item clearfix" tal:repeat="item Component"> + <h1><a tal:attributes="href item/url; title item/title" tal:content="structure item/title"></a></h1> + <p tal:condition="item/description" tal:content="structure item/description" /> + </div> +</div> +<span tal:omit-tag="" tal:condition="php: empty(Component)"> + <p tal:content="php:__Tp('MW_NO_RECORD_FOUND')"></p> +</span> +EOD; + return $skin; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/views/components/TermEdit.php b/src/application/classes/movio/modules/thesaurus/views/components/TermEdit.php new file mode 100644 index 0000000..2ae4ac0 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/views/components/TermEdit.php @@ -0,0 +1,63 @@ +<?php +class movio_modules_thesaurus_views_components_TermEdit extends org_glizycms_views_components_FormEdit +{ + protected $emptySrc; + protected $editSrc; + protected $_pageTypeObj; + + /** + * Init + * + * @return void + * @access public + */ + public function init() + { + $this->defineAttribute('mode', false, 'container', COMPONENT_TYPE_STRING); + $this->defineAttribute('initialState', false, 'empty', COMPONENT_TYPE_STRING); + $this->defineAttribute('editState', false, 'edit', COMPONENT_TYPE_STRING); + $this->defineAttribute('editUrl', false, __Config::get('glizycms.speakingUrl'), COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:cssClass', false, __Config::get('glizy.formElement.admCssClass'), COMPONENT_TYPE_STRING); + // call the superclass for validate the attributes + parent::init(); + } + + + public function process() { + if ($this->getAttribute('mode')=='container') { + $this->emptySrc = __Routing::makeUrl('linkChangeAction', array( 'action' => $this->getAttribute('initialState'))); + $this->editSrc = __Routing::makeUrl('linkChangeAction', array( 'action' => $this->getAttribute('editState'))).'?dictionaryId='.__Request::get('dictionaryId').'&termId='; + } else { + $termId = __Request::get('termId'); + $thesaurusProxy = org_glizy_ObjectFactory::createObject('movio.modules.thesaurus.models.proxy.ThesaurusProxy'); + $termVo = $thesaurusProxy->loadTerm($termId); + $this->setData($termVo); + + parent::process(); + } + } + + public function render_html_onStart() + { + if ($this->getAttribute('mode')=='container') { + + $this->addOutputCode('<iframe id="js-glizycmsPageEdit" src="" data-emptysrc="'.$this->emptySrc.'" data-editsrc="'.$this->editSrc.'"></iframe>'); + + $corePath = __Paths::get('CORE'); + $jQueryPath = $corePath.'classes/org/glizycms/js/jquery/'; + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'jquery.pnotify/jquery.pnotify.min.js' ) ); + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'jquery.pnotify/jquery.pnotify.default.css' ) ); + + } else { + $this->addOutputCode('<div id="message-box"></div>'); + parent::render_html_onStart(); + } + } + + public function render_html_onEnd($value='') + { + if ($this->getAttribute('mode')!='container') { + parent::render_html_onEnd(); + } + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/thesaurus/views/renderer/CellEditDelete.php b/src/application/classes/movio/modules/thesaurus/views/renderer/CellEditDelete.php new file mode 100644 index 0000000..8bf5444 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/views/renderer/CellEditDelete.php @@ -0,0 +1,50 @@ +<?php +class movio_modules_thesaurus_views_renderer_CellEditDelete extends org_glizycms_contents_views_renderer_AbstractCellEdit +{ + + function renderCell($key, $value, $row) + { + $this->loadAcl($value); + $output = $this->renderEditButton($value, $row). + $this->renderDeleteButton($value, $row); + return $output; + } + + + protected function renderEditButton($key, $row) + { + $output = ''; + + if ($this->canView && $this->canEdit) { + $output = __Link::makeLinkWithIcon( 'actionsMVC', + 'icon-pencil btn-icon', + array( + 'title' => __T('GLZ_RECORD_EDIT'), + 'action' => 'editDictionary'), + NULL, + array('dictionaryId' => $key)); + } + + return $output; + } + + protected function renderDeleteButton($key, $row) + { + + $output = ''; + if ($this->canView && $this->canDelete) { + $output .= __Link::makeLinkWithIcon( 'actionsMVC', + 'icon-trash btn-icon', + array( + 'title' => __T('GLZ_RECORD_DELETE'), + 'action' => 'deleteDictionary' ), + __T('GLZ_RECORD_MSG_DELETE'), + array('dictionaryId' => $key)); + } + + return $output; + } + +} + + diff --git a/src/application/classes/movio/modules/thesaurus/views/renderer/CellType.php b/src/application/classes/movio/modules/thesaurus/views/renderer/CellType.php new file mode 100644 index 0000000..07af237 --- /dev/null +++ b/src/application/classes/movio/modules/thesaurus/views/renderer/CellType.php @@ -0,0 +1,9 @@ +<?php +class movio_modules_thesaurus_views_renderer_CellType extends org_glizycms_contents_views_renderer_AbstractCellEdit +{ + + function renderCell($key, $value, $row) + { + return __T( ucfirst($value) ); + } +} diff --git a/src/application/classes/movio/modules/touristoperators/Module.php b/src/application/classes/movio/modules/touristoperators/Module.php new file mode 100644 index 0000000..f371567 --- /dev/null +++ b/src/application/classes/movio/modules/touristoperators/Module.php @@ -0,0 +1,21 @@ +<?php +class movio_modules_touristoperators_Module +{ + static function registerModule() + { + $moduleVO = org_glizy_Modules::getModuleVO(); + $moduleVO->id = 'movio_touristoperators'; + $moduleVO->name = __T('Tourist Operators'); + $moduleVO->description = ''; + $moduleVO->version = '1.0.0'; + $moduleVO->classPath = 'movio.modules.touristoperators'; + $moduleVO->pageType = 'movio.modules.touristoperators.views.FrontEnd'; + $moduleVO->author = 'META srl'; + $moduleVO->authorUrl = 'http://www.gruppometa.it'; + $moduleVO->pluginUrl = 'http://movio.beniculturali.it'; + $moduleVO->siteMapAdmin = '<glz:Page pageType="movio.modules.touristoperators.views.Admin" id="movio_touristoperators" value="{i18n:Tourist Operators}" icon="icon-circle-blank" />'; + $moduleVO->showInOntologyBuilder = true; + + org_glizy_Modules::addModule( $moduleVO ); + } +} diff --git a/src/application/classes/movio/modules/touristoperators/UrlResolver.php b/src/application/classes/movio/modules/touristoperators/UrlResolver.php new file mode 100644 index 0000000..0bb5046 --- /dev/null +++ b/src/application/classes/movio/modules/touristoperators/UrlResolver.php @@ -0,0 +1,18 @@ +<?php +class movio_modules_touristoperators_UrlResolver extends org_glizycms_speakingUrl_AbstractDocumentResolver implements org_glizycms_speakingUrl_IUrlResolver +{ + public function __construct() + { + parent::__construct(); + $this->type = 'movio.modules.touristoperators'; + $this->protocol = 'movioTouristOperators:'; + $this->model = 'movio.modules.touristoperators.models.Model'; + $this->pageType = 'movio.modules.touristoperators.views.FrontEnd'; + $this->modelName = __T('movio.modules.touristoperators.views.FrontEnd'); + } + + public function compileRouting($ar) + { + return ''; + } +} diff --git a/src/application/classes/movio/modules/touristoperators/config/routing.xml b/src/application/classes/movio/modules/touristoperators/config/routing.xml new file mode 100644 index 0000000..d6f5c30 --- /dev/null +++ b/src/application/classes/movio/modules/touristoperators/config/routing.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Routing> + <glz:Route name="movio_touristoperators" value="{pageId=movio.modules.touristoperators.views.FrontEnd}/{static=action=show}/{integer=document_id}/{value=title}" /> +</glz:Routing> \ No newline at end of file diff --git a/src/application/classes/movio/modules/touristoperators/controllers/Index.php b/src/application/classes/movio/modules/touristoperators/controllers/Index.php new file mode 100644 index 0000000..077f6f6 --- /dev/null +++ b/src/application/classes/movio/modules/touristoperators/controllers/Index.php @@ -0,0 +1,24 @@ +<?php +class movio_modules_touristoperators_controllers_Index extends org_glizy_mvc_core_Command +{ + public function execute() + { + $data = $this->view->getContent(); + if (!$data->visualization) { + $data->visualization = 'list'; + } + + $this->setComponentsAttribute('filters', 'enabled', $data->showForm == 'true' + && ($data->showFulltext + || $data->showType + || $data->showCountry + || $data->showDistrict + || $data->showPlace)); + $this->setComponentsAttribute('filterTitle', 'enabled', $data->showFulltext); + $this->setComponentsAttribute('filterType', 'enabled', $data->showType); + $this->setComponentsAttribute('filterCountry', 'enabled', $data->showCountry); + $this->setComponentsAttribute('filterDistrict', 'enabled', $data->showDistrict); + $this->setComponentsAttribute('filterPlace', 'enabled', $data->showPlace); + $this->setComponentsAttribute($data->visualization, 'enabled', true); + } +} diff --git a/src/application/classes/movio/modules/touristoperators/models/Model.xml b/src/application/classes/movio/modules/touristoperators/models/Model.xml new file mode 100644 index 0000000..291abfe --- /dev/null +++ b/src/application/classes/movio/modules/touristoperators/models/Model.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="movio.modules.touristoperators" model:usePrefix="true" model:type="document"> + + + <model:Define> + <!-- system --> + <model:Field name="url" type="string" index="false" /> + <model:Field name="title" type="string" length="255" index="true" /> + <model:Field name="fulltext" type="string" index="fulltext" /> + + <!-- custom --> + <model:Field name="type" type="string" length="255" index="true" /> + <model:Field name="country" type="string" length="255" index="true" /> + <model:Field name="district" type="string" length="255" index="true" /> + <model:Field name="place" type="string" length="255" index="true" /> + <model:Field name="description" type="text" /> + <model:Field name="locations" type="multivalues" /> + <model:Field name="coordinates" type="string" validator="notnull" /> + <model:Field name="externalUrl" type="string" /> + <model:Field name="image" type="object" readFormat="false" /> + <model:Field name="images" type="object" readFormat="false" /> + <model:Field name="attaches" type="object" readFormat="false" /> + </model:Define> + + <model:Script parent="model"> + <![CDATA[ +function loadFromArray($values, $useSet=false) +{ + parent::loadFromArray($values, $useSet); + if (!property_exists($this->data, 'images') && property_exists($this->data, 'image')) { + $this->data->images = new StdClass; + $this->data->images->image = array($this->data->image); + $this->data->image = null; + } +} + ]]> + </model:Script> +</model:Model> \ No newline at end of file diff --git a/src/application/classes/movio/modules/touristoperators/views/Admin.xml b/src/application/classes/movio/modules/touristoperators/views/Admin.xml new file mode 100644 index 0000000..fb4c81a --- /dev/null +++ b/src/application/classes/movio/modules/touristoperators/views/Admin.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:include + xmlns:cms="org.glizycms.views.components.*" + src="movio.views.TemplateModuleAdmin"> + <glz:template name="model" value="movio.modules.touristoperators.models.Model" /> + <glz:template name="add_label" value="Add tourist operator" /> + + <glz:template name="grid_fields"> + <glz:DataGridColumn columnName="title" headerText="{i18n:Title}" renderCell="org.glizycms.contents.views.renderer.DocumentTitle" /> + <glz:DataGridColumn columnName="type" headerText="{i18n:Type}" /> + <glz:DataGridColumn columnName="externalUrl" headerText="{i18n:Url}" /> + </glz:template> + + <glz:template name="form_fields"> + <glz:Input id="title" label="{i18n:Title}" size="90" required="true" /> + <glz:Input id="type" label="{i18n:Type}" data="type=selectfrom;multiple=false;add_new_values=true;model=movio.modules.touristoperators.models.Model" size="255" /> + <glz:Input id="country" label="{i18n:Country}" data="type=selectfrom;multiple=false;add_new_values=true;model=movio.modules.touristoperators.models.Model" size="255" /> + <glz:Input id="district" label="{i18n:District}" data="type=selectfrom;multiple=false;add_new_values=true;model=movio.modules.touristoperators.models.Model" size="255" /> + <glz:Input id="place" label="{i18n:Place}" data="type=selectfrom;multiple=false;add_new_values=true;model=movio.modules.touristoperators.models.Model" size="255" /> + <glz:Input id="externalUrl" label="{i18n:Url}" type="url"/> + <glz:Input id="description" label="{i18n:Description}" type="multiline" rows="10" cols="70" htmlEditor="true" data="type=tinymce" /> + <glz:Fieldset id="locations" label="{i18n:Locations}" data="type=repeat;collapsable=true"> + <glz:Input id="locationDescription" label="{i18n:Address description}" type="text"/> + <glz:Input id="location" label="{i18n:Address}" type="multiline" rows="5" htmlEditor="true" data="type=tinymce" /> + <glz:Input id="coordinates" label="{i18n:Coordinates}" data="type=googlemaps" /> + </glz:Fieldset> + +<!-- + <glz:Input id="image" label="{i18n:Image}" size="90" data="type=mediapicker;mediaType=IMAGE;preview=true" /> +--> + <glz:Fieldset id="images" label="{i18n:Images}" data="type=repeat;repeatMin=0;repeatMax=5;collapsable=false"> + <glz:Input id="image" label="{i18n:Image}" size="90" data="type=mediapicker;mediatype=IMAGE;preview=true"/> + </glz:Fieldset> + + <glz:Fieldset id="attaches" label="{i18n:Download files}" data="type=repeat;repeatMin=0;repeatMax=5;collapsable=false"> + <glz:Input id="media" label="{i18n:Media}" size="90" data="type=mediapicker;mediatype=ALL;preview=false"/> + </glz:Fieldset> + </glz:template> +</glz:include> \ No newline at end of file diff --git a/src/application/classes/movio/modules/touristoperators/views/FrontEnd.xml b/src/application/classes/movio/modules/touristoperators/views/FrontEnd.xml new file mode 100644 index 0000000..d5c9043 --- /dev/null +++ b/src/application/classes/movio/modules/touristoperators/views/FrontEnd.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + xmlns:t="movio.modules.touristoperators.views.components.*" + controllerName="movio.modules.touristoperators.controllers.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="2cols.php" + adm:editComponents="viewProperties,text"> + + <glz:Import src="Common.xml" /> + + <glz:DataProvider id="ModuleDP" recordClassName="movio.modules.touristoperators.models.Model" order="title" /> + + <mvc:State name="index"> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + + <glz:Panel id="viewProperties" visible="false"> + <glz:List id="showForm" label="{i18n:Show search form}"> + <glz:ListItem key="true" value="{i18n:Yes}"/> + <glz:ListItem key="false" value="{i18n:No}"/> + </glz:List> + <glz:List id="visualization" label="{i18n:Show}" > + <glz:ListItem key="list" value="{i18n:Show list}" /> + <glz:ListItem key="map" value="{i18n:Show map}" /> + </glz:List> + <glz:Checkbox id="showFulltext" label="{i18n:Show fulltext filter}" /> + <glz:Checkbox id="showType" label="{i18n:Show Type filter}" /> + <glz:Checkbox id="showCountry" label="{i18n:Show Country filter}" /> + <glz:Checkbox id="showDistrict" label="{i18n:Show District filter}" /> + <glz:Checkbox id="showPlace" label="{i18n:Show Place filter}" /> + </glz:Panel> + + <glz:SearchFilters id="filters" cssClass="search my-form clearfix" label="{i18n:Show search form}" method="get" rememberValues="false"> + <glz:DataDictionary id="filterTypeDP" recordClassName="movio.modules.touristoperators.models.Model" field="type" /> + <glz:DataDictionary id="filterCountryDP" recordClassName="movio.modules.touristoperators.models.Model" field="country" /> + <glz:DataDictionary id="filterDistrictDP" recordClassName="movio.modules.touristoperators.models.Model" field="district" /> + <glz:DataDictionary id="filterPlaceDP" recordClassName="movio.modules.touristoperators.models.Model" field="place" /> + + <glz:Input id="filterTitle" label="{i18n:Text to search}" bindTo="fulltext" value="{filters}" cssClass="input-large" /> + <glz:List id="filterType" label="{i18n:Type}" bindTo="type" value="{filters}" dataProvider="{filterTypeDP}" emptyValue="-" /> + <glz:List id="filterCountry" label="{i18n:Country}" bindTo="country" value="{filters}" dataProvider="{filterCountryDP}" emptyValue="-" /> + <glz:List id="filterDistrict" label="{i18n:District}" bindTo="district" value="{filters}" dataProvider="{filterDistrictDP}" emptyValue="-" /> + <glz:List id="filterPlace" label="{i18n:Place}" bindTo="place" value="{filters}" dataProvider="{filterPlaceDP}" emptyValue="-" /> + + <glz:Panel cssClass="control-group"> + <glz:HtmlButton id="submit" label="{i18n:GLZ_SEARCH}" value="SEARCH" target="{filters}" /> + <glz:HtmlButton id="reset" label="{i18n:GLZ_RESET}" value="RESET" target="{filters}" cssClass="reset" /> + </glz:Panel> + </glz:SearchFilters> + <glz:RecordSetList id="list" dataProvider="{ModuleDP}" routeUrl="movio_touristoperators" title="{i18n:Search Result}" filters="{filters}" paginate="{paginate}" skin="TouristOperators_list.html" removeTitleWithNoFilter="true" enabled="false"> + <glz:Repeater id="images"> + <glz:Image id="image" width="{config:IMG_LIST_WIDTH}" height="{config:IMG_LIST_HEIGHT}" /> + </glz:Repeater> + </glz:RecordSetList> + <t:RecordSetMap id="map" dataProvider="{ModuleDP}" routeUrl="movio_touristoperators" title="{i18n:Search Result}" filters="{filters}" skin="TouristOperators_map.html" removeTitleWithNoFilter="true" enabled="false" /> + <glz:PaginateResult id="paginate" cssClass="pagination" /> + </mvc:State> + + <mvc:State name="show"> + <t:RecordDetail id="entry" dataProvider="{ModuleDP}" idName="document_id" skin="TouristOperators_entry.html" ogTitle="title"> + <glz:Repeater id="locations" label="{i18n:Locations}"> + <glz:Input id="location" label="{i18n:Address}" size="255" /> + <glz:Input id="locationDescription" label="{i18n:Address description}" size="255" /> + <glz:Input id="coordinates" label="{i18n:Coordinates}" data="type=googlemaps" /> + </glz:Repeater> + <glz:Repeater id="images"> + <glz:Script extendParent="true"><![CDATA[ +function loadContent($id, $bindTo="") { + if ($this->contentCount>0) { + $c = $this->getComponentById($this->getId()."-image"); + $c->setAttributes(array("width" => __Config::get("THUMB_WIDTH"), + "height" => __Config::get("THUMB_HEIGHT"))); + } + return parent::loadContent($id, $bindTo); +}]]></glz:Script> + <glz:Image id="image" width="{config:IMG_WIDTH}" height="{config:IMG_HEIGHT}" zoom="true" group="slideshow" superZoom="true" /> + </glz:Repeater> + <glz:Repeater id="attaches"> + <glz:Media id="media" /> + </glz:Repeater> + </t:RecordDetail> + </mvc:State> +</mvc:Page> \ No newline at end of file diff --git a/src/application/classes/movio/modules/touristoperators/views/components/RecordDetail.php b/src/application/classes/movio/modules/touristoperators/views/components/RecordDetail.php new file mode 100644 index 0000000..b73f74c --- /dev/null +++ b/src/application/classes/movio/modules/touristoperators/views/components/RecordDetail.php @@ -0,0 +1,40 @@ +<?php +class movio_modules_touristoperators_views_components_RecordDetail extends org_glizy_components_RecordDetail +{ + function getContent() + { + parent::getContent(); + + // create the GooglMap data + $siteProp = $this->_application->getSiteProperty(); + $map = array(); + $map['style'] = 'width: 100%; height: 400px'; + $map['geo'] = ''; + $map['text'] = ''; + $map['pathEnable'] = '0'; + $map['markers'] = array(); + $map['jsSrc'] = 'https://maps.googleapis.com/maps/api/js'. + (isset($siteProp['googleMapsApiKey']) ? '?key='.$siteProp['googleMapsApiKey'] : ''); + + foreach($this->_content->locations as $l) { + $geo = explode(',', $l->coordinates); + $map['markers'][] = array( + 'lat' => $geo[0], + 'long' => $geo[1], + 'zoom' => $geo[2], + 'title' => $l->locationDescription, + 'text' => $l->location, + 'image' => '', + 'link' => '' + ); + } + + if (count($map['markers'])) { + $map['markers'] = json_encode($map['markers']); + $map['geo'] = json_encode($map['markers'][0]); + $map['text'] = $map['markers'][0]->title; + $this->_content->map = $map; + } + return $this->_content; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/modules/touristoperators/views/components/RecordSetMap.php b/src/application/classes/movio/modules/touristoperators/views/components/RecordSetMap.php new file mode 100644 index 0000000..1a20d9e --- /dev/null +++ b/src/application/classes/movio/modules/touristoperators/views/components/RecordSetMap.php @@ -0,0 +1,56 @@ +<?php +class movio_modules_touristoperators_views_components_RecordSetMap extends org_glizy_components_RecordSetList +{ + function process() + { + parent::process(); + + $it = $this->_content->records; + $siteProp = $this->_application->getSiteProperty(); + $map = array(); + $map['title'] = $this->_content->title; + $map['total'] = $this->_content->total; + $map['style'] = 'width: 100%; height: 600px'; + $map['geo'] = ''; + $map['text'] = ''; + $map['pathEnable'] = '0'; + $map['markers'] = array(); + $map['jsSrc'] = 'https://maps.googleapis.com/maps/api/js'. + (isset($siteProp['googleMapsApiKey']) ? '?key='.$siteProp['googleMapsApiKey'] : ''); + + $imageWidth = __Config::get('IMG_LIST_WIDTH'); + $imageHeight = __Config::get('IMG_LIST_HEIGHT'); + foreach ($it as $ar) { + $image = ''; + $images = org_glizy_helpers_Convert::formEditObjectToStdObject($ar->images); + if (count($images)) { + $media = json_decode($images[0]->image); + if ($media && @$media->id) { + $image = '<img src="'.GLZ_HOST.'/getImage.php?w='.$imageWidth.'&h='.$imageHeight.'&id='.$media->id.'">'; + } + } + + $localtions = org_glizy_helpers_Convert::formEditObjectToStdObject($ar->locations); + foreach($localtions as $l) { + $geo = explode(',', $l->coordinates); + $map['markers'][] = array( + 'lat' => $geo[0], + 'long' => $geo[1], + 'zoom' => $geo[2], + 'title' => $l->locationDescription!=$ar->title ? $ar->title.' - '.$l->locationDescription : $l->locationDescription, + 'text' => $l->location, + 'image' => $image, + 'link' => __Link::makeSimpleLink(__T('Read'), $ar->__url__) + ); + } + } + + if (count($map['markers'])) { + $map['markers'] = json_encode($map['markers']); + $map['geo'] = json_encode($map['markers'][0]); + $map['text'] = $map['markers'][0]->title; + } + + $this->_content = $map; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/search/Content.php b/src/application/classes/movio/search/Content.php new file mode 100644 index 0000000..68b0460 --- /dev/null +++ b/src/application/classes/movio/search/Content.php @@ -0,0 +1,32 @@ +<?php + +class movio_search_Content extends org_glizy_plugins_PluginClient +{ + function run(&$parent, $params) + { + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $languageId = $application->getLanguageId(); + $language = $application->getLanguage(); + + $it = org_glizy_objectFactory::createModelIterator('movio.search.models.Content'); + $it->load('getVisibleEntities', array(':words' => $params, ':language' => $languageId)); + + foreach ($it as $ar) { + //$ar->dump(); + + $result = $parent->getResultStructure(); + $result['title'] = $ar->title; + $result['description'] = $ar->description; + + if ($ar->keyInDataExists('url') && $ar->url) { + $url = org_glizy_helpers_Html::renderTag('a', array('href' => $language.'/'.$ar->url), true, $ar->title); + } else { + $url = __Link::makeLink('link', array('pageId' => $ar->pageId, 'title' => $ar->title)); + } + + $result['__url__'] = $url; + + $parent->addResult($result); + } + } +} \ No newline at end of file diff --git a/src/application/classes/movio/search/Entity.php b/src/application/classes/movio/search/Entity.php new file mode 100644 index 0000000..bd9f3ad --- /dev/null +++ b/src/application/classes/movio/search/Entity.php @@ -0,0 +1,36 @@ +<?php + +class movio_search_Entity extends org_glizy_plugins_PluginClient +{ + function run(&$parent, $params) + { + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $languageId = $application->getLanguageId(); + $language = $application->getLanguage(); + + $it = org_glizy_objectFactory::createModelIterator('movio.search.models.Entity'); + $it->load('getVisibleEntities', array(':words' => $params, ':language' => $languageId)); + + foreach ($it as $ar) { + //$ar->dump(); + + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $entityTypeService = $application->retrieveProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $descriptionAttribute = $entityTypeService->getDescriptionAttribute($ar->entityTypeId); + + $result = $parent->getResultStructure(); + $result['title'] = $ar->title; + $result['description'] = ($descriptionAttribute && $ar->keyInDataExists($descriptionAttribute)) ? $ar->$descriptionAttribute : ''; + + if ($ar->keyInDataExists('url') && $ar->url) { + $url = org_glizy_helpers_Html::renderTag('a', array('href' => $language.'/'.$ar->url), true, $ar->title); + } else { + $url = __Link::makeLink('showEntityDetail', $ar->getValuesAsArray()); + } + + $result['__url__'] = $url; + + $parent->addResult($result); + } + } +} \ No newline at end of file diff --git a/src/application/classes/movio/search/models/Content.xml b/src/application/classes/movio/search/models/Content.xml new file mode 100644 index 0000000..9668b11 --- /dev/null +++ b/src/application/classes/movio/search/models/Content.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="glizycms.content" + model:usePrefix="true" + model:type="document"> + + <model:Query name="mysql_getVisibleEntities"> + <![CDATA[ + SELECT `menus_tbl`.`menu_id` as `pageId`, `menudetails_tbl`.`menudetail_description` as `description`, `doc`.*, `doc_detail`.* + FROM `documents_tbl` `doc` + INNER JOIN `documents_detail_tbl` `doc_detail` ON `doc`.`document_id` = `doc_detail`.`document_detail_FK_document_id` + INNER JOIN `documents_index_int_tbl` `index1` ON `doc_detail`.`document_detail_id` = `index1`.`document_index_int_FK_document_detail_id` + INNER JOIN `menus_tbl` ON `index1`.`document_index_int_value` = `menus_tbl`.`menu_id` + INNER JOIN `menudetails_tbl` ON `menus_tbl`.`menu_id` = `menudetails_tbl`.`menudetail_FK_menu_id` + INNER JOIN `documents_index_fulltext_tbl` `fulltextIndex` ON `doc_detail`.`document_detail_id` = `fulltextIndex`.`document_index_fulltext_FK_document_detail_id` + WHERE `doc`.`document_type` = 'glizycms.content' + AND `index1`.`document_index_int_name` = 'id' + AND `doc_detail`.`document_detail_status` = 'PUBLISHED' + AND `doc_detail`.`document_detail_FK_language_id` = :language + AND `menudetails_tbl`.`menudetail_FK_language_id` = :language + AND `menudetails_tbl`.`menudetail_isVisible` = 1 + AND MATCH (`fulltextIndex`.`document_index_fulltext_value`) AGAINST (:words IN BOOLEAN MODE) + ]]> + </model:Query> + +</model:Model> + + + diff --git a/src/application/classes/movio/search/models/Entity.xml b/src/application/classes/movio/search/models/Entity.xml new file mode 100644 index 0000000..294acb5 --- /dev/null +++ b/src/application/classes/movio/search/models/Entity.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="glizycms.content" + model:usePrefix="true" + model:type="document"> + + <model:Query name="mysql_getVisibleEntities"> + <![CDATA[ + SELECT `menus_tbl`.`menu_id` as `pageId`, `index0`.`document_index_text_value` as `entityTypeId`, `doc2`.*, `doc_detail2`.* + FROM `documents_tbl` `doc` + INNER JOIN `documents_detail_tbl` `doc_detail` ON `doc`.`document_id` = `doc_detail`.`document_detail_FK_document_id` + INNER JOIN `documents_index_text_tbl` `index0` ON `doc_detail`.`document_detail_id` = `index0`.`document_index_text_FK_document_detail_id` + INNER JOIN `documents_index_int_tbl` `index1` ON `doc_detail`.`document_detail_id` = `index1`.`document_index_int_FK_document_detail_id` + INNER JOIN `menus_tbl` ON `index1`.`document_index_int_value` = `menus_tbl`.`menu_id` + INNER JOIN `menudetails_tbl` ON `menus_tbl`.`menu_id` = `menudetails_tbl`.`menudetail_FK_menu_id` + INNER JOIN `documents_tbl` doc2 ON doc2.document_type = concat('entity', index0.document_index_text_value) + INNER JOIN `documents_detail_tbl` `doc_detail2` ON `doc2`.`document_id` = `doc_detail2`.`document_detail_FK_document_id` + INNER JOIN `documents_index_fulltext_tbl` `fulltextIndex` ON `doc_detail2`.`document_detail_id` = `fulltextIndex`.`document_index_fulltext_FK_document_detail_id` + WHERE `index0`.`document_index_text_name` = 'entitySelect' AND + `index1`.`document_index_int_name` = 'id' AND + `doc`.`document_type` = 'glizycms.content' AND + `doc_detail`.`document_detail_status` = 'PUBLISHED' AND + `doc_detail`.`document_detail_FK_language_id` = :language AND + `menus_tbl`.`menu_pageType` = 'Entity' AND + `menudetails_tbl`.`menudetail_FK_language_id` = :language AND + `menudetails_tbl`.`menudetail_isVisible` = 1 AND + `doc_detail2`.`document_detail_status` = 'PUBLISHED' AND + `doc_detail2`.`document_detail_FK_language_id` = :language AND + MATCH (`fulltextIndex`.`document_index_fulltext_value`) AGAINST (:words IN BOOLEAN MODE) + ]]> + </model:Query> + +</model:Model> + + + diff --git a/src/application/classes/movio/views/AbstractLessTemplate.php b/src/application/classes/movio/views/AbstractLessTemplate.php new file mode 100644 index 0000000..d174aa5 --- /dev/null +++ b/src/application/classes/movio/views/AbstractLessTemplate.php @@ -0,0 +1,74 @@ +<?php +abstract class movio_views_AbstractLessTemplate extends GlizyObject +{ + protected $path; + protected $templateName; + + abstract protected function applyCssVariables(&$templateData, $less, $css); + abstract protected function applyFont(&$templateData, $css); + abstract protected function addLogoCss(&$templateData, $css); + abstract protected function addCustomCss(&$templateData, $css); + abstract public function fixTemplateData(&$templateData, &$newTemplateData); + abstract protected function fixTemplateName($view); + + public function render($application, $view, $templateData) + { + $templateData = $this->getTemplateDataFromCache($templateData); + + $siteProp = unserialize(org_glizy_Registry::get(__Config::get('REGISTRY_SITE_PROP').$view->_application->getLanguage(), '')); + $view->addOutputCode($templateData->css, 'css'); + $view->addOutputCode($siteProp['title'], 'siteTitle'); + $view->addOutputCode($siteProp['subtitle'], 'siteSubtitle'); + if ($templateData->footerLogo) { + $view->addOutputCode($templateData->footerLogo, 'logoFooter'); + } + $this->fixTemplateName($view); + } + + protected function getTemplateDataFromCache($templateData) + { + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + // $templateProxy->invalidateCache(); + $cache = $templateProxy->getTemplateCache(); + + $cssFileName = __Paths::get('CACHE').md5($this->getClassName().'_'.$templateData->__id).'.css'; + $self = $this; + $templateData = $cache->get($cssFileName, array(), function() use ($self, $templateData, $cssFileName) { + $newTemplateData = new StdClass; + $newTemplateData->footerLogo = ''; + + $self->compileCss($templateData, $cssFileName); + $self->fixTemplateData($templateData, $newTemplateData); + + $newTemplateData->css = $templateData->css; + return $newTemplateData; + }); + + return $templateData; + } + + public function compileCss(&$templateData, $cssFileName) + { + glz_importLib('lessphp/lessc.inc.php'); + $less = new lessc; + $less->setImportDir(array($this->path.'/less/')); + $css = file_get_contents($this->path.'/less/styles.less'); + // $css = $this->applyCssVariables($templateData, $less, $css); + $css = $this->applyFont($templateData, $css); + $css = $less->compile($css); + $css = $this->fixUrl($css); + $css = $this->addLogoCss($templateData, $css); + $css = $this->addCustomCss($templateData, $css); + file_put_contents($cssFileName, $css); + $templateData->css = '<link rel="stylesheet" href="'.$cssFileName.'" type="text/css" media="screen" />'; + } + + protected function fixUrl($css) + { + $css = str_replace( + array('../img/', '../font/'), + array('../static/movio/templates/'.$this->templateName.'/img/', '../static/movio/templates/'.$this->templateName.'/font/'), + $css); + return $css; + } +} \ No newline at end of file diff --git a/src/application/classes/movio/views/TemplateModuleAdmin.xml b/src/application/classes/movio/views/TemplateModuleAdmin.xml new file mode 100644 index 0000000..7c8274e --- /dev/null +++ b/src/application/classes/movio/views/TemplateModuleAdmin.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:mvc="org.glizy.mvc.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Page.php"> + + <glz:templateDefine name="model" required="true" /> + <glz:templateDefine name="grid_fields" required="true" /> + <glz:templateDefine name="form_fields" required="true" /> + <glz:templateDefine name="custom_states" required="false" defaultValue="" /> + <glz:templateDefine name="primary_key" required="false" defaultValue="document_id" /> + <glz:templateDefine name="controller_name" required="false" defaultValue="org.glizycms.contents.controllers.moduleEdit.*" /> + <glz:templateDefine name="show_external_id" required="false" defaultValue="true" /> + <glz:templateDefine name="add_label" required="false" defaultValue="GLZ_ADD_NEW_RECORD" /> + <glz:templateDefine name="render_class" required="false" defaultValue="org.glizycms.contents.views.renderer.CellEditDraftDeleteVisible" /> + + <glz:Import src="_common.xml" /> + + <mvc:State name="index"> + <glz:Link label="{i18n:##add_label##}" cssClass="{config:glizycms.form.actionLink.cssClass}" icon="icon-plus" routeUrl="actionsMVCAdd" editableRegion="actions" acl="*,new"/> + <glz:DataGridAjax id="dataGrid" recordClassName="##model##" cssClass="table table-bordered table-striped"> + ##grid_fields## + <glz:DataGridColumn columnName="##primary_key##" sortable="false" searchable="false" cssClass="actions" renderCell="##render_class##" /> + </glz:DataGridAjax> + </mvc:State> + + <mvc:State name="edit,editDraft"> + <cms:FormEdit id="editForm" controllerName="##controller_name##"> + <glz:Hidden id="__id" /> + <glz:Hidden id="__model" value="##model##"/> + <glz:Input id="external_id" label="{i18n:ID}" size="90" disabled="true" visible="##show_external_id##" /> + ##form_fields## + + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_PUBLISH}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <glz:HtmlButton label="{i18n:GLZ_PUBLISH_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=saveClose" /> + <glz:HtmlButton label="{i18n:GLZ_SAVE_DRAFT}" type="button" cssClass="btn js-glizycms-save" data="action=saveDraft" /> + <glz:HtmlButton label="{i18n:GLZ_SAVE_DRAFT_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=saveDraftClose" /> + <glz:HtmlButton label="{i18n:GLZ_CANCEL}" type="button" routeUrl="link" cssClass="btn js-glizycms-cancel" data="action=cancel" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="delete"> + <glz:Hidden controllerName="##controller_name##" /> + </mvc:State> + + <mvc:State name="togglevisibility"> + <glz:Hidden controllerName="##controller_name##" /> + </mvc:State> + + ##custom_states## +</mvc:Page> \ No newline at end of file diff --git a/src/application/classes/movio/views/components/Boxes.xml b/src/application/classes/movio/views/components/Boxes.xml new file mode 100644 index 0000000..c36a353 --- /dev/null +++ b/src/application/classes/movio/views/components/Boxes.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<m:BoxesCmp + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="movio.views.components.*"> + + <m:BoxesRepeater id="boxes" label="{i18n:Boxes}" adm:collapsable="true" skin="BoxList.html" editableRegion="afterContent"> + <glz:List id="type" label="{i18n:Box type}" data="target=title,text,image,linkTitle,pageId;val_0=1,1,1,0,1;val_1=1,0,1,1,1;val_2=1,0,0,0,0;"> + <glz:ListItem value="{i18n:Image with text}" key="imageText" /> + <glz:ListItem value="{i18n:Image with link}" key="imageLink" /> +<!-- <glz:ListItem value="{i18n:Timeline}" key="timeline" />--> + </glz:List> + <glz:List id="width" label="{i18n:Width}"> + <glz:ListItem value="{i18n:1}" key="1" /> + <glz:ListItem value="{i18n:2}" key="2" /> + <glz:ListItem value="{i18n:3}" key="3" /> + <glz:ListItem value="{i18n:4}" key="4" /> + </glz:List> + <glz:Input id="height" label="{i18n:Height}" size="10" required="false" /> + + <glz:Input id="title" label="{i18n:Title}" size="50" required="false" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" /> + <glz:Image id="image" label="{i18n:Image}" /> + <glz:Input id="linkTitle" label="{i18n:Link title}" size="50" required="false" /> + <cms:PagePicker id="pageId" label="{i18n:Linked page}" required="false" /> + </m:BoxesRepeater> +</m:BoxesCmp> \ No newline at end of file diff --git a/src/application/classes/movio/views/components/BoxesCmp.php b/src/application/classes/movio/views/components/BoxesCmp.php new file mode 100644 index 0000000..dc5a91b --- /dev/null +++ b/src/application/classes/movio/views/components/BoxesCmp.php @@ -0,0 +1,5 @@ +<?php +class movio_views_components_BoxesCmp extends org_glizy_components_ComponentContainer +{ + +} diff --git a/src/application/classes/movio/views/components/BoxesRepeater.php b/src/application/classes/movio/views/components/BoxesRepeater.php new file mode 100644 index 0000000..3e91d60 --- /dev/null +++ b/src/application/classes/movio/views/components/BoxesRepeater.php @@ -0,0 +1,32 @@ +<?php +class movio_views_components_BoxesRepeater extends org_glizy_components_Repeater +{ + function getContent() + { + $content = parent::getContent(); + $tempContent = array(); + $tempContentContainer = array(); + $span = 0; + $i = 0; + $numItem = count($content); + foreach($content as $item) { + $i++; + if ($span+$item->width > 4) { + $tempContentContainer[] = $tempContent; + $tempContent = array(); + } + $item->style = $item->height ? 'height:'.$item->height.'px;' : ''; + $tempContent[] = $item; + $span += $item->width; + $item->width *= 3; + + if ($span >= 4 || $i == $numItem) { + $tempContentContainer[] = $tempContent; + $span = 0; + $tempContent = array(); + } + } + + return $tempContentContainer; + } +} diff --git a/src/application/classes/movio/views/components/BoxesSidebar.xml b/src/application/classes/movio/views/components/BoxesSidebar.xml new file mode 100644 index 0000000..5e99c55 --- /dev/null +++ b/src/application/classes/movio/views/components/BoxesSidebar.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<m:BoxesCmp + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="movio.views.components.*"> + + <m:BoxesRepeater id="boxes" label="{php:$this._parent.getAttribute('label')}" adm:collapsable="true" skin="BoxSidebar.html"> + <glz:List id="type" label="{i18n:Box type}" data="target=title,text,image,linkTitle,pageId;val_0=1,1,1,0,1;val_1=1,0,1,1,1;val_2=1,1,0,0,0;"> + <glz:ListItem value="{i18n:Image with text}" key="imageText" /> + <glz:ListItem value="{i18n:Image with link}" key="imageLink" /> + <glz:ListItem value="{i18n:Text}" key="text" /> + </glz:List> + + <glz:Input id="title" label="{i18n:Title}" size="50" required="false" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" /> + <glz:Image id="image" label="{i18n:Image}" width="300" height="150" /> + <glz:Input id="linkTitle" label="{i18n:Link title}" size="50" required="false" /> + <cms:PagePicker id="pageId" label="{i18n:Linked page}" required="false" /> + </m:BoxesRepeater> +</m:BoxesCmp> \ No newline at end of file diff --git a/src/application/classes/movio/views/components/GoogleMap.xml b/src/application/classes/movio/views/components/GoogleMap.xml new file mode 100644 index 0000000..ebd24da --- /dev/null +++ b/src/application/classes/movio/views/components/GoogleMap.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<m:GoogleMapCmp + label="{i18n:Google Map}" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="movio.views.components.*"> + + <glz:Input id="width" label="{i18n:Width (default full width)}" size="50" /> + <glz:Input id="height" label="{i18n:Height (default 600px)}" size="50" /> + <glz:Input id="geo" label="{i18n:Address}" size="90" data="type=googlemaps" required="true" /> + <glz:Input id="text" label="{i18n:Text}" size="50" required="true" /> + <glz:List id="pathEnable" label="{i18n:Connect POI with a path}"> + <glz:ListItem value="{i18n:No connection}" key="0" /> + <glz:ListItem value="{i18n:Line}" key="1" /> + <glz:ListItem value="{i18n:Route car}" key="3" /> + <glz:ListItem value="{i18n:Route transit}" key="4" /> + <glz:ListItem value="{i18n:Route bicycling}" key="2" /> + <glz:ListItem value="{i18n:Route walking}" key="5" /> + </glz:List> + + <glz:Repeater id="markers" label="{i18n:Markers}" adm:collapsable="true"> + <glz:Input id="poi" label="{i18n:POI}" size="90" required="true" data="type=googlemaps" /> + <glz:Input id="title" label="{i18n:Title}" size="50" required="false" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="10" adm:cols="75" adm:htmlEditor="true" required="false" /> + <glz:Image id="image" label="{i18n:Image}" width="{config:movio.thumb.map.width}" height="{config:movio.thumb.map.height}" crop="{config:movio.thumb.map.crop}" /> + <glz:List id="type" label="{i18n:Link type}" data="target=externalLink,internalLink;val_0=1,0;val_1=0,1;"> + <glz:ListItem value="{i18n:External link}" key="externalLink" /> + <glz:ListItem value="{i18n:Internal link}" key="internalLink" /> + </glz:List> + <glz:Input id="externalLink" label="{i18n:External link}" size="50" required="false" data="type=url" /> + <cms:PagePicker id="internalLink" label="{i18n:Linked page}" required="false" /> + </glz:Repeater> + +</m:GoogleMapCmp> \ No newline at end of file diff --git a/src/application/classes/movio/views/components/GoogleMapCmp.php b/src/application/classes/movio/views/components/GoogleMapCmp.php new file mode 100644 index 0000000..d9b38e6 --- /dev/null +++ b/src/application/classes/movio/views/components/GoogleMapCmp.php @@ -0,0 +1,71 @@ +<?php +class movio_views_components_GoogleMapCmp extends org_glizy_components_Groupbox +{ + function getContent() + { + $content = $this->stripIdFromContent(parent::getContent()); + $markers = array(); + $geo = explode(',', $content['geo']); + $content['geo'] = json_encode(array('lat' => $geo[0], 'long' => $geo[1], 'zoom' => intval($geo[2]))); + $content['pathEnable'] = $content['pathEnable']; + $markers[] = array('lat' => $geo[0], 'long' => $geo[1], 'title' => $content['text'], 'text' => '', 'image' => '', 'link' => ''); + foreach($content['markers'] as $poi) { + $link = ''; + if ($poi->type == 'internalLink' && $poi->internalLink) { + /*TODO quando riesco a recuperare il titolo della pagina metto a false per internal link*/ + $link = $this->limitURL($poi->internalLink, 25, true); + } elseif ($poi->type == 'externalLink' && $poi->externalLink) { + $link = $this->limitURL($poi->externalLink, 25, true); + } + + $geo = explode(',', $poi->poi); + $markers[] = array( + 'lat' => $geo[0], + 'long' => $geo[1], + 'title' => $poi->title, + 'image' => $poi->image['__html__'], + 'text' => $poi->text, + 'link' => $link + ); + } + $geo = $geo = explode(',', $content['geo']); + $content['markers'] = json_encode($markers); + $content['style'] = 'width: '.($content['width'] ? $content['width'].'px' : '100%').'; height: '.($content['height'] ? $content['height'].'px' : '600px'); + + $siteProp = $this->_application->getSiteProperty(); + $content['jsSrc'] = 'https://maps.googleapis.com/maps/api/js'. + (isset($siteProp['googleMapsApiKey']) ? '?key='.$siteProp['googleMapsApiKey'] : ''); + + return $content; + } + + function render($mode) + { + if (!$this->_application->isAdmin()) { + $this->setAttribute('skin', 'GoogleMap.html'); + } + parent::render($mode); + } + + private function limitURL($url, $limit, $external) + { + $link = ''; + if($external) + { + if (!preg_match("~^(?:f|ht)tps?://~i", $url)) { + $title = $url; + $url = "http://" . $url; + } else { + $title = substr($url, stripos('.', -1)); + } + if (strlen($url) > $limit) { + $shorter = substr($title, 0, $limit) . '...'; + return '<a href="' . $url . '" title="' . $url . '" rel="external">' . $shorter . '</a>'; + } + + return '<a href="' . $url . '" title="' . $url . '" rel="external">' . $title . '</a>'; + } + /*TODO per intenal link mettere titolo pagina*/ + return '<a href="' . $url . '" title="' . $url . '">' . $url . '</a>'; + } +} diff --git a/src/application/classes/movio/views/components/ImageHotspot.php b/src/application/classes/movio/views/components/ImageHotspot.php new file mode 100644 index 0000000..2d8295d --- /dev/null +++ b/src/application/classes/movio/views/components/ImageHotspot.php @@ -0,0 +1,102 @@ +<?php +class movio_views_components_ImageHotspot extends org_glizy_components_Component +{ + public function process() + { + $this->_content = @json_decode($this->_parent->loadContent($this->getId())); + } + + + + public function render() + { + if (is_object($this->_content) && $this->_content->image && $this->_content->hotspots) { + $media = org_glizycms_mediaArchive_MediaManager::getMediaById($this->_content->image); + $speakingUrlManager = $this->_application->retrieveProxy('org.glizycms.speakingUrl.Manager'); + if (is_object($media)) { + $id = $this->getId(); + $imageInfo = $media->getImageInfo(); + $width = $imageInfo['width']; + $height = $imageInfo['height']; + + $attributes = array(); + $attributes['src'] = $media->getFileName(true); + $attributes['width'] = $imageInfo['width']; + $attributes['height'] = $imageInfo['height']; + $attributes['alt'] = $media->title; + $attributes['title'] = $media->title; + $image = '<img '.$this->_renderAttributes($attributes).' />'; + + $hotspots = ''; + foreach($this->_content->hotspots as $h) { + $attributes = array(); + $attributes['id'] = $id.'-'.$h->id; + $attributes['class'] = 'movio-hotspot'.($h->form=='circle' ? '-circle' : ''); + $attributes['style'] = 'display: block; top: '.$h->top.'px; left: '.$h->left.'px; height: '.$h->height.'px; width: '.$h->width.'px;'; + if ($h->description) $attributes['data-tooltip'] = glz_encodeOutput($h->description); + $link = ''; + if ($h->type='linkEx' && $h->src) { + $link = __Link::formatLink($h->src); + } else if ($h->type='link' && $h->srcInt) { + $link = __Link::formatInternalLink($speakingUrlManager->makeUrl($h->srcInt)); + } + + if ($link) { + $link = str_replace('<a ', '<a style="text-indent: -9999px; height: '.$h->height.'px; width: '.$h->width.'px; display: block;"', $link); + } + // <a target="_blank" style="height: 148px; width: 186px; display: block;" href="www.google.com" class="hotspot-circle"></a> + $hotspots .= '<div '.$this->_renderAttributes($attributes).'>'. + $link. + '</div>'; + + } + + $css = trim('movio-hotspotContainer '.$this->getAttribute('cssClass')); + + $output = <<<EOD +<div id="$id" class="$css"> + $image + <div class="movio-imageHotspot-scale"> + $hotspots + </div> +</div> +<script src="static/jquery/jquery-transform/jquery.transform2d.js"></script> +<script> +jQuery( function(){ + $('div.movio-hotspotContainer').find('div[data-tooltip!=""]').qtip({ + content: { + attr: 'data-tooltip' + }, + position: { + my: 'bottom left', + at: 'bottom left', + target: 'mouse' + }, + style: { + classes: 'qtip-bootstrap' + } + }); + var img = $('div.movio-hotspotContainer img').first(); + var scale = img.width() / parseInt(img.attr('width')); + $('.movio-imageHotspot-scale').css('transform', 'scale('+scale+','+scale+')'); +}); +</script> +EOD; + $this->addOutputCode($output); + + $this->addOutputCode( org_glizy_helpers_JS::linkStaticJSfile( 'jquery/jquery.qtip/jquery.qtip.min.js' ), 'head'); + $this->addOutputCode( org_glizy_helpers_CSS::linkStaticCSSfile( 'jquery/jquery.qtip/jquery.qtip.min.css' ), 'head'); + } + } + + } + + public static function translateForMode_edit($node) { + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['data'] = 'type=imageHotspot'; + + return org_glizy_helpers_Html::renderTag('glz:Input', $attributes); + } +} diff --git a/src/application/classes/movio/views/components/Photogallery.xml b/src/application/classes/movio/views/components/Photogallery.xml new file mode 100644 index 0000000..7d464db --- /dev/null +++ b/src/application/classes/movio/views/components/Photogallery.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<m:PhotogalleryCmp + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="movio.views.components.*"> + + <glz:List id="galleryType" label="{i18n:Gallery type}"> + <glz:ListItem value="{i18n:Gallery}" key="gallery" /> + <glz:ListItem value="{i18n:Slideshow}" key="slideshow" /> + <glz:ListItem value="{i18n:Slider}" key="slider" /> + <glz:ListItem value="{i18n:Page flip}" key="pageflip" /> + </glz:List> + <glz:Checkbox id="imageCrop" label="{i18n:Image crop}" defaultValue="1" /> + <glz:Checkbox id="imagePan" label="{i18n:Image pan}" defaultValue="1" /> + + <glz:Repeater id="images" label="{i18n:Images list}" adm:collapsable="false" skin="ImageList.html"> + <glz:Image id="image" label="{i18n:Image}" width="800" height="600" /> + </glz:Repeater> + +</m:PhotogalleryCmp> \ No newline at end of file diff --git a/src/application/classes/movio/views/components/PhotogalleryCategory.xml b/src/application/classes/movio/views/components/PhotogalleryCategory.xml new file mode 100644 index 0000000..29d1ec5 --- /dev/null +++ b/src/application/classes/movio/views/components/PhotogalleryCategory.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<m:PhotogalleryCmp + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="movio.views.components.*"> + + <glz:List id="galleryType" label="{i18n:Gallery type}"> + <glz:ListItem value="{i18n:Gallery}" key="gallery" /> + <glz:ListItem value="{i18n:Slideshow}" key="slideshow" /> + <glz:ListItem value="{i18n:Slider}" key="slider" /> + <glz:ListItem value="{i18n:Page flip}" key="pageflip" /> + </glz:List> + <glz:Checkbox id="imageCrop" label="{i18n:Image crop}" defaultValue="1" /> + <glz:Checkbox id="imagePan" label="{i18n:Image pan}" defaultValue="1" /> + <glz:Checkbox id="queryOr" label="{i18n:Query in OR}" defaultValue="1" /> + + <m:RepeaterFromModel id="images" label="{i18n:Images list}" skin="ImageList.html" adm:data="type=selectfrom;multiple=true;add_new_values=false;model=org.glizycms.models.Media;field=media_category"> + <glz:Image id="image" label="{i18n:Image}" width="800" height="600" /> + </m:RepeaterFromModel> +</m:PhotogalleryCmp> \ No newline at end of file diff --git a/src/application/classes/movio/views/components/PhotogalleryCmp.php b/src/application/classes/movio/views/components/PhotogalleryCmp.php new file mode 100644 index 0000000..58e37d2 --- /dev/null +++ b/src/application/classes/movio/views/components/PhotogalleryCmp.php @@ -0,0 +1,39 @@ +<?php +class movio_views_components_PhotogalleryCmp extends org_glizy_components_Groupbox +{ + private $galleryType; + + function process() { + $this->galleryType = $this->loadContent($this->getId().'-galleryType'); + if (!$this->galleryType) { + $this->galleryType = 'gallery'; + } + $queryOr = $this->loadContent($this->getId().'-queryOr') === 1; + $c = $this->getComponentById($this->getId().'-images'); + if ($c) { + $c->setAttribute('queryOr', $queryOr); + } + + parent::process(); + } + + function getContent() { + $imageCrop = $this->loadContent($this->getId().'-imageCrop'); + $imagePan = $this->loadContent($this->getId().'-imagePan'); + $imagePosition = $imageCrop == 1 && $imagePan == 1 ? 'top right' : '50%'; + $content = parent::getContent(); + return array( 'images' => $content[$this->getId().'-images'], + 'imageCrop' => $imageCrop == 1 ? 'true' : 'false', + 'imagePan' => $imagePan == 1 ? 'true' : 'false', + 'imagePosition' => $imagePosition, + 'type' => $this->galleryType + ); + } + + function render($mode) { + if (!$this->_application->isAdmin()) { + $this->setAttribute('skin', 'Photogallery.html'); + } + parent::render($mode); + } +} diff --git a/src/application/classes/movio/views/components/RepeaterFromModel.php b/src/application/classes/movio/views/components/RepeaterFromModel.php new file mode 100644 index 0000000..26adb49 --- /dev/null +++ b/src/application/classes/movio/views/components/RepeaterFromModel.php @@ -0,0 +1,129 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class movio_views_components_RepeaterFromModel extends org_glizy_components_ComponentContainer +{ + private $repeaterId; + private $numRecords; + // private $contentCount; + + private $it; + + /** + * Return the component information + * + * @return array component informaton. + * @access public + * @static + */ + function getInfo() + { + $info = parent::info(); + $info['name'] = 'Repeater'; + $info['class'] = 'org.glizy.components.Repeater'; + $info['package'] = 'Glizy'; + $info['version'] = GLZ_CORE_VERSION; + $info['author'] = 'Daniele Ugoletti'; + $info['author-email'] = 'daniele.ugoletti@glizy.com'; + $info['url'] = 'http://www.glizy.com'; + return $info; + } + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('queryOr', false, false, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + + function process() + { + $this->repeaterId = $this->getId(); + $this->it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.models.Media'); + $this->numRecords = 0; + + $filter = $this->_parent->loadContent($this->repeaterId); + if (is_array($filter) && count($filter)) { + $filters = array('media_type' => 'IMAGE', + 'media_category' => array()); + foreach($filter as $v) { + $filters['media_category'][] = array('field' => 'media_category', 'value' => '%"'.$v.'"%', 'condition' => 'LIKE'); + } + + if ($this->getAttribute('queryOr')) { + $this->it->setOrFilters($filters); + } else { + $this->it->setFilters($filters); + } + $this->it->orderBy('media_title'); + $this->numRecords = $this->it->count(); + } + + $this->_content = new StdClass; + } + + + function getContent() + { + $result = array(); + for ($i = 0; $i < $this->numRecords; $i++) { + $this->contentCount = $i; + $temp = new StdClass; + for ($j = 0; $j < count($this->childComponents); $j++) { + $child = $this->childComponents[$j]; + $child->process(); + $temp->{$child->getOriginalId()} = $child->getContent(); + $result[] = $temp; + } + } + return $result; + } + + function render($mode) { + if (!$this->_application->isAdmin()) { + $this->setAttribute('skin', 'ImageList.html'); + } + parent::render($mode); + } + + function loadContent($id, $bindTo='') + { + $id = $this->it->current()->media_id; + $this->it->next(); + return $id; + } + + public static function compileAddPrefix($compiler, &$node, $componentId, $idPrefix) + { + return $idPrefix.'\''.$componentId.'-\'.'; + } + + public static function translateForMode_edit($node) { + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['noChild'] = 'true'; + $attributes['data'] = ''; + if ($node->hasAttribute('adm:data')) { + $attributes['data'] .= ';'.$node->getAttribute('adm:data'); + } + + return org_glizy_helpers_Html::renderTag('glz:Input', $attributes); + } +} diff --git a/src/application/classes/movio/views/components/Timeline.xml b/src/application/classes/movio/views/components/Timeline.xml new file mode 100644 index 0000000..7494254 --- /dev/null +++ b/src/application/classes/movio/views/components/Timeline.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<m:TimelineCmp + label="{i18n:Timeline}" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="movio.views.components.*"> + + <glz:Input id="title" label="{i18n:Title}" size="50" required="true" /> + <glz:Input id="subtitle" label="{i18n:Subtitle}" size="50" /> + <glz:Input id="startDate" label="{i18n:Timeline Start date (yyyy, yyyy/mm, yyyy/mm/dd)}" size="50" required="true" /> + + <glz:Input id="width" label="{i18n:Width (default full width)}" size="50" /> + <glz:Input id="height" label="{i18n:Height (default 600px)}" size="50" /> + <glz:Input id="url" label="{i18n:Google Spreadsheet or other data source URL}" size="50" /> + <glz:Input id="start" label="{i18n:Start at specific slide number}" size="50" /> + + <glz:Repeater id="timelineDef" label="{i18n:Timeline definition}" adm:collapsable="true" skin="ImageList.html"> + <glz:Input id="startDate" label="{i18n:Start date (yyyy, yyyy/mm, yyyy/mm/dd)}" size="50"/> + <glz:Input id="endDate" label="{i18n:End date (yyyy, yyyy/mm, yyyy/mm/dd)}" size="50"/> + <glz:Input id="headline" label="{i18n:Headline}" size="50" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + + <glz:Input id="mediaExternal" label="{i18n:External Media}" size="50" /> + <glz:Media id="media" label="{i18n:Media}" size="50" /> + <glz:LongText id="mediaCaption" label="{i18n:Media caption}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + + </glz:Repeater> +</m:TimelineCmp> \ No newline at end of file diff --git a/src/application/classes/movio/views/components/TimelineCmp.php b/src/application/classes/movio/views/components/TimelineCmp.php new file mode 100644 index 0000000..4e0243f --- /dev/null +++ b/src/application/classes/movio/views/components/TimelineCmp.php @@ -0,0 +1,74 @@ +<?php +class movio_views_components_TimelineCmp extends org_glizy_components_Groupbox +{ + function getContent() { + $content = parent::getContent(); + $content = $this->stripIdFromContent($content); + + $result = array(); + $result['font'] = 'PT'; + $result['maptype'] = 'ROADMAP'; + $result['lang'] = $this->_application->getLanguage(); + // $result['title'] = $content['title']; + // $result['subtitle'] = $content['subtitle']; + // $result['startDate'] = $content['startDate']; + $result['width'] = $content['width'] ? $content['width'] : '100%'; + $result['height'] = $content['height'] ? $content['height'] : '600'; + if ($content['url']) { + $result['source'] = $content['url']; + } else { + $result['source'] = GLZ_HOST.'/'.$this->getAjaxUrl().'&.json'; + } + + return $result; + } + + function render($mode) + { + if (!$this->_application->isAdmin()) { + $this->setAttribute('skin', 'Timeline.html'); + } + parent::render($mode); + } + + function process_ajax() + { + $c = $this->getRootComponent(); + $c->process(); + $content = $this->stripIdFromContent(parent::getContent()); + + $timeline = array( 'date' => array(), + 'type' => 'default', + 'headline' => $content['title'], + 'text' => $content['subtitle'], + 'startDate' => $this->formatDate($content['startDate']) + ); + + $num = count($content['timelineDef']); + for ($i=0; $i < $num; $i++) { + $temp = array('headline' => '', 'text' => '', 'asset' => array('media' => '', 'caption' => '', 'credit' => '')); + if ($content['timelineDef'][$i]->startDate) $temp['startDate'] = $this->formatDate($content['timelineDef'][$i]->startDate); + if ($content['timelineDef'][$i]->endDate) $temp['endDate'] = $this->formatDate($content['timelineDef'][$i]->endDate); + if ($content['timelineDef'][$i]->headline) $temp['headline'] = $content['timelineDef'][$i]->headline; + if ($content['timelineDef'][$i]->text) $temp['text'] = $content['timelineDef'][$i]->text; + if ($content['timelineDef'][$i]->mediaExternal) { + $temp['asset']['media'] = $content['timelineDef'][$i]->mediaExternal; + } else if ($content['timelineDef'][$i]->media['mediaId'] > 0) { + $temp['asset']['media'] = GLZ_HOST.'/'.org_glizy_helpers_Media::getResizedImageUrlById($content['timelineDef'][$i]->media['mediaId'], false, __Config::get('IMAGE_WIDTH'), __Config::get('IMAGE_HEIGHT') ); + $temp['asset']['thumbnail'] = GLZ_HOST.'/'.org_glizy_helpers_Media::getResizedImageUrlById($content['timelineDef'][$i]->media['mediaId'], false, __Config::get('THUMB_WIDTH'), __Config::get('THUMB_HEIGHT') ); + } + if ($content['timelineDef'][$i]->mediaCaption) $temp['asset']['caption'] = $content['timelineDef'][$i]->mediaCaption; + $timeline['date'][] = $temp; + } + return array('timeline' => $timeline); + } + + private function formatDate($date) + { + $date = preg_replace('/^(\d{1,2})\/(\d{1,2})\/(-?\d{2,4})$/', '$3/$2/$1', $date); + $date = preg_replace('/^(\d{1,2})\/(-?\d{2,4})$/', '$2', $date); + $date = preg_replace('/^(-?\d{2,4})$/', '$1', $date); + + return str_replace('/', ',', $date); + } +} \ No newline at end of file diff --git a/src/application/classes/movio/views/components/Unity3D.xml b/src/application/classes/movio/views/components/Unity3D.xml new file mode 100644 index 0000000..ec07627 --- /dev/null +++ b/src/application/classes/movio/views/components/Unity3D.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<m:Unity3DCmp + label="{i18n:Unity3D}" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="movio.views.components.*"> + + <glz:Media id="unity3DFile" label="File Unity 3D" adm:mediaType="other" /> + <glz:Input id="width" label="{i18n:Width}" size="50" /> + <glz:Input id="height" label="{i18n:Height}" size="50" /> + <glz:Input id="backgroundColor" label="{i18n:LoadingBackgroundColor}" size="50" data="type=colorPicker" /> + <glz:Input id="borderColor" label="{i18n:LoadingBorderColor}" data="type=colorPicker" /> + <glz:Input id="textColor" label="{i18n:ErrorTextColor}" data="type=colorPicker" /> + <glz:Image id="logoimage" label="{i18n:LoadingLogoImage}" /> + <glz:List id="disableContextMenu" label="{i18n:disableContextMenu}"> + <glz:ListItem key="false" value="{i18n:No}" /> + <glz:ListItem key="true" value="{i18n:Yes}" /> + </glz:List> + <glz:List id="disableFullscreen" label="{i18n:disableFullscreen}"> + <glz:ListItem key="false" value="{i18n:No}" /> + <glz:ListItem key="true" value="{i18n:Yes}" /> + </glz:List> + <glz:Repeater id="attributeList" label="{i18n:attributeList}"> + <glz:Input id="attributeKey" label="{i18n:Key}" /> + <glz:Input id="attributeValue" label="{i18n:Value}" /> + </glz:Repeater> +</m:Unity3DCmp> \ No newline at end of file diff --git a/src/application/classes/movio/views/components/Unity3DCmp.php b/src/application/classes/movio/views/components/Unity3DCmp.php new file mode 100644 index 0000000..d54800d --- /dev/null +++ b/src/application/classes/movio/views/components/Unity3DCmp.php @@ -0,0 +1,35 @@ +<?php +class movio_views_components_Unity3DCmp extends org_glizy_components_Groupbox +{ + function getContent() + { + $content = parent::getContent(); + $content = $this->stripIdFromContent($content); + + if (!empty($content['unity3DFile']['mediaId'])) { + return array( + 'fileId' => $content['unity3DFile']['mediaId'], + 'width' => empty($content['width']) ? '800' : $content['width'], + 'height' => empty($content['height']) ? '600' : $content['height'], + 'backgroundColor' => strtoupper(str_replace('#', '', $content['backgroundColor'])), + 'borderColor' => strtoupper(str_replace('#', '', $content['borderColor'])), + 'textColor' => strtoupper(str_replace('#', '', $content['textColor'])), + 'logoimage' => 'http://localhost/mibac_movio/wwwRoot/getImage.php?id=' . $content['logoimage']['mediaId'], + 'disableContextMenu' => empty($content['disableContextMenu']) ? 'false' : $content['disableContextMenu'], + 'disableFullscreen' => empty($content['disableFullscreen']) ? 'false' : $content['disableFullscreen'], + 'attributes' => json_encode($content['attributeList']) + ); + } + + return array(); + } + + function render($mode) + { + if (!$this->_application->isAdmin()) { + ini_set('display_errors', 'On'); + $this->setAttribute('skin', 'Unity3D.html'); + } + parent::render($mode); + } +} \ No newline at end of file diff --git a/src/application/classes/movio/views/components/Video.xml b/src/application/classes/movio/views/components/Video.xml new file mode 100644 index 0000000..6d63984 --- /dev/null +++ b/src/application/classes/movio/views/components/Video.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<m:VideoCmp + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="movio.views.components.*"> + + <glz:LongText id="textAlternative" label="{i18n:Testo alternativo}" adm:rows="10" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + <glz:Media id="video" label="{i18n:Video}" required="true" adm:mediaType="VIDEO" directUrl="true" /> + <glz:Input id="width" label="{i18n:Width}" size="50" required="true" /> + <glz:Input id="height" label="{i18n:Height}" size="50" required="true" /> + <!--<glz:Checkbox id="autostart" label="{i18n:Autoplay}" defaultValue="1" />--> +</m:VideoCmp> \ No newline at end of file diff --git a/src/application/classes/movio/views/components/VideoCmp.php b/src/application/classes/movio/views/components/VideoCmp.php new file mode 100644 index 0000000..cbb5781 --- /dev/null +++ b/src/application/classes/movio/views/components/VideoCmp.php @@ -0,0 +1,22 @@ +<?php +class movio_views_components_VideoCmp extends org_glizy_components_Groupbox +{ + function getContent() { + $content = parent::getContent(); + $newContent = array(); + $newContent['textAlternative'] = $content[$this->getId().'-textAlternative']; + $newContent['video'] = $content[$this->getId().'-video']; + $newContent['width'] = $content[$this->getId().'-width']; + $newContent['height'] = $content[$this->getId().'-height']; + //$newContent['autostart'] = $content[$this->getId().'-autostart']['value'] == '1'; + + return $newContent; + } + + function render($mode) { + if (!$this->_application->isAdmin()) { + $this->setAttribute('skin', 'Video.html'); + } + parent::render($mode); + } +} diff --git a/src/application/classes/userModules/movio/ontologybuilder/locale/.gitignore b/src/application/classes/userModules/movio/ontologybuilder/locale/.gitignore new file mode 100644 index 0000000..66ca35b --- /dev/null +++ b/src/application/classes/userModules/movio/ontologybuilder/locale/.gitignore @@ -0,0 +1 @@ +*.php \ No newline at end of file diff --git a/src/application/classes/userModules/movio/ontologybuilder/skins/entities/.gitignore b/src/application/classes/userModules/movio/ontologybuilder/skins/entities/.gitignore new file mode 100644 index 0000000..ef1a2cc --- /dev/null +++ b/src/application/classes/userModules/movio/ontologybuilder/skins/entities/.gitignore @@ -0,0 +1 @@ +[0-9]* \ No newline at end of file diff --git a/src/application/config/acl.xml b/src/application/config/acl.xml new file mode 100644 index 0000000..5db92f5 --- /dev/null +++ b/src/application/config/acl.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:Acl> + +</glz:Acl> \ No newline at end of file diff --git a/src/application/config/config.xml b/src/application/config/config.xml new file mode 100644 index 0000000..c918689 --- /dev/null +++ b/src/application/config/config.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:Config xmlns:glz="http://www.glizy.org/dtd/1.0/"> + <glz:Import src="config_common.xml" /> + <glz:Param name="DB_TYPE" value="mysql" /> + <glz:Param name="DB_HOST" value="localhost" /> + <glz:Param name="DB_NAME" value="mmovio" /> + <glz:Param name="DB_USER" value="root" /> + <glz:Param name="DB_PSW" value="root" /> + <glz:Param name="DB_PREFIX" value="" /> +</glz:Config> diff --git a/src/application/config/config_common.xml b/src/application/config/config_common.xml new file mode 100644 index 0000000..cc353c2 --- /dev/null +++ b/src/application/config/config_common.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:Config xmlns:glz="http://www.glizy.org/dtd/1.0/"> + <glz:Param name="CHARSET" value="UTF-8" /> + <glz:Param name="APP_NAME" value="MOVIO" /> + <glz:Param name="APP_VERSION" value="1.8" /> + <glz:Param name="APP_AUTHOR"> + <![CDATA[Gruppo Meta <http://www.gruppometa.it>]]> + </glz:Param> + + <glz:Param name="IMG_WIDTH" value="400" /> + <glz:Param name="IMG_HEIGHT" value="300" /> + <glz:Param name="THUMB_WIDTH" value="86" /> + <glz:Param name="THUMB_HEIGHT" value="86" /> + <glz:Param name="THUMB_SMALL_WIDTH" value="56" /> + <glz:Param name="THUMB_SMALL_HEIGHT" value="56" /> + + <glz:Param name="SEF_URL" value="full" /> + <glz:Param name="CACHE_CODE" value="-1" /> + <glz:Param name="USER_LOG" value="false" /> + <glz:Param name="DEBUG" value="false" /> + <glz:Param name="DB_CHARSET" value="utf8" /> + <glz:Param name="DATASOURCE_MODE" value="db" /> + <glz:Param name="START_PAGE" value="1" /> + <glz:Param name="PSW_METHOD" value="MD5" /> + <glz:Param name="MULTILANGUAGE_ENABLED" value="true" /> + + <glz:Param name="GLIZY_ADD_JQUERY_JS" value="false" /> + <glz:Param name="GLIZY_ADD_JQUERYUI_JS" value="false" /> + <glz:Param name="glizycms.template.default" value="Movio" /> + <glz:Param name="glizycms.contents.templateEnabled" value="true" /> + <glz:Param name="glizy.dataAccess.serializationMode" value="json" /> + <glz:Param name="glizycms.speakingUrl" value="true" /> + <glz:Param name="glizy.dataAccess.documentVisibility" value="true" /> + <glz:Param name="glizycms.content.history" value="false" /> + <glz:Param name="glizy.routing.newParser" value="false" /> + + <glz:Param name="BASE_REGISTRY_PATH" value="movio" /> + <glz:Param name="STATIC_FOLDER" value="static/movio/" /> + + <glz:Param name="movio.noImage.src" value="{{path:STATIC_DIR}}movio/templates/Movio/img/various/img-not-disponible.jpg" /> + <glz:Param name="movio.graph.shapeColor" value="#cfced3" /> + <glz:Param name="movio.graph.backgroundColor" value="#ffffff" /> + <glz:Param name="movio.thumb.entityList.width" value="{{THUMB_WIDTH}}" /> + <glz:Param name="movio.thumb.entityList.height" value="{{THUMB_HEIGHT}}" /> + <glz:Param name="movio.thumb.entityList.crop" value="false" /> + <glz:Param name="movio.thumb.homeSlider.width" value="1200" /> + <glz:Param name="movio.thumb.homeSlider.height" value="290" /> + <glz:Param name="movio.thumb.homeSlider.crop" value="true" /> + <glz:Param name="movio.thumb.map.width" value="250" /> + <glz:Param name="movio.thumb.map.height" value="250" /> + <glz:Param name="movio.thumb.map.crop" value="false" /> + + <glz:Param name="movio.europeana.apiKey" value="" /> + <glz:Param name="movio.europeana.apiSearchUrl" value="http://europeana.eu/api/v2/search.json" /> + <glz:Param name="movio.europeana.rows" value="18" /> + <glz:Param name="movio.europeana.searchFields" value="title,who,what,when,where,TYPE,LANGUAGE" /> + <glz:Param name="movio.europeana.searchFieldsLabels" value="Titles,Creators,Subjects,Dates,Places,Media type,Language" /> + <glz:Param name="movio.europeana.registry" value="europeana" /> + <glz:Param name="FORM_ITEM_TEMPLATE"><![CDATA[ + <div class="control-group"> + ##FORM_LABEL## + <div class="controls"> + ##FORM_ITEM## + </div> + </div> + ]]></glz:Param> + <glz:Param name="FORM_ITEM_RIGHT_LABEL_TEMPLATE"><![CDATA[ + <div class="control-group"> + ##FORM_LABEL## + <div class="controls"> + ##FORM_ITEM## + </div> + </div> + ]]></glz:Param> +</glz:Config> \ No newline at end of file diff --git a/src/application/config/fieldTypes.xml b/src/application/config/fieldTypes.xml new file mode 100644 index 0000000..2ae4d00 --- /dev/null +++ b/src/application/config/fieldTypes.xml @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="utf-8"?> +<fieldTypes> + <fieldType id="attribute.text"> + <map_to>text</map_to> + <is_indexed>true</is_indexed> + <translation> + <it>Testo</it> + <en>Text</en> + </translation> + </fieldType> + <fieldType id="attribute.longtext"> + <map_to>text</map_to> + <is_indexed>true</is_indexed> + <translation> + <it>Testo lungo</it> + <en>Long text</en> + </translation> + </fieldType> + <fieldType id="attribute.descriptivetext"> + <map_to>text</map_to> + <is_indexed>true</is_indexed> + <translation> + <it>Testo descrittivo (html)</it> + <en>Descriptive text (html)</en> + </translation> + </fieldType> + <fieldType id="attribute.int"> + <map_to>integer</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Numerico</it> + <en>Numeric</en> + </translation> + </fieldType> + <fieldType id="attribute.date"> + <map_to>date</map_to> + <is_indexed>true</is_indexed> + <translation> + <it>Data</it> + <en>Date</en> + </translation> + </fieldType> + <fieldType id="attribute.image"> + <map_to>text</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Immagine</it> + <en>Image</en> + </translation> + </fieldType> + <fieldType id="attribute.imagelist"> + <map_to>object</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Elenco immagini</it> + <en>Image list</en> + </translation> + </fieldType> + <fieldType id="attribute.media"> + <map_to>text</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Media</it> + <en>Media</en> + </translation> + </fieldType> + <fieldType id="attribute.medialist"> + <map_to>object</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Elenco media</it> + <en>Media list</en> + </translation> + </fieldType> + <fieldType id="attribute.photogallery"> + <map_to>object</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Galleria fotografica</it> + <en>Photographic Gallery</en> + </translation> + </fieldType> + <fieldType id="attribute.openlist"> + <map_to>text</map_to> + <is_indexed>true</is_indexed> + <translation> + <it>Vocabolario aperto</it> + <en>Open Vocabulary</en> + </translation> + </fieldType> + <fieldType id="attribute.externalimage"> + <map_to>text</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Immagine esterna</it> + <en>External image</en> + </translation> + </fieldType> + <fieldType id="attribute.externallink"> + <map_to>text</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Link esterno</it> + <en>External link</en> + </translation> + </fieldType> + <fieldType id="attribute.internallink"> + <map_to>integer</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Link interno</it> + <en>Internal link</en> + </translation> + </fieldType> + <fieldType id="attribute.europeanaRelatedContents"> + <map_to>object</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Contenuti correlati europana</it> + <en>Europeana related contents</en> + </translation> + </fieldType> + <fieldType id="attribute.thesaurus"> + <map_to>object</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Dizionario</it> + <en>Thesaurus</en> + </translation> + </fieldType> + <fieldType id="attribute.module"> + <map_to>object</map_to> + <is_indexed>false</is_indexed> + <translation> + <it>Modulo</it> + <en>Module</en> + </translation> + </fieldType> +</fieldTypes> \ No newline at end of file diff --git a/src/application/config/routing.xml b/src/application/config/routing.xml new file mode 100644 index 0000000..7fcf430 --- /dev/null +++ b/src/application/config/routing.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:Routing> + <glz:Route name="ModuleDetail" value="{pageId}/{action=show}/{integer=document_id}/{value=title}" /> + + <glz:Route name="showEntityDetail" value="{pageId}/{pageTitle}/{action=show}/{value=entityTypeId}/{value=document_id}" cms:urlResolver="movio.modules.ontologybuilder.content" /> + + <glz:Route name="linkChangeAction" value="{pageId}/{pageTitle}/{value=action}" /> + + <glz:Route name="linkLogin" value="{pageId=Login}" /> + <glz:Route name="LinkRegistration" value="{pageId=Registration}" /> + <glz:Route name="linkLostpassword" value="{pageId=LostPassword}" /> + <glz:Route name="linkUserDetails" value="{pageId=UserDetails}" /> + <glz:Route name="linkUserProfileContents" value="{pageId=33}" /> + <glz:Route name="linkLogout" value="logout" pageId="login" action="logout" /> + + <glz:Route name="link" value="{pageId}/{pageTitle}" /> +</glz:Routing> \ No newline at end of file diff --git a/src/application/libs/captcha/CaptchaBuilder.php b/src/application/libs/captcha/CaptchaBuilder.php new file mode 100755 index 0000000..d03b53f --- /dev/null +++ b/src/application/libs/captcha/CaptchaBuilder.php @@ -0,0 +1,716 @@ +<?php + +namespace Gregwar\Captcha; + +use \Exception; + +/** + * Builds a new captcha image + * Uses the fingerprint parameter, if one is passed, to generate the same image + * + * @author Gregwar <g.passault@gmail.com> + * @author Jeremy Livingston <jeremy.j.livingston@gmail.com> + */ +class CaptchaBuilder implements CaptchaBuilderInterface +{ + /** + * @var array + */ + protected $fingerprint = array(); + + /** + * @var bool + */ + protected $useFingerprint = false; + + /** + * @var array + */ + protected $textColor = null; + + /** + * @var array + */ + protected $backgroundColor = null; + + /** + * @var array + */ + protected $backgroundImages = array(); + + /** + * @var resource + */ + protected $contents = null; + + /** + * @var string + */ + protected $phrase = null; + + /** + * @var PhraseBuilderInterface + */ + protected $builder; + + /** + * @var bool + */ + protected $distortion = true; + + /** + * The maximum number of lines to draw in front of + * the image. null - use default algorithm + */ + protected $maxFrontLines = null; + + /** + * The maximum number of lines to draw behind + * the image. null - use default algorithm + */ + protected $maxBehindLines = null; + + /** + * The maximum angle of char + */ + protected $maxAngle = 8; + + /** + * The maximum offset of char + */ + protected $maxOffset = 5; + + /** + * Is the interpolation enabled ? + * + * @var bool + */ + protected $interpolation = true; + + /** + * Ignore all effects + * + * @var bool + */ + protected $ignoreAllEffects = false; + + /** + * Allowed image types for the background images + * + * @var array + */ + protected $allowedBackgroundImageTypes = array('image/png', 'image/jpeg', 'image/gif'); + + /** + * The image contents + */ + public function getContents() + { + return $this->contents; + } + + /** + * Enable/Disables the interpolation + * + * @param $interpolate bool True to enable, false to disable + * + * @return CaptchaBuilder + */ + public function setInterpolation($interpolate = true) + { + $this->interpolation = $interpolate; + + return $this; + } + + /** + * Temporary dir, for OCR check + */ + public $tempDir = 'temp/'; + + public function __construct($phrase = null, PhraseBuilderInterface $builder = null) + { + if ($builder === null) { + $this->builder = new PhraseBuilder; + } else { + $this->builder = $builder; + } + + if ($phrase === null) { + $phrase = $this->builder->build(); + } + + $this->phrase = $phrase; + } + + /** + * Setting the phrase + */ + public function setPhrase($phrase) + { + $this->phrase = (string) $phrase; + } + + /** + * Enables/disable distortion + */ + public function setDistortion($distortion) + { + $this->distortion = (bool) $distortion; + + return $this; + } + + public function setMaxBehindLines($maxBehindLines) + { + $this->maxBehindLines = $maxBehindLines; + + return $this; + } + + public function setMaxFrontLines($maxFrontLines) + { + $this->maxFrontLines = $maxFrontLines; + + return $this; + } + + public function setMaxAngle($maxAngle) + { + $this->maxAngle = $maxAngle; + + return $this; + } + + public function setMaxOffset($maxOffset) + { + $this->maxOffset = $maxOffset; + + return $this; + } + + /** + * Gets the captcha phrase + */ + public function getPhrase() + { + return $this->phrase; + } + + /** + * Returns true if the given phrase is good + */ + public function testPhrase($phrase) + { + return ($this->builder->niceize($phrase) == $this->builder->niceize($this->getPhrase())); + } + + /** + * Instantiation + */ + public static function create($phrase = null) + { + return new self($phrase); + } + + /** + * Sets the text color to use + */ + public function setTextColor($r, $g, $b) + { + $this->textColor = array($r, $g, $b); + + return $this; + } + + /** + * Sets the background color to use + */ + public function setBackgroundColor($r, $g, $b) + { + $this->backgroundColor = array($r, $g, $b); + + return $this; + } + + /** + * Sets the ignoreAllEffects value + * + * @param bool $ignoreAllEffects + * @return CaptchaBuilder + */ + public function setIgnoreAllEffects($ignoreAllEffects) + { + $this->ignoreAllEffects = $ignoreAllEffects; + + return $this; + } + + /** + * Sets the list of background images to use (one image is randomly selected) + */ + public function setBackgroundImages(array $backgroundImages) + { + $this->backgroundImages = $backgroundImages; + + return $this; + } + + /** + * Draw lines over the image + */ + protected function drawLine($image, $width, $height, $tcol = null) + { + if ($tcol === null) { + $tcol = imagecolorallocate($image, $this->rand(100, 255), $this->rand(100, 255), $this->rand(100, 255)); + } + + if ($this->rand(0, 1)) { // Horizontal + $Xa = $this->rand(0, $width/2); + $Ya = $this->rand(0, $height); + $Xb = $this->rand($width/2, $width); + $Yb = $this->rand(0, $height); + } else { // Vertical + $Xa = $this->rand(0, $width); + $Ya = $this->rand(0, $height/2); + $Xb = $this->rand(0, $width); + $Yb = $this->rand($height/2, $height); + } + imagesetthickness($image, $this->rand(1, 3)); + imageline($image, $Xa, $Ya, $Xb, $Yb, $tcol); + } + + /** + * Apply some post effects + */ + protected function postEffect($image) + { + if (!function_exists('imagefilter')) { + return; + } + + if ($this->backgroundColor != null || $this->textColor != null) { + return; + } + + // Negate ? + if ($this->rand(0, 1) == 0) { + imagefilter($image, IMG_FILTER_NEGATE); + } + + // Edge ? + if ($this->rand(0, 10) == 0) { + imagefilter($image, IMG_FILTER_EDGEDETECT); + } + + // Contrast + imagefilter($image, IMG_FILTER_CONTRAST, $this->rand(-50, 10)); + + // Colorize + if ($this->rand(0, 5) == 0) { + imagefilter($image, IMG_FILTER_COLORIZE, $this->rand(-80, 50), $this->rand(-80, 50), $this->rand(-80, 50)); + } + } + + /** + * Writes the phrase on the image + */ + protected function writePhrase($image, $phrase, $font, $width, $height) + { + // Gets the text size and start position + $size = $width / strlen($phrase) - $this->rand(0, 3) - 1; + $box = imagettfbbox($size, 0, $font, $phrase); + $textWidth = $box[2] - $box[0]; + $textHeight = $box[1] - $box[7]; + $x = ($width - $textWidth) / 2; + $y = ($height - $textHeight) / 2 + $size; + + if (!count($this->textColor)) { + $textColor = array($this->rand(0, 150), $this->rand(0, 150), $this->rand(0, 150)); + } else { + $textColor = $this->textColor; + } + $col = imagecolorallocate($image, $textColor[0], $textColor[1], $textColor[2]); + + // Write the letters one by one, with random angle + $length = strlen($phrase); + for ($i=0; $i<$length; $i++) { + $box = imagettfbbox($size, 0, $font, $phrase[$i]); + $w = $box[2] - $box[0]; + $angle = $this->rand(-$this->maxAngle, $this->maxAngle); + $offset = $this->rand(-$this->maxOffset, $this->maxOffset); + imagettftext($image, $size, $angle, $x, $y + $offset, $col, $font, $phrase[$i]); + $x += $w; + } + + return $col; + } + + /** + * Try to read the code against an OCR + */ + public function isOCRReadable() + { + if (!is_dir($this->tempDir)) { + @mkdir($this->tempDir, 0755, true); + } + + $tempj = $this->tempDir . uniqid('captcha', true) . '.jpg'; + $tempp = $this->tempDir . uniqid('captcha', true) . '.pgm'; + + $this->save($tempj); + shell_exec("convert $tempj $tempp"); + $value = trim(strtolower(shell_exec("ocrad $tempp"))); + + @unlink($tempj); + @unlink($tempp); + + return $this->testPhrase($value); + } + + /** + * Builds while the code is readable against an OCR + */ + public function buildAgainstOCR($width = 150, $height = 40, $font = null, $fingerprint = null) + { + do { + $this->build($width, $height, $font, $fingerprint); + } while ($this->isOCRReadable()); + } + + /** + * Generate the image + */ + public function build($width = 150, $height = 40, $font = null, $fingerprint = null) + { + if (null !== $fingerprint) { + $this->fingerprint = $fingerprint; + $this->useFingerprint = true; + } else { + $this->fingerprint = array(); + $this->useFingerprint = false; + } + + if ($font === null) { + $font = __DIR__ . '/Font/captcha'.$this->rand(0, 5).'.ttf'; + } + + if (empty($this->backgroundImages)) { + // if background images list is not set, use a color fill as a background + $image = imagecreatetruecolor($width, $height); + if ($this->backgroundColor == null) { + $bg = imagecolorallocate($image, $this->rand(200, 255), $this->rand(200, 255), $this->rand(200, 255)); + } else { + $color = $this->backgroundColor; + $bg = imagecolorallocate($image, $color[0], $color[1], $color[2]); + } + $this->background = $bg; + imagefill($image, 0, 0, $bg); + } else { + // use a random background image + $randomBackgroundImage = $this->backgroundImages[rand(0, count($this->backgroundImages)-1)]; + + $imageType = $this->validateBackgroundImage($randomBackgroundImage); + + $image = $this->createBackgroundImageFromType($randomBackgroundImage, $imageType); + } + + // Apply effects + if (!$this->ignoreAllEffects) { + $square = $width * $height; + $effects = $this->rand($square/3000, $square/2000); + + // set the maximum number of lines to draw in front of the text + if ($this->maxBehindLines != null && $this->maxBehindLines > 0) { + $effects = min($this->maxBehindLines, $effects); + } + + if ($this->maxBehindLines !== 0) { + for ($e = 0; $e < $effects; $e++) { + $this->drawLine($image, $width, $height); + } + } + } + + // Write CAPTCHA text + $color = $this->writePhrase($image, $this->phrase, $font, $width, $height); + + // Apply effects + if (!$this->ignoreAllEffects) { + $square = $width * $height; + $effects = $this->rand($square/3000, $square/2000); + + // set the maximum number of lines to draw in front of the text + if ($this->maxFrontLines != null && $this->maxFrontLines > 0) { + $effects = min($this->maxFrontLines, $effects); + } + + if ($this->maxFrontLines !== 0) { + for ($e = 0; $e < $effects; $e++) { + $this->drawLine($image, $width, $height, $color); + } + } + } + + // Distort the image + if ($this->distortion && !$this->ignoreAllEffects) { + $image = $this->distort($image, $width, $height, $bg); + } + + // Post effects + if (!$this->ignoreAllEffects) { + $this->postEffect($image); + } + + $this->contents = $image; + + return $this; + } + + /** + * Distorts the image + */ + public function distort($image, $width, $height, $bg) + { + $contents = imagecreatetruecolor($width, $height); + $X = $this->rand(0, $width); + $Y = $this->rand(0, $height); + $phase = $this->rand(0, 10); + $scale = 1.1 + $this->rand(0, 10000) / 30000; + for ($x = 0; $x < $width; $x++) { + for ($y = 0; $y < $height; $y++) { + $Vx = $x - $X; + $Vy = $y - $Y; + $Vn = sqrt($Vx * $Vx + $Vy * $Vy); + + if ($Vn != 0) { + $Vn2 = $Vn + 4 * sin($Vn / 30); + $nX = $X + ($Vx * $Vn2 / $Vn); + $nY = $Y + ($Vy * $Vn2 / $Vn); + } else { + $nX = $X; + $nY = $Y; + } + $nY = $nY + $scale * sin($phase + $nX * 0.2); + + if ($this->interpolation) { + $p = $this->interpolate( + $nX - floor($nX), + $nY - floor($nY), + $this->getCol($image, floor($nX), floor($nY), $bg), + $this->getCol($image, ceil($nX), floor($nY), $bg), + $this->getCol($image, floor($nX), ceil($nY), $bg), + $this->getCol($image, ceil($nX), ceil($nY), $bg) + ); + } else { + $p = $this->getCol($image, round($nX), round($nY), $bg); + } + + if ($p == 0) { + $p = $bg; + } + + imagesetpixel($contents, $x, $y, $p); + } + } + + return $contents; + } + + /** + * Saves the Captcha to a jpeg file + */ + public function save($filename, $quality = 90) + { + imagejpeg($this->contents, $filename, $quality); + } + + /** + * Gets the image GD + */ + public function getGd() + { + return $this->contents; + } + + /** + * Gets the image contents + */ + public function get($quality = 90) + { + ob_start(); + $this->output($quality); + + return ob_get_clean(); + } + + /** + * Gets the HTML inline base64 + */ + public function inline($quality = 90) + { + return 'data:image/jpeg;base64,' . base64_encode($this->get($quality)); + } + + /** + * Outputs the image + */ + public function output($quality = 90) + { + imagejpeg($this->contents, null, $quality); + } + + /** + * @return array + */ + public function getFingerprint() + { + return $this->fingerprint; + } + + /** + * Returns a random number or the next number in the + * fingerprint + */ + protected function rand($min, $max) + { + if (!is_array($this->fingerprint)) { + $this->fingerprint = array(); + } + + if ($this->useFingerprint) { + $value = current($this->fingerprint); + next($this->fingerprint); + } else { + $value = mt_rand($min, $max); + $this->fingerprint[] = $value; + } + + return $value; + } + + /** + * @param $x + * @param $y + * @param $nw + * @param $ne + * @param $sw + * @param $se + * + * @return int + */ + protected function interpolate($x, $y, $nw, $ne, $sw, $se) + { + list($r0, $g0, $b0) = $this->getRGB($nw); + list($r1, $g1, $b1) = $this->getRGB($ne); + list($r2, $g2, $b2) = $this->getRGB($sw); + list($r3, $g3, $b3) = $this->getRGB($se); + + $cx = 1.0 - $x; + $cy = 1.0 - $y; + + $m0 = $cx * $r0 + $x * $r1; + $m1 = $cx * $r2 + $x * $r3; + $r = (int) ($cy * $m0 + $y * $m1); + + $m0 = $cx * $g0 + $x * $g1; + $m1 = $cx * $g2 + $x * $g3; + $g = (int) ($cy * $m0 + $y * $m1); + + $m0 = $cx * $b0 + $x * $b1; + $m1 = $cx * $b2 + $x * $b3; + $b = (int) ($cy * $m0 + $y * $m1); + + return ($r << 16) | ($g << 8) | $b; + } + + /** + * @param $image + * @param $x + * @param $y + * + * @return int + */ + protected function getCol($image, $x, $y, $background) + { + $L = imagesx($image); + $H = imagesy($image); + if ($x < 0 || $x >= $L || $y < 0 || $y >= $H) { + return $background; + } + + return imagecolorat($image, $x, $y); + } + + /** + * @param $col + * + * @return array + */ + protected function getRGB($col) + { + return array( + (int) ($col >> 16) & 0xff, + (int) ($col >> 8) & 0xff, + (int) ($col) & 0xff, + ); + } + + /** + * Validate the background image path. Return the image type if valid + * + * @param string $backgroundImage + * @return string + * @throws Exception + */ + protected function validateBackgroundImage($backgroundImage) + { + // check if file exists + if (!file_exists($backgroundImage)) { + $backgroundImageExploded = explode('/', $backgroundImage); + $imageFileName = count($backgroundImageExploded) > 1? $backgroundImageExploded[count($backgroundImageExploded)-1] : $backgroundImage; + + throw new Exception('Invalid background image: ' . $imageFileName); + } + + // check image type + $finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension + $imageType = finfo_file($finfo, $backgroundImage); + finfo_close($finfo); + + if (!in_array ($imageType, $this->allowedBackgroundImageTypes)) { + throw new Exception('Invalid background image type! Allowed types are: ' . join(', ', $this->allowedBackgroundImageTypes)); + } + + return $imageType; + } + + /** + * Create background image from type + * + * @param string $backgroundImage + * @param string $imageType + * @return resource + * @throws Exception + */ + protected function createBackgroundImageFromType($backgroundImage, $imageType) + { + switch ($imageType) { + case 'image/jpeg': + $image = imagecreatefromjpeg($backgroundImage); + break; + case 'image/png': + $image = imagecreatefrompng($backgroundImage); + break; + case 'image/gif': + $image = imagecreatefromgif($backgroundImage); + break; + + default: + throw new Exception('Not supported file type for background image!'); + break; + } + + return $image; + } +} diff --git a/src/application/libs/captcha/CaptchaBuilderInterface.php b/src/application/libs/captcha/CaptchaBuilderInterface.php new file mode 100755 index 0000000..bdebf38 --- /dev/null +++ b/src/application/libs/captcha/CaptchaBuilderInterface.php @@ -0,0 +1,30 @@ +<?php + +namespace Gregwar\Captcha; + +/** + * A Captcha builder + */ +interface CaptchaBuilderInterface +{ + /** + * Builds the code + */ + public function build($width, $height, $font, $fingerprint); + + /** + * Saves the code to a file + */ + public function save($filename, $quality); + + /** + * Gets the image contents + */ + public function get($quality); + + /** + * Outputs the image + */ + public function output($quality); +} + diff --git a/src/application/libs/captcha/Font/captcha0.ttf b/src/application/libs/captcha/Font/captcha0.ttf new file mode 100755 index 0000000000000000000000000000000000000000..139f0b4311ad2e0369a347b3be6c46e6c2b730d5 GIT binary patch literal 49224 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 literal 0 HcmV?d00001 diff --git a/src/application/libs/captcha/Font/captcha1.ttf b/src/application/libs/captcha/Font/captcha1.ttf new file mode 100755 index 0000000000000000000000000000000000000000..bb1abf6b6696261ffdfd5c17b74dfb03ce7c72b5 GIT binary patch literal 76232 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 E9p1;Cxc~qF literal 0 HcmV?d00001 diff --git a/src/application/libs/captcha/Font/captcha2.ttf b/src/application/libs/captcha/Font/captcha2.ttf new file mode 100755 index 0000000000000000000000000000000000000000..8d1f31e88739c0df917c030457760a25a3ced93d GIT binary patch literal 33984 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 Lfo1=BJfr^y1a>_i literal 0 HcmV?d00001 diff --git a/src/application/libs/captcha/Font/captcha3.ttf b/src/application/libs/captcha/Font/captcha3.ttf new file mode 100755 index 0000000000000000000000000000000000000000..d232902cf89aca63cb9a92ad4893ffddcf2eb63d GIT binary patch literal 15976 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 E3yqV3z5oCK literal 0 HcmV?d00001 diff --git a/src/application/libs/captcha/Font/captcha4.ttf b/src/application/libs/captcha/Font/captcha4.ttf new file mode 100755 index 0000000000000000000000000000000000000000..ab154440d796a815274ff79060759b5d1668b430 GIT binary patch literal 906980 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 literal 0 HcmV?d00001 diff --git a/src/application/libs/captcha/Font/captcha5.ttf b/src/application/libs/captcha/Font/captcha5.ttf new file mode 100755 index 0000000000000000000000000000000000000000..f7cd998656b6ca8b1fb2e82fe63fa19f97c4c2c0 GIT binary patch literal 49724 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 M!`$=T<I8#f3*$4osQ>@~ literal 0 HcmV?d00001 diff --git a/src/application/libs/captcha/ImageFileHandler.php b/src/application/libs/captcha/ImageFileHandler.php new file mode 100755 index 0000000..6b6bdb8 --- /dev/null +++ b/src/application/libs/captcha/ImageFileHandler.php @@ -0,0 +1,106 @@ +<?php + +namespace Gregwar\Captcha; + +use Symfony\Component\Finder\Finder; + +/** + * Handles actions related to captcha image files including saving and garbage collection + * + * @author Gregwar <g.passault@gmail.com> + * @author Jeremy Livingston <jeremy@quizzle.com> + */ +class ImageFileHandler +{ + /** + * Name of folder for captcha images + * @var string + */ + protected $imageFolder; + + /** + * Absolute path to public web folder + * @var string + */ + protected $webPath; + + /** + * Frequency of garbage collection in fractions of 1 + * @var int + */ + protected $gcFreq; + + /** + * Maximum age of images in minutes + * @var int + */ + protected $expiration; + + /** + * @param $imageFolder + * @param $webPath + * @param $gcFreq + * @param $expiration + */ + public function __construct($imageFolder, $webPath, $gcFreq, $expiration) + { + $this->imageFolder = $imageFolder; + $this->webPath = $webPath; + $this->gcFreq = $gcFreq; + $this->expiration = $expiration; + } + + /** + * Saves the provided image content as a file + * + * @param string $contents + * + * @return string + */ + public function saveAsFile($contents) + { + $this->createFolderIfMissing(); + + $filename = md5(uniqid()) . '.jpg'; + $filePath = $this->webPath . '/' . $this->imageFolder . '/' . $filename; + imagejpeg($contents, $filePath, 15); + + return '/' . $this->imageFolder . '/' . $filename; + } + + /** + * Randomly runs garbage collection on the image directory + * + * @return bool + */ + public function collectGarbage() + { + if (!mt_rand(1, $this->gcFreq) == 1) { + return false; + } + + $this->createFolderIfMissing(); + + $finder = new Finder(); + $criteria = sprintf('<= now - %s minutes', $this->expiration); + $finder->in($this->webPath . '/' . $this->imageFolder) + ->date($criteria); + + foreach($finder->files() as $file) { + unlink($file->getPathname()); + } + + return true; + } + + /** + * Creates the folder if it doesn't exist + */ + protected function createFolderIfMissing() + { + if (!file_exists($this->webPath . '/' . $this->imageFolder)) { + mkdir($this->webPath . '/' . $this->imageFolder, 0755); + } + } +} + diff --git a/src/application/libs/captcha/LICENSE b/src/application/libs/captcha/LICENSE new file mode 100755 index 0000000..7db6ad8 --- /dev/null +++ b/src/application/libs/captcha/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) <2012-2015> Grégoire Passault + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/application/libs/captcha/PhraseBuilder.php b/src/application/libs/captcha/PhraseBuilder.php new file mode 100755 index 0000000..b94bd61 --- /dev/null +++ b/src/application/libs/captcha/PhraseBuilder.php @@ -0,0 +1,34 @@ +<?php + +namespace Gregwar\Captcha; + +/** + * Generates random phrase + * + * @author Gregwar <g.passault@gmail.com> + */ +class PhraseBuilder implements PhraseBuilderInterface +{ + /** + * Generates random phrase of given length with given charset + */ + public function build($length = 5, $charset = 'abcdefghijklmnpqrstuvwxyz123456789') + { + $phrase = ''; + $chars = str_split($charset); + + for ($i = 0; $i < $length; $i++) { + $phrase .= $chars[array_rand($chars)]; + } + + return $phrase; + } + + /** + * "Niceize" a code + */ + public function niceize($str) + { + return strtr(strtolower($str), '01', 'ol'); + } +} diff --git a/src/application/libs/captcha/PhraseBuilderInterface.php b/src/application/libs/captcha/PhraseBuilderInterface.php new file mode 100755 index 0000000..0a4f536 --- /dev/null +++ b/src/application/libs/captcha/PhraseBuilderInterface.php @@ -0,0 +1,21 @@ +<?php + +namespace Gregwar\Captcha; + +/** + * Interface for the PhraseBuilder + * + * @author Gregwar <g.passault@gmail.com> + */ +interface PhraseBuilderInterface +{ + /** + * Generates random phrase of given length with given charset + */ + public function build($length, $charset); + + /** + * "Niceize" a code + */ + public function niceize($str); +} diff --git a/src/application/libs/captcha/README.md b/src/application/libs/captcha/README.md new file mode 100755 index 0000000..9f6c17a --- /dev/null +++ b/src/application/libs/captcha/README.md @@ -0,0 +1,108 @@ +Captcha +======= + +![Captchas examples](http://gregwar.com/captchas.png) + +Installation +============ + +With composer : + +``` json +{ + ... + "require": { + "gregwar/captcha": "1.*" + } +} +``` + +Usage +===== + +You can create a captcha with the `CaptchaBuilder` : + +```php +<?php + +use Gregwar\Captcha\CaptchaBuilder; + +$builder = new CaptchaBuilder; +$builder->build(); +``` + +You can then save it to a file : + +```php +<?php + +$builder->save('out.jpg'); +``` + +Or output it directly : + +```php +<?php + +header('Content-type: image/jpeg'); +$builder->output(); +``` + +Or inline it directly in the HTML page: + +```php +<img src="<?php echo $builder->inline(); ?>" /> +``` + +You'll be able to get the code and compare it with a user input : + +```php +<?php + +// Example: storing the phrase in the session to test for the user +// input later +$_SESSION['phrase'] = $builder->getPhrase(); +``` + +You can compare the phrase with user input: +```php +if($builder->testPhrase($userInput)) { + // instructions if user phrase is good +} +else { + // user phrase is wrong +} +``` + +API +=== + +You can use theses functions : + +* **__construct($phrase = null)**, constructs the builder with the given phrase, if the phrase is null, a random one will be generated +* **getPhrase()**, allow you to get the phrase contents +* **setDistortion($distortion)**, enable or disable the distortion, call it before `build()` +* **isOCRReadable()**, returns `true` if the OCR can be read using the `ocrad` software, you'll need to have shell_exec enabled, imagemagick and ocrad installed +* **buildAgainstOCR($width = 150, $height = 40, $font = null)**, builds a code until it is not readable by `ocrad` +* **build($width = 150, $height = 40, $font = null)**, builds a code with the given $width, $height and $font. By default, a random font will be used from the library +* **save($filename, $quality = 80)**, saves the captcha into a jpeg in the $filename, with the given quality +* **get($quality = 80)**, returns the jpeg data +* **output($quality = 80)**, directly outputs the jpeg code to a browser +* **setBackgroundColor($r, $g, $b)**, sets the background color to force it (this will disable many effects and is not recommended) +* **setBackgroundImages(array($imagepath1, $imagePath2))**, Sets custom background images to be used as captcha background. It is recommended to disable image effects when passing custom images for background (ignore_all_effects). A random image is selected from the list passed, the full paths to the image files must be passed. +* **setInterpolation($interpolate)**, enable or disable the interpolation (enabled by default), disabling it will be quicker but the images will look uglier +* **setIgnoreAllEffects($ignoreAllEffects)**, disable all effects on the captcha image. Recommended to use when passing custom background images for the captcha. +* **testPhrase($phrase)**, returns true if the given phrase is good +* **setMaxBehindLines($lines)**, sets the maximum number of lines behind the code +* **setMaxFrontLines($lines)**, sets the maximum number of lines on the front of the code + +Symfony 2 Bundle +================ + +You can have a look at the following repository to enjoy the Symfony 2 bundle packaging this captcha generator : +https://github.com/Gregwar/CaptchaBundle + +License +======= + +This library is under MIT license, have a look to the `LICENSE` file diff --git a/src/application/libs/captcha/autoload.php b/src/application/libs/captcha/autoload.php new file mode 100755 index 0000000..8b3fa39 --- /dev/null +++ b/src/application/libs/captcha/autoload.php @@ -0,0 +1,16 @@ +<?php + +/** +* Registers an autoload for all the classes in Gregwar\Captcha +*/ +spl_autoload_register(function ($className) { + $namespace = 'Gregwar\\Captcha'; + + if (strpos($className, $namespace) === 0) { + $className = str_replace($namespace, '', $className); + $fileName = __DIR__ . '/' . str_replace('\\', '/', $className) . '.php'; + if (file_exists($fileName)) { + require($fileName); + } + } +}); diff --git a/src/application/libs/captcha/composer.json b/src/application/libs/captcha/composer.json new file mode 100755 index 0000000..ef79423 --- /dev/null +++ b/src/application/libs/captcha/composer.json @@ -0,0 +1,28 @@ +{ + "name": "gregwar/captcha", + "type": "captcha", + "description": "Captcha generator", + "keywords": ["captcha", "spam", "bot"], + "homepage": "https://github.com/Gregwar/Captcha", + "license": "MIT", + "authors": [ + { + "name": "Grégoire Passault", + "email": "g.passault@gmail.com", + "homepage": "http://www.gregwar.com/" + }, + { + "name": "Jeremy Livingston", + "email": "jeremy.j.livingston@gmail.com" + } + ], + "require": { + "php": ">=5.3.0", + "ext-gd": "*" + }, + "autoload": { + "psr-4": { + "Gregwar\\Captcha\\": "/" + } + } +} diff --git a/src/application/libs/captcha/demo/demo.php b/src/application/libs/captcha/demo/demo.php new file mode 100755 index 0000000..7852745 --- /dev/null +++ b/src/application/libs/captcha/demo/demo.php @@ -0,0 +1,14 @@ +<?php + +include(__DIR__.'/../CaptchaBuilderInterface.php'); +include(__DIR__.'/../PhraseBuilderInterface.php'); +include(__DIR__.'/../CaptchaBuilder.php'); +include(__DIR__.'/../PhraseBuilder.php'); + +use Gregwar\Captcha\CaptchaBuilder; + +$captcha = new CaptchaBuilder; +$captcha + ->build() + ->save('out.jpg') +; diff --git a/src/application/libs/captcha/demo/fingerprint.php b/src/application/libs/captcha/demo/fingerprint.php new file mode 100755 index 0000000..ce30d99 --- /dev/null +++ b/src/application/libs/captcha/demo/fingerprint.php @@ -0,0 +1,15 @@ +<?php + +include(__DIR__.'/../CaptchaBuilderInterface.php'); +include(__DIR__.'/../PhraseBuilderInterface.php'); +include(__DIR__.'/../CaptchaBuilder.php'); +include(__DIR__.'/../PhraseBuilder.php'); + +use Gregwar\Captcha\CaptchaBuilder; + +echo count(CaptchaBuilder::create() + ->build() + ->getFingerprint() +); + +echo "\n"; diff --git a/src/application/libs/captcha/demo/index.php b/src/application/libs/captcha/demo/index.php new file mode 100755 index 0000000..e543883 --- /dev/null +++ b/src/application/libs/captcha/demo/index.php @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<body> + <html> + <meta charset="utf-8" /> + </html> + <body> + <h1>Captchas gallery</h1> + <?php for ($x=0; $x<8; $x++) { ?> + <?php for ($y=0; $y<5; $y++) { ?> + <img src="output.php?n=<?php echo 5*$x+$y; ?>" /> + <?php } ?> + <br /> + <?php } ?> + </body> +</body> diff --git a/src/application/libs/captcha/demo/ocr.php b/src/application/libs/captcha/demo/ocr.php new file mode 100755 index 0000000..3d745f6 --- /dev/null +++ b/src/application/libs/captcha/demo/ocr.php @@ -0,0 +1,42 @@ +<?php + +include(__DIR__.'/../CaptchaBuilderInterface.php'); +include(__DIR__.'/../PhraseBuilderInterface.php'); +include(__DIR__.'/../CaptchaBuilder.php'); +include(__DIR__.'/../PhraseBuilder.php'); + +use Gregwar\Captcha\CaptchaBuilder; + +/** + * Generates 1000 captchas and try to read their code with the + * ocrad OCR + */ + +$tests = 10000; +$passed = 0; + +shell_exec('rm passed*.jpg'); + +for ($i=0; $i<$tests; $i++) { + echo "Captcha $i/$tests... "; + + $captcha = new CaptchaBuilder; + + $captcha + ->setDistortion(false) + ->build() + ; + + if ($captcha->isOCRReadable()) { + $passed++; + $captcha->save("passed$passed.jpg"); + echo "passed at ocr... "; + } else { + echo "failed... "; + } + + echo "pass rate: ".round(100*$passed/($i+1),2)."%\n"; +} + +echo "\n"; +echo "Over, $passed/$tests readed with OCR\n"; diff --git a/src/application/libs/captcha/demo/output.php b/src/application/libs/captcha/demo/output.php new file mode 100755 index 0000000..2a4f330 --- /dev/null +++ b/src/application/libs/captcha/demo/output.php @@ -0,0 +1,15 @@ +<?php + +include(__DIR__.'/../CaptchaBuilderInterface.php'); +include(__DIR__.'/../PhraseBuilderInterface.php'); +include(__DIR__.'/../CaptchaBuilder.php'); +include(__DIR__.'/../PhraseBuilder.php'); + +use Gregwar\Captcha\CaptchaBuilder; + +header('Content-type: image/jpeg'); + +CaptchaBuilder::create() + ->build() + ->output() +; diff --git a/src/application/libs/openzoom/Oz/Deepzoom/Descriptor.php b/src/application/libs/openzoom/Oz/Deepzoom/Descriptor.php new file mode 100755 index 0000000..f3d5d9a --- /dev/null +++ b/src/application/libs/openzoom/Oz/Deepzoom/Descriptor.php @@ -0,0 +1,229 @@ +<?php +/** +* Deep Zoom Tools +* +* Copyright (c) 2008-2009, OpenZoom <http://openzoom.org/> +* Copyright (c) 2008-2009, Nicolas Fabre <nicolas.fabre@gmail.com> +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of OpenZoom nor the names of its contributors may be used +* to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @see Oz_Deezoom_Exception + */ +require 'Oz/Deepzoom/Exception.php'; +/** + * + * + * @category Oz + * @package Oz_Deepzoom + * @author Nicolas Fabre <nicolas.fabre@gmail.com> + */ +class Oz_Deepzoom_Descriptor { + /** + * Template XML + */ + const DZI_TEMPLATE = '<?xml version="1.0" encoding="UTF-8"?> +<Image TileSize="%s" Overlap="%s" Format="%s" xmlns="http://schemas.microsoft.com/deepzoom/2008"> + <Size Width="%s" Height="%s"/> +</Image>'; + + /** + * Width of the original image + * + * @var int + */ + protected $_width; + /** + * Height of the original image + * + * @var int + */ + protected $_height; + /** + * Tile size + * + * @var int + */ + protected $_tileSize; + /** + * Tile overlap + * + * @var float + */ + protected $_tileOverlap; + /** + * Image format + * + * @var string + */ + protected $_tileFormat; + /** + * Number of levels in the pyramid + * + * @var int + */ + protected $_numLevels = null; + + /** + * Constructor + * + * @param int $width + * @param int $height + * @param int $tileSize + * @param int $tileOverlap + * @param string $tileFormat + * @return void + */ + public function __construct($width=null,$height=null,$tileSize=254,$tileOverlap=1,$tileFormat="jpg") { + $this->_width = $width; + $this->_height = $height; + $this->_tileSize = $tileSize; + $this->_tileOverlap = $tileOverlap; + $this->_tileFormat = $tileFormat; + } + + /** + * Enter description here... + * + * @param string $name + * @return mixed + */ + public function __get($name) { + return $this->{'_'.$name}; + } + + /** + * Intialize descriptor from an existing descriptor file + * + * @param string $source + * @return + */ + public function open($source) { + $xml = simplexml_load_file($source); + $this->_width = (int)$xml->Size["Width"]; + $this->_height = (int)$xml->Size["Height"]; + $this->_tileSize = (string)$xml["TileSize"]; + $this->_tileOverlap = (string)$xml["Overlap"]; + $this->_tileFormat = (string)$xml["Format"]; + return $this; + } + + /** + * Save descriptor file + * + * @param string $source + * @return Oz_Deepzoom_Descriptor + */ + public function save($source) { + file_put_contents($source, + sprintf(self::DZI_TEMPLATE, + $this->_tileSize,$this->_tileOverlap,$this->_tileFormat, + $this->_width,$this->_height)); + return $this; + } + + /** + * Number of levels in the pyramid + * + * @return int + */ + public function numLevels() { + if (empty($this->_numLevels)) { + $maxDimension = max(array($this->_width,$this->_height)); + $this->_numLevels = (int)ceil(log($maxDimension,2)) + 1; + } + return $this->_numLevels; + } + + /** + * Scale of a pyramid level + * + * @param int $level + * @return float + */ + public function getScale($level) { + if(0 <= $level and $level < $this->numLevels()) { + $maxLevel = $this->numLevels() - 1 ; + return pow(0.5,$maxLevel - $level); + } else throw new Oz_Deepzoom_Exception("Invalid pyramid level (scale)"); + } + + /** + * Dimensions of level (width, height) + * + * @param int $level + * @return array + */ + public function getDimension($level) { + if(0 <= $level and $level < $this->numLevels()) { + $scale = $this->getScale($level); + $width = (int)ceil($this->_width * $scale); + $height = (int)ceil($this->_height * $scale); + return array($width,$height); + } else throw new Oz_Deepzoom_Exception("Invalid pyramid level (dimension)"); + } + + /** + * Number of tiles (columns, rows) + * + * @param int $level + * @return array + */ + public function getNumTiles($level) { + if(0 <= $level and $level < $this->numLevels()) { + list($width,$height) = $this->getDimension($level); + $columns = (int)ceil(floatval($width) / $this->_tileSize); + $rows = (int)ceil(floatval($height) / $this->_tileSize); + return array($columns, $rows); + } else throw new Oz_Deepzoom_Exception("Invalid pyramid level (NumTiles)"); + } + + /** + * Bounding box of the tile (x1, y1, width, height) + * + * @param int $level pyramid level + * @param int $column + * @param int $row + * @return array + */ + public function getTileBounds($level, $column, $row) { + if(0 <= $level and $level < $this->numLevels()) { + $offsetX = $column == 0 ? 0 : $this->_tileOverlap; + $offsetY = $row == 0 ? 0 : $this->_tileOverlap; + $x = ($column * $this->_tileSize) - $offsetX; + $y = ($row * $this->_tileSize) - $offsetY; + + list($levelWidth,$levelHeight) = $this->getDimension($level); + $width = $this->_tileSize + ($column == 0 ? 1 : 2) * $this->_tileOverlap; + $height = $this->_tileSize + ($row == 0 ? 1 : 2) * $this->_tileOverlap; + $width = min($width, $levelWidth - $x); + $height = min($height, $levelHeight - $y); + return array($x, $y, $width, $height); + } else throw new Oz_Deepzoom_Exception("Invalid pyramid level (TileBounds)"); + } +} \ No newline at end of file diff --git a/src/application/libs/openzoom/Oz/Deepzoom/Exception.php b/src/application/libs/openzoom/Oz/Deepzoom/Exception.php new file mode 100755 index 0000000..97a0b6d --- /dev/null +++ b/src/application/libs/openzoom/Oz/Deepzoom/Exception.php @@ -0,0 +1,42 @@ +<?php +/** +* Deep Zoom Tools +* +* Copyright (c) 2008-2009, OpenZoom <http://openzoom.org/> +* Copyright (c) 2008-2009, Nicolas Fabre <nicolas.fabre@gmail.com> +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of OpenZoom nor the names of its contributors may be used +* to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * + * + * @category Oz + * @package Oz_Deepzoom + * @author Nicolas Fabre <nicolas.fabre@gmail.com> + */ +class Oz_Deepzoom_Exception extends Exception {} \ No newline at end of file diff --git a/src/application/libs/openzoom/Oz/Deepzoom/ImageCreator.php b/src/application/libs/openzoom/Oz/Deepzoom/ImageCreator.php new file mode 100755 index 0000000..4808e2f --- /dev/null +++ b/src/application/libs/openzoom/Oz/Deepzoom/ImageCreator.php @@ -0,0 +1,197 @@ +<?php +/** +* Deep Zoom Tools +* +* Copyright (c) 2008-2009, OpenZoom <http://openzoom.org/> +* Copyright (c) 2008-2009, Nicolas Fabre <nicolas.fabre@gmail.com> +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* 3. Neither the name of OpenZoom nor the names of its contributors may be used +* to endorse or promote products derived from this software without +* specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + * @see Thumbnail + */ +require 'thumbnail.inc.php'; +require 'Oz/Deepzoom/Descriptor.php'; + + +/** + * Creates Deep Zoom images + * + * @category Oz + * @package Oz_Deepzoom + * @author Nicolas Fabre <nicolas.fabre@gmail.com> + */ +class Oz_Deepzoom_ImageCreator { + + /** + * @var string + */ + protected $_tileSize; + /** + * @var float + */ + protected $_tileOverlap; + protected $_tileFormat; + protected $_imageQuality; + protected $_resizeFilter; + /** + * @var Oz_Deepzoom_Image + */ + protected $_image; + + /** + * @var Oz_Deepzoom_Descriptor + */ + protected $_descriptor; + + /** + * Constructor + * + * @param int $tileSize + * @param int $tileOverlap + * @param string $tileFormat + * @param float $imageQuality + * @param int $resizeFilter + */ + public function __construct($tileSize=254, $tileOverlap=1, $tileFormat="jpg", $imageQuality=0.95, $resizeFilter = null) { + $this->_tileSize = (int) $tileSize; + $this->_tileFormat = $tileFormat; + $this->_tileOverlap = $this->_clamp((int)$tileOverlap,0,1); + $this->_resizeFilter = $resizeFilter; + } + + /** + * Returns the bitmap image at the given level + * + * @param int $level + * + * @return Gr_Image + */ + public function getImage($level) { + if(0 <= $level and $level < $this->_descriptor->numLevels()) { + list($width, $height) = $this->_descriptor->getDimension($level); + + // don't transform to what we already have + if($this->_descriptor->width == $width and $this->_descriptor->height == $height) { + return $this->_image; + } + else { + $image = clone $this->_image; + $image->resize($width,$height); + return $image; + } + } else new Oz_Deepzoom_Exception('Invalid pyramid level'); + } + + /** + * Iterator for all tiles in the given level. Returns (column, row) of a tile. + * + * @param int $level + * + * @return array + */ + public function tiles($level) { + list($columns, $rows) = $this->_descriptor->getNumTiles($level); + $yield = array(); + foreach (range(0, $columns - 1) as $column) { + foreach (range(0, $rows - 1) as $row) { + $yield[] = array($column,$row); + } + } + return $yield; + } + + /** + * Creates Deep Zoom image from source file and saves it to destination + * + * @param string $source + * @param string $destination + */ + public function create($source,$destination) { + $this->_image = new Thumbnail($source); + list($width, $height) = $this->_image->size(); + $this->_descriptor = new Oz_Deepzoom_Descriptor($width,$height,$this->_tileSize,$this->_tileOverlap,$this->_tileFormat); + $aImage = pathinfo($destination); + /** + * @todo secure varaibles + */ + $imageName = $aImage['filename']; + $dirName = $aImage['dirname']; + $imageFile = $this->_ensure($dirName.DIRECTORY_SEPARATOR.$imageName.'_files'); + foreach (range(9,$this->_descriptor->numLevels() - 1) as $level) { + $levelDir = $this->_ensure($imageFile.DIRECTORY_SEPARATOR.$level); + $levelImage = $this->getImage($level); + $tiles = $this->tiles($level); + $format = $this->_descriptor->tileFormat; + foreach ($tiles as $_tile) { + list($column, $row) = $_tile; + list($x,$y,$x2,$y2) = $this->_descriptor->getTileBounds($level,$column,$row); + $cropLevelImage = clone $levelImage; + $cropLevelImage->crop($x,$y,$x2,$y2); + $format = $this->_descriptor->tileFormat; + $tilePath = $levelDir.DIRECTORY_SEPARATOR.sprintf('%s_%s.%s',$column,$row,$format); + $cropLevelImage->save($tilePath); + unset($cropLevelImage); + } + unset($levelImage); + } + $this->_descriptor->save($destination); + } + + /** + * + * + * @param int $val + * @param int $min + * @param int $max + * + * @return int + */ + protected function _clamp($val, $min, $max) { + if($val < $min) { + return $min; + }elseif($val > $max) { + return $max; + } + return $val; + } + + /** + * Create directory if not exist + * + * @param string $pathname + * + * @return string + */ + protected function _ensure($pathname) { + if(!file_exists($pathname)) { + mkdir($pathname); + } + return $pathname; + } +} diff --git a/src/application/libs/openzoom/thumbnail.inc.php b/src/application/libs/openzoom/thumbnail.inc.php new file mode 100755 index 0000000..e439e70 --- /dev/null +++ b/src/application/libs/openzoom/thumbnail.inc.php @@ -0,0 +1,677 @@ +<?php +/** + * thumbnail.inc.php + * + * @author Ian Selby (ian@gen-x-design.com) + * @copyright Copyright 2006 + * @version 1.1 (PHP5) + * + */ + +/** + * PHP class for dynamically resizing, cropping, and rotating images for thumbnail purposes and either displaying them on-the-fly or saving them. + * + */ +class Thumbnail { + /** + * Error message to display, if any + * + * @var string + */ + private $errmsg; + /** + * Whether or not there is an error + * + * @var boolean + */ + private $error; + /** + * Format of the image file + * + * @var string + */ + private $format; + /** + * File name and path of the image file + * + * @var string + */ + private $fileName; + /** + * Image meta data if any is available (jpeg/tiff) via the exif library + * + * @var array + */ + public $imageMeta; + /** + * Current dimensions of working image + * + * @var array + */ + private $currentDimensions; + /** + * New dimensions of working image + * + * @var array + */ + private $newDimensions; + /** + * Image resource for newly manipulated image + * + * @var resource + */ + private $newImage; + /** + * Image resource for image before previous manipulation + * + * @var resource + */ + private $oldImage; + /** + * Image resource for image being currently manipulated + * + * @var resource + */ + private $workingImage; + /** + * Percentage to resize image by + * + * @var int + */ + private $percent; + /** + * Maximum width of image during resize + * + * @var int + */ + private $maxWidth; + /** + * Maximum height of image during resize + * + * @var int + */ + private $maxHeight; + + /** + * Class constructor + * + * @param string $fileName + * @return Thumbnail + */ + public function __construct($fileName) { + //make sure the GD library is installed + if(!function_exists("gd_info")) { + echo 'You do not have the GD Library installed. This class requires the GD library to function properly.' . "\n"; + echo 'visit http://us2.php.net/manual/en/ref.image.php for more information'; + exit; + } + //initialize variables + $this->errmsg = ''; + $this->error = false; + $this->currentDimensions = array(); + $this->newDimensions = array(); + $this->fileName = $fileName; + $this->imageMeta = array(); + $this->percent = 100; + $this->maxWidth = 0; + $this->maxHeight = 0; + + //check to see if file exists + if(!file_exists($this->fileName)) { + $this->errmsg = 'File not found'; + $this->error = true; + } + //check to see if file is readable + elseif(!is_readable($this->fileName)) { + $this->errmsg = 'File is not readable'; + $this->error = true; + } + + //if there are no errors, determine the file format + if($this->error == false) { + //check if gif + if(stristr(strtolower($this->fileName),'.gif')) $this->format = 'GIF'; + //check if jpg + elseif(stristr(strtolower($this->fileName),'.jpg') || stristr(strtolower($this->fileName),'.jpeg')) $this->format = 'JPG'; + //check if png + elseif(stristr(strtolower($this->fileName),'.png')) $this->format = 'PNG'; + //unknown file format + else { + $this->errmsg = 'Unknown file format'; + $this->error = true; + } + } + + //initialize resources if no errors + if($this->error == false) { + switch($this->format) { + case 'GIF': + $this->oldImage = ImageCreateFromGif($this->fileName); + break; + case 'JPG': + $this->oldImage = ImageCreateFromJpeg($this->fileName); + break; + case 'PNG': + $this->oldImage = ImageCreateFromPng($this->fileName); + break; + } + + $size = GetImageSize($this->fileName); + $this->currentDimensions = array('width'=>$size[0],'height'=>$size[1]); + $this->newImage = $this->oldImage; + $this->gatherImageMeta(); + } + + if($this->error == true) { + $this->showErrorImage(); + break; + } + } + + /** + * Class destructor + * + */ + public function __destruct() { + if(is_resource($this->newImage)) @ImageDestroy($this->newImage); + if(is_resource($this->oldImage)) @ImageDestroy($this->oldImage); + if(is_resource($this->workingImage)) @ImageDestroy($this->workingImage); + } + + /** + * Returns the current width of the image + * + * @return int + */ + private function getCurrentWidth() { + return $this->currentDimensions['width']; + } + + /** + * Returns the current height of the image + * + * @return int + */ + private function getCurrentHeight() { + return $this->currentDimensions['height']; + } + + /** + * Calculates new image width + * + * @param int $width + * @param int $height + * @return array + */ + private function calcWidth($width,$height) { + $newWp = (100 * $this->maxWidth) / $width; + $newHeight = ($height * $newWp) / 100; + return array('newWidth'=>intval($this->maxWidth),'newHeight'=>intval($newHeight)); + } + + /** + * Calculates new image height + * + * @param int $width + * @param int $height + * @return array + */ + private function calcHeight($width,$height) { + $newHp = (100 * $this->maxHeight) / $height; + $newWidth = ($width * $newHp) / 100; + return array('newWidth'=>intval($newWidth),'newHeight'=>intval($this->maxHeight)); + } + + /** + * Calculates new image size based on percentage + * + * @param int $width + * @param int $height + * @return array + */ + private function calcPercent($width,$height) { + $newWidth = ($width * $this->percent) / 100; + $newHeight = ($height * $this->percent) / 100; + return array('newWidth'=>intval($newWidth),'newHeight'=>intval($newHeight)); + } + + /** + * Calculates new image size based on width and height, while constraining to maxWidth and maxHeight + * + * @param int $width + * @param int $height + */ + private function calcImageSize($width,$height) { + $newSize = array('newWidth'=>$width,'newHeight'=>$height); + + if($this->maxWidth > 0) { + + $newSize = $this->calcWidth($width,$height); + + if($this->maxHeight > 0 && $newSize['newHeight'] > $this->maxHeight) { + $newSize = $this->calcHeight($newSize['newWidth'],$newSize['newHeight']); + } + + //$this->newDimensions = $newSize; + } + + if($this->maxHeight > 0) { + $newSize = $this->calcHeight($width,$height); + + if($this->maxWidth > 0 && $newSize['newWidth'] > $this->maxWidth) { + $newSize = $this->calcWidth($newSize['newWidth'],$newSize['newHeight']); + } + + //$this->newDimensions = $newSize; + } + + $this->newDimensions = $newSize; + } + + /** + * Calculates new image size based percentage + * + * @param int $width + * @param int $height + */ + private function calcImageSizePercent($width,$height) { + if($this->percent > 0) { + $this->newDimensions = $this->calcPercent($width,$height); + } + } + + /** + * Displays error image + * + */ + private function showErrorImage() { + header('Content-type: image/png'); + $errImg = ImageCreate(220,25); + $bgColor = imagecolorallocate($errImg,0,0,0); + $fgColor1 = imagecolorallocate($errImg,255,255,255); + $fgColor2 = imagecolorallocate($errImg,255,0,0); + imagestring($errImg,3,6,6,'Error:',$fgColor2); + imagestring($errImg,3,55,6,$this->errmsg,$fgColor1); + imagepng($errImg); + imagedestroy($errImg); + } + + /** + * Resizes image to maxWidth x maxHeight + * + * @param int $maxWidth + * @param int $maxHeight + */ + public function resize($maxWidth = 0, $maxHeight = 0) { + $this->maxWidth = $maxWidth; + $this->maxHeight = $maxHeight; + + $this->calcImageSize($this->currentDimensions['width'],$this->currentDimensions['height']); + + if(function_exists("ImageCreateTrueColor")) { + $this->workingImage = ImageCreateTrueColor($this->newDimensions['newWidth'],$this->newDimensions['newHeight']); + } + else { + $this->workingImage = ImageCreate($this->newDimensions['newWidth'],$this->newDimensions['newHeight']); + } + + ImageCopyResampled( + $this->workingImage, + $this->oldImage, + 0, + 0, + 0, + 0, + $this->newDimensions['newWidth'], + $this->newDimensions['newHeight'], + $this->currentDimensions['width'], + $this->currentDimensions['height'] + ); + + $this->oldImage = $this->workingImage; + $this->newImage = $this->workingImage; + $this->currentDimensions['width'] = $this->newDimensions['newWidth']; + $this->currentDimensions['height'] = $this->newDimensions['newHeight']; + } + + /** + * Resizes the image by $percent percent + * + * @param int $percent + */ + public function resizePercent($percent = 0) { + $this->percent = $percent; + + $this->calcImageSizePercent($this->currentDimensions['width'],$this->currentDimensions['height']); + + if(function_exists("ImageCreateTrueColor")) { + $this->workingImage = ImageCreateTrueColor($this->newDimensions['newWidth'],$this->newDimensions['newHeight']); + } + else { + $this->workingImage = ImageCreate($this->newDimensions['newWidth'],$this->newDimensions['newHeight']); + } + + ImageCopyResampled( + $this->workingImage, + $this->oldImage, + 0, + 0, + 0, + 0, + $this->newDimensions['newWidth'], + $this->newDimensions['newHeight'], + $this->currentDimensions['width'], + $this->currentDimensions['height'] + ); + + $this->oldImage = $this->workingImage; + $this->newImage = $this->workingImage; + $this->currentDimensions['width'] = $this->newDimensions['newWidth']; + $this->currentDimensions['height'] = $this->newDimensions['newHeight']; + } + + /** + * Crops the image from calculated center in a square of $cropSize pixels + * + * @param int $cropSize + */ + public function cropFromCenter($cropSize) { + if($cropSize > $this->currentDimensions['width']) $cropSize = $this->currentDimensions['width']; + if($cropSize > $this->currentDimensions['height']) $cropSize = $this->currentDimensions['height']; + + $cropX = intval(($this->currentDimensions['width'] - $cropSize) / 2); + $cropY = intval(($this->currentDimensions['height'] - $cropSize) / 2); + + if(function_exists("ImageCreateTrueColor")) { + $this->workingImage = ImageCreateTrueColor($cropSize,$cropSize); + } + else { + $this->workingImage = ImageCreate($cropSize,$cropSize); + } + + imagecopyresampled( + $this->workingImage, + $this->oldImage, + 0, + 0, + $cropX, + $cropY, + $cropSize, + $cropSize, + $cropSize, + $cropSize + ); + + $this->oldImage = $this->workingImage; + $this->newImage = $this->workingImage; + $this->currentDimensions['width'] = $cropSize; + $this->currentDimensions['height'] = $cropSize; + } + + /** + * Advanced cropping function that crops an image using $startX and $startY as the upper-left hand corner. + * + * @param int $startX + * @param int $startY + * @param int $width + * @param int $height + */ + public function crop($startX,$startY,$width,$height) { + //make sure the cropped area is not greater than the size of the image + if($width > $this->currentDimensions['width']) $width = $this->currentDimensions['width']; + if($height > $this->currentDimensions['height']) $height = $this->currentDimensions['height']; + //make sure not starting outside the image + if(($startX + $width) > $this->currentDimensions['width']) $startX = ($this->currentDimensions['width'] - $width); + if(($startY + $height) > $this->currentDimensions['height']) $startY = ($this->currentDimensions['height'] - $height); + if($startX < 0) $startX = 0; + if($startY < 0) $startY = 0; + + if(function_exists("ImageCreateTrueColor")) { + $this->workingImage = ImageCreateTrueColor($width,$height); + } + else { + $this->workingImage = ImageCreate($width,$height); + } + + imagecopyresampled( + $this->workingImage, + $this->oldImage, + 0, + 0, + $startX, + $startY, + $width, + $height, + $width, + $height + ); + + $this->oldImage = $this->workingImage; + $this->newImage = $this->workingImage; + $this->currentDimensions['width'] = $width; + $this->currentDimensions['height'] = $height; + } + + /** + * Outputs the image to the screen, or saves to $name if supplied. Quality of JPEG images can be controlled with the $quality variable + * + * @param int $quality + * @param string $name + */ + public function show($quality=100,$name = '') { + switch($this->format) { + case 'GIF': + if($name != '') { + ImageGif($this->newImage,$name); + } + else { + header('Content-type: image/gif'); + ImageGif($this->newImage); + } + break; + case 'JPG': + if($name != '') { + ImageJpeg($this->newImage,$name,$quality); + } + else { + header('Content-type: image/jpeg'); + ImageJpeg($this->newImage,'',$quality); + } + break; + case 'PNG': + if($name != '') { + ImagePng($this->newImage,$name); + } + else { + header('Content-type: image/png'); + ImagePng($this->newImage); + } + break; + } + } + + /** + * Saves image as $name (can include file path), with quality of # percent if file is a jpeg + * + * @param string $name + * @param int $quality + */ + public function save($name,$quality=100) { + $this->show($quality,$name); + } + + /** + * Creates Apple-style reflection under image, optionally adding a border to main image + * + * @param int $percent + * @param int $reflection + * @param int $white + * @param bool $border + * @param string $borderColor + */ + public function createReflection($percent,$reflection,$white,$border = true,$borderColor = '#a4a4a4') { + $width = $this->currentDimensions['width']; + $height = $this->currentDimensions['height']; + + $reflectionHeight = intval($height * ($reflection / 100)); + $newHeight = $height + $reflectionHeight; + $reflectedPart = $height * ($percent / 100); + + $this->workingImage = ImageCreateTrueColor($width,$newHeight); + + ImageAlphaBlending($this->workingImage,true); + + $colorToPaint = ImageColorAllocateAlpha($this->workingImage,255,255,255,0); + ImageFilledRectangle($this->workingImage,0,0,$width,$newHeight,$colorToPaint); + + imagecopyresampled( + $this->workingImage, + $this->newImage, + 0, + 0, + 0, + $reflectedPart, + $width, + $reflectionHeight, + $width, + ($height - $reflectedPart)); + $this->imageFlipVertical(); + + imagecopy($this->workingImage,$this->newImage,0,0,0,0,$width,$height); + + imagealphablending($this->workingImage,true); + + for($i=0;$i<$reflectionHeight;$i++) { + $colorToPaint = imagecolorallocatealpha($this->workingImage,255,255,255,($i/$reflectionHeight*-1+1)*$white); + imagefilledrectangle($this->workingImage,0,$height+$i,$width,$height+$i,$colorToPaint); + } + + if($border == true) { + $rgb = $this->hex2rgb($borderColor,false); + $colorToPaint = imagecolorallocate($this->workingImage,$rgb[0],$rgb[1],$rgb[2]); + imageline($this->workingImage,0,0,$width,0,$colorToPaint); //top line + imageline($this->workingImage,0,$height,$width,$height,$colorToPaint); //bottom line + imageline($this->workingImage,0,0,0,$height,$colorToPaint); //left line + imageline($this->workingImage,$width-1,0,$width-1,$height,$colorToPaint); //right line + } + + $this->oldImage = $this->workingImage; + $this->newImage = $this->workingImage; + $this->currentDimensions['width'] = $width; + $this->currentDimensions['height'] = $newHeight; + } + + /** + * Inverts working image, used by reflection function + * + */ + private function imageFlipVertical() { + $x_i = imagesx($this->workingImage); + $y_i = imagesy($this->workingImage); + + for($x = 0; $x < $x_i; $x++) { + for($y = 0; $y < $y_i; $y++) { + imagecopy($this->workingImage,$this->workingImage,$x,$y_i - $y - 1, $x, $y, 1, 1); + } + } + } + + /** + * Converts hexidecimal color value to rgb values and returns as array/string + * + * @param string $hex + * @param bool $asString + * @return array|string + */ + private function hex2rgb($hex, $asString = false) { + // strip off any leading # + if (0 === strpos($hex, '#')) { + $hex = substr($hex, 1); + } else if (0 === strpos($hex, '&H')) { + $hex = substr($hex, 2); + } + + // break into hex 3-tuple + $cutpoint = ceil(strlen($hex) / 2)-1; + $rgb = explode(':', wordwrap($hex, $cutpoint, ':', $cutpoint), 3); + + // convert each tuple to decimal + $rgb[0] = (isset($rgb[0]) ? hexdec($rgb[0]) : 0); + $rgb[1] = (isset($rgb[1]) ? hexdec($rgb[1]) : 0); + $rgb[2] = (isset($rgb[2]) ? hexdec($rgb[2]) : 0); + + return ($asString ? "{$rgb[0]} {$rgb[1]} {$rgb[2]}" : $rgb); + } + + /** + * Reads selected exif meta data from jpg images and populates $this->imageMeta with appropriate values if found + * + */ + private function gatherImageMeta() { + //only attempt to retrieve info if exif exists + if(function_exists("exif_read_data") && $this->format == 'JPG') { + $imageData = exif_read_data($this->fileName); + if(isset($imageData['Make'])) + $this->imageMeta['make'] = ucwords(strtolower($imageData['Make'])); + if(isset($imageData['Model'])) + $this->imageMeta['model'] = $imageData['Model']; + if(isset($imageData['COMPUTED']['ApertureFNumber'])) { + $this->imageMeta['aperture'] = $imageData['COMPUTED']['ApertureFNumber']; + $this->imageMeta['aperture'] = str_replace('/','',$this->imageMeta['aperture']); + } + if(isset($imageData['ExposureTime'])) { + $exposure = explode('/',$imageData['ExposureTime']); + $exposure = round($exposure[1]/$exposure[0],-1); + $this->imageMeta['exposure'] = '1/' . $exposure . ' second'; + } + if(isset($imageData['Flash'])) { + if($imageData['Flash'] > 0) { + $this->imageMeta['flash'] = 'Yes'; + } + else { + $this->imageMeta['flash'] = 'No'; + } + } + if(isset($imageData['FocalLength'])) { + $focus = explode('/',$imageData['FocalLength']); + $this->imageMeta['focalLength'] = round($focus[0]/$focus[1],2) . ' mm'; + } + if(isset($imageData['DateTime'])) { + $date = $imageData['DateTime']; + $date = explode(' ',$date); + $date = str_replace(':','-',$date[0]) . ' ' . $date[1]; + $this->imageMeta['dateTaken'] = date('m/d/Y g:i A',strtotime($date)); + } + } + } + + /** + * Rotates image either 90 degrees clockwise or counter-clockwise + * + * @param string $direction + */ + public function rotateImage($direction = 'CW') { + if($direction == 'CW') { + $this->workingImage = imagerotate($this->workingImage,-90,0); + } + else { + $this->workingImage = imagerotate($this->workingImage,90,0); + } + $newWidth = $this->currentDimensions['height']; + $newHeight = $this->currentDimensions['width']; + $this->oldImage = $this->workingImage; + $this->newImage = $this->workingImage; + $this->currentDimensions['width'] = $newWidth; + $this->currentDimensions['height'] = $newHeight; + } + + /** + * Get image size + * + * @return array + */ + public function size() { + return array($this->getCurrentWidth(),$this->getCurrentHeight()); + } +} +?> \ No newline at end of file diff --git a/src/application/mediaArchive/Archive/index.html b/src/application/mediaArchive/Archive/index.html new file mode 100644 index 0000000..e69de29 diff --git a/src/application/mediaArchive/Audio/index.html b/src/application/mediaArchive/Audio/index.html new file mode 100644 index 0000000..e69de29 diff --git a/src/application/mediaArchive/Flash/index.html b/src/application/mediaArchive/Flash/index.html new file mode 100644 index 0000000..e69de29 diff --git a/src/application/mediaArchive/Image/index.html b/src/application/mediaArchive/Image/index.html new file mode 100644 index 0000000..e69de29 diff --git a/src/application/mediaArchive/Office/index.html b/src/application/mediaArchive/Office/index.html new file mode 100644 index 0000000..e69de29 diff --git a/src/application/mediaArchive/Other/index.html b/src/application/mediaArchive/Other/index.html new file mode 100644 index 0000000..e69de29 diff --git a/src/application/mediaArchive/Pdf/index.html b/src/application/mediaArchive/Pdf/index.html new file mode 100644 index 0000000..e69de29 diff --git a/src/application/mediaArchive/Video/index.html b/src/application/mediaArchive/Video/index.html new file mode 100644 index 0000000..e69de29 diff --git a/src/application/pageTypes/Alias.xml b/src/application/pageTypes/Alias.xml new file mode 100644 index 0000000..30662ce --- /dev/null +++ b/src/application/pageTypes/Alias.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + templateType="php" + templateFileName="1col.php"> + <cms:PagePicker id="link" label="{i18n:Pagina collegata}" required="true" /> +</glz:Page> diff --git a/src/application/pageTypes/Common.xml b/src/application/pageTypes/Common.xml new file mode 100755 index 0000000..38beb95 --- /dev/null +++ b/src/application/pageTypes/Common.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:EmptyComponent + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:ms="movio.modules.sharingButtons.views.components.*"> + + <cms:LanguageNavigation id="languages" cssClass="langs" editableRegion="languages" /> + <glz:NavigationMenu id="navigation" startFrom="1" showOnlyChilds="true" depth="+5" forceLink="true" selectParent="false" attributeToSelect="class" showPath="true" selectLink="true" cssClass="navigationMenu" editableRegion="leftSidebar" cssCurrent="active" /> + <glz:NavigationMenu id="metanavigation" startFrom="2" showOnlyChilds="true" depth="+1" forceLink="true" selectParent="false" attributeToSelect="class" showPath="true" selectLink="true" cssClass="navigationMenu" editableRegion="metanavigation" flat="true" cssCurrent="active" /> + <glz:NavigationMenu id="metanavigation" startFrom="3" showOnlyChilds="true" depth="+1" forceLink="true" selectParent="false" attributeToSelect="class" showPath="true" selectLink="true" cssClass="navigationMenu" editableRegion="linkFooter" flat="true" cssCurrent="active" /> + + <glz:PageTitle id="pageTitle" tag="h1" editableRegion="pageTitle" /> + <glz:Breadcrumbs id="breadcrumbs" editableRegion="breadcrumbs" separator=" &amp;raquo; " label="{i18n:Breadcrumbs path}" /> + + <ms:Share id="share" editableRegion="sharing" /> + <glz:SearchBox id="boxSearch" title="{i18n:Search}" searchPageId="search" skin="BoxSearch.html" editableRegion="search" /> + <glz:SimpleList visible="{php:!$user->isLogged()}" editableRegion="userMenu" cssClass="dropdown-menu"> + <glz:ListItem value="{i18n:MW_LOGIN_TITLE}" key="linkLogin" /> + <glz:ListItem value="{i18n:MW_LOGIN_REGISTER}" key="linkRegistration" /> + <glz:ListItem value="{i18n:MW_LOGIN_ASK_PASSWORD}" key="linkLostpassword" /> + </glz:SimpleList> + <glz:SimpleList visible="{php:$user->isLogged()}" editableRegion="userMenu" cssClass="dropdown-menu"> + <glz:ListItem value="{i18n:MW_LOGIN_MYDETAILS}" key="linkUserDetails" /> + <glz:ListItem value="{i18n:Content for you}" key="linkUserProfileContents" /> + <glz:ListItem value="{i18n:MW_LOGOUT}" key="linkLogout" /> + </glz:SimpleList> +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/application/pageTypes/Cover.xml b/src/application/pageTypes/Cover.xml new file mode 100644 index 0000000..d9f9641 --- /dev/null +++ b/src/application/pageTypes/Cover.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:m="movio.views.components.*" + xmlns:cms="org.glizycms.views.components.*" + templateType="php" + templateFileName="cover.php" + defaultEditableRegion="content"> + <glz:Import src="Common.xml" /> + <glz:Groupbox id="cover" skin="Cover.html"> + <glz:Input id="width" label="{i18n:Width (default full width)}" size="50" /> + <glz:Input id="margin" label="{i18n:Margin top}" size="50" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + <glz:Image id="image" label="{i18n:Image}" /> + <cms:PagePicker id="pageId" label="{i18n:Linked page}" /> + <glz:LongText id="textAfter" label="{i18n:Final text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + </glz:Groupbox> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/DictionaryList.xml b/src/application/pageTypes/DictionaryList.xml new file mode 100644 index 0000000..f996def --- /dev/null +++ b/src/application/pageTypes/DictionaryList.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:t="movio.modules.thesaurus.views.components.*" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" > + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + + <t:DictionaryList id="dictionary" label="{i18n:Dictionary}" /> + +</glz:Page> + + diff --git a/src/application/pageTypes/DigitalExhibition.xml b/src/application/pageTypes/DigitalExhibition.xml new file mode 100644 index 0000000..5fb7881 --- /dev/null +++ b/src/application/pageTypes/DigitalExhibition.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + defaultEditableRegion="content" + templateType="php" + templateFileName="2cols.php" + adm:editComponents="exhibition"> + + <glz:Import src="Common.xml" /> + + <glz:Groupbox id="exhibition" skin="DigitalExhibition.html"> + <glz:Input id="subtitle" label="{i18n:Subtitle}" size="90" /> + <glz:Image id="banner" label="{i18n:Banner}" size="90" required="true" width="305" height="305" zoom="true" /> + <glz:Image id="appImage" label="{i18n:App image}" size="90" width="305" height="305" zoom="true" /> + <glz:Input id="appColor" label="{i18n:App color}" size="90" data="type=colorPicker"/> + <glz:Input id="accountLinkFacebook" label="{i18n:Account link on Facebook}" size="90" data="type=url"/> + <glz:Input id="emailBooking" label="{i18n:Email booking}" size="90" /> + <glz:Input id="targetUser" label="{i18n:Users}" size="255" required="true"/> + <glz:Input id="date" label="{i18n:Creation date}" size="255" required="true"/> + <glz:Input id="language" label="{i18n:Language}" size="90" /> + <glz:Input id="identifier" label="{i18n:Identifier}" size="90" /> + <glz:Input id="category" label="{i18n:Subject}" size="90" required="true"/> + <glz:Input id="urlExternal" label="{i18n:Exhibition url}" size="90" data="type=url"/> + <glz:Input id="linkedExhibition" label="{i18n:Physycal alternative}" size="90" /> + <glz:LongText id="description" label="{i18n:Abstract}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" required="true"/> + <glz:LongText id="credits" label="{i18n:Credits}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="sponsor1" label="{i18n:Patronages}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="sponsor2" label="{i18n:Promoters}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="sponsor3" label="{i18n:Sponsors}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="honoraryCommittee" label="{i18n:Committee of Honor}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="scientificCommittee" label="{i18n:Scientific Committee}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="dedication" label="{i18n:Dedication}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="aknowledgements" label="{i18n:Aknowledgements}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="contacts" label="{i18n:Contacts}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="services" label="{i18n:Services}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:Media id="video" label="{i18n:Presentation video}" size="90" adm:mediaType="video"/> + + <glz:Repeater id="images" label="{i18n:Image galleries}"> + <glz:Image id="image" label="{i18n:Image}" width="{config:THUMB_WIDTH}" height="{config:THUMB_HEIGHT}" zoom="true" /> + </glz:Repeater> + + <glz:Repeater id="attaches" label="{i18n:Download files}"> + <glz:Media id="media" label="{i18n:Media}" size="90" mediatype="video" /> + </glz:Repeater> + </glz:Groupbox> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Empty.xml b/src/application/pageTypes/Empty.xml new file mode 100644 index 0000000..a3ff00c --- /dev/null +++ b/src/application/pageTypes/Empty.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + templateType="php" + templateFileName="2cols.php"> +</glz:Page> diff --git a/src/application/pageTypes/Entity.xml b/src/application/pageTypes/Entity.xml new file mode 100644 index 0000000..bc806ea --- /dev/null +++ b/src/application/pageTypes/Entity.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cmp="movio.modules.ontologybuilder.views.components.*" + xmlns:t="movio.modules.thesaurus.views.components.*" + controllerName="movio.modules.ontologybuilder.controllers.entity.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="2cols.php" + adm:editComponents="text,entitySelectionBox"> + <glz:Import src="Common.xml" /> + + <mvc:State name="index"> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + <glz:Panel id="entitySelectionBox" visible="false"> + <glz:DataProvider id="entityDP" recordClassName="movio.modules.ontologybuilder.models.Entity" /> + <glz:List id="entitySelect" label="{i18n:Entity to show}" dataProvider="{entityDP}" bindTo="entity_name" emptyValue="{i18n:-}" data="index=text" required="true" /> + <glz:List id="showForm" label="{i18n:Show search form}"> + <glz:ListItem key="true" value="{i18n:Yes}"/> + <glz:ListItem key="false" value="{i18n:No}"/> + </glz:List> + <glz:List id="visualization" label="{i18n:Show}" > + <glz:ListItem key="list" value="{i18n:Show links}" /> + <glz:ListItem key="listWithDescription" value="{i18n:Show links and description}" /> + <glz:ListItem key="icons" value="{i18n:Show images}" /> + <glz:ListItem key="listAndIcons" value="{i18n:Show links and images}" /> + </glz:List> + </glz:Panel> + + <glz:DataProvider id="ModuleDP" recordClassName="movio.modules.ontologybuilder.models.EntityDocument" query='allFromTypeRequest' /> + <glz:SearchFilters id="filters" cssClass="search my-form all-in-row clearfix"> + <glz:Input id="filterTitle" label="{i18n:Text to search}" bindTo="title" value="{filters}" cssClass="input-large" /> + <glz:Panel cssClass="control-group"> + <glz:HtmlButton label="{i18n:GLZ_SEARCH}" value="SEARCH" target="{filters}" /> + <glz:HtmlButton label="{i18n:GLZ_RESET}" value="RESET" target="{filters}" cssClass="reset" /> + </glz:Panel> + </glz:SearchFilters> + + <cmp:EntityList id="list" dataProvider="{ModuleDP}" title="{i18n:Search Result}" filters="{filters}" paginate="{paginate}" processCell="movio.modules.ontologybuilder.views.renderer.EntityVisualization"> + <glz:routeUrl mapTo="__url__" name="showEntityDetail" /> + </cmp:EntityList> + <glz:PaginateResult id="paginate" cssClass="pagination" /> + </mvc:State> + + <mvc:State name="show"> + <cmp:Entity id="{php:__Request::get(document_id) == null ? 1 : __Request::get(document_id)}" /> + </mvc:State> + + <mvc:State name="thesaurus"> + <t:ShowTaggedContents id="thesaurus" /> + </mvc:State> + +</mvc:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Exhibition.xml b/src/application/pageTypes/Exhibition.xml new file mode 100644 index 0000000..e100933 --- /dev/null +++ b/src/application/pageTypes/Exhibition.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + defaultEditableRegion="content" + templateType="php" + templateFileName="2cols.php" + adm:editComponents="exhibition"> + + <glz:Import src="Common.xml" /> + + <glz:Groupbox id="exhibition" skin="Exhibition.html"> + <glz:Input id="subtitle" label="{i18n:Subtitle}" size="90" /> + <glz:Image id="banner" label="{i18n:Banner}" size="90" required="true" width="305" height="305" zoom="true" /> + <glz:Image id="appImage" label="{i18n:App image}" size="90" width="305" height="305" zoom="true" /> + <glz:Input id="appColor" label="{i18n:App color}" size="90" data="type=colorPicker"/> + <glz:Checkbox id="permanent" label="{i18n:Permanent exhibition}" skin="{checkBoxSKIN}" validationType="checkbox"/> + <glz:Input id="accountLinkFacebook" label="{i18n:Account link on Facebook}" size="90" data="type=url"/> + <glz:Input id="date" label="{i18n:Date}" size="255"/> + <glz:Date id="data_inziale" label="{i18n:From date}" size="255"/> + <glz:Date id="data_finale" label="{i18n:To date}" size="255"/> + <glz:Input id="place" label="{i18n:Nation, Region, Province}" size="90" required="true" /> + <glz:Input id="town" label="{i18n:Town}" size="90" required="true" /> + <glz:Input id="venue" label="{i18n:Venue}" size="90" /> + <glz:Input id="address" label="{i18n:Address}" size="90" /> + <glz:Input id="geo" label="{i18n:Venue Geolocation}" size="90" data="type=googlemaps" /> + <glz:Input id="emailBooking" label="{i18n:Email booking}" size="90" /> + <glz:Input id="targetUser" label="{i18n:Users}" required="true" /> + <glz:Input id="category" label="{i18n:Subject}" required="true" /> + <glz:Input id="urlExternal" label="{i18n:Exhibition url}" size="90" data="type=url"/> + <glz:Input id="linkedDigitalExhibition" label="{i18n:Digital alternative}" size="90" required="false" /> + <glz:LongText id="abstract" label="{i18n:Abstract}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:Input id="openingTime" label="{i18n:Timetable}" size="90" /> + <glz:Input id="ticket" label="{i18n:Access}" size="90" /> + <glz:LongText id="ticketOffice" label="{i18n:Ticket Office}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:Input id="vernissage" label="{i18n:Vernissage}" size="90" /> + <glz:LongText id="catalog" label="{i18n:Catalog}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="sponsor1" label="{i18n:Patronages}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="sponsor2" label="{i18n:Promoting organisations}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="sponsor3" label="{i18n:Sponsors}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="honoraryCommittee" label="{i18n:Committee of Honor}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="scientificCommittee" label="{i18n:Scientific Committee}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="dedication" label="{i18n:Dedication}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="aknowledgements" label="{i18n:Aknowledgements}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="promotion" label="{i18n:Promotion}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="pressOffice" label="{i18n:Press Office}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="projectConstruction" label="{i18n:Exhibition project}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="reviews" label="{i18n:Reviews}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="contacts" label="{i18n:Contacts}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:LongText id="services" label="{i18n:Services}" size="90" type="multiline" rows="10" cols="70" adm:htmlEditor="true" /> + <glz:Media id="video" label="{i18n:Presentation video}" size="90" adm:mediaType="video"/> + + <glz:Repeater id="images" label="{i18n:Image galleries}"> + <glz:Image id="image" label="{i18n:Image}" width="{config:THUMB_WIDTH}" height="{config:THUMB_HEIGHT}" zoom="true"/> + </glz:Repeater> + + <glz:Repeater id="attaches" label="{i18n:Download files}"> + <glz:Media id="media" label="{i18n:Media}" size="90" mediatype="video" /> + </glz:Repeater> + </glz:Groupbox> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/GoogleMap.xml b/src/application/pageTypes/GoogleMap.xml new file mode 100644 index 0000000..221306b --- /dev/null +++ b/src/application/pageTypes/GoogleMap.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:m="movio.views.components.*" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" > + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + <m:GoogleMap id="map" /> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Graph.xml b/src/application/pageTypes/Graph.xml new file mode 100644 index 0000000..72368ec --- /dev/null +++ b/src/application/pageTypes/Graph.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cmp="movio.modules.ontologybuilder.views.components.*" + controllerName="movio.modules.ontologybuilder.controllers.graph.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="2cols.php" + adm:editComponents="entitySelectionBox"> + <glz:Import src="Common.xml" /> + + <mvc:State name="index"> + <glz:Panel id="entitySelectionBox" visible="false"> + <glz:DataProvider id="entityDP" recordClassName="movio.modules.ontologybuilder.models.Entity" /> + <glz:List id="entitySelect" label="{i18n:Entity to show}" dataProvider="{entityDP}" bindTo="entity_name" emptyValue="{i18n:-}" /> + <glz:List id="visualization" label="{i18n:Show}" > + <glz:ListItem key="list" value="{i18n:Show links}" /> + <glz:ListItem key="listWithDescription" value="{i18n:Show links and description}" /> + <glz:ListItem key="icons" value="{i18n:Show images}" /> + <glz:ListItem key="listAndIcons" value="{i18n:Show links and images}" /> + </glz:List> + </glz:Panel> + + <cmp:Graph generateLinks="true"/> + </mvc:State> + <mvc:State name="list"> + <glz:DataProvider id="ModuleDP" recordClassName="movio.modules.ontologybuilder.models.EntityDocument" query='allFromTypeRequest' /> + <glz:SearchFilters id="filters" cssClass="search"> + <glz:Input id="filterTitle" label="{i18n:Title}" bindTo="title" value="{filters}" /> + <glz:Panel cssClass="formButtons"> + <glz:HtmlButton label="{i18n:GLZ_SEARCH}" value="SEARCH" target="{filters}" cssClass="submitButton" /> + <glz:HtmlButton label="{i18n:GLZ_RESET}" value="RESET" target="{filters}" cssClass="submitButton" /> + </glz:Panel> + </glz:SearchFilters> + + <cmp:EntityList id="list" dataProvider="{ModuleDP}" title="{i18n:Search Result}" filters="{filters}" paginate="{paginate}" processCell="movio.modules.ontologybuilder.views.renderer.EntityVisualization"> + <glz:routeUrl mapTo="__url__" name="showEntityDetail" /> + </cmp:EntityList> + + <glz:PaginateResult id="paginate" cssClass="pagination" /> + </mvc:State> + <mvc:State name="show"> + <cmp:Entity id="{php:__Request::get(document_id) == null ? 1 : __Request::get(document_id)}" /> + </mvc:State> + +</mvc:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Home.xml b/src/application/pageTypes/Home.xml new file mode 100644 index 0000000..575faec --- /dev/null +++ b/src/application/pageTypes/Home.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="movio.views.components.*" + templateType="php" + templateFileName="1col.php" + defaultEditableRegion="content" + addCoreJS="true"> + <glz:Import src="Common.xml" /> + + <glz:Modifier target="pageTitle" attribute="visible" value="false" /> + <glz:Modifier target="breadcrumbs" attribute="visible" value="false" /> + <glz:Modifier target="navigation" attribute="editableRegion" value="navigation" /> + + <glz:Repeater id="slider" label="{i18n:Image slider}" adm:collapsable="true" skin="HomeImageSlider.html"> + <glz:Input id="title" label="{i18n:Title}" size="50" required="false" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" /> + <glz:Image id="image" label="{i18n:Image}" width="{config:movio.thumb.homeSlider.width}" height="{config:movio.thumb.homeSlider.height}" crop="{config:movio.thumb.homeSlider.crop}" /> + <cms:PagePicker id="pageId" label="{i18n:Linked page}" required="false" /> + </glz:Repeater> + + <m:Boxes id="boxes" label="{i18n:Boxes}" /> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/ImageHotspot.xml b/src/application/pageTypes/ImageHotspot.xml new file mode 100644 index 0000000..e29fe2b --- /dev/null +++ b/src/application/pageTypes/ImageHotspot.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:m="movio.views.components.*" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" > + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + <m:ImageHotspot id="image" label="{i18n:Image}" size="90" data="type=imageHotspot" required="true" /> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Login.xml b/src/application/pageTypes/Login.xml new file mode 100644 index 0000000..8e9b0a5 --- /dev/null +++ b/src/application/pageTypes/Login.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="2cols.php" + adm:editComponents="text,loginPage" + controllerName="org.glizycms.userManager.fe.controllers.login.*" + defaultAction="login" + > + + <mvc:State name="login"> + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" forceP="true" adm:rows="20" adm:cols="75" adm:htmlEditor="true" /> + <cms:PagePicker id="loginPage" label="{i18n:MW_LOGIN_DESTINATION_PAGE}" visible="false" required="true" /> + + <glz:LoginBox id="formLoginPage" title="{i18n:MW_LOGIN_TITLE}" cssClass="sidebox_first" + userField="fldUsr" passwordField="fldPsw" + userLabel="{i18n:MW_LOGIN_USER}" passwordLabel="{i18n:MW_LOGIN_PSW}" + registrationLabel="{i18n:MW_LOGIN_REGISTER}" registrationUrl="Registration" + confirmLabel="{i18n:MW_LOGIN_CONFIRM}" errorLabel="{i18n:MW_LOGIN_ERROR}" + rememberLabel="{i18n:MW_LOGIN_REMEMBER}" askPasswordLabel="{i18n:MW_LOGIN_ASK_PASSWORD}" askPasswordUrl="lostpassword" + skin="Login.html" /> + </mvc:State> +</mvc:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Logout.xml b/src/application/pageTypes/Logout.xml new file mode 100644 index 0000000..f1ed77e --- /dev/null +++ b/src/application/pageTypes/Logout.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="2cols.php" + adm:editComponents="text,loginPage" + controllerName="org.glizycms.userManager.fe.controllers.login.*" + defaultAction="logout" + > + +</mvc:Page> \ No newline at end of file diff --git a/src/application/pageTypes/LostPassword.xml b/src/application/pageTypes/LostPassword.xml new file mode 100644 index 0000000..c1801f4 --- /dev/null +++ b/src/application/pageTypes/LostPassword.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="2cols.php" + adm:editComponents="text,privacy,confirm" + controllerName="org.glizycms.userManager.fe.controllers.user.*" + defaultAction="lostPassword"> + + <glz:Import src="Common.xml" /> + <mvc:State name="lostPassword"> + <glz:LongText id="text" label="{i18n:MW_LOSTPASSWORD_TEXT}" forceP="true" adm:rows="20" adm:cols="75" adm:htmlEditor="true" /> + <glz:MessageBox type="ERROR" cssClass="message error" message="{i18n:Check following errors:}" /> + <glz:Form id="passwordForm" cssClass="form-horizontal my-form"> + <glz:Input id="email" label="{i18n:MW_USER_EMAIL}" size="40" required="true" validationType="email" /> + <glz:Panel cssClass="formButtons" > + <glz:HtmlButton label="{i18n:MW_LOSTPASSWORD_SEND}" value="submit" name="submit" cssClass="submitButton" /> + </glz:Panel> + </glz:Form> + </mvc:State> + <mvc:State name="lostPasswordConfirm"> + <glz:LongText id="confirm" label="{i18n:MW_LOSTPASSWORD_CONFIRM}" forceP="true" adm:rows="10" adm:cols="75" adm:htmlEditor="true" /> + </mvc:State> +</mvc:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Page.xml b/src/application/pageTypes/Page.xml new file mode 100644 index 0000000..8caa2bf --- /dev/null +++ b/src/application/pageTypes/Page.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:m="movio.views.components.*" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" > + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" adm:required="false" /> + + <glz:Repeater id="images" label="{i18n:Images list}" adm:collapsable="true" skin="ImagesList.html"> + <glz:Image id="image" label="{i18n:Image}" width="{config:THUMB_WIDTH}" height="{config:THUMB_HEIGHT}" zoom="true" group="slideshow" superZoom="true" /> + </glz:Repeater> + + <glz:Repeater id="attachments" label="{i18n:Attachments list}" adm:collapsable="false" skin="AttachmentsList.html"> + <glz:Media id="media" label="{i18n:Attachment}" /> + </glz:Repeater> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Photogallery.xml b/src/application/pageTypes/Photogallery.xml new file mode 100644 index 0000000..252aa23 --- /dev/null +++ b/src/application/pageTypes/Photogallery.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:m="movio.views.components.*" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" > + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + + <m:Photogallery id="gallery" label="{i18n:Gallery}" /> + + <glz:LongText id="textAfter" label="{i18n:Text after gallery}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Photogallery_category.xml b/src/application/pageTypes/Photogallery_category.xml new file mode 100644 index 0000000..4f0e741 --- /dev/null +++ b/src/application/pageTypes/Photogallery_category.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:m="movio.views.components.*" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" > + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + + <m:PhotogalleryCategory id="gallery" label="{i18n:Gallery}" /> + + <glz:LongText id="textAfter" label="{i18n:Text after gallery}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/ProfileListContents.xml b/src/application/pageTypes/ProfileListContents.xml new file mode 100644 index 0000000..5f683f0 --- /dev/null +++ b/src/application/pageTypes/ProfileListContents.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cmp="movio.modules.ontologybuilder.views.components.*" + controllerName="movio.modules.ontologybuilder.controllers.profile.*" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" + adm:editComponents="visualizationBox"> + + <glz:Import src="Common.xml" /> + <glz:LoginCheck id="loginCheck" text="{i18n:MW_LOGIN_REQUIRED}" cssClass="error" /> + + + <mvc:State name="index"> + <glz:Panel id="visualizationBox" visible="false"> + <glz:DataDictionary id="usergroupsDP" recordClassName="org.glizycms.userManager.models.UserGroup" field="usergroup_id,usergroup_name" query="userGroupsAdmin" /> + <glz:List id="groupId" label="{i18n:User group}" dataProvider="{usergroupsDP}" emptyValue="{i18n:User Profile}" required="false" /> + </glz:Panel> + + <cmp:ShowProfileContents /> + </mvc:State> + + +</mvc:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Registration.xml b/src/application/pageTypes/Registration.xml new file mode 100644 index 0000000..6a4f2f6 --- /dev/null +++ b/src/application/pageTypes/Registration.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="2cols.php" + adm:editComponents="text,privacy,confirm" + controllerName="org.glizycms.userManager.fe.controllers.user.*" + defaultAction="registration"> + <glz:Import src="Common.xml" /> + <mvc:State name="registration"> +<!-- +TODO localizzare +--> + <glz:LongText id="text" label="{i18n:Text}" forceP="true" adm:rows="20" adm:cols="75" adm:htmlEditor="true" /> + <glz:MessageBox type="ERROR" cssClass="message error" message="{i18n:Check following errors:}" /> + <glz:Form id="registration" cssClass="form-horizontal my-form"> + <glz:Input id="name" label="{i18n:MW_USER_NAME}" size="50" required="true" validationType="not_empty" bindTo="user_firstName" /> + <glz:Input id="surname" label="{i18n:MW_USER_SURNAME}" size="50" required="true" validationType="not_empty" bindTo="user_lastName" /> + <glz:Input id="email" label="{i18n:MW_USER_EMAIL}" size="50" required="true" validationType="email" bindTo="user_email" /> + <glz:Input id="psw" label="{i18n:MW_USER_PSW}" size="50" type="password" required="true" validationType="not_empty" bindTo="user_password" /> + <glz:DataDictionary id="usergroupsDP" recordClassName="org.glizycms.userManager.models.UserGroup" query="userGroups" /> + <glz:List id="profile" bindTo="user_FK_usergroup_id" label="{i18n:Profilo}" dataProvider="{usergroupsDP}" emptyValue="-" required="true" /> + <glz:LongText id="privacy" label="{i18n:MW_REGISTRATION_PRIVACY_TEXT}" forceP="true" adm:rows="10" adm:cols="75" adm:htmlEditor="true" skin="{privacySKIN}" /> + <glz:Checkbox id="agree" label="{i18n:MW_REGISTRATION_PRIVACY}" skin="{checkBoxSKIN}" required="true" validationType="checkbox"/> + <glz:Panel cssClass="formButtons" > + <glz:HtmlButton label="{i18n:MW_SUBMIT}" value="submit" name="submit" cssClass="submitButton" /> + </glz:Panel> + </glz:Form> + <glz:Text text="{i18n:MW_REGISTRATION_REQUIRED}" wrapTag="p" /> + </mvc:State> + <mvc:State name="registrationConfirm"> + <glz:LongText id="confirm" label="{i18n:MW_REGISTRATION_CONFIRM}" forceP="true" adm:rows="10" adm:cols="75" adm:htmlEditor="true" /> + </mvc:State> + <glz:SkinDefine id="privacySKIN"><![CDATA[ + <span tal:omit-tag=""> + <hr /> + <div id="privacy" tal:content="structure LongText"></div> + </span> + ]]></glz:SkinDefine> + <glz:SkinDefine id="checkBoxSKIN"><![CDATA[ + <span tal:omit-tag=""> + <p class="smallPrivacy"><input type="checkbox" value="1" class="required validate[required,]" name="agree" id="agree" />&nbsp;<span tal:omit-tag="" tal:content="Checkbox/label" /></p> + </span> + ]]></glz:SkinDefine> +</mvc:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Search.xml b/src/application/pageTypes/Search.xml new file mode 100644 index 0000000..131fdd7 --- /dev/null +++ b/src/application/pageTypes/Search.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" + adm:editComponents="text"> + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" forceP="true" adm:rows="20" adm:cols="75" adm:htmlEditor="true" /> + <glz:Search id="frm_ricerca" skin="Search.html" explodeWords="false" cssClass="form-horizontal my-form no-border-row" /> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/SiteMap.xml b/src/application/pageTypes/SiteMap.xml new file mode 100644 index 0000000..c0801a2 --- /dev/null +++ b/src/application/pageTypes/SiteMap.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + templateType="php" + templateFileName="1col.php" + defaultEditableRegion="content"> + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" adm:required="false" /> + <glz:NavigationMenu startFrom="1" depth="10" forceLink="true" /> +</glz:Page> diff --git a/src/application/pageTypes/Storyteller.xml b/src/application/pageTypes/Storyteller.xml new file mode 100644 index 0000000..0bd44e3 --- /dev/null +++ b/src/application/pageTypes/Storyteller.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:st="movio.modules.storyteller.views.components.*" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" > + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + + <st:Storyteller id="storyteller" label="{i18n:Storyteller}" /> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Timeline.xml b/src/application/pageTypes/Timeline.xml new file mode 100644 index 0000000..c5c3e37 --- /dev/null +++ b/src/application/pageTypes/Timeline.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:m="movio.views.components.*" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" > + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + <m:Timeline id="timeline" /> + +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Unity3D.xml b/src/application/pageTypes/Unity3D.xml new file mode 100644 index 0000000..6636ee3 --- /dev/null +++ b/src/application/pageTypes/Unity3D.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:m="movio.views.components.*" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" > + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + <m:Unity3D id="unity3d_element" /> +</glz:Page> \ No newline at end of file diff --git a/src/application/pageTypes/UserDetails.xml b/src/application/pageTypes/UserDetails.xml new file mode 100644 index 0000000..5aaa75c --- /dev/null +++ b/src/application/pageTypes/UserDetails.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="2cols.php" + adm:editComponents="text,confirm" + controllerName="org.glizycms.userManager.fe.controllers.user.*" + defaultAction="modify"> +<!-- +TODO localizzare +--> + <glz:Import src="Common.xml" /> + <glz:LoginCheck text="{i18n:MW_LOGIN_REQUIRED}" cssClass="error" /> + <mvc:State name="modify"> + <glz:LongText id="text" label="{i18n:Text}" forceP="true" adm:rows="20" adm:cols="75" adm:htmlEditor="true" /> + <glz:MessageBox type="ERROR" cssClass="message error" message="{i18n:Controllare i seguenti errori:}" /> + <glz:Form id="registration" cssClass="form-horizontal my-form"> + <glz:Input id="name" label="{i18n:MW_USER_NAME}" size="50" required="true" validationType="not_empty" bindTo="user_firstName" /> + <glz:Input id="surname" label="{i18n:MW_USER_SURNAME}" size="50" required="true" validationType="not_empty" bindTo="user_lastName" /> + <glz:Input id="email" label="{i18n:MW_USER_EMAIL}" size="50" required="true" validationType="email" bindTo="user_email" /> + <glz:Input id="psw" label="{i18n:MW_USER_PSW}" size="50" type="password" validationType="not_empty" bindTo="user_password" /> + + <glz:DataDictionary id="usergroupsDP" recordClassName="org.glizycms.userManager.models.UserGroup" query="userGroups" /> + <glz:List id="profile" bindTo="user_FK_usergroup_id" label="{i18n:User Profile}" dataProvider="{usergroupsDP}" emptyValue="-" required="true" /> + + <glz:Panel cssClass="formButtons" > + <glz:HtmlButton label="{i18n:MW_SUBMIT}" value="submit" name="submit" cssClass="submitButton" /> + </glz:Panel> + </glz:Form> + <glz:Text text="{i18n:MW_REGISTRATION_REQUIRED}" wrapTag="p" /> + </mvc:State> + <mvc:State name="modifyConfirm"> + <glz:LongText id="confirm" label="{i18n:MW_REGISTRATION_CONFIRM}" forceP="true" adm:rows="10" adm:cols="75" adm:htmlEditor="true" /> + </mvc:State> +</mvc:Page> \ No newline at end of file diff --git a/src/application/pageTypes/Video.xml b/src/application/pageTypes/Video.xml new file mode 100644 index 0000000..5a5a393 --- /dev/null +++ b/src/application/pageTypes/Video.xml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:m="movio.views.components.*" + templateType="php" + templateFileName="2cols.php" + defaultEditableRegion="content" > + <glz:Import src="Common.xml" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" forceP="true" /> + + <m:Video id="video" label="{i18n:Video}" /> +</glz:Page> \ No newline at end of file diff --git a/src/application/startup/index.php b/src/application/startup/index.php new file mode 100644 index 0000000..f8637f6 --- /dev/null +++ b/src/application/startup/index.php @@ -0,0 +1,8 @@ +<?php +org_glizycms_Glizycms::init(); +$application = org_glizy_ObjectValues::get('org.glizy', 'application' ); +if ($application) { + $application->registerProxy('movio.modules.ontologybuilder.service.FieldTypeService'); + $application->registerProxy('movio.modules.ontologybuilder.service.EntityTypeService'); + $application->registerProxy('movio.modules.ontologybuilder.service.LocaleService'); +} diff --git a/src/application/startup/movio.php b/src/application/startup/movio.php new file mode 100644 index 0000000..c3a11d0 --- /dev/null +++ b/src/application/startup/movio.php @@ -0,0 +1,14 @@ +<?php +glz_loadLocale('movio'); +glz_loadLocale('userModules.movio.ontologybuilder'); + +$application = org_glizy_ObjectValues::get('org.glizy', 'application' ); +if ($application) { + org_glizycms_speakingUrl_Manager::registerResolver(org_glizy_ObjectFactory::createObject('movio.modules.ontologybuilder.EntityResolver')); + org_glizycms_speakingUrl_Manager::registerResolver(org_glizy_ObjectFactory::createObject('movio.modules.news.UrlResolver')); + org_glizycms_speakingUrl_Manager::registerResolver(org_glizy_ObjectFactory::createObject('movio.modules.touristoperators.UrlResolver')); +} + +movio_modules_news_Module::registerModule(); +movio_modules_thesaurus_Module::registerModule(); +movio_modules_touristoperators_Module::registerModule(); \ No newline at end of file diff --git a/src/application/startup/plugin.php b/src/application/startup/plugin.php new file mode 100644 index 0000000..407c334 --- /dev/null +++ b/src/application/startup/plugin.php @@ -0,0 +1,5 @@ +<?php + +glz_import('org.glizy.plugins.PluginManager'); +org_glizy_plugins_PluginManager::addPlugin('org.glizy.plugins.Search', 'movio.search.Content'); +org_glizy_plugins_PluginManager::addPlugin('org.glizy.plugins.Search', 'movio.search.Entity'); \ No newline at end of file diff --git a/src/cache/.gitkeep b/src/cache/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/checkUpdate.php b/src/checkUpdate.php new file mode 100644 index 0000000..67442fa --- /dev/null +++ b/src/checkUpdate.php @@ -0,0 +1,19 @@ +<?php +require_once("core/core.inc.php"); + +$application = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.Application', 'application'); +org_glizy_Paths::addClassSearchPath('admin/application/classes/'); +$application->runSoft(); + +$timestamp = __Request::get('timestamp'); +$lastUpdate = org_glizy_Registry::get('movio/modules/publishApp/lastUpdate'); +$result = array( + 'updated' => $lastUpdate > $timestamp, + 'lastUpdate' => $lastUpdate, + 'fileSize' => @filesize(__Paths::getRealPath('BASE').'export/mobileContents.zip'), + 'url' => GLZ_HOST.'/export/'.'mobileContents.zip', + 'checkUpdateUrl' => GLZ_HOST.'/checkUpdate.php' +); + +header("Content-Type: application/json"); +echo json_encode($result); \ No newline at end of file diff --git a/src/core/.htaccess b/src/core/.htaccess new file mode 100755 index 0000000..8091b4f --- /dev/null +++ b/src/core/.htaccess @@ -0,0 +1,4 @@ +<Files *> + Order deny,allow + Deny from all +</Files> diff --git a/src/core/COPYRIGHT.txt b/src/core/COPYRIGHT.txt new file mode 100755 index 0000000..f94b17c --- /dev/null +++ b/src/core/COPYRIGHT.txt @@ -0,0 +1,52 @@ +GLIZY v1.3.0 by Daniele Ugoletti +------------------------------ + +GLIZY is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +GLIZY is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +GLIZY includes or is derivative of works distributed +under the following copyright notices: + + +- Cache Lite + license: GNU Lesser General Public License (LGPL) + website: http://pear.php.net/package/Cache_Lite + author: Fabien MARTY + +- FeedCreator + license: GNU General Public License (GPL) + website: http://www.bitfolge.de + author: Kai Blankenhorn + +- HTML_TreeMenu + license: BSD + website: http://pear.php.net/package/HTML_TreeMenu + author: Richard Heyes <http://pear.php.net/user/richard> + +- PHPTAL + license: GNU Lesser General Public License (LGPL) + website: http://phptal.motion-twin.com/ + author: Laurent Bédubourg + +- phpMailer + license: GNU Lesser General Public License (LGPL) + website: http://phpmailer.sourceforge.net/ + author: Brent R. Matzelle + +- js-calendar + license: GNU Lesser General Public License (LGPL) + website: http://phpmailer.sourceforge.net/ + author: Mihai Bazon + +- TinyMCE + license: GNU Lesser General Public License (LGPL) + website: http://tinymce.moxiecode.com/ + author: Moxiecode Systems AB + \ No newline at end of file diff --git a/src/core/LICENSE.txt b/src/core/LICENSE.txt new file mode 100755 index 0000000..b1e3f5a --- /dev/null +++ b/src/core/LICENSE.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/core/classes/org/glizy/Assets.php b/src/core/classes/org/glizy/Assets.php new file mode 100755 index 0000000..fc5a9bf --- /dev/null +++ b/src/core/classes/org/glizy/Assets.php @@ -0,0 +1,220 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_Assets +{ + function init() + { + $basePath = org_glizy_Paths::get('CORE').'static/images/'; + $pathsArray = &org_glizy_Assets::_getPathsArray(true); + $pathsArray['ICON_ADD'] = $basePath.'icon_add.gif'; + $pathsArray['ICON_ADD_OFF'] = $basePath.'icon_add_off.gif'; + $pathsArray['ICON_CHECKED'] = $basePath.'icon_checked.gif'; + $pathsArray['ICON_CHECKED_OFF'] = $basePath.'icon_checked_off.gif'; + $pathsArray['ICON_DELETE'] = $basePath.'icon_delete.gif'; + $pathsArray['ICON_DELETE_OFF'] = $basePath.'icon_delete_off.gif'; + $pathsArray['ICON_DOWN'] = $basePath.'icon_down.gif'; + $pathsArray['ICON_DOWN_OFF'] = $basePath.'icon_down_off.gif'; + $pathsArray['ICON_DOWNLOAD'] = $basePath.'icon_download.gif'; + $pathsArray['ICON_DOWNLOAD_OFF'] = $basePath.'icon_download_off.gif'; + $pathsArray['ICON_EDIT'] = $basePath.'icon_edit.gif'; + $pathsArray['ICON_EDIT_OFF'] = $basePath.'icon_edit_off.gif'; + $pathsArray['ICON_EDITDRAFT'] = $basePath.'icon_editDraft.gif'; + $pathsArray['ICON_EDITDRAFT_OFF'] = $basePath.'icon_editDraft_off.gif'; + $pathsArray['ICON_INVISIBLE'] = $basePath.'icon_invisible.gif'; + $pathsArray['ICON_INVISIBLE_OFF'] = $basePath.'icon_invisible_off.gif'; + $pathsArray['ICON_NEW'] = $basePath.'icon_add.gif'; + $pathsArray['ICON_NEW_OFF'] = $basePath.'icon_add_off.gif'; + $pathsArray['ICON_ORDER_UP'] = $basePath.'icon_orderUp.gif'; + $pathsArray['ICON_ORDER_DOWN'] = $basePath.'icon_orderDown.gif'; + $pathsArray['ICON_ORDER_UPBLACK'] = $basePath.'icon_orderUpBlack.gif'; + $pathsArray['ICON_ORDER_DOWNBLACK'] = $basePath.'icon_orderDownBlack.gif'; + $pathsArray['ICON_PREVIEW'] = $basePath.'icon_preview.gif'; + $pathsArray['ICON_PREVIEW_OFF'] = $basePath.'icon_preview_off.gif'; + $pathsArray['ICON_PUBLISH'] = $basePath.'icon_publish.gif'; + $pathsArray['ICON_PUBLISH_OFF'] = $basePath.'icon_publish_off.gif'; + $pathsArray['ICON_UP'] = $basePath.'icon_up.gif'; + $pathsArray['ICON_UP_OFF'] = $basePath.'icon_up_off.gif'; + $pathsArray['ICON_UNCHECKED'] = $basePath.'icon_unchecked.gif'; + $pathsArray['ICON_UNCHECKED_OFF'] = $basePath.'icon_unchecked_off.gif'; + $pathsArray['ICON_UNPUBLISH'] = $basePath.'icon_unpublish.gif'; + $pathsArray['ICON_UNPUBLISH_OFF'] = $basePath.'icon_unpublish_off.gif'; + $pathsArray['ICON_VISIBLE'] = $basePath.'icon_visible.gif'; + $pathsArray['ICON_VISIBLE_OFF'] = $basePath.'icon_visible_off.gif'; + $pathsArray['ICON_MEDIA_IMAGE'] = $basePath.'mediaImage.png'; + $pathsArray['ICON_MEDIA_OFFICE'] = $basePath.'mediaOffice.png'; + $pathsArray['ICON_MEDIA_PDF'] = $basePath.'mediaPdf.png'; + $pathsArray['ICON_MEDIA_AUDIO'] = $basePath.'mediaAudio.png'; + $pathsArray['ICON_MEDIA_ARCHIVE'] = $basePath.'mediaArchive.png'; + $pathsArray['ICON_MEDIA_FLASH'] = $basePath.'mediaFlash.png'; + $pathsArray['ICON_MEDIA_VIDEO'] = $basePath.'mediaVideo.png'; + $pathsArray['ICON_MEDIA_OTHER'] = $basePath.'mediaOther.png'; + $pathsArray['ICON_LOCK'] = $basePath.'icon_lock.gif'; + $pathsArray['ICON_LOCK_OFF'] = $basePath.'icon_lock_off.gif'; + $pathsArray['ICON_GO'] = $basePath.'icon_go.gif'; + $pathsArray['ICON_GO_OFF'] = $basePath.'icon_go_off.gif'; + $pathsArray['ICON_DOCUMENT'] = $basePath.'icon_document.gif'; + $pathsArray['ICON_FOLDER'] = $basePath.'icon_folder.gif'; + $pathsArray['ICON_REENABLE'] = $basePath.'icon_folder.gif'; + $pathsArray['ICON_OPEN'] = $basePath.'icon_open.gif'; + $pathsArray['ICON_COD_START'] = $basePath.'icon_cod_start.png'; + $pathsArray['ICON_COD_ALERT'] = $basePath.'icon_cod_alert.png'; + $pathsArray['ICON_COD_STOP'] = $basePath.'icon_cod_stop.png'; + $pathsArray['ICON_COD_WAIT'] = $basePath.'icon_cod_wait.png'; + $pathsArray['ICON_USER'] = $basePath.'icon_user.png'; + $pathsArray['ICON_USER_RED'] = $basePath.'icon_user_red.png'; + $pathsArray['ICON_USER_GREEN'] = $basePath.'icon_user_green.png'; + $pathsArray['ICON_USER_ALERT'] = $basePath.'icon_user_alert.png'; + $pathsArray['ICON_USER_DENY'] = $basePath.'icon_user_deny.gif'; + $pathsArray['ICON_WHEEL'] = $basePath.'wheel.gif'; + $pathsArray['ICON_RELOAD'] = $basePath.'icon_reload.png'; + } + + + /** + * @param $pathCode + * @return null + */ + public static function get($pathCode) + { + $pathsArray = &org_glizy_Assets::_getPathsArray(); + return isset($pathsArray[$pathCode]) ? $pathsArray[$pathCode] : NULL; + } + + /** + * @param $pathCode + * @param string $title + * @return null|string + */ + public static function getIcon($pathCode, $title='') + { + $pathsArray = &org_glizy_Assets::_getPathsArray(); + $src = isset($pathsArray[$pathCode]) ? $pathsArray[$pathCode] : NULL; + if ( !is_null( $src ) ) + { + return '<img src="'.$src.'" width="16" height="16" border="0" alt="'.__T($title).'" title="'.__T($title).'" />'; + } + else + { + return null; + } + } + + /** + * @param $pathCode + * @param string $title + * @return null|string + */ + public static function getImgTag($pathCode, $title='') + { + $pathsArray = &org_glizy_Assets::_getPathsArray(); + return isset($pathsArray[$pathCode]) ? + '<img src="'.$pathsArray[$pathCode].'" alt="'.__t($title).'" title="'.__t($title).'" height="16" width="16" />' + : + NULL; + } + + /** + * @param $iconName + * @param $title + * @param $routing + * @param $params + * @param string $confirm + * @return string + */ + public static function getImgAction( $iconName, $title, $routing, $params, $confirm='' ) + { + $params[ 'label' ] = org_glizy_Assets::getImgTag( $iconName, $title ); + $params[ 'title' ] = $title; + return org_glizy_helpers_Link::makeLink( $routing, $params, array(), $confirm, false ); + } + + /** + * @param $iconName + * @param $title + * @param $routing + * @param $params + * @param string $confirm + * @param bool $encode + * @return string + */ + public static function getImgActionWithLabel( $iconName, $title, $routing, $params, $confirm='', $encode=true ) + { + $params[ 'label' ] = &org_glizy_Assets::getImgTag( $iconName, $title ).$title; + $params[ 'title' ] = $title; + return org_glizy_helpers_Link::makeLink( $routing, $params, array(), $confirm, $encode ).'<br />'; + } + + /** + * @param $iconName + * @param $title + * @param $description + * @param $routing + * @param $params + * @param string $confirm + * @return string + */ + public static function getImgActionWithTooltip( $iconName, $title, $description, $routing, $params, $confirm='' ) + { + $params[ 'label' ] = org_glizy_Assets::getImgTag( $iconName, $title ); + $params[ 'title' ] = $title; + return '<span title="'.$title.'|'.$description.'">'.org_glizy_helpers_Link::makeLink( $routing, $params, array(), $confirm ).'</span>'; + } + + /** + * @param $iconName string + * @param $title string + * @param $description string + * @return string + */ + public static function getImgActionWithEnTooltip( $iconName, $title, $description ) + { + static $t = 0; + $t++; + $output = '<a id="t'.$t.'" title="'.$title.'" rel="#td'.$t.'">'.org_glizy_Assets::getImgTag( $iconName, $title ).'</a>'; + $output .= '<div class="hidden"><div id="td'.$t.'">'.$description.'</div></div>'; + $output .= '<script type="text/javascript">'; + $output .= '$j(document).ready(function() { $j("#t'.$t.'").cluetip({ arrows: true, dropShadow: true, cluetipClass: "jtip", fx: {open: "fadeIn" }, local:true, mouseOutClose:true, hoverIntent: false, closePosition: "title", closeText: "<img src=\"metacms/templates/js/cluetip/images/cross.png\" alt=\"chiudi\" />",sticky: true});});'; + $output .= '</script>'; + return $output; + } + + + /** + * @param bool $init + * @return mixed + */ + public static function &_getPathsArray($init=false) + { + // Array associativo (PATH_CODE=>PATH) + static $_pathsArray = array(); + if (!count($_pathsArray) && !$init) org_glizy_Assets::init(); + return $_pathsArray; + } + + + public static function makeLinkWithIcon($routeUrl, $iconName, $params, $deleteMsg=NULL ) + { + $icon = '<i class="'.$iconName.'"></i>'; + $params[ 'label' ] = $icon; + if ( !is_null( $deleteMsg ) ) + { + $deleteJs = 'if (!confirm(\''.addslashes( $deleteMsg ).'\')){return false;}'; + } + return org_glizy_helpers_Link::makeLink( $routeUrl, $params, array(), $deleteJs, false ); + } +} + +// shortcut version +/** + * Class __Assets + */ +class __Assets extends org_glizy_Assets +{ +} diff --git a/src/core/classes/org/glizy/Config.php b/src/core/classes/org/glizy/Config.php new file mode 100755 index 0000000..1d707fa --- /dev/null +++ b/src/core/classes/org/glizy/Config.php @@ -0,0 +1,336 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_Config + */ +class org_glizy_Config +{ + /** + * @param string $serverName + */ + public static function init( $serverName='' ) + { + $configArray = &org_glizy_Config::_getConfigArray( $serverName ); + $debugErrorLevel = self::get('DEBUG_ERROR_LEVEL'); + if ($debugErrorLevel != '') { + $debugErrorLevel = explode(' ', $debugErrorLevel); + $level = 0; + $lastOp = ''; + foreach($debugErrorLevel as $v) { + if ($v=='&' || $v=='|') { + $lastOp = $v; + } else if ($v{0}=='~') { + $level = $level &~constant(substr($v, 1)); + } else if ($lastOp=='|') { + $level = $level | constant($v); + } else if ($lastOp=='&') { + $level = $level & constant($v); + } else { + $level = $level + constant($v); + } + } + + error_reporting($level); + } + } + + /** + * @param $code + * @return mixed|null + */ + public static function get($code) + { + $configArray = &org_glizy_Config::_getConfigArray(); + $value = isset($configArray[$code]) ? $configArray[$code] : NULL; + if( strpos($value, "{{") !== false ) + { + if ( strstr($value, "{{env:") !== false ) + { + return getenv(substr($value, 6, -2)); + } + + preg_match_all( "/\{\{path:([^\{]*)\}\}/U", $value, $resmatch ); + foreach( $resmatch[1] as $varname) + { + $value = str_replace('{{path:'.$varname.'}}', org_glizy_Paths::get( $varname ), $value); + } + + preg_match_all( "/\{\{([^\{]*)\}\}/U", $value, $resmatch ); + foreach( $resmatch[1] as $varname) + { + $value = str_replace('{{'.$varname.'}}', org_glizy_Config::get( $varname ), $value); + } + } + + return $value; + } + + /** + * @param $code + * @param $value + */ + public static function set($code, $value) + { + if ( $value == "true" ) + { + $value = true; + } + else if ( $value == "false" ) + { + $value = false; + } + + $configArray = &org_glizy_Config::_getConfigArray(); + $configArray[$code] = $value; + + // if ($code=='CHARSET') + // { + // org_glizy_Request::removeAll(); + // } + } + + public static function dump() + { + $configArray = &org_glizy_Config::_getConfigArray(); + var_dump($configArray); + } + + /** + * @param string $serverName + * @return array + */ + public static function &_getConfigArray( $serverName='' ) + { + // Array associativo (PATH_CODE=>PATH) + static $_configArray = null; + if (is_null($_configArray)) + { + $_configArray = array(); + org_glizy_Config::_parse( $serverName ); + } + return $_configArray; + } + + static function getAllAsArray() + { + $configArray = &org_glizy_Config::_getConfigArray(); + return $configArray; + } + + /** + * @param string $serverName + * @throws Exception + */ + function _parse( $serverName='' ) + { + // imposta i valori di default + $configArray = &org_glizy_Config::_getConfigArray(); + $configArray['DEBUG'] = false; + $configArray['DEBUG_ERROR_LEVEL'] = ''; + $configArray['ERROR_DUMP'] = ''; + $configArray['DATASOURCE_MODE'] = ''; + $configArray['SESSION_PREFIX'] = ''; + $configArray['SESSION_TIMEOUT'] = 1800; + $configArray['DEFAULT_LANGUAGE'] = 'en'; + $configArray['DEFAULT_LANGUAGE_ID'] = '1'; + $configArray['CHARSET'] = 'utf-8'; + $configArray['DB_LAYER'] = 'pdo'; + $configArray['DB_TYPE'] = 'mysql'; + $configArray['DB_HOST'] = ''; + $configArray['DB_NAME'] = ''; + $configArray['DB_USER'] = ''; + $configArray['DB_PSW'] = ''; + $configArray['DB_MYSQL_BUFFERED_QUERY'] = false; + $configArray['DB_ATTR_PERSISTENT'] = false; + $configArray['DB_PREFIX'] = ''; + $configArray['DB_SOCKET'] = ''; + $configArray['SMTP_HOST'] = ''; + $configArray['SMTP_PORT'] = 25; + $configArray['SMTP_USER'] = ''; + $configArray['SMTP_PSW'] = ''; + $configArray['SMTP_SENDER'] = ''; + $configArray['SMTP_EMAIL'] = ''; + $configArray['START_PAGE'] = 'HOME'; + $configArray['CACHE_IMAGES'] = -1; + $configArray['CACHE_CODE'] = -1; + $configArray['CACHE_PAGE'] = -1; + $configArray['ACL_MODE'] = 'xml'; + $configArray['ACL_CLASS'] = 'org.glizy.application.Acl'; + $configArray['ADM_THUMBNAIL_CROP'] = false; + $configArray['ADM_THUMBNAIL_CROPPOS'] = 1; + $configArray['ADM_SITE_MAX_DEPTH'] = NULL; + $configArray['HIDE_PRIVATE_PAGE'] = true; + $configArray['APP_NAME'] = ''; + $configArray['APP_VERSION'] = ''; + $configArray['APP_AUTHOR'] = ''; + $configArray['CORE_VERSION'] = GLZ_CORE_VERSION; + $configArray['SEF_URL'] = false; + $configArray['PRESERVE_SCRIPT_NAME']= false; + $configArray['SITEMAP'] = 'config/siteMap.xml'; + $configArray['REMEMBER_PAGEID'] = false; + $configArray['PSW_METHOD'] = 'MD5'; + $configArray['USER_LOG'] = false; + $configArray['JS_COMPRESS'] = false; + $configArray['JPG_COMPRESSION'] = 80; + $configArray['THUMB_WIDTH'] = 150; + $configArray['THUMB_HEIGHT'] = 150; + $configArray['THUMB_SMALL_WIDTH'] = 50; + $configArray['THUMB_SMALL_HEIGHT'] = 50; + $configArray['IMG_LIST_WIDTH'] = 100; + $configArray['IMG_LIST_HEIGHT'] = 100; + $configArray['IMG_WIDTH_ZOOM'] = 800; + $configArray['IMG_HEIGHT_ZOOM'] = 600; + $configArray['IMG_WIDTH'] = 200; + $configArray['IMG_HEIGHT'] = 200; + $configArray['LOG_FILE'] = ''; + $configArray['LOG_LEVEL'] = GLZ_LOG_ALL; + $configArray['STATIC_FOLDER'] = NULL; + $configArray['TEMPLATE_FOLDER'] = NULL; + $configArray['FORM_ITEM_TEMPLATE'] = '<div class="formItem">##FORM_LABEL####FORM_ITEM##<br /></div>'; + $configArray['FORM_ITEM_RIGHT_LABEL_TEMPLATE'] = '<div class="formItemRigthLabel">##FORM_LABEL####FORM_ITEM##<br /></div>'; + $configArray['FORM_ITEM_HIDEN_TEMPLATE'] = '<div class="formItemHidden">##FORM_ITEM##</div>'; + $configArray['SITE_ID'] = NULL; + $configArray['ALLOW_MODE_OVERRIDE'] = false; + $configArray['USER_DEFAULT_ACTIVE_STATE'] = 0; + $configArray['USER_DEFAULT_USERGROUP'] = 4; + $configArray['MULTILANGUAGE_ENABLED'] = false; + $configArray['ACL_ENABLED'] = false; + $configArray['CATEGORY_ENABLED'] = false; + $configArray['SANITIZE_URL'] = true; + $configArray['DEFAULT_SKIN_TYPE'] = 'PHPTAL'; + + $configArray['AJAX_SKIP_DECODE'] = true; + $configArray['GLIZY_ADD_CORE_JS'] = true; + $configArray['GLIZY_ADD_JS_LIB'] = true; + $configArray['GLIZY_ADD_JQUERY_JS'] = true; + $configArray['GLIZY_ADD_JQUERYUI_JS'] = false; + $configArray['GLIZY_ADD_VALIDATE_JS'] = true; + $configArray['GLIZY_JQUERY'] = 'jquery-1.7.2.min.js'; + $configArray['GLIZY_JQUERYUI'] = 'jquery-ui-1.8.14.custom.min.js'; + $configArray['GLIZY_JQUERYUI_THEME'] = 'ui-lightness/jquery-ui-1.8.14.custom.css'; + $configArray['TINY_MCE_DEF_PLUGINS'] = 'inlinepopups,paste,directionality,xhtmlxtras,fullscreen,GLZ_link,GLZ_image'; + $configArray['TINY_MCE_PLUGINS'] = ''; + $configArray['TINY_MCE_BUTTONS1'] = 'bold,italic,|,justifyleft,justifycenter,justifyright,justifyfull,|,bullist,numlist,outdent,indent,blockquote'; + $configArray['TINY_MCE_BUTTONS2'] = 'formatselect,|,undo,redo,pastetext,pasteword,removeformat,|,link,unlink,anchor,image,hr,charmap,|,code,fullscreen'; + $configArray['TINY_MCE_BUTTONS3'] = ''; + $configArray['TINY_MCE_INTERNAL_LINK'] = true; + $configArray['BASE_REGISTRY_PATH'] = 'org/glizy'; + $configArray['REGISTRY_TEMPLATE_NAME'] = '{{BASE_REGISTRY_PATH}}/templateName'; + $configArray['REGISTRY_TEMPLATE_VALUES'] = '{{BASE_REGISTRY_PATH}}/templateValues/'; + $configArray['REGISTRY_SITE_PROP'] = '{{BASE_REGISTRY_PATH}}/siteProp/'; + $configArray['REGISTRY_METANAVIGATION'] = '{{BASE_REGISTRY_PATH}}/metanavigation/'; + $configArray['glizy.media.imageMagick'] = false; + $configArray['glizy.media.image.unsharpMask'] = false; + $configArray['glizy.routing.newParser'] = true; + $configArray['glizy.form.cssClass'] = ''; + $configArray['glizy.formElement.cssClass'] = ''; + $configArray['glizy.formElement.cssClassLabel'] = ''; + $configArray['glizy.formElement.admCssClass'] = ''; + $configArray['glizy.formButton.cssClass'] = ''; + $configArray['glizy.datagrid.action.editCssClass'] = 'icon-pencil btn-icon'; + $configArray['glizy.datagrid.action.editDraftCssClass'] = 'icon-edit btn-icon'; + $configArray['glizy.datagrid.action.deleteCssClass'] = 'icon-trash btn-icon'; + $configArray['glizy.datagrid.action.hideCssClass'] = 'icon-eye-close btn-icon'; + $configArray['glizy.datagrid.action.showCssClass'] = 'icon-eye-open btn-icon'; + $configArray['glizy.datagrid.checkbox.on'] = 'icon-check btn-icon'; + $configArray['glizy.datagrid.checkbox.off'] = 'icon-check-empty btn-icon'; + $configArray['glizy.authentication'] = 'org.glizy.authentication.Database'; + $configArray['glizy.dataAccess.schemaManager.cacheLife'] = 36000; + $configArray['glizy.dataAccess.serializationMode'] = 'json'; + $configArray['glizy.dataAccess.document.enableComment'] = false; + $configArray['glizy.dataAccess.validate'] = true; + $configArray['glizy.session.store'] = ''; + + + if (!$serverName) { + $configFileName = org_glizy_Paths::get('APPLICATION').'config/config.xml'; + $tempName = array( + isset($_SERVER['GLIZY_APPNAME']) ? $_SERVER['GLIZY_APPNAME'] : '', + getenv('GLIZY_SERVER_NAME'), + is_null( $_SERVER["SERVER_NAME"] ) ? 'console' : $_SERVER["SERVER_NAME"] + ); + foreach($tempName as $serverName) { + if ($serverName) { + $tempConfigFileName = org_glizy_Paths::get('APPLICATION').'config/config_'.$serverName.'.xml'; + if (file_exists($tempConfigFileName)) { + $configFileName = $tempConfigFileName; + break; + } + } + } + } else { + $configFileName = org_glizy_Paths::get('APPLICATION').'config/config_'.$serverName.'.xml'; + } + + if (!file_exists($configFileName)) { + $configFileName = org_glizy_Paths::get('APPLICATION').'config/config.xml'; + if (!file_exists($configFileName)) { + throw new Exception('Config file not found.'); + } + } + + /** @var $compiler org_glizy_compilers_Config */ + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Config'); + $compiledConfigFileName = $compiler->verify($configFileName); + + // TODO + // controllare errore + include($compiledConfigFileName); + + if (!empty($configArray['STATIC_FOLDER'])) + { + org_glizy_Paths::set('APPLICATION_STATIC', org_glizy_Config::get( 'STATIC_FOLDER' ) ); + } + if (!empty($configArray['TEMPLATE_FOLDER'])) + { + org_glizy_Paths::set('APPLICATION_TEMPLATE', org_glizy_Config::get('TEMPLATE_FOLDER') ); + } + + if ( $configArray['ALLOW_MODE_OVERRIDE'] && isset( $_GET['mode'] ) ) + { + org_glizy_Config::setMode( $_GET['mode'] ); + } + + define( 'GLZ_CHARSET', __Config::get( 'CHARSET' ) ); + } + + /** + * @param $modeName + */ + function setMode( $modeName ) + { + $configArray = &org_glizy_Config::_getConfigArray(); + if ( isset( $configArray[ '__modes__'][ $modeName ] ) ) + { + foreach( $configArray[ '__modes__'][ $modeName ] as $k => $v ) + { + $configArray[ $k ] = $v; + } + } + else + { + // TODO: in modalit� debug visualzzare un warning + } + } + + static function destroy() + { + $configArray = &self::_getConfigArray(); + $configArray = null; + } +} + +// shortcut version +/** + * Class __Config + */ +class __Config extends org_glizy_Config +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/Exception.php b/src/core/classes/org/glizy/Exception.php new file mode 100755 index 0000000..97b441b --- /dev/null +++ b/src/core/classes/org/glizy/Exception.php @@ -0,0 +1,102 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +define('GLZ_E_ERROR', E_ERROR); +define('GLZ_E_WARNING', E_WARNING); +define('GLZ_E_NOTICE', E_NOTICE); +define('GLZ_E_404', 404); +define('GLZ_E_500', 500); + +/** + * Class org_glizy_Exception + */ +class org_glizy_Exception +{ + + /** + * @param string $message + * @param int $errono + * @param string $file + */ + function __construct($message, $errono = GLZ_E_ERROR, $file = '') + { + if (is_array($message)) { + $messageStr = array_shift($message); + $message = vsprintf($messageStr, $message); + } + + if ($errono != GLZ_E_404) { + self::show($errono, '', '', '', $message); + } else { + self::show404($errono, $message); + } + exit(); + } + + /** + * @param int $errno + * @param string $message + */ + static public function show404($errno, $message) + { + $e = array(); + $e['code'] = $errno; + $e['description'] = $message; + $e['message'] = ''; + header("HTTP/1.0 404 Not Found"); + include_once(dirname(__FILE__) . '/../../../pages/errors/404.php'); + exit(); + } + + /** + * @param int $errno + * @param string $errstr + * @param string $errfile + * @param int $errline + * @param string $message + * @param int $headerCode + */ + static public function show($errno, $errstr, $errfile, $errline, $message = '', $headerCode = 500) + { + $eventInfo = array('type' => 'dumpException', 'data' => array('message' => $message, 'errono' => $errono, 'file' => $errfile, 'errline' => $errline)); + $evt = &org_glizy_ObjectFactory::createObject('org.glizy.events.Event', $this, $eventInfo); + org_glizy_events_EventDispatcher::dispatchEvent($evt); + + @header('HTTP/1.0 500 Internal Server Error'); + $errors = array( + 1 => 'E_ERROR', + 2 => 'E_WARNING', + 4 => 'E_PARSE', + 8 => 'E_NOTICE', + 16 => 'E_CORE_ERROR', + 32 => 'E_CORE_WARNING', + 64 => 'E_COMPILE_ERROR', + 128 => 'E_COMPILE_WARNING', + 256 => 'E_USER_ERROR', + 512 => 'E_USER_WARNING', + 2047 => 'E_ALL', + 2048 => 'E_STRICT', + 4096 => 'E_RECOVERABLE_ERROR' + ); + + $e = array(); + $e['code'] = isset($errors[$errno]) ? $errors[$errno] : $errors[1]; + $e['description'] = $errstr; + $e['message'] = $message; + + if (class_exists('org_glizy_Config') && org_glizy_Config::get('DEBUG') === true) { + $e['file'] = $errfile; + $e['line'] = $errline; + $e['stacktrace'] = array_slice(debug_backtrace(), 2); + include_once(dirname(__FILE__) . '/../../../pages/errors/debug.php'); + } else { + include_once(dirname(__FILE__) . '/../../../pages/errors/general.php'); + } + exit(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/GlizyObject.php b/src/core/classes/org/glizy/GlizyObject.php new file mode 100755 index 0000000..e8f9a4c --- /dev/null +++ b/src/core/classes/org/glizy/GlizyObject.php @@ -0,0 +1,156 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class GlyzyObject */ +class GlizyObject +{ + protected $_className = NULL; + + /** + * + */ + function __construct() + { + } + + /** + * @param bool $toLower + * + * @return null|string + */ + function getClassName($toLower=true) + { + if ($toLower) { + return strtolower( is_null($this->_className) ? get_class($this) : $this->_className ); + } else { + return is_null($this->_className) ? get_class($this) : $this->_className; + } + } + + // events functions + /** + * @param $type + * @param $listener + * @param bool $useCapture + * @param null $method + */ + function addEventListener($type, &$listener, $useCapture=false, $method=null ) + { + org_glizy_events_EventDispatcher::addEventListener($type, $listener, $useCapture, $method ); + } + + /** + * @param $type + * @param $listener + * @param bool $useCapture + */ + function removeEventListener($type, &$listener, $useCapture=false) + { + org_glizy_events_EventDispatcher::removeEventListener($type, $listener, $useCapture); + } + + /** + * @param $evt + * @return bool + */ + function dispatchEvent(&$evt) + { + if (is_array($evt)) + { + $evt = &org_glizy_ObjectFactory::createObject('org.glizy.events.Event', $this, $evt); + } + return org_glizy_events_EventDispatcher::dispatchEvent($evt); + } + + /** + * @param $type + * @param $evt + * @return bool + */ + function dispatchEventByArray($type, $evt) + { + $eventInfo = array('type' => $type, 'data' => $evt); + $evt = &org_glizy_ObjectFactory::createObject('org.glizy.events.Event', $this, $eventInfo); + return org_glizy_events_EventDispatcher::dispatchEvent($evt); + } + + /** + * @param $type + * @return bool + */ + function hasEventListener($type) + { + return org_glizy_events_EventDispatcher::hasEventListener($type); + } + + /** + * @param $type + * @return bool + */ + function willTrigger($type) + { + return org_glizy_events_EventDispatcher::willTrigger($type); + } + + // error methods + /** + * @param $msg + */ + function triggerError($msg) + { + trigger_error($msg); + } + + /** + * @param $msg + * @param int $level + * @param string $group + * @param bool $addUserInfo + */ + function log( $msg, $level = GLZ_LOG_DEBUG, $group = '', $addUserInfo = false ) + { + if ( $addUserInfo ) + { + /** @var org_glizy_application_User $user */ + $user = &org_glizy_ObjectValues::get('org.glizy', 'user'); + if ( is_string( $msg ) ) + { + $msg .= "\t" . $user->toString(); + } + if ( is_array( $msg ) ) + { + $msg['user'] = $user->toString(); + } + if ( is_object( $msg ) ) + { + $msg->user = $user->toString(); + } + } + $this->dispatchEventByArray( GLZ_LOG_EVENT, array('level' => $level, + 'group' => $group, + 'message' => is_string( $msg ) ? $this->getClassName()." ".$msg : $msg ) ); + } + + /** + * @param $msg + * @param string $debugInfo + * @param bool $type + * @param string $group + * @param bool $addUserInfo + */ + function logAndMessage( $msg, $debugInfo = '', $type=false, $group = '', $addUserInfo = false ) + { + $type = $type===false || $type===true ? ($type ? GLZ_LOG_ERROR : GLZ_LOG_DEBUG) : $type; + if ( class_exists( 'org_glizy_application_MessageStack' ) ) + { + org_glizy_application_MessageStack::add( $msg, $type==GLZ_LOG_ERROR ? GLZ_MESSAGE_ERROR : GLZ_MESSAGE_SUCCESS ); + } + $this->log( $msg.' '.$debugInfo, $type, $group, $addUserInfo ); + } +} diff --git a/src/core/classes/org/glizy/Modules.php b/src/core/classes/org/glizy/Modules.php new file mode 100755 index 0000000..8d1f906 --- /dev/null +++ b/src/core/classes/org/glizy/Modules.php @@ -0,0 +1,174 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_Modules + */ +class org_glizy_Modules +{ + + /** + * @return null|org_glizy_ModuleVO + */ + public static function &getModules() + { + $modules = &org_glizy_ObjectValues::get('org.glizy', 'modules', array()); + return $modules; + } + + /** + * @return null|org_glizy_ModuleVO + */ + function &getModulesSorted() + { + $modules = &org_glizy_ObjectValues::get('org.glizy', 'modules', array()); + uasort($modules, function($a, $b) { + return strnatcasecmp($a->name, $b->name); + }); + return $modules; + } + + /** + * @param $id + * @return org_glizy_ModuleVO|null + */ + public static function getModule( $id ) + { + $modules = &org_glizy_ObjectValues::get( 'org.glizy', 'modules', array() ); + return isset( $modules[ $id ] ) ? $modules[ $id ] : null; + } + + /** + * @param org_glizy_ModuleVO $moduleVO + */ + function addModule( org_glizy_ModuleVO $moduleVO ) + { + $modules = &org_glizy_ObjectValues::get( 'org.glizy', 'modules', array() ); + $modulesState = self::getModulesState(); + if ( isset( $modulesState[ $moduleVO->id ] ) && !$modulesState[ $moduleVO->id ] ) + { + $moduleVO->enabled = false; + } + $modules[ $moduleVO->id ] = $moduleVO; + } + + /** + * @return org_glizy_ModuleVO + */ + function getModuleVO() + { + return new org_glizy_ModuleVO(); + } + + + /** + * @return array|mixed + */ + static function getModulesState() + { + $pref = unserialize( org_glizy_Registry::get( __Config::get( 'BASE_REGISTRY_PATH' ).'/modules', '') ); + if (empty($pref)) + { + $pref = array(); + } + return $pref; + } + + /** + * @param $state + */ + function setModulesState( $state ) + { + org_glizy_Registry::set( __Config::get( 'BASE_REGISTRY_PATH' ).'/modules', serialize( $state ) ); + org_glizy_cache_CacheFile::cleanPHP(); + } + + function deleteCache() + { + org_glizy_cache_CacheFile::cleanPHP(); + } + + function dump() + { + $modules = &org_glizy_ObjectValues::get( 'org.glizy', 'modules', array() ); + var_dump( $modules ); + } + +} + +/** + * Class org_glizy_ModuleVO + */ +class org_glizy_ModuleVO +{ + public $id; + public $name; + public $description; + public $classPath; + public $pageType = ''; + public $model = null; + public $pluginSnippet = ''; + public $enabled = true; + public $unique = true; + public $show = true; + public $edit = true; + public $pluginInPageType = false; + public $pluginInModules = false; + public $pluginInSearch = false; + public $canDuplicated = false; +} + +/** + * Class org_glizy_ModuleDescription + */ +class org_glizy_ModuleDescription +{ + private $moduleVO; + public $name; + public $author; + public $authorUrl; + public $pluginUrl; + public $version; + public $description; + public $installScript; + public $uninstallScript; + + /** + * @param org_glizy_ModuleVO $moduleVO + */ + function __construct( org_glizy_ModuleVO $moduleVO ) + { + $this->moduleVO = $moduleVO; + $this->name = $moduleVO->name; + + $path = glz_findClassPath( $moduleVO->classPath ); + if ( !is_null( $path ) && file_exists( $path . '/info.xml' ) ) + { + /** @var org_glizy_parser_XML $xml */ + $xml = org_glizy_ObjectFactory::createObject( 'org.glizy.parser.XML' ); + $xml->loadAndParseNS( $path . '/info.xml' ); + foreach( $xml->documentElement->childNodes as $n ) + { + if ( property_exists( $this, $n->tagName ) ) + { + $this->{ $n->tagName } = utf8_decode( $n->nodeValue ); + } + } + + } + } +} + +// shortcut version +/** + * Class __Modules + */ +class __Modules extends org_glizy_Modules +{ +} diff --git a/src/core/classes/org/glizy/ObjectFactory.php b/src/core/classes/org/glizy/ObjectFactory.php new file mode 100755 index 0000000..39d0c4a --- /dev/null +++ b/src/core/classes/org/glizy/ObjectFactory.php @@ -0,0 +1,324 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class org_glizy_ObjectFactory */ +class org_glizy_ObjectFactory +{ + /** + * @return GlizyObject|mixed + */ + static function createObject() + { + $args = func_get_args(); + $classPath = array_shift($args); + if (substr($classPath, -1, 1)=='*') + { + // TODO + // ERRORE + } + + $newObj = NULL; + $classPath = org_glizy_ObjectFactory::resolveClass($classPath); + $className = str_replace('.', '_', $classPath); + if (!class_exists($className)) + { + $r = glz_import($classPath); + if ( $r === false ) + { + new Exception( '[ org_glizy_ObjectFactory ] class not found: '.$className ); + } + } else { + $costructString = '$newObj = new '.$className.'('; + for ($i=0; $i<count($args); $i++) + { + $costructString .= '$args['.$i.']'; + if ($i<count($args)-1) $costructString .= ', '; + } + $costructString .= ');'; + eval($costructString); + } + return $newObj; + } + + + /** + * @param $className + * @param $application + * @param $parent + * @param $tagName + * @param $id + * @param string $originalId + * @param bool $skipImport + * @param string $mode + * @return mixed + */ + static function &createComponent($className, &$application, &$parent, $tagName, $id, $originalId='', $skipImport=false, $mode='') + { + $className = org_glizy_ObjectFactory::resolveClass($className); + $componentClassName = str_replace('.', '_', $className); + + if (!class_exists($componentClassName)) + { + // controlla se il file className.xml esiste sia nelle classi dell'applicazione + // si in quelle di sistema + // se esiste: + // deve compilarlo e caricarlo + // se non esiste + // deve dare un messaggio di errore + + // TODO + // in questo modo non carica eventuali classi dal core + // + // TODO + // deve essere prevista anche la compilazione dei models se sono in PHP e non in XML + // + $fileName = glz_findClassPath($className); + $pathInfo = pathinfo($fileName); + if (empty($pathInfo['basename'])) + { + trigger_error($className.': component file not found', E_USER_ERROR); + } + if ($pathInfo['extension']=='xml') + { + /** @var org_glizy_compilers_Component $compiler */ + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Component'); + $compiledFileName = $compiler->verify($fileName, array('originalClassName' => $className, 'mode' => $mode)); + require_once($compiledFileName); + $componentClassName = glz_basename($compiledFileName); + } + else + { + require_once($fileName); + } + + $newObj = new $componentClassName($application, $parent, $tagName, $id, $originalId, $skipImport); + return $newObj; + } + + $newObj = new $componentClassName($application, $parent, $tagName, $id, $originalId, $skipImport); + return $newObj; + } + + /** + * @param $classPath + * @param integer $connectionNumber + * + * @return org_glizy_dataAccess_ActiveRecord + * @throws org_glizy_compilers_CompilerException + */ + static function &createModel($classPath, $connectionNumber=null) + { + $classInfo = org_glizy_ObjectFactory::resolveClassNew($classPath); + if (isset($classInfo['path'])) { + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Model'); + $compiledFileName = $compiler->verify($classInfo['path'], array('originalClassName' => $classInfo['originalClassName'])); + require_once($compiledFileName); + $className = glz_basename($compiledFileName); + $newObj = $connectionNumber ? new $className($connectionNumber) : new $className(); + + $classMap = &org_glizy_ObjectValues::get('org.glizy.ObjectFactory', 'ClassMap', array()); + $classMap[$classPath] = $className; + } else if (isset($classInfo['class'])) { + $newObj = $connectionNumber ? new $classInfo['class']($connectionNumber) : new $classInfo['class'](); + } else { + throw org_glizy_compilers_CompilerException::fileNotFound($classPath); + } + return $newObj; + } + + /** + * @param string $classPath + * @param string $queryName + * @param array $options + * + * @return org_glizy_dataAccessDoctrine_RecordIterator + * @throws org_glizy_compilers_CompilerException + */ + static function &createModelIterator($classPath, $queryName=null, $options=array()) + { + /** @var org_glizy_dataAccessDoctrine_ActiveRecord $ar */ + $ar = org_glizy_objectFactory::createModel($classPath); + $it = $ar->createRecordIterator(); + if ($queryName) { + $it->load($queryName, isset($options['params']) ? $options['params'] : null); + + if (isset($options['filters'])) { + $it->setFilters($options['filters']); + } + + if (isset($options['order'])) { + $it->setOrderBy($options['order']); + } + + if (isset($options['limit'])) { + $it->limit($options['limit']); + } + } + + return $it; + } + + /** + * @param org_glizy_application_Application $application + * @param string $pageType + * @param string $path + * @param array $options + * + * @return mixed + */ + static function &createPage(&$application, $pageType, $path=NULL, $options=NULL) + { + $pageType = org_glizy_ObjectFactory::resolvePageType($pageType); + $options['pageType'] = $pageType.'.xml'; + $options['path'] = is_null($path) ? org_glizy_Paths::getRealPath('APPLICATION_PAGE_TYPE') : $path; + $fileName = $options['path'].$options['pageType']; + + if (isset($options['pathTemplate']) && isset($options['mode'])) { + $verifyFileName = $options[ 'pathTemplate' ].'/pageTypes/'.$options[ 'pageType' ]; + if (file_exists($verifyFileName)) { + $options['verifyFileName'] = $verifyFileName; + } + } + + if ( !file_exists( $fileName ) ) + { + $fileName = glz_findClassPath( $pageType ); + if ( is_null( $fileName ) ) + { + // TODO: file non trovato visualizzare errore + } + } + + // TODO + // controllare l'esistenza del file + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.PageType'); + $compiledFileName = $compiler->verify($fileName, $options); + + // TODO verificare se la pagina è stata compilata + require_once($compiledFileName); + + $idPrefix = isset($options['idPrefix']) ? $options['idPrefix'] : ''; + $className = glz_basename($compiledFileName); + $newObj = new $className($application, isset($options['skipImport']) ? $options['skipImport'] : false, $idPrefix); + return $newObj; + } + + /** + * @param org_glizy_components_Component $component + * @param org_glizy_application_Application $application + * @param string $pageType + * @param string $path + * @param array $options + * @param string $remapId + * @param bool $atTop + */ + function attachPageToComponent($component, $application, $pageType, $path, $options, $remapId, $atTop=true) + { + $originalRootComponent = $application->getRootComponent(); + $originalChildren = $component->childComponents; + $component->childComponents = array(); + org_glizy_ObjectFactory::createPage($application, $pageType, $path, $options); + $rootComponent = $application->getRootComponent(); + $rootComponent->init(); + $rootComponent->execDoLater(); + $application->_rootComponent = &$originalRootComponent; + + for($i=0; $i<count($rootComponent->childComponents); $i++) + { + $rootComponent->childComponents[$i]->remapAttributes($remapId); + $component->addChild($rootComponent->childComponents[$i]); + $rootComponent->childComponents[$i]->_parent = &$component; + } + + $component->childComponents = $atTop ? array_merge($component->childComponents, $originalChildren) : + array_merge($originalChildren, $component->childComponents); + } + + /** + * @param string $orig + * @param string $dest + */ + static function remapClass($orig='', $dest='') + { + $classMap = &org_glizy_ObjectValues::get('org.glizy.ObjectFactory', 'ClassMap', array()); + $classMap[$orig] = $dest; + } + + /** + * @param $classPath + * @return mixed + */ + static function resolveClass($classPath) + { + $classMap = &org_glizy_ObjectValues::get('org.glizy.ObjectFactory', 'ClassMap', array()); + return isset($classMap[$classPath]) ? $classMap[$classPath] : $classPath; + } + + /** + * @param string $classPath + * + * @return array + */ + function resolveClassNew($classPath) + { + $classMap = &org_glizy_ObjectValues::get('org.glizy.ObjectFactory', 'ClassMap', array()); + $newClassPath = isset($classMap[$classPath]) ? $classMap[$classPath] : $classPath; + $className = str_replace('.', '_', $newClassPath); + if (!class_exists($className)) { + return array('originalClassName' => $classPath, 'path' => glz_findClassPath($newClassPath)); + } else { + return array('originalClassName' => $classPath, 'class' => $className); + } + } + + /** + * @param string $orig + * @param string $dest + */ + function remapPageType($orig='', $dest='') + { + $orig = preg_replace('/\.xml$/i', '', $orig); + $dest = preg_replace('/\.xml$/i', '', $dest); + $pageTypeMap = &org_glizy_ObjectValues::get('org.glizy.ObjectFactory', 'PageTypeMap', array()); + $pageTypeMap[$orig] = $dest; + } + + /** + * @param $pageTypePath + * @return mixed + */ + function resolvePageType($pageTypePath) + { + $pageTypeMap = &org_glizy_ObjectValues::get('org.glizy.ObjectFactory', 'PageTypeMap', array()); + return isset($pageTypeMap[$pageTypePath]) ? $pageTypeMap[$pageTypePath] : $pageTypePath; + } + + /** + * @param $cachedFile + * @param $fileName + */ + function requireComponent( $cachedFile, $fileName ) + { + if ( !file_exists( $cachedFile ) ) + { + /** @var org_glizy_compilers_Component $compiler */ + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Component'); + $cachedFile = $compiler->verify($fileName); + } + require_once( $cachedFile ); + } +} + +// shortcut version +/** + * Class __ObjectFactory + */ +class __ObjectFactory extends org_glizy_ObjectFactory +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/ObjectValues.php b/src/core/classes/org/glizy/ObjectValues.php new file mode 100755 index 0000000..1501e23 --- /dev/null +++ b/src/core/classes/org/glizy/ObjectValues.php @@ -0,0 +1,119 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class org_glizy_ObjectValues */ +class org_glizy_ObjectValues +{ + /** + * @param $className + * @param string $name + * @param null $defaultValue + * @return null + */ + static function &get($className, $name='', $defaultValue=NULL) + { + $name = $name.'@'.$className; + if ( empty( $className ) ) return $defaultValue; + $params = &org_glizy_ObjectValues::_getValuesArray(); + if (!isset($params[$name])) $params[$name] = $defaultValue; + return $params[$name]; + } + + /** + * @param $className + * @param string $name + * @param $value + */ + static function set($className, $name='', $value) + { + $name = $name.'@'.$className; + $params = &org_glizy_ObjectValues::_getValuesArray(); + $params[$name] = $value; + } + + /** + * @param $className + * @param string $name + * @param $value + */ + static function setByReference($className, $name='', &$value) + { + $name = $name.'@'.$className; + $params = &org_glizy_ObjectValues::_getValuesArray(); + $params[$name] = &$value; + } + + + /** + * @param $className + * @param string $name + * @return bool + */ + function exists($className, $name='') + { + $name = $name.'@'.$className; + $params = &org_glizy_ObjectValues::_getValuesArray(); + return isset($params[$name]); + } + + + /** + * @param $className + * @param string $name + */ + function remove($className, $name='') + { + $name = $name.'@'.$className; + $params = &org_glizy_ObjectValues::_getValuesArray(); + if (array_key_exists($name, $params)) + { + unset($params[$name]); + } + } + + + static function removeAll() + { + $params = &org_glizy_ObjectValues::_getValuesArray(); + $params = array(); + } + + function dump() + { + $params = &org_glizy_ObjectValues::_getValuesArray(); + var_dump($params); + } + + function dumpKeys() + { + $params = &org_glizy_ObjectValues::_getValuesArray(); + var_dump(array_keys($params)); + } + + /** + * @param bool $init + * + * @return mixed + */ + static function &_getValuesArray($init=false) + { + static $_valuesArray = array(); + return $_valuesArray; + } + + +} + +// shortcut version +/** + * Class __ObjectValues + */ +class __ObjectValues extends org_glizy_ObjectValues +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/Paths.php b/src/core/classes/org/glizy/Paths.php new file mode 100755 index 0000000..26338b0 --- /dev/null +++ b/src/core/classes/org/glizy/Paths.php @@ -0,0 +1,169 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_Paths + */ +class org_glizy_Paths +{ + /** + * @param string $pathApplication + * @param string $pathCore + */ + static function init($pathApplication='', $pathCore='') + { + $pathsArray = &org_glizy_Paths::_getPathsArray(); + if (count($pathsArray)) { + return; + } + + if (empty($pathCore) || $pathCore == '/') { + $pathCore = './'; + } + if (substr($pathCore, -1, 1) != '/') { + $pathCore .= '/'; + } + if (substr($pathApplication, -1, 1) != '/') { + $pathApplication .= '/'; + } + + $pathApplicationDepth = count(explode('/', $pathApplication))-1; + $pathsArray['BASE'] = $pathCore; //str_repeat('../', $pathApplicationDepth-1); + $pathsArray['CORE'] = $pathCore.'core/'; + $pathsArray['CORE_CLASSES'] = $pathCore.'core/classes/'; + $pathsArray['CORE_LIBS'] = $pathCore.'core/libs/'; + // $pathsArray['CACHE'] = 'cache/'; + $pathsArray['CACHE'] = dirname( $pathApplication ) .'/cache/'; + $pathsArray['ROOT'] = dirname( $pathApplication ).'/'; + + $pathsArray['CACHE_CODE'] = $pathsArray['CACHE']; + $pathsArray['CACHE_IMAGES'] = $pathsArray['CACHE']; + $pathsArray['CACHE_CSS'] = $pathsArray['CACHE']; + $pathsArray['CACHE_JS'] = $pathsArray['CACHE']; + $pathsArray['APPLICATION'] = $pathApplication; + $pathsArray['APPLICATION_CLASSES'] = $pathApplication.'classes/'; + $pathsArray['APPLICATION_LIBS'] = $pathApplication.'libs/'; + $pathsArray['APPLICATION_MEDIA_ARCHIVE'] = $pathApplication.'mediaArchive/'; + $pathsArray['APPLICATION_PAGE_TYPE'] = $pathApplication.'pageTypes/'; + $pathsArray['APPLICATION_STARTUP'] = $pathApplication.'startup/'; + $pathsArray['APPLICATION_SHUTDOWN'] = $pathApplication.'shutdown/'; + $pathsArray['APPLICATION_TEMPLATE'] = $pathApplication.'templates/'; + $pathsArray['APPLICATION_STATIC'] = $pathsArray['ROOT'].'static/'; + $pathsArray['STATIC_DIR'] = $pathsArray['BASE'].'static/'; + $pathsArray['CORE_STATIC_DIR'] = $pathsArray['CORE'].'static/js/'; + + $page = pathinfo(GLZ_SCRIPNAME); + $dirname = explode('/', $page['dirname']); + $page["basename_noext"] = substr($page["basename"], 0, strlen($page["basename"])-(strlen($page["extension"])+1)); + $pathsArray['PAGE_FOLDER'] = implode('/', array_splice($dirname, count($dirname)-$pathApplicationDepth, $pathApplicationDepth+1)); + $pathsArray['PAGE_INDEX'] = $page['basename']; + + $pathsArray['PAGE_AJAX'] = $page["basename_noext"].'_ajax.php'; + $pathsArray['PAGE_IMAGEPREVIEW'] = $page["basename_noext"].'_imagePreview.php'; + $pathsArray['PAGE_IMAGETHUMBNAIL'] = $page["basename_noext"].'_getImage.php'; + $pathsArray['SEARCH_PATH'] = array($pathsArray['APPLICATION_CLASSES'] , $pathsArray['CORE_CLASSES']); + } + + + /** + * @param $pathCode + * + * @return null + */ + static function get($pathCode) + { + $pathsArray = &org_glizy_Paths::_getPathsArray(); + return isset($pathsArray[$pathCode]) ? $pathsArray[$pathCode] : NULL; + } + + /** + * @param $pathCode + * @param null $fileName + * + * @return string + */ + static function getRealPath($pathCode, $fileName=null) + { + $pathsArray = &org_glizy_Paths::_getPathsArray(); + // TODO verificare che il path richiesto esiste veramente + if (is_null($fileName)) return realpath($pathsArray[$pathCode]).'/'; + else return realpath($pathsArray[$pathCode].'/'.$fileName); + } + + + /** + * @param $pathCode + * @param $value + */ + static function set($pathCode, $value) + { + $pathsArray = &org_glizy_Paths::_getPathsArray(); + $pathsArray[$pathCode] = $value; + } + + /** + * @param $pathCode + * @param $path + * @param null $relativeTo + */ + static function add($pathCode, $path, $relativeTo=null) + { + // controlla se l'ultimo carattere è uno slash + if (substr($path, -1, 1) != "/") { + $path .= "/"; + } + $pathsArray = &org_glizy_Paths::_getPathsArray(); + $pathsArray[$pathCode] = is_null($relativeTo) ? $path : $pathsArray[$relativeTo].$path; + } + + static function dump() + { + $pathsArray = &org_glizy_Paths::_getPathsArray(); + var_dump($pathsArray); + } + + /** + * @return mixed + */ + static function getClassSearchPath() + { + $pathsArray = &org_glizy_Paths::_getPathsArray(); + return $pathsArray['SEARCH_PATH']; + } + + /** + * @param $path + */ + static function addClassSearchPath($path) + { + $pathsArray = &org_glizy_Paths::_getPathsArray(); + $pathsArray['SEARCH_PATH'][] = $path; + } + + static function &_getPathsArray() + { + // Array associativo (PATH_CODE=>PATH) + static $_pathsArray = array(); + return $_pathsArray; + } + + static function destroy() + { + $pathsArray = &self::_getPathsArray(); + $pathsArray = array(); + } +} + +// shortcut version +/** + * Class __Paths + */ +class __Paths extends org_glizy_Paths +{ +} diff --git a/src/core/classes/org/glizy/Registry.php b/src/core/classes/org/glizy/Registry.php new file mode 100755 index 0000000..ef96942 --- /dev/null +++ b/src/core/classes/org/glizy/Registry.php @@ -0,0 +1,94 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class org_glizy_Registry */ +class org_glizy_Registry +{ + /** + * @param $path + * @param null $defaultValue + * @return null + */ + static function get($path, $defaultValue=NULL) + { + $params = &org_glizy_Registry::_getValuesArray(); + + if (array_key_exists($path, $params)) return $params[$path]; + else + { + $rs = org_glizy_ObjectFactory::createModel('org.glizy.models.Registry'); + $rs->registry_path = $path; + if ($rs->find()) + { + $params[$path] = $rs->registry_value; + return $rs->registry_value; + } + else return $defaultValue; + } + } + + static function set($path, $value) + { + $params = &org_glizy_Registry::_getValuesArray(); + $params[$path] = $value; + $rs = org_glizy_ObjectFactory::createModel('org.glizy.models.Registry'); + $rs->find(array('registry_path' => $path)); + $rs->registry_path = $path; + $rs->registry_value = $value; + $rs->save(); + } + + static function add($path, $value) + { + self::set($path, $value); + } + + static function exists($key) + { + // TODO + } + + static function remove($path) + { + $params = &org_glizy_Registry::_getValuesArray(); + + if (array_key_exists($path, $params)) unset($params[$path]); + $rs = org_glizy_ObjectFactory::createModel('org.glizy.models.Registry'); + $rs->registry_path = $path; + if ($rs->find()) $rs->delete(); + } + + static function query($path) + { + $params = &org_glizy_Registry::_getValuesArray(); + $iterator = org_glizy_ObjectFactory::createModelIterator('org.glizy.models.Registry', 'all', array('filters' => array('registry_path' => $path))); + + // TODO controlare se ci sono stati errori + $result = array(); + + foreach ($iterator as $ar) + { + $params[$ar->registry_path] = $ar->registry_value; + $result[$ar->registry_path] = $ar->registry_value; + } + + return $result; + } + + static function &_getValuesArray($init=false) + { + static $_valuesArray = array(); + return $_valuesArray; + } +} + +// shortchut version +class __Registry extends org_glizy_Registry +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/Request.php b/src/core/classes/org/glizy/Request.php new file mode 100755 index 0000000..a852f34 --- /dev/null +++ b/src/core/classes/org/glizy/Request.php @@ -0,0 +1,273 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +if (!defined('GLZ_REQUEST_ALL')) define('GLZ_REQUEST_ALL', 0); +if (!defined('GLZ_REQUEST_GET')) define('GLZ_REQUEST_GET', 1); +if (!defined('GLZ_REQUEST_POST')) define('GLZ_REQUEST_POST', 2); +if (!defined('GLZ_REQUEST_ROUTING')) define('GLZ_REQUEST_ROUTING', 3); +if (!defined('GLZ_REQUEST_VALUE')) define('GLZ_REQUEST_VALUE', 0); +if (!defined('GLZ_REQUEST_TYPE')) define('GLZ_REQUEST_TYPE', 1); + + +/** + * Class org_glizy_Request + */ +class org_glizy_Request +{ + static $decodeUtf8 = false; + static $skipDecode = false; + static $translateInfo = true; + static $method = ''; + + function org_glizy_Request() + { + } + + static function init() + { + self::$method = strtolower( @$_SERVER['REQUEST_METHOD'] ); + $url = ''; + $params = &org_glizy_Request::_getValuesArray(true); + $charset = strtolower( org_glizy_Config::get('CHARSET') ); + $requestCharset = @$_SERVER[ 'CONTENT_TYPE' ]; + if ( $charset != "utf-8" && stripos( $requestCharset, 'utf-8' ) !== false ) + { + self::$decodeUtf8 = true; + } + + if ( self::$skipDecode ) + { + self::$decodeUtf8 = false; + } + + foreach($_GET as $k=>$v) + { + if (!is_array($v) && get_magic_quotes_gpc()) $v = stripslashes($v); + if ( self::$decodeUtf8 ) $v = org_glizy_Request::utf8_decode($v); + $url .= '&'.$k.'='.$v; + $params[$k]= array($v, GLZ_REQUEST_GET); + } + + foreach($_POST as $k=>$v) + { + if (!is_array($v) && get_magic_quotes_gpc()) $v = stripslashes($v); + if ( self::$decodeUtf8 ) $v = org_glizy_Request::utf8_decode($v); + $url .= '&'.$k.'='.$v; + $params[$k]= array($v, GLZ_REQUEST_POST); + } + + $contentType = @$_SERVER[ 'CONTENT_TYPE' ]; + $body = @file_get_contents('php://input'); + if ( $body && $contentType && $contentType != 'application/x-www-form-urlencoded' ) + { + $params['__postBody__'] = array($body, GLZ_REQUEST_POST); + parse_str( $body, $output ); + foreach($output as $k=>$v) + { + if ( !isset( $params[ $k ] ) ) + { + $url .= '&'.$k.'='.$v; + $params[$k]= array($v, GLZ_REQUEST_POST); + } + } + } + + $params[ '__url__' ] = array( __Routing::$requestUrl, GLZ_REQUEST_GET ); + $params[ '__back__url__' ] = array( $url, GLZ_REQUEST_GET ); + + if ( self::$translateInfo && isset($params[ 'pageId' ])) + { + $pageId = strtolower( $params[ 'pageId' ][ GLZ_REQUEST_VALUE ] ); + $translateInfo = __Session::get( '__translateInfo_'.$pageId, array( ) ); + + foreach( $translateInfo as $v ) + { + if ( isset($params[ $v[ 'target_name' ] ]) && $params[ $v[ 'target_name' ] ][ GLZ_REQUEST_VALUE ] == $v[ 'label' ] ) + { + $params[ $v[ 'target' ] ][ GLZ_REQUEST_VALUE ] = $v[ 'value' ]; + } + } + __Session::remove( '__translateInfo_'.$pageId ); + } + + $values = __Session::get( '__valuesForNextRefresh' ); + if ( isset( $values ) && is_array( $values ) ) + { + foreach( $values as $k => $v ) + { + $params[ $k ][ GLZ_REQUEST_VALUE ] = $v; + } + __Session::remove( '__valuesForNextRefresh' ); + } + } + + static function get($name, $defaultValue=NULL, $type=GLZ_REQUEST_ALL) + { + $params = &org_glizy_Request::_getValuesArray(); + $value = array_key_exists($name, $params) ? $params[$name] : NULL; + $value = is_null($value) ? $defaultValue : ($type==GLZ_REQUEST_ALL || $type==$value[GLZ_REQUEST_TYPE] ? $value[GLZ_REQUEST_VALUE] : $defaultValue); + return $value; + } + + static function getParams() + { + $params = &org_glizy_Request::_getValuesArray(); + return isset($params[ '__params__' ]) ? $params[ '__params__' ] : array(); + } + + + static function set($name, $value, $type=GLZ_REQUEST_ALL) + { + $params = &org_glizy_Request::_getValuesArray(); + + $params[$name] = array($value, $type); + } + + function add($name, $value, $type=GLZ_REQUEST_ALL) + { + $params = &org_glizy_Request::_getValuesArray(); + if (isset($params[$name])) + { + trigger_error('The param is already set'); + } + + $params[$name] = array($value, $type); + } + + static function exists($key, $type=null) + { + $params = &org_glizy_Request::_getValuesArray(); + if (is_null($type) || $type==GLZ_REQUEST_ALL) { + return isset($params[$key]); + } else { + return isset($params[$key]) && $params[$key][GLZ_REQUEST_TYPE] == $type; + } + } + + function isEqual( $name, $value ) + { + return strtolower( org_glizy_Request::get( $name, '' ) ) == strtolower( $value ); + } + + static function remove($name) + { + $params = &org_glizy_Request::_getValuesArray(); + if (isset($params[$name])) + { + unset($params[$name]); + } + } + + static function removeAll() + { + $params = &org_glizy_Request::_getValuesArray(); + $params = array(); + } + + static function getAllAsArray() + { + $params = &org_glizy_Request::_getValuesArray(); + $result = array(); + foreach($params as $k=>$v) + { + $result[$k] = $v[GLZ_REQUEST_VALUE]; + } + return $result; + } + + static function setFromArray($values, $type=GLZ_REQUEST_ALL) + { + $params = &org_glizy_Request::_getValuesArray( true ); + foreach($values as $k=>$v) + { + $params[$k] = is_array($v) ? $v : array($v, $type); + } + + } + + + function setValuesForNextRefresh( $values ) + { + __Session::set( '__valuesForNextRefresh', $values ); + } + + + static function dump($name=null) + { + if ($name) { + var_dump(org_glizy_Request::get($name)); + } else { + $params = &org_glizy_Request::_getValuesArray(); + var_dump($params); + } + } + + static function &_getValuesArray($init=false) + { + static $_valuesArray = array(); + if (!count($_valuesArray) && !$init) + { + org_glizy_Request::init(); + } + return $_valuesArray; + } + + function utf8_decode($values) + { + if (is_array($values)) + { + $keys = array_keys($values); + $count = count($values); + for ($i = 0; $i < $count; $i++) + { + if (is_array($values[$keys[$i]])) + { + $values[$keys[$i]] = org_glizy_Request::utf8_decode($values[$keys[$i]]); + } + else + { + if ( function_exists('iconv') ) + { + $output[$keys[$i]] = iconv("UTF-8", "CP1252", $values[$keys[$i]]); + } + else + { + $output[$keys[$i]] = utf8_decode($values[$keys[$i]]); + } + } + } + return $values; + } + else + { + if( function_exists('iconv') ) + { + return iconv( "UTF-8", "CP1252", $values ); + } + else + { + return utf8_decode( $values ); + } + } + } + + static function destroy() + { + $valuesArray = &self::_getValuesArray(); + $valuesArray = array(); + } +} + +// shortcut version +/** + * Class __Request + */ +class __Request extends org_glizy_Request +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/Routing.php b/src/core/classes/org/glizy/Routing.php new file mode 100755 index 0000000..166dbc0 --- /dev/null +++ b/src/core/classes/org/glizy/Routing.php @@ -0,0 +1,516 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_Routing + */ +class org_glizy_Routing +{ + static $requestUrl = ''; + static $queryString = ''; + static $baseUrl = ''; + static $baseUrlParam = ''; + + function org_glizy_Routing() + { + } + + static function init() + { + $configArray = &org_glizy_Routing::_getValuesArray(); + + $scriptName = '/' . str_replace( '/', '\/', str_replace( '\\', '/', $_SERVER["SCRIPT_NAME"] ) ) . '/'; + $dirName = '/^' . str_replace( '/', '\/', str_replace( '\\', '/', dirname( $_SERVER["SCRIPT_NAME"] ) )) . '\//'; + self::$requestUrl = $_SERVER["REQUEST_URI"]; + self::$requestUrl = preg_replace( array( $scriptName, $dirName ), array( '', '' ), self::$requestUrl, 1); + if ( org_glizy_Config::get( 'PRESERVE_SCRIPT_NAME' ) ) + { + self::$requestUrl = preg_replace( $dirName, '', self::$requestUrl, 1); + } + else + { + preg_replace( array( $scriptName, $dirName ), array( '', '' ), self::$requestUrl, 1); + } + self::$requestUrl = ltrim( self::$requestUrl, '/' ); + $pos = org_glizy_Config::get('SEF_URL') === 'full' ? strpos( self::$requestUrl, '?' ) : strpos( self::$requestUrl, '&' ); + if ( $pos !== false ) + { + self::$queryString = substr( self::$requestUrl, $pos + 1); + self::$requestUrl = substr( self::$requestUrl, 0, $pos ); + } + self::$requestUrl = trim( self::$requestUrl, '?' ); + + if ( org_glizy_Config::get('SEF_URL') === 'full' ) + { + self::$baseUrl = GLZ_HOST.'/'; + self::$baseUrlParam = '?'; + } + else + { + self::$baseUrl = org_glizy_Paths::get('PAGE_INDEX').'?'; + self::$baseUrlParam = '&'; + } + } + + static function dump() + { + var_dump(org_glizy_Routing::_getValuesArray()); + } + + + /** + * @param bool $removeGetParams + * + * @return string + */ + static function scriptUrl( $removeGetParams=false ) + { + if ( $removeGetParams ) + { + return self::$baseUrl.self::$requestUrl; + } + else + { + return self::$baseUrl.self::$requestUrl.( empty( self::$queryString ) ? '' : self::$baseUrlParam.self::$queryString ); + } + } + + /** + * @param $params + * @param bool $absolute + * + * @return string + */ + static function scriptUrlWithParams( $params, $absolute = false ) + { + $host = $absolute && org_glizy_Config::get('SEF_URL') == true ? GLZ_HOST.'/' : ''; + $params = preg_replace( '/^&amp;/', '', $params ); + return rtrim($host.self::$baseUrl.self::$requestUrl.self::$baseUrlParam.$params, '?&'); + } + + + /** + * @param string $route + * @param array $queryVars + * @param array $addParam + * + * @return mixed|string + */ + public static function makeURL($route='', $queryVars=array(), $addParam=array()) + { + if (is_object($queryVars)) { + $queryVars = method_exists($queryVars, 'getValuesAsArray') ? $queryVars->getValuesAsArray(): (array)$queryVars; + } + if ( org_glizy_Config::get('SEF_URL') == false) + { + return org_glizy_Routing::_makeURL_NOSEF( $route, $queryVars, $addParam ); + } + else + { + return org_glizy_Routing::_makeURL_SEF( $route, $queryVars, $addParam ); + } + } + + /** + * @param string $route + * @param array $queryVars + * @param array $addParam + * + * @return string + */ + public static function _makeURL_NOSEF($route='', $queryVars=array(), $addParam=array()) + { + $queryVars = array_merge( $queryVars, $addParam ); + if (!empty($route)) + { + $configArray = &org_glizy_Routing::_getValuesArray(); + /** @var $application org_glizy_application_Application */ + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + /** @var org_glizy_application_SiteMap $siteMap */ + $siteMap = &$application->getSiteMap(); + + // TODO + // controllare se il route richiesto esiste. + // + // TODO + // ci sono molte classi che usano lo stesso concetto di memorizzare + // i dati in un array statico + // conviene fare una classe base e estendere questa + // + $url = $configArray[strtolower($route)]['value']; + $pageId = 0; + preg_match_all("|\{(.*)\}|U", $url, $match, PREG_PATTERN_ORDER); + for($i=0; $i<count($match[0]); $i++) + { + $value = ''; + $key = ''; + $command = explode('=', $match[1][$i]); + $key = $command[0]; + switch ($command[0]) + { + case 'language': + $value = isset($queryVars['language']) ? $queryVars['language'] : $application->getLanguage(); + break; + case '*': + case 'currentMenu': + /** @var $page org_glizy_application_SiteMapNode */ + $page = &$application->getCurrentMenu(); + $value = $page->id; + $key = 'pageId'; + break; + case 'pageId': + // ricerca la pagina da linkare + if (count($command)>1) + { + if (is_numeric($command[1])) + { + $page = $siteMap->getNodeById($command[1]); + } + else + { + $page = $siteMap->getMenuByPageType($command[1]); + } + $value = $page->id; + } + else + { + $pageId = $queryVars[$command[0]]; + if ( empty( $pageId ) ) + { + /** @var $page org_glizy_application_SiteMapNode */ + $page = &$application->getCurrentMenu(); + $pageId = $page->id; + unset( $page ); + } + $value = $pageId; + } + + break; + case 'pageTitle': + continue; + break; + case 'value': + case 'integer': + $value = isset($queryVars[$command[1]]) ? $queryVars[$command[1]] : __Request::get( $command[1], '' ); + $key = $command[1]; + break; + case 'static': + $value = $command[2]; + $key = $command[1]; + break; + default: + $value = $command[1]; + break; + } + if (is_string($value) && $value == "" ) + { + continue; + } + + if ( !isset( $queryVars[ $key ] ) ) $queryVars[ $key ] = $value; + } + } + + $url = ''; + foreach($queryVars as $k=>$v) + { + $url .= (!empty($url) ? '&' : '').$k.'='.$v; + } + $url = org_glizy_Paths::get('PAGE_INDEX').'?'.$url; + return $url; + } + + /** + * @param string $route + * @param array $queryVars + * @param array $addParam + * + * @return mixed|string + */ + static function _makeURL_SEF($route='', $queryVars=array(), $addParam=array()) + { + if ( !isset( $addParam[ '__modal__' ] ) && __Request::exists( '__modal__' ) ) + { + $addParam[ '__modal__' ] = __Request::get( '__modal__' ); + } + + $url = ''; + if (!empty($route)) + { + $configArray = &org_glizy_Routing::_getValuesArray(); + /** @var org_glizy_application_Application $application */ + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + /** @var org_glizy_application_SiteMap $siteMap */ + $siteMap = &$application->getSiteMap(); + $isApplicationDB = $siteMap->getType() == 'db'; + + // TODO + // controllare se il route richiesto esiste. + // + // TODO + // ci sono molte classi che usano lo stesso concetto di memorizzare + // i dati in un array statico + // conviene fare una classe base e estendere questa + // + $routing = $configArray[strtolower($route)]; + if ( isset( $routing[0] ) ) + { + foreach( $routing as $v ) + { + if ( $queryVars[ $v[ 'keyName' ] ] == $v[ 'keyValue' ] || empty( $v[ 'keyValue' ] )) + { + $url = $v['value']; + break; + } + } + } + else + { + $url = $routing['value']; + } + + if ( strpos( $url, 'http://' ) !== false ) return $url; + + $pageId = 0; + preg_match_all("|\{(.*)\}|U", $url, $match, PREG_PATTERN_ORDER); + for($i=0; $i<count($match[0]); $i++) + { + $sanitize = true; + $value = ''; + $value2 = ''; + $command = explode('=', $match[1][$i]); + switch ($command[0]) + { + case 'language': + $value = isset($queryVars['language']) ? $queryVars['language'] : $application->getLanguage(); + break; + case '*': + case 'currentMenu': + $page = &$application->getCurrentMenu(); + $value = $page->id; + $value2 = $page->title; + unset( $page ); + break; + case 'currentMenuId': + $page = &$application->getCurrentMenu(); + $value = $page->id; + unset( $page ); + break; + case 'pageId': + // ricerca la pagina da linkare + if (count($command)>1) + { + if (is_numeric($command[1])) + { + $page = $siteMap->getNodeById($command[1]); + } + else + { + $page = $siteMap->getMenuByPageType($command[1]); + if ( is_null( $page ) ) + { + $module = org_glizy_Modules::getModule( $command[1] ); + if ( !is_null( $module ) && $module->pageType ) + { + $page = $siteMap->getMenuByPageType( $module->pageType ); + } + } + } + + $value = $page->id; + $value2 = $isApplicationDB ? $page->title : ''; + } + else + { + $pageId = @$queryVars[$command[0]]; + if ( empty( $pageId ) ) + { + $page = &$application->getCurrentMenu(); + $pageId = $page->id; + unset( $page ); + } + $value = $pageId; + $value2 = ''; + + } + + break; + case 'pageTitle': + // ricerca la pagina da linkare + if (!isset($queryVars['title'])) + { + // TODO + // non deve instanziare un nuovo menù altrimenti rilegge tutto dal db ogni volta + $page = $siteMap->getNodeById($pageId); + $value = $page->title; + } + else + { + $value = $queryVars['title']; + } + break; + case 'value': + case 'integer': + $value = isset($queryVars[$command[1]]) ? $queryVars[$command[1]] : __Request::get( $command[1], '' ); + break; + case 'static': + $value = ''; + break; + case 'config': + $sanitize = false; + $value = __Config::get($command[1]); + break; + default: + $value = $command[1]; + break; + } + if (is_string($value) && empty($value)) + { + $url = str_replace($match[0][$i].'/', '', $url); + $url = str_replace($match[0][$i], '', $url); + continue; + } + + if ($sanitize) { + $value = glz_sanitizeUrlTitle($value).($value2!='' ? '/' : ''); + $value2 = glz_sanitizeUrlTitle($value2); + } + + $url = str_replace($match[0][$i], $value.$value2, $url); + } + + // aggiunge in coda i valori della query string che non sono usati + if (is_array($addParam) && count($addParam)) + { + $url .= self::$baseUrlParam; + foreach($addParam as $k=>$v) + { + $url .= '&'.$k.'='.urlencode($v); + } + } else if (is_string($addParam)) { + $url .= $addParam; + } + } + + $url = !empty($url) ? $url : $route; + return !preg_match('/^(javascript:|http:|https:)/', $url) ? self::$baseUrl.$url : $url; + } + + function _compile() + { + $configArray = &org_glizy_Routing::_getValuesArray(); + + // compila il file di routing custom + $fileName = org_glizy_Paths::getRealPath('APPLICATION', 'config/routing_custom.xml'); + if ( file_exists( $fileName ) ) + { + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Routing'); + $compiledFileName = $compiler->verify($fileName); + include($compiledFileName); + } + + // compila il file di routing + $fileName = org_glizy_Paths::getRealPath('APPLICATION', 'config/routing.xml'); + if ( file_exists( $fileName ) ) + { + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Routing'); + $compiledFileName = $compiler->verify($fileName); + include($compiledFileName); + } + } + + public static function _parseUrl() + { + $newParser = __Config::get('glizy.routing.newParser'); + $scriptUrl = self::$requestUrl; + $scriptUrl = preg_replace('/(.*)\/?(\&.*$)/Ui', '$1', $scriptUrl); + $configArray = &org_glizy_Routing::_getValuesArray(); + $method = strtolower( @$_SERVER['REQUEST_METHOD'] ); + + foreach( $configArray as $k => $v ) + { + if ( !$v[ 'parseUrl' ] || ( $v[ 'method' ] != '' && $v[ 'method' ] != $method ) ) continue; + $urlPattern = $v[ 'urlPattern' ]; + + if (preg_match($urlPattern, $scriptUrl, $matches)) + { + $staticValues = unserialize( $v[ 'staticValues' ] ); + $urlValues = unserialize( $v[ 'urlValues' ] ); + $keys = array_keys($urlValues); + + if ($newParser) { + // il codice della versione precedente + // da problemi quando il valore del match contiene / + // non ricordo il motivo percui viene fatto l'explode del valore + // quindi per non rompere la compatibilità ho aggiunto nel config + // glizy.routing.newParser per abilitare questo nuovo parsing + for ($i=0; $i<count($keys); $i++) { + $urlValues[$keys[$i]] = $matches[$i+1]; + } + + } else { + for ($i=0; $i<count($keys); $i++) + { + $value = explode('/', $matches[$i+1]); + if ( $value[0] != "" ) + { + $urlValues[$keys[$i]] = $value[0]; + } + if (count($value)>1) + { + for ($j=1; $j<count($value); $j++, $j++) + { + if ($j+1<count($value)) $urlValues[$value[$j]] = $value[$j+1]; + } + } + } + } + + $urlValues[ '__params__' ] = array_values( $urlValues ); + $urlValues[ '__routingName__' ] = $k; + $urlValues[ '__routingPattern__' ] = $urlPattern; + + __Request::setFromArray( $urlValues ); + __Request::setFromArray( $staticValues, GLZ_REQUEST_ROUTING); + break; + } + } + } + + function &_getValuesArray() + { + // Array associativo (PATH_CODE=>PATH) + static $_configArray = null; + if (is_null($_configArray)) + { + $_configArray = array(); + org_glizy_Routing::_compile(); + } + return $_configArray; + } + + static function getAllAsArray() + { + return org_glizy_Routing::_getValuesArray(); + } + + static function destroy() + { + $configArray = &self::_getValuesArray(); + $configArray = null; + } +} + +// shortchut version +/** + * Class __Routing + */ +class __Routing extends org_glizy_Routing +{ +} diff --git a/src/core/classes/org/glizy/Session.php b/src/core/classes/org/glizy/Session.php new file mode 100755 index 0000000..ada91e7 --- /dev/null +++ b/src/core/classes/org/glizy/Session.php @@ -0,0 +1,224 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_Session +{ + static function init() + { + org_glizy_Session::start(); + } + + static function start() + { + if (!org_glizy_Session::isStarted()) + { + $sessionStore = org_glizy_Config::get('glizy.session.store'); + $prefix = org_glizy_Config::get('SESSION_PREFIX'); + $timeout = org_glizy_Config::get('SESSION_TIMEOUT'); + + if ($sessionStore) { + $storagePrefix = org_glizy_Config::get('glizy.session.store.prefix'); + if (!$storagePrefix) { + $storagePrefix = 'PHPSESSID'; + } + $store = org_glizy_ObjectFactory::createObject($sessionStore, $timeout, $storagePrefix.$prefix); + if (!$store) { + throw new Exception('Session Store don\'t exists: '.$sessionStore); + } + session_set_save_handler($store); + } + + if (!isset($_SESSION)) + { + org_glizy_Session::glz_session_start(); + } + if ( isset( $_SESSION[$prefix.'sessionLastAction'] ) && time() - $_SESSION[$prefix.'sessionLastAction'] > $timeout ) + { + $_SESSION=array(); + } + $_SESSION[$prefix.'sessionStarted'] = true; + $_SESSION[$prefix.'sessionLastAction'] = time(); + } + } + + function stop() + { + if (org_glizy_Session::isStarted()) + { + org_glizy_Session::set('sessionStarted', false); + session_write_close(); + } + } + + static function destroy() + { + if (org_glizy_Session::isStarted()) + { + org_glizy_Session::glz_session_start(); + $_SESSION=array(); + session_unset(); + session_destroy(); + } + } + + + /** + * @return bool + */ + static function isStarted() + { + $prefix = org_glizy_Config::get('SESSION_PREFIX'); + if ( isset($_GET['draft']) && $_GET['draft'] != '' && isset($_GET['sespre']) && $_GET['sespre'] != '' ) + { + $prefix = $_GET['sespre']; + org_glizy_Config::set('SESSION_PREFIX', $prefix); + } + if (!isset($_SESSION) || !isset($_SESSION[$prefix.'sessionStarted']) || $_SESSION[$prefix.'sessionStarted']!==true) return false; + else return true; + } + + + /** + * @param string $key + * @param mixed $defaultValue + * @param bool $readFromParams + * @param bool $writeDefaultValue + * @return mixed + */ + static function get($key, $defaultValue=NULL, $readFromParams=false, $writeDefaultValue=false) + { + org_glizy_Session::start(); + if (!array_key_exists(org_glizy_Config::get('SESSION_PREFIX').$key, $_SESSION)) + { + $value = ($readFromParams) ? org_glizy_Request::get($key, $defaultValue) : $defaultValue; + if ($writeDefaultValue) org_glizy_Session::set($key, $value); + } + else + { + $value = $_SESSION[org_glizy_Config::get('SESSION_PREFIX').$key]; + } + return $value; + } + + /** + * @param $key string + * @param $value mixed + */ + static function set($key, $value) + { + org_glizy_Session::start(); + $_SESSION[org_glizy_Config::get('SESSION_PREFIX').$key] = $value; + } + + + /** + * @param $key string + * @return bool + */ + static function exists($key) + { + org_glizy_Session::start(); + return isset($_SESSION[org_glizy_Config::get('SESSION_PREFIX').$key]); + } + + + /** + * @param $key string + */ + static function remove($key) + { + org_glizy_Session::start(); + $key = org_glizy_Config::get('SESSION_PREFIX').$key; + if (array_key_exists($key, $_SESSION)) + { + unset($_SESSION[$key]); + } + } + + static function removeKeysStartingWith($keyPrefix) + { + org_glizy_Session::start(); + $keyPrefix = org_glizy_Config::get('SESSION_PREFIX').$keyPrefix; + foreach ($_SESSION as $k => $v) { + if (substr($k, 0, strlen($keyPrefix)) == $keyPrefix) { + unset($_SESSION[$k]); + } + } + } + + static function removeAll() + { + org_glizy_Session::destroy(); + org_glizy_Session::start(); + } + + + static function getAllAsArray() + { + org_glizy_Session::start(); + return $_SESSION; + } + + /** + * @param $values array + */ + function setFromArray($values) + { + org_glizy_Session::start(); + foreach($values as $k=>$v) + { + $_SESSION[org_glizy_Config::get('SESSION_PREFIX').$k] = $v; + } + } + + /** + * @return string + */ + static function getSessionId() + { + return session_id(); + } + + + static function dump() + { + org_glizy_Session::start(); + var_dump($_SESSION); + } + + /** + * @param bool $init + * @return mixed + */ + function &_getValuesArray($init=false) + { + if (!$init) + { + org_glizy_Session::init(); + } + return $_SESSION; + } + + private static function glz_session_start() + { + $result = @session_start(); + if (!$result){ + session_regenerate_id(true); // replace the Session ID + session_start(); // restart the session (since previous start failed) + } + } +} + +// shortchut version +/** + * Class __Session + */ +class __Session extends org_glizy_Session +{ +} diff --git a/src/core/classes/org/glizy/SessionEx.php b/src/core/classes/org/glizy/SessionEx.php new file mode 100755 index 0000000..3929522 --- /dev/null +++ b/src/core/classes/org/glizy/SessionEx.php @@ -0,0 +1,164 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +define('GLZ_SESSION_EX_VOLATILE', 1); +define('GLZ_SESSION_EX_PERSISTENT', 2); +define('GLZ_SESSION_EX_PREFIX', 'session_ex'); + +class org_glizy_SessionEx extends GlizyObject +{ + var $_pageId; + var $_componentId; + var $_values; + var $_allValues; + + function __construct($componentId) + { + org_glizy_Session::init(); + + $this->_pageId = strtolower(org_glizy_ObjectValues::get('org.glizy.application', 'pageId')); + + $this->_componentId = $componentId; + $this->_allValues = org_glizy_Session::get(GLZ_SESSION_EX_PREFIX, array(), false, true); + + if (!array_key_exists($this->_pageId, $this->_allValues)) + { + $this->_allValues[$this->_pageId] = array(); + } + + foreach($this->_allValues as $k=>$v) + { + if ($k!=$this->_pageId) + { + foreach($v as $kk=>$vv) + { + if ($vv['type']!=GLZ_SESSION_EX_PERSISTENT) + { + unset($this->_allValues[$k][$kk]); + } + } + } + } + + $this->_values = &$this->_allValues[$this->_pageId]; + org_glizy_Session::set(GLZ_SESSION_EX_PREFIX, $this->_allValues); + + /* + da verificare + $url = org_glizy_Request::get( '__back__url__' ); + $userted = array(); + if ( !empty( $url ) ) + { + foreach($this->_values as $k=>$v) + { + $val = explode( "_", $k ); + if ( count( $val ) == 2 && !in_array( $val[1], $userted) ) + { + $userted[] = $val[1]; + if ( strpos( $url, $val[1].'='.$v['value'] ) === false ) + { + $url .= '&'.$val[1].'='.$v['value']; + } + } + } + org_glizy_Request::set( '__back__url__', $url ); + } + */ + } + + function get($name, $defaultValue=NULL, $readFromParams=false, $writeDefaultValue=false) + { + $origName = $name; + $name = $this->_componentId.'_'.$name; + if (!array_key_exists($name, $this->_values)) + { + // TODO + // verificare se � meglio aggiungere $this->_pageId quando si legge dai parametri della pagian + $value = ($readFromParams) ? org_glizy_Request::get($name, $defaultValue) : $defaultValue; + + if ($writeDefaultValue!==false) $this->set($origName, $value, GLZ_SESSION_EX_VOLATILE); + } + else + { + $value = ($readFromParams) ? org_glizy_Request::get($name, $this->_values[$name]['value']) : $this->_values[$name]['value']; + } + return $value; + } + + + function set($name, $value, $type=GLZ_SESSION_EX_VOLATILE) + { + $name = $this->_componentId.'_'.$name; + if (!array_key_exists($name, $this->_values)) + { + $tempValue = array(); + $tempValue['value'] = $value; + $tempValue['type'] = $type; + $this->_values[$name] = $tempValue; + } + else + { + $this->_values[$name]['value'] = $value; + } + + org_glizy_Session::set(GLZ_SESSION_EX_PREFIX, $this->_allValues); + } + + function exists($name) + { + $name = $this->_componentId.'_'.$name; + return isset($this->_values); + } + + + function remove($name) + { + $name = $this->_componentId.'_'.$name; + if (array_key_exists($name, $this->_values)) + { + unset($this->_values[$name]); + } + } + + + function removeAll() + { + $this->_values = array(); + } + + + function getAllAsArray() + { + $tempValues = array(); + foreach($this->_values as $k=>$v) + { + $tempValues[$k] = $v['value']; + } + return $tempValues; + } + + function setFromArray($values, $type=GLZ_SESSION_EX_VOLATILE) + { + foreach($values as $k=>$v) + { + $this->_values[$k] = array('value' => $v, 'type' => $type); + } + } + + function getSessionId() + { + return session_id(); + } + + + function dump() + { + var_dump($this->_values); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/application/Acl.php b/src/core/classes/org/glizy/application/Acl.php new file mode 100755 index 0000000..9161a12 --- /dev/null +++ b/src/core/classes/org/glizy/application/Acl.php @@ -0,0 +1,72 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_application_Acl extends GlizyObject +{ + protected $id; + protected $groupId; + protected $_acl; + protected $application; + + function __construct( $id, $groupId) + { + $this->id = $id; + $this->groupId = $groupId; + + $this->application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $fileName = org_glizy_Paths::getRealPath('APPLICATION', 'config/acl.xml'); + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Acl'); + $compiledFileName = $compiler->verify($fileName); + + include($compiledFileName); + $this->_acl = $acl; + } + + + function acl($name, $action, $default=NULL) + { + $action = strtolower($action); + $name = $name=='*' ? strtolower($this->application->getPageId()) : strtolower($name); + if (isset($this->_acl[$name])) + { + if (isset($this->_acl[$name]['rules'][$action])) + { + $rules = $this->_acl[$name]['rules'][$action]; + return in_array($this->groupId, $rules['allowGroups']) || in_array('*', $rules['allowGroups']) ? + true + : + in_array($this->id, $rules['allowUsers']) ? true : false; + } + else + { + return is_null($default) ? $this->_acl[$name]['default'] : $default; + } + } + else + { + return is_null($default) ? true : $default; + } + } + + function checkActions($action, $role) + { + for ($i=0; $i<count($role); $i++) + { + $action = $action==$role[$i][1] ? ($this->acl($role[$i][0], $role[$i][1]) ? $role[$i][2] : $role[$i][3]) : $action; + } + return $action; + } + + function invalidateAcl() + { + $fileName = org_glizy_Paths::getRealPath('APPLICATION', 'config/acl.xml'); + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Acl'); + $compiler->invalidate($fileName); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/application/AclAdvanced.php b/src/core/classes/org/glizy/application/AclAdvanced.php new file mode 100755 index 0000000..8339785 --- /dev/null +++ b/src/core/classes/org/glizy/application/AclAdvanced.php @@ -0,0 +1,74 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_application_AclAdvanced extends org_glizy_application_Acl +{ + protected $roles; + protected $aclMatrix; + + function __construct($id, $groupId) + { + parent::__construct($id, $groupId); + + $this->roles = array(); + $this->aclMatrix = array(); + + if ($id) { + // TODO ora la matrice è memorizzata nella sessione + // e non può essere invalidata dal gestore dei ruoli per tutti gli utenti + $roles = org_glizy_Session::exists('glizy.roles'); + if (!empty($roles)) { + $this->roles = org_glizy_Session::get('glizy.roles'); + $this->aclMatrix = org_glizy_Session::get('glizy.aclMatrix'); + } else { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizy.models.Role', 'getPermissions', array('params' => array('id' => $id, 'groupId' => $groupId))); + + foreach ($it as $ar) { + // se il ruolo non è attivo passa al prossimo + if (!$ar->role_active) continue; + + // se il ruolo non è stato ancora processato + if (!$this->roles[$ar->role_id]) { + $this->roles[$ar->role_id] = true; + $permissions = unserialize($ar->role_permissions); + // unione delle matrici dei permessi + foreach ($permissions as $name => $actions) { + foreach ((array)$actions as $action => $value) { + $this->aclMatrix[strtolower($name)][$action] |= $value; + } + } + } + } + + org_glizy_Session::set('glizy.roles', $this->roles); + org_glizy_Session::set('glizy.aclMatrix', $this->aclMatrix); + } + } + } + + function acl($name, $action, $default=null) + { + $name = $name=='*' ? strtolower($this->application->getPageId()) : strtolower($name); + return $this->aclMatrix[$name]['all'] || $this->aclMatrix[$name][$action]; + } + + function inRole($roleId) + { + return $this->roles[$roleId]; + } + + function getRoles() + { + return array_keys($this->roles); + } + + function invalidateAcl() + { + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/application/Application.php b/src/core/classes/org/glizy/application/Application.php new file mode 100755 index 0000000..9a2e5c9 --- /dev/null +++ b/src/core/classes/org/glizy/application/Application.php @@ -0,0 +1,758 @@ +<?php +/** + * Application class. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_application_Application extends GlizyObject +{ + var $_pathCore = ''; + var $_pathApplication = ''; + var $_pageId = 0; + var $_pageType = ''; + var $outputMode = 'html'; + /** @var org_glizy_application_SiteMapSimple $siteMap */ + var $siteMap = NULL; + /** @var org_glizy_application_SiteMapNode $siteMapMenu */ + var $siteMapMenu = NULL; + /** @var org_glizy_components_ComponentContainer $_rootComponent */ + var $_rootComponent = NULL; + /** @var org_glizy_application_User $_user */ + var $_user = NULL; + var $_language = ''; + var $_languageId = 0; + var $_ajaxMode = false; + var $_logObj = NULL; + var $_configHost; + protected $contentType = 'text/html'; + + /** + * @param string $pathApplication + * @param string $pathCore + * @param string $configHost + */ + function __construct($pathApplication='', $pathCore='', $configHost='') + { + if (empty($pathApplication)) + { + new org_glizy_Exception(array('[%s] %s', $this->getClassName(), GLZ_ERR_EMPTY_APP_PATH)); + } + + org_glizy_ObjectValues::setByReference('org.glizy', 'application', $this); + $this->_pathApplication = $pathApplication; + $this->_pathCore = $pathCore; + $this->_configHost = $configHost; + $this->addEventListener(GLZ_EVT_USERLOGIN, $this); + $this->_init(); + } + + + function run() + { + $this->log( "Run application", GLZ_LOG_SYSTEM ); + if (file_exists(org_glizy_Paths::get('APPLICATION_STARTUP'))) + { + // if the startup folder is defined all files are included + glz_require_once_dir(org_glizy_Paths::get('APPLICATION_STARTUP')); + } + + glz_defineBaseHost(); + $this->_initSiteMap(); + $this->_initRequest(); + + org_glizy_ObjectValues::set('org.glizy.og', 'url', GLZ_HOST.'/go/'.__Request::get('__url__') ); + glz_require_once_dir(org_glizy_Paths::getRealPath('APPLICATION_CLASSES')); + + $this->_startProcess(); + + if (file_exists(org_glizy_Paths::get('APPLICATION_SHUTDOWN'))) + { + // if the shutdown folder is defined all files are included + glz_require_once_dir(org_glizy_Paths::get('APPLICATION_SHUTDOWN')); + } + } + + function runAjax() + { + $this->log( "Run ajax application", GLZ_LOG_SYSTEM ); + org_glizy_Request::$translateInfo = false; + org_glizy_Request::$skipDecode = __Config::get( 'AJAX_SKIP_DECODE' ); + + $this->_ajaxMode = true; + $this->run(); + } + + function runSoft() + { + $this->log( "Run application (soft mode)", GLZ_LOG_SYSTEM ); + + if (file_exists(org_glizy_Paths::get('APPLICATION_STARTUP'))) + { + // if the startup folder is defined all files are included + glz_require_once_dir(org_glizy_Paths::get('APPLICATION_STARTUP')); + } + + glz_defineBaseHost(); + $this->_initSiteMap(); + $this->_initRequest(); + + if (file_exists(org_glizy_Paths::get('APPLICATION_SHUTDOWN'))) + { + // if the shutdown folder is defined all files are included + glz_require_once_dir(org_glizy_Paths::get('APPLICATION_SHUTDOWN')); + } + } + + function stop() + { + org_glizy_Paths::destroy(); + org_glizy_Config::destroy(); + org_glizy_Request::destroy(); + org_glizy_Routing::destroy(); + org_glizy_ObjectValues::removeAll(); + } + + function _init() + { + // inizializzazione delle classi + // classe statica per la gestione dei path + org_glizy_Paths::init($this->_pathApplication, $this->_pathCore); + + // legge i parametri di configurazione + org_glizy_Config::init( $this->_configHost ); + + + $sessionPrefix = org_glizy_Config::get('SESSION_PREFIX'); + if (empty($sessionPrefix)) + { + // se non è stato specificato un prefisso per la sessione + // viene usato il nome dell'applicazione + org_glizy_Config::set('SESSION_PREFIX', str_replace(array('.', ' ', '/'), '', $this->_pathApplication).'_'); + } + + // inizializzazione della sessione + __Session::start(); + if (org_glizy_config::get('LOG_FILE')!='') + { + if ( org_glizy_config::get('LOG_FILE') != "firebug" ) + { + $this->_logObj = org_glizy_log_LogFactory::create('File', org_glizy_Paths::get('APPLICATION').'/'.org_glizy_config::get('LOG_FILE'), array(), org_glizy_config::get('LOG_LEVEL')); + } + else + { + $this->_logObj = org_glizy_log_LogFactory::create('FireBug', array(), org_glizy_config::get('LOG_LEVEL')); + } + $this->log( "Start application", GLZ_LOG_SYSTEM ); + } + + if (__Config::get ( 'glizy.exception.log.format' )=='elasticsearch') { + org_glizy_log_LogFactory::create('ElasticSearch', array(), 0); // Questo serve per poter istanziare la classe in Exception.php (gruppo 0 non logga nulla) + } + + $this->login(); + $this->_initLanguage(); + } + + function _initRequest() + { + org_glizy_Routing::init(); + org_glizy_Routing::_parseUrl(); + org_glizy_Request::init(); + if ($this->siteMap) { + // gli alias del SiteMap devono essere risolti dopo il routing + // perché utilizza il Routing per generare l'URL + $this->siteMap->resolveAlias(); + } + } + + + function _initLanguage() + { + $this->log( "initLanguage", GLZ_LOG_SYSTEM ); + // inizializza la lingua + $this->_language = org_glizy_Config::get('DEFAULT_LANGUAGE'); + $this->_languageId = org_glizy_Config::get('DEFAULT_LANGUAGE_ID'); + org_glizy_ObjectValues::set('org.glizy', 'languageId', $this->_languageId); + $this->_loadLocale(); + } + + /** + * @param bool $forceReload + */ + function _initSiteMap($forceReload=false) + { + $this->log( "initSiteMap", GLZ_LOG_SYSTEM ); + $this->siteMap = &org_glizy_ObjectFactory::createObject('org.glizy.application.SiteMapSimple'); + $this->siteMap->getSiteArray($forceReload); + } + + function _readPageId() + { + $this->log( "readPageId", GLZ_LOG_SYSTEM ); + // legge il pageId della pagina da visualizzare + $this->_pageId = org_glizy_Request::get('pageId', NULL); + if (empty($this->_pageId)) + { + $this->_pageId = org_glizy_Config::get('REMEMBER_PAGEID') ? org_glizy_Session::get('glizy.pageId', org_glizy_Config::get('START_PAGE')) : org_glizy_Config::get('START_PAGE'); + } + + if (org_glizy_Config::get('REMEMBER_PAGEID')) + { + org_glizy_Session::set('glizy.pageId', $this->_pageId); + } + + if (!is_numeric($this->_pageId) && ( $this->getClassName()=='org_glizycms_core_application_application') ) + { + $this->siteMapMenu = &$this->siteMap->getMenuByPageType($this->_pageId); + $this->_pageId = $this->siteMapMenu->id; + } + else + { + $this->siteMapMenu = &$this->siteMap->getNodeById($this->_pageId); + } + + if (!is_object($this->siteMapMenu) || !$this->siteMapMenu->isVisible) + { + $report = array(); + $report['Request'] = var_export(__Request::getAllAsArray(), true); + $report['_SERVER'] = var_export($_SERVER, true); + $this->log( $report, GLZ_LOG_SYSTEM, 'glizy.404' ); + + if (!$this->getCurrentUser()->acl($this->siteMapMenu->id, "visible")) { + org_glizy_helpers_Navigation::gotoUrl( __Link::makeUrl( 'link', array( 'pageId' => __Config::get('START_PAGE')))); + } + $error404Page = __Config::get( 'ERROR_404'); + if ( !empty( $error404Page ) ) + { + org_glizy_helpers_Navigation::gotoUrl( __Link::makeUrl( 'link', array( 'pageId' => $error404Page ) ) ); + } + new org_glizy_Exception(__T('GLZ_ERR_404').'</br>'.__Request::get('pageId'), GLZ_E_404); + } + + if (!empty($this->siteMapMenu->select)) { + if ($this->siteMapMenu->select=='*') { + $menu = $this->siteMapMenu->firstChild(true); + } else { + $menu = $this->siteMap->getNodeById($this->siteMapMenu->select); + } + org_glizy_helpers_Navigation::gotoUrl( __Link::makeUrl( 'link', array( 'pageId' => $menu->id ) ) ); + } + } + + /** + * @param bool $readPageId + */ + function _startProcess($readPageId=true) + { + $this->log( "startProcess", GLZ_LOG_SYSTEM ); + if ( $this->_logObj ) + { + $this->log( array( 'Request' => __Request::getAllAsArray() ), GLZ_LOG_SYSTEM ); + } + + if ($readPageId) { + $evt = array('type' => GLZ_EVT_BEFORE_CREATE_PAGE); + $this->dispatchEvent($evt); + $this->_readPageId(); + } + + org_glizy_ObjectValues::set('org.glizy.application', 'pageId', $this->_pageId); + $this->_pageType = $this->siteMapMenu->pageType; + + if (__Request::exists('__middleware__')) { + $middlewareObj = org_glizy_ObjectFactory::createObject(__Request::get('__middleware__')); + // verify the cache before page rendering + // this type of cache is available only for Static Page + if ($middlewareObj) { + $middlewareObj->beforeProcess($this->_pageId, $this->_pageType); + } + } + + org_glizy_ObjectFactory::createPage( $this, $this->_pageType, null, array( 'pathTemplate' => org_glizy_Paths::get('APPLICATION_TEMPLATE') ) ); + + if (!is_null($this->_rootComponent)) + { + if (!$this->_ajaxMode) + { + // serve per resettare lo stato del sessionEx ad ogni caricamento delle pagine + // altrimenti gli stati vecchi non vengono cancellati + // quando c'è un cambio di pagina e SessionEx non è usato + org_glizy_ObjectFactory::createObject('org.glizy.SessionEx', ''); + + $this->_rootComponent->resetDoLater(); + $this->_rootComponent->init(); + $this->_rootComponent->execDoLater(); + + $this->log( "Process components", GLZ_LOG_SYSTEM ); + $this->_rootComponent->resetDoLater(); + + $evt = array('type' => GLZ_EVT_START_PROCESS); + $this->dispatchEvent($evt); + + if (method_exists($this, 'process_onStart')) $this->process_onStart(); + $this->_rootComponent->process(); + if (method_exists($this, 'process_onEnd')) $this->process_onEnd(); + $this->_rootComponent->execDoLater(); + + $evt = array('type' => GLZ_EVT_END_PROCESS); + $this->dispatchEvent($evt); + + + // check if enable the PDF output + if ( $this->getCurrentMenu()->printPdf ) + { + $pdfPage = org_glizy_Paths::getRealPath('APPLICATION_TEMPLATE', 'pdf.php' ); + if ( $pdfPage !== false ) + { + if ( __Request::get( 'printPdf', '0' ) ) + { + org_glizy_ObjectValues::set( 'org.glizy.application', 'pdfMode', __Request::get( 'printPdf', '0' ) == '1' ); + } + } + else + { + $this->getCurrentMenu()->printPdf = false; + } + } + + $evt = array('type' => GLZ_EVT_START_RENDER); + $this->dispatchEvent($evt); + $this->_rootComponent->resetDoLater(); + if (method_exists($this, 'render_onStart')) $this->render_onStart(); + + $this->addJScoreLibraries(); + + $output = $this->_rootComponent->render(); + + if (method_exists($this, 'render_onEnd')) $this->render_onEnd(); + $this->_rootComponent->execDoLater(); + + $evt = array('type' => GLZ_EVT_END_RENDER); + $this->dispatchEvent($evt); + + $headerErrorCode = __Request::get( 'glizyHeaderCode', '' ); + if ( $headerErrorCode == '404' ) + { + header( "HTTP/1.1 404 Not Found" ); + header( "Status: 404 Not Found" ); + } + header("Content-Type: ".$this->contentType."; charset=".__Config::get('CHARSET')); + + if ($middlewareObj) { + // verify the cache after content rendering + $middlewareObj->afterRender($output); + } + + echo $output; + } + else + { + $this->startProcessAjax(); + } + } + else + { + // TODO + // visualizzare errore + } + } + + private function startProcessAjax() + { + header('Cache-Control: no-cache'); + header('Pragma: no-cache'); + header('Expires: -1'); + + $this->_rootComponent->resetDoLater(); + $this->_rootComponent->init(); + $this->_rootComponent->execDoLater(); + + $evt = array('type' => GLZ_EVT_START_PROCESS); + $this->dispatchEvent($evt); + + $ajaxTarget = org_glizy_Request::get('ajaxTarget'); + $targetComponent = &$this->_rootComponent->getComponentById($ajaxTarget); + if (is_null($targetComponent)) { + // prima prova a creare i figli in modo ritardato + // questo è usato nella gestione degli stati + $this->_rootComponent->deferredChildCreation(true); + $targetComponent = &$this->_rootComponent->getComponentById($ajaxTarget); + + + // se il targetComponent è ancora nullo + // prova a lanciare il process di tutti i figli + if (is_null($targetComponent)) { + $this->_rootComponent->process(); + $targetComponent = &$this->_rootComponent->getComponentById($ajaxTarget); + if (is_null($targetComponent)) { + return false; + } + } + } + + $ajaxMethod = __Request::get('ajaxMethod', 'process_ajax'); + if (method_exists($targetComponent, $ajaxMethod)) { + org_glizy_Request::remove('pageId'); + org_glizy_Request::remove('ajaxTarget'); + $result = $targetComponent->{$ajaxMethod}(); + } else { + $result = $this->processAjaxCallController($targetComponent); + } + + if (!$targetComponent->controllerDirectOutput() && !is_array($result) && !is_object($result)) $result = array('status'=> ($result===true ? 'success' : 'error')); + if ( is_array($result) && isset( $result['html'] ) ) { + header("Content-Type: ".$this->contentType."; charset=".__Config::get('CHARSET')); + echo $result['html']; + } else { + header("Content-Type: application/json; charset=utf-8"); + echo json_encode( $result ); + } + return true; + } + + /** + * @param org_glizy_components_Component $targetComponent + * + * @return array + */ + private function processAjaxCallController($targetComponent) + { + if ( __Request::exists('controllerName')) { + $targetComponent->setAttribute('controllerName', __Request::get('controllerName')); + } + $result = array( 'status' => false ); + $r = $targetComponent->callController(); + if ($r !== null && $r !== false) + { + if ( $targetComponent->controllerDirectOutput() ) return $r; + + $result['status'] = true; + if ( is_array( $r ) && isset( $r[ 'error' ] ) ) + { + $result['status'] = false; + $result['error'] = $r[ 'error' ]; + return $result; + } + + $outputFormatInHtml = false; + $html = ''; + + if ( is_array( $r ) && isset( $r[ 'sendOutput' ] ) ) + { + // controlla se c'è renderizzare dei componenti da mandare all'output + __Request::set('action', isset($r['sendOutputState']) ? $r['sendOutputState'] : ''); + $outputFormatInHtml = isset( $r[ 'sendOutputFormat' ] ) && $r[ 'sendOutputFormat' ] == 'html'; + $this->_rootComponent->process(); + + $componentsId = $r[ 'sendOutput' ]; + unset( $r[ 'sendOutput' ] ); + unset( $r[ 'sendOutputState' ] ); + if ( !is_array( $componentsId ) ) { + $componentsId = array( $componentsId ); + } + + foreach( $componentsId as $id ) { + $c = $this->_rootComponent->getComponentById( $id ); + if ( is_object( $c ) ) { + $this->_rootComponent->_output = array(); + $c->render(); + + //$r[ 'sendOutput' ][ $id ] = $this->_output[ 0 ][ 'code' ]; + $r[ $id ] = ''; + foreach( $this->_rootComponent->_output as $o ) { + if ( strpos($o['editableRegion'], '__') !== false ) continue; + $r[ $id ] .= $o[ 'code' ]; + $html .= $o[ 'code' ]; + } + } + } + } + + if ( $outputFormatInHtml ) { + $result['html'] = $html; + } else { + $result['result'] = $r; + } + } + return $result; + } + + /** + * @param org_glizy_components_Component $component + */ + function addChild(&$component) + { + $this->_rootComponent = &$component; + } + + /** + * @return org_glizy_components_Component + */ + function &getRootComponent() + { + return $this->_rootComponent; + } + + /** + * @return string + */ + function getOutputMode() + { + return $this->outputMode; + } + + /** + * @return string + */ + function getPageId() + { + return strtolower( $this->_pageId ); + } + + /** + * @param string $id + */ + function setPageId($id) + { + $this->_pageId = $id; + $this->siteMapMenu = &$this->siteMap->getNodeById($this->_pageId); + } + + /** + * @return string + */ + function getPageType() + { + return $this->_pageType; + } + + /** + * @return org_glizy_application_SiteMapNode + */ + function &getCurrentMenu() + { + return $this->siteMapMenu; + } + + /** + * @return org_glizy_application_User + */ + function &getCurrentUser() + { + $user = &org_glizy_ObjectValues::get('org.glizy', 'user'); + return $user; + } + + /** + * @return org_glizy_application_SiteMapSimple + */ + function &getSiteMap() + { + return $this->siteMap; + } + + /** + * @return int + */ + function getLanguageId() + { + return $this->_languageId; + } + + /** + * @param int $value + */ + function setLanguageId($value) + { + $this->_languageId = $value; + org_glizy_ObjectValues::set('org.glizy', 'languageId', $this->_languageId); + } + + /** + * @return string + */ + function getLanguage() + { + return strtolower($this->_language); + } + + /** + * @param $value + */ + function setLanguage($value) + { + $value = strtolower($value); + if ($this->_language != $value) + { + $this->_language = $value; + $this->_loadLocale(); + } + } + + function _loadLocale() + { + // importa i file di localizzazione + if (file_exists(org_glizy_Paths::getRealPath('CORE_CLASSES').'org/glizy/locale/'.$this->getLanguage().'.php')) + { + require(org_glizy_Paths::getRealPath('CORE_CLASSES').'org/glizy/locale/'.$this->getLanguage().'.php'); + } + else + { + require(org_glizy_Paths::getRealPath('CORE_CLASSES').'org/glizy/locale/en.php'); + } + } + + function addJScoreLibraries() + { + if (!org_glizy_ObjectValues::get('org.glizy.JS.Core', 'add', false) && __Config::get( 'GLIZY_ADD_CORE_JS' ) ) + { + org_glizy_ObjectValues::set('org.glizy.JS.Core', 'add', true); + $this->addJSLibCore(); + if (__Config::get('DEBUG')) { + $this->_rootComponent->addOutputCode(org_glizy_helpers_JS::linkCoreJSfile('dejavu/strict/dejavu.js?v='.GLZ_CORE_VERSION), 'head'); + } else { + $this->_rootComponent->addOutputCode(org_glizy_helpers_JS::linkCoreJSfile('dejavu/loose/dejavu.min.js?v='.GLZ_CORE_VERSION), 'head'); + } + $this->_rootComponent->addOutputCode(org_glizy_helpers_JS::linkCoreJSfile('Glizy.js?v='.GLZ_CORE_VERSION), 'head'); + $filename = $this->getLanguage().'.js'; + if(!file_exists(__DIR__."/../../../../static/js/locale/".$filename)) { + $filename = 'en.js'; + } + $this->_rootComponent->addOutputCode(org_glizy_helpers_JS::linkCoreJSfile($filename, 'locale/'), 'head'); + } + } + + function addJSLibCore() + { + if (!org_glizy_ObjectValues::get('org.glizy.JS.lib', 'add', false) && __Config::get( 'GLIZY_ADD_JS_LIB' ) ) + { + org_glizy_ObjectValues::set('org.glizy.JS.lib', 'add', true); + if ( __Config::get( 'GLIZY_ADD_JQUERY_JS' ) ) + { + $this->_rootComponent->addOutputCode(org_glizy_helpers_JS::linkStaticJSfile( 'jquery/' . __Config::get('GLIZY_JQUERY' ) ), 'head'); + if ( __Config::get( 'GLIZY_ADD_JQUERYUI_JS' ) ) + { + $this->_rootComponent->addOutputCode( org_glizy_helpers_JS::linkStaticJSfile( 'jquery/jquery-ui/' . __Config::get('GLIZY_JQUERYUI' ) ), 'head'); + $this->_rootComponent->addOutputCode( org_glizy_helpers_CSS::linkStaticCSSfile( 'jquery/jquery-ui/' . __Config::get('GLIZY_JQUERYUI_THEME' ) ), 'head'); + } + } + } + } + + function addLightboxJsCode() + { + if (!org_glizy_ObjectValues::get('org.glizy.JS.Lightbox', 'add', false) && __Config::get( 'GLIZY_ADD_JS_LIB' ) ) + { + org_glizy_ObjectValues::set('org.glizy.JS.Lightbox', 'add', true); + $this->addJSLibCore(); + + $this->_rootComponent->addOutputCode( org_glizy_helpers_CSS::linkStaticCSSfile('jquery/colorbox/glizy/colorbox.css' ), 'head' ); + $this->_rootComponent->addOutputCode( org_glizy_helpers_JS::linkStaticJSfile('jquery/colorbox/jquery.colorbox-min.js' ), 'head' ); + $this->_rootComponent->addOutputCode(org_glizy_helpers_JS::JScode( 'jQuery(document).ready(function() { jQuery("a.js-lightbox-image").colorbox({ photo:true, slideshow:true, slideshowSpeed: Glizy.slideShowSpeed, current: "{current} di {total}", + previous: "'.__T('GLZ_PREVIOUS').'", + next: "'.__T('GLZ_NEXT').'", + close: "'.__T('GLZ_COLSE').'", + slideshowStart: "'.__T('GLZ_SLIDESHOW_START').'", + slideshowStop: "'.__T('GLZ_SLIDESHOW_STOP').'" }) });' ), 'head'); + + $this->_rootComponent->addOutputCode(org_glizy_helpers_JS::JScode( 'jQuery(document).ready(function() { jQuery("a.js-lightbox-inline").colorbox({inline:true, title: false})});' ), 'head'); + } + } + + function addZoomJsCode() + { + if (!org_glizy_ObjectValues::get('org.glizy.JS.Zoom', 'add', false) && __Config::get( 'GLIZY_ADD_JS_LIB' ) ) + { + org_glizy_ObjectValues::set('org.glizy.JS.Zoom', 'add', true); + $this->addJSLibCore(); + $this->_rootComponent->addOutputCode( org_glizy_helpers_JS::linkStaticJSfile('OpenSeadragon/OpenSeadragon.js' ), 'head' ); + $this->_rootComponent->addOutputCode( '<div id="zoomContainer" data-cache="'.__Paths::get('CACHE').'"></div>' ); + } + } + + /** + * @param string $formName + */ + function addValidateJsCode( $formName=null ) + { + if (!__Config::get('GLIZY_ADD_VALIDATE_JS')) return; + if (!org_glizy_ObjectValues::get('org.glizy.JS.Validate', 'add', false) && __Config::get( 'GLIZY_ADD_JS_LIB' ) ) + { + // Validate + org_glizy_ObjectValues::set('org.glizy.JS.Validate', 'add', true); + $this->addJSLibCore(); + + if ( file_exists( org_glizy_Paths::get('STATIC_DIR').'jquery/jquery.validationEngine/jquery.validationEngine-'.$this->getLanguage().'.js' ) ) + { + $this->_rootComponent->addOutputCode(org_glizy_helpers_JS::linkStaticJSfile( 'jquery/jquery.validationEngine/jquery.validationEngine-'.$this->getLanguage().'.js' ), 'head'); + }else { + $this->_rootComponent->addOutputCode(org_glizy_helpers_JS::linkStaticJSfile( 'jquery/jquery.validationEngine/jquery.validationEngine-en.js' ), 'head'); + } + $this->_rootComponent->addOutputCode( org_glizy_helpers_JS::linkStaticJSfile( 'jquery/jquery.validationEngine/jquery.validationEngine.js' ), 'head'); + $this->_rootComponent->addOutputCode( org_glizy_helpers_CSS::linkStaticCSSfile( 'jquery/jquery.validationEngine/validationEngine.jquery.css' ), 'head'); + } + + if ( !is_null( $formName ) && __Config::get( 'GLIZY_ADD_JS_LIB' ) ) + { + $this->_rootComponent->addOutputCode(org_glizy_helpers_JS::JScode( 'jQuery(document).ready(function() { $("#'.$formName.'").validationEngine( "attach", { validationEventTrigger: "none", scroll: false, showAllErrors: false } ); });' ), 'head'); + +// $this->_rootComponent->addOutputCode(org_glizy_helpers_JS::JScode( '$(document).ready(function() { $("#'.$formName.'").validationEngine(); });' ), 'head'); + } + } + + /* events listener */ + function login() + { + $this->log( "login", GLZ_LOG_SYSTEM ); + if (org_glizy_Session::get('glizy.userLogged')) + { + $this->log( "user is logged", GLZ_LOG_SYSTEM ); + $user = org_glizy_Session::get('glizy.user'); + + // crea l'utente + $this->_user = &org_glizy_ObjectFactory::createObject('org.glizy.application.User', $user); + org_glizy_ObjectValues::setByReference('org.glizy', 'user', $this->_user); + org_glizy_ObjectValues::set('org.glizy', 'userId', $this->_user->id); + + if (org_glizy_Config::get('USER_LOG')) + { + $this->log( "log user access", GLZ_LOG_SYSTEM ); + $arLog = &org_glizy_ObjectFactory::createModel('org.glizy.models.UserLog'); + $arLog->load($user['logId']); + $arLog->userlog_FK_user_id = $user['id']; + $arLog->save(); + } + } + else + { + $this->log( "user not logged", GLZ_LOG_SYSTEM ); + // utente finto + $user = 0; + // crea l'utente + $this->_user = &org_glizy_ObjectFactory::createObject('org.glizy.application.User', $user); + org_glizy_ObjectValues::setByReference('org.glizy', 'user', $this->_user); + org_glizy_ObjectValues::set('org.glizy', 'userId', 0); + } + } + + /** + * @return bool + */ + function isAdmin() + { + return false; + } + + /** + * @return bool + */ + function canViewPage() + { + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/application/ApplicationXML.php b/src/core/classes/org/glizy/application/ApplicationXML.php new file mode 100755 index 0000000..56868a3 --- /dev/null +++ b/src/core/classes/org/glizy/application/ApplicationXML.php @@ -0,0 +1,19 @@ +<?php +/** + * Application class. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_application_ApplicationXML extends org_glizy_application_Application +{ + function _initSiteMap($forceReload=false) + { + $this->siteMap = &org_glizy_ObjectFactory::createObject('org.glizy.application.SiteMapXML'); + $this->siteMap->getSiteArray($forceReload); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/application/MessageStack.php b/src/core/classes/org/glizy/application/MessageStack.php new file mode 100755 index 0000000..57d4048 --- /dev/null +++ b/src/core/classes/org/glizy/application/MessageStack.php @@ -0,0 +1,58 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +define( 'GLZ_MESSAGE_SUCCESS', 'SUCCESS' ); +define( 'GLZ_MESSAGE_FAULT', 'FAULT' ); +define( 'GLZ_MESSAGE_ERROR', 'ERROR' ); + +class org_glizy_application_MessageStack +{ + static function add($message, $type=GLZ_MESSAGE_SUCCESS) + { + $messages = &org_glizy_Session::get('org.glizy.application.MessageStack', array()); + if (!isset($messages[$type])) + { + $messages[$type] = array(); + } + $messages[$type][] = $message; + org_glizy_Session::set('org.glizy.application.MessageStack', $messages ); + } + + static function get($type=NULL) + { + $messages = &org_glizy_Session::get('org.glizy.application.MessageStack', array()); + if (is_null($type) || $type=='ALL') + { + $tempMessages = array(); + foreach( $messages as $k=>$v ) + { + $tempMessages = array_merge( $tempMessages, $v ); + } + return $tempMessages; + } + else + { + return isset($messages[$type]) ? $messages[$type] : array(); + } + } + + static function reset($type=NULL) + { + $messages = &org_glizy_Session::get('org.glizy.application.MessageStack', array()); + if (is_null($type) || $type=='ALL') + { + $messages = array(); + } + else + { + $messages[$type] = array(); + } + org_glizy_Session::set('org.glizy.application.MessageStack', $messages ); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/application/SiteMap.php b/src/core/classes/org/glizy/application/SiteMap.php new file mode 100755 index 0000000..317b4ff --- /dev/null +++ b/src/core/classes/org/glizy/application/SiteMap.php @@ -0,0 +1,251 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_application_SiteMap extends GlizyObject +{ + var $_siteMapArray; + var $_pageTypeMap; + var $_type = ''; + var $_user = ''; + + private $isAdmin; + private $hidePrivatePage; + + function __construct() + { + $this->init(); + } + + function init() + { + $this->_siteMapArray = array(); + $this->_pageTypeMap = array(); + $application = & org_glizy_ObjectValues::get('org.glizy', 'application'); + $this->_user = &$application->getCurrentUser(); + $this->isAdmin = $application->isAdmin(); + $this->hidePrivatePage = org_glizy_Config::get( 'HIDE_PRIVATE_PAGE', true ); + } + + function getType() + { + return $this->_type; + } + + function loadTree($forceReload=false) + { + } + + function numPages() + { + return count($this->_siteMapArray); + } + + + function _makeChilds() + { + // ripassa l'array creando i link parente creando l'aray per mappare pageId con ID + $menuIdToSort = array(); + $IDs = array_keys($this->_siteMapArray); + foreach ($IDs as $key) + { + $menuNode = &$this->_siteMapArray[$key]; + $parentId = $menuNode['parentId']; + + if ( !is_bool( $menuNode['isVisible'] ) ) + { + if (preg_match("/\{php\:.*\}/i", $menuNode['isVisible'] ) ) + { + $phpcode = org_glizy_helpers_PhpScript::parse( $menuNode['isVisible'] ); + $menuNode['isVisible'] = eval($phpcode)==1 ? true : false; + } + else + { + $menuNode['isVisible'] = $menuNode['isVisible']==='false' ? false : true; + } + } + + if ( !$this->isAdmin && $menuNode['isLocked'] && !$this->_user->isLogged() && $this->hidePrivatePage ) { + $menuNode['isVisible'] = false; + } + + $this->_pageTypeMap[strtolower($menuNode['pageType'])] = &$menuNode; + if (($this->_type=='db' && $parentId==0) || ($this->_type=='xml' && $parentId=='') || ($this->_type=='' && $parentId===0)) continue; + + if (isset($this->_siteMapArray[$parentId])) + { + $menuNodeParent = &$this->_siteMapArray[$parentId]; + + // aggiunge il riferimento come childNode + $menuNodeParent['childNodes'][] = $menuNode['id']; + $menuNode['depth'] = $menuNodeParent['depth']+1; + } + else + { + // cancella il menu + // perché è orfano + unset($this->_siteMapArray[$key]); + // TODO cancellare anche i figli in modo ricorsivo + } + + if ($menuNode['sortChild']) { + $menuIdToSort[] = $key; + } + } + + // order the menus + foreach($menuIdToSort as $key) { + $menuNode = &$this->_siteMapArray[$key]; + $tempNode = array(); + foreach($menuNode['childNodes'] as $childId) { + $tempNode[$childId] = &$this->_siteMapArray[$childId]; + } + usort($tempNode, function($a, $b) { + if (!$a['title'] && !$b['title']) { + return 0; + } else if (!$a['title']) { + return 1; + } else if (!$b['title']) { + return -1; + } else { + return strnatcasecmp($a['title'], $b['title']); + } + }); + $menuNode['childNodes'] = array(); + foreach($tempNode as $node) { + $menuNode['childNodes'][] = $node['id']; + } + } + + $this->_makeDepth($IDs[0], 0); + } + + function _makeDepth($id, $parentDepth) + { + if ($id) { + $menu = &$this->_siteMapArray[$id]; + $menu['depth'] = $parentDepth+1; + foreach($menu['childNodes'] as $m) + { + $this->_makeDepth($m, $parentDepth+1); + } + } + } + + public function resolveAlias() + { + } + + /* */ + function &getNodeById($id) + { + $id = is_numeric($id) ? $id : strtolower($id); + if (!array_key_exists($id, $this->_siteMapArray)) return NULL; + if (!is_object($this->_siteMapArray[$id]['nodeObj'])) + { + $a = new org_glizy_application_SiteMapNode($this, $this->_siteMapArray[$id]); + $this->_siteMapArray[$id]['nodeObj'] = &$a; + return $a; + } + return $this->_siteMapArray[$id]['nodeObj']; + } + + function &getMenuByPageType($pageType) + { + $pageType = strtolower($pageType); + if (!array_key_exists($pageType, $this->_pageTypeMap)) return NULL; + + if (!is_object($this->_pageTypeMap[$pageType]['nodeObj'])) + { + $a = new org_glizy_application_SiteMapNode($this, $this->_pageTypeMap[$pageType]); + $this->_pageTypeMap[$pageType]['nodeObj'] = &$a; + return $a; + } + return $this->_pageTypeMap[$pageType]['nodeObj']; + } + + function &getHomeNode() + { + $IDs = array_keys($this->_siteMapArray); + return $this->getNodeById($IDs[0]); + } + + function &getSiteArray($forceReload=false) + { + $this->loadTree($forceReload); + return $this->_siteMapArray; + } + + function getAllChildsId($id) + { + $result = array(); + $this->_getAllChildsId($id, $result); + return $result; + } + + function _getAllChildsId($id, &$result) + { + if (!array_key_exists($id, $this->_siteMapArray)) return $result; + $result[] = $id; + $menu = $this->_siteMapArray[$id]; + $childNodes = $menu['childNodes']; + foreach ($childNodes as $childId) + { + $this->_getAllChildsId($childId, $result); + } + } + + function addChildMenu(&$menu, $menuRecord) + { + $menuRecord['childNodes'] = array(); + $menuRecord['parentId'] = $menu->id; + $menuRecord['depth'] = ($menu->depth)+1; + $menuRecord['nodeObj'] = NULL; + $menuRecord['isPublished'] = 1; + $menuRecord['order'] = 1; + $menuRecord['hasPreview'] = 1; + $menuRecord['type'] = 'PAGE'; + $menuRecord['isLocked'] = false; + $menuRecord['nodeObj'] = NULL; + if ( !isset( $menuRecord['printPdf'] ) ) + { + $menuRecord['printPdf'] = true; + } + + $this->_siteMapArray[$menuRecord['id']] = $menuRecord; + $this->_pageTypeMap[strtolower($menuRecord['pageType'])] = &$this->_siteMapArray[$menuRecord["id"]]; + $this->_siteMapArray[$menu->id]['childNodes'][] = $menuRecord['id']; + } + + function getEmptyMenu() + { + $menu = array(); + $menu['id'] = 0; + $menu['parentId'] = 0; + $menu['pageType'] = ''; + $menu['isVisible'] = 1; + $menu['title'] = ''; + $menu['titleLink'] = ''; + $menu['linkDescription'] = ''; + $menu['showTitle'] = true; + $menu['depth'] = 1; + $menu['childNodes'] = array(); + $menu['order'] = 1; + $menu['type'] = 'PAGE'; + $menu['creationDate'] = time(); + $menu['modificationDate'] = time(); + $menu['isLocked'] = false; + $menu['nodeObj'] = NULL; + $menu['hasComment'] = false; + $menu['printPdf'] = true; + $menu['cssClass'] = ''; + $menu['sortChild'] = false; + return $menu; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/application/SiteMapIterator.php b/src/core/classes/org/glizy/application/SiteMapIterator.php new file mode 100755 index 0000000..b23ca4d --- /dev/null +++ b/src/core/classes/org/glizy/application/SiteMapIterator.php @@ -0,0 +1,119 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_application_SiteMapIterator extends GlizyObject +{ + var $_treeManager; + var $EOF; + var $_currentNode; + + function __construct(&$parent) + { + $this->_treeManager = &$parent; + $this->EOF = false; + $this->_currentNode = $this->_treeManager->getHomeNode(); + + } + + function moveNext() + { + if ($this->_currentNode->hasChildNodes()) + { + $tempNode = $this->_currentNode->firstChild(); + } + else + { + $tempNode = $this->_currentNode->nextSibling(); + if (is_null($tempNode)) + { + $tempNode = $this->_currentNode; + while (true) + { + $node = $tempNode->parentNode(); + + if (!is_null($node)) + { + $node2 = $node->nextSibling(); + if (!is_null($node2)) + { + $tempNode = $node2; + break; + } + else + { + $tempNode = $node; + } + } + else + { + $tempNode = null; + break; + } + } + } + } + + $this->_update($tempNode); + return $this->getNode(); + } + + function movePrevious() + { + $tempNode = $this->_currentNode->previousSibling(); + if (is_null($tempNode)) { + $tempNode = $this->_currentNode->parentNode(); + } else { + while (true) + { + $tempNodeChild = $tempNode->childNodes(); + if (!count($tempNodeChild)) { + break; + } + $tempNode = array_pop($tempNodeChild); + } + } + + $this->_update($tempNode); + return $this->getNode(); + } + + function &getNode() + { + return $this->_currentNode; + } + + function &getNodeArray() + { + return $this->_treeManager->_siteMapArray[$this->_currentNode->id]; + } + + function setNode($node) + { + $this->_currentNode = $node; + } + + function reset() + { + $this->EOF = false; + $this->_currentNode = $this->_treeManager->getHomeNode(); + } + + function _update(&$node) + { + $this->EOF = is_null($node); + $this->_currentNode = $node; + } + + + function hasMore() + { + return !$this->EOF; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/application/SiteMapNode.php b/src/core/classes/org/glizy/application/SiteMapNode.php new file mode 100755 index 0000000..f52f8c6 --- /dev/null +++ b/src/core/classes/org/glizy/application/SiteMapNode.php @@ -0,0 +1,204 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_application_SiteMapNode extends GlizyObject +{ + var $_treeManager; + var $id; + var $parentId; + var $pageType; + var $isPublished; + var $isVisible; + var $title; + var $titleLink; + var $linkDescription; + var $order; + var $hasPreview; + var $depth; + var $type; + var $isLocked; + var $creationDate; + var $modificationDate; + var $showTitle; + var $moduleClass; + var $url = NULL; + var $select = NULL; + var $hasComment; + var $printPdf; + var $cssClass; + var $icon; + var $extendsPermissions; + var $keywords = ''; + var $description = ''; + var $extraData = null; + + function __construct(&$parent, &$node) + { + $this->_treeManager = &$parent; + $this->attributes = &$node; + $this->id = $this->attributes['id']; + $this->parentId = $this->attributes['parentId']; + $this->pageType = $this->attributes['pageType']; + $this->title = javascript_to_html($this->attributes['title']); + $this->titleLink = javascript_to_html($this->attributes['titleLink']); + $this->order = $this->attributes['order']; + $this->isVisible = $this->attributes['isVisible']; + $this->depth = $this->attributes['depth']; + $this->type = $this->attributes['type']; + $this->isLocked = $this->attributes['isLocked']; + $this->creationDate = $this->attributes['creationDate']; + $this->modificationDate = $this->attributes['modificationDate']; + $this->showTitle = $this->attributes['showTitle']; + $this->hasComment = $this->attributes['hasComment']; + $this->printPdf = $this->attributes['printPdf'] == 1; + $this->cssClass = $this->attributes['cssClass']; + $this->icon = $this->attributes['icon']; + if (isset($this->attributes['linkDescription'])) $this->linkDescription = javascript_to_html($this->attributes['linkDescription']); + if (isset($this->attributes['moduleClass'])) $this->url = $this->attributes['moduleClass']; + if (isset($this->attributes['extendsPermissions'])) $this->url = $this->attributes['extendsPermissions']; + if (isset($this->attributes['url'])) $this->url = $this->attributes['url']; + if (isset($this->attributes['select'])) $this->select = $this->attributes['select']; + } + + + function hasChildNodes() + { + return count($this->attributes['childNodes'])>0; + } + + function &firstChild($onlyVisible=false) + { + if (!$this->hasChildNodes()) return NULL; + $menu = NULL; + foreach($this->attributes['childNodes'] as $id) { + $menu = $this->_treeManager->getNodeById($id); + if (!$onlyVisible || $menu->isVisible) { + break; + } + $menu = null; + } + return $menu; + } + + function &childNodes() + { + $childNodes = array(); + if ($this->hasChildNodes()) + { + foreach ($this->attributes['childNodes'] as $id) + { + $childNodes[] = $this->_treeManager->getNodeById($id); + } + } + + return $childNodes; + } + + + function &parentNode() + { + return $this->_treeManager->getNodeById($this->parentId); + } + + function &parentNodeByDepth($depth) + { + $r = NULL; + if ($this->depth<$depth) + { + return $r; + } + else if ($this->depth==$depth) + { + return $this; + } + else + { + $menu = &$this; + while (true) + { + $tempNode = &$menu->parentNode(); + if ($tempNode->depth==$depth) + { + return $tempNode; + } + else if ($tempNode->depth==0) + { + return $r; + } + + $menu = &$tempNode; + } + } + } + + function &nextSibling() + { + if ($this->parentId === 0) return NULL; + $parentNode = $this->_treeManager->getNodeById($this->parentId); + $childNodes = &$parentNode->attributes['childNodes']; + if ($childNodes === NULL) return NULL; + $pos = array_search($this->id, $childNodes); + + if ($pos<count($childNodes)-1) + { + return $this->_treeManager->getNodeById($childNodes[++$pos]); + } + else + { + return NULL; + } + } + + function &previousSibling() + { + if ($this->parentId === 0) return NULL; + $parentNode = $this->_treeManager->getNodeById($this->parentId); + $childNodes = &$parentNode->attributes['childNodes']; + if ($childNodes === NULL) return NULL; + $pos = array_search($this->id, $childNodes); + + if ($pos>0) + { + return $this->_treeManager->getNodeById($childNodes[--$pos]); + } + else + { + return NULL; + } + } + + function getAttribute($attribute) + { + // TODO controllare che l'attrinbuto esiste + return $this->attributes[$attribute]; + } + + function loadDetails() + { + if (is_integer($this->id)) { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $ar = &org_glizy_ObjectFactory::createModel('org.glizycms.core.models.MenuDetail'); + $ar->menudetail_FK_menu_id = $this->id; + $ar->menudetail_FK_language_id = $application->getLanguageId(); + $ar->find(); + $values = $ar->getValuesAsArray(); + foreach ($values as $k=>$v) + { + $propName = str_replace('menudetail_', '', $k); + if ($propName=='id') continue; + $this->$propName = glz_encodeOutput($v); + } + } + } + + function getSiteMap() + { + return $this->_treeManager; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/application/SiteMapSimple.php b/src/core/classes/org/glizy/application/SiteMapSimple.php new file mode 100755 index 0000000..1a78c54 --- /dev/null +++ b/src/core/classes/org/glizy/application/SiteMapSimple.php @@ -0,0 +1,78 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_application_SiteMapSimple extends org_glizy_application_SiteMap +{ + function loadTree($forceReload=false) + { + if ($forceReload) $this->init(); + + $menu = $this->getEmptyMenu(); + $menu['id'] = '__root__'; + $this->_siteMapArray[$menu['id']] = $menu; + + $files = array(); + $dir = org_glizy_Paths::getRealPath('APPLICATION_PAGE_TYPE'); + if ($dirHandle = @opendir($dir)) + { + while ($fileName = readdir($dirHandle)) + { + if ($fileName!='.' && + $fileName!='..' && + !is_dir($dir.'/'.$fileName) && + strstr($fileName, '.xml')!==false) + { + $files[] = $fileName; + } + } + closedir($dirHandle); + } + + //ordina il risultato alfabeticamente + sort($files); + + // legge la localizzazione dei nomi dei pageType + glz_loadLocale( $dir ); + + // crea i menù + foreach($files as $f) + { + $fileName = substr($f, 0, strrpos($f, '.')); + $title = __T($fileName); + if (empty($title)) $title = $fileName; + + $menu = $this->getEmptyMenu(); + $menu['id'] = strtolower($fileName); + $menu['parentId'] = $this->_searchParent($menu['id']); + $menu['pageType'] = $fileName; + $menu['title'] = $title; + $menu['type'] = substr($fileName, 0, 1)=='_' ? 'SYSTEM' : 'PAGE'; + $this->_siteMapArray[$menu['id']] = $menu; + } + + $this->_makeChilds(); + } + + function _searchParent($menuId) + { + $idParts = explode('_', $menuId); + $parentMenuId = ''; + foreach($idParts as $p) + { + $parentMenuId .= $p; + if (isset($this->_siteMapArray[$parentMenuId])) + { + return $parentMenuId; + } + $parentMenuId .= '_'; + } + return '__root__'; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/application/SiteMapXML.php b/src/core/classes/org/glizy/application/SiteMapXML.php new file mode 100755 index 0000000..28e1b11 --- /dev/null +++ b/src/core/classes/org/glizy/application/SiteMapXML.php @@ -0,0 +1,173 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_application_SiteMapXML extends org_glizy_application_SiteMap +{ + var $_type = 'xml'; + var $_source = NULL; + + function __construct($source=NULL) + { + parent::__construct(); + $this->_source = is_null($source) ? org_glizy_Paths::getRealPath('APPLICATION', org_glizy_Config::get('SITEMAP')) : $source; + } + + function loadTree($forceReload=false) + { + if ($forceReload) $this->init(); + + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $lang = $application->getLanguage(); + + $options = array( + 'cacheDir' => org_glizy_Paths::get('CACHE_CODE'), + 'lifeTime' => -1, + 'readControlType' => '', + 'fileExtension' => '.php' + ); + $cacheObj = &org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFile', $options ); + $cacheFileName = $cacheObj->verify( $this->_source, get_class( $this ).'_'.$application->getLanguage() ); + + if ( $cacheFileName === false ) + { + $this->_processSiteMapXML( $this->_source ); + $customSource = preg_replace( '/.xml$/i', '_custom.xml', $this->_source ); + if ( file_exists( $customSource ) ) + { + $this->_processSiteMapXML( $customSource ); + } + + $cacheObj->save( serialize( $this->_siteMapArray ), NULL, get_class( $this ).'_'.$application->getLanguage() ); + $cacheObj->getFileName(); + } + else + { + $this->_siteMapArray = unserialize( file_get_contents( $cacheFileName ) ); + } + + $this->_makeChilds(); + } + + function _processSiteMapXML( $fileName, $parentId = '' ) + { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $lang = $application->getLanguage(); + + $modulesState = org_glizy_Modules::getModulesState(); + + $xmlString = file_get_contents( $fileName ); + if ( strpos( $xmlString, '<glz:modulesAdmin />' ) ) + { + $modulesSiteMap = ''; + $modules = org_glizy_Modules::getModules(); + foreach( $modules as $m ) + { + if ( $m->enabled && $m->siteMapAdmin ) + { + $modulesSiteMap .= $m->siteMapAdmin; + } + } + $xmlString = str_replace( '<glz:modulesAdmin />', $modulesSiteMap, $xmlString ); + } + + $xml = org_glizy_ObjectFactory::createObject( 'org.glizy.parser.XML' ); + $xml->loadXmlAndParseNS( $xmlString ); + $pages = $xml->getElementsByTagName('Page'); + $total = $pages->length; + $pagesAcl = array(); + + for ($i = 0; $i < $total; $i++) { + $currNode = $pages->item( $i ); + + $nodeTitle = ''; + $this->_searchNodeDetails($currNode, $nodeTitle, $lang); + + $id = $currNode->getAttribute('id'); + if (isset($modulesState[$id]) && !$modulesState[$id]) continue; + + $menu = $this->getEmptyMenu(); + $menu['id'] = strtolower($id); + $menu['parentId'] = $currNode->hasAttribute('parentId') ? strtolower($currNode->getAttribute('parentId') ) : + ( $currNode->parentNode->hasAttribute('id') ? strtolower($currNode->parentNode->getAttribute('id')) : '' ); + $menu['pageType'] = $currNode->hasAttribute('pageType') ? $currNode->getAttribute('pageType') : $currNode->getAttribute('id'); + $menu['isPublished'] = 1; + $menu['isVisible'] = $currNode->getAttribute('visible'); + $menu['cssClass'] = $currNode->getAttribute('cssClass'); + $menu['icon'] = $currNode->getAttribute('icon'); + $menu['sortChild'] = $currNode->hasAttribute('sortChild') && $currNode->getAttribute('sortChild')=='true'; + + if (!$currNode->hasAttribute('visible')) { + if ( $currNode->hasAttribute('adm:acl') || in_array($menu['id'], $pagesAcl) ) + { + $menu['isVisible'] = '{php:$user.acl("'.$menu['id'].'", "visible")}'; + } + else if ( !$currNode->hasAttribute('adm:acl') && $currNode->hasAttribute('adm:aclPageTypes') ) + { + $temp = array(); + $aclPages = explode(',', strtolower($currNode->getAttribute('adm:aclPageTypes'))); + foreach($aclPages as $v) { + $temp[] = '$user.acl("'.$v.'", "visible")'; + } + $menu['isVisible'] = '{php:('.implode(' OR ', $temp).')}'; + } + } + + $menu['title'] = $nodeTitle; + $menu['depth'] = 1; + $menu['childNodes'] = array(); + + // solo admin + $menu['order'] = 0; + $menu['hasPreview'] = 0; + $menu['type'] = 'PAGE'; + $menu['creationDate'] = 0; + $menu['modificationDate'] = 0; + $menu['url'] = str_replace('%', '&', $currNode->getAttribute('url')); + if ( strpos( $menu['url'], '&' ) === 0 ) + { + $menu['url'] = __Link::scriptUrl( true ).$menu['url']; + } + $menu['select'] = strtolower($currNode->getAttribute('select')); + $menu['nodeObj'] = NULL; + $menu['adm:acl'] = $currNode->hasAttribute('adm:acl') ? $currNode->getAttribute('adm:acl') : null; + $menu['adm:aclLabel'] = $currNode->hasAttribute('adm:aclLabel') ? $currNode->getAttribute('adm:aclLabel') : null; + $menu['adm:aclPageTypes'] = $currNode->hasAttribute('adm:aclPageTypes') ? $currNode->getAttribute('adm:aclPageTypes') : null; + + if ($menu['adm:aclPageTypes']) { + $pagesAcl = array_merge(explode(',', strtolower($menu['adm:aclPageTypes'])), $pagesAcl); + } + + $this->_siteMapArray[$menu["id"]] = $menu; + } + } + + function _searchNodeDetails(&$myNode, &$title, $language) + { + if ( $myNode->hasAttribute('value') ) + { + $title = $myNode->getAttribute('value'); + if (preg_match("/\{i18n\:.*\}/i", $title)) + { + $code = preg_replace("/\{i18n\:(.*)\}/i", "$1", $title); + $title = org_glizy_locale_Locale::getPlain($code); + } + return $title; + } + + foreach( $myNode->childNodes as $currNode ) + { + if ( ( $currNode->nodeName=='Title' || $currNode->nodeName=='glz:Title' ) && $currNode->getAttribute('lang')==$language) + { + $title= $currNode->hasAttribute('value') ? trim($currNode->getAttribute('value')) : trim($currNode->getText()); + break; + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/application/User.php b/src/core/classes/org/glizy/application/User.php new file mode 100755 index 0000000..ce58231 --- /dev/null +++ b/src/core/classes/org/glizy/application/User.php @@ -0,0 +1,111 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class org_glizy_application_User */ +class org_glizy_application_User extends GlizyObject +{ + + var $id; + var $firstName; + var $lastName; + var $loginId; + var $email; + var $groupId; + var $backEndAccess; + var $language; + var $active; + var $dateCreation; + var $_acl = null; + + function __construct($userInfo) + { + if (is_object($userInfo)) { + $userInfo = (array)$userInfo; + } + $this->id = $userInfo['id']; + $this->firstName = $userInfo['firstName']; + $this->lastName = $userInfo['lastName']; + $this->loginId = $userInfo['loginId']; + $this->email = $userInfo['email']; + $this->groupId = $userInfo['groupId']; + $this->backEndAccess = $userInfo['backEndAccess']; + $this->language = isset($userInfo['language']) ? $userInfo['language'] : ''; + $this->active = $userInfo['isActive']; + $this->dateCreation = $userInfo['dateCreation']; + + // TODO gestire __Config::get('ACL_ENABLED') + // creando un UserAcl che viene creato se __Config::get('ACL_ENABLED') = true + $this->_acl = org_glizy_ObjectFactory::createObject(__Config::get('ACL_CLASS'), $this->id, $this->groupId); + + org_glizy_ObjectValues::set('org.glizy', 'userId', $this->id); + } + + function getId() + { + return $this->id; + } + + function toString() + { + return "user: " . $this->id . ", " . $this->loginId . ", " . $this->firstName . " " . $this->lastName; + } + + function isLogged() + { + return $this->id <> 0; + } + + function acl($name, $action, $default = null) + { + return $this->_acl->acl($name, $action, $default); + } + + function checkActions($action, $role) + { + return $this->_acl->checkActions($action, $role); + } + + function isInRole($roleId) + { + return $this->_acl->inRole($roleId); + } + + function isInRoles($roles) + { + foreach ($roles as $roleId) { + if ($this->_acl->inRole($roleId)) { + return true; + } + } + + return false; + } + + function getRoles() + { + return $this->_acl->getRoles(); + } + + function invalidateAcl() + { + return $this->_acl->invalidateAcl(); + } + + function isActive() + { + return $this->active; + } + + /** + * @return mixed + */ + public function getDateCreation() + { + return $this->dateCreation; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/authentication/AbstractLogin.php b/src/core/classes/org/glizy/authentication/AbstractLogin.php new file mode 100755 index 0000000..df8b9c6 --- /dev/null +++ b/src/core/classes/org/glizy/authentication/AbstractLogin.php @@ -0,0 +1,68 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +abstract class org_glizy_authentication_AbstractLogin extends GlizyObject +{ + protected $loginId; + protected $language = null; + protected $psw; + protected $arUser; + protected $allowGroups = array(); + protected $onlyBackendUser = false; + + public function loginFromRequest($loginIdField, $passwordFields, $rememberField=false, $readFromCookie=false) + { + $loginId = trim(__Request::get($loginIdField, $readFromCookie ? $_COOKIE['glizy_username'] : '' )); + $psw = trim(__Request::get($passwordFields, $readFromCookie ? $_COOKIE['glizy_password'] : '')); + $remember = __Request::get($rememberField, 0); + $this->login($loginId, glz_password($psw), $remember); + } + + public function setAllowGroups($allowGroups) + { + $this->allowGroups = $allowGroups; + } + + public function setOnlyBackendUser($onlyBackendUser) + { + $this->onlyBackendUser = $onlyBackendUser; + } + + public function setUserLanguage($language) + { + $this->language = $language; + } + + protected function validateLogin($loginId, $psw) + { + if (!$loginId || !$psw) { + throw org_glizy_authentication_AuthenticationException::emptyLoginIdOrPassword(); + } + } + + protected function resetSession() { + org_glizy_Session::set('glizy.userLogged', false); + org_glizy_Session::set('glizy.user', NULL); + } + + protected function setSession($user) { + org_glizy_Session::set('glizy.userLogged', true); + org_glizy_Session::set('glizy.user', $user); + } + + protected function resetCookie() { + } + + protected function setCookie($loginId, $psw) { + $lifetime = time() + 60*60*24*30; + setcookie( "glizy_username", $loginId, $lifetime); //, "/", $_SERVER["HTTP_HOST"], !$_SERVER["HTTPS"]); + setcookie( "glizy_password", $psw, $lifetime); //, "/", $_SERVER["HTTP_HOST"], !$_SERVER["HTTPS"]); + } + +} diff --git a/src/core/classes/org/glizy/authentication/AuthenticationDriver.php b/src/core/classes/org/glizy/authentication/AuthenticationDriver.php new file mode 100755 index 0000000..12024dc --- /dev/null +++ b/src/core/classes/org/glizy/authentication/AuthenticationDriver.php @@ -0,0 +1,14 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +interface org_glizy_authentication_AuthenticationDriver +{ + public function login($loginId, $password, $remember=false); + public function logout(); +} diff --git a/src/core/classes/org/glizy/authentication/AuthenticationException.php b/src/core/classes/org/glizy/authentication/AuthenticationException.php new file mode 100755 index 0000000..00c5c21 --- /dev/null +++ b/src/core/classes/org/glizy/authentication/AuthenticationException.php @@ -0,0 +1,36 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_authentication_AuthenticationException extends Exception +{ + const EMPTY_LOGINID_OR_PASSWORD = 1; + const WRONG_LOGINID_OR_PASSWORD = 2; + const USER_NOT_ACTIVE = 3; + const ACCESS_NOT_ALLOWED = 4; + + public static function emptyLoginIdOrPassword() + { + return new self('Empty username or password', self::EMPTY_LOGINID_OR_PASSWORD); + } + + public static function wrongLoginIdOrPassword() + { + return new self('Wrong username or password', self::WRONG_LOGINID_OR_PASSWORD); + } + + public static function userNotActive() + { + return new self('User not active', self::USER_NOT_ACTIVE); + } + + public static function AccessNotAllowed() + { + return new self('Access Not Allowed', self::ACCESS_NOT_ALLOWED); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/authentication/Database.php b/src/core/classes/org/glizy/authentication/Database.php new file mode 100755 index 0000000..c661a67 --- /dev/null +++ b/src/core/classes/org/glizy/authentication/Database.php @@ -0,0 +1,105 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_authentication_Database extends org_glizy_authentication_AbstractLogin implements org_glizy_authentication_AuthenticationDriver +{ + public function login($loginId, $psw, $remember=false) + { + $this->validateLogin($loginId, $psw); + $this->resetSession(); + + $it = org_glizy_ObjectFactory::createModelIterator('org.glizy.models.User') + ->load('login', array('loginId' => $loginId, 'password' => $psw)); + + if ($it->count()) { + // login success + $this->arUser = $it->current(); + + if ($this->arUser->user_isActive==0) { + throw org_glizy_authentication_AuthenticationException::userNotActive(); + } + + if (__Config::get('ACL_ROLES') && $this->onlyBackendUser) { + $user = array( + 'id' => $this->arUser->user_id, + 'firstName' => $this->arUser->user_firstName, + 'lastName' => $this->arUser->user_lastName, + 'loginId' => $this->arUser->user_loginId, + 'email' => $this->arUser->user_email, + 'groupId' => $this->arUser->user_FK_usergroup_id, + 'backEndAccess' => false, + ); + + $user = &org_glizy_ObjectFactory::createObject('org.glizy.application.User', $user); + + if (!$user->acl('Home', 'all')) { + org_glizy_Session::destroy(); + throw org_glizy_authentication_AuthenticationException::AccessNotAllowed(); + } + + $backEndAccess = true; + } + else { + if ($this->onlyBackendUser && $this->arUser->usergroup_backEndAccess==0) { + throw org_glizy_authentication_AuthenticationException::AccessNotAllowed(); + } + + if (count($this->allowGroups) ? !in_array($this->arUser->user_FK_usergroup_id, $this->allowGroups) : false) { + throw org_glizy_authentication_AuthenticationException::AccessNotAllowed(); + } + + $backEndAccess = $this->arUser->usergroup_backEndAccess; + } + + $language = $this->language; + if (!$language) $language = __Config::get('DEFAULT_LANGUAGE'); + + $user = array( 'id' => $this->arUser->user_id, + 'firstName' => $this->arUser->user_firstName, + 'lastName' => $this->arUser->user_lastName, + 'loginId' => $this->arUser->user_loginId, + 'email' => $this->arUser->user_email, + 'groupId' => $this->arUser->user_FK_usergroup_id, + 'backEndAccess' => $backEndAccess, + 'language' => $language, + // 'logId' => $logId + ); + $this->setSession($user); + + if ($remember) { + $this->setCookie($loginId, $psw); + } + + $evt = array('type' => GLZ_EVT_USERLOGIN, 'data' => $user); + $this->dispatchEvent($evt); + return $user; + } else { + // wrong username or password + throw org_glizy_authentication_AuthenticationException::wrongLoginIdOrPassword(); + } + } + + public function logout() + { + org_glizy_Session::start(); + $evt = array('type' => GLZ_EVT_USERLOGOUT, 'data' => ''); + $this->dispatchEvent($evt); + + if (org_glizy_Config::get('USER_LOG')) { + $user = org_glizy_Session::get('glizy.user'); + $arLog = &org_glizy_ObjectFactory::createModel('org.glizy.models.UserLog'); + $arLog->load($user['logId']); + $arLog->delete(); + } + org_glizy_Session::removeAll(); + + setcookie( "glizy_username", "", time()-3600 ); + setcookie( "glizy_password", "", time()-3600 ); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/cache/CacheFile.php b/src/core/classes/org/glizy/cache/CacheFile.php new file mode 100755 index 0000000..7b10c88 --- /dev/null +++ b/src/core/classes/org/glizy/cache/CacheFile.php @@ -0,0 +1,158 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +require_once(GLZ_LIBS_DIR."Cache_Lite/Lite.php"); +/** + * Class org_glizy_cache_CacheFile + */ +class org_glizy_cache_CacheFile extends Cache_Lite +{ + var $_fileExtension = ''; + + /** + * @param array $options + */ + function __construct($options = array(NULL)) + { + $options['readControl'] = false; + parent::Cache_Lite($options); + if (isset($options['fileExtension'])) $this->_fileExtension = $options['fileExtension']; + } + + /** + * @param $id + * @param string $group + * @param bool $doNotTestCacheValidity + * @param null $originalFile + * + * @return bool|string + */ + function verify($id, $group = 'default', $doNotTestCacheValidity = false, $originalFile = NULL) + { + $this->_id = $id; + $this->_group = $group; + $data = false; + if ($this->_caching) + { + $this->_setRefreshTime(); + $this->_setFileName($id, $group, $originalFile); + clearstatcache(); + if (!is_null($originalFile)) $this->_id = $originalFile; + + if ($this->_lifeTime==-1) + { + if ((file_exists($this->_file)) && (@filemtime($this->_file) == @filemtime($this->_id))) + { + $data = $this->_file; + } + } + else + { + if (($doNotTestCacheValidity) || (is_null($this->_refreshTime))) + { + if (file_exists($this->_file)) { + $data = $this->_file; + } + } + else + { + if ((file_exists($this->_file)) && (@filemtime($this->_file) > $this->_refreshTime)) + { + $data = $this->_file; + } + } + } + } + if (!is_null($originalFile)) $this->_id = $id; + return $data; + } + + /** + * @return string + */ + function getFileName() + { + return $this->_file; + } + + /** + * @param string $id + * @param string $group + */ + function _setFileName($id, $group) + { + if ($this->_fileNameProtection) { + $suffix = 'cache_'.md5($group).'_'.md5($id).$this->_fileExtension; + } else { + $suffix = 'cache_'.$group.'_'.$id.$this->_fileExtension; + } + $root = $this->_cacheDir; + if ($this->_hashedDirectoryLevel>0) { + $hash = md5($suffix); + for ($i=0 ; $i<$this->_hashedDirectoryLevel ; $i++) { + $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/'; + } + } + $this->_fileName = $suffix; + $this->_file = $root.$suffix; + } + + /** + * @param string $data + * @param null $id + * @param string $group + * + * @return bool + */ + function save($data, $id = NULL, $group = 'default') + { + $r = parent::save($data, $id, $group); + if ($this->_lifeTime==-1) + { + @touch($this->_file, filemtime($this->_id)); + } + @chmod( $this->_file, 0777 ); + return $r; + } + + /** + * @param string $file + * + * @return bool + */ + function _unlink($file) + { + @unlink($file); + return true; + } + + /** + * @param null $cacheCode + */ + static function cleanPHP($cacheCode=null) + { + $cacheCode = $cacheCode == null ? __Paths::get( 'CACHE_CODE' ) : $cacheCode; + self::rm( $cacheCode.'*.php' ); + if (function_exists('opcache_get_status')) { + opcache_reset(); + } + } + + /** + * @param $path + */ + static function rm( $path ) + { + foreach (glob( $path ) as $filename) + { + @unlink($filename); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/cache/CacheFunction.php b/src/core/classes/org/glizy/cache/CacheFunction.php new file mode 100755 index 0000000..15505f0 --- /dev/null +++ b/src/core/classes/org/glizy/cache/CacheFunction.php @@ -0,0 +1,98 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + + +class org_glizy_cache_CacheFunction extends GlizyObject +{ + private $_cacheObj; + private $parent; + private $memoryCache; + private $group; + private static $memArray = array(); + + + function __construct($parent, $lifeTime=null, $memoryCache=false, $cacheFolder=null, $group=null) + { + $cacheFolder = $cacheFolder ? $cacheFolder : org_glizy_Paths::getRealPath('CACHE_CODE'); + $this->parent = $parent; + $this->memoryCache = $memoryCache; + $this->group = $group ? $group : $cacheFolder.get_class($this->parent); + $options = array( + 'cacheDir' => $cacheFolder, + 'lifeTime' => !$lifeTime ? org_glizy_Config::get('CACHE_CODE') : $lifeTime, + 'readControlType' => '', + 'fileExtension' => '.php' + ); + + if ($options['lifeTime']=='-1') { + $options['lifeTime'] = null; + } + + $this->_cacheObj = &org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFile', $options); + } + + public function get($method, $args, $lambda) + { + $fileName = $method.serialize($args); + $memId = $fileName.$this->group; + $data = $this->getMemoryCache($memId); + + if ( $data !== false) { + return $data; + } else { + $data = $this->_cacheObj->get($fileName, $this->group); + if ($data===false) { + $data = $lambda(); + $this->_cacheObj->save($this->serialize($data), $fileName, $this->group); + } else { + $data = $this->unserialize($data); + } + + $this->setMemoryCache($memId, $data); + return $data; + } + } + + public function invalidateGroup() + { + $this->_cacheObj->clean($this->group); + } + + public function remove($method, $args) + { + $fileName = $method.serialize($args); + $this->_cacheObj->remove($fileName, $this->group); + } + + private function getMemoryCache($id) + { + if ($this->memoryCache && isset(self::$memArray[$id])) { + return self::$memArray[$id]; + } + return false; + } + + private function setMemoryCache($id, $data) + { + if ($this->memoryCache) { + self::$memArray[$id] = $data; + } + } + + private function serialize($data) + { + return is_string($data) ? 'N|'.$data : 'Y|'.serialize($data); + } + + private function unserialize($data) + { + return substr($data, 0, 2) == 'N|' ? substr($data, 2) : unserialize(substr($data, 2)); + } +} diff --git a/src/core/classes/org/glizy/compilers/Acl.php b/src/core/classes/org/glizy/compilers/Acl.php new file mode 100755 index 0000000..e7d58ea --- /dev/null +++ b/src/core/classes/org/glizy/compilers/Acl.php @@ -0,0 +1,44 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_compilers_Acl extends org_glizy_compilers_Compiler +{ + function compile($options) + { + $this->initOutput(); + + // esegue il parsing del file di configurazione + $xml = org_glizy_ObjectFactory::createObject( 'org.glizy.parser.XML' ); + $xml->loadAndParseNS( $this->_fileName ); + $services = $xml->getElementsByTagName('AclService'); + + $this->output .= '$acl = array();'; + foreach ($services as $service) + { + $name = strtolower($service->getAttribute('name')); + $default = $service->hasAttribute('default') ? $service->getAttribute('default') : 'true'; + $this->output .= '$acl[\''.$name.'\'] = array(\'default\' => '.$default.', \'rules\' => array('; + + $rules = $service->getElementsByTagName('AclAction'); + foreach ($rules as $rule) + { + $name = strtolower($rule->getAttribute('name')); + $allowGroups= $rule->getAttribute('allowGroups'); + $allowGroups= !empty($allowGroups) ? 'array(\''.str_replace(',', '\', \'', $allowGroups).'\')' : 'array()'; + $allowUsers = $rule->getAttribute('allowUsers'); + $allowUsers = !empty($allowUsers) ? 'array(\''.str_replace(',', '\', \'', $allowUsers).'\')' : 'array()'; + $this->output .= '\''.$name.'\' => array(\'allowGroups\' => '.$allowGroups.', \'allowUsers\' => '.$allowUsers.'), '; + } + + $this->output .= '))'.GLZ_COMPILER_NEWLINE; + } + return $this->save(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/compilers/Compiler.php b/src/core/classes/org/glizy/compilers/Compiler.php new file mode 100755 index 0000000..df7bc2c --- /dev/null +++ b/src/core/classes/org/glizy/compilers/Compiler.php @@ -0,0 +1,107 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +abstract class org_glizy_compilers_Compiler extends GlizyObject +{ + var $_fileName = NULL; + var $_cacheObj = NULL; + var $output = ''; + + function __construct($cacheDir=null) + { + $options = array( + 'cacheDir' => $cacheDir ? $cacheDir : org_glizy_Paths::get('CACHE_CODE'), + 'lifeTime' => org_glizy_Config::get('CACHE_CODE'), + 'readControlType' => '', + 'fileExtension' => '.php' + ); + + $this->_cacheObj = &org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFile', $options); + } + + function initOutput() + { + $this->output = ''; + $this->output .= '<?php'.GLZ_COMPILER_NEWLINE2; + $this->output .= 'if (!defined(\'GLZ_LOADED\')) exit();'.GLZ_COMPILER_NEWLINE2; + $this->output .= '// ------------------------------------------------------------------------------'.GLZ_COMPILER_NEWLINE2; + $this->output .= '// This code is generated by GLIZY ('.get_class($this).') based on the source file'.GLZ_COMPILER_NEWLINE2; + $this->output .= '// '.$this->_fileName.GLZ_COMPILER_NEWLINE2; + $this->output .= '// date: '.date('m/d/Y H:i:s').GLZ_COMPILER_NEWLINE2; + $this->output .= '// ------------------------------------------------------------------------------'.GLZ_COMPILER_NEWLINE2; + } + + function save() + { + $this->_cacheObj->save( @GLZ_CHARSET != 'UTF-8' ? utf8_decode( $this->output ) : $this->output, NULL, org_glizy_Paths::get('CACHE').get_class($this)); + $fileName = $this->_cacheObj->getFileName(); + if (function_exists('opcache_invalidate')) { + opcache_invalidate($fileName, true); + } + return $fileName; + } + + abstract function compile($options); + + /** + * Verifica se il file è compilato, in casi affermativo restutuisce il path + */ + function verify($fileName, $options=NULL) + { + // $fileName = realpath( $fileName ); + // check if the file is already compiled in the same request + // this is usefull in develop enviroment + $c = org_glizy_ObjectValues::get($this->getClassName(), $fileName); + if (!is_null($c)) + { + return $c; + } + + // può essere passato un nome di file per verificare + // il caching. è utilizzato nel reamp dei pageType + $verifyFileName = $options && isset($options['verifyFileName']) ? $options['verifyFileName'] : $fileName; + $cacheFileName = $this->_cacheObj->verify($verifyFileName, org_glizy_Paths::get('CACHE').get_class($this)); + if ($cacheFileName===false) + { + $this->_fileName = $fileName; + $cacheFileName = $this->compile( $options ); + if ($cacheFileName===false) + { + // TODO + echo "FATAL ERROR ".$fileName; + return false; + } + } + + org_glizy_ObjectValues::set($this->getClassName(), $fileName, $cacheFileName); + return $cacheFileName; + } + + function isValid( $fileName ) + { + $fileName = realpath( $fileName ); + // check if the file is already compiled in the same request + // this is usefull in develop enviroment + $c = org_glizy_ObjectValues::get($this->getClassName(), $fileName); + if (!is_null($c)) + { + return true; + } + + $cacheFileName = $this->_cacheObj->verify($fileName, org_glizy_Paths::get('CACHE').get_class($this)); + return $cacheFileName!==false; + } + + + public function invalidate() + { + $this->_cacheObj->clean(org_glizy_Paths::get('CACHE').get_class($this)); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/compilers/CompilerException.php b/src/core/classes/org/glizy/compilers/CompilerException.php new file mode 100755 index 0000000..c5c3945 --- /dev/null +++ b/src/core/classes/org/glizy/compilers/CompilerException.php @@ -0,0 +1,16 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_compilers_CompilerException extends Exception +{ + public static function fileNotFound($fileName) + { + return new self('File not found: '. $fileName); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/compilers/Component.php b/src/core/classes/org/glizy/compilers/Component.php new file mode 100755 index 0000000..3c953f8 --- /dev/null +++ b/src/core/classes/org/glizy/compilers/Component.php @@ -0,0 +1,108 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_compilers_Component extends org_glizy_compilers_PageType +{ + + /** + * @param $options + * + * @return mixed + */ + function compile($options) + { + $this->initOutput(); + if ( isset( $options[ 'mode' ] ) ) + { + $this->mode = $options[ 'mode' ]; + } + + $pageXml = org_glizy_ObjectFactory::createObject( 'org.glizy.parser.XML' ); + $pageXml->loadAndParseNS( $this->_fileName ); + $pageRootNode = $pageXml->documentElement; + $registredNameSpaces = $pageXml->namespaces; + $registredNameSpaces['glz'] = 'org.glizy.components'; + + // include i componenti usati + foreach ($registredNameSpaces as $key=>$value) + { + if ($key!='glz' && substr($value, -1, 1)=='*') + { + $this->output .= 'glz_loadLocale(\''.$value.'\')'.GLZ_COMPILER_NEWLINE; + } + } + + $className = glz_basename($this->_cacheObj->getFileName()); + $componentClassInfo = $this->_getComponentClassInfo($pageRootNode->nodeName, $registredNameSpaces); + + //if (!empty($componentClassInfo['classPath'])) + //{ + // $this->_classSource .= 'glz_import(\''.$componentClassInfo['classPath'].'\')'.GLZ_COMPILER_NEWLINE; + //} + + $this->_classSource .= 'class '.$className.' extends '.$componentClassInfo['className'].' {'.GLZ_COMPILER_NEWLINE2; + $this->_classSource .= 'function '.$className.'(&$application, &$parent, $tagName=\'\', $id=\'\', $originalId=\'\', $skipImport=false) {'.GLZ_COMPILER_NEWLINE2; + if (isset($options['originalClassName'])) $this->_classSource .= '$this->_className = \''.$options['originalClassName'].'\''.GLZ_COMPILER_NEWLINE; + $this->_classSource .= 'parent::__construct($application, $parent, $tagName, $id, $originalId)'.GLZ_COMPILER_NEWLINE; + $this->_classSource .= '$mode = ""'.GLZ_COMPILER_NEWLINE; + $this->_classSource .= '$idPrefix = ""'.GLZ_COMPILER_NEWLINE; + $this->_classSource .= '$n0 = &$this'.GLZ_COMPILER_NEWLINE; + $this->_classSource .= 'if (!empty($id)) $id .= \'-\''.GLZ_COMPILER_NEWLINE; + $this->_classSource .= 'if (!empty($originalId)) $originalId .= \'-\''.GLZ_COMPILER_NEWLINE; + + if (count($pageRootNode->attributes)) + { + // compila gli attributi + $this->_classSource .= '$attributes = array('; + foreach ( $pageRootNode->attributes as $index=>$attr ) + { + if ($attr->name!='id') + { + // NOTA: su alcune versioni di PHP (es 5.1) empty( $attr->prefix ) non viene valutato in modo corretto + $prefix = $attr->prefix == "" || is_null( $attr->prefix ) ? "" : $attr->prefix.":"; + $this->_classSource .= '\''.$prefix.$attr->name.'\' => \''.addslashes($attr->value).'\', '; + } + } + $this->_classSource .= ')'.GLZ_COMPILER_NEWLINE; + $this->_classSource .= '$this->setAttributes( $attributes )'.GLZ_COMPILER_NEWLINE; + } + + $counter = 0; + $oldcounter = $counter; + foreach( $pageRootNode->childNodes as $nc ) + { + $counter++; + $this->_compileXml($nc, $registredNameSpaces, $counter, '$n'.$oldcounter, '$id.', '$originalId.' ); + } + + if (isset($options['originalClassName']) && $pageRootNode->hasAttribute( 'allowModulesSnippets' ) && $pageRootNode->getAttribute( 'allowModulesSnippets' ) == "true" ) + { + $modulesState = org_glizy_Modules::getModulesState(); + $modules = org_glizy_Modules::getModules(); + + foreach( $modules as $m ) + { + $isEnabled = !isset( $modulesState[ $m->id ] ) || $modulesState[ $m->id ]; + if ( $isEnabled && $m->pluginInPageType && $m->pluginSnippet ) + { + $counter++; + $this->compile_glzinclude( $m->pluginSnippet, $registredNameSpaces, $counter, '$n'.$oldcounter, '$id.' ); + } + } + } + $this->_classSource .= '}'.GLZ_COMPILER_NEWLINE2; + $this->_classSource .= '}'.GLZ_COMPILER_NEWLINE2; + + $this->output .= $this->_classSource; + $this->output .= $this->_customClassSource; + + return $this->save(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/compilers/Config.php b/src/core/classes/org/glizy/compilers/Config.php new file mode 100755 index 0000000..8ff7701 --- /dev/null +++ b/src/core/classes/org/glizy/compilers/Config.php @@ -0,0 +1,141 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_compilers_Config extends org_glizy_compilers_Compiler +{ + var $_config; + function compile($options) + { + $this->initOutput(); + + // esegue il parsing del file di configurazione + $this->_config = array(); + $this->_modes = '$configArray[\'__modes__\'] = array()'.GLZ_COMPILER_NEWLINE; + $this->_compileXml($this->_fileName); + + foreach ($this->_config as $name=>$value) + { + $this->output .= '$configArray[\''.$name.'\'] = '.$value.GLZ_COMPILER_NEWLINE; + } + $this->output .= $this->_modes; + + return $this->save(); + } + + function _compileXml($fileName) + { + $dirPath = dirname($fileName).'/'; + $xml = org_glizy_ObjectFactory::createObject( 'org.glizy.parser.XML' ); + $xml->load( $fileName ); + foreach( $xml->documentElement->childNodes as $nc ) + { + $this->_compileXmlNode( $nc, $dirPath ); + } + } + + function _compileXmlNode(&$node, $dirPath) + { + switch ( strtolower( $node->nodeName ) ) + { + case 'glz:import': + case 'import': + $appName = isset($_SERVER['GLIZY_APPNAME']) ? $_SERVER['GLIZY_APPNAME'] : ''; + $envName = getenv('GLIZY_SERVER_NAME'); + $serverName = is_null( $_SERVER["SERVER_NAME"] ) ? (($appName ? :$envName) ? :'console') : $_SERVER["SERVER_NAME"]; + $src = str_replace('##HOST##', $serverName, $node->getAttribute('src')); + + if ($src=='##APPLICATION_TO_ADMIN##') { + $src = '../../'.org_glizy_Paths::get('APPLICATION_TO_ADMIN').'config/'; + + $configName = ''; + if (isset($_SERVER['GLIZY_APPNAME'])) { + $serverName = $_SERVER['GLIZY_APPNAME']; + $configName = 'config_'.$serverName.'.xml'; + if ( !file_exists( realpath($dirPath.$src.$configName) ) ) { + $configName = ''; + } + } + + if (!$configName) { + $configName = 'config_'.$serverName.'.xml'; + } + + if ( !file_exists( realpath($dirPath.$src.$configName) ) ) + { + $configName = 'config.xml'; + } + $src .= $configName; + } + + $this->_compileXml(realpath($dirPath.$src)); + break; + + case 'glz:param': + case 'param': + $name = $node->getAttribute('name'); + $value = $node->hasAttribute('value') ? $node->getAttribute('value') : $node->firstChild->nodeValue; + $value = str_replace('##ROOT##', org_glizy_Paths::get('ROOT'), $value); + + if ($value=="false") $value = false; + else if($value=="true") $value = true; + + $this->_config[$name] = $value; + + if (gettype($value)=='string') + { + $this->_config[$name] = '\''.addcslashes($value, '\'').'\''; + } + else + { + $this->_config[$name] = $value ? 'true' : 'false'; + } + break; + case 'glz:configmode': + case 'configmode': + $modeName = $node->getAttribute('name'); + $tempConfig = $this->_config; + $this->_config = array(); + for ($i=0; $i<count($node->childNodes); $i++) + { + $this->_compileXmlNode($node->childNodes[$i], $dirPath); + } + + $this->_modes .= '$configArray[\'__modes__\'][\''.$modeName.'\'] = array()'.GLZ_COMPILER_NEWLINE; + foreach ($this->_config as $name=>$value) + { + $this->_modes .= '$configArray[\'__modes__\'][\''.$modeName.'\'][\''.$name.'\'] = '.$value.GLZ_COMPILER_NEWLINE; + } + $this->_config = $tempConfig; + if ( $node->getAttribute('default') == "true" ) + { + $this->_modes .= 'org_glizy_Config::setMode(\''.$modeName.'\')'.GLZ_COMPILER_NEWLINE; + } + + break; + } + + + } + + /** + * Verifica se il file � compilato, in casi affermativo restutuisce il path + */ + function verify($fileName) + { + $cacheFileName = $this->_cacheObj->verify($fileName, get_class($this)); + if ($cacheFileName===false) + { + $this->_fileName = $fileName; + $cacheFileName = $this->compile($fileName); + } + + return $cacheFileName; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/compilers/LayoutManagerPHP.php b/src/core/classes/org/glizy/compilers/LayoutManagerPHP.php new file mode 100755 index 0000000..d9025ab --- /dev/null +++ b/src/core/classes/org/glizy/compilers/LayoutManagerPHP.php @@ -0,0 +1,28 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_compilers_LayoutManagerPHP extends org_glizy_compilers_Compiler +{ + function compile($options) + { + $this->_cacheObj->save($options); + return $this->_cacheObj->getFileName(); + } + + /** + * Verifica se il file è compilato, in casi affermativo restituisce il path + */ + function verify($fileName, $options=NULL) + { + $cacheFileName = $this->_cacheObj->verify($fileName, get_class($this)); + return $cacheFileName; + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/compilers/Model.php b/src/core/classes/org/glizy/compilers/Model.php new file mode 100755 index 0000000..7896701 --- /dev/null +++ b/src/core/classes/org/glizy/compilers/Model.php @@ -0,0 +1,476 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_compilers_Model extends org_glizy_compilers_Compiler +{ + function compile( $options ) + { + if (!file_exists( $this->_fileName )) { + throw org_glizy_compilers_CompilerException::fileNotFound($this->_fileName); + } + + $this->initOutput(); + + $xml = org_glizy_ObjectFactory::createObject('org.glizy.parser.XML'); + $xml->loadAndParseNS($this->_fileName); + $xmlRootNode = $xml->documentElement; + $className = glz_basename($this->_cacheObj->getFileName()); + $tableName = $xmlRootNode->getAttribute('model:tableName'); + if (empty($tableName)) { + throw org_glizy_compilers_ModelException::missingTableName($this->_fileName); + } + $joinFields = $xmlRootNode->hasAttribute('model:joinFields') ? explode(',', $xmlRootNode->getAttribute('model:joinFields')) : null; + $modelType = $xmlRootNode->hasAttribute('model:type') ? $xmlRootNode->getAttribute('model:type') : 'activeRecord'; + $dbConnection = $xmlRootNode->hasAttribute('model:connection') ? $dbConnection = $xmlRootNode->getAttribute('model:connection') : '0'; + $usePrefix = $xmlRootNode->hasAttribute('model:usePrefix') && + $xmlRootNode->getAttribute('model:usePrefix') == 'true' ? 'true' : 'false'; + $languageField = $xmlRootNode->hasAttribute('model:languageField') ? '$this->setLanguageField(\''.$xmlRootNode->getAttribute('model:languageField').'\');' : ''; + $siteField = $xmlRootNode->hasAttribute('model:siteField') ? '$this->setSiteField(\''.$xmlRootNode->getAttribute('model:siteField').'\');' : ''; + $originalClassName = isset($options['originalClassName']) ? '$this->_className = \''.$options['originalClassName'].'\';' : ''; + + if ($modelType == '2tables') { + list($tableName, $detailTableName) = explode(',', $tableName); + } + + $baseclassName = $this->resolveBaseClass($modelType); + $fields = $this->compileFields($xmlRootNode); + $queries = $this->compileQueries($xmlRootNode); + $script = $this->compileScript($xmlRootNode); + + + if ( $baseclassName['type'] == 'activeRecord' ) { + $compiledOutput = <<<EOD +class $className extends {$baseclassName['activeRecord']} +{ + function __construct(\$connectionNumber=$dbConnection) { + parent::__construct(\$connectionNumber); + $originalClassName + \$this->setTableName('$tableName', + $usePrefix ? org_glizy_dataAccessDoctrine_DataAccess::getTablePrefix(\$connectionNumber) : '' ); + + \$sm = new org_glizy_dataAccessDoctrine_SchemaManager(\$this->connection); + \$fields = \$sm->getFields(\$this->getTableName()); + + foreach (\$fields as \$field) { + \$this->addField(\$field); + } + + {$fields} + + if (__Config::get('MULTISITE_ENABLED')) { + {$siteField} + } + } + + public function createRecordIterator() { + return new {$className}_iterator(\$this); + } + + {$script['model']} + $queries +} +class {$className}_iterator extends {$baseclassName['recordIterator']} +{ + {$script['iterator']} +} +EOD; + } elseif ( $baseclassName['type'] == '2tables' ) { + $compiledOutput = <<<EOD +class $className extends {$baseclassName['activeRecord']} +{ + function __construct(\$connectionNumber=$dbConnection) { + parent::__construct(\$connectionNumber); + \$this->setTableName('$tableName', + $usePrefix ? org_glizy_dataAccessDoctrine_DataAccess::getTablePrefix(\$connectionNumber) : '' ); + + \$this->setDetailTableName('$detailTableName', + $usePrefix ? org_glizy_dataAccessDoctrine_DataAccess::getTablePrefix(\$connectionNumber) : '' ); + + \$this->setJoinFields('$joinFields[0]', '$joinFields[1]'); + + \$sm = new org_glizy_dataAccessDoctrine_SchemaManager(\$this->connection); + \$fields = \$sm->getFields(\$this->getTableName()); + + foreach (\$fields as \$field) { + \$this->addField(\$field); + } + + \$fields = \$sm->getFields(\$this->getDetailTableName()); + + foreach (\$fields as \$field) { + \$this->addField(\$field, true); + } + + {$fields} + + {$languageField} + + if (__Config::get('MULTISITE_ENABLED')) { + {$siteField} + } + } + + public function createRecordIterator() { + return new {$className}_iterator(\$this); + } + + {$script['model']} + $queries +} +class {$className}_iterator extends {$baseclassName['recordIterator']} +{ + {$script['iterator']} +} +EOD; + } else { + $compiledOutput = <<<EOD +class $className extends {$baseclassName['activeRecord']} +{ + function __construct(\$connectionNumber=$dbConnection) { + parent::__construct(\$connectionNumber); + $originalClassName + \$this->setTableName('$tableName', + $usePrefix ? org_glizy_dataAccessDoctrine_DataAccess::getTablePrefix(\$connectionNumber) : '' ); + \$this->setType('$tableName'); + + $fields + } + + public function createRecordIterator() { + return new {$className}_iterator(\$this); + } + + {$script['model']} + $queries +} +class {$className}_iterator extends {$baseclassName['recordIterator']} +{ + {$script['iterator']} +} +EOD; + } + + $this->output .= $compiledOutput; + return $this->save(); + } + + private function compileQueries($xmlRootNode) + { + $output = ''; + $queriesNodes = $xmlRootNode->getElementsByTagNameNS('http://www.glizy.org/dtd/1.0/model/', 'Query'); + foreach ($queriesNodes as $node) { + $phpType = $node->hasAttribute('type') && $node->getAttribute('type') == 'function' ? true : false; + $name = $node->getAttribute('name'); + if (empty($name)) { + throw org_glizy_compilers_ModelException::queryWithoutName($this->_fileName); + } + if ( $phpType) { + $funcArguments = array('$iterator'); + $arguments = explode(',', (String)$node->getAttribute('arguments')); + foreach($arguments as $v) { + if ($v) $funcArguments[] = '$'.$v; + } + $tempOutput = 'public function query_'.$name.'('.implode($funcArguments, ',').') {'.GLZ_COMPILER_NEWLINE2; + $tempOutput .= $node->textContent.GLZ_COMPILER_NEWLINE2; + } else { + $tempOutput = 'public function querysql_'.$name.'() {'.GLZ_COMPILER_NEWLINE2; + $tempOutput .= 'return '.$this->replacePlaceholderInSql($node->textContent).GLZ_COMPILER_NEWLINE; + } + + $tempOutput .= '}'.GLZ_COMPILER_NEWLINE2; + $output .= $tempOutput; + } + + return $output; + } + + + private function compileScript($xmlRootNode) { + $output = array('model' => '', 'iterator' => ''); + $queriesNodes = $xmlRootNode->getElementsByTagNameNS('http://www.glizy.org/dtd/1.0/model/', 'Script'); + foreach ($queriesNodes as $node) { + $parent = $node->getAttribute('parent'); + if ($parent != 'model' && $parent != 'iterator') { + throw org_glizy_compilers_ModelException::scriptParentError($this->_fileName); + } + $output[$parent] .= $node->textContent; + } + + return $output; + } + + private function compileFields($xmlRootNode) + { + $output = ''; + $compositeValidators = ''; + $defineNodes = $xmlRootNode->getElementsByTagNameNS('http://www.glizy.org/dtd/1.0/model/', 'Define'); + foreach ($defineNodes as $dn ) { + $fieldNodes = $dn->getElementsByTagNameNS('http://www.glizy.org/dtd/1.0/model/', 'Field'); + foreach ($fieldNodes as $node) { + // TODO: controllare se ci sono i valori + $name = $node->hasAttribute('name') ? $node->getAttribute('name') : ''; + $type = $node->hasAttribute('type') ? $node->getAttribute('type') : ''; + $key = $node->hasAttribute('key') && $node->getAttribute('key') == 'true' ? 'true' : 'false'; + $validator = $node->hasAttribute('validator') ? $node->getAttribute('validator') : 'null'; + $value = $node->hasAttribute('defaultValue') ? $node->getAttribute('defaultValue') : ''; + $readFormat = $node->hasAttribute('readFormat') && $node->getAttribute('readFormat') == 'false' ? 'false' : 'true'; + $virtual = $node->hasAttribute('virtual') && $node->getAttribute('virtual') == 'true' ? 'true' : 'false'; + $description = $node->hasAttribute('description') ? $node->getAttribute('description') : ''; + $index = $node->hasAttribute('index') ? $node->getAttribute('index') : 0; + $onlyIndex = $node->hasAttribute('onlyIndex') ? $node->getAttribute('onlyIndex') : 0; + $option = $node->hasAttribute('option') && $node->getAttribute('option') ? $node->getAttribute('option') : null; + + // TODO impostare la lunghezza del campo in base al tipo + $type = $this->resolveFieldType($type); + $validator = $this->resolveValidator($validator, $compositeValidators); + $index = $this->resolveIndex($index); + $onlyIndex = $this->resolveOnlyIndex($onlyIndex); + + if ($onlyIndex) { + $index .= ' | '.$onlyIndex; + } + + $output .= <<<EOD +\$this->addField(new org_glizy_dataAccessDoctrine_DbField( + '$name', + $type, + 255, + $key, + $validator, + '$value', + $readFormat, + $virtual, + '$description', + $index, + '$option' + )); + +EOD; + } + } + return $compositeValidators.GLZ_COMPILER_NEWLINE2.$output.GLZ_COMPILER_NEWLINE2; + } + + + private function replacePlaceholderInSql($sql) + { + $sql = str_replace(array("\n", "\r", "'"), array(" ", " ", "\'"), $sql); + $sql = str_replace('##TABLE_NAME##', "'.\$this->getTableName().'", $sql); + $sql = str_replace('##TABLE_PREFIX##',"'.\$this->tablePrefix.'", $sql); + $sql = str_replace('##SELECT_ALL##', "'.\$this->query_all().'", $sql); + $sql = str_replace('##SITE_ID##',"'.__Config::get('SITE_ID').'", $sql); + $sql = str_replace('##USER_ID##', "'.org_glizy_ObjectValues::get('org.glizy', 'user')->id.'", $sql); + $sql = str_replace('##USER_GROUP_ID##', "'.org_glizy_ObjectValues::get('org.glizy', 'user')->group.'", $sql); + $sql = str_replace('##LANGUAGE_ID##', "'.org_glizy_ObjectValues::get('org.glizy', 'languageId').'", $sql); + $sql = str_replace('##EDITING_LANGUAGE_ID##', "'.org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId').'", $sql); + + $params = ''; + if( strstr($sql, "??") != FALSE ) + { + preg_match_all( "/\?\?([^\?]*)\?\?/U", $sql, $resmatch ); + foreach( $resmatch[1] as $varname) + { + // if ( strpos( $varname, ':' ) !== false ) + // { + // list( $filterName, $functionOrClass, $method ) = explode( ':', $varname ); + // $value = $method ? $functionOrClass.'::'.$method.'(__Request::get(\''.$filterName.'\'))' : $functionOrClass.'(__Request::get(\''.$filterName.'\'))' + // } + $sql = str_replace('??'.$varname.'??', ':'.$varname, $sql); + $params .= '\':'.$varname.'\' => __Request::get(\''.$varname.'\'),'; + } + } + + return 'array(\'sql\' =>\''.$sql.'\', \'params\' => array('.$params.'), \'filters\' => array())'; + } + + + private function resolveBaseClass($type) + { + $type = strtolower($type); + + switch ($type) { + case 'document': + return array('activeRecord' => 'org_glizy_dataAccessDoctrine_ActiveRecordDocument', + 'recordIterator' => 'org_glizy_dataAccessDoctrine_RecordIteratorDocument', + 'type' => 'document' ); + + case 'simpledocument': + return array('activeRecord' => 'org_glizy_dataAccessDoctrine_ActiveRecordSimpleDocument', + 'recordIterator' => 'org_glizy_dataAccessDoctrine_RecordIteratorSimpleDocument', + 'type' => 'document' ); + + case 'simpledocumentindexed': + return array('activeRecord' => 'org_glizycms_models_ActiveRecordSimpleDocumentArraysIndexed', + 'recordIterator' => 'org_glizy_dataAccessDoctrine_RecordIteratorSimpleDocument', + 'type' => 'document' ); + + case '2tables': + return array('activeRecord' => 'org_glizy_dataAccessDoctrine_ActiveRecord2tables', + 'recordIterator' => 'org_glizy_dataAccessDoctrine_RecordIterator2tables', + 'type' => '2tables' ); + + default: + return array('activeRecord' => 'org_glizy_dataAccessDoctrine_ActiveRecord', + 'recordIterator' => 'org_glizy_dataAccessDoctrine_RecordIterator', + 'type' => 'activeRecord' ); + break; + } + } + + + private function resolveFieldType($type) + { + $type = strtolower($type); + + switch ($type) { + case 'array': + return '\Doctrine\DBAL\Types\Type::TARRAY'; + break; + + case 'array_id': + return 'org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID'; + break; + + case 'bigint': + return '\Doctrine\DBAL\Types\Type::BIGINT'; + break; + + case 'boolean': + return '\Doctrine\DBAL\Types\Type::BOOLEAN'; + break; + + case 'date': + return '\Doctrine\DBAL\Types\Type::DATE'; + break; + + case 'datetime': + return '\Doctrine\DBAL\Types\Type::DATETIME'; + break; + + case 'datetimez': + return '\Doctrine\DBAL\Types\Type::DATETIMETZ'; + break; + + case 'time': + return '\Doctrine\DBAL\Types\Type::TIME'; + break; + + case 'decimal': + return '\Doctrine\DBAL\Types\Type::DECIMAL'; + break; + + case 'int': + case 'integer': + return '\Doctrine\DBAL\Types\Type::INTEGER'; + break; + + case 'object': + return '\Doctrine\DBAL\Types\Type::OBJECT'; + break; + + case 'smallint': + return '\Doctrine\DBAL\Types\Type::SMALLINT'; + break; + + case 'blob': + return '\Doctrine\DBAL\Types\Type::BLOB'; + break; + + case 'text': + return '\Doctrine\DBAL\Types\Type::TEXT'; + break; + + case 'float': + return '\Doctrine\DBAL\Types\Type::FLOAT'; + break; + + case 'guid': + return '\Doctrine\DBAL\Types\Type::GUID'; + break; + + case 'string': + default: + return 'Doctrine\DBAL\Types\Type::STRING'; + break; + } + } + + private function resolveValidator($validator, &$compositeValidators) + { + $validator = explode(',', strtolower($validator)); + $validatorClass = array(); + foreach ($validator as $v) { + switch ($v) { + case 'notnull': + $validatorClass[] = 'new org_glizy_validators_NotNull()'; + break; + + case 'date': + $validatorClass[] = 'new org_glizy_validators_Date()'; + break; + + case 'datetime': + $validatorClass[] = 'new org_glizy_validators_DateTime()'; + break; + + case 'numeric': + $validatorClass[] = 'new org_glizy_validators_Numeric()'; + break; + + case 'text': + $validatorClass[] = 'new org_glizy_validators_Text()'; + break; + } + } + + if (!count($validatorClass)) { + return 'null'; + } else if (count($validatorClass)==1) { + return $validatorClass[0]; + } else { + $fuid = uniqid(); + $compositeValidators .= '$fn_'.$fuid.' = function(){'.GLZ_COMPILER_NEWLINE2; + $compositeValidators .= '$v = new org_glizy_validators_CompositeValidator()'.GLZ_COMPILER_NEWLINE; + foreach($validatorClass as $v) { + $compositeValidators .= '$v->add('.$v.')'.GLZ_COMPILER_NEWLINE; + } + $compositeValidators .= 'return $v'.GLZ_COMPILER_NEWLINE; + $compositeValidators .= '}'.GLZ_COMPILER_NEWLINE; + return '$fn_'.$fuid.'()'; + } + + } + + private function resolveIndex($index) + { + $index = strtolower($index); + switch ($index) { + case 'fulltext': + return 'org_glizy_dataAccessDoctrine_DbField::FULLTEXT'; + + case 'true': + return 'org_glizy_dataAccessDoctrine_DbField::INDEXED'; + + default: + return 'org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED'; + } + } + + private function resolveOnlyIndex($onlyIndex) + { + if (strtolower($onlyIndex) == 'true') { + return 'org_glizy_dataAccessDoctrine_DbField::ONLY_INDEX'; + } + else { + return null; + } + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/compilers/ModelException.php b/src/core/classes/org/glizy/compilers/ModelException.php new file mode 100755 index 0000000..9ace08a --- /dev/null +++ b/src/core/classes/org/glizy/compilers/ModelException.php @@ -0,0 +1,26 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_compilers_ModelException extends Exception +{ + public static function missingTableName($fileName) + { + return new self('Model '.$fileName.' without tablename attribute.'); + } + + public static function queryWithoutName($fileName) + { + return new self('Model '.$fileName.' with query define without name.'); + } + + public static function scriptParentError($fileName) + { + return new self('Model '.$fileName.' Script tag with wrong parent.'); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/compilers/PageType.php b/src/core/classes/org/glizy/compilers/PageType.php new file mode 100755 index 0000000..7d18b27 --- /dev/null +++ b/src/core/classes/org/glizy/compilers/PageType.php @@ -0,0 +1,405 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_compilers_PageType extends org_glizy_compilers_Compiler +{ + var $_classSource = ''; + var $_customClassSource = ''; + var $_importedPaths = array(); + var $_className = ''; + var $_path = false; + var $mode = null; + + function compile($options) + { + $this->initOutput(); + + if ( isset( $options[ 'pathTemplate' ] ) ) + { + $fileName = $options[ 'pathTemplate' ].'/pageTypes/'.$options[ 'pageType' ]; + if ( file_exists( $fileName ) ) + { + $this->_fileName = $fileName; + } + } + if ( isset( $options[ 'mode' ] ) ) + { + $this->mode = $options[ 'mode' ]; + } + + $pageXml = org_glizy_ObjectFactory::createObject( 'org.glizy.parser.XML' ); + if ($this->_fileName) { + $pageXml->loadAndParseNS( $this->_fileName ); + } else { + throw new Exception( 'PageType not found '.$options[ 'pageType' ] ); + } + $pageRootNode = $pageXml->documentElement; + $registredNameSpaces = $pageXml->namespaces; + $registredNameSpaces['glz'] = 'org.glizy.components'; + // $idPrefix = isset($options['idPrefix']) ? $options['idPrefix'] : ''; + $this->_path = $options['path']; + + // include i componenti usati + foreach ($registredNameSpaces as $key=>$value) + { + if ($key!='glz' && substr($value, -1, 1)=='*' && !in_array($value, $this->_importedPaths)) + { + glz_loadLocale($value); + $this->output .= 'glz_loadLocale(\''.$value.'\')'.GLZ_COMPILER_NEWLINE; + $this->_importedPaths[] = $value; + } + } + + $this->_className = glz_basename($this->_cacheObj->getFileName()); + $this->_classSource .= 'class '.$this->_className.'{'.GLZ_COMPILER_NEWLINE2; + $this->_classSource .= 'function '.$this->_className.'(&$application, $skipImport=false, $idPrefix=\'\') {'.GLZ_COMPILER_NEWLINE2; + $this->_classSource .= '$mode = "'.$this->mode.'"'.GLZ_COMPILER_NEWLINE; + $counter = 0; + $this->_compileXml($pageRootNode, $registredNameSpaces, $counter, '$application', ''); + $this->_classSource .= '}'.GLZ_COMPILER_NEWLINE2; + $this->_classSource .= '}'.GLZ_COMPILER_NEWLINE2; + + $this->output .= $this->_classSource; + $this->output .= $this->_customClassSource; + + return $this->save(); + } + + + function _compileXml(&$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix='', $idPrefixOriginal='') + { + if ($node->nodeType == XML_COMMENT_NODE) return; + + $componentObj = null; + $componentClassInfo = $this->_getComponentClassInfo($node->nodeName, $registredNameSpaces); + if (!empty($componentClassInfo['classPath']) && !in_array($componentClassInfo['classPath'], $this->_importedPaths)) + { + $this->_importedPaths[] = $componentClassInfo['classPath']; + } + $compileTranslateMethod = null; + $compileMethod = null; + $compileMethodAddPrefix = null; + if (class_exists($componentClassInfo['className'])) + { + try { + $compileTranslateMethod = new ReflectionMethod( $componentClassInfo['className'].'::translateForMode_'.$this->mode ); + if (!$compileTranslateMethod->isStatic()) $compileTranslateMethod = null; + } catch (Exception $e) {} + try { + $compileMethod = new ReflectionMethod( $componentClassInfo['className'].'::compile' ); + if (!$compileMethod->isStatic()) $compileMethod = null; + } catch (Exception $e) {} + try { + $compileMethodAddPrefix = new ReflectionMethod( $componentClassInfo['className'].'::compileAddPrefix' ); + if (!$compileMethodAddPrefix->isStatic()) $compileMethodAddPrefix = null; + } catch (Exception $e) {} + } + + if ($compileTranslateMethod) { + $newNodeXml = $compileTranslateMethod->invoke(null, $node); + if ($newNodeXml) { + $partXml = org_glizy_ObjectFactory::createObject( 'org.glizy.parser.XML' ); + $partXml->loadXmlAndParseNS( $newNodeXml , LIBXML_NOERROR ); + $newNode = $partXml->documentElement; + $this->addNamespace($partXml->namespaces, $registredNameSpaces); + $this->_compileXml($newNode, $registredNameSpaces, $counter, $parent, $idPrefix, $idPrefixOriginal); + $oldcounter = $counter; + + if (strpos($newNodeXml, 'noChild="true"')===false) { + $this->compileChildren($node, $registredNameSpaces, $counter, $oldcounter, $idPrefix, $idPrefixOriginal ); + } + } + return; + } + + // sostituisce i caratteri speciali all'interno del nome del tag + // per poter verificare se � stato deifnito un metodo aaposito + // per compilare il tag + $methodName = 'compile_'.preg_replace('/[\-\#\:]/', '', $node->nodeName); + if (method_exists($this, $methodName)) + { + $this->$methodName($node, $registredNameSpaces, $counter, $parent, $idPrefix); + return; + } + else + { + $this->_classSource .= '// TAG: '.$node->nodeName.GLZ_COMPILER_NEWLINE2; + $componentId = $node->hasAttribute( 'id' ) ? $node->getAttribute( 'id' ) : 'c'.md5(uniqid(rand(), true)); + $componentIdPrefix = $idPrefix; + $compileOnlyChild = false; + + if ($compileMethod) { + $r = $compileMethod->invoke(null, $this, $node, $registredNameSpaces, $counter, $parent, $idPrefix, $componentClassInfo, $componentId ); + if ($r!==true) { + // non ha figli + return true; + } + $compileOnlyChild = true; + } + if (!$compileOnlyChild) { + if ($compileMethodAddPrefix) { + $componentIdPrefix = $compileMethodAddPrefix->invoke(null, $this, $node, $componentId, $idPrefix); + } + + $this->_classSource .= '$n'.$counter.' = &org_glizy_ObjectFactory::createComponent(\''.$componentClassInfo['classPath'].'\', $application, '.$parent.', \''.$node->nodeName.'\', $idPrefix.'.$idPrefix.'\''.$componentId.'\', '.$idPrefixOriginal.'\''.$componentId.'\', $skipImport, $mode)'.GLZ_COMPILER_NEWLINE; + + if ($parent!='NULL') + { + $this->_classSource .= $parent.'->addChild($n'.$counter.')'.GLZ_COMPILER_NEWLINE; + } + + if (count($node->attributes)) + { + // compila gli attributi + $this->_classSource .= '$attributes = array('; + foreach ( $node->attributes as $index=>$attr ) + { + if ($attr->name!='id') + { + // NOTA: su alcune versioni di PHP (es 5.1) empty( $attr->prefix ) non viene valutato in modo corretto + $prefix = $attr->prefix == "" || is_null( $attr->prefix ) ? "" : $attr->prefix.":"; + $this->_classSource .= '\''.$prefix.$attr->name.'\' => \''.str_replace('\'', '\\\'', $attr->value).'\', '; + } + } + + $this->_classSource .= ')'.GLZ_COMPILER_NEWLINE; + $this->_classSource .= '$n'.$counter.'->setAttributes( $attributes )'.GLZ_COMPILER_NEWLINE; + } + } + $idPrefix = $componentIdPrefix; + $oldcounter = $counter; + $this->compileChildren($node, $registredNameSpaces, $counter, $oldcounter, $idPrefix ); + } + } + + function compileChildren(&$node, &$registredNameSpaces, &$counter, $oldcounter='NULL', $idPrefix='') { + foreach( $node->childNodes as $nc ) + { + $counter++; + $this->_compileXml($nc, $registredNameSpaces, $counter, '$n'.$oldcounter, $idPrefix); + } + + if ( $node->hasAttribute( 'allowModulesSnippets' ) && $node->getAttribute( 'allowModulesSnippets' ) == "true") + { + $modulesState = org_glizy_Modules::getModulesState(); + $modules = org_glizy_Modules::getModules(); + + foreach( $modules as $m ) + { + $isEnabled = !isset( $modulesState[ $m->id ] ) || $modulesState[ $m->id ]; + if ( $isEnabled && $m->pluginInPageType && $m->pluginSnippet ) + { + $counter++; + $this->compile_glzinclude( $m->pluginSnippet, $registredNameSpaces, $counter, '$n'.$oldcounter, $idPrefix ); + } + } + } + } + + function compileChildNode(&$node, &$registredNameSpaces, &$counter, $oldcounter='NULL', $idPrefix='') + { + $this->_compileXml($node, $registredNameSpaces, $counter, '$n'.$oldcounter, $idPrefix); + } + + function _getComponentClassInfo($componentName, &$registredNameSpaces) + { + $result = array('className' => '', 'classPath' => ''); + $componentClassName = explode(':', $componentName); + if (count($componentClassName)==2) + { + $nameSpace = $componentClassName[0]; + $componentClassName = $componentClassName[1]; + if (array_key_exists($nameSpace, $registredNameSpaces)) + { + if ($registredNameSpaces[$nameSpace]!='*') + { + $componentClassName = rtrim($registredNameSpaces[$nameSpace], '.*').'.'.$componentClassName; + } + $result['classPath'] = $componentClassName; + $componentClassName = str_replace('*', '', $componentClassName); + $componentClassName = str_replace('.', '_', $componentClassName); + $result['className'] = $componentClassName; + } + else + { + // TODO + // namespace non definito + // visualizzare un errore + + } + } + else + { + $result['className'] = $componentName; + } + return $result; + } + + function compile_cdatasection(&$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix='') + { + $this->compile_text($node, $registredNameSpaces, $counter, $parent); + } + + function compile_text(&$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix='') + { + $this->_classSource .= '$tagContent = <<<EOD'.GLZ_COMPILER_NEWLINE2; + $this->_classSource .= str_replace('$', '\$', $node->nodeValue).GLZ_COMPILER_NEWLINE2; + $this->_classSource .= 'EOD'.GLZ_COMPILER_NEWLINE; + $this->_classSource .= $parent.'->setContent($tagContent)'.GLZ_COMPILER_NEWLINE; + } + + + function compile_glzif(&$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix='') + { + $condition = $node->getAttribute( "condition" ); + $condition = str_replace( array( '$application.', '$user.' ), array( '$application->', '$application->getCurrentUser()->' ), $condition ); + $this->_classSource .= 'if ('.$condition.') {'.GLZ_COMPILER_NEWLINE2; + foreach( $node->childNodes as $nc ) + { + $this->_compileXml($nc, $registredNameSpaces, $counter, $parent, $idPrefix); + } + $this->_classSource .= '} // end if'.GLZ_COMPILER_NEWLINE2; + } + + + function compile_glztemplateDefine(&$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix='') + { + } + + function compile_glzinclude(&$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix='') + { + $origSrc = is_object( $node ) ? $node->getAttribute( 'src' ) : $node; + $src = $origSrc; + if ( strpos( $src, '.xml' ) === false ) + { + $src .= '.xml'; + } + if ( file_exists( dirname( $this->_fileName ).'/'.$src ) ) + { + $src = dirname( $this->_fileName ).'/'.$src; + } + else + { + $src = glz_findClassPath( $origSrc ); + } + if ( is_null( $src ) ) + { + die( '[ERROR] glz:include file not found: '.$node->getAttribute( 'src' ) ); + } + $this->_classSource .= '// include: '.$src.GLZ_COMPILER_NEWLINE2; + + + $srcXml = file_get_contents($src); + // esegue il parsing per sapere quale sono i parametri del template e ricavare quelli di default + $templateParams = array(); + $includeXML = org_glizy_ObjectFactory::createObject( 'org.glizy.parser.XML' ); + $includeXML->loadXmlAndParseNS( $srcXml ); + $templateDefineNodes = $includeXML->getElementsByTagName('templateDefine'); + foreach ($templateDefineNodes as $templateDefine) { + if (!$templateDefine->hasAttribute('name')) { + throw org_glizy_compilers_PageTypeException::templateDefineNotValid($src); + } + $templateParams[$templateDefine->getAttribute('name')] = $templateDefine->hasAttribute('required') && $templateDefine->getAttribute('required')=='true' ? null : + ( $templateDefine->hasAttribute('defaultValue') ? $templateDefine->getAttribute('defaultValue') : ''); + + } + + if (count($templateParams)) { + $templateParamsKeys = array_keys($templateParams); + foreach( $node->childNodes as $nc ) { + if ($nc->tagName=='glz:template' && $nc->hasAttribute('name')) { + $name = $nc->getAttribute('name'); + if (!in_array($name, $templateParamsKeys)) { + throw org_glizy_compilers_PageTypeException::templateDefinitionDontExixts($name); + } + + $value = ''; + if ($nc->hasAttribute('value')) { + $value = $nc->getAttribute('value'); + } else { + $tempDom = new DOMDocument(); + foreach( $nc->childNodes as $ncc ) { + $tempDom->appendChild($tempDom->importNode($ncc,true)); + } + $value = $tempDom->saveXML(); + $value = str_replace('<?xml version="1.0"?>', '', $value); + } + + $templateParams[$name] = $value; + } + } + + foreach($templateParams as $k=>$v) { + if (is_null($v)) { + throw org_glizy_compilers_PageTypeException::templateDefinitionRequired($k, $src); + } + $srcXml = str_replace( '##'.$k.'##', $v, $srcXml ); + } + } + + $includeXML = org_glizy_ObjectFactory::createObject( 'org.glizy.parser.XML' ); + $includeXML->loadXmlAndParseNS( $srcXml ); + $newNameSpaces = $includeXML->namespaces; + $this->addNamespace($newNameSpaces, $registredNameSpaces); + if ( $includeXML->documentElement->hasAttribute( 'adm:editComponents' ) ) + { + $this->_classSource .= '$n0->setAttribute( "adm:editComponents", "'.$includeXML->documentElement->getAttribute( 'adm:editComponents' ).'" )'.GLZ_COMPILER_NEWLINE; + } + + $this->_compileXml($includeXML->documentElement, $registredNameSpaces, $counter, $parent, $idPrefix); + } + + function compile_baseTag(&$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix, $componentClassInfo, $componentId) + { + $this->_classSource .= '$n'.$counter.' = &org_glizy_ObjectFactory::createComponent(\''.$componentClassInfo['classPath'].'\', $application, '.$parent.', \''.$node->nodeName.'\', $idPrefix.'.$idPrefix.'\''.$componentId.'\', \''.$componentId.'\', $skipImport)'.GLZ_COMPILER_NEWLINE; + + if ($parent!='NULL') + { + $this->_classSource .= $parent.'->addChild($n'.$counter.')'.GLZ_COMPILER_NEWLINE; + } + + if (count($node->attributes)) + { + // compila gli attributi + $this->_classSource .= '$attributes = array('; + foreach ( $node->attributes as $index=>$attr ) + { + if ($attr->name!='id') + { + // NOTA: su alcune versioni di PHP (es 5.1) empty( $attr->prefix ) non viene valutato in modo corretto + $prefix = $attr->prefix == "" || is_null( $attr->prefix ) ? "" : $attr->prefix.":"; + $this->_classSource .= '\''.$prefix.$attr->name.'\' => \''.addslashes($attr->value).'\', '; + } + } + + $this->_classSource .= ')'.GLZ_COMPILER_NEWLINE; + $this->_classSource .= '$n'.$counter.'->setAttributes( $attributes )'.GLZ_COMPILER_NEWLINE; + } + } + + function getPath() + { + return $this->_path; + } + + private function addNamespace($newNameSpaces, &$registredNameSpaces) + { + foreach ($newNameSpaces as $key=>$value) + { + if ( isset( $registredNameSpaces[ $key ] ) ) continue; + + if ($key!='glz' && substr($value, -1, 1)=='*' && !in_array($value, $this->_importedPaths)) + { + $this->_importedPaths[] = $value; + } + $registredNameSpaces[ $key ] = $value; + } + } +} diff --git a/src/core/classes/org/glizy/compilers/PageTypeException.php b/src/core/classes/org/glizy/compilers/PageTypeException.php new file mode 100644 index 0000000..a0e2516 --- /dev/null +++ b/src/core/classes/org/glizy/compilers/PageTypeException.php @@ -0,0 +1,27 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_compilers_PageTypeException extends Exception +{ + public static function templateDefineNotValid($src) + { + return new self('The template define tag must have name attribute, file: '.$src); + } + + public static function templateDefinitionDontExixts($name) + { + return new self('The template definition don\'t exixts: '.$name); + } + + public static function templateDefinitionRequired($name, $src) + { + return new self('The template definition "'.$name.'" is required, file: '.$src); + } +} diff --git a/src/core/classes/org/glizy/compilers/Routing.php b/src/core/classes/org/glizy/compilers/Routing.php new file mode 100755 index 0000000..4072c3d --- /dev/null +++ b/src/core/classes/org/glizy/compilers/Routing.php @@ -0,0 +1,281 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_compilers_Routing + */ +class org_glizy_compilers_Routing extends org_glizy_compilers_Compiler +{ + private $language; + private $prog; + + /** + * + */ + function compile($options) + { + $this->addEventListener(GLZ_EVT_LISTENER_COMPILE_ROUTING, $this); + $this->initOutput(); + + if ( __Config::get( 'MULTILANGUAGE_ENABLED' ) ) + { + $this->language = '{language}/'; + } + + $evt = array('type' => GLZ_EVT_START_COMPILE_ROUTING); + $this->dispatchEvent($evt); + + if ( strpos( $this->_fileName, 'routing.xml') !== false ) + { + $modules = org_glizy_Modules::getModules(); + foreach( $modules as $m ) + { + $path = glz_findClassPath( $m->classPath ); + if ( !is_null( $path ) && file_exists( $path . '/config/routing.xml' ) ) + { + $this->compileFile( $path . '/config/routing.xml' ); + } + } + } + + $this->compileFile( $this->_fileName ); + return $this->save(); + } + + /** + * @param $fileName + */ + function compileFile( $fileName ) + { + /** @var org_glizy_parser_XML $xml */ + $xml = org_glizy_ObjectFactory::createObject( 'org.glizy.parser.XML' ); + $xml->loadAndParseNS( $fileName ); + $this->compileXml($xml); + } + + /** + * @param $xmlString + */ + function compileString($xmlString) + { + $xml = org_glizy_ObjectFactory::createObject( 'org.glizy.parser.XML' ); + $xml->loadXmlAndParseNS($xmlString); + $this->compileXml($xml); + } + + /** + * @param org_glizy_parser_XML $xml + */ + private function compileXml($xml, $prefix='', $middleware='') + { + if ($xml->hasChildNodes()) { + $this->prog = 0; + + foreach ($xml->childNodes as $node) { + if ( $node->nodeName == "glz:Routing" ) { + $this->compileXml($node, $prefix, $middleware); + } else if ( $node->nodeName == "glz:Route" ) { + $this->compileRouteNode($node, $prefix, $middleware); + } else if ( $node->nodeName == "glz:RouteGroup" ) { + if (!$node->hasAttribute('value') || $node->getAttribute('value')=='') { + throw new Exception('glz:RouteGroup need value attribute'); + } + $this->compileXml($node, $prefix.$node->getAttribute('value'), $middleware); + } else if ( $node->nodeName == "glz:Middleware" ) { + if (!$node->hasAttribute('class') || $node->getAttribute('class')=='') { + throw new Exception('glz:Middleware need class attribute'); + } + $this->compileXml($node, $prefix, $node->getAttribute('class')); + } + } + } + } + + /** + * @param DOMElement $xml + * @param String $prefix + * @param String $middleware + */ + private function compileRouteNode($param, $prefix='', $middleware='') + { + $this->prog++; + $name = strtolower( $param->getAttribute('name') ); + if ( empty( $name ) ) + { + $name = (string)$this->prog; + $name = $param->hasAttribute('method') ? strtolower( $param->getAttribute('method') ).'_'.$name : $name; + } + + // controlla se il nodo ha dei figli + if ( $param->hasChildNodes() ) + { + $this->output .= '$configArray["'.$name.'"] = array()'.GLZ_COMPILER_NEWLINE; + + foreach( $param->childNodes as $node ) + { + if ( $node->nodeName == "glz:RouteCondition" ) + { + $this->compileNode($node, $name, true, $prefix, $middleware); + } + } + } + else + { + $this->compileNode($param, $name, false, $prefix, $middleware); + } + } + + /** + * @param DOMElement $param + * @param $name + * @param bool $child + */ + private function compileNode( &$param, $name, $child, $prefix, $middleware ) + { + $value = $param->hasAttribute('value') ? $param->getAttribute('value') : $param->firstChild->nodeValue; + $value = !$param->hasAttribute('method') && !$param->hasAttribute('skipLanguage') ? $this->language.$prefix.$value : $prefix.$value; + $parseUrl = $param->hasAttribute('parseUrl') ? $param->getAttribute('parseUrl') : 'true'; + $keyName = $param->hasAttribute('keyName') ? $param->getAttribute('keyName') : ''; + $keyValue = $param->hasAttribute('keyValue') ? $param->getAttribute('keyValue') : ''; + $method = $param->hasAttribute('method') ? strtolower( $param->getAttribute('method') ) : ''; + $child = $child ? '[]' : ''; + + $urlPattern = ''; + $urlValues = array(); + $staticValues = array(); + if ($middleware) { + $staticValues['__middleware__'] = $middleware; + } + if ( $parseUrl == 'true' ) + { + $attributeToSkip = array( 'name', 'value', 'parseUrl', 'keyValue', 'keyValue' ); + foreach ( $param->attributes as $index=>$attr ) + { + // NOTA: su alcune versioni di PHP (es 5.1) empty( $attr->prefix ) non viene valutato in modo corretto + $prefix = $attr->prefix == "" || is_null( $attr->prefix ) ? "" : $attr->prefix.":"; + $attrName = $prefix.$attr->name; + if ( !in_array( $attrName, $attributeToSkip ) ) + { + $staticValues[ $attrName ] = $attr->value; + } + } + + /** @var org_glizy_application_Application $application */ + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $siteMap = &$application->getSiteMap(); + $isApplicationDB = $siteMap && $siteMap->getType() == 'db'; + + $urlPattern = str_replace('/', '\/', $value ); + preg_match_all("|\{(.*)\}|U", $urlPattern, $match, PREG_PATTERN_ORDER); + for($i=0; $i<count($match[0]); $i++) + { + $command = explode('=', $match[1][$i]); + $urlValuesKey = $command[count($command)-1]; + switch ($command[0]) + { + case 'language': + $urlPartValue = '(.{2})'; + break; + case '*': + case 'currentMenu': + $urlPartValue = '(.*)'; + $urlValuesKey = 'pageId'; + break; + case 'pageId': + if (count($command)>1 && is_object( $siteMap ) ) + { + if (is_numeric($command[1])) + { + $page = $siteMap->getNodeById($command[1]); + } + else + { + $page = $siteMap->getMenuByPageType($command[1]); + if ( is_null( $page ) ) + { + $module = org_glizy_Modules::getModule( $command[1] ); + if ( !is_null( $module ) && $module->pageType ) + { + $page = $siteMap->getMenuByPageType( $module->pageType ); + } + } + } + + if ( $isApplicationDB ) + { + $urlPartValue = strtolower('('.$page->id.'\/[^\/]*?)'); + } + else + { + $urlPartValue = strtolower('('.str_replace('/', '\/', $page->id).')'); + } + } + else + { + $urlPartValue = '([^\/]*)'; + } + $urlValuesKey = $command[0]; + break; + case 'pageTitle': + $urlPartValue = '([^\/]*)'; + break; + case 'value': + $urlPartValue = '([^\/]*)'; + break; + case 'integer': + $urlPartValue = '(\d*)'; + break; + case 'static': + $urlPartValue = ''; + $urlValuesKey = $command[1]; + break; + case 'state': + $urlPartValue = '('.$command[1].')'; + $urlValuesKey = $command[0]; + break; + case 'config': + $urlPartValue = ''; + $urlValuesKey = ''; + break; + default: + $urlPartValue = '('.(count($command) > 1 ? $command[1] : $command[0]).')'; + $urlValuesKey = $command[0]; + break; + } + + + if (empty($urlPartValue)) + { + $urlPattern = str_replace(array( $match[0][$i].'\/', $match[0][$i] ) , '()', $urlPattern); + $urlValues[$urlValuesKey] = $command[2]; + continue; + } + $urlValues[$urlValuesKey] = ''; + $urlPattern = str_replace($match[0][$i], $urlPartValue, $urlPattern); + if (strpos($urlPattern, '#')!==false) { + list($urlPattern) = explode('#', $urlPattern); + } + } + + $urlPattern = rtrim( $urlPattern, '\/' ); + $urlPattern = '|^'.$urlPattern.'(\/?)$|i'; + } + + $this->output .= '$configArray["'.$name.'"]'.$child.' = array("value" => "'.addslashes($value).'", "urlPattern" => "'.addcslashes($urlPattern, '"\\' ).'", "urlValues" => "'.addcslashes( serialize( $urlValues ), '"\\' ).'", "staticValues" => "'.addcslashes( serialize( $staticValues ), '"\\' ).'", "parseUrl" => '.$parseUrl.', "keyName" => "'.$keyName.'", "keyValue" => "'.$keyValue.'", "method" => "'.$method.'" )'.GLZ_COMPILER_NEWLINE; + } + + /** + * @param $evt + */ + public function listenerCompileRouting($evt) + { + $xmlString = $evt->data; + $this->compileString($xmlString); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/compilers/Skin.php b/src/core/classes/org/glizy/compilers/Skin.php new file mode 100755 index 0000000..959e4fd --- /dev/null +++ b/src/core/classes/org/glizy/compilers/Skin.php @@ -0,0 +1,45 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_compilers_Skin extends org_glizy_compilers_Compiler +{ + function compile( $options ) + { + $this->_cacheObj->save($options['defaultHtml']); + return $this->_cacheObj->getFileName(); + } + + /** + * Verifica se il file è compilato, in casi affermativo restutuisce il path + */ + function verify($fileName, $options=NULL) + { + $cacheFileName = $fileName; + if (!empty($options['defaultHtml'])) + { + // memorizza la skin di defaul del componente + // come file in cache per poi passarlo al template engine + $cacheFileName = $this->_cacheObj->verify($fileName, get_class($this)); + if ($cacheFileName===false) + { + $this->_fileName = $fileName; + $cacheFileName = $this->compile( $options ); + if ($cacheFileName===false) + { + // TODO + echo "FATAL ERROR ".$fileName; + } + } + } + + return $cacheFileName; + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Authenticator.php b/src/core/classes/org/glizy/components/Authenticator.php new file mode 100755 index 0000000..0264682 --- /dev/null +++ b/src/core/classes/org/glizy/components/Authenticator.php @@ -0,0 +1,69 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Authenticator extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('accessPageId', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('logoutPageId', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, 'Logout', COMPONENT_TYPE_STRING); + $this->defineAttribute('allowGroups', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('showErrorMessage', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('checkAcl', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('icon', false, 'icon-signout', COMPONENT_TYPE_STRING); + + parent::init(); + } + + + function process() + { + $allowGroups = $this->getAttribute('allowGroups')!='' ? explode(',', $this->getAttribute('allowGroups')) : array(); + + if ( ( !org_glizy_Session::get('glizy.userLogged') || !(count($allowGroups) ? in_array($this->_user->groupId, $allowGroups) : true) ) && $this->getAttribute( 'enabled' ) ) + { + if (org_glizy_helpers_Link::scriptUrl() != org_glizy_helpers_Link::makeUrl('link', array('pageId' => org_glizy_Config::get('START_PAGE')))) + { + if ( $this->getAttribute( 'showErrorMessage' ) ) + { + org_glizy_Session::set('glizy.loginError', org_glizy_locale_Locale::get('GLZ_LOGIN_NOACCESS')); + } + org_glizy_Session::set('glizy.loginUrl', __Request::get('__url__')); + } + org_glizy_helpers_Navigation::gotoUrl(org_glizy_helpers_Link::makeUrl('link', array('pageId' => $this->getAttribute('accessPageId')))); + exit; + } + + if ($this->getAttribute('checkAcl') && !$this->_user->acl($this->_application->getPageId(), 'visible')) { + header('HTTP/1.0 403 Forbidden'); + exit(); + } + } + + function render_html() + { + if ( $this->getAttribute( 'logoutPageId' ) ) + { + $output = org_glizy_helpers_Link::makeLink('link', array( 'pageId' => $this->getAttribute('logoutPageId'), + 'title' => $this->getAttribute( 'label' ), + 'cssClass' => $this->getAttribute( 'cssClass' ), + 'icon' => $this->getAttribute( 'icon' )) ); + $this->addOutputCode($output); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Breadcrumbs.php b/src/core/classes/org/glizy/components/Breadcrumbs.php new file mode 100755 index 0000000..b207a03 --- /dev/null +++ b/src/core/classes/org/glizy/components/Breadcrumbs.php @@ -0,0 +1,115 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Breadcrumbs extends org_glizy_components_Component +{ + private $extraItem = null; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('label', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('separator', false, ' &gt; ', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssCurrent', false, 'current', COMPONENT_TYPE_STRING); + $this->defineAttribute('menuId', false, NULL, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + + $this->addEventListener(GLZ_EVT_BREADCRUMBS_UPDATE, $this); + $this->addEventListener(GLZ_EVT_SITEMAP_UPDATE, $this); + } + + function process() + { + $this->_content = new org_glizy_components_BreadcrumbsVO(); + $this->_content->label = $this->getAttribute('label'); + $this->_content->separator = $this->getAttribute('separator'); + $this->_content->cssClass = $this->getAttribute('cssClass'); + $menuId = $this->getAttribute('menuId'); + $siteMap = &$this->_application->getSiteMap(); + $currentMenu = is_null($menuId) ? $this->_application->getCurrentMenu() : $siteMap->getNodeById($menuId); + + if ($this->extraItem) { + array_unshift($this->_content->records, '<span class="'.$this->getAttribute('cssCurrent').'">'.$this->extraItem.'</span>'); + } + + while (true) + { + if ($currentMenu->type!='SYSTEM') + { + $nodeTitle = empty($currentMenu->titleLink) ? $currentMenu->title : $currentMenu->titleLink; + $nodeDescription = empty($currentMenu->linkDescription) ? $nodeTitle: $currentMenu->linkDescription; + if (count($this->_content->records)) + { + if (empty($currentMenu->url)) + { + array_unshift($this->_content->records, org_glizy_helpers_Link::makeLink('link', array('pageId' => $currentMenu->id, 'title' => $nodeDescription, 'label' => $nodeTitle))); + } + else + { + array_unshift($this->_content->records, org_glizy_helpers_Link::makeSimpleLink($nodeTitle, $currentMenu->url, $nodeDescription)); + } + } + else + { + array_unshift($this->_content->records, '<span class="'.$this->getAttribute('cssCurrent').'">'.$nodeTitle.'</span>'); + } + } + if ($currentMenu->parentId===0 || !$currentMenu->parentId) break; + $tempNode = &$currentMenu->parentNode(); + $currentMenu = &$tempNode; + } + } + + + function siteMapUpdate($event) + { + if (!is_null($event->data)) { + $this->setAttribute('menuId', $event->data); + } + $this->process(); + } + + function onBreadcrumbsUpdate($event) + { + $this->extraItem = $event->data; + $this->process(); + } +} + +class org_glizy_components_BreadcrumbsVO +{ + var $separator = ''; + var $label = ''; + var $cssClass = ''; + var $records = array(); +} + + +class org_glizy_components_Breadcrumbs_render extends org_glizy_components_render_Render +{ + function getDefaultSkin() + { + $skin = <<<EOD +<ul tal:condition="php: count(Component.records)"> + <li tal:condition="Component/label" tal:content="Component/label" /> + <li tal:repeat="item Component/records"><span tal:omit-tag="" tal:content="structure item" /><span tal:condition="not: repeat/item/end" tal:content="structure Component/separator" /></li> +</ul> +EOD; + return $skin; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Button.php b/src/core/classes/org/glizy/components/Button.php new file mode 100755 index 0000000..5ccd426 --- /dev/null +++ b/src/core/classes/org/glizy/components/Button.php @@ -0,0 +1,97 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Button extends org_glizy_components_HtmlComponent +{ + var $_targetForm; + var $_action; + var $_name; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('action', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('actionType',false, 'command', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('confirmMessage', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('disabled', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('value', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('target', false, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('type', false, 'button', COMPONENT_TYPE_STRING); + $this->defineAttribute('url', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + $this->_action = $this->getAttribute('action'); + $url = $this->getAttribute('url'); + $this->_name = $this->getId(); + if (!empty($this->_action)) + { + $this->_targetForm = $this->getAttribute('target'); + if (!is_null($this->_targetForm)) + { + switch ($this->getAttribute('actionType')) + { + case 'location': + $this->_action = 'location.href='.$this->_targetForm->getJSAction($this->_action); + break; + case 'action': + $this->_action = 'this.form.action='.$this->_targetForm->getJSAction($this->_action); + break; + case 'command': + $this->_action = $this->_targetForm->getJSAction($this->_action); + break; + case 'url': + $this->_action = 'location.href='.$this->_targetForm->getJSAction($this->_action, true); + break; + //case 'submit': + // $this->_name = $this->_targetForm->getId().'_command'; + } + } + } + else if (!empty($url)) + { + $this->_action = 'location.href=\''.$this->getAttribute('url').'\''; + } + + if (!is_null($this->getAttribute('confirmMessage'))) + { + $this->_action = 'if (confirm(\''.$this->getAttribute('confirmMessage').'\')) '.$this->_action.'; else return false;'; + } + } + + function render() + { + $this->applyOutputFilters('pre', $this->_content); + + if ($this->getAttribute('type')=='reset' && $this->getAttribute('actionType') != 'location' ) $this->setAttribute('type', 'submit'); + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['name'] = $this->_name; + $attributes['disabled'] = $this->getAttribute('disabled') ? 'disabled' : ''; + $attributes['class'] = $this->getAttribute('cssClass'); + $attributes['type'] = $this->getAttribute('type'); + $attributes['value'] = $this->encodeOuput($this->getAttribute('value')); + $attributes['onclick'] = $this->_action; + + $output = '<input '.$this->_renderAttributes($attributes).' />'; + $this->addOutputCode($output); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/CSS.php b/src/core/classes/org/glizy/components/CSS.php new file mode 100755 index 0000000..42a12d1 --- /dev/null +++ b/src/core/classes/org/glizy/components/CSS.php @@ -0,0 +1,119 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_CSS extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + parent::init(); + + // define the custom attributes + $this->defineAttribute('src', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('folder', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('inline', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('editableRegion', false, 'head', COMPONENT_TYPE_STRING); + } + + /** + * Render + * + * @return void + * @access public + */ + function render_html() + { + $folder = $this->getAttribute('folder'); + $src = $this->getAttribute('src'); + $region = $this->getAttribute('editableRegion'); + if ( $folder ) + { + // include tutta una cartella + $cssFileName = $this->includeFolder( $folder ); + if ( $this->getAttribute('inline')) { + $css = file_get_contents($cssFileName); + if ( strpos($css, '<style') !== false ) { + $this->addOutputCode( $css, $region ); + } else { + $this->addOutputCode( org_glizy_helpers_CSS::CSScode( $css ), $region ); + } + } else { + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $cssFileName), $region ); + } + } + else + { + if (!is_null($src)) + { + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $this->getAttribute('src') ), $region ); + } + else + { + $this->addOutputCode( org_glizy_helpers_CSS::CSScode( $this->getText() ), $region ); + } + } + } + + private function includeFolder( $folder ) + { + // controlla se il file in cache è valido + $options = array( + 'cacheDir' => org_glizy_Paths::get('CACHE_CODE'), + 'lifeTime' => org_glizy_Config::get('CACHE_CODE'), + 'readControlType' => '', + 'fileExtension' => '.css' + ); + + $cacheSignature = get_class( $this ).$folder; + $cacheObj = org_glizy_ObjectFactory::createObject( 'org.glizy.cache.CacheFile', $options ); + $cssFileName = $cacheObj->verify( $cacheSignature ); + + if ($cssFileName===false) + { + $cssFile = ''; + + if ($dir_handle = @opendir($folder)) + { + while ($file_name = readdir($dir_handle)) + { + if ($file_name!="." && + $file_name!=".." && + !is_dir("$dir/$file_name") ) + { + $f[]=$file_name; + } + } + sort($f); + closedir($dir_handle); + foreach ($f as $element) + { + $cssCode = file_get_contents( $folder.'/'.$element ); + $cssFile .= $cssCode."\n"; + } + } + + if ( __Config::get( 'DEBUG' ) !== false ) + { + $cacheObj->save( $cssFile, NULL, get_class($this) ); + } + else + { + $cacheObj->save( $cssFile, NULL, $cacheSignature ); + } + $cssFileName = $cacheObj->getFileName(); + } + return $cssFileName; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Caption.php b/src/core/classes/org/glizy/components/Caption.php new file mode 100755 index 0000000..204560f --- /dev/null +++ b/src/core/classes/org/glizy/components/Caption.php @@ -0,0 +1,48 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + + +class org_glizy_components_Caption extends org_glizy_components_Component +{ + var $_caption = NULL; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('accesskey', false, NULL, COMPONENT_TYPE_STRING); // TODO + $this->defineAttribute('crop', false, NULL, COMPONENT_TYPE_STRING); // TODO + $this->defineAttribute('image', false, NULL, COMPONENT_TYPE_STRING); // TODO + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('tabindex', false, NULL, COMPONENT_TYPE_INTEGER); // TODO + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + $this->_content = $this->getAttribute('label'); + } + + function render_html() + { + if (!is_null($this->_content)) + { + $output = '<legend>'.$this->_content.'</legend>'; + $this->addOutputCode($output); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Checkbox.php b/src/core/classes/org/glizy/components/Checkbox.php new file mode 100755 index 0000000..1ea3cc3 --- /dev/null +++ b/src/core/classes/org/glizy/components/Checkbox.php @@ -0,0 +1,103 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Checkbox extends org_glizy_components_HtmlFormElement +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('bindTo', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClassLabel', false, __Config::get('glizy.formElement.cssClassLabel'), COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('value', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('defaultValue', false, '0', COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapLabel', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('title', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('checkedValue', false, '1', COMPONENT_TYPE_STRING); + $this->defineAttribute('data', false, 'type=checkbox', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_content = $this->getAttribute('value'); + if (is_object($this->_content)) + { + $contentSource = &$this->getAttribute('value'); + $this->_content = $contentSource->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + else if (is_null($this->_content)) + { + // richiede il contenuto al padre + $this->_content = $this->_parent->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + + + if (is_null($this->_content) || $this->_content=='') + { + // imposta il valore di default + $this->_content = $this->getAttribute('defaultValue'); + } + } + + function render_html() + { + $output = ''; + $attributes = $this->getContent(true); + $output = '<input '.$this->_renderAttributes($attributes).'/>'; + + $cssClassLabel = $this->getAttribute( 'cssClassLabel' ); + $cssClassLabel .= ( $cssClassLabel ? ' ' : '' ).($this->getAttribute('required') ? 'required' : ''); + if ($this->getAttribute('wrapLabel')) { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), true, $output, array('class' => $cssClassLabel ), false); + $output = ''; + } else { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), false, '', array('class' => $cssClassLabel ), false); + } + $this->addOutputCode($this->applyItemTemplate($label, $output)); + } + + function getContent($internal=false) + { + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['name'] = $this->getOriginalId(); + $attributes['class'] = $this->getAttribute('required') ? 'required' : ''; + $attributes['class'] .= $this->getAttribute( 'cssClass' ) != '' ? ( $attributes['class'] != '' ? ' ' : '' ).$this->getAttribute( 'cssClass' ) : ''; + $attributes['type'] = 'checkbox'; + $attributes['value'] = $this->getAttribute( 'checkedValue' ); + $attributes['checked'] = $this->_content == $attributes['value'] ? 'checked' : ''; + $attributes['disabled'] = $this->getAttribute('readOnly') ? 'readonly' : ''; + if (!$internal) $attributes['label'] = $this->encodeOuput($this->getAttribute('label')); + $attributes['title'] = $this->getAttributeString('title'); + return $attributes; + } + + function resetContent($childrensReset=false) + { + $this->_content = $this->getAttribute('defaultValue'); + } +} diff --git a/src/core/classes/org/glizy/components/ColorPicker.php b/src/core/classes/org/glizy/components/ColorPicker.php new file mode 100755 index 0000000..a4c575c --- /dev/null +++ b/src/core/classes/org/glizy/components/ColorPicker.php @@ -0,0 +1,60 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_ColorPicker extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('requiredMessage', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('value', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('defaultValue', false, '#FFFFFF', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_content = $this->getAttribute('value'); + if (is_object($this->_content)) + { + $contentSource = &$this->getAttribute('value'); + $this->_content = $contentSource->loadContent($this->getId()); + } + else if (is_null($this->_content)) + { + $this->_content = $this->_parent->loadContent($this->getId()); + } + + if (is_null($this->_content) || empty($this->_content)) + { + // imposta il valore di default + $this->_content = $this->getAttribute('defaultValue'); + } + + $this->processChilds(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Component.php b/src/core/classes/org/glizy/components/Component.php new file mode 100755 index 0000000..f0bf8a4 --- /dev/null +++ b/src/core/classes/org/glizy/components/Component.php @@ -0,0 +1,1061 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +define('COMPONENT_TYPE_STRING', 1); +define('COMPONENT_TYPE_BOOLEAN', 2); +define('COMPONENT_TYPE_INTEGER', 3); +define('COMPONENT_TYPE_OBJECT', 4); +define('COMPONENT_TYPE_ENUM', 5); + +define('COMPONENT_STATE_NULL', 0); +define('COMPONENT_STATE_INIT', 1); +define('COMPONENT_STATE_PROCESS', 2); +define('COMPONENT_STATE_RENDER', 3); +define('COMPONENT_STATE_BLOCKED', 4); + +/** + * Class org_glizy_components_Component + */ +class org_glizy_components_Component extends GlizyObject +{ + /** @var org_glizy_mvc_core_Application $_application */ + public $_application; + /** @var org_glizy_components_Component */ + public $_parent; + public $_tagname; + public $_content = NULL; + public $_attributesDefinition; + public $_attributes; + public $canHaveChilds = false; + /** @var org_glizy_components_Component[] $childComponents */ + public $childComponents; + public $_oldID; + public $_originalId; + public $state; + /** @var org_glizy_application_User $_user */ + public $_user = NULL; + public $_outputMode = NULL; + protected $controller = NULL; + public $canCallController = true; + + /** + * @param $application + * @param $parent + * @param string $tagName + * @param string $id + * @param string $originalId + */ + function __construct(&$application, &$parent, $tagName='', $id='', $originalId='') + { + $IDmap = &self::_getIDmapArray(); + + $this->_application = &$application; + $this->_user = &org_glizy_ObjectValues::get('org.glizy', 'user'); + $this->_parent = &$parent; + $this->_tagname = $tagName; + $this->childComponents = array(); + $this->_originalId = $originalId; + $this->state = COMPONENT_STATE_NULL; + + $id = ltrim($id, '/'); + + // definisce gli attributi di default + $this->_attributes = array(); + $this->_attributesDefinition = array(); + $this->defineAttribute('id', false, !empty($id) ? $id :'c'.md5(uniqid(rand(), true)), COMPONENT_TYPE_STRING); + + $this->_initAttributes(); + $this->_initID(); + $this->breakCycle(false); + } + + function reset() + { + $this->state = COMPONENT_STATE_INIT; + $this->_content = NULL; + } + + function resetChilds() + { + if ($this->canHaveChilds) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $this->childComponents[$i]->reset(); + $this->childComponents[$i]->resetChilds(); + } + } + } + + function init() + { + $this->state = COMPONENT_STATE_INIT; + + $this->defineAttribute('enabled', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('editableRegion', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('editableRegionAtEnd', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('skin', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('acl', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('visible', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('og', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('controllerName', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('actionName', false, 'action', COMPONENT_TYPE_STRING); + $this->defineAttribute('data', false, '', COMPONENT_TYPE_STRING); + + $this->_initAttributes(); + $this->initChilds(); + } + + function initChilds() + { + if ($this->canHaveChilds) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $this->childComponents[$i]->init(); + } + } + } + + /** + * @param $name + * @param bool $required + * @param null $defaultValue + * @param int $type + */ + function defineAttribute($name, $required=false, $defaultValue=NULL, $type=COMPONENT_TYPE_STRING) + { + if (!isset($this->_attributesDefinition[$name])) { + $this->_attributesDefinition[$name] = array('defaultValue' => $defaultValue, 'required' => $required, 'type' => $type); + } + } + + + /** + * @param $name + */ + function removeAttribute($name) + { + unset($this->_attributesDefinition[$name]); + unset($this->_attributes); + } + + + function dumpAttributes() + { + var_dump($this->_attributes); + } + + /** + * @param $idPrefix + */ + function remapAttributes($idPrefix) + { + foreach ($this->_attributes as $k=>$v) + { + if (preg_match("/\{[^\:]*\}/i", $v)) + { + $id = str_replace(array('{', '}'), '', $v); + if (is_object($this->getComponentById($id))) continue; + $v = str_replace('{','{'.$idPrefix, $v); + $this->_attributes[$k] = $v; + } + else if (isset($this->_attributesDefinition[$k]) && $this->_attributesDefinition[$k]['type']==COMPONENT_TYPE_OBJECT) + { + $v = str_replace('{','', $v); + $v = str_replace('}','', $v); + + if (is_object($this->getComponentById($v))) continue; + $this->_attributes[$k] = $idPrefix.$v; + } + } + + for ($i=0; $i<count($this->childComponents);$i++) + { + $this->childComponents[$i]->remapAttributes($idPrefix); + } + } + + /** + * @param $idPrefix + */ + function remapChildsIDs($idPrefix) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $this->childComponents[$i]->setId($idPrefix.$this->childComponents[$i]->getId()); + $this->childComponents[$i]->remapChildsIDs($idPrefix); + } + } + + /** + * @param $idPrefix + */ + function remapChildsOriginalIDs($idPrefix) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $this->childComponents[$i]->setId($idPrefix.$this->childComponents[$i]->getOriginalId()); + $this->childComponents[$i]->remapChildsOriginalIDs($idPrefix.$this->childComponents[$i]->getOriginalId().'-'); + } + } + + /** + * @param $name + * + * @return mixed|org_glizy_components_Component|string + * @throws Exception + */ + function &getAttribute($name) + { + $value = isset($this->_attributes[$name]) ? $this->_attributes[$name] : null; + if (is_string($value)) + { + if (@$this->_attributesDefinition[$name]['type']==COMPONENT_TYPE_OBJECT || preg_match("/^\{[^\:]*\}$/i", $value)) + { + $value = str_replace('{','',$value); + $value = str_replace('}','',$value); + if (strpos($value,'.')===false) + { + $value = &$this->getComponentById($value); + } + else + { + // controlla se c'è da chiamare un metodo + $phpArray = explode('.', $value); + if (count($phpArray)) + { + $phpcode = '$A = &$this->getComponentById(\''.$phpArray[0].'\');'; + for ($i=1;$i<count($phpArray);$i++) + { + $phpcode .= '$'.chr(65+$i).'=$'.chr(64+$i).'->'.$phpArray[$i].';'; + } + $phpcode = $phpcode.'; return $'.chr(64+$i).';'; + $value= eval($phpcode); + } + } + } + else + { + if (preg_match("/\{php\:.*\}/i", $value)) + { + // Codice php per ottenere il valore dell'attributo + $phpcode = org_glizy_helpers_PhpScript::parse($value); + $value= eval($phpcode); + //return $value; + } + else if (preg_match("/\{i18n\:.*\}/i", $value)) + { + $code = preg_replace("/\{i18n\:(.*)\}/i", "$1", $value); + $value = org_glizy_locale_Locale::getPlain($code); + } + else if (preg_match("/\{config\:.*\}/i", $value)) + { + $code = preg_replace("/\{config\:(.*)\}/i", "$1", $value); + $value = __Config::get($code); + } + } + } + + if ($value && !is_object($value) && !is_array($value)) + { + $value = $this->_validateAttributeValue($name, $value); + } + return $value; + } + + /** + * @param $name + * + * @return mixed|string + */ + function getAttributeString($name) + { + $value = strval($this->_attributes[$name]); + + if (preg_match("/\{i18n\:.*\}/i", $value)) + { + $code = preg_replace("/\{i18n\:(.*)\}/i", "$1", $value); + $value = org_glizy_locale_Locale::get($code); + } + else + { + $value = glz_encodeOutput($value); + } + + return $value; + } + + /** + * @param $name + * @param $value + * @param bool $merge + */ + function setAttribute($name, $value, $merge = false ) + { + if ( !$merge ) + { + $this->_attributes[$name] = $this->_validateAttributeValue($name, $value); + } + else + { + $this->_attributes[$name] .= $value; + } + + // se l'attributo settato è l'ID + // aggiorna la mappa degli ID. + if ($name=='id') + { + $this->_initID(); + $IDmap = &self::_getIDmapArray(); + } + + if ($name=='enabled' && $value === true && $this->state==COMPONENT_STATE_INIT && $this->_parent->state!=COMPONENT_STATE_INIT) + { + $this->process(); + $this->state = COMPONENT_STATE_PROCESS; + } + } + + /** + * @param array $attributes + */ + function setAttributes( $attributes=array() ) + { + if ( is_array( $attributes ) ) + { + foreach ( $attributes as $name=>$value ) + { + $this->_attributes[$name] = $this->_validateAttributeValue($name, $value); + + // se l'attributo settato è l'ID + // aggiorna la mappa degli ID. + if ($name=='id') + { + $this->_initID(); + $IDmap = &org_glizy_components_Component::_getIDmapArray(); + } + + if ($name=='enabled' && $this->state==COMPONENT_STATE_INIT && $this->_parent->state!=COMPONENT_STATE_INIT) + { + $this->process(); + $this->state = COMPONENT_STATE_PROCESS; + } + } + } + + } + + /** + * @param $name + * + * @return bool + */ + function issetAttribute($name) + { + return isset($this->_attributes[$name]); + } + + function _initID() + { + $IDmap = &self::_getIDmapArray(); + if (!is_null($this->_oldID)) unset($IDmap[$this->_oldID]); + $ID = $this->getId(); + $IDmap[$ID] = &$this; + $this->_oldID = $ID; + } + + function _initAttributes() + { + // legge le definizioni degli attributi + // inserisce quelli di default e controlla se ci sono attributi richiesti e non inseriti + foreach ($this->_attributesDefinition as $key=>$value) + { + if (!array_key_exists($key, $this->_attributes)) + { + // l'attributo non esiste + if ($value['required']) + { + // TODO visualizzare l'errore + // attributo non settato + //$this->RaiseError(___ERRORS_MESSAGE_ABSTRACT_METHOD_UNDEFINED___,__FUNCTION__); + echo "errore required: ".get_class($this)." ".$this->_tagname." ".$key."<br>"; + } + else + { + $this->_attributes[$key] = $value['defaultValue']; + } + } + else + { +// // l'attributo esiste esegue il casting del valore + //$this->_attributes[$key] = $this->_validateAttributeValue($key, $this->_attributes[$key]); + } + } + } + + /** + * @param $name + * @param $value + * + * @return array|bool|int + */ + function _validateAttributeValue($name, $value) + { + if (array_key_exists($name, $this->_attributesDefinition) && !is_object($value) && !preg_match("/\{(.*)\}/i", $value)) + { + $attributeDefinition = $this->_attributesDefinition[$name]; + + // l'attributo esiste esegue il casting del valore + switch ($attributeDefinition['type']) + { + case COMPONENT_TYPE_BOOLEAN: + if (is_string($value)) $value = $value=="true" ? true : false; + break; + case COMPONENT_TYPE_INTEGER: + $value = intval($value); + break; + case COMPONENT_TYPE_ENUM: + $value = explode(',', $value); + break; + } + } + + return $value; + } + + /** + * @param $component + */ + function addChild(&$component) + { + $this->childComponents[] = &$component; + // TODO + // visualizzare un errore + // un componente non può avere figli + // bisogna usare un ComponentContainer + } + + /** + * @param $value + */ + function setContent($value) + { + $this->_content = $value; + } + + function deferredChildCreation($force=false) + { + // aggiunge i figli + if ($this->canHaveChilds) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $this->childComponents[$i]->deferredChildCreation($force); + } + } + } + + function process() + { + $this->processChilds(); + } + + protected function evalueteAcl($acl) + { + $aclResult = true; + if ($acl) { + $aclBooleanAnd = true; + $aclPart = explode(' ', strtolower($acl)); + foreach ($aclPart as $aclItem) { + if ($aclItem=='and') { + $aclBooleanAnd = true; + } else if ($aclItem=='or') { + $aclBooleanAnd = false; + } else if ($aclItem) { + list($service, $action) = explode(',', $aclItem); + $r = $this->_user->acl($service, $action); + $aclResult = $aclBooleanAnd ? $aclResult && $r : $aclResult || $r; + } + } + } + + return $aclResult; + } + + function processChilds() + { + if ($this->checkBreakCycle()) + { + $this->breakCycle(false); + return; + } + if ($this->canHaveChilds) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $acl = $this->childComponents[$i]->getAttribute('acl'); + if ($acl && !$this->evalueteAcl($acl)) { + $this->childComponents[$i]->setAttribute( 'enabled', false ); + continue; + } + + if ($this->childComponents[$i]->getAttribute('enabled') && $this->childComponents[$i]->state==COMPONENT_STATE_INIT) + { + if ($this->childComponents[$i]->canCallController) $this->childComponents[$i]->callController(); + $this->childComponents[$i]->process(); + $this->childComponents[$i]->setOgValue(); + $this->state = COMPONENT_STATE_PROCESS; + + if ($this->checkBreakCycle()) + { + $this->state = COMPONENT_STATE_BLOCKED; + $this->breakCycle(false); + break; + } + + if ($this->childComponents[$i]->canCallController) $this->childComponents[$i]->callController(true); + } + } + } + + if ($this->canCallController) { + $this->callController(true); + } + $this->canCallController = false; + } + + /** + * @param null $outputMode + * @param bool $skipChilds + */ + function render($outputMode=NULL, $skipChilds=false) + { + if (!$this->getAttribute('visible')) return; + if (is_null($outputMode)) $outputMode = $this->_application->getOutputMode(); + $this->_outputMode = $outputMode; + + // applica i filtri di pre rendering + $this->_content = $this->getText(); + $this->applyOutputFilters('pre', $this->_content); + + // cerca se esiste una classe + // che si chiama come il componente ma con suffisso render + $renderClassName = $this->getClassName().'_render'; + if (class_exists($renderClassName) && !method_exists($this, 'render_'.$outputMode)) + { + // delega il rendering alla classe + /** @var org_glizy_components_Component $renderClass */ + $renderClass = new $renderClassName($this, $outputMode, $skipChilds); + $renderClass->render(); + } + else if (!is_null($this->getAttribute('skin')) && $outputMode=='html') + { + // è definita una skin + // questa possibilità è accettata solo per output di tipo HTML + $renderClass = org_glizy_ObjectFactory::createObject('org.glizy.components.render.Render', $this, $outputMode, $skipChilds); + $renderClass->render(); + } + else + { + if (method_exists($this, 'render_'.$outputMode.'_onStart')) + { + $this->{'render_'.$outputMode.'_onStart'}(); + } + else if (method_exists($this, 'render_onStart')) + { + $this->render_onStart(); + } + if (method_exists($this, 'render_'.$outputMode)) + { + $this->{'render_'.$outputMode}(); + } + if (!$skipChilds) + { + $this->renderChilds($outputMode); + } + + if (method_exists($this, 'render_'.$outputMode.'_onEnd')) + { + $this->{'render_'.$outputMode.'_onEnd'}(); + } + else if (method_exists($this, 'render_onEnd')) + { + $this->render_onEnd(); + } + } + + return ''; + } + + /** + * @param null $outputMode + */ + function renderChilds($outputMode=NULL) + { + if (is_null($outputMode)) $outputMode = $this->_application->getOutputMode(); + if ($this->checkBreakCycle()) + { + $this->breakCycle(false); + return; + } + + if ($this->canHaveChilds) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + if ($this->childComponents[$i]->getAttribute('visible') && $this->childComponents[$i]->getAttribute('enabled')) + { + $this->childComponents[$i]->render($outputMode); + $this->state = COMPONENT_STATE_RENDER; + if ($this->checkBreakCycle()) + { + $this->state = COMPONENT_STATE_BLOCKED; + $this->breakCycle(false); + break; + } + } + } + } + } + + /** + * @param bool $later + * + * @return bool|mixed|null + */ + function callController($later=false) { + if (!$this->controller) { + $controllerName = $this->getAttribute( 'controllerName' ); + if ($controllerName) { + if (substr($controllerName, -1)=='*') { + $controllerName = substr($controllerName, 0, -1); + $actionAdditionalPath = explode('.', __Request::get($this->getAttribute('actionName'))); + $actionName = ucfirst(array_pop($actionAdditionalPath)); + if (!$actionName) { + return null; + } + $controllerName .= count($actionAdditionalPath) ? implode('.', $actionAdditionalPath).'.' : ''; + if($this->_application->_ajaxMode) { + $controllerName .= 'ajax.'; + } + $controllerName .= $actionName; + } + + try { + $evt = array('type' => GLZ_EVT_CALL_CONTROLLER, 'data' => $controllerName); + $this->dispatchEvent($evt); + $this->controller = &org_glizy_ObjectFactory::createObject( $controllerName, $this ); + } catch (Exception $e) {} + } + } + + if ($this->controller) { + return org_glizy_helpers_PhpScript::callMethodWithParams( $this->controller, $later ? 'executeLater' : 'execute' ); + } + + return null; + } + + /** + * @param $output + * @param string $editableRegion + * @param null $atEnd + */ + function addOutputCode($output, $editableRegion='', $atEnd=null) + { + $atEnd = empty( $atEnd ) ? $this->getAttribute( 'editableRegionAtEnd' ) : $atEnd; + // applica i filtri di post rendering + $this->applyOutputFilters('post', $output); + $this->_parent->addOutputCode($output, empty($editableRegion) ? $this->getEditableRegion() : $editableRegion, $atEnd ); + } + + /** + * @return string + */ + function getEditableRegion() + { + $editableRegion = $this->getAttribute('editableRegion'); + if (empty($editableRegion) && $this->issetAttribute('defaultEditableRegion')) $editableRegion = $this->getAttribute('defaultEditableRegion'); +// if (empty($editableRegion) && method_exists($this->_parent, 'getAttribute')) $editableRegion = $this->_parent->getAttribute('editableRegion'); + if (empty($editableRegion) && method_exists($this->_parent, 'getEditableRegion')) $editableRegion = $this->_parent->getEditableRegion(); + return $editableRegion; + } + + /** + * @return org_glizy_components_Component + */ + function &getRootComponent() + { + return $this->_application->getRootComponent(); + } + + /** + * @return org_glizy_components_Component + */ + function &getParent() + { + return $this->_parent; + } + + /** + * @param $className + * + * @return org_glizy_components_Component|null + */ + function &getParentByClass($className) + { + $className = str_replace('.', '_', strtolower($className)); + return $this->_parent->_getParentByClass($className); + } + + /** + * @param $className + * + * @return org_glizy_components_Component|null + */ + function &_getParentByClass($className) + { + if (strtolower($this->getClassName())==$className) + { + return $this; + } + else + { + if (is_object($this->_parent) && method_exists($this->_parent, '_getParentByClass')) + { + return $this->_parent->_getParentByClass($className); + } + else + { + $null = NULL; + return $null; + } + } + } + + /** + * @return string + */ + function getId() + { + return $this->getAttribute('id'); + } + + /** + * @return string + */ + function getOriginalId() + { + + $originalId = $this->_originalId; + if (preg_match("/\{php\:.*\}/i", $originalId)) { + $phpcode = org_glizy_helpers_PhpScript::parse($originalId); + $originalId = eval( $phpcode ); + } + + return $originalId; + } + + /** + * @param $value + */ + function setId($value) + { + $this->setAttribute('id', $value); + } + + function &_getIDmapArray() + { + static $_valuesArray = array(); + return $_valuesArray; + } + + /** + * @param $id + * + * @return org_glizy_components_Component + */ + function &getComponentById($id) + { + $id = preg_replace("/\{(.*)\}/i", "$1", $id); + $IDmap = & org_glizy_components_Component::_getIDmapArray(); + $result = NULL; + if (array_key_exists($id, $IDmap)) $result = &$IDmap[$id]; + return $result; + } + + function setCustomClass() + { + + } + + /** + * @param $value + */ + function setText($value) + { + // $this->setAttribute('text', $value); + $this->_content = $value; + } + + /** + * @return null|string + */ + function getText() + { + $text = $this->getAttribute('text'); + return (empty($this->_content) && !empty($text)) ? html_entity_decode( $text ) : $this->_content; + } + + /** + * @return null + */ + function getContent() + { + return $this->_content; + } + + /** + * @return mixed + */ + function getTagName() + { + $tag = explode(':', $this->_tagname); + return $tag[count($tag)-1]; + } + + function debugComponentId() + { + $IDmap = & org_glizy_components_Component::_getIDmapArray(); + print_r(array_keys($IDmap )); + } + + /** + * @param int $depth + */ + function debugComponentTree($depth=0) + { + if ($depth==0) echo 'id: '.$this->getId().' tagname: '.$this->_tagname.' orginalId: '.$this->getOriginalId()."\r\n<br>"; + $depth++; + for ($i=0; $i<count($this->childComponents); $i++) + { + echo str_repeat(" ", $depth).'id: '.$this->childComponents[$i]->getId().' tagname: '.$this->childComponents[$i]->_tagname.' orginalId: '.$this->childComponents[$i]->getOriginalId()."\r\n<br>"; + $this->childComponents[$i]->debugComponentTree($depth); + } + } + + /** + * @param $id + * + * @return string + */ + function loadContent($id) + { + // TODO visualizzare errore + return ''; + } + + /** + * @param $output + * + * @return mixed + */ + function encodeOuput($output) + { + return glz_encodeOutput($output); + } + + // DOLATER + /** + * @param $obj + * @param $functionName + */ + function doLater(&$obj, $functionName) + { + $doLaterActions = &org_glizy_ObjectValues::get('org.glizy:components.Component', 'doLater'); + $doLaterActions[] = array('class'=> &$obj, 'function' => $functionName); + } + + function resetDoLater() + { + $doLaterActions = &org_glizy_ObjectValues::get('org.glizy:components.Component', 'doLater'); + $doLaterActions = array(); + } + + function execDoLater() + { + $doLaterActions = &org_glizy_ObjectValues::get('org.glizy:components.Component', 'doLater'); + for ($i = 0; $i<count($doLaterActions); $i++) + { + call_user_func(array(&$doLaterActions[$i]['class'], $doLaterActions[$i]['function'])); + } + $this->resetDoLater(); + } + + /** + * @param array $attributes + * + * @return string + */ + function _renderAttributes($attributes=array()) + { + return org_glizy_helpers_Html::renderAttributes($attributes, $this->getAttribute( 'data' ) ); + } + + /** + * @param bool $childrensReset + */ + function resetContent($childrensReset=false) + { + $this->_content = ''; + if ($this->canHaveChilds && $childrensReset) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $this->childComponents[$i]->resetContent(true); + } + } + } + + /** + * @param $className + */ + function createChildsFromModel($className) + { + // crea i figli + /** @var org_glizy_components_Component $newComponent */ + $newComponent = &org_glizy_ObjectFactory::createComponent($className, $this->_application, $this, '', $this->getId()); + for($i=0; $i<count($newComponent->childComponents); $i++) + { + $newComponent->childComponents[$i]->remapAttributes($this->getId().'-'); + $this->addChild($newComponent->childComponents[$i]); + $newComponent->childComponents[$i]->_parent = &$this; + } + $this->initChilds(); + + // TODO + // problema da risolvere in modo più elengante + // quando si crea un componente figlio come in questo caso + // l'id del component nella mappa degli ID viene sovrascritto + // con il componente nuovo perché al memoneto della creazione gli viene passato lo stesso ID + $this->setAttribute('id', $this->getId()); + } + + /** + * @param bool $value + */ + function breakCycle($value=true) + { + $breakClice = &org_glizy_components_Component::_breakCycle(); + $breakClice[0] = $value; + } + + + function checkBreakCycle() + { + $breakClice = &org_glizy_components_Component::_breakCycle(); + return $breakClice[0]; + } + + function &_breakCycle() + { + static $_breakCycle = array(); + return $_breakCycle; + } + + /** + * @return bool + */ + function validate() + { + if ($this->canHaveChilds && $this->getAttribute( 'enabled' ) && $this->getAttribute( 'visible' ) ) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $this->childComponents[$i]->validate(); + } + } + return count( org_glizy_components_Component::validateErrors() ) == 0; + } + + function &validateErrors() + { + static $_validateErrors = array(); + return $_validateErrors; + } + + /** + * @param $message + */ + function validateAddError( $message ) + { + $validateError = &org_glizy_components_Component::validateErrors() ; + $validateError[] = array( 'component' => &$this, 'message' => $message ); + org_glizy_application_MessageStack::add( $message, GLZ_MESSAGE_ERROR ); + } + + /** + * @param $mode + * @param $value + */ + function applyOutputFilters($mode, &$value) + { + $outputFilters = &org_glizy_ObjectValues::get('org.glizy:components.Component', 'OutputFilter.'.$mode); + if (isset($outputFilters[$this->_tagname])) + { + foreach ($outputFilters[$this->_tagname] as $f) + { + $fObj = new $f; + if (is_object($fObj)) + { + $fObj->apply($value, $this); + } + } + } + } + + /** + * @param $value + */ + private function _setEnabled($value) + { + $this->_attributes['enabled'] = $value; + } + + /** + * @return string + */ + function getOgValue() { + return strip_tags( $this->_content ); + } + + function setOgValue() { + $og = $this->getAttribute('og'); + if ($og) { + org_glizy_ObjectValues::set('org.glizy.og', $og, $this->getOgValue() ); + } + } + + /** + * @return bool + */ + public function controllerDirectOutput() { + return $this->controller && $this->controller->directOutput; + } + + /** + * @return string + */ + public function getAjaxUrl() + { + return 'ajax.php?pageId='.$this->_application->getPageId().'&ajaxTarget='.$this->getId().'&action='; + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/ComponentContainer.php b/src/core/classes/org/glizy/components/ComponentContainer.php new file mode 100755 index 0000000..b01dd00 --- /dev/null +++ b/src/core/classes/org/glizy/components/ComponentContainer.php @@ -0,0 +1,79 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_ComponentContainer extends org_glizy_components_Component +{ + var $_output; + var $acceptOutput; + var $overrideEditableRegion; + + function __construct(&$application, &$parent, $tagName='', $id='', $originalId='') + { + parent::__construct($application, $parent, $tagName, $id, $originalId); + $this->canHaveChilds = true; + $this->_output = array(); + $this->acceptOutput = false; + $this->overrideEditableRegion = true; + } + + function addOutputCode($output, $editableRegion='', $atEnd=false) + { + if ($this->acceptOutput) + { + if ($this->overrideEditableRegion) + { + $editableRegion = $this->getAttribute('editableRegion'); + } + $this->_output[] = array('editableRegion' => empty($editableRegion) ? $this->getEditableRegion() : $editableRegion, 'code' => $output, 'atEnd' => $atEnd); + } + else + { + $this->addParentOutputCode($output, $editableRegion, $atEnd); + } + } + + function addParentOutputCode($output, $editableRegion='', $atEnd=false) + { + parent::addOutputCode($output, $editableRegion, $atEnd); + } + + function loadContent($id, $bindTo='') + { + return method_exists($this->_parent, 'loadContent') ? $this->_parent->loadContent($id, $bindTo) : ''; + } + + function getChildContent() + { + $result = array(); + for ($i=0; $i<count($this->childComponents);$i++) + { + $onlyAdmin = $this->childComponents[$i]->getAttribute( "onlyAdmin" ); + if ( $onlyAdmin === true ) + { + $result = array_merge( $result, $this->childComponents[$i]->getContent() ); + } + else + { + $result[$this->childComponents[$i]->getOriginalId()] = $this->childComponents[$i]->getContent(); + } + } + return $result; + } + + protected function stripIdFromContent($content) + { + $id = $this->getId(); + $result = array(); + foreach ($content as $k => $v) { + $result[preg_replace('/^'.$id.'-/', '', $k)] = $v; + } + return $result; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/ConfigValue.php b/src/core/classes/org/glizy/components/ConfigValue.php new file mode 100755 index 0000000..601c41a --- /dev/null +++ b/src/core/classes/org/glizy/components/ConfigValue.php @@ -0,0 +1,53 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_ConfigValue extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('key', true, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('value', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('action', false, 'get', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + $this->doLater($this, 'preProcess'); + parent::init(); + } + + function preProcess() + { + if ($this->getAttribute('action')=='set') + { + $value = is_null($this->getAttribute('value')) ? $this->getContent() : $this->getAttribute('value'); + org_glizy_Config::set( $this->getAttribute('key'), $value ); + } + } + + /** + * Render + * + * @return void + * @access public + */ + function render_html() + { + if ($this->getAttribute('action')=='get') + { + $this->addOutputCode(org_glizy_Config::get($this->getAttribute('key'))); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/DBdebug.php b/src/core/classes/org/glizy/components/DBdebug.php new file mode 100755 index 0000000..20f0558 --- /dev/null +++ b/src/core/classes/org/glizy/components/DBdebug.php @@ -0,0 +1,30 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_DBdebug extends org_glizy_components_Component +{ + + function init() + { + // define the custom attributes + $this->defineAttribute('value', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('connect', false, 0, COMPONENT_TYPE_INTEGER); + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + glz_import('org.glizy.dataAccess.DataAccess'); + glz_DBdebug( $this->getAttribute('value'), $this->getAttribute('connect') ); + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/DataDictionary.php b/src/core/classes/org/glizy/components/DataDictionary.php new file mode 100755 index 0000000..04b00fa --- /dev/null +++ b/src/core/classes/org/glizy/components/DataDictionary.php @@ -0,0 +1,152 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_DataDictionary extends org_glizy_components_Component +{ + var $iterator; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('recordClassName', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('query', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('queryParams', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('field', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('skipEmpty', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('delimiter', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('useCache', false, false, COMPONENT_TYPE_BOOLEAN); + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $classPath = $this->getAttribute('recordClassName'); + if (is_null($classPath)) + { + // TODO + // visualizzare FATAL ERROR + $this->RaiseError("DataProvider: record class don't found",__FUNCTION__,__FILE__,__LINE__,'verbosedie'); + } + else + { + $this->iterator = &org_glizy_ObjectFactory::createModelIterator($classPath); + if ($this->iterator === false) + { + // TODO + // visualizzare FATAL ERROR + $this->RaiseError("DataProvider: record class don't found",__FUNCTION__,__FILE__,__LINE__,'verbosedie'); + } + } + } + + function getItems() + { + $oldCacheValue = __Config::get('QUERY_CACHING'); + __Config::set('QUERY_CACHING', $this->getAttribute('cache')); + + if ( is_null( $this->iterator ) ) + { + $this->process(); + } + $items = org_glizy_ObjectValues::get('org.glizy.components.DataDictionary', $this->getAttribute('recordClassName').'.'.$this->getAttribute('field').$this->getAttribute('query')); + if (is_null($items)) + { + $items = __Session::get($this->getAttribute('recordClassName').'.'.$this->getAttribute('field').$this->getAttribute('query') ); + } + + if (is_null($items) ) + { + $items = $this->loadDictionary( $this->getAttribute('field'), + $this->getAttribute('query'), + unserialize($this->getAttribute('queryParams')), + $this->getAttribute('skipEmpty'), + $this->getAttribute('delimiter') ); + org_glizy_ObjectValues::set('org.glizy.components.DataDictionary', $this->getAttribute('recordClassName').'.'.$this->getAttribute('field').$this->getAttribute('query'), $items); + if ( $this->getAttribute('delimiter') != '' ) + { + __Session::set($this->getAttribute('recordClassName').'.'.$this->getAttribute('field').$this->getAttribute('query'), $items); + } + } + + __Config::set('QUERY_CACHING', $oldCacheValue); + return $items; + } + + function loadDictionary($field, $queryName = null, $queryParams = null, $skipEmpty = false, $delimiter = '') + { + if ($queryName) { + $this->iterator->load($queryName, $queryParams); + $k = 'k'; + $v = 'v'; + } + else { + $field = explode(',', $field); + + if (count($field) == 1) { + $k = $field[0]; + $v = $field[0]; + } else { + $k = $field[0]; + $v = $field[1]; + } + + if (method_exists($this->iterator, 'selectDistinct')) { + $this->iterator->selectDistinct($v); + } + + $this->iterator->orderBy($v); + } + + $result = array(); + $usedKeys = array(); + + foreach ($this->iterator as $ar) { + $key = $ar->$k; + $value = $ar->$v; + + if ($skipEmpty && empty($value)) { + continue; + } + + if (!$delimiter) { + $result[] = array('key' => $key, 'value' => $value); + } else { + $kk = explode( $delimiter, $key ); + $vv = explode( $delimiter, $value ); + $l = count( $kk ); + for( $i = 0; $i < $l; $i++ ) { + if ( !in_array( $kk[ $i ], $usedKeys ) ) + { + $usedKeys[] = $kk[ $i ]; + $result[] = array('key' => $kk[ $i ], 'value' => $vv[ $i ] ); + } + } + } + } + + if ($delimiter) { + org_glizy_helpers_Array::arrayMultisortByLabel( $result, 'value' ); + } + + return $result; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/DataGrid.php b/src/core/classes/org/glizy/components/DataGrid.php new file mode 100755 index 0000000..e551758 --- /dev/null +++ b/src/core/classes/org/glizy/components/DataGrid.php @@ -0,0 +1,533 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_DataGrid extends org_glizy_components_ComponentContainer +{ + var $_columns; + var $_cssClass; + var $_dataProvider; + var $_totalRecord; + var $_orderBy; + var $_orderDirection; + var $_primarykey; + var $_versionFieldName = null; + var $_languageFieldName = null; + var $iterator; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('controller', false, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('tableCssClass', false, 'list', COMPONENT_TYPE_STRING); + $this->defineAttribute('dataProvider', true, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('filters', false, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('label', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('paginate', false, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('query', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('routeUrl', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('skipOrder', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('skipGroup', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('drawHeader', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('renderRow', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('orderBy', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('orderDirection',false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('hideTotals', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('allowEmptySearch', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('emptySearchLabel', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + $this->processChilds(); + + // inizializza le variabili + $sessionEx = &org_glizy_ObjectFactory::createObject('org.glizy.SessionEx', $this->getId()); + $this->_cssClass = explode(',', $this->getAttribute('cssClass')); + $this->_contentValue = array(); + $this->_columns = array(); + $filters = array(); + $this->_totalRecord = NULL; + + // legge le colonne da visualizzare dai figli + for ($i=0; $i<count($this->childComponents);$i++) + { + $this->_columns[] = $this->childComponents[$i]->getProperties(); + } + + // verifica se c'� una colonna da ordinare + $this->_orderBy = $sessionEx->get('orderBy', $this->getAttribute('orderBy'), true, true); + $this->_orderDirection = $sessionEx->get('orderDirection', $this->getAttribute('orderDirection'), true, true); + if ( empty( $this->_orderDirection ) ) $this->_orderDirection = 'ASC'; + + // TODO + // la funzione di autosalvataggio dei sessionEx non funziona ebne + // quindi i valori li risalvo a mano + $sessionEx->set('orderBy', $this->_orderBy); + $sessionEx->set('orderDirection', $this->_orderDirection); + + + if( $this->_orderBy && !$this->_columns[ $this->_orderBy ][ 'visible' ] ) + { + $this->_orderBy = null; + } + + + if (is_null($this->_orderBy )) + { + for ($i=0; $i<count($this->_columns); $i++) + { + $v = $this->_columns[$i]; + if ($v['visible']===true) + { + $this->_orderBy = $i; + break; + } + } + } + + // verifica se ci sono dei filtri da applicare + $filtersObj = &$this->getAttribute('filters'); + if (is_object($filtersObj)) + { + $filters = $filtersObj->getFilters(); + } + + // legge i dati dal dataprovider + $this->_dataProvider = &$this->getAttribute('dataProvider'); + if (is_null($this->_dataProvider)) + { + // TODO + // visualizzare errore e uscire + } + + $ar = $this->_dataProvider->getNewObject(); + $this->_primarykey = $ar->getPrimaryKeyName(); + //$this->_versionFieldName = $ar->getVersionFieldName(); + //$this->_languageFieldName = $ar->getLanguageFieldName(); + + + // esegue la paginazione + $pageLimits = NULL; + $paginateClass = $this->getAttribute("paginate"); + if ( is_object( $paginateClass ) ) + { + $paginateClass->setRecordsCount(); + $pageLimits = $paginateClass->getLimits(); + } + + if (!is_null($this->_versionFieldName)) + { + $filters[$this->_versionFieldName] = array('<>', 'OLD'); + /* + TODO + con il datagrid ottimizzato questa tecnica non funziona + // c'� da creare dinamicamente una query per avere lo stesso risultato + // + + // legge i valori i dati della lingua di default + // questo perch� su Models multilingue + // possono esserci delle lingue che non hanno ancora definito tutti i valori + + $ar = &org_glizy_ObjectFactory::createModel('org.glizy.models.Language'); + $ar->language_isDefault = 1; + $ar->find(); + $filters[$this->_languageFieldName] = $ar->language_id; + $iteratorDefault = &$this->_dataProvider->loadQuery('', + array( 'filters' => $filters, + 'order' => array($this->_columns[$this->_orderBy]['columnName'].' '.$this->_orderDirection), + 'group' => $this->_primarykey, + 'limit' => $pageLimits + )); + //$this->_totalRecord = $iteratorDefault->count(); + + while ($iteratorDefault->hasMore()) + { + $ar = &$iteratorDefault->current(); + $iteratorDefault->next(); + $values = $ar->getValuesAsArray(true); + $this->_contentValue[$values[$this->_primarykey]] = $values; + } + */ + + // $filters[$this->_languageFieldName] = $this->_application->getEditingLanguageId(); + } + + $skipSearch = false; + if (!$this->getAttribute('allowEmptySearch')) + { + $skipSearch = true; + if (count($filters)) + { + foreach($filters as $k=>$v) + { + if (!empty($v)) + { + $skipSearch = false; + break; + } + } + } + } + + if ( !$skipSearch ) + { + // legge i dati dai record + $options = array(); + $options['filters'] = $filters; + $options['limit'] = $pageLimits; + $options['numRows'] = true; + if (!$this->getAttribute('skipOrder') && isset( $this->_columns[$this->_orderBy] ) && $this->_columns[$this->_orderBy]['columnName'] ) $options['order'] = array($this->_columns[$this->_orderBy]['columnName'] => $this->_orderDirection); + if (!$this->getAttribute('skipGroup')) $options['group'] = $this->_primarykey; + + $this->iterator = $this->_dataProvider->loadQuery('', $options); + $this->_totalRecord = $this->iterator->count(); + if ( is_object( $paginateClass ) ) + { + $paginateClass->setRecordsCount($this->iterator->count()); + } + } + } + + function render() + { + if ( !$this->iterator ) + { + $this->addOutputCode( '<p>'.$this->getAttribute( 'emptySearchLabel' ).'</p>' ); + return; + } + // legge le colonne da visualizzare dai figli + // NOTA: le colonne sono gi� state lette sul process + // ma vengono rilette perch� pu� essere variata la visibilit� + $this->_columns = array(); + for ($i=0; $i<count($this->childComponents);$i++) + { + $this->_columns[] = $this->childComponents[$i]->getProperties(); + } + + + $addJsCode = false; + $output = ''; + + if ( $this->_totalRecord > 0 ) + { + $class = $this->getAttribute('tableCssClass')!='' ? ' class="'.$this->getAttribute('tableCssClass').'"' : ''; + $output .= '<table id="'.$this->getId().'"'.$class.'>'; + if ($this->getAttribute('label')!='') $output .= '<caption>'.$this->getAttribute('label').'</caption>'; + + if ($this->getAttribute('drawHeader')) + { + // disegna le colonne + $output .= '<thead>'; + $output .= '<tr>'; + //foreach ($this->_columns as $v) + + for ($i=0; $i<count($this->_columns); $i++) + { + $v = $this->_columns[$i]; + if ($v['visible']===true) + { + $cssClass = !empty($v['cssClass']) ? ' class="'.$v['cssClass'].'"' : ''; + $id = !empty($v['id']) ? ' id="'.$v['id'].'"' : ''; + $width = !empty($v['width']) ? ' style="width: '.$v['width'].'px;"' : ''; + + if (!empty($v['renderCell'])) + { + $renderCell = &org_glizy_ObjectFactory::createObject($v['renderCell'], $this->_application ); + if (method_exists($renderCell, 'getHeader')) + { + $v['headerText'] = $renderCell->getHeader( $v['headerText'] ); + } + unset( $renderCell ); + } + + + if (!empty($v['command'])) + { + $output .= '<th'.$id.$cssClass.$width.'>'; + if ($v['command']=='publish') + { + $output .= '<input name="publishAll" value="" type="checkbox" class="js-selectall" />'; + } + $output .= '</th>'; + } + else + { + if (!$this->getAttribute('skipOrder') && $v['orderable'] ) + { + $addJsCode = true; + $headerId = 'orderBy_'.$i; + $headerClass = 'DataGridHeader'; + + $headerImage = ''; + if ($i==$this->_orderBy) + { + $headerId .= '_'.($this->_orderDirection=='ASC' ? 'DESC':'ASC'); + $headerImage = ($this->_orderDirection=='ASC' ? '<span class="ui-icon ui-icon-triangle-1-s"></span>':'<span class="ui-icon ui-icon-triangle-1-n"></span>'); + } + else $headerId .= '_'.$this->_orderDirection; + + $output .= '<th'.$id.$cssClass.$width.'><a href="#" id="'.$headerId.'" class="'.$headerClass.'">'.$v['headerText'].'</a>'.$headerImage.'</th>'; + } + else + { + $output .= '<th'.$cssClass.$width.'>'.$v['headerText'].'</th>'; + } + } + } + } + $output .= '</tr>'; + $output .= '</thead>'; + } + + if (!$this->getAttribute('hideTotals')) + { + $output .= '<tfoot>'; + $output .= '<tr><td style="text-align: right;" colspan="'.count($this->_columns).'">'.__T('GLZ_TOTAL_RECORDS').' '.$this->_totalRecord.'</td></tr>'; + $output .= '</tfoot>'; + } + $output .= '<tbody>'; + + $key = 0; + $tempCssClass = $this->_cssClass; + $rowCellClass = $this->getAttribute('renderRow');; + if (!empty($rowCellClass)) + { + $rowCellClass = &org_glizy_ObjectFactory::createObject($rowCellClass, $this->_application ); + } + + foreach ($this->iterator as $ar) + { + $v = $ar->getValuesAsArray(true); + $rowOutput = ''; + foreach ($this->_columns as $vv) + { + if ($vv['key']) $key = $v[$vv['columnName']]; + if ($vv['visible']===false) continue; + + $tempOutput = ''; + $cssClass = ''; + if (!empty($vv['renderCell'])) + { + $renderCell = &org_glizy_ObjectFactory::createObject($vv['renderCell'], $this->_application ); + if ( is_object( $renderCell ) ) + { + $tempOutput .= $renderCell->renderCell($key, isset($v[$vv['columnName']]) ? $v[$vv['columnName']] : '', $ar, $vv['columnName']); + $cssClass = !empty($vv['cssClass']) ? $vv['cssClass'] : ''; + if (method_exists($renderCell, 'getCssClass')) + { + $cssClass = $renderCell->getCssClass($key, isset($v[$vv['columnName']]) ? $v[$vv['columnName']] : '', $v); + } + } + } + else if (!empty($vv['command'])) + { + $addJsCode = true; + + if (strtolower($this->_application->getPageId())=='usergroups') + { + if ($vv['command']=='delete' && $v['usergroup_backEndAccess']) continue; + } + switch ($vv['command']) + { + case 'edit': + if ($this->_user->acl($vv['aclService'], $vv['command'])) { + if (!is_null($this->_versionFieldName)) + { + if ($this->_user->acl($vv['aclService'], $vv['command'])) + { + $icon = org_glizy_Assets::get('ICON_EDIT'); + $ar = &$this->_dataProvider->getNewObject(); + $joinFields = $ar->getJoinFields(); + $result = $ar->find(array($joinFields['detailTable'] => $key, $this->_versionFieldName => 'PUBLISHED')); + //$result = $ar->find(array($joinFields['detailTable'] => $key, $this->_versionFieldName => 'PUBLISHED', $this->_languageFieldName => $this->_application->getEditingLanguageId())); + } + else + { + $icon = org_glizy_Assets::get('ICON_EDITDRAFT'); + $result = true; + } + if ($result /*|| $v[$this->_languageFieldName]!=$this->_application->getEditingLanguageId()*/) + { + + $tempOutput .= '<img title="'.org_glizy_locale_Locale::get('GLZ_RECORD_EDIT').'" id="edit_'.$key.'" class="DataGridCommand" src="'.$icon.'" width="16" height="16" border="0" />'; + } + else + { + $tempOutput .= '<img id="" class="DataGridCommand" src="'.org_glizy_Assets::get('ICON_EDIT_OFF').'" width="16" height="16" border="0" />'; + } + } + else + { + $tempOutput .= '<img title="'.org_glizy_locale_Locale::get('GLZ_RECORD_EDIT').'" id="edit_'.$key.'" class="DataGridCommand" src="'.org_glizy_Assets::get('ICON_EDIT').'" width="16" height="16" border="0" />'; + } + } + break; + case 'editDraft': + if (!is_null($this->_versionFieldName) && $this->_user->acl($vv['aclService'], $vv['command'])) + { + $ar = &$this->_dataProvider->getNewObject(); + $joinFields = $ar->getJoinFields(); + $result = $ar->find(array($joinFields['detailTable'] => $key, $this->_versionFieldName => 'DRAFT')); + //$result = $ar->find(array($joinFields['detailTable'] => $key, $this->_versionFieldName => 'DRAFT', $this->_languageFieldName => $this->_application->getEditingLanguageId())); + if ($result) + { + $tempOutput .= '<img title="'.org_glizy_locale_Locale::get('GLZ_RECORD_EDIT').'" id="editDraft_'.$key.'" class="DataGridCommand" src="'.org_glizy_Assets::get('ICON_EDITDRAFT').'" width="16" height="16" border="0" />'; + } + else + { + $tempOutput .= '<img id="" class="DataGridCommand" src="'.org_glizy_Assets::get('ICON_EDITDRAFT_OFF').'" width="16" height="16" border="0" />'; + } + } + break; + case 'preview': + $tempOutput .= '<img title="'.org_glizy_locale_Locale::get('GLZ_RECORD_PREVIEW').'" id="preview_'.$key.'" class="DataGridCommand" src="'.org_glizy_Assets::get('ICON_PREVIEW').'" width="16" height="16" border="0" />'; + break; + case 'delete': + if ($this->_user->acl($vv['aclService'], $vv['command'])) { + $tempOutput .= '<img title="'.org_glizy_locale_Locale::get('GLZ_RECORD_DELETE').'" id="delete_'.$key.'" class="DataGridCommand" src="'.org_glizy_Assets::get('ICON_DELETE').'" width="16" height="16" border="0" />'; + } + break; + case 'publish': + if ($this->_user->acl($vv['aclService'], $vv['command'])) { + $tempOutput .= '<input name="publish[]" value="'.$key.'" type="checkbox">'; + } + break; + } + } + else + { + if (!is_null($this->_languageFieldName) && $v[$this->_languageFieldName]!=$this->_application->getEditingLanguageId()) + { + $tempOutput .= '<em>'.$v[$vv['columnName']].'</em>'; + } + else + { + $tempOutput .= $v[$vv['columnName']]; + } + } + $cssClass = !empty($cssClass) ? ' class="'.$cssClass.'"' : ''; + $rowOutput .= '<td style="text-align: '.$vv['align'].';"'.$cssClass.'>'.$tempOutput.'</td>'; + } + + if (!count($tempCssClass)) $tempCssClass = $this->_cssClass; + $cssClass = array_shift($tempCssClass); + if (!empty($rowCellClass)) + { + $output .= $rowCellClass->renderRow($v, $cssClass); + } + else + { + $output .= '<tr class="'.$cssClass.'" id="row_'.$key.'">'; + } + $output .= $rowOutput.'</tr>'; + } + + $output .= '</tbody>'; + $output .= '</table>'; + } + else + { + $emptyLabel = $this->getAttribute( 'emptyLabel' ); + if ( !empty( $emptyLabel ) ) + { + $output .= '<p class="datagridEmpty">'.$emptyLabel.'</p>'; + } + } + + $this->addOutputCode($output); + + if ( !$addJsCode ) return; + + $jsId = $this->getId(); + $jsMessage = org_glizy_locale_Locale::get('GLZ_RECORD_MSG_DELETE'); + + + // TODO + // controllare che il valore di controller sia settato + $controllerClass = &$this->getAttribute('controller'); + if (is_object($controllerClass)) + { + $jsStateUrl = $controllerClass->changeStateUrl(); + $jsStateUrl = str_replace(__Link::makeUrl( 'link', array( 'pageId' => $this->_application->getPageId())).'?', '', $jsStateUrl); + $jsStateUrl = __Link::removeParams(array($controllerClass->getId().'_recordId'), $jsStateUrl); + $jsCurrentStateUrl = $controllerClass->changeStateUrl($controllerClass->getState()); + $controllerId = $controllerClass->getid(); + } + else + { + $jsStateUrl = __Link::removeParams(array($jsId.'_orderBy', $jsId.'_orderDirection')); + $jsCurrentStateUrl = $jsStateUrl ; + $controllerId = ''; + } + + $output = ''; + + + $output = <<<EOD +<script language="JavaScript" type="text/JavaScript"> +jQuery(document).ready(function() { + jQuery('#$jsId input.js-selectall').change(function(){ + var checked = this.checked; + $(this).closest('table').find("input[name='publish[]']").each(function(i, el){ + el.checked = checked; + }) + }); + + jQuery(['#$jsId .DataGridCommand', '#$jsId .DataGridHeader']).each(function(index,element) + { + jQuery( element ).css( {cursor: 'pointer'} ); + jQuery( element ).click( function() + { + var command = this.id.split('_'); + var loc = "{$jsStateUrl}"+command[0]+"&{$controllerId}_recordId="+command[1]; + switch (command[0]) + { + case 'delete': + this.parentNode.parentNode.oldClass2 = this.parentNode.parentNode.oldClass; + this.parentNode.parentNode.className2 = this.parentNode.parentNode.className; + this.parentNode.parentNode.className = "ruled"; + this.parentNode.parentNode.oldClass = "ruled"; + + if (confirm("{$jsMessage}")) + { + location.href = loc; + } + + this.parentNode.parentNode.oldClass = this.parentNode.parentNode.oldClass2; + this.parentNode.parentNode.className = this.parentNode.parentNode.oldClass2; + break; + case 'orderBy': + loc = "{$jsCurrentStateUrl}&{$jsId}_orderBy="+command[1]+"&{$jsId}_orderDirection="+command[2]; + location.href = loc; + + default: + location.href = loc; + break; + + } + }); + }); +}); +</script> +EOD; + + if ( !empty( $output ) ) $this->addOutputCode($output); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/DataGridAjax.php b/src/core/classes/org/glizy/components/DataGridAjax.php new file mode 100644 index 0000000..d62a7aa --- /dev/null +++ b/src/core/classes/org/glizy/components/DataGridAjax.php @@ -0,0 +1,346 @@ +<?php +class org_glizy_components_DataGridAjax extends org_glizy_components_Component +{ + private $columns = array(); + + function init() + { + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('recordClassName', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('query', false, 'all', COMPONENT_TYPE_STRING); + $this->defineAttribute('queryOperator', false, 'OR', COMPONENT_TYPE_STRING); + $this->defineAttribute('fullTextSearch', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('setFiltersToQuery', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('JQueryUI', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('dbDebug', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('minSearchLenght', false, 0, COMPONENT_TYPE_INTEGER); + + // call the superclass for validate the attributes + parent::init(); + } + + function render_html(){ + $tableClass = $this->getAttribute( "cssClass" ); + $id = $this->getId(); + $ajaxUrl = $this->getAjaxUrl(); + + $colSpan = 0; + $headers = ''; + $aoColumnDefs = array(); + + foreach( $this->columns as $column ) + { + if ( $column['acl'] ) { + if (!$this->_user->acl($column['acl']['service'], $column['acl']['action'])) { + continue; + } + } + + $colSpan++; + $headers .= '<th'; + if ( !$column['visible'] ) $headers .= ' style="display:none;"'; + if ( $column['width'] ) $headers .= ' width="'.$column['width'].'%"'; + $headers .= '>'.$column['headerText'].'</th>'; + + $aoColumnDefs[] = array ( + "bSortable" => $column['sortable'], + "bSearchable" => $column['searchable'], + "aTargets" => array($colSpan-1), + "sType" => "html", + "sClass" => $column['cssClass'] + ); + } + + $aoColumnDefs = json_encode($aoColumnDefs); + + if (!org_glizy_ObjectValues::get('jquery.dataTables', 'add', false)) + { + org_glizy_ObjectValues::set('jquery.dataTables', 'add', true); + $staticDir = org_glizy_Paths::get('STATIC_DIR'); + $html = '<script type="text/javascript" src="'.$staticDir.'/jquery/datatables/media/js/jquery.dataTables.min.js"></script>'; + $html .= '<script type=""text/javascript" src="'.$staticDir.'/jquery/datatables/media/js/jquery.dataTables.bootstrap.js"></script>'; + } + + $cookieName = 'DataTables_'.__Config::get('SESSION_PREFIX').$this->getId().$this->_application->getPageId(); + $sLengthMenu = __T('records per page'); + $sEmptyTable = __T('No record found'); + $sZeroRecords = __T('No record found with current filters'); + $sInfo = __T('Showing _START_ to _END_ of _TOTAL_ entries'); + $sInfoEmpty = __T('Showing 0 to 0 of 0 entries'); + $sInfoFiltered = __T('filtered from _MAX_ total entries'); + $sLoadingRecords = __T('Loading...'); + $sProcessing = __T('Processing...'); + $Search = __T('Search'); + $sFirst = __T('First'); + $sLast = __T('Last'); + $sNext = __T('Next'); + $sPrevious = __T('Previous'); + $JQueryUI = $this->getAttribute('JQueryUI') ? 'true' : 'false'; + $minSearchLenght = $this->getAttribute('minSearchLenght'); + + $html .= <<<EOD + <table class="$tableClass" id="$id"> + <thead> + <tr > + $headers + </tr> + </thead> + <tbody> + <tr> + <td colspan="$colSpan" style="text-align: center" class="dataTables_empty">Loading data from server</td> + </tr> + </tbody> + </table> +<script type="text/javascript"> + +// <![CDATA[ +\$( function(){ + var table = \$('#$id').dataTable( { + "sDom": "<'row-fluid filter-row clearfix'<'filter-box'l><'filter-box'f>r>t<'row-fluid clearfix'<'filter-box pull-left'i><'filter-box pull-right'p>>", + "sPaginationType": "bootstrap", + "oLanguage": { + "sLengthMenu": "_MENU_ $sLengthMenu", + "sEmptyTable": "No record found", + "sZeroRecords": "$sZeroRecords", + "sInfo": "$sInfo", + "sInfoEmpty": "$sInfoEmpty", + "sInfoFiltered": "($sInfoFiltered)", + "sLoadingRecords": "$sLoadingRecords", + "sProcessing": "$sProcessing", + "sSearch": "{$Search}:", + "oPaginate": { + "sFirst": "$sFirst", + "sLast": "$sLast", + "sNext": "$sNext", + "sPrevious": "$sPrevious" + } + }, + "bJQueryUI": $JQueryUI, + "bServerSide": true, + "sAjaxSource": "$ajaxUrl", + "aoColumnDefs": $aoColumnDefs, + "bStateSave": true, + "fnStateSave": function (oSettings, oData) { + localStorage.setItem( "$cookieName", JSON.stringify(oData) ); + }, + "fnStateLoad": function (oSettings) { + return JSON.parse( localStorage.getItem("$cookieName") ); + } + } ); + + \$('.dataTables_filter input') + .unbind() + .bind('keyup', function(e){ + if (\$(this).val().length > 0 && \$(this).val().length < $minSearchLenght && e.keyCode != 13) return; + table.fnFilter(\$(this).val()); + }) + + \$('#$id').data('dataTable', table); +}); +// ]]> +</script> +EOD; + + $this->addOutputCode( $html ); + } + + + public function getAjaxUrl() + { + return parent::getAjaxUrl().__Request::get( 'action', 'Index' ); + } + + public function addColumn( $column ) + { + if (preg_match("/\{i18n\:.*\}/i", $column['headerText'])) + { + $code = preg_replace("/\{i18n\:(.*)\}/i", "$1", $column['headerText']); + $column['headerText'] = org_glizy_locale_Locale::getPlain($code); + } + + $this->columns[] = $column; + } + + function process_ajax() + { + $aColumns = array(); + foreach( $this->columns as $column ) + { + if ( !in_array( $column['columnName'], $aColumns)) { + $aColumns[] = $column['columnName']; + } + } + + $sSearch = __Request::get('sSearch'); + $filters = array(); + + $it = org_glizy_ObjectFactory::createModelIterator($this->getAttribute('recordClassName')); + + if ($it->getArType() === 'document') { + $it->setOptions(array('type' => 'PUBLISHED_DRAFT')); + } + + if ($this->getAttribute('setFiltersToQuery')) { + for ( $i=0 ; $i < count($aColumns) ; $i++ ) { + if (__Request::get('sSearch_'.$i)) { + $filters[$aColumns[$i]] = __Request::get('sSearch_'.$i); + } else if ($sSearch != '' && __Request::get('bSearchable_'.$i) == "true" ) { + $filters[$aColumns[$i]] = $sSearch; + } + } + $it->load($this->getAttribute('query'), array('filters' => $filters)); + + } else { + $it->load($this->getAttribute('query')); + if (method_exists($it, 'showAll')) { + $it->showAll(); + } + + if ($this->getAttribute('fullTextSearch') && $sSearch) { + $it->where('fulltext', '%'.$sSearch.'%', 'ILIKE'); + } else { + for ( $i=0 ; $i < count($aColumns) ; $i++ ) { + if (__Request::get('sSearch_'.$i)) { + $filters[$aColumns[$i]] = array ( + 'value' => __Request::get('sSearch_'.$i), + 'condition' => 'LIKE' + ); + } + else if ($sSearch != '' && __Request::get('bSearchable_'.$i) == "true" ) { + $filters[$aColumns[$i]] = array ( + 'value' => '%'.$sSearch.'%', + 'condition' => 'LIKE' + ); + } + } + + if (!empty($filters)) { + if ($this->getAttribute('queryOperator') === 'OR') { + $it->setOrFilters($filters); + } else { + $it->setFilters($filters); + } + } + } + } + + // Ordering + if ( __Request::exists('iSortCol_0') ) { + $iSortingCols = intval( __Request::get( 'iSortingCols' )); + for ( $i=0 ; $i<$iSortingCols ; $i++ ) { + if ( __Request::get( 'bSortable_'.intval( __Request::get('iSortCol_'.$i) ) ) == "true" ) { + $order = $aColumns[ intval( __Request::get( 'iSortCol_'.$i ) ) ]; + $order_dir = __Request::get('sSortDir_'.$i); + $it->orderBy($order, $order_dir); + break; + } + } + } + + // Paging + if ( __Request::get( 'iDisplayStart', -1 ) != -1 ) { + $it->limit(array( __Request::get( 'iDisplayStart' ), __Request::get( 'iDisplayLength', -1 ) )); + } + + $aaData = array(); + + if ($this->getAttribute('dbDebug')) { + org_glizy_dataAccessDoctrine_DataAccess::enableLogging(); + } + + try { + foreach( $it as $row ) { + $rowToInsert = array(); + + foreach( $this->columns as $column ) { + if ( $column['acl'] ) { + if (!$this->_user->acl($column['acl']['service'], $column['acl']['action'])) { + continue; + } + } + + $value = $row->$column['columnName']; + if ( $column['renderCell'] ) { + if ( !is_object( $column['renderCell'] ) ) { + $column['renderCell'] = org_glizy_ObjectFactory::createObject( $column['renderCell'], $this->_application ); + } + + if ( is_object($column['renderCell'])) { + $value = $column['renderCell']->renderCell( $row->getId(), $value, $row, $column['columnName'] ); + } + } + + if (is_object($value)) { + $value = json_encode($value); + } + $rowToInsert[] = $value; + } + $aaData[] = $rowToInsert; + + } + } catch (Exception $e) { + var_dump($e); + } + + if ($this->getAttribute('dbDebug')) { + org_glizy_dataAccessDoctrine_DataAccess::disableLogging(); die; + } + + $output = array( + "sEcho" => intval(__Request::get('sEcho')), + "iTotalRecords" => $it->count(), + "iTotalDisplayRecords" => $it->count(), + "aaData" => $aaData + ); + + return $output; + } + + public static function compile($compiler, &$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix, $componentClassInfo, $componentId) + { + $compiler->_classSource .= '$n'.$counter.' = org_glizy_ObjectFactory::createComponent(\''.$componentClassInfo['classPath'].'\', $application, '.$parent.', \''.$node->nodeName.'\', '.$idPrefix.'\''.$componentId.'\', \''.$componentId.'\', $skipImport)'.GLZ_COMPILER_NEWLINE; + + if ($parent!='NULL') + { + $compiler->_classSource .= $parent.'->addChild($n'.$counter.')'.GLZ_COMPILER_NEWLINE; + } + + if (count($node->attributes)) + { + // compila gli attributi + $compiler->_classSource .= '$attributes = array('; + foreach ( $node->attributes as $key=>$value ) + { + if ($key!='id') + { + $compiler->_classSource .= '\''.$key.'\' => \''.addslashes( $node->getAttribute( $key ) ).'\', '; + } + } + $compiler->_classSource .= ')'.GLZ_COMPILER_NEWLINE; + $compiler->_classSource .= '$n'.$counter.'->setAttributes( $attributes )'.GLZ_COMPILER_NEWLINE; + } + + + foreach ($node->childNodes as $n ) + { + if ( strpos( $n->nodeName, ":DataGridColumn" ) !== false ) + { + $params = array(); + $params['sortable'] = $n->hasAttribute( 'sortable' ) ? $n->getAttribute( 'sortable' ) == 'true' : true; + $params['searchable'] = $n->hasAttribute( 'searchable' ) ? $n->getAttribute( 'searchable' ) == 'true' : true; + $params['visible'] = $n->hasAttribute( 'visible' ) ? $n->getAttribute( 'visible' ) == 'true' : true; + $params['columnName'] = $n->hasAttribute( 'columnName' ) ? $n->getAttribute( 'columnName' ) : ''; + $params['headerText'] = $n->hasAttribute( 'headerText' ) ? $n->getAttribute( 'headerText' ) : ''; + $params['width'] = $n->hasAttribute( 'width' ) ? $n->getAttribute( 'width' ) : ''; + $params['acl'] = $n->hasAttribute( 'acl' ) ? $n->getAttribute( 'acl' ) : ''; + $params['cssClass'] = $n->hasAttribute( 'cssClass' ) ? $n->getAttribute( 'cssClass' ) : ''; + $params['renderCell'] = $n->hasAttribute( 'renderCell' ) ? $n->getAttribute( 'renderCell' ) : ''; + if ($params['acl']) { + list( $service, $action ) = explode( ',', $params['acl'] ); + $params['acl'] = array('service' => $service, 'action' => $action); + } + $compiler->_classSource .= '$n'.$counter.'->addColumn('.var_export($params, true).');'; + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/DataGridColumn.php b/src/core/classes/org/glizy/components/DataGridColumn.php new file mode 100755 index 0000000..f11bcb4 --- /dev/null +++ b/src/core/classes/org/glizy/components/DataGridColumn.php @@ -0,0 +1,55 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_DataGridColumn extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('align', false, 'left', COMPONENT_TYPE_STRING); + $this->defineAttribute('columnName', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('command', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('headerText', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('key', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('renderCell', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('width', false, NULL, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('orderable', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('aclService', false, 'EditRecord', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + function getProperties() + { + $properties = array(); + $properties['columnName'] = $this->getAttribute('columnName'); + $properties['headerText'] = $this->getAttribute('headerText'); + $properties['width'] = $this->getAttribute('width'); + $properties['align'] = $this->getAttribute('align'); + $properties['visible'] = $this->getAttribute('visible'); + $properties['key'] = $this->getAttribute('key'); + $properties['command'] = $this->getAttribute('command'); + $properties['renderCell'] = $this->getAttribute('renderCell'); + $properties['cssClass'] = $this->getAttribute('cssClass'); + $properties['orderable'] = $this->getAttribute('orderable'); + $properties['id'] = $this->getOriginalId(); + $properties['aclService'] = $this->getAttribute('aclService'); + + return $properties; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/DataProvider.php b/src/core/classes/org/glizy/components/DataProvider.php new file mode 100755 index 0000000..67acc75 --- /dev/null +++ b/src/core/classes/org/glizy/components/DataProvider.php @@ -0,0 +1,201 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_DataProvider extends org_glizy_components_Component +{ + var $_classPath; + var $_activeRecord; + var $_recordIterator; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('recordClassName', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('query', false, 'All', COMPONENT_TYPE_STRING); + $this->defineAttribute('order', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('orderModifier', false, 'ASC', COMPONENT_TYPE_STRING); + $this->defineAttribute('limit', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('filters', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('categories', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('params', false, '', COMPONENT_TYPE_OBJECT); + $this->defineAttribute('checkIntegrity', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('queryOperator', false, 'AND', COMPONENT_TYPE_STRING); + $this->defineAttribute('showAll', false, false, COMPONENT_TYPE_BOOLEAN); + + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_classPath = $this->getAttribute('recordClassName'); + if (is_null($this->_classPath)) + { + // TODO + // visualizzare FATAL ERROR + $this->RaiseError("DataProvider: record class don't found",__FUNCTION__,__FILE__,__LINE__,'verbosedie'); + } + else + { + $this->_recordIterator = &org_glizy_ObjectFactory::createModelIterator($this->_classPath); + $this->_activeRecord = &org_glizy_ObjectFactory::createModel($this->_classPath); + + if ($this->getAttribute('showAll') && method_exists($it, 'showAll')) { + $this->_recordIterator->showAll(); + } + /* + $this->_activeRecord = &org_glizy_ObjectFactory::createModel($this->_classPath); + if ($this->_activeRecord===false) + { + // TODO + // visualizzare FATAL ERROR + $this->RaiseError("DataProvider: record class don't found",__FUNCTION__,__FILE__,__LINE__,'verbosedie'); + } + $this->_activeRecord->setDefaultQuery( $this->getAttribute('query') ); + */ + } + + $this->processChilds(); + } + + + /** + * Render + * + * @return void + * @access public + */ + function render() + { + } + + function &loadQuery($queryName='', $options=array()) + { + if (is_null($this->_recordIterator)) { + $this->_recordIterator = &org_glizy_ObjectFactory::createModelIterator($this->getAttribute('recordClassName')); + + if ($this->getAttribute('showAll') && method_exists($it, 'showAll')) { + $this->_recordIterator->showAll(); + } + } + + if (empty($queryName)) + { + $queryName = $this->getAttribute('query'); + } + + $order = $this->getAttribute('order'); + if (!empty($order)) + { + $options['order'] = array( $order => $this->getAttribute('orderModifier')); + } + + if ($this->getAttribute('useQueryParams') && isset($options['filters'])) { + $options['params'] = array(); + + if (count($options['filters'])) { + foreach($options['filters'] as $k=>$v) { + $options['params'][$k] = is_array($v) ? $v[1] : $v; + } + } + unset($options['filters']); + } + + if ($this->getAttribute('limit')) $options['limit'] = explode(',', $this->getAttribute('limit')); + if ($this->getAttribute('filters')) $options['filters'] = $this->getAttribute('filters'); + + // TODO + // if ($this->getAttribute('categories')) $options['categories'] = $this->getAttribute('categories'); + // TODO + // if ($this->getAttribute('params')) $options['params'] = $this->getAttribute('params'); + + $it = $this->_recordIterator->load($queryName); + + if (!empty($options['filters'])) { + if ($this->getAttribute('queryOperator') === 'OR') { + $it->setOrFilters($options['filters']); + } + else { + $it->setFilters($options['filters']); + } + } + + if (isset($options['order'])) { + $it->setOrderBy($options['order']); + } + + if (isset($options['limit'])) { + $it->limit($options['limit']); + } + + // glz_dbdebug(true); + + return $it; + } + + function &load($id) + { + $this->_activeRecord->load($id); + return $this->getObject(); + } + + /** + * @return org_glizy_dataAccess_ActiveRecord + */ + function &getObject() + { + return $this->_activeRecord; + } + + + function &getNewObject() + { + $ar = &org_glizy_ObjectFactory::createModel($this->_classPath); + //$ar->setDefaultQuery( $this->getAttribute('query') ); + return $ar; + } + + function getRecordClassName() + { + return $this->getAttribute('recordClassName'); + } + + function getItems($name, $bindToField=NULL) + { + if (!is_null($bindToField)) + { + $name = $bindToField; + } + + $result = array(); + $iterator = &$this->loadQuery(); + foreach ($iterator as $ar) { + $result[] = array('key' => $ar->getId(), 'value' => $ar->$name); + } + + return $result; + } + + function getLastSql() + { + return $this->_activeRecord->lastSql; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Date.php b/src/core/classes/org/glizy/components/Date.php new file mode 100755 index 0000000..ecebd61 --- /dev/null +++ b/src/core/classes/org/glizy/components/Date.php @@ -0,0 +1,69 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Date extends org_glizy_components_Input +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('showTime', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('defaultNow', false, false, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_content = $this->_parent->loadContent($this->getId()); + if ($this->_content=='0000-00-00') $this->_content = ''; + if ($this->_content == '' && $this->getAttribute( 'defaultNow' ) ) + { + $this->_content = date( 'd/m/Y' ); + } + } + + function render_html() + { + parent::render_html(); + + if ( !$this->getAttribute( 'readOnly') ) + { + $id = $this->getId(); + $format = $this->getAttribute('showTime') ? 'GlizyLocale.datetime.format' : 'GlizyLocale.date.format'; + $minView = $this->getAttribute('showTime') ? '' : 'minView: \'month\','; + + $jsCode = <<<EOD +$(function () { + $("#$id").datetimepicker({ + language: 'it', + format: $format, + $minView + autoclose: true, + todayHighlight: true + }); +}); +EOD; + + $this->_parent->addOutputCode( org_glizy_helpers_JS::JScode( $jsCode ) ); + } + } +} diff --git a/src/core/classes/org/glizy/components/Email.php b/src/core/classes/org/glizy/components/Email.php new file mode 100755 index 0000000..f8dacf3 --- /dev/null +++ b/src/core/classes/org/glizy/components/Email.php @@ -0,0 +1,46 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Email extends org_glizy_components_Text +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('makeLink', false, false, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + function render_html() + { + $output = $this->getContent(); + $this->addOutputCode($output); + } + + function getContent() + { + $tagContent = trim($this->getText()); + if ($this->getAttribute('makeLink') && !empty($tagContent)) + { + return org_glizy_helpers_Link::makeEmailLink($tagContent); + } + else + { + return $tagContent; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/EmbedPage.php b/src/core/classes/org/glizy/components/EmbedPage.php new file mode 100755 index 0000000..4a8a113 --- /dev/null +++ b/src/core/classes/org/glizy/components/EmbedPage.php @@ -0,0 +1,79 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_components_EmbedPage extends org_glizy_components_ComponentContainer +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('requiredMessage', false, NULL, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $tagContent = $this->getText(); + if (empty($tagContent)) + { + // richiede il contenuto al padre + $tagContent = $this->_parent->loadContent($this->getId()); + $this->setText($tagContent); + } + + if ($this->_parent->_tagname=='glz:Page') + { + if (strpos($this->getText(), '.xml')!==false) + { + // crea i componenti leggendoli dal pageType specificato + $fileName = org_glizy_Paths::getRealPath('APPLICATION_PAGE_TYPE', $this->getText()); + if (!empty($fileName)) + { + $originalRootComponent = &$this->_application->getRootComponent(); + $this->_pageTypeObj = &org_glizy_ObjectFactory::createPage($this->_application, preg_replace('/.xml$/', '', $this->getText())); + $rootComponent = &$this->_application->getRootComponent(); + $rootComponent->init(); + $this->_application->_rootComponent = &$originalRootComponent; + + for($i=0; $i<count($rootComponent->childComponents); $i++) + { + $rootComponent->childComponents[$i]->remapAttributes($this->getId().'-'); + $this->addChild($rootComponent->childComponents[$i]); + $rootComponent->childComponents[$i]->_parent = &$this; + } + + $this->processChilds(); + } + } + else + { + $newComponent = &org_glizy_ObjectFactory::createComponent($this->getText(), $this->_application, $this, '', '', ''); + $newComponent->init(); + $this->addChild($newComponent); + $this->processChilds(); + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/EmptyComponent.php b/src/core/classes/org/glizy/components/EmptyComponent.php new file mode 100755 index 0000000..60096fb --- /dev/null +++ b/src/core/classes/org/glizy/components/EmptyComponent.php @@ -0,0 +1,31 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_EmptyComponent extends org_glizy_components_ComponentContainer +{ + function __construct(&$application, &$parent, $tagName='', $id='', $originalId='') + { + parent::__construct($application, $parent, $tagName, $id, $originalId); + $this->canHaveChilds = true; + $this->overrideEditableRegion = false; + } + + function getContent() + { + $result = array(); + for ($i=0; $i<count($this->childComponents);$i++) + { + $id = preg_replace('/([^\-]+)\-(.*)/', '$2', $this->childComponents[$i]->getId()); + $result[$id] = $this->childComponents[$i]->getContent(); + } + + return $result; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Fieldset.php b/src/core/classes/org/glizy/components/Fieldset.php new file mode 100755 index 0000000..4892334 --- /dev/null +++ b/src/core/classes/org/glizy/components/Fieldset.php @@ -0,0 +1,71 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Fieldset extends org_glizy_components_ComponentContainer +{ + function __construct(&$application, &$parent, $tagName='', $id='', $originalId='') + { + parent::__construct($application, $parent, $tagName, $id, $originalId); + $this->canHaveChilds = true; + $this->overrideEditableRegion = false; + } + + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('addExtraSpan', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('legendTag', false, 'legend', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + function render_html_onStart() + { + $attributes = array(); + $attributes['id'] = $this->getOriginalId(); + $attributes['class'] = $this->getAttribute('cssClass'); + $output = '<fieldset '.$this->_renderAttributes($attributes).'>'; + if ( !is_null( $this->getAttribute( 'label' ) ) ) + { + $required = false; + $data = $this->getAttribute('data'); + if ($data) { + if (preg_match('/minRec=(\d+)|repeatMin=(\d+)/', $data, $m)) { + $required = $m[1] > 0 || $m[2] > 0; + } + } + // TODO usare classe per css + $output .= '<'.$this->getAttribute( 'legendTag' ).' '.($required ? '' : 'style="font-weight:normal"').'>'.( $this->getAttribute( 'addExtraSpan' ) ? '<span>' : '' ).$this->getAttribute( 'label' ).( $this->getAttribute( 'addExtraSpan' ) ? '</span>' : '' ).'</'.$this->getAttribute( 'legendTag' ).'>'; + } + $this->addOutputCode($output); + } + + function render_html_onEnd() + { + $this->addOutputCode( '</fieldset>' ); + } + + + function getContent() + { + return $this->getChildContent(); + } + +} diff --git a/src/core/classes/org/glizy/components/FilterValue.php b/src/core/classes/org/glizy/components/FilterValue.php new file mode 100755 index 0000000..238e9ae --- /dev/null +++ b/src/core/classes/org/glizy/components/FilterValue.php @@ -0,0 +1,25 @@ +<?php +class org_glizy_components_FilterValue extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('name', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('value', true, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + function getItem() + { + return array($this->getAttribute('name') => $this->getAttribute('value')); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Filters.php b/src/core/classes/org/glizy/components/Filters.php new file mode 100755 index 0000000..0df8e18 --- /dev/null +++ b/src/core/classes/org/glizy/components/Filters.php @@ -0,0 +1,66 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Filters extends org_glizy_components_ComponentContainer +{ + var $_filters; + + /** + * @param $result + */ + function getChildsInfo(&$result) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $result[] = array( 'id' => $this->childComponents[$i]->getId(), + 'originalId' => $this->childComponents[$i]->getOriginalId(), + 'className' => get_class($this->childComponents[$i]), + 'parent' => $this->getId()); + if (method_exists($this->childComponents[$i], 'getChildsInfo')) + { + $this->childComponents[$i]->getChildsInfo($result); + } + } + } + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_filters = array(); + // legge i valori dai figli + for ($i=0; $i<count($this->childComponents);$i++) + { + if (method_exists($this->childComponents[$i], 'getItem') && + $this->childComponents[$i]->getAttribute( 'visible' ) && + $this->childComponents[$i]->getAttribute( 'enabled' ) ) + { + $item = $this->childComponents[$i]->getItem(); + $this->_filters = array_merge($this->_filters, $item); + } + } + + $this->processChilds(); + } + + function render() + { + } + + function getFilters() + { + return $this->_filters; + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Form.php b/src/core/classes/org/glizy/components/Form.php new file mode 100755 index 0000000..6bc7a70 --- /dev/null +++ b/src/core/classes/org/glizy/components/Form.php @@ -0,0 +1,198 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Form extends org_glizy_components_ComponentContainer +{ + var $_command = ''; + private $currentRenderChildId; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('addValidationJs', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('action', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('fieldset', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('method', false, 'post', COMPONENT_TYPE_STRING); + $this->defineAttribute('onsubmit', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, __Config::get('glizy.form.cssClass'), COMPONENT_TYPE_STRING); + // $this->defineAttribute('command', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('enctype', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('removeGetValues', false, true, COMPONENT_TYPE_STRING ); + $this->defineAttribute('readOnly', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('dataProvider', false, NULL, COMPONENT_TYPE_OBJECT); + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + if ( $this->getAttribute( 'readOnly' ) ) + { + $this->applyReadOnlyToAllChild( $this ); + } + + $dp = $this->getAttribute('dataProvider'); + if ( is_object( $dp ) ) + { + $it = $dp->loadQuery(); + if ( is_object( $it ) ) + { + $arC = $it->current(); + if ( is_object( $arC ) ) + { + __Request::setFromArray( $arC->getValuesAsArray() ); + } + } + } + + + $this->_command = org_glizy_Request::get($this->getId().'_command', NULL); + $this->processChilds(); + } + + function render($outputMode=NULL, $skipChilds=false) + { + if ( $this->getAttribute( 'addValidationJs' ) ) + { + $this->_application->addValidateJsCode( $this->getId() ); + } + + if (!is_null($this->getAttribute('skin')) && $outputMode=='html') { + $this->acceptOutput = true; + $this->_content = new StdClass; + + for ($i=0; $i<count($this->childComponents);$i++) + { + if ($this->childComponents[$i]->getAttribute('visible') && $this->childComponents[$i]->getAttribute('enabled')) + { + $this->currentRenderChildId = $this->childComponents[$i]->getId(); + $this->_content->{$this->currentRenderChildId} = ''; + $this->childComponents[$i]->render($outputMode); + $this->state = COMPONENT_STATE_RENDER; + if ($this->checkBreakCycle()) + { + $this->state = COMPONENT_STATE_BLOCKED; + $this->breakCycle(false); + break; + } + } + } + } + + parent::render($outputMode, $skipChilds); + } + + + + function addOutputCode($output, $editableRegion='', $atEnd=false) + { + if ($this->acceptOutput) + { + $this->_content->{$this->currentRenderChildId} = $output; + } + else + { + $this->addParentOutputCode($output, $editableRegion, $atEnd); + } + + } + + + + function render_html_onStart() + { + $attributes = array(); + $attributes['id'] = $this->getId(); + + if ( !is_null($this->getAttribute('action')) ) + { + $attributes['action'] = $this->getAttribute('action'); + } + else + { + $removeValues = $this->getAttribute('removeGetValues'); + if ( $removeValues === true || $removeValues == 'true' ) + { + $attributes['action'] = org_glizy_Routing::scriptUrl( true ); + } + else + { + $attributes['action'] = org_glizy_helpers_Link::removeParams( explode( ',', $removeValues ) ); + } + } + $attributes['method'] = $this->getAttribute('method'); + $attributes['onsubmit'] = $this->getAttribute('onsubmit'); + $attributes['class'] = $this->getAttribute('cssClass'); + $attributes['enctype'] = $this->getAttribute('enctype'); + + $output = '<form '.$this->_renderAttributes($attributes).'>'; + if ($this->getAttribute('fieldset')) $output .= '<fieldset>'; + // $output .= org_glizy_helpers_Html::applyItemTemplate('', + // org_glizy_helpers_Html::hidden($this->getId().'_command', $this->getAttribute('command') ), + // true ); + $this->addOutputCode( $output ); + } + + function render_html_onEnd() + { + $output = ''; + if ($this->getAttribute('fieldset')) $output .= '</fieldset>'; + $output .= '</form>'; + $this->addOutputCode($output); + } + + + function getJSAction($action) + { + return 'this.form.'.$this->getId().'_command.value = \''.$action.'\''; + } + + function getCommadFieldName() + { + return $this->getId().'_command'; + } + + + function loadContent($name, $bindToField=NULL) + { + if (empty($bindToField)) + { + $bindToField = $name; + } + return org_glizy_Request::get($bindToField, $this->_parent->loadContent($bindToField)); + } + + function applyReadOnlyToAllChild( $node ) + { + if ($node->canHaveChilds) + { + for ($i=0; $i<count($node->childComponents);$i++) + { + if ( is_subclass_of( $node->childComponents[$i], 'org_glizy_components_HtmlFormElement' ) ) + { + $node->childComponents[$i]->setAttribute( 'readOnly', true ); + } + $this->applyReadOnlyToAllChild( $node->childComponents[$i] ); + } + } + } + + function getContent() + { + return $this->_content; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/FormLabel.php b/src/core/classes/org/glizy/components/FormLabel.php new file mode 100755 index 0000000..e98de9a --- /dev/null +++ b/src/core/classes/org/glizy/components/FormLabel.php @@ -0,0 +1,29 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_FormLabel extends org_glizy_components_HtmlComponent +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('for', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('text', true, NULL, COMPONENT_TYPE_STRING); + + $this->setHtmlTag('label'); + // call the superclass for validate the attributes + parent::init(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/GoogleMap.php b/src/core/classes/org/glizy/components/GoogleMap.php new file mode 100755 index 0000000..e2c0e0e --- /dev/null +++ b/src/core/classes/org/glizy/components/GoogleMap.php @@ -0,0 +1,106 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_GoogleMap extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('cssClass', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('adm:required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:requiredMessage', false, NULL, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + function process() + { + $this->_content = $this->_parent->loadContent($this->getId()); + } + + + function render_html() + { + $this->_render_html(); + $this->addOutputCode($this->_content ); + } + + + function getContent() + { + $this->_render_html(); + return $this->_content; + } + + + function _render_html() + { + if ( !empty( $this->_content ) ) + { + if ( !org_glizy_ObjectValues::get( 'org.glizy.application', 'pdfMode' ) ) + { + $this->_addJsCode(); + + $id = $this->getOriginalId().'_initialize'; + $values = $this->_content; + $this->_content = <<<EOD +<script type="text/javascript"> +// <![CDATA[ +function $id() { + var pos = ("$values").split(","); + if ( pos.length < 3 ) + { + pos = [51.500152, -0.126236, 15]; + } + var myLatlng = new google.maps.LatLng(pos[0], pos[1]); + var myOptions = { + zoom: parseInt(pos[2]), + center: myLatlng, + mapTypeId: google.maps.MapTypeId.ROADMAP + }; + var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); + var marker = new google.maps.Marker({ + position: myLatlng, + map: map + }); +} +Glizy.addEvent('onload', '$id()'); +// ]]> +</script> +<div id="map_canvas"></div> +EOD; + } + else + { + list( $la, $lo, $z ) = explode( ',', $this->_content ); + $this->_content = '<img src="http://maps.googleapis.com/maps/api/staticmap?center='.$la.','.$lo.'&zoom='.$z.'&size=400x400&markers=color:red%7C'.$la.','.$lo.'&sensor=false" />'; + } + + } + } + + function _addJsCode() + { + if (!org_glizy_ObjectValues::get('org.glizy.googleMap', 'add', false)) + { + $rootComponent = $this->getRootComponent(); + $rootComponent->addOutputCode(org_glizy_helpers_JS::linkJSfile( 'http://maps.google.com/maps/api/js?sensor=false' ), 'head'); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Groupbox.php b/src/core/classes/org/glizy/components/Groupbox.php new file mode 100755 index 0000000..370b9e3 --- /dev/null +++ b/src/core/classes/org/glizy/components/Groupbox.php @@ -0,0 +1,89 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Groupbox extends org_glizy_components_ComponentContainer +{ + var $_caption = NULL; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('onlyAdmin', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + + } + + // TODO + // dove è usato questo metodo? + function getChildsInfo(&$result) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $result[] = array( 'id' => $this->childComponents[$i]->getId(), + 'originalId' => $this->childComponents[$i]->getOriginalId(), + 'className' => get_class($this->childComponents[$i]), + 'parent' => $this->getId()); + if (method_exists($this->childComponents[$i], 'getChildsInfo')) + { + $this->childComponents[$i]->getChildsInfo($result); + } + } + } + + function getContent() + { + return is_array( $this->_content ) ? array_merge( $this->_content, $this->getChildContent() ) : $this->getChildContent(); + } + + + function render_html_onStart() + { + if (!$this->getAttribute('onlyAdmin')) + { + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['class'] = $this->getAttribute('cssClass'); + + $output = '<fieldset '.$this->_renderAttributes($attributes).'>'; + if (!is_null($this->getAttribute('label'))) $output .= '<legend>'.$this->getAttribute('label').'</legend>'; + $this->addOutputCode($output); + } + } + + function render_html_onEnd() + { + if (!$this->getAttribute('onlyAdmin')) + { + $output = '</fieldset>'; + $this->addOutputCode($output); + } + } + + public static function translateForMode_edit($node) { + + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['cssClass'] = $node->getAttribute('cssClass'); + + return org_glizy_helpers_Html::renderTag('glz:Panel', $attributes); + } + +} diff --git a/src/core/classes/org/glizy/components/HBox.php b/src/core/classes/org/glizy/components/HBox.php new file mode 100755 index 0000000..2187761 --- /dev/null +++ b/src/core/classes/org/glizy/components/HBox.php @@ -0,0 +1,68 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_components_HBox extends org_glizy_components_ComponentContainer +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('width', false, '40%', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + function render_html_onEnd() + { + + $output = '<div style="clear: both;"></div>'; + $this->addOutputCode($output); + } + + /*function addOutputCode($output, $editableRegion='', $atEnd=false) + { + if (!empty($output) && $output!='') $output = '<div style="position: relative; float: left; margin-right: 5px; ">'.$output.'</div>'; + $this->addParentOutputCode($output, $editableRegion, $atEnd); + }*/ + + function renderChilds($outputMode=NULL) + { + if ($this->checkBreakCycle()) + { + $this->breakCycle(false); + return; + } + + if ($this->canHaveChilds) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + if ($this->childComponents[$i]->getAttribute('visible')) + { + $clear = $i==0 ? 'clear: both; ' : ''; + $this->addOutputCode('<div style="'.$clear.'position: relative; width: '.$this->getAttribute('width').'; float: left; margin-right: 5px;">'); + $this->childComponents[$i]->render($outputMode); + $this->addOutputCode('</div>'); + } + if ($this->checkBreakCycle()) + { + $this->breakCycle(false); + break; + } + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Hidden.php b/src/core/classes/org/glizy/components/Hidden.php new file mode 100755 index 0000000..f6c1b88 --- /dev/null +++ b/src/core/classes/org/glizy/components/Hidden.php @@ -0,0 +1,76 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Hidden extends org_glizy_components_HtmlFormElement +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->_hiddenItem = true; + + // define the custom attributes + $this->defineAttribute('bindTo', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('value', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('name', false, NULL, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_content = $this->getAttribute('value'); + if (is_object($this->_content)) + { + $contentSource = &$this->getAttribute('value'); + $this->_content = $contentSource->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + else if (is_null($this->_content)) + { + $this->_content = $this->_parent->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + + if (method_exists($this->_parent, 'setFilterValue')) + { + $bindTo = $this->getAttribute('bindTo'); + $this->_parent->setFilterValue(!empty($bindTo) ? $bindTo : $this->getId(), $this->_content); + } + + $this->processChilds(); + } + + function render_html() + { + $name = $this->getAttribute( 'name' ); + if ($this->_content === true) { + $this->_content = 'true'; + } + if ($this->_content === false) { + $this->_content = 'false'; + } + $output = org_glizy_helpers_Html::hidden( empty( $name ) ? $this->getOriginalId() : $name , + !is_object($this->_content) && !is_array($this->_content) ? $this->_content : json_encode($this->_content), + array( 'class' => $this->getAttribute( 'cssClass' )), + $this->getAttribute( 'data' ) + ); + $this->addOutputCode($this->applyItemTemplate('', $output, true)); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/HtmlButton.php b/src/core/classes/org/glizy/components/HtmlButton.php new file mode 100755 index 0000000..e3806d1 --- /dev/null +++ b/src/core/classes/org/glizy/components/HtmlButton.php @@ -0,0 +1,137 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_HtmlButton extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('cssClass', false, __Config::get('glizy.formButton.cssClass'), COMPONENT_TYPE_STRING); + $this->defineAttribute('bindTo', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('disabled', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('label', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('name', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('value', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('type', false, 'submit', COMPONENT_TYPE_STRING); + $this->defineAttribute('target', false, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('tag', false, 'input', COMPONENT_TYPE_STRING); + $this->defineAttribute('onclick', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('routeUrl', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('url', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('confirmMessage', false, NULL, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + $this->_content = $this->getAttribute('value'); + if (is_object($this->_content)) + { + $contentSource = &$this->getAttribute('value'); + $this->_content = $contentSource->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + else if (is_null($this->_content)) + { + $this->_content = $this->_parent->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + if (empty($this->_content)) + { + $this->_content = ''; + } + + $targetForm = $this->getAttribute('target'); + if (!is_null($targetForm)) + { + $this->setAttribute('name', $targetForm->getCommadFieldName()); + } + } + + function render() + { + $this->applyOutputFilters('pre', $this->_content); + $output = ''; + + $attributes = array(); + $attributes['id'] = $this->getId(); + // $attributes['name'] = $this->getAttribute('name') != '' ? $this->getAttribute('name') : $this->getOriginalId(); + $attributes['name'] = $this->getOriginalId(); + $attributes['disabled'] = $this->getAttribute('disabled') ? 'disabled' : ''; + $attributes['class'] = $this->getAttribute('cssClass'); + $attributes['type'] = $this->getAttribute('type'); + $attributes['onclick'] = $this->getAttribute('onclick'); + + $routeUrl = $this->getAttribute( 'routeUrl' ); + if ( $routeUrl != '' ) + { + $attributes['onclick'] = 'location.href=\''.__Link::makeUrl( $routeUrl ).'\''; + + if (!is_null($this->getAttribute('confirmMessage'))) + { + $attributes['onclick'] = 'if (confirm(\''.$this->getAttribute('confirmMessage').'\')) '.$attributes['onclick'].'; else return false;'; + } + } + $url = $this->getAttribute( 'url' ); + if ( $url != '' ) + { + $attributes['onclick'] = 'location.href=\''.$url.'\''; + } + + $targetForm = $this->getAttribute('target'); + if (!is_null($targetForm)) + { + $this->addTranslateInfo( $targetForm->getCommadFieldName(), $this->getAttribute('label'), $this->getAttribute('value') ); + } + else + { + $this->addTranslateInfo( $this->getAttribute('name'), $this->getAttribute('label'), $this->getAttribute('value') ); + } + + if ($this->getAttribute('tag') == 'input') + { + $attributes['value'] = glz_encodeOutput($this->getAttribute('label')); + $output .= '<input '.$this->_renderAttributes($attributes).' />'; + } + else + { + $attributes['value'] = glz_encodeOutput($this->getAttribute('value')); + if ( strpos( $attributes['value'], 'route:' ) === 0 ) + { + $attributes['value'] = __Link::makeUrl( str_replace( 'route:', '', $attributes['value'] ) ); + } + $output .= '<button '.$this->_renderAttributes($attributes).'>'.$this->getAttributeString('label').'</button>'; + } + + $this->addOutputCode($output); + } + + private function addTranslateInfo( $target, $label, $buttonValue ) + { + $infoName = '__translateInfo_'.strtolower( $this->_application->getPageId() ); + $translateInfo = __Session::get( $infoName, array( ) ); + $newTranslateInfo = array(); + foreach ( $translateInfo as $value ) + { + if ( $value[ 'target_name' ] != $this->getOriginalId() ) + { + $newTranslateInfo[] = $value; + } + } + $newTranslateInfo[] = array( 'target_name' => $this->getOriginalId(), 'target' => $target, 'label' => $label, 'value' => $buttonValue ); + __Session::set( $infoName, $newTranslateInfo ); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/HtmlComponent.php b/src/core/classes/org/glizy/components/HtmlComponent.php new file mode 100755 index 0000000..80d593e --- /dev/null +++ b/src/core/classes/org/glizy/components/HtmlComponent.php @@ -0,0 +1,62 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_HtmlComponent extends org_glizy_components_ComponentContainer +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('cssClass', false, NULL, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + /* + function getHtmlTag() + { + return $this->_htmlTag; + } + + function setHtmlTag($value) + { + $this->_htmlTag = $value; + } + */ + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $tagContent = $this->getText(); + if (empty($tagContent)) + { + // richiede il contenuto al padre + $tagContent = $this->_parent->loadContent($this->getId()); + $this->setText($tagContent); + } + + $this->processChilds(); + } + + function getContent() + { + return glz_encodeOutput($this->getText()); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/HtmlComponentContainer.php b/src/core/classes/org/glizy/components/HtmlComponentContainer.php new file mode 100755 index 0000000..bdaea3d --- /dev/null +++ b/src/core/classes/org/glizy/components/HtmlComponentContainer.php @@ -0,0 +1,40 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_HtmlComponentContainer extends org_glizy_components_HtmlComponent +{ + var $_output; + var $acceptOutput; + var $overrideEditableRegion; + + function __construct(&$application, &$parent, $tagName='', $id='', $originalId='') + { + parent::__construct($application, $parent, $tagName, $id, $originalId); + $this->canHaveChilds = true; + $this->_output = array(); + $this->acceptOutput = false; + $this->overrideEditableRegion = true; + } + + + function render_html() + { + $this->renderChilds(); + $ouput = ''; + for ($i=0; $i<count($this->_output); $i++) + { + $ouput .= $this->_output[$i]['code']; + } + $this->setText($ouput); + $renderString = $this->_render(); + + $this->addParentOutputCode($renderString); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/HtmlFormElement.php b/src/core/classes/org/glizy/components/HtmlFormElement.php new file mode 100755 index 0000000..39f2088 --- /dev/null +++ b/src/core/classes/org/glizy/components/HtmlFormElement.php @@ -0,0 +1,204 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + + +class org_glizy_components_HtmlFormElement extends org_glizy_components_ComponentContainer +{ + var $_hiddenItem = false; + var $_rightLabel = false; + + function init() + { + $this->defineAttribute('applyFormItemTemplate', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('validationType', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('validationMessage', false, '', COMPONENT_TYPE_STRING); + + parent::init(); + + // se c'è un binding lo imposta per poterlo rileggere + $name = $this->getAttribute( 'name' ); + $name = empty( $name ) ? $this->getOriginalId() : $name; + $bindToField = $this->getAttribute('bindTo'); + if ( !empty($bindToField) && !__Request::exists( $bindToField ) ) + { + __Request::set( $bindToField, __Request::get( $name ) ); + } + + + if ( !$this->_application->isAdmin() ) //&& $this->getAttribute( "required" ) ) + { + $this->addValidatorClass(); + } + } + + + + function addOutputCode($output, $editableRegion='', $atEnd=false) + { + $this->_parent->addOutputCode($output, empty($editableRegion) ? $this->getEditableRegion() : $editableRegion, $atEnd); + } + + protected function applyItemTemplate($label, $element) { + if ($this->_outputMode != 'jsediting' && is_null( $this->getAttribute( 'skin' ) ) && $editableRegion != 'head' && $this->getAttribute( 'applyFormItemTemplate' ) ) + { + return org_glizy_helpers_Html::applyItemTemplate($label, $element, $this->_hiddenItem, $this->_rightLabel ); + } else { + return $label.$element; + } + } + + function validate() + { + if ( !$this->getAttribute( 'enabled' ) || !$this->getAttribute( 'visible' ) ) return; + + /** @var org_glizy_validators_Validator $validator */ + $validator = org_glizy_ObjectFactory::createObject( 'org.glizy.validators.Validator' ); + + if ( !$validator->validateRequired( $this->_content, $this->getAttribute( 'required' ) ) ) + { + $message = $this->getAttribute('requiredMessage'); + $message = empty( $message ) ? $validator->getError() : $message; + $message = empty( $message ) ? '%s' : $message; + $message = vsprintf( $message, array( $this->getAttribute( 'label' ) ) ); + $this->validateAddError( $message ); + unset( $validator ); + return; + } + + if ( !is_null($this->getAttribute( 'validationType' ) ) ) + { + if (!$validator->validate($this->_content, $this->getAttribute( 'validationType' ) ) ) + { + $message = $this->getAttribute('validationMessage'); + if ( empty( $message ) ) + { + $message = $this->getAttribute('requiredMessage'); + } + $message = empty( $message ) ? $validator->getError() : $message; + $message = vsprintf( $message, array( $this->getAttribute( 'label' ) ) ); + $this->validateAddError( $message ); + } + + // valida la lunghezza massima del campo + if ( $this->issetAttribute( 'maxLength' ) || $this->issetAttribute( 'minLength' ) ) + { + if (!$validator->validateLength( $this->_content, $this->getAttribute( 'minLength' ), $this->getAttribute( 'maxLength' ) ) ) + { + $message = $this->getAttribute('validationMessage'); + if ( empty( $message ) ) + { + $message = $this->getAttribute('requiredMessage'); + } + $message = empty( $message ) ? $validator->getError() : $message; + $message = vsprintf( $message, array( $this->getAttribute( 'label' ) ) ); + $this->validateAddError( $message ); + } + } + } + unset( $validator ); + } + + function addValidatorClass() + { + $cssClass = $this->getAttribute( 'cssClass' ); + $type = $this->getAttribute( 'validationType' ); + if ( !is_null( $type ) ) + { + $required = $this->getAttribute( 'required' ); + + if ($required == 'true') + { + $requiredString = "required,"; + } + else + { + $requiredString = ""; + } + + switch ($type) + { + case 'phone': + $cssClass .= " validate[" . $requiredString. "custom[phone]]"; + break; + + case 'numeric': + case 'zip_code': + $cssClass .= " validate[" . $requiredString. "custom[integer]]"; + break; + + case 'decimal': + $cssClass .= " validate[" . $requiredString. "custom[number]]"; + break; + + case 'only_char': + $cssClass .= " validate[" . $requiredString. "'nodigit']"; + break; + + case 'date': + $cssClass .= " validate[" . $requiredString. "custom[date]]"; + break; + + case 'dateTime': + $cssClass .= " validate[" . $requiredString. "custom[dateTime]]"; + break; + + case 'email': + $cssClass .= " validate[" . $requiredString. "custom[email]]"; + break; + + case 'password': + $cssClass .= " validate[" . $requiredString. "minSize[6]]"; + break; + + case 'file': + case 'checkbox': + $cssClass .= " validate[" . $requiredString. "]"; + break; + + case 'alphanum': + $cssClass .= " validate[" . $requiredString. "custom[onlyLetterNumber]]"; + break; + + case 'not_empty': + $minLength = $this->getAttribute( 'minLength' ); + if ( is_null( $minLength ) ) $minLength = 3; + $maxLength = $this->getAttribute( 'maxLength' ); + if ( is_null( $maxLength ) ) $maxLength = 1000; + $cssClass .= " validate[" . $requiredString. "minSize[".$minLength."],maxSize[".$maxLength."]]"; + break; + } + + $this->setAttribute( 'cssClass', $cssClass ); + + } + else + { + $required = $this->getAttribute( 'required' ); + if ( $required ) + { + $cssClass .= " validate[required]"; + $this->setAttribute( 'cssClass', $cssClass ); + } + + } + } + + protected function addWrapDiv( &$output ) { + if ( $this->getAttribute('wrapDiv') ) { + $cssClass = $this->getAttribute('cssClassWrapDiv'); + $output = '<div'.( $cssClass ? ' class="'.$cssClass.'"' : '').'>'. + $output. + '</div>'; + + + } + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Image.php b/src/core/classes/org/glizy/components/Image.php new file mode 100755 index 0000000..0552d3b --- /dev/null +++ b/src/core/classes/org/glizy/components/Image.php @@ -0,0 +1,259 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Image extends org_glizy_components_Component +{ + var $imageInfo; + var $media; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('crop', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('cropOffset', false, 0, COMPONENT_TYPE_STRING); + $this->defineAttribute('height', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('width', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('zoom', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('superZoom', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('superZoomLabel',false, '{i18n:zoom}', COMPONENT_TYPE_STRING); + $this->defineAttribute('imageInfo', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('processThumbnail', false, 'true', COMPONENT_TYPE_STRING); + $this->defineAttribute('group', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('checkIfExists', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:mediaType', false, 'IMAGE', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->resetContent(); + $mediaId = $this->_parent->loadContent($this->getId()); + + if (is_string($mediaId)) { + $mediaId = json_decode($mediaId); + } + + if (is_object($mediaId)) { + $mediaId = org_glizycms_Glizycms::getMediaArchiveBridge()->getIdFromJson($mediaId); + } + + if (is_numeric($mediaId) && $mediaId > 0) { + $this->attachMedia($mediaId); + } + } + + function getContent($parent=NULL) + { + if (!is_null($parent) && $parent=='glz:RecordSetList') + { + // elimina alcuni attributi + // perch� l'immagine � visualizzata all'interno di un recordsetlist + unset($this->_content['zoom']); + unset($this->_content['onclick']); + $this->setAttribute( 'zoom', false ); + } + + $this->_render_html(); + $this->_content['__media__'] = $this->media; + return $this->_content; + } + + /** + * Render + * + * @return void + * @access public + */ + function render_html() + { + $this->_render_html(); + $this->addOutputCode($this->_content['__html__']); + } + + function _render_html() + { + if ($this->_content['mediaId']>0) + { + $attributes = $this->_content; + + if (!is_null($this->getAttribute('width')) && !is_null($this->getAttribute('height'))) + { + if ($this->getAttribute('processThumbnail') != 'false' ) + { + if ( $this->getAttribute('processThumbnail') == 'full' ) + { + $thumbnail = $this->media->getResizeImage($this->getAttribute('width'), $this->getAttribute('height'), $this->getAttribute('crop'), $this->getAttribute('cropOffset')); + } + else + { + $thumbnail = $this->media->getThumbnail($this->getAttribute('width'), $this->getAttribute('height'), $this->getAttribute('crop'), $this->getAttribute('cropOffset')); + } + $attributes['src'] = $thumbnail['fileName']; + $attributes['width'] = $thumbnail['width']; + $attributes['height'] = $thumbnail['height']; + $this->_content['src'] = $thumbnail['fileName']; + $this->_content['width'] = $thumbnail['width']; + $this->_content['height'] = $thumbnail['height']; + } + else + { + $attributes['src'] = org_glizy_helpers_Media::getImageUrlById($this->_content['mediaId'], $this->getAttribute('width'), $this->getAttribute('height'), $this->getAttribute('crop')); + $this->_content['src'] = $attributes['src']; + + } + } + + $useZoom = $attributes['zoom']; + unset($attributes['description']); + unset($attributes['mediaId']); + unset($attributes['zoom']); + unset($attributes['size']); + unset($attributes['mediaType']); + unset($attributes['originalSrc']); + unset($attributes['__media__']); + $this->_content['__html__'] = '<img '.$this->_renderAttributes($attributes).'/>'; + + if ( $this->getAttribute( 'zoom' )) + { + if ($useZoom && $this->getAttribute('superZoom')) { + $this->_application->addZoomJsCode(); + $this->_content['__html__'] .= '<span class="superzoom js-glizySuperZoom" data-mediaid="'.$this->media->id.'" data-mediawatermark="'.($this->media->watermark ? '1' : '0').'">'.$this->getAttribute('superZoomLabel').'</span>'; + } + + $this->_application->addLightboxJsCode(); + $attributes = array(); + $attributes['title'] = $this->_content['title']; + if ($this->media->type=='IMAGE') { + $attributes['class'] = 'js-lightbox-image'; + $attributes['href'] = org_glizycms_helpers_Media::getImageUrlById($this->media->id, __Config::get( 'IMG_WIDTH_ZOOM' ), __Config::get( 'IMG_HEIGHT_ZOOM' )); + } else { + $attributes['class'] = 'js-lightbox-inline'; + $attributes['href'] = org_glizycms_helpers_Media::getFileUrlById($this->media->id); + } + $attributes['data-type'] = strtolower($this->media->type); + $attributes['rel'] = $this->getAttribute( 'group' ); + + $this->_content['__html__'] = org_glizy_helpers_Html::renderTag( 'a', $attributes, true, $this->_content['__html__'] ); + } + } + else + { + $this->_content['__html__'] = ''; + } + } + + + function resetContent() + { + $this->_content = array(); + $this->_content['mediaId'] = 0; + $this->_content['src'] = ''; + $this->_content['alt'] = ''; + $this->_content['title'] = ''; + $this->_content['description'] = ''; + $this->_content['class'] = ''; + $this->_content['style'] = ''; + $this->_content['onclick'] = ''; + $this->_content['size'] = ''; + $this->_content['mediaType'] = ''; + $this->_content['zoom'] = ''; + } + + function attachMedia($mediaId) + { + $this->media = &org_glizycms_mediaArchive_MediaManager::getMediaById($mediaId); + if (is_object($this->media)) + { + if ( $this->getAttribute( 'imageInfo' ) && !$this->_application->isAdmin() ) + { + $this->imageInfo = $this->media->getImageInfo(); + $width = $this->imageInfo['width']; + $height = $this->imageInfo['height']; + } + else + { + $width = ''; + $height = ''; + } + + $this->_content = array(); + $this->_content['mediaId'] = $this->media->id; + $this->_content['src'] = $this->media->getFileName( $this->getAttribute( 'checkIfExists' ) ); + $this->_content['originalSrc'] = $this->_content['src']; + $this->_content['alt'] = $this->media->title; + $this->_content['title'] = $this->media->title; + $this->_content['description'] = $this->media->description; + $this->_content['zoom'] = $this->media->zoom; + $this->_content['class'] = $this->getAttribute('cssClass'); + $this->_content['style'] = ""; + $this->_content['onclick'] = ""; + $this->_content['width'] = $width; + $this->_content['height'] = $height; + $this->_content['size'] = $this->media->size; + $this->_content['mediaType'] = $this->media->type; + + /* + if ($this->getAttribute('zoom')==true) + { + $this->_content['onclick'] = 'Glizy.previewImage(\''.$this->media->id.'\');'; + $this->_content['style'] = 'cursor: pointer'; + } + */ + + } + } + + function getOGvalue() { + if ($this->media) { + $thumbnail = $this->media->getResizeImage(200, 200); + return $thumbnail['fileName']; + } + return null; + } + + public static function translateForMode_edit($node) { + $mediaType = $node->getAttribute('adm:mediaType'); + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['data'] = $node->getAttribute('data').';type=mediapicker;mediatype='.$mediaType.';preview=true'; + + if (count($node->attributes)) + { + foreach ( $node->attributes as $index=>$attr ) + { + if ($attr->prefix=="adm") + { + $attributes[$attr->name] = $attr->value; + } + } + } + + return org_glizy_helpers_Html::renderTag('glz:Input', $attributes); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/ImageExternal.php b/src/core/classes/org/glizy/components/ImageExternal.php new file mode 100755 index 0000000..9e6e0d7 --- /dev/null +++ b/src/core/classes/org/glizy/components/ImageExternal.php @@ -0,0 +1,182 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_ImageExternal extends org_glizy_components_Component +{ + var $imageInfo; + var $media; + var $mediaUrl; + + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('crop', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('cropOffset', false, 0, COMPONENT_TYPE_STRING); + $this->defineAttribute('height', false, NULL, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('width', false, NULL, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('group', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('checkIfExists', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('path', false, true, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->mediaUrl = $this->_parent->loadContent($this->getId()); + $this->resetContent(); + if ( !empty( $this->mediaUrl ) ) + { + $this->attachMedia(); + } + + $this->processChilds(); + } + + function getContent($parent=NULL) + { + $this->_render_html(); + return $this->_content; + } + + /** + * Render + * + * @return void + * @access public + */ + function render_html() + { + if (!is_null($parent) && $parent=='glz:RecordSetList') + { + // elimina alcuni attributi + // perch� l'immagine � visualizzata all'interno di un recordsetlist + unset($this->_content['zoom']); + unset($this->_content['onclick']); + $this->setAttribute( 'zoom', false ); + } + + $this->_render_html(); + $this->addOutputCode($this->_content['__html__']); + } + + function _render_html() + { + if ( !empty( $this->mediaUrl ) ) + { + $attributes = $this->_content; + + if (is_string($this->mediaUrl) && (!is_null($this->getAttribute('width')) || !is_null($this->getAttribute('height')))) { + if (strpos( $this->mediaUrl, 'http://') === 0 ) { + $extension = pathinfo(parse_url($this->mediaUrl, PHP_URL_PATH), PATHINFO_EXTENSION); + $cacheFileName = 'external_'.md5($this->mediaUrl).'.'.$extension; + $cacheFilePath = __Paths::get('CACHE').$cacheFileName; + + // scarica il file e lo mette in cache + if (!file_exists($cacheFilePath)) { + @file_put_contents($cacheFilePath, @file_get_contents($this->mediaUrl)); + } + + $params = array('media_id' => 0, 'media_fileName' => $cacheFilePath); + $this->media = __ObjectFactory::createObject('org.glizycms.mediaArchive.media.Image', $params); + } + + $this->media->allowDownload = true; + $thumbnail = $this->media->getResizeImage($this->getAttribute('width'), $this->getAttribute('height'), $this->getAttribute('crop'), $this->getAttribute('cropOffset'), false, false); + + $attributes['src'] = $thumbnail['fileName']; + $attributes['width'] = $thumbnail['width']; + $attributes['height'] = $thumbnail['height']; + $this->_content['src'] = $thumbnail['fileName']; + $this->_content['width'] = $thumbnail['width']; + $this->_content['height'] = $thumbnail['height']; + } + + unset($attributes['mediaUrl']); + unset($attributes['zoom']); + unset($attributes['size']); + unset($attributes['mediaType']); + $this->_content['__html__'] = '<img '.$this->_renderAttributes($attributes).'/>'; + + if ( $this->getAttribute( 'zoom' ) || $useZoom ) + { + $this->_application->addLightboxJsCode(); + $attributes = array(); + $attributes['title'] = $this->_content['title']; + $thumbnail = $this->media->getResizeImage( __Config::get( 'IMG_WIDTH_ZOOM' ), __Config::get( 'IMG_HEIGHT_ZOOM' ) ); + $attributes['href'] = $thumbnail['fileName']; + $attributes['rel'] = 'milkbox'.( $this->getAttribute( 'group' ) != '' ? '['.$this->getAttribute( 'group' ).']' : '' ) ; + $attributes['class'] = $zoomCssClass; + $this->_content['__html__'] = org_glizy_helpers_Html::renderTag( 'a', $attributes, true, $this->_content['__html__'] ); + } + } + else + { + $this->_content['__html__'] = ''; + } + } + + + function resetContent() + { + $this->_content = array(); + $this->_content['mediaUrl'] = ''; + $this->_content['src'] = ''; + $this->_content['alt'] = ''; + $this->_content['title'] = ''; + $this->_content['class'] = ''; + $this->_content['style'] = ''; + $this->_content['size'] = ''; + $this->_content['mediaType'] = ''; + } + + function attachMedia() + { + $this->_content = array(); + $this->_content['mediaUrl'] = $this->mediaUrl; + $this->_content['alt'] = $this->mediaUrl; + $this->_content['title'] = $this->mediaUrl; + $this->_content['class'] = $this->getAttribute('cssClass'); + $this->_content['style'] = ""; + + if ( is_string($this->mediaUrl) && strpos( $this->mediaUrl, 'http://') === false && strpos( $this->mediaUrl, 'https://') === false ) + { + $this->media = &org_glizycms_mediaArchive_MediaManager::getEmptyMediaByType( 'IMAGE' ); + $this->media->fileName = $this->getAttribute( 'path' ).'/'.$this->mediaUrl; + $this->imageInfo = $this->media->getImageInfo(); + $this->_content['src'] = $this->media->getFileName( $this->getAttribute( 'checkIfExists' ) ); + $this->_content['width'] = $this->imageInfo['width']; + $this->_content['height'] = $this->imageInfo['height']; + } + else + { + $this->_content['src'] = $this->mediaUrl; + $this->_content['width'] = ""; + $this->_content['height'] = ""; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Import.php b/src/core/classes/org/glizy/components/Import.php new file mode 100755 index 0000000..00c59d7 --- /dev/null +++ b/src/core/classes/org/glizy/components/Import.php @@ -0,0 +1,49 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + + +class org_glizy_components_Import extends org_glizy_components_NullComponent +{ + public static function compile($compiler, &$node, &$registredNameSpaces, &$counter, $parent='NULL') + { + if ($node->hasAttribute('src')) + { + $src = $node->getAttribute('src'); + if (strpos($src, '.xml')===strlen($src)-4) { + $src = substr($src, 0, -4); + } + + $pageType = org_glizy_ObjectFactory::resolvePageType($src).'.xml'; + $path = $compiler->getPath(); + $fileName = $path.$pageType; + + if ( !file_exists( $fileName ) ) + { + $fileName = glz_findClassPath( $src ); + if ( is_null( $fileName ) ) + { + // TODO: file non trovato visualizzare errore + } + } + + $compiler2 = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Component'); + $compiledFileName = $compiler2->verify($fileName); + + $className = GLZ_basename($compiledFileName); + $componentId = $node->hasAttribute('id') ? $node->getAttribute('id') : ''; + $compiler->_classSource .= '// TAG: '.$node->nodeName.' '.$node->getAttribute('src').GLZ_COMPILER_NEWLINE2; + $compiler->_classSource .= 'if (!$skipImport) {'.GLZ_COMPILER_NEWLINE2; + $compiler->_classSource .= 'org_glizy_ObjectFactory::requireComponent(\''.$compiledFileName.'\', \''.addslashes($fileName).'\')'.GLZ_COMPILER_NEWLINE; + $compiler->_classSource .= '$n'.$counter.' = new '.$className.'($application, '.$parent.')'.GLZ_COMPILER_NEWLINE; + $compiler->_classSource .= $parent.'->addChild($n'.$counter.')'.GLZ_COMPILER_NEWLINE; + $compiler->_classSource .= '}'.GLZ_COMPILER_NEWLINE; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Input.php b/src/core/classes/org/glizy/components/Input.php new file mode 100755 index 0000000..8c8119f --- /dev/null +++ b/src/core/classes/org/glizy/components/Input.php @@ -0,0 +1,208 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Input extends org_glizy_components_HtmlFormElement +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('defaultValue', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('bindTo', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('cols', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, __Config::get('glizy.formElement.cssClass'), COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClassLabel', false, __Config::get('glizy.formElement.cssClassLabel'), COMPONENT_TYPE_STRING); + $this->defineAttribute('disabled', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('minLength', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('maxLength', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('rows', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('readOnly', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('size', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('value', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapLabel', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('wrap', false, 'off', COMPONENT_TYPE_STRING); + $this->defineAttribute('type', false, 'text', COMPONENT_TYPE_STRING); + $this->defineAttribute('htmlEditor', false, false, COMPONENT_TYPE_BOOLEAN); // TODO + $this->defineAttribute('required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('title', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('placeholder', false, '', COMPONENT_TYPE_STRING); + + + + // call the superclass for validate the attributes + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_content = $this->getAttribute('value'); + if (is_object($this->_content)) + { + $contentSource = &$this->getAttribute('value'); + $this->_content = $contentSource->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + else if (is_null($this->_content)) + { + $this->_content = $this->_parent->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + else + { + $this->_content = html_entity_decode( $this->_content ); + } + if (empty($this->_content)) + { + $this->_content = $this->getAttribute('defaultValue'); + + if ( method_exists($this->_parent, 'setFilterValue') ) + { + $bindTo = $this->getAttribute('bindTo'); + $this->_parent->setFilterValue(!empty($bindTo) ? $bindTo : $this->getId(), $this->_content); + } + } + } + + /** + * Render + * + * @return void + * @access public + */ + function render_html() + { + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['name'] = $this->getOriginalId(); + $attributes['disabled'] = $this->getAttribute('disabled') ? 'disabled' : ''; + $attributes['readonly'] = $this->getAttribute('readOnly') ? 'readonly' : ''; + $attributes['title'] = $this->getAttributeString('title'); + $attributes['placeholder'] = $this->getAttributeString('placeholder'); + if ( empty( $attributes['title'] ) ) + { + $attributes['title'] = $this->getAttributeString('label'); + } + $attributes['class'] = $this->getAttribute('cssClass'); + $attributes['class'] .= (!empty($attributes['class']) ? ' ' : '').($this->getAttribute('required') ? 'required' : ''); + + if ($this->getAttribute('type')=='multiline') + { + $attributes['cols'] = $this->getAttribute('cols'); + $attributes['rows'] = $this->getAttribute('rows'); + $attributes['wrap'] = $this->getAttribute('wrap'); + + $output = '<textarea '.$this->_renderAttributes($attributes).'>'; + $output .= $this->encodeOuput($this->_content); + $output .= '</textarea>'; + + $this->addTinyMCE( true ); + } + else + { + $attributes['type'] = $this->getAttribute('type'); + $attributes['maxLength'] = $this->getAttribute('maxLength'); + $attributes['size'] = $this->getAttribute('size'); + $attributes['value'] = $this->encodeOuput(is_string($this->_content) ? $this->_content : json_encode($this->_content)); + + $output = '<input '.$this->_renderAttributes($attributes).'/>'; + } + + $label = $this->getAttributeString('label') ? : ''; + if ($label) { + $cssClassLabel = $this->getAttribute( 'cssClassLabel' ); + $cssClassLabel .= ( $cssClassLabel ? ' ' : '' ).($this->getAttribute('required') ? 'required' : ''); + if ($this->getAttribute('wrapLabel')) { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), true, $output, array('class' => $cssClassLabel ), false); + $output = ''; + } else { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), false, '', array('class' => $cssClassLabel ), false); + } + } + $this->addOutputCode($this->applyItemTemplate($label, $output)); + } + + + private function addTinyMCE( $attachToElement ) + { + if ($this->getAttribute('htmlEditor')===true) + { + $rootComponent = &$this->getRootComponent(); + + if (!org_glizy_ObjectValues::get('org.glizy.JS.TinyMCE', 'add', false)) + { + org_glizy_ObjectValues::set('org.glizy.JS.TinyMCE', 'add', true); + + $rootComponent->addOutputCode(org_glizy_helpers_JS::linkCoreJSfile('tiny_mce.js?v='.GLZ_CORE_VERSION, 'tiny_mce/', false), 'head'); + $rootComponent->addOutputCode(org_glizy_helpers_JS::linkCoreJSfile('Glizy_tiny_mce.js?v='.GLZ_CORE_VERSION), 'head', true); + + $jsCode = 'Glizy.tinyCSS = "'.__Config::get( 'TINY_MCE_CSS' ).'";'; + $jsCode .= 'Glizy.tinyMCE_plugins = "'.__Config::get( 'TINY_MCE_DEF_PLUGINS' ).'";'; + $jsCode .= 'Glizy.tinyMCE_btn1 = "'.__Config::get( 'TINY_MCE_BUTTONS1' ).'";'; + $jsCode .= 'Glizy.tinyMCE_btn2 = "'.__Config::get( 'TINY_MCE_BUTTONS2' ).'";'; + $jsCode .= 'Glizy.tinyMCE_btn3 = "'.__Config::get( 'TINY_MCE_BUTTONS3' ).'";'; + if ( __Config::get( 'TINY_MCE_PLUGINS' ) != '' ) + { + $jsCode .= 'Glizy.tinyMCE_plugins .= ",'.__Config::get( 'TINY_MCE_PLUGINS' ).'";'; + } + $rootComponent->addOutputCode(org_glizy_helpers_JS::JScode( $jsCode ), 'head'); + } + + if (!is_null($this->getAttribute('adm:tinyMCEplugin'))) + { + $pluginsNames = explode( ',', $this->getAttribute('adm:tinyMCEplugin') ); + $pluginsPaths = array(); + for( $i=0; $i < count( $pluginsNames ); $i++ ) + { + $pos = strrpos( $pluginsNames[ $i ], "/" ); + if ( $pos !== false ) + { + $pluginsPaths[] = '../../../../../../'.$pluginsNames[ $i ]; + $pluginsNames[ $i ] = substr( $pluginsNames[ $i ], $pos + 1 ); + } + else + { + $pluginsPaths[] = $pluginsNames[ $i ]; + } + } + if ( count( $pluginsPaths ) ) + { + $jsCode = 'Glizy.tinyMCE_plugins += ",'.implode( ',', $pluginsPaths ).'";'; + $jsCode .= 'Glizy.tinyMCE_pluginsNames += ",'.implode( ',', $pluginsNames ).'";'; + $rootComponent->addOutputCode(org_glizy_helpers_JS::JScode( $jsCode ), 'head'); + } + } + + if ( $attachToElement ) + { + $id = $this->getId(); + $jsCode = <<< EOD +jQuery(function(){ + var options = Glizy.tinyMCE_options; + options.mode = "exact"; + options.elements = '$id'; + tinyMCE.init( options ); +}); +EOD; + //$this->addOutputCode(org_glizy_helpers_JS::JScode( $jsCode )); + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/JSTab.php b/src/core/classes/org/glizy/components/JSTab.php new file mode 100644 index 0000000..ad7ce15 --- /dev/null +++ b/src/core/classes/org/glizy/components/JSTab.php @@ -0,0 +1,36 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_JSTab extends org_glizy_components_ComponentContainer +{ + function init() + { + // define the custom attributes + $this->defineAttribute('label', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, 'tab-pane', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClassTab', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('disabled', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('dropdown', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('routeUrl', false, NULL, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + function render_html_onStart() + { + $this->addOutputCode('<div class="'.$this->getAttribute('cssClass').'" id="'.$this->getId().'">'); + } + + function render_html_onEnd() + { + $this->addOutputCode('</div>'); + } +} diff --git a/src/core/classes/org/glizy/components/JSTabGroup.php b/src/core/classes/org/glizy/components/JSTabGroup.php new file mode 100644 index 0000000..2833091 --- /dev/null +++ b/src/core/classes/org/glizy/components/JSTabGroup.php @@ -0,0 +1,143 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_JSTabGroup extends org_glizy_components_ComponentContainer +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('addWrapDiv', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('cssClass', false, 'nav nav-tabs', COMPONENT_TYPE_STRING); + $this->defineAttribute('paneCssClass', false, 'tab-content', COMPONENT_TYPE_STRING); + $this->defineAttribute('showNav', false, false, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + + function render_html_onStart() + { + $tabId = $this->getId(); + $dropdownMenu = ''; + $output .= '<ul id="'.$tabId.'" class="'.$this->getAttribute('cssClass').'">'; + + for ($i=0; $i<count($this->childComponents); $i++) + { + $visible = $this->childComponents[$i]->getAttribute('visible'); + if (!$visible) continue; + + $label = $this->childComponents[$i]->getAttribute('label'); + $routeUrl = $this->childComponents[$i]->getAttribute('routeUrl'); + $cssClassTab = $this->childComponents[$i]->getAttribute('cssClassTab'); + if ($this->childComponents[$i]->getAttribute('disabled')) { + $cssClassTab .= ' disabled'; + } + $id = $this->childComponents[$i]->getId(); + $dropdown = $this->childComponents[$i]->getAttribute('dropdown'); + if (!$dropdown) { + $cssClassTab = $cssClassTab ? ' class="'.trim($cssClassTab).'"' : $cssClassTab; + if (!$routeUrl) { + $output .= '<li'.$cssClassTab.'><a href="#'.$id.'" data-target="#'.$id.'" data-toggle="tab">'.$label.'</a></li>'; + } else { + $output .= '<li'.$cssClassTab.'><a href="'.__Link::makeUrl($routeUrl).'">'.$label.'</a></li>'; + } + } else if ($dropdown && !$dropdownMenu) { + $output .= '<li class="dropdown"><a href="noTranslate:#" data-toggle="dropdown" class="tab-dropdown dropdown-toggle"><span class="js-label">'.$label.'</span><span class="caret"></span></a><ul class="dropdown-menu">##dropdown##</ul></li>'; + $dropdownMenu .= '<li><a href="#'.$id.'" data-target="#'.$id.'" data-toggle="tab">'.$label.'</a></li>'; + } else if ($dropdown && $dropdownMenu) { + $dropdownMenu .= '<li><a href="#'.$id.'" data-target="#'.$id.'" data-toggle="tab">'.$label.'</a></li>'; + } + } + if ($dropdownMenu) { + $output = str_replace('##dropdown##', $dropdownMenu, $output); + + if ($this->getAttribute('showNav')) { + $output .= '<li class="tab-navigation"><a href="#" data-toggle="tab-prev" class="btn"><span class="fa fa-angle-double-left"></span></a></li>'; + $output .= '<li class="tab-navigation"><a href="#" data-toggle="tab-next" class="btn"><span class="fa fa-angle-double-right"></span></a></li>'; + } + } + + $output .= '</ul>'. + '<div id="'.$tabId.'_content" class="'.$this->getAttribute('paneCssClass').'">'; + + $output .= <<<EOD +<script> +jQuery(function(){ + var navInPanel = function(dir) { + var activePanel = $('#{$tabId}_content div[class="tab-pane active"]'); + if (activePanel.length) { + var id; + if (dir>0) { + id = activePanel.next().attr('id'); + } else { + id = activePanel.prev().attr('id'); + } + if (id) { + $('#{$tabId} a[data-target="#'+id+'"]').tab('show'); + } + } + } + + var updateNav = function() { + var activePanel = $('#{$tabId}_content div[class="tab-pane active"]'); + $('#{$tabId} a[data-toggle="tab-prev"]').toggleClass('disabled', !activePanel.prev().hasClass('tab-pane')); + $('#{$tabId} a[data-toggle="tab-next"]').toggleClass('disabled', !activePanel.next().hasClass('tab-pane')); + } + + $('#{$tabId} a[data-toggle="tab"]').click(function (e) { + e.preventDefault(); + if ($(this).parent().hasClass('disabled') || $(this).parent().hasClass('fake-active')) { + return false; + } + $(this).tab('show'); + }).on('shown.bs.tab', function (e) { + var target = $(e.target); + var dropdown = target.closest('ul.dropdown-menu').prev(); + if (dropdown.length) { + dropdown.find('span.js-label').html(target.html()); + } + updateNav(); + }); + + + $('#{$tabId} a[data-toggle="tab-prev"]').click(function (e) { + e.preventDefault(); + $(this).blur(); + navInPanel(-1); + }); + $('#{$tabId} a[data-toggle="tab-next"]').click(function (e) { + e.preventDefault(); + $(this).blur(); + navInPanel(1); + }); + + var aFirst = $('#{$tabId} a').first(); + if (aFirst.data('toggle')==='dropdown') { + aFirst.parent().find('ul a').first().tab('show'); + } else { + aFirst.tab('show'); + } +}); +</script> +EOD; + $this->addOutputCode($output); + } + + function render_html_onEnd() + { + $this->addOutputCode('</div>'); + } +} diff --git a/src/core/classes/org/glizy/components/JSscript.php b/src/core/classes/org/glizy/components/JSscript.php new file mode 100755 index 0000000..41a2150 --- /dev/null +++ b/src/core/classes/org/glizy/components/JSscript.php @@ -0,0 +1,162 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_JSscript extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('src', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('folder', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('type', false, 'text/javascript', COMPONENT_TYPE_STRING); + $this->defineAttribute('inline', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('editableRegion', false, 'head', COMPONENT_TYPE_STRING); + $this->defineAttribute('extension', false, 'js', COMPONENT_TYPE_STRING); + + parent::init(); + } + + /** + * Render + * + * @return void + * @access public + */ + function render_html() + { + $folder = $this->getAttribute('folder'); + $src = $this->getAttribute('src'); + $type = $this->getAttribute('type'); + + $language = $this->_application->getLanguage(); + $language2 = $language.'-'.strtoupper($language); + $src = str_replace(array('##LANG##', '##LANG2##'), array($language, $language2), $src); + + if ( $folder ) + { + if (!org_glizy_ObjectValues::get('org.glizy.JS', 'run', false)) + { + org_glizy_ObjectValues::set('org.glizy.JS', 'run', true); + $pageType = $this->_application->getPageType(); + $state = __Request::get( 'action', '' ); + $params = __Request::getAllAsArray(); + unset($params['__params__']); + unset($params['__routingName__']); + unset($params['__routingPattern__']); + unset($params['__url__']); + unset($params['__back__url__']); + $params = json_encode($params); + $jsCode = <<<EOD +var GlizyApp = {}; +GlizyApp.pages = {}; +jQuery( function(){ + if ( typeof( GlizyApp.pages[ '$pageType' ] ) != 'undefined' ) + { + GlizyApp.pages[ '$pageType' ]( '$state', $params ); + } +}) +EOD; + + $this->addOutputCode( org_glizy_helpers_JS::JScode( $jsCode ), 'head' ); + } + + // include tutta una cartella + $jsFileName = $this->includeFolder( $folder ); + if ( $this->getAttribute('inline')) { + $js = file_get_contents($jsFileName); + if ( strpos($js, '<script') !== false ) { + $this->addOutputCode( $js ); + } else { + $this->addOutputCode( org_glizy_helpers_JS::JScode( $js, $type ) ); + } + } else { + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jsFileName.(__Config::get( 'DEBUG' ) ? '?'.microtime(true) : '') , null, $type) ); + } + } + else + { + if ($src) + { + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $src, null, $type ) ); + } + else + { + $this->addOutputCode( org_glizy_helpers_JS::JScode( $this->replaceLocale($this->getText()), $type ) ); + } + } + } + + private function includeFolder( $folder ) + { + // controlla se il file in cache è valido + $options = array( + 'cacheDir' => org_glizy_Paths::get('CACHE_JS'), + 'lifeTime' => org_glizy_Config::get('CACHE_CODE'), + 'readControlType' => '', + 'fileExtension' => '.js' + ); + + $cacheSignature = get_class( $this ).$folder; + $cacheObj = org_glizy_ObjectFactory::createObject( 'org.glizy.cache.CacheFile', $options ); + $jsFileName = $cacheObj->verify( $cacheSignature ); + if ($jsFileName===false) + { + $jsFile = ''; + $folder = glz_findClassPath($folder); + $extension = $this->getAttribute('extension'); + + foreach(glob($folder.'/*'.$extension) as $file) { + // $file = pathinfo($file); + // $file = str_replace('_', '.', $file['filename']); + // $availableModules[] = $file; + // $f[] = $file; + $jsCode = file_get_contents($file); + $jsCode = $this->replaceLocale($jsCode); + $jsFile .= $jsCode."\n"; + } + + if ( __Config::get( 'DEBUG' ) || $this->getAttribute('inline')) + { + $cacheObj->save( $jsFile, NULL, get_class($this) ); + } + else + { + require_once (org_glizy_Paths::get('CORE_LIBS').'/jsmin/jsmin.php'); + $cacheObj->save( JSMin::minify( $jsFile ), NULL, $cacheSignature ); + } + $jsFileName = $cacheObj->getFileName(); + } + return $jsFileName; + } + + private function replaceLocale($text) + { + preg_match_all('/(\{)((i18n:)([^(\'"\})]*))(\})/', $text, $matches, PREG_OFFSET_CAPTURE); + if (count($matches[0])) { + for ($i=count($matches[0])-1; $i>=0;$i--) { + $text = str_replace($matches[0][$i][0], __Tp($matches[4][$i][0]), $text); + } + } + + preg_match_all('/(\{)((config:)([^(\}]*))(\})/', $text, $matches, PREG_OFFSET_CAPTURE); + if (count($matches[0])) { + for ($i=count($matches[0])-1; $i>=0;$i--) { + $text = str_replace($matches[0][$i][0], __Config::get($matches[4][$i][0]), $text); + } + } + return $text; + } +} diff --git a/src/core/classes/org/glizy/components/Link.php b/src/core/classes/org/glizy/components/Link.php new file mode 100755 index 0000000..b5c3510 --- /dev/null +++ b/src/core/classes/org/glizy/components/Link.php @@ -0,0 +1,89 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Link extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('pageId', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('routeUrl', false, 'link', COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapTag', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('url', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('icon', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('target', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $currentMenu = &$this->_application->getCurrentMenu(); + $this->_content = array(); + $this->_content['id'] = $this->getId(); + $this->_content['label'] = $this->getAttribute('label'); + $this->_content['title'] = $this->_content['label']; + $this->_content['icon'] = $this->getAttribute('icon'); + $this->_content['pageId'] = !is_null($this->getAttribute('pageId')) ? $this->getAttribute('pageId') : $currentMenu->id; + } + + + /** + * Render + * + * @return void + * @access public + */ + function render_html() + { + $url = $this->getAttribute('url'); + $cssClass = $this->getAttribute('cssClass'); + $wrapStart = ''; + $wrapEnd = ''; + if (!is_null($this->getAttribute('wrapTag'))) + { + if (!is_null( $cssClass ) ) + { + $wrapperCssClass = ' class="'.$cssClass.'"'; + } else { + $wrapperCssClass = ''; + } + $wrapStart = '<'.$this->getAttribute('wrapTag').$wrapperCssClass.'>'; + $wrapEnd = '</'.$this->getAttribute('wrapTag').'>'; + } + + if ( is_null( $url ) ) + { + $output = org_glizy_helpers_Link::makeLink2($this->getAttribute('routeUrl'), $this->_content, array('class' => $cssClass, 'id' => $this->getId())); + } + else + { + $output = org_glizy_helpers_Link::makeSimpleLink( $this->_content['label'], $url, '', $cssClass, '', array('target' => $this->getAttribute('target'), 'icon' => $this->getAttribute('icon'), 'id' => $this->getId()) ); + } + + $this->addOutputCode( $wrapStart.$output.$wrapEnd); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/LinkTo.php b/src/core/classes/org/glizy/components/LinkTo.php new file mode 100755 index 0000000..d794ad3 --- /dev/null +++ b/src/core/classes/org/glizy/components/LinkTo.php @@ -0,0 +1,112 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_components_LinkTo extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('requiredMessage', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapTag', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, NULL, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_content = $this->_parent->loadContent($this->getId()); + + if ($this->_parent->_tagname=='glz:Page') + { + header('location: '.$this->_content ); + exit(); + } + } + + function render_html() + { + $this->addOutputCode( $this->_render() ); + } + + function getContent() + { + return $this->_render(); + } + + function _render() + { + if ( !empty( $this->_content ) ) + { + $cssClass = $this->getAttribute('cssClass'); + $wrapStart = ''; + $wrapEnd = ''; + if (!is_null($this->getAttribute('wrapTag'))) + { + if (!is_null( $cssClass ) ) + { + $wrapperCssClass = ' class="'.$cssClass.'"'; + } + $wrapStart = '<'.$this->getAttribute('wrapTag').$wrapperCssClass.'>'; + $wrapEnd = '</'.$this->getAttribute('wrapTag').'>'; + } + + $url = $this->_content; + $label = $url; + if (intval($url)) { + // link interno + $siteMap = $this->_application->getSiteMap(); + $menu = $siteMap->getNodeById($url); + $label = $menu->title; + $url = org_glizy_helpers_Link::makeURL('link', array('pageId' => $url)); + } + + $output = org_glizy_helpers_Link::formatLink( $url, $label, NULL, $cssClass ); + return $wrapStart.$output.$wrapEnd; + } + + return ''; + } + + public static function translateForMode_edit($node) { + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + + if (count($node->attributes)) + { + foreach ( $node->attributes as $index=>$attr ) + { + if ($attr->prefix=="adm") + { + $attributes[$attr->name] = $attr->value; + } + } + } + + return org_glizy_helpers_Html::renderTag('glz:Input', $attributes); + } +} diff --git a/src/core/classes/org/glizy/components/List.php b/src/core/classes/org/glizy/components/List.php new file mode 100755 index 0000000..16ad5e2 --- /dev/null +++ b/src/core/classes/org/glizy/components/List.php @@ -0,0 +1,291 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_List extends org_glizy_components_HtmlFormElement +{ + var $_items; + var $_drawLinked = true; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('bindTo', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, __Config::get('glizy.formElement.cssClass'), COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClassLabel', false, __Config::get('glizy.formElement.cssClassLabel'), COMPONENT_TYPE_STRING); + $this->defineAttribute('dataProvider', false, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('disabled', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('emptyValue', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('jsAction', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('multiSelect', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('rows', false, 1, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('readOnly', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('size', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('value', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapLabel', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('insertInto', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('target', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('checkValues', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('searchCondition', false, '=', COMPONENT_TYPE_STRING); + $this->defineAttribute('adm:suggest', false, NULL, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:suggestAdd', false, NULL, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:suggestDelimiter', false, ' ', COMPONENT_TYPE_STRING); + $this->defineAttribute('outputOnlyValue', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('linkedTo', false, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('flip', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('setFirstValue', false, true, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + function getChildsInfo(&$result) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $result[] = array( 'id' => $this->childComponents[$i]->getId(), + 'originalId' => $this->childComponents[$i]->getOriginalId(), + 'className' => get_class($this->childComponents[$i]), + 'parent' => $this->getId()); + if (method_exists($this->childComponents[$i], 'getChildsInfo')) + { + $this->childComponents[$i]->getChildsInfo($result); + } + } + } + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_items = array(); + $linkedTo = $this->getAttribute('linkedTo'); + $bindTo = $this->getAttribute('bindTo'); + + if ( !is_subclass_of( $this->_parent, 'org_glizy_components_RecordDetail' ) ) + { + if ( !is_null( $linkedTo ) ) + { + $linkedToId = $linkedTo->getId(); + $linkedValue = $this->_parent->loadContent( $linkedToId, $linkedTo->getAttribute('bindTo')); + if ( $linkedValue == '' ) + { + $this->_drawLinked = false; + return; + } + } + + $dataProvider = &$this->getAttribute('dataProvider'); + if (is_null($dataProvider)) + { + // legge i valori dai figli + for ($i=0; $i<count($this->childComponents);$i++) + { + if (method_exists($this->childComponents[$i], 'getItem') && + $this->childComponents[$i]->getAttribute( 'visible' ) && + $this->childComponents[$i]->getAttribute( 'enabled' ) ) + { + $item = $this->childComponents[$i]->getItem(); + if ($item!==false) { + $this->_items[] = $item; + } + } + } + } + else + { + $this->_items = array_merge( $this->_items, $dataProvider->getItems($this->getId(), $bindTo ) ); + } + + if ($this->getAttribute('flip')) + { + $this->_items = array_reverse( $this->_items ); + } + + if (!is_null($this->getAttribute('emptyValue'))) + { + $this->_items = array_merge( array( array('key' => '', 'value' => html_entity_decode( $this->getAttributeString('emptyValue') ), 'selected' => false, 'options' => '') ), $this->_items ); + } + + + if (!is_null($this->getAttribute('checkValues'))) + { + $checkValuesClass = &org_glizy_ObjectFactory::createObject($this->getAttribute('checkValues')); + $checkValuesClass->check($this->_items); + } + } + +// // TODO: da verificare perch� viene fatta questa chiamata + // $this->_content = $this->_parent->loadContent($this->getId(), $bindTo); + // $this->_content = $this->getAttribute('value'); + $contentSource = $this->getAttribute('value'); + if (is_object($contentSource)) + { + $this->_content = $contentSource->loadContent($this->getId(), $bindTo); + } + else if (is_null($this->_content)) + { + $this->_content = $this->_parent->loadContent($this->getId(), $bindTo); + if ( is_null($this->_content) && count( $this->_items ) && $this->getAttribute('setFirstValue') ) + { + $this->_content = $this->_items[0]['key']; + } + } + + if (method_exists($this->_parent, 'setFilterValue') && !empty($this->_content) && $this->getAttribute('searchCondition')=='=') + { + $this->_parent->setFilterValue(!empty($bindTo) ? $bindTo : $this->getId(), array('condition' => '=', 'value' => html_entity_decode( $this->_content) ), $this->_content ); + } + + $this->processChilds(); + } + + function render_html() + { + $linkedTo = $this->getAttribute('linkedTo'); + if (!is_null( $linkedTo ) ) + { + $id = $this->getId(); + $id_holder = $this->getId().'_holder'; + $linkedToId = $linkedTo->getId(); + $ajaxPath = 'ajax.php?pageId='.$this->_application->getPageId().'&ajaxTarget='.$id.'&'.$linkedToId.'='; + $select = $this->_drawLinked ? $this->_render() : ''; + + $output = <<<EOD +<div id="$id_holder">$select</div> +<script language="JavaScript" type="text/JavaScript"> +window.addEvent('domready', function() { + \$( "$linkedToId" ).addEvent( 'change', function() { + if ( \$( "$linkedToId" ).get( "value" ) != "" ) + { + new Request.HTML( { url: "$ajaxPath"+\$( "$linkedToId" ).get( "value" ), + update: \$( "$id_holder" ) + } ).get(); + } + else + { + \$( "$id_holder" ).set( "text", "" ); + } + }); +}); +</script> +EOD; + $this->addOutputCode( $output ); + } + else + { + $this->addOutputCode( $this->_render() ); + } + } + + function _render() + { + + if ( $this->getAttribute( 'outputOnlyValue' ) ) + { + return $this->_content; + } + else + { + $output = ''; + + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['name'] = $this->getOriginalId(); + $attributes['disabled'] = $this->getAttribute('disabled') ? 'disabled' : ''; + $attributes['class'] = $this->getAttribute('required') ? 'required' : ''; + $attributes['class'] .= $this->getAttribute( 'cssClass' ) != '' ? ( $attributes['class'] != '' ? ' ' : '' ).$this->getAttribute( 'cssClass' ) : ''; + $attributes['title'] = $this->getAttributeString('title'); + $attributes['onchange'] = $this->getAttribute('onChange'); + + if ( $this->getAttribute('readOnly') ) + { + $output .= org_glizy_helpers_Html::hidden( $attributes['name'], $this->_content ); + $attributes['name'] .= '_orig'; + $attributes['id'] .= '_orig'; + $attributes['disabled'] = true; + } + + if ( $this->getAttribute('rows')>1) + { + $attributes['size'] = $this->getAttribute('rows'); + $attributes['multiple'] = $this->getAttribute('multiSelect') ? 'multiple' : ''; + } + + $output .= '<select '.$this->_renderAttributes($attributes).'>'; + foreach($this->_items as $item) + { + if ( $this->_content=='' || is_null( $this->_content ) ) + { + $selected = (isset($item['selected']) && $item['selected']) ? ' selected="selected"':''; + } + else + { + if ( is_array( $this->_content ) ) + { + $selected = in_array( strtoupper( $item['key'] ), $this->_content ) ? ' selected="selected"':''; + } + else + { + $selected = strtoupper($item['key'])==strtoupper($this->_content) ? ' selected="selected"':''; + } + } + $disabled = isset($item['disabled']) ? ' '.$item['disabled'] : ''; + $options = isset($item['options']) ? ' data-options="'.$item['options'].'"' : ''; + $output .= '<option value="'.glz_encodeOutput($item['key']).'"'.$selected.$disabled.$options.'>'.glz_encodeOutput($item['value']).'</option>'; + } + $output .= '</select>'; + + + $label = $this->getAttributeString('label') ? : ''; + if ($label) { + $cssClassLabel = $this->getAttribute( 'cssClassLabel' ); + $cssClassLabel .= ( $cssClassLabel ? ' ' : '' ).($this->getAttribute('required') ? 'required' : ''); + if ($this->getAttribute('wrapLabel')) { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), true, $output, array('class' => $cssClassLabel ), false); + $output = ''; + } else { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), false, '', array('class' => $cssClassLabel ), false); + } + } + return $this->applyItemTemplate($label, $output); + } + } + + function getContent() + { + return glz_encodeOutput($this->getText()); + } + + function process_ajax() + { + + $this->setAttribute( 'linkedTo', null ); + $this->process(); + return array( 'html' => $this->_render() ); + } + + function addItem( $key, $value, $selected = false ) + { + $this->_items[] = array('key' => $key, 'value' => $value, 'selected' => $selected, 'options' => array()); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/ListItem.php b/src/core/classes/org/glizy/components/ListItem.php new file mode 100755 index 0000000..ef50f34 --- /dev/null +++ b/src/core/classes/org/glizy/components/ListItem.php @@ -0,0 +1,50 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_ListItem extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('key', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('options', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('selected', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('value', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('acl', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + function getItem() + { + $acl = $this->getAttribute('acl'); + if ($acl) { + list( $service, $action ) = explode( ',', $acl ); + if ( !$this->_user->acl( $service, $action ) ) + { + return false; + } + } + $key = !is_null($this->getAttribute('key')) ? $this->getAttribute('key') : $this->getAttribute('value'); +// $value = $this->encodeOuput($this->getAttribute('value')); + $value = $this->getAttribute('value'); + $options = $this->getAttribute('options'); + + return array('key' => $key, 'value' => $value, 'selected' => $this->getAttribute('selected'), 'options' => $options, 'cssClass' => $this->getAttribute('cssClass') ); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/ListMenuItem.php b/src/core/classes/org/glizy/components/ListMenuItem.php new file mode 100755 index 0000000..7cdc0fc --- /dev/null +++ b/src/core/classes/org/glizy/components/ListMenuItem.php @@ -0,0 +1,108 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_ListMenuItem extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('url', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('routeUrl', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('value', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('selected', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('acl', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapTag', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + function getItem() + { + $acl = $this->getAttribute( 'acl' ); + + if ( !empty( $acl ) ) + { + list( $service, $action ) = explode( ',', $acl ); + if ( !$this->_user->acl( $service, $action ) ) + { + return false; + } + } + $value = strtolower( $this->getAttribute( 'value' ) ); + $label = $this->getAttribute( 'label' ); + $url = $this->getAttribute( 'url' ); + $routeUrl = $this->getAttribute( 'routeUrl' ); + $cssClass = $this->getAttribute( 'cssClass' ); + + if ( $routeUrl ) + { + $title = $label; + if ( $cssClass ) + { + $label = '<i class="'.$cssClass.'"></i>'.$label; + } + $label = $this->addWrap($label); + $url = org_glizy_helpers_Link::makeLink( $routeUrl, array( 'pageId' => $value, 'title' => $title, 'label' => $label ), array(), '', false ); + $condition = $this->getAttribute( 'selected' ); + if ( !$condition ) $condition = $value; + $condition = explode( ',', $condition ); + + if ( count( $condition ) > 1 ) + { + $selected = false; + for ($i=0; $i < count( $condition ); $i++) + { + if ( __Request::get( $condition[ $i ] ) == $condition[ $i + 1 ] ) + { + $selected = true; + break; + } + $i++; + } + } + else + { + $selected = $value == $this->_application->getPageId(); + } + + return array( 'url' => $url, 'selected' => $selected ); + } + else if ( $url ) + { + return array( 'url' => org_glizy_helpers_Link::makeSimpleLink($this->addWrap($label), $url, $label, $cssClass ), 'selected' => $value == __Request::get( '__url__' ) ); + } + else if ( $value ) + { + $url = org_glizy_helpers_Link::makeLink( $value, array( 'label' => $this->addWrap($label),'title' => $label, 'cssClass' => $cssClass ), array(), '', false ); + return array( 'url' => $url, 'selected' => $value == __Request::get( '__url__' ) ); + } + else + { + return array( 'url' => '<span class="'.$cssClass.'">'.$label.'</span>', 'selected' => false ); + } + } + + private function addWrap($label) { + $wrapTag = $this->getAttribute('wrapTag'); + if ($wrapTag) { + $label = '<'.$wrapTag.'>'.$label.'</'.$wrapTag.'>'; + } + return $label; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Login.php b/src/core/classes/org/glizy/components/Login.php new file mode 100755 index 0000000..3acb827 --- /dev/null +++ b/src/core/classes/org/glizy/components/Login.php @@ -0,0 +1,41 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Login extends org_glizy_components_LoginBox +{ + var $_error = NULL; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('accessPageId', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('allowGroups', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('backend', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('errorLabel', false, __T('GLZ_LOGIN_ERROR'), COMPONENT_TYPE_STRING); + $this->defineAttribute('userField', false, 'loginuser', COMPONENT_TYPE_STRING); + $this->defineAttribute('passwordField', false, 'loginpsw', COMPONENT_TYPE_STRING); + $this->defineAttribute('rememberField', false, 'loginremember', COMPONENT_TYPE_STRING); + + parent::init(); + } + + function render_html() + { + if (!is_null($this->_content['errorLabel'])) + { + $this->addOutputCode($this->_content['errorLabel']); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/LoginBox.php b/src/core/classes/org/glizy/components/LoginBox.php new file mode 100755 index 0000000..c0a6a65 --- /dev/null +++ b/src/core/classes/org/glizy/components/LoginBox.php @@ -0,0 +1,153 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_components_LoginBox + */ +class org_glizy_components_LoginBox extends org_glizy_components_Component +{ + var $_error = NULL; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('accessPageId', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('allowGroups', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('askPasswordLabel', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('askPasswordUrl', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('backend', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('confirmLabel', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('errorLabel', false, __T('GLZ_LOGIN_ERROR'), COMPONENT_TYPE_STRING); + $this->defineAttribute('userLabel', false, __T('GLZ_USER_LOGINID'), COMPONENT_TYPE_STRING); + $this->defineAttribute('userField', false, 'loginuser', COMPONENT_TYPE_STRING); + $this->defineAttribute('passwordLabel', false, __T('GLZ_USER_PASSWORD'), COMPONENT_TYPE_STRING); + $this->defineAttribute('passwordField', false, 'loginpsw', COMPONENT_TYPE_STRING); + $this->defineAttribute('languageLabel', false, __T('GLZ_LANGUAGE'), COMPONENT_TYPE_STRING); + $this->defineAttribute('languageField', false, 'loginlanguage', COMPONENT_TYPE_STRING); + $this->defineAttribute('registrationUrl', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('registrationLabel', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('rememberLabel', false, __T('GLZ_LOGIN_REMEMBER'), COMPONENT_TYPE_STRING); + $this->defineAttribute('rememberField', false, 'remember', COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, '', COMPONENT_TYPE_STRING); + + parent::init(); + } + + function process() + { + // check if the user is already logged + if ($this->_user->isLogged()) { + $this->setAttribute('visible', false); + $this->redirectAfterLogin(); + } + + $submitId = 'submit_'.$this->getId(); + $this->_content['id'] = $this->getId(); + $this->_content['submitName'] = $submitId; + $this->_content['errorLabel'] = ''; + $this->_content['cssClass'] = $this->getAttribute('cssClass'); + $this->_content['userLabel'] = $this->getAttribute('userLabel'); + $this->_content['userField'] = $this->getAttribute('userField'); + $this->_content['passwordLabel'] = $this->getAttribute('passwordLabel'); + $this->_content['passwordField'] = $this->getAttribute('passwordField'); + $this->_content['registrationPage'] = $this->getAttribute('registrationPage'); + $this->_content['registrationLabel'] = $this->getAttribute('registrationLabel'); + $this->_content['confirmLabel'] = $this->getAttribute('confirmLabel'); + $this->_content['rememberLabel'] = $this->getAttribute('rememberLabel'); + $this->_content['askPasswordLabel'] = $this->getAttribute('askPasswordLabel'); + $this->_content['title'] = $this->getAttributeString('title'); + $this->_content['__url__'] = org_glizy_helpers_Link::makeURL($this->getAttribute('registrationUrl')); + $this->_content['askPasswordUrl'] = org_glizy_helpers_Link::makeURL($this->getAttribute('askPasswordUrl')); + + if (__Request::exists($this->_content['userField']) || __Request::exists($this->_content['passwordField'])) { + $authClass = org_glizy_ObjectFactory::createObject(__Config::get('glizy.authentication')); + if ($authClass) { + try { + $allowGroups = $this->getAttribute('allowGroups')!='' ? explode(',', $this->getAttribute('allowGroups')) : array(); + $authClass->setAllowGroups($allowGroups); + $authClass->setOnlyBackendUser($this->getAttribute('backend')); + $authClass->setUserLanguage(__Request::get($this->getAttribute('languageField'))); + $authClass->loginFromRequest($this->getAttribute('userField'), $this->getAttribute('passwordField'), $this->getAttribute('rememberField'), true); + $this->redirectAfterLogin(); + + } catch(org_glizy_authentication_AuthenticationException $e) { + switch ($e->getCode()) { + case org_glizy_authentication_AuthenticationException::EMPTY_LOGINID_OR_PASSWORD: + case org_glizy_authentication_AuthenticationException::WRONG_LOGINID_OR_PASSWORD: + $this->_content['errorLabel'] = $this->getAttribute('errorLabel'); + break; + case org_glizy_authentication_AuthenticationException::USER_NOT_ACTIVE: + case org_glizy_authentication_AuthenticationException::ACCESS_NOT_ALLOWED: + $this->_content['errorLabel'] = org_glizy_locale_Locale::get('GLZ_LOGIN_DISABLED'); + break; + } + } + } else { + // TODO mostrare errore + $this->_content['errorLabel'] = __Config::get('glizy.authentication'); + } + } else { + $this->_content['errorLabel'] = org_glizy_Session::get('glizy.loginError', ''); + org_glizy_Session::remove('glizy.loginError'); + } + } + + private function redirectAfterLogin() + { + $destPage = ''; + $accessPageId = $this->getAttribute('accessPageId'); + if ( $accessPageId && $accessPageId != $this->_application->getPageId() ) { + $destPage = strpos($accessPageId, 'http')!==false ? $accessPageId : org_glizy_helpers_Link::makeUrl('link', array('pageId' => $this->getAttribute('accessPageId'))); + } + $url = org_glizy_Session::get('glizy.loginUrl', $destPage); + if ($url) { + org_glizy_Session::remove('glizy.loginUrl' ); + org_glizy_helpers_Navigation::gotoUrl($url); + } + } +} + +if (!class_exists('org_glizy_components_LoginBox_render')) +{ + class org_glizy_components_LoginBox_render extends org_glizy_components_render_Render + { + function getDefaultSkin() + { + $skin = <<<EOD +<div tal:attributes="id Component/id; class Component/cssClass"> + <h3 tal:content="Component/title" /> + <div> + <form id="" method="post" action="" tal:attributes="id Component/id"> + <p class="error" tal:condition="Component/errorLabel" tal:content="structure Component/errorLabel"></p> + <label tal:attributes="for Component/userField" tal:content="structure Component/userLabel" /><br /> + <input type="text" class="text" tal:attributes="id Component/userField; name Component/userField"/><br /> + <label tal:attributes="for Component/passwordField" tal:content="structure Component/passwordLabel" /><br /> + <input type="password" class="text" tal:attributes="id Component/passwordField; name Component/passwordField"/><br /> + <table> + <tr> + <td><input name="remember" id="remember" value="1" type="checkbox" /><label for="remember" tal:content="structure Component/rememberLabel" /></td> + <td class="submitButton"><input type="submit" class="submitButton" tal:attributes="name Component/submitName;value Component/confirmLabel"/></td> + </tr> + </table> + <a class="link" tal:attributes="href Component/__url__" tal:content="structure Component/registrationLabel"></a><br /> + <a class="link" tal:attributes="href Component/askPasswordUrl" tal:content="structure Component/askPasswordLabel"></a> + </form> + </div> +</div> +EOD; + return $skin; + } + } +} diff --git a/src/core/classes/org/glizy/components/LoginCheck.php b/src/core/classes/org/glizy/components/LoginCheck.php new file mode 100755 index 0000000..52df2ee --- /dev/null +++ b/src/core/classes/org/glizy/components/LoginCheck.php @@ -0,0 +1,51 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_components_LoginCheck extends org_glizy_components_Component +{ + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('text', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('allowGroups', false, '', COMPONENT_TYPE_STRING); + + parent::init(); + } + + function process() + { + $user = &$this->_application->getCurrentUser(); + + $allowGroups = $this->getAttribute('allowGroups')!='' ? explode(',', $this->getAttribute('allowGroups')) : array(); + + if (!$user->isLogged() || !(count($allowGroups) ? in_array($user->groupId, $allowGroups) : true)) + { + $this->breakCycle(); + } + } + + function render() + { + $user = &$this->_application->getCurrentUser(); + $allowGroups = $this->getAttribute('allowGroups')!='' ? explode(',', $this->getAttribute('allowGroups')) : array(); + if (!$user->isLogged() || !(count($allowGroups) ? in_array($user->groupId, $allowGroups) : true)) + { + $this->breakCycle(); + $output = '<div'.($this->getAttribute('cssClass')!='' ? ' class="'.$this->getAttribute('cssClass').'"' : '').'>'.$this->getAttribute('text').'</div>'; + $this->addOutputCode($output); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Logout.php b/src/core/classes/org/glizy/components/Logout.php new file mode 100755 index 0000000..8925436 --- /dev/null +++ b/src/core/classes/org/glizy/components/Logout.php @@ -0,0 +1,31 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Logout extends org_glizy_components_Component +{ + var $_error = NULL; + + /** + * Init + * + * @return void + * @access public + */ + function process() + { + $authClass = org_glizy_ObjectFactory::createObject(__Config::get('glizy.authentication')); + if ($authClass) { + $authClass->logout(); + } + + org_glizy_helpers_Navigation::gotoUrl( GLZ_HOST ); + exit(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/LongText.php b/src/core/classes/org/glizy/components/LongText.php new file mode 100755 index 0000000..45f2692 --- /dev/null +++ b/src/core/classes/org/glizy/components/LongText.php @@ -0,0 +1,149 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_LongText extends org_glizy_components_Text +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('forceP', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('paginate', false, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('parseInternalLinks', false, true, COMPONENT_TYPE_BOOLEAN); + + $this->defineAttribute('adm:rows', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('adm:cols', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('adm:disabled', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:htmlEditor', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:maxLength', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('adm:required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:tinyMCEplugin', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('adm:validationType', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('adm:validationMessage', false, NULL, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + parent::process(); + if ($this->getAttribute('adm:htmlEditor')!==true) + { + //$tagContent = strip_tags($this->getText()); + $tagContent = $this->getText(); + $this->setText($tagContent); + } + else + { + $tagContent = trim($this->getText()); + $tagContent = str_replace(array("\r\n", "\n", "\r"), "", $tagContent); + $this->setText($tagContent); + } + } + + function render_html() + { + $this->addOutputCode($this->getContent()); + } + + /** + * @return string + */ + function getContent() + { + $output = $this->getText(); + if ($this->getAttribute('adm:htmlEditor')!==true) + { + + $output = $this->encodePlainText(); + if ($this->getAttribute('forceP')) + { + $output = org_glizy_helpers_Html::forceP($output); + } + return $output; + } + else + { + $output = javascript_to_html( $output ); + // esegue la paginazione + if (!is_null($this->getAttribute("paginate"))) + { + $paginateClass = &$this->getAttribute("paginate"); + $this->_content = $paginateClass->splitTextResult($output); + } + + if ($this->getAttribute('parseInternalLinks')) { + $output = org_glizy_helpers_Link::parseInternalLinks($output); + } + + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['class'] = $this->getAttribute('cssClass'); + $wrapTag = $this->getAttribute('wrapTag'); + $outputTag = !empty($wrapTag) ? '<'.$wrapTag.' '.$this->_renderAttributes($attributes).'>' : ''; + $outputTag .= $output; + $outputTag .= !empty($wrapTag) ? '</'.$wrapTag.'>' : ''; + return $outputTag; + } + } + + /** + * @return string + */ + function encodePlainText() + { + return str_replace( array("\r\n", "\n", "\r"), "<br />", glz_encodeOutput( str_replace( '<br />', "\r\n", $this->getText() ) ) ); + } + + /** + * @param $node + * + * @return string + */ + public static function translateForMode_edit($node) { + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['type'] = 'multiline'; + $attributes['data'] = ''; + + if (count($node->attributes)) + { + foreach ( $node->attributes as $index=>$attr ) + { + if ($attr->prefix=="adm") + { + $attributes[$attr->name] = $attr->value; + } + } + } + if ($attributes['htmlEditor']=='true') { + $attributes['data'] .= 'type=tinymce'; + } + if (!isset($attributes['cssClass'])) { + $attributes['cssClass'] = '{config:glizy.formElement.admCssClass}'; + } + return org_glizy_helpers_Html::renderTag('glz:Input', $attributes); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Media.php b/src/core/classes/org/glizy/components/Media.php new file mode 100755 index 0000000..5d57dcf --- /dev/null +++ b/src/core/classes/org/glizy/components/Media.php @@ -0,0 +1,158 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Media extends org_glizy_components_Component +{ + var $media; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('directUrl', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('rel', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('linkTitle', false, __T('GLZ_DOWNLOAD_FILE_LINK'), COMPONENT_TYPE_STRING); + + $this->defineAttribute('adm:required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:mediaType', false, 'ALL', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->resetContent(); + + $mediaId = $this->_parent->loadContent($this->getId()); + + + if (is_string($mediaId)) { + $mediaId = json_decode($mediaId); + } + + if (is_object($mediaId)) { + $mediaId = org_glizycms_Glizycms::getMediaArchiveBridge()->getIdFromJson($mediaId); + } + + if (is_numeric($mediaId) && $mediaId > 0) { + $this->attachMedia($mediaId); + } + + $this->processChilds(); + } + + + /** + * Render + * + * @return void + * @access public + */ + function render_html() + { + $this->_render_html(); + $this->addOutputCode($this->_content['__html__']); + } + + function _render_html() + { + if ($this->_content['mediaId']>0) + { + $linkTitle = $this->getAttribute('linkTitle'); + $linkTitle = str_replace('#title#', $this->_content['title'], $linkTitle); + $linkTitle = str_replace('#size#', org_glizy_helpers_String::formatFileSize($this->media->size), $linkTitle); + $originalFileName = $this->media->originalFileName; + $part = explode( '.', $originalFileName ); + $type = ''; + if ( count( $part ) > 1 ) + { + $type = strtoupper( $part[ count( $part ) - 1 ] ); + } + $linkTitle = str_replace('#format#', $type, $linkTitle); + $this->_content['linkTitle'] = $linkTitle; + $this->_content['__url__'] = org_glizy_helpers_Media::getFileUrlById($this->media->id, $this->getAttribute('directUrl')); + $this->_content['__html__'] = org_glizy_helpers_Link::makeSimpleLink($this->_content['title'], + $this->_content['__url__'], + $linkTitle, + $this->getAttribute('cssClass'), + $this->getAttribute('rel')); + + } + } + + + function getContent($parent=NULL) + { + $this->_render_html(); + return $this->_content; + } + + function resetContent() + { + $this->_content = array(); + $this->_content['mediaId'] = 0; + $this->_content['src'] = ''; + $this->_content['title'] = ''; + $this->_content['size'] = ''; + $this->_content['mediaType'] = ''; + $this->_content['__url__'] = ''; + $this->_content['__html__'] = ''; + $this->_content['linkTitle'] = ''; + } + + function attachMedia($mediaId) + { + $this->media = &org_glizycms_mediaArchive_MediaManager::getMediaById($mediaId); + if (is_object($this->media)) + { + $this->_content['mediaId'] = $this->media->id; + $this->_content['src'] = $this->media->getFileName(); + $this->_content['title'] = $this->media->title; + $this->_content['size'] = $this->media->size; + $this->_content['mediaType']= $this->media->type; + } + } + + public static function translateForMode_edit($node) { + $mediaType = $node->hasAttribute('adm:mediaType') ? $node->getAttribute('adm:mediaType') : 'ALL'; + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['data'] = 'type=mediapicker;mediatype='.$mediaType.';preview=false'; + + if (count($node->attributes)) + { + foreach ( $node->attributes as $index=>$attr ) + { + if ($attr->prefix=="adm") + { + $attributes[$attr->name] = $attr->value; + } + } + } + + return org_glizy_helpers_Html::renderTag('glz:Input', $attributes); + } +} diff --git a/src/core/classes/org/glizy/components/MessageBox.php b/src/core/classes/org/glizy/components/MessageBox.php new file mode 100755 index 0000000..98ece22 --- /dev/null +++ b/src/core/classes/org/glizy/components/MessageBox.php @@ -0,0 +1,68 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_MessageBox extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('type', false, 'ALL', COMPONENT_TYPE_STRING); + $this->defineAttribute('message', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('showEmpty', false, false, COMPONENT_TYPE_BOOLEAN); + parent::init(); + } + + + + /** + * Render + * + * @return void + * @access public + */ + function render_html() + { + // get the messages quee + $this->_content = org_glizy_application_MessageStack::get( $this->getAttribute('type') ); + if ( count($this->_content) || $this->getAttribute( 'showEmpty' ) ) + { + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['class'] = $this->getAttribute('cssClass'); + $output = '<div '.$this->_renderAttributes($attributes).'>'; + + if ( count( $this->_content ) ) + { + if ( !is_null( $this->getAttribute( 'message' ) ) ) + { + $output .= '<p>'.$this->getAttribute( 'message' ).'</p>'; + } + + $output .= '<ul>'; + foreach( $this->_content as $v ) + { + $output .= '<li>'.$v.'</li>'; + } + $output .= '</ul>'; + } + + $output .= '</div>'; + $this->addOutputCode($output); + + org_glizy_application_MessageStack::reset( $this->getAttribute('type') ); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/ModelDefine.php b/src/core/classes/org/glizy/components/ModelDefine.php new file mode 100755 index 0000000..5ca4a2e --- /dev/null +++ b/src/core/classes/org/glizy/components/ModelDefine.php @@ -0,0 +1,16 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_ModelDefine extends org_glizy_components_NullComponent +{ + public static function compile($compiler, &$node, &$registredNameSpaces, &$counter, $parent='NULL') + { + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Modifier.php b/src/core/classes/org/glizy/components/Modifier.php new file mode 100755 index 0000000..80bee1e --- /dev/null +++ b/src/core/classes/org/glizy/components/Modifier.php @@ -0,0 +1,61 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Modifier extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('attribute', true, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('value', true, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('target', true, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('reprocess', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('preprocess', false, false, COMPONENT_TYPE_BOOLEAN); + $this->doLater($this, 'preProcess'); + parent::init(); + } + + function preProcess() + { + if ($this->getAttribute('preprocess')) { + $this->modifyComponent(); + } + } + + function process() + { + if (!$this->getAttribute('preprocess')) { + $this->modifyComponent(); + } + } + + private function modifyComponent() + { + if ( !is_null($this->getAttribute('target')) && $this->getAttribute( 'enabled' ) ) + { + $component = &$this->getAttribute('target'); + $value = $this->getAttribute('value'); + $component->setAttribute($this->getAttribute('attribute'), is_object($value) ? '{'.$value->getId().'}' : $value); + if ($this->getAttribute('reprocess')) + { + $component->process(); + } + } + } + + public static function translateForMode_edit($node) { + return ''; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Module.php b/src/core/classes/org/glizy/components/Module.php new file mode 100755 index 0000000..80b8ba7 --- /dev/null +++ b/src/core/classes/org/glizy/components/Module.php @@ -0,0 +1,36 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Module extends org_glizy_components_ComponentContainer +{ + + function __construct(&$application, &$parent, $tagName='', $id='', $originalId='') + { + parent::__construct($application, $parent, $tagName, $id, $originalId); + } + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->canHaveChilds = true; + $this->overrideEditableRegion = false; + + // define the custom attributes + $this->defineAttribute('adm:editComponents', false, array(), COMPONENT_TYPE_ENUM); + + // call the superclass for validate the attributes + parent::init(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/NavigationMenu.php b/src/core/classes/org/glizy/components/NavigationMenu.php new file mode 100755 index 0000000..63e0eb3 --- /dev/null +++ b/src/core/classes/org/glizy/components/NavigationMenu.php @@ -0,0 +1,393 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_NavigationMenu extends org_glizy_components_Component +{ + var $_currentMenuId; + var $_currentMenu; + var $_menuToOpen; + var $_startMenu; + var $_startDepth; + var $_endDepth; + + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('attributeToSelect', false, 'id', COMPONENT_TYPE_STRING); + $this->defineAttribute('selectLink', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('cssClass', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('nestedCssClass', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('depth', false, '+1', COMPONENT_TYPE_STRING); + $this->defineAttribute('flat', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('forceLink', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('showPath', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('maxPathDepth', false, NULL, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('selectParent', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('startFrom', true, '*', COMPONENT_TYPE_STRING); + $this->defineAttribute('startFromDepth', false, NULL, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('showOnlyChilds', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('drawAllChilds', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('type', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('headingTitle', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('headingCssClass', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapTag', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapTagCssClass', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('omitId', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('openFirstLevel', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('cssCurrent', false, 'current', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + + $this->addEventListener(GLZ_EVT_SITEMAP_UPDATE, $this); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + if (is_null($this->getAttribute('type')) || $this->getAttribute('type')==org_glizy_Config::get('DATASOURCE_MODE')) + { + $siteMap = &$this->_application->getSiteMap(); + $this->_currentMenu = &$this->_application->getCurrentMenu(); + } + else + { + switch ($this->getAttribute('type')) + { + case 'db': + $siteMap = &org_glizy_ObjectFactory::createObject('org.glizy.application.SiteMapDB'); + break; + case 'xml': + $siteMap = &org_glizy_ObjectFactory::createObject('org.glizy.application.SiteMapXML'); + break; + case 'pageType': + $siteMap = &org_glizy_ObjectFactory::createObject('org.glizy.application.SiteMap'); + break; + } + $this->_currentMenu = &$siteMap->getHomeNode(); + } + $this->_currentMenuId = $this->_currentMenu->id; + $this->_startMenu = &$this->_currentMenu; + // cerca il menu da dove iniziare a disegnare + $startFrom = explode('-', $this->getAttribute('startFrom')); + switch( $startFrom[0] ) + { + case '*': + break; + case '*parent': + if (count($startFrom)==1) + { + $this->_startMenu = &$this->_currentMenu->parentNode(); + if (is_null($this->_startMenu)) $this->_startMenu = &$this->_currentMenu; + } + else if ($this->_startMenu->depth>=$startFrom[1]) + { + while (true) + { + if ($this->_startMenu->depth==$startFrom[1] || $this->_startMenu->depth<$startFrom[1]) + { + //$startMenu = &$this->_currentMenu; + break; + } + + $tempNode = &$this->_startMenu->parentNode(); + if (is_null($tempNode) || $tempNode->depth==0) + { + // siamo arrivati alla home + $this->_startMenu = NULL; + } + $this->_startMenu = &$tempNode; + } + } + else + { + $this->setAttribute('visible', false); + return; + } + break; + default: + // TODO + // controllare che il menù indicato sia corretto + $this->_startMenu = &$siteMap->getNodeById($startFrom[0]); + break; + } + + // calcola i menù da aprire + $this->_menuToOpen = array(); + if ($this->getAttribute('showPath')===true) + { + $tempNode2 = $this->_application->getCurrentMenu(); + + //do 16/04/2010 + if( $this->getAttribute('openFirstLevel') ) + { + $menuHome = &$siteMap->getNodeById(1); + foreach( $menuHome->attributes['childNodes'] as $childPageId ) + { + $this->_menuToOpen[] = $childPageId; + } + } + + while (true) + { + if(!is_null($this->getAttribute('maxPathDepth'))) + { + if ($tempNode2->depth<=$this->getAttribute('maxPathDepth')) $this->_menuToOpen[] = $tempNode2->id; + } + else + { + $this->_menuToOpen[] = $tempNode2->id; + } + + $tempNode = &$tempNode2->parentNode(); + if (is_null($tempNode) || $tempNode->depth==0) + { + break; + } + $tempNode2 = &$tempNode; + } + } + + $this->_startDepth = is_null($this->getAttribute('startFromDepth')) ? $this->_startMenu->depth : $this->getAttribute('startFromDepth'); + $endDepth = $this->getAttribute('depth'); + if ($endDepth{0}=='+') + { + $this->_endDepth = $this->_startMenu->depth+intval(substr($endDepth, 1)); + } + else + { + $this->_endDepth = intval($endDepth); + } + $this->_content = array(); + } + + + /** + * Render + * + * @return void + * @access public + */ + function render_html() + { + // la creazione del tree viene fatta nel render + // invece che nel process così è possibile per gli altri componenti + // cambiare dinamicamente la struttura del sito + $this->makeNavigationMenu(); + $output = ''; + if (count($this->_content)) + { + $this->_render_html($this->_content, $output); + $tempOutput = ''; + + $wrapTag = $this->getAttribute('wrapTag'); + if (!is_null($wrapTag)) + { + $tempOutput = org_glizy_helpers_Html::renderTag($wrapTag, array('class' => $this->getAttribute('wrapTagCssClass'), false)); + } + if (!is_null($this->getAttribute('headingTitle'))) + { + $title = $this->getAttributeString('title'); + if ( empty( $title ) ) $title = $this->_startMenu->title; + $tempOutput .= org_glizy_helpers_Html::renderTag($this->getAttribute('headingTitle'), array('class' => $this->getAttribute('headingCssClass')), true, $title ); + } + $output = $tempOutput.$output; + if (!is_null($wrapTag)) + { + $output .= org_glizy_helpers_Html::closeTag($wrapTag); + } + } + $this->addOutputCode($output); + } + + function _render_html(&$menu, &$output) + { + $attributes = array(); + $attributes['class'] = $this->getAttribute('cssClass'); + + if (empty($output)) + { + if ( !$this->getAttribute( 'omitId' ) ) $attributes['id'] = $this->getId(); + $attributes['title'] = $this->getAttributeString('title'); + $output .= org_glizy_helpers_Html::renderTag('ul', $attributes, false); + } + else + { + $attributes['class'] = $this->getAttribute('nestedCssClass') ? $attributes['class'] : ''; + $output .= org_glizy_helpers_Html::renderTag('ul', $attributes, false); + } + + for($i=0; $i<count($menu); $i++) + { + if (is_array($menu[$i]['node'])) + { + $this->_render_html($menu[$i]['node'], $output); + $output .= '</li>'; + } + else + { + $cssClass = $menu[$i]['cssClass']; + $selected = $menu[$i]['selected']; + if ($cssClass) { + if ( strpos($selected, 'class="')!==false) { + $selected = str_replace('class="', 'class="'.$cssClass.' ', $selected); + $cssClass = ''; + } + else + { + $cssClass = 'class="'.$cssClass.'"'; + } + } + $attributes = trim($cssClass.' '.$selected); + $output .= '<li'.($attributes ? ' '.$attributes : '').'>'.$menu[$i]['node'].($i+1<count($menu) && is_array($menu[$i+1]['node']) ? '' : '</li>'); + } + } + $output .= '</ul>'; + } + + function makeNavigationMenu() + { + $this->_makeNavigationMenu($this->_startMenu, $this->_endDepth, $this->_content, $this->getAttribute('showOnlyChilds')); + } + + function _makeNavigationMenu(&$node, $endDepth, &$menu, $skip=false) + { + $skip = !$skip ? $node->depth<$this->_startDepth : $skip; + if ($node->type == 'BLOCK') return true; + if ($node->depth > $endDepth) return true; + if ($node->isVisible==0) return true; + if (is_string($node->isVisible) && preg_match("/\{php\:.*\}/i", $node->isVisible)) { + $phpcode = org_glizy_helpers_PhpScript::parse($node->isVisible); + if (!eval($phpcode)) { + return true; + } + } + + if ($node->type == 'SYSTEM' && !$skip) return true; + if ( !$this->_application->canViewPage( $node->id ) ) return true; + + $nodeTitle = empty($node->titleLink) ? $node->title : $node->titleLink; + $nodeDescription = empty($node->linkDescription) ? $nodeTitle: $node->linkDescription; + $menuNode = array(); + if (!$skip) + { + $menuNode['id'] = $node->id; + $menuNode['title'] = $nodeTitle; + $menuNode['label'] = $nodeDescription; + $menuNode['depth'] = $node->depth; + $menuNode['type'] = $node->pageType; + $menuNode['cssClass'] = $node->cssClass; + $menuNode['haveChild'] = $node->hasChildNodes(); + if ($this->_currentMenuId==$node->id && !$this->getAttribute('forceLink')) + { + $menuNode['node'] = $nodeTitle; + } + else + { + $cssClass = $this->getAttribute('selectLink') && $this->_currentMenuId==$node->id ? $this->getAttribute('cssCurrent') : ''; + if (empty($node->url)) + { + $linkParams = array('pageId' => $node->id, 'title' => $nodeDescription, 'label' => $nodeTitle, 'cssClass' => $cssClass, 'icon' => $node->icon ); + $menuNode['node'] = org_glizy_helpers_Link::makeLink('link', $linkParams); + } + else + { + $url = $node->url; + if (strpos($url, 'route:')!==false) { + $url = substr($url, 6); + $url = __Routing::makeUrl($url, __Request::getAllAsArray()); + } + $menuNode['node'] = org_glizy_helpers_Link::makeSimpleLink($nodeTitle, $url, $nodeDescription, $cssClass); + } + } + + if ( !$this->getAttribute('selectLink') ) + { + if ( !$this->getAttribute('selectParent') ) + { + $menuNode['selected'] = ($this->_currentMenuId==$node->id) ? ' '.$this->getAttribute('attributeToSelect').'="'.$this->getAttribute('cssCurrent').'"' : ''; + } + else + { + $parentNode = &$this->_currentMenu->parentNodeByDepth($node->depth); + if (is_object($parentNode) && $node->depth > 1) + { + $menuNode['selected'] = ($parentNode->id==$node->id || $this->_currentMenuId==$node->id) ? ' '.$this->getAttribute('attributeToSelect').'="'.$this->getAttribute('cssCurrent').'"' : ''; + } + } + } + } + + if (count($menuNode)) + { + $menu[] = $menuNode; + } + + if ($node->hasChildNodes()) + { + $childNodes = &$node->childNodes(); + $tempMenu = array(); + for($i=0; $i<count($childNodes); $i++) + { + $newEndDepth = max($this->_endDepth+(in_array($node->id, $this->_menuToOpen) ? 1:0), $node->depth+(in_array($node->id, $this->_menuToOpen) ? 1:0)); + if ($this->getAttribute('showOnlyChilds')) + { + if ( in_array($node->id, $this->_menuToOpen) || + $this->_startMenu->depth==$node->depth || + $this->_currentMenuId==$node->id || + $this->getAttribute('drawAllChilds')) + { + $this->_makeNavigationMenu($childNodes[$i], $newEndDepth, $tempMenu); + } + } + else + { + $this->_makeNavigationMenu($childNodes[$i], $newEndDepth, $tempMenu); + } + } + if (count($tempMenu)) + { + $menuNode['node'] = $tempMenu; + $menuNode['selected'] = ''; + if ($this->getAttribute('flat') && count($menu)) + { + $menu = array_merge($menu, $menuNode['node']); + } + else + { + $menu[] = $menuNode; + } + } + } + if ($skip && count($menu)) + { + $menu = $menu[0]['node']; + } + } + + function siteMapUpdate() + { + $this->process(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/NullComponent.php b/src/core/classes/org/glizy/components/NullComponent.php new file mode 100755 index 0000000..00f8764 --- /dev/null +++ b/src/core/classes/org/glizy/components/NullComponent.php @@ -0,0 +1,17 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_NullComponent +{ + + public static function compile($compiler, &$node, &$registredNameSpaces, &$counter, $parent='NULL') + { + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Number.php b/src/core/classes/org/glizy/components/Number.php new file mode 100755 index 0000000..840ab47 --- /dev/null +++ b/src/core/classes/org/glizy/components/Number.php @@ -0,0 +1,13 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Number extends org_glizy_components_Text +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/OutputFilter.php b/src/core/classes/org/glizy/components/OutputFilter.php new file mode 100755 index 0000000..f43fc03 --- /dev/null +++ b/src/core/classes/org/glizy/components/OutputFilter.php @@ -0,0 +1,62 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_OutputFilter extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('tag', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('filter', true, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('mode', false, 'PRE', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + $this->doLater($this, '_setOutputFilter'); + } + + function _setOutputFilter() + { + $filterName = $this->getAttribute('filter'); + $tag = $this->getAttribute('tag'); + // risovle il nome della classe + if (file_exists(org_glizy_Paths::get('CORE_CLASSES').'org/glizy/filters/'.$filterName.'.php')) + { + $filterName = 'org.glizy.filters.'.$filterName; + glz_import($filterName); + } + else + { + glz_import($filterName); + } + + $className = str_replace('.', '_', $filterName); + if (class_exists($className)) + { + // aggiunge il filtro per essere processato + if ($this->getAttribute('mode')=='PRE') + { + $outputFilters = &org_glizy_ObjectValues::get('org.glizy:components.Component', 'OutputFilter.pre'); + } + else + { + $outputFilters = &org_glizy_ObjectValues::get('org.glizy:components.Component', 'OutputFilter.post'); + } + if (!isset($outputFilters[$tag])) $outputFilters[$tag] = array(); + $outputFilters[$tag][] = $className; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/OutputFilterGroup.php b/src/core/classes/org/glizy/components/OutputFilterGroup.php new file mode 100755 index 0000000..e783718 --- /dev/null +++ b/src/core/classes/org/glizy/components/OutputFilterGroup.php @@ -0,0 +1,13 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_OutputFilterGroup extends org_glizy_components_ComponentContainer +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Page.php b/src/core/classes/org/glizy/components/Page.php new file mode 100755 index 0000000..9960993 --- /dev/null +++ b/src/core/classes/org/glizy/components/Page.php @@ -0,0 +1,135 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Page extends org_glizy_components_ComponentContainer +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->acceptOutput = true; + $this->overrideEditableRegion = false; + + // define the custom attributes + $this->defineAttribute('defaultEditableRegion', false, 'content', COMPONENT_TYPE_STRING); + $this->defineAttribute('templateType', false, 'php', COMPONENT_TYPE_STRING); + $this->defineAttribute('templateFileName', true, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('adm:editComponents', false, array(), COMPONENT_TYPE_ENUM); + $this->defineAttribute('addCoreJS', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('allowModulesSnippets', false, false, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + if ( !$this->_application->canViewPage() ) + { + org_glizy_Session::set('glizy.loginUrl', org_glizy_helpers_Link::scriptUrl()); + org_glizy_helpers_Navigation::gotoUrl( org_glizy_helpers_Link::makeUrl( 'accessDenied' ) ); + } + + $this->processChilds(); + } + + + /** + * Render + * + * @return string + * @access public + */ + function render() + { + $t = ''; + $this->applyOutputFilters('pre', $t); + $this->renderChilds(); + return $this->_render(); + } + + function _render() + { + if ( $this->getAttribute( 'addCoreJS' ) === true ) + { + $this->_application->addJSLibCore(); + } + + $template = NULL; + + // riordina l'array con i dati dell'editableRegions da passare alla classe template + $templateOutput = array(); + $atEnd = false; + for ($j=0; $j<=1; $j++) + { + for ($i=0; $i<count($this->_output); $i++) + { + if ($this->_output[$i]['atEnd']===($j==0 ? false : true)) + { + if (array_key_exists($this->_output[$i]['editableRegion'], $templateOutput)) + { + $templateOutput[$this->_output[$i]['editableRegion']] .= $this->_output[$i]['code']; + } + else + { + $templateOutput[$this->_output[$i]['editableRegion']] = $this->_output[$i]['code']; + } + } + if ($this->_output[$i]['atEnd']===true) $atEnd = true; + } + if (!$atEnd) break; + } + + if ( org_glizy_ObjectValues::get( 'org.glizy.application', 'pdfMode' ) ) + { + $template = & org_glizy_ObjectFactory::createObject('org.glizy.template.layoutManager.PDF', $this->getAttribute('templateFileName')); + } + else + { + switch ($this->getAttribute('templateType')) + { + case ('dwt'): + $template = & org_glizy_ObjectFactory::createObject('org.glizy.template.layoutManager.DWT', $this->getAttribute('templateFileName')); + break; + case ('phptal'): + $template = & org_glizy_ObjectFactory::createObject('org.glizy.template.layoutManager.PHPTAL', $this->getAttribute('templateFileName')); + break; + case ('php'): + $template = & org_glizy_ObjectFactory::createObject('org.glizy.template.layoutManager.PHP', $this->getAttribute('templateFileName')); + break; + } + } + + $output = $template->apply($templateOutput); + $this->applyOutputFilters('post', $output); + return $output ; + } + + function loadContent($id) + { + return isset($this->_content[$id]) ? $this->_content[$id]['content_value'] : ''; + } + + public function setOutputCode($keyName, $value) { + $this->addOutputCode($value, $keyName); + } +} diff --git a/src/core/classes/org/glizy/components/PageTitle.php b/src/core/classes/org/glizy/components/PageTitle.php new file mode 100755 index 0000000..cfb7a88 --- /dev/null +++ b/src/core/classes/org/glizy/components/PageTitle.php @@ -0,0 +1,107 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_PageTitle extends org_glizy_components_Component +{ + private $currentMenu; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('tag', false, 'h1', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapCssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('wrap', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('drawIcon', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('value', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('menuDepth', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('menuId', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('setSiteMapTitle', false, false, COMPONENT_TYPE_BOOLEAN ); + + // call the superclass for validate the attributes + parent::init(); + + $this->addEventListener(GLZ_EVT_SITEMAP_UPDATE, $this); + $this->addEventListener(GLZ_EVT_PAGETITLE_UPDATE, $this); + } + + + function process() + { + if (is_null($this->getAttribute('value'))) + { + $menuId = $this->getAttribute('menuId'); + $siteMap = &$this->_application->getSiteMap(); + $this->currentMenu = is_null($menuId) ? $this->_application->getCurrentMenu() : $siteMap->getNodeById($menuId); + + if (is_null($this->getAttribute('menuDepth'))) + { + $this->_content = $this->currentMenu->title; + } + else + { + $this->currentMenu = &$this->currentMenu->parentNodeByDepth( $this->getAttribute('menuDepth') ); + $this->_content = $this->currentMenu->title; + } + } + else + { + $this->_content = glz_encodeOutput($this->getAttribute('value')); + } + + if ( $this->getAttribute( 'setSiteMapTitle' ) ) + { + $menu = $this->_application->getCurrentMenu(); + $menu->title = html_entity_decode( $this->_content ); + } + } + + + function render_html() + { + if (!empty($this->_content)) + { + $tag = $this->getAttribute('tag'); + $cssClass = $this->getAttribute('cssClass'); + $output = '<'.$tag.($cssClass ? ' class="'.$cssClass.'"' : '').'>'; + if ($this->getAttribute('drawIcon') && $this->currentMenu->icon) { + $output .= '<i class="'.$this->currentMenu->icon.'"></i> '; + } + $output .= $this->_content.'</'.$tag.'>'; + + if ($this->getAttribute('wrap')) { + $wrapCssClass = $this->getAttribute('wrapCssClass'); + $output = '<div'.($wrapCssClass ? ' class="'.$wrapCssClass.'"' : '').'>'.$output.'</div>'; + } + + $this->addOutputCode($output); + } + } + + function siteMapUpdate($event) + { + if (!is_null($event->data)) { + $this->setAttribute('menuId', $event->data); + } + $this->process(); + } + + function onPageTitleUpdate($event) + { + if (!is_null($event->data)) { + $this->_content = $event->data; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/PaginateResult.php b/src/core/classes/org/glizy/components/PaginateResult.php new file mode 100755 index 0000000..e8f5874 --- /dev/null +++ b/src/core/classes/org/glizy/components/PaginateResult.php @@ -0,0 +1,451 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +if (!defined('GLZ_PAGINATE_PAGE')) define('GLZ_PAGINATE_PAGE', 'pageNum'); + +/** + * Class org_glizy_components_PaginateResult + */ +class org_glizy_components_PaginateResult extends org_glizy_components_Component +{ + var $pageUrl; + var $pageLength; + /** @var org_glizy_SessionEx $_sessionEx */ + var $_sessionEx = NULL; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('pageLength', false, 15, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('showTotal', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('showGoTo', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('showDisabledLinks', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('groupLength', false, 10, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('remember', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:showControl', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('arrowNext', false, '&raquo;', COMPONENT_TYPE_STRING); + $this->defineAttribute('arrowPrev', false, '&laquo;', COMPONENT_TYPE_STRING); + $this->defineAttribute('arrowGroupNext', false, '&raquo;|', COMPONENT_TYPE_STRING); + $this->defineAttribute('arrowGroupPrev', false, '|&laquo;', COMPONENT_TYPE_STRING); + // call the superclass for validate the attributes + parent::init(); + + $this->_sessionEx = org_glizy_ObjectFactory::createObject('org.glizy.SessionEx', $this->getId()); + } + + /** + * @return array|null + */ + function getLimits() + { + if (isset($this->_content['start']) && isset($this->_content['stop'])) + { + return array('start' => $this->_content['start'], 'stop' => $this->_content['stop'], 'pageLength' => $this->_content['pageLength']); + } + else return NULL; + } + + function resetContent() + { + $this->_content = array(); + $this->_content['id'] = $this->getId(); + $this->_content['__cssClass__'] = $this->getAttribute('cssClass'); + $this->_content['pagesLinks'] = array(); + $this->_content['pageLength'] = 0; + $this->_content['start'] = 0; + $this->_content['stop'] = 0; + $this->_content['totalPages'] = 0; + $this->_content['goTo'] = NULL; + $this->_content['totalRecords'] = NULL; + } + + /** + * @param null $recordsCount + * @param null $pageLength + */ + function setRecordsCount($recordsCount=NULL, $pageLength=NULL) + { + if (is_null($pageLength)) { + if ($this->getAttribute('adm:showControl')) { + $content = (int)$this->_parent->loadContent($this->getId()); + if ($content) { + $this->setAttribute('pageLength', $content); + } + } + + $pageLength = $this->getAttribute("pageLength"); + } + + $this->pageUrl = GLZ_PAGINATE_PAGE; + if ( $this->getAttribute('remember')) { + $currentPage = $this->_sessionEx->get($this->pageUrl, '1', true, true); + } + else + { + $currentPage = __Request::get($this->getId().'_'.$this->pageUrl, 1); + } + if (is_null($recordsCount)) + { + $recordsCount = $currentPage * $pageLength; + } + if (($currentPage-1)*$pageLength>$recordsCount) $currentPage = 1; + $this->_sessionEx->set($this->pageUrl, $currentPage); + + $this->resetContent(); + $this->_content['pageLength'] = $pageLength; + $this->_content['currentPage'] = $currentPage; + $this->_content['recordsCount'] = $recordsCount; + + if ($currentPage=="ALL" || $recordsCount==0) + { + $this->_content['start'] = 0; + $this->_content['stop'] = $recordsCount - 1; + $this->_content['totalPages'] = 0; + } + else + { + $this->_content['start'] = ($currentPage-1) * $pageLength; + $this->_content['stop'] = $this->_content['start'] + $pageLength - 1; + $this->_content['totalPages'] = ceil($recordsCount / $pageLength); + } + } + + /** + * @param null $outputMode + * @param bool $skipChilds + */ + function render($outputMode=NULL, $skipChilds=false) + { + if ($this->_content['totalPages']>1) + { + $currentPage = $this->_content['currentPage']; + $groupLength = $this->getAttribute("groupLength"); + $start = 1; + $stop = $this->_content['totalPages']; + $lastLink = array(); + $showDisabledLinks = $this->getAttribute('showDisabledLinks'); + if ($this->_content['totalPages']>$groupLength ) + { + $start = max(1, floor(($currentPage)/$groupLength )*$groupLength ); + $stop = min($this->_content['totalPages'], $start + ($groupLength-1)); + + if ($currentPage!=1 || $showDisabledLinks) + { + $label = $this->getAttribute('arrowGroupPrev'); + if ($label) { + $tempArray = array(); + $tempArray['__cssClass__'] = 'noNumber'; + $tempArray['__url__'] = $currentPage!=1 ? org_glizy_helpers_Link::addParams(array($this->getId().'_'.$this->pageUrl => 1)) : ''; + $tempArray['value'] = $label; + $this->_content['pagesLinks'][]= $tempArray; + } + + $label = $this->getAttribute('arrowPrev'); + if ($label) { + $tempArray = array(); + $tempArray['__cssClass__'] = 'noNumber'; + $tempArray['__url__'] = $currentPage != 1 ? org_glizy_helpers_Link::addParams(array($this->getId() . '_' . $this->pageUrl => max(1, $currentPage - 1))) : ''; + $tempArray['value'] = $label; + $this->_content['pagesLinks'][] = $tempArray; + } + } + + if ($currentPage!=$this->_content['totalPages'] || $showDisabledLinks ) + { + $label = $this->getAttribute('arrowNext'); + if ($label) { + $tempArray = array(); + $tempArray['__cssClass__'] = 'noNumber'; + $tempArray['__url__'] = $currentPage != $this->_content['totalPages'] ? org_glizy_helpers_Link::addParams(array($this->getId() . '_' . $this->pageUrl => min($this->_content['totalPages'], $currentPage + 1))) : ''; + $tempArray['value'] = $label; + $lastLink[] = $tempArray; + } + $label = $this->getAttribute('arrowGroupNext'); + if ($label) { + $tempArray = array(); + $tempArray['__cssClass__'] = 'noNumber'; + $tempArray['__url__'] = $currentPage != $this->_content['totalPages'] ? org_glizy_helpers_Link::addParams(array($this->getId() . '_' . $this->pageUrl => $this->_content['totalPages'])) : ''; + $tempArray['value'] = $label; + $lastLink[] = $tempArray; + } + } + } + for ($i = $start; $i<=$stop; $i++) + { + $tempArray = array(); + $tempArray['__cssClass__'] = $currentPage==$i ? 'current' : 'number'; + $tempArray['__cssClass__'] .= $i == $start ? ($tempArray['__cssClass__']!='' ? ' ' : '').'first' : ''; + $tempArray['__cssClass__'] .= $i == $stop ? ($tempArray['__cssClass__']!='' ? ' ' : '').'last' : ''; + $tempArray['__url__'] = ''; + $tempArray['value'] = $i; + + if ($currentPage!=$i) $tempArray['__url__'] = org_glizy_helpers_Link::addParams(array($this->getId().'_'.$this->pageUrl => $i)); + $this->_content['pagesLinks'][]= $tempArray; + } + if (count($lastLink)) $this->_content['pagesLinks'] = array_merge($this->_content['pagesLinks'], $lastLink); + } + $this->_content['goTo'] = ''; + if ($this->getAttribute('showGoTo')) + { + $form = '<form action="'.org_glizy_helpers_Link::addParams(array()).'" method="post">'; + $form .= '<input class="page" type="text" onfocus="this.value=\'\';" value="#" name="'.$this->getId().'_'.$this->pageUrl.'"/>'; + $form .= '<input class="go" type="image" src="'.org_glizy_Assets::get('ICON_GO').'"/>'; + $form .= '</form>'; + $this->_content['goTo'] = $form; + } + if ($this->getAttribute('showTotal')) + { + $this->_content['totalRecords'] = $this->_content['recordsCount']; + } + + parent::render( $outputMode, $skipChilds ); + } + + /** + * @param $records + * @param null $pageLength + * + * @return array + */ + function splitResult(&$records, $pageLength=NULL) + { + if (is_null($pageLength)) $pageLength = $this->getAttribute("pageLength"); + $this->setRecordsCount(count($records), $pageLength); + $currentPage = $this->_sessionEx->get($this->pageUrl, '1', true, true); + if ($currentPage=="ALL" || !count($records)) + { + return $records; + } + else + { + return array_slice($records, $this->_content['start'], $pageLength); + } + } + + /** + * @param $records + * + * @return mixed + */ + function splitTextResult($records) + { + $records = $this->htmlParsingSplitter($records,'hr'); + $this->pageUrl = GLZ_PAGINATE_PAGE; // TODO sostituire con un attributo + $currentPage = $this->_sessionEx->get($this->pageUrl, '1', true, true); //org_glizy_Request::get($this->pageUrl, '1'); + + if (($currentPage-1)>=count($records)) $currentPage = 1; + $this->_sessionEx->set($this->pageUrl, $currentPage); + + $this->resetContent(); + $this->_content['pagesLinks'] = array(); + $this->_content['pageLength'] = 1; + $this->_content['currentPage'] = $currentPage; + + $result = array(); + if ($currentPage=="ALL" || !count($records)) + { + $this->_content['start'] = 0; + $this->_content['stop'] = count($records) - 1; + $this->_content['totalPages'] = 0; + $result = $records; + } + else + { + $this->_content['start'] = $currentPage-1; + $this->_content['stop'] = $this->_content['start']; + $this->_content['totalPages'] = count($records); + $result = array_slice($records, $this->_content['start'], 1); + } + + if ($this->_content['totalPages']>1) + { + for ($i = 1;$i<=$this->_content['totalPages'];$i++) + { + $tempArray = array(); + $tempArray['__cssClass__'] = ''; + $tempArray['__url__'] = ''; + $tempArray['value'] = $i; + + if ($i==$this->_content['totalPages']) $tempArray['__cssClass__'] = "last"; + if ($currentPage!=$i) $tempArray['__url__'] = org_glizy_helpers_Link::addParams(array($this->getId().'_'.$this->pageUrl => $i)); + $this->_content['pagesLinks'][]= $tempArray; + } + + } + + if ($this->getAttribute('showTotal')) + { + $this->_content['totalRecords'] = count($records); + } + return $result[0]; + } + + /** + * @param $source + * @param string $delimiter + * + * @return array + */ + function htmlParsingSplitter($source, $delimiter='hr') + { + if (strpos($source, '<'.$delimiter)===false) + { + return array($source); + } + $stack = array(); + $pages = array(); + $output=''; + $c=''; + $i=0; + $skip=false; + $ordA=ord('A'); + $ordZ=ord('Z'); + $orda=ord('a'); + $ordz=ord('z'); + $ord0=ord('0'); + $ord9=ord('9'); + while (strlen($source)) + { + while (strlen($source) && ($c=substr($source,0,1))!='<') + { + $output .= $c; + $source = substr($source,1); + } + if (!strlen($source)) + break; + // Apertura di un tag + if (substr($source,1,1)!='/') + { + $tag=''; + $source = substr($source,1); + do { + $tag.=$c=substr($source,0,1); + $source = substr($source,1); + $ordc=ord($c); + } while (strlen($source) && + ( + ($ordc>=$ordA && $ordc<=$ordZ) + || ($ordc>=$orda && $ordc<=$ordz) + || ($ordc>=$ord0 && $ordc<=$ord9) + ) + ); + if (!strlen($source)) + break; + $source = substr($tag,-1).$source; + $tag = substr($tag,0,-1); + // Tag normale + if (strtolower($tag)!=$delimiter) + { + // Skip � true se il tag � un tag autochiuso tipo <ciao/> + $i=0; + $skip=false; + while (!$skip && $i<strlen($source) && substr($source,$i,1)!='>') + $skip = substr($source,$i++,2)=='/>'; + if ($i<strlen($source) && !$skip) + array_push($stack,$tag); + $output.='<'.$tag; + } + else + // Delimitatore + { + $stack2 = $stack; + while (count($stack2)) + $output .= '</'.array_pop($stack2).'>'; + array_push($pages, $output); + $output=''; + $stack2 = $stack; + while (count($stack2)) + $output ='<'.array_shift($stack2).'>'; + while (strlen($source) && substr($source,0,1)!='>') + $source = substr($source,1); + if (strlen($source) && substr($source,0,1)=='>') + $source = substr($source,1); + } + } + // Chiusura di un tag + else + { + $tag=''; + $source = substr($source,2); + do { + $tag.=$c=substr($source,0,1); + $source = substr($source,1); + $ordc=ord($c); + } while (strlen($source) && + ( + ($ordc>=$ordA && $ordc<=$ordZ) + || ($ordc>=$orda && $ordc<=$ordz) + || ($ordc>=$ord0 && $ordc<=$ord9) + ) + ); + if (!strlen($source)) + break; + $source = substr($tag,-1).$source; + $tag = substr($tag,0,-1); + if (($lasttag=array_pop($stack))!=$tag) + array_push($stack,$lasttag); + $output.='</'.$tag; + } + } + while (count($stack)) + $output .= '</'.array_pop($stack).'>'; + if (strlen($output)) + array_push($pages,$output); + return $pages; + } + + public static function translateForMode_edit($node) { + if ($node->hasAttribute('adm:showControl') && $node->getAttribute('adm:showControl') == 'true') { + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['size'] = 10; + return org_glizy_helpers_Html::renderTag('glz:Input', $attributes); + } + } +} + +/** + * Class org_glizy_components_PaginateResult_render + */ +class org_glizy_components_PaginateResult_render extends org_glizy_components_render_Render +{ + + /** + * @return string + */ + function getDefaultSkin() + { + $skin = <<<EOD +<div tal:attributes="id PaginateResult/id;class PaginateResult/__cssClass__" tal:condition="php: count(PaginateResult['pagesLinks']) || !is_null(PaginateResult['totalRecords'])"> + <span tal:condition="php: !is_null(PaginateResult['totalRecords'])" > + <span tal:omit-tag="" tal:content="php: __T('GLZ_TOTAL_RECORDS')" /> <span tal:omit-tag="" tal:content="structure PaginateResult/totalRecords" /> + </span> + <ul tal:condition="php: count(PaginateResult['pagesLinks'])"> + <li tal:repeat="item PaginateResult/pagesLinks" tal:attributes="class item/__cssClass__"> + <a href="" tal:condition="php: item['__url__'] != ''" tal:attributes="href structure item/__url__" tal:content="structure item/value">1</a> + <span tal:condition="php: item['__url__'] == ''" tal:content="structure item/value">1</span> + </li> + <span tal:condition="PaginateResult/goTo" tal:omit-tag=""> + <li tal:content="structure PaginateResult/goTo" /> + </span> + </ul> +</div> +EOD; + return $skin; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Panel.php b/src/core/classes/org/glizy/components/Panel.php new file mode 100755 index 0000000..b145948 --- /dev/null +++ b/src/core/classes/org/glizy/components/Panel.php @@ -0,0 +1,77 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Panel extends org_glizy_components_ComponentContainer +{ + var $_isEnabled; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('tag', false, 'div', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('text', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('adm:showControl', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('addInnerDiv', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('innerCssClass', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + function process() + { + $this->_isEnabled = $this->getAttribute('adm:showControl') ? $this->_parent->loadContent($this->getId())=="1" : true; + + + if ($this->_isEnabled) + { + $this->processChilds(); + } + } + + function render($outputMode=NULL, $skipChilds=false) + { + if ($this->_isEnabled || $outputMode != 'html') + { + parent::render( $outputMode, $skipChilds ); + } + } + + /** + * Render + * + * @return void + * @access public + */ + function render_html_onStart() + { + $innserCssClass = $this->getAttribute('innerCssClass'); + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['class'] = $this->getAttribute('cssClass'); + $this->addOutputCode('<'.$this->getAttribute('tag').' '.$this->_renderAttributes($attributes).'>'. + ( $this->getAttribute( 'addInnerDiv' ) ? '<div'.($this->_renderAttributes(array('class' => $innserCssClass))).'>' : '' ). + $this->getAttribute('text') + ); + } + + function render_html_onEnd() + { + $this->addOutputCode( ( $this->getAttribute( 'addInnerDiv' ) ? '</div>' : '' ).'</'.$this->getAttribute('tag').'>'); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/PdfButton.php b/src/core/classes/org/glizy/components/PdfButton.php new file mode 100755 index 0000000..9b9a978 --- /dev/null +++ b/src/core/classes/org/glizy/components/PdfButton.php @@ -0,0 +1,40 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_PdfButton extends org_glizy_components_Component +{ + var $isEnabled; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', false, __T( 'GLZ_PRINT_PDF' ), COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + function render_html() + { + if( $this->_application->getCurrentMenu()->printPdf && !org_glizy_ObjectValues::get( 'org.glizy.application', 'pdfMode' ) ) + { + $url = GLZ_HOST."/index.php?".__Request::get( '__url__' )."&printPdf=1"; + $output = __Link::makeSimpleLink( $this->getAttribute( 'label' ), $url, '', 'printPdf' ); + $this->addOutputCode( $output ); + } + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/RadioButton.php b/src/core/classes/org/glizy/components/RadioButton.php new file mode 100755 index 0000000..0713e3c --- /dev/null +++ b/src/core/classes/org/glizy/components/RadioButton.php @@ -0,0 +1,102 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_RadioButton extends org_glizy_components_HtmlFormElement +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('bindTo', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClassLabel', false, __Config::get('glizy.formElement.cssClassLabel'), COMPONENT_TYPE_STRING); + $this->defineAttribute('disabled', false, NULL, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('labelPosition', false, 'left', COMPONENT_TYPE_STRING); + $this->defineAttribute('required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('value', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('defaultValue', false, '0', COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapLabel', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('name', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('checkedValue', false, '1', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_content = $this->getAttribute('value'); + if (is_object($this->_content)) + { + $contentSource = &$this->getAttribute('value'); + $this->_content = $contentSource->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + else if (is_null($this->_content)) + { + // richiede il contenuto al padre + $this->_content = $this->_parent->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + + if (is_null($this->_content) || $this->_content=='') + { + // imposta il valore di default + $this->_content = $this->getAttribute('defaultValue'); + } + } + + function render_html() + { + $attributes = $this->getContent(true); + $output = '<input '.$this->_renderAttributes($attributes).'/>'; + + $this->_rightLabel = $this->getAttribute('labelPosition')=='right'; + $cssClassLabel = $this->getAttribute( 'cssClassLabel' ); + $cssClassLabel .= ( $cssClassLabel ? ' ' : '' ).($this->getAttribute('required') ? 'required' : ''); + if ($this->getAttribute('wrapLabel')) { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), true, $output, array('class' => $cssClassLabel ), false); + $output = ''; + } else { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), false, '', array('class' => $cssClassLabel ), false); + } + $this->addOutputCode($this->applyItemTemplate($label, $output)); + } + + function getContent($internal=false) + { + $name = $this->getAttribute( 'name' ); + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['name'] = empty( $name ) ? $this->getOriginalId() : $name ; + $attributes['class'] = $this->getAttribute('required') ? 'required' : ''; + $attributes['class'] .= $this->getAttribute( 'cssClass' ) != '' ? ( $attributes['class'] != '' ? ' ' : '' ).$this->getAttribute( 'cssClass' ) : ''; + $attributes['type'] = 'radio'; + $attributes['disabled'] = $this->getAttribute('readOnly') ? 'readonly' : ''; + + $attributes['value'] = $this->getAttribute( 'checkedValue' ); + if ( $attributes['value'] == "" ) $attributes['value'] = $attributes['id']; + $attributes['checked'] = $this->_content == $attributes['value'] ? 'checked' : ''; + if (!$internal) $attributes['label'] = $this->encodeOuput($this->getAttribute('label')); + $attributes['title'] = $this->getAttributeString('title'); + return $attributes; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/RecordDetail.php b/src/core/classes/org/glizy/components/RecordDetail.php new file mode 100755 index 0000000..8885c64 --- /dev/null +++ b/src/core/classes/org/glizy/components/RecordDetail.php @@ -0,0 +1,137 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_RecordDetail extends org_glizy_components_ComponentContainer +{ + protected $recordId; + protected $ar; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('dataProvider', true, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('idName', false, 'id', COMPONENT_TYPE_STRING); + $this->defineAttribute('routeUrl', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('ogTitle', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('modifyBreadcrumbs', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('processCell', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('processCellParams', false, NULL, COMPONENT_TYPE_STRING); + + parent::init(); + } + + + function process() + { + $this->recordId = org_glizy_Request::get($this->getAttribute('idName'), NULL); + if (is_null($this->recordId)) return; + + $dataProvider = &$this->getAttribute('dataProvider'); + if ($dataProvider) { + $this->ar = $dataProvider->load($this->recordId); + $processCell = org_glizy_ObjectFactory::createObject($this->getAttribute('processCell'), $this->_application); + if ($processCell) { + $ar = &$this->ar; + call_user_func_array(array($processCell, 'renderCell'), array($ar, $this->getAttribute('processCellParams'))); + } + $this->_content = org_glizy_ObjectFactory::createObject('org.glizy.components.RecordDetailVO', $this->ar); + + $ogTitle = $this->getAttribute('ogTitle'); + if ($ogTitle) { + org_glizy_ObjectValues::set('org.glizy.og', 'title', $this->ar->{$ogTitle}); + if ($this->getAttribute('modifyBreadcrumbs')) { + $evt = array('type' => GLZ_EVT_BREADCRUMBS_UPDATE, 'data' => $this->ar->{$ogTitle}); + $this->dispatchEvent($evt); + + $evt = array('type' => GLZ_EVT_PAGETITLE_UPDATE, 'data' => $this->ar->{$ogTitle}); + $this->dispatchEvent($evt); + } + } +// TODO controllare che i dati siano stati caricati correttamento + } else { +// TODO generare errore, dataprovider non valid + } + + $this->_content->__url__ = !is_null( $this->getAttribute( 'routeUrl' ) ) ? org_glizy_helpers_Link::makeURL( $this->getAttribute( 'routeUrl' ), $this->_content) : ''; + parent::process(); + } + + + function getContent() + { + if (count($this->childComponents)) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $id = preg_replace('/^'.$this->getId().'\-/', '', $this->childComponents[$i]->getId()); + $r = $this->childComponents[$i]->getContent(); + $this->_content->{$id} = $r; + } + } + + return $this->_content; + } + + + function loadContent($id) + { + $id = preg_replace('/^'.$this->getId().'\-/', '', $id); + return $this->_content->{$id}; + } + + public function getRecordId() + { + return $this->recordId; + } + + public function getRecord() + { + return $this->ar; + } +} + +class org_glizy_components_RecordDetailVO +{ + private $content; + function __construct( $content ) + { + $this->content = $content; + } + + public function __get($name) + { + $value = $this->content->{$name}; + if (is_string($value) && strrpos($value, '<')!==false) { + // TODO migliorare + $value = org_glizy_helpers_Link::parseInternalLinks($value); + } + return $value; + } +} + + +if (!class_exists("org_glizy_components_RecordDetail_render")) +{ + class org_glizy_components_RecordDetail_render extends org_glizy_components_render_Render + { + function getDefaultSkin() + { + $skin = <<<EOD +<span>ERROR: custom skin required<br /></span> +EOD; + return $skin; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/RecordDetailEx.php b/src/core/classes/org/glizy/components/RecordDetailEx.php new file mode 100755 index 0000000..f18fc95 --- /dev/null +++ b/src/core/classes/org/glizy/components/RecordDetailEx.php @@ -0,0 +1,259 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_RecordDetailEx extends org_glizy_components_Component +{ + var $recordId; + var $items = array(); + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('dataProvider', true, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('idName', false, 'id', COMPONENT_TYPE_STRING); + $this->defineAttribute('getRelations', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('routeUrl', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('query', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('createModelComponents', false, true, COMPONENT_TYPE_BOOLEAN); + parent::init(); + } + + + function process() + { + $this->recordId = org_glizy_Request::get($this->getAttribute('idName'), NULL); + if (is_null($this->recordId)) return; + + $dataProvider = &$this->getAttribute('dataProvider'); + $ar = &$dataProvider->getNewObject(); + $versionFieldName = $ar->getVersionFieldName(); + $languageFieldName = $ar->getLanguageFieldName(); + + if (is_null($versionFieldName)) + { + $ar->load( $this->recordId, $this->getAttribute('query') ); + $this->_content = $ar->getValuesAsArray( $this->getAttribute('getRelations'), true ); + } + else + { + $query = $this->getAttribute('query'); + if ( is_null( $query ) ) + { + $result = $ar->find( array($ar->getPrimaryKey() => $this->recordId, + $versionFieldName => 'PUBLISHED', + $languageFieldName => $this->_application->getLanguageId())); + } + else + { + $result = $ar->load( $this->recordId, null, $query ); + } + + if (!$result) + { + // TODO + // record non trovato + } + else + { + $this->_content = $ar->getValuesAsArray($this->getAttribute('getRelations')); + } + } + + $this->_content['__url__'] = !is_null( $this->getAttribute( 'routeUrl' ) ) ? org_glizy_helpers_Link::makeURL( $this->getAttribute( 'routeUrl' ), $this->_content) : ''; + + // crea i figli + if ( $this->getAttribute( 'createModelComponents' ) ) + { + $this->canHaveChilds = true; + $className = $dataProvider->getRecordClassName(); + $this->createChildsFromModel($className); + $this->processChilds(); + $this->canHaveChilds = false; + } + } + + function render() + { + $content = $this->getContent(); + $outputTitle = ''; + $outputImage = ''; + $outputProperty = ''; + $outputDescription = ''; + + foreach( $this->items as $i ) + { + $value = $content[ $i[ 'field' ] ]; + if ( glz_empty( $value ) ) continue; + if ( is_array( $value ) && $value[ '__html__' ] ) + { + $value = $value[ '__html__' ]; + } + + $renderCell = $i[ 'renderCell' ]; + if ( !empty( $renderCell ) ) + { + if ( !is_object( $renderCell ) ) + { + $renderCell = &org_glizy_ObjectFactory::createObject( $renderCell ); + $i[ 'renderCell' ] = $renderCell; + } + + if ( is_object( $renderCell ) ) + { + $value = $renderCell->renderCell( $value ); + } + } + + $label = $i[ 'label' ]; + if (preg_match("/\{i18n\:.*\}/i", $label)) + { + $code = preg_replace("/\{i18n\:(.*)\}/i", "$1", $label); + $label = org_glizy_locale_Locale::getPlain($code); + } + + if ( $i[ 'type' ] == 'title' ) + { + $outputTitle .= '<h2>'.$value.'</h2>'; + } + else if ( $i[ 'type' ] == 'property' ) + { + $outputProperty .= '<li><span>'.$label.':</span> '.$value.'</li>'; + } + else if ( $i[ 'type' ] == 'description' ) + { + $outputDescription .= '<h3>'.$label.'</h3> '.$value; + } + else if ( $i[ 'type' ] == 'image' ) + { + $outputImage .= $value; + } + } + + $cssClass = $this->getAttribute( 'cssClass' ); + + if ( $outputProperty != '' ) + { + $outputProperty = '<ul>'.$outputProperty.'</ul>'; + } + + if ( $outputImage != '' ) + { + $outputImage = '<dic class="row"><div class="three columns images">'.$outputImage.'</div>'; + $outputProperty = '<div class="eight columns">'.$outputProperty.'</div></div>'; + } + + + + $output = '<div id="'.$this->getOriginalId().'"'.( $cssClass != "" ? ' class="'.$cssClass.'"' : '' ).'>'; + $output .= $outputTitle.$outputImage.$outputProperty.$outputDescription; + $output .= '</div>'; + + $this->addOutputCode( $output ); + } + + function getContent() + { + return $this->getChildContent(); + } + + function getChildContent() + { + $result = array(); + if (is_null($this->recordId)) return $result; + + if (count($this->childComponents)) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $id = preg_replace('/^'.$this->getId().'\-/', '', $this->childComponents[$i]->getId()); + $r = $this->childComponents[$i]->getContent(); + if ($this->childComponents[$i]->_tagname=='glz:Groupbox') + { + // TODO + // da risolvere in modo differente + // ci sono TAG che sono solo container + // quindi deveno passare il contenuto senza essere inseriti nel result + // penso che il modo migliore + // sia fare un componente dal quale derivano e poi verificare la subclass + // oppure aggiungere una nuova proprietà a componentContainer + // in fin dei conti se un componentContainer non accetta l'outputnon dovrebbe avere un contenuto proprio + // ma questa è una cosa da verificare bene + $result = array_merge($result, $r); + } + else + { + + $result[$id] = $r; + } + } + $result['__url__'] = $this->_content['__url__']; + return $result; + } + else + { + return $this->_content; + } + } + + function loadContent($id) + { + $id = preg_replace('/^'.$this->getId().'\-/', '', $id); + return isset($this->_content[$id]) ? $this->_content[$id] : ''; + } + + + function addItem( $i ) + { + $this->items[] = $i; + } + + + public static function compile($compiler, &$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix, $componentClassInfo, $componentId) + { + $compiler->_classSource .= '$n'.$counter.' = &org_glizy_ObjectFactory::createComponent(\''.$componentClassInfo['classPath'].'\', $application, '.$parent.', \''.$node->nodeName.'\', '.$idPrefix.'\''.$componentId.'\', \''.$componentId.'\', $skipImport)'.GLZ_COMPILER_NEWLINE; + + if ($parent!='NULL') + { + $compiler->_classSource .= $parent.'->addChild($n'.$counter.')'.GLZ_COMPILER_NEWLINE; + } + + if (count($node->attributes)) + { + // compila gli attributi + $compiler->_classSource .= '$attributes = array('; + foreach ( $node->attributes as $key=>$value ) + { + if ($key!='id') + { + $compiler->_classSource .= '\''.$key.'\' => \''.addslashes($value).'\', '; + } + } + $compiler->_classSource .= ')'.GLZ_COMPILER_NEWLINE; + $compiler->_classSource .= '$n'.$counter.'->setAttributes( $attributes )'.GLZ_COMPILER_NEWLINE; + } + + foreach ($node->childNodes as $n ) + { + if ( $n->nodeName == "glz:RecordDetailItem" ) + { + $type = $n->hasAttribute( 'type' ) ? $n->getAttribute( 'type' ) : ''; + $field = $n->hasAttribute( 'field' ) ? $n->getAttribute( 'field' ) : ''; + $label = $n->hasAttribute( 'label' ) ? $n->getAttribute( 'label' ) : ''; + $renderCell = $n->hasAttribute( 'renderCell' ) ? $n->getAttribute( 'renderCell' ) : ''; + $compiler->_classSource .= '$n'.$counter.'->addItem( array( "type" => "'.$type.'", "field" => "'.$field.'", "label" => "'.$label.'", "renderCell" => "'.$renderCell.'" ) );'; + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/RecordSetBox.php b/src/core/classes/org/glizy/components/RecordSetBox.php new file mode 100755 index 0000000..161648c --- /dev/null +++ b/src/core/classes/org/glizy/components/RecordSetBox.php @@ -0,0 +1,87 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_RecordSetBox extends org_glizy_components_Component +{ + var $_dataProvider; + + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('cssClass', false, 'even,odd', COMPONENT_TYPE_STRING); + $this->defineAttribute('dataProvider', true, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('filters', false, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('numRecord', false, 5, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('query', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('routeUrl', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('getRelations', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:showControl', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('label', false, '', COMPONENT_TYPE_STRING); + + parent::init(); + } + + function process() + { + $this->_isEnabled = $this->getAttribute('adm:showControl') ? $this->_parent->loadContent($this->getId())=="1" : true; + $this->_content = array(); + $this->_content['records'] = array(); + + if ($this->_isEnabled) + { + $filters = array(); + if (is_object($this->getAttribute("filters"))) + { + $filtersClass = &$this->getAttribute("filters"); + $filters = $filtersClass->getFilters(); + } + + // carica i dati attraverso il componente dataprovider + $this->_dataProvider = &$this->getAttribute('dataProvider'); + if (!is_null($this->_dataProvider)) + { + $iterator = &$this->_dataProvider->loadQuery($this->getAttribute('query'), array( 'filters' => $filters )); + if (!is_null($iterator)) + { + $this->_content['title'] = $this->getAttributeString('title'); + $this->_content['records'] = org_glizy_helpers_ActiveRecord::recordSet2List( $iterator, + $this->getAttribute("routeUrl"), + explode(',', $this->getAttribute('cssClass')), + $this->getAttribute('numRecord'), + array(), + $this->getAttribute("getRelations")); + } + } + else + { + // TODO: fatal error + // visualizzare errore + } + } + } +} + +class org_glizy_components_RecordSetBox_render extends org_glizy_components_render_Render +{ + function getDefaultSkin() + { + $skin = <<<EOD +<span>ERROR: custom skin required<br /></span> +EOD; + return $skin; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/RecordSetList.php b/src/core/classes/org/glizy/components/RecordSetList.php new file mode 100755 index 0000000..7f4426d --- /dev/null +++ b/src/core/classes/org/glizy/components/RecordSetList.php @@ -0,0 +1,282 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_RecordSetList extends org_glizy_components_ComponentContainer +{ + protected $routeUrl = array(); + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('dataProvider', true, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('cssClass', false, 'even,odd', COMPONENT_TYPE_STRING); + $this->defineAttribute('filters', false, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('useQueryParams',false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('paginate', false, NULL, COMPONENT_TYPE_OBJECT); + $this->defineAttribute('query', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('routeUrl', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('processCell', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('processCellParams', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('allowEmptySearch', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:showControl', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('wrapTagCssClass', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('removeTitleWithNoFilter', false, false, COMPONENT_TYPE_BOOLEAN); + parent::init(); + + $this->canHaveChilds = false; + } + + function process() + { + if ($this->getAttribute('adm:showControl')) { + $content = $this->_parent->loadContent($this->getId()); + if (!$content) { + $this->setAttribute('visible', false); + return; + } + } + + $query = $this->getAttribute('query'); + $filtersOrParams = $this->getAttribute('useQueryParams') ? 'params' : 'filters'; + $cssClass = explode(',', $this->getAttribute('cssClass')); + + // load filters + $filtersClass = &$this->getAttribute("filters"); + $filters = is_object($filtersClass) ? $filtersClass->getFilters() : array(); + + // is the filters exists but isn't visible + // the componet title will be removed + if ((!is_object($filtersClass) || !$filtersClass->getAttribute('visible') || !$filtersClass->getAttribute('enabled')) && $this->getAttribute('removeTitleWithNoFilter')) { + $this->setAttribute('title', ''); + } + + + // carica i dati attraverso il componente dataprovider + $dataProvider = &$this->getAttribute('dataProvider'); + if (is_null($dataProvider)) + { + // TODO: fatal error + // visualizzare errore + } + + $skipSearch = false; + if (!$this->getAttribute('allowEmptySearch')) + { + $skipSearch = true; + if (count($filters)) + { + foreach($filters as $k=>$v) + { + if (!empty($v)) + { + $skipSearch = false; + break; + } + } + } + } + + // esegue la paginazione + $paginateClass = $this->getAttribute("paginate"); + $pageLimits = NULL; + if ( !$skipSearch && is_object( $paginateClass ) ) + { + $paginateClass->setRecordsCount(); + $pageLimits = $paginateClass->getLimits(); + } + + $this->_content = new org_glizy_components_RecordSetListVO(); + $this->_content->title = $this->getAttributeString('title'); + $this->_content->cssClass = $this->getAttribute('wrapTagCssClass'); + $this->_content->pageType = $this->_application->getPageType(); + $this->_content->total = 0; + if (!$skipSearch) + { + $iterator = $dataProvider->loadQuery( $query, + array( $filtersOrParams => $filters, + 'limit' => $pageLimits, + 'numRows' => true) + ); + $this->_content->records = new org_glizy_components_RecordSetListIterator( $this->_application, $this, $iterator, $this->routeUrl, $cssClass, $this->getAttribute('processCell'), $this->getAttribute('processCellParams') ); + $this->_content->total = $iterator->count(); + + if ( is_object( $paginateClass ) ) { + $paginateClass->setRecordsCount( $this->_content->total ); + } + } + } + + public function addRoute( $mapTo, $routUrl ) + { + $this->routeUrl[ $mapTo ] = $routUrl; + } + + + public function getContent() + { + if (count($this->childComponents) && $this->_content->total > 0) + { + for ($i=0; $i<count($this->childComponents);$i++) + { + $id = preg_replace('/^'.$this->getId().'\-/', '', $this->childComponents[$i]->getId()); + $this->childComponents[$i]->process(); + $r = $this->childComponents[$i]->getContent($this->_tagname); + $this->_content->records->current()->{$id} = $r; + } + } + + return $this->_content; + } + + function loadContent($id) + { + return $this->_content->records ? $this->_content->records->current()->{$id} : 0; + } + + + public static function compile($compiler, &$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix, $componentClassInfo, $componentId) + { + $compiler->compile_baseTag( $node, $registredNameSpaces, $counter, $parent, $idPrefix, $componentClassInfo, $componentId ); + + $routeUrl = $node->hasAttribute( 'routeUrl' ) ? $node->getAttribute( 'routeUrl' ) : ''; + if ($routeUrl) $compiler->_classSource .= '$n'.$counter.'->addRoute( "__url__", "'.$routeUrl.'" );'; + foreach ($node->childNodes as $n ) + { + if ( $n->nodeName == "glz:routeUrl" ) + { + $mapTo = $n->hasAttribute( 'mapTo' ) ? $n->getAttribute( 'mapTo' ) : ''; + $name = $n->hasAttribute( 'name' ) ? $n->getAttribute( 'name' ) : ''; + if ( $mapTo && $name ) + { + $compiler->_classSource .= '$n'.$counter.'->addRoute( "'.$mapTo.'", "'.$name.'" );'; + } + } else { + $oldcounter = $counter; + $compiler->compileChildren($node, $registredNameSpaces, $counter, $oldcounter, $idPrefix ); + } + } + + return false; + } + + + public static function translateForMode_edit($node) { + if ($node->hasAttribute('adm:showControl') && $node->getAttribute('adm:showControl') == 'true') { + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['data'] = "type=checkbox"; + return org_glizy_helpers_Html::renderTag('glz:Checkbox', $attributes); + } + } + + public function getCount() + { + return $this->_content->total; + } +} + +class org_glizy_components_RecordSetListVO +{ + var $tile = ''; + var $pageType = ''; + var $records = NULL; + var $hasFilter = false; + var $params = NULL; + var $total = 0; + var $cssClass = ''; +} + +class org_glizy_components_RecordSetListIterator extends GlizyObject implements Iterator +{ + private $parent; + private $iterator; + private $routeUrl; + private $cssClass; + private $processCell; + private $currentAr; + private $tempCssClass = array(); + private $processCellParams; + + function __construct( $application, $parent, $iterator, $routeUrl, $cssClass, $processCell=null, $processCellParams=null ) + { + $this->parent = $parent; + $this->iterator = $iterator; + $this->routeUrl = $routeUrl; + $this->cssClass = $cssClass; + $this->processCellParams = $processCellParams; + if ($processCell) { + $this->processCell = org_glizy_ObjectFactory::createObject($processCell, $application); + } + } + + function current() + { + if (!$this->currentAr) { + $this->currentAr = $this->iterator->current(); + + call_user_func(array($this->parent, 'getContent'), array()); + + // aggiunge proprietà dinamiche + if (!count( $this->tempCssClass ) ) + { + $this->tempCssClass = $this->cssClass; + } + $this->currentAr->__cssClass__ = count( $this->tempCssClass ) ? array_shift( $this->tempCssClass ) : ''; + $languageId = $this->parent->_application->getLanguage(); + foreach( $this->routeUrl as $k => $v ) { + if ($k=='__url__' && $this->currentAr->fieldExists('url') && $this->currentAr->url) { + $this->currentAr->$k = $languageId.'/'.$this->currentAr->url; + } else { + $this->currentAr->$k = __Link::makeURL( $v, $this->currentAr->getValuesAsArray() ); + } + } + if ($this->processCell) { + $ar = &$this->currentAr; + call_user_func_array(array($this->processCell, 'renderCell'), array($ar, $this->processCellParams)); + } + + } + return $this->currentAr; + } + + function key() + { + return $this->iterator->key(); + } + + function next() + { + $this->iterator->next(); + $this->currentAr = null; + } + + function rewind() + { + $this->iterator->rewind(); + $this->currentAr = null; + } + + function valid() + { + return $this->iterator->valid(); + } + + function count() + { + return $this->iterator->count(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Repeater.php b/src/core/classes/org/glizy/components/Repeater.php new file mode 100755 index 0000000..1b4645a --- /dev/null +++ b/src/core/classes/org/glizy/components/Repeater.php @@ -0,0 +1,105 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Repeater extends org_glizy_components_ComponentContainer +{ + protected $repeaterId; + protected $repeaterIdLen; + protected $numRecords; + protected $contentCount; + + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + // $this->defineAttribute('start', false, NULL, COMPONENT_TYPE_INTEGER); + // $this->defineAttribute('count', false, NULL, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('newMode', false, false, COMPONENT_TYPE_BOOLEAN); + // $this->defineAttribute('routeUrl', false, NULL, COMPONENT_TYPE_STRING); + + $this->defineAttribute('adm:min', false, NULL, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('adm:max', false, NULL, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('adm:collapsable', false, NULL, COMPONENT_TYPE_INTEGER); + + // call the superclass for validate the attributes + parent::init(); + } + + + function process() + { + $this->repeaterId = $this->getId(); + $this->repeaterIdLen = strlen($this->repeaterId); + $this->_content = $this->_parent->loadContent($this->repeaterId); + $child = $this->childComponents[0]; + $childId = $child->getOriginalId(); + $this->numRecords = count($this->_content->$childId); + } + + + function getContent() + { + $result = array(); + for ($i = 0; $i < $this->numRecords; $i++) { + $this->contentCount = $i; + + $temp = new StdClass; + for ($j = 0; $j < count($this->childComponents); $j++) { + $child = $this->childComponents[$j]; + $child->setContent(null); + $child->process(); + $c = $child->getContent(); + $temp->{$child->getOriginalId()} = $c; + } + $result[] = $temp; + } + if ($this->getAttribute('newMode')) { + $tempResult = new StdClass; + $tempResult->cssClass = $this->getAttribute('cssClass'); + $tempResult->records = $result; + return $tempResult; + } + return $result; + } + + function loadContent($id, $bindTo='') + { + $id = substr($id, $this->repeaterIdLen + 1); + return $this->_content->{$id}[$this->contentCount]; + } + + public static function compileAddPrefix($compiler, &$node, $componentId, $idPrefix) + { + return $idPrefix.'\''.$componentId.'-\'.'; + } + + public static function translateForMode_edit($node) { + $min = $node->hasAttribute('adm:min') ? $node->getAttribute('adm:min') : '0'; + $max = $node->hasAttribute('adm:max') ? $node->getAttribute('adm:max') : '100'; + $collapsable = $node->hasAttribute('adm:collapsable') && $node->getAttribute('adm:collapsable') == 'true' ? 'true' : 'false'; + + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['data'] = 'type=repeat;repeatMin='.$min.';repeatMax='.$max.';collapsable='.$collapsable; + if ($node->hasAttribute('adm:data')) { + $attributes['data'] .= ';'.$node->getAttribute('adm:data'); + } + + return org_glizy_helpers_Html::renderTag('glz:Fieldset', $attributes); + } +} diff --git a/src/core/classes/org/glizy/components/RepeaterRecord.php b/src/core/classes/org/glizy/components/RepeaterRecord.php new file mode 100755 index 0000000..b042646 --- /dev/null +++ b/src/core/classes/org/glizy/components/RepeaterRecord.php @@ -0,0 +1,106 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_RepeaterRecord extends org_glizy_components_ComponentContainer +{ + var $recordId = null; + var $prefix = null; + var $targetId = null; + + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('id', false, NULL, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('target', false, NULL, COMPONENT_TYPE_OBJECT); + + // call the superclass for validate the attributes + parent::init(); + } + + + function process() + { + $this->recordId = org_glizy_Request::get('id', null); + + if (!is_null($this->recordId)) + { + $target = &$this->getAttribute('target'); + + if (is_object($target)) + { + $targetId = $target->getId(); + $prefix = $targetId.($this->recordId > 1 ? '@'.($this->recordId-1) : ''); + + for ($i=0; $i<count($target->childComponents);$i++) + { + $target->childComponents[$i]->setAttribute('id', str_replace($targetId, $prefix, $target->childComponents[$i]->getId())); + $this->addChild($target->childComponents[$i]); + + $target->childComponents[$i]->_parent = &$this; + } + $target->childComponents = array(); + $this->processChilds(); + } + else + { + // TODO + // visualizzare errore + } + } + + } + + function loadContent($id) + { + if (!is_null($this->prefix)) + { + $id = str_replace($this->targetId, $this->prefix, $id); + + } + + return $this->_parent->loadContent($id); + } + + function getContent() + { + $item = array(); + for ($i=0; $i<count($this->childComponents);$i++) + { + $r = $this->childComponents[$i]->getContent(); + if ($this->childComponents[$i]->_tagname=='glz:Groupbox' || get_parent_class($this->childComponents[$i])=='org_glizy_components_emptycomponent') + { + // TODO + // da risolvere in modo differente + // ci sono TAG che sono solo container + // quindi deveno passare il contenuto senza essere inseriti nel result + // penso che il modo migliore + // sia fare un componente dal quale derivano e poi verificare la subclass + // oppure aggiungere una nuova proprietà a componentContainer + // in fin dei conti se un componentContainer non accetta l'outputnon dovrebbe avere un contenuto proprio + // ma questa è una cosa da verificare bene + $item = array_merge($item, $r); + } + else + { + $item[$this->childComponents[$i]->getOriginalId()] = $r; + } + } + + + return $item; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Script.php b/src/core/classes/org/glizy/components/Script.php new file mode 100755 index 0000000..d127d4a --- /dev/null +++ b/src/core/classes/org/glizy/components/Script.php @@ -0,0 +1,40 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + + +class org_glizy_components_Script extends org_glizy_components_NullComponent +{ + + + public static function compile($compiler, &$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix, $componentClassInfo, $componentId) + { + if ( $node->hasAttribute( 'extendParent' ) ) + { + $scriptClassName = $compiler->_className.'__class__'.$counter; + preg_match('/(\\'.$parent.'\s*=\s*&\s*org_glizy_ObjectFactory::createComponent\(\')([^\']*)(.*)/u', $compiler->_classSource, $matches, PREG_OFFSET_CAPTURE); + $originalClassName = str_replace('.', '_', $matches[2][0]); + $compiler->_customClassSource .= 'class '.$scriptClassName.' extends '.$originalClassName.GLZ_COMPILER_NEWLINE2; + $compiler->_customClassSource .= '{'.$node->nodeValue.GLZ_COMPILER_NEWLINE2.'}'.GLZ_COMPILER_NEWLINE2; + $compiler->_classSource = preg_replace('/(\\'.$parent.'\s*=\s*&\s*org_glizy_ObjectFactory::createComponent\(\')([^\']*)/', '$1'.$scriptClassName, $compiler->_classSource); + } + else if ( $node->hasAttribute( 'target' ) ) + { + $scriptClassName = $compiler->_className.'__class__'.$counter; + $compiler->_customClassSource .= 'class '.$scriptClassName.GLZ_COMPILER_NEWLINE2; + $compiler->_customClassSource .= '{'.$node->nodeValue.GLZ_COMPILER_NEWLINE2.'}'.GLZ_COMPILER_NEWLINE2; + $compiler->_classSource .= '$'.$scriptClassName.' = &'.$parent.'->getComponentById(\''.$node->attributes['target'].'\')'.GLZ_COMPILER_NEWLINE; + $compiler->_classSource .= '$'.$scriptClassName.'->setCustomClass(\''.$scriptClassName.'\')'.GLZ_COMPILER_NEWLINE; + } + else + { + $compiler->output .= $node->nodeValue.GLZ_COMPILER_NEWLINE; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Search.php b/src/core/classes/org/glizy/components/Search.php new file mode 100755 index 0000000..8b90f89 --- /dev/null +++ b/src/core/classes/org/glizy/components/Search.php @@ -0,0 +1,121 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Search extends org_glizy_components_Form +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('label', false, org_glizy_locale_Locale::get('GLZ_SEARCH_LABEL'), COMPONENT_TYPE_STRING); + $this->defineAttribute('buttonLabel', false, org_glizy_locale_Locale::get('GLZ_SEARCH_BUTTON'), COMPONENT_TYPE_STRING); + $this->defineAttribute('comment', false, org_glizy_locale_Locale::get('GLZ_SEARCH_COMMENT'), COMPONENT_TYPE_STRING); + $this->defineAttribute('skipFormTag', false, false, COMPONENT_TYPE_BOOLEAN); + parent::init(); + $this->setAttribute('method', 'get'); + } + + function process() + { + if ( !$this->_application->isAdmin() ) + { + $this->_content = array(); + $this->_content['label'] = $this->getAttribute('label'); + $this->_content['buttonLabel'] = $this->getAttribute('buttonLabel'); + $this->_content['comment'] = $this->getAttribute('comment'); + $this->_content['comment1'] = org_glizy_locale_Locale::get('GLZ_SEARCH_RESULT'); + $this->_content['value'] = org_glizy_Request::get('search', ''); + $this->_content['result'] = null; + + // preg_match( '/"([^"]*)"/i', $this->_content['value'], $match ); + // if ( count( $match ) ) + // { + // $searchArray2 = array( $match[ 1 ] ); + // } + // else + // { + // if ($this->getAttribute('explodeWords')) { + // $searchArray = explode(' ', $this->_content['value']); + // $searchArray2 = array(); + + // foreach ($searchArray as $word) + // { + // if (strlen($word)>=3) $searchArray2[] = $word; + // } + // } else { + // $searchArray2 = $this->_content['value']; + // } + // } + + if (strlen($this->_content['value'])>=3) + { + $pluginObj = &org_glizy_ObjectFactory::createObject('org.glizy.plugins.Search'); + $this->_content['result'] = $pluginObj->run(array('search' => $this->_content['value'], 'languageId' => $this->_application->getLanguageId())); + } + + $this->_content['total'] = org_glizy_locale_Locale::get('GLZ_SEARCH_RESULT_TOTAL').' '.count($this->_content['result']); + } + } + + + function render() + { + if ( !$this->_application->isAdmin() ) + { + if ($this->_content['result']) { + org_glizy_helpers_Array::arrayMultisortByLabel($this->_content['result'], '__weight__'); + } + + if (!$this->getAttribute('skipFormTag')) + { + parent::render_html_onStart(); + } + parent::render(); + if (!$this->getAttribute('skipFormTag')) + { + parent::render_html_onEnd(); + } + } + } +} + +class org_glizy_components_Search_render extends org_glizy_components_render_Render +{ + function getDefaultSkin() + { + $skin = <<<EOD +<span tal:omit-tag=""> + <div class="formItem"> + <label for="search" tal:content="Search/label" /> + <input type="text" name="search" id="search" value="" size="20" tabindex="22" class="long" tal:attributes="value Search/value"/> + <input type="submit" class="submitButton" value="cerca" tal:attributes="value Search/buttonLabel"/> + </div> + <p tal:content="structure Search/comment" /> + <span tal:omit-tag="" tal:condition="php: !is_null(Search['result'])" > + <div id="searchResult" tal:condition="php: count(Search['result'])"> + <h2 tal:content="structure Search/comment1"/> + <p tal:content="structure Search/total"/> + <ul> + <li tal:repeat="item Search/result"><strong tal:content="structure item/__url__"></strong> + <p class="small" tal:content="structure item/description" /> + </li> + </ul> + </div> + </span> + <span tal:condition="php: !count(Search['result'])" tal:content="php:__T('MW_NO_RECORD_FOUND')" /> +</span> +EOD; + return $skin; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/SearchBox.php b/src/core/classes/org/glizy/components/SearchBox.php new file mode 100755 index 0000000..3ab1214 --- /dev/null +++ b/src/core/classes/org/glizy/components/SearchBox.php @@ -0,0 +1,83 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_SearchBox extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('label', false, __T('GLZ_SEARCH_LABEL'), COMPONENT_TYPE_STRING); + $this->defineAttribute('buttonLabel', false, __T('GLZ_SEARCH_BUTTON'), COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('searchPageId', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, __T('GLZ_SEARCH_BUTTON'), COMPONENT_TYPE_STRING); + parent::init(); + } + + function process() + { + parent::process(); + $this->_content['id'] = $this->getId(); + $this->_content['cssClass'] = $this->getAttribute('cssClass'); + $this->_content['title'] = $this->getAttributeString('title'); + $this->_content['label'] = $this->getAttributeString('label'); + $this->_content['buttonLabel'] = $this->getAttributeString('buttonLabel'); + $this->_content['value'] = __Request::get('search', ''); + if (!$this->_content['buttonLabel']) { + $this->_content['buttonLabel'] = $this->_content['label']; + } + + $searchPageId = $this->getAttribute('searchPageId'); + + if (!is_int($searchPageId)) { + $siteMap = $this->_application->getSiteMap(); + $menu = $siteMap->getMenuByPageType($searchPageId); + if ($menu && $menu->isVisible) { + $this->_content['__url__'] = org_glizy_helpers_Link::makeURL('link', array('pageId' => $menu->id)); + } else { + $this->setAttribute('visible', false); + } + } else { + $this->_content['__url__'] = org_glizy_helpers_Link::makeURL('link', array('pageId' => $searchPageId)); + } + } +} + +if (!class_exists('org_glizy_components_SearchBox_render')) +{ + class org_glizy_components_SearchBox_render extends org_glizy_components_render_Render + { + function getDefaultSkin() + { + $skin = <<<EOD +<div class="" tal:attributes="class SearchBox/cssClass"> + <h3 tal:content="SearchBox/title" /> + <form id="" method="post" action="" tal:attributes="id SearchBox/id; action SearchBox/__url__"> + <label for="search" tal:content="SearchBox/label" /> + <input type="text" name="search" id="search" class="text" tal:attributes="value SearchBox/value"/> + <br /> + <table> + <tr> + <td class="span"></td> + <td><input type="submit" class="submitButton" tal:attributes="value SearchBox/buttonLabel" /></td> + </tr> + </table> + </form> +</div> +EOD; + return $skin; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/SearchFilters.php b/src/core/classes/org/glizy/components/SearchFilters.php new file mode 100755 index 0000000..cdeb137 --- /dev/null +++ b/src/core/classes/org/glizy/components/SearchFilters.php @@ -0,0 +1,142 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_SearchFilters extends org_glizy_components_Form +{ + protected $_filters = array(); + /** @var org_glizy_SessionEx $sessionEx */ + protected $sessionEx = NULL; + + function init() + { + $this->defineAttribute('cssClass', false, __Config::get('glizy.searchFilters.cssClass'), COMPONENT_TYPE_STRING); + $this->defineAttribute('wrapDiv', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('fieldset', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('rememberValues', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('rememberMode', false, 'persistent', COMPONENT_TYPE_STRING); + $this->defineAttribute('setRequest', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('filterClass', false, '', COMPONENT_TYPE_STRING); + + parent::init(); + } + + function process() + { + $this->sessionEx = new org_glizy_SessionEx($this->getId()); + $this->_command = org_glizy_Request::get($this->getId().'_command'); + $this->rememberMode = $this->getAttribute( 'rememberMode' ) == 'persistent' ? GLZ_SESSION_EX_PERSISTENT : GLZ_SESSION_EX_VOLATILE; + if ($this->_command=='RESET') $this->sessionEx->removeAll(); + $this->processChilds(); + } + + function &getDataProvider() + { + return $this->_dataProvider; + } + + function loadContent($name, $bindToField=NULL, $value=NULL) + { + if (empty($bindToField)) + { + $bindToField = $name; + } + + if ($this->_command=='RESET') + { + $this->_filters[$bindToField] = ''; + } + else + { + if ( $this->getAttribute( 'rememberValues') ) + { + $defValue = !is_null( $this->sessionEx ) ? $this->sessionEx->get($name, '') : ''; + $this->_filters[$bindToField] = org_glizy_Request::get($name, $defValue ); + } + else + { + $this->_filters[$bindToField] = org_glizy_Request::get($name, ''); + } + } + + if ( !is_null( $this->sessionEx ) ) + { + $this->sessionEx->set($name, $this->_filters[$bindToField], $this->rememberMode); + } + + if ( $this->getAttribute('setRequest') ) + { + __Request::set( $name, $this->_filters[$bindToField] ); + } + + return $this->_filters[$bindToField]; + } + + function setFilterValue($name, $value, $originalValue=null) + { + $this->_filters[$name] = $value; + if ( !is_null( $this->sessionEx ) ) + { + $this->sessionEx->set($name, is_null( $originalValue ) ? $value : $originalValue, $this->rememberMode ); + } + } + + function getFilters() + { + $filterClass = org_glizy_ObjectFactory::createObject($this->getAttribute('filterClass')); + if (!$filterClass) { + $tempFilters = $this->_filters; + foreach($this->_filters as $k=>$v) + { + if (strpos($k, ',')!==false ) + { + unset($tempFilters[$k]); + + if (!empty( $v )) { + $fields = explode(',', $k); + $tempOR = array(); + + foreach ($fields as $field) { + $tempOR[$field] = $v; + } + $tempFilters['__OR__'] = $tempOR; + } + } + } + } else { + $tempFilters = $filterClass->getFilters($this->_filters); + } + + return $tempFilters; + } + + function render_html_onStart() + { + if ($this->getAttribute('wrapDiv')) + { + $this->addOutputCode('<div'.$this->_renderAttributes(array('class' => $this->getAttribute('cssClass'))).'>'); + $this->setAttribute('cssClass', ''); + } + parent::render_html_onStart(); + if ($this->getAttribute('fieldset')) $this->addOutputCode('<fieldset>'); + } + + function render_html_onEnd() + { + if ($this->getAttribute('fieldset')) + { + $this->addOutputCode('</fieldset>'); + } + parent::render_html_onEnd(); + if ($this->getAttribute('wrapDiv')) + { + $this->addOutputCode('</div>'); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/SelectPage.php b/src/core/classes/org/glizy/components/SelectPage.php new file mode 100755 index 0000000..14682eb --- /dev/null +++ b/src/core/classes/org/glizy/components/SelectPage.php @@ -0,0 +1,81 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_SelectPage extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('requiredMessage', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('startFrom', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('maxDepth', false, false, COMPONENT_TYPE_STRING); + $this->defineAttribute('pageType', false, '', COMPONENT_TYPE_STRING); + // attributo aggiunto per compatibilità + // il render HTML è abilitato solo se impostato a true + $this->defineAttribute('renderHtml', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('wrapTag', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('generateLink', false, false, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + + function process() + { + $this->_content = $this->_parent->loadContent($this->getId()); + } + + function getContent() + { + if ( !$this->getAttribute( 'generateLink' ) ) + { + return (!is_null($this->_content) && $this->_content > 0) ? org_glizy_helpers_Link::makeURL('link', array('pageId' => $this->_content)) : ''; + } + + $title = $this->getAttribute( 'title' ); + if ( empty( $title ) && !empty( $this->_content ) ) { + $siteMap = $this->_application->getSiteMap(); + $page = $siteMap->getNodeById( $this->_content ); + $title = $page->title; + } + return (!is_null($this->_content) && $this->_content > 0) ? org_glizy_helpers_Link::makeLink('link', array('pageId' => $this->_content, 'title' => $title )) : ''; + } + + function render_html() + { + if ( $this->getAttribute( 'renderHtml' ) ) + { + $tag = $this->getAttribute( 'wrapTag' ); + $label = ( !empty( $tag ) ? '<'.$tag.'>' : '' ) .$this->getAttribute( 'title' ).( !empty( $tag ) ? '</'.$tag.'>' : '' ); + $output = org_glizy_helpers_Link::makeLink('link', array( 'cssClass' => $this->getAttribute( 'cssClass' ), 'label' => $label, 'pageId' => $this->_content)); + $this->addOutputCode( $output ); + } + } + + public static function translateForMode_edit($node) { + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['required'] = $node->getAttribute('required'); + $attributes['xmlns:cms'] = "org.glizycms.views.components.*"; + + return org_glizy_helpers_Html::renderTag('cms:SelectPage', $attributes); + } +} diff --git a/src/core/classes/org/glizy/components/SimpleList.php b/src/core/classes/org/glizy/components/SimpleList.php new file mode 100755 index 0000000..7905ebe --- /dev/null +++ b/src/core/classes/org/glizy/components/SimpleList.php @@ -0,0 +1,83 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_SimpleList extends org_glizy_components_ComponentContainer +{ + var $_items; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('cssClass', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('attributeToSelect', false, 'id', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClassCurrent', false, 'current', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_items = array(); + // legge i valori dai figli + for ($i=0; $i<count($this->childComponents);$i++) + { + if (method_exists($this->childComponents[$i], 'getItem') && + $this->childComponents[$i]->getAttribute( 'visible' ) && + $this->childComponents[$i]->getAttribute( 'enabled' ) ) + { + $item = $this->childComponents[$i]->getItem(); + if ( is_array( $item ) ) + { + $this->_items[] = $item; + } + } + } + + $this->processChilds(); + } + + function render_html() + { + $output = '<ul id="'.$this->getId().'"'.(!is_null($this->getAttribute('cssClass')) ? ' class="'.$this->getAttribute('cssClass').'"' : '').'>'; + foreach($this->_items as $item) + { + $output .= '<li'; + $output .= $item['selected'] ? ' '.$this->getAttribute('attributeToSelect').'="'.$this->getAttribute('cssClassCurrent').'">' : '>'; + if ( isset( $item[ 'url' ] ) ) + { + $output .= $item[ 'url' ]; + } + else if ( !empty( $item['key'] ) ) + { + $output .= org_glizy_helpers_Link::makeLink($item['key'], array('title' => $item['value'], 'cssClass' => @$item['cssClass'] ), array(), '', false ); + } + else + { + $output .= $item['value']; + } + $output .= '</li>'; + } + $output .= '</ul>'; + $this->addOutputCode($output); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/SkinDefine.php b/src/core/classes/org/glizy/components/SkinDefine.php new file mode 100755 index 0000000..e2cb505 --- /dev/null +++ b/src/core/classes/org/glizy/components/SkinDefine.php @@ -0,0 +1,55 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_SkinDefine extends org_glizy_components_Component +{ + var $_templateString; + var $_skinType; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('skinType', false, NULL, COMPONENT_TYPE_STRING); + parent::init(); + } + + + + function process() + { + $this->_skinType = $this->getAttribute('skinType'); + if (is_null($this->_skinType)) + { + $root = &$this->getRootComponent(); + $this->_skinType = $root->getAttribute('skinType'); + $this->setAttribute('skinType', $this->_skinType); + } + $this->_templateString = $this->getText(); + } + + function getTemplateString() + { + if ($this->getAttribute('skinType')=='PHPTAL') + { + $this->_templateString = str_replace('&gt;![CDATA[', '<![CDATA[', $this->_templateString); + $this->_templateString = str_replace(']]&lt;', ']]>', $this->_templateString); + return '<span tal:omit-tag="">'.$this->_templateString.'</span>'; + } + else + { + return $this->_templateString; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/State.php b/src/core/classes/org/glizy/components/State.php new file mode 100755 index 0000000..8aa4494 --- /dev/null +++ b/src/core/classes/org/glizy/components/State.php @@ -0,0 +1,138 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_State extends org_glizy_components_ComponentContainer +{ + var $_state; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('name', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('forceChildCreation', false, NULL, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + function deferredChildCreation() + { + // aggiunge i figli + $function = 'addChild_'.$this->getId(); + $function ( $this->_application, $this ); + $this->initChilds(); + $this->execDoLater(); + } + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->_state = explode(',', strtolower($this->getAttribute('name'))); + + if (in_array($this->_parent->getState(), $this->_state)) + { + if ( !count( $this->childComponents ) ) + { + $this->deferredChildCreation(); + } + + $this->processChilds(); + } + } + + /** + * Render + * + * @return void + * @access public + */ + function render($outputMode) + { + if (in_array($this->_parent->getState(), $this->_state) || $outputMode=='jsediting') + { + $this->renderChilds($outputMode); + } + } + + function getState() + { + return $this->_parent->getState(); + } + + function getStatesArray() + { + return $this->_state; + } + + function getDefaultState() + { + return $this->_state[0]; + } + + + public static function compile($compiler, &$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix, $componentClassInfo, $componentId) + { + $compiler->_classSource .= '$n'.$counter.' = &org_glizy_ObjectFactory::createComponent(\''.$componentClassInfo['classPath'].'\', $application, '.$parent.', \''.$node->nodeName.'\', '.$idPrefix.'\''.$componentId.'\', \''.$componentId.'\', $skipImport)'.GLZ_COMPILER_NEWLINE; + + $forceChildCreation = $node->hasAttribute( 'forceChildCreation' ) && strtolower( $node->getAttribute( 'forceChildCreation' ) ) == 'true' ? + 'true' : + $node->parentNode->hasAttribute( 'forceChildCreation' ) && strtolower($node->parentNode->getAttribute( 'forceChildCreation' ) ) == 'true' ? 'true' : 'false'; + $compiler->_classSource .= '$forceChildCreation = '.$forceChildCreation.GLZ_COMPILER_NEWLINE; + if ($parent!='NULL') + { + $compiler->_classSource .= $parent.'->addChild($n'.$counter.')'.GLZ_COMPILER_NEWLINE; + } + + if (count($node->attributes)) + { + // compila gli attributi + $compiler->_classSource .= '$attributes = array('; + foreach ( $node->attributes as $index=>$attr ) + { + if ($attr->name!='id') + { + $compiler->_classSource .= '\''.$attr->name.'\' => \''.addslashes($attr->value).'\', '; + } + } + $compiler->_classSource .= ')'.GLZ_COMPILER_NEWLINE; + $compiler->_classSource .= '$n'.$counter.'->setAttributes( $attributes )'.GLZ_COMPILER_NEWLINE; + } + + $compiler->_classSource .= 'if ($skipImport || $forceChildCreation) {addChild_'.$componentId.'($application, $n'.$counter.', $skipImport, $idPrefix, $mode);}'.GLZ_COMPILER_NEWLINE; + + $previusClassSource = $compiler->_classSource; + $compiler->_classSource = ''; + $compiler->_classSource .= '// STATE function '.GLZ_COMPILER_NEWLINE2; + $compiler->_classSource .= 'function addChild_'.$componentId.'( &$application, &$n'.$counter.', $skipImport=false, $idPrefix=\'\', $mode=\'\') {'.GLZ_COMPILER_NEWLINE2; + + $oldcounter = $counter; + foreach( $node->childNodes as $nc ) + { + $counter++; + $compiler->_compileXml($nc, $registredNameSpaces, $counter, '$n'.$oldcounter, $idPrefix); + } + $compiler->_classSource .= '} '.GLZ_COMPILER_NEWLINE; + $compiler->_classSource .= '// end STATE function '.GLZ_COMPILER_NEWLINE2; + + $compiler->_customClassSource .= $compiler->_classSource; + $compiler->_classSource = $previusClassSource; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/StateSwitch.php b/src/core/classes/org/glizy/components/StateSwitch.php new file mode 100755 index 0000000..7a2abf7 --- /dev/null +++ b/src/core/classes/org/glizy/components/StateSwitch.php @@ -0,0 +1,188 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +define('GLZ_STATE_SWITCH_SUFFIX', 'state'); + +class org_glizy_components_StateSwitch extends org_glizy_components_ComponentContainer +{ + var $_currentState = NULL; + var $_sessionEx = NULL; + var $_oldState = NULL; + var $_stateName = NULL; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('customClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('defaultState', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('rememberState', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('useIdPrefix', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('overrideEditableRegion', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('targetPage', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('forceChildCreation', false, NULL, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->overrideEditableRegion = $this->getAttribute('overrideEditableRegion'); + $this->_stateName = $this->getAttribute('useIdPrefix') ? $this->getId().'_'.GLZ_STATE_SWITCH_SUFFIX : GLZ_STATE_SWITCH_SUFFIX; + $this->_sessionEx = org_glizy_ObjectFactory::createObject('org.glizy.SessionEx', $this->getId()); + + $this->_oldState = $this->_sessionEx->get($this->_stateName); + + // se lo stato non è setttato lo cerca nella sessione + if ($this->getAttribute('rememberState')) + { + $this->_currentState = $this->_sessionEx->get($this->_stateName); + } + + if (is_null($this->_currentState)) + { + $this->resetState(); + } + + $newState = org_glizy_Request::get($this->_stateName, NULL); + if (!empty($newState)) + { + // cambio di stato + // TODO + // verificare che lo stato impostato sia definito + $this->_currentState = org_glizy_Request::get($this->_stateName, NULL); + } + + if ($this->_currentState=='reset') + { + $this->_currentState = NULL; + $this->resetState(); + } + $this->_currentState = strtolower($this->_currentState); + $this->_sessionEx->set($this->_stateName, $this->_currentState); + + $customClassName = $this->getAttribute('customClass'); + if (!empty($customClassName)) + { + $customClass = &org_glizy_ObjectFactory::createObject($customClassName, $this); + // TODO + // createObject purtroppo non passa i parametri in riferimento e questa è una grande limitazione + $customClass->_parent = &$this; + if (method_exists($customClass, $this->_currentState)) call_user_func(array($customClass, $this->_currentState), $this->_oldState); + else if (method_exists($customClass, 'execute_'.$this->_currentState)) call_user_func(array($customClass, 'execute_'.$this->_currentState), $this->_oldState); + } + else + { + if (method_exists($this, $this->_currentState)) call_user_func(array($this, $this->_currentState), $this->_oldState); + } + + $this->processChilds(); + + if (!empty($customClassName)) + { + $customClass = &org_glizy_ObjectFactory::createObject($customClassName, $this); + $customClass->_parent = &$this; + if (method_exists($customClass, 'executeLater_'.$this->_currentState)) call_user_func(array($customClass, 'executeLater_'.$this->_currentState), $this->_oldState); + } + } + +/* */ + + function getState() + { + return strtolower($this->_currentState); + } + + function setState($value) + { + $this->_currentState = $value; + $this->_sessionEx->set($this->_stateName, $this->_currentState); + } + + function resetState() + { + // se lo stato non è settato dagli attributi + if (is_null($this->_currentState)) $this->_currentState = $this->getAttribute('defaultState'); + + // se lo stato non è settato lo legge dal primo figlio + if (is_null($this->_currentState)) $this->_currentState = $this->childComponents[0]->getDefaultState(); + + //TODO + // se lo stato è nullo + // visualizzare un errore + } + + // TODO + // modificare il tipo di implementazione + // non mi piace che un componente chieda l'url ad un'altro componente + function changeStateUrl($newState='', $amp=false ) + { + if ( is_null( $this->getAttribute('targetPage') ) ) + { + return org_glizy_helpers_Link::addParams(array($this->_stateName => $newState)); + } + else + { + return org_glizy_helpers_Link::makeUrl('link', array('pageId' => $this->getAttribute('targetPage')), array($this->_stateName => $newState)); + } + } + + function refreshToState($newState='', $params=null) + { + $url = str_replace( '&amp;', '&', $this->changeStateUrl( $newState ) ); + org_glizy_helpers_Navigation::gotoUrl( $url, $params); + } + + + function getStateParamName() + { + return $this->_stateName; + } + + // TODO + // modificare il tipo di implementazione + // non mi piace che un componente chieda l'url ad un'altro componente + // + // TODO + // la generazione dei link deve sempre passare dal org_glizy_helpers_Link + function getJSAction($action, $forceUrl=true) + { + $pageId = $this->_application->getPageId(); + $targetPage = $this->getAttribute('targetPage'); + if (!is_null($targetPage)) + { + $pageId = $this->getAttribute('targetPage'); + } + + if ( $forceUrl ) + { + $url = '\''.org_glizy_helpers_Link::makeUrl('link', array('pageId' => $pageId), array($this->_stateName => $action)).'\''; + } + else + { + $url = '\''.org_glizy_helpers_Link::addParams( array($this->_stateName => $action) ).'\''; + } + + + return $url; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/StateSwitchClass.php b/src/core/classes/org/glizy/components/StateSwitchClass.php new file mode 100755 index 0000000..cb01dde --- /dev/null +++ b/src/core/classes/org/glizy/components/StateSwitchClass.php @@ -0,0 +1,18 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_components_StateSwitchClass extends GlizyObject +{ + var $_parent = NULL; + + function __construct(&$parent) + { + $this->_parent = &$parent; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Tab.php b/src/core/classes/org/glizy/components/Tab.php new file mode 100755 index 0000000..a1b1392 --- /dev/null +++ b/src/core/classes/org/glizy/components/Tab.php @@ -0,0 +1,30 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Tab extends org_glizy_components_State +{ + var $_state; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('label', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('url', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('draw', false , true, COMPONENT_TYPE_BOOLEAN); + // call the superclass for validate the attributes + parent::init(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/TabGroup.php b/src/core/classes/org/glizy/components/TabGroup.php new file mode 100755 index 0000000..abbb65c --- /dev/null +++ b/src/core/classes/org/glizy/components/TabGroup.php @@ -0,0 +1,80 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_TabGroup extends org_glizy_components_StateSwitch +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('addWrapDiv', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('forceLink', false, true, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + + $this->setAttribute('useIdPrefix', true); + } + + function render_html() + { + if ($this->getAttribute('addWrapDiv')) + { + $output = '<div id="'.$this->getId().'" class="clearfix"><ul '.(!is_null($this->getAttribute('cssClass')) ? ' class="'.$this->getAttribute('cssClass').'"' : '').'>'; + } + else + { + $output .= '<ul id="'.$this->getId().'"'.(!is_null($this->getAttribute('cssClass')) ? ' class="'.$this->getAttribute('cssClass').'"' : '').'>'; + } + for ($i=0; $i<count($this->childComponents); $i++) + { + $label = $this->childComponents[$i]->getAttribute('label'); + $states = $this->childComponents[$i]->getStatesArray(); + $draw = $this->childComponents[$i]->getAttribute('draw'); + $cssClass = in_array($this->getState(), $states) ? ' class="active"' : ''; + $id = $this->childComponents[$i]->getId(); + if ( $draw ) + { + if (!empty($cssClass) && !$this->getAttribute('forceLink')) + { + $output .= '<li'.$cssClass.'>'.$label.'</li>'; + } + else + { + $url = $this->childComponents[$i]->getAttribute('url'); + if (is_null($url)) + { + $url = $this->childComponents[$i]->getAttribute('routeUrl'); + if (!is_null($url)) + { + $url = __Link::makeUrl( $url ); + } + } + if (is_null($url)) + { + $url = $this->changeStateUrl($states[0], true ); + } + $output .= '<li'.$cssClass.'><a id="' . $id . '" href="'.$url.'">'.$label.'</a></li>'; + } + } + } + $output .= '</ul>'; + if ($this->getAttribute('addWrapDiv')) + { + $output .= '</div>'; + } + $this->addOutputCode($output); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Text.php b/src/core/classes/org/glizy/components/Text.php new file mode 100755 index 0000000..7515c4b --- /dev/null +++ b/src/core/classes/org/glizy/components/Text.php @@ -0,0 +1,109 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Text extends org_glizy_components_HtmlComponent +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('cssClass', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('text', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('textIfEmpty', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('html', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('wrapTag', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('adm:disabled', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:readOnly', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:maxLength', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('adm:size', false, 50, COMPONENT_TYPE_INTEGER); + $this->defineAttribute('adm:required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('model:required', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:requiredMessage', false, NULL, COMPONENT_TYPE_STRING); + + + // call the superclass for validate the attributes + parent::init(); + } + + + function process() + { + $tagContent = $this->getText(); + if (empty($tagContent)) + { + // richiede il contenuto al padre + $tagContent = $this->_parent->loadContent($this->getId()); + $this->setText($tagContent); + } + + $textIfEmpty = $this->getAttribute( 'textIfEmpty' ); + if (empty($tagContent) && !empty( $textIfEmpty ) ) + { + $this->setText($textIfEmpty); + } + + $this->processChilds(); + } + + + function render_html() + { + $content = $this->getAttribute( 'html' ) ? $this->getText() : glz_encodeOutput($this->getText()); + if (!empty($content)) + { + $attributes = array(); + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['class'] = $this->getAttribute('cssClass'); + + $wrapTag = $this->getAttribute('wrapTag'); + $output = ''; + $output .= !empty($wrapTag) ? '<'.$wrapTag.' '.$this->_renderAttributes($attributes).'>' : ''; + $output .= $content; + $output .= !empty($wrapTag) ? '</'.$wrapTag.'>' : ''; + $this->addOutputCode($output); + } + } + + + function getContent() + { + $content = $this->getAttribute( 'html' ) ? $this->getText() : glz_encodeOutput($this->getText()); + return $content; + } + + public static function translateForMode_edit($node) { + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['data'] = ''; + + if (count($node->attributes)) + { + foreach ( $node->attributes as $index=>$attr ) + { + if ($attr->prefix=="adm") + { + $attributes[$attr->name] = $attr->value; + } + } + } + if (!isset($attributes['cssClass'])) { + $attributes['cssClass'] = '{config:glizy.formElement.admCssClass}'; + } + return org_glizy_helpers_Html::renderTag('glz:Input', $attributes); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/Url.php b/src/core/classes/org/glizy/components/Url.php new file mode 100755 index 0000000..8694a64 --- /dev/null +++ b/src/core/classes/org/glizy/components/Url.php @@ -0,0 +1,46 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_Url extends org_glizy_components_Text +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('makeLink', false, false, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + function render_html() + { + $output = $this->getContent(); + $this->addOutputCode($output); + } + + function getContent() + { + $tagContent = trim($this->getText()); + if ($this->getAttribute('makeLink') && !empty($tagContent)) + { + return org_glizy_helpers_Link::makeSimpleLink($tagContent, $tagContent); + } + else + { + return $tagContent; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/UserBox.php b/src/core/classes/org/glizy/components/UserBox.php new file mode 100755 index 0000000..bce8241 --- /dev/null +++ b/src/core/classes/org/glizy/components/UserBox.php @@ -0,0 +1,57 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_UserBox extends org_glizy_components_ComponentContainer +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('showWelcome', false, true, COMPONENT_TYPE_BOOLEAN); + $this->acceptOutput = true; + parent::init(); + } + + function process() + { + $user = &$this->_application->getCurrentUser(); + $this->_content = array(); + $this->_content['id'] = $this->getId(); + $this->_content['cssClass'] = $this->getAttribute('cssClass'); + $this->_content['message'] = ''; + if ( $this->getAttribute('showWelcome') ) + { + $this->_content['message'] = org_glizy_locale_Locale::get('LOGGED_MESSAGE', $user->firstName); + } + $this->processChilds(); + } +} + +if (!class_exists('org_glizy_components_UserBox_render')) +{ + class org_glizy_components_UserBox_render extends org_glizy_components_render_Render + { + function getDefaultSkin() + { + $skin = <<<EOD +<div class="" tal:attributes="class UserBox/cssClass; id UserBox/id"> +<h3 tal:condition="UserBox/message" tal:content="structure UserBox/message" /> +<span tal:omit-tag="" tal:content="structure childOutput" /> +</div> +EOD; + return $skin; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/VBox.php b/src/core/classes/org/glizy/components/VBox.php new file mode 100755 index 0000000..4870cc0 --- /dev/null +++ b/src/core/classes/org/glizy/components/VBox.php @@ -0,0 +1,43 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_VBox extends org_glizy_components_ComponentContainer +{ + + function init() + { + $this->defineAttribute('cssClass', false, null, COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, null, COMPONENT_TYPE_STRING); + $this->defineAttribute('titleTag', false, 'h3', COMPONENT_TYPE_STRING); + + parent::init(); + } + + + function render_html_onStart() + { + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['class'] = $this->getAttribute('cssClass'); + $output = '<div '.$this->_renderAttributes($attributes).'>'; + $title = $this->getAttributeString('title'); + if (!empty($title)) + { + $output .= '<'.$this->getAttribute('titleTag').'>'.$title.'</'.$this->getAttribute('titleTag').'>'; + } + $this->addOutputCode($output); + } + + function render_html_onEnd() + { + $output = '</div>'; + $this->addOutputCode($output); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/interfaces/IDataProvider.php b/src/core/classes/org/glizy/components/interfaces/IDataProvider.php new file mode 100644 index 0000000..c9d1473 --- /dev/null +++ b/src/core/classes/org/glizy/components/interfaces/IDataProvider.php @@ -0,0 +1,7 @@ +<?php + +interface org_glizy_components_interfaces_IDataProvider +{ + public function &loadQuery($queryName='', $options=array()); + public function &load($id); +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/interfaces/ISearchFilters.php b/src/core/classes/org/glizy/components/interfaces/ISearchFilters.php new file mode 100644 index 0000000..77950c3 --- /dev/null +++ b/src/core/classes/org/glizy/components/interfaces/ISearchFilters.php @@ -0,0 +1,6 @@ +<?php + +interface org_glizy_components_interfaces_ISearchFilters +{ + public function getFilters($filters); +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/render/Render.php b/src/core/classes/org/glizy/components/render/Render.php new file mode 100755 index 0000000..f4d1b0e --- /dev/null +++ b/src/core/classes/org/glizy/components/render/Render.php @@ -0,0 +1,129 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_render_Render extends GlizyObject +{ + var $_parent; + var $_application; + var $_rootComponent; + var $_outputMode; + var $_skipChilds; + + function __construct(&$parent, $outputMode, $skipChilds=false) + { + $this->_parent = &$parent; + $this->_application = &$parent->_application; + $this->_rootComponent = &$this->_application->getRootComponent(); + $this->_outputMode = $outputMode; + $this->_skipChilds = $skipChilds; + + } + + function render() + { + if (method_exists($this, 'render_'.$this->_outputMode)) + { + $this->{'render_'.$this->_outputMode}(); + } + else + { + $content = $this->_parent->getContent(); + if (is_array( $content ) && isset($content['id'])) + { + $content['id'] = str_replace('@', '___', $content['id']); + } + $skinClass = &$this->getSkinClass(); + + $skinClass->set($this->_parent->getTagName(), $content); + $skinClass->set('Component', $content); + $skinClass->set('id', $this->_parent->getId()); + $skinClass->set('ajaxMode', $this->_application->_ajaxMode); + + if (!$this->_skipChilds && isset($this->_parent->acceptOutput)) + { + if ($this->_parent->acceptOutput && $this->_parent->overrideEditableRegion) + { + $this->_parent->renderChilds($this->_outputMode); + $childOutput = ''; + for ($i=0; $i<count($this->_parent->_output); $i++) + { + $childOutput .= $this->_parent->_output[$i]['code']; + } + $skinClass->set('childOutput', $childOutput); + $output = $skinClass->execute(); + $this->_parent->addParentOutputCode($output); + return; + } + } + + $output = $skinClass->execute(); + $this->_parent->addOutputCode($output); + } + } + + // gestione skins + + function &getSkin() + { + return $this->_parent->getAttribute('skin'); + } + + function getDefaultSkin() + { + return ''; + } + + function &getSkinClass() + { + $skin = &$this->getSkin(); + $skinFileName = NULL; + $skinDefaultHtml = NULL; + $skinType = __Config::get( 'DEFAULT_SKIN_TYPE' ); + + if (empty($skin)) + { + $skinFileName = str_replace(":", "", $this->_parent->_tagname); + $skinType = "PHPTAL"; + $skinDefaultHtml = $this->getDefaultSkin(); + } + else if (is_object($skin)) + { + $skinType = $skin->getAttribute('skinType'); + if ( empty( $skinType ) ) $skinType = __Config::get( 'DEFAULT_SKIN_TYPE' ); + $skinFileName = $this->_parent->_application->getPageId().'_'.$skin->getId(); + $skinDefaultHtml = $skin->getTemplateString(); + } + else + { + $skin = explode(':', $skin); + if (count($skin)>1) + { + $skinType = strtoupper($skin[0]); + $skinFileName = $skin[1]; + } + else + { + if ( strpos( $skin[0], '/' ) === false ) + { + $skinFileName = $skin[0]; + } + else + { + $skin = explode('/', $skin[0]); + $skin[0] = str_replace( '.', '/', $skin[0] ); + $skinFileName = org_glizy_Paths::get( 'APPLICATION_CLASSES' ).( implode( '/', $skin ) ); + } + } + } + + $skinClass = org_glizy_ObjectFactory::createObject('org.glizy.template.skin.'.strtoupper($skinType), $skinFileName, $skinDefaultHtml); + return $skinClass; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/render/RenderCell.php b/src/core/classes/org/glizy/components/render/RenderCell.php new file mode 100755 index 0000000..fabe923 --- /dev/null +++ b/src/core/classes/org/glizy/components/render/RenderCell.php @@ -0,0 +1,37 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_render_RenderCell extends GlizyObject +{ + protected $application; + protected $user = NULL; + + function __construct($application) + { + $this->application = $application; + $this->user = $this->application->getCurrentUser(); + } + + function renderCell( $key, $value, $item, $columnName ) + { + return ''; + } + + function getHeader( $text ) + { + return $text; + } + + function getCssClass( $key, $value, $item ) + { + return ''; + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/components/render/RenderCellRecordSetList.php b/src/core/classes/org/glizy/components/render/RenderCellRecordSetList.php new file mode 100755 index 0000000..164d266 --- /dev/null +++ b/src/core/classes/org/glizy/components/render/RenderCellRecordSetList.php @@ -0,0 +1,23 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_render_RenderCellRecordSetList extends GlizyObject +{ + protected $application; + + function __construct(&$application) + { + $this->application = $application; + } + + function renderCell( &$ar, $params ) + { + } +} diff --git a/src/core/classes/org/glizy/components/render/RenderCellRow.php b/src/core/classes/org/glizy/components/render/RenderCellRow.php new file mode 100755 index 0000000..41c2dbb --- /dev/null +++ b/src/core/classes/org/glizy/components/render/RenderCellRow.php @@ -0,0 +1,27 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_components_render_RenderCellRow extends GlizyObject +{ + var $application; + + function __construct(&$application) + { + $this->application = $application; + } + + function renderRow( $item, $cssClass ) + { + return ''; + } + + + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/ActiveRecord.php b/src/core/classes/org/glizy/dataAccess/ActiveRecord.php new file mode 100755 index 0000000..720d17e --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/ActiveRecord.php @@ -0,0 +1,1588 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + + +class org_glizy_dataAccess_ActiveRecord extends GlizyObject +{ + var $_conn = NULL; + var $_connNumber = 0; + var $_tableName = ''; + var $_tablePrimaryKey = NULL; + var $_fieldsList = array(); + var $_sql = array(); + var $_querySql = array(); + var $_error = false; + var $_relations = array(); + var $_processRelations = false; + var $_relationBuilded = false; + var $_tablePrefix = ''; + var $_defaultQuery = 'SELECT'; + var $_siteIdField = NULL; + var $_aclField = NULL; + var $_aclCategories = NULL; + var $lastSql = ''; + var $enableLog = false; + var $queue = NULL; + + function __construct() + { + $this->_conn = &org_glizy_dataAccess_DataAccess::getConnection($this->_connNumber); + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $this->enableLog = !is_null( $application->_logObj ); + //$this->_conn->debug = true; + } + + function setDebugMode($value) + { + $this->_conn->debug = $value; + } + + function getTableName() + { + return $this->_tableName; + } + + function getTableNameWithoutPrefix() + { + return substr( $this->getTableName(), strlen( $this->_tablePrefix ) ); + } + + + function setTableName($theName) + { + $this->_tableName = $this->_tablePrefix.$theName; + } + + function setTablePrefix($prefix="") + { + $this->_tablePrefix = $prefix; + } + + function getProcessRelations() + { + return $this->_processRelations; + } + + function setProcessRelations($value) + { + $this->_processRelations = $value; + } + + function getDefaultQuery() + { + return $this->_defaultQuery; + } + + function setDefaultQuery( $value ) + { + $this->_defaultQuery = $value; + } + + function addField($field, $skipPrimaryCheck=false) + { + $field['type'] = strtolower( $field['type'] ); + + if ( is_null( __Config::get( 'SITE_ID' ) ) && $field[ 'type' ] == AR_TYPE_SITEID ) + { + return; + } + + if ($skipPrimaryCheck===false) + { + if (array_key_exists('primaryKey', $field) && $field['primaryKey']===true) + { + if (is_null($this->_tablePrimaryKey)) + { + $this->_tablePrimaryKey = $field['name']; + $field['defaultValue'] = NULL; + $field['defaultInsertValue'] = NULL; + } + else + { + // TODO: + // visualizzare un errore perch� pu� esserci solo una chiave primaria + } + } + } + + // inserire le chiavi mancanti dentro $field + $fieldName = $field['name']; + $field['canEncode'] = true; + if ( !empty( $field['filter'] ) ) + { + $field['filter'] = org_glizy_ObjectFactory::createObject( $field['filter'] ); + } + + if (!array_key_exists('type', $field)) $field['type'] = 'string'; + + if ($field['type']== AR_TYPE_VERSIONDATE ) + { + $field['type'] = AR_TYPE_DATE; + $field['versionDate'] = true; + $field['defaultInsertValue'] = 'NOW()'; + $field['defaultUpdateValue'] = 'NOW()'; + } + else if ($field['type']== AR_TYPE_VERSIONSTATUS) + { + $field['type'] = AR_TYPE_ENUM; + $field['values'] = array('PUBLISHED', 'DRAFT', 'OLD'); + $field['versionField'] = true; + $field['defaultSelectValue'] = 'PUBLISHED'; + $field['defaultValue'] = NULL; + } + else if ($field['type']== AR_TYPE_LANGUAGE ) + { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $field['type'] = AR_TYPE_INTEGER; + $field['languageField'] = true; + $field['defaultSelectValue'] = $application->getLanguageId(); + } + else if ($field['type']==AR_TYPE_USER) + { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $user = &$application->getCurrentUser(); + $field['type'] = AR_TYPE_INTEGER; + $field['userField'] = true; + $field['defaultInsertValue'] = $user->id; + } + else if ($field['type'] == AR_TYPE_INT) + { + $field['type'] = AR_TYPE_INTEGER; + } + else if ($field['type'] == AR_TYPE_RICHTEXT || $field['type'] == AR_TYPE_TEXT ) + { + $field['type'] = AR_TYPE_STRING; + $field['canEncode'] = false; + } + else if ($field['type'] == AR_TYPE_SITEID) + { + $siteId = org_glizy_Config::get( 'SITE_ID' ); + if ( is_null( $siteId ) ) + { + return; + } + $this->_siteIdField = $fieldName; + $field['defaultSelectValue'] = $siteId ; + $field['defaultValue'] = $siteId ; + } + else if ($field['type']== AR_TYPE_ACL) + { + $field['type'] = AR_TYPE_VIRTUAL; + $this->_aclField = $fieldName; + // definisce la relazione + $this->addRelation(array('type' => 'joinTable', 'name' => 'rel_acl', 'className' => 'org.glizy.models.Join', 'field' => 'join_FK_source_id', 'destinationField' => 'join_FK_dest_id', 'bindTo' => $fieldName , 'objectName' => $this->getTableNameWithoutPrefix().'#acl')); + } + else if ($field['type']=='category') + { + if ( !__Config::get( 'CATEGORY_ENABLED' ) ) + { + return; + } + $field['type'] = AR_TYPE_VIRTUAL; + $this->_aclCategories = $fieldName; + // definisce la relazione + $this->addRelation(array('type' => 'joinTable', 'name' => 'rel_section', 'className' => 'org.glizy.models.Join', 'field' => 'join_FK_source_id', 'destinationField' => 'join_FK_dest_id', 'bindTo' => $fieldName , 'objectName' => $this->getTableNameWithoutPrefix().'#acl_category')); + } + + $this->_fieldsList[$fieldName] = $field; + $this->$fieldName = array_key_exists('defaultValue', $field) ? $field['defaultValue'] : NULL; + + if (array_key_exists('relation', $field)) + { + $relation = $field['relation']; + $relation['field'] = $fieldName; + $this->addRelation($relation); + } + + } + + function emptyRecord() + { + foreach ($this->_fieldsList as $k=>$v) + { + $this->$k = array_key_exists('defaultValue', $v) ? $v['defaultValue'] : NULL;; + } + foreach ($this->_relations as $k=>$v) + { + $this->$k = NULL; + } + } + + + function modifyField($fieldName, $attribute, $value) + { + if ( array_key_exists($fieldName,$this->_fieldsList) ) + { + if ($attribute=='relation') + { + // TODO + } + + $this->_fieldsList[$fieldName][$attribute] = $value; + $this->addField($this->_fieldsList[$fieldName]); + $this->_makeSql('SELECT'); + } + } + + function getFieldType($fieldName) + { + if (array_key_exists($fieldName,$this->_fieldsList)) + { + return $this->_fieldsList[$fieldName]['type']; + } + else + { + return NULL; + } + } + + function removeField() + { + // TODO + } + + function addRelation($options) + { + assert(isset($options['name'])); + + if ( empty( $options['objectName'] ) ) + { + $options['objectName'] = $this->getTableNameWithoutPrefix().'#'.$options['name']; + } + $this->_relations[$options['name']] = $options; + $this->{$options['name']} = NULL; + } + + function modifyRelation() + { + // TODO + } + + function removeRelation() + { + // TODO + } + + function invalidateRelations() + { + $this->_relationBuilded = false; + foreach ($this->_relations as $k=>$v) + { + $this->$k = NULL; + } + } + + function buildAllRelations( $build = true ) + { + if ($this->_processRelations && !$this->_relationBuilded) + { + $this->_relationBuilded = true; + // risolve le relazioni + foreach ($this->_relations as $k=>$v) + { + $relation = org_glizy_dataAccess_Relation::createObject($this, $v); + if ( $build ) $relation->build(); + $this->$k = $relation; + } + + } + } + + function _saveAllRelations($preSave=true) + { + // TODO + // quando si fa l'update anche delle relazioni + // c'� da controllare che non si verifichino errori + // in questo caso c'� da segnalarlo + foreach ($this->_relations as $k=>$v) + { + if (is_object($this->$k)) + { + if ($preSave==true) + { + $this->$k->preSave(); + } + else + { + $this->$k->postSave(); + } + } + } + } + + function _deleteAllRelations() + { + foreach ($this->_relations as $k=>$v) + { + if (is_object($this->$k)) + { + $this->$k->delete(); + } + } + + $this->_relationBuilded = false; + } + + function buildRelation($name, $params=array()) + { + //$relation = &new ActiveRecord_has_one($this, $this->_relations[$name]['key'], $this->_relations[$name]['className']); + $relation = &org_glizy_dataAccess_relation::createObject($this, $this->_relations[$name]); + $relation->build($params); + $this->$name = &$relation; + } + + function createRelation($name, $params=array()) + { + // force to true the process relation flag + $this->setProcessRelations(true); + $relation = &org_glizy_dataAccess_relation::createObject($this, $this->_relations[$name]); + $relation->create($params); + $this->$name = &$relation; + } + + function bindRelationObject($name, &$object) + { + // force to true the process relation flag + $this->setProcessRelations(true); + $relation = &org_glizy_dataAccess_relation::createObject($this, $this->_relations[$name]); + $relation->bind($object); + $this->$name = $relation; + } + + function getId() + { + if (is_null($this->_tablePrimaryKey)) + { + // TODO: + // visualizzare un errore perch� pu� esserci solo una chiave primaria + + return NULL; + } + $primarykey = $this->_tablePrimaryKey; + return $this->$primarykey; + } + + function setId($value) + { + $primarykey = $this->_tablePrimaryKey; + $this->$primarykey = $value; + } + + + function getPrimarykey() + { + return $this->_tablePrimaryKey; + } + + function isNew() + { + return empty( $this->{$this->_tablePrimaryKey} ); + } + + function load( $id=NULL, $queryName=NULL, $params=array() ) + { + org_glizy_dataAccess_DataAccess::selectDB( $this->_connNumber ); + + $this->error = false; + if (is_null($id)) + { + $id = $this->getId(); + } + + if ( !is_null( $queryName ) ) + { + $sql = $this->_getQuerySqlString( $queryName ); + //if ( stristr($sql, $this->getPrimarykey() ) === FALSE && !is_null( $id ) ) + if ( stristr($sql, '?' ) === FALSE && !is_null( $id ) ) + { + $sql .= stristr($sql, 'WHERE' ) === FALSE ? ' WHERE ' : ' AND '; + $sql .= $this->getPrimarykey().' = ?'; + } + + if ( !is_null( $id ) ) + { + $params = array_merge( $params , array( $id ) ) ; + } + + $rs = &$this->_execute( $sql, $params ); + + } + else if ( $this->_defaultQuery == "SELECT" || $this->_defaultQuery == "All") + { + $rs = &$this->_execute($this->_getSqlString( "SELECT" ), array($id)); + } + else + { + $sql = $this->_getQuerySqlString( $this->_defaultQuery ); + if ( stristr($sql, $this->getPrimarykey() ) === FALSE && !is_null( $id ) ) + { + $sql .= stristr($sql, 'WHERE' ) === FALSE ? ' WHERE ' : ' AND '; + $sql .= $this->getPrimarykey().' = ?'; + } + + if ( !is_null( $id ) ) + { + $params = array_merge( $params , array( $id ) ) ; + } + + $rs = &$this->_execute( $sql, $params ); + } + + $rsFields = $rs->fields; + if ($rsFields) + { + $this->loadFromArray($rsFields); + $this->buildAllRelations(); + return true; + } + else + { + // TODO + // visualizzare errore + // $e = ADODB_Pear_Error(); + // echo '<p>',$e->message,'</p>'; + $this->error = true; + return NULL; + } + } + + + function loadFromArray($values) + { + $this->_relationBuilded = false; + + // mappa i risulatato all'oggetto + if ( is_array( $values ) ) + { + foreach ($values as $k=>$v) + { + if ( !empty( $k ) ) + { + $this->$k = $v; + if ( !isset( $this->_fieldsList[ $k ] ) ) + { + $this->addField( array ( 'name' => $k, 'type' => AR_TYPE_VIRTUAL ) ); + } + } + } + } + + foreach ($this->_fieldsList as $k=>$v) + { + if (is_array($values) && array_key_exists($k, $values)) + { + + $value = $values[$k]; + if (is_null($value) && isset($this->_fieldsList[$k]['notNull']) && $this->_fieldsList[$k]['notNull']) + { + $value = $this->_fieldsList[$k]['defaultValue']; + } + if ($this->_fieldsList[$k]['type']==AR_TYPE_DATE || $this->_fieldsList[$k]['type']==AR_TYPE_DATETIME) + { + $value = $this->_validateDate( $value, $this->_fieldsList[$k]['type'] ); + } + else if ($this->_fieldsList[$k]['type']==AR_TYPE_INTEGER) + { + $value = intval($value); + if ( isset($this->_fieldsList[$k]['zeroIsNull']) && $this->_fieldsList[$k]['zeroIsNull'] === true && $value == 0 ) $value = ""; + } + $this->$k = $value; + } + else + { + if ($v['type']=='virtual' && isset($v['bindTo'])) + { + if (isset($values[$v['bindTo']])) + { + $this->$k = $values[$v['bindTo']]; + } + } + } + } + foreach ($this->_relations as $k=>$v) + { + if (array_key_exists($k, $values)) + { + $this->$k = $values[$k]; + } + } + } + + function find($values=array()) + { + org_glizy_dataAccess_DataAccess::selectDB( $this->_connNumber ); + $this->loadFromArray($values); + $this->error = false; + + $tempFields = array(); + $tempWhereValue = array(); + $tempWhereCond = array(); + + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL) continue; + $tempFields[] = $k; + if (!is_null($this->$k) && ($v['defaultValue']!=$this->$k || array_key_exists( $k, $values ) ) ) + { + $tempWhereValue[] = $this->$k; + $tempWhereCond[] = $k.'=?'; + } + if ($v['type']==AR_TYPE_SITEID) + { + $tempWhereValue[] = $this->$k; + $tempWhereCond[] = $k.'=?'; + } + } + + $sql = ''; + $sql .= 'SELECT '; + $sql .= implode(',', $tempFields); + $sql .= ' FROM '.$this->getTableName(); + $sql .= ' WHERE '.implode(' AND ', $tempWhereCond).' LIMIT 1'; + + $rs = &$this->_execute($sql, $tempWhereValue); + $rsFields = $rs->fields; + if ($rsFields) + { + $this->loadFromArray($rsFields); + $this->buildAllRelations(); + return true; + } + else + { + $this->error = true; + return false; + } + } + + function loadRecord($queryName, $params=array()) + { + org_glizy_dataAccess_DataAccess::selectDB( $this->_connNumber ); + $sql = $this->_getQuerySqlString($queryName); + $rs = &$this->_execute($sql, $params); + $rsFields = $rs->fields; + if ($rsFields) + { + $this->loadFromArray($rsFields); + $this->buildAllRelations(); + return true; + } + else + { + // TODO + // visualizzare errore + // $e = ADODB_Pear_Error(); + // echo '<p>',$e->message,'</p>'; + $this->error = true; + return NULL; + } + } + + + function save($values=NULL, $forceNew=false) + { + org_glizy_dataAccess_DataAccess::selectDB( $this->_connNumber ); + if (!is_null($values)) $this->loadFromArray($values); + + if ($this->_processRelations) + { + $this->buildAllRelations(); + $this->_saveAllRelations(true); + } + + $result = false; + if ( $this->isNew() || $forceNew ) + { + $evt = array('type' => GLZ_EVT_AR_INSERT_PRE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + $result = $this->_insert($values); + $evt = array('type' => GLZ_EVT_AR_INSERT.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + } + else + { + $evt = array('type' => GLZ_EVT_AR_UPDATE_PRE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + $result = $this->_update($values); + $evt = array('type' => GLZ_EVT_AR_UPDATE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + } + if ($this->_processRelations) $this->_saveAllRelations(false); + + return $result; + } + + function delete($id=NULL) + { + org_glizy_dataAccess_DataAccess::selectDB( $this->_connNumber ); + + if (is_null($id)) + { + $id = $this->getId(); + } + + if ( is_array( $id ) ) + { + $tempWhereValue = array(); + $tempWhereCond = array(); + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL) continue; + if ( array_key_exists( $k, $id ) ) + { + $tempWhereValue[] = $id[ $k ]; + $tempWhereCond[] = $k.'=?'; + } + } + + $sql = 'DELETE FROM '.$this->getTableName(); + $sql .= ' WHERE '.implode(' AND ', $tempWhereCond); + $rs = $this->_execute( $sql, $tempWhereValue ); + } + else + { + $this->setId( $id ); + $rs = $this->_execute($this->_getSqlString('DELETE'), array($id)); + } + + $evt = array('type' => GLZ_EVT_AR_DELETE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + if ($this->_processRelations) + { + $this->buildAllRelations( false ); + $this->_deleteAllRelations(); + } + $this->emptyRecord(); + + if ($rs) return true; + else { + // TODO + // visualizzare errore + // $e = ADODB_Pear_Error(); + // echo '<p>',$e->message,'</p>'; + return false; + } + + } + + function getValuesAsArray($getRelationValues=false, $getVirtualField=true, $encode=false) + { + $result = $this->_collectFieldsValues($getRelationValues, $getVirtualField, $encode); + return $result; + } + + + function _getSqlString($type='SELECT') + { + if (!array_key_exists($type, $this->_sql)) + { + $this->_makeSql($type); + } + return $this->_sql[$type]; + } + + + function _makeSql($type) + { +/* if (is_null($this->_tablePrimaryKey)) + { + // TODO: + // visualizzare un errore + return NULL; + } +*/ + $tempFields = array(); + $tempInsertField = array(); + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL) continue; + $tempFields[] = $k; + $tempInsertField[] = '?'; + } + + $sql = ''; + switch ($type) + { + case 'SELECT': + $sql .= 'SELECT '; + $sql .= implode(',', $tempFields); + $sql .= ' FROM '.$this->getTableName(); + $sql .= ' WHERE '.$this->_tablePrimaryKey.' = ?'; + $sql .= $this->_addAclClause(); + break; + case 'INSERT': + $sql .= 'INSERT INTO '.$this->getTableName().' '; + $sql .= '('.implode(',', $tempFields).')'; + $sql .= ' VALUES ( '.implode(',', $tempInsertField).');'; + break; + case 'INSERT_QUEUE': + $sql .= 'INSERT INTO '.$this->getTableName().' '; + $sql .= '('.implode(',', $tempFields).')'; + $sql .= ' VALUES '; + break; + case 'UPDATE': + $sql .= 'UPDATE '.$this->getTableName().' SET '; + $sql .= implode('= ?,', $tempFields).'= ? '; + $sql .= ' WHERE '.$this->_tablePrimaryKey.' = ?'; + break; + case 'DELETE': + $sql .= 'DELETE '; + $sql .= ' FROM '.$this->getTableName(); + $sql .= ' WHERE '.$this->_tablePrimaryKey.' = ?'; + break; + default: + // TODO + // visualizzare errore + break; + } + $this->_sql[$type] = $sql; + } + + + function _insert($values=NULL) + { + $insertSql = $this->_getSqlString('INSERT'); + $values = $this->_collectFieldsValues(false, false); + $queryParams = array(); + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL) continue; + if (array_key_exists('defaultInsertValue', $v) ) + { + $values[$k] = is_null( $values[$k] ) ? $v['defaultInsertValue'] : $values[$k]; + if ( ( $v['type']==AR_TYPE_DATE || $v['type']==AR_TYPE_DATETIME ) && ( empty ( $values[$k] ) || $values[$k] === "0000-00-00 00:00:00" || $values[$k] === "0000-00-00" ) ) $values[$k] = $v['defaultInsertValue']; + if ($values[$k]=='NOW()' && ( $v['type']==AR_TYPE_DATE || $v['type']==AR_TYPE_DATETIME ) ) + { + $explodedSql = explode('?', $insertSql); + $numParams = count($queryParams); + $numParts = count($explodedSql); + $explodedSql[$numParams] .= $this->_createInsertDateNative( $v['type'] ).($numParams==$numParts ? '' : ','); + array_splice($explodedSql, $numParams+1, 1); + if ($explodedSql[$numParts-2]!=');') { + $explodedSql[$numParts-2] = rtrim($explodedSql[$numParts-2], ',').');'; + } + $insertSql = implode('?', $explodedSql); + continue; + } + } + if ( $v['type']==AR_TYPE_DATE || $v['type']==AR_TYPE_DATETIME ) + { + if ( empty($values[$k]) ) + { + $values[$k] = $this->_createEmptyDate( $v['type'] ); + } + else + { + $values[$k] = glz_localeDate2default($values[$k] ); + } + } + if (is_null($values[$k]) && array_key_exists('null', $v) && $v['null']==false) + { + $values[$k] = ''; + } + + if ( $v['type'] == AR_TYPE_INTEGER ) { + if (!is_null($values[$k] ) && $values[$k] == '' ) $values[$k] = 0; + else if ($values[$k]===true) $values[$k] = 1; + else if ($values[$k]===false) $values[$k] = 0; + } + + $queryParams[] = $values[$k]; + } + if ( is_null( $this->queue ) ) + { + $this->_execute($insertSql, $queryParams); + $this->setId($this->_conn->Insert_ID()); + return $this->getId(); + } + else + { + $sql = array(); + foreach( $queryParams as $v ) + { + $sql[] = org_glizy_dataAccess_DataAccess::qstr( $v ); + } + $this->queue->push( '('.implode( ', ', $sql ).')' ); + return true; + } + } + + function _update($values=NULL) + { + $values = $this->_collectFieldsValues(false, false); + $queryParams = array(); + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL) continue; + if (array_key_exists('defaultUpdateValue', $v)) + { + $values[$k] = $v['defaultUpdateValue']; + + if ($values[$k]=='NOW()' && ( $v['type']==AR_TYPE_DATE || $v['type']==AR_TYPE_DATETIME ) ) + { + $values[$k] = $this->_createInsertDate( $v['type'] ); + } + } + if ( $v['type']==AR_TYPE_DATE || $v['type']==AR_TYPE_DATETIME ) + { + if ( empty($values[$k]) ) + { + $values[$k] = $this->_createEmptyDate( $v['type'] ); + } + else + { + $values[$k] = glz_localeDate2default($values[$k] ); + } + } + if ( $v['type'] == AR_TYPE_INTEGER ) { + if ($values[$k]===true) $values[$k] = 1; + else if ($values[$k]===false) $values[$k] = 0; + } + + if (is_null($values[$k]) && array_key_exists('null', $v) && $v['null']==false) + { + $values[$k] = ''; + } + + $queryParams[] = $values[$k]; + } + $queryParams[] = $this->getId(); + // TODO + // controllare che l'ID sia valido + $rs = &$this->_execute($this->_getSqlString('UPDATE'), $queryParams); + + if ($rs) + { + return true; + } + else + { + // TODO + // visualizzare errore + // $e = ADODB_Pear_Error(); + // echo '<p>',$e->message,'</p>'; + return false; + } + } + + + function _collectFieldsValues($getRelationValues=false, $getVirtualField=true, $encode=false) + { + $values = array(); + $relationsKeys = array_keys($this->_relations); + + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL && ((in_array($k, $relationsKeys) && !$getRelationValues) || (!$getVirtualField))) + { + continue; + } + if ($encode && $v['canEncode'] && $v['type']!= AR_TYPE_VIRTUAL ) + { + $values[$k] = glz_encodeOutput($this->$k); + } + else + { + if ( !empty( $v['filter'] ) ) + { + $v['filter']->apply( $this->$k, $this ); + } + $values[$k] = $this->$k; + } + } + + if ($getRelationValues) + { + $this->buildAllRelations(); + foreach ($this->_relations as $k=>$v) + { + if (!is_object($this->$k)) $values[$k] = $this->$k; + else + { + if ( method_exists( $this->$k, 'collectFieldsValues' ) ) + { + $values[$k] = $this->$k->collectFieldsValues( $getVirtualField, $encode ); + } + else + { + $values[$k] = NULL; + } + } + } + } + return $values; + } + + function getFieldValue($name) + { + $this->buildAllRelations(); + return isset($this->$name) ? $this->$name : ''; + } + + function getFieldValueByRegexp($name) + { + $this->buildAllRelations(); + + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL ) + { + continue; + } + if ( strpos( $k, $name ) !== false ) + { + return $this->$k; + } + } + return ''; + } + + + + function getFieldDefaultValue($name) + { + return $this->_fieldsList[$name]['defaultValue']; + } + + + function setFieldValue($name, $value) + { + //if (isset($this->$name)) + //{ + $this->$name = $value; + //} + } + + // TODO + // rimuovere la funzione perch� � un duplicato di getPrimaryKey + function getPrimaryKeyName() + { + return $this->_tablePrimaryKey; + } + + /*****/ + + + function _replaceSqlTag($sql) + { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + if (strpos($sql, '##TABLE_NAME##')!==false) $sql = str_replace('##TABLE_NAME##', $this->getTableName(), $sql); + $sql = str_replace('##SELECT_ALL##', $this->_getQuerySqlString('all', false), $sql); + $sql = str_replace('##TABLE_PREFIX##', $this->_tablePrefix, $sql); + $sql = str_replace('##SITE_ID##', org_glizy_Config::get('SITE_ID'), $sql); + if (!is_null($application)) + { + $user = &$application->getCurrentUser(); + $sql = str_replace('##USER_ID##', $user->id, $sql); + $sql = str_replace('##USER_GROUP_ID##', $user->groupId, $sql); + $sql = str_replace('##LANGUAGE_ID##', $application->getLanguageId(), $sql); + if (method_exists($application, 'getEditingLanguageId')) $sql = str_replace('##EDITING_LANGUAGE_ID##', $application->getEditingLanguageId(), $sql); + } + if( strpos($sql, "??") !== false ) + { + preg_match_all( "/\?\?([^\?]*)\?\?/U", $sql, $resmatch ); + foreach( $resmatch[1] as $varname) + { + if ( strpos( $varname, '.' ) !== false ) + { + list( $filterName, $name ) = explode( '.', $varname ); + $value = call_user_func( $filterName, __Request::get($name) ); + } + else + { + $value = __Request::get($varname); + } + $sql = str_replace("??$varname??", org_glizy_dataAccess_DataAccess::qstr( $value ), $sql); + } + } + return $sql; + } + + function &loadQuery($queryName, $options=array()) + { + org_glizy_dataAccess_DataAccess::selectDB( $this->_connNumber ); + if ($this->_conn->debug) { + echo '<b>'.$queryName.'</b><br>'; + } + + if ( $this->enableLog ) + { + $eventInfo = array('type' => GLZ_LOG_EVENT, 'data' => array( + 'level' => GLZ_LOG_DEBUG, + 'group' => '', + 'message' => 'loadQuery: '.$queryName + )); + $evt = org_glizy_ObjectFactory::createObject( 'org.glizy.events.Event', $this, $eventInfo ); + org_glizy_events_EventDispatcher::dispatchEvent( $evt ); + } + if ( !isset( $options[ 'sql' ] ) ) + { + $sql = $this->_getQuerySqlString($queryName); + $sql = rtrim($sql, ';'); + $params = isset($options['params']) ? $options['params'] : array(); + $checkIntegrity = isset($options['checkIntegrity']) ? $options['checkIntegrity'] : true; + + if (!isset($options['filters'])) $options['filters'] = array(); + if (!is_array($options['filters'])) $options['filters'] = array($options['filters']); + + if (strpos($sql, 'WHERE')===false) + { + foreach ($this->_fieldsList as $k=>$v) + { + if (isset($v['defaultSelectValue']) && !isset($options['filters'][$k]) ) + { + if ( $v['languageField'] === true || $v['versionField']== true || $options['default'] !== false) + { + $options['filters'][$k] = $v['defaultSelectValue']; + } + } + } + } + // se � definito un sito forza la condizione + if ( !is_null( __Config::get( 'SITE_ID' ) ) && !is_null( $this->_siteIdField ) && !isset( $options['filters'][ $this->_siteIdField ] ) ) + { + $options['filters'][ $this->_siteIdField ] = __Config::get( 'SITE_ID' ); + } + $sqlWhere = '('; + foreach ($options['filters'] as $filterName=>$filterValue) + { + if (!is_string($filterName)) + { + $sqlWhere .= $filterValue.' AND '; + continue; + } + else if (!isset($this->_fieldsList[$filterName]) && $checkIntegrity ) continue; + + if ( $this->_fieldsList[$filterName]['type'] == AR_TYPE_DATE || $this->_fieldsList[$filterName]['type'] == AR_TYPE_DATETIME ) + { + if ( is_array($filterValue) && $filterValue[0] == "=" ) + { + $filterValue = $filterValue[1]; + } + } + + if (!is_array($filterValue)) + { + switch ($this->_fieldsList[$filterName]['type']) + { + case AR_TYPE_DATE: + case AR_TYPE_DATETIME: + $sqlWhere .= $filterName.' LIKE '.org_glizy_dataAccess_DataAccess::qstr('%'.$filterValue.'%').' AND '; + break; + case AR_TYPE_INTEGER: + case AR_TYPE_SITEID: + case AR_TYPE_ENUM: + if ($filterValue!='') $sqlWhere .= $filterName.'= '.org_glizy_dataAccess_DataAccess::qstr($filterValue).' AND '; + break; + default: + if ($this->_fieldsList[$filterName]['canEncode'] === false) + { + $filterValue = glz_encodeOutput($filterValue); + } + if ( !empty( $filterValue ) ) + { + $sqlWhere .= $filterName.' LIKE '.org_glizy_dataAccess_DataAccess::qstr('%'.$filterValue.'%').' AND '; + } + break; + } + } + else + { + $sqlWhere .= $filterName.' '.$filterValue[0].(isset($filterValue[1]) ? ' '.org_glizy_dataAccess_DataAccess::qstr($filterValue[1]) : '').' AND '; + } + } + $sqlWhere .= '1=1) '; + + // se � definita l'acl + $sqlWhere .= $this->_addAclClause(); + if (isset($options['categories'])) $sqlWhere .= $this->_addAclCategoriesClause( $options['categories'] ); + + if (strripos ( $sql, 'WHERE' ) === false) + { + if (strripos ( $sql, 'ORDER' )===false && strripos ( $sql, 'GROUP BY' )===false ) + { + $sql .= ' WHERE '.$sqlWhere; + } + else if (strripos ( $sql, 'GROUP BY' )===false ) + { + $sql = str_replace('ORDER', ' WHERE '.$sqlWhere.' ORDER ', $sql); + } + else + { + $sql = str_replace('GROUP BY', ' WHERE '.$sqlWhere.' GROUP BY', $sql); + } + } + else + { + $sql = str_replace('WHERE', 'WHERE '.$sqlWhere.' AND ', $sql); + } + $sql = str_replace('##W##', 'WHERE', $sql); + + if (isset($options['group'])) + { + if ( strripos( $sql, 'GROUP BY') !== false ) + { + $sql .= ' GROUP BY '.$options['group']; + } + } + + if (isset($options['order'])) + { + // TODO + // controllare che i valori passati in orderBy siano delle colonne valide + $order = is_array($options['order']) ? implode(',', $options['order']) : $options['order']; + + if ( strripos( $sql, 'ORDER') === false ) + { + $order = ' ORDER BY '.$order; + } + else + { + $order = ', '.$order; + } + // if ( strripos( $sql, 'GROUP BY') !== false ) + // { + // list( $p1, $p2 ) = explode( 'GROUP BY', $sql ); + // $sql = $p1.$order.' GROUP BY '.$p2; + // } + // else + // { + $sql .= $order; + // } + } + } + else + { + $sql = $options[ 'sql' ]; + } + + if ( isset( $options[ 'numRows' ] ) && $options[ 'numRows' ] == true ) + { + if ( stripos( $sql, 'SELECT SQL_CALC_FOUND_ROWS' ) === false ) + { + $pos = stripos( $sql, 'SELECT' ); + $sql = 'SELECT SQL_CALC_FOUND_ROWS '.substr( $sql, $pos + 7 ); + } + } + + // esegue la paginazione + if (isset($options['limit']) && !empty($options['limit'])) + { + if (is_string($options['limit'])) + { + list($limitStart, $limitLength) = explode(',', $options['limit']); + } + else + { + if (!isset($options['limit']['start'])) + { + $limitStart = $options['limit'][0]; + $limitLength = $options['limit'][1]; + } + else + { + $limitStart = $options['limit']['start']; + $limitLength = $options['limit']['pageLength']; + } + } + if ( stripos( $sql, 'limit' ) ) + { + $sql = preg_replace( '/limit\s*\d*,\s*?\d$/i', '', $sql ); + } + $rs = &$this->_execute($sql, $params, $limitLength, $limitStart ); + } + else + { + $rs = &$this->_execute($sql, $params); + } + + if ($this->_conn->ErrorNo()) + { + $this->triggerError($this->getClassName().': '.$this->_conn->ErrorMsg()." ".$sql); + } + + + $recordIterator = new org_glizy_dataAccess_RecordIterator($rs, get_class($this)); + + if ( stripos( $sql, 'SELECT SQL_CALC_FOUND_ROWS' ) !== false ) + { + $rs2 = $this->execSql( 'SELECT FOUND_ROWS() as tot;' ); + $recordIterator->setCount( $rs2->fields[ 'tot' ] ); + } + + return $recordIterator; + } + + function &loadOneRecord($queryName, $params=array()) + { + $recordIterator = &$this->loadQuery($queryName, $params); + return $recordIterator->current(); + } + + function &findBySql($sql, $params=array()) + { + org_glizy_dataAccess_DataAccess::selectDB( $this->_connNumber ); + $sql = $this->_replaceSqlTag($sql); + $rs = &$this->_execute($sql, $params); + $recordIterator = new org_glizy_dataAccess_RecordIterator($rs, get_class($this)); + + if ( stripos( $sql, 'SELECT SQL_CALC_FOUND_ROWS' ) !== false ) + { + $rs2 = $this->execSql( 'SELECT FOUND_ROWS() as tot;' ); + $a = $rs2->GetArray(); + $recordIterator->setCount( $a[ 0 ][ 'tot' ] ); + } + + return $recordIterator; + } + + function execSql($sql, $params=array()) + { + org_glizy_dataAccess_DataAccess::selectDB( $this->_connNumber ); + $sql = $this->_replaceSqlTag($sql); + $result = $this->_execute($sql, $params); + return $result; + } + + function execSqlByName($queryName, $params=array()) + { + org_glizy_dataAccess_DataAccess::selectDB( $this->_connNumber ); + $sql = $this->_getQuerySqlString($queryName); + $result = $this->_execute($sql, $params); + return $result; + } + + + function addQuery($name, $sql) + { + $this->_querySql[strtolower($name)] = $sql; + } + + function getQuery($name) + { + return $this->_querySql[strtolower($name)]; + } + + function _getQuerySqlString($queryName, $replaceTags=true) + { + $queryName = strtolower($queryName); + + if (!array_key_exists('all', $this->_querySql)) + { + $sql = 'SELECT *'; + $sql .= ' FROM '.$this->_tableName; + $this->addQuery('all', $sql); + } + + $sql = ''; + if (!array_key_exists($queryName, $this->_querySql)) + { + if ( method_exists( $this, $queryName ) ) + { + $sql = call_user_func_array( array( $this, $queryName ), array() ); + } + } + else + { + // sostituisce le keywords riconosciute + $sql = $this->_querySql[$queryName]; + } + + if ($replaceTags) + { + $sql = $this->_replaceSqlTag( $sql ); + } + + return $sql; + } + + function loadDictionary($field, $queryName=NULL, $skipEmpty=false, $delimiter='', $version='PUBLISHED') + { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + if (is_null($queryName)) + { + $field = explode(',', $field); + $filter = $this->_fieldsList[ count($field)>1 ? $field[1] : $field[0] ][ 'filter' ]; + $sql = 'SELECT DISTINCT UPPER('.$field[0].') as k, '.(count($field)>1 ? $field[1] : $field[0]).' as v' ; + $sql .= ' FROM '.$this->getTableName(); + $sql .= ' WHERE 1=1'; + foreach ($this->_fieldsList as $k=>$v) + { + if (isset($v['languageField']) && $v['languageField']===true) + { + $sql .= ' AND '.$k.'='.$application->getLanguageId(); + } + if (isset($v['versionField']) && $v['versionField']===true) + { + $sql .= ' AND '.$k.'=\''.$version.'\''; + } + if (isset($v['defaultSelectValue'])) + { + $sql .= ' AND '.$k.'=\''.$v['defaultSelectValue'].'\''; + } + } + /* + codice da verificare + if ( !is_null( __Config::get( 'SITE_ID' ) ) && !is_null( $this->_siteIdField ) ) + { + $sql .= ' AND '.$this->_siteIdField.'=\''.__Config::get( 'SITE_ID' ).'\''; + } + */ + + $sql .= ' ORDER BY v'; + } + else + { + $filter = null; + $sql = $this->_getQuerySqlString($queryName); + } + $result = array(); + $usedKeys = array(); + $rs = &$this->_execute($sql); + while (!$rs->EOF) + { + if (!($skipEmpty && empty($rs->fields['v']))) + { + $value = $rs->fields['v']; + if ( !empty( $filter ) ) + { + $filter->apply( $value, $this ); + } + if ( !$delimiter ) + { + $result[] = array('key' => $rs->fields['k'], 'value' => $value ); + } + else + { + $kk = explode( $delimiter, $rs->fields['k'] ); + $vv = explode( $delimiter, $value ); + $l = count( $kk ); + for( $i = 0; $i < $l; $i++ ) + { + if ( !in_array( $kk[ $i ], $usedKeys ) ) + { + $usedKeys[] = $kk[ $i ]; + $result[] = array('key' => $kk[ $i ], 'value' => $vv[ $i ] ); + } + } + } + } + $rs->MoveNext(); + } + if ( $delimiter ) + { + org_glizy_helpers_Array::arrayMultisortByLabel( $result, 'value' ); + } + return $result; + } + + + function getVersionFieldName() + { + $fieldName = NULL; + foreach ($this->_fieldsList as $k=>$v) + { + if (isset($v['versionField']) && $v['versionField']===true) + { + $fieldName = $k; + break; + } + } + return $fieldName; + } + + function getLanguageFieldName() + { + $fieldName = NULL; + foreach ($this->_fieldsList as $k=>$v) + { + if (isset($v['languageField']) && $v['languageField']===true) + { + $fieldName = $k; + break; + } + } + return $fieldName; + } + + function _createInsertDate( $type ) + { + if ( $type == AR_TYPE_DATE ) + { + return date('Y-m-d'); + } + else if ( $type == AR_TYPE_DATETIME ) + { + return date('Y-m-d H:i:s'); + } + } + + function _createInsertDateNative( $type ) + { + if ( $type == AR_TYPE_DATE ) + { + return 'CURDATE()'; + } + else if ( $type == AR_TYPE_DATETIME ) + { + return 'NOW()'; + } + } + + function _createEmptyDate( $type ) + { + if ( $type == AR_TYPE_DATE ) + { + return date('0000-00-00'); + } + else if ( $type == AR_TYPE_DATETIME ) + { + return date('0000-00-00 00:00:00'); + } + } + + function _validateDate( $value, $type ) + { + if ($value!='0000-00-00' && $value!='0000-00-00 00:00:00' && !is_null($value) && !empty($value) ) + { + if (strlen($value)>=10) + { + $reg = __T( $type == 'date' ? 'GLZ_TIME_TO_DATE_REGEXP' : 'GLZ_TIME_TO_DATETIME_REGEXP' ); + + if ( is_array( $reg ) && preg_match( $reg[0], $value ) ) + { + $value = glz_defaultDate2locale( __T( $type == AR_TYPE_DATE ? 'GLZ_DATE_FORMAT' : 'GLZ_DATETIME_FORMAT' ), $value ); + } + } + } + else + { + $value = ''; + } + return $value; + } + + function _addAclClause() + { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $sql = ''; + if ( !is_null( $this->_aclField ) && !$application->isAdmin() ) + { + $user = &$application->getCurrentUser(); + $sql = ' AND ( ( SELECT count(*) FROM '.$this->_tablePrefix.'joins_tbl WHERE join_objectName = \''.$this->getTableNameWithoutPrefix().'#acl\' AND join_FK_source_id = '.$this->getPrimaryKey().' ) = 0 '; + $sql .= ' OR '; + $sql .= ' ( SELECT join_id FROM '.$this->_tablePrefix.'joins_tbl WHERE join_objectName = \''.$this->getTableNameWithoutPrefix().'#acl\' AND join_FK_source_id = '.$this->getPrimaryKey().' AND join_FK_dest_id = \''.$user->groupId.'\' LIMIT 0,1) IS NOT NULL )'; + } + return $sql; + } + + function _addAclCategoriesClause( $categories ) + { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $sql = ''; + if ( !is_null( $this->_aclCategories ) && !empty( $categories ) && !$application->isAdmin() ) + { + $user = &$application->getCurrentUser(); + $sql = ' AND ( ( SELECT count(*) FROM '.$this->_tablePrefix.'joins_tbl WHERE join_objectName = \''.$this->getTableNameWithoutPrefix().'#acl_category\' AND join_FK_source_id = '.$this->getPrimaryKey().' ) = 0 '; + $sql .= ' OR '; + $sql .= ' ( SELECT join_id FROM '.$this->_tablePrefix.'joins_tbl WHERE join_objectName = \''.$this->getTableNameWithoutPrefix().'#acl_category\' AND join_FK_source_id = '.$this->getPrimaryKey().' AND join_FK_dest_id IN('.$categories.') LIMIT 0,1) IS NOT NULL )'; + } + return $sql; + } + + /** + * @param $sql + * @param array $params + * @param null $limitLength + * @param null $limitStart + * @return mixed + */ + function _execute( $sql, $params = array(), $limitLength = null, $limitStart = null ) + { + if ( $sql != 'SELECT FOUND_ROWS() as tot;' ) + { + $this->lastSql = $sql; + } + + $debugState = $this->_conn->debug; + if ( $this->enableLog ) + { + $this->_conn->debug = true; + } + + $startTime = microtime(); + $sqlForLog = $sql; + ob_start(); + if ( is_null( $limitLength ) ) + { + $r = $this->_conn->execute( $sql, $params ); + } + else + { + $r = $this->_conn->selectLimit( $sql, $limitLength, $limitStart, $params ); + } + + $sql = ob_get_clean(); + $this->_conn->debug = $debugState; + + $eventInfo = array( 'type' => GLZ_EVT_AR_EXEC_SQL, + 'data' => array( + 'level' => GLZ_LOG_DEBUG, + 'group' => '', + 'message' => array( 'sql' => $sqlForLog, + 'params' => $params, + 'startTime' => $startTime, + 'resultSet' => $r) + )); + $evt = org_glizy_ObjectFactory::createObject( 'org.glizy.events.Event', $this, $eventInfo ); + org_glizy_events_EventDispatcher::dispatchEvent( $evt ); + + if ( $this->_conn->debug || $this->enableLog ) + { + if ( $this->enableLog ) + { + $eventInfo = array('type' => GLZ_LOG_EVENT, 'data' => array( + 'level' => GLZ_LOG_DEBUG, + 'group' => '', + 'message' => strip_tags( $sql ) + )); + $evt = org_glizy_ObjectFactory::createObject( 'org.glizy.events.Event', $this, $eventInfo ); + org_glizy_events_EventDispatcher::dispatchEvent( $evt ); + } + + if ( $this->_conn->debug ) + { + echo $sql."<br />\n\r"; + } + } + + return $r; + } + + function enableQueue() + { + $this->queue = $this->_conn->getQueueExecute(); + $this->queue->init( $this->_getSqlString( 'INSERT_QUEUE' ) ); + return true; + } + + function executeQueue() + { + $result = $this->queue->execute(); + $this->queue = NULL; + if (!$result) { + return false; + } else { + return true; + } + } + + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/ActiveRecord2tables.php b/src/core/classes/org/glizy/dataAccess/ActiveRecord2tables.php new file mode 100755 index 0000000..96e7325 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/ActiveRecord2tables.php @@ -0,0 +1,613 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_dataAccess_ActiveRecord2tables extends org_glizy_dataAccess_ActiveRecord +{ + var $_tablesName = array(); + var $_joinFields = array(); + var $_tableDetailPrimaryKey = NULL; + + function __construct() + { + parent::__construct(); + } + + function getTableName() + { + return $this->_tablesName['mainTable']; + } + + function setTableName($theName1, $theName2) + { + $this->_tablesName['mainTable'] = $this->_tablePrefix.$theName1; + $this->_tablesName['detailTable'] = $this->_tablePrefix.$theName2; + } + + function getJoinFields() + { + return $this->_joinFields; + } + + function setJoinFields($theJoin1, $theJoin2) + { + $this->_joinFields['mainTable'] = $theJoin1; + $this->_joinFields['detailTable'] = $theJoin2; + } + + function addField($field) + { + if (isset($field['primaryKey']) && $field['primaryKey']===true) + { + + if (isset($field['detailTable']) && $field['detailTable']===true) + { + if (is_null($this->_tableDetailPrimaryKey)) + { + $this->_tableDetailPrimaryKey = $field['name']; + } + else + { + // TODO: + // visualizzare un errore perché puà esserci solo una chiave primaria + } + } + else + { + if (is_null($this->_tablePrimaryKey)) + { + $this->_tablePrimaryKey = $field['name']; + } + else + { + // TODO: + // visualizzare un errore perché puà esserci solo una chiave primaria + } + } + } + + parent::addField($field, true); + } + + function getDetailId() + { + if (is_null($this->_tablePrimaryKey)) + { + // TODO: + // visualizzare un errore perché puà esserci solo una chiave primaria + + return NULL; + } + $primarykey = $this->_tableDetailPrimaryKey; + return $this->$primarykey; + } + + function setDetailId($value) + { + $primarykey = $this->_tableDetailPrimaryKey; + $this->$primarykey = $value; + } + + function getDetailPrimarykey() + { + return $this->_tableDetailPrimaryKey; + } + + function load($id=NULL, $idDetail=NULL, $queryName=NULL ) + { + $this->error = false; + + $queryParams = array(); + if (is_null($id)) + { + $id = $this->getId(); + } + + if (is_null($idDetail)) + { + $idDetail = $this->getDetailId(); + } + + if ( is_null( $queryName ) ) + { + $tempFields = array(); + $tempInsertField = array(); + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL) continue; + $tempFields[] = $k; + $tempInsertField[] = '?'; + } + + $sql = ''; + $sql .= 'SELECT '; + $sql .= implode(',', $tempFields); + $sql .= ' FROM '.$this->_tablesName['mainTable']; + $sql .= ' INNER JOIN '.$this->_tablesName['detailTable'].' ON ('.implode('=', $this->_joinFields).')'; + $sql .= ' WHERE 1=1'; + if (!is_null($id)) + { + $sql .= ' AND '.$this->_tablePrimaryKey.' = ?'; + $queryParams[] = $id; + } + if (!is_null($idDetail)) + { + $sql .= ' AND '.$this->_tableDetailPrimaryKey.' = ?'; + $queryParams[] = $idDetail; + } + } + else + { + $sql = $this->_getQuerySqlString( $queryName ); + } + $sql .= $this->_addAclClause(); + + // TODO + // se la query genera più record + // bisogna generare un errore + + $rs = &$this->_execute($sql, $queryParams); + $rsFields = $rs->fields; + if ($rsFields) + { + $this->loadFromArray($rsFields); + $this->buildAllRelations(); + return true; + } + else + { + // TODO + // visualizzare errore + // $e = ADODB_Pear_Error(); + // echo '<p>',$e->message,'</p>'; + $this->error = true; + return NULL; + } + } + + function find($values=array()) + { + org_glizy_dataAccess_DataAccess::selectDB( $this->_connNumber ); + $this->loadFromArray($values); + $this->error = false; + + $tempFields = array(); + $tempWhereValue = array(); + $tempWhereCond = array(); + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL) continue; + $tempFields[] = $k; + if (!is_null($this->$k) && ($v['defaultValue']!=$this->$k)) + { + $tempWhereValue[] = $this->$k; + $tempWhereCond[] = $k.'=?'; + } + } + + $sql = ''; + $sql .= 'SELECT '; + $sql .= implode(',', $tempFields); + $sql .= ' FROM '.$this->_tablesName['mainTable']; + $sql .= ' INNER JOIN '.$this->_tablesName['detailTable'].' ON ('.implode('=', $this->_joinFields).')'; + $sql .= ' WHERE '.implode(' AND ', $tempWhereCond); + $sql .= $this->_addAclClause(); + $sql .= ' LIMIT 1'; + + $rs = &$this->_execute($sql, $tempWhereValue); + $rsFields = $rs->fields; + if ($rsFields) + { + $this->loadFromArray($rsFields); + $this->buildAllRelations(); + return true; + } + else + { + $this->error = true; + return NULL; + } + } + + function save($values=NULL) + { + if ($this->_processRelations) $this->buildAllRelations(); + if (!is_null($values)) $this->loadFromArray($values); + if ($this->_processRelations) $this->_saveAllRelations(true); + + // TODO + // controllo della validità dei campi e se i campi "required" sono riempiti + $primaryId = $this->getId(); + if (empty($primaryId)) + { + $result1 = $this->_insertMain($values); + } + else + { + $result1 = $this->_updateMain($values); + } + + $detailId = $this->getDetailId(); + if (empty($detailId)) + { + $result2 = $this->_insertDetail($values); + $evt = array('type' => GLZ_EVT_AR_INSERT.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + } + else + { + $result2 = $this->_updateDetail($values); + $evt = array('type' => GLZ_EVT_AR_UPDATE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + } + + if ($this->_processRelations) $this->_saveAllRelations(false); + + return array($result1, $result2); + } + + function delete($id=NULL) + { + org_glizy_dataAccess_DataAccess::selectDB( $this->_connNumber ); + if (is_null($id)) + { + $id = $this->getId(); + } + + if (is_null($id)) + { + // visualizzare errore + } + + $this->setId( $id ); + $sql = 'DELETE '; + $sql .= ' FROM '.$this->_tablesName['mainTable']; + $sql .= ' WHERE '.$this->_tablePrimaryKey.' = ?'; + $rs = $this->_execute($sql, array($id)); + + $sql = 'DELETE '; + $sql .= ' FROM '.$this->_tablesName['detailTable']; + $sql .= ' WHERE '.$this->_joinFields['detailTable'].' = ?'; + $rs = $this->_execute($sql, array($id)); + + $evt = array('type' => GLZ_EVT_AR_DELETE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + if ($this->_processRelations) + { + $this->buildAllRelations( false ); + $this->_deleteAllRelations(); + } + $this->emptyRecord(); + + if ($rs) return true; + else { + // TODO + // visualizzare errore + // $e = ADODB_Pear_Error(); + // echo '<p>',$e->message,'</p>'; + return false; + } + } + + + + function _insert() + { + } + + function _insertMain($values=NULL) + { + $values = $this->_collectFieldsValues(); + $tempFields = array(); + $tempInsertField = array(); + $queryParams = array(); + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL || (isset($v['detailTable']) && $v['detailTable']===true)) continue; + if (isset($v['defaultInsertValue'])) + { + $values[$k] = $v['defaultInsertValue']; + if ($values[$k]=='NOW()' && ( $v['type']==AR_TYPE_DATE || $v['type']==AR_TYPE_DATETIME ) ) + { + $values[$k] = $this->_createInsertDate( $v['type'] ); + } + } + if ( $v['type']==AR_TYPE_DATE || $v['type']==AR_TYPE_DATETIME ) + { + if ( empty($values[$k]) ) + { + $values[$k] = $this->_createEmptyDate( $v['type'] ); + } + else + { + $values[$k] = glz_localeDate2default($values[$k] ); + } + } + $queryParams[] = $values[$k]; + $tempFields[] = $k; + $tempInsertField[] = '?'; + } + $sql = 'INSERT INTO '.$this->_tablesName['mainTable'].' '; + $sql .= '('.implode(',', $tempFields).')'; + $sql .= ' VALUES ( '.implode(',', $tempInsertField).');'; + + $this->_execute($sql, $queryParams); + $this->setId($this->_conn->Insert_ID()); + return $this->getId(); + } + + function _insertDetail($values=NULL) + { + // TODO + // forse il loadFromArray può essere spostato in save() + $values[$this->_joinFields['detailTable']] = $this->getId(); + if (!is_null($values)) $this->loadFromArray($values); + $values = $this->_collectFieldsValues(); + + $tempFields = array(); + $tempInsertField = array(); + $queryParams = array(); + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL || (!isset($v['detailTable']) || $v['detailTable']===false)) continue; + if (isset($v['defaultInsertValue']) && ($values[$k]==$v['defaultValue'] || empty($values[$k]))) + { + $values[$k] = $v['defaultInsertValue']; + if ($values[$k]=='NOW()' && ( $v['type']==AR_TYPE_DATE || $v['type']==AR_TYPE_DATETIME ) ) + { + $values[$k] = $this->_createInsertDate( $v['type'] ); + } + } + if ( $v['type']==AR_TYPE_DATE || $v['type']==AR_TYPE_DATETIME ) + { + if ( empty($values[$k]) ) + { + $values[$k] = $this->_createEmptyDate( $v['type'] ); + } + else + { + $values[$k] = glz_localeDate2default($values[$k] ); + } + } + $queryParams[] = is_null($values[$k]) && !$v['primaryKey']==true ? '' : $values[$k]; + $tempFields[] = $k; + $tempInsertField[] = '?'; + } + + + $sql = 'INSERT INTO '.$this->_tablesName['detailTable'].' '; + $sql .= '('.implode(',', $tempFields).')'; + $sql .= ' VALUES ( '.implode(',', $tempInsertField).');'; + + $this->_execute($sql, $queryParams); + $this->setDetailId($this->_conn->Insert_ID()); + return $this->getDetailId(); + } + + + function _update() + { + } + + function _updateMain($values=NULL) + { + $values = $this->_collectFieldsValues(); + $tempFields = array(); + $tempInsertField = array(); + $queryParams = array(); + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL || (isset($v['detailTable']) && $v['detailTable']===true)) continue; + if (isset($v['defaultUpdateValue'])) + { + $values[$k] = $v['defaultUpdateValue']; + + // TODO + // controllare il tipo del campo + if ($values[$k]=='NOW()') $values[$k] = date('Y-m-d H:i:s'); + } + if ( $v['type']==AR_TYPE_DATE || $v['type']==AR_TYPE_DATETIME ) + { + if ( empty($values[$k]) ) + { + $values[$k] = $this->_createEmptyDate( $v['type'] ); + } + else + { + $values[$k] = glz_localeDate2default($values[$k] ); + } + } + $queryParams[] = $values[$k]; + $tempFields[] = $k; + $tempInsertField[] = '?'; + } + $queryParams[] = $this->getId(); + + $sql = 'UPDATE '.$this->_tablesName['mainTable'].' SET '; + $sql .= implode('= ?,', $tempFields).'= ? '; + $sql .= ' WHERE '.$this->_tablePrimaryKey.' = ?'; + + $rs = $this->_execute($sql, $queryParams); + if ($rs) + { + return true; + } + else + { + // TODO + // visualizzare errore + // $e = ADODB_Pear_Error(); + // echo '<p>',$e->message,'</p>'; + return false; + } + } + + function _updateDetail($values=NULL) + { + // TODO + // forse il loadFromArray può essere spostato in save() + if (!is_null($values)) $this->loadFromArray($values); + $values = $this->_collectFieldsValues(); + $tempFields = array(); + $tempInsertField = array(); + $queryParams = array(); + foreach ($this->_fieldsList as $k=>$v) + { + if ($v['type']==AR_TYPE_VIRTUAL || (!isset($v['detailTable']) || $v['detailTable']===false)) continue; + if (isset($v['defaultUpdateValue'])) + { + $values[$k] = $v['defaultUpdateValue']; + + if ($values[$k]=='NOW()' && ( $v['type']==AR_TYPE_DATE|| $v['type']==AR_TYPE_DATETIME ) ) + { + $values[$k] = $this->_createInsertDate( $v['type'] ); + } + } + if ( $v['type']==AR_TYPE_DATE || $v['type']==AR_TYPE_DATETIME ) + { + if ( empty($values[$k]) ) + { + $values[$k] = $this->_createEmptyDate( $v['type'] ); + } + else + { + $values[$k] = glz_localeDate2default($values[$k] ); + } + } + $queryParams[] = is_null($values[$k]) ? '' : $values[$k]; + $tempFields[] = $k; + $tempInsertField[] = '?'; + } + $queryParams[] = $this->getDetailId(); + + $sql = 'UPDATE '.$this->_tablesName['detailTable'].' SET '; + $sql .= implode('= ?,', $tempFields).'= ? '; + $sql .= ' WHERE '.$this->_tableDetailPrimaryKey.' = ?'; + + $rs = $this->_execute($sql, $queryParams); + if ($rs) + { + return true; + } + else + { + // TODO + // visualizzare errore + // $e = ADODB_Pear_Error(); + // echo '<p>',$e->message,'</p>'; + return false; + } + } + + // TODO + // rimuovere la funzione perché è un duplicato di getDetailPrimaryKey + function getDetailPrimaryKeyName() + { + return $this->_tableDetailPrimaryKey; + } + + /*****/ + + function _replaceSqlTag($sql) + { + $sql = str_replace('##TABLE_NAME##', $this->_tablesName['mainTable'], $sql); + $sql = str_replace('##TABLE_DETAIL_NAME##', $this->_tablesName['detailTable'], $sql); + return parent::_replaceSqlTag($sql); + } + + function _getQuerySqlString($queryName, $replaceTags=true) + { + $queryName = strtolower($queryName); + + if (!array_key_exists('all', $this->_querySql)) + { + $sql = 'SELECT *'; + $sql .= ' FROM '.$this->_tablesName['mainTable']; + $sql .= ' INNER JOIN '.$this->_tablesName['detailTable'].' ON ('.implode('=', $this->_joinFields).')'; + $this->addQuery('all', $sql); + } + + return parent::_getQuerySqlString($queryName, $replaceTags); + } + + function loadDictionary($field, $queryName=NULL, $skipEmpty=false, $delimiter='', $version='PUBLISHED') + { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + if (is_null($queryName)) + { + $field = explode(',', $field); + $filter = $this->_fieldsList[ count($field)>1 ? $field[1] : $field[0] ][ 'filter' ]; + $sql = 'SELECT DISTINCT UPPER('.$field[0].') as k, '.(count($field)>1 ? $field[1] : $field[0]).' as v' ; + $sql .= ' FROM '.$this->_tablesName['mainTable']; + $sql .= ' INNER JOIN '.$this->_tablesName['detailTable'].' ON ('.implode('=', $this->_joinFields).')'; + $sql .= ' WHERE 1=1'; + foreach ($this->_fieldsList as $k=>$v) + { + if (isset($v['languageField']) && $v['languageField']===true) + { + $sql .= ' AND '.$k.'='.( method_exists($application, 'getEditingLanguageId') ? $application->getEditingLanguageId() : $application->getLanguageId() ); + } + if (isset($v['versionField']) && $v['versionField']===true) + { + $sql .= ' AND '.$k.'=\''.$version.'\''; + } + if (isset($v['defaultSelectValue'])) + { + $sql .= ' AND '.$k.'=\''.$v['defaultSelectValue'].'\''; + } + } + $sql .= ' ORDER BY v'; + } + else + { + $filter = null; + $sql = $this->_getQuerySqlString($queryName); + } + + $result = array(); + $usedKeys = array(); + $rs = &$this->_execute($sql); + while (!$rs->EOF) + { + if (!($skipEmpty && empty($rs->fields['v']))) + { + $value = $rs->fields['v']; + if ( !empty( $filter ) ) + { + $filter->apply( $value, $this ); + } + if ( !$delimiter ) + { + $result[] = array('key' => $rs->fields['k'], 'value' => $value ); + } + else + { + $kk = explode( $delimiter, $rs->fields['k'] ); + $vv = explode( $delimiter, $value ); + $l = count( $kk ); + for( $i = 0; $i < $l; $i++ ) + { + if ( !in_array( $kk[ $i ], $usedKeys ) ) + { + $usedKeys[] = $kk[ $i ]; + $result[] = array('key' => $kk[ $i ], 'value' => $vv[ $i ] ); + } + } + } + } + $rs->MoveNext(); + } + + if ( $delimiter ) + { + org_glizy_helpers_Array::arrayMultisortByLabel( $result, 'value' ); + } + return $result; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/DataAccess.php b/src/core/classes/org/glizy/dataAccess/DataAccess.php new file mode 100755 index 0000000..132863a --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/DataAccess.php @@ -0,0 +1,196 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +define( 'AR_TYPE_STRING', 'string' ); +define( 'AR_TYPE_VERSIONDATE', 'versiondate' ); +define( 'AR_TYPE_VERSIONSTATUS', 'versionstatus' ); +define( 'AR_TYPE_ENUM', 'enum' ); +define( 'AR_TYPE_LANGUAGE', 'language' ); +define( 'AR_TYPE_USER', 'user' ); +define( 'AR_TYPE_INTEGER', 'integer' ); +define( 'AR_TYPE_INT', 'int' ); +define( 'AR_TYPE_TEXT', 'text' ); +define( 'AR_TYPE_RICHTEXT', 'richtext' ); +define( 'AR_TYPE_SITEID', 'siteid' ); +define( 'AR_TYPE_DATE', 'date' ); +define( 'AR_TYPE_DATETIME', 'datetime' ); +define( 'AR_TYPE_ACL', 'acl' ); +define( 'AR_TYPE_CATEGORY', 'category' ); +define( 'AR_TYPE_VIRTUAL', 'virtual' ); + +include_once('driver/Connection.php'); + +class org_glizy_dataAccess_DataAccess +{ + /** + * @param int $n + * + * @return mixed + * @throws Exception + */ + static function &getConnection($n=0) + { + static $instance = array(); + + if (!isset($instance['__'.$n])) + { + $options = array(); + $sufix = $n == 0 ? '' : '#'.$n; + switch ( __Config::get( 'DB_TYPE'.$sufix ) ) + { + case 'sqlite': + $dsn = 'sqlite:'.__Paths::getRealPath( 'APPLICATION', 'data/'.__Config::get( 'DB_NAME'.$sufix ) ); + $dbUser = ''; + $dbPassword = ''; + break; + default: + $socket = __Config::get( 'DB_SOCKET'.$sufix ); + $socket = empty( $socket ) ? '' : ';unix_socket='.$socket; + $dsn = 'mysql:dbname='.__Config::get( 'DB_NAME'.$sufix ).';host='.__Config::get( 'DB_HOST'.$sufix ).$socket; + $dbUser = __Config::get( 'DB_USER'.$sufix ); + $dbPassword = __Config::get( 'DB_PSW'.$sufix ); + if ( __Config::get( 'CHARSET' ) == 'utf-8' ) + { + $options = array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"); + } + if ( __Config::get( 'DB_MYSQL_BUFFERED_QUERY' ) ) + { + $options[ PDO::MYSQL_ATTR_USE_BUFFERED_QUERY ] = true; + } + break; + } + $i = 0; + $lastException = null; + while (!isset($instance['__' . $n] )) { + try { + if ($i < 3) { + $instance['__' . $n] = new Connection($dsn, $dbUser, $dbPassword, $options); + } else { + break; + } + } catch (Exception $e) { + $i++; + $lastException = $e; + $eventInfo = array('type' => GLZ_LOG_EVENT, + 'data' => array( + 'level' => GLZ_LOG_ERROR, + 'group' => 'glizy.sql', + 'message' => array('errorMessage' => $e->getMessage(), 'errorCode' => $e->getCode(), 'attempt' => $i) + )); + $evt = org_glizy_ObjectFactory::createObject( 'org.glizy.events.Event', org_glizy_ObjectValues::get('org.glizy', 'application'), $eventInfo ); + org_glizy_events_EventDispatcher::dispatchEvent( $evt ); + } + } + if (!isset($instance['__' . $n])) { + throw new Exception($lastException->getMessage(), $lastException->getCode(), $lastException); + } + } + + + + return $instance['__'.$n]; + } + + /** + * @param $value + * @param int $n + * + * @return mixed + */ + static function qstr($value, $n=0) + { + $conn = &org_glizy_dataAccess_DataAccess::getConnection($n); + return $conn->qstr($value, false); + } + + /** + * @param $value + * @param int $n + * + * @return mixed + */ + static function escape($value, $n = 0) { + $conn = & org_glizy_dataAccess_DataAccess::getConnection($n); + + return $conn->escape($value); + } + + /** + * @param int $n + */ + static function close($n=0) + { + $conn = org_glizy_dataAccess_DataAccess::getConnection($n); + $conn->close(); + } + + /** + * @param $table + * @param bool $usePrefix + * @param int $n + * + * @return mixed + */ + static function getMetaColumns($table, $usePrefix=true, $n=0) + { + $prefix = $usePrefix!=false ? org_glizy_dataAccess_DataAccess::getTablePrefix( $n ) : ''; + $conn = org_glizy_dataAccess_DataAccess::getConnection($n); + $conn->SelectDB($conn->database); + return $conn->MetaColumns($prefix.$table, true); + } + + /** + * @param int $n + * + * @return mixed|null + */ + static function getTablePrefix( $n=0 ) + { + return org_glizy_Config::get( $n== 0 ? 'DB_PREFIX' : 'DB_PREFIX#'.$n); + } + + static function selectDB( $n=0 ) + { + $conn = org_glizy_dataAccess_DataAccess::getConnection($n); + $conn->SelectDB( $conn->database ); + } + + /** + * @param int $n + * + * @return mixed + */ + static function beginTransaction( $n=0 ) + { + $conn = org_glizy_dataAccess_DataAccess::getConnection($n); + return $conn->beginTransaction(); + } + + /** + * @param int $n + * + * @return mixed + */ + static function commit( $n=0 ) + { + $conn = org_glizy_dataAccess_DataAccess::getConnection($n); + return $conn->commit(); + } + + /** + * @param int $n + * + * @return mixed + */ + static function rollBack( $n=0 ) + { + $conn = org_glizy_dataAccess_DataAccess::getConnection($n); + return $conn->rollBack(); + } +} diff --git a/src/core/classes/org/glizy/dataAccess/RecordIterator.php b/src/core/classes/org/glizy/dataAccess/RecordIterator.php new file mode 100755 index 0000000..c384e58 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/RecordIterator.php @@ -0,0 +1,76 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class org_glizy_dataAccess_RecordIterator */ +class org_glizy_dataAccess_RecordIterator extends GlizyObject implements Iterator +{ + var $_rs = NULL; + var $_recordClassName = ''; + var $_count = NULL; + + function __construct(&$rs, $recordClassName) + { + $this->_rs = &$rs; + $this->_recordClassName = $recordClassName; + } + + function rewind() + { + $this->_rs->MoveFirst(); + } + + function valid() + { + return !$this->_rs->EOF; + } + + function &first() + { + $this->_rs->MoveFirst(); + return $this->current(); + } + + function key() + { + return $this->_rs->recordPos(); + } + + function &current() + { + $fields = $this->_rs->fields; + $activeRecord = & org_glizy_ObjectFactory::createModel($this->_recordClassName); + $activeRecord->loadFromArray($fields); + return $activeRecord; + } + + function next() + { + $this->_rs->MoveNext(); + } + + function count() + { + return $this->_count == NULL ? $this->_rs->RecordCount() : $this->_count; + } + + function setCount( $v ) + { + $this->_count = $v; + } + + function hasMore() + { + return !$this->_rs->EOF; + } + + function recordPos() + { + return $this->_rs->recordPos(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/Relation.php b/src/core/classes/org/glizy/dataAccess/Relation.php new file mode 100755 index 0000000..bfbafd1 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/Relation.php @@ -0,0 +1,93 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class org_glizy_dataAccess_Relation */ +class org_glizy_dataAccess_Relation extends GlizyObject +{ + var $_key = ''; + var $_destinationKey = ''; + var $_parent = NULL; + var $_conn = NULL; + var $_className = ''; + var $record = NULL; + var $_backUpValues = array(); + + function __construct(&$parent, $options) + { + //parent::BaseClass(); + $this->_conn = &org_glizy_dataAccess_DataAccess::getConnection(); + $this->_parent = &$parent; + assert(isset($options['className'])); + $this->_className = $options['className']; + } + + function createObject(&$parent, $options) + { + $relation = NULL; + switch (strtolower($options['type'])) + { + case 'hasone': + case 'has_one': + case 'fk': + $relation = new org_glizy_dataAccess_RelationHasOne($parent, $options); + break; + case 'hasmany': + case 'has_many': + $relation = new org_glizy_dataAccess_RelationHasMany($parent, $options); + break; + case 'many': + $relation = new org_glizy_dataAccess_RelationMany2Many($parent, $options); + break; + case 'jointable': + $relation = new org_glizy_dataAccess_RelationJoinTable($parent, $options); + break; + case 'contenttable': + $relation = new org_glizy_dataAccess_RelationContentTable($parent, $options); + break; + default: + // TODO + // visualizzare errore + break; + } + + return $relation; + } + + function &getObject() + { + return $this->record; + } + + function _bindRecordFields() + { + assert(!is_null($this->record)); + + foreach (array_keys($this->record->_fieldsList) as $fieldName) + { + $this->$fieldName = &$this->record->$fieldName; + } + } + + + // TODO + // implementare i metodi astratti + + function preSave() + { + + } + + function postSave() + { + } + + function delete() + { + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/RelationContentTable.php b/src/core/classes/org/glizy/dataAccess/RelationContentTable.php new file mode 100755 index 0000000..8903598 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/RelationContentTable.php @@ -0,0 +1,106 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class org_glizy_dataAccess_RelationContentTable */ +class org_glizy_dataAccess_RelationContentTable extends org_glizy_dataAccess_Relation +{ + var $_objectName = ''; + var $_newRecord; + var $_bindTo; + + function __construct(&$parent, $options) + { + parent::__construct($parent, $options); + $this->_objectName = $options['objectName'].':'.$options['name']; + $this->_bindTo = $options['bindTo']; + } + + function build($params=array()) + { + $this->_reset(); + $parentId = $this->_parent->getId(); + if (!is_null($parentId)) + { + $this->_newRecord = empty( $parentId ); + if ( !$this->_newRecord ) + { + + if ( $this->record->find( array( 'contentplugin_FK_id' => $parentId, 'contentplugin_objectName' => $this->_objectName ) ) ) + { + if ( __Request::exists( $this->_bindTo[ 0 ] ) ) return; + $values = unserialize( $this->record->contentplugin_value ); + if ( is_array( $values ) ) + { + foreach( $values as $k => $v ) + { + if ( in_array( $k, $this->_bindTo ) ) + { + $this->_parent->{$k} = $v; + } + } + } + } + } + } + } + + function create($params) + { + $this->record = org_glizy_ObjectFactory::createModel( $this->_className ); + $this->record->setProcessRelations(false); + + // TODO + } + + function bind(&$object) + { + $this->record = &$object; + $this->record->setProcessRelations(false); + + // TODO + } + + function postSave() + { + if ( !is_object( $this->record ) ) + { + $this->_reset(); + } + + $values = array(); + foreach( $this->_bindTo as $v ) + { + $values[ $v ] = $this->_parent->{$v}; + } + + $parentId = $this->_parent->getId(); + // $this->record->find( array( 'contentplugin_FK_id' => $parentId, 'contentplugin_objectName' => $this->_objectName ) ); + $this->record->contentplugin_FK_id = $parentId; + $this->record->contentplugin_objectName = $this->_objectName; + $this->record->contentplugin_value = serialize( $values ); + $this->record->save(); + } + + function delete() + { + // NOTA il delete deve funzionare anche senza la build della relazione + $this->_reset(); + $parentId = $this->_parent->getId(); + $this->record->execSql( 'DELETE ##TABLE_NAME## WHERE contentplugin_FK_id = '.$parentId.' AND contentplugin_objectName="'.$this->_objectName.'"' ); + $this->record->delete(); + } + + + function _reset() + { + $this->record = org_glizy_ObjectFactory::createModel( $this->_className ); + $this->_newRecord = false; + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/RelationHasMany.php b/src/core/classes/org/glizy/dataAccess/RelationHasMany.php new file mode 100755 index 0000000..5572e0e --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/RelationHasMany.php @@ -0,0 +1,200 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +/** class org_glizy_dataAccess_RelationHasMany */ +class org_glizy_dataAccess_RelationHasMany extends org_glizy_dataAccess_Relation +{ + var $recordSet = NULL; + var $iterator = NULL; + var $_recordsList = array(); + + function __construct(&$parent, $options) + { + parent::__construct($parent, $options); + assert(isset($options['field'])); + $this->_key = $options['field']; + assert(!is_null($this->_destinationKey)); + $this->_destinationKey = $options['destinationField']; + } + + function build($params=array()) + { + $this->record = &org_glizy_ObjectFactory::createModel($this->_className); + $filters = array(); + + if ( strpos( $this->_parent->{$this->_key}, ',' ) !== false ) + { + $filters[ $this->_destinationKey ] = array( 'IN ('.$this->_parent->{$this->_key}.')' ); + } + else + { + $filters[ $this->_destinationKey ] = $this->_parent->{$this->_key}; + } + $this->iterator = &$this->record->loadQuery('All', array('filters' => $filters ) ); + + if ($this->iterator->count()) + { + $this->current(); + } + else + { + $this->record = NULL; + } + } + + function create($params) + { + $this->_reset(); + $this->record = & org_glizy_ObjectFactory::createModel($this->_className); + $this->record->setProcessRelations(false); + + if (count($params)) + { + $this->record->loadFromArray($params); + } + $this->_bindRecordFields(); + } + + function bind(&$object) + { + if (get_class($object)!=$this->_className) + { + // TODO + // visualizzare errore + } + + $this->_reset(); + $this->record = &$object; + $this->record->{$this->_destinationKey} = $this->_parent->{$this->_key}; + $this->_recordsList[$this->record->getId()] = &$this->record; + $this->_backUpValues[$this->record->getId()] = $this->record->getValuesAsArray(); + $this->record->setProcessRelations(false); + $this->_bindRecordFields(); + } + + function postSave() + { + if (!is_object($this->record)) return; + if (is_null($this->record->{$this->_destinationKey})) + { + // nuovo record + $this->record->{$this->_destinationKey} = $this->_parent->{$this->_key}; + $newId = $this->record->save(); + $this->_backUpValues[$newId] = $this->record->getValuesAsArray(); + } + else + { + foreach($this->_recordsList as $id=>$obj) + { + $canSave = false; + $currentValues = $this->_recordsList[$id]->getValuesAsArray(); + foreach ($currentValues as $k=>$v) + { + if (!array_key_exists($k, $this->_backUpValues[$this->_recordsList[$id]->getId()]) || $this->_backUpValues[$this->_recordsList[$id]->getId()][$k]!=$v) + { + $canSave = true; + break; + } + } + + if ($canSave) + { + $this->_recordsList[$id]->save(); + $this->_backUpValues[$this->_recordsList[$id]->getId()] = $this->_recordsList[$id]->getValuesAsArray(); + } + } + } + } + + function &getIterator() + { + return $this->iterator; + } + + /* implementa gli stessi metodi dell'iterator */ + function rewind() + { + assert(!is_null($this->iterator)); + $this->iterator->rewind(); + $this->current(); + } + + function valid() + { + assert(!is_null($this->iterator)); + return $this->iterator->valid(); + } + + function &first() + { + assert(!is_null($this->iterator)); + $this->iterator->first(); + $this->current(); + return $this->record; + } + + function key() + { + assert(!is_null($this->iterator)); + return $this->iterator->key(); + } + + function next() + { + assert(!is_null($this->iterator)); + + $this->iterator->next(); + if ($this->iterator->hasMore()) + { + $this->current(); + } + } + + function count() + { + assert(!is_null($this->iterator)); + return $this->iterator->count(); + } + + function hasMore() + { + assert(!is_null($this->iterator)); + return $this->iterator->hasMore(); + } + + function &current() + { + assert(!is_null($this->iterator)); + $this->record = &$this->iterator->current(); + $this->_recordsList[$this->record->getId()] = &$this->record; + $this->_backUpValues[$this->record->getId()] = $this->record->getValuesAsArray(); + $this->_bindRecordFields(); + return $this->record; + } + + function _reset() + { + $this->record = NULL; + $this->iterator = NULL; + $this->_recordsList = array(); + $this->_backUpValues = array(); + } + + function collectFieldsValues( $getVirtualField, $encode ) + { + $output = array(); + while ( $this->hasMore() ) + { + $output[] = $this->record->_collectFieldsValues(false, $getVirtualField, $encode); + $this->next(); + } + return $output; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/RelationHasOne.php b/src/core/classes/org/glizy/dataAccess/RelationHasOne.php new file mode 100755 index 0000000..a1654d9 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/RelationHasOne.php @@ -0,0 +1,116 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class org_glizy_dataAccess_RelationHasOne */ +class org_glizy_dataAccess_RelationHasOne extends org_glizy_dataAccess_Relation +{ + + function __construct(&$parent, $options) + { + parent::__construct($parent, $options); + assert(isset($options['field'])); + $this->_key = $options['field']; + $this->_destinationKey = isset($options['destinationField']) ? $options['destinationField'] : NULL; + } + + function build($params=array()) + { + $this->record = org_glizy_ObjectFactory::createModel($this->_className); + $this->record->setProcessRelations(false); + $this->_getDestinationField(); + $this->record->{$this->_destinationKey} = $this->_parent->{$this->_key}; + + if (count($params)) + { + $this->record->loadFromArray($params); + } + $this->record->find(); + $this->current(); + } + + function create($params) + { + $this->_reset(); + $this->record = & org_glizy_ObjectFactory::createModel($this->_className); + $this->record->setProcessRelations(false); + $this->_getDestinationField(); + + if (count($params)) + { + $this->record->loadFromArray($params); + } + + $this->_bindRecordFields(); + } + + function bind(&$object) + { + if (get_class($object)!=$this->_className) + { + // TODO + // visualizzare errore + } + + $this->_reset(); + $this->record = &$object; + $this->record->setProcessRelations(false); + $this->_getDestinationField(); + $this->_bindRecordFields(); + } + + function preSave() + { + $canSave = false; + + $currentValues = $this->record->getValuesAsArray(); + foreach ($currentValues as $k=>$v) + { + if (!array_key_exists($k, $this->_backUpValues) || $this->_backUpValues[$k]!=$v) + { + $canSave = true; + break; + } + } + if ($canSave) + { + $this->record->save(); + $this->_backUpValues = $this->record->getValuesAsArray(); + $this->_parent->{$this->_key} = $this->record->{$this->_destinationKey}; + } + } + + function _getDestinationField() + { + if (is_null($this->_destinationKey)) + { + $this->_destinationKey = $this->record->getPrimaryKey(); + assert(!is_null($this->_destinationKey)); + } + } + + function &current() + { + $this->_backUpValues = $this->record->getValuesAsArray(); + $this->_bindRecordFields(); + return $this->record; + } + + function _reset() + { + $this->_backUpValues = array(); + } + + function collectFieldsValues( $getVirtualField, $encode ) + { + if (is_object($this->record)) + { + return $this->record->_collectFieldsValues(false, $getVirtualField, $encode); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/RelationJoinTable.php b/src/core/classes/org/glizy/dataAccess/RelationJoinTable.php new file mode 100755 index 0000000..15d2a05 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/RelationJoinTable.php @@ -0,0 +1,131 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +/** class org_glizy_dataAccess_RelationJoinTable */ +class org_glizy_dataAccess_RelationJoinTable extends org_glizy_dataAccess_RelationMany2Many +{ + var $_objectName = ''; + var $_objectField = 'join_objectName'; + var $_ordered = true; + var $_newRecord; + + function __construct(&$parent, $options) + { + parent::__construct($parent, $options); + $this->_objectName = $options['objectName']; + } + + function build($params=array()) + { + $this->record = org_glizy_ObjectFactory::createModel($this->_className); + $this->iterator = NULL; + + $parentId = $this->_parent->getId(); + if (!is_null($parentId)) + { + $this->_newRecord = empty( $parentId ); + $this->iterator = &$this->record->loadQuery('All', array('filters' => array($this->_key => $parentId, $this->_objectField => array( '=', $this->_objectName ) ), + 'order' => $this->record->getPrimaryKey() ) ); + + if (is_null($this->_parent->{$this->_bindTo}) ) + { + $this->record = NULL; + $values = array(); + while($this->iterator->hasMore()) + { + $this->record = &$this->iterator->current(); + $values[] = $this->record->{$this->_destinationKey}; + $this->iterator->next(); + } + $this->_parent->{$this->_bindTo} = implode(',', $values); + } + else + { + $this->record = &$this->iterator->current(); + } + + if ($this->iterator->count()) + { + $this->iterator->first(); + } + } + } + + function postSave() + { + $values = $this->_parent->{$this->_bindTo}; + if (is_null($values)) return; + $values = is_string($values) ? + !empty($values) ? explode(',', $values) : array() + : + $values; + if ( !is_array( $values ) ) + { + $values = array( $values ); + } + if (is_null($this->record->{$this->_destinationKey}) + || $this->record->{$this->_destinationKey} == $this->record->getFieldDefaultValue($this->_destinationKey) + || is_null($this->iterator)) + { + // nuovo record + $parentId = $this->_parent->getId(); + foreach ($values as $v) + { + $this->record = & org_glizy_ObjectFactory::createModel($this->_className); + $this->record->{$this->_key} = $this->_parent->getId(); + $this->record->{$this->_destinationKey} = $v; + $this->record->{$this->_objectField} = $this->_objectName; + $newId = $this->record->save(); + } + } + else + { + $recordIds = array(); + while($this->iterator->hasMore()) + { + $ar = &$this->iterator->current(); + + if ( $this->_ordered ) + { + if ( !$this->_newRecord ) + { + $ar->delete(); + } + } + else + { + if (!in_array($ar->{$this->_destinationKey}, $values)) + { + $ar->delete(); + } + else + { + $recordIds[] = $ar->{$this->_destinationKey}; + } + } + $this->iterator->next(); + } + if (count($values)) + { + foreach ($values as $v) + { + if (!in_array($v, $recordIds)) + { + $this->record = & org_glizy_ObjectFactory::createModel($this->_className); + $this->record->{$this->_key} = $this->_parent->getId(); + $this->record->{$this->_destinationKey} = $v; + $this->record->{$this->_objectField} = $this->_objectName; + $newId = $this->record->save(); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/RelationMany2Many.php b/src/core/classes/org/glizy/dataAccess/RelationMany2Many.php new file mode 100755 index 0000000..311e472 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/RelationMany2Many.php @@ -0,0 +1,228 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +/** class org_glizy_dataAccess_RelationMany2Many */ +class org_glizy_dataAccess_RelationMany2Many extends org_glizy_dataAccess_Relation +{ + var $recordSet = NULL; + var $iterator = NULL; + var $_bindTo = ''; + + function __construct(&$parent, $options) + { + parent::__construct($parent, $options); + assert(isset($options['field'])); + $this->_key = $options['field']; + assert(!is_null($this->_destinationKey)); + $this->_destinationKey = $options['destinationField']; + $this->_bindTo = $options['bindTo']; + } + + function build($params=array()) + { + $this->record = org_glizy_ObjectFactory::createModel($this->_className); + $this->iterator = NULL; + + $parentId = $this->_parent->getId(); + if (!is_null($parentId)) + { + $this->iterator = &$this->record->loadQuery('All', array('filters' => array($this->_key => $parentId))); + + // TODO + // 28 mag 2006 + // controllo se il campo linkato è già riempito + // in questo caso non carico i valori + // ho fatto in questo modo perché se si sava un valore + // proveniente da un post con i valori riempiti + // questi venivano cancellati + // la soluzione non è l'ideale + // c'è da trovare un modo migliore per risolvere il problema + if (is_null($this->_parent->{$this->_bindTo}) ) + { + $this->record = NULL; + $values = array(); + while($this->iterator->hasMore()) + { + $this->record = &$this->iterator->current(); + $values[] = $this->record->{$this->_destinationKey}; + $this->iterator->next(); + } + $this->rewind(); + $this->_parent->{$this->_bindTo} = implode(',', $values); + } + else + { + $this->record = &$this->iterator->current(); + } + + if ($this->iterator->count()) + { + $this->iterator->first(); + } + } + } + + function create($params) + { + $this->_reset(); + $this->record = & org_glizy_ObjectFactory::createModel($this->_className); + $this->record->setProcessRelations(false); + + if (count($params)) + { + $this->record->loadFromArray($params); + } + $this->_bindRecordFields(); + } + + function bind(&$object) + { + if (get_class($object)!=$this->_className) + { + // TODO + // visualizzare errore + } + + $this->_reset(); + $this->record = &$object; + $this->record->{$this->_destinationKey} = $this->_parent->{$this->_key}; + //$this->_recordsList[$this->record->getId()] = &$this->record; + //$this->_backUpValues[$this->record->getId()] = $this->record->getValuesAsArray(); + $this->record->setProcessRelations(false); + $this->_bindRecordFields(); + } + + function postSave() + { + $values = $this->_parent->{$this->_bindTo}; + if (is_null($values)) return; + $values = is_string($values) ? + !empty($values) ? explode(',', $values) : array() + : + $values; + + if (is_null($this->record->{$this->_destinationKey}) + || $this->record->{$this->_destinationKey} == $this->record->getFieldDefaultValue($this->_destinationKey) + || is_null($this->iterator)) + { + // nuovo record + $parentId = $this->_parent->getId(); + foreach ($values as $v) + { + $this->record = & org_glizy_ObjectFactory::createModel($this->_className); + $this->record->{$this->_key} = $this->_parent->getId(); + $this->record->{$this->_destinationKey} = $v; + $newId = $this->record->save(); + } + } + else + { + $recordIds = array(); + while($this->iterator->hasMore()) + { + $ar = &$this->iterator->current(); + if (!in_array($ar->{$this->_destinationKey}, $values)) + { + $ar->delete(); + } + else + { + $recordIds[] = $ar->{$this->_destinationKey}; + } + $this->iterator->next(); + } + if (count($values)) + { + foreach ($values as $v) + { + if (!in_array($v, $recordIds)) + { + $this->record = & org_glizy_ObjectFactory::createModel($this->_className); + $this->record->{$this->_key} = $this->_parent->getId(); + $this->record->{$this->_destinationKey} = $v; + $newId = $this->record->save(); + } + } + } + } + } + + function &getIterator() + { + return $this->iterator; + } + + /* implementa gli stessi metodi dell'iterator */ + function rewind() + { + assert(!is_null($this->iterator)); + $this->iterator->rewind(); + $this->current(); + } + + function valid() + { + assert(!is_null($this->iterator)); + return $this->iterator->valid(); + } + + function &first() + { + assert(!is_null($this->iterator)); + $this->iterator->first(); + $this->current(); + return $this->record; + } + + function key() + { + assert(!is_null($this->iterator)); + return $this->iterator->key(); + } + + function next() + { + assert(!is_null($this->iterator)); + + $this->iterator->next(); + if ($this->iterator->hasMore()) + { + $this->current(); + } + } + + function count() + { + assert(!is_null($this->iterator)); + return $this->iterator->count(); + } + + function hasMore() + { + assert(!is_null($this->iterator)); + return $this->iterator->hasMore(); + } + + function &current() + { + assert(!is_null($this->iterator)); + $this->record = &$this->iterator->current(); + $this->_bindRecordFields(); + return $this->record; + } + + function _reset() + { + $this->record = NULL; + $this->iterator = NULL; + //$this->_recordsList = array(); + //$this->_backUpValues = array(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/cache/ActiveRecord.php b/src/core/classes/org/glizy/dataAccess/cache/ActiveRecord.php new file mode 100755 index 0000000..28280a4 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/cache/ActiveRecord.php @@ -0,0 +1,29 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_dataAccess_cache_ActiveRecord extends GlizyObject +{ + private $data = NULL; + + function __construct($data) + { + $this->data = $data; + } + + function getValuesAsArray() + { + return $this->data; + } + + public function __get($name) + { + return @$this->data[$name]; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/cache/Iterator.php b/src/core/classes/org/glizy/dataAccess/cache/Iterator.php new file mode 100755 index 0000000..ca33db1 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/cache/Iterator.php @@ -0,0 +1,77 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_dataAccess_cache_Iterator extends GlizyObject implements Iterator +{ + private $data = NULL; + private $pos = 0; + + function __construct($data) + { + $this->data = $data; + } + + function rewind() + { + $this->pos = 0; + } + + function valid() + { + return count($this->data) > $this->pos; + } + + function &first() + { + $this->rewind(); + return $this->current(); + } + + function key() + { + return $this->pos; + } + + function current() + { + return new org_glizy_dataAccess_cache_ActiveRecord($this->data[$this->pos]); + } + + function next() + { + $this->pos++; + } + + function count() + { + return count($this->data); + } + + + function hasMore() + { + return count($this->data) > $this->pos; + } + + function recordPos() + { + return $this->pos; + } + + function getData() + { + return $this->data; + } + + function setData($data) + { + $this->pos = 0; + $this->data = $data; + } +} diff --git a/src/core/classes/org/glizy/dataAccess/cache/Query.php b/src/core/classes/org/glizy/dataAccess/cache/Query.php new file mode 100755 index 0000000..10423c2 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/cache/Query.php @@ -0,0 +1,74 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_dataAccess_cache_Query extends GlizyObject +{ + private $_cacheObj; + private $model; + private $group; + + + function __construct($model, $lifeTime=null, $cacheFolder=null) + { + $cacheFolder = $cacheFolder ? $cacheFolder : org_glizy_Paths::getRealPath('CACHE_CODE'); + $this->model = $model; + $this->group = $cacheFolder.$model; + $options = array( + 'cacheDir' => $cacheFolder, + 'lifeTime' => !$lifeTime ? org_glizy_Config::get('CACHE_CODE') : $lifeTime, + 'readControlType' => '', + 'fileExtension' => '.php' + ); + + $this->_cacheObj = &org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFile', $options); + } + + public function get($queryName, $options=array()) + { + $fileName = $queryName.serialize($options); + return $this->getWithName($queryName.serialize($options), $queryName, $options ); + } + + public function getWithName($fileName, $queryName, $options=array()) + { + $data = $this->_cacheObj->get($fileName, $this->group); + if ($data===false) { + $data = array(); + $it = org_glizy_ObjectFactory::createModelIterator($this->model, $queryName, $options); + foreach ($it as $ar) { + $data[] = $ar->getValuesAsArray(); + } + $this->_cacheObj->save($this->serialize($data), $fileName, $this->group); + } else { + $data = $this->unserialize($data); + } + + return new org_glizy_dataAccess_cache_Iterator($data); + } + + public function remove($queryName, $args=array()) + { + $this->removeWithName($queryName.serialize($args)); + } + + public function removeWithName($fileName) + { + $this->_cacheObj->remove($fileName, $this->group); + } + + private function serialize($data) + { + return serialize($data); + } + + private function unserialize($data) + { + return unserialize($data); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccess/cache/QueryRedis.php b/src/core/classes/org/glizy/dataAccess/cache/QueryRedis.php new file mode 100755 index 0000000..5c3e900 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/cache/QueryRedis.php @@ -0,0 +1,112 @@ +<?php + + /** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + class org_glizy_dataAccess_cache_QueryRedis extends GlizyObject { + + private $model; + private $lifeTime; + /** @var \Predis\Client $redis */ + protected $redis; + + /** + * @param $model + * @param $lifeTime + * @param null $cacheFolder + */ + function __construct($model, $lifeTime = -1, $cacheFolder = null) { + $this->model = $model; + $this->lifeTime = $lifeTime; + $this->redis = org_glizy_redis_Client::getConnection(); + } + + /** + * @param $queryName + * @param array $options + * + * @return org_glizy_dataAccess_cache_Iterator + */ + public function get($queryName, $options = array()) { + return $this->getWithName($queryName . serialize($options), $queryName, $options); + } + + /** + * @param $key + * @param $queryName + * @param array $options + * + * @return org_glizy_dataAccess_cache_Iterator + */ + public function getWithName($key, $queryName, $options = array()) { + $data = $this->redis->get($key); + + if ($data == null) { + $data = array(); + /** @var org_glizy_dataAccess_cache_Iterator $it */ + $it = org_glizy_ObjectFactory::createModelIterator($this->model, $queryName, $options); + /** @var org_glizy_dataAccess_cache_ActiveRecord $ar */ + foreach ($it as $ar) { + $data[] = $ar->getValuesAsArray(); + } + $this->redis->set($key, $this->serialize($data)); + } else { + $data = $this->unserialize($data); + } + + if ($this->lifeTime != -1) { + $this->redis->expire($key, $this->lifeTime); + } + + return new org_glizy_dataAccess_cache_Iterator($data); + } + + /** + * @param $queryName + * @param array $args + * + * @return int + */ + public function remove($queryName, $args = array()) { + return $this->removeWithName($queryName . serialize($args)); + } + + /** + * @param $key + * + * @return int + */ + public function removeWithName($key) { + $result = 0; + // se key ha l'asterisco, cancella tutte le chiavi che iniziano per il prefisso in $key + if (strpos($key, '*') !== false) { + foreach ($this->redis->keys($key) as $k) { + $result += $this->redis->del($k); + } + } else { + $result += $this->redis->del($key); + } + return $result; + } + + /** + * @param $data + * + * @return string + */ + private function serialize($data) { + return serialize($data); + } + + /** + * @param $data + * + * @return mixed + */ + private function unserialize($data) { + return unserialize($data); + } + } diff --git a/src/core/classes/org/glizy/dataAccess/driver/Connection.php b/src/core/classes/org/glizy/dataAccess/driver/Connection.php new file mode 100755 index 0000000..486ad41 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccess/driver/Connection.php @@ -0,0 +1,536 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class Connection + */ +class Connection extends PDO +{ + public $debug = false; + private $_errorCode = 0; + private $_errorInfo = ""; + private $_dsn; + + /** + * @param $dsn + * @param $username + * @param $password + * @param array $driver_options + */ + function __construct($dsn, $username, $password, $driver_options = array() ) + { + $this->_dsn = $dsn; + parent::__construct($dsn, $username, $password, $driver_options); + } + + /** + * @param $sql + * @param array $param + * @param bool $silent + * + * @return bool|DBResultSet + */ + function execute( $sql, $param = array(), $silent = false ) + { + $time_start = 0; + if ( $this->debug ) $time_start = microtime(); + + if ( strpos( $this->_dsn, 'sqlite:' ) !== false ) + { + preg_match_all( '/(CONCAT\(([^\)]*)\))/', $sql, $match ); + if ( count( $match[ 0 ] ) ) + { + $sql = str_replace( $match[ 0 ], str_replace( ',', ' || ', $match[ 2 ]), $sql ); + } + } + + // controlla se sono passati dei parametri e se questi sono un array ( es. per clausola IN) + if ( count( $param ) ) + { + foreach ($param as $k => $v ) + { + if ( is_array( $v ) && $v[ 1 ] == 'EXPRESSION' ) + { + $sql = str_replace( $k, $v[ 0 ], $sql ); + unset( $param[ $k ] ); + } else if (preg_match('/IN\s*?\(\s*?'.$k.'\s*?\)/i', $sql)) { + $sql = str_replace( $k, $v, $sql ); + unset( $param[ $k ] ); + } + } + + } + + + $sth = $this->prepare( $sql ); + if ( count( $param ) ) + { + if ( strpos( $sql, '?' ) !== false ) + { + $r = $sth->execute( $param ); + } + else + { + foreach ($param as $k => $v ) + { + if ( is_array( $v ) ) + { + $sth->bindValue( $k, $v[ 0 ], $v[ 1 ] ); + } + else + { + $sth->bindValue( $k, $v ); + } + } + + $r = $sth->execute(); + } + } + else + { + $r = $sth->execute(); + } + + $this->_errorCode = $sth->errorCode(); + $this->_errorInfo = $sth->errorInfo(); + + + if ( $this->debug ) + { + $time_end = microtime(); + $time = $time_end - $time_start; + echo "[time: ".$time.", ".( $r ? "records: ".$sth->rowCount() : "" )."] "; + $sql_br = nl2br($sql); + if ( count( $param ) ) + { + if ( strpos( $sql_br, '?' ) !== false ) + { + $sql_br = vsprintf( str_replace( array( "%", "?" ), array( "%%", "'%s'" ), $sql_br ), $param ); + } + else + { + foreach ($param as $k => $v ) + { + $sql_br = str_replace( $k, is_array( $v ) ? $v[ 0 ] : '"'.$v.'"', $sql_br ); + } + } + } + + echo $sql_br; + echo "<br />\n\r"; + } + + if ( !$r ) + { + if ( !$this->debug ) { + // $sql = nl2br($sql); + if ( count( $param ) ) + { + if ( strpos( $sql, '?' ) !== false ) + { + $sql = vsprintf( str_replace( array( "%", "?" ), array( "%%", "'%s'" ), $sql ), $param ); + } + else + { + foreach ($param as $k => $v ) + { + $sql = str_replace( $k, is_array( $v ) ? $v[ 0 ] : '"'.$v.'"', $sql ); + } + } + } + } + + $eventInfo = array('type' => GLZ_LOG_EVENT, + 'data' => array( + 'level' => GLZ_LOG_ERROR, + 'group' => 'glizy.sql', + 'message' => array('sql' => $sql, 'errorCode' => $this->_errorCode, 'errorInfo' => $this->_errorInfo) + )); + $evt = org_glizy_ObjectFactory::createObject( 'org.glizy.events.Event', $this, $eventInfo ); + org_glizy_events_EventDispatcher::dispatchEvent( $evt ); + + if ( !$silent ) echo $this->ErrorMsg()."<br />\n\r"; + return false; + } + return new DBResultSet( $sth, $this, strpos( $this->_dsn, 'sqlite:' ) !== false ); + } + + + /** + * @param $str + * @param $option + * + * @return string + */ + function qstr( $str, $option ) + { + return '\''.addslashes( $str ).'\''; + } + + /** + * @param $str + * + * @return array|mixed + */ + function escape( $str ) + { + if(is_array($str)) + return array_map(__METHOD__, $str); + + if(!empty($str) && is_string($str)) { + return str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $str); + } + + return $str; + } + + /** + * @return ConnectionQueueExecute + */ + function getQueueExecute() + { + return new ConnectionQueueExecute( $this ); + } + + function SelectDB( $n ) + { + } + + /** + * @param $sql + * @param $limitLength + * @param $limitStart + * @param array $params + * + * @return bool|DBResultSet + */ + function selectLimit( $sql, $limitLength, $limitStart, $params = array() ) + { + return $this->execute( $sql.' LIMIT '.$limitStart.', '.$limitLength, $params ); + } + + /** + * @return string + */ + function Insert_ID() + { + return $this->lastInsertId(); + } + + /** + * @return bool|int + */ + function ErrorNo() + { + if ( $this->_errorCode != 0 ) + { + return $this->_errorCode ; + } + else + { + return false; + } + } + + function ErrorMsg() + { + $info = $this->_errorInfo; + return $info[2]; + } + + /** + * @param $table + * @param $param + * + * @return array|string + */ + function MetaColumns( $table, $param ) + { + if ( strpos( $this->_dsn, 'sqlite:' ) !== false ) + { + $sql = 'PRAGMA table_info ('.$table.')'; + $stmt = $this->prepare($sql); + + try + { + $meta = array(); + if( $stmt->execute() ) + { + $raw_column_data = $stmt->fetchAll(); + + foreach($raw_column_data as $array) + { + $dbField = new DBfield; + $dbField->name = $array['name']; + $dbField->type = $array['type']; + $dbField->max_length = -1; + $dbField->not_null = $array['notnull'] == '1'; + $dbField->has_default = $array['dflt_value'] != null; + $dbField->default_value = $array['dflt_value']; + $dbField->primary_key = $array['pk'] == '1'; + $dbField->auto_increment = false; + $meta[ $array['name'] ] = $dbField; + } + } + + return $meta; + } catch (Exception $e){ + return $e->getMessage(); //return exception + } + } + else + { + $sql = 'SHOW COLUMNS FROM ' . $table; + $stmt = $this->prepare($sql); + $meta = array(); + + if( $stmt->execute() ) + { + + $raw_column_data = $stmt->fetchAll(); + + foreach($raw_column_data as $array) + { + $dbField = new DBfield; + $dbField->name = $array['Field']; + if ( preg_match('/^enum/i', $array['Type'] ) ) + { + $dbField->type = $array['Type']; + + } + else + { + $dbField->type = preg_replace( '/([^\(]*).*/', '$1', $array['Type'] ); + } + $dbField->max_length = preg_replace( '/([^\(]*)\((\d*)\).*/', '$2', $array['Type'] ); + if ( $dbField->max_length == $array['Type'] ) $dbField->max_length = -1; + $dbField->not_null = $array['Null'] == 'NO'; + $dbField->has_default = $array['Default'] != ''; + $dbField->default_value = $array['Default']; + $dbField->primary_key = $array['Key'] == 'PRI'; + $dbField->auto_increment = $array['Extra'] == 'auto_increment'; + $meta[ $array['Field'] ] = $dbField; + } + } + + return $meta; + } + } +} + +/** + * Class DBResultSet + */ +class DBResultSet +{ + public $fields; + public $_currentRow; + public $EOF; + /** @var $sth PDOStatement */ + private $sth; + private $_count; + private $_sqlite; + private $_conn; + private $buffer; + private $pos; + + /** + * @param $sth + * @param $conn + * @param $sqlite + */ + function __construct( $sth, $conn, $sqlite ) + { + $this->_conn = $conn; + $this->_sqlite = $sqlite; + $this->sth = $sth; + $this->buffer = array(); + $this->pos = 0; + $this->fetch(); + } + + function MoveFirst() + { + $this->pos = 0; + $this->fetch(); + } + + + function MoveNext() + { + $this->fetch(); + } + + /** + * @return mixed + */ + function RecordCount() + { + if ( $this->_sqlite ) + { + if ( is_null( $this->_count ) ) + { + $sql = 'select count(*) from ( '.$this->sth->queryString.' )'; + /** @var $sth PDOStatement */ + $sth = $this->_conn->prepare( $sql ); + $sth->execute(); + $row = $sth->fetch(PDO::FETCH_NUM); + $this->_count = $row[ 0 ]; + } + return $this->_count; + } + else + { + return $this->sth->rowCount(); + } + } + + private function fetch() + { + if ( isset( $this->buffer[ $this->pos ] ) ) + { + $this->fields = $this->buffer[ $this->pos ]; + $this->_currentRow = $this->fields; + $this->EOF = count( $this->buffer ) === $this->pos; + } + else + { + $this->fields = $this->sth->fetch(PDO::FETCH_ASSOC); + $this->_currentRow = $this->fields; + $this->EOF = $this->_currentRow === false; + if ( !$this->EOF ) + { + $this->buffer[ $this->pos ] = $this->fields; + } + } + + $this->pos++; + } + + /** + * @return int + */ + public function recordPos() + { + return $this->pos; + } +} + +/** + * Class DBfield + */ +class DBfield +{ + public $name; + public $max_length; + public $type; + public $not_null; + public $has_default; + public $default_value; + public $scale; + public $primary_key; + public $auto_increment; + public $binary = false; + public $enums; +} + +/** + * Class ConnectionQueueExecute + */ +class ConnectionQueueExecute +{ + public $queryLength = 50000; + /** @var Connection $_conn */ + private $_conn; + private $queue = array(); + private $startSql; + public $decodeFunction = null; + + /** + * @param $conn + */ + function __construct( $conn ) + { + $this->_conn = $conn; + } + + /** + * @param $sql + */ + public function init( $sql ) + { + $this->startSql = $sql.' '; + } + + /** + * @param $values + */ + public function push( $values ) + { + $this->queue[] = $values; + } + + /** + * @return bool + */ + public function execute() + { + if ( !count( $this->queue ) ) return true; + $sql = ''; + $part = ''; + $sqlLength = 0; + $i = 0; + $result = true; + while ( true ) + { + if ( $sql == '' ) + { + $i = $part == '' ? 0 : 1; + $sql = $this->startSql.' '.$part; + $sqlLength = strlen( $sql ); + } + if ( !count( $this->queue ) ) break; + + $part = array_shift( $this->queue ); + $partLenght = strlen( $part ); + if ( $partLenght + $sqlLength < $this->queryLength ) + { + $sql .= ( $i > 0 ? ', ' : '' ).$part; + $sqlLength += $partLenght + 2; + } + else + { + if (!$this->fireSql( $sql )) { + $result = false; + } + $sql = ''; + } + $i++; + } + if (!$this->fireSql( $sql )) { + $result = false; + } + return $result; + } + + /** + * @param $sql + * + * @return bool|DBResultSet + */ + private function fireSql( $sql ) + { + $sql .= ';'; + if ( !is_null( $this->decodeFunction ) ) + { + $sql = call_user_func( $this->decodeFunction, $sql ); + } + return $this->_conn->execute( $sql ); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/AbstractRecordIterator.php b/src/core/classes/org/glizy/dataAccessDoctrine/AbstractRecordIterator.php new file mode 100755 index 0000000..1124fa8 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/AbstractRecordIterator.php @@ -0,0 +1,454 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +abstract class org_glizy_dataAccessDoctrine_AbstractRecordIterator extends GlizyObject implements Iterator +{ + protected $ar; + protected $qb; + protected $pos = 0; + protected $statement = NULL; + protected $data = NULL; + protected $count = NULL; + protected $EOF = false; + protected $lastQuery; + protected $querySqlToExec; + protected $lastParams; + protected $hasSelect; + protected $hasLimit; + protected $siteSet; + protected $expr; + + function __construct($ar) + { + $this->ar = $ar; + $this->expr = $ar->getConnection()->getExpressionBuilder(); + $this->resetQuery(); + } + + public function getArType() + { + return $this->ar->getBaseClassName(); + } + + // serve per cambiare un parametro di un campo a runtime + public function setFieldParam($fieldName, $param, $value) + { + $this->ar->setFieldParam($fieldName, $param, $value); + } + + protected function resetQuery() { + $this->siteSet = false; + } + + public function expr() { + return $this->expr; + } + + public function qb() + { + return $this->qb; + } + + public function load($query, $params=null) + { + $driverName = $this->ar->getDriverName(); + + if (method_exists($this->ar, 'query_'.$query)) { + // NOTE: verificare se i parametri nel caso di query di tipo function + // vengono passati nell'array params o come array diretto + // così da pulire questa parte di codice + $params = is_array($params) ? + (isset($params['params']) ? $params['params'] : $params) + : array($params); + $params['iterator'] = $this; + org_glizy_helpers_PhpScript::callMethodWithParams($this->ar, 'query_'.$query, $params); + unset($params['iterator']); + } else if (method_exists($this->ar, 'querysql_'.$driverName.'_'.$query)) { + $this->querySqlToExec = org_glizy_helpers_PhpScript::callMethodWithParams($this->ar, 'querysql_'.$driverName.'_'.$query); + } else if (method_exists($this->ar, 'querysql_'.$query)) { + $this->querySqlToExec = org_glizy_helpers_PhpScript::callMethodWithParams($this->ar, 'querysql_'.$query); + } + + $this->lastQuery = $query; + $this->lastParams = $params; + + return $this; + } + + public function setSqlQuery($query, $params=array()) + { + $this->querySqlToExec = $query; + $this->lastQuery = $query; + $this->lastParams = $params; + } + + abstract protected function processUnionFields($fieldName, $value); + + public function setFilters($filters) + { + if ($this->querySqlToExec) { + $filtersSql = array(); + foreach ($filters as $fieldName => $value) { + if ($fieldName == '__OR__') { + $this->setOrFilters($value); + continue; + } +// TODO implementare il quoting per postgress + if (is_array($value)) { + if (isset($value['value']) && !is_array($value['value'])) { + $filtersSql[] = (isset($value['field']) ? $value['field'] : $fieldName).$value['condition'].'"'.$value['value'].'"'; + } else { + foreach ($value as $v) { + $filtersSql[] = $v['field'].$v['condition'].'"'.$v['value'].'"'; + } + } + } else { + $filtersSql[] = $fieldName.' like "%'.$value.'%"'; + } + } + if (count($filtersSql)) { + $this->querySqlToExec['filters'][] = '('.implode(' AND ', $filtersSql).')'; + } + + return $this; + } + + foreach ($filters as $fieldName => $value) { + if ($fieldName == '__OR__') { + $this->setOrFilters($value); + continue; + } + $newValue = $this->processUnionFields($fieldName, $value); + + if ($newValue === '' && is_int($fieldName)) { + $this->qb->andWhere($value); + continue; + } else if ($newValue === '') { + continue; + } + + $value = $newValue; + + if (is_array($value)) { + if (isset($value['value']) && !is_array($value['value'])) { + $this->where((isset($value['field']) ? $value['field'] : $fieldName), $value['value'], $value['condition']); + } else { + foreach ($value as $v) { + $this->where($v['field'], $v['value'], $v['condition']); + } + } + } else { +// TODO perché fa sempre il like? dovrebbe fare la codizione in base al tipo di campo + $this->where($fieldName, '%'.$value.'%', 'LIKE'); + } + } + + return $this; + } + + public function setOrFilters($filters) + { + if ($this->querySqlToExec) { +// rimuovere duplicato con la parte sopra + $filtersSql = array(); + foreach ($filters as $fieldName => $value) { +// TODO implementare il quoting per postgress + if (is_array($value)) { + if (isset($value['value']) && !is_array($value['value'])) { + $filtersSql[] = (isset($value['field']) ? $value['field'] : $fieldName).$value['condition'].'"'.$value['value'].'"'; + } else { + foreach ($value as $v) { + $filtersSql[] = $v['field'].$v['condition'].'"'.$v['value'].'"'; + } + } + } else { + $filtersSql[] = $fieldName.' like "%'.$value.'%"'; + } + } + + if (count($filtersSql)) { + $this->querySqlToExec['filters'][] = '('.implode(' OR ', $filtersSql).')'; + } + return $this; + } + + + $or = $this->expr->orX(); + $added = false; + foreach ($filters as $fieldName => $value) { + $value = $this->processUnionFields($fieldName, $value); + + if ($value == '' /*|| (is_array($value) && $value['value'] == '') || !$this->ar->fieldExists($fieldName)*/) { + continue; + } + $added = true; + if (is_array($value)) { + if (isset($value['value']) && !is_array($value['value'])) { + $this->where((isset($value['field']) ? $value['field'] : $fieldName), $value['value'], $value['condition'], $or); + } else { + foreach ($value as $v) { + $this->where($v['field'], $v['value'], $v['condition'], $or); + } + } + } + else { + $this->where($fieldName, '%'.$value.'%', 'LIKE', $or); + } + } + if ($added) { + $this->qb->andWhere($or); + } + return $this; + } + + public function setOrderBy($order) { + if (is_string($order)) { + $this->orderBy($order); + } else { + foreach ($order as $fieldName => $direction) { + $this->orderBy($fieldName, $direction); + } + } + + return $this; + } + + public function groupBy($field) + { + $this->qb->groupBy($field); + return $this; + } + + public function select($select) + { + $selects = is_array($select) ? $select : func_get_args(); + $this->qb->select($selects); + $this->hasSelect = true; + return $this; + } + + public function addSelect($select = null) + { + $selects = is_array($select) ? $select : func_get_args(); + $this->qb->addSelect($selects); + $this->hasSelect = true; + return $this; + } + + public function join($fromAlias, $join, $alias, $condition = null) + { + $this->qb->join($fromAlias, $join, $alias, $condition); + return $this; + } + + public function leftJoin($fromAlias, $join, $alias, $condition = null) + { + $this->qb->leftJoin($fromAlias, $join, $alias, $condition); + return $this; + } + + public function rightJoin($fromAlias, $join, $alias, $condition = null) + { + $this->qb->rightJoin($fromAlias, $join, $alias, $condition); + return $this; + } + + public function where($fieldName, $value = null, $condition = '=', $composite = null) + { + $driverName = $this->ar->getDriverName(); + + if ($driverName == 'mysql' && strtoupper($condition) == 'ILIKE') { + $condition = 'LIKE'; + } + + if (strpos($fieldName, 'MATCH')!==false) { + $this->qb->andWhere($fieldName); + return $this; + } + + // se $value è null allora $fieldName contiene un'espressione del tipo 'nomecampo1 = valore1' + if (is_null($value)) { + list($fieldName, $condition, $value) = array_map('trim', explode(' ', $fieldName)); + } + + $value = $this->ar->convertIfDateType($fieldName, $value); + + return $this->whereCondition($fieldName, $value, $condition, $composite); + } + + abstract protected function whereCondition($fieldName, $value, $condition = '=', $composite = null); + + public function whereSiteIs($value) + { + $this->qb->andWhere($this->expr->eq($this->ar->getSiteField(), ':site')) + ->setParameter(':site', $value); + $this->siteSet = true; + return $this; + } + + public function disableSiteConditionIs() + { + $this->siteSet = true; + return $this; + } + + abstract public function orderBy($fieldName, $order = 'ASC'); + + public function limit($offset, $limit = -1, $performCount=true) + { + if (is_array($offset)) { + if (!isset($offset['start'])) { + list($offset, $limit) = array_values($offset); + } else { + $limit = $offset['pageLength']; + $offset = $offset['start']; + } + } + $this->qb->setFirstResult($offset); + $this->qb->setMaxResults($limit); + $this->hasLimit = $performCount; + return $this; + } + + public function setParameter($param, $value) + { + $this->qb->setParameter($param, $value); + return $this; + } + + public function exec() + { + if ($this->querySqlToExec) { + $this->execSql($this->querySqlToExec, $this->lastParams); + } + else { + if (!$this->siteSet && $this->ar->getSiteField()) { + $this->whereSiteIs($this->ar->getSiteid()); + } + + $this->lastQuery = $this->qb; + $this->statement = $this->qb->execute(); + + // TODO la count rallenta le query + // renderla opzionale + if ($this->hasLimit) { + $qb = clone $this->qb; + + // elimina la parte select e orderBy perchè non servono per il conteggio + $qb->resetQueryParts(array('select', 'orderBy')); + + // resetta i limiti della query + $qb->setFirstResult(null); + $qb->setMaxResults(null); + + // aggiunge il conteggio alla query + $qb->select('COUNT(*) AS tot'); + $stmt = $qb->execute(); + $row = $stmt->fetch(); + $this->count = $row['tot']; + } + } + + $this->resetQuery(); + + return $this; + } + + abstract public function execSql($sql, $options=array()); + + public function next() + { + $this->fetch(); + } + + public function rewind() + { + if ($this->pos == 0) { + $this->exec(); + } else if ($this->pos == 1) { + // noting + return; + } else { + if ($this->lastQuery instanceof Doctrine\DBAL\Query\QueryBuilder) { + $this->statement = $this->lastQuery->execute(); + } else { + $this->execSql($this->querySqlToExec, $this->lastParams); + } + } + + $this->pos = 0; + $this->fetch(); + } + + public function valid() + { + return !$this->EOF; + } + + public function key() + { + return $this->recordPos(); + } + + public function &first($returnNewIfNull=false) + { + $ar = $this->current(); + if ($returnNewIfNull && !$ar) { + $ar = clone $this->ar; + } + return $ar; + } + + public function &current() + { + if ($this->data == NULL) { + $this->rewind(); + } + + // se non ci sono record + if ($this->EOF) { + return null; + } + + $ar = clone $this->ar; + $ar->loadFromArray($this->data); + return $ar; + } + + public function count() + { + if ($this->statement == NULL) { + $this->rewind(); + } + + return $this->count == NULL ? $this->statement->rowCount() : $this->count; + } + + public function setCount( $v ) + { + $this->count = $v; + } + + public function recordPos() + { + return $this->pos; + } + + private function fetch() + { + $this->data = $this->statement->fetch(PDO::FETCH_NAMED); + $this->EOF = $this->data === false; + $this->pos++; + + if ($this->EOF) { + $this->statement->closeCursor(); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/AbstractRelation.php b/src/core/classes/org/glizy/dataAccessDoctrine/AbstractRelation.php new file mode 100644 index 0000000..c02157d --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/AbstractRelation.php @@ -0,0 +1,29 @@ +<?php + +abstract class org_glizy_dataAccessDoctrine_AbstractRelation extends GlizyObject implements org_glizy_dataAccessDoctrine_interfaces_RelationInterface +{ + protected $key = ''; + protected $destinationKey = ''; + protected $parent; + protected $className = ''; + protected $record = null; + + function __construct($parent, $options) + { + $this->parent = $parent; + assert(isset($options['className'])); + $this->className = $options['className']; + } + + public function preSave() + { + } + + public function postSave() + { + } + + public function delete() + { + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecord.php b/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecord.php new file mode 100755 index 0000000..1642a7a --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecord.php @@ -0,0 +1,681 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use Doctrine\DBAL\Types\Type; + +class org_glizy_dataAccessDoctrine_ActiveRecord extends GlizyObject +{ + protected $connection; + protected $tableName; + protected $tablePrefix; + protected $sequenceName = null; + protected $sequenceNameLoaded = false; + protected $primaryKeyName; + protected $fields = array(); + protected $modifiedFields = array(); + protected $data; + protected $virtualData; + protected $siteField = null; + protected $relations = array(); + protected $processRelations = false; + protected $relationBuilded = false; + protected $driverName; + protected $baseclassName; + + function __construct($connectionNumber=0) + { + $this->connection = org_glizy_dataAccessDoctrine_DataAccess::getConnection($connectionNumber); + $this->data = new StdClass(); + $this->virtualData = new StdClass(); + $this->driverName = __Config::get( 'DB_TYPE'.($connectionNumber == 0 ? '' : '#'.$connectionNumber) ); + } + + public function getConnection() + { + return $this->connection; + } + + public function getDriverName() + { + return $this->driverName; + } + + public function getBaseClassName() + { + return 'activerecord'; + } + + public function getTableName() + { + return $this->tableName; + } + + public function getTableNameWithoutPrefix() + { + return substr( $this->getTableName(), strlen( $this->tablePrefix ) ); + } + + public function getTablePrefix() + { + return $this->tablePrefix; + } + + + public function setTableName($tableName, $prefix="") + { + $this->tablePrefix = $prefix; + $this->tableName = $this->tablePrefix.$tableName; + } + + public function setSequenceName($sequenceName) + { + $this->sequenceName = $sequenceName; + } + + public function getSequenceName() + { + if (!$this->sequenceNameLoaded) { + $this->loadSequenceName(); + } + + return $this->sequenceName; + } + + public function getProcessRelations() + { + return $this->processRelations; + } + + public function setProcessRelations($value) + { + $this->processRelations = $value; + } + + public function addField(org_glizy_dataAccessDoctrine_DbField $field ) + { + $this->fields[$field->name] = $field; + + if ($field->key) { + if (!$this->primaryKeyName) { + $this->primaryKeyName = $field->name; + } else { + throw org_glizy_dataAccessDoctrine_ActiveRecordException::primaryKeyAlreadyDefined($this->tableName); + } + } + } + + // serve per cambiare un parametro di un campo a runtime + public function setFieldParam($fieldName, $param, $value) + { + $field = $this->getField($fieldName); + $field->$param = $value; + } + + public function getPrimaryKeyName() + { + return $this->primaryKeyName; + } + + public function getField($fieldName) + { + return $this->fields[$fieldName]; + } + + public function getFields() + { + return $this->fields; + } + + public function getFieldType($fieldName) + { + return $this->fields[$fieldName]->type; + } + + public function getSiteId() + { + return org_glizy_ObjectValues::get('org.glizy', 'siteId'); + } + + public function setSiteField($fieldName) + { + $this->siteField = $fieldName; + } + + public function getSiteField() + { + return $this->siteField; + } + + public function load($id) + { + if (empty($id)) { + $this->emptyRecord(); + return false; + } + + if (is_null($this->primaryKeyName)) { + throw org_glizy_dataAccessDoctrine_ActiveRecordException::primaryKeyNotDefined($this->tableName); + } + + $qb = $this->createQueryBuilder() + ->select('*') + ->where($this->primaryKeyName.' = :id') + ->setParameter(':id', $id); + + if ($this->siteField) { + $qb->andWhere($qb->expr()->eq($this->siteField, ':site')) + ->setParameter(':site', $this->getSiteId()); + } + + $r = $qb->execute()->fetch(); + + if ($r) { + $this->loadFromArray($r); + $this->buildAllRelations(); + return true; + } else { + $this->emptyRecord(); + return false; + } + } + + function loadFromArray($values, $useSet=false) + { + if (!empty($values)) { + $this->emptyRecord(); + + if ($useSet) { + foreach ($values as $k => $v) { + $this->$k = $v; + } + } + else { + foreach ($values as $k => $v) { + $this->data->$k = $v; + } + } + + foreach ($this->relations as $k=>$v) + { + if (array_key_exists($k, $values)) + { + $this->$k = $values[$k]; + } + } + } + } + + public function loadFromQuery($name, $params) + { + $it = $this->createRecordIterator(); + $newAr = $it->load($name, $params)->first(); + if ( $newAr ) { + $this->loadFromArray($newAr->getRawData()); + } + + return $newAr ? $this : false; + } + + public function validate($values = null, $isNew=false) + { + if (is_null($values)) { + if (!empty($this->modifiedFields)) { + // solo i valori dei campi modificati + $values = array_intersect_key(get_object_vars($this->data), $this->modifiedFields); + } else if ($isNew) { + $values = array_keys($this->fields); + } else { + return true; + } + } + + $validationErrors = array(); + + foreach ($values as $fieldName => $value) { + if (is_int($fieldName) && $isNew) { + $fieldName = $value; + if ($fieldName==$this->getPrimaryKeyName()) continue; + $value = $this->getField($fieldName); + } + $field = $this->fields[$fieldName]; + + if (is_null($field->validator)) { + continue; + } + + $validationResult = $field->validator->validate($field->description, $value); + + if (is_string($validationResult)) { + $validationErrors[] = $validationResult; + } + else if (is_array($validationResult)) { + $validationErrors = array_merge($validationErrors, $validationResult); + } + } + + if (!empty($validationErrors)) { + throw new org_glizy_validators_ValidationException($validationErrors); + } + + return true; + } + + public function emptyRecord() + { + $this->data = new StdClass(); + // $this->virtualData = new StdClass(); + $this->modifiedFields = array(); + } + + public function addRelation($options) + { + assert(isset($options['name'])); + + if ( empty( $options['objectName'] ) ) + { + $options['objectName'] = $this->getTableNameWithoutPrefix().'#'.$options['name']; + } + $this->relations[$options['name']] = $options; + $this->{$options['bindTo']} = null; + } + + protected function buildAllRelations($build = true) + { + if ($this->processRelations && !$this->relationBuilded) + { + $this->relationBuilded = true; + + // risolve le relazioni + foreach ($this->relations as $k => $v) + { + $relation = org_glizy_dataAccessDoctrine_RelationFactory::createRelation($this, $v); + if ( $build ) { + $relation->build(); + } + $this->$k = $relation; + } + } + } + + protected function saveAllRelations($preSave=true) + { + // TODO + // quando si fa l'update anche delle relazioni + // c'è da controllare che non si verifichino errori + // in questo caso c'è da segnalarlo + foreach ($this->relations as $k => $v) { + if (is_object($this->$k)) { + if ($preSave==true) { + $this->$k->preSave(); + } else { + $this->$k->postSave(); + } + } + } + } + + protected function deleteAllRelations() + { + foreach ($this->relations as $k => $v) { + if (is_object($this->$k)) { + $this->$k->delete(); + } + } + + $this->relationBuilded = false; + } + + public function find($options=array()) { + $options = array_merge(get_object_vars($this->data), $options); + $qb = $this->connection->createQueryBuilder() + ->select('*') + ->from($this->tableName, 't1'); + $conditionNumber = 0; + foreach($options as $k=>$v) { + if (is_null($v)) continue; + $valueParam = ":value".$conditionNumber++; + $qb->andWhere($qb->expr()->eq($k, $valueParam)); + $qb->setParameter($valueParam, $this->convertIfDateType($k, $v)); + } + + if ($this->siteField && !isset($options[$this->siteField])) { + $qb->andWhere($qb->expr()->eq($this->siteField, ':site')) + ->setParameter(':site', $this->getSiteId()); + } + + $r = $qb->execute()->fetch(); + + if ($r) { + $this->loadFromArray($r); + $this->buildAllRelations(); + return true; + } else { + $this->emptyRecord(); + return false; + } + } + + public function save($values = null, $forceNew = false) + { + if (!is_null($values)) { + $this->loadFromArray($values, true); + } + + if ($this->processRelations) { + $this->buildAllRelations(); + $this->saveAllRelations(true); + } + + if ( $this->isNew() || $forceNew ) + { + if (__Config::get('glizy.dataAccess.validate')) { + $this->validate(null, true); + } + $evt = array('type' => GLZ_EVT_AR_INSERT_PRE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + $result = $this->insert($values); + $evt = array('type' => GLZ_EVT_AR_INSERT.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + } + else + { + if (__Config::get('glizy.dataAccess.validate')) { + $this->validate(null); + } + $evt = array('type' => GLZ_EVT_AR_UPDATE_PRE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + $result = $this->update($values); + $evt = array('type' => GLZ_EVT_AR_UPDATE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + } + + if ($this->processRelations) { + $this->saveAllRelations(false); + } + + return $result; + } + + protected function insert($values=NULL) + { + $sequenceName = $this->getSequenceName(); + if (is_null($values)) { + $values = get_object_vars($this->data); + } + + $insertValues = array(); + $types = array(); + + // filtra i campi virtuali e la chiave primaria + foreach ($values as $fieldName => $value) { + $field = $this->fields[$fieldName]; + if (!$field->virtual && !$field->key) { + $insertValues[$fieldName] = $value; + $types[] = $field->type; + } + } + + if ($this->siteField && !isset($values[$this->siteField])) { + $insertValues[$this->siteField] = $this->getSiteId(); + $types[] = $this->fields[$this->siteField]->type; + } + + if (!empty($insertValues)) { + $r = $this->connection->insert($this->tableName, $insertValues, $types); + } + + if ($r != false) { + $this->modifiedFields = array(); + $this->setId($this->connection->lastInsertId($sequenceName)); + return $this->getId(); + } + else { + return false; + } + } + + protected function update($values=NULL) + { + $identifier = array($this->primaryKeyName => $this->getId()); + + if (is_null($values)) { + $values = array_intersect_key(get_object_vars($this->data), $this->modifiedFields); + } + + $updateValues = array(); + $types = array(); + + foreach ($values as $fieldName => $value) { + $field = $this->fields[$fieldName]; + if (!$field->virtual && isset($this->modifiedFields[$fieldName])) { + $updateValues[$fieldName] = $value; + $types[] = $field->type; + } + } + + if (!empty($updateValues)) { + $this->connection->update($this->tableName, $updateValues, $identifier, $types); + } + + return $this->getId(); + } + + public function delete($id = null) + { + if (is_array($id)) { + $identifier = $id; + } + else { + $identifier = array($this->primaryKeyName => is_null($id) ? $this->getId() : $id); + } + + $evt = array('type' => GLZ_EVT_AR_DELETE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + + if ($this->processRelations) + { + if ($this->isNew()) { + $this->load($id); + } + $this->buildAllRelations(); + $this->deleteAllRelations(); + } + + $this->emptyRecord(); + + return $this->connection->delete($this->tableName, $identifier); + } + + public function __call($name, $arguments) + { + return $this->{$name}; + + } + + public function __get($name) + { + if (property_exists($this->data, $name)) { + $value = $this->data->$name; + return array_key_exists($name, $this->fields) ? $this->fields[$name]->format($value, $this->connection) : $value; + } + else if (property_exists($this->virtualData, $name)) { + return $this->virtualData->$name; + } + else if (array_key_exists($name, $this->fields)) { + return $this->fields[$name]->defaultValue; + } + + throw org_glizy_dataAccessDoctrine_ActiveRecordException::getFailed($this->tableName, $name); + } + + public function convertIfDateType($fieldName, $value) + { + $field = $this->fields[$fieldName]; + + if ($field->type == Type::DATE || $field->type == Type::DATETIME) { + return glz_localeDate2ISO($value); + } else { + return $value; + } + } + + public function __set($name, $value) + { + if (array_key_exists($name, $this->fields)) { + $field = $this->fields[$name]; + // La condizione verifica che il campo è stato modificato, non è un campo di sistema + if ($this->$name != $value && !$field->isSystemField) { + $this->modifiedFields[$name] = true; + } + $this->data->$name = $this->convertIfDateType($name, $value); + } + else { + $this->virtualData->$name = $value; + } + } + + public function forceModified($name) + { + $this->modifiedFields[$name] = true; + } + + public function getValues($getRelationValues=false, $getVirtualField=true, $encode=false, $systemFields=true) + { + $result = new StdClass; + foreach ($this->data as $name => $value) { + if ($systemFields == false && $this->fields[$name]->isSystemField) { + continue; + } + $result->{$name} = array_key_exists($name, $this->fields) ? $this->fields[$name]->format($value, $this->connection) : $value; + } + + foreach ($this->virtualData as $name => $value) { + $result->{$name} = $value; + } + + if ($getRelationValues) { + $this->buildAllRelations(); + foreach ($this->relations as $k => $v) { + if (!is_object($this->$k)) { + $result->$k = $this->$k; + } else { + if ( method_exists( $this->$k, 'collectFieldsValues' ) ) { + $result->$k = $this->$k->collectFieldsValues( $getVirtualField, $encode ); + } else { + $result->$k = null; + } + } + } + } + return $result; + } + + public function getRawData() + { + return $this->data; + } + + // restituisce anche i campi con valore null + public function getValuesForced($getRelationValues=false, $getVirtualField=true, $encode=false, $systemFields=true) + { + $result = $this->getValues($getRelationValues, $getVirtualField, $encode, $systemFields); + foreach($this->fields as $k=>$v) { + if (!property_exists($result, $k)) { + $result->$k = null; + } + } + return $result; + } + + public function getValuesAsArray($getRelationValues=false, $getVirtualField=true, $encode=false, $systemFields=true) + { + $result = $this->getValues($getRelationValues, $getVirtualField, $encode, $systemFields); + return get_object_vars($result); + } + + function getFieldValue($name, $raw=false) + { + $this->buildAllRelations(); + return property_exists($this->data, $name) || property_exists($this->virtualData, $name) ? ($raw ? $this->data->$name : $this->$name) : ''; + } + + function getFieldValueByRegexp($name, $raw=false) + { + $this->buildAllRelations(); + + foreach ($this->data as $k => $value) { + if (strpos( $k, $name) !== false) { + return $raw ? $this->data->$k : $this->$k; + } + } + + return ''; + } + + public function getId() + { + if (is_null($this->primaryKeyName)) { + throw org_glizy_dataAccessDoctrine_ActiveRecordException::primaryKeyNotDefined($this->tableName); + } + $primarykey = $this->primaryKeyName; + return $this->$primarykey; + } + + public function setId($value) + { + $primarykey = $this->primaryKeyName; + $this->$primarykey = $value; + } + + public function isNew() + { + return is_null( $this->{$this->primaryKeyName} ); + } + + public function fieldExists($name) + { + return array_key_exists($name, $this->fields); + } + + public function keyInDataExists($name) { + return property_exists($this->data, $name); + } + + public function isModified($name) { + return $this->modifiedFields[$name] == true; + } + + public function createRecordIterator() { + return new org_glizy_dataAccessDoctrine_RecordIterator($this); + } + + public function createQueryBuilder($addFrom=true, $tableAlias='t1') + { + $qb = $this->connection->createQueryBuilder(); + + if ($addFrom) { + $qb->from($this->tableName, $tableAlias); + } + + return $qb; + } + + public function dump() + { + var_dump($this->getValuesAsArray()); + } + + private function loadSequenceName() + { + $this->sequenceNameLoaded = true; + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($this->connection); + $sequenceName = $sm->getSequenceName($this->getTableName()); + $this->setSequenceName($sequenceName); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecord2tables.php b/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecord2tables.php new file mode 100755 index 0000000..b4998dd --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecord2tables.php @@ -0,0 +1,444 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + + +class org_glizy_dataAccessDoctrine_ActiveRecord2tables extends org_glizy_dataAccessDoctrine_ActiveRecord +{ + protected $detailTableName = null; + protected $detailSequenceName = null; + protected $detailPrimaryKeyName = null; + protected $joinFields = array(); + protected $detailFieldsMap = array(); + protected $languageField = null; + + function __construct($connectionNumber=0) + { + parent::__construct($connectionNumber); + } + + public function getBaseClassName() + { + return '2tables'; + } + + public function getDetailTableName() + { + return $this->detailTableName; + } + + public function getDetailTableNameWithoutPrefix() + { + return substr( $this->getDetailTableName(), strlen( $this->tablePrefix ) ); + } + + function getSequenceName() + { + if (!$this->sequenceNameLoaded) { + $this->loadSequenceName(); + } + + return $this->sequenceName; + } + + function getDetailSequenceName() + { + if (!$this->sequenceNameLoaded) { + $this->loadSequenceName(); + } + + return $this->detailSequenceName; + } + + public function setDetailTableName($tableName, $prefix="") + { + $this->tablePrefix = $prefix; + $this->detailTableName = $prefix.$tableName; + } + + public function setDetailSequenceName($sequenceName) + { + $this->detailSequenceName = $sequenceName; + } + + function getJoinFields() + { + return $this->joinFields; + } + + function setJoinFields($theJoin1, $theJoin2) + { + $this->joinFields['mainTable'] = $theJoin1; + $this->joinFields['detailTable'] = $theJoin2; + } + + public function addField(org_glizy_dataAccessDoctrine_DbField $field, $isDetailField = false) + { + if ($isDetailField) { + $this->detailFieldsMap[$field->name] = true; + } + + $this->fields[$field->name] = $field; + + if ($field->key) { + if (!$this->primaryKeyName && !$isDetailField) { + $this->primaryKeyName = $field->name; + } + else if (!$this->detailPrimaryKeyName && $isDetailField) { + $this->detailPrimaryKeyName = $field->name; + } else if ($this->primaryKeyName) { + throw org_glizy_dataAccessDoctrine_ActiveRecordException::primaryKeyAlreadyDefined($this->tableName); + } else if ($this->detailPrimaryKeyName) { + throw org_glizy_dataAccessDoctrine_ActiveRecordException::detailPrimaryKeyAlreadyDefined($this->tableName); + } + } + } + + public function getDetailPrimaryKeyName() + { + return $this->detailPrimaryKeyName; + } + + public function getLanguageId() + { + $editingLanguageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + if (!is_null($editingLanguageId)) { + return $editingLanguageId; + } + else { + return org_glizy_ObjectValues::get('org.glizy', 'languageId'); + } + } + + public function getLanguagesId() + { + $languagesId = org_glizy_ObjectValues::get('org.glizy', 'languagesId'); + return !is_null($languagesId) ? $languagesId : array($this->getLanguageId()); + } + + public function getLanguageField() + { + if ($this->detailFieldsMap[$this->languageField]) { + return 'detail.'.$this->languageField; + } else { + return $this->languageField; + } + } + + public function setLanguageField($fieldName) + { + $this->languageField = $fieldName; + } + + public function load($id, $idDetail = null) + { + if (is_null($this->primaryKeyName)) { + throw org_glizy_dataAccessDoctrine_ActiveRecordException::primaryKeyNotDefined($this->tableName); + } + + $qb = $this->createQueryBuilder() + ->select('*') + ->where($this->primaryKeyName.' = :id') + ->setParameter(':id', $id); + + if ($idDetail != null) { + $qb->andWhere($this->detailPrimaryKeyName.' = :idDetail') + ->setParameter(':idDetail', $idDetail); + } + + $this->addLanguageFilter($qb); + $this->addSiteFilter($qb); + + + $r = $qb->execute()->fetch(); + + if ($r) { + $this->loadFromArray($r); + $this->buildAllRelations(); + return true; + } else { + $this->emptyRecord(); + return false; + } + } + + public function save($values=NULL, $forceNew=false) + { + if (!is_null($values)) { + $this->loadFromArray($values, true); + } + + if (__Config::get('glizy.dataAccess.validate')) { + $this->validate(); + } + + if ($this->processRelations) { + $this->buildAllRelations(); + $this->saveAllRelations(true); + } + + if (is_null($this->getId()) || $forceNew) { + $result1 = $this->insertMain($values); + } + else { + $result1 = $this->updateMain($values); + } + + if (is_null($this->getDetailId()) || $forceNew) { + $result2 = $this->insertDetail($values); + } + else { + $result2 = $this->updateDetail($values); + } + + if ($this->processRelations) { + $this->saveAllRelations(false); + } + + return $result1; + } + + protected function insertMain($values=NULL) + { + // sequenceName deve essere letto prima della insert + // altrimenti può creare problemi con la insert del dettaglio + $sequenceName = $this->getSequenceName(); + if (is_null($values)) { + $values = get_object_vars($this->data); + } + + $insertValues = array(); + $types = array(); + + foreach ($values as $fieldName => $value) { + $field = $this->fields[$fieldName]; + if (!$field->virtual && $this->detailFieldsMap[$fieldName] == false) { + $insertValues[$fieldName] = $values[$fieldName]; + $types[] = $field->type; + } + } + + if ($this->siteField && !$this->detailFieldsMap[$this->siteField] && !isset($values[$this->siteField])) { + $insertValues[$this->siteField] = $this->getSiteId(); + $types[] = $this->fields[$this->siteField]->type; + } + + $r = $this->connection->insert($this->tableName, $insertValues, $types); + + if ($r != false) { + $this->modifiedFields = array(); + $this->setId($this->connection->lastInsertId($sequenceName)); + return $this->getId(); + } + else { + return false; + } + } + + protected function updateMain($values=NULL) + { + if (is_null($values)) { + $values = get_object_vars($this->data); + } + + $insertValues = array(); + $types = array(); + + foreach ($values as $fieldName => $value) { + $field = $this->fields[$fieldName]; + if (isset($this->modifiedFields[$fieldName]) && !$field->virtual && $this->detailFieldsMap[$fieldName] == false) { + $insertValues[$fieldName] = $values[$fieldName]; + $types[] = $field->type; + } + } + + if (!empty($insertValues)) { + $identifier = array($this->primaryKeyName => $this->getId()); + $this->connection->update($this->tableName, $insertValues, $identifier, $types); + } + + return $this->getId(); + } + + protected function insertDetail($values=NULL) + { + $sequenceName = $this->getDetailSequenceName(); + if (is_null($values)) { + $values = get_object_vars($this->data); + } + + $insertValues = array(); + $types = array(); + + foreach ($values as $fieldName => $value) { + $field = $this->fields[$fieldName]; + if (!$field->virtual && $this->detailFieldsMap[$fieldName] == true) { + $insertValues[$fieldName] = $values[$fieldName]; + $types[] = $field->type; + } + } + + $detailFkField = $this->joinFields['detailTable']; + if (is_null($insertValues[$detailFkField])) { + $insertValues[$detailFkField] = $this->getId(); + } + + if ($this->siteField && $this->detailFieldsMap[$this->siteField] && !isset($values[$this->siteField])) { + $insertValues[$this->siteField] = $this->getSiteId(); + $types[] = $this->fields[$this->siteField]->type; + } + + if ($this->languageField && $this->detailFieldsMap[$this->languageField] && !$values[$this->languageField]) { + $types[] = $this->fields[$this->languageField]->type; + + $languages = $this->getLanguagesId(); + + foreach ($languages as $languageId) { + $insertValues[$this->languageField] = $languageId; + $r = $this->connection->insert($this->detailTableName, $insertValues, $types); + + if ($languageId == $this->getLanguageId()) { + if ($r != false) { + $this->modifiedFields = array(); + $this->setDetailId($this->connection->lastInsertId($sequenceName)); + $returnDetailId = $this->getDetailId(); + } + else { + return false; + } + } + } + + return $returnDetailId; + } + + $r = $this->connection->insert($this->detailTableName, $insertValues, $types); + + if ($r != false) { + $this->modifiedFields = array(); + $this->setDetailId($this->connection->lastInsertId($sequenceName)); + return $this->getDetailId(); + } + else { + return false; + } + } + + protected function updateDetail($values=NULL) + { + if (is_null($values)) { + $values = get_object_vars($this->data); + } + + $insertValues = array(); + $types = array(); + + foreach ($values as $fieldName => $value) { + $field = $this->fields[$fieldName]; + if (isset($this->modifiedFields[$fieldName]) && !$field->virtual && $this->detailFieldsMap[$fieldName] == true) { + $insertValues[$fieldName] = $values[$fieldName]; + $types[] = $field->type; + } + } + + if (!empty($insertValues)) { + $identifier = array($this->detailPrimaryKeyName => $this->getDetailId()); + $this->connection->update($this->detailTableName, $insertValues, $identifier, $types); + } + return $this->getDetailId(); + } + + public function delete($id = null) + { + if (is_array($id)) { + $identifier = $id; + } + else { + $identifier = array($this->primaryKeyName => is_null($id) ? $this->getId() : $id); + } + + $evt = array('type' => GLZ_EVT_AR_DELETE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + + if ($this->processRelations) + { + if ($this->isNew()) { + $this->load($id); + } + $this->buildAllRelations(); + $this->deleteAllRelations(); + } + + $this->emptyRecord(); + + $detailId = array($this->joinFields['detailTable'] => $identifier[$this->primaryKeyName] ); + $this->connection->delete($this->detailTableName, $detailId); + + return $this->connection->delete($this->tableName, $identifier); + } + + public function getDetailId() + { + if (is_null($this->detailPrimaryKeyName)) { + throw org_glizy_dataAccessDoctrine_ActiveRecordException::detailPrimaryKeyNotDefined($this->tableName); + } + $detailPrimaryKeyName = $this->detailPrimaryKeyName; + return $this->$detailPrimaryKeyName; + } + + public function setDetailId($value) + { + $detailPrimaryKeyName = $this->detailPrimaryKeyName; + $this->$detailPrimaryKeyName = $value; + } + + public function createRecordIterator() { + return new org_glizy_dataAccessDoctrine_RecordIterator2tables($this); + } + + public function createQueryBuilder($addFrom=true, $tableAlias='t1', $tableDetailAlias='detail') { + $qb = $this->connection->createQueryBuilder(); + + if ($addFrom) { + $qb->from($this->tableName, $tableAlias) + ->join($tableAlias, $this->detailTableName, $tableDetailAlias, + $qb->expr()->eq($tableAlias.'.'.$this->joinFields['mainTable'], $tableDetailAlias.'.'. $this->joinFields['detailTable'])); + } + + return $qb; + } + + protected function addLanguageFilter($qb) + { + if ($this->languageField) { + $qb->andWhere($qb->expr()->eq($this->languageField, ':language')) + ->setParameter(':language', $this->getLanguageId()); + } + } + + protected function addSiteFilter($qb) + { + if ($this->siteField) { + $qb->andWhere($qb->expr()->eq($this->siteField, ':site')) + ->setParameter(':site', $this->getSiteId()); + } + } + + private function loadSequenceName() + { + $this->sequenceNameLoaded = true; + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($this->connection); + $sequenceName = $sm->getSequenceName($this->getTableName()); + $this->setSequenceName($sequenceName); + + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($this->connection); + $detailSequenceName = $sm->getSequenceName($this->getDetailTableName()); + $this->setDetailSequenceName($detailSequenceName); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordDocument.php b/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordDocument.php new file mode 100755 index 0000000..9ca71a5 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordDocument.php @@ -0,0 +1,1038 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use Doctrine\DBAL\Types\Type; + +class org_glizy_dataAccessDoctrine_ActiveRecordDocument extends org_glizy_dataAccessDoctrine_ActiveRecord +{ + const DOCUMENT_TABLE = 'documents_tbl'; + const DOCUMENT_TABLE_ALIAS = 'doc'; + const DOCUMENT_ID = 'document_id'; + const DOCUMENT_TYPE = 'document_type'; + const DOCUMENT_CREATION_DATE = 'document_creationDate'; + const DOCUMENT_FK_SITE_ID = 'document_FK_site_id'; + const DOCUMENT_DETAIL_TABLE = 'documents_detail_tbl'; + const DOCUMENT_DETAIL_TABLE_ALIAS = 'doc_detail'; + const DOCUMENT_DETAIL_TABLE_PUBLISHED_ALIAS = 'doc_detail_published'; + const DOCUMENT_DETAIL_TABLE_DRAFT_ALIAS = 'doc_detail_draft'; + const DOCUMENT_DETAIL_ID = 'document_detail_id'; + const DOCUMENT_DETAIL_FK_DOCUMENT = 'document_detail_FK_document_id'; + const DOCUMENT_DETAIL_FK_LANGUAGE = 'document_detail_FK_language_id'; + const DOCUMENT_DETAIL_FK_USER = 'document_detail_FK_user_id'; + const DOCUMENT_DETAIL_MODIFICATION_DATE = 'document_detail_modificationDate'; + const DOCUMENT_DETAIL_STATUS = 'document_detail_status'; + const DOCUMENT_DETAIL_TRANSLATED = 'document_detail_translated'; + const DOCUMENT_DETAIL_IS_VISIBLE = 'document_detail_isVisible'; + const DOCUMENT_DETAIL_NOTE = 'document_detail_note'; + const DOCUMENT_DETAIL_OBJECT = 'document_detail_object'; + const DOCUMENT_INDEX_TABLE_PREFIX = 'documents_index_'; + const DOCUMENT_INDEX_FIELD_PREFIX = 'document_index_'; + const DOCUMENT_BASE_PREFIX = 'document_'; + + const STATUS_PUBLISHED = 'PUBLISHED'; + const STATUS_DRAFT = 'DRAFT'; + const STATUS_OLD = 'OLD'; + + protected $detailPrimaryKeyName; + protected $detailSequenceName; + protected $status; + protected $type; + protected $isVisible = array(); + protected $hasPublishedVersion; + protected $hasDraftVersion; + + protected static $typeMap = array(Type::INTEGER => 'int', + Type::SMALLINT => 'int', + Type::BIGINT => 'int', + Type::STRING => 'text', + Type::TEXT => 'text', + Type::TARRAY => 'text', + Type::DATE => 'date', + Type::DATETIME => 'datetime', + Type::TIME => 'time', + org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID => 'int'); + + protected static $indexQueueEnabled = false; + protected static $indexQueue = null; + + function __construct($connectionNumber=0) + { + parent::__construct($connectionNumber); + + $this->detailSequenceName = null; + $this->status = null; + + foreach ($this->getLanguagesId() as $languageId) { + $this->isVisible[$languageId] = 1; + } + + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_ID, Doctrine\DBAL\Types\Type::INTEGER, 10, true, null, null)); + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_TYPE, Doctrine\DBAL\Types\Type::STRING, 255, false, null, 0, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_FK_SITE_ID, Doctrine\DBAL\Types\Type::INTEGER, 255, false, null, 0, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_CREATION_DATE, Doctrine\DBAL\Types\Type::DATETIME, 255, false, null, 0, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_DETAIL_ID, Doctrine\DBAL\Types\Type::INTEGER, 10, true, null, null)); + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_DETAIL_FK_DOCUMENT, Doctrine\DBAL\Types\Type::INTEGER, 255, false, null, 0, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_DETAIL_FK_USER, Doctrine\DBAL\Types\Type::INTEGER, 255, false, null, 0, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_DETAIL_TRANSLATED, Doctrine\DBAL\Types\Type::INTEGER, 255, false, null, 0, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_DETAIL_MODIFICATION_DATE, Doctrine\DBAL\Types\Type::DATETIME, 255, false, null, 0, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_DETAIL_STATUS, Doctrine\DBAL\Types\Type::STRING, 255, false, null, 0, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_DETAIL_FK_LANGUAGE, Doctrine\DBAL\Types\Type::INTEGER, 10, false, null, 0, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_DETAIL_IS_VISIBLE, Doctrine\DBAL\Types\Type::INTEGER, 1, false, null, 1, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_DETAIL_OBJECT, Doctrine\DBAL\Types\Type::TEXT, 255, false, null, 1, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + + if (__Config::get('glizy.dataAccess.document.enableComment')) { + $this->addField(new org_glizy_dataAccessDoctrine_SystemField(self::DOCUMENT_DETAIL_NOTE, Doctrine\DBAL\Types\Type::TEXT, 255, false, null, 1, true, false, '', org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED)); + + } + + if (__Config::get('MULTISITE_ENABLED')) { + $this->siteField = self::DOCUMENT_FK_SITE_ID; + } + + if (!self::$indexQueue) { + self::$indexQueue = new org_glizy_dataAccessDoctrine_IndexQueue($this->connection); + } + } + + public function getBaseClassName() + { + return 'document'; + } + + public function addField(org_glizy_dataAccessDoctrine_DbField $field ) + { + $this->fields[$field->name] = $field; + + if ($field->key) { + if (!$this->primaryKeyName && $field->name == self::DOCUMENT_ID) { + $this->primaryKeyName = $field->name; + } + else if (!$this->detailPrimaryKeyName && $field->name == self::DOCUMENT_DETAIL_ID) { + $this->detailPrimaryKeyName = $field->name; + } else { + throw org_glizy_dataAccessDoctrine_ActiveRecordException::primaryKeyAlreadyDefined($this->tableName); + } + } + } + + public function getDetailId() + { + if (is_null($this->detailPrimaryKeyName)) { + throw org_glizy_dataAccessDoctrine_ActiveRecordException::detailPrimaryKeyNotDefined($this->tableName); + } + $detailPrimaryKeyName = $this->detailPrimaryKeyName; + return $this->$detailPrimaryKeyName; + } + + public function setDetailId($value) + { + $detailPrimaryKeyName = $this->detailPrimaryKeyName; + $this->$detailPrimaryKeyName = $value; + } + + public function getType() + { + return $this->{self::DOCUMENT_TYPE}; + } + + public function setType($type) + { + $this->type = $type; + $this->{self::DOCUMENT_TYPE} = $type; + } + + public function getStatus() + { + return $this->status; + } + + public function setStatus($status) + { + $this->status = $status; + } + + public function getLanguage() + { + return $this->{self::DOCUMENT_DETAIL_FK_LANGUAGE}; + } + + public function setLanguage($languageId) + { + $this->{self::DOCUMENT_DETAIL_FK_LANGUAGE} = $languageId; + $this->modifiedFields[self::DOCUMENT_DETAIL_FK_LANGUAGE] = true; + } + + public function isTranslated() + { + return $this->{self::DOCUMENT_DETAIL_TRANSLATED}; + } + + public function isVisible() + { + return $this->{self::DOCUMENT_DETAIL_IS_VISIBLE}; + } + + public function setVisible($visible) + { + $this->isVisible[$this->getLanguageId()] = $visible; + $this->modifiedFields[self::DOCUMENT_DETAIL_IS_VISIBLE] = true; + } + + function getSequenceName() + { + if (!$this->sequenceNameLoaded) { + $this->loadSequenceName(); + } + + return $this->sequenceName; + } + + function getDetailSequenceName() + { + if (!$this->sequenceNameLoaded) { + $this->loadSequenceName(); + } + + return $this->detailSequenceName; + } + + public function setDetailSequenceName($detailSequenceName) + { + $this->detailSequenceName = $detailSequenceName; + } + + public function getDocumentTableName() + { + return $this->tablePrefix.self::DOCUMENT_TABLE; + } + + public function getDocumentDetailTableName() + { + return $this->tablePrefix.self::DOCUMENT_DETAIL_TABLE; + } + + public function getDocumentTableIdName() + { + return self::DOCUMENT_ID; + } + + public function getDocumentDetailTableIdName() + { + return self::DOCUMENT_DETAIL_ID; + } + + public function getDocumentIndexTablePrefix() + { + return $this->tablePrefix.self::DOCUMENT_INDEX_TABLE_PREFIX; + } + + public function getDocumentIndexFieldPrefix() + { + return self::DOCUMENT_INDEX_FIELD_PREFIX; + } + + public function getTypeField() + { + return self::DOCUMENT_TYPE; + } + + public function getLanguageField() + { + return self::DOCUMENT_DETAIL_FK_LANGUAGE; + } + + public function getStatusField() + { + return self::DOCUMENT_DETAIL_STATUS; + } + + function getIndexFieldType($fieldName) + { + $field = $this->fields[$fieldName]; + + if (!$field) { + throw org_glizy_dataAccessDoctrine_ActiveRecordException::undefinedField($this->_className, $fieldName); + } + + if ($field->index & $field::FULLTEXT) { + return 'fulltext'; + } else { + $type = $this->fields[$fieldName]->type; + + if ($type==org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID) { + return self::$typeMap[$this->fields[$fieldName]->option[org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID]['type']]; + } + + return self::$typeMap[$type]; + } + } + + public function getLanguageId() + { + $editingLanguageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + if (!is_null($editingLanguageId)) { + return $editingLanguageId; + } else { + return org_glizy_ObjectValues::get('org.glizy', 'languageId'); + } + } + + public function getLanguagesId() + { + // NOTE: non mi piace questa dipendenza sulla lingue disponibili + $languagesId = org_glizy_ObjectValues::get('org.glizy', 'languagesId'); + return !is_null($languagesId) ? $languagesId : array($this->getLanguageId()); + } + + public function getUserId() + { + return org_glizy_ObjectValues::get('org.glizy', 'userId'); + } + + public function load($id, $status='PUBLISHED', $languageId=null) + { + if (empty($id)) { + $this->emptyRecord(); + return false; + } + + if ($languageId === null) { + $languageId = $this->getLanguageId(); + } + + $qb = $this->createQueryBuilder(array('type' => 'PUBLISHED')); + $expr = $qb->expr(); + + $qb->select('*') + ->where($expr->eq($this->primaryKeyName, ':id')) + ->andWhere($expr->eq(self::DOCUMENT_DETAIL_FK_LANGUAGE, ':language')) + ->setParameter(':id', $id) + ->setParameter(':language', $languageId) + ->setMaxResults(1); + + // restituisce prima PUBLISHED se c'è, altrimenti DRAFT grazie all'orderBy sullo status + if ($status == 'PUBLISHED') { + $or = $expr->orX(); + $or->add($expr->eq(self::DOCUMENT_DETAIL_STATUS, ':status1')) + ->add($expr->eq(self::DOCUMENT_DETAIL_STATUS, ':status2')); + + $qb->andWhere($or) + ->setParameter(':status1', self::STATUS_DRAFT) + ->setParameter(':status2', self::STATUS_PUBLISHED) + ->orderBy(self::DOCUMENT_DETAIL_STATUS, 'DESC'); + } else if ($status == 'DRAFT') { + $qb->andWhere($expr->eq(self::DOCUMENT_DETAIL_STATUS, ':status1')) + ->setParameter(':status1', self::STATUS_DRAFT); + } else if ($status == 'LAST_MODIFIED') { + $qb->orderBy(self::DOCUMENT_DETAIL_MODIFICATION_DATE, 'DESC'); + } + + if ($this->siteField) { + $qb->andWhere($expr->eq($this->siteField, ':site')) + ->setParameter(':site', $this->getSiteId()); + } + + $r = $qb->execute()->fetch(); + + if ($r) { + $this->loadFromArray($r); + return true; + } else { + $this->emptyRecord(); + return false; + } + } + + public function hasPublishedVersion() + { + return $this->hasPublishedVersion; + } + + public function hasDraftVersion() + { + return $this->hasDraftVersion; + } + + public function loadFromArray($values, $useSet=false) + { + if (!empty($values)) { + $this->emptyRecord(); + + $documentObjVo = __ObjectFactory::createObject('org.glizy.dataAccessDoctrine.vo.DocumentObjectVO', $values); + + $this->hasPublishedVersion = $documentObjVo->hasPublishedVersion(); + $this->hasDraftVersion = $documentObjVo->hasDraftVersion(); + + $detailObj = $documentObjVo->{self::DOCUMENT_DETAIL_OBJECT}; + + if ($detailObj) { + if (__Config::get('glizy.dataAccess.serializationMode') == 'json') { + $this->data = json_decode($detailObj); + } else { + $data = unserialize($detailObj); + + // TODO rimuovere quando la migrazione dei dati da serializzazione php a json è completata + if (is_array($data)) { + foreach ($data as $k => $v) { + $this->data->$k = $v; + } + } else { + $this->data = $data; + } + } + } + + if (!is_object($this->data)) { + $this->data = new StdClass; + } + + foreach ($values as $k => $v) { + if (strpos($k, self::DOCUMENT_BASE_PREFIX)===false) { + $this->virtualData->$k = $documentObjVo->$k; + } else { + $this->data->$k = $documentObjVo->$k; + } + } + + if ($values[self::DOCUMENT_ID]) $this->setId($values[self::DOCUMENT_ID]); + + // NOTA: forse non è opportuno non permettere l'override del tipo + if ($values[self::DOCUMENT_TYPE]) $this->setType($values[self::DOCUMENT_TYPE]); + if ($documentObjVo->{self::DOCUMENT_DETAIL_ID}) $this->setDetailId($documentObjVo->{self::DOCUMENT_DETAIL_ID}); + if ( $documentObjVo->{self::DOCUMENT_DETAIL_STATUS}) $this->setStatus( $documentObjVo->{self::DOCUMENT_DETAIL_STATUS}); + } + } + + public function emptyRecord() + { + parent::emptyRecord(); + $this->setType($this->type); + $this->status = null; + } + + // TODO + // gestire senza recordIterator + public function find($options=array()) + { + $options = array_merge(get_object_vars($this->data), $options); + $it = $this->createRecordIterator(); + + foreach($options as $k => $v) { + $it->where($k, $v); + } + + if ($this->siteField && !isset($options[$this->siteField])) { + $it->where($this->siteField, $this->getSiteId()); + } + + $ar = $it->first(); + + if ($ar) { + $this->loadFromArray($ar->getValuesAsArray()); + return true; + } else { + $this->emptyRecord(); + return false; + } + } + + public function save($values=null, $forceNew=false, $status=self::STATUS_DRAFT, $comment='') + { + if (!is_null($values)) { + $this->loadFromArray($values, true); + } + + if (__Config::get('glizy.dataAccess.validate')) { + $this->validate(); + } + + if ( $this->isNew() || $forceNew ) + { + $evt = array('type' => GLZ_EVT_AR_INSERT_PRE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + $result = $this->insert($values, $status, $comment); + $evt = array('type' => GLZ_EVT_AR_INSERT.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + } + else + { + $evt = array('type' => GLZ_EVT_AR_UPDATE_PRE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + $result = $this->update($values, $comment); + $evt = array('type' => GLZ_EVT_AR_UPDATE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + } + + return $result; + } + + protected function insert($values = NULL, $status=self::STATUS_DRAFT, $comment) + { + // sequenceName deve essere letto prima della insert + // altrimenti può creare problemi con la insert del dettaglio + $sequenceName = $this->getSequenceName(); + + if (is_null($values)) { + $values = get_object_vars($this->data); + } + + $valArray = array(); + $valArrayIndex = array(); + + // seleziona solo i valori che non siano campi di sistema + foreach ($values as $fieldName => $value) { + $field = $this->fields[$fieldName]; + if ($field && !$field->isSystemField) { + if (!($field->index & $field::ONLY_INDEX) && !is_null($value) && $value !== '') { + $valArray[$fieldName] = $value; + } + $valArrayIndex[$fieldName] = is_string($value) ? trim(strip_tags($value)) : $value; + } + } + + $document = array( + self::DOCUMENT_TYPE => $this->getType(), + self::DOCUMENT_CREATION_DATE => new org_glizy_types_DateTime() + ); + + if ($this->siteField && !isset($document[$this->siteField])) { + $document[$this->siteField] = $this->getSiteId(); + } + + $r = $this->connection->insert($this->getDocumentTableName(), $document); + + if ($r != false) { + $id = $this->connection->lastInsertId($sequenceName); + + $languages = $this->getLanguagesId(); + + foreach ($languages as $languageId) { + $detailId = $this->insertValues($id, $valArray, $status, $languageId, $comment); + $this->insertValuesIntoIndex($detailId, $valArrayIndex); + + if ($languageId == $this->getLanguageId()) { + $this->setId($id); + $this->setDetailId($detailId); + $this->modifiedFields = array(); + } + } + return $this->getId(); + } + else { + return false; + } + } + + protected function insertValues($id, $values, $status = self::STATUS_DRAFT, $languageId, $comment) + { + $sequenceName = $this->getDetailSequenceName(); + $documentDetail = array( + self::DOCUMENT_DETAIL_FK_DOCUMENT => $id, + self::DOCUMENT_DETAIL_FK_LANGUAGE => $languageId, + self::DOCUMENT_DETAIL_FK_USER => $this->getUserId(), + self::DOCUMENT_DETAIL_MODIFICATION_DATE => new org_glizy_types_DateTime(), + self::DOCUMENT_DETAIL_STATUS => $status, + self::DOCUMENT_DETAIL_TRANSLATED => $languageId == $this->getLanguageId(), + self::DOCUMENT_DETAIL_IS_VISIBLE => $this->isVisible[$languageId] + ); + + if (__Config::get('glizy.dataAccess.serializationMode') == 'json') { + $documentDetail[self::DOCUMENT_DETAIL_OBJECT] = json_encode($values); + } + else { + $documentDetail[self::DOCUMENT_DETAIL_OBJECT] = serialize($values); + } + + $types = array( + Type::INTEGER, + Type::INTEGER, + Type::INTEGER, + Type::DATETIME, + Type::STRING, + Type::INTEGER, + Type::TEXT + ); + + if (__Config::get('glizy.dataAccess.document.enableComment')) { + $documentDetail[self::DOCUMENT_DETAIL_NOTE] = $comment; + $types[] = Type::TEXT; + } + + $this->setStatus($status); + $this->connection->insert($this->getDocumentDetailTableName(), $documentDetail, $types); + return $this->connection->lastInsertId($sequenceName); + } + + protected function insertValuesIntoIndex($id, $values) + { + foreach ($values as $fieldName => $value) { + $field = $this->fields[$fieldName]; + if (!$field->virtual && $field->index != $field::NOT_INDEXED && isset(self::$typeMap[$field->type])) { + $indexFieldType = $this->getIndexFieldType($fieldName); + $tableName = $this->getDocumentIndexTablePrefix() . $indexFieldType . '_tbl'; + $fieldPrefix = self::DOCUMENT_INDEX_FIELD_PREFIX . $indexFieldType; + + $documentIndex = array( + $fieldPrefix.'_FK_document_detail_id' => $id, + $fieldPrefix.'_name' => $fieldName + ); + + $types = array( + Type::INTEGER, + Type::STRING + ); + + // TODO + // troncare value se l'indice è 'text' e se value è maggiore di 255 + + // se $value è un array inserisce i singoli valori nell'indice + if (is_array($value)) { + foreach ($value as $v) { + $v = $this->getValueToIndex($field->type, $v, $field->option); + if (!is_null($v)) { + $documentIndex[$fieldPrefix.'_value'] = $v; + $this->connection->insert($tableName, $documentIndex); + } + } + } else { + $value = $this->getValueToIndex($field->type, $value, $field->option); + + if ((!is_null($value) && $value !== '') || $field->type == Type::STRING) { + $documentIndex[$fieldPrefix.'_value'] = $value; + $types[] = $field->type; + if (!self::$indexQueueEnabled) { + $this->connection->insert($tableName, $documentIndex, $types); + } else { + $documentIndex[$fieldPrefix.'_name'] = "'".$documentIndex[$fieldPrefix.'_name']."'"; + $documentIndex[$fieldPrefix.'_value'] = $this->connection->quote($documentIndex[$fieldPrefix.'_value'], $field->type); + self::$indexQueue->insert($tableName, $documentIndex, $types); + } + } + } + } + } + } + + public function reIndex($reloadContent=true) + { + list($documentDetailIds, $languages) = $this->findDetailRecords($this->getId()); + foreach ($documentDetailIds as $documentDetailId => $data) { + if ($reloadContent) { + $this->loadFromArray($data); + } + $fields = $this->fields; + unset($fields['fulltext']); + $values = get_object_vars($this->data); + foreach ($fields as $fieldName => $field) { + if (is_null($values[$fieldName])) { + $values[$fieldName] = ''; + } + } + $this->updateValuesIntoIndex($documentDetailId, $documentDetailId, $fields, $values); + } + } + + protected function update($values=NULL, $comment='') + { + + if (is_null($values)) { + // solo i valori dei campi modificati + $updatedfields = array_intersect_key($this->fields, $this->modifiedFields); + $values = get_object_vars($this->data); + } + else { + $updatedfields = array_intersect_key($this->fields, $values); + } + + $this->updateValuesIntoIndex($this->getDetailId(), $this->getDetailId(), $updatedfields, $values); + + $valArray = array(); + foreach ($values as $fieldName => $value) { + $field = $this->fields[$fieldName]; + if ($field && !$field->isSystemField) { + if (!($field->index & $field::ONLY_INDEX) && !is_null($value) && $value !== '') { + $valArray[$fieldName] = $value; + } + } + } + + $this->updateValues($valArray, $comment); + + return $this->getId(); + } + + protected function updateValues($values, $comment) + { + $identifier = array(self::DOCUMENT_DETAIL_ID => $this->getDetailId()); + + $documentDetail = array( + self::DOCUMENT_DETAIL_TRANSLATED => true, + self::DOCUMENT_DETAIL_MODIFICATION_DATE => new org_glizy_types_DateTime(), + self::DOCUMENT_DETAIL_IS_VISIBLE => $this->isVisible[$this->getLanguageId()] + ); + + if (__Config::get('glizy.dataAccess.serializationMode') == 'json') { + $documentDetail[self::DOCUMENT_DETAIL_OBJECT] = json_encode($values); + } else { + $documentDetail[self::DOCUMENT_DETAIL_OBJECT] = serialize($values); + } + + $types = array( + Type::INTEGER, + Type::INTEGER, + Type::DATETIME, + Type::TEXT + ); + + if (__Config::get('glizy.dataAccess.document.enableComment')) { + $documentDetail[self::DOCUMENT_DETAIL_NOTE] = $comment; + $types[] = Type::TEXT; + } + + return $this->connection->update($this->getDocumentDetailTableName(), $documentDetail, $identifier, $types); + } + + protected function updateValuesIntoIndex($newDetailId, $oldDetailId, $fields, $values) + { + // per ogni campo modificato si va a modificare la corrispondente tabella indice + foreach ($fields as $fieldName => $field) { + if (!$field->virtual && !$field->isSystemField && $field->index != $field::NOT_INDEXED && isset(self::$typeMap[$field->type])) { + $indexFieldType = $this->getIndexFieldType($fieldName); + $tableName = $this->getDocumentIndexTablePrefix() . $indexFieldType . '_tbl'; + $fieldPrefix = self::DOCUMENT_INDEX_FIELD_PREFIX . $indexFieldType; + + $documentIndex = array( + $fieldPrefix.'_FK_document_detail_id' => $oldDetailId, + $fieldPrefix.'_name' => $fieldName + ); + + $types = array( + Type::INTEGER, + Type::STRING + ); + + // cancella dall'indice il vecchio valore + $this->connection->delete($tableName, $documentIndex); + + $documentIndex[$fieldPrefix.'_FK_document_detail_id'] = $newDetailId; + + $value = $values[$fieldName]; + + if (is_array($value)) { + foreach ($value as $v) { + $v = $this->getValueToIndex($field->type, $v, $field->option); + if (!is_null($v)) { + $documentIndex[$fieldPrefix.'_value'] = $v; + $this->connection->insert($tableName, $documentIndex); + } + } + } else { + $value = $this->getValueToIndex($field->type, $value, $field->option); + + if ((!is_null($value) && $value !== '') || $field->type == Type::STRING) { + $documentIndex[$fieldPrefix.'_value'] = $value; + $types[] = $field->type; + if (!self::$indexQueueEnabled) { + $this->connection->insert($tableName, $documentIndex, $types); + } else { + $documentIndex[$fieldPrefix.'_name'] = "'".$documentIndex[$fieldPrefix.'_name']."'"; + $documentIndex[$fieldPrefix.'_value'] = $this->connection->quote($documentIndex[$fieldPrefix.'_value'], $field->type); + self::$indexQueue->insert($tableName, $documentIndex, $types); + } + } + } + } + } + } + + protected function insertDetailOnly($values = NULL, $currentStatus, $newStatus = self::STATUS_DRAFT, $comment='') + { + $evt = array('type' => GLZ_EVT_AR_UPDATE_PRE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + + if (is_null($values)) { + $values = get_object_vars($this->data); + } + + $valArray = array(); + $valArrayIndex = array(); + + // seleziona solo i valori non null o che non siano campi di sistema + foreach ($this->fields as $fieldName => $field) { + if (!$field->isSystemField && !is_null($values[$fieldName]) && $values[$fieldName] !== '') { + if (!($field->index & $field::ONLY_INDEX)) { + $valArray[$fieldName] = $values[$fieldName]; + } + $value = $values[$fieldName]; + $valArrayIndex[$fieldName] = is_string($value) ? trim(strip_tags($value)) : $value; + } + } + + $id = $this->getId(); + + list($documentDetailIds, $languages) = $this->findDetailRecords($id, $currentStatus); + + // verifica se esiste un record di dettaglio per la lingua corrente + if ($languages[$this->getLanguageId()]) { + foreach ($documentDetailIds as $documentDetailId => $data) { + $languageId = $data[self::DOCUMENT_DETAIL_FK_LANGUAGE]; + + // non modifica i record nelle altre lingue che già sono stati tradotti + if ($languageId != $this->getLanguageId() && $data[self::DOCUMENT_DETAIL_TRANSLATED]) { + continue; + } + + $updateOld = false; + + if ($newStatus === self::STATUS_PUBLISHED) { + // setta a OLD tutti i record precedenti + $identifier = array( + self::DOCUMENT_DETAIL_FK_DOCUMENT => $id, + self::DOCUMENT_DETAIL_FK_LANGUAGE => $languageId + ); + $updateOld = true; + } else if ($currentStatus !== self::STATUS_PUBLISHED) { + // setta a OLD lo stato della versione precedente del record da modificare + $identifier = array(self::DOCUMENT_DETAIL_ID => $documentDetailId); + $updateOld = true; + } + + if ($updateOld) { + $oldStatus = array(self::DOCUMENT_DETAIL_STATUS => self::STATUS_OLD); + $this->connection->update($this->getDocumentDetailTableName(), $oldStatus, $identifier); + } + + $newDetailId = $this->insertValues($id, $valArray, $newStatus, $languageId, $comment); + $this->insertValuesIntoIndex($newDetailId, $valArrayIndex); + + if ($languageId == $this->getLanguageId()) { + $this->setId($id); + $this->setDetailId($newDetailId); + $this->modifiedFields = array(); + $returnDetailId = $newDetailId; + } + } + } else { + // si sta inserendo un record di dettaglio per una nuova lingua + $languageId = $this->{self::DOCUMENT_DETAIL_FK_LANGUAGE}; + $newDetailId = $this->insertValues($id, $valArray, $newStatus, $languageId, $comment); + $this->insertValuesIntoIndex($newDetailId, $valArrayIndex); + $this->setId($id); + $this->setDetailId($newDetailId); + $this->modifiedFields = array(); + $returnDetailId = $newDetailId; + } + + $evt = array('type' => GLZ_EVT_AR_UPDATE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + + return $returnDetailId; + } + + private function findDetailRecords($id, $status = null) + { + $qb = $this->createQueryBuilder(array('type' => 'PUBLISHED')); + + // cerca gli id dei record nella tabella dettaglio collegati alla tabella principale del documento da cancellare + $qb->select('*') + ->where($qb->expr()->eq(self::DOCUMENT_ID, ':id')) + ->setParameter(':id', $id); + + if ($status != null) { + $qb->andWhere($qb->expr()->eq(self::DOCUMENT_DETAIL_STATUS, ':status')) + ->setParameter(':status', $status); + } + + if ($this->siteField) { + $qb->andWhere($qb->expr()->eq($this->siteField, ':site')) + ->setParameter(':site', $this->getSiteId()); + } + + $statement = $qb->execute(); + + $documentDetailIds = array(); + $languages = array(); + + while ($data = $statement->fetch()) { + $documentDetailId = $data[self::DOCUMENT_DETAIL_ID]; + $documentDetailIds[$documentDetailId] = $data; + $languages[$data[self::DOCUMENT_DETAIL_FK_LANGUAGE]] = true; + } + + return array($documentDetailIds, $languages); + } + + private function getValueToIndex($type, $value, $fieldOption=null) { + if ($type == org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID && $fieldOption && is_object($value)) { + $field = $fieldOption[org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID]['field']; + if (property_exists($value, $field)) { + return $value->{$field}; + } else { + return null; + } + } + return $value; + } + + // se il record è nuovo viene salvato con lo stato DRAFT + // in caso di update fa diventare il record corrente a OLD se non è PUBLISHED + // e inserisce un nuovo record con lo stato DRAFT + public function saveHistory($values=NULL, $forceNew=false, $comment='') + { + if (__Config::get('glizy.dataAccess.validate')) { + $this->validate($values); + } + + if (!is_null($values)) { + parent::loadFromArray($values); + } + + if ( $this->isNew() || $forceNew ) { + $result = $this->insert($values, self::STATUS_DRAFT, $comment); + } else { + if (!empty($this->modifiedFields) || !is_null($values)) { + $result = $this->insertDetailOnly($values, $this->getStatus(), self::STATUS_DRAFT, $comment); + } + } + + return $this->getId(); + } + + // se il record è nuovo viene salvato con lo stato PUBLISHED + // in caso di update fa diventare i record precedenti a OLD + // e inserisce un nuovo record con lo stato PUBLISHED + public function publish($values = null, $comment='', $forceNew=false) + { + if (__Config::get('glizy.dataAccess.validate')) { + $this->validate($values); + } + + // se il record non è stato salvato, si salva prima di fare publish + if ($this->getStatus() === self::STATUS_DRAFT || !empty($this->modifiedFields) || !is_null($values)) { + // se il record corrente è già self::STATUS_PUBLISHED si crea un nuovo record di dettaglio + if (!$forceNew && !$this->isNew()) { + $this->insertDetailOnly($values, $this->getStatus(), self::STATUS_PUBLISHED, $comment); + } else { + $this->save($values, $forceNew, self::STATUS_PUBLISHED, $comment); + } + } + $this->setStatus(self::STATUS_PUBLISHED); + return $this->getId(); + } + + public function delete($id=NULL) + { + if (is_null($id)) { + $id = $this->getId(); + } else { + $this->setId($id); + } + + $indexTypes = array_unique(array_values(self::$typeMap)); + $indexTypes[] = 'fulltext'; + + $documentDetailIds = $this->findDetailRecords($id); + + foreach ($documentDetailIds as $documentDetailId => $data) { + foreach ($indexTypes as $indexType) { + $tableName = $this->getDocumentIndexTablePrefix() . $indexType . '_tbl'; + $fieldPrefix = self::DOCUMENT_INDEX_FIELD_PREFIX . $indexType; + $indexIdentifier = array($fieldPrefix.'_FK_document_detail_id' => $documentDetailId); + $this->connection->delete($tableName, $indexIdentifier); + } + } + + // cancella i record nella tabella dettaglio collegati alla tabella principale + $detailId = array(self::DOCUMENT_DETAIL_FK_DOCUMENT => $id); + $this->connection->delete($this->getDocumentDetailTableName(), $detailId); + + // cancella il record nella tabella principale + $identifier = array(self::DOCUMENT_ID => $id); + $r = $this->connection->delete($this->getDocumentTableName(), $identifier); + + $evt = array('type' => GLZ_EVT_AR_DELETE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + $this->emptyRecord(); + return $r; + } + + public function createRecordIterator() { + return new org_glizy_dataAccessDoctrine_RecordIteratorDocument($this); + } + + protected function queryBuilderJoinDetail($qb, $tableAlias, $tableDetailAlias, $status, $paramName) + { + $and = $qb->expr()->andX( + $qb->expr()->eq($tableAlias.'.'.self::DOCUMENT_ID, $tableDetailAlias.'.'.self::DOCUMENT_DETAIL_FK_DOCUMENT), + $qb->expr()->eq($tableDetailAlias.'.'.self::DOCUMENT_DETAIL_STATUS, "'".$status."'"), + $qb->expr()->eq($tableDetailAlias.'.'.self::DOCUMENT_DETAIL_FK_LANGUAGE, $paramName) + ); + + $qb->from($this->getDocumentTableName(), $tableAlias) + ->leftJoin($tableAlias, $this->getDocumentDetailTableName(), $tableDetailAlias, $and); + + } + + public function createQueryBuilder($options) + { + $qb = $this->connection->createQueryBuilder(); + + if ($options['type'] == 'PUBLISHED') { + $tableAlias = self::DOCUMENT_TABLE_ALIAS; + $tableDetailAlias = self::DOCUMENT_DETAIL_TABLE_ALIAS; + + $qb->from($this->getDocumentTableName(), $tableAlias) + ->join($tableAlias, $this->getDocumentDetailTableName(), $tableDetailAlias, + $qb->expr()->eq($tableAlias.'.'.self::DOCUMENT_ID, $tableDetailAlias.'.'.self::DOCUMENT_DETAIL_FK_DOCUMENT)); + } else if ($options['type'] == 'PUBLISHED_DRAFT') { + $tableAlias = $options['tableAlias']; + $tableDetailPublishedAlias = $options['tableDetailPublishedAlias']; + $tableDetailDraftAlias = $options['tableDetailDraftAlias']; + + $this->queryBuilderJoinDetail($qb, $tableAlias, $tableDetailPublishedAlias, self::STATUS_PUBLISHED, ':language'); + $this->queryBuilderJoinDetail($qb, $tableAlias, $tableDetailDraftAlias, self::STATUS_DRAFT, ':language'); + $qb->setParameter(':language', $this->getLanguageId()); + + $languageProxy = __ObjectFactory::createObject('org.glizycms.languages.models.proxy.LanguagesProxy'); + $defaultLanguageId = $languageProxy->getDefaultLanguageId(); + + if ($defaultLanguageId != $this->getLanguageId()) { + $this->queryBuilderJoinDetail($qb, $tableAlias, $tableDetailPublishedAlias.'_defaultLanguage', self::STATUS_PUBLISHED, ':defaultLanguage'); + $this->queryBuilderJoinDetail($qb, $tableAlias, $tableDetailDraftAlias.'_defaultLanguage', self::STATUS_DRAFT, ':defaultLanguage'); + $qb->setParameter(':defaultLanguage', $defaultLanguageId); + } + } + + return $qb; + } + + public static function enableIndexQueue() + { + self::$indexQueueEnabled = true; + } + + public static function executeIndexQueue() + { + self::$indexQueue->execute(); + } + + + private function loadSequenceName() + { + $this->sequenceNameLoaded = true; + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($this->connection); + $sequenceName = $sm->getSequenceName($this->getDocumentTableName()); + $this->setSequenceName($sequenceName); + + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($this->connection); + $detailSequenceName = $sm->getSequenceName($this->getDocumentDetailTableName()); + $this->setDetailSequenceName($detailSequenceName); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordException.php b/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordException.php new file mode 100755 index 0000000..3c6ae59 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordException.php @@ -0,0 +1,47 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_dataAccessDoctrine_ActiveRecordException extends Exception +{ + public static function getFailed($tableName, $field) + { + return new self('Undefined property via __get(), table: '. $tableName .' field: '. $field); + } + + public static function setFailed($tableName, $field) + { + return new self('Undefined property via __set(), table: '. $tableName .' field: '. $field); + } + + public static function primaryKeyNotDefined($tableName) + { + return new self('Undefined primary key on table '. $tableName); + } + + public static function detailPrimaryKeyNotDefined($tableName) + { + return new self('Undefined primary key on detail table '. $tableName); + } + + public static function primaryKeyAlreadyDefined($tableName) + { + return new self('Primary key is already defined on table '. $tableName); + } + + public static function detailPrimaryKeyAlreadyDefined($tableName) + { + return new self('Detail primary key is already defined on table '. $tableName); + } + + public static function undefinedField($tableName, $field) + { + return new self('Undefined field "'.$field.'" in model "'. $tableName.'"'); + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordSimpleDocument.php b/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordSimpleDocument.php new file mode 100755 index 0000000..43f662d --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/ActiveRecordSimpleDocument.php @@ -0,0 +1,404 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use Doctrine\DBAL\Types\Type; + +class org_glizy_dataAccessDoctrine_ActiveRecordSimpleDocument extends org_glizy_dataAccessDoctrine_ActiveRecord +{ + const DOCUMENT_TABLE_NAME = 'simple_documents_tbl'; + const DOCUMENT_TABLE_ID = 'simple_document_id'; + const DOCUMENT_TABLE_TYPE = 'simple_document_type'; + const DOCUMENT_FK_SITE_ID = 'simple_document_FK_site_id'; + const DOCUMENT_TABLE_OBJECT = 'simple_document_object'; + const DOCUMENT_INDEX_TABLE_PREFIX = 'simple_documents_index_'; + const DOCUMENT_INDEX_FIELD_PREFIX = 'simple_document_index_'; + const DOCUMENT_BASE_PREFIX = 'simple_document_'; + + protected $type; + protected static $typeMap = array(Type::INTEGER => 'int', + Type::SMALLINT => 'int', + Type::BIGINT => 'int', + Type::STRING => 'text', + Type::TEXT => 'text', + Type::TARRAY => 'text', + Type::DATE => 'date', + Type::DATETIME => 'datetime', + Type::TIME => 'time'); + + function __construct($connectionNumber=0) + { + parent::__construct($connectionNumber); + + $this->addField(new org_glizy_dataAccessDoctrine_SystemField( + self::DOCUMENT_TABLE_ID, + Doctrine\DBAL\Types\Type::INTEGER, + 10, + true, + null, + NULL + ) + ); + + $this->addField(new org_glizy_dataAccessDoctrine_SystemField( + self::DOCUMENT_TABLE_TYPE, + Doctrine\DBAL\Types\Type::STRING, + 255, + false, + null, + 0, + true, + false, + '', + org_glizy_dataAccessDoctrine_DbField::NOT_INDEXED + ) + ); + + if (__Config::get('MULTISITE_ENABLED')) { + $this->addField(new org_glizy_dataAccessDoctrine_SystemField( + self::DOCUMENT_FK_SITE_ID, + Doctrine\DBAL\Types\Type::INTEGER, + 10, + false, + null, + NULL + ) + ); + } + } + + public function addField(org_glizy_dataAccessDoctrine_DbField $field ) + { + parent::addField($field); + + if ($field->name == self::DOCUMENT_FK_SITE_ID) { + $this->setSiteField(self::DOCUMENT_FK_SITE_ID); + } + } + + public function getType() + { + return $this->{self::DOCUMENT_TABLE_TYPE}; + } + + public function setType($type) + { + $this->type = $type; + $this->{self::DOCUMENT_TABLE_TYPE} = $type; + } + + function getSequenceName() + { + if (!$this->sequenceNameLoaded) { + $this->loadSequenceName(); + } + + return $this->sequenceName; + } + + public function getDocumentTableName() + { + return $this->tablePrefix.self::DOCUMENT_TABLE_NAME; + } + + function getDocumentTableIdName() + { + return self::DOCUMENT_TABLE_ID; + } + + function getDocumentIndexTablePrefix() + { + return $this->tablePrefix.self::DOCUMENT_INDEX_TABLE_PREFIX; + } + + function getDocumentIndexFieldPrefix() + { + return self::DOCUMENT_INDEX_FIELD_PREFIX; + } + + function getIndexFieldType($fieldName) + { + $field = $this->fields[$fieldName]; + + if ($field->index == $field::FULLTEXT) { + return 'fulltext'; + } else { + $type = $this->fields[$fieldName]->type; + return self::$typeMap[$type]; + } + } + + public function load($id) + { + if (empty($id)) { + $this->emptyRecord(); + return false; + } + + $qb = $this->createQueryBuilder(); + + $qb->select('*') + ->where($qb->expr()->eq($this->primaryKeyName, ':id')) + ->setParameter(':id', $id); + + if ($this->siteField) { + $qb->andWhere($qb->expr()->eq($this->siteField, ':site')) + ->setParameter(':site', $this->getSiteId()); + } + + $r = $qb->execute()->fetch(); + + if ($r) { + $this->loadFromArray($r); + return true; + } else { + $this->emptyRecord(); + return false; + } + } + + function loadFromArray($values) + { + if (!empty($values)) { + $this->emptyRecord(); + + if (__Config::get('glizy.dataAccess.serializationMode') == 'json') { + $this->data = json_decode($values[self::DOCUMENT_TABLE_OBJECT]); + } + else { + $data = unserialize($values[self::DOCUMENT_TABLE_OBJECT]); + + // TODO rimuovere quando la migrazine dei dati da serializzazione php a json è completata + if (is_array($data)) { + foreach ($data as $k => $v) { + $this->data->$k = $v; + } + } + else { + $this->data = $data; + } + } + + if (!is_object($this->data)) { + $this->data = new StdClass; + } + + foreach ($values as $k => $v) { + if (strpos($k, self::DOCUMENT_BASE_PREFIX)===false) { + $this->virtualData->$k = $v; + } + } + + $this->setId($values[self::DOCUMENT_TABLE_ID]); + if ($values[self::DOCUMENT_TABLE_TYPE]) $this->setType($values[self::DOCUMENT_TABLE_TYPE]); + } + } + + public function emptyRecord() + { + parent::emptyRecord(); + $this->setType($this->type); + } + + protected function insert($values = NULL) + { + // sequenceName deve essere letto prima della insert + // altrimenti può creare problemi con la insert del dettaglio + $sequenceName = $this->getSequenceName(); + if (is_null($values)) { + $values = get_object_vars($this->data); + } + + $valArray = array(); + $valArrayIndex = array(); + + // seleziona solo i valori non null o che non sia la chiave primaria dall'array dei valori + foreach ($this->fields as $fieldName => $field) { + if (!$field->isSystemField && !is_null($values[$fieldName]) && $values[$fieldName] != '') { + if (!($field->index & $field::ONLY_INDEX)) { + $valArray[$fieldName] = $values[$fieldName]; + } + $valArrayIndex[$fieldName] = $values[$fieldName]; + } + } + + $document = array(self::DOCUMENT_TABLE_TYPE => $this->type); + + if (__Config::get('glizy.dataAccess.serializationMode') == 'json') { + $document[self::DOCUMENT_TABLE_OBJECT] = json_encode($valArray); + } + else { + $document[self::DOCUMENT_TABLE_OBJECT] = serialize($valArray); + } + + if ($this->siteField) { + $document[$this->siteField] = $this->getSiteId(); + } + + $r = $this->connection->insert($this->getDocumentTableName(), $document); + + if ($r != false) { + $id = $this->connection->lastInsertId($sequenceName); + $this->insertValuesIntoIndex($id, $valArrayIndex); + $this->setId($id); + $this->modifiedFields = array(); + return $this->getId(); + } + else { + return false; + } + } + + protected function insertValuesIntoIndex($id, $values) + { + foreach ($values as $fieldName => $value) + { + $field = $this->fields[$fieldName]; + + if (!$field->virtual && !$field->isSystemField && $field->index != $field::NOT_INDEXED && isset(self::$typeMap[$field->type])) { + $indexFieldType = $this->getIndexFieldType($fieldName); + $tableName = $this->getDocumentIndexTablePrefix() . $indexFieldType . '_tbl'; + $fieldPrefix = self::DOCUMENT_INDEX_FIELD_PREFIX . $indexFieldType; + + $documentIndex = array( + $fieldPrefix.'_FK_simple_document_id' => $id, + $fieldPrefix.'_name' => $fieldName, + $fieldPrefix.'_value' => $value, + ); + + $types = array( + Type::INTEGER, + Type::STRING, + $field->type + ); + + $this->connection->insert($tableName, $documentIndex, $types); + } + } + } + + protected function update($values=NULL) + { + if (is_null($values)) { + // solo i valori dei campi modificati + $updatedfields = array_intersect_key($this->fields, $this->modifiedFields); + $values = get_object_vars($this->data); + } + else { + $updatedfields = array_intersect_key($this->fields, $values); + } + + $this->updateValuesIntoIndex($updatedfields, $values); + + // rimuove la chiave primaria dall'array dei valori + $values = array_diff_key($values, array_flip(array($this->primaryKeyName))); + + // seleziona solo i valori non null o che non siano campi di sistema + foreach ($updatedfields as $fieldName => $field) { + if (!$field->isSystemField && !is_null($values[$fieldName])) { + $valArray[$fieldName] = $values[$fieldName]; + } + } + + if (__Config::get('glizy.dataAccess.serializationMode') == 'json') { + $document[self::DOCUMENT_TABLE_OBJECT] = json_encode($values); + } + else { + $document[self::DOCUMENT_TABLE_OBJECT] = serialize($values); + } + + $identifier = array($this->primaryKeyName => $this->getId()); + + $this->connection->update($this->getDocumentTableName(), $document, $identifier); + + return $this->getId(); + } + + protected function updateValuesIntoIndex($fields, $values) + { + // per ogni campo modificato si va a modificare la corrispondente tabella indice + foreach ($fields as $fieldName => $field) { + if (!$field->virtual && !$field->isSystemField && $field->index != $field::NOT_INDEXED && isset(self::$typeMap[$field->type])) { + $indexFieldType = $this->getIndexFieldType($fieldName); + $tableName = $this->getDocumentIndexTablePrefix() . $indexFieldType . '_tbl'; + $fieldPrefix = self::DOCUMENT_INDEX_FIELD_PREFIX . $indexFieldType; + + $indexIdentifier = array( + $fieldPrefix.'_FK_simple_document_id' => $this->getId(), + $fieldPrefix.'_name' => $fieldName + ); + + // cancella dall'indice il vecchio valore + $this->connection->delete($tableName, $indexIdentifier); + + $value = $values[$fieldName]; + + // inserisce nell'indice solo se il valore è non nullo + if (!is_null($value) && $value !== '') { + $documentIndex = array_merge($indexIdentifier, array($fieldPrefix.'_value' => $value)); + + $types = array( + Type::INTEGER, + Type::STRING, + $field->type + ); + + $this->connection->insert($tableName, $documentIndex, $types); + } + } + } + } + + public function delete($id=NULL) + { + if (is_null($id)) { + $id = $this->getId(); + } + + $indexTypes = array_unique(array_values(self::$typeMap)); + $indexTypes[] = 'fulltext'; + + // cancella i campi nelle tabelle indice collegate alla tabella principale per l'id fornito + foreach ($indexTypes as $indexType) { + $tableName = $this->getDocumentIndexTablePrefix() . $indexType . '_tbl'; + $fieldPrefix = self::DOCUMENT_INDEX_FIELD_PREFIX . $indexType; + $indexIdentifier = array($fieldPrefix.'_FK_simple_document_id' => $id); + $this->connection->delete($tableName, $indexIdentifier); + } + + $evt = array('type' => GLZ_EVT_AR_DELETE.'@'.$this->getClassName(), 'data' => $this); + $this->dispatchEvent($evt); + $this->emptyRecord(); + + $identifier = array($this->primaryKeyName => $id); + + return $this->connection->delete($this->getDocumentTableName(), $identifier); + } + + public function createRecordIterator() { + return new org_glizy_dataAccessDoctrine_RecordIteratorSimpleDocument($this); + } + + public function createQueryBuilder($addFrom=true, $tableAlias='t1') { + $qb = $this->connection->createQueryBuilder(); + + if ($addFrom) { + $qb->from($this->getDocumentTableName(), $tableAlias); + } + + return $qb; + } + + private function loadSequenceName() + { + $this->sequenceNameLoaded = true; + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($this->connection); + $sequenceName = $sm->getSequenceName($this->getDocumentTableName()); + $this->setSequenceName($sequenceName); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/Connection.php b/src/core/classes/org/glizy/dataAccessDoctrine/Connection.php new file mode 100644 index 0000000..2a08ed2 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/Connection.php @@ -0,0 +1,161 @@ +<?php + +use Doctrine\DBAL\Driver, + Doctrine\DBAL\Configuration, + Doctrine\Common\EventManager; + +// classe Connection che quota gli identificatori nelle query +class org_glizy_dataAccessDoctrine_Connection extends \Doctrine\DBAL\Connection +{ + protected static $mapIdentifier = array(); + + /** + * Initializes a new instance of the Connection class. + * + * @param array $params The connection parameters. + * @param Driver $driver + * @param Configuration $config + * @param EventManager $eventManager + */ + public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null) + { + parent::__construct($params, $driver, $config, $eventManager); + $this->_expr = new org_glizy_dataAccessDoctrine_Query_Expression_ExpressionBuilder($this); + } + + /** + * Executes an SQL DELETE statement on a table. + * + * @param string $tableName The name of the table on which to delete. + * @param array $identifier The deletion criteria. An associative array containing column-value pairs. + * @return integer The number of affected rows. + */ + public function delete($tableName, array $identifier) + { + $this->connect(); + + $criteria = array(); + + foreach (array_keys($identifier) as $columnName) { + $criteria[] = $this->quoteIdentifier($columnName) . ' = ?'; + } + + $query = 'DELETE FROM ' . $this->quoteIdentifier($tableName) . ' WHERE ' . implode(' AND ', $criteria); + + return $this->executeUpdate($query, array_values($identifier)); + } + + /** + * Executes an SQL UPDATE statement on a table. + * + * @param string $tableName The name of the table to update. + * @param array $data + * @param array $identifier The update criteria. An associative array containing column-value pairs. + * @param array $types Types of the merged $data and $identifier arrays in that order. + * @return integer The number of affected rows. + */ + public function update($tableName, array $data, array $identifier, array $types = array()) + { + $this->connect(); + $set = array(); + foreach ($data as $columnName => $value) { + $set[] = $this->quoteIdentifier($columnName) . ' = ?'; + } + + $params = array_merge(array_values($data), array_values($identifier)); + + $quotedIdentifier = $this->quoteIdentifiers(array_keys($identifier)); + + $sql = 'UPDATE ' . $this->quoteIdentifier($tableName) . ' SET ' . implode(', ', $set) + . ' WHERE ' . implode(' = ? AND ', $quotedIdentifier) + . ' = ?'; + + return $this->executeUpdate($sql, $params, $types); + } + + /** + * Inserts a table row with specified data. + * + * @param string $tableName The name of the table to insert data into. + * @param array $data An associative array containing column-value pairs. + * @param array $types Types of the inserted data. + * @return integer The number of affected rows. + */ + public function insert($tableName, array $data, array $types = array()) + { + $this->connect(); + + // column names are specified as array keys + $cols = array(); + $placeholders = array(); + + foreach ($data as $columnName => $value) { + $cols[] = $this->quoteIdentifier($columnName); + $placeholders[] = '?'; + } + + $query = 'INSERT INTO ' . $this->quoteIdentifier($tableName) + . ' (' . implode(', ', $cols) . ')' + . ' VALUES (' . implode(', ', $placeholders) . ')'; + + return $this->executeUpdate($query, array_values($data), $types); + } + + /** + * Quote a string so it can be safely used as a table or column name, even if + * it is a reserved name. + * + * Delimiting style depends on the underlying database platform that is being used. + * + * NOTE: Just because you CAN use quoted identifiers does not mean + * you SHOULD use them. In general, they end up causing way more + * problems than they solve. + * + * @param string $str The name to be quoted. + * @return string The quoted name. + */ + public function quoteIdentifier($str) + { + if (isset(self::$mapIdentifier[$str])) { + return self::$mapIdentifier[$str]; + } + + $upStr = strtoupper($str); + + if ($str == '*' || $str[0] == ':' || $str[0] == "'" || strpos($upStr, 'DISTINCT') === 0 || strpos($upStr, 'COUNT') === 0) { + self::$mapIdentifier[$str] = $str; + } + else if (strpos($str, '.') !== false) { + $parts = array_map(array($this, "quoteIdentifier"), explode(".", $str)); + self::$mapIdentifier[$str] = implode(".", $parts); + } + else { + self::$mapIdentifier[$str] = parent::quoteIdentifier($str); + } + + return self::$mapIdentifier[$str]; + } + + /** + * @param array $identifiers The array of names to be quoted. + * @return array The quoted names. + */ + public function quoteIdentifiers($identifiers) + { + $result = array(); + foreach ($identifiers as $s) { + $result[] = $this->quoteIdentifier($s); + } + return $result; + } + + /** + * Create a new instance of a SQL query builder. + * + * @return \Doctrine\DBAL\Query\QueryBuilder + */ + public function createQueryBuilder() + { + return new org_glizy_dataAccessDoctrine_Query_QueryBuilder($this); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/DataAccess.php b/src/core/classes/org/glizy/dataAccessDoctrine/DataAccess.php new file mode 100755 index 0000000..9535080 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/DataAccess.php @@ -0,0 +1,519 @@ +<?php + +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ +class org_glizy_dataAccessDoctrine_DataAccess +{ + + /** + * Static array with connections + */ + /** @var \Doctrine\DBAL\Connection[] $connection */ + private static $connections = array(); + private static $transactionStack = array(); + private static $transactionStackCounter = 0; + + private static $defaultTypesOverridden = false; + private static $cacheDriver = null; + private static $isLibLoaded = false; + + public function initCache() + { + + $cacheDir = __Paths::get('CACHE') . 'doctrine'; + @mkdir($cacheDir); + if (!self::$isLibLoaded) { + self::loadLibrary(); + } + self::$cacheDriver = new \Doctrine\Common\Cache\PhpFileCache($cacheDir); + } + + /** + * @return \Doctrine\Common\Cache\PhpFileCache + */ + public function getCache() + { + + return self::$cacheDriver; + } + + /** + * Creates a connection object based on the config values. + * This method returns a Doctrine\DBAL\Connection which wraps the underlying + * driver connection. + * + * @param integer $n connection number + * @return Doctrine\DBAL\Connection + */ + public static function getConnection($n = 0) + { + + if (!self::$isLibLoaded) { + self::loadLibrary(); + } + + if (!isset( self::$connections['__' . $n] )) { + // se non è settato a true si effettua l'override dei tipi standard di doctrine + if (!self::$defaultTypesOverridden) { + \Doctrine\DBAL\Types\Type::overrideType(\Doctrine\DBAL\Types\Type::BOOLEAN, 'org_glizy_dataAccessDoctrine_types_Boolean'); + \Doctrine\DBAL\Types\Type::overrideType(\Doctrine\DBAL\Types\Type::TARRAY, 'org_glizy_dataAccessDoctrine_types_Array'); + \Doctrine\DBAL\Types\Type::overrideType(\Doctrine\DBAL\Types\Type::TIME, 'org_glizy_dataAccessDoctrine_types_Time'); + \Doctrine\DBAL\Types\Type::overrideType(\Doctrine\DBAL\Types\Type::DATE, 'org_glizy_dataAccessDoctrine_types_Date'); + \Doctrine\DBAL\Types\Type::overrideType(\Doctrine\DBAL\Types\Type::DATETIME, 'org_glizy_dataAccessDoctrine_types_DateTime'); + \Doctrine\DBAL\Types\Type::overrideType(\Doctrine\DBAL\Types\Type::DATETIMETZ, 'org_glizy_dataAccessDoctrine_types_DateTimeTz'); + \Doctrine\DBAL\Types\Type::addType(org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID, 'org_glizy_dataAccessDoctrine_types_ArrayID'); + self::$defaultTypesOverridden = true; + + } + + $sufix = $n == 0 ? '' : '#' . $n; + + $dbType = __Config::get('DB_TYPE' . $sufix); + + switch ($dbType) { + case 'mysql': + $params = array( + 'driver' => 'pdo_mysql', + 'host' => __Config::get('DB_HOST' . $sufix), + 'user' => __Config::get('DB_USER' . $sufix), + 'password' => __Config::get('DB_PSW' . $sufix), + 'dbname' => __Config::get('DB_NAME' . $sufix), + 'driverOptions' => array() + ); + + $socket = __Config::get('DB_SOCKET' . $sufix); + if ($socket) { + $params['unix_socket'] = $socket; + } + if (__Config::get('DB_MYSQL_BUFFERED_QUERY' . $sufix)) { + $params['driverOptions'][PDO::MYSQL_ATTR_USE_BUFFERED_QUERY] = true; + } + if (__Config::get('DB_ATTR_PERSISTENT' . $sufix)) { + $params['driverOptions'][PDO::ATTR_PERSISTENT] = true; + } + + $charset = __Config::get('CHARSET'); + if ($charset) { + if (strtolower($charset) == 'utf-8') { + $params['charset'] = 'utf8'; + $params['driverOptions'][PDO::MYSQL_ATTR_INIT_COMMAND] = "SET NAMES utf8"; + } else { + $params['charset'] = $charset; + } + } + + break; + + case 'sqlite': + $params = array( + 'driver' => 'pdo_sqlite', + 'user' => __Config::get('DB_USER' . $sufix), + 'password' => __Config::get('DB_PSW' . $sufix), + ); + $path = __Config::get('DB_NAME' . $sufix); + if ($path == 'memory:') { + $params['memory'] = true; + } else { + $params['path'] = $path; + } + break; + + case 'pgsql': + $params = array( + 'driver' => 'pdo_pgsql', + 'host' => __Config::get('DB_HOST' . $sufix), + 'user' => __Config::get('DB_USER' . $sufix), + 'password' => __Config::get('DB_PSW' . $sufix), + 'dbname' => __Config::get('DB_NAME' . $sufix) + ); + break; + } + + if (__Config::get('DB_PORT' . $sufix)) { + $params['port'] = __Config::get('DB_PORT' . $sufix); + } + + $params['wrapperClass'] = 'org_glizy_dataAccessDoctrine_Connection'; + + + $checkDbConnection = __Config::get('DB_CHECK_CONNECTION' . $sufix)===true; + $attempt = 0; + $lastException = null; + while ($attempt < 3) { + try { + $conn = \Doctrine\DBAL\DriverManager::getConnection($params); + if ($checkDbConnection) { + $conn->connect(); + } + self::$connections['__' . $n] = $conn; + break; + } catch (\PDOException $e) { + $attempt++; + $lastException = $e; + } + } + if (!isset(self::$connections['__' . $n])) { + $eventInfo = array('type' => GLZ_LOG_EVENT, + 'data' => array( + 'level' => GLZ_LOG_ERROR, + 'group' => 'glizy.sql', + 'message' => array('errorMessage' => $e->getMessage(), 'errorCode' => $e->getCode(), 'attempt' => $attempt) + )); + $evt = org_glizy_ObjectFactory::createObject( 'org.glizy.events.Event', org_glizy_ObjectValues::get('org.glizy', 'application'), $eventInfo ); + org_glizy_events_EventDispatcher::dispatchEvent( $evt ); + throw new Exception($lastException->getMessage(), $lastException->getCode(), $lastException); + } else { + $platform = self::$connections['__' . $n]->getDatabasePlatform(); + $platform->registerDoctrineTypeMapping('enum', 'string'); + } + + } + + return self::$connections['__' . $n]; + } + + /** + * @param string $name + * @param string $className + * @throws \Doctrine\DBAL\DBALException + */ + public static function addType($name, $className) + { + + \Doctrine\DBAL\Types\Type::addType($name, $className); + } + + /** + * @param string $name + * @return \Doctrine\DBAL\Types\Type + * @throws \Doctrine\DBAL\DBALException + */ + public static function getType($name) + { + + return \Doctrine\DBAL\Types\Type::getType($name); + } + + /** + * Close a connection + * @param integer $n connection number + */ + public static function close($n = 0) + { + + $conn = self::getConnection($n); + if ($conn->getTransactionNestingLevel()) { + self::stackDump(false); + } + $conn->close(); + unset( self::$connections['__' . $n] ); + } + + /** + * Close all connections + */ + public static function closeAll() + { + self::transactionCheck(); + foreach (self::$connections as $connection) { + $connection->close(); + } + self::$connections = array(); + } + + /** + * Get the table prefix for a connection, the table prefix is defined in config file + * @param integer $n connection number + * @return string table prefix + */ + public static function getTablePrefix($n = 0) + { + + return org_glizy_Config::get($n == 0 ? 'DB_PREFIX' : 'DB_PREFIX#' . $n); + } + + /** + * @param int $n + */ + public static function enableLogging($n = 0) + { + + $conn = self::getConnection($n); + $config = $conn->getConfiguration(); + $config->setSQLLogger(new org_glizy_dataAccessDoctrine_logging_EchoSQLLogger()); + } + + /** + * @param int $n + */ + public static function disableLogging($n = 0) + { + + $conn = self::getConnection($n); + $config = $conn->getConfiguration(); + $config->setSQLLogger(null); + } + + /** + * @param int $n + * @param string $fileName + * @param string $dbName + * @param array $options + * @throws \Doctrine\DBAL\DBALException + */ + function importSqlFile($n, $fileName, $dbName, $options = null) + { + + $conn = self::getConnection(); + $sm = $conn->getSchemaManager(); + $sm->createDatabase($dbName); + unset( $options ); + + $conn = self::getConnection($n); + + $lines = file($fileName); + $sql = ''; + + foreach ($lines as $line) { + if (preg_match('/^--|^\/\*|^\s*$/m', $line)) { + continue; + } + + $sql .= $line; + + if (preg_match('/;\n/', $line)) { + $conn->exec($sql); + $sql = ''; + } + } + + if (strpos($sql, ';')) { + $conn->exec($sql); + } + + self::close($n); + } + + /** + * @param string $dbName + */ + public function dropDatabase($dbName) + { + + $conn = self::getConnection(); + $sm = $conn->getSchemaManager(); + $sm->dropDatabase($dbName); + } + + /** + * @param string $tableName + * @param int $n + * @throws \Doctrine\DBAL\DBALException + */ + public function truncateTable($tableName, $n = 0) + { + + $conn = self::getConnection($n); + $platform = $conn->getDatabasePlatform(); + $query = $platform->getTruncateTableSQL($tableName); + $conn->executeQuery($query); + } + + // TODO: astrarre per tipo db + /** + * @param string $schema + * @param int $n + * @throws \Doctrine\DBAL\DBALException + */ + public function changeSchema($schema, $n = 0) + { + + $conn = self::getConnection($n); + $conn->executeQuery('SET search_path = "' . $schema . '", public;'); + } + + /** + * @param int $n + * + * @return bool + */ + public static function beginTransaction($n = 0) + { + + $conn = self::getConnection($n); + + self::pushStack('beginTransaction', $conn->getTransactionNestingLevel()); + + try { + $conn->beginTransaction(); + return true; + } catch (Exception $e) { + return false; + } + + } + + /** + * @param int $n + * + * @return bool + */ + public static function commit($n = 0) + { + + $conn = self::getConnection($n); + + self::pushStack('commit', $conn->getTransactionNestingLevel()); + + try { + $conn->commit(); + return true; + } catch (Exception $e) { + return false; + } + } + + + /** + * @param int $n + * + * @return bool + */ + public static function rollBack($n = 0) + { + + $conn = self::getConnection($n); + + self::pushStack('rollBack', $conn->getTransactionNestingLevel()); + + // Il rollback va fatto solo se ho aperta una transazione + if ($conn->getTransactionNestingLevel()) { + self::stackDump(true); + + try { + $conn->rollBack(); + $result = true; + } catch (Exception $e) { + $result = false; + } + } + + if (!$result) { + /** @var org_glizy_application_Application $application */ + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $application->log('Error during rollback', GLZ_LOG_ERROR, 'glizy.sql'); + } + + return $result; + + } + + /** + * @return bool + */ + public static function transactionCheck() + { + $error = false; + + foreach (self::$connections as $connection) { + if ($connection->getTransactionNestingLevel()) { + $error = true; + + } + } + + if ($error) { + self::stackDump(false); + } + + return $error; + } + + /** + * @param string $function + * @param int $counter + * @return bool + */ + public static function pushStack($function, $counter=0) + { + + $data = array( + 'caller' => self::getCallingName(), + 'counter' => $counter, + 'function' => $function + ); + self::$transactionStack[self::$transactionStackCounter] = $data; + self::$transactionStackCounter ++; + + return true; + } + + /** + * @return string + */ + public static function getCallingName() + { + + $trace = debug_backtrace(); + $caller = $trace[3]; + + if (isset( $caller['class'] )) { + $result = $caller['class'] . '::' . $caller['function']; + } else { + $result = $caller['function']; + } + + return $result; + } + + /** + * @param bool $rollback + */ + public static function stackDump($rollback = false) + { + + $stackReport = array(); + $stackReport['errorInfo'] = "Transaction report"; + $stackReport['stack'] = serialize(self::$transactionStack); + if ($rollback) { + $stackReport['cond'] = 'rollback'; + } else { + $stackReport['cond'] = 'open transaction'; + } + /** @var org_glizy_application_Application $application */ + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $application->log($stackReport, GLZ_LOG_ERROR, 'glizy.sql'); + } + + private static function loadLibrary() + { + + self::$isLibLoaded = true; + require_once( GLZ_LIBS_DIR . '/Doctrine/Common/ClassLoader.php' ); + + $classLoader = new \Doctrine\Common\ClassLoader('Doctrine\Common', GLZ_LIBS_DIR); + $classLoader->register(); + + $classLoader = new \Doctrine\Common\ClassLoader('Doctrine\DBAL', GLZ_LIBS_DIR); + $classLoader->register(); + } +} + +/** + * @param bool $state + * @param int $n + */ +function glz_DBdebug($state = true, $n = 0) +{ + + if ($state) { + org_glizy_dataAccessDoctrine_DataAccess::enableLogging($n); + } else { + org_glizy_dataAccessDoctrine_DataAccess::disableLogging($n); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/DbField.php b/src/core/classes/org/glizy/dataAccessDoctrine/DbField.php new file mode 100755 index 0000000..adc714b --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/DbField.php @@ -0,0 +1,78 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + + +class org_glizy_dataAccessDoctrine_DbField +{ + const NOT_INDEXED = 0; // non indicizzato + const INDEXED = 1; // indicizzato + const FULLTEXT = 2; // indice fulltext + const ONLY_INDEX = 16; // indice fulltext + + public $name; + public $type; + public $size; + public $key; + public $validator; // viene settato dal compilatore del model + public $defaultValue; + public $readFormat; + public $virtual; + public $description; // con la label del campo si usa questo + public $index; // tre costanti non indicizzato, indicizzato, fulltext + public $option; + public $isSystemField = false; + + function __construct($name, $type, $size, $key, $validator, $defaultValue, $readFormat=true, $virtual=false, $description='', $index=self::INDEXED, $option=null) + { + $this->name = $name; + $this->type = $type; + $this->size = $size; + $this->key = $key; + $this->validator = $validator; + $this->defaultValue = $defaultValue; + $this->readFormat = $readFormat; + $this->virtual = $virtual; + $this->description = $description !== '' ? $description : $name; + $this->index = $index; + $this->option = $option; + + + if ( $this->type == org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID && + (is_null($this->option) || !isset($this->option[org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID])) ) { + // backward compatibility if the ARRAY_ID field don't have options + // set the default values + $this->option = array( org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID => array( + 'type' => \Doctrine\DBAL\Types\Type::INTEGER, + 'field' => 'id' + )); + } + } + + public function format($value, $connection) + { + return $this->readFormat ? $connection->convertToPHPValue($value, $this->type) : $value; + } + + /** + * @param org_glizy_validators_AbstractValidator $validator + */ + public function addValidator($validator) + { + if (!$this->validator || (!$this->validator instanceof org_glizy_validators_CompositeValidator)) { + $composite = new org_glizy_validators_CompositeValidator(); + if ($this->validator ) { + $composite->add($this->validator); + } + $this->validator = $composite; + } + $this->validator->add($validator); + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/IndexQueue.php b/src/core/classes/org/glizy/dataAccessDoctrine/IndexQueue.php new file mode 100755 index 0000000..c8f6390 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/IndexQueue.php @@ -0,0 +1,44 @@ +<?php +class org_glizy_dataAccessDoctrine_IndexQueue +{ + protected $queryLength = 50000; + protected $connection; + protected $query = array(); + + public function __construct($connection) + { + $this->connection = $connection; + } + + public function insert($tableName, array $data, array $types = array()) + { + if (!isset($this->query[$tableName])) { + $tableNameQuoted = $this->connection->quoteIdentifier($tableName); + $cols = $this->connection->quoteIdentifiers(array_keys($data)); + + $sql = 'INSERT INTO ' . $tableNameQuoted + . ' (' . implode(', ', $cols) . ') VALUES '; + + $this->query[$tableName] = array(); + $this->query[$tableName]['insert'] = $sql; + $this->query[$tableName]['insertLength'] = strlen($sql); + $this->query[$tableName]['values'] = array(); + } + + $part = '(' . implode(', ', array_values($data)) . ')'; + if ($this->query[$tableName]['insertLength']+strlen($part)>$this->queryLength) { + $this->execute(); + } + $this->query[$tableName]['values'][] = $part; + } + + public function execute() + { + foreach ($this->query as $tableName => $q) { + $sql = $q['insert']; + $sql .= implode(', ', $q['values']); + $this->connection->executeQuery($sql); + $this->query[$tableName]['values'] = array(); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/Query/Expression/ExpressionBuilder.php b/src/core/classes/org/glizy/dataAccessDoctrine/Query/Expression/ExpressionBuilder.php new file mode 100644 index 0000000..2124c9e --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/Query/Expression/ExpressionBuilder.php @@ -0,0 +1,79 @@ +<?php + +use \Doctrine\DBAL\Connection, + \Doctrine\DBAL\Query\Expression\CompositeExpression; + +class org_glizy_dataAccessDoctrine_Query_Expression_ExpressionBuilder extends \Doctrine\DBAL\Query\Expression\ExpressionBuilder +{ + protected $conn = null; + + /** + * Initializes a new <tt>ExpressionBuilder</tt>. + * + * @param \Doctrine\DBAL\Connection $connection DBAL Connection + */ + public function __construct(Connection $connection) + { + parent::__construct($connection); + $this->conn = $connection; + } + + /** + * Creates a comparison expression. + * + * @param mixed $x Left expression + * @param string $operator One of the ExpressionBuilder::* constants. + * @param mixed $y Right expression + * @return string + */ + public function comparison($x, $operator, $y, $cast = true) + { + if (strtoupper($operator) == 'LIKE') { + return $this->like($x, $y, $cast); + } + + return $this->conn->quoteIdentifier($x) . ' ' . $operator . ' ' . $this->conn->quoteIdentifier($y); + } + + /** + * Creates an IS NULL expression with the given arguments. + * + * @param string $x Field in string format to be restricted by IS NULL + * + * @return string + */ + public function isNull($x) + { + return $this->conn->quoteIdentifier($x) . ' IS NULL'; + } + + /** + * Creates an IS NOT NULL expression with the given arguments. + * + * @param string $x Field in string format to be restricted by IS NOT NULL + * + * @return string + */ + public function isNotNull($x) + { + return $this->conn->quoteIdentifier($x) . ' IS NOT NULL'; + } + + /** + * Creates a LIKE() comparison expression with the given arguments. + * + * @param string $x Field in string format to be inspected by LIKE() comparison. + * @param mixed $y Argument to be used in LIKE() comparison. + * + * @return string + */ + public function like($x, $y, $cast = true) + { + if ($cast) { + return 'CAST('.$this->conn->quoteIdentifier($x) . ' AS CHAR(255)) LIKE ' . $this->conn->quoteIdentifier($y); + } + else { + return $this->conn->quoteIdentifier($x) . ' LIKE ' . $this->conn->quoteIdentifier($y); + } + } +} diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/Query/QueryBuilder.php b/src/core/classes/org/glizy/dataAccessDoctrine/Query/QueryBuilder.php new file mode 100644 index 0000000..7971149 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/Query/QueryBuilder.php @@ -0,0 +1,173 @@ +<?php + +use Doctrine\DBAL\Query\Expression\CompositeExpression, + Doctrine\DBAL\Connection, + Doctrine\DBAL\Cache\QueryCacheProfile; + +class org_glizy_dataAccessDoctrine_Query_QueryBuilder extends \Doctrine\DBAL\Query\QueryBuilder +{ + public function quoteSelectTerm($term) { + $connection = $this->getConnection(); + if (preg_match('/DISTINCT ON\((.+)\)(.+)/i', $term, $m)) { + return 'DISTINCT ON('. $connection->quoteIdentifier($m[1]).')'.$m[2]; + } elseif (preg_match('/DISTINCT (.+) as (.+)/i', $term, $m)) { + return 'DISTINCT '. $connection->quoteIdentifier($m[1]) . ' as ' . $connection->quoteIdentifier($m[2]); + } elseif (preg_match('/DISTINCT (.+)/i', $term, $m)) { + return 'DISTINCT '. $connection->quoteIdentifier($m[1]); + } elseif (preg_match('/MATCH\s*(.+)\s*AGAINST\s*(.+)/i', $term, $m)) { + return $term; + } elseif (preg_match('/(.+) as (.+)/', $term, $m)) { + return $connection->quoteIdentifier($m[1]) . ' as ' . $connection->quoteIdentifier($m[2]); + } else { + return $connection->quoteIdentifier($term); + } + } + + public function add($sqlPartName, $sqlPart, $append = false) + { + if ($sqlPartName == 'select') { + if (is_array($sqlPart)) { + $i = 0; + foreach ($sqlPart as $term) { + $sqlPart[$i] = $this->quoteSelectTerm($term); + $i++; + } + } + else { + $sqlPart = $this->quoteSelectTerm($sqlPart); + } + } + + return parent::add($sqlPartName, $sqlPart, $append); + } + + protected function getSQLForSelect() + { + $connection = $this->getConnection(); + $query = 'SELECT ' . implode(', ', $this->sqlParts['select']) . ' FROM '; + + $fromClauses = array(); + + // Loop through all FROM clauses + foreach ($this->sqlParts['from'] as $from) { + $fromClause = $connection->quoteIdentifier($from['table']) . ' ' . $connection->quoteIdentifier($from['alias']); + + if (isset($this->sqlParts['join'][$from['alias']])) { + foreach ($this->sqlParts['join'][$from['alias']] as $join) { + $fromClause .= ' ' . strtoupper($join['joinType']) + . ' JOIN ' . $connection->quoteIdentifier($join['joinTable']) . ' ' . $connection->quoteIdentifier($join['joinAlias']) + . ' ON ' . ((string) $join['joinCondition']); + } + } + + $fromClauses[$from['alias']] = $fromClause; + } + + // loop through all JOIN clasues for validation purpose + foreach ($this->sqlParts['join'] as $fromAlias => $joins) { + if ( ! isset($fromClauses[$fromAlias]) ) { + throw Doctrine\DBAL\Query\QueryException::unknownFromAlias($fromAlias, array_keys($fromClauses)); + } + } + + $query .= implode(', ', $fromClauses) + . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '') + . ($this->sqlParts['groupBy'] ? ' GROUP BY ' . implode(', ', $this->sqlParts['groupBy']) : '') + . ($this->sqlParts['having'] !== null ? ' HAVING ' . ((string) $this->sqlParts['having']) : '') + . ($this->sqlParts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->sqlParts['orderBy']) : ''); + + return ($this->maxResults === null && $this->firstResult == null) + ? $query + : $connection->getDatabasePlatform()->modifyLimitQuery($query, $this->maxResults, $this->firstResult); + } + + /** + * Converts this instance into an UPDATE string in SQL. + * + * @return string + */ + protected function getSQLForUpdate() + { + $connection = $this->getConnection(); + $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : ''); + $query = 'UPDATE ' . $connection->quoteIdentifier($table) + . ' SET ' . implode(", ", $connection->quoteIdentifiers($this->sqlParts['set'])) + . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); + + return $query; + } + + /** + * Converts this instance into a DELETE string in SQL. + * + * @return string + */ + protected function getSQLForDelete() + { + $connection = $this->getConnection(); + $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : ''); + $query = 'DELETE FROM ' . $connection->quoteIdentifier($table) . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); + + return $query; + } + + /** + * Specifies an ordering for the query results. + * Replaces any previously specified orderings, if any. + * + * @param string $sort The ordering expression. + * @param string $order The ordering direction. + * @return QueryBuilder This QueryBuilder instance. + */ + public function orderBy($sort, $order = null) + { + $connection = $this->getConnection(); + return parent::orderBy($connection->quoteIdentifier($sort), $order); + } + + /** + * Adds an ordering to the query results. + * + * @param string $sort The ordering expression. + * @param string $order The ordering direction. + * @return QueryBuilder This QueryBuilder instance. + */ + public function addOrderBy($sort, $order = null) + { + $connection = $this->getConnection(); + return parent::addOrderBy($connection->quoteIdentifier($sort), $order); + } + + + public function groupBy($groupBy) + { + $connection = $this->getConnection(); + return parent::groupBy($connection->quoteIdentifier($groupBy)); + } + + /** + * Execute this query using the bound parameters and their types. + * + * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate} + * for insert, update and delete statements. + * + * @return mixed + */ + public function execute() + { + $connection = $this->getConnection(); + if ($this->type == self::SELECT) { + // TODO migliorare creando un QuerybuiBuilderCache + if (__Config::get('QUERY_CACHING') && ($cacheDriver = org_glizy_dataAccessDoctrine_DataAccess::getCache())) { + $lifeTime = __Config::get('QUERY_CACHING_LIFETIME'); + $sql = $this->getSQL(); + $key = md5($sql); + return $connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes, new QueryCacheProfile($lifeTime, $key, $cacheDriver)); + } else { + return $connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes); + } + } else { + return $connection->executeUpdate($this->getSQL(), $this->params, $this->paramTypes); + } + } +} diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/RecordIterator.php b/src/core/classes/org/glizy/dataAccessDoctrine/RecordIterator.php new file mode 100755 index 0000000..b8533ed --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/RecordIterator.php @@ -0,0 +1,138 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use Doctrine\DBAL\Types\Type; + +class org_glizy_dataAccessDoctrine_RecordIterator extends org_glizy_dataAccessDoctrine_AbstractRecordIterator +{ + protected $conditionNumber; + + protected function resetQuery() + { + parent::resetQuery(); + $this->qb = $this->ar->createQueryBuilder(true); + $this->conditionNumber = 0; + $this->hasLimit = false; + $this->hasSelect = false; + } + + protected function processUnionFields($fieldName, $value) + { + if (strpos($fieldName, ',') !== false) { + if (!empty( $value )) { + $fields = explode(',', $fieldName); + + $v = array(); + foreach ($fields as $field) { + $v[] = array('field' => $field, 'value' => '%'.$value.'%', 'condition' => 'LIKE' ); + } + $value = $v; + } + } else if (!$this->ar->fieldExists($fieldName)) { + return ''; + } + + return $value; + } + + public function execSql($sql, $options=array()) + { + if (is_string($sql)) { + $sql = array('sql' => $sql); + } + +// TODO controllare se nella query c'è già l'order + $orderBy = $this->qb->getQueryPart('orderBy'); + $sql['sql'] .= $orderBy ? ' ORDER BY ' . implode(', ', $orderBy) : ''; + + if (__Config::get('MULTISITE_ENABLED') && $this->ar->getSiteField()) { + $siteField = $this->ar->getSiteField(); + $siteId = $this->ar->getSiteId(); + + preg_match_all('/WHERE(.*?)( FROM | ORDER | GROUP |$)/si', $sql['sql'], $m); + $lastMatch = count($m[0]) - 1; + $sql['sql'] = str_replace($m[1][$lastMatch], ' '.$siteField.' = '.$siteId.' AND ('.$m[1][$lastMatch].') ', $sql['sql']); + } + + if (isset($sql['filters']) && count($sql['filters'])) { + $filtersSql = implode(' AND ', $sql['filters']); + preg_match_all('/WHERE(.*?)( FROM | ORDER | GROUP |$)/si', $sql['sql'], $m); + $lastMatch = count($m[0]) - 1; + $sql['sql'] = str_replace($m[1][$lastMatch], '('.$m[1][$lastMatch].') AND ('.$filtersSql.') ', $sql['sql']); + } + $params = isset($options['params']) ? $options['params'] : ( is_array($options) ? $options : array()); + $params = isset($sql['params']) ? array_merge($sql['params'], $params) : $params; + + $connection = $this->ar->getConnection(); + + +// ($this->sqlParts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->sqlParts['orderBy']) : ''); + $this->statement = $connection->executeQuery($sql['sql'], $params); +// TODO implementare meglio + $this->count = $this->statement->rowCount(); + +// TODO implementare meglio + $firstResult = $this->qb->getFirstResult(); + $maxResults = $this->qb->getMaxResults(); + if (!is_null($firstResult) && !is_null($maxResults)) { + $sql['sql'] = $connection->getDatabasePlatform()->modifyLimitQuery($sql['sql'], $maxResults, $firstResult); + $this->statement = $connection->executeQuery($sql['sql'], $params); + } + } + + protected function whereCondition($fieldName, $value, $condition = null, $composite = null) + { + $valueParam = ":value".$this->conditionNumber++; + + if (is_null($condition)) { + if (is_null($composite)) { + $this->qb->andWhere($this->expr->eq($fieldName, $valueParam)); + } + else { + $composite->add($this->expr->eq($fieldName, $valueParam)); + } + } + else { + $fieldType = $this->ar->getFieldType($fieldName); + $cast = $fieldType == Type::DATE || $fieldType == Type::DATETIME; + + if (is_null($composite)) { + $this->qb->andWhere($this->expr->comparison($fieldName, $condition, $valueParam, $cast)); + } + else { + $composite->add($this->expr->comparison($fieldName, $condition, $valueParam, $cast)); + } + } + + $this->qb->setParameter($valueParam, $value); + + return $this; + } + + public function orderBy($fieldName, $order = 'ASC') + { + $this->qb->addOrderBy($fieldName, $order); + return $this; + } + + public function groupBy($groupBy) + { + $this->qb->groupBy($groupBy); + return $this; + } + + public function exec() + { + if (!$this->querySqlToExec && !$this->hasSelect) { + $this->select('*'); + } + + parent:: exec(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/RecordIterator2tables.php b/src/core/classes/org/glizy/dataAccessDoctrine/RecordIterator2tables.php new file mode 100755 index 0000000..a679c2a --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/RecordIterator2tables.php @@ -0,0 +1,45 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_dataAccessDoctrine_RecordIterator2tables extends org_glizy_dataAccessDoctrine_RecordIterator +{ + protected $conditionNumber; + protected $hasSelect; + protected $languageSet; + + protected function resetQuery() + { + parent::resetQuery(); + $this->languageSet = false; + } + + public function whereLanguageIs($value) + { + $this->qb->andWhere($this->expr->eq($this->ar->getLanguageField(), ':language')) + ->setParameter(':language', $value); + $this->languageSet = true; + return $this; + } + + public function allLanguages() + { + $this->languageSet = true; + return $this; + } + + public function exec() + { + if (!$this->languageSet && $this->ar->getLanguageField()) { + $this->whereLanguageIs($this->ar->getLanguageId()); + } + + parent:: exec(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/RecordIteratorDocument.php b/src/core/classes/org/glizy/dataAccessDoctrine/RecordIteratorDocument.php new file mode 100755 index 0000000..7064c60 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/RecordIteratorDocument.php @@ -0,0 +1,558 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use Doctrine\DBAL\Types\Type, + Doctrine\DBAL\Cache\QueryCacheProfile; + +class org_glizy_dataAccessDoctrine_RecordIteratorDocument extends org_glizy_dataAccessDoctrine_AbstractRecordIterator +{ + const DOCUMENT_TABLE_ALIAS = 'doc'; + const DOCUMENT_ID = 'document_id'; + const DOCUMENT_TYPE = 'document_type'; + const DOCUMENT_DETAIL_TABLE_ALIAS = 'doc_detail'; + const DOCUMENT_DETAIL_TABLE_PUBLISHED_ALIAS = 'doc_detail_published'; + const DOCUMENT_DETAIL_TABLE_DRAFT_ALIAS = 'doc_detail_draft'; + const DOCUMENT_DETAIL_FK_LANGUAGE = 'document_detail_FK_language_id'; + const DOCUMENT_DETAIL_STATUS = 'document_detail_status'; + const DOCUMENT_DETAIL_IS_VISIBLE = 'document_detail_isVisible'; + const DOCUMENT_DETAIL_FK_USER = 'document_detail_FK_user_id'; + const DOCUMENT_DETAIL_BASE_PREFIX = 'document_detail_'; + + const STATUS_PUBLISHED = 'PUBLISHED'; + const STATUS_DRAFT = 'DRAFT'; + const STATUS_OLD = 'OLD'; + + protected $conditionNumber; + protected $indexNumber; + protected $typeSet; + protected $statusSet; + protected $visibilitySet; + protected $languageSet; + protected $unionArray; + protected $unionArrayParams; + protected $unionOrderBy; + protected $conditionsMap; + protected $options; + + function __construct($ar) + { + parent::__construct($ar); + } + + public function setOptions($options) + { + $this->options = $options; + $this->resetQuery(); + + return $this; + } + + protected function initQueryBuilder() + { + if ($this->options['type'] == 'PUBLISHED_DRAFT') { + $options = array( + 'type' => 'PUBLISHED_DRAFT', + 'tableAlias' => self::DOCUMENT_TABLE_ALIAS, + 'tableDetailPublishedAlias' => self::DOCUMENT_DETAIL_TABLE_PUBLISHED_ALIAS, + 'tableDetailDraftAlias' => self::DOCUMENT_DETAIL_TABLE_DRAFT_ALIAS, + ); + $this->qb = $this->ar->createQueryBuilder($options); + + $languageProxy = __ObjectFactory::createObject('org.glizycms.languages.models.proxy.LanguagesProxy'); + $defaultLanguageId = $languageProxy->getDefaultLanguageId(); + if ($defaultLanguageId != $this->ar->getLanguageId()) { + $this->qb->select( + self::DOCUMENT_TABLE_ALIAS.'.*', + self::DOCUMENT_DETAIL_TABLE_PUBLISHED_ALIAS.'.*', + self::DOCUMENT_DETAIL_TABLE_DRAFT_ALIAS.'.*', + self::DOCUMENT_DETAIL_TABLE_PUBLISHED_ALIAS.'_defaultLanguage.*', + self::DOCUMENT_DETAIL_TABLE_DRAFT_ALIAS.'_defaultLanguage.*' + ); + } else { + $this->qb->select(self::DOCUMENT_TABLE_ALIAS.'.*', self::DOCUMENT_DETAIL_TABLE_PUBLISHED_ALIAS.'.*', self::DOCUMENT_DETAIL_TABLE_DRAFT_ALIAS.'.*'); + } + + $this->statusSet = true; + $this->languageSet = true; + } else { + $options = array( + 'type' => 'PUBLISHED', + 'tableAlias' => self::DOCUMENT_TABLE_ALIAS, + 'tableDetailAlias' => self::DOCUMENT_DETAIL_TABLE_ALIAS, + ); + $this->qb = $this->ar->createQueryBuilder($options); + $this->qb->select(self::DOCUMENT_TABLE_ALIAS.'.*', self::DOCUMENT_DETAIL_TABLE_ALIAS.'.*'); + + $this->statusSet = false; + $this->languageSet = false; + } + + $this->hasSelect = true; + $this->hasLimit = false; + $this->typeSet = false; + $this->visibilitySet = false; + + $this->conditionsMap = array(); + } + + protected function getDetailTableAlias() + { + return ($this->options['type'] == 'PUBLISHED_DRAFT') ? self::DOCUMENT_DETAIL_TABLE_PUBLISHED_ALIAS : self::DOCUMENT_DETAIL_TABLE_ALIAS; + } + + protected function getSystemTableAlias($fieldName) + { + return (strpos($fieldName, self::DOCUMENT_DETAIL_BASE_PREFIX)===false) ? self::DOCUMENT_TABLE_ALIAS : $this->getDetailTableAlias(); + } + + protected function resetQuery() + { + parent::resetQuery(); + + $this->initQueryBuilder(); + + $this->conditionNumber = 0; + $this->indexNumber = 0; + + $this->unionArray = array(); + $this->unionArrayParams = array(); + $this->unionOrderBy = array(); + } + + protected function processUnionFields($fieldName, $value) + { + if (strpos($fieldName, ',') !== false && !$this->ar->fieldExists($fieldName)) { + if (!empty( $value )) { + $fields = explode(',', $fieldName); + + $v = array(); + foreach ($fields as $field) { + $v[] = array('field' => $field, 'value' => '%'.$value,'%', 'condition' => 'LIKE' ); + } + $value = $v; + } + } else if (!$this->ar->fieldExists($fieldName)) { + return ''; + } + + return $value; + } + + public function setOrFilters($filters) + { + $i = 0; + + foreach ($filters as $fieldName => $value) { + if (is_array($value)) { + $this->where($fieldName, $value['value'], $value['condition']); + } + else { + $this->where($fieldName, $value); + } + + if ($i != count($filters)-1) { + $this->newQueryInOr(); + $i++; + } + } + + return $this; + } + + public function selectDistinct($fieldName) + { + $indexData = $this->addIndex($fieldName); + $indexValue = $indexData['indexFieldPrefixAlias'].'_value'; + $this->qb->resetQueryPart('select'); + if ($this->ar->getDriverName() == 'mysql') { + $this->qb->select('DISTINCT('.$indexValue.'), '.$indexValue.' AS '.$fieldName); + } else { + $this->qb->select('DISTINCT ON('.$indexValue.') '.$indexValue.' AS '.$fieldName); + } + $this->hasSelect = true; + return $this; + } + + protected function addIndex($fieldName, $indexAliasPrefix='index') + { + if ($this->conditionsMap[$fieldName]) { + return $this->conditionsMap[$fieldName]; + } + + $indexAlias = $indexAliasPrefix.$this->indexNumber; + $indexType = $this->ar->getIndexFieldType($fieldName); + + $documentDetailIdName = $this->ar->getDocumentDetailTableIdName(); + + $documentIndexTablePrefix = $this->ar->getDocumentIndexTablePrefix(); + $indexTablePrefix = $documentIndexTablePrefix.$indexType; + + $documentIndexFieldPrefix = $this->ar->getDocumentIndexFieldPrefix(); + $indexFieldPrefixAlias = $indexAlias.'.'.$documentIndexFieldPrefix.$indexType; + + if ($this->options['type'] == 'PUBLISHED_DRAFT') { + $this->qb->leftJoin( + self::DOCUMENT_TABLE_ALIAS, $indexTablePrefix.'_tbl', $indexAlias, + $this->qb->expr()->andX( + $this->expr->eq(self::DOCUMENT_DETAIL_TABLE_PUBLISHED_ALIAS.'.'.$documentDetailIdName, $indexFieldPrefixAlias."_FK_document_detail_id"), + $this->expr->eq("{$indexFieldPrefixAlias}_name", ":name{$this->indexNumber}") + ) + ); + } else { + $this->qb->join( + self::DOCUMENT_TABLE_ALIAS, $indexTablePrefix.'_tbl', $indexAlias, + $this->qb->expr()->andX( + $this->expr->eq(self::DOCUMENT_DETAIL_TABLE_ALIAS.".".$documentDetailIdName, $indexFieldPrefixAlias."_FK_document_detail_id"), + $this->expr->eq("{$indexFieldPrefixAlias}_name", ":name{$this->indexNumber}") + ) + ); + } + + $this->qb->setParameter(":name{$this->indexNumber}", $fieldName); + + $indexData = array( + 'indexNumber' => $this->indexNumber, + 'indexAlias' => $indexAlias, + 'indexFieldPrefixAlias' => $indexFieldPrefixAlias, + 'indexType' => $indexType + ); + + $this->conditionsMap[$fieldName] = $indexData; + + $this->indexNumber++; + + return $indexData; + } + + // il primo parametro è il campo da cui si ricava l'indice da selezionare + public function selectIndex($fieldName, $key, $value) + { + $indexData = $this->addIndex($fieldName); + $indexAlias = $indexData['indexAlias']; + $this->select($indexAlias.'.'.$key, $indexAlias.'.'.$value); + return $this; + } + + public function where($fieldName, $value = null, $condition = '=') + { + if ($fieldName == self::DOCUMENT_TYPE) { + return $this->whereTypeIs($value, $condition); + } else if ($fieldName == self::DOCUMENT_ID) { + return $this->whereDocumentIdIs($value); + } else if ($fieldName == self::DOCUMENT_DETAIL_FK_LANGUAGE) { + return $this->whereLanguageIs($value); + } else if ($fieldName == self::DOCUMENT_DETAIL_STATUS) { + return $this->whereStatusIs($value); + } else if ($this->ar->getField($fieldName)->isSystemField) { + return $this->whereSystemField($fieldName, $value, $condition); + } else { + return parent::where($fieldName, $value, $condition); + } + } + + protected function whereCondition($fieldName, $value, $condition = '=', $composite = null) + { + $indexData = $this->addIndex($fieldName); + + $indexFieldPrefixAlias = $indexData['indexFieldPrefixAlias']; + $indexNumber = $indexData['indexNumber']; + + $valueColumn = "{$indexFieldPrefixAlias}_value"; + $valueParam = ":value{$indexNumber}"; + + $cast = $indexData['indexType'] != 'text' && $indexData['indexType'] != 'fulltext'; + $this->qb->andWhere($this->qb->expr()->comparison($valueColumn, $condition, $valueParam, $cast)); + + // NOTA: nel caso di un campo di tipo array + // viene passato 'array' come tipo di ricerca nel where e crea dei problemi perché non trova nulla + if ($fieldType) { + $fieldType = 'text'; + } + + $this->qb->setParameter($valueParam, $value, $fieldType); + + return $this; + } + + public function newQueryInOr() + { + $this->finalizeQuery(); + $this->unionArray[] = $this->qb; + $this->unionArrayParams = array_merge($this->unionArrayParams, $this->qb->getParameters()); + + $this->initQueryBuilder(); + + return $this; + } + + public function whereTypeIs($type, $condition = '=') + { + $valueParam = ':type'.$this->conditionNumber++; + $fieldName = self::DOCUMENT_TABLE_ALIAS.'.'.self::DOCUMENT_TYPE; + $this->qb->andWhere($this->expr->comparison($fieldName, $condition, $valueParam)) + ->setParameter($valueParam, $type); + $this->typeSet = true; + + return $this; + } + + public function allTypes() + { + $this->typeSet = true; + return $this; + } + + public function whereStatusIs($value) + { + $valueParam = ':status'.$this->conditionNumber++; + $this->qb->andWhere($this->expr->eq(self::DOCUMENT_DETAIL_STATUS, $valueParam)) + ->setParameter($valueParam, $value); + $this->statusSet = true; + return $this; + } + + public function allStatuses() + { + $this->statusSet = true; + return $this; + } + + public function whereLanguageIs($value) + { + $alias = $this->getDetailTableAlias(); + $this->qb->andWhere($this->expr->eq($alias.'.'.self::DOCUMENT_DETAIL_FK_LANGUAGE, ':language')) + ->setParameter(':language', $value); + $this->languageSet = true; + return $this; + } + + public function allLanguages() + { + $this->languageSet = true; + return $this; + } + + public function whereDocumentIdIs($value) + { + $paramName = ':documenId_'.count($this->unionArray); + $this->qb->andWhere($this->expr->eq(self::DOCUMENT_ID, $paramName)) + ->setParameter($paramName, $value); + return $this; + } + + protected function whereSystemField($fieldName, $value, $condition = '=') + { + $alias = $this->getSystemTableAlias($fieldName); + $valueParam = ':system'.$this->conditionNumber++; + $this->qb->andWhere($this->expr->comparison($alias.'.'.$fieldName, $condition, $valueParam)) + ->setParameter($valueParam, $value); + return $this; + } + + + public function showAll() + { + $this->visibilitySet = true; + return $this; + } + + public function showVisible() + { + $alias = $this->getDetailTableAlias(); + $valueParam = ':isVisible'.$this->conditionNumber++; + $this->qb->andWhere($this->expr->eq($alias.'.'.self::DOCUMENT_DETAIL_IS_VISIBLE, $valueParam)) + ->setParameter($valueParam, 1); + $this->visibilitySet = true; + return $this; + } + + public function orderBy($fieldName, $order = 'ASC') + { + if (!empty($this->unionArray)) { + $this->unionOrderBy = array($fieldName, $order); + return $this; + } + + if ($this->ar->getField($fieldName)->isSystemField) { + return $this->orderBySystemField($fieldName, $order); + } else { + $indexData = $this->addIndex($fieldName); + $indexFieldPrefixAlias = $indexData['indexFieldPrefixAlias']; + $this->qb->addOrderBy("{$indexFieldPrefixAlias}_value", $order); + return $this; + } + } + + protected function orderBySystemField($fieldName, $order = 'ASC') + { + $alias = $this->getSystemTableAlias($fieldName); + $this->qb->addOrderBy($alias.'.'.$fieldName, $order); + return $this; + } + + private function finalizeQuery() + { + if (!$this->typeSet) { + $this->whereTypeIs($this->ar->getType()); + } + + if (!$this->statusSet && !$this->options['type'] == 'PUBLISHED_DRAFT') { + $this->whereStatusIs(self::STATUS_PUBLISHED); + } + + if (!$this->languageSet) { + $this->whereLanguageIs($this->ar->getLanguageId()); + } + + if (__Config::get('glizy.dataAccess.documentVisibility') && !$this->visibilitySet) { + $this->showVisible(); + } + } + + // TODO aggiustare + public function addAcl() + { + $qb = $this->qb; + $and = $qb->expr()->andX(); + $and->add($qb->expr()->eq('acl.join_FK_source_id', self::DOCUMENT_TABLE_ALIAS.'.'.self::DOCUMENT_ID)); + $and->add($qb->expr()->eq('acl.join_objectName', ':join_objectName')); + + $or = $qb->expr()->orX(); + $or->add($qb->expr()->isNull('acl.join_FK_dest_id')); + + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $user = $application->getCurrentUser(); + $roles = $user->getRoles(); + + $i = 0; + + foreach ($roles as $role) { + $roleParam = ':role'.$i++; + $or->add($qb->expr()->eq('acl.join_FK_dest_id', $roleParam)); + $qb->setParameter($roleParam, $role); + } + + $qb->addSelect('acl.*') + ->leftJoin(self::DOCUMENT_TABLE_ALIAS, $this->ar->getTablePrefix().'joins_tbl', 'acl', $and) + ->andWhere($or) + ->setParameter(':join_objectName', 'documents_tbl#rel_aclView'); + + return $this; + } + + public function exec() + { + if (!$this->querySqlToExec) { + $this->finalizeQuery(); + } + + if (empty($this->unionArray)) { + if (__Config::get('ACL_ROLES')) { + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $user = $application->getCurrentUser(); + if ($user->id && !$user->acl($application->getPageId(), 'all')) { + $this->addAcl(); + } + } + + try { + parent::exec(); + } catch (Exception $e) { + require_once(org_glizy_Paths::get('CORE_LIBS').'sql-formatter/lib/SqlFormatter.php'); + $trace = $e->getTrace(); + var_dump($trace[0]['args'][0]->errorInfo); + echo SqlFormatter::format($sql).'</br></br>'; + var_dump($this->unionArrayParams); + } + } else { + $this->unionArray[] = $this->qb; + $this->unionArrayParams = array_merge($this->unionArrayParams, $this->qb->getParameters()); + + if (!empty($this->unionOrderBy)) { + list($fieldName, $order) = $this->unionOrderBy; + + if (!$this->ar->getField($fieldName)->isSystemField) { + $indexType = $this->ar->getIndexFieldType($fieldName); + $documentDetailIdName = $this->ar->getDocumentDetailTableIdName(); + $documentTableIndexPrefix = $this->ar->getDocumentIndexTablePrefix(); + $indexAlias = 'orderIndex'; + $indexTablePrefix = $documentTableIndexPrefix.$indexType; + + $documentFieldIndexPrefix = $this->ar->getDocumentIndexFieldPrefix(); + $indexFieldPrefix = $documentFieldIndexPrefix.$indexType; + $indexFieldPrefixAlias = $indexAlias.'.'.$indexFieldPrefix; + + $detailAlias = ($this->options['type'] == 'PUBLISHED_DRAFT') ? self::DOCUMENT_DETAIL_TABLE_PUBLISHED_ALIAS : self::DOCUMENT_DETAIL_TABLE_ALIAS; + + foreach ($this->unionArray as $qb) { + $qb->addSelect('orderIndex.*'); + $qb->join(self::DOCUMENT_TABLE_ALIAS, $indexTablePrefix.'_tbl', 'orderIndex', + $this->expr->eq($detailAlias.'.'.$documentDetailIdName, $indexFieldPrefixAlias.'_FK_document_detail_id')); + $qb->andWhere($this->expr->eq("{$indexFieldPrefixAlias}_name", ':orderIndex')); + } + + $this->unionArrayParams[":orderIndex"] = $fieldName; + + $orderSql = "ORDER BY {$indexFieldPrefix}_value"; + } else { + $orderSql = "ORDER BY $fieldName $order"; + } + } + + $sqlArray = array(); + + foreach ($this->unionArray as $qb) { + if (!$this->siteSet && $this->ar->getSiteField()) { + $qb->andWhere($this->expr->eq($this->ar->getSiteField(), ':site')); + $this->unionArrayParams[":site"] = $this->ar->getSiteid(); + } + + $sqlArray[] = $qb->getSql(); + } + + $sql = '(' . implode(') UNION (', $sqlArray) . ')'; + + if (!empty($this->unionOrderBy)) { + $sql .= $orderSql; + } + + try { + if (__Config::get('QUERY_CACHING') && ($cacheDriver = org_glizy_dataAccessDoctrine_DataAccess::getCache())) { + $lifeTime = __Config::get('QUERY_CACHING_LIFETIME'); + $key = md5($sql); + $this->statement = $this->ar->getConnection()->executeQuery($sql, $this->unionArrayParams, array(), new QueryCacheProfile($lifeTime, $key, $cacheDriver)); + } else { + $this->statement = $this->ar->getConnection()->executeQuery($sql, $this->unionArrayParams); + } + } catch (Exception $e) { + require_once(org_glizy_Paths::get('CORE_LIBS').'sql-formatter/lib/SqlFormatter.php'); + $trace = $e->getTrace(); + var_dump($trace[0]['args'][0]->errorInfo); + echo SqlFormatter::format($sql).'</br></br>'; + var_dump($this->unionArrayParams); + } + + $this->resetQuery(); + } + } + + // TODO + public function execSql($sql, $options=array()) + { + if (is_string($sql)) { + $sql = array('sql' => $sql); + } + + $params = isset($options['params']) ? $options['params'] : ( is_array($options) ? $options : array()); + $params = isset($sql['params']) ? array_merge($sql['params'], $params) : $params; + $this->statement = $this->ar->getConnection()->executeQuery($sql['sql'], $params); +// TODO implementare meglio + $this->count = $this->statement->rowCount(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/RecordIteratorSimpleDocument.php b/src/core/classes/org/glizy/dataAccessDoctrine/RecordIteratorSimpleDocument.php new file mode 100755 index 0000000..dee6e90 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/RecordIteratorSimpleDocument.php @@ -0,0 +1,100 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use Doctrine\DBAL\Types\Type; + +class org_glizy_dataAccessDoctrine_RecordIteratorSimpleDocument extends org_glizy_dataAccessDoctrine_RecordIterator +{ + const DOCUMENT_TABLE_ALIAS = 'doc'; + const DOCUMENT_TABLE_TYPE = 'simple_document_type'; + + protected $indexNumber; + protected $conditionsMap; + + protected function resetQuery() + { + $this->qb = $this->ar->createQueryBuilder(true, self::DOCUMENT_TABLE_ALIAS); + $this->qb->select(self::DOCUMENT_TABLE_ALIAS.'.*') + ->where($this->expr->eq(self::DOCUMENT_TABLE_ALIAS.'.'.self::DOCUMENT_TABLE_TYPE, ':type')) + ->setParameter(":type", $this->ar->getType()); + $this->indexNumber = 0; + $this->hasLimit = false; + $this->hasSelect = true; + $this->conditionsMap = array(); + } + + protected function whereCondition($fieldName, $value, $condition = '=', $composite = null) + { + $indexType = $this->ar->getIndexFieldType($fieldName); + $indexAlias = 'index'.$this->indexNumber++; + + $documentId = $this->ar->getDocumentTableIdName(); + + $documentIndexTablePrefix = $this->ar->getDocumentIndexTablePrefix(); + $indexTablePrefix = $documentIndexTablePrefix.$indexType; + + $documentIndexFieldPrefix = $this->ar->getDocumentIndexFieldPrefix(); + $indexFieldPrefixAlias = $indexAlias.'.'.$documentIndexFieldPrefix.$indexType; + + $this->qb->join(self::DOCUMENT_TABLE_ALIAS, $indexTablePrefix.'_tbl', $indexAlias, + $this->expr->eq(self::DOCUMENT_TABLE_ALIAS.'.'.$documentId, $indexFieldPrefixAlias.'_FK_simple_document_id')); + + $and = $this->expr->andX(); + $and->add($this->expr->eq("{$indexFieldPrefixAlias}_name", ":name{$this->indexNumber}")); + + $fieldType = $this->ar->getField($fieldName)->type; + + $valueColumn = "{$indexFieldPrefixAlias}_value"; + $valueParam = ":value{$this->indexNumber}"; + + $and->add($this->expr->comparison($valueColumn, $condition, $valueParam)); + + $this->qb->setParameter(":name{$this->indexNumber}", $fieldName); + $this->qb->setParameter(":value{$this->indexNumber}", $value); + + $this->qb->andWhere($and); + + $this->conditionsMap[$fieldName] = $indexFieldPrefixAlias; + + return $this; + } + + public function orderBy($fieldName, $order = 'ASC') + { + if (is_null($this->conditionsMap[$fieldName])) { + $indexAlias = 'index'.$this->indexNumber++; + $indexType = $this->ar->getIndexFieldType($fieldName); + + $documentId = $this->ar->getDocumentTableIdName(); + + $documentIndexTablePrefix = $this->ar->getDocumentIndexTablePrefix(); + $indexTablePrefix = $documentIndexTablePrefix.$indexType; + + $documentIndexFieldPrefix = $this->ar->getDocumentIndexFieldPrefix(); + $indexFieldPrefixAlias = $indexAlias.'.'.$documentIndexFieldPrefix.$indexType; + + $this->qb->join(self::DOCUMENT_TABLE_ALIAS, $indexTablePrefix.'_tbl', $indexAlias, self::DOCUMENT_TABLE_ALIAS.".{$documentId} = {$indexFieldPrefixAlias}_FK_simple_document_id"); + $this->qb->andWhere($this->expr->eq("{$indexFieldPrefixAlias}_name", ":name{$this->indexNumber}")); + $this->qb->setParameter(":name{$this->indexNumber}", $fieldName); + } + else { + $indexFieldPrefixAlias = $this->conditionsMap[$fieldName]; + } + + $this->qb->addOrderBy("{$indexFieldPrefixAlias}_value", $order); + + return $this; + } + + // TODO + public function execSql($sql, $options=array()) + { + // lanciare eccezione + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/RelationFactory.php b/src/core/classes/org/glizy/dataAccessDoctrine/RelationFactory.php new file mode 100644 index 0000000..60ae96b --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/RelationFactory.php @@ -0,0 +1,36 @@ +<?php + +class org_glizy_dataAccessDoctrine_RelationFactory extends GlizyObject +{ + function createRelation(&$parent, $options) + { + $relation = NULL; + switch (strtolower($options['type'])) + { + case 'hasone': + case 'has_one': + case 'fk': + //$relation = new org_glizy_dataAccess_RelationHasOne($parent, $options); + break; + case 'hasmany': + case 'has_many': + //$relation = new org_glizy_dataAccess_RelationHasMany($parent, $options); + break; + case 'many': + //$relation = new org_glizy_dataAccess_RelationMany2Many($parent, $options); + break; + case 'jointable': + $relation = new org_glizy_dataAccessDoctrine_RelationJoinTable($parent, $options); + break; + case 'contenttable': + //$relation = new org_glizy_dataAccess_RelationContentTable($parent, $options); + break; + default: + // TODO + // visualizzare errore + break; + } + + return $relation; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/RelationJoinTable.php b/src/core/classes/org/glizy/dataAccessDoctrine/RelationJoinTable.php new file mode 100644 index 0000000..9b23ba9 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/RelationJoinTable.php @@ -0,0 +1,123 @@ +<?php + +class org_glizy_dataAccessDoctrine_RelationJoinTable extends org_glizy_dataAccessDoctrine_AbstractRelation +{ + protected $iterator = NULL; + protected $bindTo = ''; + protected $objectName = ''; + protected $objectField = 'join_objectName'; + protected $ordered = true; + protected $newRecord; + + function __construct($parent, $options) + { + parent::__construct($parent, $options); + assert(isset($options['field'])); + $this->key = $options['field']; + assert(!is_null($options['destinationField'])); + $this->destinationKey = $options['destinationField']; + $this->bindTo = $options['bindTo']; + $this->objectName = $options['objectName']; + } + + function build($params=array()) + { + $this->record = org_glizy_ObjectFactory::createModel($this->className); + $this->iterator = null; + + $parentId = $this->parent->getId(); + + if (!is_null($parentId)) { + $this->newRecord = empty( $parentId ); + + $this->iterator = org_glizy_ObjectFactory::createModelIterator($this->className) + ->where($this->key, $parentId) + ->where($this->objectField, $this->objectName) + ->orderBy($this->record->getPrimaryKeyName()); + + if (is_null($this->parent->{$this->bindTo})) { + $this->record = null; + $values = array(); + foreach($this->iterator as $ar) { + $values[] = $ar->{$this->destinationKey}; + $this->record = $this->iterator->current(); + } + + $this->parent->{$this->bindTo} = implode(',', $values); + } else { + $this->record = $this->iterator->current(); + } + + if ($this->iterator->count()) { + $this->iterator->first(); + } + } + } + + function postSave() + { + $values = $this->parent->{$this->bindTo}; + + if (is_null($values)) { + return; + } + + $values = is_string($values) ? !empty($values) ? explode(',', $values) : array() + : $values; + if ( !is_array( $values ) ) { + $values = array( $values ); + } + + if (is_null($this->record->{$this->destinationKey}) + || $this->record->{$this->destinationKey} == $this->record->getField($this->destinationKey)->defaultValue + || is_null($this->iterator)) { + // nuovo record + $parentId = $this->parent->getId(); + foreach ($values as $v) { + $this->record = org_glizy_ObjectFactory::createModel($this->className); + $this->record->{$this->key} = $parentId; + $this->record->{$this->destinationKey} = $v; + $this->record->{$this->objectField} = $this->objectName; + $this->record->save(); + } + } else { + $recordIds = array(); + foreach ($this->iterator as $ar) { + if ( $this->ordered ) { + if ( !$this->newRecord ) { + $ar->delete(); + } + } else { + if (!in_array($ar->{$this->destinationKey}, $values)) { + $ar->delete(); + } else { + $recordIds[] = $ar->{$this->destinationKey}; + } + } + } + + if (count($values)) { + foreach ($values as $v) { + if (!in_array($v, $recordIds)) { + $this->record = org_glizy_ObjectFactory::createModel($this->className); + $this->record->{$this->key} = $this->parent->getId(); + $this->record->{$this->destinationKey} = $v; + $this->record->{$this->objectField} = $this->objectName; + $newId = $this->record->save(); + } + } + } + } + } + + public function delete() + { + $this->iterator = org_glizy_ObjectFactory::createModelIterator($this->className) + ->where($this->key, $this->parent->getId()) + ->where($this->objectField, $this->objectName); + + foreach ($this->iterator as $ar) { + $ar->delete(); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/SchemaManager.php b/src/core/classes/org/glizy/dataAccessDoctrine/SchemaManager.php new file mode 100755 index 0000000..28330ab --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/SchemaManager.php @@ -0,0 +1,133 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use Doctrine\DBAL\Types\Type; + +class org_glizy_dataAccessDoctrine_SchemaManager +{ + private $sm; + private $cache; + protected $conn; + + public function __construct($connection) + { + $this->conn = $connection; + $this->sm = $connection->getSchemaManager(); + $this->cache = org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFunction', $this, __Config::get('glizy.dataAccess.schemaManager.cacheLife'), true); + } + + public function getTableNames() + { + return $this->sm->listTableNames(); + } + + public function getColumnNames($tableName) + { + $columns = $this->sm->listTableColumns($tableName); + + $names = array(); + + foreach ($columns as $column) { + $names[] = $column->getName(); + } + + return $names; + } + + public function getSequenceName($tableName) + { + $sm = $this->sm; + $method = __METHOD__.get_class($this->sm->getDatabasePlatform()).$this->conn->getHost().$this->conn->getDatabase(); + return $this->cache->get($method, func_get_args(), function() use ($tableName, $sm) { + $columns = $sm->listTableColumns($tableName); + + foreach ($columns as $column) { + $options = $column->getPlatformOptions(); + + if (!empty($options) && isset($options['sequence'])) { + return $options['sequence']; + } + } + return null; + }); + } + + public function getFields($tableName) + { + $sm = $this->sm; + $that = $this; + $method = __METHOD__.get_class($this->sm->getDatabasePlatform()).$this->conn->getHost().$this->conn->getDatabase(); + return $this->cache->get($method, func_get_args(), function() use ($tableName, $sm, $that) { + // recupera gli indici per cercare la chiave primaria + $indexes = $sm->listTableIndexes($tableName); + + // cerca la chiave primaria + foreach ($indexes as $index) { + if ($index->isPrimary()) { + $indexColumns = array_flip($index->getColumns()); + break; + } + } + + $fields = array(); + $columns = $sm->listTableColumns($tableName); + foreach ($columns as $column) { + $name = $column->getName(); + $size = !is_null($column->getLength()) ? $column->getLength() : $column->getPrecision(); + $key = isset($indexColumns[$name]); + + // ($name, $type, $size, $key, $notNull, $defaultValue, $readFormat=true, $virtual=false) + $fields[$name] = new org_glizy_dataAccessDoctrine_DbField( + $name, + $column->getType()->getName(), + $size, + $key, + $that->getValidator($column), + $column->getDefault(), + true, + false, + $name + ); + } + + return $fields; + }); + } + + + public function getValidator($column) + { + $validators = array(); + + $type = $column->getType()->getName(); + + if ($type == Type::INTEGER || $type == Type::SMALLINT || $type == Type::BIGINT) { + $validators[] = new org_glizy_validators_Numeric(); + } + else if ($type == Type::STRING || $type == Type::TEXT) { + $validators[] = new org_glizy_validators_Text(); + } + + if ($column->getNotnull()) { + $validators[] = new org_glizy_validators_NotNull(); + } + + if (empty($validators)) { + return null; + } + else if (count($validators) == 1) { + return $validators[0]; + } + else { + $composite = new org_glizy_validators_CompositeValidator(); + $composite->addArray($validators); + return $composite; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/SqlRecordIterator.php b/src/core/classes/org/glizy/dataAccessDoctrine/SqlRecordIterator.php new file mode 100644 index 0000000..2b5caac --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/SqlRecordIterator.php @@ -0,0 +1,228 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use Doctrine\DBAL\Types\Type; + +class org_glizy_dataAccessDoctrine_SqlRecordIterator extends GlizyObject implements Iterator +{ + protected $connectionNumber; + protected $querySqlToExec = ''; + protected $returnClass; + protected $EOF = false; + protected $lastParams = NULL; + protected $lastQuery = ''; + protected $pos = 0; + protected $statement = NULL; + protected $data = NULL; + protected $count = NULL; + + + /** + * @param int $connectionNumber + */ + function __construct($connectionNumber=0) + { + $this->connection = org_glizy_dataAccessDoctrine_DataAccess::getConnection($connectionNumber); + } + + /** + * @param string $query + * @param null $params + * + * @return $this + */ + public function load($query, $params=null) + { + if (method_exists($this, $query)) { + $this->querySqlToExec = org_glizy_helpers_PhpScript::callMethodWithParams($this, $query, $params); + } else { + // TODO errore + } + + $this->lastQuery = $query; + $this->lastParams = null; + + return $this; + } + + /** + * @return $this + */ + public function exec() + { + $this->execSql($this->querySqlToExec, $this->lastParams); + return $this; + } + + /** + * @param string $sql + * @param array $options + */ + protected function execSql($sql, $options=array()) + { + if (is_string($sql)) { + $sql = array('sql' => $sql); + } + + $params = isset($options['params']) ? $options['params'] : ( is_array($options) ? $options : array()); + $params = isset($sql['params']) ? array_merge($sql['params'], $params) : $params; + +// TODO controllare se nella query c'è già l'order + // $orderBy = $this->qb->getQueryPart('orderBy'); + // $sql['sql'] .= $orderBy ? ' ORDER BY ' . implode(', ', $orderBy) : ''; + + if (count($sql['filters'])) { + $index = 0; + $filtersSql = array(); + foreach($sql['filters'] as $k=>$v) { + $condition = is_array($v) ? $v['condition'] : '='; + $value = is_array($v) ? $v['value'] : $v; + $paramName = ':params'.$index++; + $filtersSql[] = $k.$condition.$paramName; + $params[$paramName] = $value; + } + + $filtersSql = implode(' AND ', $filtersSql); + preg_match_all('/WHERE(.*?)( FROM | ORDER | GROUP |$)/si', $sql['sql'], $m); + $lastMatch = count($m[0]) - 1; + if ($lastMatch <= 0) { + $sql['sql'] .= ' WHERE 1=1 '; + preg_match_all('/WHERE(.*?)( FROM | ORDER | GROUP |$)/si', $sql['sql'], $m); + $lastMatch = count($m[0]) - 1; + } + $sql['sql'] = str_replace($m[1][$lastMatch], '('.$m[1][$lastMatch].') AND ('.$filtersSql.') ', $sql['sql']); + } + + +// ($this->sqlParts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->sqlParts['orderBy']) : ''); + $this->statement = $this->connection->executeQuery($sql['sql'], $params); +// TODO implementare meglio + $this->count = $this->statement->rowCount(); + + $this->returnClass = isset($sql['return']) ? $sql['return'] : ''; +// TODO implementare meglio + // $firstResult = $this->qb->getFirstResult(); + // $maxResults = $this->qb->getMaxResults(); + // if (!is_null($firstResult) && !is_null($maxResults)) { + // $sql['sql'] = $connection->getDatabasePlatform()->modifyLimitQuery($sql['sql'], $maxResults, $firstResult); + // $this->statement = $connection->executeQuery($sql['sql'], $params); + // } + } + + public function next() + { + $this->fetch(); + } + + public function rewind() + { + if ($this->pos == 0) { + $this->exec(); + } else if ($this->pos == 1) { + // noting + return; + } else { + $this->execSql($this->querySqlToExec, $this->lastParams); + } + + $this->pos = 0; + $this->fetch(); + } + + /** + * @return bool + */ + public function valid() + { + return !$this->EOF; + } + + /** + * @return int + */ + public function key() + { + return $this->recordPos(); + } + + /** + * @param bool $returnNewIfNull + * + * @return GlizyObject|mixed|null|StdClass + */ + public function &first($returnNewIfNull=false) + { + return $this->current(); + } + + /** + * @return GlizyObject|mixed|null|StdClass + */ + public function &current() + { + if ($this->data == NULL) { + $this->rewind(); + } + + // se non ci sono record + if ($this->EOF) { + return null; + } + + if (!$this->returnClass) { + $r = new StdClass; + foreach($this->data as $k=>$v) { + $r->{$k} = $v; + } + } else { + $r = __ObjectFactory::createObject($this->returnClass, $this->data); + } + + return $r; + } + + /** + * @return mixed + */ + public function count() + { + if ($this->statement == NULL) { + $this->rewind(); + } + + return $this->count == NULL ? $this->statement->rowCount() : $this->count; + } + + /** + * @param $v + */ + public function setCount( $v ) + { + $this->count = $v; + } + + /** + * @return int + */ + public function recordPos() + { + return $this->pos; + } + + private function fetch() + { + $this->data = $this->statement->fetch(); + $this->EOF = $this->data === false; + $this->pos++; + + if ($this->EOF) { + $this->statement->closeCursor(); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/SystemField.php b/src/core/classes/org/glizy/dataAccessDoctrine/SystemField.php new file mode 100755 index 0000000..2bdde00 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/SystemField.php @@ -0,0 +1,17 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_dataAccessDoctrine_SystemField extends org_glizy_dataAccessDoctrine_DbField +{ + function __construct($name, $type, $size, $key, $validator, $defaultValue, $readFormat=true, $virtual=false, $description='', $index=self::INDEXED) + { + parent::__construct($name, $type, $size, $key, $validator, $defaultValue, $readFormat, $virtual, $description, $index); + $this->isSystemField = true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/interfaces/RelationInterface.php b/src/core/classes/org/glizy/dataAccessDoctrine/interfaces/RelationInterface.php new file mode 100644 index 0000000..432950a --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/interfaces/RelationInterface.php @@ -0,0 +1,9 @@ +<?php + +interface org_glizy_dataAccessDoctrine_interfaces_RelationInterface +{ + public function build($params=array()); + public function preSave(); + public function postSave(); + public function delete(); +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/logging/DebugLogger.php b/src/core/classes/org/glizy/dataAccessDoctrine/logging/DebugLogger.php new file mode 100644 index 0000000..abb26e8 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/logging/DebugLogger.php @@ -0,0 +1,24 @@ +<?php + +class org_glizy_dataAccessDoctrine_logging_DebugLogger implements Doctrine\DBAL\Logging\SQLLogger +{ + /** + * {@inheritdoc} + */ + public function startQuery($sql, array $params = null, array $types = null) + { + foreach($params as $k=>$v) { + $sql = str_replace($k, '\''.$v.'\'', $sql); + } + + echo $sql . PHP_EOL; + } + + /** + * {@inheritdoc} + */ + public function stopQuery() + { + + } +} diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/logging/EchoSQLLogger.php b/src/core/classes/org/glizy/dataAccessDoctrine/logging/EchoSQLLogger.php new file mode 100644 index 0000000..47389c7 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/logging/EchoSQLLogger.php @@ -0,0 +1,37 @@ +<?php +require_once(org_glizy_Paths::get('CORE_LIBS').'sql-formatter/lib/SqlFormatter.php'); + +use \Doctrine\DBAL\Connection, + \Doctrine\DBAL\Query\Expression\CompositeExpression; + +class org_glizy_dataAccessDoctrine_logging_EchoSQLLogger extends \Doctrine\DBAL\Logging\EchoSQLLogger +{ + public $start = null; + + /** + * {@inheritdoc} + */ + public function startQuery($sql, array $params = null, array $types = null) + { + $this->start = microtime(true); + + $replacedSql = $sql; + if ($params) { + foreach ($params as $param => $value) { + $value = is_string($value) ? "'".$value."'" : $value; + $replacedSql = str_replace($param, $value, $replacedSql); + } + } + + echo SqlFormatter::format($replacedSql).'</br></br>'; + parent::startQuery($sql, $params, $types); + } + + /** + * {@inheritdoc} + */ + public function stopQuery() + { + echo 'query time: '.round((microtime(true)-$this->start), 3).'s </br></br>'; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/types/Array.php b/src/core/classes/org/glizy/dataAccessDoctrine/types/Array.php new file mode 100644 index 0000000..938a85a --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/types/Array.php @@ -0,0 +1,18 @@ +<?php + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +class org_glizy_dataAccessDoctrine_types_Array extends \Doctrine\DBAL\Types\ArrayType +{ + public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) + { + if (is_object($value)) { + return get_object_vars($value); + } else if (is_array($value)) { + return $value; + } else if (!$value) { + return array(); + } + return parent::convertToPHPValue($value, $platform); + } +} diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/types/ArrayID.php b/src/core/classes/org/glizy/dataAccessDoctrine/types/ArrayID.php new file mode 100644 index 0000000..dd0d22c --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/types/ArrayID.php @@ -0,0 +1,11 @@ +<?php + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +class org_glizy_dataAccessDoctrine_types_ArrayID extends org_glizy_dataAccessDoctrine_types_Array +{ + public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform = null) + { + return $value; + } +} diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/types/Boolean.php b/src/core/classes/org/glizy/dataAccessDoctrine/types/Boolean.php new file mode 100644 index 0000000..9ca1ff8 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/types/Boolean.php @@ -0,0 +1,13 @@ +<?php + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +class org_glizy_dataAccessDoctrine_types_Boolean extends \Doctrine\DBAL\Types\BooleanType +{ + public function convertToDatabaseValue($value, AbstractPlatform $platform = null) + { + $value = $value==='false' ? 0 : + ($value==='true' ? 1 : $value); + return parent::convertToDatabaseValue($value, $platform); + } +} diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/types/Date.php b/src/core/classes/org/glizy/dataAccessDoctrine/types/Date.php new file mode 100644 index 0000000..5f562bb --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/types/Date.php @@ -0,0 +1,16 @@ +<?php + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +class org_glizy_dataAccessDoctrine_types_Date extends \Doctrine\DBAL\Types\DateType +{ + public function convertToDatabaseValue($value, AbstractPlatform $platform = null) + { + return glz_localeDate2ISO($value); + } + + public function convertToPHPValue($value, AbstractPlatform $platform = null) + { + return is_string($value) ? glz_defaultDate2locale(__T('GLZ_DATE_FORMAT'), $value) : $value; + } +} diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/types/DateTime.php b/src/core/classes/org/glizy/dataAccessDoctrine/types/DateTime.php new file mode 100644 index 0000000..10e13cd --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/types/DateTime.php @@ -0,0 +1,16 @@ +<?php + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +class org_glizy_dataAccessDoctrine_types_DateTime extends \Doctrine\DBAL\Types\DateTimeType +{ + public function convertToDatabaseValue($value, AbstractPlatform $platform = null) + { + return glz_localeDate2ISO($value); + } + + public function convertToPHPValue($value, AbstractPlatform $platform = null) + { + return is_string($value) ? glz_defaultDate2locale(__T('GLZ_DATETIME_FORMAT'), $value) : $value; + } +} diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/types/DateTimeTz.php b/src/core/classes/org/glizy/dataAccessDoctrine/types/DateTimeTz.php new file mode 100644 index 0000000..64d3520 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/types/DateTimeTz.php @@ -0,0 +1,24 @@ +<?php + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +class org_glizy_dataAccessDoctrine_types_DateTimeTz extends \Doctrine\DBAL\Types\DateTimeTzType +{ + public function convertToDatabaseValue($value, AbstractPlatform $platform = null) + { + return $value; + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof org_glizy_types_DateTimeTz) { + return $value; + } + + $val = org_glizy_types_DateTimeTz::createFromFormat($platform->getDateTimeTzFormatString(), $value); + if ( ! $val) { + throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeTzFormatString()); + } + return $val; + } +} diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/types/Time.php b/src/core/classes/org/glizy/dataAccessDoctrine/types/Time.php new file mode 100644 index 0000000..74d7635 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/types/Time.php @@ -0,0 +1,24 @@ +<?php + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +class org_glizy_dataAccessDoctrine_types_Time extends \Doctrine\DBAL\Types\TimeType +{ + public function convertToDatabaseValue($value, AbstractPlatform $platform = null) + { + return $value; + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof org_glizy_types_Time) { + return $value; + } + + $val = org_glizy_types_Time::createFromFormat('!'.$platform->getTimeFormatString(), $value); + if ( ! $val) { + throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getTimeFormatString()); + } + return $val; + } +} diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/types/Types.php b/src/core/classes/org/glizy/dataAccessDoctrine/types/Types.php new file mode 100644 index 0000000..ea635bf --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/types/Types.php @@ -0,0 +1,6 @@ +<?php + +class org_glizy_dataAccessDoctrine_types_Types +{ + const ARRAY_ID = 'array_id'; +} diff --git a/src/core/classes/org/glizy/dataAccessDoctrine/vo/DocumentObjectVO.php b/src/core/classes/org/glizy/dataAccessDoctrine/vo/DocumentObjectVO.php new file mode 100755 index 0000000..2c34555 --- /dev/null +++ b/src/core/classes/org/glizy/dataAccessDoctrine/vo/DocumentObjectVO.php @@ -0,0 +1,58 @@ +<?php + +class org_glizy_dataAccessDoctrine_vo_DocumentObjectVO extends GlizyObject +{ + const DOCUMENT_DETAIL_OBJECT = 'document_detail_object'; + const DOCUMENT_DETAIL_STATUS = 'document_detail_status'; + + protected $data; + protected $hasPublishedVersion; + protected $hasDraftVersion; + + function __construct($data) + { + $languageProxy = __ObjectFactory::createObject('org.glizycms.languages.models.proxy.LanguagesProxy'); + + $index = null; + + if (is_array($data[self::DOCUMENT_DETAIL_STATUS])) { + $index = array_search('PUBLISHED', $data[self::DOCUMENT_DETAIL_STATUS]); + $this->hasPublishedVersion = $index !== FALSE; + + $indexDraft = array_search('DRAFT', $data[self::DOCUMENT_DETAIL_STATUS]); + $this->hasDraftVersion = $indexDraft !== FALSE; + + if (!$this->hasPublishedVersion) { + $index = $indexDraft; + } + } + + if ($index && $data['document_detail_FK_language_id'][$index] != $languageProxy->getLanguageId()) { + $data['document_detail_FK_language_id'][$index] = $languageProxy->getLanguageId(); + $data['document_detail_translated'][$index] = 0; + } + + foreach ($data as $k => $v) { + if (is_array($v)) { + $this->data[$k] = $v[$index]; + } else { + $this->data[$k] = $v; + } + } + } + + public function __get($name) + { + return $this->data[$name]; + } + + public function hasPublishedVersion() + { + return $this->hasPublishedVersion; + } + + public function hasDraftVersion() + { + return $this->hasDraftVersion; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/debug/GlizyDebugBar.php b/src/core/classes/org/glizy/debug/GlizyDebugBar.php new file mode 100644 index 0000000..a4736ea --- /dev/null +++ b/src/core/classes/org/glizy/debug/GlizyDebugBar.php @@ -0,0 +1,148 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +use DebugBar\DebugBar; +use DebugBar\DataCollector\PhpInfoCollector; +use DebugBar\DataCollector\MessagesCollector; +use DebugBar\DataCollector\TimeDataCollector; +use DebugBar\DataCollector\RequestDataCollector; +use DebugBar\DataCollector\MemoryCollector; +use DebugBar\DataCollector\ExceptionsCollector; +use DebugBar\DataCollector\ConfigCollector; +use DebugBar\Bridge\DoctrineCollector; + +/** + * Debug bar subclass which adds all included collectors + */ +class org_glizy_debug_GlizyDebugBar extends GlizyObject +{ + private $debugBar; + private $startTime; + private $glizyCollector; + // private $calledControllerName = array(); + + public function __construct() + { + $this->startTime = microtime(true); + spl_autoload_register(array($this, 'loadClass')); + + $this->initDebugBar(); + $this->addEventListener(GLZ_LOG_EVENT, $this); + $this->addEventListener(GLZ_EVT_START_PROCESS, $this); + $this->addEventListener(GLZ_EVT_END_PROCESS, $this); + $this->addEventListener(GLZ_EVT_START_RENDER, $this); + $this->addEventListener(GLZ_EVT_END_RENDER, $this); + $this->addEventListener(GLZ_EVT_CALL_CONTROLLER, $this); + } + + public function loadClass($className) + { + if (strpos($className, 'DebugBar') === 0 || strpos($className, 'Psr') === 0) { + glz_importLib(str_replace('\\', '/', $className).'.php'); + } + } + + public function getJavascriptRenderer($baseUrl = null, $basePath = null) + { + return $this->debugBar->getJavascriptRenderer($baseUrl, $basePath); + } + + + + public function logByEvent($evt) + { + $group = $evt->data['group'] == 'debugBar' ? 'messages' : 'logs'; + + switch ($evt->data['level']) { + case GLZ_LOG_DEBUG: + $this->debugBar[$group]->debug($evt->data['message']); + break; + case GLZ_LOG_INFO: + case GLZ_LOG_SYSTEM: + $this->debugBar[$group]->info($evt->data['message']); + break; + case GLZ_LOG_WARNING: + $this->debugBar[$group]->warning($evt->data['message']); + break; + case GLZ_LOG_ERROR: + $this->debugBar[$group]->critical($evt->data['message']); + break; + case GLZ_LOG_FATAL: + $this->debugBar[$group]->critical($evt->data['message']); + break; + } + } + + public function addMesage($message, $level) + { + $this->debugBar['messages']->addMessage($message, $level); + } + + public function getTime() + { + return $this->debugBar['time']; + } + + /** + * Listeners + */ + + public function onProcessStart($evt) + { + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $rootComponent = $application->getRootComponent(); + $c = org_glizy_ObjectFactory::createComponent('org.glizy.debug.views.components.DebugBar', $application, $rootComponent, 'debugBar', 'debugBar'); + $c->init(); + $rootComponent->addChild($c); + + $this->debugBar['time']->addMeasure('Booting', $this->startTime, microtime(true)); + $this->debugBar['time']->startMeasure('application.process', 'Process'); + } + + public function onProcessEnd($evt) + { + $this->debugBar['time']->stopMeasure('application.process'); + } + + public function onRenderStart($evt) + { + $this->debugBar['time']->startMeasure('application.render', 'Render'); + } + + public function onRenderEnd($evt) + { + // $this->debugBar['time']->stopMeasure('application.render'); + } + + public function onCallController($evt) + { + $this->glizyCollector->addCalledController($evt->data); + } + + private function initDebugBar() + { + $this->glizyCollector = org_glizy_ObjectFactory::createObject('org.glizy.debug.dataCollector.GlizyCollector'); + $this->debugBar = new DebugBar; + $this->debugBar->addCollector(new PhpInfoCollector()); + $this->debugBar->addCollector(new MessagesCollector()); + $this->debugBar->addCollector(new MessagesCollector('logs')); + $this->debugBar->addCollector(new TimeDataCollector()); + $this->debugBar->addCollector(new MemoryCollector()); + $this->debugBar->addCollector($this->glizyCollector); + + $conn = org_glizy_dataAccessDoctrine_DataAccess::getConnection(); + $config = $conn->getConfiguration(); + $debugStack = new Doctrine\DBAL\Logging\DebugStack(); + $config->setSQLLogger($debugStack); + $this->debugBar->addCollector(new DoctrineCollector($debugStack)); + } +} + + diff --git a/src/core/classes/org/glizy/debug/Helpers.php b/src/core/classes/org/glizy/debug/Helpers.php new file mode 100644 index 0000000..b5fa776 --- /dev/null +++ b/src/core/classes/org/glizy/debug/Helpers.php @@ -0,0 +1,49 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + + +class __DebugBar +{ + static function debug($message) + { + org_glizy_debug_Module::$debugBar->addMesage($message, 'debug'); + } + + static function info($message) + { + org_glizy_debug_Module::$debugBar->addMesage($message, 'info'); + } + + static function warning($message) + { + org_glizy_debug_Module::$debugBar->addMesage($message, 'warning'); + } + + static function error($message) + { + org_glizy_debug_Module::$debugBar->addMesage($message, 'error'); + } + + static function fatal($message) + { + org_glizy_debug_Module::$debugBar->addMesage($message, 'critical'); + } + + static function startMeasure($name) + { + org_glizy_debug_Module::$debugBar->getTime()->startMeasure($name); + } + + static function stopMeasure($name) + { + org_glizy_debug_Module::$debugBar->getTime()->stopMeasure($name); + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/debug/Module.php b/src/core/classes/org/glizy/debug/Module.php new file mode 100644 index 0000000..55bfb30 --- /dev/null +++ b/src/core/classes/org/glizy/debug/Module.php @@ -0,0 +1,23 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_debug_Module extends GlizyObject +{ + static $debugBar = null; + + static function registerModule() + { + if (__Config::get('DEBUG')) { + include_once('Helpers.php'); + self::$debugBar = org_glizy_ObjectFactory::createObject('org.glizy.debug.GlizyDebugBar'); + org_glizy_ObjectFactory::createObject('org.glizy.debug.Whoops'); + } + } +} diff --git a/src/core/classes/org/glizy/debug/Whoops.php b/src/core/classes/org/glizy/debug/Whoops.php new file mode 100644 index 0000000..a94a75f --- /dev/null +++ b/src/core/classes/org/glizy/debug/Whoops.php @@ -0,0 +1,37 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_debug_Whoops extends GlizyObject +{ + + + public function __construct() + { + spl_autoload_register(array($this, 'loadClass')); + + GlizyErrorHandler::unregister(); + + $whoops = new \Whoops\Run; + $handler = new \Whoops\Handler\PrettyPageHandler; + + $whoops->pushHandler($handler); + $whoops->register(); + } + + public function loadClass($className) + { + if (strpos($className, 'Whoops') === 0) { + require_once(__DIR__.'/../../../../libs/'.str_replace('\\', '/', $className).'.php'); + return true; + } + } +} + + diff --git a/src/core/classes/org/glizy/debug/dataCollector/GlizyCollector.php b/src/core/classes/org/glizy/debug/dataCollector/GlizyCollector.php new file mode 100644 index 0000000..b1c47cb --- /dev/null +++ b/src/core/classes/org/glizy/debug/dataCollector/GlizyCollector.php @@ -0,0 +1,103 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + + +use DebugBar\DataCollector\DataCollector; +use DebugBar\DataCollector\Renderable; + +/** + * Debug bar subclass which adds all included collectors + */ +class org_glizy_debug_dataCollector_GlizyCollector extends DataCollector implements Renderable +{ + private $calledControllers = array(); + + /** + * {@inheritdoc} + */ + public function collect() + { + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + + $result = array(); + + $result['pageId'] = $application->getPageId(); + $result['routing'] = __Request::get('__routingName__').' > '.__Request::get('__routingPattern__'); + $result['controllers'] = implode(', ', $this->calledControllers); + + $user = $application->getCurrentUser(); + $userData = array( + 'id' => $user->id, + 'firstName' => $user->firstName, + 'lastName' => $user->lastName, + 'email' => $user->email, + 'groupId' => $user->groupId, + 'backEndAccess' => $user->backEndAccess, + ); + $result['user'] = $this->getDataFormatter()->formatVar($userData); + + $menu = $application->getCurrentMenu(); + $menuData = array( + 'id' => $menu->id, + 'title' => $menu->title, + 'parentId' => $menu->parentId, + 'pageType' => $menu->pageType, + 'type' => $menu->type, + 'depth' => $menu->depth, + ); + $result['menu'] = $this->getDataFormatter()->formatVar($menuData); + + + // request + $data = __Request::getAllAsArray(); + $tempData = array(); + foreach($data as $k=>$v) { + if (strpos($k, '__')!==0) { + $tempData[$k] = $v; + } + } + $result['__Request'] = $this->getDataFormatter()->formatVar($tempData); + $result['__Config'] = $this->getDataFormatter()->formatVar(__Config::getAllAsArray()); + $result['__Routing'] = $this->getDataFormatter()->formatVar(__Routing::getAllAsArray()); + $result['__Session'] = $this->getDataFormatter()->formatVar(__Session::getAllAsArray()); + + + return $result; + } + + public function addCalledController($name) + { + $this->calledControllers[] = $name; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'glizy'; + } + + /** + * {@inheritDoc} + */ + public function getWidgets() + { + $name = $this->getName(); + return array( + "$name" => array( + "icon" => "archive", + "widget" => "PhpDebugBar.Widgets.VariableListWidget", + "map" => $name, + "default" => "{}" + ) + ); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/debug/views/components/DebugBar.php b/src/core/classes/org/glizy/debug/views/components/DebugBar.php new file mode 100644 index 0000000..9998a4f --- /dev/null +++ b/src/core/classes/org/glizy/debug/views/components/DebugBar.php @@ -0,0 +1,33 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use DebugBar\StandardDebugBar; + +class org_glizy_debug_views_components_DebugBar extends org_glizy_components_Component +{ + private $debugbarRenderer; + + function __construct(&$application, &$parent, $tagName='', $id='', $originalId='') + { + parent::__construct($application, $parent, $tagName, $id, $originalId); + $debugBar = org_glizy_debug_Module::$debugBar; + + $this->debugbarRenderer = $debugBar->getJavascriptRenderer(GLZ_HOST.'/'.__Paths::get('CORE').'libs/DebugBar/Resources/'); + + + } + + + public function render($mode) + { + $this->addOutputCode($this->debugbarRenderer->renderHead(), 'head'); + $this->addOutputCode($this->debugbarRenderer->render(), 'tail'); + } + +} diff --git a/src/core/classes/org/glizy/events/Event.php b/src/core/classes/org/glizy/events/Event.php new file mode 100755 index 0000000..10221b8 --- /dev/null +++ b/src/core/classes/org/glizy/events/Event.php @@ -0,0 +1,69 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +DEFINE('EVENT_CAPTURING_PHASE', 1); +DEFINE('EVENT_AT_TARGET', 2); +DEFINE('EVENT_BUBBLING_PHASE', 3); + +class org_glizy_events_Event +{ + var $type; + var $target; + var $currentTarget; + var $eventPhase; + var $bubbles; + var $cancelable; + var $timeStamp; + var $data; + + function __construct(&$target, $params=array()) + { + $this->target = $target; + + $allowParams = array('type', 'bubbles', 'cancelable', 'data'); + foreach($allowParams as $p) + { + if (isset($params[$p])) + { + $this->{$p} = $params[$p]; + } + } + + $this->type = strtolower( $this->type ); + } + + function initEvent($eventTypeArg, $canBubbleArg=false, $cancelableArg=false, $dataArg=NULL) + { + $this->type = strtolower( $eventTypeArg ); + $this->bubbles = $canBubbleArg; + $this->cancelable = $cancelableArg; + $this->timeStamp = time(); + $this->data = $dataArg; + + } + + function stopPropagation() + { + } + + function preventDefault() + { + } + + function setTarget(&$target) + { + $this->target = $target; + } + + function setCurrentTarget(&$target) + { + $this->currentTarget = $target; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/events/EventDispatcher.php b/src/core/classes/org/glizy/events/EventDispatcher.php new file mode 100755 index 0000000..86d92a8 --- /dev/null +++ b/src/core/classes/org/glizy/events/EventDispatcher.php @@ -0,0 +1,66 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class org_glizy_events_EventDispatcher */ +class org_glizy_events_EventDispatcher +{ + + static function addEventListener($type, &$listener, $useCapture=false, $method=null ) + { + $type = strtolower( $type ); + $eventsChain = &org_glizy_ObjectValues::get('org.glizy.events.EventTarget', 'events', array()); + if (!isset($eventsChain[$type])) + { + $eventsChain[$type] = array(); + } + $eventsChain[$type][] = array('listener' => &$listener, 'useCapture' => $useCapture, 'method' => $method); + } + + static function removeEventListener($type, &$listener, $useCapture=false) + { + // TODO + } + + static function dispatchEvent(&$evt) + { + $eventsChain = &org_glizy_ObjectValues::get('org.glizy.events.EventTarget', 'events', array()); + if (isset($eventsChain[$evt->type])) + { + for($i=0; $i<count($eventsChain[$evt->type]); $i++) + { + $listener = $eventsChain[$evt->type][$i]; + $evt->setCurrentTarget($listener['listener']); + $method = str_replace(array('@', '.'), '_', $evt->type); + if (method_exists($listener['listener'], $method)) + { + $listener['listener']->{$method}($evt); + } + else if ( !is_null( $listener['method'] ) && method_exists($listener['listener'], $listener['method'] ) ) + { + $listener['listener']->{ $listener['method'] }($evt); + } + } + } + + // TODO + return true; + } + + static function hasEventListener($type) + { + // TODO + return true; + } + + static function willTrigger($type) + { + // TODO + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/events/EventException.php b/src/core/classes/org/glizy/events/EventException.php new file mode 100755 index 0000000..2b200b4 --- /dev/null +++ b/src/core/classes/org/glizy/events/EventException.php @@ -0,0 +1,17 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +DEFINE('EVENT_UNSPECIFIED_EVENT_TYPE_ERR', 0); + +class org_glizy_events_EventException +{ + var $code; + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/filters/ForceNoTagText.php b/src/core/classes/org/glizy/filters/ForceNoTagText.php new file mode 100755 index 0000000..a61ef6c --- /dev/null +++ b/src/core/classes/org/glizy/filters/ForceNoTagText.php @@ -0,0 +1,59 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_filters_ForceNoTagText extends org_glizy_filters_OutputFilter +{ + function apply(&$value, &$component) + { + $xml = new XML(); + $xml->parseXML($value); + $rootNode = $xml->firstChild; + $result = ''; + $this->__toString($rootNode, $result); + $value = preg_replace('/^<root>/i', '', $result); + } + + function __toString($node, &$result) + { + switch ($node->nodeType) + { + case XML_COMMENT_NODE: + $result .= '<!-- '.$node->nodeValue.' -->'; + break; + case XML_TEXT_NODE: + $result .= '<p>'.$node->nodeValue.'</p>'; + break; + case XML_CDATASection: + break; + default: + $result .= '<'.$node->nodeName; + + if ($node->hasAttributes()) + { + foreach ($node->attributes as $key => $val) + { + $result .= ' '.$key.'="'.$val.'"'; + } + } + + if ($node->hasChildNodes()) + { + $result .= '>'; + foreach ($node->childNodes as $child) + { + toString($child, $result); + } + $result .= '</'.$node->nodeName.'>'; + } else { + $result .= '/>'; + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/filters/OutputFilter.php b/src/core/classes/org/glizy/filters/OutputFilter.php new file mode 100755 index 0000000..fe8663b --- /dev/null +++ b/src/core/classes/org/glizy/filters/OutputFilter.php @@ -0,0 +1,15 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_filters_OutputFilter extends GlizyObject +{ + function apply(&$value, &$component) + { + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/filters/Uppercase.php b/src/core/classes/org/glizy/filters/Uppercase.php new file mode 100755 index 0000000..dddb16f --- /dev/null +++ b/src/core/classes/org/glizy/filters/Uppercase.php @@ -0,0 +1,20 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_filters_Uppercase extends org_glizy_filters_OutputFilter +{ + function apply(&$value, &$component) + { + if (is_string($value)) + { + $value = strtoupper($value); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/ActiveRecord.php b/src/core/classes/org/glizy/helpers/ActiveRecord.php new file mode 100755 index 0000000..ffa8dd3 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/ActiveRecord.php @@ -0,0 +1,51 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_helpers_ActiveRecord extends GlizyObject +{ + function recordSet2List(&$iterator, $routeUrl='', $cssClass=array(), $maxRecord=NULL, $queryVars=array(), $getRelationValues=false) + { + $output = array(); + $tempCssClass = $cssClass; + $i = 0; + while ($iterator->hasMore()) + { + $ar = &$iterator->current(); + if ($getRelationValues) + { + $ar->setProcessRelations(true); + $ar->buildAllRelations(); + } + $values = $ar->getValuesAsArray($getRelationValues, true, true); + $values = array_merge($values, $queryVars); + if (!count($tempCssClass)) $tempCssClass = $cssClass; + if (count($tempCssClass)) $values['__cssClass__'] = array_shift($tempCssClass); + + $values['__url__'] = org_glizy_helpers_Link::makeURL($routeUrl, $values); + $output[] = $values; + $iterator->next(); + $i++; + if (!is_null($maxRecord) && $i==$maxRecord) break; + } + return $output; + } + + function recordSet2ItemsList(&$iterator) + { + $output = array(); + while ($iterator->hasMore()) + { + $ar = &$iterator->current(); + $values = $ar->getValuesAsArray(); +// $output[] = array('key' => $values[0], 'value' => $values[count($values)-1]); + $iterator->next(); + } + return $output; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/Array.php b/src/core/classes/org/glizy/helpers/Array.php new file mode 100755 index 0000000..4bb263c --- /dev/null +++ b/src/core/classes/org/glizy/helpers/Array.php @@ -0,0 +1,47 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class org_glizy_helpers_Array */ +class org_glizy_helpers_Array extends GlizyObject +{ + // the multisort code if based on http://wiki.grusp.it/tips:array_key_multisort?s=multisort by AlberT (http://www.superalbert.it/) + + /** + * ordina un array multidimensionale in base ad un campo + * + * @param $arr, l'array da ordinare + * @param $l la "label" che identifica il campo di ordinamento + * @param $f la funzione di ordinamento che si vuole applicare, di default si usa strnatcasecmp() + * @return TRUE in caso di successo, FALSE in caso di fallimento. + */ + static function arrayMultisortByLabel(&$arr, $l, $invert=false, $f='strnatcasecmp') + { + if ( $invert ) + { + return usort($arr, create_function('$a, $b', "return $f(\$b['$l'], \$a['$l']);")); + } + else + { + return usort($arr, create_function('$a, $b', "return $f(\$a['$l'], \$b['$l']);")); + } + } + + + /** + * ordina un array multidimensionale in base all'indice + * + * @param $arr, l'array da ordinare + * @param $l la "label" che identifica il campo di ordinamento + * @param $f la funzione di ordinamento che si vuole applicare, di default si usa strnatcasecmp() + * @return TRUE in caso di successo, FALSE in caso di fallimento. + */ + function arrayMultisortByIndex(&$arr, $l , $f='strnatcasecmp') { + return usort($arr, create_function('$a, $b', "return $f(\$a[$l], \$b[$l]);")); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/CSS.php b/src/core/classes/org/glizy/helpers/CSS.php new file mode 100755 index 0000000..26abfd6 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/CSS.php @@ -0,0 +1,44 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_helpers_CSS extends GlizyObject +{ + static function linkCoreCSSfile($name, $subDir='') + { + $output = '<link rel="stylesheet" type="text/css" media="all" href="'.org_glizy_Paths::get('CORE_STATIC_DIR').'assets/css/'.$subDir.$name.'" />'; + return $output; + } + + static function linkCoreCSSfile2($name) + { + $output = '<link rel="stylesheet" type="text/css" media="all" href="'.org_glizy_Paths::get('CORE_STATIC_DIR').$name.'" />'; + return $output; + } + + static function linkStaticCSSfile($name) + { + $output = '<link rel="stylesheet" type="text/css" media="all" href="'.org_glizy_Paths::get('STATIC_DIR').$name.'" />'; + return $output; + } + + static function linkCSSfile($name, $media='all') + { + if ($media) { + $mediaAttr = 'media="'.$media.'"'; + } + $output = '<link rel="stylesheet" type="text/css" '.$mediaAttr.' href="'.$name.'" />'; + return $output; + } + + static function CSScode($code) + { + $output = '<style type="text/css">'.$code.'</style>'; + return $output; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/Convert.php b/src/core/classes/org/glizy/helpers/Convert.php new file mode 100644 index 0000000..4a49144 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/Convert.php @@ -0,0 +1,26 @@ +<?php +class org_glizy_helpers_Convert +{ + public static function formEditObjectToStdObject($data) + { + $result = array(); + if (is_object($data)) { + $objectKeys = array_keys(get_object_vars($data)); + if ($objectKeys) { + $numItems = 0; + foreach($objectKeys as $k) { + $numItems = max(count($data->{$k}), $numItems); + } + for($i=0; $i < $numItems; $i++) { + $tempObj = new StdClass; + foreach($objectKeys as $k) { + $value = $data->{$k}[$i]; + $tempObj->{$k} = $value; + } + $result[] = $tempObj; + } + } + } + return $result; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/Files.php b/src/core/classes/org/glizy/helpers/Files.php new file mode 100644 index 0000000..e1af553 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/Files.php @@ -0,0 +1,84 @@ +<?php +/** + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2006 Daniele Ugoletti <daniele@ugoletti.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + * + * @copyright Copyright (c) 2005, 2006 Daniele Ugoletti + * @link http://www.glizy.org Glizy Project + * @license http://www.gnu.org/copyleft/lesser.html GNU LESSER GENERAL PUBLIC LICENSE + * @package glizy + * @subpackage glizy.helpers + * @author Alessandro Graziano <alessandro.graziano@gruppometa.it> + * @category script + * @since Glizy v 0.01 + * @version $Rev$ + * @modifiedby $LastChangedBy$ + * @lastmodified $Date$ + */ + +class org_glizy_helpers_Files extends GlizyObject +{ + public static function deleteDirectory($dir, $expireTime=null) + { + if (!file_exists($dir)) return false; + + if (!is_dir($dir) || is_link($dir)) { + if ($expireTime) { + $fileCreationTime = filectime($dir); + if ((time() - $fileCreationTime) < $expireTime) { + return true; + } + } + return unlink($dir); + } + + foreach (scandir($dir) as $item) + { + if ($item == '.' || $item == '..') continue; + + if (!org_glizy_helpers_Files::deleteDirectory($dir . "/" . $item, $expireTime)) { + chmod($dir . "/" . $item, 0777); + if (!org_glizy_helpers_Files::deleteDirectory($dir . "/" . $item, $expireTime)) return false; + } + } + + return @rmdir($dir); + } + + + public static function copyDirectory($src, $dst) + { + if (is_dir($src)) { + @mkdir($dst, fileperms($src), true); + $files = scandir($src); + foreach ($files as $file) { + if ($file != '.' && $file != '..') { + self::copyDirectory($src.'/'.$file, $dst.'/'.$file); + } + } + } else if (file_exists($src)) { + copy($src, $dst); + } + } + + // // http://stackoverflow.com/questions/22316808/php-delete-all-files-older-than-x-days-in-2-folders + // public static function deleteFrom($src, $dst) + // { + // $dir = opendir($src); + // @mkdir($dst, 0777, true); + // while(false !== ( $file = readdir($dir)) ) { + // if (( $file != '.' ) && ( $file != '..' )) { + // if ( is_dir($src . '/' . $file) ) { + // org_glizy_helpers_Files::copyDirectory($src . '/' . $file,$dst . '/' . $file); + // } else { + // copy($src . '/' . $file, $dst . '/' . $file); + // } + // } + // } + // closedir($dir); + // } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/Html.php b/src/core/classes/org/glizy/helpers/Html.php new file mode 100755 index 0000000..27a61b9 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/Html.php @@ -0,0 +1,304 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_helpers_Html + */ +class org_glizy_helpers_Html extends GlizyObject +{ + /** + * @param $name + * @param $value + * @param array $attributes + * + * @return string + */ + static function hidden($name, $value, $attributes=array(), $data=array()) + { + $ouput = '<input name="'.$name.'" id="'.$name.'" type="hidden" value="'.$value.'"'.org_glizy_helpers_Html::renderAttributes($attributes, $data).'/>'; + return $ouput; + } + + /** + * @return string + */ + static function requestToHiddenFields() + { + $ouput = ''; + $requestValues = __Request::getAllAsArray(); + foreach ( $requestValues as $k=>$v ) + { + if ( empty( $v ) ) continue; + + if ( is_array( $v ) ) + { + for( $i = 0; $i < count( $v ); $i++ ) + { + $ouput .= '<input name="'.$k.'[]" type="hidden" value="'.$v[ $i ].'" />'; + } + } + else + { + $ouput .= '<input name="'.$k.'" type="hidden" value="'.$v.'" />'; + } + } + + return $ouput; + } + + /** + * @param $label + * @param string $for + * @param bool $wrap + * @param string $content + * @param array $attributes + * @param bool $addBr + * + * @return string + */ + static function label($label, $for='', $wrap=false, $content='', $attributes=array(), $addBr=false) + { + if ( is_null( $label ) ) + { + $ouput = $content; + } + else + { + $ouput = '<label for="'.$for.'" '.org_glizy_helpers_Html::renderAttributes($attributes).'>'.$label.(!$wrap ? '</label>' : ''); + $ouput .= $content; + $ouput .= $wrap ? '</label>' : ''; + } + if ($addBr) $ouput .= '<br />'; + return $ouput; + } + + /** + * @param array $attributes + * + * @return string + */ + static function renderAttributes($attributes=array(), $dataAttributes = null ) + { + if ( $dataAttributes ) + { + $dataAttributes = explode( ';', $dataAttributes ); + foreach ($dataAttributes as $value) + { + list( $name, $value ) = explode( '=', $value ); + $attributes[ 'data-'.$name ] = htmlentities($value); + } + } + $output = ''; + foreach ($attributes as $k=>$v) + { + if (!empty($v) || $k == 'value' ) + { + if ($k == 'href' || $k == 'src') + { + $v = preg_replace('/&(?!amp;)/i', '&amp;', $v); + } + else if ($k == 'id') + { + $v = str_replace('@', '___', $v); + } + $output .= ' '.$k.'="'.$v.'"'; + } + } + return $output; + } + + /** + * @param $tag + * @param array $attributes + * @param bool $close + * @param null $content + * + * @return string + */ + static function renderTag($tag, $attributes=array(), $close=true, $content=NULL) + { + $output = '<'.$tag; + $output .= org_glizy_helpers_Html::renderAttributes($attributes); + if (is_null($content)) + { + $output .= $close ? '/>' : '>'; + } + else + { + $output .= '>'.$content.'</'.$tag.'>'; + } + return $output; + } + + /** + * @param $tag + * + * @return string + */ + static function closeTag($tag) + { + return '</'.$tag.'>'; + } + + /** + * @param $output + * @param $hidden + * @param bool $rightLabel + * @param null $cssClass + * + * @return string + */ + function applyItemTemplate($label, $element, $hidden, $rightLabel=false, $cssClass=NULL ) + { + if ( $hidden ) + { + $template = org_glizy_Config::get('FORM_ITEM_HIDEN_TEMPLATE'); + } + else if ( $rightLabel ) + { + $template = org_glizy_Config::get('FORM_ITEM_RIGHT_LABEL_TEMPLATE'); + } + else + { + $template = org_glizy_Config::get('FORM_ITEM_TEMPLATE'); + } + // TODO: verificare + // if ( !empty( $cssClass ) ) + // { + // $template = preg_replace( '/(<div\s*)(class=")/i', '$1class="'.$cssClass.' ', $template ) ; + // } + + return str_replace(array('##FORM_LABEL##','##FORM_ITEM##'), array($label, $element), $template); + } + + /** + * @param $text + * + * @return string + */ + static function forceP($text) + { + $output = ''; + $allowTag = array('strong', 'em', 'br', 'a', 'img', 'hr'); + $allowAutocloseTag = array('img', 'br', 'hr'); + preg_match_all('/\<([^>]*)\>/is', $text, $matches); + if (count($matches[0])) + { + $open = false; + $numMatches = count($matches[0]); + $stack = array(); + + for($i=0; $i<$numMatches; $i++) + { + $pos = strpos($text, $matches[0][$i]); + if ($pos!==false) + { + $tag = preg_replace('/\<(\w*)(.*)/i', '$1', $matches[0][$i]); + if ($pos!=0) + { + $part = substr($text, 0, $pos); + $trimmed = trim($part); + if ($open===false && !empty($trimmed)) + { + $output .= '<p>'.$part; + if (in_array($tag, $allowTag)) + { + array_unshift($stack, '</p>'); + } + else + { + $output .= '</p>'; + } + } + else + { + $output .= $part; + } + } + else + { + if ($open===false) + { + if (in_array($tag, $allowTag)) + { + $output .= '<p>'; + array_unshift($stack, '</p>'); + } + } + } + + $closeTag = '</'.$tag.'>'; + $outputText = substr($text, $pos, strlen($matches[0][$i])); + + if (strpos($matches[0][$i], '/>')===false) + { + if ($stack[0]==$matches[0][$i]) + { + array_shift($stack); + $open = count($stack)>0; + } + else if (strpos($matches[0][$i], '</')===false) + { + array_unshift($stack, $closeTag); + $open = count($stack)>0; + } + } + else + { + // tag with autoclose + if (!in_array($tag, $allowAutocloseTag)) + { + $outputText = preg_replace('/\s?\/>$/i', '>'.$closeTag, $outputText); + + } + $open = count($stack)>0; + } + $output .= $outputText; + $text = substr($text, $pos+strlen($matches[0][$i])); + } + } + if (count($stack)) + { + if (!empty($text)) + { + $output .= $text; + $text = ''; + } + for ($i=0; $i<count($stack); $i++) + { + $output .= $stack[$i]; + } + } + + } + + if (!empty($text)) $output .= '<p>'.$text.'</p>'; + unset ($stack); + unset ($matches); + return $output; + } + + /** + * @param $label + * @param string $tag + * + * @return string + */ + static function renderPageTitle( $label, $tag='h2' ) + { + return !empty( $label ) ? '<'.$tag.'>'.$label.'</'.$tag.'>' : ''; + } +} + +/** + * Class __Html + */ +class __Html extends org_glizy_helpers_Html { + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/JS.php b/src/core/classes/org/glizy/helpers/JS.php new file mode 100755 index 0000000..a16beb9 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/JS.php @@ -0,0 +1,53 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_helpers_JS extends GlizyObject +{ + static function linkCoreJSfile($name, $subDir='', $compress=NULL, $type='text/javascript') + { + $url = org_glizy_helpers_JS::getCompressedUrl(org_glizy_Paths::get('CORE_STATIC_DIR').$subDir.$name, $compress); + $output = '<script type="'.$type.'" src="'.$url.'"></script>'; + return $output; + } + + static function linkCoreJSfile2($name, $compress=NULL, $type='text/javascript') + { + $url = org_glizy_helpers_JS::getCompressedUrl(org_glizy_Paths::get('CORE_STATIC_DIR').$name, $compress); + $output = '<script type="'.$type.'" src="'.$url.'"></script>'; + return $output; + } + + static function linkStaticJSfile($name, $compress=NULL, $type='text/javascript') + { + $url = org_glizy_helpers_JS::getCompressedUrl(org_glizy_Paths::get('STATIC_DIR').$name, $compress); + $output = '<script type="'.$type.'" src="'.$url.'"></script>'; + return $output; + } + + static function linkJSfile($url, $compress=NULL, $type='text/javascript') + { + $url = org_glizy_helpers_JS::getCompressedUrl($url, $compress); + $output = '<script type="'.$type.'" src="'.$url.'"></script>'; + return $output; + } + + static function JScode($code, $type='text/javascript') + { + $output = '<script type="'.$type.'">'.GLZ_COMPILER_NEWLINE2.'// <![CDATA['.GLZ_COMPILER_NEWLINE2.$code.GLZ_COMPILER_NEWLINE2.'// ]]>'.GLZ_COMPILER_NEWLINE2.'</script>'; + return $output; + } + + function getCompressedUrl($url, $compress=NULL) + { + $compress = is_null($compress) ? org_glizy_Config::get('JS_COMPRESS') : $compress; + $url = $compress ? org_glizy_Paths::get('STATIC_DIR').'js.php?v='.org_glizy_Config::get('APP_VERSION').'&r='.org_glizy_Paths::get('ROOT').'&s='.$url : $url; + return str_replace('&', '&amp;', $url); + + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/Link.php b/src/core/classes/org/glizy/helpers/Link.php new file mode 100755 index 0000000..fd619b3 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/Link.php @@ -0,0 +1,487 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_helpers_Link extends GlizyObject +{ + function getDefaultUrl() + { + return GLZ_SCRIPNAME; + } + + /** + * @param string $route + * @param array $queryVars + * @param array $addParam + * + * @return mixed|string + */ + static function makeURL($route='', $queryVars=array(), $addParam=array()) + { + return __Routing::makeURL( $route, $queryVars, $addParam ); + } + + + /** + * @param string $route + * @param array $queryVars + * @param array $addParam + * @param string $onclick + * @param bool $encode + * + * @return string + */ + static function makeLink($route='', $queryVars=array(), $addParam=array(), $onclick='', $encode = true ) + { + $cssClass = ''; + if (isset($queryVars['cssClass'])) + { + $cssClass = $queryVars['cssClass']; + unset($queryVars['cssClass']); + } + $rel = ''; + if (isset($queryVars['rel'])) + { + $rel = $queryVars['rel']; + unset($queryVars['rel']); + } + $icon = ''; + if (isset($queryVars['icon'])) { + $icon = '<i class="'.$queryVars['icon'].'"></i> '; + } + + $label = isset($queryVars['label']) ? $queryVars['label'] : $queryVars['title']; + unset( $queryVars['label'] ); + $url = org_glizy_helpers_Link::makeURL($route, $queryVars, $addParam); + $target = isset($queryVars['target']) ? $queryVars['target'] : ''; + return org_glizy_helpers_Html::renderTag( 'a', + array( 'href' => $url, + 'class' => $cssClass, + 'title' => glz_encodeOutput( $queryVars['title'] ), + 'target' => $target, + 'rel' => $rel, + 'onclick' => $onclick), + true, + $icon.($encode ? glz_encodeOutput( $label ) : $label )); + } + + + /** + * @param $route + * @param array $options + * @param array $attributes + * + * @return string + */ + static function makeLink2($route, $options=array(), $attributes=array()) + { + if (isset($options['id'])) + { + $attributes['id'] = $options['id']; + } + $attributes['title'] = glz_encodeOutput(isset($options['title']) ? $options['title'] : $options['label']); + $attributes['href'] = isset($options['url']) ? $options['url'] : org_glizy_helpers_Link::makeURL($route, $options); + $label = $options['label']; + if ($options['icon']) { + $label = '<i class="'.$options['icon'].'"></i> '.$label; + } + + $output = org_glizy_helpers_Html::renderTag('a', $attributes, true, $label); + return $output; + } + + /** + * @param string $route + * @param array $queryVars + * @param array $addParam + * + * @return string + */ + static function makeJSLocation($route='', $queryVars=array(), $addParam=array()) + { + $url = org_glizy_helpers_Link::makeURL($route, $queryVars, $addParam); + return 'location.href = \''.$url.'\''; + } + + + + /** + * @param $label + * @param $url + * @param string $title + * @param string $cssClass + * @param string $rel + * @param string $target + * + * @return string + */ + static function makeSimpleLink($label, $url, $title='', $cssClass='', $rel='', $attributes=array()) + { + if (empty($title)) $title = $label; + $attributes['href'] = $url; + $attributes['class'] = $cssClass; + $attributes['title'] = $title; + $attributes['rel'] = $rel; + if (isset($attributes['icon'])) { + $label = '<i class="'.$attributes['icon'].'"></i> '.$label; + unset($attributes['icon']); + } + return org_glizy_helpers_Html::renderTag( 'a', + $attributes, + true, + $label); + } + + /** + * @param $email + * @param null $label + * + * @return string + */ + static function makeEmailLink($email, $label=NULL) + { + if (empty($label)) $label = $email; + return '<a href="mailto:'.$email.'" title="'.glz_encodeOutput($email).'">'.glz_encodeOutput($label).'</a>'; + } + + /** + * @param $route + * @param array $options + * @param array $attributes + * + * @return string + */ + static function imageLink($route, $options=array(), $attributes=array()) + { + $options['title'] = glz_encodeOutput($options['title']); + $attributes['title'] = $options['title']; + $attributes['alt'] = $options['title']; + $attributes['src'] = $options['src']; + $attributes['width'] = @$options['width']; + $attributes['height'] = @$options['height']; + unset($options['src']); + $url = isset($options['url']) ? $options['url'] : org_glizy_helpers_Link::makeURL($route, $options); + + $output = org_glizy_helpers_Html::renderTag('a', + array( 'href' => $url, + 'class' => $options['cssClass'], + 'title' => $options['title'], + 'rel' => $rel, + 'target' => @$options['target']), + true, + org_glizy_helpers_Html::renderTag('img', $attributes)); + return $output; + } + + /** + * @param $iconName + * @param $title + * @param $routing + * @param $params + * @param string $confirm + * + * @return string + */ + static function assetsLink( $iconName, $title, $routing, $params, $confirm='' ) + { + $params[ 'label' ] = __Assets::getIcon( $iconName, $title ); + $params[ 'title' ] = $title; + return org_glizy_helpers_Link::makeLink( $routing, $params, array(), $confirm ); + } + + + /** + * @param array $params + * @param bool $absolute + * + * @return string + */ + static function addParams($params=array(), $absolute=false) + { + $url = __Routing::$queryString; + + if (count($params)) + { + foreach($params as $k=>$v) + { + if (preg_match('/'.$k.'=/', $url)) + { + $url = preg_replace('/('.$k.'=)([^\&]*)/', $k.'='.$v, $url); + } + else + { + $url .= '&'.$k.'='.$v; + } + + } + } + //$url = preg_replace('/&(?!amp;)/i', '&amp;', $url); + return __Routing::scriptUrlWithParams( $url, $absolute ); + } + + /** + * @param array $params + * + * @return string + */ + static function addParamsJS( $params=array() ) + { + $url = org_glizy_helpers_Link::addParams( $params, true ); + return 'location.href = \''.$url.'\''; + } + + + /** + * @param array $params + * @param null $url + * + * @return string + */ + static function removeParams($params=array(), $url = null) + { + if ( is_null( $url ) ) + { + $url = __Routing::$queryString; + } + + if (count($params)) + { + foreach($params as $v) + { + if (preg_match('/('.$v.'=)([^\&]*)(\&?)/', $url)) + { + $url = preg_replace('/('.$v.'=)([^\&]*)(\&?)/', '', $url); + } + } + } + $url = trim($url, '&'); + return __Routing::scriptUrlWithParams( $url ); + } + + /** + * @param array $params + * + * @return string + */ + static function removeParamsJS( $params=array() ) + { + $url = org_glizy_helpers_Link::removeParams( $params, true ); + return 'location.href = \''.$url.'\''; + } + + /** + * @param $language + * @param $languageCode + * + * @return string + */ + static function makeLanguageSwitch($language, $languageCode) + { + // TODO sef e routing + $scriptUrl = $_SERVER["QUERY_STRING"]; + if (empty($scriptUrl)) $scriptUrl = org_glizy_Paths::get('PAGE_INDEX').'?'.$languageCode.'/1/home'; + else $scriptUrl = org_glizy_Paths::get('PAGE_INDEX').'?'.preg_replace('/([^\/]*)(\/.*)$/', $languageCode.'$2', $scriptUrl ); + return org_glizy_helpers_Link::makeSimpleLink($language, $scriptUrl); + } + + + + /** + * @param bool $removeGetParams + * + * @return string + */ + static function scriptUrl($removeGetParams=false) + { + if (!$removeGetParams) + { + return org_glizy_Paths::get('PAGE_INDEX').'?'.$_SERVER["QUERY_STRING"]; + } + else + { + list($url) = explode('&', $_SERVER["QUERY_STRING"]); + return org_glizy_Paths::get('PAGE_INDEX').'?'.$url; + } + } + + /** + * @return string + */ + static function getUrlFromRequest() + { + $requestValues = __Request::getAllAsArray(); + $url = array(); + + foreach ( $requestValues as $k=>$v ) + { + if ( empty( $v ) ) continue; + + if ( is_array( $v ) ) + { + for( $i = 0; $i < count( $v ); $i++ ) + { + $url[] = $k.'[]='.$v[ $i ]; + } + } + else + { + $url[] = $k.'='.$v; + } + } + return org_glizy_Paths::get('PAGE_INDEX').'?'.implode( '&', $url ); + } + + + /** + * @param $text + * @param bool $absolute + * + * @return mixed + */ + static function parseInternalLinks($text, $absolute = false ) + { + $serverUrl = $absolute ? GLZ_HOST_ROOT.'/' : ''; + preg_match_all('/<a.*href=["\'](internal\:)(\d*)["\'].*/Ui', $text, $internalLinks); + if (count($internalLinks) && count($internalLinks[0])) + { + for ($i=0; $i<count($internalLinks[0]); $i++) + { + $link = $serverUrl.org_glizy_helpers_Link::makeURL('link', array('pageId' => $internalLinks[2][$i])); + $originaLink = $internalLinks[0][$i]; + $newLink = str_replace('internal:'.$internalLinks[2][$i], $link, $originaLink); + $text = str_replace($originaLink, $newLink, $text); + } + } + + preg_match_all('/<a.*href=["\'](glossary\:)(.*)["\'].*/Ui', $text, $internalLinks); + if (count($internalLinks) && count($internalLinks[0])) + { + for ($i=0; $i<count($internalLinks[0]); $i++) + { + $link = $serverUrl.org_glizy_helpers_Link::makeURL('glossary', array('glossarydetail_term2' => '' )).urlencode($internalLinks[2][$i] ); + $originaLink = $internalLinks[0][$i]; + $newLink = str_replace('glossary:'.$internalLinks[2][$i], $link, $originaLink); + $text = str_replace($originaLink, $newLink, $text); + } + } + + preg_match_all('/<a.*href=["\'](media\:)(.*)(\:)(.*)["\'].*/Ui', $text, $internalLinks); + if (count($internalLinks) && count($internalLinks[0])) + { + for ($i=0; $i<count($internalLinks[0]); $i++) + { + $link = $serverUrl.'getFile.php?id='.$internalLinks[2][$i]; + $originaLink = $internalLinks[0][$i]; + $newLink = str_replace('media:'.$internalLinks[2][$i].":".$internalLinks[4][$i], $link, $originaLink); + $text = str_replace($originaLink, $newLink, $text); + } + } + + preg_match_all('/{{route:(.*)}}/Ui', $text, $internalLinks); + if (count($internalLinks) && count($internalLinks[0])) + { + for ($i=0; $i<count($internalLinks[0]); $i++) + { + $link = __Link::makeUrl($internalLinks[1][$i]); + $text = str_replace($internalLinks[0][$i], $link, $text); + } + } + preg_match_all('/{{config:(.*)}}/Ui', $text, $internalLinks); + if (count($internalLinks) && count($internalLinks[0])) + { + for ($i=0; $i<count($internalLinks[0]); $i++) + { + $link = __Config::get($internalLinks[1][$i]); + $text = str_replace($internalLinks[0][$i], $link, $text); + } + } + + // non è il massimo ma la regexp su testi lunghi crasha + $text = str_replace( array( 'href="#', 'href=\'#' ), array( 'href="'.__Routing::scriptUrl().'#', 'href=\''.__Routing::scriptUrl().'#' ), $text ); + // $text = preg_replace("/<(.*?)(href)\s*=\s*(\'|\")#(.*?)(\'|\")(.*?)>/si", "<$1$2=$3".__Routing::scriptUrl()."#$4$5$6>", $text); + + + if ( $absolute ) + { + $text = str_replace( 'src="getImage', 'src="'.$serverUrl.'getImage', $text); + $text = str_replace( 'src="cache/', 'src="'.$serverUrl.'cache/', $text); + } + return $text; + } + + /** + * @param $link + * @param null $label + * @param null $content + * @param string $cssClass + * + * @return mixed|string + */ + static function formatLink($link, $label=NULL, $content=NULL, $cssClass='') + { + if (is_null($label)) { + $label = $link; + } + if (is_null($content)) { + $content = $label; + } + if (!is_null($cssClass)) { + $cssClass = ' class="' . $cssClass . '"'; + } + $link = preg_replace("/^http:\/\//", "", $link); + $link = preg_replace('/&(?!amp;)/i', '&amp;', $link); + $protocol = ((strpos($link, "index.php")==0 && strpos($link, "index.php")!==false) || (strpos($link, "?")==0 && strpos($link, "?")!==false)) ? "":"http://"; + $target = ((strpos($link, "index.php")==0 && strpos($link, "index.php")!==false) || (strpos($link, "?")==0 && strpos($link, "?")!==false)) ? "internal":"external"; + + + $link = '<a href="'.$protocol.$link.'" rel="'.$target.'" title="'.$label.'"'.$cssClass.'>'.$content.'</a>'; + return $link; + } + + /** + * @param $link + * @param null $label + * @param null $content + * @param string $cssClass + * @param string $target + * + * @return string + */ + static function formatInternalLink($link, $label=NULL, $content=NULL, $cssClass='', $target='internal') + { + if (is_null($label)) { + $label = $link; + } + if (is_null($content)) { + $content = $label; + } + if (!is_null($cssClass)) { + $cssClass = ' class="' . $cssClass . '"'; + } + + $link = '<a href="'.$link.'" rel="'.$target.'" title="'.$label.'"'.$cssClass.'>'.$content.'</a>'; + return $link; + } + + + function makeLinkWithIcon($routeUrl, $iconName, $params, $deleteMsg=NULL, $addParam=array()) + { + $params['icon'] = $iconName; + $params['label'] = ''; + $deleteJs = ''; + if ( !is_null( $deleteMsg ) ) + { + $deleteJs = 'if (!confirm(\''.addslashes( $deleteMsg ).'\')){return false;}'; + } + return self::makeLink( $routeUrl, $params, $addParam, $deleteJs, false ); + } +} + +class __Link extends org_glizy_helpers_Link +{ +} diff --git a/src/core/classes/org/glizy/helpers/Mail.php b/src/core/classes/org/glizy/helpers/Mail.php new file mode 100644 index 0000000..cd73a64 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/Mail.php @@ -0,0 +1,224 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_helpers_Mail extends GlizyObject +{ + /** + * @param $to + * @param $from + * @param $subject + * @param $body + * @param array $attach + * @param array $cc + * @param array $bcc + * @param null $embedDir + * + * @return array + */ + static function sendEmail($to, $from, $subject, $body, $attach=array(), $cc=array(), $bcc=array(), $embedDir=NULL, $templateHeader='', $templateFooter='') + { + try + { + require_once(GLZ_LIBS_DIR."phpmailer/class.phpmailer.php"); + + /** @var PHPMailer $mail */ + $mail = new PHPMailer(); + $mail->CharSet = __Config::get('CHARSET'); + if (org_glizy_Config::get('SMTP_HOST')!='') + { + $mail->IsSMTP(); // telling the class to use SMTP + $mail->Host = org_glizy_Config::get('SMTP_HOST'); // SMTP server + if (org_glizy_Config::get('SMTP_USER')!='') + { + $mail->Username = org_glizy_Config::get('SMTP_USER'); + $mail->Password = org_glizy_Config::get('SMTP_PSW'); + } + $port = org_glizy_Config::get('SMTP_PORT'); + if ($port) { + $mail->Port = $port; + } + } + + $mail->From = trim($from['email']); + $mail->FromName = $from['name']; + $mail->AddAddress(trim($to['email']), $to['name']); + $mail->Subject = $subject; + + $mail->AddAddress(trim($to['email']), $to['name']); + + if ($cc) + { + if ( !is_array( $cc ) ) $cc = array( $cc ); + foreach( $cc as $v ) + { + if ($v) $mail->AddCC($v); + } + } + + if ($bcc) + { + if ( !is_array( $bcc ) ) $bcc = array( $bcc ); + foreach( $bcc as $v ) + { + if ($v) $mail->AddBCC($v); + } + } + + $bodyTxt = $body; + $bodyTxt = str_replace('<br>', "\r\n", $bodyTxt); + $bodyTxt = str_replace('<br />', "\r\n", $bodyTxt); + $bodyTxt = str_replace('</p>', "\r\n\r\n", $bodyTxt); + $bodyTxt = strip_tags($bodyTxt); + $bodyTxt = html_entity_decode($bodyTxt); + + if (!is_null($attach)){ + foreach ($attach as $a) + { + $mail->AddAttachment($a['fileName'], $a['originalFileName']); + } + } + + if (!is_null($embedDir)) + { + $processedImage = array(); + $embImage = 0; + // controlla se c'è da fare l'embed delle immagini + preg_match_all('/<img[^>]*src=("|\')([^("|\')]*)("|\')/i', $body, $inlineImages); + if (count($inlineImages) && count($inlineImages[2])) + { + for ($i=0;$i<count($inlineImages[2]);$i++) + { + if (in_array($inlineImages[2][$i], $processedImage)) continue; + $processedImage[] = $inlineImages[2][$i]; + + $embImage++; + $imageType = explode('.', $inlineImages[2][$i]); + $code = str_pad($embImage, 3, '0', STR_PAD_LEFT); + $mail->AddEmbeddedImage($embedDir.$inlineImages[2][$i], $code, $inlineImages[2][$i], "base64", "image/".$imageType[count($imageType)-1]); + $body = str_replace($inlineImages[2][$i], 'cid:'.$code, $body); + } + } + + preg_match_all('/<td[^>]*background=("|\')([^("|\')]*)("|\')/i', $body, $inlineImages); + if (count($inlineImages) && count($inlineImages[2])) + { + for ($i=0;$i<count($inlineImages[2]);$i++) + { + if (in_array($inlineImages[2][$i], $processedImage)) continue; + $processedImage[] = $inlineImages[2][$i]; + + $embImage++; + $imageType = explode('.', $inlineImages[2][$i]); + $code = str_pad($embImage, 3, '0', STR_PAD_LEFT); + $mail->AddEmbeddedImage($embedDir.$inlineImages[2][$i], $code, $inlineImages[2][$i], "base64", "image/".$imageType[count($imageType)-1]); + $body = str_replace($inlineImages[2][$i], 'cid:'.$code, $body); + } + } + } + + $mail->Body = $templateHeader.$body.$templateFooter; + $mail->AltBody = $bodyTxt; + + $r = array('status' => $mail->Send(), + 'error' => $mail->ErrorInfo); + + } + catch (Exception $e) + { + $r = array('status' => false, + 'error' => $e->getMessage()); + } + + if (isset($mail)) { + $smtp_host = $mail->Host; + $smtp_port = $mail->Port; + } else { + $smtp_host = ''; + $smtp_port = ''; + } + + $eventInfo = array('type' => GLZ_LOG_EVENT, 'data' => array( + 'level' => $r['status'] ? GLZ_LOG_DEBUG : GLZ_LOG_ERROR, + 'group' => 'glizy.helpers.Mail', + 'message' => array('result' => $r, + 'to' => $to, + 'from' => $from, + 'subject' => $subject, + 'body' => $body, + 'attach' => $attach, + 'cc' => $cc, + 'bcc' => $bcc, + 'smtp_host' => $smtp_host, + 'smtp_port' => $smtp_port + ))); + + $evt = org_glizy_ObjectFactory::createObject( 'org.glizy.events.Event', null, $eventInfo ); + org_glizy_events_EventDispatcher::dispatchEvent( $evt ); + + return $r; + } + + /** + * @param string $fileName + * @param array $info + * @param string $htmlTemplateHeader + * @param string $htmlTemplateFooter + * @param string $templatePath + * @return array + */ + static function sendEmailFromTemplate( $fileName, $info, $htmlTemplateHeader = '', $htmlTemplateFooter = '', $templatePath = '') + { + /** @var org_glizy_application_Application $application */ + $application = org_glizy_ObjectValues::get('org.glizy', 'application' ); + $templatePath = $templatePath ? $templatePath : __Paths::get( 'APPLICATION_STATIC' ) . '/templatesEmail/'. $application->getLanguage() .'/'; + $emailText = file_get_contents( $templatePath.$fileName.'.txt' ); + $emailText = explode( "\n", $emailText ); + $emailTitle = array_shift( $emailText ); + $emailBody = implode( "\n<br />", $emailText ); + foreach( $info as $k => $v ) + { + $emailBody = str_replace('##'.$k.'##', $v, $emailBody); + $emailTitle = str_replace('##'.$k.'##', $v, $emailTitle); + } + + if ($htmlTemplateHeader && $htmlTemplateFooter) { + $emailBody = file_get_contents($templatePath.$htmlTemplateHeader). + $emailBody. + file_get_contents($templatePath . $htmlTemplateFooter); + } + + return org_glizy_helpers_Mail::sendEmail( array('email' => $info['EMAIL'], 'name' => $info['FIRST_NAME'].' '.$info['LAST_NAME'] ), + array('email' => org_glizy_Config::get('SMTP_EMAIL'), 'name' => org_glizy_Config::get('SMTP_SENDER')), + $emailTitle, + $emailBody, + $info['ATTACHS'], + $info['CC'], + $info['BCC'] + ); + } + + /** + * @return array + */ + static function getEmailInfoStructure() + { + $info = array(); + $info['EMAIL'] = ''; + $info['FIRST_NAME'] = ''; + $info['LAST_NAME'] = ''; + $info['USER'] = ''; + $info['PASSWORD'] = ''; + $info['URL_SITE'] = org_glizy_helpers_Link::makeSimpleLink(GLZ_HOST, GLZ_HOST); + $info['HOST'] = GLZ_HOST; + $info['ATTACHS'] = array(); + $info['BCC'] = array(); + $info['CC'] = array(); + return $info; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/Media.php b/src/core/classes/org/glizy/helpers/Media.php new file mode 100755 index 0000000..d3150b4 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/Media.php @@ -0,0 +1,16 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Moved in Glizycms + * This class is for compatibility with old projects + */ +class org_glizy_helpers_Media extends org_glizycms_helpers_Media +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/Navigation.php b/src/core/classes/org/glizy/helpers/Navigation.php new file mode 100755 index 0000000..3c8c0a7 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/Navigation.php @@ -0,0 +1,33 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_helpers_Navigation extends GlizyObject +{ + + /** + * @param $location + * @param $params + */ + static function gotoUrl($location, $params=null, $hash='') + { + if ($params) { + $location .= (strpos($location, '?')===false ? '?' : '&').http_build_query($params); + } + header('Location: '.$location.$hash); + echo '<html><head><meta http-equiv="refresh" content="1;url='.$location.'"/></head></html>'; + exit; + } + + function goHere() + { + /** @var org_glizy_application_Application $application */ + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + org_glizy_helpers_Navigation::gotoUrl( org_glizy_helpers_Link::makeUrl( 'link', array( 'pageId' => $application->getPageId() ) ) ); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/PhpScript.php b/src/core/classes/org/glizy/helpers/PhpScript.php new file mode 100755 index 0000000..2d05fb4 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/PhpScript.php @@ -0,0 +1,53 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_helpers_PhpScript +{ + static function parse($phpcode) + { + $phpcode = preg_replace("/\{php\:(.*)\}/i", "$1", $phpcode); + $phpcode = str_replace('.', '->', $phpcode); + $phpcode = str_replace('->->', '.', $phpcode); + $phpcode = preg_replace('/\bnot\b/i', ' !', $phpcode); + $phpcode = preg_replace('/\bne\b/i', ' != ', $phpcode); + $phpcode = preg_replace('/\band\b/i', ' && ', $phpcode); + $phpcode = preg_replace('/\bor\b/i', ' || ', $phpcode); + $phpcode = preg_replace('/\blt\b/i', ' < ', $phpcode); + $phpcode = preg_replace('/\bgt\b/i', ' > ', $phpcode); + $phpcode = preg_replace('/\bge\b/i', ' >= ', $phpcode); + $phpcode = preg_replace('/\ble\b/i', ' <= ', $phpcode); + $phpcode = preg_replace('/\beq\b/i', ' == ', $phpcode); + if (substr($phpcode,-1,1)!=';') $phpcode .= ';'; + if ('return '!= substr($phpcode,0,7)) $phpcode = 'return '.$phpcode; + $phpcode = '$application = &org_glizy_ObjectValues::get(\'org.glizy\', \'application\'); $user = &$application->getCurrentUser(); $menu = &$application->getCurrentMenu();'.$phpcode; + return $phpcode; + } + + static function callMethodWithParams( $actionClass, $method, $callParams=null ) + { + if ( is_object( $actionClass ) ) + { + $reflectionClass = new ReflectionClass( $actionClass ); + $params = __Request::getParams(); + if ( $reflectionClass->hasMethod( $method ) ) + { + $reflectionMethod = $reflectionClass->getMethod( $method ); + $methodParams = $reflectionMethod->getParameters(); + $params = array(); + foreach( $methodParams as $v ) + { + $params[] = is_array($callParams) && isset($callParams[$v->name]) ? $callParams[$v->name] : __Request::get( $v->name ); + } + return call_user_func_array( array( $actionClass, $method ), $params ); + } + } + + return false; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/helpers/String.php b/src/core/classes/org/glizy/helpers/String.php new file mode 100755 index 0000000..b4f11f3 --- /dev/null +++ b/src/core/classes/org/glizy/helpers/String.php @@ -0,0 +1,61 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_helpers_String +{ + function formatFileSize($size) + { + if($size<1024) + { + return $size.' bytes'; + } + else if($size<1048576) + { + return round(($size/1024), 1 ).' kb'; + } + else + { + return round(($size/1048576), 1).' Mb'; + } + } + + // code based on http://www.php.net/manual/en/function.substr.php#70417 + // by feedback at realitymedias dot com + + function strtrim($str, $maxlen=100, $elli=NULL, $stripTags=false, $maxoverflow=15) + { + if ($stripTags) + { + $str = str_replace('</p>', '</p> ', $str); + $str = str_replace('<br', ' <br', $str); + return strip_tags($str); + } + if (strlen($str) > $maxlen) + { + $output = NULL; + $body = explode(" ", $str); + $body_count = count($body); + + $i=0; + + do { + $output .= $body[$i]." "; + $thisLen = strlen($output); + $cycle = ($thisLen < $maxlen && $i < $body_count-1 && ($thisLen+strlen($body[$i+1])) < $maxlen+$maxoverflow?true:false); + $i++; + } while ($cycle); + return $output.$elli; + } + else return $str; + } +} + +class __String extends org_glizy_helpers_String +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/locale/Locale.php b/src/core/classes/org/glizy/locale/Locale.php new file mode 100755 index 0000000..c902443 --- /dev/null +++ b/src/core/classes/org/glizy/locale/Locale.php @@ -0,0 +1,79 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_locale_Locale extends GlizyObject +{ + + /** + * @return mixed|string + */ + static function get() + { + $args = func_get_args(); + $code = array_shift($args); + $values = &org_glizy_ObjectValues::get('org.glizy.locale.Locale'); + if (!isset($values[$code])) + { + return glz_encodeOutput( $code ); + } + if (is_array($values[$code])) return $values[$code]; + if (strpos($values[$code], '<')!==false) return vsprintf($values[$code], $args); + + return glz_encodeOutput(vsprintf($values[$code], $args)); + } + + /** + * @return mixed|string + */ + static function getPlain() + { + $args = func_get_args(); + $code = array_shift($args); + $values = &org_glizy_ObjectValues::get('org.glizy.locale.Locale'); + if (!isset($values[$code])) + { + return $code; + } + if (is_array($values[$code])) return $values[$code]; + if (strpos($values[$code], '<')!==false) return vsprintf($values[$code], $args); + + return vsprintf($values[$code], $args); + } + + /** + * @param array $newValues + */ + static function append($newValues) + { + $values = &org_glizy_ObjectValues::get('org.glizy.locale.Locale', '', array()); + $values = array_merge($values, $newValues); + } + +} + +/* shortcut */ +/** + * @return mixed + */ +function __T() +{ + $l = new org_glizy_locale_Locale(); + $args = func_get_args(); + return call_user_func_array(array($l, 'get'), $args); +} + +/** + * @return mixed + */ +function __Tp() +{ + $l = new org_glizy_locale_Locale(); + $args = func_get_args(); + return call_user_func_array(array($l, 'getPlain'), $args); +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/locale/de.php b/src/core/classes/org/glizy/locale/de.php new file mode 100755 index 0000000..e4afa0f --- /dev/null +++ b/src/core/classes/org/glizy/locale/de.php @@ -0,0 +1,188 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +$strings = array ( + 'GLZ_DATE_FORMAT' => "d/m/Y", + 'GLZ_DATETIME_FORMAT' => "d/m/Y H:i:s", + 'GLZ_DATE_TOISO_REGEXP' => array("|^(\d{1,2})\/(\d{1,2})\/(\d{4})$|", "$3-$2-$1"), + 'GLZ_DATE_TOTIME_REGEXP' => array("|^(\d{1,2})\/(\d{1,2})\/(\d{4})$|", "$3-$2-$1 00:00:00"), + 'GLZ_DATETIME_TOTIME_REGEXP' => array("|^(\d{1,2})\/(\d{1,2})\/(\d{4})\s*(\d{1,2}):(\d{1,2}):(\d{1,2})$|", "$3-$2-$1 $4:$5:$6"), + 'GLZ_TIME_TO_DATE_REGEXP' => array("|^(\d{4})-(\d{1,2})-(\d{1,2})$|", "$3/$2/$1"), + 'GLZ_TIME_TO_DATETIME_REGEXP' => array("|^(\d{4})-(\d{1,2})-(\d{1,2})\s*(\d{1,2}):(\d{1,2}):(\d{1,2})$|", "$3/$2/$1 $4:$5:$6"), + "GLZ_MONTHS" => array( "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember" ), + "GLZ_WARNING" => "Achtung", + "GLZ_ERROR" => "Fehler", + "GLZ_NEW_PAGE" => "Neue Seite", + "GLZ_CREATINING_NEW_PAGE" => "Neue Seite erstellen", + "GLZ_INSERT_NEW_PAGE" => "Neue Seite einfügen", + "GLZ_PAGE_TITLE" => "Titel", + "GLZ_PAGE_TITLE_LINK" => "Seitentitel für Navigation", + "GLZ_PAGE_TITLE_ALT" => "Alt-Text für Navigation", + "GLZ_PAGE_SELECT" => "Seite auswählen", + "GLZ_PAGE_SELECT_PARENT" => "Ãœbergeordnete Seite auswählen", + "GLZ_PAGE_SELECT_TYPE" => "Seitentyp auswählen", + "GLZ_PAGE_PAGEID" => "Seiten-ID", + "GLZ_PAGE_LINKED_URL" => "Verknüpfte URL", + "GLZ_PAGE_KEYWORDS" => "Schlüsselwörter", + "GLZ_PAGE_DESCRIPTION" => "Kurzbeschreibung", + "GLZ_CONFIRM" => "Bestätigen", + "GLZ_CANCEL" => "Abbrechen", + "GLZ_UPLOAD" => "Upload", + "GLZ_RESET" => "Zurücksetzen", + "GLZ_PREVIEW" => "Seitenvorschau", + "GLZ_SEARCH" => "Suche", + "GLZ_NEW_SEARCH" => "Neue Suche", + "GLZ_PUBLISHED" => "Veröffentlicht, zum ändern klicken", + "GLZ_UNPUBLISHED" => "Unveröffentlicht, zum ändern klicken", + "GLZ_SEARCH_FILTERS" => "Suchfilter", + "GLZ_SEARCH_MEDIA" => "", + "GLZ_SITEMAP_TITLE" => "Seitenstruktur", + "GLZ_SITEMAP_MSG_DELETE" => "Soll die Seite wirklich gelöscht werden?", + "GLZ_SITEMAP_NEW" => "Eine Seite auf einer Ebene tiefer einfügen", + "GLZ_SITEMAP_UP" => "Seite nach oben verschieben", + "GLZ_SITEMAP_DOWN" => "Seite nach unten verschieben", + "GLZ_SITEMAP_EDIT" => "Seiteninhalt bearbeiten", + "GLZ_SITEMAP_EDITDRAFT" => "Seitenentwurf bearbeiten", + "GLZ_SITEMAP_DELETE" => "Seite und Unterseiten löschen", + "GLZ_SITEMAP_PUBLISH" => "Seite veröffentlichen ", + "GLZ_SITEMAP_VISIBLE" => "Seite verstecken", + "GLZ_SITEMAP_INVISIBLE" => "Seite anzeigen", + "GLZ_SITEMAP_PREVIEW" => "Seitenvorschau", + "GLZ_SITEMAP_LOCK" => "Seitenstatus bearbeiten: geschützt/nicht geschützt", + "GLZ_MODIFY_PAGE_CONTENT" => "Seiteninhalt bearbeiten", + "GLZ_MODIFY_PAGE_DETAILS" => "Seiteneigenschaften bearbeiten", + "GLZ_RECORD_ADD_BEFORE" => "Neuer Eintrag davor", + "GLZ_RECORD_ADD" => "Neuer Eintrag danach", + "GLZ_RECORD_MOVE_UP" => "Noch oben", + "GLZ_RECORD_MOVE_DOWN" => "nach unten", + "GLZ_RECORD_DELETE" => "Löschen", + "GLZ_RECORD_DELETE_VERSION" => "Version löschen", + "GLZ_RECORD_EDIT" => "Eintrag bearbeiten", + "GLZ_RECORD_PUBLISH" => "Veröffentlichen", + "GLZ_RECORD_PREVIEW" => "Vorschau", + "GLZ_RECORD_MSG_DELETE" => "Soll der ausgewählte Eintrag gelöscht werden?", + "GLZ_RECORDS_MSG_DELETE" => "Sollen die ausgewählten Einträge gelöscht werden?", + "GLZ_RECORD_NEW_TITLE" => "Eintrag in '%s' ", + "GLZ_RECORD_EDIT_TITLE" => "Eintrag bearbeiten in '%s'", + "GLZ_RECORD_EDITDEF_TITLE" => "Eintrag bearbeiten", + "GLZ_SAVE" => "Speichern", + "GLZ_SAVE_DRAFT" => "Entwurf speichern", + "GLZ_SAVE_DRAFT_CLOSE" => "Als Volage speichern und schliessen", + "GLZ_SAVE_CLOSE" => "Speichern und schliessen", + "GLZ_PAGE_SUBTITLE" => "Untertitel", + "GLZ_JUMP_TO" => "Springe zu Seite:", + "GLZ_CLOSE_PICKER" => "Schliessen", + "GLZ_ADD_MEDIA" => "Medienobjekt hinzufügen", + "GLZ_PAGE_NUM" => "Seite", + "GLZ_MEDIAM_IMAGELIST" => "Verfügbare Bilder", + "GLZ_MEDIAM_MEDIALIST" => "Verfügbare Medien", + "GLZ_MEDIAM_EDIT" => "Eintrag bearbeiten", + "GLZ_MEDIAM_PREVIEW" => "Vorschau", + "GLZ_MEDIAM_TITLE" => "Titel", + "GLZ_MEDIAM_SHORTTITLE" => "Kurztitel", + "GLZ_MEDIAM_NULL" => "Keine Auswahl", + "GLZ_MEDIAM_CHOICE" => "Medien auswählen", + "GLZ_MEDIAM_NO_IMG" => "Kein Bild ausgewählt, bittte klicken Sie für die Auswahl", + "GLZ_MEDIAM_CURRENT_IMG" => "Aktuelles Bild", + "GLZ_MEDIAM_IMG_CHANGED" => "Bild ausgewechselt", + "GLZ_MEDIAM_CUSTOM_PATH" => "Uploadpfad", + "GLZ_MEDIAM_FILE_TYPE" => "Dateityp", + "GLZ_MEDIAM_SELECT_FILE" => "Dateiauswahl", + "GLZ_MEDIAM_UPLOAD_GENERIC_TITLE" => "Medienobjekt hochladen", + "GLZ_MEDIAM_UPLOAD_TITLE" => "Datei hochladen", + "GLZ_MEDIAM_UPLOAD_DONE" => "Hochladen abgeschlossen", + "GLZ_MEDIAM_DELETE_DONE" => "Löschung abgeschlossen", + "GLZ_MEDIAM_NO_FILE" => "Keine Datei ausgewählt, bittte klicken Sie für die Auswahl", + "GLZ_MEDIAM_EDITING" => "Medieneigenschaften bearbeiten", + "GLZ_MEDIAM_MSG_DELETE" => "Sollen die ausgewählten Medienobjekte gelöscht werden?", + "GLZ_MEDIAM_ERR_NO_FILE" => "Keine Datei ausgewählt", + "GLZ_MEDIAM_ERR_INI_SIZE" => "Datei zu groß", + "GLZ_MEDIAM_ERR_PARTIAL" => "Fehler beim Upload", + "GLZ_MEDIAM_ERR_FORM_SIZE" => "Datei zu groß", + "GLZ_MEDIAM_ERR_CREATE_DIR" => "Fehler beim Erstellen des Ordners: '%s'", + "GLZ_MEDIAM_ERR_COPYING" => "Fehler beim Kopieren, Speichermedium ist voll", + "GLZ_MEDIAM_ERR_IMAGE_SIZE" => "Fehler: Bildgröße überschreitet das Maximum (%s)", + "GLZ_MEDIAM_ERR_NOGDLOADED" => "PHP gd libraries plugin nicht geladen", + "GLZ_MEDIA_TITLE" => "Titel", + "GLZ_MEDIA_FILENAME" => "Dateiname", + "GLZ_MEDIA_CATEGORY" => "Kategorie", + "GLZ_MEDIA_SIZE" => "Dateigröße", + "GLZ_ADD_NEW_RECORD" => "Neuen Eintrag hinzufügen", + "GLZ_SAVE_REVISION" => "Als neuer Version speichern", + "GLZ_MODIFY_LIST" => "Liste bearbeiten", + "GLZ_CHANGE_LANGUAGE" => "Sprache wechseln", + "GLZ_PAGE_CONTENT" => "Seiteninhalt", + "GLZ_PAGE_PROP" => "Seiteneigenschaften", + "GLZ_MODIFY1" => "Veröffentlichte Version bearbeiten", + "GLZ_MODIFY2" => "Letzte Prüfung bearbeiten", + "GLZ_LAST_REVSION" => "Letzte Prüfung", + "GLZ_LOGIN_ERROR" => "Der angegebene Nutzer oder das Passwort existieren nicht", + "GLZ_LOGIN_NOACCESS" => "Zugriff verweigert, bitte melden Sie sich an", + "LOGGER_INSUFFICIENT_GROUP_LEVEL" => "Seite erfordert höhere Zugriffsrechte", + "LOGGER_INSUFFICIENT_USER_LEVEL" => "Seite mit aktuellem Account nicht aufzurufen. Bitte kontakjtieren Sie Ihren System-Administrator", + "GLZ_LOGIN_DISABLED" => "Ihr Account wurde gesperrt. Bitte kontaktieren Sie Ihren Systemadministrator", + "GLZ_LANGUAGE_LIST" => "Liste der Sprachen", + "GLZ_LANGUAGE_EDIT" => "Sprache bearbeiten", + "GLZ_LANGUAGE" => "Sprache", + "GLZ_LANGUAGE_CODE" => "Code", + "GLZ_LANGUAGE_DEFAULT" => "Standardsprache", + "GLZ_LANGUAGE_ORDER" => "Sortierreihenfolge", + "GLZ_LABEL" => "Label", + "GLZ_EDIT_LANGUAGE" => "Verwendete Sprachen", + "GLZ_SEARCH_LABEL" => "Suchbegriff:", + "GLZ_SEARCH_BUTTON" => "Start", + "GLZ_SEARCH_COMMENT" => "Bitte geben Sie mehr als drei /eichen ein", + "GLZ_SEARCH_RESULT" => "Suchergebnisse", + "GLZ_SEARCH_RESULT_TOTAL" => "Seiten gefunden:", + "LOGGED_MESSAGE" => "Guten Tag %s", + "GLZ_ERR_EMPTY_APP_PATH" => "Der Applikationspfad darf nicht leer sein", + "GLZ_ERR_NO_PAGETYPE_FOLDER" => "Kann pageType-application-Ordner nicht öffnen", + "GLZ_ERR_404" => "Seite nicht gefunden", + "GLZ_USER_LIST_TITLE" => "Nutzerliste", + "GLZ_USER_EDIT_TITLE" => "Nutzer bearbeiten", + "GLZ_USER_EDIT" => "Nutzer bearbeiten", + "GLZ_USER_FIRST" => "Vorname", + "GLZ_USER_LAST" => "Nachname", + "GLZ_USER_EMAIL" => "Email", + "GLZ_USER_ACTIVE" => "Aktiv", + "GLZ_USER_IS_ACTIVE" => "Aktive Nutzer", + "GLZ_USER_LOGINID" => "Nutzername", + "GLZ_USER_PASSWORD" => "Passwort", + "GLZ_USER_GROUP" => "Gruppe", + "GLZ_LOGIN_REMEMBER" => "Anmeldung speichern", + "GLZ_ENABLED" => "Freigeschaltet", + "GLZ_ENABLE" => "Freischalten", + "GLZ_DISABLED" => "Gesperrt", + "GLZ_DISABLE" => "sperren", + "GLZ_USERGROUP_LIST_TITLE" => "Liste der Gruppen", + "GLZ_USERGROUP_EDIT_TITLE" => "Gruppe bearbeiten", + "GLZ_USERGROUP_EDIT" => "Gruppe bearbeiten", + "GLZ_USERGROUP_NAME" => "Gruppenname", + "GLZ_USERGROUP_INTERNAL" => "Interner Nutzer", + "GLZ_MODULE_SHOW_TITLE" => "Seitentitel anzeigen", + "GLZ_MODULE_LINKED" => "Art der Verlinkung", + "GLZ_TOTAL_RECORDS" => "Alle Einträge", + "GLZ_PROTECTED_PAGE" => "reservierte Seite", + "GLZ_LINKED_URL" => "Verknüpfte URL", + "GLZ_CREATION_DATE" => "Erstellungsdatum", + "GLZ_DOWNLOAD_FILE" => "Datei zum Download", + "GLZ_DOWNLOAD_FILE_LINK" => "Download Datei: #title#, #size#", + "GLZ_ADDMEDIA" => "Neues Medienobjekt", + "GLZ_NOIMAGE" => "Kein Bild", + "GLZ_NOMEDIA" => "Kein Medienobjekt", + "GLZ_URL_LINK" => "URL-Link", + "GLZ_PRINT_PDF" => "Print PDF", + "GLZ_ENABLE_PAGE_COMMENTS" => "Aktivieren Kommentare", + "GLZ_PREVIOUS" => "früher", + "GLZ_NEXT" => "nächste", + "GLZ_COLSE"=> "Schließen", + "GLZ_SLIDESHOW_START" => "slideshow start", + "GLZ_SLIDESHOW_STOP" => "slideshow stoppen", +); +org_glizy_locale_Locale::append($strings); \ No newline at end of file diff --git a/src/core/classes/org/glizy/locale/en.php b/src/core/classes/org/glizy/locale/en.php new file mode 100755 index 0000000..7abd288 --- /dev/null +++ b/src/core/classes/org/glizy/locale/en.php @@ -0,0 +1,194 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +$strings = array ( + 'GLZ_DATE_FORMAT' => "Y-m-d", + 'GLZ_DATETIME_FORMAT' => "Y-m-d h:i:s A", + 'GLZ_DATE_TOISO_REGEXP' => array("|^(\d{4})-(\d{1,2})-(\d{1,2})$|", "$1-$2-$3"), + 'GLZ_DATE_TOTIME_REGEXP' => array("|^(\d{4})-(\d{1,2})-(\d{1,2})$|", "$1-$2-$3 00:00:00"), + 'GLZ_DATETIME_TOTIME_REGEXP' => array("|^(\d{4})-(\d{1,2})-(\d{1,2})\s*(\d{1,2}):(\d{1,2}):(\d{1,2})$|", "$1-$2-$3 $4:$5:$6"), + 'GLZ_TIME_TO_DATE_REGEXP' => array("|^(\d{4})-(\d{1,2})-(\d{1,2})$|", "$1-$2-$3 00:00:00"), + 'GLZ_TIME_TO_DATETIME_REGEXP' => array("|^(\d{4})-(\d{1,2})-(\d{1,2})\s*(\d{1,2}):(\d{1,2}):(\d{1,2})$|", "$1-$2-$3 $4:$5:$6"), + "GLZ_MONTHS" => array( "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ), + "GLZ_WARNING" => "Warning", + "GLZ_ERROR" => "Error", + "GLZ_NEW_PAGE" => "New page", + "GLZ_CREATINING_NEW_PAGE" => "Create new page", + "GLZ_INSERT_NEW_PAGE" => "Insert new page", + "GLZ_PAGE_TITLE" => "Title", + "GLZ_PAGE_TITLE_LINK" => "Page title for navigation bar", + "GLZ_PAGE_TITLE_ALT" => "Alt text for navigation bar", + "GLZ_PAGE_SELECT" => "Select page", + "GLZ_PAGE_SELECT_PARENT" => "Select parent page", + "GLZ_PAGE_SELECT_TYPE" => "Select page type", + "GLZ_PAGE_PAGEID" => "Page ID", + "GLZ_PAGE_LINKED_URL" => "Connected URL", + "GLZ_PAGE_KEYWORDS" => "Keywords", + "GLZ_PAGE_DESCRIPTION" => "Short description", + "GLZ_CONFIRM" => "Confirm", + "GLZ_CANCEL" => "Cancel", + "GLZ_UPLOAD" => "Upload", + "GLZ_RESET" => "Reset form", + "GLZ_PREVIEW" => "Page view", + "GLZ_SEARCH" => "Search", + "GLZ_NEW_SEARCH" => "New search", + "GLZ_PUBLISHED" => "Published, click-on for change", + "GLZ_UNPUBLISHED" => "Unpublished, click-on for change", + "GLZ_SEARCH_FILTERS" => "Search filters", + "GLZ_SEARCH_MEDIA" => "", + "GLZ_SITEMAP_TITLE" => "Site structure", + "GLZ_SITEMAP_MSG_DELETE" => "Do you really want to cancel the page?", + "GLZ_SITEMAP_NEW" => "Add a new page at lower level", + "GLZ_SITEMAP_UP" => "Move the page up", + "GLZ_SITEMAP_DOWN" => "Move the page down", + "GLZ_SITEMAP_EDIT" => "Edit the page contents", + "GLZ_SITEMAP_EDITDRAFT" => "Edit the page draft", + "GLZ_SITEMAP_DELETE" => "Delete the page and its sub-pages", + "GLZ_SITEMAP_PUBLISH" => "Publish the page", + "GLZ_SITEMAP_VISIBLE" => "It makes the page invisible", + "GLZ_SITEMAP_INVISIBLE" => "It makes the page visible", + "GLZ_SITEMAP_PREVIEW" => "Page view", + "GLZ_SITEMAP_LOCK" => "Edit the page status: protected/not protected", + "GLZ_MODIFY_PAGE_CONTENT" => "Edit the page content", + "GLZ_MODIFY_PAGE_DETAILS" => "Edit page details", + "GLZ_RECORD_ADD_BEFORE" => "Add a record before", + "GLZ_RECORD_ADD" => "Add ", + "GLZ_RECORD_MOVE_UP" => "Move up", + "GLZ_RECORD_MOVE_DOWN" => "Move down", + "GLZ_RECORD_DELETE" => "Delete", + "GLZ_RECORD_DELETE_VERSION" => "Delete version", + "GLZ_RECORD_EDIT" => "Edit ", + "GLZ_RECORD_PUBLISH" => "Publish", + "GLZ_RECORD_PREVIEW" => "Preview ", + "GLZ_RECORD_MSG_DELETE" => "Are you sure to delete the selected record?", + "GLZ_RECORDS_MSG_DELETE" => "Are you sure to delete the selected records?", + "GLZ_RECORD_NEW_TITLE" => "Insert record in '%s'", + "GLZ_RECORD_EDIT_TITLE" => "Edit record in '%s'", + "GLZ_RECORD_EDITDEF_TITLE" => "Edit record", + "GLZ_SAVE" => "Save", + "GLZ_PUBLISH" => "Publish", + "GLZ_SAVE_DRAFT" => "Save draft", + "GLZ_SAVE_DRAFT_CLOSE" => "Save as draft and close", + "GLZ_SAVE_CLOSE" => "Save and close", + "GLZ_PUBLISH_CLOSE" => "Publish and close", + "GLZ_CLOSE" => 'Close', + "GLZ_PAGE_SUBTITLE" => "Subtitle", + "GLZ_JUMP_TO" => "Jump to page:", + "GLZ_CLOSE_PICKER" => "Close", + "GLZ_ADD_MEDIA" => "Add media", + "GLZ_PAGE_NUM" => "Page", + "GLZ_MEDIAM_IMAGELIST" => "Available images", + "GLZ_MEDIAM_MEDIALIST" => "Available media", + "GLZ_MEDIAM_EDIT" => "Edit media", + "GLZ_MEDIAM_PREVIEW" => "Preview", + "GLZ_MEDIAM_TITLE" => "Title", + "GLZ_MEDIAM_SHORTTITLE" => "Short title", + "GLZ_MEDIAM_NULL" => "Null", + "GLZ_MEDIAM_CHOICE" => "Select media", + "GLZ_MEDIAM_NO_IMG" => "No image selected, please click on to select one.", + "GLZ_MEDIAM_CURRENT_IMG" => "Current image:", + "GLZ_MEDIAM_IMG_CHANGED" => "Changed image", + "GLZ_MEDIAM_CUSTOM_PATH" => "Upload path", + "GLZ_MEDIAM_FILE_TYPE" => "File type", + "GLZ_MEDIAM_SELECT_FILE" => "Select file", + "GLZ_MEDIAM_UPLOAD_GENERIC_TITLE" => "Media upload", + "GLZ_MEDIAM_UPLOAD_TITLE" => "File Upload:", + "GLZ_MEDIAM_UPLOAD_DONE" => "Upload done", + "GLZ_MEDIAM_DELETE_DONE" => "File deleted", + "GLZ_MEDIAM_NO_FILE" => "No file selected, please click on to select.", + "GLZ_MEDIAM_EDITING" => "Edit media details", + "GLZ_MEDIAM_MSG_DELETE" => "Are you sure to delete the selected media?", + "GLZ_MEDIAM_ERR_NO_FILE" => "No file selected", + "GLZ_MEDIAM_ERR_INI_SIZE" => "File too big", + "GLZ_MEDIAM_ERR_PARTIAL" => "Upload error", + "GLZ_MEDIAM_ERR_FORM_SIZE" => "File too big", + "GLZ_MEDIAM_ERR_CREATE_DIR" => "Error during directory creation: '%s'", + "GLZ_MEDIAM_ERR_COPYING" => "Error during file copyng, perhaps disk full.", + "GLZ_MEDIAM_ERR_IMAGE_SIZE" => "Error: image size exceeds the granted maximum dimensions (%s)", + "GLZ_MEDIAM_ERR_NOGDLOADED" => "PHP gd libraries plugin not enabled", + "GLZ_MEDIA_TITLE" => "Title", + "GLZ_MEDIA_FILENAME" => "File name", + "GLZ_MEDIA_CATEGORY" => "Category", + "GLZ_MEDIA_SIZE" => "Dimension", + "GLZ_ADD_NEW_RECORD" => "Add a new record", + "GLZ_SAVE_REVISION" => "Save as new revision", + "GLZ_MODIFY_LIST" => "List of changes to be approved", + "GLZ_CHANGE_LANGUAGE" => "Change language", + "GLZ_PAGE_CONTENT" => "Page content", + "GLZ_PAGE_PROP" => "Page property", + "GLZ_MODIFY1" => "Edit the published version", + "GLZ_MODIFY2" => "Edit the last revision", + "GLZ_LAST_REVSION" => "Last revision", + "GLZ_LOGIN_ERROR" => "User and/or password unknown. Try again", + "GLZ_LOGIN_NOACCESS" => "Access not allowed, login is requested", + "LOGGER_INSUFFICIENT_GROUP_LEVEL" => "The page requires higher access level.", + "LOGGER_INSUFFICIENT_USER_LEVEL" => "Page not available with current access. Please contact the system administrator", + "GLZ_LOGIN_DISABLED" => "Your account has been disabled. Please contact the system administrator. ", + "GLZ_LANGUAGE_LIST" => "Languages list", + "GLZ_LANGUAGE_EDIT" => "Edit language", + "GLZ_LANGUAGE" => "Language", + "GLZ_LANGUAGE_CODE" => "Code", + "GLZ_LANGUAGE_DEFAULT" => "Default language", + "GLZ_LANGUAGE_ORDER" => "Order", + "GLZ_LABEL" => "Label", + "GLZ_EDIT_LANGUAGE" => "Edit language", + "GLZ_SEARCH_LABEL" => "Word to search:", + "GLZ_SEARCH_BUTTON" => "Go", + "GLZ_SEARCH_COMMENT" => "Please insert more than 3 characters", + "GLZ_SEARCH_RESULT" => "Search result", + "GLZ_SEARCH_RESULT_TOTAL" => "Pages found:", + "LOGGED_MESSAGE" => "Welcome %s", + "GLZ_ERR_EMPTY_APP_PATH" => "The application path can't be empty", + "GLZ_ERR_NO_PAGETYPE_FOLDER" => "Can't open pageType application folder.", + "GLZ_ERR_404" => "Page not found", + "GLZ_USER_LIST_TITLE" => "User list", + "GLZ_USER_EDIT_TITLE" => "Edit user", + "GLZ_USER_EDIT" => "Edit user", + "GLZ_USER_FIRST" => "First name", + "GLZ_USER_LAST" => "Last name", + "GLZ_USER_EMAIL" => "Email", + "GLZ_USER_ACTIVE" => "Active", + "GLZ_USER_IS_ACTIVE" => "Active user", + "GLZ_USER_LOGINID" => "User name", + "GLZ_USER_PASSWORD" => "Password", + "GLZ_USER_GROUP" => "Group", + "GLZ_USER_ADD_NEW_RECORD" => "Add a new user", + "GLZ_USERGROUP_ADD_NEW_RECORD" => "Add a new group", + "GLZ_LOGIN_REMEMBER" => "Remember login", + "GLZ_ENABLED" => "Enabled", + "GLZ_ENABLE" => "Enable", + "GLZ_DISABLED" => "Disabled", + "GLZ_DISABLE" => "Disable", + "GLZ_USERGROUP_LIST_TITLE" => "Group list", + "GLZ_USERGROUP_EDIT_TITLE" => "Edit group", + "GLZ_USERGROUP_EDIT" => "Edit group", + "GLZ_USERGROUP_NAME" => "Group name", + "GLZ_USERGROUP_INTERNAL" => "Internal users", + "GLZ_MODULE_SHOW_TITLE" => "", + "GLZ_MODULE_LINKED" => "Form to be linked", + "GLZ_TOTAL_RECORDS" => "Record total", + "GLZ_PROTECTED_PAGE" => "Reserved page", + "GLZ_LINKED_URL" => "Linked URL", + "GLZ_CREATION_DATE" => "Creation Date", + "GLZ_DOWNLOAD_FILE" => "Download file", + "GLZ_DOWNLOAD_FILE_LINK" => "Download file: #title#, #size#", + "GLZ_ADDMEDIA" => "Add media", + "GLZ_NOIMAGE" => "No image", + "GLZ_NOMEDIA" => "No media", + "GLZ_URL_LINK" => "URL Link", + "GLZ_PRINT_PDF" => "Print PDF", + "GLZ_ENABLE_PAGE_COMMENTS" => "Enable comments", + "GLZ_MESSAGE_DELETE_SUCCESS" => "Record deleted", + "GLZ_PREVIOUS" => "previous", + "GLZ_NEXT" => "next", + "GLZ_COLSE"=> "close", + "GLZ_SLIDESHOW_START" => "slideshow start", + "GLZ_SLIDESHOW_STOP" => "slideshow stop", +); +org_glizy_locale_Locale::append($strings); \ No newline at end of file diff --git a/src/core/classes/org/glizy/locale/fr.php b/src/core/classes/org/glizy/locale/fr.php new file mode 100755 index 0000000..1f0acce --- /dev/null +++ b/src/core/classes/org/glizy/locale/fr.php @@ -0,0 +1,188 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +$strings = array ( + 'GLZ_DATE_FORMAT' => "d/m/Y", + 'GLZ_DATETIME_FORMAT' => "d/m/Y H:i:s", + 'GLZ_DATE_TOISO_REGEXP' => array("|^(\d{1,2})\/(\d{1,2})\/(\d{4})$|", "$3-$2-$1"), + 'GLZ_DATE_TOTIME_REGEXP' => array("|^(\d{1,2})\/(\d{1,2})\/(\d{4})$|", "$3-$2-$1 00:00:00"), + 'GLZ_DATETIME_TOTIME_REGEXP' => array("|^(\d{1,2})\/(\d{1,2})\/(\d{4})\s*(\d{1,2}):(\d{1,2}):(\d{1,2})$|", "$3-$2-$1 $4:$5:$6"), + 'GLZ_TIME_TO_DATE_REGEXP' => array("|^(\d{4})-(\d{1,2})-(\d{1,2})$|", "$3/$2/$1"), + 'GLZ_TIME_TO_DATETIME_REGEXP' => array("|^(\d{4})-(\d{1,2})-(\d{1,2})\s*(\d{1,2}):(\d{1,2}):(\d{1,2})$|", "$3/$2/$1 $4:$5:$6"), + "GLZ_MONTHS" => array( "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" ), + "GLZ_WARNING" => "Attention", + "GLZ_ERROR" => "Erreur", + "GLZ_NEW_PAGE" => "Nouvelle page", + "GLZ_CREATINING_NEW_PAGE" => " Créer une nouvelle page", + "GLZ_INSERT_NEW_PAGE" => " Ajouter une nouvelle page", + "GLZ_PAGE_TITLE" => "Titre", + "GLZ_PAGE_TITLE_LINK" => "Titre pour lien dans la navigation", + "GLZ_PAGE_TITLE_ALT" => "Alt pour lien dans la navigation", + "GLZ_PAGE_SELECT" => "Sélectionner la page", + "GLZ_PAGE_SELECT_PARENT" => "Sélectionner la page parent", + "GLZ_PAGE_SELECT_TYPE" => "Sélectionner le type de page", + "GLZ_PAGE_PAGEID" => "Page ID", + "GLZ_PAGE_LINKED_URL" => "URL lié", + "GLZ_PAGE_KEYWORDS" => "Mots clefs", + "GLZ_PAGE_DESCRIPTION" => "Courte description", + "GLZ_CONFIRM" => "Confirmer", + "GLZ_CANCEL" => "Annuler", + "GLZ_UPLOAD" => "Charger le fichier", + "GLZ_RESET" => "Réinitialiser", + "GLZ_PREVIEW" => "Voir la page", + "GLZ_SEARCH" => "Rechercher", + "GLZ_NEW_SEARCH" => "Nouvelle recherche", + "GLZ_PUBLISHED" => "Publié, cliquer pour changer l'état", + "GLZ_UNPUBLISHED" => "Non publié, cliquer pour changer l'état", + "GLZ_SEARCH_FILTERS" => "Filtres de recherche", + "GLZ_SEARCH_MEDIA" => "", + "GLZ_SITEMAP_TITLE" => "Structure du site", + "GLZ_SITEMAP_MSG_DELETE" => "Etes-vous sûrs de vouloir supprimer la page?", + "GLZ_SITEMAP_NEW" => "Ajouter une nouvelle page au niveau inférieur", + "GLZ_SITEMAP_UP" => "Déplacer la page vers le haut", + "GLZ_SITEMAP_DOWN" => "Déplacer la page vers le bas", + "GLZ_SITEMAP_EDIT" => "Modifier les contenus de la page", + "GLZ_SITEMAP_EDITDRAFT" => "Modifier le brouillon de la page", + "GLZ_SITEMAP_DELETE" => "Effacer les pages et toutes les sous-pages", + "GLZ_SITEMAP_PUBLISH" => "Publier la page", + "GLZ_SITEMAP_VISIBLE" => "Rendre la page non visible", + "GLZ_SITEMAP_INVISIBLE" => "Rendre la page visible", + "GLZ_SITEMAP_PREVIEW" => "Visualiser la page", + "GLZ_SITEMAP_LOCK" => "Modifier l'état de la page: protégée/non protégée", + "GLZ_MODIFY_PAGE_CONTENT" => "Modifier la page", + "GLZ_MODIFY_PAGE_DETAILS" => "Modifier la propriété de la page", + "GLZ_RECORD_ADD_BEFORE" => "Ajouter un enregistrement avant", + "GLZ_RECORD_ADD" => "Ajouter", + "GLZ_RECORD_MOVE_UP" => "Déplacer vers le haut", + "GLZ_RECORD_MOVE_DOWN" => "Déplacer vers le bas", + "GLZ_RECORD_DELETE" => "Effacer", + "GLZ_RECORD_DELETE_VERSION" => "Effacer cette version", + "GLZ_RECORD_EDIT" => "Modifier", + "GLZ_RECORD_PUBLISH" => "Publier", + "GLZ_RECORD_PREVIEW" => "Aperçu", + "GLZ_RECORD_MSG_DELETE" => "Etes-vous sûrs de vouloir supprimer l'enregistrement sélectionné?", + "GLZ_RECORDS_MSG_DELETE" => "Etes-vous sûrs de vouloir effacer les enregistrements sélectionnés?", + "GLZ_RECORD_NEW_TITLE" => "Insérer un enregistrement en '%s'", + "GLZ_RECORD_EDIT_TITLE" => "Modifier un enregistrement en '%s'", + "GLZ_RECORD_EDITDEF_TITLE" => "Modifier un enregistrement", + "GLZ_SAVE" => "Sauvegarder", + "GLZ_SAVE_DRAFT" => "Sauvegarder comme brouillon", + "GLZ_SAVE_DRAFT_CLOSE" => "Sauvegarder comme brouillon et fermer", + "GLZ_SAVE_CLOSE" => "Sauvegarder et fermer", + "GLZ_PAGE_SUBTITLE" => "Sous-titre", + "GLZ_JUMP_TO" => "Aller à la page:", + "GLZ_CLOSE_PICKER" => "Fermer", + "GLZ_ADD_MEDIA" => "Ajouter un média", + "GLZ_PAGE_NUM" => "Page", + "GLZ_MEDIAM_IMAGELIST" => "Images disponibles", + "GLZ_MEDIAM_MEDIALIST" => "Médias disponibles", + "GLZ_MEDIAM_PREVIEW" => "Aperçu", + "GLZ_MEDIAM_EDIT" => "Modifier un enregistrement", + "GLZ_MEDIAM_TITLE" => "Titre", + "GLZ_MEDIAM_SHORTTITLE" => "Titre court", + "GLZ_MEDIAM_NULL" => "Aucune sélection", + "GLZ_MEDIAM_CHOICE" => "Sélection médias", + "GLZ_MEDIAM_NO_IMG" => "Aucune image sélectionnée, cliquer pour en sélectionner une", + "GLZ_MEDIAM_CURRENT_IMG" => "Image actuelle:", + "GLZ_MEDIAM_IMG_CHANGED" => "Nouvelle image", + "GLZ_MEDIAM_CUSTOM_PATH" => "Chemin d'accès pour télécharger", + "GLZ_MEDIAM_FILE_TYPE" => "Type de fichier", + "GLZ_MEDIAM_SELECT_FILE" => "Sélectionner un fichier", + "GLZ_MEDIAM_UPLOAD_GENERIC_TITLE" => "Télécharger un Média", + "GLZ_MEDIAM_UPLOAD_TITLE" => "Télécharger un fichier de type:", + "GLZ_MEDIAM_UPLOAD_DONE" => "Nouveau fichier téléchargé avec succès", + "GLZ_MEDIAM_DELETE_DONE" => "Fichier supprimé des archives", + "GLZ_MEDIAM_NO_FILE" => "Aucun fichier sélectionné, cliquer pour en sélectionner un", + "GLZ_MEDIAM_EDITING" => "Modifier les propriétés du média", + "GLZ_MEDIAM_MSG_DELETE" => "Etes-vous sûrs de vouloir supprimer le média sélectionné", + "GLZ_MEDIAM_ERR_NO_FILE" => "Aucun fichier sélectionné", + "GLZ_MEDIAM_ERR_INI_SIZE" => "Taille du fichier trop importante", + "GLZ_MEDIAM_ERR_PARTIAL" => "Erreur de téléchargement", + "GLZ_MEDIAM_ERR_FORM_SIZE" => "Taille de fichier trop importante", + "GLZ_MEDIAM_ERR_CREATE_DIR" => "Erreur dans la création de la page: '%s'", + "GLZ_MEDIAM_ERR_COPYING" => "Erreur de copie du fichier, le disque est peut-être plein", + "GLZ_MEDIAM_ERR_IMAGE_SIZE" => "Erreur: l'image téléchargée excède les dimensions maximales", + "GLZ_MEDIAM_ERR_NOGDLOADED" => "PHP gd libraries plugin non autorisé", + "GLZ_MEDIA_TITLE" => "Titre", + "GLZ_MEDIA_FILENAME" => "Nom du fichier", + "GLZ_MEDIA_CATEGORY" => "Catégorie", + "GLZ_MEDIA_SIZE" => "Dimension", + "GLZ_ADD_NEW_RECORD" => "Ajouter un nouvel enregistrement", + "GLZ_SAVE_REVISION" => "Sauvegarder comme nouvelle modification", + "GLZ_MODIFY_LIST" => "Liste des modifications à valider", + "GLZ_CHANGE_LANGUAGE" => "Changer langue", + "GLZ_PAGE_CONTENT" => "Contenus de la page", + "GLZ_PAGE_PROP" => "Propriétés de la page", + "GLZ_MODIFY1" => "Modifier la version publiée", + "GLZ_MODIFY2" => "Modifier la dernière modification", + "GLZ_LAST_REVSION" => "Dernière modification", + "GLZ_LOGIN_ERROR" => "Identifiant et/ou mot de passe inexistant. Réessayer", + "GLZ_LOGIN_NOACCESS" => "Accès non autorisé. Vous devez vous identifier", + "LOGGER_INSUFFICIENT_GROUP_LEVEL" => "Accès refusé", + "LOGGER_INSUFFICIENT_USER_LEVEL" => " Le système actuel ne vous permet pas l'accès à la page demandée. Merci de contacter l'administrateur système.", + "GLZ_LOGIN_DISABLED" => "Votre compte a été supprimé.Contactez l'administrateur", + "GLZ_LANGUAGE_LIST" => "Liste des langues", + "GLZ_LANGUAGE_EDIT" => "Modification de la langue", + "GLZ_LANGUAGE" => "Langue", + "GLZ_LANGUAGE_CODE" => "Code", + "GLZ_LANGUAGE_DEFAULT" => "Langue principale", + "GLZ_LANGUAGE_ORDER" => "Ordre", + "GLZ_LABEL" => "Etiquette", + "GLZ_EDIT_LANGUAGE" => "Langue des données", + "GLZ_SEARCH_LABEL" => "Mot à rechercher", + "GLZ_SEARCH_BUTTON" => "Lancer la recherche", + "GLZ_SEARCH_COMMENT" => " Tapez plus de 3 caractères", + "GLZ_SEARCH_RESULT" => "Résultat de la recherche", + "GLZ_SEARCH_RESULT_TOTAL" => "Pages trouvées", + "LOGGED_MESSAGE" => "Bienvenu/e à %s", + "GLZ_ERR_EMPTY_APP_PATH" => "Le chemin du programme ne peut pas être vide", + "GLZ_ERR_NO_PAGETYPE_FOLDER" => "Impossible d'ouvrir le fichier pageType programme", + "GLZ_ERR_404" => "Impossible de trouver la page", + "GLZ_USER_LIST_TITLE" => "Liste des utilisateurs", + "GLZ_USER_EDIT_TITLE" => "Modification des utilisateurs", + "GLZ_USER_EDIT" => "Modification des utilisateurs", + "GLZ_USER_FIRST" => "Prénom", + "GLZ_USER_LAST" => "Nom de famille", + "GLZ_USER_EMAIL" => "Email", + "GLZ_USER_ACTIVE" => "Actif", + "GLZ_USER_IS_ACTIVE" => "Utilisateur actif", + "GLZ_USER_LOGINID" => "Nom d'utilisateur", + "GLZ_USER_PASSWORD" => "Mot de passe", + "GLZ_USER_GROUP" => "Groupe", + "GLZ_LOGIN_REMEMBER" => "Se souvenir de mon identifiant", + "GLZ_ENABLED" => "Autorisé", + "GLZ_ENABLE" => "autoriser", + "GLZ_DISABLED" => "Non autorisé", + "GLZ_DISABLE" => "Non autoriser", + "GLZ_USERGROUP_LIST_TITLE" => "Liste des groupes", + "GLZ_USERGROUP_EDIT_TITLE" => "Modification du groupe", + "GLZ_USERGROUP_EDIT" => "Modification du groupe", + "GLZ_USERGROUP_NAME" => "Nom du groupe", + "GLZ_USERGROUP_INTERNAL" => "Utilisateurs internes", + "GLZ_MODULE_SHOW_TITLE" => "Visualiser le titre de la page?", + "GLZ_MODULE_LINKED" => "Document à lier", + "GLZ_TOTAL_RECORDS" => "Total enregistrement", + "GLZ_PROTECTED_PAGE" => "Page réservée", + "GLZ_LINKED_URL" => "URL liée", + "GLZ_CREATION_DATE" => "Date de création", + "GLZ_DOWNLOAD_FILE" => "Télécharger le fichier", + "GLZ_DOWNLOAD_FILE_LINK" => "Télécharger le fichier: #titre#, #taille#", + "GLZ_ADDMEDIA" => "Ajouter un Média", + "GLZ_NOIMAGE" => "Aucune image", + "GLZ_NOMEDIA" => "Aucune Média", + "GLZ_URL_LINK" => "lien URL ", + "GLZ_PRINT_PDF" => "PDF Imprimer", + "GLZ_ENABLE_PAGE_COMMENTS" => "Activer les commentaires", + "GLZ_PREVIOUS" => "précédent", + "GLZ_NEXT" => "suivant", + "GLZ_COLSE"=> "fermer", + "GLZ_SLIDESHOW_START" => "slideshow début", + "GLZ_SLIDESHOW_STOP" => "slideshow arrêt", +); +org_glizy_locale_Locale::append($strings); \ No newline at end of file diff --git a/src/core/classes/org/glizy/locale/it.php b/src/core/classes/org/glizy/locale/it.php new file mode 100755 index 0000000..09008e5 --- /dev/null +++ b/src/core/classes/org/glizy/locale/it.php @@ -0,0 +1,195 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +$strings = array ( + 'GLZ_DATE_FORMAT' => "d/m/Y", + 'GLZ_DATETIME_FORMAT' => "d/m/Y H:i:s", + 'GLZ_DATE_TOISO_REGEXP' => array("|^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$|", "$3-$2-$1"), + 'GLZ_DATE_TOTIME_REGEXP' => array("|^(\d{1,2})\/(\d{1,2})\/(\d{2,4})$|", "$3-$2-$1 00:00:00"), + 'GLZ_DATETIME_TOTIME_REGEXP' => array("|^(\d{1,2})\/(\d{1,2})\/(\d{2,4})\s*(\d{1,2}):(\d{1,2}):(\d{1,2})$|", "$3-$2-$1 $4:$5:$6"), + 'GLZ_TIME_TO_DATE_REGEXP' => array("|^(\d{2,4})-(\d{1,2})-(\d{1,2})$|", "$3/$2/$1"), + 'GLZ_TIME_TO_DATETIME_REGEXP' => array("|^(\d{2,4})-(\d{1,2})-(\d{1,2})\s*(\d{1,2}):(\d{1,2}):(\d{1,2})$|", "$3/$2/$1 $4:$5:$6"), + "GLZ_MONTHS" => array("Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre" ), + "GLZ_WARNING" => "Attenzione", + "GLZ_ERROR" => "Errore", + "GLZ_NEW_PAGE" => "Nuova pagina", + "GLZ_CREATINING_NEW_PAGE" => "Creazione nuova pagina", + "GLZ_INSERT_NEW_PAGE" => "Aggiunta nuova pagina", + "GLZ_PAGE_TITLE" => "Titolo", + "GLZ_PAGE_TITLE_LINK" => "Attributo Title per link nella navigazione", + "GLZ_PAGE_TITLE_ALT" => "Alt per link nella navigazione", + "GLZ_PAGE_SELECT" => "Selezionare la pagina", + "GLZ_PAGE_SELECT_PARENT" => "Selezionare la pagina padre", + "GLZ_PAGE_SELECT_TYPE" => "Selezionare il tipo della pagina", + "GLZ_PAGE_PAGEID" => "Identificativo univoco della pagina", + "GLZ_PAGE_LINKED_URL" => "URL collegato", + "GLZ_PAGE_KEYWORDS" => "Parole chiave", + "GLZ_PAGE_DESCRIPTION" => "Breve descrizione", + "GLZ_CONFIRM" => "Conferma", + "GLZ_CANCEL" => "Annulla", + "GLZ_UPLOAD" => "Carica file", + "GLZ_RESET" => "Azzera", + "GLZ_PREVIEW" => "Visualizza pagina", + "GLZ_SEARCH" => "Cerca", + "GLZ_NEW_SEARCH" => "Nuova ricerca", + "GLZ_PUBLISHED" => "Pubblicato, premere per cambiare lo stato", + "GLZ_UNPUBLISHED" => "Non pubblicato, premere per cambiare lo stato", + "GLZ_SEARCH_FILTERS" => "Filtri di ricerca", + "GLZ_SEARCH_MEDIA" => "", + "GLZ_SITEMAP_TITLE" => "Struttura del sito", + "GLZ_SITEMAP_MSG_DELETE" => "Siete sicuri di voler cancellare la pagina?", + "GLZ_SITEMAP_NEW" => "Aggiungi una nuova pagina di livello inferiore", + "GLZ_SITEMAP_UP" => "Sposta la pagina in alto", + "GLZ_SITEMAP_DOWN" => "Sposta la pagina in basso", + "GLZ_SITEMAP_EDIT" => "Modifica i contenuti della pagina", + "GLZ_SITEMAP_EDITDRAFT" => "Modifica la bozza della pagina", + "GLZ_SITEMAP_DELETE" => "Rimuovi la pagina e tutte le sottopagine", + "GLZ_SITEMAP_PUBLISH" => "Pubblica la pagina", + "GLZ_SITEMAP_VISIBLE" => "Rende la pagina non visibile", + "GLZ_SITEMAP_INVISIBLE" => "Rende la pagina visibile", + "GLZ_SITEMAP_PREVIEW" => "Visualizza la pagina", + "GLZ_SITEMAP_LOCK" => "Modifica lo stato della pagina: protetta/non protetta", + "GLZ_MODIFY_PAGE_CONTENT" => "Modifica pagina", + "GLZ_MODIFY_PAGE_DETAILS" => "Modifica proprietà della pagina", + "GLZ_RECORD_ADD_BEFORE" => "Aggiungi un record prima di questo", + "GLZ_RECORD_ADD" => "Aggiungi", + "GLZ_RECORD_MOVE_UP" => "Sposta in alto", + "GLZ_RECORD_MOVE_DOWN" => "Sposta in basso", + "GLZ_RECORD_DELETE" => "Cancella", + "GLZ_RECORD_DELETE_VERSION" => "Cancella versione", + "GLZ_RECORD_EDIT" => "Modifica", + "GLZ_RECORD_EDIT_DRAFT" => "Modifica bozza", + "GLZ_RECORD_PUBLISH" => "Pubblica", + "GLZ_RECORD_PREVIEW" => "Anteprima", + "GLZ_RECORD_MSG_DELETE" => "Siete sicuri di voler cancellare il record selezionato?", + "GLZ_RECORDS_MSG_DELETE" => "Siete sicuri di voler cancellare i record selezionati?", + "GLZ_RECORD_NEW_TITLE" => "Inserimento record in '%s'", + "GLZ_RECORD_EDIT_TITLE" => "Modifica record in '%s'", + "GLZ_RECORD_EDITDEF_TITLE" => "Modifica record", + "GLZ_SAVE" => "Salva", + "GLZ_PUBLISH" => "Pubblica", + "GLZ_SAVE_DRAFT" => "Salva come bozza", + "GLZ_SAVE_DRAFT_CLOSE" => "Salva come bozza e chiudi", + "GLZ_SAVE_CLOSE" => "Salva e chiudi", + "GLZ_PUBLISH_CLOSE" => "Pubblica e chiudi", + "GLZ_CLOSE" => 'Chiudi', + "GLZ_PAGE_SUBTITLE" => "Sottotitolo", + "GLZ_JUMP_TO" => "Vai alla pagina:", + "GLZ_CLOSE_PICKER" => "Chiudi", + "GLZ_ADD_MEDIA" => "Aggiungi media", + "GLZ_PAGE_NUM" => "Pagina", + "GLZ_MEDIAM_IMAGELIST" => "Immagini disponibili", + "GLZ_MEDIAM_MEDIALIST" => "Media disponibili", + "GLZ_MEDIAM_EDIT" => "Modifica media", + "GLZ_MEDIAM_PREVIEW" => "Anteprima", + "GLZ_MEDIAM_TITLE" => "Titolo", + "GLZ_MEDIAM_SHORTTITLE" => "Titolo breve", + "GLZ_MEDIAM_NULL" => "Nessuna selezione", + "GLZ_MEDIAM_CHOICE" => "Seleziona media", + "GLZ_MEDIAM_NO_IMG" => "Nessuna immagine selezionata, premere per selezionarne una.", + "GLZ_MEDIAM_CURRENT_IMG" => "Immagine corrente:", + "GLZ_MEDIAM_IMG_CHANGED" => "Immagine cambiata", + "GLZ_MEDIAM_CUSTOM_PATH" => "Percorso upload", + "GLZ_MEDIAM_FILE_TYPE" => "Tipo di file", + "GLZ_MEDIAM_SELECT_FILE" => "Selezionare il file", + "GLZ_MEDIAM_UPLOAD_GENERIC_TITLE" => "Carica un Media", + "GLZ_MEDIAM_UPLOAD_TITLE" => "Carica un file di tipo: ", + "GLZ_MEDIAM_UPLOAD_DONE" => "Nuovo file caricato con successo", + "GLZ_MEDIAM_DELETE_DONE" => "File rimosso dall'archivio", + "GLZ_MEDIAM_NO_FILE" => "Nessun file selezionato, premere per selezionarne uno.", + "GLZ_MEDIAM_EDITING" => "Modifica proprietà media", + "GLZ_MEDIAM_MSG_DELETE" => "Siete sicuri di voler cancellare il media selezionato ?", + "GLZ_MEDIAM_ERR_NO_FILE" => "Nessun file selezionato", + "GLZ_MEDIAM_ERR_INI_SIZE" => "File di dimensione troppo grande", + "GLZ_MEDIAM_ERR_PARTIAL" => "Upload non completo", + "GLZ_MEDIAM_ERR_FORM_SIZE" => "File di dimensione troppo grande", + "GLZ_MEDIAM_ERR_CREATE_DIR" => "Errore nella creazione della cartella: '%s'", + "GLZ_MEDIAM_ERR_COPYING" => "Errore nella copia del file, possibile disco pieno.", + "GLZ_MEDIAM_ERR_IMAGE_SIZE" => "Errore: l'immagine che è stata caricata eccede le dimensioni massime concesse (%s)", + "GLZ_MEDIAM_ERR_NOGDLOADED" => "PHP gd libraries plugin non abilitato", + "GLZ_MEDIA_TITLE" => "Titolo", + "GLZ_MEDIA_FILENAME" => "Nome del file", + "GLZ_MEDIA_CATEGORY" => "Categoria", + "GLZ_MEDIA_SIZE" => "Dimensione", + "GLZ_ADD_NEW_RECORD" => "Aggiungi nuovo record", + "GLZ_SAVE_REVISION" => "Salva come nuova revisione", + "GLZ_MODIFY_LIST" => "Elenco modifiche da approvare", + "GLZ_CHANGE_LANGUAGE" => "Cambia lingua", + "GLZ_PAGE_CONTENT" => "Contenuti della pagina", + "GLZ_PAGE_PROP" => "Proprietà della pagina", + "GLZ_MODIFY1" => "Modifica la versione pubblicata", + "GLZ_MODIFY2" => "Modifica l'ultima revisione", + "GLZ_LAST_REVSION" => "Ultima revisione", + "GLZ_LOGIN_ERROR" => "Utente e/o password inesistenti. Riprovare.", + "GLZ_LOGIN_NOACCESS" => "Accesso non consentito, è necessario effettuare l'autenticazione.", + "LOGGER_INSUFFICIENT_GROUP_LEVEL" => "La pagina richiesta richiede un maggiore livello di accesso.", + "LOGGER_INSUFFICIENT_USER_LEVEL" => "La pagina richiesta non &egrave; disponibile con l'accesso corrente. Contattate l'amministratore di sistema.", + "GLZ_LOGIN_DISABLED" => "Il Suo account è stato disabilitato. Contattare l'amministratore di sistema.", + "GLZ_LANGUAGE_LIST" => "Elenco lingue", + "GLZ_LANGUAGE_EDIT" => "Modifica lingua", + "GLZ_LANGUAGE" => "Lingua", + "GLZ_LANGUAGE_CODE" => "Codice", + "GLZ_LANGUAGE_DEFAULT" => "Lingua principale", + "GLZ_LANGUAGE_ORDER" => "Ordine", + "GLZ_LABEL" => "Etichetta", + "GLZ_EDIT_LANGUAGE" => "Lingua inserimento dati", + "GLZ_SEARCH_LABEL" => "Parola da ricercare:", + "GLZ_SEARCH_BUTTON" => "Cerca", + "GLZ_SEARCH_COMMENT" => "La ricerca viene effettuata su parole con più di 3 caratteri", + "GLZ_SEARCH_RESULT" => "Risultato della ricerca", + "GLZ_SEARCH_RESULT_TOTAL" => "Pagine trovate:", + "LOGGED_MESSAGE" => "Benvenuto/a %s", + "GLZ_ERR_EMPTY_APP_PATH" => "Il percorso dell'applicazione non può essere vuoto", + "GLZ_ERR_NO_PAGETYPE_FOLDER" => "Non si può aprire il pageTipe application folder.", + "GLZ_ERR_404" => "Pagina non trovata", + "GLZ_USER_LIST_TITLE" => "Elenco utenti", + "GLZ_USER_EDIT_TITLE" => "Modifica utente", + "GLZ_USER_EDIT" => "Modifica utente", + "GLZ_USER_FIRST" => "Nome", + "GLZ_USER_LAST" => "Cognome", + "GLZ_USER_EMAIL" => "Email", + "GLZ_USER_ACTIVE" => "Attivo", + "GLZ_USER_IS_ACTIVE" => "Utente Attivo", + "GLZ_USER_LOGINID" => "Nome utente", + "GLZ_USER_PASSWORD" => "Password", + "GLZ_USER_GROUP" => "Gruppo", + "GLZ_USER_ADD_NEW_RECORD" => "Aggiungi un nuovo utente", + "GLZ_USERGROUP_ADD_NEW_RECORD" => "Aggiungi un nuovo gruppo", + "GLZ_LOGIN_REMEMBER" => "Ricorda login", + "GLZ_ENABLED" => "Abilitato", + "GLZ_ENABLE" => "Abilita", + "GLZ_DISABLED" => "Disabilitato", + "GLZ_DISABLE" => "Disabilita", + "GLZ_USERGROUP_LIST_TITLE" => "Elenco gruppi", + "GLZ_USERGROUP_EDIT_TITLE" => "Modifica gruppo", + "GLZ_USERGROUP_EDIT" => "Modifica gruppo", + "GLZ_USERGROUP_NAME" => "Nome gruppo", + "GLZ_USERGROUP_INTERNAL" => "Utenti interni", + "GLZ_MODULE_SHOW_TITLE" => "Visualizza il titolo della pagina?", + "GLZ_MODULE_LINKED" => "Modulo da collegare", + "GLZ_TOTAL_RECORDS" => "Totale record:", + "GLZ_PROTECTED_PAGE" => "Pagina riservata", + "GLZ_LINKED_URL" => "URL collegato", + "GLZ_CREATION_DATE" => "Data di creazione", + "GLZ_DOWNLOAD_FILE" => "Scarica file", + "GLZ_DOWNLOAD_FILE_LINK" => "Scarica file: #title#, #size#", + "GLZ_ADDMEDIA" => "Aggiungi Media", + "GLZ_NOIMAGE" => "Nessuna Immagine", + "GLZ_NOMEDIA" => "Nessuna media", + "GLZ_URL_LINK" => "Url link", + "GLZ_PRINT_PDF" => "Stampa PDF", + "GLZ_ENABLE_PAGE_COMMENTS" => "Abilita commenti", + "GLZ_MESSAGE_DELETE_SUCCESS" => "Record cancellato con successo.", + "GLZ_PREVIOUS" => "precedente", + "GLZ_NEXT" => "successiva", + "GLZ_COLSE"=> "chiudi", + "GLZ_SLIDESHOW_START" => "inizia slideshow", + "GLZ_SLIDESHOW_STOP" => "ferma slideshow", +); +org_glizy_locale_Locale::append($strings); \ No newline at end of file diff --git a/src/core/classes/org/glizy/log/Console.php b/src/core/classes/org/glizy/log/Console.php new file mode 100755 index 0000000..925691d --- /dev/null +++ b/src/core/classes/org/glizy/log/Console.php @@ -0,0 +1,37 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_log_Console extends org_glizy_log_LogBase +{ + + function log($msg, $level=GLZ_LOG_DEBUG, $group='') + { + if ( is_array( $msg ) || is_object( $msg ) ) + { + $msg = json_encode($msg); + } + echo $this->_format($msg, $level, $group); + return true; + } + + function open() + { + return true; + } + + function close() + { + return true; + } + + function flush() + { + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/log/DB.php b/src/core/classes/org/glizy/log/DB.php new file mode 100755 index 0000000..d09d7d6 --- /dev/null +++ b/src/core/classes/org/glizy/log/DB.php @@ -0,0 +1,55 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_log_DB extends org_glizy_log_LogBase +{ + /*private*/ var $_ar; + /*private*/ var $application; + /*private*/ var $_append = true; + /*private*/ var $_lock = false; + /*private*/ var $_keepOpen = true; + /*private*/ var $_fileResource = false; + + + function __construct($options=array(), $level=GLZ_LOG_DEBUG, $group='') + { + parent::__construct($options, $level, $group); + + $this->_ar = org_glizy_ObjectFactory::createModel( 'org.glizy.models.Log' ); + $this->application = org_glizy_ObjectValues::get('org.glizy', 'application'); + + // TODO + //$this->_ar->enableQueue(); + } + + function __destruct() + { + // TODO + //$this->_ar->executeQueue(); + } + + function log($msg, $level=GLZ_LOG_DEBUG, $group='') + { + if (!$this->_check($level, $group)) + { + return false; + } + + $this->_ar->emptyRecord(); + $this->_ar->log_level = (string)$level; + // TODO + $this->_ar->log_date = new org_glizy_types_DateTime(); + $this->_ar->log_ip = $_SERVER["REMOTE_ADDR"]; + $this->_ar->log_session = session_id(); + $this->_ar->log_group = $group; + $this->_ar->log_message = $msg; + $this->_ar->log_FK_user_id = $this->application->getCurrentUser()->id; + return $this->_ar->save(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/log/ElasticSearch.php b/src/core/classes/org/glizy/log/ElasticSearch.php new file mode 100755 index 0000000..a8e87b0 --- /dev/null +++ b/src/core/classes/org/glizy/log/ElasticSearch.php @@ -0,0 +1,122 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_log_ElasticSearch + */ +class org_glizy_log_ElasticSearch extends org_glizy_log_LogBase +{ + private $_message = array(); + private $_index = 'glizy'; + private $_type = 'log'; + private $_host = ''; + + /** + * @param array $options + * @param int|string $level + * @param string $group + */ + function __construct($options=array(), $level=GLZ_LOG_DEBUG, $group='') + { + parent::__construct($options, $level, $group); + if (isset($options['index'])) + { + $this->_index = $options['index']; + } + if (isset($options['type'])) + { + $this->_type = $options['type']; + } + if (isset($options['host'])) { + $this->_host = $options['host']; + } else { + $this->_host = __Config::get ( 'glizy.exception.log.elasticsearch.url' ); + } + $this->_message['index'] = $this->_index; + $this->_message['type'] = $this->_type; + } + + /** + * @return string + */ + private function getCallingName() { + $trace = debug_backtrace(); + $caller = $trace[5]; + + if (isset($caller['class'])) { + $result = $caller['class'] . '::' . $caller['function']; + } else { + $result = $caller['function']; + } + + return $result; + } + + /** + * @param $msg + * @param int $level + * @param string $group + * + * @return bool|mixed + * @throws Exception + */ + function log($msg, $level=GLZ_LOG_DEBUG, $group='') + { + if (!$this->_check($level, $group)) + { + return false; + } + + $t = explode ( " ", microtime ( ) ); + $params = array( + '@timestamp' => date("Y-m-d\TH:i:s",$t[1]).substr((string)$t[0],1,4).date("P"), + 'host' => !isset( $_SERVER["SERVER_ADDR"] ) ? 'console' : $_SERVER["SERVER_ADDR"], + 'group' => $group, + 'level' => $level, + 'caller' => $this->getCallingName(), + 'pid' => getmypid(), + 'appName' => __Config::get ( 'APP_NAME' ) + ); + + $message = array_merge($this->_message, $params); + + if (is_array( $msg )) + { + $message = array_merge($message, $msg); + } + else + { + $message = array_merge($message, array('message' => $msg)); + } + + // set_time_limit(0); + + $data = json_encode ( $message ); + $restUrl = $this->_host . $this->_index . '-' . date ( "Y.m.d" ) . '/' . $this->_type; + $ch = curl_init ( $restUrl ); + curl_setopt ( $ch, CURLOPT_CUSTOMREQUEST, 'POST' ); + curl_setopt ( $ch, CURLOPT_POSTFIELDS, $data ); + curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true ); + curl_setopt ( $ch, CURLOPT_HTTPHEADER, array( + 'Content-Type: application/json', + 'Content-Length: ' . strlen ( $data ) ) + ); + + if( ! $result = curl_exec($ch)) + { + if (class_exists('org_glizy_Config') && org_glizy_Config::get('DEBUG') === true) { + throw new Exception(curl_error($ch), curl_errno($ch)); + } + } + + curl_close($ch); + + return $result; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/log/File.php b/src/core/classes/org/glizy/log/File.php new file mode 100755 index 0000000..0f9b1e3 --- /dev/null +++ b/src/core/classes/org/glizy/log/File.php @@ -0,0 +1,106 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_log_File extends org_glizy_log_LogBase +{ + /*private*/ var $_fileName = ''; + /*private*/ var $_append = true; + /*private*/ var $_lock = false; + /*private*/ var $_keepOpen = true; + /*private*/ var $_fileResource = false; + + + function __construct($fileName, $options=array(), $level=GLZ_LOG_DEBUG, $group='') + { + parent::__construct($options, $level, $group); + $this->_fileName = $fileName; + if (isset($options['append'])) + { + $this->_append = $options['append']; + } + if (isset($conf['lock'])) + { + $this->_lock = $options['lock']; + } + if (isset($conf['keepOpen'])) + { + $this->_lock = $options['keepOpen']; + } + //$this->log( "----------------- start logging", $level, $group ); + } + + function __destruct() + { + $this->close(); + } + + + function log($msg, $level=GLZ_LOG_DEBUG, $group='') + { + if (!$this->_check($level, $group)) + { + return false; + } + + if (!$this->_isOpen && !$this->open()) { + return false; + } + + if ( is_array( $msg ) || is_object( $msg ) ) + { + $msg = json_encode($msg); + } + + if ($this->_lock) + { + flock($this->_fileResource, LOCK_EX); + } + + $ret = (fwrite($this->_fileResource, $this->_format($msg, $level, $group)) !== false); + + if ($this->_lock) + { + flock($this->_fileResource, LOCK_UN); + } + + if (!$this->_keepOpen) + { + $this->close(); + } + + return $ret; + } + + function open() + { + if (!$this->_isOpen) + { + $this->_fileResource = fopen($this->_fileName, ($this->_append) ? 'a' : 'w'); + } + + $this->_isOpen = $this->_fileResource !== false; + return $this->_isOpen; + } + + function close() + { + if ($this->_isOpen) + { + if (fclose($this->_fileResource)) $this->_fileResource = false; + } + + $this->_isOpen = $this->_fileResource !== false; + return (!$this->_isOpen); + } + + function flush() + { + return fflush($this->_fileResource); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/log/FireBug.php b/src/core/classes/org/glizy/log/FireBug.php new file mode 100755 index 0000000..8ea4a91 --- /dev/null +++ b/src/core/classes/org/glizy/log/FireBug.php @@ -0,0 +1,160 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_log_FireBug extends org_glizy_log_LogBase +{ + var $_logFormat = '%g %m'; + var $_methodMap = array( GLZ_LOG_DEBUG => 'console.debug', + GLZ_LOG_SYSTEM => 'console.info', + GLZ_LOG_INFO => 'console.info', + GLZ_LOG_WARNING => 'console.warn', + GLZ_LOG_ERROR => 'console.error', + GLZ_LOG_FATAL => 'console.error'); + var $_outputBuffer = ''; + var $logBuffer = ''; + + function log($msg, $level=GLZ_LOG_DEBUG, $group='') + { + if ( is_array( $msg ) || is_object( $msg ) ) + { + $msg = json_encode($msg); + } + + // controlla se il motodo è stato chiamato in modo statico + if(!method_exists($this, '_check')) + { + $l = new org_glizy_log_FireBug(NULL, $level); + $l->log($msg, $level, $group); + return; + } + + + if (!$this->_check($level, $group)) + { + return false; + } + + $this->_outputBuffer = ''; + + if (is_array($msg)) + { + foreach( $msg as $k => $v ) + { + $this->_outputBuffer .= $this->_methodMap[$level].'("'.$k.'", '.json_encode( $v ).');'; + } + } + else + { + $msg = $this->_format($msg, $level, $group); + $this->_outputBuffer .= $this->_methodMap[$level].'("'.$this->_cleanText($msg).'");'; + } + + $this->logBuffer .= $this->_outputBuffer.GLZ_COMPILER_NEWLINE2; + + // cerca l'istanza dell'applicazione + // per inviare l'output al componente root + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + if (is_object($application)) + { + $root = $application->getRootComponent(); + if ( !is_null( $root ) ) + { + $root->addOutputCode( '<script type="text/javascript">'.$this->logBuffer.'</script>', 'log'); + $this->logBuffer = ''; + } + } + + + return true; + } + + // i vari metodo sono ridefiniti + // per permettere di invocare il logger + // anche con chiamate statiche + function debug($msg, $group='') + { + if(!method_exists($this, '_check')) + { + return org_glizy_log_FireBug::log($msg, GLZ_LOG_DEBUG, $group); + } + else + { + return $this->log($msg, GLZ_LOG_DEBUG, $group); + } + } + + function system($msg, $group='') + { + if(!method_exists($this, '_check')) + { + return org_glizy_log_FireBug::log($msg, GLZ_LOG_SYSTEM, $group); + } + else + { + return $this->log($msg, GLZ_LOG_SYSTEM, $group); + } + } + + function info($msg, $group='') + { + if(!method_exists($this, '_check')) + { + return org_glizy_log_FireBug::log($msg, GLZ_LOG_INFO, $group); + } + else + { + return $this->log($msg, GLZ_LOG_INFO, $group); + } + } + + function warning($msg, $group='') + { + if(!method_exists($this, '_check')) + { + return org_glizy_log_FireBug::log($msg, GLZ_LOG_WARNING, $group); + } + else + { + return $this->log($msg, GLZ_LOG_WARNING, $group); + } + } + + function error($msg, $group='') + { + if(!method_exists($this, '_check')) + { + return org_glizy_log_FireBug::log($msg, GLZ_LOG_ERROR, $group); + } + else + { + return $this->log($msg, GLZ_LOG_ERROR, $group); + } + } + + function fatal($msg, $group='') + { + if(!method_exists($this, '_check')) + { + return org_glizy_log_FireBug::log($msg, GLZ_LOG_FATAL, $group); + } + else + { + return $this->log($msg, GLZ_LOG_FATAL, $group); + } + } + + /*private*/ function _cleanText($t) + { + $t = str_replace("\r", "", $t); + $t = str_replace("\n", "\\n", $t); + $t = str_replace('"', '\\"', $t); + return $t; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/log/LiveLog.php b/src/core/classes/org/glizy/log/LiveLog.php new file mode 100755 index 0000000..f833c81 --- /dev/null +++ b/src/core/classes/org/glizy/log/LiveLog.php @@ -0,0 +1,123 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_log_LiveLog extends org_glizy_log_LogBase +{ + var $_host = '127.0.0.1'; + var $_port; + var $_sock; + var $_msgsock; + var $_eol = "\x00"; + + + function __construct($port, $options=array(), $level=GLZ_LOG_DEBUG, $group='') + { + parent::__construct($options, $level, $group); + // $this->_host = $host; + $this->_port = $port; + } + + function __destruct() + { + $this->close(); + } + + + function log($msg, $level=GLZ_LOG_DEBUG, $group='') + { + if (!$this->_check($level, $group)) + { + return false; + } + + /* If the log file isn't already open, open it now. */ + if (!$this->_isOpen && !$this->open()) { + return false; + } + + if ( is_array( $msg ) || is_object( $msg ) ) + { + $msg = json_encode($msg); + } + + if ($msg!='[PAUSE]' && + $msg!='[RESTORE]' && + $msg!='[CLEAR]' && + $msg!='[RESET]' && + $msg!='[SETLEVEL]') + { + + $levelMap = array(GLZ_LOG_DEBUG => '0', + GLZ_LOG_INFO => '1', + GLZ_LOG_WARNING => '2', + GLZ_LOG_ERROR => '3', + GLZ_LOG_FATAL => '4', + GLZ_LOG_SYSTEM => '5'); + + $message = $levelMap[$level].$this->_format($msg, $level, $group); + } + else + { + $message = $msg.$this->_eol; + } + + $ret = socket_write($this->_msgsock, $message, strlen($message)); + return $ret; + } + + function open() + { + if (!$this->_isOpen && function_exists('socket_create')) + { + if (($this->_sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) + { + //echo "socket_create() failed: reason: " . socket_strerror($this->_sock) . "\n"; + return false; + } + + if (($ret = socket_bind($this->_sock, $this->_host, $this->_port)) < 0) + { + //echo "socket_bind() failed: reason: " . socket_strerror($ret) . "\n"; + return false; + } + + if (($ret = socket_listen($this->_sock, 5)) < 0) + { + //echo "socket_listen() failed: reason: " . socket_strerror($ret) . "\n"; + return false; + } + + if (($this->_msgsock = socket_accept($this->_sock)) < 0) + { + //echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n"; + return false; + } + + $this->_isOpen = true; + } + return $this->_isOpen; + } + + function close() + { + if ($this->_isOpen && function_exists('socket_create')) + { + socket_close($this->_msgsock); + socket_close($this->_sock); + } + + $this->_isOpen = false; + return (!$this->_isOpen); + } + + function flush() + { + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/log/LogBase.php b/src/core/classes/org/glizy/log/LogBase.php new file mode 100755 index 0000000..a3c7410 --- /dev/null +++ b/src/core/classes/org/glizy/log/LogBase.php @@ -0,0 +1,240 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/* + %a = remote IP + %A = server IP + %q = query string + %l = level name + %L = level number + %g = group + %m = message + %t = time +*/ + +if (!defined('GLZ_LOG_EVENT')) define('GLZ_LOG_EVENT', 'logByEvent'); +if (!defined('GLZ_LOG_DEBUG')) define('GLZ_LOG_DEBUG', 1); +if (!defined('GLZ_LOG_SYSTEM')) define('GLZ_LOG_SYSTEM', 2); +if (!defined('GLZ_LOG_INFO')) define('GLZ_LOG_INFO', 4); +if (!defined('GLZ_LOG_WARNING')) define('GLZ_LOG_WARNING', 8); +if (!defined('GLZ_LOG_ERROR')) define('GLZ_LOG_ERROR', 16); +if (!defined('GLZ_LOG_FATAL')) define('GLZ_LOG_FATAL', 32); +if (!defined('GLZ_LOG_ALL')) define('GLZ_LOG_ALL', 255); + + +class org_glizy_log_LogBase extends GlizyObject +{ + /*private*/ var $_formatFunc = NULL; + /*private*/ var $_logFormat = '[%l] %g %T%t %T%m'; + /*private*/ var $_timeFormat = 'Y-m-d H:I:S'; + /*private*/ var $_level = GLZ_LOG_ALL; + /*private*/ var $_levelsName = array(GLZ_LOG_DEBUG => 'DEBUG', + GLZ_LOG_SYSTEM => 'SYSTEM', + GLZ_LOG_INFO => 'INFO', + GLZ_LOG_WARNING => 'WARNING', + GLZ_LOG_ERROR => 'ERROR', + GLZ_LOG_FATAL => 'FATAL', + GLZ_LOG_ALL => 'ALL'); + /*private*/ var $_group = ''; + /*private*/ var $_isOpen = false; + + /** + * String containing the end-on-line character sequence. + * @var string + * @access private + */ + var $_eol = "\r\n"; + + + function __construct($options=array(), $level=GLZ_LOG_DEBUG, $group='') + { + $this->_level = $level; + $this->_group = $group; + + if (isset($options['logFormat'])) + { + $this->_logFormat = $options['logFormat']; + } + + if (isset($options['timeFormat'])) + { + $this->_timeFormat = $options['timeFormat']; + } + + $this->addEventListener(GLZ_LOG_EVENT, $this); + } + + + + function log($msg, $level=GLZ_LOG_DEBUG, $group='') + { + return false; + } + + function debug($msg, $group='') + { + $this->log($msg, GLZ_LOG_DEBUG, $group); + } + + function system($msg, $group='') + { + $this->log($msg, GLZ_LOG_SYSTEM, $group); + } + + function info($msg, $group='') + { + $this->log($msg, GLZ_LOG_INFO, $group); + } + + function warning($msg, $group='') + { + $this->log($msg, GLZ_LOG_WARNING, $group); + } + + function error($msg, $group='') + { + $this->log($msg, GLZ_LOG_ERROR, $group); + } + + function fatal($msg, $group='') + { + $this->log($msg, GLZ_LOG_FATAL, $group); + } + + function logByEvent($evt) + { + if (isset($evt->data['command']) && $evt->data['command']=='flush') + { + $this->flush(); + } + if (isset($evt->data['message'])) + { + $message = $evt->data['message']; + if ( is_array( $message )) + { + $message = var_export($message, true); + } + $this->log($message, isset($evt->data['level']) ? $evt->data['level'] : GLZ_LOG_DEBUG , isset($evt->data['group']) ? $evt->data['group'] : ''); + } + } + + function open() + { + return true; + } + + function close() + { + return true; + } + + function flush() + { + return true; + } + + + /* getter/setter */ + function setLevel($value) + { + $this->_level = $value; + } + + function getLevel() + { + return $this->_level; + } + + function setGroup($value) + { + $this->_group = $value; + } + + function getGroup() + { + return $this->_group; + } + + /* private methods */ + /*private*/ function _format($msg, $level, $group) + { + if (is_null($this->_formatFunc)) $this->_parseLogFormat(); + /** @var Callable $f */ + $f = $this->_formatFunc; + return $f($this->_levelsName[$level], $level, $group, $msg).$this->_eol; + } + + /*private*/ function _parseLogFormat() + { + $funCode = '$out = \'\';'; + + preg_match_all("|%[aAqlLgmdtT]|U", $this->_logFormat, $part1, PREG_SET_ORDER); + $part2 = preg_split("|%[aAqlLgmdtT]|U", $this->_logFormat, -1, PREG_SPLIT_DELIM_CAPTURE); + $part2Count = count($part2); + for($i=0; $i<$part2Count; $i++) + { + if ($i>0) + { + switch($part1[$i-1][0]) + { + case ('%a'): + $funCode .= '$out .= $_SERVER["REMOTE_ADDR"];'; + break; + case ('%A'): + $funCode .= '$out .= $_SERVER["SERVER_ADDR"];'; + break; + case ('%q'): + $funCode .= '$out .= $_SERVER["QUERY_STRING"];'; + break; + case ('%l'): + $funCode .= '$out .= $level;'; + break; + case ('%L'): + $funCode .= '$out .= $levelNum;'; + break; + case ('%g'): + $funCode .= '$out .= $group;'; + break; + case ('%m'): + $funCode .= '$out .= $msg;'; + break; + case ('%t'): + if (preg_match('|^{([^\}]*)}(.*)|', $part2[$i], $tf)) + { + $newTimeFormat = $tf[1]; + $part2[$i] = $tf[2]; + + } + else + { + $newTimeFormat = $this->_timeFormat; + } + + $newTimeFormat = preg_replace('|([aAbBcCdDegGhHIJmMnprRStTuUVWwxXyYzZ])|', '%$1', $newTimeFormat); + $funCode .= '$out .= strftime(\''.addslashes($newTimeFormat).'\');'; + + break; + case ('%T'): + $funCode .= '$out .= "\t";'; + break; + } + } + + $funCode .= '$out .= \''.addslashes($part2[$i]).'\';'; + } + + $funCode .= 'return $out;'; + $this->_formatFunc = create_function('$level, $levelNum, $group, $msg', $funCode); + } + + function _check($level, $group) + { + return (($level & $this->_level)>=1 && ($this->_group==$group || $this->_group=='*')); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/log/LogFactory.php b/src/core/classes/org/glizy/log/LogFactory.php new file mode 100755 index 0000000..e5182fb --- /dev/null +++ b/src/core/classes/org/glizy/log/LogFactory.php @@ -0,0 +1,36 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_log_LogFactory +{ + /** + * @return org_glizy_log_LogBase + */ + static function &create() + { + $args = func_get_args(); + $name = array_shift($args); + $newObj = NULL; + + if (file_exists(dirname(__FILE__).'/'.$name.'.php')) + { + glz_import('org.glizy.log.'.$name); + $className = str_replace('.', '_', 'org.glizy.log.'.$name); + $costructString = '$newObj = new '.$className.'('; + for ($i=0; $i<count($args); $i++) + { + $costructString .= '$args['.$i.']'; + if ($i<count($args)-1) $costructString .= ', '; + } + $costructString .= ');'; + eval($costructString); + } + return $newObj; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/log/Mail.php b/src/core/classes/org/glizy/log/Mail.php new file mode 100755 index 0000000..f68fe17 --- /dev/null +++ b/src/core/classes/org/glizy/log/Mail.php @@ -0,0 +1,55 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_log_Mail extends org_glizy_log_LogBase +{ + private $mailTitle; + private $destEmail; + + function __construct($destEmail, $mailTitle, $options=array(), $level=GLZ_LOG_DEBUG, $group='') + { + parent::__construct($options, $level, $group); + $this->destEmail = $destEmail; + $this->mailTitle = $mailTitle; + } + + + function log($msg, $level=GLZ_LOG_DEBUG, $group='') + { + if (!$this->_check($level, $group)) + { + return false; + } + if ( is_array( $msg ) || is_object( $msg ) ) + { + $msg = json_encode($msg); + } + org_glizy_helpers_Mail::sendEmail( array('email' => $this->destEmail, 'name' => $this->destEmail ), + array('email' => org_glizy_Config::get('SMTP_EMAIL'), 'name' => org_glizy_Config::get('SMTP_SENDER')), + $this->mailTitle, + str_replace( "\t", "<br />", $this->_format($msg, $level, $group) ) + ); + return true; + } + + function open() + { + return true; + } + + function close() + { + return true; + } + + function flush() + { + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/log/Null.php b/src/core/classes/org/glizy/log/Null.php new file mode 100755 index 0000000..63c4163 --- /dev/null +++ b/src/core/classes/org/glizy/log/Null.php @@ -0,0 +1,32 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_log_Null extends org_glizy_log_LogBase +{ + + function log($msg, $level=GLZ_LOG_DEBUG, $group='') + { + return true; + } + + function open() + { + return true; + } + + function close() + { + return true; + } + + function flush() + { + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/middleware/AbstractHttpCache.php b/src/core/classes/org/glizy/middleware/AbstractHttpCache.php new file mode 100755 index 0000000..96f4632 --- /dev/null +++ b/src/core/classes/org/glizy/middleware/AbstractHttpCache.php @@ -0,0 +1,27 @@ +<?php +abstract class org_glizy_middleware_AbstractHttpCache implements org_glizy_middleware_IMiddleware +{ + protected $etag; + protected $lastModifiedTime; + + protected function checkIfIsChanged() { + $this->setEtag(); + + $ifModifiedSince = (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false); + $etagHeader = (isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : false); + + if (($this->lastModifiedTime && $ifModifiedSince == $this->lastModifiedTime) || ($etagHeader == $this->etag)) { + header('HTTP/1.1 304 Not Modified'); + exit; + } + } + + protected function setEtag() + { + header("Cache-Control: private"); + header("Pragma:"); + header("Expires:"); + if ($this->lastModifiedTime) header('Last-Modified: '.gmdate('D, d M Y H:i:s', $this->lastModifiedTime).' GMT'); + header('Etag: '.$this->etag); + } +} diff --git a/src/core/classes/org/glizy/middleware/DynamicPage.php b/src/core/classes/org/glizy/middleware/DynamicPage.php new file mode 100755 index 0000000..c59eb3d --- /dev/null +++ b/src/core/classes/org/glizy/middleware/DynamicPage.php @@ -0,0 +1,13 @@ +<?php +class org_glizy_middleware_DynamicPage extends org_glizy_middleware_AbstractHttpCache +{ + public function beforeProcess($pageId, $pageType) + { + } + + public function afterRender($content) + { + $this->etag = md5($content.var_export(__Request::getAllAsArray(), true)); + $this->checkIfIsChanged(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/middleware/IMiddleware.php b/src/core/classes/org/glizy/middleware/IMiddleware.php new file mode 100644 index 0000000..ada26f1 --- /dev/null +++ b/src/core/classes/org/glizy/middleware/IMiddleware.php @@ -0,0 +1,6 @@ +<?php +interface org_glizy_middleware_IMiddleware +{ + public function beforeProcess($pageId, $pageType); + public function afterRender($content); +} diff --git a/src/core/classes/org/glizy/middleware/StaticPage.php b/src/core/classes/org/glizy/middleware/StaticPage.php new file mode 100755 index 0000000..f6b7a60 --- /dev/null +++ b/src/core/classes/org/glizy/middleware/StaticPage.php @@ -0,0 +1,19 @@ +<?php +class org_glizy_middleware_StaticPage extends org_glizy_middleware_AbstractHttpCache +{ + protected $etag; + protected $lastModifiedTime; + + public function beforeProcess($pageId, $pageType) + { + $fileName = org_glizy_Paths::getRealPath('APPLICATION_PAGE_TYPE').$pageType.'.xml'; + $this->lastModifiedTime = filemtime($fileName); + $this->etag = md5_file($fileName); + + $this->checkIfIsChanged(); + } + + public function afterRender($content) + { + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/models/Join.xml b/src/core/classes/org/glizy/models/Join.xml new file mode 100755 index 0000000..efc36d8 --- /dev/null +++ b/src/core/classes/org/glizy/models/Join.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="joins_tbl" model:usePrefix="true"> +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizy/models/JoinDoctrine.xml b/src/core/classes/org/glizy/models/JoinDoctrine.xml new file mode 100755 index 0000000..a94648e --- /dev/null +++ b/src/core/classes/org/glizy/models/JoinDoctrine.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="joins_tbl" model:usePrefix="true"> +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizy/models/Log.xml b/src/core/classes/org/glizy/models/Log.xml new file mode 100755 index 0000000..ed0961b --- /dev/null +++ b/src/core/classes/org/glizy/models/Log.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="logs_tbl" model:usePrefix="true"> + + <model:Query name="report" type="function"> + <![CDATA[ + $expr = $iterator->expr(); + + $iterator->join("t1", $this->tablePrefix."users_tbl", "t2", $expr->eq("t1.log_FK_user_id", "t2.user_id")); + ]]> + </model:Query> + +</model:Model> diff --git a/src/core/classes/org/glizy/models/Registry.xml b/src/core/classes/org/glizy/models/Registry.xml new file mode 100755 index 0000000..0f3e49f --- /dev/null +++ b/src/core/classes/org/glizy/models/Registry.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="registry_tbl" model:usePrefix="true"> +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizy/models/Role.xml b/src/core/classes/org/glizy/models/Role.xml new file mode 100644 index 0000000..7a68ac4 --- /dev/null +++ b/src/core/classes/org/glizy/models/Role.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="roles_tbl" model:usePrefix="true"> + + <!-- + // TODO + <model:Query name="getPermissions" type="function" arguments="id,groupId"> + <![CDATA[ + /* + org_glizy_dataAccessDoctrine_DataAccess::enableLogging(); + $andX = $iterator->expr()->andX(); + $orX = $iterator->expr()->orX(); + + $iterator->join('t1', $this->tablePrefix.'joins_tbl', 't2', $iterator->expr()->eq('role_id','join_FK_source_id')) + ->where($orX->add( + $andX->add( + $iterator->where('join_objectName', 'roles2users'), + $iterator->where('join_FK_dest_id', $id) + ), + $andX->add( + $iterator->where('join_objectName', 'roles2usergroups'), + $iterator->where('join_FK_dest_id', $groupId) + ) + ) + ); + ]]> + </model:Query> + --> + + <model:Query name="mysql_getPermissions"> + <![CDATA[ + SELECT * + FROM ##TABLE_PREFIX##joins_tbl JOIN + ##TABLE_PREFIX##roles_tbl ON join_FK_source_id = role_id + WHERE (join_objectName = 'roles2users' AND join_FK_dest_id = :id) OR + (join_objectName = 'roles2usergroups' AND join_FK_dest_id = :groupId) + ]]> + </model:Query> + + <model:Query name="pgsql_getPermissions"> + <![CDATA[ + SELECT * + FROM ##TABLE_PREFIX##joins_tbl JOIN + ##TABLE_PREFIX##roles_tbl ON "join_FK_source_id" = role_id + WHERE ("join_objectName" = 'roles2users' AND "join_FK_dest_id" = :id) OR + ("join_objectName" = 'roles2usergroups' AND "join_FK_dest_id" = :groupId) + ]]> + </model:Query> + +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizy/models/User.xml b/src/core/classes/org/glizy/models/User.xml new file mode 100755 index 0000000..efabffb --- /dev/null +++ b/src/core/classes/org/glizy/models/User.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="users_tbl" model:usePrefix="true"> + + <model:Query name="login" type="function" arguments="loginId,password"> + <!-- + Query for login + Used in: + org.glizy.authentication.Database + --> + <![CDATA[ + $iterator->join('t1', $this->tablePrefix.'usergroups_tbl', 't2', $iterator->expr()->eq('user_FK_usergroup_id', 'usergroup_id')) + ->where('user_loginId', $loginId) + ->where('user_password', $password); + ]]> + </model:Query> + + <!-- + <model:Query name="login"> + Query for login + Used in: + org.glizy.authentication.Database + <![CDATA[ + SELECT * FROM ##TABLE_NAME## + INNER JOIN ##TABLE_PREFIX##usergroups_tbl ON (user_FK_usergroup_id=usergroup_id) + WHERE user_loginId = :loginId AND user_password = :password + ]]> + </model:Query> + --> +</model:Model> diff --git a/src/core/classes/org/glizy/models/UserGroup.xml b/src/core/classes/org/glizy/models/UserGroup.xml new file mode 100755 index 0000000..734f158 --- /dev/null +++ b/src/core/classes/org/glizy/models/UserGroup.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="usergroups_tbl" model:usePrefix="true"> + +</model:Model> diff --git a/src/core/classes/org/glizy/models/UserLog.xml b/src/core/classes/org/glizy/models/UserLog.xml new file mode 100755 index 0000000..de8798e --- /dev/null +++ b/src/core/classes/org/glizy/models/UserLog.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="userlogs_tbl" model:usePrefix="true"> +<!-- + <glz:ModelDefine> + <glz:ModelField name="userlog_date" attribute="defaultInsertValue" value="NOW()" /> + <glz:ModelField name="userlog_lastAction" attribute="defaultInsertValue" value="NOW()" /> + <glz:ModelField name="userlog_lastAction" attribute="defaultUpdateValue" value="NOW()" /> + </glz:ModelDefine> +--> +</model:Model> diff --git a/src/core/classes/org/glizy/mvc/components/Page.php b/src/core/classes/org/glizy/mvc/components/Page.php new file mode 100755 index 0000000..439c1dd --- /dev/null +++ b/src/core/classes/org/glizy/mvc/components/Page.php @@ -0,0 +1,174 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_mvc_components_Page extends org_glizy_components_Page +{ + protected $controllerBasePath; + protected $sessionEx; + protected $action; + protected $actionName; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->acceptOutput = true; + $this->overrideEditableRegion = false; + $this->canCallController = false; + + // define the custom attributes + //$this->defineAttribute('actionName', false, 'action', COMPONENT_TYPE_STRING); + $this->defineAttribute('defaultAction', false, 'index', COMPONENT_TYPE_STRING); + $this->defineAttribute('baseClassPath', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('controllerName', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + + $this->actionName = $this->getAttribute( 'actionName' ); + + if (__Request::get($this->actionName, '') == '') { + __Request::set($this->actionName, $this->getAttribute( 'defaultAction' )); + } + + // backward compatibility + $baseClassPath = $this->getAttribute('baseClassPath'); + if ($baseClassPath) { + $controllerName = $this->getAttribute('controllerName'); + $this->setAttribute('controllerName', $baseClassPath.'.controllers.'.$controllerName.'.*'); + } + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $acl = $this->getAttribute( 'acl' ); + if ( !empty( $acl ) ) + { + list( $service, $action ) = explode( ',', $acl ); + if ( !$this->_user->acl( $service, $action ) ) + { + $this->breakCycle(); + $this->addOutputCode( "403 Forbidden" ); + return; + } + } + + $this->sessionEx = org_glizy_ObjectFactory::createObject('org.glizy.SessionEx', $this->getId()); + + $this->action = __Request::get( $this->actionName); + $oldAction = $this->sessionEx->get( $this->actionName ); + + foreach ( $this->childComponents as $c ) + { + if ( is_a( $c, 'org_glizy_mvc_components_State' ) ) + { + $c->deferredChildCreation(); + } + } + + $this->callController(); + $this->canCallController = true; + $this->action = strtolower( $this->action ); + parent::process(); + + $this->sessionEx->set( $this->actionName, $oldAction ); + } + + + /** + * Render + * + * @return string + * @access public + */ + function render($outputMode=NULL, $skipChilds=false) + { + $this->_application->_rootComponent->addOutputCode( org_glizy_helpers_JS::JScode( 'if ( typeof(Glizy) == "undefined" ) Glizy = {}; Glizy.baseUrl ="'.GLZ_HOST.'"; Glizy.ajaxUrl = "ajax.php?pageId='.$this->_application->getPageId().'&ajaxTarget='.$this->getId().'&action=";' ), 'head' ); + $t = ''; + $this->applyOutputFilters('pre', $t); + $this->renderChilds($outputMode); + return $this->_render(); + } + + function _render() + { + if ( $this->getAttribute( 'addCoreJS' ) === true ) + { + $this->_application->addJSLibCore(); + } + $template = NULL; + + // riordina l'array con i dati dell'editableRegions da passare alla classe template + $templateOutput = array(); + $atEnd = false; + for ($j=0; $j<=1; $j++) + { + for ($i=0; $i<count($this->_output); $i++) + { + if ($this->_output[$i]['atEnd']===($j==0 ? false : true)) + { + if (!array_key_exists($this->_output[$i]['editableRegion'], $templateOutput)) + { + $templateOutput[$this->_output[$i]['editableRegion']] = ''; + } + + $templateOutput[$this->_output[$i]['editableRegion']] .= $this->_output[$i]['code']; + } + if ($this->_output[$i]['atEnd']===true) $atEnd = true; + } + if (!$atEnd) break; + } + + $templateFileName = $this->getAttribute( 'templateFileName' ); + if ( empty( $templateFileName ) ) + { + $templateFileName = $this->_application->getPageId().'.php'; + } + $template = org_glizy_ObjectFactory::createObject ('org.glizy.template.layoutManager.PHP', $templateFileName ); + $output = $template->apply($templateOutput); + return $output ; + } + + function getAction() + { + return $this->action; + } + + + function getState() + { + return strtolower($this->action); + } + + // TODO + // modificare il tipo di implementazione + // non mi piace che un componente chieda l'url ad un'altro componente + function changeStateUrl($newState='', $amp=false ) + { + if ( is_null( $this->getAttribute('targetPage') ) ) + { + return org_glizy_helpers_Link::makeUrl('linkChangeAction', array('pageId' => $this->_application->getPageId(), $this->actionName => $newState)); + } + else + { + return org_glizy_helpers_Link::makeUrl('link', array('pageId' => $this->getAttribute('targetPage')), array($this->actionName => $newState)); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/mvc/components/State.php b/src/core/classes/org/glizy/mvc/components/State.php new file mode 100755 index 0000000..41e0d02 --- /dev/null +++ b/src/core/classes/org/glizy/mvc/components/State.php @@ -0,0 +1,178 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_mvc_components_State extends org_glizy_components_ComponentContainer +{ + private $actions; + private $actionsOriginal; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('name', true, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('url', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('draw', false , true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('backUrl', false , false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('cssClassTab', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + + $this->actionsOriginal = explode(',', $this->getAttribute('name') ); + $this->actions = explode(',', strtolower($this->getAttribute('name'))); + } + + function deferredChildCreation($force=false) + { + if ( $this->isCurrentState() || $force) + { + // aggiunge i figli + if ( !count( $this->childComponents ) ) + { + $function = 'addChild_'.$this->getId(); + $function ( $this->_application, $this ); + $this->initChilds(); + $this->execDoLater(); + } + + if ( $this->getAttribute( 'backUrl' ) ) + { + __Session::set( '__backUrl__', __Request::get( '__backUrl__' ) ); + } + } + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + if ( $this->isCurrentState() ) + { + if ( !count( $this->childComponents ) ) + { + $this->deferredChildCreation(); + } + + $this->processChilds(); + } + } + + /** + * Render + * + * @return void + * @access public + */ + function render($outputMode=NULL, $skipChilds=false) + { + if ( $this->isCurrentState() ) + { + $cssClass = $this->getAttribute( 'cssClass' ); + if ( !empty( $cssClass ) ) + { + $this->addOutputCode( '<div class="'.$cssClass.'">' ); + } + + $this->renderChilds($outputMode); + + if ( !empty( $cssClass ) ) + { + $this->addOutputCode( '</div>' ); + } + } + } + + function getAction() + { + if ( method_exists( $this->_parent, "getAction" ) ) + { + return $this->_parent->getAction(); + } + else if ( method_exists( $this->_parent, "getState" ) ) + { + return $this->_parent->getState(); + } + return ''; + } + + function getStateAction() + { + return $this->actionsOriginal[0]; + } + + function getActionArray() + { + return $this->actions; + } + + function isCurrentState() + { + return in_array( strtolower( $this->getAction() ), $this->actions ); + } + + public static function compile($compiler, &$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix, $componentClassInfo, $componentId) + { + $compiler->_classSource .= '$n'.$counter.' = &org_glizy_ObjectFactory::createComponent(\''.$componentClassInfo['classPath'].'\', $application, '.$parent.', \''.$node->nodeName.'\', '.$idPrefix.'\''.$componentId.'\', \''.$componentId.'\', $skipImport)'.GLZ_COMPILER_NEWLINE; + + $forceChildCreation = $node->hasAttribute( 'forceChildCreation' ) && strtolower( $node->getAttribute( 'forceChildCreation' ) ) == 'true' ? + 'true' : + $node->parentNode->hasAttribute( 'forceChildCreation' ) && strtolower($node->parentNode->getAttribute( 'forceChildCreation' ) ) == 'true' ? 'true' : 'false'; + $compiler->_classSource .= '$forceChildCreation = '.$forceChildCreation.GLZ_COMPILER_NEWLINE; + if ($parent!='NULL') + { + $compiler->_classSource .= $parent.'->addChild($n'.$counter.')'.GLZ_COMPILER_NEWLINE; + } + + if (count($node->attributes)) + { + // compila gli attributi + $compiler->_classSource .= '$attributes = array('; + foreach ( $node->attributes as $index=>$attr ) + { + if ($attr->name!='id') + { + $compiler->_classSource .= '\''.$attr->name.'\' => \''.addslashes($attr->value).'\', '; + } + } + $compiler->_classSource .= ')'.GLZ_COMPILER_NEWLINE; + $compiler->_classSource .= '$n'.$counter.'->setAttributes( $attributes )'.GLZ_COMPILER_NEWLINE; + } + + $compiler->_classSource .= 'if ($skipImport || $forceChildCreation) {addChild_'.$componentId.'($application, $n'.$counter.', $skipImport, $idPrefix, $mode);}'.GLZ_COMPILER_NEWLINE; + + $previusClassSource = $compiler->_classSource; + $compiler->_classSource = ''; + $compiler->_classSource .= '// STATE function '.GLZ_COMPILER_NEWLINE2; + $compiler->_classSource .= 'function addChild_'.$componentId.'( &$application, &$n'.$counter.', $skipImport=false, $idPrefix=\'\', $mode=\'\') {'.GLZ_COMPILER_NEWLINE2; + + $oldcounter = $counter; + foreach( $node->childNodes as $nc ) + { + $counter++; + $compiler->_compileXml($nc, $registredNameSpaces, $counter, '$n'.$oldcounter, $idPrefix); + } + $compiler->_classSource .= '} '.GLZ_COMPILER_NEWLINE; + $compiler->_classSource .= '// end STATE function '.GLZ_COMPILER_NEWLINE2; + + $compiler->_customClassSource .= $compiler->_classSource; + $compiler->_classSource = $previusClassSource; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/mvc/components/StateTabNavigation.php b/src/core/classes/org/glizy/mvc/components/StateTabNavigation.php new file mode 100755 index 0000000..4019736 --- /dev/null +++ b/src/core/classes/org/glizy/mvc/components/StateTabNavigation.php @@ -0,0 +1,91 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizy_mvc_components_StateTabNavigation extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('addWrapDiv', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClassCurrent', false, 'current', COMPONENT_TYPE_STRING); + $this->defineAttribute('forceLink', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('addQueryString', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('routeUrl', false, 'moduleAction', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + function render_html() + { + if ($this->getAttribute('addWrapDiv')) + { + $output = '<div id="'.$this->getId().'"><ul '.(!is_null($this->getAttribute('cssClass')) ? ' class="'.$this->getAttribute('cssClass').'"' : '').'>'; + } + else + { + $output = '<ul id="'.$this->getId().'"'.(!is_null($this->getAttribute('cssClass')) ? ' class="'.$this->getAttribute('cssClass').'"' : '').'>'; + } + + $controller = $this->_parent; + + $queryString = $this->getAttribute('addQueryString') ? '?'.__Request::get('__back__url__') : ''; + + foreach ( $controller->childComponents as $c ) + { + if ( is_a( $c, 'org_glizy_mvc_components_State' ) ) + { + $label = $c->getAttribute('label'); + $draw = $c->getAttribute('draw'); + $aclResult = $this->evalueteAcl($c->getAttribute('acl')); + $cssClass = trim($c->getAttribute('cssClassTab'). + ($c->isCurrentState() ? ' '.$this->getAttribute( 'cssClassCurrent' ) : '')); + if ($cssClass) { + $cssClass = ' class="'.$cssClass.'"'; + } + $id = $c->getId(); + if ( $draw && !empty($label) && $aclResult) + { + if (!empty($cssClass) && !$this->getAttribute('forceLink')) + { + $output .= '<li'.$cssClass.'>'.$label.'</li>'; + } + else + { + $url = $c->getAttribute('url'); + if (is_null($url)) + { + $url = __Link::makeUrl( $this->getAttribute('routeUrl'), array( 'title' => $label, 'action' => $c->getStateAction() ) ); + } + else + { + $url = __Link::makeUrl( $url ); + } + $output .= '<li'.$cssClass.'><a id="' . $id . '" href="'.$url.$queryString.'"'.$cssClass.'>'.$label.'</a></li>'; + } + } + } + } + + + $output .= '</ul>'; + if ($this->getAttribute('addWrapDiv')) + { + $output .= '</div>'; + } + $this->addOutputCode($output); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/mvc/core/Application.php b/src/core/classes/org/glizy/mvc/core/Application.php new file mode 100755 index 0000000..8c88050 --- /dev/null +++ b/src/core/classes/org/glizy/mvc/core/Application.php @@ -0,0 +1,110 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_mvc_core_Application extends org_glizy_application_Application +{ + protected $proxyMap = array(); + public $useXmlSiteMap = false; + + /** + * @param bool $readPageId + */ + function _startProcess($readPageId=true) + { + foreach( $this->proxyMap as $k=>$v ) + { + $v->onRegister(); + } + + parent::_startProcess($readPageId); + } + + /** + * @param string $className + * + * @return GlizyObject|mixed + */ + function registerProxy( $className ) + { + if ( array_key_exists( $className, $this->proxyMap ) ) + { + new org_glizy_Exception( '[mvc:Application] Proxy già registrato' ); + } + + $classObj = __ObjectFactory::createObject( $className, $this ); + + if ( is_object( $classObj ) ) + { + $this->proxyMap[ $className ] = $classObj; + return $classObj; + } + else + { + new org_glizy_Exception( '[mvc:Application] Proxy non trovato '.$className ); + } + } + + /** + * @param string $className + * + * @return null| + */ + function retrieveProxy( $className ) + { + if ( array_key_exists( $className, $this->proxyMap ) ) + { + return $this->proxyMap[ $className ]; + } + + return null; + } + + /** + * @param $className + * + * @return GlizyObject|mixed + */ + function retrieveService( $className ) + { + $classObj = __ObjectFactory::createObject( $className, $this ); + return $classObj; + } + + /** + * @param bool $forceReload + */ + function _initSiteMap($forceReload=false) + { + if ( $this->useXmlSiteMap ) + { + $this->siteMap = org_glizy_ObjectFactory::createObject('org.glizy.application.SiteMapXML'); + $this->siteMap->getSiteArray($forceReload); + } + else + { + parent::_initSiteMap(); + } + } + + /** + * @param string $command + * + * @return mixed + */ + function executeCommand( $command ) + { + $actionClass = &org_glizy_ObjectFactory::createObject( $command, null, $this ); + if ( is_object( $actionClass ) && method_exists( $actionClass, "execute" ) ) { + $params = func_get_args(); + array_shift($params); + return call_user_func_array( array( $actionClass, "execute" ), $params ); + } + return null; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/mvc/core/Command.php b/src/core/classes/org/glizy/mvc/core/Command.php new file mode 100755 index 0000000..ee12a2b --- /dev/null +++ b/src/core/classes/org/glizy/mvc/core/Command.php @@ -0,0 +1,77 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_mvc_core_Command + */ +class org_glizy_mvc_core_Command extends GlizyObject +{ + /** @var org_glizy_mvc_components_State $controller */ + protected $controller = NULL; + /** @var org_glizy_mvc_components_State $view */ + protected $view = NULL; + /** @var org_glizy_mvc_core_Application $application */ + protected $application = NULL; + /** @var org_glizy_application_User $user */ + protected $user = NULL; + + function __construct( $view=NULL, $application=NULL ) + { + $this->controller = $view; + $this->view = $view; + $this->application = is_null( $application ) && !is_null( $view ) ? $view->_application : $application; + $this->user = &$this->application->getCurrentUser(); + } + + function execute( $oldAction=null ) + { + } + + function changePage( $routingName, $option=array(), $addParam=array() ) + { + $url = __Link::makeUrl( $routingName, $option, $addParam ); + org_glizy_helpers_Navigation::gotoUrl( $url ); + } + + function changeAction( $action ) + { + $url = __Link::makeUrl( 'linkChangeAction', array( 'action' => $action ) ); + org_glizy_helpers_Navigation::gotoUrl( $url ); + } + + function goHere($params=null, $hash) + { + org_glizy_helpers_Navigation::gotoUrl( __Routing::scriptUrl(), $params, $hash); + } + + function changeBackPage() + { + $url = __Session::get( '__backUrl__', '' ); + org_glizy_helpers_Navigation::gotoUrl( $url ); + } + + + function setComponentsVisibility( $components, $state ) + { + $this->setComponentsAttribute( $components, 'visible', $state ); + } + + function setComponentsAttribute( $components, $attribute, $state ) + { + $components = is_array( $components ) ? $components : array( $components ); + foreach( $components as $v ) + { + $c = $this->view->getComponentById( $v ); + if ( is_object( $c ) ) + { + $c->setAttribute( $attribute, $state ); + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/mvc/core/CommandAjax.php b/src/core/classes/org/glizy/mvc/core/CommandAjax.php new file mode 100755 index 0000000..d2f159f --- /dev/null +++ b/src/core/classes/org/glizy/mvc/core/CommandAjax.php @@ -0,0 +1,48 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** class org_glizy_mvc_core_CommandAjax */ +class org_glizy_mvc_core_CommandAjax extends GlizyObject +{ + protected $controller = NULL; + protected $view = NULL; + /** @var org_glizy_mvc_core_Application $application */ + protected $application = NULL; + /** @var org_glizy_application_User $user */ + protected $user = NULL; + public $directOutput = false; + + function __construct( $view=NULL, $application=NULL ) + { + $this->controller = $view; + $this->view = $view; + $this->application = is_null( $application ) && !is_null( $view ) ? $view->_application : $application; + $this->user = &$this->application->getCurrentUser(); + } + + function execute( $oldAction=null ) + { + return true; + } + + function changePage( $routingName, $option=array() ) + { + $url = __Link::makeUrl( $routingName, $option ); + $url = str_replace( "ajax", "index", $url ); + return $url; + } + + function changeAction( $action ) + { + $url = __Link::makeUrl( 'linkChangeAction', array( 'action' => $action ) ); + $url = str_replace( "ajax", "index", $url ); + return $url; + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/mvc/core/Proxy.php b/src/core/classes/org/glizy/mvc/core/Proxy.php new file mode 100755 index 0000000..dc4aef5 --- /dev/null +++ b/src/core/classes/org/glizy/mvc/core/Proxy.php @@ -0,0 +1,24 @@ +<?php + +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ +class org_glizy_mvc_core_Proxy extends GlizyObject +{ + + /** + * @var org_glizy_mvc_core_Application $application + */ + protected $application = null; + + /** + * @param org_glizy_application_Application $application + */ + function __construct($application) + { + $this->application = $application; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/mvc/scaffold/controllers/AbstractCommand.php b/src/core/classes/org/glizy/mvc/scaffold/controllers/AbstractCommand.php new file mode 100755 index 0000000..248264c --- /dev/null +++ b/src/core/classes/org/glizy/mvc/scaffold/controllers/AbstractCommand.php @@ -0,0 +1,32 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_mvc_scaffold_controllers_AbstractCommand + */ +class org_glizy_mvc_scaffold_controllers_AbstractCommand extends org_glizy_mvc_core_Command +{ + protected $modelName = ''; + protected $pageId = ''; + protected $submit = false; + protected $refreshPage = false; + protected $show = false; + protected $id; + + function __construct( $controller=NULL, $application=NULL ) + { + parent::__construct( $controller, $application ); + + $this->submit = strtolower( __Request::get( 'submit', '' ) ) == 'submit' || strtolower( __Request::get( 'submit', '' ) ) == 'submitclose'; + $this->show = strtolower( __Request::get( 'action', '' ) ) == 'show'; + $this->refreshPage = strtolower( __Request::get( 'action', '' ) ) == 'close' || strtolower( __Request::get( 'submit', '' ) ) == 'submitclose'; + $this->id = intval( __Request::get( 'id', '' ) ); + $this->pageId = $this->application->getPageId(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/mvc/scaffold/controllers/Add.php b/src/core/classes/org/glizy/mvc/scaffold/controllers/Add.php new file mode 100755 index 0000000..6b0c7ce --- /dev/null +++ b/src/core/classes/org/glizy/mvc/scaffold/controllers/Add.php @@ -0,0 +1,50 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_mvc_scaffold_controllers_Add + */ +class org_glizy_mvc_scaffold_controllers_Add extends org_glizy_mvc_scaffold_controllers_Show +{ + function executeLater() + { + if ( $this->submit ) + { + if ($this->controller->validate()) + { + $isNewRecord = $this->id == 0; + $ar = org_glizy_ObjectFactory::createModel( $this->modelName ); + $ar->loadFromArray( __Request::getAllAsArray() ); + $this->id = $ar->save(); + + $this->redirect( $isNewRecord ); + } + } + } + + protected function redirect( $isNewRecord ) + { + $this->logAndMessage( __T( 'Informazioni salvate con successo' ) ); + if ( !$this->refreshPage ) + { + if ( !$isNewRecord ) + { + $this->goHere(); + } + else + { + $this->changePage( 'linkChangeAction', array( 'pageId' => $this->pageId, 'action' => 'add' ), array( 'id' => $this->id ) ); + } + } + else + { + $this->changePage( 'link', array( 'pageId' => $this->pageId ) ); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/mvc/scaffold/controllers/Delete.php b/src/core/classes/org/glizy/mvc/scaffold/controllers/Delete.php new file mode 100755 index 0000000..48041a7 --- /dev/null +++ b/src/core/classes/org/glizy/mvc/scaffold/controllers/Delete.php @@ -0,0 +1,25 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_mvc_scaffold_controllers_Delete + */ +class org_glizy_mvc_scaffold_controllers_Delete extends org_glizy_mvc_scaffold_controllers_AbstractCommand +{ + function execute() + { + if ( $this->id > 0 ) + { + $this->logAndMessage( __T( 'Record cancellato' ) ); + $ar = org_glizy_ObjectFactory::createModel( $this->modelName ); + $ar->delete( $this->id ); + $this->changePage( 'link', array( 'pageId' => $this->pageId ) ); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/mvc/scaffold/controllers/Show.php b/src/core/classes/org/glizy/mvc/scaffold/controllers/Show.php new file mode 100755 index 0000000..18e21b9 --- /dev/null +++ b/src/core/classes/org/glizy/mvc/scaffold/controllers/Show.php @@ -0,0 +1,36 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_mvc_scaffold_controllers_Show + */ +class org_glizy_mvc_scaffold_controllers_Show extends org_glizy_mvc_scaffold_controllers_AbstractCommand +{ + protected $ar; + + function execute() + { + if ( !$this->submit ) + { + if ( is_numeric( $this->id ) ) + { + if ( $this->id > 0 ) + { + $this->ar = org_glizy_ObjectFactory::createModel( $this->modelName ); + $this->ar->load( $this->id ); + __Request::setFromArray( $this->ar->getValuesAsArray() ); + } + } + else + { + $this->changePage( 'link', array( 'pageId' => $this->pageId ) ); + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/oaipmh/OaiPmh.php b/src/core/classes/org/glizy/oaipmh/OaiPmh.php new file mode 100755 index 0000000..5b0ff8b --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/OaiPmh.php @@ -0,0 +1,163 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_oaipmh_OaiPmh +{ + public static function is_valid_uri($url) + { + return((bool) preg_match("'^[^:]+:(?:[a-z_0-9-]+[\.]{1})*(?:[a-z_0-9-]+\.)[a-z]{2,3}.*$'i", $url)); + } + + public static function encode($string, $xmlescaped=false) + { + $string = stripslashes($string); + // just remove invalid characters + $pattern ="/[\x-\x8\xb-\xc\xe-\x1f]/"; + $string = preg_replace($pattern,'',$string); + + // escape only if string is not escaped + if (!$xmlescaped) { + $string = htmlspecialchars($string, ENT_QUOTES); + } + + return $string; + } + + public static function openMetadataHeader( $metadata ) + { + $output = !$metadata[ 'recordPrefix' ] ? '<'.$metadata[ 'prefix' ] : '<'.$metadata[ 'prefix' ].':'.$metadata[ 'recordPrefix' ]; + $output .= ' xmlns:'.$metadata[ 'prefix' ].'="'.$metadata['namespace'].'"'; + if ( $metadata[ 'recordPrefix' ] && $metadata[ 'recordNamespace' ] ) + { + $output .= ' xmlns:'.$metadata[ 'recordPrefix' ].'="'.$metadata['recordNamespace'].'"'; + } + $output .= ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'; + $output .= ' xsi:schemaLocation="'.$metadata['namespace'].' '.$metadata['schema'].'">'; + + return $output; + } + + public static function closeMetadataHeader( $metadata ) + { + return !$metadata[ 'recordPrefix' ] ? '</'.$metadata[ 'prefix' ].'>' : '</'.$metadata[ 'prefix' ].':'.$metadata[ 'recordPrefix' ].'>'; + } + + public static function checkDateFormat($date) + { + if ( __Config::get( 'oaipmh.granularity' ) == 'YYYY-MM-DDThh:mm:ssZ') + { + $checkstr = '/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})T([0-9]{2}):([0-9]{2}):([0-9]{2})Z$/'; + } else { + $checkstr = '/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2}$)/'; + } + if (preg_match($checkstr, $date, $regs)) + { + if (checkdate($regs[2], $regs[3], $regs[1])) { + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } + + + public static function formatDatestamp($datestamp) + { + $datestamp = glz_localeDate2default($datestamp); + $datestamp = org_glizy_oaipmh_OaiPmh::date2UTCdatestamp($datestamp); + if (!org_glizy_oaipmh_OaiPmh::checkDateFormat($datestamp)) { + if ( __Config::get( 'oaipmh.granularity' ) == 'YYYY-MM-DD') { + return '2002-01-01'; + } else { + return '2002-01-01T00:00:00Z'; + } + } else { + return $datestamp; + } + } + + + public static function date2UTCdatestamp($date) + { + $granularity = __Config::get( 'oaipmh.granularity' ); + + switch ($granularity) { + + case 'YYYY-MM-DDThh:mm:ssZ': + // we assume common date ("YYYY-MM-DD") or + // datetime format ("YYYY-MM-DD hh:mm:ss") + // in the database + if (strstr($date, ' ')) { + // date is datetime format + if (strstr($date, '+')) { + // format ("YYYY-MM-DD hh:mm:ss+01") + list($ld, $lt) = explode(" ", $date); + list($y, $m, $d) = explode("-", $ld); + list($time, $tz) = explode("+", $lt); + list($h, $min, $s) = explode(":", $time); + if ($tz > 0) { + $timestamp = mktime($h, $min, $s, $m, $d, $y); + $timestamp -= (int) $tz * 86400; + return strftime("%Y-%m-%dT%H:%M:%SZ", $timestamp); + } + } + return str_replace(' ', 'T', $date).'Z'; + } else { + // date is date format + // granularity 'YYYY-MM-DD' should be used... + return $date.'T00:00:00Z'; + } + break; + + case 'YYYY-MM-DD': + if (strstr($date, ' ')) { + // date is datetime format + list($date) = explode(" ", $date); + return $date; + } else { + return $date; + } + break; + + default: die("Unknown granularity!"); + } + } + + public static function tokenValid() + { + return 24*3600; + } + + public static function getTokenId() + { + return md5( microtime( true ) ); + } + + public static function createResumptionToken( $type, $info ) + { + $isLast = $info[ 'numRows' ] <= $info[ 'limitEnd' ]; + if ( !$isLast ) + { + $expirationdatetime = gmstrftime('%Y-%m-%dT%TZ', time()+self::tokenValid()); + $tokenId = $type.'-'.self::getTokenId(); + file_put_contents( __Paths::get( 'CACHE' ).$tokenId, serialize( $info ) ); + return '<resumptionToken expirationDate="'.$expirationdatetime.'" completeListSize="'.$info[ 'numRows' ].'" cursor="'.$info[ 'limitStart' ].'">'.$tokenId.'</resumptionToken>'; + } + else + { + return '<resumptionToken completeListSize="'.$info[ 'numRows' ].'" cursor="'.$info[ 'limitStart' ].'"></resumptionToken>'; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/oaipmh/components/GetRecord.php b/src/core/classes/org/glizy/oaipmh/components/GetRecord.php new file mode 100755 index 0000000..8ccabd1 --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/components/GetRecord.php @@ -0,0 +1,115 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_oaipmh_components_GetRecord extends org_glizy_components_Component +{ + protected $arPico; + protected $setClass; + + /** + * Render + * + * @return void + * @access public + */ + function render($outputMode=NULL, $skipChilds=false) + { + if ( __Request::exists( 'identifier' ) ) + { + $identifier = __Request::get( 'identifier' ); + if (!org_glizy_oaipmh_OaiPmh::is_valid_uri($identifier)) + { + $this->_application->setError('badArgument', 'identifier', $identifier ); + return; + } + } + else + { + $this->_application->setError( 'missingArgument', 'identifier' ); + return; + } + + if ( __Request::exists( 'metadataPrefix' ) ) + { + $metadataPrefix = __Request::get( 'metadataPrefix' ); + $metadata = $this->_application->getMetadataFormat(); + if ( isset( $metadata[$metadataPrefix] ) ) + { + //TODO + //$inc_record = $metadata[$metadataPrefix]['myhandler']; + } + else + { + $this->_application->setError( 'cannotDisseminateFormat', 'metadataPrefix', $metadataPrefix ); + return; + } + } + else + { + $this->_application->setError( 'missingArgument', 'metadataPrefix' ); + return; + } + + $id = str_replace( __Config::get( 'oaipmh.oaiPrefix' ), '', $identifier ); + if ($id == '') + { + $this->_application->setError( 'idDoesNotExist', '', $identifier); + return; + } + + $this->loadeRecord($id); + if ( $this->arPico && $this->setClass ) + { + if ( $this->setClass->loadRecord( $this->arPico->picoqueue_recordId ) ) + { + $output = '<GetRecord>'; + $output .= '<record>'; + + // header + $datestamp = org_glizy_oaipmh_OaiPmh::formatDatestamp( $this->arPico->picoqueue_date ); + $status_deleted = $this->arPico->picoqueue_action == 'delete' ? true : false; + + $output .= '<header'.($status_deleted ? ' status="deleted"' : '' ).'>'; + $output .= '<identifier>'.org_glizy_oaipmh_OaiPmh::encode( $identifier ).'</identifier>'; + $output .= '<datestamp>'.org_glizy_oaipmh_OaiPmh::encode( $datestamp ).'</datestamp>'; + if (!$status_deleted) + { + $output .= '<setSpec>'.org_glizy_oaipmh_OaiPmh::encode( $this->arPico->picoqueue_recordModule ).'</setSpec>'; + } + $output .= '</header>'; + $output .= '<metadata>'; + $output .= $this->setClass->getRecord($identifier); + $output .= '</metadata>'; + $output .= '</record>'; + $output .= '</GetRecord>'; + $this->addOutputCode( $output ); + } + else + { + $this->_application->setError( 'idDoesNotExist', '', $identifier); + return; + } + } + else + { + $this->_application->setError( 'idDoesNotExist', '', $identifier); + return; + } + } + + protected function loadeRecord($id) { + $this->arPico = org_glizy_ObjectFactory::createModel( 'org.glizy.oaipmh.models.PicoQueue' ); + if ( $this->arPico->find( array( 'picoqueue_identifier' => $id ) ) ) { + // record trovato + $this->setClass = org_glizy_ObjectFactory::createObject( $this->arPico->picoqueue_recordModule, $this->_application ); + } else { + $this->arPico = null; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/oaipmh/components/Identify.php b/src/core/classes/org/glizy/oaipmh/components/Identify.php new file mode 100755 index 0000000..9931cd0 --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/components/Identify.php @@ -0,0 +1,32 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_oaipmh_components_Identify extends org_glizy_components_Component +{ + /** + * Render + * + * @return void + * @access public + */ + function render($outputMode=NULL, $skipChilds=false) + { + $output = '<Identify>'; + $output .= '<repositoryName>'.org_glizy_oaipmh_OaiPmh::encode( __Config::get( 'oaipmh.title' ) ).'</repositoryName>'; + $output .= '<baseURL>'.org_glizy_oaipmh_OaiPmh::encode( GLZ_HOST ).'</baseURL>'; + $output .= '<protocolVersion>'.org_glizy_oaipmh_OaiPmh::encode( __Config::get( 'oaipmh.protocolVersion' ) ).'</protocolVersion>'; + $output .= '<adminEmail>'.org_glizy_oaipmh_OaiPmh::encode( __Config::get( 'oaipmh.adminEmail' ) ).'</adminEmail>'; + $output .= '<earliestDatestamp>'.org_glizy_oaipmh_OaiPmh::encode( __Config::get( 'oaipmh.earliestDatestamp' ) ).'</earliestDatestamp>'; + $output .= '<deletedRecord>no</deletedRecord>'; + $output .= '<granularity>'.org_glizy_oaipmh_OaiPmh::encode( __Config::get( 'oaipmh.granularity' ) ).'</granularity>'; + $output .= '</Identify>'; + $this->addOutputCode( $output ); + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/oaipmh/components/ListIdentifiers.php b/src/core/classes/org/glizy/oaipmh/components/ListIdentifiers.php new file mode 100755 index 0000000..591891a --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/components/ListIdentifiers.php @@ -0,0 +1,172 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_oaipmh_components_ListIdentifiers extends org_glizy_components_Component +{ + /** + * Render + * + * @return void + * @access public + */ + function render($outputMode=NULL, $skipChilds=false) + { + $from = ''; + $until = ''; + $set = ''; + $limitStart = 0; + + if ( __Request::exists( 'resumptionToken' ) ) + { + if ( !__Request::exists( 'from' ) && !__Request::exists( 'until' ) && !__Request::exists( 'set' ) && !__Request::exists( 'metadataPrefix' ) ) + { + // TODO controllare la data di scadenza del token + $tokenId = __Request::get( 'resumptionToken' ); + $fileName = __Paths::get( 'CACHE' ).$tokenId; + if ( file_exists( $fileName ) ) + { + $info = unserialize( file_get_contents( $fileName ) ); + $limitStart = $info[ 'limitEnd' ]; + $filters = $info[ 'filters' ]; + $metadataPrefix = $info[ 'metadataPrefix' ]; + } + else + { + $this->_application->setError( 'badResumptionToken', '', $tokenId ); + return; + } + } + else + { + $this->_application->setError( 'exclusiveArgument' ); + return; + } + } + else + { + // controlla i parametri ricevuti + if ( __Request::exists( 'from' ) ) + { + $from = __Request::get( 'from' ); + if ( !org_glizy_oaipmh_OaiPmh::checkDateFormat($from) ) + { + $this->_application->setError( 'badGranularity', 'from', $from); + return; + } + } + + if ( __Request::exists( 'until' ) ) + { + $until = __Request::get( 'until' ); + if (!org_glizy_oaipmh_OaiPmh::checkDateFormat($until)) + { + $this->_application->setError( 'badGranularity', 'until', $until); + return; + } + } + + if ( __Request::exists( 'set' ) ) + { + $set = __Request::get( 'set' ); + } + + if ( __Request::exists( 'metadataPrefix' ) ) + { + $metadataPrefix = __Request::get( 'metadataPrefix' ); + + } + else + { + $this->_application->setError( 'missingArgument', 'metadataPrefix' ); + return; + } + + // TODO: scrivere i filtri per ActiveRecord Doctrine + $filters = array(); + if ( $from ) + { + $filters[] = 'picoqueue_date >= '.org_glizy_dataAccess_DataAccess::qstr( $from ); + } + if ( $until ) + { + $filters[] = 'picoqueue_date <= '.org_glizy_dataAccess_DataAccess::qstr( $until ); + } + if ( $set ) + { + $filters[] = 'picoqueue_recordModule = '.org_glizy_dataAccess_DataAccess::qstr( $set ); + } + } + + + $metadata = $this->_application->getMetadataFormat(); + if ( isset( $metadata[$metadataPrefix] ) ) + { + // TODO +// $inc_record = $metadata[$metadataPrefix]['myhandler']; + } + else + { + $this->_application->setError( 'cannotDisseminateFormat', 'metadataPrefix', $metadataPrefix ); + return; + } + + $limitLength = __Config::get( 'oaipmh.maxIds' ); + $it = org_glizy_ObjectFactory::createModelIterator( 'org.glizy.oaipmh.models.PicoQueue', 'all', array( + 'filters' => $filters, + 'limit' => array( $limitStart, $limitLength ), + 'numRows' => true + ) ); + $num_rows = $it->count(); + if ( $num_rows > 0 ) + { + $oaiPrefix = __Config::get( 'oaipmh.oaiPrefix' ); + $countrec = 0; + + $output = '<ListIdentifiers>'; + $output .= org_glizy_oaipmh_OaiPmh::createResumptionToken( 'ListIdentifiers', + array( + 'numRows' => $num_rows, + 'limitStart' => $limitStart, + 'limitEnd' => $limitStart + $limitLength, + 'filters' => $filters, + 'metadataPrefix' => $metadataPrefix, + ) ); + + foreach ($it as $arC) { + $countrec++; + $identifier = $oaiPrefix.$arC->picoqueue_identifier; + $datestamp = org_glizy_oaipmh_OaiPmh::formatDatestamp( $arC->picoqueue_date ); + $status_deleted = $arC->picoqueue_action == 'delete' ? true : false; + + $output .= ' <header'; + if ($status_deleted) + { + $output .= ' status="deleted"'; + } + $output .='>'; + + // use xmlrecord since we use stuff from database + $output .= '<identifier>'.org_glizy_oaipmh_OaiPmh::encode( $identifier ).'</identifier>'; + $output .= '<datestamp>'.org_glizy_oaipmh_OaiPmh::encode( $datestamp ).'</datestamp>'; + if (!$status_deleted) + { + $output .= '<setSpec>'.org_glizy_oaipmh_OaiPmh::encode( $arC->picoqueue_recordModule ).'</setSpec>'; + } + $output .= ' </header>'."\n"; + } + + $output .= '</ListIdentifiers>'; + $this->addOutputCode( $output ); + } + else + { + $this->_application->setError( 'noRecordsMatch' ); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/oaipmh/components/ListMetadataFormats.php b/src/core/classes/org/glizy/oaipmh/components/ListMetadataFormats.php new file mode 100755 index 0000000..f50f2d7 --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/components/ListMetadataFormats.php @@ -0,0 +1,35 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_oaipmh_components_ListMetadataFormats extends org_glizy_components_Component +{ + + /** + * Render + * + * @return void + * @access public + */ + function render($outputMode=NULL, $skipChilds=false) + { + $metadataFormat = $this->_application->getMetadataFormat(); + $output = '<ListMetadataFormats>'; + foreach( $metadataFormat as $v ) + { + $output .= '<metadataFormat>'; + $output .= '<metadataPrefix>'.org_glizy_oaipmh_OaiPmh::encode($v[ 'prefix' ] ).'</metadataPrefix>'; + $output .= '<schema>'.org_glizy_oaipmh_OaiPmh::encode($v[ 'schema' ] ).'</schema>'; + $output .= '<metadataNamespace>'.org_glizy_oaipmh_OaiPmh::encode($v[ 'namespace' ] ).'</metadataNamespace>'; + $output .= '</metadataFormat>'; + } + $output .= '</ListMetadataFormats>'; + $this->addOutputCode( $output ); + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/oaipmh/components/ListRecords.php b/src/core/classes/org/glizy/oaipmh/components/ListRecords.php new file mode 100755 index 0000000..3eb79cd --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/components/ListRecords.php @@ -0,0 +1,187 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_oaipmh_components_ListRecords extends org_glizy_components_Component +{ + /** + * Render + * + * @return void + * @access public + */ + function render($outputMode=NULL, $skipChilds=false) + { + $from = ''; + $until = ''; + $set = ''; + $limitStart = 0; + + + if ( __Request::exists( 'resumptionToken' ) ) + { + if ( !__Request::exists( 'from' ) && !__Request::exists( 'until' ) && !__Request::exists( 'set' ) && !__Request::exists( 'metadataPrefix' ) ) + { + // TODO controllare la data di scadenza del token + $tokenId = __Request::get( 'resumptionToken' ); + $fileName = __Paths::get( 'CACHE' ).$tokenId; + if ( file_exists( $fileName ) ) + { + $info = unserialize( file_get_contents( $fileName ) ); + $limitStart = $info[ 'limitEnd' ]; + $filters = $info[ 'filters' ]; + $metadataPrefix = $info[ 'metadataPrefix' ]; + } + else + { + $this->_application->setError( 'badResumptionToken', '', $tokenId ); + return; + } + } + else + { + $this->_application->setError( 'exclusiveArgument' ); + return; + } + } + else + { + // controlla i parametri ricevuti + if ( __Request::exists( 'from' ) ) + { + $from = __Request::get( 'from' ); + if ( !org_glizy_oaipmh_OaiPmh::checkDateFormat($from) ) + { + $this->_application->setError( 'badGranularity', 'from', $from); + return; + } + } + + if ( __Request::exists( 'until' ) ) + { + $until = __Request::get( 'until' ); + if (!org_glizy_oaipmh_OaiPmh::checkDateFormat($until)) + { + $this->_application->setError( 'badGranularity', 'until', $until); + return; + } + } + + if ( __Request::exists( 'set' ) ) + { + $set = __Request::get( 'set' ); + } + + if ( __Request::exists( 'metadataPrefix' ) ) + { + $metadataPrefix = __Request::get( 'metadataPrefix' ); + + } + else + { + $this->_application->setError( 'missingArgument', 'metadataPrefix' ); + return; + } + + $filters = array(); + if ( $from ) + { + $filters[] = 'picoqueue_date >= '.org_glizy_dataAccess_DataAccess::qstr( $from ); + } + if ( $until ) + { + $filters[] = 'picoqueue_date <= '.org_glizy_dataAccess_DataAccess::qstr( $until ); + } + if ( $set ) + { + $filters[] = 'picoqueue_recordModule = '.org_glizy_dataAccess_DataAccess::qstr( $set ); + } + } + + + $metadata = $this->_application->getMetadataFormat(); + if ( isset( $metadata[$metadataPrefix] ) ) + { + // TODO + //$inc_record = $metadata[$metadataPrefix]['myhandler']; + } + else + { + $this->_application->setError( 'cannotDisseminateFormat', 'metadataPrefix', $metadataPrefix ); + return; + } + + $limitLength = __Config::get( 'oaipmh.maxRecords' ); + $it = org_glizy_ObjectFactory::createModelIterator( 'org.glizy.oaipmh.models.PicoQueue', 'all', array( + 'filters' => $filters, + 'limit' => array( $limitStart, $limitLength ), + 'numRows' => true + ) ); + $num_rows = $it->count(); + if ( $num_rows > 0 ) + { + $oaiPrefix = __Config::get( 'oaipmh.oaiPrefix' ); + $countrec = 0; + + $output = '<ListRecords>'; + $output .= org_glizy_oaipmh_OaiPmh::createResumptionToken( 'ListRecords', + array( + 'numRows' => $num_rows, + 'limitStart' => $limitStart, + 'limitEnd' => $limitStart + $limitLength, + 'filters' => $filters, + 'metadataPrefix' => $metadataPrefix, + ) ); + + while ($it->hasMore()) + { + $countrec++; + $arC = $it->current(); + $it->next(); + + $setClass = org_glizy_ObjectFactory::createObject( $arC->picoqueue_recordModule, $this->_application ); + if ( is_null( $setClass ) ) continue; + + $setClass->loadRecord( $arC->picoqueue_recordId ); + $identifier = $oaiPrefix.$arC->picoqueue_identifier; + $datestamp = org_glizy_oaipmh_OaiPmh::formatDatestamp( $arC->picoqueue_date ); + $status_deleted = $arC->picoqueue_action == 'delete' ? true : false; + + $output .= '<record>'; + $output .= '<header'; + if ($status_deleted) + { + $output .= ' status="deleted"'; + } + $output .='>'; + + // use xmlrecord since we use stuff from database + $output .= '<identifier>'.org_glizy_oaipmh_OaiPmh::encode( $identifier ).'</identifier>'; + $output .= '<datestamp>'.org_glizy_oaipmh_OaiPmh::encode( $datestamp ).'</datestamp>'; + if (!$status_deleted) + { + $output .= '<setSpec>'.org_glizy_oaipmh_OaiPmh::encode( $arC->picoqueue_recordModule ).'</setSpec>'; + } + $output .= '</header>'; + $output .= '<metadata>'; + $output .= $setClass->getRecord($identifier); + $output .= '</metadata>'; + $output .= '</record>'; + } + + $output .= '</ListRecords>'; + + $this->addOutputCode( $output ); + } + else + { + $this->_application->setError( 'noRecordsMatch' ); + } + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/oaipmh/components/ListSets.php b/src/core/classes/org/glizy/oaipmh/components/ListSets.php new file mode 100755 index 0000000..9b3f646 --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/components/ListSets.php @@ -0,0 +1,55 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_oaipmh_components_ListSets extends org_glizy_components_Component +{ + /** + * Render + * + * @return void + * @access public + */ + function render($outputMode=NULL, $skipChilds=false) + { + $sets = $this->_application->getSets(); + + if ( !count( $sets ) ) + { + $this->_application->setError( 'noSetHierarchy' ); + } + else + { + $metadataFormat = $this->_application->getMetadataFormat(); + $output = '<ListSets>'; + foreach( $sets as $v ) + { + $setClass = org_glizy_ObjectFactory::createObject( $v ); + if ( $setClass ) + { + $info = $setClass->getSetInfo(); + $output .= '<set>'; + $output .= '<setSpec>'.org_glizy_oaipmh_OaiPmh::encode($info[ 'setSpec' ] ).'</setSpec>'; + $output .= '<setName>'.org_glizy_oaipmh_OaiPmh::encode($info[ 'setName' ] ).'</setName>'; + if ( !empty( $info[ 'setDescription' ] ) ) + { + $output .= '<setDescription>'; + $output .= org_glizy_oaipmh_OaiPmh::openMetadataHeader( $metadataFormat[ 'oai_dc' ] ); + $output .= '<dc:description>'.org_glizy_oaipmh_OaiPmh::encode($info[ 'setDescription' ] ).'</dc:description>'; + $output .= '<dc:creator>'.org_glizy_oaipmh_OaiPmh::encode($info[ 'setCreator' ] ).'</dc:creator>'; + $output .= org_glizy_oaipmh_OaiPmh::closeMetadataHeader( $metadataFormat[ 'oai_dc' ] ); + $output .= '</setDescription>'; + } + $output .= '</set>'; + } + } + $output .= '</ListSets>'; + $this->addOutputCode( $output ); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/oaipmh/components/Page.php b/src/core/classes/org/glizy/oaipmh/components/Page.php new file mode 100755 index 0000000..baf223a --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/components/Page.php @@ -0,0 +1,135 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_oaipmh_components_Page extends org_glizy_mvc_components_Page +{ + protected $actionClass; + + function process() + { + $this->action = __Request::get( $this->actionName, $this->getAttribute( 'defaultAction' ) ); + if ( empty( $this->action ) ) + { + $this->_application->setError( 'noVerb' ); + return; + } + + $found = false; + foreach ( $this->childComponents as $c ) + { + if ( is_a( $c, 'org_glizy_mvc_components_State' ) ) + { + $c->deferredChildCreation(); + if ( $c->isCurrentState() ) + { + $found = true; + break; + } + } + } + + if ( $found ) + { + $this->actionClass = &org_glizy_ObjectFactory::createObject( $this->controllerBasePath.$this->action, $this ); + if ( !is_object( $this->actionClass ) ) + { + $this->action = ucfirst( $this->action ); + $this->actionClass = &org_glizy_ObjectFactory::createObject( $this->controllerBasePath.$this->action, $this ); + } + + if ( is_object( $this->actionClass ) ) + { + if ( method_exists( $this->actionClass, "execute" ) ) + { + call_user_func( array( $this->actionClass, "execute" ), '' ); + } + } + + $this->action = strtolower( $this->action ); + + parent::process(); + + if ( is_object( $this->actionClass ) ) + { + if ( method_exists( $this->actionClass, 'executeLater' ) ) + { + call_user_func( array( $this->actionClass, 'executeLater' ), '' ); + } + } + } + else + { + $this->_application->setError( 'badVerb', $this->action ); + } + + + } + + function process_ajax() + { + return false; + } + + /** + * Render + * + * @return string + * @access public + */ + function render() + { + $this->renderChilds(); + + $responseDate = gmstrftime('%Y-%m-%dT%T').'Z'; + $error = $this->_application->getError(); + $requestAttribs = ''; + $content = ''; + + if ( empty( $error ) ) + { + + for ($i=0; $i<count($this->_output); $i++) + { + if ( $this->_output[$i]['editableRegion'] != 'content' ) continue; + $content .= $this->_output[$i]['code']; + } + + $params = &org_glizy_Request::_getValuesArray(); + unset($params['__url__']); + unset($params['__back__url__']); + foreach($params as $k=>$v) + { + if ( $v[ GLZ_REQUEST_TYPE ] == GLZ_REQUEST_GET ) + { + $requestAttribs .= ' '.$k.'="'.htmlentities( $v[GLZ_REQUEST_VALUE] ).'"'; + } + } + } + else + { + $content = $error; + } + $requestUrl = org_glizy_Routing::$baseUrl; + $charset = GLZ_CHARSET; + $output = <<<EOD +<?xml version="1.0" encoding="$charset"?> +<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ + http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd"> + <responseDate>$responseDate</responseDate> + <request $requestAttribs>$requestUrl</request> + $content +</OAI-PMH> +EOD; + + + return $output; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/oaipmh/core/AbstractMapping.php b/src/core/classes/org/glizy/oaipmh/core/AbstractMapping.php new file mode 100755 index 0000000..4ea10a3 --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/core/AbstractMapping.php @@ -0,0 +1,57 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_oaipmh_core_AbstractMapping extends GlizyObject +{ + protected $application; + protected $ar; + + function __construct( $application=NULL ) + { + $this->application = $application; + } + + public function getSetInfo() + { + $info = array(); + $info[ 'setSpec' ] = ''; + $info[ 'setName' ] = ''; + $info[ 'setDescription' ] = ''; + $info[ 'setCreator' ] = ''; + $info[ 'model' ] = ''; + return $info; + } + + function getModelName() + { + $info = $this->getSetInfo(); + return $info['model']; + } + + function loadRecord( $id ) + { + $this->ar = org_glizy_ObjectFactory::createModel( $this->getModelName() ); + $pk = $this->ar->getPrimarykey(); + $versionFieldName = $this->ar->getVersionFieldName(); + $languageFieldName = $this->ar->getLanguageFieldName(); + $this->ar->setFieldValue( $pk, $id ); + if ( !is_null( $versionFieldName ) ) $this->ar->setFieldValue( $versionFieldName, 'PUBLISHED' ); + if ( !is_null( $languageFieldName ) ) $this->ar->setFieldValue( $languageFieldName, $this->application->getLanguageId() ); + return $this->ar->find(); + } + + + function getRecord($identifier) + { + $output = '<record>'; + $output .= $this->getMetadata($identifier); + $output .= '</record>'; + return $output; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/oaipmh/core/Application.php b/src/core/classes/org/glizy/oaipmh/core/Application.php new file mode 100755 index 0000000..265ca00 --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/core/Application.php @@ -0,0 +1,137 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_oaipmh_core_Application extends org_glizy_mvc_core_Application +{ + private $error = ''; + private $metadataFormat = array(); + private $sets = array(); + + function _init() + { + parent::_init(); + $this->contentType = 'text/xml'; + __Paths::set( 'APPLICATION_PAGE_TYPE', __Paths::get( 'CORE_CLASSES' ).'org/glizy/oaipmh/pageTypes/' ); + $this->addMetadataFormat( 'oai_dc', 'http://www.openarchives.org/OAI/2.0/oai_dc.xsd', 'http://www.openarchives.org/OAI/2.0/oai_dc/', 'dc', 'http://purl.org/dc/elements/1.1/' ); + } + + function _readPageId() + { + __Request::set( 'pageId', 'Index' ); + parent::_readPageId(); + } + + function addMetadataFormat( $prefix, $schema, $namespace, $recordPrefix = '', $recordNamespace = '' ) + { + $this->metadataFormat[ $prefix ] = array( 'prefix' => $prefix, 'schema' => $schema, 'namespace' => $namespace, 'recordPrefix' => $recordPrefix, 'recordNamespace' => $recordNamespace ); + } + + function getMetadataFormat() + { + return $this->metadataFormat; + } + + function addSet( $classPath ) + { + // $this->sets[] = array( 'metadata' => $metadata, 'spec' => $spec, 'name' => $name, 'description' => $description, 'creator' => $creator ); + $this->sets[] = $classPath; + } + + function getSets() + { + return $this->sets; + } + + function getError() + { + return $this->error; + } + + function setError($code, $argument='', $value='') + { + switch ($code) { + case 'badArgument' : + $text = "The argument '$argument' (value='$value') included in the request is not valid."; + break; + + case 'badGranularity' : + $text = "The value '$value' of the argument '$argument' is not valid."; + // $code = 'badArgument'; + break; + + case 'badResumptionToken' : + $text = "The resumptionToken '$value' does not exist or has already expired."; + break; + + case 'badRequestMethod' : + $text = "The request method '$argument' is unknown."; + // $code = 'badVerb'; + break; + + case 'badVerb' : + $text = "The verb '$argument' provided in the request is illegal."; + break; + + case 'cannotDisseminateFormat' : + $text = "The metadata format '$value' given by $argument is not supported by this repository."; + break; + + case 'exclusiveArgument' : + $text = 'The usage of resumptionToken as an argument allows no other arguments.'; + // $code = 'badArgument'; + break; + + case 'idDoesNotExist' : + $text = "The value '$value' of the identifier is illegal for this repository."; + //if (!is_valid_url($value)) { + $code = 'badArgument'; + //} + break; + + case 'missingArgument' : + $text = "The required argument '$argument' is missing in the request."; + // $code = 'badArgument'; + break; + + case 'noRecordsMatch' : + $text = 'The combination of the given values results in an empty list.'; + break; + + case 'noMetadataFormats' : + $text = 'There are no metadata formats available for the specified item.'; + break; + + case 'noVerb' : + $text = 'The request does not provide any verb.'; + // $code = 'badVerb'; + break; + + case 'noSetHierarchy' : + $text = 'This repository does not support sets.'; + break; + + case 'sameArgument' : + $text = 'Do not use them same argument more than once.'; + // $code = 'badArgument'; + break; + + case 'sameVerb' : + $text = 'Do not use verb more than once.'; + // $code = 'badVerb'; + break; + + default: + $text = "Unknown error: code: '$code', argument: '$argument', value: '$value'"; + $code = 'badArgument'; + } + + $this->error = ' <error code="'.org_glizy_oaipmh_OaiPmh::encode( $code ).'">'.org_glizy_oaipmh_OaiPmh::encode( $text )."</error>"; + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/oaipmh/models/PicoQueue.xml b/src/core/classes/org/glizy/oaipmh/models/PicoQueue.xml new file mode 100755 index 0000000..6498b73 --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/models/PicoQueue.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="picoqueues_tbl" model:usePrefix="true"> +</model:Model> + diff --git a/src/core/classes/org/glizy/oaipmh/pageTypes/index.xml b/src/core/classes/org/glizy/oaipmh/pageTypes/index.xml new file mode 100755 index 0000000..d15cda0 --- /dev/null +++ b/src/core/classes/org/glizy/oaipmh/pageTypes/index.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<o:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:o="org.glizy.oaipmh.components.*" + baseClassPath="org.glizy.oaipmh" + controllerName="oaipmh" + defaultEditableRegion="content" + actionName="verb" + templateType="php" + templateFileName="oaipmh.php" + defaultAction=""> + + + <mvc:State name="Identify"> + <o:Identify /> + </mvc:State> + + <mvc:State name="ListMetadataFormats"> + <o:ListMetadataFormats /> + </mvc:State> + + <mvc:State name="ListSets"> + <o:ListSets /> + </mvc:State> + + <mvc:State name="ListIdentifiers"> + <o:ListIdentifiers /> + </mvc:State> + + <mvc:State name="ListRecords"> + <o:ListRecords /> + </mvc:State> + + <mvc:State name="GetRecord"> + <o:GetRecord /> + </mvc:State> +</o:Page> diff --git a/src/core/classes/org/glizy/parser/XML.php b/src/core/classes/org/glizy/parser/XML.php new file mode 100755 index 0000000..c0ace78 --- /dev/null +++ b/src/core/classes/org/glizy/parser/XML.php @@ -0,0 +1,88 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_parser_XML extends DOMDocument +{ + public $namespaces = array(); + private $defaultNamespaces = array ( 'xmlns:glz' => '"http://www.glizy.org/dtd/glz/1.0"', 'xmlns:model' => '"http://www.glizy.org/dtd/model/1.0"', 'xmlns:adm' => '"http://www.glizy.org/dtd/adm/1.0"' ); + + public function load( $file ) + { + $this->checkIfFileExits( $file ); + $this->preserveWhiteSpace = false; + $r = parent::load( $file, LIBXML_NOERROR ); + + return $r; + } + + + public function loadAndParseNS( $file ) + { + $this->checkIfFileExits( $file ); + $xmlString = file_get_contents( $file ); + return $this->loadXmlAndParseNS( $xmlString ); + } + + + public function loadXmlAndParseNS( $xmlString ) + { + // esegue il parsing del primo nodo per ricavare i namespace definiti + preg_match_all( '/<[^\?]*\s*[^>]*>/iU', $xmlString, $match ); + if ( count( $match[ 0 ] ) ) + { + foreach( $match[ 0 ] as $m ) + { + if ( strpos( $m, '<?' ) === false ) + { + // controlla se sono presenti i namespace di default + $rootNodeString = $m; + foreach( $this->defaultNamespaces as $ns => $uri ) + { + $rootNodeString = $this->addDefaultNS( $rootNodeString, $ns, $uri ); + } + $xmlString = str_replace( $m, $rootNodeString, $xmlString ); + + preg_match_all( '/xmlns:(.*)[\s\\n\\r]*=[\s\\n\\r]*["\'](.*)["\']/iU', $rootNodeString, $matchns ); + $numNS = count( $matchns[ 0 ] ); + if ( $numNS ) + { + for( $i = 0; $i < $numNS; $i++ ) + { + $this->namespaces[ $matchns[ 1 ][ $i ] ] = $matchns[ 2 ][ $i ]; + } + } + + break; + } + } + } + + $this->preserveWhiteSpace = false; + $r = $this->loadXML( $xmlString , LIBXML_NOERROR ); + return $r; + } + + private function addDefaultNS( $text, $ns, $uri ) + { + if ( stripos( $text, $ns ) === false ) + { + $text = preg_replace( '/(\s|>)/', ' '.$ns.'='.$uri.'$1', $text, 1 ); + } + return $text; + } + + + private function checkIfFileExits( $file ) + { + if ( !file_exists( $file ) ) + { + throw new Exception( 'File non esiste '.$file ); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/plugins/PluginClient.php b/src/core/classes/org/glizy/plugins/PluginClient.php new file mode 100755 index 0000000..2148b6f --- /dev/null +++ b/src/core/classes/org/glizy/plugins/PluginClient.php @@ -0,0 +1,17 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_plugins_PluginClient extends GlizyObject +{ + + function run($params) + { + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/plugins/PluginManager.php b/src/core/classes/org/glizy/plugins/PluginManager.php new file mode 100755 index 0000000..c00b57e --- /dev/null +++ b/src/core/classes/org/glizy/plugins/PluginManager.php @@ -0,0 +1,43 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_plugins_PluginManager extends GlizyObject +{ + function addPlugin($name, $class) + { + $name = str_replace('_', '.', strtolower($name)); + $pluginsInfo = &org_glizy_ObjectValues::get('org.glizy.plugins.PluginManager', 'pluginsInfo', array()); + if (!isset($pluginsInfo[$name])) + { + $pluginsInfo[$name] = array(); + } + $pluginsInfo[$name][] = $class; + } + + function getPluginChain($name) + { + $name = strtolower($name); + $pluginsInfo = &org_glizy_ObjectValues::get('org.glizy.plugins.PluginManager', 'pluginsInfo', array()); + if (!isset($pluginsInfo[$name])) + { + $pluginsInfo[$name] = array(); + } + return $pluginsInfo[$name]; + } + + static function processPluginChain($name, &$parent, $params) + { + $pluginsInfo = org_glizy_plugins_PluginManager::getPluginChain($name); + foreach ($pluginsInfo as $plugin) + { + $pluginObj = &org_glizy_ObjectFactory::createObject($plugin); + $pluginObj->run($parent, $params); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/plugins/PluginServer.php b/src/core/classes/org/glizy/plugins/PluginServer.php new file mode 100755 index 0000000..a83397a --- /dev/null +++ b/src/core/classes/org/glizy/plugins/PluginServer.php @@ -0,0 +1,40 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_plugins_PluginServer extends GlizyObject +{ + var $_output = array(); + + + function runClients($params) + { + $className = str_replace('_', '.', $this->getClassName()); + org_glizy_plugins_PluginManager::processPluginChain($className, $this, $params); + } + + function run($params) + { + } + + function getResultStructure() + { + $result = array(); + return $result; + } + + function addResult($result) + { + $this->_output[] = $result; + } + + function getResult() + { + return $this->_output; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/plugins/Search.php b/src/core/classes/org/glizy/plugins/Search.php new file mode 100755 index 0000000..dfaeeda --- /dev/null +++ b/src/core/classes/org/glizy/plugins/Search.php @@ -0,0 +1,35 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_plugins_Search extends org_glizy_plugins_PluginServer +{ + function run($params) + { + $this->runClients($params); + + return $this->getResult(); + } + + function addResult($result) + { + $result['__weight__'] = str_pad( $result['__weight__'], 6, "0", STR_PAD_LEFT ).$result['title']; + $this->_output[] = $result; + } + + function getResultStructure() + { + $result = array(); + $result['title'] = ''; + $result['date'] = ''; + $result['dateOrd'] = ''; + $result['description'] = ''; + $result['__url__'] = ''; + $result['__weight__'] = 0; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/redis/Client.php b/src/core/classes/org/glizy/redis/Client.php new file mode 100755 index 0000000..1d8c94f --- /dev/null +++ b/src/core/classes/org/glizy/redis/Client.php @@ -0,0 +1,28 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_redis_Client extends GlizyObject +{ + /** @var PredisPhpdoc\Client $predis */ + private static $predis; + + /** + * @return \Predis\Client|\PredisPhpdoc\Client + */ + public static function getConnection() + { + if (is_null(self::$predis)) { + $host = __Config::get('glizy.database.caching.redis'); + + self::$predis = new Predis\Client($host ? $host : 'tcp://127.0.0.1:6379'); + } + + return self::$predis; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/rest/core/Application.php b/src/core/classes/org/glizy/rest/core/Application.php new file mode 100755 index 0000000..5344912 --- /dev/null +++ b/src/core/classes/org/glizy/rest/core/Application.php @@ -0,0 +1,287 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_rest_core_Application + */ + +class org_glizy_rest_core_Application extends org_glizy_mvc_core_Application +{ + function run() + { + $this->log( "Run Rest application", GLZ_LOG_SYSTEM ); + if (file_exists(org_glizy_Paths::get('APPLICATION_STARTUP'))) + { + // if the startup folder is defined all files are included + glz_require_once_dir(org_glizy_Paths::get('APPLICATION_STARTUP')); + } + + glz_defineBaseHost(); + $this->_initRequest(); + + glz_require_once_dir(org_glizy_Paths::getRealPath('APPLICATION_CLASSES')); + + $this->_startProcess(); + + if (file_exists(org_glizy_Paths::get('APPLICATION_SHUTDOWN'))) + { + // if the shutdown folder is defined all files are included + glz_require_once_dir(org_glizy_Paths::get('APPLICATION_SHUTDOWN')); + } + } + + function _startProcess() + { + foreach( $this->proxyMap as $k=>$v ) + { + $v->onRegister(); + } + + $method = __Request::$method ? __Request::$method : 'get'; + $controller = __Request::get( 'controller', '' ); + $status = 200; + $directOutput = false; + $result = array(); + + if ( $method!='options' && $controller ) + { + $actionClass = org_glizy_ObjectFactory::createObject( $controller, $this ); + + if ( is_object( $actionClass ) ) + { + $reflectionClass = new ReflectionClass( $actionClass ); + $callMethod = ''; + if ( $reflectionClass->hasMethod( "execute_".$method ) ) + { + $callMethod = "execute_".$method; + } + else if ( $reflectionClass->hasMethod( "execute" ) ) + { + $callMethod = "execute"; + } + + if ( $callMethod ) + { + $reflectionMethod = $reflectionClass->getMethod( $callMethod ); + $methodParams = $reflectionMethod->getParameters(); + $params = array(); + foreach( $methodParams as $v ) + { + $params[] = __Request::get( $v->name ); + } + $result = call_user_func_array( array( $actionClass, "execute" ), $params ); + $directOutput = $actionClass->directOutput; + + if (is_array($result)) { + if (isset($result['http-status'])) { + $status = $result['http-status']; + unset($result['http-status']); + } else if (isset($result['httpStatus'])) { + $status = $result['httpStatus']; + unset($result['httpStatus']); + } + $keys = array_keys($result); + if (count($result)==1 && $keys[0]===0) { + $result = $result[0]; + } + } else if (is_object($result)) { + if (property_exists($result, 'httpStatus')) { + $status = $result->httpStatus; + unset($result->httpStatus); + } + } + } + else + { + $status = 501; + } + } + else + { + $status = 404; + } + } + else if ( $method=='options') + { + $status = 200; + } + else + { + $status = 404; + } + + if ( $result === false ) + { + $status = 500; + } + + if ($status === 404) { + $report = array(); + $report['Request'] = __Request::getAllAsArray(); + $report['_SERVER'] = $_SERVER; + $this->log( $report, GLZ_LOG_SYSTEM, 'glizy.404' ); + } + $httpAccept = (strpos(@$_SERVER['HTTP_ACCEPT'], 'xml')!==false) ? 'xml' : 'json'; + + // sent response + header('Cache-Control: no-cache'); + header('Pragma: no-cache'); + header('Expires: -1'); + header( $_SERVER['SERVER_PROTOCOL'].' '.$status.' '.$this->getStatusCodeMessage( $status ) ); + + if ( $result ) + { + if ( $httpAccept == 'json' ) + { + header("Content-Type: application/json; charset=utf-8"); + if (!$directOutput) { + // @ serve per evitare waring di conversione nel caso ci siano caratteri non utf8 + echo @json_encode( $result ); + } else { + echo $result; + } + } + else + { + header("Content-Type: text/xml; charset=".GLZ_CHARSET); + if ( !is_array( $result ) || !isset( $result['result'] ) ) + { + $result = array( 'result' => $result ); + } + echo $this->createXml( $result ); + } + } + } + + private function createXml( $data ) + { + $xml = new XmlWriter(); + $xml->openMemory(); + $xml->startDocument('1.0', GLZ_CHARSET); + $this->createXmlNode($xml, $data); + return $xml->outputMemory(true); + } + + private function createXmlNode( XMLWriter $xml, $data ) + { + foreach($data as $key => $value){ + if ( $key == "_className" || is_null( $value ) ) continue; + + + if( is_string( $key) && is_object( $value ) ) + { + $xml->startElement($key); + $this->createXmlNode($xml, $value ); + $xml->endElement(); + } + else if( is_string( $key) && is_array($value) ) + { + $arrayKeys = array_keys( $value ); + $wrapTag = preg_replace( '/ies$/i', 'y', $key ); + $wrapTag = rtrim( $wrapTag, 's' ); + foreach( $arrayKeys as $k ) + { + if ( is_string( $k ) ) + { + $wrapTag = ''; + break; + } + } + $xml->startElement($key); + if ( !empty( $wrapTag ) ) + { + foreach( $value as $v ) + { + $xml->startElement( $wrapTag ); + $this->createXmlNode($xml, $v); + $xml->endElement(); + } + } + else + { + $this->createXmlNode($xml, $value ); + } + $xml->endElement(); + } + else if( is_array($value) ) + { + $this->createXmlNode($xml, $value); + } + else + { + if (strtolower(GLZ_CHARSET) != 'utf-8') { + $value = utf8_encode($value); + } + $xml->writeElement($key, $value); + } + + } + } + + private function getStatusCodeMessage($status) + { + $codes = array( + 200 => 'OK', + 201 => 'Created', + 202 => 'Accepted', + 203 => 'Non-Authoritative Information', + 204 => 'No Content', + 205 => 'Reset Content', + 206 => 'Partial Content', + 300 => 'Multiple Choices', + 301 => 'Moved Permanently', + 302 => 'Found', + 303 => 'See Other', + 304 => 'Not Modified', + 305 => 'Use Proxy', + 306 => '(Unused)', + 307 => 'Temporary Redirect', + 400 => 'Bad Request', + 401 => 'Unauthorized', + 402 => 'Payment Required', + 403 => 'Forbidden', + 404 => 'Not Found', + 405 => 'Method Not Allowed', + 406 => 'Not Acceptable', + 407 => 'Proxy Authentication Required', + 408 => 'Request Timeout', + 409 => 'Conflict', + 410 => 'Gone', + 411 => 'Length Required', + 412 => 'Precondition Failed', + 413 => 'Request Entity Too Large', + 414 => 'Request-URI Too Long', + 415 => 'Unsupported Media Type', + 416 => 'Requested Range Not Satisfiable', + 417 => 'Expectation Failed', + 500 => 'Internal Server Error', + 501 => 'Not Implemented', + 502 => 'Bad Gateway', + 503 => 'Service Unavailable', + 504 => 'Gateway Timeout', + 505 => 'HTTP Version Not Supported' + ); + + return (isset($codes[$status])) ? $codes[$status] : ''; + } + + function executeCommand( $command ) + { + $actionClass = &org_glizy_ObjectFactory::createObject( $command, $this ); + if ( is_object( $actionClass ) ) + { + if ( method_exists( $actionClass, "execute" ) ) + { + $params = func_get_args(); + array_shift($params); + return call_user_func_array( array( $actionClass, "execute" ), $params ); + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/rest/core/CommandRest.php b/src/core/classes/org/glizy/rest/core/CommandRest.php new file mode 100755 index 0000000..d2998cd --- /dev/null +++ b/src/core/classes/org/glizy/rest/core/CommandRest.php @@ -0,0 +1,37 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Class org_glizy_rest_core_CommandRest + */ +class org_glizy_rest_core_CommandRest extends GlizyObject +{ + /** @var org_glizy_rest_core_Application $application */ + protected $application = NULL; + protected $user = NULL; + public $directOutput = false; + + /** + * @param org_glizy_rest_core_Application $application + */ + function __construct( $application=NULL ) + { + $this->application = $application; + $this->user = &$this->application->getCurrentUser(); + } + + /** + * @param null $oldAction + * + * @return bool + */ + function execute($oldAction = null) { + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/rest/core/RestRequest.php b/src/core/classes/org/glizy/rest/core/RestRequest.php new file mode 100755 index 0000000..fc69ccd --- /dev/null +++ b/src/core/classes/org/glizy/rest/core/RestRequest.php @@ -0,0 +1,485 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Code By https://github.com/ptisp/PHP-API-Client + */ + +/** + * Class org_glizy_rest_core_RestRequest + */ + +class org_glizy_rest_core_RestRequest extends GlizyObject +{ + protected $url; + protected $verb; + protected $requestBody; + protected $requestLength; + protected $username; + protected $password; + protected $acceptType; + protected $responseBody; + protected $responseInfo; + protected $responseError; + protected $authType; + protected $disableSslCheck = false; + protected $contentType; + protected $cookies; + protected $proxy; + protected $proxyPort; + protected $timeout; + + /** + * @param null $url + * @param string $verb + * @param null $requestBody + * @param null $contentType + */ + public function __construct ($url = null, $verb = 'GET', $requestBody = null, $contentType = null) + { + $this->url = $url; + $this->verb = $verb; + $this->requestBody = $requestBody; + $this->requestLength = 0; + $this->username = null; + $this->password = null; + $this->acceptType = 'application/json'; + $this->responseBody = null; + $this->responseInfo = null; + $this->authType = CURLAUTH_BASIC; + $this->contentType = $contentType; + $this->cookies = null; + $this->proxy = null; + $this->proxyPort = null; + + if ($this->requestBody !== null && !is_string($this->requestBody)) + { + $this->buildPostBody(); + } + } + + public function flush () + { + $this->requestBody = null; + $this->requestLength = 0; + $this->verb = 'GET'; + $this->responseBody = null; + $this->responseInfo = null; + } + + /** + * @return bool + * @throws Exception + */ + public function execute () + { + $ch = curl_init(); + $this->setAuth($ch); + + try + { + switch (strtoupper($this->verb)) + { + case 'GET': + $result = $this->executeGet($ch); + break; + case 'POST': + $result = $this->executePost($ch); + break; + case 'PUT': + $result = $this->executePut($ch); + break; + case 'DELETE': + $result = $this->executeDelete($ch); + break; + default: + throw new InvalidArgumentException('Current verb (' . $this->verb . ') is an invalid REST verb.'); + } + + return $result; + } + catch (InvalidArgumentException $e) + { + curl_close($ch); + throw $e; + } + catch (Exception $e) + { + curl_close($ch); + throw $e; + } + + } + + /** + * @param null $data + */ + public function buildPostBody ($data = null) + { + if ($this->contentType == 'multipart/form-data') return; + $data = ($data !== null) ? $data : $this->requestBody; + + if (!is_array($data)) + { + throw new InvalidArgumentException('Invalid data input for postBody. Array expected'); + } + + $data = http_build_query($data, '', '&'); + $this->requestBody = $data; + } + + /** + * @param $ch + * + * @return bool + */ + protected function executeGet ($ch) + { + if (!is_string($this->requestBody) && !is_null($this->requestBody)) + { + $this->buildPostBody(); + } + + $this->url .= ( strpos( '?', $this->url ) === false ? '?' : '&' ).$this->requestBody; + return $this->doExecute($ch); + } + + /** + * @param $ch + * + * @return bool + */ + protected function executePost ($ch) + { + if (!is_string($this->requestBody) && !is_null($this->requestBody)) + { + $this->buildPostBody(); + } + + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $this->requestBody); + + return $this->doExecute($ch); + } + + /** + * @param $ch + * + * @return bool + */ + protected function executePut ($ch) + { + if (!is_string($this->requestBody) && !is_null($this->requestBody)) + { + $this->buildPostBody(); + } + + $this->requestLength = strlen($this->requestBody); + + $fh = fopen('php://memory', 'rw'); + fwrite($fh, $this->requestBody); + rewind($fh); + + curl_setopt($ch, CURLOPT_INFILE, $fh); + curl_setopt($ch, CURLOPT_INFILESIZE, $this->requestLength); + curl_setopt($ch, CURLOPT_PUT, true); + + $result = $this->doExecute($ch); + + fclose($fh); + + return $result; + } + + /** + * @param $ch + * + * @return bool + */ + protected function executeDelete ($ch) + { + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); + + return $this->doExecute($ch); + } + + /** + * @param $curlHandle + * + * @return bool + */ + protected function doExecute (&$curlHandle) + { + $this->setCurlOpts($curlHandle); + + if ($result = curl_exec($curlHandle)) { + $this->responseBody = $result; + $this->responseInfo = curl_getinfo($curlHandle); + $result = true; + } else { + $this->responseError = curl_error($curlHandle); + $result = false; + } + + curl_close($curlHandle); + return $result; + } + + /** + * @param $ch + * @param string $headerLine + * + * @return int + */ + function curlResponseHeaderCallback($ch, $headerLine) + { + if (preg_match('/^Set-Cookie:\s*([^;]*)/mi', $headerLine, $cookie) == 1) { + $this->cookies[] = $cookie[1]; + } + return strlen($headerLine); // Needed by curl + } + + /** + * @param $curlHandle + */ + protected function setCurlOpts (&$curlHandle) + { + if (!empty($this->cookies)) { + curl_setopt($curlHandle, CURLOPT_COOKIE, implode('; ', $this->cookies)); + $this->cookies = array(); + } + curl_setopt($curlHandle, CURLOPT_TIMEOUT, $this->timeout ? $this->timeout : 10); + curl_setopt($curlHandle, CURLOPT_URL, $this->url); + curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curlHandle, CURLOPT_HEADERFUNCTION, array($this, 'curlResponseHeaderCallback')); + + $header = array('Accept: ' . $this->acceptType); + + if ($this->contentType) { + $header[] = 'Content-Type: ' . $this->contentType; + } + + curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $header); + + if ($this->proxy && $this->proxyPort) + { + curl_setopt($curlHandle, CURLOPT_PROXY, $this->proxy); + curl_setopt($curlHandle, CURLOPT_PROXYPORT, $this->proxyPort); + } + + if ( $this->disableSslCheck ) + { + curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, false); + } + } + + /** + * @param $curlHandle + */ + protected function setAuth (&$curlHandle) + { + if ($this->username !== null && $this->password !== null) + { + curl_setopt($curlHandle, CURLOPT_HTTPAUTH, $this->authType ); + curl_setopt($curlHandle, CURLOPT_USERPWD, $this->username . ':' . $this->password); + } + } + + /** + * @return string + */ + public function getAcceptType () + { + return $this->acceptType; + } + + /** + * @param $acceptType + */ + public function setAcceptType ($acceptType) + { + $this->acceptType = $acceptType; + } + + /** + * @return null + */ + public function getPassword () + { + return $this->password; + } + + /** + * @param $password + */ + public function setPassword ($password) + { + $this->password = $password; + } + + /** + * @return null + */ + public function getResponseBody () + { + return $this->responseBody; + } + + /** + * @return null + */ + public function getResponseInfo () + { + return $this->responseInfo; + } + + /** + * @return mixed + */ + public function getResponseError () + { + return $this->responseError; + } + + /** + * @return null + */ + public function getUrl () + { + return $this->url; + } + + /** + * @param $url + */ + public function setUrl ($url) + { + $this->url = $url; + } + + /** + * @return null + */ + public function getUsername () + { + return $this->username; + } + + /** + * @param $username + */ + public function setUsername ($username) + { + $this->username = $username; + } + + /** + * @return string + */ + public function getVerb () + { + return $this->verb; + } + + /** + * @param $verb + */ + public function setVerb ($verb) + { + $this->verb = $verb; + } + + /** + * @return string + */ + public function getCookies() + { + return $this->cookies; + } + + /** + * @param string $cookies + */ + public function setCookies($cookies) + { + $this->cookies = $cookies; + } + + /** + * @return int + */ + public function getAuthType () + { + return $this->authType; + } + + /** + * @param $authType + */ + public function setAuthType ($authType) + { + $this->authType = $authType; + } + + /** + * @param bool $state + */ + public function disableSslCheck ($state = true) + { + $this->disableSslCheck = $state; + } + + /** + * @return int + */ + public function getProxyPort() + { + return $this->proxyPort; + } + + /** + * @param $proxyPort + */ + public function setProxyPort($proxyPort) + { + $this->proxyPort = $proxyPort; + } + + /** + * @return string + */ + public function getProxy() + { + return $this->proxy; + } + + /** + * @param $proxy + */ + public function setProxy($proxy) + { + $this->proxy = $proxy; + } + + /** + * @param $value + * + * @return bool + */ + public function setTimeout ($value) + { + if ($value) { + $this->timeout = $value; + return true; + } + else { + return false; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/rest/core/RestRequestMultipart.php b/src/core/classes/org/glizy/rest/core/RestRequestMultipart.php new file mode 100755 index 0000000..63c1de6 --- /dev/null +++ b/src/core/classes/org/glizy/rest/core/RestRequestMultipart.php @@ -0,0 +1,116 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +/** + * Code By https://github.com/ptisp/PHP-API-Client + */ + +/** + * Class org_glizy_rest_core_RestRequestMultipart + * + * Estensione di RestRequest specifica per le richieste di tipo multipart/form-data + * + * Prende come parametro $postfields una lista di chiave->valore, dove valore può anche essere un'array + * + * Esempio: + * $postfields = array( + * 'myobject[attachments][][resource]' => array('@/path/to/file1.txt','@/path/to/file2.txt') + * 'myobject[anotherproperty] => 'a_value' + * ); + * + */ +class org_glizy_rest_core_RestRequestMultipart extends org_glizy_rest_core_RestRequest +{ + + public function __construct ($url = null, $verb = 'POST', $postfields = null, $fileNameMap = null) + { + $convertedRequest = $this->convertPostFieldsToString($postfields, $fileNameMap); + + parent::__construct( + $url, + $verb, + $convertedRequest["content"], + 'multipart/form-data; boundary=' . $convertedRequest['boundary'] + ); + } + + public function buildPostBody ($data = null) + { + return; + } + + /** + * Converte la lista di chavi->valori in una stringa rapprensentante il corpo richiesta in multipart/form-data + * + * Codice originario: + * - source: https://gist.github.com/simensen/288242 + * - usage: https://gist.github.com/simensen/288240 + */ + protected function convertPostFieldsToString ($postfields, $fileNameMap=null) { + $algos = hash_algos(); + $hashAlgo = null; + foreach ( array('sha1', 'md5') as $preferred ) { + if ( in_array($preferred, $algos) ) { + $hashAlgo = $preferred; + break; + } + } + if ( $hashAlgo === null ) { list($hashAlgo) = $algos; } + $boundary = + '----------------------------' . + substr(hash($hashAlgo, 'cURL-php-multiple-value-same-key-support' . microtime()), 0, 12); + + $body = array(); + $crlf = "\r\n"; + $fields = array(); + foreach ( $postfields as $key => $value ) { + if ( is_array($value) ) { + foreach ( $value as $v ) { + $fields[] = array($key, $v); + } + } else { + $fields[] = array($key, $value); + } + } + foreach ( $fields as $field ) { + list($key, $value) = $field; + if ( strpos($value, '@') === 0 ) { + preg_match('/^@(.*?)$/', $value, $matches); + list($dummy, $filename) = $matches; + $body[] = '--' . $boundary; + if ( isset($fileNameMap[$filename]) && $fileNameMap[$filename] !== null ) + { + $computedName = $fileNameMap[$filename]; + } else + { + $computedName = basename($filename); + } + $body[] = 'Content-Disposition: form-data; name="' . $key . '"; filename="' . $computedName . '"'; + $body[] = 'Content-Type: application/octet-stream'; + $body[] = ''; + $body[] = file_get_contents($filename); + } else { + $body[] = '--' . $boundary; + $body[] = 'Content-Disposition: form-data; name="' . $key . '"'; + $body[] = ''; + $body[] = $value; + } + } + $body[] = '--' . $boundary . '--'; + $body[] = ''; + $content = join($crlf, $body); + + return array( + "content" => $content, + "boundary" => $boundary + ); + + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/sessionStore/Redis.php b/src/core/classes/org/glizy/sessionStore/Redis.php new file mode 100755 index 0000000..b37a6b8 --- /dev/null +++ b/src/core/classes/org/glizy/sessionStore/Redis.php @@ -0,0 +1,39 @@ +<?php +class org_glizy_sessionStore_Redis implements SessionHandlerInterface +{ + protected $lifetime; + protected $redis; + protected $prefix; + + public function __construct($lifetime, $prefix) { + $this->redis = org_glizy_redis_Client::getConnection(); + $this->lifetime = (int)$lifetime; + $this->prefix = $prefix.':'; + } + + public function open($savePath, $sessionName) { + } + + public function close() { + $this->redis = null; + unset($this->redis); + } + + public function read($id) { + $sessData = $this->redis->get($this->prefix.$id); + $this->redis->expire($this->prefix.$id, $this->lifetime); + return $sessData; + } + + public function write($id, $data) { + $this->redis->set($this->prefix.$id, $data); + $this->redis->expire($this->prefix.$id, $this->lifetime); + } + + public function destroy($id) { + $this->redis->del($this->prefix.$id); + } + + public function gc($maxLifetime) { + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/template/layoutManager/DWT.php b/src/core/classes/org/glizy/template/layoutManager/DWT.php new file mode 100755 index 0000000..c79b54e --- /dev/null +++ b/src/core/classes/org/glizy/template/layoutManager/DWT.php @@ -0,0 +1,48 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_template_layoutManager_DWT extends org_glizy_template_layoutManager_LayoutManager +{ + var $pathPrefix = 'Templates/'; + + function apply(&$regionContent) + { + $this->checkRequiredValues( $regionContent ); + $templateSource = @implode('', file($this->fileName)); + $templateSource = $this->fixUrl( $templateSource ); + + foreach ($regionContent as $region => $content) + { + if ($content == '') + { + $templateSource = preg_replace("/(<!--[\s]+TemplateBeginIf[\s]+cond\=\"".$region."[^\>]+-->)[\s]*(\s.*)+?[\s]*(<!--[\s]+TemplateEndIf[\s]+-->)/i", "", $templateSource); + } + + preg_match("/(<!--\s*TemplateBeginEditable\s*name=\"".$region."\"[^>]*?>)(.*?)(<!--[^>]*?>)/si", $templateSource, $matches, PREG_OFFSET_CAPTURE); + if (count($matches)) + { + $templateSource = preg_replace("/(<!--\s*TemplateBeginEditable\s*name=\"".$region."\"[^>]*?>)(.*?)(<!--[^>]*?>)/si", "$1 ".$content." $3",$templateSource); + } + else + { + $templateSource = preg_replace("/(<!--\s*InstanceBeginEditable\s*name=\"".$region."\"[^>]*?>)(.*?)(<!--[^>]*?>)/si", "$1 ".$content." $3",$templateSource); + } + } + + $templateSource = preg_replace("/(^|[^(\/\/\s)])<!\[CDATA\[/mi", "$1",$templateSource); + $templateSource = preg_replace("/(^|[^(\/\/\s)])\]\]>/mi", "$1",$templateSource); + + if (isset($regionContent['__body__'])) + { + $templateSource = $this->modifyBodyTag($regionContent['__body__'], $templateSource); + } + $templateSource = $this->fixLanguages( $templateSource ); + return $templateSource; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/template/layoutManager/LayoutManager.php b/src/core/classes/org/glizy/template/layoutManager/LayoutManager.php new file mode 100755 index 0000000..b274127 --- /dev/null +++ b/src/core/classes/org/glizy/template/layoutManager/LayoutManager.php @@ -0,0 +1,80 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_template_layoutManager_LayoutManager extends GlizyObject +{ + var $fileName; + var $rootPath; + var $pathPrefix = ''; + var $language = ''; + var $currentMenu = ''; + + function __construct($fileName='', $rootPath='') + { + $this->fileName = org_glizy_Paths::getRealPath('APPLICATION_TEMPLATE', $this->pathPrefix.$fileName); + $this->rootPath = org_glizy_Paths::get('APPLICATION_TEMPLATE'); + + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $this->currentMenu = $application->getCurrentMenu(); + $this->language = $application->getLanguage(); + + if ( !file_exists( $this->fileName ) ) + { + org_glizy_Exception::show( 500, "Template non trovato: ".$this->rootPath.$this->pathPrefix.$fileName, "", ""); + exit; + } + } + + function apply($pageXmlOutput, $title, $subtitle) + { + return $pageXmlOutput; + } + + function modifyBodyTag($value, $templateSource) + { + return str_replace('<body', '<body '.$value, $templateSource); + } + + function checkRequiredValues( &$regionContent ) + { + if (!isset($regionContent['doctitle'])) + { + $regionContent['doctitle'] = $this->currentMenu->title.' - '.__Config::get('APP_NAME'); + } + } + + + function fixUrl( $templateSource ) + { + $templateSource = preg_replace("/<(.*?)(href|src|background)\s*=\s*(\'|\")(?!((http|https|ftp|mailto|javascript):|<\?php|\/\/))(.*?)(\'|\")(.*?)>/si", "<$1$2=$3".$this->rootPath.$this->pathPrefix."$6$7$8>", $templateSource); + + $templateSource = preg_replace("/(url\s*?\([\'\"]*)(?!((http|https):))(.*?)([\'\"]*\))/i", "$1".$this->rootPath."$4$5", $templateSource); + + return $templateSource; + } + + function fixLanguages( $templateSource ) + { + $templateSource = str_replace( '<head>', '<head><base href="'.GLZ_HOST.'/" />', $templateSource ); + $templateSource = preg_replace('/(\<html.*xml:lang=)"([^"]*)"/', '$1"'.$this->language.'"', $templateSource ); + $templateSource = preg_replace('/(\<html.*lang=)"([^"]*)"/', '$1"'.$this->language.'"', $templateSource ); + + if ( org_glizy_Config::get('SEF_URL') === 'full' ) + { + // non è il massimo ma la regexp su testi lunghi crasha + $templateSource = str_replace( array( 'href="#', 'href=\'#', 'href="noTranslate:' ), array( 'href="'.__Routing::scriptUrl().'#', 'href=\''.__Routing::scriptUrl().'#', 'href="'), $templateSource ); + //$newtemplateSource = preg_replace("/<(.*?)(href)\s*=\s*(\'|\")(\#.*)(\'|\")(.*?)>/si", "<$1$2=$3".__Routing::scriptUrl()."$4$5$6>", $templateSource); + // if ( !empty( $newtemplateSource ) ) + // { + // $templateSource = &$newtemplateSource; + // } + } + return $templateSource; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/template/layoutManager/PDF.php b/src/core/classes/org/glizy/template/layoutManager/PDF.php new file mode 100755 index 0000000..04e8855 --- /dev/null +++ b/src/core/classes/org/glizy/template/layoutManager/PDF.php @@ -0,0 +1,249 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +define ('K_PATH_CACHE', org_glizy_Paths::getRealPath( 'CACHE' ) ); +define ('K_PATH_URL_CACHE', org_glizy_Paths::getRealPath( 'CACHE' ) ); +define ('K_PATH_IMAGES', org_glizy_Paths::getRealPath( 'APPLICATION_TEMPLATE' ) ); + + +glz_importApplicationLib('tcpdf/tcpdf.php'); +glz_importApplicationLib('tcpdf/config/lang/eng.php'); + +class org_glizy_template_layoutManager_PDF extends org_glizy_template_layoutManager_PHP +{ + private $pageUrl; + private $pageTitle; + function __construct($fileName='', $rootPath='') + { + parent::__construct( 'pdf.php', $rootPath ); + + $this->pageUrl = GLZ_HOST."/index.php?".__Request::get( '__url__' ); + $this->pageUrl = str_replace( '&printPdf=1', '', $this->pageUrl ); + $this->pageTitle = $this->currentMenu->title; + } + + function apply(&$regionContent) + { + $templateSource = parent::apply( $regionContent ); + $xml = new SimpleXMLElement( utf8_encode( $templateSource ) ); + + // TCPDF stuff: + // create new PDF document + $pdf = new GlizyPDF( (string)$xml['orientation'] == 'portrait' ? 'P' : 'L' , PDF_UNIT, (string)$xml['size'], true, 'UTF-8', false); + // set document information + $pdf->SetCreator( PDF_CREATOR ); + $pdf->SetAuthor( __Config::get( 'APP_NAME' ) ); + $pdf->SetTitle( $this->currentMenu->title ); + $pdf->SetSubject( '' ); + $pdf->SetFooterText( $this->replacePlaceHolders( $xml->footer ) ); + + // set default header data + $logo = $xml->header['logo']; + $logoUrl = ''.$logo; + $logoWidth = 0; + + if ( file_exists( $logoUrl ) ) + { + $logo = str_replace( org_glizy_Paths::get( 'APPLICATION_TEMPLATE' ), '', $logo ); + if ( strpos( $logo, 'application/mediaArchive' ) !== false ) + { + $logo = '../../../../'.$logo; + } + $imageSize = getImageSize( $logoUrl ); + $logoWidth = $imageSize[0] * ( (float)$xml['logoScale'] / 5 ); + } + else + { + $logo = ''; + } + $pdf->SetHeaderData( $logo, $logoWidth, '', '' ); + + + // set header and footer fonts + $pdf->setHeaderFont(Array( (string)$xml->header[ 'font' ], '', (int)$xml->header[ 'fontSize' ] )); + $pdf->setFooterFont(Array( (string)$xml->footer[ 'font' ], '', (int)$xml->footer[ 'fontSize' ] )); + + // set default monospaced font + $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); + + //set margins + $margin = explode( ',', $xml[ 'margin' ] ); + $marginHeaderFooter = explode( ',', $xml[ 'marginHeaderFooter' ] ); + $pdf->SetMargins( $margin[3], $margin[0], $margin[1]); + $pdf->SetHeaderMargin( $marginHeaderFooter[0] ); + $pdf->SetFooterMargin( $marginHeaderFooter[1]); + + //set auto page breaks + $pdf->SetAutoPageBreak(TRUE, $margin[2]); + + //set image scale factor + $pdf->setImageScale( (float)$xml['imageScale'] ); + + //set some language-dependent strings + $pdf->setLanguageArray($l); + + // set font + $pdf->SetFont( (string)$xml->content[ 'font' ], '', (int)$xml->content[ 'fontSize' ]); + + // add a page + $pdf->AddPage(); + + $styles = $xml->styles; + $content = $xml->content; + $this->fixImages( $content, $xml[ 'stripImages' ] ); + $this->fixHtml( $content ); + + $html = <<<EOF +<style> + $styles + +h1 { + font-size: 24pt; + text-decoration: underline; +} +h2 { + font-size: 20pt; +} +h3 { + font-size: 15pt; +} +h4 { + font-size: 10pt; +} +h5 { + font-size: 10pt; +} +</style> +$content +EOF; + + $tags = array( 'ul' => array(0 => array('h' => '', 'n' => 0), 1 => array('h' => '', 'n' => 0)), + 'ol' => array(0 => array('h' => '', 'n' => 0), 1 => array('h' => '', 'n' => 0)), + 'dt' => array(0 => array('h' => '', 'n' => 0), 1 => array('h' => '', 'n' => 0)), + 'dl' => array(0 => array('h' => '', 'n' => 0), 1 => array('h' => '', 'n' => 0)), + 'dd' => array(0 => array('h' => '', 'n' => 0), 1 => array('h' => '', 'n' => 0)), + 'div' => array(0 => array('h' => '', 'n' => 0), 1 => array('h' => '', 'n' => 0)), + 'p' => array(0 => array('h' => '', 'n' => 1), 1 => array('h' => '', 'n' => 0.5)), + 'h2' => array(0 => array('h' => '', 'n' => 1), 1 => array('h' => '', 'n' => 0.5)), + 'h3' => array(0 => array('h' => '', 'n' => 1), 1 => array('h' => '', 'n' => 0.5)), + 'h4' => array(0 => array('h' => '', 'n' => 1), 1 => array('h' => '', 'n' => 0.5)), + 'h5' => array(0 => array('h' => '', 'n' => 0), 1 => array('h' => '', 'n' => 0.5)) + ); + $pdf->setHtmlVSpace($tags); + + // output the HTML content + $pdf->writeHTML($html, true, false, true, false, ''); + // reset pointer to the last page + $pdf->lastPage(); + //Close and output PDF document + $pdf->Output( $this->currentMenu->title.'.pdf', 'I'); + exit; + } + + private function fixImages( &$html, $strip ) + { + if ( $strip == "true" ) + { + $html = preg_replace( '/<img[^>]+\>/i', '', $html ); + } + else + { + $pattern = '/<\s*img [^\>]+src\s*=\s*[\""\']?([^\""\'\s>]*)/i'; + preg_match_all( $pattern, $html, $matches, PREG_PATTERN_ORDER ); + for($i=0; $i<count($matches[0]); $i++) + { + $replacement = $this->imageSrc( $matches[1][$i] ); + if( $replacement ) + { + $html = str_replace( $matches[0][$i], $replacement, $html); + } + } + } + } + + private function fixHtml( &$html ) + { + $html = str_replace( array( '<dl', '</dl>', '<dt>', '</dt>', '<dd>', '</dd>', '<div', '</div>' ), + array( '<p', '</p>', '', ': ', '', '<br>', '<div', '</div>' ), + $html ); + + $html = str_replace( array( 'href="index.php?', 'href="getFile.php?' ), array( 'href="'.GLZ_HOST.'/index.php?', 'href="'.GLZ_HOST.'/getFile.php?' ), $html ); + + preg_match_all ("/a[\s]+[^>]*?href[\s]?=[\s\"\']+(.*?)[\"\']+(.*?)>([^<]+|.*?)?<\/a>/", $html, $matches ); + $links = ''; + $row = 0; + for( $i = 0; $i < count( $matches[ 0 ] ); $i++ ) + { + if ( strpos( $matches[ 0 ][ $i ], 'getImage.php' ) !== false ) continue; + $row++; + $html = str_replace( $matches[ 2 ][ $i ].'>'.$matches[ 3 ][ $i ].'</a>', $matches[ 2 ][ $i ].'>'.$matches[ 3 ][ $i ].'</a><span style="font-size: small"> ['.$row.'] </span>', $html ); + $links .= '- ['.$row.'] '.$matches[ 1 ][ $i ].'<br>'; + } + if ( !empty( $links ) ) + { + $html .= '<i style="page-break-before: always; font-size: small;"><p><b>Collegamenti</b><br>'.$links.'</p></i>'; + } + } + + private function imageSrc( $url ) + { + if ( strpos( $url, 'getImage.php' ) !== false ) + { + $url = str_replace( array( 'getImage.php?', '&amp;' ), array( '', '&' ), $url ); + $chunks = explode( '&', $url ); + $image = array(); + foreach( $chunks as $key => $chunk ) + { + list( $k, $v ) = explode( '=', $chunk ); + $image[ $k ] = $v; + } + + // controllo + if( !isset($image['id']) ) return ""; + $media = org_glizycms_mediaArchive_MediaManager::getMediaById( $image['id'] ); + if( isset($image['w']) && isset($image['h']) ) + { + $mediaInfo = $media->getResizeImage( $image['w'], $image['h'] ); + } + else + { + $mediaInfo = $media->getImageInfo(); + } + return "<img src=\"".$mediaInfo['fileName']; + } + + } + + private function replacePlaceHolders( $text ) + { + $text = (string)$text; + $text = str_replace( '##url##', $this->pageUrl, (string)$text ); + $text = str_replace( '##title##', $this->pageTitle, $text ); + return $text; + } +} + + +class GlizyPDF extends TCPDF +{ + private $footerText; + + public function SetFooterText( $footerText ) + { + $this->footerText = $footerText; + } + + public function Footer() + { + parent::Footer(); + $this->SetY(-13); + //$this->SetFont( 'helvetica', 'I', 8 ); + $this->Cell(0, 10, $this->footerText, 0, false, 'L', 0, '', 0, false, 'T', 'M'); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/template/layoutManager/PHP.php b/src/core/classes/org/glizy/template/layoutManager/PHP.php new file mode 100755 index 0000000..64771b9 --- /dev/null +++ b/src/core/classes/org/glizy/template/layoutManager/PHP.php @@ -0,0 +1,45 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_template_layoutManager_PHP extends org_glizy_template_layoutManager_LayoutManager +{ + + function apply(&$regionContent) + { + $this->checkRequiredValues( $regionContent ); + foreach ($regionContent as $k => $v) + { + if (!isset($$k)) $$k = $v; + else $$k .= $v; + } + + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.LayoutManagerPHP'); + $compiledFileName = $compiler->verify( $this->fileName ); + + if ( $compiledFileName === false ) + { + $templateSource = @implode('', file($this->fileName)); + $templateSource = $this->fixUrl( $templateSource ); + $compiledFileName = $compiler->compile( $templateSource ); + } + + ob_start(); + include($compiledFileName); + $templateSource = ob_get_contents(); + ob_end_clean(); + + if (isset($regionContent['__body__'])) + { + $templateSource = $this->modifyBodyTag($regionContent['__body__'], $templateSource); + } + + $templateSource = $this->fixLanguages( $templateSource ); + return $templateSource; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/template/layoutManager/PHPTAL.php b/src/core/classes/org/glizy/template/layoutManager/PHPTAL.php new file mode 100755 index 0000000..4a2e34b --- /dev/null +++ b/src/core/classes/org/glizy/template/layoutManager/PHPTAL.php @@ -0,0 +1,44 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_template_layoutManager_PHPTAL extends org_glizy_template_layoutManager_LayoutManager +{ + + function apply(&$regionContent) + { + $this->checkRequiredValues( $regionContent ); + $templateSource = @implode('', file($this->fileName)); + $templateSource = $this->fixUrl( $templateSource ); + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Skin'); + $compiledFileName = $compiler->verify($this->fileName, array('defaultHtml' => $templateSource)); + + $pathInfo = pathinfo($compiledFileName); + $templClass = new PHPTAL($pathInfo['basename'], $pathInfo['dirname'], org_glizy_Paths::getRealPath('CACHE_CODE')); + foreach ($regionContent as $region => $content) + { + $templClass->set($region, $content); + } + $res = $templClass->execute(); + if (PEAR::isError($res)) + { + $templateSource = $res->toString()."\n"; + } + else + { + $templateSource = $res; + } + + if (isset($regionContent['__body__'])) + { + $templateSource = $this->modifyBodyTag($regionContent['__body__'], $templateSource); + } + $templateSource = $this->fixLanguages( $templateSource ); + return $templateSource; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/template/skin/PHP.php b/src/core/classes/org/glizy/template/skin/PHP.php new file mode 100755 index 0000000..8aff70e --- /dev/null +++ b/src/core/classes/org/glizy/template/skin/PHP.php @@ -0,0 +1,39 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_template_skin_PHP extends org_glizy_template_skin_Skin +{ + private $_values; + + function __construct($fileName='', $defaultHtml='') + { + $this->_values = array(); + parent::__construct($fileName, $defaultHtml); + } + + function set($theBlock, $theValue) + { + $this->_values[$theBlock] = $theValue; + } + + function execute() + { + foreach (array_keys($this->_values) as $k) + { + $$k =& $this->_values[$k]; + } + + unset($k); + ob_start(); + include($this->filePath.$this->fileName); + $ret = ob_get_contents(); + ob_end_clean(); + return $ret; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/template/skin/PHPTAL.php b/src/core/classes/org/glizy/template/skin/PHPTAL.php new file mode 100755 index 0000000..c47e230 --- /dev/null +++ b/src/core/classes/org/glizy/template/skin/PHPTAL.php @@ -0,0 +1,46 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_template_skin_PHPTAL extends org_glizy_template_skin_Skin +{ + private static $isLibLoaded = false; + + function __construct($fileName='', $defaultHtml='') + { + if (!self::$isLibLoaded) { + self::$isLibLoaded = true; + set_include_path(get_include_path() . PATH_SEPARATOR . GLZ_LIBS_DIR . 'PHPTAL5/'); + set_include_path(get_include_path() . PATH_SEPARATOR . GLZ_LIBS_DIR . 'PHPTAL5/PHPTAL/'); + require_once(GLZ_LIBS_DIR.'PHPTAL5/PHPTAL.php'); + } + + parent::__construct($fileName, $defaultHtml); + $this->_templClass = new PHPTAL(); + + $this->_templClass->setPhpCodeDestination(org_glizy_Paths::getRealPath('CACHE')) + ->setTemplate($this->filePath.$this->fileName) + ->setForceReparse(false) + ->setEncoding( __Config::get('CHARSET')); + } + + function set($theBlock, $theValue) + { + $this->_templClass->set($theBlock, $theValue); + } + + function execute() + { + $res = $this->_templClass->execute(); + if ( preg_match( "/^.*<body[^>]*>(.*)<\/body>.*$/si", $res ) ) + { + $res = preg_replace("/^.*<body[^>]*>(.*)<\/body>.*$/si", "$1", $res); + } + return $res; + } +} diff --git a/src/core/classes/org/glizy/template/skin/Skin.php b/src/core/classes/org/glizy/template/skin/Skin.php new file mode 100755 index 0000000..f0837a1 --- /dev/null +++ b/src/core/classes/org/glizy/template/skin/Skin.php @@ -0,0 +1,53 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_template_skin_Skin extends GlizyObject +{ + var $filePath; + var $fileName; + var $_templClass = NULL; + + function __construct($fileName='', $defaultHtml='') + { + $this->filePath = org_glizy_Paths::getRealPath('APPLICATION_TEMPLATE', 'skins'); + + if ( !empty( $this->filePath ) ) { + $this->filePath .= '/'; + } + + if (!empty($defaultHtml)) { + $compiler = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Skin'); + $compiledFileName = $compiler->verify($this->filePath.$fileName, array('defaultHtml' => $defaultHtml)); + + $this->fileName = basename($compiledFileName); + $this->filePath = dirname($compiledFileName).'/'; + } else { + if ( org_glizy_ObjectValues::get( 'org.glizy.application', 'pdfMode' ) ) { + // check if is available a pdf skin + $pdfFilePath = preg_replace( '/\/skins\/$/', '/skins-pdf/', $this->filePath ); + if ( file_exists($pdfFilePath.$fileName) ) { + $this->filePath = $pdfFilePath; + } else { + $pdfFilePath = org_glizy_Paths::getRealPath('APPLICATION_TEMPLATE_DEFAULT', 'skins-pdf').'/'; + if ( file_exists($pdfFilePath.$fileName) ) { + $this->filePath = $pdfFilePath; + } + } + } + if (file_exists($fileName) ) { + $this->filePath = ''; + } else if ( !file_exists($this->filePath.$fileName) ) { + $this->filePath = org_glizy_Paths::getRealPath('APPLICATION_TEMPLATE_DEFAULT', 'skins').'/'; + } else if (!file_exists($this->filePath.$fileName) && file_exists(org_glizy_Paths::getRealPath('APPLICATION', 'skins').'/'.$fileName)) { + $this->filePath = org_glizy_Paths::getRealPath('APPLICATION', 'skins').'/'; + } + $this->fileName = $fileName; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/template/skin/TWIG.php b/src/core/classes/org/glizy/template/skin/TWIG.php new file mode 100755 index 0000000..0238e59 --- /dev/null +++ b/src/core/classes/org/glizy/template/skin/TWIG.php @@ -0,0 +1,48 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_template_skin_TWIG extends org_glizy_template_skin_Skin +{ + static $isLibLoaded = false; + private $templateData = array(); + + function __construct($fileName='', $defaultHtml='') + { + if (!self::$isLibLoaded) { + self::$isLibLoaded = true; + require_once(GLZ_LIBS_DIR.'/Twig/Autoloader.php'); + Twig_Autoloader::register(); + } + + parent::__construct($fileName, $defaultHtml); + + $loader = new Twig_Loader_Filesystem($this->filePath); + $this->_templClass = new Twig_Environment($loader, array( + 'cache' => org_glizy_Paths::getRealPath('CACHE'), + 'auto_reload' => true, + 'debug' => true + )); + $this->_templClass->addExtension(new Twig_Extension_Debug()); + } + + function set($theBlock, $theValue) + { + $this->templateData[$theBlock] = $theValue; + } + + function execute() + { + $res = $this->_templClass->render($this->fileName, $this->templateData); + if ( preg_match( "/^.*<body[^>]*>(.*)<\/body>.*$/si", $res ) ) + { + $res = preg_replace("/^.*<body[^>]*>(.*)<\/body>.*$/si", "$1", $res); + } + return $res; + } +} diff --git a/src/core/classes/org/glizy/types/Date.php b/src/core/classes/org/glizy/types/Date.php new file mode 100644 index 0000000..9a1474a --- /dev/null +++ b/src/core/classes/org/glizy/types/Date.php @@ -0,0 +1,14 @@ +<?php + +class org_glizy_types_Date extends DateTime +{ + public static function createFromFormat($format, $time) + { + return new self($time); + } + + public function __toString() + { + return $this->format('Y-m-d'); + } +} diff --git a/src/core/classes/org/glizy/types/DateTime.php b/src/core/classes/org/glizy/types/DateTime.php new file mode 100644 index 0000000..681f3a6 --- /dev/null +++ b/src/core/classes/org/glizy/types/DateTime.php @@ -0,0 +1,14 @@ +<?php + +class org_glizy_types_DateTime extends DateTime +{ + public static function createFromFormat($format, $time) + { + return new self($time); + } + + public function __toString() + { + return $this->format('Y-m-d H:i:s'); + } +} diff --git a/src/core/classes/org/glizy/types/DateTimeTz.php b/src/core/classes/org/glizy/types/DateTimeTz.php new file mode 100644 index 0000000..fd56fee --- /dev/null +++ b/src/core/classes/org/glizy/types/DateTimeTz.php @@ -0,0 +1,14 @@ +<?php + +class org_glizy_types_DateTimeTz extends DateTime +{ + public static function createFromFormat($format, $time) + { + return new self($time); + } + + public function __toString() + { + return $this->format('Y-m-d H:i:s'); + } +} diff --git a/src/core/classes/org/glizy/types/Time.php b/src/core/classes/org/glizy/types/Time.php new file mode 100644 index 0000000..691f559 --- /dev/null +++ b/src/core/classes/org/glizy/types/Time.php @@ -0,0 +1,14 @@ +<?php + +class org_glizy_types_Time extends DateTime +{ + public static function createFromFormat($format, $time) + { + return new self($time); + } + + public function __toString() + { + return $this->format('H:i:s'); + } +} diff --git a/src/core/classes/org/glizy/validators/AbstractValidator.php b/src/core/classes/org/glizy/validators/AbstractValidator.php new file mode 100755 index 0000000..034484b --- /dev/null +++ b/src/core/classes/org/glizy/validators/AbstractValidator.php @@ -0,0 +1,13 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +abstract class org_glizy_validators_AbstractValidator extends GlizyObject +{ + public abstract function validate($description, $value); +} diff --git a/src/core/classes/org/glizy/validators/CompositeValidator.php b/src/core/classes/org/glizy/validators/CompositeValidator.php new file mode 100755 index 0000000..0b60fe9 --- /dev/null +++ b/src/core/classes/org/glizy/validators/CompositeValidator.php @@ -0,0 +1,34 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_validators_CompositeValidator extends org_glizy_validators_AbstractValidator +{ + private $validators = array(); + + public function validate($description, $value) { + $errors = array(); + + foreach ($this->validators as $validator) { + $result = $validator->validate($description, $value); + if (is_string($result)) { + $errors[] = $result; + } + } + + return empty($errors) ? true : $errors; + } + + public function add($validator) { + $this->validators[] = $validator; + } + + public function addArray($validators) { + $this->validators = array_merge($this->validators, $validators); + } +} diff --git a/src/core/classes/org/glizy/validators/Date.php b/src/core/classes/org/glizy/validators/Date.php new file mode 100755 index 0000000..7318548 --- /dev/null +++ b/src/core/classes/org/glizy/validators/Date.php @@ -0,0 +1,21 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_validators_Date extends org_glizy_validators_AbstractValidator +{ + public function validate($description, $value) + { + if (preg_match('/^[\d]{2,4}-[\d]{1,2}-[\d]{1,2}$/', $value) || empty($value)) { + return true; + } + else { + return $description . " deve essere una data"; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/validators/DateTime.php b/src/core/classes/org/glizy/validators/DateTime.php new file mode 100644 index 0000000..d8e7679 --- /dev/null +++ b/src/core/classes/org/glizy/validators/DateTime.php @@ -0,0 +1,21 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_validators_DateTime extends org_glizy_validators_AbstractValidator +{ + public function validate($description, $value) + { + if (preg_match('/^[\d]{2,4}-[\d]{1,2}-[\d]{1,2} [\d]{1,2}:[\d]{1,2}:[\d]{1,2}$/', $value) || empty($value)) { + return true; + } + else { + return $description . " deve essere una data"; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/validators/Email.php b/src/core/classes/org/glizy/validators/Email.php new file mode 100755 index 0000000..98fb0a5 --- /dev/null +++ b/src/core/classes/org/glizy/validators/Email.php @@ -0,0 +1,26 @@ +<?php + +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ +class org_glizy_validators_Email extends org_glizy_validators_AbstractValidator +{ + + /** + * @param string $description + * @param string $value + * + * @return bool|string + */ + public function validate($description, $value) + { + if (filter_var($value, FILTER_VALIDATE_EMAIL)) { + return true; + } else { + return $description . " deve essere un'email"; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/validators/NotNull.php b/src/core/classes/org/glizy/validators/NotNull.php new file mode 100755 index 0000000..f092460 --- /dev/null +++ b/src/core/classes/org/glizy/validators/NotNull.php @@ -0,0 +1,21 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_validators_NotNull extends org_glizy_validators_AbstractValidator +{ + public function validate($description, $value) + { + if ($value !== null) { + return true; + } + else { + return $description . " non può essere vuoto"; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/validators/Numeric.php b/src/core/classes/org/glizy/validators/Numeric.php new file mode 100755 index 0000000..7443823 --- /dev/null +++ b/src/core/classes/org/glizy/validators/Numeric.php @@ -0,0 +1,21 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_validators_Numeric extends org_glizy_validators_AbstractValidator +{ + public function validate($description, $value) + { + if (is_numeric($value) || empty($value)) { + return true; + } + else { + return $description . " deve essere un numero intero"; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/validators/Text.php b/src/core/classes/org/glizy/validators/Text.php new file mode 100755 index 0000000..1466121 --- /dev/null +++ b/src/core/classes/org/glizy/validators/Text.php @@ -0,0 +1,21 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_validators_Text extends org_glizy_validators_AbstractValidator +{ + public function validate($description, $value) + { + if (is_string($value) || empty($value)) { + return true; + } + else { + return $description . " deve essere una stringa"; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizy/validators/ValidationException.php b/src/core/classes/org/glizy/validators/ValidationException.php new file mode 100755 index 0000000..c87c855 --- /dev/null +++ b/src/core/classes/org/glizy/validators/ValidationException.php @@ -0,0 +1,24 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_validators_ValidationException extends Exception +{ + private $errors; + + public function __construct($errors) + { + $this->errors = $errors; + parent::__construct("There were validation errors, call getErrors() to get them"); + } + + public function getErrors() + { + return $this->errors; + } +} diff --git a/src/core/classes/org/glizy/validators/Validator.php b/src/core/classes/org/glizy/validators/Validator.php new file mode 100755 index 0000000..1c59f29 --- /dev/null +++ b/src/core/classes/org/glizy/validators/Validator.php @@ -0,0 +1,215 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizy_validators_Validator extends GlizyObject +{ + var $messageResult = ''; + + + + function org_glizy_validators_Validator () + { + } + + function getError() + { + return __Tp( $this->messageResult ); + } + + + function validate( $value, $type ) + { + $this->messageResult = ''; + + if ( !empty( $value ) ) + { + switch ($type) + { + case 'phone': + if ($this->phone_validation($value) == 0) + { + $this->messageResult = $this->get_error_input_message ($type); + } + break; + + case 'numeric': + if ($this->numeric_validation($value) == 0) + { + $this->messageResult = $this->get_error_input_message ($type); + } + break; + + case 'only_char': + if ($this->only_char_validation($value) == 0 ) + { + $this->messageResult = $this->get_error_input_message ($type); + } + break; + + case 'date': + if ($this->date_validation($value) == 0) + { + $this->messageResult = $this->get_error_input_message ($type); + } + break; + + case 'email': + if ($this->email_validation($value) == 0) + { + $this->messageResult = $this->get_error_input_message ($type); + } + break; + + case 'decimal': + if ($this->decimal_validation($value) == 0) + { + $this->messageResult = $this->get_error_input_message ($type); + } + break; + + case 'zip_code': + if ($this->zip_code_validation($value) == 0) + { + $this->messageResult = $this->get_error_input_message ($type); + } + break; + + default: + if ($this->alphaNumeric_validation($value) == 0 ) + { + $this->messageResult = $this->get_error_input_message ($type); + } + break; + } + } + return empty( $this->messageResult ); + } + + function validateRequired ($value, $required ) + { + $this->messageResult = ''; + if ( !$required ) + { + return true; + } + + if ( empty( $value ) ) + { + $this->messageResult = "Il campo '%s' &egrave; richiesto"; + } + + return empty( $this->messageResult ); + } + + function validateLength ($value, $minLength, $maxLength ) + { + $this->messageResult = ''; + + if( !is_null( $minLength ) && (strlen ($value ) < $minLength ) ) + { + $this->messageResult = "Il campo '%s' &egrave; inferiore alla lunghezza minima consentita"; + } + + if( !empty( $value ) && !is_null( $maxLength ) && (strlen ($value ) > $maxLength ) ) + { + $this->messageResult = "Il campo '%s' supera la lunghezza massima consentita"; + } + return empty( $this->messageResult ); + } + + + function phone_validation($phone) + { + $result = preg_match("/^[0-9\+\-\ ]+$/ ",$phone); + return $result; + } + + function numeric_validation($value) + { + $result = preg_match("/^[0-9]+$/",$value); + return $result; + } + + function only_char_validation($value) + { + $result = preg_match("/^[a-zA-Z]+$/s",$value); + return $result; + } + + function alphaNumeric_validation($value) + { + #$result = preg_match("/^[a-zA-Z0-9\.\-\Ä\ä\Ö\ö\Ãœ\ü\è\é\ò\à\ù\ì\/\\ ]+$/",$value); + $result = !empty($value); + return $result; + } + + + + function date_validation($date) + { + $acc_date = __T( 'GLZ_DATE_TOTIME_REGEXP'); + $result = preg_match($acc_date[0], $date); + return $result; + } + + function email_validation($email) + { + $result = TRUE; + if(preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/i", $email)) + { + $result = FALSE; + } + return $result; + } + + function decimal_validation($value) + { + $result = preg_match("/^\d*\.?\d*$/",$value); + return $result; + } + + function zip_code_validation ($zip_code) + { + $result = preg_match("/^[0-9]+$/ ",$zip_code); + return $result; + } + + // + function get_error_input_message ($type) + { + switch ($type) + { + case 'phone': $message = "Il numero telefonico in input non &egrave; ammesso" ; + break; + + case 'numeric': $message = "Il valore in input non &egrave; numerico" ; + break; + + case 'only_char': $message = "Il valore in input non &egrave; valido"; + break; + + case 'date': $message = "la data Il valore in input non &egrave; ammessa"; + break; + + case 'email': $message = "Il valore email in input non &egrave; ammesso"; + break; + + case 'decimal': $message = "Il valore in input non &egrave; decimale corretto"; + + break; + + case 'zip_code': $message = "CAP non ammesso"; + break; + + default: $message = "Il valore in input non &egrave; alfanumerico"; + break; + } + return $message; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/Glizycms.php b/src/core/classes/org/glizycms/Glizycms.php new file mode 100755 index 0000000..9723238 --- /dev/null +++ b/src/core/classes/org/glizycms/Glizycms.php @@ -0,0 +1,106 @@ +<?php +class org_glizycms_Glizycms extends GlizyObject +{ + const FULLTEXT_DELIMITER = ' ## '; + const FULLTEXT_MIN_CHAR = 2; + private static $mediaArchiveBridge; + + function init() + { + if (__Config::get('QUERY_CACHING_INIT')) { + org_glizy_dataAccessDoctrine_DataAccess::initCache(); + } + + glz_loadLocale( 'org.glizycms.*' ); + glz_loadLocale( 'org.glizycms.contents.*' ); + glz_loadLocale( 'org.glizycms.languages.*' ); + + $application = org_glizy_ObjectValues::get('org.glizy', 'application' ); + + if ($application) { + if (!$application->isAdmin()) { + org_glizy_ObjectFactory::remapClass('org.glizy.components.Page', 'org.glizycms.views.components.Page'); + org_glizy_ObjectFactory::remapClass('org.glizy.mvc.components.Page', 'org.glizycms.views.components.MvcPage'); + + org_glizycms_userManager_fe_Module::registerModule(); + } + + // la creazione dell'istanza serve per il listener + $speakingUrlManager = $application->registerProxy('org.glizycms.speakingUrl.Manager'); + + // registra il resolver di default + org_glizycms_speakingUrl_Manager::registerResolver(org_glizy_ObjectFactory::createObject('org.glizycms.speakingUrl.PageResolver')); + } + + if (is_null(__Config::get('glizycms.sitemap.cacheLife'))) { + __Config::set('glizycms.sitemap.cacheLife', 36000); + } + + if (is_null(__Config::get('glizycms.content.history', ''))) { + __Config::set('glizycms.content.history', true); + } + + if (is_null(__Config::get('glizycms.content.history.comment', ''))) { + __Config::set('glizycms.content.history.comment', false); + } + + __Config::set('glizy.dataAccess.document.enableComment', __Config::get('glizycms.content.history.comment')); + + if (is_null(__Config::get('glizycms.pageEdit.editUrlEnabled', ''))) { + __Config::set('glizycms.pageEdit.editUrlEnabled', true); + } + + if (is_null(__Config::get('glizycms.mediaArchive.exifEnabled', ''))) { + __Config::set('glizycms.mediaArchive.exifEnabled', false); + } + + if (is_null(__Config::get('glizycms.speakingUrl', ''))) { + __Config::set('glizycms.speakingUrl', false); + } + + if (is_null(__Config::get('glizycms.content.showAllPageTypes', ''))) { + __Config::set('glizycms.content.showAllPageTypes', true); + } + + if (is_null(__Config::get('glizycms.form.actionLink.cssClass', ''))) { + __Config::set('glizycms.form.actionLink.cssClass', 'btn action-link'); + } + + if (is_null(__Config::get('glizycms.print.enabled', ''))) { + __Config::set('glizycms.print.enabled', false); + } + if (is_null(__Config::get('glizycms.print.pdf.enabled', ''))) { + __Config::set('glizycms.print.pdf.enabled', false); + } + if (is_null(__Config::get('glizycms.mediaArchive.bridge', ''))) { + __Config::set('glizycms.mediaArchive.bridge', 'org.glizycms.mediaArchive.Bridge'); + } + + self::$mediaArchiveBridge = org_glizy_ObjectFactory::createObject(__Config::get('glizycms.mediaArchive.bridge')); + + if ($application && __Config::get('glizycms.mediaArchive.mediaMappingEnabled')) { + $application->registerProxy('org.glizycms.mediaArchive.services.MediaMappingService'); + } + } + + + static public function getSiteTemplatePath() + { + $templateName = org_glizy_Registry::get( __Config::get( 'REGISTRY_TEMPLATE_NAME' ), ''); + if (empty($templateName)) { + $templateName = __Config::get('glizycms.template.default'); + } + $templatePath = __Paths::get( 'TEMPLATE_FOLDER' ); + if ( empty( $templatePath ) ) { + // TODO verificare perché il path è sbagliato ed è necessartio mettere ../ + $templatePath = __Paths::get( 'APPLICATION_STATIC' ).'templates/'; + } + $templatePath .= $templateName; + return '../'.$templatePath; + } + + static public function getMediaArchiveBridge() + { + return self::$mediaArchiveBridge; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/Delete.php b/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/Delete.php new file mode 100644 index 0000000..0af607e --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/Delete.php @@ -0,0 +1,14 @@ +<?php +class org_glizycms_contents_controllers_activeRecordEdit_Delete extends org_glizy_mvc_core_Command +{ + public function execute($id, $model) + { +// TODO controllo ACL + if ($id) { + $proxy = org_glizy_objectFactory::createObject('org.glizycms.contents.models.proxy.ActiveRecordProxy'); + $proxy->delete($id, $model); + + org_glizy_helpers_Navigation::goHere(); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/Edit.php b/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/Edit.php new file mode 100644 index 0000000..c363fa5 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/Edit.php @@ -0,0 +1,16 @@ +<?php +class org_glizycms_contents_controllers_activeRecordEdit_Edit extends org_glizy_mvc_core_Command +{ + public function execute($id) + { + if ($id) { + $c = $this->view->getComponentById('__model'); + $model = $c->getAttribute('value'); + $proxy = org_glizy_objectFactory::createObject('org.glizycms.contents.models.proxy.ActiveRecordProxy'); + $data = $proxy->load($id, $model); + + $data['__id'] = $id; + $this->view->setData($data); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/Cancel.php b/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/Cancel.php new file mode 100644 index 0000000..731e496 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/Cancel.php @@ -0,0 +1,9 @@ +<?php +class org_glizycms_contents_controllers_activeRecordEdit_ajax_Cancel extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { + $this->directOutput = true; + return array('url' => $this->changeAction('')); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/Save.php b/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/Save.php new file mode 100644 index 0000000..ae0d1e9 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/Save.php @@ -0,0 +1,21 @@ +<?php +class org_glizycms_contents_controllers_activeRecordEdit_ajax_Save extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { +// TODO controllo acl +// TODO per motifi di sicurezza forse è meglio non passare il nome del model nella request +// ma avere un controller specifico che estende quello base al quale viene passato il nome del model, come succede per Scaffold + $proxy = org_glizy_objectFactory::createObject('org.glizycms.contents.models.proxy.ActiveRecordProxy'); + $result = $proxy->save(json_decode($data)); + + $this->directOutput = true; + + if ($result['__id']) { + return array('set' => $result); + } + else { + return array('errors' => $result); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/SaveClose.php b/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/SaveClose.php new file mode 100644 index 0000000..d909e39 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/activeRecordEdit/ajax/SaveClose.php @@ -0,0 +1,14 @@ +<?php +class org_glizycms_contents_controllers_activeRecordEdit_ajax_SaveClose extends org_glizycms_contents_controllers_activeRecordEdit_ajax_Save +{ + function execute($data) + { + $result = parent::execute($data); + + if ($result['errors']) { + return $result; + } + + return array('url' => $this->changeAction('')); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/autocomplete/ajax/FindTerm.php b/src/core/classes/org/glizycms/contents/controllers/autocomplete/ajax/FindTerm.php new file mode 100644 index 0000000..1df0e94 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/autocomplete/ajax/FindTerm.php @@ -0,0 +1,62 @@ +<?php +class org_glizycms_contents_controllers_autocomplete_ajax_FindTerm extends org_glizy_mvc_core_CommandAjax +{ + function execute($fieldName, $model, $query, $term, $proxy, $proxyParams, $getId) + { + $fieldName = explode('-', $fieldName); + $fieldName = array_pop($fieldName); + if (!$proxy) { + $it = org_glizy_objectFactory::createModelIterator($model, $query); + + if ($term != '') { + $it->where($fieldName, '%'.$term.'%', 'LIKE'); + } + + $it->where($fieldName, '', '<>') + ->orderBy($fieldName); + + $foundValues = array(); + + foreach($it as $ar) { + if (is_array($ar->$fieldName)) { + foreach ($ar->$fieldName as $value) { + if ($term == '' || stripos($value, $term) !== false) { + if ($getId) { + $foundValues[$ar->getId()] = $value; + } else { + $foundValues[$value] = $value; + } + } + } + } + else { + if ($getId) { + $foundValues[$ar->getId()] = $ar->$fieldName; + } else { + $foundValues[$ar->$fieldName] = $ar->$fieldName; + } + } + } + + ksort($foundValues); + + $result = array(); + + foreach ($foundValues as $k => $v) { + $result[] = array( + 'id' => $k, + 'text' => $v + ); + } + return $result; + } + else { + $p = $this->application->retrieveProxy($proxy); + if (!$p) { + $p = org_glizy_ObjectFactory::createObject($proxy); + } + $result = $p->findTerm($fieldName, $model, $query, $term, json_decode($proxyParams)); + return $result; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/autocomplete/ajax/PagePicker.php b/src/core/classes/org/glizycms/contents/controllers/autocomplete/ajax/PagePicker.php new file mode 100644 index 0000000..a51d441 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/autocomplete/ajax/PagePicker.php @@ -0,0 +1,26 @@ +<?php +class org_glizycms_contents_controllers_autocomplete_ajax_PagePicker extends org_glizy_mvc_core_CommandAjax +{ + function execute($term, $id, $protocol, $filterType) + { + $this->directOutput = true; + + $speakingUrlManager = $this->application->retrieveProxy('org.glizycms.speakingUrl.Manager'); + if ($id && !$term) { + $result = array(); + $json = json_decode($id); + $id = is_array($json) ? $json : array($id); + foreach($id as $v) { + $tempResult = $speakingUrlManager->searchDocumentsByTerm('', $v, $protocol, $filterType); + if ($tempResult && is_array($tempResult)) { + $result[] = $tempResult[0]; + } + } + + } else { + $result = $speakingUrlManager->searchDocumentsByTerm($term, '', $protocol, $filterType); + + } + return $result; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/moduleEdit/Delete.php b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/Delete.php new file mode 100644 index 0000000..45695de --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/Delete.php @@ -0,0 +1,13 @@ +<?php +class org_glizycms_contents_controllers_moduleEdit_Delete extends org_glizy_mvc_core_Command +{ + public function execute($id, $model) + { +// TODO controllo ACL + if ($id) { + $contentproxy = org_glizy_objectFactory::createObject('org.glizycms.contents.models.proxy.ModuleContentProxy'); + $contentproxy->delete($id, $model); + org_glizy_helpers_Navigation::goHere(); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/moduleEdit/Edit.php b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/Edit.php new file mode 100644 index 0000000..89d9ef9 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/Edit.php @@ -0,0 +1,17 @@ +<?php +class org_glizycms_contents_controllers_moduleEdit_Edit extends org_glizy_mvc_core_Command +{ + public function execute($id) + { +// TODO controllo ACL + if ($id) { + // read the module content + $c = $this->view->getComponentById('__model'); + $contentproxy = org_glizy_objectFactory::createObject('org.glizycms.contents.models.proxy.ModuleContentProxy'); + $data = $contentproxy->loadContent($id, $c->getAttribute('value')); +// TODO verifica se il record esiste + $data['__id'] = $id; + $this->view->setData($data); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/moduleEdit/EditDraft.php b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/EditDraft.php new file mode 100644 index 0000000..d80835d --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/EditDraft.php @@ -0,0 +1,17 @@ +<?php +class org_glizycms_contents_controllers_moduleEdit_EditDraft extends org_glizy_mvc_core_Command +{ + public function execute($id) + { +// TODO controllo ACL + if ($id) { + // read the module content + $c = $this->view->getComponentById('__model'); + $contentproxy = org_glizy_objectFactory::createObject('org.glizycms.contents.models.proxy.ModuleContentProxy'); + $data = $contentproxy->loadContent($id, $c->getAttribute('value'), 'DRAFT'); +// TODO verifica se il record esiste + $data['__id'] = $id; + $this->view->setData($data); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/moduleEdit/Togglevisibility.php b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/Togglevisibility.php new file mode 100644 index 0000000..b756a29 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/Togglevisibility.php @@ -0,0 +1,13 @@ +<?php +class org_glizycms_contents_controllers_moduleEdit_Togglevisibility extends org_glizy_mvc_core_Command +{ + public function execute($id, $model) + { +// TODO controllo ACL + if ($id) { + $contentproxy = org_glizy_objectFactory::createObject('org.glizycms.contents.models.proxy.ModuleContentProxy'); + $contentproxy->toggleVisibility($id, $model); + org_glizy_helpers_Navigation::goHere(); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/Save.php b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/Save.php new file mode 100644 index 0000000..b444dca --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/Save.php @@ -0,0 +1,22 @@ +<?php +class org_glizycms_contents_controllers_moduleEdit_ajax_Save extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { +// TODO controllo acl +// TODO per motifi di sicurezza forse è meglio non passare il nome del model nella request +// ma avere un controller specifico che estende quello base al quale viene passato il nome del model, come succede per Scaffold + + $contentproxy = org_glizy_objectFactory::createObject('org.glizycms.contents.models.proxy.ModuleContentProxy'); + $result = $contentproxy->saveContent(json_decode($data)); + + $this->directOutput = true; + + if ($result['__id']) { + return array('set' => $result); + } + else { + return array('errors' => $result); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveClose.php b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveClose.php new file mode 100644 index 0000000..9372c9a --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveClose.php @@ -0,0 +1,14 @@ +<?php +class org_glizycms_contents_controllers_moduleEdit_ajax_SaveClose extends org_glizycms_contents_controllers_moduleEdit_ajax_Save +{ + function execute($data) + { + $result = parent::execute($data); + + if ($result['errors']) { + return $result; + } + + return array('url' => $this->changeAction('')); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveDraft.php b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveDraft.php new file mode 100644 index 0000000..41c0f2e --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveDraft.php @@ -0,0 +1,22 @@ +<?php +class org_glizycms_contents_controllers_moduleEdit_ajax_SaveDraft extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { +// TODO controllo acl +// TODO per motifi di sicurezza forse è meglio non passare il nome del model nella request +// ma avere un controller specifico che estende quello base al quale viene passato il nome del model, come succede per Scaffold + + $contentproxy = org_glizy_objectFactory::createObject('org.glizycms.contents.models.proxy.ModuleContentProxy'); + $result = $contentproxy->saveContent(json_decode($data), false); + + $this->directOutput = true; + + if ($result['__id']) { + return array('set' => $result); + } + else { + return array('errors' => $result); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveDraftClose.php b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveDraftClose.php new file mode 100644 index 0000000..d721538 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/moduleEdit/ajax/SaveDraftClose.php @@ -0,0 +1,14 @@ +<?php +class org_glizycms_contents_controllers_moduleEdit_ajax_SaveDraftClose extends org_glizycms_contents_controllers_moduleEdit_ajax_SaveDraft +{ + function execute($data) + { + $result = parent::execute($data); + + if ($result['errors']) { + return $result; + } + + return array('url' => $this->changeAction('')); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/Add.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/Add.php new file mode 100644 index 0000000..d8e7673 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/Add.php @@ -0,0 +1,10 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_Add extends org_glizy_mvc_core_Command +{ + public function execute($menuId) + { + if ($menuId) { + $this->setComponentsAttribute('pageParent', 'value', $menuId); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/Addblock.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/Addblock.php new file mode 100644 index 0000000..ef6055d --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/Addblock.php @@ -0,0 +1,15 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_Addblock extends org_glizycms_contents_controllers_pageEdit_Add +{ + public function execute($menuId) + { + if ($menuId) { + parent::execute($menuId); + + // serve per impostare i filtri sui pagetype + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $arMenu = $menuProxy->getMenuFromId($menuId, org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId')); + $this->setComponentsAttribute('pageParent', 'data', 'options='.$arMenu->menu_pageType); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/Edit.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/Edit.php new file mode 100644 index 0000000..aee8623 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/Edit.php @@ -0,0 +1,27 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_Edit extends org_glizy_mvc_core_Command +{ + public function execute($menuId) + { + // TODO controllo permessi + if ($menuId) { + // controlla se il menù è di tipo Block + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $arMenu = $menuProxy->getMenuFromId($menuId, org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId')); + + $previewUrl = GLZ_HOST.'/../?pageId='.($arMenu->menu_type != org_glizycms_core_models_enum_MenuEnum::BLOCK ? $menuId : $arMenu->menu_parentId); + + $this->setComponentsAttribute('preview', 'visible', true); + $this->setComponentsAttribute('preview', 'url', $previewUrl); + $this->setComponentsVisibility('saveAndClose', $arMenu->menu_type == org_glizycms_core_models_enum_MenuEnum::BLOCK); + + if ($arMenu->menu_type == org_glizycms_core_models_enum_MenuEnum::BLOCK) { + $this->view->setAttribute('editUrl', false); + $this->setComponentsAttribute('propertiesState', 'draw', false); + $this->setComponentsAttribute('templateState', 'draw', false); + + + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/Permissions.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/Permissions.php new file mode 100644 index 0000000..67d958f --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/Permissions.php @@ -0,0 +1,45 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_Permissions extends org_glizy_mvc_core_Command +{ + public function execute($menuId) + { + if ($menuId) { + $menu = org_glizy_ObjectFactory::createModel('org.glizycms.contents.models.Menu'); + $menu->load($menuId); + + //inserire menu_extendsPermissions nella tabella menus_tbl + $data = new StdClass; + $data->extendsPermissions = $menu->menu_extendsPermissions; + + $tableName = $menu->getTableName(); + + $aclBack = array(); + + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.contents.models.Role') + ->load('getAclBack', array('menuId' => $menuId, 'tableName' => $tableName)); + + foreach ($it as $ar) { + $aclBack[] = array( + 'id' => $ar->role_id, + 'text' => $ar->role_name + ); + } + + $aclFront = array(); + + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.contents.models.Role') + ->load('getAclFront', array('menuId' => $menuId, 'tableName' => $tableName)); + + foreach ($it as $ar) { + $aclFront[] = array( + 'id' => $ar->role_id, + 'text' => $ar->role_name + ); + } + + $data->aclBack = $aclBack; + $data->aclFront = $aclFront; + $this->view->setData($data); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/Properties.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/Properties.php new file mode 100644 index 0000000..7d075c0 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/Properties.php @@ -0,0 +1,32 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_Properties extends org_glizy_mvc_core_Command +{ + public function execute($menuId) + { + if ($menuId) { + $menu = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Menu'); + $menu->load($menuId); + $data = $menu->getValuesAsArray(); + // TODO controllase se il componente deve essere nascosto + // quando ci sono pagine che devono essere usate una sola volta + $this->setComponentsAttribute('menu_pageType', 'hide', $menu->menu_type == 'SYSTEM'); + + $menuDetail = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.MenuDetail'); + $menuDetail->find(array('menudetail_FK_menu_id' => $menuId, 'menudetail_FK_language_id' => org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'))); + $data = array_merge($data, $menuDetail->getValuesAsArray()); + + if ($menu->menu_parentId) { + $menuParent = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Menu'); + $menuParent->load($menu->menu_parentId); + $data['menu_parentPageType'] = $menuParent->menu_pageType; + } + + if ($this->user->acl('glizycms', 'page.properties.modifyPageTypeFree')) { + $this->setComponentsAttribute('menu_pageType', 'linked', ''); + } + + $this->view->setData($data); + } + + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Add.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Add.php new file mode 100644 index 0000000..410707e --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Add.php @@ -0,0 +1,28 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_ajax_Add extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { + $this->directOutput = true; + $data = json_decode($data); + if ($data) { +// TODO: controllo acl + $pageTitle = $data->title; + $pageParent = $data->pageParent; + $pageType = $data->pageType; + if ($pageTitle && $pageParent && $pageType) { + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $pageId = $menuProxy->addMenu( $pageTitle, + $pageParent, + $pageType, + strtolower(__Request::get('action'))=='addblock' ? org_glizycms_core_models_enum_MenuEnum::BLOCK : org_glizycms_core_models_enum_MenuEnum::PAGE + ); + return array( + 'evt' => 'glizycms.pageAdded', + 'message' => array('menuId' => $pageId, 'parentId' => $pageParent) + ); + } + } + return false; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Addblock.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Addblock.php new file mode 100644 index 0000000..d8e7f3d --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Addblock.php @@ -0,0 +1,4 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_ajax_Addblock extends org_glizycms_contents_controllers_pageEdit_ajax_Add +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/GetChildBlocks.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/GetChildBlocks.php new file mode 100644 index 0000000..1e8bfeb --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/GetChildBlocks.php @@ -0,0 +1,32 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_ajax_GetChildBlocks extends org_glizy_mvc_core_CommandAjax +{ + public function execute($id) + { + $this->directOutput = true; + $output = array(); + + $languageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $contentProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.ContentProxy'); + + $itMenus = $menuProxy->getChildMenusFromId($id, $languageId, false); + foreach($itMenus as $subMenu) { + $content = $contentProxy->readRawContentFromMenu($subMenu->menu_id, $languageId); + $description = ''; + if ($content) { + $description = property_exists($content->content, 'text') ? $content->content->text : + (property_exists($content->content, 'description') ? $content->content->description : ''); + } + +; $output[] = array( + 'id' => $subMenu->menu_id, + 'title' => $subMenu->menudetail_title, + 'description' => glz_strtrim($description).' ('.$subMenu->menu_pageType.')' + ); + + } + + return $output; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/MoveBlock.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/MoveBlock.php new file mode 100644 index 0000000..c1317e2 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/MoveBlock.php @@ -0,0 +1,4 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_ajax_MoveBlock extends org_glizycms_contents_controllers_siteTree_ajax_Move +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Save.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Save.php new file mode 100644 index 0000000..4ee6f57 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/Save.php @@ -0,0 +1,25 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_ajax_Save extends org_glizy_mvc_core_CommandAjax +{ + protected $menuId; + + public function execute($data) + { + $this->directOutput = true; +// TODO: controllo acl + $contentProxy = org_glizy_objectFactory::createObject('org.glizycms.contents.models.proxy.ContentProxy'); + $contentVO = $contentProxy->getContentVO(); + $contentVO->setFromJson($data); + $this->menuId = $contentVO->getId(); + $r = $contentProxy->saveContent($contentVO, + org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'), + __Config::get('glizycms.content.history') + ); + + if ($r===true) { + return true; + } else { + return array('errors' => array($r)); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveClose.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveClose.php new file mode 100644 index 0000000..ba00662 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveClose.php @@ -0,0 +1,18 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_ajax_SaveClose extends org_glizycms_contents_controllers_pageEdit_ajax_Save +{ + public function execute($data) + { + $r = parent::execute($data); + + if ($r===true) { + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $arMenu = $menuProxy->getMenuFromId($this->menuId, org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId')); + if ($arMenu->menu_type == org_glizycms_core_models_enum_MenuEnum::BLOCK) { + return array('evt' => 'glizycms.pageEdit', 'message' => array('menuId' => $arMenu->menu_parentId)); + } + } + + return $r; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SavePermissions.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SavePermissions.php new file mode 100644 index 0000000..d1cabda --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SavePermissions.php @@ -0,0 +1,50 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_ajax_SavePermissions extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { +// TODO: controllo acl + $data = json_decode($data); + + $aclBack = implode(',', $data->aclBack); + $aclFront = implode(',', $data->aclFront); + + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.contents.models.Menu'); + $ar->load($data->menuId); + //$ar->aclBack = $data->editPermissions; + //$ar->aclFront = $data->viewPermissions; + $ar->menu_extendsPermissions = $data->extendsPermissions; + $ar->menu_isLocked = $aclFront ? 1 : 0; + $ar->save(); + + $tableName = $ar->getTableName(); + + $ar = org_glizy_ObjectFactory::createModel('org.glizy.models.JoinDoctrine'); + $ar->delete(array('join_objectName' => $tableName.'#rel_aclBack')); + $ar->delete(array('join_objectName' => $tableName.'#rel_aclFront')); + + if ($aclBack != '') { + $aclBack = explode(',', $aclBack); + + foreach ($aclBack as $role) { + $ar->join_FK_source_id = $data->menuId; + $ar->join_FK_dest_id = $role; + $ar->join_objectName = $tableName.'#rel_aclBack'; + $ar->save(null, true); + } + } + + if ($aclFront != '') { + $aclFront = explode(',', $aclFront); + + foreach ($aclFront as $role) { + $ar->join_FK_source_id = $data->menuId; + $ar->join_FK_dest_id = $role; + $ar->join_objectName = $tableName.'#rel_aclFront'; + $ar->save(null, true); + } + } + + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveProperties.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveProperties.php new file mode 100644 index 0000000..6357301 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveProperties.php @@ -0,0 +1,44 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_ajax_SaveProperties extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { +// TODO: controllo acl + $data = json_decode($data); + + $menu = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Menu'); + $menu->load($data->menu_id); + $menu->menu_url = $data->menu_url; + $menu->menu_isLocked = $data->menu_isLocked; + $menu->menu_hasComment = $data->menu_hasComment; + $menu->menu_printPdf = $data->menu_printPdf; + $menu->menu_pageType = $data->menu_pageType; + $menu->menu_cssClass = $data->menu_cssClass; + if (@$data->menu_creationDate) $menu->menu_creationDate = $data->menu_creationDate; + $menu->save(); + + + $menu = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.MenuDetail'); + $menu->find(array('menudetail_FK_menu_id' => $data->menu_id, 'menudetail_FK_language_id' => org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'))); + $menu->menudetail_title = $data->menudetail_title; + $menu->menudetail_titleLink = $data->menudetail_titleLink; + $menu->menudetail_linkDescription = $data->menudetail_linkDescription; + $menu->menudetail_keywords = $data->menudetail_keywords; + $menu->menudetail_description = $data->menudetail_description; + $menu->menudetail_subject = $data->menudetail_subject; + $menu->menudetail_creator = $data->menudetail_creator; + $menu->menudetail_publisher = $data->menudetail_publisher; + $menu->menudetail_contributor = $data->menudetail_contributor; + $menu->menudetail_type = $data->menudetail_type; + $menu->menudetail_identifier = $data->menudetail_identifier; + $menu->menudetail_source = $data->menudetail_source; + $menu->menudetail_relation = $data->menudetail_relation; + $menu->menudetail_coverage = $data->menudetail_coverage; + $menu->save(); + + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menuProxy->invalidateSitemapCache(); + + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveTemplate.php b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveTemplate.php new file mode 100644 index 0000000..42fed7e --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/pageEdit/ajax/SaveTemplate.php @@ -0,0 +1,16 @@ +<?php +class org_glizycms_contents_controllers_pageEdit_ajax_SaveTemplate extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { +// TODO: controllo acl + $data = json_decode($data); + if ($data && property_exists($data, 'template')) { + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + $templateProxy->setSelectedTemplate($data->template); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/AddPage.php b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/AddPage.php new file mode 100644 index 0000000..d5fc540 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/AddPage.php @@ -0,0 +1,14 @@ +<?php +class org_glizycms_contents_controllers_siteTree_ajax_AddPage extends org_glizy_mvc_core_CommandAjax +{ + public function execute($menuId, $title, $pageType) { +// TODO: CONTROLLO ACL + if ($menuId) { + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menuProxy->addMenu($title, $menuId, $pageType); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Delete.php b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Delete.php new file mode 100644 index 0000000..fa53a1c --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Delete.php @@ -0,0 +1,11 @@ +<?php +class org_glizycms_contents_controllers_siteTree_ajax_Delete extends org_glizy_mvc_core_CommandAjax +{ + public function execute($menuId) { +// TODO: CONTROLLO ACL + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menuProxy->deleteMenu($menuId); + + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/GetSiteTree.php b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/GetSiteTree.php new file mode 100644 index 0000000..5707dca --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/GetSiteTree.php @@ -0,0 +1,115 @@ +<?php +class org_glizycms_contents_controllers_siteTree_ajax_GetSiteTree extends org_glizy_mvc_core_CommandAjax +{ + private $pageTypes; + + public function execute($id) { + $this->directOutput = true; + $output = array(); + + if ($this->user->acl('glizycms', 'page.modify.pagetype')) { + $pageTypeService = org_glizy_ObjectFactory::createObject('org.glizycms.contents.services.PageTypeService'); + $this->pageTypes = $pageTypeService->getAllPageTypes(); + } + + $languageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + + if ($id==0) { + // root + $menu = $menuProxy->getRootMenu($languageId); + $output[] = $this->addNode($menu, true); + return $output; + } + + $itMenus = $menuProxy->getChildMenusFromId($id, $languageId); + foreach($itMenus as $subMenu) { + $output[] = $this->addNode($subMenu); + } + + return $output; + } + + private function addNode($menu, $isRoot=false) { + $title = strip_tags($menu->menudetail_title); + $icon = 'page'; + if ( $menu->menu_pageType=='Empty') { + $icon = 'folder'; + } else if ( $menu->menu_pageType=='Alias') { + $icon = 'alias'; + } + + if ( $menu->menu_type == 'HOMEPAGE' ) { + $icon = 'home'; + } else if ( $menu->menu_type == 'SYSTEM' ) { + $icon .= ' system'; + } + + if ( $menu->menu_isLocked == 1 ) { + $icon .= ' lock'; + } + + $node = array( + 'data' => array( + 'title' => $title, + 'icon' => $icon + ), + 'attr' => array( + 'id' => $menu->menu_id, + 'rel' => 'default', + 'class' => '', + 'title' => $title.' ('.$menu->menu_pageType.':'.$menu->menu_id.')', + ), + 'metadata' => array(), + 'state' => '' + ); + + + if ( !$menu->menudetail_isVisible ) { + $node['data']['icon'] .= ' hide'; + $node['attr']['class'] .= ' glizycmsSiteTree-nodeHide'; + } + if ($isRoot || $menu->numChild) { + $node['attr']['rel'] = 'folder'; + $node['state'] = 'closed'; + } + + // stato delle varie azioni da gestire con acl + $node['metadata']['edit'] = $this->user->acl($this->application->getPageId(),'edit'); + $node['metadata']['draft'] = 0; + $node['metadata']['show'] = $this->user->acl($this->application->getPageId(),'visible'); + $node['metadata']['delete'] = $this->user->acl($this->application->getPageId(),'delete'); + $node['metadata']['preview'] = 0; + $node['metadata']['publish'] = $this->user->acl($this->application->getPageId(),'publish'); + $node['metadata']['lock'] = $this->user->acl($this->application->getPageId(),'lock'); + $node['metadata']['move'] = $this->user->acl($this->application->getPageId(),'move'); + $node['metadata']['add'] = true; + + // stato della pagina + $node['metadata']['isDraft'] = 0; //!$menu->menu_isPublished ? 1 : 0; + $node['metadata']['isShown'] = $menu->menudetail_isVisible ? 1 : 0; + $node['metadata']['isLocked'] = $menu->menu_isLocked ? 1 : 0; + $node['metadata']['hasPreview'] = $menu->menu_hasPreview ? 1 : 0; + $node['metadata']['pageType'] = $menu->menu_pageType; + + // rimuove alcune azioni se la pagina non è di tipo PAGE + if ( $menu->menu_type != 'PAGE' ) { + $node['metadata']['delete'] = false; + $node['metadata']['show'] = false; + } + + if ($this->pageTypes && $this->pageTypes[$menu->menu_pageType]) { + $node['metadata']['pagetype'] = $menu->menu_pageType; + $node['metadata']['acceptparent'] = $this->pageTypes[$menu->menu_pageType]['acceptParent']; + $found = false; + foreach($this->pageTypes as $k=>$v) { + $found = strpos($v['acceptParent'], $menu->menu_pageType)!==false; + if ($found) break; + } + $node['metadata']['add'] = $found; + } + + return $node; + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Hide.php b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Hide.php new file mode 100644 index 0000000..3b7e079 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Hide.php @@ -0,0 +1,15 @@ +<?php +class org_glizycms_contents_controllers_siteTree_ajax_Hide extends org_glizy_mvc_core_CommandAjax +{ + public function execute($menuId) { +// TODO: CONTROLLO ACL + if ($menuId) { + $languageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menuProxy->showHide($menuId, $languageId, false); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Lock.php b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Lock.php new file mode 100644 index 0000000..2b128be --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Lock.php @@ -0,0 +1,15 @@ +<?php +class org_glizycms_contents_controllers_siteTree_ajax_Lock extends org_glizy_mvc_core_CommandAjax +{ + public function execute($menuId) { +// TODO: CONTROLLO ACL + if ($menuId) { + $languageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menuProxy->lockUnlock($menuId, true); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Move.php b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Move.php new file mode 100644 index 0000000..d73e2c3 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Move.php @@ -0,0 +1,11 @@ +<?php +class org_glizycms_contents_controllers_siteTree_ajax_Move extends org_glizy_mvc_core_CommandAjax +{ + public function execute($menuId, $position, $parentId) { +// TODO: CONTROLLO ACL + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menuProxy->moveMenu($menuId, $position, $parentId); + + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Rename.php b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Rename.php new file mode 100644 index 0000000..db490ed --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Rename.php @@ -0,0 +1,16 @@ +<?php +class org_glizycms_contents_controllers_siteTree_ajax_Rename extends org_glizy_mvc_core_CommandAjax +{ + public function execute($menuId, $title) { +// TODO: CONTROLLO ACL + if ($menuId) { + $languageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menuProxy->rename($menuId, $languageId, $title); + return true; + } + + + return false; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Show.php b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Show.php new file mode 100644 index 0000000..844379a --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Show.php @@ -0,0 +1,15 @@ +<?php +class org_glizycms_contents_controllers_siteTree_ajax_Show extends org_glizy_mvc_core_CommandAjax +{ + public function execute($menuId) { +// TODO: CONTROLLO ACL + if ($menuId) { + $languageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menuProxy->showHide($menuId, $languageId, true); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Unlock.php b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Unlock.php new file mode 100644 index 0000000..562374f --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/siteTree/ajax/Unlock.php @@ -0,0 +1,15 @@ +<?php +class org_glizycms_contents_controllers_siteTree_ajax_Unlock extends org_glizy_mvc_core_CommandAjax +{ + public function execute($menuId) { +// TODO: CONTROLLO ACL + if ($menuId) { + $languageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menuProxy->lockUnlock($menuId, false); + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/controllers/tinymce/ajax/GlzLinkList.php b/src/core/classes/org/glizycms/contents/controllers/tinymce/ajax/GlzLinkList.php new file mode 100644 index 0000000..6bccbbb --- /dev/null +++ b/src/core/classes/org/glizycms/contents/controllers/tinymce/ajax/GlzLinkList.php @@ -0,0 +1,24 @@ +<?php +class org_glizycms_contents_controllers_tinymce_ajax_GlzLinkList extends org_glizy_mvc_core_CommandAjax +{ + function execute() + { + $this->directOutput = true; + $links = array('internal' => array()); + + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $siteMap = $menuProxy->getSiteMap(); + $siteMap->getSiteArray(); + $siteMapIterator = &org_glizy_ObjectFactory::createObject('org.glizy.application.SiteMapIterator', $siteMap); + while (!$siteMapIterator->EOF) + { + $n = $siteMapIterator->getNodeArray(); + if ($n['type'] != org_glizycms_core_models_enum_MenuEnum::BLOCK ) { + $links['internal'][] = array( 'name' => str_repeat('. ', $n["depth"]-1).strip_tags($n['title']), + 'link' => 'internal:'.$n['id']); + } + $siteMapIterator->moveNext(); + } + return $links; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/events/Menu.php b/src/core/classes/org/glizycms/contents/events/Menu.php new file mode 100644 index 0000000..07f3dcd --- /dev/null +++ b/src/core/classes/org/glizycms/contents/events/Menu.php @@ -0,0 +1,10 @@ +<?php +class org_glizycms_contents_events_Menu +{ + const ADD = 'onMenuAdd'; + const DELETE = 'onMenuDelete'; + const MOVE = 'onMenuMove'; + const RENAME = 'onMenuRename'; + const INVALIDATE_SITEMAP = 'onInvalidateSitemap'; + const SAVE_CONTENT = 'onSaveContent'; +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/js/BlocksEdit.js b/src/core/classes/org/glizycms/contents/js/BlocksEdit.js new file mode 100755 index 0000000..a155843 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/js/BlocksEdit.js @@ -0,0 +1,125 @@ +Glizy.module('glizycms.BlockEdit', function(){ + var self = this; + + this.container = null; + this.ajaxUrl = null; + this.menuId = null; + this.blocksPos = null; + // this.emptySrc = null; + // this.editSrc = null; + // this.iframeOffset = null; + + this.run = function() { + this.templateDefine(); + + this.container = $('.js-glizycmsBlocksEdit'); + if (this.container.length) { + this.container.addClass('GlizycmsBlockEdit loading clearfix'); + this.ajaxUrl = this.container.data('ajaxurl'); + this.menuId = this.container.data('menuid'); + this.loadChild(); + + + $(this.container).on('click', 'a.js-edit', function(e){ + e.preventDefault(); + Glizy.events.broadcast("glizycms.pageEdit", {"menuId": $(this).data("id")}); + }); + + $(this.container).on('click', 'a.js-delete', function(e){ + e.preventDefault(); + var id = $(this).data("id"); + Glizy.confirm("{i18n:glizycms.confirm.pageDelete}", [], function(success){ + if (success) { + $.ajax({ + type: 'GET', + url: self.ajaxUrl.replace('pageEdit', 'treeview')+"Delete", + data : { + "menuId" : id + }, + success : function (r) { + self.loadChild(); + } + }); + } + }); + }); + + + $(this.container).on('click', 'div.blockEmpty', function(e){ + e.preventDefault(); + Glizy.events.broadcast("glizycms.pageAdd", {"href": 'glizycms_contentsedit/addblock?menuId='+self.menuId}); + }); + } + }; + + this.loadChild = function() { + $.ajax({ + type: 'GET', + url: this.ajaxUrl+"GetChildBlocks", + data : { + "id" : this.menuId + }, + success : function (r) { + self.render(r); + } + }); + }; + + this.render = function(blocks) { + var html = Glizy.template.render('glizycms.BlockEdit.items', {blocks: blocks}); + this.container.html($(html)); + this.container.find('.js-sortable').sortable({ + 'stop': function(event, ui) { + self.onChange(event, ui); + } + }); + this.refreshBlockPos(); + }; + + this.refreshBlockPos = function() { + this.blocksPos = []; + this.container.find('.js-edit').each(function(index, el){ + var $el = $(el); + self.blocksPos.push($el.data('id')); + }); + } + + this.onChange = function(event, ui) { + var id = ui.item.find('.js-edit').data('id'); + var oldPos = this.blocksPos.indexOf(id); + this.refreshBlockPos(); + var newPos = this.blocksPos.indexOf(id); + if (oldPos!=newPos) { + $.ajax({ + type: 'POST', + url: this.ajaxUrl+"MoveBlock", + data : { + "menuId" : id, + "parentId" : this.menuId, + "position" : newPos + } + }); + } + } + + this.templateDefine = function() { + // Glizy.template.define('container', '<div class="GlizycmsBlockEdit loading js-glizycmsBlockEdit"></div>'); + Glizy.template.define('glizycms.BlockEdit.items', '<h2>Contenuti</h2>'+ + '<div class="js-sortable">'+ + '<% _.each(blocks, function(item) { %>'+ + '<div class="blockItem">'+ + '<h3><%= item.title %></h3>'+ + '<p><%= item.description %></p>'+ + '<div class="actions">'+ + '<a alt="Modifica" title="Modifica" class="js-edit" href="#" data-id="<%= item.id %>"><span class="btn-icon icon-pencil"></span></a>'+ + '<a alt="Elimina" title="Elimina" class="js-delete" href="#" data-id="<%= item.id %>"><span class="btn-icon icon-trash"></span></a>'+ + '</div>'+ + '</div>'+ + '<% }); %>'+ + '</div>'+ + '<div class="blockItem blockEmpty">'+ + '<i class="icon-plus"></i>'+ + '<div class="actions">Aggiungi</div>'+ + '</div>'); + }; +}); diff --git a/src/core/classes/org/glizycms/contents/js/ContentsEdit.js b/src/core/classes/org/glizycms/contents/js/ContentsEdit.js new file mode 100755 index 0000000..9e18c8e --- /dev/null +++ b/src/core/classes/org/glizycms/contents/js/ContentsEdit.js @@ -0,0 +1,11 @@ +GlizyApp.pages[ 'org.glizycms.contents.views.ContentsEdit' ] = function( state, routing ) { + $(function(){ + if ('index'==state) { + var tree = new GlizycmsSiteTree("#js-glizycmsSiteTree", "#js-glizycmsSiteTreeAdd"); + // Glizy.module('cms.SiteTree').run(); + Glizy.module('cms.PageEditIframe').run(); + } else if ('edit'==state) { + Glizy.module('glizycms.BlockEdit').run(); + } + }); +} diff --git a/src/core/classes/org/glizycms/contents/js/PageEditIframe.js b/src/core/classes/org/glizycms/contents/js/PageEditIframe.js new file mode 100755 index 0000000..5883741 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/js/PageEditIframe.js @@ -0,0 +1,41 @@ +Glizy.module('cms.PageEditIframe', function(){ + this.iframe = null; + this.emptySrc = null; + this.editSrc = null; + this.iframeOffset = null; + + this.run = function() { + var self = this; + this.iframe = $("#js-glizycmsPageEdit"); + this.iframeOffset = this.iframe.offset(); + this.emptySrc = this.iframe.data("emptysrc"); + this.editSrc = this.iframe.data("editsrc"); + this.changeUrl(null, this.emptySrc); + + Glizy.events.on("glizycms.pageEdit", function(e){ + self.changeUrl(e.message.menuId); + }); + + Glizy.events.on("glizycms.pageAdd", function(e){ + self.changeUrl(null, e.message.href); + }); + + $('body').css('overflow', 'hidden'); + $(window).resize(Glizy.responder(this, this.onResize)); + this.onResize(); + }; + + this.changeUrl = function(menuId, href) { + if (menuId) { + jQuery("#modalDiv").remove(); + this.iframe.attr("src", this.editSrc+menuId+"&_"+(new Date()).getTime()); + } else { + this.iframe.attr("src", href); + } + }; + + this.onResize = function() { + var h = $(window).height() - this.iframeOffset.top; + this.iframe.height(h); + }; +}); diff --git a/src/core/classes/org/glizycms/contents/js/SiteTree.js b/src/core/classes/org/glizycms/contents/js/SiteTree.js new file mode 100755 index 0000000..4305f77 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/js/SiteTree.js @@ -0,0 +1,291 @@ +var GlizycmsSiteTree = dejavu.Class.declare({ + treeId: null, + tree: null, + addPageId: null, + ajaxUrl: null, + treeOffset: null, + + initialize: function(treeId, addPageId) { + var self = this; + this.treeId = treeId; + this.addPageId = addPageId; + this.tree = $(this.treeId); + this.ajaxUrl = this.tree.data('ajaxurl'); + + // initialize the tree + this.tree.jstree({ + // List of active plugins + dots : false, + "plugins" : [ "themes","json_data","ui","crrm","cookies","dnd","types","contextmenu"], + "json_data" : { + "ajax" : { + "url" : this.ajaxUrl+"GetSiteTree", + "data" : function (n) { + self.onResize(); + return { + "id" : n.attr ? n.attr("id").replace("node_","") : 0 + }; + } + } + }, + + "themes": { + dots: false + }, + "cookies" : { + "save_selected" : false + }, + "contextmenu" : { + "items" : this.customMenu + }, + "crrm" : { + "move" : { + "check_move" : this.onCheckMove + } + } + }) + .bind("select_node.jstree", this.onNodeSelect) + .bind("remove.jstree", this.onNodeRemove) + .bind("move_node.jstree", this.onNodeMove) + .bind("loaded.jstree", this.onTreeLoaded); + this.tree.css("overflow", "auto"); + this.treeOffset = this.tree.offset(); + // add page button + $(addPageId).click(this.onAddPageClick); + + // Listen events + Glizy.events.on("glizycms.pageAdded", this.onPageAdded); + Glizy.events.on("glizycms.refreshTree", this.onRefreshTree); + Glizy.events.on("glizycms.renameTitle", this.onRefreshTree); + Glizy.events.on("glizycms.treeCallAjaxForMenu", this.onTreeAjaxCall); + + $(window).resize(this.onResize); + this.onResize(); + }, + + + onResize: function (event) { + var h = $(window).height() - this.treeOffset.top; + this.tree.height(h); + }.$bound(), + + onTreeLoaded: function (event, data) { + this.tree.find('li a').first().trigger('click'); + this.tree.jstree("open_node", this.tree.find('li a').first()); + }.$bound(), + + /** + * Tree node selected, dispatch the event with the menuId param + * @param event event DOM event + * @param object data Treeview data object + */ + onNodeSelect: function (event, data) { + if (data.rslt.e) { + Glizy.events.broadcast("glizycms.pageEdit", {"menuId": data.rslt.obj.attr("id")}); + if (data.rslt.obj.data('add')) { + $(this.addPageId).show(); + } else { + $(this.addPageId).hide(); + } + } + }.$bound(), + + /** + * Tree node delete, send a ajax request to delete the node, + * after deleted the tree is refreshed. + * The ajax call Delete command with: + * menuId: id to delete + * @param event event DOM event + * @param object data Treeview data object + */ + onNodeRemove: function (event, data) { + var self = this; + data.rslt.obj.each(function () { + $.ajax({ + async : false, + type: 'POST', + url: self.ajaxUrl+"Delete", + data : { + "menuId" : this.id.replace("node_","") + }, + success : function (r) { + if(!r.status) { + data.inst.refresh(); + } + } + }); + }); + }.$bound(), + + /** + * Tree node move, send a ajax request to move the node, + * after the mode the tree is refreshed. + * The ajax call Move command with: + * menuId: id to move + * parentId: id of parent node + * position: a new position + * @param event event DOM event + * @param object data Treeview data object + */ + onNodeMove: function (event, data) { + var self = this; + data.rslt.o.each(function (i) { + $.ajax({ + async : false, + type: 'POST', + url: self.ajaxUrl+"Move", + data : { + "menuId" : $(this).attr("id").replace("node_",""), + "parentId" : data.rslt.cr === -1 ? 1 : data.rslt.np.attr("id").replace("node_",""), + "position" : data.rslt.cp + i + }, + success : function (r) { + if(!r.status) { + $.jstree.rollback(data.rlbk); + } + else { + $(data.rslt.oc).attr("id", "node_" + r.id); + if(data.rslt.cy && $(data.rslt.oc).children("UL").length) { + data.inst.refresh(data.inst._get_parent(data.rslt.oc)); + } + } + } + }); + }); + }.$bound(), + + onAddPageClick: function(e){ + e.preventDefault(); + Glizy.events.broadcast("glizycms.pageAdd", {"href": e.currentTarget.href+(e.currentTarget.href.indexOf('?') > -1 ? '&' : '?')+'menuId='+this.tree.jstree('get_selected').attr("id")}); + }.$bound(), + + onPageAdded: function(e){ + Glizy.events.broadcast("glizycms.pageEdit", {"menuId": e.message.menuId}); + var node = this.tree.find("#"+e.message.parentId); + var tree = jQuery.jstree._reference(this.treeId); + tree.refresh(node); + }.$bound(), + + onRefreshTree: function(e){ + var tree = jQuery.jstree._reference(this.treeId); + var currentNode = tree._get_node(null, false); + var parentNode = tree._get_parent(currentNode); + tree.refresh(parentNode); + }.$bound(), + + onTreeAjaxCall: function(e){ + var self = this; + $.ajax({ + async : false, + type: 'POST', + url: self.ajaxUrl+e.message.action, + data : { + "menuId" : e.message.menuId + }, + success : function (r) { + Glizy.events.broadcast("glizycms.refreshTree"); + } + }); + }.$bound(), + + onCheckMove: function(m) { + var pagetype = m.np.data('pagetype'); + var acceptparent = m.o.data('acceptparent'); + if (pagetype && acceptparent) { + acceptparent = acceptparent.split(','); + return acceptparent.indexOf(pagetype)!==-1; + } + return true; + }.$bound(), + + + customMenu: function(node) { + var self = this; + var menu = {}; + if (node.data("edit") == "1") { + menu.modify = { + "label": "{i18n:Edit}", + "icon": "icon-pencil", + "action": function(obj) { + Glizy.events.broadcast("glizycms.pageEdit", {"menuId": obj.attr("id")}); + } + }; + } + if (node.data("draft") == "1" && node.data("isDraft") == "1") { + menu.modifyDraft = { + "label": "{i18n:Edit draft}", + "icon": "icon-pencil", + "action": function(obj) { + Glizy.events.broadcast("glizycms.pageEdit", {"menuId": obj.attr("id")}); + } + }; + } + if (node.data("publish") == "1" && node.data("isDraft") == "1") { + menu.publish = { + "label": "{i18n:Publish}", + "icon": "icon-check", + "action": function(obj) { + } + }; + } + if (node.data("delete") == "1") { + menu.remove = { + "label": "{i18n:Delete}", + "icon": "icon-remove", + "action": function(obj) { + Glizy.confirm("{i18n:glizycms.confirm.pageDelete}", [], function(success){ + if (success) self.remove(obj); + }); + } + }; + } + if (node.data("show") == "1") { + if (node.data("isShown") == "1") { + menu.show = { + "label": "{i18n:Hide}", + "icon": "icon-eye-close", + "action": function(obj) { + Glizy.events.broadcast("glizycms.treeCallAjaxForMenu", {"action": "hide", "menuId": obj.attr("id")}); + } + }; + } else { + menu.show = { + "label": "{i18n:Show}", + "icon": "icon-eye-open", + "action": function(obj) { + Glizy.events.broadcast("glizycms.treeCallAjaxForMenu", {"action": "show", "menuId": obj.attr("id")}); + } + }; + } + } + if (node.data("lock") == "1") { + if (node.data("isLocked") == "1") { + menu.lock = { + "label": "{i18n:Change to public page}", + "icon": "icon-lock", + "action": function(obj) { + Glizy.events.broadcast("glizycms.treeCallAjaxForMenu", {"action": "unlock", "menuId": obj.attr("id")}); + } + }; + } else { + menu.lock = { + "label": "{i18n:Change to private page}", + "icon": "icon-unlock", + "action": function(obj) { + Glizy.events.broadcast("glizycms.treeCallAjaxForMenu", {"action": "lock", "menuId": obj.attr("id")}); + } + }; + } + } + if (node.data("preview") == "1") { + menu.preview = { + "label": "{i18n:Preview}", + "icon": "icon-desktop", + "action": function(obj) { + Glizy.events.broadcast("glizycms.treeCallAjaxForMenu", {"action": "hide", "menuId": obj.attr("id")}); + } + }; + } + return menu; + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/locale/en.php b/src/core/classes/org/glizycms/contents/locale/en.php new file mode 100644 index 0000000..10062b3 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/locale/en.php @@ -0,0 +1,17 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +$strings = array ( + "glizycms.confirm.pageDelete" => "Do you really want to cancel the page?", + "glizycms.Add Page" => "Add Page", + "glizycms.Site Structure" => "Site Structure", + "History" => "History", + "Menu css class" => "Menu css class", +); +org_glizy_locale_Locale::append($strings); diff --git a/src/core/classes/org/glizycms/contents/locale/it.php b/src/core/classes/org/glizycms/contents/locale/it.php new file mode 100644 index 0000000..1f522c6 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/locale/it.php @@ -0,0 +1,31 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +$strings = array ( + "glizycms.confirm.pageDelete" => "Siete sicuri di voler cancellare la pagina?", + "glizycms.Add Page" => "Aggiungi pagina", + "glizycms.Site Structure" => "Struttura sito", + "Title" => "Titolo", + "Edit" => "Modifica", + "Edit draft" => "Modifica bozza", + "Publish" => "Pubblica", + "Delete" => "Cancella", + "Hide" => "Nascondi", + "Show" => "Mostra", + "Preview" => "Anteprima", + "Change to public page" => "Rendi la pagina pubblica", + "Change to private page" => "Rendi la pagina privata", + "Content" => "Contenuti", + "Properties" => "Proprietà", + "Permissions" => "Permessi", + "Templates and colors" => "Template e colori", + "History" => "Versioni", + "Menu css class" => "Classe css menu", +); +org_glizy_locale_Locale::append($strings); diff --git a/src/core/classes/org/glizycms/contents/models/ContentVO.php b/src/core/classes/org/glizycms/contents/models/ContentVO.php new file mode 100644 index 0000000..9a56f1a --- /dev/null +++ b/src/core/classes/org/glizycms/contents/models/ContentVO.php @@ -0,0 +1,57 @@ +<?php +class org_glizycms_contents_models_ContentVO +{ + public $__id; + public $__title = ''; + public $__url = ''; + public $__comment = ''; + public $__indexFields = array(); + + public function setId($value) + { + $this->__id = intval($value); + } + + public function getId() + { + return $this->__id; + } + + public function setTitle($value) + { + $this->__title = $value; + } + + public function setUrl($value) + { + $this->__url = $value; + } + + public function getUrl($value) + { + return $this->__url; + } + + public function setIndexFields(array $indexFields) + { + $this->__indexFields = $indexFields; + } + + public function getComment() + { + return $this->__comment; + } + + public function setFromJson($data) + { + $data = is_string($data) ? json_decode($data) : $data; + foreach ($data as $k => $v) { + // remove the system values + if (strpos($k, 'pageEdit_command') === 0) continue; + $this->$k = $v; + } + $this->__indexFields = property_exists($data, '__indexFields') ? + (is_string($data->__indexFields) ? json_decode($data->__indexFields) : $data->__indexFields ) + : array(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/models/DocumentACL.php b/src/core/classes/org/glizycms/contents/models/DocumentACL.php new file mode 100644 index 0000000..8c5add7 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/models/DocumentACL.php @@ -0,0 +1,25 @@ +<?php +// TODO +// implementare il tag relation nel compiler del model ed elimare questo provvisioro + +class org_glizycms_contents_models_DocumentACL extends org_glizy_dataAccessDoctrine_ActiveRecord { + + function __construct($connectionNumber=0) { + parent::__construct($connectionNumber); + $this->setTableName('documents_tbl', org_glizy_dataAccessDoctrine_DataAccess::getTablePrefix($connectionNumber)); + + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($this->connection); + $sequenceName = $sm->getSequenceName($this->getTableName()); + $this->setSequenceName($sequenceName); + + $fields = $sm->getFields($this->getTableName()); + + foreach ($fields as $field) { + $this->addField($field); + } + + $this->addRelation(array('type' => 'joinTable', 'name' => 'rel_aclEdit', 'className' => 'org.glizy.models.JoinDoctrine', 'field' => 'join_FK_source_id', 'destinationField' => 'join_FK_dest_id', 'bindTo' => '__aclEdit', 'objectName' => '')); + $this->addRelation(array('type' => 'joinTable', 'name' => 'rel_aclView', 'className' => 'org.glizy.models.JoinDoctrine', 'field' => 'join_FK_source_id', 'destinationField' => 'join_FK_dest_id', 'bindTo' => '__aclView', 'objectName' => '')); + $this->setProcessRelations(true); + } +} diff --git a/src/core/classes/org/glizycms/contents/models/Menu.php b/src/core/classes/org/glizycms/contents/models/Menu.php new file mode 100644 index 0000000..bc04052 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/models/Menu.php @@ -0,0 +1,29 @@ +<?php +// TODO +// implementare il tag relation nel compiler del model ed elimare questo provvisioro + +class org_glizycms_contents_models_Menu extends org_glizy_dataAccessDoctrine_ActiveRecord { + + function __construct($connectionNumber=0) { + parent::__construct($connectionNumber); + $this->setTableName('menus_tbl', org_glizy_dataAccessDoctrine_DataAccess::getTablePrefix($connectionNumber)); + + $sm = new org_glizy_dataAccessDoctrine_SchemaManager($this->connection); + $sequenceName = $sm->getSequenceName($this->getTableName()); + $this->setSequenceName($sequenceName); + + $fields = $sm->getFields($this->getTableName()); + + foreach ($fields as $field) { + $this->addField($field); + } + + /* + // TODO far funzionare le relazioni + + $this->addRelation(array('type' => 'joinTable', 'name' => 'rel_aclFront', 'className' => 'org.glizy.models.JoinDoctrine', 'field' => 'join_FK_source_id', 'destinationField' => 'join_FK_dest_id', 'bindTo' => 'aclFront', 'objectName' => '')); + $this->addRelation(array('type' => 'joinTable', 'name' => 'rel_aclBack', 'className' => 'org.glizy.models.JoinDoctrine', 'field' => 'join_FK_source_id', 'destinationField' => 'join_FK_dest_id', 'bindTo' => 'aclBack', 'objectName' => '')); + $this->setProcessRelations(true); + */ + } +} diff --git a/src/core/classes/org/glizycms/contents/models/Role.xml b/src/core/classes/org/glizycms/contents/models/Role.xml new file mode 100644 index 0000000..774e123 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/models/Role.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:type="2tables" + model:tableName="joins_tbl,roles_tbl" + model:joinFields="join_FK_dest_id,role_id" + model:usePrefix="true"> + + <model:Query name="getAclBack" type="function" arguments="menuId,tableName"> + <![CDATA[ + $iterator->where('join_FK_source_id', $menuId) + ->where('join_objectName', $tableName.'#rel_aclBack'); + ]]> + </model:Query> + + <model:Query name="getAclFront" type="function" arguments="menuId,tableName"> + <![CDATA[ + $iterator->where('join_FK_source_id', $menuId) + ->where('join_objectName', $tableName.'#rel_aclFront'); + ]]> + </model:Query> + +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/models/proxy/ActiveRecordProxy.php b/src/core/classes/org/glizycms/contents/models/proxy/ActiveRecordProxy.php new file mode 100644 index 0000000..91f0257 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/models/proxy/ActiveRecordProxy.php @@ -0,0 +1,89 @@ +<?php +class org_glizycms_contents_models_proxy_ActiveRecordProxy extends GlizyObject +{ + public function load($recordId, $model) + { + $ar = org_glizy_objectFactory::createModel($model); + + if (__Config::get('ACL_MODULES')) { + // permessi editing e visualizzazione record + $this->addAclRelations($ar); + } + + $ar->load($recordId); + $values = $ar->getValuesAsArray(); + + if (__Config::get('ACL_MODULES')) { + $values['__aclEdit'] = $this->getPermissionName($ar->__aclEdit); + $values['__aclView'] = $this->getPermissionName($ar->__aclView); + } + + return $values; + } + + protected function addAclRelations($ar) { + $ar->addRelation(array('type' => 'joinTable', 'name' => 'rel_aclEdit', 'className' => 'org.glizy.models.JoinDoctrine', 'field' => 'join_FK_source_id', 'destinationField' => 'join_FK_dest_id', 'bindTo' => '__aclEdit', 'objectName' => '')); + $ar->addRelation(array('type' => 'joinTable', 'name' => 'rel_aclView', 'className' => 'org.glizy.models.JoinDoctrine', 'field' => 'join_FK_source_id', 'destinationField' => 'join_FK_dest_id', 'bindTo' => '__aclView', 'objectName' => '')); + $ar->setProcessRelations(true); + } + + protected function getPermissionName($permissions) + { + $names = array(); + $permissions = explode(',', $permissions); + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.roleManager.models.Role'); + foreach ($permissions as $v) { + if ($ar->load($v)) { + $names[] = array ( + 'id' => $ar->role_id, + 'text' => $ar->role_name + ); + } + } + + return $names; + } + + public function save($data) + { + $id = $data->__id; + $model = $data->__model; + + $ar = org_glizy_objectFactory::createModel($model); + $ar->load($id); + + foreach ($data as $k => $v) { + // remove the system values + if (strpos($k, '__') === 0 || !$ar->fieldExists($k)) continue; + $ar->$k = $v; + } + + try { + if (__Config::get('ACL_MODULES')) { + // permessi editing e visualizzazione record + $this->addAclRelations($ar); + $ar->__aclEdit = $data->__aclEdit; + $ar->__aclView = $data->__aclView; + } + + $id = $ar->save(); + } + catch (org_glizy_validators_ValidationException $e) { + return $e->getErrors(); + } + + return array('__id' => $id); + } + + public function delete($recordId, $model) + { + $ar = org_glizy_objectFactory::createModel($model); + + if (__Config::get('ACL_MODULES')) { + // permessi editing e visualizzazione record + $this->addAclRelations($ar); + } + + $ar->delete($recordId); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/models/proxy/ContentFindTermProxy.php b/src/core/classes/org/glizycms/contents/models/proxy/ContentFindTermProxy.php new file mode 100644 index 0000000..dd13013 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/models/proxy/ContentFindTermProxy.php @@ -0,0 +1,36 @@ +<?php +class org_glizycms_contents_models_proxy_ContentFindTermProxy +{ + function findTerm($fieldName, $model, $query, $term, $proxyParams) + { + $oldMultisite = __Config::get('MULTISITE_ENABLED'); + if ($proxyParams && property_exists($proxyParams, 'multisite') && !$proxyParams->multisite) { + __Config::set('MULTISITE_ENABLED', false); + } + $document = org_glizy_objectFactory::createObject('org.glizy.dataAccessDoctrine.ActiveRecordDocument'); + $document->addField(new org_glizy_dataAccessDoctrine_DbField($fieldName, Doctrine\DBAL\Types\Type::STRING, 255, false, null,'', false)); + + $it = $document->createRecordIterator() + ->select('index0.document_index_text_value') + ->where('document_type', 'glizycms.content') + ->groupBy('index0.document_index_text_value') + ->allStatuses(); + + if ($term != '') { + $it->where($fieldName, '%'.$term.'%', 'LIKE'); + } + + $it->orderBy($fieldName); + + $result = array(); + foreach($it as $ar) { + $result[] = array( + 'id' => $ar->document_index_text_value, + 'text' => $ar->document_index_text_value + ); + } + + __Config::set('MULTISITE_ENABLED', $oldMultisite); + return $result; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/models/proxy/ContentProxy.php b/src/core/classes/org/glizycms/contents/models/proxy/ContentProxy.php new file mode 100644 index 0000000..46d5058 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/models/proxy/ContentProxy.php @@ -0,0 +1,154 @@ +<?php +class org_glizycms_contents_models_proxy_ContentProxy extends GlizyObject +{ + /** + * Return a object with the system property for read or save the content values + * @return org_glizycms_contents_models_ContentVO + */ + public function getContentVO() + { + $vo = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.ContentVO'); + return $vo; + } + + + /** + * Read the content for a menu + * @param int $menuId Menu id + * @param int $languageId Language id + * @return org_glizycms_contents_models_ContentVO Content + */ + public function readContentFromMenu($menuId, $languageId, $setMenuTitle=true) + { + $menuDocument = $this->readRawContentFromMenu($menuId, $languageId); + $contentVO = $menuDocument ? $menuDocument->getContentVO() : $this->getContentVO(); + + // il contenuto può non esserci + // viene caricato il titolo e l'id dal menù + $contentVO->setId($menuId); + + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menu = $menuProxy->getMenuFromId($menuId, $languageId); + if ($setMenuTitle){ + $contentVO->setTitle($menu->menudetail_title); + } + if (__Config::get('glizycms.speakingUrl')) { + $contentVO->setUrl($menu->speakingurl_value); + } + + return $contentVO; + } + + + /** + * Read the content for a menu + * + * NOTA: per velocizzare non viene controllato se il menù esiste + * quindi se il menù non esiste oppure se non ci sono contenuti + * ritorna un oggetto nullo + * + * @param int $menuId Menu id + * @param int $languageId Language id + * @return org_glizycms_contents_models_Content Content + */ + public function readRawContentFromMenu($menuId, $languageId) + { + $it = org_glizy_objectFactory::createModelIterator('org.glizycms.core.models.Content'); + $it->setOptions(array('type' => 'PUBLISHED_DRAFT')); + $menuDocument = $it->where('id', $menuId)->first(); + if (!$menuDocument) { + $languageProxy = __ObjectFactory::createObject('org.glizycms.languages.models.proxy.LanguagesProxy'); + $it = org_glizy_objectFactory::createModelIterator('org.glizycms.core.models.Content') + ->setOptions(array('type' => 'PUBLISHED_DRAFT')) + ->whereLanguageIs($languageProxy->getDefaultLanguageId()) + ->where('id', $menuId); + $menuDocument = $it->first(true); + } + + return $menuDocument; + } + + /** + * Save the content for a menu + * @param org_glizycms_contents_models_ContentVO $data Content to save + * @param int $languageId Language id + * @param boolean $publish Publish or save + */ + public function saveContent(org_glizycms_contents_models_ContentVO $data, $languageId, $publish=true, $setMenuTitle=true) + { + $speakingUrlProxy = __Config::get('glizycms.speakingUrl') ? org_glizy_ObjectFactory::createObject('org.glizycms.speakingUrl.models.proxy.SpeakingUrlProxy') : null; + +// TODO gestire meglio gli errori tramite eccezioni + $menuId = (int)$data->getId(); + if ($menuId) { + $invalidateSitemapCache = false; + + $menuDocument = $this->readRawContentFromMenu($menuId, $languageId); + $originalUrl = $menuDocument->url; + $menuDocument->setDataFromContentVO($data); + + if ($speakingUrlProxy && $originalUrl != $menuDocument->url) { + //valida l'url + if (!$speakingUrlProxy->validate($menuDocument->url, $languageId, $menuId, 'org.glizycms.core.models.Content')) { + return 'Url non valido perché già utilizzato'; + } + } + + // salva i dati + if ($publish) { + $menuDocument->publish(null, $data->getComment()); + } else { + $menuDocument->save(null, false, 'PUBLISHED', $data->getComment()); + } + + if ($speakingUrlProxy && $originalUrl!=$menuDocument->url) { + // aggiorna l'url parlante + $speakingUrlProxy = org_glizy_ObjectFactory::createModel('org.glizycms.speakingUrl.models.proxy.SpeakingUrlProxy'); + if ($menuDocument->url) { + $speakingUrlProxy->addUrl($menuDocument->url, $languageId, $menuId, 'org.glizycms.core.models.Content'); + } else { + $speakingUrlProxy->deleteUrl($languageId, $menuId, 'org.glizycms.core.models.Content'); + } + $invalidateSitemapCache = true; + } + + // aggiorna il titolo della pagina + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menuProxy->touch($menuId, $languageId); + $menu = $menuProxy->getMenuFromId($menuId, $languageId); + if ($setMenuTitle && $menu->menudetail_title != $menuDocument->title) { + $menuProxy->rename($menuId, $languageId, $menuDocument->title); + } + + // TODO implementare meglio + if (strtolower($menu->menu_pageType) == 'alias') { + $menu->menu_url = 'alias:'.$data->link; + $menu->save(); + $invalidateSitemapCache = true; + } + + if ($invalidateSitemapCache) { + $menuProxy->invalidateSitemapCache(); + } + + $evt = array('type' => org_glizycms_contents_events_Menu::SAVE_CONTENT); + $this->dispatchEvent($evt); + + return true; + } else { + // TODO: errore dati non validi + } + } + + + public function deleteContent($menuId) + { + // cancella il contenuto del documento associato + $it = org_glizy_objectFactory::createModelIterator('org.glizycms.core.models.Content'); + $menuDocument = $it->load('getContentForMenu', array('menuId' => $menuId))->first(); + + if ($menuDocument) { + $menuDocument->delete(); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/models/proxy/MenuProxy.php b/src/core/classes/org/glizycms/contents/models/proxy/MenuProxy.php new file mode 100644 index 0000000..b82eba6 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/models/proxy/MenuProxy.php @@ -0,0 +1,280 @@ +<?php +class org_glizycms_contents_models_proxy_MenuProxy extends GlizyObject +{ + /** + * Load the site map from DB + * + * @return org.glizycms.core.application.SiteMapDB The sitemap + */ + public function getSiteMap($load=true) + { + $siteMap = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.SiteMapDB'); + if ($load) { + $siteMap->loadTree(); + } + return $siteMap; + } + + /** + * Get a menu root menu record + * + * @return org.glizy.dataAccessDoctrine.ActiveRecord The menu record + */ + public function getRootMenu($languageId) + { + // org_glizy_dataAccessDoctrine_DataAccess::enableLogging(); + $menu = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Menu') + ->load('getRootMenu', array('languageId' => $languageId)) + ->first(); + + return $menu; + } + + /** + * Get a menu record from id + * + * @return org.glizy.dataAccessDoctrine.ActiveRecord The menu record + */ + public function getMenuFromId($menuId, $languageId) + { + // org_glizy_dataAccessDoctrine_DataAccess::enableLogging(); + $menu = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Menu') + ->load('getMenu', array('menuId' => $menuId, 'languageId' => $languageId)) + ->first(); + +// TODO: lanciare un'eccezione se il menù non è trovato + return $menu; + } + + + /** + * Get child menus from id + * + * @return org.glizy.dataAccessDoctrine.RecordIterator + */ + public function getChildMenusFromId($menuId, $languageId, $skipBlock=true) + { + // org_glizy_dataAccessDoctrine_DataAccess::enableLogging(); + $menus = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Menu') + ->load($skipBlock ? 'getChildMenusNoBlock' : 'getChildMenus', array(':menuId' => $menuId, ':languageId' => $languageId)); + +// TODO: lanciare un'eccezione se il menù non è trovato + return $menus; + } + + + /** + * Move a menu in a new position + */ + public function moveMenu($menuId, $position, $parentId) + { + // load the menu from DB + $menu = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Menu'); + $menu->load($menuId); + // set the parent and the order +// TODO: lanciare un'eccezione se il menù non è trovato + $menu->menu_parentId = $parentId; + $menu->menu_order = $position; + $menu->save(); + + // reorder the children menus + $menus = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Menu'); + $menus->load('getChildrenMenuInOrder', array('menuId' => $parentId)); +// TODO: lanciare un'eccezione se il parent trovato + $pos = 0; + foreach ($menus as $menu) { + if ($menuId == $menu->menu_id) continue; + if ($position == $pos) $pos++; + $menu->menu_order = $pos; + $menu->save(); + $pos++; + } + $this->invalidateSitemapCache(); + + $evt = array('type' => org_glizycms_contents_events_Menu::MOVE, 'data' => $menuId); + $this->dispatchEvent($evt); + } + + /** + * Delete a menu + * @param int $menuId the menu id + */ + public function deleteMenu($menuId) + { + // cancella prima i nodi figli + $menus = $this->getChildMenusFromId($menuId, org_glizy_ObjectValues::get('org.glizy', 'languageId'), false); + foreach ($menus as $ar) { + $this->deleteMenu($ar->menu_id); + } + $menu = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Menu'); + $menu->delete($menuId); + + $contentProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.ContentProxy'); + $contentProxy->deleteContent($menuId); + $this->invalidateSitemapCache(); + + $evt = array('type' => org_glizycms_contents_events_Menu::DELETE, 'data' => $menuId); + $this->dispatchEvent($evt); + } + + /** + * Add a new menu + * + * @param string $title the menu title + * @param int $parent the menu parent id + * @param string $pageType the menu pageType + * @return int new menu id + */ + public function addMenu($title, $parent, $pageType, $type='PAGE') { + $userId = org_glizy_ObjectValues::get('org.glizy', 'userId'); + + $menus = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Menu'); + $menus->load('getChildrenMenuInOrder', array('params' => array('menuId' => $parent))); + $order = $menus->count()+1; + + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $user = $application->getCurrentUser(); + + // add the menu + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Menu'); + $ar->menu_parentId = $parent; + $ar->menu_pageType = $pageType; + $ar->menu_order = $order; + $ar->menu_type = $type; + $ar->menu_hasPreview= '1'; + $ar->menu_url = ''; + $ar->menu_creationDate = new org_glizy_types_DateTime(); + $ar->menu_modificationDate = new org_glizy_types_DateTime(); + + $ar->menudetail_title = $title; + $ar->menudetail_isVisible = $user->acl(__Config::get('SITEMAP_ID'), 'publish') === true ? 1 : 0; + + $pageId = $ar->save(); + + // reorder all brothers menus + $this->moveMenu($pageId, $order, $parent); + + /* + // add the details for each languages + $languages = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language'); + $languages->select('*')->orderBy('language_order'); + foreach ($languages as $ar) { + $ar2 = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.MenuDetail'); + $ar2->menudetail_FK_menu_id = $pageId; + $ar2->menudetail_FK_language_id = $ar->language_id; + $ar2->menudetail_title = $title; + +// TODO dublin core + // if ( !empty( $values['pageParent'] ) ) + // { + // $arParent = org_glizy_ObjectFactory::createModel('org.glizy.models.MenuDetail'); + // $arParent->modifyField('menudetail_FK_language_id', 'defaultSelectValue', NULL); + // $result = $arParent->find(array('menudetail_FK_menu_id' => $values['pageParent'], 'menudetail_FK_language_id' => $this->_application->getEditingLanguageId())); + + // $ar2->menudetail_keywords = $arParent->menudetail_keywords; + // $ar2->menudetail_description = $arParent->menudetail_description; + // $ar2->menudetail_subject = $arParent->menudetail_subject; + // $ar2->menudetail_creator = $arParent->menudetail_creator; + // $ar2->menudetail_publisher = $arParent->menudetail_publisher; + // $ar2->menudetail_contributor = $arParent->menudetail_contributor; + // $ar2->menudetail_type = $arParent->menudetail_type; + // $ar2->menudetail_identifier = $arParent->menudetail_identifier; + // $ar2->menudetail_source = $arParent->menudetail_source; + // $ar2->menudetail_relation = $arParent->menudetail_relation; + // $ar2->menudetail_coverage = $arParent->menudetail_coverage; + // } + // else + // { + // $ar2->menudetail_keywords = ''; + // $ar2->menudetail_description = ''; + // $ar2->menudetail_subject = ''; + // $ar2->menudetail_creator = ''; + // $ar2->menudetail_publisher = ''; + // $ar2->menudetail_contributor = ''; + // $ar2->menudetail_type = ''; + // $ar2->menudetail_identifier = ''; + // $ar2->menudetail_source = ''; + // $ar2->menudetail_relation = ''; + // $ar2->menudetail_coverage = ''; + // } + +// TODO acl associare a publish su sitemap + $ar2->menudetail_isVisible = 1; //$user->acl('SiteMap','visible')===true ? '1' : '0'; + $ar2->save(); + } + */ + + // if ( __Config::get( 'ACL_ENABLED' ) ) + // { + // __Session::remove( 'glizy.aclBack' ); + // __Session::remove( 'glizy.aclFront' ); + // } + + $this->invalidateSitemapCache(); + $evt = array('type' => org_glizycms_contents_events_Menu::ADD, 'data' => $pageId); + $this->dispatchEvent($evt); + + return $pageId; + } + + public function showHide($menuId, $languageId, $isShown) + { + $menus = $this->getChildMenusFromId($menuId, org_glizy_ObjectValues::get('org.glizy', 'languageId'), false); + foreach ($menus as $ar) { + $this->showHide($ar->menu_id, $languageId, $isShown); + } + + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.MenuDetail'); + if ($ar->find( array( + 'menudetail_FK_menu_id' => $menuId, + 'menudetail_FK_language_id' => $languageId ))) { + + $ar->menudetail_isVisible = $isShown ? 1 : 0; + $ar->save(); + $this->invalidateSitemapCache(); + } +// TODO controlare che il menù esiste + } + + + public function lockUnlock($menuId, $state) { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Menu'); + if ($ar->load($menuId)) { + $ar->menu_isLocked = $state ? 1 : 0; + $ar->save(); + $this->invalidateSitemapCache(); + } +// TODO controlare che il menù esiste + } + + + public function touch($menuId) { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Menu'); + if ($ar->load($menuId)) { + $ar->menu_modificationDate = new org_glizy_types_DateTime(); + $ar->save(); + } + } + + public function rename($menuId, $languageId, $title) { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.MenuDetail'); + if ($ar->find( array( + 'menudetail_FK_menu_id' => $menuId, + 'menudetail_FK_language_id' => $languageId ))) { + + $ar->menudetail_title = $title; + $ar->save(); + $this->invalidateSitemapCache(); + + $evt = array('type' => org_glizycms_contents_events_Menu::RENAME, 'data' => $pageId); + $this->dispatchEvent($evt); + } +// TODO controlare che il menù esiste + } + + public function invalidateSitemapCache() + { + $evt = array('type' => org_glizycms_contents_events_Menu::INVALIDATE_SITEMAP); + $this->dispatchEvent($evt); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/models/proxy/ModuleContentProxy.php b/src/core/classes/org/glizycms/contents/models/proxy/ModuleContentProxy.php new file mode 100644 index 0000000..7ac5f9d --- /dev/null +++ b/src/core/classes/org/glizycms/contents/models/proxy/ModuleContentProxy.php @@ -0,0 +1,136 @@ +<?php +class org_glizycms_contents_models_proxy_ModuleContentProxy extends GlizyObject +{ + // restituisce true se è valido + // altrimenti un array con gli errori di validazione + public function validate($data, $model) + { + $document = org_glizy_objectFactory::createModel($model); + + try { + $document->validate($data); + } catch (org_glizy_validators_ValidationException $e) { + return $e->getErrors(); + } + + return true; + } + + public function loadContent($recordId, $model, $status='PUBLISHED') + { + $document = org_glizy_objectFactory::createModel($model); + $result = $document->load($recordId, $status); + + if (!$result) { + $languageProxy = __ObjectFactory::createObject('org.glizycms.languages.models.proxy.LanguagesProxy'); + $document->load($recordId, $status, $languageProxy->getDefaultLanguageId()); + } + + $values = $document->getValuesAsArray(); + + if (__Config::get('ACL_MODULES')) { + // caricamento permessi editing e visualizzazione record + $ar = org_glizy_objectFactory::createModel('org.glizycms.contents.models.DocumentACL'); + $ar->load($recordId); + + $values['__aclEdit'] = $this->getPermissionName($ar->__aclEdit); + $values['__aclView'] = $this->getPermissionName($ar->__aclView); + } + + return $values; + } + + private function getPermissionName($permissions) + { + $names = array(); + $permissions = explode(',', $permissions); + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.roleManager.models.Role'); + foreach ($permissions as $v) { + if ($ar->load($v)) { + $names[] = array ( + 'id' => $ar->role_id, + 'text' => $ar->role_name + ); + } + } + + return $names; + } + + public function saveContent($data, $publish=true) + { + $recordId = $data->__id; + $model = $data->__model; + + $document = org_glizy_objectFactory::createModel($model); + $result = $document->load($recordId, 'LAST_MODIFIED'); + + if (!$result) { + $languageProxy = __ObjectFactory::createObject('org.glizycms.languages.models.proxy.LanguagesProxy'); + $defaultLanguageId = $languageProxy->getDefaultLanguageId(); + $document->load($recordId, 'LAST_MODIFIED', $defaultLanguageId); + $document->setLanguage($languageProxy->getLanguageId()); + } + + if (property_exists($data, 'title')) { + $document->title = $data->title; + } + + if (property_exists($data, 'url')) { + $document->url = $data->url; + } + + $document->fulltext = org_glizycms_core_helpers_Fulltext::make($data, $document, true); + try { + if ($publish) { + $id = $document->publish(); + } else { + if (__Config::get('glizycms.content.history')) { + $id = $document->saveHistory(); + } else { + $id = $document->save(); + } + } + + if (__Config::get('ACL_MODULES')) { + // gestione acl record + $ar = org_glizy_objectFactory::createModel('org.glizycms.contents.models.DocumentACL'); + $ar->load($id); + $ar->__aclEdit = $data->__aclEdit; + $ar->__aclView = $data->__aclView; + $ar->save(); + } + } + catch (org_glizy_validators_ValidationException $e) { + return $e->getErrors(); + } + + return array('__id' => $id); + } + + public function delete($recordId, $model='') + { + if (__Config::get('ACL_MODULES')) { + // cancella i permessi di editing e visualizzazione record + // TODO gestire le relazioni in ActiveRecordDocument cosicché questo codice venga automaticamente gestito + // dal delete sul document + $ar = org_glizy_objectFactory::createModel('org.glizycms.contents.models.DocumentACL'); + $ar->load($recordId); + $ar->__aclEdit = array(); + $ar->__aclView = array(); + $ar->save(); + } + + // cancella il document; + $document = org_glizy_objectFactory::createModel(!$model ? 'org.glizycms.core.models.Content' : $model); + $document->delete($recordId); + } + + public function toggleVisibility($recordId, $model='') + { + $document = org_glizy_objectFactory::createModel(!$model ? 'org.glizycms.core.models.Content' : $model); + $document->load($recordId); + $document->setVisible($document->isVisible() ? 0 : 1); + $document->save(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/services/PageTypeService.php b/src/core/classes/org/glizycms/contents/services/PageTypeService.php new file mode 100644 index 0000000..25e8dc6 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/services/PageTypeService.php @@ -0,0 +1,61 @@ +<?php +class org_glizycms_contents_services_PageTypeService extends GlizyObject +{ + protected $source = null; + protected $pageTypesMap = array(); + + public function __construct() + { + $this->source = __Paths::get('APPLICATION').'config/pageTypes.xml'; + + if (file_exists($this->source)) { + $options = array( + 'cacheDir' => org_glizy_Paths::get('CACHE_CODE'), + 'lifeTime' => -1, + 'readControlType' => '', + 'fileExtension' => '.php' + ); + $cacheObj = &org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFile', $options ); + $cacheFileName = $cacheObj->verify( $this->_source, get_class( $this ) ); + + if ( $cacheFileName === false ) + { + $this->loadXml(); + $cacheObj->save( serialize( $this->pageTypesMap ), NULL, get_class( $this ) ); + $cacheObj->getFileName(); + } + else + { + $this->pageTypesMap = unserialize( file_get_contents( $cacheFileName ) ); + } + } + } + + function onRegister() { + + } + + private function loadXml() { + $xml = org_glizy_ObjectFactory::createObject('org.glizy.parser.XML'); + $xml->loadAndParseNS($this->source); + $pageTypes = $xml->getElementsByTagName('pageType'); + + $this->pageTypesMap = array(); + + foreach ($pageTypes as $pageType) { + $name = $pageType->getAttribute('name'); + $this->pageTypesMap[$name] = array ( + 'name' => $name, + 'label' => $pageType->hasAttribute('label') ? __T($pageType->getAttribute('label')) : $pageType->getAttribute('name'), + 'class' => $pageType->getAttribute('class'), + 'unique' => $pageType->hasAttribute('unique') ? $pageType->getAttribute('unique') == 'true' : false, + 'acceptParent' => $pageType->hasAttribute('acceptParent') ? $pageType->getAttribute('acceptParent') : '' + ); + } + } + + public function getAllPageTypes() + { + return $this->pageTypesMap; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/views/ContentsEdit.xml b/src/core/classes/org/glizycms/contents/views/ContentsEdit.xml new file mode 100644 index 0000000..d449ab8 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/ContentsEdit.xml @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="org.glizycms.contents.views.components.*" + xmlns:t="org.glizycms.template.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Popup.php"> + <glz:Import src="_common.xml" /> + <glz:JSscript folder="org.glizycms.contents.js" /> + + <mvc:StateTabNavigation id="tabs" cssClass="nav nav-tabs" cssClassCurrent="active" addQueryString="true" visible="true" /> + + <mvc:State name="index"> + <glz:Modifier target="Page" attribute="templateFileName" value="Page.php" /> + <glz:Modifier target="tabs" attribute="visible" value="false" /> + <glz:Modifier target="pageTitle" attribute="visible" value="false" /> + <m:SiteTreeView id="treeview" editableRegion="treeview" controllerName="org.glizycms.contents.controllers.siteTree.*" /> + <m:PageEdit id="pageEdit" mode="container" /> + </mvc:State> + + <mvc:State name="empty"> + <glz:Modifier target="tabs" attribute="visible" value="false" /> + <glz:LongText><![CDATA[]]></glz:LongText> + </mvc:State> + + <mvc:State name="add"> + <glz:Modifier target="tabs" attribute="visible" value="false" /> + <cms:FormEdit id="myForm" controllerName="org.glizycms.contents.controllers.pageEdit.*"> + <cms:pageTitleModifier action="add" label="{i18n:Add a new page}" new="true" /> + + <glz:Input id="title" label="{i18n:GLZ_PAGE_TITLE}" size="90" required="true" /> + <cms:SelectPage id="pageParent" label="{i18n:GLZ_PAGE_SELECT_PARENT}" required="true" /> + <cms:SelectPageTypeNew id="pageType" label="{i18n:GLZ_PAGE_SELECT_TYPE}" required="true" linked="pageParent" /> + + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=add" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="addblock"> + <glz:Modifier target="tabs" attribute="visible" value="false" /> + <cms:FormEdit id="myForm" controllerName="org.glizycms.contents.controllers.pageEdit.*"> + <cms:pageTitleModifier action="addblock" label="{i18n:Aggiungi un nuovo plugin}" new="true" /> + + <glz:Input id="title" label="{i18n:GLZ_PAGE_TITLE}" size="90" required="true" /> + <glz:Hidden id="pageParent" /> + <cms:SelectPageTypeNew id="pageType" label="{i18n:GLZ_PAGE_SELECT_TYPE}" required="true" linked="pageParent" onlyWithParent="true" /> + + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=addblock" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="edit" label="{i18n:Content}"> + <m:PageEdit id="pageEdit" mode="edit" controllerName="org.glizycms.contents.controllers.pageEdit.*"> + <cms:pageTitleModifier action="edit" label="{i18n:Edit page}" field="__title" /> + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <glz:HtmlButton id="saveAndClose" label="{i18n:GLZ_SAVE_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=saveClose" /> + <glz:Link id="preview" label="{i18n:GLZ_PREVIEW}" cssClass="btn" visible="false" target="_blank" /> + <!-- + <glz:HtmlButton label="{i18n:GLZ_SAVE_DRAFT}" type="button" cssClass="btn js-glizycms-save" data="action=saveDraft" /> + <glz:HtmlButton label="{i18n:GLZ_PREVIEW}" type="button" cssClass="btn js-glizycms-preview pull-right" data="action=preview" /> + --> + </cms:FormButtonsPanel> + </m:PageEdit> + </mvc:State> + + <mvc:State id="propertiesState" name="properties" label="{i18n:Properties}"> + <cms:FormEdit id="myForm" controllerName="org.glizycms.contents.controllers.pageEdit.*"> + <cms:pageTitleModifier action="properties" label="{i18n:Edit properties}" field="menudetail_title" /> + <glz:Hidden id="menu_id" /> + <glz:Input id="menudetail_title" label="{i18n:GLZ_PAGE_TITLE}" size="90" required="true" /> + <glz:Input id="menudetail_titleLink" label="{i18n:GLZ_PAGE_TITLE_LINK}" size="90" /> + <glz:Input id="menudetail_linkDescription" label="{i18n:GLZ_PAGE_TITLE_ALT}" size="90" /> + <glz:Input id="menu_cssClass" label="{i18n:Menu css class}" size="90" /> + <glz:Input id="menu_url" label="{i18n:GLZ_LINKED_URL}" size="90" /> + <glz:Date id="menu_creationDate" label="{i18n:GLZ_CREATION_DATE}" /> + <glz:Checkbox id="menu_isLocked" label="{i18n:GLZ_PROTECTED_PAGE}" data="type=checkbox" /> + <!-- + <glz:Checkbox id="menu_hasComment" label="{i18n:GLZ_ENABLE_PAGE_COMMENTS}" data="type=checkbox" /> + <glz:Checkbox id="menu_printPdf" label="{i18n:GLZ_PRINT_PDF}" data="type=checkbox" /> + --> + <cms:SelectPageTypeNew id="menu_pageType" label="{i18n:GLZ_PAGE_SELECT_TYPE}" showAllPageTypes="true" required="true" /> + <glz:Fieldset cssClass="dublinCoreBox" label="{i18n:MW_DUBLIN_CORE}"> + <glz:Input id="menudetail_keywords" label="{i18n:MW_DC_KEYWORDS}" size="90" /> + <glz:Input id="menudetail_description" label="{i18n:MW_DC_SHORTDESCRIPTION}" size="90" /> + <glz:Input id="menudetail_subject" label="{i18n:MW_DC_SUBJECT}" size="90" /> + <glz:Input id="menudetail_creator" label="{i18n:MW_DC_CREATOR}" size="90" /> + <glz:Input id="menudetail_publisher" label="{i18n:MW_DC_PUBLISHER}" size="90" /> + <glz:Input id="menudetail_contributor" label="{i18n:MW_DC_CONTRIBUTOR}" size="90" /> + <glz:Input id="menudetail_type" label="{i18n:MW_DC_TYPE}" size="90" /> + <glz:Input id="menudetail_identifier" label="{i18n:MW_DC_IDENTIFIER}" size="90" /> + <glz:Input id="menudetail_source" label="{i18n:MW_DC_SOURCE}" size="90" /> + <glz:Input id="menudetail_relation" label="{i18n:MW_DC_RELATION}" size="90" /> + <glz:Input id="menudetail_coverage" label="{i18n:MW_DC_COVERAGE}" size="90" /> + </glz:Fieldset> + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=saveProperties" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="history" label="{i18n:History}" draw="{config:glizycms.content.history}"> + <cms:FormEdit id="history" addValidationJs="false"> + <cms:pageTitleModifier action="history" label="{i18n:History}" /> + <m:ShowHistory id="history" /> + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:Confronta}" type="button" cssClass="btn btn-primary js-glizycms-history" data="action=add" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State id="templateState" name="template" label="{i18n:Templates and colors}" controllerName="org.glizycms.template.controllers.CheckTemplateTabDraw"> + <t:TemplateEdit id="templateEdit" controllerName="org.glizycms.template.controllers.*"> + <cms:pageTitleModifier action="template" label="{i18n:Edit layout}" /> + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <!--<glz:HtmlButton id="loadFromParent" label="{i18n:MW_LOAD_PARENT}" type="submit" cssClass="btn" value="loadFromParent" />--> + </cms:FormButtonsPanel> + </t:TemplateEdit> + </mvc:State> + + <mvc:State name="permissions" label="{i18n:Permissions}" draw="{config:ACL_ROLES}"> + <cms:FormEdit id="myForm" controllerName="org.glizycms.contents.controllers.pageEdit.*"> + <glz:Hidden id="menuId" /> + <glz:Fieldset label="Permessi di modifica (Back-end)" cssClass="permessi"> + <glz:Input id="aclBack" label="{i18n:Ruoli}" data="type=selectfrom;multiple=true;model=org.glizycms.roleManager.models.Role;field=role_name;get_id=true" size="255" /> + <glz:Checkbox id="extendsPermissions" label="Estendi permessi alle pagine figlie" data="type=checkbox"/> + </glz:Fieldset> + <glz:Fieldset label="Permessi di visualizzazione (Front-end)" cssClass="permessi"> + <glz:Input id="aclFront" label="{i18n:Ruoli}" data="type=selectfrom;multiple=true;model=org.glizycms.roleManager.models.Role;field=role_name;get_id=true" size="255" /> + </glz:Fieldset> + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=savePermissions" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> +</mvc:Page> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/views/components/PageEdit.php b/src/core/classes/org/glizycms/contents/views/components/PageEdit.php new file mode 100644 index 0000000..1d0cf86 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/components/PageEdit.php @@ -0,0 +1,169 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_contents_views_components_PageEdit extends org_glizycms_views_components_FormEdit +{ + protected $emptySrc; + protected $editSrc; + protected $_pageTypeObj; + protected $allowBlocks; + protected $menuId; + + /** + * Init + * + * @return void + * @access public + */ + public function init() + { + $this->defineAttribute('mode', false, 'container', COMPONENT_TYPE_STRING); + $this->defineAttribute('initialState', false, 'empty', COMPONENT_TYPE_STRING); + $this->defineAttribute('editState', false, 'edit', COMPONENT_TYPE_STRING); + $this->defineAttribute('editUrl', false, __Config::get('glizycms.speakingUrl'), COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:cssClass', false, __Config::get('glizy.formElement.admCssClass'), COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + public function process() { + if ($this->getAttribute('mode')=='container') { + $this->emptySrc = __Routing::makeUrl('linkChangeAction', array( 'action' => $this->getAttribute('initialState'))); + $this->editSrc = __Routing::makeUrl('linkChangeAction', array( 'action' => $this->getAttribute('editState'))).'?menuId='; + } else { + $this->menuId = __Request::get('menuId'); +// TODO: lanciare un'eccezione se l'id non è valido + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $menu = $menuProxy->getMenuFromId($this->menuId, org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId')); +// TODO: il menù viene letto due volte, in questo codice ed in readContentFromMenu + $contentProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.ContentProxy'); + $content = $contentProxy->readContentFromMenu($this->menuId, org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId')); + $this->setData($content); + + $this->addComponentsToEdit($menu); + parent::process(); + } + } + + public function render_html_onStart() + { + if ($this->getAttribute('mode')=='container') { + + $this->addOutputCode('<iframe id="js-glizycmsPageEdit" src="" data-emptysrc="'.$this->emptySrc.'" data-editsrc="'.$this->editSrc.'"></iframe>'); + + $corePath = __Paths::get('CORE'); + $jQueryPath = $corePath.'classes/org/glizycms/js/jquery/'; + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'jquery.pnotify/jquery.pnotify.min.js' ) ); + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'jquery.pnotify/jquery.pnotify.default.css' ) ); + + } else { + // TODO: verificare se è da rimuovere + $this->addOutputCode('<div id="message-box"></div>'); + parent::render_html_onStart(); + } + } + + public function render_html_onEnd($value='') + { + if ($this->getAttribute('mode')!='container') { + parent::render_html_onEnd(); + + if ($this->allowBlocks) { + $this->addOutputCode('<div class="js-glizycmsBlocksEdit" data-menuid="'.$this->menuId.'" data-ajaxurl="'.$this->getAjaxUrl().'"></div>'); + } + } + } + + function addComponentsToEdit($menu) + { + $templatePath = org_glizycms_Glizycms::getSiteTemplatePath(); + $originalRootComponent = &$this->_application->getRootComponent(); + $originalChildren = $this->childComponents; + $this->childComponents = array(); + + $this->addDefaultComponents($menu); + + $this->_pageTypeObj = &org_glizy_ObjectFactory::createPage($this->_application, + $menu->menu_pageType, + org_glizy_Paths::get('APPLICATION_TO_ADMIN_PAGETYPE'), + array( 'idPrefix' => $this->getId().'-', + 'skipImport' => true, + 'pathTemplate' => $templatePath, + 'mode' => 'edit' ) ); + + $rootComponent = &$this->_application->getRootComponent(); + $rootComponent->init(); + $this->_application->_rootComponent = &$originalRootComponent; + $editComponents = $rootComponent->getAttribute('adm:editComponents'); + $this->allowBlocks = $rootComponent->getAttribute('allowBlocks'); + if (count($editComponents)) + { + foreach($editComponents as $id) + { + $component = &$rootComponent->getComponentById($this->getId().'-'.$id); + if (!is_object($component)) continue; + $component->remapAttributes($this->getId().'-'); + $this->addChild($component); + $component->_parent = &$this; + $component->setAttribute('visible', true); + } + } + else + { + for($i=0; $i<count($rootComponent->childComponents); $i++) + { + $rootComponent->childComponents[$i]->remapAttributes($this->getId().'-'); + $this->addChild($rootComponent->childComponents[$i]); + $rootComponent->childComponents[$i]->_parent = &$this; + } + } + + $this->childComponents = array_merge($this->childComponents, $originalChildren); + } + + private function addDefaultComponents($menu) { + $id = '__id'; + $c = org_glizy_ObjectFactory::createComponent('org.glizy.components.Hidden', $this->_application, $this, 'glz:Hidden', $id, $id); + $this->addChild($c); + $c->init(); + + $id = '__indexFields'; + $childs[$id] = org_glizy_ObjectFactory::createComponent('org.glizy.components.Hidden', $this->_application, $this, 'glz:Hidden', $id, $id); + $c = &$childs[$id]; + $this->addChild($c); + $c->init(); + + $id = '__title'; + $childs[$id] = org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $id, $id); + $c = &$childs[$id]; + $c->setAttribute('label', __T('Title')); + $c->setAttribute('required', true); + $c->setAttribute('size', '90'); + $c->setAttribute('cssClass', $this->getAttribute('adm:cssClass')); + $this->addChild($c); + $c->init(); + + + $id = '__url'; + if ($this->getAttribute('editUrl')) { + $childs[$id] = org_glizy_ObjectFactory::createComponent('org.glizy.components.Input', $this->_application, $this, 'glz:Input', $id, $id); + } else { + $childs[$id] = org_glizy_ObjectFactory::createComponent('org.glizy.components.Hidden', $this->_application, $this, 'glz:Hidden', $id, $id); + } + $c = &$childs[$id]; + $c->setAttribute('label', __T('URL')); + $c->setAttribute('required', false); + $c->setAttribute('size', '90'); + $c->setAttribute('cssClass', $this->getAttribute('adm:cssClass')); + $this->addChild($c); + $c->init(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/views/components/ShowHistory.php b/src/core/classes/org/glizycms/contents/views/components/ShowHistory.php new file mode 100644 index 0000000..e8dfb64 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/components/ShowHistory.php @@ -0,0 +1,93 @@ +<?php +class org_glizycms_contents_views_components_ShowHistory extends org_glizy_components_ComponentContainer +{ + function render() + { + $menuId = __Request::get('menuId'); + + // TODO spostare nel model + $it = org_glizy_objectFactory::createModelIterator('org.glizycms.core.models.Content'); + $it->addSelect('u.*') + ->join($it::DOCUMENT_TABLE_ALIAS, __Config::get('DB_PREFIX').'users_tbl', 'u', + $it->expr()->eq($it::DOCUMENT_DETAIL_TABLE_ALIAS.'.'.$it::DOCUMENT_DETAIL_FK_USER, 'u.user_id')) + ->where("id", $menuId) + ->orderBy('document_detail_modificationDate', 'DESC') + ->allStatuses(); + + // TODO localizzare + $output = '<table class="table table-bordered table-striped">'; + $output .= '<thead><tr><th>Aggiornato da</th><th>Commento</th><th width="140">Data modifica</th></tr></thead>'; + $output .= '<tbody>'; + + foreach ($it as $ar) { + $output .= '<tr>'. + '<td><input type="radio" name="history_a" value="'.$ar->document_detail_id.'" /> '. + '<input type="radio" name="history_b" value="'.$ar->document_detail_id.'" /> '. + $ar->user_firstName.' '.$ar->user_lastName.'</td>'. + '<td></td>'. + // '<td>'.$ar->document_detail_note.'</td>'. + '<td>'.$ar->document_detail_modificationDate.'</td>'. + '</tr>'; + } + + $output .= '</tbody>'; + $output .= '</table>'; + $output .= '<div id="diff"></div>'; + + $ajaxUrl = $this->getAjaxUrl(); + $output .= <<<EOD +<script> +$(function(){ + $('input.js-glizycms-history').click(function(e){ + e.preventDefault(); + var a = $('input[name=history_a]:checked').val(); + var b = $('input[name=history_b]:checked').val(); + if (a && b && a!=b) { + $.ajax({ + 'url': '$ajaxUrl', + 'data': {a: a, b: b}, + 'dataType': 'html', + 'success': function(data) { + $("#diff").html(data); + } + }); + } + }); +}); +</script> +EOD; + $this->addOutputCode($output); + } + + public function process_ajax() + { + $a = __Request::get('a'); + $b = __Request::get('b'); + + $it = org_glizy_objectFactory::createModelIterator('org.glizycms.core.models.Content'); + $it->where("document_detail_id", $a) + ->allStatuses(); + $ar_a = $it->first(); + + $it = org_glizy_objectFactory::createModelIterator('org.glizycms.core.models.Content'); + $it->where("document_detail_id", $b) + ->allStatuses(); + $ar_b = $it->first(); + + $a = explode("\n", str_replace("<\/p>", "<\/p>\n", json_encode(json_decode($ar_a->document_detail_object), JSON_PRETTY_PRINT))); + $b = explode("\n", str_replace("<\/p>", "<\/p>\n", json_encode(json_decode($ar_b->document_detail_object), JSON_PRETTY_PRINT))); + + glz_importLib('Diff/Diff.php'); + glz_importLib('Diff/Diff/Renderer/Html/SideBySide.php'); + // Options for generating the diff + $options = array( + //'ignoreWhitespace' => true, + //'ignoreCase' => true, + ); + $diff = new Diff($a, $b, $options); + + $renderer = new Diff_Renderer_Html_SideBySide; + $result = $diff->Render($renderer); + return array('html' => $result); + } +} diff --git a/src/core/classes/org/glizycms/contents/views/components/SiteTreeView.php b/src/core/classes/org/glizycms/contents/views/components/SiteTreeView.php new file mode 100644 index 0000000..fc61d8a --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/components/SiteTreeView.php @@ -0,0 +1,75 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_contents_views_components_SiteTreeView extends org_glizy_components_Component +{ + /** + * Init + * + * @return void + * @access public + */ + public function init() + { + $this->defineAttribute('addLabel', false, '{i18n:glizycms.Add Page}', COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, '{i18n:glizycms.Site Structure}', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + public function process() { + $this->_content = new org_glizycms_contents_views_components_SiteTreeViewVO(); + $this->_content->addLabel = $this->getAttribute('addLabel'); + $this->_content->title = $this->getAttribute('title'); + $this->_content->ajaxUrl = $this->getAjaxUrl(); + $this->_content->addUrl = __Routing::makeUrl('linkChangeAction', array('action' => 'add')); + } + + public function render($outputMode=NULL, $skipChilds=false) { + parent::render($outputMode, $skipChilds); + if (!org_glizy_ObjectValues::get('org.glizycms.js', 'jsTree', false)) + { + org_glizy_ObjectValues::set('org.glizycms.js', 'jsTree', true); + $this->addOutputCode( org_glizy_helpers_JS::linkStaticJSfile( 'jquery/jquery-jstree/jquery.jstree.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkStaticJSfile( 'jquery/jquery-jstree/jquery.cookie.js' ) ); + } + } +} + +class org_glizycms_contents_views_components_SiteTreeViewVO +{ + public $addLabel; + public $title; + public $ajaxUrl; + public $addUrl; +} + +class org_glizycms_contents_views_components_SiteTreeView_render extends org_glizy_components_render_Render +{ + function getDefaultSkin() + { + $skin = <<<EOD +<div id="treeview"> + <div id="treeview-title"> + <a id="js-glizycmsSiteTreeAdd" tal:attributes="href Component/addUrl"><i class="icon-plus"></i> <span tal:omit-tag="" tal:content="Component/addLabel" /></a> + <h3 tal:content="Component/title"></h3> + </div> + <div id="treeview-inner"> + <div id="js-glizycmsSiteTree" tal:attributes="data-ajaxurl Component/ajaxUrl"></div> + </div> + <div id="openclose"> + <i class="icon-chevron-left"></i> + </div> +</div> +EOD; + return $skin; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/contents/views/renderer/AbstractCellEdit.php b/src/core/classes/org/glizycms/contents/views/renderer/AbstractCellEdit.php new file mode 100644 index 0000000..79bad0b --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/renderer/AbstractCellEdit.php @@ -0,0 +1,116 @@ +<?php +// TODO: spostare in un path più corretto non dentro contents +abstract class org_glizycms_contents_views_renderer_AbstractCellEdit extends org_glizy_components_render_RenderCell +{ + protected $canView = true; + protected $canEdit = true; + protected $canDelete = true; + + protected function loadAcl($key) + { + // TODO: posstare questa parte di codice in un classe comune + // e gestire in modo simile quando sono attivi i ruoli e quando no + $pageId = $this->application->getPageId(); + if (__Config::get('ACL_ROLES')) { + if (!$this->user->acl($pageId, 'all')) { + $this->canView = $this->user->acl($pageId, 'visible'); + $this->canEdit = $this->user->acl($pageId, 'edit'); + $this->canDelete = $this->user->acl($pageId, 'delete'); + + if ($this->canView) { + $ar = org_glizy_objectFactory::createModel('org.glizycms.contents.models.DocumentACL'); + $ar->load($key); + + if ($ar->__aclEdit) { + $roles = explode(',', $ar->__aclEdit); + $this->canEdit = $this->canDelete = $this->user->isInRoles($roles); + } + } + } + } else { + $this->canView = $this->user->acl($pageId, 'visible'); + $this->canEdit = $this->user->acl($pageId, 'edit'); + $this->canDelete = $this->user->acl($pageId, 'delete'); + } + } + + protected function renderEditButton($key, $row, $enabled = true) + { + $output = ''; + if ($this->canView && $this->canEdit) { + $output = __Link::makeLinkWithIcon( + 'actionsMVC', + __Config::get('glizy.datagrid.action.editCssClass').($enabled ? '' : ' disabled'), + array( + 'title' => __T('GLZ_RECORD_EDIT'), + 'id' => $key, + 'action' => 'edit' + ) + ); + } + + return $output; + } + + protected function renderEditDraftButton($key, $row, $enabled = true) + { + $output = ''; + if ($this->canView && $this->canEdit) { + $output = __Link::makeLinkWithIcon( + 'actionsMVC', + __Config::get('glizy.datagrid.action.editDraftCssClass').($enabled ? '' : ' disabled'), + array( + 'title' => __T('GLZ_RECORD_EDIT_DRAFT'), + 'id' => $key, + 'action' => 'editDraft' + ) + ); + } + + return $output; + } + + protected function renderDeleteButton($key, $row) + { + $output = ''; + if ($this->canView && $this->canDelete) { + $output .= __Link::makeLinkWithIcon( 'actionsMVCDelete', + __Config::get('glizy.datagrid.action.deleteCssClass'), + array( + 'title' => __T('GLZ_RECORD_DELETE'), + 'id' => $key, + 'model' => $row->getClassName(false), + 'action' => 'delete' ), + __T('GLZ_RECORD_MSG_DELETE') ); + } + + return $output; + } + + protected function renderVisibilityButton($key, $row) + { + $output = ''; + if ($this->canView && $this->canEdit) { + $output .= __Link::makeLinkWithIcon( 'actionsMVCToggleVisibility', + __Config::get($row->isVisible() ? 'glizy.datagrid.action.showCssClass' : 'glizy.datagrid.action.hideCssClass'), + array( + 'title' => $row->isVisible() ? __T('Hide') : __T('Show'), + 'id' => $key, + 'model' => $row->getClassName(false), + 'action' => 'togglevisibility' )); + } + + return $output; + } + + protected function renderCheckBox($key, $row) + { + $output = ''; + if ($this->canView && $this->canDelete) { + $output .= '<input name="check[]" data-id="'.$row->getId().'" type="checkbox">'; + } + + return $output; + } +} + diff --git a/src/core/classes/org/glizycms/contents/views/renderer/CellDelete.php b/src/core/classes/org/glizycms/contents/views/renderer/CellDelete.php new file mode 100644 index 0000000..ccf42b5 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/renderer/CellDelete.php @@ -0,0 +1,12 @@ +<?php +class org_glizycms_contents_views_renderer_CellDelete extends org_glizycms_contents_views_renderer_AbstractCellEdit +{ + function renderCell($key, $value, $row) + { + $this->loadAcl($key); + $output = $this->renderDeleteButton($key, $row); + return $output; + } +} + + diff --git a/src/core/classes/org/glizycms/contents/views/renderer/CellEdit.php b/src/core/classes/org/glizycms/contents/views/renderer/CellEdit.php new file mode 100644 index 0000000..3a0afee --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/renderer/CellEdit.php @@ -0,0 +1,12 @@ +<?php +class org_glizycms_contents_views_renderer_CellEdit extends org_glizycms_contents_views_renderer_AbstractCellEdit +{ + function renderCell($key, $value, $row) + { + $this->loadAcl($key); + $output = $this->renderEditButton($key, $row); + return $output; + } +} + + diff --git a/src/core/classes/org/glizycms/contents/views/renderer/CellEditDelete.php b/src/core/classes/org/glizycms/contents/views/renderer/CellEditDelete.php new file mode 100644 index 0000000..c152eb6 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/renderer/CellEditDelete.php @@ -0,0 +1,13 @@ +<?php +class org_glizycms_contents_views_renderer_CellEditDelete extends org_glizycms_contents_views_renderer_AbstractCellEdit +{ + function renderCell($key, $value, $row) + { + $this->loadAcl($key); + $output = $this->renderEditButton($key, $row). + $this->renderDeleteButton($key, $row); + return $output; + } +} + + diff --git a/src/core/classes/org/glizycms/contents/views/renderer/CellEditDeleteVisible.php b/src/core/classes/org/glizycms/contents/views/renderer/CellEditDeleteVisible.php new file mode 100644 index 0000000..2db6144 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/renderer/CellEditDeleteVisible.php @@ -0,0 +1,13 @@ +<?php +class org_glizycms_contents_views_renderer_CellEditDeleteVisible extends org_glizycms_contents_views_renderer_AbstractCellEdit +{ + function renderCell($key, $value, $row) + { + $this->loadAcl($key); + $output = $this->renderEditButton($key, $row). + $this->renderDeleteButton($key, $row). + $this->renderVisibilityButton($key, $row); + return $output; + } +} + diff --git a/src/core/classes/org/glizycms/contents/views/renderer/CellEditDraftDelete.php b/src/core/classes/org/glizycms/contents/views/renderer/CellEditDraftDelete.php new file mode 100644 index 0000000..03c820c --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/renderer/CellEditDraftDelete.php @@ -0,0 +1,16 @@ +<?php +class org_glizycms_contents_views_renderer_CellEditDraftDelete extends org_glizycms_contents_views_renderer_AbstractCellEdit +{ + function renderCell($key, $value, $row) + { + $this->loadAcl($key); + + $output = $this->renderEditButton($key, $row, $row->hasPublishedVersion()). + $this->renderEditDraftButton($key, $row, $row->hasDraftVersion()). + $this->renderDeleteButton($key, $row); + + return $output; + } +} + + diff --git a/src/core/classes/org/glizycms/contents/views/renderer/CellEditDraftDeleteVisible.php b/src/core/classes/org/glizycms/contents/views/renderer/CellEditDraftDeleteVisible.php new file mode 100644 index 0000000..693ee4a --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/renderer/CellEditDraftDeleteVisible.php @@ -0,0 +1,17 @@ +<?php +class org_glizycms_contents_views_renderer_CellEditDraftDeleteVisible extends org_glizycms_contents_views_renderer_AbstractCellEdit +{ + function renderCell($key, $value, $row) + { + $this->loadAcl($key); + + $output = $this->renderEditButton($key, $row, $row->hasPublishedVersion()). + $this->renderEditDraftButton($key, $row, $row->hasDraftVersion()). + $this->renderDeleteButton($key, $row). + $this->renderVisibilityButton($key, $row); + + return $output; + } +} + + diff --git a/src/core/classes/org/glizycms/contents/views/renderer/DocumentTitle.php b/src/core/classes/org/glizycms/contents/views/renderer/DocumentTitle.php new file mode 100644 index 0000000..72026a2 --- /dev/null +++ b/src/core/classes/org/glizycms/contents/views/renderer/DocumentTitle.php @@ -0,0 +1,13 @@ +<?php +class org_glizycms_contents_views_renderer_DocumentTitle extends GlizyObject +{ + function renderCell( $key, $value, $row ) + { + if ($row->isTranslated()) { + return $value; + } + else { + return '<em>'.$value.'</em>'; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/core/application/AdminApplication.php b/src/core/classes/org/glizycms/core/application/AdminApplication.php new file mode 100644 index 0000000..523fb47 --- /dev/null +++ b/src/core/classes/org/glizycms/core/application/AdminApplication.php @@ -0,0 +1,150 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_core_application_AdminApplication extends org_glizy_mvc_core_Application +{ + var $_pathApplicationToAdmin; + public $hostApplicationToAdmin; + + function __construct($pathApplication='', $pathCore='', $pathApplicationToAdmin='', $configHost='') + { + $this->_pathApplicationToAdmin = $pathApplicationToAdmin; + + org_glizy_ObjectValues::set('org.glizy', 'admin', true); + org_glizy_Paths::init($pathApplication, $pathCore); + org_glizy_Paths::set('APPLICATION_MEDIA_ARCHIVE', $this->_pathApplicationToAdmin.'mediaArchive/'); + // org_glizy_Paths::set('CACHE', $this->_pathCore.'../cache/'); + // org_glizy_Paths::set('CACHE_CODE', $this->_pathCore.'../cache/'); + // org_glizy_Paths::set('CACHE_IMAGES', $this->_pathCore.'../cache/'); + // org_glizy_Paths::set('STATIC_DIR', $this->_pathCore.'../static/'); + // org_glizy_Paths::set('CORE_STATIC_DIR', $this->_pathCore.'../static/org_glizy/'); + org_glizy_Paths::add('APPLICATION_TO_ADMIN', $this->_pathApplicationToAdmin); + org_glizy_Paths::add('APPLICATION_TO_ADMIN_CACHE', $this->_pathApplicationToAdmin.'../cache/'); + org_glizy_Paths::add('APPLICATION_TO_ADMIN_PAGETYPE', $this->_pathApplicationToAdmin.'pageTypes/'); + org_glizy_Paths::addClassSearchPath( $this->_pathApplicationToAdmin.'classes/' ); + + //if (org_glizy_Config::get('SESSION_PREFIX')=='') org_glizy_Config::set('SESSION_PREFIX', 'admin'); + parent::__construct($pathApplication, $pathCore, $configHost); + + $this->addEventListener(org_glizycms_contents_events_Menu::INVALIDATE_SITEMAP, $this); + } + + + function _init() + { + parent::_init(); + + // inizialize the editing language + $language = org_glizy_Session::get('glizy.editingLanguageId'); + + if (is_null($language)) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Language'); + $ar->language_isDefault = 1; + $ar->language_FK_site_id = org_glizy_Config::get( 'SITE_ID' ); + $ar->find(); + org_glizy_Session::set('glizy.editingLanguage', $ar->language_code); + org_glizy_Session::set('glizy.editingLanguageId', $ar->language_id); + org_glizy_Session::set('glizy.editingLanguageIsDefault', $ar->language_isDefault); + $language = $ar->language_id; + } + + org_glizy_ObjectValues::set('org.glizy', 'editingLanguageId', $language); + + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language'); + //$it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language'); + + $languagesId = array(); + + foreach ($it as $ar) { + $languagesId[] = $ar->language_id; + } + + org_glizy_ObjectValues::set('org.glizy', 'languagesId', $languagesId); + } + + function _startProcess() + { + $this->hostApplicationToAdmin = preg_replace('/\/admin$/', '', GLZ_HOST); + parent::_startProcess(); + } + + function render_onStart() + { + $this->addJSLibCore(); + } + + function _loadLocale() + { + // importa i file di localizzazione + if (file_exists(org_glizy_Paths::getRealPath('CORE_CLASSES').'org/glizycms/locale/'.$this->getLanguage().'.php')) + { + require_once(org_glizy_Paths::getRealPath('CORE_CLASSES').'org/glizycms/locale/'.$this->getLanguage().'.php'); + } + else + { + require_once(org_glizy_Paths::getRealPath('CORE_CLASSES').'org/glizycms/locale/en.php'); + } + parent::_loadLocale(); + } + + function switchEditingLanguage($id) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Language'); + $ar->load($id); + org_glizy_Session::set('glizy.editingLanguage', $ar->language_code); + org_glizy_Session::set('glizy.editingLanguageId', $ar->language_id); + org_glizy_Session::set('glizy.editingLanguageIsDefault', $ar->language_isDefault); + org_glizy_ObjectValues::set('org.glizy', 'editingLanguageId', $ar->language_id); + } + + function getEditingLanguageId() + { + return org_glizy_Session::get('glizy.editingLanguageId'); + } + + function getEditingLanguage() + { + return org_glizy_Session::get('glizy.editingLanguage'); + } + + function getEditingLanguageIsDefault() + { + return org_glizy_Session::get('glizy.editingLanguageIsDefault'); + } + + function getPathApplicationToAdmin() + { + return $this->_pathApplicationToAdmin; + } + + function getLanguageId() + { + return 1; + } + + function getLanguage() + { + return !empty($this->_user->language) ? $this->_user->language : parent::getLanguage(); + } + + function isAdmin() + { + return true; + } + + public function onInvalidateSitemap() + { + $siteMap = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.SiteMapDB'); + $siteMap->invalidate(); + + $siteMap = org_glizy_ObjectFactory::createObject('org.glizy.compilers.Routing', __Paths::getRealPath('APPLICATION_TO_ADMIN_CACHE')); + $siteMap->invalidate(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/core/application/Application.php b/src/core/classes/org/glizycms/core/application/Application.php new file mode 100755 index 0000000..13a309a --- /dev/null +++ b/src/core/classes/org/glizycms/core/application/Application.php @@ -0,0 +1,310 @@ +<?php +/** + * Application class. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizycms_core_application_Application extends org_glizy_mvc_core_Application +{ + var $_aclPage; + var $_siteProperty; + var $_templateName; + + function __construct($pathApplication='', $pathCore='', $configHost='') + { + org_glizy_Paths::init($pathApplication, $pathCore); + org_glizy_Paths::add('APPLICATION_TO_ADMIN', org_glizy_Paths::get('APPLICATION')); + org_glizy_Paths::add('APPLICATION_TO_ADMIN_CACHE', org_glizy_Paths::get('APPLICATION').'../cache/'); + parent::__construct($pathApplication, $pathCore, $configHost); + } + + public function runSoft() + { + parent::runSoft(); + $this->readSiteProperties(); + } + + function _initLanguage() + { + $this->log( "initLanguage", GLZ_LOG_SYSTEM ); + // inizializza la lingua + $this->_language = org_glizy_Session::get('glizy.language', NULL); + $this->_languageId = org_glizy_Session::get('glizy.languageId', NULL); + if (is_null($this->_languageId)) + { + $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2); + // try to read the browser language + $this->log( "Read browser language", GLZ_LOG_SYSTEM ); + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Language'); + if (!$ar->find(array('language_code' => $lang, 'language_FK_site_id' => __Config::get( 'SITE_ID' )))) { + $this->log( "Read defaul language", GLZ_LOG_SYSTEM ); + $ar->emptyRecord(); + $ar->find(array('language_isDefault' => 1, + 'language_FK_site_id' => __Config::get( 'SITE_ID' ) + )); + } + + $this->_language = $ar->language_code; + $this->_languageId = $ar->language_id; + org_glizy_Session::set('glizy.language', $this->_language); + org_glizy_Session::set('glizy.languageId', $this->_languageId); + } + + org_glizy_ObjectValues::set('org.glizy', 'languageId', $this->_languageId); + + // importa i file di localizzazione + if (file_exists(org_glizy_Paths::getRealPath('CORE_CLASSES').'org/glizy/locale/'.$this->getLanguage().'.php')) + { + $this->log( "Import locale file", GLZ_LOG_SYSTEM ); + require_once(org_glizy_Paths::getRealPath('CORE_CLASSES').'org/glizy/locale/'.$this->getLanguage().'.php'); + } else { + require_once(org_glizy_Paths::getRealPath('CORE_CLASSES').'org/glizy/locale/en.php'); + } + } + + function _initSiteMap($forceReload=false) + { + $this->log( "initSiteMap", GLZ_LOG_SYSTEM ); + $this->siteMap = &org_glizy_ObjectFactory::createObject('org.glizycms.core.application.SiteMapDB'); + $this->siteMap->getSiteArray($forceReload); + + // controlla se l'utente ha i permessi per modificare la pagina + // per velocizzare vengono precaricate tutte le relazioni in memoria + $this->_aclPage = array(); + if ( __Config::get( 'ACL_ENABLED' ) ) + { + + $this->_aclPage = __Session::get('glizy.aclFront', NULL); + if (is_null($this->_aclPage)) { + $this->_aclPage = array(); + $it = org_glizy_ObjectFactory::createModelIterator( 'org.glizy.models.Join', 'all', array( 'filters' => array( 'join_objectName' => 'menus_tbl#rel_aclFront' ) ) ); + foreach ($it as $arC) { + if ( !isset( $this->_aclPage[ $arC->join_FK_source_id ] ) ) + { + $this->_aclPage[ $arC->join_FK_source_id ] = array(); + } + $this->_aclPage[ $arC->join_FK_source_id ][] = $arC->join_FK_dest_id ; + } + + // scorre tutti i menù per attribuire l'acl ai menù che non ce l'hanno + // ereditandola dal padre + $siteMapIterator = &org_glizy_ObjectFactory::createObject('org.glizy.application.SiteMapIterator', $this->siteMap); + while (!$siteMapIterator->EOF) { + $n = $siteMapIterator->getNode(); + $siteMapIterator->moveNext(); + + if ( !isset($this->_aclPage[$n->id])) { + $n2 = $n; + while (true) { + if ( $n2->parentId == 0 ) break; + $parentNode = $n2->parentNode(); + $n2 = $parentNode; + if ( isset( $this->_aclPage[$parentNode->id])) { + $this->_aclPage[$n->id] = $this->_aclPage[$parentNode->id]; + break; + } + } + } + } + __Session::set('glizy.aclFront', $this->_aclPage); + } + } + } + + function _startProcess($readPageId=true) + { + $this->log( "startProcess", GLZ_LOG_SYSTEM ); + $this->checkSwitchLanguage(); + + $controller = __Request::get( 'controller', '', GLZ_REQUEST_ROUTING ); + if ($controller) + { + $controllerClass = org_glizy_ObjectFactory::createObject( $controller, null, $this ); + org_glizy_helpers_PhpScript::callMethodWithParams( $controllerClass, 'execute' ); + } + + $this->readSiteProperties(); + $this->setTemplateFolder(); + if ($readPageId) { + $evt = array('type' => GLZ_EVT_BEFORE_CREATE_PAGE); + $this->dispatchEvent($evt); + $this->_readPageId(); + } + + if ($this->siteMapMenu->isVisible===false) + { + while(true) + { + $parentMenu = &$this->siteMapMenu->parentNode(); + + if (is_null($parentMenu)) + { + // ERROR + $e = new org_glizy_Exception(array('[%s] %s', $this->getClassName(), __T(GLZ_ERR_EMPTY_APP_PATH))); + } + + $this->siteMapMenu = &$parentMenu; + if ($parentMenu->isVisible===true) + { + $this->_pageId = $this->siteMapMenu->id; + break; + } + } + } + + // TODO da risolvare in modo migliore + // creando un nuovo menu_type + + if ($this->siteMapMenu->pageType=='Empty') + { + $currentPage = &$this->siteMapMenu; + while (true) + { + $childNodes = $currentPage->childNodes(); + if (!count($childNodes)) + { + org_glizy_helpers_Navigation::gotoUrl(GLZ_HOST); + break; + } + $tempPage = &$childNodes[0]; + $currentPage = &$tempPage; + if ($currentPage->pageType!='Empty') + { + $this->siteMapMenu = &$currentPage; + $this->_pageId = $currentPage->id; + break; + } + } + } + + parent::_startProcess(false); + } + + function canViewPage( $page=null ) + { + if ( is_null( $page ) ) + { + $page = $this->_pageId; + } + + $user = &$this->getCurrentUser(); + + /* + if ( isset( $this->_aclPage[ $page ] ) && $user->groupId != 1 ) + { + return in_array( $user->groupId, $this->_aclPage[ $page ] ); + } + else return true; + */ + + if (__Config::get('ACL_ROLES')) { + if ( isset( $this->_aclPage[ $page ] ) && !$user->acl(__Config::get('SITEMAP_ID'), 'all')) { + return $user->isInRoles($this->_aclPage[ $page ]); + } else { + return true; + } + } else { + if ( isset( $this->_aclPage[ $page ]) && $user->groupId != 1 ) { + return in_array( $user->groupId, $this->_aclPage[ $page ] ); + } else { + return true; + } + } + } + + function getSiteProperty() + { + return $this->_siteProperty; + } + + function getTemplateName() + { + return $this->_templateName; + } + + private function setTemplateFolder() + { + // read the template name + $this->_templateName = org_glizy_Registry::get( __Config::get( 'REGISTRY_TEMPLATE_NAME' ), ''); + if (org_glizy_Request::get('template', '') != '') + { + $this->_templateName = org_glizy_Request::get('template', ''); + } + + $browser = strpos($_SERVER['HTTP_USER_AGENT'],"iPhone") || strpos($_SERVER['HTTP_USER_AGENT'],"Android"); + if ($browser == true) + { + if ( file_exists( org_glizy_Paths::get('APPLICATION_STATIC').'templates/'.$this->_templateName.'-mobile' ) ) + { + $this->_templateName .= '-iPhone'; + } + else if ( file_exists( org_glizy_Paths::get('APPLICATION_STATIC').'templates/mobile' ) ) + { + $this->_templateName = 'iPhone'; + } + } + if (empty($this->_templateName)) + { + $this->_templateName = __Config::get('glizycms.template.default'); + } + org_glizy_Paths::set('APPLICATION_TEMPLATE', org_glizy_Paths::get('APPLICATION_STATIC').'templates/'.$this->_templateName.'/'); + org_glizy_Paths::set('APPLICATION_TEMPLATE_DEFAULT', org_glizy_Paths::get('APPLICATION_STATIC').'templates/Default/'); + } + + private function readSiteProperties() + { + $siteProp = unserialize(org_glizy_Registry::get(__Config::get( 'REGISTRY_SITE_PROP' ).$this->getLanguage(), '')); + if (!is_array($siteProp)) + { + // if the site properties are not defined + // try to read the properties from default language + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Language'); + $ar->language_isDefault = 1; + $ar->find(); + $siteProp = org_glizy_Registry::get(__Config::get( 'REGISTRY_SITE_PROP' ).$ar->language_code, ''); + org_glizy_Registry::set(__Config::get( 'REGISTRY_SITE_PROP' ).$this->getLanguage(), $siteProp); + $siteProp = unserialize($siteProp); + } + if (!is_array($siteProp)) + { + $siteProp = array(); + } + $this->_siteProperty = $siteProp; + } + + private function checkSwitchLanguage() + { + $language = org_glizy_Request::get('language', NULL); + + if (!is_null($language) && $language!=$this->_language) + { + // cambio lingua + $this->log( "change language", GLZ_LOG_SYSTEM ); + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Language'); + $ar->language_code = $language; + $ar->find(); + + org_glizy_Session::set('glizy.language', $ar->language_code); + org_glizy_Session::set('glizy.languageId', $ar->language_id); + org_glizy_ObjectValues::set('org.glizy', 'languageId', $ar->language_id); + $this->_languageId = $ar->language_id; + $this->_language = $ar->language_code; + + // ricarica la struttura del sito per avere i titoli aggiornati + $this->_initSiteMap(true); + + // controlla se il routing ha definito un urlResolver + $speakingUrlManager = $this->retrieveProxy('org.glizycms.speakingUrl.Manager'); + $urlResolver = $speakingUrlManager->getResolver(__Request::get('cms:urlResolver', 'org.glizycms.core.models.Content')); + $url = $urlResolver->makeUrlFromRequest(); + + org_glizy_helpers_Navigation::gotoUrl($url); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/core/application/SiteMapDB.php b/src/core/classes/org/glizycms/core/application/SiteMapDB.php new file mode 100755 index 0000000..5dd5116 --- /dev/null +++ b/src/core/classes/org/glizycms/core/application/SiteMapDB.php @@ -0,0 +1,132 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizycms_core_application_SiteMapDB extends org_glizy_application_SiteMap +{ + var $_type = 'db'; + private $cache; + + function __construct() + { + parent::__construct(); + $this->cache = org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFunction', + $this, + __Config::get('glizycms.sitemap.cacheLife'), + false, + __Paths::getRealPath('APPLICATION_TO_ADMIN_CACHE')); + } + + function loadTree($forceReload=false) + { + if ($forceReload) $this->init(); + $emptyMenu = serialize($this->getEmptyMenu()); + $siteId = org_glizy_ObjectValues::get('org.glizy', 'siteId'); + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $languageId = $application->getLanguageId(); + $speakingUrl = __Config::get('glizycms.speakingUrl') === true; + $this->_siteMapArray = $this->cache->get(__METHOD__.$siteId.'_'.$languageId, array(), function() use ($emptyMenu, $application, $speakingUrl) { + $siteMapArray = array(); + $isAdmin = $application->isAdmin(); + $user = $application->getCurrentUser(); + $showDraft = false; + $showDraft = isset($_GET['draft']) && $_GET['draft'] == '1'; + $languageId = method_exists($application, 'getEditingLanguageId') ? $application->getEditingLanguageId() : $application->getLanguageId(); + + // TODO + // carica le versioni dei vari men� + // per poter disabilitare i men� che hanno solo la versione bozza + // $menuVersion = array(); + // $it = &org_glizy_ObjectFactory::createModelIterator('org.glizy.models.ContentVersion', 'all', array('filters' => array( 'contentversion_status' => 'DRAFT', 'contentversion_FK_language_id' => $languageId ) ) ); + + // while ( $it->hasMore() ) + // { + // $arC = &$it->current(); + // $it->next(); + // $menuVersion[ $arC->contentversion_FK_menu_id ] = false; + // } + // $it = &org_glizy_ObjectFactory::createModelIterator('org.glizy.models.ContentVersion', 'all', array('filters' => array( 'contentversion_status' => 'PUBLISHED', 'contentversion_FK_language_id' => $languageId ) ) ); + // while ( $it->hasMore() ) + // { + // $arC = &$it->current(); + // $it->next(); + // $menuVersion[ $arC->contentversion_FK_menu_id ] = true; + // } + // + // $isAdmin = org_glizy_ObjectValues::get('org.glizy', 'admin', false); + // $hidePrivatePage = org_glizy_Config::get( 'HIDE_PRIVATE_PAGE', true ); + + // TODO chiamare il proxy + $menus = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Menu'); + $menus->load('getAllMenu', array('params' => array( 'languageId' => $languageId))); + + foreach ($menus as $ar) { + if (is_null($ar->menu_parentId)) continue; + $menu = unserialize($emptyMenu); + $menu['id'] = $ar->menu_id; + $menu['parentId'] = $ar->menu_parentId; + $menu['pageType'] = $ar->menu_pageType; + $menu['isVisible'] = $ar->menudetail_isVisible == 1 ? true : false; + $menu['title'] = $ar->menudetail_title; //str_replace( "\n", " ", $ar->title ); + $menu['titleLink'] = $ar->menudetail_titleLink; + $menu['linkDescription']= $ar->menudetail_linkDescription; + $menu['depth'] = 1; + $menu['childNodes'] = array(); + $menu['isLocked'] = $ar->menu_isLocked == '1'; + $menu['url'] = $ar->menu_url; + $menu['cssClass'] = $ar->menu_cssClass; + // solo admin + $menu['order'] = $ar->menu_order; + $menu['type'] = $ar->menu_type; + $menu['creationDate'] = glz_localeDate2default($ar->menu_creationDate); + $menu['modificationDate']= glz_localeDate2default($ar->menu_modificationDate); + $menu['hasComment'] = $ar->menu_hasComment; + $menu['printPdf'] = $ar->menu_printPdf; + + //$menu['extendsPermissions'] = $ar->menu_extendsPermissions; + $menu['nodeObj'] = NULL; + + if ($speakingUrl && !$menu['url'] && $ar->speakingurl_value) { + $menu['url'] = $ar->language_code.'/'.$ar->speakingurl_value; + } + + $siteMapArray[$menu["id"]] = $menu; + } + return $siteMapArray; + }); + $this->_makeChilds(); + } + + public function invalidate() + { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $siteId = org_glizy_ObjectValues::get('org.glizy', 'siteId'); + $iterator = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language', 'all'); + foreach($iterator as $ar) { + $this->cache->remove('org_glizycms_core_application_SiteMapDB::loadTree'.$siteId.'_'.$ar->language_id, array()); + } + } + + public function resolveAlias() + { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $speakingUrlManager = $application->retrieveProxy('org.glizycms.speakingUrl.Manager'); + + $IDs = array_keys($this->_siteMapArray); + foreach ($IDs as $key) + { + $menu = &$this->_siteMapArray[$key]; + if (strpos($menu['url'], 'alias:')===0) { + $url = substr($menu['url'], 6); + $menu['url'] = $speakingUrlManager->makeUrl($url); + } + } + } + +} diff --git a/src/core/classes/org/glizycms/core/application/renderer/CellUser.php b/src/core/classes/org/glizycms/core/application/renderer/CellUser.php new file mode 100644 index 0000000..0ead1e3 --- /dev/null +++ b/src/core/classes/org/glizycms/core/application/renderer/CellUser.php @@ -0,0 +1,10 @@ +<?php +class org_glizycms_core_application_renderer_CellUser extends org_glizy_components_render_RenderCell +{ + function renderCell( $key, $value, $item, $columnName ) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizy.models.User'); + $ar->load($value); + return $ar->user_firstName.' '.$ar->user_lastName; + } +} diff --git a/src/core/classes/org/glizycms/core/application/renderer/CellUserActive.php b/src/core/classes/org/glizycms/core/application/renderer/CellUserActive.php new file mode 100644 index 0000000..d11eff8 --- /dev/null +++ b/src/core/classes/org/glizycms/core/application/renderer/CellUserActive.php @@ -0,0 +1,15 @@ +<?php +// TODO +// fare una superclasse processCell +// e una renderCell + +// TODO rinominare in CellIsChecked +class org_glizycms_core_application_renderer_CellUserActive extends GlizyObject +{ + function renderCell($key, $value) + { + if ($value=='1') $value = '<span class="'.__Config::get('glizy.datagrid.checkbox.on').'"></span>'; + else $value = '<span class="'.__Config::get('glizy.datagrid.checkbox.off').'"></span>'; + return $value; + } +} diff --git a/src/core/classes/org/glizycms/core/helpers/Fulltext.php b/src/core/classes/org/glizycms/core/helpers/Fulltext.php new file mode 100644 index 0000000..daa7a35 --- /dev/null +++ b/src/core/classes/org/glizycms/core/helpers/Fulltext.php @@ -0,0 +1,31 @@ +<?php + +class org_glizycms_core_helpers_Fulltext extends GlizyObject +{ + function make($data, $model, $setValuesInModel = false) + { + $fulltext = ''; + + if ($model->fieldExists('title')) { + $fulltext = $model->title.org_glizycms_Glizycms::FULLTEXT_DELIMITER; + } + + foreach ($data as $k => $v) { + // remove the system values + if (strpos($k, '__') === 0 || !$model->fieldExists($k)) continue; + + if ($setValuesInModel) { + $model->$k = $v; + } + + if (is_string($v) || is_numeric($v)) { + $stripped = trim(strip_tags($v)); + if (strlen($stripped) > org_glizycms_Glizycms::FULLTEXT_MIN_CHAR || is_numeric($v)) { + $fulltext .= $stripped.org_glizycms_Glizycms::FULLTEXT_DELIMITER; + } + } + } + + return $fulltext; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/core/models/Content.xml b/src/core/classes/org/glizycms/core/models/Content.xml new file mode 100755 index 0000000..dd9ce11 --- /dev/null +++ b/src/core/classes/org/glizycms/core/models/Content.xml @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="glizycms.content" model:usePrefix="true" model:type="document"> + + <model:Query name="getContentForMenu" type="function" arguments="menuId"> + <![CDATA[ + $iterator->setOptions(array('type' => 'PUBLISHED_DRAFT')); + $iterator->where("id", $menuId); + ]]> + </model:Query> + <model:Script parent="model"> + <![CDATA[ +public function getContentVO() +{ + $vo = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.ContentVO'); + $vo->__id = $this->id; + $vo->__title = $this->title; + $vo->__url = $this->url; + + $content = $this->data->content; + if ($content) { + foreach ($content as $name => $value) { + $vo->{$name} = $value; + } + } + + return $vo; +} + +public function isValidVO($data) +{ + return property_exists($data, '__id') && property_exists($data, '__title') && property_exists($data, '__url'); +} + +public function setDataFromContentVO(org_glizycms_contents_models_ContentVO $data) +{ + if ($this->isValidVO($data)) { + $this->id = $data->__id; + $this->title = $data->__title; + $this->url = $data->__url; + + $fulltext = $this->title.org_glizycms_Glizycms::FULLTEXT_DELIMITER; + $newContent = new StdClass(); + foreach ($data as $k => $v) { + // remove the system values and keep __indexFields for reindex function + if (strpos($k, '__') === 0 && $k!='__indexFields') continue; + $newContent->$k = $v; + $this->addInFulltext($v, $fulltext); + } + $this->content = $newContent; + $this->fulltext = $fulltext; + $this->addFieldsToIndex($data->__indexFields); + + return true; + } else { + return false; + } +} + +protected function addInFulltext($value, &$fulltext) +{ + if (is_array($value) || is_object($value)) { + foreach($value as $v) { + $this->addInFulltext($v, $fulltext); + } + } else { + if (strpos($value, '{"')===0) return; + $stripped = trim(strip_tags($value)); + if (!is_numeric($value) && strlen($stripped) > org_glizycms_Glizycms::FULLTEXT_MIN_CHAR ) { + $fulltext .= $stripped.org_glizycms_Glizycms::FULLTEXT_DELIMITER; + } + } +} + +// init the index fields they can be: +// index={tipo} ie. index=true, index=int, index=text +// for objects in array +// index={fieldName:type,fieldName:type} ie. id:int,type:text + +public function addFieldsToIndex($indexFields) +{ + if (!$indexFields) return; + + $addedFields = array(); + foreach($indexFields as $k=>$v) { + $fieldPath = explode('.', $k); + $targetObj = $this->content; + $targetKeyName = ''; + $targetKeyNamePart = ''; + $found = true; + foreach($fieldPath as $p) { + if (strpos($p, '@')!==false) { + list($p, $targetKeyNamePart) = explode('@', $p); + } + if (!property_exists($targetObj, $p)) { + $found = false; + break; + } + if (is_object($targetObj->{$p})) $targetObj = $targetObj->{$p}; + $targetKeyName = $p; + } + if (!$found || is_null($targetObj->{$targetKeyName})) continue; + + $indexType = org_glizy_dataAccessDoctrine_DbField::INDEXED; + $options = null; + switch ($v) { + case 'int': + $type = \Doctrine\DBAL\Types\Type::INTEGER; + break; + case 'date': + $type = \Doctrine\DBAL\Types\Type::DATE; + break; + case 'fulltext': + $type = Doctrine\DBAL\Types\Type::STRING; + $indexType = org_glizy_dataAccessDoctrine_DbField::FULLTEXT; + break; + case 'array_id': + $type = org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID; + break; + default: + $type = Doctrine\DBAL\Types\Type::STRING; + } + + // verify if the field to index is part of array + $targetPropName = $targetKeyName; + + if ($targetKeyNamePart) { + $options = array( org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID => array( + 'type' => $type, + 'field' => $targetKeyNamePart + )); + $type = org_glizy_dataAccessDoctrine_types_Types::ARRAY_ID; + $targetPropName .= $targetKeyNamePart; + } + + $this->addField(new org_glizy_dataAccessDoctrine_DbField( + $targetPropName, + $type, + 255, + false, + null, + '', + false, + false, + '', + $indexType | org_glizy_dataAccessDoctrine_DbField::ONLY_INDEX, + $options + )); + + if (!in_array($targetPropName, $addedFields)) { + $this->{$targetPropName} = array(); + $addedFields[] = $targetKeyName; + } + + $this->{$targetPropName} = array_merge($this->{$targetPropName}, is_array($targetObj->{$targetKeyName}) ? $targetObj->{$targetKeyName} : array($targetObj->{$targetKeyName})); + } +} + ]]> + </model:Script> + + <model:Define> + <model:Field name="id" type="int" validator="notNull" index="true" /> + <model:Field name="title" type="string" validator="notNull" index="false" /> + <model:Field name="url" type="string" index="false" /> + <model:Field name="content" type="object" index="false" readFormat="false" /> + <model:Field name="fulltext" type="string" index="fulltext" onlyIndex="true" /> + </model:Define> + +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/core/models/Country.xml b/src/core/classes/org/glizycms/core/models/Country.xml new file mode 100755 index 0000000..e0990d2 --- /dev/null +++ b/src/core/classes/org/glizycms/core/models/Country.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="countries_tbl" model:usePrefix="true"> +</model:Model> diff --git a/src/core/classes/org/glizycms/core/models/Language.xml b/src/core/classes/org/glizycms/core/models/Language.xml new file mode 100755 index 0000000..e6bc710 --- /dev/null +++ b/src/core/classes/org/glizycms/core/models/Language.xml @@ -0,0 +1,270 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="languages_tbl" model:usePrefix="true"> + + <model:Query name="getLanguageDictionary" type="function"> + <![CDATA[ + $iterator->select('language_id as k', 'language_name as v') + ->orderBy('language_id'); + ]]> + </model:Query> + + <model:Query name="mysql_duplicateMenuDetail"> + <!-- + Duplicate the menu details + Used in: + org.glizycms.languages.models.proxy.LanguagesProxy + --> + <![CDATA[ + INSERT INTO ##TABLE_PREFIX##menudetails_tbl ( + menudetail_FK_menu_id, + menudetail_FK_language_id, + menudetail_title, + menudetail_keywords, + menudetail_description, + menudetail_subject, + menudetail_creator, + menudetail_publisher, + menudetail_contributor, + menudetail_type, + menudetail_identifier, + menudetail_source, + menudetail_relation, + menudetail_coverage, + menudetail_isVisible, + menudetail_titleLink, + menudetail_linkDescription) +SELECT + menudetail_FK_menu_id, + :newLanguageId, + menudetail_title, + menudetail_keywords, + menudetail_description, + menudetail_subject, + menudetail_creator, + menudetail_publisher, + menudetail_contributor, + menudetail_type, + menudetail_identifier, + menudetail_source, + menudetail_relation, + menudetail_coverage, + menudetail_isVisible, + menudetail_titleLink, + menudetail_linkDescription +FROM ##TABLE_PREFIX##menudetails_tbl +WHERE menudetail_FK_language_id=:languageId + ]]> + </model:Query> + <model:Query name="mysql_duplicateDocumentsDetail"> + <!-- + Duplicate the documents + Used in: + org.glizycms.languages.models.proxy.LanguagesProxy + --> + <![CDATA[ + INSERT INTO ##TABLE_PREFIX##documents_detail_tbl ( + document_detail_FK_document_id, + document_detail_FK_language_id, + document_detail_FK_user_id, + document_detail_modificationDate, + document_detail_status, + document_detail_translated, + document_detail_object) +SELECT + document_detail_FK_document_id, + :newLanguageId, + document_detail_FK_user_id, + document_detail_modificationDate, + document_detail_status, + 0, + document_detail_object +FROM ##TABLE_PREFIX##documents_detail_tbl +WHERE document_detail_FK_language_id=:languageId AND document_detail_status = 'PUBLISHED' + ]]> + </model:Query> + <model:Query name="mysql_duplicateMediaDetail"> + <!-- + Duplicate the media detail + Used in: + org.glizycms.languages.models.proxy.LanguagesProxy + --> + <![CDATA[ + INSERT INTO ##TABLE_PREFIX##mediadetails_tbl ( + mediadetail_FK_media_id, + media_FK_language_id, + media_FK_user_id, + media_modificationDate, + media_title, + media_category, + media_date, + media_copyright, + media_description) +SELECT + mediadetail_FK_media_id, + :newLanguageId, + media_FK_user_id, + media_modificationDate, + media_title, + media_category, + media_date, + media_copyright, + media_description +FROM ##TABLE_PREFIX##mediadetails_tbl +WHERE media_FK_language_id=:languageId + ]]> + </model:Query> +<model:Query name="pgsql_duplicateMenuDetail"> + <!-- + Duplicate the menu details + Used in: + org.glizycms.languages.models.proxy.LanguagesProxy + --> + <![CDATA[ + INSERT INTO ##TABLE_PREFIX##menudetails_tbl ( + "menudetail_FK_menu_id", + "menudetail_FK_language_id", + "menudetail_title", + "menudetail_keywords", + "menudetail_description", + "menudetail_subject", + "menudetail_creator", + "menudetail_publisher", + "menudetail_contributor", + "menudetail_type", + "menudetail_identifier", + "menudetail_source", + "menudetail_relation", + "menudetail_coverage", + "menudetail_isVisible", + "menudetail_titleLink", + "menudetail_linkDescription") +SELECT + "menudetail_FK_menu_id", + :newLanguageId, + "menudetail_title", + "menudetail_keywords", + "menudetail_description", + "menudetail_subject", + "menudetail_creator", + "menudetail_publisher", + "menudetail_contributor", + "menudetail_type", + "menudetail_identifier", + "menudetail_source", + "menudetail_relation", + "menudetail_coverage", + "menudetail_isVisible", + "menudetail_titleLink", + "menudetail_linkDescription" +FROM ##TABLE_PREFIX##menudetails_tbl +WHERE "menudetail_FK_language_id"=:languageId + ]]> + </model:Query> + <model:Query name="pgsql_duplicateDocumentsDetail"> + <!-- + Duplicate the documents + Used in: + org.glizycms.languages.models.proxy.LanguagesProxy + --> + <![CDATA[ + INSERT INTO ##TABLE_PREFIX##documents_detail_tbl ( + "document_detail_FK_document_id", + "document_detail_FK_language_id", + "document_detail_FK_user_id", + "document_detail_modificationDate", + "document_detail_status", + "document_detail_translated", + "document_detail_object") +SELECT + "document_detail_FK_document_id", + :newLanguageId, + "document_detail_FK_user_id", + "document_detail_modificationDate", + "document_detail_status", + 0, + "document_detail_object" +FROM ##TABLE_PREFIX##documents_detail_tbl +WHERE "document_detail_FK_language_id"=:languageId AND document_detail_status = 'PUBLISHED' + ]]> + </model:Query> + <model:Query name="pgsql_duplicateMediaDetail"> + <!-- + Duplicate the media detail + Used in: + org.glizycms.languages.models.proxy.LanguagesProxy + --> + <![CDATA[ + INSERT INTO ##TABLE_PREFIX##mediadetails_tbl ( + "mediadetail_FK_media_id", + "media_FK_language_id", + "media_FK_user_id", + "media_modificationDate", + "media_title", + "media_category", + "media_date", + "media_copyright", + "media_description") +SELECT + "mediadetail_FK_media_id", + :newLanguageId, + "media_FK_user_id", + "media_modificationDate", + "media_title", + "media_category", + "media_date", + "media_copyright", + "media_description" +FROM ##TABLE_PREFIX##mediadetails_tbl +WHERE "media_FK_language_id"=:languageId + ]]> + </model:Query> + + <model:Query name="deleteMenuDetail" type="function" arguments="languageId"> + <!-- + Delete the menu details + Used in: + org.glizycms.languages.models.proxy.LanguagesProxy + --> + <![CDATA[ + $expr = $iterator->expr(); + $qb = $iterator->qb(); + $qb->delete($this->tablePrefix.'menudetails_tbl') + ->where($expr->comparison('menudetail_FK_language_id', '=', ':languageId')) + ->setParameter('languageId', $languageId); + $iterator->setSqlQuery($qb->getSQL()); + ]]> + </model:Query> + <model:Query name="deleteDocumentsDetail" type="function" arguments="languageId"> + <!-- + Delete the menu details + Used in: + org.glizycms.languages.models.proxy.LanguagesProxy + --> + <![CDATA[ + $expr = $iterator->expr(); + $qb = $iterator->qb(); + $qb->delete($this->tablePrefix.'documents_detail_tbl') + ->where($expr->comparison('document_detail_FK_language_id', '=', ':languageId')) + ->setParameter(':languageId', $languageId); + $iterator->setSqlQuery($qb->getSQL()); + ]]> + </model:Query> + <model:Query name="deleteMediaDetail" type="function" arguments="languageId"> + <!-- + Delete the menu details + Used in: + org.glizycms.languages.models.proxy.LanguagesProxy + --> + <![CDATA[ + $expr = $iterator->expr(); + $qb = $iterator->qb(); + $qb->delete($this->tablePrefix.'mediadetails_tbl') + ->where($expr->comparison('media_FK_language_id', '=', ':languageId')) + ->setParameter(':languageId', $languageId); + $iterator->setSqlQuery($qb->getSQL()); + ]]> + </model:Query> +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/core/models/Menu.xml b/src/core/classes/org/glizycms/core/models/Menu.xml new file mode 100755 index 0000000..b6b2100 --- /dev/null +++ b/src/core/classes/org/glizycms/core/models/Menu.xml @@ -0,0 +1,207 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:type="2tables" + model:tableName="menus_tbl,menudetails_tbl" + model:joinFields="menu_id,menudetail_FK_menu_id" + model:languageField="menudetail_FK_language_id" + model:siteField="menu_FK_site_id" + model:usePrefix="true"> + + <model:Query name="getRootMenu" type="function" arguments="languageId"> + <!-- + Get a menu. + Used in: + org.glizycms.contents.models.proxy.MenuProxy + --> + <![CDATA[ + $iterator->where('menu_parentId', 0); + ]]> + </model:Query> + + <model:Query name="getMenu" type="function" arguments="menuId,languageId"> + <!-- + Get a menu. + Used in: + org.glizycms.contents.models.proxy.MenuProxy + --> + <![CDATA[ + $iterator->where('menu_id', $menuId) + ->whereLanguageIs($languageId); + + if (__Config::get('glizycms.speakingUrl')) { + $expr = $iterator->expr(); + $iterator->leftJoin("t1", $this->tablePrefix."speakingurls_tbl", "t3", + $expr->andX( + $expr->eq("t1.menu_id", "t3.speakingurl_FK"), + $expr->andX( $expr->eq("t3.speakingurl_type", "'org.glizycms.core.models.Content'"), + $expr->eq("detail.menudetail_FK_language_id", "t3.speakingurl_FK_language_id") + ) + ) + ) + ->join("t1", $this->tablePrefix."languages_tbl", "t2", $expr->eq("detail.menudetail_FK_language_id", "t2.language_id")); + } + ]]> + </model:Query> + + <model:Query name="autocompletePagePicker" type="function" arguments="search,languageId,menuId,pageType"> + <!-- + Search a menu by title and returns the title and path + Used in: + org.glizycms.contents.controllers.autocomplete.ajax.PagePicker + --> + <![CDATA[ + $expr = $iterator->expr(); + + $iterator->select("t1.menu_id", "t5.menudetail_title", "t6.menudetail_title as p3", "t7.menudetail_title as p2", "t8.menudetail_title as p1") + ->leftJoin("t1", $this->tablePrefix."menus_tbl", "t2", $expr->eq("t1.menu_parentId", "t2.menu_id")) + ->leftJoin("t1", $this->tablePrefix."menus_tbl", "t3", $expr->eq("t2.menu_parentId", "t3.menu_id")) + ->leftJoin("t1", $this->tablePrefix."menus_tbl", "t4", $expr->eq("t3.menu_parentId", "t4.menu_id")) + ->leftJoin("t1", $this->tablePrefix."menudetails_tbl", "t5", $expr->andX($expr->eq("t5.menudetail_FK_menu_id", "t1.menu_id"), $expr->eq("t5.menudetail_FK_language_id", ":languageId"))) + ->leftJoin("t1", $this->tablePrefix."menudetails_tbl", "t6", $expr->andX($expr->eq("t6.menudetail_FK_menu_id", "t2.menu_id"), $expr->eq("t6.menudetail_FK_language_id", ":languageId"))) + ->leftJoin("t1", $this->tablePrefix."menudetails_tbl", "t7", $expr->andX($expr->eq("t7.menudetail_FK_menu_id", "t3.menu_id"), $expr->eq("t7.menudetail_FK_language_id", ":languageId"))) + ->leftJoin("t1", $this->tablePrefix."menudetails_tbl", "t8", $expr->andX($expr->eq("t8.menudetail_FK_menu_id", "t4.menu_id"), $expr->eq("t8.menudetail_FK_language_id", ":languageId"))) + ->setParameter(':languageId', $languageId) + ->where("t1.menu_type", 'BLOCK', '!=') + ->limit(0, 10) + ->orderBy("t5.menudetail_title"); + + if ($pageType) { + $iterator->where("t1.menu_pageType", $pageType, '='); + } + if ($search) { + $iterator->where("t5.menudetail_title", $search, 'ILIKE'); + } else if ($menuId) { + $iterator->where("t1.menu_id", $menuId); + } + + if ($this->siteField) { + $this->siteField = "t1.menu_FK_site_id"; + } + ]]> + </model:Query> + + <model:Query name="mysql_getChildMenus"> + <!-- + Get a child menu. + Used in: + org.glizycms.contents.models.proxy.MenuProxy + --> + <![CDATA[ + SELECT t1.*, + menudetail_title, + menudetail_titleLink, + menudetail_linkDescription, + menudetail_isVisible, + (SELECT count(*) FROM ##TABLE_PREFIX##menus_tbl as t2 WHERE t2.menu_parentId = t1.menu_id) as numChild + FROM ##TABLE_PREFIX##menus_tbl as t1 + INNER JOIN ##TABLE_PREFIX##menudetails_tbl ON (menudetail_FK_menu_id=menu_id) + WHERE t1.menu_parentId=:menuId AND menudetail_FK_language_id=:languageId + ORDER BY t1.menu_order, t1.menu_id + ]]> + </model:Query> + + <model:Query name="mysql_getChildMenusNoBlock"> + <!-- + Get a child menu. + Used in: + org.glizycms.contents.models.proxy.MenuProxy + --> + <![CDATA[ + SELECT t1.*, + menudetail_title, + menudetail_titleLink, + menudetail_linkDescription, + menudetail_isVisible, + (SELECT count(*) FROM ##TABLE_PREFIX##menus_tbl as t2 WHERE t2.menu_parentId = t1.menu_id AND t2.menu_type!='BLOCK') as numChild + FROM ##TABLE_PREFIX##menus_tbl as t1 + INNER JOIN ##TABLE_PREFIX##menudetails_tbl ON (menudetail_FK_menu_id=menu_id) + WHERE t1.menu_parentId=:menuId AND menudetail_FK_language_id=:languageId AND t1.menu_type!='BLOCK' + ORDER BY t1.menu_order, t1.menu_id + ]]> + </model:Query> + + <model:Query name="pgsql_getChildMenus"> + <!-- + Get a child menu. + Used in: + org.glizycms.contents.models.proxy.MenuProxy + --> + <![CDATA[ + SELECT t1.*, + menudetail_title, + "menudetail_titleLink", + "menudetail_linkDescription", + "menudetail_isVisible", + (SELECT count(*) FROM ##TABLE_PREFIX##menus_tbl as t2 WHERE t2."menu_parentId" = t1.menu_id) as "numChild" + FROM ##TABLE_PREFIX##menus_tbl as t1 + INNER JOIN ##TABLE_PREFIX##menudetails_tbl ON ("menudetail_FK_menu_id" = menu_id) + WHERE t1."menu_parentId"=:menuId AND "menudetail_FK_language_id"=:languageId + ORDER BY t1.menu_order, t1.menu_id + ]]> + </model:Query> + + <model:Query name="pgsql_getChildMenusNoBlock"> + <!-- + Get a child menu. + Used in: + org.glizycms.contents.models.proxy.MenuProxy + --> + <![CDATA[ + SELECT t1.*, + menudetail_title, + "menudetail_titleLink", + "menudetail_linkDescription", + "menudetail_isVisible", + (SELECT count(*) FROM ##TABLE_PREFIX##menus_tbl as t2 WHERE t2."menu_parentId" = t1.menu_id AND t2.menu_type!='BLOCK') as "numChild" + FROM ##TABLE_PREFIX##menus_tbl as t1 + INNER JOIN ##TABLE_PREFIX##menudetails_tbl ON ("menudetail_FK_menu_id" = menu_id) + WHERE t1."menu_parentId"=:menuId AND "menudetail_FK_language_id"=:languageId AND t1.menu_type!='BLOCK' + ORDER BY t1.menu_order, t1.menu_id + ]]> + </model:Query> + + <model:Query name="getAllMenu" type="function" arguments="languageId"> + <!-- + Get a menu. + Used in: + org.glizycms.core.application.SiteMapDB + --> + <![CDATA[ + $iterator->select('t1.*', 'detail.menudetail_title', 'detail.menudetail_titleLink', 'detail.menudetail_linkDescription', 'detail.menudetail_isVisible' ) + ->whereLanguageIs($languageId) + ->orderBy('t1.menu_parentId') + ->orderBy('t1.menu_order') + ->orderBy('t1.menu_id'); + + if (__Config::get('glizycms.speakingUrl')) { + $expr = $iterator->expr(); + $iterator->select('t1.*', 'detail.menudetail_title', 'detail.menudetail_titleLink', 'detail.menudetail_linkDescription', 'detail.menudetail_isVisible', 't3.speakingurl_value', 't2.language_code' ) + ->leftJoin("t1", $this->tablePrefix."speakingurls_tbl", "t3", + $expr->andX( + $expr->eq("t1.menu_id", "t3.speakingurl_FK"), + $expr->andX( $expr->eq("t3.speakingurl_type", "'org.glizycms.core.models.Content'"), + $expr->eq("detail.menudetail_FK_language_id", "t3.speakingurl_FK_language_id") + ) + ) + ) + ->join("t1", $this->tablePrefix."languages_tbl", "t2", $expr->eq("detail.menudetail_FK_language_id", "t2.language_id")); + } + ]]> + </model:Query> + + <model:Query name="getChildrenMenuInOrder" type="function" arguments="menuId"> + <!-- + Get the children of a menu + Used in: + org.glizycms.contents.models.proxy.Menu + --> + <![CDATA[ + $iterator->select('menu_id', 'menu_order', 'menudetail_id') + ->where('menu_parentId', $menuId) + ->orderBy('menu_order'); + ]]> + </model:Query> + +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/core/models/MenuDetail.xml b/src/core/classes/org/glizycms/core/models/MenuDetail.xml new file mode 100755 index 0000000..e1619f7 --- /dev/null +++ b/src/core/classes/org/glizycms/core/models/MenuDetail.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="menudetails_tbl" model:usePrefix="true"> +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/core/models/enum/FieldTypeEnum.php b/src/core/classes/org/glizycms/core/models/enum/FieldTypeEnum.php new file mode 100644 index 0000000..3967135 --- /dev/null +++ b/src/core/classes/org/glizycms/core/models/enum/FieldTypeEnum.php @@ -0,0 +1,13 @@ +<?php +class org_glizycms_core_models_enum_FieldTypeEnum +{ + const TEXT = 'TEXT'; + const NUMBER = 'NUMBER'; + const URL = 'URL'; + const CHECKBOX = 'CHECKBOX'; + const IMAGE = 'IMAGE'; + const MEDIA = 'MEDIA'; + const REPEATER = 'REPEATER'; + const REPEATER_IMAGE = 'REPEATER IMAGE'; + const REPEATER_MEDIA = 'REPEATER MEDIA'; +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/core/models/enum/MenuEnum.php b/src/core/classes/org/glizycms/core/models/enum/MenuEnum.php new file mode 100644 index 0000000..5f6dcf9 --- /dev/null +++ b/src/core/classes/org/glizycms/core/models/enum/MenuEnum.php @@ -0,0 +1,8 @@ +<?php +class org_glizycms_core_models_enum_MenuEnum +{ + const HOME = 'HOME'; + const PAGE = 'PAGE'; + const SYSTEM = 'SYSTEM'; + const BLOCK = 'BLOCK'; +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/groupManager/models/UserGroup.xml b/src/core/classes/org/glizycms/groupManager/models/UserGroup.xml new file mode 100755 index 0000000..f85e03b --- /dev/null +++ b/src/core/classes/org/glizycms/groupManager/models/UserGroup.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="usergroups_tbl" model:usePrefix="true"> + + <model:Query name="userGroupsAdmin" type="function"> + $iterator->select('usergroup_id as k', 'usergroup_name as v') + ->orderBy('v'); + </model:Query> +</model:Model> diff --git a/src/core/classes/org/glizycms/groupManager/views/GroupManagerEdit.xml b/src/core/classes/org/glizycms/groupManager/views/GroupManagerEdit.xml new file mode 100755 index 0000000..8f4f305 --- /dev/null +++ b/src/core/classes/org/glizycms/groupManager/views/GroupManagerEdit.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Page.php"> + <glz:Import src="_common.xml" /> + + <mvc:State name="index"> + <glz:DataProvider id="dp" recordClassName="org.glizycms.groupManager.models.UserGroup" /> + <glz:DataGrid id="dataGrid" label="{i18n: Elenco utenti}" dataProvider="{dp}" filters="{filters}" tableCssClass="table table-striped table-bordered" cssClass="odd,even" paginate="{dataGridPaginate}" controller="{dataGridEdit}" orderStyle="BLACK"> + <glz:DataGridColumn columnName="usergroup_id" visible="false" key="true"/> + <glz:DataGridColumn columnName="usergroup_name" headerText="{i18n:GLZ_USERGROUP_NAME}" /> + <glz:DataGridColumn columnName="usergroup_id" align="right" width="80" renderCell="org.glizycms.contents.views.renderer.CellEditDelete" /> + </glz:DataGrid> + <glz:PaginateResult id="dataGridPaginate" cssClass="pagination"/> + <glz:Link label="{i18n:GLZ_USERGROUP_ADD_NEW_RECORD}" cssClass="{config:glizycms.form.actionLink.cssClass}" icon="icon-plus" routeUrl="actionsMVCAdd" editableRegion="actions" acl="*,new"/> + </mvc:State> + + <mvc:State name="edit"> + <cms:FormEdit id="myForm" controllerName="org.glizycms.contents.controllers.activeRecordEdit.*"> + <cms:pageTitleModifier action="edit" label="{i18n:New group}" new="true" /> + <cms:pageTitleModifier action="edit" label="{i18n:Edit group}" new="false" field="usergroup_name" /> + <glz:Hidden id='__id' /> + <glz:Hidden id="__model" value="org.glizycms.groupManager.models.UserGroup"/> + <glz:Input id="usergroup_name" label="{i18n:GLZ_USERGROUP_NAME}" size="90" required="true" /> + <glz:Checkbox id="usergroup_backEndAccess" label="{i18n:GLZ_USERGROUP_INTERNAL}" visible="{php:!__Config::get(ACL_ROLES)}" defaultStatus="on" data="type=checkbox" /> + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <glz:HtmlButton label="{i18n:GLZ_SAVE_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=saveClose" /> + <glz:HtmlButton label="{i18n:GLZ_CANCEL}" type="button" cssClass="btn js-glizycms-cancel" data="action=cancel" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="delete"> + <glz:Hidden controllerName="org.glizycms.contents.controllers.activeRecordEdit.*" /> + <glz:Hidden id="__model" value="org.glizycms.groupManager.models.UserGroup"/> + </mvc:State> + +</mvc:Page> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/helpers/Media.php b/src/core/classes/org/glizycms/helpers/Media.php new file mode 100755 index 0000000..2fc09b4 --- /dev/null +++ b/src/core/classes/org/glizycms/helpers/Media.php @@ -0,0 +1,98 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_helpers_Media extends GlizyObject +{ + + public static function getImageById($id, $direct=false, $cssClass='', $style='', $onclick='') + { + $media = &org_glizycms_mediaArchive_MediaManager::getMediaById($id); + if (is_null($media)) { + return ''; + } + $attributes = array(); + $attributes['alt'] = $media->title; + $attributes['title'] = $media->title; + $attributes['class'] = $cssClass; + $attributes['style'] = $style; + $attributes['onclick'] = $onclick; + $attributes['src'] = $direct ? $media->getFileName() : org_glizycms_Glizycms::getMediaArchiveBridge()->getImageById($id); + ; + return org_glizy_helpers_Html::renderTag('img', $attributes); + } + + + public static function getResizedImageById($id, $direct=false, $width, $height, $crop=false, $cssClass='', $style='', $onclick='') + { + $media = &org_glizycms_mediaArchive_MediaManager::getMediaById($id); + if (is_null($media)) { + return ''; + } + if ($direct) { + $thumb = $media->getThumbnail($width, $height, $crop); + } + $attributes = array(); + $attributes['alt'] = $media->title; + $attributes['title'] = $media->title; + $attributes['class'] = $cssClass; + $attributes['style'] = $style; + $attributes['onclick'] = $onclick; + $attributes['src'] = $direct ? $thumb['fileName'] : org_glizycms_Glizycms::getMediaArchiveBridge()->getImageByIdAndResize($id, $width, $height, $crop); + ; + return org_glizy_helpers_Html::renderTag('img', $attributes); + } + + public static function getImageUrlById($id, $width, $height, $crop=false, $cropOffset=1, $forceSize=false, $useThumbnail=false ) + { + return org_glizycms_Glizycms::getMediaArchiveBridge()->getImageByIdAndResize($id, $width, $height, $crop, $cropOffset, $forceSize, $useThumbnail); + } + + public static function getResizedImageUrlById($id, $direct=false, $width, $height, $crop=false, $cropOffset=1, $forceSize=false ) + { + if ($direct) { + $media = &org_glizycms_mediaArchive_MediaManager::getMediaById($id); + if (is_null($media)) { + return ''; + } + $thumb = $media->getThumbnail($width, $height, $crop, $cropOffset, $forceSize ); + return $thumb['fileName']; + } + return self::getImageUrlById( $id, $width, $height, $crop, $cropOffset, $forceSize ); + } + + public static function getUrlById($id, $direct=false) + { + if ($direct) { + $media = &org_glizycms_mediaArchive_MediaManager::getMediaById($id); + return is_null($media) ? '' : $media->getFileName(); + } else { + return org_glizycms_Glizycms::getMediaArchiveBridge()->getImageById($id); + } + } + + public static function getFileUrlById($id, $direct=false) + { + if ($direct) { + $media = &org_glizycms_mediaArchive_MediaManager::getMediaById($id); + return is_null($media) ? '' : $media->getFileName(false); + } else { + return org_glizycms_Glizycms::getMediaArchiveBridge()->getMediaById($id); + } + } + + /* deprecated */ + public static function getThumbnailById($id, $width, $height, $crop=false, $class='', $onclick='') + { + return self::getResizedImageById($id, false, $width, $height, $crop, $class, '', ''); + } +} + +class __Media extends org_glizycms_helpers_Media +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/helpers/Modules.php b/src/core/classes/org/glizycms/helpers/Modules.php new file mode 100644 index 0000000..cc18515 --- /dev/null +++ b/src/core/classes/org/glizycms/helpers/Modules.php @@ -0,0 +1,123 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizycms_helpers_Modules extends GlizyObject +{ + public function getFields($pageId, $getRepChild = false) + { + $editForm = $this->getEditForm($pageId); + $fields = $this->getChildFields($editForm, $getRepChild); + return $fields; + } + + public function getModelPath($pageId) + { + $editForm = $this->getEditForm($pageId); + + for ($i = 0; $i < count($editForm->childComponents); $i++) { + $c = $editForm->childComponents[$i]; + $id = $c->getAttribute('id'); + + if ($id == '__model') { + return $c->getAttribute('value'); + } + } + + return null; + } + + protected function getEditForm($pageId, $formId='editForm', $formAction='edit') + { + $oldAction = __Request::get('action'); + __Request::set('action', $formAction); + + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $originalRootComponent = $application->getRootComponent(); + + $siteMap = $application->getSiteMap(); + $siteMapNode = $siteMap->getNodeById($pageId); + $pageType = $siteMapNode->getAttribute('pageType'); + + $path = org_glizy_Paths::get('APPLICATION_PAGETYPE'); + $templatePath = org_glizycms_Glizycms::getSiteTemplatePath(); + $options = array( + 'skipImport' => true, + 'pathTemplate' => $templatePath, + 'mode' => 'edit' + ); + $pageTypeObj = &org_glizy_ObjectFactory::createPage($application, $pageType, $path, $options); + $rootComponent = $application->getRootComponent(); + $rootComponent->init(); + $application->_rootComponent = &$originalRootComponent; + __Request::set('action', $oldAction); + + return $rootComponent->getComponentById($formId); + } + + protected function getChildFields($component, $getRepChild = false) + { + $fields = array(); + $childComponents = $component->childComponents; + for ($i = 0; $i < count($childComponents); $i++) { + $c = $childComponents[$i]; + $id = $c->getAttribute('id'); + $data = $c->getAttribute('data'); + + if (( is_subclass_of($c, 'org_glizy_components_HtmlFormElement') || + ( is_a($c, 'org_glizy_components_Fieldset') && $data) + ) && substr($id, 0, 2) != '__' ) { + $temp = new StdClass; + $temp->type = $this->getFieldTypeFromComponent($c); + if($getRepChild && ($temp->type == org_glizycms_core_models_enum_FieldTypeEnum::REPEATER_IMAGE + || $temp->type == org_glizycms_core_models_enum_FieldTypeEnum::REPEATER_MEDIA + || $temp->type == org_glizycms_core_models_enum_FieldTypeEnum::REPEATER) ){ + $fields = array_merge($fields, $this->getChildFields($c, $getRepChild)); + } else { + $temp->id = $id; + $temp->label = $c->getAttribute('label'); + $fields[$id] = $temp; + } + } else if (is_a($c, 'org_glizy_components_Fieldset') && !$data) { + $fields = array_merge($fields, $this->getChildFields($c, $getRepChild)); + } + } + + return $fields; + } + + protected function getFieldTypeFromComponent($component) + { + $data = $component->getAttribute('data'); + + if (strpos($data, 'type=mediapicker') !== false && strpos($data, 'mediatype=IMAGE') !== false) { + return org_glizycms_core_models_enum_FieldTypeEnum::IMAGE; + } else if (strpos($data, 'type=mediapicker') !== false && strpos($data, 'mediatype=IMAGE') === false) { + return org_glizycms_core_models_enum_FieldTypeEnum::MEDIA; + } else if (strpos($data, 'type=checkbox') !== false) { + return org_glizycms_core_models_enum_FieldTypeEnum::CHECKBOX; + } else if (strpos($data, 'type=url') !== false) { + return org_glizycms_core_models_enum_FieldTypeEnum::URL; + } else if (strpos($data, 'type=number') !== false) { + return org_glizycms_core_models_enum_FieldTypeEnum::NUMBER; + } else if (strpos($data, 'type=repeat') !== false) { + if (count($component->childComponents)==1) { + $temp = $this->getFieldTypeFromComponent($component->childComponents[0]); + if ($temp==org_glizycms_core_models_enum_FieldTypeEnum::IMAGE) { + return org_glizycms_core_models_enum_FieldTypeEnum::REPEATER_IMAGE; + } else if ($temp==org_glizycms_core_models_enum_FieldTypeEnum::MEDIA) { + return org_glizycms_core_models_enum_FieldTypeEnum::REPEATER_MEDIA; + } + } + return org_glizycms_core_models_enum_FieldTypeEnum::REPEATER; + } else { + return org_glizycms_core_models_enum_FieldTypeEnum::TEXT; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/.htaccess b/src/core/classes/org/glizycms/js/.htaccess new file mode 100755 index 0000000..a842017 --- /dev/null +++ b/src/core/classes/org/glizycms/js/.htaccess @@ -0,0 +1,4 @@ +<Files *> + Order deny,allow + Allow from all +</Files> diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEdit.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEdit.js new file mode 100644 index 0000000..82b41f3 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEdit.js @@ -0,0 +1,718 @@ +jQuery( (function( $ ){ + var fieldTypes = {}; + var imageAllowExt = 'jpg|jpeg|png|gif|tiff|tif'; + + $.GlizyRegisterType = function (type, typeDef) { + + fieldTypes[type] = typeDef; + }; + + $.GlizyRegisterTypeGet = function (type) { + return fieldTypes[type]; + }; + + $.fn.GlizyFormEdit = function(glizyOpt) { + + $.fn.syncRecords = function () { + + return this.each(function () { + jQuery(this).find('.GFERowContainer').each(function (i) { + jQuery(this).toggleClass('GFERowContainerOdd', !!(i % 2)) + .find('.GFERecordId').text(i +1) + .end().find('[name]').each(function () { + + var name = this.name, + newName = name.replace(/\[\d*\]$/, '[' + i + ']'); + + overloadCaller.call(this, 'destroy'); + this.name = newName; + $(this).data('origValue', $(this).data('oldVal')); + overloadCaller.call(this, '__construct'); + }); + }); + }); + }; + + $.fn.makeSortable = function () { + + return this.sortable({ + items: '.GFERowContainer', + handle: '.GFERowHandler', + start: function (ev) { + jQuery(ev.target).find('[name]').each(function () { + overloadCaller.call(this, 'destroy'); + }); + }, + stop: function (ev) { + jQuery(ev.target).syncRecords(); + } + }); + }; + + var $form = jQuery(this), + + lang = glizyOpt.lang, + + invalidFields = 0, + customValidationInvalid = false, + + cutText = function (text, len, reverse) { + + if (text && text.length > len) { + if (reverse) { + text = "... " + text.substr(text.length - len); + } + else { + text = text.substr(0, len) + " ..."; + } + } + return text || ''; + }, + + htmlStripTags = function (text) { + return typeof(text) == "string" ? text.replace(/<[a-z\/][^>]*>/gi, '') : ''; + }, + + getOptions = function ($anyDesc) { + + var $fieldSet = $anyDesc.closest('fieldset'); + + return { + isCollapsable: $fieldSet.attr('data-collapsable') == 'true', + minRec: parseInt($fieldSet.attr('data-repeatmin') || 0), + maxRec: parseInt($fieldSet.attr('data-repeatmax') || 0), + noAddRowButton: $fieldSet.attr('data-noAddRowButton') == 'true' + }; + }, + + overloadCaller = function (method) { + + var $this = jQuery(this), + type = $this.attr('data-type'), + args; + if (fieldTypes[type] && fieldTypes[type][method]) { + + if (arguments.length > 1) args = Array.prototype.slice.call(arguments).slice(1); + + $this.data({overloadCalled: true, formEdit: fieldTypes[type], glizyOpt: glizyOpt}); + return fieldTypes[type][method].apply(this, args); + } + $this.data('overloadCalled', false); + }, + + addRow = function ($fieldSet, $footer, id, justCreated) { + var fieldSetId = $fieldSet.attr('id'); + $footer.before($fieldSet.data('rowModel').clone(true) + .data('justCreated', justCreated || false) + .find('.GFERecordId').text(id +1) + .end().find('[name]').attr('name', function (i, name) { + $(this).data('originalName', $(this).attr('name')); + return fieldSetId+'[' + name + '][' + id + ']' + }).end() + ); + }, + + filterEditingFields = function () { + + var i, el; + + if (jQuery('.GFEEditingRow').length) { + for (i = 0; el = this[i]; i++) { + if (jQuery(el).parents('.GFEEditingRow').length) { + return jQuery(el); + } + } + return jQuery(); + } + else { + return jQuery(this).first(); + } + }, + + enableValidation = function () { + $form.validVal({ + validate: { + fields: { + hidden: true, + filter: function( fields ) { + var newFields = []; + $(fields).each(function(index, el){ + if ($(el).parent().parent().css('display')!=='none') { + newFields.push(el); + } + }); + return $(newFields); + } + } + }, + fields: { + onValidate: function ($form, language) { + overloadCaller.call(this, 'save'); + }, + onInvalid: function( $form, language ) { + filterEditingFields.call([$(this)]).parent().parent().addClass('GFEValidationError').next().stop();; //.fadeIn(); + }, + onValid: function( $form, language ) { + var $el = filterEditingFields.call([$(this)]); + if ($el.length) { + jQuery($el[0]).parent().parent().removeClass('GFEValidationError'); + $el.removeClass('GFEValidationError').next().stop(); //.fadeOut(); + } + } + }, + form: { + onValidate: function () { + + var error, fieldVals = {}; + + if (glizyOpt.customValidation && typeof(window[glizyOpt.customValidation]) == 'function') { + jQuery(this).find('input:not( [type="button"], [type="submit"], [type="reset"] ), textarea, select').each(function () { + if (this.name) fieldVals[this.name] = jQuery(this).val(); + }); + if (error = window[glizyOpt.customValidation](fieldVals)) { + Glizy.events.broadcast("glizy.message.showError", {"title": error, "message": ""}); + customValidationInvalid = true; + } + } + }, + onInvalid: function( field_arr, language ) { + + var $invalidEl = filterEditingFields.call(field_arr); + + invalidFields = $invalidEl.length; + + if ($invalidEl.length) { + if ($invalidEl.attr('data-type')) { + overloadCaller.call($invalidEl, 'focus'); + } else { + $invalidEl.focus(); + } + + $invalidEl.parent().parent().addClass('GFEValidationError'); + Glizy.events.broadcast("glizy.message.showError", {"title": lang.errorValidationMsg, "message": ""}); + } + } + } + }); + }, + + getFieldPreview = function (val) { + var preview = overloadCaller.call(this, 'getPreview', val) || val; + return preview && preview != ' ' ? '<div class="GFEPreviewItem">' + this.parent().prevAll('label').first().text() + ' : ' + cutText(htmlStripTags(preview), 30) + '</div>' : ''; + }, + + getFileExtension = function(filename) { + var re = /(?:\.([^.]+))?$/; + return (re.exec(filename)[1]).toLowerCase(); + }, + + verifySelectWithTarget = function($container) { + $container.find('select').each(function () { + var target = $(this).data('target'); + if ( target ) { + $(this).change(function(e){ + var sel = this.selectedIndex, + name = this.name; + states = $(this).data("val_"+sel); + var t = target.split(","); + states = states.split(","); + + $(t).each(function(index, val){ + var elName = name.match(/(\[([^\d])*\])/) ? name.replace(/(\[([^\d])*\])/, "["+val+"]") : val; + $container.find("[name]").each(function(){ + var $el = $(this); + if ($el.attr("name")==elName) { + if (states[index]=="1") { + $el.closest("div.control-group").show(); + } else { + $el.closest("div.control-group").hide(); + } + } + }); + }); + + var container = $(this).closest('.GFERowContainer'); + if (!container.find('.GFERowCollapsed').length) { + var height = container.height(); + container.find('.GFERowHandler img').css('height', height - 4); + } + }); + $(this).trigger("change"); + } + }); + }, + setIndexFields = function() { + // init the index fields; + // gli indici possono essere + // index={tipo} es. index=true, index=int, index=text + // per oggetti complessi + // index={campo:tipo,campo:tipo} es. id:int,type:text + var indexFields = {}; + $("input[data-index], select[data-index]").each(function(index, el){ + var $el = $(el); + var name = $el.attr('name'); + + if (m = name.match(/^([^\[]*)\[([^\]]*)]\[(\d+)\]$/)) { + name = m[1]+'.'+m[2]; + } + var indexType = $el.data('index').split(','); + if (indexType.length==1 && indexType[0].split(':').length==1) { + indexFields[name] = indexType[0]; + } else { + $(indexType).each(function(index, el){ + var parts = el.split(':'); + indexFields[name+'@'+parts[0]] = parts[1]; + }) + } + }); + $("#__indexFields").val(JSON.stringify(indexFields)); + }; + + + $form.find('fieldset[data-type=repeat]').each(function () { + + var $fieldSet = jQuery(this), + fieldSetId = $fieldSet.attr('id'), + opt = getOptions($fieldSet), + $fields = $fieldSet.children(':not(legend)'), + $rowContainer, $footer, firstField, fieldPrev, i, + addLabel = $fieldSet.data('add-label') || lang.addRecord; + + $fieldSet.addClass('GFEFieldset'); + if (!opt.noAddRowButton) { + $fieldSet.append('<div class="GFEFooter"><div class="GFEButtonContainer"><input type="button" value="' + addLabel + '" class="btn GFEAddRow"></div><div class="GFEStatusContainer">' + lang.minRecords + opt.minRec + (opt.maxRec ? (lang.maxRecords + opt.maxRec) : '') + '</div><div class="GFESideClearer"></div></div>'); + } + else { + $fieldSet.append('<div class="GFEFooter"></div>'); + } + + $fields.wrapAll('<div class="GFERowContainer" />'); + + $rowContainer = $fieldSet.children('.GFERowContainer'); + if (opt.isCollapsable) { + $fields.wrapAll('<div class="GFERowExpanded" />'); + + $rowContainer + .append('<div class="GFERowCollapsed"><div class="GFERowHeader"><span class="GFERowHandler"><img width="16" height="38" title="' + lang.drag + '" alt="' + lang.drag + '" src="./application/templates/images/dragHandler.gif"></span><span class="GFERecordTitle">' + lang.record + ' <span class="GFERecordId">1</span></span><span class="GFERowPreview"></span></div><div class="GFERowPanel">'+ + '<a href="#" class=" GFERowEdit" title="' + lang.edit + '" alt="' + lang.edit + '"><span class="btn-icon icon-pencil"></span></a>'+ + '<a href="#" class=" GFERowDelete" title="' + lang.remove + '" alt="' + lang.remove + '"><span class="btn-icon icon-trash"></span></a>'+ + '</div><div class="GFESideClearer"></div></div>') + .children('.GFERowExpanded') + .append('<div class="GFERowButtonContainer"><input type="button" value="' + lang.confirm + '" class="btn btn-primary GFERowDoCollapse GFERowDoConfirm">&nbsp;<input type="button" value="' + lang.cancel + '" class="btn GFERowDoCollapse"></div>') + .hide(); + } + else { + $rowContainer + .append('<span class="GFERowHandler GFERowHandlerExpanded"><img width="16" style="height:' + ($rowContainer.height() - 4) + 'px" title="' + lang.drag + '" alt="' + lang.drag + '" src="./application/templates/images/dragHandler.gif"></span><a href="#" class=" GFERowDelete GFERightIcon" title="' + lang.remove + '" alt="' + lang.remove + '"><span class="btn-icon icon-trash"></span></a>') + + } + var $rowContainerCloned = $rowContainer.clone(true).find("[name]").removeAttr('id').end(); + $rowContainerCloned.find("[name] [type^=checkbox]").val(''); + $fieldSet.data('rowModel', $rowContainerCloned); + $rowContainer.remove(); + + if (!opt.noAddRowButton) { + $fieldSet.prepend('<div class="GFEEmptyMessage">' + (opt.minRec ? lang.noRecordEntered1 + opt.minRec + lang.noRecordEntered2 : lang.clickAddRecordButton.replace('%s', addLabel)) + '</div>'); + } + + var repeaterSetValues = function(repeaterValues) { + $footer = $fieldSet.children('.GFEFooter'); + if (repeaterValues && ( firstField = repeaterValues[$fields.find('[name]').first().attr('name')])) { + for (i = 0; i < firstField.length; i++) { + fieldPrev = ''; + addRow($fieldSet, $footer, i); + $footer.prev().find('[name]').each(function () { + var $this = jQuery(this), + name = this.name.replace(/^[^\[]*\[([^\]]*)]\[\d+\]$/, '$1'), + val; + $this.data('glz-inRepeater', true); + if (repeaterValues[name] && (val = repeaterValues[name][i]) !== undefined) { + var simpleSelect = ($this.prop("tagName") == "SELECT") && (!$this.data("type")); + if (typeof(val)!=='string' && !simpleSelect) { + val = JSON.stringify(val); + } + $this.val(val).data('oldVal', val); + $this.val(val).data('origValue', val); + if (val) fieldPrev += getFieldPreview.call($this, val); + } + }) + .end().find('.GFERowPreview').html(fieldPrev); + } + $fieldSet.syncRecords().makeSortable() + .children('.GFEEmptyMessage').hide(); + } + } + + if (glizyOpt.formData) { + repeaterSetValues(glizyOpt.formData[fieldSetId]); + } + + Glizy.events.on("glizycms.repeater.setValues", function(e) { + if ($fieldSet.attr('id')!=e.message.targetId) return; + $fieldSet.children('.GFERowContainer').remove(); + $fieldSet.syncRecords(); + repeaterSetValues(e.message.data); + }); + + Glizy.events.on("glizycms.fileUpload", function(e) { + if ($fieldSet.attr('id')!=e.message.targetId) return; + $footer = $fieldSet.children('.GFEFooter'); + $rows = $fieldSet.children('.GFERowContainer'); + addRow($fieldSet, $footer, $rows.length, true); + $fieldSet.syncRecords().makeSortable(); + var lastRow = $fieldSet.find('.GFERowContainer:last'); + verifySelectWithTarget($fieldSet); + enableValidation(); + $uploadFilename = lastRow.find('input[name*=uploadFilename]'); + $originalFileName = lastRow.find('input[name*=originalFileName]'); + var ext = getFileExtension(e.message.originalFilename) + var media_allowDownload = lastRow.find('input[name*=media_allowDownload]'); + var media_watermark = lastRow.find('input[name*=media_watermark]') + if(ext == 'tif' || ext =='tiff') { + if(media_allowDownload.length) { + media_allowDownload.prop('checked', false); + } + if(media_watermark.length) { + media_watermark.prop('checked', true); + } + } else { + if(media_allowDownload.length) { + media_allowDownload.prop('checked', true); + } + } + var re = new RegExp("\.(" + imageAllowExt + ")$"); + if (!e.message.originalFilename.match(re)){ + lastRow.find('input[name*=media_watermark]').prop('disabled', 'disabled'); + lastRow.find('input[name*=media_zoom]').prop('disabled', 'disabled'); + } + $title = lastRow.find('input[name*=title]'); + if ($title) { + $uploadFilename.val(e.message.uploadFilename); + $originalFileName.val(e.message.originalFilename); + $title.val(e.message.originalFilename.replace(/\.[^/.]+$/, "")); + } + if (e.message.preview) { + var preview = jQuery('<div class="dropzone-previews"></div>'); + preview.append(jQuery('#'+e.message.preview).clone()); + lastRow.append(preview); + lastRow.addClass('GFERowWithPreview'); + } + }); + }); + + $form.find(':input[name]').each(function () { + var type = $(this).attr('data-type'); + if ( glizyOpt.formData[this.name] !== undefined ) { + jQuery(this).val(glizyOpt.formData[this.name]); + } + jQuery(this).data('origValue', glizyOpt.formData[this.name] || ''); + if ($(this).data('glz-inRepeater')!==true) { + overloadCaller.call(this, '__construct'); + } + }); + + + + + $('#mediaFileServer').change(function(e) { + var ext = getFileExtension($(this).val()); + var re = new RegExp("^(" + imageAllowExt + ")$"); + if(ext === 'tif' || ext === 'tiff'){ + $('[name=media_watermark]').prop('checked', true); + $('[name=media_allowDownload]').prop('checked', false); + $('[name=media_watermark]').prop('disabled', false); + $('[name=media_zoom]').prop('disabled', false); + } else if(!ext.match(re)) { + $('[name=media_watermark]').prop('disabled', 'disabled'); + $('[name=media_zoom]').prop('disabled', 'disabled'); + $('[name=media_watermark]').prop('checked', false); + $('[name=media_allowDownload]').prop('checked', true); + } else { + $('[name=media_allowDownload]').prop('checked', true); + $('[name=media_watermark]').prop('checked', false); + $('[name=media_watermark]').prop('disabled', false); + $('[name=media_zoom]').prop('disabled', false); + } + }); + + verifySelectWithTarget($form); + // enableValidation(); + + jQuery('body').append('<div class="GFETranslucentCover"></div>'); + + jQuery(document).on('click', '.GFERowDoCollapse', function () { + + var $button = jQuery(this), + hasConfirmed = $button.hasClass('GFERowDoConfirm'), + $rowCont = $button.closest('.GFERowContainer'), + $inputFields = jQuery('input:not([type=button]), textarea', $rowCont), + fieldPrev = ''; + + if (hasConfirmed && ($form.triggerHandler('submitForm') === false && invalidFields || customValidationInvalid)) { + customValidationInvalid = false; + return; + } + $rowCont.removeClass('GFEEditingRow').children('.GFERowCollapsed').show() + .end().children('.GFERowExpanded').hide(); + + if (hasConfirmed) { + $inputFields.each(function () { + var $this = jQuery(this), + val = overloadCaller.call(this, 'getValue') || $this.val(); + + if (val) { + $this.data('oldVal', val); + fieldPrev += getFieldPreview.call($this, val); + } + }); + jQuery('.GFERowPreview', $rowCont).html(fieldPrev); + $rowCont.removeData('justCreated'); + } + else { + $inputFields.each(function () { + + var $this = jQuery(this); + + overloadCaller.call(this, 'setValue', $this.data('oldVal') || ''); + + if (!$this.data('overloadCalled')) { + $this.val($this.data('oldVal') || ''); + } + $this.removeClass('GFEValidationError'); + }); + if ($rowCont.data('justCreated')) { + $rowCont.remove(); + } + } + + jQuery('.GFETranslucentCover').hide(); + }); + + jQuery(document).on('click', '.GFERowEdit', function (e) { + e.preventDefault(); + var $container = jQuery(this).closest('.GFERowContainer'), + $contBound = $container[0].getBoundingClientRect(), + $window = jQuery(window), + wHeight = $window.height(); + + $container.addClass('GFEEditingRow') + .children('.GFERowCollapsed').hide() + .end().children('.GFERowExpanded').show(); + + $window.scrollTop($container.offset().top - Math.max((wHeight - $container.height()) / 2, 0)); + + jQuery('.GFETranslucentCover').show(); + }); + + jQuery(document).on('click', '.GFERowDelete', function (e) { + e.preventDefault(); + + var $container = jQuery(this).closest('.GFERowContainer'), + $fieldSet = $container.parent(), + $rows = $fieldSet.children('.GFERowContainer'), + opt = getOptions($container); + + var i = $container.index() - 1; + overloadCaller.call($('#fileuploader'), 'removeFile', i); + + if ($rows.length == opt.minRec) { + Glizy.events.broadcast("glizy.message.showError", {"title": lang.minRecordMsg + opt.minRec, "message": ""}); + return; + } + jQuery('.GFEAddRow').removeClass('GButtonDisabled').removeAttr('disabled'); + $container.remove(); + + if (!$fieldSet.children('.GFERowContainer').length) { + jQuery('.GFEEmptyMessage').show(); + } + + $fieldSet.syncRecords(); + }); + + jQuery('.GFEAddRow').click(function () { + + var $button = jQuery(this), + $fieldSet = $button.closest('fieldset'), + opt = getOptions($fieldSet), + $rows = $fieldSet.children('.GFERowContainer'); + + if ($button.hasClass('GButtonDisabled')) { + return; + } + if (opt.maxRec && $rows.length == opt.maxRec -1) { + $button.addClass('GButtonDisabled').attr('disabled', 'disabled').blur(); + } + jQuery('.GFEEmptyMessage').hide(); + + addRow($fieldSet, $button.closest('.GFEFooter'), $rows.length, true); + + $fieldSet.syncRecords().makeSortable(); + $fieldSet.find('.GFERowEdit:last').click(); + + verifySelectWithTarget($fieldSet); + enableValidation(); + }); + + var setFormButtonStates = function(state) { + if (state) { + jQuery('.js-glizycms-cancel').removeAttr('disabled'); + jQuery('.js-glizycms-save').removeAttr('disabled'); + } else { + jQuery('.js-glizycms-cancel').attr('disabled', 'disabled'); + jQuery('.js-glizycms-savecomment').attr('disabled', 'disabled'); + jQuery('.js-glizycms-save').attr('disabled', 'disabled'); + } + } + var saveOrCancelSuccess = function(data, triggerAction, titleChanged) { + setFormButtonStates(true); + if (data.evt) { + window.parent.Glizy.events.broadcast(data.evt, data.message); + } else if (data.url) { + if (data.target == 'window') { + parent.window.location.href = data.url; + } else { + document.location.href = data.url; + } + } else if (data.set) { + $.each(data.set, function(id, value){ + $('#'+id).val(value); + }); + Glizy.events.broadcast("glizy.message.showSuccess", {"title": lang.saveSuccessMsg, "message": ""}); + } else if (data.callback) { + window[data.callback](data); + } else if (data.errors) { + // TODO localizzare + var errorMsg = '<p>Impossibile salvare questo documento, a causa dei seguenti errori:</p><ul>'; + $.each(data.errors, function(id, value) { + errorMsg += '<li><p class="alert alert-error">'+value+'</p></li>'; + }); + Glizy.events.broadcast("glizy.message.showError", {"title": lang.errorValidationMsg+' '+errorMsg, "message": ""}); + } else { + if (triggerAction) { + $(triggerAction).trigger('click'); + } else { + Glizy.events.broadcast("glizy.message.showSuccess", {"title": lang.saveSuccessMsg, "message": ""}); + } + } + + if (titleChanged===true) { + Glizy.events.broadcast("glizycms.renameTitle"); + } + } + jQuery('.js-glizycms-cancel').click(function (e) { + e.preventDefault(); + setFormButtonStates(false); + jQuery.ajax(glizyOpt.AJAXAction, { + data: jQuery.param({action: $(e.currentTarget).data("action")}), + type: "POST", + success: function(data){ + saveOrCancelSuccess(data); + } + }); + }); + + jQuery('.js-glizycms-savecomment').click(function (e){ + enableValidation(); + e.preventDefault(); + var $el = jQuery(this); + var newId = $el.attr('id')+'_textare'; + var isCancelled = false; + + var pos = Glizy.events.on('glizy.closeDialog', function(e){ + Glizy.events.unbind('glizy.closeDialog', pos); + if (isCancelled) return; + $el.val(e.message[newId]); + jQuery('.js-glizycms-save').trigger('click'); + $el.val(undefined); + }) + + var buttons = {}; + buttons[lang.save] = function() { + Glizy.closeDialog(); + }; + buttons[lang.cancel] = function() { + isCancelled = true; + Glizy.closeDialog(); + }; + Glizy.openDialog( + '<div><textarea id="'+newId+'" class="GFEcomments">'+$el.val()+'</textarea></div>', + { + autoOpen: true, + height: 300, + width: 650, + modal: true, + title: lang.insertComment, + buttons: buttons + }); + }); + + jQuery('.js-glizycms-save').click(function (e) { + enableValidation(); + setIndexFields(); + e.preventDefault(); + + var data = {}; + var titleChanged = false; + + if ($form.triggerHandler('submitForm') === false && invalidFields || customValidationInvalid) { + customValidationInvalid = false; + return; + } + setFormButtonStates(false); + $form.find('fieldset[data-type=repeat]').each(function () { + var el = jQuery(this); + data[el.attr('id')] = {}; + }); + $form.find('[name]:not([type=button],[type=submit])').each(function () { + var el = jQuery(this); + var val = overloadCaller.call(this, 'getValue'), m; + + if (val === undefined) { + val = el.val(); + } + titleChanged = titleChanged || (el.attr('name') == '__title' && val!=el.data('origValue')); + + if (val !== undefined) { + // name = this.name.replace(/[^\[]*\[([^\]]*)]\[\d\]$/, '$1'), + // if (m = this.name.match(/^(.*)\[(\d+)\]$/)) { + if (m = this.name.match(/^([^\[]*)\[([^\]]*)]\[(\d+)\]$/)) { + if (!data[m[1]]) data[m[1]] = {}; + if (!data[m[1]][m[2]]) data[m[1]][m[2]] = []; + data[m[1]][m[2]][parseInt(m[3])] = val; + } + else { + data[this.name] = val; + } + } + }); + + var triggerAction = $(e.currentTarget).data("trigger"); + jQuery.ajax(glizyOpt.AJAXAction, { + data: jQuery.param({action: $(e.currentTarget).data("action"), data: JSON.stringify(data)}), + type: "POST", + success: function(data){ + saveOrCancelSuccess(data, triggerAction, titleChanged); + } + }); + }); + + Glizy.events.broadcast("glizycms.formEdit.onReady"); + return this; + }; + + $.fn.scrollToVisible = function () { + + var $window = jQuery(window), + wHeight = $window.height(); + + return this.each(function () { + + var contBound = this.getBoundingClientRect(); + + if (wHeight < contBound.bottom || contBound.top < 0) { + $window.scrollTop(jQuery(this).offset().top -10); + } + }); + }; + +})( jQuery )); diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditCheckbox.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditCheckbox.js new file mode 100644 index 0000000..f43391c --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditCheckbox.js @@ -0,0 +1,72 @@ +jQuery.GlizyRegisterType('checkbox', { + + __construct: function () { + var self = this; + var format = $(this).data('format'); + var group = $(this).data('group'); + if (format) { + format = format.split('/'); + } else { + format = [0, 1]; + } + + if (group) { + group += $(this).attr('name').replace(/\[\w*\]/, ''); + } + + $(this).on('change', function(e){ + self._getValue(); + if (group) { + Glizy.events.broadcast("glizycms.checkbox.group", {group: group, checked: $(self).attr('name') }); + } + }); + + this._setValue = function(v) { + if (v===undefined) { + var value = $(this).data('origValue'); + var currentValue = $(this).val(); + if (currentValue=='true') { + currentValue = '1'; + } + if (value!=='' && value!== undefined && value!=currentValue) { + value = currentValue; + jQuery(this).data('origValue', value); + } + } else { + value = v; + } + + $(this).attr('checked', value == format[1]); + } + + this._getValue = function() { + var value = format[ $(this)[0].checked ? 1 : 0]; + $(this).data('origValue', value); + $(this).val(value); + return value; + } + + if (group) { + Glizy.events.on("glizycms.checkbox.group", function(e){ + if (group==e.message.group) { + $(self)[0].checked = $(self).attr('name')==e.message.checked; + self._getValue(); + } + }); + } + + this._setValue(); + }, + + getValue: function () { + return this._getValue(); + }, + + setValue: function (value) { + this._setValue(value); + }, + + destroy: function () { + $(this).off("change"); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditCmsPagePicker.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditCmsPagePicker.js new file mode 100644 index 0000000..72e4fb8 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditCmsPagePicker.js @@ -0,0 +1,65 @@ +jQuery.GlizyRegisterType('CmsPagePicker', { + + __construct: function () { + var el = $(this); + el.removeAttr('value'); + + var controllerName = $(this).data('controllername'); + var filterType = $(this).data('filtertype') || ''; + var protocol = $(this).data('protocol') || ''; + var multiple = $(this).data('multiple'); + + el.select2({ + placeholder: '', + allowClear: true, + multiple: multiple, + minimumInputLength: 3, + ajax: { + url: Glizy.ajaxUrl + "&controllerName="+controllerName+"&filterType="+filterType+"&protocol="+protocol, + dataType: 'json', + quietMillis: 100, + data: function(term) { + return { + term: term + }; + }, + results: function(data, page ) { + return { results: data } + } + }, + formatResult: function(data) { + return data.text+'<br><small>'+data.path+'</small>'; + }, + formatSelection: function(data) { + return data.text+' <small>'+data.path+'</small>'; + } + }); + + var value = el.data('origValue'); + if (value) { + $.ajax({ + url: Glizy.ajaxUrl + "&controllerName="+controllerName, + dataType: 'json', + data: {id: value}, + success: function(data) { + el.select2('data', multiple ? data : data[0]); + } + }); + } + }, + + getValue: function () { + return $(this).select2('val'); + }, + + setValue: function (value) { + if (value && value.length && value[0].id) { + $(this).select2('data', value); + } + }, + + destroy: function () { + $(this).data('origValue', $(this).val()); + $(this).select2('destroy'); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditColorPicker.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditColorPicker.js new file mode 100644 index 0000000..7da69ad --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditColorPicker.js @@ -0,0 +1,31 @@ +jQuery.GlizyRegisterType('colorPicker', { + __construct: function () { + var self = $(this).data('formEdit'); + self.element = $(this); + + self.element.css('width', 150); + self.element.after('<div style="width: 28px; height:28px; float: left; border: 1px solid #e0e0e0;background-color:'+self.element.val()+'"></div>'); + + self.element.colorpicker().on('changeColor', function(ev){ + var el = $(ev.currentTarget); + el.next().css('background-color', ev.color.toHex()); + }); + + self.element.on('change', function(e) { + var el = $(e.currentTarget); + el.next().css('background-color', el.val()); + }); + + }, + + getValue: function () { + return $(this).val(); + }, + + setValue: function (value) { + $(this).val(value); + }, + + destroy: function () { + } +}); diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditDate.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditDate.js new file mode 100644 index 0000000..e43aad6 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditDate.js @@ -0,0 +1,29 @@ +jQuery.GlizyRegisterType('date', { + + __construct: function () { + var format = $(this).data('format') ? $(this).data('format') : GlizyLocale.date.format; + + $(this).datetimepicker({ + language: 'it', + minView: 'month', + format: format, + autoclose: true, + todayHighlight: true + }); + }, + + getValue: function () { + return $(this).val(); + }, + + setValue: function (value) { + $(this).val(value); + }, + + destroy: function () { + }, + + focus: function () { + document.getElementById($(this).attr('id')).scrollIntoView(); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditDatetime.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditDatetime.js new file mode 100644 index 0000000..0500a66 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditDatetime.js @@ -0,0 +1,24 @@ +jQuery.GlizyRegisterType('datetime', { + + __construct: function () { + var format = $(this).data('format') ? $(this).data('format') : GlizyLocale.datetime.format; + + $(this).datetimepicker({ + language: 'it', + format: format, + autoclose: true, + todayHighlight: true + }); + }, + + getValue: function () { + return $(this).val(); + }, + + setValue: function (value) { + $(this).val(value); + }, + + destroy: function () { + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditFile.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditFile.js new file mode 100644 index 0000000..3838899 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditFile.js @@ -0,0 +1,62 @@ +jQuery.GlizyRegisterType('file', { + __construct: function () { + var self = this; + self.el = $(this); + self.el.hide(); + var isWaiting = false; + var queue = []; + var uploadedFileCount = 0; + + self.init = function() { + var maxFiles = self.el.data('maxfiles'); + var maxFilesize = self.el.data('maxfilesize') || 256; + var acceptedFiles = self.el.data('acceptedfiles'); + var dropId = self.el.attr('id')+'dropDiv'; + self.dropDiv = jQuery('<div id="'+dropId+'" class="glizy-dropzone"><p>'+GlizyLocale.FineUploader.uploadButton+' (' + GlizyLocale.FineUploader.maxsize + ': '+self.el.data('maxlabel')+')'+'</p></div>').insertAfter(self.el); + var myDropzone = new Dropzone("div#"+dropId, { + url: "uploader.php", + maxFiles: maxFiles, + maxFilesize: maxFilesize, + acceptedFiles: acceptedFiles + }); + myDropzone.on("addedfile", function(file) { + self.dropDiv.find('p').hide(); + uploadedFileCount++; + file.__id = uploadedFileCount; + file.__status = 0; + file.__previewId = 'fileUpload-'+file.__id; + var preview = self.dropDiv.find('.dz-preview:last'); + preview.attr('id', file.__previewId); + }); + myDropzone.on("success", function(file, response) { + response.preview = file.__previewId; + response.targetId = self.el.data('fieldsetid'); + self.dispatchDelayed(response); + }); + }; + + + self.dispatchDelayed = function(info) { + if (!isWaiting) { + isWaiting = true; + setTimeout(function () { + isWaiting = false; + Glizy.events.broadcast("glizycms.fileUpload", info); + if ( queue.length) { + info = queue.pop(); + self.dispatchDelayed(info); + } + }, 500); + } else { + queue.push(info); + } + } + + + self.init(); + }, + + destroy: function () { + } +}); + diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditGUID.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditGUID.js new file mode 100644 index 0000000..ebd2d75 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditGUID.js @@ -0,0 +1,20 @@ +jQuery.GlizyRegisterType('inputguid', { + __construct: function () { + var self = $(this).data('formEdit'); + self.element = $(this); + if (''==self.element.val()) { + self.element.val(self.element.data('base')+(new Date().getTime())); + } + }, + + getValue: function () { + return $(this).val(); + }, + + setValue: function (value) { + $(this).val(value); + }, + + destroy: function () { + } +}); diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditGoogleMaps.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditGoogleMaps.js new file mode 100644 index 0000000..34683fe --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditGoogleMaps.js @@ -0,0 +1,272 @@ +jQuery.GlizyRegisterType('googlemaps', { + + __construct: function () { + // var self = $(this).data('formEdit'); + // self.element = $(this); + // self.render(); + + var self = this; + self.element = $(this); + // el.removeAttr('value'); + + + self.render = function() { + var self = this; + if (this.element.data('isInit')!==true) { + var name = this.element.attr('name'), + html = jQuery('<input id="'+name+'-search" class="btn" type="button" value="'+GlizyLocale.FormEdit.search+'"/>'); + this.element.after(html); + this.element.addClass("span10"); + this.element.data('isInit', true); + } + + if (jQuery("#GlizyFormEditgooglemaps").length == 0) { + window.GlizyFormEditgooglemaps = {}; + html = '<div id="GlizyFormEditgooglemaps" class="mapPicker" style="width: 600px; height: 400px; background: #fff; border: 1px solid #ccc; padding: 5px; position: absolute; z-index: 3000; display: none;"></div>'; + jQuery('body').append(html); + + window.GlizyFormEditgooglemaps.geocoder = new google.maps.Geocoder(); + + var pos = this.getDefaultCurrentPosition(); + var latlng = new google.maps.LatLng(pos[ 0 ], pos[ 1 ]); + var myOptions = { + zoom: pos[ 2 ], + center: latlng, + mapTypeId: google.maps.MapTypeId.HYBRID, + mapTypeControl: false, + disableDoubleClickZoom: true, + streetViewControl: false + }; + + window.GlizyFormEditgooglemaps.map = new google.maps.Map( jQuery("#GlizyFormEditgooglemaps").get(0), myOptions); + window.GlizyFormEditgooglemaps.marker = new google.maps.Marker({ + position: latlng, + map: window.GlizyFormEditgooglemaps.map, + title: "Trascinami", + draggable: true + }); + } + + this.map = window.GlizyFormEditgooglemaps.map; + this.marker = window.GlizyFormEditgooglemaps.marker; + this.geocoder = window.GlizyFormEditgooglemaps.geocoder; + this.elementMap = jQuery("#GlizyFormEditgooglemaps"); + + this.elementMap.click(function( e ) { + if ( e.stopPropagation ) { + e.stopPropagation(); + } + e.cancelBubble = true; + } ); + + this.element.click(function( e ) { + if ( e.stopPropagation ) { + e.stopPropagation(); + } + e.cancelBubble = true; + } ); + + jQuery(document).click( function( e ) { + self.closeMap(); + } ); + + + this.element.next().click( function( e ) { + if ( e.stopPropagation ) { + e.stopPropagation(); + } + e.cancelBubble = true; + self.search(); + } ); + + this.element.keyup( function( e ) { + var charCode = e.charCode || e.keyCode || e.which; + if (charCode == 13){ + if ( e.stopPropagation ) { + e.stopPropagation(); + } + e.cancelBubble = true; + self.search(); + } + } ); + + }, + + self.trim = function (str) + { + var str = str.replace(/^\s\s*/, ''), + ws = /\s/, + i = str.length; + while (ws.test(str.charAt(--i))); + return str.slice(0, i + 1); + }, + + self.roundDecimal = function( num, decimals ) + { + var mag = Math.pow(10, decimals); + return Math.round(num * mag)/mag; + }, + + self.getDefaultCurrentPosition = function() + { + var posStr = this.element.val(); + if(posStr != "") + { + var posArr = posStr.split(","); + if(posArr.length == 2 || posArr.length == 3 ) + { + var lat = this.trim( posArr[0] ); + var lng = this.trim( posArr[1] ); + var zoom = posArr.length == 3 ? parseInt( this.trim( posArr[2] ) ) : 15; + return [lat, lng, zoom ]; + } + } + return [ 51.500152, -0.126236, 15 ]; + }, + + self.getCurrentPosition = function() + { + var pos = this.getDefaultCurrentPosition(); + var latlng = new google.maps.LatLng(pos[ 0 ], pos[ 1 ]); + this.setPosition(latlng); + }, + + self.setPosition = function(latLng, viewport) + { + var lat = this.roundDecimal( latLng.lat(), 6 ); + var lng = this.roundDecimal( latLng.lng(), 6 ); + this.marker.setPosition( latLng ); + var zoom; + if ( viewport ) + { + this.map.fitBounds( viewport ); + this.map.setZoom( this.map.getZoom() + 2); + zoom = this.map.getZoom() + 2; + } + else + { + this.map.panTo(latLng); + zoom = this.map.getZoom(); + } + this.map.setZoom( zoom ); + this.element.val(lat + "," + lng+","+zoom); + // this.setValue( lat + "," + lng+","+zoom ); + }, + + self.setPositionValues = function() + { + if( this.elementMap.css("display") != "none") + { + var pos = this.getDefaultCurrentPosition(); + pos[ 2 ] = this.map.getZoom(); + this.element.val( pos.join( "," ) ); + //this.setValue( pos.join( "," ) ); + } + }, + + self.isLngLat = function (val) + { + var lngLatArr = val.split(","); + if(lngLatArr.length == 2 || lngLatArr.length == 3 ){ + if(isNaN(lngLatArr[0]) || isNaN(lngLatArr[1])){ + return false; + }else{ + return true; + } + } + return false; + }, + + self.openMap = function() + { + var self = this; + google.maps.event.clearListeners(this.map, 'dblclick'); + google.maps.event.clearListeners(this.map, 'idle'); + google.maps.event.clearListeners(this.marker, 'dragend'); + + google.maps.event.addListener( this.map, 'dblclick', function(event) { + self.setPosition( event.latLng ); + }); + + google.maps.event.addListener( this.marker, 'dragend', function(event) { + self.setPosition( self.marker.position ); + }); + + google.maps.event.addListener( this.map, 'idle', function(event) { + self.setPositionValues(); + }); + + this.elementMap.css("left", this.element.offset().left); + this.elementMap.css("top", this.element.offset().top); + this.elementMap.css("width", this.element.width()); + this.elementMap.css("display", "block"); + google.maps.event.trigger( this.map, 'resize'); + this.map.setCenter( this.marker.position ); + }, + + self.closeMap = function() + { + google.maps.event.clearListeners(this.map, 'dblclick'); + google.maps.event.clearListeners(this.map, 'idle'); + google.maps.event.clearListeners(this.marker, 'dragend'); + this.elementMap.css("display", "none"); + }, + + self.search = function() + { + this.findAddress(); + }, + + self.findAddress = function() + { + var self = this; + var address = this.element.val(); + if(address == ""){ + alert(GlizyLocale.FormEdit.googleMapError_1); + }else{ + if(this.isLngLat(address)){ + self.getCurrentPosition(); + // self.setPosition( + // results[0].geometry.location, + // results[0].geometry.viewport + // ); + this.openMap(); + }else{ + this.geocoder.geocode( {'address': address.replace(/\'/g, '\\\'')}, function(results, status) { + if (status == google.maps.GeocoderStatus.OK) { + self.setPosition( + results[0].geometry.location, + results[0].geometry.viewport + ); + self.openMap(); + } else { + alert(GlizyLocale.FormEdit.googleMapError_1+": " + status); + } + }); + } + this.focus(); + } + } + + self.render(); + + }, + + getValue: function () { + return $(this).val(); + }, + + setValue: function (value) { + $(this).val(value); + }, + + destroy: function () { + }, + + + + focus: function() + { + this.element.focus(); + } +}); diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditImageHotspot.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditImageHotspot.js new file mode 100644 index 0000000..85d4e99 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditImageHotspot.js @@ -0,0 +1,1082 @@ +jQuery.GlizyRegisterType('imageHotspot', { + // rendere gli hotspot modificabili: sia come dimensione che come posizione + // togliere la checkbox disegna, si disegna sempre, in modalità edit non ci deve essere qtip ed il link + // mettere quadrangolare / circle come costanti della classe + // mettere i vari tipi come costanti della classe così da non dovver ripetere sempre la stessa stringa + // anche cliccando sull'hotspot devi selezionarlo per modificarlo + // impostare la larghezza hotspots-container dopo che si è letta l'immagine altrimenti su finestra piccola l'immagine va accapo rispetto alla colonna degli hotspot + // + __construct: function () { + var self = this; + var el = $(this); + el.removeAttr('value'); + el.hide(); + + self.el = el; + self.glizyOpt = el.data('glizyOpt'); + self.data = {}; + self.btnLoadImage = null; + self.image = null; + self.id = null; + self.selected = -1; + self.dragresize = null; + self.dragres = false; + self.init = function() { + var hotspotsContainer = $('<div/>') + .addClass('hotspots-container'); + var btnContainer = $('<div/>') + .addClass('btn-container'); + var btnLoadImage = $('<button/>') + .attr('class', 'js-loadImage') + .text(GlizyLocale.HotSpot.loadImage) + .click(function(evt) { + evt.preventDefault(); + self.onLoadImageClick(); + }); + btnContainer.append(btnLoadImage); + var btnAddTrack = $('<button/>') + .css('margin-left', 5) + .text(GlizyLocale.HotSpot.addPath) + .click(function(evt) { + evt.preventDefault(); + var id = self.calcId(); + self.createDefault(id); + self.saveHotspot(id); + self.addTrack(id); + self.selectHotspot(id); + + $("#hotspotsList").animate({ scrollTop: $('#hotspotsList')[0].scrollHeight}, 500); + }); + btnContainer.append(btnAddTrack); + hotspotsContainer.append(btnContainer); + + var hotspotsList = $('<div/>') + .attr('id', 'hotspotsList') + .addClass('hotspots-list'); + hotspotsContainer.append(hotspotsList); + var hotspotsImage = $('<div/>') + .attr('id', 'hotspots-image') + .addClass('hotspots-image'); + var image = $('<img/>') + .attr('id', 'image') + .addClass('js-image') + .attr('src', '') + .css('display', 'none') + .load({container: hotspotsContainer, list: hotspotsList}, function(e) { + var h = $(this).height() + 8; + contH = h + 45; + e.data.container.css('height', contH); + e.data.list.css('height', h); + + var w = $(this).width() + 330; + e.data.container.css('width', w); + self.dragRes(); + }); + self.image = image; + hotspotsImage.append(image); + hotspotsImage.append($('<div/>').attr('id', 'selectionMarquee')); + hotspotsContainer.append(hotspotsImage); + + el.parent().before(hotspotsContainer); + + /*var html = $('<div class="imageHotSpot">'+ + '<button class="js-loadImage">Carica immagine</button>'+ + '<button class="js-loadImage">Aggiungi tracciato</button>'+ + '<img class="js-image" src="" style="display: none">'+ + '</div>');*/ + + /*el.parent().before(html); + self.btnLoadImage = html.find('.js-loadImage').first(); + self.image = html.find('.js-image').first(); + + self.btnLoadImage.click(function(evt){ + evt.preventDefault(); + self.onLoadImageClick(); + })*/ + + // reimposta i valori + var value = el.data('origValue'); + if (value) { + // console.log(value) + self.data = JSON.parse(value); + self.setImage({id: self.data.image}); + self.loadHotspots(); + }; + }; + + self.onLoadImageClick = function() { + var url = self.glizyOpt.mediaPicker; + url += '&mediaType=IMAGE'; + Glizy.openIFrameDialog( GlizyLocale.MediaPicker.imageTitle, + url, + 900, + 50, + 50, + el.data('formEdit').openDialogCallback ); + Glizy.lastMediaPicker = self; + }; + + self.setImage = function(image) { + if (image) { + self.image.attr('src', + Glizy.tinyMCE_options.urls.imageResizer + .replace('#id#', image.id) + .replace('#w#', '') + .replace('#h#', '') + ); + self.image.show(); + + self.data.image = image.id; + self.storeValue(); + } + }; + + self.loadHotspots = function() { + if(!self.data.hotspots) + self.data.hotspots = []; + for (var i=0; i<self.data.hotspots.length; i++) { + self.addTrack(self.data.hotspots[i].id); + }; + }; + + self.createDefault = function(id) { + self.hotspot = { + id: id, + top: 0, + left: 0, + height: 0, + width: 0, + form: 'rect', + type: 'linkEx', + description: '', + src: '', + srcInt: '' + }; + }; + + self.selectHotspot = function(id) { + for (var i=0; i<self.data.hotspots.length; i++) { + var ind = self.data.hotspots[i].id; + $('#hotspot_'+ind).removeClass('selected'); + $('#hotspot'+ind).removeClass('selected'); + if(document.getElementById('hotspot'+ind)); + self.dragresize.deselect(document.getElementById('hotspot'+ind)); + }; + $('#hotspot_'+id).addClass('selected'); + $('#hotspot'+id).addClass('selected'); + self.hotspot = _.findWhere(self.data.hotspots, {id: id}); + self.selected = id; + self.printHotspot(id); + if(document.getElementById('hotspot'+id)) + self.dragresize.select(document.getElementById('hotspot'+id)); + }; + + self.addTrack = function(id) { + self.hotspot = _.findWhere(self.data.hotspots, {id: id}); + var hotspotContainer = $('<div/>') + .attr('id', 'hotspot_'+id) + .addClass('hotspot') + .click(function() { + self.selectHotspot(id); + }); + var closeDiv = $('<div/>') + .addClass('delete'); + var close = $('<a/>') + .attr('href', '#') + .text('X') + .click(function(evt) { + evt.preventDefault(); + self.removeHotspot(id); + }); + closeDiv.append(close); + hotspotContainer.append(closeDiv); + + var formDiv = $('<div/>') + .addClass('list-container') + .css('clear', 'both'); + var label = $('<label/>') + .attr('for', 'form_'+id) + .addClass('label') + .addClass('list-label') + .text(GlizyLocale.HotSpot.hotspotForm); + formDiv.append(label); + var form = $('<select/>') + .attr('id', 'form_'+id) + .addClass('list-select') + .click(function() { + self.selectHotspot(id); + }) + .change(function() { + self.changeForm($(this), id); + }); + var opt = $('<option value="rect"/>') + .text(GlizyLocale.HotSpot.formQuad); + form.append(opt); + opt = $('<option value="circle"/>') + .text(GlizyLocale.HotSpot.formCircle); + form.append(opt); + formDiv.append(form); + hotspotContainer.append(formDiv); + form.val(self.hotspot.form); + + var typeDiv = $('<div/>') + .addClass('list-container') + .css('clear', 'both'); + var label = $('<label/>') + .attr('for', 'type_'+id) + .addClass('label') + .addClass('list-label') + .text(GlizyLocale.HotSpot.hotspotType); + typeDiv.append(label); + var type = $('<select/>') + .attr('id', 'type_'+id) + .addClass('list-select') + .click(function() { + self.selectHotspot(id); + }) + .change(function() { + self.changeType($(this), id); + }); + opt = $('<option value="linkEx"/>') + .text(GlizyLocale.HotSpot.linkEx); + type.append(opt); + opt = $('<option value="link"/>') + .text(GlizyLocale.HotSpot.linkInt); + type.append(opt); + opt = $('<option value="tooltip"/>') + .text(GlizyLocale.HotSpot.tooltip); + type.append(opt); + typeDiv.append(type); + hotspotContainer.append(typeDiv); + type.val(self.hotspot.type); + + var description = $('<textarea/>') + .attr('id', 'description_'+id) + .attr('placeholder', GlizyLocale.HotSpot.description) + .addClass('list-description') + .keyup(function() { + self.updateDescription($(this), id); + }); + hotspotContainer.append(description); + description.text(self.hotspot.description); + $('#hotspotsList').append(hotspotContainer); + + var urlDiv = $('<div/>') + .attr('id', 'urlDiv_'+id) + .addClass('list-container') + .css('clear', 'both'); + var label = $('<label/>') + .attr('for', 'url_'+id) + .addClass('label') + .addClass('list-label') + .text(GlizyLocale.HotSpot.urlEx); + urlDiv.append(label); + var url = $('<input/>') + .attr('id', 'url_'+id) + .attr('type', 'text') + .addClass('list-url') + .blur(function() { + self.updateUrl($(this), id); + }); + urlDiv.append(url); + hotspotContainer.append(urlDiv); + url.val(self.hotspot.src); + + var urlIntDiv = $('<div/>') + .attr('id', 'urlIntDiv_'+id) + .addClass('list-container') + .css('clear', 'both'); + var label = $('<label/>') + .attr('for', 'urlInt_'+id) + .addClass('label') + .addClass('list-label') + .text(GlizyLocale.HotSpot.urlInt); + urlIntDiv.append(label); + var urlInt = $('<input/>') + .attr('id', 'urlInt_'+id) + .attr('type', 'text') + .addClass('list-url') + .blur(function() { + self.updateUrlInt($(this), id); + }); + urlIntDiv.append(urlInt); + hotspotContainer.append(urlIntDiv); + urlInt.val(self.hotspot.srcInt); + + + urlInt.select2({ + placeholder: '', + allowClear: true, + minimumInputLength: 3, + ajax: { + url: Glizy.ajaxUrl + "&controllerName=org.glizycms.contents.controllers.autocomplete.ajax.PagePicker", + dataType: 'json', + quietMillis: 100, + data: function(term) { + return { + term: term + }; + }, + results: function(data, page ) { + return { results: data } + } + }, + formatResult: function(data) { + return data.text+'<br><small>'+data.path+'</small>'; + }, + formatSelection: function(data) { + this.element.val(data.id); + this.element.trigger("blur"); + return data.text+' <small>'+data.path+'</small>'; + } + }); + self.changeType(type, id); + + if (self.hotspot.srcInt) { + $.ajax({ + url: Glizy.ajaxUrl + "&controllerName=org.glizycms.contents.controllers.autocomplete.ajax.PagePicker", + dataType: 'json', + data: {id: self.hotspot.srcInt}, + success: function(data) { + var oldHotspot = self.hotspot; + self.hotspot = _.findWhere(self.data.hotspots, {id: id}); + urlInt.select2('data', data[0]); + self.hotspot = oldHotspot; + } + }); + } + + if(self.hotspot.height != 0 && self.hotspot.width != 0) { + self.drawHotspot(id); + }; + }; + + self.storeValue = function() { + self.el.val(JSON.stringify(self.data)); + }; + + self.calcId = function() { + if(!self.data.hotspots) + self.data.hotspots = []; + var id = -1; + for (var i=0; i<=self.data.hotspots.length; i++) { + var ind = self.data.hotspots.indexOf(_.findWhere(self.data.hotspots, {id: i})); + if(ind == -1) { + id = i; + i = self.data.hotspots.length; + }; + }; + return id; + }; + + self.drawHotspot = function(id) { + $('#hotspot'+id).remove(); + $selectedBox = $('<div/>') + .attr('id', 'hotspot'+id) + .addClass('selected-box') + .addClass('drsElement') + .addClass('drsMoveHandle') + .mousedown(function() { + self.selectHotspot(id); + }); + if(self.hotspot.form == 'circle') { + $selectedBox.addClass('hotspot-circle'); + } + else { + $selectedBox.removeClass('hotspot-circle'); + }; + $selectedBox.hide(); + $('.hotspots-image').append($selectedBox); + $selectedBox.css('top', self.hotspot.top) + .css('left', self.hotspot.left) + .css('height', self.hotspot.height) + .css('width', self.hotspot.width) + .css('margin', 4); + $selectedBox.show(); + self.createHotspot(id); + }; + + self.printHotspot = function(id) { + var $selectionMarquee = $('#selectionMarquee'); + $('#image').off('mousedown') + .off('mouseup'); + $selectionMarquee.off('mouseup'); + + var startX, + startY, + selectedBox; + + if($('#form_'+id).val() == 'circle') { + $selectionMarquee.addClass('hotspot-circle'); + } + else { + $selectionMarquee.removeClass('hotspot-circle'); + }; + + positionBox = function ($box, coordinates, save) { + if(save) { + self.hotspot.top = coordinates.top; + self.hotspot.left = coordinates.left; + self.hotspot.height = coordinates.bottom - coordinates.top; + self.hotspot.width = coordinates.right - coordinates.left; + }; + $box.css('top', coordinates.top) + .css('left', coordinates.left) + .css('height', coordinates.bottom - coordinates.top) + .css('width', coordinates.right - coordinates.left) + .css('margin', 4); + }, + + compareNumbers = function (a, b) { + return a - b; + }, + + getBoxCoordinates = function (startX, startY, endX, endY) { + var x = [startX, endX].sort(compareNumbers), + y = [startY, endY].sort(compareNumbers); + + return { + top: y[0], + left: x[0], + right: x[1], + bottom: y[1] + }; + }, + + trackMouse = function (event) { + event.preventDefault(); + var endX = (event.clientX - $('#image').offset().left + window.pageXOffset); + var endY = (event.clientY - $('#image').offset().top + window.pageYOffset); + var position = getBoxCoordinates(startX, startY, endX, endY); + positionBox($selectionMarquee, position); + }, + + mouseDown = function (event) { + if(!self.dragres) { + event.preventDefault(); + startX = (event.clientX - $('#image').offset().left + window.pageXOffset); + startY = (event.clientY - $('#image').offset().top + window.pageYOffset); + positionBox($selectionMarquee, getBoxCoordinates(startX, startY, startX, startY)); + $selectionMarquee.show(); + $(this).on('mousemove', trackMouse); + }; + }, + + mouseUp = function (event) { + if(!self.dragres) { + var position, + $selectedBox; + $selectionMarquee.hide(); + var endX = (event.clientX - $('#image').offset().left + window.pageXOffset); + var endY = (event.clientY - $('#image').offset().top + window.pageYOffset); + + position = getBoxCoordinates(startX, startY, endX, endY); + + if (position.left !== position.right && position.top !== position.bottom) { + $('#hotspot'+id).remove(); + $selectedBox = $('<div/>') + .attr('id', 'hotspot'+id) + .addClass('selected-box') + .addClass('selected') + .addClass('drsElement') + .addClass('drsMoveHandle') + .mousedown(function() { + self.selectHotspot(id); + }); + + if($('#form_'+id).val() == 'circle') { + $selectedBox.addClass('hotspot-circle'); + } + else { + $selectedBox.removeClass('hotspot-circle'); + }; + + $selectedBox.hide(); + $('.hotspots-image').append($selectedBox); + + positionBox($selectedBox, position, true); + //self.dragresize.deselect(document.getElementById('hotspot'+id)); + //self.dragresize.removeHandleSet(document.getElementById('hotspot'+id)); + self.dragresize.select(document.getElementById('hotspot'+id)); + $selectedBox.show(); + + selectedBox = position; + + $('#image').off('mousemove', trackMouse); + + //self.createHotspot(id); + self.saveHotspot(id); + }; + } + }; + + $('#image').on('mousedown', mouseDown); + $selectionMarquee.on('mousemove', trackMouse); + $('#image').on('mouseup', mouseUp); + $selectionMarquee.on('mouseup', mouseUp); + + $('body').on('mouseup', function() { + $selectionMarquee.hide(); + }); + }; + + self.changeForm = function($form, id) { + if($form.val() == 'circle') { + $('#hotspot'+id).addClass('hotspot-circle'); + $('#selectionMarquee').addClass('hotspot-circle'); + } + else { + $('#hotspot'+id).removeClass('hotspot-circle'); + $('#selectionMarquee').removeClass('hotspot-circle'); + }; + self.hotspot.form = $form.val(); + self.saveHotspot(id); + }; + + self.changeType = function($type, id) { + switch($type.val()) { + case 'linkEx': + $('#urlIntDiv_'+id).hide(); + $('#urlDiv_'+id).show(); + self.hotspot.srcInt = ''; + $('#urlInt_'+id).val(''); + break; + case 'link': + $('#urlDiv_'+id).hide(); + $('#urlIntDiv_'+id).show(); + self.hotspot.src = ''; + $('#url_'+id).val(''); + break; + case 'tooltip': + $('#urlDiv_'+id).hide(); + $('#urlIntDiv_'+id).hide(); + self.hotspot.src = ''; + $('#url_'+id).val(''); + self.hotspot.srcInt = ''; + $('#urlInt_'+id).val(''); + break; + } + self.hotspot.type = $type.val(); + self.createHotspot(id); + self.saveHotspot(id); + }; + + self.updateDescription = function($description, id) { + self.hotspot.description = $description.val(); + // $('#hotspot'+id).qtip({ + // content: self.hotspot.description, + // position: { + // my: 'bottom left', + // at: 'bottom left', + // target: 'mouse' + // } + // }); + self.saveHotspot(id); + }; + + self.updateUrl = function($url, id) { + self.hotspot.src = $url.val(); + var link = $('#hotspot'+id).children().get(0); + if(link) { + $(link).attr('href', $url.val()); + }; + self.saveHotspot(id); + }; + + self.updateUrlInt = function($urlInt, id) { + self.hotspot.srcInt = $urlInt.val(); + var link = $('#hotspot'+id).children().get(0); + if(link) { + $(link).attr('href', $urlInt.val()); + }; + self.saveHotspot(id); + }; + + self.removeHotspot = function(id) { + $('#hotspot'+id).remove(); + $('#hotspot_'+id).remove(); + var pos = self.data.hotspots.indexOf(_.findWhere(self.data.hotspots, {id: id})); + if(pos != -1) { + self.data.hotspots.splice(pos, 1); + }; + if(self.selected != -1 && self.selected == id) { + $('#image').off('mousedown') + .off('mouseup'); + self.selected = -1; + }; + self.storeValue(); + }; + + self.createHotspot = function(id) { + $('#hotspot'+id).empty(); + // $('#hotspot'+id).qtip({ + // content: self.hotspot.description, + // position: { + // my: 'bottom left', + // at: 'bottom left', + // target: 'mouse' + // } + // }); + // switch($('#type_'+id).val()) { + // case 'linkEx': + // var link = $('<a/>') + // .attr('target', '_blank') + // .css('height', self.hotspot.height) + // .css('width', self.hotspot.width) + // .css('display', 'block'); + // if(self.hotspot.src != '') + // link.attr('href', self.hotspot.src); + // if($('#form_'+id).val() == 'circle') { + // link.addClass('hotspot-circle'); + // } + // else { + // link.removeClass('hotspot-circle'); + // }; + // $('#hotspot'+id).append(link); + // break; + // case 'link': + // // DA FARE + // break; + // }; + }; + + self.saveHotspot = function(id) { + var pos = self.data.hotspots.indexOf(_.findWhere(self.data.hotspots, {id: id})); + if(pos != -1) { + self.data.hotspots.splice(pos, 1, self.hotspot); + } + else { + self.data.hotspots.push(self.hotspot) + }; + + self.storeValue(); + }; + + self.dragRes = function() { + self.dragresize = new DragResize('dragresize', + {minWidth: 1, minHeight: 1, minLeft: 0, minTop: 0, maxLeft: $('#image').width(), maxTop: $('#image').height() }); + self.dragresize.isElement = function(elm) { + if (elm.className && elm.className.indexOf('drsElement') > -1) return true; + }; + self.dragresize.isHandle = function(elm) { + if (elm.className && elm.className.indexOf('drsMoveHandle') > -1) return true; + }; + self.dragresize.ondragfocus = function() { + + }; + self.dragresize.ondragstart = function(isResize) { + self.dragres = true; + }; + self.dragresize.ondragmove = function(isResize) { + + }; + self.dragresize.ondragend = function(isResize) { + self.hotspot.top = parseInt($('#hotspot'+self.hotspot.id).css('top')); + self.hotspot.left = parseInt($('#hotspot'+self.hotspot.id).css('left')); + self.hotspot.height = $('#hotspot'+self.hotspot.id).height(); + self.hotspot.width = $('#hotspot'+self.hotspot.id).width(); + self.dragres = false; + self.saveHotspot(self.hotspot.id); + }; + self.dragresize.ondragblur = function() { + + }; + self.dragresize.apply(document.getElementById('hotspots-image')); + }; + + self.init(); + }, + + getValue: function () { + return $(this).val(); + }, + + setValue: function (value) { + $(this).val(value); + }, + + destroy: function () { + }, + + openDialogCallback: function() { + var $frame = jQuery(this).children(); + $frame.load(function () { + jQuery( "img.js-glizyMediaPicker", $frame.contents().get(0)).click( function(){ + var $img = jQuery( this ); + Glizy.lastMediaPicker.setImage($img.data("jsonmedia")); + Glizy.closeIFrameDialog(); + }); + + jQuery( ".js-glizycmsMediaPicker-noMedia", $frame.contents().get(0)).click( function(){ + Glizy.lastMediaPicker.setImage(); + Glizy.closeIFrameDialog(); + }); + }); + } +}); + + +/* + +DragResize v1.0 +(c) 2005-2006 Angus Turnbull, TwinHelix Designs http://www.twinhelix.com + +Licensed under the CC-GNU LGPL, version 2.1 or later: +http://creativecommons.org/licenses/LGPL/2.1/ +This is distributed WITHOUT ANY WARRANTY; without even the implied +warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +*/ + + +// Common API code. + +if (typeof addEvent != 'function') +{ + var addEvent = function(o, t, f, l) + { + var d = 'addEventListener', n = 'on' + t, rO = o, rT = t, rF = f, rL = l; + if (o[d] && !l) return o[d](t, f, false); + if (!o._evts) o._evts = {}; + if (!o._evts[t]) + { + o._evts[t] = o[n] ? { b: o[n] } : {}; + o[n] = new Function('e', + 'var r = true, o = this, a = o._evts["' + t + '"], i; for (i in a) {' + + 'o._f = a[i]; r = o._f(e||window.event) != false && r; o._f = null;' + + '} return r'); + if (t != 'unload') addEvent(window, 'unload', function() { + removeEvent(rO, rT, rF, rL); + }); + } + if (!f._i) f._i = addEvent._i++; + o._evts[t][f._i] = f; + }; + addEvent._i = 1; + var removeEvent = function(o, t, f, l) + { + var d = 'removeEventListener'; + if (o[d] && !l) return o[d](t, f, false); + if (o._evts && o._evts[t] && f._i) delete o._evts[t][f._i]; + }; +} + + +function cancelEvent(e, c) +{ + e.returnValue = false; + if (e.preventDefault) e.preventDefault(); + if (c) + { + e.cancelBubble = true; + if (e.stopPropagation) e.stopPropagation(); + } +}; + + + + + + + +// *** DRAG/RESIZE CODE *** + +function DragResize(myName, config) +{ + var props = { + myName: myName, // Name of the object. + enabled: true, // Global toggle of drag/resize. + handles: ['tl', 'tm', 'tr', + 'ml', 'mr', 'bl', 'bm', 'br'], // Array of drag handles: top/mid/bot/right. + isElement: null, // Function ref to test for an element. + isHandle: null, // Function ref to test for move handle. + element: null, // The currently selected element. + handle: null, // Active handle reference of the element. + minWidth: 10, minHeight: 10, // Minimum pixel size of elements. + minLeft: 0, maxLeft: 9999, // Bounding box area, in pixels. + minTop: 0, maxTop: 9999, + zIndex: 1, // The highest Z-Index yet allocated. + mouseX: 0, mouseY: 0, // Current mouse position, recorded live. + lastMouseX: 0, lastMouseY: 0, // Last processed mouse positions. + mOffX: 0, mOffY: 0, // A known offset between position & mouse. + elmX: 0, elmY: 0, // Element position. + elmW: 0, elmH: 0, // Element size. + allowBlur: true, // Whether to allow automatic blur onclick. + ondragfocus: null, // Event handler functions. + ondragstart: null, + ondragmove: null, + ondragend: null, + ondragblur: null + }; + + for (var p in props) + this[p] = (typeof config[p] == 'undefined') ? props[p] : config[p]; +}; + + +DragResize.prototype.apply = function(node) +{ + // Adds object event handlers to the specified DOM node. + + var obj = this; + addEvent(node, 'mousedown', function(e) { obj.mouseDown(e) } ); + addEvent(node, 'mousemove', function(e) { obj.mouseMove(e) } ); + addEvent(node, 'mouseup', function(e) { obj.mouseUp(e) } ); +}; + + +DragResize.prototype.select = function(newElement) { with (this) +{ + // Selects an element for dragging. + + if (!document.getElementById || !enabled) return; + + // Activate and record our new dragging element. + if (newElement && (newElement != element) && enabled) + { + element = newElement; + // Elevate it and give it resize handles. + element.style.zIndex = ++zIndex; + if (this.resizeHandleSet) this.resizeHandleSet(element, true); + // Record element attributes for mouseMove(). + elmX = parseInt(element.style.left); + elmY = parseInt(element.style.top); + elmW = element.offsetWidth; + elmH = element.offsetHeight; + if (ondragfocus) this.ondragfocus(); + } +}}; + + +DragResize.prototype.deselect = function(delHandles) { with (this) +{ + // Immediately stops dragging an element. If 'delHandles' is true, this + // remove the handles from the element and clears the element flag, + // completely resetting the . + + if (!document.getElementById || !enabled) return; + + if (delHandles) + { + if (ondragblur) this.ondragblur(); + if (this.resizeHandleSet && element) this.resizeHandleSet(element, false); + element = null; + } + + handle = null; + mOffX = 0; + mOffY = 0; +}}; + + +DragResize.prototype.mouseDown = function(e) { with (this) +{ + // Suitable elements are selected for drag/resize on mousedown. + // We also initialise the resize boxes, and drag parameters like mouse position etc. + if (!document.getElementById || !enabled) return true; + + var elm = e.target || e.srcElement, + newElement = null, + newHandle = null, + hRE = new RegExp(myName + '-([trmbl]{2})', ''); + + while (elm) + { + // Loop up the DOM looking for matching elements. Remember one if found. + if (elm.className) + { + if (!newHandle && (hRE.test(elm.className) || isHandle(elm))) newHandle = elm; + if (isElement(elm)) { newElement = elm; break } + } + elm = elm.parentNode; + } + + // If this isn't on the last dragged element, call deselect(), + // which will hide its handles and clear element. + if (element && (element != newElement) && allowBlur) deselect(true); + + // If we have a new matching element, call select(). + if (newElement && (!element || (newElement == element))) + { + // Stop mouse selections if we're dragging a handle. + if (newHandle) cancelEvent(e); + select(newElement, newHandle); + handle = newHandle; + if (handle && ondragstart) this.ondragstart(hRE.test(handle.className)); + } +}}; + + +DragResize.prototype.mouseMove = function(e) { with (this) +{ + // This continually offsets the dragged element by the difference between the + // last recorded mouse position (mouseX/Y) and the current mouse position. + if (!document.getElementById || !enabled) return true; + + // We always record the current mouse position. + mouseX = e.pageX || e.clientX + document.documentElement.scrollLeft; + mouseY = e.pageY || e.clientY + document.documentElement.scrollTop; + // Record the relative mouse movement, in case we're dragging. + // Add any previously stored & ignored offset to the calculations. + var diffX = mouseX - lastMouseX + mOffX; + var diffY = mouseY - lastMouseY + mOffY; + mOffX = mOffY = 0; + // Update last processed mouse positions. + lastMouseX = mouseX; + lastMouseY = mouseY; + + // That's all we do if we're not dragging anything. + if (!handle) return true; + + // If included in the script, run the resize handle drag routine. + // Let it create an object representing the drag offsets. + var isResize = false; + if (this.resizeHandleDrag && this.resizeHandleDrag(diffX, diffY)) + { + isResize = true; + } + else + { + // If the resize drag handler isn't set or returns fase (to indicate the drag was + // not on a resize handle), we must be dragging the whole element, so move that. + // Bounds check left-right... + var dX = diffX, dY = diffY; + if (elmX + dX < minLeft) mOffX = (dX - (diffX = minLeft - elmX)); + else if (elmX + elmW + dX > maxLeft) mOffX = (dX - (diffX = maxLeft - elmX - elmW)); + // ...and up-down. + if (elmY + dY < minTop) mOffY = (dY - (diffY = minTop - elmY)); + else if (elmY + elmH + dY > maxTop) mOffY = (dY - (diffY = maxTop - elmY - elmH)); + elmX += diffX; + elmY += diffY; + } + + // Assign new info back to the element, with minimum dimensions. + + with (element.style) + { + left = elmX + 'px'; + width = elmW + 'px'; + top = elmY + 'px'; + height = elmH + 'px'; + } + + // Evil, dirty, hackish Opera select-as-you-drag fix. + if (window.opera && document.documentElement) + { + var oDF = document.getElementById('op-drag-fix'); + if (!oDF) + { + var oDF = document.createElement('input'); + oDF.id = 'op-drag-fix'; + oDF.style.display = 'none'; + document.body.appendChild(oDF); + } + oDF.focus(); + } + + if (ondragmove) this.ondragmove(isResize); + + // Stop a normal drag event. + cancelEvent(e); + +}}; + + +DragResize.prototype.mouseUp = function(e) { with (this) +{ + // On mouseup, stop dragging, but don't reset handler visibility. + if (!document.getElementById || !enabled) return; + + var hRE = new RegExp(myName + '-([trmbl]{2})', ''); + if (handle && ondragend) this.ondragend(hRE.test(handle.className)); + deselect(false); +}}; + +/* Mattia remove handle */ + +DragResize.prototype.removeHandleSet = function(elm) { with (this) +{ + + // Remove handles. + for (var h = 0; h < handles.length; h++) + { + elm['_handle_' + handles[h]] = undefined; + } +}}; + +/* Resize Code -- can be deleted if you're not using it. */ + +DragResize.prototype.resizeHandleSet = function(elm, show) { with (this) +{ + // Either creates, shows or hides the resize handles within an element. + + // If we're showing them, and no handles have been created, create 4 new ones. + if (!elm._handle_tr) + { + for (var h = 0; h < handles.length; h++) + { + // Create 4 news divs, assign each a generic + specific class. + var hDiv = document.createElement('div'); + hDiv.className = myName + ' ' + myName + '-' + handles[h]; + elm['_handle_' + handles[h]] = elm.appendChild(hDiv); + } + } + + // We now have handles. Find them all and show/hide. + for (var h = 0; h < handles.length; h++) + { + elm['_handle_' + handles[h]].style.visibility = show ? 'inherit' : 'hidden'; + } +}}; + + +DragResize.prototype.resizeHandleDrag = function(diffX, diffY) { with (this) +{ + // Passed the mouse movement amounts. This function checks to see whether the + // drag is from a resize handle created above; if so, it changes the stored + // elm* dimensions and mOffX/Y. + + var hClass = handle && handle.className && + handle.className.match(new RegExp(myName + '-([tmblr]{2})')) ? RegExp.$1 : ''; + + // If the hClass is one of the resize handles, resize one or two dimensions. + // Bounds checking is the hard bit -- basically for each edge, check that the + // element doesn't go under minimum size, and doesn't go beyond its boundary. + var dY = diffY, dX = diffX, processed = false; + if (hClass.indexOf('t') >= 0) + { + rs = 1; + if (elmH - dY < minHeight) mOffY = (dY - (diffY = elmH - minHeight)); + else if (elmY + dY < minTop) mOffY = (dY - (diffY = minTop - elmY)); + elmY += diffY; + elmH -= diffY; + processed = true; + } + if (hClass.indexOf('b') >= 0) + { + rs = 1; + if (elmH + dY < minHeight) mOffY = (dY - (diffY = minHeight - elmH)); + else if (elmY + elmH + dY > maxTop) mOffY = (dY - (diffY = maxTop - elmY - elmH)); + elmH += diffY; + processed = true; + } + if (hClass.indexOf('l') >= 0) + { + rs = 1; + if (elmW - dX < minWidth) mOffX = (dX - (diffX = elmW - minWidth)); + else if (elmX + dX < minLeft) mOffX = (dX - (diffX = minLeft - elmX)); + elmX += diffX; + elmW -= diffX; + processed = true; + } + if (hClass.indexOf('r') >= 0) + { + rs = 1; + if (elmW + dX < minWidth) mOffX = (dX - (diffX = minWidth - elmW)); + else if (elmX + elmW + dX > maxLeft) mOffX = (dX - (diffX = maxLeft - elmX - elmW)); + elmW += diffX; + processed = true; + } + + return processed; +}}; \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditMediaPicker.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditMediaPicker.js new file mode 100644 index 0000000..f9f0517 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditMediaPicker.js @@ -0,0 +1,137 @@ +jQuery.GlizyRegisterType('mediapicker', { + __construct: function () { + var $input = jQuery(this).hide(), + val = $input.val(), + pickerType = $input.attr('data-mediatype'), + hasPreview = $input.attr('data-preview') == 'true', + glizyOpt = $input.data('glizyOpt'), + $mediaPicker = + hasPreview ? jQuery('<div id="'+jQuery(this).attr('name')+'-mediapicker" class="mediaPickerSelector mediaPickerField"><div class="mediaPickerCaption"></div><div class="mediaPickerElement">' + GlizyLocale.MediaPicker.imageEmpty + '</div></div>') + : jQuery('<input class="mediaPickerField" type="text" size="50" readonly="readonly" style="cursor:pointer" value="' + GlizyLocale.MediaPicker.imageEmptyText + '">'); + $input.data('mediaPicker', $mediaPicker); + + if (!$input.next().hasClass('mediaPickerField')) { + $mediaPicker.insertAfter($input).click(function() { + var url = glizyOpt.mediaPicker; + if (pickerType) { + url += '&mediaType=' + pickerType; + } + Glizy.openIFrameDialog( hasPreview ? GlizyLocale.MediaPicker.imageTitle : GlizyLocale.MediaPicker.mediaTitle, + url, + 900, + 50, + 50, + null, + Glizy.responder($input, $input.data('formEdit').disposeEvent)); + Glizy.lastMediaPicker = jQuery(this); + + var eventPos = Glizy.events.on("glizycms.onSetMediaPicker", Glizy.responder($input, $input.data('formEdit').onSetMediaPicker)); + $input.data('eventPos', eventPos); + }); + } + if (val == GlizyLocale.MediaPicker.imageEmptyText) { + $input.data('formEdit').setValue.call($mediaPicker); + } + else if (val) { + $input.data('formEdit').setValue.call($mediaPicker, val); + } + }, + + disposeEvent: function() + { + if (Glizy.lastMediaPicker) { + var $this = Glizy.lastMediaPicker.prev(); + var eventPos = $this.data('eventPos'); + if (eventPos!==null && eventPos!==undefined) { + Glizy.events.unbind("glizycms.onSetMediaPicker", eventPos); + $this.data('eventPos', null); + } + } + }, + + onSetMediaPicker: function(event) + { + var $this = Glizy.lastMediaPicker.prev(); + $this.data('formEdit').disposeEvent.call(); + $this.data('formEdit').setValue.call(Glizy.lastMediaPicker, event.message); + Glizy.closeIFrameDialog(); + var mediaPickerId = $this.attr('name')+'-mediapicker'; + $('#'+mediaPickerId).removeClass('GFEValidationError'); + }, + + getPreview: function (val) { + try { + props = JSON.parse(val); + return props.title; + } catch(e) { + return val; + } + }, + + setValue: function (props) { + if (typeof(props)=='string' && props) { + props = JSON.parse(props); + } + var $this = jQuery(this); + if ($this.data('mediaPicker')) { + $this = $this.data('mediaPicker'); + } + var $img = $this.find('img'); + + if (!props || !props.src) { + if ($img.length) { + $img.replaceWith(GlizyLocale.MediaPicker.imageEmpty); + } + else { + $this.val(GlizyLocale.MediaPicker.imageEmptyText); + } + $this.prev().val(''); + } + else { + if ($img.length) { + $img.load(function () { + + var w = this.naturalWidth, + h = this.naturalHeight, + maxW = $this.width() -6, + maxH = $this.height() -6; + + if (w > maxW) { + h = h * (maxW / w); + w = maxW; + } + if (h > maxH) { + w = w * (maxH / h); + h = maxH; + } + jQuery(this).attr({width: w, height: h}) + .show(); + }) + .hide(); + + $img.attr({title: props.title, src: props.src}) + .data({id: props.id, fileName: props.fileName}); + + if ($img[0].complete && $img[0].naturalWidth !== 0) { + $img.trigger('load'); + } + } + else { + $this.val(props.title); + } + $this.prev().val( JSON.stringify(props) ); + } + }, + + destroy: function () { + var $this = jQuery(this); + $this.data('formEdit').disposeEvent.call(); + }, + + focus: function () { + var mediaPickerId = jQuery(this).attr('name')+'-mediapicker'; + $('#'+mediaPickerId).addClass('GFEValidationError'); + document.getElementById(mediaPickerId).scrollIntoView(); + } + + }); diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditPermission.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditPermission.js new file mode 100644 index 0000000..d9e7918 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditPermission.js @@ -0,0 +1,37 @@ +jQuery.GlizyRegisterType('permission', { + + __construct: function () { + $(this).removeAttr('value'); + $(this).css('width', '500px'); + + var value = jQuery(this).data('origValue'); + + if (value !== undefined && value.length > 0) { + var arrayVal = [] + + $.each(value, function(index, v) { + if (typeof(v)=="object") { + arrayVal.push(v); + } + else { + arrayVal.push({id: v, text: v}); + } + }); + + $(this).select2('data', arrayVal); + } + }, + + getValue: function () { + return $(this).select2('val'); + }, + + setValue: function (value) { + if (value[0].id) { + $(this).select2('data', value); + } + }, + + destroy: function () { + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditPhotoGalleryCategory.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditPhotoGalleryCategory.js new file mode 100644 index 0000000..a133ada --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditPhotoGalleryCategory.js @@ -0,0 +1,34 @@ +jQuery.GlizyRegisterType('photogallerycategory', { + + __construct: function () { + var value = jQuery(this).data('origValue'); + if (value) { + $('#galleryType').val(value['galleryType']); + + var arrayVal = [] + + $.each(value['gallery-images'], function(index, v) { + if (typeof(v)=="object") { + arrayVal.push(v); + } + else { + arrayVal.push({id: v, text: v}); + } + }); + + $('#gallery-images').select2('data', arrayVal); + } + }, + + getValue: function () { + var galleryType = $('#galleryType').val(); + var galleryImages = $('#gallery-images').select2('val'); + return {'galleryType': galleryType, 'gallery-images': galleryImages}; + }, + + setValue: function (value) { + }, + + destroy: function () { + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditSelectFrom.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditSelectFrom.js new file mode 100644 index 0000000..2074748 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditSelectFrom.js @@ -0,0 +1,142 @@ +jQuery.GlizyRegisterType('selectfrom', { + + __construct: function () { + var self = this; + $(this).removeAttr('value'); + $(this).css('width', '500px'); + + var fieldName = $(this).data('field') || $(this).attr('name'); + var multiple = $(this).data('multiple'); + var addNewValues = $(this).data('add_new_values'); + var model = $(this).data('model'); + var query = $(this).data('query'); + var proxy = $(this).data('proxy'); + var proxyParams = $(this).data('proxy_params'); + if (typeof(proxyParams)=='string') { + proxyParams = proxyParams.replace(/##/g,'"'); + } else { + proxyParams = JSON.stringify(proxyParams); + } + var placeholder = $(this).data('placeholder'); + var originalName = $(this).data('originalName'); + var getId = $(this).data('get_id'); + var minimumInputLength = $(this).data('min_input_length') || 0; + var formatSelection = $(this).data('format_selection'); + var formatResult = $(this).data('format_result'); + + if (originalName !== undefined && $(this).data('override')!==false) { + fieldName = originalName; + } + + $(this).select2({ + width: 'off', + multiple: multiple, + minimumInputLength: minimumInputLength, + placeholder: placeholder === undefined ? '' : placeholder, + allowClear: true, + ajax: { + url: Glizy.ajaxUrl + "&controllerName=org.glizycms.contents.controllers.autocomplete.ajax.FindTerm", + dataType: 'json', + quietMillis: 250, + data: function(term, page) { + return { + fieldName: fieldName, + model: model, + query: query, + term: term, + proxy: proxy, + proxyParams: proxyParams, + getId: getId + }; + }, + results: function(data, page ) { + return { results: data.result } + } + }, + createSearchChoice: function(term, data) { + if (!addNewValues) { + return false; + } + + if ($(data).filter(function() { + return this.text.localeCompare(term)===0; + }).length===0) { + return {id:term, text:term}; + } + }, + formatResult: function(data) { + return formatResult === undefined ? data.text : window[formatResult](data); + }, + formatSelection: function(data) { + return formatSelection === undefined ? data.text : window[formatSelection](data); + } + }).on('change', function(e){ + self._getValue(); + }) + + this._setValue = function(value) { + var baseValue = value || $(this).data('origValue'); + var multiple = $(this).data('multiple'); + + try { + value = JSON.parse(baseValue); + } catch (e) { + value = baseValue; + } + if (multiple === undefined || multiple === false) { + if (value) { + if (typeof(value)=="object") { + $(this).select2('data', value); + } else { + $(this).select2('data', {id: value, text: value}); + } + } + } + else if (value !== undefined && value.length > 0) { + var arrayVal = [] + + $.each(value, function(index, v) { + if (typeof(v)=="object") { + arrayVal.push(v); + } + else { + arrayVal.push({id: v, text: v}); + } + }); + + $(this).select2('data', arrayVal); + } + } + + this._getValue = function() { + var data; + if ($(this).data('return_object')) { + data = $(this).select2('data'); + } else { + data = $(this).select2('val'); + } + $(this).data('origValue', JSON.stringify(data)); + return data; + } + + this._setValue(); + }, + + getValue: function () { + return this._getValue(); + }, + + setValue: function (value) { + if (value) { + this._setValue(value); + } + }, + + destroy: function () { + $(this).select2("destroy").off("change"); + }, + + focus: function () { + $(this).select2('focus'); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditSelectPageType.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditSelectPageType.js new file mode 100644 index 0000000..a166c3d --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditSelectPageType.js @@ -0,0 +1,76 @@ +jQuery.GlizyRegisterType('selectpagetype', { + + __construct: function () { + var $that = $(this); + var $previous = null; + var linkedElement = $that.data('linked'); + var onlyWithParent = $that.data('onlywithparent')===true; + var isSelect = linkedElement && $('#'+linkedElement)[0].tagName=='SELECT'; + + $that.next().hide(); + + var updateItemVisibility = function() { + var currentMenuType = isSelect ? $('#'+linkedElement+' option:selected').data('options') : + $('#'+linkedElement).data('options'); + if (!currentMenuType) { + currentMenuType = $('#'+linkedElement).val(); + } + $that.next().find('a').each(function(index, el) { + var $el = $(el), + acceptType = $el.data('acceptparent'); + $el.parent().show(); + if (currentMenuType && (acceptType || (!acceptType && onlyWithParent))) { + acceptType = acceptType.split(','); + if (acceptType.indexOf(currentMenuType)==-1) { + $el.parent().hide(); + if ($el.parent().hasClass('button-selected')) { + $el.parent().removeClass('button-selected'); + $that.val(''); + } + } + } + }); + } + + $(this).next().find('a').click(function( event ) { + $that.next().find('li').each(function( index ) { + $(this).removeClass('button-selected'); + }); + $(this).parent().addClass('button-selected'); + var pageType = $(this).data('type'); + $that.val(pageType); + }); + + var currentValue = $that.val(); + if (currentValue) { + $(this).next().find('a').each(function(index) { + if ($(this).data('type')==currentValue) { + $(this).parent().addClass('button-selected'); + } + }); + } + + if (linkedElement) { + $('#'+linkedElement).change(function(){ + updateItemVisibility(); + }); + + updateItemVisibility(); + } + + $that.next().show(); + + + }, + + getValue: function () { + return $(this).val(); + }, + + setValue: function (value) { + $(this).val(value); + }, + + destroy: function () { + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditTINYMCE.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditTINYMCE.js new file mode 100644 index 0000000..646961a --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditTINYMCE.js @@ -0,0 +1,41 @@ +jQuery.GlizyRegisterType('tinymce', { + + __construct: function () { + + var $this = jQuery(this), + $container = $this.closest('.GFERowContainer'), + $fieldSet = $container.parent(), + options = Glizy.tinyMCE_options, + h; + + options.mode = "exact"; + options.elements = this.name; + options.document_base_url = Glizy.tinyMCE_options.urls.root; + tinyMCE.init( options ); + + if (!$fieldSet.attr('data-collapsable') == 'true') { + h = $container.height(); + $container.height(h) + .find('.GFERowHandler > img').attr('height', h); + } + }, + + save: function () { + return tinyMCE.get(this.id).save(); + }, + + getValue: function () { + + return tinyMCE.get(this.id).getContent(); + }, + + setValue: function (value) { + + tinyMCE.get(this.id).setContent(value || ''); + }, + + destroy: function () { + + tinyMCE.execCommand('mceRemoveControl', true, this.id); + } + }); diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditTreeSelect.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditTreeSelect.js new file mode 100644 index 0000000..bc83889 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditTreeSelect.js @@ -0,0 +1,89 @@ +$.GlizyRegisterType('treeselect', { + + __construct: function () { + var self = this; + this.element = $(this); + this.controllerName = this.element.data("controllername"); + this.lazyLoadUrl = Glizy.ajaxUrl + "&controllerName="+this.controllerName + "&method=lazyLoad"; + this.getPathUrl = Glizy.ajaxUrl + "&controllerName="+this.controllerName + "&method=getPath"; + + this.render = function() { + var self = this; + if (this.element.data('isInit')!==true) { + var name = this.element.attr('name'); + this.element.data('isInit', true); + if (this.element.prop("tagName") == "INPUT") { + this.element.attr('type', 'hidden'); + } + + var html = '<div id="'+name+'-tree"></div>'; + this.element.after(html); + + $('#'+name+'-tree').fancytree({ + source: { + url: this.lazyLoadUrl + //cache: false + }, + lazyLoad: function(event, data) { + var node = data.node; + // Issue an ajax request to load child nodes + data.result = { + url: self.lazyLoadUrl, + data: { + "key": node.key + } + } + }, + activate: function(event, data){ + self.element.val(data.node.key) + }, + init: function(event, data){ + + var key = self.element.val(); + if (key && key !== "") { + // carico il nodo selezionato e tutta la catena per raggiungerlo (array di id) + $.ajax({ + url: self.getPathUrl, + data: { + "key": key + }, + success: function(result) { + if (result.status) { + data.tree.loadKeyPath("/"+result.data.join("/"), function(node, status){ + if (status === "loaded") { + // traversing node + } else if (status === "ok") { + // node found + node.setExpanded(true); + node.setActive(true); + } + }); + } + } + }) + } + } + }); + } + }; + + this.render(); + + }, + + getValue: function () { + return $(this).val(); + }, + + setValue: function (value) { + $(this).val(value); + }, + + destroy: function () { + }, + + focus: function() + { + this.element.focus(); + } +}); diff --git a/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditValuesPreset.js b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditValuesPreset.js new file mode 100644 index 0000000..9ad424d --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit/GlizyFormEditValuesPreset.js @@ -0,0 +1,29 @@ +jQuery.GlizyRegisterType('valuesPreset', { + __construct: function () { + var self = $(this).data('formEdit'); + self.element = $(this); + self.element.on('change', function() { + var options = self.element.find('option:selected').data('options'); + var elements = self.element.data('elements'); + if (options && elements) { + options = options.split(','); + elements = elements.split(','); + $(elements).each(function(index, item){ + $('input[name='+item+']').val(options[index]).change(); + }); + } + }); + + }, + + getValue: function () { + return $(this).val(); + }, + + setValue: function (value) { + $(this).val(value); + }, + + destroy: function () { + } +}); diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEdit.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEdit.js new file mode 100644 index 0000000..8c645fd --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEdit.js @@ -0,0 +1,270 @@ +Glizy.oop.declare("glizy.FormEdit", { + formId: null, + $form: null, + glizyOpt: null, + invalidFields: 0, + customValidationInvalid: false, + lang: null, + fields: [], + + $statics: { + fieldTypes: [], + registerType: function (name, object) { + this.fieldTypes[name] = object; + } + }, + + initialize: function(formId, glizyOpt) { + this.formId = formId; + this.glizyOpt = glizyOpt; + this.$form = $('#'+this.formId); + this.lang = glizyOpt.lang; + + var self = this; + + $('#'+this.formId+' input[name]:not( [type="button"], [type="submit"], [type="reset"] ), '+ + '#'+this.formId+' textarea[name], '+ + '#'+this.formId+' select[name]').each(function () { + self.createField(this); + }); + + // non unire alla selezione precedente, altrimenti gli input nel fieldset custom vengono + // assegnati anche al formedit + $('#'+this.formId+' fieldset[data-type]').each(function () { + self.createField(this); + }); + + jQuery('.js-glizycms-save').click(function (e) { + $(this).attr("disabled", "disabled"); + e.preventDefault(); + self.save(e.currentTarget, $(this)); + }); + + this.enableValidation(); + + // aggangia anche l'evento submit per permettere la validazione dei campi + this.$form.submit(function(event){ + if (self.$form.triggerHandler('submitForm') === false && this.invalidFields || this.customValidationInvalid) { + self.customValidationInvalid = false; + return false; + } else { + return true; + } + }) + }, + + // restituisce true se l'elemento è contenuto in un altro componente + isSubComponent: function(element) { + // se l'elemento è contenuto in altri tipi contenitori + if ($(element).parents('[data-type]').length !== 0) { + return true; + } else { + return false; + } + }, + + createField: function(element) { + if (this.isSubComponent(element)) { + return; + } + + var type = $(element).data('type') || 'standard'; + var obj = Glizy.oop.create("glizy.FormEdit."+type, $(element), this.glizyOpt, this.$form); + if (obj) { + var value = this.glizyOpt.formData[obj.getName()]; + if (value !== undefined) { + obj.setValue(value); + } + + this.fields.push(obj); + } + }, + + enableValidation: function () { + var self = this; + var firstInvalidObj = null; + + self.$form.validVal({ + validate: { + fields: { + hidden: true + } + }, + fields: { + onValidate: function ($form, language) { + var obj = $(this).data('instance'); + + if (obj && !obj.isValid()) { + obj.addClass('GFEValidationError'); + obj.getElement().closest('.control-group').addClass('GFEValidationError'); + self.invalidFields++; + return false; + } + }, + onInvalid: function( $form, language ) { + var obj = $(this).data('instance'); + if (obj && !obj.isValid()) { + obj.addClass('GFEValidationError'); + obj.getElement().closest('.control-group').addClass('GFEValidationError'); + } + }, + onValid: function( $form, language ) { + var obj = $(this).data('instance'); + if (obj && obj.isValid()) { + obj.removeClass('GFEValidationError'); + obj.getElement().closest('.control-group').removeClass('GFEValidationError'); + } + } + }, + form: { + onValidate: function () { + var error, fieldVals = {}; + + firstInvalidObj = null; + + $('#'+self.formId+' fieldset[data-type]').each(function () { + + // se l'elemento è contenuto in altro componente + if (self.isSubComponent($(this))) { + return; + } + + var obj = $(this).data('instance'); + if (!obj.isValid()) { + obj.addClass('GFEValidationError'); + obj.getElement().closest('.control-group').addClass('GFEValidationError'); + if (!self.customValidationInvalid) { + firstInvalidObj = obj; + } + self.customValidationInvalid = true; + } else { + obj.removeClass('GFEValidationError'); + obj.getElement().closest('.control-group').removeClass('GFEValidationError'); + } + }); + + if (self.glizyOpt.customValidation && typeof(window[self.glizyOpt.customValidation]) == 'function') { + jQuery(this).find('input:not( [type="button"], [type="submit"], [type="reset"] ), textarea, select').each(function () { + if (this.name) fieldVals[this.name] = jQuery(this).val(); + }); + if (error = window[self.glizyOpt.customValidation](fieldVals)) { + alert(error); + Glizy.events.broadcast("glizy.message.showError", {"title": error, "message": ""}); + self.customValidationInvalid = true; + } + } + }, + onInvalid: function( field_arr, language ) { + var $invalidEl = field_arr.first(); + var obj = $invalidEl.data('instance'); + obj.focus(); + + self.invalidFields = $invalidEl.length; + + $invalidEl.addClass('GFEValidationError'); + $invalidEl.closest('.control-group').addClass('GFEValidationError'); + + if (!self.customValidationInvalid) { + var inTab = $invalidEl.closest('div.tab-pane'); + if (inTab.length) { + $('a[data-target="#'+inTab.attr('id')+'"]').tab('show'); + } + } + /* + var $invalidEl = self.filterEditingFields.call(field_arr); + + if ($invalidEl.length) { + if ($invalidEl.attr('data-type')) { + var obj = $invalidEl.data('instance'); + obj.focus(); + } else { + $invalidEl.focus(); + } + + $invalidEl.addClass('GFEValidationError'); + alert(self.lang.errorValidationMsg); + } + */ + }, + onValid: function() { + if (self.customValidationInvalid && firstInvalidObj) { + Glizy.events.broadcast("glizy.message.showError", {"title": self.lang.errorValidationMsg, "message": ""}); + firstInvalidObj.focus(); + } + } + } + }); + }, + + save: function (el, $saveButton) { + var formData = {}; + var result = this.$form.triggerHandler('submitForm'); + + if (result === false || this.invalidFields || this.customValidationInvalid) { + this.customValidationInvalid = false; + $saveButton.removeAttr("disabled"); + this.invalidFields = 0; + Glizy.events.broadcast("glizy.message.showError", {"title": this.lang.errorValidationMsg, "message": ""}); + return; + } + + var self = this; + + this.fields.forEach(function(field) { + if (!field.isDisabled()) { + var val = field.getValue(); + formData[field.getName()] = val; + } + }); + + + var triggerAction = $(el).data("trigger"); + + // return; + + jQuery.ajax(this.glizyOpt.AJAXAction, { + data: jQuery.param({action: $(el).data("action"), data: JSON.stringify(formData)}), + type: "POST", + success: function (data) { + if (data.evt) { + window.parent.Glizy.events.broadcast(data.evt, data.message); + } else if (data.url) { + if (data.target == 'window') { + parent.window.location.href = data.url; + } else { + document.location.href = data.url; + } + } else if (data.set) { + $.each(data.set, function(id, value){ + $('#'+id).val(value); + }); + Glizy.events.broadcast("glizy.message.showSuccess", {"title": self.lang.saveSuccessMsg, "message": ""}); + if (triggerAction) { + triggerAction('click', formData); + } + } else if (data.callback) { + window[data.callback](data); + } else if (data.errors) { + // TODO localizzare + var errorMsg = '<p>Impossibile salvare questo documento, a causa dei seguenti errori:</p><ul>'; + $.each(data.errors, function(id, value) { + errorMsg += '<li><p class="alert alert-error">'+value+'</p></li>'; + }); + Glizy.events.broadcast("glizy.message.showError", {"title": self.lang.errorValidationMsg, "message": errorMsg}); + + } else { + if (triggerAction) { + triggerAction('click', formData); + //$(triggerAction).trigger('click'); + } else { + Glizy.events.broadcast("glizy.message.showSuccess", {"title": self.lang.saveSuccessMsg, "message": ""}); + } + } + + $saveButton.removeAttr("disabled"); + } + }); + } +}); + + diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditCheckbox.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditCheckbox.js new file mode 100644 index 0000000..aa54bd2 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditCheckbox.js @@ -0,0 +1,11 @@ +Glizy.oop.declare("glizy.FormEdit.checkbox", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + + getValue: function () { + return this.$element.attr('checked') ? 1 : 0; + }, + + setValue: function (value) { + this.$element.attr('checked', value == 1); + }, +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditCmsPagePicker.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditCmsPagePicker.js new file mode 100644 index 0000000..b2b7eba --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditCmsPagePicker.js @@ -0,0 +1,83 @@ +Glizy.oop.declare("glizy.FormEdit.CmsPagePicker", { + $element: null, + controllerName: null, + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + + element.removeAttr('value'); + + this.controllerName = element.data('controllername'); + var filterType = element.data('filtertype') || ''; + var protocol = element.data('protocol') || ''; + + element.select2({ + placeholder: '', + allowClear: true, + minimumInputLength: 3, + ajax: { + url: Glizy.ajaxUrl + "&controllerName="+this.controllerName+"&filterType="+filterType+"&protocol="+protocol, + dataType: 'json', + quietMillis: 100, + data: function(term) { + return { + term: term + }; + }, + results: function(data, page ) { + return { results: data } + } + }, + formatResult: function(data) { + return data.text+'<br><small>'+data.path+'</small>'; + }, + formatSelection: function(data) { + return data.text+' <small>'+data.path+'</small>'; + } + }); + }, + + getValue: function () { + return this.$element.val(); + }, + + setValue: function (value) { + if (value) { + $.ajax({ + url: Glizy.ajaxUrl + "&controllerName="+this.controllerName, + dataType: 'json', + data: {id: value}, + success: function(data) { + this.$element.select2('data', data[0]); + } + }); + } + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function() + { + this.$element.focus(); + }, + + destroy: function () { + //this.$element.data('origValue', $(this).val()); + this.$element.select2('destroy'); + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditColorPicker.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditColorPicker.js new file mode 100644 index 0000000..aef85aa --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditColorPicker.js @@ -0,0 +1,53 @@ +Glizy.oop.declare("glizy.FormEdit.colorPicker", { + $element: null, + + initialize: function (element, data) { + element.data('instance', this); + this.$element = element; + + element.css('width', 300); + element.after('<div style="width: 28px; height:28px; float: left; border: 1px solid #e0e0e0;background-color:'+element.val()+'"></div>'); + + element.colorpicker().on('changeColor', function(ev){ + var el = $(ev.currentTarget); + el.next().css('background-color', ev.color.toHex()); + }); + + element.on('change', function(e) { + var el = $(e.currentTarget); + el.next().css('background-color', el.val()); + }); + }, + + getValue: function () { + return this.$element.val(); + }, + + setValue: function (value) { + this.$element.val(value); + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function() + { + this.$element.focus(); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditDate.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditDate.js new file mode 100644 index 0000000..f2acffa --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditDate.js @@ -0,0 +1,49 @@ +Glizy.oop.declare("glizy.FormEdit.date", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + var format = element.data('format') ? element.data('format') : GlizyLocale.date.format; + + this.$element.datetimepicker({ + language: 'it', + minView: 'month', + format: format, + autoclose: true, + todayHighlight: true + }); + }, + + getValue: function () { + return this.$element.val(); + }, + + setValue: function (value) { + this.$element.val(value); + this.$element.datetimepicker('update'); + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function () { + document.getElementById(this.$element.attr('id')).scrollIntoView(); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditDateTime.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditDateTime.js new file mode 100644 index 0000000..1b07a41 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditDateTime.js @@ -0,0 +1,48 @@ +Glizy.oop.declare("glizy.FormEdit.datetime", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + var format = element.data('format') ? element.data('format') : GlizyLocale.datetime.format; + + this.$element.datetimepicker({ + language: 'it', + format: format, + autoclose: true, + todayHighlight: true + }); + }, + + getValue: function () { + return this.$element.val(); + }, + + setValue: function (value) { + this.$element.val(value); + this.$element.datetimepicker('update'); + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function () { + document.getElementById(this.$element.attr('id')).scrollIntoView(); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditFile.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditFile.js new file mode 100644 index 0000000..fc62a4d --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditFile.js @@ -0,0 +1,117 @@ +Glizy.oop.declare("glizy.FormEdit.file", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + isWaiting: false, + alertSent: false, + queue: [], + uploadedFiles: [], + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + var isWaiting = false; + var alertSent = false; + var that = this; + + var uploadedFiles = [], + $input = element.hide(), + $uploader = jQuery('<div></div>').insertAfter($input); + + $uploader.fineUploader({ + request: { + endpoint: 'uploader.php' + }, + text: GlizyLocale.FineUploader + }) + .bind('complete', function(event, id, fileName, responseJSON){ + if (responseJSON.uploadFilename) { + that.uploadedFiles.push( [responseJSON.uploadFilename, responseJSON.originFilename] ); + $input.val( JSON.stringify( that.uploadedFiles ) ); + jQuery("li.qq-upload-success:not(:has(.fu-remove-button))").append('<div class="fu-remove-button"></div>'); + that.dispatchDelayed({"id": id, 'fileName': fileName}); + } + else { + if (!that.alertSent) { + alert(responseJSON.error); + that.alertSent = true; + } + } + }) + .bind('upload', function(event, id, fileName) { + + }) + + jQuery(document).on('click', '.fu-remove-button', function () { + + var $this = element, + filename = $this.siblings('.qq-upload-file').text(), + i, f; + + for (i = 0; f = that.uploadedFiles[i]; i++) { + if (f[1] == filename) { + that.uploadedFiles.splice(i, 1); + break; + } + } + $input.val( JSON.stringify( that.uploadedFiles ) ); + $this.parent().remove(); + Glizy.events.broadcast("glizycms.fileRemoved", i); + }); + }, + + getValue: function () { + return this.$element.val(); + }, + + setValue: function (value) { + this.$element.val(value); + }, + + getName: function () { + return this.$element.attr('name'); + }, + + removeFile: function (id) { + this.uploadedFiles = JSON.parse(this.$element.val()); + this.uploadedFiles.splice(id, 1); + this.$element.val( JSON.stringify( this.uploadedFiles ) ); + this.$element.siblings().find('.qq-upload-success').get(id).remove(); + }, + + dispatchDelayed: function(info) { + var that = this; + + if (!that.isWaiting) { + that.isWaiting = true; + setTimeout(function () { + that.isWaiting = false; + Glizy.events.broadcast("glizycms.fileUpload", info); + if ( that.queue.length) { + info = that.queue.pop(); + that.dispatchDelayed(info); + } + }, 500); + } else { + this.queue.push(info); + } + }, + + focus: function() + { + this.$element.focus(); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditGUID.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditGUID.js new file mode 100644 index 0000000..4aeeccf --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditGUID.js @@ -0,0 +1,45 @@ +Glizy.oop.declare("glizy.FormEdit.inputguid", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + if (element.val() == '') { + this.$element.val(this.$element.data('base')+(new Date().getTime())); + } + }, + + getValue: function () { + return this.$element.val(); + }, + + setValue: function (value) { + if (value != undefined) { + this.$element.val(value); + } + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function() + { + this.$element.focus(); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditGoogleMaps.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditGoogleMaps.js new file mode 100644 index 0000000..c9698ad --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditGoogleMaps.js @@ -0,0 +1,266 @@ +Glizy.oop.declare("glizy.FormEdit.googlemaps", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + map: null, + marker: null, + geocoder: null, + elementMap: null, + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + this.render(); + }, + + getValue: function () { + return this.$element.val(); + }, + + setValue: function (value) { + this.$element.val(value); + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function() + { + this.$element.focus(); + }, + + render: function() { + if (this.$element.data('isInit')!==true) { + var name = this.$element.attr('name'), + html = '<input id="'+name+'-search" class="btn" type="button" value="Cerca"/>'; + this.$element.after(jQuery(html)); + this.$element.addClass("span10"); + this.$element.data('isInit', true); + } + + if (jQuery("#GlizyFormEditgooglemaps").length == 0) { + window.GlizyFormEditgooglemaps = {}; + html = '<div id="GlizyFormEditgooglemaps" class="mapPicker" style="width: 600px; height: 400px; background: #fff; border: 1px solid #ccc; padding: 5px; position: absolute; z-index: 3000; display: none;"></div>'; + jQuery('body').append(html); + + window.GlizyFormEditgooglemaps.geocoder = new google.maps.Geocoder(); + + var pos = this.getDefaultCurrentPosition(); + var latlng = new google.maps.LatLng(pos[ 0 ], pos[ 1 ]); + var myOptions = { + zoom: pos[ 2 ], + center: latlng, + mapTypeId: google.maps.MapTypeId.HYBRID, + mapTypeControl: false, + disableDoubleClickZoom: true, + streetViewControl: false + }; + + window.GlizyFormEditgooglemaps.map = new google.maps.Map( jQuery("#GlizyFormEditgooglemaps").get(0), myOptions); + window.GlizyFormEditgooglemaps.marker = new google.maps.Marker({ + position: latlng, + map: window.GlizyFormEditgooglemaps.map, + title: "Trascinami", + draggable: true + }); + } + + var self = this; + this.map = window.GlizyFormEditgooglemaps.map; + this.marker = window.GlizyFormEditgooglemaps.marker; + this.geocoder = window.GlizyFormEditgooglemaps.geocoder; + this.elementMap = jQuery("#GlizyFormEditgooglemaps"); + + this.elementMap.click(function( e ) { + if ( e.stopPropagation ) { + e.stopPropagation(); + } + e.cancelBubble = true; + } ); + + this.$element.click(function( e ) { + if ( e.stopPropagation ) { + e.stopPropagation(); + } + e.cancelBubble = true; + } ); + + jQuery(document).click( function( e ) { + self.closeMap(); + } ); + + + this.$element.next().click( function( e ) { + if ( e.stopPropagation ) { + e.stopPropagation(); + } + e.cancelBubble = true; + self.search(); + } ); + }, + + trim: function (str) + { + var str = str.replace(/^\s\s*/, ''), + ws = /\s/, + i = str.length; + while (ws.test(str.charAt(--i))); + return str.slice(0, i + 1); + }, + + roundDecimal: function( num, decimals ) + { + var mag = Math.pow(10, decimals); + return Math.round(num * mag)/mag; + }, + + getDefaultCurrentPosition: function() + { + var posStr = this.$element.val(); + if(posStr != "") + { + var posArr = posStr.split(","); + if(posArr.length == 2 || posArr.length == 3 ) + { + var lat = this.trim( posArr[0] ); + var lng = this.trim( posArr[1] ); + var zoom = posArr.length == 3 ? parseInt( this.trim( posArr[2] ) ) : 15; + return [lat, lng, zoom ]; + } + } + return [ 51.500152, -0.126236, 15 ]; + }, + + getCurrentPosition: function() + { + var pos = this.getDefaultCurrentPosition(); + var latlng = new google.maps.LatLng(pos[ 0 ], pos[ 1 ]); + this.setPosition(latlng); + }, + + setPosition: function(latLng, viewport) + { + var lat = this.roundDecimal( latLng.lat(), 6 ); + var lng = this.roundDecimal( latLng.lng(), 6 ); + this.marker.setPosition( latLng ); + var zoom; + if ( viewport ) + { + this.map.fitBounds( viewport ); + this.map.setZoom( this.map.getZoom() + 2); + zoom = this.map.getZoom() + 2; + } + else + { + this.map.panTo(latLng); + zoom = this.map.getZoom(); + } + this.map.setZoom( zoom ); + this.$element.val(lat + "," + lng+","+zoom); + // this.setValue( lat + "," + lng+","+zoom ); + }, + + setPositionValues: function() + { + if( this.elementMap.css("display") != "none") + { + var pos = this.getDefaultCurrentPosition(); + pos[ 2 ] = this.map.getZoom(); + this.setValue( pos.join( "," ) ); + } + }, + + isLngLat: function (val) + { + var lngLatArr = val.split(","); + if(lngLatArr.length == 2 || lngLatArr.length == 3 ){ + if(isNaN(lngLatArr[0]) || isNaN(lngLatArr[1])){ + return false; + }else{ + return true; + } + } + return false; + }, + + openMap: function() + { + var self = this; + google.maps.event.clearListeners(this.map, 'dblclick'); + google.maps.event.clearListeners(this.map, 'idle'); + google.maps.event.clearListeners(this.marker, 'dragend'); + + google.maps.event.addListener( this.map, 'dblclick', function(event) { + self.setPosition( event.latLng ); + }); + + google.maps.event.addListener( this.marker, 'dragend', function(event) { + self.setPosition( self.marker.position ); + }); + + google.maps.event.addListener( this.map, 'idle', function(event) { + self.setPositionValues(); + }); + + this.elementMap.css("left", this.$element.offset().left); + this.elementMap.css("top", this.$element.offset().top); + this.elementMap.css("width", this.$element.width()); + this.elementMap.css("display", "block"); + google.maps.event.trigger( this.map, 'resize'); + this.map.setCenter( this.marker.position ); + }, + + closeMap: function() + { + google.maps.event.clearListeners(this.map, 'dblclick'); + google.maps.event.clearListeners(this.map, 'idle'); + google.maps.event.clearListeners(this.marker, 'dragend'); + this.elementMap.css("display", "none"); + }, + + search: function() + { + this.findAddress(); + }, + + findAddress: function() + { + console.log("findAddress") + var self = this; + var address = this.$element.val(); + if (address == ""){ + alert("Inserire un indirizzo o le coordinate longitudine/latitudine."); + }else{ + if(this.isLngLat(address)){ + this.openMap(); + }else{ + this.geocoder.geocode( {'address': address, 'region': 'it'}, function(results, status) { + if (status == google.maps.GeocoderStatus.OK) { + self.setPosition( + results[0].geometry.location, + results[0].geometry.viewport + ); + self.openMap(); + } else { + alert("Geocode was not successful for the following reason: " + status); + } + }); + } + this.focus(); + } + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditMediaPicker.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditMediaPicker.js new file mode 100644 index 0000000..f417e4b --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditMediaPicker.js @@ -0,0 +1,179 @@ +Glizy.oop.declare("glizy.FormEdit.mediapicker", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + $mediaPicker: null, + populateDataEnabled: false, + eventPos: null, + + initialize: function (element, glizyOpt) { + element.data('instance', this); + this.$element = element; + this.populateDataEnabled = element.attr('data-populate_data') == 'true'; + + var that = this; + var $input = element.hide(), + pickerType = $input.attr('data-mediatype'), + hasPreview = $input.attr('data-preview') == 'true'; + + that.$mediaPicker = + hasPreview ? jQuery('<div id="'+element.attr('name')+'-mediapicker" class="mediaPickerSelector mediaPickerField"><div class="mediaPickerCaption"></div><div class="mediaPickerElement">' + GlizyLocale.MediaPicker.imageEmpty + '</div></div>') + : jQuery('<input class="mediaPickerField" type="text" size="50" readonly="readonly" style="cursor:pointer" value="' + GlizyLocale.MediaPicker.imageEmptyText + '">'); + + if (!$input.next().hasClass('mediaPickerField')) { + that.$mediaPicker.insertAfter($input).click(function() { + var url = glizyOpt.mediaPicker; + if (pickerType) { + url += '&mediaType=' + pickerType; + } + Glizy.openIFrameDialog( hasPreview ? GlizyLocale.MediaPicker.imageTitle : GlizyLocale.MediaPicker.mediaTitle, + url, + 900, + 50, + 50, + null, + Glizy.responder(that, that.disposeEvent)); + Glizy.lastMediaPicker = that; + that.eventPos = Glizy.events.on("glizycms.onSetMediaPicker", Glizy.responder(that, that.onSetMediaPicker)); + }); + } + + }, + + getValue: function () { + return this.$element.val(); + }, + + setValue: function (value) { + if (value) { + this.setProps(JSON.parse(value)); + } + }, + + populateData: function(values) { + // TODO: slegare il componente dal repeater + var $container = this.$element.closest('.GFERowContainer'); + + for (var field in values) { + var $el = $container.find('input[data-media_picker_mapping='+field+']'); + if ($el) { + var obj = $el.data('instance'); + + if (obj) { + obj.setValue(values[field]); + } + } + } + }, + + clearData: function() { + // TODO: slegare il componente dal repeater + var $container = this.$element.closest('.GFERowContainer'); + $container.find('input[disabled=disabled]').val(''); + }, + + setProps: function (props) { + var $this = this.$mediaPicker, + $img = $this.find('img'); + + if (this.populateDataEnabled) { + if (props) { + this.populateData(props); + } else { + this.clearData(); + } + } + + if (!props || !props.id) { + if ($img.length) { + $img.replaceWith(GlizyLocale.MediaPicker.imageEmpty); + } + else { + $this.val(GlizyLocale.MediaPicker.imageEmptyText); + } + $this.prev().val(''); + } + else { + if ($img.length) { + $img.load(function () { + + var w = this.naturalWidth, + h = this.naturalHeight, + maxW = $this.width() -6, + maxH = $this.height() -6; + + if (w > maxW) { + h = h * (maxW / w); + w = maxW; + } + if (h > maxH) { + w = w * (maxH / h); + h = maxH; + } + jQuery(this).attr({width: w, height: h}) + .show(); + }) + .hide(); + + $img.attr({title: props.title, src: props.src}) + .data(props); + + if ($img[0].complete && $img[0].naturalWidth !== 0) { + $img.trigger('load'); + } + } + else { + $this.val(props.title); + } + $this.prev().val( JSON.stringify(props) ); + } + }, + + getName: function () { + return this.$element.attr('name'); + }, + + getPreview: function (val) { + try { + var props = JSON.parse(val); + return props.title; + } catch(e) { + return val; + } + }, + + disposeEvent: function() + { + if (this.eventPos!==null && this.eventPos!==undefined) { + Glizy.events.unbind("glizycms.onSetMediaPicker", this.eventPos); + this.eventPos = null; + } + }, + + onSetMediaPicker: function(event) + { + this.disposeEvent(); + this.setProps(event.message); + Glizy.closeIFrameDialog(); + }, + + focus: function () { + var mediaPickerId = this.$element.attr('id')+'-mediapicker'; + $('#'+mediaPickerId).addClass('GFEValidationError'); + document.getElementById(mediaPickerId).scrollIntoView(); + }, + + destroy: function() { + this.disposeEvent(); + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditModalPage.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditModalPage.js new file mode 100644 index 0000000..8db581c --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditModalPage.js @@ -0,0 +1,148 @@ +Glizy.oop.declare("glizy.FormEdit.modalPage", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + pageId: null, + modalDivId: null, + modalIFrameId: null, + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + this.pageId = element.data('pageid'); + var controller = element.data('controller'); + + this.modalDivId = 'modalDiv-'+element.attr('id'); + this.modalIFrameId = 'modalIFrame-'+element.attr('id'); + + var that = this; + + element.select2({ + placeholder: '', + allowClear: true, + ajax: { + url: Glizy.ajaxUrl + '&controllerName='+controller, + dataType: 'json', + quietMillis: 250, + data: function(term, page) { + return { + fieldName: 'fieldName', + model: 'model', + term: term + }; + }, + results: function(data, page ) { + data.result.push({id:'__addNewEntry', 'text':'<input class="btn" type="button" value="Aggiungi nuova entry" />'}); + return { results: data.result } + } + }, + formatSelection: function(data) { + if (data.id == '__addNewEntry') { + that.openModal(); + } else { + that.populateData(data.values); + return data.text; + } + } + }) + .on("change", function(e) { + if (e.val == '') { + that.clearData(); + } + }); + + window.addEventListener("message", this.receiveMessage, false); + }, + + populateData: function(values) { + // TODO: slegare il componente dal repeater + var $container = this.$element.closest('.GFERowContainer'); + + for (var field in values) { + var $el = $container.find('input[name='+field+']'); + if ($el) { + var obj = $el.data('instance'); + + if (obj) { + obj.setValue(values[field]); + } + } + } + }, + + clearData: function() { + // TODO: slegare il componente dal repeater + var $container = this.$element.closest('.GFERowContainer'); + $container.find('input[disabled=disabled]').val(''); + }, + + openDialogCallback: function() { + }, + + receiveMessage: function (event) + { + Glizy.closeIFrameDialog(true); + + var $element = $('.__selectedModalPage'); + + var msg = JSON.parse(event.data); + + if (msg.type == 'save') { + $element.select2('data', {id: msg.id, text: msg.text, values: msg.values}); + } + + $element.removeClass('__selectedModalPage'); + }, + + openModal: function() { + var w = Math.min( $( window ).width() - 50, 900 ); + + this.$element.addClass('__selectedModalPage'); + + Glizy.openIFrameDialog( + '', + 'index.php?pageId='+this.pageId, + w, + 50, + 50, + this.openDialogCallback + ); + }, + + getValue: function () { + var data = this.$element.select2('data'); + + if (data) { + return {id: data.id, text: data.text}; + } else { + return null; + } + }, + + setValue: function (value) { + if (value) { + this.$element.select2('data', value); + } + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function () { + this.$element.select2('focus'); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditPermission.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditPermission.js new file mode 100644 index 0000000..b7e14c5 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditPermission.js @@ -0,0 +1,55 @@ +Glizy.oop.declare("glizy.FormEdit.permission", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + element.removeAttr('value'); + element.css('width', '500px'); + }, + + getValue: function () { + return this.$element.select2('val'); + }, + + setValue: function (value) { + if (value !== undefined && value.length > 0) { + var arrayVal = [] + + $.each(value, function(index, v) { + if (typeof(v)=="object") { + arrayVal.push(v); + } + else { + arrayVal.push({id: v, text: v}); + } + }); + + this.$element.select2('data', arrayVal); + } + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function() + { + this.$element.focus(); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditPhotoGalleryCategory.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditPhotoGalleryCategory.js new file mode 100644 index 0000000..410bf37 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditPhotoGalleryCategory.js @@ -0,0 +1,57 @@ +Glizy.oop.declare("glizy.FormEdit.photogallerycategory", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + }, + + getValue: function () { + var galleryType = $('#galleryType').val(); + var galleryImages = $('#gallery-images').select2('val'); + return {'galleryType': galleryType, 'gallery-images': galleryImages}; + }, + + setValue: function (value) { + if (value) { + $('#galleryType').val(value['galleryType']); + + var arrayVal = [] + + $.each(value['gallery-images'], function(index, v) { + if (typeof(v)=="object") { + arrayVal.push(v); + } + else { + arrayVal.push({id: v, text: v}); + } + }); + + $('#gallery-images').select2('data', arrayVal); + } + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function() + { + this.$element.focus(); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditRepeat.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditRepeat.js new file mode 100644 index 0000000..9b41da8 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditRepeat.js @@ -0,0 +1,419 @@ +Glizy.oop.declare("glizy.FormEdit.repeat", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + id: null, + idParent: null, + children: [], + isCollapsable: null, + minRec: null, + maxRec: null, + noAddRowButton: null, + sortable: null, + glizyOpt: null, + form: null, + + initialize: function (element, glizyOpt, form, addBtnId, idParent) { + this.$super(element); + this.idParent = idParent; + + this.id = element.attr('id'); + this.glizyOpt = glizyOpt; + this.form = form; + + if (addBtnId === undefined) { + addBtnId = this.id; + } + + var self = this; + + this.getOptions(); + this.addClass('GFEFieldset'); + if (this.minRec > 0 ) { + this.addClass('required'); + } + var $fields = this.$element.children(':not(legend)'); + var $fieldSet = this.$element; + + // TODO: spostare tutta la logica di template in un file appaorte (es handlebars.js) + if (!this.noAddRowButton) { + this.$element.append('<div class="GFEFooter"><div class="GFEButtonContainer"><input type="button" id="'+addBtnId+'-addRowBtn" value="' + GlizyLocale.Repeater.addRecord + '" class="btn GFEAddRow"></div><div class="GFEStatusContainer">' + GlizyLocale.Repeater.minRecords + this.minRec + (this.maxRec ? (GlizyLocale.Repeater.maxRecords + this.maxRec) : '') + '</div><div class="GFESideClearer"></div></div>'); + } else { + this.$element.append('<div class="GFEFooter"></div>'); + } + + $fields.wrapAll('<div class="GFERowContainer" />'); + + var $rowContainer = $fieldSet.children('.GFERowContainer'); + + if (this.isCollapsable) { + $fields.wrapAll('<div class="GFERowExpanded" />'); + + var rowhandler = this.sortable ? '<span class="GFERowHandler"><img width="16" height="38" title="' + GlizyLocale.Repeater.drag + '" alt="' + GlizyLocale.Repeater.drag + '" src="./application/templates/images/dragHandler.gif"></span>' : ''; + + $rowContainer + .append('<div class="GFERowCollapsed"><div class="GFERowHeader">'+rowhandler+'<span class="GFERecordTitle">' + GlizyLocale.Repeater.record + ' <span class="GFERecordId">1</span></span><span class="GFERowPreview"></span></div><div class="GFERowPanel"><img width="16" height="16" class="icon GFERowEdit" title="' + GlizyLocale.Repeater.edit + '" alt="' + GlizyLocale.Repeater.edit + '" src="./application/templates/images/icon_edit.gif"><img width="16" height="16" class="icon GFERowDelete " title="' + GlizyLocale.Repeater.remove + '" alt="' + GlizyLocale.Repeater.remove + '" src="./application/templates/images/icon_delete.gif"></div><div class="GFESideClearer"></div></div>') + .children('.GFERowExpanded') + .append('<div class="GFERowButtonContainer"><input type="button" value="' + GlizyLocale.Repeater.confirm + '" class="btn btn-primary GFERowDoCollapse GFERowDoConfirm">&nbsp;<input type="button" value="' + GlizyLocale.Repeater.cancel + '" class="btn GFERowDoCollapse"></div>') + .hide(); + } + else { + var rowhandler = this.sortable ? '<span class="GFERowHandler GFERowHandlerExpanded"><img width="16" style="height:100%" title="' + GlizyLocale.Repeater.drag + '" widalt="' + GlizyLocale.Repeater.drag + '" src="./application/templates/images/dragHandler.gif"></span>' : ''; + $rowContainer + .append(rowhandler + '<img width="16" height="16" class="icon GFERowDelete GFERightIcon" title="' + GlizyLocale.Repeater.remove + '" alt="' + GlizyLocale.Repeater.remove + '" src="./application/templates/images/icon_delete.gif">') + } + + $fieldSet.data('rowModel', $rowContainer.clone(true) + .find('[name]').val('').removeAttr('id').end() + ); + + $rowContainer.remove(); + + if (!this.noAddRowButton) { + $fieldSet.prepend('<div class="GFEEmptyMessage">' + (this.minRec ? GlizyLocale.Repeater.noRecordEntered1 + this.minRec + GlizyLocale.Repeater.noRecordEntered2 : GlizyLocale.Repeater.clickAddRecordButton) + '</div>'); + } + + // TODO: aggiungere solo se non è stato aggiunto in precedenza + $('body').append('<div class="GFETranslucentCover"></div>'); + + this.makeSortable(); + + var invalidFields = 0; + var customValidationInvalid = false; + + $fieldSet.data('instance', self); + + $(document).on('click', '.GFERowDoCollapse', function () { + var $button = $(this), + hasConfirmed = $button.hasClass('GFERowDoConfirm'), + $rowCont = $button.closest('.GFERowContainer'), + $inputFields = $('[name]', $rowCont), + //$inputFields = $('input:not([type=button]), textarea', $rowCont), + fieldPrev = ''; + + if (hasConfirmed && (form.triggerHandler('submitForm') === false && invalidFields || customValidationInvalid)) { + customValidationInvalid = false; + return; + } + $rowCont.removeClass('GFEEditingRow').children('.GFERowCollapsed').show() + .end().children('.GFERowExpanded').hide(); + + // TODO rivedere questa parte, forse conviene usare this.children + if (hasConfirmed) { + $inputFields.each(function () { + var $this = $(this); + var obj = $this.data('instance'); + if (obj) { + var val = obj.getValue(); + if (val) { + $this.data('oldVal', val); + //fieldPrev += getFieldPreview.call($this, val); + } + } + }); + $('.GFERowPreview', $rowCont).html(fieldPrev); + $rowCont.removeData('justCreated'); + } + else { + $inputFields.each(function () { + var $this = $(this); + var obj = $this.data('instance'); + + if (obj) { + var val = obj.setValue($(this).data('oldVal') || ''); + } + + if (!$this.data('overloadCalled')) { + $this.val($this.data('oldVal') || ''); + } + $this.removeClass('GFEValidationError'); + }); + if ($rowCont.data('justCreated')) { + $rowCont.remove(); + } + } + + $('.GFETranslucentCover').hide(); + }); + + $(document).on('click', '.GFERowEdit', function () { + var $container = $(this).closest('.GFERowContainer'), + $contBound = $container[0].getBoundingClientRect(), + $window = $(window), + wHeight = $window.height(); + + $container.addClass('GFEEditingRow') + .children('.GFERowCollapsed').hide() + .end().children('.GFERowExpanded').show(); + + $window.scrollTop($container.offset().top - Math.max((wHeight - $container.height()) / 2, 0)); + + $('.GFETranslucentCover').show(); + }); + + $('#'+addBtnId+'-addRowBtn').on('click', function () { + var $button = $(this), + $fieldSet = $button.parents('fieldset:first'), + self = $fieldSet.data('instance'), + $rows = $fieldSet.children('.GFERowContainer'); + + if ($button.hasClass('GButtonDisabled')) { + return; + } + + if (self.maxRec && $rows.length == self.maxRec - 1) { + $button.addClass('GButtonDisabled').attr('disabled', 'disabled').blur(); + } + + var newRowId; + + // Gestisce il caso di riordino dei GFERowContainer + // oppure la cancellazione di un GFERowContainer tra più GFERowContainer + if ($rows.length > 0) { + // gli id dei GFERowContainer in un array + var rowsId = $rows.map(function() { return $(this).data('id') }).get(); + newRowId = Math.max.apply(Math, rowsId) + 1; + } else { + newRowId = 0; + } + + self.addRow($fieldSet, $button.closest('.GFEFooter'), newRowId, true); + //self.makeSortable(); + }); + + Glizy.events.on("glizycms.fileUpload", function(e) { + var $footer = $fieldSet.children('.GFEFooter'); + var $rows = $fieldSet.children('.GFERowContainer'); + + self.addRow($fieldSet, $footer, $rows.length, true); + + //$fieldSet.syncRecords().makeSortable(); + $fieldSet.find('.GFERowEdit:last').click(); + + //self.verifySelectWithTarget($fieldSet); + //enableValidation(); + + var $title = $fieldSet.find('input[name*=title]:last'); + + if ($title) { + $title.val(e.message.fileName.replace(/\.[^/.]+$/, "")); + } + }); + }, + + verifySelectWithTarget: function($container) { + $container.find('select').each(function () { + var target = $(this).data('target'); + if ( target ) { + $(this).change(function(e){ + var sel = this.selectedIndex, + name = this.name, + states = $(this).data("val_"+sel), + stateMap = {}; + var t = target.split(","); + states = states.split(","); + + $(t).each(function(index, val) { + stateMap[val] = states[index]; + }); + + $container.find("[name]").each(function(){ + var $el = $(this); + var state = stateMap[$el.attr("name")]; + if (state === '1') { + $el.closest("div.control-group").show(); + } else if (state == '0') { + $el.closest("div.control-group").hide(); + } + }); + }); + $(this).trigger("change"); + } + }); + }, + + getOptions: function () { + this.isCollapsable = this.$element.attr('data-collapsable') == 'true'; + this.minRec = parseInt(this.$element.attr('data-repeatmin') || 0); + this.maxRec = parseInt(this.$element.attr('data-repeatmax') || 0); + this.noAddRowButton = this.$element.attr('data-noAddRowButton') == 'true'; + this.sortable = this.$element.attr('data-sortable') == 'true' || this.$element.attr('data-sortable') === undefined; + }, + + addDeleteHandler : function(containerId) { + var self = this; + + $('#'+containerId+' img.GFERowDelete').on('click', function () { + var $container = $('#'+containerId), + $fieldSet = $container.parent(), + $rows = $fieldSet.children('.GFERowContainer'); + + var id = $container.data('id'); + + //overloadCaller.call($('#fileuploader'), 'removeFile', i); + + if ($rows.length == 0) { + //alert(GlizyLocale.Repeater.minRecordMsg + self.minRec); + return; + } + + for (var field in self.children[id]) { + var fieldObj = self.children[id][field]; + fieldObj.destroy(); + } + + self.children.splice(id, 1); + + $('.GFEAddRow').removeClass('GButtonDisabled').removeAttr('disabled'); + $container.remove(); + + if (!$fieldSet.children('.GFERowContainer').length) { + $('.GFEEmptyMessage:first', $fieldSet).show(); + } + }); + }, + + addRow: function (fieldSet, footer, id, justCreated, noVerifySelectWithTarget) { + var idParentPrefix = (this.idParent === null) ? '' : this.idParent+'-'; + var self = this; + var fieldSetId = fieldSet.attr('id'); + var containerId = idParentPrefix+fieldSetId+id; + var $container = fieldSet.data('rowModel').clone(true); + $container.find('.GFERecordId').text(id + 1); + $container.attr('id', containerId); + + footer.before($container); + + $('#'+containerId).data('justCreated', justCreated || false); + $('#'+containerId).data('id', id); + + this.addDeleteHandler(containerId); + + $('.GFEEmptyMessage:first', fieldSet).hide(); + + this.children.splice(id, 0, {}); + + $('#'+containerId+' input[name]:not( [type="button"], [type="submit"], [type="reset"] ), '+ + '#'+containerId+' select[name], '+ + '#'+containerId+' textarea[name], '+ + '#'+containerId+' fieldset[data-type]').each(function () { + var element = $(this); + + var parents = element.parents('[data-type]'); + + // se l'elemento è contenuto immediatamente nel repeater + if (parents[0] == self.$element[0]) { + var addBtnId = containerId+'-'+$(this).attr('id'); + self.createChild(id, element, addBtnId, containerId); + } + }); + + if (noVerifySelectWithTarget === undefined) { + this.verifySelectWithTarget($container); + } + + return $container; + }, + + createChild: function(rowId, element, addBtnId, containerId) { + var type = element.data('type') || 'standard'; + var obj = Glizy.oop.create("glizy.FormEdit."+type, element, this.glizyOpt, this.$form, addBtnId, containerId); + var name = obj.getName(); + this.children[rowId][name] = obj; + }, + + makeSortable: function () { + var from; + var self = this; + return this.$element.sortable({ + items: '.GFERowContainer', + handle: '.GFERowHandler', + start: function (ev, ui) { + from = ui.item.index()-2; + }, + stop: function (ev, ui) { + var to = ui.item.index()-2; + + // sposta un elemento nell'array da from a to + function arraymove(arr, from, to) { + var element = arr[from]; + arr.splice(from, 1); + arr.splice(to, 0, element); + } + + if (from !== to) { + arraymove(self.children, from, to); + } + } + }); + }, + + getValue: function () { + var data = []; + for (var i in this.children) { + var row = this.children[i]; + var obj = {}; + for (var field in row) { + var fieldObj = row[field]; + + if (!fieldObj.isDisabled()) { + var val = fieldObj.getValue(); + obj[field] = val; + } + } + data.push(obj); + } + + return data; + }, + + setValue: function (value) { + if (value && value.length > 0) { + var $fieldSet = this.$element; + var $footer = $fieldSet.children('.GFEFooter'); + + for (var i in value) { + var $container = this.addRow($fieldSet, $footer, i, true, true); + var row = value[i]; + for (var field in row) { + var v = row[field]; + var obj = this.children[i][field]; + + if (obj) { + obj.setValue(v); + } + } + this.verifySelectWithTarget($container); + } + } + }, + + getName: function () { + return this.id; + }, + + focus: function() { + $('html, body').animate({ scrollTop: this.$element.offset().top - this.$element.prop('scrollHeight')}, 'slow'); + }, + + isValid: function() { + if (this.minRec == 0 || this.children.length >= this.minRec) { + var isValid = true; + + for (var i in this.children) { + var row = this.children[i]; + for (var field in row) { + var fieldObj = row[field]; + + if (!fieldObj.isValid()) { + fieldObj.addClass('GFEValidationError'); + isValid = false; + } else { + fieldObj.removeClass('GFEValidationError'); + } + } + } + return isValid; + } else { + return false; + } + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditSelectFrom.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditSelectFrom.js new file mode 100644 index 0000000..11faefb --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditSelectFrom.js @@ -0,0 +1,153 @@ +Glizy.oop.declare("glizy.FormEdit.selectfrom", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + multiple: null, + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + + element.removeAttr('value'); + element.css('width', '500px'); + + var fieldName = element.data('field') || element.attr('name'); + this.multiple = element.data('multiple'); + var addNewValues = element.data('add_new_values'); + var model = element.data('model'); + var query = element.data('query'); + var proxy = element.data('proxy'); + var proxyParams = element.data('proxy_params'); + if (proxyParams) { + proxyParams = proxyParams.replace(/##/g,'"'); + } + var placeholder = element.data('placeholder'); + var originalName = element.data('originalName'); + var getId = element.data('get_id'); + var selectedCallback = element.data('selected_callback'); + var minimumInputLength = $(this).data('min_input_length') || 0; + var formatSelection = $(this).data('format_selection'); + var formatResult = $(this).data('format_result'); + + if (originalName !== undefined && element.data('override')!==false) { + fieldName = originalName; + } + + element.select2({ + width: 'off', + multiple: this.multiple, + minimumInputLength: minimumInputLength, + placeholder: placeholder === undefined ? '' : placeholder, + allowClear: true, + ajax: { + url: Glizy.ajaxUrl + "&controllerName=org.glizycms.contents.controllers.autocomplete.ajax.FindTerm", + dataType: 'json', + quietMillis: 250, + data: function(term, page) { + return { + fieldName: fieldName, + model: model, + query: query, + term: term, + proxy: proxy, + proxyParams: proxyParams, + getId: getId + }; + }, + results: function(data, page ) { + return { results: data.result } + } + }, + createSearchChoice: function(term, data) { + if (!addNewValues) { + return false; + } + + if ($(data).filter(function() { + return this.text.localeCompare(term)===0; + }).length===0) { + return {id:term, text:term}; + } + }, + formatResult: function(data) { + return formatResult === undefined ? data.text : window[formatResult](data); + }, + formatSelection: function(data) { + if (selectedCallback) { + var term = data.text; + + $.ajax({ + url: Glizy.ajaxUrl+"&controllerName="+selectedCallback, + data: { + fieldName: fieldName, + model: model, + query: query, + term: term, + proxy: proxy, + proxyParams: proxyParams, + getId: getId + }, + type: "POST" + }); + } + + return formatSelection === undefined ? data.text : window[formatSelection](data); + } + }); + }, + + getValue: function () { + if (this.$element.data('return_object')) { + return this.$element.select2('data'); + } else { + return this.$element.select2('val'); + } + }, + + setValue: function (value) { + if (!this.multiple) { + if (value) { + if (typeof(value)=="object") { + this.$element.select2('data', value); + } else { + this.$element.select2('data', {id: value, text: value}); + } + } + } + else if (value !== undefined && value.length > 0) { + var arrayVal = [] + + $.each(value, function(index, v) { + if (typeof(v)=="object") { + arrayVal.push(v); + } + else { + arrayVal.push({id: v, text: v}); + } + }); + + this.$element.select2('data', arrayVal); + } + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function () { + this.$element.select2('focus'); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditSelectPageType.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditSelectPageType.js new file mode 100644 index 0000000..0d38a60 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditSelectPageType.js @@ -0,0 +1,59 @@ +Glizy.oop.declare("glizy.FormEdit.selectpagetype", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + var $previous = null; + + element.next().find('a').click(function( event ) { + element.next().find('li').each(function( index ) { + $(this).removeClass('button-selected'); + }); + $(this).parent().addClass('button-selected'); + var pageType = $(this).data('type'); + element.val(pageType); + }); + + var currentValue = element.val(); + if (currentValue) { + element.next().find('a').each(function(element) { + if ($(this).data('type')==currentValue) { + $(this).parent().addClass('button-selected'); + } + }); + } + }, + + getValue: function () { + return this.$element.val(); + }, + + setValue: function (value) { + this.$element.val(value); + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function() + { + this.$element.focus(); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditStandard.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditStandard.js new file mode 100644 index 0000000..818c30e --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditStandard.js @@ -0,0 +1,52 @@ +Glizy.oop.declare("glizy.FormEdit.standard", { + $element: null, + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + }, + + getElement: function () { + return this.$element; + }, + + getValue: function () { + return this.$element.val(); + }, + + setValue: function (value) { + this.$element.val(value); + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function() + { + this.$element.focus(); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + }, + + isValid: function() { + if (this.$element.hasClass('required')) { + return this.getValue() != ''; + } else { + return true; + } + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditTINYMCE.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditTINYMCE.js new file mode 100644 index 0000000..77ef1e6 --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditTINYMCE.js @@ -0,0 +1,67 @@ +Glizy.oop.declare("glizy.FormEdit.tinymce", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + elementId: null, + editor: null, + + $statics: { + id: 0 + }, + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + + if (!element.attr('id')) { + this.$self.id++; + this.elementId = element.attr('name') + this.$self.id; + element.attr('id', this.elementId); + } else { + this.elementId = element.attr('id'); + } + + var options = Glizy.tinyMCE_options; + + options.mode = "exact"; + options.elements = this.elementId; + options.document_base_url = Glizy.tinyMCE_options.urls.root; + tinyMCE.init( options ); + }, + + save: function () { + return tinyMCE.get(this.elementId).save(); + }, + + getValue: function () { + return tinyMCE.get(this.elementId).getContent(); + }, + + setValue: function (value) { + this.$element.val(value); + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function() + { + $('html, body').animate({ scrollTop: this.$element.parent().offset().top - this.$element.parent().prop('scrollHeight') }, 'slow'); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + var container = tinyMCE.get(this.elementId).getContainer(); + $(container).find('.mceLayout').addClass(className); + }, + + removeClass: function(className) { + var container = tinyMCE.get(this.elementId).getContainer(); + $(container).find('.mceLayout').removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditUrl.js b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditUrl.js new file mode 100644 index 0000000..0ab8ecf --- /dev/null +++ b/src/core/classes/org/glizycms/js/formEdit2/GlizyFormEditUrl.js @@ -0,0 +1,40 @@ +Glizy.oop.declare("glizy.FormEdit.url", { + $extends: Glizy.oop.get('glizy.FormEdit.standard'), + + initialize: function (element) { + element.data('instance', this); + this.$element = element; + }, + + getValue: function () { + return this.$element.val(); + }, + + setValue: function (value) { + this.$element.val(value); + }, + + getName: function () { + return this.$element.attr('name'); + }, + + focus: function() + { + this.$element.focus(); + }, + + destroy: function() { + }, + + isDisabled: function() { + return this.$element.attr('disabled') == 'disabled'; + }, + + addClass: function(className) { + this.$element.addClass(className); + }, + + removeClass: function(className) { + this.$element.removeClass(className); + } +}); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/glizy-locale/en-EN.js b/src/core/classes/org/glizycms/js/glizy-locale/en-EN.js new file mode 100644 index 0000000..a81de86 --- /dev/null +++ b/src/core/classes/org/glizycms/js/glizy-locale/en-EN.js @@ -0,0 +1,81 @@ +GlizyLocale.FormEdit = { + saveSuccessMsg: "Data saved correctly", + errorValidationMsg: "Error saving data", + addRecord: "Add record", + minRecords: "Minimum Records: ", + maxRecords: " / Maximum Records: ", + drag: "Drag", + record: "Record", + edit: "Edit", + remove: "Remove", + confirm: "Confirm", + save: "Save", + cancel: "Cancel", + noRecordEntered1: "No records entered, you must enter at least ", + noRecordEntered2: " record(s)", + clickAddRecordButton: "Press the \"Add record\" button to insert a record", + minRecordMsg: "The minimum number of records is ", + insertComment: "Insert a note", + search: "Search", + googleMapError_1: "Enter an address or coordinates", + googleMapError_2: "Geocode was not successful for the following reason" +}; + +GlizyLocale.FineUploader = { + uploadButton: 'Click to upload one or more files', + cancelButton: 'Cancel', + retryButton: 'Retry', + failUpload: 'Upload failed', + dragZone: 'Drop files here to upload', + formatProgress: "{percent}% of {total_size}", + waitingForResponse: "Processing...", + fileTitle: 'Title', + fileCategory: 'Category', + maxsize: 'max size' +}; + +GlizyLocale.MediaPicker = { + mediaTitle: 'Select a media', + imageTitle: 'Select an image', + imageEmpty: '<img src="./application/templates/images/noimage.jpg">', + imageEmptyText: 'NO MEDIA SELECTED' +}; + +GlizyLocale.Repeater = { + addRecord: "Add record", + minRecords: "Minimum Records: ", + maxRecords: " / Maximum Records: ", + drag: "Drag", + record: "Record", + edit: "Edit", + remove: "Remove", + confirm: "Confirm", + cancel: "Cancel", + noRecordEntered1: "No records entered, you must enter at least ", + noRecordEntered2: " record(s)", + clickAddRecordButton: "Press the \"Add record\" button to insert a record", + minRecordMsg: "The minimum number of records is " +}; + +GlizyLocale.date = { + format: "yyyy-mm-dd" + }; + +GlizyLocale.datetime = { + format: "yyyy-mm-dd hh:mm:ss" + }; + +GlizyLocale.HotSpot = { + loadImage: 'Load image', + addPath: 'Add hotspot', + hotspotForm: 'Shape', + hotspotType: 'Type', + formQuad: 'quadrangular', + formCircle: 'circular', + linkEx: 'external link', + linkInt: 'internal link', + tooltip: 'tooltip', + urlEx: 'Url', + urlInt: 'Page', + description: 'text' +}; \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/glizy-locale/it-IT.js b/src/core/classes/org/glizycms/js/glizy-locale/it-IT.js new file mode 100644 index 0000000..b7e0157 --- /dev/null +++ b/src/core/classes/org/glizycms/js/glizy-locale/it-IT.js @@ -0,0 +1,81 @@ +GlizyLocale.FormEdit = { + saveSuccessMsg: "Dati salvati correttamente", + errorValidationMsg: "Errore nell'inserimento dati", + addRecord: "Aggiungi un record", + minRecords: "Record Minimi: ", + maxRecords: " / Record Massimi: ", + drag: "Trascina", + record: "Record", + edit: "Modifica", + remove: "Elimina", + save: "Salva", + confirm: "Conferma", + cancel: "Annulla", + noRecordEntered1: "Nessun record inserito, è necessario inserire almeno ", + noRecordEntered2: " record(s)", + clickAddRecordButton: "Premere il tasto \"%s\" per inserire un record", + minRecordMsg: "Il numero minimo di records è ", + insertComment: "Inserisci un commento", + search: "Cerca", + googleMapError_1: "Inserire un indirizzo o le coordinate longitudine/latitudine", + googleMapError_2: "Errore nella ricerca dell'indirizzo" +} + +GlizyLocale.FineUploader = { + uploadButton: 'Trascina qui i files da caricare', + cancelButton: 'Cancella', + retryButton: 'Riprova', + failUpload: 'Caricamento fallito', + dragZone: 'Trascina qui i files da caricare', + formatProgress: "{percent}% di {total_size}", + waitingForResponse: "Processando...", + fileTitle: 'Titolo', + fileCategory: 'Categoria', + maxsize: 'dimensione massima' +}; + +GlizyLocale.MediaPicker = { + mediaTitle: 'Seleziona un media', + imageTitle: 'Seleziona un\'immagine', + imageEmpty: '<img src="./application/templates/images/noimage.jpg">', + imageEmptyText: 'NESSUNA MEDIA SELEZIONATO' +}; + +GlizyLocale.Repeater = { + addRecord: "Aggiungi un record", + minRecords: "Record Minimi: ", + maxRecords: " / Record Massimi: ", + drag: "Trascina", + record: "Record", + edit: "Modifica", + remove: "Elimina", + confirm: "Conferma", + cancel: "Annulla", + noRecordEntered1: "Nessun record inserito, è necessario inserire almeno ", + noRecordEntered2: " record(s)", + clickAddRecordButton: "Premere il tasto \"Aggiungi un record\" per inserire un record", + minRecordMsg: "Il numero minimo di records è " +}; + +GlizyLocale.date = { + format: "dd/mm/yyyy" +}; + +GlizyLocale.datetime = { + format: "dd/mm/yyyy hh:mm:ss" +}; + +GlizyLocale.HotSpot = { + loadImage: 'Carica immagine', + addPath: 'Aggiungi tracciato', + hotspotForm: 'Forma', + hotspotType: 'Tipo', + formQuad: 'quadrangolare', + formCircle: 'circolare', + linkEx: 'link esterno', + linkInt: 'link interno', + tooltip: 'tooltip', + urlEx: 'Url', + urlInt: 'Pagina', + description: 'descrizione' +}; diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/LICENSE b/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/LICENSE new file mode 100755 index 0000000..a37331e --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/LICENSE @@ -0,0 +1,13 @@ +Copyright 2012 Stefan Petre + +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. \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/README.md b/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/README.md new file mode 100755 index 0000000..689c1eb --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/README.md @@ -0,0 +1,15 @@ +# Colorpicker plugin for Twitter Bootstrap + +Originally written by [Stefan Petre](http://www.eyecon.ro/) + +Read the documentation [here](http://mjaalnir.github.io/bootstrap-colorpicker/) + + +## Contributors + +Please, before perform a Pull Request: + +* Check that the index.html demos aren't broken (modify if necessary) +* Test your code in all modern browsers (and at least IE >= 9) + +Thanks =) \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css b/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css new file mode 100755 index 0000000..5a6866f --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/css/bootstrap-colorpicker.min.css @@ -0,0 +1,6 @@ +/*! + * Bootstrap Colorpicker + * (c) 2012 Stefan Petre + * http://mjaalnir.github.io/bootstrap-colorpicker/ + * http://www.apache.org/licenses/LICENSE-2.0.txt + */.colorpicker-saturation{width:100px;height:100px;background-image:url(../img/bootstrap-colorpicker/saturation.png);cursor:crosshair;float:left}.colorpicker-saturation i{display:block;height:5px;width:5px;border:1px solid #000;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;position:absolute;top:0;left:0;margin:-4px 0 0 -4px}.colorpicker-saturation i b{display:block;height:5px;width:5px;border:1px solid #fff;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.colorpicker-hue,.colorpicker-alpha{width:15px;height:100px;float:left;cursor:row-resize;margin-left:4px;margin-bottom:4px}.colorpicker-hue i,.colorpicker-alpha i{display:block;height:1px;background:#000;border-top:1px solid #fff;position:absolute;top:0;left:0;width:100%;margin-top:-1px}.colorpicker-hue{background-image:url(../img/bootstrap-colorpicker/hue.png)}.colorpicker-alpha{background-image:url(../img/bootstrap-colorpicker/alpha.png);display:none}.colorpicker{*zoom:1;top:0;left:0;padding:4px;min-width:130px;margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.colorpicker:before,.colorpicker:after{display:table;content:""}.colorpicker:after{clear:both}.colorpicker:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0,0,0,.2);position:absolute;top:-7px;left:6px}.colorpicker:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #fff;position:absolute;top:-6px;left:7px}.colorpicker div{position:relative}.colorpicker.alpha{min-width:140px}.colorpicker.alpha .colorpicker-alpha{display:block}.colorpicker-color{height:10px;margin-top:5px;clear:both;background-image:url(../img/bootstrap-colorpicker/alpha.png);background-position:0 100%}.colorpicker-color div{height:10px}.colorpicker-component .add-on i,.colorpicker-component .input-group-addon i{display:block;cursor:pointer;width:16px;height:16px} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha.png b/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/img/bootstrap-colorpicker/alpha.png new file mode 100755 index 0000000000000000000000000000000000000000..38043f1c85f20fe8ce37ad380bebe2d42d14fb29 GIT binary patch literal 3271 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 FV1iYw9mW6v literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/img/bootstrap-colorpicker/hue.png b/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/img/bootstrap-colorpicker/hue.png new file mode 100755 index 0000000000000000000000000000000000000000..d89560e999f86c349ddc78c298b0328293f13e1e GIT binary patch literal 2972 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 Sf}iF90000<MNUMnLSTZ^%YmT) literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/img/bootstrap-colorpicker/saturation.png b/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/img/bootstrap-colorpicker/saturation.png new file mode 100755 index 0000000000000000000000000000000000000000..594ae50ed77608cf6373d6b39e5cacb9f63b7bbe GIT binary patch literal 8817 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 literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js new file mode 100755 index 0000000..7816861 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js @@ -0,0 +1,21 @@ +/*! + * Bootstrap Colorpicker + * (c) 2012 Stefan Petre + * http://mjaalnir.github.io/bootstrap-colorpicker/ + * http://www.apache.org/licenses/LICENSE-2.0.txt + */(function(d){var k=function(a){this.value={h:1,s:1,b:1,a:1};this.setColor(a)};k.prototype={constructor:k,setColor:function(a){a=a.toLowerCase();var b=this;d.each(e.stringParsers,function(c,d){var f=d.re.exec(a),f=f&&d.parse(f),g=d.space||"rgba";return f?(b.value="hsla"===g?e.RGBtoHSB.apply(null,e.HSLtoRGB.apply(null,f)):e.RGBtoHSB.apply(null,f),!1):!0})},setHue:function(a){this.value.h=1-a},setSaturation:function(a){this.value.s=a},setLightness:function(a){this.value.b=1-a},setAlpha:function(a){this.value.a= +parseInt(100*(1-a),10)/100},toRGB:function(a,b,c,d){a||(a=this.value.h,b=this.value.s,c=this.value.b);var f,g,e;a=360*a%360/60;e=c*b;b=e*(1-Math.abs(a%2-1));c=f=g=c-e;a=~~a;c+=[e,b,0,0,b,e][a];f+=[b,e,e,b,0,0][a];g+=[0,0,b,e,e,b][a];return{r:Math.round(255*c),g:Math.round(255*f),b:Math.round(255*g),a:d||this.value.a}},toHex:function(a,b,c,d){a=this.toRGB(a,b,c,d);return"#"+(16777216|parseInt(a.r)<<16|parseInt(a.g)<<8|parseInt(a.b)).toString(16).substr(1)},toHSL:function(a,b,c,d){a||(a=this.value.h, +b=this.value.s,c=this.value.b);var f=(2-b)*c;b*=c;b=0<f&&1>=f?b/f:b/(2-f);1<b&&(b=1);return{h:a,s:b,l:f/2,a:d||this.value.a}}};var l=0,h=function(a,b){l++;this.element=d(a).attr("data-colorpicker-guid",l);var c=b.format||this.element.data("color-format")||"hex";this.format=e.translateFormats[c];this.isInput=this.element.is("input");this.component=this.element.is(".colorpicker-component")?this.element.find(".add-on, .input-group-addon"):!1;this.picker=d(e.template).attr("data-colorpicker-guid",l).appendTo("body").on("mousedown.colorpicker", +d.proxy(this.mousedown,this));if(this.isInput)this.element.on({"focus.colorpicker":d.proxy(this.show,this),"keyup.colorpicker":d.proxy(this.update,this)});else if(this.component)this.component.on({"click.colorpicker":d.proxy(this.show,this)});else this.element.on({"click.colorpicker":d.proxy(this.show,this)});if("rgba"===c||"hsla"===c)this.picker.addClass("alpha"),this.alpha=this.picker.find(".colorpicker-alpha")[0].style;this.component?(this.picker.find(".colorpicker-color").hide(),this.preview= +this.element.find("i")[0].style):this.preview=this.picker.find("div:last")[0].style;this.base=this.picker.find("div:first")[0].style;this.update();d(d.proxy(function(){this.element.trigger("create",[this])},this))};h.prototype={constructor:h,show:function(a){this.picker.show();this.height=this.component?this.component.outerHeight():this.element.outerHeight();this.place();d(window).on("resize.colorpicker",d.proxy(this.place,this));!this.isInput&&a&&(a.stopPropagation(),a.preventDefault());d(document).on({"mousedown.colorpicker":d.proxy(this.hide, +this)});this.element.trigger({type:"showPicker",color:this.color})},update:function(){var a=this.isInput?this.element.prop("value"):this.element.data("color");if("undefined"===typeof a||null===a)a="#ffffff";this.color=new k(a);this.picker.find("i").eq(0).css({left:100*this.color.value.s,top:100-100*this.color.value.b}).end().eq(1).css("top",100*(1-this.color.value.h)).end().eq(2).css("top",100*(1-this.color.value.a));this.previewColor()},hide:function(){this.picker.hide();d(window).off("resize",this.place); +d(document).off({mousedown:this.hide});this.isInput?""!==this.element.val()&&this.element.prop("value",this.format.call(this)).trigger("change"):(this.component&&""!==this.element.find("input").val()&&this.element.find("input").prop("value",this.format.call(this)).trigger("change"),this.element.data("color",this.format.call(this)));this.element.trigger({type:"hidePicker",color:this.color})},place:function(){var a=this.component?this.component.offset():this.element.offset();this.picker.css({top:a.top+ +this.height,left:a.left})},destroy:function(){d(".colorpicker[data-colorpicker-guid="+this.element.attr("data-colorpicker-guid")+"]").remove();this.element.removeData("colorpicker").removeAttr("data-colorpicker-guid").off(".colorpicker");!1!==this.component&&this.component.off(".colorpicker");this.element.trigger("destroy",[this])},setValue:function(a){this.isInput?this.element.prop("value",a):(this.element.find("input").val(a),this.element.data("color",a));this.update();this.element.trigger({type:"changeColor", +color:this.color})},previewColor:function(){try{this.preview.backgroundColor=this.format.call(this)}catch(a){this.preview.backgroundColor=this.color.toHex()}this.base.backgroundColor=this.color.toHex(this.color.value.h,1,1,1);this.alpha&&(this.alpha.backgroundColor=this.color.toHex())},pointer:null,slider:null,mousedown:function(a){a.stopPropagation();a.preventDefault();var b=d(a.target).closest("div");if(!b.is(".colorpicker")){if(b.is(".colorpicker-saturation"))this.slider=d.extend({},e.sliders.saturation); +else if(b.is(".colorpicker-hue"))this.slider=d.extend({},e.sliders.hue);else if(b.is(".colorpicker-alpha"))this.slider=d.extend({},e.sliders.alpha);else return!1;var c=b.offset();this.slider.knob=b.find("i")[0].style;this.slider.left=a.pageX-c.left;this.slider.top=a.pageY-c.top;this.pointer={left:a.pageX,top:a.pageY};d(document).on({"mousemove.colorpicker":d.proxy(this.mousemove,this),"mouseup.colorpicker":d.proxy(this.mouseup,this)}).trigger("mousemove")}return!1},mousemove:function(a){a.stopPropagation(); +a.preventDefault();var b=Math.max(0,Math.min(this.slider.maxLeft,this.slider.left+((a.pageX||this.pointer.left)-this.pointer.left)));a=Math.max(0,Math.min(this.slider.maxTop,this.slider.top+((a.pageY||this.pointer.top)-this.pointer.top)));this.slider.knob.left=b+"px";this.slider.knob.top=a+"px";this.slider.callLeft&&this.color[this.slider.callLeft].call(this.color,b/100);this.slider.callTop&&this.color[this.slider.callTop].call(this.color,a/100);this.previewColor();if(this.isInput)try{this.element.val(this.format.call(this)).trigger("change")}catch(c){this.element.val(this.color.toHex()).trigger("change")}else try{this.element.find("input").val(this.format.call(this)).trigger("change")}catch(d){this.element.find("input").val(this.color.toHex()).trigger("change")}this.element.trigger({type:"changeColor", +color:this.color});return!1},mouseup:function(a){a.stopPropagation();a.preventDefault();d(document).off({mousemove:this.mousemove,mouseup:this.mouseup});return!1}};d.fn.colorpicker=function(a,b){return this.each(function(){var c=d(this),e=c.data("colorpicker"),f="object"===typeof a&&a;if(!e)"destroy"!==a&&c.data("colorpicker",new h(this,d.extend({},d.fn.colorpicker.defaults,f)));else if("string"===typeof a)e[a](b)})};d.fn.colorpicker.defaults={};d.fn.colorpicker.Constructor=h;var e={translateFormats:{rgb:function(){var a= +this.color.toRGB();return"rgb("+a.r+","+a.g+","+a.b+")"},rgba:function(){var a=this.color.toRGB();return"rgba("+a.r+","+a.g+","+a.b+","+a.a+")"},hsl:function(){var a=this.color.toHSL();return"hsl("+Math.round(360*a.h)+","+Math.round(100*a.s)+"%,"+Math.round(100*a.l)+"%)"},hsla:function(){var a=this.color.toHSL();return"hsla("+Math.round(360*a.h)+","+Math.round(100*a.s)+"%,"+Math.round(100*a.l)+"%,"+a.a+")"},hex:function(){return this.color.toHex()}},sliders:{saturation:{maxLeft:100,maxTop:100,callLeft:"setSaturation", +callTop:"setLightness"},hue:{maxLeft:0,maxTop:100,callLeft:!1,callTop:"setHue"},alpha:{maxLeft:0,maxTop:100,callLeft:!1,callTop:"setAlpha"}},RGBtoHSB:function(a,b,c,d){a/=255;b/=255;c/=255;var f,e;f=Math.max(a,b,c);e=f-Math.min(a,b,c);a=60*(((0===e?0:f===a?(b-c)/e:f===b?(c-a)/e+2:(a-b)/e+4)+360)%6)/360;return{h:a||1,s:0===e?0:e/f,b:f,a:d||1}},HueToRGB:function(a,b,c){0>c?c+=1:1<c&&(c-=1);return 1>6*c?a+6*(b-a)*c:1>2*c?b:2>3*c?a+6*(b-a)*(2/3-c):a},HSLtoRGB:function(a,b,c,d){0>b&&(b=0);b=0.5>=c?c*(1+ +b):c+b-c*b;var f=2*c-b,g=a-1/3;c=Math.round(255*e.HueToRGB(f,b,a+1/3));a=Math.round(255*e.HueToRGB(f,b,a));b=Math.round(255*e.HueToRGB(f,b,g));return[c,a,b,d||1]},stringParsers:[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(a){return[a[1],a[2],a[3],a[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(a){return[2.55*a[1],2.55*a[2],2.55*a[3],a[4]]}},{re:/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/, +parse:function(a){return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],16)]}},{re:/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,parse:function(a){return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(a){return[a[1]/360,a[2]/100,a[3]/100,a[4]]}}],template:'<div class="colorpicker dropdown-menu"><div class="colorpicker-saturation"><i><b></b></i></div><div class="colorpicker-hue"><i></i></div><div class="colorpicker-alpha"><i></i></div><div class="colorpicker-color"><div /></div></div>'}})(window.jQuery); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/css/datetimepicker.css b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/css/datetimepicker.css new file mode 100755 index 0000000..10285e0 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/css/datetimepicker.css @@ -0,0 +1,313 @@ +/*! + * Datetimepicker for Bootstrap + * + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +.datetimepicker { + padding: 4px; + margin-top: 1px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + direction: ltr; + /*.dow { + border-top: 1px solid #ddd !important; + }*/ + +} +.datetimepicker-inline { + width: 220px; +} +.datetimepicker.datetimepicker-rtl { + direction: rtl; +} +.datetimepicker.datetimepicker-rtl table tr td span { + float: right; +} +.datetimepicker-dropdown { + top: 0; + left: 0; +} +.datetimepicker-dropdown:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; + top: -7px; + left: 6px; +} +.datetimepicker-dropdown:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + position: absolute; + top: -6px; + left: 7px; +} +.datetimepicker > div { + display: none; +} +.datetimepicker.minutes div.datetimepicker-minutes { + display: block; +} +.datetimepicker.hours div.datetimepicker-hours { + display: block; +} +.datetimepicker.days div.datetimepicker-days { + display: block; +} +.datetimepicker.months div.datetimepicker-months { + display: block; +} +.datetimepicker.years div.datetimepicker-years { + display: block; +} +.datetimepicker table { + margin: 0; +} +.datetimepicker td, +.datetimepicker th { + text-align: center; + width: 20px; + height: 20px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + border: none; +} +.table-striped .datetimepicker table tr td, +.table-striped .datetimepicker table tr th { + background-color: transparent; +} +.datetimepicker table tr td.minute:hover { + background: #eeeeee; + cursor: pointer; +} +.datetimepicker table tr td.hour:hover { + background: #eeeeee; + cursor: pointer; +} +.datetimepicker table tr td.day:hover { + background: #eeeeee; + cursor: pointer; +} +.datetimepicker table tr td.old, +.datetimepicker table tr td.new { + color: #999999; +} +.datetimepicker table tr td.disabled, +.datetimepicker table tr td.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datetimepicker table tr td.today, +.datetimepicker table tr td.today:hover, +.datetimepicker table tr td.today.disabled, +.datetimepicker table tr td.today.disabled:hover { + background-color: #fde19a; + background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a)); + background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -o-linear-gradient(top, #fdd49a, #fdf59a); + background-image: linear-gradient(top, #fdd49a, #fdf59a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0); + border-color: #fdf59a #fdf59a #fbed50; + 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(enabled=false); +} +.datetimepicker table tr td.today:hover, +.datetimepicker table tr td.today:hover:hover, +.datetimepicker table tr td.today.disabled:hover, +.datetimepicker table tr td.today.disabled:hover:hover, +.datetimepicker table tr td.today:active, +.datetimepicker table tr td.today:hover:active, +.datetimepicker table tr td.today.disabled:active, +.datetimepicker table tr td.today.disabled:hover:active, +.datetimepicker table tr td.today.active, +.datetimepicker table tr td.today:hover.active, +.datetimepicker table tr td.today.disabled.active, +.datetimepicker table tr td.today.disabled:hover.active, +.datetimepicker table tr td.today.disabled, +.datetimepicker table tr td.today:hover.disabled, +.datetimepicker table tr td.today.disabled.disabled, +.datetimepicker table tr td.today.disabled:hover.disabled, +.datetimepicker table tr td.today[disabled], +.datetimepicker table tr td.today:hover[disabled], +.datetimepicker table tr td.today.disabled[disabled], +.datetimepicker table tr td.today.disabled:hover[disabled] { + background-color: #fdf59a; +} +.datetimepicker table tr td.today:active, +.datetimepicker table tr td.today:hover:active, +.datetimepicker table tr td.today.disabled:active, +.datetimepicker table tr td.today.disabled:hover:active, +.datetimepicker table tr td.today.active, +.datetimepicker table tr td.today:hover.active, +.datetimepicker table tr td.today.disabled.active, +.datetimepicker table tr td.today.disabled:hover.active { + background-color: #fbf069 \9; +} +.datetimepicker table tr td.active, +.datetimepicker table tr td.active:hover, +.datetimepicker table tr td.active.disabled, +.datetimepicker table tr td.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-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(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + 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(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datetimepicker table tr td.active:hover, +.datetimepicker table tr td.active:hover:hover, +.datetimepicker table tr td.active.disabled:hover, +.datetimepicker table tr td.active.disabled:hover:hover, +.datetimepicker table tr td.active:active, +.datetimepicker table tr td.active:hover:active, +.datetimepicker table tr td.active.disabled:active, +.datetimepicker table tr td.active.disabled:hover:active, +.datetimepicker table tr td.active.active, +.datetimepicker table tr td.active:hover.active, +.datetimepicker table tr td.active.disabled.active, +.datetimepicker table tr td.active.disabled:hover.active, +.datetimepicker table tr td.active.disabled, +.datetimepicker table tr td.active:hover.disabled, +.datetimepicker table tr td.active.disabled.disabled, +.datetimepicker table tr td.active.disabled:hover.disabled, +.datetimepicker table tr td.active[disabled], +.datetimepicker table tr td.active:hover[disabled], +.datetimepicker table tr td.active.disabled[disabled], +.datetimepicker table tr td.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datetimepicker table tr td.active:active, +.datetimepicker table tr td.active:hover:active, +.datetimepicker table tr td.active.disabled:active, +.datetimepicker table tr td.active.disabled:hover:active, +.datetimepicker table tr td.active.active, +.datetimepicker table tr td.active:hover.active, +.datetimepicker table tr td.active.disabled.active, +.datetimepicker table tr td.active.disabled:hover.active { + background-color: #003399 \9; +} +.datetimepicker table tr td span { + display: block; + width: 23%; + height: 54px; + line-height: 54px; + float: left; + margin: 1%; + cursor: pointer; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.datetimepicker .datetimepicker-hours span { + height: 26px; + line-height: 26px; +} +.datetimepicker .datetimepicker-minutes span { + height: 26px; + line-height: 26px; +} + +.datetimepicker table tr td span:hover { + background: #eeeeee; +} +.datetimepicker table tr td span.disabled, +.datetimepicker table tr td span.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datetimepicker table tr td span.active, +.datetimepicker table tr td span.active:hover, +.datetimepicker table tr td span.active.disabled, +.datetimepicker table tr td span.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-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(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + 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(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datetimepicker table tr td span.active:hover, +.datetimepicker table tr td span.active:hover:hover, +.datetimepicker table tr td span.active.disabled:hover, +.datetimepicker table tr td span.active.disabled:hover:hover, +.datetimepicker table tr td span.active:active, +.datetimepicker table tr td span.active:hover:active, +.datetimepicker table tr td span.active.disabled:active, +.datetimepicker table tr td span.active.disabled:hover:active, +.datetimepicker table tr td span.active.active, +.datetimepicker table tr td span.active:hover.active, +.datetimepicker table tr td span.active.disabled.active, +.datetimepicker table tr td span.active.disabled:hover.active, +.datetimepicker table tr td span.active.disabled, +.datetimepicker table tr td span.active:hover.disabled, +.datetimepicker table tr td span.active.disabled.disabled, +.datetimepicker table tr td span.active.disabled:hover.disabled, +.datetimepicker table tr td span.active[disabled], +.datetimepicker table tr td span.active:hover[disabled], +.datetimepicker table tr td span.active.disabled[disabled], +.datetimepicker table tr td span.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datetimepicker table tr td span.active:active, +.datetimepicker table tr td span.active:hover:active, +.datetimepicker table tr td span.active.disabled:active, +.datetimepicker table tr td span.active.disabled:hover:active, +.datetimepicker table tr td span.active.active, +.datetimepicker table tr td span.active:hover.active, +.datetimepicker table tr td span.active.disabled.active, +.datetimepicker table tr td span.active.disabled:hover.active { + background-color: #003399 \9; +} +.datetimepicker table tr td span.old { + color: #999999; +} +.datetimepicker th.switch { + width: 145px; +} +.datetimepicker thead tr:first-child th, +.datetimepicker tfoot tr:first-child th { + cursor: pointer; +} +.datetimepicker thead tr:first-child th:hover, +.datetimepicker tfoot tr:first-child th:hover { + background: #eeeeee; +} +.input-append.date .add-on i, +.input-prepend.date .add-on i { + cursor: pointer; + width: 14px; + height: 14px; +} diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/bootstrap-datetimepicker.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/bootstrap-datetimepicker.js new file mode 100755 index 0000000..5664794 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/bootstrap-datetimepicker.js @@ -0,0 +1,1146 @@ +/* ========================================================= + * bootstrap-datetimepicker.js + * ========================================================= + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * Improvements by Sébastien Malot + * + * 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( $ ) { + + function UTCDate(){ + return new Date(Date.UTC.apply(Date, arguments)); + } + function UTCToday(){ + var today = new Date(); + return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate(), today.getUTCHours(), today.getUTCMinutes(), today.getUTCSeconds()); + } + + // Picker object + + var Datetimepicker = function(element, options) { + var that = this; + + this.element = $(element); + this.language = options.language || this.element.data('date-language') || "en"; + this.language = this.language in dates ? this.language : "en"; + this.isRTL = dates[this.language].rtl || false; + this.format = DPGlobal.parseFormat(options.format || this.element.data('date-format') || 'yyyy-mm-dd hh:ii'); + this.isInline = false; + this.isInput = this.element.is('input'); + this.component = this.element.is('.date') ? this.element.find('.add-on .icon-th').parent() : false; + this.componentReset = this.element.is('.date') ? this.element.find('.add-on .icon-remove').parent() : false; + this.hasInput = this.component && this.element.find('input').length; + if (this.component && this.component.length === 0) { + this.component = false; + } + this.linkField = options.linkField || this.element.data('link-field') || false; + this.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || 'yyyy-mm-dd hh:ii:ss'); + this.minuteStep = options.minuteStep || this.element.data('minute-step') || 5; + this.pickerReferer = options.pickerReferer || this.element.data('picker-referer') || 'default'; + + this._attachEvents(); + + this.minView = 0; + if ('minView' in options) { + this.minView = options.minView; + } else if ('minView' in this.element.data()) { + this.minView = this.element.data('min-view'); + } + this.minView = DPGlobal.convertViewMode(this.minView); + + this.maxView = DPGlobal.modes.length-1; + if ('maxView' in options) { + this.maxView = options.maxView; + } else if ('maxView' in this.element.data()) { + this.maxView = this.element.data('max-view'); + } + this.maxView = DPGlobal.convertViewMode(this.maxView); + + this.startViewMode = 2; + if ('startView' in options) { + this.startViewMode = options.startView; + } else if ('startView' in this.element.data()) { + this.startViewMode = this.element.data('start-view'); + } + this.startViewMode = DPGlobal.convertViewMode(this.startViewMode); + this.viewMode = this.startViewMode; + + this.forceParse = true; + if ('forceParse' in options) { + this.forceParse = options.forceParse; + } else if ('dateForceParse' in this.element.data()) { + this.forceParse = this.element.data('date-force-parse'); + } + + this.picker = $(DPGlobal.template) + .appendTo(this.isInline ? this.element : 'body') + .on({ + click: $.proxy(this.click, this), + mousedown: $.proxy(this.mousedown, this) + }); + + if (this.isInline) { + this.picker.addClass('datetimepicker-inline'); + } else { + this.picker.addClass('datetimepicker-dropdown dropdown-menu'); + } + if (this.isRTL){ + this.picker.addClass('datetimepicker-rtl'); + this.picker.find('.prev i, .next i') + .toggleClass('icon-arrow-left icon-arrow-right'); + } + $(document).on('mousedown', function (e) { + // Clicked outside the datetimepicker, hide it + if ($(e.target).closest('.datetimepicker').length === 0) { + that.hide(); + } + }); + + this.autoclose = false; + if ('autoclose' in options) { + this.autoclose = options.autoclose; + } else if ('dateAutoclose' in this.element.data()) { + this.autoclose = this.element.data('date-autoclose'); + } + + this.keyboardNavigation = true; + if ('keyboardNavigation' in options) { + this.keyboardNavigation = options.keyboardNavigation; + } else if ('dateKeyboardNavigation' in this.element.data()) { + this.keyboardNavigation = this.element.data('date-keyboard-navigation'); + } + + this.todayBtn = (options.todayBtn || this.element.data('date-today-btn') || false); + this.todayHighlight = (options.todayHighlight || this.element.data('date-today-highlight') || false); + + this.weekStart = ((options.weekStart || this.element.data('date-weekstart') || dates[this.language].weekStart || 0) % 7); + this.weekEnd = ((this.weekStart + 6) % 7); + this.startDate = -Infinity; + this.endDate = Infinity; + this.daysOfWeekDisabled = []; + this.setStartDate(options.startDate || this.element.data('date-startdate')); + this.setEndDate(options.endDate || this.element.data('date-enddate')); + this.setDaysOfWeekDisabled(options.daysOfWeekDisabled || this.element.data('date-days-of-week-disabled')); + this.fillDow(); + this.fillMonths(); + this.update(); + this.showMode(); + + if(this.isInline) { + this.show(); + } + }; + + Datetimepicker.prototype = { + constructor: Datetimepicker, + + _events: [], + _attachEvents: function(){ + this._detachEvents(); + if (this.isInput) { // single input + this._events = [ + [this.element, { + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }] + ]; + } + else if (this.component && this.hasInput){ // component: input + button + this._events = [ + // For components that are not readonly, allow keyboard nav + [this.element.find('input'), { + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }], + [this.component, { + click: $.proxy(this.show, this) + }] + ]; + if (this.componentReset) { + this._events.push([ + this.componentReset, + {click: $.proxy(this.reset, this)} + ]); + } + } + else if (this.element.is('div')) { // inline datetimepicker + this.isInline = true; + } + else { + this._events = [ + [this.element, { + click: $.proxy(this.show, this) + }] + ]; + } + for (var i=0, el, ev; i<this._events.length; i++){ + el = this._events[i][0]; + ev = this._events[i][1]; + el.on(ev); + } + }, + + _detachEvents: function(){ + for (var i=0, el, ev; i<this._events.length; i++){ + el = this._events[i][0]; + ev = this._events[i][1]; + el.off(ev); + } + this._events = []; + }, + + show: function(e) { + this.picker.show(); + this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); + if (this.forceParse) { + this.update(); + } + this.place(); + $(window).on('resize', $.proxy(this.place, this)); + if (e) { + e.stopPropagation(); + e.preventDefault(); + } + this.element.trigger({ + type: 'show', + date: this.date + }); + }, + + hide: function(e){ + if(this.isInline) return; + this.picker.hide(); + $(window).off('resize', this.place); + this.viewMode = this.startViewMode; + this.showMode(); + if (!this.isInput) { + $(document).off('mousedown', this.hide); + } + + if ( + this.forceParse && + ( + this.isInput && this.element.val() || + this.hasInput && this.element.find('input').val() + ) + ) + this.setValue(); + this.element.trigger({ + type: 'hide', + date: this.date + }); + }, + + remove: function() { + this._detachEvents(); + this.picker.remove(); + delete this.element.data().datetimepicker; + }, + + getDate: function() { + var d = this.getUTCDate(); + return new Date(d.getTime() + (d.getTimezoneOffset()*60000)); + }, + + getUTCDate: function() { + return this.date; + }, + + setDate: function(d) { + this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000))); + }, + + setUTCDate: function(d) { + this.date = d; + this.setValue(); + }, + + setValue: function() { + var formatted = this.getFormattedDate(); + if (!this.isInput) { + if (this.component){ + this.element.find('input').prop('value', formatted); + } + this.element.data('date', formatted); + } else { + this.element.prop('value', formatted); + } + if (this.linkField) { + $('#' + this.linkField).val(this.getFormattedDate(this.linkFormat)); + } + }, + + getFormattedDate: function(format) { + if(format == undefined) format = this.format; + return DPGlobal.formatDate(this.date, format, this.language); + }, + + setStartDate: function(startDate){ + this.startDate = startDate || -Infinity; + if (this.startDate !== -Infinity) { + this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language); + } + this.update(); + this.updateNavArrows(); + }, + + setEndDate: function(endDate){ + this.endDate = endDate || Infinity; + if (this.endDate !== Infinity) { + this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language); + } + this.update(); + this.updateNavArrows(); + }, + + setDaysOfWeekDisabled: function(daysOfWeekDisabled){ + this.daysOfWeekDisabled = daysOfWeekDisabled || []; + if (!$.isArray(this.daysOfWeekDisabled)) { + this.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\s*/); + } + this.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled, function (d) { + return parseInt(d, 10); + }); + this.update(); + this.updateNavArrows(); + }, + + place: function(){ + if(this.isInline) return; + var zIndex = parseInt(this.element.parents().filter(function() { + return $(this).css('z-index') != 'auto'; + }).first().css('z-index'))+10; + var offset = this.element.offset(); + if (this.component && this.pickerReferer == 'default') { + offset = this.component.offset(); + } + this.picker.css({ + top: offset.top + this.height, + left: offset.left, + zIndex: zIndex + }); + }, + + update: function(){ + var date, fromArgs = false; + if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) { + date = arguments[0]; + fromArgs = true; + } else { + date = this.isInput ? this.element.prop('value') : this.element.data('date') || this.element.find('input').prop('value'); + } + + this.date = DPGlobal.parseDate(date, this.format, this.language); + + if(fromArgs) this.setValue(); + + if (this.date < this.startDate) { + this.viewDate = new Date(this.startDate); + } else if (this.date > this.endDate) { + this.viewDate = new Date(this.endDate); + } else { + this.viewDate = new Date(this.date); + } + this.fill(); + }, + + fillDow: function(){ + var dowCnt = this.weekStart, + html = '<tr>'; + while (dowCnt < this.weekStart + 7) { + html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>'; + } + html += '</tr>'; + this.picker.find('.datetimepicker-days thead').append(html); + }, + + fillMonths: function(){ + var html = '', + i = 0; + while (i < 12) { + html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>'; + } + this.picker.find('.datetimepicker-months td').html(html); + }, + + fill: function() { + if (this.date == null || this.viewDate == null) { + return; + } + var d = new Date(this.viewDate), + year = d.getUTCFullYear(), + month = d.getUTCMonth(), + dayMonth = d.getUTCDate(), + hours = d.getUTCHours(), + minutes = d.getUTCMinutes(), + startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity, + startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity, + endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity, + endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity, + currentDate = (new UTCDate(this.date.getUTCFullYear(), this.date.getUTCMonth(), this.date.getUTCDate())).valueOf(), + today = new Date(); + this.picker.find('.datetimepicker-days thead th:eq(1)') + .text(dates[this.language].months[month]+' '+year); + this.picker.find('.datetimepicker-hours thead th:eq(1)') + .text(dayMonth+' '+dates[this.language].months[month]+' '+year); + this.picker.find('.datetimepicker-minutes thead th:eq(1)') + .text(dayMonth+' '+dates[this.language].months[month]+' '+year); + this.picker.find('tfoot th.today') + .text(dates[this.language].today) + .toggle(this.todayBtn !== false); + this.updateNavArrows(); + this.fillMonths(); + var prevMonth = UTCDate(year, month-1, 28,0,0,0,0), + day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); + prevMonth.setUTCDate(day); + prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7); + var nextMonth = new Date(prevMonth); + nextMonth.setUTCDate(nextMonth.getUTCDate() + 42); + nextMonth = nextMonth.valueOf(); + var html = []; + var clsName; + while(prevMonth.valueOf() < nextMonth) { + if (prevMonth.getUTCDay() == this.weekStart) { + html.push('<tr>'); + } + clsName = ''; + if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) { + clsName += ' old'; + } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) { + clsName += ' new'; + } + // Compare internal UTC date with local today, not UTC today + if (this.todayHighlight && + prevMonth.getUTCFullYear() == today.getFullYear() && + prevMonth.getUTCMonth() == today.getMonth() && + prevMonth.getUTCDate() == today.getDate()) { + clsName += ' today'; + } + if (prevMonth.valueOf() == currentDate) { + clsName += ' active'; + } + if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate || + $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1) { + clsName += ' disabled'; + } + html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>'); + if (prevMonth.getUTCDay() == this.weekEnd) { + html.push('</tr>'); + } + prevMonth.setUTCDate(prevMonth.getUTCDate()+1); + } + this.picker.find('.datetimepicker-days tbody').empty().append(html.join('')); + + html = []; + for (var i=0;i<24;i++) { + clsName = ''; + if (hours == i) { + clsName += ' active'; + } + html.push('<span class="hour'+clsName+'">'+i+':00</span>'); + } + this.picker.find('.datetimepicker-hours td').html(html.join('')); + + html = []; + for(var i=0;i<60;i+=this.minuteStep) { + clsName = ''; + if (Math.floor(minutes/5) == Math.floor(i/5)) { + clsName += ' active'; + } + html.push('<span class="minute'+clsName+'">'+hours+':'+(i<10?'0'+i:i)+'</span>'); + } + this.picker.find('.datetimepicker-minutes td').html(html.join('')); + + var currentYear = this.date.getUTCFullYear(); + var months = this.picker.find('.datetimepicker-months') + .find('th:eq(1)') + .text(year) + .end() + .find('span').removeClass('active'); + if (currentYear == year) { + months.eq(this.date.getUTCMonth()).addClass('active'); + } + if (year < startYear || year > endYear) { + months.addClass('disabled'); + } + if (year == startYear) { + months.slice(0, startMonth).addClass('disabled'); + } + if (year == endYear) { + months.slice(endMonth+1).addClass('disabled'); + } + + html = ''; + year = parseInt(year/10, 10) * 10; + var yearCont = this.picker.find('.datetimepicker-years') + .find('th:eq(1)') + .text(year + '-' + (year + 9)) + .end() + .find('td'); + year -= 1; + for (var i = -1; i < 11; i++) { + html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>'; + year += 1; + } + yearCont.html(html); + }, + + updateNavArrows: function() { + var d = new Date(this.viewDate), + year = d.getUTCFullYear(), + month = d.getUTCMonth(); + switch (this.viewMode) { + case 2: + if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + case 3: + case 4: + if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + } + }, + + click: function(e) { + e.stopPropagation(); + e.preventDefault(); + var target = $(e.target).closest('span, td, th'); + if (target.length == 1) { + switch(target[0].nodeName.toLowerCase()) { + case 'th': + switch(target[0].className) { + case 'switch': + this.showMode(1); + break; + case 'prev': + case 'next': + var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1); + switch(this.viewMode){ + case 0: + this.viewDate = this.moveHour(this.viewDate, dir); + break; + case 1: + this.viewDate = this.moveDate(this.viewDate, dir); + break; + case 2: + this.viewDate = this.moveMonth(this.viewDate, dir); + break; + case 3: + case 4: + this.viewDate = this.moveYear(this.viewDate, dir); + break; + } + this.fill(); + break; + case 'today': + var date = new Date(); + date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()); + + this.viewMode = this.startViewMode; + this.showMode(0); + var which = this.todayBtn == 'linked' ? null : 'view'; + this._setDate(date, which); + break; + } + break; + case 'span': + if (!target.is('.disabled')) { + if (target.is('.month')) { + this.viewDate.setUTCDate(1); + var month = target.parent().find('span').index(target); + this.viewDate.setUTCMonth(month); + this.element.trigger({ + type: 'changeMonth', + date: this.viewDate + }); + } else if (target.is('.year')) { + this.viewDate.setUTCDate(1); + var year = parseInt(target.text(), 10) || 0; + this.viewDate.setUTCFullYear(year); + this.element.trigger({ + type: 'changeYear', + date: this.viewDate + }); + } else if (target.is('.hour')){ + var hours = parseInt(target.text(), 10) || 0; + var year = this.viewDate.getUTCFullYear(), + month = this.viewDate.getUTCMonth(), + day = this.viewDate.getUTCDate(), + minutes = this.viewDate.getUTCMinutes(), + seconds = this.viewDate.getUTCSeconds(); + this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); + } else if (target.is('.minute')){ + var minutes = parseInt(target.text().substr(target.text().indexOf(':')+1), 10) || 0; + var year = this.viewDate.getUTCFullYear(), + month = this.viewDate.getUTCMonth(), + day = this.viewDate.getUTCDate(), + hours = this.viewDate.getUTCHours(), + seconds = this.viewDate.getUTCSeconds(); + this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); + } + if (this.viewMode != 0) { + var oldViewMode = this.viewMode; + this.showMode(-1); + this.fill(); + if (oldViewMode == this.viewMode && this.autoclose) { + this.hide(); + } + } else { + this.fill(); + if (this.autoclose) { + this.hide(); + } + } + } + break; + case 'td': + if (target.is('.day') && !target.is('.disabled')){ + var day = parseInt(target.text(), 10) || 1; + var year = this.viewDate.getUTCFullYear(), + month = this.viewDate.getUTCMonth(), + hours = this.viewDate.getUTCHours(), + minutes = this.viewDate.getUTCMinutes(), + seconds = this.viewDate.getUTCSeconds(); + if (target.is('.old')) { + if (month === 0) { + month = 11; + year -= 1; + } else { + month -= 1; + } + } else if (target.is('.new')) { + if (month == 11) { + month = 0; + year += 1; + } else { + month += 1; + } + } + this._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0)); + } + var oldViewMode = this.viewMode; + this.showMode(-1); + this.fill(); + if (oldViewMode == this.viewMode && this.autoclose) { + this.hide(); + } + break; + } + } + }, + + _setDate: function(date, which){ + if (!which || which == 'date') + this.date = date; + if (!which || which == 'view') + this.viewDate = date; + this.fill(); + this.element.trigger({ + type: 'changeDate', + date: this.date + }); + this.setValue(); + var element; + if (this.isInput) { + element = this.element; + } else if (this.component){ + element = this.element.find('input'); + } + if (element) { + element.change(); + if (this.autoclose && (!which || which == 'date')) { + //this.hide(); + } + } + }, + + moveHour: function(date, dir){ + if (!dir) return date; + var new_date = new Date(date.valueOf()); + dir = dir > 0 ? 1 : -1; + new_date.setUTCHours(new_date.getUTCHours() + dir); + return new_date; + }, + + moveDate: function(date, dir){ + if (!dir) return date; + var new_date = new Date(date.valueOf()); + dir = dir > 0 ? 1 : -1; + new_date.setUTCDate(new_date.getUTCDate() + dir); + return new_date; + }, + + moveMonth: function(date, dir){ + if (!dir) return date; + var new_date = new Date(date.valueOf()), + day = new_date.getUTCDate(), + month = new_date.getUTCMonth(), + mag = Math.abs(dir), + new_month, test; + dir = dir > 0 ? 1 : -1; + if (mag == 1){ + test = dir == -1 + // If going back one month, make sure month is not current month + // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02) + ? function(){ return new_date.getUTCMonth() == month; } + // If going forward one month, make sure month is as expected + // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02) + : function(){ return new_date.getUTCMonth() != new_month; }; + new_month = month + dir; + new_date.setUTCMonth(new_month); + // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11 + if (new_month < 0 || new_month > 11) + new_month = (new_month + 12) % 12; + } else { + // For magnitudes >1, move one month at a time... + for (var i=0; i<mag; i++) + // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)... + new_date = this.moveMonth(new_date, dir); + // ...then reset the day, keeping it in the new month + new_month = new_date.getUTCMonth(); + new_date.setUTCDate(day); + test = function(){ return new_month != new_date.getUTCMonth(); }; + } + // Common date-resetting loop -- if date is beyond end of month, make it + // end of month + while (test()){ + new_date.setUTCDate(--day); + new_date.setUTCMonth(new_month); + } + return new_date; + }, + + moveYear: function(date, dir){ + return this.moveMonth(date, dir*12); + }, + + dateWithinRange: function(date){ + return date >= this.startDate && date <= this.endDate; + }, + + keydown: function(e){ + if (this.picker.is(':not(:visible)')){ + if (e.keyCode == 27) // allow escape to hide and re-show picker + this.show(); + return; + } + var dateChanged = false, + dir, day, month, + newDate, newViewDate; + switch(e.keyCode){ + case 27: // escape + this.hide(); + e.preventDefault(); + break; + case 37: // left + case 39: // right + if (!this.keyboardNavigation) break; + dir = e.keyCode == 37 ? -1 : 1; + if (e.ctrlKey){ + newDate = this.moveYear(this.date, dir); + newViewDate = this.moveYear(this.viewDate, dir); + } else if (e.shiftKey){ + newDate = this.moveMonth(this.date, dir); + newViewDate = this.moveMonth(this.viewDate, dir); + } else { + newDate = new Date(this.date); + newDate.setUTCDate(this.date.getUTCDate() + dir); + newViewDate = new Date(this.viewDate); + newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir); + } + if (this.dateWithinRange(newDate)){ + this.date = newDate; + this.viewDate = newViewDate; + this.setValue(); + this.update(); + e.preventDefault(); + dateChanged = true; + } + break; + case 38: // up + case 40: // down + if (!this.keyboardNavigation) break; + dir = e.keyCode == 38 ? -1 : 1; + if (e.ctrlKey){ + newDate = this.moveYear(this.date, dir); + newViewDate = this.moveYear(this.viewDate, dir); + } else if (e.shiftKey){ + newDate = this.moveMonth(this.date, dir); + newViewDate = this.moveMonth(this.viewDate, dir); + } else { + newDate = new Date(this.date); + newDate.setUTCDate(this.date.getUTCDate() + dir * 7); + newViewDate = new Date(this.viewDate); + newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7); + } + if (this.dateWithinRange(newDate)){ + this.date = newDate; + this.viewDate = newViewDate; + this.setValue(); + this.update(); + e.preventDefault(); + dateChanged = true; + } + break; + case 13: // enter + this.hide(); + e.preventDefault(); + break; + case 9: // tab + this.hide(); + break; + } + if (dateChanged){ + this.element.trigger({ + type: 'changeDate', + date: this.date + }); + var element; + if (this.isInput) { + element = this.element; + } else if (this.component){ + element = this.element.find('input'); + } + if (element) { + element.change(); + } + } + }, + + showMode: function(dir) { + if (dir) { + var newViewMode = Math.max(0, Math.min(DPGlobal.modes.length - 1, this.viewMode + dir)); + if (newViewMode >= this.minView && newViewMode <= this.maxView) { + this.viewMode = newViewMode; + } + } + /* + vitalets: fixing bug of very special conditions: + jquery 1.7.1 + webkit + show inline datetimepicker in bootstrap popover. + Method show() does not set display css correctly and datetimepicker is not shown. + Changed to .css('display', 'block') solve the problem. + See https://github.com/vitalets/x-editable/issues/37 + + In jquery 1.7.2+ everything works fine. + */ + //this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); + this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block'); + this.updateNavArrows(); + }, + + reset: function(e) { + this._setDate(null, 'date'); + } + }; + + $.fn.datetimepicker = function ( option ) { + var args = Array.apply(null, arguments); + args.shift(); + return this.each(function () { + var $this = $(this), + data = $this.data('datetimepicker'), + options = typeof option == 'object' && option; + if (!data) { + $this.data('datetimepicker', (data = new Datetimepicker(this, $.extend({}, $.fn.datetimepicker.defaults,options)))); + } + if (typeof option == 'string' && typeof data[option] == 'function') { + data[option].apply(data, args); + } + }); + }; + + $.fn.datetimepicker.defaults = { + }; + $.fn.datetimepicker.Constructor = Datetimepicker; + var dates = $.fn.datetimepicker.dates = { + en: { + days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], + daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], + months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], + today: "Today" + } + }; + + var DPGlobal = { + modes: [ + { + clsName: 'minutes', + navFnc: 'Hours', + navStep: 1 + }, + { + clsName: 'hours', + navFnc: 'Date', + navStep: 1 + }, + { + clsName: 'days', + navFnc: 'Month', + navStep: 1 + }, + { + clsName: 'months', + navFnc: 'FullYear', + navStep: 1 + }, + { + clsName: 'years', + navFnc: 'FullYear', + navStep: 10 + }], + isLeapYear: function (year) { + return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)) + }, + getDaysInMonth: function (year, month) { + return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month] + }, + validParts: /hh?|ii?|ss?|dd?|mm?|MM?|yy(?:yy)?/g, + nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\rTZ]+/g, + parseFormat: function(format){ + // IE treats \0 as a string end in inputs (truncating the value), + // so it's a bad format delimiter, anyway + var separators = format.replace(this.validParts, '\0').split('\0'), + parts = format.match(this.validParts); + if (!separators || !separators.length || !parts || parts.length == 0){ + throw new Error("Invalid date format."); + } + return {separators: separators, parts: parts}; + }, + parseDate: function(date, format, language) { + if (date instanceof Date) return date; + if (/^\d{4}\-\d{2}\-\d{2}$/.test(date)) { + format = this.parseFormat('yyyy-mm-dd'); + } + if (/^\d{4}\-\d{2}\-\d{2}[T ]\d{2}\:\d{2}$/.test(date)) { + format = this.parseFormat('yyyy-mm-dd hh:ii'); + } + if (/^\d{4}\-\d{2}\-\d{2}[T ]\d{2}\:\d{2}\:\d{2}[Z]{0,1}$/.test(date)) { + format = this.parseFormat('yyyy-mm-dd hh:ii:ss'); + } + if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) { + var part_re = /([-+]\d+)([dmwy])/, + parts = date.match(/([-+]\d+)([dmwy])/g), + part, dir; + date = new Date(); + for (var i=0; i<parts.length; i++) { + part = part_re.exec(parts[i]); + dir = parseInt(part[1]); + switch(part[2]){ + case 'd': + date.setUTCDate(date.getUTCDate() + dir); + break; + case 'm': + date = Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype, date, dir); + break; + case 'w': + date.setUTCDate(date.getUTCDate() + dir * 7); + break; + case 'y': + date = Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype, date, dir); + break; + } + } + return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()); + } + var parts = date && date.match(this.nonpunctuation) || [], + date = new Date(), + parsed = {}, + setters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'], + setters_map = { + hh: function(d,v){ return d.setUTCHours(v); }, + h: function(d,v){ return d.setUTCHours(v); }, + ii: function(d,v){ return d.setUTCMinutes(v); }, + i: function(d,v){ return d.setUTCMinutes(v); }, + ss: function(d,v){ return d.setUTCSeconds(v); }, + s: function(d,v){ return d.setUTCSeconds(v); }, + yyyy: function(d,v){ return d.setUTCFullYear(v); }, + yy: function(d,v){ return d.setUTCFullYear(2000+v); }, + m: function(d,v){ + v -= 1; + while (v<0) v += 12; + v %= 12; + d.setUTCMonth(v); + while (d.getUTCMonth() != v) + d.setUTCDate(d.getUTCDate()-1); + return d; + }, + d: function(d,v){ return d.setUTCDate(v); } + }, + val, filtered, part; + setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m']; + setters_map['dd'] = setters_map['d']; + date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0);//date.getHours(), date.getMinutes(), date.getSeconds()); + if (parts.length == format.parts.length) { + for (var i=0, cnt = format.parts.length; i < cnt; i++) { + val = parseInt(parts[i], 10); + part = format.parts[i]; + if (isNaN(val)) { + switch(part) { + case 'MM': + filtered = $(dates[language].months).filter(function(){ + var m = this.slice(0, parts[i].length), + p = parts[i].slice(0, m.length); + return m == p; + }); + val = $.inArray(filtered[0], dates[language].months) + 1; + break; + case 'M': + filtered = $(dates[language].monthsShort).filter(function(){ + var m = this.slice(0, parts[i].length), + p = parts[i].slice(0, m.length); + return m == p; + }); + val = $.inArray(filtered[0], dates[language].monthsShort) + 1; + break; + } + } + parsed[part] = val; + } + for (var i=0, s; i<setters_order.length; i++){ + s = setters_order[i]; + if (s in parsed && !isNaN(parsed[s])) + setters_map[s](date, parsed[s]) + } + } + return date; + }, + formatDate: function(date, format, language){ + if (date == null) { + return ''; + } + var val = { + h: date.getUTCHours(), + i: date.getUTCMinutes(), + s: date.getUTCSeconds(), + d: date.getUTCDate(), + m: date.getUTCMonth() + 1, + M: dates[language].monthsShort[date.getUTCMonth()], + MM: dates[language].months[date.getUTCMonth()], + yy: date.getUTCFullYear().toString().substring(2), + yyyy: date.getUTCFullYear() + }; + val.hh = (val.h < 10 ? '0' : '') + val.h; + val.ii = (val.i < 10 ? '0' : '') + val.i; + val.ss = (val.s < 10 ? '0' : '') + val.s; + val.dd = (val.d < 10 ? '0' : '') + val.d; + val.mm = (val.m < 10 ? '0' : '') + val.m; + var date = [], + seps = $.extend([], format.separators); + for (var i=0, cnt = format.parts.length; i < cnt; i++) { + if (seps.length) + date.push(seps.shift()) + date.push(val[format.parts[i]]); + } + return date.join(''); + }, + convertViewMode: function(viewMode){ + switch (viewMode) { + case 4: + case 'decade': + viewMode = 4; + break; + case 3: + case 'year': + viewMode = 3; + break; + case 2: + case 'month': + viewMode = 2; + break; + case 1: + case 'day': + viewMode = 1; + break; + case 0: + case 'hour': + viewMode = 0; + break; + } + + return viewMode; + }, + headTemplate: '<thead>'+ + '<tr>'+ + '<th class="prev"><i class="icon-arrow-left"/></th>'+ + '<th colspan="5" class="switch"></th>'+ + '<th class="next"><i class="icon-arrow-right"/></th>'+ + '</tr>'+ + '</thead>', + contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>', + footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>' + }; + DPGlobal.template = '<div class="datetimepicker">'+ + '<div class="datetimepicker-minutes">'+ + '<table class=" table-condensed">'+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '<div class="datetimepicker-hours">'+ + '<table class=" table-condensed">'+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '<div class="datetimepicker-days">'+ + '<table class=" table-condensed">'+ + DPGlobal.headTemplate+ + '<tbody></tbody>'+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '<div class="datetimepicker-months">'+ + '<table class="table-condensed">'+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '<div class="datetimepicker-years">'+ + '<table class="table-condensed">'+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '</div>'; + + $.fn.datetimepicker.DPGlobal = DPGlobal; + +}( window.jQuery ); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datepicker.uk.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datepicker.uk.js new file mode 100755 index 0000000..bbd0c73 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datepicker.uk.js @@ -0,0 +1,14 @@ +/** + * Ukrainian translation for bootstrap-datepicker + * Andrey Vityuk <andrey [dot] vityuk [at] gmail.com> + */ +;(function($){ + $.fn.datepicker.dates['uk'] = { + days: ["ÐеділÑ", "Понеділок", "Вівторок", "Середа", "Четвер", "П'ÑтницÑ", "Субота", "ÐеділÑ"], + daysShort: ["Ðед", "Пнд", "Ð’Ñ‚Ñ€", "Срд", "Чтв", "Птн", "Суб", "Ðед"], + daysMin: ["Ðд", "Пн", "Ð’Ñ‚", "Ср", "Чт", "Пт", "Сб", "Ðд"], + months: ["Січень", "Лютий", "Березень", "Квітень", "Травень", "Червень", "Липень", "Серпень", "ВереÑень", "Жовтень", "ЛиÑтопад", "Грудень"], + monthsShort: ["Січ", "Лют", "Бер", "Кві", "Тра", "Чер", "Лип", "Сер", "Вер", "Жов", "ЛиÑ", "Гру"], + today: "Сьогодні" + }; +}(jQuery)); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.bg.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.bg.js new file mode 100755 index 0000000..0282103 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.bg.js @@ -0,0 +1,14 @@ +/** + * Bulgarian translation for bootstrap-datetimepicker + * Apostol Apostolov <apostol.s.apostolov@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['bg'] = { + days: ["ÐеделÑ", "Понеделник", "Вторник", "СрÑда", "Четвъртък", "Петък", "Събота", "ÐеделÑ"], + daysShort: ["Ðед", "Пон", "Вто", "СрÑ", "Чет", "Пет", "Съб", "Ðед"], + daysMin: ["Ð", "П", "Ð’", "С", "Ч", "П", "С", "Ð"], + months: ["Януари", "Февруари", "Март", "Ðприл", "Май", "Юни", "Юли", "ÐвгуÑÑ‚", "Септември", "Октомври", "Ðоември", "Декември"], + monthsShort: ["Ян", "Фев", "Мар", "Ðпр", "Май", "Юни", "Юли", "Ðвг", "Сеп", "Окт", "Ðое", "Дек"], + today: "днеÑ" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.cs.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.cs.js new file mode 100755 index 0000000..b8f151f --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.cs.js @@ -0,0 +1,14 @@ +/** + * Czech translation for bootstrap-datetimepicker + * MatÄ›j Koubík <matej@koubik.name> + */ +;(function($){ + $.fn.datetimepicker.dates['cs'] = { + days: ["NedÄ›le", "PondÄ›lí", "Úterý", "StÅ™eda", "ÄŒtvrtek", "Pátek", "Sobota", "NedÄ›le"], + daysShort: ["Ne", "Po", "Út", "St", "ÄŒt", "Pá", "So", "Ne"], + daysMin: ["N", "P", "Ú", "St", "ÄŒ", "P", "So", "N"], + months: ["Leden", "Únor", "BÅ™ezen", "Duben", "KvÄ›ten", "ÄŒerven", "ÄŒervenec", "Srpen", "Září", "Říjen", "Listopad", "Prosinec"], + monthsShort: ["Led", "Úno", "BÅ™e", "Dub", "KvÄ›", "ÄŒer", "ÄŒnc", "Srp", "Zář", "Říj", "Lis", "Pro"], + today: "Dnes" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.da.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.da.js new file mode 100755 index 0000000..db2a63d --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.da.js @@ -0,0 +1,14 @@ +/** + * Danish translation for bootstrap-datetimepicker + * Christian Pedersen <http://github.com/chripede> + */ +;(function($){ + $.fn.datetimepicker.dates['da'] = { + days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"], + daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"], + daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"], + months: ["Januar", "Februar", "Marts", "April", "Maj", "Juni", "Juli", "August", "September", "Oktober", "November", "December"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], + today: "I Dag" + }; +}(jQuery)); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.de.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.de.js new file mode 100755 index 0000000..d578768 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.de.js @@ -0,0 +1,14 @@ +/** + * German translation for bootstrap-datetimepicker + * Sam Zurcher <sam@orelias.ch> + */ +;(function($){ + $.fn.datetimepicker.dates['de'] = { + days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"], + daysShort: ["Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam", "Son"], + daysMin: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"], + months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], + monthsShort: ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"], + today: "Heute" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.es.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.es.js new file mode 100755 index 0000000..1114f5a --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.es.js @@ -0,0 +1,14 @@ +/** + * Spanish translation for bootstrap-datetimepicker + * Bruno Bonamin <bruno.bonamin@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['es'] = { + days: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"], + daysShort: ["Dom", "Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Dom"], + daysMin: ["Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa", "Do"], + months: ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"], + monthsShort: ["Ene", "Feb", "Mar", "Abr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dic"], + today: "Hoy" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.fi.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.fi.js new file mode 100755 index 0000000..a902f05 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.fi.js @@ -0,0 +1,14 @@ +/** + * Finnish translation for bootstrap-datetimepicker + * Jaakko Salonen <https://github.com/jsalonen> + */ +;(function($){ + $.fn.datetimepicker.dates['fi'] = { + days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai", "sunnuntai"], + daysShort: ["sun", "maa", "tii", "kes", "tor", "per", "lau", "sun"], + daysMin: ["su", "ma", "ti", "ke", "to", "pe", "la", "su"], + months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"], + monthsShort: ["tam", "hel", "maa", "huh", "tou", "kes", "hei", "elo", "syy", "lok", "mar", "jou"], + today: "tänään" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.fr.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.fr.js new file mode 100755 index 0000000..c5ce090 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.fr.js @@ -0,0 +1,14 @@ +/** + * French translation for bootstrap-datetimepicker + * Nico Mollet <nico.mollet@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['fr'] = { + days: ["Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"], + daysShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"], + daysMin: ["D", "L", "Ma", "Me", "J", "V", "S", "D"], + months: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"], + monthsShort: ["Jan", "Fev", "Mar", "Avr", "Mai", "Jui", "Jul", "Aou", "Sep", "Oct", "Nov", "Dec"], + today: "Aujourd'hui" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.he.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.he.js new file mode 100755 index 0000000..8acccac --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.he.js @@ -0,0 +1,15 @@ +/** + * Hebrew translation for bootstrap-datetimepicker + * Sagie Maoz <sagie@maoz.info> + */ +;(function($){ + $.fn.datetimepicker.dates['he'] = { + days: ["ר×שון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת", "ר×שון"], + daysShort: ["×", "ב", "×’", "ד", "×”", "ו", "ש", "×"], + daysMin: ["×", "ב", "×’", "ד", "×”", "ו", "ש", "×"], + months: ["ינו×ר", "פברו×ר", "מרץ", "×פריל", "מ××™", "יוני", "יולי", "×וגוסט", "ספטמבר", "×וקטובר", "נובמבר", "דצמבר"], + monthsShort: ["ינו", "פבר", "מרץ", "×פר", "מ××™", "יונ", "יול", "×וג", "ספט", "×וק", "נוב", "דצמ"], + today: "היו×", + rtl: true + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.hr.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.hr.js new file mode 100755 index 0000000..c72cbb5 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.hr.js @@ -0,0 +1,13 @@ +/** + * Croatian localisation + */ +;(function($){ + $.fn.datetimepicker.dates['hr'] = { + days: ["Nedjelja", "Ponedjelja", "Utorak", "Srijeda", "ÄŒetrtak", "Petak", "Subota", "Nedjelja"], + daysShort: ["Ned", "Pon", "Uto", "Srr", "ÄŒet", "Pet", "Sub", "Ned"], + daysMin: ["Ne", "Po", "Ut", "Sr", "ÄŒe", "Pe", "Su", "Ne"], + months: ["SijeÄanj", "VeljaÄa", "Ožujak", "Travanj", "Svibanj", "Lipanj", "Srpanj", "Kolovoz", "Rujan", "Listopad", "Studeni", "Prosinac"], + monthsShort: ["Sije", "Velj", "Ožu", "Tra", "Svi", "Lip", "Jul", "Kol", "Ruj", "Lis", "Stu", "Pro"], + today: "Danas" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.id.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.id.js new file mode 100755 index 0000000..10397b2 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.id.js @@ -0,0 +1,13 @@ +/** + * Bahasa translation for bootstrap-datetimepicker + * Azwar Akbar <azwar.akbar@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['id'] = { + days: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"], + daysShort: ["Mgu", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Mgu"], + daysMin: ["Mg", "Sn", "Sl", "Ra", "Ka", "Ju", "Sa", "Mg"], + months: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ags", "Sep", "Okt", "Nov", "Des"] + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.is.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.is.js new file mode 100755 index 0000000..27ed846 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.is.js @@ -0,0 +1,14 @@ +/** + * Icelandic translation for bootstrap-datetimepicker + * Hinrik Örn Sigurðsson <hinrik.sig@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['is'] = { + days: ["Sunnudagur", "Mánudagur", "Þriðjudagur", "Miðvikudagur", "Fimmtudagur", "Föstudagur", "Laugardagur", "Sunnudagur"], + daysShort: ["Sun", "Mán", "Þri", "Mið", "Fim", "Fös", "Lau", "Sun"], + daysMin: ["Su", "Má", "Þr", "Mi", "Fi", "Fö", "La", "Su"], + months: ["Janúar", "Febrúar", "Mars", "Apríl", "Maí", "Júní", "Júlí", "Ãgúst", "September", "Október", "Nóvember", "Desember"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maí", "Jún", "Júl", "Ãgú", "Sep", "Okt", "Nóv", "Des"], + today: "à Dag" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.it.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.it.js new file mode 100755 index 0000000..4a20fd6 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.it.js @@ -0,0 +1,14 @@ +/** + * Italian translation for bootstrap-datetimepicker + * Enrico Rubboli <rubboli@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['it'] = { + days: ["Domenica", "Lunedi", "Martedi", "Mercoledi", "Giovedi", "Venerdi", "Sabato", "Domenica"], + daysShort: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab", "Dom"], + daysMin: ["Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa", "Do"], + months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"], + monthsShort: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"], + today: "Oggi" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ja.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ja.js new file mode 100755 index 0000000..2040a7e --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ja.js @@ -0,0 +1,13 @@ +/** + * Japanese translation for bootstrap-datetimepicker + * Norio Suzuki <https://github.com/suzuki/> + */ +;(function($){ + $.fn.datetimepicker.dates['ja'] = { + days: ["日曜", "月曜", "ç«æ›œ", "水曜", "木曜", "金曜", "土曜", "日曜"], + daysShort: ["æ—¥", "月", "ç«", "æ°´", "木", "金", "土", "æ—¥"], + daysMin: ["æ—¥", "月", "ç«", "æ°´", "木", "金", "土", "æ—¥"], + months: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"], + monthsShort: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"] + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.kr.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.kr.js new file mode 100755 index 0000000..23c112e --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.kr.js @@ -0,0 +1,13 @@ +/** + * Korean translation for bootstrap-datetimepicker + * Gu Youn <http://github.com/guyoun> + */ +;(function($){ + $.fn.datetimepicker.dates['kr'] = { + days: ["ì¼ìš”ì¼", "월요ì¼", "화요ì¼", "수요ì¼", "목요ì¼", "금요ì¼", "토요ì¼", "ì¼ìš”ì¼"], + daysShort: ["ì¼", "ì›”", "í™”", "수", "목", "금", "토", "ì¼"], + daysMin: ["ì¼", "ì›”", "í™”", "수", "목", "금", "토", "ì¼"], + months: ["1ì›”", "2ì›”", "3ì›”", "4ì›”", "5ì›”", "6ì›”", "7ì›”", "8ì›”", "9ì›”", "10ì›”", "11ì›”", "12ì›”"], + monthsShort: ["1ì›”", "2ì›”", "3ì›”", "4ì›”", "5ì›”", "6ì›”", "7ì›”", "8ì›”", "9ì›”", "10ì›”", "11ì›”", "12ì›”"] + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.lt.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.lt.js new file mode 100755 index 0000000..761b89d --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.lt.js @@ -0,0 +1,16 @@ +/** + * Lithuanian translation for bootstrap-datetimepicker + * Å arÅ«nas Gliebus <ssharunas@yahoo.co.uk> + */ + +;(function($){ + $.fn.datetimepicker.dates['lt'] = { + days: ["Sekmadienis", "Pirmadienis", "Antradienis", "TreÄiadienis", "Ketvirtadienis", "Penktadienis", "Å eÅ¡tadienis", "Sekmadienis"], + daysShort: ["S", "Pr", "A", "T", "K", "Pn", "Å ", "S"], + daysMin: ["Sk", "Pr", "An", "Tr", "Ke", "Pn", "Å t", "Sk"], + months: ["Sausis", "Vasaris", "Kovas", "Balandis", "Gegužė", "Birželis", "Liepa", "RugpjÅ«tis", "RugsÄ—jis", "Spalis", "Lapkritis", "Gruodis"], + monthsShort: ["Sau", "Vas", "Kov", "Bal", "Geg", "Bir", "Lie", "Rugp", "Rugs", "Spa", "Lap", "Gru"], + today: "Å iandien", + weekStart: 1 + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.lv.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.lv.js new file mode 100755 index 0000000..86b1276 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.lv.js @@ -0,0 +1,16 @@ +/** + * Latvian translation for bootstrap-datetimepicker + * Artis Avotins <artis@apit.lv> + */ + +;(function($){ + $.fn.datetimepicker.dates['lv'] = { + days: ["SvÄ“tdiena", "Pirmdiena", "Otrdiena", "TreÅ¡diena", "Ceturtdiena", "Piektdiena", "Sestdiena", "SvÄ“tdiena"], + daysShort: ["Sv", "P", "O", "T", "C", "Pk", "S", "Sv"], + daysMin: ["Sv", "Pr", "Ot", "Tr", "Ce", "Pk", "St", "Sv"], + months: ["JanvÄris", "FebruÄris", "Marts", "AprÄ«lis", "Maijs", "JÅ«nijs", "JÅ«lijs", "Augusts", "Septembris", "Oktobris", "Novembris", "Decembris"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "JÅ«n", "JÅ«l", "Aug", "Sep", "Okt", "Nov", "Dec."], + today: "Å odien", + weekStart: 1 + }; +}(jQuery)); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ms.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ms.js new file mode 100755 index 0000000..b1f689f --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ms.js @@ -0,0 +1,14 @@ +/** + * Malay translation for bootstrap-datetimepicker + * Ateman Faiz <noorulfaiz@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['ms'] = { + days: ["Ahad", "Isnin", "Selasa", "Rabu", "Khamis", "Jumaat", "Sabtu", "Ahad"], + daysShort: ["Aha", "Isn", "Sel", "Rab", "Kha", "Jum", "Sab", "Aha"], + daysMin: ["Ah", "Is", "Se", "Ra", "Kh", "Ju", "Sa", "Ah"], + months: ["Januari", "Februari", "Mac", "April", "Mei", "Jun", "Julai", "Ogos", "September", "Oktober", "November", "Disember"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ogo", "Sep", "Okt", "Nov", "Dis"], + today: "Hari Ini" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.nb.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.nb.js new file mode 100755 index 0000000..74e8ddd --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.nb.js @@ -0,0 +1,14 @@ +/** + * Norwegian (bokmÃ¥l) translation for bootstrap-datetimepicker + * Fredrik Sundmyhr <http://github.com/fsundmyhr> + */ +;(function($){ + $.fn.datetimepicker.dates['nb'] = { + days: ["Søndag", "Mandag", "Tirsdag", "Onsdag", "Torsdag", "Fredag", "Lørdag", "Søndag"], + daysShort: ["Søn", "Man", "Tir", "Ons", "Tor", "Fre", "Lør", "Søn"], + daysMin: ["Sø", "Ma", "Ti", "On", "To", "Fr", "Lø", "Sø"], + months: ["Januar", "Februar", "Mars", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Desember"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Des"], + today: "I Dag" + }; +}(jQuery)); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.nl.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.nl.js new file mode 100755 index 0000000..64c7527 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.nl.js @@ -0,0 +1,14 @@ +/** + * Dutch translation for bootstrap-datetimepicker + * Reinier Goltstein <mrgoltstein@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['nl'] = { + days: ["Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"], + daysShort: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], + daysMin: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"], + months: ["Januari", "Februari", "Maart", "April", "Mei", "Juni", "Juli", "Augustus", "September", "Oktober", "November", "December"], + monthsShort: ["Jan", "Feb", "Mrt", "Apr", "Mei", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], + today: "Vandaag" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pl.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pl.js new file mode 100755 index 0000000..8307f51 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pl.js @@ -0,0 +1,15 @@ +/** + * Polish translation for bootstrap-datetimepicker + * Robert <rtpm@gazeta.pl> + */ +;(function($){ + $.fn.datetimepicker.dates['pl'] = { + days: ["Niedziela", "PoniedziaÅ‚ek", "Wtorek", "Åšroda", "Czwartek", "PiÄ…tek", "Sobota", "Niedziela"], + daysShort: ["Nie", "Pn", "Wt", "Åšr", "Czw", "Pt", "So", "Nie"], + daysMin: ["N", "Pn", "Wt", "Åšr", "Cz", "Pt", "So", "N"], + months: ["StyczeÅ„", "Luty", "Marzec", "KwiecieÅ„", "Maj", "Czerwiec", "Lipiec", "SierpieÅ„", "WrzesieÅ„", "Październik", "Listopad", "GrudzieÅ„"], + monthsShort: ["Sty", "Lu", "Mar", "Kw", "Maj", "Cze", "Lip", "Sie", "Wrz", "Pa", "Lis", "Gru"], + today: "Dzisiaj", + weekStart: 1 + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pt-BR.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pt-BR.js new file mode 100755 index 0000000..056b138 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pt-BR.js @@ -0,0 +1,14 @@ +/** + * Brazilian translation for bootstrap-datetimepicker + * Cauan Cabral <cauan@radig.com.br> + */ +;(function($){ + $.fn.datetimepicker.dates['pt-BR'] = { + days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"], + daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"], + daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa", "Do"], + months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], + monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"], + today: "Hoje" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pt.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pt.js new file mode 100755 index 0000000..223c24d --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.pt.js @@ -0,0 +1,14 @@ +/** + * Portuguese translation for bootstrap-datetimepicker + * Original code: Cauan Cabral <cauan@radig.com.br> + * Tiago Melo <tiago.blackcode@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['pt'] = { + days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"], + daysShort: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"], + daysMin: ["Do", "Se", "Te", "Qu", "Qu", "Se", "Sa", "Do"], + months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], + monthsShort: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"] + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ro.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ro.js new file mode 100755 index 0000000..d2103a3 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ro.js @@ -0,0 +1,15 @@ +/** + * Romanian translation for bootstrap-datetimepicker + * Cristian Vasile <cristi.mie@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['ro'] = { + days: ["Duminică", "Luni", "MarÅ£i", "Miercuri", "Joi", "Vineri", "Sâmbătă", "Duminică"], + daysShort: ["Dum", "Lun", "Mar", "Mie", "Joi", "Vin", "Sâm", "Dum"], + daysMin: ["Du", "Lu", "Ma", "Mi", "Jo", "Vi", "Sâ", "Du"], + months: ["Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie"], + monthsShort: ["Ian", "Feb", "Mar", "Apr", "Mai", "Iun", "Iul", "Aug", "Sep", "Oct", "Nov", "Dec"], + today: "Astăzi", + weekStart: 1 + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.rs-latin.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.rs-latin.js new file mode 100755 index 0000000..832cc4b --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.rs-latin.js @@ -0,0 +1,14 @@ +/** + * Serbian latin translation for bootstrap-datetimepicker + * Bojan Milosavlević <milboj@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['rs'] = { + days: ["Nedelja","Ponedeljak", "Utorak", "Sreda", "ÄŒetvrtak", "Petak", "Subota", "Nedelja"], + daysShort: ["Ned", "Pon", "Uto", "Sre", "ÄŒet", "Pet", "Sub", "Ned"], + daysMin: ["N", "Po", "U", "Sr", "ÄŒ", "Pe", "Su", "N"], + months: ["Januar", "Februar", "Mart", "April", "Maj", "Jun", "Jul", "Avgust", "Septembar", "Oktobar", "Novembar", "Decembar"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"], + today: "Danas" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.rs.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.rs.js new file mode 100755 index 0000000..7c7e5fc --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.rs.js @@ -0,0 +1,14 @@ +/** + * Serbian cyrillic translation for bootstrap-datetimepicker + * Bojan Milosavlević <milboj@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['rs'] = { + days: ["Ðедеља","Понедељак", "Уторак", "Среда", "Четвртак", "Петак", "Субота", "Ðедеља"], + daysShort: ["Ðед", "Пон", "Уто", "Сре", "Чет", "Пет", "Суб", "Ðед"], + daysMin: ["Ð", "По", "У", "Ср", "Ч", "Пе", "Су", "Ð"], + months: ["Јануар", "Фебруар", "Март", "Ðприл", "Мај", "Јун", "Јул", "ÐвгуÑÑ‚", "Септембар", "Октобар", "Ðовембар", "Децембар"], + monthsShort: ["Јан", "Феб", "Мар", "Ðпр", "Мај", "Јун", "Јул", "Ðвг", "Сеп", "Окт", "Ðов", "Дец"], + today: "ДанаÑ" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ru.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ru.js new file mode 100755 index 0000000..464397a --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.ru.js @@ -0,0 +1,14 @@ +/** + * Russian translation for bootstrap-datetimepicker + * Victor Taranenko <darwin@snowdale.com> + */ +;(function($){ + $.fn.datetimepicker.dates['ru'] = { + days: ["ВоÑкреÑенье", "Понедельник", "Вторник", "Среда", "Четверг", "ПÑтница", "Суббота", "ВоÑкреÑенье"], + daysShort: ["Ð’Ñк", "Пнд", "Ð’Ñ‚Ñ€", "Срд", "Чтв", "Птн", "Суб", "Ð’Ñк"], + daysMin: ["Ð’Ñ", "Пн", "Ð’Ñ‚", "Ср", "Чт", "Пт", "Сб", "Ð’Ñ"], + months: ["Январь", "Февраль", "Март", "Ðпрель", "Май", "Июнь", "Июль", "ÐвгуÑÑ‚", "СентÑбрь", "ОктÑбрь", "ÐоÑбрь", "Декабрь"], + monthsShort: ["Янв", "Фев", "Мар", "Ðпр", "Май", "Июн", "Июл", "Ðвг", "Сен", "Окт", "ÐоÑ", "Дек"], + today: "СегоднÑ" + }; +}(jQuery)); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sk.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sk.js new file mode 100755 index 0000000..d9e2490 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sk.js @@ -0,0 +1,14 @@ +/** + * Slovak translation for bootstrap-datetimepicker + * Marek Lichtner <marek@licht.sk> + */ +;(function($){ + $.fn.datetimepicker.dates["sk"] = { + days: ["Nedeľa", "Pondelok", "Utorok", "Streda", "Å tvrtok", "Piatok", "Sobota", "Nedeľa"], + daysShort: ["Ne", "Po", "Ut", "St", "Å t", "Pi", "So", "Ne"], + daysMin: ["Ne", "Po", "Ut", "St", "Å t", "Pi", "So", "Ne"], + months: ["Január", "Február", "Marec", "Apríl", "Máj", "Jún", "Júl", "August", "September", "Október", "November", "December"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "Máj", "Jún", "Júl", "Aug", "Sep", "Okt", "Nov", "Dec"], + today: "Dnes" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sl.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sl.js new file mode 100755 index 0000000..1fac6cd --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sl.js @@ -0,0 +1,14 @@ +/** + * Slovene translation for bootstrap-datetimepicker + * Gregor Rudolf <gregor.rudolf@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['sl'] = { + days: ["Nedelja", "Ponedeljek", "Torek", "Sreda", "ÄŒetrtek", "Petek", "Sobota", "Nedelja"], + daysShort: ["Ned", "Pon", "Tor", "Sre", "ÄŒet", "Pet", "Sob", "Ned"], + daysMin: ["Ne", "Po", "To", "Sr", "ÄŒe", "Pe", "So", "Ne"], + months: ["Januar", "Februar", "Marec", "April", "Maj", "Junij", "Julij", "Avgust", "September", "Oktober", "November", "December"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Avg", "Sep", "Okt", "Nov", "Dec"], + today: "Danes" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sv.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sv.js new file mode 100755 index 0000000..bb19b50 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.sv.js @@ -0,0 +1,14 @@ +/** + * Swedish translation for bootstrap-datetimepicker + * Patrik Ragnarsson <patrik@starkast.net> + */ +;(function($){ + $.fn.datetimepicker.dates['sv'] = { + days: ["Söndag", "MÃ¥ndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag", "Söndag"], + daysShort: ["Sön", "MÃ¥n", "Tis", "Ons", "Tor", "Fre", "Lör", "Sön"], + daysMin: ["Sö", "MÃ¥", "Ti", "On", "To", "Fr", "Lö", "Sö"], + months: ["Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"], + today: "I Dag" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.th.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.th.js new file mode 100755 index 0000000..a068355 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.th.js @@ -0,0 +1,14 @@ +/** + * Thai translation for bootstrap-datetimepicker + * Suchau Jiraprapot <seroz24@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['th'] = { + days: ["อาทิตย์", "จันทร์", "อังคาร", "พุธ", "พฤหัส", "ศุà¸à¸£à¹Œ", "เสาร์", "อาทิตย์"], + daysShort: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"], + daysMin: ["อา", "จ", "อ", "พ", "พฤ", "ศ", "ส", "อา"], + months: ["มà¸à¸£à¸²à¸„ม", "à¸à¸¸à¸¡à¸ à¸²à¸žà¸±à¸™à¸˜à¹Œ", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "à¸à¸£à¸à¸Žà¸²à¸„ม", "สิงหาคม", "à¸à¸±à¸™à¸¢à¸²à¸¢à¸™", "ตุลาคม", "พฤศจิà¸à¸²à¸¢à¸™", "ธันวาคม"], + monthsShort: ["ม.ค.", "à¸.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "à¸.ค.", "ส.ค.", "à¸.ย.", "ต.ค.", "พ.ย.", "ธ.ค."], + today: "วันนี้" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.tr.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.tr.js new file mode 100755 index 0000000..01f7dc1 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.tr.js @@ -0,0 +1,15 @@ +/** + * Turkish translation for bootstrap-datetimepicker + * Serkan Algur <kaisercrazy_2@hotmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['tr'] = { + days: ["Pazar", "Pazartesi", "Salı", "ÇarÅŸamba", "PerÅŸembe", "Cuma", "Cumartesi", "Pazar"], + daysShort: ["Pz", "Pzt", "Sal", "ÇrÅŸ", "PrÅŸ", "Cu", "Cts", "Pz"], + daysMin: ["Pz", "Pzt", "Sa", "Çr", "Pr", "Cu", "Ct", "Pz"], + months: ["Ocak", "Åžubat", "Mart", "Nisan", "Mayıs", "Haziran", "Temmuz", "AÄŸustos", "Eylül", "Ekim", "Kasım", "Aralık"], + monthsShort: ["Oca", "Åžub", "Mar", "Nis", "May", "Haz", "Tem", "AÄŸu", "Eyl", "Eki", "Kas", "Ara"], + today: "Bugün" + }; +}(jQuery)); + diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.zh-CN.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.zh-CN.js new file mode 100755 index 0000000..42629c0 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.zh-CN.js @@ -0,0 +1,14 @@ +/** + * Simplified Chinese translation for bootstrap-datetimepicker + * Yuan Cheung <advanimal@gmail.com> + */ +;(function($){ + $.fn.datetimepicker.dates['zh-CN'] = { + days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], + daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"], + daysMin: ["æ—¥", "一", "二", "三", "å››", "五", "å…­", "æ—¥"], + months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "ä¹æœˆ", "å月", "å一月", "å二月"], + monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "ä¹æœˆ", "å月", "å一月", "å二月"], + today: "今日" + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.zh-TW.js b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.zh-TW.js new file mode 100755 index 0000000..2dab261 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.zh-TW.js @@ -0,0 +1,13 @@ +/** + * Traditional Chinese translation for bootstrap-datetimepicker + * Rung-Sheng Jang <daniel@i-trend.co.cc> + */ +;(function($){ + $.fn.datetimepicker.dates['zh-TW'] = { + days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"], + daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"], + daysMin: ["æ—¥", "一", "二", "三", "å››", "五", "å…­", "æ—¥"], + months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "ä¹æœˆ", "å月", "å一月", "å二月"], + monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "ä¹æœˆ", "å月", "å一月", "å二月"] + }; +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/dropzone/css/basic.css b/src/core/classes/org/glizycms/js/jquery/dropzone/css/basic.css new file mode 100755 index 0000000..83084db --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/dropzone/css/basic.css @@ -0,0 +1,155 @@ +/* The MIT License */ +.dropzone, +.dropzone *, +.dropzone-previews, +.dropzone-previews * { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.dropzone { + position: relative; + border: 1px solid rgba(0,0,0,0.08); + background: rgba(0,0,0,0.02); + padding: 1em; +} +.dropzone.dz-clickable { + cursor: pointer; +} +.dropzone.dz-clickable .dz-message, +.dropzone.dz-clickable .dz-message span { + cursor: pointer; +} +.dropzone.dz-clickable * { + cursor: default; +} +.dropzone .dz-message { + opacity: 1; + -ms-filter: none; + filter: none; +} +.dropzone.dz-drag-hover { + border-color: rgba(0,0,0,0.15); + background: rgba(0,0,0,0.04); +} +.dropzone.dz-started .dz-message { + display: none; +} +.dropzone .dz-preview, +.dropzone-previews .dz-preview { + background: rgba(255,255,255,0.8); + position: relative; + display: inline-block; + margin: 17px; + vertical-align: top; + border: 1px solid #acacac; + padding: 6px 6px 6px 6px; +} +.dropzone .dz-preview.dz-file-preview [data-dz-thumbnail], +.dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail] { + display: none; +} +.dropzone .dz-preview .dz-details, +.dropzone-previews .dz-preview .dz-details { + width: 100px; + height: 100px; + position: relative; + background: #ebebeb; + padding: 5px; + margin-bottom: 22px; +} +.dropzone .dz-preview .dz-details .dz-filename, +.dropzone-previews .dz-preview .dz-details .dz-filename { + overflow: hidden; + height: 100%; +} +.dropzone .dz-preview .dz-details img, +.dropzone-previews .dz-preview .dz-details img { + position: absolute; + top: 0; + left: 0; + width: 100px; + height: 100px; +} +.dropzone .dz-preview .dz-details .dz-size, +.dropzone-previews .dz-preview .dz-details .dz-size { + position: absolute; + bottom: -28px; + left: 3px; + height: 28px; + line-height: 28px; +} +.dropzone .dz-preview.dz-error .dz-error-mark, +.dropzone-previews .dz-preview.dz-error .dz-error-mark { + display: block; +} +.dropzone .dz-preview.dz-success .dz-success-mark, +.dropzone-previews .dz-preview.dz-success .dz-success-mark { + display: block; +} +.dropzone .dz-preview:hover .dz-details img, +.dropzone-previews .dz-preview:hover .dz-details img { + display: none; +} +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark, +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + display: none; + position: absolute; + width: 40px; + height: 40px; + font-size: 30px; + text-align: center; + right: -10px; + top: -10px; +} +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark { + color: #8cc657; +} +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + color: #ee162d; +} +.dropzone .dz-preview .dz-progress, +.dropzone-previews .dz-preview .dz-progress { + position: absolute; + top: 100px; + left: 6px; + right: 6px; + height: 6px; + background: #d7d7d7; + display: none; +} +.dropzone .dz-preview .dz-progress .dz-upload, +.dropzone-previews .dz-preview .dz-progress .dz-upload { + display: block; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 0%; + background-color: #8cc657; +} +.dropzone .dz-preview.dz-processing .dz-progress, +.dropzone-previews .dz-preview.dz-processing .dz-progress { + display: block; +} +.dropzone .dz-preview .dz-error-message, +.dropzone-previews .dz-preview .dz-error-message { + display: none; + position: absolute; + top: -5px; + left: -20px; + background: rgba(245,245,245,0.8); + padding: 8px 10px; + color: #800; + min-width: 140px; + max-width: 500px; + z-index: 500; +} +.dropzone .dz-preview:hover.dz-error .dz-error-message, +.dropzone-previews .dz-preview:hover.dz-error .dz-error-message { + display: block; +} diff --git a/src/core/classes/org/glizycms/js/jquery/dropzone/css/basic2.css b/src/core/classes/org/glizycms/js/jquery/dropzone/css/basic2.css new file mode 100755 index 0000000..380d7ff --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/dropzone/css/basic2.css @@ -0,0 +1,155 @@ +/* The MIT License */ +.glizy-dropzone, +.glizy-dropzone *, +.dropzone-previews, +.dropzone-previews * { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.glizy-dropzone { + position: relative; + border: 1px solid rgba(0,0,0,0.08); + background: rgba(0,0,0,0.02); + padding: 1em; +} +.glizy-dropzone.dz-clickable { + cursor: pointer; +} +.glizy-dropzone.dz-clickable .dz-message, +.glizy-dropzone.dz-clickable .dz-message span { + cursor: pointer; +} +.glizy-dropzone.dz-clickable * { + cursor: default; +} +.glizy-dropzone .dz-message { + opacity: 1; + -ms-filter: none; + filter: none; +} +.glizy-dropzone.dz-drag-hover { + border-color: rgba(0,0,0,0.15); + background: rgba(0,0,0,0.04); +} +.glizy-dropzone.dz-started .dz-message { + display: none; +} +.glizy-dropzone .dz-preview, +.dropzone-previews .dz-preview { + background: rgba(255,255,255,0.8); + position: relative; + display: inline-block; + margin: 17px; + vertical-align: top; + border: 1px solid #acacac; + padding: 6px 6px 6px 6px; +} +.glizy-dropzone .dz-preview.dz-file-preview [data-dz-thumbnail], +.dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail] { + display: none; +} +.glizy-dropzone .dz-preview .dz-details, +.dropzone-previews .dz-preview .dz-details { + width: 100px; + height: 100px; + position: relative; + background: #ebebeb; + padding: 5px; + margin-bottom: 22px; +} +.glizy-dropzone .dz-preview .dz-details .dz-filename, +.dropzone-previews .dz-preview .dz-details .dz-filename { + overflow: hidden; + height: 100%; +} +.glizy-dropzone .dz-preview .dz-details img, +.dropzone-previews .dz-preview .dz-details img { + position: absolute; + top: 0; + left: 0; + width: 100px; + height: 100px; +} +.glizy-dropzone .dz-preview .dz-details .dz-size, +.dropzone-previews .dz-preview .dz-details .dz-size { + position: absolute; + bottom: -28px; + left: 3px; + height: 28px; + line-height: 28px; +} +.glizy-dropzone .dz-preview.dz-error .dz-error-mark, +.dropzone-previews .dz-preview.dz-error .dz-error-mark { + display: block; +} +.glizy-dropzone .dz-preview.dz-success .dz-success-mark, +.dropzone-previews .dz-preview.dz-success .dz-success-mark { + display: block; +} +.glizy-dropzone .dz-preview:hover .dz-details img, +.dropzone-previews .dz-preview:hover .dz-details img { + display: none; +} +.glizy-dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark, +.glizy-dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + display: none; + position: absolute; + width: 40px; + height: 40px; + font-size: 30px; + text-align: center; + right: -10px; + top: -10px; +} +.glizy-dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark { + color: #8cc657; +} +.glizy-dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + color: #ee162d; +} +.glizy-dropzone .dz-preview .dz-progress, +.dropzone-previews .dz-preview .dz-progress { + position: absolute; + top: 100px; + left: 6px; + right: 6px; + height: 6px; + background: #d7d7d7; + display: none; +} +.glizy-dropzone .dz-preview .dz-progress .dz-upload, +.dropzone-previews .dz-preview .dz-progress .dz-upload { + display: block; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 0%; + background-color: #8cc657; +} +.glizy-dropzone .dz-preview.dz-processing .dz-progress, +.dropzone-previews .dz-preview.dz-processing .dz-progress { + display: block; +} +.glizy-dropzone .dz-preview .dz-error-message, +.dropzone-previews .dz-preview .dz-error-message { + display: none; + position: absolute; + top: -5px; + left: -20px; + background: rgba(245,245,245,0.8); + padding: 8px 10px; + color: #800; + min-width: 140px; + max-width: 500px; + z-index: 500; +} +.glizy-dropzone .dz-preview:hover.dz-error .dz-error-message, +.dropzone-previews .dz-preview:hover.dz-error .dz-error-message { + display: block; +} diff --git a/src/core/classes/org/glizycms/js/jquery/dropzone/css/dropzone.css b/src/core/classes/org/glizycms/js/jquery/dropzone/css/dropzone.css new file mode 100755 index 0000000..fc18729 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/dropzone/css/dropzone.css @@ -0,0 +1,410 @@ +/* The MIT License */ +.dropzone, +.dropzone *, +.dropzone-previews, +.dropzone-previews * { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.dropzone { + position: relative; + border: 1px solid rgba(0,0,0,0.08); + background: rgba(0,0,0,0.02); + padding: 1em; +} +.dropzone.dz-clickable { + cursor: pointer; +} +.dropzone.dz-clickable .dz-message, +.dropzone.dz-clickable .dz-message span { + cursor: pointer; +} +.dropzone.dz-clickable * { + cursor: default; +} +.dropzone .dz-message { + opacity: 1; + -ms-filter: none; + filter: none; +} +.dropzone.dz-drag-hover { + border-color: rgba(0,0,0,0.15); + background: rgba(0,0,0,0.04); +} +.dropzone.dz-started .dz-message { + display: none; +} +.dropzone .dz-preview, +.dropzone-previews .dz-preview { + background: rgba(255,255,255,0.8); + position: relative; + display: inline-block; + margin: 17px; + vertical-align: top; + border: 1px solid #acacac; + padding: 6px 6px 6px 6px; +} +.dropzone .dz-preview.dz-file-preview [data-dz-thumbnail], +.dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail] { + display: none; +} +.dropzone .dz-preview .dz-details, +.dropzone-previews .dz-preview .dz-details { + width: 100px; + height: 100px; + position: relative; + background: #ebebeb; + padding: 5px; + margin-bottom: 22px; +} +.dropzone .dz-preview .dz-details .dz-filename, +.dropzone-previews .dz-preview .dz-details .dz-filename { + overflow: hidden; + height: 100%; +} +.dropzone .dz-preview .dz-details img, +.dropzone-previews .dz-preview .dz-details img { + position: absolute; + top: 0; + left: 0; + width: 100px; + height: 100px; +} +.dropzone .dz-preview .dz-details .dz-size, +.dropzone-previews .dz-preview .dz-details .dz-size { + position: absolute; + bottom: -28px; + left: 3px; + height: 28px; + line-height: 28px; +} +.dropzone .dz-preview.dz-error .dz-error-mark, +.dropzone-previews .dz-preview.dz-error .dz-error-mark { + display: block; +} +.dropzone .dz-preview.dz-success .dz-success-mark, +.dropzone-previews .dz-preview.dz-success .dz-success-mark { + display: block; +} +.dropzone .dz-preview:hover .dz-details img, +.dropzone-previews .dz-preview:hover .dz-details img { + display: none; +} +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark, +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + display: none; + position: absolute; + width: 40px; + height: 40px; + font-size: 30px; + text-align: center; + right: -10px; + top: -10px; +} +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark { + color: #8cc657; +} +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + color: #ee162d; +} +.dropzone .dz-preview .dz-progress, +.dropzone-previews .dz-preview .dz-progress { + position: absolute; + top: 100px; + left: 6px; + right: 6px; + height: 6px; + background: #d7d7d7; + display: none; +} +.dropzone .dz-preview .dz-progress .dz-upload, +.dropzone-previews .dz-preview .dz-progress .dz-upload { + display: block; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 0%; + background-color: #8cc657; +} +.dropzone .dz-preview.dz-processing .dz-progress, +.dropzone-previews .dz-preview.dz-processing .dz-progress { + display: block; +} +.dropzone .dz-preview .dz-error-message, +.dropzone-previews .dz-preview .dz-error-message { + display: none; + position: absolute; + top: -5px; + left: -20px; + background: rgba(245,245,245,0.8); + padding: 8px 10px; + color: #800; + min-width: 140px; + max-width: 500px; + z-index: 500; +} +.dropzone .dz-preview:hover.dz-error .dz-error-message, +.dropzone-previews .dz-preview:hover.dz-error .dz-error-message { + display: block; +} +.dropzone { + border: 1px solid rgba(0,0,0,0.03); + min-height: 360px; + -webkit-border-radius: 3px; + border-radius: 3px; + background: rgba(0,0,0,0.03); + padding: 23px; +} +.dropzone .dz-default.dz-message { + opacity: 1; + -ms-filter: none; + filter: none; + -webkit-transition: opacity 0.3s ease-in-out; + -moz-transition: opacity 0.3s ease-in-out; + -o-transition: opacity 0.3s ease-in-out; + -ms-transition: opacity 0.3s ease-in-out; + transition: opacity 0.3s ease-in-out; + background-image: url("../images/spritemap.png"); + background-repeat: no-repeat; + background-position: 0 0; + position: absolute; + width: 428px; + height: 123px; + margin-left: -214px; + margin-top: -61.5px; + top: 50%; + left: 50%; +} +@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) { + .dropzone .dz-default.dz-message { + background-image: url("../images/spritemap@2x.png"); + -webkit-background-size: 428px 406px; + -moz-background-size: 428px 406px; + background-size: 428px 406px; + } +} +.dropzone .dz-default.dz-message span { + display: none; +} +.dropzone.dz-square .dz-default.dz-message { + background-position: 0 -123px; + width: 268px; + margin-left: -134px; + height: 174px; + margin-top: -87px; +} +.dropzone.dz-drag-hover .dz-message { + opacity: 0.15; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=15)"; + filter: alpha(opacity=15); +} +.dropzone.dz-started .dz-message { + display: block; + opacity: 0; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + filter: alpha(opacity=0); +} +.dropzone .dz-preview, +.dropzone-previews .dz-preview { + -webkit-box-shadow: 1px 1px 4px rgba(0,0,0,0.16); + box-shadow: 1px 1px 4px rgba(0,0,0,0.16); + font-size: 14px; +} +.dropzone .dz-preview.dz-image-preview:hover .dz-details img, +.dropzone-previews .dz-preview.dz-image-preview:hover .dz-details img { + display: block; + opacity: 0.1; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=10)"; + filter: alpha(opacity=10); +} +.dropzone .dz-preview.dz-success .dz-success-mark, +.dropzone-previews .dz-preview.dz-success .dz-success-mark { + opacity: 1; + -ms-filter: none; + filter: none; +} +.dropzone .dz-preview.dz-error .dz-error-mark, +.dropzone-previews .dz-preview.dz-error .dz-error-mark { + opacity: 1; + -ms-filter: none; + filter: none; +} +.dropzone .dz-preview.dz-error .dz-progress .dz-upload, +.dropzone-previews .dz-preview.dz-error .dz-progress .dz-upload { + background: #ee1e2d; +} +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark, +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark { + display: block; + opacity: 0; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + filter: alpha(opacity=0); + -webkit-transition: opacity 0.4s ease-in-out; + -moz-transition: opacity 0.4s ease-in-out; + -o-transition: opacity 0.4s ease-in-out; + -ms-transition: opacity 0.4s ease-in-out; + transition: opacity 0.4s ease-in-out; + background-image: url("../images/spritemap.png"); + background-repeat: no-repeat; +} +@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) { + .dropzone .dz-preview .dz-error-mark, + .dropzone-previews .dz-preview .dz-error-mark, + .dropzone .dz-preview .dz-success-mark, + .dropzone-previews .dz-preview .dz-success-mark { + background-image: url("../images/spritemap@2x.png"); + -webkit-background-size: 428px 406px; + -moz-background-size: 428px 406px; + background-size: 428px 406px; + } +} +.dropzone .dz-preview .dz-error-mark span, +.dropzone-previews .dz-preview .dz-error-mark span, +.dropzone .dz-preview .dz-success-mark span, +.dropzone-previews .dz-preview .dz-success-mark span { + display: none; +} +.dropzone .dz-preview .dz-error-mark, +.dropzone-previews .dz-preview .dz-error-mark { + background-position: -268px -123px; +} +.dropzone .dz-preview .dz-success-mark, +.dropzone-previews .dz-preview .dz-success-mark { + background-position: -268px -163px; +} +.dropzone .dz-preview .dz-progress .dz-upload, +.dropzone-previews .dz-preview .dz-progress .dz-upload { + -webkit-animation: loading 0.4s linear infinite; + -moz-animation: loading 0.4s linear infinite; + -o-animation: loading 0.4s linear infinite; + -ms-animation: loading 0.4s linear infinite; + animation: loading 0.4s linear infinite; + -webkit-transition: width 0.3s ease-in-out; + -moz-transition: width 0.3s ease-in-out; + -o-transition: width 0.3s ease-in-out; + -ms-transition: width 0.3s ease-in-out; + transition: width 0.3s ease-in-out; + -webkit-border-radius: 2px; + border-radius: 2px; + position: absolute; + top: 0; + left: 0; + width: 0%; + height: 100%; + background-image: url("../images/spritemap.png"); + background-repeat: repeat-x; + background-position: 0px -400px; +} +@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) { + .dropzone .dz-preview .dz-progress .dz-upload, + .dropzone-previews .dz-preview .dz-progress .dz-upload { + background-image: url("../images/spritemap@2x.png"); + -webkit-background-size: 428px 406px; + -moz-background-size: 428px 406px; + background-size: 428px 406px; + } +} +.dropzone .dz-preview.dz-success .dz-progress, +.dropzone-previews .dz-preview.dz-success .dz-progress { + display: block; + opacity: 0; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + filter: alpha(opacity=0); + -webkit-transition: opacity 0.4s ease-in-out; + -moz-transition: opacity 0.4s ease-in-out; + -o-transition: opacity 0.4s ease-in-out; + -ms-transition: opacity 0.4s ease-in-out; + transition: opacity 0.4s ease-in-out; +} +.dropzone .dz-preview .dz-error-message, +.dropzone-previews .dz-preview .dz-error-message { + display: block; + opacity: 0; + -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; + filter: alpha(opacity=0); + -webkit-transition: opacity 0.3s ease-in-out; + -moz-transition: opacity 0.3s ease-in-out; + -o-transition: opacity 0.3s ease-in-out; + -ms-transition: opacity 0.3s ease-in-out; + transition: opacity 0.3s ease-in-out; +} +.dropzone .dz-preview:hover.dz-error .dz-error-message, +.dropzone-previews .dz-preview:hover.dz-error .dz-error-message { + opacity: 1; + -ms-filter: none; + filter: none; +} +.dropzone a.dz-remove, +.dropzone-previews a.dz-remove { + background-image: -webkit-linear-gradient(top, #fafafa, #eee); + background-image: -moz-linear-gradient(top, #fafafa, #eee); + background-image: -o-linear-gradient(top, #fafafa, #eee); + background-image: -ms-linear-gradient(top, #fafafa, #eee); + background-image: linear-gradient(to bottom, #fafafa, #eee); + -webkit-border-radius: 2px; + border-radius: 2px; + border: 1px solid #eee; + text-decoration: none; + display: block; + padding: 4px 5px; + text-align: center; + color: #aaa; + margin-top: 26px; +} +.dropzone a.dz-remove:hover, +.dropzone-previews a.dz-remove:hover { + color: #666; +} +@-moz-keyframes loading { + 0% { + background-position: 0 -400px; + } + + 100% { + background-position: -7px -400px; + } +} +@-webkit-keyframes loading { + 0% { + background-position: 0 -400px; + } + + 100% { + background-position: -7px -400px; + } +} +@-o-keyframes loading { + 0% { + background-position: 0 -400px; + } + + 100% { + background-position: -7px -400px; + } +} +@-ms-keyframes loading { + 0% { + background-position: 0 -400px; + } + + 100% { + background-position: -7px -400px; + } +} +@keyframes loading { + 0% { + background-position: 0 -400px; + } + + 100% { + background-position: -7px -400px; + } +} diff --git a/src/core/classes/org/glizycms/js/jquery/dropzone/dropzone.js b/src/core/classes/org/glizycms/js/jquery/dropzone/dropzone.js new file mode 100755 index 0000000..e1926f0 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/dropzone/dropzone.js @@ -0,0 +1,1919 @@ +;(function(){ + +/** + * Require the given path. + * + * @param {String} path + * @return {Object} exports + * @api public + */ + +function require(path, parent, orig) { + var resolved = require.resolve(path); + + // lookup failed + if (null == resolved) { + orig = orig || path; + parent = parent || 'root'; + var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); + err.path = orig; + err.parent = parent; + err.require = true; + throw err; + } + + var module = require.modules[resolved]; + + // perform real require() + // by invoking the module's + // registered function + if (!module._resolving && !module.exports) { + var mod = {}; + mod.exports = {}; + mod.client = mod.component = true; + module._resolving = true; + module.call(this, mod.exports, require.relative(resolved), mod); + delete module._resolving; + module.exports = mod.exports; + } + + return module.exports; +} + +/** + * Registered modules. + */ + +require.modules = {}; + +/** + * Registered aliases. + */ + +require.aliases = {}; + +/** + * Resolve `path`. + * + * Lookup: + * + * - PATH/index.js + * - PATH.js + * - PATH + * + * @param {String} path + * @return {String} path or null + * @api private + */ + +require.resolve = function(path) { + if (path.charAt(0) === '/') path = path.slice(1); + + var paths = [ + path, + path + '.js', + path + '.json', + path + '/index.js', + path + '/index.json' + ]; + + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + if (require.modules.hasOwnProperty(path)) return path; + if (require.aliases.hasOwnProperty(path)) return require.aliases[path]; + } +}; + +/** + * Normalize `path` relative to the current path. + * + * @param {String} curr + * @param {String} path + * @return {String} + * @api private + */ + +require.normalize = function(curr, path) { + var segs = []; + + if ('.' != path.charAt(0)) return path; + + curr = curr.split('/'); + path = path.split('/'); + + for (var i = 0; i < path.length; ++i) { + if ('..' == path[i]) { + curr.pop(); + } else if ('.' != path[i] && '' != path[i]) { + segs.push(path[i]); + } + } + + return curr.concat(segs).join('/'); +}; + +/** + * Register module at `path` with callback `definition`. + * + * @param {String} path + * @param {Function} definition + * @api private + */ + +require.register = function(path, definition) { + require.modules[path] = definition; +}; + +/** + * Alias a module definition. + * + * @param {String} from + * @param {String} to + * @api private + */ + +require.alias = function(from, to) { + if (!require.modules.hasOwnProperty(from)) { + throw new Error('Failed to alias "' + from + '", it does not exist'); + } + require.aliases[to] = from; +}; + +/** + * Return a require function relative to the `parent` path. + * + * @param {String} parent + * @return {Function} + * @api private + */ + +require.relative = function(parent) { + var p = require.normalize(parent, '..'); + + /** + * lastIndexOf helper. + */ + + function lastIndexOf(arr, obj) { + var i = arr.length; + while (i--) { + if (arr[i] === obj) return i; + } + return -1; + } + + /** + * The relative require() itself. + */ + + function localRequire(path) { + var resolved = localRequire.resolve(path); + return require(resolved, parent, path); + } + + /** + * Resolve relative to the parent. + */ + + localRequire.resolve = function(path) { + var c = path.charAt(0); + if ('/' == c) return path.slice(1); + if ('.' == c) return require.normalize(p, path); + + // resolve deps by returning + // the dep in the nearest "deps" + // directory + var segs = parent.split('/'); + var i = lastIndexOf(segs, 'deps') + 1; + if (!i) i = 0; + path = segs.slice(0, i + 1).join('/') + '/deps/' + path; + return path; + }; + + /** + * Check if module is defined at `path`. + */ + + localRequire.exists = function(path) { + return require.modules.hasOwnProperty(localRequire.resolve(path)); + }; + + return localRequire; +}; +require.register("component-emitter/index.js", function(exports, require, module){ + +/** + * Expose `Emitter`. + */ + +module.exports = Emitter; + +/** + * Initialize a new `Emitter`. + * + * @api public + */ + +function Emitter(obj) { + if (obj) return mixin(obj); +}; + +/** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + +function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; +} + +/** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.on = function(event, fn){ + this._callbacks = this._callbacks || {}; + (this._callbacks[event] = this._callbacks[event] || []) + .push(fn); + return this; +}; + +/** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.once = function(event, fn){ + var self = this; + this._callbacks = this._callbacks || {}; + + function on() { + self.off(event, on); + fn.apply(this, arguments); + } + + fn._off = on; + this.on(event, on); + return this; +}; + +/** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + +Emitter.prototype.off = +Emitter.prototype.removeListener = +Emitter.prototype.removeAllListeners = function(event, fn){ + this._callbacks = this._callbacks || {}; + var callbacks = this._callbacks[event]; + if (!callbacks) return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks[event]; + return this; + } + + // remove specific handler + var i = callbacks.indexOf(fn._off || fn); + if (~i) callbacks.splice(i, 1); + return this; +}; + +/** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + +Emitter.prototype.emit = function(event){ + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks[event]; + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; +}; + +/** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + +Emitter.prototype.listeners = function(event){ + this._callbacks = this._callbacks || {}; + return this._callbacks[event] || []; +}; + +/** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + +Emitter.prototype.hasListeners = function(event){ + return !! this.listeners(event).length; +}; + +}); +require.register("dropzone/index.js", function(exports, require, module){ + + +/** + * Exposing dropzone + */ +module.exports = require("./lib/dropzone.js"); + +}); +require.register("dropzone/lib/dropzone.js", function(exports, require, module){ +/* +# +# More info at [www.dropzonejs.com](http://www.dropzonejs.com) +# +# Copyright (c) 2012, Matias Meno +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# +*/ + + +(function() { + var Dropzone, Em, camelize, contentLoaded, detectVerticalSquash, drawImageIOSFix, noop, without, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, + __slice = [].slice; + + Em = typeof Emitter !== "undefined" && Emitter !== null ? Emitter : require("emitter"); + + noop = function() {}; + + Dropzone = (function(_super) { + var extend; + + __extends(Dropzone, _super); + + /* + This is a list of all available events you can register on a dropzone object. + + You can register an event handler like this: + + dropzone.on("dragEnter", function() { }); + */ + + + Dropzone.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached"]; + + Dropzone.prototype.defaultOptions = { + url: null, + method: "post", + withCredentials: false, + parallelUploads: 2, + uploadMultiple: false, + maxFilesize: 256, + paramName: "file", + createImageThumbnails: true, + maxThumbnailFilesize: 10, + thumbnailWidth: 100, + thumbnailHeight: 100, + maxFiles: null, + params: {}, + clickable: true, + ignoreHiddenFiles: true, + acceptedFiles: null, + acceptedMimeTypes: null, + autoProcessQueue: true, + addRemoveLinks: false, + previewsContainer: null, + dictDefaultMessage: "Drop files here to upload", + dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.", + dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.", + dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.", + dictInvalidFileType: "You can't upload files of this type.", + dictResponseError: "Server responded with {{statusCode}} code.", + dictCancelUpload: "Cancel upload", + dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?", + dictRemoveFile: "Remove file", + dictRemoveFileConfirmation: null, + dictMaxFilesExceeded: "You can not upload any more files.", + accept: function(file, done) { + return done(); + }, + init: function() { + return noop; + }, + forceFallback: false, + fallback: function() { + var child, messageElement, span, _i, _len, _ref; + this.element.className = "" + this.element.className + " dz-browser-not-supported"; + _ref = this.element.getElementsByTagName("div"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + if (/(^| )dz-message($| )/.test(child.className)) { + messageElement = child; + child.className = "dz-message"; + continue; + } + } + if (!messageElement) { + messageElement = Dropzone.createElement("<div class=\"dz-message\"><span></span></div>"); + this.element.appendChild(messageElement); + } + span = messageElement.getElementsByTagName("span")[0]; + if (span) { + span.textContent = this.options.dictFallbackMessage; + } + return this.element.appendChild(this.getFallbackForm()); + }, + resize: function(file) { + var info, srcRatio, trgRatio; + info = { + srcX: 0, + srcY: 0, + srcWidth: file.width, + srcHeight: file.height + }; + srcRatio = file.width / file.height; + trgRatio = this.options.thumbnailWidth / this.options.thumbnailHeight; + if (file.height < this.options.thumbnailHeight || file.width < this.options.thumbnailWidth) { + info.trgHeight = info.srcHeight; + info.trgWidth = info.srcWidth; + } else { + if (srcRatio > trgRatio) { + info.srcHeight = file.height; + info.srcWidth = info.srcHeight * trgRatio; + } else { + info.srcWidth = file.width; + info.srcHeight = info.srcWidth / trgRatio; + } + } + info.srcX = (file.width - info.srcWidth) / 2; + info.srcY = (file.height - info.srcHeight) / 2; + return info; + }, + /* + Those functions register themselves to the events on init and handle all + the user interface specific stuff. Overwriting them won't break the upload + but can break the way it's displayed. + You can overwrite them if you don't like the default behavior. If you just + want to add an additional event handler, register it on the dropzone object + and don't overwrite those options. + */ + + drop: function(e) { + return this.element.classList.remove("dz-drag-hover"); + }, + dragstart: noop, + dragend: function(e) { + return this.element.classList.remove("dz-drag-hover"); + }, + dragenter: function(e) { + return this.element.classList.add("dz-drag-hover"); + }, + dragover: function(e) { + return this.element.classList.add("dz-drag-hover"); + }, + dragleave: function(e) { + return this.element.classList.remove("dz-drag-hover"); + }, + paste: noop, + reset: function() { + return this.element.classList.remove("dz-started"); + }, + addedfile: function(file) { + var node, removeFileEvent, removeLink, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results, + _this = this; + if (this.element === this.previewsContainer) { + this.element.classList.add("dz-started"); + } + file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim()); + file.previewTemplate = file.previewElement; + this.previewsContainer.appendChild(file.previewElement); + _ref = file.previewElement.querySelectorAll("[data-dz-name]"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + node.textContent = file.name; + } + _ref1 = file.previewElement.querySelectorAll("[data-dz-size]"); + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + node = _ref1[_j]; + node.innerHTML = this.filesize(file.size); + } + if (this.options.addRemoveLinks) { + file._removeLink = Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>" + this.options.dictRemoveFile + "</a>"); + file.previewElement.appendChild(file._removeLink); + } + removeFileEvent = function(e) { + e.preventDefault(); + e.stopPropagation(); + if (file.status === Dropzone.UPLOADING) { + return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() { + return _this.removeFile(file); + }); + } else { + if (_this.options.dictRemoveFileConfirmation) { + return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() { + return _this.removeFile(file); + }); + } else { + return _this.removeFile(file); + } + } + }; + _ref2 = file.previewElement.querySelectorAll("[data-dz-remove]"); + _results = []; + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + removeLink = _ref2[_k]; + _results.push(removeLink.addEventListener("click", removeFileEvent)); + } + return _results; + }, + removedfile: function(file) { + var _ref; + if ((_ref = file.previewElement) != null) { + _ref.parentNode.removeChild(file.previewElement); + } + return this._updateMaxFilesReachedClass(); + }, + thumbnail: function(file, dataUrl) { + var thumbnailElement, _i, _len, _ref, _results; + file.previewElement.classList.remove("dz-file-preview"); + file.previewElement.classList.add("dz-image-preview"); + _ref = file.previewElement.querySelectorAll("[data-dz-thumbnail]"); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + thumbnailElement = _ref[_i]; + thumbnailElement.alt = file.name; + _results.push(thumbnailElement.src = dataUrl); + } + return _results; + }, + error: function(file, message) { + var node, _i, _len, _ref, _results; + file.previewElement.classList.add("dz-error"); + if (typeof message !== "String" && message.error) { + message = message.error; + } + _ref = file.previewElement.querySelectorAll("[data-dz-errormessage]"); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + _results.push(node.textContent = message); + } + return _results; + }, + errormultiple: noop, + processing: function(file) { + file.previewElement.classList.add("dz-processing"); + if (file._removeLink) { + return file._removeLink.textContent = this.options.dictCancelUpload; + } + }, + processingmultiple: noop, + uploadprogress: function(file, progress, bytesSent) { + var node, _i, _len, _ref, _results; + _ref = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + _results.push(node.style.width = "" + progress + "%"); + } + return _results; + }, + totaluploadprogress: noop, + sending: noop, + sendingmultiple: noop, + success: function(file) { + return file.previewElement.classList.add("dz-success"); + }, + successmultiple: noop, + canceled: function(file) { + return this.emit("error", file, "Upload canceled."); + }, + canceledmultiple: noop, + complete: function(file) { + if (file._removeLink) { + return file._removeLink.textContent = this.options.dictRemoveFile; + } + }, + completemultiple: noop, + maxfilesexceeded: noop, + maxfilesreached: noop, + previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n <div class=\"dz-details\">\n <div class=\"dz-filename\"><span data-dz-name></span></div>\n <div class=\"dz-size\" data-dz-size></div>\n <img data-dz-thumbnail />\n </div>\n <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n <div class=\"dz-success-mark\"><span>✔</span></div>\n <div class=\"dz-error-mark\"><span>✘</span></div>\n <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n</div>" + }; + + extend = function() { + var key, object, objects, target, val, _i, _len; + target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + for (_i = 0, _len = objects.length; _i < _len; _i++) { + object = objects[_i]; + for (key in object) { + val = object[key]; + target[key] = val; + } + } + return target; + }; + + function Dropzone(element, options) { + var elementOptions, fallback, _ref; + this.element = element; + this.version = Dropzone.version; + this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\n*/g, ""); + this.clickableElements = []; + this.listeners = []; + this.files = []; + if (typeof this.element === "string") { + this.element = document.querySelector(this.element); + } + if (!(this.element && (this.element.nodeType != null))) { + throw new Error("Invalid dropzone element."); + } + if (this.element.dropzone) { + throw new Error("Dropzone already attached."); + } + Dropzone.instances.push(this); + this.element.dropzone = this; + elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {}; + this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {}); + if (this.options.forceFallback || !Dropzone.isBrowserSupported()) { + return this.options.fallback.call(this); + } + if (this.options.url == null) { + this.options.url = this.element.getAttribute("action"); + } + if (!this.options.url) { + throw new Error("No URL provided."); + } + if (this.options.acceptedFiles && this.options.acceptedMimeTypes) { + throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated."); + } + if (this.options.acceptedMimeTypes) { + this.options.acceptedFiles = this.options.acceptedMimeTypes; + delete this.options.acceptedMimeTypes; + } + this.options.method = this.options.method.toUpperCase(); + if ((fallback = this.getExistingFallback()) && fallback.parentNode) { + fallback.parentNode.removeChild(fallback); + } + if (this.options.previewsContainer) { + this.previewsContainer = Dropzone.getElement(this.options.previewsContainer, "previewsContainer"); + } else { + this.previewsContainer = this.element; + } + if (this.options.clickable) { + if (this.options.clickable === true) { + this.clickableElements = [this.element]; + } else { + this.clickableElements = Dropzone.getElements(this.options.clickable, "clickable"); + } + } + this.init(); + } + + Dropzone.prototype.getAcceptedFiles = function() { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.accepted) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.getRejectedFiles = function() { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (!file.accepted) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.getQueuedFiles = function() { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.status === Dropzone.QUEUED) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.getUploadingFiles = function() { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.status === Dropzone.UPLOADING) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.init = function() { + var eventName, noPropagation, setupHiddenFileInput, _i, _len, _ref, _ref1, + _this = this; + if (this.element.tagName === "form") { + this.element.setAttribute("enctype", "multipart/form-data"); + } + if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) { + this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><span>" + this.options.dictDefaultMessage + "</span></div>")); + } + if (this.clickableElements.length) { + setupHiddenFileInput = function() { + if (_this.hiddenFileInput) { + document.body.removeChild(_this.hiddenFileInput); + } + _this.hiddenFileInput = document.createElement("input"); + _this.hiddenFileInput.setAttribute("type", "file"); + if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) { + _this.hiddenFileInput.setAttribute("multiple", "multiple"); + } + if (_this.options.acceptedFiles != null) { + _this.hiddenFileInput.setAttribute("accept", _this.options.acceptedFiles); + } + _this.hiddenFileInput.style.visibility = "hidden"; + _this.hiddenFileInput.style.position = "absolute"; + _this.hiddenFileInput.style.top = "0"; + _this.hiddenFileInput.style.left = "0"; + _this.hiddenFileInput.style.height = "0"; + _this.hiddenFileInput.style.width = "0"; + document.body.appendChild(_this.hiddenFileInput); + return _this.hiddenFileInput.addEventListener("change", function() { + var file, files, _i, _len; + files = _this.hiddenFileInput.files; + if (files.length) { + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + _this.addFile(file); + } + } + return setupHiddenFileInput(); + }); + }; + setupHiddenFileInput(); + } + this.URL = (_ref = window.URL) != null ? _ref : window.webkitURL; + _ref1 = this.events; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + eventName = _ref1[_i]; + this.on(eventName, this.options[eventName]); + } + this.on("uploadprogress", function() { + return _this.updateTotalUploadProgress(); + }); + this.on("removedfile", function() { + return _this.updateTotalUploadProgress(); + }); + this.on("canceled", function(file) { + return _this.emit("complete", file); + }); + this.on("complete", function(file) { + if (_this.getUploadingFiles().length === 0 && _this.getQueuedFiles().length === 0) { + return setTimeout((function() { + return _this.emit("queuecomplete"); + }), 0); + } + }); + noPropagation = function(e) { + e.stopPropagation(); + if (e.preventDefault) { + return e.preventDefault(); + } else { + return e.returnValue = false; + } + }; + this.listeners = [ + { + element: this.element, + events: { + "dragstart": function(e) { + return _this.emit("dragstart", e); + }, + "dragenter": function(e) { + noPropagation(e); + return _this.emit("dragenter", e); + }, + "dragover": function(e) { + var efct; + try { + efct = e.dataTransfer.effectAllowed; + } catch (_error) {} + e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; + noPropagation(e); + return _this.emit("dragover", e); + }, + "dragleave": function(e) { + return _this.emit("dragleave", e); + }, + "drop": function(e) { + noPropagation(e); + return _this.drop(e); + }, + "dragend": function(e) { + return _this.emit("dragend", e); + } + } + } + ]; + this.clickableElements.forEach(function(clickableElement) { + return _this.listeners.push({ + element: clickableElement, + events: { + "click": function(evt) { + if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(".dz-message")))) { + return _this.hiddenFileInput.click(); + } + } + } + }); + }); + this.enable(); + return this.options.init.call(this); + }; + + Dropzone.prototype.destroy = function() { + var _ref; + this.disable(); + this.removeAllFiles(true); + if ((_ref = this.hiddenFileInput) != null ? _ref.parentNode : void 0) { + this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput); + this.hiddenFileInput = null; + } + delete this.element.dropzone; + return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1); + }; + + Dropzone.prototype.updateTotalUploadProgress = function() { + var acceptedFiles, file, totalBytes, totalBytesSent, totalUploadProgress, _i, _len, _ref; + totalBytesSent = 0; + totalBytes = 0; + acceptedFiles = this.getAcceptedFiles(); + if (acceptedFiles.length) { + _ref = this.getAcceptedFiles(); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + totalBytesSent += file.upload.bytesSent; + totalBytes += file.upload.total; + } + totalUploadProgress = 100 * totalBytesSent / totalBytes; + } else { + totalUploadProgress = 100; + } + return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent); + }; + + Dropzone.prototype.getFallbackForm = function() { + var existingFallback, fields, fieldsString, form; + if (existingFallback = this.getExistingFallback()) { + return existingFallback; + } + fieldsString = "<div class=\"dz-fallback\">"; + if (this.options.dictFallbackText) { + fieldsString += "<p>" + this.options.dictFallbackText + "</p>"; + } + fieldsString += "<input type=\"file\" name=\"" + this.options.paramName + (this.options.uploadMultiple ? "[]" : "") + "\" " + (this.options.uploadMultiple ? 'multiple="multiple"' : void 0) + " /><input type=\"submit\" value=\"Upload!\"></div>"; + fields = Dropzone.createElement(fieldsString); + if (this.element.tagName !== "FORM") { + form = Dropzone.createElement("<form action=\"" + this.options.url + "\" enctype=\"multipart/form-data\" method=\"" + this.options.method + "\"></form>"); + form.appendChild(fields); + } else { + this.element.setAttribute("enctype", "multipart/form-data"); + this.element.setAttribute("method", this.options.method); + } + return form != null ? form : fields; + }; + + Dropzone.prototype.getExistingFallback = function() { + var fallback, getFallback, tagName, _i, _len, _ref; + getFallback = function(elements) { + var el, _i, _len; + for (_i = 0, _len = elements.length; _i < _len; _i++) { + el = elements[_i]; + if (/(^| )fallback($| )/.test(el.className)) { + return el; + } + } + }; + _ref = ["div", "form"]; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + tagName = _ref[_i]; + if (fallback = getFallback(this.element.getElementsByTagName(tagName))) { + return fallback; + } + } + }; + + Dropzone.prototype.setupEventListeners = function() { + var elementListeners, event, listener, _i, _len, _ref, _results; + _ref = this.listeners; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + elementListeners = _ref[_i]; + _results.push((function() { + var _ref1, _results1; + _ref1 = elementListeners.events; + _results1 = []; + for (event in _ref1) { + listener = _ref1[event]; + _results1.push(elementListeners.element.addEventListener(event, listener, false)); + } + return _results1; + })()); + } + return _results; + }; + + Dropzone.prototype.removeEventListeners = function() { + var elementListeners, event, listener, _i, _len, _ref, _results; + _ref = this.listeners; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + elementListeners = _ref[_i]; + _results.push((function() { + var _ref1, _results1; + _ref1 = elementListeners.events; + _results1 = []; + for (event in _ref1) { + listener = _ref1[event]; + _results1.push(elementListeners.element.removeEventListener(event, listener, false)); + } + return _results1; + })()); + } + return _results; + }; + + Dropzone.prototype.disable = function() { + var file, _i, _len, _ref, _results; + this.clickableElements.forEach(function(element) { + return element.classList.remove("dz-clickable"); + }); + this.removeEventListeners(); + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + _results.push(this.cancelUpload(file)); + } + return _results; + }; + + Dropzone.prototype.enable = function() { + this.clickableElements.forEach(function(element) { + return element.classList.add("dz-clickable"); + }); + return this.setupEventListeners(); + }; + + Dropzone.prototype.filesize = function(size) { + var string; + if (size >= 1024 * 1024 * 1024 * 1024 / 10) { + size = size / (1024 * 1024 * 1024 * 1024 / 10); + string = "TiB"; + } else if (size >= 1024 * 1024 * 1024 / 10) { + size = size / (1024 * 1024 * 1024 / 10); + string = "GiB"; + } else if (size >= 1024 * 1024 / 10) { + size = size / (1024 * 1024 / 10); + string = "MiB"; + } else if (size >= 1024 / 10) { + size = size / (1024 / 10); + string = "KiB"; + } else { + size = size * 10; + string = "b"; + } + return "<strong>" + (Math.round(size) / 10) + "</strong> " + string; + }; + + Dropzone.prototype._updateMaxFilesReachedClass = function() { + if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) { + if (this.getAcceptedFiles().length === this.options.maxFiles) { + this.emit('maxfilesreached', this.files); + } + return this.element.classList.add("dz-max-files-reached"); + } else { + return this.element.classList.remove("dz-max-files-reached"); + } + }; + + Dropzone.prototype.drop = function(e) { + var files, items; + if (!e.dataTransfer) { + return; + } + this.emit("drop", e); + files = e.dataTransfer.files; + if (files.length) { + items = e.dataTransfer.items; + if (items && items.length && (items[0].webkitGetAsEntry != null)) { + this._addFilesFromItems(items); + } else { + this.handleFiles(files); + } + } + }; + + Dropzone.prototype.paste = function(e) { + var items, _ref; + if ((e != null ? (_ref = e.clipboardData) != null ? _ref.items : void 0 : void 0) == null) { + return; + } + this.emit("paste", e); + items = e.clipboardData.items; + if (items.length) { + return this._addFilesFromItems(items); + } + }; + + Dropzone.prototype.handleFiles = function(files) { + var file, _i, _len, _results; + _results = []; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + _results.push(this.addFile(file)); + } + return _results; + }; + + Dropzone.prototype._addFilesFromItems = function(items) { + var entry, item, _i, _len, _results; + _results = []; + for (_i = 0, _len = items.length; _i < _len; _i++) { + item = items[_i]; + if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) { + if (entry.isFile) { + _results.push(this.addFile(item.getAsFile())); + } else if (entry.isDirectory) { + _results.push(this._addFilesFromDirectory(entry, entry.name)); + } else { + _results.push(void 0); + } + } else if (item.getAsFile != null) { + if ((item.kind == null) || item.kind === "file") { + _results.push(this.addFile(item.getAsFile())); + } else { + _results.push(void 0); + } + } else { + _results.push(void 0); + } + } + return _results; + }; + + Dropzone.prototype._addFilesFromDirectory = function(directory, path) { + var dirReader, entriesReader, + _this = this; + dirReader = directory.createReader(); + entriesReader = function(entries) { + var entry, _i, _len; + for (_i = 0, _len = entries.length; _i < _len; _i++) { + entry = entries[_i]; + if (entry.isFile) { + entry.file(function(file) { + if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') { + return; + } + file.fullPath = "" + path + "/" + file.name; + return _this.addFile(file); + }); + } else if (entry.isDirectory) { + _this._addFilesFromDirectory(entry, "" + path + "/" + entry.name); + } + } + }; + return dirReader.readEntries(entriesReader, function(error) { + return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(error) : void 0 : void 0; + }); + }; + + Dropzone.prototype.accept = function(file, done) { + if (file.size > this.options.maxFilesize * 1024 * 1024) { + return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize)); + } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) { + return done(this.options.dictInvalidFileType); + } else if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) { + done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles)); + return this.emit("maxfilesexceeded", file); + } else { + return this.options.accept.call(this, file, done); + } + }; + + Dropzone.prototype.addFile = function(file) { + var _this = this; + file.upload = { + progress: 0, + total: file.size, + bytesSent: 0 + }; + this.files.push(file); + file.status = Dropzone.ADDED; + this.emit("addedfile", file); + this._enqueueThumbnail(file); + return this.accept(file, function(error) { + if (error) { + file.accepted = false; + _this._errorProcessing([file], error); + } else { + _this.enqueueFile(file); + } + return _this._updateMaxFilesReachedClass(); + }); + }; + + Dropzone.prototype.enqueueFiles = function(files) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + this.enqueueFile(file); + } + return null; + }; + + Dropzone.prototype.enqueueFile = function(file) { + var _this = this; + file.accepted = true; + if (file.status === Dropzone.ADDED) { + file.status = Dropzone.QUEUED; + if (this.options.autoProcessQueue) { + return setTimeout((function() { + return _this.processQueue(); + }), 0); + } + } else { + throw new Error("This file can't be queued because it has already been processed or was rejected."); + } + }; + + Dropzone.prototype._thumbnailQueue = []; + + Dropzone.prototype._processingThumbnail = false; + + Dropzone.prototype._enqueueThumbnail = function(file) { + var _this = this; + if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) { + this._thumbnailQueue.push(file); + return setTimeout((function() { + return _this._processThumbnailQueue(); + }), 0); + } + }; + + Dropzone.prototype._processThumbnailQueue = function() { + var _this = this; + if (this._processingThumbnail || this._thumbnailQueue.length === 0) { + return; + } + this._processingThumbnail = true; + return this.createThumbnail(this._thumbnailQueue.shift(), function() { + _this._processingThumbnail = false; + return _this._processThumbnailQueue(); + }); + }; + + Dropzone.prototype.removeFile = function(file) { + if (file.status === Dropzone.UPLOADING) { + this.cancelUpload(file); + } + this.files = without(this.files, file); + this.emit("removedfile", file); + if (this.files.length === 0) { + return this.emit("reset"); + } + }; + + Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) { + var file, _i, _len, _ref; + if (cancelIfNecessary == null) { + cancelIfNecessary = false; + } + _ref = this.files.slice(); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) { + this.removeFile(file); + } + } + return null; + }; + + Dropzone.prototype.createThumbnail = function(file, callback) { + var fileReader, + _this = this; + fileReader = new FileReader; + fileReader.onload = function() { + var img; + img = document.createElement("img"); + img.onload = function() { + var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3; + file.width = img.width; + file.height = img.height; + resizeInfo = _this.options.resize.call(_this, file); + if (resizeInfo.trgWidth == null) { + resizeInfo.trgWidth = _this.options.thumbnailWidth; + } + if (resizeInfo.trgHeight == null) { + resizeInfo.trgHeight = _this.options.thumbnailHeight; + } + canvas = document.createElement("canvas"); + ctx = canvas.getContext("2d"); + canvas.width = resizeInfo.trgWidth; + canvas.height = resizeInfo.trgHeight; + drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight); + thumbnail = canvas.toDataURL("image/png"); + _this.emit("thumbnail", file, thumbnail); + if (callback != null) { + return callback(); + } + }; + return img.src = fileReader.result; + }; + return fileReader.readAsDataURL(file); + }; + + Dropzone.prototype.processQueue = function() { + var i, parallelUploads, processingLength, queuedFiles; + parallelUploads = this.options.parallelUploads; + processingLength = this.getUploadingFiles().length; + i = processingLength; + if (processingLength >= parallelUploads) { + return; + } + queuedFiles = this.getQueuedFiles(); + if (!(queuedFiles.length > 0)) { + return; + } + if (this.options.uploadMultiple) { + return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength)); + } else { + while (i < parallelUploads) { + if (!queuedFiles.length) { + return; + } + this.processFile(queuedFiles.shift()); + i++; + } + } + }; + + Dropzone.prototype.processFile = function(file) { + return this.processFiles([file]); + }; + + Dropzone.prototype.processFiles = function(files) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + file.processing = true; + file.status = Dropzone.UPLOADING; + this.emit("processing", file); + } + if (this.options.uploadMultiple) { + this.emit("processingmultiple", files); + } + return this.uploadFiles(files); + }; + + Dropzone.prototype._getFilesWithXhr = function(xhr) { + var file, files; + return files = (function() { + var _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.xhr === xhr) { + _results.push(file); + } + } + return _results; + }).call(this); + }; + + Dropzone.prototype.cancelUpload = function(file) { + var groupedFile, groupedFiles, _i, _j, _len, _len1, _ref; + if (file.status === Dropzone.UPLOADING) { + groupedFiles = this._getFilesWithXhr(file.xhr); + for (_i = 0, _len = groupedFiles.length; _i < _len; _i++) { + groupedFile = groupedFiles[_i]; + groupedFile.status = Dropzone.CANCELED; + } + file.xhr.abort(); + for (_j = 0, _len1 = groupedFiles.length; _j < _len1; _j++) { + groupedFile = groupedFiles[_j]; + this.emit("canceled", groupedFile); + } + if (this.options.uploadMultiple) { + this.emit("canceledmultiple", groupedFiles); + } + } else if ((_ref = file.status) === Dropzone.ADDED || _ref === Dropzone.QUEUED) { + file.status = Dropzone.CANCELED; + this.emit("canceled", file); + if (this.options.uploadMultiple) { + this.emit("canceledmultiple", [file]); + } + } + if (this.options.autoProcessQueue) { + return this.processQueue(); + } + }; + + Dropzone.prototype.uploadFile = function(file) { + return this.uploadFiles([file]); + }; + + Dropzone.prototype.uploadFiles = function(files) { + var file, formData, handleError, headerName, headerValue, headers, input, inputName, inputType, key, option, progressObj, response, updateProgress, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4, + _this = this; + xhr = new XMLHttpRequest(); + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + file.xhr = xhr; + } + xhr.open(this.options.method, this.options.url, true); + xhr.withCredentials = !!this.options.withCredentials; + response = null; + handleError = function() { + var _j, _len1, _results; + _results = []; + for (_j = 0, _len1 = files.length; _j < _len1; _j++) { + file = files[_j]; + _results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr)); + } + return _results; + }; + updateProgress = function(e) { + var allFilesFinished, progress, _j, _k, _l, _len1, _len2, _len3, _results; + if (e != null) { + progress = 100 * e.loaded / e.total; + for (_j = 0, _len1 = files.length; _j < _len1; _j++) { + file = files[_j]; + file.upload = { + progress: progress, + total: e.total, + bytesSent: e.loaded + }; + } + } else { + allFilesFinished = true; + progress = 100; + for (_k = 0, _len2 = files.length; _k < _len2; _k++) { + file = files[_k]; + if (!(file.upload.progress === 100 && file.upload.bytesSent === file.upload.total)) { + allFilesFinished = false; + } + file.upload.progress = progress; + file.upload.bytesSent = file.upload.total; + } + if (allFilesFinished) { + return; + } + } + _results = []; + for (_l = 0, _len3 = files.length; _l < _len3; _l++) { + file = files[_l]; + _results.push(_this.emit("uploadprogress", file, progress, file.upload.bytesSent)); + } + return _results; + }; + xhr.onload = function(e) { + var _ref; + if (files[0].status === Dropzone.CANCELED) { + return; + } + if (xhr.readyState !== 4) { + return; + } + response = xhr.responseText; + if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) { + try { + response = JSON.parse(response); + } catch (_error) { + e = _error; + response = "Invalid JSON response from server."; + } + } + updateProgress(); + if (!((200 <= (_ref = xhr.status) && _ref < 300))) { + return handleError(); + } else { + return _this._finished(files, response, e); + } + }; + xhr.onerror = function() { + if (files[0].status === Dropzone.CANCELED) { + return; + } + return handleError(); + }; + progressObj = (_ref = xhr.upload) != null ? _ref : xhr; + progressObj.onprogress = updateProgress; + headers = { + "Accept": "application/json", + "Cache-Control": "no-cache", + "X-Requested-With": "XMLHttpRequest" + }; + if (this.options.headers) { + extend(headers, this.options.headers); + } + for (headerName in headers) { + headerValue = headers[headerName]; + xhr.setRequestHeader(headerName, headerValue); + } + formData = new FormData(); + if (this.options.params) { + _ref1 = this.options.params; + for (key in _ref1) { + value = _ref1[key]; + formData.append(key, value); + } + } + for (_j = 0, _len1 = files.length; _j < _len1; _j++) { + file = files[_j]; + this.emit("sending", file, xhr, formData); + } + if (this.options.uploadMultiple) { + this.emit("sendingmultiple", files, xhr, formData); + } + if (this.element.tagName === "FORM") { + _ref2 = this.element.querySelectorAll("input, textarea, select, button"); + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + input = _ref2[_k]; + inputName = input.getAttribute("name"); + inputType = input.getAttribute("type"); + if (input.tagName === "SELECT" && input.hasAttribute("multiple")) { + _ref3 = input.options; + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + option = _ref3[_l]; + if (option.selected) { + formData.append(inputName, option.value); + } + } + } else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== "checkbox" && _ref4 !== "radio") || input.checked) { + formData.append(inputName, input.value); + } + } + } + for (_m = 0, _len4 = files.length; _m < _len4; _m++) { + file = files[_m]; + formData.append("" + this.options.paramName + (this.options.uploadMultiple ? "[]" : ""), file, file.name); + } + return xhr.send(formData); + }; + + Dropzone.prototype._finished = function(files, responseText, e) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + file.status = Dropzone.SUCCESS; + this.emit("success", file, responseText, e); + this.emit("complete", file); + } + if (this.options.uploadMultiple) { + this.emit("successmultiple", files, responseText, e); + this.emit("completemultiple", files); + } + if (this.options.autoProcessQueue) { + return this.processQueue(); + } + }; + + Dropzone.prototype._errorProcessing = function(files, message, xhr) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + file.status = Dropzone.ERROR; + this.emit("error", file, message, xhr); + this.emit("complete", file); + } + if (this.options.uploadMultiple) { + this.emit("errormultiple", files, message, xhr); + this.emit("completemultiple", files); + } + if (this.options.autoProcessQueue) { + return this.processQueue(); + } + }; + + return Dropzone; + + })(Em); + + Dropzone.version = "3.8.4"; + + Dropzone.options = {}; + + Dropzone.optionsForElement = function(element) { + if (element.getAttribute("id")) { + return Dropzone.options[camelize(element.getAttribute("id"))]; + } else { + return void 0; + } + }; + + Dropzone.instances = []; + + Dropzone.forElement = function(element) { + if (typeof element === "string") { + element = document.querySelector(element); + } + if ((element != null ? element.dropzone : void 0) == null) { + throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone."); + } + return element.dropzone; + }; + + Dropzone.autoDiscover = true; + + Dropzone.discover = function() { + var checkElements, dropzone, dropzones, _i, _len, _results; + if (document.querySelectorAll) { + dropzones = document.querySelectorAll(".dropzone"); + } else { + dropzones = []; + checkElements = function(elements) { + var el, _i, _len, _results; + _results = []; + for (_i = 0, _len = elements.length; _i < _len; _i++) { + el = elements[_i]; + if (/(^| )dropzone($| )/.test(el.className)) { + _results.push(dropzones.push(el)); + } else { + _results.push(void 0); + } + } + return _results; + }; + checkElements(document.getElementsByTagName("div")); + checkElements(document.getElementsByTagName("form")); + } + _results = []; + for (_i = 0, _len = dropzones.length; _i < _len; _i++) { + dropzone = dropzones[_i]; + if (Dropzone.optionsForElement(dropzone) !== false) { + _results.push(new Dropzone(dropzone)); + } else { + _results.push(void 0); + } + } + return _results; + }; + + Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\/12/i]; + + Dropzone.isBrowserSupported = function() { + var capableBrowser, regex, _i, _len, _ref; + capableBrowser = true; + if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) { + if (!("classList" in document.createElement("a"))) { + capableBrowser = false; + } else { + _ref = Dropzone.blacklistedBrowsers; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + regex = _ref[_i]; + if (regex.test(navigator.userAgent)) { + capableBrowser = false; + continue; + } + } + } + } else { + capableBrowser = false; + } + return capableBrowser; + }; + + without = function(list, rejectedItem) { + var item, _i, _len, _results; + _results = []; + for (_i = 0, _len = list.length; _i < _len; _i++) { + item = list[_i]; + if (item !== rejectedItem) { + _results.push(item); + } + } + return _results; + }; + + camelize = function(str) { + return str.replace(/[\-_](\w)/g, function(match) { + return match[1].toUpperCase(); + }); + }; + + Dropzone.createElement = function(string) { + var div; + div = document.createElement("div"); + div.innerHTML = string; + return div.childNodes[0]; + }; + + Dropzone.elementInside = function(element, container) { + if (element === container) { + return true; + } + while (element = element.parentNode) { + if (element === container) { + return true; + } + } + return false; + }; + + Dropzone.getElement = function(el, name) { + var element; + if (typeof el === "string") { + element = document.querySelector(el); + } else if (el.nodeType != null) { + element = el; + } + if (element == null) { + throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element."); + } + return element; + }; + + Dropzone.getElements = function(els, name) { + var e, el, elements, _i, _j, _len, _len1, _ref; + if (els instanceof Array) { + elements = []; + try { + for (_i = 0, _len = els.length; _i < _len; _i++) { + el = els[_i]; + elements.push(this.getElement(el, name)); + } + } catch (_error) { + e = _error; + elements = null; + } + } else if (typeof els === "string") { + elements = []; + _ref = document.querySelectorAll(els); + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + el = _ref[_j]; + elements.push(el); + } + } else if (els.nodeType != null) { + elements = [els]; + } + if (!((elements != null) && elements.length)) { + throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those."); + } + return elements; + }; + + Dropzone.confirm = function(question, accepted, rejected) { + if (window.confirm(question)) { + return accepted(); + } else if (rejected != null) { + return rejected(); + } + }; + + Dropzone.isValidFile = function(file, acceptedFiles) { + var baseMimeType, mimeType, validType, _i, _len; + if (!acceptedFiles) { + return true; + } + acceptedFiles = acceptedFiles.split(","); + mimeType = file.type; + baseMimeType = mimeType.replace(/\/.*$/, ""); + for (_i = 0, _len = acceptedFiles.length; _i < _len; _i++) { + validType = acceptedFiles[_i]; + validType = validType.trim(); + if (validType.charAt(0) === ".") { + if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) { + return true; + } + } else if (/\/\*$/.test(validType)) { + if (baseMimeType === validType.replace(/\/.*$/, "")) { + return true; + } + } else { + if (mimeType === validType) { + return true; + } + } + } + return false; + }; + + if (typeof jQuery !== "undefined" && jQuery !== null) { + jQuery.fn.dropzone = function(options) { + return this.each(function() { + return new Dropzone(this, options); + }); + }; + } + + if (typeof module !== "undefined" && module !== null) { + module.exports = Dropzone; + } else { + window.Dropzone = Dropzone; + } + + Dropzone.ADDED = "added"; + + Dropzone.QUEUED = "queued"; + + Dropzone.ACCEPTED = Dropzone.QUEUED; + + Dropzone.UPLOADING = "uploading"; + + Dropzone.PROCESSING = Dropzone.UPLOADING; + + Dropzone.CANCELED = "canceled"; + + Dropzone.ERROR = "error"; + + Dropzone.SUCCESS = "success"; + + /* + + Bugfix for iOS 6 and 7 + Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios + based on the work of https://github.com/stomita/ios-imagefile-megapixel + */ + + + detectVerticalSquash = function(img) { + var alpha, canvas, ctx, data, ey, ih, iw, py, ratio, sy; + iw = img.naturalWidth; + ih = img.naturalHeight; + canvas = document.createElement("canvas"); + canvas.width = 1; + canvas.height = ih; + ctx = canvas.getContext("2d"); + ctx.drawImage(img, 0, 0); + data = ctx.getImageData(0, 0, 1, ih).data; + sy = 0; + ey = ih; + py = ih; + while (py > sy) { + alpha = data[(py - 1) * 4 + 3]; + if (alpha === 0) { + ey = py; + } else { + sy = py; + } + py = (ey + sy) >> 1; + } + ratio = py / ih; + if (ratio === 0) { + return 1; + } else { + return ratio; + } + }; + + drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) { + var vertSquashRatio; + vertSquashRatio = detectVerticalSquash(img); + return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio); + }; + + /* + # contentloaded.js + # + # Author: Diego Perini (diego.perini at gmail.com) + # Summary: cross-browser wrapper for DOMContentLoaded + # Updated: 20101020 + # License: MIT + # Version: 1.2 + # + # URL: + # http://javascript.nwbox.com/ContentLoaded/ + # http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE + */ + + + contentLoaded = function(win, fn) { + var add, doc, done, init, poll, pre, rem, root, top; + done = false; + top = true; + doc = win.document; + root = doc.documentElement; + add = (doc.addEventListener ? "addEventListener" : "attachEvent"); + rem = (doc.addEventListener ? "removeEventListener" : "detachEvent"); + pre = (doc.addEventListener ? "" : "on"); + init = function(e) { + if (e.type === "readystatechange" && doc.readyState !== "complete") { + return; + } + (e.type === "load" ? win : doc)[rem](pre + e.type, init, false); + if (!done && (done = true)) { + return fn.call(win, e.type || e); + } + }; + poll = function() { + var e; + try { + root.doScroll("left"); + } catch (_error) { + e = _error; + setTimeout(poll, 50); + return; + } + return init("poll"); + }; + if (doc.readyState !== "complete") { + if (doc.createEventObject && root.doScroll) { + try { + top = !win.frameElement; + } catch (_error) {} + if (top) { + poll(); + } + } + doc[add](pre + "DOMContentLoaded", init, false); + doc[add](pre + "readystatechange", init, false); + return win[add](pre + "load", init, false); + } + }; + + Dropzone._autoDiscoverFunction = function() { + if (Dropzone.autoDiscover) { + return Dropzone.discover(); + } + }; + + contentLoaded(window, Dropzone._autoDiscoverFunction); + +}).call(this); + +}); +require.alias("component-emitter/index.js", "dropzone/deps/emitter/index.js"); +require.alias("component-emitter/index.js", "emitter/index.js"); +if (typeof exports == "object") { + module.exports = require("dropzone"); +} else if (typeof define == "function" && define.amd) { + define(function(){ return require("dropzone"); }); +} else { + this["Dropzone"] = require("dropzone"); +}})(); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/dropzone/dropzone.min.js b/src/core/classes/org/glizycms/js/jquery/dropzone/dropzone.min.js new file mode 100755 index 0000000..e4f438e --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/dropzone/dropzone.min.js @@ -0,0 +1 @@ +!function(){function a(b,c,d){var e=a.resolve(b);if(null==e){d=d||b,c=c||"root";var f=new Error('Failed to require "'+d+'" from "'+c+'"');throw f.path=d,f.parent=c,f.require=!0,f}var g=a.modules[e];if(!g._resolving&&!g.exports){var h={};h.exports={},h.client=h.component=!0,g._resolving=!0,g.call(this,h.exports,a.relative(e),h),delete g._resolving,g.exports=h.exports}return g.exports}a.modules={},a.aliases={},a.resolve=function(b){"/"===b.charAt(0)&&(b=b.slice(1));for(var c=[b,b+".js",b+".json",b+"/index.js",b+"/index.json"],d=0;d<c.length;d++){var b=c[d];if(a.modules.hasOwnProperty(b))return b;if(a.aliases.hasOwnProperty(b))return a.aliases[b]}},a.normalize=function(a,b){var c=[];if("."!=b.charAt(0))return b;a=a.split("/"),b=b.split("/");for(var d=0;d<b.length;++d)".."==b[d]?a.pop():"."!=b[d]&&""!=b[d]&&c.push(b[d]);return a.concat(c).join("/")},a.register=function(b,c){a.modules[b]=c},a.alias=function(b,c){if(!a.modules.hasOwnProperty(b))throw new Error('Failed to alias "'+b+'", it does not exist');a.aliases[c]=b},a.relative=function(b){function c(a,b){for(var c=a.length;c--;)if(a[c]===b)return c;return-1}function d(c){var e=d.resolve(c);return a(e,b,c)}var e=a.normalize(b,"..");return d.resolve=function(d){var f=d.charAt(0);if("/"==f)return d.slice(1);if("."==f)return a.normalize(e,d);var g=b.split("/"),h=c(g,"deps")+1;return h||(h=0),d=g.slice(0,h+1).join("/")+"/deps/"+d},d.exists=function(b){return a.modules.hasOwnProperty(d.resolve(b))},d},a.register("component-emitter/index.js",function(a,b,c){function d(a){return a?e(a):void 0}function e(a){for(var b in d.prototype)a[b]=d.prototype[b];return a}c.exports=d,d.prototype.on=function(a,b){return this._callbacks=this._callbacks||{},(this._callbacks[a]=this._callbacks[a]||[]).push(b),this},d.prototype.once=function(a,b){function c(){d.off(a,c),b.apply(this,arguments)}var d=this;return this._callbacks=this._callbacks||{},b._off=c,this.on(a,c),this},d.prototype.off=d.prototype.removeListener=d.prototype.removeAllListeners=function(a,b){this._callbacks=this._callbacks||{};var c=this._callbacks[a];if(!c)return this;if(1==arguments.length)return delete this._callbacks[a],this;var d=c.indexOf(b._off||b);return~d&&c.splice(d,1),this},d.prototype.emit=function(a){this._callbacks=this._callbacks||{};var b=[].slice.call(arguments,1),c=this._callbacks[a];if(c){c=c.slice(0);for(var d=0,e=c.length;e>d;++d)c[d].apply(this,b)}return this},d.prototype.listeners=function(a){return this._callbacks=this._callbacks||{},this._callbacks[a]||[]},d.prototype.hasListeners=function(a){return!!this.listeners(a).length}}),a.register("dropzone/index.js",function(a,b,c){c.exports=b("./lib/dropzone.js")}),a.register("dropzone/lib/dropzone.js",function(a,b,c){(function(){var a,d,e,f,g,h,i,j,k={}.hasOwnProperty,l=function(a,b){function c(){this.constructor=a}for(var d in b)k.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},m=[].slice;d="undefined"!=typeof Emitter&&null!==Emitter?Emitter:b("emitter"),i=function(){},a=function(a){function b(a,d){var e,f,g;if(this.element=a,this.version=b.version,this.defaultOptions.previewTemplate=this.defaultOptions.previewTemplate.replace(/\n*/g,""),this.clickableElements=[],this.listeners=[],this.files=[],"string"==typeof this.element&&(this.element=document.querySelector(this.element)),!this.element||null==this.element.nodeType)throw new Error("Invalid dropzone element.");if(this.element.dropzone)throw new Error("Dropzone already attached.");if(b.instances.push(this),this.element.dropzone=this,e=null!=(g=b.optionsForElement(this.element))?g:{},this.options=c({},this.defaultOptions,e,null!=d?d:{}),this.options.forceFallback||!b.isBrowserSupported())return this.options.fallback.call(this);if(null==this.options.url&&(this.options.url=this.element.getAttribute("action")),!this.options.url)throw new Error("No URL provided.");if(this.options.acceptedFiles&&this.options.acceptedMimeTypes)throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");this.options.acceptedMimeTypes&&(this.options.acceptedFiles=this.options.acceptedMimeTypes,delete this.options.acceptedMimeTypes),this.options.method=this.options.method.toUpperCase(),(f=this.getExistingFallback())&&f.parentNode&&f.parentNode.removeChild(f),this.previewsContainer=this.options.previewsContainer?b.getElement(this.options.previewsContainer,"previewsContainer"):this.element,this.options.clickable&&(this.clickableElements=this.options.clickable===!0?[this.element]:b.getElements(this.options.clickable,"clickable")),this.init()}var c;return l(b,a),b.prototype.events=["drop","dragstart","dragend","dragenter","dragover","dragleave","addedfile","removedfile","thumbnail","error","errormultiple","processing","processingmultiple","uploadprogress","totaluploadprogress","sending","sendingmultiple","success","successmultiple","canceled","canceledmultiple","complete","completemultiple","reset","maxfilesexceeded","maxfilesreached"],b.prototype.defaultOptions={url:null,method:"post",withCredentials:!1,parallelUploads:2,uploadMultiple:!1,maxFilesize:256,paramName:"file",createImageThumbnails:!0,maxThumbnailFilesize:10,thumbnailWidth:100,thumbnailHeight:100,maxFiles:null,params:{},clickable:!0,ignoreHiddenFiles:!0,acceptedFiles:null,acceptedMimeTypes:null,autoProcessQueue:!0,addRemoveLinks:!1,previewsContainer:null,dictDefaultMessage:"Drop files here to upload",dictFallbackMessage:"Your browser does not support drag'n'drop file uploads.",dictFallbackText:"Please use the fallback form below to upload your files like in the olden days.",dictFileTooBig:"File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",dictInvalidFileType:"You can't upload files of this type.",dictResponseError:"Server responded with {{statusCode}} code.",dictCancelUpload:"Cancel upload",dictCancelUploadConfirmation:"Are you sure you want to cancel this upload?",dictRemoveFile:"Remove file",dictRemoveFileConfirmation:null,dictMaxFilesExceeded:"You can not upload any more files.",accept:function(a,b){return b()},init:function(){return i},forceFallback:!1,fallback:function(){var a,c,d,e,f,g;for(this.element.className=""+this.element.className+" dz-browser-not-supported",g=this.element.getElementsByTagName("div"),e=0,f=g.length;f>e;e++)a=g[e],/(^| )dz-message($| )/.test(a.className)&&(c=a,a.className="dz-message");return c||(c=b.createElement('<div class="dz-message"><span></span></div>'),this.element.appendChild(c)),d=c.getElementsByTagName("span")[0],d&&(d.textContent=this.options.dictFallbackMessage),this.element.appendChild(this.getFallbackForm())},resize:function(a){var b,c,d;return b={srcX:0,srcY:0,srcWidth:a.width,srcHeight:a.height},c=a.width/a.height,d=this.options.thumbnailWidth/this.options.thumbnailHeight,a.height<this.options.thumbnailHeight||a.width<this.options.thumbnailWidth?(b.trgHeight=b.srcHeight,b.trgWidth=b.srcWidth):c>d?(b.srcHeight=a.height,b.srcWidth=b.srcHeight*d):(b.srcWidth=a.width,b.srcHeight=b.srcWidth/d),b.srcX=(a.width-b.srcWidth)/2,b.srcY=(a.height-b.srcHeight)/2,b},drop:function(){return this.element.classList.remove("dz-drag-hover")},dragstart:i,dragend:function(){return this.element.classList.remove("dz-drag-hover")},dragenter:function(){return this.element.classList.add("dz-drag-hover")},dragover:function(){return this.element.classList.add("dz-drag-hover")},dragleave:function(){return this.element.classList.remove("dz-drag-hover")},paste:i,reset:function(){return this.element.classList.remove("dz-started")},addedfile:function(a){var c,d,e,f,g,h,i,j,k,l,m,n,o,p=this;for(this.element===this.previewsContainer&&this.element.classList.add("dz-started"),a.previewElement=b.createElement(this.options.previewTemplate.trim()),a.previewTemplate=a.previewElement,this.previewsContainer.appendChild(a.previewElement),l=a.previewElement.querySelectorAll("[data-dz-name]"),f=0,i=l.length;i>f;f++)c=l[f],c.textContent=a.name;for(m=a.previewElement.querySelectorAll("[data-dz-size]"),g=0,j=m.length;j>g;g++)c=m[g],c.innerHTML=this.filesize(a.size);for(this.options.addRemoveLinks&&(a._removeLink=b.createElement('<a class="dz-remove" href="javascript:undefined;" data-dz-remove>'+this.options.dictRemoveFile+"</a>"),a.previewElement.appendChild(a._removeLink)),d=function(c){return c.preventDefault(),c.stopPropagation(),a.status===b.UPLOADING?b.confirm(p.options.dictCancelUploadConfirmation,function(){return p.removeFile(a)}):p.options.dictRemoveFileConfirmation?b.confirm(p.options.dictRemoveFileConfirmation,function(){return p.removeFile(a)}):p.removeFile(a)},n=a.previewElement.querySelectorAll("[data-dz-remove]"),o=[],h=0,k=n.length;k>h;h++)e=n[h],o.push(e.addEventListener("click",d));return o},removedfile:function(a){var b;return null!=(b=a.previewElement)&&b.parentNode.removeChild(a.previewElement),this._updateMaxFilesReachedClass()},thumbnail:function(a,b){var c,d,e,f,g;for(a.previewElement.classList.remove("dz-file-preview"),a.previewElement.classList.add("dz-image-preview"),f=a.previewElement.querySelectorAll("[data-dz-thumbnail]"),g=[],d=0,e=f.length;e>d;d++)c=f[d],c.alt=a.name,g.push(c.src=b);return g},error:function(a,b){var c,d,e,f,g;for(a.previewElement.classList.add("dz-error"),"String"!=typeof b&&b.error&&(b=b.error),f=a.previewElement.querySelectorAll("[data-dz-errormessage]"),g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(c.textContent=b);return g},errormultiple:i,processing:function(a){return a.previewElement.classList.add("dz-processing"),a._removeLink?a._removeLink.textContent=this.options.dictCancelUpload:void 0},processingmultiple:i,uploadprogress:function(a,b){var c,d,e,f,g;for(f=a.previewElement.querySelectorAll("[data-dz-uploadprogress]"),g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(c.style.width=""+b+"%");return g},totaluploadprogress:i,sending:i,sendingmultiple:i,success:function(a){return a.previewElement.classList.add("dz-success")},successmultiple:i,canceled:function(a){return this.emit("error",a,"Upload canceled.")},canceledmultiple:i,complete:function(a){return a._removeLink?a._removeLink.textContent=this.options.dictRemoveFile:void 0},completemultiple:i,maxfilesexceeded:i,maxfilesreached:i,previewTemplate:'<div class="dz-preview dz-file-preview">\n <div class="dz-details">\n <div class="dz-filename"><span data-dz-name></span></div>\n <div class="dz-size" data-dz-size></div>\n <img data-dz-thumbnail />\n </div>\n <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div>\n <div class="dz-success-mark"><span>✔</span></div>\n <div class="dz-error-mark"><span>✘</span></div>\n <div class="dz-error-message"><span data-dz-errormessage></span></div>\n</div>'},c=function(){var a,b,c,d,e,f,g;for(d=arguments[0],c=2<=arguments.length?m.call(arguments,1):[],f=0,g=c.length;g>f;f++){b=c[f];for(a in b)e=b[a],d[a]=e}return d},b.prototype.getAcceptedFiles=function(){var a,b,c,d,e;for(d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.accepted&&e.push(a);return e},b.prototype.getRejectedFiles=function(){var a,b,c,d,e;for(d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.accepted||e.push(a);return e},b.prototype.getQueuedFiles=function(){var a,c,d,e,f;for(e=this.files,f=[],c=0,d=e.length;d>c;c++)a=e[c],a.status===b.QUEUED&&f.push(a);return f},b.prototype.getUploadingFiles=function(){var a,c,d,e,f;for(e=this.files,f=[],c=0,d=e.length;d>c;c++)a=e[c],a.status===b.UPLOADING&&f.push(a);return f},b.prototype.init=function(){var a,c,d,e,f,g,h,i=this;for("form"===this.element.tagName&&this.element.setAttribute("enctype","multipart/form-data"),this.element.classList.contains("dropzone")&&!this.element.querySelector(".dz-message")&&this.element.appendChild(b.createElement('<div class="dz-default dz-message"><span>'+this.options.dictDefaultMessage+"</span></div>")),this.clickableElements.length&&(d=function(){return i.hiddenFileInput&&document.body.removeChild(i.hiddenFileInput),i.hiddenFileInput=document.createElement("input"),i.hiddenFileInput.setAttribute("type","file"),(null==i.options.maxFiles||i.options.maxFiles>1)&&i.hiddenFileInput.setAttribute("multiple","multiple"),null!=i.options.acceptedFiles&&i.hiddenFileInput.setAttribute("accept",i.options.acceptedFiles),i.hiddenFileInput.style.visibility="hidden",i.hiddenFileInput.style.position="absolute",i.hiddenFileInput.style.top="0",i.hiddenFileInput.style.left="0",i.hiddenFileInput.style.height="0",i.hiddenFileInput.style.width="0",document.body.appendChild(i.hiddenFileInput),i.hiddenFileInput.addEventListener("change",function(){var a,b,c,e;if(b=i.hiddenFileInput.files,b.length)for(c=0,e=b.length;e>c;c++)a=b[c],i.addFile(a);return d()})},d()),this.URL=null!=(g=window.URL)?g:window.webkitURL,h=this.events,e=0,f=h.length;f>e;e++)a=h[e],this.on(a,this.options[a]);return this.on("uploadprogress",function(){return i.updateTotalUploadProgress()}),this.on("removedfile",function(){return i.updateTotalUploadProgress()}),this.on("canceled",function(a){return i.emit("complete",a)}),this.on("complete",function(){return 0===i.getUploadingFiles().length&&0===i.getQueuedFiles().length?setTimeout(function(){return i.emit("queuecomplete")},0):void 0}),c=function(a){return a.stopPropagation(),a.preventDefault?a.preventDefault():a.returnValue=!1},this.listeners=[{element:this.element,events:{dragstart:function(a){return i.emit("dragstart",a)},dragenter:function(a){return c(a),i.emit("dragenter",a)},dragover:function(a){var b;try{b=a.dataTransfer.effectAllowed}catch(d){}return a.dataTransfer.dropEffect="move"===b||"linkMove"===b?"move":"copy",c(a),i.emit("dragover",a)},dragleave:function(a){return i.emit("dragleave",a)},drop:function(a){return c(a),i.drop(a)},dragend:function(a){return i.emit("dragend",a)}}}],this.clickableElements.forEach(function(a){return i.listeners.push({element:a,events:{click:function(c){return a!==i.element||c.target===i.element||b.elementInside(c.target,i.element.querySelector(".dz-message"))?i.hiddenFileInput.click():void 0}}})}),this.enable(),this.options.init.call(this)},b.prototype.destroy=function(){var a;return this.disable(),this.removeAllFiles(!0),(null!=(a=this.hiddenFileInput)?a.parentNode:void 0)&&(this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput),this.hiddenFileInput=null),delete this.element.dropzone,b.instances.splice(b.instances.indexOf(this),1)},b.prototype.updateTotalUploadProgress=function(){var a,b,c,d,e,f,g,h;if(d=0,c=0,a=this.getAcceptedFiles(),a.length){for(h=this.getAcceptedFiles(),f=0,g=h.length;g>f;f++)b=h[f],d+=b.upload.bytesSent,c+=b.upload.total;e=100*d/c}else e=100;return this.emit("totaluploadprogress",e,c,d)},b.prototype.getFallbackForm=function(){var a,c,d,e;return(a=this.getExistingFallback())?a:(d='<div class="dz-fallback">',this.options.dictFallbackText&&(d+="<p>"+this.options.dictFallbackText+"</p>"),d+='<input type="file" name="'+this.options.paramName+(this.options.uploadMultiple?"[]":"")+'" '+(this.options.uploadMultiple?'multiple="multiple"':void 0)+' /><input type="submit" value="Upload!"></div>',c=b.createElement(d),"FORM"!==this.element.tagName?(e=b.createElement('<form action="'+this.options.url+'" enctype="multipart/form-data" method="'+this.options.method+'"></form>'),e.appendChild(c)):(this.element.setAttribute("enctype","multipart/form-data"),this.element.setAttribute("method",this.options.method)),null!=e?e:c)},b.prototype.getExistingFallback=function(){var a,b,c,d,e,f;for(b=function(a){var b,c,d;for(c=0,d=a.length;d>c;c++)if(b=a[c],/(^| )fallback($| )/.test(b.className))return b},f=["div","form"],d=0,e=f.length;e>d;d++)if(c=f[d],a=b(this.element.getElementsByTagName(c)))return a},b.prototype.setupEventListeners=function(){var a,b,c,d,e,f,g;for(f=this.listeners,g=[],d=0,e=f.length;e>d;d++)a=f[d],g.push(function(){var d,e;d=a.events,e=[];for(b in d)c=d[b],e.push(a.element.addEventListener(b,c,!1));return e}());return g},b.prototype.removeEventListeners=function(){var a,b,c,d,e,f,g;for(f=this.listeners,g=[],d=0,e=f.length;e>d;d++)a=f[d],g.push(function(){var d,e;d=a.events,e=[];for(b in d)c=d[b],e.push(a.element.removeEventListener(b,c,!1));return e}());return g},b.prototype.disable=function(){var a,b,c,d,e;for(this.clickableElements.forEach(function(a){return a.classList.remove("dz-clickable")}),this.removeEventListeners(),d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(this.cancelUpload(a));return e},b.prototype.enable=function(){return this.clickableElements.forEach(function(a){return a.classList.add("dz-clickable")}),this.setupEventListeners()},b.prototype.filesize=function(a){var b;return a>=109951162777.6?(a/=109951162777.6,b="TiB"):a>=107374182.4?(a/=107374182.4,b="GiB"):a>=104857.6?(a/=104857.6,b="MiB"):a>=102.4?(a/=102.4,b="KiB"):(a=10*a,b="b"),"<strong>"+Math.round(a)/10+"</strong> "+b},b.prototype._updateMaxFilesReachedClass=function(){return null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(this.getAcceptedFiles().length===this.options.maxFiles&&this.emit("maxfilesreached",this.files),this.element.classList.add("dz-max-files-reached")):this.element.classList.remove("dz-max-files-reached")},b.prototype.drop=function(a){var b,c;a.dataTransfer&&(this.emit("drop",a),b=a.dataTransfer.files,b.length&&(c=a.dataTransfer.items,c&&c.length&&null!=c[0].webkitGetAsEntry?this._addFilesFromItems(c):this.handleFiles(b)))},b.prototype.paste=function(a){var b,c;if(null!=(null!=a?null!=(c=a.clipboardData)?c.items:void 0:void 0))return this.emit("paste",a),b=a.clipboardData.items,b.length?this._addFilesFromItems(b):void 0},b.prototype.handleFiles=function(a){var b,c,d,e;for(e=[],c=0,d=a.length;d>c;c++)b=a[c],e.push(this.addFile(b));return e},b.prototype._addFilesFromItems=function(a){var b,c,d,e,f;for(f=[],d=0,e=a.length;e>d;d++)c=a[d],null!=c.webkitGetAsEntry&&(b=c.webkitGetAsEntry())?b.isFile?f.push(this.addFile(c.getAsFile())):b.isDirectory?f.push(this._addFilesFromDirectory(b,b.name)):f.push(void 0):null!=c.getAsFile?null==c.kind||"file"===c.kind?f.push(this.addFile(c.getAsFile())):f.push(void 0):f.push(void 0);return f},b.prototype._addFilesFromDirectory=function(a,b){var c,d,e=this;return c=a.createReader(),d=function(a){var c,d,f;for(d=0,f=a.length;f>d;d++)c=a[d],c.isFile?c.file(function(a){return e.options.ignoreHiddenFiles&&"."===a.name.substring(0,1)?void 0:(a.fullPath=""+b+"/"+a.name,e.addFile(a))}):c.isDirectory&&e._addFilesFromDirectory(c,""+b+"/"+c.name)},c.readEntries(d,function(a){return"undefined"!=typeof console&&null!==console?"function"==typeof console.log?console.log(a):void 0:void 0})},b.prototype.accept=function(a,c){return a.size>1024*this.options.maxFilesize*1024?c(this.options.dictFileTooBig.replace("{{filesize}}",Math.round(a.size/1024/10.24)/100).replace("{{maxFilesize}}",this.options.maxFilesize)):b.isValidFile(a,this.options.acceptedFiles)?null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(c(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}",this.options.maxFiles)),this.emit("maxfilesexceeded",a)):this.options.accept.call(this,a,c):c(this.options.dictInvalidFileType)},b.prototype.addFile=function(a){var c=this;return a.upload={progress:0,total:a.size,bytesSent:0},this.files.push(a),a.status=b.ADDED,this.emit("addedfile",a),this._enqueueThumbnail(a),this.accept(a,function(b){return b?(a.accepted=!1,c._errorProcessing([a],b)):c.enqueueFile(a),c._updateMaxFilesReachedClass()})},b.prototype.enqueueFiles=function(a){var b,c,d;for(c=0,d=a.length;d>c;c++)b=a[c],this.enqueueFile(b);return null},b.prototype.enqueueFile=function(a){var c=this;if(a.accepted=!0,a.status!==b.ADDED)throw new Error("This file can't be queued because it has already been processed or was rejected.");return a.status=b.QUEUED,this.options.autoProcessQueue?setTimeout(function(){return c.processQueue()},0):void 0},b.prototype._thumbnailQueue=[],b.prototype._processingThumbnail=!1,b.prototype._enqueueThumbnail=function(a){var b=this;return this.options.createImageThumbnails&&a.type.match(/image.*/)&&a.size<=1024*this.options.maxThumbnailFilesize*1024?(this._thumbnailQueue.push(a),setTimeout(function(){return b._processThumbnailQueue()},0)):void 0},b.prototype._processThumbnailQueue=function(){var a=this;if(!this._processingThumbnail&&0!==this._thumbnailQueue.length)return this._processingThumbnail=!0,this.createThumbnail(this._thumbnailQueue.shift(),function(){return a._processingThumbnail=!1,a._processThumbnailQueue()})},b.prototype.removeFile=function(a){return a.status===b.UPLOADING&&this.cancelUpload(a),this.files=j(this.files,a),this.emit("removedfile",a),0===this.files.length?this.emit("reset"):void 0},b.prototype.removeAllFiles=function(a){var c,d,e,f;for(null==a&&(a=!1),f=this.files.slice(),d=0,e=f.length;e>d;d++)c=f[d],(c.status!==b.UPLOADING||a)&&this.removeFile(c);return null},b.prototype.createThumbnail=function(a,b){var c,d=this;return c=new FileReader,c.onload=function(){var e;return e=document.createElement("img"),e.onload=function(){var c,f,g,i,j,k,l,m;return a.width=e.width,a.height=e.height,g=d.options.resize.call(d,a),null==g.trgWidth&&(g.trgWidth=d.options.thumbnailWidth),null==g.trgHeight&&(g.trgHeight=d.options.thumbnailHeight),c=document.createElement("canvas"),f=c.getContext("2d"),c.width=g.trgWidth,c.height=g.trgHeight,h(f,e,null!=(j=g.srcX)?j:0,null!=(k=g.srcY)?k:0,g.srcWidth,g.srcHeight,null!=(l=g.trgX)?l:0,null!=(m=g.trgY)?m:0,g.trgWidth,g.trgHeight),i=c.toDataURL("image/png"),d.emit("thumbnail",a,i),null!=b?b():void 0},e.src=c.result},c.readAsDataURL(a)},b.prototype.processQueue=function(){var a,b,c,d;if(b=this.options.parallelUploads,c=this.getUploadingFiles().length,a=c,!(c>=b)&&(d=this.getQueuedFiles(),d.length>0)){if(this.options.uploadMultiple)return this.processFiles(d.slice(0,b-c));for(;b>a;){if(!d.length)return;this.processFile(d.shift()),a++}}},b.prototype.processFile=function(a){return this.processFiles([a])},b.prototype.processFiles=function(a){var c,d,e;for(d=0,e=a.length;e>d;d++)c=a[d],c.processing=!0,c.status=b.UPLOADING,this.emit("processing",c);return this.options.uploadMultiple&&this.emit("processingmultiple",a),this.uploadFiles(a)},b.prototype._getFilesWithXhr=function(a){var b,c;return c=function(){var c,d,e,f;for(e=this.files,f=[],c=0,d=e.length;d>c;c++)b=e[c],b.xhr===a&&f.push(b);return f}.call(this)},b.prototype.cancelUpload=function(a){var c,d,e,f,g,h,i;if(a.status===b.UPLOADING){for(d=this._getFilesWithXhr(a.xhr),e=0,g=d.length;g>e;e++)c=d[e],c.status=b.CANCELED;for(a.xhr.abort(),f=0,h=d.length;h>f;f++)c=d[f],this.emit("canceled",c);this.options.uploadMultiple&&this.emit("canceledmultiple",d)}else((i=a.status)===b.ADDED||i===b.QUEUED)&&(a.status=b.CANCELED,this.emit("canceled",a),this.options.uploadMultiple&&this.emit("canceledmultiple",[a]));return this.options.autoProcessQueue?this.processQueue():void 0},b.prototype.uploadFile=function(a){return this.uploadFiles([a])},b.prototype.uploadFiles=function(a){var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I=this;for(s=new XMLHttpRequest,t=0,x=a.length;x>t;t++)d=a[t],d.xhr=s;s.open(this.options.method,this.options.url,!0),s.withCredentials=!!this.options.withCredentials,p=null,f=function(){var b,c,e;for(e=[],b=0,c=a.length;c>b;b++)d=a[b],e.push(I._errorProcessing(a,p||I.options.dictResponseError.replace("{{statusCode}}",s.status),s));return e},q=function(b){var c,e,f,g,h,i,j,k,l;if(null!=b)for(e=100*b.loaded/b.total,f=0,i=a.length;i>f;f++)d=a[f],d.upload={progress:e,total:b.total,bytesSent:b.loaded};else{for(c=!0,e=100,g=0,j=a.length;j>g;g++)d=a[g],(100!==d.upload.progress||d.upload.bytesSent!==d.upload.total)&&(c=!1),d.upload.progress=e,d.upload.bytesSent=d.upload.total;if(c)return}for(l=[],h=0,k=a.length;k>h;h++)d=a[h],l.push(I.emit("uploadprogress",d,e,d.upload.bytesSent));return l},s.onload=function(c){var d;if(a[0].status!==b.CANCELED&&4===s.readyState){if(p=s.responseText,s.getResponseHeader("content-type")&&~s.getResponseHeader("content-type").indexOf("application/json"))try{p=JSON.parse(p)}catch(e){c=e,p="Invalid JSON response from server."}return q(),200<=(d=s.status)&&300>d?I._finished(a,p,c):f()}},s.onerror=function(){return a[0].status!==b.CANCELED?f():void 0},o=null!=(D=s.upload)?D:s,o.onprogress=q,i={Accept:"application/json","Cache-Control":"no-cache","X-Requested-With":"XMLHttpRequest"},this.options.headers&&c(i,this.options.headers);for(g in i)h=i[g],s.setRequestHeader(g,h);if(e=new FormData,this.options.params){E=this.options.params;for(m in E)r=E[m],e.append(m,r)}for(u=0,y=a.length;y>u;u++)d=a[u],this.emit("sending",d,s,e);if(this.options.uploadMultiple&&this.emit("sendingmultiple",a,s,e),"FORM"===this.element.tagName)for(F=this.element.querySelectorAll("input, textarea, select, button"),v=0,z=F.length;z>v;v++)if(j=F[v],k=j.getAttribute("name"),l=j.getAttribute("type"),"SELECT"===j.tagName&&j.hasAttribute("multiple"))for(G=j.options,w=0,A=G.length;A>w;w++)n=G[w],n.selected&&e.append(k,n.value);else(!l||"checkbox"!==(H=l.toLowerCase())&&"radio"!==H||j.checked)&&e.append(k,j.value);for(C=0,B=a.length;B>C;C++)d=a[C],e.append(""+this.options.paramName+(this.options.uploadMultiple?"[]":""),d,d.name);return s.send(e)},b.prototype._finished=function(a,c,d){var e,f,g;for(f=0,g=a.length;g>f;f++)e=a[f],e.status=b.SUCCESS,this.emit("success",e,c,d),this.emit("complete",e);return this.options.uploadMultiple&&(this.emit("successmultiple",a,c,d),this.emit("completemultiple",a)),this.options.autoProcessQueue?this.processQueue():void 0},b.prototype._errorProcessing=function(a,c,d){var e,f,g;for(f=0,g=a.length;g>f;f++)e=a[f],e.status=b.ERROR,this.emit("error",e,c,d),this.emit("complete",e);return this.options.uploadMultiple&&(this.emit("errormultiple",a,c,d),this.emit("completemultiple",a)),this.options.autoProcessQueue?this.processQueue():void 0},b}(d),a.version="3.8.4",a.options={},a.optionsForElement=function(b){return b.getAttribute("id")?a.options[e(b.getAttribute("id"))]:void 0},a.instances=[],a.forElement=function(a){if("string"==typeof a&&(a=document.querySelector(a)),null==(null!=a?a.dropzone:void 0))throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");return a.dropzone},a.autoDiscover=!0,a.discover=function(){var b,c,d,e,f,g;for(document.querySelectorAll?d=document.querySelectorAll(".dropzone"):(d=[],b=function(a){var b,c,e,f;for(f=[],c=0,e=a.length;e>c;c++)b=a[c],/(^| )dropzone($| )/.test(b.className)?f.push(d.push(b)):f.push(void 0);return f},b(document.getElementsByTagName("div")),b(document.getElementsByTagName("form"))),g=[],e=0,f=d.length;f>e;e++)c=d[e],a.optionsForElement(c)!==!1?g.push(new a(c)):g.push(void 0);return g},a.blacklistedBrowsers=[/opera.*Macintosh.*version\/12/i],a.isBrowserSupported=function(){var b,c,d,e,f;if(b=!0,window.File&&window.FileReader&&window.FileList&&window.Blob&&window.FormData&&document.querySelector)if("classList"in document.createElement("a"))for(f=a.blacklistedBrowsers,d=0,e=f.length;e>d;d++)c=f[d],c.test(navigator.userAgent)&&(b=!1);else b=!1;else b=!1;return b},j=function(a,b){var c,d,e,f;for(f=[],d=0,e=a.length;e>d;d++)c=a[d],c!==b&&f.push(c);return f},e=function(a){return a.replace(/[\-_](\w)/g,function(a){return a[1].toUpperCase()})},a.createElement=function(a){var b;return b=document.createElement("div"),b.innerHTML=a,b.childNodes[0]},a.elementInside=function(a,b){if(a===b)return!0;for(;a=a.parentNode;)if(a===b)return!0;return!1},a.getElement=function(a,b){var c;if("string"==typeof a?c=document.querySelector(a):null!=a.nodeType&&(c=a),null==c)throw new Error("Invalid `"+b+"` option provided. Please provide a CSS selector or a plain HTML element.");return c},a.getElements=function(a,b){var c,d,e,f,g,h,i,j;if(a instanceof Array){e=[];try{for(f=0,h=a.length;h>f;f++)d=a[f],e.push(this.getElement(d,b))}catch(k){c=k,e=null}}else if("string"==typeof a)for(e=[],j=document.querySelectorAll(a),g=0,i=j.length;i>g;g++)d=j[g],e.push(d);else null!=a.nodeType&&(e=[a]);if(null==e||!e.length)throw new Error("Invalid `"+b+"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");return e},a.confirm=function(a,b,c){return window.confirm(a)?b():null!=c?c():void 0},a.isValidFile=function(a,b){var c,d,e,f,g;if(!b)return!0;for(b=b.split(","),d=a.type,c=d.replace(/\/.*$/,""),f=0,g=b.length;g>f;f++)if(e=b[f],e=e.trim(),"."===e.charAt(0)){if(-1!==a.name.toLowerCase().indexOf(e.toLowerCase(),a.name.length-e.length))return!0}else if(/\/\*$/.test(e)){if(c===e.replace(/\/.*$/,""))return!0}else if(d===e)return!0;return!1},"undefined"!=typeof jQuery&&null!==jQuery&&(jQuery.fn.dropzone=function(b){return this.each(function(){return new a(this,b)})}),"undefined"!=typeof c&&null!==c?c.exports=a:window.Dropzone=a,a.ADDED="added",a.QUEUED="queued",a.ACCEPTED=a.QUEUED,a.UPLOADING="uploading",a.PROCESSING=a.UPLOADING,a.CANCELED="canceled",a.ERROR="error",a.SUCCESS="success",g=function(a){var b,c,d,e,f,g,h,i,j,k;for(h=a.naturalWidth,g=a.naturalHeight,c=document.createElement("canvas"),c.width=1,c.height=g,d=c.getContext("2d"),d.drawImage(a,0,0),e=d.getImageData(0,0,1,g).data,k=0,f=g,i=g;i>k;)b=e[4*(i-1)+3],0===b?f=i:k=i,i=f+k>>1;return j=i/g,0===j?1:j},h=function(a,b,c,d,e,f,h,i,j,k){var l;return l=g(b),a.drawImage(b,c,d,e,f,h,i,j,k/l)},f=function(a,b){var c,d,e,f,g,h,i,j,k;if(e=!1,k=!0,d=a.document,j=d.documentElement,c=d.addEventListener?"addEventListener":"attachEvent",i=d.addEventListener?"removeEventListener":"detachEvent",h=d.addEventListener?"":"on",f=function(c){return"readystatechange"!==c.type||"complete"===d.readyState?(("load"===c.type?a:d)[i](h+c.type,f,!1),!e&&(e=!0)?b.call(a,c.type||c):void 0):void 0},g=function(){var a;try{j.doScroll("left")}catch(b){return a=b,setTimeout(g,50),void 0}return f("poll")},"complete"!==d.readyState){if(d.createEventObject&&j.doScroll){try{k=!a.frameElement}catch(l){}k&&g()}return d[c](h+"DOMContentLoaded",f,!1),d[c](h+"readystatechange",f,!1),a[c](h+"load",f,!1)}},a._autoDiscoverFunction=function(){return a.autoDiscover?a.discover():void 0},f(window,a._autoDiscoverFunction)}).call(this)}),a.alias("component-emitter/index.js","dropzone/deps/emitter/index.js"),a.alias("component-emitter/index.js","emitter/index.js"),"object"==typeof exports?module.exports=a("dropzone"):"function"==typeof define&&define.amd?define(function(){return a("dropzone")}):this.Dropzone=a("dropzone")}(); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/dropzone/images/spritemap.png b/src/core/classes/org/glizycms/js/jquery/dropzone/images/spritemap.png new file mode 100755 index 0000000000000000000000000000000000000000..d711b0f0e6d7e33407fb067e33fdc3a29a299409 GIT binary patch literal 10208 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 Bm{9-# literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/jquery/dropzone/images/spritemap@2x.png b/src/core/classes/org/glizycms/js/jquery/dropzone/images/spritemap@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..ed29b88b6e2154cb6d1b88ab5bf9a3b7eac87d0c GIT binary patch literal 35675 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 literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/jquery/fancytree/jquery.fancytree-all.js b/src/core/classes/org/glizycms/js/jquery/fancytree/jquery.fancytree-all.js new file mode 100644 index 0000000..d28026d --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/fancytree/jquery.fancytree-all.js @@ -0,0 +1,7409 @@ +/*! + * jquery.fancytree.js + * Dynamic tree view control, with support for lazy loading of branches. + * https://github.com/mar10/fancytree/ + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +/** Core Fancytree module. + */ + + +// Start of local namespace +;(function($, window, document, undefined) { +"use strict"; + +// prevent duplicate loading +if ( $.ui && $.ui.fancytree ) { + $.ui.fancytree.warn("Fancytree: ignored duplicate include"); + return; +} + + +/* ***************************************************************************** + * Private functions and variables + */ + +function _assert(cond, msg){ + // TODO: see qunit.js extractStacktrace() + if(!cond){ + msg = msg ? ": " + msg : ""; + // consoleApply("assert", [!!cond, msg]); + $.error("Fancytree assertion failed" + msg); + } +} + +_assert($.ui, "Fancytree requires jQuery UI (http://jqueryui.com)"); + +function consoleApply(method, args){ + var i, s, + fn = window.console ? window.console[method] : null; + + if(fn){ + try{ + fn.apply(window.console, args); + } catch(e) { + // IE 8? + s = ""; + for( i=0; i<args.length; i++){ + s += args[i]; + } + fn(s); + } + } +} + +/*Return true if x is a FancytreeNode.*/ +function _isNode(x){ + return !!(x.tree && x.statusNodeType !== undefined); +} + +/** Return true if dotted version string is equal or higher than requested version. + * + * See http://jsfiddle.net/mar10/FjSAN/ + */ +function isVersionAtLeast(dottedVersion, major, minor, patch){ + var i, v, t, + verParts = $.map($.trim(dottedVersion).split("."), function(e){ return parseInt(e, 10); }), + testParts = $.map(Array.prototype.slice.call(arguments, 1), function(e){ return parseInt(e, 10); }); + + for( i = 0; i < testParts.length; i++ ){ + v = verParts[i] || 0; + t = testParts[i] || 0; + if( v !== t ){ + return ( v > t ); + } + } + return true; +} + +/** Return a wrapper that calls sub.methodName() and exposes + * this : tree + * this._local : tree.ext.EXTNAME + * this._super : base.methodName() + */ +function _makeVirtualFunction(methodName, tree, base, extension, extName){ + // $.ui.fancytree.debug("_makeVirtualFunction", methodName, tree, base, extension, extName); + // if(rexTestSuper && !rexTestSuper.test(func)){ + // // extension.methodName() doesn't call _super(), so no wrapper required + // return func; + // } + // Use an immediate function as closure + var proxy = (function(){ + var prevFunc = tree[methodName], // org. tree method or prev. proxy + baseFunc = extension[methodName], // + _local = tree.ext[extName], + _super = function(){ + return prevFunc.apply(tree, arguments); + }, + _superApply = function(args){ + return prevFunc.apply(tree, args); + }; + + // Return the wrapper function + return function(){ + var prevLocal = tree._local, + prevSuper = tree._super, + prevSuperApply = tree._superApply; + + try{ + tree._local = _local; + tree._super = _super; + tree._superApply = _superApply; + return baseFunc.apply(tree, arguments); + }finally{ + tree._local = prevLocal; + tree._super = prevSuper; + tree._superApply = prevSuperApply; + } + }; + })(); // end of Immediate Function + return proxy; +} + +/** + * Subclass `base` by creating proxy functions + */ +function _subclassObject(tree, base, extension, extName){ + // $.ui.fancytree.debug("_subclassObject", tree, base, extension, extName); + for(var attrName in extension){ + if(typeof extension[attrName] === "function"){ + if(typeof tree[attrName] === "function"){ + // override existing method + tree[attrName] = _makeVirtualFunction(attrName, tree, base, extension, extName); + }else if(attrName.charAt(0) === "_"){ + // Create private methods in tree.ext.EXTENSION namespace + tree.ext[extName][attrName] = _makeVirtualFunction(attrName, tree, base, extension, extName); + }else{ + $.error("Could not override tree." + attrName + ". Use prefix '_' to create tree." + extName + "._" + attrName); + } + }else{ + // Create member variables in tree.ext.EXTENSION namespace + if(attrName !== "options"){ + tree.ext[extName][attrName] = extension[attrName]; + } + } + } +} + + +function _getResolvedPromise(context, argArray){ + if(context === undefined){ + return $.Deferred(function(){this.resolve();}).promise(); + }else{ + return $.Deferred(function(){this.resolveWith(context, argArray);}).promise(); + } +} + + +function _getRejectedPromise(context, argArray){ + if(context === undefined){ + return $.Deferred(function(){this.reject();}).promise(); + }else{ + return $.Deferred(function(){this.rejectWith(context, argArray);}).promise(); + } +} + + +function _makeResolveFunc(deferred, context){ + return function(){ + deferred.resolveWith(context); + }; +} + + +function _getElementDataAsDict($el){ + // Evaluate 'data-NAME' attributes with special treatment for 'data-json'. + var d = $.extend({}, $el.data()), + json = d.json; + delete d.fancytree; // added to container by widget factory + if( json ) { + delete d.json; + // <li data-json='...'> is already returned as object (http://api.jquery.com/data/#data-html5) + d = $.extend(d, json); + } + return d; +} + + +// TODO: use currying +function _makeNodeTitleMatcher(s){ + s = s.toLowerCase(); + return function(node){ + return node.title.toLowerCase().indexOf(s) >= 0; + }; +} + + +function _makeNodeTitleStartMatcher(s){ + var reMatch = new RegExp("^" + s, "i"); + return function(node){ + return reMatch.test(node.title); + }; +} + +var i, + FT = null, // initialized below + ENTITY_MAP = {"&": "&amp;", "<": "&lt;", ">": "&gt;", "\"": "&quot;", "'": "&#39;", "/": "&#x2F;"}, + IGNORE_KEYCODES = { 16: true, 17: true, 18: true }, + SPECIAL_KEYCODES = { + 8: "backspace", 9: "tab", 10: "return", 13: "return", + // 16: null, 17: null, 18: null, // ignore shift, ctrl, alt + 19: "pause", 20: "capslock", 27: "esc", 32: "space", 33: "pageup", + 34: "pagedown", 35: "end", 36: "home", 37: "left", 38: "up", + 39: "right", 40: "down", 45: "insert", 46: "del", 59: ";", 61: "=", + 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", + 103: "7", 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", + 111: "/", 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", + 117: "f6", 118: "f7", 119: "f8", 120: "f9", 121: "f10", 122: "f11", + 123: "f12", 144: "numlock", 145: "scroll", 173: "-", 186: ";", 187: "=", + 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", + 221: "]", 222: "'"}, + MOUSE_BUTTONS = { 0: "", 1: "left", 2: "middle", 3: "right" }, + //boolean attributes that can be set with equivalent class names in the LI tags + CLASS_ATTRS = "active expanded focus folder hideCheckbox lazy selected unselectable".split(" "), + CLASS_ATTR_MAP = {}, + // Top-level Fancytree node attributes, that can be set by dict + NODE_ATTRS = "expanded extraClasses folder hideCheckbox key lazy refKey selected title tooltip unselectable".split(" "), + NODE_ATTR_MAP = {}, + // Attribute names that should NOT be added to node.data + NONE_NODE_DATA_MAP = {"active": true, "children": true, "data": true, "focus": true}; + +for(i=0; i<CLASS_ATTRS.length; i++){ CLASS_ATTR_MAP[CLASS_ATTRS[i]] = true; } +for(i=0; i<NODE_ATTRS.length; i++){ NODE_ATTR_MAP[NODE_ATTRS[i]] = true; } + + +/* ***************************************************************************** + * FancytreeNode + */ + + +/** + * Creates a new FancytreeNode + * + * @class FancytreeNode + * @classdesc A FancytreeNode represents the hierarchical data model and operations. + * + * @param {FancytreeNode} parent + * @param {NodeData} obj + * + * @property {Fancytree} tree The tree instance + * @property {FancytreeNode} parent The parent node + * @property {string} key Node id (must be unique inside the tree) + * @property {string} title Display name (may contain HTML) + * @property {object} data Contains all extra data that was passed on node creation + * @property {FancytreeNode[] | null | undefined} children Array of child nodes.<br> + * For lazy nodes, null or undefined means 'not yet loaded'. Use an empty array + * to define a node that has no children. + * @property {boolean} expanded Use isExpanded(), setExpanded() to access this property. + * @property {string} extraClasses Addtional CSS classes, added to the node's `&lt;span>` + * @property {boolean} folder Folder nodes have different default icons and click behavior.<br> + * Note: Also non-folders may have children. + * @property {string} statusNodeType null or type of temporarily generated system node like 'loading', or 'error'. + * @property {boolean} lazy True if this node is loaded on demand, i.e. on first expansion. + * @property {boolean} selected Use isSelected(), setSelected() to access this property. + * @property {string} tooltip Alternative description used as hover banner + */ +function FancytreeNode(parent, obj){ + var i, l, name, cl; + + this.parent = parent; + this.tree = parent.tree; + this.ul = null; + this.li = null; // <li id='key' ftnode=this> tag + this.statusNodeType = null; // if this is a temp. node to display the status of its parent + this._isLoading = false; // if this node itself is loading + this._error = null; // {message: '...'} if a load error occured + this.data = {}; + + // TODO: merge this code with node.toDict() + // copy attributes from obj object + for(i=0, l=NODE_ATTRS.length; i<l; i++){ + name = NODE_ATTRS[i]; + this[name] = obj[name]; + } + // node.data += obj.data + if(obj.data){ + $.extend(this.data, obj.data); + } + // copy all other attributes to this.data.NAME + for(name in obj){ + if(!NODE_ATTR_MAP[name] && !$.isFunction(obj[name]) && !NONE_NODE_DATA_MAP[name]){ + // node.data.NAME = obj.NAME + this.data[name] = obj[name]; + } + } + + // Fix missing key + if( this.key == null ){ // test for null OR undefined + if( this.tree.options.defaultKey ) { + this.key = this.tree.options.defaultKey(this); + _assert(this.key, "defaultKey() must return a unique key"); + } else { + this.key = "_" + (FT._nextNodeKey++); + } + } else { + this.key = "" + this.key; // Convert to string (#217) + } + + // Fix tree.activeNode + // TODO: not elegant: we use obj.active as marker to set tree.activeNode + // when loading from a dictionary. + if(obj.active){ + _assert(this.tree.activeNode === null, "only one active node allowed"); + this.tree.activeNode = this; + } + if( obj.selected ){ // #186 + this.tree.lastSelectedNode = this; + } + // TODO: handle obj.focus = true + // Create child nodes + this.children = null; + cl = obj.children; + if(cl && cl.length){ + this._setChildren(cl); + } + // Add to key/ref map (except for root node) +// if( parent ) { + this.tree._callHook("treeRegisterNode", this.tree, true, this); +// } +} + + +FancytreeNode.prototype = /** @lends FancytreeNode# */{ + /* Return the direct child FancytreeNode with a given key, index. */ + _findDirectChild: function(ptr){ + var i, l, + cl = this.children; + + if(cl){ + if(typeof ptr === "string"){ + for(i=0, l=cl.length; i<l; i++){ + if(cl[i].key === ptr){ + return cl[i]; + } + } + }else if(typeof ptr === "number"){ + return this.children[ptr]; + }else if(ptr.parent === this){ + return ptr; + } + } + return null; + }, + // TODO: activate() + // TODO: activateSilently() + /* Internal helper called in recursive addChildren sequence.*/ + _setChildren: function(children){ + _assert(children && (!this.children || this.children.length === 0), "only init supported"); + this.children = []; + for(var i=0, l=children.length; i<l; i++){ + this.children.push(new FancytreeNode(this, children[i])); + } + }, + /** + * Append (or insert) a list of child nodes. + * + * @param {NodeData[]} children array of child node definitions (also single child accepted) + * @param {FancytreeNode | string | Integer} [insertBefore] child node (or key or index of such). + * If omitted, the new children are appended. + * @returns {FancytreeNode} first child added + * + * @see FancytreeNode#applyPatch + */ + addChildren: function(children, insertBefore){ + var i, l, pos, + firstNode = null, + nodeList = []; + + if($.isPlainObject(children) ){ + children = [children]; + } + if(!this.children){ + this.children = []; + } + for(i=0, l=children.length; i<l; i++){ + nodeList.push(new FancytreeNode(this, children[i])); + } + firstNode = nodeList[0]; + if(insertBefore == null){ + this.children = this.children.concat(nodeList); + }else{ + insertBefore = this._findDirectChild(insertBefore); + pos = $.inArray(insertBefore, this.children); + _assert(pos >= 0, "insertBefore must be an existing child"); + // insert nodeList after children[pos] + this.children.splice.apply(this.children, [pos, 0].concat(nodeList)); + } + if( !this.parent || this.parent.ul || this.tr ){ + // render if the parent was rendered (or this is a root node) + this.render(); + } + if( this.tree.options.selectMode === 3 ){ + this.fixSelection3FromEndNodes(); + } + return firstNode; + }, + /** + * Append or prepend a node, or append a child node. + * + * This a convenience function that calls addChildren() + * + * @param {NodeData} node node definition + * @param {string} [mode=child] 'before', 'after', 'firstChild', or 'child' ('over' is a synonym for 'child') + * @returns {FancytreeNode} new node + */ + addNode: function(node, mode){ + if(mode === undefined || mode === "over"){ + mode = "child"; + } + switch(mode){ + case "after": + return this.getParent().addChildren(node, this.getNextSibling()); + case "before": + return this.getParent().addChildren(node, this); + case "firstChild": + // Insert before the first child if any + var insertBefore = (this.children ? this.children[0] : null); + return this.addChildren(node, insertBefore); + case "child": + case "over": + return this.addChildren(node); + } + _assert(false, "Invalid mode: " + mode); + }, + /** + * Append new node after this. + * + * This a convenience function that calls addNode(node, 'after') + * + * @param {NodeData} node node definition + * @returns {FancytreeNode} new node + */ + appendSibling: function(node){ + return this.addNode(node, "after"); + }, + /** + * Modify existing child nodes. + * + * @param {NodePatch} patch + * @returns {$.Promise} + * @see FancytreeNode#addChildren + */ + applyPatch: function(patch) { + // patch [key, null] means 'remove' + if(patch === null){ + this.remove(); + return _getResolvedPromise(this); + } + // TODO: make sure that root node is not collapsed or modified + // copy (most) attributes to node.ATTR or node.data.ATTR + var name, promise, v, + IGNORE_MAP = { children: true, expanded: true, parent: true }; // TODO: should be global + + for(name in patch){ + v = patch[name]; + if( !IGNORE_MAP[name] && !$.isFunction(v)){ + if(NODE_ATTR_MAP[name]){ + this[name] = v; + }else{ + this.data[name] = v; + } + } + } + // Remove and/or create children + if(patch.hasOwnProperty("children")){ + this.removeChildren(); + if(patch.children){ // only if not null and not empty list + // TODO: addChildren instead? + this._setChildren(patch.children); + } + // TODO: how can we APPEND or INSERT child nodes? + } + if(this.isVisible()){ + this.renderTitle(); + this.renderStatus(); + } + // Expand collapse (final step, since this may be async) + if(patch.hasOwnProperty("expanded")){ + promise = this.setExpanded(patch.expanded); + }else{ + promise = _getResolvedPromise(this); + } + return promise; + }, + /** Collapse all sibling nodes. + * @returns {$.Promise} + */ + collapseSiblings: function() { + return this.tree._callHook("nodeCollapseSiblings", this); + }, + /** Copy this node as sibling or child of `node`. + * + * @param {FancytreeNode} node source node + * @param {string} [mode=child] 'before' | 'after' | 'child' + * @param {Function} [map] callback function(NodeData) that could modify the new node + * @returns {FancytreeNode} new + */ + copyTo: function(node, mode, map) { + return node.addNode(this.toDict(true, map), mode); + }, + /** Count direct and indirect children. + * + * @param {boolean} [deep=true] pass 'false' to only count direct children + * @returns {int} number of child nodes + */ + countChildren: function(deep) { + var cl = this.children, i, l, n; + if( !cl ){ + return 0; + } + n = cl.length; + if(deep !== false){ + for(i=0, l=n; i<l; i++){ + n += cl[i].countChildren(); + } + } + return n; + }, + // TODO: deactivate() + /** Write to browser console if debugLevel >= 2 (prepending node info) + * + * @param {*} msg string or object or array of such + */ + debug: function(msg){ + if( this.tree.options.debugLevel >= 2 ) { + Array.prototype.unshift.call(arguments, this.toString()); + consoleApply("log", arguments); + } + }, + /** Deprecated. + * @deprecated since 2014-02-16. Use resetLazy() instead. + */ + discard: function(){ + this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."); + return this.resetLazy(); + }, + // TODO: expand(flag) + /**Find all nodes that contain `match` in the title. + * + * @param {string | function(node)} match string to search for, of a function that + * returns `true` if a node is matched. + * @returns {FancytreeNode[]} array of nodes (may be empty) + * @see FancytreeNode#findAll + */ + findAll: function(match) { + match = $.isFunction(match) ? match : _makeNodeTitleMatcher(match); + var res = []; + this.visit(function(n){ + if(match(n)){ + res.push(n); + } + }); + return res; + }, + /**Find first node that contains `match` in the title (not including self). + * + * @param {string | function(node)} match string to search for, of a function that + * returns `true` if a node is matched. + * @returns {FancytreeNode} matching node or null + * @example + * <b>fat</b> text + */ + findFirst: function(match) { + match = $.isFunction(match) ? match : _makeNodeTitleMatcher(match); + var res = null; + this.visit(function(n){ + if(match(n)){ + res = n; + return false; + } + }); + return res; + }, + /* Apply selection state (internal use only) */ + _changeSelectStatusAttrs: function (state) { + var changed = false; + + switch(state){ + case false: + changed = ( this.selected || this.partsel ); + this.selected = false; + this.partsel = false; + break; + case true: + changed = ( !this.selected || !this.partsel ); + this.selected = true; + this.partsel = true; + break; + case undefined: + changed = ( this.selected || !this.partsel ); + this.selected = false; + this.partsel = true; + break; + default: + _assert(false, "invalid state: " + state); + } + // this.debug("fixSelection3AfterLoad() _changeSelectStatusAttrs()", state, changed); + if( changed ){ + this.renderStatus(); + } + return changed; + }, + /** + * Fix selection status, after this node was (de)selected in multi-hier mode. + * This includes (de)selecting all children. + */ + fixSelection3AfterClick: function() { + var flag = this.isSelected(); + +// this.debug("fixSelection3AfterClick()"); + + this.visit(function(node){ + node._changeSelectStatusAttrs(flag); + }); + this.fixSelection3FromEndNodes(); + }, + /** + * Fix selection status for multi-hier mode. + * Only end-nodes are considered to update the descendants branch and parents. + * Should be called after this node has loaded new children or after + * children have been modified using the API. + */ + fixSelection3FromEndNodes: function() { +// this.debug("fixSelection3FromEndNodes()"); + _assert(this.tree.options.selectMode === 3, "expected selectMode 3"); + + // Visit all end nodes and adjust their parent's `selected` and `partsel` + // attributes. Return selection state true, false, or undefined. + function _walk(node){ + var i, l, child, s, state, allSelected,someSelected, + children = node.children; + + if( children && children.length ){ + // check all children recursively + allSelected = true; + someSelected = false; + + for( i=0, l=children.length; i<l; i++ ){ + child = children[i]; + // the selection state of a node is not relevant; we need the end-nodes + s = _walk(child); + if( s !== false ) { + someSelected = true; + } + if( s !== true ) { + allSelected = false; + } + } + state = allSelected ? true : (someSelected ? undefined : false); + }else{ + // This is an end-node: simply report the status +// state = ( node.unselectable ) ? undefined : !!node.selected; + state = !!node.selected; + } + node._changeSelectStatusAttrs(state); + return state; + } + _walk(this); + + // Update parent's state + this.visitParents(function(node){ + var i, l, child, state, + children = node.children, + allSelected = true, + someSelected = false; + + for( i=0, l=children.length; i<l; i++ ){ + child = children[i]; + // When fixing the parents, we trust the sibling status (i.e. + // we don't recurse) + if( child.selected || child.partsel ) { + someSelected = true; + } + if( !child.unselectable && !child.selected ) { + allSelected = false; + } + } + state = allSelected ? true : (someSelected ? undefined : false); + node._changeSelectStatusAttrs(state); + }); + }, + // TODO: focus() + /** + * Update node data. If dict contains 'children', then also replace + * the hole sub tree. + * @param {NodeData} dict + * + * @see FancytreeNode#addChildren + * @see FancytreeNode#applyPatch + */ + fromDict: function(dict) { + // copy all other attributes to this.data.xxx + for(var name in dict){ + if(NODE_ATTR_MAP[name]){ + // node.NAME = dict.NAME + this[name] = dict[name]; + }else if(name === "data"){ + // node.data += dict.data + $.extend(this.data, dict.data); + }else if(!$.isFunction(dict[name]) && !NONE_NODE_DATA_MAP[name]){ + // node.data.NAME = dict.NAME + this.data[name] = dict[name]; + } + } + if(dict.children){ + // recursively set children and render + this.removeChildren(); + this.addChildren(dict.children); + } + this.renderTitle(); +/* + var children = dict.children; + if(children === undefined){ + this.data = $.extend(this.data, dict); + this.render(); + return; + } + dict = $.extend({}, dict); + dict.children = undefined; + this.data = $.extend(this.data, dict); + this.removeChildren(); + this.addChild(children); +*/ + }, + /** Return the list of child nodes (undefined for unexpanded lazy nodes). + * @returns {FancytreeNode[] | undefined} + */ + getChildren: function() { + if(this.hasChildren() === undefined){ // TODO: only required for lazy nodes? + return undefined; // Lazy node: unloaded, currently loading, or load error + } + return this.children; + }, + /** Return the first child node or null. + * @returns {FancytreeNode | null} + */ + getFirstChild: function() { + return this.children ? this.children[0] : null; + }, + /** Return the 0-based child index. + * @returns {int} + */ + getIndex: function() { +// return this.parent.children.indexOf(this); + return $.inArray(this, this.parent.children); // indexOf doesn't work in IE7 + }, + /** Return the hierarchical child index (1-based, e.g. '3.2.4'). + * @returns {string} + */ + getIndexHier: function(separator) { + separator = separator || "."; + var res = []; + $.each(this.getParentList(false, true), function(i, o){ + res.push(o.getIndex() + 1); + }); + return res.join(separator); + }, + /** Return the parent keys separated by options.keyPathSeparator, e.g. "id_1/id_17/id_32". + * @param {boolean} [excludeSelf=false] + * @returns {string} + */ + getKeyPath: function(excludeSelf) { + var path = [], + sep = this.tree.options.keyPathSeparator; + this.visitParents(function(n){ + if(n.parent){ + path.unshift(n.key); + } + }, !excludeSelf); + return sep + path.join(sep); + }, + /** Return the last child of this node or null. + * @returns {FancytreeNode | null} + */ + getLastChild: function() { + return this.children ? this.children[this.children.length - 1] : null; + }, + /** Return node depth. 0: System root node, 1: visible top-level node, 2: first sub-level, ... . + * @returns {int} + */ + getLevel: function() { + var level = 0, + dtn = this.parent; + while( dtn ) { + level++; + dtn = dtn.parent; + } + return level; + }, + /** Return the successor node (under the same parent) or null. + * @returns {FancytreeNode | null} + */ + getNextSibling: function() { + // TODO: use indexOf, if available: (not in IE6) + if( this.parent ){ + var i, l, + ac = this.parent.children; + + for(i=0, l=ac.length-1; i<l; i++){ // up to length-2, so next(last) = null + if( ac[i] === this ){ + return ac[i+1]; + } + } + } + return null; + }, + /** Return the parent node (null for the system root node). + * @returns {FancytreeNode | null} + */ + getParent: function() { + // TODO: return null for top-level nodes? + return this.parent; + }, + /** Return an array of all parent nodes (top-down). + * @param {boolean} [includeRoot=false] Include the invisible system root node. + * @param {boolean} [includeSelf=false] Include the node itself. + * @returns {FancytreeNode[]} + */ + getParentList: function(includeRoot, includeSelf) { + var l = [], + dtn = includeSelf ? this : this.parent; + while( dtn ) { + if( includeRoot || dtn.parent ){ + l.unshift(dtn); + } + dtn = dtn.parent; + } + return l; + }, + /** Return the predecessor node (under the same parent) or null. + * @returns {FancytreeNode | null} + */ + getPrevSibling: function() { + if( this.parent ){ + var i, l, + ac = this.parent.children; + + for(i=1, l=ac.length; i<l; i++){ // start with 1, so prev(first) = null + if( ac[i] === this ){ + return ac[i-1]; + } + } + } + return null; + }, + /** Return true if node has children. Return undefined if not sure, i.e. the node is lazy and not yet loaded). + * @returns {boolean | undefined} + */ + hasChildren: function() { + if(this.lazy){ + if(this.children == null ){ + // null or undefined: Not yet loaded + return undefined; + }else if(this.children.length === 0){ + // Loaded, but response was empty + return false; + }else if(this.children.length === 1 && this.children[0].isStatusNode() ){ + // Currently loading or load error + return undefined; + } + return true; + } + return !!( this.children && this.children.length ); + }, + /** Return true if node has keyboard focus. + * @returns {boolean} + */ + hasFocus: function() { + return (this.tree.hasFocus() && this.tree.focusNode === this); + }, + /** Write to browser console if debugLevel >= 1 (prepending node info) + * + * @param {*} msg string or object or array of such + */ + info: function(msg){ + if( this.tree.options.debugLevel >= 1 ) { + Array.prototype.unshift.call(arguments, this.toString()); + consoleApply("info", arguments); + } + }, + /** Return true if node is active (see also FancytreeNode#isSelected). + * @returns {boolean} + */ + isActive: function() { + return (this.tree.activeNode === this); + }, + /** Return true if node is a direct child of otherNode. + * @param {FancytreeNode} otherNode + * @returns {boolean} + */ + isChildOf: function(otherNode) { + return (this.parent && this.parent === otherNode); + }, + /** Return true, if node is a direct or indirect sub node of otherNode. + * @param {FancytreeNode} otherNode + * @returns {boolean} + */ + isDescendantOf: function(otherNode) { + if(!otherNode || otherNode.tree !== this.tree){ + return false; + } + var p = this.parent; + while( p ) { + if( p === otherNode ){ + return true; + } + p = p.parent; + } + return false; + }, + /** Return true if node is expanded. + * @returns {boolean} + */ + isExpanded: function() { + return !!this.expanded; + }, + /** Return true if node is the first node of its parent's children. + * @returns {boolean} + */ + isFirstSibling: function() { + var p = this.parent; + return !p || p.children[0] === this; + }, + /** Return true if node is a folder, i.e. has the node.folder attribute set. + * @returns {boolean} + */ + isFolder: function() { + return !!this.folder; + }, + /** Return true if node is the last node of its parent's children. + * @returns {boolean} + */ + isLastSibling: function() { + var p = this.parent; + return !p || p.children[p.children.length-1] === this; + }, + /** Return true if node is lazy (even if data was already loaded) + * @returns {boolean} + */ + isLazy: function() { + return !!this.lazy; + }, + /** Return true if node is lazy and loaded. For non-lazy nodes always return true. + * @returns {boolean} + */ + isLoaded: function() { + return !this.lazy || this.hasChildren() !== undefined; // Also checks if the only child is a status node + }, + /** Return true if children are currently beeing loaded, i.e. a Ajax request is pending. + * @returns {boolean} + */ + isLoading: function() { + return !!this._isLoading; + }, + /** + * @deprecated since v2.4.0: Use isRootNode() instead + */ + isRoot: function() { + return this.isRootNode(); + }, + /** Return true if this is the (invisible) system root node. + * @returns {boolean} + */ + isRootNode: function() { + return (this.tree.rootNode === this); + }, + /** Return true if node is selected, i.e. has a checkmark set (see also FancytreeNode#isActive). + * @returns {boolean} + */ + isSelected: function() { + return !!this.selected; + }, + /** Return true if this node is a temporarily generated system node like + * 'loading', or 'error' (node.statusNodeType contains the type). + * @returns {boolean} + */ + isStatusNode: function() { + return !!this.statusNodeType; + }, + /** Return true if this a top level node, i.e. a direct child of the (invisible) system root node. + * @returns {boolean} + */ + isTopLevel: function() { + return (this.tree.rootNode === this.parent); + }, + /** Return true if node is lazy and not yet loaded. For non-lazy nodes always return false. + * @returns {boolean} + */ + isUndefined: function() { + return this.hasChildren() === undefined; // also checks if the only child is a status node + }, + /** Return true if all parent nodes are expanded. Note: this does not check + * whether the node is scrolled into the visible part of the screen. + * @returns {boolean} + */ + isVisible: function() { + var i, l, + parents = this.getParentList(false, false); + + for(i=0, l=parents.length; i<l; i++){ + if( ! parents[i].expanded ){ return false; } + } + return true; + }, + /** Deprecated. + * @deprecated since 2014-02-16: use load() instead. + */ + lazyLoad: function(discard) { + this.warn("FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead."); + return this.load(discard); + }, + /** + * Load all children of a lazy node if neccessary. The *expanded* state is maintained. + * @param {boolean} [forceReload=false] Pass true to discard any existing nodes before. + * @returns {$.Promise} + */ + load: function(forceReload) { + var res, source, + that = this; + + _assert( this.isLazy(), "load() requires a lazy node" ); + // _assert( forceReload || this.isUndefined(), "Pass forceReload=true to re-load a lazy node" ); + if( !forceReload && !this.isUndefined() ) { + return _getResolvedPromise(this); + } + if( this.isLoaded() ){ + this.resetLazy(); // also collapses + } + // This method is also called by setExpanded() and loadKeyPath(), so we + // have to avoid recursion. + source = this.tree._triggerNodeEvent("lazyLoad", this); + if( source === false ) { // #69 + return _getResolvedPromise(this); + } + _assert(typeof source !== "boolean", "lazyLoad event must return source in data.result"); + res = this.tree._callHook("nodeLoadChildren", this, source); + if( this.expanded ) { + res.always(function(){ + that.render(); + }); + } + return res; + }, + /** Expand all parents and optionally scroll into visible area as neccessary. + * Promise is resolved, when lazy loading and animations are done. + * @param {object} [opts] passed to `setExpanded()`. + * Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true} + * @returns {$.Promise} + */ + makeVisible: function(opts) { + var i, + that = this, + deferreds = [], + dfd = new $.Deferred(), + parents = this.getParentList(false, false), + len = parents.length, + effects = !(opts && opts.noAnimation === true), + scroll = !(opts && opts.scrollIntoView === false); + + // Expand bottom-up, so only the top node is animated + for(i = len - 1; i >= 0; i--){ + // that.debug("pushexpand" + parents[i]); + deferreds.push(parents[i].setExpanded(true, opts)); + } + $.when.apply($, deferreds).done(function(){ + // All expands have finished + // that.debug("expand DONE", scroll); + if( scroll ){ + that.scrollIntoView(effects).done(function(){ + // that.debug("scroll DONE"); + dfd.resolve(); + }); + } else { + dfd.resolve(); + } + }); + return dfd.promise(); + }, + /** Move this node to targetNode. + * @param {FancytreeNode} targetNode + * @param {string} mode <pre> + * 'child': append this node as last child of targetNode. + * This is the default. To be compatble with the D'n'd + * hitMode, we also accept 'over'. + * 'before': add this node as sibling before targetNode. + * 'after': add this node as sibling after targetNode.</pre> + * @param {function} [map] optional callback(FancytreeNode) to allow modifcations + */ + moveTo: function(targetNode, mode, map) { + if(mode === undefined || mode === "over"){ + mode = "child"; + } + var pos, + prevParent = this.parent, + targetParent = (mode === "child") ? targetNode : targetNode.parent; + + if(this === targetNode){ + return; + }else if( !this.parent ){ + throw "Cannot move system root"; + }else if( targetParent.isDescendantOf(this) ){ + throw "Cannot move a node to its own descendant"; + } + // Unlink this node from current parent + if( this.parent.children.length === 1 ) { + if( this.parent === targetParent ){ + return; // #258 + } + this.parent.children = this.parent.lazy ? [] : null; + this.parent.expanded = false; + } else { + pos = $.inArray(this, this.parent.children); + _assert(pos >= 0); + this.parent.children.splice(pos, 1); + } + // Remove from source DOM parent +// if(this.parent.ul){ +// this.parent.ul.removeChild(this.li); +// } + + // Insert this node to target parent's child list + this.parent = targetParent; + if( targetParent.hasChildren() ) { + switch(mode) { + case "child": + // Append to existing target children + targetParent.children.push(this); + break; + case "before": + // Insert this node before target node + pos = $.inArray(targetNode, targetParent.children); + _assert(pos >= 0); + targetParent.children.splice(pos, 0, this); + break; + case "after": + // Insert this node after target node + pos = $.inArray(targetNode, targetParent.children); + _assert(pos >= 0); + targetParent.children.splice(pos+1, 0, this); + break; + default: + throw "Invalid mode " + mode; + } + } else { + targetParent.children = [ this ]; + } + // Parent has no <ul> tag yet: +// if( !targetParent.ul ) { +// // This is the parent's first child: create UL tag +// // (Hidden, because it will be +// targetParent.ul = document.createElement("ul"); +// targetParent.ul.style.display = "none"; +// targetParent.li.appendChild(targetParent.ul); +// } +// // Issue 319: Add to target DOM parent (only if node was already rendered(expanded)) +// if(this.li){ +// targetParent.ul.appendChild(this.li); +// }^ + + // Let caller modify the nodes + if( map ){ + targetNode.visit(map, true); + } + // Handle cross-tree moves + if( this.tree !== targetNode.tree ) { + // Fix node.tree for all source nodes +// _assert(false, "Cross-tree move is not yet implemented."); + this.warn("Cross-tree moveTo is experimantal!"); + this.visit(function(n){ + // TODO: fix selection state and activation, ... + n.tree = targetNode.tree; + }, true); + } + + // A collaposed node won't re-render children, so we have to remove it manually + // if( !targetParent.expanded ){ + // prevParent.ul.removeChild(this.li); + // } + + // Update HTML markup + if( !prevParent.isDescendantOf(targetParent)) { + prevParent.render(); + } + if( !targetParent.isDescendantOf(prevParent) && targetParent !== prevParent) { + targetParent.render(); + } + // TODO: fix selection state + // TODO: fix active state + +/* + var tree = this.tree; + var opts = tree.options; + var pers = tree.persistence; + + + // Always expand, if it's below minExpandLevel +// tree.logDebug ("%s._addChildNode(%o), l=%o", this, ftnode, ftnode.getLevel()); + if ( opts.minExpandLevel >= ftnode.getLevel() ) { +// tree.logDebug ("Force expand for %o", ftnode); + this.bExpanded = true; + } + + // In multi-hier mode, update the parents selection state + // DT issue #82: only if not initializing, because the children may not exist yet +// if( !ftnode.data.isStatusNode() && opts.selectMode==3 && !isInitializing ) +// ftnode._fixSelectionState(); + + // In multi-hier mode, update the parents selection state + if( ftnode.bSelected && opts.selectMode==3 ) { + var p = this; + while( p ) { + if( !p.hasSubSel ) + p._setSubSel(true); + p = p.parent; + } + } + // render this node and the new child + if ( tree.bEnableUpdate ) + this.render(); + + return ftnode; + +*/ + }, + /** Set focus relative to this node and optionally activate. + * + * @param {number} where The keyCode that would normally trigger this move, + * e.g. `$.ui.keyCode.LEFT` would collapse the node if it + * is expanded or move to the parent oterwise. + * @param {boolean} [activate=true] + * @returns {$.Promise} + */ + // navigate: function(where, activate) { + // console.time("navigate") + // this._navigate(where, activate) + // console.timeEnd("navigate") + // }, + navigate: function(where, activate) { + var i, parents, + handled = true, + KC = $.ui.keyCode, + sib = null; + + // Navigate to node + function _goto(n){ + if( n ){ + try { n.makeVisible(); } catch(e) {} // #272 + // Node may still be hidden by a filter + if( ! $(n.span).is(":visible") ) { + n.debug("Navigate: skipping hidden node"); + n.navigate(where, activate); + return; + } + return activate === false ? n.setFocus() : n.setActive(); + } + } + + switch( where ) { + case KC.BACKSPACE: + if( this.parent && this.parent.parent ) { + _goto(this.parent); + } + break; + case KC.LEFT: + if( this.expanded ) { + this.setExpanded(false); + _goto(this); + } else if( this.parent && this.parent.parent ) { + _goto(this.parent); + } + break; + case KC.RIGHT: + if( !this.expanded && (this.children || this.lazy) ) { + this.setExpanded(); + _goto(this); + } else if( this.children && this.children.length ) { + _goto(this.children[0]); + } + break; + case KC.UP: + sib = this.getPrevSibling(); + // #359: skip hidden sibling nodes, preventing a _goto() recursion + while( sib && !$(sib.span).is(":visible") ) { + sib = sib.getPrevSibling(); + } + while( sib && sib.expanded && sib.children && sib.children.length ) { + sib = sib.children[sib.children.length - 1]; + } + if( !sib && this.parent && this.parent.parent ){ + sib = this.parent; + } + _goto(sib); + break; + case KC.DOWN: + if( this.expanded && this.children && this.children.length ) { + sib = this.children[0]; + } else { + parents = this.getParentList(false, true); + for(i=parents.length-1; i>=0; i--) { + sib = parents[i].getNextSibling(); + // #359: skip hidden sibling nodes, preventing a _goto() recursion + while( sib && !$(sib.span).is(":visible") ) { + sib = sib.getNextSibling(); + } + if( sib ){ break; } + } + } + _goto(sib); + break; + default: + handled = false; + } + }, + /** + * Remove this node (not allowed for system root). + */ + remove: function() { + return this.parent.removeChild(this); + }, + /** + * Remove childNode from list of direct children. + * @param {FancytreeNode} childNode + */ + removeChild: function(childNode) { + return this.tree._callHook("nodeRemoveChild", this, childNode); + }, + /** + * Remove all child nodes and descendents. This converts the node into a leaf.<br> + * If this was a lazy node, it is still considered 'loaded'; call node.resetLazy() + * in order to trigger lazyLoad on next expand. + */ + removeChildren: function() { + return this.tree._callHook("nodeRemoveChildren", this); + }, + /** + * This method renders and updates all HTML markup that is required + * to display this node in its current state.<br> + * Note: + * <ul> + * <li>It should only be neccessary to call this method after the node object + * was modified by direct access to its properties, because the common + * API methods (node.setTitle(), moveTo(), addChildren(), remove(), ...) + * already handle this. + * <li> {@link FancytreeNode#renderTitle} and {@link FancytreeNode#renderStatus} + * are implied. If changes are more local, calling only renderTitle() or + * renderStatus() may be sufficient and faster. + * <li>If a node was created/removed, node.render() must be called <i>on the parent</i>. + * </ul> + * + * @param {boolean} [force=false] re-render, even if html markup was already created + * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed + */ + render: function(force, deep) { + return this.tree._callHook("nodeRender", this, force, deep); + }, + /** Create HTML markup for the node's outer <span> (expander, checkbox, icon, and title). + * @see Fancytree_Hooks#nodeRenderTitle + */ + renderTitle: function() { + return this.tree._callHook("nodeRenderTitle", this); + }, + /** Update element's CSS classes according to node state. + * @see Fancytree_Hooks#nodeRenderStatus + */ + renderStatus: function() { + return this.tree._callHook("nodeRenderStatus", this); + }, + /** + * Remove all children, collapse, and set the lazy-flag, so that the lazyLoad + * event is triggered on next expand. + */ + resetLazy: function() { + this.removeChildren(); + this.expanded = false; + this.lazy = true; + this.children = undefined; + this.renderStatus(); + }, + /** Schedule activity for delayed execution (cancel any pending request). + * scheduleAction('cancel') will only cancel a pending request (if any). + * @param {string} mode + * @param {number} ms + */ + scheduleAction: function(mode, ms) { + if( this.tree.timer ) { + clearTimeout(this.tree.timer); +// this.tree.debug("clearTimeout(%o)", this.tree.timer); + } + this.tree.timer = null; + var self = this; // required for closures + switch (mode) { + case "cancel": + // Simply made sure that timer was cleared + break; + case "expand": + this.tree.timer = setTimeout(function(){ + self.tree.debug("setTimeout: trigger expand"); + self.setExpanded(true); + }, ms); + break; + case "activate": + this.tree.timer = setTimeout(function(){ + self.tree.debug("setTimeout: trigger activate"); + self.setActive(true); + }, ms); + break; + default: + throw "Invalid mode " + mode; + } +// this.tree.debug("setTimeout(%s, %s): %s", mode, ms, this.tree.timer); + }, + /** + * + * @param {boolean | PlainObject} [effects=false] animation options. + * @param {object} [options=null] {topNode: null, effects: ..., parent: ...} this node will remain visible in + * any case, even if `this` is outside the scroll pane. + * @returns {$.Promise} + */ + scrollIntoView: function(effects, options) { + if( options !== undefined && _isNode(options) ) { + this.warn("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead."); + options = {topNode: options}; + } + // this.$scrollParent = (this.options.scrollParent === "auto") ? $ul.scrollParent() : $(this.options.scrollParent); + // this.$scrollParent = this.$scrollParent.length ? this.$scrollParent || this.$container; + + var topNodeY, nodeY, horzScrollbarHeight, containerOffsetTop, + opts = $.extend({ + effects: (effects === true) ? {duration: 200, queue: false} : effects, + scrollOfs: this.tree.options.scrollOfs, + scrollParent: this.tree.options.scrollParent || this.tree.$container, + topNode: null + }, options), + dfd = new $.Deferred(), + that = this, + nodeHeight = $(this.span).height(), + $container = $(opts.scrollParent), + topOfs = opts.scrollOfs.top || 0, + bottomOfs = opts.scrollOfs.bottom || 0, + containerHeight = $container.height(),// - topOfs - bottomOfs, + scrollTop = $container.scrollTop(), + $animateTarget = $container, + isParentWindow = $container[0] === window, + topNode = opts.topNode || null, + newScrollTop = null; + + // this.debug("scrollIntoView(), scrollTop=", scrollTop, opts.scrollOfs); +// _assert($(this.span).is(":visible"), "scrollIntoView node is invisible"); // otherwise we cannot calc offsets + if( !$(this.span).is(":visible") ) { + // We cannot calc offsets for hidden elements + this.warn("scrollIntoView(): node is invisible."); + return _getResolvedPromise(); + } + if( isParentWindow ) { + nodeY = $(this.span).offset().top; + topNodeY = (topNode && topNode.span) ? $(topNode.span).offset().top : 0; + $animateTarget = $("html,body"); + + } else { + _assert($container[0] !== document && $container[0] !== document.body, "scrollParent should be an simple element or `window`, not document or body."); + + containerOffsetTop = $container.offset().top, + nodeY = $(this.span).offset().top - containerOffsetTop + scrollTop; // relative to scroll parent + topNodeY = topNode ? $(topNode.span).offset().top - containerOffsetTop + scrollTop : 0; + horzScrollbarHeight = Math.max(0, ($container.innerHeight() - $container[0].clientHeight)); + containerHeight -= horzScrollbarHeight; + } + + // this.debug(" scrollIntoView(), nodeY=", nodeY, "containerHeight=", containerHeight); + if( nodeY < (scrollTop + topOfs) ){ + // Node is above visible container area + newScrollTop = nodeY - topOfs; + // this.debug(" scrollIntoView(), UPPER newScrollTop=", newScrollTop); + + }else if((nodeY + nodeHeight) > (scrollTop + containerHeight - bottomOfs)){ + newScrollTop = nodeY + nodeHeight - containerHeight + bottomOfs; + // this.debug(" scrollIntoView(), LOWER newScrollTop=", newScrollTop); + // If a topNode was passed, make sure that it is never scrolled + // outside the upper border + if(topNode){ + _assert(topNode.isRoot() || $(topNode.span).is(":visible"), "topNode must be visible"); + if( topNodeY < newScrollTop ){ + newScrollTop = topNodeY - topOfs; + // this.debug(" scrollIntoView(), TOP newScrollTop=", newScrollTop); + } + } + } + + if(newScrollTop !== null){ + // this.debug(" scrollIntoView(), SET newScrollTop=", newScrollTop); + if(opts.effects){ + opts.effects.complete = function(){ + dfd.resolveWith(that); + }; + $animateTarget.stop(true).animate({ + scrollTop: newScrollTop + }, opts.effects); + }else{ + $animateTarget[0].scrollTop = newScrollTop; + dfd.resolveWith(this); + } + }else{ + dfd.resolveWith(this); + } + return dfd.promise(); + }, + + /**Activate this node. + * @param {boolean} [flag=true] pass false to deactivate + * @param {object} [opts] additional options. Defaults to {noEvents: false} + * @returns {$.Promise} + */ + setActive: function(flag, opts){ + return this.tree._callHook("nodeSetActive", this, flag, opts); + }, + /**Expand or collapse this node. Promise is resolved, when lazy loading and animations are done. + * @param {boolean} [flag=true] pass false to collapse + * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false} + * @returns {$.Promise} + */ + setExpanded: function(flag, opts){ + return this.tree._callHook("nodeSetExpanded", this, flag, opts); + }, + /**Set keyboard focus to this node. + * @param {boolean} [flag=true] pass false to blur + * @see Fancytree#setFocus + */ + setFocus: function(flag){ + return this.tree._callHook("nodeSetFocus", this, flag); + }, + /**Select this node, i.e. check the checkbox. + * @param {boolean} [flag=true] pass false to deselect + */ + setSelected: function(flag){ + return this.tree._callHook("nodeSetSelected", this, flag); + }, + /**Mark a lazy node as 'error', 'loading', or 'ok'. + * @param {string} status 'error', 'ok' + * @param {string} [message] + * @param {string} [details] + */ + setStatus: function(status, message, details){ + return this.tree._callHook("nodeSetStatus", this, status, message, details); + }, + /**Rename this node. + * @param {string} title + */ + setTitle: function(title){ + this.title = title; + this.renderTitle(); + }, + /**Sort child list by title. + * @param {function} [cmp] custom compare function(a, b) that returns -1, 0, or 1 (defaults to sort by title). + * @param {boolean} [deep=false] pass true to sort all descendant nodes + */ + sortChildren: function(cmp, deep) { + var i,l, + cl = this.children; + + if( !cl ){ + return; + } + cmp = cmp || function(a, b) { + var x = a.title.toLowerCase(), + y = b.title.toLowerCase(); + return x === y ? 0 : x > y ? 1 : -1; + }; + cl.sort(cmp); + if( deep ){ + for(i=0, l=cl.length; i<l; i++){ + if( cl[i].children ){ + cl[i].sortChildren(cmp, "$norender$"); + } + } + } + if( deep !== "$norender$" ){ + this.render(); + } + }, + /** Convert node (or whole branch) into a plain object. + * + * The result is compatible with node.addChildren(). + * + * @param {boolean} [recursive=false] include child nodes + * @param {function} [callback] callback(dict) is called for every node, in order to allow modifications + * @returns {NodeData} + */ + toDict: function(recursive, callback) { + var i, l, node, + dict = {}, + self = this; + + $.each(NODE_ATTRS, function(i, a){ + if(self[a] || self[a] === false){ + dict[a] = self[a]; + } + }); + if(!$.isEmptyObject(this.data)){ + dict.data = $.extend({}, this.data); + if($.isEmptyObject(dict.data)){ + delete dict.data; + } + } + if( callback ){ + callback(dict); + } + if( recursive ) { + if(this.hasChildren()){ + dict.children = []; + for(i=0, l=this.children.length; i<l; i++ ){ + node = this.children[i]; + if( !node.isStatusNode() ){ + dict.children.push(node.toDict(true, callback)); + } + } + }else{ +// dict.children = null; + } + } + return dict; + }, + /** Flip expanded status. */ + toggleExpanded: function(){ + return this.tree._callHook("nodeToggleExpanded", this); + }, + /** Flip selection status. */ + toggleSelected: function(){ + return this.tree._callHook("nodeToggleSelected", this); + }, + toString: function() { + return "<FancytreeNode(#" + this.key + ", '" + this.title + "')>"; + }, + /** Call fn(node) for all child nodes.<br> + * Stop iteration, if fn() returns false. Skip current branch, if fn() returns "skip".<br> + * Return false if iteration was stopped. + * + * @param {function} fn the callback function. + * Return false to stop iteration, return "skip" to skip this node and + * its children only. + * @param {boolean} [includeSelf=false] + * @returns {boolean} + */ + visit: function(fn, includeSelf) { + var i, l, + res = true, + children = this.children; + + if( includeSelf === true ) { + res = fn(this); + if( res === false || res === "skip" ){ + return res; + } + } + if(children){ + for(i=0, l=children.length; i<l; i++){ + res = children[i].visit(fn, true); + if( res === false ){ + break; + } + } + } + return res; + }, + /** Call fn(node) for all child nodes and recursively load lazy children.<br> + * <b>Note:</b> If you need this method, you probably should consider to review + * your architecture! Recursivley loading nodes is a perfect way for lazy + * programmers to flood the server with requests ;-) + * + * @param {function} [fn] optional callback function. + * Return false to stop iteration, return "skip" to skip this node and + * its children only. + * @param {boolean} [includeSelf=false] + * @returns {$.Promise} + */ + visitAndLoad: function(fn, includeSelf, _recursion) { + var dfd, res, loaders, + node = this; + + // node.debug("visitAndLoad"); + if( fn && includeSelf === true ) { + res = fn(node); + if( res === false || res === "skip" ) { + return _recursion ? res : _getResolvedPromise(); + } + } + if( !node.children && !node.lazy ) { + return _getResolvedPromise(); + } + dfd = new $.Deferred(); + loaders = []; + // node.debug("load()..."); + node.load().done(function(){ + // node.debug("load()... done."); + for(var i=0, l=node.children.length; i<l; i++){ + res = node.children[i].visitAndLoad(fn, true, true); + if( res === false ) { + dfd.reject(); + break; + } else if ( res !== "skip" ) { + loaders.push(res); // Add promise to the list + } + } + $.when.apply(this, loaders).then(function(){ + dfd.resolve(); + }); + }); + return dfd.promise(); + }, + /** Call fn(node) for all parent nodes, bottom-up, including invisible system root.<br> + * Stop iteration, if fn() returns false.<br> + * Return false if iteration was stopped. + * + * @param {function} fn the callback function. + * Return false to stop iteration, return "skip" to skip this node and children only. + * @param {boolean} [includeSelf=false] + * @returns {boolean} + */ + visitParents: function(fn, includeSelf) { + // Visit parent nodes (bottom up) + if(includeSelf && fn(this) === false){ + return false; + } + var p = this.parent; + while( p ) { + if(fn(p) === false){ + return false; + } + p = p.parent; + } + return true; + }, + /** Write warning to browser console (prepending node info) + * + * @param {*} msg string or object or array of such + */ + warn: function(msg){ + Array.prototype.unshift.call(arguments, this.toString()); + consoleApply("warn", arguments); + } +}; + + +/* ***************************************************************************** + * Fancytree + */ +/** + * Construct a new tree object. + * + * @class Fancytree + * @classdesc The controller behind a fancytree. + * This class also contains 'hook methods': see {@link Fancytree_Hooks}. + * + * @param {Widget} widget + * + * @property {FancytreeOptions} options + * @property {FancytreeNode} rootNode + * @property {FancytreeNode} activeNode + * @property {FancytreeNode} focusNode + * @property {jQueryObject} $div + * @property {object} widget + * @property {object} ext + * @property {object} data + * @property {object} options + * @property {string} _id + * @property {string} statusClassPropName + * @property {string} ariaPropName + * @property {string} nodeContainerAttrName + * @property {string} $container + * @property {FancytreeNode} lastSelectedNode + */ +function Fancytree(widget) { + this.widget = widget; + this.$div = widget.element; + this.options = widget.options; + if( this.options ) { + if( $.isFunction(this.options.lazyload ) && !$.isFunction(this.options.lazyLoad) ) { + this.options.lazyLoad = function() { + FT.warn("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead."); + return widget.options.lazyload.apply(this, arguments); + }; + } + if( $.isFunction(this.options.loaderror) ) { + $.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead."); + } + if( this.options.fx !== undefined ) { + FT.warn("The 'fx' options was replaced by 'toggleEffect' since 2014-11-30."); + } + } + this.ext = {}; // Active extension instances + // allow to init tree.data.foo from <div data-foo=''> + this.data = _getElementDataAsDict(this.$div); + this._id = $.ui.fancytree._nextId++; + this._ns = ".fancytree-" + this._id; // append for namespaced events + this.activeNode = null; + this.focusNode = null; + this._hasFocus = null; + this.lastSelectedNode = null; + this.systemFocusElement = null; + this.lastQuicksearchTerm = ""; + this.lastQuicksearchTime = 0; + + this.statusClassPropName = "span"; + this.ariaPropName = "li"; + this.nodeContainerAttrName = "li"; + + // Remove previous markup if any + this.$div.find(">ul.fancytree-container").remove(); + + // Create a node without parent. + var fakeParent = { tree: this }, + $ul; + this.rootNode = new FancytreeNode(fakeParent, { + title: "root", + key: "root_" + this._id, + children: null, + expanded: true + }); + this.rootNode.parent = null; + + // Create root markup + $ul = $("<ul>", { + "class": "ui-fancytree fancytree-container" + }).appendTo(this.$div); + this.$container = $ul; + this.rootNode.ul = $ul[0]; + + if(this.options.debugLevel == null){ + this.options.debugLevel = FT.debugLevel; + } + // Add container to the TAB chain + // See http://www.w3.org/TR/wai-aria-practices/#focus_activedescendant + this.$container.attr("tabindex", this.options.tabbable ? "0" : "-1"); + if(this.options.aria){ + this.$container + .attr("role", "tree") + .attr("aria-multiselectable", true); + } +} + + +Fancytree.prototype = /** @lends Fancytree# */{ + /* Return a context object that can be re-used for _callHook(). + * @param {Fancytree | FancytreeNode | EventData} obj + * @param {Event} originalEvent + * @param {Object} extra + * @returns {EventData} + */ + _makeHookContext: function(obj, originalEvent, extra) { + var ctx, tree; + if(obj.node !== undefined){ + // obj is already a context object + if(originalEvent && obj.originalEvent !== originalEvent){ + $.error("invalid args"); + } + ctx = obj; + }else if(obj.tree){ + // obj is a FancytreeNode + tree = obj.tree; + ctx = { node: obj, tree: tree, widget: tree.widget, options: tree.widget.options, originalEvent: originalEvent }; + }else if(obj.widget){ + // obj is a Fancytree + ctx = { node: null, tree: obj, widget: obj.widget, options: obj.widget.options, originalEvent: originalEvent }; + }else{ + $.error("invalid args"); + } + if(extra){ + $.extend(ctx, extra); + } + return ctx; + }, + /* Trigger a hook function: funcName(ctx, [...]). + * + * @param {string} funcName + * @param {Fancytree|FancytreeNode|EventData} contextObject + * @param {any} [_extraArgs] optional additional arguments + * @returns {any} + */ + _callHook: function(funcName, contextObject, _extraArgs) { + var ctx = this._makeHookContext(contextObject), + fn = this[funcName], + args = Array.prototype.slice.call(arguments, 2); + if(!$.isFunction(fn)){ + $.error("_callHook('" + funcName + "') is not a function"); + } + args.unshift(ctx); +// this.debug("_hook", funcName, ctx.node && ctx.node.toString() || ctx.tree.toString(), args); + return fn.apply(this, args); + }, + /* Check if current extensions dependencies are met and throw an error if not. + * + * This method may be called inside the `treeInit` hook for custom extensions. + * + * @param {string} extension name of the required extension + * @param {boolean} [required=true] pass `false` if the extension is optional, but we want to check for order if it is present + * @param {boolean} [before] `true` if `name` must be included before this, `false` otherwise (use `null` if order doesn't matter) + * @param {string} [message] optional error message (defaults to a descriptve error message) + */ + _requireExtension: function(name, required, before, message) { + before = !!before; + var thisName = this._local.name, + extList = this.options.extensions, + isBefore = $.inArray(name, extList) < $.inArray(thisName, extList), + isMissing = required && this.ext[name] == null, + badOrder = !isMissing && before != null && (before !== isBefore); + + _assert(thisName && thisName !== name); + + if( isMissing || badOrder ){ + if( !message ){ + if( isMissing || required ){ + message = "'" + thisName + "' extension requires '" + name + "'"; + if( badOrder ){ + message += " to be registered " + (before ? "before" : "after") + " itself"; + } + }else{ + message = "If used together, `" + name + "` must be registered " + (before ? "before" : "after") + " `" + thisName + "`"; + } + } + $.error(message); + return false; + } + return true; + }, + /** Activate node with a given key and fire focus and activate events. + * + * A prevously activated node will be deactivated. + * If activeVisible option is set, all parents will be expanded as necessary. + * Pass key = false, to deactivate the current node only. + * @param {string} key + * @returns {FancytreeNode} activated node (null, if not found) + */ + activateKey: function(key) { + var node = this.getNodeByKey(key); + if(node){ + node.setActive(); + }else if(this.activeNode){ + this.activeNode.setActive(false); + } + return node; + }, + /** (experimental) + * + * @param {Array} patchList array of [key, NodePatch] arrays + * @returns {$.Promise} resolved, when all patches have been applied + * @see TreePatch + */ + applyPatch: function(patchList) { + var dfd, i, p2, key, patch, node, + patchCount = patchList.length, + deferredList = []; + + for(i=0; i<patchCount; i++){ + p2 = patchList[i]; + _assert(p2.length === 2, "patchList must be an array of length-2-arrays"); + key = p2[0]; + patch = p2[1]; + node = (key === null) ? this.rootNode : this.getNodeByKey(key); + if(node){ + dfd = new $.Deferred(); + deferredList.push(dfd); + node.applyPatch(patch).always(_makeResolveFunc(dfd, node)); + }else{ + this.warn("could not find node with key '" + key + "'"); + } + } + // Return a promise that is resolved, when ALL patches were applied + return $.when.apply($, deferredList).promise(); + }, + /* TODO: implement in dnd extension + cancelDrag: function() { + var dd = $.ui.ddmanager.current; + if(dd){ + dd.cancel(); + } + }, + */ + /** Return the number of nodes. + * @returns {integer} + */ + count: function() { + return this.rootNode.countChildren(); + }, + /** Write to browser console if debugLevel >= 2 (prepending tree name) + * + * @param {*} msg string or object or array of such + */ + debug: function(msg){ + if( this.options.debugLevel >= 2 ) { + Array.prototype.unshift.call(arguments, this.toString()); + consoleApply("log", arguments); + } + }, + // TODO: disable() + // TODO: enable() + // TODO: enableUpdate() + + /** Find the next visible node that starts with `match`, starting at `startNode` + * and wrap-around at the end. + * + * @param {string|function} match + * @param {FancytreeNode} [startNode] defaults to first node + * @returns {FancytreeNode} matching node or null + */ + findNextNode: function(match, startNode, visibleOnly) { + var stopNode = null, + parentChildren = startNode.parent.children, + matchingNode = null, + walkVisible = function(parent, idx, fn) { + var i, grandParent, + parentChildren = parent.children, + siblingCount = parentChildren.length, + node = parentChildren[idx]; + // visit node itself + if( node && fn(node) === false ) { + return false; + } + // visit descendants + if( node && node.children && node.expanded ) { + if( walkVisible(node, 0, fn) === false ) { + return false; + } + } + // visit subsequent siblings + for( i = idx + 1; i < siblingCount; i++ ) { + if( walkVisible(parent, i, fn) === false ) { + return false; + } + } + // visit parent's subsequent siblings + grandParent = parent.parent; + if( grandParent ) { + return walkVisible(grandParent, grandParent.children.indexOf(parent) + 1, fn); + } else { + // wrap-around: restart with first node + return walkVisible(parent, 0, fn); + } + }; + + match = (typeof match === "string") ? _makeNodeTitleStartMatcher(match) : match; + startNode = startNode || this.getFirstChild(); + + walkVisible(startNode.parent, parentChildren.indexOf(startNode), function(node){ + // Stop iteration if we see the start node a second time + if( node === stopNode ) { + return false; + } + stopNode = stopNode || node; + // Ignore nodes hidden by a filter + if( ! $(node.span).is(":visible") ) { + node.debug("quicksearch: skipping hidden node"); + return; + } + // Test if we found a match, but search for a second match if this + // was the currently active node + if( match(node) ) { + // node.debug("quicksearch match " + node.title, startNode); + matchingNode = node; + if( matchingNode !== startNode ) { + return false; + } + } + }); + return matchingNode; + }, + // TODO: fromDict + /** + * Generate INPUT elements that can be submitted with html forms. + * + * In selectMode 3 only the topmost selected nodes are considered, unless + * `opts.stopOnParents: false` is passed. + * + * @param {boolean | string} [selected=true] Pass false to disable, pass a string to overide the field name (default: 'ft_ID[]') + * @param {boolean | string} [active=true] Pass false to disable, pass a string to overide the field name (default: 'ft_ID_active') + * @param {object} [opts] default { stopOnParents: true } + */ + generateFormElements: function(selected, active, opts) { + // TODO: test case + opts = opts || {}; + + var nodeList, + selectedName = (typeof selected === "string") ? selected : "ft_" + this._id + "[]", + activeName = (typeof active === "string") ? active : "ft_" + this._id + "_active", + id = "fancytree_result_" + this._id, + $result = $("#" + id), + stopOnParents = this.options.selectMode === 3 && opts.stopOnParents !== false; + + if($result.length){ + $result.empty(); + }else{ + $result = $("<div>", { + id: id + }).hide().insertAfter(this.$container); + } + if(selected !== false){ + nodeList = this.getSelectedNodes(stopOnParents); + $.each(nodeList, function(idx, node){ + $result.append($("<input>", { + type: "checkbox", + name: selectedName, + value: node.key, + checked: true + })); + }); + } + if(active !== false && this.activeNode){ + $result.append($("<input>", { + type: "radio", + name: activeName, + value: this.activeNode.key, + checked: true + })); + } + }, + /** + * Return the currently active node or null. + * @returns {FancytreeNode} + */ + getActiveNode: function() { + return this.activeNode; + }, + /** Return the first top level node if any (not the invisible root node). + * @returns {FancytreeNode | null} + */ + getFirstChild: function() { + return this.rootNode.getFirstChild(); + }, + /** + * Return node that has keyboard focus or null. + * @returns {FancytreeNode} + */ + getFocusNode: function() { + return this.focusNode; + }, + /** + * Return node with a given key or null if not found. + * @param {string} key + * @param {FancytreeNode} [searchRoot] only search below this node + * @returns {FancytreeNode | null} + */ + getNodeByKey: function(key, searchRoot) { + // Search the DOM by element ID (assuming this is faster than traversing all nodes). + // $("#...") has problems, if the key contains '.', so we use getElementById() + var el, match; + if(!searchRoot){ + el = document.getElementById(this.options.idPrefix + key); + if( el ){ + return el.ftnode ? el.ftnode : null; + } + } + // Not found in the DOM, but still may be in an unrendered part of tree + // TODO: optimize with specialized loop + // TODO: consider keyMap? + searchRoot = searchRoot || this.rootNode; + match = null; + searchRoot.visit(function(node){ +// window.console.log("getNodeByKey(" + key + "): ", node.key); + if(node.key === key) { + match = node; + return false; + } + }, true); + return match; + }, + /** Return the invisible system root node. + * @returns {FancytreeNode} + */ + getRootNode: function() { + return this.rootNode; + }, + /** + * Return an array of selected nodes. + * @param {boolean} [stopOnParents=false] only return the topmost selected + * node (useful with selectMode 3) + * @returns {FancytreeNode[]} + */ + getSelectedNodes: function(stopOnParents) { + var nodeList = []; + this.rootNode.visit(function(node){ + if( node.selected ) { + nodeList.push(node); + if( stopOnParents === true ){ + return "skip"; // stop processing this branch + } + } + }); + return nodeList; + }, + /** Return true if the tree control has keyboard focus + * @returns {boolean} + */ + hasFocus: function(){ + return !!this._hasFocus; + }, + /** Write to browser console if debugLevel >= 1 (prepending tree name) + * @param {*} msg string or object or array of such + */ + info: function(msg){ + if( this.options.debugLevel >= 1 ) { + Array.prototype.unshift.call(arguments, this.toString()); + consoleApply("info", arguments); + } + }, +/* + TODO: isInitializing: function() { + return ( this.phase=="init" || this.phase=="postInit" ); + }, + TODO: isReloading: function() { + return ( this.phase=="init" || this.phase=="postInit" ) && this.options.persist && this.persistence.cookiesFound; + }, + TODO: isUserEvent: function() { + return ( this.phase=="userEvent" ); + }, +*/ + + /** + * Make sure that a node with a given ID is loaded, by traversing - and + * loading - its parents. This method is ment for lazy hierarchies. + * A callback is executed for every node as we go. + * @example + * tree.loadKeyPath("/_3/_23/_26/_27", function(node, status){ + * if(status === "loaded") { + * console.log("loaded intermiediate node " + node); + * }else if(status === "ok") { + * node.activate(); + * } + * }); + * + * @param {string | string[]} keyPathList one or more key paths (e.g. '/3/2_1/7') + * @param {function} callback callback(node, status) is called for every visited node ('loading', 'loaded', 'ok', 'error') + * @returns {$.Promise} + */ + loadKeyPath: function(keyPathList, callback, _rootNode) { + var deferredList, dfd, i, path, key, loadMap, node, root, segList, + sep = this.options.keyPathSeparator, + self = this; + + if(!$.isArray(keyPathList)){ + keyPathList = [keyPathList]; + } + // Pass 1: handle all path segments for nodes that are already loaded + // Collect distinct top-most lazy nodes in a map + loadMap = {}; + + for(i=0; i<keyPathList.length; i++){ + root = _rootNode || this.rootNode; + path = keyPathList[i]; + // strip leading slash + if(path.charAt(0) === sep){ + path = path.substr(1); + } + // traverse and strip keys, until we hit a lazy, unloaded node + segList = path.split(sep); + while(segList.length){ + key = segList.shift(); +// node = _findDirectChild(root, key); + node = root._findDirectChild(key); + if(!node){ + this.warn("loadKeyPath: key not found: " + key + " (parent: " + root + ")"); + callback.call(this, key, "error"); + break; + }else if(segList.length === 0){ + callback.call(this, node, "ok"); + break; + }else if(!node.lazy || (node.hasChildren() !== undefined )){ + callback.call(this, node, "loaded"); + root = node; + }else{ + callback.call(this, node, "loaded"); +// segList.unshift(key); + if(loadMap[key]){ + loadMap[key].push(segList.join(sep)); + }else{ + loadMap[key] = [segList.join(sep)]; + } + break; + } + } + } +// alert("loadKeyPath: loadMap=" + JSON.stringify(loadMap)); + // Now load all lazy nodes and continue itearation for remaining paths + deferredList = []; + // Avoid jshint warning 'Don't make functions within a loop.': + function __lazyload(key, node, dfd){ + callback.call(self, node, "loading"); + node.load().done(function(){ + self.loadKeyPath.call(self, loadMap[key], callback, node).always(_makeResolveFunc(dfd, self)); + }).fail(function(errMsg){ + self.warn("loadKeyPath: error loading: " + key + " (parent: " + root + ")"); + callback.call(self, node, "error"); + dfd.reject(); + }); + } + for(key in loadMap){ + node = root._findDirectChild(key); +// alert("loadKeyPath: lazy node(" + key + ") = " + node); + dfd = new $.Deferred(); + deferredList.push(dfd); + __lazyload(key, node, dfd); + } + // Return a promise that is resolved, when ALL paths were loaded + return $.when.apply($, deferredList).promise(); + }, + /** Re-fire beforeActivate and activate events. */ + reactivate: function(setFocus) { + var res, + node = this.activeNode; + + if( !node ) { + return _getResolvedPromise(); + } + this.activeNode = null; // Force re-activating + res = node.setActive(); + if( setFocus ){ + node.setFocus(); + } + return res; + }, + /** Reload tree from source and return a promise. + * @param [source] optional new source (defaults to initial source data) + * @returns {$.Promise} + */ + reload: function(source) { + this._callHook("treeClear", this); + return this._callHook("treeLoad", this, source); + }, + /**Render tree (i.e. create DOM elements for all top-level nodes). + * @param {boolean} [force=false] create DOM elemnts, even is parent is collapsed + * @param {boolean} [deep=false] + */ + render: function(force, deep) { + return this.rootNode.render(force, deep); + }, + // TODO: selectKey: function(key, select) + // TODO: serializeArray: function(stopOnParents) + /** + * @param {boolean} [flag=true] + */ + setFocus: function(flag) { + return this._callHook("treeSetFocus", this, flag); + }, + /** + * Return all nodes as nested list of {@link NodeData}. + * + * @param {boolean} [includeRoot=false] Returns the hidden system root node (and its children) + * @param {function} [callback(node)] Called for every node + * @returns {Array | object} + * @see FancytreeNode#toDict + */ + toDict: function(includeRoot, callback){ + var res = this.rootNode.toDict(true, callback); + return includeRoot ? res : res.children; + }, + /* Implicitly called for string conversions. + * @returns {string} + */ + toString: function(){ + return "<Fancytree(#" + this._id + ")>"; + }, + /* _trigger a widget event with additional node ctx. + * @see EventData + */ + _triggerNodeEvent: function(type, node, originalEvent, extra) { +// this.debug("_trigger(" + type + "): '" + ctx.node.title + "'", ctx); + var ctx = this._makeHookContext(node, originalEvent, extra), + res = this.widget._trigger(type, originalEvent, ctx); + if(res !== false && ctx.result !== undefined){ + return ctx.result; + } + return res; + }, + /* _trigger a widget event with additional tree data. */ + _triggerTreeEvent: function(type, originalEvent, extra) { +// this.debug("_trigger(" + type + ")", ctx); + var ctx = this._makeHookContext(this, originalEvent, extra), + res = this.widget._trigger(type, originalEvent, ctx); + + if(res !== false && ctx.result !== undefined){ + return ctx.result; + } + return res; + }, + /** Call fn(node) for all nodes. + * + * @param {function} fn the callback function. + * Return false to stop iteration, return "skip" to skip this node and children only. + * @returns {boolean} false, if the iterator was stopped. + */ + visit: function(fn) { + return this.rootNode.visit(fn, false); + }, + /** Write warning to browser console (prepending tree info) + * + * @param {*} msg string or object or array of such + */ + warn: function(msg){ + Array.prototype.unshift.call(arguments, this.toString()); + consoleApply("warn", arguments); + } +}; + +/** + * These additional methods of the {@link Fancytree} class are 'hook functions' + * that can be used and overloaded by extensions. + * (See <a href="https://github.com/mar10/fancytree/wiki/TutorialExtensions">writing extensions</a>.) + * @mixin Fancytree_Hooks + */ +$.extend(Fancytree.prototype, + /** @lends Fancytree_Hooks# */ + { + /** Default handling for mouse click events. + * + * @param {EventData} ctx + */ + nodeClick: function(ctx) { +// this.tree.logDebug("ftnode.onClick(" + event.type + "): ftnode:" + this + ", button:" + event.button + ", which: " + event.which); + var activate, expand, + // event = ctx.originalEvent, + targetType = ctx.targetType, + node = ctx.node; + + // TODO: use switch + // TODO: make sure clicks on embedded <input> doesn't steal focus (see table sample) + if( targetType === "expander" ) { + // Clicking the expander icon always expands/collapses + this._callHook("nodeToggleExpanded", ctx); + + } else if( targetType === "checkbox" ) { + // Clicking the checkbox always (de)selects + this._callHook("nodeToggleSelected", ctx); + if( ctx.options.focusOnSelect ) { // #358 + this._callHook("nodeSetFocus", ctx, true); + } + + } else { + // Honor `clickFolderMode` for + expand = false; + activate = true; + if( node.folder ) { + switch( ctx.options.clickFolderMode ) { + case 2: // expand only + expand = true; + activate = false; + break; + case 3: // expand and activate + activate = true; + expand = true; //!node.isExpanded(); + break; + // else 1 or 4: just activate + } + } + if( activate ) { + this.nodeSetFocus(ctx); + this._callHook("nodeSetActive", ctx, true); + } + if( expand ) { + if(!activate){ +// this._callHook("nodeSetFocus", ctx); + } +// this._callHook("nodeSetExpanded", ctx, true); + this._callHook("nodeToggleExpanded", ctx); + } + } + // Make sure that clicks stop, otherwise <a href='#'> jumps to the top + // if(event.target.localName === "a" && event.target.className === "fancytree-title"){ + // event.preventDefault(); + // } + // TODO: return promise? + }, + /** Collapse all other children of same parent. + * + * @param {EventData} ctx + * @param {object} callOpts + */ + nodeCollapseSiblings: function(ctx, callOpts) { + // TODO: return promise? + var ac, i, l, + node = ctx.node; + + if( node.parent ){ + ac = node.parent.children; + for (i=0, l=ac.length; i<l; i++) { + if ( ac[i] !== node && ac[i].expanded ){ + this._callHook("nodeSetExpanded", ac[i], false, callOpts); + } + } + } + }, + /** Default handling for mouse douleclick events. + * @param {EventData} ctx + */ + nodeDblclick: function(ctx) { + // TODO: return promise? + if( ctx.targetType === "title" && ctx.options.clickFolderMode === 4) { +// this.nodeSetFocus(ctx); +// this._callHook("nodeSetActive", ctx, true); + this._callHook("nodeToggleExpanded", ctx); + } + // TODO: prevent text selection on dblclicks + if( ctx.targetType === "title" ) { + ctx.originalEvent.preventDefault(); + } + }, + /** Default handling for mouse keydown events. + * + * NOTE: this may be called with node == null if tree (but no node) has focus. + * @param {EventData} ctx + */ + nodeKeydown: function(ctx) { + // TODO: return promise? + var matchNode, stamp, res, + event = ctx.originalEvent, + node = ctx.node, + tree = ctx.tree, + opts = ctx.options, + which = event.which, + whichChar = String.fromCharCode(which), + clean = !(event.altKey || event.ctrlKey || event.metaKey || event.shiftKey), + $target = $(event.target), + handled = true, + activate = !(event.ctrlKey || !opts.autoActivate ); + +// (node || FT).debug("ftnode.nodeKeydown(" + event.type + "): ftnode:" + this + ", charCode:" + event.charCode + ", keyCode: " + event.keyCode + ", which: " + event.which); +// FT.debug("eventToString", which, '"' + String.fromCharCode(which) + '"', '"' + FT.eventToString(event) + '"'); + + // Set focus to active (or first node) if no other node has the focus yet + if( !node ){ + (this.getActiveNode() || this.getFirstChild()).setFocus(); + node = ctx.node = this.focusNode; + node.debug("Keydown force focus on active node"); + } + + if( opts.quicksearch && clean && /\w/.test(whichChar) && !$target.is(":input:enabled") ) { + // Allow to search for longer streaks if typed in quickly + stamp = new Date().getTime(); + if( stamp - tree.lastQuicksearchTime > 500 ) { + tree.lastQuicksearchTerm = ""; + } + tree.lastQuicksearchTime = stamp; + tree.lastQuicksearchTerm += whichChar; + // tree.debug("quicksearch find", tree.lastQuicksearchTerm); + matchNode = tree.findNextNode(tree.lastQuicksearchTerm, tree.getActiveNode()); + if( matchNode ) { + matchNode.setActive(); + } + event.preventDefault(); + return; + } + switch( FT.eventToString(event) ) { + case "+": + case "=": // 187: '+' @ Chrome, Safari + tree.nodeSetExpanded(ctx, true); + break; + case "-": + tree.nodeSetExpanded(ctx, false); + break; + case "space": + if(opts.checkbox){ + tree.nodeToggleSelected(ctx); + }else{ + tree.nodeSetActive(ctx, true); + } + break; + case "enter": + tree.nodeSetActive(ctx, true); + break; + case "backspace": + case "left": + case "right": + case "up": + case "down": + res = node.navigate(event.which, activate); + break; + default: + handled = false; + } + if(handled){ + event.preventDefault(); + } + }, + + + // /** Default handling for mouse keypress events. */ + // nodeKeypress: function(ctx) { + // var event = ctx.originalEvent; + // }, + + // /** Trigger lazyLoad event (async). */ + // nodeLazyLoad: function(ctx) { + // var node = ctx.node; + // if(this._triggerNodeEvent()) + // }, + /** Load child nodes (async). + * + * @param {EventData} ctx + * @param {object[]|object|string|$.Promise|function} source + * @returns {$.Promise} The deferred will be resolved as soon as the (ajax) + * data was rendered. + */ + nodeLoadChildren: function(ctx, source) { + var ajax, delay, dfd, + tree = ctx.tree, + node = ctx.node; + + if($.isFunction(source)){ + source = source(); + } + // TOTHINK: move to 'ajax' extension? + if(source.url){ + // `source` is an Ajax options object + ajax = $.extend({}, ctx.options.ajax, source); + if(ajax.debugDelay){ + // simulate a slow server + delay = ajax.debugDelay; + if($.isArray(delay)){ // random delay range [min..max] + delay = delay[0] + Math.random() * (delay[1] - delay[0]); + } + + node.debug("nodeLoadChildren waiting debug delay " + Math.round(delay) + "ms"); + ajax.debugDelay = false; + dfd = $.Deferred(function (dfd) { + setTimeout(function () { + $.ajax(ajax) + .done(function () { dfd.resolveWith(this, arguments); }) + .fail(function () { dfd.rejectWith(this, arguments); }); + }, delay); + }); + }else{ + dfd = $.ajax(ajax); + } + + // Defer the deferred: we want to be able to reject, even if ajax + // resolved ok. + source = new $.Deferred(); + dfd.done(function (data, textStatus, jqXHR) { + var errorObj, res; + if(typeof data === "string"){ + $.error("Ajax request returned a string (did you get the JSON dataType wrong?)."); + } + // postProcess is similar to the standard ajax dataFilter hook, + // but it is also called for JSONP + if( ctx.options.postProcess ){ + res = tree._triggerNodeEvent("postProcess", ctx, ctx.originalEvent, {response: data, error: null, dataType: this.dataType}); + if( res.error ) { + errorObj = $.isPlainObject(res.error) ? res.error : {message: res.error}; + errorObj = tree._makeHookContext(node, null, errorObj); + source.rejectWith(this, [errorObj]); + return; + } + data = $.isArray(res) ? res : data; + + } else if (data && data.hasOwnProperty("d") && ctx.options.enableAspx ) { + // Process ASPX WebMethod JSON object inside "d" property + data = (typeof data.d === "string") ? $.parseJSON(data.d) : data.d; + } + source.resolveWith(this, [data]); + }).fail(function (jqXHR, textStatus, errorThrown) { + var errorObj = tree._makeHookContext(node, null, { + error: jqXHR, + args: Array.prototype.slice.call(arguments), + message: errorThrown, + details: jqXHR.status + ": " + errorThrown + }); + source.rejectWith(this, [errorObj]); + }); + } + // #383: accept and convert ECMAScript 6 Promise + if( $.isFunction(source.then) && $.isFunction(source["catch"]) ) { + dfd = source; + source = new $.Deferred(); + dfd.then(function(value){ + source.resolve(value); + }, function(reason){ + source.reject(reason); + }); + } + if($.isFunction(source.promise)){ + // `source` is a deferred, i.e. ajax request + _assert(!node.isLoading()); + // node._isLoading = true; + tree.nodeSetStatus(ctx, "loading"); + + source.done(function (children) { + tree.nodeSetStatus(ctx, "ok"); + }).fail(function(error){ + var ctxErr; + if (error.node && error.error && error.message) { + // error is already a context object + ctxErr = error; + } else { + ctxErr = tree._makeHookContext(node, null, { + error: error, // it can be jqXHR or any custom error + args: Array.prototype.slice.call(arguments), + message: error ? (error.message || error.toString()) : "" + }); + } + if( tree._triggerNodeEvent("loadError", ctxErr, null) !== false ) { + tree.nodeSetStatus(ctx, "error", ctxErr.message, ctxErr.details); + } + }); + } + // $.when(source) resolves also for non-deferreds + return $.when(source).done(function(children){ + var metaData; + + if( $.isPlainObject(children) ){ + // We got {foo: 'abc', children: [...]} + // Copy extra properties to tree.data.foo + _assert($.isArray(children.children), "source must contain (or be) an array of children"); + _assert(node.isRoot(), "source may only be an object for root nodes"); + metaData = children; + children = children.children; + delete metaData.children; + $.extend(tree.data, metaData); + } + _assert($.isArray(children), "expected array of children"); + node._setChildren(children); + // trigger fancytreeloadchildren + tree._triggerNodeEvent("loadChildren", node); + // }).always(function(){ + // node._isLoading = false; + }); + }, + /** [Not Implemented] */ + nodeLoadKeyPath: function(ctx, keyPathList) { + // TODO: implement and improve + // http://code.google.com/p/dynatree/issues/detail?id=222 + }, + /** + * Remove a single direct child of ctx.node. + * @param {EventData} ctx + * @param {FancytreeNode} childNode dircect child of ctx.node + */ + nodeRemoveChild: function(ctx, childNode) { + var idx, + node = ctx.node, + opts = ctx.options, + subCtx = $.extend({}, ctx, {node: childNode}), + children = node.children; + + // FT.debug("nodeRemoveChild()", node.toString(), childNode.toString()); + + if( children.length === 1 ) { + _assert(childNode === children[0]); + return this.nodeRemoveChildren(ctx); + } + if( this.activeNode && (childNode === this.activeNode || this.activeNode.isDescendantOf(childNode))){ + this.activeNode.setActive(false); // TODO: don't fire events + } + if( this.focusNode && (childNode === this.focusNode || this.focusNode.isDescendantOf(childNode))){ + this.focusNode = null; + } + // TODO: persist must take care to clear select and expand cookies + this.nodeRemoveMarkup(subCtx); + this.nodeRemoveChildren(subCtx); + idx = $.inArray(childNode, children); + _assert(idx >= 0); + // Unlink to support GC + childNode.visit(function(n){ + n.parent = null; + }, true); + this._callHook("treeRegisterNode", this, false, childNode); + if ( opts.removeNode ){ + opts.removeNode.call(ctx.tree, {type: "removeNode"}, subCtx); + } + // remove from child list + children.splice(idx, 1); + }, + /**Remove HTML markup for all descendents of ctx.node. + * @param {EventData} ctx + */ + nodeRemoveChildMarkup: function(ctx) { + var node = ctx.node; + + // FT.debug("nodeRemoveChildMarkup()", node.toString()); + // TODO: Unlink attr.ftnode to support GC + if(node.ul){ + if( node.isRoot() ) { + $(node.ul).empty(); + } else { + $(node.ul).remove(); + node.ul = null; + } + node.visit(function(n){ + n.li = n.ul = null; + }); + } + }, + /**Remove all descendants of ctx.node. + * @param {EventData} ctx + */ + nodeRemoveChildren: function(ctx) { + var subCtx, + tree = ctx.tree, + node = ctx.node, + children = node.children, + opts = ctx.options; + + // FT.debug("nodeRemoveChildren()", node.toString()); + if(!children){ + return; + } + if( this.activeNode && this.activeNode.isDescendantOf(node)){ + this.activeNode.setActive(false); // TODO: don't fire events + } + if( this.focusNode && this.focusNode.isDescendantOf(node)){ + this.focusNode = null; + } + // TODO: persist must take care to clear select and expand cookies + this.nodeRemoveChildMarkup(ctx); + // Unlink children to support GC + // TODO: also delete this.children (not possible using visit()) + subCtx = $.extend({}, ctx); + node.visit(function(n){ + n.parent = null; + tree._callHook("treeRegisterNode", tree, false, n); + if ( opts.removeNode ){ + subCtx.node = n; + opts.removeNode.call(ctx.tree, {type: "removeNode"}, subCtx); + } + }); + if( node.lazy ){ + // 'undefined' would be interpreted as 'not yet loaded' for lazy nodes + node.children = []; + } else{ + node.children = null; + } + this.nodeRenderStatus(ctx); + }, + /**Remove HTML markup for ctx.node and all its descendents. + * @param {EventData} ctx + */ + nodeRemoveMarkup: function(ctx) { + var node = ctx.node; + // FT.debug("nodeRemoveMarkup()", node.toString()); + // TODO: Unlink attr.ftnode to support GC + if(node.li){ + $(node.li).remove(); + node.li = null; + } + this.nodeRemoveChildMarkup(ctx); + }, + /** + * Create `&lt;li>&lt;span>..&lt;/span> .. &lt;/li>` tags for this node. + * + * This method takes care that all HTML markup is created that is required + * to display this node in it's current state. + * + * Call this method to create new nodes, or after the strucuture + * was changed (e.g. after moving this node or adding/removing children) + * nodeRenderTitle() and nodeRenderStatus() are implied. + * + * Note: if a node was created/removed, nodeRender() must be called for the + * parent. + * <code> + * <li id='KEY' ftnode=NODE> + * <span class='fancytree-node fancytree-expanded fancytree-has-children fancytree-lastsib fancytree-exp-el fancytree-ico-e'> + * <span class="fancytree-expander"></span> + * <span class="fancytree-checkbox"></span> // only present in checkbox mode + * <span class="fancytree-icon"></span> + * <a href="#" class="fancytree-title"> Node 1 </a> + * </span> + * <ul> // only present if node has children + * <li id='KEY' ftnode=NODE> child1 ... </li> + * <li id='KEY' ftnode=NODE> child2 ... </li> + * </ul> + * </li> + * </code> + * + * @param {EventData} ctx + * @param {boolean} [force=false] re-render, even if html markup was already created + * @param {boolean} [deep=false] also render all descendants, even if parent is collapsed + * @param {boolean} [collapsed=false] force root node to be collapsed, so we can apply animated expand later + */ + nodeRender: function(ctx, force, deep, collapsed, _recursive) { + /* This method must take care of all cases where the current data mode + * (i.e. node hierarchy) does not match the current markup. + * + * - node was not yet rendered: + * create markup + * - node was rendered: exit fast + * - children have been added + * - childern have been removed + */ + var childLI, childNode1, childNode2, i, l, next, subCtx, + node = ctx.node, + tree = ctx.tree, + opts = ctx.options, + aria = opts.aria, + firstTime = false, + parent = node.parent, + isRootNode = !parent, + children = node.children; + // FT.debug("nodeRender(" + !!force + ", " + !!deep + ")", node.toString()); + + if( ! isRootNode && ! parent.ul ) { + // Calling node.collapse on a deep, unrendered node + return; + } + _assert(isRootNode || parent.ul, "parent UL must exist"); + + // Render the node + if( !isRootNode ){ + // Discard markup on force-mode, or if it is not linked to parent <ul> + if(node.li && (force || (node.li.parentNode !== node.parent.ul) ) ){ + if(node.li.parentNode !== node.parent.ul){ + // May happen, when a top-level node was dropped over another + this.debug("Unlinking " + node + " (must be child of " + node.parent + ")"); + } +// this.debug("nodeRemoveMarkup..."); + this.nodeRemoveMarkup(ctx); + } + // Create <li><span /> </li> +// node.debug("render..."); + if( !node.li ) { +// node.debug("render... really"); + firstTime = true; + node.li = document.createElement("li"); + node.li.ftnode = node; + if(aria){ + // TODO: why doesn't this work: +// node.li.role = "treeitem"; +// $(node.li).attr("role", "treeitem") +// .attr("aria-labelledby", "ftal_" + node.key); + } + if( node.key && opts.generateIds ){ + node.li.id = opts.idPrefix + node.key; + } + node.span = document.createElement("span"); + node.span.className = "fancytree-node"; + if(aria){ + $(node.span).attr("aria-labelledby", "ftal_" + node.key); + } + node.li.appendChild(node.span); + + // Create inner HTML for the <span> (expander, checkbox, icon, and title) + this.nodeRenderTitle(ctx); + + // Allow tweaking and binding, after node was created for the first time + if ( opts.createNode ){ + opts.createNode.call(tree, {type: "createNode"}, ctx); + } + }else{ +// this.nodeRenderTitle(ctx); + this.nodeRenderStatus(ctx); + } + // Allow tweaking after node state was rendered + if ( opts.renderNode ){ + opts.renderNode.call(tree, {type: "renderNode"}, ctx); + } + } + + // Visit child nodes + if( children ){ + if( isRootNode || node.expanded || deep === true ) { + // Create a UL to hold the children + if( !node.ul ){ + node.ul = document.createElement("ul"); + if((collapsed === true && !_recursive) || !node.expanded){ + // hide top UL, so we can use an animation to show it later + node.ul.style.display = "none"; + } + if(aria){ + $(node.ul).attr("role", "group"); + } + if ( node.li ) { // issue #67 + node.li.appendChild(node.ul); + } else { + node.tree.$div.append(node.ul); + } + } + // Add child markup + for(i=0, l=children.length; i<l; i++) { + subCtx = $.extend({}, ctx, {node: children[i]}); + this.nodeRender(subCtx, force, deep, false, true); + } + // Remove <li> if nodes have moved to another parent + childLI = node.ul.firstChild; + while( childLI ){ + childNode2 = childLI.ftnode; + if( childNode2 && childNode2.parent !== node ) { + node.debug("_fixParent: remove missing " + childNode2, childLI); + next = childLI.nextSibling; + childLI.parentNode.removeChild(childLI); + childLI = next; + }else{ + childLI = childLI.nextSibling; + } + } + // Make sure, that <li> order matches node.children order. + childLI = node.ul.firstChild; + for(i=0, l=children.length-1; i<l; i++) { + childNode1 = children[i]; + childNode2 = childLI.ftnode; + if( childNode1 !== childNode2 ) { + // node.debug("_fixOrder: mismatch at index " + i + ": " + childNode1 + " != " + childNode2); + node.ul.insertBefore(childNode1.li, childNode2.li); + } else { + childLI = childLI.nextSibling; + } + } + } + }else{ + // No children: remove markup if any + if( node.ul ){ +// alert("remove child markup for " + node); + this.warn("remove child markup for " + node); + this.nodeRemoveChildMarkup(ctx); + } + } + if( !isRootNode ){ + // Update element classes according to node state + // this.nodeRenderStatus(ctx); + // Finally add the whole structure to the DOM, so the browser can render + if(firstTime){ + parent.ul.appendChild(node.li); + } + } + }, + /** Create HTML for the node's outer <span> (expander, checkbox, icon, and title). + * + * nodeRenderStatus() is implied. + * @param {EventData} ctx + * @param {string} [title] optinal new title + */ + nodeRenderTitle: function(ctx, title) { + // set node connector images, links and text + var id, iconSpanClass, nodeTitle, role, tabindex, tooltip, + node = ctx.node, + tree = ctx.tree, + opts = ctx.options, + aria = opts.aria, + level = node.getLevel(), + ares = [], + iconSrc = node.data.icon; + + if(title !== undefined){ + node.title = title; + } + if(!node.span){ + // Silently bail out if node was not rendered yet, assuming + // node.render() will be called as the node becomes visible + return; + } + // connector (expanded, expandable or simple) + // TODO: optimize this if clause + if( level < opts.minExpandLevel ) { + if( !node.lazy ) { + node.expanded = true; + } + if(level > 1){ + if(aria){ + ares.push("<span role='button' class='fancytree-expander fancytree-expander-fixed'></span>"); + }else{ + ares.push("<span class='fancytree-expander fancytree-expander-fixed''></span>"); + } + } + // .. else (i.e. for root level) skip expander/connector alltogether + } else { + if(aria){ + ares.push("<span role='button' class='fancytree-expander'></span>"); + }else{ + ares.push("<span class='fancytree-expander'></span>"); + } + } + // Checkbox mode + if( opts.checkbox && node.hideCheckbox !== true && !node.isStatusNode() ) { + if(aria){ + ares.push("<span role='checkbox' class='fancytree-checkbox'></span>"); + }else{ + ares.push("<span class='fancytree-checkbox'></span>"); + } + } + // folder or doctype icon + role = aria ? " role='img'" : ""; + if( iconSrc === true || (iconSrc !== false && opts.icons !== false) ) { + // opts.icons defines the default behavior, node.icon == true/false can override this + if ( iconSrc && typeof iconSrc === "string" ) { + // node.icon is an image url + iconSrc = (iconSrc.charAt(0) === "/") ? iconSrc : ((opts.imagePath || "") + iconSrc); + ares.push("<img src='" + iconSrc + "' class='fancytree-icon' alt='' />"); + } else { + // See if node.iconClass or opts.iconClass() define a class name + iconSpanClass = (opts.iconClass && opts.iconClass.call(tree, node, ctx)) || node.data.iconclass || null; + if( iconSpanClass ) { + ares.push("<span " + role + " class='fancytree-custom-icon " + iconSpanClass + "'></span>"); + } else { + ares.push("<span " + role + " class='fancytree-icon'></span>"); + } + } + } + + // node title + nodeTitle = ""; + if ( opts.renderTitle ){ + nodeTitle = opts.renderTitle.call(tree, {type: "renderTitle"}, ctx) || ""; + } + if(!nodeTitle){ + tooltip = node.tooltip ? " title='" + FT.escapeHtml(node.tooltip) + "'" : ""; + id = aria ? " id='ftal_" + node.key + "'" : ""; + role = aria ? " role='treeitem'" : ""; + tabindex = opts.titlesTabbable ? " tabindex='0'" : ""; + + nodeTitle = "<span " + role + " class='fancytree-title'" + id + tooltip + tabindex + ">" + node.title + "</span>"; + } + ares.push(nodeTitle); + // Note: this will trigger focusout, if node had the focus + //$(node.span).html(ares.join("")); // it will cleanup the jQuery data currently associated with SPAN (if any), but it executes more slowly + node.span.innerHTML = ares.join(""); + // Update CSS classes + this.nodeRenderStatus(ctx); + }, + /** Update element classes according to node state. + * @param {EventData} ctx + */ + nodeRenderStatus: function(ctx) { + // Set classes for current status + var node = ctx.node, + tree = ctx.tree, + opts = ctx.options, +// nodeContainer = node[tree.nodeContainerAttrName], + hasChildren = node.hasChildren(), + isLastSib = node.isLastSibling(), + aria = opts.aria, +// $ariaElem = aria ? $(node[tree.ariaPropName]) : null, + $ariaElem = $(node.span).find(".fancytree-title"), + cn = opts._classNames, + cnList = [], + statusElem = node[tree.statusClassPropName]; + + if( !statusElem ){ + // if this function is called for an unrendered node, ignore it (will be updated on nect render anyway) + return; + } + // Build a list of class names that we will add to the node <span> + cnList.push(cn.node); + if( tree.activeNode === node ){ + cnList.push(cn.active); +// $(">span.fancytree-title", statusElem).attr("tabindex", "0"); +// tree.$container.removeAttr("tabindex"); + // }else{ +// $(">span.fancytree-title", statusElem).removeAttr("tabindex"); +// tree.$container.attr("tabindex", "0"); + } + if( tree.focusNode === node ){ + cnList.push(cn.focused); + if(aria){ +// $(">span.fancytree-title", statusElem).attr("tabindex", "0"); +// $(">span.fancytree-title", statusElem).attr("tabindex", "-1"); + // TODO: is this the right element for this attribute? + $ariaElem + .attr("aria-activedescendant", true); +// .attr("tabindex", "-1"); + } + }else if(aria){ +// $(">span.fancytree-title", statusElem).attr("tabindex", "-1"); + $ariaElem + .removeAttr("aria-activedescendant"); +// .removeAttr("tabindex"); + } + if( node.expanded ){ + cnList.push(cn.expanded); + if(aria){ + $ariaElem.attr("aria-expanded", true); + } + }else if(aria){ + $ariaElem.removeAttr("aria-expanded"); + } + if( node.folder ){ + cnList.push(cn.folder); + } + if( hasChildren !== false ){ + cnList.push(cn.hasChildren); + } + // TODO: required? + if( isLastSib ){ + cnList.push(cn.lastsib); + } + if( node.lazy && node.children == null ){ + cnList.push(cn.lazy); + } + if( node.partsel ){ + cnList.push(cn.partsel); + } + if( node.unselectable ){ + cnList.push(cn.unselectable); + } + if( node._isLoading ){ + cnList.push(cn.loading); + } + if( node._error ){ + cnList.push(cn.error); + } + if( node.selected ){ + cnList.push(cn.selected); + if(aria){ + $ariaElem.attr("aria-selected", true); + } + }else if(aria){ + $ariaElem.attr("aria-selected", false); + } + if( node.extraClasses ){ + cnList.push(node.extraClasses); + } + // IE6 doesn't correctly evaluate multiple class names, + // so we create combined class names that can be used in the CSS + if( hasChildren === false ){ + cnList.push(cn.combinedExpanderPrefix + "n" + + (isLastSib ? "l" : "") + ); + }else{ + cnList.push(cn.combinedExpanderPrefix + + (node.expanded ? "e" : "c") + + (node.lazy && node.children == null ? "d" : "") + + (isLastSib ? "l" : "") + ); + } + cnList.push(cn.combinedIconPrefix + + (node.expanded ? "e" : "c") + + (node.folder ? "f" : "") + ); +// node.span.className = cnList.join(" "); + statusElem.className = cnList.join(" "); + + // TODO: we should not set this in the <span> tag also, if we set it here: + // Maybe most (all) of the classes should be set in LI instead of SPAN? + if(node.li){ + node.li.className = isLastSib ? cn.lastsib : ""; + } + }, + /** Activate node. + * flag defaults to true. + * If flag is true, the node is activated (must be a synchronous operation) + * If flag is false, the node is deactivated (must be a synchronous operation) + * @param {EventData} ctx + * @param {boolean} [flag=true] + * @param {object} [opts] additional options. Defaults to {noEvents: false, noFocus: false} + * @returns {$.Promise} + */ + nodeSetActive: function(ctx, flag, callOpts) { + // Handle user click / [space] / [enter], according to clickFolderMode. + callOpts = callOpts || {}; + var subCtx, + node = ctx.node, + tree = ctx.tree, + opts = ctx.options, + noEvents = (callOpts.noEvents === true), + noFocus = (callOpts.noFocus === true), + isActive = (node === tree.activeNode); + + // flag defaults to true + flag = (flag !== false); + // node.debug("nodeSetActive", flag); + + if(isActive === flag){ + // Nothing to do + return _getResolvedPromise(node); + }else if(flag && !noEvents && this._triggerNodeEvent("beforeActivate", node, ctx.originalEvent) === false ){ + // Callback returned false + return _getRejectedPromise(node, ["rejected"]); + } + if(flag){ + if(tree.activeNode){ + _assert(tree.activeNode !== node, "node was active (inconsistency)"); + subCtx = $.extend({}, ctx, {node: tree.activeNode}); + tree.nodeSetActive(subCtx, false); + _assert(tree.activeNode === null, "deactivate was out of sync?"); + } + if(opts.activeVisible){ + // tree.nodeMakeVisible(ctx); + node.makeVisible({scrollIntoView: false}); // nodeSetFocus will scroll + } + tree.activeNode = node; + tree.nodeRenderStatus(ctx); + if( !noFocus ) { + tree.nodeSetFocus(ctx); + } + if( !noEvents ) { + tree._triggerNodeEvent("activate", node, ctx.originalEvent); + } + }else{ + _assert(tree.activeNode === node, "node was not active (inconsistency)"); + tree.activeNode = null; + this.nodeRenderStatus(ctx); + if( !noEvents ) { + ctx.tree._triggerNodeEvent("deactivate", node, ctx.originalEvent); + } + } + }, + /** Expand or collapse node, return Deferred.promise. + * + * @param {EventData} ctx + * @param {boolean} [flag=true] + * @param {object} [opts] additional options. Defaults to {noAnimation: false, noEvents: false} + * @returns {$.Promise} The deferred will be resolved as soon as the (lazy) + * data was retrieved, rendered, and the expand animation finshed. + */ + nodeSetExpanded: function(ctx, flag, callOpts) { + callOpts = callOpts || {}; + var _afterLoad, dfd, i, l, parents, prevAC, + node = ctx.node, + tree = ctx.tree, + opts = ctx.options, + noAnimation = (callOpts.noAnimation === true), + noEvents = (callOpts.noEvents === true); + + // flag defaults to true + flag = (flag !== false); + + // node.debug("nodeSetExpanded(" + flag + ")"); + + if((node.expanded && flag) || (!node.expanded && !flag)){ + // Nothing to do + // node.debug("nodeSetExpanded(" + flag + "): nothing to do"); + return _getResolvedPromise(node); + }else if(flag && !node.lazy && !node.hasChildren() ){ + // Prevent expanding of empty nodes + // return _getRejectedPromise(node, ["empty"]); + return _getResolvedPromise(node); + }else if( !flag && node.getLevel() < opts.minExpandLevel ) { + // Prevent collapsing locked levels + return _getRejectedPromise(node, ["locked"]); + }else if ( !noEvents && this._triggerNodeEvent("beforeExpand", node, ctx.originalEvent) === false ){ + // Callback returned false + return _getRejectedPromise(node, ["rejected"]); + } + // If this node inside a collpased node, no animation and scrolling is needed + if( !noAnimation && !node.isVisible() ) { + noAnimation = callOpts.noAnimation = true; + } + + dfd = new $.Deferred(); + + // Auto-collapse mode: collapse all siblings + if( flag && !node.expanded && opts.autoCollapse ) { + parents = node.getParentList(false, true); + prevAC = opts.autoCollapse; + try{ + opts.autoCollapse = false; + for(i=0, l=parents.length; i<l; i++){ + // TODO: should return promise? + this._callHook("nodeCollapseSiblings", parents[i], callOpts); + } + }finally{ + opts.autoCollapse = prevAC; + } + } + // Trigger expand/collapse after expanding + dfd.done(function(){ + if( flag && opts.autoScroll && !noAnimation ) { + // Scroll down to last child, but keep current node visible + node.getLastChild().scrollIntoView(true, {topNode: node}).always(function(){ + if( !noEvents ) { + ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx); + } + }); + } else { + if( !noEvents ) { + ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx); + } + } + }); + // vvv Code below is executed after loading finished: + _afterLoad = function(callback){ + var isVisible, isExpanded, + effect = opts.toggleEffect; + + node.expanded = flag; + // Create required markup, but make sure the top UL is hidden, so we + // can animate later + tree._callHook("nodeRender", ctx, false, false, true); + + // If the currently active node is now hidden, deactivate it + // if( opts.activeVisible && this.activeNode && ! this.activeNode.isVisible() ) { + // this.activeNode.deactivate(); + // } + + // Expanding a lazy node: set 'loading...' and call callback + // if( bExpand && this.data.isLazy && this.childList === null && !this._isLoading ) { + // this._loadContent(); + // return; + // } + // Hide children, if node is collapsed + if( node.ul ) { + isVisible = (node.ul.style.display !== "none"); + isExpanded = !!node.expanded; + if ( isVisible === isExpanded ) { + node.warn("nodeSetExpanded: UL.style.display already set"); + + } else if ( !effect || noAnimation ) { + node.ul.style.display = ( node.expanded || !parent ) ? "" : "none"; + + } else { + // The UI toggle() effect works with the ext-wide extension, + // while jQuery.animate() has problems when the title span + // has positon: absolute + + // duration = opts.fx.duration || 200; + // easing = opts.fx.easing; + // $(node.ul).animate(opts.fx, duration, easing, function(){ + + // node.debug("nodeSetExpanded: animate start..."); + $(node.ul).toggle(effect.effect, effect.options, effect.duration, function(){ + // node.debug("nodeSetExpanded: animate done"); + callback(); + }); + return; + } + } + callback(); + }; + // ^^^ Code above is executed after loading finshed. + + // Load lazy nodes, if any. Then continue with _afterLoad() + if(flag && node.lazy && node.hasChildren() === undefined){ + // node.debug("nodeSetExpanded: load start..."); + node.load().done(function(){ + // node.debug("nodeSetExpanded: load done"); + if(dfd.notifyWith){ // requires jQuery 1.6+ + dfd.notifyWith(node, ["loaded"]); + } + _afterLoad(function () { dfd.resolveWith(node); }); + }).fail(function(errMsg){ + _afterLoad(function () { dfd.rejectWith(node, ["load failed (" + errMsg + ")"]); }); + }); +/* + var source = tree._triggerNodeEvent("lazyLoad", node, ctx.originalEvent); + _assert(typeof source !== "boolean", "lazyLoad event must return source in data.result"); + node.debug("nodeSetExpanded: load start..."); + this._callHook("nodeLoadChildren", ctx, source).done(function(){ + node.debug("nodeSetExpanded: load done"); + if(dfd.notifyWith){ // requires jQuery 1.6+ + dfd.notifyWith(node, ["loaded"]); + } + _afterLoad.call(tree); + }).fail(function(errMsg){ + dfd.rejectWith(node, ["load failed (" + errMsg + ")"]); + }); +*/ + }else{ + _afterLoad(function () { dfd.resolveWith(node); }); + } + // node.debug("nodeSetExpanded: returns"); + return dfd.promise(); + }, + /** Focus or blur this node. + * @param {EventData} ctx + * @param {boolean} [flag=true] + */ + nodeSetFocus: function(ctx, flag) { + // ctx.node.debug("nodeSetFocus(" + flag + ")"); + var ctx2, + tree = ctx.tree, + node = ctx.node; + + flag = (flag !== false); + + // Blur previous node if any + if(tree.focusNode){ + if(tree.focusNode === node && flag){ + // node.debug("nodeSetFocus(" + flag + "): nothing to do"); + return; + } + ctx2 = $.extend({}, ctx, {node: tree.focusNode}); + tree.focusNode = null; + this._triggerNodeEvent("blur", ctx2); + this._callHook("nodeRenderStatus", ctx2); + } + // Set focus to container and node + if(flag){ + if( !this.hasFocus() ){ + node.debug("nodeSetFocus: forcing container focus"); + this._callHook("treeSetFocus", ctx, true, {calledByNode: true}); + } + node.makeVisible({scrollIntoView: false}); + tree.focusNode = node; +// node.debug("FOCUS..."); +// $(node.span).find(".fancytree-title").focus(); + this._triggerNodeEvent("focus", ctx); +// if(ctx.options.autoActivate){ +// tree.nodeSetActive(ctx, true); +// } + if(ctx.options.autoScroll){ + node.scrollIntoView(); + } + this._callHook("nodeRenderStatus", ctx); + } + }, + /** (De)Select node, return new status (sync). + * + * @param {EventData} ctx + * @param {boolean} [flag=true] + */ + nodeSetSelected: function(ctx, flag) { + var node = ctx.node, + tree = ctx.tree, + opts = ctx.options; + // flag defaults to true + flag = (flag !== false); + + node.debug("nodeSetSelected(" + flag + ")", ctx); + if( node.unselectable){ + return; + } + // TODO: !!node.expanded is nicer, but doesn't pass jshint + // https://github.com/jshint/jshint/issues/455 +// if( !!node.expanded === !!flag){ + if((node.selected && flag) || (!node.selected && !flag)){ + return !!node.selected; + }else if ( this._triggerNodeEvent("beforeSelect", node, ctx.originalEvent) === false ){ + return !!node.selected; + } + if(flag && opts.selectMode === 1){ + // single selection mode + if(tree.lastSelectedNode){ + tree.lastSelectedNode.setSelected(false); + } + }else if(opts.selectMode === 3){ + // multi.hier selection mode + node.selected = flag; +// this._fixSelectionState(node); + node.fixSelection3AfterClick(); + } + node.selected = flag; + this.nodeRenderStatus(ctx); + tree.lastSelectedNode = flag ? node : null; + tree._triggerNodeEvent("select", ctx); + }, + /** Show node status (ok, loading, error) using styles and a dummy child node. + * + * @param {EventData} ctx + * @param status + * @param message + * @param details + */ + nodeSetStatus: function(ctx, status, message, details) { + var node = ctx.node, + tree = ctx.tree; + // cn = ctx.options._classNames; + + function _clearStatusNode() { + // Remove dedicated dummy node, if any + var firstChild = ( node.children ? node.children[0] : null ); + if ( firstChild && firstChild.isStatusNode() ) { + try{ + // I've seen exceptions here with loadKeyPath... + if(node.ul){ + node.ul.removeChild(firstChild.li); + firstChild.li = null; // avoid leaks (DT issue 215) + } + }catch(e){} + if( node.children.length === 1 ){ + node.children = []; + }else{ + node.children.shift(); + } + } + } + function _setStatusNode(data, type) { + // Create/modify the dedicated dummy node for 'loading...' or + // 'error!' status. (only called for direct child of the invisible + // system root) + var firstChild = ( node.children ? node.children[0] : null ); + if ( firstChild && firstChild.isStatusNode() ) { + $.extend(firstChild, data); + // tree._callHook("nodeRender", firstChild); + tree._callHook("nodeRenderTitle", firstChild); + } else { + data.key = "_statusNode"; + node._setChildren([data]); + node.children[0].statusNodeType = type; + tree.render(); + } + return node.children[0]; + } + + switch( status ){ + case "ok": + _clearStatusNode(); + // $(node.span).removeClass(cn.loading).removeClass(cn.error); + node._isLoading = false; + node._error = null; + node.renderStatus(); + break; + case "loading": + // $(node.span).removeClass(cn.error).addClass(cn.loading); + if( !node.parent ) { + _setStatusNode({ + title: tree.options.strings.loading + (message ? " (" + message + ") " : ""), + tooltip: details, + extraClasses: "fancytree-statusnode-wait" + }, status); + } + node._isLoading = true; + node._error = null; + node.renderStatus(); + break; + case "error": + // $(node.span).removeClass(cn.loading).addClass(cn.error); + _setStatusNode({ + title: tree.options.strings.loadError + (message ? " (" + message + ") " : ""), + tooltip: details, + extraClasses: "fancytree-statusnode-error" + }, status); + node._isLoading = false; + node._error = { message: message, details: details }; + node.renderStatus(); + break; + default: + $.error("invalid node status " + status); + } + }, + /** + * + * @param {EventData} ctx + */ + nodeToggleExpanded: function(ctx) { + return this.nodeSetExpanded(ctx, !ctx.node.expanded); + }, + /** + * @param {EventData} ctx + */ + nodeToggleSelected: function(ctx) { + return this.nodeSetSelected(ctx, !ctx.node.selected); + }, + /** Remove all nodes. + * @param {EventData} ctx + */ + treeClear: function(ctx) { + var tree = ctx.tree; + tree.activeNode = null; + tree.focusNode = null; + tree.$div.find(">ul.fancytree-container").empty(); + // TODO: call destructors and remove reference loops + tree.rootNode.children = null; + }, + /** Widget was created (called only once, even it re-initialized). + * @param {EventData} ctx + */ + treeCreate: function(ctx) { + }, + /** Widget was destroyed. + * @param {EventData} ctx + */ + treeDestroy: function(ctx) { + }, + /** Widget was (re-)initialized. + * @param {EventData} ctx + */ + treeInit: function(ctx) { + //this.debug("Fancytree.treeInit()"); + this.treeLoad(ctx); + }, + /** Parse Fancytree from source, as configured in the options. + * @param {EventData} ctx + * @param {object} [source] optional new source (use last data otherwise) + */ + treeLoad: function(ctx, source) { + var type, $ul, + tree = ctx.tree, + $container = ctx.widget.element, + dfd, + // calling context for root node + rootCtx = $.extend({}, ctx, {node: this.rootNode}); + + if(tree.rootNode.children){ + this.treeClear(ctx); + } + source = source || this.options.source; + + if(!source){ + type = $container.data("type") || "html"; + switch(type){ + case "html": + $ul = $container.find(">ul:first"); + $ul.addClass("ui-fancytree-source ui-helper-hidden"); + source = $.ui.fancytree.parseHtml($ul); + // allow to init tree.data.foo from <ul data-foo=''> + this.data = $.extend(this.data, _getElementDataAsDict($ul)); + break; + case "json": + // $().addClass("ui-helper-hidden"); + source = $.parseJSON($container.text()); + if(source.children){ + if(source.title){tree.title = source.title;} + source = source.children; + } + break; + default: + $.error("Invalid data-type: " + type); + } + }else if(typeof source === "string"){ + // TODO: source is an element ID + $.error("Not implemented"); + } + + // $container.addClass("ui-widget ui-widget-content ui-corner-all"); + // Trigger fancytreeinit after nodes have been loaded + dfd = this.nodeLoadChildren(rootCtx, source).done(function(){ + tree.render(); + if( ctx.options.selectMode === 3 ){ + tree.rootNode.fixSelection3FromEndNodes(); + } + tree._triggerTreeEvent("init", null, { status: true }); + }).fail(function(){ + tree.render(); + tree._triggerTreeEvent("init", null, { status: false }); + }); + return dfd; + }, + /** Node was inserted into or removed from the tree. + * @param {EventData} ctx + * @param {boolean} add + * @param {FancytreeNode} node + */ + treeRegisterNode: function(ctx, add, node) { + }, + /** Widget got focus. + * @param {EventData} ctx + * @param {boolean} [flag=true] + */ + treeSetFocus: function(ctx, flag, callOpts) { + flag = (flag !== false); + + // this.debug("treeSetFocus(" + flag + "), callOpts: " + callOpts); + // this.debug(" focusNode: " + this.focusNode); + // this.debug(" activeNode: " + this.activeNode); + if( flag !== this.hasFocus() ){ + this._hasFocus = flag; + if( !flag && this.focusNode ) { + // Node also looses focus if widget blurs + this.focusNode.setFocus(false); + } + this.$container.toggleClass("fancytree-treefocus", flag); + this._triggerTreeEvent(flag ? "focusTree" : "blurTree"); + } + } +}); + + +/* ****************************************************************************** + * jQuery UI widget boilerplate + */ + +/** + * The plugin (derrived from <a href=" http://api.jqueryui.com/jQuery.widget/">jQuery.Widget</a>).<br> + * This constructor is not called directly. Use `$(selector).fancytree({})` + * to initialize the plugin instead.<br> + * <pre class="sh_javascript sunlight-highlight-javascript">// Access widget methods and members: + * var tree = $("#tree").fancytree("getTree"); + * var node = $("#tree").fancytree("getActiveNode", "1234"); + * </pre> + * + * @mixin Fancytree_Widget + */ + +$.widget("ui.fancytree", + /** @lends Fancytree_Widget# */ + { + /**These options will be used as defaults + * @type {FancytreeOptions} + */ + options: + { + activeVisible: true, + ajax: { + type: "GET", + cache: false, // false: Append random '_' argument to the request url to prevent caching. +// timeout: 0, // >0: Make sure we get an ajax error if server is unreachable + dataType: "json" // Expect json format and pass json object to callbacks. + }, // + aria: false, // TODO: default to true + autoActivate: true, + autoCollapse: false, +// autoFocus: false, + autoScroll: false, + checkbox: false, + /**defines click behavior*/ + clickFolderMode: 4, + debugLevel: null, // 0..2 (null: use global setting $.ui.fancytree.debugInfo) + disabled: false, // TODO: required anymore? + enableAspx: true, // TODO: document + extensions: [], + // fx: { height: "toggle", duration: 200 }, + // toggleEffect: { effect: "drop", options: {direction: "left"}, duration: 200 }, + // toggleEffect: { effect: "slide", options: {direction: "up"}, duration: 200 }, + toggleEffect: { effect: "blind", options: {direction: "vertical", scale: "box"}, duration: 200 }, + generateIds: false, + icons: true, + idPrefix: "ft_", + focusOnSelect: false, + keyboard: true, + keyPathSeparator: "/", + minExpandLevel: 1, + quicksearch: false, + scrollOfs: {top: 0, bottom: 0}, + scrollParent: null, + selectMode: 2, + strings: { + loading: "Loading&#8230;", + loadError: "Load error!" + }, + tabbable: true, + titlesTabbable: false, + _classNames: { + node: "fancytree-node", + folder: "fancytree-folder", + combinedExpanderPrefix: "fancytree-exp-", + combinedIconPrefix: "fancytree-ico-", + hasChildren: "fancytree-has-children", + active: "fancytree-active", + selected: "fancytree-selected", + expanded: "fancytree-expanded", + lazy: "fancytree-lazy", + focused: "fancytree-focused", + partsel: "fancytree-partsel", + unselectable: "fancytree-unselectable", + lastsib: "fancytree-lastsib", + loading: "fancytree-loading", + error: "fancytree-error" + }, + // events + lazyLoad: null, + postProcess: null + }, + /* Set up the widget, Called on first $().fancytree() */ + _create: function() { + this.tree = new Fancytree(this); + + this.$source = this.source || this.element.data("type") === "json" ? this.element + : this.element.find(">ul:first"); + // Subclass Fancytree instance with all enabled extensions + var extension, extName, i, + extensions = this.options.extensions, + base = this.tree; + + for(i=0; i<extensions.length; i++){ + extName = extensions[i]; + extension = $.ui.fancytree._extensions[extName]; + if(!extension){ + $.error("Could not apply extension '" + extName + "' (it is not registered, did you forget to include it?)"); + } + // Add extension options as tree.options.EXTENSION +// _assert(!this.tree.options[extName], "Extension name must not exist as option name: " + extName); + this.tree.options[extName] = $.extend(true, {}, extension.options, this.tree.options[extName]); + // Add a namespace tree.ext.EXTENSION, to hold instance data + _assert(this.tree.ext[extName] === undefined, "Extension name must not exist as Fancytree.ext attribute: '" + extName + "'"); +// this.tree[extName] = extension; + this.tree.ext[extName] = {}; + // Subclass Fancytree methods using proxies. + _subclassObject(this.tree, base, extension, extName); + // current extension becomes base for the next extension + base = extension; + } + // + this.tree._callHook("treeCreate", this.tree); + // Note: 'fancytreecreate' event is fired by widget base class +// this.tree._triggerTreeEvent("create"); + }, + + /* Called on every $().fancytree() */ + _init: function() { + this.tree._callHook("treeInit", this.tree); + // TODO: currently we call bind after treeInit, because treeInit + // might change tree.$container. + // It would be better, to move ebent binding into hooks altogether + this._bind(); + }, + + /* Use the _setOption method to respond to changes to options */ + _setOption: function(key, value) { + var callDefault = true, + rerender = false; + switch( key ) { + case "aria": + case "checkbox": + case "icons": + case "minExpandLevel": + case "tabbable": +// case "nolink": + this.tree._callHook("treeCreate", this.tree); + rerender = true; + break; + case "source": + callDefault = false; + this.tree._callHook("treeLoad", this.tree, value); + break; + } + this.tree.debug("set option " + key + "=" + value + " <" + typeof(value) + ">"); + if(callDefault){ + // In jQuery UI 1.8, you have to manually invoke the _setOption method from the base widget + $.Widget.prototype._setOption.apply(this, arguments); + // TODO: In jQuery UI 1.9 and above, you use the _super method instead +// this._super( "_setOption", key, value ); + } + if(rerender){ + this.tree.render(true, false); // force, not-deep + } + }, + + /** Use the destroy method to clean up any modifications your widget has made to the DOM */ + destroy: function() { + this._unbind(); + this.tree._callHook("treeDestroy", this.tree); + // this.element.removeClass("ui-widget ui-widget-content ui-corner-all"); + this.tree.$div.find(">ul.fancytree-container").remove(); + this.$source && this.$source.removeClass("ui-helper-hidden"); + // In jQuery UI 1.8, you must invoke the destroy method from the base widget + $.Widget.prototype.destroy.call(this); + // TODO: delete tree and nodes to make garbage collect easier? + // TODO: In jQuery UI 1.9 and above, you would define _destroy instead of destroy and not call the base method + }, + + // ------------------------------------------------------------------------- + + /* Remove all event handlers for our namespace */ + _unbind: function() { + var ns = this.tree._ns; + this.element.unbind(ns); + this.tree.$container.unbind(ns); + $(document).unbind(ns); + }, + /* Add mouse and kyboard handlers to the container */ + _bind: function() { + var that = this, + opts = this.options, + tree = this.tree, + ns = tree._ns + // selstartEvent = ( $.support.selectstart ? "selectstart" : "mousedown" ) + ; + + // Remove all previuous handlers for this tree + this._unbind(); + + //alert("keydown" + ns + "foc=" + tree.hasFocus() + tree.$container); + // tree.debug("bind events; container: ", tree.$container); + tree.$container.on("focusin" + ns + " focusout" + ns, function(event){ + var node = FT.getNode(event), + flag = (event.type === "focusin"); + // tree.debug("Tree container got event " + event.type, node, event); + // tree.treeOnFocusInOut.call(tree, event); + if(node){ + // For example clicking into an <input> that is part of a node + tree._callHook("nodeSetFocus", node, flag); + }else{ + tree._callHook("treeSetFocus", tree, flag); + } + }).on("selectstart" + ns, "span.fancytree-title", function(event){ + // prevent mouse-drags to select text ranges + // tree.debug("<span title> got event " + event.type); + event.preventDefault(); + }).on("keydown" + ns, function(event){ + // TODO: also bind keyup and keypress + // tree.debug("got event " + event.type + ", hasFocus:" + tree.hasFocus()); + // if(opts.disabled || opts.keyboard === false || !tree.hasFocus() ){ + if(opts.disabled || opts.keyboard === false ){ + return true; + } + var res, + node = tree.focusNode, // node may be null + ctx = tree._makeHookContext(node || tree, event), + prevPhase = tree.phase; + + try { + tree.phase = "userEvent"; + // If a 'fancytreekeydown' handler returns false, skip the default + // handling (implemented by tree.nodeKeydown()). + if(node){ + res = tree._triggerNodeEvent("keydown", node, event); + }else{ + res = tree._triggerTreeEvent("keydown", event); + } + if ( res === "preventNav" ){ + res = true; // prevent keyboard navigation, but don't prevent default handling of embedded input controls + } else if ( res !== false ){ + res = tree._callHook("nodeKeydown", ctx); + } + return res; + } finally { + tree.phase = prevPhase; + } + }).on("click" + ns + " dblclick" + ns, function(event){ + if(opts.disabled){ + return true; + } + var ctx, + et = FT.getEventTarget(event), + node = et.node, + tree = that.tree, + prevPhase = tree.phase; + + if( !node ){ + return true; // Allow bubbling of other events + } + ctx = tree._makeHookContext(node, event); +// that.tree.debug("event(" + event.type + "): node: ", node); + try { + tree.phase = "userEvent"; + switch(event.type) { + case "click": + ctx.targetType = et.type; + return ( tree._triggerNodeEvent("click", ctx, event) === false ) ? false : tree._callHook("nodeClick", ctx); + case "dblclick": + ctx.targetType = et.type; + return ( tree._triggerNodeEvent("dblclick", ctx, event) === false ) ? false : tree._callHook("nodeDblclick", ctx); + } +// } catch(e) { +// // var _ = null; // DT issue 117 // TODO +// $.error(e); + } finally { + tree.phase = prevPhase; + } + }); + }, + /** Return the active node or null. + * @returns {FancytreeNode} + */ + getActiveNode: function() { + return this.tree.activeNode; + }, + /** Return the matching node or null. + * @param {string} key + * @returns {FancytreeNode} + */ + getNodeByKey: function(key) { + return this.tree.getNodeByKey(key); + }, + /** Return the invisible system root node. + * @returns {FancytreeNode} + */ + getRootNode: function() { + return this.tree.rootNode; + }, + /** Return the current tree instance. + * @returns {Fancytree} + */ + getTree: function() { + return this.tree; + } +}); + +// $.ui.fancytree was created by the widget factory. Create a local shortcut: +FT = $.ui.fancytree; + +/** + * Static members in the `$.ui.fancytree` namespace.<br> + * <br> + * <pre class="sh_javascript sunlight-highlight-javascript">// Access static members: + * var node = $.ui.fancytree.getNode(element); + * alert($.ui.fancytree.version); + * </pre> + * + * @mixin Fancytree_Static + */ +$.extend($.ui.fancytree, + /** @lends Fancytree_Static# */ + { + /** @type {string} */ + version: "2.8.1", // Set to semver by 'grunt release' + /** @type {string} */ + buildType: "production", // Set to 'production' by 'grunt build' + /** @type {int} */ + debugLevel: 1, // Set to 1 by 'grunt build' + // Used by $.ui.fancytree.debug() and as default for tree.options.debugLevel + + _nextId: 1, + _nextNodeKey: 1, + _extensions: {}, + // focusTree: null, + + /** Expose class object as $.ui.fancytree._FancytreeClass */ + _FancytreeClass: Fancytree, + /** Expose class object as $.ui.fancytree._FancytreeNodeClass */ + _FancytreeNodeClass: FancytreeNode, + /* Feature checks to provide backwards compatibility */ + jquerySupports: { + // http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at + positionMyOfs: isVersionAtLeast($.ui.version, 1, 9) + }, + /** Throw an error if condition fails (debug method). + * @param {boolean} cond + * @param {string} msg + */ + assert: function(cond, msg){ + return _assert(cond, msg); + }, + /** Return a function that executes *fn* at most every *timeout* ms. + * @param {integer} timeout + * @param {function} fn + * @param {boolean} [invokeAsap=false] + * @param {any} [ctx] + */ + debounce: function(timeout, fn, invokeAsap, ctx) { + var timer; + if(arguments.length === 3 && typeof invokeAsap !== "boolean") { + ctx = invokeAsap; + invokeAsap = false; + } + return function() { + var args = arguments; + ctx = ctx || this; + invokeAsap && !timer && fn.apply(ctx, args); + clearTimeout(timer); + timer = setTimeout(function() { + invokeAsap || fn.apply(ctx, args); + timer = null; + }, timeout); + }; + }, + /** Write message to console if debugLevel >= 2 + * @param {string} msg + */ + debug: function(msg){ + /*jshint expr:true */ + ($.ui.fancytree.debugLevel >= 2) && consoleApply("log", arguments); + }, + /** Write error message to console. + * @param {string} msg + */ + error: function(msg){ + consoleApply("error", arguments); + }, + /** Convert &lt;, &gt;, &amp;, &quot;, &#39;, &#x2F; to the equivalent entitites. + * + * @param {string} s + * @returns {string} + */ + escapeHtml: function(s){ + return ("" + s).replace(/[&<>"'\/]/g, function (s) { + return ENTITY_MAP[s]; + }); + }, + /** Make jQuery.position() arguments backwards compatible, i.e. if + * jQuery UI version <= 1.8, convert + * { my: "left+3 center", at: "left bottom", of: $target } + * to + * { my: "left center", at: "left bottom", of: $target, offset: "3 0" } + * + * See http://jqueryui.com/upgrade-guide/1.9/#deprecated-offset-option-merged-into-my-and-at + * and http://jsfiddle.net/mar10/6xtu9a4e/ + */ + fixPositionOptions: function(opts) { + if( opts.offset || ("" + opts.my + opts.at ).indexOf("%") >= 0 ) { + $.error("expected new position syntax (but '%' is not supported)"); + } + if( ! $.ui.fancytree.jquerySupports.positionMyOfs ) { + var // parse 'left+3 center' into ['left+3 center', 'left', '+3', 'center', undefined] + myParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(opts.my), + atParts = /(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(opts.at), + // convert to numbers + dx = (myParts[2] ? (+myParts[2]) : 0) + (atParts[2] ? (+atParts[2]) : 0), + dy = (myParts[4] ? (+myParts[4]) : 0) + (atParts[4] ? (+atParts[4]) : 0); + + opts = $.extend({}, opts, { // make a copy and overwrite + my: myParts[1] + " " + myParts[3], + at: atParts[1] + " " + atParts[3] + }); + if( dx || dy ) { + opts.offset = "" + dx + " " + dy; + } + } + return opts; + }, + /** Return a {node: FancytreeNode, type: TYPE} object for a mouse event. + * + * @param {Event} event Mouse event, e.g. click, ... + * @returns {string} 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined + */ + getEventTargetType: function(event){ + return this.getEventTarget(event).type; + }, + /** Return a {node: FancytreeNode, type: TYPE} object for a mouse event. + * + * @param {Event} event Mouse event, e.g. click, ... + * @returns {object} Return a {node: FancytreeNode, type: TYPE} object + * TYPE: 'title' | 'prefix' | 'expander' | 'checkbox' | 'icon' | undefined + */ + getEventTarget: function(event){ + var tcn = event && event.target ? event.target.className : "", + res = {node: this.getNode(event.target), type: undefined}; + // We use a fast version of $(res.node).hasClass() + // See http://jsperf.com/test-for-classname/2 + if( /\bfancytree-title\b/.test(tcn) ){ + res.type = "title"; + }else if( /\bfancytree-expander\b/.test(tcn) ){ + res.type = (res.node.hasChildren() === false ? "prefix" : "expander"); + }else if( /\bfancytree-checkbox\b/.test(tcn) || /\bfancytree-radio\b/.test(tcn) ){ + res.type = "checkbox"; + }else if( /\bfancytree-icon\b/.test(tcn) ){ + res.type = "icon"; + }else if( /\bfancytree-node\b/.test(tcn) ){ + // Somewhere near the title + res.type = "title"; + }else if( event && event.target && $(event.target).closest(".fancytree-title").length ) { + // #228: clicking an embedded element inside a title + res.type = "title"; + } + return res; + }, + /** Return a FancytreeNode instance from element. + * + * @param {Element | jQueryObject | Event} el + * @returns {FancytreeNode} matching node or null + */ + getNode: function(el){ + if(el instanceof FancytreeNode){ + return el; // el already was a FancytreeNode + }else if(el.selector !== undefined){ + el = el[0]; // el was a jQuery object: use the DOM element + }else if(el.originalEvent !== undefined){ + el = el.target; // el was an Event + } + while( el ) { + if(el.ftnode) { + return el.ftnode; + } + el = el.parentNode; + } + return null; + }, + /* Return a Fancytree instance from element. + * TODO: this function could help to get around the data('fancytree') / data('ui-fancytree') problem + * @param {Element | jQueryObject | Event} el + * @returns {Fancytree} matching tree or null + * / + getTree: function(el){ + if(el instanceof Fancytree){ + return el; // el already was a Fancytree + }else if(el.selector !== undefined){ + el = el[0]; // el was a jQuery object: use the DOM element + }else if(el.originalEvent !== undefined){ + el = el.target; // el was an Event + } + ... + return null; + }, + */ + /** Write message to console if debugLevel >= 1 + * @param {string} msg + */ + info: function(msg){ + /*jshint expr:true */ + ($.ui.fancytree.debugLevel >= 1) && consoleApply("info", arguments); + }, + /** Convert a keydown or mouse event to a canonical string like 'ctrl+a', 'ctrl+shift+f2', 'shift+leftdblclick'. + * This is especially handy for switch-statements in event handlers. + * @param {event} + * @returns {string} + */ + eventToString: function(event) { + // Poor-man's hotkeys. See here for a complete implementation: + // https://github.com/jeresig/jquery.hotkeys + var which = event.which, + et = event.type, + s = []; + + if( event.altKey ) { s.push("alt"); } + if( event.ctrlKey ) { s.push("ctrl"); } + if( event.metaKey ) { s.push("meta"); } + if( event.shiftKey ) { s.push("shift"); } + + if( et === "click" || et === "dblclick" ) { + s.push(MOUSE_BUTTONS[event.button] + et); + } else { + if( !IGNORE_KEYCODES[which] ) { + s.push( SPECIAL_KEYCODES[which] || String.fromCharCode(which).toLowerCase() ); + } + } + return s.join("+"); + }, + /* @deprecated: use eventToString(event) instead. + */ + keyEventToString: function(event) { + this.warn("keyEventToString() is deprecated: use eventToString()"); + return this.eventToString(event); + }, + /** + * Parse tree data from HTML <ul> markup + * + * @param {jQueryObject} $ul + * @returns {NodeData[]} + */ + parseHtml: function($ul) { + // TODO: understand this: + /*jshint validthis:true */ + var extraClasses, i, l, iPos, tmp, tmp2, classes, className, + $children = $ul.find(">li"), + children = []; + + $children.each(function() { + var allData, + $li = $(this), + $liSpan = $li.find(">span:first", this), + $liA = $liSpan.length ? null : $li.find(">a:first"), + d = { tooltip: null, data: {} }; + + if( $liSpan.length ) { + d.title = $liSpan.html(); + + } else if( $liA && $liA.length ) { + // If a <li><a> tag is specified, use it literally and extract href/target. + d.title = $liA.html(); + d.data.href = $liA.attr("href"); + d.data.target = $liA.attr("target"); + d.tooltip = $liA.attr("title"); + + } else { + // If only a <li> tag is specified, use the trimmed string up to + // the next child <ul> tag. + d.title = $li.html(); + iPos = d.title.search(/<ul/i); + if( iPos >= 0 ){ + d.title = d.title.substring(0, iPos); + } + } + d.title = $.trim(d.title); + + // Make sure all fields exist + for(i=0, l=CLASS_ATTRS.length; i<l; i++){ + d[CLASS_ATTRS[i]] = undefined; + } + // Initialize to `true`, if class is set and collect extraClasses + classes = this.className.split(" "); + extraClasses = []; + for(i=0, l=classes.length; i<l; i++){ + className = classes[i]; + if(CLASS_ATTR_MAP[className]){ + d[className] = true; + }else{ + extraClasses.push(className); + } + } + d.extraClasses = extraClasses.join(" "); + + // Parse node options from ID, title and class attributes + tmp = $li.attr("title"); + if( tmp ){ + d.tooltip = tmp; // overrides <a title='...'> + } + tmp = $li.attr("id"); + if( tmp ){ + d.key = tmp; + } + // Add <li data-NAME='...'> as node.data.NAME + allData = _getElementDataAsDict($li); + if(allData && !$.isEmptyObject(allData)) { + // #56: Allow to set special node.attributes from data-... + for(i=0, l=NODE_ATTRS.length; i<l; i++){ + tmp = NODE_ATTRS[i]; + tmp2 = allData[tmp]; + if( tmp2 != null ) { + delete allData[tmp]; + d[tmp] = tmp2; + } + } + // All other data-... goes to node.data... + $.extend(d.data, allData); + } + // Recursive reading of child nodes, if LI tag contains an UL tag + $ul = $li.find(">ul:first"); + if( $ul.length ) { + d.children = $.ui.fancytree.parseHtml($ul); + }else{ + d.children = d.lazy ? undefined : null; + } + children.push(d); +// FT.debug("parse ", d, children); + }); + return children; + }, + /** Add Fancytree extension definition to the list of globally available extensions. + * + * @param {object} definition + */ + registerExtension: function(definition){ + _assert(definition.name != null, "extensions must have a `name` property."); + _assert(definition.version != null, "extensions must have a `version` property."); + $.ui.fancytree._extensions[definition.name] = definition; + }, + /** Inverse of escapeHtml(). + * + * @param {string} s + * @returns {string} + */ + unescapeHtml: function(s){ + var e = document.createElement("div"); + e.innerHTML = s; + return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue; + }, + /** Write warning message to console. + * @param {string} msg + */ + warn: function(msg){ + consoleApply("warn", arguments); + } +}); + +}(jQuery, window, document)); + +// Extending Fancytree +// =================== +// +// See also the [live demo](http://wwwendt.de/tech/fancytree/demo/sample-ext-childcounter.html) of this code. +// +// Every extension should have a comment header containing some information +// about the author, copyright and licensing. Also a pointer to the latest +// source code. +// Prefix with `/*!` so the comment is not removed by the minifier. + +/*! + * jquery.fancytree.childcounter.js + * + * Add a child counter bubble to tree nodes. + * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +// To keep the global namespace clean, we wrap everything in a closure + +;(function($, undefined) { + +// Consider to use [strict mode](http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/) +"use strict"; + +// The [coding guidelines](http://contribute.jquery.org/style-guide/js/) +// require jshint compliance. +// But for this sample, we want to allow unused variables for demonstration purpose. + +/*jshint unused:false */ + + +// Adding methods +// -------------- + +// New member functions can be added to the `Fancytree` class. +// This function will be available for every tree instance. +// +// var tree = $("#tree").fancytree("getTree"); +// tree.countSelected(false); + +$.ui.fancytree._FancytreeClass.prototype.countSelected = function(topOnly){ + var tree = this, + treeOptions = tree.options; + return tree.getSelectedNodes(topOnly).length; +}; + + +// The `FancytreeNode` class can also be easily extended. This would be called +// like +// +// node.toUpper(); + +$.ui.fancytree._FancytreeNodeClass.prototype.toUpper = function(){ + var node = this; + return node.setTitle(node.title.toUpperCase()); +}; + + +// Finally, we can extend the widget API and create functions that are called +// like so: +// +// $("#tree").fancytree("widgetMethod1", "abc"); + +$.ui.fancytree.prototype.widgetMethod1 = function(arg1){ + var tree = this.tree; + return arg1; +}; + + +// Register a Fancytree extension +// ------------------------------ +// A full blown extension, extension is available for all trees and can be +// enabled like so (see also the [live demo](http://wwwendt.de/tech/fancytree/demo/sample-ext-childcounter.html)): +// +// <script src="../src/jquery.fancytree.js" type="text/javascript"></script> +// <script src="../src/jquery.fancytree.childcounter.js" type="text/javascript"></script> +// ... +// +// $("#tree").fancytree({ +// extensions: ["childcounter"], +// childcounter: { +// hideExpanded: true +// }, +// ... +// }); +// + + +/* 'childcounter' extension */ +$.ui.fancytree.registerExtension({ +// Every extension must be registered by a unique name. + name: "childcounter", +// Version information should be compliant with [semver](http://semver.org) + version: "1.0.0", + +// Extension specific options and their defaults. +// This options will be available as `tree.options.childcounter.hideExpanded` + + options: { + deep: true, + hideZeros: true, + hideExpanded: false + }, + +// Attributes other than `options` (or functions) can be defined here, and +// will be added to the tree.ext.EXTNAME namespace, in this case `tree.ext.childcounter.foo`. +// They can also be accessed as `this._local.foo` from within the extension +// methods. + foo: 42, + +// Local functions are prefixed with an underscore '_'. +// Callable as `this._local._appendCounter()`. + + _appendCounter: function(bar){ + var tree = this; + }, + +// **Override virtual methods for this extension.** +// +// Fancytree implements a number of 'hook methods', prefixed by 'node...' or 'tree...'. +// with a `ctx` argument (see [EventData](http://www.wwwendt.de/tech/fancytree/doc/jsdoc/global.html#EventData) +// for details) and an extended calling context:<br> +// `this` : the Fancytree instance<br> +// `this._local`: the namespace that contains extension attributes and private methods (same as this.ext.EXTNAME)<br> +// `this._super`: the virtual function that was overridden (member of previous extension or Fancytree) +// +// See also the [complete list of available hook functions](http://www.wwwendt.de/tech/fancytree/doc/jsdoc/Fancytree_Hooks.html). + + /* Init */ +// `treeInit` is triggered when a tree is initalized. We can set up classes or +// bind event handlers here... + treeInit: function(ctx){ + var tree = this, // same as ctx.tree, + opts = ctx.options, + extOpts = ctx.options.childcounter; +// Optionally check for dependencies with other extensions + /* this._requireExtension("glyph", false, false); */ +// Call the base implementation + this._superApply(arguments); +// Add a class to the tree container + this.$container.addClass("fancytree-ext-childcounter"); + }, + +// Destroy this tree instance (we only call the default implementation, so +// this method could as well be omitted). + + treeDestroy: function(ctx){ + this._superApply(arguments); + }, + +// Overload the `renderTitle` hook, to append a counter badge + nodeRenderTitle: function(ctx, title) { + var node = ctx.node, + extOpts = ctx.options.childcounter, + count = (node.data.childCounter == null) ? node.countChildren(extOpts.deep) : +node.data.childCounter; +// Let the base implementation render the title + this._superApply(arguments); +// Append a counter badge + if( (count || ! extOpts.hideZeros) && (!node.isExpanded() || !extOpts.hideExpanded) ){ + $("span.fancytree-icon", node.span).append($("<span class='fancytree-childcounter'/>").text(count)); + } + }, +// Overload the `setExpanded` hook, so the counters are updated + nodeSetExpanded: function(ctx, flag, opts) { + var tree = ctx.tree, + node = ctx.node; +// Let the base implementation expand/collapse the node, then redraw the title +// after the animation has finished + return this._superApply(arguments).always(function(){ + tree.nodeRenderTitle(ctx); + }); + } + +// End of extension definition +}); +// End of namespace closure +}(jQuery)); + +/*! + * + * jquery.fancytree.clones.js + * Support faster lookup of nodes by key and shared ref-ids. + * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +;(function($, window, document, undefined) { + +"use strict"; + +/******************************************************************************* + * Private functions and variables + */ +function _assert(cond, msg){ + // TODO: see qunit.js extractStacktrace() + if(!cond){ + msg = msg ? ": " + msg : ""; + $.error("Assertion failed" + msg); + } +} + + +/* Return first occurrence of member from array. */ +function _removeArrayMember(arr, elem) { + // TODO: use Array.indexOf for IE >= 9 + var i; + for (i = arr.length - 1; i >= 0; i--) { + if (arr[i] === elem) { + arr.splice(i, 1); + return true; + } + } + return false; +} + + +// /** +// * Calculate a 32 bit FNV-1a hash +// * Found here: https://gist.github.com/vaiorabbit/5657561 +// * Ref.: http://isthe.com/chongo/tech/comp/fnv/ +// * +// * @param {string} str the input value +// * @param {boolean} [asString=false] set to true to return the hash value as +// * 8-digit hex string instead of an integer +// * @param {integer} [seed] optionally pass the hash of the previous chunk +// * @returns {integer | string} +// */ +// function hashFnv32a(str, asString, seed) { +// /*jshint bitwise:false */ +// var i, l, +// hval = (seed === undefined) ? 0x811c9dc5 : seed; + +// for (i = 0, l = str.length; i < l; i++) { +// hval ^= str.charCodeAt(i); +// hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24); +// } +// if( asString ){ +// // Convert to 8 digit hex string +// return ("0000000" + (hval >>> 0).toString(16)).substr(-8); +// } +// return hval >>> 0; +// } + + +/** + * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011) + * + * @author <a href="mailto:gary.court@gmail.com">Gary Court</a> + * @see http://github.com/garycourt/murmurhash-js + * @author <a href="mailto:aappleby@gmail.com">Austin Appleby</a> + * @see http://sites.google.com/site/murmurhash/ + * + * @param {string} key ASCII only + * @param {boolean} [asString=false] + * @param {number} seed Positive integer only + * @return {number} 32-bit positive integer hash + */ +function hashMurmur3(key, asString, seed) { + /*jshint bitwise:false */ + var h1b, k1, + remainder = key.length & 3, + bytes = key.length - remainder, + h1 = seed, + c1 = 0xcc9e2d51, + c2 = 0x1b873593, + i = 0; + + while (i < bytes) { + k1 = + ((key.charCodeAt(i) & 0xff)) | + ((key.charCodeAt(++i) & 0xff) << 8) | + ((key.charCodeAt(++i) & 0xff) << 16) | + ((key.charCodeAt(++i) & 0xff) << 24); + ++i; + + k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff; + + h1 ^= k1; + h1 = (h1 << 13) | (h1 >>> 19); + h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff; + h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16)); + } + + k1 = 0; + + switch (remainder) { + /*jshint -W086:true */ + case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16; + case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8; + case 1: k1 ^= (key.charCodeAt(i) & 0xff); + + k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff; + h1 ^= k1; + } + + h1 ^= key.length; + + h1 ^= h1 >>> 16; + h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff; + h1 ^= h1 >>> 13; + h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff; + h1 ^= h1 >>> 16; + + if( asString ){ + // Convert to 8 digit hex string + return ("0000000" + (h1 >>> 0).toString(16)).substr(-8); + } + return h1 >>> 0; +} + +// console.info(hashMurmur3("costarring")); +// console.info(hashMurmur3("costarring", true)); +// console.info(hashMurmur3("liquid")); +// console.info(hashMurmur3("liquid", true)); + + +/* + * Return a unique key for node by calculationg the hash of the parents refKey-list + */ +function calcUniqueKey(node) { + var key, + path = $.map(node.getParentList(false, true), function(e){ return e.refKey || e.key; }); + path = path.join("/"); + key = "id_" + hashMurmur3(path, true); + // node.debug(path + " -> " + key); + return key; +} + + +/** + * [ext-clones] Return a list of clone-nodes or null. + * @param {boolean} [includeSelf=false] + * @returns {FancytreeNode[] | null} + * + * @alias FancytreeNode#getCloneList + * @requires jquery.fancytree.clones.js + */ +$.ui.fancytree._FancytreeNodeClass.prototype.getCloneList = function(includeSelf){ + var key, + tree = this.tree, + refList = tree.refMap[this.refKey] || null, + keyMap = tree.keyMap; + + if( refList ) { + key = this.key; + // Convert key list to node list + if( includeSelf ) { + refList = $.map(refList, function(val){ return keyMap[val]; }); + } else { + refList = $.map(refList, function(val){ return val === key ? null : keyMap[val]; }); + if( refList.length < 1 ) { + refList = null; + } + } + } + return refList; +}; + + +/** + * [ext-clones] Return true if this node has at least another clone with same refKey. + * @returns {boolean} + * + * @alias FancytreeNode#isClone + * @requires jquery.fancytree.clones.js + */ +$.ui.fancytree._FancytreeNodeClass.prototype.isClone = function(){ + var refKey = this.refKey || null, + refList = refKey && this.tree.refMap[refKey] || null; + return !!(refList && refList.length > 1); +}; + + +/** + * [ext-clones] Update key and/or refKey for an existing node. + * @param {string} key + * @param {string} refKey + * @returns {boolean} + * + * @alias FancytreeNode#reRegister + * @requires jquery.fancytree.clones.js + */ +$.ui.fancytree._FancytreeNodeClass.prototype.reRegister = function(key, refKey){ + key = (key == null) ? null : "" + key; + refKey = (refKey == null) ? null : "" + refKey; + // this.debug("reRegister", key, refKey); + + var tree = this.tree, + prevKey = this.key, + prevRefKey = this.refKey, + keyMap = tree.keyMap, + refMap = tree.refMap, + refList = refMap[prevRefKey] || null, +// curCloneKeys = refList ? node.getCloneList(true), + modified = false; + + // Key has changed: update all references + if( key != null && key !== this.key ) { + if( keyMap[key] ) { + $.error("[ext-clones] reRegister(" + key + "): already exists: " + this); + } + // Update keyMap + delete keyMap[prevKey]; + keyMap[key] = this; + // Update refMap + if( refList ) { + refMap[prevRefKey] = $.map(refList, function(e){ + return e === prevKey ? key : e; + }); + } + this.key = key; + modified = true; + } + + // refKey has changed + if( refKey != null && refKey !== this.refKey ) { + // Remove previous refKeys + if( refList ){ + if( refList.length === 1 ){ + delete refMap[prevRefKey]; + }else{ + refMap[prevRefKey] = $.map(refList, function(e){ + return e === prevKey ? null : e; + }); + } + } + // Add refKey + if( refMap[refKey] ) { + refMap[refKey].append(key); + }else{ + refMap[refKey] = [ this.key ]; + } + this.refKey = refKey; + modified = true; + } + return modified; +}; + + +/** + * [ext-clones] Return all nodes with a given refKey (null if not found). + * @param {string} refKey + * @param {FancytreeNode} [rootNode] optionally restrict results to descendants of this node + * @returns {FancytreeNode[] | null} + * @alias Fancytree#getNodesByRef + * @requires jquery.fancytree.clones.js + */ +$.ui.fancytree._FancytreeClass.prototype.getNodesByRef = function(refKey, rootNode){ + var keyMap = this.keyMap, + refList = this.refMap[refKey] || null; + + if( refList ) { + // Convert key list to node list + if( rootNode ) { + refList = $.map(refList, function(val){ + var node = keyMap[val]; + return node.isDescendantOf(rootNode) ? node : null; + }); + }else{ + refList = $.map(refList, function(val){ return keyMap[val]; }); + } + if( refList.length < 1 ) { + refList = null; + } + } + return refList; +}; + + +/** + * [ext-clones] Replace a refKey with a new one. + * @param {string} oldRefKey + * @param {string} newRefKey + * @alias Fancytree#changeRefKey + * @requires jquery.fancytree.clones.js + */ +$.ui.fancytree._FancytreeClass.prototype.changeRefKey = function(oldRefKey, newRefKey) { + var i, node, + keyMap = this.keyMap, + refList = this.refMap[oldRefKey] || null; + + if (refList) { + for (i = 0; i < refList.length; i++) { + node = keyMap[refList[i]]; + node.refKey = newRefKey; + } + delete this.refMap[oldRefKey]; + this.refMap[newRefKey] = refList; + } +}; + + +/******************************************************************************* + * Extension code + */ +$.ui.fancytree.registerExtension({ + name: "clones", + version: "0.0.3", + // Default options for this extension. + options: { + highlightActiveClones: true, // set 'fancytree-active-clone' on active clones and all peers + highlightClones: false // set 'fancytree-clone' class on any node that has at least one clone + }, + + treeCreate: function(ctx){ + this._superApply(arguments); + ctx.tree.refMap = {}; + ctx.tree.keyMap = {}; + }, + treeInit: function(ctx){ + this.$container.addClass("fancytree-ext-clones"); + _assert(ctx.options.defaultKey == null); + // Generate unique / reproducible default keys + ctx.options.defaultKey = function(node){ + return calcUniqueKey(node); + }; + // The default implementation loads initial data + this._superApply(arguments); + }, + treeClear: function(ctx){ + ctx.tree.refMap = {}; + ctx.tree.keyMap = {}; + return this._superApply(arguments); + }, + treeRegisterNode: function(ctx, add, node) { + var refList, len, + tree = ctx.tree, + keyMap = tree.keyMap, + refMap = tree.refMap, + key = node.key, + refKey = (node && node.refKey != null) ? "" + node.refKey : null; + +// ctx.tree.debug("clones.treeRegisterNode", add, node); + + if( key === "_statusNode" ){ + return this._superApply(arguments); + } + + if( add ) { + if( keyMap[node.key] != null ) { + $.error("clones.treeRegisterNode: node.key already exists: " + node); + } + keyMap[key] = node; + if( refKey ) { + refList = refMap[refKey]; + if( refList ) { + refList.push(key); + if( refList.length === 2 && ctx.options.clones.highlightClones ) { + // Mark peer node, if it just became a clone (no need to + // mark current node, since it will be rendered later anyway) + keyMap[refList[0]].renderStatus(); + } + } else { + refMap[refKey] = [key]; + } + // node.debug("clones.treeRegisterNode: add clone =>", refMap[refKey]); + } + }else { + if( keyMap[key] == null ) { + $.error("clones.treeRegisterNode: node.key not registered: " + node.key); + } + delete keyMap[key]; + if( refKey ) { + refList = refMap[refKey]; + // node.debug("clones.treeRegisterNode: remove clone BEFORE =>", refMap[refKey]); + if( refList ) { + len = refList.length; + if( len <= 1 ){ + _assert(len === 1); + _assert(refList[0] === key); + delete refMap[refKey]; + }else{ + _removeArrayMember(refList, key); + // Unmark peer node, if this was the only clone + if( len === 2 && ctx.options.clones.highlightClones ) { +// node.debug("clones.treeRegisterNode: last =>", node.getCloneList()); + keyMap[refList[0]].renderStatus(); + } + } + // node.debug("clones.treeRegisterNode: remove clone =>", refMap[refKey]); + } + } + } + return this._superApply(arguments); + }, + nodeRenderStatus: function(ctx) { + var $span, res, + node = ctx.node; + + res = this._superApply(arguments); + + if( ctx.options.clones.highlightClones ) { + $span = $(node[ctx.tree.statusClassPropName]); + // Only if span already exists + if( $span.length && node.isClone() ){ +// node.debug("clones.nodeRenderStatus: ", ctx.options.clones.highlightClones); + $span.addClass("fancytree-clone"); + } + } + return res; + }, + nodeSetActive: function(ctx, flag) { + var res, + scpn = ctx.tree.statusClassPropName, + node = ctx.node; + + res = this._superApply(arguments); + + if( ctx.options.clones.highlightActiveClones && node.isClone() ) { + $.each(node.getCloneList(true), function(idx, n){ + // n.debug("clones.nodeSetActive: ", flag !== false); + $(n[scpn]).toggleClass("fancytree-active-clone", flag !== false); + }); + } + return res; + } +}); +}(jQuery, window, document)); + +/*! + * jquery.fancytree.dnd.js + * + * Drag-and-drop support. + * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +;(function($, window, document, undefined) { + +"use strict"; + +/* ***************************************************************************** + * Private functions and variables + */ +var didRegisterDnd = false; + +/* Convert number to string and prepend +/-; return empty string for 0.*/ +function offsetString(n){ + return n === 0 ? "" : (( n > 0 ) ? ("+" + n) : ("" + n)); +} + +/* ***************************************************************************** + * Drag and drop support + */ +function _initDragAndDrop(tree) { + var dnd = tree.options.dnd || null; + // Register 'connectToFancytree' option with ui.draggable + if( dnd ) { + _registerDnd(); + } + // Attach ui.draggable to this Fancytree instance + if(dnd && dnd.dragStart ) { + tree.widget.element.draggable($.extend({ + addClasses: false, + // DT issue 244: helper should be child of scrollParent: + appendTo: tree.$container, +// appendTo: "body", + containment: false, + delay: 0, + distance: 4, + revert: false, + scroll: true, // to disable, also set css 'position: inherit' on ul.fancytree-container + scrollSpeed: 7, + scrollSensitivity: 10, + // Delegate draggable.start, drag, and stop events to our handler + connectToFancytree: true, + // Let source tree create the helper element + helper: function(event) { + var $helper, + sourceNode = $.ui.fancytree.getNode(event.target), + $nodeTag = $(sourceNode.span); + if(!sourceNode){ + // DT issue 211: might happen, if dragging a table *header* + return "<div>ERROR?: helper requested but sourceNode not found</div>"; + } + // Only event and node argument is available + $helper = $("<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>") + .css({zIndex: 3, position: "relative"}) // so it appears above ext-wide selection bar + .append($nodeTag.find("span.fancytree-title").clone()); + + // Attach node reference to helper object + $helper.data("ftSourceNode", sourceNode); + // we return an unconnected element, so `draggable` will add this + // to the parent specified as `appendTo` option + return $helper; + }, + start: function(event, ui) { + var sourceNode = ui.helper.data("ftSourceNode"); + return !!sourceNode; // Abort dragging if no node could be found + } + }, tree.options.dnd.draggable)); + } + // Attach ui.droppable to this Fancytree instance + if(dnd && dnd.dragDrop) { + tree.widget.element.droppable($.extend({ + addClasses: false, + tolerance: "intersect", + greedy: false +/* + activate: function(event, ui) { + tree.debug("droppable - activate", event, ui, this); + }, + create: function(event, ui) { + tree.debug("droppable - create", event, ui); + }, + deactivate: function(event, ui) { + tree.debug("droppable - deactivate", event, ui); + }, + drop: function(event, ui) { + tree.debug("droppable - drop", event, ui); + }, + out: function(event, ui) { + tree.debug("droppable - out", event, ui); + }, + over: function(event, ui) { + tree.debug("droppable - over", event, ui); + } +*/ + }, tree.options.dnd.droppable)); + } +} + +//--- Extend ui.draggable event handling -------------------------------------- + +function _registerDnd() { + if(didRegisterDnd){ + return; + } + + // Register proxy-functions for draggable.start/drag/stop + + $.ui.plugin.add("draggable", "connectToFancytree", { + start: function(event, ui) { + // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10 + var draggable = $(this).data("ui-draggable") || $(this).data("draggable"), + sourceNode = ui.helper.data("ftSourceNode") || null; + + if(sourceNode) { + // Adjust helper offset, so cursor is slightly outside top/left corner + draggable.offset.click.top = -2; + draggable.offset.click.left = + 16; + // Trigger dragStart event + // TODO: when called as connectTo..., the return value is ignored(?) + return sourceNode.tree.ext.dnd._onDragEvent("start", sourceNode, null, event, ui, draggable); + } + }, + drag: function(event, ui) { + var isHelper, logObject, + // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10 + draggable = $(this).data("ui-draggable") || $(this).data("draggable"), + sourceNode = ui.helper.data("ftSourceNode") || null, + prevTargetNode = ui.helper.data("ftTargetNode") || null, + targetNode = $.ui.fancytree.getNode(event.target); + + if(event.target && !targetNode){ + // We got a drag event, but the targetNode could not be found + // at the event location. This may happen, + // 1. if the mouse jumped over the drag helper, + // 2. or if a non-fancytree element is dragged + // We ignore it: + isHelper = $(event.target).closest("div.fancytree-drag-helper,#fancytree-drop-marker").length > 0; + if(isHelper){ + logObject = sourceNode || prevTargetNode || $.ui.fancytree; + logObject.debug("Drag event over helper: ignored."); + return; + } + } + ui.helper.data("ftTargetNode", targetNode); + // Leaving a tree node + if(prevTargetNode && prevTargetNode !== targetNode ) { + prevTargetNode.tree.ext.dnd._onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable); + } + if(targetNode){ + if(!targetNode.tree.options.dnd.dragDrop) { + // not enabled as drop target + } else if(targetNode === prevTargetNode) { + // Moving over same node + targetNode.tree.ext.dnd._onDragEvent("over", targetNode, sourceNode, event, ui, draggable); + }else{ + // Entering this node first time + targetNode.tree.ext.dnd._onDragEvent("enter", targetNode, sourceNode, event, ui, draggable); + } + } + // else go ahead with standard event handling + }, + stop: function(event, ui) { + // 'draggable' was renamed to 'ui-draggable' since jQueryUI 1.10 + var logObject, + draggable = $(this).data("ui-draggable") || $(this).data("draggable"), + sourceNode = ui.helper.data("ftSourceNode") || null, + targetNode = ui.helper.data("ftTargetNode") || null, +// mouseDownEvent = draggable._mouseDownEvent, + eventType = event.type, + dropped = (eventType === "mouseup" && event.which === 1); + + if(!dropped){ + logObject = sourceNode || targetNode || $.ui.fancytree; + logObject.debug("Drag was cancelled"); + } + if(targetNode) { + if(dropped){ + targetNode.tree.ext.dnd._onDragEvent("drop", targetNode, sourceNode, event, ui, draggable); + } + targetNode.tree.ext.dnd._onDragEvent("leave", targetNode, sourceNode, event, ui, draggable); + } + if(sourceNode){ + sourceNode.tree.ext.dnd._onDragEvent("stop", sourceNode, null, event, ui, draggable); + } + } + }); + + didRegisterDnd = true; +} + + +/* ***************************************************************************** + * + */ + +$.ui.fancytree.registerExtension({ + name: "dnd", + version: "0.1.0", + // Default options for this extension. + options: { + // Make tree nodes accept draggables + autoExpandMS: 1000, // Expand nodes after n milliseconds of hovering. + draggable: null, // Additional options passed to jQuery draggable + droppable: null, // Additional options passed to jQuery droppable + focusOnClick: false, // Focus, although draggable cancels mousedown event (#270) +// helper: null, // Callback +// helperParent: null, // jQuery object (defaults to Fancytree container) + preventVoidMoves: true, // Prevent dropping nodes 'before self', etc. + preventRecursiveMoves: true, // Prevent dropping nodes on own descendants + // Events (drag support) + dragStart: null, // Callback(sourceNode, data), return true, to enable dnd + dragStop: null, // Callback(sourceNode, data) + // Events (drop support) + dragEnter: null, // Callback(targetNode, data) + dragOver: null, // Callback(targetNode, data) + dragDrop: null, // Callback(targetNode, data) + dragLeave: null // Callback(targetNode, data) + }, + + treeInit: function(ctx){ + var tree = ctx.tree; + this._superApply(arguments); + // issue #270: draggable eats mousedown events + if( tree.options.dnd.dragStart ){ + tree.$container.on("mousedown", function(event){ + if( !tree.hasFocus() && ctx.options.dnd.focusOnClick ) { + var node = $.ui.fancytree.getNode(event); + node.debug("Re-enable focus that was prevented by jQuery UI draggable."); + // node.setFocus(); + // $(node.span).closest(":tabbable").focus(); + // $(event.target).trigger("focus"); + // $(event.target).closest(":tabbable").trigger("focus"); + setTimeout(function() { // #300 + $(event.target).closest(":tabbable").focus(); + }, 10); + } + }); + } + _initDragAndDrop(tree); + }, + /* Override key handler in order to cancel dnd on escape.*/ + nodeKeydown: function(ctx) { + var event = ctx.originalEvent; + if( event.which === $.ui.keyCode.ESCAPE) { + this._local._cancelDrag(); + } + return this._superApply(arguments); + }, + nodeClick: function(ctx) { + // if( ctx.options.dnd.dragStart ){ + // ctx.tree.$container.focus(); + // } + return this._superApply(arguments); + }, + /* Display drop marker according to hitMode ('after', 'before', 'over', 'out', 'start', 'stop'). */ + _setDndStatus: function(sourceNode, targetNode, helper, hitMode, accept) { + var markerOffsetX = 0, + markerAt = "center", + instData = this._local, + $source = sourceNode ? $(sourceNode.span) : null, + $target = $(targetNode.span); + + if( !instData.$dropMarker ) { + instData.$dropMarker = $("<div id='fancytree-drop-marker'></div>") + .hide() + .css({"z-index": 1000}) + .prependTo($(this.$div).parent()); +// .prependTo("body"); + } +// this.$dropMarker.attr("class", hitMode); + if(hitMode === "after" || hitMode === "before" || hitMode === "over"){ +// $source && $source.addClass("fancytree-drag-source"); + +// $target.addClass("fancytree-drop-target"); + + switch(hitMode){ + case "before": + instData + .$dropMarker.removeClass("fancytree-drop-after fancytree-drop-over") + .addClass("fancytree-drop-before"); + markerAt = "top"; + break; + case "after": + instData.$dropMarker.removeClass("fancytree-drop-before fancytree-drop-over") + .addClass("fancytree-drop-after"); + markerAt = "bottom"; + break; + default: + instData.$dropMarker.removeClass("fancytree-drop-after fancytree-drop-before") + .addClass("fancytree-drop-over"); + $target.addClass("fancytree-drop-target"); + markerOffsetX = 8; + } + + instData.$dropMarker + .show() + .position($.ui.fancytree.fixPositionOptions({ + my: "left" + offsetString(markerOffsetX) + " center", + at: "left " + markerAt, + of: $target + })); +// helper.addClass("fancytree-drop-hover"); + } else { +// $source && $source.removeClass("fancytree-drag-source"); + $target.removeClass("fancytree-drop-target"); + instData.$dropMarker.hide(); +// helper.removeClass("fancytree-drop-hover"); + } + if(hitMode === "after"){ + $target.addClass("fancytree-drop-after"); + } else { + $target.removeClass("fancytree-drop-after"); + } + if(hitMode === "before"){ + $target.addClass("fancytree-drop-before"); + } else { + $target.removeClass("fancytree-drop-before"); + } + if(accept === true){ + if($source){ + $source.addClass("fancytree-drop-accept"); + } + $target.addClass("fancytree-drop-accept"); + helper.addClass("fancytree-drop-accept"); + }else{ + if($source){ + $source.removeClass("fancytree-drop-accept"); + } + $target.removeClass("fancytree-drop-accept"); + helper.removeClass("fancytree-drop-accept"); + } + if(accept === false){ + if($source){ + $source.addClass("fancytree-drop-reject"); + } + $target.addClass("fancytree-drop-reject"); + helper.addClass("fancytree-drop-reject"); + }else{ + if($source){ + $source.removeClass("fancytree-drop-reject"); + } + $target.removeClass("fancytree-drop-reject"); + helper.removeClass("fancytree-drop-reject"); + } + }, + + /* + * Handles drag'n'drop functionality. + * + * A standard jQuery drag-and-drop process may generate these calls: + * + * draggable helper(): + * _onDragEvent("helper", sourceNode, null, event, null, null); + * start: + * _onDragEvent("start", sourceNode, null, event, ui, draggable); + * drag: + * _onDragEvent("leave", prevTargetNode, sourceNode, event, ui, draggable); + * _onDragEvent("over", targetNode, sourceNode, event, ui, draggable); + * _onDragEvent("enter", targetNode, sourceNode, event, ui, draggable); + * stop: + * _onDragEvent("drop", targetNode, sourceNode, event, ui, draggable); + * _onDragEvent("leave", targetNode, sourceNode, event, ui, draggable); + * _onDragEvent("stop", sourceNode, null, event, ui, draggable); + */ + _onDragEvent: function(eventName, node, otherNode, event, ui, draggable) { + if(eventName !== "over"){ + this.debug("tree.ext.dnd._onDragEvent(%s, %o, %o) - %o", eventName, node, otherNode, this); + } + var /*$helper, $helperParent,*/ nodeOfs, relPos, relPos2, + enterResponse, hitMode, r, + opts = this.options, + dnd = opts.dnd, + ctx = this._makeHookContext(node, event, {otherNode: otherNode, ui: ui, draggable: draggable}), + res = null, + $nodeTag = $(node.span); + + switch (eventName) { +// case "helper": +// // Only event and node argument is available +// $helper = $("<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>") +// .css({zIndex: 3, position: "relative"}) // so it appears above ext-wide selection bar +// .append($nodeTag.find("span.fancytree-title").clone()); +// // #345: helper parent is now set using draggable.appendTo +// // $helperParent = dnd.helperParent || $("ul.fancytree-container", node.tree.$div); +// // DT issue 244: helper should be child of scrollParent +// // $helperParent.append($helper); +// // Attach node reference to helper object +// $helper.data("ftSourceNode", node); +// // this.debug("helper=%o", $helper); +// // this.debug("helper.sourceNode=%o", $helper.data("ftSourceNode")); +// res = $helper; +// break; + + case "start": + if( node.isStatusNode() ) { + res = false; + } else if(dnd.dragStart) { + res = dnd.dragStart(node, ctx); + } + if(res === false) { + this.debug("tree.dragStart() cancelled"); + //draggable._clear(); + // NOTE: the return value seems to be ignored (drag is not canceled, when false is returned) + // TODO: call this._cancelDrag()? + ui.helper.trigger("mouseup") + .hide(); + } else { + $nodeTag.addClass("fancytree-drag-source"); + } + break; + + case "enter": + if(dnd.preventRecursiveMoves && node.isDescendantOf(otherNode)){ + r = false; + }else{ + r = dnd.dragEnter ? dnd.dragEnter(node, ctx) : null; + } + if(!r){ + // convert null, undefined, false to false + res = false; + }else if ( $.isArray(r) ) { + // TODO: also accept passing an object of this format directly + res = { + over: ($.inArray("over", r) >= 0), + before: ($.inArray("before", r) >= 0), + after: ($.inArray("after", r) >= 0) + }; + }else{ + res = { + over: ((r === true) || (r === "over")), + before: ((r === true) || (r === "before")), + after: ((r === true) || (r === "after")) + }; + } + ui.helper.data("enterResponse", res); + this.debug("helper.enterResponse: %o", res); + break; + + case "over": + enterResponse = ui.helper.data("enterResponse"); + hitMode = null; + if(enterResponse === false){ + // Don't call dragOver if onEnter returned false. +// break; + } else if(typeof enterResponse === "string") { + // Use hitMode from onEnter if provided. + hitMode = enterResponse; + } else { + // Calculate hitMode from relative cursor position. + nodeOfs = $nodeTag.offset(); + relPos = { x: event.pageX - nodeOfs.left, + y: event.pageY - nodeOfs.top }; + relPos2 = { x: relPos.x / $nodeTag.width(), + y: relPos.y / $nodeTag.height() }; + + if( enterResponse.after && relPos2.y > 0.75 ){ + hitMode = "after"; + } else if(!enterResponse.over && enterResponse.after && relPos2.y > 0.5 ){ + hitMode = "after"; + } else if(enterResponse.before && relPos2.y <= 0.25) { + hitMode = "before"; + } else if(!enterResponse.over && enterResponse.before && relPos2.y <= 0.5) { + hitMode = "before"; + } else if(enterResponse.over) { + hitMode = "over"; + } + // Prevent no-ops like 'before source node' + // TODO: these are no-ops when moving nodes, but not in copy mode + if( dnd.preventVoidMoves ){ + if(node === otherNode){ + this.debug(" drop over source node prevented"); + hitMode = null; + }else if(hitMode === "before" && otherNode && node === otherNode.getNextSibling()){ + this.debug(" drop after source node prevented"); + hitMode = null; + }else if(hitMode === "after" && otherNode && node === otherNode.getPrevSibling()){ + this.debug(" drop before source node prevented"); + hitMode = null; + }else if(hitMode === "over" && otherNode && otherNode.parent === node && otherNode.isLastSibling() ){ + this.debug(" drop last child over own parent prevented"); + hitMode = null; + } + } +// this.debug("hitMode: %s - %s - %s", hitMode, (node.parent === otherNode), node.isLastSibling()); + ui.helper.data("hitMode", hitMode); + } + // Auto-expand node (only when 'over' the node, not 'before', or 'after') + if(hitMode === "over" && dnd.autoExpandMS && node.hasChildren() !== false && !node.expanded) { + node.scheduleAction("expand", dnd.autoExpandMS); + } + if(hitMode && dnd.dragOver){ + // TODO: http://code.google.com/p/dynatree/source/detail?r=625 + ctx.hitMode = hitMode; + res = dnd.dragOver(node, ctx); + } + // DT issue 332 +// this._setDndStatus(otherNode, node, ui.helper, hitMode, res!==false); + this._local._setDndStatus(otherNode, node, ui.helper, hitMode, res!==false && hitMode !== null); + break; + + case "drop": + hitMode = ui.helper.data("hitMode"); + if(hitMode && dnd.dragDrop){ + ctx.hitMode = hitMode; + dnd.dragDrop(node, ctx); + } + break; + + case "leave": + // Cancel pending expand request + node.scheduleAction("cancel"); + ui.helper.data("enterResponse", null); + ui.helper.data("hitMode", null); + this._local._setDndStatus(otherNode, node, ui.helper, "out", undefined); + if(dnd.dragLeave){ + dnd.dragLeave(node, ctx); + } + break; + + case "stop": + $nodeTag.removeClass("fancytree-drag-source"); + if(dnd.dragStop){ + dnd.dragStop(node, ctx); + } + break; + + default: + $.error("Unsupported drag event: " + eventName); + } + return res; + }, + + _cancelDrag: function() { + var dd = $.ui.ddmanager.current; + if(dd){ + dd.cancel(); + } + } +}); +}(jQuery, window, document)); + +/*! + * jquery.fancytree.edit.js + * + * Make node titles editable. + * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +;(function($, window, document, undefined) { + +"use strict"; + + +/******************************************************************************* + * Private functions and variables + */ + +var isMac = /Mac/.test(navigator.platform), + escapeHtml = $.ui.fancytree.escapeHtml, + unescapeHtml = $.ui.fancytree.unescapeHtml; + +/** + * [ext-edit] Start inline editing of current node title. + * + * @alias FancytreeNode#editStart + * @requires Fancytree + */ +$.ui.fancytree._FancytreeNodeClass.prototype.editStart = function(){ + var $input, + node = this, + tree = this.tree, + local = tree.ext.edit, + instOpts = tree.options.edit, + $title = $(".fancytree-title", node.span), + eventData = { + node: node, + tree: tree, + options: tree.options, + isNew: $(node.span).hasClass("fancytree-edit-new"), + orgTitle: node.title, + input: null, + dirty: false + }; + + // beforeEdit may want to modify the title before editing + if( instOpts.beforeEdit.call(node, {type: "beforeEdit"}, eventData) === false ) { + return false; + } + $.ui.fancytree.assert(!local.currentNode, "recursive edit"); + local.currentNode = this; + local.eventData = eventData; + + // Disable standard Fancytree mouse- and key handling + tree.widget._unbind(); + // #116: ext-dnd prevents the blur event, so we have to catch outer clicks + $(document).on("mousedown.fancytree-edit", function(event){ + if( ! $(event.target).hasClass("fancytree-edit-input") ){ + node.editEnd(true, event); + } + }); + + // Replace node with <input> + $input = $("<input />", { + "class": "fancytree-edit-input", + type: "text", + value: unescapeHtml(eventData.orgTitle) + }); + local.eventData.input = $input; + if ( instOpts.adjustWidthOfs != null ) { + $input.width($title.width() + instOpts.adjustWidthOfs); + } + if ( instOpts.inputCss != null ) { + $input.css(instOpts.inputCss); + } + + $title.html($input); + + // Focus <input> and bind keyboard handler + $input + .focus() + .change(function(event){ + $input.addClass("fancytree-edit-dirty"); + }).keydown(function(event){ + switch( event.which ) { + case $.ui.keyCode.ESCAPE: + node.editEnd(false, event); + break; + case $.ui.keyCode.ENTER: + node.editEnd(true, event); + return false; // so we don't start editmode on Mac + } + event.stopPropagation(); + }).blur(function(event){ + return node.editEnd(true, event); + }); + + instOpts.edit.call(node, {type: "edit"}, eventData); +}; + + +/** + * [ext-edit] Stop inline editing. + * @param {Boolean} [applyChanges=false] false: cancel edit, true: save (if modified) + * @alias FancytreeNode#editEnd + * @requires jquery.fancytree.edit.js + */ +$.ui.fancytree._FancytreeNodeClass.prototype.editEnd = function(applyChanges, _event){ + var newVal, + node = this, + tree = this.tree, + local = tree.ext.edit, + eventData = local.eventData, + instOpts = tree.options.edit, + $title = $(".fancytree-title", node.span), + $input = $title.find("input.fancytree-edit-input"); + + // eventData.isNew = $(node.span).hasClass("fancytree-edit-new"); + + if( instOpts.trim ) { + $input.val($.trim($input.val())); + } + newVal = $input.val(); + // eventData.dirty = $input.hasClass("fancytree-edit-dirty") || ; + eventData.dirty = ( newVal !== node.title ); + + // Find out, if saving is required + if( applyChanges === false ) { + // If true/false was passed, honor this (except in rename mode, if unchanged) + eventData.save = false; + } else if( eventData.isNew ) { + // In create mode, we save everyting, except for empty text + eventData.save = (newVal !== ""); + } else { + // In rename mode, we save everyting, except for empty or unchanged text + eventData.save = eventData.dirty && (newVal !== ""); + } + // Allow to break (keep editor open), modify input, or re-define data.save + if( instOpts.beforeClose.call(node, {type: "beforeClose"}, eventData) === false){ + return false; + } + if( eventData.save && instOpts.save.call(node, {type: "save"}, eventData) === false){ + return false; + } + $input + .removeClass("fancytree-edit-dirty") + .unbind(); + // Unbind outer-click handler + $(document).off(".fancytree-edit"); + + if( eventData.save ) { + node.setTitle( escapeHtml(newVal) ); + // $(node.span).removeClass("fancytree-edit-new"); + node.setFocus(); + }else{ + if( eventData.isNew ) { + node.remove(); + node = eventData.node = null; + local.relatedNode.setFocus(); + } else { + node.renderTitle(); + node.setFocus(); + } + } + local.eventData = null; + local.currentNode = null; + local.relatedNode = null; + // Re-enable mouse and keyboard handling + tree.widget._bind(); + // Set keyboard focus, even if setFocus() claims 'nothing to do' + $(tree.$container).focus(); + eventData.input = null; + instOpts.close.call(node, {type: "close"}, eventData); + return true; +}; + + +/** +* [ext-edit] Create a new child or sibling node and start edit mode. +* +* @param {String} [mode='child'] 'before', 'after', or 'child' +* @param {Object} [init] NodeData (or simple title string) +* @alias FancytreeNode#editCreateNode +* @requires jquery.fancytree.edit.js +*/ +$.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode = function(mode, init){ + var newNode, + self = this; + + mode = mode || "child"; + if( init == null ) { + init = { title: "" }; + } else if( typeof init === "string" ) { + init = { title: init }; + } else { + $.ui.fancytree.assert($.isPlainObject(init)); + } + // Make sure node is expanded (and loaded) in 'child' mode + if( mode === "child" && !this.isExpanded() && this.hasChildren() !== false ) { + this.setExpanded().done(function(){ + self.editCreateNode(mode, init); + }); + return; + } + newNode = this.addNode(init, mode); + newNode.makeVisible(/*{noAnimation: true}*/).done(function(){ + $(newNode.span).addClass("fancytree-edit-new"); + self.tree.ext.edit.relatedNode = self; + newNode.editStart(); + }); +}; + + +/** + * [ext-edit] Check if any node in this tree in edit mode. + * + * @returns {FancytreeNode | null} + * @alias Fancytree#isEditing + * @requires jquery.fancytree.edit.js + */ +$.ui.fancytree._FancytreeClass.prototype.isEditing = function(){ + return this.ext.edit.currentNode; +}; + + +/** + * [ext-edit] Check if this node is in edit mode. + * @returns {Boolean} true if node is currently beeing edited + * @alias FancytreeNode#isEditing + * @requires jquery.fancytree.edit.js + */ +$.ui.fancytree._FancytreeNodeClass.prototype.isEditing = function(){ + return this.tree.ext.edit.currentNode === this; +}; + + +/******************************************************************************* + * Extension code + */ +$.ui.fancytree.registerExtension({ + name: "edit", + version: "0.2.0", + // Default options for this extension. + options: { + adjustWidthOfs: 4, // null: don't adjust input size to content + allowEmpty: false, // Prevent empty input + inputCss: {minWidth: "3em"}, + triggerCancel: ["esc", "tab", "click"], + // triggerStart: ["f2", "dblclick", "shift+click", "mac+enter"], + triggerStart: ["f2", "shift+click", "mac+enter"], + trim: true, // Trim whitespace before save + // Events: + beforeClose: $.noop, // Return false to prevent cancel/save (data.input is available) + beforeEdit: $.noop, // Return false to prevent edit mode + close: $.noop, // Editor was removed + edit: $.noop, // Editor was opened (available as data.input) +// keypress: $.noop, // Not yet implemented + save: $.noop // Save data.input.val() or return false to keep editor open + }, + // Local attributes + currentNode: null, + + treeInit: function(ctx){ + this._superApply(arguments); + this.$container.addClass("fancytree-ext-edit"); + }, + nodeClick: function(ctx) { + if( $.inArray("shift+click", ctx.options.edit.triggerStart) >= 0 ){ + if( ctx.originalEvent.shiftKey ){ + ctx.node.editStart(); + return false; + } + } + return this._superApply(arguments); + }, + nodeDblclick: function(ctx) { + if( $.inArray("dblclick", ctx.options.edit.triggerStart) >= 0 ){ + ctx.node.editStart(); + return false; + } + return this._superApply(arguments); + }, + nodeKeydown: function(ctx) { + switch( ctx.originalEvent.which ) { + case 113: // [F2] + if( $.inArray("f2", ctx.options.edit.triggerStart) >= 0 ){ + ctx.node.editStart(); + return false; + } + break; + case $.ui.keyCode.ENTER: + if( $.inArray("mac+enter", ctx.options.edit.triggerStart) >= 0 && isMac ){ + ctx.node.editStart(); + return false; + } + break; + } + return this._superApply(arguments); + } +}); +}(jQuery, window, document)); + +/*! + * jquery.fancytree.filter.js + * + * Remove or highlight tree nodes, based on a filter. + * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +;(function($, window, document, undefined) { + +"use strict"; + + +/******************************************************************************* + * Private functions and variables + */ + +function _escapeRegex(str){ + /*jshint regexdash:true */ + return (str + "").replace(/([.?*+\^\$\[\]\\(){}|-])/g, "\\$1"); +} + +$.ui.fancytree._FancytreeClass.prototype._applyFilterImpl = function(filter, branchMode, leavesOnly){ + var match, re, + count = 0, + hideMode = this.options.filter.mode === "hide"; + // leavesOnly = !branchMode && this.options.filter.leavesOnly; + leavesOnly = !!leavesOnly && !branchMode; + + // Default to 'match title substring (not case sensitive)' + if(typeof filter === "string"){ + match = _escapeRegex(filter); // make sure a '.' is treated literally + re = new RegExp(".*" + match + ".*", "i"); + filter = function(node){ + return !!re.exec(node.title); + }; + } + + this.enableFilter = true; + this.lastFilterArgs = arguments; + + this.$div.addClass("fancytree-ext-filter"); + if( hideMode ){ + this.$div.addClass("fancytree-ext-filter-hide"); + } else { + this.$div.addClass("fancytree-ext-filter-dimm"); + } + // Reset current filter + this.visit(function(node){ + delete node.match; + delete node.subMatch; + }); + // Adjust node.hide, .match, .subMatch flags + this.visit(function(node){ + if ((!leavesOnly || node.children == null) && filter(node)) { + count++; + node.match = true; + node.visitParents(function(p){ + p.subMatch = true; + }); + if( branchMode ) { + node.visit(function(p){ + p.match = true; + }); + return "skip"; + } + } + }); + // Redraw + this.render(); + return count; +}; + +/** + * [ext-filter] Dimm or hide nodes. + * + * @param {function | string} filter + * @param {boolean} [leavesOnly=false] + * @returns {integer} count + * @alias Fancytree#filterNodes + * @requires jquery.fancytree.filter.js + */ +$.ui.fancytree._FancytreeClass.prototype.filterNodes = function(filter, leavesOnly){ + return this._applyFilterImpl(filter, false, leavesOnly); +}; + +/** + * @deprecated + */ +$.ui.fancytree._FancytreeClass.prototype.applyFilter = function(filter){ + this.warn("Fancytree.applyFilter() is deprecated since 2014-05-10. Use .filterNodes() instead."); + return this.filterNodes.apply(this, arguments); +}; + +/** + * [ext-filter] Dimm or hide whole branches. + * + * @param {function | string} filter + * @returns {integer} count + * @alias Fancytree#filterBranches + * @requires jquery.fancytree.filter.js + */ +$.ui.fancytree._FancytreeClass.prototype.filterBranches = function(filter){ + return this._applyFilterImpl(filter, true, null); +}; + + +/** + * [ext-filter] Reset the filter. + * + * @alias Fancytree#clearFilter + * @requires jquery.fancytree.filter.js + */ +$.ui.fancytree._FancytreeClass.prototype.clearFilter = function(){ + this.visit(function(node){ + delete node.match; + delete node.subMatch; + }); + this.enableFilter = false; + this.lastFilterArgs = null; + this.$div.removeClass("fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide"); + this.render(); +}; + + +/******************************************************************************* + * Extension code + */ +$.ui.fancytree.registerExtension({ + name: "filter", + version: "0.3.0", + // Default options for this extension. + options: { + autoApply: true, // re-apply last filter if lazy data is loaded + mode: "dimm" + }, + treeInit: function(ctx){ + this._superApply(arguments); + }, + nodeLoadChildren: function(ctx, source) { + return this._superApply(arguments).done(function() { + if( ctx.tree.enableFilter && ctx.tree.lastFilterArgs && ctx.options.filter.autoApply ) { + ctx.tree._applyFilterImpl.apply(ctx.tree, ctx.tree.lastFilterArgs); + } + }); + }, + nodeRenderStatus: function(ctx) { + // Set classes for current status + var res, + node = ctx.node, + tree = ctx.tree, + $span = $(node[tree.statusClassPropName]); + + res = this._superApply(arguments); + // nothing to do, if node was not yet rendered + if( !$span.length || !tree.enableFilter ) { + return res; + } + $span + .toggleClass("fancytree-match", !!node.match) + .toggleClass("fancytree-submatch", !!node.subMatch) + .toggleClass("fancytree-hide", !(node.match || node.subMatch)); + + return res; + } +}); +}(jQuery, window, document)); + +/*! + * jquery.fancytree.glyph.js + * + * Use glyph fonts as instead of icon sprites. + * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +;(function($, window, document, undefined) { + +"use strict"; + +/* ***************************************************************************** + * Private functions and variables + */ + +function _getIcon(opts, type){ + return opts.map[type]; +} + +$.ui.fancytree.registerExtension({ + name: "glyph", + version: "0.2.0", + // Default options for this extension. + options: { + map: { + checkbox: "icon-check-empty", + checkboxSelected: "icon-check", + checkboxUnknown: "icon-check icon-muted", + error: "icon-exclamation-sign", + expanderClosed: "icon-caret-right", + expanderLazy: "icon-angle-right", + expanderOpen: "icon-caret-down", + doc: "icon-file-alt", + noExpander: "", + // Default node icons. + // (Use tree.options.iconClass(node) callback to define custom icons + // based on node data) + docOpen: "icon-file-alt", + loading: "icon-refresh icon-spin", + folder: "icon-folder-close-alt", + folderOpen: "icon-folder-open-alt" + } + }, + + treeInit: function(ctx){ + var tree = ctx.tree; + this._superApply(arguments); + tree.$container.addClass("fancytree-ext-glyph"); + }, + nodeRenderStatus: function(ctx) { + var icon, span, + node = ctx.node, + $span = $(node.span), + opts = ctx.options.glyph, + // callback = opts.icon, + map = opts.map + // $span = $(node.span) + ; + + this._superApply(arguments); + + if( node.isRoot() ){ + return; + } + span = $span.children("span.fancytree-expander").get(0); + if( span ){ + if( node.isLoading() ){ + icon = "loading"; + }else if( node.expanded ){ + icon = "expanderOpen"; + }else if( node.isUndefined() ){ + icon = "expanderLazy"; + }else if( node.hasChildren() ){ + icon = "expanderClosed"; + }else{ + icon = "noExpander"; + } + span.className = "fancytree-expander " + map[icon]; + } + + if( node.tr ){ + span = $("td", node.tr).children("span.fancytree-checkbox").get(0); + }else{ + span = $span.children("span.fancytree-checkbox").get(0); + } + if( span ){ + icon = node.selected ? "checkboxSelected" : (node.partsel ? "checkboxUnknown" : "checkbox"); + span.className = "fancytree-checkbox " + map[icon]; + } + + // Icon (note that this does not match .fancytree-custom-icon, that might + // be set by opts.iconClass) + span = $span.children("span.fancytree-icon").get(0); + if( span ){ + if( node.folder ){ + icon = node.expanded ? _getIcon(opts, "folderOpen") : _getIcon(opts, "folder"); + }else{ + icon = node.expanded ? _getIcon(opts, "docOpen") : _getIcon(opts, "doc"); + } + span.className = "fancytree-icon " + icon; + } + }, + nodeSetStatus: function(ctx, status, message, details) { + var span, + opts = ctx.options.glyph, + node = ctx.node; + + this._superApply(arguments); + + if(node.parent){ + span = $("span.fancytree-expander", node.span).get(0); + }else{ + span = $(".fancytree-statusnode-wait, .fancytree-statusnode-error", node[this.nodeContainerAttrName]) + .find("span.fancytree-expander").get(0); + } + if( status === "loading"){ + // $("span.fancytree-expander", ctx.node.span).addClass(_getIcon(opts, "loading")); + span.className = "fancytree-expander " + _getIcon(opts, "loading"); + }else if( status === "error"){ + span.className = "fancytree-expander " + _getIcon(opts, "error"); + } + } +}); +}(jQuery, window, document)); + +/*! + * jquery.fancytree.gridnav.js + * + * Support keyboard navigation for trees with embedded input controls. + * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +;(function($, window, document, undefined) { + +"use strict"; + + +/******************************************************************************* + * Private functions and variables + */ + +// Allow these navigation keys even when input controls are focused + +var KC = $.ui.keyCode, + // which keys are *not* handled by embedded control, but passed to tree + // navigation handler: + NAV_KEYS = { + "text": [KC.UP, KC.DOWN], + "checkbox": [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT], + "radiobutton": [KC.UP, KC.DOWN, KC.LEFT, KC.RIGHT], + "select-one": [KC.LEFT, KC.RIGHT], + "select-multiple": [KC.LEFT, KC.RIGHT] + }; + + +/* Calculate TD column index (considering colspans).*/ +function getColIdx($tr, $td) { + var colspan, + td = $td.get(0), + idx = 0; + + $tr.children().each(function () { + if( this === td ) { + return false; + } + colspan = $(this).prop("colspan"); + idx += colspan ? colspan : 1; + }); + return idx; +} + + +/* Find TD at given column index (considering colspans).*/ +function findTdAtColIdx($tr, colIdx) { + var colspan, + res = null, + idx = 0; + + $tr.children().each(function () { + if( idx >= colIdx ) { + res = $(this); + return false; + } + colspan = $(this).prop("colspan"); + idx += colspan ? colspan : 1; + }); + return res; +} + + +/* Find adjacent cell for a given direction. Skip empty cells and consider merged cells */ +function findNeighbourTd($target, keyCode){ + var $tr, colIdx, + $td = $target.closest("td"), + $tdNext = null; + + switch( keyCode ){ + case KC.LEFT: + $tdNext = $td.prev(); + break; + case KC.RIGHT: + $tdNext = $td.next(); + break; + case KC.UP: + case KC.DOWN: + $tr = $td.parent(); + colIdx = getColIdx($tr, $td); + while( true ) { + $tr = (keyCode === KC.UP) ? $tr.prev() : $tr.next(); + if( !$tr.length ) { + break; + } + // Skip hidden rows + if( $tr.is(":hidden") ) { + continue; + } + // Find adjacent cell in the same column + $tdNext = findTdAtColIdx($tr, colIdx); + // Skip cells that don't conatain a focusable element + if( $tdNext && $tdNext.find(":input").length ) { + break; + } + } + break; + } + return $tdNext; +} + + +/******************************************************************************* + * Extension code + */ +$.ui.fancytree.registerExtension({ + name: "gridnav", + version: "0.0.1", + // Default options for this extension. + options: { + autofocusInput: false, // Focus first embedded input if node gets activated + handleCursorKeys: true // Allow UP/DOWN in inputs to move to prev/next node + }, + + treeInit: function(ctx){ + // gridnav requires the table extension to be loaded before itself + this._requireExtension("table", true, true); + this._superApply(arguments); + + this.$container.addClass("fancytree-ext-gridnav"); + + // Activate node if embedded input gets focus (due to a click) + this.$container.on("focusin", function(event){ + var ctx2, + node = $.ui.fancytree.getNode(event.target); + + if( node && !node.isActive() ){ + // Call node.setActive(), but also pass the event + ctx2 = ctx.tree._makeHookContext(node, event); + ctx.tree._callHook("nodeSetActive", ctx2, true); + } + }); + }, + nodeSetActive: function(ctx, flag) { + var $outer, + opts = ctx.options.gridnav, + node = ctx.node, + event = ctx.originalEvent || {}, + triggeredByInput = $(event.target).is(":input"); + + flag = (flag !== false); + + this._superApply(arguments); + + if( flag ){ + if( ctx.options.titlesTabbable ){ + if( !triggeredByInput ) { + $(node.span).find("span.fancytree-title").focus(); + node.setFocus(); + } + // If one node is tabbable, the container no longer needs to be + ctx.tree.$container.attr("tabindex", "-1"); + // ctx.tree.$container.removeAttr("tabindex"); + } else if( opts.autofocusInput && !triggeredByInput ){ + // Set focus to input sub input (if node was clicked, but not + // when TAB was pressed ) + $outer = $(node.tr || node.span); + $outer.find(":input:enabled:first").focus(); + } + } + }, + nodeKeydown: function(ctx) { + var inputType, handleKeys, $td, + opts = ctx.options.gridnav, + event = ctx.originalEvent, + $target = $(event.target); + + // jQuery + inputType = $target.is(":input:enabled") ? $target.prop("type") : null; +// ctx.tree.debug("ext-gridnav nodeKeydown", event, inputType); + + if( inputType && opts.handleCursorKeys ){ + handleKeys = NAV_KEYS[inputType]; + if( handleKeys && $.inArray(event.which, handleKeys) >= 0 ){ + $td = findNeighbourTd($target, event.which); + // ctx.node.debug("ignore keydown in input", event.which, handleKeys); + if( $td && $td.length ) { + $td.find(":input:enabled").focus(); + // Prevent Fancytree default navigation + return false; + } + } + return true; + } + // ctx.tree.debug("ext-gridnav NOT HANDLED", event, inputType); + return this._superApply(arguments); + } +}); +}(jQuery, window, document)); + +/*! + * jquery.fancytree.persist.js + * + * Persist tree status in cookiesRemove or highlight tree nodes, based on a filter. + * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) + * + * @depends: jquery.cookie.js + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +;(function($, window, document, undefined) { + +"use strict"; + + +/******************************************************************************* + * Private functions and variables + */ +var _assert = $.ui.fancytree.assert, + ACTIVE = "active", + EXPANDED = "expanded", + FOCUS = "focus", + SELECTED = "selected"; + + +/* Recursively load lazy nodes + * @param {string} mode 'load', 'expand', false + */ +function _loadLazyNodes(tree, local, keyList, mode, dfd) { + var i, key, l, node, + foundOne = false, + deferredList = [], + missingKeyList = []; + + keyList = keyList || []; + dfd = dfd || $.Deferred(); + + for( i=0, l=keyList.length; i<l; i++ ) { + key = keyList[i]; + node = tree.getNodeByKey(key); + if( node ) { + if( mode && node.isUndefined() ) { + foundOne = true; + tree.debug("_loadLazyNodes: " + node + " is lazy: loading..."); + if( mode === "expand" ) { + deferredList.push(node.setExpanded()); + } else { + deferredList.push(node.load()); + } + } else { + tree.debug("_loadLazyNodes: " + node + " already loaded."); + node.setExpanded(); + } + } else { + missingKeyList.push(key); + tree.debug("_loadLazyNodes: " + node + " was not yet found."); + } + } + + $.when.apply($, deferredList).always(function(){ + // All lazy-expands have finished + if( foundOne && missingKeyList.length > 0 ) { + // If we read new nodes from server, try to resolve yet-missing keys + _loadLazyNodes(tree, local, missingKeyList, mode, dfd); + } else { + if( missingKeyList.length ) { + tree.warn("_loadLazyNodes: could not load those keys: ", missingKeyList); + for( i=0, l=missingKeyList.length; i<l; i++ ) { + key = keyList[i]; + local._appendKey(EXPANDED, keyList[i], false); + } + } + dfd.resolve(); + } + }); + return dfd; +} + + +/** + * [ext-persist] Remove persistence cookies of the given type(s). + * Called like + * $("#tree").fancytree("getTree").clearCookies("active expanded focus selected"); + * + * @alias Fancytree#clearCookies + * @requires jquery.fancytree.persist.js + */ +$.ui.fancytree._FancytreeClass.prototype.clearCookies = function(types){ + var local = this.ext.persist, + prefix = local.cookiePrefix; + + types = types || "active expanded focus selected"; + if(types.indexOf(ACTIVE) >= 0){ + local._data(prefix + ACTIVE, null); + } + if(types.indexOf(EXPANDED) >= 0){ + local._data(prefix + EXPANDED, null); + } + if(types.indexOf(FOCUS) >= 0){ + local._data(prefix + FOCUS, null); + } + if(types.indexOf(SELECTED) >= 0){ + local._data(prefix + SELECTED, null); + } +}; + + +/** + * [ext-persist] Return persistence information from cookies + * + * Called like + * $("#tree").fancytree("getTree").getPersistData(); + * + * @alias Fancytree#getPersistData + * @requires jquery.fancytree.persist.js + */ +$.ui.fancytree._FancytreeClass.prototype.getPersistData = function(){ + var local = this.ext.persist, + prefix = local.cookiePrefix, + delim = local.cookieDelimiter, + res = {}; + + res[ACTIVE] = local._data(prefix + ACTIVE); + res[EXPANDED] = (local._data(prefix + EXPANDED) || "").split(delim); + res[SELECTED] = (local._data(prefix + SELECTED) || "").split(delim); + res[FOCUS] = local._data(prefix + FOCUS); + return res; +}; + + +/* ***************************************************************************** + * Extension code + */ +$.ui.fancytree.registerExtension({ + name: "persist", + version: "0.3.0", + // Default options for this extension. + options: { + cookieDelimiter: "~", + cookiePrefix: undefined, // 'fancytree-<treeId>-' by default + cookie: { + raw: false, + expires: "", + path: "", + domain: "", + secure: false + }, + expandLazy: false, // true: recursively expand and load lazy nodes + overrideSource: true, // true: cookie takes precedence over `source` data attributes. + store: "auto", // 'cookie': force cookie, 'local': force localStore, 'session': force sessionStore + types: "active expanded focus selected" + }, + + /* Generic read/write string data to cookie, sessionStorage or localStorage. */ + _data: function(key, value){ + var ls = this._local.localStorage; // null, sessionStorage, or localStorage + + if( value === undefined ) { + return ls ? ls.getItem(key) : $.cookie(key); + } else if ( value === null ) { + if( ls ) { + ls.removeItem(key); + } else { + $.removeCookie(key); + } + } else { + if( ls ) { + ls.setItem(key, value); + } else { + $.cookie(key, value, this.options.persist.cookie); + } + } + }, + + /* Append `key` to a cookie. */ + _appendKey: function(type, key, flag){ + key = "" + key; // #90 + var local = this._local, + instOpts = this.options.persist, + delim = instOpts.cookieDelimiter, + cookieName = local.cookiePrefix + type, + data = local._data(cookieName), + keyList = data ? data.split(delim) : [], + idx = $.inArray(key, keyList); + // Remove, even if we add a key, so the key is always the last entry + if(idx >= 0){ + keyList.splice(idx, 1); + } + // Append key to cookie + if(flag){ + keyList.push(key); + } + local._data(cookieName, keyList.join(delim)); + }, + + treeInit: function(ctx){ + var tree = ctx.tree, + opts = ctx.options, + local = this._local, + instOpts = this.options.persist; + + // For 'auto' or 'cookie' mode, the cookie plugin must be available + _assert(instOpts.store === "localStore" || $.cookie, "Missing required plugin for 'persist' extension: jquery.cookie.js"); + + local.cookiePrefix = instOpts.cookiePrefix || ("fancytree-" + tree._id + "-"); + local.storeActive = instOpts.types.indexOf(ACTIVE) >= 0; + local.storeExpanded = instOpts.types.indexOf(EXPANDED) >= 0; + local.storeSelected = instOpts.types.indexOf(SELECTED) >= 0; + local.storeFocus = instOpts.types.indexOf(FOCUS) >= 0; + if( instOpts.store === "cookie" || !window.localStorage ) { + local.localStorage = null; + } else { + local.localStorage = (instOpts.store === "local") ? window.localStorage : window.sessionStorage; + } + + // Bind init-handler to apply cookie state + tree.$div.bind("fancytreeinit", function(event){ + var cookie, dfd, i, keyList, node, + prevFocus = local._data(local.cookiePrefix + FOCUS); // record this before node.setActive() overrides it; + + // tree.debug("document.cookie:", document.cookie); + + cookie = local._data(local.cookiePrefix + EXPANDED); + keyList = cookie && cookie.split(instOpts.cookieDelimiter); + + if( local.storeExpanded ) { + // Recursively load nested lazy nodes if expandLazy is 'expand' or 'load' + // Also remove expand-cookies for unmatched nodes + dfd = _loadLazyNodes(tree, local, keyList, instOpts.expandLazy ? "expand" : false , null); + } else { + // nothing to do + dfd = new $.Deferred().resolve(); + } + + dfd.done(function(){ + if(local.storeSelected){ + cookie = local._data(local.cookiePrefix + SELECTED); + if(cookie){ + keyList = cookie.split(instOpts.cookieDelimiter); + for(i=0; i<keyList.length; i++){ + node = tree.getNodeByKey(keyList[i]); + if(node){ + if(node.selected === undefined || instOpts.overrideSource && (node.selected === false)){ +// node.setSelected(); + node.selected = true; + node.renderStatus(); + } + }else{ + // node is no longer member of the tree: remove from cookie also + local._appendKey(SELECTED, keyList[i], false); + } + } + } + // In selectMode 3 we have to fix the child nodes, since we + // only stored the selected *top* nodes + if( tree.options.selectMode === 3 ){ + tree.visit(function(n){ + if( n.selected ) { + n.fixSelection3AfterClick(); + return "skip"; + } + }); + } + } + if(local.storeActive){ + cookie = local._data(local.cookiePrefix + ACTIVE); + if(cookie && (opts.persist.overrideSource || !tree.activeNode)){ + node = tree.getNodeByKey(cookie); + if(node){ + node.debug("persist: set active", cookie); + // We only want to set the focus if the container + // had the keyboard focus before + node.setActive(true, {noFocus: true}); + } + } + } + if(local.storeFocus && prevFocus){ + node = tree.getNodeByKey(prevFocus); + if(node){ + // node.debug("persist: set focus", cookie); + if( tree.options.titlesTabbable ) { + $(node.span).find(".fancytree-title").focus(); + } else { + $(tree.$container).focus(); + } + // node.setFocus(); + } + } + tree._triggerTreeEvent("restore", null, {}); + }); + }); + // Init the tree + return this._superApply(arguments); + }, + nodeSetActive: function(ctx, flag, opts) { + var res, + local = this._local; + + flag = (flag !== false); + res = this._superApply(arguments); + + if(local.storeActive){ + local._data(local.cookiePrefix + ACTIVE, this.activeNode ? this.activeNode.key : null); + } + return res; + }, + nodeSetExpanded: function(ctx, flag, opts) { + var res, + node = ctx.node, + local = this._local; + + flag = (flag !== false); + res = this._superApply(arguments); + + if(local.storeExpanded){ + local._appendKey(EXPANDED, node.key, flag); + } + return res; + }, + nodeSetFocus: function(ctx, flag) { + var res, + local = this._local; + + flag = (flag !== false); + res = this._superApply(arguments); + + if( local.storeFocus ) { + local._data(local.cookiePrefix + FOCUS, this.focusNode ? this.focusNode.key : null); + } + return res; + }, + nodeSetSelected: function(ctx, flag) { + var res, selNodes, + tree = ctx.tree, + node = ctx.node, + local = this._local; + + flag = (flag !== false); + res = this._superApply(arguments); + + if(local.storeSelected){ + if( tree.options.selectMode === 3 ){ + // In selectMode 3 we only store the the selected *top* nodes. + // De-selecting a node may also de-select some parents, so we + // calculate the current status again + selNodes = $.map(tree.getSelectedNodes(true), function(n){ + return n.key; + }); + selNodes = selNodes.join(ctx.options.persist.cookieDelimiter); + local._data(local.cookiePrefix + SELECTED, selNodes); + } else { + local._appendKey(SELECTED, node.key, flag); + } + } + return res; + } +}); +}(jQuery, window, document)); + +/*! + * jquery.fancytree.table.js + * + * Render tree as table (aka 'treegrid', 'tabletree'). + * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +;(function($, window, document, undefined) { + +"use strict"; + +/* ***************************************************************************** + * Private functions and variables + */ +function _assert(cond, msg){ + msg = msg || ""; + if(!cond){ + $.error("Assertion failed " + msg); + } +} + +function insertSiblingAfter(referenceNode, newNode) { + referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); +} + +/* Show/hide all rows that are structural descendants of `parent`. */ +function setChildRowVisibility(parent, flag) { + parent.visit(function(node){ + var tr = node.tr; + // currentFlag = node.hide ? false : flag; // fix for ext-filter + if(tr){ + tr.style.display = (node.hide || !flag) ? "none" : ""; + } + if(!node.expanded){ + return "skip"; + } + }); +} + +/* Find node that is rendered in previous row. */ +function findPrevRowNode(node){ + var i, last, prev, + parent = node.parent, + siblings = parent ? parent.children : null; + + if(siblings && siblings.length > 1 && siblings[0] !== node){ + // use the lowest descendant of the preceeding sibling + i = $.inArray(node, siblings); + prev = siblings[i - 1]; + _assert(prev.tr); + // descend to lowest child (with a <tr> tag) + while(prev.children){ + last = prev.children[prev.children.length - 1]; + if(!last.tr){ + break; + } + prev = last; + } + }else{ + // if there is no preceding sibling, use the direct parent + prev = parent; + } + return prev; +} + + +$.ui.fancytree.registerExtension({ + name: "table", + version: "0.2.1", + // Default options for this extension. + options: { + checkboxColumnIdx: null, // render the checkboxes into the this column index (default: nodeColumnIdx) + customStatus: false, // true: generate renderColumns events for status nodes + indentation: 16, // indent every node level by 16px + nodeColumnIdx: 0 // render node expander, icon, and title to this column (default: #0) + }, + // Overide virtual methods for this extension. + // `this` : is this extension object + // `this._super`: the virtual function that was overriden (member of prev. extension or Fancytree) + treeInit: function(ctx){ + var i, $row, tdRole, + tree = ctx.tree, + $table = tree.widget.element; + + $table.addClass("fancytree-container fancytree-ext-table"); + tree.tbody = $table.find("> tbody")[0]; + tree.columnCount = $("thead >tr >th", $table).length; + $(tree.tbody).empty(); + + tree.rowFragment = document.createDocumentFragment(); + $row = $("<tr />"); + tdRole = ""; + if(ctx.options.aria){ + $row.attr("role", "row"); + tdRole = " role='gridcell'"; + } + for(i=0; i<tree.columnCount; i++) { + if(ctx.options.table.nodeColumnIdx === i){ + $row.append("<td" + tdRole + "><span class='fancytree-node' /></td>"); + }else{ + $row.append("<td" + tdRole + " />"); + } + } + tree.rowFragment.appendChild($row.get(0)); + + // Make sure that status classes are set on the node's <tr> elements + tree.statusClassPropName = "tr"; + tree.ariaPropName = "tr"; + this.nodeContainerAttrName = "tr"; + + this._superApply(arguments); + + // standard Fancytree created a root UL + $(tree.rootNode.ul).remove(); + tree.rootNode.ul = null; + tree.$container = $table; + // Add container to the TAB chain + this.$container.attr("tabindex", this.options.tabbable ? "0" : "-1"); + if(this.options.aria){ + tree.$container + .attr("role", "treegrid") + .attr("aria-readonly", true); + } + }, + /* Called by nodeRender to sync node order with tag order.*/ +// nodeFixOrder: function(ctx) { +// }, + nodeRemoveChildMarkup: function(ctx) { + var node = ctx.node; +// node.debug("nodeRemoveChildMarkup()"); + node.visit(function(n){ + if(n.tr){ + $(n.tr).remove(); + n.tr = null; + } + }); + }, + nodeRemoveMarkup: function(ctx) { + var node = ctx.node; +// node.debug("nodeRemoveMarkup()"); + if(node.tr){ + $(node.tr).remove(); + node.tr = null; + } + this.nodeRemoveChildMarkup(ctx); + }, + /* Override standard render. */ + nodeRender: function(ctx, force, deep, collapsed, _recursive) { + var children, firstTr, i, l, newRow, prevNode, prevTr, subCtx, + tree = ctx.tree, + node = ctx.node, + opts = ctx.options, + isRootNode = !node.parent; + + if( !_recursive ){ + ctx.hasCollapsedParents = node.parent && !node.parent.expanded; + } + // $.ui.fancytree.debug("*** nodeRender " + node + ", isRoot=" + isRootNode, "tr=" + node.tr, "hcp=" + ctx.hasCollapsedParents, "parent.tr=" + (node.parent && node.parent.tr)); + if( !isRootNode ){ + if(!node.tr){ + if( ctx.hasCollapsedParents /*&& !node.parent.tr*/ ) { + // #166: we assume that the parent will be (recursively) rendered + // later anyway. + node.debug("nodeRender ignored due to unrendered parent"); + return; + } + // Create new <tr> after previous row + newRow = tree.rowFragment.firstChild.cloneNode(true); + prevNode = findPrevRowNode(node); + // $.ui.fancytree.debug("*** nodeRender " + node + ": prev: " + prevNode.key); + _assert(prevNode); + if(collapsed === true && _recursive){ + // hide all child rows, so we can use an animation to show it later + newRow.style.display = "none"; + }else if(deep && ctx.hasCollapsedParents){ + // also hide this row if deep === true but any parent is collapsed + newRow.style.display = "none"; +// newRow.style.color = "red"; + } + if(!prevNode.tr){ + _assert(!prevNode.parent, "prev. row must have a tr, or is system root"); + tree.tbody.appendChild(newRow); + }else{ + insertSiblingAfter(prevNode.tr, newRow); + } + node.tr = newRow; + if( node.key && opts.generateIds ){ + node.tr.id = opts.idPrefix + node.key; + } + node.tr.ftnode = node; + if(opts.aria){ + // TODO: why doesn't this work: +// node.li.role = "treeitem"; + $(node.tr).attr("aria-labelledby", "ftal_" + node.key); + } + node.span = $("span.fancytree-node", node.tr).get(0); + // Set icon, link, and title (normally this is only required on initial render) + this.nodeRenderTitle(ctx); + // Allow tweaking, binding, after node was created for the first time +// tree._triggerNodeEvent("createNode", ctx); + if ( opts.createNode ){ + opts.createNode.call(tree, {type: "createNode"}, ctx); + } + } else { + if( force ) { + // Set icon, link, and title (normally this is only required on initial render) + this.nodeRenderTitle(ctx); // triggers renderColumns() + } else { + // Update element classes according to node state + this.nodeRenderStatus(ctx); + } + } + } + // Allow tweaking after node state was rendered +// tree._triggerNodeEvent("renderNode", ctx); + if ( opts.renderNode ){ + opts.renderNode.call(tree, {type: "renderNode"}, ctx); + } + // Visit child nodes + // Add child markup + children = node.children; + if(children && (isRootNode || deep || node.expanded)){ + for(i=0, l=children.length; i<l; i++) { + subCtx = $.extend({}, ctx, {node: children[i]}); + subCtx.hasCollapsedParents = subCtx.hasCollapsedParents || !node.expanded; + this.nodeRender(subCtx, force, deep, collapsed, true); + } + } + // Make sure, that <tr> order matches node.children order. + if(children && !_recursive){ // we only have to do it once, for the root branch + prevTr = node.tr || null; + firstTr = tree.tbody.firstChild; + // Iterate over all descendants + node.visit(function(n){ + if(n.tr){ + if(!n.parent.expanded && n.tr.style.display !== "none"){ + // fix after a node was dropped over a collapsed + n.tr.style.display = "none"; + setChildRowVisibility(n, false); + } + if(n.tr.previousSibling !== prevTr){ + node.debug("_fixOrder: mismatch at node: " + n); + var nextTr = prevTr ? prevTr.nextSibling : firstTr; + tree.tbody.insertBefore(n.tr, nextTr); + } + prevTr = n.tr; + } + }); + } + // Update element classes according to node state + // if(!isRootNode){ + // this.nodeRenderStatus(ctx); + // } + }, + nodeRenderTitle: function(ctx, title) { + var $cb, + node = ctx.node, + opts = ctx.options; + + this._superApply(arguments); + // Move checkbox to custom column + if(opts.checkbox && opts.table.checkboxColumnIdx != null ){ + $cb = $("span.fancytree-checkbox", node.span).detach(); + $(node.tr).find("td").eq(+opts.table.checkboxColumnIdx).html($cb); + } + // Update element classes according to node state + if( ! node.isRoot() ){ + this.nodeRenderStatus(ctx); + } + if( !opts.table.customStatus && node.isStatusNode() ) { + // default rendering for status node: leave other cells empty + } else if ( opts.renderColumns ) { + // Let user code write column content + opts.renderColumns.call(ctx.tree, {type: "renderColumns"}, ctx); + } + }, + nodeRenderStatus: function(ctx) { + var indent, + node = ctx.node, + opts = ctx.options; + + this._superApply(arguments); + + $(node.tr).removeClass("fancytree-node"); + // indent + indent = (node.getLevel() - 1) * opts.table.indentation; + $(node.span).css({marginLeft: indent + "px"}); + }, + /* Expand node, return Deferred.promise. */ + nodeSetExpanded: function(ctx, flag, opts) { + var dfd = new $.Deferred(), + subOpts = $.extend({}, opts, {noEvents: true, noAnimation: true}); + + opts = opts || {}; + + function _afterExpand(ok) { + flag = (flag !== false); + setChildRowVisibility(ctx.node, flag); + if( ok ) { + if( flag && ctx.options.autoScroll && !opts.noAnimation && ctx.node.hasChildren() ) { + // Scroll down to last child, but keep current node visible + ctx.node.getLastChild().scrollIntoView(true, {topNode: ctx.node}).always(function(){ + if( !opts.noEvents ) { + ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx); + } + dfd.resolveWith(ctx.node); + }); + } else { + if( !opts.noEvents ) { + ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx); + } + dfd.resolveWith(ctx.node); + } + } else { + if( !opts.noEvents ) { + ctx.tree._triggerNodeEvent(flag ? "expand" : "collapse", ctx); + } + dfd.rejectWith(ctx.node); + } + } + // Call base-expand with disabled events and animation + this._super(ctx, flag, subOpts).done(function () { + _afterExpand(true); + }).fail(function () { + _afterExpand(false); + }); + return dfd.promise(); + }, + nodeSetStatus: function(ctx, status, message, details) { + if(status === "ok"){ + var node = ctx.node, + firstChild = ( node.children ? node.children[0] : null ); + if ( firstChild && firstChild.isStatusNode() ) { + $(firstChild.tr).remove(); + } + } + return this._superApply(arguments); + }, + treeClear: function(ctx) { + this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode)); + return this._superApply(arguments); + } + /*, + treeSetFocus: function(ctx, flag) { +// alert("treeSetFocus" + ctx.tree.$container); + ctx.tree.$container.focus(); + $.ui.fancytree.focusTree = ctx.tree; + }*/ +}); +}(jQuery, window, document)); + +/*! + * jquery.fancytree.themeroller.js + * + * Enable jQuery UI ThemeRoller styles. + * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) + * + * @see http://jqueryui.com/themeroller/ + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +;(function($, window, document, undefined) { + +"use strict"; + +/******************************************************************************* + * Extension code + */ +$.ui.fancytree.registerExtension({ + name: "themeroller", + version: "0.0.1", + // Default options for this extension. + options: { + activeClass: "ui-state-active", + foccusClass: "ui-state-focus", + hoverClass: "ui-state-hover", + selectedClass: "ui-state-highlight" + }, + + treeInit: function(ctx){ + this._superApply(arguments); + var $el = ctx.widget.element; + + if($el[0].nodeName === "TABLE"){ + $el.addClass("ui-widget ui-corner-all"); + $el.find(">thead tr").addClass("ui-widget-header"); + $el.find(">tbody").addClass("ui-widget-conent"); + }else{ + $el.addClass("ui-widget ui-widget-content ui-corner-all"); + } + + $el.delegate(".fancytree-node", "mouseenter mouseleave", function(event){ + var node = $.ui.fancytree.getNode(event.target), + flag = (event.type === "mouseenter"); + node.debug("hover: " + flag); + $(node.span).toggleClass("ui-state-hover ui-corner-all", flag); + }); + }, + treeDestroy: function(ctx){ + this._superApply(arguments); + ctx.widget.element.removeClass("ui-widget ui-widget-content ui-corner-all"); + }, + nodeRenderStatus: function(ctx){ + var node = ctx.node, + $el = $(node.span); + this._superApply(arguments); +/* + .ui-state-highlight: Class to be applied to highlighted or selected elements. Applies "highlight" container styles to an element and its child text, links, and icons. + .ui-state-error: Class to be applied to error messaging container elements. Applies "error" container styles to an element and its child text, links, and icons. + .ui-state-error-text: An additional class that applies just the error text color without background. Can be used on form labels for instance. Also applies error icon color to child icons. + + .ui-state-default: Class to be applied to clickable button-like elements. Applies "clickable default" container styles to an element and its child text, links, and icons. + .ui-state-hover: Class to be applied on mouseover to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons. + .ui-state-focus: Class to be applied on keyboard focus to clickable button-like elements. Applies "clickable hover" container styles to an element and its child text, links, and icons. + .ui-state-active: Class to be applied on mousedown to clickable button-like elements. Applies "clickable active" container styles to an element and its child text, links, and icons. +*/ + $el.toggleClass("ui-state-active", node.isActive()); + $el.toggleClass("ui-state-focus", node.hasFocus()); + $el.toggleClass("ui-state-highlight", node.isSelected()); +// node.debug("ext-themeroller.nodeRenderStatus: ", node.span.className); + } +}); +}(jQuery, window, document)); + +/*! + * jquery.fancytree.wide.js + * Support for 100% wide selection bars. + * (Extension module for jquery.fancytree.js: https://github.com/mar10/fancytree/) + * + * Copyright (c) 2008-2015, Martin Wendt (http://wwWendt.de) + * + * Released under the MIT license + * https://github.com/mar10/fancytree/wiki/LicenseInfo + * + * @version 2.8.1 + * @date 2015-03-01T20:28 + */ + +;(function($, window, document, undefined) { + +"use strict"; + +var reNumUnit = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/; // split "1.5em" to ["1.5", "em"] + +/******************************************************************************* + * Private functions and variables + */ +// var _assert = $.ui.fancytree.assert; + +/* Calculate inner width without scrollbar */ +// function realInnerWidth($el) { +// // http://blog.jquery.com/2012/08/16/jquery-1-8-box-sizing-width-csswidth-and-outerwidth/ +// // inst.contWidth = parseFloat(this.$container.css("width"), 10); +// // 'Client width without scrollbar' - 'padding' +// return $el[0].clientWidth - ($el.innerWidth() - parseFloat($el.css("width"), 10)); +// } + +/* Create a global embedded CSS style for the tree. */ +function defineHeadStyleElement(id, cssText) { + id = "fancytree-style-" + id; + var $headStyle = $("#" + id); + + if( !cssText ) { + $headStyle.remove(); + return null; + } + if( !$headStyle.length ) { + $headStyle = $("<style />") + .attr("id", id) + .addClass("fancytree-style") + .prop("type", "text/css") + .appendTo("head"); + } + try { + $headStyle.html(cssText); + } catch ( e ) { + // fix for IE 6-8 + $headStyle[0].styleSheet.cssText = cssText; + } + return $headStyle; +} + +/* Calculate the CSS rules that indent title spans. */ +function renderLevelCss(containerId, depth, levelOfs, lineOfs, measureUnit) { + var i, + prefix = "#" + containerId + " span.fancytree-level-", + rules = []; + + for(i = 0; i < depth; i++) { + rules.push(prefix + (i + 1) + " span.fancytree-title { padding-left: " + + (i * levelOfs + lineOfs) + measureUnit + "; }"); + } + // Some UI animations wrap the UL inside a DIV and set position:relative on both. + // This breaks the left:0 and padding-left:nn settings of the title + rules.push("#" + containerId + + " div.ui-effects-wrapper ul li span.fancytree-title " + + "{ padding-left: 3px; position: static; width: auto; }"); + return rules.join("\n"); +} + + +// /** +// * [ext-wide] Recalculate the width of the selection bar after the tree container +// * was resized.<br> +// * May be called explicitly on container resize, since there is no resize event +// * for DIV tags. +// * +// * @alias Fancytree#wideUpdate +// * @requires jquery.fancytree.wide.js +// */ +// $.ui.fancytree._FancytreeClass.prototype.wideUpdate = function(){ +// var inst = this.ext.wide, +// prevCw = inst.contWidth, +// prevLo = inst.lineOfs; + +// inst.contWidth = realInnerWidth(this.$container); +// // Each title is precceeded by 2 or 3 icons (16px + 3 margin) +// // + 1px title border and 3px title padding +// // TODO: use code from treeInit() below +// inst.lineOfs = (this.options.checkbox ? 3 : 2) * 19; +// if( prevCw !== inst.contWidth || prevLo !== inst.lineOfs ) { +// this.debug("wideUpdate: " + inst.contWidth); +// this.visit(function(node){ +// node.tree._callHook("nodeRenderTitle", node); +// }); +// } +// }; + +/******************************************************************************* + * Extension code + */ +$.ui.fancytree.registerExtension({ + name: "wide", + version: "0.0.3", + // Default options for this extension. + options: { + iconWidth: null, // Adjust this if @fancy-icon-width != "16px" + iconSpacing: null, // Adjust this if @fancy-icon-spacing != "3px" + levelOfs: null // Adjust this if ul padding != "16px" + }, + + treeCreate: function(ctx){ + this._superApply(arguments); + this.$container.addClass("fancytree-ext-wide"); + + var containerId, cssText, iconSpacingUnit, iconWidthUnit, levelOfsUnit, + instOpts = ctx.options.wide, + // css sniffing + $dummyLI = $("<li id='fancytreeTemp'><span class='fancytree-node'><span class='fancytree-icon' /><span class='fancytree-title' /></span><ul />") + .appendTo(ctx.tree.$container), + $dummyIcon = $dummyLI.find(".fancytree-icon"), + $dummyUL = $dummyLI.find("ul"), + // $dummyTitle = $dummyLI.find(".fancytree-title"), + iconSpacing = instOpts.iconSpacing || $dummyIcon.css("margin-left"), + iconWidth = instOpts.iconWidth || $dummyIcon.css("width"), + levelOfs = instOpts.levelOfs || $dummyUL.css("padding-left"); + + $dummyLI.remove(); + + iconSpacingUnit = iconSpacing.match(reNumUnit)[2]; + iconSpacing = parseFloat(iconSpacing, 10); + iconWidthUnit = iconWidth.match(reNumUnit)[2]; + iconWidth = parseFloat(iconWidth, 10); + levelOfsUnit = levelOfs.match(reNumUnit)[2]; + if( iconSpacingUnit !== iconWidthUnit || levelOfsUnit !== iconWidthUnit ) { + $.error("iconWidth, iconSpacing, and levelOfs must have the same css measure unit"); + } + this._local.measureUnit = iconWidthUnit; + this._local.levelOfs = parseFloat(levelOfs); + this._local.lineOfs = (ctx.options.checkbox ? 3 : 2) * (iconWidth + iconSpacing) + iconSpacing; + this._local.maxDepth = 10; + + // Get/Set a unique Id on the container (if not already exists) + containerId = this.$container.uniqueId().attr("id"); + // Generated css rules for some levels (extended on demand) + cssText = renderLevelCss(containerId, this._local.maxDepth, + this._local.levelOfs, this._local.lineOfs, this._local.measureUnit); + defineHeadStyleElement(containerId, cssText); + }, + treeDestroy: function(ctx){ + // Remove generated css rules + defineHeadStyleElement(this.$container.attr("id"), null); + return this._superApply(arguments); + }, + nodeRenderStatus: function(ctx) { + var containerId, cssText, res, + node = ctx.node, + level = node.getLevel(); + + res = this._superApply(arguments); + // Generate some more level-n rules if required + if( level > this._local.maxDepth ) { + containerId = this.$container.attr("id"); + this._local.maxDepth *= 2; + node.debug("Define global ext-wide css up to level " + this._local.maxDepth); + cssText = renderLevelCss(containerId, this._local.maxDepth, + this._local.levelOfs, this._local.lineOfs, this._local.measureUnit); + defineHeadStyleElement(containerId, cssText); + } + // Add level-n class to apply indentation padding. + // (Setting element style would not work, since it cannot easily be + // overriden while animations run) + $(node.span).addClass("fancytree-level-" + level); + return res; + } +}); +}(jQuery, window, document)); diff --git a/src/core/classes/org/glizycms/js/jquery/fancytree/jquery.fancytree-all.min.js b/src/core/classes/org/glizycms/js/jquery/fancytree/jquery.fancytree-all.min.js new file mode 100644 index 0000000..374a1c5 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/fancytree/jquery.fancytree-all.min.js @@ -0,0 +1,44 @@ +/*! jQuery Fancytree Plugin - 2.8.1 - 2015-03-01T20:28 + * https://github.com/mar10/fancytree + * Copyright (c) 2015 Martin Wendt; Licensed MIT */ +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + define( [ "jquery" ], factory ); + } else { + factory( jQuery ); + } +}(function( $ ) { + +!function(a,b,c,d){"use strict";function e(b,c){b||(c=c?": "+c:"",a.error("Fancytree assertion failed"+c))}function f(a,c){var d,e,f=b.console?b.console[a]:null;if(f)try{f.apply(b.console,c)}catch(g){for(e="",d=0;d<c.length;d++)e+=c[d];f(e)}}function g(a){return!(!a.tree||a.statusNodeType===d)}function h(b){var c,d,e,f=a.map(a.trim(b).split("."),function(a){return parseInt(a,10)}),g=a.map(Array.prototype.slice.call(arguments,1),function(a){return parseInt(a,10)});for(c=0;c<g.length;c++)if(d=f[c]||0,e=g[c]||0,d!==e)return d>e;return!0}function i(a,b,c,d,e){var f=function(){var c=b[a],f=d[a],g=b.ext[e],h=function(){return c.apply(b,arguments)},i=function(a){return c.apply(b,a)};return function(){var a=b._local,c=b._super,d=b._superApply;try{return b._local=g,b._super=h,b._superApply=i,f.apply(b,arguments)}finally{b._local=a,b._super=c,b._superApply=d}}}();return f}function j(b,c,d,e){for(var f in d)"function"==typeof d[f]?"function"==typeof b[f]?b[f]=i(f,b,c,d,e):"_"===f.charAt(0)?b.ext[e][f]=i(f,b,c,d,e):a.error("Could not override tree."+f+". Use prefix '_' to create tree."+e+"._"+f):"options"!==f&&(b.ext[e][f]=d[f])}function k(b,c){return b===d?a.Deferred(function(){this.resolve()}).promise():a.Deferred(function(){this.resolveWith(b,c)}).promise()}function l(b,c){return b===d?a.Deferred(function(){this.reject()}).promise():a.Deferred(function(){this.rejectWith(b,c)}).promise()}function m(a,b){return function(){a.resolveWith(b)}}function n(b){var c=a.extend({},b.data()),d=c.json;return delete c.fancytree,d&&(delete c.json,c=a.extend(c,d)),c}function o(a){return a=a.toLowerCase(),function(b){return b.title.toLowerCase().indexOf(a)>=0}}function p(a){var b=new RegExp("^"+a,"i");return function(a){return b.test(a.title)}}function q(b,c){var d,f,g,h;for(this.parent=b,this.tree=b.tree,this.ul=null,this.li=null,this.statusNodeType=null,this._isLoading=!1,this._error=null,this.data={},d=0,f=A.length;f>d;d++)g=A[d],this[g]=c[g];c.data&&a.extend(this.data,c.data);for(g in c)B[g]||a.isFunction(c[g])||C[g]||(this.data[g]=c[g]);null==this.key?this.tree.options.defaultKey?(this.key=this.tree.options.defaultKey(this),e(this.key,"defaultKey() must return a unique key")):this.key="_"+t._nextNodeKey++:this.key=""+this.key,c.active&&(e(null===this.tree.activeNode,"only one active node allowed"),this.tree.activeNode=this),c.selected&&(this.tree.lastSelectedNode=this),this.children=null,h=c.children,h&&h.length&&this._setChildren(h),this.tree._callHook("treeRegisterNode",this.tree,!0,this)}function r(b){this.widget=b,this.$div=b.element,this.options=b.options,this.options&&(a.isFunction(this.options.lazyload)&&!a.isFunction(this.options.lazyLoad)&&(this.options.lazyLoad=function(){return t.warn("The 'lazyload' event is deprecated since 2014-02-25. Use 'lazyLoad' (with uppercase L) instead."),b.options.lazyload.apply(this,arguments)}),a.isFunction(this.options.loaderror)&&a.error("The 'loaderror' event was renamed since 2014-07-03. Use 'loadError' (with uppercase E) instead."),this.options.fx!==d&&t.warn("The 'fx' options was replaced by 'toggleEffect' since 2014-11-30.")),this.ext={},this.data=n(this.$div),this._id=a.ui.fancytree._nextId++,this._ns=".fancytree-"+this._id,this.activeNode=null,this.focusNode=null,this._hasFocus=null,this.lastSelectedNode=null,this.systemFocusElement=null,this.lastQuicksearchTerm="",this.lastQuicksearchTime=0,this.statusClassPropName="span",this.ariaPropName="li",this.nodeContainerAttrName="li",this.$div.find(">ul.fancytree-container").remove();var c,e={tree:this};this.rootNode=new q(e,{title:"root",key:"root_"+this._id,children:null,expanded:!0}),this.rootNode.parent=null,c=a("<ul>",{"class":"ui-fancytree fancytree-container"}).appendTo(this.$div),this.$container=c,this.rootNode.ul=c[0],null==this.options.debugLevel&&(this.options.debugLevel=t.debugLevel),this.$container.attr("tabindex",this.options.tabbable?"0":"-1"),this.options.aria&&this.$container.attr("role","tree").attr("aria-multiselectable",!0)}if(a.ui&&a.ui.fancytree)return void a.ui.fancytree.warn("Fancytree: ignored duplicate include");e(a.ui,"Fancytree requires jQuery UI (http://jqueryui.com)");var s,t=null,u={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;"},v={16:!0,17:!0,18:!0},w={8:"backspace",9:"tab",10:"return",13:"return",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",59:";",61:"=",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},x={0:"",1:"left",2:"middle",3:"right"},y="active expanded focus folder hideCheckbox lazy selected unselectable".split(" "),z={},A="expanded extraClasses folder hideCheckbox key lazy refKey selected title tooltip unselectable".split(" "),B={},C={active:!0,children:!0,data:!0,focus:!0};for(s=0;s<y.length;s++)z[y[s]]=!0;for(s=0;s<A.length;s++)B[A[s]]=!0;q.prototype={_findDirectChild:function(a){var b,c,d=this.children;if(d)if("string"==typeof a){for(b=0,c=d.length;c>b;b++)if(d[b].key===a)return d[b]}else{if("number"==typeof a)return this.children[a];if(a.parent===this)return a}return null},_setChildren:function(a){e(a&&(!this.children||0===this.children.length),"only init supported"),this.children=[];for(var b=0,c=a.length;c>b;b++)this.children.push(new q(this,a[b]))},addChildren:function(b,c){var d,f,g,h=null,i=[];for(a.isPlainObject(b)&&(b=[b]),this.children||(this.children=[]),d=0,f=b.length;f>d;d++)i.push(new q(this,b[d]));return h=i[0],null==c?this.children=this.children.concat(i):(c=this._findDirectChild(c),g=a.inArray(c,this.children),e(g>=0,"insertBefore must be an existing child"),this.children.splice.apply(this.children,[g,0].concat(i))),(!this.parent||this.parent.ul||this.tr)&&this.render(),3===this.tree.options.selectMode&&this.fixSelection3FromEndNodes(),h},addNode:function(a,b){switch((b===d||"over"===b)&&(b="child"),b){case"after":return this.getParent().addChildren(a,this.getNextSibling());case"before":return this.getParent().addChildren(a,this);case"firstChild":var c=this.children?this.children[0]:null;return this.addChildren(a,c);case"child":case"over":return this.addChildren(a)}e(!1,"Invalid mode: "+b)},appendSibling:function(a){return this.addNode(a,"after")},applyPatch:function(b){if(null===b)return this.remove(),k(this);var c,d,e,f={children:!0,expanded:!0,parent:!0};for(c in b)e=b[c],f[c]||a.isFunction(e)||(B[c]?this[c]=e:this.data[c]=e);return b.hasOwnProperty("children")&&(this.removeChildren(),b.children&&this._setChildren(b.children)),this.isVisible()&&(this.renderTitle(),this.renderStatus()),d=b.hasOwnProperty("expanded")?this.setExpanded(b.expanded):k(this)},collapseSiblings:function(){return this.tree._callHook("nodeCollapseSiblings",this)},copyTo:function(a,b,c){return a.addNode(this.toDict(!0,c),b)},countChildren:function(a){var b,c,d,e=this.children;if(!e)return 0;if(d=e.length,a!==!1)for(b=0,c=d;c>b;b++)d+=e[b].countChildren();return d},debug:function(){this.tree.options.debugLevel>=2&&(Array.prototype.unshift.call(arguments,this.toString()),f("log",arguments))},discard:function(){return this.warn("FancytreeNode.discard() is deprecated since 2014-02-16. Use .resetLazy() instead."),this.resetLazy()},findAll:function(b){b=a.isFunction(b)?b:o(b);var c=[];return this.visit(function(a){b(a)&&c.push(a)}),c},findFirst:function(b){b=a.isFunction(b)?b:o(b);var c=null;return this.visit(function(a){return b(a)?(c=a,!1):void 0}),c},_changeSelectStatusAttrs:function(a){var b=!1;switch(a){case!1:b=this.selected||this.partsel,this.selected=!1,this.partsel=!1;break;case!0:b=!this.selected||!this.partsel,this.selected=!0,this.partsel=!0;break;case d:b=this.selected||!this.partsel,this.selected=!1,this.partsel=!0;break;default:e(!1,"invalid state: "+a)}return b&&this.renderStatus(),b},fixSelection3AfterClick:function(){var a=this.isSelected();this.visit(function(b){b._changeSelectStatusAttrs(a)}),this.fixSelection3FromEndNodes()},fixSelection3FromEndNodes:function(){function a(b){var c,e,f,g,h,i,j,k=b.children;if(k&&k.length){for(i=!0,j=!1,c=0,e=k.length;e>c;c++)f=k[c],g=a(f),g!==!1&&(j=!0),g!==!0&&(i=!1);h=i?!0:j?d:!1}else h=!!b.selected;return b._changeSelectStatusAttrs(h),h}e(3===this.tree.options.selectMode,"expected selectMode 3"),a(this),this.visitParents(function(a){var b,c,e,f,g=a.children,h=!0,i=!1;for(b=0,c=g.length;c>b;b++)e=g[b],(e.selected||e.partsel)&&(i=!0),e.unselectable||e.selected||(h=!1);f=h?!0:i?d:!1,a._changeSelectStatusAttrs(f)})},fromDict:function(b){for(var c in b)B[c]?this[c]=b[c]:"data"===c?a.extend(this.data,b.data):a.isFunction(b[c])||C[c]||(this.data[c]=b[c]);b.children&&(this.removeChildren(),this.addChildren(b.children)),this.renderTitle()},getChildren:function(){return this.hasChildren()===d?d:this.children},getFirstChild:function(){return this.children?this.children[0]:null},getIndex:function(){return a.inArray(this,this.parent.children)},getIndexHier:function(b){b=b||".";var c=[];return a.each(this.getParentList(!1,!0),function(a,b){c.push(b.getIndex()+1)}),c.join(b)},getKeyPath:function(a){var b=[],c=this.tree.options.keyPathSeparator;return this.visitParents(function(a){a.parent&&b.unshift(a.key)},!a),c+b.join(c)},getLastChild:function(){return this.children?this.children[this.children.length-1]:null},getLevel:function(){for(var a=0,b=this.parent;b;)a++,b=b.parent;return a},getNextSibling:function(){if(this.parent){var a,b,c=this.parent.children;for(a=0,b=c.length-1;b>a;a++)if(c[a]===this)return c[a+1]}return null},getParent:function(){return this.parent},getParentList:function(a,b){for(var c=[],d=b?this:this.parent;d;)(a||d.parent)&&c.unshift(d),d=d.parent;return c},getPrevSibling:function(){if(this.parent){var a,b,c=this.parent.children;for(a=1,b=c.length;b>a;a++)if(c[a]===this)return c[a-1]}return null},hasChildren:function(){return this.lazy?null==this.children?d:0===this.children.length?!1:1===this.children.length&&this.children[0].isStatusNode()?d:!0:!(!this.children||!this.children.length)},hasFocus:function(){return this.tree.hasFocus()&&this.tree.focusNode===this},info:function(){this.tree.options.debugLevel>=1&&(Array.prototype.unshift.call(arguments,this.toString()),f("info",arguments))},isActive:function(){return this.tree.activeNode===this},isChildOf:function(a){return this.parent&&this.parent===a},isDescendantOf:function(a){if(!a||a.tree!==this.tree)return!1;for(var b=this.parent;b;){if(b===a)return!0;b=b.parent}return!1},isExpanded:function(){return!!this.expanded},isFirstSibling:function(){var a=this.parent;return!a||a.children[0]===this},isFolder:function(){return!!this.folder},isLastSibling:function(){var a=this.parent;return!a||a.children[a.children.length-1]===this},isLazy:function(){return!!this.lazy},isLoaded:function(){return!this.lazy||this.hasChildren()!==d},isLoading:function(){return!!this._isLoading},isRoot:function(){return this.isRootNode()},isRootNode:function(){return this.tree.rootNode===this},isSelected:function(){return!!this.selected},isStatusNode:function(){return!!this.statusNodeType},isTopLevel:function(){return this.tree.rootNode===this.parent},isUndefined:function(){return this.hasChildren()===d},isVisible:function(){var a,b,c=this.getParentList(!1,!1);for(a=0,b=c.length;b>a;a++)if(!c[a].expanded)return!1;return!0},lazyLoad:function(a){return this.warn("FancytreeNode.lazyLoad() is deprecated since 2014-02-16. Use .load() instead."),this.load(a)},load:function(a){var b,c,d=this;return e(this.isLazy(),"load() requires a lazy node"),a||this.isUndefined()?(this.isLoaded()&&this.resetLazy(),c=this.tree._triggerNodeEvent("lazyLoad",this),c===!1?k(this):(e("boolean"!=typeof c,"lazyLoad event must return source in data.result"),b=this.tree._callHook("nodeLoadChildren",this,c),this.expanded&&b.always(function(){d.render()}),b)):k(this)},makeVisible:function(b){var c,d=this,e=[],f=new a.Deferred,g=this.getParentList(!1,!1),h=g.length,i=!(b&&b.noAnimation===!0),j=!(b&&b.scrollIntoView===!1);for(c=h-1;c>=0;c--)e.push(g[c].setExpanded(!0,b));return a.when.apply(a,e).done(function(){j?d.scrollIntoView(i).done(function(){f.resolve()}):f.resolve()}),f.promise()},moveTo:function(b,c,f){(c===d||"over"===c)&&(c="child");var g,h=this.parent,i="child"===c?b:b.parent;if(this!==b){if(!this.parent)throw"Cannot move system root";if(i.isDescendantOf(this))throw"Cannot move a node to its own descendant";if(1===this.parent.children.length){if(this.parent===i)return;this.parent.children=this.parent.lazy?[]:null,this.parent.expanded=!1}else g=a.inArray(this,this.parent.children),e(g>=0),this.parent.children.splice(g,1);if(this.parent=i,i.hasChildren())switch(c){case"child":i.children.push(this);break;case"before":g=a.inArray(b,i.children),e(g>=0),i.children.splice(g,0,this);break;case"after":g=a.inArray(b,i.children),e(g>=0),i.children.splice(g+1,0,this);break;default:throw"Invalid mode "+c}else i.children=[this];f&&b.visit(f,!0),this.tree!==b.tree&&(this.warn("Cross-tree moveTo is experimantal!"),this.visit(function(a){a.tree=b.tree},!0)),h.isDescendantOf(i)||h.render(),i.isDescendantOf(h)||i===h||i.render()}},navigate:function(b,c){function d(d){if(d){try{d.makeVisible()}catch(e){}return a(d.span).is(":visible")?c===!1?d.setFocus():d.setActive():(d.debug("Navigate: skipping hidden node"),void d.navigate(b,c))}}var e,f,g=!0,h=a.ui.keyCode,i=null;switch(b){case h.BACKSPACE:this.parent&&this.parent.parent&&d(this.parent);break;case h.LEFT:this.expanded?(this.setExpanded(!1),d(this)):this.parent&&this.parent.parent&&d(this.parent);break;case h.RIGHT:this.expanded||!this.children&&!this.lazy?this.children&&this.children.length&&d(this.children[0]):(this.setExpanded(),d(this));break;case h.UP:for(i=this.getPrevSibling();i&&!a(i.span).is(":visible");)i=i.getPrevSibling();for(;i&&i.expanded&&i.children&&i.children.length;)i=i.children[i.children.length-1];!i&&this.parent&&this.parent.parent&&(i=this.parent),d(i);break;case h.DOWN:if(this.expanded&&this.children&&this.children.length)i=this.children[0];else for(f=this.getParentList(!1,!0),e=f.length-1;e>=0;e--){for(i=f[e].getNextSibling();i&&!a(i.span).is(":visible");)i=i.getNextSibling();if(i)break}d(i);break;default:g=!1}},remove:function(){return this.parent.removeChild(this)},removeChild:function(a){return this.tree._callHook("nodeRemoveChild",this,a)},removeChildren:function(){return this.tree._callHook("nodeRemoveChildren",this)},render:function(a,b){return this.tree._callHook("nodeRender",this,a,b)},renderTitle:function(){return this.tree._callHook("nodeRenderTitle",this)},renderStatus:function(){return this.tree._callHook("nodeRenderStatus",this)},resetLazy:function(){this.removeChildren(),this.expanded=!1,this.lazy=!0,this.children=d,this.renderStatus()},scheduleAction:function(a,b){this.tree.timer&&clearTimeout(this.tree.timer),this.tree.timer=null;var c=this;switch(a){case"cancel":break;case"expand":this.tree.timer=setTimeout(function(){c.tree.debug("setTimeout: trigger expand"),c.setExpanded(!0)},b);break;case"activate":this.tree.timer=setTimeout(function(){c.tree.debug("setTimeout: trigger activate"),c.setActive(!0)},b);break;default:throw"Invalid mode "+a}},scrollIntoView:function(f,h){h!==d&&g(h)&&(this.warn("scrollIntoView() with 'topNode' option is deprecated since 2014-05-08. Use 'options.topNode' instead."),h={topNode:h});var i,j,l,m,n=a.extend({effects:f===!0?{duration:200,queue:!1}:f,scrollOfs:this.tree.options.scrollOfs,scrollParent:this.tree.options.scrollParent||this.tree.$container,topNode:null},h),o=new a.Deferred,p=this,q=a(this.span).height(),r=a(n.scrollParent),s=n.scrollOfs.top||0,t=n.scrollOfs.bottom||0,u=r.height(),v=r.scrollTop(),w=r,x=r[0]===b,y=n.topNode||null,z=null;return a(this.span).is(":visible")?(x?(j=a(this.span).offset().top,i=y&&y.span?a(y.span).offset().top:0,w=a("html,body")):(e(r[0]!==c&&r[0]!==c.body,"scrollParent should be an simple element or `window`, not document or body."),m=r.offset().top,j=a(this.span).offset().top-m+v,i=y?a(y.span).offset().top-m+v:0,l=Math.max(0,r.innerHeight()-r[0].clientHeight),u-=l),v+s>j?z=j-s:j+q>v+u-t&&(z=j+q-u+t,y&&(e(y.isRoot()||a(y.span).is(":visible"),"topNode must be visible"),z>i&&(z=i-s))),null!==z?n.effects?(n.effects.complete=function(){o.resolveWith(p)},w.stop(!0).animate({scrollTop:z},n.effects)):(w[0].scrollTop=z,o.resolveWith(this)):o.resolveWith(this),o.promise()):(this.warn("scrollIntoView(): node is invisible."),k())},setActive:function(a,b){return this.tree._callHook("nodeSetActive",this,a,b)},setExpanded:function(a,b){return this.tree._callHook("nodeSetExpanded",this,a,b)},setFocus:function(a){return this.tree._callHook("nodeSetFocus",this,a)},setSelected:function(a){return this.tree._callHook("nodeSetSelected",this,a)},setStatus:function(a,b,c){return this.tree._callHook("nodeSetStatus",this,a,b,c)},setTitle:function(a){this.title=a,this.renderTitle()},sortChildren:function(a,b){var c,d,e=this.children;if(e){if(a=a||function(a,b){var c=a.title.toLowerCase(),d=b.title.toLowerCase();return c===d?0:c>d?1:-1},e.sort(a),b)for(c=0,d=e.length;d>c;c++)e[c].children&&e[c].sortChildren(a,"$norender$");"$norender$"!==b&&this.render()}},toDict:function(b,c){var d,e,f,g={},h=this;if(a.each(A,function(a,b){(h[b]||h[b]===!1)&&(g[b]=h[b])}),a.isEmptyObject(this.data)||(g.data=a.extend({},this.data),a.isEmptyObject(g.data)&&delete g.data),c&&c(g),b&&this.hasChildren())for(g.children=[],d=0,e=this.children.length;e>d;d++)f=this.children[d],f.isStatusNode()||g.children.push(f.toDict(!0,c));return g},toggleExpanded:function(){return this.tree._callHook("nodeToggleExpanded",this)},toggleSelected:function(){return this.tree._callHook("nodeToggleSelected",this)},toString:function(){return"<FancytreeNode(#"+this.key+", '"+this.title+"')>"},visit:function(a,b){var c,d,e=!0,f=this.children;if(b===!0&&(e=a(this),e===!1||"skip"===e))return e;if(f)for(c=0,d=f.length;d>c&&(e=f[c].visit(a,!0),e!==!1);c++);return e},visitAndLoad:function(b,c,d){var e,f,g,h=this;return b&&c===!0&&(f=b(h),f===!1||"skip"===f)?d?f:k():h.children||h.lazy?(e=new a.Deferred,g=[],h.load().done(function(){for(var c=0,d=h.children.length;d>c;c++){if(f=h.children[c].visitAndLoad(b,!0,!0),f===!1){e.reject();break}"skip"!==f&&g.push(f)}a.when.apply(this,g).then(function(){e.resolve()})}),e.promise()):k()},visitParents:function(a,b){if(b&&a(this)===!1)return!1;for(var c=this.parent;c;){if(a(c)===!1)return!1;c=c.parent}return!0},warn:function(){Array.prototype.unshift.call(arguments,this.toString()),f("warn",arguments)}},r.prototype={_makeHookContext:function(b,c,e){var f,g;return b.node!==d?(c&&b.originalEvent!==c&&a.error("invalid args"),f=b):b.tree?(g=b.tree,f={node:b,tree:g,widget:g.widget,options:g.widget.options,originalEvent:c}):b.widget?f={node:null,tree:b,widget:b.widget,options:b.widget.options,originalEvent:c}:a.error("invalid args"),e&&a.extend(f,e),f},_callHook:function(b,c){var d=this._makeHookContext(c),e=this[b],f=Array.prototype.slice.call(arguments,2);return a.isFunction(e)||a.error("_callHook('"+b+"') is not a function"),f.unshift(d),e.apply(this,f)},_requireExtension:function(b,c,d,f){d=!!d;var g=this._local.name,h=this.options.extensions,i=a.inArray(b,h)<a.inArray(g,h),j=c&&null==this.ext[b],k=!j&&null!=d&&d!==i;return e(g&&g!==b),j||k?(f||(j||c?(f="'"+g+"' extension requires '"+b+"'",k&&(f+=" to be registered "+(d?"before":"after")+" itself")):f="If used together, `"+b+"` must be registered "+(d?"before":"after")+" `"+g+"`"),a.error(f),!1):!0},activateKey:function(a){var b=this.getNodeByKey(a);return b?b.setActive():this.activeNode&&this.activeNode.setActive(!1),b},applyPatch:function(b){var c,d,f,g,h,i,j=b.length,k=[];for(d=0;j>d;d++)f=b[d],e(2===f.length,"patchList must be an array of length-2-arrays"),g=f[0],h=f[1],i=null===g?this.rootNode:this.getNodeByKey(g),i?(c=new a.Deferred,k.push(c),i.applyPatch(h).always(m(c,i))):this.warn("could not find node with key '"+g+"'");return a.when.apply(a,k).promise()},count:function(){return this.rootNode.countChildren()},debug:function(){this.options.debugLevel>=2&&(Array.prototype.unshift.call(arguments,this.toString()),f("log",arguments))},findNextNode:function(b,c){var d=null,e=c.parent.children,f=null,g=function(a,b,c){var d,e,f=a.children,h=f.length,i=f[b];if(i&&c(i)===!1)return!1;if(i&&i.children&&i.expanded&&g(i,0,c)===!1)return!1;for(d=b+1;h>d;d++)if(g(a,d,c)===!1)return!1;return e=a.parent,e?g(e,e.children.indexOf(a)+1,c):g(a,0,c)};return b="string"==typeof b?p(b):b,c=c||this.getFirstChild(),g(c.parent,e.indexOf(c),function(e){return e===d?!1:(d=d||e,a(e.span).is(":visible")?b(e)&&(f=e,f!==c)?!1:void 0:void e.debug("quicksearch: skipping hidden node"))}),f},generateFormElements:function(b,c,d){d=d||{};var e,f="string"==typeof b?b:"ft_"+this._id+"[]",g="string"==typeof c?c:"ft_"+this._id+"_active",h="fancytree_result_"+this._id,i=a("#"+h),j=3===this.options.selectMode&&d.stopOnParents!==!1;i.length?i.empty():i=a("<div>",{id:h}).hide().insertAfter(this.$container),b!==!1&&(e=this.getSelectedNodes(j),a.each(e,function(b,c){i.append(a("<input>",{type:"checkbox",name:f,value:c.key,checked:!0}))})),c!==!1&&this.activeNode&&i.append(a("<input>",{type:"radio",name:g,value:this.activeNode.key,checked:!0}))},getActiveNode:function(){return this.activeNode},getFirstChild:function(){return this.rootNode.getFirstChild()},getFocusNode:function(){return this.focusNode},getNodeByKey:function(a,b){var d,e;return!b&&(d=c.getElementById(this.options.idPrefix+a))?d.ftnode?d.ftnode:null:(b=b||this.rootNode,e=null,b.visit(function(b){return b.key===a?(e=b,!1):void 0},!0),e)},getRootNode:function(){return this.rootNode},getSelectedNodes:function(a){var b=[];return this.rootNode.visit(function(c){return c.selected&&(b.push(c),a===!0)?"skip":void 0}),b},hasFocus:function(){return!!this._hasFocus},info:function(){this.options.debugLevel>=1&&(Array.prototype.unshift.call(arguments,this.toString()),f("info",arguments))},loadKeyPath:function(b,c,e){function f(a,b,d){c.call(r,b,"loading"),b.load().done(function(){r.loadKeyPath.call(r,l[a],c,b).always(m(d,r))}).fail(function(){r.warn("loadKeyPath: error loading: "+a+" (parent: "+o+")"),c.call(r,b,"error"),d.reject()})}var g,h,i,j,k,l,n,o,p,q=this.options.keyPathSeparator,r=this;for(a.isArray(b)||(b=[b]),l={},i=0;i<b.length;i++)for(o=e||this.rootNode,j=b[i],j.charAt(0)===q&&(j=j.substr(1)),p=j.split(q);p.length;){if(k=p.shift(),n=o._findDirectChild(k),!n){this.warn("loadKeyPath: key not found: "+k+" (parent: "+o+")"),c.call(this,k,"error");break}if(0===p.length){c.call(this,n,"ok");break}if(n.lazy&&n.hasChildren()===d){c.call(this,n,"loaded"),l[k]?l[k].push(p.join(q)):l[k]=[p.join(q)];break}c.call(this,n,"loaded"),o=n}g=[];for(k in l)n=o._findDirectChild(k),h=new a.Deferred,g.push(h),f(k,n,h);return a.when.apply(a,g).promise()},reactivate:function(a){var b,c=this.activeNode;return c?(this.activeNode=null,b=c.setActive(),a&&c.setFocus(),b):k()},reload:function(a){return this._callHook("treeClear",this),this._callHook("treeLoad",this,a)},render:function(a,b){return this.rootNode.render(a,b)},setFocus:function(a){return this._callHook("treeSetFocus",this,a)},toDict:function(a,b){var c=this.rootNode.toDict(!0,b);return a?c:c.children},toString:function(){return"<Fancytree(#"+this._id+")>"},_triggerNodeEvent:function(a,b,c,e){var f=this._makeHookContext(b,c,e),g=this.widget._trigger(a,c,f);return g!==!1&&f.result!==d?f.result:g},_triggerTreeEvent:function(a,b,c){var e=this._makeHookContext(this,b,c),f=this.widget._trigger(a,b,e);return f!==!1&&e.result!==d?e.result:f},visit:function(a){return this.rootNode.visit(a,!1)},warn:function(){Array.prototype.unshift.call(arguments,this.toString()),f("warn",arguments)}},a.extend(r.prototype,{nodeClick:function(a){var b,c,d=a.targetType,e=a.node;if("expander"===d)this._callHook("nodeToggleExpanded",a);else if("checkbox"===d)this._callHook("nodeToggleSelected",a),a.options.focusOnSelect&&this._callHook("nodeSetFocus",a,!0);else{if(c=!1,b=!0,e.folder)switch(a.options.clickFolderMode){case 2:c=!0,b=!1;break;case 3:b=!0,c=!0}b&&(this.nodeSetFocus(a),this._callHook("nodeSetActive",a,!0)),c&&this._callHook("nodeToggleExpanded",a)}},nodeCollapseSiblings:function(a,b){var c,d,e,f=a.node;if(f.parent)for(c=f.parent.children,d=0,e=c.length;e>d;d++)c[d]!==f&&c[d].expanded&&this._callHook("nodeSetExpanded",c[d],!1,b)},nodeDblclick:function(a){"title"===a.targetType&&4===a.options.clickFolderMode&&this._callHook("nodeToggleExpanded",a),"title"===a.targetType&&a.originalEvent.preventDefault()},nodeKeydown:function(b){var c,d,e,f=b.originalEvent,g=b.node,h=b.tree,i=b.options,j=f.which,k=String.fromCharCode(j),l=!(f.altKey||f.ctrlKey||f.metaKey||f.shiftKey),m=a(f.target),n=!0,o=!(f.ctrlKey||!i.autoActivate);if(g||((this.getActiveNode()||this.getFirstChild()).setFocus(),g=b.node=this.focusNode,g.debug("Keydown force focus on active node")),i.quicksearch&&l&&/\w/.test(k)&&!m.is(":input:enabled"))return d=(new Date).getTime(),d-h.lastQuicksearchTime>500&&(h.lastQuicksearchTerm=""),h.lastQuicksearchTime=d,h.lastQuicksearchTerm+=k,c=h.findNextNode(h.lastQuicksearchTerm,h.getActiveNode()),c&&c.setActive(),void f.preventDefault();switch(t.eventToString(f)){case"+":case"=":h.nodeSetExpanded(b,!0);break;case"-":h.nodeSetExpanded(b,!1);break;case"space":i.checkbox?h.nodeToggleSelected(b):h.nodeSetActive(b,!0);break;case"enter":h.nodeSetActive(b,!0);break;case"backspace":case"left":case"right":case"up":case"down":e=g.navigate(f.which,o);break;default:n=!1}n&&f.preventDefault()},nodeLoadChildren:function(b,c){var d,f,g,h=b.tree,i=b.node;return a.isFunction(c)&&(c=c()),c.url&&(d=a.extend({},b.options.ajax,c),d.debugDelay?(f=d.debugDelay,a.isArray(f)&&(f=f[0]+Math.random()*(f[1]-f[0])),i.debug("nodeLoadChildren waiting debug delay "+Math.round(f)+"ms"),d.debugDelay=!1,g=a.Deferred(function(b){setTimeout(function(){a.ajax(d).done(function(){b.resolveWith(this,arguments)}).fail(function(){b.rejectWith(this,arguments)})},f)})):g=a.ajax(d),c=new a.Deferred,g.done(function(d){var e,f;if("string"==typeof d&&a.error("Ajax request returned a string (did you get the JSON dataType wrong?)."),b.options.postProcess){if(f=h._triggerNodeEvent("postProcess",b,b.originalEvent,{response:d,error:null,dataType:this.dataType}),f.error)return e=a.isPlainObject(f.error)?f.error:{message:f.error},e=h._makeHookContext(i,null,e),void c.rejectWith(this,[e]);d=a.isArray(f)?f:d}else d&&d.hasOwnProperty("d")&&b.options.enableAspx&&(d="string"==typeof d.d?a.parseJSON(d.d):d.d);c.resolveWith(this,[d])}).fail(function(a,b,d){var e=h._makeHookContext(i,null,{error:a,args:Array.prototype.slice.call(arguments),message:d,details:a.status+": "+d});c.rejectWith(this,[e])})),a.isFunction(c.then)&&a.isFunction(c["catch"])&&(g=c,c=new a.Deferred,g.then(function(a){c.resolve(a)},function(a){c.reject(a)})),a.isFunction(c.promise)&&(e(!i.isLoading()),h.nodeSetStatus(b,"loading"),c.done(function(){h.nodeSetStatus(b,"ok")}).fail(function(a){var c;c=a.node&&a.error&&a.message?a:h._makeHookContext(i,null,{error:a,args:Array.prototype.slice.call(arguments),message:a?a.message||a.toString():""}),h._triggerNodeEvent("loadError",c,null)!==!1&&h.nodeSetStatus(b,"error",c.message,c.details)})),a.when(c).done(function(b){var c;a.isPlainObject(b)&&(e(a.isArray(b.children),"source must contain (or be) an array of children"),e(i.isRoot(),"source may only be an object for root nodes"),c=b,b=b.children,delete c.children,a.extend(h.data,c)),e(a.isArray(b),"expected array of children"),i._setChildren(b),h._triggerNodeEvent("loadChildren",i)})},nodeLoadKeyPath:function(){},nodeRemoveChild:function(b,c){var d,f=b.node,g=b.options,h=a.extend({},b,{node:c}),i=f.children;return 1===i.length?(e(c===i[0]),this.nodeRemoveChildren(b)):(this.activeNode&&(c===this.activeNode||this.activeNode.isDescendantOf(c))&&this.activeNode.setActive(!1),this.focusNode&&(c===this.focusNode||this.focusNode.isDescendantOf(c))&&(this.focusNode=null),this.nodeRemoveMarkup(h),this.nodeRemoveChildren(h),d=a.inArray(c,i),e(d>=0),c.visit(function(a){a.parent=null},!0),this._callHook("treeRegisterNode",this,!1,c),g.removeNode&&g.removeNode.call(b.tree,{type:"removeNode"},h),void i.splice(d,1))},nodeRemoveChildMarkup:function(b){var c=b.node;c.ul&&(c.isRoot()?a(c.ul).empty():(a(c.ul).remove(),c.ul=null),c.visit(function(a){a.li=a.ul=null}))},nodeRemoveChildren:function(b){var c,d=b.tree,e=b.node,f=e.children,g=b.options;f&&(this.activeNode&&this.activeNode.isDescendantOf(e)&&this.activeNode.setActive(!1),this.focusNode&&this.focusNode.isDescendantOf(e)&&(this.focusNode=null),this.nodeRemoveChildMarkup(b),c=a.extend({},b),e.visit(function(a){a.parent=null,d._callHook("treeRegisterNode",d,!1,a),g.removeNode&&(c.node=a,g.removeNode.call(b.tree,{type:"removeNode"},c))}),e.children=e.lazy?[]:null,this.nodeRenderStatus(b))},nodeRemoveMarkup:function(b){var c=b.node;c.li&&(a(c.li).remove(),c.li=null),this.nodeRemoveChildMarkup(b)},nodeRender:function(b,d,f,g,h){var i,j,k,l,m,n,o,p=b.node,q=b.tree,r=b.options,s=r.aria,t=!1,u=p.parent,v=!u,w=p.children;if(v||u.ul){if(e(v||u.ul,"parent UL must exist"),v||(p.li&&(d||p.li.parentNode!==p.parent.ul)&&(p.li.parentNode!==p.parent.ul&&this.debug("Unlinking "+p+" (must be child of "+p.parent+")"),this.nodeRemoveMarkup(b)),p.li?this.nodeRenderStatus(b):(t=!0,p.li=c.createElement("li"),p.li.ftnode=p,p.key&&r.generateIds&&(p.li.id=r.idPrefix+p.key),p.span=c.createElement("span"),p.span.className="fancytree-node",s&&a(p.span).attr("aria-labelledby","ftal_"+p.key),p.li.appendChild(p.span),this.nodeRenderTitle(b),r.createNode&&r.createNode.call(q,{type:"createNode"},b)),r.renderNode&&r.renderNode.call(q,{type:"renderNode"},b)),w){if(v||p.expanded||f===!0){for(p.ul||(p.ul=c.createElement("ul"),(g===!0&&!h||!p.expanded)&&(p.ul.style.display="none"),s&&a(p.ul).attr("role","group"),p.li?p.li.appendChild(p.ul):p.tree.$div.append(p.ul)),l=0,m=w.length;m>l;l++)o=a.extend({},b,{node:w[l]}),this.nodeRender(o,d,f,!1,!0);for(i=p.ul.firstChild;i;)k=i.ftnode,k&&k.parent!==p?(p.debug("_fixParent: remove missing "+k,i),n=i.nextSibling,i.parentNode.removeChild(i),i=n):i=i.nextSibling;for(i=p.ul.firstChild,l=0,m=w.length-1;m>l;l++)j=w[l],k=i.ftnode,j!==k?p.ul.insertBefore(j.li,k.li):i=i.nextSibling}}else p.ul&&(this.warn("remove child markup for "+p),this.nodeRemoveChildMarkup(b));v||t&&u.ul.appendChild(p.li)}},nodeRenderTitle:function(a,b){var c,e,f,g,h,i,j=a.node,k=a.tree,l=a.options,m=l.aria,n=j.getLevel(),o=[],p=j.data.icon;b!==d&&(j.title=b),j.span&&(n<l.minExpandLevel?(j.lazy||(j.expanded=!0),n>1&&o.push(m?"<span role='button' class='fancytree-expander fancytree-expander-fixed'></span>":"<span class='fancytree-expander fancytree-expander-fixed''></span>")):o.push(m?"<span role='button' class='fancytree-expander'></span>":"<span class='fancytree-expander'></span>"),l.checkbox&&j.hideCheckbox!==!0&&!j.isStatusNode()&&o.push(m?"<span role='checkbox' class='fancytree-checkbox'></span>":"<span class='fancytree-checkbox'></span>"),g=m?" role='img'":"",(p===!0||p!==!1&&l.icons!==!1)&&(p&&"string"==typeof p?(p="/"===p.charAt(0)?p:(l.imagePath||"")+p,o.push("<img src='"+p+"' class='fancytree-icon' alt='' />")):(e=l.iconClass&&l.iconClass.call(k,j,a)||j.data.iconclass||null,o.push(e?"<span "+g+" class='fancytree-custom-icon "+e+"'></span>":"<span "+g+" class='fancytree-icon'></span>"))),f="",l.renderTitle&&(f=l.renderTitle.call(k,{type:"renderTitle"},a)||""),f||(i=j.tooltip?" title='"+t.escapeHtml(j.tooltip)+"'":"",c=m?" id='ftal_"+j.key+"'":"",g=m?" role='treeitem'":"",h=l.titlesTabbable?" tabindex='0'":"",f="<span "+g+" class='fancytree-title'"+c+i+h+">"+j.title+"</span>"),o.push(f),j.span.innerHTML=o.join(""),this.nodeRenderStatus(a))},nodeRenderStatus:function(b){var c=b.node,d=b.tree,e=b.options,f=c.hasChildren(),g=c.isLastSibling(),h=e.aria,i=a(c.span).find(".fancytree-title"),j=e._classNames,k=[],l=c[d.statusClassPropName]; +l&&(k.push(j.node),d.activeNode===c&&k.push(j.active),d.focusNode===c?(k.push(j.focused),h&&i.attr("aria-activedescendant",!0)):h&&i.removeAttr("aria-activedescendant"),c.expanded?(k.push(j.expanded),h&&i.attr("aria-expanded",!0)):h&&i.removeAttr("aria-expanded"),c.folder&&k.push(j.folder),f!==!1&&k.push(j.hasChildren),g&&k.push(j.lastsib),c.lazy&&null==c.children&&k.push(j.lazy),c.partsel&&k.push(j.partsel),c.unselectable&&k.push(j.unselectable),c._isLoading&&k.push(j.loading),c._error&&k.push(j.error),c.selected?(k.push(j.selected),h&&i.attr("aria-selected",!0)):h&&i.attr("aria-selected",!1),c.extraClasses&&k.push(c.extraClasses),k.push(f===!1?j.combinedExpanderPrefix+"n"+(g?"l":""):j.combinedExpanderPrefix+(c.expanded?"e":"c")+(c.lazy&&null==c.children?"d":"")+(g?"l":"")),k.push(j.combinedIconPrefix+(c.expanded?"e":"c")+(c.folder?"f":"")),l.className=k.join(" "),c.li&&(c.li.className=g?j.lastsib:""))},nodeSetActive:function(b,c,d){d=d||{};var f,g=b.node,h=b.tree,i=b.options,j=d.noEvents===!0,m=d.noFocus===!0,n=g===h.activeNode;return c=c!==!1,n===c?k(g):c&&!j&&this._triggerNodeEvent("beforeActivate",g,b.originalEvent)===!1?l(g,["rejected"]):void(c?(h.activeNode&&(e(h.activeNode!==g,"node was active (inconsistency)"),f=a.extend({},b,{node:h.activeNode}),h.nodeSetActive(f,!1),e(null===h.activeNode,"deactivate was out of sync?")),i.activeVisible&&g.makeVisible({scrollIntoView:!1}),h.activeNode=g,h.nodeRenderStatus(b),m||h.nodeSetFocus(b),j||h._triggerNodeEvent("activate",g,b.originalEvent)):(e(h.activeNode===g,"node was not active (inconsistency)"),h.activeNode=null,this.nodeRenderStatus(b),j||b.tree._triggerNodeEvent("deactivate",g,b.originalEvent)))},nodeSetExpanded:function(b,c,e){e=e||{};var f,g,h,i,j,m,n=b.node,o=b.tree,p=b.options,q=e.noAnimation===!0,r=e.noEvents===!0;if(c=c!==!1,n.expanded&&c||!n.expanded&&!c)return k(n);if(c&&!n.lazy&&!n.hasChildren())return k(n);if(!c&&n.getLevel()<p.minExpandLevel)return l(n,["locked"]);if(!r&&this._triggerNodeEvent("beforeExpand",n,b.originalEvent)===!1)return l(n,["rejected"]);if(q||n.isVisible()||(q=e.noAnimation=!0),g=new a.Deferred,c&&!n.expanded&&p.autoCollapse){j=n.getParentList(!1,!0),m=p.autoCollapse;try{for(p.autoCollapse=!1,h=0,i=j.length;i>h;h++)this._callHook("nodeCollapseSiblings",j[h],e)}finally{p.autoCollapse=m}}return g.done(function(){c&&p.autoScroll&&!q?n.getLastChild().scrollIntoView(!0,{topNode:n}).always(function(){r||b.tree._triggerNodeEvent(c?"expand":"collapse",b)}):r||b.tree._triggerNodeEvent(c?"expand":"collapse",b)}),f=function(d){var e,f,g=p.toggleEffect;if(n.expanded=c,o._callHook("nodeRender",b,!1,!1,!0),n.ul)if(e="none"!==n.ul.style.display,f=!!n.expanded,e===f)n.warn("nodeSetExpanded: UL.style.display already set");else{if(g&&!q)return void a(n.ul).toggle(g.effect,g.options,g.duration,function(){d()});n.ul.style.display=n.expanded||!parent?"":"none"}d()},c&&n.lazy&&n.hasChildren()===d?n.load().done(function(){g.notifyWith&&g.notifyWith(n,["loaded"]),f(function(){g.resolveWith(n)})}).fail(function(a){f(function(){g.rejectWith(n,["load failed ("+a+")"])})}):f(function(){g.resolveWith(n)}),g.promise()},nodeSetFocus:function(b,c){var d,e=b.tree,f=b.node;if(c=c!==!1,e.focusNode){if(e.focusNode===f&&c)return;d=a.extend({},b,{node:e.focusNode}),e.focusNode=null,this._triggerNodeEvent("blur",d),this._callHook("nodeRenderStatus",d)}c&&(this.hasFocus()||(f.debug("nodeSetFocus: forcing container focus"),this._callHook("treeSetFocus",b,!0,{calledByNode:!0})),f.makeVisible({scrollIntoView:!1}),e.focusNode=f,this._triggerNodeEvent("focus",b),b.options.autoScroll&&f.scrollIntoView(),this._callHook("nodeRenderStatus",b))},nodeSetSelected:function(a,b){var c=a.node,d=a.tree,e=a.options;if(b=b!==!1,c.debug("nodeSetSelected("+b+")",a),!c.unselectable){if(c.selected&&b||!c.selected&&!b)return!!c.selected;if(this._triggerNodeEvent("beforeSelect",c,a.originalEvent)===!1)return!!c.selected;b&&1===e.selectMode?d.lastSelectedNode&&d.lastSelectedNode.setSelected(!1):3===e.selectMode&&(c.selected=b,c.fixSelection3AfterClick()),c.selected=b,this.nodeRenderStatus(a),d.lastSelectedNode=b?c:null,d._triggerNodeEvent("select",a)}},nodeSetStatus:function(b,c,d,e){function f(){var a=h.children?h.children[0]:null;if(a&&a.isStatusNode()){try{h.ul&&(h.ul.removeChild(a.li),a.li=null)}catch(b){}1===h.children.length?h.children=[]:h.children.shift()}}function g(b,c){var d=h.children?h.children[0]:null;return d&&d.isStatusNode()?(a.extend(d,b),i._callHook("nodeRenderTitle",d)):(b.key="_statusNode",h._setChildren([b]),h.children[0].statusNodeType=c,i.render()),h.children[0]}var h=b.node,i=b.tree;switch(c){case"ok":f(),h._isLoading=!1,h._error=null,h.renderStatus();break;case"loading":h.parent||g({title:i.options.strings.loading+(d?" ("+d+") ":""),tooltip:e,extraClasses:"fancytree-statusnode-wait"},c),h._isLoading=!0,h._error=null,h.renderStatus();break;case"error":g({title:i.options.strings.loadError+(d?" ("+d+") ":""),tooltip:e,extraClasses:"fancytree-statusnode-error"},c),h._isLoading=!1,h._error={message:d,details:e},h.renderStatus();break;default:a.error("invalid node status "+c)}},nodeToggleExpanded:function(a){return this.nodeSetExpanded(a,!a.node.expanded)},nodeToggleSelected:function(a){return this.nodeSetSelected(a,!a.node.selected)},treeClear:function(a){var b=a.tree;b.activeNode=null,b.focusNode=null,b.$div.find(">ul.fancytree-container").empty(),b.rootNode.children=null},treeCreate:function(){},treeDestroy:function(){},treeInit:function(a){this.treeLoad(a)},treeLoad:function(b,c){var d,e,f,g=b.tree,h=b.widget.element,i=a.extend({},b,{node:this.rootNode});if(g.rootNode.children&&this.treeClear(b),c=c||this.options.source)"string"==typeof c&&a.error("Not implemented");else switch(d=h.data("type")||"html"){case"html":e=h.find(">ul:first"),e.addClass("ui-fancytree-source ui-helper-hidden"),c=a.ui.fancytree.parseHtml(e),this.data=a.extend(this.data,n(e));break;case"json":c=a.parseJSON(h.text()),c.children&&(c.title&&(g.title=c.title),c=c.children);break;default:a.error("Invalid data-type: "+d)}return f=this.nodeLoadChildren(i,c).done(function(){g.render(),3===b.options.selectMode&&g.rootNode.fixSelection3FromEndNodes(),g._triggerTreeEvent("init",null,{status:!0})}).fail(function(){g.render(),g._triggerTreeEvent("init",null,{status:!1})})},treeRegisterNode:function(){},treeSetFocus:function(a,b){b=b!==!1,b!==this.hasFocus()&&(this._hasFocus=b,!b&&this.focusNode&&this.focusNode.setFocus(!1),this.$container.toggleClass("fancytree-treefocus",b),this._triggerTreeEvent(b?"focusTree":"blurTree"))}}),a.widget("ui.fancytree",{options:{activeVisible:!0,ajax:{type:"GET",cache:!1,dataType:"json"},aria:!1,autoActivate:!0,autoCollapse:!1,autoScroll:!1,checkbox:!1,clickFolderMode:4,debugLevel:null,disabled:!1,enableAspx:!0,extensions:[],toggleEffect:{effect:"blind",options:{direction:"vertical",scale:"box"},duration:200},generateIds:!1,icons:!0,idPrefix:"ft_",focusOnSelect:!1,keyboard:!0,keyPathSeparator:"/",minExpandLevel:1,quicksearch:!1,scrollOfs:{top:0,bottom:0},scrollParent:null,selectMode:2,strings:{loading:"Loading&#8230;",loadError:"Load error!"},tabbable:!0,titlesTabbable:!1,_classNames:{node:"fancytree-node",folder:"fancytree-folder",combinedExpanderPrefix:"fancytree-exp-",combinedIconPrefix:"fancytree-ico-",hasChildren:"fancytree-has-children",active:"fancytree-active",selected:"fancytree-selected",expanded:"fancytree-expanded",lazy:"fancytree-lazy",focused:"fancytree-focused",partsel:"fancytree-partsel",unselectable:"fancytree-unselectable",lastsib:"fancytree-lastsib",loading:"fancytree-loading",error:"fancytree-error"},lazyLoad:null,postProcess:null},_create:function(){this.tree=new r(this),this.$source=this.source||"json"===this.element.data("type")?this.element:this.element.find(">ul:first");var b,c,f,g=this.options.extensions,h=this.tree;for(f=0;f<g.length;f++)c=g[f],b=a.ui.fancytree._extensions[c],b||a.error("Could not apply extension '"+c+"' (it is not registered, did you forget to include it?)"),this.tree.options[c]=a.extend(!0,{},b.options,this.tree.options[c]),e(this.tree.ext[c]===d,"Extension name must not exist as Fancytree.ext attribute: '"+c+"'"),this.tree.ext[c]={},j(this.tree,h,b,c),h=b;this.tree._callHook("treeCreate",this.tree)},_init:function(){this.tree._callHook("treeInit",this.tree),this._bind()},_setOption:function(b,c){var d=!0,e=!1;switch(b){case"aria":case"checkbox":case"icons":case"minExpandLevel":case"tabbable":this.tree._callHook("treeCreate",this.tree),e=!0;break;case"source":d=!1,this.tree._callHook("treeLoad",this.tree,c)}this.tree.debug("set option "+b+"="+c+" <"+typeof c+">"),d&&a.Widget.prototype._setOption.apply(this,arguments),e&&this.tree.render(!0,!1)},destroy:function(){this._unbind(),this.tree._callHook("treeDestroy",this.tree),this.tree.$div.find(">ul.fancytree-container").remove(),this.$source&&this.$source.removeClass("ui-helper-hidden"),a.Widget.prototype.destroy.call(this)},_unbind:function(){var b=this.tree._ns;this.element.unbind(b),this.tree.$container.unbind(b),a(c).unbind(b)},_bind:function(){var a=this,b=this.options,c=this.tree,d=c._ns;this._unbind(),c.$container.on("focusin"+d+" focusout"+d,function(a){var b=t.getNode(a),d="focusin"===a.type;b?c._callHook("nodeSetFocus",b,d):c._callHook("treeSetFocus",c,d)}).on("selectstart"+d,"span.fancytree-title",function(a){a.preventDefault()}).on("keydown"+d,function(a){if(b.disabled||b.keyboard===!1)return!0;var d,e=c.focusNode,f=c._makeHookContext(e||c,a),g=c.phase;try{return c.phase="userEvent",d=e?c._triggerNodeEvent("keydown",e,a):c._triggerTreeEvent("keydown",a),"preventNav"===d?d=!0:d!==!1&&(d=c._callHook("nodeKeydown",f)),d}finally{c.phase=g}}).on("click"+d+" dblclick"+d,function(c){if(b.disabled)return!0;var d,e=t.getEventTarget(c),f=e.node,g=a.tree,h=g.phase;if(!f)return!0;d=g._makeHookContext(f,c);try{switch(g.phase="userEvent",c.type){case"click":return d.targetType=e.type,g._triggerNodeEvent("click",d,c)===!1?!1:g._callHook("nodeClick",d);case"dblclick":return d.targetType=e.type,g._triggerNodeEvent("dblclick",d,c)===!1?!1:g._callHook("nodeDblclick",d)}}finally{g.phase=h}})},getActiveNode:function(){return this.tree.activeNode},getNodeByKey:function(a){return this.tree.getNodeByKey(a)},getRootNode:function(){return this.tree.rootNode},getTree:function(){return this.tree}}),t=a.ui.fancytree,a.extend(a.ui.fancytree,{version:"2.8.1",buildType: "production",debugLevel: 1,_nextId:1,_nextNodeKey:1,_extensions:{},_FancytreeClass:r,_FancytreeNodeClass:q,jquerySupports:{positionMyOfs:h(a.ui.version,1,9)},assert:function(a,b){return e(a,b)},debounce:function(a,b,c,d){var e;return 3===arguments.length&&"boolean"!=typeof c&&(d=c,c=!1),function(){var f=arguments;d=d||this,c&&!e&&b.apply(d,f),clearTimeout(e),e=setTimeout(function(){c||b.apply(d,f),e=null},a)}},debug:function(){a.ui.fancytree.debugLevel>=2&&f("log",arguments)},error:function(){f("error",arguments)},escapeHtml:function(a){return(""+a).replace(/[&<>"'\/]/g,function(a){return u[a]})},fixPositionOptions:function(b){if((b.offset||(""+b.my+b.at).indexOf("%")>=0)&&a.error("expected new position syntax (but '%' is not supported)"),!a.ui.fancytree.jquerySupports.positionMyOfs){var c=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(b.my),d=/(\w+)([+-]?\d+)?\s+(\w+)([+-]?\d+)?/.exec(b.at),e=(c[2]?+c[2]:0)+(d[2]?+d[2]:0),f=(c[4]?+c[4]:0)+(d[4]?+d[4]:0);b=a.extend({},b,{my:c[1]+" "+c[3],at:d[1]+" "+d[3]}),(e||f)&&(b.offset=""+e+" "+f)}return b},getEventTargetType:function(a){return this.getEventTarget(a).type},getEventTarget:function(b){var c=b&&b.target?b.target.className:"",e={node:this.getNode(b.target),type:d};return/\bfancytree-title\b/.test(c)?e.type="title":/\bfancytree-expander\b/.test(c)?e.type=e.node.hasChildren()===!1?"prefix":"expander":/\bfancytree-checkbox\b/.test(c)||/\bfancytree-radio\b/.test(c)?e.type="checkbox":/\bfancytree-icon\b/.test(c)?e.type="icon":/\bfancytree-node\b/.test(c)?e.type="title":b&&b.target&&a(b.target).closest(".fancytree-title").length&&(e.type="title"),e},getNode:function(a){if(a instanceof q)return a;for(a.selector!==d?a=a[0]:a.originalEvent!==d&&(a=a.target);a;){if(a.ftnode)return a.ftnode;a=a.parentNode}return null},info:function(){a.ui.fancytree.debugLevel>=1&&f("info",arguments)},eventToString:function(a){var b=a.which,c=a.type,d=[];return a.altKey&&d.push("alt"),a.ctrlKey&&d.push("ctrl"),a.metaKey&&d.push("meta"),a.shiftKey&&d.push("shift"),"click"===c||"dblclick"===c?d.push(x[a.button]+c):v[b]||d.push(w[b]||String.fromCharCode(b).toLowerCase()),d.join("+")},keyEventToString:function(a){return this.warn("keyEventToString() is deprecated: use eventToString()"),this.eventToString(a)},parseHtml:function(b){var c,e,f,g,h,i,j,k,l=b.find(">li"),m=[];return l.each(function(){var l,o=a(this),p=o.find(">span:first",this),q=p.length?null:o.find(">a:first"),r={tooltip:null,data:{}};for(p.length?r.title=p.html():q&&q.length?(r.title=q.html(),r.data.href=q.attr("href"),r.data.target=q.attr("target"),r.tooltip=q.attr("title")):(r.title=o.html(),g=r.title.search(/<ul/i),g>=0&&(r.title=r.title.substring(0,g))),r.title=a.trim(r.title),e=0,f=y.length;f>e;e++)r[y[e]]=d;for(j=this.className.split(" "),c=[],e=0,f=j.length;f>e;e++)k=j[e],z[k]?r[k]=!0:c.push(k);if(r.extraClasses=c.join(" "),h=o.attr("title"),h&&(r.tooltip=h),h=o.attr("id"),h&&(r.key=h),l=n(o),l&&!a.isEmptyObject(l)){for(e=0,f=A.length;f>e;e++)h=A[e],i=l[h],null!=i&&(delete l[h],r[h]=i);a.extend(r.data,l)}b=o.find(">ul:first"),r.children=b.length?a.ui.fancytree.parseHtml(b):r.lazy?d:null,m.push(r)}),m},registerExtension:function(b){e(null!=b.name,"extensions must have a `name` property."),e(null!=b.version,"extensions must have a `version` property."),a.ui.fancytree._extensions[b.name]=b},unescapeHtml:function(a){var b=c.createElement("div");return b.innerHTML=a,0===b.childNodes.length?"":b.childNodes[0].nodeValue},warn:function(){f("warn",arguments)}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.childcounter.min.js' */ +!function(a){"use strict";a.ui.fancytree._FancytreeClass.prototype.countSelected=function(a){{var b=this;b.options}return b.getSelectedNodes(a).length},a.ui.fancytree._FancytreeNodeClass.prototype.toUpper=function(){var a=this;return a.setTitle(a.title.toUpperCase())},a.ui.fancytree.prototype.widgetMethod1=function(a){this.tree;return a},a.ui.fancytree.registerExtension({name:"childcounter",version:"1.0.0",options:{deep:!0,hideZeros:!0,hideExpanded:!1},foo:42,_appendCounter:function(){},treeInit:function(a){a.options,a.options.childcounter;this._superApply(arguments),this.$container.addClass("fancytree-ext-childcounter")},treeDestroy:function(){this._superApply(arguments)},nodeRenderTitle:function(b){var c=b.node,d=b.options.childcounter,e=null==c.data.childCounter?c.countChildren(d.deep):+c.data.childCounter;this._superApply(arguments),!e&&d.hideZeros||c.isExpanded()&&d.hideExpanded||a("span.fancytree-icon",c.span).append(a("<span class='fancytree-childcounter'/>").text(e))},nodeSetExpanded:function(a){{var b=a.tree;a.node}return this._superApply(arguments).always(function(){b.nodeRenderTitle(a)})}})}(jQuery); + +/*! Extension 'jquery.fancytree.clones.min.js' */ +!function(a){"use strict";function b(b,c){b||(c=c?": "+c:"",a.error("Assertion failed"+c))}function c(a,b){var c;for(c=a.length-1;c>=0;c--)if(a[c]===b)return a.splice(c,1),!0;return!1}function d(a,b,c){for(var d,e,f=3&a.length,g=a.length-f,h=c,i=3432918353,j=461845907,k=0;g>k;)e=255&a.charCodeAt(k)|(255&a.charCodeAt(++k))<<8|(255&a.charCodeAt(++k))<<16|(255&a.charCodeAt(++k))<<24,++k,e=(65535&e)*i+(((e>>>16)*i&65535)<<16)&4294967295,e=e<<15|e>>>17,e=(65535&e)*j+(((e>>>16)*j&65535)<<16)&4294967295,h^=e,h=h<<13|h>>>19,d=5*(65535&h)+((5*(h>>>16)&65535)<<16)&4294967295,h=(65535&d)+27492+(((d>>>16)+58964&65535)<<16);switch(e=0,f){case 3:e^=(255&a.charCodeAt(k+2))<<16;case 2:e^=(255&a.charCodeAt(k+1))<<8;case 1:e^=255&a.charCodeAt(k),e=(65535&e)*i+(((e>>>16)*i&65535)<<16)&4294967295,e=e<<15|e>>>17,e=(65535&e)*j+(((e>>>16)*j&65535)<<16)&4294967295,h^=e}return h^=a.length,h^=h>>>16,h=2246822507*(65535&h)+((2246822507*(h>>>16)&65535)<<16)&4294967295,h^=h>>>13,h=3266489909*(65535&h)+((3266489909*(h>>>16)&65535)<<16)&4294967295,h^=h>>>16,b?("0000000"+(h>>>0).toString(16)).substr(-8):h>>>0}function e(b){var c,e=a.map(b.getParentList(!1,!0),function(a){return a.refKey||a.key});return e=e.join("/"),c="id_"+d(e,!0)}a.ui.fancytree._FancytreeNodeClass.prototype.getCloneList=function(b){var c,d=this.tree,e=d.refMap[this.refKey]||null,f=d.keyMap;return e&&(c=this.key,b?e=a.map(e,function(a){return f[a]}):(e=a.map(e,function(a){return a===c?null:f[a]}),e.length<1&&(e=null))),e},a.ui.fancytree._FancytreeNodeClass.prototype.isClone=function(){var a=this.refKey||null,b=a&&this.tree.refMap[a]||null;return!!(b&&b.length>1)},a.ui.fancytree._FancytreeNodeClass.prototype.reRegister=function(b,c){b=null==b?null:""+b,c=null==c?null:""+c;var d=this.tree,e=this.key,f=this.refKey,g=d.keyMap,h=d.refMap,i=h[f]||null,j=!1;return null!=b&&b!==this.key&&(g[b]&&a.error("[ext-clones] reRegister("+b+"): already exists: "+this),delete g[e],g[b]=this,i&&(h[f]=a.map(i,function(a){return a===e?b:a})),this.key=b,j=!0),null!=c&&c!==this.refKey&&(i&&(1===i.length?delete h[f]:h[f]=a.map(i,function(a){return a===e?null:a})),h[c]?h[c].append(b):h[c]=[this.key],this.refKey=c,j=!0),j},a.ui.fancytree._FancytreeClass.prototype.getNodesByRef=function(b,c){var d=this.keyMap,e=this.refMap[b]||null;return e&&(e=c?a.map(e,function(a){var b=d[a];return b.isDescendantOf(c)?b:null}):a.map(e,function(a){return d[a]}),e.length<1&&(e=null)),e},a.ui.fancytree._FancytreeClass.prototype.changeRefKey=function(a,b){var c,d,e=this.keyMap,f=this.refMap[a]||null;if(f){for(c=0;c<f.length;c++)d=e[f[c]],d.refKey=b;delete this.refMap[a],this.refMap[b]=f}},a.ui.fancytree.registerExtension({name:"clones",version:"0.0.3",options:{highlightActiveClones:!0,highlightClones:!1},treeCreate:function(a){this._superApply(arguments),a.tree.refMap={},a.tree.keyMap={}},treeInit:function(a){this.$container.addClass("fancytree-ext-clones"),b(null==a.options.defaultKey),a.options.defaultKey=function(a){return e(a)},this._superApply(arguments)},treeClear:function(a){return a.tree.refMap={},a.tree.keyMap={},this._superApply(arguments)},treeRegisterNode:function(d,e,f){var g,h,i=d.tree,j=i.keyMap,k=i.refMap,l=f.key,m=f&&null!=f.refKey?""+f.refKey:null;return"_statusNode"===l?this._superApply(arguments):(e?(null!=j[f.key]&&a.error("clones.treeRegisterNode: node.key already exists: "+f),j[l]=f,m&&(g=k[m],g?(g.push(l),2===g.length&&d.options.clones.highlightClones&&j[g[0]].renderStatus()):k[m]=[l])):(null==j[l]&&a.error("clones.treeRegisterNode: node.key not registered: "+f.key),delete j[l],m&&(g=k[m],g&&(h=g.length,1>=h?(b(1===h),b(g[0]===l),delete k[m]):(c(g,l),2===h&&d.options.clones.highlightClones&&j[g[0]].renderStatus())))),this._superApply(arguments))},nodeRenderStatus:function(b){var c,d,e=b.node;return d=this._superApply(arguments),b.options.clones.highlightClones&&(c=a(e[b.tree.statusClassPropName]),c.length&&e.isClone()&&c.addClass("fancytree-clone")),d},nodeSetActive:function(b,c){var d,e=b.tree.statusClassPropName,f=b.node;return d=this._superApply(arguments),b.options.clones.highlightActiveClones&&f.isClone()&&a.each(f.getCloneList(!0),function(b,d){a(d[e]).toggleClass("fancytree-active-clone",c!==!1)}),d}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.dnd.min.js' */ +!function(a,b,c,d){"use strict";function e(a){return 0===a?"":a>0?"+"+a:""+a}function f(b){var c=b.options.dnd||null;c&&g(),c&&c.dragStart&&b.widget.element.draggable(a.extend({addClasses:!1,appendTo:b.$container,containment:!1,delay:0,distance:4,revert:!1,scroll:!0,scrollSpeed:7,scrollSensitivity:10,connectToFancytree:!0,helper:function(b){var c,d=a.ui.fancytree.getNode(b.target),e=a(d.span);return d?(c=a("<div class='fancytree-drag-helper'><span class='fancytree-drag-helper-img' /></div>").css({zIndex:3,position:"relative"}).append(e.find("span.fancytree-title").clone()),c.data("ftSourceNode",d),c):"<div>ERROR?: helper requested but sourceNode not found</div>"},start:function(a,b){var c=b.helper.data("ftSourceNode");return!!c}},b.options.dnd.draggable)),c&&c.dragDrop&&b.widget.element.droppable(a.extend({addClasses:!1,tolerance:"intersect",greedy:!1},b.options.dnd.droppable))}function g(){h||(a.ui.plugin.add("draggable","connectToFancytree",{start:function(b,c){var d=a(this).data("ui-draggable")||a(this).data("draggable"),e=c.helper.data("ftSourceNode")||null;return e?(d.offset.click.top=-2,d.offset.click.left=16,e.tree.ext.dnd._onDragEvent("start",e,null,b,c,d)):void 0},drag:function(b,c){var d,e,f=a(this).data("ui-draggable")||a(this).data("draggable"),g=c.helper.data("ftSourceNode")||null,h=c.helper.data("ftTargetNode")||null,i=a.ui.fancytree.getNode(b.target);return b.target&&!i&&(d=a(b.target).closest("div.fancytree-drag-helper,#fancytree-drop-marker").length>0)?(e=g||h||a.ui.fancytree,void e.debug("Drag event over helper: ignored.")):(c.helper.data("ftTargetNode",i),h&&h!==i&&h.tree.ext.dnd._onDragEvent("leave",h,g,b,c,f),void(i&&i.tree.options.dnd.dragDrop&&(i===h?i.tree.ext.dnd._onDragEvent("over",i,g,b,c,f):i.tree.ext.dnd._onDragEvent("enter",i,g,b,c,f))))},stop:function(b,c){var d,e=a(this).data("ui-draggable")||a(this).data("draggable"),f=c.helper.data("ftSourceNode")||null,g=c.helper.data("ftTargetNode")||null,h=b.type,i="mouseup"===h&&1===b.which;i||(d=f||g||a.ui.fancytree,d.debug("Drag was cancelled")),g&&(i&&g.tree.ext.dnd._onDragEvent("drop",g,f,b,c,e),g.tree.ext.dnd._onDragEvent("leave",g,f,b,c,e)),f&&f.tree.ext.dnd._onDragEvent("stop",f,null,b,c,e)}}),h=!0)}var h=!1;a.ui.fancytree.registerExtension({name:"dnd",version:"0.1.0",options:{autoExpandMS:1e3,draggable:null,droppable:null,focusOnClick:!1,preventVoidMoves:!0,preventRecursiveMoves:!0,dragStart:null,dragStop:null,dragEnter:null,dragOver:null,dragDrop:null,dragLeave:null},treeInit:function(b){var c=b.tree;this._superApply(arguments),c.options.dnd.dragStart&&c.$container.on("mousedown",function(d){if(!c.hasFocus()&&b.options.dnd.focusOnClick){var e=a.ui.fancytree.getNode(d);e.debug("Re-enable focus that was prevented by jQuery UI draggable."),setTimeout(function(){a(d.target).closest(":tabbable").focus()},10)}}),f(c)},nodeKeydown:function(b){var c=b.originalEvent;return c.which===a.ui.keyCode.ESCAPE&&this._local._cancelDrag(),this._superApply(arguments)},nodeClick:function(){return this._superApply(arguments)},_setDndStatus:function(b,c,d,f,g){var h=0,i="center",j=this._local,k=b?a(b.span):null,l=a(c.span);if(j.$dropMarker||(j.$dropMarker=a("<div id='fancytree-drop-marker'></div>").hide().css({"z-index":1e3}).prependTo(a(this.$div).parent())),"after"===f||"before"===f||"over"===f){switch(f){case"before":j.$dropMarker.removeClass("fancytree-drop-after fancytree-drop-over").addClass("fancytree-drop-before"),i="top";break;case"after":j.$dropMarker.removeClass("fancytree-drop-before fancytree-drop-over").addClass("fancytree-drop-after"),i="bottom";break;default:j.$dropMarker.removeClass("fancytree-drop-after fancytree-drop-before").addClass("fancytree-drop-over"),l.addClass("fancytree-drop-target"),h=8}j.$dropMarker.show().position(a.ui.fancytree.fixPositionOptions({my:"left"+e(h)+" center",at:"left "+i,of:l}))}else l.removeClass("fancytree-drop-target"),j.$dropMarker.hide();"after"===f?l.addClass("fancytree-drop-after"):l.removeClass("fancytree-drop-after"),"before"===f?l.addClass("fancytree-drop-before"):l.removeClass("fancytree-drop-before"),g===!0?(k&&k.addClass("fancytree-drop-accept"),l.addClass("fancytree-drop-accept"),d.addClass("fancytree-drop-accept")):(k&&k.removeClass("fancytree-drop-accept"),l.removeClass("fancytree-drop-accept"),d.removeClass("fancytree-drop-accept")),g===!1?(k&&k.addClass("fancytree-drop-reject"),l.addClass("fancytree-drop-reject"),d.addClass("fancytree-drop-reject")):(k&&k.removeClass("fancytree-drop-reject"),l.removeClass("fancytree-drop-reject"),d.removeClass("fancytree-drop-reject"))},_onDragEvent:function(b,c,e,f,g,h){"over"!==b&&this.debug("tree.ext.dnd._onDragEvent(%s, %o, %o) - %o",b,c,e,this);var i,j,k,l,m,n,o=this.options,p=o.dnd,q=this._makeHookContext(c,f,{otherNode:e,ui:g,draggable:h}),r=null,s=a(c.span);switch(b){case"start":c.isStatusNode()?r=!1:p.dragStart&&(r=p.dragStart(c,q)),r===!1?(this.debug("tree.dragStart() cancelled"),g.helper.trigger("mouseup").hide()):s.addClass("fancytree-drag-source");break;case"enter":n=p.preventRecursiveMoves&&c.isDescendantOf(e)?!1:p.dragEnter?p.dragEnter(c,q):null,r=n?a.isArray(n)?{over:a.inArray("over",n)>=0,before:a.inArray("before",n)>=0,after:a.inArray("after",n)>=0}:{over:n===!0||"over"===n,before:n===!0||"before"===n,after:n===!0||"after"===n}:!1,g.helper.data("enterResponse",r),this.debug("helper.enterResponse: %o",r);break;case"over":l=g.helper.data("enterResponse"),m=null,l===!1||("string"==typeof l?m=l:(i=s.offset(),j={x:f.pageX-i.left,y:f.pageY-i.top},k={x:j.x/s.width(),y:j.y/s.height()},l.after&&k.y>.75?m="after":!l.over&&l.after&&k.y>.5?m="after":l.before&&k.y<=.25?m="before":!l.over&&l.before&&k.y<=.5?m="before":l.over&&(m="over"),p.preventVoidMoves&&(c===e?(this.debug(" drop over source node prevented"),m=null):"before"===m&&e&&c===e.getNextSibling()?(this.debug(" drop after source node prevented"),m=null):"after"===m&&e&&c===e.getPrevSibling()?(this.debug(" drop before source node prevented"),m=null):"over"===m&&e&&e.parent===c&&e.isLastSibling()&&(this.debug(" drop last child over own parent prevented"),m=null)),g.helper.data("hitMode",m))),"over"===m&&p.autoExpandMS&&c.hasChildren()!==!1&&!c.expanded&&c.scheduleAction("expand",p.autoExpandMS),m&&p.dragOver&&(q.hitMode=m,r=p.dragOver(c,q)),this._local._setDndStatus(e,c,g.helper,m,r!==!1&&null!==m);break;case"drop":m=g.helper.data("hitMode"),m&&p.dragDrop&&(q.hitMode=m,p.dragDrop(c,q));break;case"leave":c.scheduleAction("cancel"),g.helper.data("enterResponse",null),g.helper.data("hitMode",null),this._local._setDndStatus(e,c,g.helper,"out",d),p.dragLeave&&p.dragLeave(c,q);break;case"stop":s.removeClass("fancytree-drag-source"),p.dragStop&&p.dragStop(c,q);break;default:a.error("Unsupported drag event: "+b)}return r},_cancelDrag:function(){var b=a.ui.ddmanager.current;b&&b.cancel()}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.edit.min.js' */ +!function(a,b,c){"use strict";var d=/Mac/.test(navigator.platform),e=a.ui.fancytree.escapeHtml,f=a.ui.fancytree.unescapeHtml;a.ui.fancytree._FancytreeNodeClass.prototype.editStart=function(){var b,d=this,e=this.tree,g=e.ext.edit,h=e.options.edit,i=a(".fancytree-title",d.span),j={node:d,tree:e,options:e.options,isNew:a(d.span).hasClass("fancytree-edit-new"),orgTitle:d.title,input:null,dirty:!1};return h.beforeEdit.call(d,{type:"beforeEdit"},j)===!1?!1:(a.ui.fancytree.assert(!g.currentNode,"recursive edit"),g.currentNode=this,g.eventData=j,e.widget._unbind(),a(c).on("mousedown.fancytree-edit",function(b){a(b.target).hasClass("fancytree-edit-input")||d.editEnd(!0,b)}),b=a("<input />",{"class":"fancytree-edit-input",type:"text",value:f(j.orgTitle)}),g.eventData.input=b,null!=h.adjustWidthOfs&&b.width(i.width()+h.adjustWidthOfs),null!=h.inputCss&&b.css(h.inputCss),i.html(b),b.focus().change(function(){b.addClass("fancytree-edit-dirty")}).keydown(function(b){switch(b.which){case a.ui.keyCode.ESCAPE:d.editEnd(!1,b);break;case a.ui.keyCode.ENTER:return d.editEnd(!0,b),!1}b.stopPropagation()}).blur(function(a){return d.editEnd(!0,a)}),void h.edit.call(d,{type:"edit"},j))},a.ui.fancytree._FancytreeNodeClass.prototype.editEnd=function(b){var d,f=this,g=this.tree,h=g.ext.edit,i=h.eventData,j=g.options.edit,k=a(".fancytree-title",f.span),l=k.find("input.fancytree-edit-input");return j.trim&&l.val(a.trim(l.val())),d=l.val(),i.dirty=d!==f.title,i.save=b===!1?!1:i.isNew?""!==d:i.dirty&&""!==d,j.beforeClose.call(f,{type:"beforeClose"},i)===!1?!1:i.save&&j.save.call(f,{type:"save"},i)===!1?!1:(l.removeClass("fancytree-edit-dirty").unbind(),a(c).off(".fancytree-edit"),i.save?(f.setTitle(e(d)),f.setFocus()):i.isNew?(f.remove(),f=i.node=null,h.relatedNode.setFocus()):(f.renderTitle(),f.setFocus()),h.eventData=null,h.currentNode=null,h.relatedNode=null,g.widget._bind(),a(g.$container).focus(),i.input=null,j.close.call(f,{type:"close"},i),!0)},a.ui.fancytree._FancytreeNodeClass.prototype.editCreateNode=function(b,c){var d,e=this;return b=b||"child",null==c?c={title:""}:"string"==typeof c?c={title:c}:a.ui.fancytree.assert(a.isPlainObject(c)),"child"!==b||this.isExpanded()||this.hasChildren()===!1?(d=this.addNode(c,b),void d.makeVisible().done(function(){a(d.span).addClass("fancytree-edit-new"),e.tree.ext.edit.relatedNode=e,d.editStart()})):void this.setExpanded().done(function(){e.editCreateNode(b,c)})},a.ui.fancytree._FancytreeClass.prototype.isEditing=function(){return this.ext.edit.currentNode},a.ui.fancytree._FancytreeNodeClass.prototype.isEditing=function(){return this.tree.ext.edit.currentNode===this},a.ui.fancytree.registerExtension({name:"edit",version:"0.2.0",options:{adjustWidthOfs:4,allowEmpty:!1,inputCss:{minWidth:"3em"},triggerCancel:["esc","tab","click"],triggerStart:["f2","shift+click","mac+enter"],trim:!0,beforeClose:a.noop,beforeEdit:a.noop,close:a.noop,edit:a.noop,save:a.noop},currentNode:null,treeInit:function(){this._superApply(arguments),this.$container.addClass("fancytree-ext-edit")},nodeClick:function(b){return a.inArray("shift+click",b.options.edit.triggerStart)>=0&&b.originalEvent.shiftKey?(b.node.editStart(),!1):this._superApply(arguments)},nodeDblclick:function(b){return a.inArray("dblclick",b.options.edit.triggerStart)>=0?(b.node.editStart(),!1):this._superApply(arguments)},nodeKeydown:function(b){switch(b.originalEvent.which){case 113:if(a.inArray("f2",b.options.edit.triggerStart)>=0)return b.node.editStart(),!1;break;case a.ui.keyCode.ENTER:if(a.inArray("mac+enter",b.options.edit.triggerStart)>=0&&d)return b.node.editStart(),!1}return this._superApply(arguments)}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.filter.min.js' */ +!function(a){"use strict";function b(a){return(a+"").replace(/([.?*+\^\$\[\]\\(){}|-])/g,"\\$1")}a.ui.fancytree._FancytreeClass.prototype._applyFilterImpl=function(a,c,d){var e,f,g=0,h="hide"===this.options.filter.mode;return d=!!d&&!c,"string"==typeof a&&(e=b(a),f=new RegExp(".*"+e+".*","i"),a=function(a){return!!f.exec(a.title)}),this.enableFilter=!0,this.lastFilterArgs=arguments,this.$div.addClass("fancytree-ext-filter"),this.$div.addClass(h?"fancytree-ext-filter-hide":"fancytree-ext-filter-dimm"),this.visit(function(a){delete a.match,delete a.subMatch}),this.visit(function(b){return d&&null!=b.children||!a(b)||(g++,b.match=!0,b.visitParents(function(a){a.subMatch=!0}),!c)?void 0:(b.visit(function(a){a.match=!0}),"skip")}),this.render(),g},a.ui.fancytree._FancytreeClass.prototype.filterNodes=function(a,b){return this._applyFilterImpl(a,!1,b)},a.ui.fancytree._FancytreeClass.prototype.applyFilter=function(){return this.warn("Fancytree.applyFilter() is deprecated since 2014-05-10. Use .filterNodes() instead."),this.filterNodes.apply(this,arguments)},a.ui.fancytree._FancytreeClass.prototype.filterBranches=function(a){return this._applyFilterImpl(a,!0,null)},a.ui.fancytree._FancytreeClass.prototype.clearFilter=function(){this.visit(function(a){delete a.match,delete a.subMatch}),this.enableFilter=!1,this.lastFilterArgs=null,this.$div.removeClass("fancytree-ext-filter fancytree-ext-filter-dimm fancytree-ext-filter-hide"),this.render()},a.ui.fancytree.registerExtension({name:"filter",version:"0.3.0",options:{autoApply:!0,mode:"dimm"},treeInit:function(){this._superApply(arguments)},nodeLoadChildren:function(a){return this._superApply(arguments).done(function(){a.tree.enableFilter&&a.tree.lastFilterArgs&&a.options.filter.autoApply&&a.tree._applyFilterImpl.apply(a.tree,a.tree.lastFilterArgs)})},nodeRenderStatus:function(b){var c,d=b.node,e=b.tree,f=a(d[e.statusClassPropName]);return c=this._superApply(arguments),f.length&&e.enableFilter?(f.toggleClass("fancytree-match",!!d.match).toggleClass("fancytree-submatch",!!d.subMatch).toggleClass("fancytree-hide",!(d.match||d.subMatch)),c):c}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.glyph.min.js' */ +!function(a){"use strict";function b(a,b){return a.map[b]}a.ui.fancytree.registerExtension({name:"glyph",version:"0.2.0",options:{map:{checkbox:"icon-check-empty",checkboxSelected:"icon-check",checkboxUnknown:"icon-check icon-muted",error:"icon-exclamation-sign",expanderClosed:"icon-caret-right",expanderLazy:"icon-angle-right",expanderOpen:"icon-caret-down",doc:"icon-file-alt",noExpander:"",docOpen:"icon-file-alt",loading:"icon-refresh icon-spin",folder:"icon-folder-close-alt",folderOpen:"icon-folder-open-alt"}},treeInit:function(a){var b=a.tree;this._superApply(arguments),b.$container.addClass("fancytree-ext-glyph")},nodeRenderStatus:function(c){var d,e,f=c.node,g=a(f.span),h=c.options.glyph,i=h.map;this._superApply(arguments),f.isRoot()||(e=g.children("span.fancytree-expander").get(0),e&&(d=f.isLoading()?"loading":f.expanded?"expanderOpen":f.isUndefined()?"expanderLazy":f.hasChildren()?"expanderClosed":"noExpander",e.className="fancytree-expander "+i[d]),e=f.tr?a("td",f.tr).children("span.fancytree-checkbox").get(0):g.children("span.fancytree-checkbox").get(0),e&&(d=f.selected?"checkboxSelected":f.partsel?"checkboxUnknown":"checkbox",e.className="fancytree-checkbox "+i[d]),e=g.children("span.fancytree-icon").get(0),e&&(d=f.folder?f.expanded?b(h,"folderOpen"):b(h,"folder"):f.expanded?b(h,"docOpen"):b(h,"doc"),e.className="fancytree-icon "+d))},nodeSetStatus:function(c,d){var e,f=c.options.glyph,g=c.node;this._superApply(arguments),e=g.parent?a("span.fancytree-expander",g.span).get(0):a(".fancytree-statusnode-wait, .fancytree-statusnode-error",g[this.nodeContainerAttrName]).find("span.fancytree-expander").get(0),"loading"===d?e.className="fancytree-expander "+b(f,"loading"):"error"===d&&(e.className="fancytree-expander "+b(f,"error"))}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.gridnav.min.js' */ +!function(a){"use strict";function b(b,c){var d,e=c.get(0),f=0;return b.children().each(function(){return this===e?!1:(d=a(this).prop("colspan"),void(f+=d?d:1))}),f}function c(b,c){var d,e=null,f=0;return b.children().each(function(){return f>=c?(e=a(this),!1):(d=a(this).prop("colspan"),void(f+=d?d:1))}),e}function d(a,d){var f,g,h=a.closest("td"),i=null;switch(d){case e.LEFT:i=h.prev();break;case e.RIGHT:i=h.next();break;case e.UP:case e.DOWN:for(f=h.parent(),g=b(f,h);;){if(f=d===e.UP?f.prev():f.next(),!f.length)break;if(!f.is(":hidden")&&(i=c(f,g),i&&i.find(":input").length))break}}return i}var e=a.ui.keyCode,f={text:[e.UP,e.DOWN],checkbox:[e.UP,e.DOWN,e.LEFT,e.RIGHT],radiobutton:[e.UP,e.DOWN,e.LEFT,e.RIGHT],"select-one":[e.LEFT,e.RIGHT],"select-multiple":[e.LEFT,e.RIGHT]};a.ui.fancytree.registerExtension({name:"gridnav",version:"0.0.1",options:{autofocusInput:!1,handleCursorKeys:!0},treeInit:function(b){this._requireExtension("table",!0,!0),this._superApply(arguments),this.$container.addClass("fancytree-ext-gridnav"),this.$container.on("focusin",function(c){var d,e=a.ui.fancytree.getNode(c.target);e&&!e.isActive()&&(d=b.tree._makeHookContext(e,c),b.tree._callHook("nodeSetActive",d,!0))})},nodeSetActive:function(b,c){var d,e=b.options.gridnav,f=b.node,g=b.originalEvent||{},h=a(g.target).is(":input");c=c!==!1,this._superApply(arguments),c&&(b.options.titlesTabbable?(h||(a(f.span).find("span.fancytree-title").focus(),f.setFocus()),b.tree.$container.attr("tabindex","-1")):e.autofocusInput&&!h&&(d=a(f.tr||f.span),d.find(":input:enabled:first").focus()))},nodeKeydown:function(b){var c,e,g,h=b.options.gridnav,i=b.originalEvent,j=a(i.target);return c=j.is(":input:enabled")?j.prop("type"):null,c&&h.handleCursorKeys?(e=f[c],e&&a.inArray(i.which,e)>=0&&(g=d(j,i.which),g&&g.length)?(g.find(":input:enabled").focus(),!1):!0):this._superApply(arguments)}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.persist.min.js' */ +!function(a,b,c,d){"use strict";function e(b,c,d,f,g){var i,j,k,l,m=!1,n=[],o=[];for(d=d||[],g=g||a.Deferred(),i=0,k=d.length;k>i;i++)j=d[i],l=b.getNodeByKey(j),l?f&&l.isUndefined()?(m=!0,b.debug("_loadLazyNodes: "+l+" is lazy: loading..."),n.push("expand"===f?l.setExpanded():l.load())):(b.debug("_loadLazyNodes: "+l+" already loaded."),l.setExpanded()):(o.push(j),b.debug("_loadLazyNodes: "+l+" was not yet found."));return a.when.apply(a,n).always(function(){if(m&&o.length>0)e(b,c,o,f,g);else{if(o.length)for(b.warn("_loadLazyNodes: could not load those keys: ",o),i=0,k=o.length;k>i;i++)j=d[i],c._appendKey(h,d[i],!1);g.resolve()}}),g}var f=a.ui.fancytree.assert,g="active",h="expanded",i="focus",j="selected";a.ui.fancytree._FancytreeClass.prototype.clearCookies=function(a){var b=this.ext.persist,c=b.cookiePrefix;a=a||"active expanded focus selected",a.indexOf(g)>=0&&b._data(c+g,null),a.indexOf(h)>=0&&b._data(c+h,null),a.indexOf(i)>=0&&b._data(c+i,null),a.indexOf(j)>=0&&b._data(c+j,null)},a.ui.fancytree._FancytreeClass.prototype.getPersistData=function(){var a=this.ext.persist,b=a.cookiePrefix,c=a.cookieDelimiter,d={};return d[g]=a._data(b+g),d[h]=(a._data(b+h)||"").split(c),d[j]=(a._data(b+j)||"").split(c),d[i]=a._data(b+i),d},a.ui.fancytree.registerExtension({name:"persist",version:"0.3.0",options:{cookieDelimiter:"~",cookiePrefix:d,cookie:{raw:!1,expires:"",path:"",domain:"",secure:!1},expandLazy:!1,overrideSource:!0,store:"auto",types:"active expanded focus selected"},_data:function(b,c){var e=this._local.localStorage;return c===d?e?e.getItem(b):a.cookie(b):void(null===c?e?e.removeItem(b):a.removeCookie(b):e?e.setItem(b,c):a.cookie(b,c,this.options.persist.cookie))},_appendKey:function(b,c,d){c=""+c;var e=this._local,f=this.options.persist,g=f.cookieDelimiter,h=e.cookiePrefix+b,i=e._data(h),j=i?i.split(g):[],k=a.inArray(c,j);k>=0&&j.splice(k,1),d&&j.push(c),e._data(h,j.join(g))},treeInit:function(c){var k=c.tree,l=c.options,m=this._local,n=this.options.persist;return f("localStore"===n.store||a.cookie,"Missing required plugin for 'persist' extension: jquery.cookie.js"),m.cookiePrefix=n.cookiePrefix||"fancytree-"+k._id+"-",m.storeActive=n.types.indexOf(g)>=0,m.storeExpanded=n.types.indexOf(h)>=0,m.storeSelected=n.types.indexOf(j)>=0,m.storeFocus=n.types.indexOf(i)>=0,m.localStorage="cookie"!==n.store&&b.localStorage?"local"===n.store?b.localStorage:b.sessionStorage:null,k.$div.bind("fancytreeinit",function(){var b,c,f,o,p,q=m._data(m.cookiePrefix+i);b=m._data(m.cookiePrefix+h),o=b&&b.split(n.cookieDelimiter),c=m.storeExpanded?e(k,m,o,n.expandLazy?"expand":!1,null):(new a.Deferred).resolve(),c.done(function(){if(m.storeSelected){if(b=m._data(m.cookiePrefix+j))for(o=b.split(n.cookieDelimiter),f=0;f<o.length;f++)p=k.getNodeByKey(o[f]),p?(p.selected===d||n.overrideSource&&p.selected===!1)&&(p.selected=!0,p.renderStatus()):m._appendKey(j,o[f],!1);3===k.options.selectMode&&k.visit(function(a){return a.selected?(a.fixSelection3AfterClick(),"skip"):void 0})}m.storeActive&&(b=m._data(m.cookiePrefix+g),!b||!l.persist.overrideSource&&k.activeNode||(p=k.getNodeByKey(b),p&&(p.debug("persist: set active",b),p.setActive(!0,{noFocus:!0})))),m.storeFocus&&q&&(p=k.getNodeByKey(q),p&&(k.options.titlesTabbable?a(p.span).find(".fancytree-title").focus():a(k.$container).focus())),k._triggerTreeEvent("restore",null,{})})}),this._superApply(arguments)},nodeSetActive:function(a,b){var c,d=this._local;return b=b!==!1,c=this._superApply(arguments),d.storeActive&&d._data(d.cookiePrefix+g,this.activeNode?this.activeNode.key:null),c},nodeSetExpanded:function(a,b){var c,d=a.node,e=this._local;return b=b!==!1,c=this._superApply(arguments),e.storeExpanded&&e._appendKey(h,d.key,b),c},nodeSetFocus:function(a,b){var c,d=this._local;return b=b!==!1,c=this._superApply(arguments),d.storeFocus&&d._data(d.cookiePrefix+i,this.focusNode?this.focusNode.key:null),c},nodeSetSelected:function(b,c){var d,e,f=b.tree,g=b.node,h=this._local;return c=c!==!1,d=this._superApply(arguments),h.storeSelected&&(3===f.options.selectMode?(e=a.map(f.getSelectedNodes(!0),function(a){return a.key}),e=e.join(b.options.persist.cookieDelimiter),h._data(h.cookiePrefix+j,e)):h._appendKey(j,g.key,c)),d}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.table.min.js' */ +!function(a,b,c){"use strict";function d(b,c){c=c||"",b||a.error("Assertion failed "+c)}function e(a,b){a.parentNode.insertBefore(b,a.nextSibling)}function f(a,b){a.visit(function(a){var c=a.tr;return c&&(c.style.display=a.hide||!b?"none":""),a.expanded?void 0:"skip"})}function g(b){var c,e,f,g=b.parent,h=g?g.children:null;if(h&&h.length>1&&h[0]!==b)for(c=a.inArray(b,h),f=h[c-1],d(f.tr);f.children&&(e=f.children[f.children.length-1],e.tr);)f=e;else f=g;return f}a.ui.fancytree.registerExtension({name:"table",version:"0.2.1",options:{checkboxColumnIdx:null,customStatus:!1,indentation:16,nodeColumnIdx:0},treeInit:function(b){var d,e,f,g=b.tree,h=g.widget.element;for(h.addClass("fancytree-container fancytree-ext-table"),g.tbody=h.find("> tbody")[0],g.columnCount=a("thead >tr >th",h).length,a(g.tbody).empty(),g.rowFragment=c.createDocumentFragment(),e=a("<tr />"),f="",b.options.aria&&(e.attr("role","row"),f=" role='gridcell'"),d=0;d<g.columnCount;d++)e.append(b.options.table.nodeColumnIdx===d?"<td"+f+"><span class='fancytree-node' /></td>":"<td"+f+" />");g.rowFragment.appendChild(e.get(0)),g.statusClassPropName="tr",g.ariaPropName="tr",this.nodeContainerAttrName="tr",this._superApply(arguments),a(g.rootNode.ul).remove(),g.rootNode.ul=null,g.$container=h,this.$container.attr("tabindex",this.options.tabbable?"0":"-1"),this.options.aria&&g.$container.attr("role","treegrid").attr("aria-readonly",!0)},nodeRemoveChildMarkup:function(b){var c=b.node;c.visit(function(b){b.tr&&(a(b.tr).remove(),b.tr=null)})},nodeRemoveMarkup:function(b){var c=b.node;c.tr&&(a(c.tr).remove(),c.tr=null),this.nodeRemoveChildMarkup(b)},nodeRender:function(b,c,h,i,j){var k,l,m,n,o,p,q,r,s=b.tree,t=b.node,u=b.options,v=!t.parent;if(j||(b.hasCollapsedParents=t.parent&&!t.parent.expanded),!v)if(t.tr)c?this.nodeRenderTitle(b):this.nodeRenderStatus(b);else{if(b.hasCollapsedParents)return void t.debug("nodeRender ignored due to unrendered parent");o=s.rowFragment.firstChild.cloneNode(!0),p=g(t),d(p),i===!0&&j?o.style.display="none":h&&b.hasCollapsedParents&&(o.style.display="none"),p.tr?e(p.tr,o):(d(!p.parent,"prev. row must have a tr, or is system root"),s.tbody.appendChild(o)),t.tr=o,t.key&&u.generateIds&&(t.tr.id=u.idPrefix+t.key),t.tr.ftnode=t,u.aria&&a(t.tr).attr("aria-labelledby","ftal_"+t.key),t.span=a("span.fancytree-node",t.tr).get(0),this.nodeRenderTitle(b),u.createNode&&u.createNode.call(s,{type:"createNode"},b)}if(u.renderNode&&u.renderNode.call(s,{type:"renderNode"},b),k=t.children,k&&(v||h||t.expanded))for(m=0,n=k.length;n>m;m++)r=a.extend({},b,{node:k[m]}),r.hasCollapsedParents=r.hasCollapsedParents||!t.expanded,this.nodeRender(r,c,h,i,!0);k&&!j&&(q=t.tr||null,l=s.tbody.firstChild,t.visit(function(a){if(a.tr){if(a.parent.expanded||"none"===a.tr.style.display||(a.tr.style.display="none",f(a,!1)),a.tr.previousSibling!==q){t.debug("_fixOrder: mismatch at node: "+a);var b=q?q.nextSibling:l;s.tbody.insertBefore(a.tr,b)}q=a.tr}}))},nodeRenderTitle:function(b){var c,d=b.node,e=b.options;this._superApply(arguments),e.checkbox&&null!=e.table.checkboxColumnIdx&&(c=a("span.fancytree-checkbox",d.span).detach(),a(d.tr).find("td").eq(+e.table.checkboxColumnIdx).html(c)),d.isRoot()||this.nodeRenderStatus(b),!e.table.customStatus&&d.isStatusNode()||e.renderColumns&&e.renderColumns.call(b.tree,{type:"renderColumns"},b)},nodeRenderStatus:function(b){var c,d=b.node,e=b.options;this._superApply(arguments),a(d.tr).removeClass("fancytree-node"),c=(d.getLevel()-1)*e.table.indentation,a(d.span).css({marginLeft:c+"px"})},nodeSetExpanded:function(b,c,d){function e(a){c=c!==!1,f(b.node,c),a?c&&b.options.autoScroll&&!d.noAnimation&&b.node.hasChildren()?b.node.getLastChild().scrollIntoView(!0,{topNode:b.node}).always(function(){d.noEvents||b.tree._triggerNodeEvent(c?"expand":"collapse",b),g.resolveWith(b.node)}):(d.noEvents||b.tree._triggerNodeEvent(c?"expand":"collapse",b),g.resolveWith(b.node)):(d.noEvents||b.tree._triggerNodeEvent(c?"expand":"collapse",b),g.rejectWith(b.node))}var g=new a.Deferred,h=a.extend({},d,{noEvents:!0,noAnimation:!0});return d=d||{},this._super(b,c,h).done(function(){e(!0)}).fail(function(){e(!1)}),g.promise()},nodeSetStatus:function(b,c){if("ok"===c){var d=b.node,e=d.children?d.children[0]:null;e&&e.isStatusNode()&&a(e.tr).remove()}return this._superApply(arguments)},treeClear:function(){return this.nodeRemoveChildMarkup(this._makeHookContext(this.rootNode)),this._superApply(arguments)}})}(jQuery,window,document); + +/*! Extension 'jquery.fancytree.themeroller.min.js' */ +!function(a){"use strict";a.ui.fancytree.registerExtension({name:"themeroller",version:"0.0.1",options:{activeClass:"ui-state-active",foccusClass:"ui-state-focus",hoverClass:"ui-state-hover",selectedClass:"ui-state-highlight"},treeInit:function(b){this._superApply(arguments);var c=b.widget.element;"TABLE"===c[0].nodeName?(c.addClass("ui-widget ui-corner-all"),c.find(">thead tr").addClass("ui-widget-header"),c.find(">tbody").addClass("ui-widget-conent")):c.addClass("ui-widget ui-widget-content ui-corner-all"),c.delegate(".fancytree-node","mouseenter mouseleave",function(b){var c=a.ui.fancytree.getNode(b.target),d="mouseenter"===b.type;c.debug("hover: "+d),a(c.span).toggleClass("ui-state-hover ui-corner-all",d)})},treeDestroy:function(a){this._superApply(arguments),a.widget.element.removeClass("ui-widget ui-widget-content ui-corner-all")},nodeRenderStatus:function(b){var c=b.node,d=a(c.span);this._superApply(arguments),d.toggleClass("ui-state-active",c.isActive()),d.toggleClass("ui-state-focus",c.hasFocus()),d.toggleClass("ui-state-highlight",c.isSelected())}})}(jQuery,window,document); +})); diff --git a/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/icons.gif b/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/icons.gif new file mode 100644 index 0000000000000000000000000000000000000000..65719ccc28fb0b78fbed90cb04341280b4cd6ac0 GIT binary patch literal 5492 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 literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/loading.gif b/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..ef88497ccc2f6c2a3a0c5e41f3cbfc7a18ff5329 GIT binary patch literal 3234 zcmds%i#ybL8^(WQ#u$ej2Sa3rp)m%7sivB(F%FHhDI_7okYgsR<69dujU3CNB<+^N ztV6YhRM@hNV-6*UQmK_F*$z@kwt8OewfkP}b@dm#-#_5{+@Je?o_n2(Gjk<h9Z^T# zBZzYec$I<wIS4urVKoqQ34~W*dmZd(fW24Yz;BS;1QHpfwZf4O$nAt<U2w7&PThc_ zn^4>b(tfyb2deHs^)Ot%4-F6C>O*KAg^tJ2H37X(pzkU4KZDy-F#HGHdjY?{g3(v- zXc{JF;E#9kViu;~!^{VG|0m4-34eY9S1EXw!TJi=cosscAgUH(FT;PX!Tv@_ZGrqQ zDCmaM3!`sBX+M<rL**cxzXP@Rpne3dK7f`-(Eb=Y$Dw-y2A;v4g`v-3<RwhLg_pDN zb{@E;u%Qw*pNGKn5MBe(wGe*=gmtjzD(t%k;%3NLAZ>@A`=Mgt=i5+y7cSj{Umw7= zhah_d*T><;6S(yhZcW1d7x3^UjJ<{@Z{XQmcs&R2=7CoZyb9n~!w-#+cO8yihZEg! z>Ly&g3$=HlZ43sdVB`fnnSrSVN$=s!2l((2+@#=p1`_IE*RPNwgN!yf+z!XPpz(L; zn}oa1Vf;0`S}<x3X6Ir46NFbo^d(4XfucSrAArGUFg6X7Z(w>3<~~BeFA#MR3VWce zA7rD@`4}F)f~j}lT@HQ=u3mue>)}8n{B#3aA3^^l3{AoFSqQBHK{d3FL3$fh4a1fT zaIhJ!+=uZQ*s`!2)sWc^X9wZ8-(mhEApb9q1j?RHJ{uhDy`5~W=xEde7wNO52VW3Q z4BbO?OW=PW6&IDjCwhiQhed|(<P#~ocI~o?jpqxZwnfBSZ3|B{M@SzqC?$lB(7u@R z<*pFyNp^vE>Qo5r#{r?D8(%+7T%43$R8Zc@xs}AiA4G8&J}&xdYJa?2AEhD^YhK>& z=<Z%np`OH8sz%(y(L<rh#v0l*F`bG=beCxAS!Y?R$Y~ql^|LtU6dGBZV0k*0ZlR~U zTWoDvPABOurtXQO*3b;}4JlR}YZ{e8&F4@J8%d@&OwBsnEy+uaNF)=}ez9e7d$XJU z-+Ga+^eU7mAtDjQ$brM9h%*pR$5ktpnJbjp9+{N2YO1T&uv8Tkl-<M@_N%`m(yXmL zotVp*>4-CneKEt0$zWyKuW`*3JD``lyR$honaD%I&cVgrsYlGTWx1vfA=XSAmOIDE zYlwoTbG)1#>oSdO?4+(vM%^;&b@n1JqLHgdu*%*?V`)w6UD*`As3c8msfDUl!uHVX znkkeYkDi?sNu0%*a;R@<ulS-p&Q&0Yh+ELU%{h3LTHt22ko1f={_3EhEy1e;HmOC6 zw}l3WxW-!})bK$6z~hm+p~o|#12zU{h4H1CB7xtgn3ym@e6xt^?<<H3i|7__W&}k$ zM-C#^0ULtiA|kuG<NVf##z$_Y4)S?E(%8tTiHxlb)GASYbd=f1Xs%padYb*`+f`AI z+uM}2{UT#Gzpe6EtR3(7GfL-qTgD2je0jOQ#iPD59#@B;arn7ItvM#-k1Bx#L_L)i zOc|+m;P)7%9AJ(&i??!@DD5y9*<?4}n?nklyQ(o~cJL?cPCS-q<9yR8#cYb!q&3>B z@ZElbD$BOq-e|26r%v6q&t9&GI7ineRCuCT`)9d7>8IWp677@o_+(d(DCnBaA%&|P zRpoLI+@90u7T!FD+Ep?C`pwp;B=!$8c=aSAWoT{EL(F_j2=XHnJB!=@*x1_$g<uD5 zSnoU}EWR!l^Nl2MwFqhfrXnZRDa&9{AP&jJ+3uO~M?#xZWs)O0dOXK=T&op}#?YVS zU~<*6h>D3gGVgds7CUu!t2(>XN)5kEP&*mgtCp&{Y;S9YqqGpCr8hrX(aMz~#yd9A zrA0Rjb9Rq*qAPiMrCdY9hGcTC$-0o3TvBZaS-OrIV=J@Ab+WlR#>GAN1>9o&lv7HB z7GkVw10#|a;xiy4+KU7|70nLQGH&L~^rWp6(~|Tpkc(eHaOPS@YhoD-AR$^O)w$`J z8g^y}Ws>Z<K&9qe?m2Yb_FBC<#erPYxaAt-Chcwo83*Wm(E^B>%CSsFY+hAaliM-c zr{uvWN4$~?X)kcqE(2|)TbAJOVq7L}d2Fe}M@0^mml<yEc|QI<{<=uP<hVhBW{KHp zOC}vRZlahjrJJw#WX@4kzL!iglP4r5X^x;3>av4UqYg>UH$=M2#=-@?9yH5M`r<S` z`)>}pueYlnk;maDIr58_mp)Vpq>M_GcqX&t1rv_QB-YNqXteQsa#h1PzxY>#4pLTF zV;cDbd>my3^+5&qx_4Uvix}E3ps)ueEUNy?@egK4ba~r`F%v6=IC=7ErVSz8Moo>( zK~xBBK1nCNPR(W$)QMgj)zv6MiF)}4%~LU~l>`%^2g(!M-m|Y-?z$Mu%2yf|haf0< zH6p{is%bz!C3ZKF;yub1VRh?f_End)NR$nS=_<HyrE+B<6@v<w4Hh0&SSr4*(pPKw z(tH{}PsmpmtKOyYYtx66Bqx{G4>PJr7Iwq{oQg;~Ce!Ao(@<4Xyt$pSLJg_pjPDXc zS>ZT-xP*I3t1@&%cw)ePiC?9l$ap25okKjAa&*<unW=OZn|zNzmriLK?P-`T;zd5; zEN8E;)a=CiF7j~-kPKo<It~+!<gNI^siR__H9MKRN5#D|Gq%nM`x5bxs&UYvQ|#QW zsd~jq=zs41>%ztT#X{(mCv%grRE#%A5fN{5&YI8jCh2e7=!ehj#O5h-(Kf!xwx(H} z6$SlAg(UBF$i_$=xun)fmBlF+N)G0jPaip9m(AeT+onHlvEw@LIKinj_A+&HP27G- z@-xp)zaL+jJ8^`^HDH9uj<&gKl$yy>x1)<Pv|UXFhx>&jvm{<%jnIB<M}#6hm{Fze zZ+s!&FsO0&EuOhMPg2^%8kS8YAGWH(b}!o?#T9m-|HtyL4!iiJ!#da9UaEuEQjNv% z5d@VL%oa)Mhy_|WsuEJfG0r%wtgJYBwBx37vbE2gjrsJAB#U#@#_5aBPKcIdJhhUN zEpN2Onu#w6%iD^qG4bi7B9ElJH7*}%anTHRAvxwPIn}q;nC!>>$Vi|oq}@7aMCmGY z*y`b=y|-PeG1=isTYXL)n^YUoLm=-(pR0e2$jVuv0`n(*zD4OayNDyjLZ(ZI<cFpo zxC2b~KiBfFO#Z4b|4{B3pG$;#LT9$e8GSoJt2)C3=a8I<?<?>X`^o9s_RtK5TfMU| z4vczXbGv)SF?6!}`ld<aq+^8vNJv<!y531NeB90_Hy5vE%YWuSF3A`9m?YQmODpq> zt$1-Y=C3<4iwz5N8>-qOql_J0azEF%a-U`^R1OahCMq5bL=H4OM-rk08Ts6KRe=`S z_jrIHGn>T0I{K#^$i$#Dr8;Amqut2$K4Y(&zFA+_zSLJ;#BozMhubQFxS}j81K({A za*fjt%OueWhRmc=l-NQn=VNbIwaAdB!el;bJL^FR^cGfX;IQk?pHS%?S(S}tm#tFn zq8k*HEwV-;5?%;x6Nwje5axLQP+~}i&Q)gLhlE<H@={By7gd-`=GIH&0+`i_Pjfde zcSbdx!I%y7>BQWo%U2m^o+m|jH3)OfveM2kIuwX&Y3?y)5c{O&tFz@(gB*4?+lnKy RGR}AoOL=)|H48+m{|ju`J$C>A literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.css b/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.css new file mode 100644 index 0000000..71bde0e --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.css @@ -0,0 +1,595 @@ +/*! + * Fancytree "Win7" skin. + * + * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from + * the LESS templates. + */ +/******************************************************************************* + * Common Styles for Fancytree Skins. + * + * This section is automatically generated from the `skin-common.less` template. + ******************************************************************************/ +/*------------------------------------------------------------------------------ + * Helpers + *----------------------------------------------------------------------------*/ +.ui-helper-hidden { + display: none; +} +/*------------------------------------------------------------------------------ + * Container and UL / LI + *----------------------------------------------------------------------------*/ +ul.fancytree-container { + font-family: tahoma, arial, helvetica; + font-size: 10pt; + white-space: nowrap; + padding: 3px; + margin: 0; + background-color: white; + border: 1px dotted gray; + overflow: auto; + min-height: 0%; + position: relative; +} +ul.fancytree-container ul { + padding: 0 0 0 16px; + margin: 0; +} +ul.fancytree-container li { + list-style-image: none; + list-style-position: outside; + list-style-type: none; + -moz-background-clip: border; + -moz-background-inline-policy: continuous; + -moz-background-origin: padding; + background-attachment: scroll; + background-color: transparent; + background-position: 0px 0px; + background-repeat: repeat-y; + background-image: none; + margin: 0; +} +ul.fancytree-container li.fancytree-lastsib { + background-image: none; +} +ul.fancytree-no-connector > li { + background-image: none; +} +.ui-fancytree-disabled ul.fancytree-container { + opacity: 0.5; + background-color: silver; +} +/*------------------------------------------------------------------------------ + * Common icon definitions + *----------------------------------------------------------------------------*/ +span.fancytree-empty, +span.fancytree-vline, +span.fancytree-expander, +span.fancytree-icon, +span.fancytree-checkbox, +span.fancytree-radio, +span.fancytree-drag-helper-img, +#fancytree-drop-marker { + width: 16px; + height: 16px; + display: inline-block; + vertical-align: top; + background-repeat: no-repeat; + background-position: left; + background-image: url("icons.gif"); + background-position: 0px 0px; +} +span.fancytree-icon, +span.fancytree-checkbox, +span.fancytree-expander, +span.fancytree-radio, +span.fancytree-custom-icon { + margin-top: 2px; +} +/* Used by iconclass option */ +span.fancytree-custom-icon { + display: inline-block; +} +/* Used by 'icon' node option: */ +img.fancytree-icon { + width: 16px; + height: 16px; + margin-left: 3px; + margin-top: 2px; + vertical-align: top; + border-style: none; +} +/*------------------------------------------------------------------------------ + * Expander icon + * + * Note: IE6 doesn't correctly evaluate multiples class names, + * so we create combined class names that can be used in the CSS. + * + * Prefix: fancytree-exp- + * 1st character: 'e': expanded, 'c': collapsed, 'n': no children + * 2nd character (optional): 'd': lazy (Delayed) + * 3rd character (optional): 'l': Last sibling + *----------------------------------------------------------------------------*/ +span.fancytree-expander { + cursor: pointer; +} +.fancytree-exp-n span.fancytree-expander, +.fancytree-exp-nl span.fancytree-expander { + background-image: none; + cursor: default; +} +.fancytree-exp-n span.fancytree-expander, +.fancytree-exp-n span.fancytree-expander:hover { + background-position: 0px -64px; +} +.fancytree-exp-nl span.fancytree-expander, +.fancytree-exp-nl span.fancytree-expander:hover { + background-position: -16px -64px; +} +.fancytree-exp-c span.fancytree-expander { + background-position: 0px -80px; +} +.fancytree-exp-c span.fancytree-expander:hover { + background-position: -16px -80px; +} +.fancytree-exp-cl span.fancytree-expander { + background-position: 0px -96px; +} +.fancytree-exp-cl span.fancytree-expander:hover { + background-position: -16px -96px; +} +.fancytree-exp-cd span.fancytree-expander { + background-position: -64px -80px; +} +.fancytree-exp-cd span.fancytree-expander:hover { + background-position: -80px -80px; +} +.fancytree-exp-cdl span.fancytree-expander { + background-position: -64px -96px; +} +.fancytree-exp-cdl span.fancytree-expander:hover { + background-position: -80px -96px; +} +.fancytree-exp-e span.fancytree-expander, +.fancytree-exp-ed span.fancytree-expander { + background-position: -32px -80px; +} +.fancytree-exp-e span.fancytree-expander:hover, +.fancytree-exp-ed span.fancytree-expander:hover { + background-position: -48px -80px; +} +.fancytree-exp-el span.fancytree-expander, +.fancytree-exp-edl span.fancytree-expander { + background-position: -32px -96px; +} +.fancytree-exp-el span.fancytree-expander:hover, +.fancytree-exp-edl span.fancytree-expander:hover { + background-position: -48px -96px; +} +/*------------------------------------------------------------------------------ + * Checkbox icon + *----------------------------------------------------------------------------*/ +span.fancytree-checkbox { + margin-left: 3px; + background-position: 0px -32px; +} +span.fancytree-checkbox:hover { + background-position: -16px -32px; +} +.fancytree-partsel span.fancytree-checkbox { + background-position: -64px -32px; +} +.fancytree-partsel span.fancytree-checkbox:hover { + background-position: -80px -32px; +} +.fancytree-selected span.fancytree-checkbox { + background-position: -32px -32px; +} +.fancytree-selected span.fancytree-checkbox:hover { + background-position: -48px -32px; +} +.fancytree-unselectable span.fancytree-checkbox, +.fancytree-unselectable span.fancytree-checkbox:hover { + opacity: 0.4; + filter: alpha(opacity=40); + background-position: 0px -32px; +} +/*------------------------------------------------------------------------------ + * Radiobutton icon + * This is a customization, that may be activated by overriding the 'checkbox' + * class name as 'fancytree-radio' in the tree options. + *----------------------------------------------------------------------------*/ +.fancytree-radio span.fancytree-checkbox { + background-position: 0px -48px; +} +.fancytree-radio span.fancytree-checkbox:hover { + background-position: -16px -48px; +} +.fancytree-radio .fancytree-partsel span.fancytree-checkbox { + background-position: -64px -48px; +} +.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover { + background-position: -80px -48px; +} +.fancytree-radio .fancytree-selected span.fancytree-checkbox { + background-position: -32px -48px; +} +.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover { + background-position: -48px -48px; +} +.fancytree-radio .fancytree-unselectable span.fancytree-checkbox, +.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover { + background-position: 0px -48px; +} +/*------------------------------------------------------------------------------ + * Node type icon + * Note: IE6 doesn't correctly evaluate multiples class names, + * so we create combined class names that can be used in the CSS. + * + * Prefix: fancytree-ico- + * 1st character: 'e': expanded, 'c': collapsed + * 2nd character (optional): 'f': folder + *----------------------------------------------------------------------------*/ +span.fancytree-icon { + margin-left: 3px; + background-position: 0px 0px; +} +/* Documents */ +.fancytree-ico-c span.fancytree-icon:hover { + background-position: -16px 0px; +} +.fancytree-has-children.fancytree-ico-c span.fancytree-icon { + background-position: -32px 0px; +} +.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover { + background-position: -48px 0px; +} +.fancytree-ico-e span.fancytree-icon { + background-position: -64px 0px; +} +.fancytree-ico-e span.fancytree-icon:hover { + background-position: -80px 0px; +} +/* Folders */ +.fancytree-ico-cf span.fancytree-icon { + background-position: 0px -16px; +} +.fancytree-ico-cf span.fancytree-icon:hover { + background-position: -16px -16px; +} +.fancytree-has-children.fancytree-ico-cf span.fancytree-icon { + background-position: -32px -16px; +} +.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover { + background-position: -48px -16px; +} +.fancytree-ico-ef span.fancytree-icon { + background-position: -64px -16px; +} +.fancytree-ico-ef span.fancytree-icon:hover { + background-position: -80px -16px; +} +.fancytree-loading span.fancytree-expander, +.fancytree-loading span.fancytree-expander:hover, +.fancytree-statusnode-wait span.fancytree-icon, +.fancytree-statusnode-wait span.fancytree-icon:hover { + background-image: url("loading.gif"); + background-position: 0px 0px; +} +/* Status node icons */ +.fancytree-statusnode-error span.fancytree-icon, +.fancytree-statusnode-error span.fancytree-icon:hover { + background-position: 0px -112px; +} +/*------------------------------------------------------------------------------ + * Node titles and highlighting + *----------------------------------------------------------------------------*/ +span.fancytree-node { + /* See #117 */ + display: inherit; + width: 100%; + margin-top: 1px; + min-height: 20px; +} +span.fancytree-title { + color: black; + cursor: pointer; + display: inline-block; + vertical-align: top; + min-height: 20px; + padding: 0 3px 0 3px; + margin: 0px 0 0 3px; + border: 1px solid transparent; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + -o-border-radius: 3px; + border-radius: 3px; +} +span.fancytree-node.fancytree-error span.fancytree-title { + color: red; +} +/*------------------------------------------------------------------------------ + * Drag'n'drop support + *----------------------------------------------------------------------------*/ +div.fancytree-drag-helper a { + border: 1px solid gray; + background-color: white; + padding-left: 5px; + padding-right: 5px; + opacity: 0.8; +} +div.fancytree-drag-helper.fancytree-drop-reject { + border-color: red; +} +div.fancytree-drop-accept span.fancytree-drag-helper-img { + background-position: -32px -112px; +} +div.fancytree-drop-reject span.fancytree-drag-helper-img { + background-position: -16px -112px; +} +/*** Drop marker icon *********************************************************/ +#fancytree-drop-marker { + width: 32px; + position: absolute; + background-position: 0px -128px; + margin: 0; +} +#fancytree-drop-marker.fancytree-drop-after, +#fancytree-drop-marker.fancytree-drop-before { + width: 64px; + background-position: 0px -144px; +} +#fancytree-drop-marker.fancytree-drop-copy { + background-position: -64px -128px; +} +#fancytree-drop-marker.fancytree-drop-move { + background-position: -32px -128px; +} +/*** Source node while dragging ***********************************************/ +span.fancytree-drag-source { + background-color: #e0e0e0; +} +span.fancytree-drag-source span.fancytree.title { + color: gray; +} +/*** Target node while dragging cursor is over it *****************************/ +span.fancytree-drop-target.fancytree-drop-accept a { + background-color: #3169C6 !important; + color: white !important; + /* @ IE6 */ + text-decoration: none; +} +/*------------------------------------------------------------------------------ + * 'table' extension + *----------------------------------------------------------------------------*/ +table.fancytree-ext-table { + border-collapse: collapse; +} +table.fancytree-ext-table span.fancytree-node { + display: inline-block; +} +/*------------------------------------------------------------------------------ + * 'columnview' extension + *----------------------------------------------------------------------------*/ +table.fancytree-ext-columnview tbody tr td { + position: relative; + border: 1px solid gray; + vertical-align: top; + overflow: auto; +} +table.fancytree-ext-columnview tbody tr td > ul { + padding: 0; +} +table.fancytree-ext-columnview tbody tr td > ul li { + list-style-image: none; + list-style-position: outside; + list-style-type: none; + -moz-background-clip: border; + -moz-background-inline-policy: continuous; + -moz-background-origin: padding; + background-attachment: scroll; + background-color: transparent; + background-position: 0px 0px; + background-repeat: repeat-y; + background-image: none; + /* no v-lines */ + margin: 0; +} +table.fancytree-ext-columnview span.fancytree-node { + position: relative; + /* allow positioning of embedded spans */ + display: inline-block; +} +table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded { + background-color: #CBE8F6; +} +table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right { + position: absolute; + right: 3px; + background-position: 0px -80px; +} +table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover { + background-position: -16px -80px; +} +/*------------------------------------------------------------------------------ + * 'filter' extension + *----------------------------------------------------------------------------*/ +.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title { + color: silver; + font-weight: lighter; +} +.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title, +.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title { + color: black; + font-weight: normal; +} +.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title, +.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title { + color: black; + font-weight: bold; +} +.fancytree-ext-filter-hide tr.fancytree-hide, +.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide { + display: none; +} +.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title, +.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title { + color: silver; + font-weight: lighter; +} +.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title, +.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title { + color: black; + font-weight: normal; +} +/*------------------------------------------------------------------------------ + * 'wide' extension + *----------------------------------------------------------------------------*/ +ul.fancytree-ext-wide { + position: relative; + min-width: 100%; + z-index: 2; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +ul.fancytree-ext-wide span.fancytree-node > span { + position: relative; + z-index: 2; +} +ul.fancytree-ext-wide span.fancytree-node span.fancytree-title { + position: absolute; + z-index: 1; + left: 0px; + width: 100%; + margin-left: 0; + margin-right: 0; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +/******************************************************************************* + * Styles specific to this skin. + * + * This section is automatically generated from the `ui-fancytree.less` template. + ******************************************************************************/ +/******************************************************************************* + * Node titles + */ +span.fancytree-active .fancytree-title, +span.fancytree-selected .fancytree-title { + border-color: #d9d9d9; + background: #e5e5e5; + color: inherit; + background: -moz-linear-gradient(top, #fafafb 0%, #e5e5e5 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fafafb), color-stop(100%, #e5e5e5)); + background: -webkit-linear-gradient(top, #fafafb 0%, #e5e5e5 100%); + background: -o-linear-gradient(top, #fafafb 0%, #e5e5e5 100%); + background: -ms-linear-gradient(top, #fafafb 0%, #e5e5e5 100%); + background: linear-gradient(to bottom, #fafafb 0%, #e5e5e5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fafafb', endColorstr='#e5e5e5', GradientType=0); +} +span.fancytree-selected .fancytree-title { + font-style: italic; +} +.fancytree-treefocus span.fancytree-active .fancytree-title, +.fancytree-treefocus span.fancytree-selected .fancytree-title { + border-color: #99defd; + background: #f6fbfd; + color: inherit; + background: -moz-linear-gradient(top, #f6fbfd 0%, #d5effc 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f6fbfd), color-stop(100%, #d5effc)); + background: -webkit-linear-gradient(top, #f6fbfd 0%, #d5effc 100%); + background: -o-linear-gradient(top, #f6fbfd 0%, #d5effc 100%); + background: -ms-linear-gradient(top, #f6fbfd 0%, #d5effc 100%); + background: linear-gradient(to bottom, #f6fbfd 0%, #d5effc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6fbfd', endColorstr='#d5effc', GradientType=0); +} +.fancytree-treefocus span.fancytree-focused span.fancytree-title { + border: 1px solid #719acb; +} +span.fancytree-title:hover { + border-color: #d8f0fa; + background: #f8fcfe; + color: inherit; + background: -moz-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f8fcfe), color-stop(100%, #eff9fe)); + background: -webkit-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%); + background: -o-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%); + background: -ms-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%); + background: linear-gradient(to bottom, #f8fcfe 0%, #eff9fe 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8fcfe', endColorstr='#eff9fe', GradientType=0); +} +span.fancytree-active .fancytree-title:hover, +span.fancytree-selected .fancytree-title:hover { + border-color: #719acb; + background: #f2f9fd; + color: inherit; + background: -moz-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f2f9fd), color-stop(100%, #c4e8fa)); + background: -webkit-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%); + background: -o-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%); + background: -ms-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%); + background: linear-gradient(to bottom, #f2f9fd 0%, #c4e8fa 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2f9fd', endColorstr='#c4e8fa', GradientType=0); +} +/******************************************************************************* + * 'table' extension + */ +table.fancytree-ext-table tbody tr td { + border: 1px solid #ededed; +} +table.fancytree-ext-table tbody tr:hover { + border-color: inherit; + background: #f8fcfe; + color: inherit; + background: -moz-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f8fcfe), color-stop(100%, #eff9fe)); + background: -webkit-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%); + background: -o-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%); + background: -ms-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%); + background: linear-gradient(to bottom, #f8fcfe 0%, #eff9fe 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8fcfe', endColorstr='#eff9fe', GradientType=0); + outline: 1px solid #d8f0fa; +} +table.fancytree-ext-table tbody tr.fancytree-focused { + outline: 1px dotted #090402; +} +table.fancytree-ext-table tbody span.fancytree-focused span.fancytree-title { + outline: solid dotted black; +} +table.fancytree-ext-table tbody span.fancytree-title:hover { + border: 1px solid transparent; + background: inherit; + background: transparent; + background: none; + filter: none; +} +table.fancytree-ext-table tbody tr.fancytree-active:hover, +table.fancytree-ext-table tbody tr.fancytree-selected:hover { + border-color: inherit; + background: #f2f9fd; + color: inherit; + background: -moz-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f2f9fd), color-stop(100%, #c4e8fa)); + background: -webkit-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%); + background: -o-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%); + background: -ms-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%); + background: linear-gradient(to bottom, #f2f9fd 0%, #c4e8fa 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2f9fd', endColorstr='#c4e8fa', GradientType=0); + outline: 1px solid #B6E6FB; +} +table.fancytree-ext-table tbody tr.fancytree-active, +table.fancytree-ext-table tbody tr.fancytree-selected { + border-color: inherit; + background: #f6fbfd; + color: inherit; + background: -moz-linear-gradient(top, #f6fbfd 0%, #d5effc 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f6fbfd), color-stop(100%, #d5effc)); + background: -webkit-linear-gradient(top, #f6fbfd 0%, #d5effc 100%); + background: -o-linear-gradient(top, #f6fbfd 0%, #d5effc 100%); + background: -ms-linear-gradient(top, #f6fbfd 0%, #d5effc 100%); + background: linear-gradient(to bottom, #f6fbfd 0%, #d5effc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6fbfd', endColorstr='#d5effc', GradientType=0); + outline: 1px solid #99DEFD; +} diff --git a/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.less b/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.less new file mode 100644 index 0000000..d517e06 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.less @@ -0,0 +1,146 @@ +/*! + * Fancytree "Win7" skin. + * + * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from + * the LESS templates. + */ + +// Fancytree Win7 styles + +// both: +// unselected background: #FCFCFC 'nearly white', no border +// +// hover bar (unselected, inactive): #fcfdfe..#EFF9FE (border: #b8d6fb) 'very light blue' +// background: #f8fcfe; // +// background: -moz-linear-gradient(top, #f8fcfe 0%, #eff9fe 100%); + +// active node: #F6FBFD..#D5EFFC (border: #719acb) 'light blue' +// background: #f6fbfd; +// background: -moz-linear-gradient(top, #f6fbfd 0%, #d5effc 100%); + +// active node with hover: #F2F9FD..#C4E8FA (border: #B6E6FB) +// background: #f2f9fd; +// background: -moz-linear-gradient(top, #f2f9fd 0%, #c4e8fa 100%); + +// Tree view: +// active node, tree inactive: #FAFAFB..#E5E5E5 (border: #D9D9D9) 'light gray, selected, but tree not active' +// background: #fafafb; +// background: -moz-linear-gradient(top, #fafafb 0%, #e5e5e5 100%); + +// List view: +// selected bar: --> active bar +// focus bar: active + border 1px dotted #090402 (inside the blue border) + +// table left/right border: #EDEDED 'light gray' + +// Import common styles +@import "../skin-common.less"; + + +/******************************************************************************* + * Styles specific to this skin. + * + * This section is automatically generated from the `ui-fancytree.less` template. + ******************************************************************************/ + +// Override the variable after the import. +// NOTE: Variables are always resolved as the last definition, even if it is +// after where it is used. +@fancy-use-sprites: true; +@fancy-hide-connectors: true; + +@fancy-line-height: 20px; // height of a nodes selection bar including borders +@fancy-node-v-spacing: 1px; // gap between two node borders +@fancy-icon-width: 16px; +@fancy-icon-height: 16px; +@fancy-icon-spacing: 3px; // margin between icon/icon or icon/title +@fancy-icon-ofs-top: 2px; // extra vertical offset for expander, checkbox and icon +@fancy-title-ofs-top: 0px; // extra vertical offset for title +@fancy-node-border-width: 1px; +@fancy-node-border-radius: 3px; +@fancy-node-outline-width: 1px; + + +ul.fancytree-container { + +} + +/******************************************************************************* + * Node titles + */ +span.fancytree-title { +} +// active nodes inside an UN-focused tree are gray instead of blue +span.fancytree-active .fancytree-title, +span.fancytree-selected .fancytree-title { + .spanStyleMixin(inherit, #e5e5e5, #d9d9d9, #fafafb, #e5e5e5); +} +span.fancytree-selected .fancytree-title { + font-style: italic; +} +// Markers inside an active tree +.fancytree-treefocus { + span.fancytree-active .fancytree-title, + span.fancytree-selected .fancytree-title { + .spanStyleMixin(inherit, #f6fbfd, #99defd, #f6fbfd, #d5effc); + } + span.fancytree-focused span.fancytree-title { + border: @fancy-node-border-width solid #719acb; + } +} +// Hover is always colored (even if tree is inactive) +span.fancytree-title:hover { + .spanStyleMixin(inherit, #f8fcfe, #d8f0fa, #f8fcfe, #eff9fe); +} +span.fancytree-active .fancytree-title:hover, +span.fancytree-selected .fancytree-title:hover { + .spanStyleMixin(inherit, #f2f9fd, #719acb, #f2f9fd, #c4e8fa); +} + +/******************************************************************************* + * 'table' extension + */ + +table.fancytree-ext-table tbody { + tr td { + border: 1px solid #ededed; + } + tr:hover { + .spanStyleMixin(inherit, #f8fcfe, inherit, #f8fcfe, #eff9fe); + outline: 1px solid #d8f0fa; + } + // tr:hover td { + // outline: 1px solid #D8F0FA; + // } + tr.fancytree-focused { + // background-color: #99DEFD; + outline: 1px dotted #090402; + } + span.fancytree-focused span.fancytree-title { + outline: solid dotted black; + } + + // Title get's a white background, when hovered. Undo standard node formatting + span.fancytree-title:hover { + border: 1px solid transparent; + background: inherit; + background: transparent; + background: none; + filter: none; + } + + tr.fancytree-active:hover, + tr.fancytree-selected:hover { + .spanStyleMixin(inherit, #f2f9fd, inherit, #f2f9fd, #c4e8fa); + outline: 1px solid #B6E6FB; + } + tr.fancytree-active, + tr.fancytree-selected { + .spanStyleMixin(inherit, #f6fbfd, inherit, #f6fbfd, #d5effc); + outline: 1px solid #99DEFD; + } + // tr.fancytree-selected .fancytree-title { + // font-style: italic; + // } + +} diff --git a/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.min.css b/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.min.css new file mode 100644 index 0000000..4e1fb61 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/fancytree/skin-win7/ui.fancytree.min.css @@ -0,0 +1,6 @@ +/*! + * Fancytree "Win7" skin. + * + * DON'T EDIT THE CSS FILE DIRECTLY, since it is automatically generated from + * the LESS templates. + */.ui-helper-hidden{display:none}ul.fancytree-container{font-family:tahoma,arial,helvetica;font-size:10pt;white-space:nowrap;padding:3px;margin:0;background-color:#fff;border:1px dotted gray;overflow:auto;min-height:0;position:relative}ul.fancytree-container ul{padding:0 0 0 16px;margin:0}ul.fancytree-container li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}ul.fancytree-container li.fancytree-lastsib,ul.fancytree-no-connector>li{background-image:none}.ui-fancytree-disabled ul.fancytree-container{opacity:.5;background-color:silver}#fancytree-drop-marker,span.fancytree-checkbox,span.fancytree-drag-helper-img,span.fancytree-empty,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio,span.fancytree-vline{width:16px;height:16px;display:inline-block;vertical-align:top;background-repeat:no-repeat;background-image:url(icons.gif);background-position:0 0}span.fancytree-checkbox,span.fancytree-custom-icon,span.fancytree-expander,span.fancytree-icon,span.fancytree-radio{margin-top:2px}span.fancytree-custom-icon{display:inline-block}img.fancytree-icon{width:16px;height:16px;margin-left:3px;margin-top:2px;vertical-align:top;border-style:none}span.fancytree-expander{cursor:pointer}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander{background-image:none;cursor:default}.fancytree-exp-n span.fancytree-expander,.fancytree-exp-n span.fancytree-expander:hover{background-position:0 -64px}.fancytree-exp-nl span.fancytree-expander,.fancytree-exp-nl span.fancytree-expander:hover{background-position:-16px -64px}.fancytree-exp-c span.fancytree-expander{background-position:0 -80px}.fancytree-exp-c span.fancytree-expander:hover{background-position:-16px -80px}.fancytree-exp-cl span.fancytree-expander{background-position:0 -96px}.fancytree-exp-cl span.fancytree-expander:hover{background-position:-16px -96px}.fancytree-exp-cd span.fancytree-expander{background-position:-64px -80px}.fancytree-exp-cd span.fancytree-expander:hover{background-position:-80px -80px}.fancytree-exp-cdl span.fancytree-expander{background-position:-64px -96px}.fancytree-exp-cdl span.fancytree-expander:hover{background-position:-80px -96px}.fancytree-exp-e span.fancytree-expander,.fancytree-exp-ed span.fancytree-expander{background-position:-32px -80px}.fancytree-exp-e span.fancytree-expander:hover,.fancytree-exp-ed span.fancytree-expander:hover{background-position:-48px -80px}.fancytree-exp-edl span.fancytree-expander,.fancytree-exp-el span.fancytree-expander{background-position:-32px -96px}.fancytree-exp-edl span.fancytree-expander:hover,.fancytree-exp-el span.fancytree-expander:hover{background-position:-48px -96px}span.fancytree-checkbox{margin-left:3px;background-position:0 -32px}span.fancytree-checkbox:hover{background-position:-16px -32px}.fancytree-partsel span.fancytree-checkbox{background-position:-64px -32px}.fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -32px}.fancytree-selected span.fancytree-checkbox{background-position:-32px -32px}.fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -32px}.fancytree-unselectable span.fancytree-checkbox,.fancytree-unselectable span.fancytree-checkbox:hover{opacity:.4;filter:alpha(opacity=40);background-position:0 -32px}.fancytree-radio span.fancytree-checkbox{background-position:0 -48px}.fancytree-radio span.fancytree-checkbox:hover{background-position:-16px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox{background-position:-64px -48px}.fancytree-radio .fancytree-partsel span.fancytree-checkbox:hover{background-position:-80px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox{background-position:-32px -48px}.fancytree-radio .fancytree-selected span.fancytree-checkbox:hover{background-position:-48px -48px}.fancytree-radio .fancytree-unselectable span.fancytree-checkbox,.fancytree-radio .fancytree-unselectable span.fancytree-checkbox:hover{background-position:0 -48px}span.fancytree-icon{margin-left:3px;background-position:0 0}.fancytree-ico-c span.fancytree-icon:hover{background-position:-16px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon{background-position:-32px 0}.fancytree-has-children.fancytree-ico-c span.fancytree-icon:hover{background-position:-48px 0}.fancytree-ico-e span.fancytree-icon{background-position:-64px 0}.fancytree-ico-e span.fancytree-icon:hover{background-position:-80px 0}.fancytree-ico-cf span.fancytree-icon{background-position:0 -16px}.fancytree-ico-cf span.fancytree-icon:hover{background-position:-16px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon{background-position:-32px -16px}.fancytree-has-children.fancytree-ico-cf span.fancytree-icon:hover{background-position:-48px -16px}.fancytree-ico-ef span.fancytree-icon{background-position:-64px -16px}.fancytree-ico-ef span.fancytree-icon:hover{background-position:-80px -16px}.fancytree-loading span.fancytree-expander,.fancytree-loading span.fancytree-expander:hover,.fancytree-statusnode-wait span.fancytree-icon,.fancytree-statusnode-wait span.fancytree-icon:hover{background-image:url(loading.gif);background-position:0 0}.fancytree-statusnode-error span.fancytree-icon,.fancytree-statusnode-error span.fancytree-icon:hover{background-position:0 -112px}span.fancytree-node{display:inherit;width:100%;margin-top:1px;min-height:20px}span.fancytree-title{color:#000;cursor:pointer;display:inline-block;vertical-align:top;min-height:20px;padding:0 3px;margin:0 0 0 3px;border:1px solid transparent;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}span.fancytree-node.fancytree-error span.fancytree-title{color:red}div.fancytree-drag-helper a{border:1px solid gray;background-color:#fff;padding-left:5px;padding-right:5px;opacity:.8}div.fancytree-drag-helper.fancytree-drop-reject{border-color:red}div.fancytree-drop-accept span.fancytree-drag-helper-img{background-position:-32px -112px}div.fancytree-drop-reject span.fancytree-drag-helper-img{background-position:-16px -112px}#fancytree-drop-marker{width:32px;position:absolute;background-position:0 -128px;margin:0}#fancytree-drop-marker.fancytree-drop-after,#fancytree-drop-marker.fancytree-drop-before{width:64px;background-position:0 -144px}#fancytree-drop-marker.fancytree-drop-copy{background-position:-64px -128px}#fancytree-drop-marker.fancytree-drop-move{background-position:-32px -128px}span.fancytree-drag-source{background-color:#e0e0e0}span.fancytree-drag-source span.fancytree.title{color:gray}span.fancytree-drop-target.fancytree-drop-accept a{background-color:#3169C6!important;color:#fff!important;text-decoration:none}table.fancytree-ext-table{border-collapse:collapse}table.fancytree-ext-table span.fancytree-node{display:inline-block}table.fancytree-ext-columnview tbody tr td{position:relative;border:1px solid gray;vertical-align:top;overflow:auto}table.fancytree-ext-columnview tbody tr td>ul{padding:0}table.fancytree-ext-columnview tbody tr td>ul li{list-style-image:none;list-style-position:outside;list-style-type:none;-moz-background-clip:border;-moz-background-inline-policy:continuous;-moz-background-origin:padding;background-attachment:scroll;background-color:transparent;background-position:0 0;background-repeat:repeat-y;background-image:none;margin:0}table.fancytree-ext-columnview span.fancytree-node{position:relative;display:inline-block}table.fancytree-ext-columnview span.fancytree-node.fancytree-expanded{background-color:#CBE8F6}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right{position:absolute;right:3px;background-position:0 -80px}table.fancytree-ext-columnview .fancytree-has-children span.fancytree-cv-right:hover{background-position:-16px -80px}.fancytree-ext-filter-dimm span.fancytree-node span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-submatch span.fancytree-title{color:#000;font-weight:400}.fancytree-ext-filter-dimm span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-dimm tr.fancytree-match span.fancytree-title{color:#000;font-weight:700}.fancytree-ext-filter-hide span.fancytree-node.fancytree-hide,.fancytree-ext-filter-hide tr.fancytree-hide{display:none}.fancytree-ext-filter-hide span.fancytree-node.fancytree-submatch span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-submatch span.fancytree-title{color:silver;font-weight:lighter}.fancytree-ext-filter-hide span.fancytree-node.fancytree-match span.fancytree-title,.fancytree-ext-filter-hide tr.fancytree-match span.fancytree-title{color:#000;font-weight:400}ul.fancytree-ext-wide{position:relative;min-width:100%;z-index:2;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}ul.fancytree-ext-wide span.fancytree-node>span{position:relative;z-index:2}ul.fancytree-ext-wide span.fancytree-node span.fancytree-title{position:absolute;z-index:1;left:0;width:100%;margin-left:0;margin-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}span.fancytree-active .fancytree-title,span.fancytree-selected .fancytree-title{border-color:#d9d9d9;color:inherit;background:-moz-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#fafafb),color-stop(100%,#e5e5e5));background:-webkit-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:-o-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:-ms-linear-gradient(top,#fafafb 0,#e5e5e5 100%);background:linear-gradient(to bottom,#fafafb 0,#e5e5e5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fafafb', endColorstr='#e5e5e5', GradientType=0)}span.fancytree-selected .fancytree-title{font-style:italic}.fancytree-treefocus span.fancytree-active .fancytree-title,.fancytree-treefocus span.fancytree-selected .fancytree-title{border-color:#99defd;color:inherit;background:-moz-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f6fbfd),color-stop(100%,#d5effc));background:-webkit-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-o-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-ms-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:linear-gradient(to bottom,#f6fbfd 0,#d5effc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6fbfd', endColorstr='#d5effc', GradientType=0)}.fancytree-treefocus span.fancytree-focused span.fancytree-title{border:1px solid #719acb}span.fancytree-title:hover{border-color:#d8f0fa;color:inherit;background:-moz-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f8fcfe),color-stop(100%,#eff9fe));background:-webkit-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-o-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-ms-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:linear-gradient(to bottom,#f8fcfe 0,#eff9fe 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8fcfe', endColorstr='#eff9fe', GradientType=0)}span.fancytree-active .fancytree-title:hover,span.fancytree-selected .fancytree-title:hover{border-color:#719acb;color:inherit;background:-moz-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f2f9fd),color-stop(100%,#c4e8fa));background:-webkit-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-o-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-ms-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:linear-gradient(to bottom,#f2f9fd 0,#c4e8fa 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2f9fd', endColorstr='#c4e8fa', GradientType=0)}table.fancytree-ext-table tbody tr td{border:1px solid #ededed}table.fancytree-ext-table tbody tr:hover{border-color:inherit;color:inherit;background:-moz-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f8fcfe),color-stop(100%,#eff9fe));background:-webkit-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-o-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:-ms-linear-gradient(top,#f8fcfe 0,#eff9fe 100%);background:linear-gradient(to bottom,#f8fcfe 0,#eff9fe 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f8fcfe', endColorstr='#eff9fe', GradientType=0);outline:1px solid #d8f0fa}table.fancytree-ext-table tbody tr.fancytree-focused{outline:1px dotted #090402}table.fancytree-ext-table tbody span.fancytree-focused span.fancytree-title{outline:solid dotted #000}table.fancytree-ext-table tbody span.fancytree-title:hover{border:1px solid transparent;background:inherit;background:0 0;background:0 0;filter:none}table.fancytree-ext-table tbody tr.fancytree-active:hover,table.fancytree-ext-table tbody tr.fancytree-selected:hover{border-color:inherit;color:inherit;background:-moz-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f2f9fd),color-stop(100%,#c4e8fa));background:-webkit-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-o-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:-ms-linear-gradient(top,#f2f9fd 0,#c4e8fa 100%);background:linear-gradient(to bottom,#f2f9fd 0,#c4e8fa 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f2f9fd', endColorstr='#c4e8fa', GradientType=0);outline:1px solid #B6E6FB}table.fancytree-ext-table tbody tr.fancytree-active,table.fancytree-ext-table tbody tr.fancytree-selected{border-color:inherit;color:inherit;background:-moz-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#f6fbfd),color-stop(100%,#d5effc));background:-webkit-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-o-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:-ms-linear-gradient(top,#f6fbfd 0,#d5effc 100%);background:linear-gradient(to bottom,#f6fbfd 0,#d5effc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6fbfd', endColorstr='#d5effc', GradientType=0);outline:1px solid #99DEFD} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/jquery.pnotify/jquery.pnotify.default.css b/src/core/classes/org/glizycms/js/jquery/jquery.pnotify/jquery.pnotify.default.css new file mode 100755 index 0000000..dd36cc5 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/jquery.pnotify/jquery.pnotify.default.css @@ -0,0 +1,94 @@ +/* +Document : jquery.pnotify.default.css +Created on : Nov 23, 2009, 3:14:10 PM +Author : Hunter Perrin +Version : 1.2.2 +Link : http://sciactive.com/pnotify/ +Description: + Default styling for PNotify jQuery plugin. +*/ +/* -- Notice */ +.ui-pnotify { +top: 25px; +right: 25px; +position: absolute; +height: auto; +/* Ensures notices are above everything */ +z-index: 9999; +} +/* Hides position: fixed from IE6 */ +html > body .ui-pnotify { +position: fixed; +} +.ui-pnotify .ui-pnotify-shadow { +-webkit-box-shadow: 0px 2px 10px rgba(50, 50, 50, 0.5); +-moz-box-shadow: 0px 2px 10px rgba(50, 50, 50, 0.5); +box-shadow: 0px 2px 10px rgba(50, 50, 50, 0.5); +} +.ui-pnotify-container { +background-position: 0 0; +padding: .8em; +height: 100%; +margin: 0; +} +.ui-pnotify-sharp { +-webkit-border-radius: 0; +-moz-border-radius: 0; +border-radius: 0; +} +.ui-pnotify-closer, .ui-pnotify-sticker { +float: right; +margin-left: .2em; +} +.ui-pnotify-title { +display: block; +margin-bottom: .4em; +margin-top: 0; +} +.ui-pnotify-text { +display: block; +} +.ui-pnotify-icon, .ui-pnotify-icon span { +display: block; +float: left; +margin-right: .2em; +} +/* -- History Pulldown */ +.ui-pnotify-history-container { +position: absolute; +top: 0; +right: 18px; +width: 70px; +border-top: none; +padding: 0; +-webkit-border-top-left-radius: 0; +-moz-border-top-left-radius: 0; +border-top-left-radius: 0; +-webkit-border-top-right-radius: 0; +-moz-border-top-right-radius: 0; +border-top-right-radius: 0; +/* Ensures history container is above notices. */ +z-index: 10000; +} +.ui-pnotify-history-container .ui-pnotify-history-header { +padding: 2px; +text-align: center; +} +.ui-pnotify-history-container button { +cursor: pointer; +display: block; +width: 100%; +} +.ui-pnotify-history-container .ui-pnotify-history-pulldown { +display: block; +margin: 0 auto; +} +/* Alternate stack initial positioning. */ +.ui-pnotify.stack-topleft, .ui-pnotify.stack-bottomleft { +left: 25px; +right: auto; +} +.ui-pnotify.stack-bottomright, .ui-pnotify.stack-bottomleft { +bottom: 25px; +top: auto; +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/jquery.pnotify/jquery.pnotify.min.js b/src/core/classes/org/glizycms/js/jquery/jquery.pnotify/jquery.pnotify.min.js new file mode 100644 index 0000000..6452764 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/jquery.pnotify/jquery.pnotify.min.js @@ -0,0 +1,11 @@ +/* + * jQuery PNotify Plugin 1.2.2 + * + * http://sciactive.com/pnotify/ + * Copyright (c) 2009-2012 Hunter Perrin + * + * Triple license under the GPL, LGPL, and MPL: + * http://www.gnu.org/licenses/gpl.html + * http://www.gnu.org/licenses/lgpl.html + * http://www.mozilla.org/MPL/MPL-1.1.html + */(function(e){var t,n,r,i=e(window),s={jqueryui:{container:"ui-widget ui-widget-content ui-corner-all",notice:"ui-state-highlight",notice_icon:"ui-icon ui-icon-info",info:"",info_icon:"ui-icon ui-icon-info",success:"ui-state-default",success_icon:"ui-icon ui-icon-circle-check",error:"ui-state-error",error_icon:"ui-icon ui-icon-alert",closer:"ui-icon ui-icon-close",pin_up:"ui-icon ui-icon-pin-w",pin_down:"ui-icon ui-icon-pin-s",hi_menu:"ui-state-default ui-corner-bottom",hi_btn:"ui-state-default ui-corner-all",hi_btnhov:"ui-state-hover",hi_hnd:"ui-icon ui-icon-grip-dotted-horizontal"},bootstrap:{container:"alert",notice:"",notice_icon:"icon-exclamation-sign",info:"alert-info",info_icon:"icon-info-sign",success:"alert-success",success_icon:"icon-ok-sign",error:"alert-error",error_icon:"icon-warning-sign",closer:"icon-remove",pin_up:"icon-pause",pin_down:"icon-play",hi_menu:"well",hi_btn:"btn",hi_btnhov:"",hi_hnd:"icon-chevron-down"},bootstrap3:{container:"alert",notice:"alert-warning",notice_icon:"glyphicon glyphicon-exclamation-sign",info:"alert-info",info_icon:"glyphicon glyphicon-info-sign",success:"alert-success",success_icon:"glyphicon glyphicon-ok-sign",error:"alert-danger",error_icon:"glyphicon glyphicon-warning-sign",closer:"glyphicon glyphicon-remove",pin_up:"glyphicon glyphicon-pause",pin_down:"glyphicon glyphicon-play",hi_menu:"well",hi_btn:"btn btn-default",hi_btnhov:"",hi_hnd:"glyphicon glyphicon-chevron-down"}};s.fontawesome=e.extend({},s.bootstrap3);s.fontawesome.notice_icon="fa fa-exclamation-circle";s.fontawesome.info_icon="fa fa-info";s.fontawesome.success_icon="fa fa-check";s.fontawesome.error_icon="fa fa-warning";s.fontawesome.closer="fa fa-times";s.fontawesome.pin_up="fa fa-pause";s.fontawesome.pin_down="fa fa-play";s.fontawesome.hi_hnd="fa fa-chevron-down";var o=function(){r=e("body");i=e(window);i.bind("resize",function(){n&&clearTimeout(n);n=setTimeout(e.pnotify_position_all,10)})};document.body?o():e(o);e.extend({pnotify_remove_all:function(){var t=i.data("pnotify");t&&t.length&&e.each(t,function(){this.pnotify_remove&&this.pnotify_remove()})},pnotify_position_all:function(){n&&clearTimeout(n);n=null;var t=i.data("pnotify");if(!t||!t.length)return;e.each(t,function(){var e=this.opts.stack;if(!e)return;e.nextpos1=e.firstpos1;e.nextpos2=e.firstpos2;e.addpos2=0;e.animation=!0});e.each(t,function(){this.pnotify_position()})},pnotify:function(o){var u,a;if(typeof o!="object"){a=e.extend({},e.pnotify.defaults);a.text=o}else a=e.extend({},e.pnotify.defaults,o);for(var f in a)typeof f=="string"&&f.match(/^pnotify_/)&&(a[f.replace(/^pnotify_/,"")]=a[f]);if(a.before_init&&a.before_init(a)===!1)return null;var l,h=function(t,n){d.css("display","none");var r=document.elementFromPoint(t.clientX,t.clientY);d.css("display","block");var i=e(r),s=i.css("cursor");d.css("cursor",s!="auto"?s:"default");if(!l||l.get(0)!=r){if(l){c.call(l.get(0),"mouseleave",t.originalEvent);c.call(l.get(0),"mouseout",t.originalEvent)}c.call(r,"mouseenter",t.originalEvent);c.call(r,"mouseover",t.originalEvent)}c.call(r,n,t.originalEvent);l=i},p;typeof a.styling=="object"?p=a.styling:p=s[a.styling];var d=e("<div />",{"class":"ui-pnotify "+a.addclass,css:{display:"none"},mouseenter:function(e){a.nonblock&&e.stopPropagation();if(a.mouse_reset&&u=="out"){d.stop(!0);u="in";d.css("height","auto").animate({width:a.width,opacity:a.nonblock?a.nonblock_opacity:a.opacity},"fast")}a.nonblock&&d.stop().animate({opacity:a.nonblock_opacity},"fast");a.hide&&a.mouse_reset&&d.pnotify_cancel_remove();a.sticker&&!a.nonblock&&d.sticker.trigger("pnotify_icon").css("visibility","visible");a.closer&&!a.nonblock&&d.closer.css("visibility","visible")},mouseleave:function(t){a.nonblock&&t.stopPropagation();l=null;d.css("cursor","auto");a.nonblock&&u!="out"&&d.stop().animate({opacity:a.opacity},"fast");a.hide&&a.mouse_reset&&d.pnotify_queue_remove();a.sticker_hover&&d.sticker.css("visibility","hidden");a.closer_hover&&d.closer.css("visibility","hidden");e.pnotify_position_all()},mouseover:function(e){a.nonblock&&e.stopPropagation()},mouseout:function(e){a.nonblock&&e.stopPropagation()},mousemove:function(e){if(a.nonblock){e.stopPropagation();h(e,"onmousemove")}},mousedown:function(e){if(a.nonblock){e.stopPropagation();e.preventDefault();h(e,"onmousedown")}},mouseup:function(e){if(a.nonblock){e.stopPropagation();e.preventDefault();h(e,"onmouseup")}},click:function(e){if(a.nonblock){e.stopPropagation();h(e,"onclick")}},dblclick:function(e){if(a.nonblock){e.stopPropagation();h(e,"ondblclick")}}});d.opts=a;d.container=e("<div />",{"class":p.container+" ui-pnotify-container "+(a.type=="error"?p.error:a.type=="info"?p.info:a.type=="success"?p.success:p.notice)}).appendTo(d);a.cornerclass!=""&&d.container.removeClass("ui-corner-all").addClass(a.cornerclass);a.shadow&&d.container.addClass("ui-pnotify-shadow");d.pnotify_version="1.2.2";d.pnotify=function(t){var n=a;typeof t=="string"?a.text=t:a=e.extend({},a,t);for(var r in a)typeof r=="string"&&r.match(/^pnotify_/)&&(a[r.replace(/^pnotify_/,"")]=a[r]);d.opts=a;a.cornerclass!=n.cornerclass&&d.container.removeClass("ui-corner-all").addClass(a.cornerclass);a.shadow!=n.shadow&&(a.shadow?d.container.addClass("ui-pnotify-shadow"):d.container.removeClass("ui-pnotify-shadow"));a.addclass===!1?d.removeClass(n.addclass):a.addclass!==n.addclass&&d.removeClass(n.addclass).addClass(a.addclass);a.title===!1?d.title_container.slideUp("fast"):a.title!==n.title&&(a.title_escape?d.title_container.text(a.title).slideDown(200):d.title_container.html(a.title).slideDown(200));a.text===!1?d.text_container.slideUp("fast"):a.text!==n.text&&(a.text_escape?d.text_container.text(a.text).slideDown(200):d.text_container.html(a.insert_brs?String(a.text).replace(/\n/g,"<br />"):a.text).slideDown(200));d.pnotify_history=a.history;d.pnotify_hide=a.hide;a.type!=n.type&&d.container.removeClass(p.error+" "+p.notice+" "+p.success+" "+p.info).addClass(a.type=="error"?p.error:a.type=="info"?p.info:a.type=="success"?p.success:p.notice);if(a.icon!==n.icon||a.icon===!0&&a.type!=n.type){d.container.find("div.ui-pnotify-icon").remove();a.icon!==!1&&e("<div />",{"class":"ui-pnotify-icon"}).append(e("<span />",{"class":a.icon===!0?a.type=="error"?p.error_icon:a.type=="info"?p.info_icon:a.type=="success"?p.success_icon:p.notice_icon:a.icon})).prependTo(d.container)}a.width!==n.width&&d.animate({width:a.width});a.min_height!==n.min_height&&d.container.animate({minHeight:a.min_height});a.opacity!==n.opacity&&d.fadeTo(a.animate_speed,a.opacity);!a.closer||a.nonblock?d.closer.css("display","none"):d.closer.css("display","block");!a.sticker||a.nonblock?d.sticker.css("display","none"):d.sticker.css("display","block");d.sticker.trigger("pnotify_icon");a.sticker_hover?d.sticker.css("visibility","hidden"):a.nonblock||d.sticker.css("visibility","visible");a.closer_hover?d.closer.css("visibility","hidden"):a.nonblock||d.closer.css("visibility","visible");a.hide?n.hide||d.pnotify_queue_remove():d.pnotify_cancel_remove();d.pnotify_queue_position();return d};d.pnotify_position=function(e){var t=d.opts.stack;if(!t)return;t.nextpos1||(t.nextpos1=t.firstpos1);t.nextpos2||(t.nextpos2=t.firstpos2);t.addpos2||(t.addpos2=0);var n=d.css("display")=="none";if(!n||e){var r,s,o={},u;switch(t.dir1){case"down":u="top";break;case"up":u="bottom";break;case"left":u="right";break;case"right":u="left"}r=parseInt(d.css(u));isNaN(r)&&(r=0);if(typeof t.firstpos1=="undefined"&&!n){t.firstpos1=r;t.nextpos1=t.firstpos1}var a;switch(t.dir2){case"down":a="top";break;case"up":a="bottom";break;case"left":a="right";break;case"right":a="left"}s=parseInt(d.css(a));isNaN(s)&&(s=0);if(typeof t.firstpos2=="undefined"&&!n){t.firstpos2=s;t.nextpos2=t.firstpos2}if(t.dir1=="down"&&t.nextpos1+d.height()>i.height()||t.dir1=="up"&&t.nextpos1+d.height()>i.height()||t.dir1=="left"&&t.nextpos1+d.width()>i.width()||t.dir1=="right"&&t.nextpos1+d.width()>i.width()){t.nextpos1=t.firstpos1;t.nextpos2+=t.addpos2+(typeof t.spacing2=="undefined"?25:t.spacing2);t.addpos2=0}if(t.animation&&t.nextpos2<s)switch(t.dir2){case"down":o.top=t.nextpos2+"px";break;case"up":o.bottom=t.nextpos2+"px";break;case"left":o.right=t.nextpos2+"px";break;case"right":o.left=t.nextpos2+"px"}else t.nextpos2&&d.css(a,t.nextpos2+"px");switch(t.dir2){case"down":case"up":d.outerHeight(!0)>t.addpos2&&(t.addpos2=d.height());break;case"left":case"right":d.outerWidth(!0)>t.addpos2&&(t.addpos2=d.width())}if(t.nextpos1)if(t.animation&&(r>t.nextpos1||o.top||o.bottom||o.right||o.left))switch(t.dir1){case"down":o.top=t.nextpos1+"px";break;case"up":o.bottom=t.nextpos1+"px";break;case"left":o.right=t.nextpos1+"px";break;case"right":o.left=t.nextpos1+"px"}else d.css(u,t.nextpos1+"px");(o.top||o.bottom||o.right||o.left)&&d.animate(o,{duration:this.opts.position_animate_speed,queue:!1});switch(t.dir1){case"down":case"up":t.nextpos1+=d.height()+(typeof t.spacing1=="undefined"?25:t.spacing1);break;case"left":case"right":t.nextpos1+=d.width()+(typeof t.spacing1=="undefined"?25:t.spacing1)}}};d.pnotify_queue_position=function(t){n&&clearTimeout(n);t||(t=10);n=setTimeout(e.pnotify_position_all,t)};d.pnotify_display=function(){v=i.data("pnotify");v&&v.length>a.maxonscreen&&e.each(v.slice(0,v.length-a.maxonscreen),function(){this.pnotify_remove&&this.pnotify_remove()});d.parent().length||d.appendTo(r);if(a.before_open&&a.before_open(d)===!1)return;a.stack.push!="top"&&d.pnotify_position(!0);a.animation=="fade"||a.animation.effect_in=="fade"?d.show().fadeTo(0,0).hide():a.opacity!=1&&d.show().fadeTo(0,a.opacity).hide();d.animate_in(function(){a.after_open&&a.after_open(d);d.pnotify_queue_position();a.hide&&d.pnotify_queue_remove()})};d.pnotify_remove=function(e){if(d.timer){window.clearTimeout(d.timer);d.timer=null}if(a.before_close&&a.before_close(d,e)===!1)return;d.animate_out(function(){if(a.after_close&&a.after_close(d,e)===!1)return;d.pnotify_queue_position();a.remove&&d.detach()})};d.animate_in=function(e){u="in";var t;typeof a.animation.effect_in!="undefined"?t=a.animation.effect_in:t=a.animation;if(t=="none"){d.show();e()}else t=="show"?d.show(a.animate_speed,e):t=="fade"?d.show().fadeTo(a.animate_speed,a.opacity,e):t=="slide"?d.slideDown(a.animate_speed,e):typeof t=="function"?t("in",e,d):d.show(t,typeof a.animation.options_in=="object"?a.animation.options_in:{},a.animate_speed,e)};d.animate_out=function(e){u="out";var t;typeof a.animation.effect_out!="undefined"?t=a.animation.effect_out:t=a.animation;if(t=="none"){d.hide();e()}else t=="show"?d.hide(a.animate_speed,e):t=="fade"?d.fadeOut(a.animate_speed,e):t=="slide"?d.slideUp(a.animate_speed,e):typeof t=="function"?t("out",e,d):d.hide(t,typeof a.animation.options_out=="object"?a.animation.options_out:{},a.animate_speed,e)};d.pnotify_cancel_remove=function(){d.timer&&window.clearTimeout(d.timer)};d.pnotify_queue_remove=function(){d.pnotify_cancel_remove();d.timer=window.setTimeout(function(){d.pnotify_remove(!0)},isNaN(a.delay)?0:a.delay)};d.closer=e("<div />",{"class":"ui-pnotify-closer",css:{cursor:"pointer",visibility:a.closer_hover?"hidden":"visible"},click:function(){d.pnotify_remove(!1);d.sticker.css("visibility","hidden");d.closer.css("visibility","hidden")}}).append(e("<span />",{"class":p.closer,title:a.labels.close})).appendTo(d.container);(!a.closer||a.nonblock)&&d.closer.css("display","none");d.sticker=e("<div />",{"class":"ui-pnotify-sticker",css:{cursor:"pointer",visibility:a.sticker_hover?"hidden":"visible"},click:function(){a.hide=!a.hide;a.hide?d.pnotify_queue_remove():d.pnotify_cancel_remove();e(this).trigger("pnotify_icon")}}).bind("pnotify_icon",function(){e(this).children().removeClass(p.pin_up+" "+p.pin_down).addClass(a.hide?p.pin_up:p.pin_down)}).append(e("<span />",{"class":p.pin_up,title:a.labels.stick})).appendTo(d.container);(!a.sticker||a.nonblock)&&d.sticker.css("display","none");a.icon!==!1&&e("<div />",{"class":"ui-pnotify-icon"}).append(e("<span />",{"class":a.icon===!0?a.type=="error"?p.error_icon:a.type=="info"?p.info_icon:a.type=="success"?p.success_icon:p.notice_icon:a.icon})).prependTo(d.container);d.title_container=e("<h4 />",{"class":"ui-pnotify-title"}).appendTo(d.container);a.title===!1?d.title_container.hide():a.title_escape?d.title_container.text(a.title):d.title_container.html(a.title);d.text_container=e("<div />",{"class":"ui-pnotify-text"}).appendTo(d.container);a.text===!1?d.text_container.hide():a.text_escape?d.text_container.text(a.text):d.text_container.html(a.insert_brs?String(a.text).replace(/\n/g,"<br />"):a.text);typeof a.width=="string"&&d.css("width",a.width);typeof a.min_height=="string"&&d.container.css("min-height",a.min_height);d.pnotify_history=a.history;d.pnotify_hide=a.hide;var v=i.data("pnotify");if(v==null||typeof v!="object")v=[];a.stack.push=="top"?v=e.merge([d],v):v=e.merge(v,[d]);i.data("pnotify",v);a.stack.push=="top"&&d.pnotify_queue_position(1);a.after_init&&a.after_init(d);if(a.history){var m=i.data("pnotify_history");if(typeof m=="undefined"){m=e("<div />",{"class":"ui-pnotify-history-container "+p.hi_menu,mouseleave:function(){m.animate({top:"-"+t+"px"},{duration:100,queue:!1})}}).append(e("<div />",{"class":"ui-pnotify-history-header",text:a.labels.redisplay})).append(e("<button />",{"class":"ui-pnotify-history-all "+p.hi_btn,text:a.labels.all,mouseenter:function(){e(this).addClass(p.hi_btnhov)},mouseleave:function(){e(this).removeClass(p.hi_btnhov)},click:function(){e.each(v,function(){this.pnotify_history&&(this.is(":visible")?this.pnotify_hide&&this.pnotify_queue_remove():this.pnotify_display&&this.pnotify_display())});return!1}})).append(e("<button />",{"class":"ui-pnotify-history-last "+p.hi_btn,text:a.labels.last,mouseenter:function(){e(this).addClass(p.hi_btnhov)},mouseleave:function(){e(this).removeClass(p.hi_btnhov)},click:function(){var t=e.pnotify.defaults.stack.push=="top",n=t?0:-1,r;do{n==-1?r=v.slice(n):r=v.slice(n,n+1);if(!r[0])return!1;n=t?n+1:n-1}while(!r[0].pnotify_history||r[0].is(":visible"));r[0].pnotify_display&&r[0].pnotify_display();return!1}})).appendTo(r);var g=e("<span />",{"class":"ui-pnotify-history-pulldown "+p.hi_hnd,mouseenter:function(){m.animate({top:"0"},{duration:100,queue:!1})}}).appendTo(m);t=g.offset().top+2;m.css({top:"-"+t+"px"});i.data("pnotify_history",m)}}a.stack.animation=!1;a.auto_display&&d.pnotify_display();return d}});var u=/^on/,a=/^(dbl)?click$|^mouse(move|down|up|over|out|enter|leave)$|^contextmenu$/,f=/^(focus|blur|select|change|reset)$|^key(press|down|up)$/,l=/^(scroll|resize|(un)?load|abort|error)$/,c=function(t,n){var r;t=t.toLowerCase();if(document.createEvent&&this.dispatchEvent){t=t.replace(u,"");if(t.match(a)){e(this).offset();r=document.createEvent("MouseEvents");r.initMouseEvent(t,n.bubbles,n.cancelable,n.view,n.detail,n.screenX,n.screenY,n.clientX,n.clientY,n.ctrlKey,n.altKey,n.shiftKey,n.metaKey,n.button,n.relatedTarget)}else if(t.match(f)){r=document.createEvent("UIEvents");r.initUIEvent(t,n.bubbles,n.cancelable,n.view,n.detail)}else if(t.match(l)){r=document.createEvent("HTMLEvents");r.initEvent(t,n.bubbles,n.cancelable)}if(!r)return;this.dispatchEvent(r)}else{t.match(u)||(t="on"+t);r=document.createEventObject(n);this.fireEvent(t,r)}};e.pnotify.defaults={title:!1,title_escape:!1,text:!1,text_escape:!1,styling:"bootstrap",addclass:"",cornerclass:"",nonblock:!1,nonblock_opacity:.2,history:!0,maxonscreen:Infinity,auto_display:!0,width:"300px",min_height:"16px",type:"notice",icon:!0,animation:"fade",animate_speed:"slow",position_animate_speed:500,opacity:1,shadow:!0,closer:!0,closer_hover:!0,sticker:!0,sticker_hover:!0,hide:!0,delay:8e3,mouse_reset:!0,remove:!0,insert_brs:!0,stack:{dir1:"down",dir2:"left",push:"bottom",spacing1:25,spacing2:25},labels:{redisplay:"Redisplay",all:"All",last:"Last",close:"Close",stick:"Stick"}}})(jQuery); \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/jquery.validVal-packed.js b/src/core/classes/org/glizycms/js/jquery/jquery.validVal-packed.js new file mode 100644 index 0000000..bb768f1 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/jquery.validVal-packed.js @@ -0,0 +1 @@ +/* * jQuery validVal version 4.3.2 * demo's and documentation: * validval.frebsite.nl * * Copyright (c) 2013 Fred Heusschen * www.frebsite.nl * * Dual licensed under the MIT and GPL licenses. * http://en.wikipedia.org/wiki/MIT_License * http://en.wikipedia.org/wiki/GNU_General_Public_License */ eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(6($){5($.E.C){7}x u=\'1B:28( [Q="3p"], [Q="2C"], [Q="2D"] )\',19=u+\', 29, 1l\';$.E.C=$.E.3q=6(o,c,l){5(L.z>1){7 L.1m(6(){$(L).C(o,c)})}5(A o==\'1s\'){l=o;o=1g}J 5(A c==\'1s\'){l=c;c=1g}x m=L,w=$.1L(F,{},$.E.C.2E,o),1Y=$.1L(F,{},$.E.C.2F,c);5(A w.2a==\'6\'){$.E.C.11(\'1M 6 "2a"\',\'"N.1a"\');w.N.1a=w.2a}5(A w.1C==\'6\'){$.E.C.11(\'1M 6 "1C"\',\'"N.1b"\');w.N.1b=w.1C}5(A w.1n==\'6\'){$.E.C.11(\'1M 6 "1n"\',\'"N.1n"\');w.N.1n=w.1n}5(A w.2b==\'6\'){$.E.C.11(\'1M 6 "2b"\',\'"G.1b"\');w.G.1b=w.2b}5(A w.2c==\'6\'){$.E.C.11(\'1M 6 "2c"\',\'"G.1a"\');w.G.1a=w.2c}5(A w.B.2d==\'1s\'){$.E.C.11(\'1N "B.2d"\',\'"B.G.1O"\');w.B.G.1O=w.B.2d}5(A w.B.2e==\'1s\'){$.E.C.11(\'1N "B.2e"\',\'"B.G.1D"\');w.B.G.1D=w.B.2e}5(y(m,\'1t\')){m.T(\'1P.8\')}m.y(\'8-1t\',F);w.O={};5($.E.C.1Q){w.O=$.1L(w.O,$.E.C.1Q)}5(w.1Q){w.O=$.1L(w.O,w.1Q)}w.O=$.1L(w.O,$.E.C.1Z);m.I(\'2G.8\',6(h,i){h.1c();x j=$(i);5(y(j,\'1t\')){j.T(\'1P.8\')}j.y(\'8-1t\',F);2H(j,w);j.I(\'1h.8\',6(a){1R(j);j.1i(X(\'1h\'))});j.I(\'20.8\',6(a){j.Y(X(\'1h\'));j.T(\'B.8\',[w.B.2f])});j.I(\'2g.8\',6(a){5(!21(a.2h)){j.T(\'B.8\',[w.B.2i,D])}});j.I(\'B.8\',6(a,b,c){a.1c();5(b===D){7}5(A c!=\'1s\'){c=F}j.y(\'8-1j\',\'1S\');5((j.K(\':1O\')&&!w.B.G.1O)||(j.K(\':1D\')&&!w.B.G.1D)){7}5(c){1R(j)}5(A w.G.1E==\'6\'){w.G.1E.1d(j[0],m,w.1o)}x d=D,R=1p(j.R());1q(x v 1u w.O){x f=w.O[v];5(1v(j,v)&&A f==\'6\'){5(!f.1d(j[0],R)){d=v;1w}}}x e=(d)?D:F;x g=(e)?(b!==\'1F\'):(b!==\'1S\');j.T(\'1j.8\',[e,g]);2I(j,e);5(c){2j(j)}5(l&&d){$.E.C.2J(\'1F 3r: \'+d)}7 e});j.I(\'1j.8\',6(a,b,c){a.1c();5(A b==\'1s\'){5(b){j.y(\'8-1j\',\'1S\');5(c){2K(j,m,w)}}J{j.y(\'8-1j\',\'3s\');5(c){2L(j,m,w)}}}J{7 y(j,\'1j\')==\'1S\'}});j.I(\'3t.8\',6(a,b){a.1c();x c=y(j,\'O\').1x(\' \');c.Z(b);j.y(\'8-O\',c.1G(\' \'))});j.I(\'3u.8\',6(a,b){a.1c();x c=\' \'+y(j,\'O\')+\' \';c=c.1x(\' \'+b+\' \');j.y(\'8-O\',c.1G(\' \'))});j.I(\'1P.8\',6(a){a.1c();j.2M(\'.8\');j.y(\'8-1t\',D)});5(1H(j)){5(j.R()==\'\'){j.R(y(j,\'H-1e\'))}5(1T(j)){j.1i(X(\'1k\'))}5(j.K(\'1l\')){j.2k(\'1N:3v(\'+y(j,\'H-1I\')+\')\').1i(X(\'1k\'));j.I(\'2l.8\',6(a){5(1T(j)){j.1i(X(\'1k\'))}J{j.Y(X(\'1k\'))}})}}5(2N(j)){$(19).10(\'[1f="\'+j.y(\'8-W\')+\'"]\').I(\'20.8\',6(a){j.T(\'B.8\',[w.B.2f])}).I(\'2g.8\',6(a){5(!21(a.2h)){j.T(\'B.8\',[w.B.2i,D])}})}5(1v(j,\'3w\')){x k=j.M(\'3x\'),22=j.M(\'2O\'),$1U=$(19).10(\'[2O="\'+(3y(22)+1)+\'"]\');5(j.K(\'1l\')){5(22){j.I(\'2l.8\',6(a){5($1U.z){$1U.1h()}})}}J{5(k&&22){j.I(\'2g.8\',6(a){5(j.R().z==k){5(!21(a.2h)){j.T(\'20\');5($1U.z){$1U.1h()}}}})}}}5(1v(j,\'2P\')&&!j.K(\':1D\')){j.1h()}});w.B.G.10($(19,m)).1m(6(){m.T(\'2G.8\',[$(L)])}).10(\'1l, 1B[Q="2m"], 1B[Q="23"]\').I(\'2l.8\',6(a){$(L).T(\'20.8\')});m.I(\'1P.8\',6(a){a.1c();m.2M(\'.8\');w.B.G.10($(19,m)).T(\'1P.8\');m.y(\'8-1t\',D)});m.I(\'B.8\',6(b,c,d){b.1c();5(A c==\'12\'){c=m;d=F}J 5(A d!=\'1s\'){d=D}5(A w.N.1E==\'6\'){w.N.1E.1d(m[0],w.1o)}x e=$(),2n={};w.B.G.10($(19,c)).1m(6(){x a=$(L);5(y(a,\'1t\')){a.T(\'B.8\',[w.B.1C]);x v=a.R();5(y(a,\'1j\')==\'1S\'){5(a.K(\'[Q="23"]\')||a.K(\'[Q="2m"]\')){5(!a.K(\':2Q\')){v=\'\'}}5(A v==\'12\'||v==1g){v=\'\'}5(v.z>0){2n[a.M(\'1f\')]=v}}J{5(w.B.1C!==D){e=e.2o(a)}}}});5(e.z>0){5(A w.N.1a==\'6\'&&d){w.N.1a.1d(m[0],e,w.1o)}7 D}J{5(A w.N.1b==\'6\'&&d){w.N.1b.1d(m[0],w.1o)}7 2n}});m.I(\'2R.8\',6(a){a.1c();x b=m.2p(\'B.8\');5(b){w.B.G.10($(u,m)).1m(6(){1R($(L))})}7 b});m.I(\'2S.8\',6(b){b.1c();5(A w.N.1n==\'6\'){w.N.1n.1d(m[0],w.1o)}w.B.G.10($(19,m)).1m(6(){x a=$(L);5(1H(a)){a.1i(X(\'1k\'));a.R(y(a,\'H-1e\'))}J{a.R(y(a,\'2T-1e\'))}a.T(\'1j.8\',[F,F])});7 D});5(m.K(\'N\')){m.M(\'2U\',\'2U\');m.I(\'2C.8\',6(a){7 m.2p(\'2R.8\')});m.I(\'2D.8\',6(a){7 m.2p(\'2S.8\')})}7 m};$.E.C.2E={\'2q\':0,\'24\':F,\'1o\':\'2V\',\'1Q\':{},\'B\':{\'2f\':F,\'1C\':F,\'2i\':D,\'G\':{\'1O\':D,\'1D\':D,\'10\':6(a){7 a}}},\'G\':{\'1E\':1g,\'1b\':6(){x a=$(L);a.2o(a.2W()).Y(X(\'1F\'))},\'1a\':6(){x a=$(L);a.2o(a.2W()).1i(X(\'1F\'))}},\'N\':{\'1n\':1g,\'1E\':1g,\'1b\':1g,\'1a\':6(a,b){2X(b){U\'3z\':1V=\'3A 3B, 3C 2Y 3D 3E 3F 3G.\';1w;U\'3H\':1V=\'3I, 3J 2Y 3K 3L 3M 3N.\';1w;U\'3O\':1V=\'3Pón, 3Q 3R 3S 3T 3U 3V 3W 3X.\';1w;U\'2V\':2Z:1V=\'3Y, 28 3Z G 41 42 43 44 45.\';1w}46(1V);a.47().1h()}},\'30\':[\'14\'],\'2r\':[\'V\']};$.E.C.1Z={\'14\':6(v){x a=$(L);5(a.K(\'[Q="23"]\')||a.K(\'[Q="2m"]\')){5(a.K(\'[Q="23"]\')){x b=a.M(\'1f\');5(b&&b.z>0){a=$(\'1B[1f="\'+b+\'"]\')}}5(!a.K(\':2Q\')){7 D}}J 5(a.K(\'1l\')){5(1H(a)){5(1T(a)){7 D}}J{5(v.z==0){7 D}}}J{5(v.z==0){7 D}}7 F},\'48\':6(v){7 $.E.C.1Z.14.1d(L,v)},\'15\':6(v){x a=$(L),2s=y(a,\'15\');5(2s.z){a=$(19).10(\':8-15(\'+2s+\')\')}x b=D;a.1m(6(){x f=L;5($.E.C.1Z.14.1d(f,1p($(f).R()))){b=F}});7 b},\'W\':6(v){x a=$(19).10(\'[1f="\'+y($(L),\'W\')+\'"]\');1R(a);x b=1p(a.R());2j(a);7(v==b)},\'1I\':6(v){v=2t(v);5(v.z==0){7 F}5(49(v)){7 D}7 F},\'31\':6(v){5(v.z==0){7 F}x r=/^([a-2u-2v-4a\\.\\-])+\\@(([a-2u-2v-9\\-])+\\.)+([a-2u-2v-9]{2,4})+$/;7 r.32(v)},\'33\':6(v){5(v.z==0){7 F}5(v.34(/^4b\\./)){v="35://"+v}7 v.34(/^(35\\:\\/\\/|4c\\:\\/\\/)(.{4,})$/)},\'V\':6(v){5(v.z==0){7 F}x a=$(L),p=y(a,\'V\');5(p.P(0,1)==\'/\'){p=p.P(1)}5(p.P(p.z-1)==\'/\'){p=p.P(0,p.z-1)}7 4d 4e(p).32(v)}};$.E.C.2F={\'1h\':\'1h\',\'1F\':\'1F\',\'1k\':\'1k\'};$.E.C.2J=6(a){5(A 1J!=\'12\'){5(A 1J.36!=\'12\'){1J.36(\'C: \'+a)}}};$.E.C.11=6(a,b){5(A 1J!=\'12\'){5(A 1J.3a!=\'12\'){1J.3a(a+\' K 4f, 4g \'+b+\' 4h.\')}}};$.E.C.3b={4i:(6(){7\'4j\'1u 3c.4k})(),H:(6(){7\'H\'1u 3c.4l(\'1B\')})()};$.3d[\':\'][\'8-15\']=6(a,b,c){7 2w(\'15\',a,b,c)};$.3d[\':\'][\'8-1y\']=6(a,b,c){7 2w(\'1y\',a,b,c)};6 2w(a,b,c,d){5(!b||!d||!d[3]){7 D}x e=y($(b),a);5(!e.z){7 D}7 e==d[3]}6 1H(a){7 1v(a,\'H\')}6 1T(a){5(1p(a.R())==y(a,\'H-1e\')){7 F}7 D}6 1R(a){5(1H(a)){5(1T(a)&&!a.K(\'1l\')){a.R(\'\');a.Y(X(\'1k\'))}}}6 2j(a){5(1H(a)){5(1p(a.R())==\'\'&&!a.K(\'1l\')){a.R(y(a,\'H-1e\'));a.1i(X(\'1k\'))}}}6 2N(a){7 1v(a,\'W\')}6 3e(a){7 1v(a,\'1y\')}6 2I(a,b){5(3e(a)){x c=y(a,\'1y\');5(c.z){$(19).10(\':8-1y(\'+c+\')\').28(a).1m(6(){$(L).T(\'1j.8\',[b,F])})}}}6 2K(a,f,o){5(A o.G.1b==\'6\'){o.G.1b.1d(a[0],f,o.1o)}}6 2L(a,f,o){5(A o.G.1a==\'6\'){o.G.1a.1d(a[0],f,o.1o)}}6 25(b,a){5(A b.M(a)==\'12\'){7 D}5(b.M(a)===\'D\'||b.M(a)===D){7 D}7 F}6 3f(a,t){5(a.M(\'Q\')==t){7 F}5(a.K(\'1B[Q="\'+t+\'"]\')){7 F}x b=1W(a);5(b.S(\'Q="\'+t+\'"\')!=-1||b.S(\'Q=\\\'\'+t+\'\\\'\')!=-1||b.S(\'Q=\'+t+\'\')!=-1){7 F}7 D}6 2H(b,o){x c=b.M(\'1z\');x e=b.M(\'1A\');5(e&&e.z>0&&!b.1X(\'V\')){5(b.1X(\'W\')){$.E.C.11(\'1f 1u "1A"-3g\',\'1z="W:1f"\');b.Y(\'W\');b.1r(\'1A\');5(o.24){b.y(\'8-W\',e)}J{b.1i(\'W:\'+e)}}5(b.1X(\'14\')){$.E.C.11(\'3h 14 3i 1u 4m "1A"-3g\',\'1z="15:1f"\');b.Y(\'14\');b.1r(\'1A\');5(o.24){b.y(\'8-15\',e)}J{b.1i(\'15:\'+e)}}}5(c&&c.S(\'14:\')!=-1){$.E.C.11(\'3h 14 3i 4n 1z="14:1f"\',\'1z="15:1f"\')}x f=[],26=3j(b,o);5(o.24){x h=y(b,\'O\');5(h.z){f.Z(h)}5(25(b,\'H\')&&b.M(\'H\').z>0){5(!$.E.C.3b.H||$.2x(\'H\',o.2r)==-1){b.y(\'8-H-1e\',b.M(\'H\'))}}x i=y(b,\'H-1e\');5(i.z){1r(b,\'H\',o);f.Z(\'H\')}5(25(b,\'V\')&&b.M(\'V\').z>0){b.y(\'8-V\',b.M(\'V\'));1r(b,\'V\',o);f.Z(\'V\')}x j=[\'W\',\'15\',\'1y\'];1q(x d=0,l=j.z;d<l;d++){5(y(b,j[d]).z){f.Z(j[d])}}x k=[\'14\',\'2P\'];1q(x a=0,l=k.z;a<l;a++){5(25(b,k[a])){f.Z(k[a]);1r(b,k[a],o)}}x m=[\'1I\',\'31\',\'33\'];1q(x t=0,l=m.z;t<l;t++){5(3f(b,m[t])){f.Z(m[t])}}}x c=b.M(\'1z\');5(c&&c.z){5(b.1X(\'H\')){Y(b,\'H\',o);b.y(\'8-H-1e\',26);f.Z(\'H\');26=\'\'}x n=\'W:\',1K=c.S(n);5(1K!=-1){x p=c.P(1K).1x(\' \')[0],2y=p.P(n.z);5(2y.z){b.Y(p);b.y(\'8-W\',2y);f.Z(\'W\')}}5(b.1X(\'V\')){Y(b,\'V\',o);b.y(\'8-V\',27(b,\'1A\'));1r(b,\'1A\',o);f.Z(\'V\')}x q=[\'15\',\'1y\'];1q(x g=0,l=q.z;g<l;g++){x r=q[g]+\':\',1K=c.S(r);5(1K!=-1){x s=c.P(1K).1x(\' \')[0],2z=s.P(r.z);5(2z.z){b.Y(s);b.y(\'8-\'+q[g],2z);f.Z(q[g])}}}}x c=b.M(\'1z\');5(c&&c.z){f.Z(c)}b.y(\'8-O\',f.1G(\' \'));b.y(\'8-2T-1e\',26)}6 1v(a,v){x d=\' \'+y(a,\'O\')+\' \';7 d.S(\' \'+v+\' \')!=-1}6 y(a,d){x v=a.y(\'8-\'+d);5(A v==\'12\'){v=\'\'}7 v}6 1r(b,a,o){5($.2x(a,o.2r)==-1){b.1r(a)}}6 Y(a,c,o){5($.2x(c,o.30)==-1){a.Y(c)}}6 3j(b,o){x c=1W(b);5(b.K(\'1l\')){x d=0,2A=y(b,\'H-1I\');5(2A.z){d=2A}J 5(A o.2q==\'1I\'){d=o.2q}J{b.2k(\'> 1N\').1m(6(n){c=1W($(L));x a=c.1x("\'").1G(\'"\').1x(\'"\').1G(\'\');a=a.P(0,a.S(\'>\'));5(a.S(\'3k=3k\')>-1){d=n}})}b.y(\'8-H-1I\',d);7 27(b.2k(\'> 1N:4o(\'+d+\')\'))}J 5(b.K(\'29\')){c=c.P(c.S(\'>\')+1);c=c.P(0,c.S(\'</29\'));7 c}J{7 27(b)}}6 27(a,b){5(A b==\'12\'){b=\'1e\'}x c=1W(a),2B=c.4p();5(2B.S(b+\'=\')>-1){c=c.P(2B.S(b+\'=\')+(b.z+1));x d=c.P(0,1);5(d==\'"\'||d=="\'"){c=c.P(1);c=c.P(0,c.S(d))}J{c=c.P(0,c.S(\' \'))}7 c}J{7\'\'}}6 1W(a){7 $(\'<3l></3l>\').4q(a.4r()).4s()}6 X(a){5(A 1Y!=\'12\'&&A 1Y[a]!=\'12\'){7 1Y[a]}7 a}6 1p(b){5(b===1g){7\'\'}5(A b==\'3m\'){x c=[];1q(x a 1u b){c[a]=1p(b[a])}7 c}5(A b!=\'3n\'){7\'\'}5(b.z==0){7\'\'}7 b.3o(/^\\s\\s*/,\'\').3o(/\\s\\s*$/,\'\')}6 2t(b){5(b===1g){7\'\'}5(A b==\'3m\'){1q(x a 1u b){b[a]=2t(b[a])}7 b}5(A b!=\'3n\'){7\'\'}5(b.z==0){7\'\'}b=1p(b);x r=[\' \',\'-\',\'+\',\'(\',\')\',\'/\',\'\\\\\'];1q(x i=0,l=r.z;i<l;i++){b=b.1x(r[i]).1G(\'\')}7 b}6 21(a){2X(a){U 9:U 13:U 16:U 17:U 18:U 37:U 38:U 39:U 40:U 4t:7 F;1w;2Z:7 D;1w}}})(4u);',62,279,'|||||if|function|return|vv||||||||||||||||||||||||opts|var|data|length|typeof|validate|validVal|false|fn|true|fields|placeholder|bind|else|is|this|attr|form|validations|substr|type|val|indexOf|trigger|case|pattern|corresponding|getclass|removeClass|push|filter|deprecated|undefined||required|requiredgroup||||inputSelector|onInvalid|onValid|stopPropagation|call|value|name|null|focus|addClass|isValid|inactive|select|each|onReset|language|trim|for|removeAttr|boolean|isValidVal|in|has_validation|break|split|validationgroup|class|alt|input|onSubmit|disabled|onValidate|invalid|join|is_placeholderfield|number|console|start|extend|callback|option|hidden|destroy|customValidations|clear_placeholdervalue|valid|has_placeholdervalue|next|msg|get_outerHtml|hasClass|clss|defaultValidations|blur|preventkeyup|tab|radio|supportHtml5|has_html5_attr|original_value|get_original_value_from_value|not|textarea|invalidFormFunc|validFieldFunc|invalidFieldFunc|hiddenFields|disabledFields|onBlur|keyup|keyCode|onKeyup|restore_placeholdervalue|find|change|checkbox|data_obj|add|triggerHandler|selectPlaceholder|keepAttributes|gr|strip_whitespace|zA|Z0|selector_engine|inArray|corresp|groupname|dal|lal|submit|reset|defaults|classes|addField|get_validations|set_validationgroup|debug|set_valid|set_invalid|unbind|is_correspondingfield|tabindex|autofocus|checked|submitForm|resetForm|original|novalidate|en|parent|switch|alle|default|keepClasses|email|test|url|match|http|log||||error|support|document|expr|is_validationgroupfield|has_html5_type|attribute|grouping|elements|get_original_value|selected|div|object|string|replace|button|validval|validation|NOT|addValidation|removeValidation|eq|autotab|maxlength|parseInt|nl|Let|op|niet|velden|zijn|correct|ingevuld|de|Achtung|nicht|Felder|sind|korrekt|ausgefuellt|es|Atenci|no|se|han|completado|todos|los|campos|correctamente|Attention|all||have|been|filled|out|correctly|alert|first|Required|isNaN|9_|www|https|new|RegExp|DEPRECATED|use|instead|touch|ontouchstart|documentElement|createElement|the|with|nth|toLowerCase|append|clone|html|224|jQuery'.split('|'),0,{})) \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/select2/LICENSE b/src/core/classes/org/glizycms/js/jquery/select2/LICENSE new file mode 100755 index 0000000..627fdde --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/select2/LICENSE @@ -0,0 +1,12 @@ +Copyright 2012 Igor Vaynberg + +Version: @@ver@@ Timestamp: @@timestamp@@ + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in +compliance with the License. You may obtain a copy of the License in the LICENSE file, or 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. \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/select2/README.md b/src/core/classes/org/glizycms/js/jquery/select2/README.md new file mode 100755 index 0000000..3a6dcaf --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/select2/README.md @@ -0,0 +1,68 @@ +Select2 +================= + +Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results. Look and feel of Select2 is based on the excellent [Chosen](http://harvesthq.github.com/chosen/) library. + +To get started -- checkout http://ivaynberg.github.com/select2! + +What Does Select2 Support That Chosen Does Not? +------------------------------------------------- + +* Working with large datasets: Chosen requires the entire dataset to be loaded as `option` tags in the DOM, which limits +it to working with small-ish datasets. Select2 uses a function to find results on-the-fly, which allows it to partially +load results. +* Paging of results: Since Select2 works with large datasets and only loads a small amount of matching results at a time +it has to support paging. Select2 will call the search function when the user scrolls to the bottom of currently loaded +result set allowing for the 'infinite scrolling' of results. +* Custom markup for results: Chosen only supports rendering text results because that is the only markup supported by +`option` tags. Select2 provides an extension point which can be used to produce any kind of markup to represent results. +* Ability to add results on the fly: Select2 provides the ability to add results from the search term entered by the user, which allows it to be used for +tagging. + +Browser Compatibility +-------------------- +* IE 8+ (7 mostly works except for [issue with z-index](https://github.com/ivaynberg/select2/issues/37)) +* Chrome 8+ +* Firefox 3.5+ +* Safari 3+ +* Opera 10.6+ + +Integrations +------------ + +* [Wicket-Select2](https://github.com/ivaynberg/wicket-select2) (Java / Apache Wicket) +* [select2-rails](https://github.com/argerim/select2-rails) (Ruby on Rails) +* [AngularUI](http://angular-ui.github.com/#directives-select2) ([AngularJS](angularjs.org)) +* [Django](https://github.com/applegrew/django-select2) + +Bug tracker +----------- + +Have a bug? Please create an issue here on GitHub! + +https://github.com/ivaynberg/select2/issues + + +Mailing list +------------ + +Have a question? Ask on our mailing list! + +select2@googlegroups.com + +https://groups.google.com/d/forum/select2 + + +Copyright and License +--------------------- + +Copyright 2012 Igor Vaynberg + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in +compliance with the License. You may obtain a copy of the License in the LICENSE file, or 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. \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/jquery/select2/release.sh b/src/core/classes/org/glizycms/js/jquery/select2/release.sh new file mode 100755 index 0000000..6ec395d --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/select2/release.sh @@ -0,0 +1,63 @@ +#!/bin/bash +set -e + +echo -n "Enter the version for this release: " + +read ver + +if [ ! $ver ]; then + echo "Invalid version." + exit +fi + +name="select2" +js="$name.js" +mini="$name.min.js" +css="$name.css" +release="$name-$ver" +tag="release-$ver" +branch="build-$ver" +curbranch=`git branch | grep "*" | sed "s/* //"` +timestamp=$(date) +tokens="s/@@ver@@/$ver/g;s/\@@timestamp@@/$timestamp/g" +remote="github" + +git branch "$branch" +git checkout "$branch" + +echo "Tokenizing..." + +find . -name "$js" | xargs -I{} sed -e "$tokens" -i "" {} +find . -name "$css" | xargs -I{} sed -e "$tokens" -i "" {} + +git add "$js" +git add "$css" + +echo "Minifying..." + +echo "/*" > "$mini" +cat LICENSE | sed "$tokens" >> "$mini" +echo "*/" >> "$mini" + +curl -s \ + -d compilation_level=SIMPLE_OPTIMIZATIONS \ + -d output_format=text \ + -d output_info=compiled_code \ + --data-urlencode "js_code@$js" \ + http://closure-compiler.appspot.com/compile \ + >> "$mini" + +git add "$mini" + +git commit -m "release $ver" + +echo "Tagging..." +git tag -a "$tag" -m "tagged version $ver" +git push "$remote" --tags + +echo "Cleaning Up..." + +git checkout "$curbranch" +git branch -D "$branch" + +echo "Done" diff --git a/src/core/classes/org/glizycms/js/jquery/select2/select2.css b/src/core/classes/org/glizycms/js/jquery/select2/select2.css new file mode 100755 index 0000000..d5aa280 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/select2/select2.css @@ -0,0 +1,524 @@ +/* +Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012 +*/ +.select2-container { + position: relative; + display: inline-block; + /* inline-block for ie7 */ + zoom: 1; + *display: inline; + vertical-align: top; +} + +.select2-container, +.select2-drop, +.select2-search, +.select2-search input{ + /* + Force border-box so that % widths fit the parent + container without overlap because of margin/padding. + + More Info : http://www.quirksmode.org/css/box.html + */ + -moz-box-sizing: border-box; /* firefox */ + -ms-box-sizing: border-box; /* ie */ + -webkit-box-sizing: border-box; /* webkit */ + -khtml-box-sizing: border-box; /* konqueror */ + box-sizing: border-box; /* css3 */ +} + +.select2-container .select2-choice { + background-color: #fff; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.5, white)); + background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 50%); + background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 50%); + background-image: -o-linear-gradient(bottom, #eeeeee 0%, #ffffff 50%); + background-image: -ms-linear-gradient(top, #eeeeee 0%, #ffffff 50%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#ffffff', GradientType = 0); + background-image: linear-gradient(top, #eeeeee 0%, #ffffff 50%); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #aaa; + display: block; + overflow: hidden; + white-space: nowrap; + position: relative; + height: 26px; + line-height: 26px; + padding: 0 0 0 8px; + color: #444; + text-decoration: none; +} + +.select2-container.select2-drop-above .select2-choice +{ + border-bottom-color: #aaa; + -webkit-border-radius:0px 0px 4px 4px; + -moz-border-radius:0px 0px 4px 4px; + border-radius:0px 0px 4px 4px; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.9, white)); + background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 90%); + background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 90%); + background-image: -o-linear-gradient(bottom, #eeeeee 0%, white 90%); + background-image: -ms-linear-gradient(top, #eeeeee 0%,#ffffff 90%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff',GradientType=0 ); + background-image: linear-gradient(top, #eeeeee 0%,#ffffff 90%); +} + +.select2-container .select2-choice span { + margin-right: 26px; + display: block; + overflow: hidden; + white-space: nowrap; + -o-text-overflow: ellipsis; + -ms-text-overflow: ellipsis; + text-overflow: ellipsis; +} + +.select2-container .select2-choice abbr { + display: block; + position: absolute; + right: 26px; + top: 8px; + width: 12px; + height: 12px; + font-size: 1px; + background: url('select2.png') right top no-repeat; + cursor: pointer; + text-decoration: none; + border:0; + outline: 0; +} +.select2-container .select2-choice abbr:hover { + background-position: right -11px; + cursor: pointer; +} + +.select2-drop { + background: #fff; + color: #000; + border: 1px solid #aaa; + border-top: 0; + position: absolute; + top: 100%; + -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + -moz-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + -o-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + z-index: 9999; + width:100%; + margin-top:-1px; + + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +.select2-drop.select2-drop-above { + -webkit-border-radius: 4px 4px 0px 0px; + -moz-border-radius: 4px 4px 0px 0px; + border-radius: 4px 4px 0px 0px; + margin-top:1px; + border-top: 1px solid #aaa; + border-bottom: 0; + + -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); + -moz-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); + -o-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); + box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); +} + +.select2-container .select2-choice div { + -webkit-border-radius: 0 4px 4px 0; + -moz-border-radius: 0 4px 4px 0; + border-radius: 0 4px 4px 0; + -moz-background-clip: padding; + -webkit-background-clip: padding-box; + background-clip: padding-box; + background: #ccc; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee)); + background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%); + background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%); + background-image: -o-linear-gradient(bottom, #ccc 0%, #eee 60%); + background-image: -ms-linear-gradient(top, #cccccc 0%, #eeeeee 60%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#cccccc', endColorstr = '#eeeeee', GradientType = 0); + background-image: linear-gradient(top, #cccccc 0%, #eeeeee 60%); + border-left: 1px solid #aaa; + position: absolute; + right: 0; + top: 0; + display: block; + height: 100%; + width: 18px; +} + +.select2-container .select2-choice div b { + background: url('select2.png') no-repeat 0 1px; + display: block; + width: 100%; + height: 100%; +} + +.select2-search { + display: inline-block; + white-space: nowrap; + z-index: 10000; + min-height: 26px; + width: 100%; + margin: 0; + padding-left: 4px; + padding-right: 4px; +} + +.select2-search-hidden { + display: block; + position: absolute; + left: -10000px; +} + +.select2-search input { + background: #fff url('select2.png') no-repeat 100% -22px; + background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); + background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('select2.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); + background: url('select2.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%); + background: url('select2.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%, #eeeeee 99%); + padding: 4px 20px 4px 5px; + outline: 0; + border: 1px solid #aaa; + font-family: sans-serif; + font-size: 1em; + width:100%; + margin:0; + height:auto !important; + min-height: 26px; + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + border-radius: 0; + -moz-border-radius: 0; + -webkit-border-radius: 0; +} + +.select2-drop.select2-drop-above .select2-search input +{ + margin-top:4px; +} + +.select2-search input.select2-active { + background: #fff url('spinner.gif') no-repeat 100%; + background: url('spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee)); + background: url('spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, white 85%, #eeeeee 99%); + background: url('spinner.gif') no-repeat 100%, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); + background: url('spinner.gif') no-repeat 100%, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%); + background: url('spinner.gif') no-repeat 100%, linear-gradient(top, #ffffff 85%, #eeeeee 99%); +} + + +.select2-container-active .select2-choice, +.select2-container-active .select2-choices { + -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); + -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); + -o-box-shadow : 0 0 5px rgba(0,0,0,.3); + box-shadow : 0 0 5px rgba(0,0,0,.3); + border: 1px solid #5897fb; + outline: none; +} + +.select2-dropdown-open .select2-choice { + border: 1px solid #aaa; + border-bottom-color: transparent; + -webkit-box-shadow: 0 1px 0 #fff inset; + -moz-box-shadow : 0 1px 0 #fff inset; + -o-box-shadow : 0 1px 0 #fff inset; + box-shadow : 0 1px 0 #fff inset; + background-color: #eee; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, white), color-stop(0.5, #eeeeee)); + background-image: -webkit-linear-gradient(center bottom, white 0%, #eeeeee 50%); + background-image: -moz-linear-gradient(center bottom, white 0%, #eeeeee 50%); + background-image: -o-linear-gradient(bottom, white 0%, #eeeeee 50%); + background-image: -ms-linear-gradient(top, #ffffff 0%,#eeeeee 50%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee',GradientType=0 ); + background-image: linear-gradient(top, #ffffff 0%,#eeeeee 50%); + -webkit-border-bottom-left-radius : 0; + -webkit-border-bottom-right-radius: 0; + -moz-border-radius-bottomleft : 0; + -moz-border-radius-bottomright: 0; + border-bottom-left-radius : 0; + border-bottom-right-radius: 0; +} + +.select2-dropdown-open .select2-choice div { + background: transparent; + border-left: none; +} +.select2-dropdown-open .select2-choice div b { + background-position: -18px 1px; +} + +/* results */ +.select2-results { + margin: 4px 4px 4px 0; + padding: 0 0 0 4px; + position: relative; + overflow-x: hidden; + overflow-y: auto; + max-height: 200px; +} + +.select2-results ul.select2-result-sub { + margin: 0 0 0 0; +} + +.select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px } +.select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px } +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px } +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px } +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px } +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px } +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px } + +.select2-results li { + list-style: none; + display: list-item; +} + +.select2-results li.select2-result-with-children > .select2-result-label { + font-weight: bold; +} + +.select2-results .select2-result-label { + padding: 3px 7px 4px; + margin: 0; + cursor: pointer; +} + +.select2-results .select2-highlighted { + background: #3875d7; + color: #fff; +} +.select2-results li em { + background: #feffde; + font-style: normal; +} +.select2-results .select2-highlighted em { + background: transparent; +} +.select2-results .select2-no-results, +.select2-results .select2-searching, +.select2-results .select2-selection-limit { + background: #f4f4f4; + display: list-item; +} + +/* +disabled look for already selected choices in the results dropdown +.select2-results .select2-disabled.select2-highlighted { + color: #666; + background: #f4f4f4; + display: list-item; + cursor: default; +} +.select2-results .select2-disabled { + background: #f4f4f4; + display: list-item; + cursor: default; +} +*/ +.select2-results .select2-disabled { + display: none; +} + +.select2-more-results.select2-active { + background: #f4f4f4 url('spinner.gif') no-repeat 100%; +} + +.select2-more-results { + background: #f4f4f4; + display: list-item; +} + +/* disabled styles */ + +.select2-container.select2-container-disabled .select2-choice { + background-color: #f4f4f4; + background-image: none; + border: 1px solid #ddd; + cursor: default; +} + +.select2-container.select2-container-disabled .select2-choice div { + background-color: #f4f4f4; + background-image: none; + border-left: 0; +} + + +/* multiselect */ + +.select2-container-multi .select2-choices { + background-color: #fff; + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff)); + background-image: -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%); + background-image: -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%); + background-image: -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%); + background-image: -ms-linear-gradient(top, #eeeeee 1%, #ffffff 15%); + background-image: linear-gradient(top, #eeeeee 1%, #ffffff 15%); + border: 1px solid #aaa; + margin: 0; + padding: 0; + cursor: text; + overflow: hidden; + height: auto !important; + height: 1%; + position: relative; +} + +.select2-container-multi .select2-choices { + min-height: 26px; +} + +.select2-container-multi.select2-container-active .select2-choices { + -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); + -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); + -o-box-shadow : 0 0 5px rgba(0,0,0,.3); + box-shadow : 0 0 5px rgba(0,0,0,.3); + border: 1px solid #5897fb; + outline: none; +} +.select2-container-multi .select2-choices li { + float: left; + list-style: none; +} +.select2-container-multi .select2-choices .select2-search-field { + white-space: nowrap; + margin: 0; + padding: 0; +} + +.select2-container-multi .select2-choices .select2-search-field input { + color: #666; + background: transparent !important; + font-family: sans-serif; + font-size: 100%; + height: 15px; + padding: 5px; + margin: 1px 0; + outline: 0; + border: 0; + -webkit-box-shadow: none; + -moz-box-shadow : none; + -o-box-shadow : none; + box-shadow : none; +} + +.select2-container-multi .select2-choices .select2-search-field input.select2-active { + background: #fff url('spinner.gif') no-repeat 100% !important; +} + +.select2-default { + color: #999 !important; +} + +.select2-container-multi .select2-choices .select2-search-choice { + -webkit-border-radius: 3px; + -moz-border-radius : 3px; + border-radius : 3px; + -moz-background-clip : padding; + -webkit-background-clip: padding-box; + background-clip : padding-box; + background-color: #e4e4e4; + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 ); + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee)); + background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%); + -webkit-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05); + -moz-box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05); + box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05); + color: #333; + border: 1px solid #aaaaaa; + line-height: 13px; + padding: 3px 5px 3px 18px; + margin: 3px 0 3px 5px; + position: relative; + cursor: default; +} +.select2-container-multi .select2-choices .select2-search-choice span { + cursor: default; +} +.select2-container-multi .select2-choices .select2-search-choice-focus { + background: #d4d4d4; +} + +.select2-search-choice-close { + display: block; + position: absolute; + right: 3px; + top: 4px; + width: 12px; + height: 13px; + font-size: 1px; + background: url('select2.png') right top no-repeat; + outline: none; +} + +.select2-container-multi .select2-search-choice-close { + left: 3px; +} + + +.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover { + background-position: right -11px; +} +.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close { + background-position: right -11px; +} + +/* disabled styles */ + +.select2-container-multi.select2-container-disabled .select2-choices{ + background-color: #f4f4f4; + background-image: none; + border: 1px solid #ddd; + cursor: default; +} + +.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice { + background-image: none; + background-color: #f4f4f4; + border: 1px solid #ddd; + padding: 3px 5px 3px 5px; +} + +.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { + display: none; +} +/* end multiselect */ + +.select2-result-selectable .select2-match, +.select2-result-unselectable .select2-result-selectable .select2-match { text-decoration: underline; } +.select2-result-unselectable .select2-match { text-decoration: none; } + +.select2-offscreen { position: absolute; left: -10000px; } + +/* Retina-ize icons */ + +@media only screen and (-webkit-min-device-pixel-ratio: 1.5) { + .select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice div b { + background-image: url(select2x2.png) !important; + background-repeat: no-repeat !important; + background-size: 60px 40px !important; + } + .select2-search input { + background-position: 100% -21px !important; + } +} diff --git a/src/core/classes/org/glizycms/js/jquery/select2/select2.js b/src/core/classes/org/glizycms/js/jquery/select2/select2.js new file mode 100755 index 0000000..213f4cf --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/select2/select2.js @@ -0,0 +1,2407 @@ +/* + Copyright 2012 Igor Vaynberg + + Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012 + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in + compliance with the License. You may obtain a copy of the License in the LICENSE file, or 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 ($) { + if(typeof $.fn.each2 == "undefined"){ + $.fn.extend({ + /* + * 4-10 times faster .each replacement + * use it carefully, as it overrides jQuery context of element on each iteration + */ + each2 : function (c) { + var j = $([0]), i = -1, l = this.length; + while ( + ++i < l + && (j.context = j[0] = this[i]) + && c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object + ); + return this; + } + }); + } +})(jQuery); + +(function ($, undefined) { + "use strict"; + /*global document, window, jQuery, console */ + + if (window.Select2 !== undefined) { + return; + } + + var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer; + + KEY = { + TAB: 9, + ENTER: 13, + ESC: 27, + SPACE: 32, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + SHIFT: 16, + CTRL: 17, + ALT: 18, + PAGE_UP: 33, + PAGE_DOWN: 34, + HOME: 36, + END: 35, + BACKSPACE: 8, + DELETE: 46, + isArrow: function (k) { + k = k.which ? k.which : k; + switch (k) { + case KEY.LEFT: + case KEY.RIGHT: + case KEY.UP: + case KEY.DOWN: + return true; + } + return false; + }, + isControl: function (e) { + var k = e.which; + switch (k) { + case KEY.SHIFT: + case KEY.CTRL: + case KEY.ALT: + return true; + } + + if (e.metaKey) return true; + + return false; + }, + isFunctionKey: function (k) { + k = k.which ? k.which : k; + return k >= 112 && k <= 123; + } + }; + + nextUid=(function() { var counter=1; return function() { return counter++; }; }()); + + function indexOf(value, array) { + var i = 0, l = array.length, v; + + if (typeof value === "undefined") { + return -1; + } + + if (value.constructor === String) { + for (; i < l; i = i + 1) if (value.localeCompare(array[i]) === 0) return i; + } else { + for (; i < l; i = i + 1) { + v = array[i]; + if (v.constructor === String) { + if (v.localeCompare(value) === 0) return i; + } else { + if (v === value) return i; + } + } + } + return -1; + } + + /** + * Compares equality of a and b taking into account that a and b may be strings, in which case localeCompare is used + * @param a + * @param b + */ + function equal(a, b) { + if (a === b) return true; + if (a === undefined || b === undefined) return false; + if (a === null || b === null) return false; + if (a.constructor === String) return a.localeCompare(b) === 0; + if (b.constructor === String) return b.localeCompare(a) === 0; + return false; + } + + /** + * Splits the string into an array of values, trimming each value. An empty array is returned for nulls or empty + * strings + * @param string + * @param separator + */ + function splitVal(string, separator) { + var val, i, l; + if (string === null || string.length < 1) return []; + val = string.split(separator); + for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]); + return val; + } + + function getSideBorderPadding(element) { + return element.outerWidth() - element.width(); + } + + function installKeyUpChangeEvent(element) { + var key="keyup-change-value"; + element.bind("keydown", function () { + if ($.data(element, key) === undefined) { + $.data(element, key, element.val()); + } + }); + element.bind("keyup", function () { + var val= $.data(element, key); + if (val !== undefined && element.val() !== val) { + $.removeData(element, key); + element.trigger("keyup-change"); + } + }); + } + + $(document).delegate("body", "mousemove", function (e) { + $.data(document, "select2-lastpos", {x: e.pageX, y: e.pageY}); + }); + + /** + * filters mouse events so an event is fired only if the mouse moved. + * + * filters out mouse events that occur when mouse is stationary but + * the elements under the pointer are scrolled. + */ + function installFilteredMouseMove(element) { + element.bind("mousemove", function (e) { + var lastpos = $.data(document, "select2-lastpos"); + if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) { + $(e.target).trigger("mousemove-filtered", e); + } + }); + } + + /** + * Debounces a function. Returns a function that calls the original fn function only if no invocations have been made + * within the last quietMillis milliseconds. + * + * @param quietMillis number of milliseconds to wait before invoking fn + * @param fn function to be debounced + * @param ctx object to be used as this reference within fn + * @return debounced version of fn + */ + function debounce(quietMillis, fn, ctx) { + ctx = ctx || undefined; + var timeout; + return function () { + var args = arguments; + window.clearTimeout(timeout); + timeout = window.setTimeout(function() { + fn.apply(ctx, args); + }, quietMillis); + }; + } + + /** + * A simple implementation of a thunk + * @param formula function used to lazily initialize the thunk + * @return {Function} + */ + function thunk(formula) { + var evaluated = false, + value; + return function() { + if (evaluated === false) { value = formula(); evaluated = true; } + return value; + }; + }; + + function installDebouncedScroll(threshold, element) { + var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);}); + element.bind("scroll", function (e) { + if (indexOf(e.target, element.get()) >= 0) notify(e); + }); + } + + function killEvent(event) { + event.preventDefault(); + event.stopPropagation(); + } + + function measureTextWidth(e) { + if (!sizer){ + var style = e[0].currentStyle || window.getComputedStyle(e[0], null); + sizer = $("<div></div>").css({ + position: "absolute", + left: "-10000px", + top: "-10000px", + display: "none", + fontSize: style.fontSize, + fontFamily: style.fontFamily, + fontStyle: style.fontStyle, + fontWeight: style.fontWeight, + letterSpacing: style.letterSpacing, + textTransform: style.textTransform, + whiteSpace: "nowrap" + }); + $("body").append(sizer); + } + sizer.text(e.val()); + return sizer.width(); + } + + function markMatch(text, term, markup) { + var match=text.toUpperCase().indexOf(term.toUpperCase()), + tl=term.length; + + if (match<0) { + markup.push(text); + return; + } + + markup.push(text.substring(0, match)); + markup.push("<span class='select2-match'>"); + markup.push(text.substring(match, match + tl)); + markup.push("</span>"); + markup.push(text.substring(match + tl, text.length)); + } + + /** + * Produces an ajax-based query function + * + * @param options object containing configuration paramters + * @param options.transport function that will be used to execute the ajax request. must be compatible with parameters supported by $.ajax + * @param options.url url for the data + * @param options.data a function(searchTerm, pageNumber, context) that should return an object containing query string parameters for the above url. + * @param options.dataType request data type: ajax, jsonp, other datatatypes supported by jQuery's $.ajax function or the transport function if specified + * @param options.traditional a boolean flag that should be true if you wish to use the traditional style of param serialization for the ajax request + * @param options.quietMillis (optional) milliseconds to wait before making the ajaxRequest, helps debounce the ajax function if invoked too often + * @param options.results a function(remoteData, pageNumber) that converts data returned form the remote request to the format expected by Select2. + * The expected format is an object containing the following keys: + * results array of objects that will be used as choices + * more (optional) boolean indicating whether there are more results available + * Example: {results:[{id:1, text:'Red'},{id:2, text:'Blue'}], more:true} + */ + function ajax(options) { + var timeout, // current scheduled but not yet executed request + requestSequence = 0, // sequence used to drop out-of-order responses + handler = null, + quietMillis = options.quietMillis || 100; + + return function (query) { + window.clearTimeout(timeout); + timeout = window.setTimeout(function () { + requestSequence += 1; // increment the sequence + var requestNumber = requestSequence, // this request's sequence number + data = options.data, // ajax data function + transport = options.transport || $.ajax, + traditional = options.traditional || false, + type = options.type || 'GET'; // set type of request (GET or POST) + + data = data.call(this, query.term, query.page, query.context); + + if( null !== handler) { handler.abort(); } + + handler = transport.call(null, { + url: options.url, + dataType: options.dataType, + data: data, + type: type, + traditional: traditional, + success: function (data) { + if (requestNumber < requestSequence) { + return; + } + // TODO 3.0 - replace query.page with query so users have access to term, page, etc. + var results = options.results(data, query.page); + query.callback(results); + } + }); + }, quietMillis); + }; + } + + /** + * Produces a query function that works with a local array + * + * @param options object containing configuration parameters. The options parameter can either be an array or an + * object. + * + * If the array form is used it is assumed that it contains objects with 'id' and 'text' keys. + * + * If the object form is used ti is assumed that it contains 'data' and 'text' keys. The 'data' key should contain + * an array of objects that will be used as choices. These objects must contain at least an 'id' key. The 'text' + * key can either be a String in which case it is expected that each element in the 'data' array has a key with the + * value of 'text' which will be used to match choices. Alternatively, text can be a function(item) that can extract + * the text. + */ + function local(options) { + var data = options, // data elements + dataText, + text = function (item) { return ""+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search + + if (!$.isArray(data)) { + text = data.text; + // if text is not a function we assume it to be a key name + if (!$.isFunction(text)) { + dataText = data.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available + text = function (item) { return item[dataText]; }; + } + data = data.results; + } + + return function (query) { + var t = query.term, filtered = { results: [] }, process; + if (t === "") { + query.callback({results: data}); + return; + } + + process = function(datum, collection) { + var group, attr; + datum = datum[0]; + if (datum.children) { + group = {}; + for (attr in datum) { + if (datum.hasOwnProperty(attr)) group[attr]=datum[attr]; + } + group.children=[]; + $(datum.children).each2(function(i, childDatum) { process(childDatum, group.children); }); + if (group.children.length) { + collection.push(group); + } + } else { + if (query.matcher(t, text(datum))) { + collection.push(datum); + } + } + }; + + $(data).each2(function(i, datum) { process(datum, filtered.results); }); + query.callback(filtered); + }; + } + + // TODO javadoc + function tags(data) { + // TODO even for a function we should probably return a wrapper that does the same object/string check as + // the function for arrays. otherwise only functions that return objects are supported. + if ($.isFunction(data)) { + return data; + } + + // if not a function we assume it to be an array + + return function (query) { + var t = query.term, filtered = {results: []}; + $(data).each(function () { + var isObject = this.text !== undefined, + text = isObject ? this.text : this; + if (t === "" || query.matcher(t, text)) { + filtered.results.push(isObject ? this : {id: this, text: this}); + } + }); + query.callback(filtered); + }; + } + + /** + * Checks if the formatter function should be used. + * + * Throws an error if it is not a function. Returns true if it should be used, + * false if no formatting should be performed. + * + * @param formatter + */ + function checkFormatter(formatter, formatterName) { + if ($.isFunction(formatter)) return true; + if (!formatter) return false; + throw new Error("formatterName must be a function or a falsy value"); + } + + function evaluate(val) { + return $.isFunction(val) ? val() : val; + } + + function countResults(results) { + var count = 0; + $.each(results, function(i, item) { + if (item.children) { + count += countResults(item.children); + } else { + count++; + } + }); + return count; + } + + /** + * Default tokenizer. This function uses breaks the input on substring match of any string from the + * opts.tokenSeparators array and uses opts.createSearchChoice to create the choice object. Both of those + * two options have to be defined in order for the tokenizer to work. + * + * @param input text user has typed so far or pasted into the search field + * @param selection currently selected choices + * @param selectCallback function(choice) callback tho add the choice to selection + * @param opts select2's opts + * @return undefined/null to leave the current input unchanged, or a string to change the input to the returned value + */ + function defaultTokenizer(input, selection, selectCallback, opts) { + var original = input, // store the original so we can compare and know if we need to tell the search to update its text + dupe = false, // check for whether a token we extracted represents a duplicate selected choice + token, // token + index, // position at which the separator was found + i, l, // looping variables + separator; // the matched separator + + if (!opts.createSearchChoice || !opts.tokenSeparators || opts.tokenSeparators.length < 1) return undefined; + + while (true) { + index = -1; + + for (i = 0, l = opts.tokenSeparators.length; i < l; i++) { + separator = opts.tokenSeparators[i]; + index = input.indexOf(separator); + if (index >= 0) break; + } + + if (index < 0) break; // did not find any token separator in the input string, bail + + token = input.substring(0, index); + input = input.substring(index + separator.length); + + if (token.length > 0) { + token = opts.createSearchChoice(token, selection); + if (token !== undefined && token !== null && opts.id(token) !== undefined && opts.id(token) !== null) { + dupe = false; + for (i = 0, l = selection.length; i < l; i++) { + if (equal(opts.id(token), opts.id(selection[i]))) { + dupe = true; break; + } + } + + if (!dupe) selectCallback(token); + } + } + } + + if (original.localeCompare(input) != 0) return input; + } + + /** + * blurs any Select2 container that has focus when an element outside them was clicked or received focus + * + * also takes care of clicks on label tags that point to the source element + */ + $(document).ready(function () { + $(document).delegate("body", "mousedown touchend", function (e) { + var target = $(e.target).closest("div.select2-container").get(0), attr; + if (target) { + $(document).find("div.select2-container-active").each(function () { + if (this !== target) $(this).data("select2").blur(); + }); + } else { + target = $(e.target).closest("div.select2-drop").get(0); + $(document).find("div.select2-drop-active").each(function () { + if (this !== target) $(this).data("select2").blur(); + }); + } + + target=$(e.target); + attr = target.attr("for"); + if ("LABEL" === e.target.tagName && attr && attr.length > 0) { + target = $("#"+attr); + target = target.data("select2"); + if (target !== undefined) { target.focus(); e.preventDefault();} + } + }); + }); + + /** + * Creates a new class + * + * @param superClass + * @param methods + */ + function clazz(SuperClass, methods) { + var constructor = function () {}; + constructor.prototype = new SuperClass; + constructor.prototype.constructor = constructor; + constructor.prototype.parent = SuperClass.prototype; + constructor.prototype = $.extend(constructor.prototype, methods); + return constructor; + } + + AbstractSelect2 = clazz(Object, { + + // abstract + bind: function (func) { + var self = this; + return function () { + func.apply(self, arguments); + }; + }, + + // abstract + init: function (opts) { + var results, search, resultsSelector = ".select2-results"; + + // prepare options + this.opts = opts = this.prepareOpts(opts); + + this.id=opts.id; + + // destroy if called on an existing component + if (opts.element.data("select2") !== undefined && + opts.element.data("select2") !== null) { + this.destroy(); + } + + this.enabled=true; + this.container = this.createContainer(); + + this.containerId="s2id_"+(opts.element.attr("id") || "autogen"+nextUid()); + this.containerSelector="#"+this.containerId.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1'); + this.container.attr("id", this.containerId); + + // cache the body so future lookups are cheap + this.body = thunk(function() { return opts.element.closest("body"); }); + + if (opts.element.attr("class") !== undefined) { + this.container.addClass(opts.element.attr("class").replace(/validate\[[\S ]+] ?/, '')); + } + + this.container.css(evaluate(opts.containerCss)); + this.container.addClass(evaluate(opts.containerCssClass)); + + // swap container for the element + this.opts.element + .data("select2", this) + .hide() + .before(this.container); + this.container.data("select2", this); + + this.dropdown = this.container.find(".select2-drop"); + this.dropdown.addClass(evaluate(opts.dropdownCssClass)); + this.dropdown.data("select2", this); + + this.results = results = this.container.find(resultsSelector); + this.search = search = this.container.find("input.select2-input"); + + search.attr("tabIndex", this.opts.element.attr("tabIndex")); + + this.resultsPage = 0; + this.context = null; + + // initialize the container + this.initContainer(); + this.initContainerWidth(); + + installFilteredMouseMove(this.results); + this.dropdown.delegate(resultsSelector, "mousemove-filtered", this.bind(this.highlightUnderEvent)); + + installDebouncedScroll(80, this.results); + this.dropdown.delegate(resultsSelector, "scroll-debounced", this.bind(this.loadMoreIfNeeded)); + + // if jquery.mousewheel plugin is installed we can prevent out-of-bounds scrolling of results via mousewheel + if ($.fn.mousewheel) { + results.mousewheel(function (e, delta, deltaX, deltaY) { + var top = results.scrollTop(), height; + if (deltaY > 0 && top - deltaY <= 0) { + results.scrollTop(0); + killEvent(e); + } else if (deltaY < 0 && results.get(0).scrollHeight - results.scrollTop() + deltaY <= results.height()) { + results.scrollTop(results.get(0).scrollHeight - results.height()); + killEvent(e); + } + }); + } + + installKeyUpChangeEvent(search); + search.bind("keyup-change", this.bind(this.updateResults)); + search.bind("focus", function () { search.addClass("select2-focused"); if (search.val() === " ") search.val(""); }); + search.bind("blur", function () { search.removeClass("select2-focused");}); + + this.dropdown.delegate(resultsSelector, "mouseup", this.bind(function (e) { + if ($(e.target).closest(".select2-result-selectable:not(.select2-disabled)").length > 0) { + this.highlightUnderEvent(e); + this.selectHighlighted(e); + } else { + this.focusSearch(); + } + killEvent(e); + })); + + // trap all mouse events from leaving the dropdown. sometimes there may be a modal that is listening + // for mouse events outside of itself so it can close itself. since the dropdown is now outside the select2's + // dom it will trigger the popup close, which is not what we want + this.dropdown.bind("click mouseup mousedown", function (e) { e.stopPropagation(); }); + + if ($.isFunction(this.opts.initSelection)) { + // initialize selection based on the current value of the source element + this.initSelection(); + + // if the user has provided a function that can set selection based on the value of the source element + // we monitor the change event on the element and trigger it, allowing for two way synchronization + this.monitorSource(); + } + + if (opts.element.is(":disabled") || opts.element.is("[readonly='readonly']")) this.disable(); + }, + + // abstract + destroy: function () { + var select2 = this.opts.element.data("select2"); + if (select2 !== undefined) { + select2.container.remove(); + select2.dropdown.remove(); + select2.opts.element + .removeData("select2") + .unbind(".select2") + .show(); + } + }, + + // abstract + prepareOpts: function (opts) { + var element, select, idKey, ajaxUrl; + + element = opts.element; + + if (element.get(0).tagName.toLowerCase() === "select") { + this.select = select = opts.element; + } + + if (select) { + // these options are not allowed when attached to a select because they are picked up off the element itself + $.each(["id", "multiple", "ajax", "query", "createSearchChoice", "initSelection", "data", "tags"], function () { + if (this in opts) { + throw new Error("Option '" + this + "' is not allowed for Select2 when attached to a <select> element."); + } + }); + } + + opts = $.extend({}, { + populateResults: function(container, results, query) { + var populate, data, result, children, id=this.opts.id, self=this; + + populate=function(results, container, depth) { + + var i, l, result, selectable, compound, node, label, innerContainer, formatted; + for (i = 0, l = results.length; i < l; i = i + 1) { + + result=results[i]; + selectable=id(result) !== undefined; + compound=result.children && result.children.length > 0; + + node=$("<li></li>"); + node.addClass("select2-results-dept-"+depth); + node.addClass("select2-result"); + node.addClass(selectable ? "select2-result-selectable" : "select2-result-unselectable"); + if (compound) { node.addClass("select2-result-with-children"); } + node.addClass(self.opts.formatResultCssClass(result)); + + label=$("<div></div>"); + label.addClass("select2-result-label"); + + formatted=opts.formatResult(result, label, query); + if (formatted!==undefined) { + label.html(self.opts.escapeMarkup(formatted)); + } + + node.append(label); + + if (compound) { + + innerContainer=$("<ul></ul>"); + innerContainer.addClass("select2-result-sub"); + populate(result.children, innerContainer, depth+1); + node.append(innerContainer); + } + + node.data("select2-data", result); + container.append(node); + } + }; + + populate(results, container, 0); + } + }, $.fn.select2.defaults, opts); + + if (typeof(opts.id) !== "function") { + idKey = opts.id; + opts.id = function (e) { return e[idKey]; }; + } + + if (select) { + opts.query = this.bind(function (query) { + var data = { results: [], more: false }, + term = query.term, + children, firstChild, process; + + process=function(element, collection) { + var group; + if (element.is("option")) { + if (query.matcher(term, element.text(), element)) { + collection.push({id:element.attr("value"), text:element.text(), element: element.get(), css: element.attr("class")}); + } + } else if (element.is("optgroup")) { + group={text:element.attr("label"), children:[], element: element.get(), css: element.attr("class")}; + element.children().each2(function(i, elm) { process(elm, group.children); }); + if (group.children.length>0) { + collection.push(group); + } + } + }; + + children=element.children(); + + // ignore the placeholder option if there is one + if (this.getPlaceholder() !== undefined && children.length > 0) { + firstChild = children[0]; + if ($(firstChild).text() === "") { + children=children.not(firstChild); + } + } + + children.each2(function(i, elm) { process(elm, data.results); }); + + query.callback(data); + }); + // this is needed because inside val() we construct choices from options and there id is hardcoded + opts.id=function(e) { return e.id; }; + opts.formatResultCssClass = function(data) { return data.css; } + } else { + if (!("query" in opts)) { + if ("ajax" in opts) { + ajaxUrl = opts.element.data("ajax-url"); + if (ajaxUrl && ajaxUrl.length > 0) { + opts.ajax.url = ajaxUrl; + } + opts.query = ajax(opts.ajax); + } else if ("data" in opts) { + opts.query = local(opts.data); + } else if ("tags" in opts) { + opts.query = tags(opts.tags); + opts.createSearchChoice = function (term) { return {id: term, text: term}; }; + opts.initSelection = function (element, callback) { + var data = []; + $(splitVal(element.val(), opts.separator)).each(function () { + var id = this, text = this, tags=opts.tags; + if ($.isFunction(tags)) tags=tags(); + $(tags).each(function() { if (equal(this.id, id)) { text = this.text; return false; } }); + data.push({id: id, text: text}); + }); + + callback(data); + }; + } + } + } + if (typeof(opts.query) !== "function") { + throw "query function not defined for Select2 " + opts.element.attr("id"); + } + + return opts; + }, + + /** + * Monitor the original element for changes and update select2 accordingly + */ + // abstract + monitorSource: function () { + this.opts.element.bind("change.select2", this.bind(function (e) { + if (this.opts.element.data("select2-change-triggered") !== true) { + this.initSelection(); + } + })); + }, + + /** + * Triggers the change event on the source element + */ + // abstract + triggerChange: function (details) { + + details = details || {}; + details= $.extend({}, details, { type: "change", val: this.val() }); + // prevents recursive triggering + this.opts.element.data("select2-change-triggered", true); + this.opts.element.trigger(details); + this.opts.element.data("select2-change-triggered", false); + + // some validation frameworks ignore the change event and listen instead to keyup, click for selects + // so here we trigger the click event manually + this.opts.element.click(); + + // ValidationEngine ignorea the change event and listens instead to blur + // so here we trigger the blur event manually if so desired + if (this.opts.blurOnChange) + this.opts.element.blur(); + }, + + + // abstract + enable: function() { + if (this.enabled) return; + + this.enabled=true; + this.container.removeClass("select2-container-disabled"); + }, + + // abstract + disable: function() { + if (!this.enabled) return; + + this.close(); + + this.enabled=false; + this.container.addClass("select2-container-disabled"); + }, + + // abstract + opened: function () { + return this.container.hasClass("select2-dropdown-open"); + }, + + // abstract + positionDropdown: function() { + var offset = this.container.offset(), + height = this.container.outerHeight(), + width = this.container.outerWidth(), + dropHeight = this.dropdown.outerHeight(), + viewportBottom = $(window).scrollTop() + document.documentElement.clientHeight, + dropTop = offset.top + height, + dropLeft = offset.left, + enoughRoomBelow = dropTop + dropHeight <= viewportBottom, + enoughRoomAbove = (offset.top - dropHeight) >= this.body().scrollTop(), + aboveNow = this.dropdown.hasClass("select2-drop-above"), + bodyOffset, + above, + css; + + // console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow); + // console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove); + + // fix positioning when body has an offset and is not position: static + + if (this.body().css('position') !== 'static') { + bodyOffset = this.body().offset(); + dropTop -= bodyOffset.top; + dropLeft -= bodyOffset.left; + } + + // always prefer the current above/below alignment, unless there is not enough room + + if (aboveNow) { + above = true; + if (!enoughRoomAbove && enoughRoomBelow) above = false; + } else { + above = false; + if (!enoughRoomBelow && enoughRoomAbove) above = true; + } + + if (above) { + dropTop = offset.top - dropHeight; + this.container.addClass("select2-drop-above"); + this.dropdown.addClass("select2-drop-above"); + } + else { + this.container.removeClass("select2-drop-above"); + this.dropdown.removeClass("select2-drop-above"); + } + + css = $.extend({ + top: dropTop, + left: dropLeft, + width: width + }, evaluate(this.opts.dropdownCss)); + + this.dropdown.css(css); + }, + + // abstract + shouldOpen: function() { + var event; + + if (this.opened()) return false; + + event = $.Event("open"); + this.opts.element.trigger(event); + return !event.isDefaultPrevented(); + }, + + // abstract + clearDropdownAlignmentPreference: function() { + // clear the classes used to figure out the preference of where the dropdown should be opened + this.container.removeClass("select2-drop-above"); + this.dropdown.removeClass("select2-drop-above"); + }, + + /** + * Opens the dropdown + * + * @return {Boolean} whether or not dropdown was opened. This method will return false if, for example, + * the dropdown is already open, or if the 'open' event listener on the element called preventDefault(). + */ + // abstract + open: function () { + + if (!this.shouldOpen()) return false; + + window.setTimeout(this.bind(this.opening), 1); + + return true; + }, + + /** + * Performs the opening of the dropdown + */ + // abstract + opening: function() { + var cid = this.containerId, selector = this.containerSelector, + scroll = "scroll." + cid, resize = "resize." + cid; + + this.container.parents().each(function() { + $(this).bind(scroll, function() { + var s2 = $(selector); + if (s2.length == 0) { + $(this).unbind(scroll); + } + s2.select2("close"); + }); + }); + + $(window).bind(resize, function() { + var s2 = $(selector); + if (s2.length == 0) { + $(window).unbind(resize); + } + s2.select2("close"); + }); + + this.clearDropdownAlignmentPreference(); + + if (this.search.val() === " ") { this.search.val(""); } + + this.container.addClass("select2-dropdown-open").addClass("select2-container-active"); + + this.updateResults(true); + + if(this.dropdown[0] !== this.body().children().last()[0]) { + this.dropdown.detach().appendTo(this.body()); + } + + this.dropdown.show(); + + this.positionDropdown(); + this.dropdown.addClass("select2-drop-active"); + + this.ensureHighlightVisible(); + + this.focusSearch(); + }, + + // abstract + close: function () { + if (!this.opened()) return; + + var self = this; + + this.container.parents().each(function() { + $(this).unbind("scroll." + self.containerId); + }); + $(window).unbind("resize." + this.containerId); + + this.clearDropdownAlignmentPreference(); + + this.dropdown.hide(); + this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active"); + this.results.empty(); + this.clearSearch(); + + this.opts.element.trigger($.Event("close")); + }, + + // abstract + clearSearch: function () { + + }, + + // abstract + ensureHighlightVisible: function () { + var results = this.results, children, index, child, hb, rb, y, more; + + index = this.highlight(); + + if (index < 0) return; + + if (index == 0) { + + // if the first element is highlighted scroll all the way to the top, + // that way any unselectable headers above it will also be scrolled + // into view + + results.scrollTop(0); + return; + } + + children = results.find(".select2-result-selectable"); + + child = $(children[index]); + + hb = child.offset().top + child.outerHeight(); + + // if this is the last child lets also make sure select2-more-results is visible + if (index === children.length - 1) { + more = results.find("li.select2-more-results"); + if (more.length > 0) { + hb = more.offset().top + more.outerHeight(); + } + } + + rb = results.offset().top + results.outerHeight(); + if (hb > rb) { + results.scrollTop(results.scrollTop() + (hb - rb)); + } + y = child.offset().top - results.offset().top; + + // make sure the top of the element is visible + if (y < 0) { + results.scrollTop(results.scrollTop() + y); // y is negative + } + }, + + // abstract + moveHighlight: function (delta) { + var choices = this.results.find(".select2-result-selectable"), + index = this.highlight(); + + while (index > -1 && index < choices.length) { + index += delta; + var choice = $(choices[index]); + if (choice.hasClass("select2-result-selectable") && !choice.hasClass("select2-disabled")) { + this.highlight(index); + break; + } + } + }, + + // abstract + highlight: function (index) { + var choices = this.results.find(".select2-result-selectable").not(".select2-disabled"); + + if (arguments.length === 0) { + return indexOf(choices.filter(".select2-highlighted")[0], choices.get()); + } + + if (index >= choices.length) index = choices.length - 1; + if (index < 0) index = 0; + + choices.removeClass("select2-highlighted"); + + $(choices[index]).addClass("select2-highlighted"); + this.ensureHighlightVisible(); + + }, + + // abstract + countSelectableResults: function() { + return this.results.find(".select2-result-selectable").not(".select2-disabled").length; + }, + + // abstract + highlightUnderEvent: function (event) { + var el = $(event.target).closest(".select2-result-selectable"); + if (el.length > 0 && !el.is(".select2-highlighted")) { + var choices = this.results.find('.select2-result-selectable'); + this.highlight(choices.index(el)); + } else if (el.length == 0) { + // if we are over an unselectable item remove al highlights + this.results.find(".select2-highlighted").removeClass("select2-highlighted"); + } + }, + + // abstract + loadMoreIfNeeded: function () { + var results = this.results, + more = results.find("li.select2-more-results"), + below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible + offset = -1, // index of first element without data + page = this.resultsPage + 1, + self=this, + term=this.search.val(), + context=this.context; + + if (more.length === 0) return; + below = more.offset().top - results.offset().top - results.height(); + + if (below <= 0) { + more.addClass("select2-active"); + this.opts.query({ + term: term, + page: page, + context: context, + matcher: this.opts.matcher, + callback: this.bind(function (data) { + + // ignore a response if the select2 has been closed before it was received + if (!self.opened()) return; + + + self.opts.populateResults.call(this, results, data.results, {term: term, page: page, context:context}); + + if (data.more===true) { + more.detach().appendTo(results).text(self.opts.formatLoadMore(page+1)); + window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10); + } else { + more.remove(); + } + self.positionDropdown(); + self.resultsPage = page; + })}); + } + }, + + /** + * Default tokenizer function which does nothing + */ + tokenize: function() { + + }, + + /** + * @param initial whether or not this is the call to this method right after the dropdown has been opened + */ + // abstract + updateResults: function (initial) { + var search = this.search, results = this.results, opts = this.opts, data, self=this, input; + + // if the search is currently hidden we do not alter the results + if (initial !== true && (this.showSearchInput === false || !this.opened())) { + return; + } + + search.addClass("select2-active"); + + function postRender() { + results.scrollTop(0); + search.removeClass("select2-active"); + self.positionDropdown(); + } + + function render(html) { + results.html(self.opts.escapeMarkup(html)); + postRender(); + } + + if (opts.maximumSelectionSize >=1) { + data = this.data(); + if ($.isArray(data) && data.length >= opts.maximumSelectionSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) { + render("<li class='select2-selection-limit'>" + opts.formatSelectionTooBig(opts.maximumSelectionSize) + "</li>"); + return; + } + } + + if (search.val().length < opts.minimumInputLength && checkFormatter(opts.formatInputTooShort, "formatInputTooShort")) { + render("<li class='select2-no-results'>" + opts.formatInputTooShort(search.val(), opts.minimumInputLength) + "</li>"); + return; + } + else { + render("<li class='select2-searching'>" + opts.formatSearching() + "</li>"); + } + + // give the tokenizer a chance to pre-process the input + input = this.tokenize(); + if (input != undefined && input != null) { + search.val(input); + } + + this.resultsPage = 1; + opts.query({ + term: search.val(), + page: this.resultsPage, + context: null, + matcher: opts.matcher, + callback: this.bind(function (data) { + var def; // default choice + + // ignore a response if the select2 has been closed before it was received + if (!this.opened()) return; + + // save context, if any + this.context = (data.context===undefined) ? null : data.context; + + // create a default choice and prepend it to the list + if (this.opts.createSearchChoice && search.val() !== "") { + def = this.opts.createSearchChoice.call(null, search.val(), data.results); + if (def !== undefined && def !== null && self.id(def) !== undefined && self.id(def) !== null) { + if ($(data.results).filter( + function () { + return equal(self.id(this), self.id(def)); + }).length === 0) { + data.results.unshift(def); + } + } + } + + if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, "formatNoMatches")) { + render("<li class='select2-no-results'>" + opts.formatNoMatches(search.val()) + "</li>"); + return; + } + + results.empty(); + self.opts.populateResults.call(this, results, data.results, {term: search.val(), page: this.resultsPage, context:null}); + + if (data.more === true && checkFormatter(opts.formatLoadMore, "formatLoadMore")) { + results.append("<li class='select2-more-results'>" + self.opts.escapeMarkup(opts.formatLoadMore(this.resultsPage)) + "</li>"); + window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10); + } + + this.postprocessResults(data, initial); + + postRender(); + })}); + }, + + // abstract + cancel: function () { + this.close(); + }, + + // abstract + blur: function () { + this.close(); + this.container.removeClass("select2-container-active"); + this.dropdown.removeClass("select2-drop-active"); + // synonymous to .is(':focus'), which is available in jquery >= 1.6 + if (this.search[0] === document.activeElement) { this.search.blur(); } + this.clearSearch(); + this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); + }, + + // abstract + focusSearch: function () { + // need to do it here as well as in timeout so it works in IE + this.search.show(); + this.search.focus(); + + /* we do this in a timeout so that current event processing can complete before this code is executed. + this makes sure the search field is focussed even if the current event would blur it */ + window.setTimeout(this.bind(function () { + // reset the value so IE places the cursor at the end of the input box + this.search.show(); + this.search.focus(); + this.search.val(this.search.val()); + }), 10); + }, + + // abstract + selectHighlighted: function () { + var index=this.highlight(), + highlighted=this.results.find(".select2-highlighted").not(".select2-disabled"), + data = highlighted.closest('.select2-result-selectable').data("select2-data"); + if (data) { + highlighted.addClass("select2-disabled"); + this.highlight(index); + this.onSelect(data); + } + }, + + // abstract + getPlaceholder: function () { + return this.opts.element.attr("placeholder") || + this.opts.element.attr("data-placeholder") || // jquery 1.4 compat + this.opts.element.data("placeholder") || + this.opts.placeholder; + }, + + /** + * Get the desired width for the container element. This is + * derived first from option `width` passed to select2, then + * the inline 'style' on the original element, and finally + * falls back to the jQuery calculated element width. + */ + // abstract + initContainerWidth: function () { + function resolveContainerWidth() { + var style, attrs, matches, i, l; + + if (this.opts.width === "off") { + return null; + } else if (this.opts.width === "element"){ + return this.opts.element.outerWidth() === 0 ? 'auto' : this.opts.element.outerWidth() + 'px'; + } else if (this.opts.width === "copy" || this.opts.width === "resolve") { + // check if there is inline style on the element that contains width + style = this.opts.element.attr('style'); + if (style !== undefined) { + attrs = style.split(';'); + for (i = 0, l = attrs.length; i < l; i = i + 1) { + matches = attrs[i].replace(/\s/g, '') + .match(/width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/); + if (matches !== null && matches.length >= 1) + return matches[1]; + } + } + + if (this.opts.width === "resolve") { + // next check if css('width') can resolve a width that is percent based, this is sometimes possible + // when attached to input type=hidden or elements hidden via css + style = this.opts.element.css('width'); + if (style.indexOf("%") > 0) return style; + + // finally, fallback on the calculated width of the element + return (this.opts.element.outerWidth() === 0 ? 'auto' : this.opts.element.outerWidth() + 'px'); + } + + return null; + } else if ($.isFunction(this.opts.width)) { + return this.opts.width(); + } else { + return this.opts.width; + } + }; + + var width = resolveContainerWidth.call(this); + if (width !== null) { + this.container.attr("style", "width: "+width); + } + } + }); + + SingleSelect2 = clazz(AbstractSelect2, { + + // single + + createContainer: function () { + var container = $("<div></div>", { + "class": "select2-container" + }).html([ + " <a href='#' onclick='return false;' class='select2-choice'>", + " <span></span><abbr class='select2-search-choice-close' style='display:none;'></abbr>", + " <div><b></b></div>" , + "</a>", + " <div class='select2-drop select2-offscreen'>" , + " <div class='select2-search'>" , + " <input type='text' autocomplete='off' class='select2-input'/>" , + " </div>" , + " <ul class='select2-results'>" , + " </ul>" , + "</div>"].join("")); + return container; + }, + + // single + opening: function () { + this.search.show(); + this.parent.opening.apply(this, arguments); + this.dropdown.removeClass("select2-offscreen"); + }, + + // single + close: function () { + if (!this.opened()) return; + this.parent.close.apply(this, arguments); + this.dropdown.removeAttr("style").addClass("select2-offscreen").insertAfter(this.selection).show(); + }, + + // single + focus: function () { + this.close(); + this.selection.focus(); + }, + + // single + isFocused: function () { + return this.selection[0] === document.activeElement; + }, + + // single + cancel: function () { + this.parent.cancel.apply(this, arguments); + this.selection.focus(); + }, + + // single + initContainer: function () { + + var selection, + container = this.container, + dropdown = this.dropdown, + clickingInside = false; + + this.selection = selection = container.find(".select2-choice"); + + this.search.bind("keydown", this.bind(function (e) { + if (!this.enabled) return; + + if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) { + // prevent the page from scrolling + killEvent(e); + return; + } + + if (this.opened()) { + switch (e.which) { + case KEY.UP: + case KEY.DOWN: + this.moveHighlight((e.which === KEY.UP) ? -1 : 1); + killEvent(e); + return; + case KEY.TAB: + case KEY.ENTER: + this.selectHighlighted(); + killEvent(e); + return; + case KEY.ESC: + this.cancel(e); + killEvent(e); + return; + } + } else { + + if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) { + return; + } + + if (this.opts.openOnEnter === false && e.which === KEY.ENTER) { + return; + } + + this.open(); + + if (e.which === KEY.ENTER) { + // do not propagate the event otherwise we open, and propagate enter which closes + return; + } + } + })); + + this.search.bind("focus", this.bind(function() { + this.selection.attr("tabIndex", "-1"); + })); + this.search.bind("blur", this.bind(function() { + if (!this.opened()) this.container.removeClass("select2-container-active"); + window.setTimeout(this.bind(function() { this.selection.attr("tabIndex", this.opts.element.attr("tabIndex")); }), 10); + })); + + selection.bind("mousedown", this.bind(function (e) { + clickingInside = true; + + if (this.opened()) { + this.close(); + this.selection.focus(); + } else if (this.enabled) { + this.open(); + } + + clickingInside = false; + })); + + dropdown.bind("mousedown", this.bind(function() { this.search.focus(); })); + + selection.bind("focus", this.bind(function() { + this.container.addClass("select2-container-active"); + // hide the search so the tab key does not focus on it + this.search.attr("tabIndex", "-1"); + })); + + selection.bind("blur", this.bind(function() { + if (!this.opened()) { + this.container.removeClass("select2-container-active"); + } + window.setTimeout(this.bind(function() { this.search.attr("tabIndex", this.opts.element.attr("tabIndex")); }), 10); + })); + + selection.bind("keydown", this.bind(function(e) { + if (!this.enabled) return; + + if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) { + // prevent the page from scrolling + killEvent(e); + return; + } + + if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) + || e.which === KEY.ESC) { + return; + } + + if (this.opts.openOnEnter === false && e.which === KEY.ENTER) { + return; + } + + if (e.which == KEY.DELETE) { + if (this.opts.allowClear) { + this.clear(); + } + return; + } + + this.open(); + + if (e.which === KEY.ENTER) { + // do not propagate the event otherwise we open, and propagate enter which closes + killEvent(e); + return; + } + + // do not set the search input value for non-alpha-numeric keys + // otherwise pressing down results in a '(' being set in the search field + if (e.which < 48 ) { // '0' == 48 + killEvent(e); + return; + } + + var keyWritten = String.fromCharCode(e.which).toLowerCase(); + + if (e.shiftKey) { + keyWritten = keyWritten.toUpperCase(); + } + + // focus the field before calling val so the cursor ends up after the value instead of before + this.search.focus(); + this.search.val(keyWritten); + + // prevent event propagation so it doesnt replay on the now focussed search field and result in double key entry + killEvent(e); + })); + + selection.delegate("abbr", "mousedown", this.bind(function (e) { + if (!this.enabled) return; + this.clear(); + killEvent(e); + this.close(); + this.triggerChange(); + this.selection.focus(); + })); + + this.setPlaceholder(); + + this.search.bind("focus", this.bind(function() { + this.container.addClass("select2-container-active"); + })); + }, + + // single + clear: function() { + this.opts.element.val(""); + this.selection.find("span").empty(); + this.selection.removeData("select2-data"); + this.setPlaceholder(); + }, + + /** + * Sets selection based on source element's value + */ + // single + initSelection: function () { + var selected; + if (this.opts.element.val() === "") { + this.close(); + this.setPlaceholder(); + } else { + var self = this; + this.opts.initSelection.call(null, this.opts.element, function(selected){ + if (selected !== undefined && selected !== null) { + self.updateSelection(selected); + self.close(); + self.setPlaceholder(); + } + }); + } + }, + + // single + prepareOpts: function () { + var opts = this.parent.prepareOpts.apply(this, arguments); + + if (opts.element.get(0).tagName.toLowerCase() === "select") { + // install the selection initializer + opts.initSelection = function (element, callback) { + var selected = element.find(":selected"); + // a single select box always has a value, no need to null check 'selected' + if ($.isFunction(callback)) + callback({id: selected.attr("value"), text: selected.text()}); + }; + } + + return opts; + }, + + // single + setPlaceholder: function () { + var placeholder = this.getPlaceholder(); + + if (this.opts.element.val() === "" && placeholder !== undefined) { + + // check for a first blank option if attached to a select + if (this.select && this.select.find("option:first").text() !== "") return; + + this.selection.find("span").html(this.opts.escapeMarkup(placeholder)); + + this.selection.addClass("select2-default"); + + this.selection.find("abbr").hide(); + } + }, + + // single + postprocessResults: function (data, initial) { + var selected = 0, self = this, showSearchInput = true; + + // find the selected element in the result list + + this.results.find(".select2-result-selectable").each2(function (i, elm) { + if (equal(self.id(elm.data("select2-data")), self.opts.element.val())) { + selected = i; + return false; + } + }); + + // and highlight it + + this.highlight(selected); + + // hide the search box if this is the first we got the results and there are a few of them + + if (initial === true) { + showSearchInput = this.showSearchInput = countResults(data.results) >= this.opts.minimumResultsForSearch; + this.dropdown.find(".select2-search")[showSearchInput ? "removeClass" : "addClass"]("select2-search-hidden"); + + //add "select2-with-searchbox" to the container if search box is shown + $(this.dropdown, this.container)[showSearchInput ? "addClass" : "removeClass"]("select2-with-searchbox"); + } + + }, + + // single + onSelect: function (data) { + var old = this.opts.element.val(); + + this.opts.element.val(this.id(data)); + this.updateSelection(data); + this.close(); + this.selection.focus(); + + if (!equal(old, this.id(data))) { this.triggerChange(); } + }, + + // single + updateSelection: function (data) { + + var container=this.selection.find("span"), formatted; + + this.selection.data("select2-data", data); + + container.empty(); + formatted=this.opts.formatSelection(data, container); + if (formatted !== undefined) { + container.append(this.opts.escapeMarkup(formatted)); + } + + this.selection.removeClass("select2-default"); + + if (this.opts.allowClear && this.getPlaceholder() !== undefined) { + this.selection.find("abbr").show(); + } + }, + + // single + val: function () { + var val, data = null, self = this; + + if (arguments.length === 0) { + return this.opts.element.val(); + } + + val = arguments[0]; + + if (this.select) { + this.select + .val(val) + .find(":selected").each2(function (i, elm) { + data = {id: elm.attr("value"), text: elm.text()}; + return false; + }); + this.updateSelection(data); + this.setPlaceholder(); + } else { + if (this.opts.initSelection === undefined) { + throw new Error("cannot call val() if initSelection() is not defined"); + } + // val is an id. !val is true for [undefined,null,''] + if (!val) { + this.clear(); + return; + } + this.opts.element.val(val); + this.opts.initSelection(this.opts.element, function(data){ + self.opts.element.val(!data ? "" : self.id(data)); + self.updateSelection(data); + self.setPlaceholder(); + }); + } + }, + + // single + clearSearch: function () { + this.search.val(""); + }, + + // single + data: function(value) { + var data; + + if (arguments.length === 0) { + data = this.selection.data("select2-data"); + if (data == undefined) data = null; + return data; + } else { + if (!value || value === "") { + this.clear(); + } else { + this.opts.element.val(!value ? "" : this.id(value)); + this.updateSelection(value); + } + } + } + }); + + MultiSelect2 = clazz(AbstractSelect2, { + + // multi + createContainer: function () { + var container = $("<div></div>", { + "class": "select2-container select2-container-multi" + }).html([ + " <ul class='select2-choices'>", + //"<li class='select2-search-choice'><span>California</span><a href="javascript:void(0)" class="select2-search-choice-close"></a></li>" , + " <li class='select2-search-field'>" , + " <input type='text' autocomplete='off' class='select2-input'>" , + " </li>" , + "</ul>" , + "<div class='select2-drop select2-drop-multi' style='display:none;'>" , + " <ul class='select2-results'>" , + " </ul>" , + "</div>"].join("")); + return container; + }, + + // multi + prepareOpts: function () { + var opts = this.parent.prepareOpts.apply(this, arguments); + + // TODO validate placeholder is a string if specified + + if (opts.element.get(0).tagName.toLowerCase() === "select") { + // install sthe selection initializer + opts.initSelection = function (element,callback) { + + var data = []; + element.find(":selected").each2(function (i, elm) { + data.push({id: elm.attr("value"), text: elm.text()}); + }); + + if ($.isFunction(callback)) + callback(data); + }; + } + + return opts; + }, + + // multi + initContainer: function () { + + var selector = ".select2-choices", selection; + + this.searchContainer = this.container.find(".select2-search-field"); + this.selection = selection = this.container.find(selector); + + this.search.bind("keydown", this.bind(function (e) { + if (!this.enabled) return; + + if (e.which === KEY.BACKSPACE && this.search.val() === "") { + this.close(); + + var choices, + selected = selection.find(".select2-search-choice-focus"); + if (selected.length > 0) { + this.unselect(selected.first()); + this.search.width(10); + killEvent(e); + return; + } + + choices = selection.find(".select2-search-choice"); + if (choices.length > 0) { + choices.last().addClass("select2-search-choice-focus"); + } + } else { + selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); + } + + if (this.opened()) { + switch (e.which) { + case KEY.UP: + case KEY.DOWN: + this.moveHighlight((e.which === KEY.UP) ? -1 : 1); + killEvent(e); + return; + case KEY.ENTER: + case KEY.TAB: + this.selectHighlighted(); + killEvent(e); + return; + case KEY.ESC: + this.cancel(e); + killEvent(e); + return; + } + } + + if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) + || e.which === KEY.BACKSPACE || e.which === KEY.ESC) { + return; + } + + if (this.opts.openOnEnter === false && e.which === KEY.ENTER) { + return; + } + + this.open(); + + if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) { + // prevent the page from scrolling + killEvent(e); + } + })); + + this.search.bind("keyup", this.bind(this.resizeSearch)); + + this.search.bind("blur", this.bind(function(e) { + this.container.removeClass("select2-container-active"); + this.search.removeClass("select2-focused"); + this.clearSearch(); + e.stopImmediatePropagation(); + })); + + this.container.delegate(selector, "mousedown", this.bind(function (e) { + if (!this.enabled) return; + if ($(e.target).closest(".select2-search-choice").length > 0) { + // clicked inside a select2 search choice, do not open + return; + } + this.clearPlaceholder(); + this.open(); + this.focusSearch(); + e.preventDefault(); + })); + + this.container.delegate(selector, "focus", this.bind(function () { + if (!this.enabled) return; + this.container.addClass("select2-container-active"); + this.dropdown.addClass("select2-drop-active"); + this.clearPlaceholder(); + })); + + // set the placeholder if necessary + this.clearSearch(); + }, + + // multi + enable: function() { + if (this.enabled) return; + + this.parent.enable.apply(this, arguments); + + this.search.removeAttr("disabled"); + }, + + // multi + disable: function() { + if (!this.enabled) return; + + this.parent.disable.apply(this, arguments); + + this.search.attr("disabled", true); + }, + + // multi + initSelection: function () { + var data; + if (this.opts.element.val() === "") { + this.updateSelection([]); + this.close(); + // set the placeholder if necessary + this.clearSearch(); + } + if (this.select || this.opts.element.val() !== "") { + var self = this; + this.opts.initSelection.call(null, this.opts.element, function(data){ + if (data !== undefined && data !== null) { + self.updateSelection(data); + self.close(); + // set the placeholder if necessary + self.clearSearch(); + } + }); + } + }, + + // multi + clearSearch: function () { + var placeholder = this.getPlaceholder(); + + if (placeholder !== undefined && this.getVal().length === 0 && this.search.hasClass("select2-focused") === false) { + this.search.val(placeholder).addClass("select2-default"); + // stretch the search box to full width of the container so as much of the placeholder is visible as possible + this.resizeSearch(); + } else { + // we set this to " " instead of "" and later clear it on focus() because there is a firefox bug + // that does not properly render the caret when the field starts out blank + this.search.val(" ").width(10); + } + }, + + // multi + clearPlaceholder: function () { + if (this.search.hasClass("select2-default")) { + this.search.val("").removeClass("select2-default"); + } else { + // work around for the space character we set to avoid firefox caret bug + if (this.search.val() === " ") this.search.val(""); + } + }, + + // multi + opening: function () { + this.parent.opening.apply(this, arguments); + + this.clearPlaceholder(); + this.resizeSearch(); + this.focusSearch(); + }, + + // multi + close: function () { + if (!this.opened()) return; + this.parent.close.apply(this, arguments); + }, + + // multi + focus: function () { + this.close(); + this.search.focus(); + }, + + // multi + isFocused: function () { + return this.search.hasClass("select2-focused"); + }, + + // multi + updateSelection: function (data) { + var ids = [], filtered = [], self = this; + + // filter out duplicates + $(data).each(function () { + if (indexOf(self.id(this), ids) < 0) { + ids.push(self.id(this)); + filtered.push(this); + } + }); + data = filtered; + + this.selection.find(".select2-search-choice").remove(); + $(data).each(function () { + self.addSelectedChoice(this); + }); + self.postprocessResults(); + }, + + tokenize: function() { + var input = this.search.val(); + input = this.opts.tokenizer(input, this.data(), this.bind(this.onSelect), this.opts); + if (input != null && input != undefined) { + this.search.val(input); + if (input.length > 0) { + this.open(); + } + } + + }, + + // multi + onSelect: function (data) { + this.addSelectedChoice(data); + if (this.select) { this.postprocessResults(); } + + if (this.opts.closeOnSelect) { + this.close(); + this.search.width(10); + } else { + if (this.countSelectableResults()>0) { + this.search.width(10); + this.resizeSearch(); + this.positionDropdown(); + } else { + // if nothing left to select close + this.close(); + } + } + + // since its not possible to select an element that has already been + // added we do not need to check if this is a new element before firing change + this.triggerChange({ added: data }); + + this.focusSearch(); + }, + + // multi + cancel: function () { + this.close(); + this.focusSearch(); + }, + + // multi + addSelectedChoice: function (data) { + var choice=$( + "<li class='select2-search-choice'>" + + " <div></div>" + + " <a href='#' onclick='return false;' class='select2-search-choice-close' tabindex='-1'></a>" + + "</li>"), + id = this.id(data), + val = this.getVal(), + formatted; + + formatted=this.opts.formatSelection(data, choice); + choice.find("div").replaceWith("<div>"+this.opts.escapeMarkup(formatted)+"</div>"); + choice.find(".select2-search-choice-close") + .bind("mousedown", killEvent) + .bind("click dblclick", this.bind(function (e) { + if (!this.enabled) return; + + $(e.target).closest(".select2-search-choice").fadeOut('fast', this.bind(function(){ + this.unselect($(e.target)); + this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); + this.close(); + this.focusSearch(); + })).dequeue(); + killEvent(e); + })).bind("focus", this.bind(function () { + if (!this.enabled) return; + this.container.addClass("select2-container-active"); + this.dropdown.addClass("select2-drop-active"); + })); + + choice.data("select2-data", data); + choice.insertBefore(this.searchContainer); + + val.push(id); + this.setVal(val); + }, + + // multi + unselect: function (selected) { + var val = this.getVal(), + data, + index; + + selected = selected.closest(".select2-search-choice"); + + if (selected.length === 0) { + throw "Invalid argument: " + selected + ". Must be .select2-search-choice"; + } + + data = selected.data("select2-data"); + + index = indexOf(this.id(data), val); + + if (index >= 0) { + val.splice(index, 1); + this.setVal(val); + if (this.select) this.postprocessResults(); + } + selected.remove(); + this.triggerChange({ removed: data }); + }, + + // multi + postprocessResults: function () { + var val = this.getVal(), + choices = this.results.find(".select2-result-selectable"), + compound = this.results.find(".select2-result-with-children"), + self = this; + + choices.each2(function (i, choice) { + var id = self.id(choice.data("select2-data")); + if (indexOf(id, val) >= 0) { + choice.addClass("select2-disabled").removeClass("select2-result-selectable"); + } else { + choice.removeClass("select2-disabled").addClass("select2-result-selectable"); + } + }); + + compound.each2(function(i, e) { + if (e.find(".select2-result-selectable").length==0) { + e.addClass("select2-disabled"); + } else { + e.removeClass("select2-disabled"); + } + }); + + choices.each2(function (i, choice) { + if (!choice.hasClass("select2-disabled") && choice.hasClass("select2-result-selectable")) { + self.highlight(0); + return false; + } + }); + + }, + + // multi + resizeSearch: function () { + + var minimumWidth, left, maxWidth, containerLeft, searchWidth, + sideBorderPadding = getSideBorderPadding(this.search); + + minimumWidth = measureTextWidth(this.search) + 10; + + left = this.search.offset().left; + + maxWidth = this.selection.width(); + containerLeft = this.selection.offset().left; + + searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding; + if (searchWidth < minimumWidth) { + searchWidth = maxWidth - sideBorderPadding; + } + + if (searchWidth < 40) { + searchWidth = maxWidth - sideBorderPadding; + } + this.search.width(searchWidth); + }, + + // multi + getVal: function () { + var val; + if (this.select) { + val = this.select.val(); + return val === null ? [] : val; + } else { + val = this.opts.element.val(); + return splitVal(val, this.opts.separator); + } + }, + + // multi + setVal: function (val) { + var unique; + if (this.select) { + this.select.val(val); + } else { + unique = []; + // filter out duplicates + $(val).each(function () { + if (indexOf(this, unique) < 0) unique.push(this); + }); + this.opts.element.val(unique.length === 0 ? "" : unique.join(this.opts.separator)); + } + }, + + // multi + val: function () { + var val, data = [], self=this; + + if (arguments.length === 0) { + return this.getVal(); + } + + val = arguments[0]; + + if (!val) { + this.opts.element.val(""); + this.updateSelection([]); + this.clearSearch(); + return; + } + + // val is a list of ids + this.setVal(val); + + if (this.select) { + this.select.find(":selected").each(function () { + data.push({id: $(this).attr("value"), text: $(this).text()}); + }); + this.updateSelection(data); + } else { + if (this.opts.initSelection === undefined) { + throw new Error("val() cannot be called if initSelection() is not defined") + } + + this.opts.initSelection(this.opts.element, function(data){ + var ids=$(data).map(self.id); + self.setVal(ids); + self.updateSelection(data); + self.clearSearch(); + }); + } + this.clearSearch(); + }, + + // multi + onSortStart: function() { + if (this.select) { + throw new Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead."); + } + + // collapse search field into 0 width so its container can be collapsed as well + this.search.width(0); + // hide the container + this.searchContainer.hide(); + }, + + // multi + onSortEnd:function() { + + var val=[], self=this; + + // show search and move it to the end of the list + this.searchContainer.show(); + // make sure the search container is the last item in the list + this.searchContainer.appendTo(this.searchContainer.parent()); + // since we collapsed the width in dragStarted, we resize it here + this.resizeSearch(); + + // update selection + + this.selection.find(".select2-search-choice").each(function() { + val.push(self.opts.id($(this).data("select2-data"))); + }); + this.setVal(val); + this.triggerChange(); + }, + + // multi + data: function(values) { + var self=this, ids; + if (arguments.length === 0) { + return this.selection + .find(".select2-search-choice") + .map(function() { return $(this).data("select2-data"); }) + .get(); + } else { + if (!values) { values = []; } + ids = $.map(values, function(e) { return self.opts.id(e)}); + this.setVal(ids); + this.updateSelection(values); + this.clearSearch(); + } + } + }); + + $.fn.select2 = function () { + + var args = Array.prototype.slice.call(arguments, 0), + opts, + select2, + value, multiple, allowedMethods = ["val", "destroy", "opened", "open", "close", "focus", "isFocused", "container", "onSortStart", "onSortEnd", "enable", "disable", "positionDropdown", "data"]; + + this.each(function () { + if (args.length === 0 || typeof(args[0]) === "object") { + opts = args.length === 0 ? {} : $.extend({}, args[0]); + opts.element = $(this); + + if (opts.element.get(0).tagName.toLowerCase() === "select") { + multiple = opts.element.attr("multiple"); + } else { + multiple = opts.multiple || false; + if ("tags" in opts) {opts.multiple = multiple = true;} + } + + select2 = multiple ? new MultiSelect2() : new SingleSelect2(); + select2.init(opts); + } else if (typeof(args[0]) === "string") { + + if (indexOf(args[0], allowedMethods) < 0) { + throw "Unknown method: " + args[0]; + } + + value = undefined; + select2 = $(this).data("select2"); + if (select2 === undefined) return; + if (args[0] === "container") { + value=select2.container; + } else { + value = select2[args[0]].apply(select2, args.slice(1)); + } + if (value !== undefined) {return false;} + } else { + throw "Invalid arguments to select2 plugin: " + args; + } + }); + return (value === undefined) ? this : value; + }; + + // plugin defaults, accessible to users + $.fn.select2.defaults = { + width: "copy", + closeOnSelect: true, + openOnEnter: true, + containerCss: {}, + dropdownCss: {}, + containerCssClass: "", + dropdownCssClass: "", + formatResult: function(result, container, query) { + var markup=[]; + markMatch(result.text, query.term, markup); + return markup.join(""); + }, + formatSelection: function (data, container) { + return data ? data.text : undefined; + }, + formatResultCssClass: function(data) {return undefined;}, + formatNoMatches: function () { return "No matches found"; }, + formatInputTooShort: function (input, min) { return "Please enter " + (min - input.length) + " more characters"; }, + formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Loading more results..."; }, + formatSearching: function () { return "Searching..."; }, + minimumResultsForSearch: 0, + minimumInputLength: 0, + maximumSelectionSize: 0, + id: function (e) { return e.id; }, + matcher: function(term, text) { + return text.toUpperCase().indexOf(term.toUpperCase()) >= 0; + }, + separator: ",", + tokenSeparators: [], + tokenizer: defaultTokenizer, + escapeMarkup: function (markup) { + if (markup && typeof(markup) === "string") { + return markup.replace(/&/g, "&amp;"); + } + return markup; + }, + blurOnChange: false + }; + + // exports + window.Select2 = { + query: { + ajax: ajax, + local: local, + tags: tags + }, util: { + debounce: debounce, + markMatch: markMatch + }, "class": { + "abstract": AbstractSelect2, + "single": SingleSelect2, + "multi": MultiSelect2 + } + }; + +}(jQuery)); diff --git a/src/core/classes/org/glizycms/js/jquery/select2/select2.min.js b/src/core/classes/org/glizycms/js/jquery/select2/select2.min.js new file mode 100755 index 0000000..1523735 --- /dev/null +++ b/src/core/classes/org/glizycms/js/jquery/select2/select2.min.js @@ -0,0 +1,82 @@ +/* +Copyright 2012 Igor Vaynberg + +Version: 3.2 Timestamp: Mon Sep 10 10:38:04 PDT 2012 + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in +compliance with the License. You may obtain a copy of the License in the LICENSE file, or 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(e){"undefined"==typeof e.fn.each2&&e.fn.extend({each2:function(g){for(var i=e([0]),m=-1,s=this.length;++m<s&&(i.context=i[0]=this[m])&&!1!==g.call(i[0],m,i););return this}})})(jQuery); +(function(e,g){function i(a,b){var c=0,d=b.length,j;if("undefined"===typeof a)return-1;if(a.constructor===String)for(;c<d;c+=1){if(0===a.localeCompare(b[c]))return c}else for(;c<d;c+=1)if(j=b[c],j.constructor===String){if(0===j.localeCompare(a))return c}else if(j===a)return c;return-1}function m(a,b){return a===b?!0:a===g||b===g||null===a||null===b?!1:a.constructor===String?0===a.localeCompare(b):b.constructor===String?0===b.localeCompare(a):!1}function s(a,b){var c,d,j;if(null===a||1>a.length)return[]; +c=a.split(b);d=0;for(j=c.length;d<j;d+=1)c[d]=e.trim(c[d]);return c}function A(a,b,c){var c=c||g,d;return function(){var j=arguments;window.clearTimeout(d);d=window.setTimeout(function(){b.apply(c,j)},a)}}function l(a){a.preventDefault();a.stopPropagation()}function B(a,b,c){var d=a.toUpperCase().indexOf(b.toUpperCase()),b=b.length;0>d?c.push(a):(c.push(a.substring(0,d)),c.push("<span class='select2-match'>"),c.push(a.substring(d,d+b)),c.push("</span>"),c.push(a.substring(d+b,a.length)))}function C(a){var b, +c=0,d=null,j=a.quietMillis||100;return function(h){window.clearTimeout(b);b=window.setTimeout(function(){var b=c+=1,j=a.data,n=a.transport||e.ajax,f=a.traditional||!1,g=a.type||"GET",j=j.call(this,h.term,h.page,h.context);null!==d&&d.abort();d=n.call(null,{url:a.url,dataType:a.dataType,data:j,type:g,traditional:f,success:function(d){b<c||(d=a.results(d,h.page),h.callback(d))}})},j)}}function D(a){var b=a,c,d=function(a){return""+a.text};e.isArray(b)||(d=b.text,e.isFunction(d)||(c=b.text,d=function(a){return a[c]}), +b=b.results);return function(a){var c=a.term,f={results:[]},k;if(c==="")a.callback({results:b});else{k=function(b,f){var g,t,b=b[0];if(b.children){g={};for(t in b)b.hasOwnProperty(t)&&(g[t]=b[t]);g.children=[];e(b.children).each2(function(a,b){k(b,g.children)});g.children.length&&f.push(g)}else a.matcher(c,d(b))&&f.push(b)};e(b).each2(function(a,b){k(b,f.results)});a.callback(f)}}}function E(a){return e.isFunction(a)?a:function(b){var c=b.term,d={results:[]};e(a).each(function(){var a=this.text!== +g,e=a?this.text:this;if(""===c||b.matcher(c,e))d.results.push(a?this:{id:this,text:this})});b.callback(d)}}function u(a){if(e.isFunction(a))return!0;if(!a)return!1;throw Error("formatterName must be a function or a falsy value");}function v(a){return e.isFunction(a)?a():a}function F(a){var b=0;e.each(a,function(a,d){d.children?b+=F(d.children):b++});return b}function H(a,b,c,d){var e=a,h=!1,f,k,n,o;if(!d.createSearchChoice||!d.tokenSeparators||1>d.tokenSeparators.length)return g;for(;;){h=-1;k=0; +for(n=d.tokenSeparators.length;k<n&&!(o=d.tokenSeparators[k],h=a.indexOf(o),0<=h);k++);if(0>h)break;f=a.substring(0,h);a=a.substring(h+o.length);if(0<f.length&&(f=d.createSearchChoice(f,b),f!==g&&null!==f&&d.id(f)!==g&&null!==d.id(f))){h=!1;k=0;for(n=b.length;k<n;k++)if(m(d.id(f),d.id(b[k]))){h=!0;break}h||c(f)}}if(0!=e.localeCompare(a))return a}function x(a,b){var c=function(){};c.prototype=new a;c.prototype.constructor=c;c.prototype.parent=a.prototype;c.prototype=e.extend(c.prototype,b);return c} +if(window.Select2===g){var f,w,y,z,G,q;f={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,isArrow:function(a){a=a.which?a.which:a;switch(a){case f.LEFT:case f.RIGHT:case f.UP:case f.DOWN:return!0}return!1},isControl:function(a){switch(a.which){case f.SHIFT:case f.CTRL:case f.ALT:return!0}return a.metaKey?!0:!1},isFunctionKey:function(a){a=a.which?a.which:a;return 112<=a&&123>=a}};var I=1;G=function(){return I++}; +e(document).delegate("body","mousemove",function(a){e.data(document,"select2-lastpos",{x:a.pageX,y:a.pageY})});e(document).ready(function(){e(document).delegate("body","mousedown touchend",function(a){var b=e(a.target).closest("div.select2-container").get(0),c;b?e(document).find("div.select2-container-active").each(function(){this!==b&&e(this).data("select2").blur()}):(b=e(a.target).closest("div.select2-drop").get(0),e(document).find("div.select2-drop-active").each(function(){this!==b&&e(this).data("select2").blur()})); +b=e(a.target);c=b.attr("for");"LABEL"===a.target.tagName&&(c&&0<c.length)&&(b=e("#"+c),b=b.data("select2"),b!==g&&(b.focus(),a.preventDefault()))})});w=x(Object,{bind:function(a){var b=this;return function(){a.apply(b,arguments)}},init:function(a){var b,c;this.opts=a=this.prepareOpts(a);this.id=a.id;a.element.data("select2")!==g&&null!==a.element.data("select2")&&this.destroy();this.enabled=!0;this.container=this.createContainer();this.containerId="s2id_"+(a.element.attr("id")||"autogen"+G());this.containerSelector= +"#"+this.containerId.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g,"\\$1");this.container.attr("id",this.containerId);var d=!1,j;this.body=function(){!1===d&&(j=a.element.closest("body"),d=!0);return j};a.element.attr("class")!==g&&this.container.addClass(a.element.attr("class").replace(/validate\[[\S ]+] ?/,""));this.container.css(v(a.containerCss));this.container.addClass(v(a.containerCssClass));this.opts.element.data("select2",this).hide().before(this.container);this.container.data("select2", +this);this.dropdown=this.container.find(".select2-drop");this.dropdown.addClass(v(a.dropdownCssClass));this.dropdown.data("select2",this);this.results=b=this.container.find(".select2-results");this.search=c=this.container.find("input.select2-input");c.attr("tabIndex",this.opts.element.attr("tabIndex"));this.resultsPage=0;this.context=null;this.initContainer();this.initContainerWidth();this.results.bind("mousemove",function(a){var b=e.data(document,"select2-lastpos");(b===g||b.x!==a.pageX||b.y!==a.pageY)&& +e(a.target).trigger("mousemove-filtered",a)});this.dropdown.delegate(".select2-results","mousemove-filtered",this.bind(this.highlightUnderEvent));var h=this.results,f=A(80,function(a){h.trigger("scroll-debounced",a)});h.bind("scroll",function(a){0<=i(a.target,h.get())&&f(a)});this.dropdown.delegate(".select2-results","scroll-debounced",this.bind(this.loadMoreIfNeeded));e.fn.mousewheel&&b.mousewheel(function(a,c,d,e){c=b.scrollTop();0<e&&0>=c-e?(b.scrollTop(0),l(a)):0>e&&b.get(0).scrollHeight-b.scrollTop()+ +e<=b.height()&&(b.scrollTop(b.get(0).scrollHeight-b.height()),l(a))});c.bind("keydown",function(){e.data(c,"keyup-change-value")===g&&e.data(c,"keyup-change-value",c.val())});c.bind("keyup",function(){var a=e.data(c,"keyup-change-value");a!==g&&c.val()!==a&&(e.removeData(c,"keyup-change-value"),c.trigger("keyup-change"))});c.bind("keyup-change",this.bind(this.updateResults));c.bind("focus",function(){c.addClass("select2-focused");" "===c.val()&&c.val("")});c.bind("blur",function(){c.removeClass("select2-focused")}); +this.dropdown.delegate(".select2-results","mouseup",this.bind(function(a){0<e(a.target).closest(".select2-result-selectable:not(.select2-disabled)").length?(this.highlightUnderEvent(a),this.selectHighlighted(a)):this.focusSearch();l(a)}));this.dropdown.bind("click mouseup mousedown",function(a){a.stopPropagation()});e.isFunction(this.opts.initSelection)&&(this.initSelection(),this.monitorSource());(a.element.is(":disabled")||a.element.is("[readonly='readonly']"))&&this.disable()},destroy:function(){var a= +this.opts.element.data("select2");a!==g&&(a.container.remove(),a.dropdown.remove(),a.opts.element.removeData("select2").unbind(".select2").show())},prepareOpts:function(a){var b,c,d;b=a.element;"select"===b.get(0).tagName.toLowerCase()&&(this.select=c=a.element);c&&e.each("id multiple ajax query createSearchChoice initSelection data tags".split(" "),function(){if(this in a)throw Error("Option '"+this+"' is not allowed for Select2 when attached to a <select> element.");});a=e.extend({},{populateResults:function(b, +c,d){var f,n=this.opts.id,o=this;f=function(b,c,j){var h,l,i,m,r,p,q;h=0;for(l=b.length;h<l;h=h+1){i=b[h];m=n(i)!==g;r=i.children&&i.children.length>0;p=e("<li></li>");p.addClass("select2-results-dept-"+j);p.addClass("select2-result");p.addClass(m?"select2-result-selectable":"select2-result-unselectable");r&&p.addClass("select2-result-with-children");p.addClass(o.opts.formatResultCssClass(i));m=e("<div></div>");m.addClass("select2-result-label");q=a.formatResult(i,m,d);q!==g&&m.html(o.opts.escapeMarkup(q)); +p.append(m);if(r){r=e("<ul></ul>");r.addClass("select2-result-sub");f(i.children,r,j+1);p.append(r)}p.data("select2-data",i);c.append(p)}};f(c,b,0)}},e.fn.select2.defaults,a);"function"!==typeof a.id&&(d=a.id,a.id=function(a){return a[d]});if(c)a.query=this.bind(function(a){var c={results:[],more:false},d=a.term,f,n,o;o=function(b,c){var e;if(b.is("option"))a.matcher(d,b.text(),b)&&c.push({id:b.attr("value"),text:b.text(),element:b.get(),css:b.attr("class")});else if(b.is("optgroup")){e={text:b.attr("label"), +children:[],element:b.get(),css:b.attr("class")};b.children().each2(function(a,b){o(b,e.children)});e.children.length>0&&c.push(e)}};f=b.children();if(this.getPlaceholder()!==g&&f.length>0){n=f[0];e(n).text()===""&&(f=f.not(n))}f.each2(function(a,b){o(b,c.results)});a.callback(c)}),a.id=function(a){return a.id},a.formatResultCssClass=function(a){return a.css};else if(!("query"in a))if("ajax"in a){if((c=a.element.data("ajax-url"))&&0<c.length)a.ajax.url=c;a.query=C(a.ajax)}else"data"in a?a.query=D(a.data): +"tags"in a&&(a.query=E(a.tags),a.createSearchChoice=function(a){return{id:a,text:a}},a.initSelection=function(b,c){var d=[];e(s(b.val(),a.separator)).each(function(){var b=this,c=this,j=a.tags;e.isFunction(j)&&(j=j());e(j).each(function(){if(m(this.id,b)){c=this.text;return false}});d.push({id:b,text:c})});c(d)});if("function"!==typeof a.query)throw"query function not defined for Select2 "+a.element.attr("id");return a},monitorSource:function(){this.opts.element.bind("change.select2",this.bind(function(){!0!== +this.opts.element.data("select2-change-triggered")&&this.initSelection()}))},triggerChange:function(a){a=a||{};a=e.extend({},a,{type:"change",val:this.val()});this.opts.element.data("select2-change-triggered",!0);this.opts.element.trigger(a);this.opts.element.data("select2-change-triggered",!1);this.opts.element.click();this.opts.blurOnChange&&this.opts.element.blur()},enable:function(){this.enabled||(this.enabled=!0,this.container.removeClass("select2-container-disabled"))},disable:function(){this.enabled&& +(this.close(),this.enabled=!1,this.container.addClass("select2-container-disabled"))},opened:function(){return this.container.hasClass("select2-dropdown-open")},positionDropdown:function(){var a=this.container.offset(),b=this.container.outerHeight(),c=this.container.outerWidth(),d=this.dropdown.outerHeight(),j=e(window).scrollTop()+document.documentElement.clientHeight,b=a.top+b,f=a.left,j=b+d<=j,g=a.top-d>=this.body().scrollTop(),k=this.dropdown.hasClass("select2-drop-above"),n;"static"!==this.body().css("position")&& +(n=this.body().offset(),b-=n.top,f-=n.left);k?(k=!0,!g&&j&&(k=!1)):(k=!1,!j&&g&&(k=!0));k?(b=a.top-d,this.container.addClass("select2-drop-above"),this.dropdown.addClass("select2-drop-above")):(this.container.removeClass("select2-drop-above"),this.dropdown.removeClass("select2-drop-above"));a=e.extend({top:b,left:f,width:c},v(this.opts.dropdownCss));this.dropdown.css(a)},shouldOpen:function(){var a;if(this.opened())return!1;a=e.Event("open");this.opts.element.trigger(a);return!a.isDefaultPrevented()}, +clearDropdownAlignmentPreference:function(){this.container.removeClass("select2-drop-above");this.dropdown.removeClass("select2-drop-above")},open:function(){if(!this.shouldOpen())return!1;window.setTimeout(this.bind(this.opening),1);return!0},opening:function(){var a=this.containerId,b=this.containerSelector,c="scroll."+a,d="resize."+a;this.container.parents().each(function(){e(this).bind(c,function(){var a=e(b);0==a.length&&e(this).unbind(c);a.select2("close")})});e(window).bind(d,function(){var a= +e(b);0==a.length&&e(window).unbind(d);a.select2("close")});this.clearDropdownAlignmentPreference();" "===this.search.val()&&this.search.val("");this.container.addClass("select2-dropdown-open").addClass("select2-container-active");this.updateResults(!0);this.dropdown[0]!==this.body().children().last()[0]&&this.dropdown.detach().appendTo(this.body());this.dropdown.show();this.positionDropdown();this.dropdown.addClass("select2-drop-active");this.ensureHighlightVisible();this.focusSearch()},close:function(){if(this.opened()){var a= +this;this.container.parents().each(function(){e(this).unbind("scroll."+a.containerId)});e(window).unbind("resize."+this.containerId);this.clearDropdownAlignmentPreference();this.dropdown.hide();this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active");this.results.empty();this.clearSearch();this.opts.element.trigger(e.Event("close"))}},clearSearch:function(){},ensureHighlightVisible:function(){var a=this.results,b,c,d,f;c=this.highlight();0>c||(0==c?a.scrollTop(0): +(b=a.find(".select2-result-selectable"),d=e(b[c]),f=d.offset().top+d.outerHeight(),c===b.length-1&&(b=a.find("li.select2-more-results"),0<b.length&&(f=b.offset().top+b.outerHeight())),b=a.offset().top+a.outerHeight(),f>b&&a.scrollTop(a.scrollTop()+(f-b)),d=d.offset().top-a.offset().top,0>d&&a.scrollTop(a.scrollTop()+d)))},moveHighlight:function(a){for(var b=this.results.find(".select2-result-selectable"),c=this.highlight();-1<c&&c<b.length;){var c=c+a,d=e(b[c]);if(d.hasClass("select2-result-selectable")&& +!d.hasClass("select2-disabled")){this.highlight(c);break}}},highlight:function(a){var b=this.results.find(".select2-result-selectable").not(".select2-disabled");if(0===arguments.length)return i(b.filter(".select2-highlighted")[0],b.get());a>=b.length&&(a=b.length-1);0>a&&(a=0);b.removeClass("select2-highlighted");e(b[a]).addClass("select2-highlighted");this.ensureHighlightVisible()},countSelectableResults:function(){return this.results.find(".select2-result-selectable").not(".select2-disabled").length}, +highlightUnderEvent:function(a){a=e(a.target).closest(".select2-result-selectable");if(0<a.length&&!a.is(".select2-highlighted")){var b=this.results.find(".select2-result-selectable");this.highlight(b.index(a))}else 0==a.length&&this.results.find(".select2-highlighted").removeClass("select2-highlighted")},loadMoreIfNeeded:function(){var a=this.results,b=a.find("li.select2-more-results"),c,d=this.resultsPage+1,e=this,f=this.search.val(),g=this.context;0!==b.length&&(c=b.offset().top-a.offset().top- +a.height(),0>=c&&(b.addClass("select2-active"),this.opts.query({term:f,page:d,context:g,matcher:this.opts.matcher,callback:this.bind(function(c){e.opened()&&(e.opts.populateResults.call(this,a,c.results,{term:f,page:d,context:g}),!0===c.more?(b.detach().appendTo(a).text(e.opts.formatLoadMore(d+1)),window.setTimeout(function(){e.loadMoreIfNeeded()},10)):b.remove(),e.positionDropdown(),e.resultsPage=d)})})))},tokenize:function(){},updateResults:function(a){function b(){f.scrollTop(0);d.removeClass("select2-active"); +k.positionDropdown()}function c(a){f.html(k.opts.escapeMarkup(a));b()}var d=this.search,f=this.results,h=this.opts,i,k=this;if(!(!0!==a&&(!1===this.showSearchInput||!this.opened()))){d.addClass("select2-active");if(1<=h.maximumSelectionSize&&(i=this.data(),e.isArray(i)&&i.length>=h.maximumSelectionSize&&u(h.formatSelectionTooBig,"formatSelectionTooBig"))){c("<li class='select2-selection-limit'>"+h.formatSelectionTooBig(h.maximumSelectionSize)+"</li>");return}d.val().length<h.minimumInputLength&&u(h.formatInputTooShort, +"formatInputTooShort")?c("<li class='select2-no-results'>"+h.formatInputTooShort(d.val(),h.minimumInputLength)+"</li>"):(c("<li class='select2-searching'>"+h.formatSearching()+"</li>"),i=this.tokenize(),i!=g&&null!=i&&d.val(i),this.resultsPage=1,h.query({term:d.val(),page:this.resultsPage,context:null,matcher:h.matcher,callback:this.bind(function(i){var l;this.opened()&&((this.context=i.context===g?null:i.context,this.opts.createSearchChoice&&""!==d.val()&&(l=this.opts.createSearchChoice.call(null, +d.val(),i.results),l!==g&&null!==l&&k.id(l)!==g&&null!==k.id(l)&&0===e(i.results).filter(function(){return m(k.id(this),k.id(l))}).length&&i.results.unshift(l)),0===i.results.length&&u(h.formatNoMatches,"formatNoMatches"))?c("<li class='select2-no-results'>"+h.formatNoMatches(d.val())+"</li>"):(f.empty(),k.opts.populateResults.call(this,f,i.results,{term:d.val(),page:this.resultsPage,context:null}),!0===i.more&&u(h.formatLoadMore,"formatLoadMore")&&(f.append("<li class='select2-more-results'>"+k.opts.escapeMarkup(h.formatLoadMore(this.resultsPage))+ +"</li>"),window.setTimeout(function(){k.loadMoreIfNeeded()},10)),this.postprocessResults(i,a),b()))})}))}},cancel:function(){this.close()},blur:function(){this.close();this.container.removeClass("select2-container-active");this.dropdown.removeClass("select2-drop-active");this.search[0]===document.activeElement&&this.search.blur();this.clearSearch();this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus")},focusSearch:function(){this.search.show();this.search.focus(); +window.setTimeout(this.bind(function(){this.search.show();this.search.focus();this.search.val(this.search.val())}),10)},selectHighlighted:function(){var a=this.highlight(),b=this.results.find(".select2-highlighted").not(".select2-disabled"),c=b.closest(".select2-result-selectable").data("select2-data");c&&(b.addClass("select2-disabled"),this.highlight(a),this.onSelect(c))},getPlaceholder:function(){return this.opts.element.attr("placeholder")||this.opts.element.attr("data-placeholder")||this.opts.element.data("placeholder")|| +this.opts.placeholder},initContainerWidth:function(){var a=function(){var a,c,d,f;if("off"===this.opts.width)return null;if("element"===this.opts.width)return 0===this.opts.element.outerWidth()?"auto":this.opts.element.outerWidth()+"px";if("copy"===this.opts.width||"resolve"===this.opts.width){a=this.opts.element.attr("style");if(a!==g){a=a.split(";");d=0;for(f=a.length;d<f;d+=1)if(c=a[d].replace(/\s/g,"").match(/width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/),null!==c&&1<=c.length)return c[1]}return"resolve"=== +this.opts.width?(a=this.opts.element.css("width"),0<a.indexOf("%")?a:0===this.opts.element.outerWidth()?"auto":this.opts.element.outerWidth()+"px"):null}return e.isFunction(this.opts.width)?this.opts.width():this.opts.width}.call(this);null!==a&&this.container.attr("style","width: "+a)}});y=x(w,{createContainer:function(){return e("<div></div>",{"class":"select2-container"}).html(" <a href='#' onclick='return false;' class='select2-choice'> <span></span><abbr class='select2-search-choice-close' style='display:none;'></abbr> <div><b></b></div></a> <div class='select2-drop select2-offscreen'> <div class='select2-search'> <input type='text' autocomplete='off' class='select2-input'/> </div> <ul class='select2-results'> </ul></div>")}, +opening:function(){this.search.show();this.parent.opening.apply(this,arguments);this.dropdown.removeClass("select2-offscreen")},close:function(){this.opened()&&(this.parent.close.apply(this,arguments),this.dropdown.removeAttr("style").addClass("select2-offscreen").insertAfter(this.selection).show())},focus:function(){this.close();this.selection.focus()},isFocused:function(){return this.selection[0]===document.activeElement},cancel:function(){this.parent.cancel.apply(this,arguments);this.selection.focus()}, +initContainer:function(){var a,b=this.dropdown;this.selection=a=this.container.find(".select2-choice");this.search.bind("keydown",this.bind(function(a){if(this.enabled)if(a.which===f.PAGE_UP||a.which===f.PAGE_DOWN)l(a);else if(this.opened())switch(a.which){case f.UP:case f.DOWN:this.moveHighlight(a.which===f.UP?-1:1);l(a);break;case f.TAB:case f.ENTER:this.selectHighlighted();l(a);break;case f.ESC:this.cancel(a),l(a)}else a.which===f.TAB||f.isControl(a)||f.isFunctionKey(a)||a.which===f.ESC||!1=== +this.opts.openOnEnter&&a.which===f.ENTER||this.open()}));this.search.bind("focus",this.bind(function(){this.selection.attr("tabIndex","-1")}));this.search.bind("blur",this.bind(function(){this.opened()||this.container.removeClass("select2-container-active");window.setTimeout(this.bind(function(){this.selection.attr("tabIndex",this.opts.element.attr("tabIndex"))}),10)}));a.bind("mousedown",this.bind(function(){this.opened()?(this.close(),this.selection.focus()):this.enabled&&this.open()}));b.bind("mousedown", +this.bind(function(){this.search.focus()}));a.bind("focus",this.bind(function(){this.container.addClass("select2-container-active");this.search.attr("tabIndex","-1")}));a.bind("blur",this.bind(function(){this.opened()||this.container.removeClass("select2-container-active");window.setTimeout(this.bind(function(){this.search.attr("tabIndex",this.opts.element.attr("tabIndex"))}),10)}));a.bind("keydown",this.bind(function(a){if(this.enabled)if(a.which===f.PAGE_UP||a.which===f.PAGE_DOWN)l(a);else if(!(a.which=== +f.TAB||f.isControl(a)||f.isFunctionKey(a)||a.which===f.ESC)&&!(!1===this.opts.openOnEnter&&a.which===f.ENTER))if(a.which==f.DELETE)this.opts.allowClear&&this.clear();else{this.open();if(a.which!==f.ENTER&&!(48>a.which)){var b=String.fromCharCode(a.which).toLowerCase();a.shiftKey&&(b=b.toUpperCase());this.search.focus();this.search.val(b)}l(a)}}));a.delegate("abbr","mousedown",this.bind(function(a){this.enabled&&(this.clear(),l(a),this.close(),this.triggerChange(),this.selection.focus())}));this.setPlaceholder(); +this.search.bind("focus",this.bind(function(){this.container.addClass("select2-container-active")}))},clear:function(){this.opts.element.val("");this.selection.find("span").empty();this.selection.removeData("select2-data");this.setPlaceholder()},initSelection:function(){if(""===this.opts.element.val())this.close(),this.setPlaceholder();else{var a=this;this.opts.initSelection.call(null,this.opts.element,function(b){b!==g&&null!==b&&(a.updateSelection(b),a.close(),a.setPlaceholder())})}},prepareOpts:function(){var a= +this.parent.prepareOpts.apply(this,arguments);"select"===a.element.get(0).tagName.toLowerCase()&&(a.initSelection=function(a,c){var d=a.find(":selected");e.isFunction(c)&&c({id:d.attr("value"),text:d.text()})});return a},setPlaceholder:function(){var a=this.getPlaceholder();""===this.opts.element.val()&&a!==g&&!(this.select&&""!==this.select.find("option:first").text())&&(this.selection.find("span").html(this.opts.escapeMarkup(a)),this.selection.addClass("select2-default"),this.selection.find("abbr").hide())}, +postprocessResults:function(a,b){var c=0,d=this,f=!0;this.results.find(".select2-result-selectable").each2(function(a,b){if(m(d.id(b.data("select2-data")),d.opts.element.val()))return c=a,!1});this.highlight(c);!0===b&&(f=this.showSearchInput=F(a.results)>=this.opts.minimumResultsForSearch,this.dropdown.find(".select2-search")[f?"removeClass":"addClass"]("select2-search-hidden"),e(this.dropdown,this.container)[f?"addClass":"removeClass"]("select2-with-searchbox"))},onSelect:function(a){var b=this.opts.element.val(); +this.opts.element.val(this.id(a));this.updateSelection(a);this.close();this.selection.focus();m(b,this.id(a))||this.triggerChange()},updateSelection:function(a){var b=this.selection.find("span");this.selection.data("select2-data",a);b.empty();a=this.opts.formatSelection(a,b);a!==g&&b.append(this.opts.escapeMarkup(a));this.selection.removeClass("select2-default");this.opts.allowClear&&this.getPlaceholder()!==g&&this.selection.find("abbr").show()},val:function(){var a,b=null,c=this;if(0===arguments.length)return this.opts.element.val(); +a=arguments[0];if(this.select)this.select.val(a).find(":selected").each2(function(a,c){b={id:c.attr("value"),text:c.text()};return!1}),this.updateSelection(b),this.setPlaceholder();else{if(this.opts.initSelection===g)throw Error("cannot call val() if initSelection() is not defined");a?(this.opts.element.val(a),this.opts.initSelection(this.opts.element,function(a){c.opts.element.val(!a?"":c.id(a));c.updateSelection(a);c.setPlaceholder()})):this.clear()}},clearSearch:function(){this.search.val("")}, +data:function(a){var b;if(0===arguments.length)return b=this.selection.data("select2-data"),b==g&&(b=null),b;!a||""===a?this.clear():(this.opts.element.val(!a?"":this.id(a)),this.updateSelection(a))}});z=x(w,{createContainer:function(){return e("<div></div>",{"class":"select2-container select2-container-multi"}).html(" <ul class='select2-choices'> <li class='select2-search-field'> <input type='text' autocomplete='off' class='select2-input'> </li></ul><div class='select2-drop select2-drop-multi' style='display:none;'> <ul class='select2-results'> </ul></div>")}, +prepareOpts:function(){var a=this.parent.prepareOpts.apply(this,arguments);"select"===a.element.get(0).tagName.toLowerCase()&&(a.initSelection=function(a,c){var d=[];a.find(":selected").each2(function(a,b){d.push({id:b.attr("value"),text:b.text()})});e.isFunction(c)&&c(d)});return a},initContainer:function(){var a;this.searchContainer=this.container.find(".select2-search-field");this.selection=a=this.container.find(".select2-choices");this.search.bind("keydown",this.bind(function(b){if(this.enabled){if(b.which=== +f.BACKSPACE&&""===this.search.val()){this.close();var c;c=a.find(".select2-search-choice-focus");if(0<c.length){this.unselect(c.first());this.search.width(10);l(b);return}c=a.find(".select2-search-choice");0<c.length&&c.last().addClass("select2-search-choice-focus")}else a.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");if(this.opened())switch(b.which){case f.UP:case f.DOWN:this.moveHighlight(b.which===f.UP?-1:1);l(b);return;case f.ENTER:case f.TAB:this.selectHighlighted(); +l(b);return;case f.ESC:this.cancel(b);l(b);return}if(!(b.which===f.TAB||f.isControl(b)||f.isFunctionKey(b)||b.which===f.BACKSPACE||b.which===f.ESC)&&!(!1===this.opts.openOnEnter&&b.which===f.ENTER))this.open(),(b.which===f.PAGE_UP||b.which===f.PAGE_DOWN)&&l(b)}}));this.search.bind("keyup",this.bind(this.resizeSearch));this.search.bind("blur",this.bind(function(a){this.container.removeClass("select2-container-active");this.search.removeClass("select2-focused");this.clearSearch();a.stopImmediatePropagation()})); +this.container.delegate(".select2-choices","mousedown",this.bind(function(a){this.enabled&&!(0<e(a.target).closest(".select2-search-choice").length)&&(this.clearPlaceholder(),this.open(),this.focusSearch(),a.preventDefault())}));this.container.delegate(".select2-choices","focus",this.bind(function(){this.enabled&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"),this.clearPlaceholder())}));this.clearSearch()},enable:function(){this.enabled||(this.parent.enable.apply(this, +arguments),this.search.removeAttr("disabled"))},disable:function(){this.enabled&&(this.parent.disable.apply(this,arguments),this.search.attr("disabled",!0))},initSelection:function(){""===this.opts.element.val()&&(this.updateSelection([]),this.close(),this.clearSearch());if(this.select||""!==this.opts.element.val()){var a=this;this.opts.initSelection.call(null,this.opts.element,function(b){if(b!==g&&b!==null){a.updateSelection(b);a.close();a.clearSearch()}})}},clearSearch:function(){var a=this.getPlaceholder(); +a!==g&&0===this.getVal().length&&!1===this.search.hasClass("select2-focused")?(this.search.val(a).addClass("select2-default"),this.resizeSearch()):this.search.val(" ").width(10)},clearPlaceholder:function(){this.search.hasClass("select2-default")?this.search.val("").removeClass("select2-default"):" "===this.search.val()&&this.search.val("")},opening:function(){this.parent.opening.apply(this,arguments);this.clearPlaceholder();this.resizeSearch();this.focusSearch()},close:function(){this.opened()&& +this.parent.close.apply(this,arguments)},focus:function(){this.close();this.search.focus()},isFocused:function(){return this.search.hasClass("select2-focused")},updateSelection:function(a){var b=[],c=[],d=this;e(a).each(function(){0>i(d.id(this),b)&&(b.push(d.id(this)),c.push(this))});a=c;this.selection.find(".select2-search-choice").remove();e(a).each(function(){d.addSelectedChoice(this)});d.postprocessResults()},tokenize:function(){var a=this.search.val(),a=this.opts.tokenizer(a,this.data(),this.bind(this.onSelect), +this.opts);null!=a&&a!=g&&(this.search.val(a),0<a.length&&this.open())},onSelect:function(a){this.addSelectedChoice(a);this.select&&this.postprocessResults();this.opts.closeOnSelect?(this.close(),this.search.width(10)):0<this.countSelectableResults()?(this.search.width(10),this.resizeSearch(),this.positionDropdown()):this.close();this.triggerChange({added:a});this.focusSearch()},cancel:function(){this.close();this.focusSearch()},addSelectedChoice:function(a){var b=e("<li class='select2-search-choice'> <div></div> <a href='#' onclick='return false;' class='select2-search-choice-close' tabindex='-1'></a></li>"), +c=this.id(a),d=this.getVal(),f;f=this.opts.formatSelection(a,b);b.find("div").replaceWith("<div>"+this.opts.escapeMarkup(f)+"</div>");b.find(".select2-search-choice-close").bind("mousedown",l).bind("click dblclick",this.bind(function(a){this.enabled&&(e(a.target).closest(".select2-search-choice").fadeOut("fast",this.bind(function(){this.unselect(e(a.target));this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");this.close();this.focusSearch()})).dequeue(), +l(a))})).bind("focus",this.bind(function(){this.enabled&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"))}));b.data("select2-data",a);b.insertBefore(this.searchContainer);d.push(c);this.setVal(d)},unselect:function(a){var b=this.getVal(),c,d,a=a.closest(".select2-search-choice");if(0===a.length)throw"Invalid argument: "+a+". Must be .select2-search-choice";c=a.data("select2-data");d=i(this.id(c),b);0<=d&&(b.splice(d,1),this.setVal(b),this.select&& +this.postprocessResults());a.remove();this.triggerChange({removed:c})},postprocessResults:function(){var a=this.getVal(),b=this.results.find(".select2-result-selectable"),c=this.results.find(".select2-result-with-children"),d=this;b.each2(function(b,c){var e=d.id(c.data("select2-data"));0<=i(e,a)?c.addClass("select2-disabled").removeClass("select2-result-selectable"):c.removeClass("select2-disabled").addClass("select2-result-selectable")});c.each2(function(a,b){0==b.find(".select2-result-selectable").length? +b.addClass("select2-disabled"):b.removeClass("select2-disabled")});b.each2(function(a,b){if(!b.hasClass("select2-disabled")&&b.hasClass("select2-result-selectable"))return d.highlight(0),!1})},resizeSearch:function(){var a,b,c,d,f=this.search.outerWidth()-this.search.width();a=this.search;q||(c=a[0].currentStyle||window.getComputedStyle(a[0],null),q=e("<div></div>").css({position:"absolute",left:"-10000px",top:"-10000px",display:"none",fontSize:c.fontSize,fontFamily:c.fontFamily,fontStyle:c.fontStyle, +fontWeight:c.fontWeight,letterSpacing:c.letterSpacing,textTransform:c.textTransform,whiteSpace:"nowrap"}),e("body").append(q));q.text(a.val());a=q.width()+10;b=this.search.offset().left;c=this.selection.width();d=this.selection.offset().left;b=c-(b-d)-f;b<a&&(b=c-f);40>b&&(b=c-f);this.search.width(b)},getVal:function(){var a;if(this.select)return a=this.select.val(),null===a?[]:a;a=this.opts.element.val();return s(a,this.opts.separator)},setVal:function(a){var b;this.select?this.select.val(a):(b= +[],e(a).each(function(){0>i(this,b)&&b.push(this)}),this.opts.element.val(0===b.length?"":b.join(this.opts.separator)))},val:function(){var a,b=[],c=this;if(0===arguments.length)return this.getVal();if(a=arguments[0])if(this.setVal(a),this.select)this.select.find(":selected").each(function(){b.push({id:e(this).attr("value"),text:e(this).text()})}),this.updateSelection(b);else{if(this.opts.initSelection===g)throw Error("val() cannot be called if initSelection() is not defined");this.opts.initSelection(this.opts.element, +function(a){var b=e(a).map(c.id);c.setVal(b);c.updateSelection(a);c.clearSearch()})}else this.opts.element.val(""),this.updateSelection([]);this.clearSearch()},onSortStart:function(){if(this.select)throw Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead.");this.search.width(0);this.searchContainer.hide()},onSortEnd:function(){var a=[],b=this;this.searchContainer.show();this.searchContainer.appendTo(this.searchContainer.parent());this.resizeSearch(); +this.selection.find(".select2-search-choice").each(function(){a.push(b.opts.id(e(this).data("select2-data")))});this.setVal(a);this.triggerChange()},data:function(a){var b=this,c;if(0===arguments.length)return this.selection.find(".select2-search-choice").map(function(){return e(this).data("select2-data")}).get();a||(a=[]);c=e.map(a,function(a){return b.opts.id(a)});this.setVal(c);this.updateSelection(a);this.clearSearch()}});e.fn.select2=function(){var a=Array.prototype.slice.call(arguments,0),b, +c,d,f,h="val destroy opened open close focus isFocused container onSortStart onSortEnd enable disable positionDropdown data".split(" ");this.each(function(){if(0===a.length||"object"===typeof a[0])b=0===a.length?{}:e.extend({},a[0]),b.element=e(this),"select"===b.element.get(0).tagName.toLowerCase()?f=b.element.attr("multiple"):(f=b.multiple||!1,"tags"in b&&(b.multiple=f=!0)),c=f?new z:new y,c.init(b);else if("string"===typeof a[0]){if(0>i(a[0],h))throw"Unknown method: "+a[0];d=g;c=e(this).data("select2"); +if(c!==g&&(d="container"===a[0]?c.container:c[a[0]].apply(c,a.slice(1)),d!==g))return!1}else throw"Invalid arguments to select2 plugin: "+a;});return d===g?this:d};e.fn.select2.defaults={width:"copy",closeOnSelect:!0,openOnEnter:!0,containerCss:{},dropdownCss:{},containerCssClass:"",dropdownCssClass:"",formatResult:function(a,b,c){b=[];B(a.text,c.term,b);return b.join("")},formatSelection:function(a){return a?a.text:g},formatResultCssClass:function(){return g},formatNoMatches:function(){return"No matches found"}, +formatInputTooShort:function(a,b){return"Please enter "+(b-a.length)+" more characters"},formatSelectionTooBig:function(a){return"You can only select "+a+" item"+(1==a?"":"s")},formatLoadMore:function(){return"Loading more results..."},formatSearching:function(){return"Searching..."},minimumResultsForSearch:0,minimumInputLength:0,maximumSelectionSize:0,id:function(a){return a.id},matcher:function(a,b){return 0<=b.toUpperCase().indexOf(a.toUpperCase())},separator:",",tokenSeparators:[],tokenizer:H, +escapeMarkup:function(a){return a&&"string"===typeof a?a.replace(/&/g,"&amp;"):a},blurOnChange:!1};window.Select2={query:{ajax:C,local:D,tags:E},util:{debounce:A,markMatch:B},"class":{"abstract":w,single:y,multi:z}}}})(jQuery); diff --git a/src/core/classes/org/glizycms/js/jquery/select2/select2.png b/src/core/classes/org/glizycms/js/jquery/select2/select2.png new file mode 100755 index 0000000000000000000000000000000000000000..1d804ffb99699b9e030f1010314de0970b5a000d GIT binary patch literal 613 zcmV-r0-F7aP)<h;3K|Lk000e1NJLTq002Ay001Zm1^@s6qPv;@0006kNkl<Zc-rmR z&r1|x9LMps2uh5F)-GaQDk#Z_4iR>#WY!I$JQV$)A5aAS1BM||2XVJl=+L1^1S1H% zM-&lx?NZpUrHhn>fk<>POqf2sh40}xxGZfc+t+#Eb(q<Oecn6I%nq|DNy|zSyexzN z$5AL0?&Dan9pN5UxC<ug5`<4^!bTJ!40{Z2#(M~pn1C$$pw}f`kJpeHM`McNHFyg? zK;|>Hy9_3*1(U%t9t)QDnI#YAL(|ACV(>)>6WD-t!8tutHkdb^#3`HzoJG3A2@T`% zA|K@o*b!`R#(7)PWrMFn2))Ca3MR4(zaT`Zr61*kZK5NPnZwQszxh$fyv3?&4c>$q z2m=+yc0dRXRAsPDxF6sD;@rK4JGdR_``1S~o6Xi@2&aR6hcSrEp9HVRzEqVDqB<bN zXhRETAUt&UJ4{pqo<W$!4+ziE?D9@4ilQ3gUO=XZ)oyPsiQA7akeNo#WiVk!@H1G( zkAmgh?J@W$gqNtpN{mA2@w%j2(GYBBaKPD;E<cjsBsd99f~(<?&RR6i%jfeou7io} z!W3j)q1|OLVRs>n<1%hR=D4e1f^ra^A|34Cjc=Gny{F(o#MrvPYgZuTJOz(n)-F<| zj()qR;C={)N<0RRvDZ^@6ND+W*}gh-Lip(MDt!(zMSO)!j2j+*hxgzC-e3$@(O2p* zu;+gddm(cZwXTCLx*Ky4THOa*^b^F`woveIeCK^0aR|TJ00000NkvXXu0mjfA#WC6 literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/jquery/select2/select2x2.png b/src/core/classes/org/glizycms/js/jquery/select2/select2x2.png new file mode 100755 index 0000000000000000000000000000000000000000..4bdd5c961d452c49dfa0789c2c7ffb82c238fc24 GIT binary patch literal 845 zcmV-T1G4;yP)<h;3K|Lk000e1NJLTq004LZ002-31^@s6(wnh~0009NNkl<Zc-rlq zv2GJV5I`eA5ebSzqy-%%f8hdLP~9h_qV^Xci^>upQ6WKflyv?C|ADVW!U!t`EpA+x zB)5#EjWk-_X77YJZtQo`E0SF)^1bZr%<ScI;+%s6=ICz#f&syRU}(wBHJi=KJtvV% z&q1&qv^eJpB{$ANuo1Mlh~(%T1ltp=DYaY#8zmuerN1Ub+fTAw3X&{)g1bmADU*y5 zUblqhl?+n{vw|Hrl|2~9qJcUX=wx*w)_|YxX&9mxeE=mzu0C`g40D>)B7Cd`*OK*r z5WG-7e-R9G9^69ksDt29&oyHqxPSt|-S>xi3%PTd+GjY+BGF|nWC(7D-sd(kxqd9~ zS@2YF5vB+>dP8+$l^{oO3-lEWiGA*QI<ZQyKyWv~v4m^Xqu?O1N>U)Wds#9M6RZ9N zcQ4y4)xqQOxD=vwu%7cz1nY#$lT&y8HCmkWgpwQP#3dhnYj9|2aS_R}IUF_^6s#$= zTm%~>A#oM?KIg$kh=<`gJkeoHa2LrulVy$Yx+N_0R3$4I!R*0677f(FKqm`2_o4~W z0h}fQZ`lC^1A+m;fM7uI(R1`S0KtG@KrkQ}5DW+&@cTnDVIow56KciMk7a899t0bC zC1KI<NAq=n6MhK=f(@YLo(pv#^;)>{TsMe5NAR%GD_5`B-@<p{rSMpIB)k$<!Y=ql zC=fhg{GPi}!nVSD;k03YekgqMb862<$PheS!4oBGC%j9%)a;J%LAX>ad4k~K3SO%H z_M31|`HV?E6)u$E3c&*<*n20+V@mRCop>R5;DWuZCmjSo7p@R&OYl<!6QXYf&j`^5 z2wIX~h5Ie!o(UI9@DjnpE|YYF<D+mlkwJf^OtRPLs6AUR@T@`Z1L2FXRdRPirluiy zpsh;Xe!LWZ2ycXE!VBT8@Kdi`MTuYwhYjIDL;SG8HBchh)^TC22*vJVk`Zj@z<=2w zxbkC}P{t%9`0)R&U5Q}xg42=_Y+Z0#a)n^ig42=_Y+P_C8Nv2R^{Fc*c#2>^@G<ZQ XF(xQ&SEjMs00000NkvXXu0mjf{}FjY literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/jquery/select2/spinner.gif b/src/core/classes/org/glizycms/js/jquery/select2/spinner.gif new file mode 100755 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 GIT binary patch literal 1849 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 EAHN$8j{pDw literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/underscore/underscore-min.js b/src/core/classes/org/glizycms/js/underscore/underscore-min.js new file mode 100644 index 0000000..d22f881 --- /dev/null +++ b/src/core/classes/org/glizycms/js/underscore/underscore-min.js @@ -0,0 +1,6 @@ +// Underscore.js 1.5.2 +// http://underscorejs.org +// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. +(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,w=Object.keys,_=i.bind,j=function(n){return n instanceof j?n:this instanceof j?(this._wrapped=n,void 0):new j(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports._=j):n._=j,j.VERSION="1.5.2";var A=j.each=j.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a=j.keys(n),u=0,i=a.length;i>u;u++)if(t.call(e,n[a[u]],a[u],n)===r)return};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var E="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(E);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(E);return r},j.find=j.detect=function(n,t,r){var e;return O(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var O=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:O(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,function(n){return n[t]})},j.where=function(n,t,r){return j.isEmpty(t)?r?void 0:[]:j[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},j.findWhere=function(n,t){return j.where(n,t,!0)},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);if(!t&&j.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>e.computed&&(e={value:n,computed:a})}),e.value},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);if(!t&&j.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a<e.computed&&(e={value:n,computed:a})}),e.value},j.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=j.random(r++),e[r-1]=e[t],e[t]=n}),e},j.sample=function(n,t,r){return arguments.length<2||r?n[j.random(n.length-1)]:j.shuffle(n).slice(0,Math.max(0,t))};var k=function(n){return j.isFunction(n)?n:function(t){return t[n]}};j.sortBy=function(n,t,r){var e=k(t);return j.pluck(j.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={},i=null==r?j.identity:k(r);return A(t,function(r,a){var o=i.call(e,r,a,t);n(u,o,r)}),u}};j.groupBy=F(function(n,t,r){(j.has(n,t)?n[t]:n[t]=[]).push(r)}),j.indexBy=F(function(n,t,r){n[t]=r}),j.countBy=F(function(n,t){j.has(n,t)?n[t]++:n[t]=1}),j.sortedIndex=function(n,t,r,e){r=null==r?j.identity:k(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;r.call(e,n[o])<u?i=o+1:a=o}return i},j.toArray=function(n){return n?j.isArray(n)?o.call(n):n.length===+n.length?j.map(n,j.identity):j.values(n):[]},j.size=function(n){return null==n?0:n.length===+n.length?n.length:j.keys(n).length},j.first=j.head=j.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},j.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},j.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},j.rest=j.tail=j.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},j.compact=function(n){return j.filter(n,j.identity)};var M=function(n,t,r){return t&&j.every(n,j.isArray)?c.apply(r,n):(A(n,function(n){j.isArray(n)||j.isArguments(n)?t?a.apply(r,n):M(n,t,r):r.push(n)}),r)};j.flatten=function(n,t){return M(n,t,[])},j.without=function(n){return j.difference(n,o.call(arguments,1))},j.uniq=j.unique=function(n,t,r,e){j.isFunction(t)&&(e=r,r=t,t=!1);var u=r?j.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:j.contains(a,r))||(a.push(r),i.push(n[e]))}),i},j.union=function(){return j.uniq(j.flatten(arguments,!0))},j.intersection=function(n){var t=o.call(arguments,1);return j.filter(j.uniq(n),function(n){return j.every(t,function(t){return j.indexOf(t,n)>=0})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var R=function(){};j.bind=function(n,t){var r,e;if(_&&n.bind===_)return _.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));R.prototype=n.prototype;var u=new R;R.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},j.bindAll=function(n){var t=o.call(arguments,1);if(0===t.length)throw new Error("bindAll must be passed function names");return A(t,function(t){n[t]=j.bind(n[t],n)}),n},j.memoize=function(n,t){var r={};return t||(t=j.identity),function(){var e=t.apply(this,arguments);return j.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},j.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},j.defer=function(n){return j.delay.apply(j,[n,1].concat(o.call(arguments,1)))},j.throttle=function(n,t,r){var e,u,i,a=null,o=0;r||(r={});var c=function(){o=r.leading===!1?0:new Date,a=null,i=n.apply(e,u)};return function(){var l=new Date;o||r.leading!==!1||(o=l);var f=t-(l-o);return e=this,u=arguments,0>=f?(clearTimeout(a),a=null,o=l,i=n.apply(e,u)):a||r.trailing===!1||(a=setTimeout(c,f)),i}},j.debounce=function(n,t,r){var e,u,i,a,o;return function(){i=this,u=arguments,a=new Date;var c=function(){var l=new Date-a;t>l?e=setTimeout(c,t-l):(e=null,r||(o=n.apply(i,u)))},l=r&&!e;return e||(e=setTimeout(c,t)),l&&(o=n.apply(i,u)),o}},j.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},j.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},j.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},j.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},j.keys=w||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)j.has(n,r)&&t.push(r);return t},j.values=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},j.pairs=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},j.invert=function(n){for(var t={},r=j.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},j.functions=j.methods=function(n){var t=[];for(var r in n)j.isFunction(n[r])&&t.push(r);return t.sort()},j.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},j.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},j.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)j.contains(r,u)||(t[u]=n[u]);return t},j.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]===void 0&&(n[r]=t[r])}),n},j.clone=function(n){return j.isObject(n)?j.isArray(n)?n.slice():j.extend({},n):n},j.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof j&&(n=n._wrapped),t instanceof j&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==String(t);case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var a=n.constructor,o=t.constructor;if(a!==o&&!(j.isFunction(a)&&a instanceof a&&j.isFunction(o)&&o instanceof o))return!1;r.push(n),e.push(t);var c=0,f=!0;if("[object Array]"==u){if(c=n.length,f=c==t.length)for(;c--&&(f=S(n[c],t[c],r,e)););}else{for(var s in n)if(j.has(n,s)&&(c++,!(f=j.has(t,s)&&S(n[s],t[s],r,e))))break;if(f){for(s in t)if(j.has(t,s)&&!c--)break;f=!c}}return r.pop(),e.pop(),f};j.isEqual=function(n,t){return S(n,t,[],[])},j.isEmpty=function(n){if(null==n)return!0;if(j.isArray(n)||j.isString(n))return 0===n.length;for(var t in n)if(j.has(n,t))return!1;return!0},j.isElement=function(n){return!(!n||1!==n.nodeType)},j.isArray=x||function(n){return"[object Array]"==l.call(n)},j.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){j["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),j.isArguments(arguments)||(j.isArguments=function(n){return!(!n||!j.has(n,"callee"))}),"function"!=typeof/./&&(j.isFunction=function(n){return"function"==typeof n}),j.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},j.isNaN=function(n){return j.isNumber(n)&&n!=+n},j.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},j.isNull=function(n){return null===n},j.isUndefined=function(n){return n===void 0},j.has=function(n,t){return f.call(n,t)},j.noConflict=function(){return n._=t,this},j.identity=function(n){return n},j.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},j.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var I={escape:{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;"}};I.unescape=j.invert(I.escape);var T={escape:new RegExp("["+j.keys(I.escape).join("")+"]","g"),unescape:new RegExp("("+j.keys(I.unescape).join("|")+")","g")};j.each(["escape","unescape"],function(n){j[n]=function(t){return null==t?"":(""+t).replace(T[n],function(t){return I[n][t]})}}),j.result=function(n,t){if(null==n)return void 0;var r=n[t];return j.isFunction(r)?r.call(n):r},j.mixin=function(n){A(j.functions(n),function(t){var r=j[t]=n[t];j.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(j,n))}})};var N=0;j.uniqueId=function(n){var t=++N+"";return n?n+t:t},j.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;j.template=function(n,t,r){var e;r=j.defaults({},r,j.templateSettings);var u=new RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(D,function(n){return"\\"+B[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=new Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,j);var c=function(n){return e.call(this,n,j)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},j.chain=function(n){return j(n).chain()};var z=function(n){return this._chain?j(n).chain():n};j.mixin(j),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];j.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];j.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),j.extend(j.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); +//# sourceMappingURL=underscore-min.map \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/underscore/underscore-min.map b/src/core/classes/org/glizycms/js/underscore/underscore-min.map new file mode 100644 index 0000000..4fbe0ba --- /dev/null +++ b/src/core/classes/org/glizycms/js/underscore/underscore-min.map @@ -0,0 +1 @@ +{"version":3,"file":"underscore-min.js","sources":["underscore.js"],"names":["root","this","previousUnderscore","_","breaker","ArrayProto","Array","prototype","ObjProto","Object","FuncProto","Function","push","slice","concat","toString","hasOwnProperty","nativeForEach","forEach","nativeMap","map","nativeReduce","reduce","nativeReduceRight","reduceRight","nativeFilter","filter","nativeEvery","every","nativeSome","some","nativeIndexOf","indexOf","nativeLastIndexOf","lastIndexOf","nativeIsArray","isArray","nativeKeys","keys","nativeBind","bind","obj","_wrapped","exports","module","VERSION","each","iterator","context","length","i","call","collect","results","value","index","list","reduceError","foldl","inject","memo","initial","arguments","TypeError","foldr","find","detect","result","any","select","reject","all","identity","contains","include","target","invoke","method","args","isFunc","isFunction","apply","pluck","key","where","attrs","first","isEmpty","findWhere","max","Math","Infinity","computed","min","shuffle","rand","shuffled","random","sample","n","guard","lookupIterator","sortBy","criteria","sort","left","right","a","b","group","behavior","groupBy","has","indexBy","countBy","sortedIndex","array","low","high","mid","toArray","values","size","head","take","last","rest","tail","drop","compact","flatten","input","shallow","output","isArguments","without","difference","uniq","unique","isSorted","seen","union","intersection","item","other","zip","object","from","hasIndex","range","start","stop","step","ceil","idx","ctor","func","bound","self","partial","bindAll","funcs","Error","f","memoize","hasher","delay","wait","setTimeout","defer","throttle","options","timeout","previous","later","leading","Date","now","remaining","clearTimeout","trailing","debounce","immediate","timestamp","callNow","once","ran","wrap","wrapper","compose","after","times","pairs","invert","functions","methods","names","extend","source","prop","pick","copy","omit","defaults","clone","isObject","tap","interceptor","eq","aStack","bStack","className","String","global","multiline","ignoreCase","aCtor","constructor","bCtor","pop","isEqual","isString","isElement","nodeType","name","isFinite","isNaN","parseFloat","isNumber","isBoolean","isNull","isUndefined","noConflict","accum","floor","entityMap","escape","&","<",">","\"","'","unescape","entityRegexes","RegExp","join","string","replace","match","property","mixin","idCounter","uniqueId","prefix","id","templateSettings","evaluate","interpolate","noMatch","escapes","\\","\r","\n","\t","
","
","escaper","template","text","data","settings","render","matcher","offset","variable","e","chain","_chain"],"mappings":"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"} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/visualsearch/cancel_search.png b/src/core/classes/org/glizycms/js/visualsearch/cancel_search.png new file mode 100755 index 0000000000000000000000000000000000000000..967bf530d46df36cf98722f2c6f15cb16f11b3fb GIT binary patch literal 541 zcmV+&0^<FNP)<h;3K|Lk000e1NJLTq000XB000&U1^@s67UX7Q0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzzez+vRCwByQoU*dK@i?OB!vokk|<hu zXao_he1S9((j-{;7J*2>#=<8^5kjgIzJa2cDg**~0KrC$MKpJXhZ6h=YP;F*xDg{U zn1Q`vX1|&5o7v++2+pL<X0zk*c$}Y1CYi-z5p=uVrmCv1fk5EK>-D|^!vQu;^L#KE z+%A{PL$+lum+LbUiChPR!ACATYVCIWMFOMj7n99UpeK{bQ)M(76(sEuE;5-6i^t;@ z2p%!#oUK+X6%rlLC=&tz!!TGl9Javlh{=F+U>HjDdc7Y&ieXY_K*7|M05t*O5ks>* z=t#kO2)x;m3ZNP0^ZB0nbUKZ7I-RFo+kiQpPCb=MohVp%G#b5>G<})>+CIq3`zw#f zWAMLT5Y&FZ|BhbJK~(*IpVjMiR;g52x7%fjM1p0r*@Ijz$I|Ka`h|F{R=dzN4b}7Q zgFNmn1+7*~vw>pQ357x*&1N&ERIAm3uIoqiAC${wixHl7JRA;HDKQUiZ#Jcn00G<d zcK5lBTk8|s1shUuKmA|lVzKx@;7tG(5V%w--7`$N&o;0%YtM~F<7}@z<AVbRP|*zV fh><7Ew*UhGN$F+f!hm3800000NkvXXu0mjfenafN literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/visualsearch/dependencies.js b/src/core/classes/org/glizycms/js/visualsearch/dependencies.js new file mode 100755 index 0000000..590a200 --- /dev/null +++ b/src/core/classes/org/glizycms/js/visualsearch/dependencies.js @@ -0,0 +1,312 @@ +(function(c,j){function i(a){var b=a.length,h=d.type(a);return d.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===h||"function"!==h&&(0===b||"number"===typeof b&&0<b&&b-1 in a)}function r(a){var b=Ra[a]={};d.each(a.match(aa)||[],function(a,d){b[d]=!0});return b}function q(a,b,h,o){if(d.acceptData(a)){var p=d.expando,f="string"===typeof b,e=a.nodeType,l=e?d.cache:a,c=e?a[p]:a[p]&&p;if(c&&l[c]&&(o||l[c].data)||!(f&&h===j)){c||(e?a[p]=c=ha.pop()||d.guid++:c=p);l[c]||(l[c]={},e||(l[c].toJSON=d.noop));if("object"=== +typeof b||"function"===typeof b)o?l[c]=d.extend(l[c],b):l[c].data=d.extend(l[c].data,b);a=l[c];o||(a.data||(a.data={}),a=a.data);h!==j&&(a[d.camelCase(b)]=h);f?(h=a[b],null==h&&(h=a[d.camelCase(b)])):h=a;return h}}}function u(a,b,h){if(d.acceptData(a)){var o,p,f,e=a.nodeType,l=e?d.cache:a,c=e?a[d.expando]:d.expando;if(l[c]){if(b&&(o=h?l[c]:l[c].data)){d.isArray(b)?b=b.concat(d.map(b,d.camelCase)):b in o?b=[b]:(b=d.camelCase(b),b=b in o?[b]:b.split(" "));for(p=0,f=b.length;p<f;p++)delete o[b[p]];if(!(h? +n:d.isEmptyObject)(o))return}if(!h&&(delete l[c].data,!n(l[c])))return;e?d.cleanData([a],!0):d.support.deleteExpando||l!=l.window?delete l[c]:l[c]=null}}}function g(a,b,h){if(h===j&&1===a.nodeType)if(h="data-"+b.replace(qb,"-$1").toLowerCase(),h=a.getAttribute(h),"string"===typeof h){try{h="true"===h?!0:"false"===h?!1:"null"===h?null:+h+""===h?+h:rb.test(h)?d.parseJSON(h):h}catch(o){}d.data(a,b,h)}else h=j;return h}function n(a){for(var b in a)if(!("data"===b&&d.isEmptyObject(a[b]))&&"toJSON"!==b)return!1; +return!0}function z(){return!0}function J(){return!1}function y(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}function E(a,b,h){b=b||0;if(d.isFunction(b))return d.grep(a,function(a,d){return!!b.call(a,d,a)===h});if(b.nodeType)return d.grep(a,function(a){return a===b===h});if("string"===typeof b){var o=d.grep(a,function(a){return 1===a.nodeType});if(sb.test(b))return d.filter(b,o,!h);b=d.filter(b,o)}return d.grep(a,function(a){return 0<=d.inArray(a,b)===h})}function K(a){var b=Ta.split("|"),a=a.createDocumentFragment(); +if(a.createElement)for(;b.length;)a.createElement(b.pop());return a}function F(a){var b=a.getAttributeNode("type");a.type=(b&&b.specified)+"/"+a.type;return a}function T(a){var b=tb.exec(a.type);b?a.type=b[1]:a.removeAttribute("type");return a}function Z(a,b){for(var h,o=0;null!=(h=a[o]);o++)d._data(h,"globalEval",!b||d._data(b[o],"globalEval"))}function I(a,b){if(1===b.nodeType&&d.hasData(a)){var h,o,p;o=d._data(a);var f=d._data(b,o),e=o.events;if(e)for(h in delete f.handle,f.events={},e)for(o=0, +p=e[h].length;o<p;o++)d.event.add(b,h,e[h][o]);f.data&&(f.data=d.extend({},f.data))}}function x(a,b){var h,o,p=0,f="undefined"!==typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!==typeof a.querySelectorAll?a.querySelectorAll(b||"*"):j;if(!f)for(f=[],h=a.childNodes||a;null!=(o=h[p]);p++)!b||d.nodeName(o,b)?f.push(o):d.merge(f,x(o,b));return b===j||b&&d.nodeName(a,b)?d.merge([a],f):f}function G(a){Ca.test(a.type)&&(a.defaultChecked=a.checked)}function O(a,b){if(b in a)return b; +for(var d=b.charAt(0).toUpperCase()+b.slice(1),o=b,p=Ua.length;p--;)if(b=Ua[p]+d,b in a)return b;return o}function H(a,b){a=b||a;return"none"===d.css(a,"display")||!d.contains(a.ownerDocument,a)}function m(a,b){for(var h,o=[],p=0,f=a.length;p<f;p++)h=a[p],h.style&&(o[p]=d._data(h,"olddisplay"),b?(!o[p]&&"none"===h.style.display&&(h.style.display=""),""===h.style.display&&H(h)&&(o[p]=d._data(h,"olddisplay",P(h.nodeName)))):!o[p]&&!H(h)&&d._data(h,"olddisplay",d.css(h,"display")));for(p=0;p<f;p++)if(h= +a[p],h.style&&(!b||"none"===h.style.display||""===h.style.display))h.style.display=b?o[p]||"":"none";return a}function w(a,b,d){return(a=ub.exec(b))?Math.max(0,a[1]-(d||0))+(a[2]||"px"):b}function V(a,b,h,o,p){for(var b=h===(o?"border":"content")?4:"width"===b?1:0,f=0;4>b;b+=2)"margin"===h&&(f+=d.css(a,h+ia[b],!0,p)),o?("content"===h&&(f-=d.css(a,"padding"+ia[b],!0,p)),"margin"!==h&&(f-=d.css(a,"border"+ia[b]+"Width",!0,p))):(f+=d.css(a,"padding"+ia[b],!0,p),"padding"!==h&&(f+=d.css(a,"border"+ia[b]+ +"Width",!0,p)));return f}function W(a,b,h){var o=!0,p="width"===b?a.offsetWidth:a.offsetHeight,f=X(a),e=d.support.boxSizing&&"border-box"===d.css(a,"boxSizing",!1,f);if(0>=p||null==p){p=Y(a,b,f);if(0>p||null==p)p=a.style[b];if(ta.test(p))return p;o=e&&(d.support.boxSizingReliable||p===a.style[b]);p=parseFloat(p)||0}return p+V(a,b,h||(e?"border":"content"),o,f)+"px"}function P(a){var b=v,h=Va[a];if(!h){h=$(a,b);if("none"===h||!h)ra=(ra||d("<iframe frameborder='0' width='0' height='0'/>").css("cssText", +"display:block !important")).appendTo(b.documentElement),b=(ra[0].contentWindow||ra[0].contentDocument).document,b.write("<!doctype html><html><body>"),b.close(),h=$(a,b),ra.detach();Va[a]=h}return h}function $(a,b){var h=d(b.createElement(a)).appendTo(b.body),o=d.css(h[0],"display");h.remove();return o}function M(a,b,h,o){var p;if(d.isArray(b))d.each(b,function(b,d){h||vb.test(a)?o(a,d):M(a+"["+("object"===typeof d?b:"")+"]",d,h,o)});else if(!h&&"object"===d.type(b))for(p in b)M(a+"["+p+"]",b[p], +h,o);else o(a,b)}function e(a){return function(b,h){"string"!==typeof b&&(h=b,b="*");var o,p=0,f=b.toLowerCase().match(aa)||[];if(d.isFunction(h))for(;o=f[p++];)"+"===o[0]?(o=o.slice(1)||"*",(a[o]=a[o]||[]).unshift(h)):(a[o]=a[o]||[]).push(h)}}function k(a,b,h,o){function p(l){var c;f[l]=!0;d.each(a[l]||[],function(a,d){var l=d(b,h,o);if("string"===typeof l&&!e&&!f[l])return b.dataTypes.unshift(l),p(l),!1;if(e)return!(c=l)});return c}var f={},e=a===Da;return p(b.dataTypes[0])||!f["*"]&&p("*")}function t(a, +b){var h,o,p=d.ajaxSettings.flatOptions||{};for(h in b)b[h]!==j&&((p[h]?a:o||(o={}))[h]=b[h]);o&&d.extend(!0,a,o);return a}function R(){try{return new c.XMLHttpRequest}catch(a){}}function C(){setTimeout(function(){ka=j});return ka=d.now()}function ea(a,b){d.each(b,function(b,d){for(var p=(fa[b]||[]).concat(fa["*"]),f=0,e=p.length;f<e&&!p[f].call(a,b,d);f++);})}function Q(a,b,h){var o,p=0,e=ua.length,l=d.Deferred().always(function(){delete c.elem}),c=function(){if(o)return!1;for(var b=ka||C(),b=Math.max(0, +k.startTime+k.duration-b),d=1-(b/k.duration||0),h=0,p=k.tweens.length;h<p;h++)k.tweens[h].run(d);l.notifyWith(a,[k,d,b]);if(1>d&&p)return b;l.resolveWith(a,[k]);return!1},k=l.promise({elem:a,props:d.extend({},b),opts:d.extend(!0,{specialEasing:{}},h),originalProperties:b,originalOptions:h,startTime:ka||C(),duration:h.duration,tweens:[],createTween:function(b,h){var o=d.Tween(a,k.opts,b,h,k.opts.specialEasing[b]||k.opts.easing);k.tweens.push(o);return o},stop:function(b){var d=0,h=b?k.tweens.length: +0;if(o)return this;for(o=!0;d<h;d++)k.tweens[d].run(1);b?l.resolveWith(a,[k,b]):l.rejectWith(a,[k,b]);return this}}),h=k.props;for(f(h,k.opts.specialEasing);p<e;p++)if(b=ua[p].call(k,a,h,k.opts))return b;ea(k,h);d.isFunction(k.opts.start)&&k.opts.start.call(a,k);d.fx.timer(d.extend(c,{elem:a,anim:k,queue:k.opts.queue}));return k.progress(k.opts.progress).done(k.opts.done,k.opts.complete).fail(k.opts.fail).always(k.opts.always)}function f(a,b){var h,o,p,f,e;for(h in a)if(o=d.camelCase(h),p=b[o],f= +a[h],d.isArray(f)&&(p=f[1],f=a[h]=f[0]),h!==o&&(a[o]=f,delete a[h]),(e=d.cssHooks[o])&&"expand"in e)for(h in f=e.expand(f),delete a[o],f)h in a||(a[h]=f[h],b[h]=p);else b[o]=p}function l(a,b,d,o,p){return new l.prototype.init(a,b,d,o,p)}function s(a,b){for(var d,o={height:a},p=0,b=b?1:0;4>p;p+=2-b)d=ia[p],o["margin"+d]=o["padding"+d]=a;b&&(o.opacity=o.width=a);return o}function B(a){return d.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}var S,A,v=c.document,ba=c.location,la=c.jQuery, +Aa=c.$,ma={},ha=[],va=ha.concat,ya=ha.push,ga=ha.slice,Wa=ha.indexOf,wb=ma.toString,Ea=ma.hasOwnProperty,Fa="1.9.0".trim,d=function(a,b){return new d.fn.init(a,b,S)},wa=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,aa=/\S+/g,xb=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,yb=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,Xa=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,zb=/^[\],:{}\s]*$/,Ab=/(?:^|:|,)(?:\s*\[)+/g,Bb=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,Cb=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,Db=/^-ms-/,Eb= +/-([\da-z])/gi,Fb=function(a,b){return b.toUpperCase()},xa=function(){v.addEventListener?(v.removeEventListener("DOMContentLoaded",xa,!1),d.ready()):"complete"===v.readyState&&(v.detachEvent("onreadystatechange",xa),d.ready())};d.fn=d.prototype={jquery:"1.9.0",constructor:d,init:function(a,b,h){var o;if(!a)return this;if("string"===typeof a){if((o="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&3<=a.length?[null,a,null]:yb.exec(a))&&(o[1]||!b)){if(o[1]){if(b=b instanceof d?b[0]:b,d.merge(this,d.parseHTML(o[1], +b&&b.nodeType?b.ownerDocument||b:v,!0)),Xa.test(o[1])&&d.isPlainObject(b))for(o in b)if(d.isFunction(this[o]))this[o](b[o]);else this.attr(o,b[o])}else{if((b=v.getElementById(o[2]))&&b.parentNode){if(b.id!==o[2])return h.find(a);this.length=1;this[0]=b}this.context=v;this.selector=a}return this}return!b||b.jquery?(b||h).find(a):this.constructor(b).find(a)}if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(d.isFunction(a))return h.ready(a);a.selector!==j&&(this.selector=a.selector,this.context= +a.context);return d.makeArray(a,this)},selector:"",length:0,size:function(){return this.length},toArray:function(){return ga.call(this)},get:function(a){return null==a?this.toArray():0>a?this[this.length+a]:this[a]},pushStack:function(a){a=d.merge(this.constructor(),a);a.prevObject=this;a.context=this.context;return a},each:function(a,b){return d.each(this,a,b)},ready:function(a){d.ready.promise().done(a);return this},slice:function(){return this.pushStack(ga.apply(this,arguments))},first:function(){return this.eq(0)}, +last:function(){return this.eq(-1)},eq:function(a){var b=this.length,a=+a+(0>a?b:0);return this.pushStack(0<=a&&a<b?[this[a]]:[])},map:function(a){return this.pushStack(d.map(this,function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:ya,sort:[].sort,splice:[].splice};d.fn.init.prototype=d.fn;d.extend=d.fn.extend=function(){var a,b,h,o,p,f=arguments[0]||{},e=1,l=arguments.length,k=!1;"boolean"===typeof f&&(k=f,f=arguments[1]||{},e=2);"object"!== +typeof f&&!d.isFunction(f)&&(f={});l===e&&(f=this,--e);for(;e<l;e++)if(null!=(a=arguments[e]))for(b in a)h=f[b],o=a[b],f!==o&&(k&&o&&(d.isPlainObject(o)||(p=d.isArray(o)))?(p?(p=!1,h=h&&d.isArray(h)?h:[]):h=h&&d.isPlainObject(h)?h:{},f[b]=d.extend(k,h,o)):o!==j&&(f[b]=o));return f};d.extend({noConflict:function(a){c.$===d&&(c.$=Aa);a&&c.jQuery===d&&(c.jQuery=la);return d},isReady:!1,readyWait:1,holdReady:function(a){a?d.readyWait++:d.ready(!0)},ready:function(a){if(!(!0===a?--d.readyWait:d.isReady)){if(!v.body)return setTimeout(d.ready); +d.isReady=!0;!0!==a&&0<--d.readyWait||(A.resolveWith(v,[d]),d.fn.trigger&&d(v).trigger("ready").off("ready"))}},isFunction:function(a){return"function"===d.type(a)},isArray:Array.isArray||function(a){return"array"===d.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return null==a?""+a:"object"===typeof a||"function"===typeof a?ma[wb.call(a)]||"object":typeof a},isPlainObject:function(a){if(!a||"object"!==d.type(a)|| +a.nodeType||d.isWindow(a))return!1;try{if(a.constructor&&!Ea.call(a,"constructor")&&!Ea.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(b){return!1}for(var h in a);return h===j||Ea.call(a,h)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw Error(a);},parseHTML:function(a,b,h){if(!a||"string"!==typeof a)return null;"boolean"===typeof b&&(h=b,b=!1);var b=b||v,o=Xa.exec(a),h=!h&&[];if(o)return[b.createElement(o[1])];o=d.buildFragment([a],b,h);h&&d(h).remove(); +return d.merge([],o.childNodes)},parseJSON:function(a){if(c.JSON&&c.JSON.parse)return c.JSON.parse(a);if(null===a)return a;if("string"===typeof a&&(a=d.trim(a))&&zb.test(a.replace(Bb,"@").replace(Cb,"]").replace(Ab,"")))return(new Function("return "+a))();d.error("Invalid JSON: "+a)},parseXML:function(a){var b,h;if(!a||"string"!==typeof a)return null;try{c.DOMParser?(h=new DOMParser,b=h.parseFromString(a,"text/xml")):(b=new ActiveXObject("Microsoft.XMLDOM"),b.async="false",b.loadXML(a))}catch(o){b= +j}(!b||!b.documentElement||b.getElementsByTagName("parsererror").length)&&d.error("Invalid XML: "+a);return b},noop:function(){},globalEval:function(a){a&&d.trim(a)&&(c.execScript||function(a){c.eval.call(c,a)})(a)},camelCase:function(a){return a.replace(Db,"ms-").replace(Eb,Fb)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,d){var o,p=0,f=a.length;o=i(a);if(d)if(o)for(;p<f&&!(o=b.apply(a[p],d),!1===o);p++);else for(p in a){if(o=b.apply(a[p], +d),!1===o)break}else if(o)for(;p<f&&!(o=b.call(a[p],p,a[p]),!1===o);p++);else for(p in a)if(o=b.call(a[p],p,a[p]),!1===o)break;return a},trim:Fa&&!Fa.call("\ufeff\u00a0")?function(a){return null==a?"":Fa.call(a)}:function(a){return null==a?"":(a+"").replace(xb,"")},makeArray:function(a,b){var h=b||[];null!=a&&(i(Object(a))?d.merge(h,"string"===typeof a?[a]:a):ya.call(h,a));return h},inArray:function(a,b,d){var o;if(b){if(Wa)return Wa.call(b,a,d);o=b.length;for(d=d?0>d?Math.max(0,o+d):d:0;d<o;d++)if(d in +b&&b[d]===a)return d}return-1},merge:function(a,b){var d=b.length,o=a.length,p=0;if("number"===typeof d)for(;p<d;p++)a[o++]=b[p];else for(;b[p]!==j;)a[o++]=b[p++];a.length=o;return a},grep:function(a,b,d){for(var o,p=[],f=0,e=a.length,d=!!d;f<e;f++)o=!!b(a[f],f),d!==o&&p.push(a[f]);return p},map:function(a,b,d){var o,p=0,f=a.length,e=[];if(i(a))for(;p<f;p++)o=b(a[p],p,d),null!=o&&(e[e.length]=o);else for(p in a)o=b(a[p],p,d),null!=o&&(e[e.length]=o);return va.apply([],e)},guid:1,proxy:function(a, +b){var h,o;"string"===typeof b&&(h=a[b],b=a,a=h);if(!d.isFunction(a))return j;o=ga.call(arguments,2);h=function(){return a.apply(b||this,o.concat(ga.call(arguments)))};h.guid=a.guid=a.guid||d.guid++;return h},access:function(a,b,h,o,p,f,e){var l=0,k=a.length,c=null==h;if("object"===d.type(h))for(l in p=!0,h)d.access(a,b,l,h[l],!0,f,e);else if(o!==j&&(p=!0,d.isFunction(o)||(e=!0),c&&(e?(b.call(a,o),b=null):(c=b,b=function(a,b,h){return c.call(d(a),h)})),b))for(;l<k;l++)b(a[l],h,e?o:o.call(a[l],l,b(a[l], +h)));return p?a:c?b.call(a):k?b(a[0],h):f},now:function(){return(new Date).getTime()}});d.ready.promise=function(a){if(!A)if(A=d.Deferred(),"complete"===v.readyState)setTimeout(d.ready);else if(v.addEventListener)v.addEventListener("DOMContentLoaded",xa,!1),c.addEventListener("load",d.ready,!1);else{v.attachEvent("onreadystatechange",xa);c.attachEvent("onload",d.ready);var b=!1;try{b=null==c.frameElement&&v.documentElement}catch(h){}b&&b.doScroll&&function p(){if(!d.isReady){try{b.doScroll("left")}catch(a){return setTimeout(p, +50)}d.ready()}}()}return A.promise(a)};d.each("Boolean,Number,String,Function,Array,Date,RegExp,Object,Error".split(","),function(a,b){ma["[object "+b+"]"]=b.toLowerCase()});S=d(v);var Ra={};d.Callbacks=function(a){var a="string"===typeof a?Ra[a]||r(a):d.extend({},a),b,h,o,p,f,e,l=[],k=!a.once&&[],c=function(d){b=a.memory&&d;h=!0;e=p||0;p=0;f=l.length;for(o=!0;l&&e<f;e++)if(!1===l[e].apply(d[0],d[1])&&a.stopOnFalse){b=!1;break}o=!1;l&&(k?k.length&&c(k.shift()):b?l=[]:m.disable())},m={add:function(){if(l){var h= +l.length;(function Gb(b){d.each(b,function(b,h){var o=d.type(h);"function"===o?(!a.unique||!m.has(h))&&l.push(h):h&&h.length&&"string"!==o&&Gb(h)})})(arguments);o?f=l.length:b&&(p=h,c(b))}return this},remove:function(){l&&d.each(arguments,function(a,b){for(var h;-1<(h=d.inArray(b,l,h));)l.splice(h,1),o&&(h<=f&&f--,h<=e&&e--)});return this},has:function(a){return-1<d.inArray(a,l)},empty:function(){l=[];return this},disable:function(){l=k=b=j;return this},disabled:function(){return!l},lock:function(){k= +j;b||m.disable();return this},locked:function(){return!k},fireWith:function(a,b){b=b||[];b=[a,b.slice?b.slice():b];if(l&&(!h||k))o?k.push(b):c(b);return this},fire:function(){m.fireWith(this,arguments);return this},fired:function(){return!!h}};return m};d.extend({Deferred:function(a){var b=[["resolve","done",d.Callbacks("once memory"),"resolved"],["reject","fail",d.Callbacks("once memory"),"rejected"],["notify","progress",d.Callbacks("memory")]],h="pending",o={state:function(){return h},always:function(){p.done(arguments).fail(arguments); +return this},then:function(){var a=arguments;return d.Deferred(function(h){d.each(b,function(b,f){var e=f[0],l=d.isFunction(a[b])&&a[b];p[f[1]](function(){var a=l&&l.apply(this,arguments);if(a&&d.isFunction(a.promise))a.promise().done(h.resolve).fail(h.reject).progress(h.notify);else h[e+"With"](this===o?h.promise():this,l?[a]:arguments)})});a=null}).promise()},promise:function(a){return null!=a?d.extend(a,o):o}},p={};o.pipe=o.then;d.each(b,function(a,d){var f=d[2],e=d[3];o[d[1]]=f.add;e&&f.add(function(){h= +e},b[a^1][2].disable,b[2][2].lock);p[d[0]]=function(){p[d[0]+"With"](this===p?o:this,arguments);return this};p[d[0]+"With"]=f.fireWith});o.promise(p);a&&a.call(p,p);return p},when:function(a){var b=0,h=ga.call(arguments),o=h.length,f=1!==o||a&&d.isFunction(a.promise)?o:0,e=1===f?a:d.Deferred(),l=function(a,b,d){return function(h){b[a]=this;d[a]=1<arguments.length?ga.call(arguments):h;d===k?e.notifyWith(b,d):--f||e.resolveWith(b,d)}},k,c,m;if(1<o){k=Array(o);c=Array(o);for(m=Array(o);b<o;b++)h[b]&& +d.isFunction(h[b].promise)?h[b].promise().done(l(b,m,h)).fail(e.reject).progress(l(b,c,k)):--f}f||e.resolveWith(m,h);return e.promise()}});d.support=function(){var a,b,h,o,f,e,l,k=v.createElement("div");k.setAttribute("className","t");k.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";b=k.getElementsByTagName("*");h=k.getElementsByTagName("a")[0];if(!b||!h||!b.length)return{};o=v.createElement("select");f=o.appendChild(v.createElement("option"));b=k.getElementsByTagName("input")[0]; +h.style.cssText="top:1px;float:left;opacity:.5";a={getSetAttribute:"t"!==k.className,leadingWhitespace:3===k.firstChild.nodeType,tbody:!k.getElementsByTagName("tbody").length,htmlSerialize:!!k.getElementsByTagName("link").length,style:/top/.test(h.getAttribute("style")),hrefNormalized:"/a"===h.getAttribute("href"),opacity:/^0.5/.test(h.style.opacity),cssFloat:!!h.style.cssFloat,checkOn:!!b.value,optSelected:f.selected,enctype:!!v.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==v.createElement("nav").cloneNode(!0).outerHTML, +boxModel:"CSS1Compat"===v.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1};b.checked=!0;a.noCloneChecked=b.cloneNode(!0).checked;o.disabled=!0;a.optDisabled=!f.disabled;try{delete k.test}catch(m){a.deleteExpando=!1}b=v.createElement("input");b.setAttribute("value","");a.input=""===b.getAttribute("value");b.value="t";b.setAttribute("type","radio");a.radioValue="t"===b.value;b.setAttribute("checked", +"t");b.setAttribute("name","t");h=v.createDocumentFragment();h.appendChild(b);a.appendChecked=b.checked;a.checkClone=h.cloneNode(!0).cloneNode(!0).lastChild.checked;k.attachEvent&&(k.attachEvent("onclick",function(){a.noCloneEvent=!1}),k.cloneNode(!0).click());for(l in{submit:!0,change:!0,focusin:!0})k.setAttribute(h="on"+l,"t"),a[l+"Bubbles"]=h in c||!1===k.attributes[h].expando;k.style.backgroundClip="content-box";k.cloneNode(!0).style.backgroundClip="";a.clearCloneStyle="content-box"===k.style.backgroundClip; +d(function(){var b,d,h=v.getElementsByTagName("body")[0];h&&(b=v.createElement("div"),b.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",h.appendChild(b).appendChild(k),k.innerHTML="<table><tr><td></td><td>t</td></tr></table>",d=k.getElementsByTagName("td"),d[0].style.cssText="padding:0;margin:0;border:0;display:none",e=0===d[0].offsetHeight,d[0].style.display="",d[1].style.display="none",a.reliableHiddenOffsets=e&&0===d[0].offsetHeight,k.innerHTML="", +k.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",a.boxSizing=4===k.offsetWidth,a.doesNotIncludeMarginInBodyOffset=1!==h.offsetTop,c.getComputedStyle&&(a.pixelPosition="1%"!==(c.getComputedStyle(k,null)||{}).top,a.boxSizingReliable="4px"===(c.getComputedStyle(k,null)||{width:"4px"}).width,d=k.appendChild(v.createElement("div")),d.style.cssText=k.style.cssText="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", +d.style.marginRight=d.style.width="0",k.style.width="1px",a.reliableMarginRight=!parseFloat((c.getComputedStyle(d,null)||{}).marginRight)),"undefined"!==typeof k.style.zoom&&(k.innerHTML="",k.style.cssText="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;width:1px;padding:1px;display:inline;zoom:1",a.inlineBlockNeedsLayout=3===k.offsetWidth,k.style.display="block",k.innerHTML="<div></div>",k.firstChild.style.width="5px",a.shrinkWrapBlocks= +3!==k.offsetWidth,h.style.zoom=1),h.removeChild(b),k=null)});b=o=h=f=h=b=null;return a}();var rb=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,qb=/([A-Z])/g;d.extend({cache:{},expando:"jQuery"+("1.9.0"+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?d.cache[a[d.expando]]:a[d.expando];return!!a&&!n(a)},data:function(a,b,d){return q(a,b,d,!1)},removeData:function(a,b){return u(a,b,!1)},_data:function(a,b,d){return q(a, +b,d,!0)},_removeData:function(a,b){return u(a,b,!0)},acceptData:function(a){var b=a.nodeName&&d.noData[a.nodeName.toLowerCase()];return!b||!0!==b&&a.getAttribute("classid")===b}});d.fn.extend({data:function(a,b){var h,o,f=this[0],e=0,l=null;if(a===j){if(this.length&&(l=d.data(f),1===f.nodeType&&!d._data(f,"parsedAttrs"))){for(h=f.attributes;e<h.length;e++)o=h[e].name,o.indexOf("data-")||(o=d.camelCase(o.substring(5)),g(f,o,l[o]));d._data(f,"parsedAttrs",!0)}return l}return"object"===typeof a?this.each(function(){d.data(this, +a)}):d.access(this,function(b){if(b===j)return f?g(f,a,d.data(f,a)):null;this.each(function(){d.data(this,a,b)})},null,b,1<arguments.length,null,!0)},removeData:function(a){return this.each(function(){d.removeData(this,a)})}});d.extend({queue:function(a,b,h){var o;if(a)return b=(b||"fx")+"queue",o=d._data(a,b),h&&(!o||d.isArray(h)?o=d._data(a,b,d.makeArray(h)):o.push(h)),o||[]},dequeue:function(a,b){var b=b||"fx",h=d.queue(a,b),o=h.length,f=h.shift(),e=d._queueHooks(a,b),l=function(){d.dequeue(a, +b)};"inprogress"===f&&(f=h.shift(),o--);if(e.cur=f)"fx"===b&&h.unshift("inprogress"),delete e.stop,f.call(a,l,e);!o&&e&&e.empty.fire()},_queueHooks:function(a,b){var h=b+"queueHooks";return d._data(a,h)||d._data(a,h,{empty:d.Callbacks("once memory").add(function(){d._removeData(a,b+"queue");d._removeData(a,h)})})}});d.fn.extend({queue:function(a,b){var h=2;"string"!==typeof a&&(b=a,a="fx",h--);return arguments.length<h?d.queue(this[0],a):b===j?this:this.each(function(){var h=d.queue(this,a,b);d._queueHooks(this, +a);"fx"===a&&"inprogress"!==h[0]&&d.dequeue(this,a)})},dequeue:function(a){return this.each(function(){d.dequeue(this,a)})},delay:function(a,b){a=d.fx?d.fx.speeds[a]||a:a;return this.queue(b||"fx",function(b,d){var f=setTimeout(b,a);d.stop=function(){clearTimeout(f)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var h,o=1,f=d.Deferred(),e=this,l=this.length,k=function(){--o||f.resolveWith(e,[e])};"string"!==typeof a&&(b=a,a=j);for(a=a||"fx";l--;)if((h=d._data(e[l], +a+"queueHooks"))&&h.empty)o++,h.empty.add(k);k();return f.promise(b)}});var na,Ya,Ga=/[\t\r\n]/g,Hb=/\r/g,Ib=/^(?:input|select|textarea|button|object)$/i,Jb=/^(?:a|area)$/i,Za=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,Ha=/^(?:checked|selected)$/i,da=d.support.getSetAttribute,Ia=d.support.input;d.fn.extend({attr:function(a,b){return d.access(this,d.attr,a,b,1<arguments.length)},removeAttr:function(a){return this.each(function(){d.removeAttr(this, +a)})},prop:function(a,b){return d.access(this,d.prop,a,b,1<arguments.length)},removeProp:function(a){a=d.propFix[a]||a;return this.each(function(){try{this[a]=j,delete this[a]}catch(b){}})},addClass:function(a){var b,h,o,f,e,l=0,k=this.length;b="string"===typeof a&&a;if(d.isFunction(a))return this.each(function(b){d(this).addClass(a.call(this,b,this.className))});if(b)for(b=(a||"").match(aa)||[];l<k;l++)if(h=this[l],o=1===h.nodeType&&(h.className?(" "+h.className+" ").replace(Ga," "):" ")){for(e= +0;f=b[e++];)0>o.indexOf(" "+f+" ")&&(o+=f+" ");h.className=d.trim(o)}return this},removeClass:function(a){var b,h,o,f,e,l=0,k=this.length;b=0===arguments.length||"string"===typeof a&&a;if(d.isFunction(a))return this.each(function(b){d(this).removeClass(a.call(this,b,this.className))});if(b)for(b=(a||"").match(aa)||[];l<k;l++)if(h=this[l],o=1===h.nodeType&&(h.className?(" "+h.className+" ").replace(Ga," "):"")){for(e=0;f=b[e++];)for(;0<=o.indexOf(" "+f+" ");)o=o.replace(" "+f+" "," ");h.className= +a?d.trim(o):""}return this},toggleClass:function(a,b){var h=typeof a,o="boolean"===typeof b;return d.isFunction(a)?this.each(function(h){d(this).toggleClass(a.call(this,h,this.className,b),b)}):this.each(function(){if("string"===h)for(var f,e=0,l=d(this),k=b,c=a.match(aa)||[];f=c[e++];)k=o?k:!l.hasClass(f),l[k?"addClass":"removeClass"](f);else if("undefined"===h||"boolean"===h)this.className&&d._data(this,"__className__",this.className),this.className=this.className||!1===a?"":d._data(this,"__className__")|| +""})},hasClass:function(a){for(var a=" "+a+" ",b=0,d=this.length;b<d;b++)if(1===this[b].nodeType&&0<=(" "+this[b].className+" ").replace(Ga," ").indexOf(a))return!0;return!1},val:function(a){var b,h,o,f=this[0];if(arguments.length)return o=d.isFunction(a),this.each(function(h){var f=d(this);if(1===this.nodeType&&(h=o?a.call(this,h,f.val()):a,null==h?h="":"number"===typeof h?h+="":d.isArray(h)&&(h=d.map(h,function(a){return null==a?"":a+""})),b=d.valHooks[this.type]||d.valHooks[this.nodeName.toLowerCase()], +!b||!("set"in b)||b.set(this,h,"value")===j))this.value=h});if(f){if((b=d.valHooks[f.type]||d.valHooks[f.nodeName.toLowerCase()])&&"get"in b&&(h=b.get(f,"value"))!==j)return h;h=f.value;return"string"===typeof h?h.replace(Hb,""):null==h?"":h}}});d.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){for(var b,h=a.options,o=a.selectedIndex,f=(a="select-one"===a.type||0>o)?null:[],e=a?o+1:h.length,l=0>o?e:a?o:0;l<e;l++)if(b= +h[l],(b.selected||l===o)&&(d.support.optDisabled?!b.disabled:null===b.getAttribute("disabled"))&&(!b.parentNode.disabled||!d.nodeName(b.parentNode,"optgroup"))){b=d(b).val();if(a)return b;f.push(b)}return f},set:function(a,b){var h=d.makeArray(b);d(a).find("option").each(function(){this.selected=0<=d.inArray(d(this).val(),h)});h.length||(a.selectedIndex=-1);return h}}},attr:function(a,b,h){var o,f,e;e=a.nodeType;if(a&&!(3===e||8===e||2===e)){if("undefined"===typeof a.getAttribute)return d.prop(a, +b,h);if(e=1!==e||!d.isXMLDoc(a))b=b.toLowerCase(),f=d.attrHooks[b]||(Za.test(b)?Ya:na);if(h!==j)if(null===h)d.removeAttr(a,b);else{if(f&&e&&"set"in f&&(o=f.set(a,h,b))!==j)return o;a.setAttribute(b,h+"");return h}else{if(f&&e&&"get"in f&&null!==(o=f.get(a,b)))return o;"undefined"!==typeof a.getAttribute&&(o=a.getAttribute(b));return null==o?j:o}}},removeAttr:function(a,b){var h,o,f=0,e=b&&b.match(aa);if(e&&1===a.nodeType)for(;h=e[f++];)o=d.propFix[h]||h,Za.test(h)?!da&&Ha.test(h)?a[d.camelCase("default-"+ +h)]=a[o]=!1:a[o]=!1:d.attr(a,h,""),a.removeAttribute(da?h:o)},attrHooks:{type:{set:function(a,b){if(!d.support.radioValue&&"radio"===b&&d.nodeName(a,"input")){var h=a.value;a.setAttribute("type",b);h&&(a.value=h);return b}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a, +b,h){var o,f,e=a.nodeType;if(a&&!(3===e||8===e||2===e)){if(1!==e||!d.isXMLDoc(a))b=d.propFix[b]||b,f=d.propHooks[b];return h!==j?f&&"set"in f&&(o=f.set(a,h,b))!==j?o:a[b]=h:f&&"get"in f&&null!==(o=f.get(a,b))?o:a[b]}},propHooks:{tabIndex:{get:function(a){var b=a.getAttributeNode("tabindex");return b&&b.specified?parseInt(b.value,10):Ib.test(a.nodeName)||Jb.test(a.nodeName)&&a.href?0:j}}}});Ya={get:function(a,b){var h=d.prop(a,b),f="boolean"===typeof h&&a.getAttribute(b);return(h="boolean"===typeof h? +Ia&&da?null!=f:Ha.test(b)?a[d.camelCase("default-"+b)]:!!f:a.getAttributeNode(b))&&!1!==h.value?b.toLowerCase():j},set:function(a,b,h){!1===b?d.removeAttr(a,h):Ia&&da||!Ha.test(h)?a.setAttribute(!da&&d.propFix[h]||h,h):a[d.camelCase("default-"+h)]=a[h]=!0;return h}};if(!Ia||!da)d.attrHooks.value={get:function(a,b){var h=a.getAttributeNode(b);return d.nodeName(a,"input")?a.defaultValue:h&&h.specified?h.value:j},set:function(a,b,h){if(d.nodeName(a,"input"))a.defaultValue=b;else return na&&na.set(a, +b,h)}};da||(na=d.valHooks.button={get:function(a,b){var d=a.getAttributeNode(b);return d&&("id"===b||"name"===b||"coords"===b?""!==d.value:d.specified)?d.value:j},set:function(a,b,d){var f=a.getAttributeNode(d);f||a.setAttributeNode(f=a.ownerDocument.createAttribute(d));f.value=b+="";return"value"===d||b===a.getAttribute(d)?b:j}},d.attrHooks.contenteditable={get:na.get,set:function(a,b,d){na.set(a,""===b?!1:b,d)}},d.each(["width","height"],function(a,b){d.attrHooks[b]=d.extend(d.attrHooks[b],{set:function(a, +d){if(""===d)return a.setAttribute(b,"auto"),d}})}));d.support.hrefNormalized||(d.each(["href","src","width","height"],function(a,b){d.attrHooks[b]=d.extend(d.attrHooks[b],{get:function(a){a=a.getAttribute(b,2);return null==a?j:a}})}),d.each(["href","src"],function(a,b){d.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}));d.support.style||(d.attrHooks.style={get:function(a){return a.style.cssText||j},set:function(a,b){return a.style.cssText=b+""}});d.support.optSelected||(d.propHooks.selected= +d.extend(d.propHooks.selected,{get:function(a){if(a=a.parentNode)a.selectedIndex,a.parentNode&&a.parentNode.selectedIndex;return null}}));d.support.enctype||(d.propFix.enctype="encoding");d.support.checkOn||d.each(["radio","checkbox"],function(){d.valHooks[this]={get:function(a){return null===a.getAttribute("value")?"on":a.value}}});d.each(["radio","checkbox"],function(){d.valHooks[this]=d.extend(d.valHooks[this],{set:function(a,b){if(d.isArray(b))return a.checked=0<=d.inArray(d(a).val(),b)}})}); +var Ja=/^(?:input|select|textarea)$/i,Kb=/^key/,Lb=/^(?:mouse|contextmenu)|click/,$a=/^(?:focusinfocus|focusoutblur)$/,ab=/^([^.]*)(?:\.(.+)|)$/;d.event={global:{},add:function(a,b,h,f,e){var l,k,c,m,s,g,n,t,i;if(s=3!==a.nodeType&&8!==a.nodeType&&d._data(a)){h.handler&&(l=h,h=l.handler,e=l.selector);h.guid||(h.guid=d.guid++);if(!(m=s.events))m=s.events={};if(!(k=s.handle))k=s.handle=function(a){return"undefined"!==typeof d&&(!a||d.event.triggered!==a.type)?d.event.dispatch.apply(k.elem,arguments): +j},k.elem=a;b=(b||"").match(aa)||[""];for(s=b.length;s--;){c=ab.exec(b[s])||[];t=g=c[1];i=(c[2]||"").split(".").sort();c=d.event.special[t]||{};t=(e?c.delegateType:c.bindType)||t;c=d.event.special[t]||{};g=d.extend({type:t,origType:g,data:f,handler:h,guid:h.guid,selector:e,needsContext:e&&d.expr.match.needsContext.test(e),namespace:i.join(".")},l);if(!(n=m[t]))if(n=m[t]=[],n.delegateCount=0,!c.setup||!1===c.setup.call(a,f,i,k))a.addEventListener?a.addEventListener(t,k,!1):a.attachEvent&&a.attachEvent("on"+ +t,k);c.add&&(c.add.call(a,g),g.handler.guid||(g.handler.guid=h.guid));e?n.splice(n.delegateCount++,0,g):n.push(g);d.event.global[t]=!0}a=null}},remove:function(a,b,h,f,e){var l,k,c,m,s,g,n,t,j,i,B,u=d.hasData(a)&&d._data(a);if(u&&(m=u.events)){b=(b||"").match(aa)||[""];for(s=b.length;s--;)if(c=ab.exec(b[s])||[],j=B=c[1],i=(c[2]||"").split(".").sort(),j){n=d.event.special[j]||{};j=(f?n.delegateType:n.bindType)||j;t=m[j]||[];c=c[2]&&RegExp("(^|\\.)"+i.join("\\.(?:.*\\.|)")+"(\\.|$)");for(k=l=t.length;l--;)if(g= +t[l],(e||B===g.origType)&&(!h||h.guid===g.guid)&&(!c||c.test(g.namespace))&&(!f||f===g.selector||"**"===f&&g.selector))t.splice(l,1),g.selector&&t.delegateCount--,n.remove&&n.remove.call(a,g);k&&!t.length&&((!n.teardown||!1===n.teardown.call(a,i,u.handle))&&d.removeEvent(a,j,u.handle),delete m[j])}else for(j in m)d.event.remove(a,j+b[s],h,f,!0);d.isEmptyObject(m)&&(delete u.handle,d._removeData(a,"events"))}},trigger:function(a,b,h,f){var e,l,k,m,g,s,n=[h||v],t=a.type||a;s=a.namespace?a.namespace.split("."): +[];l=e=h=h||v;if(!(3===h.nodeType||8===h.nodeType)&&!$a.test(t+d.event.triggered))if(0<=t.indexOf(".")&&(s=t.split("."),t=s.shift(),s.sort()),m=0>t.indexOf(":")&&"on"+t,a=a[d.expando]?a:new d.Event(t,"object"===typeof a&&a),a.isTrigger=!0,a.namespace=s.join("."),a.namespace_re=a.namespace?RegExp("(^|\\.)"+s.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,a.result=j,a.target||(a.target=h),b=null==b?[a]:d.makeArray(b,[a]),s=d.event.special[t]||{},f||!(s.trigger&&!1===s.trigger.apply(h,b))){if(!f&&!s.noBubble&& +!d.isWindow(h)){k=s.delegateType||t;$a.test(k+t)||(l=l.parentNode);for(;l;l=l.parentNode)n.push(l),e=l;if(e===(h.ownerDocument||v))n.push(e.defaultView||e.parentWindow||c)}for(e=0;(l=n[e++])&&!a.isPropagationStopped();)a.type=1<e?k:s.bindType||t,(g=(d._data(l,"events")||{})[a.type]&&d._data(l,"handle"))&&g.apply(l,b),(g=m&&l[m])&&d.acceptData(l)&&g.apply&&!1===g.apply(l,b)&&a.preventDefault();a.type=t;if(!f&&!a.isDefaultPrevented()&&(!s._default||!1===s._default.apply(h.ownerDocument,b))&&!("click"=== +t&&d.nodeName(h,"a"))&&d.acceptData(h)&&m&&h[t]&&!d.isWindow(h)){(e=h[m])&&(h[m]=null);d.event.triggered=t;try{h[t]()}catch(i){}d.event.triggered=j;e&&(h[m]=e)}return a.result}},dispatch:function(a){var a=d.event.fix(a),b,h,f,e,l=[],k=ga.call(arguments);b=(d._data(this,"events")||{})[a.type]||[];var c=d.event.special[a.type]||{};k[0]=a;a.delegateTarget=this;if(!(c.preDispatch&&!1===c.preDispatch.call(this,a))){l=d.event.handlers.call(this,a,b);for(b=0;(e=l[b++])&&!a.isPropagationStopped();){a.currentTarget= +e.elem;for(h=0;(f=e.handlers[h++])&&!a.isImmediatePropagationStopped();)if(!a.namespace_re||a.namespace_re.test(f.namespace))if(a.handleObj=f,a.data=f.data,f=((d.event.special[f.origType]||{}).handle||f.handler).apply(e.elem,k),f!==j&&!1===(a.result=f))a.preventDefault(),a.stopPropagation()}c.postDispatch&&c.postDispatch.call(this,a);return a.result}},handlers:function(a,b){var h,f,e,l,k=[],c=b.delegateCount,m=a.target;if(c&&m.nodeType&&(!a.button||"click"!==a.type))for(;m!=this;m=m.parentNode||this)if(!0!== +m.disabled||"click"!==a.type){f=[];for(h=0;h<c;h++)l=b[h],e=l.selector+" ",f[e]===j&&(f[e]=l.needsContext?0<=d(e,this).index(m):d.find(e,this,null,[m]).length),f[e]&&f.push(l);f.length&&k.push({elem:m,handlers:f})}c<b.length&&k.push({elem:this,handlers:b.slice(c)});return k},fix:function(a){if(a[d.expando])return a;var b,h,f=a,e=d.event.fixHooks[a.type]||{},l=e.props?this.props.concat(e.props):this.props,a=new d.Event(f);for(b=l.length;b--;)h=l[b],a[h]=f[h];a.target||(a.target=f.srcElement||v);3=== +a.target.nodeType&&(a.target=a.target.parentNode);a.metaKey=!!a.metaKey;return e.filter?e.filter(a,f):a},props:"altKey,bubbles,cancelable,ctrlKey,currentTarget,eventPhase,metaKey,relatedTarget,shiftKey,target,timeStamp,view,which".split(","),fixHooks:{},keyHooks:{props:["char","charCode","key","keyCode"],filter:function(a,b){null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button,buttons,clientX,clientY,fromElement,offsetX,offsetY,pageX,pageY,screenX,screenY,toElement".split(","), +filter:function(a,b){var d,f,e=b.button,l=b.fromElement;null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||v,f=d.documentElement,d=d.body,a.pageX=b.clientX+(f&&f.scrollLeft||d&&d.scrollLeft||0)-(f&&f.clientLeft||d&&d.clientLeft||0),a.pageY=b.clientY+(f&&f.scrollTop||d&&d.scrollTop||0)-(f&&f.clientTop||d&&d.clientTop||0));!a.relatedTarget&&l&&(a.relatedTarget=l===a.target?b.toElement:l);!a.which&&e!==j&&(a.which=e&1?1:e&2?3:e&4?2:0);return a}},special:{load:{noBubble:!0},click:{trigger:function(){if(d.nodeName(this, +"input")&&"checkbox"===this.type&&this.click)return this.click(),!1}},focus:{trigger:function(){if(this!==v.activeElement&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){if(this===v.activeElement&&this.blur)return this.blur(),!1},delegateType:"focusout"},beforeunload:{postDispatch:function(a){a.result!==j&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,h,f){a=d.extend(new d.Event,h,{type:a,isSimulated:!0,originalEvent:{}});f?d.event.trigger(a, +null,b):d.event.dispatch.call(b,a);a.isDefaultPrevented()&&h.preventDefault()}};d.removeEvent=v.removeEventListener?function(a,b,d){a.removeEventListener&&a.removeEventListener(b,d,!1)}:function(a,b,d){b="on"+b;a.detachEvent&&("undefined"===typeof a[b]&&(a[b]=null),a.detachEvent(b,d))};d.Event=function(a,b){if(!(this instanceof d.Event))return new d.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||!1===a.returnValue||a.getPreventDefault&&a.getPreventDefault()? +z:J):this.type=a;b&&d.extend(this,b);this.timeStamp=a&&a.timeStamp||d.now();this[d.expando]=!0};d.Event.prototype={isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=z;a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=z;a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped= +z;this.stopPropagation()}};d.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){d.event.special[a]={delegateType:b,bindType:b,handle:function(a){var f,e=a.relatedTarget,l=a.handleObj;if(!e||e!==this&&!d.contains(this,e))a.type=l.origType,f=l.handler.apply(this,arguments),a.type=b;return f}}});d.support.submitBubbles||(d.event.special.submit={setup:function(){if(d.nodeName(this,"form"))return!1;d.event.add(this,"click._submit keypress._submit",function(a){a=a.target;if((a=d.nodeName(a, +"input")||d.nodeName(a,"button")?a.form:j)&&!d._data(a,"submitBubbles"))d.event.add(a,"submit._submit",function(a){a._submit_bubble=!0}),d._data(a,"submitBubbles",!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&d.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(d.nodeName(this,"form"))return!1;d.event.remove(this,"._submit")}});d.support.changeBubbles||(d.event.special.change={setup:function(){if(Ja.test(this.nodeName)){if("checkbox"=== +this.type||"radio"===this.type)d.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),d.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1);d.event.simulate("change",this,a,!0)});return!1}d.event.add(this,"beforeactivate._change",function(a){a=a.target;Ja.test(a.nodeName)&&!d._data(a,"changeBubbles")&&(d.event.add(a,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&& +d.event.simulate("change",this.parentNode,a,!0)}),d._data(a,"changeBubbles",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type)return a.handleObj.handler.apply(this,arguments)},teardown:function(){d.event.remove(this,"._change");return!Ja.test(this.nodeName)}});d.support.focusinBubbles||d.each({focus:"focusin",blur:"focusout"},function(a,b){var h=0,f=function(a){d.event.simulate(b,a.target,d.event.fix(a),!0)};d.event.special[b]= +{setup:function(){0===h++&&v.addEventListener(a,f,!0)},teardown:function(){0===--h&&v.removeEventListener(a,f,!0)}}});d.fn.extend({on:function(a,b,h,f,e){var l,k;if("object"===typeof a){"string"!==typeof b&&(h=h||b,b=j);for(k in a)this.on(k,b,h,a[k],e);return this}null==h&&null==f?(f=b,h=b=j):null==f&&("string"===typeof b?(f=h,h=j):(f=h,h=b,b=j));if(!1===f)f=J;else if(!f)return this;1===e&&(l=f,f=function(a){d().off(a);return l.apply(this,arguments)},f.guid=l.guid||(l.guid=d.guid++));return this.each(function(){d.event.add(this, +a,f,h,b)})},one:function(a,b,d,f){return this.on(a,b,d,f,1)},off:function(a,b,h){var f;if(a&&a.preventDefault&&a.handleObj)return f=a.handleObj,d(a.delegateTarget).off(f.namespace?f.origType+"."+f.namespace:f.origType,f.selector,f.handler),this;if("object"===typeof a){for(f in a)this.off(f,b,a[f]);return this}if(!1===b||"function"===typeof b)h=b,b=j;!1===h&&(h=J);return this.each(function(){d.event.remove(this,a,h,b)})},bind:function(a,b,d){return this.on(a,null,b,d)},unbind:function(a,b){return this.off(a, +null,b)},delegate:function(a,b,d,f){return this.on(b,a,d,f)},undelegate:function(a,b,d){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",d)},trigger:function(a,b){return this.each(function(){d.event.trigger(a,b,this)})},triggerHandler:function(a,b){var h=this[0];if(h)return d.event.trigger(a,b,h,!0)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});d.each("blur,focus,focusin,focusout,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error,contextmenu".split(","), +function(a,b){d.fn[b]=function(a,d){return 0<arguments.length?this.on(b,null,a,d):this.trigger(b)};Kb.test(b)&&(d.event.fixHooks[b]=d.event.keyHooks);Lb.test(b)&&(d.event.fixHooks[b]=d.event.mouseHooks)});(function(a,b){var h,f,e,l,k,c,m,s,g;function t(a){return ya.test(a+"")}function n(){var a,b=[];return a=function(d,h){b.push(d+=" ")>D.cacheLength&&delete a[b.shift()];return a[d]=h}}function j(a){a[N]=!0;return a}function i(a){var b=w.createElement("div");try{return a(b)}catch(d){return!1}finally{}} +function B(a,b,d,e){var l,k,p,c,m;(b?b.ownerDocument||b:P)!==w&&O(b);b=b||w;d=d||[];if(!a||"string"!==typeof a)return d;if(1!==(c=b.nodeType)&&9!==c)return[];if(!M&&!e){if(l=sa.exec(a))if(p=l[1])if(9===c)if((k=b.getElementById(p))&&k.parentNode){if(k.id===p)return d.push(k),d}else return d;else{if(b.ownerDocument&&(k=b.ownerDocument.getElementById(p))&&V(b,k)&&k.id===p)return d.push(k),d}else{if(l[2])return X.apply(d,Y.call(b.getElementsByTagName(a),0)),d;if((p=l[3])&&h&&b.getElementsByClassName)return X.apply(d, +Y.call(b.getElementsByClassName(p),0)),d}if(f&&!ba.test(a)){l=!0;k=N;p=b;m=9===c&&a;if(1===c&&"object"!==b.nodeName.toLowerCase()){c=z(a);(l=b.getAttribute("id"))?k=l.replace(wa,"\\$&"):b.setAttribute("id",k);k="[id='"+k+"'] ";for(p=c.length;p--;)c[p]=k+C(c[p]);p=va.test(a)&&b.parentNode||b;m=c.join(",")}if(m)try{return X.apply(d,Y.call(p.querySelectorAll(m),0)),d}catch(s){}finally{l||b.removeAttribute("id")}}}var g;a:{a=a.replace(ca,"$1");k=z(a);if(!e&&1===k.length){l=k[0]=k[0].slice(0);if(2<l.length&& +"ID"===(g=l[0]).type&&9===b.nodeType&&!M&&D.relative[l[1].type]){b=D.find.ID(g.matches[0].replace(oa,pa),b)[0];if(!b){g=d;break a}a=a.slice(l.shift().value.length)}for(c=fa.needsContext.test(a)?-1:l.length-1;0<=c;c--){g=l[c];if(D.relative[p=g.type])break;if(p=D.find[p])if(e=p(g.matches[0].replace(oa,pa),va.test(l[0].type)&&b.parentNode||b)){l.splice(c,1);a=e.length&&C(l);if(!a){X.apply(d,Y.call(e,0));g=d;break a}break}}}H(a,k)(e,b,M,d,va.test(a));g=d}return g}function u(a,b){for(var d=a&&b&&a.nextSibling;d;d= +d.nextSibling)if(d===b)return-1;return a?1:-1}function R(a){return function(b){return"input"===b.nodeName.toLowerCase()&&b.type===a}}function Z(a){return function(b){var d=b.nodeName.toLowerCase();return("input"===d||"button"===d)&&b.type===a}}function r(a){return j(function(b){b=+b;return j(function(d,h){for(var f,e=a([],d.length,b),l=e.length;l--;)if(d[f=e[l]])d[f]=!(h[f]=d[f])})})}function z(a,b){var d,h,f,e,l,o,k;if(l=ha[a+" "])return b?0:l.slice(0);l=a;o=[];for(k=D.preFilter;l;){if(!d||(h=ka.exec(l)))h&& +(l=l.slice(h[0].length)||l),o.push(f=[]);d=!1;if(h=na.exec(l))d=h.shift(),f.push({value:d,type:h[0].replace(ca," ")}),l=l.slice(d.length);for(e in D.filter)if((h=fa[e].exec(l))&&(!k[e]||(h=k[e](h))))d=h.shift(),f.push({value:d,type:e,matches:h}),l=l.slice(d.length);if(!d)break}return b?l.length:l?B.error(a):ha(a,o).slice(0)}function C(a){for(var b=0,d=a.length,h="";b<d;b++)h+=a[b].value;return h}function S(a,b,d){var h=b.dir,f=d&&"parentNode"===b.dir,e=$++;return b.first?function(b,d,e){for(;b=b[h];)if(1=== +b.nodeType||f)return a(b,d,e)}:function(b,d,l){var o,k,p,c=L+" "+e;if(l)for(;b=b[h];){if((1===b.nodeType||f)&&a(b,d,l))return!0}else for(;b=b[h];)if(1===b.nodeType||f)if(p=b[N]||(b[N]={}),(k=p[h])&&k[0]===c){if(!0===(o=k[1])||o===y)return!0===o}else if(k=p[h]=[c],k[1]=a(b,d,l)||y,!0===k[1])return!0}}function v(a){return 1<a.length?function(b,d,h){for(var f=a.length;f--;)if(!a[f](b,d,h))return!1;return!0}:a[0]}function A(a,b,d,h,f){for(var e,l=[],o=0,k=a.length,p=null!=b;o<k;o++)if(e=a[o])if(!d||d(e, +h,f))l.push(e),p&&b.push(o);return l}function x(a,b,d,h,f,e){h&&!h[N]&&(h=x(h));f&&!f[N]&&(f=x(f,e));return j(function(e,l,o,k){var p,c,m=[],g=[],s=l.length,t;if(!(t=e)){t=b||"*";for(var n=o.nodeType?[o]:o,j=[],i=0,Ba=n.length;i<Ba;i++)B(t,n[i],j);t=j}t=a&&(e||!b)?A(t,m,a,o,k):t;n=d?f||(e?a:s||h)?[]:l:t;d&&d(t,n,o,k);if(h){p=A(n,g);h(p,[],o,k);for(o=p.length;o--;)if(c=p[o])n[g[o]]=!(t[g[o]]=c)}if(e){if(f||a){if(f){p=[];for(o=n.length;o--;)if(c=n[o])p.push(t[o]=c);f(null,n=[],p,k)}for(o=n.length;o--;)if((c= +n[o])&&-1<(p=f?ma.call(e,c):m[o]))e[p]=!(l[p]=c)}}else n=A(n===l?n.splice(s,n.length):n),f?f(null,l,n,k):X.apply(l,n)})}function I(a){var b,d,h,f=a.length,e=D.relative[a[0].type];d=e||D.relative[" "];for(var l=e?1:0,o=S(function(a){return a===b},d,!0),k=S(function(a){return-1<ma.call(b,a)},d,!0),p=[function(a,d,h){return!e&&(h||d!==E)||((b=d).nodeType?o(a,d,h):k(a,d,h))}];l<f;l++)if(d=D.relative[a[l].type])p=[S(v(p),d)];else{d=D.filter[a[l].type].apply(null,a[l].matches);if(d[N]){for(h=++l;h<f&&!D.relative[a[h].type];h++); +return x(1<l&&v(p),1<l&&C(a.slice(0,l-1)).replace(ca,"$1"),d,l<h&&I(a.slice(l,h)),h<f&&I(a=a.slice(h)),h<f&&C(a))}p.push(d)}return v(p)}function J(a,b){var d=0,h=0<b.length,f=0<a.length,e=function(e,l,o,k,p){var c,m,g=[],s=0,t="0",n=e&&[],j=null!=p,i=E,Ba=e||f&&D.find.TAG("*",p&&l.parentNode||l),u=L+=null==i?1:Math.E;j&&(E=l!==w&&l,y=d);for(;null!=(p=Ba[t]);t++){if(f&&p){for(c=0;m=a[c];c++)if(m(p,l,o)){k.push(p);break}j&&(L=u,y=++d)}h&&((p=!m&&p)&&s--,e&&n.push(p))}s+=t;if(h&&t!==s){for(c=0;m=b[c];c++)m(n, +g,l,o);if(e){if(0<s)for(;t--;)!n[t]&&!g[t]&&(g[t]=ia.call(k));g=A(g)}X.apply(k,g);j&&!e&&0<g.length&&1<s+b.length&&B.uniqueSort(k)}j&&(L=u,E=i);return n};return h?j(e):e}function G(){}var q,y,D,ea,K,H,F,E,O,w,Q,M,ba,la,T,V,W,N="sizzle"+-new Date,P=a.document;h=void 0;f=void 0;e=void 0;l=void 0;k=void 0;c=void 0;m=void 0;s=void 0;g=void 0;var L=0,$=0,aa=n(),ha=n(),Aa=n(),ja=typeof b,U=[],ia=U.pop,X=U.push,Y=U.slice,ma=U.indexOf||function(a){for(var b=0,d=this.length;b<d;b++)if(this[b]===a)return b; +return-1},U="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+".replace("w","w#"),ga="\\[[\\x20\\t\\r\\n\\f]*((?:\\\\.|[\\w-]|[^\\x00-\\xa0])+)[\\x20\\t\\r\\n\\f]*(?:([*^$|!~]?=)[\\x20\\t\\r\\n\\f]*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+U+")|)|)[\\x20\\t\\r\\n\\f]*\\]",da=":((?:\\\\.|[\\w-]|[^\\x00-\\xa0])+)(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+ga.replace(3,8)+")*)|.*)\\)|)",ca=RegExp("^[\\x20\\t\\r\\n\\f]+|((?:^|[^\\\\])(?:\\\\.)*)[\\x20\\t\\r\\n\\f]+$","g"),ka=/^[\x20\t\r\n\f]*,[\x20\t\r\n\f]*/, +na=/^[\x20\t\r\n\f]*([\x20\t\r\n\f>+~])[\x20\t\r\n\f]*/,qa=RegExp(da),ra=RegExp("^"+U+"$"),fa={ID:/^#((?:\\.|[\w-]|[^\x00-\xa0])+)/,CLASS:/^\.((?:\\.|[\w-]|[^\x00-\xa0])+)/,NAME:/^\[name=['"]?((?:\\.|[\w-]|[^\x00-\xa0])+)['"]?\]/,TAG:RegExp("^("+"(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+".replace("w","w*")+")"),ATTR:RegExp("^"+ga),PSEUDO:RegExp("^"+da),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\([\\x20\\t\\r\\n\\f]*(even|odd|(([+-]|)(\\d*)n|)[\\x20\\t\\r\\n\\f]*(?:([+-]|)[\\x20\\t\\r\\n\\f]*(\\d+)|))[\\x20\\t\\r\\n\\f]*\\)|)", +"i"),needsContext:RegExp("^[\\x20\\t\\r\\n\\f]*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\([\\x20\\t\\r\\n\\f]*((?:-\\d)?\\d*)[\\x20\\t\\r\\n\\f]*\\)|)(?=[^-]|$)","i")},va=/[\x20\t\r\n\f]*[+~]/,ya=/\{\s*\[native code\]\s*\}/,sa=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ta=/^(?:input|select|textarea|button)$/i,ua=/^h\d$/i,wa=/'|\\/g,xa=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,oa=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,pa=function(a,b){var d="0x"+b-65536;return d!==d?b:0>d?String.fromCharCode(d+ +65536):String.fromCharCode(d>>10|55296,d&1023|56320)};try{Y.call(Q.childNodes,0)[0].nodeType}catch(za){Y=function(a){for(var b,d=[];b=this[a];a++)d.push(b);return d}}K=B.isXML=function(a){return(a=a&&(a.ownerDocument||a).documentElement)?"HTML"!==a.nodeName:!1};O=B.setDocument=function(a){var d=a?a.ownerDocument||a:P;if(d===w||9!==d.nodeType||!d.documentElement)return w;w=d;Q=d.documentElement;M=K(d);e=i(function(a){a.appendChild(d.createComment(""));return!a.getElementsByTagName("*").length});l= +i(function(a){a.innerHTML="<select></select>";a=typeof a.lastChild.getAttribute("multiple");return"boolean"!==a&&"string"!==a});h=i(function(a){a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>";if(!a.getElementsByClassName||!a.getElementsByClassName("e").length)return!1;a.lastChild.className="e";return 2===a.getElementsByClassName("e").length});k=i(function(a){a.id=N+0;a.innerHTML="<a name='"+N+"'></a><div name='"+N+"'></div>";Q.insertBefore(a,Q.firstChild);var b=d.getElementsByName&& +d.getElementsByName(N).length===2+d.getElementsByName(N+0).length;c=!d.getElementById(N);Q.removeChild(a);return b});D.attrHandle=i(function(a){a.innerHTML="<a href='#'></a>";return a.firstChild&&typeof a.firstChild.getAttribute!==ja&&"#"===a.firstChild.getAttribute("href")})?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}};c?(D.find.ID=function(a,b){if(typeof b.getElementById!==ja&&!M){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}, +D.filter.ID=function(a){var b=a.replace(oa,pa);return function(a){return a.getAttribute("id")===b}}):(D.find.ID=function(a,d){if(typeof d.getElementById!==ja&&!M){var h=d.getElementById(a);return h?h.id===a||typeof h.getAttributeNode!==ja&&h.getAttributeNode("id").value===a?[h]:b:[]}},D.filter.ID=function(a){var b=a.replace(oa,pa);return function(a){return(a=typeof a.getAttributeNode!==ja&&a.getAttributeNode("id"))&&a.value===b}});D.find.TAG=e?function(a,b){if(typeof b.getElementsByTagName!==ja)return b.getElementsByTagName(a)}: +function(a,b){var d,h=[],f=0,e=b.getElementsByTagName(a);if("*"===a){for(;d=e[f];f++)1===d.nodeType&&h.push(d);return h}return e};D.find.NAME=k&&function(a,b){if(typeof b.getElementsByName!==ja)return b.getElementsByName(name)};D.find.CLASS=h&&function(a,b){if(typeof b.getElementsByClassName!==ja&&!M)return b.getElementsByClassName(a)};la=[];ba=[":focus"];if(f=t(d.querySelectorAll))i(function(a){a.innerHTML="<select><option selected=''></option></select>";a.querySelectorAll("[selected]").length|| +ba.push("\\[[\\x20\\t\\r\\n\\f]*(?:checked|disabled|ismap|multiple|readonly|selected|value)");a.querySelectorAll(":checked").length||ba.push(":checked")}),i(function(a){a.innerHTML="<input type='hidden' i=''/>";a.querySelectorAll("[i^='']").length&&ba.push("[*^$]=[\\x20\\t\\r\\n\\f]*(?:\"\"|'')");a.querySelectorAll(":enabled").length||ba.push(":enabled",":disabled");a.querySelectorAll("*,:x");ba.push(",.*:")});(m=t(T=Q.matchesSelector||Q.mozMatchesSelector||Q.webkitMatchesSelector||Q.oMatchesSelector|| +Q.msMatchesSelector))&&i(function(a){s=T.call(a,"div");T.call(a,"[s!='']:x");la.push("!=",da)});ba=RegExp(ba.join("|"));la=RegExp(la.join("|"));V=t(Q.contains)||Q.compareDocumentPosition?function(a,b){var d=9===a.nodeType?a.documentElement:a,h=b&&b.parentNode;return a===h||!(!h||!(1===h.nodeType&&(d.contains?d.contains(h):a.compareDocumentPosition&&a.compareDocumentPosition(h)&16)))}:function(a,b){if(b)for(;b=b.parentNode;)if(b===a)return!0;return!1};W=Q.compareDocumentPosition?function(a,b){var h; +return a===b?(F=!0,0):(h=b.compareDocumentPosition&&a.compareDocumentPosition&&a.compareDocumentPosition(b))?h&1||a.parentNode&&11===a.parentNode.nodeType?a===d||V(P,a)?-1:b===d||V(P,b)?1:0:h&4?-1:1:a.compareDocumentPosition?-1:1}:function(a,b){var h,f=0;h=a.parentNode;var e=b.parentNode,l=[a],o=[b];if(a===b)return F=!0,0;if(a.sourceIndex&&b.sourceIndex)return(~b.sourceIndex||-2147483648)-(V(P,a)&&~a.sourceIndex||-2147483648);if(!h||!e)return a===d?-1:b===d?1:h?-1:e?1:0;if(h===e)return u(a,b);for(h= +a;h=h.parentNode;)l.unshift(h);for(h=b;h=h.parentNode;)o.unshift(h);for(;l[f]===o[f];)f++;return f?u(l[f],o[f]):l[f]===P?-1:o[f]===P?1:0};F=!1;[0,0].sort(W);g=F;return w};B.matches=function(a,b){return B(a,null,null,b)};B.matchesSelector=function(a,b){(a.ownerDocument||a)!==w&&O(a);b=b.replace(xa,"='$1']");if(m&&!M&&(!la||!la.test(b))&&!ba.test(b))try{var d=T.call(a,b);if(d||s||a.document&&11!==a.document.nodeType)return d}catch(h){}return 0<B(b,w,null,[a]).length};B.contains=function(a,b){(a.ownerDocument|| +a)!==w&&O(a);return V(a,b)};B.attr=function(a,b){var d;(a.ownerDocument||a)!==w&&O(a);M||(b=b.toLowerCase());return(d=D.attrHandle[b])?d(a):M||l?a.getAttribute(b):((d=a.getAttributeNode(b))||a.getAttribute(b))&&!0===a[b]?b:d&&d.specified?d.value:null};B.error=function(a){throw Error("Syntax error, unrecognized expression: "+a);};B.uniqueSort=function(a){var b,d=[],h=1,f=0;F=!g;a.sort(W);if(F){for(;b=a[h];h++)b===a[h-1]&&(f=d.push(h));for(;f--;)a.splice(d[f],1)}return a};ea=B.getText=function(a){var b, +d="",h=0;if(b=a.nodeType)if(1===b||9===b||11===b){if("string"===typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)d+=ea(a)}else{if(3===b||4===b)return a.nodeValue}else for(;b=a[h];h++)d+=ea(b);return d};D=B.selectors={cacheLength:50,createPseudo:j,match:fa,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){a[1]=a[1].replace(oa,pa);a[3]=(a[4]||a[5]||"").replace(oa, +pa);"~="===a[2]&&(a[3]=" "+a[3]+" ");return a.slice(0,4)},CHILD:function(a){a[1]=a[1].toLowerCase();"nth"===a[1].slice(0,3)?(a[3]||B.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&B.error(a[0]);return a},PSEUDO:function(a){var b,d=!a[5]&&a[2];if(fa.CHILD.test(a[0]))return null;if(a[4])a[2]=a[4];else if(d&&qa.test(d)&&(b=z(d,!0))&&(b=d.indexOf(")",d.length-b)-d.length))a[0]=a[0].slice(0,b),a[2]=d.slice(0,b);return a.slice(0,3)}},filter:{TAG:function(a){if("*"=== +a)return function(){return!0};a=a.replace(oa,pa).toLowerCase();return function(b){return b.nodeName&&b.nodeName.toLowerCase()===a}},CLASS:function(a){var b=aa[a+" "];return b||(b=RegExp("(^|[\\x20\\t\\r\\n\\f])"+a+"([\\x20\\t\\r\\n\\f]|$)"))&&aa(a,function(a){return b.test(a.className||typeof a.getAttribute!==ja&&a.getAttribute("class")||"")})},ATTR:function(a,b,d){return function(h){h=B.attr(h,a);if(null==h)return"!="===b;if(!b)return!0;h+="";return"="===b?h===d:"!="===b?h!==d:"^="===b?d&&0===h.indexOf(d): +"*="===b?d&&-1<h.indexOf(d):"$="===b?d&&h.substr(h.length-d.length)===d:"~="===b?-1<(" "+h+" ").indexOf(d):"|="===b?h===d||h.substr(0,d.length+1)===d+"-":!1}},CHILD:function(a,b,d,h,f){var e="nth"!==a.slice(0,3),l="last"!==a.slice(-4),o="of-type"===b;return 1===h&&0===f?function(a){return!!a.parentNode}:function(b,d,k){var p,c,m,g,s,d=e!==l?"nextSibling":"previousSibling",t=b.parentNode,n=o&&b.nodeName.toLowerCase(),k=!k&&!o;if(t){if(e){for(;d;){for(c=b;c=c[d];)if(o?c.nodeName.toLowerCase()===n:1=== +c.nodeType)return!1;s=d="only"===a&&!s&&"nextSibling"}return!0}s=[l?t.firstChild:t.lastChild];if(l&&k){k=t[N]||(t[N]={});p=k[a]||[];g=p[0]===L&&p[1];m=p[0]===L&&p[2];for(c=g&&t.childNodes[g];c=++g&&c&&c[d]||(m=g=0)||s.pop();)if(1===c.nodeType&&++m&&c===b){k[a]=[L,g,m];break}}else if(k&&(p=(b[N]||(b[N]={}))[a])&&p[0]===L)m=p[1];else for(;c=++g&&c&&c[d]||(m=g=0)||s.pop();)if((o?c.nodeName.toLowerCase()===n:1===c.nodeType)&&++m)if(k&&((c[N]||(c[N]={}))[a]=[L,m]),c===b)break;m-=f;return m===h||0===m% +h&&0<=m/h}}},PSEUDO:function(a,b){var d,h=D.pseudos[a]||D.setFilters[a.toLowerCase()]||B.error("unsupported pseudo: "+a);if(h[N])return h(b);return 1<h.length?(d=[a,a,"",b],D.setFilters.hasOwnProperty(a.toLowerCase())?j(function(a,d){for(var f,e=h(a,b),l=e.length;l--;)f=ma.call(a,e[l]),a[f]=!(d[f]=e[l])}):function(a){return h(a,0,d)}):h}},pseudos:{not:j(function(a){var b=[],d=[],h=H(a.replace(ca,"$1"));return h[N]?j(function(a,b,d,f){for(var f=h(a,null,f,[]),e=a.length;e--;)if(d=f[e])a[e]=!(b[e]= +d)}):function(a,f,e){b[0]=a;h(b,null,e,d);return!d.pop()}}),has:j(function(a){return function(b){return 0<B(a,b).length}}),contains:j(function(a){return function(b){return-1<(b.textContent||b.innerText||ea(b)).indexOf(a)}}),lang:j(function(a){ra.test(a||"")||B.error("unsupported lang: "+a);a=a.replace(oa,pa).toLowerCase();return function(b){var d;do if(d=M?b.getAttribute("xml:lang")||b.getAttribute("lang"):b.lang)return d=d.toLowerCase(),d===a||0===d.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType); +return!1}}),target:function(b){var d=a.location&&a.location.hash;return d&&d.slice(1)===b.id},root:function(a){return a===Q},focus:function(a){return a===w.activeElement&&(!w.hasFocus||w.hasFocus())&&!(!a.type&&!a.href&&!~a.tabIndex)},enabled:function(a){return!1===a.disabled},disabled:function(a){return!0===a.disabled},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return!0=== +a.selected},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if("@"<a.nodeName||3===a.nodeType||4===a.nodeType)return!1;return!0},parent:function(a){return!D.pseudos.empty(a)},header:function(a){return ua.test(a.nodeName)},input:function(a){return ta.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||b.toLowerCase()=== +a.type)},first:r(function(){return[0]}),last:r(function(a,b){return[b-1]}),eq:r(function(a,b,d){return[0>d?d+b:d]}),even:r(function(a,b){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:r(function(a,b){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:r(function(a,b,d){for(b=0>d?d+b:d;0<=--b;)a.push(b);return a}),gt:r(function(a,b,d){for(d=0>d?d+b:d;++d<b;)a.push(d);return a})}};for(q in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})D.pseudos[q]=R(q);for(q in{submit:!0,reset:!0})D.pseudos[q]=Z(q);H= +B.compile=function(a,b){var d,h=[],f=[],e=Aa[a+" "];if(!e){b||(b=z(a));for(d=b.length;d--;)e=I(b[d]),e[N]?h.push(e):f.push(e);e=Aa(a,J(f,h))}return e};D.pseudos.nth=D.pseudos.eq;D.filters=G.prototype=D.pseudos;D.setFilters=new G;O();B.attr=d.attr;d.find=B;d.expr=B.selectors;d.expr[":"]=d.expr.pseudos;d.unique=B.uniqueSort;d.text=B.getText;d.isXMLDoc=B.isXML;d.contains=B.contains})(c);var Mb=/Until$/,Nb=/^(?:parents|prev(?:Until|All))/,sb=/^.[^:#\[\.,]*$/,bb=d.expr.match.needsContext,Ob={children:!0, +contents:!0,next:!0,prev:!0};d.fn.extend({find:function(a){var b,h,f;if("string"!==typeof a)return f=this,this.pushStack(d(a).filter(function(){for(b=0;b<f.length;b++)if(d.contains(f[b],this))return!0}));h=[];for(b=0;b<this.length;b++)d.find(a,this[b],h);h=this.pushStack(d.unique(h));h.selector=(this.selector?this.selector+" ":"")+a;return h},has:function(a){var b,h=d(a,this),f=h.length;return this.filter(function(){for(b=0;b<f;b++)if(d.contains(this,h[b]))return!0})},not:function(a){return this.pushStack(E(this, +a,!1))},filter:function(a){return this.pushStack(E(this,a,!0))},is:function(a){return!!a&&("string"===typeof a?bb.test(a)?0<=d(a,this.context).index(this[0]):0<d.filter(a,this).length:0<this.filter(a).length)},closest:function(a,b){for(var h,f=0,e=this.length,l=[],k=bb.test(a)||"string"!==typeof a?d(a,b||this.context):0;f<e;f++)for(h=this[f];h&&h.ownerDocument&&h!==b&&11!==h.nodeType;){if(k?-1<k.index(h):d.find.matchesSelector(h,a)){l.push(h);break}h=h.parentNode}return this.pushStack(1<l.length? +d.unique(l):l)},index:function(a){return!a?this[0]&&this[0].parentNode?this.first().prevAll().length:-1:"string"===typeof a?d.inArray(this[0],d(a)):d.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var h="string"===typeof a?d(a,b):d.makeArray(a&&a.nodeType?[a]:a),h=d.merge(this.get(),h);return this.pushStack(d.unique(h))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});d.fn.andSelf=d.fn.addBack;d.each({parent:function(a){return(a=a.parentNode)&&11!==a.nodeType? +a:null},parents:function(a){return d.dir(a,"parentNode")},parentsUntil:function(a,b,h){return d.dir(a,"parentNode",h)},next:function(a){return y(a,"nextSibling")},prev:function(a){return y(a,"previousSibling")},nextAll:function(a){return d.dir(a,"nextSibling")},prevAll:function(a){return d.dir(a,"previousSibling")},nextUntil:function(a,b,h){return d.dir(a,"nextSibling",h)},prevUntil:function(a,b,h){return d.dir(a,"previousSibling",h)},siblings:function(a){return d.sibling((a.parentNode||{}).firstChild, +a)},children:function(a){return d.sibling(a.firstChild)},contents:function(a){return d.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:d.merge([],a.childNodes)}},function(a,b){d.fn[a]=function(h,f){var e=d.map(this,b,h);Mb.test(a)||(f=h);f&&"string"===typeof f&&(e=d.filter(f,e));e=1<this.length&&!Ob[a]?d.unique(e):e;1<this.length&&Nb.test(a)&&(e=e.reverse());return this.pushStack(e)}});d.extend({filter:function(a,b,h){h&&(a=":not("+a+")");return 1===b.length?d.find.matchesSelector(b[0], +a)?[b[0]]:[]:d.find.matches(a,b)},dir:function(a,b,h){for(var f=[],a=a[b];a&&9!==a.nodeType&&(h===j||1!==a.nodeType||!d(a).is(h));)1===a.nodeType&&f.push(a),a=a[b];return f},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&d.push(a);return d}});var Ta="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",Pb=/ jQuery\d+="(?:null|\d+)"/g,cb=RegExp("<(?:"+Ta+")[\\s/>]","i"), +Ka=/^\s+/,db=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,eb=/<([\w:]+)/,fb=/<tbody/i,Qb=/<|&#?\w+;/,Rb=/<(?:script|style|link)/i,Ca=/^(?:checkbox|radio)$/i,Sb=/checked\s*(?:[^=]|=\s*.checked.)/i,gb=/^$|\/(?:java|ecma)script/i,tb=/^true\/(.*)/,Tb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,L={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"], +tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:d.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},La=K(v).appendChild(v.createElement("div"));L.optgroup=L.option;L.tbody=L.tfoot=L.colgroup=L.caption=L.thead;L.th=L.td;d.fn.extend({text:function(a){return d.access(this,function(a){return a===j?d.text(this):this.empty().append((this[0]&&this[0].ownerDocument||v).createTextNode(a))}, +null,a,arguments.length)},wrapAll:function(a){if(d.isFunction(a))return this.each(function(b){d(this).wrapAll(a.call(this,b))});if(this[0]){var b=d(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var a=this;a.firstChild&&1===a.firstChild.nodeType;)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return d.isFunction(a)?this.each(function(b){d(this).wrapInner(a.call(this,b))}):this.each(function(){var b=d(this),h=b.contents(); +h.length?h.wrapAll(a):b.append(a)})},wrap:function(a){var b=d.isFunction(a);return this.each(function(h){d(this).wrapAll(b?a.call(this,h):a)})},unwrap:function(){return this.parent().each(function(){d.nodeName(this,"body")||d(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(1===this.nodeType|| +11===this.nodeType||9===this.nodeType)&&this.insertBefore(a,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,!1,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var h,f=0;null!=(h=this[f]);f++)if(!a||0<d.filter(a,[h]).length)!b&&1===h.nodeType&&d.cleanData(x(h)),h.parentNode&&(b&&d.contains(h.ownerDocument, +h)&&Z(x(h,"script")),h.parentNode.removeChild(h));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){for(1===a.nodeType&&d.cleanData(x(a,!1));a.firstChild;)a.removeChild(a.firstChild);a.options&&d.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){a=null==a?!1:a;b=null==b?a:b;return this.map(function(){return d.clone(this,a,b)})},html:function(a){return d.access(this,function(a){var h=this[0]||{},f=0,e=this.length;if(a===j)return 1===h.nodeType?h.innerHTML.replace(Pb, +""):j;if("string"===typeof a&&!Rb.test(a)&&(d.support.htmlSerialize||!cb.test(a))&&(d.support.leadingWhitespace||!Ka.test(a))&&!L[(eb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(db,"<$1></$2>");try{for(;f<e;f++)h=this[f]||{},1===h.nodeType&&(d.cleanData(x(h,!1)),h.innerHTML=a);h=0}catch(l){}}h&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){!d.isFunction(a)&&"string"!==typeof a&&(a=d(a).not(this).detach());return this.domManip([a],!0,function(a){var h=this.nextSibling, +f=this.parentNode;if(f&&1===this.nodeType||11===this.nodeType)d(this).remove(),h?h.parentNode.insertBefore(a,h):f.appendChild(a)})},detach:function(a){return this.remove(a,!0)},domManip:function(a,b,h){var a=va.apply([],a),f,e,l,k,c=0,m=this.length,g=this,s=m-1,t=a[0],n=d.isFunction(t);if(n||!(1>=m||"string"!==typeof t||d.support.checkClone||!Sb.test(t)))return this.each(function(d){var f=g.eq(d);n&&(a[0]=t.call(this,d,b?f.html():j));f.domManip(a,b,h)});if(m&&(f=d.buildFragment(a,this[0].ownerDocument, +!1,this),e=f.firstChild,1===f.childNodes.length&&(f=e),e)){b=b&&d.nodeName(e,"tr");e=d.map(x(f,"script"),F);for(l=e.length;c<m;c++)k=f,c!==s&&(k=d.clone(k,!0,!0),l&&d.merge(e,x(k,"script"))),h.call(b&&d.nodeName(this[c],"table")?this[c].getElementsByTagName("tbody")[0]||this[c].appendChild(this[c].ownerDocument.createElement("tbody")):this[c],k,c);if(l){f=e[e.length-1].ownerDocument;d.map(e,T);for(c=0;c<l;c++)if(k=e[c],gb.test(k.type||"")&&!d._data(k,"globalEval")&&d.contains(f,k))k.src?d.ajax({url:k.src, +type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):d.globalEval((k.text||k.textContent||k.innerHTML||"").replace(Tb,""))}f=e=null}return this}});d.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){d.fn[a]=function(a){for(var f=0,e=[],l=d(a),k=l.length-1;f<=k;f++)a=f===k?this:this.clone(!0),d(l[f])[b](a),ya.apply(e,a.get());return this.pushStack(e)}});d.extend({clone:function(a,b,h){var f,e,l,k,c,m=d.contains(a.ownerDocument, +a);d.support.html5Clone||d.isXMLDoc(a)||!cb.test("<"+a.nodeName+">")?c=a.cloneNode(!0):(La.innerHTML=a.outerHTML,La.removeChild(c=La.firstChild));if((!d.support.noCloneEvent||!d.support.noCloneChecked)&&(1===a.nodeType||11===a.nodeType)&&!d.isXMLDoc(a)){f=x(c);e=x(a);for(k=0;null!=(l=e[k]);++k)if(f[k]){var g=f[k],s=void 0,t=void 0,n=void 0;if(1===g.nodeType){s=g.nodeName.toLowerCase();if(!d.support.noCloneEvent&&g[d.expando]){t=d._data(g);for(n in t.events)d.removeEvent(g,n,t.handle);g.removeAttribute(d.expando)}if("script"=== +s&&g.text!==l.text)F(g).text=l.text,T(g);else if("object"===s)g.parentNode&&(g.outerHTML=l.outerHTML),d.support.html5Clone&&l.innerHTML&&!d.trim(g.innerHTML)&&(g.innerHTML=l.innerHTML);else if("input"===s&&Ca.test(l.type))g.defaultChecked=g.checked=l.checked,g.value!==l.value&&(g.value=l.value);else if("option"===s)g.defaultSelected=g.selected=l.defaultSelected;else if("input"===s||"textarea"===s)g.defaultValue=l.defaultValue}}}if(b)if(h){e=e||x(a);f=f||x(c);for(k=0;null!=(l=e[k]);k++)I(l,f[k])}else I(a, +c);f=x(c,"script");0<f.length&&Z(f,!m&&x(a,"script"));return c},buildFragment:function(a,b,h,f){for(var e,l,k,c,m,g,s=a.length,t=K(b),n=[],j=0;j<s;j++)if((e=a[j])||0===e)if("object"===d.type(e))d.merge(n,e.nodeType?[e]:e);else if(Qb.test(e)){k=k||t.appendChild(b.createElement("div"));l=(eb.exec(e)||["",""])[1].toLowerCase();c=L[l]||L._default;k.innerHTML=c[1]+e.replace(db,"<$1></$2>")+c[2];for(g=c[0];g--;)k=k.lastChild;!d.support.leadingWhitespace&&Ka.test(e)&&n.push(b.createTextNode(Ka.exec(e)[0])); +if(!d.support.tbody)for(g=(e="table"===l&&!fb.test(e)?k.firstChild:"<table>"===c[1]&&!fb.test(e)?k:0)&&e.childNodes.length;g--;)d.nodeName(m=e.childNodes[g],"tbody")&&!m.childNodes.length&&e.removeChild(m);d.merge(n,k.childNodes);for(k.textContent="";k.firstChild;)k.removeChild(k.firstChild);k=t.lastChild}else n.push(b.createTextNode(e));k&&t.removeChild(k);d.support.appendChecked||d.grep(x(n,"input"),G);for(j=0;e=n[j++];)if(!(f&&-1!==d.inArray(e,f))&&(a=d.contains(e.ownerDocument,e),k=x(t.appendChild(e), +"script"),a&&Z(k),h))for(g=0;e=k[g++];)gb.test(e.type||"")&&h.push(e);return t},cleanData:function(a,b){for(var h,f,e,l,k=0,c=d.expando,g=d.cache,m=d.support.deleteExpando,s=d.event.special;null!=(e=a[k]);k++)if(b||d.acceptData(e))if(h=(f=e[c])&&g[f]){if(h.events)for(l in h.events)s[l]?d.event.remove(e,l):d.removeEvent(e,l,h.handle);g[f]&&(delete g[f],m?delete e[c]:"undefined"!==typeof e.removeAttribute?e.removeAttribute(c):e[c]=null,ha.push(f))}}});var Y,X,ra,Ma=/alpha\([^)]*\)/i,Ub=/opacity\s*=\s*([^)]*)/, +Vb=/^(top|right|bottom|left)$/,Wb=/^(none|table(?!-c[ea]).+)/,hb=/^margin/,ub=RegExp("^("+wa+")(.*)$","i"),ta=RegExp("^("+wa+")(?!px)[a-z%]+$","i"),Xb=RegExp("^([+-])=("+wa+")","i"),Va={BODY:"block"},Yb={position:"absolute",visibility:"hidden",display:"block"},ib={letterSpacing:0,fontWeight:400},ia=["Top","Right","Bottom","Left"],Ua=["Webkit","O","Moz","ms"];d.fn.extend({css:function(a,b){return d.access(this,function(a,b,f){var e,l={},k=0;if(d.isArray(b)){f=X(a);for(e=b.length;k<e;k++)l[b[k]]=d.css(a, +b[k],!1,f);return l}return f!==j?d.style(a,b,f):d.css(a,b)},a,b,1<arguments.length)},show:function(){return m(this,!0)},hide:function(){return m(this)},toggle:function(a){var b="boolean"===typeof a;return this.each(function(){(b?a:H(this))?d(this).show():d(this).hide()})}});d.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=Y(a,"opacity");return""===d?"1":d}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":d.support.cssFloat? +"cssFloat":"styleFloat"},style:function(a,b,h,f){if(a&&!(3===a.nodeType||8===a.nodeType||!a.style)){var e,l,k,c=d.camelCase(b),g=a.style,b=d.cssProps[c]||(d.cssProps[c]=O(g,c));k=d.cssHooks[b]||d.cssHooks[c];if(h!==j){l=typeof h;if("string"===l&&(e=Xb.exec(h)))h=(e[1]+1)*e[2]+parseFloat(d.css(a,b)),l="number";if(!(null==h||"number"===l&&isNaN(h)))if("number"===l&&!d.cssNumber[c]&&(h+="px"),!d.support.clearCloneStyle&&""===h&&0===b.indexOf("background")&&(g[b]="inherit"),!k||!("set"in k)||(h=k.set(a, +h,f))!==j)try{g[b]=h}catch(m){}}else return k&&"get"in k&&(e=k.get(a,!1,f))!==j?e:g[b]}},css:function(a,b,h,f){var e,l;l=d.camelCase(b);b=d.cssProps[l]||(d.cssProps[l]=O(a.style,l));(l=d.cssHooks[b]||d.cssHooks[l])&&"get"in l&&(e=l.get(a,!0,h));e===j&&(e=Y(a,b,f));"normal"===e&&b in ib&&(e=ib[b]);return h?(a=parseFloat(e),!0===h||d.isNumeric(a)?a||0:e):e},swap:function(a,b,d,f){var e,l={};for(e in b)l[e]=a.style[e],a.style[e]=b[e];d=d.apply(a,f||[]);for(e in b)a.style[e]=l[e];return d}});c.getComputedStyle? +(X=function(a){return c.getComputedStyle(a,null)},Y=function(a,b,h){var f,e=(h=h||X(a))?h.getPropertyValue(b)||h[b]:j,l=a.style;h&&(""===e&&!d.contains(a.ownerDocument,a)&&(e=d.style(a,b)),ta.test(e)&&hb.test(b)&&(a=l.width,b=l.minWidth,f=l.maxWidth,l.minWidth=l.maxWidth=l.width=e,e=h.width,l.width=a,l.minWidth=b,l.maxWidth=f));return e}):v.documentElement.currentStyle&&(X=function(a){return a.currentStyle},Y=function(a,b,d){var f,e,l=(d=d||X(a))?d[b]:j,k=a.style;null==l&&k&&k[b]&&(l=k[b]);if(ta.test(l)&& +!Vb.test(b)){d=k.left;if(e=(f=a.runtimeStyle)&&f.left)f.left=a.currentStyle.left;k.left="fontSize"===b?"1em":l;l=k.pixelLeft+"px";k.left=d;e&&(f.left=e)}return""===l?"auto":l});d.each(["height","width"],function(a,b){d.cssHooks[b]={get:function(a,f,e){if(f)return 0===a.offsetWidth&&Wb.test(d.css(a,"display"))?d.swap(a,Yb,function(){return W(a,b,e)}):W(a,b,e)},set:function(a,f,e){var l=e&&X(a);return w(a,f,e?V(a,b,e,d.support.boxSizing&&"border-box"===d.css(a,"boxSizing",!1,l),l):0)}}});d.support.opacity|| +(d.cssHooks.opacity={get:function(a,b){return Ub.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?0.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var f=a.style,e=a.currentStyle,l=d.isNumeric(b)?"alpha(opacity="+100*b+")":"",k=e&&e.filter||f.filter||"";f.zoom=1;if((1<=b||""===b)&&""===d.trim(k.replace(Ma,""))&&f.removeAttribute)if(f.removeAttribute("filter"),""===b||e&&!e.filter)return;f.filter=Ma.test(k)?k.replace(Ma,l):k+" "+l}});d(function(){d.support.reliableMarginRight|| +(d.cssHooks.marginRight={get:function(a,b){if(b)return d.swap(a,{display:"inline-block"},Y,[a,"marginRight"])}});!d.support.pixelPosition&&d.fn.position&&d.each(["top","left"],function(a,b){d.cssHooks[b]={get:function(a,f){if(f)return f=Y(a,b),ta.test(f)?d(a).position()[b]+"px":f}}})});d.expr&&d.expr.filters&&(d.expr.filters.hidden=function(a){return 0===a.offsetWidth&&0===a.offsetHeight||!d.support.reliableHiddenOffsets&&"none"===(a.style&&a.style.display||d.css(a,"display"))},d.expr.filters.visible= +function(a){return!d.expr.filters.hidden(a)});d.each({margin:"",padding:"",border:"Width"},function(a,b){d.cssHooks[a+b]={expand:function(d){for(var f=0,e={},d="string"===typeof d?d.split(" "):[d];4>f;f++)e[a+ia[f]+b]=d[f]||d[f-2]||d[0];return e}};hb.test(a)||(d.cssHooks[a+b].set=w)});var Zb=/%20/g,vb=/\[\]$/,jb=/\r?\n/g,$b=/^(?:submit|button|image|reset)$/i,ac=/^(?:input|select|textarea|keygen)/i;d.fn.extend({serialize:function(){return d.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a= +d.prop(this,"elements");return a?d.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!d(this).is(":disabled")&&ac.test(this.nodeName)&&!$b.test(a)&&(this.checked||!Ca.test(a))}).map(function(a,b){var f=d(this).val();return null==f?null:d.isArray(f)?d.map(f,function(a){return{name:b.name,value:a.replace(jb,"\r\n")}}):{name:b.name,value:f.replace(jb,"\r\n")}}).get()}});d.param=function(a,b){var f,e=[],l=function(a,b){b=d.isFunction(b)?b():null==b?"":b;e[e.length]=encodeURIComponent(a)+ +"="+encodeURIComponent(b)};b===j&&(b=d.ajaxSettings&&d.ajaxSettings.traditional);if(d.isArray(a)||a.jquery&&!d.isPlainObject(a))d.each(a,function(){l(this.name,this.value)});else for(f in a)M(f,a[f],b,l);return e.join("&").replace(Zb,"+")};var ca,U,Na=d.now(),Oa=/\?/,bc=/#.*$/,kb=/([?&])_=[^&]*/,cc=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dc=/^(?:GET|HEAD)$/,ec=/^\/\//,lb=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,mb=d.fn.load,nb={},Da={},ob="*/".concat("*");try{U=ba.href}catch(jc){U=v.createElement("a"), +U.href="",U=U.href}ca=lb.exec(U.toLowerCase())||[];d.fn.load=function(a,b,f){if("string"!==typeof a&&mb)return mb.apply(this,arguments);var e,l,k,c=this,g=a.indexOf(" ");0<=g&&(e=a.slice(g,a.length),a=a.slice(0,g));d.isFunction(b)?(f=b,b=j):b&&"object"===typeof b&&(l="POST");0<c.length&&d.ajax({url:a,type:l,dataType:"html",data:b}).done(function(a){k=arguments;c.html(e?d("<div>").append(d.parseHTML(a)).find(e):a)}).complete(f&&function(a,b){c.each(f,k||[a.responseText,b,a])});return this};d.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), +function(a,b){d.fn[b]=function(a){return this.on(b,a)}});d.each(["get","post"],function(a,b){d[b]=function(a,f,e,l){d.isFunction(f)&&(l=l||e,e=f,f=j);return d.ajax({url:a,type:b,dataType:l,data:f,success:e})}});d.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:U,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(ca[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":ob,text:"text/plain",html:"text/html", +xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":c.String,"text html":!0,"text json":d.parseJSON,"text xml":d.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?t(t(a,d.ajaxSettings),b):t(d.ajaxSettings,a)},ajaxPrefilter:e(nb),ajaxTransport:e(Da),ajax:function(a,b){function f(a,b,h,k){var g,s,n,z,C=b;if(2!==S){S=2;m&&clearTimeout(m); +e=j;c=k||"";A.readyState=0<a?4:0;if(h){z=i;var k=A,v,x,I,J,G=z.contents,q=z.dataTypes,Sa=z.responseFields;for(x in Sa)x in h&&(k[Sa[x]]=h[x]);for(;"*"===q[0];)q.shift(),v===j&&(v=z.mimeType||k.getResponseHeader("Content-Type"));if(v)for(x in G)if(G[x]&&G[x].test(v)){q.unshift(x);break}if(q[0]in h)I=q[0];else{for(x in h){if(!q[0]||z.converters[x+" "+q[0]]){I=x;break}J||(J=x)}I=I||J}I?(I!==q[0]&&q.unshift(I),z=h[I]):z=void 0}if(200<=a&&300>a||304===a)if(i.ifModified&&((h=A.getResponseHeader("Last-Modified"))&& +(d.lastModified[l]=h),(h=A.getResponseHeader("etag"))&&(d.etag[l]=h)),304===a)g=!0,C="notmodified";else{a:{s=i;n=z;var w,y,C={};v=0;x=s.dataTypes.slice();I=x[0];s.dataFilter&&(n=s.dataFilter(n,s.dataType));if(x[1])for(w in s.converters)C[w.toLowerCase()]=s.converters[w];for(;h=x[++v];)if("*"!==h){if("*"!==I&&I!==h){w=C[I+" "+h]||C["* "+h];if(!w)for(y in C)if(g=y.split(" "),g[1]===h&&(w=C[I+" "+g[0]]||C["* "+g[0]])){!0===w?w=C[y]:!0!==C[y]&&(h=g[0],x.splice(v--,0,h));break}if(!0!==w)if(w&&s["throws"])n= +w(n);else try{n=w(n)}catch(ea){g={state:"parsererror",error:w?ea:"No conversion from "+I+" to "+h};break a}}I=h}g={state:"success",data:n}}C=g.state;s=g.data;n=g.error;g=!n}else if(n=C,a||!C)C="error",0>a&&(a=0);A.status=a;A.statusText=(b||C)+"";g?R.resolveWith(B,[s,C,A]):R.rejectWith(B,[A,C,n]);A.statusCode(r);r=j;t&&u.trigger(g?"ajaxSuccess":"ajaxError",[A,i,g?s:n]);Z.fireWith(B,[A,C]);t&&(u.trigger("ajaxComplete",[A,i]),--d.active||d.event.trigger("ajaxStop"))}}"object"===typeof a&&(b=a,a=j);var b= +b||{},e,l,c,g,m,s,t,n,i=d.ajaxSetup({},b),B=i.context||i,u=i.context&&(B.nodeType||B.jquery)?d(B):d.event,R=d.Deferred(),Z=d.Callbacks("once memory"),r=i.statusCode||{},z={},C={},S=0,v="canceled",A={readyState:0,getResponseHeader:function(a){var b;if(2===S){if(!g)for(g={};b=cc.exec(c);)g[b[1].toLowerCase()]=b[2];b=g[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===S?c:null},setRequestHeader:function(a,b){var d=a.toLowerCase();S||(a=C[d]=C[d]||a,z[a]=b);return this}, +overrideMimeType:function(a){S||(i.mimeType=a);return this},statusCode:function(a){var b;if(a)if(2>S)for(b in a)r[b]=[r[b],a[b]];else A.always(a[A.status]);return this},abort:function(a){a=a||v;e&&e.abort(a);f(0,a);return this}};R.promise(A).complete=Z.add;A.success=A.done;A.error=A.fail;i.url=((a||i.url||U)+"").replace(bc,"").replace(ec,ca[1]+"//");i.type=b.method||b.type||i.method||i.type;i.dataTypes=d.trim(i.dataType||"*").toLowerCase().match(aa)||[""];null==i.crossDomain&&(s=lb.exec(i.url.toLowerCase()), +i.crossDomain=!(!s||!(s[1]!==ca[1]||s[2]!==ca[2]||(s[3]||("http:"===s[1]?80:443))!=(ca[3]||("http:"===ca[1]?80:443)))));i.data&&i.processData&&"string"!==typeof i.data&&(i.data=d.param(i.data,i.traditional));k(nb,i,b,A);if(2===S)return A;(t=i.global)&&0===d.active++&&d.event.trigger("ajaxStart");i.type=i.type.toUpperCase();i.hasContent=!dc.test(i.type);l=i.url;i.hasContent||(i.data&&(l=i.url+=(Oa.test(l)?"&":"?")+i.data,delete i.data),!1===i.cache&&(i.url=kb.test(l)?l.replace(kb,"$1_="+Na++):l+(Oa.test(l)? +"&":"?")+"_="+Na++));i.ifModified&&(d.lastModified[l]&&A.setRequestHeader("If-Modified-Since",d.lastModified[l]),d.etag[l]&&A.setRequestHeader("If-None-Match",d.etag[l]));(i.data&&i.hasContent&&!1!==i.contentType||b.contentType)&&A.setRequestHeader("Content-Type",i.contentType);A.setRequestHeader("Accept",i.dataTypes[0]&&i.accepts[i.dataTypes[0]]?i.accepts[i.dataTypes[0]]+("*"!==i.dataTypes[0]?", "+ob+"; q=0.01":""):i.accepts["*"]);for(n in i.headers)A.setRequestHeader(n,i.headers[n]);if(i.beforeSend&& +(!1===i.beforeSend.call(B,A,i)||2===S))return A.abort();v="abort";for(n in{success:1,error:1,complete:1})A[n](i[n]);if(e=k(Da,i,b,A)){A.readyState=1;t&&u.trigger("ajaxSend",[A,i]);i.async&&0<i.timeout&&(m=setTimeout(function(){A.abort("timeout")},i.timeout));try{S=1,e.send(z,f)}catch(x){if(2>S)f(-1,x);else throw x;}}else f(-1,"No Transport");return A},getScript:function(a,b){return d.get(a,j,b,"script")},getJSON:function(a,b,f){return d.get(a,b,f,"json")}});d.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"}, +contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){d.globalEval(a);return a}}});d.ajaxPrefilter("script",function(a){a.cache===j&&(a.cache=!1);a.crossDomain&&(a.type="GET",a.global=!1)});d.ajaxTransport("script",function(a){if(a.crossDomain){var b,f=v.head||d("head")[0]||v.documentElement;return{send:function(d,e){b=v.createElement("script");b.async=!0;a.scriptCharset&&(b.charset=a.scriptCharset);b.src=a.url;b.onload=b.onreadystatechange=function(a,d){if(d||!b.readyState|| +/loaded|complete/.test(b.readyState))b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,d||e(200,"success")};f.insertBefore(b,f.firstChild)},abort:function(){if(b)b.onload(j,!0)}}}});var pb=[],Pa=/(=)\?(?=&|$)|\?\?/;d.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=pb.pop()||d.expando+"_"+Na++;this[a]=!0;return a}});d.ajaxPrefilter("json jsonp",function(a,b,f){var e,l,k,g=!1!==a.jsonp&&(Pa.test(a.url)?"url":"string"===typeof a.data&&!(a.contentType||"").indexOf("application/x-www-form-urlencoded")&& +Pa.test(a.data)&&"data");if(g||"jsonp"===a.dataTypes[0])return e=a.jsonpCallback=d.isFunction(a.jsonpCallback)?a.jsonpCallback():a.jsonpCallback,g?a[g]=a[g].replace(Pa,"$1"+e):!1!==a.jsonp&&(a.url+=(Oa.test(a.url)?"&":"?")+a.jsonp+"="+e),a.converters["script json"]=function(){k||d.error(e+" was not called");return k[0]},a.dataTypes[0]="json",l=c[e],c[e]=function(){k=arguments},f.always(function(){c[e]=l;a[e]&&(a.jsonpCallback=b.jsonpCallback,pb.push(e));k&&d.isFunction(l)&&l(k[0]);k=l=j}),"script"}); +var qa,sa,fc=0,Qa=c.ActiveXObject&&function(){for(var a in qa)qa[a](j,!0)};d.ajaxSettings.xhr=c.ActiveXObject?function(){var a;if(!(a=!this.isLocal&&R()))a:{try{a=new c.ActiveXObject("Microsoft.XMLHTTP");break a}catch(b){}a=void 0}return a}:R;sa=d.ajaxSettings.xhr();d.support.cors=!!sa&&"withCredentials"in sa;(sa=d.support.ajax=!!sa)&&d.ajaxTransport(function(a){if(!a.crossDomain||d.support.cors){var b;return{send:function(f,e){var l,k,g=a.xhr();a.username?g.open(a.type,a.url,a.async,a.username,a.password): +g.open(a.type,a.url,a.async);if(a.xhrFields)for(k in a.xhrFields)g[k]=a.xhrFields[k];a.mimeType&&g.overrideMimeType&&g.overrideMimeType(a.mimeType);!a.crossDomain&&!f["X-Requested-With"]&&(f["X-Requested-With"]="XMLHttpRequest");try{for(k in f)g.setRequestHeader(k,f[k])}catch(m){}g.send(a.hasContent&&a.data||null);b=function(f,h){var k,c,m,s,n;try{if(b&&(h||4===g.readyState))if(b=j,l&&(g.onreadystatechange=d.noop,Qa&&delete qa[l]),h)4!==g.readyState&&g.abort();else{s={};k=g.status;n=g.responseXML; +m=g.getAllResponseHeaders();n&&n.documentElement&&(s.xml=n);"string"===typeof g.responseText&&(s.text=g.responseText);try{c=g.statusText}catch(t){c=""}!k&&a.isLocal&&!a.crossDomain?k=s.text?200:404:1223===k&&(k=204)}}catch(i){h||e(-1,i)}s&&e(k,c,s,m)};a.async?4===g.readyState?setTimeout(b):(l=++fc,Qa&&(qa||(qa={},d(c).unload(Qa)),qa[l]=b),g.onreadystatechange=b):b()},abort:function(){b&&b(j,!0)}}}});var ka,za,gc=/^(?:toggle|show|hide)$/,hc=RegExp("^(?:([+-])=|)("+wa+")([a-z%]*)$","i"),ic=/queueHooks$/, +ua=[function(a,b,f){var e,l,k,c,g,m,s=this,n=a.style,t={},i=[],j=a.nodeType&&H(a);f.queue||(g=d._queueHooks(a,"fx"),null==g.unqueued&&(g.unqueued=0,m=g.empty.fire,g.empty.fire=function(){g.unqueued||m()}),g.unqueued++,s.always(function(){s.always(function(){g.unqueued--;d.queue(a,"fx").length||g.empty.fire()})}));if(1===a.nodeType&&("height"in b||"width"in b))f.overflow=[n.overflow,n.overflowX,n.overflowY],"inline"===d.css(a,"display")&&"none"===d.css(a,"float")&&(!d.support.inlineBlockNeedsLayout|| +"inline"===P(a.nodeName)?n.display="inline-block":n.zoom=1);f.overflow&&(n.overflow="hidden",d.support.shrinkWrapBlocks||s.done(function(){n.overflow=f.overflow[0];n.overflowX=f.overflow[1];n.overflowY=f.overflow[2]}));for(e in b)k=b[e],gc.exec(k)&&(delete b[e],l=l||"toggle"===k,k!==(j?"hide":"show")&&i.push(e));if(b=i.length){k=d._data(a,"fxshow")||d._data(a,"fxshow",{});"hidden"in k&&(j=k.hidden);l&&(k.hidden=!j);j?d(a).show():s.done(function(){d(a).hide()});s.done(function(){var b;d._removeData(a, +"fxshow");for(b in t)d.style(a,b,t[b])});for(e=0;e<b;e++)l=i[e],c=s.createTween(l,j?k[l]:0),t[l]=k[l]||d.style(a,l),l in k||(k[l]=c.start,j&&(c.end=c.start,c.start="width"===l||"height"===l?1:0))}}],fa={"*":[function(a,b){var f,e,l=this.createTween(a,b),k=hc.exec(b),c=l.cur(),g=+c||0,m=1,s=20;if(k){f=+k[2];e=k[3]||(d.cssNumber[a]?"":"px");if("px"!==e&&g){g=d.css(l.elem,a,!0)||f||1;do m=m||".5",g/=m,d.style(l.elem,a,g+e);while(m!==(m=l.cur()/c)&&1!==m&&--s)}l.unit=e;l.start=g;l.end=k[1]?g+(k[1]+1)* +f:f}return l}]};d.Animation=d.extend(Q,{tweener:function(a,b){d.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var f,e=0,l=a.length;e<l;e++)f=a[e],fa[f]=fa[f]||[],fa[f].unshift(b)},prefilter:function(a,b){b?ua.unshift(a):ua.push(a)}});d.Tween=l;l.prototype={constructor:l,init:function(a,b,f,e,l,k){this.elem=a;this.prop=f;this.easing=l||"swing";this.options=b;this.start=this.now=this.cur();this.end=e;this.unit=k||(d.cssNumber[f]?"":"px")},cur:function(){var a=l.propHooks[this.prop];return a&&a.get? +a.get(this):l.propHooks._default.get(this)},run:function(a){var b,f=l.propHooks[this.prop];this.pos=this.options.duration?b=d.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):b=a;this.now=(this.end-this.start)*b+this.start;this.options.step&&this.options.step.call(this.elem,this.now,this);f&&f.set?f.set(this):l.propHooks._default.set(this);return this}};l.prototype.init.prototype=l.prototype;l.propHooks={_default:{get:function(a){if(null!=a.elem[a.prop]&&(!a.elem.style||null== +a.elem.style[a.prop]))return a.elem[a.prop];a=d.css(a.elem,a.prop,"auto");return!a||"auto"===a?0:a},set:function(a){if(d.fx.step[a.prop])d.fx.step[a.prop](a);else a.elem.style&&(null!=a.elem.style[d.cssProps[a.prop]]||d.cssHooks[a.prop])?d.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}};l.propHooks.scrollTop=l.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}};d.each(["toggle","show","hide"],function(a,b){var f=d.fn[b];d.fn[b]=function(a,d, +e){return null==a||"boolean"===typeof a?f.apply(this,arguments):this.animate(s(b,!0),a,d,e)}});d.fn.extend({fadeTo:function(a,b,d,f){return this.filter(H).css("opacity",0).show().end().animate({opacity:b},a,d,f)},animate:function(a,b,f,e){var l=d.isEmptyObject(a),k=d.speed(b,f,e),c=function(){var b=Q(this,d.extend({},a),k);c.finish=function(){b.stop(!0)};(l||d._data(this,"finish"))&&b.stop(!0)};c.finish=c;return l||!1===k.queue?this.each(c):this.queue(k.queue,c)},stop:function(a,b,f){var e=function(a){var b= +a.stop;delete a.stop;b(f)};"string"!==typeof a&&(f=b,b=a,a=j);b&&!1!==a&&this.queue(a||"fx",[]);return this.each(function(){var b=!0,l=null!=a&&a+"queueHooks",k=d.timers,c=d._data(this);if(l)c[l]&&c[l].stop&&e(c[l]);else for(l in c)c[l]&&c[l].stop&&ic.test(l)&&e(c[l]);for(l=k.length;l--;)if(k[l].elem===this&&(null==a||k[l].queue===a))k[l].anim.stop(f),b=!1,k.splice(l,1);(b||!f)&&d.dequeue(this,a)})},finish:function(a){!1!==a&&(a=a||"fx");return this.each(function(){var b,f=d._data(this),e=f[a+"queue"]; +b=f[a+"queueHooks"];var l=d.timers,k=e?e.length:0;f.finish=!0;d.queue(this,a,[]);b&&b.cur&&b.cur.finish&&b.cur.finish.call(this);for(b=l.length;b--;)l[b].elem===this&&l[b].queue===a&&(l[b].anim.stop(!0),l.splice(b,1));for(b=0;b<k;b++)e[b]&&e[b].finish&&e[b].finish.call(this);delete f.finish})}});d.each({slideDown:s("show"),slideUp:s("hide"),slideToggle:s("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){d.fn[a]=function(a,d,f){return this.animate(b, +a,d,f)}});d.speed=function(a,b,f){var e=a&&"object"===typeof a?d.extend({},a):{complete:f||!f&&b||d.isFunction(a)&&a,duration:a,easing:f&&b||b&&!d.isFunction(b)&&b};e.duration=d.fx.off?0:"number"===typeof e.duration?e.duration:e.duration in d.fx.speeds?d.fx.speeds[e.duration]:d.fx.speeds._default;if(null==e.queue||!0===e.queue)e.queue="fx";e.old=e.complete;e.complete=function(){d.isFunction(e.old)&&e.old.call(this);e.queue&&d.dequeue(this,e.queue)};return e};d.easing={linear:function(a){return a}, +swing:function(a){return 0.5-Math.cos(a*Math.PI)/2}};d.timers=[];d.fx=l.prototype.init;d.fx.tick=function(){var a,b=d.timers,f=0;for(ka=d.now();f<b.length;f++)a=b[f],!a()&&b[f]===a&&b.splice(f--,1);b.length||d.fx.stop();ka=j};d.fx.timer=function(a){a()&&d.timers.push(a)&&d.fx.start()};d.fx.interval=13;d.fx.start=function(){za||(za=setInterval(d.fx.tick,d.fx.interval))};d.fx.stop=function(){clearInterval(za);za=null};d.fx.speeds={slow:600,fast:200,_default:400};d.fx.step={};d.expr&&d.expr.filters&& +(d.expr.filters.animated=function(a){return d.grep(d.timers,function(b){return a===b.elem}).length});d.fn.offset=function(a){if(arguments.length)return a===j?this:this.each(function(b){d.offset.setOffset(this,a,b)});var b,f,e={top:0,left:0},l=(f=this[0])&&f.ownerDocument;if(l){b=l.documentElement;if(!d.contains(b,f))return e;"undefined"!==typeof f.getBoundingClientRect&&(e=f.getBoundingClientRect());f=B(l);return{top:e.top+(f.pageYOffset||b.scrollTop)-(b.clientTop||0),left:e.left+(f.pageXOffset|| +b.scrollLeft)-(b.clientLeft||0)}}};d.offset={setOffset:function(a,b,f){var e=d.css(a,"position");"static"===e&&(a.style.position="relative");var l=d(a),k=l.offset(),c=d.css(a,"top"),g=d.css(a,"left"),m={},s={};("absolute"===e||"fixed"===e)&&-1<d.inArray("auto",[c,g])?(s=l.position(),e=s.top,g=s.left):(e=parseFloat(c)||0,g=parseFloat(g)||0);d.isFunction(b)&&(b=b.call(a,f,k));null!=b.top&&(m.top=b.top-k.top+e);null!=b.left&&(m.left=b.left-k.left+g);"using"in b?b.using.call(a,m):l.css(m)}};d.fn.extend({position:function(){if(this[0]){var a, +b,f={top:0,left:0},e=this[0];"fixed"===d.css(e,"position")?b=e.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),d.nodeName(a[0],"html")||(f=a.offset()),f.top+=d.css(a[0],"borderTopWidth",!0),f.left+=d.css(a[0],"borderLeftWidth",!0));return{top:b.top-f.top-d.css(e,"marginTop",!0),left:b.left-f.left-d.css(e,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||v.documentElement;a&&!d.nodeName(a,"html")&&"static"===d.css(a,"position");)a=a.offsetParent; +return a||v.documentElement})}});d.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var f=/Y/.test(b);d.fn[a]=function(e){return d.access(this,function(a,e,l){var k=B(a);if(l===j)return k?b in k?k[b]:k.document.documentElement[e]:a[e];k?k.scrollTo(!f?l:d(k).scrollLeft(),f?l:d(k).scrollTop()):a[e]=l},a,e,arguments.length,null)}});d.each({Height:"height",Width:"width"},function(a,b){d.each({padding:"inner"+a,content:b,"":"outer"+a},function(f,e){d.fn[e]=function(e,l){var k=arguments.length&& +(f||"boolean"!==typeof e),c=f||(!0===e||!0===l?"margin":"border");return d.access(this,function(b,f,e){if(d.isWindow(b))return b.document.documentElement["client"+a];return 9===b.nodeType?(f=b.documentElement,Math.max(b.body["scroll"+a],f["scroll"+a],b.body["offset"+a],f["offset"+a],f["client"+a])):e===j?d.css(b,f,c):d.style(b,f,e,c)},b,k?e:j,k,null)}})});c.jQuery=c.$=d;"function"===typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return d})})(window); +(function(c,j){function i(g,n){var i,j;i=g.nodeName.toLowerCase();if("area"===i){i=g.parentNode;j=i.name;if(!g.href||!j||"map"!==i.nodeName.toLowerCase())return!1;i=c("img[usemap=#"+j+"]")[0];return!!i&&r(i)}return(/input|select|textarea|button|object/.test(i)?!g.disabled:"a"===i?g.href||n:n)&&r(g)}function r(g){return c.expr.filters.visible(g)&&!c(g).parents().addBack().filter(function(){return"hidden"===c.css(this,"visibility")}).length}var q=0,u=/^ui-id-\d+$/;c.ui=c.ui||{};c.ui.version||(c.extend(c.ui, +{version:"1.10.0",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),c.fn.extend({_focus:c.fn.focus,focus:function(g,n){return"number"===typeof g?this.each(function(){var i=this;setTimeout(function(){c(i).focus();n&&n.call(i)},g)}):this._focus.apply(this,arguments)},scrollParent:function(){var g; +g=c.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.css(this,"position"))&&/(auto|scroll)/.test(c.css(this,"overflow")+c.css(this,"overflow-y")+c.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.css(this,"overflow")+c.css(this,"overflow-y")+c.css(this,"overflow-x"))}).eq(0);return/fixed/.test(this.css("position"))||!g.length?c(document): +g},zIndex:function(g){if(g!==j)return this.css("zIndex",g);if(this.length)for(var g=c(this[0]),n;g.length&&g[0]!==document;){n=g.css("position");if("absolute"===n||"relative"===n||"fixed"===n)if(n=parseInt(g.css("zIndex"),10),!isNaN(n)&&0!==n)return n;g=g.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++q)})},removeUniqueId:function(){return this.each(function(){u.test(this.id)&&c(this).removeAttr("id")})}}),c.extend(c.expr[":"],{data:c.expr.createPseudo? +c.expr.createPseudo(function(g){return function(n){return!!c.data(n,g)}}):function(g,n,i){return!!c.data(g,i[3])},focusable:function(g){return i(g,!isNaN(c.attr(g,"tabindex")))},tabbable:function(g){var n=c.attr(g,"tabindex"),j=isNaN(n);return(j||0<=n)&&i(g,!j)}}),c("<a>").outerWidth(1).jquery||c.each(["Width","Height"],function(g,n){function i(g,n,j,r){c.each(u,function(){n-=parseFloat(c.css(g,"padding"+this))||0;j&&(n-=parseFloat(c.css(g,"border"+this+"Width"))||0);r&&(n-=parseFloat(c.css(g,"margin"+ +this))||0)});return n}var u="Width"===n?["Left","Right"]:["Top","Bottom"],r=n.toLowerCase(),q={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight,outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+n]=function(g){return g===j?q["inner"+n].call(this):this.each(function(){c(this).css(r,i(this,g)+"px")})};c.fn["outer"+n]=function(g,j){return"number"!==typeof g?q["outer"+n].call(this,g):this.each(function(){c(this).css(r,i(this,g,!0,j)+"px")})}}),c.fn.addBack||(c.fn.addBack=function(c){return this.add(null== +c?this.prevObject:this.prevObject.filter(c))}),c("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(c.fn.removeData=function(g){return function(n){return arguments.length?g.call(this,c.camelCase(n)):g.call(this)}}(c.fn.removeData)),c.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),c.support.selectstart="onselectstart"in document.createElement("div"),c.fn.extend({disableSelection:function(){return this.bind((c.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection", +function(c){c.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),c.extend(c.ui,{plugin:{add:function(g,n,i){var j,g=c.ui[g].prototype;for(j in i)g.plugins[j]=g.plugins[j]||[],g.plugins[j].push([n,i[j]])},call:function(c,n,i){var j=c.plugins[n];if(j&&c.element[0].parentNode&&11!==c.element[0].parentNode.nodeType)for(n=0;n<j.length;n++)c.options[j[n][0]]&&j[n][1].apply(c.element,i)}},hasScroll:function(g,n){if("hidden"===c(g).css("overflow"))return!1;var i= +n&&"left"===n?"scrollLeft":"scrollTop",j=!1;if(0<g[i])return!0;g[i]=1;j=0<g[i];g[i]=0;return j}}))})(jQuery); +(function(c,j){var i=0,r=Array.prototype.slice,q=c.cleanData;c.cleanData=function(i){for(var g=0,n;null!=(n=i[g]);g++)try{c(n).triggerHandler("remove")}catch(j){}q(i)};c.widget=function(i,g,n){var j,r,q,E,K={},F=i.split(".")[0],i=i.split(".")[1];j=F+"-"+i;n||(n=g,g=c.Widget);c.expr[":"][j.toLowerCase()]=function(g){return!!c.data(g,j)};c[F]=c[F]||{};r=c[F][i];q=c[F][i]=function(c,g){if(!this._createWidget)return new q(c,g);arguments.length&&this._createWidget(c,g)};c.extend(q,r,{version:n.version, +_proto:c.extend({},n),_childConstructors:[]});E=new g;E.options=c.widget.extend({},E.options);c.each(n,function(i,n){K[i]=c.isFunction(n)?function(){var c=function(){return g.prototype[i].apply(this,arguments)},j=function(c){return g.prototype[i].apply(this,c)};return function(){var g=this._super,i=this._superApply,u;this._super=c;this._superApply=j;u=n.apply(this,arguments);this._super=g;this._superApply=i;return u}}():n});q.prototype=c.widget.extend(E,{widgetEventPrefix:r?E.widgetEventPrefix:i}, +K,{constructor:q,namespace:F,widgetName:i,widgetFullName:j});r?(c.each(r._childConstructors,function(g,i){var n=i.prototype;c.widget(n.namespace+"."+n.widgetName,q,i._proto)}),delete r._childConstructors):g._childConstructors.push(q);c.widget.bridge(i,q)};c.widget.extend=function(i){for(var g=r.call(arguments,1),n=0,z=g.length,q,y;n<z;n++)for(q in g[n])y=g[n][q],g[n].hasOwnProperty(q)&&y!==j&&(i[q]=c.isPlainObject(y)?c.isPlainObject(i[q])?c.widget.extend({},i[q],y):c.widget.extend({},y):y);return i}; +c.widget.bridge=function(i,g){var n=g.prototype.widgetFullName||i;c.fn[i]=function(q){var J="string"===typeof q,y=r.call(arguments,1),E=this,q=!J&&y.length?c.widget.extend.apply(null,[q].concat(y)):q;J?this.each(function(){var g,r=c.data(this,n);if(!r)return c.error("cannot call methods on "+i+" prior to initialization; attempted to call method '"+q+"'");if(!c.isFunction(r[q])||"_"===q.charAt(0))return c.error("no such method '"+q+"' for "+i+" widget instance");g=r[q].apply(r,y);if(g!==r&&g!==j)return E= +g&&g.jquery?E.pushStack(g.get()):g,!1}):this.each(function(){var i=c.data(this,n);i?i.option(q||{})._init():c.data(this,n,new g(q,this))});return E}};c.Widget=function(){};c.Widget._childConstructors=[];c.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(j,g){g=c(g||this.defaultElement||this)[0];this.element=c(g);this.uuid=i++;this.eventNamespace="."+this.widgetName+this.uuid;this.options=c.widget.extend({},this.options, +this._getCreateOptions(),j);this.bindings=c();this.hoverable=c();this.focusable=c();g!==this&&(c.data(g,this.widgetFullName,this),this._on(!0,this.element,{remove:function(c){c.target===g&&this.destroy()}}),this.document=c(g.style?g.ownerDocument:g.document||g),this.window=c(this.document[0].defaultView||this.document[0].parentWindow));this._create();this._trigger("create",null,this._getCreateEventData());this._init()},_getCreateOptions:c.noop,_getCreateEventData:c.noop,_create:c.noop,_init:c.noop, +destroy:function(){this._destroy();this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(c.camelCase(this.widgetFullName));this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled");this.bindings.unbind(this.eventNamespace);this.hoverable.removeClass("ui-state-hover");this.focusable.removeClass("ui-state-focus")},_destroy:c.noop,widget:function(){return this.element}, +option:function(i,g){var n=i,r,q,y;if(0===arguments.length)return c.widget.extend({},this.options);if("string"===typeof i)if(n={},r=i.split("."),i=r.shift(),r.length){q=n[i]=c.widget.extend({},this.options[i]);for(y=0;y<r.length-1;y++)q[r[y]]=q[r[y]]||{},q=q[r[y]];i=r.pop();if(g===j)return q[i]===j?null:q[i];q[i]=g}else{if(g===j)return this.options[i]===j?null:this.options[i];n[i]=g}this._setOptions(n);return this},_setOptions:function(c){for(var g in c)this._setOption(g,c[g]);return this},_setOption:function(c, +g){this.options[c]=g;"disabled"===c&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!g).attr("aria-disabled",g),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"));return this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,g,n){var j,r=this;"boolean"!==typeof i&&(n=g,g=i,i=!1);n?(g=j=c(g),this.bindings=this.bindings.add(g)):(n=g,g=this.element,j= +this.widget());c.each(n,function(n,q){function K(){return!i&&(!0===r.options.disabled||c(this).hasClass("ui-state-disabled"))?void 0:("string"===typeof q?r[q]:q).apply(r,arguments)}"string"!==typeof q&&(K.guid=q.guid=q.guid||K.guid||c.guid++);var F=n.match(/^(\w+)\s*(.*)$/),T=F[1]+r.eventNamespace;(F=F[2])?j.delegate(F,T,K):g.bind(T,K)})},_off:function(c,g){g=(g||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace;c.unbind(g).undelegate(g)},_delay:function(c,g){var i=this;return setTimeout(function(){return("string"=== +typeof c?i[c]:c).apply(i,arguments)},g||0)},_hoverable:function(i){this.hoverable=this.hoverable.add(i);this._on(i,{mouseenter:function(g){c(g.currentTarget).addClass("ui-state-hover")},mouseleave:function(g){c(g.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(i){this.focusable=this.focusable.add(i);this._on(i,{focusin:function(g){c(g.currentTarget).addClass("ui-state-focus")},focusout:function(g){c(g.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(i,g,n){var j, +r=this.options[i],n=n||{},g=c.Event(g);g.type=(i===this.widgetEventPrefix?i:this.widgetEventPrefix+i).toLowerCase();g.target=this.element[0];if(i=g.originalEvent)for(j in i)j in g||(g[j]=i[j]);this.element.trigger(g,n);return!(c.isFunction(r)&&!1===r.apply(this.element[0],[g].concat(n))||g.isDefaultPrevented())}};c.each({show:"fadeIn",hide:"fadeOut"},function(i,g){c.Widget.prototype["_"+i]=function(n,j,r){"string"===typeof j&&(j={effect:j});var q,E=!j?i:!0===j||"number"===typeof j?g:j.effect||g,j= +j||{};"number"===typeof j&&(j={duration:j});q=!c.isEmptyObject(j);j.complete=r;j.delay&&n.delay(j.delay);if(q&&c.effects&&c.effects.effect[E])n[i](j);else if(E!==i&&n[E])n[E](j.duration,j.easing,r);else n.queue(function(g){c(this)[i]();r&&r.call(n[0]);g()})}})})(jQuery); +(function(c,j){function i(c,g,i){return[parseInt(c[0],10)*(F.test(c[0])?g/100:1),parseInt(c[1],10)*(F.test(c[1])?i/100:1)]}function r(g,i){return parseInt(c.css(g,i),10)||0}function q(g){var i=g[0];return 9===i.nodeType?{width:g.width(),height:g.height(),offset:{top:0,left:0}}:c.isWindow(i)?{width:g.width(),height:g.height(),offset:{top:g.scrollTop(),left:g.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:g.outerWidth(),height:g.outerHeight(),offset:g.offset()}} +c.ui=c.ui||{};var u,g=Math.max,n=Math.abs,z=Math.round,J=/left|center|right/,y=/top|center|bottom/,E=/[\+\-]\d+%?/,K=/^\w+/,F=/%$/,T=c.fn.position;c.position={scrollbarWidth:function(){if(u!==j)return u;var g,i,n=c("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>");i=n.children()[0];c("body").append(n);g=i.offsetWidth;n.css("overflow","scroll");i=i.offsetWidth;g===i&&(i=n[0].clientWidth);n.remove();return u=g-i},getScrollInfo:function(g){var i= +g.isWindow?"":g.element.css("overflow-x"),n=g.isWindow?"":g.element.css("overflow-y"),n="scroll"===n||"auto"===n&&g.height<g.element[0].scrollHeight;return{width:"scroll"===i||"auto"===i&&g.width<g.element[0].scrollWidth?c.position.scrollbarWidth():0,height:n?c.position.scrollbarWidth():0}},getWithinInfo:function(g){var g=c(g||window),i=c.isWindow(g[0]);return{element:g,isWindow:i,offset:g.offset()||{left:0,top:0},scrollLeft:g.scrollLeft(),scrollTop:g.scrollTop(),width:i?g.width():g.outerWidth(), +height:i?g.height():g.outerHeight()}}};c.fn.position=function(j){if(!j||!j.of)return T.apply(this,arguments);var j=c.extend({},j),u,x,G,O,H,m,w=c(j.of),F=c.position.getWithinInfo(j.within),W=c.position.getScrollInfo(F),P=(j.collision||"flip").split(" "),$={};m=q(w);w[0].preventDefault&&(j.at="left top");x=m.width;G=m.height;O=m.offset;H=c.extend({},O);c.each(["my","at"],function(){var c=(j[this]||"").split(" "),e,k;1===c.length&&(c=J.test(c[0])?c.concat(["center"]):y.test(c[0])?["center"].concat(c): +["center","center"]);c[0]=J.test(c[0])?c[0]:"center";c[1]=y.test(c[1])?c[1]:"center";e=E.exec(c[0]);k=E.exec(c[1]);$[this]=[e?e[0]:0,k?k[0]:0];j[this]=[K.exec(c[0])[0],K.exec(c[1])[0]]});1===P.length&&(P[1]=P[0]);"right"===j.at[0]?H.left+=x:"center"===j.at[0]&&(H.left+=x/2);"bottom"===j.at[1]?H.top+=G:"center"===j.at[1]&&(H.top+=G/2);u=i($.at,x,G);H.left+=u[0];H.top+=u[1];return this.each(function(){var m,e,k=c(this),t=k.outerWidth(),R=k.outerHeight(),C=r(this,"marginLeft"),q=r(this,"marginTop"), +Q=t+C+r(this,"marginRight")+W.width,f=R+q+r(this,"marginBottom")+W.height,l=c.extend({},H),s=i($.my,k.outerWidth(),k.outerHeight());"right"===j.my[0]?l.left-=t:"center"===j.my[0]&&(l.left-=t/2);"bottom"===j.my[1]?l.top-=R:"center"===j.my[1]&&(l.top-=R/2);l.left+=s[0];l.top+=s[1];c.support.offsetFractions||(l.left=z(l.left),l.top=z(l.top));m={marginLeft:C,marginTop:q};c.each(["left","top"],function(e,g){if(c.ui.position[P[e]])c.ui.position[P[e]][g](l,{targetWidth:x,targetHeight:G,elemWidth:t,elemHeight:R, +collisionPosition:m,collisionWidth:Q,collisionHeight:f,offset:[u[0]+s[0],u[1]+s[1]],my:j.my,at:j.at,within:F,elem:k})});j.using&&(e=function(f){var e=O.left-l.left,c=e+x-t,i=O.top-l.top,m=i+G-R,s={target:{element:w,left:O.left,top:O.top,width:x,height:G},element:{element:k,left:l.left,top:l.top,width:t,height:R},horizontal:0>c?"left":0<e?"right":"center",vertical:0>m?"top":0<i?"bottom":"middle"};x<t&&n(e+c)<x&&(s.horizontal="center");G<R&&n(i+m)<G&&(s.vertical="middle");s.important=g(n(e),n(c))>g(n(i), +n(m))?"horizontal":"vertical";j.using.call(this,f,s)});k.offset(c.extend(l,{using:e}))})};c.ui.position={fit:{left:function(c,i){var j=i.within,n=j.isWindow?j.scrollLeft:j.offset.left,r=j.width,q=c.left-i.collisionPosition.marginLeft,j=n-q,m=q+i.collisionWidth-r-n;i.collisionWidth>r?0<j&&0>=m?(n=c.left+j+i.collisionWidth-r-n,c.left+=j-n):c.left=0<m&&0>=j?n:j>m?n+r-i.collisionWidth:n:c.left=0<j?c.left+j:0<m?c.left-m:g(c.left-q,c.left)},top:function(c,i){var j=i.within,n=j.isWindow?j.scrollTop:j.offset.top, +r=i.within.height,q=c.top-i.collisionPosition.marginTop,j=n-q,m=q+i.collisionHeight-r-n;i.collisionHeight>r?0<j&&0>=m?(n=c.top+j+i.collisionHeight-r-n,c.top+=j-n):c.top=0<m&&0>=j?n:j>m?n+r-i.collisionHeight:n:c.top=0<j?c.top+j:0<m?c.top-m:g(c.top-q,c.top)}},flip:{left:function(c,g){var i=g.within,j=i.offset.left+i.scrollLeft,r=i.width,q=i.isWindow?i.scrollLeft:i.offset.left,m=c.left-g.collisionPosition.marginLeft,i=m-q,u=m+g.collisionWidth-r-q,m="left"===g.my[0]?-g.elemWidth:"right"===g.my[0]?g.elemWidth: +0,z="left"===g.at[0]?g.targetWidth:"right"===g.at[0]?-g.targetWidth:0,y=-2*g.offset[0];if(0>i){if(j=c.left+m+z+y+g.collisionWidth-r-j,0>j||j<n(i))c.left+=m+z+y}else if(0<u&&(j=c.left-g.collisionPosition.marginLeft+m+z+y-q,0<j||n(j)<u))c.left+=m+z+y},top:function(c,g){var i=g.within,j=i.offset.top+i.scrollTop,r=i.height,q=i.isWindow?i.scrollTop:i.offset.top,m=c.top-g.collisionPosition.marginTop,i=m-q,u=m+g.collisionHeight-r-q,m="top"===g.my[1]?-g.elemHeight:"bottom"===g.my[1]?g.elemHeight:0,z="top"=== +g.at[1]?g.targetHeight:"bottom"===g.at[1]?-g.targetHeight:0,y=-2*g.offset[1];if(0>i){if(j=c.top+m+z+y+g.collisionHeight-r-j,c.top+m+z+y>i&&(0>j||j<n(i)))c.top+=m+z+y}else if(0<u&&(j=c.top-g.collisionPosition.marginTop+m+z+y-q,c.top+m+z+y>u&&(0<j||n(j)<u)))c.top+=m+z+y}},flipfit:{left:function(){c.ui.position.flip.left.apply(this,arguments);c.ui.position.fit.left.apply(this,arguments)},top:function(){c.ui.position.flip.top.apply(this,arguments);c.ui.position.fit.top.apply(this,arguments)}}};(function(){var g, +i,j,n,r=document.getElementsByTagName("body")[0];j=document.createElement("div");g=document.createElement(r?"div":"body");i={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"};r&&c.extend(i,{position:"absolute",left:"-1000px",top:"-1000px"});for(n in i)g.style[n]=i[n];g.appendChild(j);i=r||document.documentElement;i.insertBefore(g,i.firstChild);j.style.cssText="position: absolute; left: 10.7432222px;";j=c(j).offset().left;c.support.offsetFractions=10<j&&11>j;g.innerHTML=""; +i.removeChild(g)})()})(jQuery); +(function(c){var j=0;c.widget("ui.autocomplete",{version:"1.10.0",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var i,j,q;this.isMultiLine=this._isMultiLine();this.valueMethod=this.element[this.element.is("input,textarea")?"val":"text"];this.isNewMenu=!0;this.element.addClass("ui-autocomplete-input").attr("autocomplete", +"off");this._on(this.element,{keydown:function(u){if(this.element.prop("readOnly"))j=q=i=!0;else{j=q=i=!1;var g=c.ui.keyCode;switch(u.keyCode){case g.PAGE_UP:i=!0;this._move("previousPage",u);break;case g.PAGE_DOWN:i=!0;this._move("nextPage",u);break;case g.UP:i=!0;this._keyEvent("previous",u);break;case g.DOWN:i=!0;this._keyEvent("next",u);break;case g.ENTER:case g.NUMPAD_ENTER:this.menu.active&&(i=!0,u.preventDefault(),this.menu.select(u));break;case g.TAB:this.menu.active&&this.menu.select(u); +break;case g.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(u),u.preventDefault());break;default:j=!0,this._searchTimeout(u)}}},keypress:function(q){if(i)i=!1,q.preventDefault();else if(!j){var g=c.ui.keyCode;switch(q.keyCode){case g.PAGE_UP:this._move("previousPage",q);break;case g.PAGE_DOWN:this._move("nextPage",q);break;case g.UP:this._keyEvent("previous",q);break;case g.DOWN:this._keyEvent("next",q)}}},input:function(c){q?(q=!1,c.preventDefault()):this._searchTimeout(c)}, +focus:function(){this.selectedItem=null;this.previous=this._value()},blur:function(c){this.cancelBlur?delete this.cancelBlur:(clearTimeout(this.searching),this.close(c),this._change(c))}});this._initSource();this.menu=c("<ul>").addClass("ui-autocomplete").appendTo(this._appendTo()).menu({input:c(),role:null}).zIndex(this.element.zIndex()+1).hide().data("ui-menu");this._on(this.menu.element,{mousedown:function(i){i.preventDefault();this.cancelBlur=!0;this._delay(function(){delete this.cancelBlur}); +var g=this.menu.element[0];c(i.target).closest(".ui-menu-item").length||this._delay(function(){var i=this;this.document.one("mousedown",function(j){j.target!==i.element[0]&&j.target!==g&&!c.contains(g,j.target)&&i.close()})})},menufocus:function(i,g){if(this.isNewMenu&&(this.isNewMenu=!1,i.originalEvent&&/^mouse/.test(i.originalEvent.type))){this.menu.blur();this.document.one("mousemove",function(){c(i.target).trigger(i.originalEvent)});return}var j=g.item.data("ui-autocomplete-item");!1!==this._trigger("focus", +i,{item:j})?i.originalEvent&&/^key/.test(i.originalEvent.type)&&this._value(j.value):this.liveRegion.text(j.value)},menuselect:function(c,g){var i=g.item.data("ui-autocomplete-item"),j=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=j,this._delay(function(){this.previous=j;this.selectedItem=i}));!1!==this._trigger("select",c,{item:i})&&this._value(i.value);this.term=this._value();this.close(c);this.selectedItem=i}});this.liveRegion=c("<span>",{role:"status", +"aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertAfter(this.element);this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching);this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete");this.menu.element.remove();this.liveRegion.remove()},_setOption:function(c,j){this._super(c,j);"source"===c&&this._initSource();"appendTo"===c&&this.menu.element.appendTo(this._appendTo());"disabled"=== +c&&j&&this.xhr&&this.xhr.abort()},_appendTo:function(){var i=this.options.appendTo;i&&(i=i.jquery||i.nodeType?c(i):this.document.find(i).eq(0));i||(i=this.element.closest(".ui-front"));i.length||(i=this.document[0].body);return i},_isMultiLine:function(){return this.element.is("textarea")?!0:this.element.is("input")?!1:this.element.prop("isContentEditable")},_initSource:function(){var i,j,q=this;c.isArray(this.options.source)?(i=this.options.source,this.source=function(j,g){g(c.ui.autocomplete.filter(i, +j.term))}):"string"===typeof this.options.source?(j=this.options.source,this.source=function(i,g){q.xhr&&q.xhr.abort();q.xhr=c.ajax({url:j,data:i,dataType:"json",success:function(c){g(c)},error:function(){g([])}})}):this.source=this.options.source},_searchTimeout:function(c){clearTimeout(this.searching);this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,c))},this.options.delay)},search:function(c,j){c=null!=c?c:this._value();this.term=this._value(); +return c.length<this.options.minLength?this.close(j):!1===this._trigger("search",j)?void 0:this._search(c)},_search:function(c){this.pending++;this.element.addClass("ui-autocomplete-loading");this.cancelSearch=!1;this.source({term:c},this._response())},_response:function(){var c=this,r=++j;return function(q){r===j&&c.__response(q);c.pending--;c.pending||c.element.removeClass("ui-autocomplete-loading")}},__response:function(c){c&&(c=this._normalize(c));this._trigger("response",null,{content:c});!this.options.disabled&& +c&&c.length&&!this.cancelSearch?(this._suggest(c),this._trigger("open")):this._close()},close:function(c){this.cancelSearch=!0;this._close(c)},_close:function(c){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",c))},_change:function(c){this.previous!==this._value()&&this._trigger("change",c,{item:this.selectedItem})},_normalize:function(i){return i.length&&i[0].label&&i[0].value?i:c.map(i,function(i){return"string"===typeof i?{label:i, +value:i}:c.extend({label:i.label||i.value,value:i.value||i.label},i)})},_suggest:function(i){var j=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(j,i);this.menu.refresh();j.show();this._resizeMenu();j.position(c.extend({of:this.element},this.options.position));this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var c=this.menu.element;c.outerWidth(Math.max(c.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(i,j){var q=this;c.each(j, +function(c,g){q._renderItemData(i,g)})},_renderItemData:function(c,j){return this._renderItem(c,j).data("ui-autocomplete-item",j)},_renderItem:function(i,j){return c("<li>").append(c("<a>").text(j.label)).appendTo(i)},_move:function(c,j){if(this.menu.element.is(":visible"))if(this.menu.isFirstItem()&&/^previous/.test(c)||this.menu.isLastItem()&&/^next/.test(c))this._value(this.term),this.menu.blur();else this.menu[c](j);else this.search(null,j)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element, +arguments)},_keyEvent:function(c,j){if(!this.isMultiLine||this.menu.element.is(":visible"))this._move(c,j),j.preventDefault()}});c.extend(c.ui.autocomplete,{escapeRegex:function(c){return c.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(i,j){var q=RegExp(c.ui.autocomplete.escapeRegex(j),"i");return c.grep(i,function(c){return q.test(c.label||c.value||c)})}});c.widget("ui.autocomplete",c.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(c){return c+ +(1<c?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(c){this._superApply(arguments);!this.options.disabled&&!this.cancelSearch&&this.liveRegion.text(c&&c.length?this.options.messages.results(c.length):this.options.messages.noResults)}})})(jQuery); +(function(c){c.widget("ui.menu",{version:"1.10.0",defaultElement:"<ul>",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.mouseHandled=!1;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,c.proxy(function(c){this.options.disabled&&c.preventDefault()},this));this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true");this._on({"mousedown .ui-menu-item > a":function(c){c.preventDefault()},"click .ui-state-disabled > a":function(c){c.preventDefault()},"click .ui-menu-item:has(a)":function(j){var i=c(j.target).closest(".ui-menu-item");!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.mouseHandled=!0,this.select(j),i.has(".ui-menu").length? +this.expand(j):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(j){var i=c(j.currentTarget);i.siblings().children(".ui-state-active").removeClass("ui-state-active");this.focus(j,i)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(c,i){var r=this.active||this.element.children(".ui-menu-item").eq(0);i||this.focus(c,r)},blur:function(j){this._delay(function(){c.contains(this.element[0], +this.document[0].activeElement)||this.collapseAll(j)})},keydown:"_keydown"});this.refresh();this._on(this.document,{click:function(j){c(j.target).closest(".ui-menu").length||this.collapseAll(j);this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().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 j=c(this);j.data("ui-menu-submenu-carat")&&j.remove()});this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(j){function i(c){return c.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, +"\\$&")}var r,q,u,g,n=!0;switch(j.keyCode){case c.ui.keyCode.PAGE_UP:this.previousPage(j);break;case c.ui.keyCode.PAGE_DOWN:this.nextPage(j);break;case c.ui.keyCode.HOME:this._move("first","first",j);break;case c.ui.keyCode.END:this._move("last","last",j);break;case c.ui.keyCode.UP:this.previous(j);break;case c.ui.keyCode.DOWN:this.next(j);break;case c.ui.keyCode.LEFT:this.collapse(j);break;case c.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(j);break;case c.ui.keyCode.ENTER:case c.ui.keyCode.SPACE:this._activate(j); +break;case c.ui.keyCode.ESCAPE:this.collapse(j);break;default:n=!1,r=this.previousFilter||"",q=String.fromCharCode(j.keyCode),u=!1,clearTimeout(this.filterTimer),q===r?u=!0:q=r+q,g=RegExp("^"+i(q),"i"),r=this.activeMenu.children(".ui-menu-item").filter(function(){return g.test(c(this).children("a").text())}),r=u&&-1!==r.index(this.active.next())?this.active.nextAll(".ui-menu-item"):r,r.length||(q=String.fromCharCode(j.keyCode),g=RegExp("^"+i(q),"i"),r=this.activeMenu.children(".ui-menu-item").filter(function(){return g.test(c(this).children("a").text())})), +r.length?(this.focus(j,r),1<r.length?(this.previousFilter=q,this.filterTimer=this._delay(function(){delete this.previousFilter},1E3)):delete this.previousFilter):delete this.previousFilter}n&&j.preventDefault()},_activate:function(c){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(c):this.select(c))},refresh:function(){var j,i=this.options.icons.submenu;j=this.element.find(this.options.menus);j.filter(":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"}).each(function(){var j=c(this),q=j.prev("a"),u=c("<span>").addClass("ui-menu-icon ui-icon "+i).data("ui-menu-submenu-carat",!0);q.attr("aria-haspopup","true").prepend(u);j.attr("aria-labelledby",q.attr("id"))});j=j.add(this.element);j.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()});j.children(":not(.ui-menu-item)").each(function(){var i= +c(this);/[^\-\u2014\u2013\s]/.test(i.text())||i.addClass("ui-widget-content ui-menu-divider")});j.children(".ui-state-disabled").attr("aria-disabled","true");this.active&&!c.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(c,i){"icons"===c&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(i.submenu);this._super(c,i)},focus:function(c,i){var r;this.blur(c,c&& +"focus"===c.type);this._scrollIntoView(i);this.active=i.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");c&&"keydown"===c.type?this._close():this.timer=this._delay(function(){this._close()},this.delay);r=i.children(".ui-menu");r.length&&/^mouse/.test(c.type)&&this._startOpening(r);this.activeMenu=i.parent();this._trigger("focus", +c,{item:i})},_scrollIntoView:function(j){var i,r,q;this._hasScroll()&&(i=parseFloat(c.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(c.css(this.activeMenu[0],"paddingTop"))||0,i=j.offset().top-this.activeMenu.offset().top-i-r,r=this.activeMenu.scrollTop(),q=this.activeMenu.height(),j=j.height(),0>i?this.activeMenu.scrollTop(r+i):i+j>q&&this.activeMenu.scrollTop(r+i-q+j))},blur:function(c,i){i||clearTimeout(this.timer);this.active&&(this.active.children("a").removeClass("ui-state-focus"), +this.active=null,this._trigger("blur",c,{item:this.active}))},_startOpening:function(c){clearTimeout(this.timer);"true"===c.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close();this._open(c)},this.delay))},_open:function(j){var i=c.extend({of:this.active},this.options.position);clearTimeout(this.timer);this.element.find(".ui-menu").not(j.parents(".ui-menu")).hide().attr("aria-hidden","true");j.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(j, +i){clearTimeout(this.timer);this.timer=this._delay(function(){var r=i?this.element:c(j&&j.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element);this._close(r);this.blur(j);this.activeMenu=r},this.delay)},_close:function(c){c||(c=this.active?this.active.parent():this.element);c.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(c){var i=this.active&&this.active.parent().closest(".ui-menu-item", +this.element);i&&i.length&&(this._close(),this.focus(c,i))},expand:function(c){var i=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();i&&i.length&&(this._open(i.parent()),this._delay(function(){this.focus(c,i)}))},next:function(c){this._move("next","first",c)},previous:function(c){this._move("prev","last",c)},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(c,i,r){var q;this.active&&(q="first"===c||"last"===c?this.active["first"===c?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[c+"All"](".ui-menu-item").eq(0));if(!q||!q.length||!this.active)q=this.activeMenu.children(".ui-menu-item")[i]();this.focus(r,q)},nextPage:function(j){var i,r,q;this.active?this.isLastItem()||(this._hasScroll()?(r=this.active.offset().top,q=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){i=c(this);return 0>i.offset().top-r- +q}),this.focus(j,i)):this.focus(j,this.activeMenu.children(".ui-menu-item")[!this.active?"first":"last"]())):this.next(j)},previousPage:function(j){var i,r,q;this.active?this.isFirstItem()||(this._hasScroll()?(r=this.active.offset().top,q=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){i=c(this);return 0<i.offset().top-r+q}),this.focus(j,i)):this.focus(j,this.activeMenu.children(".ui-menu-item").first())):this.next(j)},_hasScroll:function(){return this.element.outerHeight()< +this.element.prop("scrollHeight")},select:function(j){this.active=this.active||c(j.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(j,!0);this._trigger("select",j,i)}})})(jQuery); +(function(){var c=this,j=c._,i={},r=Array.prototype,q=Object.prototype,u=r.push,g=r.slice,n=r.concat,z=q.toString,J=q.hasOwnProperty,y=r.forEach,E=r.map,K=r.reduce,F=r.reduceRight,T=r.filter,Z=r.every,I=r.some,x=r.indexOf,G=r.lastIndexOf,q=Array.isArray,O=Object.keys,H=Function.prototype.bind,m=function(f){if(f instanceof m)return f;if(!(this instanceof m))return new m(f);this._wrapped=f};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=m),exports._= +m):c._=m;m.VERSION="1.4.3";var w=m.each=m.forEach=function(f,e,c){if(null!=f)if(y&&f.forEach===y)f.forEach(e,c);else if(f.length===+f.length)for(var k=0,g=f.length;k<g&&!(e.call(c,f[k],k,f)===i);k++);else for(k in f)if(m.has(f,k)&&e.call(c,f[k],k,f)===i)break};m.map=m.collect=function(f,e,c){var k=[];if(null==f)return k;if(E&&f.map===E)return f.map(e,c);w(f,function(f,g,i){k[k.length]=e.call(c,f,g,i)});return k};m.reduce=m.foldl=m.inject=function(f,e,c,k){var g=2<arguments.length;null==f&&(f=[]); +if(K&&f.reduce===K)return k&&(e=m.bind(e,k)),g?f.reduce(e,c):f.reduce(e);w(f,function(f,i,j){g?c=e.call(k,c,f,i,j):(c=f,g=!0)});if(!g)throw new TypeError("Reduce of empty array with no initial value");return c};m.reduceRight=m.foldr=function(f,e,c,k){var g=2<arguments.length;null==f&&(f=[]);if(F&&f.reduceRight===F)return k&&(e=m.bind(e,k)),g?f.reduceRight(e,c):f.reduceRight(e);var i=f.length;if(i!==+i)var j=m.keys(f),i=j.length;w(f,function(m,n,t){n=j?j[--i]:--i;g?c=e.call(k,c,f[n],n,t):(c=f[n],g= +!0)});if(!g)throw new TypeError("Reduce of empty array with no initial value");return c};m.find=m.detect=function(f,e,c){var k;V(f,function(f,g,i){if(e.call(c,f,g,i))return k=f,!0});return k};m.filter=m.select=function(f,e,c){var k=[];if(null==f)return k;if(T&&f.filter===T)return f.filter(e,c);w(f,function(f,g,i){e.call(c,f,g,i)&&(k[k.length]=f)});return k};m.reject=function(f,e,c){return m.filter(f,function(f,k,g){return!e.call(c,f,k,g)},c)};m.every=m.all=function(f,e,c){e||(e=m.identity);var k= +!0;if(null==f)return k;if(Z&&f.every===Z)return f.every(e,c);w(f,function(f,g,j){if(!(k=k&&e.call(c,f,g,j)))return i});return!!k};var V=m.some=m.any=function(f,e,c){e||(e=m.identity);var k=!1;if(null==f)return k;if(I&&f.some===I)return f.some(e,c);w(f,function(f,g,j){if(k||(k=e.call(c,f,g,j)))return i});return!!k};m.contains=m.include=function(f,e){return null==f?!1:x&&f.indexOf===x?-1!=f.indexOf(e):V(f,function(f){return f===e})};m.invoke=function(f,e){var c=g.call(arguments,2);return m.map(f,function(f){return(m.isFunction(e)? +e:f[e]).apply(f,c)})};m.pluck=function(f,e){return m.map(f,function(f){return f[e]})};m.where=function(f,e){return m.isEmpty(e)?[]:m.filter(f,function(f){for(var c in e)if(e[c]!==f[c])return!1;return!0})};m.max=function(f,e,c){if(!e&&m.isArray(f)&&f[0]===+f[0]&&65535>f.length)return Math.max.apply(Math,f);if(!e&&m.isEmpty(f))return-Infinity;var k={computed:-Infinity,value:-Infinity};w(f,function(f,g,i){g=e?e.call(c,f,g,i):f;g>=k.computed&&(k={value:f,computed:g})});return k.value};m.min=function(f, +e,c){if(!e&&m.isArray(f)&&f[0]===+f[0]&&65535>f.length)return Math.min.apply(Math,f);if(!e&&m.isEmpty(f))return Infinity;var k={computed:Infinity,value:Infinity};w(f,function(f,g,i){g=e?e.call(c,f,g,i):f;g<k.computed&&(k={value:f,computed:g})});return k.value};m.shuffle=function(f){var e,c=0,k=[];w(f,function(f){e=m.random(c++);k[c-1]=k[e];k[e]=f});return k};var W=function(f){return m.isFunction(f)?f:function(e){return e[f]}};m.sortBy=function(f,e,c){var k=W(e);return m.pluck(m.map(f,function(f,e, +l){return{value:f,index:e,criteria:k.call(c,f,e,l)}}).sort(function(f,e){var c=f.criteria,k=e.criteria;if(c!==k){if(c>k||void 0===c)return 1;if(c<k||void 0===k)return-1}return f.index<e.index?-1:1}),"value")};var P=function(f,e,c,k){var g={},i=W(e||m.identity);w(f,function(e,l){var j=i.call(c,e,l,f);k(g,j,e)});return g};m.groupBy=function(f,e,c){return P(f,e,c,function(f,e,c){(m.has(f,e)?f[e]:f[e]=[]).push(c)})};m.countBy=function(f,e,c){return P(f,e,c,function(f,e){m.has(f,e)||(f[e]=0);f[e]++})}; +m.sortedIndex=function(f,e,c,k){for(var c=null==c?m.identity:W(c),e=c.call(k,e),g=0,i=f.length;g<i;){var j=g+i>>>1;c.call(k,f[j])<e?g=j+1:i=j}return g};m.toArray=function(f){return!f?[]:m.isArray(f)?g.call(f):f.length===+f.length?m.map(f,m.identity):m.values(f)};m.size=function(f){return null==f?0:f.length===+f.length?f.length:m.keys(f).length};m.first=m.head=m.take=function(f,e,c){return null==f?void 0:null!=e&&!c?g.call(f,0,e):f[0]};m.initial=function(f,e,c){return g.call(f,0,f.length-(null==e|| +c?1:e))};m.last=function(f,e,c){return null==f?void 0:null!=e&&!c?g.call(f,Math.max(f.length-e,0)):f[f.length-1]};m.rest=m.tail=m.drop=function(f,e,c){return g.call(f,null==e||c?1:e)};m.compact=function(f){return m.filter(f,m.identity)};var $=function(f,e,c){w(f,function(f){m.isArray(f)?e?u.apply(c,f):$(f,e,c):c.push(f)});return c};m.flatten=function(f,e){return $(f,e,[])};m.without=function(f){return m.difference(f,g.call(arguments,1))};m.uniq=m.unique=function(f,e,c,k){m.isFunction(e)&&(k=c,c=e, +e=!1);var c=c?m.map(f,c,k):f,g=[],i=[];w(c,function(c,k){if(e?!k||i[i.length-1]!==c:!m.contains(i,c))i.push(c),g.push(f[k])});return g};m.union=function(){return m.uniq(n.apply(r,arguments))};m.intersection=function(f){var e=g.call(arguments,1);return m.filter(m.uniq(f),function(f){return m.every(e,function(e){return 0<=m.indexOf(e,f)})})};m.difference=function(f){var e=n.apply(r,g.call(arguments,1));return m.filter(f,function(f){return!m.contains(e,f)})};m.zip=function(){for(var f=g.call(arguments), +e=m.max(m.pluck(f,"length")),c=Array(e),k=0;k<e;k++)c[k]=m.pluck(f,""+k);return c};m.object=function(f,e){if(null==f)return{};for(var c={},k=0,g=f.length;k<g;k++)e?c[f[k]]=e[k]:c[f[k][0]]=f[k][1];return c};m.indexOf=function(f,e,c){if(null==f)return-1;var k=0,g=f.length;if(c)if("number"==typeof c)k=0>c?Math.max(0,g+c):c;else return k=m.sortedIndex(f,e),f[k]===e?k:-1;if(x&&f.indexOf===x)return f.indexOf(e,c);for(;k<g;k++)if(f[k]===e)return k;return-1};m.lastIndexOf=function(f,e,c){if(null==f)return-1; +var k=null!=c;if(G&&f.lastIndexOf===G)return k?f.lastIndexOf(e,c):f.lastIndexOf(e);for(c=k?c:f.length;c--;)if(f[c]===e)return c;return-1};m.range=function(f,e,c){1>=arguments.length&&(e=f||0,f=0);for(var c=arguments[2]||1,k=Math.max(Math.ceil((e-f)/c),0),g=0,i=Array(k);g<k;)i[g++]=f,f+=c;return i};var M=function(){};m.bind=function(f,e){var c,k;if(f.bind===H&&H)return H.apply(f,g.call(arguments,1));if(!m.isFunction(f))throw new TypeError;c=g.call(arguments,2);return k=function(){if(!(this instanceof +k))return f.apply(e,c.concat(g.call(arguments)));M.prototype=f.prototype;var i=new M;M.prototype=null;var j=f.apply(i,c.concat(g.call(arguments)));return Object(j)===j?j:i}};m.bindAll=function(f){var e=g.call(arguments,1);0==e.length&&(e=m.functions(f));w(e,function(e){f[e]=m.bind(f[e],f)});return f};m.memoize=function(f,e){var c={};e||(e=m.identity);return function(){var k=e.apply(this,arguments);return m.has(c,k)?c[k]:c[k]=f.apply(this,arguments)}};m.delay=function(f,e){var c=g.call(arguments,2); +return setTimeout(function(){return f.apply(null,c)},e)};m.defer=function(f){return m.delay.apply(m,[f,1].concat(g.call(arguments,1)))};m.throttle=function(f,e){var c,k,g,i,j=0,m=function(){j=new Date;g=null;i=f.apply(c,k)};return function(){var n=new Date,t=e-(n-j);c=this;k=arguments;0>=t?(clearTimeout(g),g=null,j=n,i=f.apply(c,k)):g||(g=setTimeout(m,t));return i}};m.debounce=function(f,e,c){var k,g;return function(){var i=this,j=arguments,m=c&&!k;clearTimeout(k);k=setTimeout(function(){k=null;c|| +(g=f.apply(i,j))},e);m&&(g=f.apply(i,j));return g}};m.once=function(f){var e=!1,c;return function(){if(e)return c;e=!0;c=f.apply(this,arguments);f=null;return c}};m.wrap=function(f,e){return function(){var c=[f];u.apply(c,arguments);return e.apply(this,c)}};m.compose=function(){var f=arguments;return function(){for(var e=arguments,c=f.length-1;0<=c;c--)e=[f[c].apply(this,e)];return e[0]}};m.after=function(f,e){return 0>=f?e():function(){if(1>--f)return e.apply(this,arguments)}};m.keys=O||function(f){if(f!== +Object(f))throw new TypeError("Invalid object");var e=[],c;for(c in f)m.has(f,c)&&(e[e.length]=c);return e};m.values=function(f){var e=[],c;for(c in f)m.has(f,c)&&e.push(f[c]);return e};m.pairs=function(f){var e=[],c;for(c in f)m.has(f,c)&&e.push([c,f[c]]);return e};m.invert=function(f){var e={},c;for(c in f)m.has(f,c)&&(e[f[c]]=c);return e};m.functions=m.methods=function(f){var e=[],c;for(c in f)m.isFunction(f[c])&&e.push(c);return e.sort()};m.extend=function(e){w(g.call(arguments,1),function(c){if(c)for(var k in c)e[k]= +c[k]});return e};m.pick=function(e){var c={},k=n.apply(r,g.call(arguments,1));w(k,function(k){k in e&&(c[k]=e[k])});return c};m.omit=function(e){var c={},k=n.apply(r,g.call(arguments,1)),i;for(i in e)m.contains(k,i)||(c[i]=e[i]);return c};m.defaults=function(e){w(g.call(arguments,1),function(c){if(c)for(var k in c)null==e[k]&&(e[k]=c[k])});return e};m.clone=function(e){return!m.isObject(e)?e:m.isArray(e)?e.slice():m.extend({},e)};m.tap=function(e,c){c(e);return e};var e=function(f,c,k,g){if(f===c)return 0!== +f||1/f==1/c;if(null==f||null==c)return f===c;f instanceof m&&(f=f._wrapped);c instanceof m&&(c=c._wrapped);var i=z.call(f);if(i!=z.call(c))return!1;switch(i){case "[object String]":return f==""+c;case "[object Number]":return f!=+f?c!=+c:0==f?1/f==1/c:f==+c;case "[object Date]":case "[object Boolean]":return+f==+c;case "[object RegExp]":return f.source==c.source&&f.global==c.global&&f.multiline==c.multiline&&f.ignoreCase==c.ignoreCase}if("object"!=typeof f||"object"!=typeof c)return!1;for(var j=k.length;j--;)if(k[j]== +f)return g[j]==c;k.push(f);g.push(c);var j=0,n=!0;if("[object Array]"==i){if(j=f.length,n=j==c.length)for(;j--&&(n=e(f[j],c[j],k,g)););}else{var i=f.constructor,t=c.constructor;if(i!==t&&(!m.isFunction(i)||!(i instanceof i&&m.isFunction(t)&&t instanceof t)))return!1;for(var q in f)if(m.has(f,q)&&(j++,!(n=m.has(c,q)&&e(f[q],c[q],k,g))))break;if(n){for(q in c)if(m.has(c,q)&&!j--)break;n=!j}}k.pop();g.pop();return n};m.isEqual=function(f,c){return e(f,c,[],[])};m.isEmpty=function(e){if(null==e)return!0; +if(m.isArray(e)||m.isString(e))return 0===e.length;for(var c in e)if(m.has(e,c))return!1;return!0};m.isElement=function(e){return!!(e&&1===e.nodeType)};m.isArray=q||function(e){return"[object Array]"==z.call(e)};m.isObject=function(e){return e===Object(e)};w("Arguments,Function,String,Number,Date,RegExp".split(","),function(e){m["is"+e]=function(c){return z.call(c)=="[object "+e+"]"}});m.isArguments(arguments)||(m.isArguments=function(e){return!(!e||!m.has(e,"callee"))});"function"!==typeof/./&&(m.isFunction= +function(e){return"function"===typeof e});m.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))};m.isNaN=function(e){return m.isNumber(e)&&e!=+e};m.isBoolean=function(e){return!0===e||!1===e||"[object Boolean]"==z.call(e)};m.isNull=function(e){return null===e};m.isUndefined=function(e){return void 0===e};m.has=function(e,c){return J.call(e,c)};m.noConflict=function(){c._=j;return this};m.identity=function(e){return e};m.times=function(e,c,k){for(var g=Array(e),i=0;i<e;i++)g[i]=c.call(k, +i);return g};m.random=function(e,c){null==c&&(c=e,e=0);return e+(0|Math.random()*(c-e+1))};var k={escape:{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;"}};k.unescape=m.invert(k.escape);var t={escape:RegExp("["+m.keys(k.escape).join("")+"]","g"),unescape:RegExp("("+m.keys(k.unescape).join("|")+")","g")};m.each(["escape","unescape"],function(e){m[e]=function(c){return null==c?"":(""+c).replace(t[e],function(c){return k[e][c]})}});m.result=function(e,c){if(null==e)return null; +var k=e[c];return m.isFunction(k)?k.call(e):k};m.mixin=function(e){w(m.functions(e),function(c){var k=m[c]=e[c];m.prototype[c]=function(){var e=[this._wrapped];u.apply(e,arguments);e=k.apply(m,e);return this._chain?m(e).chain():e}})};var R=0;m.uniqueId=function(e){var c=""+ ++R;return e?e+c:c};m.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var C=/(.)^/,ea={"'":"'","\\":"\\","\r":"r","\n":"n","\t":"t","\u2028":"u2028","\u2029":"u2029"},Q=/\\|'|\r|\n|\t|\u2028|\u2029/g; +m.template=function(e,c,k){var k=m.defaults({},k,m.templateSettings),g=RegExp([(k.escape||C).source,(k.interpolate||C).source,(k.evaluate||C).source].join("|")+"|$","g"),i=0,j="__p+='";e.replace(g,function(c,k,g,l,m){j+=e.slice(i,m).replace(Q,function(e){return"\\"+ea[e]});k&&(j+="'+\n((__t=("+k+"))==null?'':_.escape(__t))+\n'");g&&(j+="'+\n((__t=("+g+"))==null?'':__t)+\n'");l&&(j+="';\n"+l+"\n__p+='");i=m+c.length;return c});j+="';\n";k.variable||(j="with(obj||{}){\n"+j+"}\n");j="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+ +j+"return __p;\n";try{var n=new Function(k.variable||"obj","_",j)}catch(t){throw t.source=j,t;}if(c)return n(c,m);c=function(e){return n.call(this,e,m)};c.source="function("+(k.variable||"obj")+"){\n"+j+"}";return c};m.chain=function(e){return m(e).chain()};m.mixin(m);w("pop,push,reverse,shift,sort,splice,unshift".split(","),function(e){var c=r[e];m.prototype[e]=function(){var k=this._wrapped;c.apply(k,arguments);("shift"==e||"splice"==e)&&0===k.length&&delete k[0];return this._chain?m(k).chain(): +k}});w(["concat","join","slice"],function(e){var c=r[e];m.prototype[e]=function(){var e=c.apply(this._wrapped,arguments);return this._chain?m(e).chain():e}});m.extend(m.prototype,{chain:function(){this._chain=!0;return this},value:function(){return this._wrapped}})}).call(this); +(function(){var c=this,j=c.Backbone,i=[],r=i.push,q=i.slice,u=i.splice,g;g="undefined"!==typeof exports?exports:c.Backbone={};g.VERSION="0.9.10";var n=c._;!n&&"undefined"!==typeof require&&(n=require("underscore"));g.$=c.jQuery||c.Zepto||c.ender;g.noConflict=function(){c.Backbone=j;return this};g.emulateHTTP=!1;g.emulateJSON=!1;var z=/\s+/,J=function(e,c,g,i){if(!g)return!0;if("object"===typeof g)for(var j in g)e[c].apply(e,[j,g[j]].concat(i));else if(z.test(g)){g=g.split(z);j=0;for(var m=g.length;j< +m;j++)e[c].apply(e,[g[j]].concat(i))}else return!0},y=function(e,c){var g,i=-1,j=e.length;switch(c.length){case 0:for(;++i<j;)(g=e[i]).callback.call(g.ctx);break;case 1:for(;++i<j;)(g=e[i]).callback.call(g.ctx,c[0]);break;case 2:for(;++i<j;)(g=e[i]).callback.call(g.ctx,c[0],c[1]);break;case 3:for(;++i<j;)(g=e[i]).callback.call(g.ctx,c[0],c[1],c[2]);break;default:for(;++i<j;)(g=e[i]).callback.apply(g.ctx,c)}},i=g.Events={on:function(e,c,g){if(!J(this,"on",e,[c,g])||!c)return this;this._events||(this._events= +{});(this._events[e]||(this._events[e]=[])).push({callback:c,context:g,ctx:g||this});return this},once:function(e,c,g){if(!J(this,"once",e,[c,g])||!c)return this;var i=this,j=n.once(function(){i.off(e,j);c.apply(this,arguments)});j._callback=c;this.on(e,j,g);return this},off:function(e,c,g){var i,j,m,q,f,l,r,u;if(!this._events||!J(this,"off",e,[c,g]))return this;if(!e&&!c&&!g)return this._events={},this;q=e?[e]:n.keys(this._events);for(f=0,l=q.length;f<l;f++)if(e=q[f],i=this._events[e]){m=[];if(c|| +g)for(r=0,u=i.length;r<u;r++)j=i[r],(c&&c!==j.callback&&c!==j.callback._callback||g&&g!==j.context)&&m.push(j);this._events[e]=m}return this},trigger:function(e){if(!this._events)return this;var c=q.call(arguments,1);if(!J(this,"trigger",e,c))return this;var g=this._events[e],i=this._events.all;g&&y(g,c);i&&y(i,arguments);return this},listenTo:function(e,c,g){var i=this._listeners||(this._listeners={}),j=e._listenerId||(e._listenerId=n.uniqueId("l"));i[j]=e;e.on(c,"object"===typeof c?this:g,this); +return this},stopListening:function(e,c,g){var i=this._listeners;if(i){if(e)e.off(c,"object"===typeof c?this:g,this),!c&&!g&&delete i[e._listenerId];else{"object"===typeof c&&(g=this);for(var j in i)i[j].off(c,g,this);this._listeners={}}return this}}};i.bind=i.on;i.unbind=i.off;n.extend(g,i);var E=g.Model=function(e,c){var g,i=e||{};this.cid=n.uniqueId("c");this.attributes={};c&&c.collection&&(this.collection=c.collection);c&&c.parse&&(i=this.parse(i,c)||{});if(g=n.result(this,"defaults"))i=n.defaults({}, +i,g);this.set(i,c);this.changed={};this.initialize.apply(this,arguments)};n.extend(E.prototype,i,{changed:null,idAttribute:"id",initialize:function(){},toJSON:function(){return n.clone(this.attributes)},sync:function(){return g.sync.apply(this,arguments)},get:function(e){return this.attributes[e]},escape:function(e){return n.escape(this.get(e))},has:function(e){return null!=this.get(e)},set:function(e,c,g){var i,j,m,q,f,l,r;if(null==e)return this;"object"===typeof e?(j=e,g=c):(j={})[e]=c;g||(g={}); +if(!this._validate(j,g))return!1;m=g.unset;q=g.silent;e=[];f=this._changing;this._changing=!0;f||(this._previousAttributes=n.clone(this.attributes),this.changed={});r=this.attributes;l=this._previousAttributes;this.idAttribute in j&&(this.id=j[this.idAttribute]);for(i in j)c=j[i],n.isEqual(r[i],c)||e.push(i),n.isEqual(l[i],c)?delete this.changed[i]:this.changed[i]=c,m?delete r[i]:r[i]=c;if(!q){e.length&&(this._pending=!0);c=0;for(i=e.length;c<i;c++)this.trigger("change:"+e[c],this,r[e[c]],g)}if(f)return this; +if(!q)for(;this._pending;)this._pending=!1,this.trigger("change",this,g);this._changing=this._pending=!1;return this},unset:function(e,c){return this.set(e,void 0,n.extend({},c,{unset:!0}))},clear:function(e){var c={},g;for(g in this.attributes)c[g]=void 0;return this.set(c,n.extend({},e,{unset:!0}))},hasChanged:function(e){return null==e?!n.isEmpty(this.changed):n.has(this.changed,e)},changedAttributes:function(e){if(!e)return this.hasChanged()?n.clone(this.changed):!1;var c,g=!1,i=this._changing? +this._previousAttributes:this.attributes,j;for(j in e)if(!n.isEqual(i[j],c=e[j]))(g||(g={}))[j]=c;return g},previous:function(e){return null==e||!this._previousAttributes?null:this._previousAttributes[e]},previousAttributes:function(){return n.clone(this._previousAttributes)},fetch:function(e){e=e?n.clone(e):{};void 0===e.parse&&(e.parse=!0);var c=e.success;e.success=function(e,g,i){if(!e.set(e.parse(g,i),i))return!1;c&&c(e,g,i)};return this.sync("read",this,e)},save:function(e,c,g){var i,j,m=this.attributes; +null==e||"object"===typeof e?(i=e,g=c):(i={})[e]=c;if(i&&(!g||!g.wait)&&!this.set(i,g))return!1;g=n.extend({validate:!0},g);if(!this._validate(i,g))return!1;i&&g.wait&&(this.attributes=n.extend({},m,i));void 0===g.parse&&(g.parse=!0);j=g.success;g.success=function(e,c,k){e.attributes=m;var g=e.parse(c,k);k.wait&&(g=n.extend(i||{},g));if(n.isObject(g)&&!e.set(g,k))return!1;j&&j(e,c,k)};e=this.isNew()?"create":g.patch?"patch":"update";"patch"===e&&(g.attrs=i);e=this.sync(e,this,g);i&&g.wait&&(this.attributes= +m);return e},destroy:function(e){var e=e?n.clone(e):{},c=this,g=e.success,i=function(){c.trigger("destroy",c,c.collection,e)};e.success=function(e,c,f){(f.wait||e.isNew())&&i();g&&g(e,c,f)};if(this.isNew())return e.success(this,null,e),!1;var j=this.sync("delete",this,e);e.wait||i();return j},url:function(){var e=n.result(this,"urlRoot")||n.result(this.collection,"url")||M();return this.isNew()?e:e+("/"===e.charAt(e.length-1)?"":"/")+encodeURIComponent(this.id)},parse:function(e){return e},clone:function(){return new this.constructor(this.attributes)}, +isNew:function(){return null==this.id},isValid:function(e){return!this.validate||!this.validate(this.attributes,e)},_validate:function(e,c){if(!c.validate||!this.validate)return!0;var e=n.extend({},this.attributes,e),g=this.validationError=this.validate(e,c)||null;if(!g)return!0;this.trigger("invalid",this,g,c||{});return!1}});var K=g.Collection=function(e,c){c||(c={});c.model&&(this.model=c.model);void 0!==c.comparator&&(this.comparator=c.comparator);this.models=[];this._reset();this.initialize.apply(this, +arguments);e&&this.reset(e,n.extend({silent:!0},c))};n.extend(K.prototype,i,{model:E,initialize:function(){},toJSON:function(e){return this.map(function(c){return c.toJSON(e)})},sync:function(){return g.sync.apply(this,arguments)},add:function(e,c){e=n.isArray(e)?e.slice():[e];c||(c={});var g,i,j,m,q,f,l,s,w,x;l=[];s=c.at;w=this.comparator&&null==s&&!1!=c.sort;x=n.isString(this.comparator)?this.comparator:null;for(g=0,i=e.length;g<i;g++)(j=this._prepareModel(m=e[g],c))?(q=this.get(j))?c.merge&&(q.set(m=== +j?j.attributes:m,c),w&&!f&&q.hasChanged(x)&&(f=!0)):(l.push(j),j.on("all",this._onModelEvent,this),this._byId[j.cid]=j,null!=j.id&&(this._byId[j.id]=j)):this.trigger("invalid",this,m,c);l.length&&(w&&(f=!0),this.length+=l.length,null!=s?u.apply(this.models,[s,0].concat(l)):r.apply(this.models,l));f&&this.sort({silent:!0});if(c.silent)return this;for(g=0,i=l.length;g<i;g++)(j=l[g]).trigger("add",j,this,c);f&&this.trigger("sort",this,c);return this},remove:function(e,c){e=n.isArray(e)?e.slice():[e]; +c||(c={});var g,i,j,m;for(g=0,i=e.length;g<i;g++)if(m=this.get(e[g]))delete this._byId[m.id],delete this._byId[m.cid],j=this.indexOf(m),this.models.splice(j,1),this.length--,c.silent||(c.index=j,m.trigger("remove",m,this,c)),this._removeReference(m);return this},push:function(e,c){e=this._prepareModel(e,c);this.add(e,n.extend({at:this.length},c));return e},pop:function(e){var c=this.at(this.length-1);this.remove(c,e);return c},unshift:function(e,c){e=this._prepareModel(e,c);this.add(e,n.extend({at:0}, +c));return e},shift:function(e){var c=this.at(0);this.remove(c,e);return c},slice:function(e,c){return this.models.slice(e,c)},get:function(e){if(null!=e)return this._idAttr||(this._idAttr=this.model.prototype.idAttribute),this._byId[e.id||e.cid||e[this._idAttr]||e]},at:function(e){return this.models[e]},where:function(e){return n.isEmpty(e)?[]:this.filter(function(c){for(var g in e)if(e[g]!==c.get(g))return!1;return!0})},sort:function(e){if(!this.comparator)throw Error("Cannot sort a set without a comparator"); +e||(e={});n.isString(this.comparator)||1===this.comparator.length?this.models=this.sortBy(this.comparator,this):this.models.sort(n.bind(this.comparator,this));e.silent||this.trigger("sort",this,e);return this},pluck:function(e){return n.invoke(this.models,"get",e)},update:function(e,c){c=n.extend({add:!0,merge:!0,remove:!0},c);c.parse&&(e=this.parse(e,c));var g,i,j,m,q=[],f=[],l={};n.isArray(e)||(e=e?[e]:[]);if(c.add&&!c.remove)return this.add(e,c);for(i=0,j=e.length;i<j;i++)g=e[i],m=this.get(g), +c.remove&&m&&(l[m.cid]=!0),(c.add&&!m||c.merge&&m)&&q.push(g);if(c.remove)for(i=0,j=this.models.length;i<j;i++)g=this.models[i],l[g.cid]||f.push(g);f.length&&this.remove(f,c);q.length&&this.add(q,c);return this},reset:function(e,c){c||(c={});c.parse&&(e=this.parse(e,c));for(var g=0,i=this.models.length;g<i;g++)this._removeReference(this.models[g]);c.previousModels=this.models.slice();this._reset();e&&this.add(e,n.extend({silent:!0},c));c.silent||this.trigger("reset",this,c);return this},fetch:function(e){e= +e?n.clone(e):{};void 0===e.parse&&(e.parse=!0);var c=e.success;e.success=function(e,g,i){e[i.update?"update":"reset"](g,i);c&&c(e,g,i)};return this.sync("read",this,e)},create:function(e,c){c=c?n.clone(c):{};if(!(e=this._prepareModel(e,c)))return!1;c.wait||this.add(e,c);var g=this,i=c.success;c.success=function(e,c,k){k.wait&&g.add(e,k);i&&i(e,c,k)};e.save(null,c);return e},parse:function(e){return e},clone:function(){return new this.constructor(this.models)},_reset:function(){this.length=0;this.models.length= +0;this._byId={}},_prepareModel:function(e,c){if(e instanceof E)return e.collection||(e.collection=this),e;c||(c={});c.collection=this;var g=new this.model(e,c);return!g._validate(e,c)?!1:g},_removeReference:function(e){this===e.collection&&delete e.collection;e.off("all",this._onModelEvent,this)},_onModelEvent:function(e,c,g,i){("add"===e||"remove"===e)&&g!==this||("destroy"===e&&this.remove(c,i),c&&e==="change:"+c.idAttribute&&(delete this._byId[c.previous(c.idAttribute)],null!=c.id&&(this._byId[c.id]= +c)),this.trigger.apply(this,arguments))},sortedIndex:function(e,c,g){c||(c=this.comparator);var i=n.isFunction(c)?c:function(e){return e.get(c)};return n.sortedIndex(this.models,e,i,g)}});n.each("forEach,each,map,collect,reduce,foldl,inject,reduceRight,foldr,find,detect,filter,select,reject,every,all,some,any,include,contains,invoke,max,min,toArray,size,first,head,take,initial,rest,tail,drop,last,without,indexOf,shuffle,lastIndexOf,isEmpty,chain".split(","),function(e){K.prototype[e]=function(){var c= +q.call(arguments);c.unshift(this.models);return n[e].apply(n,c)}});n.each(["groupBy","countBy","sortBy"],function(e){K.prototype[e]=function(c,g){var i=n.isFunction(c)?c:function(e){return e.get(c)};return n[e](this.models,i,g)}});var F=g.Router=function(e){e||(e={});e.routes&&(this.routes=e.routes);this._bindRoutes();this.initialize.apply(this,arguments)},T=/\((.*?)\)/g,Z=/(\(\?)?:\w+/g,I=/\*\w+/g,x=/[\-{}\[\]+?.,\\\^$|#\s]/g;n.extend(F.prototype,i,{initialize:function(){},route:function(e,c,i){n.isRegExp(e)|| +(e=this._routeToRegExp(e));i||(i=this[c]);g.history.route(e,n.bind(function(j){j=this._extractParameters(e,j);i&&i.apply(this,j);this.trigger.apply(this,["route:"+c].concat(j));this.trigger("route",c,j);g.history.trigger("route",this,c,j)},this));return this},navigate:function(c,i){g.history.navigate(c,i);return this},_bindRoutes:function(){if(this.routes)for(var c,g=n.keys(this.routes);null!=(c=g.pop());)this.route(c,this.routes[c])},_routeToRegExp:function(c){c=c.replace(x,"\\$&").replace(T,"(?:$1)?").replace(Z, +function(c,e){return e?c:"([^/]+)"}).replace(I,"(.*?)");return RegExp("^"+c+"$")},_extractParameters:function(c,g){return c.exec(g).slice(1)}});var G=g.History=function(){this.handlers=[];n.bindAll(this,"checkUrl");"undefined"!==typeof window&&(this.location=window.location,this.history=window.history)},O=/^[#\/]|\s+$/g,H=/^\/+|\/+$/g,m=/msie [\w.]+/,w=/\/$/;G.started=!1;n.extend(G.prototype,i,{interval:50,getHash:function(c){return(c=(c||this).location.href.match(/#(.*)$/))?c[1]:""},getFragment:function(c, +g){if(null==c)if(this._hasPushState||!this._wantsHashChange||g){var c=this.location.pathname,i=this.root.replace(w,"");c.indexOf(i)||(c=c.substr(i.length))}else c=this.getHash();return c.replace(O,"")},start:function(c){if(G.started)throw Error("Backbone.history has already been started");G.started=!0;this.options=n.extend({},{root:"/"},this.options,c);this.root=this.options.root;this._wantsHashChange=!1!==this.options.hashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=!(!this.options.pushState|| +!this.history||!this.history.pushState);var c=this.getFragment(),i=document.documentMode,i=m.exec(navigator.userAgent.toLowerCase())&&(!i||7>=i);this.root=("/"+this.root+"/").replace(H,"/");i&&this._wantsHashChange&&(this.iframe=g.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow,this.navigate(c));if(this._hasPushState)g.$(window).on("popstate",this.checkUrl);else if(this._wantsHashChange&&"onhashchange"in window&&!i)g.$(window).on("hashchange",this.checkUrl); +else this._wantsHashChange&&(this._checkUrlInterval=setInterval(this.checkUrl,this.interval));this.fragment=c;c=this.location;i=c.pathname.replace(/[^\/]$/,"$&/")===this.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!i)return this.fragment=this.getFragment(null,!0),this.location.replace(this.root+this.location.search+"#"+this.fragment),!0;this._wantsPushState&&this._hasPushState&&i&&c.hash&&(this.fragment=this.getHash().replace(O,""),this.history.replaceState({},document.title, +this.root+this.fragment+c.search));if(!this.options.silent)return this.loadUrl()},stop:function(){g.$(window).off("popstate",this.checkUrl).off("hashchange",this.checkUrl);clearInterval(this._checkUrlInterval);G.started=!1},route:function(c,g){this.handlers.unshift({route:c,callback:g})},checkUrl:function(){var c=this.getFragment();c===this.fragment&&this.iframe&&(c=this.getFragment(this.getHash(this.iframe)));if(c===this.fragment)return!1;this.iframe&&this.navigate(c);this.loadUrl()||this.loadUrl(this.getHash())}, +loadUrl:function(c){var g=this.fragment=this.getFragment(c);return n.any(this.handlers,function(c){if(c.route.test(g))return c.callback(g),!0})},navigate:function(c,g){if(!G.started)return!1;if(!g||!0===g)g={trigger:g};c=this.getFragment(c||"");if(this.fragment!==c){this.fragment=c;var i=this.root+c;if(this._hasPushState)this.history[g.replace?"replaceState":"pushState"]({},document.title,i);else if(this._wantsHashChange)this._updateHash(this.location,c,g.replace),this.iframe&&c!==this.getFragment(this.getHash(this.iframe))&& +(g.replace||this.iframe.document.open().close(),this._updateHash(this.iframe.location,c,g.replace));else return this.location.assign(i);g.trigger&&this.loadUrl(c)}},_updateHash:function(c,g,i){i?(i=c.href.replace(/(javascript:|#).*$/,""),c.replace(i+"#"+g)):c.hash="#"+g}});g.history=new G;var V=g.View=function(c){this.cid=n.uniqueId("view");this._configure(c||{});this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()},W=/^(\S+)\s*(.*)$/,P="model,collection,el,id,attributes,className,tagName,events".split(","); +n.extend(V.prototype,i,{tagName:"div",$:function(c){return this.$el.find(c)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();this.stopListening();return this},setElement:function(c,i){this.$el&&this.undelegateEvents();this.$el=c instanceof g.$?c:g.$(c);this.el=this.$el[0];!1!==i&&this.delegateEvents();return this},delegateEvents:function(c){if(c||(c=n.result(this,"events"))){this.undelegateEvents();for(var g in c){var i=c[g];n.isFunction(i)||(i=this[c[g]]); +if(!i)throw Error('Method "'+c[g]+'" does not exist');var j=g.match(W),m=j[1],j=j[2],i=n.bind(i,this),m=m+(".delegateEvents"+this.cid);if(""===j)this.$el.on(m,i);else this.$el.on(m,j,i)}}},undelegateEvents:function(){this.$el.off(".delegateEvents"+this.cid)},_configure:function(c){this.options&&(c=n.extend({},n.result(this,"options"),c));n.extend(this,n.pick(c,P));this.options=c},_ensureElement:function(){if(this.el)this.setElement(n.result(this,"el"),!1);else{var c=n.extend({},n.result(this,"attributes")); +this.id&&(c.id=n.result(this,"id"));this.className&&(c["class"]=n.result(this,"className"));this.setElement(g.$("<"+n.result(this,"tagName")+">").attr(c),!1)}}});var $={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};g.sync=function(c,i,j){var m=$[c];n.defaults(j||(j={}),{emulateHTTP:g.emulateHTTP,emulateJSON:g.emulateJSON});var q={type:m,dataType:"json"};j.url||(q.url=n.result(i,"url")||M());if(null==j.data&&i&&("create"===c||"update"===c||"patch"===c))q.contentType="application/json", +q.data=JSON.stringify(j.attrs||i.toJSON(j));j.emulateJSON&&(q.contentType="application/x-www-form-urlencoded",q.data=q.data?{model:q.data}:{});if(j.emulateHTTP&&("PUT"===m||"DELETE"===m||"PATCH"===m)){q.type="POST";j.emulateJSON&&(q.data._method=m);var r=j.beforeSend;j.beforeSend=function(c){c.setRequestHeader("X-HTTP-Method-Override",m);if(r)return r.apply(this,arguments)}}"GET"!==q.type&&!j.emulateJSON&&(q.processData=!1);var u=j.success;j.success=function(c){u&&u(i,c,j);i.trigger("sync",i,c,j)}; +var f=j.error;j.error=function(c){f&&f(i,c,j);i.trigger("error",i,c,j)};c=j.xhr=g.ajax(n.extend(q,j));i.trigger("request",i,c,j);return c};g.ajax=function(){return g.$.ajax.apply(g.$,arguments)};E.extend=K.extend=F.extend=V.extend=G.extend=function(c,g){var i=this,j;j=c&&n.has(c,"constructor")?c.constructor:function(){return i.apply(this,arguments)};n.extend(j,i,g);var m=function(){this.constructor=j};m.prototype=i.prototype;j.prototype=new m;c&&n.extend(j.prototype,c);j.__super__=i.prototype;return j}; +var M=function(){throw Error('A "url" property or function must be specified');}}).call(this); diff --git a/src/core/classes/org/glizycms/js/visualsearch/dependencies.js.gz b/src/core/classes/org/glizycms/js/visualsearch/dependencies.js.gz new file mode 100755 index 0000000000000000000000000000000000000000..535e957f9a2850f9b3f6ca66bfd6ceb5da5cc7a7 GIT binary patch literal 53610 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 XOY?c2%`ie!BR0(s5L?W&YiR-i(Qcw0 literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/visualsearch/search_glyph.png b/src/core/classes/org/glizycms/js/visualsearch/search_glyph.png new file mode 100755 index 0000000000000000000000000000000000000000..017a6d0105ede9a7e5e9fa93b9f0333d60a32551 GIT binary patch literal 420 zcmV;V0bBlwP)<h;3K|Lk000e1NJLTq000aC000aK0ssI2*%!;O0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUzMoC0LRCwA{P|d1>U=YnO4T(q#%`z7) zlor(si1Y?MK=hXO1U*73;=+<p5EW}xWcGKub}!sn%r|pp&dm9SD$DYGKHIjv-|yo% z9t;Mms!k>oj^k>-Mx9Ql&1T~`4n<L~*Q-Kjv)Oz;=Xt(LY3Ii<0PNv#7)6omx)|K; zb`8V$Hu=7fXF8ptiD8&dr$Y$AUf{Z}BSw{^X^KbFG?rx>jRrhoAW4!`+u?~QicoVn z9P0HtAb7+GBuT28P$i?$2+4N4wJfVB3V6goWLZY}t7$wQACE`R^TIHMg6H%3p%Sv& z?VzdEYJG-*jrEWj1OfE*dObx^km59gAgop^^nGrFdtNS=$K!Fo-|<0Ek*?S4JkP;d zE|)Z#Xqs-f+kcnDx@NPvSS(D_yk4)j+l{J3)czYljL)(R%znTB7GMAlw6;F0t2}7{ O0000<MNUMnLSTZs+`J6{ literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/visualsearch/visualsearch-datauri.css b/src/core/classes/org/glizycms/js/visualsearch/visualsearch-datauri.css new file mode 100755 index 0000000..6e99ceb --- /dev/null +++ b/src/core/classes/org/glizycms/js/visualsearch/visualsearch-datauri.css @@ -0,0 +1 @@ +.VS-search .VS-icon{background-repeat:no-repeat;background-position:center center;vertical-align:middle;width:16px;height:16px}.VS-search .VS-icon-cancel{width:11px;height:11px;background-position:center 0;background-image:url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAWCAYAAAAW5GZjAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAb9JREFUeNqUUr1qAkEQ3j0khQp6kihaeGgEEa18gTQR0iRY+BaBSMDGwidIEUKqFL6BopgqBAJ5AMFGjUU0d4WHEvwJarvZ77gRIzGYgb1hZr+Z75vZ40IIzqTNZrPj8Xicn0wmmcViEXS73aaqqq+BQODG6/W+A8MBNk3zfDAY3C6Xy0O2ZS6X6zMSiVwHg8FHLjtq7Xb7RQKj7BeTzVCgJ5PJU2U0GhUk7REuMpkMi8fjFggeMeecrVYrFRId0CgTAgDDMFg4HLbA8IjJgHNgGEr0er0fQIphUmZAwdSUADUB4RFDsz3oSMF6CLzZkQqgGebz+Z75dDqNdTqdp13bgDmdTj2VSp0oWHg0Gr2UNH2Z/9o+yMv7K4/HY/C/XhDUfr//jl7QQVT9fp/V63VWqVRYt9tliUSCZbPZg1wux9Lp9PqFeK1Wu9A0DdXz7YM87i0FrVZLs4Fi1wmFQh/NZjOmVKvVgq7rR/QflMtlixGedjwcDlUpMQ9tbzalkAAB2/R297mNW+sT2wUbUnA//V/nYrH4QOBNABUQuFQq3TNMuc82sDVrz41G42yvPeODAwZQ0QzwiJEnzLcAAwBJ6WXlwoBgZAAAAABJRU5ErkJggg==");cursor:pointer}.VS-search .VS-icon-cancel:hover{background-position:center -11px}.VS-search .VS-icon-search{width:12px;height:12px;background-image:url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAUZJREFUeNpUUM2qgmAQzS8NiUgLzTIXLZQW1QuI9AY9QPSW9gQ9QiriwpJQEBVrVWT2d7p2L9xZzDdzZs7M+YYqy/J8Ptu2vd/v4zgeDAaqqk4mE47jar9GnU6nzWbjOA5FUa/Xq0Jns9l8Pud5vkpp58cwAOzhcBhFkeu6GNztdg3D+Db5vo9nOp2iiWGYTqdDCMFe4LquI0aVpGmKR9M0lmUbjQY8YiBJklTb4YkoilBzOBzq9TogeMQIJEmqmlAlo9EIyXa7tSyrKAp4xEBkWUb5q2k8Hh+PR8/zwjCEgufz+aESstvtoKnVan2GgY31kBkEAfT1ej1FUZDiNIIgrFYr9H1ug3teLpfH43G/3/FBUJGu1+s8z8FZLpc0mmiabrfbf5fEumazuVgsTNO8Xq+3242qRNT+G0CMz7IMzH6//xZgAA60tj6rqzxpAAAAAElFTkSuQmCC")}.VS-search div,.VS-search span,.VS-search a,.VS-search img,.VS-search ul,.VS-search li,.VS-search form,.VS-search label,.VS-interface ul,.VS-interface li,.VS-interface{margin:0;padding:0;border:0;outline:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline}.VS-search :focus{outline:0}.VS-search{line-height:1;color:black}.VS-search ol,.VS-search ul{list-style:none}.VS-search{font-family:Arial,sans-serif;color:#373737;font-size:12px}.VS-search input{display:block;border:none;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none;outline:none;margin:0;padding:4px;background:transparent;font-size:16px;line-height:20px;width:100%}.VS-interface,.VS-search .dialog,.VS-search input{font-family:"Lucida Grande","Lucida Sans Unicode",Helvetica,Arial,sans-serif!important;line-height:1.1em}.VS-search .VS-search-box{cursor:text;position:relative;background:transparent;border:2px solid #ccc;border-radius:16px;-webkit-border-radius:16px;-moz-border-radius:16px;background-color:#fafafa;-webkit-box-shadow:inset 0 0 3px #ccc;-moz-box-shadow:inset 0 0 3px #ccc;box-shadow:inset 0 0 3px #ccc;min-height:28px;height:auto}.VS-search .VS-search-box.VS-focus{border-color:#acf;-webkit-box-shadow:inset 0 0 3px #acf;-moz-box-shadow:inset 0 0 3px #acf;box-shadow:inset 0 0 3px #acf}.VS-search .VS-placeholder{position:absolute;top:7px;left:4px;margin:0 20px 0 22px;color:#808080;font-size:14px}.VS-search .VS-search-box.VS-focus .VS-placeholder,.VS-search .VS-search-box .VS-placeholder.VS-hidden{display:none}.VS-search .VS-search-inner{position:relative;margin:0 20px 0 22px;overflow:hidden}.VS-search input{width:100px}.VS-search input,.VS-search .VS-input-width-tester{padding:6px 0;float:left;color:#808080;font:13px/17px Helvetica,Arial}.VS-search.VS-focus input{color:#606060}.VS-search .VS-icon-search{position:absolute;left:9px;top:8px}.VS-search .VS-icon-cancel{position:absolute;right:9px;top:8px}.VS-search .search_facet{float:left;margin:0;padding:0 0 0 14px;position:relative;border:1px solid transparent;height:20px;margin:3px -3px 3px 0}.VS-search .search_facet.is_selected{margin-left:-3px;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px;background-color:#d2e6fd;background-image:-moz-linear-gradient(top,#d2e6fd,#b0d1f9);background-image:-webkit-gradient(linear,left top,left bottom,from(#d2e6fd),to(#b0d1f9));background-image:linear-gradient(top,#d2e6fd,#b0d1f9);border:1px solid #6eadf5}.VS-search .search_facet .category{float:left;text-transform:uppercase;font-weight:bold;font-size:10px;color:#808080;padding:8px 0 5px;line-height:13px;cursor:pointer;padding:4px 0 0}.VS-search .search_facet.is_selected .category{margin-left:3px}.VS-search .search_facet .search_facet_input_container{float:left}.VS-search .search_facet input{margin:0;padding:0;color:#000;font-size:13px;line-height:16px;padding:5px 0 5px 4px;height:16px;width:auto;z-index:100;position:relative;padding-top:1px;padding-bottom:2px;padding-right:3px}.VS-search .search_facet.is_editing input,.VS-search .search_facet.is_selected input{color:#000}.VS-search .search_facet .search_facet_remove{position:absolute;left:0;top:4px}.VS-search .search_facet.is_selected .search_facet_remove{opacity:.4;left:3px;filter:alpha(opacity=40);background-position:center -11px}.VS-search .search_facet .search_facet_remove:hover{opacity:1}.VS-search .search_facet.is_editing .category,.VS-search .search_facet.is_selected .category{color:#000}.VS-search .search_facet.search_facet_maybe_delete .category,.VS-search .search_facet.search_facet_maybe_delete input{color:darkred}.VS-search .search_input{height:28px;float:left;margin-left:-1px}.VS-search .search_input input{padding:6px 3px 6px 2px;line-height:10px;height:22px;margin-top:-4px;width:10px;z-index:100;min-width:4px;position:relative}.VS-search .search_input.is_editing input{color:#202020}.ui-helper-hidden-accessible{display:none}.VS-interface.ui-autocomplete{position:absolute;border:1px solid #c0c0c0;border-top:1px solid #d9d9d9;background-color:#f6f6f6;cursor:pointer;z-index:10000;padding:0;margin:0;width:auto;min-width:80px;max-width:220px;max-height:240px;overflow-y:auto;overflow-x:hidden;font-size:13px;top:5px;opacity:.97;box-shadow:3px 4px 5px -2px rgba(0,0,0,0.5);-webkit-box-shadow:3px 4px 5px -2px rgba(0,0,0,0.5);-moz-box-shadow:3px 4px 5px -2px rgba(0,0,0,0.5)}.VS-interface.ui-autocomplete .ui-autocomplete-category{text-transform:capitalize;font-size:11px;padding:4px 4px 4px;border-top:1px solid #a2a2a2;border-bottom:1px solid #a2a2a2;background-color:#b7b7b7;text-shadow:0 -1px 0 #999;font-weight:bold;color:white;cursor:default}.VS-interface.ui-autocomplete .ui-menu-item{float:none}.VS-interface.ui-autocomplete .ui-menu-item a{color:#000;outline:none;display:block;padding:3px 4px 5px;border-radius:none;line-height:1;background-color:#f8f8f8;background-image:-moz-linear-gradient(top,#f8f8f8,#f3f3f3);background-image:-webkit-gradient(linear,left top,left bottom,from(#f8f8f8),to(#f3f3f3));background-image:linear-gradient(top,#f8f8f8,#f3f3f3);border-top:1px solid #fafafa;border-bottom:1px solid #f0f0f0}.VS-interface.ui-autocomplete .ui-menu-item a:active{outline:none}.VS-interface.ui-autocomplete .ui-menu-item .ui-state-hover,.VS-interface.ui-autocomplete .ui-menu-item .ui-state-focus{background-color:#6483f7;background-image:-moz-linear-gradient(top,#648bf5,#2465f3);background-image:-webkit-gradient(linear,left top,left bottom,from(#648bf5),to(#2465f3));background-image:linear-gradient(top,#648bf5,#2465f3);border-top:1px solid #5b83ec;border-bottom:1px solid #1459e9;border-left:none;border-right:none;color:white;margin:0}.VS-interface.ui-autocomplete .ui-corner-all{border-radius:0}.VS-interface.ui-autocomplete li{list-style:none;width:auto} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/visualsearch/visualsearch-datauri.css.gz b/src/core/classes/org/glizycms/js/visualsearch/visualsearch-datauri.css.gz new file mode 100755 index 0000000000000000000000000000000000000000..2cbebca8838f3543e1cd94d54db68bb96a26afed GIT binary patch literal 2697 zcmV;43U>7$iwFP!%LY*b1FcwVlbTEu{VTpny;VuAtca+fl@GYySKUQLSH7eM7;u!E zTy$kC|NWT(bn&*?q>`zu%naT1boV*ka6g++J_Me+%-!Qlq&oJS0@StPIiaml9&{lH zYPOSJ)iZmp<D&pMc1?wL0KHuDQ{O@_Kq@dPU?Rh=SxD1NSl=NnSk{Ua_qD!+$XEvP z^{@NO$5Se>RcOAY62*)Jx&FWaI=hK1V8B}Fncu!>AON*^UT|%rt}cP+!{A34=oE)V zd{|-gXx4Zd@94*l;RyKOXd*3Jl0hzg@@M`aEaKmCM_!SO&dazx?~bPmBhwnw-pgX6 zA$NErPa1t?-nQjg-(1YcWmPrJXCk2R{c)=;!O=#Nyy8Y!x5UzlUN1$rvPMe)J4UMo zikvYO$21x*?i!#m88$oE3%!=~xM>e64aYS$4WVBahV9Nul4y;ccU#+CA9!22S~bSK zsIxGX;!^hR<Z5{<vvjW)ZKfmHdtPxbNVVymWvMgNdYM#90Bkm!yN3AG>{JT#JAoTE zM(a|fH-$y%q4Kh)pBQ;kd8tIh37YM?2G{NmR>7wFqEyG?<Eq+#(`fc!^vlnEiIM2e zQd(EXt#IhBhltZxZNq>=2vu*k@Y>^^Mn4!+!Du#zZG-I&6oKol`bKwTbXpz_Jz5ug z?ozU3VW&+bp(!=kal7e9C1)~hR~`nDycRb`2PzRcnbzElwCP53izUTqTH18Q%qA}F z%)18N@fc~;W#j_y-0g?k>LXj|E(#BYmt|AZy+UDSRz-0(<#o3(tCVK*&1}2~_`pQc z<Uv-RWuv$YU-^N{KX2Obu{aNTfo^IqQFSros)%lTGkM^%ZB*P@ZE;x`$*U)8_PCuH zo2oZ1h`Kq%x?Vd_TkX`QDY-+D50nU)Ye8r*g)zfdt<n6>pE5g1k!+z*m=)}W*JZ`0 z#z<&LV%QcprRiuGsvP4tXI{h>J1n!`KEtP`u#-hvjCQEsvZH}22)jnVGJi35PQ#E% zjtPzaSSq)?b>A?IA3wf)udAWwJ6_Fo5JAWXaH}mH4BWR5&_xmWUDc4x4}fJdfMrer z`_C}BBY%buLJ$8m<u(`Y{tA<loMO_Iq#?60EJ2JW+z3g=Ae#1G2C_IWieZlz7QFa8 zne&Foi^xMew=cFDGjBGZGFsJT2K=iWHML0gtHZm+VzV#wx#u8cwpwA!Mh0vO7;9_R zYO&Q7@c51`RqSZ4te%8&TLOib4c)hW-sGM`t-M{kZkbbe!c(+V8_V_@hLz4J3N)kC zylX1ut;5?-E`!j#v%nB&J`CHC9c;oL4Q6h~dK~jZ+O#BPB`&xHYV_CURACou2bqoN zsS$1Xse^$j_WCVrW0`{K@U7nd1yqB{-g^{W_O;bm&n2b2Vb)xCdG|c#3ej%$&@w_j zx&y6=A8Z5X(VhXD=@^Sraot$A1bteBt72P{n`qSQ8D4wg@!eu*lma+#^)6fL6iS75 zL+W?J;+@Y$Tw5NvDs5Q^D4wq9WxW+zAPQ%OKOH@BFPpm(!!n!kXnNP7ABIu2H;lTK zLg7`$(XY_Ks^V>;S2s@imf4=JC!uIPJbd|{O-~JN^O>pd0y{eg*$J|Y>@+m9GZSTJ zy5m_VyFh`-?J>l3pu&Uv`$DSXxbS8H&p>vKuDd|fkZs^A#ql)g;R`3k6k<bsr8{;& z?Gh{@dkH-hBx`=KH{sb5ieRls)BjJVI<SzrKi+aylnKDdGqV1w>5dxuZ^x%+_TI<} zbpUl;bxh1Diiv@pRp6MXKEzV~!BpEhdDvUlM!`eC%=^Ih@vevTRR7mfm5l7^m{S5m zwi^a-8uDEe?6EzLx;}W3Jg-h!PDClrE9EbN=IqkN9aPpRxL7}*AN&wcF2cp05L+$q zu=OtRFjHpjCEZTebqtLcQkuk(`gM{MS?Aqr*d@+MP9}%V`t8dgRFMX99sF<&e#sx^ z6KqRPvN1K2)h;x*ki<TJ?&tp@%XPc}V4F|kdtZdsInO7T#A$D7NeSR<P(RiP51JrA zTX@SUX;^RobG~CDE%#Mb)pV8efQCXpao2lzF1M0!UaV&dOqw}5Amdu7k&UZNj>e;e zO^J;-&yp**e7tKR`xs#Ez4(DJaBjPi%o4z*CrV8Rs{RSP<GVh#o80o@?zwFkL@Hc5 zCN}2n7+0X+aD@S^2aa2-l5~c85NH1Z5;>C8SS>?peR>FvCL@ak_Of-j;)`=T@;61! z?<CVDe$#;Vkq^!&C#wM2cJ`3R<h^<((iiC_c44Cbl7NnYzQRuDCx{oRSb_?m9}qKA zN~w@X*71|@`xf!?6=&9pICzC3jzjJY)|m&tdowXFRa2qK_^5xo40;@F9{YeqpZoZA z?NZu{VQ@=4`Ta?l57XNFsV^&IoV6r_uF*}xE5#$PWJxE>x~W={{1o{^{?j)Nx<~#` zTp^(vKrOA+RO}2Q`&S(G8QRhqSkbl1hB;PBC>nT_K~&(weZxM@rxN+E3au4&{`(ct z)YPL`q9#uclOrnP3&jZn$I9!TV|`0?e$NNaw}aj*ia%%0d33&3Akg&kO~2>vRS-bK z@%Gu2Af<+i1528(TIjmaQ*j4#(jO_92TnSn3pzR^6c=N=d{&zYw9a0avelj>;iu9i zbA)W-ls-uR)7j4$wm&hn0)Plly?f%eh6L(Yy2{iAG<`zHrSrp+gggk95B|xqr(bK* z)`b+ddW5M=gRg}4uD~)?MG@c^-&IpdqLDV>xRkKONA4lsg&KZ>ZCoMMn{hZ{KYaer zy5EBqru<uMNXKNx{>I$*WVoi<ae<10eeIsDA9ACvBNJy_4Vdl{d`oZm!P4LBfAmKF z+he7#`3DP%pK|&!qw{|VfKNF8)JO~L75G!bngaNl$KDpsMqdNo+Jo9P8<N|y-P=Ve zN{Ro5t78S})3TME)EDy0oFk2X$5h;2qz@rkMX{OJ1ALjq7-=$-t*eFbrfC=8IRu5F z$@q02B5az888z*nD4?p)_mN`4%U0_6vO>fN52%ji5`SNT%O&}%G#Q6lm~z8mQ{&0F z*34JPIH%@}Z|E%F9VsxwRqwvzl2+g~oifZ}euxN5XF5J=pU5BQuW1i>PNn21q@Ems z%~!L%cPXLLm{KY73gj6I_(tdBabNy^t>OQ@%vt;YJAsemmpfmejvzj(zAA8008D)L ztQRsQA6Lut|BYA!hK$2zS`@DAU*v*PB_nAF(sR=}0!>`7zVbYO*%2gyyCuRInWm5i zbr71tCmdoyJEX9rmDb?j<KR>*2Qn0R`bFXNtHr@}nIN9EjIq$^XP7Hc;mG)t1~QSr zza=vMO#_+eOd7~k?`Ipx3v;ffPx^X)GktWLj6Vxh4XA`i-?BmaBMoHc2N*O|Tw?Qo zC!2l}xQJ|p<w|<>Pa=yY6uq4P%CMF4zlv<4Gl^`f_p_0`Fz0Gy%L-S5>g~uD*)k9L z!+u<t(~oxvR$^qtD_PthYQiVtsX88RxhY_pZ>RYCov?|{KX+y-(69dhcO!z!W*q<k DBZo|b literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/visualsearch/visualsearch.css b/src/core/classes/org/glizycms/js/visualsearch/visualsearch.css new file mode 100755 index 0000000..46f61e0 --- /dev/null +++ b/src/core/classes/org/glizycms/js/visualsearch/visualsearch.css @@ -0,0 +1 @@ +.VS-search .VS-icon{background-repeat:no-repeat;background-position:center center;vertical-align:middle;width:16px;height:16px}.VS-search .VS-icon-cancel{width:11px;height:11px;background-position:center 0;background-image:url(cancel_search.png?1311104738);cursor:pointer}.VS-search .VS-icon-cancel:hover{background-position:center -11px}.VS-search .VS-icon-search{width:12px;height:12px;background-image:url(search_glyph.png?1311104738)}.VS-search div,.VS-search span,.VS-search a,.VS-search img,.VS-search ul,.VS-search li,.VS-search form,.VS-search label,.VS-interface ul,.VS-interface li,.VS-interface{margin:0;padding:0;border:0;outline:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline}.VS-search :focus{outline:0}.VS-search{line-height:1;color:black}.VS-search ol,.VS-search ul{list-style:none}.VS-search{font-family:Arial,sans-serif;color:#373737;font-size:12px}.VS-search input{display:block;border:none;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none;outline:none;margin:0;padding:4px;background:transparent;font-size:16px;line-height:20px;width:100%}.VS-interface,.VS-search .dialog,.VS-search input{font-family:"Lucida Grande","Lucida Sans Unicode",Helvetica,Arial,sans-serif!important;line-height:1.1em}.VS-search .VS-search-box{cursor:text;position:relative;background:transparent;border:2px solid #ccc;border-radius:16px;-webkit-border-radius:16px;-moz-border-radius:16px;background-color:#fafafa;-webkit-box-shadow:inset 0 0 3px #ccc;-moz-box-shadow:inset 0 0 3px #ccc;box-shadow:inset 0 0 3px #ccc;min-height:28px;height:auto}.VS-search .VS-search-box.VS-focus{border-color:#acf;-webkit-box-shadow:inset 0 0 3px #acf;-moz-box-shadow:inset 0 0 3px #acf;box-shadow:inset 0 0 3px #acf}.VS-search .VS-placeholder{position:absolute;top:7px;left:4px;margin:0 20px 0 22px;color:#808080;font-size:14px}.VS-search .VS-search-box.VS-focus .VS-placeholder,.VS-search .VS-search-box .VS-placeholder.VS-hidden{display:none}.VS-search .VS-search-inner{position:relative;margin:0 20px 0 22px;overflow:hidden}.VS-search input{width:100px}.VS-search input,.VS-search .VS-input-width-tester{padding:6px 0;float:left;color:#808080;font:13px/17px Helvetica,Arial}.VS-search.VS-focus input{color:#606060}.VS-search .VS-icon-search{position:absolute;left:9px;top:8px}.VS-search .VS-icon-cancel{position:absolute;right:9px;top:8px}.VS-search .search_facet{float:left;margin:0;padding:0 0 0 14px;position:relative;border:1px solid transparent;height:20px;margin:3px -3px 3px 0}.VS-search .search_facet.is_selected{margin-left:-3px;-webkit-border-radius:16px;-moz-border-radius:16px;border-radius:16px;background-color:#d2e6fd;background-image:-moz-linear-gradient(top,#d2e6fd,#b0d1f9);background-image:-webkit-gradient(linear,left top,left bottom,from(#d2e6fd),to(#b0d1f9));background-image:linear-gradient(top,#d2e6fd,#b0d1f9);border:1px solid #6eadf5}.VS-search .search_facet .category{float:left;text-transform:uppercase;font-weight:bold;font-size:10px;color:#808080;padding:8px 0 5px;line-height:13px;cursor:pointer;padding:4px 0 0}.VS-search .search_facet.is_selected .category{margin-left:3px}.VS-search .search_facet .search_facet_input_container{float:left}.VS-search .search_facet input{margin:0;padding:0;color:#000;font-size:13px;line-height:16px;padding:5px 0 5px 4px;height:16px;width:auto;z-index:100;position:relative;padding-top:1px;padding-bottom:2px;padding-right:3px}.VS-search .search_facet.is_editing input,.VS-search .search_facet.is_selected input{color:#000}.VS-search .search_facet .search_facet_remove{position:absolute;left:0;top:4px}.VS-search .search_facet.is_selected .search_facet_remove{opacity:.4;left:3px;filter:alpha(opacity=40);background-position:center -11px}.VS-search .search_facet .search_facet_remove:hover{opacity:1}.VS-search .search_facet.is_editing .category,.VS-search .search_facet.is_selected .category{color:#000}.VS-search .search_facet.search_facet_maybe_delete .category,.VS-search .search_facet.search_facet_maybe_delete input{color:darkred}.VS-search .search_input{height:28px;float:left;margin-left:-1px}.VS-search .search_input input{padding:6px 3px 6px 2px;line-height:10px;height:22px;margin-top:-4px;width:10px;z-index:100;min-width:4px;position:relative}.VS-search .search_input.is_editing input{color:#202020}.ui-helper-hidden-accessible{display:none}.VS-interface.ui-autocomplete{position:absolute;border:1px solid #c0c0c0;border-top:1px solid #d9d9d9;background-color:#f6f6f6;cursor:pointer;z-index:10000;padding:0;margin:0;width:auto;min-width:80px;max-width:220px;max-height:240px;overflow-y:auto;overflow-x:hidden;font-size:13px;top:5px;opacity:.97;box-shadow:3px 4px 5px -2px rgba(0,0,0,0.5);-webkit-box-shadow:3px 4px 5px -2px rgba(0,0,0,0.5);-moz-box-shadow:3px 4px 5px -2px rgba(0,0,0,0.5)}.VS-interface.ui-autocomplete .ui-autocomplete-category{text-transform:capitalize;font-size:11px;padding:4px 4px 4px;border-top:1px solid #a2a2a2;border-bottom:1px solid #a2a2a2;background-color:#b7b7b7;text-shadow:0 -1px 0 #999;font-weight:bold;color:white;cursor:default}.VS-interface.ui-autocomplete .ui-menu-item{float:none}.VS-interface.ui-autocomplete .ui-menu-item a{color:#000;outline:none;display:block;padding:3px 4px 5px;border-radius:none;line-height:1;background-color:#f8f8f8;background-image:-moz-linear-gradient(top,#f8f8f8,#f3f3f3);background-image:-webkit-gradient(linear,left top,left bottom,from(#f8f8f8),to(#f3f3f3));background-image:linear-gradient(top,#f8f8f8,#f3f3f3);border-top:1px solid #fafafa;border-bottom:1px solid #f0f0f0}.VS-interface.ui-autocomplete .ui-menu-item a:active{outline:none}.VS-interface.ui-autocomplete .ui-menu-item .ui-state-hover,.VS-interface.ui-autocomplete .ui-menu-item .ui-state-focus{background-color:#6483f7;background-image:-moz-linear-gradient(top,#648bf5,#2465f3);background-image:-webkit-gradient(linear,left top,left bottom,from(#648bf5),to(#2465f3));background-image:linear-gradient(top,#648bf5,#2465f3);border-top:1px solid #5b83ec;border-bottom:1px solid #1459e9;border-left:none;border-right:none;color:white;margin:0}.VS-interface.ui-autocomplete .ui-corner-all{border-radius:0}.VS-interface.ui-autocomplete li{list-style:none;width:auto} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/js/visualsearch/visualsearch.css.gz b/src/core/classes/org/glizycms/js/visualsearch/visualsearch.css.gz new file mode 100755 index 0000000000000000000000000000000000000000..b00a17989cdff90ff9d04f6d1ce4a71d4b3767a5 GIT binary patch literal 1687 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 literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/visualsearch/visualsearch.js b/src/core/classes/org/glizycms/js/visualsearch/visualsearch.js new file mode 100755 index 0000000..20bad19 --- /dev/null +++ b/src/core/classes/org/glizycms/js/visualsearch/visualsearch.js @@ -0,0 +1,67 @@ +/* + VisualSearch.js 0.4.0 + (c) 2011 Samuel Clay, @samuelclay, DocumentCloud Inc. + VisualSearch.js may be freely distributed under the MIT license. + For all details and documentation: + http://documentcloud.github.com/visualsearch +*/ +(function(){var c=jQuery;window.VS||(window.VS={});VS.app||(VS.app={});VS.ui||(VS.ui={});VS.model||(VS.model={});VS.utils||(VS.utils={});VS.VERSION="0.4.0";VS.VisualSearch=function(a){var b={container:"",query:"",autosearch:!0,unquotable:[],remainder:"text",showFacets:!0,callbacks:{search:c.noop,focus:c.noop,blur:c.noop,facetMatches:c.noop,valueMatches:c.noop}};this.options=_.extend({},b,a);this.options.callbacks=_.extend({},b.callbacks,a.callbacks);VS.app.hotkeys.initialize();this.searchQuery=new VS.model.SearchQuery; +this.searchBox=new VS.ui.SearchBox({app:this,showFacets:this.options.showFacets});a.container&&(a=this.searchBox.render().el,c(this.options.container).html(a));this.searchBox.value(this.options.query||"");c(window).bind("unload",function(){});return this};VS.init=function(a){return new VS.VisualSearch(a)}})(); +(function(){var c=jQuery;VS.ui.SearchBox=Backbone.View.extend({id:"search",events:{"click .VS-cancel-search-box":"clearSearch","mousedown .VS-search-box":"maybeFocusSearch","dblclick .VS-search-box":"highlightSearch","click .VS-search-box":"maybeTripleClick"},initialize:function(){this.app=this.options.app;this.flags={allSelected:!1};this.facetViews=[];this.inputViews=[];_.bindAll(this,"renderFacets","_maybeDisableFacets","disableFacets","deselectAllFacets","addedFacet","removedFacet","changedFacet"); +this.app.searchQuery.bind("reset",this.renderFacets).bind("add",this.addedFacet).bind("remove",this.removedFacet).bind("change",this.changedFacet);c(document).bind("keydown",this._maybeDisableFacets)},render:function(){c(this.el).append(JST.search_box({}));c(document.body).setMode("no","search");return this},value:function(a){return null==a?this.serialize():this.setQuery(a)},serialize:function(){var a=[],b=this.inputViews.length;this.app.searchQuery.each(_.bind(function(b,c){a.push(this.inputViews[c].value()); +a.push(b.serialize())},this));b&&a.push(this.inputViews[b-1].value());return _.compact(a).join(" ")},selected:function(){return _.select(this.facetViews,function(a){return"is"==a.modes.editing||"is"==a.modes.selected})},selectedModels:function(){return _.pluck(this.selected(),"model")},setQuery:function(a){this.currentQuery=a;VS.app.SearchParser.parse(this.app,a)},viewPosition:function(a){a=_.indexOf("facet"==a.type?this.facetViews:this.inputViews,a);-1==a&&(a=0);return a},searchEvent:function(a){var b= +this.value();this.focusSearch(a);this.value(b);this.app.options.callbacks.search(b,this.app.searchQuery)},addFacet:function(a,b,c){a=VS.utils.inflector.trim(a);b=VS.utils.inflector.trim(b||"");a&&this.app.searchQuery.add(new VS.model.SearchFacet({category:a,value:b||"",app:this.app}),{at:c})},addedFacet:function(a){this.renderFacets();var b=_.detect(this.facetViews,function(b){if(b.model==a)return!0});_.defer(function(){b.enableEdit()})},changedFacet:function(){this.renderFacets()},removedFacet:function(){}, +renderFacets:function(){this.facetViews=[];this.inputViews=[];this.$(".VS-search-inner").empty();this.app.searchQuery.each(_.bind(this.renderFacet,this));this.renderSearchInput();this.renderPlaceholder()},renderFacet:function(a,b){var c=new VS.ui.SearchFacet({app:this.app,model:a,order:b});this.renderSearchInput();this.facetViews.push(c);this.$(".VS-search-inner").children().eq(2*b).after(c.render().el);c.calculateSize();_.defer(_.bind(c.calculateSize,c));return c},renderSearchInput:function(){var a= +new VS.ui.SearchInput({position:this.inputViews.length,app:this.app,showFacets:this.options.showFacets});this.$(".VS-search-inner").append(a.render().el);this.inputViews.push(a)},renderPlaceholder:function(){var a=this.$(".VS-placeholder");this.app.searchQuery.length?a.addClass("VS-hidden"):a.removeClass("VS-hidden").text(this.app.options.placeholder)},clearSearch:function(a){var b=_.bind(function(){this.disableFacets();this.value("");this.flags.allSelected=!1;this.searchEvent(a);this.focusSearch(a)}, +this);this.app.options.callbacks.clearSearch?this.app.options.callbacks.clearSearch(b):b()},selectAllFacets:function(){this.flags.allSelected=!0;c(document).one("click.selectAllFacets",this.deselectAllFacets);_.each(this.facetViews,function(a){a.selectFacet()});_.each(this.inputViews,function(a){a.selectText()})},allSelected:function(a){a&&(this.flags.allSelected=!1);return this.flags.allSelected},deselectAllFacets:function(a){this.disableFacets();if(this.$(a.target).is(".category,input")){var b= +c(a.target).closest(".search_facet,.search_input"),g=_.detect(this.facetViews.concat(this.inputViews),function(a){return a.el==b[0]});"facet"==g.type?g.selectFacet():"input"==g.type&&_.defer(function(){g.enableEdit(!0)})}},disableFacets:function(a){_.each(this.inputViews,function(b){b&&b!=a&&("is"==b.modes.editing||"is"==b.modes.selected)&&b.disableEdit()});_.each(this.facetViews,function(b){if(b&&b!=a&&("is"==b.modes.editing||"is"==b.modes.selected))b.disableEdit(),b.deselectFacet()});this.flags.allSelected= +!1;this.removeFocus();c(document).unbind("click.selectAllFacets")},resizeFacets:function(a){_.each(this.facetViews,function(b){(!a||b==a)&&b.resize()})},_maybeDisableFacets:function(a){if(this.flags.allSelected&&"backspace"==VS.app.hotkeys.key(a))return a.preventDefault(),this.clearSearch(a),!1;this.flags.allSelected&&VS.app.hotkeys.printable(a)&&this.clearSearch(a)},focusNextFacet:function(a,b,c){var c=c||{},e=this.facetViews.length,d=c.viewPosition||this.viewPosition(a);if(c.skipToFacet){if(c.skipToFacet&& +"text"==a.type&&e==d&&0<=b)return!1}else"text"==a.type&&0<b&&(b-=1),"facet"==a.type&&0>b&&(b+=1);var f,d=Math.min(e,d+b);"text"==a.type?(0<=d&&d<e?f=this.facetViews[d]:d==e&&(f=this.inputViews[this.inputViews.length-1]),f&&c.selectFacet&&"facet"==f.type?f.selectFacet():f&&(f.enableEdit(),f.setCursorAtEnd(b||c.startAtEnd))):"facet"==a.type&&(c.skipToFacet?d>=e||0>d?(f=_.last(this.inputViews),f.enableEdit()):(f=this.facetViews[d],f.enableEdit(),f.setCursorAtEnd(b||c.startAtEnd)):(f=this.inputViews[d], +f.enableEdit()));c.selectText&&f.selectText();this.resizeFacets();return!0},maybeFocusSearch:function(a){(c(a.target).is(".VS-search-box")||c(a.target).is(".VS-search-inner")||"keydown"==a.type)&&this.focusSearch(a)},focusSearch:function(a,b){var c=this.inputViews[this.inputViews.length-1];c.enableEdit(b);b||c.setCursorAtEnd(-1);"keydown"==a.type&&(c.keydown(a),c.box.trigger("keydown"));_.defer(_.bind(function(){this.$("input:focus").length||c.enableEdit(b)},this))},highlightSearch:function(a){if(c(a.target).is(".VS-search-box")|| +c(a.target).is(".VS-search-inner")||"keydown"==a.type)this.inputViews[this.inputViews.length-1].startTripleClickTimer(),this.focusSearch(a,!0)},maybeTripleClick:function(a){return this.inputViews[this.inputViews.length-1].maybeTripleClick(a)},addFocus:function(){this.app.options.callbacks.focus();this.$(".VS-search-box").addClass("VS-focus")},removeFocus:function(){this.app.options.callbacks.blur();_.any(this.facetViews.concat(this.inputViews),function(a){return a.isFocused()})||this.$(".VS-search-box").removeClass("VS-focus")}, +showFacetCategoryMenu:function(a){a.preventDefault();a.stopPropagation();if(this.facetCategoryMenu&&"is"==this.facetCategoryMenu.modes.open)return this.facetCategoryMenu.close();a=[{title:"Account",onClick:_.bind(this.addFacet,this,"account","")},{title:"Project",onClick:_.bind(this.addFacet,this,"project","")},{title:"Filter",onClick:_.bind(this.addFacet,this,"filter","")},{title:"Access",onClick:_.bind(this.addFacet,this,"access","")}];a=this.facetCategoryMenu||(this.facetCategoryMenu=new dc.ui.Menu({items:a, +standalone:!0}));this.$(".VS-icon-search").after(a.render().open().content);return!1}})})(); +(function(){var c=jQuery;VS.ui.SearchFacet=Backbone.View.extend({type:"facet",className:"search_facet",events:{"click .category":"selectFacet","keydown input":"keydown","mousedown input":"enableEdit","mouseover .VS-icon-cancel":"showDelete","mouseout .VS-icon-cancel":"hideDelete","click .VS-icon-cancel":"remove"},initialize:function(){this.flags={canClose:!1};_.bindAll(this,"set","keydown","deselectFacet","deferDisableEdit")},render:function(){c(this.el).html(JST.search_facet({model:this.model})); +this.setMode("not","editing");this.setMode("not","selected");this.box=this.$("input");this.box.val(this.model.label());this.box.bind("blur",this.deferDisableEdit);this.box.bind("input propertychange",this.keydown);this.setupAutocomplete();return this},calculateSize:function(){this.box.autoGrowInput();this.box.unbind("updated.autogrow");this.box.bind("updated.autogrow",_.bind(this.moveAutocomplete,this))},resize:function(a){this.box.trigger("resize.autogrow",a)},setupAutocomplete:function(){this.box.autocomplete({source:_.bind(this.autocompleteValues, +this),minLength:0,delay:0,autoFocus:!0,position:{offset:"0 5"},create:_.bind(function(){c(this.el).find(".ui-autocomplete-input").css("z-index","auto")},this),select:_.bind(function(a,b){a.preventDefault();var c=this.model.get("value");this.set(b.item.value);if(c!=b.item.value||this.box.val()!=b.item.value)this.options.app.options.autosearch?this.search(a):(this.options.app.searchBox.renderFacets(),this.options.app.searchBox.focusNextFacet(this,1,{viewPosition:this.options.order}));return!1},this), +open:_.bind(function(){var a=this.box;this.box.autocomplete("widget").find(".ui-menu-item").each(function(){var b=c(this);(b.data("item.autocomplete")||b.data("ui-autocomplete-item")).value==a.val()&&a.data("uiAutocomplete").menu.activate&&a.data("uiAutocomplete").menu.activate(new c.Event("mouseover"),b)})},this)});this.box.autocomplete("widget").addClass("VS-interface")},moveAutocomplete:function(){var a=this.box.data("uiAutocomplete");a&&a.menu.element.position({my:"left top",at:"left bottom", +of:this.box.data("uiAutocomplete").element,collision:"flip",offset:"0 5"})},searchAutocomplete:function(){var a=this.box.data("uiAutocomplete");if(a){var b=a.menu.element;a.search();b.outerWidth(Math.max(b.width("").outerWidth(),a.element.outerWidth()))}},closeAutocomplete:function(){var a=this.box.data("uiAutocomplete");a&&a.close()},autocompleteValues:function(a,b){var g=this.model.get("category"),e=this.model.get("value"),d=a.term;this.options.app.options.callbacks.valueMatches(g,d,function(a, +g){g=g||{};a=a||[];if(d&&e!=d)if(g.preserveMatches)b(a);else var h=VS.utils.inflector.escapeRegExp(d||""),i=RegExp("\\b"+h,"i"),a=c.grep(a,function(a){return i.test(a)||i.test(a.value)||i.test(a.label)});g.preserveOrder?b(a):b(_.sortBy(a,function(a){return a==e||a.value==e?"":a}))})},set:function(a){a&&this.model.set({value:a})},search:function(a,b){b||(b=1);this.closeAutocomplete();this.options.app.searchBox.searchEvent(a);_.defer(_.bind(function(){this.options.app.searchBox.focusNextFacet(this, +b,{viewPosition:this.options.order})},this))},enableEdit:function(){"is"!=this.modes.editing&&(this.setMode("is","editing"),this.deselectFacet(),""==this.box.val()&&this.box.val(this.model.get("value")));this.flags.canClose=!1;this.options.app.searchBox.disableFacets(this);this.options.app.searchBox.addFocus();_.defer(_.bind(function(){this.options.app.searchBox.addFocus()},this));this.resize();this.searchAutocomplete();this.box.focus()},deferDisableEdit:function(){this.flags.canClose=!0;_.delay(_.bind(function(){this.flags.canClose&& +!this.box.is(":focus")&&"is"==this.modes.editing&&"is"!=this.modes.selected&&this.disableEdit()},this),250)},disableEdit:function(){var a=VS.utils.inflector.trim(this.box.val());a!=this.model.get("value")&&this.set(a);this.flags.canClose=!1;this.box.selectRange(0,0);this.box.blur();this.setMode("not","editing");this.closeAutocomplete();this.options.app.searchBox.removeFocus()},selectFacet:function(a){a&&a.preventDefault();var b=this.options.app.searchBox.allSelected();if("is"!=this.modes.selected){this.box.is(":focus")&& +(this.box.setCursorPosition(0),this.box.blur());this.flags.canClose=!1;this.closeAutocomplete();this.setMode("is","selected");this.setMode("not","editing");if(!b||a)c(document).unbind("keydown.facet",this.keydown),c(document).unbind("click.facet",this.deselectFacet),_.defer(_.bind(function(){c(document).unbind("keydown.facet").bind("keydown.facet",this.keydown);c(document).unbind("click.facet").one("click.facet",this.deselectFacet)},this)),this.options.app.searchBox.disableFacets(this),this.options.app.searchBox.addFocus(); +return!1}},deselectFacet:function(a){a&&a.preventDefault();"is"==this.modes.selected&&(this.setMode("not","selected"),this.closeAutocomplete(),this.options.app.searchBox.removeFocus());c(document).unbind("keydown.facet",this.keydown);c(document).unbind("click.facet",this.deselectFacet);return!1},isFocused:function(){return this.box.is(":focus")},showDelete:function(){c(this.el).addClass("search_facet_maybe_delete")},hideDelete:function(){c(this.el).removeClass("search_facet_maybe_delete")},setCursorAtEnd:function(a){-1== +a?this.box.setCursorPosition(this.box.val().length):this.box.setCursorPosition(0)},remove:function(a){var b=this.model.get("value");this.deselectFacet();this.disableEdit();this.options.app.searchQuery.remove(this.model);b&&this.options.app.options.autosearch?this.search(a,-1):(this.options.app.searchBox.renderFacets(),this.options.app.searchBox.focusNextFacet(this,-1,{viewPosition:this.options.order}))},selectText:function(){this.box.selectRange(0,this.box.val().length)},keydown:function(a){var b= +VS.app.hotkeys.key(a);if("enter"==b&&this.box.val())this.disableEdit(),this.search(a);else if("left"==b)"is"==this.modes.selected?(this.deselectFacet(),this.options.app.searchBox.focusNextFacet(this,-1,{startAtEnd:-1})):0==this.box.getCursorPosition()&&!this.box.getSelection().length&&this.selectFacet();else if("right"==b)"is"==this.modes.selected?(a.preventDefault(),this.deselectFacet(),this.setCursorAtEnd(0),this.enableEdit()):this.box.getCursorPosition()==this.box.val().length&&(a.preventDefault(), +this.disableEdit(),this.options.app.searchBox.focusNextFacet(this,1));else if(VS.app.hotkeys.shift&&"tab"==b)a.preventDefault(),this.options.app.searchBox.focusNextFacet(this,-1,{startAtEnd:-1,skipToFacet:!0,selectText:!0});else if("tab"==b)a.preventDefault(),this.options.app.searchBox.focusNextFacet(this,1,{skipToFacet:!0,selectText:!0});else{if(VS.app.hotkeys.command&&(97==a.which||65==a.which))return a.preventDefault(),this.options.app.searchBox.selectAllFacets(),!1;VS.app.hotkeys.printable(a)&& +"is"==this.modes.selected?(this.options.app.searchBox.focusNextFacet(this,-1,{startAtEnd:-1}),this.remove(a)):"backspace"==b&&("is"==this.modes.selected?(a.preventDefault(),this.remove(a)):0==this.box.getCursorPosition()&&!this.box.getSelection().length&&(a.preventDefault(),this.selectFacet()))}null==a.which?_.defer(_.bind(this.resize,this,a)):this.resize(a)}})})(); +(function(){var c=jQuery;VS.ui.SearchInput=Backbone.View.extend({type:"text",className:"search_input ui-menu",events:{"keypress input":"keypress","keydown input":"keydown","click input":"maybeTripleClick","dblclick input":"startTripleClickTimer"},initialize:function(){this.app=this.options.app;this.flags={canClose:!1};_.bindAll(this,"removeFocus","addFocus","moveAutocomplete","deferDisableEdit")},render:function(){c(this.el).html(JST.search_input({}));this.setMode("not","editing");this.setMode("not", +"selected");this.box=this.$("input");this.box.autoGrowInput();this.box.bind("updated.autogrow",this.moveAutocomplete);this.box.bind("blur",this.deferDisableEdit);this.box.bind("focus",this.addFocus);this.setupAutocomplete();return this},setupAutocomplete:function(){this.box.autocomplete({minLength:this.options.showFacets?0:1,delay:50,autoFocus:!0,position:{offset:"0 -1"},source:_.bind(this.autocompleteValues,this),create:_.bind(function(){c(this.el).find(".ui-autocomplete-input").css("z-index","auto")}, +this),select:_.bind(function(a,b){a.preventDefault();var c=this.options.position+(this.addTextFacetRemainder(b.item.value)?1:0);this.app.searchBox.addFacet(b.item instanceof String?b.item:b.item.value,"",c);return!1},this)});this.box.data("uiAutocomplete")._renderMenu=function(a,b){var c="";_.each(b,_.bind(function(b){b.category&&b.category!=c&&(a.append('<li class="ui-autocomplete-category">'+b.category+"</li>"),c=b.category);this._renderItemData?this._renderItemData(a,b):this._renderItem(a,b)}, +this))};this.box.autocomplete("widget").addClass("VS-interface")},autocompleteValues:function(a,b){var g=a.term.match(/\w+\*?$/),e=VS.utils.inflector.escapeRegExp(g&&g[0]||"");this.app.options.callbacks.facetMatches(function(a,g){var g=g||{},a=a||[],j=RegExp("^"+e,"i"),h=c.grep(a,function(a){return a&&j.test(a.label||a)});g.preserveOrder?b(h):b(_.sortBy(h,function(a){return a.label?a.category+"-"+a.label:a}))})},closeAutocomplete:function(){var a=this.box.data("uiAutocomplete");a&&a.close()},moveAutocomplete:function(){var a= +this.box.data("uiAutocomplete");a&&a.menu.element.position({my:"left top",at:"left bottom",of:this.box.data("uiAutocomplete").element,collision:"none",offset:"0 -1"})},searchAutocomplete:function(){var a=this.box.data("uiAutocomplete");if(a){var b=a.menu.element;a.search();b.outerWidth(Math.max(b.width("").outerWidth(),a.element.outerWidth()))}},addTextFacetRemainder:function(a){var b=this.box.val(),c=b.match(/\b(\w+)$/);if(!c)return"";0==a.search(RegExp(c[0],"i"))&&(b=b.replace(/\b(\w+)$/,""));(b= +b.replace("^s+|s+$",""))&&this.app.searchBox.addFacet(this.app.options.remainder,b,this.options.position);return b},enableEdit:function(a){this.addFocus();a&&this.selectText();this.box.focus()},addFocus:function(){this.flags.canClose=!1;this.app.searchBox.allSelected()||this.app.searchBox.disableFacets(this);this.app.searchBox.addFocus();this.setMode("is","editing");this.setMode("not","selected");this.app.searchBox.allSelected()||this.searchAutocomplete()},disableEdit:function(){this.box.blur();this.removeFocus()}, +removeFocus:function(){this.flags.canClose=!1;this.app.searchBox.removeFocus();this.setMode("not","editing");this.setMode("not","selected");this.closeAutocomplete()},deferDisableEdit:function(){this.flags.canClose=!0;_.delay(_.bind(function(){this.flags.canClose&&!this.box.is(":focus")&&"is"==this.modes.editing&&this.disableEdit()},this),250)},startTripleClickTimer:function(){this.tripleClickTimer=setTimeout(_.bind(function(){this.tripleClickTimer=null},this),500)},maybeTripleClick:function(a){if(this.tripleClickTimer)return a.preventDefault(), +this.app.searchBox.selectAllFacets(),!1},isFocused:function(){return this.box.is(":focus")},value:function(){return this.box.val()},setCursorAtEnd:function(a){-1==a?this.box.setCursorPosition(this.box.val().length):this.box.setCursorPosition(0)},selectText:function(){this.box.selectRange(0,this.box.val().length);this.app.searchBox.allSelected()?this.setMode("is","selected"):this.box.focus()},search:function(a,b){b||(b=0);this.closeAutocomplete();this.app.searchBox.searchEvent(a);_.defer(_.bind(function(){this.app.searchBox.focusNextFacet(this, +b)},this))},keypress:function(a){var b=VS.app.hotkeys.key(a);if("enter"==b)return this.search(a,100);if(VS.app.hotkeys.colon(a)){this.box.trigger("resize.autogrow",a);var b=this.box.val(),c=[];this.app.options.callbacks.facetMatches&&this.app.options.callbacks.facetMatches(function(a){c=a});var e=_.map(c,function(a){return a.label?a.label:a});if(_.contains(e,b))return a.preventDefault(),a=this.options.position+(this.addTextFacetRemainder(b)?1:0),this.app.searchBox.addFacet(b,"",a),!1}else if("backspace"== +b&&0==this.box.getCursorPosition()&&!this.box.getSelection().length)return a.preventDefault(),a.stopPropagation(),a.stopImmediatePropagation(),this.app.searchBox.resizeFacets(),!1},keydown:function(a){var b=VS.app.hotkeys.key(a);if("left"==b)0==this.box.getCursorPosition()&&(a.preventDefault(),this.app.searchBox.focusNextFacet(this,-1,{startAtEnd:-1}));else if("right"==b)this.box.getCursorPosition()==this.box.val().length&&(a.preventDefault(),this.app.searchBox.focusNextFacet(this,1,{selectFacet:!0})); +else if(VS.app.hotkeys.shift&&"tab"==b)a.preventDefault(),this.app.searchBox.focusNextFacet(this,-1,{selectText:!0});else if("tab"==b)if(b=this.box.val(),b.length){a.preventDefault();var c=this.addTextFacetRemainder(b),e=this.options.position+(c?1:0);b!=c&&this.app.searchBox.addFacet(b,"",e)}else this.app.searchBox.focusNextFacet(this,0,{skipToFacet:!0,selectText:!0})&&a.preventDefault();else{if(VS.app.hotkeys.command&&"a"==String.fromCharCode(a.which).toLowerCase())return a.preventDefault(),this.app.searchBox.selectAllFacets(), +!1;if("backspace"==b&&!this.app.searchBox.allSelected()){if(0==this.box.getCursorPosition()&&!this.box.getSelection().length)return a.preventDefault(),this.app.searchBox.focusNextFacet(this,-1,{backspace:!0}),!1}else"end"==b?(b=this.app.searchBox.inputViews[this.app.searchBox.inputViews.length-1],b.setCursorAtEnd(-1)):"home"==b&&(b=this.app.searchBox.inputViews[0],b.setCursorAtEnd(-1))}this.box.trigger("resize.autogrow",a)}})})(); +(function(){var c=jQuery;Backbone.View.prototype.setMode=function(a,b){this.modes||(this.modes={});this.modes[b]!==a&&(c(this.el).setMode(a,b),this.modes[b]=a)}})(); +(function(){var c=jQuery;VS.app.hotkeys={KEYS:{16:"shift",17:"command",91:"command",93:"command",224:"command",13:"enter",37:"left",38:"upArrow",39:"right",40:"downArrow",46:"delete",8:"backspace",35:"end",36:"home",9:"tab",188:"comma"},initialize:function(){_.bindAll(this,"down","up","blur");c(document).bind("keydown",this.down);c(document).bind("keyup",this.up);c(window).bind("blur",this.blur)},down:function(a){(a=this.KEYS[a.which])&&(this[a]=!0)},up:function(a){(a=this.KEYS[a.which])&&(this[a]= +!1)},blur:function(){for(var a in this.KEYS)this[this.KEYS[a]]=!1},key:function(a){return this.KEYS[a.which]},colon:function(a){return(a=a.which)&&":"==String.fromCharCode(a)},printable:function(a){var b=a.which;if("keydown"==a.type){if(32==b||48<=b&&90>=b||96<=b&&111>=b||186<=b&&192>=b||219<=b&&222>=b)return!0}else if(32<=b&&126>=b||160<=b&&500>=b||":"==String.fromCharCode(b))return!0;return!1}}})(); +(function(){VS.utils.inflector={trim:function(c){return c.trim?c.trim():c.replace(/^\s+|\s+$/g,"")},escapeRegExp:function(c){return c.replace(/([.*+?^${}()|[\]\/\\])/g,"\\$1")}}})(); +(function(){var c=jQuery;c.fn.extend({setMode:function(a,b){var b=b||"mode",c=RegExp("\\w+_"+b+"(\\s|$)","g"),e=null===a?"":a+"_"+b;this.each(function(){this.className=(this.className.replace(c,"")+" "+e).replace(/\s\s/g," ")});return e},autoGrowInput:function(){return this.each(function(){var a=c(this),b=c("<div />").css({opacity:0,top:-9999,left:-9999,position:"absolute",whiteSpace:"nowrap"}).addClass("VS-input-width-tester").addClass("VS-interface");a.next(".VS-input-width-tester").remove();a.after(b); +a.unbind("keydown.autogrow keypress.autogrow resize.autogrow change.autogrow").bind("keydown.autogrow keypress.autogrow resize.autogrow change.autogrow",function(c,e){e&&(c=e);var d=a.val();if("backspace"==VS.app.hotkeys.key(c)){var f=a.getCursorPosition();0<f&&(d=d.slice(0,f-1)+d.slice(f,d.length))}else VS.app.hotkeys.printable(c)&&!VS.app.hotkeys.command&&(d+=String.fromCharCode(c.which));d=d.replace(/&/g,"&amp;").replace(/\s/g,"&nbsp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");b.html(d);a.width(b.width()+ +3+parseInt(a.css("min-width")));a.trigger("updated.autogrow")});a.trigger("resize.autogrow")})},getCursorPosition:function(){var a=0,b=this.get(0);if(document.selection){b.focus();var a=document.selection.createRange(),g=document.selection.createRange().text.length;a.moveStart("character",-b.value.length);a=a.text.length-g}else b&&c(b).is(":visible")&&null!=b.selectionStart&&(a=b.selectionStart);return a},setCursorPosition:function(a){return this.each(function(){return c(this).selectRange(a,a)})}, +selectRange:function(a,b){return this.filter(":visible").each(function(){if(this.setSelectionRange)this.focus(),this.setSelectionRange(a,b);else if(this.createTextRange){var c=this.createTextRange();c.collapse(!0);c.moveEnd("character",b);c.moveStart("character",a);0<=b-a&&c.select()}})},getSelection:function(){var a=this[0];if(null!=a.selectionStart){var b=a.selectionStart,c=a.selectionEnd;return{start:b,end:c,length:c-b,text:a.value.substr(b,c-b)}}if(document.selection){var e=document.selection.createRange(); +if(e)return a=a.createTextRange(),b=a.duplicate(),a.moveToBookmark(e.getBookmark()),b.setEndPoint("EndToStart",a),b=b.text.length,c=b+e.text.length,{start:b,end:c,length:c-b,text:e.text}}return{start:0,end:0,length:0}}})})(); +(function(){VS.app.SearchParser={ALL_FIELDS:RegExp("('[^']+'|\"[^\"]+\"|[^'\"\\s]\\S*):\\s*('[^']+'|\"[^\"]+\"|[^'\"\\s]\\S*)","g"),CATEGORY:/('[^']+'|"[^"]+"|[^'"\s]\S*):\s*/,parse:function(c,a){var b=this._extractAllFacets(c,a);c.searchQuery.reset(b);return b},_extractAllFacets:function(c,a){for(var b=[],g=a;a;){var e,d,g=a,f=this._extractNextField(a);f?-1!=f.indexOf(":")?(e=f.match(this.CATEGORY)[1].replace(/(^['"]|['"]$)/g,""),d=f.replace(this.CATEGORY,"").replace(/(^['"]|['"]$)/g,""),a=VS.utils.inflector.trim(a.replace(f, +""))):-1==f.indexOf(":")&&(e=c.options.remainder,d=f,a=VS.utils.inflector.trim(a.replace(d,""))):(e=c.options.remainder,d=this._extractSearchText(a),a=VS.utils.inflector.trim(a.replace(d,"")));e&&d&&(f=new VS.model.SearchFacet({category:e,value:VS.utils.inflector.trim(d),app:c}),b.push(f));if(g==a)break}return b},_extractNextField:function(c){var a=c.match(/^\s*(\S+)\s+(?=('[^']+'|"[^"]+")('[^']+'|"[^"]+"|[^'"\s]\S*))/);return a&&1<=a.length?a[1]:this._extractFirstField(c)},_extractFirstField:function(c){return(c= +c.match(this.ALL_FIELDS))&&c.length&&c[0]},_extractSearchText:function(c){return VS.utils.inflector.trim((c||"").replace(this.ALL_FIELDS,""))}}})(); +(function(){VS.model.SearchFacet=Backbone.Model.extend({serialize:function(){var c=this.quoteCategory(this.get("category")),a=VS.utils.inflector.trim(this.get("value")),b=this.get("app").options.remainder;if(!a)return"";if(!_.contains(this.get("app").options.unquotable||[],c)&&c!=b)a=this.quoteValue(a);return(c!=b?c+": ":"")+a},quoteCategory:function(c){var a=/"/.test(c),b=/'/.test(c),g=/\s/.test(c);return a&&!b?"'"+c+"'":g||b&&!a?'"'+c+'"':c},quoteValue:function(c){var a=/"/.test(c),b=/'/.test(c); +return a&&!b?"'"+c+"'":'"'+c+'"'},label:function(){return this.get("label")||this.get("value")}})})(); +(function(){VS.model.SearchQuery=Backbone.Collection.extend({model:VS.model.SearchFacet,serialize:function(){return this.map(function(c){return c.serialize()}).join(" ")},facets:function(){return this.map(function(c){var a={};a[c.get("category")]=c.get("value");return a})},find:function(c){var a=this.detect(function(a){return a.get("category").toLowerCase()==c.toLowerCase()});return a&&a.get("value")},count:function(c){return this.select(function(a){return a.get("category").toLowerCase()==c.toLowerCase()}).length}, +values:function(c){var a=this.select(function(a){return a.get("category").toLowerCase()==c.toLowerCase()});return _.map(a,function(a){return a.get("value")})},has:function(c,a){return this.any(function(b){var g=b.get("category").toLowerCase()==c.toLowerCase();return!a?g:g&&b.get("value")==a})},withoutCategory:function(){var c=_.map(_.toArray(arguments),function(a){return a.toLowerCase()});return this.map(function(a){if(!_.include(c,a.get("category").toLowerCase()))return a.serialize()}).join(" ")}})})(); +(function(){window.JST=window.JST||{};window.JST.search_box=_.template('<div class="VS-search">\n <div class="VS-search-box-wrapper VS-search-box">\n <div class="VS-icon VS-icon-search"></div>\n <div class="VS-placeholder"></div>\n <div class="VS-search-inner"></div>\n <div class="VS-icon VS-icon-cancel VS-cancel-search-box" title="clear search"></div>\n </div>\n</div>');window.JST.search_facet=_.template('<% if (model.has(\'category\')) { %>\n <div class="category"><%= model.get(\'category\') %>:</div>\n<% } %>\n\n<div class="search_facet_input_container">\n <input type="text" class="search_facet_input ui-menu VS-interface" value="" />\n</div>\n\n<div class="search_facet_remove VS-icon VS-icon-cancel"></div>'); +window.JST.search_input=_.template('<input type="text" class="ui-menu" />')})(); diff --git a/src/core/classes/org/glizycms/js/visualsearch/visualsearch.js.gz b/src/core/classes/org/glizycms/js/visualsearch/visualsearch.js.gz new file mode 100755 index 0000000000000000000000000000000000000000..cd4f45ee634fe8c1c214af20ca392680df837e77 GIT binary patch literal 7307 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 literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/js/visualsearch/visualsearch_templates.js b/src/core/classes/org/glizycms/js/visualsearch/visualsearch_templates.js new file mode 100755 index 0000000..01b2487 --- /dev/null +++ b/src/core/classes/org/glizycms/js/visualsearch/visualsearch_templates.js @@ -0,0 +1,2 @@ +(function(){window.JST=window.JST||{};window.JST.search_box=_.template('<div class="VS-search">\n <div class="VS-search-box-wrapper VS-search-box">\n <div class="VS-icon VS-icon-search"></div>\n <div class="VS-placeholder"></div>\n <div class="VS-search-inner"></div>\n <div class="VS-icon VS-icon-cancel VS-cancel-search-box" title="clear search"></div>\n </div>\n</div>');window.JST.search_facet=_.template('<% if (model.has(\'category\')) { %>\n <div class="category"><%= model.get(\'category\') %>:</div>\n<% } %>\n\n<div class="search_facet_input_container">\n <input type="text" class="search_facet_input ui-menu VS-interface" value="" />\n</div>\n\n<div class="search_facet_remove VS-icon VS-icon-cancel"></div>'); +window.JST.search_input=_.template('<input type="text" class="ui-menu" />')})(); diff --git a/src/core/classes/org/glizycms/js/visualsearch/visualsearch_templates.js.gz b/src/core/classes/org/glizycms/js/visualsearch/visualsearch_templates.js.gz new file mode 100755 index 0000000000000000000000000000000000000000..8f36a3fb5bbfa026c81b04321fda2fc41fbfb318 GIT binary patch literal 326 zcmV-M0lEGkiwFS!$_7ya1BH=IZi6roh4($h2nhiT$i59dK)0#7iiBJ<Nh}!~nSmrC z+`SXXAA+PSkH_!Ld_2NUZ6qmc!l>OVliPjrwfau)<>}ORANOlgp>T4S{n|sCC4@z( z1z{L0bJc*<qN-BwXB7`B?{jScW}jjn5bvEROLQ>m4yK7sNo(M8-o`H%ESlFdm&Bdb zIl7m+%VK5BKf)1!6h@*xUx(_EA4rkL)RUTfFh#vq!x=;~>28>v#`*f7HV_szN1g0M z6|Mux4_oVw>mZ7t1%DFuRlv*r6b9=SX>4WR`;EwluAjr@!<<K`OqsH#j58pi`pEjN zeHZ9h@^=#+$b0UETEzvLy3f)Oy7QX{jnFllJy_hLdCB3hunofekGaOp;l54N?J>sb YKIOl_p0R?ci$Wgw2b|sb!7~E@0HTkh#Q*>R literal 0 HcmV?d00001 diff --git a/src/core/classes/org/glizycms/languages/controllers/Delete.php b/src/core/classes/org/glizycms/languages/controllers/Delete.php new file mode 100644 index 0000000..bafdc49 --- /dev/null +++ b/src/core/classes/org/glizycms/languages/controllers/Delete.php @@ -0,0 +1,14 @@ +<?php +class org_glizycms_languages_controllers_Delete extends org_glizy_mvc_core_Command +{ + public function executeLater($id) + { +// TODO controllo ACL + if ($id) { + $proxy = org_glizy_objectFactory::createObject('org.glizycms.languages.models.proxy.LanguagesProxy'); + $proxy->delete($id); + + org_glizy_helpers_Navigation::goHere(); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/languages/controllers/Edit.php b/src/core/classes/org/glizycms/languages/controllers/Edit.php new file mode 100644 index 0000000..46413ca --- /dev/null +++ b/src/core/classes/org/glizycms/languages/controllers/Edit.php @@ -0,0 +1,4 @@ +<?php +class org_glizycms_languages_controllers_Edit extends org_glizycms_contents_controllers_activeRecordEdit_Edit +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/languages/controllers/ajax/Cancel.php b/src/core/classes/org/glizycms/languages/controllers/ajax/Cancel.php new file mode 100644 index 0000000..62cc0be --- /dev/null +++ b/src/core/classes/org/glizycms/languages/controllers/ajax/Cancel.php @@ -0,0 +1,4 @@ +<?php +class org_glizycms_languages_controllers_ajax_Cancel extends org_glizycms_contents_controllers_activeRecordEdit_ajax_Cancel +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/languages/controllers/ajax/Save.php b/src/core/classes/org/glizycms/languages/controllers/ajax/Save.php new file mode 100644 index 0000000..42f7ae6 --- /dev/null +++ b/src/core/classes/org/glizycms/languages/controllers/ajax/Save.php @@ -0,0 +1,26 @@ +<?php +class org_glizycms_languages_controllers_ajax_Save extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { +// TODO controllo acl +// TODO per motifi di sicurezza forse è meglio non passare il nome del model nella request +// ma avere un controller specifico che estende quello base al quale viene passato il nome del model, come succede per Scaffold + $this->directOutput = true; + + $data = json_decode($data); + + $proxy = org_glizy_objectFactory::createObject('org.glizycms.languages.models.proxy.LanguagesProxy'); + if ($proxy->findLanguageByCountry($data->language_FK_country_id)) { + return array('errors' => array(__T('LANGUAGE_ALREADY_PRESENT'))); + } + + $result = $proxy->save($data); + + if ($result['__id']) { + return array('set' => $result); + } else { + return array('errors' => $result); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/languages/controllers/ajax/SaveClose.php b/src/core/classes/org/glizycms/languages/controllers/ajax/SaveClose.php new file mode 100644 index 0000000..b4534e3 --- /dev/null +++ b/src/core/classes/org/glizycms/languages/controllers/ajax/SaveClose.php @@ -0,0 +1,14 @@ +<?php +class org_glizycms_languages_controllers_ajax_SaveClose extends org_glizycms_languages_controllers_ajax_Save +{ + function execute($data) + { + $result = parent::execute($data); + + if ($result['errors']) { + return $result; + } + + return array('url' => $this->changeAction('')); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/languages/locale/en.php b/src/core/classes/org/glizycms/languages/locale/en.php new file mode 100644 index 0000000..841e9d6 --- /dev/null +++ b/src/core/classes/org/glizycms/languages/locale/en.php @@ -0,0 +1,5 @@ +<?php +$strings = array ( + 'LANGUAGE_ALREADY_PRESENT' => 'Language already present' +); +org_glizy_locale_Locale::append($strings); diff --git a/src/core/classes/org/glizycms/languages/locale/it.php b/src/core/classes/org/glizycms/languages/locale/it.php new file mode 100644 index 0000000..9c707f6 --- /dev/null +++ b/src/core/classes/org/glizycms/languages/locale/it.php @@ -0,0 +1,5 @@ +<?php +$strings = array ( + 'LANGUAGE_ALREADY_PRESENT' => 'Lingua già esistente' +); +org_glizy_locale_Locale::append($strings); diff --git a/src/core/classes/org/glizycms/languages/models/proxy/LanguagesProxy.php b/src/core/classes/org/glizycms/languages/models/proxy/LanguagesProxy.php new file mode 100644 index 0000000..1718775 --- /dev/null +++ b/src/core/classes/org/glizycms/languages/models/proxy/LanguagesProxy.php @@ -0,0 +1,122 @@ +<?php +class org_glizycms_languages_models_proxy_LanguagesProxy extends org_glizycms_contents_models_proxy_ActiveRecordProxy +{ + public function save($data) + { + $isNew = !(intval($data->__id) && $data->__id > 0); + $isDefault = $data->language_isDefault; + $currentDefaultId = 0; + $countryId = $data->language_FK_country_id; + if ($countryId) { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Country'); + if ($ar->load($countryId)) { + $data->language_code = $ar->country_639_1; + } + } else { + $data->language_code = ''; + } + + if (!$data->language_order) { + $data->language_order = 1; + } + + // if isDefault read the current defautl language + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Language'); + if ($ar->find(array('language_isDefault' => 1))) { + $currentDefaultId = $ar->language_id; + } + + if (!$isDefault && $currentDefaultId==$data->__id) { + return array(__T('You can\'t remove the default proerty, to do it set the default to other record')); + } else if ($isDefault && $currentDefaultId!=$data->__id) { + $ar->language_isDefault = 0; + $ar->save(); + } + + if ($isNew && !$currentDefaultId) { + return array(__T('Can\'t create a new language if there aren\'t a default one')); + } + + $result = parent::save($data); + + if ($isNew && $currentDefaultId) { + $this->duplicateMenu($currentDefaultId, $result['__id']); + $this->duplicateMedia($currentDefaultId, $result['__id']); + } + } + + + public function delete($recordId) + { + $this->deleteMenu($recordId); + $this->deleteContents($recordId); + $this->deleteMedia($recordId); + parent::delete($recordId, 'org.glizycms.core.models.Language'); + } + + private function duplicateMenu($languageId, $newLanguageId) + { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language'); + $it->load('duplicateMenuDetail', array(':languageId' => $languageId, ':newLanguageId' => $newLanguageId)); + $it->exec(); + } + + private function duplicateContents($languageId, $newLanguageId) + { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language'); + $it->load('duplicateDocumentsDetail', array(':languageId' => $languageId, ':newLanguageId' => $newLanguageId)); + $it->exec(); + } + + private function duplicateMedia($languageId, $newLanguageId) + { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language'); + $it->load('duplicateMediaDetail', array(':languageId' => $languageId, ':newLanguageId' => $newLanguageId)); + $it->exec(); + } + + private function deleteMenu($languageId) + { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language'); + $it->load('deleteMenuDetail', array(':languageId' => $languageId)); + $it->exec(); + } + + private function deleteContents($languageId) + { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language'); + $it->load('deleteDocumentsDetail', array(':languageId' => $languageId)); + $it->exec(); + } + + private function deleteMedia($languageId) + { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language'); + $it->load('deleteMediaDetail', array(':languageId' => $languageId)); + $it->exec(); + } + + public function getLanguageId() + { + $editingLanguageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + if (!is_null($editingLanguageId)) { + return $editingLanguageId; + } else { + return org_glizy_ObjectValues::get('org.glizy', 'languageId'); + } + } + + public function getDefaultLanguageId() + { + // TODO caching + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Language'); + $ar->find(array('language_isDefault' => 1)); + return $ar->language_id; + } + + public function findLanguageByCountry($languageCountryId) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Language'); + return $ar->find(array('language_FK_country_id' => $languageCountryId)); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/languages/views/Admin.xml b/src/core/classes/org/glizycms/languages/views/Admin.xml new file mode 100644 index 0000000..010e718 --- /dev/null +++ b/src/core/classes/org/glizycms/languages/views/Admin.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Page.php"> + <glz:Import src="_common.xml" /> + + <mvc:State name="index"> + <glz:DataProvider id="dp" recordClassName="org.glizycms.core.models.Language" /> + <glz:DataGrid id="dataGrid" label="{i18n:GLZ_LANGUAGE_LIST}" dataProvider="{dp}" filters="{filters}" tableCssClass="table table-striped table-bordered" cssClass="odd,even" controller="{dataGridEdit}" orderStyle="BLACK"> + <glz:DataGridColumn columnName="language_id" visible="false" key="true" /> + <glz:DataGridColumn columnName="language_name" headerText="{i18n:GLZ_LANGUAGE}" /> + <glz:DataGridColumn columnName="language_code" headerText="{i18n:GLZ_LANGUAGE_CODE}" /> + <glz:DataGridColumn columnName="language_isDefault" headerText="{i18n:GLZ_LANGUAGE_DEFAULT}" width="120" align="center" renderCell="org.glizycms.core.application.renderer.CellUserActive" /> + <glz:DataGridColumn columnName="language_id" align="right" width="80" renderCell="org.glizycms.languages.views.renderer.CellEditDelete" /> + </glz:DataGrid> + <glz:Link label="{i18n:Add new language}" cssClass="{config:glizycms.form.actionLink.cssClass}" icon="icon-plus" routeUrl="actionsMVCAdd" editableRegion="actions" acl="*,new"/> + </mvc:State> + + <mvc:State name="edit"> + <cms:FormEdit id="myForm" controllerName="org.glizycms.languages.controllers.*"> + <cms:pageTitleModifier action="edit" label="{i18n:New language}" new="true" /> + <cms:pageTitleModifier action="edit" label="{i18n:Edit language}" new="false" field="language_name" /> + <glz:Hidden id='__id' /> + <glz:Hidden id="__model" value="org.glizycms.core.models.Language"/> + <glz:Hidden id="language_code" /> + <glz:Input id="language_name" label="{i18n:GLZ_LABEL}" required="true" size="90" /> + <glz:DataDictionary id="countryDP" recordClassName="org.glizycms.core.models.Country" field="country_id,country_name" /> + <glz:List id="language_FK_country_id" label="{i18n:GLZ_LANGUAGE}" dataProvider="{countryDP}" emptyValue="-" required="true" /> + <glz:Checkbox id="language_isDefault" label="{i18n:GLZ_LANGUAGE_DEFAULT}" data="type=checkbox"/> + <glz:Input id="language_order" label="{i18n:GLZ_LANGUAGE_ORDER}" size="10" /> + + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <glz:HtmlButton label="{i18n:GLZ_SAVE_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=saveClose" /> + <glz:HtmlButton label="{i18n:GLZ_CANCEL}" type="button" cssClass="btn js-glizycms-cancel" data="action=cancel" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="delete"> + <glz:Hidden controllerName="org.glizycms.languages.controllers.*" /> + </mvc:State> + +</mvc:Page> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/languages/views/renderer/CellEditDelete.php b/src/core/classes/org/glizycms/languages/views/renderer/CellEditDelete.php new file mode 100644 index 0000000..766f482 --- /dev/null +++ b/src/core/classes/org/glizycms/languages/views/renderer/CellEditDelete.php @@ -0,0 +1,29 @@ +<?php +class org_glizycms_languages_views_renderer_CellEditDelete extends org_glizy_components_render_RenderCell +{ + function renderCell( $key, $value, $item, $columnName ) + { + $pageId = $this->application->getPageId(); + if ($this->user->acl($pageId, 'all') or $this->user->acl($pageId, 'edit')) { + $output = org_glizy_Assets::makeLinkWithIcon( 'actionsMVC', + 'icon-pencil btn-icon', + array( + 'title' => __T('GLZ_RECORD_EDIT'), + 'id' => $key, + 'action' => 'edit')); + } + + if (!$item->language_isDefault) { + $output .= org_glizy_Assets::makeLinkWithIcon( 'actionsMVC', + 'icon-trash btn-icon', + array( + 'title' => __T('GLZ_RECORD_DELETE'), + 'id' => $key, + 'action' => 'delete'), + __T( 'conferma cancellazione record')); + } + + return $output; + } +} + diff --git a/src/core/classes/org/glizycms/locale/en.php b/src/core/classes/org/glizycms/locale/en.php new file mode 100644 index 0000000..4377923 --- /dev/null +++ b/src/core/classes/org/glizycms/locale/en.php @@ -0,0 +1,104 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +$strings = array ( + "MW_MEDIA_ADD" => "Add media", + "MW_NO_MEDIA" => "No media", + "MW_NO_RECORD_FOUND" => "No record found", + "MW_SM_MEDIA_ARCHIVE" => "Media archive", + "MW_SM_SHOW_ALL_MEDIA" => "Show all media", + "MW_SM_SHOW_IMAGES" => "Show images", + "MW_SM_SHOW_DOCUMENTS" => "Show documents", + "MW_SM_SHOW_PDF" => "Show PDF", + "MW_SM_SHOW_COMPRESSED" => "Show compressed files", + "MW_SM_SHOW_AUDIO_FILES" => "Show audio files", + "MW_SM_SHOW_VIDEO" => "Show video files", + "MW_DUBLIN_CORE" => "Dublin Core", + "MW_DC_KEYWORDS" => "Keywords", + "MW_DC_SHORTDESCRIPTION" => "Description", + "MW_DC_SUBJECT" => "Subject", + "MW_DC_CREATOR" => "Creator", + "MW_DC_PUBLISHER" => "Publisher", + "MW_DC_CONTRIBUTOR" => "Contributor", + "MW_DC_TYPE" => "Type", + "MW_DC_IDENTIFIER" => "Identifier", + "MW_DC_SOURCE" => "Source", + "MW_DC_RELATION" => "Relation", + "MW_DC_COVERAGE" => "Coverage", + "MW_LOAD_PARENT" => "Load from parent", + "MW_MEDIA_SELECTFILE_FROM_SERVER" => "Select file from server", + "MW_SM_SITE_PROPERTIES" => "Proprietà del sito", + "MW_SM_MULTILINGUALISM" => "Multilingualism", + "Show" => "Show", + "Hide" => "Hide", + "Search" => "Search", + "Previous" => "Previous", + "Next" => "Next", + "First" => "First", + "Last" => "Last", + + "Site Contents" => "Site Contents", + "Site Management" => "Site Management", + "Pages" => "Pages", + "Contents" => "Contents", + "Title" => "Title", + "Author" => "Author", + "Category" => "Category", + "Description" => "Description", + "Type" => "Type", + "Date" => "Date", + "Show zoom" => "Show zoom", + "File name" => "File name", + "Allow download" => "Allow download", + "Insert watermark" => "Insert watermark", + + // datagrd ajax (DataTable) + "records per page" => "records per page", + "Filter by type" => "Filter by type", + "Showing _START_ to _END_ of _TOTAL_ entries" => "Showing _START_ to _END_ of _TOTAL_ entries", + "Showing 0 to 0 of 0 entries" => "Showing 0 to 0 of 0 entries", + "filtered from _MAX_ total entries" => "filtered from _MAX_ total entries", + "Loading..." => "Loading...", + "Processing..." => "Processing...", + "No record found" => "No record found", + "No record found with current filters" => "No record found with current filters", + // site properties + "Google Analytics code" => "Google Analytics code", + "Add new language" => "Add new language", + "New language" => "New language", + "Edit language" => "Edit language: <em>%s</em>", + "Add new user group" => "Add new user group", + "New group" => "New group", + "Edit group" => "Edit group: <em>%s</em>", + "New user" => "New user", + "Edit user" => "Edit user: <em>%s</em>", + "Add a new page" => "Add a new page", + "Edit page" => "Edit page: <em>%s</em>", + "Edit properties" => "Edit properties: <em>%s</em>", + "Edit layout" => "Edit layout", + "File already in media archive" => "The file \"%s\" is already in the media archive", + "Delete selected" => "Delete selected", + "No exif data" => "No exif data", + "Exif data" => "Exif data", + "General data" => "General data", + "Dimension" => "Dimension", + "Resolution" => "Resolution", + "Device manufacturer" => "Device manufacturer", + "Device model" => "Device model", + "Exposure time"=> "Exposure time", + "Aperture" => "Aperture", + "Exposure program" => "Exposure program", + "ISO" => "ISO", + "Original date" => "Original date", + "Digitized date" => "Digitized date", + "GPS coordinates" => "GPS coordinates", + "GPS time" => "GPS time", + "Select" => "Seleziona", +); +org_glizy_locale_Locale::append($strings); diff --git a/src/core/classes/org/glizycms/locale/it.php b/src/core/classes/org/glizycms/locale/it.php new file mode 100644 index 0000000..ed7d1b0 --- /dev/null +++ b/src/core/classes/org/glizycms/locale/it.php @@ -0,0 +1,105 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +$strings = array ( + "MW_MEDIA_ADD" => "Aggiungi media", + "MW_NO_MEDIA" => "Nessun media", + "MW_NO_RECORD_FOUND" => "Nessun record trovato", + "MW_SM_MEDIA_ARCHIVE" => "Archivio Media", + "MW_SM_SHOW_ALL_MEDIA" => "Mostra tutti i media", + "MW_SM_SHOW_IMAGES" => "Mostra le immagini", + "MW_SM_SHOW_DOCUMENTS" => "Mostra i documenti", + "MW_SM_SHOW_PDF" => "Mostra i PDF", + "MW_SM_SHOW_COMPRESSED" => "Mostra i file compressi", + "MW_SM_SHOW_AUDIO_FILES" => "Mostra i file audio", + "MW_SM_SHOW_VIDEO" => "Mostra i file video", + "MW_DUBLIN_CORE" => "Dublin Core", + "MW_DC_KEYWORDS" => "Parole chiave", + "MW_DC_SHORTDESCRIPTION" => "Descrizione", + "MW_DC_SUBJECT" => "Soggetto", + "MW_DC_CREATOR" => "Autore", + "MW_DC_PUBLISHER" => "Editore", + "MW_DC_CONTRIBUTOR" => "Autore di contributo subordinato", + "MW_DC_TYPE" => "Tipo", + "MW_DC_IDENTIFIER" => "Identificatore", + "MW_DC_SOURCE" => "Fonte", + "MW_DC_RELATION" => "Relazione", + "MW_DC_COVERAGE" => "Copertura", + "MW_LOAD_PARENT" => "Carica dal padre", + "MW_MEDIA_SELECTFILE_FROM_SERVER" => "Seleziona file dal server", + "MW_SM_SITE_PROPERTIES" => "Proprietà del sito", + "MW_SM_MULTILINGUALISM" => "Multilingue", + "Show" => "Visualizza", + "Hide" => "Nascondi", + "Search" => "Cerca", + "Previous" => "Precedente", + "Next" => "Successivo", + "First" => "Inizio", + "Last" => "Fine", + + "Site Contents" => "Contenuti del sito", + "Site Management" => "Gestione sito", + "Pages" => "Pagine", + "Contents" => "Contenuti", + "Title" => "Titolo", + "Author" => "Autore", + "Category" => "Categoria", + "Description" => "Descrizione", + "Type" => "Tipo", + "Date" => "Data", + "Show zoom" => "Abilita Zoom", + "File name" => "Nome del file", + "Allow download" => "Permetti download", + "Insert watermark" => "Inserisci watermark", + + // datagrd ajax (DataTable) + "records per page" => "record per pagina", + "Filter by type" => "Filtra per tipologia", + "Showing _START_ to _END_ of _TOTAL_ entries" => "Mostra da _START_ a _END_ di _TOTAL_ record", + "Showing 0 to 0 of 0 entries" => "", + "filtered from _MAX_ total entries" => "mostra _MAX_ record", + "Loading..." => "Caricamento...", + "Processing..." => "Elaborazione...", + "No record found" => "Nessun record trovato", + "No record found with current filters" => "Nessun record trovato per i filtri di ricerca indicati", + // site properties + "Google Analytics code" => "Chiave Google Analytics", + "Add new language" => "Aggiungi una nuova lingua", + "New language" => "Nuova lingua", + "Edit language" => "Modifica lingua", + "Add new user group" => "Aggiungi un nuovo gruppo", + "New group" => "Nuovo gruppo", + "Edit group" => "Modifica gruppo: <em>%s</em>", + "New user" => "Nuovo utente", + "Edit user" => "Modifica utente: <em>%s</em>", + "Add a new page" => "Aggiungi una nuova pagina", + "Edit page" => "Modifica pagina: <em>%s</em>", + "Edit properties" => "Modifica proprietà: <em>%s</em>", + "Edit layout" => "Modifica aspetto", + "File already in media archive" => "Il file \"%s\" è già presente nell'archivio media", + "Delete selected" => "Elimina selezionati", + "No exif data" => "Dati exif non presenti", + "Exif data" => "Dati exif", + "General data" => "Generale", + "Dimension" => "Dimensione", + "Resolution" => "Risoluzione", + "Device manufacturer" => "Marca dispositivo", + "Device model" => "Modello dispositivo", + "Exposure time"=> "Tempo di esposizione", + "Aperture" => "Apertura", + "Exposure program" => "Programma di esposizione", + "ISO" => "ISO", + "Original date" => "Data originale", + "Digitized date" => "Data digitalizzazione", + "GPS coordinates" => "Coordinate GPS", + "GPS time" => "Orario GPS", + "Select" => "Seleziona", +); +org_glizy_locale_Locale::append($strings); + diff --git a/src/core/classes/org/glizycms/mediaArchive/Bridge.php b/src/core/classes/org/glizycms/mediaArchive/Bridge.php new file mode 100644 index 0000000..71b9a77 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/Bridge.php @@ -0,0 +1,64 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_Bridge implements org_glizycms_mediaArchive_IBridge +{ + public function getMediaById($id) + { + return 'getFile.php?id='.$id; + } + + public function getImageById($id) + { + return 'getImage.php?id='.$id; + } + + public function getImageByIdAndResize($id, $width, $height, $crop=false, $cropOffset=1, $forceSize=false, $useThumbnail=false) + { + return 'getImage.php?id='.$id.'&w='.$width.'&h='.$height.'&c='.($crop ? '1' : '0').'&co='.$cropOffset.'&f='.($forceSize ? '1' : '0').'&t='.($useThumbnail ? '1' : '0').'&.jpg'; + } + + public function getJsonFromAr(org_glizy_dataAccessDoctrine_ActiveRecord $ar) + { + return json_encode(array( + 'id' => $ar->media_id, + 'filename' => $ar->media_fileName, + 'title' => $ar->media_title, + 'src' => $ar->thumb_filename, + 'category' => $ar->media_category, + 'author' => $ar->media_author, + 'date' => $ar->media_date, + 'copyright' => $ar->media_copyright, + )); + } + + public function getMediaPickerUrl($tinyVersion=false, $mediaType='ALL') + { + if (!$tinyVersion) { + return 'index.php?pageId=mediaarchive_picker&mediaType='.$mediaType.'&'; + } else { + return 'index.php?pageId=MediaArchive_pickerTiny&mediaType='.$mediaType.'&'; + } + } + + public function getImageResizeTemplate($tinyVersion=false, $mediaType='ALL') + { + return $this->getImageByIdAndResize('#id#', '#w#', '#h#', false, 1, true); + } + + public function getIdFromJson($json) + { + if (!is_null($json->id)) { + return $json->id; + } else { + preg_match('/getImage.php\?id=(\d+)/', $json->src, $m); + return $m[1]; + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/IBridge.php b/src/core/classes/org/glizycms/mediaArchive/IBridge.php new file mode 100644 index 0000000..ab6b94f --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/IBridge.php @@ -0,0 +1,18 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +interface org_glizycms_mediaArchive_IBridge +{ + public function getMediaById($id); + public function getImageById($id); + public function getImageByIdAndResize($id, $width, $height, $crop=false, $cropOffset=1, $forceSize=false, $useThumbnail=false); + public function getJsonFromAr(org_glizy_dataAccessDoctrine_ActiveRecord $ar); + public function getMediaPickerUrl($tinyVersion=false, $mediaType='ALL'); + public function getImageResizeTemplate($tinyVersion=false, $mediaType='ALL'); +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/MediaManager.php b/src/core/classes/org/glizycms/mediaArchive/MediaManager.php new file mode 100755 index 0000000..df77748 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/MediaManager.php @@ -0,0 +1,143 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_MediaManager extends GlizyObject +{ + /** + * @param $id + * + * @return GlizyObject|null + */ + static function &getMediaById($id) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.models.Media'); + if ($ar->load($id)) + { + $media = &org_glizycms_mediaArchive_MediaManager::getMediaByRecord($ar); + return $media; + } + else + { + // TODO + // ERRORE + } + + return NULL; + } + + + /** + * @param $ar + * + * @return GlizyObject + */ + static function &getMediaByRecord(&$ar) + { + $mediaType = $ar->media_type; + $mediaTypeInfo = org_glizycms_mediaArchive_MediaManager::getMediaTypeInfo(); + $mediaClassName = 'org.glizycms.mediaArchive.media.'.$mediaTypeInfo[$mediaType]['class']; + $media = &org_glizy_ObjectFactory::createObject($mediaClassName, $ar); + return $media; + } + + /** + * @param $values + * + * @return GlizyObject + */ + static function &getMediaByValues( $values ) + { + $mediaType = $values['media_type']; + $mediaTypeInfo = org_glizycms_mediaArchive_MediaManager::getMediaTypeInfo(); + $mediaClassName = 'org.glizycms.mediaArchive.media.'.$mediaTypeInfo[$mediaType]['class']; + $media = &org_glizy_ObjectFactory::createObject($mediaClassName, $values ); + return $media; + } + + /** + * @param $mediaType + * + * @return GlizyObject + */ + static function &getEmptyMediaByType($mediaType) + { + $mediaTypeInfo = org_glizycms_mediaArchive_MediaManager::getMediaTypeInfo(); + $mediaClassName = 'org.glizycms.mediaArchive.media.'.$mediaTypeInfo[$mediaType]['class']; + $ar = null; + /** @var org_glizycms_mediaArchive_media_Media $media */ + $media = &org_glizy_ObjectFactory::createObject($mediaClassName, null); + $media->type = $mediaType; + return $media; + } + + /** + * @return array + */ + function getMediaTypeInfo() + { + $fileTypes = array( 'IMAGE' => array('extension' => array('jpg', 'jpeg', 'png', 'gif', 'tif', 'tiff'), 'class' => 'Image'), + 'OFFICE' => array('extension' => array('doc', 'xls', 'mdb', 'ppt', 'pps', 'html', 'htm', 'odb', 'odc', 'odf', 'odg', 'odi', 'odm', 'odp', 'ods', 'odt', 'otc', 'otf', 'otg', 'oth', 'oti', 'otp', 'ots', 'ott'), 'class' => 'Office'), + 'ARCHIVE' => array('extension' => array('zip', 'rar', '7z', 'tar', 'gz', 'tgz'), 'class' => 'Archive'), + 'AUDIO' => array('extension' => array('wav', 'mp3', 'aif'), 'class' => 'Audio'), + 'PDF' => array('extension' => array('pdf'), 'class' => 'Pdf'), + 'VIDEO' => array('extension' => array('avi', 'mov', 'flv', 'wmv', 'mp4', 'm4v', 'mpg'), 'class' => 'Video'), + 'FLASH' => array('extension' => array('swf'), 'class' => 'Flash'), + 'OTHER' => array('extension' => array(), 'class' => 'Other'), + ); + + $customType = org_glizycms_mediaArchive_MediaManager::getCustomMediaType(); + if (count($customType)) + { + $fileTypes = array_merge($fileTypes, $customType); + } + + return $fileTypes; + } + + /** + * @param $ext + * + * @return int|string + */ + static function getMediaTypeFromExtension($ext) + { + $ext = strtolower($ext); + $fileTypes = org_glizycms_mediaArchive_MediaManager::getMediaTypeInfo(); + + $fileType = 'OTHER'; + foreach($fileTypes as $k=>$v) + { + if (in_array($ext, $v['extension'])) + { + $fileType = $k; + break; + } + } + return $fileType; + } + + /** + * @param $type + * @param $values + */ + static function addCustomMediaType($type, $values) + { + $customType = &org_glizy_ObjectValues::get('glizy.MediaManager', 'customType', array()); + $customType[$type] = $values; + } + + /** + * @return string + */ + function getCustomMediaType() + { + $customType = &org_glizy_ObjectValues::get('glizy.MediaManager', 'customType', array()); + return $customType; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/controllers/Add.php b/src/core/classes/org/glizycms/mediaArchive/controllers/Add.php new file mode 100644 index 0000000..08b5c61 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/controllers/Add.php @@ -0,0 +1,19 @@ +<?php +class org_glizycms_mediaArchive_controllers_Add extends org_glizy_mvc_core_Command +{ + public function execute() + { + $c = $this->view->getComponentById('fileuploader'); + $c->setAttribute('data', ';maxlabel='.ini_get('upload_max_filesize').'B', true); + + if (!__Config::get('glizycms.mediaArchive.mediaMappingEnabled')) { + $c = $this->view->getComponentById('addFromServer'); + if ($c) { + $c->setAttribute('label', null); + $c->setAttribute('visible', false); + } + } + } +} + + diff --git a/src/core/classes/org/glizycms/mediaArchive/controllers/AddFromZip.php b/src/core/classes/org/glizycms/mediaArchive/controllers/AddFromZip.php new file mode 100644 index 0000000..f6e0e11 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/controllers/AddFromZip.php @@ -0,0 +1,11 @@ +<?php +class org_glizycms_mediaArchive_controllers_AddFromZip extends org_glizycms_mediaArchive_controllers_Add +{ + public function execute() + { + parent::execute(); + $this->setComponentsVisibility('media_title', false); + } +} + + diff --git a/src/core/classes/org/glizycms/mediaArchive/controllers/Delete.php b/src/core/classes/org/glizycms/mediaArchive/controllers/Delete.php new file mode 100644 index 0000000..4e347d8 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/controllers/Delete.php @@ -0,0 +1,11 @@ +<?php +class org_glizycms_mediaArchive_controllers_Delete extends org_glizy_mvc_core_Command +{ + public function execute($id) + { + $mediaProxy = org_glizy_ObjectFactory::createObject('org.glizycms.mediaArchive.models.proxy.MediaProxy'); + $mediaProxy->deleteMedia($id); + + org_glizy_helpers_Navigation::goHere(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/controllers/Index.php b/src/core/classes/org/glizycms/mediaArchive/controllers/Index.php new file mode 100644 index 0000000..de13aee --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/controllers/Index.php @@ -0,0 +1,38 @@ +<?php +class org_glizycms_mediaArchive_controllers_Index extends org_glizy_mvc_core_Command +{ + public function execute() + { + $c = $this->view->getComponentById('dp'); + + if (stripos($this->application->getPageId(), 'picker') !== false) { + // picker + $sessionEx = org_glizy_ObjectFactory::createObject('org.glizy.SessionEx', $c->getId()); + $mediaType = org_glizy_Request::get('mediaType', ''); + if (empty($mediaType)) { + $mediaType = $sessionEx->get('mediaType', 'ALL', false, false); + } + + if (!empty($mediaType) && strtoupper($mediaType)!='ALL') { + $sessionEx->set('mediaType', $mediaType, GLZ_SESSION_EX_PERSISTENT); + $c->setAttribute('query', 'all'.ucfirst(strtolower(str_replace(',', '_', $mediaType)))); + // $this->setAttribute('filters', 'media_type IN (\''.str_replace(',', '\',\'',$mediaType).'\')'); + } + + if (stripos($this->application->getPageId(), 'tiny') !== false) { + $this->setComponentsVisibility('buttonsBar', false); + } + } else { + $query = str_replace('all', '', __Request::get('tabs_state', 'allMedia')); + // $query = str_replace('mediaarchive_all', '', strtolower($this->application->getPageId())); + if (empty($query) || $query=='mediaarchive') $query = 'media'; + $query = 'all'.ucfirst($query); + $c->setAttribute('query', $query); + + } + + // TODO disabilitare il pulsane aggiungi in base all'acl + } +} + + diff --git a/src/core/classes/org/glizycms/mediaArchive/controllers/ajax/Delete.php b/src/core/classes/org/glizycms/mediaArchive/controllers/ajax/Delete.php new file mode 100644 index 0000000..83aa669 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/controllers/ajax/Delete.php @@ -0,0 +1,14 @@ +<?php +class org_glizycms_mediaArchive_controllers_ajax_Delete extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { + $ids = explode(',', __Request::get('ids')); + if (!empty($ids)) { + $mediaProxy = org_glizy_ObjectFactory::createObject('org.glizycms.mediaArchive.models.proxy.MediaProxy'); + foreach ($ids as $id) { + $mediaProxy->deleteMedia($id); + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/Edit.php b/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/Edit.php new file mode 100644 index 0000000..c7aff39 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/Edit.php @@ -0,0 +1,13 @@ +<?php +class org_glizycms_mediaArchive_controllers_mediaEdit_Edit extends org_glizy_mvc_core_Command +{ + public function execute() + { + $id = __Request::get('id'); + $media = org_glizy_ObjectFactory::createModel('org.glizycms.models.Media'); + $media->load($id); + $data = $media->getValuesAsArray(); + + $this->view->setData($data); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/Cancel.php b/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/Cancel.php new file mode 100644 index 0000000..d719534 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/Cancel.php @@ -0,0 +1,9 @@ +<?php +class org_glizycms_mediaArchive_controllers_mediaEdit_ajax_Cancel extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { + $this->directOutput = true; + return array('url' => $this->changeAction('')); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/Save.php b/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/Save.php new file mode 100644 index 0000000..6f1bdee --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/Save.php @@ -0,0 +1,202 @@ +<?php +class org_glizycms_mediaArchive_controllers_mediaEdit_ajax_Save extends org_glizy_mvc_core_CommandAjax +{ + protected $mediaIds = array(); + + public function execute($data) + { + $data = json_decode($data); + + if (__Config::get('glizycms.mediaArchive.mediaMappingEnabled') && $data->mediaFileServer) { + $result = $this->saveMediasFromServer($data); + return $this->processResult($result); + } else if (property_exists($data, 'medias')) { + $result = $this->saveMedias($data); + return $this->processResult($result); + } else if ($data->media_id){ + return $this->modifyMedia($data); + } else { + $this->directOutput = true; + return array('evt' => array('No medias')); + } + } + + protected function processResult($result) + { + $this->directOutput = true; + if (is_array($result) && $result['errors']) { + return $result; + } else { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $url = org_glizy_helpers_Link::makeUrl( $this->getRedirectUrl(), array( 'pageId' => $application->getPageId() ) ); + return array('url' => $url); + } + } + + public function saveMediasFromServer($data) + { + $file_path = $data->mediaFileServer; + $file_virtual_path = preg_replace('/\//', '://', $file_path, 1); + + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $mappingService = $application->retrieveProxy('org.glizycms.mediaArchive.services.MediaMappingService'); + $file_path = $mappingService->getRealPath($file_path); + $file_name = pathinfo($file_path, PATHINFO_BASENAME); + + $media = new StdClass(); + foreach ($data as $k => $v) { + $media->$k = $v; + } + $media->media_fileName = $file_virtual_path; + $media->__filePath = $file_path; + $media->__originalFileName = $file_name; + + $mediaProxy = org_glizy_ObjectFactory::createObject('org.glizycms.mediaArchive.models.proxy.MediaProxy'); + $currentMediaId = $mediaProxy->saveMedia($media, $data->copyToCMS == 'true' ? $mediaProxy::COPY_TO_CMS : $mediaProxy::NONE); + array_push($this->mediaIds,$currentMediaId); + return $currentMediaId; + } + + public function saveMedias($data) + { + $mediaProxy = org_glizy_ObjectFactory::createObject('org.glizycms.mediaArchive.models.proxy.MediaProxy'); + $medias = $data->medias; + + $r = $this->checkDuplicates($medias); + if (!$r) { + return $r; + } + + $medias = $this->decompressFiles($medias); + + $uploadedFiles = 0; + for ($i = 0; $i < count($medias->__uploadFilename); $i++) { + if (!$medias->__uploadFilename[$i]) continue; + + $media = new StdClass(); + foreach ($medias as $k => $v) { + if ($v[$i]) { + $media->$k = $v[$i]; + } + } + $media->__filePath = realpath($medias->__uploadFilename[$i]); + try { + $result = $mediaProxy->saveMedia($media); + } catch (Exception $e) { + var_dump($e->getErrors()); + } + + if (is_array($result) && $result['errors']) { + return $result; + } + + array_push($this->mediaIds,$result); + $uploadedFiles++; + } + + if (!$uploadedFiles) { + return array('errors' => array(__T('Nessun file caricato'))); + } + + return true; + } + + public function modifyMedia($data) + { + $media = org_glizy_ObjectFactory::createModel('org.glizycms.models.Media'); + + $media->load($data->media_id); + + $media->media_modificationDate = new org_glizy_types_DateTime(); + + foreach ($data as $k => $v) { + // remove the system values + if (strpos($k, '__') === 0 || !$media->fieldExists($k)) continue; + $media->$k = $v; + } + + $media->media_FK_user_id = org_glizy_ObjectValues::get('org.glizy', 'userId'); + + try { + return $media->save(); + } + catch (org_glizy_validators_ValidationException $e) { + $this->directOutput = true; + return array('errors' => $e->getErrors()); + } + } + + public function getRedirectUrl() + { + return 'glizycmsMediaArchiveAdd'; + } + + private function checkDuplicates($medias) + { + // controlla se il file esiste già nell'archivio + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.models.Media'); + if ($ar->getField('media_md5')) { + for ($i = 0; $i < count($medias->__uploadFilename); $i++) { + if (!$medias->__uploadFilename[$i]) continue; + + $md5 = md5_file(realpath($medias->__uploadFilename[$i])); + + $ar->emptyRecord(); + $result = $ar->find(array('media_md5' => $md5)); + + if ($result) { + return array('errors' => array(__T('File already in media archive', $medias->__originalFileName[$i]))); + } + } + } + return true; + } + + private function decompressFiles($medias) + { + if (!property_exists($medias, '__expand')) { + return $medias; + } + + GlizyClassLoader::addLib('VIPSoft\Unzip', __Paths::get('APPLICATION_LIBS') . 'VIPSoft/Unzip'); + + $copyProperties = function(&$properties, &$medias, &$tempMedias, $pos) { + foreach($properties as $v) { + $tempMedias->{$v}[] = @$medias->{$v}[$pos]; + } + }; + + $properties = array_keys(get_object_vars($medias)); + if (!in_array('media_title', $properties)) { + $properties[] = 'media_title'; + } + $tempMedias = new StdClass(); + foreach($properties as $v) { + $tempMedias->$v = array(); + } + $numUploaded = count($medias->__uploadFilename); + for ($i = 0; $i<$numUploaded; $i++) { + if (!$medias->__uploadFilename[$i]) continue; + if ($medias->__expand[$i]==1) { + $unzipper = new VIPSoft\Unzip\Unzip(); + $destFolder = $medias->__uploadFilename[$i].md5(time()); + $filenames = $unzipper->extract($medias->__uploadFilename[$i], $destFolder); + foreach($filenames as $f) { + if (strpos($f, '__MACOSX')!==false || strpos($f, '.DS_Store')!==false) continue; + $filename = $destFolder.'/'.$f; + if (is_dir($filename)) continue; + $pos = count($tempMedias->__uploadFilename); + $copyProperties($properties, $medias, $tempMedias, $i); + $info = pathinfo($filename); + $tempMedias->__uploadFilename[$pos] = $filename; + $tempMedias->__originalFileName[$pos] = $info['basename']; + $tempMedias->media_title[$pos] = str_replace(array('_', '-'), ' ', $info['filename']); + } + } else { + $copyProperties($properties, $medias, $tempMedias, $i); + } + } + + return $tempMedias; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/SaveClose.php b/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/SaveClose.php new file mode 100644 index 0000000..3c1f390 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/controllers/mediaEdit/ajax/SaveClose.php @@ -0,0 +1,16 @@ +<?php +class org_glizycms_mediaArchive_controllers_mediaEdit_ajax_SaveClose extends org_glizycms_mediaArchive_controllers_mediaEdit_ajax_Save +{ + public function execute($data) + { + $result = parent::execute($data); + + if ($result['errors']) { + return $result; + } + else { + $this->directOutput = true; + return array('url' => $this->changeAction('')); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/media/Archive.php b/src/core/classes/org/glizycms/mediaArchive/media/Archive.php new file mode 100755 index 0000000..4264790 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/media/Archive.php @@ -0,0 +1,16 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_media_Archive extends org_glizycms_mediaArchive_media_Media +{ + function getIconFileName() + { + return org_glizy_Assets::get('ICON_MEDIA_ARCHIVE'); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/media/Audio.php b/src/core/classes/org/glizycms/mediaArchive/media/Audio.php new file mode 100755 index 0000000..e018c9a --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/media/Audio.php @@ -0,0 +1,16 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_media_Audio extends org_glizycms_mediaArchive_media_Media +{ + function getIconFileName() + { + return org_glizy_Assets::get('ICON_MEDIA_AUDIO'); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/media/Flash.php b/src/core/classes/org/glizycms/mediaArchive/media/Flash.php new file mode 100755 index 0000000..f1ebbe5 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/media/Flash.php @@ -0,0 +1,16 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_media_Flash extends org_glizycms_mediaArchive_media_Media +{ + function getIconFileName() + { + return org_glizy_Assets::get('ICON_MEDIA_FLASH'); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/media/Image.php b/src/core/classes/org/glizycms/mediaArchive/media/Image.php new file mode 100755 index 0000000..78a1ab3 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/media/Image.php @@ -0,0 +1,532 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_media_Image extends org_glizycms_mediaArchive_media_Media +{ + var $_imageInfo = null; + var $_cacheObj; + var $_piramidImageSizes = array( array( 1024, 768 ), array( 512, 384 ), array( 256, 192 ) ); + + function getOriginalImageInfo() + { + if ( file_exists( $this->getFileName() ) ) + { + if (is_null($this->_imageInfo)) $this->_imageInfo = getImageSize($this->getFileName()); + return $this->_imageInfo; + } + } + + function getOriginalSizes() + { + $this->getOriginalImageInfo(); + return array('width' => $this->_imageInfo[0], 'height' => $this->_imageInfo[1]); + } + + function getOriginalImageType() + { + $this->getOriginalImageInfo(); + return $this->_imageInfo['mime']; + } + + function getImageInfo() + { + $sizes = $this->getOriginalSizes(); + $fileName = $this->getFileName(); + $filetype = $this->getOriginalImageType(); + return array('imageType' => $filetype, 'fileName' => $fileName, 'width'=> $sizes['width'], 'height'=> $sizes['height']); + } + + function preparePiraimdImages() + { + foreach ( $this->_piramidImageSizes as $v ) + { + $this->getResizeImage( $v[ 0 ], $v[ 1 ], false, 1, false, true, true ); + } + } + + function getResizeImage($width, $height, $crop=false, $cropOffset=1, $forceSize=false, $returnResizedDimension=true, $usePiramidalSizes = true) + { + // check the size + $originalWidth = $width; + $originalHeight = $height; + $resize = true; + $cacheFileName = $this->_verifyCache( $width, $height, $crop, $cropOffset, $forceSize ); + if ($cacheFileName!==false) + { + $useCache = true; + if (!$this->allowDownload) { + $returnResizedDimension = true; + } + + if ( $returnResizedDimension ) + { + list($width, $height) = getImageSize($cacheFileName); + if (!$this->allowDownload) { + $maxWidth = intval(__Config::get('IMG_DOWNLOAD_WIDTH')); + $maxHeight = intval(__Config::get('IMG_DOWNLOAD_HEIGHT')); + if ($maxWidth < $width || $maxHeight < $height) { + $useCache = false; + } + } + } + else + { + $width = NULL; + $height = NULL; + } + + if ($useCache) { + return array('imageType' => IMG_JPG, 'fileName' => $cacheFileName, 'width' => $width, 'height' => $height, 'originalWidth'=> NULL, 'originalHeight'=> NULL); + } + } + + $originalSizes = $this->getOriginalSizes(); + if ( $width == $originalSizes['width'] && $height == $originalSizes['height']) { + $resize = false; + } + + if ( !$resize && !$this->watermark) + { + copy( $this->getFileName(), $this->_cacheObj->getFileName() ); + @touch( $this->_cacheObj->getFileName(), filemtime($this->getFileName())); + return array('imageType' => IMG_JPG, 'fileName' => $this->getFileName(), 'width' => $width, 'height' => $height, 'originalWidth'=> $width, 'originalHeight'=> $height ); + } + + return $this->resizeImage($this->_cacheObj->getFileName(), $width, $height, $crop, $cropOffset, $forceSize, $usePiramidalSizes, $resize); + } + + // NOTE: verificare la duplicazione del codice con getResizeImage + function getThumbnail($width, $height, $crop=false, $cropOffset=1, $forceSize=false, $useThumbnail = true, $returnResizedDimension = true ) + { + if ( $useThumbnail && !empty( $this->ar->media_thumbFileName ) ) + { + $this->fileName = $this->ar->media_thumbFileName; + $this->_imageInfo = null; + } + + $originalSizes = $this->getOriginalSizes(); + if ( $width == $originalSizes['width'] && $height == $originalSizes['height'] ) + { + return array('imageType' => IMG_JPG, 'fileName' => $this->getFileName(), 'width' => $width, 'height' => $height, 'originalWidth'=> $width, 'originalHeight'=> $height ); + } + + $cacheFileName = $this->_verifyCache( $width, $height, $crop, $cropOffset, $forceSize); + if ($cacheFileName!==false) + { + if ( $returnResizedDimension ) + { + list($width, $height) = getImageSize($cacheFileName); + } + else + { + $width = NULL; + $height = NULL; + } + return array('imageType' => IMG_JPG, 'fileName' => $cacheFileName, 'width' => $width, 'height' => $height, 'originalWidth'=> NULL, 'originalHeight'=> NULL); + } + + if ( $returnResizedDimension ) + { + $sizes = $this->resizeImageGetFinalSizes($width, $height, $crop, $cropOffset, $forceSize); + $newWidth = $crop ? min($sizes['width'], $width) : $sizes['width']; + $newHeight = $crop ? min($sizes['height'], $height) : $sizes['height']; + } + else + { + $newWidth = NULL; + $newHeight = NULL; + } + + + return array( 'imageType' => NULL, + 'fileName' => org_glizycms_helpers_Media::getImageUrlById($this->id, $width, $height, $crop, $cropOffset, $forceSize, $useThumbnail ), + 'width' => $newWidth, + 'height' => $newHeight, + 'originalWidth' => NULL, + 'originalHeight' => NULL); + } + + function resizeImage($cacheFileName, $width, $height, $crop=false, $cropOffset=1, $forceSize=false, $usePiramidalSizes = true, $resize = true) + { + $objImg = NULL; + // cerca l'immagine piramidale da cui partire + $originalFileName = $this->fileName; + $originalImageInfo = $this->_imageInfo; + + if ( $usePiramidalSizes && $resize ) + { + $useSize = null; + foreach ( $this->_piramidImageSizes as $v ) + { + if ( $v[ 0 ] > $width && $v[ 1 ] > $height ) + { + $useSize = $v; + } + } + + if ( !is_null( $useSize ) ) + { + $oldWatermark = $this->watermark; + $this->watermark = false; + $resizedPiramidImage = $this->getResizeImage( $useSize[ 0 ], $useSize[ 1 ], false, 1, false, true, false); + $this->fileName = $resizedPiramidImage[ 'fileName' ]; + $this->_imageInfo = null; + $this->watermark = $oldWatermark; + } + } + if (__Config::get('glizy.media.imageMagick')==true) { + $result = $this->resizeImage_im($cacheFileName, $width, $height, $crop, $cropOffset, $forceSize, $usePiramidalSizes, $resize); + } else { + $result = $this->resizeImage_gd($cacheFileName, $width, $height, $crop, $cropOffset, $forceSize, $usePiramidalSizes, $resize); + } + + $this->fileName = $originalFileName; + $this->_imageInfo = $originalImageInfo; + return $result; + } + + private function insertWatermark(&$img, $width, $height, $mode) { + $minWidth = __Config::get('IMG_WATERMARK_MIN_WIDTH'); + $minHeight = __Config::get('IMG_WATERMARK_MIN_HEIGHT'); + $watermarkFile = __Config::get('IMG_WATERMARK'); + $pos = __Config::get('IMG_WATERMARK_POS') ?: 'RB'; + $watermarkFile = $watermarkFile ? __Paths::getRealPath('BASE', $watermarkFile) : false; + if(!$watermarkFile || ($minWidth >= $width && $minHeight >= $height)) { + return; + } + $perc = __Config::get('IMG_WATERMARK_SIZE_PERC'); + if($mode == 'Imagick') { + $watermark = new Imagick(); + $watermark->readImage($watermarkFile); + $w_height = $watermark->getImageHeight(); + $w_width = $watermark->getImageWidth(); + } else { + $watermark = imagecreatefrompng($watermarkFile); + imagealphablending($watermark, true); + $w_width = imagesx($watermark); + $w_height = imagesy($watermark); + }; + if($width > $height) { + $sy = $height*$perc/100; + $sx = $w_width/$w_height*$sy; + } else { + $sx = $width*$perc/100; + $sy = $sx*$w_height/$w_width; + } + $marg_left = $width/100; + //$margin_right = $margin_left; + $marg_top = $height/100; + //$marg_bottom = $margin_top; + switch($pos) { + case "LT": + $posx = $marg_left; + $posy = $marg_top; + break; + case "LC": + $posx = $marg_left; + $posy = $height/2 - $w_height/2; + break; + case "LB": + $posx = $marg_left; + $posy = $height - $sy - $marg_top; + break; + case "CT": + $posx = $width/2 - $w_width/2; + $posy = $marg_top; + break; + case "CC": + $posx = $width/2 - $w_width/2; + $posy = $height/2 - $w_height/2; + break; + case "CB": + $posx = $width/2 - $w_width/2; + $posy = $height - $sy - $marg_top; + break; + case "RT": + $posx = $width -$sx -$marg_left; + $posy = $marg_top; + break; + case "RC": + $posx = $width -$sx -$marg_left; + $posy = $height/2 - $w_height/2; + break; + case "RB": + default: + $posx = $width -$sx -$marg_left; + $posy = $height - $sy - $marg_top; + } + + if($mode == 'Imagick') { + $watermark->scaleImage($sx, $sy); + $img->compositeImage($watermark, imagick::COMPOSITE_OVER, $posx, $posy); + $watermark->clear(); + $watermark->destroy(); + } else { + imagecopyresampled($img, $watermark, $posx, $posy, 0, 0, $sx, $sy, imagesx($watermark), imagesy($watermark)); + imagedestroy($watermark); + } + } + + private function resizeImage_gd($cacheFileName, $width, $height, $crop=false, $cropOffset=1, $forceSize=false, $usePiramidalSizes = true, $resize = true) + { + $objImg = null; + if ( file_exists( $this->getFileName() ) ) + { + $imagetype = $this->getOriginalImageType(); + + switch ($imagetype) { + case 'image/gif': + if (function_exists('imageCreateFromGIF')) + { + $objImg = imageCreateFromGIF($this->getFileName()) ; + } + else + { + $objImg = imageCreateFromPNG($this->getFileName()) ; + } + break; + case 'image/jpeg': + $objImg = imageCreateFromJPEG($this->getFileName()) ; + break; + case 'image/png': + $objImg = imageCreateFromPNG($this->getFileName()) ; + break; + case 'image/vnd.wap.wbmp': + $objImg = imageCreateFromWBMP($this->getFileName()); + break; + default: + // $ermsg = $imageInfo['mime'].' images are not supported<br />'; + break; + } + } + + $originalSizes = $this->getOriginalSizes(); + + if (!is_null($objImg)) + { + $finalSizes = $this->resizeImageGetFinalSizes($width, $height, $crop, $cropOffset, $forceSize); + $img = imageCreateTrueColor($crop ? $width : $finalSizes['width'], $crop ? $height : $finalSizes['height']); + $w = imagecolorallocate($img, 255, 255, 255); + imagefill($img, 0, 0, $w); + if($resize) { + imageCopyResampled($img, $objImg, $finalSizes['cropX'], $finalSizes['cropY'], 0, 0, $finalSizes['width'], $finalSizes['height'], $originalSizes['width'], $originalSizes['height']); + $unsharpMask = __Config::get('glizy.media.image.unsharpMask'); + if ($unsharpMask) { + list($a, $r, $t) = explode(',', $unsharpMask); + glz_importLib('phpUnsharpMask/phpUnsharpMask.php'); + phpUnsharpMask::applyUnsharpMask($img, $a, $r, $t); + } + } else { + imageCopy($img, $objImg, 0, 0, 0, 0, $originalSizes['width'], $originalSizes['height']); + } + + if($this->watermark) { + $this->insertWatermark($img, $crop ? $width : $finalSizes['width'], $crop ? $height : $finalSizes['height'], 'gd', false); + } + + imageJPEG($img, $cacheFileName, org_glizy_Config::get('JPG_COMPRESSION') ); + imageDestroy($objImg); + imageDestroy($img); + unset( $objImg ); + unset( $img ); + @touch($cacheFileName, filemtime($this->getFileName())); + @chmod( $cacheFileName, 0777 ); + $retInfo = array( 'imageType' => IMG_JPG, + 'fileName' => $cacheFileName, + 'width' => $crop ? $width : $finalSizes['width'], + 'height' => $crop ? $height : $finalSizes['height'], + 'originalWidth' => $originalSizes['width'], + 'originalHeight' => $originalSizes['height']); + } + else + { + $fileName = org_glizy_Assets::get('ICON_MEDIA_IMAGE'); + list($width, $height, $imagetypes) = getImageSize($fileName); + $retInfo = array( 'imageType' => IMG_GIF, + 'fileName' => $fileName, + 'width' => $width, + 'height' => $height, + 'originalWidth' => $width, + 'originalHeight' => $height); + } + return $retInfo; + } + + + private function resizeImage_im($cacheFileName, $width, $height, $crop=false, $cropOffset=1, $forceSize=false, $usePiramidalSizes = true, $resize = true) + { + if ( file_exists( $this->getFileName() ) ) + { + $originalSizes = $this->getOriginalSizes(); + $finalSizes = $this->resizeImageGetFinalSizes($width, $height, $crop, $cropOffset, $forceSize); + + $filename = utf8_encode(realpath($this->getFileName())); + $cacheFileName = str_replace(__Paths::get('CACHE'), org_glizy_Paths::getRealPath('CACHE'), $cacheFileName); + $thumb = new Imagick(); + $thumb->readImage($this->getFileName()); + if($resize) { + $thumb->resizeImage($finalSizes['width'], $finalSizes['height'], Imagick::FILTER_LANCZOS, 1); + if ($crop) { + $thumb->cropImage($width, $height, -$finalSizes['cropX'], -$finalSizes['cropY']); + } + $thumb->setImageCompressionQuality(org_glizy_Config::get('JPG_COMPRESSION')); + $thumb->stripImage(); + } + + if($this->watermark) { + $this->insertWatermark($thumb, $crop ? $width : $finalSizes['width'], $crop ? $height : $finalSizes['height'], 'Imagick', false); + } + + $thumb->writeImage($cacheFileName); + + $thumb->clear(); + $thumb->destroy(); + @touch($cacheFileName, filemtime($this->getFileName())); + @chmod( $cacheFileName, 0777 ); + $retInfo = array( 'imageType' => IMG_JPG, + 'fileName' => $cacheFileName, + 'width' => $crop ? $width : $finalSizes['width'], + 'height' => $crop ? $height : $finalSizes['height'], + 'originalWidth' => $originalSizes['width'], + 'originalHeight' => $originalSizes['height']); + } + else + { + $fileName = org_glizy_Assets::get('ICON_MEDIA_IMAGE'); + list($width, $height, $imagetypes) = getImageSize($fileName); + $retInfo = array( 'imageType' => IMG_GIF, + 'fileName' => $fileName, + 'width' => $width, + 'height' => $height, + 'originalWidth' => $width, + 'originalHeight' => $height); + } + + return $retInfo; + } + + function resizeImageGetFinalSizes($width, $height, $crop=false, $cropOffset=1, $forceSize=false) + { + $sizes = $this->getOriginalSizes(); + $originalWidth = $sizes['width']; + $originalHeight = $sizes['height']; + $cropX = 0; + $cropY = 0; + // $destHeight = $height; + // $destWidth = $height/$originalHeight*$originalWidth; + + if ( is_null( $originalWidth ) ) return; + + if ( ( $width == '*' || is_null( $width ) || $width == 0 ) && ($height == '*' || is_null( $height ) || $height == 0) ) + { + $width = $originalWidth; + $height = $originalHeight; + } + else if ( $width == '*' || is_null( $width ) || $width == 0 ) + { + $height = intval($height); + $width = round($originalWidth * $height / $originalHeight); + } + else if( $height == '*' || is_null( $height ) || $height == 0 ) + { + $width = intval($width); + $height = round($originalHeight * $width / $originalWidth); + } + else + { + $width = intval($width); + $height = intval($height); + if (!$crop) + { + if (!$forceSize) + { + if (($originalWidth/$originalHeight) > ($width/$height)) + { + $height = round($originalHeight * $width / $originalWidth); + } + else + { + $width = round($originalWidth * $height / $originalHeight); + } + } + } + else + { + if (($originalWidth/$originalHeight) > ($width/$height)) + { + $destHeight = $height; + $destWidth = $height/$originalHeight*$originalWidth; + switch ($cropOffset) + { + case 0: + break; + case 1: + $cropX = round(($width-$destWidth)/2); + break; + case 2: + $cropX = round($width-$destWidth); + break; + } + } + else + { + $destWidth = $width; + $destHeight = $width/$originalWidth*$originalHeight; + switch ($cropOffset) + { + case 0: + break; + case 1: + $cropY = round(($height-$destHeight)/2); + break; + case 2: + $cropY = round($height-$destHeight); + break; + } + } + } + } + + if (!isset($destWidth)) + { + + $destWidth = $width; + $destHeight = $height; + } + if (!$this->allowDownload) { + $maxWidth = intval(__Config::get('IMG_DOWNLOAD_WIDTH')); + $maxHeight = intval(__Config::get('IMG_DOWNLOAD_HEIGHT')); + if ($maxWidth && $maxHeight && ($maxWidth < $destWidth || $maxHeight < $destHeight)) { + $destWidth = min($maxWidth, $destWidth); + $destHeight = min($maxHeight, $destHeight); + if (!$crop) { + $destWidth = $originalWidth/$originalHeight > 1 ? '*' : $destWidth; + $destHeight = $originalWidth/$originalHeight > 1 ? $destHeight : '*'; + } + return $this->resizeImageGetFinalSizes($destWidth, $destHeight, $crop, $cropOffset, $forceSize); + } + } + + return array('width' => intval($destWidth), 'height' => intval($destHeight), 'cropX' => $cropX, 'cropY' => $cropY); + } + + function _verifyCache( $width, $height, $crop, $cropOffset, $forceSize) + { + $cacheOptions = array( + 'cacheDir' => org_glizy_Paths::get('CACHE_IMAGES'), + 'lifeTime' => org_glizy_Config::get('CACHE_IMAGES'), + 'readControlType' => '', + 'fileExtension' => '.jpg' + ); + + $this->_cacheObj = &org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFile', $cacheOptions); + $fileName = $this->getFileName().$width.'_'.$height.'_'.($crop ? '1' : '0').'_'.$cropOffset.'_'.($forceSize ? '1' : '0').'_'.($this->watermark ? '1' : '0'); + return $this->_cacheObj->verify($fileName, get_class($this), false, $this->getFileName()); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/media/Media.php b/src/core/classes/org/glizycms/mediaArchive/media/Media.php new file mode 100755 index 0000000..ef9eb65 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/media/Media.php @@ -0,0 +1,149 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizycms_mediaArchive_media_Media extends GlizyObject +{ + var $id; + var $fileName; + var $size; + var $type; + var $title; + var $description; + var $creationDate; + var $modificationDate; + var $category; + var $author; + var $date; + var $originalFileName; + var $copyright; + var $allowDownload; + var $watermark; + var $ar; + + function __construct(&$ar) + { + if ( is_object( $ar ) ) + { + $this->ar = $ar; + $this->id = $ar->media_id; + $this->fileName = $ar->media_fileName; + $this->size = $ar->media_size; + $this->type = $ar->media_type; + $this->title = glz_encodeOutput($ar->media_title); + $this->description = $ar->media_description; + $this->creationDate = $ar->media_creationDate; + $this->modificationDate = $ar->media_modificationDate; + $this->category = $ar->media_category; + $this->author = $ar->media_author; + $this->date = $ar->media_date; + $this->zoom = $ar->media_zoom; + $this->originalFileName = $ar->media_originalFileName ? $ar->media_originalFileName : $ar->media_fileName; + $this->copyright = $ar->media_copyright; + $this->allowDownload = $ar->media_allowDownload; + $this->watermark = $ar->media_watermark; + } + else + { + $this->id = $ar['media_id']; + $this->fileName = $ar['media_fileName']; + $this->size = $ar['media_size']; + $this->type = $ar['media_type']; + $this->title = glz_encodeOutput($ar['media_title']); + $this->creationDate = $ar['media_creationDate']; + $this->modificationDate = $ar['media_modificationDate']; + $this->category = $ar['media_category']; + $this->author = $ar['media_author']; + $this->date = $ar['media_date']; + $this->zoom = $ar['media_zoom']; + $this->originalFileName = !empty($ar['media_originalFileName']) ? $ar['media_originalFileName'] : $ar['media_fileName']; + $this->copyright = $ar['media_copyright']; + $this->allowDownload = $ar['media_allowDownload']; + $this->watermark = $ar['media_watermark']; + } + } + + function isMapped() + { + return preg_match('/([^:]+):\/\/(.+)/', $this->fileName); + } + + function getFileName( $checkIfExists=true ) + { + $file = $this->resolveFileName(); + + if ( !$checkIfExists ) { + return $file; + } else { + return file_exists($file) ? $file : org_glizy_Assets::get('ICON_MEDIA_IMAGE'); + } + } + + function exists() + { + $file = $this->resolveFileName(); + return file_exists($file); + } + + function getIconFileName() + { + return org_glizy_Assets::get('ICON_MEDIA_IMAGE'); + } + + function getResizeImage($width, $height, $crop=false, $cropOffset=1, $forceSize=false, $returnResizedDimension=true, $usePiramidalSizes = true) + { + return array('imageType' => IMG_JPG, 'fileName' => $this->getIconFileName(), 'width' => NULL, 'height' => NULL, 'originalWidth'=> NULL, 'originalHeight'=> NULL); + } + + function getThumbnail( $width, $height, $crop=false, $cropOffset = 0 ) + { + $iconPath = $this->getIconFileName(); + // controlla se c'è un'anteprima associata + if ( !empty( $this->ar->media_thumbFileName ) ) + { + // TODO: da implementare meglio in modo che i metodi di resize + // non siano in Image ma comuni a tutti i media + $this->ar->media_fileName = $this->ar->media_thumbFileName; + $this->ar->media_type = 'IMAGE'; + $media = org_glizycms_mediaArchive_MediaManager::getMediaByRecord( $this->ar ); + return $media->getThumbnail( $width, $height ); + } + list( $originalWidth, $originalHeight, $imagetypes ) = getImageSize($iconPath); + return array('fileName' => $iconPath, 'width' => $originalWidth, 'height' => $originalHeight); + } + + function addDownloadCount() + { + $this->ar->media_download++; + $this->ar->save(); + } + + private function resolveFileName() + { + // gestione mapping delle cartelle + if (__Config::get('glizycms.mediaArchive.mediaMappingEnabled') && preg_match('/([^:]+):\/\/(.+)/', $this->fileName, $m)) { + $application = org_glizy_ObjectValues::get('org.glizy', 'application' ); + if ($application) { + $mappingService = $application->retrieveProxy('org.glizycms.mediaArchive.services.MediaMappingService'); + } else { + $mappingService = org_glizy_objectFactory::createObject('org.glizycms.mediaArchive.services.MediaMappingService'); + } + $targetPath = $mappingService->getMapping($m[1]); + $this->fileName = $targetPath.'/'.$m[2]; + } + + if ( strpos( $this->fileName, '/' ) === false ) { + $file = org_glizy_Paths::get('APPLICATION_MEDIA_ARCHIVE').ucfirst(strtolower($this->type)).'/'.$this->fileName; + } else { + $file = $this->fileName; + } + + return $file; + } +} diff --git a/src/core/classes/org/glizycms/mediaArchive/media/Office.php b/src/core/classes/org/glizycms/mediaArchive/media/Office.php new file mode 100755 index 0000000..be888a0 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/media/Office.php @@ -0,0 +1,16 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_media_Office extends org_glizycms_mediaArchive_media_Media +{ + function getIconFileName() + { + return org_glizy_Assets::get('ICON_MEDIA_OFFICE'); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/media/Other.php b/src/core/classes/org/glizycms/mediaArchive/media/Other.php new file mode 100755 index 0000000..2f875e2 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/media/Other.php @@ -0,0 +1,16 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_media_Other extends org_glizycms_mediaArchive_media_Media +{ + function getIconFileName() + { + return org_glizy_Assets::get('ICON_MEDIA_OTHER'); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/media/Pdf.php b/src/core/classes/org/glizycms/mediaArchive/media/Pdf.php new file mode 100755 index 0000000..0228f76 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/media/Pdf.php @@ -0,0 +1,15 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ +class org_glizycms_mediaArchive_media_Pdf extends org_glizycms_mediaArchive_media_Media +{ + function getIconFileName() + { + return org_glizy_Assets::get('ICON_MEDIA_PDF'); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/media/Video.php b/src/core/classes/org/glizycms/mediaArchive/media/Video.php new file mode 100755 index 0000000..bd2d843 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/media/Video.php @@ -0,0 +1,16 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_media_Video extends org_glizycms_mediaArchive_media_Media +{ + function getIconFileName() + { + return org_glizy_Assets::get('ICON_MEDIA_VIDEO'); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/models/Exif.xml b/src/core/classes/org/glizycms/mediaArchive/models/Exif.xml new file mode 100644 index 0000000..db48740 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/models/Exif.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="exif_tbl" model:usePrefix="true"> +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/models/proxy/MediaProxy.php b/src/core/classes/org/glizycms/mediaArchive/models/proxy/MediaProxy.php new file mode 100644 index 0000000..ffc1b46 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/models/proxy/MediaProxy.php @@ -0,0 +1,196 @@ +<?php + +class org_glizycms_mediaArchive_models_proxy_MediaProxy extends GlizyObject +{ + const NONE = 0; + const MOVE_TO_CMS = 1; + const COPY_TO_CMS = 2; + + public function deleteMedia($id) + { + $media = org_glizycms_mediaArchive_MediaManager::getMediaById($id); + + if (!$media->isMapped()) { + $fileName = $media->getFileName(); + + if (file_exists($fileName) && $media->getIconFileName() != $fileName) { + unlink($fileName); + } + } + + $media->ar->delete($id); + + if (__Config::get('glizycms.mediaArchive.exifEnabled')) { + $exifService = org_glizy_ObjectFactory::createObject('org.glizycms.mediaArchive.services.ExifService'); + $exifService->delete($id); + } + + } + + public function getMediaJson($mediaMappingName) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.models.Media'); + $result = $ar->find(array('media_fileName' => $mediaMappingName)); + if ($result) { + return org_glizycms_Glizycms::getMediaArchiveBridge()->getJsonFromAr($ar); + } else { + return null; + } + } + + protected function createMediaRecord($data) + { + $filePath = $data->__filePath; + $originalFileName = $data->__originalFileName; + $fileExtension = strtolower(pathinfo($data->__originalFileName, PATHINFO_EXTENSION)); + $fileType = org_glizycms_mediaArchive_MediaManager::getMediaTypeFromExtension($fileExtension); + $media = org_glizy_ObjectFactory::createModel('org.glizycms.models.Media'); + $media->media_fileName = $originalFileName; + $media->media_originalFileName = $originalFileName; + $media->media_size = 0; + $media->media_type = $fileType; + $media->media_FK_user_id = org_glizy_ObjectValues::get('org.glizy', 'userId'); + $media->media_creationDate = new org_glizy_types_DateTime(); + $media->media_modificationDate = new org_glizy_types_DateTime(); + $media->media_download = 0; + if($fileExtension == 'tif' || $fileExtension =='tiff') { + $media->media_watermark = 1; + $media->media_allowDownload = 0; + } else { + $media->media_watermark = 0; + $media->media_allowDownload = 1; + } + + foreach ($data as $k => $v) { + // remove the system values + if (strpos($k, '__') === 0 || !$media->fieldExists($k)) continue; + $media->$k = $v; + } + + $mediaId = $media->save(); + + return $mediaId; + } + + protected function copyFileInArchive($action, $filePath, $originalFileName, $fileType) + { + $file_destname = md5(time()) . "_" . $originalFileName; + $destinationFolder = org_glizy_Paths::get('APPLICATION_MEDIA_ARCHIVE').ucfirst(strtolower($fileType)); + $fileDestinationPath = $destinationFolder.'/'.$file_destname; + + // verifica che la cartella di destinazione sia scrivibile + if (!is_writeable($destinationFolder)) { + return array('status' => false, 'errors' => array('Rendere scrivibile la cartella '.$destinationFolder)); + } + + if ($action == self::MOVE_TO_CMS) { + rename($filePath, $fileDestinationPath); + } else if ($action == self::COPY_TO_CMS) { + copy($filePath, $fileDestinationPath); + } + + return array('status' => true, 'destName' => $file_destname, 'destPath' => $fileDestinationPath); + } + + public function saveMedia($data, $action = self::MOVE_TO_CMS, $createRecordIfFileNotExists = false) + { + $filePath = $data->__filePath; + $filePathThumb = property_exists($data, '__filePathThumb') ? $data->__filePathThumb : ''; + // controlla che il file esista + if (!file_exists($filePath)) { + if ($createRecordIfFileNotExists) { + return $this->createMediaRecord($data); + } else { + return array('errors' => array('Il file '.$filePath.' non esiste')); + } + } + + $originalFileName = $data->__originalFileName; + + $fileSize = filesize($filePath); + $fileExtension = strtolower(pathinfo($data->__originalFileName, PATHINFO_EXTENSION)); + $fileType = org_glizycms_mediaArchive_MediaManager::getMediaTypeFromExtension($fileExtension); + $saveExifData = __Config::get('glizycms.mediaArchive.exifEnabled') && $fileType == 'IMAGE'; + if ($saveExifData) { + $exif = @exif_read_data($filePath); + } + + + if ($action != self::NONE) { + $r = $this->copyFileInArchive($action, $filePath, $originalFileName, $fileType); + if (!$r['status']) { + return $r; + } + + $data->media_fileName = $r['destName']; + $fileDestinationPath = $r['destPath']; + + if ($filePathThumb) { + $r = $this->copyFileInArchive($action, $filePathThumb, 'thumb_'.$originalFileName, $fileType); + if (!$r['status']) { + return $r; + } + $filePathThumb = $r['destName']; + } + /* + $file_destname = md5(time()) . "_" . $originalFileName; + $destinationFolder = org_glizy_Paths::get('APPLICATION_MEDIA_ARCHIVE').ucfirst(strtolower($fileType)); + $fileDestinationPath = $destinationFolder.'/'.$file_destname; + $data->media_fileName = $file_destname; + + // verifica che la cartella di destinazione sia scrivibile + if (!is_writeable($destinationFolder)) { + return array('errors' => array('Rendere scrivibile la cartella '.$destinationFolder)); + } + + if ($action == self::MOVE_TO_CMS) { + rename($filePath, $fileDestinationPath); + } else if ($action == self::COPY_TO_CMS) { + copy($filePath, $fileDestinationPath); + } + + */ + } else { + $fileDestinationPath = $filePath; + } + + $media = org_glizy_ObjectFactory::createModel('org.glizycms.models.Media'); + $media->media_originalFileName = $originalFileName; + $media->media_thumbFileName = $filePathThumb; + $media->media_size = $fileSize; + $media->media_type = $fileType; + $media->media_FK_user_id = org_glizy_ObjectValues::get('org.glizy', 'userId'); + $media->media_creationDate = new org_glizy_types_DateTime(); + $media->media_modificationDate = new org_glizy_types_DateTime(); + $media->media_download = 0; + $media->media_md5 = md5_file($fileDestinationPath); + if($fileExtension == 'tif' || $fileExtension =='tiff') { + $media->media_watermark = 1; + $media->media_allowDownload = 0; + } else { + $media->media_allowDownload = 1; + $media->media_watermark = 0; + } + + foreach ($data as $k => $v) { + // remove the system values + if (strpos($k, '__') === 0 || !$media->fieldExists($k)) continue; + $media->$k = $v; + } + + if ($saveExifData) { + if ($exif['COMPUTED']['Copyright'] && empty($ar->media_copyright)) { + $ar->media_copyright = $exif['COMPUTED']['Copyright']; + } + } + + $mediaId = $media->save(); + + if ($saveExifData) { + $exifService = org_glizy_ObjectFactory::createObject('org.glizycms.mediaArchive.services.ExifService'); + $exifService->saveExifData($mediaId, $exif); + } + + return $mediaId; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/services/ExifService.php b/src/core/classes/org/glizycms/mediaArchive/services/ExifService.php new file mode 100644 index 0000000..66b104b --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/services/ExifService.php @@ -0,0 +1,122 @@ +<?php +class org_glizycms_mediaArchive_services_ExifService extends GlizyObject +{ + public function saveExifData($mediaId, $exif) + { + if (strpos($exif['SectionsFound'], 'EXIF') !== false) { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.mediaArchive.models.Exif'); + $ar->exif_FK_media_id = $mediaId; + $ar->exif_imageWidth = $exif['COMPUTED']['Width']; + $ar->exif_imageHeight = $exif['COMPUTED']['Height']; + $ar->exif_resolution = $this->getResolution($exif['XResolution'], $exif['YResolution'], $exif['ResolutionUnit']); + $ar->exif_make = $exif['Make']; + $ar->exif_model = $exif['Model']; + $ar->exif_exposureTime = $this->simplify($exif['ExposureTime']); + $ar->exif_fNumber = $exif['FNumber']; + $ar->exif_exposureProgram = $exif['ExposureProgram']; + $ar->exif_ISOSpeedRatings = $exif['ISOSpeedRatings']; + $ar->exif_dateTimeOriginal = $exif['DateTimeOriginal']; + $ar->exif_dateTimeDigitized = $exif['DateTimeDigitized']; + $ar->exif_GPSCoords = $this->getGPSCoords($exif['GPSLatitudeRef'], $exif['GPSLatitude'], $exif['GPSLongitudeRef'], $exif['GPSLongitude']); + $ar->exif_GPSTimeStamp = $this->getGPSTime($exif['GPSTimeStamp'], ':'); + $ar->exif_data = utf8_encode(serialize($exif)); + $ar->save(); + } + } + + public function delete($mediaId) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.mediaArchive.models.Exif'); + $ar->delete(array('exif_FK_media_id' => $mediaId)); + } + + protected function getResolution($xResolution, $yResolution, $resolutionUnit) + { + if (!$xResolution) { + return ''; + } + + $xResolution = $this->eval_rational($xResolution); + $yResolution = $this->eval_rational($yResolution); + + if ($resolutionUnit == 3) { + return $xResolution/2.54 . 'x' . $yResolution/2.54; + } + else { + return $xResolution . 'x' . $yResolution; + } + } + + protected function getGPSCoords($latRef, $lat, $longRef, $long, $glue=', ') + { + if (is_null($latRef)) { + return null; + } + + $latValue = $this->eval_rational($lat[0]) + $this->eval_rational($lat[1])/60 + $this->eval_rational($lat[2])/3600; + $longValue = $this->eval_rational($long[0]) + $this->eval_rational($long[1])/60 + $this->eval_rational($long[2])/3600; + + if ($latRef == 'S') { + $latValue = -$latValue; + } + + if ($longRef == 'W') { + $longValue = -$longValue; + } + + return $latValue.$glue.$longValue; + } + + protected function getGPSTime($gpsValArray, $glue=', ') + { + if (is_null($gpsValArray)) { + return null; + } + + $v = array ( + $this->eval_rational($gpsValArray[0]), + $this->eval_rational($gpsValArray[1]), + $this->eval_rational($gpsValArray[2]) + ); + + return implode($glue, $v); + } + + protected function gcd($a,$b) + { + $a = abs($a); $b = abs($b); + if( $a < $b) list($b,$a) = array($a,$b); + if( $b == 0) return $a; + $r = $a % $b; + while($r > 0) { + $a = $b; + $b = $r; + $r = $a % $b; + } + return $b; + } + + protected function simplify($e) + { + list($n, $d) = explode('/', $e); + + if ($d == 0) { + return ''; + } + + $g = $this->gcd($n, $d); + + return $n/$g . '/'. $d/$g; + } + + protected function eval_rational($e) + { + list($n, $d) = explode('/', $e); + + if ($d == 0) { + return ''; + } + + return $n / $d; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/services/MediaMappingService.php b/src/core/classes/org/glizycms/mediaArchive/services/MediaMappingService.php new file mode 100755 index 0000000..f2605f9 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/services/MediaMappingService.php @@ -0,0 +1,183 @@ +<?php +class org_glizycms_mediaArchive_services_MediaMappingService extends GlizyObject +{ + protected $init = false; + protected $source = null; + protected $fileSystemMap = array(); + + public function __construct() + { + } + + public function init() + { + if (isset($_SERVER['GLIZY_APPNAME'])) { + $serverName = $_SERVER['GLIZY_APPNAME']; + $filename = 'filesystem_'.$serverName.'.xml'; + } + else { + $filename = 'filesystem.xml'; + } + + $this->source = __Paths::get('APPLICATION_TO_ADMIN').'config/'.$filename; + + if (!file_exists($this->source)) { + $this->source = __Paths::get('APPLICATION').'config/'.$filename; + } + + $options = array( + 'cacheDir' => org_glizy_Paths::get('CACHE_CODE'), + 'lifeTime' => -1, + 'readControlType' => '', + 'fileExtension' => '.php' + ); + $cacheObj = &org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFile', $options ); + $cacheFileName = $cacheObj->verify( $this->source, get_class( $this ) ); + + if ( $cacheFileName === false ) + { + $this->loadXml(); + $cacheObj->save( serialize( $this->fileSystemMap ), NULL, get_class( $this ) ); + $cacheObj->getFileName(); + } + else + { + $this->fileSystemMap = unserialize( file_get_contents( $cacheFileName ) ); + } + + $this->init = true; + } + + function checkInit() + { + if (!$this->init) { + $this->init(); + } + } + + function onRegister() { + + } + + private function invalidate() + { + $options = array( + 'cacheDir' => org_glizy_Paths::get('CACHE_CODE'), + 'lifeTime' => -1, + 'readControlType' => '', + 'fileExtension' => '.php' + ); + $cacheObj = &org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFile', $options ); + $cacheObj->remove( $this->source, get_class( $this ) ); + } + + private function loadXml() + { + $xml = org_glizy_ObjectFactory::createObject('org.glizy.parser.XML'); + $xml->loadAndParseNS($this->source); + $folders = $xml->getElementsByTagName('Folder'); + + $this->fileSystemMap = array(); + + foreach ($folders as $folder) { + $this->fileSystemMap[$folder->getAttribute('name')] = $folder->getAttribute('target'); + } + } + + private function saveMappingXML($name, $target) + { + $xml = org_glizy_ObjectFactory::createObject('org.glizy.parser.XML'); + $xml->loadAndParseNS($this->source); + + $xpath = new DOMXpath($xml); + $elements = $xpath->query('/glz:FileSystem/glz:Folder[@name="'.$name.'"]'); + + if ($elements->length == 1) { + $folder = $elements->item(0); + } + else { + $folder = $xml->createElement('glz:Folder'); + $folder->setAttribute('name', $name); + $root = $xml->childNodes->item(0); + $root->appendChild($folder); + } + + $folder->setAttribute('target', $target); + + $xml->formatOutput = true; + $xml->save($this->source); + + $this->invalidate(); + } + + private function deleteMappingXML($name) + { + $xml = org_glizy_ObjectFactory::createObject('org.glizy.parser.XML'); + $xml->loadAndParseNS($this->source); + + $xpath = new DOMXpath($xml); + $elements = $xpath->query('/glz:FileSystem/glz:Folder[@name="'.$name.'"]'); + + if ($elements->length == 1) { + $folder = $elements->item(0); + $root = $xml->childNodes->item(0); + $root->removeChild($folder); + + $xml->formatOutput = true; + $xml->save($this->source); + + $this->invalidate(); + } + } + + // esempio di filePath: folder1/folder2/filename + // dove folder1 è la cartella mappata da risolvere + public function getRealPath($filePath) + { + $slashPos = strpos($filePath, '/'); + $folderName = substr($filePath, 0, $slashPos); + $target = substr($filePath, $slashPos); + return $this->getMapping($folderName) . $target; + } + + public function getMapping($name) + { + $this->checkInit(); + return $this->fileSystemMap[$name]; + } + + public function getPathFromMapping ($map) { + if (__Config::get('glizycms.mediaArchive.mediaMappingEnabled')) { + $m = explode('/', $map, 2); + $application = org_glizy_ObjectValues::get('org.glizy', 'application' ); + if ($application) { + $mappingService = $application->retrieveProxy('org.glizycms.mediaArchive.services.MediaMappingService'); + } else { + $mappingService = org_glizy_objectFactory::createObject('org.glizycms.mediaArchive.services.MediaMappingService'); + } + $targetPath = $mappingService->getMapping($m[0]); + $map = $m[1] ? $targetPath.'/'.$m[1] : $targetPath; + } + return $map; + } + + public function setMapping($name, $target) + { + $this->checkInit(); + $this->saveMappingXML($name, $target); + return $this->fileSystemMap[$name] = $target; + } + + public function deleteMapping($name) + { + $this->checkInit(); + $this->deleteMappingXML($name); + unset($this->fileSystemMap[$name]); + } + + public function getAllMappings() + { + $this->checkInit(); + return $this->fileSystemMap; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/views/MediaArchive.xml b/src/core/classes/org/glizycms/mediaArchive/views/MediaArchive.xml new file mode 100644 index 0000000..6512ef3 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/views/MediaArchive.xml @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:ma="org.glizycms.mediaArchive.views.components.*" + controllerName="org.glizycms.mediaArchive.controllers.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Page.php"> + <glz:Import src="_common.xml" /> + + <mvc:StateTabNavigation id="tab" cssClass="nav nav-tabs" cssClassCurrent="active" visible="false" /> + + <mvc:State name="index"> + <glz:TabGroup id="tabs" defaultState="allMedia" cssClass="nav nav-pills" rememberState="true"> + <glz:Tab name="allMedia" label="{i18n:MW_SM_SHOW_ALL_MEDIA}"></glz:Tab> + <glz:Tab name="allImage" label="{i18n:MW_SM_SHOW_IMAGES}"></glz:Tab> + <glz:Tab name="allOffice" label="{i18n:MW_SM_SHOW_DOCUMENTS}"></glz:Tab> + <glz:Tab name="allPdf" label="{i18n:MW_SM_SHOW_PDF}"></glz:Tab> + <glz:Tab name="allArchive" label="{i18n:MW_SM_SHOW_COMPRESSED}"></glz:Tab> + <glz:Tab name="allAudio" label="{i18n:MW_SM_SHOW_AUDIO_FILES}"></glz:Tab> + <glz:Tab name="allVideo" label="{i18n:MW_SM_SHOW_VIDEO}"></glz:Tab> + </glz:TabGroup> + + <cms:VisualSearch id="filters" label="{i18n:Search}" cssClass="row-fluid clearfix my-filters" model="org.glizycms.models.Media"> + <cms:VisualSearchItem id="media_author" label="{i18n:Author}" type="facet" /> + <cms:VisualSearchItem id="media_category" label="{i18n:Category}" type="facet" /> + <cms:VisualSearchItem id="media_description" label="{i18n:Description}" /> + <cms:VisualSearchItem id="media_originalFileName" label="{i18n:File name}" /> + <cms:VisualSearchItem id="media_title" label="{i18n:Title}" /> + + <glz:Panel cssClass="pull-left"> + <glz:HtmlButton label="{i18n:GLZ_SEARCH}" value="SEARCH" target="{filters}" cssClass="btn btn-primary" /> + <glz:HtmlButton label="{i18n:GLZ_RESET}" value="RESET" target="{filters}" cssClass="btn" /> + </glz:Panel> + </cms:VisualSearch> + + <glz:Panel cssClass="row-fluid"> + <glz:Script extendParent="true"><![CDATA[ +public function render_html_onStart() +{ + $this->_application->addLightboxJsCode(); + parent::render_html_onStart(); +} + ]]></glz:Script> + + <glz:DataProvider id="dp" recordClassName="org.glizycms.models.Media" order="media_title" queryOperator="OR" /> + <glz:RecordSetList id="list" dataProvider="{dp}" processCell="org.glizycms.mediaArchive.views.renderer.CellMediaArchive" paginate="{paginate}" filters="{filters}" skin="{listSKIN}" /> + <glz:PaginateResult id="paginate" pageLength="42" cssClass="pagination" showTotal="true" /> + </glz:Panel> + + <glz:Link id="deleteSelectedButton" label="{i18n:Delete selected}" cssClass="{config:glizycms.form.actionLink.cssClass}" icon="icon-remove" routeUrl="" editableRegion="actions" acl="*,delete"/> + <glz:Link label="{i18n:MW_MEDIA_ADD}" cssClass="{config:glizycms.form.actionLink.cssClass}" icon="icon-plus" routeUrl="glizycmsMediaArchiveAdd" editableRegion="actions" acl="*,new"/> + + <glz:JSscript><![CDATA[ + $(document).ready(function() { + $('#deleteSelectedButton').addClass('disabled'); + + $('#deleteSelectedButton').on('click', function() { + var pattern = new RegExp("disabled"); + if (!pattern.test($(this).prop('class'))) { + if (confirm('{i18n:Do you want to confirm the deletion?}')) { + var removalList = new Array(); + $('[id^=mediacheckbox]').each(function() { + if ($(this).is(':checked')) { + removalList.push($(this).prop('id').split('_')[1]); + } + }); + + if (removalList.length) { + $('#deleteSelectedButton').addClass('disabled'); + var ids = removalList.join(','); + $.ajax({ + type: 'POST', + url: Glizy.ajaxUrl + 'Delete', + data: 'ids=' + ids, + success: function(data) { + location.reload(); + }, + error: function() { + alert('{i18n:Error}'); + $('#deleteSelectedButton').removeClass('disabled'); + } + }); + } + } + } else { + + } + + return false; + }); + + $('[id^=mediacheckbox]').on('change', function() { + var oneChecked = false; + $('[id^=mediacheckbox]').each(function() { + if ($(this).is(':checked')) { + oneChecked = true; + return; + } + }); + + if (oneChecked) { + $('#deleteSelectedButton').removeClass('disabled'); + } else { + $('#deleteSelectedButton').addClass('disabled'); + } + }); + }); + ]]></glz:JSscript> + </mvc:State> + + <mvc:State name="add" label="{i18n:MW_MEDIA_ADD}"> + <glz:Modifier target="tab" attribute="visible" value="true" /> + <cms:FormEdit id="myForm" controllerName="org.glizycms.mediaArchive.controllers.mediaEdit.*" > + <glz:Input id="fileuploader" label="{i18n:GLZ_UPLOAD}" data="type=file;fieldsetid=medias" /> + <glz:Fieldset id="medias" label="Media" data="type=repeat;collapsable=false;noAddRowButton=true"> + <glz:Hidden id="__uploadFilename" /> + <glz:Hidden id="__originalFileName" /> + <glz:Input id="media_title" label="{i18n:Title}" size="90" required="true" /> + <glz:Input id="media_category" label="{i18n:Category}" data="type=selectfrom;multiple=true;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_author" label="{i18n:Author}" data="type=selectfrom;multiple=false;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_date" label="{i18n:Date}" size="90" /> + <glz:Input id="media_copyright" label="{i18n:Copyright}" data="type=selectfrom;multiple=false;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_description" label="{i18n:Description}" size="90" type="multiline" rows="10" cols="70" htmlEditor="true" data="type=tinymce" /> + <glz:Checkbox id="media_zoom" label="{i18n:Show zoom}" /> + <glz:Checkbox id="media_allowDownload" label="{i18n:Allow download}" /> + <glz:Checkbox id="media_watermark" label="{i18n:Insert watermark}" /> + </glz:Fieldset> + <cms:FormButtonsPanel> + <!--<glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" />--> + <glz:HtmlButton label="{i18n:GLZ_SAVE_CLOSE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=saveClose" /> + <glz:HtmlButton label="{i18n:GLZ_CLOSE}" type="button" cssClass="btn js-glizycms-cancel" data="action=cancel" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State id="addFromServer" name="addFromServer" label="Aggiungi file da server"> + <glz:Modifier target="tab" attribute="visible" value="true" /> + <cms:FormEdit id="myForm" controllerName="org.glizycms.mediaArchive.controllers.mediaEdit.*" > + <ma:FilePicker id="mediaFileServer" pageId="MediaStorageBrowser" label="{i18n:File}" required="true"/> + <glz:Input id="media_title" label="{i18n:Title}" size="90" required="true" /> + <glz:Input id="media_category" label="{i18n:Category}" data="type=selectfrom;multiple=true;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_author" label="{i18n:Author}" data="type=selectfrom;multiple=false;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_date" label="{i18n:Date}" size="90" /> + <glz:Input id="media_copyright" label="{i18n:Copyright}" data="type=selectfrom;multiple=false;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_description" label="{i18n:Description}" size="90" type="multiline" rows="10" cols="70" htmlEditor="true" data="type=tinymce" /> + <glz:Checkbox id="media_zoom" label="{i18n:Show zoom}" /> + <glz:Checkbox id="media_allowDownload" label="{i18n:Allow download}" data="type=checkbox" defaultValue="1" /> + <glz:Checkbox id="media_watermark" label="{i18n:Insert watermark}" /> + <glz:Panel cssClass="formButtons"> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <glz:HtmlButton label="{i18n:GLZ_SAVE_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=saveClose" /> + <glz:HtmlButton label="{i18n:GLZ_CLOSE}" type="button" cssClass="btn js-glizycms-cancel" data="action=cancel" /> + </glz:Panel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="edit,delete"> + <cms:FormEdit id="myForm" controllerName="org.glizycms.mediaArchive.controllers.mediaEdit.*" > + <glz:Hidden id='media_id' /> + <glz:Input id="media_originalFileName" label="{i18n:File name}" size="90" disabled="true"/> + <glz:JSTabGroup id="editImage" visible="true"> + <glz:JSTab id="generalData" label="{i18n:General data}"> + <glz:Input id="media_title" label="{i18n:Title}" size="90" required="true" /> + <glz:Input id="media_category" label="{i18n:Category}" data="type=selectfrom;multiple=true;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_author" label="{i18n:Author}" data="type=selectfrom;multiple=false;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_date" label="{i18n:Date}" size="90" /> + <glz:Input id="media_copyright" label="{i18n:Copyright}" data="type=selectfrom;multiple=false;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_description" label="{i18n:Description}" size="90" type="multiline" rows="10" cols="70" htmlEditor="true" data="type=tinymce" /> + <glz:Checkbox id="media_zoom" label="{i18n:Show zoom}" /> + <glz:Checkbox id="media_allowDownload" label="{i18n:Allow download}" data="type=checkbox" defaultValue="1"/> + <glz:Checkbox id="media_watermark" label="{i18n:Insert watermark}" /> + <glz:Input id="media_download" label="{i18n:Downloads}" size="90" disabled="true"/> + </glz:JSTab> + <glz:JSTab id="exifData" label="{i18n:Exif data}"> + <ma:ShowExif imageId="{php:__Request::get(id)}"/> + </glz:JSTab> + </glz:JSTabGroup> + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <glz:HtmlButton label="{i18n:GLZ_SAVE_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=saveClose" /> + <glz:HtmlButton label="{i18n:GLZ_CLOSE}" type="button" cssClass="btn js-glizycms-cancel" data="action=cancel" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + + <glz:SkinDefine id="listSKIN"><![CDATA[ +<span tal:omit-tag=""> + <script> +$("a.lightbox").colorbox({photo:true, maxHeight: 300, maxWidth: 300, scalePhotos: true}); + </script> + <div class="row-fluid"> + <ul class="thumbnails"> + <li class="span2" tal:repeat="item Component/records"> + <input type="checkbox" tal:attributes="id php: 'mediacheckbox_' . item.media_id" class="delete-media js-delete-media" /> + <a class="thumbnail" tal:attributes="href item/__url__; title php:__T('Edit')"> + <img class="js-glizyMediaPicker" tal:attributes="src item/thumb_filename; id item/media_id; fileName item/media_fileName; title item/media_title; data-type item/media_type" /> + </a> + <div class="title"> + <div class="inner" tal:content="php: glz_strtrim(item.media_title, 20)"></div> + </div> + <div class="actions"> + <a tal:attributes="href item/__urlPreview__; title php:__T('Preview')" class="lightbox"><i class="icon-eye-open icon-white"></i></a> + <a tal:attributes="href item/__urlDownload__; title php:__T('Download')"><i class="icon-download-alt icon-white"></i></a> + <a tal:condition="item/__url__" tal:attributes="href item/__url__; title php:__T('Edit')"><i class="icon-pencil icon-white"></i></a> + <a tal:condition="item/__urlDelete__" onclick="if (!confirm('conferma cancellazione record')){return false;}" tal:attributes="href item/__urlDelete__; title php:__T('Delete')"><i class="icon-remove icon-white"></i></a> + </div> + </li> + </ul> +</div> +</span> + ]]></glz:SkinDefine> + +</mvc:Page> diff --git a/src/core/classes/org/glizycms/mediaArchive/views/MediaPicker.xml b/src/core/classes/org/glizycms/mediaArchive/views/MediaPicker.xml new file mode 100644 index 0000000..3b18af3 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/views/MediaPicker.xml @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:ma="org.glizycms.mediaArchive.views.components.*" + controllerName="org.glizycms.mediaArchive.controllers.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Popup.php"> + + <mvc:StateTabNavigation id="tab" cssClass="nav nav-tabs" cssClassCurrent="active" visible="false" /> + + <mvc:State name="index"> + <glz:Panel cssClass="row-fluid formButtonsTop" editableRegion=""> + <glz:HtmlButton label="{i18n:MW_MEDIA_ADD}" type="button" routeUrl="glizycmsMediaArchiveAdd" cssClass="btn" /> + <glz:Button id="btnNoImage" value="{i18n:MW_NO_MEDIA}" cssClass="btn js-glizycmsMediaPicker-noMedia" /> + </glz:Panel> + <cms:VisualSearch id="filters" label="{i18n:Search}" removeGetValues="false" cssClass="row-fluid clearfix my-filters" model="org.glizycms.models.Media"> + <cms:VisualSearchItem id="media_author" label="{i18n:Author}" type="facet" /> + <cms:VisualSearchItem id="media_category" label="{i18n:Category}" type="facet" /> + <cms:VisualSearchItem id="media_description" label="{i18n:Description}" type="facet" /> + <cms:VisualSearchItem id="media_originalFileName" label="{i18n:File name}" /> + <cms:VisualSearchItem id="media_title" label="{i18n:Title}" /> + + <glz:Panel cssClass="pull-right span2"> + <glz:HtmlButton label="{i18n:GLZ_SEARCH}" value="SEARCH" target="{filters}" cssClass="btn btn-primary" /> + <glz:HtmlButton label="{i18n:GLZ_RESET}" value="RESET" target="{filters}" cssClass="btn" /> + </glz:Panel> + </cms:VisualSearch> + + <glz:Panel cssClass="row-fluid"> + <glz:Script extendParent="true"><![CDATA[ +public function render_html_onStart() +{ + $this->_application->addLightboxJsCode(); + parent::render_html_onStart(); +} + ]]></glz:Script> + + <glz:DataProvider id="dp" recordClassName="org.glizycms.models.Media" order="media_title" queryOperator="OR" > + </glz:DataProvider> + <glz:RecordSetList id="list" dataProvider="{dp}" processCell="org.glizycms.mediaArchive.views.renderer.CellMediaArchive" paginate="{paginate}" filters="{filters}" skin="{listSKIN}" /> + <glz:PaginateResult id="paginate" pageLength="42" cssClass="pagination" /> + </glz:Panel> + </mvc:State> + + <mvc:State name="add" label="Aggiungi media"> + <glz:Modifier target="tab" attribute="visible" value="true" /> + <cms:FormEdit id="myForm" cssClass="form-horizontal row-fluid" controllerName="org.glizycms.mediaArchive.controllers.mediaEdit.*" > + <glz:Input id="fileuploader" label="{i18n:GLZ_UPLOAD}" data="type=file;fieldsetid=medias" /> + <glz:Fieldset id="medias" label="Media" data="type=repeat;collapsable=false;noAddRowButton=true"> + <glz:Hidden id="__uploadFilename" /> + <glz:Hidden id="__originalFileName" /> + <glz:Input id="media_title" label="{i18n:Title}" size="90" required="true" /> + <glz:Input id="media_category" label="{i18n:Category}" data="type=selectfrom;multiple=true;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_author" label="{i18n:Author}" data="type=selectfrom;multiple=false;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_date" label="{i18n:Date}" size="90" /> + <glz:Input id="media_copyright" label="{i18n:Copyright}" data="type=selectfrom;multiple=false;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_description" label="{i18n:Description}" size="90" type="multiline" rows="10" cols="70" htmlEditor="true" data="type=tinymce" /> + <glz:Checkbox id="media_zoom" label="{i18n:Show zoom}" /> + <glz:Checkbox id="media_allowDownload" label="{i18n:Allow download}" /> + <glz:Checkbox id="media_watermark" label="{i18n:Insert watermark}" /> + </glz:Fieldset> + <glz:Panel cssClass="formButtons"> + <glz:HtmlButton label="{i18n:GLZ_SAVE_CLOSE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=saveClose" /> + <glz:HtmlButton label="{i18n:GLZ_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=cancel" /> + </glz:Panel> + </cms:FormEdit> + </mvc:State> + + <mvc:State id="addFromServer" name="addFromServer" label="Aggiungi file da server"> + <glz:Modifier target="tab" attribute="visible" value="true" /> + <cms:FormEdit id="myForm" cssClass="form-horizontal row-fluid" controllerName="org.glizycms.mediaArchive.controllers.mediaEdit.*" > + <ma:FilePicker id="mediaFileServer" pageId="MediaStorageBrowser" label="{i18n:File}" required="true"/> + <glz:Input id="media_title" label="{i18n:Title}" size="90" required="true" /> + <glz:Input id="media_category" label="{i18n:Category}" data="type=selectfrom;multiple=true;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_author" label="{i18n:Author}" data="type=selectfrom;multiple=false;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_date" label="{i18n:Date}" size="90" /> + <glz:Input id="media_copyright" label="{i18n:Copyright}" data="type=selectfrom;multiple=false;add_new_values=true;model=org.glizycms.models.Media" size="255" /> + <glz:Input id="media_description" label="{i18n:Description}" size="90" type="multiline" rows="10" cols="70" htmlEditor="true" data="type=tinymce" /> + <glz:Checkbox id="media_zoom" label="{i18n:Show zoom}" /> + <glz:Checkbox id="media_allowDownload" label="{i18n:Allow download}" /> + <glz:Checkbox id="media_watermark" label="{i18n:Insert watermark}" /> + <glz:Panel cssClass="formButtons"> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <glz:HtmlButton label="{i18n:GLZ_SAVE_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=saveClose" /> + <glz:HtmlButton label="{i18n:GLZ_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=cancel" /> + </glz:Panel> + </cms:FormEdit> + </mvc:State> + + <glz:SkinDefine id="listSKIN"><![CDATA[ +<span tal:omit-tag=""> + <script> +$(function(){ + $("a.lightbox").colorbox({photo:true, maxHeight: 300, maxWidth: 300, scalePhotos: true}); + $( "img.js-glizyMediaPicker").click( function(){ + var $img = jQuery( this ); + Glizy.events.broadcast('glizycms.onSetMediaPicker', $img.data("jsonmedia")); + }); + + $( ".js-glizycmsMediaPicker-noMedia").click( function(){ + Glizy.events.broadcast('glizycms.onSetMediaPicker', null); + }); +}); + </script> + <div class="row-fluid"> + <ul class="thumbnails"> + <li class="span2" tal:repeat="item Component/records"> + <a class="thumbnail js-glizyMediaPicker-a" style="cursor:pointer;" tal:attributes="title php:__T('Select')"> + <img class="js-glizyMediaPicker" tal:attributes="src item/thumb_filename; data-id item/media_id; data-filename item/media_fileName; title item/media_title; data-width item/media_w; data-height item/media_h; data-category item/media_category; data-author item/media_author; data-date item/media_date; data-copyright item/media_copyright; data-type item/media_type; data-jsonmedia item/__jsonMedia" /> + </a> + <div class="title"> + <div class="inner" tal:content="php: glz_strtrim(item.media_title, 20)"></div> + </div> + <div class="actions"> + <a tal:attributes="href item/__urlPreview__" class="lightbox"><i class="icon-eye-open icon-white"></i></a> + </div> + </li> + </ul> +</div> +</span> + ]]></glz:SkinDefine> + +</mvc:Page> diff --git a/src/core/classes/org/glizycms/mediaArchive/views/MediaStorageBrowser.xml b/src/core/classes/org/glizycms/mediaArchive/views/MediaStorageBrowser.xml new file mode 100755 index 0000000..fd83e3a --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/views/MediaStorageBrowser.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:ma="org.glizycms.mediaArchive.views.components.*" + baseClassPath="it.gruppometa.iccd" + controllerName="storageBrowser" + defaultEditableRegion="content" + templateType="php" + templateFileName="Popup.php"> + + <mvc:State name="index"> + <!--<glz:Authenticator accessPageId="login" /> + + <glz:ConfigValue key="GLIZY_JS_LIB" value="jquery" action="set" /> + + <glz:MessageBox type="SUCCESS" cssClass="alert alert-success" message="Risultato operazione"/> + <glz:MessageBox type="ERROR" cssClass="alert alert-error" message=""/>--> + + <ma:CustomStorageBrowser id="storageBrowser" /> + + </mvc:State> +</mvc:Page> diff --git a/src/core/classes/org/glizycms/mediaArchive/views/components/CustomStorageBrowser.php b/src/core/classes/org/glizycms/mediaArchive/views/components/CustomStorageBrowser.php new file mode 100644 index 0000000..6d88d30 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/views/components/CustomStorageBrowser.php @@ -0,0 +1,257 @@ +<?php +class org_glizycms_mediaArchive_views_components_CustomStorageBrowser extends org_glizy_components_Component +{ + function init() + { + // define the custom attributes + $this->defineAttribute('filter', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('copyCheckbox', false, true, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + } + + function render() + { + $onlyFolder = __Request::get('onlyFolder'); + $onlyFirstLevel = __Request::get('onlyFirstLevel'); + $customPath = __Request::get('customPath'); + $enableDownload = __Request::get('enableDownload'); + +// TODO localizzare l'interfaccia + $this->_application->_rootComponent->addOutputCode( org_glizy_helpers_JS::JScode( 'if ( typeof(Glizy) == "undefined" ) Glizy = {}; Glizy.baseUrl ="'.GLZ_HOST.'"; Glizy.ajaxUrl = "ajax.php?pageId='.$this->_application->getPageId().'&ajaxTarget='.$this->getId().'&onlyFolder='.$onlyFolder.'&customPath='.$customPath.'&enableDownload='.$enableDownload.'&command=";' ), 'head' ); + $showCopy = $this->getAttribute('copyCheckbox') && !$onlyFolder ? 'true' : 'false'; + $showFolderSelection = $onlyFolder ? 'true' : 'false'; + $showOnlyFirstLevel = $onlyFirstLevel ? 'true' : 'false'; + + $output = <<<EOD +<div id="storageBrowser"></div> +<script type="text/javascript"> +jQuery(document).ready(function() { + var currentFolder = ''; + + function redraw( data ) + { + var html = ''; + if ($showCopy) { + html += '<input name="copyToCMS" id="copyToCMS" type="checkbox" class="pull-left"/>'; + html += '<label for="copyToCMS" class="pull-left">Copia il file nell\'archivio del CMS</label></br></br>'; + } + + html += '<h4>Posizione: root/'+ currentFolder+'</h4>'; + html += '<table id="dataGrid" class="storageBrowser table table-bordered table-striped">'; + html += '<thead><tr>'; + html += '<th class="icon"></th>'; + html += '<th class="filename">Nome file</th>'; + html += '<th class="size">Dimensione</th>'; + html += '<th class="date">Ultima modifica</th>'; + html += '</tr></thead>'; + + var htmlDirs = ''; + var htmlFiles = ''; + jQuery( data ).each( function( index, value ){ + var rowCss = index % 2 ? 'odd' : 'even'; + if ( value.type == "dir" ) + { + htmlDirs += '<tr class="'+rowCss+'" data-path="'+value.path+'" data-type="folder"><td class="icon folder"></td>'; + htmlDirs += '<td class="filename">'+value.name+'</td>'; + htmlDirs += '<td class="size"></td>'; + htmlDirs += '<td class="date"></td>'; + htmlDirs += '</tr>'; + } + else + { + htmlFiles += '<tr class="'+rowCss+'" data-path="'+value.path+'" data-type="file"><td class="icon '+value.icon+'"></td>'; + htmlFiles += '<td class="filename">'+value.name+'</td>'; + htmlFiles += '<td class="size">'+value.size+'</td>'; + htmlFiles += '<td class="date">'+value.date+'</td>'; + htmlFiles += '</tr>'; + } + }); + + html += '<tbody>'+htmlDirs+htmlFiles+'</tbody></table>'; + + if ($showFolderSelection && !$showOnlyFirstLevel ) { + html += '<input value="Seleziona cartella" name="selectFolder" id="selectFolder" type="button" class="btn"/>'; + } + + jQuery('#storageBrowser').html( html ); + } + + function loadFolder() { + jQuery.ajax({ + type: "POST", + url: Glizy.ajaxUrl + "read", + dataType: "json", + data: {path: currentFolder}, + success: function (data) { + // console.log( data ); + redraw( data ); + } + }); + } + + jQuery( document ).on( 'click', '#storageBrowser tbody tr', function( ){ + if ( jQuery( this ).data( 'type' ) == 'folder' ) + { + currentFolder = jQuery( this ).data( 'path' ); + if ($showOnlyFirstLevel) { + parent.custom_storageBrowserSelect(currentFolder); + } else { + loadFolder(); + } + } + else + { + parent.custom_storageBrowserSelect( jQuery( this ).data( 'path' ) ); + } + }) + + jQuery( document ).on('change', '#copyToCMS', function () { + parent.setCopyToCMS( jQuery( this ).attr('checked') ); + }); + + jQuery(document).on( 'click', '#selectFolder', function( ){ + parent.custom_storageBrowserSelect( currentFolder ); + }) + + jQuery( document ).on( 'hover', '#storageBrowser tbody tr', function( ){ + jQuery( this ).addClass( 'ruled' ); + }).on( 'mouseout', function( ){ + jQuery( this ).removeClass( 'ruled' ); + }) + + loadFolder(); +}); +</script> +EOD; + + $this->addOutputCode($output); + } + + function process_ajax() + { + $onlyFolder = __Request::get( 'onlyFolder' ); + $command = __Request::get( 'command' ); + $path = ltrim( __Request::get( 'path' ), '/' ); + $customPath = __Request::get('customPath'); + $enableDownload = __Request::get('enableDownload'); + + $result = array(); + if ( $command == "read" ) + { + $path = utf8_decode($path); + if (!$customPath) { + $mappingService = $this->_application->retrieveProxy('org.glizycms.mediaArchive.services.MediaMappingService'); + + if ($path == '') { + $mappings = $mappingService->getAllMappings(); + foreach ($mappings as $mappingName => $mappingTarget) { + $result[] = array( 'type' => 'dir', 'name' => $mappingName, 'path' => $mappingName, 'icon' => 'folder' ); + } + return $result; + } + + $slashPos = strpos($path, '/'); + + if ($slashPos == false) { + $dir = $mappingService->getMapping($path); + } else { + $name = substr($path, 0, $slashPos); + $dir = $mappingService->getMapping($name) . substr($path, $slashPos); + } + + } else { + $dir = $customPath.$path; + } + + $result[] = array( 'type' => 'dir', 'name' => 'root/', 'path' => '', 'icon' => 'folder' ); + + $files = glob($dir.'/*'); + + if (!empty($files)) { + $filter = $this->getAttribute('filter'); + + foreach ($files as $file_name) + { + $file_name = str_replace($dir.'/', '', $file_name); + + if ( $file_name == "." ) continue; + if ( $file_name == ".." && $path == '' ) continue; + if ( $file_name[0] == "." && $file_name[1] != ".") continue; // nasconde i file che iniziano col punto + + // se è settato un filtro sull'estensione dei file, allora non mostra i file che non hanno come estensione quella specificata nel filtro + if (!is_dir($dir.'/'.$file_name) && $filter != '' && pathinfo($file_name, PATHINFO_EXTENSION) != $filter ) continue; + + $fullPath = $dir.'/'.$file_name; + $fullPath2 = $path.'/'.$file_name; + + if ( is_dir( $fullPath ) ) + { + if ( $file_name == ".." ) + { + $fullPath2 = dirname( dirname( $fullPath2 ) ); + } + if ( $fullPath2 == '/' || $fullPath2 == '.') $fullPath2 = ''; + $result[] = array( 'type' => 'dir', 'name' => utf8_encode($file_name), 'path' => ltrim( utf8_encode($fullPath2), '/' ), 'icon' => 'folder' ); + } + else if (!$onlyFolder) + { + $sizeInBytes = filesize( $fullPath ); + $extension = strtolower( pathinfo( $fullPath, PATHINFO_EXTENSION ) ); + $iconType= array( + 'jpg' => 'image', + 'jpeg' => 'image', + 'gif' => 'image', + 'png' => 'image', + 'pdf' => 'pdf', + 'flv' => 'video', + 'mp4' => 'video', + 'm4v' => 'video', + 'mp3' => 'audio' + ); + $icon = isset( $iconType[ $extension ] ) ? $iconType[ $extension ] : 'other'; + + if ($enableDownload) { + $name = org_glizy_helpers_Link::makeSimpleLink($file_name, $fullPath, '', '', '', array('download' => $file_name)); + } else { + $name = utf8_encode($file_name); + } + + $result[] = array( 'type' => 'file', + 'name' => $name, + 'path' => utf8_encode($fullPath2), + 'size' => $this->formatSize( $sizeInBytes ), + 'icon' => $icon, + 'date' => date( 'H:i:s d/m/Y', filemtime( $fullPath ) ) + ); + } + } + } + } + + return $result; + } + + function formatSize($size) + { + $sizes = Array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB'); + $y = $sizes[0]; + for ($i = 1; (($i < count($sizes)) && ($size >= 1024)); $i++) + { + $size = $size / 1024; + $y = $sizes[$i]; + } + return round($size, 2)." ".$y; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/views/components/FilePicker.php b/src/core/classes/org/glizycms/mediaArchive/views/components/FilePicker.php new file mode 100644 index 0000000..3bc927e --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/views/components/FilePicker.php @@ -0,0 +1,89 @@ +<?php +class org_glizycms_mediaArchive_views_components_FilePicker extends org_glizy_components_Component +{ + function init() + { + // define the custom attributes + $this->defineAttribute('pageId', true, 'MediaStorageBrowser', COMPONENT_TYPE_STRING); + $this->defineAttribute('title', false, 'Seleziona Media', COMPONENT_TYPE_STRING); + $this->defineAttribute('onlyFolder', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('onlyFirstLevel', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('customPath', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + function render() + { + $id = $this->getAttribute('id'); + $pageId = $this->getAttribute('pageId'); + $onlyFolder = $this->getAttribute('onlyFolder'); + $onlyFirstLevel = $this->getAttribute('onlyFirstLevel'); + $customPath = $this->getAttribute('customPath'); + + $this->_application->_rootComponent->addOutputCode(org_glizy_helpers_CSS::linkCSSfile( __Paths::get('APPLICATION_TEMPLATE').'css/customStorageBrowser.css' ), 'head' ); + + $storageBrowserUrl = 'index.php?pageId='.$pageId.'&onlyFolder='.$onlyFolder.'&onlyFirstLevel='.$onlyFirstLevel.'&customPath='.$customPath; + $title = $this->getAttribute('title'); + + $output = <<<EOD +<script type="text/javascript"> +jQuery(document).ready(function() { + jQuery("#modalDiv").dialog({ + modal: true, + autoOpen: false, + draggable: true, + resizeable: true, + title: '$title' + }); + + function openFilePicker() { + var w = Math.min( jQuery( window ).width() - 50, 900 ); + var h = jQuery( window ).height() - 50; + + $("#modalDiv").dialog("option", { height: h, width: w } ); + $("#modalDiv").dialog("open" ); + if ( $("#modalIFrame").attr('src') == "" ) + { + $("#modalIFrame").attr('src', '$storageBrowserUrl'); + } + } + jQuery( "#$id" ).click(openFilePicker); + jQuery( "#mediaFilePicker" ).click(openFilePicker); +}); + +function custom_storageBrowserSelect( path ) +{ + jQuery( "#$id" ).val( path ).trigger('change'); + $("#modalDiv").dialog("close"); + + if ( window.filePicker ) + { + window.filePicker( path ); + } +} + +function setCopyToCMS( value ) +{ + jQuery( "#copyToCMS" ).val( value ? 'true' : 'false' ); +} +</script> +EOD; + $required = $this->getAttribute('required') == 'true' ? 'required' : ''; + + $output .= '<div class="control-group">'; + $output .= ' <label for="argumentId" class="control-label '.$required.'">'.$this->getAttribute('label').'</label>'; + $output .= ' <div class="controls">'; + $output .= ' <input type="hidden" name="copyToCMS" id="copyToCMS" value="false"/>'; + $output .= ' <input type="text" name="'.$id.'" id="'.$id.'" value="" readonly="true" class="span6 '.$required.'"/>'; + $output .= ' <input id="mediaFilePicker" type="button" value="Seleziona" class="btn"/>'; + $output .= ' </div>'; + $output .= '</div>'; + $output .= '<div id="modalDiv" style="display: none; margin: 0; padding: 0; overflow: hidden;"><iframe src="" id="modalIFrame" width="100%" height="100%" marginWidth="0" marginHeight="0" frameBorder="0" scrolling="auto" title="Seleziona Media"></iframe></div>'; + + $this->addOutputCode($output); + + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/views/components/ShowExif.php b/src/core/classes/org/glizycms/mediaArchive/views/components/ShowExif.php new file mode 100644 index 0000000..5ac9ea1 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/views/components/ShowExif.php @@ -0,0 +1,100 @@ +<?php +class org_glizycms_mediaArchive_views_components_ShowExif extends org_glizy_components_Component +{ + protected $imageId; + + function init() + { + // define the custom attributes + $this->defineAttribute('imageId', true, 0, COMPONENT_TYPE_INTEGER); + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + parent::process(); + + $this->imageId = $this->getAttribute('imageId'); + } + + function eval_rational($e) + { + list($n, $d) = explode('/', $e); + + if ($d == 0) { + return ''; + } + + return $n / $d; + } + + function render() + { + if (!__Config::get('glizycms.mediaArchive.exifEnabled')) { + return; + } + + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.models.Media'); + $ar->load($this->imageId); + + if ($ar->media_type == 'IMAGE') { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.mediaArchive.models.Exif'); + $result = $ar->find(array('exif_FK_media_id' => $this->imageId)); + + $values = array( + __T('Dimension') => array('values' => array($ar->exif_imageWidth, $ar->exif_imageHeight), 'format' => '%dx%d'), + __T('Resolution') => array('values' => array($ar->exif_resolution), 'format' => '%s dpi'), + __T('Device manufacturer') => array('values' => array($ar->exif_make)), + __T('Device model') => array('values' => array($ar->exif_model)), + __T('Exposure time') => array('values' => array($ar->exif_exposureTime), 'format' => '%s s'), + __T('Aperture') => array('values' => array($this->eval_rational($ar->exif_fNumber)), 'format' => '%.1f f'), + __T('Exposure program') => array('values' => array($ar->exif_exposureProgram)), + __T('ISO') => array('values' => array($ar->exif_ISOSpeedRatings)), + __T('Original date') => array('values' => array($ar->exif_dateTimeOriginal)), + __T('Digitized date') => array('values' => array($ar->exif_dateTimeDigitized)), + __T('GPS coordinates') => array('values' => array($ar->exif_GPSCoords)), + __T('GPS time') => array('values' => array($ar->exif_GPSTimeStamp)) + ); + + $li = $this->formatValues($values); + + if ($result) { + $output = <<<EOD + <ul> + $li + </ul> +EOD; + } + else { + $output = '<fieldset class="exif">'.__T('No exif data').'</fieldset>'; + } + + $this->addOutputCode($output); + } + } + + protected function formatValues($valArray, $tag = 'li') + { + $output = ''; + + foreach ($valArray as $k => $v) { + $values = $v['values']; + if (empty($values[0])) { + continue; + } + + if ($v['format']) { + $vv = vsprintf($v['format'], $values); + } + else { + $vv = implode(' ', $values); + } + + $output .= '<'.$tag.'><strong>'.$k.'</strong>: '.$vv.'</'.$tag.'>'.PHP_EOL; + } + + return $output; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchive.php b/src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchive.php new file mode 100644 index 0000000..077111b --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchive.php @@ -0,0 +1,39 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_views_renderer_CellMediaArchive extends org_glizy_components_render_RenderCellRecordSetList +{ + public function renderCell( &$ar ) + { + $media = org_glizycms_mediaArchive_MediaManager::getMediaByRecord( $ar ); + $sizes = method_exists( $media, 'getOriginalSizes') ? $media->getOriginalSizes() : array( 'width' => 0, 'height' => 0 ); + $thumbnail = $media->getThumbnail( __Config::get('THUMB_WIDTH'), + __Config::get('THUMB_HEIGHT'), + __Config::get('ADM_THUMBNAIL_CROP'), + __Config::get('ADM_THUMBNAIL_CROPPOS')); + $ar->thumb_filename = $thumbnail['fileName']; + $ar->thumb_w = $thumbnail['width']; + $ar->thumb_h = $thumbnail['height']; + $ar->media_w = $sizes['width']; + $ar->media_h = $sizes['height']; + if ($ar->media_title=='') { + $ar->media_title = $ar->media_originalFileName; + } + if (!$ar->media_date) $ar->media_date = ''; + if (!$ar->media_copyright) $ar->media_copyright = ''; + if (!$ar->media_description) $ar->media_description = ''; + $ar->__jsonMedia = org_glizycms_Glizycms::getMediaArchiveBridge()->getJsonFromAr($ar); + $application = $this->application; + $user = $application->_user; + $ar->__url__ = $user->acl($application->getPageId(),'edit') ? __Routing::makeUrl('actionsMVC', array('action' => 'edit', 'id' => $ar->media_id)) : false; + $ar->__urlDelete__ = $user->acl($application->getPageId(),'delete') ? __Routing::makeUrl('actionsMVC', array('action' => 'delete', 'id' => $ar->media_id)) : false; + $ar->__urlDownload__ = org_glizycms_helpers_Media::getFileUrlById($ar->media_id); + $ar->__urlPreview__ = org_glizycms_helpers_Media::getImageUrlById($ar->media_id, 800, 600); + } +} diff --git a/src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchiveInfo.php b/src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchiveInfo.php new file mode 100644 index 0000000..fa55795 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchiveInfo.php @@ -0,0 +1,21 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_views_renderer_CellMediaArchiveInfo extends GlizyObject +{ + function renderCell( $key, $value, $row ) + { + $output = ''; + $output .= '<p>'.__T('GLZ_MEDIA_TITLE').': <strong>'.( !empty( $row[ 'media_title' ] ) ? $row[ 'media_title' ] : '-').'</strong><br />'; + $output .= __T('GLZ_MEDIA_CATEGORY').': <strong>'.( !empty( $row[ 'media_category' ] ) ? $row[ 'media_category' ] : '-').'</strong><br />'; + $output .= __T('GLZ_MEDIA_FILENAME').': <strong>'.$row[ 'media_originalFileName' ].'</strong> <small>('.$row[ 'media_fileName' ].')</small><br />'; + $output .= __T('GLZ_MEDIA_SIZE').': <strong>'.number_format( $row[ 'media_size' ] /1024).' Kb</strong></p>'; + return $output; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchiveThumb.php b/src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchiveThumb.php new file mode 100644 index 0000000..94dbda2 --- /dev/null +++ b/src/core/classes/org/glizycms/mediaArchive/views/renderer/CellMediaArchiveThumb.php @@ -0,0 +1,25 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_mediaArchive_views_renderer_CellMediaArchiveThumb extends GlizyObject +{ + function renderCell( $key, $value, $row ) + { + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + $media = org_glizycms_mediaArchive_MediaManager::getMediaByValues( $row ); + $sizes = method_exists( $media, 'getOriginalSizes') ? $media->getOriginalSizes() : array( 'width' => 0, 'height' => 0 ); + // $scale = strpos( $application->getPageId(), 'picker' ) !== false ? 2 : 1; + // vavr_dump(__Config::get('THUMB_WIDTH')); + $scale = 1; + + $thumbnail = $media->getThumbnail( __Config::get('THUMB_WIDTH') / $scale, __Config::get('THUMB_HEIGHT') / $scale, __Config::get('ADM_THUMBNAIL_CROP'), __Config::get('ADM_THUMBNAIL_CROPPOS')); + $title = !empty( $media->title ) ? $media->title : $media->fileName; + return '<img src="'.$thumbnail['fileName'].'" width="'.$thumbnail['width'].'" height="'.$thumbnail['height'].'" alt="'.$title.'" title="'.$title.'" data-id="'.$media->id.'" data-filename="'.$media->fileName.'" data-width="'.$sizes['width'].'" data-height="'.$sizes['height'].'" style="cursor: pointer;" />'; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/models/ActiveRecordSimpleDocumentArraysIndexed.php b/src/core/classes/org/glizycms/models/ActiveRecordSimpleDocumentArraysIndexed.php new file mode 100755 index 0000000..64c372a --- /dev/null +++ b/src/core/classes/org/glizycms/models/ActiveRecordSimpleDocumentArraysIndexed.php @@ -0,0 +1,84 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +use Doctrine\DBAL\Types\Type; + +class org_glizycms_models_ActiveRecordSimpleDocumentArraysIndexed extends org_glizy_dataAccessDoctrine_ActiveRecordSimpleDocument +{ + protected function insertValuesIntoIndex($id, $values) + { + foreach ($values as $fieldName => $value) + { + $field = $this->fields[$fieldName]; + + if (!$field->virtual && !$field->key && $field->index != $field::NOT_INDEXED && isset(self::$typeMap[$field->type])) { + $indexFieldType = $this->getIndexFieldType($fieldName); + $tableName = self::DOCUMENT_INDEX_TABLE_PREFIX . $indexFieldType . '_tbl'; + $fieldPrefix = self::DOCUMENT_INDEX_FIELD_PREFIX . $indexFieldType; + + if (is_array($value)) { + foreach ($value as $k => $v) { + if ($v != '') { + $documentIndex = array( + $fieldPrefix.'_FK_simple_document_id' => $id, + $fieldPrefix.'_name' => $fieldName, + $fieldPrefix.'_value' => $k.":".$v, + ); + + $this->connection->insert($tableName, $documentIndex); + } + } + } + else { + $documentIndex = array( + $fieldPrefix.'_FK_simple_document_id' => $id, + $fieldPrefix.'_name' => $fieldName, + $fieldPrefix.'_value' => $value, + ); + + $this->connection->insert($tableName, $documentIndex); + } + } + } + } + + protected function updateValuesIntoIndex($fields, $values) + { + // per ogni campo modificato si va a modificare la corrispondente tabella indice + foreach ($fields as $fieldName => $field) { + if (!$field->virtual && !$field->key && $field->index != $field::NOT_INDEXED && isset(self::$typeMap[$field->type])) { + $indexFieldType = $this->getIndexFieldType($fieldName); + $tableName = self::DOCUMENT_INDEX_TABLE_PREFIX . $indexFieldType . '_tbl'; + $fieldPrefix = self::DOCUMENT_INDEX_FIELD_PREFIX . $indexFieldType; + + $value = $values[$fieldName]; + + $indexIdentifier = array( + $fieldPrefix.'_FK_simple_document_id' => $this->getId(), + $fieldPrefix.'_name' => $fieldName + ); + + $this->connection->delete($tableName, $indexIdentifier); + + if (is_array($value)) { + foreach ($value as $k => $v) { + if ($v != '') { + $documentIndex = array_merge($indexIdentifier, array($fieldPrefix.'_value' => $k.":".$v)); + $this->connection->insert($tableName, $documentIndex); + } + } + } + else { + $documentIndex = array_merge($indexIdentifier, array($fieldPrefix.'_value' => $value)); + $this->connection->insert($tableName, $documentIndex); + } + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/models/Media.xml b/src/core/classes/org/glizycms/models/Media.xml new file mode 100755 index 0000000..47c98d1 --- /dev/null +++ b/src/core/classes/org/glizycms/models/Media.xml @@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:type="2tables" + model:tableName="media_tbl,mediadetails_tbl" + model:joinFields="media_id,mediadetail_FK_media_id" + model:languageField="media_FK_language_id" + model:siteField="media_FK_site_id" + model:usePrefix="true"> + + <model:Define> + <model:Field name="media_category" type="array" defaultValue="a:0:{}" index="true"/> + </model:Define> + + <model:Query name="allMedia" type="function"> + <![CDATA[ + ]]> + </model:Query> + + <model:Query name="allImage" type="function"> + <![CDATA[ + $iterator->where('media_type', 'IMAGE'); + ]]> + </model:Query> + + <model:Query name="allOffice" type="function"> + <![CDATA[ + $iterator->where('media_type', 'OFFICE'); + ]]> + </model:Query> + + <model:Query name="allPdf" type="function"> + <![CDATA[ + $iterator->where('media_type', 'PDF'); + ]]> + </model:Query> + + <model:Query name="allArchive" type="function"> + <![CDATA[ + $iterator->where('media_type', 'ARCHIVE'); + ]]> + </model:Query> + + <model:Query name="allFlash" type="function"> + <![CDATA[ + $iterator->where('media_type', 'FLASH'); + ]]> + </model:Query> + + <model:Query name="allAudio" type="function"> + <![CDATA[ + $iterator->where('media_type', 'AUDIO'); + ]]> + </model:Query> + + <model:Query name="allAudio_video" type="function"> + <![CDATA[ + $or = $iterator->expr()->orX(); + $iterator->where('media_type', 'AUDIO', '=', $or); + $iterator->where('media_type', 'VIDEO', '=', $or); + $iterator->qb()->andWhere($or); + ]]> + </model:Query> + + <model:Query name="allVideo" type="function"> + <![CDATA[ + $iterator->where('media_type', 'VIDEO'); + ]]> + </model:Query> + + <model:Query name="allOther" type="function"> + <![CDATA[ + $iterator->where('media_type', 'OTHER'); + ]]> + </model:Query> +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/modulesManager/controllers/Duplicate.php b/src/core/classes/org/glizycms/modulesManager/controllers/Duplicate.php new file mode 100644 index 0000000..28fd81a --- /dev/null +++ b/src/core/classes/org/glizycms/modulesManager/controllers/Duplicate.php @@ -0,0 +1,29 @@ +<?php +class org_glizycms_modulesManager_controllers_Duplicate extends org_glizy_mvc_core_Command +{ + public function execute($id, $moduleId) + { +// TODO tradurre le label + + if (!$moduleId) { + $this->setComponentsAttribute('moduleId', 'value', $id); + $moduleVO = $this->getModuleVO($id); + $text = '<p>Duplicazione modulo <b>'.__T($moduleVO->name).'</b> id: '.$moduleVO->id.'<p>'; + $this->setComponentsAttribute('text', 'text', $text); + } else { + $moduleVO = $this->getModuleVO($moduleId); + $duplicateClass = org_glizy_ObjectFactory::createObject($moduleVO->classPath.'.Duplicate', $moduleVO); + + + org_glizy_Modules::deleteCache(); + $this->changeAction('index'); + } + } + + private function getModuleVO($id) + { +// TODO controllare che il modulo sia corretto + $modules = org_glizy_Modules::getModules(); + return $modules[$id]; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/modulesManager/controllers/ajax/Disable.php b/src/core/classes/org/glizycms/modulesManager/controllers/ajax/Disable.php new file mode 100755 index 0000000..a4ba541 --- /dev/null +++ b/src/core/classes/org/glizycms/modulesManager/controllers/ajax/Disable.php @@ -0,0 +1,12 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_modulesManager_controllers_ajax_Disable extends org_glizycms_modulesManager_controllers_ajax_Enable +{ +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/modulesManager/controllers/ajax/Enable.php b/src/core/classes/org/glizycms/modulesManager/controllers/ajax/Enable.php new file mode 100755 index 0000000..73f2ebe --- /dev/null +++ b/src/core/classes/org/glizycms/modulesManager/controllers/ajax/Enable.php @@ -0,0 +1,20 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_modulesManager_controllers_ajax_Enable extends org_glizy_mvc_core_CommandAjax +{ + function execute() + { + $id = __Request::get( 'id' ); + $modulesState = org_glizy_Modules::getModulesState(); + $modulesState[ $id ] = __Request::get( 'action' ) == 'enable'; + org_glizy_Modules::setModulesState( $modulesState ); + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/modulesManager/views/ModulesManager.xml b/src/core/classes/org/glizycms/modulesManager/views/ModulesManager.xml new file mode 100755 index 0000000..21eac99 --- /dev/null +++ b/src/core/classes/org/glizycms/modulesManager/views/ModulesManager.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:m="org.glizycms.modulesManager.views.components.*" + controllerName="org.glizycms.modulesManager.controllers.*" + templateType="php" + templateFileName="Page.php" + defaultEditableRegion="content"> + <glz:Import src="_common.xml" /> + + <mvc:State name="index"> + <m:Datagrid id="dataGrid" cssClass="table table-bordered table-striped" /> + </mvc:State> + + <mvc:State name="duplicate"> + <glz:Form> + <glz:LongText id="text" adm:htmlEditor="true" /> + <glz:Hidden id="moduleId" /> + <glz:Input id="moduleName" label="{i18n:Nome del modulo}" required="true" /> + + <glz:Panel cssClass="formButtons"> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" cssClass="btn btn-primary" /> + </glz:Panel> + </glz:Form> + </mvc:State> + +</mvc:Page> diff --git a/src/core/classes/org/glizycms/modulesManager/views/components/Datagrid.php b/src/core/classes/org/glizycms/modulesManager/views/components/Datagrid.php new file mode 100644 index 0000000..738d53e --- /dev/null +++ b/src/core/classes/org/glizycms/modulesManager/views/components/Datagrid.php @@ -0,0 +1,126 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_modulesManager_views_components_Datagrid extends org_glizy_components_Component +{ + function init() + { + // define the custom attributes + $this->defineAttribute('cssClass', false, 'odd,even', COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + /** + * Render + * + * @return void + * @access public + */ + function render() + { +// TODO tradurre le label + + $output = ''; + $output .= '<table id="'.$this->getId().'" class="js-modulesManager '.$this->getAttribute('cssClass').'">'; + if ($this->getAttribute('label')!='') $output .= '<caption>'.$this->getAttribute('label').'</caption>'; + + // disegna le colonne + $output .= '<thead>'; + $output .= '<tr>'; + $output .= '<th class="name">Plugin</th>'; + $output .= '<th>Descrizione</th>'; + $output .= '<th class="actions"></th>'; + $output .= '</tr>'; + + $output .= '<tfoot><tr><td colspan="3"></td></tr></tfoot>'; + + $output .= '<tbody>'; + $origCssClass = explode(',', $this->getAttribute('cssClass')); + $tempCssClass = array(); + $modulesState = org_glizy_Modules::getModulesState(); + + $modules = org_glizy_Modules::getModules(); + $this->sort( $modules ); + + foreach( $modules as $m ) + { + // $moduleDescription = org_glizy_ObjectFactory::createObject( 'org.glizy.ModuleDescription', $m ); + // if ( !empty( $m->pageType ) ) continue; + $isEnabled = !isset( $modulesState[ $m->id ] ) || $modulesState[ $m->id ]; + + if (!count($tempCssClass)) $tempCssClass = $origCssClass; + $cssClass = array_shift($tempCssClass); + $cssClass .= ' '.( $isEnabled ? 'enabled' : 'disabled' ); + + $output .= '<tr class="'.$cssClass.'">'. + '<td class="name">'.__T($m->name).'</td>'. + '<td>'. + '<p class="description">'.$m->description.'</p>'. + '<p class="info">Versione '.$m->version.' | '. + __Link::makeLink2( null, array( 'label' => $m->author, 'title' => 'Visita il sito dell\'autore', 'url' => $m->authorUrl, 'rel' => 'external' ) ).' | '. + __Link::makeLink2( null, array( 'label' => 'Visita il sito del plugin', 'url' => $m->pluginUrl, 'rel' => 'external' ) ). + '</p>'. + '</td>'. + '<td class="actions">'. + ( !$isEnabled ? '<a href="" data-action="enable" data-id="'.$m->id.'" class="js-modulesManagerAction action">abilita</a>' : '' ). + ( $isEnabled ? '<a href="" data-action="disable" data-id="'.$m->id.'" class="js-modulesManagerAction action">disabilita</a>' : '' ). + ' '.( $m->canDuplicated ? '<a href="'.__Routing::makeUrl('glizycmsModuleManagerDuplicate', array('pageId' => $this->pageId, 'id' => $m->id)).'" class="action">duplica</a>' : '' ). + /*'<a data-action="uninstall" data-id="'.$m->id.'" class="action danger">rimuovi</a>'.*/ + '</td>'. + '</tr>'; + } + $output .= '</tbody>'; + $output .= '</table>'; + $output .= <<<EOD +<script type="text/javascript"> +jQuery(document).ready(function() { + + $("table.js-modulesManager a.js-modulesManagerAction ").click( function( e ){ + e.stopPropagation(); + if ( jQuery( this ).data( "action" ) == "uninstall" ) + { + if ( !confirm( "Sei sicuro di voler rimuovere il plugin?") ) + { + return false; + } + } + + // jQuery.modal('<div></div>', { + // close: false, + // overlayCss:{ + // backgroundColor:"#000" + // }, + // overlayClose: false + // }); + + jQuery.ajax( { url: Glizy.ajaxUrl+jQuery( this ).data( "action" ), + type: 'POST', + data: { id: jQuery( this ).data( "id" ) }, + success: function( response, r, a ) { + location.reload(); + }}); + return false; + }); + +}); +</script> +EOD; + + $this->addOutputCode($output); + } + + + private function sort( &$arr, $f='strnatcasecmp') + { + return usort($arr, create_function('$a, $b', "return $f(\$a->name, \$b->name);")); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/roleManager/AdminPage.xml b/src/core/classes/org/glizycms/roleManager/AdminPage.xml new file mode 100755 index 0000000..3066a1e --- /dev/null +++ b/src/core/classes/org/glizycms/roleManager/AdminPage.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:r="org.glizycms.roleManager.views.*" + xmlns:cms="org.glizycms.views.components.*" + templateType="php" + templateFileName="Page.php" + defaultEditableRegion="content"> + <glz:Import src="_common.xml" /> + <!-- TODO: USARE MVC STATE--> + <glz:StateSwitch id="dataGridEdit" defaultState="list" rememberState="false" customClass="org.glizycms.roleManager.controllers.StateController" > + <glz:State name="list"> + <glz:DataProvider id="dp" recordClassName="org.glizycms.roleManager.models.Role" /> + <glz:Form id="editForm"> + <glz:DataGrid id="dataGrid" label="Elenco ruoli" dataProvider="{dp}" filters="{filters}" tableCssClass="table table-striped table-bordered" cssClass="odd,even" paginate="{dataGridPaginate}" controller="{dataGridEdit}" orderStyle="BLACK"> + <glz:DataGridColumn columnName="role_id" visible="false" key="true"/> + <glz:DataGridColumn columnName="role_name" headerText="Nome" /> + <glz:DataGridColumn command="edit" width="20" aclService="{php:$application->getPageId()}" /> + <glz:DataGridColumn command="delete" width="20" aclService="{php:$application->getPageId()}" /> + </glz:DataGrid> + <glz:PaginateResult id="dataGridPaginate" cssClass="pagination"/> + + <glz:Button value="{i18n:Aggiungi un nuovo ruolo}" target="{dataGridEdit}" action="new" actionType="location" cssClass="{config:glizycms.form.actionLink.cssClass}" visible="{php:$user->acl($application->getPageId(),'new')}" editableRegion="actions"/> + </glz:Form> + </glz:State> + <glz:State name="new,edit"> + <glz:MessageBox type="ERROR" cssClass="message failure"/> + <glz:LongText adm:htmlEditor="true"><![CDATA[ + <p class="genericCaption">Creazione nuovo ruolo.</p> + <p>Inserire i dati per la creazione del nuovo sito.</p> + ]]></glz:LongText> + <glz:Form id="myForm" removeGetValues="false" enctype="multipart/form-data" addValidationJs="false"> + <glz:Hidden id="roleId" /> + <glz:Input id="roleName" label="{i18n:Nome del ruolo}" size="90" required="true" /> + <r:Input id="groups" mode="groups" label="{i18n:Gruppo associati}" size="90" /> + <r:Input id="users" mode="users" label="{i18n:Utenti associati}" size="90" /> + <glz:Checkbox id="roleActive" label="{i18n:Attivo}" size="90" /> + <r:Permissions id="permissions" label="{i18n:Permessi per il ruolo}" /> + + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:Salva}" id="next" value="next" name="action" cssClass="btn btn-primary" /> + <glz:Button value="{i18n:GLZ_CANCEL}" target="{dataGridEdit}" action="reset" actionType="location" cssClass="btn" visible="true"/> + </cms:FormButtonsPanel> + </glz:Form> + </glz:State> + </glz:StateSwitch> +</glz:Page> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/roleManager/controllers/Login.php b/src/core/classes/org/glizycms/roleManager/controllers/Login.php new file mode 100644 index 0000000..5ca191f --- /dev/null +++ b/src/core/classes/org/glizycms/roleManager/controllers/Login.php @@ -0,0 +1,22 @@ +<?php +class org_glizycms_roleManager_controllers_Login extends org_glizy_mvc_core_Command +{ + function execute() + { + if ($this->user->isLogged()) { + $siteMap = $this->application->getSiteMap(); + $siteMapIterator = org_glizy_ObjectFactory::createObject('org.glizy.application.SiteMapIterator',$siteMap); + while (!$siteMapIterator->EOF) + { + $n = $siteMapIterator->getNode(); + $siteMapIterator->moveNext(); + if ($n->isVisible && $n->depth > 1 && !$n->select) { + org_glizy_helpers_Navigation::gotoUrl( $n->id ); + } + } + + $authClass = org_glizy_ObjectFactory::createObject(__Config::get('glizy.authentication')); + $authClass->logout(); + } + } +} diff --git a/src/core/classes/org/glizycms/roleManager/controllers/StateController.php b/src/core/classes/org/glizycms/roleManager/controllers/StateController.php new file mode 100644 index 0000000..06f2976 --- /dev/null +++ b/src/core/classes/org/glizycms/roleManager/controllers/StateController.php @@ -0,0 +1,130 @@ +<?php +class org_glizycms_roleManager_controllers_StateController extends org_glizy_components_StateSwitchClass +{ + function execute_edit($oldState) + { + $id = __Request::get('dataGridEdit_recordId'); + if ($id && strtolower( __Request::get( 'action', '' ) ) != 'next') { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.roleManager.models.Role'); + $ar->load($id); + __Request::set('roleId', $ar->role_id); + __Request::set('roleName', $ar->role_name); + __Request::set('roleActive', $ar->role_active); + __Request::set('permissions', $ar->role_permissions); + + $groups = array(); + + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.roleManager.models.Group', 'getGroups', array('params' => array('roleId' => $id))); + + foreach ($it as $ar) { + $groups[] = array( + 'id' => $ar->join_FK_dest_id, + 'text' => $ar->usergroup_name + ); + } + + $users = array(); + + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.roleManager.models.User', 'getUsers', array('params' => array('roleId' => $id))); + + foreach ($it as $ar) { + $users[] = array( + 'id' => $ar->join_FK_dest_id, + 'text' => $ar->user_loginId + ); + } + + __Request::set('groups', $groups); + __Request::set('users', $users); + } + } + + function executeLater_edit($oldState) + { + $this->executeLater_new($oldState); + } + + function executeLater_new( $oldState ) + { + // controlla se � stato ftto submit + if ( strtolower( __Request::get( 'action', '' ) ) == 'next' ) + { + if ($this->_parent->validate()) { + $roleId = __Request::get('roleId'); + $roleName = __Request::get('roleName'); + $groups = __Request::get('groups'); + $users = __Request::get('users'); + $roleActive = __Request::get('roleActive'); + $permissions = __Request::get('permissions'); + $aclPageTypes = __Request::get('aclPageTypes'); + + foreach ((array)$aclPageTypes as $masterPage => $pages) { + $pages = explode(',', $pages); + + foreach ($pages as $page) { + $page = strtolower($page); + + // se già sono settati permessi specifici non vengon copiati dal pagetype master + if ($permissions[$page]) continue; + + // copia i permessi del pagetype master + $permissions[$page] = $permissions[$masterPage]; + } + } + + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.roleManager.models.Role'); + if ($roleId) $ar->load($roleId); + $ar->role_name = $roleName; + $ar->role_active = $roleActive; + $ar->role_permissions = serialize($permissions); + + if ($roleId) { + $ar->save(); + } + else { + $roleId = $ar->save(); + } + + $ar = org_glizy_ObjectFactory::createModel('org.glizy.models.Join'); + $ar->delete(array('join_FK_source_id' => $roleId, 'join_objectName' => 'roles2usergroups')); + $ar->delete(array('join_FK_source_id' => $roleId, 'join_objectName' => 'roles2users')); + + if ($groups != '') { + $groups = explode(',', $groups); + + foreach ($groups as $groupId) { + $ar->join_FK_source_id = $roleId; + $ar->join_FK_dest_id = $groupId; + $ar->join_objectName = 'roles2usergroups'; + $ar->save(null, true); + } + } + + if ($users != '') { + $users = explode(',', $users); + + foreach ($users as $userId) { + $ar->join_FK_source_id = $roleId; + $ar->join_FK_dest_id = $userId; + $ar->join_objectName = 'roles2users'; + $ar->save(null, true); + } + } + + org_glizy_Session::remove('glizy.roles'); + + $this->_parent->refreshToState( 'reset' ); + } + } + } + + function execute_delete( $oldState ) + { + $id = __Request::get('dataGridEdit_recordId'); + if ($id) { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.roleManager.models.Role'); + $ar->delete($id); + $this->_parent->refreshToState( 'reset' ); + } + } +} diff --git a/src/core/classes/org/glizycms/roleManager/models/Group.xml b/src/core/classes/org/glizycms/roleManager/models/Group.xml new file mode 100755 index 0000000..78720b9 --- /dev/null +++ b/src/core/classes/org/glizycms/roleManager/models/Group.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:type="2tables" + model:tableName="joins_tbl,usergroups_tbl" + model:joinFields="join_FK_dest_id,usergroup_id" + model:usePrefix="true"> + + <model:Query name="getGroups" type="function" arguments="roleId"> + <![CDATA[ + $iterator->where('join_objectName', 'roles2usergroups') + ->where('join_FK_source_id', $roleId); + ]]> + </model:Query> + +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/roleManager/models/Role.xml b/src/core/classes/org/glizycms/roleManager/models/Role.xml new file mode 100755 index 0000000..8c6c72b --- /dev/null +++ b/src/core/classes/org/glizycms/roleManager/models/Role.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="roles_tbl" model:usePrefix="true"> +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/roleManager/models/User.xml b/src/core/classes/org/glizycms/roleManager/models/User.xml new file mode 100755 index 0000000..ad2e6ad --- /dev/null +++ b/src/core/classes/org/glizycms/roleManager/models/User.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:type="2tables" + model:tableName="joins_tbl,users_tbl" + model:joinFields="join_FK_dest_id,user_id" + model:usePrefix="true"> + + <model:Query name="getUsers" type="function" arguments="roleId"> + <![CDATA[ + $iterator->where('join_objectName', 'roles2users') + ->where('join_FK_source_id', $roleId); + ]]> + </model:Query> + +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/roleManager/services/RoleService.php b/src/core/classes/org/glizycms/roleManager/services/RoleService.php new file mode 100644 index 0000000..13e6385 --- /dev/null +++ b/src/core/classes/org/glizycms/roleManager/services/RoleService.php @@ -0,0 +1,16 @@ +<?php + +class org_glizycms_roleManager_services_RoleService extends GlizyObject +{ + function addModule($moduleId, $permission = array('visible' => 'true')) + { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.roleManager.models.Role'); + + foreach ($it as $ar) { + $permissions = unserialize($ar->role_permissions); + $permissions[$moduleId] = $permission; + $ar->role_permissions = serialize($permissions); + $ar->save(); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/roleManager/views/Input.php b/src/core/classes/org/glizycms/roleManager/views/Input.php new file mode 100644 index 0000000..f8b6805 --- /dev/null +++ b/src/core/classes/org/glizycms/roleManager/views/Input.php @@ -0,0 +1,83 @@ +<?php + +class org_glizycms_roleManager_views_Input extends org_glizy_components_Input +{ + function render() + { + parent::render(); + + $rootComponent = &$this->getRootComponent(); + if (!org_glizy_ObjectValues::get('org.glizy.JS.textext', 'add', false)) { + org_glizy_ObjectValues::set('org.glizy.JS.textext', 'add', true); + $core = __Paths::get('CORE'); + $output = <<<EOD +<link rel="stylesheet" type="text/css" href="$core/classes/org/glizycms/js/jquery/select2/select2.css" /> +<script type="text/javascript" src="$core/classes/org/glizycms/js/jquery/select2/select2.min.js" charset="UTF-8"></script> +EOD; + $rootComponent->addOutputCode($output, 'head'); + } + + $id = $this->getId(); + + $content = $this->_content ? json_encode($this->_content) : '[]'; + $ajaxUrl = 'ajax.php?pageId='.__Request::get('pageId').'&ajaxTarget='.$this->getId(); + $output = <<<EOD +<script type="text/javascript"> +$(function(){ + $('#$id').val(''); + $('#$id').select2({ + multiple: true, + ajax: { + url: '$ajaxUrl', + dataType: 'json', + quietMillis: 100, + data: function(term, page) { + return { + q: term, + }; + }, + results: function(data, page ) { + return { results: data } + } + }, + }); + + $('#$id').select2('data', $content); +}); +</script> +EOD; + $rootComponent->addOutputCode($output, 'head'); + } + + function process_ajax() { + $mode = $this->getAttribute('mode'); + $q = __Request::get('q'); + $result = array(); + if ($mode == 'users') { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.userManager.models.UserGroup', 'all'); + $it->setOrFilters(array( + "user_firstName" => $q, + "user_lastName" => $q, + "user_loginId" => $q, + )); + foreach ($it as $ar) { + $result[] = array('id' => $ar->user_id, 'text' => $ar->user_loginId); + } + } else if ($mode == 'groups') { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.userManager.models.UserGroup', 'all', + array('filters' => array('usergroup_name' => $q) ) + ); + foreach ($it as $ar) { + $result[] = array('id' => $ar->usergroup_id, 'text' => $ar->usergroup_name); + } + } else { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.roleManager.models.Role', 'all', + array('filters' => array('role_name' => $q) ) + ); + foreach ($it as $ar) { + $result[] = array('id' => $ar->role_id, 'text' => $ar->role_name); + } + } + return $result; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/roleManager/views/Permissions.php b/src/core/classes/org/glizycms/roleManager/views/Permissions.php new file mode 100644 index 0000000..09fc414 --- /dev/null +++ b/src/core/classes/org/glizycms/roleManager/views/Permissions.php @@ -0,0 +1,98 @@ +<?php + +class org_glizycms_roleManager_views_Permissions extends org_glizy_components_Input +{ + protected static $ACTIONS = array('all', 'edit', 'editDraft', 'new', 'delete', 'publish', 'visible'); + + function process() + { + parent::process(); + if (is_string($this->_content)) { + $this->_content = unserialize($this->_content); + if (!$this->_content) $this->_content = array(); + } + } + + function render() + { + $output = <<<EOD +<table class="table table-striped table-bordered"> + <thead> + <tr> + <th></th> + <th>Consenti tutto</th> + <th>Modifica</th> + <th>Modifica bozza</th> + <th>Nuovo</th> + <th>Cancellazione</th> + <th>Pubblicazione</th> + <th>Visualizzazione</th> + </tr> + </thead> + <tbody> +EOD; + $siteMap = $this->_application->getSiteMap(); + + $siteMapIterator = &org_glizy_ObjectFactory::createObject('org.glizy.application.SiteMapIterator', $siteMap); + + $cssClass = ''; + $row = 0; + $perms = array('a', 'm', 'b', 'n', 'c', 'p', 'v'); + $modules = array(); + + while (!$siteMapIterator->EOF) { + $n = $siteMapIterator->getNode(); + $title = $n->getAttribute('adm:aclLabel') ? $n->getAttribute('adm:aclLabel') : $n->getAttribute('title'); + $acl = $n->getAttribute('adm:acl'); + if ($title && $acl) $modules[$title] = $n; + $siteMapIterator->moveNext(); + } + ksort($modules); + + foreach($modules as $title=>$n) { + $cssClass = $cssClass == 'odd' ? 'even' : 'odd'; + $output .= '<tr class="'.$cssClass.'"><td>'.$title.'</td>'; + $acl = $n->getAttribute('adm:acl'); + + if ($acl == '*') { + $v = '1111111'; + } + else { + $v = ''; + $acl = array_flip(explode(',', $acl)); + foreach ($perms as $p) { + $v .= isset($acl[$p]) ? '1' : '0'; + } + } + + $id = $n->getAttribute('id'); + $this->drawCheckox($id, $v, $row, 0, $output); + $this->drawCheckox($id, $v, $row, 1, $output); + $this->drawCheckox($id, $v, $row, 2, $output); + $this->drawCheckox($id, $v, $row, 3, $output); + $this->drawCheckox($id, $v, $row, 4, $output); + $this->drawCheckox($id, $v, $row, 5, $output); + $this->drawCheckox($id, $v, $row, 6, $output); + $output .= '</tr>'; + + $aclPageTypes = $n->getAttribute('adm:aclPageTypes'); + + if ($aclPageTypes) { + $output .= '<input type="hidden" name="aclPageTypes['.$id.']" value="'.$aclPageTypes.'" />'; + } + + $row++; + } + + $output .= '</tbody></table>'; + $this->addOutputCode($output); + } + + private function drawCheckox($id, $flags, $row, $pos, &$output) + { + $checked = @$this->_content[$id][self::$ACTIONS[$pos]] == '1' ? 'checked="checked"' : ''; + if ($flags{$pos}=='1') $output .= '<td style="text-align: center"><input type="checkbox" name="permissions['.$id.']['.self::$ACTIONS[$pos].']" value="1" '.$checked.' /></td>'; + else $output .= '<td></td>'; + } + +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/siteProperties/controllers/Index.php b/src/core/classes/org/glizycms/siteProperties/controllers/Index.php new file mode 100644 index 0000000..13d00e4 --- /dev/null +++ b/src/core/classes/org/glizycms/siteProperties/controllers/Index.php @@ -0,0 +1,11 @@ +<?php +class org_glizycms_siteProperties_controllers_Index extends org_glizy_mvc_core_Command +{ + public function execute() + { + $siteProp = unserialize(org_glizy_Registry::get(__Config::get('REGISTRY_SITE_PROP').$this->application->getEditingLanguage(), '')); + if ($siteProp) { + $this->view->setData($siteProp); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/siteProperties/controllers/ajax/Save.php b/src/core/classes/org/glizycms/siteProperties/controllers/ajax/Save.php new file mode 100644 index 0000000..54c8ee8 --- /dev/null +++ b/src/core/classes/org/glizycms/siteProperties/controllers/ajax/Save.php @@ -0,0 +1,18 @@ +<?php +class org_glizycms_siteProperties_controllers_ajax_Save extends org_glizy_mvc_core_CommandAjax +{ + // TODO creare un proxy per gestire le proprietà del sito + public function execute($data) + { + $data = json_decode($data); + $newData = array(); + $newData['title'] = $data->title; + $newData['address'] = $data->address; + $newData['copyright'] = $data->copyright; + $newData['slideShow'] = $data->slideShow; + $newData['analytics'] = $data->analytics; + + org_glizy_Registry::set(__Config::get('REGISTRY_SITE_PROP').$this->application->getEditingLanguage(), serialize($newData)); + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/siteProperties/views/SiteProperties.xml b/src/core/classes/org/glizycms/siteProperties/views/SiteProperties.xml new file mode 100644 index 0000000..b36d829 --- /dev/null +++ b/src/core/classes/org/glizycms/siteProperties/views/SiteProperties.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Page.php"> + <glz:Import src="_common.xml" /> + + <mvc:State name="index"> + <cms:FormEdit id="myForm" controllerName="org.glizycms.siteProperties.controllers.*"> + <glz:Input id="title" label="{i18n:MW_SITE_TITLE}" value="{siteProp}" size="50" required="true" /> + <glz:Input id="address" label="{i18n:MW_SITE_ADDRESS}" value="{siteProp}" rows="12" cols="75" type="multiline" htmlEditor="true" required="false" data="type=tinymce" /> + <glz:Input id="copyright" label="{i18n:MW_SITE_COPYRIGHT}" value="{siteProp}" size="75" required="false" /> + <glz:Input id="slideShow" label="{i18n:MW_SITE_SLIDESHOW_SPEED}" value="{siteProp}" size="3" maxLength="3" required="false" /> + <glz:Input id="analytics" label="{i18n:Google Analytics code}" value="{siteProp}" size="30" /> + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> +</mvc:Page> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/speakingUrl/AbstractDocumentResolver.php b/src/core/classes/org/glizycms/speakingUrl/AbstractDocumentResolver.php new file mode 100644 index 0000000..61b94be --- /dev/null +++ b/src/core/classes/org/glizycms/speakingUrl/AbstractDocumentResolver.php @@ -0,0 +1,104 @@ +<?php +class org_glizycms_speakingUrl_AbstractDocumentResolver extends org_glizycms_speakingUrl_AbstractUrlResolver +{ + protected $model; + protected $pageType; + protected $modelName; + + protected function getIdFromLink($id) + { + return str_replace($this->protocol, '', $id); + } + + public function searchDocumentsByTerm($term, $id, $protocol='', $filterType='') + { + $result = array(); + if ($protocol && $protocol!=$this->protocol) return $result; + + + if ($term) { + $it = org_glizy_objectFactory::createModelIterator($this->model)->load('All'); + + if ($term != '') { + $it->where('title', '%'.$term.'%', 'ILIKE'); + } + $it->orderBy('title'); + + foreach($it as $ar) { + + $result[] = array( + 'id' => $this->protocol.$ar->document_id, + 'text' => $ar->title, + 'path' => $this->modelName + ); + } + } elseif ($id) { + if (strpos($id, $this->protocol) !== 0) { + return $result; + } + + $ar = org_glizy_objectFactory::createModel($this->model); + $ar->load($this->getIdFromLink($id)); + $result[] = array( + 'id' => $this->protocol.$ar->document_id, + 'text' => $ar->title, + 'path' => $this->modelName + ); + } + + return $result; + } + + public function makeUrl($id) + { + if (strpos($id, $this->protocol) === 0) { + $id = $this->getIdFromLink($id); + return $this->makeUrlFromId($id); + } else { + return false; + } + } + + + public function makeLink($id) + { + if (strpos($id, $this->protocol) === 0) { + $id = $this->getIdFromLink($id); + return $this->makeUrlFromId($id, true); + } else { + return false; + } + } + + public function makeUrlFromRequest() + { + $id = __Request::get('document_id'); + return $this->makeUrlFromId($id); + } + + private function makeUrlFromId($id, $fullLink=false) + { + $ar = org_glizy_objectFactory::createModel($this->model); + if ($ar->load($this->getIdFromLink($id))) { + $siteMap = $this->application->getSiteMap(); + $menu = $siteMap->getMenuByPageType($this->pageType); + + if ($ar->document_detail_isVisible && $ar->document_detail_translated && $menu && $menu->isVisible) { + if ($ar->keyInDataExists('url') && $ar->url) { + $language = $this->application->getLanguage(); + $url = GLZ_HOST.'/'.$language.'/'.$ar->url; + } else { + $url = __Link::makeUrl('movio_news', array( 'document_id' => $id, + 'title' => $ar->title)); + } + + return $fullLink ? __Link::makeSimpleLink($ar->title, $url) : $url; + } + } + + // document not found, isn't visible or isn't traslated + // go to entity page or home + $speakingUrlManager = $this->application->retrieveProxy('org.glizycms.speakingUrl.Manager'); + return $fullLink ? '' : $speakingUrlManager->makeUrl('internal:'.( $menu ? $menu->id : __Config::get('START_PAGE'))); + } +} diff --git a/src/core/classes/org/glizycms/speakingUrl/AbstractUrlResolver.php b/src/core/classes/org/glizycms/speakingUrl/AbstractUrlResolver.php new file mode 100644 index 0000000..48563d7 --- /dev/null +++ b/src/core/classes/org/glizycms/speakingUrl/AbstractUrlResolver.php @@ -0,0 +1,27 @@ +<?php +class org_glizycms_speakingUrl_AbstractUrlResolver +{ + protected $application; + protected $languageId; + protected $editLanguageId; + protected $type; + protected $protocol; + + public function __construct() + { + $this->application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $this->languageId = $this->application->getLanguageId(); + $this->editLanguageId = org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId'); + } + + + public function getType() + { + return $this->type; + } + + protected function getIdFromLink($id) + { + return str_replace($this->protocol, '', $id); + } +} diff --git a/src/core/classes/org/glizycms/speakingUrl/IUrlResolver.php b/src/core/classes/org/glizycms/speakingUrl/IUrlResolver.php new file mode 100644 index 0000000..c671b31 --- /dev/null +++ b/src/core/classes/org/glizycms/speakingUrl/IUrlResolver.php @@ -0,0 +1,9 @@ +<?php +interface org_glizycms_speakingUrl_IUrlResolver +{ + public function compileRouting($ar); + public function searchDocumentsByTerm($term, $id, $protocol='', $filterType=''); + public function makeUrl($id); + public function makeUrlFromRequest(); + public function makeLink($id); +} diff --git a/src/core/classes/org/glizycms/speakingUrl/Manager.php b/src/core/classes/org/glizycms/speakingUrl/Manager.php new file mode 100644 index 0000000..1b1ee3f --- /dev/null +++ b/src/core/classes/org/glizycms/speakingUrl/Manager.php @@ -0,0 +1,90 @@ +<?php +class org_glizycms_speakingUrl_Manager extends GlizyObject +{ + private static $modules = array(); + + public function __construct() + { + $application = org_glizy_ObjectValues::get('org.glizy', 'application'); + if (__Config::get('glizycms.speakingUrl') && !$application->isAdmin()) { + $this->addEventListener(GLZ_EVT_START_COMPILE_ROUTING, $this); + } + } + + + public function registerResolver($resolver) + { + self::$modules[$resolver->getType()] = $resolver; + } + + public function getResolver($type) + { + return isset(self::$modules[$type]) ? self::$modules[$type] : null; + } + + + public function startCompileRouting() + { + $this->compileRouting(); + } + + + private function compileRouting() + { + $routing = ''; + + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.speakingUrl.models.SpeakingUrl') + ->load('all'); + foreach($it as $ar) { + if (isset(self::$modules[$ar->speakingurl_type])) { + $routing .= self::$modules[$ar->speakingurl_type]->compileRouting($ar); + } + } + + $routing = '<?xml version="1.0" encoding="utf-8"?><glz:Routing>'.$routing.'</glz:Routing>'; + $evt = array('type' => GLZ_EVT_LISTENER_COMPILE_ROUTING, 'data' => $routing); + $this->dispatchEvent($evt); + } + + public function searchDocumentsByTerm($term, $id, $protocol='', $filterType='') + { + $result = array(); + + foreach (self::$modules as $module) { + $partialResult = $module->searchDocumentsByTerm($term, $id, $protocol, $filterType); + $result = array_merge($result, $partialResult); + } + + return $result; + } + + public function makeUrl($id) + { + foreach (self::$modules as $module) { + $url = $module->makeUrl($id); + + if ($url!==false) { + return $url; + } + } + + return false; + } + + public function makeLink($id) + { + foreach (self::$modules as $module) { + $url = $module->makeLink($id); + + if ($url!==false) { + return $url; + } + } + + return false; + } + + public function onRegister() + { + } +} diff --git a/src/core/classes/org/glizycms/speakingUrl/PageResolver.php b/src/core/classes/org/glizycms/speakingUrl/PageResolver.php new file mode 100644 index 0000000..139fcc5 --- /dev/null +++ b/src/core/classes/org/glizycms/speakingUrl/PageResolver.php @@ -0,0 +1,91 @@ +<?php +class org_glizycms_speakingUrl_PageResolver extends org_glizycms_speakingUrl_AbstractUrlResolver implements org_glizycms_speakingUrl_IUrlResolver +{ + public function __construct() + { + parent::__construct(); + $this->type = 'org.glizycms.core.models.Content'; + $this->protocol = 'internal:'; + } + + public function compileRouting($ar) + { + return '<glz:Route skipLanguage="true" value="'.$ar->language_code.'/'.$ar->speakingurl_value.'" pageId="'.$ar->speakingurl_FK.'" language="'.$ar->language_code.'"/>'; + } + + + public function searchDocumentsByTerm($term, $id, $protocol='', $filterType='') + { + $result = array(); + if ($protocol && $protocol!=$this->protocol) return $result; + + $languageId = $this->editLanguageId; + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Menu'); + + if ($term) { + $it->load('autocompletePagePicker', array('search' => '%'.$term.'%', 'languageId' => $languageId, 'menuId' => '', 'pageType' => $filterType)); + } else if ($id) { + if (!is_numeric($id) && strpos($id, $this->protocol) !== 0) { + return $result; + } elseif (is_string($id)) { + $id = $this->getIdFromLink($id); + } + + $it->load('autocompletePagePicker', array('search' => '', 'languageId' => $languageId, 'menuId' => $id)); + } else { + return $result; + } + + foreach($it as $ar) { + $result[] = array( + 'id' => $this->protocol.$ar->menu_id, + 'text' => $ar->menudetail_title, + 'path' => ltrim($ar->p1.'/'.$ar->p2.'/'.$ar->p3, '/').'/'.$ar->menudetail_title + ); + } + + return $result; + } + + public function makeUrl($id) + { + list($protocol, $id) = explode(':', $id); + if ($protocol.':' == $this->protocol && is_numeric($id)) { + return $this->makeUrlFromId($id); + } + return false; + } + + public function makeLink($id) + { + list($protocol, $id) = explode(':', $id); + if ($protocol.':' == $this->protocol && is_numeric($id)) { + return $this->makeUrlFromId($id, true); + } + return false; + } + + + public function makeUrlFromRequest() + { + $id = __Request::get('pageId', __Config::get('START_PAGE')); + return $this->makeUrlFromId($id); + } + + private function makeUrlFromId($id, $fullLink=false) + { + $siteMap = $this->application->getSiteMap(); + $menu = $siteMap->getNodeById($id); + if ($menu && $menu->isVisible) { + $menuUrl = $menu->url; + $menuTitle = $menu->title; + $url = $menuUrl ? GLZ_HOST.'/'.$menuUrl : __Link::makeUrl('link', array('pageId' => $id, 'title' => $menuTitle)); + + return $fullLink ? __Link::makeSimpleLink($menuTitle, $url) : $url; + } + + // the menu isn't found or isn't visible in this language + // redirect to home + return $this->makeUrlFromId(__Config::get('START_PAGE'), $fullLink); + } +} diff --git a/src/core/classes/org/glizycms/speakingUrl/models/SpeakingUrl.xml b/src/core/classes/org/glizycms/speakingUrl/models/SpeakingUrl.xml new file mode 100755 index 0000000..435f6b4 --- /dev/null +++ b/src/core/classes/org/glizycms/speakingUrl/models/SpeakingUrl.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="speakingurls_tbl" model:usePrefix="true"> + + <model:Query name="all" type="function"> + <![CDATA[ + $expr = $iterator->expr(); + $iterator->join("t1", $this->tablePrefix."languages_tbl", "t2", $expr->eq("t1.speakingurl_FK_language_id", "t2.language_id")); + ]]> + </model:Query> + <model:Query name="deleteAllByType" type="function" arguments="type"> + <!-- + Delete record by type + Used in: + org.glizycms.speakingUrl.models.proxy.SpeakingUrlProxy + --> + <![CDATA[ + $expr = $iterator->expr(); + $qb = $iterator->qb(); + $qb->delete($this->tablePrefix.'speakingurls_tbl') + ->where($expr->comparison('speakingurl_type', '=', ':type')) + ->setParameter(':type', $type); + $iterator->setSqlQuery($qb->getSQL()); + ]]> + </model:Query> +</model:Model> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/speakingUrl/models/proxy/SpeakingUrlProxy.php b/src/core/classes/org/glizycms/speakingUrl/models/proxy/SpeakingUrlProxy.php new file mode 100644 index 0000000..3d59ccd --- /dev/null +++ b/src/core/classes/org/glizycms/speakingUrl/models/proxy/SpeakingUrlProxy.php @@ -0,0 +1,73 @@ +<?php +class org_glizycms_speakingUrl_models_proxy_SpeakingUrlProxy extends GlizyObject +{ + public function validate($value, $languageId, $id, $type) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.speakingUrl.models.SpeakingUrl'); + $ar->speakingurl_FK_language_id = $languageId; + $ar->speakingurl_value = $value; + // TODO: perché non cercare su tutti i campi? + if ($ar->find()) { + return $ar->speakingurl_FK == $id && $ar->speakingurl_type == $type; + } + + return true; + } + + + public function deleteUrl($languageId, $id, $type) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.speakingUrl.models.SpeakingUrl'); + $ar->speakingurl_FK_language_id = $languageId; + $ar->speakingurl_FK = $id; + $ar->speakingurl_type = $type; + if ($ar->find()) { + $ar->delete(); + } + } + + public function addUrl($value, $languageId, $id, $type, $options=array()) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.speakingUrl.models.SpeakingUrl'); + $ar->speakingurl_FK_language_id = $languageId; + $ar->speakingurl_FK = $id; + $ar->speakingurl_type = $type; + if (!$ar->find()) { + $ar->speakingurl_FK_language_id = $languageId; + $ar->speakingurl_FK = $id; + $ar->speakingurl_type = $type; + } + + $ar->speakingurl_value = $value; + $ar->speakingurl_option = serialize($options); + $ar->save(); + } + + public function getUrlForId($id, $languageId) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.speakingUrl.models.SpeakingUrl'); + $ar->speakingurl_FK_language_id = $languageId; + $ar->speakingurl_FK = $id; + $r = $ar->find(array('speakingurl_FK_language_id' => $languageId, 'speakingurl_FK' => $id)); + return $r ? $ar : false; + } + + public function getUrlByValueAndType($value, $type) + { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.speakingUrl.models.SpeakingUrl'); + $r = $ar->find(array('speakingurl_value' => $value, 'speakingurl_type' => $type)); + return $r ? $ar : false; + } + + public function deleteAllByType($type) + { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.speakingUrl.models.SpeakingUrl'); + $it->load('deleteAllByType', array(':type' => $type)); + $it->exec(); + } + + public function getModel() + { + return org_glizy_ObjectFactory::createModel('org.glizycms.speakingUrl.models.SpeakingUrl'); + } +} diff --git a/src/core/classes/org/glizycms/template/controllers/CheckTemplateTabDraw.php b/src/core/classes/org/glizycms/template/controllers/CheckTemplateTabDraw.php new file mode 100644 index 0000000..574fc51 --- /dev/null +++ b/src/core/classes/org/glizycms/template/controllers/CheckTemplateTabDraw.php @@ -0,0 +1,13 @@ +<?php +class org_glizycms_template_controllers_CheckTemplateTabDraw extends org_glizy_mvc_core_Command +{ + public function execute($menuId) + { + $templateEnabled = __Config::get('glizycms.contents.templateEnabled'); + if ($templateEnabled) { + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + $templateEnabled = $templateProxy->getTemplateAdmin()!==false; + } + $this->view->setAttribute('draw', $templateEnabled); + } +} diff --git a/src/core/classes/org/glizycms/template/controllers/Template.php b/src/core/classes/org/glizycms/template/controllers/Template.php new file mode 100644 index 0000000..b418496 --- /dev/null +++ b/src/core/classes/org/glizycms/template/controllers/Template.php @@ -0,0 +1,15 @@ +<?php +class org_glizycms_template_controllers_Template extends org_glizy_mvc_core_Command +{ + public function execute($menuId) + { + if ($menuId) { + // read + + $this->view->setData($data); + } else { +// TODO errore + } + + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/template/controllers/ajax/Save.php b/src/core/classes/org/glizycms/template/controllers/ajax/Save.php new file mode 100644 index 0000000..d6d0c11 --- /dev/null +++ b/src/core/classes/org/glizycms/template/controllers/ajax/Save.php @@ -0,0 +1,12 @@ +<?php +class org_glizycms_template_controllers_ajax_Save extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { +// TODO: controllo acl + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + $templateProxy->saveEditData($data); + + return true; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/template/controllers/ajax/SaveTemplate.php b/src/core/classes/org/glizycms/template/controllers/ajax/SaveTemplate.php new file mode 100644 index 0000000..099207e --- /dev/null +++ b/src/core/classes/org/glizycms/template/controllers/ajax/SaveTemplate.php @@ -0,0 +1,16 @@ +<?php +class org_glizycms_template_controllers_ajax_SaveTemplate extends org_glizy_mvc_core_CommandAjax +{ + public function execute($data) + { +// TODO: controllo acl + $data = json_decode($data); + if ($data && property_exists($data, 'template')) { + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + $templateProxy->setSelectedTemplate($data->template); + org_glizy_cache_CacheFile::cleanPHP(__Paths::get('APPLICATION_TO_ADMIN_CACHE')); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/template/fe/views/AbstractLessTemplate.php b/src/core/classes/org/glizycms/template/fe/views/AbstractLessTemplate.php new file mode 100644 index 0000000..38c4f8c --- /dev/null +++ b/src/core/classes/org/glizycms/template/fe/views/AbstractLessTemplate.php @@ -0,0 +1,91 @@ +<?php +abstract class org_glizycms_template_fe_views_AbstractLessTemplate extends GlizyObject +{ + protected $path; + + abstract protected function applyCssVariables(&$templateData, $less, $css); + abstract protected function applyFont(&$templateData, $css); + abstract protected function addLogoCss(&$templateData, $css); + abstract protected function addCustomCss(&$templateData, $css); + abstract protected function addCustomOutput(&$view, &$templateData); + abstract public function fixTemplateData(&$templateData); + abstract protected function fixTemplateName($view); + + public function render($application, $view, $templateData) + { + $templateData = $this->getTemplateDataFromCache($templateData); + + $siteProp = unserialize(org_glizy_Registry::get(__Config::get('REGISTRY_SITE_PROP').$view->_application->getLanguage(), '')); + $view->addOutputCode($templateData->css, 'css'); + $view->addOutputCode($siteProp['title'], 'siteTitle'); + $view->addOutputCode($siteProp['subtitle'], 'siteSubtitle'); + $this->fixTemplateName($view); + $this->addCustomOutput($view, $templateData); + } + + protected function getTemplateDataFromCache($templateData) + { + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + // $templateProxy->invalidateCache(); + $cache = $templateProxy->getTemplateCache(); + + $cssFileName = __Paths::get('CACHE').md5($this->getClassName().'_'.$templateData->__id).'.css'; + $self = $this; + $templateData = $cache->get($cssFileName, array(), function() use ($self, $templateData, $cssFileName) { + + $self->fixTemplateData($templateData); + $self->compileCss($templateData, $cssFileName); + + return $templateData; + }); + + return $templateData; + } + + public function compileCss(&$templateData, $cssFileName) + { + glz_importLib('lessphp/lessc.inc.php'); + $less = new lessc; + $less->setImportDir(array($this->path.'/less/')); + $css = file_get_contents($this->path.'/less/styles.less'); + $css = $this->applyCssVariables($templateData, $less, $css); + $css = $this->applyFont($templateData, $css); + $css = $less->compile($css); + $css = $this->fixUrl($css); + $css = $this->addLogoCss($templateData, $css); + $css = $this->addCustomCss($templateData, $css); + file_put_contents($cssFileName, $css); + $templateData->css = '<link rel="stylesheet" href="'.$cssFileName.'" type="text/css" media="screen" />'; + } + + protected function fixUrl($css) + { + $templatePath = __Paths::get('APPLICATION_TEMPLATE'); + $css = str_replace( + array('../img/', '../font/'), + array('../'.$templatePath.'/img/', '../'.$templatePath.'/font/'), + $css); + return $css; + } + + protected function applyCssVariablesFromJson(&$templateData, $less, $css) + { + $colorsData = json_decode(file_get_contents($this->path.'/colors.json')); + if ($colorsData) { + $variables = array(); + foreach($colorsData as $part=>$colors) { + foreach($colors as $colorLabel=>$colorData) { + $firstId = $colorData->id[0]; + if (property_exists($templateData, $firstId)) { + $value = $templateData->{$firstId}; + foreach($colorData->id as $v) { + $css .= '@'.$v.':'.$value.';'; + } + + } + } + } + } + return $css; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/template/models/TemplateVO.php b/src/core/classes/org/glizycms/template/models/TemplateVO.php new file mode 100644 index 0000000..070ab22 --- /dev/null +++ b/src/core/classes/org/glizycms/template/models/TemplateVO.php @@ -0,0 +1,13 @@ +<?php +class org_glizycms_template_models_TemplateVO extends GlizyObject +{ + public $name; + public $path; + public $preview; + + function __construct($name, $path, $preview) { + $this->name = str_replace('-', ' ', $name); + $this->path = $path; + $this->preview = $preview; + } +} diff --git a/src/core/classes/org/glizycms/template/models/proxy/TemplateProxy.php b/src/core/classes/org/glizycms/template/models/proxy/TemplateProxy.php new file mode 100644 index 0000000..ab980d3 --- /dev/null +++ b/src/core/classes/org/glizycms/template/models/proxy/TemplateProxy.php @@ -0,0 +1,208 @@ +<?php +class org_glizycms_template_models_proxy_TemplateProxy extends GlizyObject +{ + private $application; + private $templateName; + private $templateValues; + + function __construct() + { + $this->application = org_glizy_ObjectValues::get('org.glizy', 'application'); + $templatePath = __Paths::get('APPLICATION_TO_ADMIN_TEMPLATE'); + if (!$templatePath) { + $tempPath = __Config::get('APPLICATION_TO_ADMIN_TEMPLATE'); + __Paths::set('APPLICATION_TO_ADMIN_TEMPLATE', $tempPath ? $tempPath : __Paths::get('BASE').__Config::get('STATIC_FOLDER').'templates'); + } + } + + public function getAvailableTemplates() + { + $templatePath = __Paths::get('APPLICATION_TO_ADMIN_TEMPLATE'); + $templates = array(); + if ($dh = @opendir($templatePath)) { + // scan the template repository + while ($dirName = readdir($dh)) { + // check if the item is a folder + if ($dirName!="." && + $dirName!=".." && + is_dir($templatePath.'/'.$dirName)) + { + // is a folder + // check if ther eis the rpeview image + // withou the preview the template isn't added + if (file_exists($templatePath.'/'.$dirName.'/preview.jpg') && !file_exists($templatePath.'/'.$dirName.'/disabled')) + { + // check and include the locale file + if (file_exists($templatePath.'/'.$dirName.'/locale/'.$this->application->getLanguage().'.php')) + { + include ($templatePath.'/'.$dirName.'/locale/'.$this->application->getLanguage().'.php'); + $templateName = __T($dirName); + } + else + { + $templateName = $dirName; + } + + $templates[] = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.TemplateVO', $templateName, $dirName, $templatePath.'/'.$dirName.'/preview.jpg'); + } + } + } + closedir($dh); + } + else + { + // TODO + // show error + } + + return $templates; + } + + public function getSelectedTemplate() + { + if (!$this->templateName) { + $this->templateName = org_glizy_Registry::get(__Config::get('REGISTRY_TEMPLATE_NAME'), __Config::get('glizycms.template.default')); + } + return $this->templateName; + } + + public function setSelectedTemplate($name) + { + $this->templateName = $name; + org_glizy_Registry::set(__Config::get('REGISTRY_TEMPLATE_NAME'), $name); + } + + public function getTemplateRealpath() + { + if ($this->application->isAdmin()) { + return org_glizy_Paths::getRealPath('APPLICATION_TO_ADMIN_TEMPLATE', $this->getSelectedTemplate()); + } else { + return org_glizy_Paths::getRealPath('APPLICATION_TEMPLATE'); + } + } + + public function getTemplateCustomClass() + { + $templatePath = $this->getTemplateRealpath(); + if (file_exists($templatePath.'/Template.php')) + { + require_once($templatePath.'/Template.php'); + return new Template(); + } + return null; + } + + public function getTemplateAdmin() + { + $templatePath = $this->getTemplateRealpath(); + return file_exists($templatePath.'/TemplateAdmin.xml') ? $templatePath.'/TemplateAdmin.xml' : false; + } + + public function getTemplateAdminGlobal() + { + $templatePath = $this->getTemplateRealpath(); + return file_exists($templatePath.'/TemplateAdminGlobal.xml') ? $templatePath.'/TemplateAdminGlobal.xml' : false; + } + + public function loadTemplateLocale() + { + $language = $this->application->getLanguage(); + $templatePath = $this->getTemplateRealpath(); + if (file_exists($templatePath.'/locale/'.$language.'.php')) + { + include ($templatePath.'/locale/'.$language.'.php'); + } + } + + public function getEditDataForMenu($menuId, $readFromParent) + { + $this->getData(); + if ($readFromParent && $menuId > 0){ + $data = $this->getDataForMenu($menuId, true); + } else { + $data = property_exists($this->templateValues, $menuId) ? $this->templateValues->{$menuId} : new StdClass; + } + $data->__id = $menuId; + return $data; + } + + public function getDataForMenu($menuId, $readFromParent=false) + { + $this->getData(); + + if (!$readFromParent && property_exists($this->templateValues, $menuId)) { + $data = $this->templateValues->{$menuId}; + $data->__id = $menuId; + } else { + $data = new StdClass; + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $siteMap = $menuProxy->getSiteMap(); + $menu = $siteMap->getNodeById($menuId); + + // scorre tutti i parent per trovare il primo menù che ha i dati + while ($menu->parentId > 0) { + // $tempMenuId = $menu->parentId; + $menu = $siteMap->getNodeById($menu->parentId); + if (property_exists($this->templateValues, $menu->id)) { + $data = $this->templateValues->{$menu->id}; + $data->__id = $menu->id; + break; + } + } + } + + // merge the data with global data + if ($menuId != 0) { + $globalData = $this->getDataForMenu(0); + foreach($globalData as $k=>$v) { + if (!property_exists($data, $k)) { + $data->{$k} = $v; + } + } + } + + return $data; + } + + + public function saveEditData($data) + { + $data = json_decode($data); + $menuId = $data->__id; + if (!$menuId) $menuId = 0; + unset($data->__id); + unset($data->templateEdit_command); + $this->getData(); + $this->templateValues->{$menuId} = $data; + $this->setData(); + $this->invalidateCache(); + } + + public function getTemplateCache() + { + $cache = org_glizy_ObjectFactory::createObject('org.glizy.cache.CacheFunction', + $this, + -1, + false, + __Paths::getRealPath('APPLICATION_TO_ADMIN_CACHE')); + return $cache; + } + + public function invalidateCache() + { + $cache = $this->getTemplateCache(); + $cache->invalidateGroup(); + } + + private function getData() + { + if (!$this->templateValues) { + $this->templateValues = json_decode(org_glizy_Registry::get(__Config::get('REGISTRY_TEMPLATE_VALUES').$this->getSelectedTemplate(), '{}')); + } + } + + private function setData() + { + org_glizy_Registry::set(__Config::get('REGISTRY_TEMPLATE_VALUES').$this->getSelectedTemplate(), json_encode($this->templateValues)); + } +} diff --git a/src/core/classes/org/glizycms/template/views/TemplateSelect.xml b/src/core/classes/org/glizycms/template/views/TemplateSelect.xml new file mode 100644 index 0000000..5cf0947 --- /dev/null +++ b/src/core/classes/org/glizycms/template/views/TemplateSelect.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + xmlns:t="org.glizycms.template.views.components.*" + controllerName="org.glizycms.template.controllers.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Page.php"> + <glz:Import src="_common.xml" /> + + <mvc:StateTabNavigation id="tabs" cssClass="nav nav-tabs" cssClassCurrent="active" addQueryString="true" /> + + <mvc:State name="index" label="{i18n:Template select}"> + <cms:FormEdit id="myForm"> + <t:SelectTemplate id="template" label="{i18n:Select the template}" /> + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=saveTemplate" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="customize" label="{i18n:Customize}"> + <t:TemplateEdit id="templateEdit" global="true"> + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + </cms:FormButtonsPanel> + </t:TemplateEdit> + </mvc:State> +</mvc:Page> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/template/views/components/SelectTemplate.php b/src/core/classes/org/glizycms/template/views/components/SelectTemplate.php new file mode 100644 index 0000000..e2a0dba --- /dev/null +++ b/src/core/classes/org/glizycms/template/views/components/SelectTemplate.php @@ -0,0 +1,70 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_template_views_components_SelectTemplate extends org_glizy_components_HtmlFormElement +{ + protected $template; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('cssClass', false, 'entities big ico-box span11', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClassLabel', false, __Config::get('glizy.formElement.cssClassLabel'), COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('value', false, NULL, COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + $this->templates = $templateProxy->getAvailableTemplates(); + $this->_content = $templateProxy->getSelectedTemplate(); + } + + function render() + { +// TODO: controllo acl + $name = $this->getId(); + + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['name'] = $this->getOriginalId(); + $attributes['disabled'] = $this->getAttribute('disabled') ? 'disabled' : ''; + $attributes['data-type'] = $this->getAttribute('data-type') ? $this->getAttribute('data-type') : 'selectpagetype'; + $attributes['class'] = $this->getAttribute('required') ? 'required' : ''; + $attributes['class'] .= $this->getAttribute( 'cssClass' ) != '' ? ( $attributes['class'] != '' ? ' ' : '' ).$this->getAttribute( 'cssClass' ) : ''; + $attributes['class'] .= ' hidden'; + $attributes['value'] = $this->_content; + + $output = '<input '.$this->_renderAttributes($attributes).'/>'; + $output .= '<ul class="'.$this->getAttribute( 'cssClass' ).'">'; + + foreach ($this->templates as $template) { + $output .= '<li>'; + $output .= '<a class="" data-type="'.$template->path.'"><img src="'.$template->preview.'" />'.$template->name.'</a>'; + $output .= '</li>'; + } + + $output .= '</ul>'; + $cssClassLabel = $this->getAttribute( 'cssClassLabel' ); + $cssClassLabel .= ( $cssClassLabel ? ' ' : '' ).($this->getAttribute('required') ? 'required' : ''); + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), false, '', array('class' => $cssClassLabel ), false); + + $this->addOutputCode($this->applyItemTemplate($label, $output)); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/template/views/components/TemplateColorEdit.php b/src/core/classes/org/glizycms/template/views/components/TemplateColorEdit.php new file mode 100644 index 0000000..336b2de --- /dev/null +++ b/src/core/classes/org/glizycms/template/views/components/TemplateColorEdit.php @@ -0,0 +1,88 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_template_views_components_TemplateColorEdit extends org_glizy_components_Component +{ + private $idParent; + + public function render_html() + { + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + $templateRealPath = $templateProxy->getTemplateRealpath(); + + if ($templateRealPath) { + $idParent = $this->_parent->_parent->getId().'-'; + $data = json_decode(file_get_contents($templateRealPath.'/colors.json')); + if ($data) { + $output = $this->addFieldset($data, $idParent); + $this->addOutputCode($output); + } + } + } + + private function addFieldset(&$data, $idParent) + { + $id = $this->getId(); + $output = ''; + $presets = array(); + $ids = array(); + $label = __T('Preset'); + foreach($data as $k=>$v) { + $result = $this->addColorPicker($v, $idParent); + $output .= '<fieldset><legend>'.__T($k).'</legend>'. + implode('', $result['output']). + '</fieldset>'; + $presets = array_merge($presets, $result['presets']); + $ids = array_merge($ids, $result['id']); + } + + $presets = implode(',', $presets); + $ids = implode(',', $ids); + $output = <<<EOD + <div class="control-group"> + <label class="control-label " for="{$idParent}{$id}">{$label}</label> + <div class="controls"> + <select data-elements="{$ids}" data-type="valuesPreset" class="span11" name="{$id}" id="{$idParent}{$id}"><option value="">-</option><option data-options="{$presets}" value="0">{$label} 1</option></select> + </div> + </div> + {$output} +EOD; + + return $output; + } + + private function addColorPicker(&$data, $idParent) + { + $result = array('output' => array(), 'presets' => array(), 'id' => array()); + $presets = ''; + foreach($data as $k=>$v) { + $label = __T($k); + $id = $v->id[0]; + $result['id'][] = $id; + $result['presets'][] = $v->preset[0]; + $result['output'][] = <<<EOD +<div class="control-group"> + <label for="{$idParent}{$id}" class="control-label ">{$label}</label> + <div class="controls"> + <input id="{$idParent}{$id}" name="{$id}" title="{$label}" class="span11 " type="text" value="" data-type="colorPicker"/> + </div> +</div> +EOD; + } + return $result; + } +} + + + + + + + + diff --git a/src/core/classes/org/glizycms/template/views/components/TemplateEdit.php b/src/core/classes/org/glizycms/template/views/components/TemplateEdit.php new file mode 100644 index 0000000..eb6d7d9 --- /dev/null +++ b/src/core/classes/org/glizycms/template/views/components/TemplateEdit.php @@ -0,0 +1,89 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_template_views_components_TemplateEdit extends org_glizycms_views_components_FormEdit +{ + protected $emptySrc; + protected $editSrc; + protected $_pageTypeObj; + + /** + * Init + * + * @return void + * @access public + */ + public function init() + { + $this->defineAttribute('global', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('adm:cssClass', false, __Config::get('glizy.formElement.admCssClass'), COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + public function process() + { + if ($this->getAttribute('global')) { + $templateXml = 'TemplateAdminGlobal'; + $menuId = 0; + } else { + $templateXml = 'TemplateAdmin'; + $menuId = __Request::get('menuId', __Request::get('__id')); + if (!$menuId) { + // TODO ERRORE + } + } + + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + $templateName = $templateProxy->getSelectedTemplate(); + if (!$templateName) { +// TODO ERRORE + } + $templateProxy->loadTemplateLocale(); + + + // legge i dati del template + $data = $templateProxy->getEditDataForMenu($menuId, __Request::exists('loadFromParent')); + $customTemplate = $templateProxy->getTemplateCustomClass(); + if ($customTemplate && method_exists($customTemplate, 'updateTemplateData')) { + $customTemplate->updateTemplateData($data); + } + $this->setData($data); + + $this->addDefaultComponents(); + + $templateRealPath = $templateProxy->getTemplateRealpath(); + if ($templateRealPath) { + org_glizy_ObjectFactory::attachPageToComponent( + $this, + $this->_application, + $templateXml, + $templateRealPath.'/', + array( 'idPrefix' => $this->getId().'-', + 'skipImport' => true, + 'mode' => 'edit' ), + $this->getId().'-'); + + parent::process(); + // TODO visualizzare che non ci sono parametri di personalizzazione + } + + + + } + + private function addDefaultComponents() { + $id = '__id'; + $c = org_glizy_ObjectFactory::createComponent('org.glizy.components.Hidden', $this->_application, $this, 'glz:Hidden', $id, $id); + $this->addChild($c); + $c->init(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/userManager/fe/Module.php b/src/core/classes/org/glizycms/userManager/fe/Module.php new file mode 100644 index 0000000..464e0e6 --- /dev/null +++ b/src/core/classes/org/glizycms/userManager/fe/Module.php @@ -0,0 +1,17 @@ +<?php +class org_glizycms_userManager_fe_Module +{ + static function registerModule() + { + $moduleVO = org_glizy_Modules::getModuleVO(); + $moduleVO->id = 'glizycms.userManager.fe'; + $moduleVO->name = __T('User Manager'); + $moduleVO->description = ''; + $moduleVO->version = '1.0.0'; + $moduleVO->classPath = 'org.glizycms.userManager.fe'; + $moduleVO->author = 'META srl'; + $moduleVO->authorUrl = 'http://www.gruppometa.it'; + + org_glizy_Modules::addModule( $moduleVO ); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/userManager/fe/config/routing.xml b/src/core/classes/org/glizycms/userManager/fe/config/routing.xml new file mode 100644 index 0000000..c63bbe8 --- /dev/null +++ b/src/core/classes/org/glizycms/userManager/fe/config/routing.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:Routing> + <glz:Route name="glizycms.userManager.registration" value="{pageId=registration}" /> + <glz:Route name="glizycms.userManager.lostpassword" value="{pageId=lostpassword}" /> + <glz:Route name="glizycms.userManager.userdetails" value="{pageId=userdetails}" /> + <glz:Route name="glizycms.userManager.logout" value="logout" pageId="login" action="logout" /> +</glz:Routing> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/userManager/fe/controllers/login/Login.php b/src/core/classes/org/glizycms/userManager/fe/controllers/login/Login.php new file mode 100644 index 0000000..78815f4 --- /dev/null +++ b/src/core/classes/org/glizycms/userManager/fe/controllers/login/Login.php @@ -0,0 +1,13 @@ +<?php +class org_glizycms_userManager_fe_controllers_login_Login extends org_glizy_mvc_core_Command +{ + public function execute() + { + $c = $this->view->getComponentById('formLoginPage'); + if (is_object($c)) { + $url = $this->view->loadContent('loginPage'); + $speakingUrlManager = $this->application->retrieveProxy('org.glizycms.speakingUrl.Manager'); + $c->setAttribute('accessPageId', $speakingUrlManager->makeUrl($url)); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/userManager/fe/controllers/login/Logout.php b/src/core/classes/org/glizycms/userManager/fe/controllers/login/Logout.php new file mode 100644 index 0000000..7ca41d8 --- /dev/null +++ b/src/core/classes/org/glizycms/userManager/fe/controllers/login/Logout.php @@ -0,0 +1,12 @@ +<?php +class org_glizycms_userManager_fe_controllers_login_Logout extends org_glizy_mvc_core_Command +{ + public function execute() + { + $authClass = org_glizy_ObjectFactory::createObject(__Config::get('glizy.authentication')); + $authClass->logout(); + + org_glizy_helpers_Navigation::gotoUrl( GLZ_HOST ); + exit(); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/userManager/fe/controllers/user/LostPassword.php b/src/core/classes/org/glizycms/userManager/fe/controllers/user/LostPassword.php new file mode 100644 index 0000000..ad9618a --- /dev/null +++ b/src/core/classes/org/glizycms/userManager/fe/controllers/user/LostPassword.php @@ -0,0 +1,38 @@ +<?php +class org_glizycms_userManager_fe_controllers_user_LostPassword extends org_glizy_mvc_core_Command +{ + protected $submit; + + function __construct( $view=NULL, $application=NULL ) + { + parent::__construct( $view, $application ); + $this->submit = strtolower( __Request::get( 'submit', '' ) ) == 'submit'; + } + + public function executeLater($email) + { + if ($this->submit && $this->controller->validate()) { + $ar = org_glizy_ObjectFactory::createModel('org.glizy.models.User'); + if (!$ar->find(array('user_email' => $email))) { + // utente non trovato + $this->view->validateAddError(__T('MW_LOSTPASSWORD_ERROR')); + return false; + } + + // utente trovato + // genera una nuova password e la invia per email + glz_import('org.glizy.helpers.Mail'); + // invia la notifica all'utente + $subject = org_glizy_locale_Locale::get('MW_LOSTPASSWORD_EMAIL_SUBJECT'); + $body = org_glizy_locale_Locale::get('MW_LOSTPASSWORD_EMAIL_BODY'); + $body = str_replace('##USER##', $email, $body); + $body = str_replace('##HOST##', org_glizy_helpers_Link::makeSimpleLink(GLZ_HOST, GLZ_HOST), $body); + $body = str_replace('##PASSWORD##', $ar->user_password, $body); + org_glizy_helpers_Mail::sendEmail( array('email' => org_glizy_Request::get('email', ''), 'name' => $ar->user_firstName.' '.$ar->user_lastName), + array('email' => org_glizy_Config::get('SMTP_EMAIL'), 'name' => org_glizy_Config::get('SMTP_SENDER')), + $subject, + $body); + $this->changeAction('lostPasswordConfirm'); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/userManager/fe/controllers/user/Modify.php b/src/core/classes/org/glizycms/userManager/fe/controllers/user/Modify.php new file mode 100644 index 0000000..59cbb64 --- /dev/null +++ b/src/core/classes/org/glizycms/userManager/fe/controllers/user/Modify.php @@ -0,0 +1,56 @@ +<?php +class org_glizycms_userManager_fe_controllers_user_Modify extends org_glizy_mvc_core_Command +{ + protected $submit; + + function __construct( $view=NULL, $application=NULL ) + { + parent::__construct( $view, $application ); + $this->submit = strtolower( __Request::get( 'submit', '' ) ) == 'submit'; + } + + public function execute() + { + if ($this->user->isLogged() && !$this->submit) { + $ar = org_glizy_ObjectFactory::createModel('org.glizy.models.User'); + $ar->load($this->user->id); + $values = $ar->getValuesAsArray(); + $values['user_password'] = ''; + __Request::setFromArray($values); + } + } + + public function executeLater() + { + if ($this->user->isLogged() && $this->submit && $this->controller->validate()) { + $ar = org_glizy_ObjectFactory::createModel('org.glizy.models.User'); + $ar->load($this->user->id); + + $email = org_glizy_Request::get('user_email', ''); + if ($email != $ar->user_loginId) { + $ar2 = org_glizy_ObjectFactory::createModel('org.glizy.models.User'); + if ($ar2->find(array('user_loginId' => $email)) && $ar2->user_id!=$ar->user_id) { + $this->view->validateAddError('L\'email è già presente nel database, usare un\'altra email'); + return; + } + } + + // TODO migliorare così siamo esposti a problemi di sicurezza + $fields = $ar->getFields(); + foreach($fields as $k=>$v) { + if ($k=='user_password') continue; + if (__Request::exists($k)) { + $ar->$k = __Request::get($k); + } + } + $password = __Request::get('user_password'); + if ($password) { + $ar->user_password = glz_password($password); + } + $ar->user_loginId = $email; + $ar->user_email = $email; + $ar->save(); + $this->changeAction('modifyConfirm'); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/userManager/fe/controllers/user/Registration.php b/src/core/classes/org/glizycms/userManager/fe/controllers/user/Registration.php new file mode 100644 index 0000000..e0e2f49 --- /dev/null +++ b/src/core/classes/org/glizycms/userManager/fe/controllers/user/Registration.php @@ -0,0 +1,40 @@ +<?php +class org_glizycms_userManager_fe_controllers_user_Registration extends org_glizy_mvc_core_Command +{ + protected $submit; + + function __construct( $view=NULL, $application=NULL ) + { + parent::__construct( $view, $application ); + $this->submit = strtolower( __Request::get( 'submit', '' ) ) == 'submit'; + } + + public function executeLater() + { + if ($this->submit && $this->controller->validate()) { + $email = org_glizy_Request::get('user_email', ''); + $ar = org_glizy_ObjectFactory::createModel('org.glizy.models.User'); + if ($ar->find(array('user_loginId' => $email))) { +// TODO tradurre + $this->view->validateAddError('L\'email è già presente nel database, usare un\'altra email o richiedere la password'); + return; + } + + $fields = $ar->getFields(); + foreach($fields as $k=>$v) { + if (__Request::exists($k)) { + $ar->$k = __Request::get($k); + } + } + + $ar->user_FK_usergroup_id = __Config::get('USER_DEFAULT_USERGROUP'); + $ar->user_isActive = __Config::get('USER_DEFAULT_ACTIVE_STATE'); + $ar->user_password = glz_password(__Request::get('user_password')); + $ar->user_loginId = $email; + $ar->user_email = $email; + $ar->user_dateCreation = new org_glizy_types_DateTime(); + $ar->save(); + $this->changeAction('registrationConfirm'); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/userManager/models/UserGroup.xml b/src/core/classes/org/glizycms/userManager/models/UserGroup.xml new file mode 100755 index 0000000..84e2d4a --- /dev/null +++ b/src/core/classes/org/glizycms/userManager/models/UserGroup.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<model:Model + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:model="http://www.glizy.org/dtd/1.0/model/" + model:tableName="usergroups_tbl" model:usePrefix="true"> + + <model:Query name="userGroupsAdmin" type="function"> + $iterator->select('usergroup_id as k', 'usergroup_name as v') + ->orderBy('v'); + </model:Query> + + <model:Query name="userGroups" type="function"> + $iterator->select('usergroup_id as k', 'usergroup_name as v') + ->where('userGroup_backEndAccess', 0) + ->orderBy('v'); + </model:Query> +</model:Model> diff --git a/src/core/classes/org/glizycms/userManager/views/UserManagerEdit.xml b/src/core/classes/org/glizycms/userManager/views/UserManagerEdit.xml new file mode 100755 index 0000000..b3b2805 --- /dev/null +++ b/src/core/classes/org/glizycms/userManager/views/UserManagerEdit.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:cms="org.glizycms.views.components.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="Page.php"> + <glz:Import src="_common.xml" /> + + <mvc:State name="index"> + <glz:DataProvider id="dp" recordClassName="org.glizy.models.User" /> + <glz:DataGrid id="dataGrid" label="{i18n: Elenco utenti}" dataProvider="{dp}" filters="{filters}" tableCssClass="table table-striped table-bordered" cssClass="odd,even" paginate="{dataGridPaginate}" controller="{dataGridEdit}" orderStyle="BLACK"> + <glz:DataGridColumn columnName="user_id" visible="false" key="true"/> + <glz:DataGridColumn columnName="user_firstName" headerText="{i18n:GLZ_USER_FIRST}" /> + <glz:DataGridColumn columnName="user_lastName" headerText="{i18n:GLZ_USER_LAST}" /> + <glz:DataGridColumn columnName="user_email" headerText="{i18n:GLZ_USER_EMAIL}" /> + <glz:DataGridColumn columnName="user_isActive" headerText="{i18n:GLZ_USER_ACTIVE}" align="center" renderCell="org.glizycms.core.application.renderer.CellUserActive" /> + <glz:DataGridColumn columnName="user_id" align="right" width="80" renderCell="org.glizycms.contents.views.renderer.CellEditDelete" /> + </glz:DataGrid> + <glz:PaginateResult id="dataGridPaginate" cssClass="pagination"/> + <glz:Link label="{i18n:GLZ_USER_ADD_NEW_RECORD}" cssClass="{config:glizycms.form.actionLink.cssClass}" icon="icon-plus" routeUrl="actionsMVCAdd" editableRegion="actions" acl="*,new"/> + </mvc:State> + + <mvc:State name="edit"> + <glz:DataDictionary id="usergroupsDP" recordClassName="org.glizycms.userManager.models.UserGroup" field="usergroup_id,usergroup_name" query="userGroupsAdmin" /> + <cms:FormEdit id="myForm" controllerName="org.glizycms.contents.controllers.activeRecordEdit.*"> + <cms:pageTitleModifier action="edit" label="{i18n:New user}" new="true" /> + <cms:pageTitleModifier action="edit" label="{i18n:Edit user}" new="false" field="user_loginId" /> + <glz:Hidden id='__id' /> + <glz:Hidden id="__model" value="org.glizy.models.User"/> + <glz:Checkbox id="user_isActive" label="{i18n:GLZ_USER_IS_ACTIVE}" data="type=checkbox" /> + <glz:Input id="user_loginId" label="{i18n:Username}" size="90" required="true" /> + <glz:Input id="user_password" label="{i18n:Password}" size="90" required="true" /> + <glz:List id="user_FK_usergroup_id" label="{i18n:User group}" dataProvider="{usergroupsDP}" emptyValue="-" required="true" /> + <glz:Input id="user_firstName" label="{i18n:GLZ_USER_FIRST}" size="90" required="true" /> + <glz:Input id="user_lastName" label="{i18n:GLZ_USER_LAST}" size="90" required="true" /> + <glz:Input id="user_email" label="{i18n:GLZ_USER_EMAIL}" size="90" required="true" /> + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <glz:HtmlButton label="{i18n:GLZ_SAVE_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=saveClose" /> + <glz:HtmlButton label="{i18n:GLZ_CANCEL}" type="button" cssClass="btn js-glizycms-cancel" data="action=cancel" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="delete"> + <glz:Hidden controllerName="org.glizycms.contents.controllers.activeRecordEdit.*" /> + <glz:Hidden id="__model" value="org.glizy.models.User"/> + </mvc:State> + +</mvc:Page> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/views/TemplateModuleAdmin.xml b/src/core/classes/org/glizycms/views/TemplateModuleAdmin.xml new file mode 100644 index 0000000..daa6115 --- /dev/null +++ b/src/core/classes/org/glizycms/views/TemplateModuleAdmin.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="utf-8"?> +<mvc:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:mvc="org.glizy.mvc.components.*" + xmlns:r="org.glizycms.roleManager.views.*" + defaultEditableRegion="content" + templateType="php" + templateFileName="##templateFileName##"> + + <glz:templateDefine name="templateFileName" required="false" defaultValue="Page.php"/> + <glz:templateDefine name="model" required="true" /> + <glz:templateDefine name="grid_fields" required="true" /> + <glz:templateDefine name="form_fields" required="true" /> + <glz:templateDefine name="custom_states" required="false" defaultValue="" /> + <glz:templateDefine name="primary_key" required="false" defaultValue="document_id" /> + <glz:templateDefine name="controller_name" required="false" defaultValue="org.glizycms.contents.controllers.moduleEdit.*" /> + <glz:templateDefine name="show_external_id" required="false" defaultValue="true" /> + <glz:templateDefine name="show_permissions" required="false" defaultValue="true" /> + <glz:templateDefine name="render_cell" required="false" defaultValue="org.glizycms.contents.views.renderer.CellEditDeleteVisible" /> + + <glz:Import src="_common.xml" /> + + <mvc:State name="index"> + <glz:Link label="{i18n:GLZ_ADD_NEW_RECORD}" cssClass="{config:glizycms.form.actionLink.cssClass}" icon="icon-plus" routeUrl="actionsMVCAdd" editableRegion="actions" acl="*,new"/> + <glz:DataGridAjax id="dataGrid" recordClassName="##model##" cssClass="table table-bordered table-striped"> + ##grid_fields## + <glz:DataGridColumn columnName="##primary_key##" sortable="false" searchable="false" cssClass="actions" renderCell="##render_cell##" /> + </glz:DataGridAjax> + </mvc:State> + + <mvc:State name="edit"> + <cms:FormEdit id="editForm" controllerName="##controller_name##"> + <glz:Hidden id="__id" /> + <glz:Hidden id="__model" value="##model##"/> + <glz:Input id="external_id" label="{i18n:ID}" size="90" disabled="true" visible="##show_external_id##" /> + ##form_fields## + + <glz:if condition="##show_permissions##"> + <glz:Import src="_permissions.xml" /> + </glz:if> + + <cms:FormButtonsPanel> + <glz:HtmlButton label="{i18n:GLZ_SAVE}" type="button" cssClass="btn btn-primary js-glizycms-save" data="action=save" /> + <glz:HtmlButton label="{i18n:GLZ_SAVE_CLOSE}" type="button" cssClass="btn js-glizycms-save" data="action=saveClose" /> + <glz:HtmlButton label="{i18n:GLZ_CANCEL}" type="button" routeUrl="link" cssClass="btn js-glizycms-cancel" data="action=cancel" /> + </cms:FormButtonsPanel> + </cms:FormEdit> + </mvc:State> + + <mvc:State name="delete"> + <glz:Hidden controllerName="##controller_name##" /> + </mvc:State> + + <mvc:State name="togglevisibility"> + <glz:Hidden controllerName="##controller_name##" /> + </mvc:State> + + ##custom_states## +</mvc:Page> \ No newline at end of file diff --git a/src/core/classes/org/glizycms/views/components/EditLanguage.php b/src/core/classes/org/glizycms/views/components/EditLanguage.php new file mode 100644 index 0000000..9a1e246 --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/EditLanguage.php @@ -0,0 +1,74 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_views_components_EditLanguage extends org_glizy_components_Component +{ + function init() + { + $this->defineAttribute('label', false, '{i18n:GLZ_EDIT_LANGUAGE}', COMPONENT_TYPE_STRING); + parent::init(); + $this->doLater($this, 'checkSwicth'); + } + + function checkSwicth() + { + if (!is_null(org_glizy_Request::get('switchLanguage'))) + { + $language = org_glizy_Request::get('switchLanguage'); + $this->_application->switchEditingLanguage($language); + } + } + + function process() + { + $this->_content = array(); + $this->_content['label'] = $this->getAttribute('label'); + $this->_content['cssClass'] = $this->getAttribute('cssClass'); + $this->_content['current'] = ''; + $this->_content['records'] = array(); + + $iterator = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language'); + $iterator->orderBy('language_order'); + + if ($iterator->count()) { + $editLanguageId = $this->_application->getEditingLanguageId(); + foreach ($iterator as $ar) { + if ($ar->language_id == $editLanguageId) { + $this->_content['current'] = $ar->language_name; + continue; + } + + $url = org_glizy_helpers_Link::addParams(array('switchLanguage' => $ar->language_id)); + $this->_content['records'][] = org_glizy_helpers_Link::makeSimpleLink( glz_encodeOutput( $ar->language_name ), $url, $ar->language_name); + } + } + } + +} + +class org_glizycms_views_components_EditLanguage_render extends org_glizy_components_render_Render +{ + function getDefaultSkin() + { + $skin = <<<EOD +<div tal:attributes="id id; class Component/cssClass"> + <span tal:omit-tag="" tal:content="Component/label" /> + <div class="btn-group"> + <a tal:attributes="data-target php: '#' . id . 'menu'" data-toggle="dropdown" class="btn dropdown-toggle action-link"><i class="icon-chevron-down"></i> <span tal:omit-tag="" tal:content="Component/current" /></a> + <div tal:attributes="id php: id . 'menu'"> + <ul class="dropdown-menu right"> + <li tal:repeat="item Component/records" tal:content="structure item" /> + </ul> + </div> + </div> +</div> +EOD; + return $skin; + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/views/components/FormButtonsPanel.php b/src/core/classes/org/glizycms/views/components/FormButtonsPanel.php new file mode 100644 index 0000000..1fe51d0 --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/FormButtonsPanel.php @@ -0,0 +1,36 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizycms_views_components_FormButtonsPanel extends org_glizy_components_ComponentContainer +{ + private $templateStart = ''; + private $templateEnd = ''; + + function process() + { + $template = __Config::get('glizycms.form.buttonsPanel'); + if ($template) { + list($templateStart, $templateEnd) = explode('##CONTENT##', $template); + $this->templateStart = str_replace('##ID##', $this->getid(), $templateStart); + $this->templateEnd = $templateEnd; + } + parent::process(); + } + + function render_html_onStart() + { + $this->addOutputCode($this->templateStart); + } + + function render_html_onEnd() + { + $this->addOutputCode($this->templateEnd); + } +} diff --git a/src/core/classes/org/glizycms/views/components/FormEdit.php b/src/core/classes/org/glizycms/views/components/FormEdit.php new file mode 100644 index 0000000..ade5a81 --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/FormEdit.php @@ -0,0 +1,312 @@ +<?php +class org_glizycms_views_components_FormEdit extends org_glizy_components_Form +{ + protected $data = '{}'; + protected $pageTitleModifiers = array(); + + function init() + { + // define the custom attributes + $this->defineAttribute( 'customValidation', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute( 'newCode', false, false, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + + $this->setAttribute( 'addValidationJs', false ); + $this->setAttribute('cssClass', ' formEdit', true); + } + + public function setData($data) + { + $this->data = is_array($data) || is_object($data) ? json_encode($data) : $data; + $this->_content = is_object($data) ? get_object_vars($data) : $data; + } + + public function addPageTitleModifier(org_glizycms_views_components_FormEditPageTitleModifierVO $modifier) + { + $this->pageTitleModifiers[] = $modifier; + } + + public function process() + { + parent::process(); + $this->changePageTitle(); + } + + // public function render_html_onStart() + // { + // $this->setAttribute( 'addValidationJs', false ); + // $this->setAttribute('cssClass', ' formEdit', true); + // parent::render_html_onStart(); + // } + + public function render_html_onEnd($value='') + { + parent::render_html_onEnd(); + + + $corePath = __Paths::get('CORE'); + $jQueryPath = $corePath.'classes/org/glizycms/js/jquery/'; + + $languageCode = $this->_application->getLanguage(); + $language = $languageCode.'-'.strtoupper($languageCode); + + if ($this->getAttribute('newCode')) { + $formEditPath = $corePath.'classes/org/glizycms/js/formEdit2/'; + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $corePath.'classes/org/glizycms/js/underscore/underscore-min.js' )); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEdit.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditStandard.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditCheckbox.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditRepeat.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditDate.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditDateTime.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'bootstrap-datetimepicker-master/js/bootstrap-datetimepicker.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.it.js' ) ); + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'bootstrap-datetimepicker-master/css/datetimepicker.css' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditColorPicker.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'bootstrap-colorpicker/js/bootstrap-colorpicker.min.js' ) ); + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'bootstrap-colorpicker/css/bootstrap-colorpicker.min.css' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditGUID.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditSelectFrom.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'select2/select2.min.js' ) ); + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'select2/select2.css' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditTINYMCE.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditMediaPicker.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditFile.js' ) ); + //$this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'fineuploader.jquery/jquery.fineuploader.js' ) ); + //$this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'fineuploader.jquery/fineuploader.css' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'jquery.validVal-packed.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditPermission.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditPhotoGalleryCategory.js' ) ); + + // $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditGoogleMaps.js' ) ); + // $this->addOutputCode(org_glizy_helpers_JS::linkJSfile( 'http://maps.google.com/maps/api/js?sensor=false' )); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditCmsPagePicker.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditSelectPageType.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditUrl.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditModalPage.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $corePath.'classes/org/glizycms/js/glizy-locale/'.$language.'.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'jquery.pnotify/jquery.pnotify.min.js' ) ); + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'jquery.pnotify/jquery.pnotify.default.css' ) ); + + $id = $this->getId(); + + $mediaPicker = $this->getMediaPickerUrl(); + $AJAXAtion = $this->getAttribute('controllerName') ? $this->getAjaxUrl() : ''; + + $customValidation = $this->getAttribute('customValidation'); + if ( $customValidation ) { + $customValidation = 'customValidation: "'.$customValidation.'",'; + } + + $tinyMceUrls = json_encode($this->getTinyMceUrls()); + + $jsCode = <<< EOD +jQuery(function(){ + if ( Glizy.tinyMCE_options ) + { + Glizy.tinyMCE_options.urls = $tinyMceUrls; + } + + var myFormEdit = Glizy.oop.create("glizy.FormEdit", '$id', { + AJAXAction: "$AJAXAtion", + mediaPicker: $mediaPicker, + formData: $this->data, + $customValidation + lang: GlizyLocale.FormEdit + }); +}); +EOD; + } else { + $formEditPath = $corePath.'classes/org/glizycms/js/formEdit/'; + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $corePath.'classes/org/glizycms/js/underscore/underscore-min.js' )); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEdit.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditTINYMCE.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditFile.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditMediaPicker.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditGoogleMaps.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditGUID.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditColorPicker.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditValuesPreset.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditDate.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditDatetime.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'bootstrap-datetimepicker-master/js/bootstrap-datetimepicker.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'bootstrap-datetimepicker-master/js/locales/bootstrap-datetimepicker.it.js' ) ); + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'bootstrap-datetimepicker-master/css/datetimepicker.css' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'bootstrap-colorpicker/js/bootstrap-colorpicker.min.js' ) ); + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'bootstrap-colorpicker/css/bootstrap-colorpicker.min.css' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $corePath.'classes/org/glizycms/js/glizy-locale/'.$language.'.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'dropzone/dropzone.min.js' ) ); + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'dropzone/css/basic2.css' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'jquery.validVal-packed.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditCmsPagePicker.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditSelectFrom.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'select2/select2.min.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'jquery.pnotify/jquery.pnotify.min.js' ) ); + + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditPermission.js' ) ); + + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'select2/select2.css' ) ); + $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'jquery.pnotify/jquery.pnotify.default.css' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditCheckbox.js' ) ); + $this->addOutputCode(org_glizy_helpers_JS::linkJSfile( 'http://maps.google.com/maps/api/js?sensor=false' )); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditSelectPageType.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditPhotoGalleryCategory.js' ) ); + $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditImageHotspot.js' ) ); + + // $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $formEditPath.'GlizyFormEditTreeSelect.js' ) ); + // $this->addOutputCode( org_glizy_helpers_JS::linkJSfile( $jQueryPath.'fancytree/jquery.fancytree-all.min.js' ) ); + // $this->addOutputCode( org_glizy_helpers_CSS::linkCSSfile( $jQueryPath.'fancytree/skin-win7/ui.fancytree.min.css' ) ); + + $id = $this->getId(); + + $mediaPicker = $this->getMediaPickerUrl(); + $AJAXAtion = $this->getAttribute('controllerName') ? $this->getAjaxUrl() : ''; + + $customValidation = $this->getAttribute('customValidation'); + if ( $customValidation ) { + $customValidation = 'customValidation: "'.$customValidation.'",'; + } + + $tinyMceUrls = json_encode($this->getTinyMceUrls()); + + $jsCode = <<< EOD +jQuery(function(){ + if ( Glizy.tinyMCE_options ) + { + Glizy.tinyMCE_options.urls = $tinyMceUrls; + } + + var ajaxUrl = "$AJAXAtion"; + jQuery( "#$id" ).GlizyFormEdit({ + AJAXAction: ajaxUrl ? ajaxUrl : Glizy.ajaxUrl, + mediaPicker: $mediaPicker, + formData: $this->data, + $customValidation + lang: GlizyLocale.FormEdit + }); +}); +EOD; + } + + $this->addOutputCode(org_glizy_helpers_JS::JScode( $jsCode )); + } + + protected function getMediaPickerUrl() + { + return '"'.org_glizycms_Glizycms::getMediaArchiveBridge()->getMediaPickerUrl().'"'; + } + + protected function getTinyMceUrls() + { + return array( + 'ajaxUrl' => GLZ_HOST.'/'.$this->getAjaxUrl(), + 'mediaPicker' => GLZ_HOST.'/'.org_glizycms_Glizycms::getMediaArchiveBridge()->getMediaPickerUrl(), + 'mediaPickerTiny' => GLZ_HOST.'/'.org_glizycms_Glizycms::getMediaArchiveBridge()->getMediaPickerUrl(true), + 'imagePickerTiny' => GLZ_HOST.'/'.org_glizycms_Glizycms::getMediaArchiveBridge()->getMediaPickerUrl(true, 'IMAGE'), + 'imageResizer' => org_glizycms_Glizycms::getMediaArchiveBridge()->getImageResizeTemplate(), + 'root' => GLZ_HOST.'/', + ); + } + + protected function changePageTitle() + { + if ( method_exists( $this->_parent, "getAction" ) ) + { + $currentAction = $this->_parent->getAction(); + foreach($this->pageTitleModifiers as $modifier) + { + if ($currentAction==$modifier->action) { + $newTitle = $modifier->label; + $newSubtitle = $modifier->fieldSubtitle && $this->_content[$modifier->fieldSubtitle] ? $this->_content[$modifier->fieldSubtitle] : ''; + if ($modifier->isNew) { + if ($modifier->idField && + ($this->_content[$modifier->idField]!='0' && isset($this->_content[$modifier->idField]))) { + continue; + } + } + + if (preg_match("/\{i18n\:.*\}/i", $newTitle)) + { + $code = preg_replace("/\{i18n\:(.*)\}/i", "$1", $newTitle); + $newTitle = org_glizy_locale_Locale::get($code, $newSubtitle); + } + + $evt = array('type' => GLZ_EVT_PAGETITLE_UPDATE, 'data' => $newTitle); + $this->dispatchEvent($evt); + break; + } + } + } + } + + function loadContent($name, $bindToField=NULL) + { + if (empty($bindToField)) { + $bindToField = $name; + } + + return org_glizy_Request::get($bindToField, $this->_content[$bindToField]); + } + + + public static function compile($compiler, &$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix, $componentClassInfo, $componentId) + { + $compiler->compile_baseTag( $node, $registredNameSpaces, $counter, $parent, $idPrefix, $componentClassInfo, $componentId ); + + $oldcounter = $counter; + foreach ($node->childNodes as $n ) { + if ( $n->nodeName == "cms:pageTitleModifier" ) { + $action = $n->hasAttribute('action') ? $n->getAttribute('action') : ''; + $label = $n->hasAttribute('label') ? $n->getAttribute('label') : ''; + $new = $n->hasAttribute('new') ? $n->getAttribute('new') : 'false'; + $field = $n->hasAttribute('field') ? $n->getAttribute('field') : ''; + $idField = $n->hasAttribute('idField') ? $n->getAttribute('idField') : '__id'; + if ( $action && $label ) + { + $compiler->_classSource .= '$n'.$counter.'->addPageTitleModifier('. + 'new org_glizycms_views_components_FormEditPageTitleModifierVO("'.$action.'", "'.$label.'", '.$new.', "'.$idField.'", "'.$field.'"));'; + } + } else { + $counter++; + $compiler->compileChildNode($n, $registredNameSpaces, $counter, $oldcounter, $idPrefix); + } + } + + return false; + } +} + +class org_glizycms_views_components_FormEditPageTitleModifierVO +{ + function __construct($action, $label, $isNew, $idField, $fieldSubtitle) { + $this->action = $action; + $this->label = $label; + $this->isNew = $isNew; + $this->idField = $idField; + $this->fieldSubtitle = $fieldSubtitle; + } +} + + diff --git a/src/core/classes/org/glizycms/views/components/FormEditWithAjaxSteps.php b/src/core/classes/org/glizycms/views/components/FormEditWithAjaxSteps.php new file mode 100644 index 0000000..045f790 --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/FormEditWithAjaxSteps.php @@ -0,0 +1,25 @@ +<?php +class org_glizycms_views_components_FormEditWithAjaxSteps extends org_glizycms_views_components_FormEdit +{ + public function render_html_onStart() + { + // TODO localizzare il javascript + $this->addOutputCode(org_glizy_helpers_JS::linkCoreJSfile('jquery-simplemodal/jquery.simplemodal.1.4.1.min.js')); + $this->addOutputCode(org_glizy_helpers_JS::linkCoreJSfile('progressBar/progressBar.js')); + $this->addOutputCode(org_glizy_helpers_CSS::linkCoreCSSfile2('progressBar/progressBar.css'), 'head'); + $this->addOutputCode(org_glizy_helpers_JS::linkCoreJSfile('formWithAjaxSteps.js?v='.GLZ_CORE_VERSION)); + + parent::render_html_onStart(); + + $ajaxUrl = $this->getAttribute('controllerName') ? $this->getAjaxUrl() : ''; + + $output = <<<EOD +<div id="progress_bar" class="js-glizycms-FormEditWithAjaxSteps ui-progress-bar ui-container" data-ajaxurl="$ajaxUrl"> + <div class="ui-progress" style="width: 0%;"> + <span class="ui-label" style="display:none;"><b class="value">0%</b></span> + </div> +</div> +EOD; + $this->addOutputCode($output); + } +} diff --git a/src/core/classes/org/glizycms/views/components/GoogleAnalytics.php b/src/core/classes/org/glizycms/views/components/GoogleAnalytics.php new file mode 100644 index 0000000..735bcdd --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/GoogleAnalytics.php @@ -0,0 +1,35 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_views_components_GoogleAnalytics extends org_glizy_components_Component +{ + function render_html() + { + $siteProp = $this->_application->getSiteProperty(); + if ( isset( $siteProp[ 'analytics' ] ) && !empty( $siteProp[ 'analytics' ] ) ) + { + $code = $siteProp[ 'analytics' ]; + $host = $_SERVER['SERVER_NAME']; + $output = <<< EOD +<script> + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) + })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); + + ga('create', '{$code}', 'auto'); + ga('send', 'pageview'); + +</script> +EOD; + // add the code in the output buffer + $this->addOutputCode($output); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/views/components/LanguageNavigation.php b/src/core/classes/org/glizycms/views/components/LanguageNavigation.php new file mode 100644 index 0000000..4edd95a --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/LanguageNavigation.php @@ -0,0 +1,61 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_views_components_LanguageNavigation extends org_glizy_components_Component +{ + + function init() + { + // define the custom attributes + $this->defineAttribute('cssClass', false, 'languages', COMPONENT_TYPE_STRING); + $this->defineAttribute('separator', false, 'none', COMPONENT_TYPE_STRING); // none, start, end + + // call the superclass for validate the attributes + parent::init(); + } + + function render_html() + { + if (!__Config::get('MULTILANGUAGE_ENABLED')) { + return false; + } + + $iterator = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language', + 'all', array('order' => 'language_order')); + + if ($iterator->count() > 1) + { + $output = '<ul class="'.$this->getAttribute('cssClass').'" id="'.$this->getId().'">'; + if ($this->getAttribute('separator')=='start') + { + $output .= '<li class="separator">|</li>'; + } + + foreach($iterator as $ar) + { + $url = __Link::addParams(array('language' => $ar->language_code)); + if ($ar->language_id==$this->_application->getLanguageId()) + { + $output .= '<li class="'.$ar->language_code.'">'.org_glizy_helpers_Link::makeSimpleLink( glz_encodeOutput( $ar->language_name ), $url, '', 'active').'</li>'; + } + else + { + $output .= '<li class="'.$ar->language_code.'">'.org_glizy_helpers_Link::makeSimpleLink( glz_encodeOutput( $ar->language_name ), $url).'</li>'; + } + } + + if ($this->getAttribute('separator')=='end') + { + $output .= '<li>|</li>'; + } + $output .= '</ul>'; + $this->addOutputCode($output); + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/views/components/MvcPage.php b/src/core/classes/org/glizycms/views/components/MvcPage.php new file mode 100755 index 0000000..406532e --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/MvcPage.php @@ -0,0 +1,127 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_views_components_MvcPage extends org_glizycms_views_components_Page +{ + private $controllerBasePath; + private $sessionEx; + private $action; + private $actionName; + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->acceptOutput = true; + $this->overrideEditableRegion = false; + $this->canCallController = false; + + // define the custom attributes + //$this->defineAttribute('actionName', false, 'action', COMPONENT_TYPE_STRING); + $this->defineAttribute('defaultAction', false, 'index', COMPONENT_TYPE_STRING); + $this->defineAttribute('baseClassPath', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('controllerName', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + + $this->actionName = $this->getAttribute( 'actionName' ); + if (__Request::get($this->actionName, '') == '') { + __Request::set($this->actionName, $this->getAttribute( 'defaultAction' )); + } + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $acl = $this->getAttribute( 'acl' ); + if ( !empty( $acl ) ) + { + list( $service, $action ) = explode( ',', $acl ); + if ( !$this->_user->acl( $service, $action ) ) + { + $this->breakCycle(); + $this->addOutputCode( "403 Forbidden" ); + return; + } + } + + $this->loadContentFromDB(); + $this->loadTemplate(); + $this->sessionEx = org_glizy_ObjectFactory::createObject('org.glizy.SessionEx', $this->getId()); + + $this->action = __Request::get( $this->actionName); + $oldAction = $this->sessionEx->get( $this->actionName ); + + foreach ( $this->childComponents as $c ) + { + if ( is_a( $c, 'org_glizy_mvc_components_State' ) ) + { + $c->deferredChildCreation(); + } + } + + $this->callController(); + $this->canCallController = true; + $this->action = strtolower( $this->action ); + $this->processChilds(); + $this->sessionEx->set( $this->actionName, $oldAction ); + } + + + /** + * Render + * + * @return void + * @access public + */ + function render($outputMode=NULL, $skipChilds=false) + { + $this->_application->_rootComponent->addOutputCode( org_glizy_helpers_JS::JScode( 'if (typeof(Glizy)!=\'object\') Glizy = {}; Glizy.baseUrl ="'.GLZ_HOST.'"; Glizy.ajaxUrl = "ajax.php?pageId='.$this->_application->getPageId().'&ajaxTarget='.$this->getId().'&action=";' ), 'head' ); + return parent::render($outputMode, $skipChilds); + } + + + + function getAction() + { + return $this->action; + } + + + function getState() + { + return strtolower($this->action); + } + + // TODO + // modificare il tipo di implementazione + // non mi piace che un componente chieda l'url ad un'altro componente + function changeStateUrl($newState='', $amp=false ) + { + if ( is_null( $this->getAttribute('targetPage') ) ) + { + return org_glizy_helpers_Link::makeUrl('linkChangeAction', array('pageId' => $this->_application->getPageId(), $this->actionName => $newState)); + } + else + { + return org_glizy_helpers_Link::makeUrl('link', array('pageId' => $this->getAttribute('targetPage')), array($this->actionName => $newState)); + } + } +} diff --git a/src/core/classes/org/glizycms/views/components/Page.php b/src/core/classes/org/glizycms/views/components/Page.php new file mode 100755 index 0000000..f5f1a20 --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/Page.php @@ -0,0 +1,157 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizycms_views_components_Page extends org_glizy_components_Page +{ + private $templateData; + private $customTemplate; + private $selfId; + + + + /** + * Init + * + * @return void + * @access public + */ + function init() + { + $this->defineAttribute('allowBlocks', false, false, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + + /** + * Process + * + * @return boolean false if the process is aborted + * @access public + */ + function process() + { + $this->selfId = $this->getId(); + $this->_content = array(); + $this->loadContentFromDB(); + $this->loadTemplate(); + + $this->processChilds(); + } + + + function render() + { + $this->loadSiteProperties(); + + if (is_object($this->customTemplate)) { + $this->customTemplate->render($this->_application, $this, $this->templateData); + } + return parent::render(); + } + + + function loadContent($id) + { + if (property_exists($this->_content, $id)) { + return $this->_content->{$id}; + } else if (strpos($id, 'template:')===0) { + $id = substr($id, strlen('template:')); + } else if (strpos($id, $this->selfId)===0) { + $id = substr($id, strlen($this->selfId)+1); + } else { + return ''; + } + + return property_exists($this->templateData, $id) ? $this->templateData->{$id} : ''; + } + + + protected function loadContentFromDB() + { + if ( !$this->_application->canViewPage() ) + { + //$this->setAttribute('templateFileName', 'accessDenaied' ); + org_glizy_Session::set('glizy.loginUrl', org_glizy_helpers_Link::scriptUrl()); + org_glizy_helpers_Navigation::gotoUrl( org_glizy_helpers_Link::makeUrl( 'accessDenied' ) ); + } + + // if ($this->_user->backEndAccess && org_glizy_Request::get( 'draft', '' ) == '1') + // { + // $versionStatus = 'DRAFT'; + // } +// TODO gestire lo stato PUBLISHED E DRAFT + $contentProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.ContentProxy'); + $this->_content = $contentProxy->readContentFromMenu($this->_application->getPageId(), org_glizy_ObjectValues::get('org.glizy', 'languageId')); + } + + protected function loadTemplate() + { + if (__Config::get('glizycms.contents.templateEnabled')) { + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + $templateName = $templateProxy->getSelectedTemplate(); + $templatePath = $templateProxy->getTemplateRealpath(); + $this->templateData = $templateProxy->getDataForMenu($this->_application->getPageId()); + + // if is defined a custom XML file read and attach to component DOM + if (file_exists($templatePath.'/Template.xml')) + { + org_glizy_ObjectFactory::attachPageToComponent( + $this, + $this->_application, + 'Template', + $templateProxy->getTemplateRealpath(), + array(), + $this->selfId.'-', + false); + } + + // check if there is a templateFileName override + if (property_exists($this->templateData, 'templateFileName') && $this->templateData->templateFileName != 'default') { + $this->setAttribute('templateFileName', $this->templateData->templateFileName); + } + + $this->customTemplate = $templateProxy->getTemplateCustomClass(); + + if (is_object($this->customTemplate) && method_exists($this->customTemplate, 'process')) { + $this->customTemplate->process($this->_application, $this, $this->templateData); + } + } + } + + protected function loadSiteProperties() + { + $menu = $this->_application->getCurrentMenu(); + $siteProp = $this->_application->getSiteProperty(); + + $title = org_glizy_ObjectValues::get('org.glizy.og', 'title', $menu->title ); + $description = org_glizy_ObjectValues::get('org.glizy.og', 'description', $menu->description ); + $keywords = org_glizy_ObjectValues::get('org.glizy.og', 'keywords', $menu->keywords ); + + + $this->addOutputCode($title.' - '.$siteProp['title'], 'docTitle'); + $this->addOutputCode($title.' - '.$siteProp['title'], 'doctitle'); // NOTE: per compatibilità + $this->addOutputCode($title, 'metadata_title'); + $this->addOutputCode($description, 'metadata_description'); + $this->addOutputCode($keywords, 'metadata_keywords'); + $this->addOutputCode($siteProp['copyright'], 'copyright'); + $this->addOutputCode($siteProp['address'], 'address'); + + $slideShowSpeed = ((int)$siteProp['slideShow'] ? :5)*1000; + $this->addOutputCode( org_glizy_helpers_JS::JScode( 'if (typeof(Glizy)!=\'object\') Glizy = {}; Glizy.slideShowSpeed = '.$slideShowSpeed.';' ), 'head' ); + + $reg = __T( strlen( $menu->creationDate ) <= 10 || preg_match('/00:00:00|12:00:00 AM/', $menu->creationDate) ? 'GLZ_DATE_FORMAT' : 'GLZ_DATETIME_FORMAT' ); + $updateText= org_glizy_locale_Locale::get('MW_FOOTER', + glz_defaultDate2locale($reg, $menu->creationDate), + glz_defaultDate2locale($reg, $menu->modificationDate)); + $this->addOutputCode($updateText, 'docUpdate'); + } +} diff --git a/src/core/classes/org/glizycms/views/components/PagePicker.php b/src/core/classes/org/glizycms/views/components/PagePicker.php new file mode 100644 index 0000000..86b96d3 --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/PagePicker.php @@ -0,0 +1,43 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizycms_views_components_PagePicker extends org_glizy_components_Input +{ + function init() + { + // define the custom attributes + $this->defineAttribute('ajaxController', false, 'org.glizycms.contents.controllers.autocomplete.ajax.PagePicker', COMPONENT_TYPE_STRING); + $this->defineAttribute('type', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('protocol', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('makeLink', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('multiple', false, false, COMPONENT_TYPE_BOOLEAN); + parent::init(); + + } + + + function process() + { + if (!$this->_application->isAdmin()) { + $this->_content = $this->_parent->loadContent($this->getId()); + + $speakingUrlManager = $this->_application->retrieveProxy('org.glizycms.speakingUrl.Manager'); + $this->_content = $this->getAttribute('makeLink') ? + $speakingUrlManager->makeLink($this->_content) : + $speakingUrlManager->makeUrl($this->_content); + } else { + $this->setAttribute('data', ';type=CmsPagePicker;controllername='.$this->getAttribute('ajaxController'). + ';filtertype='.$this->getAttribute('type'). + ';multiple='.($this->getAttribute('multiple') ? 'true':'false'). + ';protocol='.$this->getAttribute('protocol') + , true); + } + } +} diff --git a/src/core/classes/org/glizycms/views/components/SearchFilters.php b/src/core/classes/org/glizycms/views/components/SearchFilters.php new file mode 100644 index 0000000..816ed75 --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/SearchFilters.php @@ -0,0 +1,31 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_views_components_SearchFilters extends org_glizy_components_SearchFilters +{ + function process() + { + $visible = $this->_parent->loadContent($this->getId())===1; + if ($visible) { + parent::process(); + } else { + $this->setAttribute('visible', false); + } + } + + public static function translateForMode_edit($node) { + $attributes = array(); + $attributes['id'] = $node->getAttribute('id'); + $attributes['label'] = $node->getAttribute('label'); + $attributes['data'] = ''; + $attributes['noChild'] = 'true'; + + return org_glizy_helpers_Html::renderTag('glz:Checkbox', $attributes); + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/views/components/SelectPage.php b/src/core/classes/org/glizycms/views/components/SelectPage.php new file mode 100755 index 0000000..10fa478 --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/SelectPage.php @@ -0,0 +1,113 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + + +class org_glizycms_views_components_SelectPage extends org_glizy_components_List +{ + function init() + { + // define the custom attributes + $this->defineAttribute('startFrom', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('maxDepth', false, false, COMPONENT_TYPE_STRING); + $this->defineAttribute('pageType', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('value', false, '', COMPONENT_TYPE_STRING); + + // call the superclass for validate the attributes + parent::init(); + } + + + function process() + { + $this->_content = $this->_parent->loadContent($this->getId()); + if (!$this->_content) { + $this->_content = $this->getAttribute('value'); + } + + $this->_items = array(); + if ($this->_application->isAdmin()) { + if (!is_null($this->getAttribute('emptyValue'))) + { + $this->_items[] = array( array('key' => '', 'value' => html_entity_decode( $this->getAttributeString('emptyValue') ), 'selected' => false, 'options' => '') ); + } + $this->getItems(); + } + } + + + + function getItems() + { + $menuProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.MenuProxy'); + $siteMap = $menuProxy->getSiteMap(); + + $siteMapIterator = &org_glizy_ObjectFactory::createObject('org.glizy.application.SiteMapIterator', $siteMap); + $menus = array(); + // $menus[] = array('-', '', 0); + $maxDepth = org_glizy_Config::get('ADM_SITE_MAX_DEPTH'); + $maxDepth = !is_null($maxDepth) && $this->getAttribute('maxDepth') ? $maxDepth : NULL; + $pageTypeFilter = $this->getAttribute('pageType'); + $startFrom = $this->getAttribute('startFrom'); + + if ( is_null( $startFrom ) ) + { + while (!$siteMapIterator->EOF) + { + $n = $siteMapIterator->getNodeArray(); + $siteMapIterator->moveNext(); + + if ((!is_null($maxDepth ) && $n['depth'] > $maxDepth) || + ($n['depth']==1 && !$this->_user->acl(__Config::get('SITEMAP_ID'), 'new') && $this->_content != 1 ) ) + { + continue; + } + $pad = str_repeat('. ', $n['depth']-1); + if ( !empty( $pageTypeFilter ) ) + { + if ( $pageTypeFilter != $n['pageType'] ) + { + continue; + } + $pad = ''; + } + $this->_items[] = array('key' => $n['id'], 'value' => $pad.(trim(strip_tags($n['title']))), 'selected' => $n['id']==$this->_content ? 1 : 0, 'options' => $n['pageType']); + } + } + else + { + $found = false; + $menuDepth = 0; + while (!$siteMapIterator->EOF) + { + $n = $siteMapIterator->getNodeArray(); + $siteMapIterator->moveNext(); + if ( $n['id'] == $startFrom ) + { + $found = true; + $menuDepth = $n['depth']; + continue; + } + + if ( $found ) + { + if ( $menuDepth == $n['depth']) break; + + if ( !empty( $pageTypeFilter ) ) + { + if ( $pageTypeFilter != $n['pageType'] ) + { + continue; + } + } + $this->_items[] = array('key' => $n['id'], 'value' => trim(strip_tags($n['title'])), 'selected' => $n['id']==$this->_content ? 1 : 0, 'options' => $n['pageType']); + } + } + } + } +} \ No newline at end of file diff --git a/src/core/classes/org/glizycms/views/components/SelectPageType.php b/src/core/classes/org/glizycms/views/components/SelectPageType.php new file mode 100644 index 0000000..3c03074 --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/SelectPageType.php @@ -0,0 +1,148 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_views_components_SelectPageType extends org_glizy_components_HtmlFormElement +{ + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('bindTo', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClassLabel', false, __Config::get('glizy.formElement.cssClassLabel'), COMPONENT_TYPE_STRING); + // $this->defineAttribute('defaultValue', false, NULL, COMPONENT_TYPE_STRING); + // $this->defineAttribute('emptyValue', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('value', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('modify', false, false, COMPONENT_TYPE_BOOLEAN); + // $this->defineAttribute('required', false, false, COMPONENT_TYPE_BOOLEAN); + // $this->defineAttribute('requiredMessage', false, NULL, COMPONENT_TYPE_STRING); + // $this->defineAttribute('size', false, '', COMPONENT_TYPE_STRING); + + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + $this->_content = $this->getAttribute('value'); + if (is_object($this->_content)) + { + // legge il contenuto da un dataProvider + $contentSource = &$this->getAttribute('value'); + $this->_content = $contentSource->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + else if (is_null($this->_content)) + { + // richiede il contenuto al padre + $this->_content = $this->_parent->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + } + + function render() + { +// TODO: controllo acl + $name = $this->getId(); + + if (!$this->_user->acl($this->_application->getPageId(),'new')) + { + $output = org_glizy_helpers_Html::hidden( $name , $this->_content, array( 'class' => $this->getAttribute( 'cssClass' ) ) ); + } + else + { + $pageTypes = array(); + if ($dh = @opendir(org_glizy_Paths::get('APPLICATION_TO_ADMIN_PAGETYPE'))) + { + // scan the pageType folder + while ($fileName = readdir($dh)) + { + // check if the item is a folder + if ($fileName!="." && + $fileName!=".." && + strpos($fileName, '.xml')!==false) + { + if ($fileName=='Common.xml') continue; + $pageTypes[] = preg_replace('/\.xml/i', '', $fileName); + } + } + closedir($dh); + glz_loadLocale(org_glizy_Paths::get('APPLICATION_TO_ADMIN_PAGETYPE')); + } + else + { + // can't open pageTypes folder + // show the error + new org_glizy_Exception(array('[%s] %s: %s', $this->getClassName(), GLZ_ERR_NO_PAGETYPE_FOLDER, org_glizy_Paths::get('APPLICATION_TO_ADMIN').'/pageTypes/')); + } + + $modules = org_glizy_Modules::getModules(); + foreach($modules as $moduleVO) { + if ($moduleVO->pageType) { + $pageTypes[] = $moduleVO->pageType; + } + } + + $output = '<option value=""></option>'; + $values = array(array($this->getAttribute('emptyValue'), '', 1, array(), 0)); + $modifyMode = $this->getAttribute('modify'); + foreach($pageTypes as $item) + { + $moduleVO = null; + foreach ($modules as $m) { + if ($m->pageType==$item) { + $moduleVO = $m; + break; + } + } + if ($moduleVO) { + if (!$moduleVO->show) { + continue; + } + + if ( $moduleVO->unique && (!$modifyMode || ($modifyMode && $item!=$this->_content))) { + $ar = &org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Menu'); + $result = $ar->find(array('menu_pageType' => $item)); + unset($ar); + if ($result) + { + continue; + } + } + } + $pageName = __T($item); + $output .= '<option value="'.$item.'"'.($item==$this->_content ? ' selected':'').'>'.__T($item).'</option>'; + } + + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['name'] = $this->getOriginalId(); + $attributes['disabled'] = $this->getAttribute('disabled') ? 'disabled' : ''; + $attributes['class'] = $this->getAttribute('required') ? 'required' : ''; + $attributes['class'] .= $this->getAttribute( 'cssClass' ) != '' ? ( $attributes['class'] != '' ? ' ' : '' ).$this->getAttribute( 'cssClass' ) : ''; + + $output = '<select '.$this->_renderAttributes($attributes).'>'.$output.'</select>'; + + $cssClassLabel = $this->getAttribute( 'cssClassLabel' ); + $cssClassLabel .= ( $cssClassLabel ? ' ' : '' ).($this->getAttribute('required') ? 'required' : ''); + if ($this->getAttribute('wrapLabel')) { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), true, $output, array('class' => $cssClassLabel ), false); + $output = ''; + } else { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), false, '', array('class' => $cssClassLabel ), false); + } + $this->addOutputCode($this->applyItemTemplate($label, $output)); + } + } +} diff --git a/src/core/classes/org/glizycms/views/components/SelectPageTypeNew.php b/src/core/classes/org/glizycms/views/components/SelectPageTypeNew.php new file mode 100644 index 0000000..5777a96 --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/SelectPageTypeNew.php @@ -0,0 +1,175 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_views_components_SelectPageTypeNew extends org_glizy_components_HtmlFormElement +{ + protected $items = array(); + /** + * Init + * + * @return void + * @access public + */ + function init() + { + // define the custom attributes + $this->defineAttribute('bindTo', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClass', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('cssClassLabel', false, __Config::get('glizy.formElement.cssClassLabel'), COMPONENT_TYPE_STRING); + $this->defineAttribute('label', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('value', false, NULL, COMPONENT_TYPE_STRING); + $this->defineAttribute('showAllPageTypes', false, __Config::get('glizycms.content.showAllPageTypes'), COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('linked', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('onlyWithParent', false, '', COMPONENT_TYPE_STRING); + $this->defineAttribute('hide', false, false, COMPONENT_TYPE_BOOLEAN); + + // call the superclass for validate the attributes + parent::init(); + } + + function process() + { + $this->_content = $this->getAttribute('value'); + if (is_object($this->_content)) + { + // legge il contenuto da un dataProvider + $contentSource = &$this->getAttribute('value'); + $this->_content = $contentSource->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + else if (is_null($this->_content)) + { + // richiede il contenuto al padre + $this->_content = $this->_parent->loadContent($this->getId(), $this->getAttribute('bindTo')); + } + + $this->readFromXml(); + $this->readFromFolder(); + $this->readFromModules(); + + org_glizy_helpers_Array::arrayMultisortByLabel($this->items, 'label'); + } + + function render() + { + // TODO: controllo acl + $name = $this->getId(); + + if (!$this->_user->acl($this->_application->getPageId(),'new') || $this->getAttribute('hide')) + { + $output = org_glizy_helpers_Html::hidden( $name , $this->_content, array( 'class' => $this->getAttribute( 'cssClass' ) ) ); + $this->addOutputCode($output); + } + else + { + $attributes = array(); + $attributes['id'] = $this->getId(); + $attributes['name'] = $this->getOriginalId(); + $attributes['disabled'] = $this->getAttribute('disabled') ? 'disabled' : ''; + $attributes['data-type'] = $this->getAttribute('data-type') ? $this->getAttribute('data-type') : 'selectpagetype'; + $attributes['data-linked'] = $this->getAttribute('linked') ? $this->getAttribute('linked') : ''; + $attributes['data-onlywithparent'] = $this->getAttribute('onlyWithParent') ? $this->getAttribute('onlyWithParent') : ''; + $attributes['class'] = $this->getAttribute('required') ? 'required' : ''; + $attributes['class'] .= $this->getAttribute( 'cssClass' ) != '' ? ( $attributes['class'] != '' ? ' ' : '' ).$this->getAttribute( 'cssClass' ) : ''; + $attributes['class'] .= ' hidden'; + + $output = '<input '.$this->_renderAttributes($attributes).'/>'; + $output .= '<ul class="pageTypeSelect">'; + + foreach ($this->items as $v) { + $output .= '<li>'; + $output .= '<a class="'.$v['cssClass'].'" data-type="'.$v['type'].'" data-acceptparent="'.@$v['acceptParent'].'">'.$v['label'].'</a>'; + $output .= '</li>'; + } + $output .= '</ul>'; + + $cssClassLabel = $this->getAttribute( 'cssClassLabel' ); + $cssClassLabel .= ( $cssClassLabel ? ' ' : '' ).($this->getAttribute('required') ? 'required' : ''); + + if ($this->getAttribute('wrapLabel')) { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), true, $output, array('class' => $cssClassLabel ), false); + $output = ''; + } else { + $label = org_glizy_helpers_Html::label($this->getAttributeString('label'), $this->getId(), false, '', array('class' => $cssClassLabel ), false); + } + + $this->addOutputCode($this->applyItemTemplate($label, $output)); + } + } + + + protected function readFromXml() + { + $pageTypeService = org_glizy_ObjectFactory::createObject('org.glizycms.contents.services.PageTypeService'); + $pageTypes = $pageTypeService->getAllPageTypes(); + + foreach ($pageTypes as $pageTypeName => $pageType) { + if (!isset($this->items[$pageTypeName])) { + if ($pageType['unique'] && $pageTypeName != $this->_content) { + // TODO migliorare + $ar = &org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Menu'); + $result = $ar->find(array('menu_pageType' => $pageTypeName)); + unset($ar); + if ($result) { + continue; + } + } + + $this->items[$pageTypeName] = array('label' => $pageType['label'], + 'type' => $pageTypeName, + 'cssClass' => $pageType['class'], + 'acceptParent' => $pageType['acceptParent'], + ); + } + } + } + + protected function readFromFolder() + { + if ($this->getAttribute('showAllPageTypes')) { + glz_loadLocale(org_glizy_Paths::get('APPLICATION_TO_ADMIN_PAGETYPE')); + foreach (glob(org_glizy_Paths::get('APPLICATION_TO_ADMIN_PAGETYPE').'*.{xml}', GLOB_BRACE) as $file) { + $pathInfo = pathinfo($file); + if ($pathInfo['basename']=='Common.xml' || isset($this->items[$pathInfo['filename']])) continue; + $this->items[$pathInfo['filename']] = array('label' => __T($pathInfo['filename']), + 'type' => $pathInfo['filename'], + 'cssClass' => 'button-generic'); + } + } + } + + protected function readFromModules() + { + if ($this->getAttribute('showAllPageTypes')) { + $modules = org_glizy_Modules::getModules(); + foreach($modules as $moduleVO) { + $pageType = $moduleVO->pageType; + if ($pageType) { + if (isset($this->items[$pageType])) continue; + if (!$moduleVO->show) { + continue; + } + + if ($moduleVO->unique && $pageType != $this->_content) { + // TODO migliorare + $ar = &org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Menu'); + $result = $ar->find(array('menu_pageType' => $pageType)); + unset($ar); + if ($result) { + continue; + } + } + + $this->items[$pageType] = array('label' => __T($pageType), + 'type' => $pageType, + 'cssClass' => 'button-generic'); + } + } + } + } +} diff --git a/src/core/classes/org/glizycms/views/components/VisualSearch.php b/src/core/classes/org/glizycms/views/components/VisualSearch.php new file mode 100644 index 0000000..1a0aaec --- /dev/null +++ b/src/core/classes/org/glizycms/views/components/VisualSearch.php @@ -0,0 +1,244 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +class org_glizycms_views_components_VisualSearch extends org_glizy_components_Form +{ + private $sessionEx; + private $criteria = array(); + private $filters = array(); + + function init() + { + $this->defineAttribute('addValidationJs', false, false, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('rememberValues', false, true, COMPONENT_TYPE_BOOLEAN); + $this->defineAttribute('rememberMode', false, 'persistent', COMPONENT_TYPE_STRING); + + parent::init(); + } + + + function process() + { + $this->sessionEx = new org_glizy_SessionEx($this->getId()); + $this->_command = org_glizy_Request::get($this->getId().'_command'); + $this->rememberMode = $this->getAttribute( 'rememberMode' ) == 'persistent' ? GLZ_SESSION_EX_PERSISTENT : GLZ_SESSION_EX_VOLATILE; + if ($this->_command=='RESET') { + $this->sessionEx->remove('filters_filters'); + } else { + $name = $this->getId().'_filters'; + $defValue = ''; + if ( $this->getAttribute( 'rememberValues') ) { + $defValue = $this->sessionEx->get($name); + } + + $this->filters = __Request::get($name, $defValue); + $this->sessionEx->set($name, $this->filters, $this->rememberMode); + $this->filters = json_decode($this->filters); + } + + if (!$this->filters) { + $this->filters = array(); + } + + parent::process(); + } + + + function render_html_onStart() + { + parent::render_html_onStart(); + + $folderPath = __Paths::get('CORE').'classes/org/glizycms/js/visualsearch/'; + $output = <<< EOD +<script src="{$folderPath}dependencies.js" type="text/javascript"></script> +<script src="{$folderPath}visualsearch.js" type="text/javascript"></script> +<!--[if (!IE)|(gte IE 8)]><!--> +<link href="{$folderPath}visualsearch-datauri.css" media="screen" rel="stylesheet" type="text/css" /> +<!--<![endif]--> +<!--[if lte IE 7]><!--> + <link href="{$folderPath}visualsearch.css" media="screen" rel="stylesheet" type="text/css" /> +<!--<![endif]--> +EOD; + $this->addOutputCode($output, 'head'); + + $id = $this->getId(); + $query = ''; + $callback = array(); + $valuesMapping = array(); + $valuesMappingRev = array(); + $valueMatches = ''; + foreach($this->criteria as $v) { + $callback[] = array('label' => $v->label, 'id' => $v->id); + + if ('facet'==$v->type) { + + $it = org_glizy_objectFactory::createModelIterator($this->getAttribute('model')); + $it->where($v->id, '', '<>') + ->orderBy($v->id); + + $foundValues = array(); + foreach($it as $ar) { + if (is_array($ar->{$v->id})) { + foreach ($ar->{$v->id} as $value) { + if (!in_array($value, $foundValues)) $foundValues[] = $value; + } + } else { + if (!in_array($ar->{$v->id}, $foundValues)) $foundValues[] = $ar->{$v->id}; + } + } + $valueMatches .= 'case "'.$v->label.'":callback('.json_encode($foundValues).');break;'; + } else if ('static'==$v->type) { + $foundValues = array(); + $valuesMapping[$v->label] = array(); + $values = json_decode($v->values); + foreach($values as $kk=>$vv) { + $label = __T($vv); + $foundValues[] = $label; + $valuesMapping[$v->label][$label] = $kk; + $valuesMappingRev[$v->label][$kk] = $label; + } + + $valueMatches .= 'case "'.$v->label.'":callback('.json_encode($foundValues).');break;'; + } else if ('dictionary'==$v->type) { + $dataProvider = $this->getComponentById($v->dataProvider); + if (!is_null($dataProvider)) + { + $foundValues = array(); + $valuesMapping[$v->label] = array(); + $values = $dataProvider->getItems(); + foreach($values as $vv) { + $foundValues[] = $vv['value']; + $valuesMapping[$v->label][$vv['value']] = $vv['key']; + $valuesMappingRev[$v->label][$vv['key']] = $vv['value']; + } + $valueMatches .= 'case "'.$v->label.'":callback('.json_encode($foundValues).');break;'; + } + } + } + + foreach($this->filters as $item) { + foreach($item as $k=>$v) { + if (isset($valuesMappingRev[$k]) && isset($valuesMappingRev[$k][$v])) { + $v = $valuesMappingRev[$k][$v]; + } + $query .= '"'.$k.'": "'.addslashes($v).'" '; + } + } + + $callback = json_encode($callback); + $valuesMapping = json_encode($valuesMapping); + + $output = <<<EOD +<input name="{$id}_filters" id="{$id}_filters" type="hidden" value=""> +<div id="{$id}_visualsearch"></div> +<script type="text/javascript" charset="utf-8"> + + $(document).ready(function() { + var valuesMapping = $valuesMapping; + var visualSearch = VS.init({ + container : $('#{$id}_visualsearch'), + query : '$query', + remainder: '', + callbacks : { + facetMatches : function(callback) { + callback($callback) + }, + valueMatches : function(facet, searchTerm, callback) { + switch (facet) { + $valueMatches + } + } + } + }); + + $('#{$id}').submit(function(){ + var e = jQuery.Event("keydown"); + e.which = 13 + _.each(visualSearch.searchBox.inputViews, function(inputView, i) { + inputView.box.trigger("focus"); + inputView.box.trigger(e); + }); + var values = []; + _.each(visualSearch.searchQuery.facets(), function(el, i){ + _.each(el, function(el2, i2){ + if (valuesMapping[i2]) { + var temp = {}; + temp[i2] = valuesMapping[i2][el2] + values.push(temp); + } else { + values.push(el); + } + }); + }); + + $('#{$id}_filters').val(JSON.stringify(values)); + return true; + }) + }); +</script> +EOD; + + $this->addOutputCode($output); + } + + + public function addCriteria($id, $label, $type, $values, $dataProvider) + { + if (preg_match("/\{i18n\:.*\}/i", $label)) { + $code = preg_replace("/\{i18n\:(.*)\}/i", "$1", $label); + $label = org_glizy_locale_Locale::getPlain($code); + } + + $temp = new StdClass(); + $temp->id = $id; + $temp->label = $label; + $temp->type = $type; + $temp->values = $values; + $temp->dataProvider = $dataProvider; + $this->criteria[$temp->label] = $temp; + } + + function getFilters() + { + $tempFilters = array(); + foreach($this->filters as $item) { + foreach($item as $k=>$v) { + $tempFilters[$this->criteria[$k]->id] = $this->criteria[$k]->type == 'facet' ? + array('value' => '%"'.$v.'"%', 'condition' => 'LIKE') : + $v; + } + } + + return $tempFilters; + } + + public static function compile($compiler, &$node, &$registredNameSpaces, &$counter, $parent='NULL', $idPrefix, $componentClassInfo, $componentId) + { + $compiler->compile_baseTag( $node, $registredNameSpaces, $counter, $parent, $idPrefix, $componentClassInfo, $componentId ); + + $oldcounter = $counter; + foreach ($node->childNodes as $n ) { + if ( $n->nodeName == "cms:VisualSearchItem" ) { + $id = $n->hasAttribute('id') ? $n->getAttribute('id') : ''; + $label = $n->hasAttribute('label') ? $n->getAttribute('label') : ''; + $type = $n->hasAttribute('type') ? $n->getAttribute('type') : 'text'; + $values = $n->hasAttribute('values') ? $n->getAttribute('values') : ''; + $dataProvider = $n->hasAttribute('dataProvider') ? $n->getAttribute('dataProvider') : ''; + if ( $id && $label ) { + $compiler->_classSource .= '$n'.$counter.'->addCriteria( "'.$id.'", "'.$label.'", "'.$type.'", "'.addslashes($values).'", "'.$dataProvider.'" );'; + } + continue; + } + + $counter++; + $compiler->_compileXml($n, $registredNameSpaces, $counter, '$n'.$oldcounter, $idPrefix); + } + return false; + } +} diff --git a/src/core/composer.json b/src/core/composer.json new file mode 100644 index 0000000..4258753 --- /dev/null +++ b/src/core/composer.json @@ -0,0 +1,19 @@ +{ + "_comment": "Aggiunte tutte le librerie del core divise fra produzione e sviluppo", + "require": { + "tedivm/jshrink": "1.0.1", + "doctrine/dbal": "2.3.0", + "leafo/lessphp": "0.4.0", + "phptal/phptal": "1.3.0", + "james-heinrich/phpthumb": "1.7.13", + "phpmailer/phpmailer": "5.2.9", + "jdorn/sql-formatter": "1.2.17", + "twig/twig": "1.18.1", + "predis/predis": "1.0.1", + "filp/whoops": "1.1.5" + }, + "require-dev": { + "maximebf/debugbar": "1.*", + "ukko/phpredis-phpdoc": "2.2.*@dev" + } +} \ No newline at end of file diff --git a/src/core/composer.lock b/src/core/composer.lock new file mode 100644 index 0000000..3b19f84 --- /dev/null +++ b/src/core/composer.lock @@ -0,0 +1,811 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "b027d6472fefff381a8ee1f68f6d32dc", + "packages": [ + { + "name": "doctrine/common", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "d1c7d4334e38cad603a5c863d4c7b91bb04ec6b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/d1c7d4334e38cad603a5c863d4c7b91bb04ec6b2", + "reference": "d1c7d4334e38cad603a5c863d4c7b91bb04ec6b2", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com", + "homepage": "http://www.jwage.com/", + "role": "Creator" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com", + "homepage": "http://www.instaclick.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com", + "homepage": "https://github.com/schmittjoh", + "role": "Developer of wrapped JMSSerializerBundle" + } + ], + "description": "Common Library for Doctrine projects", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "collections", + "eventmanager", + "persistence", + "spl" + ], + "time": "2012-09-20 05:55:18" + }, + { + "name": "doctrine/dbal", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/dbal.git", + "reference": "30dc433ea08f4863479700492bdb70c3b06440bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/30dc433ea08f4863479700492bdb70c3b06440bd", + "reference": "30dc433ea08f4863479700492bdb70c3b06440bd", + "shasum": "" + }, + "require": { + "doctrine/common": "2.3.*", + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\DBAL": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com", + "homepage": "http://www.jwage.com/", + "role": "Creator" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com", + "homepage": "http://www.instaclick.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + } + ], + "description": "Database Abstraction Layer", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "database", + "dbal", + "persistence", + "queryobject" + ], + "time": "2012-09-20 05:56:37" + }, + { + "name": "filp/whoops", + "version": "1.1.5", + "source": { + "type": "git", + "url": "https://github.com/filp/whoops.git", + "reference": "c982fe62c44798c433229cb0425c61b487cc1883" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/filp/whoops/zipball/c982fe62c44798c433229cb0425c61b487cc1883", + "reference": "c982fe62c44798c433229cb0425c61b487cc1883", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "mockery/mockery": "0.9.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, + "autoload": { + "psr-0": { + "Whoops": "src/" + }, + "classmap": [ + "src/deprecated" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" + } + ], + "description": "php error handling for cool kids", + "homepage": "https://github.com/filp/whoops", + "keywords": [ + "error", + "exception", + "handling", + "library", + "silex-provider", + "whoops", + "zf2" + ], + "time": "2015-03-30 15:26:59" + }, + { + "name": "james-heinrich/phpthumb", + "version": "v1.7.13", + "source": { + "type": "git", + "url": "https://github.com/JamesHeinrich/phpThumb.git", + "reference": "6a582647f352706432898e332d196c3c84a982d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/JamesHeinrich/phpThumb/zipball/6a582647f352706432898e332d196c3c84a982d9", + "reference": "6a582647f352706432898e332d196c3c84a982d9", + "shasum": "" + }, + "require": { + "php": ">=4.3.3" + }, + "suggest": { + "ext-gd": "PHP GD library", + "ext-imagick": "PHP ImageMagick" + }, + "type": "library", + "autoload": { + "files": [ + "phpthumb.class.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL" + ], + "authors": [ + { + "name": "James Heinric", + "email": "info@silisoftware.com", + "homepage": "http://www.silisoftware.com/", + "role": "Developer" + } + ], + "description": "The PHP thumbnail generator", + "homepage": "http://phpthumb.sourceforge.net/", + "keywords": [ + "ImageMagick", + "gd", + "image", + "magic", + "thumb", + "thumbnail" + ], + "time": "2014-06-26 14:09:03" + }, + { + "name": "jdorn/sql-formatter", + "version": "v1.2.17", + "source": { + "type": "git", + "url": "https://github.com/jdorn/sql-formatter.git", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jdorn/sql-formatter/zipball/64990d96e0959dff8e059dfcdc1af130728d92bc", + "reference": "64990d96e0959dff8e059dfcdc1af130728d92bc", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "classmap": [ + "lib" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jeremy Dorn", + "email": "jeremy@jeremydorn.com", + "homepage": "http://jeremydorn.com/" + } + ], + "description": "a PHP SQL highlighting library", + "homepage": "https://github.com/jdorn/sql-formatter/", + "keywords": [ + "highlight", + "sql" + ], + "time": "2014-01-12 16:20:24" + }, + { + "name": "leafo/lessphp", + "version": "v0.4.0", + "source": { + "type": "git", + "url": "https://github.com/leafo/lessphp.git", + "reference": "51f3f06f0fe78a722dabfd14578444bdd078d9de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/leafo/lessphp/zipball/51f3f06f0fe78a722dabfd14578444bdd078d9de", + "reference": "51f3f06f0fe78a722dabfd14578444bdd078d9de", + "shasum": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.3-dev" + } + }, + "autoload": { + "classmap": [ + "lessc.inc.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT", + "GPL-3.0" + ], + "authors": [ + { + "name": "Leaf Corcoran", + "email": "leafot@gmail.com", + "homepage": "http://leafo.net" + } + ], + "description": "lessphp is a compiler for LESS written in PHP.", + "homepage": "http://leafo.net/lessphp/", + "time": "2013-08-09 17:09:19" + }, + { + "name": "phpmailer/phpmailer", + "version": "v5.2.9", + "source": { + "type": "git", + "url": "https://github.com/PHPMailer/PHPMailer.git", + "reference": "73b61679809615850706f1dbf88e6df2ddc05745" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/73b61679809615850706f1dbf88e6df2ddc05745", + "reference": "73b61679809615850706f1dbf88e6df2ddc05745", + "shasum": "" + }, + "require": { + "php": ">=5.0.0" + }, + "require-dev": { + "phpdocumentor/phpdocumentor": "*", + "phpunit/phpunit": "4.1.*" + }, + "type": "library", + "autoload": { + "classmap": [ + "class.phpmailer.php", + "class.pop3.php", + "class.smtp.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "Jim Jagielski", + "email": "jimjag@gmail.com" + }, + { + "name": "Marcus Bointon", + "email": "phpmailer@synchromedia.co.uk" + }, + { + "name": "Andy Prevost", + "email": "codeworxtech@users.sourceforge.net" + }, + { + "name": "Brent R. Matzelle" + } + ], + "description": "PHPMailer is a full-featured email creation and transfer class for PHP", + "time": "2014-09-26 18:33:30" + }, + { + "name": "phptal/phptal", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/pornel/PHPTAL.git", + "reference": "090948f2c4756a068530fe648743b1849d1c51cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pornel/PHPTAL/zipball/090948f2c4756a068530fe648743b1849d1c51cd", + "reference": "090948f2c4756a068530fe648743b1849d1c51cd", + "shasum": "" + }, + "require": { + "php": ">=5.1.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "PHPTAL": "classes/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1+" + ], + "authors": [ + { + "name": "Laurent Bédubourg", + "email": "lbedubourg@motion-twin.com", + "homepage": "http://labe.me" + }, + { + "name": "Kornel LesiÅ„ski", + "email": "kornel@geekhood.net", + "homepage": "http://pornel.net/" + } + ], + "description": "PHPTAL is a templating engine for PHP5 that implements Zope Page Templates syntax", + "homepage": "http://phptal.org/", + "keywords": [ + "phptal", + "template engine", + "zope" + ], + "time": "2014-03-15 19:29:30" + }, + { + "name": "predis/predis", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/nrk/predis.git", + "reference": "7a170b3d8123c556597b4fbdb88631f99de180c2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nrk/predis/zipball/7a170b3d8123c556597b4fbdb88631f99de180c2", + "reference": "7a170b3d8123c556597b4fbdb88631f99de180c2", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "ext-curl": "Allows access to Webdis when paired with phpiredis", + "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" + }, + "type": "library", + "autoload": { + "psr-4": { + "Predis\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniele Alessandri", + "email": "suppakilla@gmail.com", + "homepage": "http://clorophilla.net" + } + ], + "description": "Flexible and feature-complete PHP client library for Redis", + "homepage": "http://github.com/nrk/predis", + "keywords": [ + "nosql", + "predis", + "redis" + ], + "time": "2015-01-02 12:51:34" + }, + { + "name": "tedivm/jshrink", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/tedious/JShrink.git", + "reference": "7575d9d96f113bc7c1c28ec8231ee086751a9078" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/tedious/JShrink/zipball/7575d9d96f113bc7c1c28ec8231ee086751a9078", + "reference": "7575d9d96f113bc7c1c28ec8231ee086751a9078", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "fabpot/php-cs-fixer": "0.4.0", + "phpunit/phpunit": "4.0.*", + "satooshi/php-coveralls": "dev-master" + }, + "type": "library", + "autoload": { + "psr-0": { + "JShrink": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Robert Hafner", + "email": "tedivm@tedivm.com" + } + ], + "description": "Javascript Minifier built in PHP", + "homepage": "http://github.com/tedious/JShrink", + "keywords": [ + "javascript", + "minifier" + ], + "time": "2014-11-11 03:54:14" + }, + { + "name": "twig/twig", + "version": "v1.18.1", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/9f70492f44398e276d1b81c1b43adfe6751c7b7f", + "reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f", + "shasum": "" + }, + "require": { + "php": ">=5.2.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.18-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + }, + { + "name": "Twig Team", + "homepage": "http://twig.sensiolabs.org/contributors", + "role": "Contributors" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "http://twig.sensiolabs.org", + "keywords": [ + "templating" + ], + "time": "2015-04-19 08:30:27" + } + ], + "packages-dev": [ + { + "name": "maximebf/debugbar", + "version": "v1.10.4", + "source": { + "type": "git", + "url": "https://github.com/maximebf/php-debugbar.git", + "reference": "7b2006e6e095126b5a061ec33fca3d90ea8a8219" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/7b2006e6e095126b5a061ec33fca3d90ea8a8219", + "reference": "7b2006e6e095126b5a061ec33fca3d90ea8a8219", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/log": "~1.0", + "symfony/var-dumper": "~2.6" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "kriswallsmith/assetic": "The best way to manage assets", + "monolog/monolog": "Log using Monolog", + "predis/predis": "Redis storage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-0": { + "DebugBar": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maxime Bouroumeau-Fuseau", + "email": "maxime.bouroumeau@gmail.com", + "homepage": "http://maximebf.com" + } + ], + "description": "Debug bar in the browser for php application", + "homepage": "https://github.com/maximebf/php-debugbar", + "keywords": [ + "debug" + ], + "time": "2015-02-05 07:51:20" + }, + { + "name": "psr/log", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b", + "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-0": { + "Psr\\Log\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2012-12-21 11:40:51" + }, + { + "name": "symfony/var-dumper", + "version": "v2.7.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "e8903ebba5eb019f5886ffce739ea9e3b7519579" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e8903ebba5eb019f5886ffce739ea9e3b7519579", + "reference": "e8903ebba5eb019f5886ffce739ea9e3b7519579", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/phpunit-bridge": "~2.7" + }, + "suggest": { + "ext-symfony_debug": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2015-07-28 15:18:12" + }, + { + "name": "ukko/phpredis-phpdoc", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/ukko/phpredis-phpdoc.git", + "reference": "dd9f75942bccba922d473fd11dd792be67f07504" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ukko/phpredis-phpdoc/zipball/dd9f75942bccba922d473fd11dd792be67f07504", + "reference": "dd9f75942bccba922d473fd11dd792be67f07504", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2.x-dev" + } + }, + "autoload": { + "psr-0": { + "phpredis-phpdoc": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Max Kamashev", + "email": "max.kamashev@gmail.com", + "homepage": "http://uk0.us/", + "role": "Developer" + } + ], + "description": "@phpdoc extension phpredis for IDE autocomplete", + "homepage": "https://github.com/ukko/phpredis-phpdoc", + "keywords": [ + "helper", + "phpredis", + "redis" + ], + "time": "2015-07-20 07:02:01" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "ukko/phpredis-phpdoc": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/src/core/core.inc.php b/src/core/core.inc.php new file mode 100755 index 0000000..c006ff1 --- /dev/null +++ b/src/core/core.inc.php @@ -0,0 +1,869 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +// ini_set( "display_errors", "on" ); +// ini_set( "display_startup_errors", "on" ); + +define('GLZ_CORE_VERSION', '1.5.0 alpha'); + + +// directory contente tutti i file del core +define('GLZ_LOADED', true); +define('GLZ_CORE_DIR', realpath(dirname(__FILE__)).'/'); + +// directory contente tutti i file del core +define('GLZ_CLASSES_DIR', realpath(dirname(__FILE__)).'/classes/'); + +// directory contentente le librerie +define('GLZ_LIBS_DIR', realpath(dirname(__FILE__)).'/libs/'); + +define('GLZ_COMPILER_NEWLINE', ";\n"); +define('GLZ_COMPILER_NEWLINE2', "\n"); + +define('GLZ_SCRIPNAME', $_SERVER['PHP_SELF']); +define('GLZ_ERR_EMPTY_APP_PATH', 'The application path can\'t be empty'); + +// eventi +define('GLZ_EVT_BEFORE_CREATE_PAGE', 'beforeCreatePage'); +define('GLZ_EVT_START_PROCESS', 'onProcessStart'); +define('GLZ_EVT_END_PROCESS', 'onProcessEnd'); +define('GLZ_EVT_START_RENDER', 'onRenderStart'); +define('GLZ_EVT_END_RENDER', 'onRenderEnd'); +define('GLZ_EVT_CALL_CONTROLLER', 'onCallController'); +define('GLZ_EVT_START_COMPILE_ROUTING', 'startCompileRouting'); +define('GLZ_EVT_LISTENER_COMPILE_ROUTING', 'listenerCompileRouting'); +define('GLZ_EVT_USERLOGIN', 'login'); +define('GLZ_EVT_USERLOGOUT', 'logout'); +define('GLZ_EVT_AR_UPDATE', 'update'); +define('GLZ_EVT_AR_UPDATE_PRE', 'preUpdate'); +define('GLZ_EVT_AR_INSERT', 'insert'); +define('GLZ_EVT_AR_INSERT_PRE', 'preInsert'); +define('GLZ_EVT_AR_DELETE', 'delete'); +define('GLZ_EVT_SITEMAP_UPDATE', 'siteMapUpdate'); +define('GLZ_EVT_BREADCRUMBS_UPDATE', 'onBreadcrumbsUpdate'); +define('GLZ_EVT_PAGETITLE_UPDATE', 'onPageTitleUpdate'); + +if (!defined('GLZ_LOG_EVENT')) define('GLZ_LOG_EVENT', 'logByEvent'); +if (!defined('GLZ_LOG_DEBUG')) define('GLZ_LOG_DEBUG', 1); +if (!defined('GLZ_LOG_SYSTEM')) define('GLZ_LOG_SYSTEM', 2); +if (!defined('GLZ_LOG_INFO')) define('GLZ_LOG_INFO', 4); +if (!defined('GLZ_LOG_WARNING')) define('GLZ_LOG_WARNING', 8); +if (!defined('GLZ_LOG_ERROR')) define('GLZ_LOG_ERROR', 16); +if (!defined('GLZ_LOG_FATAL')) define('GLZ_LOG_FATAL', 32); +if (!defined('GLZ_LOG_ALL')) define('GLZ_LOG_ALL', 255); + +if (!defined('E_STRICT')) define('E_STRICT', 2048); +if (!defined('E_DEPRECATED')) define('E_DEPRECATED', 8192); + + +date_default_timezone_set( 'Europe/Rome' ); + +set_include_path('./' . PATH_SEPARATOR . get_include_path()); + +$errorlevel=error_reporting(); +error_reporting( $errorlevel & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT ); + +if (!defined('GLZ_TESTS')) { + // set_error_handler('glz_exception_handler', E_ALL); + // register_shutdown_function('shutdownFunction'); + GlizyErrorHandler::register(); + +} + +if ( phpversion() < 5) +{ + glz_import('org.glizy.Exception'); + org_glizy_Exception::show( 500, "GLIZY work only with php 5", "", ""); +} + +// import all the libraries +glz_require_once_dir(GLZ_LIBS_DIR); + +// import the main Object class +glz_import('org.glizy.GlizyObject'); + +// import the needed classes for start-up a application +glz_import('org.glizy.locale.Locale'); +glz_import('org.glizy.*'); +glz_import('org.glizy.helpers.Link'); + +GlizyClassLoader::register(); + +function glz_defineBaseHost() +{ + if ( !defined( 'GLZ_HOST' ) ) + { + $host = __Config::get( 'GLZ_HOST', '' ); + if ( !$host ) + { + $protocol = @$_SERVER["HTTPS"] === true || @$_SERVER["HTTPS"] === 'on' ? 'https://' : 'http://'; + $host = $protocol.$_SERVER['HTTP_HOST'].$_SERVER["PHP_SELF"]; + $host = substr( $host, 0, strrpos( $host, '/' ) ); + } + define('GLZ_HOST', $host); + } else { + $host = GLZ_HOST; + } + + if ( !defined( 'GLZ_HOST_ROOT' ) ) + { + define('GLZ_HOST_ROOT', str_replace( '/admin', '', $host ) ); + } +} + +/** + * @param $dir + * @param string $default + */ +function glz_require_once_dir($dir, $default='') +{ + $dir = rtrim($dir, "*"); + if ($default!='') + { + if (!is_array($default)) + { + $default = array($default); + } + + foreach ($default as $value) + { + $retArray[] = "$dir/$value"; + require_once("$dir/$value"); + } + } + + if ($dir_handle = @opendir($dir)) + { + while ($file_name = readdir($dir_handle)) + { + if ($file_name!="." && + $file_name!=".." && + $file_name!=$default && + !is_dir("$dir/$file_name") && + substr($file_name, -3)=='php' && + strpos($file_name, '._') === false ) + { + require_once("$dir/$file_name"); + } + } + closedir($dir_handle); + } + else + { + echo "Could not open directory $dir"; + } +} + + +/** + * @param $classPath + * @param array $classToReadFirst + * @param string $path + * + * @return bool + */ +function glz_import($classPath, $classToReadFirst=array(), $path='') +{ + static $loadedClass = array(); + $classPath = str_replace('.', '/', $classPath); + $classPath = rtrim($classPath, '*'); + $origClassPath = $classPath; + + if (in_array($classPath, $loadedClass)) return true; + + if (empty($path)) + { + if (class_exists('org_glizy_Paths') && !is_null(org_glizy_Paths::get('APPLICATION_CLASSES'))) + { + $path = NULL; + $searchPath = org_glizy_Paths::getClassSearchPath(); + foreach($searchPath as $p) + { + $path = $p.$classPath; + if (file_exists($p.$classPath) || file_exists($p.$classPath.'.php')) + { + $path = $p; + break; + } + } + + if (is_null($path)) + { + // TODO + // visualizzare errore + echo "errore"; + } + } + else + { + $path = realpath(dirname(__FILE__)).'/classes/'; + } + } + + if (substr($classPath, -1, 1)=='/' || $classPath=='') + { + // import all file in the folder + $classPath = rtrim($classPath, '/'); + glz_require_once_dir($path.$classPath, $classToReadFirst); + glz_loadLocale( $classPath ); + } + else + { + // import a single file + if (file_exists($path.$classPath.'.php')) + { + require_once($path.$classPath.'.php'); + } + else + { + return false; + } + } + + $loadedClass[] = $origClassPath; + return true; +} + +/** + * @param $classPath + */ +function glz_loadLocale( $classPath ) +{ + if (class_exists('org_glizy_ObjectValues')) + { + $classPath = str_replace('.', '/', $classPath); + $classPath = rtrim($classPath, '*'); + /** @var org_glizy_application_Application $application */ + $application = &org_glizy_ObjectValues::get('org.glizy', 'application'); + if (is_object($application) ) + { + $searchPath = org_glizy_Paths::getClassSearchPath(); + foreach($searchPath as $p) + { + $path = $p.$classPath.'/locale/'.$application->getLanguage().'.php'; + $pathEn = $p.$classPath.'/locale/en.php'; + if ( file_exists($path) ) + { + require_once( $path ); + break; + } + else if ( file_exists($pathEn) ) + { + require_once( $pathEn ); + break; + } + } + } + } +} + +/** + * @param $classPath + * + * @return null|string + */ +function glz_findClassPath($classPath) +{ + if (!class_exists('org_glizy_Paths')) return NULL; + $classPath = str_replace(array('.', '*'), '/', $classPath); + + $path = NULL; + $searchPath = org_glizy_Paths::getClassSearchPath(); + foreach($searchPath as $p) + { + if (file_exists($p.$classPath)) + { + $path = $p.$classPath; + break; + } + else if (file_exists($p.$classPath.'.xml')) + { + $path = $p.$classPath.'.xml'; + break; + } + else if (file_exists($p.$classPath.'.php')) + { + $path = $p.$classPath.'.php'; + break; + } + } + return $path; +} + +/** + * @param $path + * + * @return null + */ +function glz_importLib($path) +{ + if (!class_exists('org_glizy_Paths')) return NULL; + require_once(org_glizy_Paths::get('CORE_LIBS').$path); +} + +/** + * @param $path + * + * @return null + */ +function glz_importApplicationLib($path) +{ + if (!class_exists('org_glizy_Paths')) return NULL; + require_once(org_glizy_Paths::get('APPLICATION_LIBS').$path); +} + +/** + * @param $output + * + * @return mixed + */ +function glz_encodeOutput($output) +{ + if (!$output) return $output; + if (is_array($output)) + { + return glz_encodeOutputArray($output); + } + else return glz_htmlentities($output); +} + +/** + * @param $output + * + * @return mixed + */ +function glz_encodeOutputArray($output) +{ + $keys = array_keys($output); + $count = count($output); + for ($i = 0; $i < $count; $i++) + { + if (is_array($output[$keys[$i]])) + { + $output[$keys[$i]] = glz_encodeOutputArray($output[$keys[$i]]); + } + else + { + $output[$keys[$i]] = glz_htmlentities($output[$keys[$i]]); + } + } + return $output; +} + +/** + * @param $text + * + * @return mixed + */ +function glz_htmlentities( $text ) +{ + if (!$text) return $text; + $tempText = @htmlentities( $text, ENT_COMPAT | ENT_SUBSTITUTE , GLZ_CHARSET ); + if (!$tempText) { + $tempText = @htmlentities( $text, ENT_COMPAT); + } + + if ($tempText) { + $text = $tempText; + } + + return str_replace('&amp;#', '&#', $text); +} + +/** + * @param $psw + * + * @return string + */ +function glz_password($psw) +{ + switch (org_glizy_config::get('PSW_METHOD')) + { + case 'MD5': + return md5($psw); + case 'SHA1': + return sha1($psw); + case 'SHA1OFMD5': + return sha1(md5($psw)); + default: + return $psw; + } +} + +/** + * @param $name + * + * @return mixed + */ +function glz_basename($name) +{ + return preg_replace('/.php/', '', basename($name)); +} + + +/** + * @param $value + * + * @return bool + */ +function glz_empty($value) +{ + if ( strpos( $value, '<img') !== false ) return false; + $value = is_string($value) ? strip_tags($value) : $value; + return empty($value); +} +/** + * @param $value + * + * @return mixed + */ +function glz_localeDate2ISO( $value ) +{ + if (!is_string($value)) return $value; + $type = strlen( $value ) <= 10 ? 'date' : 'datetime'; + $reg = __T( $type == 'date' ? 'GLZ_DATE_TOISO_REGEXP' : 'GLZ_DATETIME_TOTIME_REGEXP' ); + if ( is_array( $reg ) && preg_match( $reg[0], $value ) ) + { + $value = preg_replace( $reg[0], $reg[1], $value ); + } + return $value; +} + +/** + * @param $value + * + * @return mixed + */ +function glz_localeDate2default( $value ) +{ + if (!is_string($value)) return $value; + $type = strlen( $value ) <= 10 ? 'date' : 'datetime'; + $reg = __T( $type == 'date' ? 'GLZ_DATE_TOTIME_REGEXP' : 'GLZ_DATETIME_TOTIME_REGEXP' ); + if ( is_array( $reg ) && preg_match( $reg[0], $value ) ) + { + $value = preg_replace( $reg[0], $reg[1], $value ); + } + return $value; +} + +/** + * @param string $format + * @param $value + * + * @return bool|string + */ +function glz_defaultDate2locale( $format, $value ) +{ + list( $d, $t ) = explode( ' ', $value . ' '); + list( $y, $m, $day ) = explode( '-', $d ); + if (!$t) $t = '00:00:00'; + list( $hh, $mm, $ss ) = explode( ':', $t ); + return date( $format, mktime( intval( $hh ), intval( $mm ), intval( $ss ), intval( $m ), intval( $day ), intval( $y ) ) ); +} + + +/* + code borrowed By Stewart Rosenberger + http://www.stewartspeak.com/headings/ + convert embedded, javascript unicode characters into embedded HTML + entities. (e.g. '%u2018' => '&#8216;'). returns the converted string. +*/ + +/* +APL Quote " &quot; &#34; &#x22; +Double Quote (left) “ &ldquo; &#8220; &#x201C; +Double Quote (right) †&rdquo; &#8221; &#x201D; +Single Quote (left) ‘ &lsquo; &#8216; &#x2018; +Single Quote (right) ’ &rsquo; &#8217; &#x2019; +Prime ' &prime; &#8242; &#x2032; +Double Prime ? &Prime; &#8243; &#x2033; +Em Dash &mdash; &#8212; &#x2013; +En Dash – &ndash; &#8211; &#x2013; +Minus - &minus; &#8722; &#x2212; +Multiplication Symbol × &times; &#215; &#xD7; +Division Symbol ÷ &divide; &#247; &#xF7; +Ellipsis … &hellip; &#8230; &#x2026; +Copyright Symbol © &copy; &#169; &#xA9; +Trademark â„¢ &trade; &#8482; &#x2122; +Registered Trademark ® &reg; &#174; &#xAE; + +*/ + +/** + * @param string $text + * + * @return string mixed + */ +function javascript_to_html($text) +{ + $matches = null ; + + preg_match_all('/%u([0-9A-F]{4})/i',$text,$matches) ; + if(!empty($matches)) + { + $convTable = array( + '2026' => "…", + '201C' => "“", + '201D' => "â€", + '2018' => "‘", + '2019' => "’", + '2032' => "'", + '2013' => "—", + '2212' => "–" + ); + for($i=0;$i<sizeof($matches[0]);$i++) + { + if (isset($convTable[$matches[1][$i]])) + { + $text = str_replace($matches[0][$i], $convTable[$matches[1][$i]], $text); + } + else + { + $text = str_replace($matches[0][$i], '&#'.hexdec($matches[1][$i]).';',$text); + } + } + } + + preg_match_all('/\&#([0-9A-F]{4});/i',$text,$matches) ; + if(!empty($matches)) + { + $convTable = array( + '8230' => "…", + '8220' => "“", + '8221' => "â€", + '8216' => "‘", + '8217' => "’", + '8242' => "'", + '8211' => "—", + '8212' => "-", + '8722' => "–", + '8364' => "€" + ); + for($i=0;$i<sizeof($matches[0]);$i++) + { + if (isset($convTable[$matches[1][$i]])) + { + $text = str_replace($matches[0][$i], $convTable[$matches[1][$i]], $text); + } + } + } + return $text; +} + +/** + * @param int $len + * + * @return string + */ +function glz_makePass( $len = 7) +{ + $pass = ""; + $salt = "abchefghjkmnpqrstuvwxyz0123456789"; + srand((double)microtime()*1000000); + $i = 0; + while ($i <= $len ) + { + $num = rand() % 33; + $tmp = substr($salt, $num, 1); + $pass = $pass . $tmp; + $i++; + } + return $pass; +} + +/** + * @param int $len + * @param null $id + * + * @return string + */ +function glz_makeConfirmCode( $len=7, $id=NULL ) +{ + $convTable = array( 0 => "f", 1 => "x", 2 => "r", 3 => "i", 4 => "d",5 => "g", 6 => "n", 7 => "k", 8 => "h", 9 => "o" ); + + // creazione password normale + $code = glz_makePass( $len ); + // codifica di cesare per id + $s_id = sprintf("%d",$id); + for( $i=0; $i<strlen($id); $i++ ) + { + // accodiamo la conversione dell'id al codice + $code .= $convTable[ $s_id{$i} ]; + } + return $code; +} + +/** + * @param $str + * @param int $maxlen + * @param string $elli + * @param int $maxoverflow + * + * @return string + */ +function glz_strtrim($str, $maxlen=200, $elli='...', $maxoverflow=15) +{ + $str = strip_tags( $str ); + if ( strlen($str) > $maxlen) + { + $output = NULL; + $body = explode(" ", $str); + $body_count = count($body); + + $i=0; + do { + $output .= $body[$i]." "; + $thisLen = strlen($output); + $cycle = ($thisLen < $maxlen && $i < $body_count-1 && ($thisLen+strlen($body[$i+1])) < $maxlen+$maxoverflow?true:false); + $i++; + } while ($cycle); + return $output.$elli; + } + else return $str; +} + +/** + * @return string + */ +function glz_hostName() +{ + return GLZ_HOST.'/'; +} + +/** + * @param $string + * + * @return string + */ +function glz_htmlWithUnicodeToUtf8( $string ) +{ + return utf8_encode( glz_htmlWithUnicodeDecode( $string ) ); +} + +/** + * @param $string + * + * @return string + */ +function glz_htmlWithUnicodeDecode( $string ) +{ + return html_entity_decode( preg_replace("/\\\\u([0-9abcdef]{4})/", "&#x$1;", $string ), ENT_NOQUOTES, 'UTF-8'); +} + +/** + * @param $title + * + * @return string + */ +function glz_sanitizeUrlTitle($title, $force=false) { + if (!$title) return $title; + if ( __Config::get( 'SANITIZE_URL' ) || $force ) + { + $title = glz_slugify($title, true); + } else { + $title = str_replace(' ', '-', $title); + } + + return $title; +} + +/** + * http://stackoverflow.com/questions/10152894/php-replacing-special-characters-like-%C3%A0-a-%C3%A8-e + * @param $title + * @param $strict + * + * @return string + */ +function glz_slugify($text, $strict = false) { + if ($text) { + $text = html_entity_decode($text, ENT_QUOTES, 'UTF-8'); + // replace non letter or digits by - + $text = preg_replace('~[^\\pL\d.]+~u', '-', $text); + + // trim + $text = trim($text, '-'); + setlocale(LC_CTYPE, 'en_GB.utf8'); + // transliterate + if (function_exists('iconv')) { + $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text); + } + + // lowercase + $text = strtolower($text); + // remove unwanted characters + $text = preg_replace('~[^-\w.]+~', '', $text); + if (empty($text)) { + return 'empty_$'; + } + if ($strict) { + $text = str_replace(".", "_", $text); + } + } + return $text; +} + +/** + * @param string $text + * @param bool $html + * + * @return string + */ +function glz_stringToJs($text, $html=false) { + if ($html) { + $text = str_replace(array("\n","\r"), '', $text); + } + $text = addslashes($text); + return $text; +} + +function glz_closeGlizy() +{ + GlizyClassLoader::unregister(); + GlizyErrorHandler::unregister(); +} + +if ( !function_exists( "stripos" ) ) +{ + /** + * @param $str + * @param $needle + * + * @return int + */ + function stripos($str,$needle) + { + return strpos(strtolower($str),strtolower($needle)); + } +} + +/** + * Class GlizyClassLoader + */ +class GlizyClassLoader { + private static $instance = null; + public $libMap = array(); + + public static function register() + { + if (!self::$instance) { + self::$instance = new GlizyClassLoader(); + } + spl_autoload_register(array(self::$instance, 'loadClass')); + } + + public static function unregister() + { + spl_autoload_unregister(array(self::$instance, 'loadClass')); + } + + /** + * @param string $name + * @param string $path + */ + public static function addLib($name, $path) + { + self::$instance->libMap[$name] = $path; + } + + /** + * @param string $className + * + * @return bool + */ + public function loadClass($className) + { + foreach($this->libMap as $name=>$path) { + if (strpos($className, $name)===0) { + $fileName = str_replace(array($name.'\\', '\\'), array('/', '/'), $className).'.php'; + require_once($path.$fileName); + return true; + } + } + + $className = str_replace( '_', '.', $className ); + return glz_import( $className ); + } +} + +/** + * Class GlizyErrorHandler + */ +class GlizyErrorHandler { + private static $isRegistred = false; + private static $instance = null; + + /** + * + */ + function __construct() + { + set_error_handler(array($this, 'onErrorHandler'), E_ALL); + set_exception_handler(array($this, 'onExceptionHandler')); + register_shutdown_function(array($this, 'onShutdownFunction')); + } + + public static function register() + { + if (!self::$instance) { + self::$instance = new GlizyErrorHandler(); + } + self::$isRegistred = true; + } + + public static function unregister() + { + self::$isRegistred = false; + restore_exception_handler(); + restore_error_handler(); + } + + /** + * @param $errno + * @param $errstr + * @param $errfile + * @param $errline + */ + public function onErrorHandler($errno, $errstr, $errfile, $errline) + { + if (!self::$isRegistred) return; + $errorlevel=error_reporting(); + if ($errorlevel&$errno && !($errno&E_STRICT)) + { + glz_import('org.glizy.Exception'); + if (org_glizy_Config::get('ERROR_DUMP') !== '') { + org_glizy_Exception::error_dump($errno, $errstr, $errfile, $errline); + } + org_glizy_Exception::show($errno, $errstr, $errfile, $errline); + } + } + + /** + * @param Exception $exception + */ + public function onExceptionHandler($exception) + { + if (!self::$isRegistred) return; + glz_import('org.glizy.Exception'); + if (org_glizy_Config::get('ERROR_DUMP') !== '') { + org_glizy_Exception::error_dump($exception->getCode(), $exception->getMessage(), $exception->getFile(), $exception->getLine()); + } + org_glizy_Exception::show($exception->getCode(), $exception->getMessage(), $exception->getFile(), $exception->getLine()); + } + + public function onShutdownFunction() { + if (!self::$isRegistred) return; + $error = error_get_last(); + if ($error['type'] == 1) { + if (org_glizy_Config::get('ERROR_DUMP') !== '') { + org_glizy_Exception::error_dump($error['type'], $error['message'], $error['file'], $error['line']); + } + org_glizy_Exception::show( $error['type'], $error['message'], $error['file'], $error['line']); + } + } +} \ No newline at end of file diff --git a/src/core/libs/Cache_Lite/LICENSE b/src/core/libs/Cache_Lite/LICENSE new file mode 100755 index 0000000..27950e8 --- /dev/null +++ b/src/core/libs/Cache_Lite/LICENSE @@ -0,0 +1,458 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS diff --git a/src/core/libs/Cache_Lite/Lite.php b/src/core/libs/Cache_Lite/Lite.php new file mode 100644 index 0000000..0ca762d --- /dev/null +++ b/src/core/libs/Cache_Lite/Lite.php @@ -0,0 +1,886 @@ +<?php + +/** +* Fast, light and safe Cache Class +* +* Cache_Lite is a fast, light and safe cache system. It's optimized +* for file containers. It is fast and safe (because it uses file +* locking and/or anti-corruption tests). +* +* There are some examples in the 'docs/examples' file +* Technical choices are described in the 'docs/technical' file +* +* Memory Caching is from an original idea of +* Mike BENOIT <ipso@snappymail.ca> +* +* Nota : A chinese documentation (thanks to RainX <china_1982@163.com>) is +* available at : +* http://rainx.phpmore.com/manual/cache_lite.html +* +* @package Cache_Lite +* @category Caching +* @author Fabien MARTY <fab@php.net> +* @author Markus Tacker <tacker@php.net> +*/ + +define('CACHE_LITE_ERROR_RETURN', 1); +define('CACHE_LITE_ERROR_DIE', 8); + +class Cache_Lite +{ + + // --- Private properties --- + + /** + * Directory where to put the cache files + * (make sure to add a trailing slash) + * + * @var string $_cacheDir + */ + var $_cacheDir = '/tmp/'; + + /** + * Enable / disable caching + * + * (can be very usefull for the debug of cached scripts) + * + * @var boolean $_caching + */ + var $_caching = true; + + /** + * Cache lifetime (in seconds) + * + * If null, the cache is valid forever. + * + * @var int $_lifeTime + */ + var $_lifeTime = 3600; + + /** + * Enable / disable fileLocking + * + * (can avoid cache corruption under bad circumstances) + * + * @var boolean $_fileLocking + */ + var $_fileLocking = true; + + /** + * Timestamp of the last valid cache + * + * @var int $_refreshTime + */ + var $_refreshTime; + + /** + * File name (with path) + * + * @var string $_file + */ + var $_file; + + /** + * File name (without path) + * + * @var string $_fileName + */ + var $_fileName; + + /** + * Enable / disable write control (the cache is read just after writing to detect corrupt entries) + * + * Enable write control will lightly slow the cache writing but not the cache reading + * Write control can detect some corrupt cache files but maybe it's not a perfect control + * + * @var boolean $_writeControl + */ + var $_writeControl = true; + + /** + * Enable / disable read control + * + * If enabled, a control key is embeded in cache file and this key is compared with the one + * calculated after the reading. + * + * @var boolean $_writeControl + */ + var $_readControl = true; + + /** + * Type of read control (only if read control is enabled) + * + * Available values are : + * 'md5' for a md5 hash control (best but slowest) + * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice) + * 'strlen' for a length only test (fastest) + * + * @var boolean $_readControlType + */ + var $_readControlType = 'crc32'; + + /** + * Pear error mode (when raiseError is called) + * + * (see PEAR doc) + * + * @see setToDebug() + * @var int $_pearErrorMode + */ + var $_pearErrorMode = CACHE_LITE_ERROR_RETURN; + + /** + * Current cache id + * + * @var string $_id + */ + var $_id; + + /** + * Current cache group + * + * @var string $_group + */ + var $_group; + + /** + * Enable / Disable "Memory Caching" + * + * NB : There is no lifetime for memory caching ! + * + * @var boolean $_memoryCaching + */ + var $_memoryCaching = false; + + /** + * Enable / Disable "Only Memory Caching" + * (be carefull, memory caching is "beta quality") + * + * @var boolean $_onlyMemoryCaching + */ + var $_onlyMemoryCaching = false; + + /** + * Memory caching array + * + * @var array $_memoryCachingArray + */ + var $_memoryCachingArray = array(); + + /** + * Memory caching counter + * + * @var int $memoryCachingCounter + */ + var $_memoryCachingCounter = 0; + + /** + * Memory caching limit + * + * @var int $memoryCachingLimit + */ + var $_memoryCachingLimit = 1000; + + /** + * File Name protection + * + * if set to true, you can use any cache id or group name + * if set to false, it can be faster but cache ids and group names + * will be used directly in cache file names so be carefull with + * special characters... + * + * @var boolean $fileNameProtection + */ + var $_fileNameProtection = true; + + /** + * Enable / disable automatic serialization + * + * it can be used to save directly datas which aren't strings + * (but it's slower) + * + * @var boolean $_serialize + */ + var $_automaticSerialization = false; + + /** + * Disable / Tune the automatic cleaning process + * + * The automatic cleaning process destroy too old (for the given life time) + * cache files when a new cache file is written. + * 0 => no automatic cache cleaning + * 1 => systematic cache cleaning + * x (integer) > 1 => automatic cleaning randomly 1 times on x cache write + * + * @var int $_automaticCleaning + */ + var $_automaticCleaningFactor = 0; + + /** + * Nested directory level + * + * Set the hashed directory structure level. 0 means "no hashed directory + * structure", 1 means "one level of directory", 2 means "two levels"... + * This option can speed up Cache_Lite only when you have many thousands of + * cache file. Only specific benchs can help you to choose the perfect value + * for you. Maybe, 1 or 2 is a good start. + * + * @var int $_hashedDirectoryLevel + */ + var $_hashedDirectoryLevel = 0; + + /** + * Umask for hashed directory structure + * + * @var int $_hashedDirectoryUmask + */ + var $_hashedDirectoryUmask = 0700; + + /** + * API break for error handling in CACHE_LITE_ERROR_RETURN mode + * + * In CACHE_LITE_ERROR_RETURN mode, error handling was not good because + * for example save() method always returned a boolean (a PEAR_Error object + * would be better in CACHE_LITE_ERROR_RETURN mode). To correct this without + * breaking the API, this option (false by default) can change this handling. + * + * @var boolean + */ + var $_errorHandlingAPIBreak = false; + + var $_hashedDirectoryGroup = NULL; + + var $_cacheFileMode = NULL; + + var $_cacheFileGroup = NULL; + + // --- Public methods --- + + /** + * Constructor + * + * $options is an assoc. Available options are : + * $options = array( + * 'cacheDir' => directory where to put the cache files (string), + * 'caching' => enable / disable caching (boolean), + * 'lifeTime' => cache lifetime in seconds (int), + * 'fileLocking' => enable / disable fileLocking (boolean), + * 'writeControl' => enable / disable write control (boolean), + * 'readControl' => enable / disable read control (boolean), + * 'readControlType' => type of read control 'crc32', 'md5', 'strlen' (string), + * 'pearErrorMode' => pear error mode (when raiseError is called) (cf PEAR doc) (int), + * 'memoryCaching' => enable / disable memory caching (boolean), + * 'onlyMemoryCaching' => enable / disable only memory caching (boolean), + * 'memoryCachingLimit' => max nbr of records to store into memory caching (int), + * 'fileNameProtection' => enable / disable automatic file name protection (boolean), + * 'automaticSerialization' => enable / disable automatic serialization (boolean), + * 'automaticCleaningFactor' => distable / tune automatic cleaning process (int), + * 'hashedDirectoryLevel' => level of the hashed directory system (int), + * 'hashedDirectoryUmask' => umask for hashed directory structure (int), + * 'errorHandlingAPIBreak' => API break for better error handling ? (boolean) + * 'hashedDirectoryGroup' => group of hashed directory structure (int | string) (see function chgrp) + * 'cacheFileMode' => filesystem mode of newly created cache files (int) + * 'cacheFileGroup' => group of newly created cache files (int | string) (see function chgrp) + * ); + * + * If sys_get_temp_dir() is available and the + * 'cacheDir' option is not provided in the + * constructor options array its output is used + * to determine the suitable temporary directory. + * + * @see http://de.php.net/sys_get_temp_dir + * @see http://pear.php.net/bugs/bug.php?id=18328 + * + * @param array $options options + * @access public + */ + function Cache_Lite($options = array(NULL)) + { + foreach($options as $key => $value) { + $this->setOption($key, $value); + } + if (!isset($options['cacheDir']) && function_exists('sys_get_temp_dir')) { + $this->setOption('cacheDir', sys_get_temp_dir() . DIRECTORY_SEPARATOR); + } + } + + /** + * Generic way to set a Cache_Lite option + * + * see Cache_Lite constructor for available options + * + * @var string $name name of the option + * @var mixed $value value of the option + * @access public + */ + function setOption($name, $value) + { + $availableOptions = array('errorHandlingAPIBreak', 'hashedDirectoryUmask', 'hashedDirectoryLevel', 'automaticCleaningFactor', 'automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode', 'hashedDirectoryGroup', 'cacheFileMode', 'cacheFileGroup'); + if (in_array($name, $availableOptions)) { + $property = '_'.$name; + $this->$property = $value; + } + } + + /** + * Test if a cache is available and (if yes) return it + * + * @param string $id cache id + * @param string $group name of the cache group + * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested + * @return string data of the cache (else : false) + * @access public + */ + function get($id, $group = 'default', $doNotTestCacheValidity = false) + { + $this->_id = $id; + $this->_group = $group; + $data = false; + if ($this->_caching) { + $this->_setRefreshTime(); + $this->_setFileName($id, $group); + clearstatcache(); + if ($this->_memoryCaching) { + if (isset($this->_memoryCachingArray[$this->_file])) { + if ($this->_automaticSerialization) { + return unserialize($this->_memoryCachingArray[$this->_file]); + } + return $this->_memoryCachingArray[$this->_file]; + } + if ($this->_onlyMemoryCaching) { + return false; + } + } + if (($doNotTestCacheValidity) || (is_null($this->_refreshTime))) { + if (file_exists($this->_file)) { + $data = $this->_read(); + } + } else { + if ((file_exists($this->_file)) && (@filemtime($this->_file) > $this->_refreshTime)) { + $data = $this->_read(); + } + } + if (($data) and ($this->_memoryCaching)) { + $this->_memoryCacheAdd($data); + } + if (($this->_automaticSerialization) and (is_string($data))) { + $data = unserialize($data); + } + return $data; + } + return false; + } + + /** + * Save some data in a cache file + * + * @param string $data data to put in cache (can be another type than strings if automaticSerialization is on) + * @param string $id cache id + * @param string $group name of the cache group + * @return boolean true if no problem (else : false or a PEAR_Error object) + * @access public + */ + function save($data, $id = NULL, $group = 'default') + { + if ($this->_caching) { + if ($this->_automaticSerialization) { + $data = serialize($data); + } + if (isset($id)) { + $this->_setFileName($id, $group); + } + if ($this->_memoryCaching) { + $this->_memoryCacheAdd($data); + if ($this->_onlyMemoryCaching) { + return true; + } + } + if ($this->_automaticCleaningFactor>0 && ($this->_automaticCleaningFactor==1 || mt_rand(1, $this->_automaticCleaningFactor)==1)) { + $this->clean(false, 'old'); + } + if ($this->_writeControl) { + $res = $this->_writeAndControl($data); + if (is_bool($res)) { + if ($res) { + return true; + } + // if $res if false, we need to invalidate the cache + @touch($this->_file, time() - 2*abs($this->_lifeTime)); + return false; + } + } else { + $res = $this->_write($data); + } + if (is_object($res)) { + // $res is a PEAR_Error object + if (!($this->_errorHandlingAPIBreak)) { + return false; // we return false (old API) + } + } + return $res; + } + return false; + } + + /** + * Remove a cache file + * + * @param string $id cache id + * @param string $group name of the cache group + * @param boolean $checkbeforeunlink check if file exists before removing it + * @return boolean true if no problem + * @access public + */ + function remove($id, $group = 'default', $checkbeforeunlink = false) + { + $this->_setFileName($id, $group); + if ($this->_memoryCaching) { + if (isset($this->_memoryCachingArray[$this->_file])) { + unset($this->_memoryCachingArray[$this->_file]); + $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1; + } + if ($this->_onlyMemoryCaching) { + return true; + } + } + if ( $checkbeforeunlink ) { + if (!file_exists($this->_file)) return true; + } + return $this->_unlink($this->_file); + } + + /** + * Clean the cache + * + * if no group is specified all cache files will be destroyed + * else only cache files of the specified group will be destroyed + * + * @param string $group name of the cache group + * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup', + * 'callback_myFunction' + * @return boolean true if no problem + * @access public + */ + function clean($group = false, $mode = 'ingroup') + { + return $this->_cleanDir($this->_cacheDir, $group, $mode); + } + + /** + * Set to debug mode + * + * When an error is found, the script will stop and the message will be displayed + * (in debug mode only). + * + * @access public + */ + function setToDebug() + { + $this->setOption('pearErrorMode', CACHE_LITE_ERROR_DIE); + } + + /** + * Set a new life time + * + * @param int $newLifeTime new life time (in seconds) + * @access public + */ + function setLifeTime($newLifeTime) + { + $this->_lifeTime = $newLifeTime; + $this->_setRefreshTime(); + } + + /** + * Save the state of the caching memory array into a cache file cache + * + * @param string $id cache id + * @param string $group name of the cache group + * @access public + */ + function saveMemoryCachingState($id, $group = 'default') + { + if ($this->_caching) { + $array = array( + 'counter' => $this->_memoryCachingCounter, + 'array' => $this->_memoryCachingArray + ); + $data = serialize($array); + $this->save($data, $id, $group); + } + } + + /** + * Load the state of the caching memory array from a given cache file cache + * + * @param string $id cache id + * @param string $group name of the cache group + * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested + * @access public + */ + function getMemoryCachingState($id, $group = 'default', $doNotTestCacheValidity = false) + { + if ($this->_caching) { + if ($data = $this->get($id, $group, $doNotTestCacheValidity)) { + $array = unserialize($data); + $this->_memoryCachingCounter = $array['counter']; + $this->_memoryCachingArray = $array['array']; + } + } + } + + /** + * Return the cache last modification time + * + * BE CAREFUL : THIS METHOD IS FOR HACKING ONLY ! + * + * @return int last modification time + */ + function lastModified() + { + return @filemtime($this->_file); + } + + /** + * Trigger a PEAR error + * + * To improve performances, the PEAR.php file is included dynamically. + * The file is so included only when an error is triggered. So, in most + * cases, the file isn't included and perfs are much better. + * + * @param string $msg error message + * @param int $code error code + * @access public + */ + function raiseError($msg, $code) + { + include_once('PEAR.php'); + return PEAR::raiseError($msg, $code, $this->_pearErrorMode); + } + + /** + * Extend the life of a valid cache file + * + * see http://pear.php.net/bugs/bug.php?id=6681 + * + * @access public + */ + function extendLife() + { + @touch($this->_file); + } + + // --- Private methods --- + + /** + * Compute & set the refresh time + * + * @access private + */ + function _setRefreshTime() + { + if (is_null($this->_lifeTime)) { + $this->_refreshTime = null; + } else { + $this->_refreshTime = time() - $this->_lifeTime; + } + } + + /** + * Remove a file + * + * @param string $file complete file path and name + * @return boolean true if no problem + * @access private + */ + function _unlink($file) + { + if (!@unlink($file)) { + return $this->raiseError('Cache_Lite : Unable to remove cache !', -3); + } + return true; + } + + /** + * Recursive function for cleaning cache file in the given directory + * + * @param string $dir directory complete path (with a trailing slash) + * @param string $group name of the cache group + * @param string $mode flush cache mode : 'old', 'ingroup', 'notingroup', + 'callback_myFunction' + * @return boolean true if no problem + * @access private + */ + function _cleanDir($dir, $group = false, $mode = 'ingroup') + { + if ($this->_fileNameProtection) { + $motif = ($group) ? 'cache_'.md5($group).'_' : 'cache_'; + } else { + $motif = ($group) ? 'cache_'.$group.'_' : 'cache_'; + } + if ($this->_memoryCaching) { + foreach($this->_memoryCachingArray as $key => $v) { + if (strpos($key, $motif) !== false) { + unset($this->_memoryCachingArray[$key]); + $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1; + } + } + if ($this->_onlyMemoryCaching) { + return true; + } + } + if (!($dh = opendir($dir))) { + return $this->raiseError('Cache_Lite : Unable to open cache directory !', -4); + } + $result = true; + while (($file = readdir($dh)) !== false) { + if (($file != '.') && ($file != '..')) { + if (substr($file, 0, 6)=='cache_') { + $file2 = $dir . $file; + if (is_file($file2)) { + switch (substr($mode, 0, 9)) { + case 'old': + // files older than lifeTime get deleted from cache + if (!is_null($this->_lifeTime)) { + if ((time() - @filemtime($file2)) > $this->_lifeTime) { + $result = ($result and ($this->_unlink($file2))); + } + } + break; + case 'notingrou': + if (strpos($file2, $motif) === false) { + $result = ($result and ($this->_unlink($file2))); + } + break; + case 'callback_': + $func = substr($mode, 9, strlen($mode) - 9); + if ($func($file2, $group)) { + $result = ($result and ($this->_unlink($file2))); + } + break; + case 'ingroup': + default: + if (strpos($file2, $motif) !== false) { + $result = ($result and ($this->_unlink($file2))); + } + break; + } + } + if ((is_dir($file2)) and ($this->_hashedDirectoryLevel>0)) { + $result = ($result and ($this->_cleanDir($file2 . '/', $group, $mode))); + } + } + } + } + return $result; + } + + /** + * Touch the cache file while are recreating it to avoid + * launch this task more then once when necessary + * When the cache recreated and Added in Cache Memory + * @return void + * @access private + */ + function _touchCacheFile(){ + if (file_exists($this->_file)) { + @touch($this->_file); + } + } + /** + * Add some date in the memory caching array + * + * @param string $data data to cache + * @access private + */ + function _memoryCacheAdd($data) + { + $this->_touchCacheFile(); + $this->_memoryCachingArray[$this->_file] = $data; + if ($this->_memoryCachingCounter >= $this->_memoryCachingLimit) { + list($key, ) = each($this->_memoryCachingArray); + unset($this->_memoryCachingArray[$key]); + } else { + $this->_memoryCachingCounter = $this->_memoryCachingCounter + 1; + } + } + + /** + * Make a file name (with path) + * + * @param string $id cache id + * @param string $group name of the group + * @access private + */ + function _setFileName($id, $group) + { + + if ($this->_fileNameProtection) { + $suffix = 'cache_'.md5($group).'_'.md5($id); + } else { + $suffix = 'cache_'.$group.'_'.$id; + } + $root = $this->_cacheDir; + if ($this->_hashedDirectoryLevel>0) { + $hash = md5($suffix); + for ($i=0 ; $i<$this->_hashedDirectoryLevel ; $i++) { + $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/'; + } + } + $this->_fileName = $suffix; + $this->_file = $root.$suffix; + } + + /** + * Read the cache file and return the content + * + * @return string content of the cache file (else : false or a PEAR_Error object) + * @access private + */ + function _read() + { + $fp = @fopen($this->_file, "rb"); + if ($fp) { + if ($this->_fileLocking) @flock($fp, LOCK_SH); + clearstatcache(); + $length = @filesize($this->_file); + $mqr = get_magic_quotes_runtime(); + if ($mqr) { + set_magic_quotes_runtime(0); + } + if ($this->_readControl) { + $hashControl = @fread($fp, 32); + $length = $length - 32; + } + + if ($length) { + $data = ''; + // See https://bugs.php.net/bug.php?id=30936 + // The 8192 magic number is the chunk size used internally by PHP. + while(!feof($fp)) $data .= fread($fp, 8192); + } else { + $data = ''; + } + if ($mqr) { + set_magic_quotes_runtime($mqr); + } + if ($this->_fileLocking) @flock($fp, LOCK_UN); + @fclose($fp); + if ($this->_readControl) { + $hashData = $this->_hash($data, $this->_readControlType); + if ($hashData != $hashControl) { + if (!(is_null($this->_lifeTime))) { + @touch($this->_file, time() - 2*abs($this->_lifeTime)); + } else { + @unlink($this->_file); + } + return false; + } + } + return $data; + } + return $this->raiseError('Cache_Lite : Unable to read cache !', -2); + } + + /** + * Write the given data in the cache file + * + * @param string $data data to put in cache + * @return boolean true if ok (a PEAR_Error object else) + * @access private + */ + function _write($data) + { + if ($this->_hashedDirectoryLevel > 0) { + $hash = md5($this->_fileName); + $root = $this->_cacheDir; + for ($i=0 ; $i<$this->_hashedDirectoryLevel ; $i++) { + $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/'; + if (!(@is_dir($root))) { + if (@mkdir($root)) + { + @chmod($root, $this->_hashedDirectoryUmask); + if (! is_null($this->_hashedDirectoryGroup)) + @chgrp($root, $this->_hashedDirectoryGroup); + } + } + } + } + // if both _cacheFileMode and _cacheFileGroup is null, then we don't need to call + // file_exists (see below: if ($is_newfile) ...) + $is_newfile = (! is_null($this->_cacheFileMode) || !is_null($this->_cacheFileGroup)) + && ! @file_exists($this->_file); + $fp = @fopen($this->_file, "wb"); + if ($fp) { + if ($this->_fileLocking) @flock($fp, LOCK_EX); + if ($is_newfile) + { + if (! is_null($this->_cacheFileMode)) + @chmod($this->_file, $this->_cacheFileMode); + if (! is_null($this->_cacheFileGroup)) + @chgrp($this->_file, $this->_cacheFileGroup); + } + if ($this->_readControl) { + @fwrite($fp, $this->_hash($data, $this->_readControlType), 32); + } + $mqr = get_magic_quotes_runtime(); + if ($mqr) { + set_magic_quotes_runtime(0); + } + @fwrite($fp, $data); + if ($mqr) { + set_magic_quotes_runtime($mqr); + } + if ($this->_fileLocking) @flock($fp, LOCK_UN); + @fclose($fp); + return true; + } + return $this->raiseError('Cache_Lite : Unable to write cache file : '.$this->_file, -1); + } + + /** + * Write the given data in the cache file and control it just after to avoir corrupted cache entries + * + * @param string $data data to put in cache + * @return boolean true if the test is ok (else : false or a PEAR_Error object) + * @access private + */ + function _writeAndControl($data) + { + $result = $this->_write($data); + if (is_object($result)) { + return $result; # We return the PEAR_Error object + } + $dataRead = $this->_read(); + if (is_object($dataRead)) { + return $dataRead; # We return the PEAR_Error object + } + if ((is_bool($dataRead)) && (!$dataRead)) { + return false; + } + return ($dataRead==$data); + } + + /** + * Make a control key with the string containing datas + * + * @param string $data data + * @param string $controlType type of control 'md5', 'crc32' or 'strlen' + * @return string control key + * @access private + */ + function _hash($data, $controlType) + { + switch ($controlType) { + case 'md5': + return md5($data); + case 'crc32': + return sprintf('% 32d', crc32($data)); + case 'strlen': + return sprintf('% 32d', strlen($data)); + default: + return $this->raiseError('Unknown controlType ! (available values are only \'md5\', \'crc32\', \'strlen\')', -5); + } + } + +} diff --git a/src/core/libs/Cache_Lite/Lite/File.php b/src/core/libs/Cache_Lite/Lite/File.php new file mode 100644 index 0000000..2cb2758 --- /dev/null +++ b/src/core/libs/Cache_Lite/Lite/File.php @@ -0,0 +1,90 @@ +<?php + +/** +* This class extends Cache_Lite and offers a cache system driven by a master file +* +* With this class, cache validity is only dependent of a given file. Cache files +* are valid only if they are older than the master file. It's a perfect way for +* caching templates results (if the template file is newer than the cache, cache +* must be rebuild...) or for config classes... +* There are some examples in the 'docs/examples' file +* Technical choices are described in the 'docs/technical' file +* +* @package Cache_Lite +* @author Fabien MARTY <fab@php.net> +*/ + +require_once('Cache/Lite.php'); + +class Cache_Lite_File extends Cache_Lite +{ + + // --- Private properties --- + + /** + * Complete path of the file used for controlling the cache lifetime + * + * @var string $_masterFile + */ + var $_masterFile = ''; + + /** + * Masterfile mtime + * + * @var int $_masterFile_mtime + */ + var $_masterFile_mtime = 0; + + // --- Public methods ---- + + /** + * Constructor + * + * $options is an assoc. To have a look at availables options, + * see the constructor of the Cache_Lite class in 'Cache_Lite.php' + * + * Comparing to Cache_Lite constructor, there is another option : + * $options = array( + * (...) see Cache_Lite constructor + * 'masterFile' => complete path of the file used for controlling the cache lifetime(string) + * ); + * + * @param array $options options + * @access public + */ + function Cache_Lite_File($options = array(NULL)) + { + $options['lifetime'] = 0; + $this->Cache_Lite($options); + if (isset($options['masterFile'])) { + $this->_masterFile = $options['masterFile']; + } else { + return $this->raiseError('Cache_Lite_File : masterFile option must be set !'); + } + if (!($this->_masterFile_mtime = @filemtime($this->_masterFile))) { + return $this->raiseError('Cache_Lite_File : Unable to read masterFile : '.$this->_masterFile, -3); + } + } + + /** + * Test if a cache is available and (if yes) return it + * + * @param string $id cache id + * @param string $group name of the cache group + * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested + * @return string data of the cache (else : false) + * @access public + */ + function get($id, $group = 'default', $doNotTestCacheValidity = false) + { + if ($data = parent::get($id, $group, true)) { + if ($filemtime = $this->lastModified()) { + if ($filemtime > $this->_masterFile_mtime) { + return $data; + } + } + } + return false; + } + +} diff --git a/src/core/libs/Cache_Lite/Lite/Function.php b/src/core/libs/Cache_Lite/Lite/Function.php new file mode 100644 index 0000000..6c4861a --- /dev/null +++ b/src/core/libs/Cache_Lite/Lite/Function.php @@ -0,0 +1,208 @@ +<?php + +/** +* This class extends Cache_Lite and can be used to cache the result and output of functions/methods +* +* This class is completly inspired from Sebastian Bergmann's +* PEAR/Cache_Function class. This is only an adaptation to +* Cache_Lite +* +* There are some examples in the 'docs/examples' file +* Technical choices are described in the 'docs/technical' file +* +* @package Cache_Lite +* @author Sebastian BERGMANN <sb@sebastian-bergmann.de> +* @author Fabien MARTY <fab@php.net> +*/ + +require_once('Cache/Lite.php'); + +class Cache_Lite_Function extends Cache_Lite +{ + + // --- Private properties --- + + /** + * Default cache group for function caching + * + * @var string $_defaultGroup + */ + var $_defaultGroup = 'Cache_Lite_Function'; + + /** + * Don't cache the method call when its output contains the string "NOCACHE" + * + * if set to true, the output of the method will never be displayed (because the output is used + * to control the cache) + * + * @var boolean $_dontCacheWhenTheOutputContainsNOCACHE + */ + var $_dontCacheWhenTheOutputContainsNOCACHE = false; + + /** + * Don't cache the method call when its result is false + * + * @var boolean $_dontCacheWhenTheResultIsFalse + */ + var $_dontCacheWhenTheResultIsFalse = false; + + /** + * Don't cache the method call when its result is null + * + * @var boolean $_dontCacheWhenTheResultIsNull + */ + var $_dontCacheWhenTheResultIsNull = false; + + /** + * Debug the Cache_Lite_Function caching process + * + * @var boolean $_debugCacheLiteFunction + */ + var $_debugCacheLiteFunction = false; + + // --- Public methods ---- + + /** + * Constructor + * + * $options is an assoc. To have a look at availables options, + * see the constructor of the Cache_Lite class in 'Cache_Lite.php' + * + * Comparing to Cache_Lite constructor, there is another option : + * $options = array( + * (...) see Cache_Lite constructor + * 'debugCacheLiteFunction' => (bool) debug the caching process, + * 'defaultGroup' => default cache group for function caching (string), + * 'dontCacheWhenTheOutputContainsNOCACHE' => (bool) don't cache when the function output contains "NOCACHE", + * 'dontCacheWhenTheResultIsFalse' => (bool) don't cache when the function result is false, + * 'dontCacheWhenTheResultIsNull' => (bool don't cache when the function result is null + * ); + * + * @param array $options options + * @access public + */ + function Cache_Lite_Function($options = array(NULL)) + { + $availableOptions = array('debugCacheLiteFunction', 'defaultGroup', 'dontCacheWhenTheOutputContainsNOCACHE', 'dontCacheWhenTheResultIsFalse', 'dontCacheWhenTheResultIsNull'); + while (list($name, $value) = each($options)) { + if (in_array($name, $availableOptions)) { + $property = '_'.$name; + $this->$property = $value; + } + } + reset($options); + $this->Cache_Lite($options); + } + + /** + * Calls a cacheable function or method (or not if there is already a cache for it) + * + * Arguments of this method are read with func_get_args. So it doesn't appear + * in the function definition. Synopsis : + * call('functionName', $arg1, $arg2, ...) + * (arg1, arg2... are arguments of 'functionName') + * + * @return mixed result of the function/method + * @access public + */ + function call() + { + $arguments = func_get_args(); + $id = $this->_makeId($arguments); + $data = $this->get($id, $this->_defaultGroup); + if ($data !== false) { + if ($this->_debugCacheLiteFunction) { + echo "Cache hit !\n"; + } + $array = unserialize($data); + $output = $array['output']; + $result = $array['result']; + } else { + if ($this->_debugCacheLiteFunction) { + echo "Cache missed !\n"; + } + ob_start(); + ob_implicit_flush(false); + $target = array_shift($arguments); + if (is_array($target)) { + // in this case, $target is for example array($obj, 'method') + $object = $target[0]; + $method = $target[1]; + $result = call_user_func_array(array(&$object, $method), $arguments); + } else { + if (strstr($target, '::')) { // classname::staticMethod + list($class, $method) = explode('::', $target); + $result = call_user_func_array(array($class, $method), $arguments); + } else if (strstr($target, '->')) { // object->method + // use a stupid name ($objet_123456789 because) of problems where the object + // name is the same as this var name + list($object_123456789, $method) = explode('->', $target); + global $$object_123456789; + $result = call_user_func_array(array($$object_123456789, $method), $arguments); + } else { // function + $result = call_user_func_array($target, $arguments); + } + } + $output = ob_get_contents(); + ob_end_clean(); + if ($this->_dontCacheWhenTheResultIsFalse) { + if ((is_bool($result)) && (!($result))) { + echo($output); + return $result; + } + } + if ($this->_dontCacheWhenTheResultIsNull) { + if (is_null($result)) { + echo($output); + return $result; + } + } + if ($this->_dontCacheWhenTheOutputContainsNOCACHE) { + if (strpos($output, 'NOCACHE') > -1) { + return $result; + } + } + $array['output'] = $output; + $array['result'] = $result; + $this->save(serialize($array), $id, $this->_defaultGroup); + } + echo($output); + return $result; + } + + /** + * Drop a cache file + * + * Arguments of this method are read with func_get_args. So it doesn't appear + * in the function definition. Synopsis : + * remove('functionName', $arg1, $arg2, ...) + * (arg1, arg2... are arguments of 'functionName') + * + * @return boolean true if no problem + * @access public + */ + function drop() + { + $id = $this->_makeId(func_get_args()); + return $this->remove($id, $this->_defaultGroup); + } + + /** + * Make an id for the cache + * + * @var array result of func_get_args for the call() or the remove() method + * @return string id + * @access private + */ + function _makeId($arguments) + { + $id = serialize($arguments); // Generate a cache id + if (!$this->_fileNameProtection) { + $id = md5($id); + // if fileNameProtection is set to false, then the id has to be hashed + // because it's a very bad file name in most cases + } + return $id; + } + +} diff --git a/src/core/libs/Cache_Lite/Lite/NestedOutput.php b/src/core/libs/Cache_Lite/Lite/NestedOutput.php new file mode 100644 index 0000000..81ece30 --- /dev/null +++ b/src/core/libs/Cache_Lite/Lite/NestedOutput.php @@ -0,0 +1,56 @@ +<?php + +/** +* This class extends Cache_Lite and uses output buffering to get the data to cache. +* It supports nesting of caches +* +* @package Cache_Lite +* @author Markus Tacker <tacker@php.net> +*/ + +require_once('Cache/Lite/Output.php'); + +class Cache_Lite_NestedOutput extends Cache_Lite_Output +{ + private $nestedIds = array(); + private $nestedGroups = array(); + + /** + * Start the cache + * + * @param string $id cache id + * @param string $group name of the cache group + * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested + * @return boolean|string false if the cache is not hit else the data + * @access public + */ + function start($id, $group = 'default', $doNotTestCacheValidity = false) + { + $this->nestedIds[] = $id; + $this->nestedGroups[] = $group; + $data = $this->get($id, $group, $doNotTestCacheValidity); + if ($data !== false) { + return $data; + } + ob_start(); + ob_implicit_flush(false); + return false; + } + + /** + * Stop the cache + * + * @param boolen + * @return string return contents of cache + */ + function end() + { + $data = ob_get_contents(); + ob_end_clean(); + $id = array_pop($this->nestedIds); + $group = array_pop($this->nestedGroups); + $this->save($data, $id, $group); + return $data; + } + +} diff --git a/src/core/libs/Cache_Lite/Lite/Output.php b/src/core/libs/Cache_Lite/Lite/Output.php new file mode 100644 index 0000000..87d7c19 --- /dev/null +++ b/src/core/libs/Cache_Lite/Lite/Output.php @@ -0,0 +1,68 @@ +<?php + +/** +* This class extends Cache_Lite and uses output buffering to get the data to cache. +* +* There are some examples in the 'docs/examples' file +* Technical choices are described in the 'docs/technical' file +* +* @package Cache_Lite +* @author Fabien MARTY <fab@php.net> +*/ + +require_once('Cache/Lite.php'); + +class Cache_Lite_Output extends Cache_Lite +{ + + // --- Public methods --- + + /** + * Constructor + * + * $options is an assoc. To have a look at availables options, + * see the constructor of the Cache_Lite class in 'Cache_Lite.php' + * + * @param array $options options + * @access public + */ + function Cache_Lite_Output($options) + { + $this->Cache_Lite($options); + } + + /** + * Start the cache + * + * @param string $id cache id + * @param string $group name of the cache group + * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested + * @return boolean true if the cache is hit (false else) + * @access public + */ + function start($id, $group = 'default', $doNotTestCacheValidity = false) + { + $data = $this->get($id, $group, $doNotTestCacheValidity); + if ($data !== false) { + echo($data); + return true; + } + ob_start(); + ob_implicit_flush(false); + return false; + } + + /** + * Stop the cache + * + * @access public + */ + function end() + { + $data = ob_get_contents(); + ob_end_clean(); + $this->save($data, $this->_id, $this->_group); + echo($data); + } + +} diff --git a/src/core/libs/DebugBar/Bridge/CacheCacheCollector.php b/src/core/libs/DebugBar/Bridge/CacheCacheCollector.php new file mode 100755 index 0000000..3d841c6 --- /dev/null +++ b/src/core/libs/DebugBar/Bridge/CacheCacheCollector.php @@ -0,0 +1,62 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Bridge; + +use CacheCache\Cache; +use CacheCache\LoggingBackend; +use Monolog\Logger; + +/** + * Collects CacheCache operations + * + * http://maximebf.github.io/CacheCache/ + * + * Example: + * <code> + * $debugbar->addCollector(new CacheCacheCollector(CacheManager::get('default'))); + * // or + * $debugbar->addCollector(new CacheCacheCollector()); + * $debugbar['cache']->addCache(CacheManager::get('default')); + * </code> + */ +class CacheCacheCollector extends MonologCollector +{ + protected $logger; + + public function __construct(Cache $cache = null, Logger $logger = null, $level = Logger::DEBUG, $bubble = true) + { + parent::__construct(null, $level, $bubble); + + if ($logger === null) { + $logger = new Logger('Cache'); + } + $this->logger = $logger; + + if ($cache !== null) { + $this->addCache($cache); + } + } + + public function addCache(Cache $cache) + { + $backend = $cache->getBackend(); + if (!($backend instanceof LoggingBackend)) { + $backend = new LoggingBackend($backend, $this->logger); + } + $cache->setBackend($backend); + $this->addLogger($backend->getLogger()); + } + + public function getName() + { + return 'cache'; + } +} diff --git a/src/core/libs/DebugBar/Bridge/DoctrineCollector.php b/src/core/libs/DebugBar/Bridge/DoctrineCollector.php new file mode 100755 index 0000000..1ef6c96 --- /dev/null +++ b/src/core/libs/DebugBar/Bridge/DoctrineCollector.php @@ -0,0 +1,98 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Bridge; + +use DebugBar\DataCollector\DataCollector; +use DebugBar\DataCollector\Renderable; +use DebugBar\DataCollector\AssetProvider; +use DebugBar\DebugBarException; +use Doctrine\ORM\EntityManager; +use Doctrine\DBAL\Logging\DebugStack; + +/** + * Collects Doctrine queries + * + * http://doctrine-project.org + * + * Uses the DebugStack logger to collects data about queries + * + * <code> + * $debugStack = new Doctrine\DBAL\Logging\DebugStack(); + * $entityManager->getConnection()->getConfiguration()->setSQLLogger($debugStack); + * $debugbar->addCollector(new DoctrineCollector($debugStack)); + * </code> + */ +class DoctrineCollector extends DataCollector implements Renderable, AssetProvider +{ + protected $debugStack; + + public function __construct($debugStackOrEntityManager) + { + if ($debugStackOrEntityManager instanceof EntityManager) { + $debugStackOrEntityManager = $debugStackOrEntityManager->getConnection()->getConfiguration()->getSQLLogger(); + } + if (!($debugStackOrEntityManager instanceof DebugStack)) { + throw new DebugBarException("'DoctrineCollector' requires an 'EntityManager' or 'DebugStack' object"); + } + $this->debugStack = $debugStackOrEntityManager; + } + + public function collect() + { + $queries = array(); + $totalExecTime = 0; + foreach ($this->debugStack->queries as $q) { + $queries[] = array( + 'sql' => $q['sql'], + 'params' => (object) $q['params'], + 'duration' => $q['executionMS'], + 'duration_str' => $this->formatDuration($q['executionMS']) + ); + $totalExecTime += $q['executionMS']; + } + + return array( + 'nb_statements' => count($queries), + 'accumulated_duration' => $totalExecTime, + 'accumulated_duration_str' => $this->formatDuration($totalExecTime), + 'statements' => $queries + ); + } + + public function getName() + { + return 'doctrine'; + } + + public function getWidgets() + { + return array( + "database" => array( + "icon" => "arrow-right", + "widget" => "PhpDebugBar.Widgets.SQLQueriesWidget", + "map" => "doctrine", + "default" => "[]" + ), + "database:badge" => array( + "map" => "doctrine.nb_statements", + "default" => 0 + ) + ); + } + + public function getAssets() + { + return array( + 'css' => 'widgets/sqlqueries/widget.css', + 'js' => 'widgets/sqlqueries/widget.js' + ); + } +} diff --git a/src/core/libs/DebugBar/Bridge/MonologCollector.php b/src/core/libs/DebugBar/Bridge/MonologCollector.php new file mode 100755 index 0000000..0036d49 --- /dev/null +++ b/src/core/libs/DebugBar/Bridge/MonologCollector.php @@ -0,0 +1,103 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Bridge; + +use Monolog\Logger; +use Monolog\Handler\AbstractProcessingHandler; +use DebugBar\DataCollector\DataCollectorInterface; +use DebugBar\DataCollector\Renderable; +use DebugBar\DataCollector\MessagesAggregateInterface; + +/** + * A monolog handler as well as a data collector + * + * https://github.com/Seldaek/monolog + * + * <code> + * $debugbar->addCollector(new MonologCollector($logger)); + * </code> + */ +class MonologCollector extends AbstractProcessingHandler implements DataCollectorInterface, Renderable, MessagesAggregateInterface +{ + protected $name; + + protected $records = array(); + + /** + * @param Logger $logger + * @param int $level + * @param boolean $bubble + * @param string $name + */ + public function __construct(Logger $logger = null, $level = Logger::DEBUG, $bubble = true, $name = 'monolog') + { + parent::__construct($level, $bubble); + $this->name = $name; + if ($logger !== null) { + $this->addLogger($logger); + } + } + + /** + * Adds logger which messages you want to log + * + * @param Logger $logger + */ + public function addLogger(Logger $logger) + { + $logger->pushHandler($this); + } + + protected function write(array $record) + { + $this->records[] = array( + 'message' => $record['formatted'], + 'is_string' => true, + 'label' => strtolower($record['level_name']), + 'time' => $record['datetime']->format('U') + ); + } + + public function getMessages() + { + return $this->records; + } + + public function collect() + { + return array( + 'count' => count($this->records), + 'records' => $this->records + ); + } + + public function getName() + { + return $this->name; + } + + public function getWidgets() + { + $name = $this->getName(); + return array( + $name => array( + "icon" => "suitcase", + "widget" => "PhpDebugBar.Widgets.MessagesWidget", + "map" => "$name.records", + "default" => "[]" + ), + "$name:badge" => array( + "map" => "$name.count", + "default" => "null" + ) + ); + } +} diff --git a/src/core/libs/DebugBar/Bridge/PropelCollector.php b/src/core/libs/DebugBar/Bridge/PropelCollector.php new file mode 100755 index 0000000..7110563 --- /dev/null +++ b/src/core/libs/DebugBar/Bridge/PropelCollector.php @@ -0,0 +1,253 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Bridge; + +use Propel; +use PropelPDO; +use PropelConfiguration; +use BasicLogger; +use DebugBar\DataCollector\DataCollector; +use DebugBar\DataCollector\Renderable; +use DebugBar\DataCollector\AssetProvider; +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; + +/** + * A Propel logger which acts as a data collector + * + * http://propelorm.org/ + * + * Will log queries and display them using the SQLQueries widget. + * You can provide a LoggerInterface object to forward non-query related message to. + * + * Example: + * <code> + * $debugbar->addCollector(new PropelCollector($debugbar['messages'])); + * PropelCollector::enablePropelProfiling(); + * </code> + */ +class PropelCollector extends DataCollector implements BasicLogger, Renderable, AssetProvider +{ + protected $logger; + + protected $statements = array(); + + protected $accumulatedTime = 0; + + protected $peakMemory = 0; + + /** + * Sets the needed configuration option in propel to enable query logging + * + * @param PropelConfiguration $config Apply profiling on a specific config + */ + public static function enablePropelProfiling(PropelConfiguration $config = null) + { + if ($config === null) { + $config = Propel::getConfiguration(PropelConfiguration::TYPE_OBJECT); + } + $config->setParameter('debugpdo.logging.details.method.enabled', true); + $config->setParameter('debugpdo.logging.details.time.enabled', true); + $config->setParameter('debugpdo.logging.details.mem.enabled', true); + $allMethods = array( + 'PropelPDO::__construct', // logs connection opening + 'PropelPDO::__destruct', // logs connection close + 'PropelPDO::exec', // logs a query + 'PropelPDO::query', // logs a query + 'PropelPDO::beginTransaction', // logs a transaction begin + 'PropelPDO::commit', // logs a transaction commit + 'PropelPDO::rollBack', // logs a transaction rollBack (watch out for the capital 'B') + 'DebugPDOStatement::execute', // logs a query from a prepared statement + ); + $config->setParameter('debugpdo.logging.methods', $allMethods, false); + } + + /** + * @param LoggerInterface $logger A logger to forward non-query log lines to + * @param PropelPDO $conn Bound this collector to a connection only + */ + public function __construct(LoggerInterface $logger = null, PropelPDO $conn = null) + { + if ($conn) { + $conn->setLogger($this); + } else { + Propel::setLogger($this); + } + $this->logger = $logger; + $this->logQueriesToLogger = false; + } + + public function setLogQueriesToLogger($enable = true) + { + $this->logQueriesToLogger = $enable; + return $this; + } + + public function isLogQueriesToLogger() + { + return $this->logQueriesToLogger; + } + + public function emergency($m) + { + $this->log($m, Propel::LOG_EMERG); + } + + public function alert($m) + { + $this->log($m, Propel::LOG_ALERT); + } + + public function crit($m) + { + $this->log($m, Propel::LOG_CRIT); + } + + public function err($m) + { + $this->log($m, Propel::LOG_ERR); + } + + public function warning($m) + { + $this->log($m, Propel::LOG_WARNING); + } + + public function notice($m) + { + $this->log($m, Propel::LOG_NOTICE); + } + + public function info($m) + { + $this->log($m, Propel::LOG_INFO); + } + + public function debug($m) + { + $this->log($m, Propel::LOG_DEBUG); + } + + public function log($message, $severity = null) + { + if (strpos($message, 'DebugPDOStatement::execute') !== false) { + list($sql, $duration_str) = $this->parseAndLogSqlQuery($message); + if (!$this->logQueriesToLogger) { + return; + } + $message = "$sql ($duration_str)"; + } + + if ($this->logger !== null) { + $this->logger->log($this->convertLogLevel($severity), $message); + } + } + + /** + * Converts Propel log levels to PSR log levels + * + * @param int $level + * @return string + */ + protected function convertLogLevel($level) + { + $map = array( + Propel::LOG_EMERG => LogLevel::EMERGENCY, + Propel::LOG_ALERT => LogLevel::ALERT, + Propel::LOG_CRIT => LogLevel::CRITICAL, + Propel::LOG_ERR => LogLevel::ERROR, + Propel::LOG_WARNING => LogLevel::WARNING, + Propel::LOG_NOTICE => LogLevel::NOTICE, + Propel::LOG_DEBUG => LogLevel::DEBUG + ); + return $map[$level]; + } + + /** + * Parse a log line to extract query information + * + * @param string $message + */ + protected function parseAndLogSqlQuery($message) + { + $parts = explode('|', $message, 4); + $sql = trim($parts[3]); + + $duration = 0; + if (preg_match('/([0-9]+\.[0-9]+)/', $parts[1], $matches)) { + $duration = (float) $matches[1]; + } + + $memory = 0; + if (preg_match('/([0-9]+\.[0-9]+) ([A-Z]{1,2})/', $parts[2], $matches)) { + $memory = (float) $matches[1]; + if ($matches[2] == 'KB') { + $memory *= 1024; + } else if ($matches[2] == 'MB') { + $memory *= 1024 * 1024; + } + } + + $this->statements[] = array( + 'sql' => $sql, + 'is_success' => true, + 'duration' => $duration, + 'duration_str' => $this->formatDuration($duration), + 'memory' => $memory, + 'memory_str' => $this->formatBytes($memory) + ); + $this->accumulatedTime += $duration; + $this->peakMemory = max($this->peakMemory, $memory); + return array($sql, $this->formatDuration($duration)); + } + + public function collect() + { + return array( + 'nb_statements' => count($this->statements), + 'nb_failed_statements' => 0, + 'accumulated_duration' => $this->accumulatedTime, + 'accumulated_duration_str' => $this->formatDuration($this->accumulatedTime), + 'peak_memory_usage' => $this->peakMemory, + 'peak_memory_usage_str' => $this->formatBytes($this->peakMemory), + 'statements' => $this->statements + ); + } + + public function getName() + { + return 'propel'; + } + + public function getWidgets() + { + return array( + "propel" => array( + "icon" => "bolt", + "widget" => "PhpDebugBar.Widgets.SQLQueriesWidget", + "map" => "propel", + "default" => "[]" + ), + "propel:badge" => array( + "map" => "propel.nb_statements", + "default" => 0 + ) + ); + } + + public function getAssets() + { + return array( + 'css' => 'widgets/sqlqueries/widget.css', + 'js' => 'widgets/sqlqueries/widget.js' + ); + } +} diff --git a/src/core/libs/DebugBar/Bridge/SlimCollector.php b/src/core/libs/DebugBar/Bridge/SlimCollector.php new file mode 100755 index 0000000..be1caa6 --- /dev/null +++ b/src/core/libs/DebugBar/Bridge/SlimCollector.php @@ -0,0 +1,66 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Bridge; + +use DebugBar\DataCollector\MessagesCollector; +use Slim\Slim; +use Slim\Log; +use Psr\Log\LogLevel; + +/** + * Collects messages from a Slim logger + * + * http://slimframework.com + */ +class SlimCollector extends MessagesCollector +{ + protected $slim; + + protected $originalLogWriter; + + public function __construct(Slim $slim) + { + $this->slim = $slim; + if ($log = $slim->getLog()) { + $this->originalLogWriter = $log->getWriter(); + $log->setWriter($this); + $log->setEnabled(true); + } + } + + public function write($message, $level) + { + if ($this->originalLogWriter) { + $this->originalLogWriter->write($message, $level); + } + $this->addMessage($message, $this->getLevelName($level)); + } + + protected function getLevelName($level) + { + $map = array( + Log::EMERGENCY => LogLevel::EMERGENCY, + Log::ALERT => LogLevel::ALERT, + Log::CRITICAL => LogLevel::CRITICAL, + Log::ERROR => LogLevel::ERROR, + Log::WARN => LogLevel::WARNING, + Log::NOTICE => LogLevel::NOTICE, + Log::INFO => LogLevel::INFO, + Log::DEBUG => LogLevel::DEBUG + ); + return $map[$level]; + } + + public function getName() + { + return 'slim'; + } +} diff --git a/src/core/libs/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php b/src/core/libs/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php new file mode 100755 index 0000000..fdef79a --- /dev/null +++ b/src/core/libs/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php @@ -0,0 +1,44 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Bridge\SwiftMailer; + +use DebugBar\DataCollector\MessagesCollector; +use Swift_Mailer; +use Swift_Plugins_Logger; +use Swift_Plugins_LoggerPlugin; + +/** + * Collects log messages + * + * http://swiftmailer.org/ + */ +class SwiftLogCollector extends MessagesCollector implements Swift_Plugins_Logger +{ + public function __construct(Swift_Mailer $mailer) + { + $mailer->registerPlugin(new Swift_Plugins_LoggerPlugin($this)); + } + + public function add($entry) + { + $this->addMessage($entry); + } + + public function dump() + { + return implode(PHP_EOL, $this->_log); + } + + public function getName() + { + return 'swiftmailer_logs'; + } +} diff --git a/src/core/libs/DebugBar/Bridge/SwiftMailer/SwiftMailCollector.php b/src/core/libs/DebugBar/Bridge/SwiftMailer/SwiftMailCollector.php new file mode 100755 index 0000000..d143eff --- /dev/null +++ b/src/core/libs/DebugBar/Bridge/SwiftMailer/SwiftMailCollector.php @@ -0,0 +1,90 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Bridge\SwiftMailer; + +use DebugBar\DataCollector\DataCollector; +use DebugBar\DataCollector\Renderable; +use DebugBar\DataCollector\AssetProvider; +use Swift_Mailer; +use Swift_Plugins_MessageLogger; + +/** + * Collects data about sent mails + * + * http://swiftmailer.org/ + */ +class SwiftMailCollector extends DataCollector implements Renderable, AssetProvider +{ + protected $messagesLogger; + + public function __construct(Swift_Mailer $mailer) + { + $this->messagesLogger = new Swift_Plugins_MessageLogger(); + $mailer->registerPlugin($this->messagesLogger); + } + + public function collect() + { + $mails = array(); + foreach ($this->messagesLogger->getMessages() as $msg) { + $mails[] = array( + 'to' => $this->formatTo($msg->getTo()), + 'subject' => $msg->getSubject(), + 'headers' => $msg->getHeaders()->toString() + ); + } + return array( + 'count' => count($mails), + 'mails' => $mails + ); + } + + protected function formatTo($to) + { + if (!$to) return ''; + + $f = array(); + foreach ($to as $k => $v) { + $f[] = (empty($v) ? '' : "$v ") . "<$k>"; + } + return implode(', ', $f); + } + + public function getName() + { + return 'swiftmailer_mails'; + } + + public function getWidgets() + { + return array( + 'emails' => array( + 'icon' => 'inbox', + 'widget' => 'PhpDebugBar.Widgets.MailsWidget', + 'map' => 'swiftmailer_mails.mails', + 'default' => '[]', + 'title' => 'Mails' + ), + 'emails:badge' => array( + 'map' => 'swiftmailer_mails.count', + 'default' => 'null' + ) + ); + } + + public function getAssets() + { + return array( + 'css' => 'widgets/mails/widget.css', + 'js' => 'widgets/mails/widget.js' + ); + } +} diff --git a/src/core/libs/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php b/src/core/libs/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php new file mode 100755 index 0000000..539251f --- /dev/null +++ b/src/core/libs/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php @@ -0,0 +1,412 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Bridge\Twig; + +use Twig_Environment; +use Twig_LexerInterface; +use Twig_ParserInterface; +use Twig_TokenStream; +use Twig_CompilerInterface; +use Twig_NodeInterface; +use Twig_LoaderInterface; +use Twig_ExtensionInterface; +use Twig_TokenParserInterface; +use Twig_NodeVisitorInterface; +use DebugBar\DataCollector\TimeDataCollector; + +/** + * Wrapped a Twig Environment to provide profiling features + */ +class TraceableTwigEnvironment extends Twig_Environment +{ + protected $twig; + + protected $renderedTemplates = array(); + + protected $timeDataCollector; + + /** + * @param Twig_Environment $twig + * @param TimeDataCollector $timeDataCollector + */ + public function __construct(Twig_Environment $twig, TimeDataCollector $timeDataCollector = null) + { + $this->twig = $twig; + $this->timeDataCollector = $timeDataCollector; + } + + public function getRenderedTemplates() + { + return $this->renderedTemplates; + } + + public function addRenderedTemplate(array $info) + { + $this->renderedTemplates[] = $info; + } + + public function getTimeDataCollector() + { + return $this->timeDataCollector; + } + + public function getBaseTemplateClass() + { + return $this->twig->getBaseTemplateClass(); + } + + public function setBaseTemplateClass($class) + { + $this->twig->setBaseTemplateClass($class); + } + + public function enableDebug() + { + $this->twig->enableDebug(); + } + + public function disableDebug() + { + $this->twig->disableDebug(); + } + + public function isDebug() + { + return $this->twig->isDebug(); + } + + public function enableAutoReload() + { + $this->twig->enableAutoReload(); + } + + public function disableAutoReload() + { + $this->twig->disableAutoReload(); + } + + public function isAutoReload() + { + return $this->twig->isAutoReload(); + } + + public function enableStrictVariables() + { + $this->twig->enableStrictVariables(); + } + + public function disableStrictVariables() + { + $this->twig->disableStrictVariables(); + } + + public function isStrictVariables() + { + return $this->twig->isStrictVariables(); + } + + public function getCache() + { + return $this->twig->getCache(); + } + + public function setCache($cache) + { + $this->twig->setCache($cache); + } + + public function getCacheFilename($name) + { + return $this->twig->getCacheFilename($name); + } + + public function getTemplateClass($name, $index = null) + { + return $this->twig->getTemplateClass($name, $index); + } + + public function getTemplateClassPrefix() + { + return $this->twig->getTemplateClassPrefix(); + } + + public function render($name, array $context = array()) + { + return $this->loadTemplate($name)->render($context); + } + + public function display($name, array $context = array()) + { + $this->loadTemplate($name)->display($context); + } + + public function loadTemplate($name, $index = null) + { + $cls = $this->twig->getTemplateClass($name, $index); + + if (isset($this->twig->loadedTemplates[$cls])) { + return $this->twig->loadedTemplates[$cls]; + } + + if (!class_exists($cls, false)) { + if (false === $cache = $this->getCacheFilename($name)) { + eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name)); + } else { + if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) { + $this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name)); + } + + require_once $cache; + } + } + + if (!$this->twig->runtimeInitialized) { + $this->initRuntime(); + } + + return $this->twig->loadedTemplates[$cls] = new TraceableTwigTemplate($this, new $cls($this)); + } + + public function isTemplateFresh($name, $time) + { + return $this->twig->isTemplateFresh($name, $time); + } + + public function resolveTemplate($names) + { + return $this->twig->resolveTemplate($names); + } + + public function clearTemplateCache() + { + $this->twig->clearTemplateCache(); + } + + public function clearCacheFiles() + { + $this->twig->clearCacheFiles(); + } + + public function getLexer() + { + return $this->twig->getLexer(); + } + + public function setLexer(Twig_LexerInterface $lexer) + { + $this->twig->setLexer($lexer); + } + + public function tokenize($source, $name = null) + { + return $this->twig->tokenize($source, $name); + } + + public function getParser() + { + return $this->twig->getParser(); + } + + public function setParser(Twig_ParserInterface $parser) + { + $this->twig->setParser($parser); + } + + public function parse(Twig_TokenStream $tokens) + { + return $this->twig->parse($tokens); + } + + public function getCompiler() + { + return $this->twig->getCompiler(); + } + + public function setCompiler(Twig_CompilerInterface $compiler) + { + $this->twig->setCompiler($compiler); + } + + public function compile(Twig_NodeInterface $node) + { + return $this->twig->compile($node); + } + + public function compileSource($source, $name = null) + { + return $this->twig->compileSource($source, $name); + } + + public function setLoader(Twig_LoaderInterface $loader) + { + $this->twig->setLoader($loader); + } + + public function getLoader() + { + return $this->twig->getLoader(); + } + + public function setCharset($charset) + { + $this->twig->setCharset($charset); + } + + public function getCharset() + { + return $this->twig->getCharset(); + } + + public function initRuntime() + { + $this->twig->initRuntime(); + } + + public function hasExtension($name) + { + return $this->twig->hasExtension($name); + } + + public function getExtension($name) + { + return $this->twig->getExtension($name); + } + + public function addExtension(Twig_ExtensionInterface $extension) + { + $this->twig->addExtension($extension); + } + + public function removeExtension($name) + { + $this->twig->removeExtension($name); + } + + public function setExtensions(array $extensions) + { + $this->twig->setExtensions($extensions); + } + + public function getExtensions() + { + return $this->twig->getExtensions(); + } + + public function addTokenParser(Twig_TokenParserInterface $parser) + { + $this->twig->addTokenParser($parser); + } + + public function getTokenParsers() + { + return $this->twig->getTokenParsers(); + } + + public function getTags() + { + return $this->twig->getTags(); + } + + public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) + { + $this->twig->addNodeVisitor($visitor); + } + + public function getNodeVisitors() + { + return $this->twig->getNodeVisitors(); + } + + public function addFilter($name, $filter = null) + { + $this->twig->addFilter($name, $filter); + } + + public function getFilter($name) + { + return $this->twig->getFilter($name); + } + + public function registerUndefinedFilterCallback($callable) + { + $this->twig->registerUndefinedFilterCallback($callable); + } + + public function getFilters() + { + return $this->twig->getFilters(); + } + + public function addTest($name, $test = null) + { + $this->twig->addTest($name, $test); + } + + public function getTests() + { + return $this->twig->getTests(); + } + + public function getTest($name) + { + return $this->twig->getTest($name); + } + + public function addFunction($name, $function = null) + { + $this->twig->addFunction($name, $function); + } + + public function getFunction($name) + { + return $this->twig->getFunction($name); + } + + public function registerUndefinedFunctionCallback($callable) + { + $this->twig->registerUndefinedFunctionCallback($callable); + } + + public function getFunctions() + { + return $this->twig->getFunctions(); + } + + public function addGlobal($name, $value) + { + $this->twig->addGlobal($name, $value); + } + + public function getGlobals() + { + return $this->twig->getGlobals(); + } + + public function mergeGlobals(array $context) + { + return $this->twig->mergeGlobals($context); + } + + public function getUnaryOperators() + { + return $this->twig->getUnaryOperators(); + } + + public function getBinaryOperators() + { + return $this->twig->getBinaryOperators(); + } + + public function computeAlternatives($name, $items) + { + return $this->twig->computeAlternatives($name, $items); + } +} diff --git a/src/core/libs/DebugBar/Bridge/Twig/TraceableTwigTemplate.php b/src/core/libs/DebugBar/Bridge/Twig/TraceableTwigTemplate.php new file mode 100755 index 0000000..2698c8b --- /dev/null +++ b/src/core/libs/DebugBar/Bridge/Twig/TraceableTwigTemplate.php @@ -0,0 +1,126 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Bridge\Twig; + +use Twig_TemplateInterface; +use Twig_Template; + +/** + * Wraps a Twig_Template to add profiling features + */ +class TraceableTwigTemplate implements Twig_TemplateInterface +{ + protected $template; + + /** + * @param TraceableTwigEnvironment $env + * @param Twig_Template $template + */ + public function __construct(TraceableTwigEnvironment $env, Twig_Template $template) + { + $this->env = $env; + $this->template = $template; + } + + public function getTemplateName() + { + return $this->template->getTemplateName(); + } + + public function getEnvironment() + { + return $this->template->getEnvironment(); + } + + public function getParent(array $context) + { + return $this->template->getParent($context); + } + + public function isTraitable() + { + return $this->template->isTraitable(); + } + + public function displayParentBlock($name, array $context, array $blocks = array()) + { + $this->template->displayParentBlock($name, $context, $blocks); + } + + public function displayBlock($name, array $context, array $blocks = array()) + { + $this->template->displayBlock($name, $context, $blocks); + } + + public function renderParentBlock($name, array $context, array $blocks = array()) + { + return $this->template->renderParentBlock($name, $context, $blocks); + } + + public function renderBlock($name, array $context, array $blocks = array()) + { + return $this->template->renderBlock($name, $context, $blocks); + } + + public function hasBlock($name) + { + return $this->template->hasBlock($name); + } + + public function getBlockNames() + { + return $this->template->getBlockNames(); + } + + public function getBlocks() + { + return $this->template->getBlocks(); + } + + public function display(array $context, array $blocks = array()) + { + $start = microtime(true); + $this->template->display($context, $blocks); + $end = microtime(true); + + if ($timeDataCollector = $this->env->getTimeDataCollector()) { + $name = sprintf("twig.render(%s)", $this->template->getTemplateName()); + $timeDataCollector->addMeasure($name, $start, $end); + } + + $this->env->addRenderedTemplate(array( + 'name' => $this->template->getTemplateName(), + 'render_time' => $end - $start + )); + } + + public function render(array $context) + { + $level = ob_get_level(); + ob_start(); + try { + $this->display($context); + } catch (Exception $e) { + while (ob_get_level() > $level) { + ob_end_clean(); + } + + throw $e; + } + + return ob_get_clean(); + } + + public static function clearCache() + { + $this->template->clearCache(); + } +} diff --git a/src/core/libs/DebugBar/Bridge/Twig/TwigCollector.php b/src/core/libs/DebugBar/Bridge/Twig/TwigCollector.php new file mode 100755 index 0000000..e07cbf8 --- /dev/null +++ b/src/core/libs/DebugBar/Bridge/Twig/TwigCollector.php @@ -0,0 +1,87 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Bridge\Twig; + +use DebugBar\DataCollector\DataCollector; +use DebugBar\DataCollector\Renderable; +use DebugBar\DataCollector\AssetProvider; + +/** + * Collects data about rendered templates + * + * http://twig.sensiolabs.org/ + * + * Your Twig_Environment object needs to be wrapped in a + * TraceableTwigEnvironment object + * + * <code> + * $env = new TraceableTwigEnvironment(new Twig_Environment($loader)); + * $debugbar->addCollector(new TwigCollector($env)); + * </code> + */ +class TwigCollector extends DataCollector implements Renderable, AssetProvider +{ + public function __construct(TraceableTwigEnvironment $twig) + { + $this->twig = $twig; + } + + public function collect() + { + $templates = array(); + $accuRenderTime = 0; + + foreach ($this->twig->getRenderedTemplates() as $tpl) { + $accuRenderTime += $tpl['render_time']; + $templates[] = array( + 'name' => $tpl['name'], + 'render_time' => $tpl['render_time'], + 'render_time_str' => $this->formatDuration($tpl['render_time']) + ); + } + + return array( + 'nb_templates' => count($templates), + 'templates' => $templates, + 'accumulated_render_time' => $accuRenderTime, + 'accumulated_render_time_str' => $this->formatDuration($accuRenderTime) + ); + } + + public function getName() + { + return 'twig'; + } + + public function getWidgets() + { + return array( + 'twig' => array( + 'icon' => 'leaf', + 'widget' => 'PhpDebugBar.Widgets.TemplatesWidget', + 'map' => 'twig', + 'default' => '[]' + ), + 'twig:badge' => array( + 'map' => 'twig.nb_templates', + 'default' => 0 + ) + ); + } + + public function getAssets() + { + return array( + 'css' => 'widgets/templates/widget.css', + 'js' => 'widgets/templates/widget.js' + ); + } +} diff --git a/src/core/libs/DebugBar/DataCollector/AggregatedCollector.php b/src/core/libs/DebugBar/DataCollector/AggregatedCollector.php new file mode 100755 index 0000000..d471cdd --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/AggregatedCollector.php @@ -0,0 +1,166 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +use ArrayAccess; +use DebugBar\DebugBarException; + +/** + * Aggregates data from multiple collectors + * + * <code> + * $aggcollector = new AggregateCollector('foobar'); + * $aggcollector->addCollector(new MessagesCollector('msg1')); + * $aggcollector->addCollector(new MessagesCollector('msg2')); + * $aggcollector['msg1']->addMessage('hello world'); + * </code> + */ +class AggregatedCollector implements DataCollectorInterface, ArrayAccess +{ + protected $name; + + protected $mergeProperty; + + protected $sort; + + protected $collectors = array(); + + /** + * @param string $name + * @param string $mergeProperty + * @param boolean $sort + */ + public function __construct($name, $mergeProperty = null, $sort = false) + { + $this->name = $name; + $this->mergeProperty = $mergeProperty; + $this->sort = $sort; + } + + /** + * @param DataCollectorInterface $collector + */ + public function addCollector(DataCollectorInterface $collector) + { + $this->collectors[$collector->getName()] = $collector; + } + + /** + * @return array + */ + public function getCollectors() + { + return $this->collectors; + } + + /** + * Merge data from one of the key/value pair of the collected data + * + * @param string $property + */ + public function setMergeProperty($property) + { + $this->mergeProperty = $property; + } + + /** + * @return string + */ + public function getMergeProperty() + { + return $this->mergeProperty; + } + + /** + * Sorts the collected data + * + * If true, sorts using sort() + * If it is a string, sorts the data using the value from a key/value pair of the array + * + * @param bool|string $sort + */ + public function setSort($sort) + { + $this->sort = $sort; + } + + /** + * @return bool|string + */ + public function getSort() + { + return $this->sort; + } + + public function collect() + { + $aggregate = array(); + foreach ($this->collectors as $collector) { + $data = $collector->collect(); + if ($this->mergeProperty !== null) { + $data = $data[$this->mergeProperty]; + } + $aggregate = array_merge($aggregate, $data); + } + + return $this->sort($aggregate); + } + + /** + * Sorts the collected data + * + * @param array $data + * @return array + */ + protected function sort($data) + { + if (is_string($this->sort)) { + $p = $this->sort; + usort($data, function($a, $b) use ($p) { + if ($a[$p] == $b[$p]) { + return 0; + } + return $a[$p] < $b[$p] ? -1 : 1; + }); + } else if ($this->sort === true) { + sort($data); + } + return $data; + } + + public function getName() + { + return $this->name; + } + + // -------------------------------------------- + // ArrayAccess implementation + + public function offsetSet($key, $value) + { + throw new DebugBarException("AggregatedCollector[] is read-only"); + } + + public function offsetGet($key) + { + return $this->collectors[$key]; + } + + public function offsetExists($key) + { + return isset($this->collectors[$key]); + } + + public function offsetUnset($key) + { + throw new DebugBarException("AggregatedCollector[] is read-only"); + } +} diff --git a/src/core/libs/DebugBar/DataCollector/AssetProvider.php b/src/core/libs/DebugBar/DataCollector/AssetProvider.php new file mode 100755 index 0000000..6910f73 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/AssetProvider.php @@ -0,0 +1,28 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +/** + * Indicates that a DataCollector provides some assets + */ +interface AssetProvider +{ + /** + * Returns an array with the following keys: + * - base_path + * - base_url + * - css: an array of filenames + * - js: an array of filenames + * + * @return array + */ + function getAssets(); +} diff --git a/src/core/libs/DebugBar/DataCollector/ConfigCollector.php b/src/core/libs/DebugBar/DataCollector/ConfigCollector.php new file mode 100755 index 0000000..7b4ac90 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/ConfigCollector.php @@ -0,0 +1,71 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +/** + * Collects array data + */ +class ConfigCollector extends DataCollector implements Renderable +{ + protected $name; + + protected $data; + + /** + * @param array $data + * @param string $name + */ + public function __construct(array $data = array(), $name = 'config') + { + $this->name = $name; + $this->data = $data; + } + + /** + * Sets the data + * + * @param array $data + */ + public function setData(array $data) + { + $this->data = $data; + } + + public function collect() + { + $data = array(); + foreach ($this->data as $k => $v) { + if (!is_string($v)) { + $v = $this->getDataFormatter()->formatVar($v); + } + $data[$k] = $v; + } + return $data; + } + + public function getName() + { + return $this->name; + } + + public function getWidgets() + { + $name = $this->getName(); + return array( + "$name" => array( + "icon" => "gear", + "widget" => "PhpDebugBar.Widgets.VariableListWidget", + "map" => "$name", + "default" => "{}" + ) + ); + } +} diff --git a/src/core/libs/DebugBar/DataCollector/DataCollector.php b/src/core/libs/DebugBar/DataCollector/DataCollector.php new file mode 100755 index 0000000..789e767 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/DataCollector.php @@ -0,0 +1,90 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +use DebugBar\DataFormatter\DataFormatterInterface; +use DebugBar\DataFormatter\DataFormatter; + +/** + * Abstract class for data collectors + */ +abstract class DataCollector implements DataCollectorInterface +{ + private static $defaultDataFormatter; + + protected $dataFormater; + + /** + * Sets the default data formater instance used by all collectors subclassing this class + * + * @param DataFormatterInterface $formater + */ + public static function setDefaultDataFormatter(DataFormatterInterface $formater) + { + self::$defaultDataFormatter = $formater; + } + + /** + * Returns the default data formater + * + * @return DataFormatterInterface + */ + public static function getDefaultDataFormatter() + { + if (self::$defaultDataFormatter === null) { + self::$defaultDataFormatter = new DataFormatter(); + } + return self::$defaultDataFormatter; + } + + /** + * Sets the data formater instance used by this collector + * + * @param DataFormatterInterface $formater + */ + public function setDataFormatter(DataFormatterInterface $formater) + { + $this->dataFormater = $formater; + return $this; + } + + public function getDataFormatter() + { + if ($this->dataFormater === null) { + $this->dataFormater = self::getDefaultDataFormatter(); + } + return $this->dataFormater; + } + + /** + * @deprecated + */ + public function formatVar($var) + { + return $this->getDataFormatter()->formatVar($var); + } + + /** + * @deprecated + */ + public function formatDuration($seconds) + { + return $this->getDataFormatter()->formatDuration($seconds); + } + + /** + * @deprecated + */ + public function formatBytes($size, $precision = 2) + { + return $this->getDataFormatter()->formatBytes($size, $precision); + } +} diff --git a/src/core/libs/DebugBar/DataCollector/DataCollectorInterface.php b/src/core/libs/DebugBar/DataCollector/DataCollectorInterface.php new file mode 100755 index 0000000..b7f234c --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/DataCollectorInterface.php @@ -0,0 +1,31 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +/** + * DataCollector Interface + */ +interface DataCollectorInterface +{ + /** + * Called by the DebugBar when data needs to be collected + * + * @return array Collected data + */ + function collect(); + + /** + * Returns the unique name of the collector + * + * @return string + */ + function getName(); +} diff --git a/src/core/libs/DebugBar/DataCollector/ExceptionsCollector.php b/src/core/libs/DebugBar/DataCollector/ExceptionsCollector.php new file mode 100755 index 0000000..8bf08d4 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/ExceptionsCollector.php @@ -0,0 +1,111 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +use Exception; + +/** + * Collects info about exceptions + */ +class ExceptionsCollector extends DataCollector implements Renderable +{ + protected $exceptions = array(); + protected $chainExceptions = false; + + /** + * Adds an exception to be profiled in the debug bar + * + * @param Exception $e + */ + public function addException(Exception $e) + { + $this->exceptions[] = $e; + if ($this->chainExceptions && $previous = $e->getPrevious()) { + $this->addException($previous); + } + } + + /** + * Configure whether or not all chained exceptions should be shown. + * + * @param bool $chainExceptions + */ + public function setChainExceptions($chainExceptions = true) + { + $this->chainExceptions = $chainExceptions; + } + + /** + * Returns the list of exceptions being profiled + * + * @return array[Exception] + */ + public function getExceptions() + { + return $this->exceptions; + } + + public function collect() + { + return array( + 'count' => count($this->exceptions), + 'exceptions' => array_map(array($this, 'formatExceptionData'), $this->exceptions) + ); + } + + /** + * Returns exception data as an array + * + * @param Exception $e + * @return array + */ + public function formatExceptionData(Exception $e) + { + $filePath = $e->getFile(); + if ($filePath && file_exists($filePath)) { + $lines = file($filePath); + $start = $e->getLine() - 4; + $lines = array_slice($lines, $start < 0 ? 0 : $start, 7); + } else { + $lines = array("Cannot open the file ($filePath) in which the exception occurred "); + } + + return array( + 'type' => get_class($e), + 'message' => $e->getMessage(), + 'code' => $e->getCode(), + 'file' => $filePath, + 'line' => $e->getLine(), + 'surrounding_lines' => $lines + ); + } + + public function getName() + { + return 'exceptions'; + } + + public function getWidgets() + { + return array( + 'exceptions' => array( + 'icon' => 'bug', + 'widget' => 'PhpDebugBar.Widgets.ExceptionsWidget', + 'map' => 'exceptions.exceptions', + 'default' => '[]' + ), + 'exceptions:badge' => array( + 'map' => 'exceptions.count', + 'default' => 'null' + ) + ); + } +} diff --git a/src/core/libs/DebugBar/DataCollector/LocalizationCollector.php b/src/core/libs/DebugBar/DataCollector/LocalizationCollector.php new file mode 100755 index 0000000..33b7616 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/LocalizationCollector.php @@ -0,0 +1,66 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +use Exception; + +/** + * Collects info about the current localization state + */ +class LocalizationCollector extends DataCollector implements Renderable +{ + /** + * Get the current locale + * + * @return string + */ + public function getLocale() + { + return setlocale(LC_ALL, 0); + } + + /** + * Get the current translations domain + * + * @return string + */ + public function getDomain() + { + return textdomain(); + } + + public function collect() + { + return array( + 'locale' => $this->getLocale(), + 'domain' => $this->getDomain(), + ); + } + + public function getName() + { + return 'localization'; + } + + public function getWidgets() + { + return array( + 'domain' => array( + 'icon' => 'bookmark', + 'map' => 'localization.domain', + ), + 'locale' => array( + 'icon' => 'flag', + 'map' => 'localization.locale', + ) + ); + } +} diff --git a/src/core/libs/DebugBar/DataCollector/MemoryCollector.php b/src/core/libs/DebugBar/DataCollector/MemoryCollector.php new file mode 100755 index 0000000..1a27c40 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/MemoryCollector.php @@ -0,0 +1,63 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +/** + * Collects info about memory usage + */ +class MemoryCollector extends DataCollector implements Renderable +{ + protected $peakUsage = 0; + + /** + * Returns the peak memory usage + * + * @return integer + */ + public function getPeakUsage() + { + return $this->peakUsage; + } + + /** + * Updates the peak memory usage value + */ + public function updatePeakUsage() + { + $this->peakUsage = memory_get_peak_usage(true); + } + + public function collect() + { + $this->updatePeakUsage(); + return array( + 'peak_usage' => $this->peakUsage, + 'peak_usage_str' => $this->getDataFormatter()->formatBytes($this->peakUsage) + ); + } + + public function getName() + { + return 'memory'; + } + + public function getWidgets() + { + return array( + "memory" => array( + "icon" => "cogs", + "tooltip" => "Memory Usage", + "map" => "memory.peak_usage_str", + "default" => "'0B'" + ) + ); + } +} diff --git a/src/core/libs/DebugBar/DataCollector/MessagesAggregateInterface.php b/src/core/libs/DebugBar/DataCollector/MessagesAggregateInterface.php new file mode 100755 index 0000000..1e2d4d2 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/MessagesAggregateInterface.php @@ -0,0 +1,21 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +interface MessagesAggregateInterface +{ + /** + * Returns collected messages + * + * @return array + */ + public function getMessages(); +} diff --git a/src/core/libs/DebugBar/DataCollector/MessagesCollector.php b/src/core/libs/DebugBar/DataCollector/MessagesCollector.php new file mode 100755 index 0000000..249b5cc --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/MessagesCollector.php @@ -0,0 +1,152 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +use Psr\Log\AbstractLogger; + +/** + * Provides a way to log messages + */ +class MessagesCollector extends AbstractLogger implements DataCollectorInterface, MessagesAggregateInterface, Renderable +{ + protected $name; + + protected $messages = array(); + + protected $aggregates = array(); + + protected $dataFormater; + + /** + * @param string $name + */ + public function __construct($name = 'messages') + { + $this->name = $name; + } + + /** + * Sets the data formater instance used by this collector + * + * @param DataFormatterInterface $formater + */ + public function setDataFormatter(DataFormatterInterface $formater) + { + $this->dataFormater = $formater; + return $this; + } + + public function getDataFormatter() + { + if ($this->dataFormater === null) { + $this->dataFormater = DataCollector::getDefaultDataFormatter(); + } + return $this->dataFormater; + } + + /** + * Adds a message + * + * A message can be anything from an object to a string + * + * @param mixed $message + * @param string $label + */ + public function addMessage($message, $label = 'info', $isString = true) + { + if (!is_string($message)) { + $message = $this->getDataFormatter()->formatVar($message); + $isString = false; + } + $this->messages[] = array( + 'message' => $message, + 'is_string' => $isString, + 'label' => $label, + 'time' => microtime(true) + ); + } + + /** + * Aggregates messages from other collectors + * + * @param MessagesAggregateInterface $messages + */ + public function aggregate(MessagesAggregateInterface $messages) + { + $this->aggregates[] = $messages; + } + + public function getMessages() + { + $messages = $this->messages; + foreach ($this->aggregates as $collector) { + $msgs = array_map(function($m) use ($collector) { + $m['collector'] = $collector->getName(); + return $m; + }, $collector->getMessages()); + $messages = array_merge($messages, $msgs); + } + + // sort messages by their timestamp + usort($messages, function($a, $b) { + if ($a['time'] === $b['time']) { + return 0; + } + return $a['time'] < $b['time'] ? -1 : 1; + }); + + return $messages; + } + + public function log($level, $message, array $context = array()) + { + $this->addMessage($message, $level); + } + + /** + * Deletes all messages + */ + public function clear() + { + $this->messages = array(); + } + + public function collect() + { + $messages = $this->getMessages(); + return array( + 'count' => count($messages), + 'messages' => $messages + ); + } + + public function getName() + { + return $this->name; + } + + public function getWidgets() + { + $name = $this->getName(); + return array( + "$name" => array( + 'icon' => 'list-alt', + "widget" => "PhpDebugBar.Widgets.MessagesWidget", + "map" => "$name.messages", + "default" => "[]" + ), + "$name:badge" => array( + "map" => "$name.count", + "default" => "null" + ) + ); + } +} diff --git a/src/core/libs/DebugBar/DataCollector/PDO/PDOCollector.php b/src/core/libs/DebugBar/DataCollector/PDO/PDOCollector.php new file mode 100755 index 0000000..0c5b018 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/PDO/PDOCollector.php @@ -0,0 +1,182 @@ +<?php + +namespace DebugBar\DataCollector\PDO; + +use DebugBar\DataCollector\DataCollector; +use DebugBar\DataCollector\Renderable; +use DebugBar\DataCollector\AssetProvider; +use DebugBar\DataCollector\TimeDataCollector; + +/** + * Collects data about SQL statements executed with PDO + */ +class PDOCollector extends DataCollector implements Renderable, AssetProvider +{ + protected $connections = array(); + + protected $timeCollector; + + protected $renderSqlWithParams = false; + + protected $sqlQuotationChar = '<>'; + + /** + * @param TraceablePDO $pdo + * @param TimeDataCollector $timeCollector + */ + public function __construct(TraceablePDO $pdo = null, TimeDataCollector $timeCollector = null) + { + $this->timeCollector = $timeCollector; + if ($pdo !== null) { + $this->addConnection($pdo, 'default'); + } + } + + /** + * Renders the SQL of traced statements with params embeded + * + * @param boolean $enabled + */ + public function setRenderSqlWithParams($enabled = true, $quotationChar = '<>') + { + $this->renderSqlWithParams = $enabled; + $this->sqlQuotationChar = $quotationChar; + } + + public function isSqlRenderedWithParams() + { + return $this->renderSqlWithParams; + } + + public function getSqlQuotationChar() + { + return $this->sqlQuotationChar; + } + + /** + * Adds a new PDO instance to be collector + * + * @param TraceablePDO $pdo + * @param string $name Optional connection name + */ + public function addConnection(TraceablePDO $pdo, $name = null) + { + if ($name === null) { + $name = spl_object_hash($pdo); + } + $this->connections[$name] = $pdo; + } + + /** + * Returns PDO instances to be collected + * + * @return array + */ + public function getConnections() + { + return $this->connections; + } + + public function collect() + { + $data = array( + 'nb_statements' => 0, + 'nb_failed_statements' => 0, + 'accumulated_duration' => 0, + 'memory_usage' => 0, + 'peak_memory_usage' => 0, + 'statements' => array() + ); + + foreach ($this->connections as $name => $pdo) { + $pdodata = $this->collectPDO($pdo, $this->timeCollector); + $data['nb_statements'] += $pdodata['nb_statements']; + $data['nb_failed_statements'] += $pdodata['nb_failed_statements']; + $data['accumulated_duration'] += $pdodata['accumulated_duration']; + $data['memory_usage'] += $pdodata['memory_usage']; + $data['peak_memory_usage'] = max($data['peak_memory_usage'], $pdodata['peak_memory_usage']); + $data['statements'] = array_merge($data['statements'], + array_map(function($s) use ($name) { $s['connection'] = $name; return $s; }, $pdodata['statements'])); + } + + $data['accumulated_duration_str'] = $this->getDataFormatter()->formatDuration($data['accumulated_duration']); + $data['memory_usage_str'] = $this->getDataFormatter()->formatBytes($data['memory_usage']); + $data['peak_memory_usage_str'] = $this->getDataFormatter()->formatBytes($data['peak_memory_usage']); + + return $data; + } + + /** + * Collects data from a single TraceablePDO instance + * + * @param TraceablePDO $pdo + * @param TimeDataCollector $timeCollector + * @return array + */ + protected function collectPDO(TraceablePDO $pdo, TimeDataCollector $timeCollector = null) + { + $stmts = array(); + foreach ($pdo->getExecutedStatements() as $stmt) { + $stmts[] = array( + 'sql' => $this->renderSqlWithParams ? $stmt->getSqlWithParams($this->sqlQuotationChar) : $stmt->getSql(), + 'row_count' => $stmt->getRowCount(), + 'stmt_id' => $stmt->getPreparedId(), + 'prepared_stmt' => $stmt->getSql(), + 'params' => (object) $stmt->getParameters(), + 'duration' => $stmt->getDuration(), + 'duration_str' => $this->getDataFormatter()->formatDuration($stmt->getDuration()), + 'memory' => $stmt->getMemoryUsage(), + 'memory_str' => $this->getDataFormatter()->formatBytes($stmt->getMemoryUsage()), + 'end_memory' => $stmt->getEndMemory(), + 'end_memory_str' => $this->getDataFormatter()->formatBytes($stmt->getEndMemory()), + 'is_success' => $stmt->isSuccess(), + 'error_code' => $stmt->getErrorCode(), + 'error_message' => $stmt->getErrorMessage() + ); + if ($timeCollector !== null) { + $timeCollector->addMeasure($stmt->getSql(), $stmt->getStartTime(), $stmt->getEndTime()); + } + } + + return array( + 'nb_statements' => count($stmts), + 'nb_failed_statements' => count($pdo->getFailedExecutedStatements()), + 'accumulated_duration' => $pdo->getAccumulatedStatementsDuration(), + 'accumulated_duration_str' => $this->getDataFormatter()->formatDuration($pdo->getAccumulatedStatementsDuration()), + 'memory_usage' => $pdo->getMemoryUsage(), + 'memory_usage_str' => $this->getDataFormatter()->formatBytes($pdo->getPeakMemoryUsage()), + 'peak_memory_usage' => $pdo->getPeakMemoryUsage(), + 'peak_memory_usage_str' => $this->getDataFormatter()->formatBytes($pdo->getPeakMemoryUsage()), + 'statements' => $stmts + ); + } + + public function getName() + { + return 'pdo'; + } + + public function getWidgets() + { + return array( + "database" => array( + "icon" => "inbox", + "widget" => "PhpDebugBar.Widgets.SQLQueriesWidget", + "map" => "pdo", + "default" => "[]" + ), + "database:badge" => array( + "map" => "pdo.nb_statements", + "default" => 0 + ) + ); + } + + public function getAssets() + { + return array( + 'css' => 'widgets/sqlqueries/widget.css', + 'js' => 'widgets/sqlqueries/widget.js' + ); + } +} diff --git a/src/core/libs/DebugBar/DataCollector/PDO/TraceablePDO.php b/src/core/libs/DebugBar/DataCollector/PDO/TraceablePDO.php new file mode 100755 index 0000000..70ce91e --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/PDO/TraceablePDO.php @@ -0,0 +1,196 @@ +<?php + +namespace DebugBar\DataCollector\PDO; + +use PDO; +use PDOException; + +/** + * A PDO proxy which traces statements + */ +class TraceablePDO extends PDO +{ + protected $pdo; + + protected $executedStatements = array(); + + public function __construct(PDO $pdo) + { + $this->pdo = $pdo; + $this->pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DebugBar\DataCollector\PDO\TraceablePDOStatement', array($this))); + } + + public function beginTransaction() + { + return $this->pdo->beginTransaction(); + } + + public function commit() + { + return $this->pdo->commit(); + } + + public function errorCode() + { + return $this->pdo->errorCode(); + } + + public function errorInfo() + { + return $this->pdo->errorInfo(); + } + + public function exec($sql) + { + return $this->profileCall('exec', $sql, func_get_args()); + } + + public function getAttribute($attr) + { + return $this->pdo->getAttribute($attr); + } + + public function inTransaction() + { + return $this->pdo->inTransaction(); + } + + public function lastInsertId($name = null) + { + return $this->pdo->lastInsertId($name); + } + + public function prepare($sql, $driver_options = array()) + { + return $this->pdo->prepare($sql, $driver_options); + } + + public function query($sql) + { + return $this->profileCall('query', $sql, func_get_args()); + } + + public function quote($expr, $parameter_type = PDO::PARAM_STR) + { + return $this->pdo->quote($expr, $parameter_type); + } + + public function rollBack() + { + return $this->pdo->rollBack(); + } + + public function setAttribute($attr, $value) + { + return $this->pdo->setAttribute($attr, $value); + } + + /** + * Profiles a call to a PDO method + * + * @param string $method + * @param string $sql + * @param array $args + * @return mixed The result of the call + */ + protected function profileCall($method, $sql, array $args) + { + $trace = new TracedStatement($sql); + $trace->start(); + + $ex = null; + try { + $result = call_user_func_array(array($this->pdo, $method), $args); + } catch (PDOException $e) { + $ex = $e; + } + + if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) !== PDO::ERRMODE_EXCEPTION && $result === false) { + $error = $this->pdo->errorInfo(); + $ex = new PDOException($error[2], $error[0]); + } + + $trace->end($ex); + $this->addExecutedStatement($trace); + + if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) === PDO::ERRMODE_EXCEPTION && $ex !== null) { + throw $ex; + } + return $result; + } + + /** + * Adds an executed TracedStatement + * + * @param TracedStatement $stmt + */ + public function addExecutedStatement(TracedStatement $stmt) + { + $this->executedStatements[] = $stmt; + } + + /** + * Returns the accumulated execution time of statements + * + * @return int + */ + public function getAccumulatedStatementsDuration() + { + return array_reduce($this->executedStatements, function($v, $s) { return $v + $s->getDuration(); }); + } + + /** + * Returns the peak memory usage while performing statements + * + * @return int + */ + public function getMemoryUsage() + { + return array_reduce($this->executedStatements, function($v, $s) { return $v + $s->getMemoryUsage(); }); + } + + /** + * Returns the peak memory usage while performing statements + * + * @return int + */ + public function getPeakMemoryUsage() + { + return array_reduce($this->executedStatements, function($v, $s) { $m = $s->getEndMemory(); return $m > $v ? $m : $v; }); + } + + /** + * Returns the list of executed statements as TracedStatement objects + * + * @return array + */ + public function getExecutedStatements() + { + return $this->executedStatements; + } + + /** + * Returns the list of failed statements + * + * @return array + */ + public function getFailedExecutedStatements() + { + return array_filter($this->executedStatements, function($s) { return !$s->isSuccess(); }); + } + + public function __get($name) + { + return $this->pdo->$name; + } + + public function __set($name, $value) + { + $this->pdo->$name = $value; + } + + public function __call($name, $args) + { + return call_user_func_array(array($this->pdo, $name), $args); + } +} diff --git a/src/core/libs/DebugBar/DataCollector/PDO/TraceablePDOStatement.php b/src/core/libs/DebugBar/DataCollector/PDO/TraceablePDOStatement.php new file mode 100755 index 0000000..ee8e393 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/PDO/TraceablePDOStatement.php @@ -0,0 +1,71 @@ +<?php + +namespace DebugBar\DataCollector\PDO; + +use PDO; +use PDOStatement; +use PDOException; + +/** + * A traceable PDO statement to use with Traceablepdo + */ +class TraceablePDOStatement extends PDOStatement +{ + protected $pdo; + + protected $boundParameters = array(); + + protected function __construct(TraceablePDO $pdo) + { + $this->pdo = $pdo; + } + + public function bindColumn($column, &$param, $type = null, $maxlen = null, $driverdata = null) { + $this->boundParameters[$column] = $param; + $args = array_merge(array($column, &$param), array_slice(func_get_args(), 2)); + return call_user_func_array(array("parent", 'bindColumn'), $args); + } + + public function bindParam($param, &$var, $data_type = PDO::PARAM_STR, $length = null, $driver_options = null) { + $this->boundParameters[$param] = $var; + $args = array_merge(array($param, &$var), array_slice(func_get_args(), 2)); + return call_user_func_array(array("parent", 'bindParam'), $args); + } + + public function bindValue($param, $value, $data_type = PDO::PARAM_STR) { + $this->boundParameters[$param] = $value; + return call_user_func_array(array("parent", 'bindValue'), func_get_args()); + } + + public function execute($params = null) + { + $preparedId = spl_object_hash($this); + $boundParameters = $this->boundParameters; + if (is_array($params)) { + $boundParameters = array_merge($boundParameters, $params); + } + + $trace = new TracedStatement($this->queryString, $boundParameters, $preparedId); + $trace->start(); + + $ex = null; + try { + $result = parent::execute($params); + } catch (PDOException $e) { + $ex = $e; + } + + if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) !== PDO::ERRMODE_EXCEPTION && $result === false) { + $error = $this->errorInfo(); + $ex = new PDOException($error[2], $error[0]); + } + + $trace->end($ex, $this->rowCount()); + $this->pdo->addExecutedStatement($trace); + + if ($this->pdo->getAttribute(PDO::ATTR_ERRMODE) === PDO::ERRMODE_EXCEPTION && $ex !== null) { + throw $ex; + } + return $result; + } +} diff --git a/src/core/libs/DebugBar/DataCollector/PDO/TracedStatement.php b/src/core/libs/DebugBar/DataCollector/PDO/TracedStatement.php new file mode 100755 index 0000000..ef50ec4 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/PDO/TracedStatement.php @@ -0,0 +1,240 @@ +<?php + +namespace DebugBar\DataCollector\PDO; + +/** + * Holds information about a statement + */ +class TracedStatement +{ + protected $sql; + + protected $rowCount; + + protected $parameters; + + protected $startTime; + + protected $endTime; + + protected $duration; + + protected $startMemory; + + protected $endMemory; + + protected $memoryDelta; + + protected $exception; + + /** + * @param string $sql + * @param array $params + * @param string $preparedId + * @param integer $rowCount + * @param integer $startTime + * @param integer $endTime + * @param integer $memoryUsage + * @param \Exception $e + */ + public function __construct($sql, array $params = array(), $preparedId = null) + { + $this->sql = $sql; + $this->parameters = $this->checkParameters($params); + $this->preparedId = $preparedId; + } + + public function start($startTime = null, $startMemory = null) + { + $this->startTime = $startTime ?: microtime(true); + $this->startMemory = $startMemory ?: memory_get_usage(true); + } + + public function end(\Exception $exception = null, $rowCount = 0, $endTime = null, $endMemory = null) + { + $this->endTime = $endTime ?: microtime(true); + $this->duration = $this->endTime - $this->startTime; + $this->endMemory = $endMemory ?: memory_get_usage(true); + $this->memoryDelta = $this->endMemory - $this->startMemory; + $this->exception = $exception; + $this->rowCount = $rowCount; + } + + /** + * Check parameters for illegal (non UTF-8) strings, like Binary data. + * + * @param $params + * @return mixed + */ + public function checkParameters($params) + { + foreach ($params as &$param) { + if(!mb_check_encoding($param, 'UTF-8')) { + $param = '[BINARY DATA]'; + } + } + return $params; + } + + /** + * Returns the SQL string used for the query + * + * @return string + */ + public function getSql() + { + return $this->sql; + } + + /** + * Returns the SQL string with any parameters used embedded + * + * @param string $quotationChar + * @return string + */ + public function getSqlWithParams($quotationChar = '<>') + { + if (($l = strlen($quotationChar)) > 1) { + $quoteLeft = substr($quotationChar, 0, $l / 2); + $quoteRight = substr($quotationChar, $l / 2); + } else { + $quoteLeft = $quoteRight = $quotationChar; + } + + $sql = $this->sql; + foreach ($this->parameters as $k => $v) { + $v = "$quoteLeft$v$quoteRight"; + if (!is_numeric($k)) { + $sql = str_replace($k, $v, $sql); + } else { + $p = strpos($sql, '?'); + $sql = substr($sql, 0, $p) . $v. substr($sql, $p + 1); + } + } + return $sql; + } + + /** + * Returns the number of rows affected/returned + * + * @return int + */ + public function getRowCount() + { + return $this->rowCount; + } + + /** + * Returns an array of parameters used with the query + * + * @return array + */ + public function getParameters() + { + $params = array(); + foreach ($this->parameters as $param) { + $params[] = htmlentities($param, ENT_QUOTES, 'UTF-8', false); + } + return $params; + } + + /** + * Returns the prepared statement id + * + * @return string + */ + public function getPreparedId() + { + return $this->preparedId; + } + + /** + * Checks if this is a prepared statement + * + * @return boolean + */ + public function isPrepared() + { + return $this->preparedId !== null; + } + + public function getStartTime() + { + return $this->startTime; + } + + public function getEndTime() + { + return $this->endTime; + } + + /** + * Returns the duration in seconds of the execution + * + * @return int + */ + public function getDuration() + { + return $this->duration; + } + + public function getStartMemory() + { + return $this->startMemory; + } + + public function getEndMemory() + { + return $this->endMemory; + } + + /** + * Returns the memory usage during the execution + * + * @return int + */ + public function getMemoryUsage() + { + return $this->memoryDelta; + } + + /** + * Checks if the statement was successful + * + * @return boolean + */ + public function isSuccess() + { + return $this->exception === null; + } + + /** + * Returns the exception triggered + * + * @return \Exception + */ + public function getException() + { + return $this->exception; + } + + /** + * Returns the exception's code + * + * @return string + */ + public function getErrorCode() + { + return $this->exception !== null ? $this->exception->getCode() : 0; + } + + /** + * Returns the exception's message + * + * @return string + */ + public function getErrorMessage() + { + return $this->exception !== null ? $this->exception->getMessage() : ''; + } +} diff --git a/src/core/libs/DebugBar/DataCollector/PhpInfoCollector.php b/src/core/libs/DebugBar/DataCollector/PhpInfoCollector.php new file mode 100755 index 0000000..e323ccc --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/PhpInfoCollector.php @@ -0,0 +1,29 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +/** + * Collects info about PHP + */ +class PhpInfoCollector extends DataCollector +{ + public function collect() + { + return array( + 'version' => PHP_VERSION + ); + } + + public function getName() + { + return 'php'; + } +} diff --git a/src/core/libs/DebugBar/DataCollector/Renderable.php b/src/core/libs/DebugBar/DataCollector/Renderable.php new file mode 100755 index 0000000..1a6a833 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/Renderable.php @@ -0,0 +1,25 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +/** + * Indicates that a DataCollector is renderable using JavascriptRenderer + */ +interface Renderable +{ + /** + * Returns a hash where keys are control names and their values + * an array of options as defined in {@see DebugBar\JavascriptRenderer::addControl()} + * + * @return array + */ + function getWidgets(); +} diff --git a/src/core/libs/DebugBar/DataCollector/RequestDataCollector.php b/src/core/libs/DebugBar/DataCollector/RequestDataCollector.php new file mode 100755 index 0000000..1b8de32 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/RequestDataCollector.php @@ -0,0 +1,48 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +/** + * Collects info about the current request + */ +class RequestDataCollector extends DataCollector implements Renderable +{ + public function collect() + { + $vars = array('_GET', '_POST', '_SESSION', '_COOKIE', '_SERVER'); + $data = array(); + + foreach ($vars as $var) { + if (isset($GLOBALS[$var])) { + $data["$" . $var] = $this->getDataFormatter()->formatVar($GLOBALS[$var]); + } + } + + return $data; + } + + public function getName() + { + return 'request'; + } + + public function getWidgets() + { + return array( + "request" => array( + "icon" => "tags", + "widget" => "PhpDebugBar.Widgets.VariableListWidget", + "map" => "request", + "default" => "{}" + ) + ); + } +} diff --git a/src/core/libs/DebugBar/DataCollector/TimeDataCollector.php b/src/core/libs/DebugBar/DataCollector/TimeDataCollector.php new file mode 100755 index 0000000..907fae9 --- /dev/null +++ b/src/core/libs/DebugBar/DataCollector/TimeDataCollector.php @@ -0,0 +1,213 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataCollector; + +use DebugBar\DebugBarException; + +/** + * Collects info about the request duration as well as providing + * a way to log duration of any operations + */ +class TimeDataCollector extends DataCollector implements Renderable +{ + + /** + * @var float + */ + protected $requestStartTime; + + /** + * @var float + */ + protected $requestEndTime; + + /** + * @var array + */ + protected $startedMeasures = array(); + + /** + * @var array + */ + protected $measures = array(); + + /** + * @param float $requestStartTime + */ + public function __construct($requestStartTime = null) + { + if ($requestStartTime === null) { + if (isset($_SERVER['REQUEST_TIME_FLOAT'])) { + $requestStartTime = $_SERVER['REQUEST_TIME_FLOAT']; + } else { + $requestStartTime = microtime(true); + } + } + $this->requestStartTime = $requestStartTime; + } + + /** + * Starts a measure + * + * @param string $name Internal name, used to stop the measure + * @param string $label Public name + */ + public function startMeasure($name, $label = null) + { + $start = microtime(true); + $this->startedMeasures[$name] = array( + 'label' => $label ?: $name, + 'start' => $start + ); + } + + /** + * Check a measure exists + * + * @param string $name + * @return bool + */ + public function hasStartedMeasure($name) + { + return isset($this->startedMeasures[$name]); + } + + /** + * Stops a measure + * + * @param string $name + */ + public function stopMeasure($name) + { + $end = microtime(true); + if (!$this->hasStartedMeasure($name)) { + throw new DebugBarException("Failed stopping measure '$name' because it hasn't been started"); + } + $this->addMeasure($this->startedMeasures[$name]['label'], $this->startedMeasures[$name]['start'], $end); + unset($this->startedMeasures[$name]); + } + + /** + * Adds a measure + * + * @param string $label + * @param float $start + * @param float $end + */ + public function addMeasure($label, $start, $end) + { + $this->measures[] = array( + 'label' => $label, + 'start' => $start, + 'relative_start' => $start - $this->requestStartTime, + 'end' => $end, + 'relative_end' => $end - $this->requestEndTime, + 'duration' => $end - $start, + 'duration_str' => $this->getDataFormatter()->formatDuration($end - $start) + ); + } + + /** + * Utility function to measure the execution of a Closure + * + * @param string $label + * @param Closure $closure + */ + public function measure($label, \Closure $closure) + { + $name = spl_object_hash($closure); + $this->startMeasure($name, $label); + $closure(); + $this->stopMeasure($name); + } + + /** + * Returns an array of all measures + * + * @return array + */ + public function getMeasures() + { + return $this->measures; + } + + /** + * Returns the request start time + * + * @return float + */ + public function getRequestStartTime() + { + return $this->requestStartTime; + } + + /** + * Returns the request end time + * + * @return float + */ + public function getRequestEndTime() + { + return $this->requestEndTime; + } + + /** + * Returns the duration of a request + * + * @return float + */ + public function getRequestDuration() + { + if ($this->requestEndTime !== null) { + return $this->requestEndTime - $this->requestStartTime; + } + return microtime(true) - $this->requestStartTime; + } + + public function collect() + { + $this->requestEndTime = microtime(true); + foreach (array_keys($this->startedMeasures) as $name) { + $this->stopMeasure($name); + } + + return array( + 'start' => $this->requestStartTime, + 'end' => $this->requestEndTime, + 'duration' => $this->getRequestDuration(), + 'duration_str' => $this->getDataFormatter()->formatDuration($this->getRequestDuration()), + 'measures' => array_values($this->measures) + ); + } + + public function getName() + { + return 'time'; + } + + public function getWidgets() + { + return array( + "time" => array( + "icon" => "clock-o", + "tooltip" => "Request Duration", + "map" => "time.duration_str", + "default" => "'0ms'" + ), + "timeline" => array( + "icon" => "tasks", + "widget" => "PhpDebugBar.Widgets.TimelineWidget", + "map" => "time", + "default" => "{}" + ) + ); + } +} diff --git a/src/core/libs/DebugBar/DataFormatter/DataFormatter.php b/src/core/libs/DebugBar/DataFormatter/DataFormatter.php new file mode 100755 index 0000000..eea1c16 --- /dev/null +++ b/src/core/libs/DebugBar/DataFormatter/DataFormatter.php @@ -0,0 +1,173 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataFormatter; + +class DataFormatter implements DataFormatterInterface +{ + public function formatVar($data) + { + return $this->kintLite($data); + } + + public function formatDuration($seconds) + { + if ($seconds < 0.001) { + return round($seconds * 1000000) . 'μs'; + } else if ($seconds < 1) { + return round($seconds * 1000, 2) . 'ms'; + } + return round($seconds, 2) . 's'; + } + + public function formatBytes($size, $precision = 2) + { + if ($size === 0 || $size === null) { + return "0B"; + } + $base = log($size) / log(1024); + $suffixes = array('B', 'KB', 'MB', 'GB', 'TB'); + return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)]; + } + + /** + * lightweight version of Kint::dump(). Uses whitespace for formatting instead of html + * sadly not DRY yet + * + * Extracted from Kint.class.php in raveren/kint, https://github.com/raveren/kint + * Copyright (c) 2013 Rokas Å leinius (raveren@gmail.com) + * + * @param mixed $var + * @param int $level + * + * @return string + */ + protected function kintLite(&$var, $level = 0) + { + // initialize function names into variables for prettier string output (html and implode are also DRY) + $html = "htmlspecialchars"; + $implode = "implode"; + $strlen = "strlen"; + $count = "count"; + $getClass = "get_class"; + + + if ( $var === null ) { + return 'NULL'; + } elseif ( is_bool( $var ) ) { + return 'bool ' . ( $var ? 'TRUE' : 'FALSE' ); + } elseif ( is_float( $var ) ) { + return 'float ' . $var; + } elseif ( is_int( $var ) ) { + return 'integer ' . $var; + } elseif ( is_resource( $var ) ) { + if ( ( $type = get_resource_type( $var ) ) === 'stream' AND $meta = stream_get_meta_data( $var ) ) { + + if ( isset( $meta['uri'] ) ) { + $file = $meta['uri']; + + return "resource ({$type}) {$html( $file, 0 )}"; + } else { + return "resource ({$type})"; + } + } else { + return "resource ({$type})"; + } + } elseif ( is_string( $var ) ) { + return "string ({$strlen( $var )}) \"{$html( $var )}\""; + } elseif ( is_array( $var ) ) { + $output = array(); + $space = str_repeat( $s = ' ', $level ); + + static $marker; + + if ( $marker === null ) { + // Make a unique marker + $marker = uniqid( "\x00" ); + } + + if ( empty( $var ) ) { + return "array()"; + } elseif ( isset( $var[$marker] ) ) { + $output[] = "[\n$space$s*RECURSION*\n$space]"; + } elseif ( $level < 7 ) { + $isSeq = array_keys( $var ) === range( 0, count( $var ) - 1 ); + + $output[] = "["; + + $var[$marker] = true; + + + foreach ( $var as $key => &$val ) { + if ( $key === $marker ) continue; + + $key = $space . $s . ( $isSeq ? "" : "'{$html( $key, 0 )}' => " ); + + $dump = $this->kintLite( $val, $level + 1 ); + $output[] = "{$key}{$dump}"; + } + + unset( $var[$marker] ); + $output[] = "$space]"; + + } else { + $output[] = "[\n$space$s*depth too great*\n$space]"; + } + return "array({$count( $var )}) {$implode( "\n", $output )}"; + } elseif ( is_object( $var ) ) { + if ( $var instanceof SplFileInfo ) { + return "object SplFileInfo " . $var->getRealPath(); + } + + // Copy the object as an array + $array = (array)$var; + + $output = array(); + $space = str_repeat( $s = ' ', $level ); + + $hash = spl_object_hash( $var ); + + // Objects that are being dumped + static $objects = array(); + + if ( empty( $array ) ) { + return "object {$getClass( $var )} {}"; + } elseif ( isset( $objects[$hash] ) ) { + $output[] = "{\n$space$s*RECURSION*\n$space}"; + } elseif ( $level < 7 ) { + $output[] = "{"; + $objects[$hash] = true; + + foreach ( $array as $key => & $val ) { + if ( $key[0] === "\x00" ) { + + $access = $key[1] === "*" ? "protected" : "private"; + + // Remove the access level from the variable name + $key = substr( $key, strrpos( $key, "\x00" ) + 1 ); + } else { + $access = "public"; + } + + $output[] = "$space$s$access $key -> " . $this->kintLite( $val, $level + 1 ); + } + unset( $objects[$hash] ); + $output[] = "$space}"; + + } else { + $output[] = "{\n$space$s*depth too great*\n$space}"; + } + + return "object {$getClass( $var )} ({$count( $array )}) {$implode( "\n", $output )}"; + } else { + return gettype( $var ) . htmlspecialchars( var_export( $var, true ), ENT_NOQUOTES ); + } + } +} diff --git a/src/core/libs/DebugBar/DataFormatter/DataFormatterInterface.php b/src/core/libs/DebugBar/DataFormatter/DataFormatterInterface.php new file mode 100755 index 0000000..cb7b426 --- /dev/null +++ b/src/core/libs/DebugBar/DataFormatter/DataFormatterInterface.php @@ -0,0 +1,42 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\DataFormatter; + +/** + * Formats data to be outputed as string + */ +interface DataFormatterInterface +{ + /** + * Transforms a PHP variable to a string representation + * + * @param mixed $var + * @return string + */ + function formatVar($data); + + /** + * Transforms a duration in seconds in a readable string + * + * @param float $seconds + * @return string + */ + function formatDuration($seconds); + + /** + * Transforms a size in bytes to a human readable string + * + * @param string $size + * @param integer $precision + * @return string + */ + function formatBytes($size, $precision = 2); +} diff --git a/src/core/libs/DebugBar/DebugBar.php b/src/core/libs/DebugBar/DebugBar.php new file mode 100755 index 0000000..8a87785 --- /dev/null +++ b/src/core/libs/DebugBar/DebugBar.php @@ -0,0 +1,468 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar; + +use ArrayAccess; +use DebugBar\DataCollector\DataCollectorInterface; +use DebugBar\Storage\StorageInterface; + +/** + * Main DebugBar object + * + * Manages data collectors. DebugBar provides an array-like access + * to collectors by name. + * + * <code> + * $debugbar = new DebugBar(); + * $debugbar->addCollector(new DataCollector\MessagesCollector()); + * $debugbar['messages']->addMessage("foobar"); + * </code> + */ +class DebugBar implements ArrayAccess +{ + public static $useOpenHandlerWhenSendingDataHeaders = false; + + protected $collectors = array(); + + protected $data; + + protected $jsRenderer; + + protected $requestIdGenerator; + + protected $requestId; + + protected $storage; + + protected $httpDriver; + + protected $stackSessionNamespace = 'PHPDEBUGBAR_STACK_DATA'; + + protected $stackAlwaysUseSessionStorage = false; + + /** + * Adds a data collector + * + * @param DataCollectorInterface $collector + * + * @throws DebugBarException + * @return $this + */ + public function addCollector(DataCollectorInterface $collector) + { + if ($collector->getName() === '__meta') { + throw new DebugBarException("'__meta' is a reserved name and cannot be used as a collector name"); + } + if (isset($this->collectors[$collector->getName()])) { + throw new DebugBarException("'{$collector->getName()}' is already a registered collector"); + } + $this->collectors[$collector->getName()] = $collector; + return $this; + } + + /** + * Checks if a data collector has been added + * + * @param string $name + * @return boolean + */ + public function hasCollector($name) + { + return isset($this->collectors[$name]); + } + + /** + * Returns a data collector + * + * @param string $name + * @return DataCollectorInterface + */ + public function getCollector($name) + { + if (!isset($this->collectors[$name])) { + throw new DebugBarException("'$name' is not a registered collector"); + } + return $this->collectors[$name]; + } + + /** + * Returns an array of all data collectors + * + * @return array[DataCollectorInterface] + */ + public function getCollectors() + { + return $this->collectors; + } + + /** + * Sets the request id generator + * + * @param RequestIdGeneratorInterface $generator + */ + public function setRequestIdGenerator(RequestIdGeneratorInterface $generator) + { + $this->requestIdGenerator = $generator; + return $this; + } + + /** + * @return RequestIdGeneratorInterface + */ + public function getRequestIdGenerator() + { + if ($this->requestIdGenerator === null) { + $this->requestIdGenerator = new RequestIdGenerator(); + } + return $this->requestIdGenerator; + } + + /** + * Returns the id of the current request + * + * @return string + */ + public function getCurrentRequestId() + { + if ($this->requestId === null) { + $this->requestId = $this->getRequestIdGenerator()->generate(); + } + return $this->requestId; + } + + /** + * Sets the storage backend to use to store the collected data + * + * @param StorageInterface $storage + */ + public function setStorage(StorageInterface $storage = null) + { + $this->storage = $storage; + return $this; + } + + /** + * @return StorageInterface + */ + public function getStorage() + { + return $this->storage; + } + + /** + * Checks if the data will be persisted + * + * @return boolean + */ + public function isDataPersisted() + { + return $this->storage !== null; + } + + /** + * Sets the HTTP driver + * + * @param HttpDriverInterface $driver + */ + public function setHttpDriver(HttpDriverInterface $driver) + { + $this->httpDriver = $driver; + return $this; + } + + /** + * Returns the HTTP driver + * + * If no http driver where defined, a PhpHttpDriver is automatically created + * + * @return HttpDriverInterface + */ + public function getHttpDriver() + { + if ($this->httpDriver === null) { + $this->httpDriver = new PhpHttpDriver(); + } + return $this->httpDriver; + } + + /** + * Collects the data from the collectors + * + * @return array + */ + public function collect() + { + $this->data = array( + '__meta' => array( + 'id' => $this->getCurrentRequestId(), + 'datetime' => date('Y-m-d H:i:s'), + 'utime' => microtime(true), + 'method' => isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : null, + 'uri' => isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null, + 'ip' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null + ) + ); + + foreach ($this->collectors as $name => $collector) { + $this->data[$name] = $collector->collect(); + } + + // Remove all invalid (non UTF-8) characters + array_walk_recursive($this->data, function(&$item){ + if (is_string($item) && !mb_check_encoding($item, 'UTF-8')) { + $item = mb_convert_encoding($item, 'UTF-8', 'UTF-8'); + } + }); + + if ($this->storage !== null) { + $this->storage->save($this->getCurrentRequestId(), $this->data); + } + + return $this->data; + } + + /** + * Returns collected data + * + * Will collect the data if none have been collected yet + * + * @return array + */ + public function getData() + { + if ($this->data === null) { + $this->collect(); + } + return $this->data; + } + + /** + * Returns an array of HTTP headers containing the data + * + * @param string $headerName + * @param integer $maxHeaderLength + * @return array + */ + public function getDataAsHeaders($headerName = 'phpdebugbar', $maxHeaderLength = 4096, $maxTotalHeaderLength = 250000) + { + $data = rawurlencode(json_encode(array( + 'id' => $this->getCurrentRequestId(), + 'data' => $this->getData() + ))); + + if (strlen($data) > $maxTotalHeaderLength){ + $data = rawurlencode(json_encode(array( + 'error' => 'Maximum header size exceeded' + ))); + } + + $chunks = array(); + + while (strlen($data) > $maxHeaderLength) { + $chunks[] = substr($data, 0, $maxHeaderLength); + $data = substr($data, $maxHeaderLength); + } + $chunks[] = $data; + + $headers = array(); + for ($i = 0, $c = count($chunks); $i < $c; $i++) { + $name = $headerName . ($i > 0 ? "-$i" : ''); + $headers[$name] = $chunks[$i]; + } + + return $headers; + } + + /** + * Sends the data through the HTTP headers + * + * @param bool $useOpenHandler + * @param string $headerName + * @param integer $maxHeaderLength + */ + public function sendDataInHeaders($useOpenHandler = null, $headerName = 'phpdebugbar', $maxHeaderLength = 4096) + { + if ($useOpenHandler === null) { + $useOpenHandler = self::$useOpenHandlerWhenSendingDataHeaders; + } + if ($useOpenHandler && $this->storage !== null) { + $this->getData(); + $headerName .= '-id'; + $headers = array($headerName => $this->getCurrentRequestId()); + } else { + $headers = $this->getDataAsHeaders($headerName, $maxHeaderLength); + } + $this->getHttpDriver()->setHeaders($headers); + return $this; + } + + /** + * Stacks the data in the session for later rendering + */ + public function stackData() + { + $http = $this->initStackSession(); + + $data = null; + if (!$this->isDataPersisted() || $this->stackAlwaysUseSessionStorage) { + $data = $this->getData(); + } else if ($this->data === null) { + $this->collect(); + } + + $stack = $http->getSessionValue($this->stackSessionNamespace); + $stack[$this->getCurrentRequestId()] = $data; + $http->setSessionValue($this->stackSessionNamespace, $stack); + return $this; + } + + /** + * Checks if there is stacked data in the session + * + * @return boolean + */ + public function hasStackedData() + { + try { + $http = $this->initStackSession(); + } catch (DebugBarException $e) { + return false; + } + return count($http->getSessionValue($this->stackSessionNamespace)) > 0; + } + + /** + * Returns the data stacked in the session + * + * @param boolean $delete Whether to delete the data in the session + * @return array + */ + public function getStackedData($delete = true) + { + $http = $this->initStackSession(); + $stackedData = $http->getSessionValue($this->stackSessionNamespace); + if ($delete) { + $http->deleteSessionValue($this->stackSessionNamespace); + } + + $datasets = array(); + if ($this->isDataPersisted() && !$this->stackAlwaysUseSessionStorage) { + foreach ($stackedData as $id => $data) { + $datasets[$id] = $this->getStorage()->get($id); + } + } else { + $datasets = $stackedData; + } + + return $datasets; + } + + /** + * Sets the key to use in the $_SESSION array + * + * @param string $ns + */ + public function setStackDataSessionNamespace($ns) + { + $this->stackSessionNamespace = $ns; + return $this; + } + + /** + * Returns the key used in the $_SESSION array + * + * @return string + */ + public function getStackDataSessionNamespace() + { + return $this->stackSessionNamespace; + } + + /** + * Sets whether to only use the session to store stacked data even + * if a storage is enabled + * + * @param boolean $enabled + */ + public function setStackAlwaysUseSessionStorage($enabled = true) + { + $this->stackAlwaysUseSessionStorage = $enabled; + return $this; + } + + /** + * Checks if the session is always used to store stacked data + * even if a storage is enabled + * + * @return boolean + */ + public function isStackAlwaysUseSessionStorage() + { + return $this->stackAlwaysUseSessionStorage; + } + + /** + * Initializes the session for stacked data + * + * @return HttpDriverInterface + */ + protected function initStackSession() + { + $http = $this->getHttpDriver(); + if (!$http->isSessionStarted()) { + throw new DebugBarException("Session must be started before using stack data in the debug bar"); + } + + if (!$http->hasSessionValue($this->stackSessionNamespace)) { + $http->setSessionValue($this->stackSessionNamespace, array()); + } + + return $http; + } + + /** + * Returns a JavascriptRenderer for this instance + * + * @param string $baseUrl + * @param string $basePathng + * @return JavascriptRenderer + */ + public function getJavascriptRenderer($baseUrl = null, $basePath = null) + { + if ($this->jsRenderer === null) { + $this->jsRenderer = new JavascriptRenderer($this, $baseUrl, $basePath); + } + return $this->jsRenderer; + } + + // -------------------------------------------- + // ArrayAccess implementation + + public function offsetSet($key, $value) + { + throw new DebugBarException("DebugBar[] is read-only"); + } + + public function offsetGet($key) + { + return $this->getCollector($key); + } + + public function offsetExists($key) + { + return $this->hasCollector($key); + } + + public function offsetUnset($key) + { + throw new DebugBarException("DebugBar[] is read-only"); + } +} diff --git a/src/core/libs/DebugBar/DebugBarException.php b/src/core/libs/DebugBar/DebugBarException.php new file mode 100755 index 0000000..cf7d9d7 --- /dev/null +++ b/src/core/libs/DebugBar/DebugBarException.php @@ -0,0 +1,16 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar; + +class DebugBarException extends \Exception +{ + +} diff --git a/src/core/libs/DebugBar/HttpDriverInterface.php b/src/core/libs/DebugBar/HttpDriverInterface.php new file mode 100755 index 0000000..f91b139 --- /dev/null +++ b/src/core/libs/DebugBar/HttpDriverInterface.php @@ -0,0 +1,63 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar; + +/** + * Provides an abstraction of PHP native features for easier integration + * in third party frameworks + */ +interface HttpDriverInterface +{ + /** + * Sets HTTP headers + * + * @param string $headers + */ + function setHeaders(array $headers); + + /** + * Checks if the session is started + * + * @return boolean + */ + function isSessionStarted(); + + /** + * Sets a value in the session + * + * @param string $name + * @param string $value + */ + function setSessionValue($name, $value); + + /** + * Checks if a value is in the session + * + * @param string $name + * @return boolean + */ + function hasSessionValue($name); + + /** + * Returns a value from the session + * + * @param string $name + * @return mixed + */ + function getSessionValue($name); + + /** + * Deletes a value from the session + * + * @param string $name + */ + function deleteSessionValue($name); +} diff --git a/src/core/libs/DebugBar/JavascriptRenderer.php b/src/core/libs/DebugBar/JavascriptRenderer.php new file mode 100755 index 0000000..3450394 --- /dev/null +++ b/src/core/libs/DebugBar/JavascriptRenderer.php @@ -0,0 +1,919 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar; + +use DebugBar\DataCollector\Renderable; +use DebugBar\DataCollector\AssetProvider; + +/** + * Renders the debug bar using the client side javascript implementation + * + * Generates all the needed initialization code of controls + */ +class JavascriptRenderer +{ + const INITIALIZE_CONSTRUCTOR = 2; + + const INITIALIZE_CONTROLS = 4; + + const REPLACEABLE_TAG = "{--DEBUGBAR_OB_START_REPLACE_ME--}"; + + const RELATIVE_PATH = 'path'; + + const RELATIVE_URL = 'url'; + + protected $debugBar; + + protected $baseUrl; + + protected $basePath; + + protected $cssVendors = array( + 'vendor/font-awesome/css/font-awesome.min.css', + 'vendor/highlightjs/styles/github.css' + ); + + protected $jsVendors = array( + 'vendor/jquery/dist/jquery.min.js', + 'vendor/highlightjs/highlight.pack.js' + ); + + protected $includeVendors = true; + + protected $cssFiles = array('debugbar.css', 'widgets.css', 'openhandler.css'); + + protected $jsFiles = array('debugbar.js', 'widgets.js', 'openhandler.js'); + + protected $additionalAssets = array(); + + protected $javascriptClass = 'PhpDebugBar.DebugBar'; + + protected $variableName = 'phpdebugbar'; + + protected $enableJqueryNoConflict = true; + + protected $initialization; + + protected $controls = array(); + + protected $ignoredCollectors = array(); + + protected $ajaxHandlerClass = 'PhpDebugBar.AjaxHandler'; + + protected $ajaxHandlerBindToJquery = true; + + protected $openHandlerClass = 'PhpDebugBar.OpenHandler'; + + protected $openHandlerUrl; + + /** + * @param \DebugBar\DebugBar $debugBar + * @param string $baseUrl + * @param string $basePath + */ + public function __construct(DebugBar $debugBar, $baseUrl = null, $basePath = null) + { + $this->debugBar = $debugBar; + + if ($baseUrl === null) { + $baseUrl = '/vendor/maximebf/debugbar/src/DebugBar/Resources'; + } + $this->baseUrl = $baseUrl; + + if ($basePath === null) { + $basePath = __DIR__ . DIRECTORY_SEPARATOR . 'Resources'; + } + $this->basePath = $basePath; + + // bitwise operations cannot be done in class definition :( + $this->initialization = self::INITIALIZE_CONSTRUCTOR | self::INITIALIZE_CONTROLS; + } + + /** + * Sets options from an array + * + * Options: + * - base_path + * - base_url + * - include_vendors + * - javascript_class + * - variable_name + * - initialization + * - enable_jquery_noconflict + * - controls + * - disable_controls + * - ignore_collectors + * - ajax_handler_classname + * - ajax_handler_bind_to_jquery + * - open_handler_classname + * - open_handler_url + * + * @param array $options [description] + */ + public function setOptions(array $options) + { + if (array_key_exists('base_path', $options)) { + $this->setBasePath($options['base_path']); + } + if (array_key_exists('base_url', $options)) { + $this->setBaseUrl($options['base_url']); + } + if (array_key_exists('include_vendors', $options)) { + $this->setIncludeVendors($options['include_vendors']); + } + if (array_key_exists('javascript_class', $options)) { + $this->setJavascriptClass($options['javascript_class']); + } + if (array_key_exists('variable_name', $options)) { + $this->setVariableName($options['variable_name']); + } + if (array_key_exists('initialization', $options)) { + $this->setInitialization($options['initialization']); + } + if (array_key_exists('enable_jquery_noconflict', $options)) { + $this->setEnableJqueryNoConflict($options['enable_jquery_noconflict']); + } + if (array_key_exists('controls', $options)) { + foreach ($options['controls'] as $name => $control) { + $this->addControl($name, $control); + } + } + if (array_key_exists('disable_controls', $options)) { + foreach ((array) $options['disable_controls'] as $name) { + $this->disableControl($name); + } + } + if (array_key_exists('ignore_collectors', $options)) { + foreach ((array) $options['ignore_collectors'] as $name) { + $this->ignoreCollector($name); + } + } + if (array_key_exists('ajax_handler_classname', $options)) { + $this->setAjaxHandlerClass($options['ajax_handler_classname']); + } + if (array_key_exists('ajax_handler_bind_to_jquery', $options)) { + $this->setBindAjaxHandlerToJquery($options['ajax_handler_bind_to_jquery']); + } + if (array_key_exists('open_handler_classname', $options)) { + $this->setOpenHandlerClass($options['open_handler_classname']); + } + if (array_key_exists('open_handler_url', $options)) { + $this->setOpenHandlerUrl($options['open_handler_url']); + } + } + + /** + * Sets the path which assets are relative to + * + * @param string $path + */ + public function setBasePath($path) + { + $this->basePath = $path; + return $this; + } + + /** + * Returns the path which assets are relative to + * + * @return string + */ + public function getBasePath() + { + return $this->basePath; + } + + /** + * Sets the base URL from which assets will be served + * + * @param string $url + */ + public function setBaseUrl($url) + { + $this->baseUrl = $url; + return $this; + } + + /** + * Returns the base URL from which assets will be served + * + * @return string + */ + public function getBaseUrl() + { + return $this->baseUrl; + } + + /** + * Whether to include vendor assets + * + * You can only include js or css vendors using + * setIncludeVendors('css') or setIncludeVendors('js') + * + * @param boolean $enabled + */ + public function setIncludeVendors($enabled = true) + { + if (is_string($enabled)) { + $enabled = array($enabled); + } + $this->includeVendors = $enabled; + + if (!$enabled || (is_array($enabled) && !in_array('js', $enabled))) { + // no need to call jQuery.noConflict() if we do not include our own version + $this->enableJqueryNoConflict = false; + } + + return $this; + } + + /** + * Checks if vendors assets are included + * + * @return boolean + */ + public function areVendorsIncluded() + { + return $this->includeVendors !== false; + } + + /** + * Sets the javascript class name + * + * @param string $className + */ + public function setJavascriptClass($className) + { + $this->javascriptClass = $className; + return $this; + } + + /** + * Returns the javascript class name + * + * @return string + */ + public function getJavascriptClass() + { + return $this->javascriptClass; + } + + /** + * Sets the variable name of the class instance + * + * @param string $name + */ + public function setVariableName($name) + { + $this->variableName = $name; + return $this; + } + + /** + * Returns the variable name of the class instance + * + * @return string + */ + public function getVariableName() + { + return $this->variableName; + } + + /** + * Sets what should be initialized + * + * - INITIALIZE_CONSTRUCTOR: only initializes the instance + * - INITIALIZE_CONTROLS: initializes the controls and data mapping + * - INITIALIZE_CONSTRUCTOR | INITIALIZE_CONTROLS: initialize everything (default) + * + * @param integer $init + */ + public function setInitialization($init) + { + $this->initialization = $init; + return $this; + } + + /** + * Returns what should be initialized + * + * @return integer + */ + public function getInitialization() + { + return $this->initialization; + } + + /** + * Sets whether to call jQuery.noConflict() + * + * @param boolean $enabled + */ + public function setEnableJqueryNoConflict($enabled = true) + { + $this->enableJqueryNoConflict = $enabled; + return $this; + } + + /** + * Checks if jQuery.noConflict() will be called + * + * @return boolean + */ + public function isJqueryNoConflictEnabled() + { + return $this->enableJqueryNoConflict; + } + + /** + * Adds a control to initialize + * + * Possible options: + * - icon: icon name + * - tooltip: string + * - widget: widget class name + * - title: tab title + * - map: a property name from the data to map the control to + * - default: a js string, default value of the data map + * + * "icon" or "widget" are at least needed + * + * @param string $name + * @param array $options + */ + public function addControl($name, array $options) + { + if (count(array_intersect(array_keys($options), array('icon', 'widget', 'tab', 'indicator'))) === 0) { + throw new DebugBarException("Not enough options for control '$name'"); + } + $this->controls[$name] = $options; + return $this; + } + + /** + * Disables a control + * + * @param string $name + */ + public function disableControl($name) + { + $this->controls[$name] = null; + return $this; + } + + /** + * Returns the list of controls + * + * This does not include controls provided by collectors + * + * @return array + */ + public function getControls() + { + return $this->controls; + } + + /** + * Ignores widgets provided by a collector + * + * @param string $name + */ + public function ignoreCollector($name) + { + $this->ignoredCollectors[] = $name; + return $this; + } + + /** + * Returns the list of ignored collectors + * + * @return array + */ + public function getIgnoredCollectors() + { + return $this->ignoredCollectors; + } + + /** + * Sets the class name of the ajax handler + * + * Set to false to disable + * + * @param string $className + */ + public function setAjaxHandlerClass($className) + { + $this->ajaxHandlerClass = $className; + return $this; + } + + /** + * Returns the class name of the ajax handler + * + * @return string + */ + public function getAjaxHandlerClass() + { + return $this->ajaxHandlerClass; + } + + /** + * Sets whether to call bindToJquery() on the ajax handler + * + * @param boolean $bind + */ + public function setBindAjaxHandlerToJquery($bind = true) + { + $this->ajaxHandlerBindToJquery = $bind; + return $this; + } + + /** + * Checks whether bindToJquery() will be called on the ajax handler + * + * @return boolean + */ + public function isAjaxHandlerBoundToJquery() + { + return $this->ajaxHandlerBindToJquery; + } + + /** + * Sets the class name of the js open handler + * + * @param string $className + */ + public function setOpenHandlerClass($className) + { + $this->openHandlerClass = $className; + return $this; + } + + /** + * Returns the class name of the js open handler + * + * @return string + */ + public function getOpenHandlerClass() + { + return $this->openHandlerClass; + } + + /** + * Sets the url of the open handler + * + * @param string $url + */ + public function setOpenHandlerUrl($url) + { + $this->openHandlerUrl = $url; + return $this; + } + + /** + * Returns the url for the open handler + * + * @return string + */ + public function getOpenHandlerUrl() + { + return $this->openHandlerUrl; + } + + /** + * Add assets to render in the head + * + * @param array $cssFiles An array of filenames + * @param array $jsFiles An array of filenames + * @param string $basePath Base path of those files + * @param string $baseUrl Base url of those files + */ + public function addAssets($cssFiles, $jsFiles, $basePath = null, $baseUrl = null) + { + $this->additionalAssets[] = array( + 'base_path' => $basePath, + 'base_url' => $baseUrl, + 'css' => (array) $cssFiles, + 'js' => (array) $jsFiles + ); + return $this; + } + + /** + * Returns the list of asset files + * + * @param string $type Only return css or js files + * @param string $relativeTo The type of path to which filenames must be relative (path, url or null) + * @return array + */ + public function getAssets($type = null, $relativeTo = self::RELATIVE_PATH) + { + $cssFiles = $this->cssFiles; + $jsFiles = $this->jsFiles; + + if ($this->includeVendors !== false) { + if ($this->includeVendors === true || in_array('css', $this->includeVendors)) { + $cssFiles = array_merge($this->cssVendors, $cssFiles); + } + if ($this->includeVendors === true || in_array('js', $this->includeVendors)) { + $jsFiles = array_merge($this->jsVendors, $jsFiles); + } + } + + if ($relativeTo) { + $root = $this->getRelativeRoot($relativeTo, $this->basePath, $this->baseUrl); + $cssFiles = $this->makeUriRelativeTo($cssFiles, $root); + $jsFiles = $this->makeUriRelativeTo($jsFiles, $root); + } + + $additionalAssets = $this->additionalAssets; + // finds assets provided by collectors + foreach ($this->debugBar->getCollectors() as $collector) { + if (($collector instanceof AssetProvider) && !in_array($collector->getName(), $this->ignoredCollectors)) { + $additionalAssets[] = $collector->getAssets(); + } + } + + foreach ($additionalAssets as $assets) { + $basePath = isset($assets['base_path']) ? $assets['base_path'] : null; + $baseUrl = isset($assets['base_url']) ? $assets['base_url'] : null; + $root = $this->getRelativeRoot($relativeTo, + $this->makeUriRelativeTo($basePath, $this->basePath), + $this->makeUriRelativeTo($baseUrl, $this->baseUrl)); + $cssFiles = array_merge($cssFiles, $this->makeUriRelativeTo((array) $assets['css'], $root)); + $jsFiles = array_merge($jsFiles, $this->makeUriRelativeTo((array) $assets['js'], $root)); + } + + return $this->filterAssetArray(array($cssFiles, $jsFiles), $type); + } + + /** + * Returns the correct base according to the type + * + * @param string $relativeTo + * @param string $basePath + * @param string $baseUrl + * @return string + */ + protected function getRelativeRoot($relativeTo, $basePath, $baseUrl) + { + if ($relativeTo === self::RELATIVE_PATH) { + return $basePath; + } + if ($relativeTo === self::RELATIVE_URL) { + return $baseUrl; + } + return null; + } + + /** + * Makes a URI relative to another + * + * @param string|array $uri + * @param string $root + * @return string + */ + protected function makeUriRelativeTo($uri, $root) + { + if (!$root) { + return $uri; + } + + if (is_array($uri)) { + $uris = array(); + foreach ($uri as $u) { + $uris[] = $this->makeUriRelativeTo($u, $root); + } + return $uris; + } + + if (substr($uri, 0, 1) === '/' || preg_match('/^([a-z]+:\/\/|[a-zA-Z]:\/)/', $uri)) { + return $uri; + } + return rtrim($root, '/') . "/$uri"; + } + + /** + * Filters a tuple of (css, js) assets according to $type + * + * @param array $array + * @param string $type 'css', 'js' or null for both + * @return array + */ + protected function filterAssetArray($array, $type = null) + { + $type = strtolower($type); + if ($type === 'css') { + return $array[0]; + } + if ($type === 'js') { + return $array[1]; + } + return $array; + } + + /** + * Returns a tuple where the both items are Assetic AssetCollection, + * the first one being css files and the second js files + * + * @param string $type Only return css or js collection + * @return array or \Assetic\Asset\AssetCollection + */ + public function getAsseticCollection($type = null) + { + list($cssFiles, $jsFiles) = $this->getAssets(); + return $this->filterAssetArray(array( + $this->createAsseticCollection($cssFiles), + $this->createAsseticCollection($jsFiles) + ), $type); + } + + /** + * Create an Assetic AssetCollection with the given files. + * Filenames will be converted to absolute path using + * the base path. + * + * @param array $files + * @return \Assetic\Asset\AssetCollection + */ + protected function createAsseticCollection($files) + { + $assets = array(); + foreach ($files as $file) { + $assets[] = new \Assetic\Asset\FileAsset($file); + } + return new \Assetic\Asset\AssetCollection($assets); + } + + /** + * Write all CSS assets to standard output or in a file + * + * @param string $targetFilename + */ + public function dumpCssAssets($targetFilename = null) + { + $this->dumpAssets($this->getAssets('css'), $targetFilename); + } + + /** + * Write all JS assets to standard output or in a file + * + * @param string $targetFilename + */ + public function dumpJsAssets($targetFilename = null) + { + $this->dumpAssets($this->getAssets('js'), $targetFilename); + } + + /** + * Write assets to standard output or in a file + * + * @param array $files + * @param string $targetFilename + */ + protected function dumpAssets($files, $targetFilename = null) + { + $content = ''; + foreach ($files as $file) { + $content .= file_get_contents($file) . "\n"; + } + if ($targetFilename !== null) { + file_put_contents($targetFilename, $content); + } else { + echo $content; + } + } + + /** + * Renders the html to include needed assets + * + * Only useful if Assetic is not used + * + * @return string + */ + public function renderHead() + { + list($cssFiles, $jsFiles) = $this->getAssets(null, self::RELATIVE_URL); + $html = ''; + + foreach ($cssFiles as $file) { + $html .= sprintf('<link rel="stylesheet" type="text/css" href="%s">' . "\n", $file); + } + + foreach ($jsFiles as $file) { + $html .= sprintf('<script type="text/javascript" src="%s"></script>' . "\n", $file); + } + + if ($this->enableJqueryNoConflict) { + $html .= '<script type="text/javascript">jQuery.noConflict(true);</script>' . "\n"; + } + + return $html; + } + + /** + * Register shutdown to display the debug bar + * + * @param boolean $here Set position of HTML. True if is to current position or false for end file + * @param boolean $initialize Whether to render the de bug bar initialization code + * @return string Return "{--DEBUGBAR_OB_START_REPLACE_ME--}" or return an empty string if $here == false + */ + public function renderOnShutdown($here = true, $initialize = true, $renderStackedData = true, $head = false) + { + register_shutdown_function(array($this, "replaceTagInBuffer"), $here, $initialize, $renderStackedData, $head); + + if (ob_get_level() === 0) { + ob_start(); + } + + return ($here) ? self::REPLACEABLE_TAG : ""; + } + + /** + * Same as renderOnShutdown() with $head = true + * + * @param boolean $here + * @param boolean $initialize + * @param boolean $renderStackedData + * @return string + */ + public function renderOnShutdownWithHead($here = true, $initialize = true, $renderStackedData = true) + { + return $this->renderOnShutdown($here, $initialize, $renderStackedData, true); + } + + /** + * Is callback function for register_shutdown_function(...) + * + * @param boolean $here Set position of HTML. True if is to current position or false for end file + * @param boolean $initialize Whether to render the de bug bar initialization code + */ + public function replaceTagInBuffer($here = true, $initialize = true, $renderStackedData = true, $head = false) + { + $render = ($head ? $this->renderHead() : "") + . $this->render($initialize, $renderStackedData); + + $current = ($here && ob_get_level() > 0) ? ob_get_clean() : self::REPLACEABLE_TAG; + + echo str_replace(self::REPLACEABLE_TAG, $render, $current, $count); + + if ($count === 0) { + echo $render; + } + } + + /** + * Returns the code needed to display the debug bar + * + * AJAX request should not render the initialization code. + * + * @param boolean $initialize Whether to render the de bug bar initialization code + * @return string + */ + public function render($initialize = true, $renderStackedData = true) + { + $js = ''; + + if ($initialize) { + $js = $this->getJsInitializationCode(); + } + + if ($renderStackedData && $this->debugBar->hasStackedData()) { + foreach ($this->debugBar->getStackedData() as $id => $data) { + $js .= $this->getAddDatasetCode($id, $data, '(stacked)'); + } + } + + $suffix = !$initialize ? '(ajax)' : null; + $js .= $this->getAddDatasetCode($this->debugBar->getCurrentRequestId(), $this->debugBar->getData(), $suffix); + + return "<script type=\"text/javascript\">\n$js\n</script>\n"; + } + + /** + * Returns the js code needed to initialize the debug bar + * + * @return string + */ + protected function getJsInitializationCode() + { + $js = ''; + + if (($this->initialization & self::INITIALIZE_CONSTRUCTOR) === self::INITIALIZE_CONSTRUCTOR) { + $js .= sprintf("var %s = new %s();\n", $this->variableName, $this->javascriptClass); + } + + if (($this->initialization & self::INITIALIZE_CONTROLS) === self::INITIALIZE_CONTROLS) { + $js .= $this->getJsControlsDefinitionCode($this->variableName); + } + + if ($this->ajaxHandlerClass) { + $js .= sprintf("%s.ajaxHandler = new %s(%s);\n", $this->variableName, $this->ajaxHandlerClass, $this->variableName); + if ($this->ajaxHandlerBindToJquery) { + $js .= sprintf("if (jQuery) %s.ajaxHandler.bindToJquery(jQuery);\n", $this->variableName); + } + } + + if ($this->openHandlerUrl !== null) { + $js .= sprintf("%s.setOpenHandler(new %s(%s));\n", $this->variableName, + $this->openHandlerClass, + json_encode(array("url" => $this->openHandlerUrl))); + } + + return $js; + } + + /** + * Returns the js code needed to initialized the controls and data mapping of the debug bar + * + * Controls can be defined by collectors themselves or using {@see addControl()} + * + * @param string $varname Debug bar's variable name + * @return string + */ + protected function getJsControlsDefinitionCode($varname) + { + $js = ''; + $dataMap = array(); + $excludedOptions = array('indicator', 'tab', 'map', 'default', 'widget', 'position'); + + // finds controls provided by collectors + $widgets = array(); + foreach ($this->debugBar->getCollectors() as $collector) { + if (($collector instanceof Renderable) && !in_array($collector->getName(), $this->ignoredCollectors)) { + if ($w = $collector->getWidgets()) { + $widgets = array_merge($widgets, $w); + } + } + } + $controls = array_merge($widgets, $this->controls); + + + foreach (array_filter($controls) as $name => $options) { + $opts = array_diff_key($options, array_flip($excludedOptions)); + + if (isset($options['tab']) || isset($options['widget'])) { + if (!isset($opts['title'])) { + $opts['title'] = ucfirst(str_replace('_', ' ', $name)); + } + $js .= sprintf("%s.addTab(\"%s\", new %s({%s%s}));\n", + $varname, + $name, + isset($options['tab']) ? $options['tab'] : 'PhpDebugBar.DebugBar.Tab', + substr(json_encode($opts, JSON_FORCE_OBJECT), 1, -1), + isset($options['widget']) ? sprintf('%s"widget": new %s()', count($opts) ? ', ' : '', $options['widget']) : '' + ); + } else if (isset($options['indicator']) || isset($options['icon'])) { + $js .= sprintf("%s.addIndicator(\"%s\", new %s(%s), \"%s\");\n", + $varname, + $name, + isset($options['indicator']) ? $options['indicator'] : 'PhpDebugBar.DebugBar.Indicator', + json_encode($opts, JSON_FORCE_OBJECT), + isset($options['position']) ? $options['position'] : 'right' + ); + } + + if (isset($options['map']) && isset($options['default'])) { + $dataMap[$name] = array($options['map'], $options['default']); + } + } + + // creates the data mapping object + $mapJson = array(); + foreach ($dataMap as $name => $values) { + $mapJson[] = sprintf('"%s": ["%s", %s]', $name, $values[0], $values[1]); + } + $js .= sprintf("%s.setDataMap({\n%s\n});\n", $varname, implode(",\n", $mapJson)); + + // activate state restoration + $js .= sprintf("%s.restoreState();\n", $varname); + + return $js; + } + + /** + * Returns the js code needed to add a dataset + * + * @param string $requestId + * @param array $data + * @return string + */ + protected function getAddDatasetCode($requestId, $data, $suffix = null) + { + $js = sprintf("%s.addDataSet(%s, \"%s\"%s);\n", + $this->variableName, + json_encode($data), + $requestId, + $suffix ? ", " . json_encode($suffix) : '' + ); + return $js; + } +} diff --git a/src/core/libs/DebugBar/LICENSE b/src/core/libs/DebugBar/LICENSE new file mode 100644 index 0000000..1344c98 --- /dev/null +++ b/src/core/libs/DebugBar/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2013 Maxime Bouroumeau-Fuseau + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/core/libs/DebugBar/OpenHandler.php b/src/core/libs/DebugBar/OpenHandler.php new file mode 100755 index 0000000..cd9840b --- /dev/null +++ b/src/core/libs/DebugBar/OpenHandler.php @@ -0,0 +1,107 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar; + +/** + * Handler to list and open saved dataset + */ +class OpenHandler +{ + protected $debugBar; + + /** + * @param DebugBar $debugBar + */ + public function __construct(DebugBar $debugBar) + { + if (!$debugBar->isDataPersisted()) { + throw new DebugBarException("DebugBar must have a storage backend to use OpenHandler"); + } + $this->debugBar = $debugBar; + } + + /** + * Handles the current request + * + * @param array $request Request data + */ + public function handle($request = null, $echo = true, $sendHeader = true) + { + if ($request === null) { + $request = $_REQUEST; + } + + $op = 'find'; + if (isset($request['op'])) { + $op = $request['op']; + if (!in_array($op, array('find', 'get', 'clear'))) { + throw new DebugBarException("Invalid operation '{$request['op']}'"); + } + } + + if ($sendHeader) { + $this->debugBar->getHttpDriver()->setHeaders(array( + 'Content-Type'=> 'application/json' + )); + } + + $response = json_encode(call_user_func(array($this, $op), $request)); + if ($echo) { + echo $response; + } + return $response; + } + + /** + * Find operation + */ + protected function find($request) + { + $max = 20; + if (isset($request['max'])) { + $max = $request['max']; + } + + $offset = 0; + if (isset($request['offset'])) { + $offset = $request['offset']; + } + + $filters = array(); + foreach (array('utime', 'datetime', 'ip', 'uri', 'method') as $key) { + if (isset($request[$key])) { + $filters[$key] = $request[$key]; + } + } + + return $this->debugBar->getStorage()->find($filters, $max, $offset); + } + + /** + * Get operation + */ + protected function get($request) + { + if (!isset($request['id'])) { + throw new DebugBarException("Missing 'id' parameter in 'get' operation"); + } + return $this->debugBar->getStorage()->get($request['id']); + } + + /** + * Clear operation + */ + protected function clear($request) + { + $this->debugBar->getStorage()->clear(); + return array('success' => true); + } +} diff --git a/src/core/libs/DebugBar/PhpHttpDriver.php b/src/core/libs/DebugBar/PhpHttpDriver.php new file mode 100755 index 0000000..af07060 --- /dev/null +++ b/src/core/libs/DebugBar/PhpHttpDriver.php @@ -0,0 +1,49 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar; + +/** + * HTTP driver for native php + */ +class PhpHttpDriver implements HttpDriverInterface +{ + function setHeaders(array $headers) + { + foreach ($headers as $name => $value) { + header("$name: $value"); + } + } + + function isSessionStarted() + { + return isset($_SESSION); + } + + function setSessionValue($name, $value) + { + $_SESSION[$name] = $value; + } + + function hasSessionValue($name) + { + return array_key_exists($name, $_SESSION); + } + + function getSessionValue($name) + { + return $_SESSION[$name]; + } + + function deleteSessionValue($name) + { + unset($_SESSION[$name]); + } +} diff --git a/src/core/libs/DebugBar/RequestIdGenerator.php b/src/core/libs/DebugBar/RequestIdGenerator.php new file mode 100755 index 0000000..934f407 --- /dev/null +++ b/src/core/libs/DebugBar/RequestIdGenerator.php @@ -0,0 +1,22 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar; + +/** + * Request id generator based on the $_SERVER array + */ +class RequestIdGenerator implements RequestIdGeneratorInterface +{ + public function generate() + { + return md5(serialize($_SERVER) . microtime()); + } +} diff --git a/src/core/libs/DebugBar/RequestIdGeneratorInterface.php b/src/core/libs/DebugBar/RequestIdGeneratorInterface.php new file mode 100755 index 0000000..c727624 --- /dev/null +++ b/src/core/libs/DebugBar/RequestIdGeneratorInterface.php @@ -0,0 +1,21 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar; + +interface RequestIdGeneratorInterface +{ + /** + * Generates a unique id for the current request + * + * @return string + */ + function generate(); +} diff --git a/src/core/libs/DebugBar/Resources/.htaccess b/src/core/libs/DebugBar/Resources/.htaccess new file mode 100644 index 0000000..16ff119 --- /dev/null +++ b/src/core/libs/DebugBar/Resources/.htaccess @@ -0,0 +1,4 @@ +<Files *> + Order deny,allow + Allow from all +</Files> diff --git a/src/core/libs/DebugBar/Resources/debugbar.css b/src/core/libs/DebugBar/Resources/debugbar.css new file mode 100755 index 0000000..1da6937 --- /dev/null +++ b/src/core/libs/DebugBar/Resources/debugbar.css @@ -0,0 +1,225 @@ +div.phpdebugbar { + position: fixed; + bottom: 0; + left: 0; + width: 100%; + border-top: 0; + font-family: arial, sans-serif; + background: #fff; + z-index: 10000; + font-size: 14px; + color: #000; + text-align: left; +} + +div.phpdebugbar-closed { + width: auto; +} + +div.phpdebugbar * { + + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +a.phpdebugbar-restore-btn { + float: left; + padding: 5px 8px; + font-size: 14px; + color: #555; + text-decoration: none; + border-right: 1px solid #ddd; +} + +div.phpdebugbar-resize-handle { + display: none; + height: 4px; + margin-top: -4px; + width: 100%; + background: none; + border-bottom: 1px solid #ccc; + cursor: n-resize; +} + +div.phpdebugbar-closed, div.phpdebugbar-minimized{ + border-top: 1px solid #ccc; +} + +/* -------------------------------------- */ + +div.phpdebugbar-header { + background: #efefef url(php-icon.png) no-repeat 5px 4px; + padding-left: 29px; + min-height: 26px; + line-height: 16px; +} +div.phpdebugbar-header:before, div.phpdebugbar-header:after { + display: table; + line-height: 0; + content: ""; +} +div.phpdebugbar-header:after { + clear: both; +} +div.phpdebugbar-header-left { + float: left; +} +div.phpdebugbar-header-right { + float: right; +} +div.phpdebugbar-header > div > * { + padding: 5px 8px; + font-size: 14px; + color: #555; + text-decoration: none; +} +div.phpdebugbar-header-left > * { + float: left; +} +div.phpdebugbar-header-right > * { + float: right; +} +div.phpdebugbar-header-right > select { + padding: 0; +} + +/* -------------------------------------- */ + +span.phpdebugbar-indicator, +a.phpdebugbar-indicator, +a.phpdebugbar-close-btn { + border-right: 1px solid #ddd; +} + +a.phpdebugbar-tab.phpdebugbar-active { + background: #ccc; + color: #444; + background-image: linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%); + background-image: -o-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%); + background-image: -moz-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%); + background-image: -webkit-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%); + background-image: -ms-linear-gradient(bottom, rgb(173,173,173) 41%, rgb(209,209,209) 71%); + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0.41, rgb(173,173,173)), color-stop(0.71, rgb(209,209,209))); +} + a.phpdebugbar-tab span.phpdebugbar-badge { + display: none; + margin-left: 5px; + font-size: 11px; + line-height: 14px; + padding: 0px 6px; + background: #ccc; + border-radius: 4px; + color: #555; + font-weight: normal; + text-shadow: none; + vertical-align: middle; + } + a.phpdebugbar-tab i { + display: none; + vertical-align: middle; + } + a.phpdebugbar-tab span.phpdebugbar-badge.phpdebugbar-important { + background: #ed6868; + color: white; + } + +a.phpdebugbar-close-btn { + background: url(icons.png) no-repeat 10px 7px; + width: 16px; + height: 16px; +} + +a.phpdebugbar-open-btn { + background: url(icons.png) no-repeat -14px 8px; + width: 16px; + height: 16px; +} + +a.phpdebugbar-restore-btn { + background: #efefef url(php-icon.png) no-repeat 5px 4px; + width: 16px; + height: 16px; +} + +.phpdebugbar-indicator { + position: relative; + cursor: pointer; +} + .phpdebugbar-indicator span.phpdebugbar-text { + margin-left: 5px; + } + .phpdebugbar-indicator span.phpdebugbar-tooltip { + display: none; + position: absolute; + top: -30px; + background: #efefef; + opacity: .7; + border: 1px solid #ccc; + color: #555; + font-size: 11px; + padding: 2px 3px; + z-index: 1000; + text-align: center; + width: 200%; + right: 0; + } + .phpdebugbar-indicator:hover span.phpdebugbar-tooltip:not(.phpdebugbar-disabled) { + display: block; + } + +select.phpdebugbar-datasets-switcher { + float: right; + display: none; + margin: 2px 0 0 7px; + max-width: 200px; + max-height: 23px; + padding: 0; +} + +/* -------------------------------------- */ + +div.phpdebugbar-body { + border-top: 1px solid #ccc; + display: none; + position: relative; + height: 300px; +} + +/* -------------------------------------- */ + +div.phpdebugbar-panel { + display: none; + height: 100%; + overflow: auto; + width: 100%; +} +div.phpdebugbar-panel.phpdebugbar-active { + display: block; +} + +/* -------------------------------------- */ + +div.phpdebugbar-mini-design a.phpdebugbar-tab { + position: relative; + border-right: 1px solid #ddd; +} + div.phpdebugbar-mini-design a.phpdebugbar-tab span.phpdebugbar-text { + display: none; + } + div.phpdebugbar-mini-design a.phpdebugbar-tab:hover span.phpdebugbar-text { + display: block; + position: absolute; + top: -30px; + background: #efefef; + opacity: .7; + border: 1px solid #ccc; + color: #555; + font-size: 11px; + padding: 2px 3px; + z-index: 1000; + text-align: center; + right: 0; + } + div.phpdebugbar-mini-design a.phpdebugbar-tab i { + display:inline-block; + } diff --git a/src/core/libs/DebugBar/Resources/debugbar.js b/src/core/libs/DebugBar/Resources/debugbar.js new file mode 100755 index 0000000..73bee1d --- /dev/null +++ b/src/core/libs/DebugBar/Resources/debugbar.js @@ -0,0 +1,1085 @@ +if (typeof(PhpDebugBar) == 'undefined') { + // namespace + var PhpDebugBar = {}; + PhpDebugBar.$ = jQuery; +} + +(function($) { + + if (typeof(localStorage) == 'undefined') { + // provide mock localStorage object for dumb browsers + localStorage = { + setItem: function(key, value) {}, + getItem: function(key) { return null; } + }; + } + + if (typeof(PhpDebugBar.utils) == 'undefined') { + PhpDebugBar.utils = {}; + } + + /** + * Returns the value from an object property. + * Using dots in the key, it is possible to retrieve nested property values + * + * @param {Object} dict + * @param {String} key + * @param {Object} default_value + * @return {Object} + */ + var getDictValue = PhpDebugBar.utils.getDictValue = function(dict, key, default_value) { + var d = dict, parts = key.split('.'); + for (var i = 0; i < parts.length; i++) { + if (!d[parts[i]]) { + return default_value; + } + d = d[parts[i]]; + } + return d; + } + + /** + * Counts the number of properties in an object + * + * @param {Object} obj + * @return {Integer} + */ + var getObjectSize = PhpDebugBar.utils.getObjectSize = function(obj) { + if (Object.keys) { + return Object.keys(obj).length; + } + var count = 0; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + count++; + } + } + return count; + } + + /** + * Returns a prefixed css class name + * + * @param {String} cls + * @return {String} + */ + PhpDebugBar.utils.csscls = function(cls, prefix) { + if (cls.indexOf(' ') > -1) { + var clss = cls.split(' '), out = []; + for (var i = 0, c = clss.length; i < c; i++) { + out.push(PhpDebugBar.utils.csscls(clss[i], prefix)); + } + return out.join(' '); + } + if (cls.indexOf('.') === 0) { + return '.' + prefix + cls.substr(1); + } + return prefix + cls; + }; + + /** + * Creates a partial function of csscls where the second + * argument is already defined + * + * @param {string} prefix + * @return {Function} + */ + PhpDebugBar.utils.makecsscls = function(prefix) { + var f = function(cls) { + return PhpDebugBar.utils.csscls(cls, prefix); + }; + return f; + } + + var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-'); + + + // ------------------------------------------------------------------ + + /** + * Base class for all elements with a visual component + * + * @param {Object} options + * @constructor + */ + var Widget = PhpDebugBar.Widget = function(options) { + this._attributes = $.extend({}, this.defaults); + this._boundAttributes = {}; + this.$el = $('<' + this.tagName + ' />'); + if (this.className) { + this.$el.addClass(this.className); + } + this.initialize.apply(this, [options || {}]); + this.render.apply(this); + }; + + $.extend(Widget.prototype, { + + tagName: 'div', + + className: null, + + defaults: {}, + + /** + * Called after the constructor + * + * @param {Object} options + */ + initialize: function(options) { + this.set(options); + }, + + /** + * Called after the constructor to render the element + */ + render: function() {}, + + /** + * Sets the value of an attribute + * + * @param {String} attr Can also be an object to set multiple attributes at once + * @param {Object} value + */ + set: function(attr, value) { + if (typeof(attr) != 'string') { + for (var k in attr) { + this.set(k, attr[k]); + } + return; + } + + this._attributes[attr] = value; + if (typeof(this._boundAttributes[attr]) !== 'undefined') { + for (var i = 0, c = this._boundAttributes[attr].length; i < c; i++) { + this._boundAttributes[attr][i].apply(this, [value]); + } + } + }, + + /** + * Checks if an attribute exists and is not null + * + * @param {String} attr + * @return {[type]} [description] + */ + has: function(attr) { + return typeof(this._attributes[attr]) !== 'undefined' && this._attributes[attr] !== null; + }, + + /** + * Returns the value of an attribute + * + * @param {String} attr + * @return {Object} + */ + get: function(attr) { + return this._attributes[attr]; + }, + + /** + * Registers a callback function that will be called whenever the value of the attribute changes + * + * If cb is a jQuery element, text() will be used to fill the element + * + * @param {String} attr + * @param {Function} cb + */ + bindAttr: function(attr, cb) { + if ($.isArray(attr)) { + for (var i = 0, c = attr.length; i < c; i++) { + this.bindAttr(attr[i], cb); + } + return; + } + + if (typeof(this._boundAttributes[attr]) == 'undefined') { + this._boundAttributes[attr] = []; + } + if (typeof(cb) == 'object') { + var el = cb; + cb = function(value) { el.text(value || ''); }; + } + this._boundAttributes[attr].push(cb); + if (this.has(attr)) { + cb.apply(this, [this._attributes[attr]]); + } + } + + }); + + + /** + * Creates a subclass + * + * Code from Backbone.js + * + * @param {Array} props Prototype properties + * @return {Function} + */ + Widget.extend = function(props) { + var parent = this; + + var child = function() { return parent.apply(this, arguments); }; + $.extend(child, parent); + + var Surrogate = function(){ this.constructor = child; }; + Surrogate.prototype = parent.prototype; + child.prototype = new Surrogate; + $.extend(child.prototype, props); + + child.__super__ = parent.prototype; + + return child; + }; + + // ------------------------------------------------------------------ + + /** + * Tab + * + * A tab is composed of a tab label which is always visible and + * a tab panel which is visible only when the tab is active. + * + * The panel must contain a widget. A widget is an object which has + * an element property containing something appendable to a jQuery object. + * + * Options: + * - title + * - badge + * - widget + * - data: forward data to widget data + */ + var Tab = Widget.extend({ + + className: csscls('panel'), + + render: function() { + this.$tab = $('<a href="javascript:" />').addClass(csscls('tab')); + + this.$icon = $('<i />').appendTo(this.$tab); + this.bindAttr('icon', function(icon) { + if (icon) { + this.$icon.attr('class', 'fa fa-' + icon); + } else { + this.$icon.attr('class', ''); + } + }); + + this.bindAttr('title', $('<span />').addClass(csscls('text')).appendTo(this.$tab)); + + this.$badge = $('<span />').addClass(csscls('badge')).appendTo(this.$tab); + this.bindAttr('badge', function(value) { + if (value !== null) { + this.$badge.text(value); + this.$badge.show(); + } else { + this.$badge.hide(); + } + }); + + this.bindAttr('widget', function(widget) { + this.$el.empty().append(widget.$el); + }); + + this.bindAttr('data', function(data) { + if (this.has('widget')) { + this.get('widget').set('data', data); + } + }) + } + + }); + + // ------------------------------------------------------------------ + + /** + * Indicator + * + * An indicator is a text and an icon to display single value information + * right inside the always visible part of the debug bar + * + * Options: + * - icon + * - title + * - tooltip + * - data: alias of title + */ + var Indicator = Widget.extend({ + + tagName: 'span', + + className: csscls('indicator'), + + render: function() { + this.$icon = $('<i />').appendTo(this.$el); + this.bindAttr('icon', function(icon) { + if (icon) { + this.$icon.attr('class', 'fa fa-' + icon); + } else { + this.$icon.attr('class', ''); + } + }); + + this.bindAttr(['title', 'data'], $('<span />').addClass(csscls('text')).appendTo(this.$el)); + + this.$tooltip = $('<span />').addClass(csscls('tooltip disabled')).appendTo(this.$el); + this.bindAttr('tooltip', function(tooltip) { + if (tooltip) { + this.$tooltip.text(tooltip).removeClass(csscls('disabled')); + } else { + this.$tooltip.addClass(csscls('disabled')); + } + }); + } + + }); + + // ------------------------------------------------------------------ + + /** + * Dataset title formater + * + * Formats the title of a dataset for the select box + */ + var DatasetTitleFormater = PhpDebugBar.DatasetTitleFormater = function(debugbar) { + this.debugbar = debugbar; + }; + + $.extend(DatasetTitleFormater.prototype, { + + /** + * Formats the title of a dataset + * + * @this {DatasetTitleFormater} + * @param {String} id + * @param {Object} data + * @param {String} suffix + * @return {String} + */ + format: function(id, data, suffix) { + if (suffix) { + suffix = ' ' + suffix; + } else { + suffix = ''; + } + + var nb = getObjectSize(this.debugbar.datasets) + 1; + + if (typeof(data['__meta']) === 'undefined') { + return "#" + nb + suffix; + } + + var filename = data['__meta']['uri'].substr(data['__meta']['uri'].lastIndexOf('/') + 1); + var label = "#" + nb + " " + filename + suffix + ' (' + data['__meta']['datetime'].split(' ')[1] + ')'; + return label; + } + + }); + + // ------------------------------------------------------------------ + + + /** + * DebugBar + * + * Creates a bar that appends itself to the body of your page + * and sticks to the bottom. + * + * The bar can be customized by adding tabs and indicators. + * A data map is used to fill those controls with data provided + * from datasets. + */ + var DebugBar = PhpDebugBar.DebugBar = Widget.extend({ + + className: "phpdebugbar " + csscls('minimized'), + + options: { + bodyPaddingBottom: true + }, + + initialize: function() { + this.controls = {}; + this.dataMap = {}; + this.datasets = {}; + this.firstTabName = null; + this.activePanelName = null; + this.datesetTitleFormater = new DatasetTitleFormater(this); + this.registerResizeHandler(); + }, + + /** + * Register resize event, for resize debugbar with reponsive css. + * + * @this {DebugBar} + */ + registerResizeHandler: function() { + var f = this.resize.bind(this); + this.respCSSSize = 0; + $(window).resize(f); + setTimeout(f, 20); + }, + + /** + * Resizes the debugbar to fit the current browser window + */ + resize: function() { + var contentSize = this.respCSSSize; + if (this.respCSSSize == 0) { + this.$header.find("> div > *:visible").each(function () { + contentSize += $(this).outerWidth(); + }); + } + + var currentSize = this.$header.width(); + var cssClass = "phpdebugbar-mini-design"; + var bool = this.$header.hasClass(cssClass); + + if (currentSize <= contentSize && !bool) { + this.respCSSSize = contentSize; + this.$header.addClass(cssClass); + } else if (contentSize < currentSize && bool) { + this.respCSSSize = 0; + this.$header.removeClass(cssClass); + } + }, + + /** + * Initialiazes the UI + * + * @this {DebugBar} + */ + render: function() { + var self = this; + this.$el.appendTo('body'); + this.$resizehdle = $('<div />').addClass(csscls('resize-handle')).appendTo(this.$el); + this.$header = $('<div />').addClass(csscls('header')).appendTo(this.$el); + this.$headerLeft = $('<div />').addClass(csscls('header-left')).appendTo(this.$header); + this.$headerRight = $('<div />').addClass(csscls('header-right')).appendTo(this.$header); + var $body = this.$body = $('<div />').addClass(csscls('body')).appendTo(this.$el); + this.recomputeBottomOffset(); + + // dragging of resize handle + var dragging = false; + var min_h = 40; + var max_h = $(window).height() - this.$header.height() - 10; + this.$resizehdle.on('mousedown', function(e) { + var orig_h = $body.height(), pos_y = e.pageY; + dragging = true; + + $body.parents().on('mousemove', function(e) { + if (dragging) { + var h = orig_h + (pos_y - e.pageY); + // Respect the min/max values + h = Math.min(h, max_h); + h = Math.max(h, min_h); + $body.css('height', h); + localStorage.setItem('phpdebugbar-height', h); + self.recomputeBottomOffset(); + } + }).on('mouseup', function() { + dragging = false; + }); + + e.preventDefault(); + }); + + // minimize button + this.$closebtn = $('<a href="javascript:" />').addClass(csscls('close-btn')).appendTo(this.$headerRight); + this.$closebtn.click(function() { + self.close(); + }); + + // minimize button + this.$restorebtn = $('<a href="javascript:" />').addClass(csscls('restore-btn')).hide().appendTo(this.$el); + this.$restorebtn.click(function() { + self.restore(); + }); + + // open button + this.$openbtn = $('<a href="javascript:" />').addClass(csscls('open-btn')).appendTo(this.$headerRight).hide(); + this.$openbtn.click(function() { + self.openHandler.show(function(id, dataset) { + self.addDataSet(dataset, id, "(opened)"); + self.showTab(); + }); + }); + + // select box for data sets + this.$datasets = $('<select />').addClass(csscls('datasets-switcher')).appendTo(this.$headerRight); + this.$datasets.change(function() { + self.dataChangeHandler(self.datasets[this.value]); + self.showTab(); + }); + }, + + /** + * Restores the state of the DebugBar using localStorage + * This is not called by default in the constructor and + * needs to be called by subclasses in their init() method + * + * @this {DebugBar} + */ + restoreState: function() { + // bar height + var height = localStorage.getItem('phpdebugbar-height'); + if (height) { + this.$body.css('height', height); + } else { + localStorage.setItem('phpdebugbar-height', this.$body.height()); + } + + // bar visibility + var open = localStorage.getItem('phpdebugbar-open'); + if (open && open == '0') { + this.close(); + } else { + var visible = localStorage.getItem('phpdebugbar-visible'); + if (visible && visible == '1') { + var tab = localStorage.getItem('phpdebugbar-tab'); + if (this.isTab(tab)) { + this.showTab(tab); + } + } + } + }, + + /** + * Creates and adds a new tab + * + * @this {DebugBar} + * @param {String} name Internal name + * @param {Object} widget A widget object with an element property + * @param {String} title The text in the tab, if not specified, name will be used + * @return {Tab} + */ + createTab: function(name, widget, title) { + var tab = new Tab({ + title: title || (name.replace(/[_\-]/g, ' ').charAt(0).toUpperCase() + name.slice(1)), + widget: widget + }); + return this.addTab(name, tab); + }, + + /** + * Adds a new tab + * + * @this {DebugBar} + * @param {String} name Internal name + * @param {Tab} tab Tab object + * @return {Tab} + */ + addTab: function(name, tab) { + if (this.isControl(name)) { + throw new Error(name + ' already exists'); + } + + var self = this; + tab.$tab.appendTo(this.$headerLeft).click(function() { + if (!self.isMinimized() && self.activePanelName == name) { + self.minimize(); + } else { + self.showTab(name); + } + }); + tab.$el.appendTo(this.$body); + + this.controls[name] = tab; + if (this.firstTabName == null) { + this.firstTabName = name; + } + return tab; + }, + + /** + * Creates and adds an indicator + * + * @this {DebugBar} + * @param {String} name Internal name + * @param {String} icon + * @param {String} tooltip + * @param {String} position "right" or "left", default is "right" + * @return {Indicator} + */ + createIndicator: function(name, icon, tooltip, position) { + var indicator = new Indicator({ + icon: icon, + tooltip: tooltip + }); + return this.addIndicator(name, indicator, position); + }, + + /** + * Adds an indicator + * + * @this {DebugBar} + * @param {String} name Internal name + * @param {Indicator} indicator Indicator object + * @return {Indicator} + */ + addIndicator: function(name, indicator, position) { + if (this.isControl(name)) { + throw new Error(name + ' already exists'); + } + + if (position == 'left') { + indicator.$el.insertBefore(this.$headerLeft.children().first()); + } else { + indicator.$el.appendTo(this.$headerRight); + } + + this.controls[name] = indicator; + return indicator; + }, + + /** + * Returns a control + * + * @param {String} name + * @return {Object} + */ + getControl: function(name) { + if (this.isControl(name)) { + return this.controls[name]; + } + }, + + /** + * Checks if there's a control under the specified name + * + * @this {DebugBar} + * @param {String} name + * @return {Boolean} + */ + isControl: function(name) { + return typeof(this.controls[name]) != 'undefined'; + }, + + /** + * Checks if a tab with the specified name exists + * + * @this {DebugBar} + * @param {String} name + * @return {Boolean} + */ + isTab: function(name) { + return this.isControl(name) && this.controls[name] instanceof Tab; + }, + + /** + * Checks if an indicator with the specified name exists + * + * @this {DebugBar} + * @param {String} name + * @return {Boolean} + */ + isIndicator: function(name) { + return this.isControl(name) && this.controls[name] instanceof Indicator; + }, + + /** + * Removes all tabs and indicators from the debug bar and hides it + * + * @this {DebugBar} + */ + reset: function() { + this.minimize(); + var self = this; + $.each(this.controls, function(name, control) { + if (self.isTab(name)) { + control.$tab.remove(); + } + control.$el.remove(); + }); + this.controls = {}; + }, + + /** + * Open the debug bar and display the specified tab + * + * @this {DebugBar} + * @param {String} name If not specified, display the first tab + */ + showTab: function(name) { + if (!name) { + if (this.activePanelName) { + name = this.activePanelName; + } else { + name = this.firstTabName; + } + } + + if (!this.isTab(name)) { + throw new Error("Unknown tab '" + name + "'"); + } + + this.$resizehdle.show(); + this.$body.show(); + this.recomputeBottomOffset(); + + $(this.$header).find('> div > .' + csscls('active')).removeClass(csscls('active')); + $(this.$body).find('> .' + csscls('active')).removeClass(csscls('active')); + + this.controls[name].$tab.addClass(csscls('active')); + this.controls[name].$el.addClass(csscls('active')); + this.activePanelName = name; + + this.$el.removeClass(csscls('minimized')); + localStorage.setItem('phpdebugbar-visible', '1'); + localStorage.setItem('phpdebugbar-tab', name); + this.resize(); + }, + + /** + * Hide panels and minimize the debug bar + * + * @this {DebugBar} + */ + minimize: function() { + this.$header.find('> div > .' + csscls('active')).removeClass(csscls('active')); + this.$body.hide(); + this.$resizehdle.hide(); + this.recomputeBottomOffset(); + localStorage.setItem('phpdebugbar-visible', '0'); + this.$el.addClass(csscls('minimized')); + this.resize(); + }, + + /** + * Checks if the panel is minimized + * + * @return {Boolean} + */ + isMinimized: function() { + return this.$el.hasClass(csscls('minimized')); + }, + + /** + * Close the debug bar + * + * @this {DebugBar} + */ + close: function() { + this.$resizehdle.hide(); + this.$header.hide(); + this.$body.hide(); + this.$restorebtn.show(); + localStorage.setItem('phpdebugbar-open', '0'); + this.$el.addClass(csscls('closed')); + this.recomputeBottomOffset(); + }, + + /** + * Restore the debug bar + * + * @this {DebugBar} + */ + restore: function() { + this.$resizehdle.show(); + this.$header.show(); + this.$restorebtn.hide(); + localStorage.setItem('phpdebugbar-open', '1'); + var tab = localStorage.getItem('phpdebugbar-tab'); + if (this.isTab(tab)) { + this.showTab(tab); + } + this.$el.removeClass(csscls('closed')); + this.resize(); + }, + + /** + * Recomputes the padding-bottom css property of the body so + * that the debug bar never hides any content + */ + recomputeBottomOffset: function() { + if (this.options.bodyPaddingBottom) { + $('body').css('padding-bottom', this.$el.height()); + } + }, + + /** + * Sets the data map used by dataChangeHandler to populate + * indicators and widgets + * + * A data map is an object where properties are control names. + * The value of each property should be an array where the first + * item is the name of a property from the data object (nested properties + * can be specified) and the second item the default value. + * + * Example: + * {"memory": ["memory.peak_usage_str", "0B"]} + * + * @this {DebugBar} + * @param {Object} map + */ + setDataMap: function(map) { + this.dataMap = map; + }, + + /** + * Same as setDataMap() but appends to the existing map + * rather than replacing it + * + * @this {DebugBar} + * @param {Object} map + */ + addDataMap: function(map) { + $.extend(this.dataMap, map); + }, + + /** + * Resets datasets and add one set of data + * + * For this method to be usefull, you need to specify + * a dataMap using setDataMap() + * + * @this {DebugBar} + * @param {Object} data + * @return {String} Dataset's id + */ + setData: function(data) { + this.datasets = {}; + return this.addDataSet(data); + }, + + /** + * Adds a dataset + * + * If more than one dataset are added, the dataset selector + * will be displayed. + * + * For this method to be usefull, you need to specify + * a dataMap using setDataMap() + * + * @this {DebugBar} + * @param {Object} data + * @param {String} id The name of this set, optional + * @param {String} suffix + * @return {String} Dataset's id + */ + addDataSet: function(data, id, suffix) { + var label = this.datesetTitleFormater.format(id, data, suffix); + id = id || (getObjectSize(this.datasets) + 1); + this.datasets[id] = data; + + this.$datasets.append($('<option value="' + id + '">' + label + '</option>')); + if (this.$datasets.children().length > 1) { + this.$datasets.show(); + } + + this.showDataSet(id); + return id; + }, + + /** + * Loads a dataset using the open handler + * + * @param {String} id + */ + loadDataSet: function(id, suffix, callback) { + if (!this.openHandler) { + throw new Error('loadDataSet() needs an open handler'); + } + var self = this; + this.openHandler.load(id, function(data) { + self.addDataSet(data, id, suffix); + callback && callback(data); + }); + }, + + /** + * Returns the data from a dataset + * + * @this {DebugBar} + * @param {String} id + * @return {Object} + */ + getDataSet: function(id) { + return this.datasets[id]; + }, + + /** + * Switch the currently displayed dataset + * + * @this {DebugBar} + * @param {String} id + */ + showDataSet: function(id) { + this.dataChangeHandler(this.datasets[id]); + this.$datasets.val(id); + }, + + /** + * Called when the current dataset is modified. + * + * @this {DebugBar} + * @param {Object} data + */ + dataChangeHandler: function(data) { + var self = this; + $.each(this.dataMap, function(key, def) { + var d = getDictValue(data, def[0], def[1]); + if (key.indexOf(':') != -1) { + key = key.split(':'); + self.getControl(key[0]).set(key[1], d); + } else { + self.getControl(key).set('data', d); + } + }); + }, + + /** + * Sets the handler to open past dataset + * + * @this {DebugBar} + * @param {object} handler + */ + setOpenHandler: function(handler) { + this.openHandler = handler; + if (handler !== null) { + this.$openbtn.show(); + } else { + this.$openbtn.hide(); + } + }, + + /** + * Returns the handler to open past dataset + * + * @this {DebugBar} + * @return {object} + */ + getOpenHandler: function() { + return this.openHandler; + } + + }); + + DebugBar.Tab = Tab; + DebugBar.Indicator = Indicator; + + // ------------------------------------------------------------------ + + /** + * AjaxHandler + * + * Extract data from headers of an XMLHttpRequest and adds a new dataset + */ + var AjaxHandler = PhpDebugBar.AjaxHandler = function(debugbar, headerName) { + this.debugbar = debugbar; + this.headerName = headerName || 'phpdebugbar'; + }; + + $.extend(AjaxHandler.prototype, { + + /** + * Handles an XMLHttpRequest + * + * @this {AjaxHandler} + * @param {XMLHttpRequest} xhr + * @return {Bool} + */ + handle: function(xhr) { + if (!this.loadFromId(xhr)) { + return this.loadFromData(xhr); + } + return true; + }, + + /** + * Checks if the HEADER-id exists and loads the dataset using the open handler + * + * @param {XMLHttpRequest} xhr + * @return {Bool} + */ + loadFromId: function(xhr) { + var id = this.extractIdFromHeaders(xhr); + if (id && this.debugbar.openHandler) { + this.debugbar.loadDataSet(id, "(ajax)"); + return true; + } + return false; + }, + + /** + * Extracts the id from the HEADER-id + * + * @param {XMLHttpRequest} xhr + * @return {String} + */ + extractIdFromHeaders: function(xhr) { + return xhr.getResponseHeader(this.headerName + '-id'); + }, + + /** + * Checks if the HEADER exists and loads the dataset + * + * @param {XMLHttpRequest} xhr + * @return {Bool} + */ + loadFromData: function(xhr) { + var raw = this.extractDataFromHeaders(xhr); + if (!raw) { + return false; + } + + var data = this.parseHeaders(raw); + if (data.error) { + throw new Error('Error loading debugbar data: ' + data.error); + } else if(data.data) { + this.debugbar.addDataSet(data.data, data.id, "(ajax)"); + } + return true; + }, + + /** + * Extract the data as a string from headers of an XMLHttpRequest + * + * @this {AjaxHandler} + * @param {XMLHttpRequest} xhr + * @return {string} + */ + extractDataFromHeaders: function(xhr) { + var data = xhr.getResponseHeader(this.headerName); + if (!data) { + return; + } + for (var i = 1;; i++) { + var header = xhr.getResponseHeader(this.headerName + '-' + i); + if (!header) { + break; + } + data += header; + } + return decodeURIComponent(data); + }, + + /** + * Parses the string data into an object + * + * @this {AjaxHandler} + * @param {string} data + * @return {string} + */ + parseHeaders: function(data) { + return JSON.parse(data); + }, + + /** + * Attaches an event listener to jQuery.ajaxComplete() + * + * @this {AjaxHandler} + * @param {jQuery} jq Optional + */ + bindToJquery: function(jq) { + var self = this; + jq(document).ajaxComplete(function(e, xhr, settings) { + if (!settings.ignoreDebugBarAjaxHandler) { + self.handle(xhr); + } + }); + } + + }); + +})(PhpDebugBar.$); diff --git a/src/core/libs/DebugBar/Resources/icons.png b/src/core/libs/DebugBar/Resources/icons.png new file mode 100755 index 0000000000000000000000000000000000000000..5dc6d9c8ca03a3f4d074c4c273ad5449f4c46b55 GIT binary patch literal 500 zcmV<Q0So?#P)<h;3K|Lk000e1NJLTq001Ze000gM1ONa4_X3v900002VoOIv0RM-N z%)bBt010qNS#tmY3ljhU3ljkVnw%H_000McNliru-3kU2FANPToyGtF0fk9KK~y-) zwUaSR!%!53zn3N`#?qQWOh7~^tzAqj4kCi?PL3|3NCr0t9s3{Z9IY<uu1j$;po@!& zi$ey%Ax@<Q1<~3#q!FvHf}nSL@1A!K_nvzn{Beli63i5LqyeZ01K)AA{cM*4b3p^l z6sKGTD_!J5g+UYmT4};KABYY?b2q)LQS;1MNO*?*S^&AE_35m9x&@sT4oxY5Vb?q` zYz>Xxsh~^CJrC!LKRKrY?5wT3PZ<rv1`W{t^4dff!Ex6bVegw2AD#+;P`#X4cb_s5 zsQYE7cqW=Mx#{4%n7c?0%dl+aaFxhk(JbA(v|`|;Rl1SO!MJPX`iAA$WaXoIGnMcR zTWbTa)UMxVgNBS04&}C!^U`ruj~2vpyTVvb_jMmM3_Ib;tFU^sc{wtAAfBVy1Nr;* zD4enrN#^h6w7!jAX<qlYj^kwlPByJ-G>YO`+0lKgda~JNX_n;q?7paXEKoQ`KUbm& qp-O>AaVsZ=Gx6X061U=k|A}|zdur)rMSJxC0000<MNUMnLSTZWli4Hy literal 0 HcmV?d00001 diff --git a/src/core/libs/DebugBar/Resources/openhandler.css b/src/core/libs/DebugBar/Resources/openhandler.css new file mode 100755 index 0000000..b5dc852 --- /dev/null +++ b/src/core/libs/DebugBar/Resources/openhandler.css @@ -0,0 +1,69 @@ +div.phpdebugbar-openhandler-overlay { + position: fixed; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: #000; + opacity: .3; + z-index: 20000; +} + +div.phpdebugbar-openhandler { + position: fixed; + margin: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 70%; + height: 70%; + background: #fff; + border: 2px solid #888; + overflow: auto; + z-index: 20001; + font-family: arial; + font-size: 14px; + padding-bottom: 10px; +} + div.phpdebugbar-openhandler a { + color: #555; + } + div.phpdebugbar-openhandler .phpdebugbar-openhandler-header { + background: #efefef url(php-icon.png) no-repeat 5px 4px; + padding-left: 29px; + min-height: 26px; + line-height: 25px; + color: #555; + margin-bottom: 10px; + } + div.phpdebugbar-openhandler .phpdebugbar-openhandler-header a { + font-size: 14px; + color: #555; + text-decoration: none; + float: right; + padding: 5px 8px; + } + div.phpdebugbar-openhandler table { + width: 100%; + table-layout: fixed; + font-size: 14px; + } + div.phpdebugbar-openhandler table td { + padding: 6px 3px; + border-bottom: 1px solid #ddd; + } + div.phpdebugbar-openhandler table td a{ + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions { + text-align: center; + padding: 7px 0; + } + div.phpdebugbar-openhandler .phpdebugbar-openhandler-actions a { + margin: 0 10px; + color: #555; + } diff --git a/src/core/libs/DebugBar/Resources/openhandler.js b/src/core/libs/DebugBar/Resources/openhandler.js new file mode 100755 index 0000000..dce96df --- /dev/null +++ b/src/core/libs/DebugBar/Resources/openhandler.js @@ -0,0 +1,201 @@ +if (typeof(PhpDebugBar) == 'undefined') { + // namespace + var PhpDebugBar = {}; + PhpDebugBar.$ = jQuery; +} + +(function($) { + + var csscls = function(cls) { + return PhpDebugBar.utils.csscls(cls, 'phpdebugbar-openhandler-'); + }; + + PhpDebugBar.OpenHandler = PhpDebugBar.Widget.extend({ + + className: 'phpdebugbar-openhandler', + + defaults: { + items_per_page: 20 + }, + + render: function() { + var self = this; + + this.$el.appendTo('body').hide(); + this.$closebtn = $('<a href="javascript:"><i class="fa fa-times"></i></a>'); + this.$table = $('<tbody />'); + $('<div>PHP DebugBar | Open</div>').addClass(csscls('header')).append(this.$closebtn).appendTo(this.$el); + $('<table><thead><tr><th width="150">Date</th><th width="55">Method</th><th>URL</th><th width="100">IP</th><th width="100">Filter data</th></tr></thead></table>').append(this.$table).appendTo(this.$el); + this.$actions = $('<div />').addClass(csscls('actions')).appendTo(this.$el); + + this.$closebtn.on('click', function() { + self.hide(); + }); + + this.$loadmorebtn = $('<a href="javascript:">Load more</a>') + .appendTo(this.$actions) + .on('click', function() { + self.find(self.last_find_request, self.last_find_request.offset + self.get('items_per_page'), self.handleFind.bind(self)); + }); + + this.$showonlycurrentbtn = $('<a href="javascript:">Show only current URL</a>') + .appendTo(this.$actions) + .on('click', function() { + self.$table.empty(); + self.find({uri: window.location.pathname}, 0, self.handleFind.bind(self)); + }); + + this.$showallbtn = $('<a href="javascript:">Show all</a>') + .appendTo(this.$actions) + .on('click', function() { + self.refresh(); + }); + + this.$clearbtn = $('<a href="javascript:">Delete all</a>') + .appendTo(this.$actions) + .on('click', function() { + self.clear(function() { + self.hide(); + }); + }); + + this.addSearch(); + + this.$overlay = $('<div />').addClass(csscls('overlay')).hide().appendTo('body'); + this.$overlay.on('click', function() { + self.hide(); + }); + }, + + refresh: function() { + this.$table.empty(); + this.$loadmorebtn.show(); + this.find({}, 0, this.handleFind.bind(this)); + }, + + addSearch: function(){ + var self = this; + var searchBtn = $('<button />') + .text('Search') + .on('click', function(e) { + self.$table.empty(); + var search = {}; + var a = $(this).parent().serializeArray(); + $.each(a, function() { + if(this.value){ + search[this.name] = this.value; + } + }); + + self.find(search, 0, self.handleFind.bind(self)); + e.preventDefault(); + }); + + $('<form />') + .append('<br/><b>Filter results</b><br/>') + .append('Method: <select name="method"><option></option><option>GET</option><option>POST</option><option>PUT</option><option>DELETE</option></select><br/>') + .append('Uri: <input type="text" name="uri"><br/>') + .append('IP: <input type="text" name="ip"><br/>') + .append(searchBtn) + .appendTo(this.$actions); + }, + + handleFind: function(data) { + var self = this; + $.each(data, function(i, meta) { + var a = $('<a href="javascript:" />') + .text('Load dataset') + .on('click', function(e) { + self.hide(); + self.load(meta['id'], function(data) { + self.callback(meta['id'], data); + }); + e.preventDefault(); + }); + + var method = $('<a href="javascript:" />') + .text(meta['method']) + .on('click', function(e) { + self.$table.empty(); + self.find({method: meta['method']}, 0, self.handleFind.bind(self)); + e.preventDefault(); + }); + + var uri = $('<a href="javascript:" />') + .text(meta['uri']) + .on('click', function(e) { + self.hide(); + self.load(meta['id'], function(data) { + self.callback(meta['id'], data); + }); + e.preventDefault(); + }); + + var ip = $('<a href="javascript:" />') + .text(meta['ip']) + .on('click', function(e) { + self.$table.empty(); + self.find({ip: meta['ip']}, 0, self.handleFind.bind(self)); + e.preventDefault(); + }); + + var search = $('<a href="javascript:" />') + .text('Show URL') + .on('click', function(e) { + self.$table.empty(); + self.find({uri: meta['uri']}, 0, self.handleFind.bind(self)); + e.preventDefault(); + }); + + $('<tr />') + .append('<td>' + meta['datetime'] + '</td>') + .append('<td>' + meta['method'] + '</td>') + .append($('<td />').append(uri)) + .append($('<td />').append(ip)) + .append($('<td />').append(search)) + .appendTo(self.$table); + }); + if (data.length < this.get('items_per_page')) { + this.$loadmorebtn.hide(); + } + }, + + show: function(callback) { + this.callback = callback; + this.$el.show(); + this.$overlay.show(); + this.refresh(); + }, + + hide: function() { + this.$el.hide(); + this.$overlay.hide(); + }, + + find: function(filters, offset, callback) { + var data = $.extend({}, filters, {max: this.get('items_per_page'), offset: offset || 0}); + this.last_find_request = data; + this.ajax(data, callback); + }, + + load: function(id, callback) { + this.ajax({op: "get", id: id}, callback); + }, + + clear: function(callback) { + this.ajax({op: "clear"}, callback); + }, + + ajax: function(data, callback) { + $.ajax({ + dataType: 'json', + url: this.get('url'), + data: data, + success: callback, + ignoreDebugBarAjaxHandler: true + }); + } + + }); + +})(PhpDebugBar.$); diff --git a/src/core/libs/DebugBar/Resources/php-icon.png b/src/core/libs/DebugBar/Resources/php-icon.png new file mode 100755 index 0000000000000000000000000000000000000000..2cb46bf4ef43614df269b2d6b1119a5e5597eb53 GIT binary patch literal 3621 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 literal 0 HcmV?d00001 diff --git a/src/core/libs/DebugBar/Resources/vendor/font-awesome/css/font-awesome.min.css b/src/core/libs/DebugBar/Resources/vendor/font-awesome/css/font-awesome.min.css new file mode 100755 index 0000000..3d920fc --- /dev/null +++ b/src/core/libs/DebugBar/Resources/vendor/font-awesome/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.1.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.1.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.1.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.1.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-square:before,.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"} \ No newline at end of file diff --git a/src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/FontAwesome.otf b/src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/FontAwesome.otf new file mode 100755 index 0000000000000000000000000000000000000000..3461e3fce6a37f2321ecbe64707f04c0a4f05424 GIT binary patch literal 75188 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 DgjuED literal 0 HcmV?d00001 diff --git a/src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.eot b/src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.eot new file mode 100755 index 0000000000000000000000000000000000000000..6cfd56609567bc9db55186415c694d1d32808fc2 GIT binary patch literal 72449 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 literal 0 HcmV?d00001 diff --git a/src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.svg b/src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.svg new file mode 100755 index 0000000..a9f8469 --- /dev/null +++ b/src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.svg @@ -0,0 +1,504 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata></metadata> +<defs> +<font id="fontawesomeregular" horiz-adv-x="1536" > +<font-face units-per-em="1792" ascent="1536" descent="-256" /> +<missing-glyph horiz-adv-x="448" /> +<glyph unicode=" " horiz-adv-x="448" /> +<glyph unicode="&#x09;" horiz-adv-x="448" /> +<glyph unicode="&#xa0;" horiz-adv-x="448" /> +<glyph unicode="&#xa8;" horiz-adv-x="1792" /> +<glyph unicode="&#xa9;" horiz-adv-x="1792" /> +<glyph unicode="&#xae;" horiz-adv-x="1792" /> +<glyph unicode="&#xb4;" horiz-adv-x="1792" /> +<glyph unicode="&#xc6;" horiz-adv-x="1792" /> +<glyph unicode="&#xd8;" horiz-adv-x="1792" /> +<glyph unicode="&#x2000;" horiz-adv-x="768" /> +<glyph unicode="&#x2001;" horiz-adv-x="1537" /> +<glyph unicode="&#x2002;" horiz-adv-x="768" /> +<glyph unicode="&#x2003;" horiz-adv-x="1537" /> +<glyph unicode="&#x2004;" horiz-adv-x="512" /> +<glyph unicode="&#x2005;" horiz-adv-x="384" /> +<glyph unicode="&#x2006;" horiz-adv-x="256" /> +<glyph unicode="&#x2007;" horiz-adv-x="256" /> +<glyph unicode="&#x2008;" horiz-adv-x="192" /> +<glyph unicode="&#x2009;" horiz-adv-x="307" /> +<glyph unicode="&#x200a;" horiz-adv-x="85" /> +<glyph unicode="&#x202f;" horiz-adv-x="307" /> +<glyph unicode="&#x205f;" horiz-adv-x="384" /> +<glyph unicode="&#x2122;" horiz-adv-x="1792" /> +<glyph unicode="&#x221e;" horiz-adv-x="1792" /> +<glyph unicode="&#x2260;" horiz-adv-x="1792" /> +<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" /> +<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M93 1350q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78z" /> +<glyph unicode="&#xf001;" d="M0 -64q0 50 34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5 q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89z" /> +<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M0 704q0 143 55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5z M256 704q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5z" /> +<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M0 32v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113zM128 32q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5 t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768zM128 1120q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317 q54 43 100.5 115.5t46.5 131.5v11v13.5t-0.5 13t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5z" /> +<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M0 940q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138z " /> +<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M0 889q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48z" /> +<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M0 889q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354 q-25 27 -25 48zM221 829l306 -297l-73 -421l378 199l377 -199l-72 421l306 297l-422 62l-189 382l-189 -382z" /> +<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M0 131q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5q0 -120 -73 -189.5t-194 -69.5 h-874q-121 0 -194 69.5t-73 189.5zM320 1024q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5z" /> +<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M0 -96v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113zM128 64v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45zM128 320q0 -26 19 -45t45 -19h128 q26 0 45 19t19 45v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128zM128 704q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128zM128 1088q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v128q0 26 -19 45t-45 19 h-128q-26 0 -45 -19t-19 -45v-128zM512 -64q0 -26 19 -45t45 -19h768q26 0 45 19t19 45v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512zM512 704q0 -26 19 -45t45 -19h768q26 0 45 19t19 45v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512zM1536 64 v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45zM1536 320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128zM1536 704q0 -26 19 -45t45 -19h128q26 0 45 19t19 45 v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128zM1536 1088q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128z" /> +<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M0 128v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90zM0 896v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90zM896 128v384q0 52 38 90t90 38h512q52 0 90 -38 t38 -90v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90zM896 896v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90z" /> +<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M0 96v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM0 608v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM0 1120v192q0 40 28 68t68 28h320q40 0 68 -28 t28 -68v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM640 96v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM640 608v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68zM640 1120v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM1280 96v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM1280 608v192 q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM1280 1120v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68z" /> +<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M0 96v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM0 608v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM0 1120v192q0 40 28 68t68 28h320q40 0 68 -28 t28 -68v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM640 96v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68zM640 608v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68zM640 1120v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68z" /> +<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M121 608q0 40 28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68t-28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68z" /> +<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M110 214q0 40 28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68t-28 -68l-294 -294l294 -294q28 -28 28 -68t-28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294 q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68z" /> +<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M0 704q0 143 55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90t-37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5z M256 704q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5zM384 672v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224q13 0 22.5 -9.5t9.5 -22.5v-64 q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M0 704q0 143 55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90t-37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5z M256 704q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5zM384 672v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf011;" d="M0 640q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181 q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298zM640 768v640q0 52 38 90t90 38t90 -38t38 -90v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90z" /> +<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M0 -96v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23zM384 -96v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23zM768 -96v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576 q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23zM1152 -96v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23zM1536 -96v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf013;" d="M0 531v222q0 12 8 23t19 13l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10 q129 -119 165 -170q7 -8 7 -22q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108 q-44 -23 -91 -38q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5z M512 640q0 -106 75 -181t181 -75t181 75t75 181t-75 181t-181 75t-181 -75t-75 -181z" /> +<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M0 1056v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23zM256 76q0 -22 7 -40.5 t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5v948h-896v-948zM384 224v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM640 224v576q0 14 9 23t23 9h64 q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23zM896 224v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M26 636.5q1 13.5 11 21.5l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5zM256 64 v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf016;" d="M0 -160v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 -128h1280v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536zM1024 1024h376q-10 29 -22 41l-313 313q-12 12 -41 22 v-376z" /> +<glyph unicode="&#xf017;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73 t-198 -198t-73 -273zM512 544v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M50 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256 q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73zM809 540q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4z" /> +<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M0 96v320q0 40 28 68t68 28h465l135 -136q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68zM325 985q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39q17 -41 -14 -70 l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70zM1152 192q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45zM1408 192q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45z" /> +<glyph unicode="&#xf01a;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73 t-198 -198t-73 -273zM418 620q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35z" /> +<glyph unicode="&#xf01b;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73 t-198 -198t-73 -273zM416 672q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf01c;" d="M0 64v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552q25 -61 25 -123v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45zM197 576h316l95 -192h320l95 192h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8 t-2.5 -8z" /> +<glyph unicode="&#xf01d;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73 t-198 -198t-73 -273zM512 320v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55t-32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56z" /> +<glyph unicode="&#xf01e;" d="M0 640q0 156 61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5 t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q14 0 25 -9l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298z" /> +<glyph unicode="&#xf021;" d="M0 0v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129 q-19 -19 -45 -19t-45 19t-19 45zM18 800v7q65 268 270 434.5t480 166.5q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179 q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M0 160v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113zM128 160q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832z M256 288v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM256 544v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5z M256 800v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM512 288v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5z M512 544v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5zM512 800v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5z " /> +<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M0 96v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68zM320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192z" /> +<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M64 1280q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110zM320 320v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19 q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M0 650q0 151 67 291t179 242.5t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32 q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32 q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314z" /> +<glyph unicode="&#xf026;" horiz-adv-x="768" d="M0 448v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M0 448v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45zM908 464q0 21 12 35.5t29 25t34 23t29 35.5t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5 q15 0 25 -5q70 -27 112.5 -93t42.5 -142t-42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5z" /> +<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M0 448v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45zM908 464q0 21 12 35.5t29 25t34 23t29 35.5t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5 q15 0 25 -5q70 -27 112.5 -93t42.5 -142t-42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5zM1008 228q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5 q140 -59 225 -188.5t85 -282.5t-85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45zM1109 -7q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19 q13 0 26 -5q211 -91 338 -283.5t127 -422.5t-127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M0 0v640h640v-640h-640zM0 768v640h640v-640h-640zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM256 256v128h128v-128h-128zM256 1024v128h128v-128h-128zM768 0v640h384v-128h128v128h128v-384h-384v128h-128v-384h-128zM768 768v640h640v-640h-640z M896 896h384v384h-384v-384zM1024 0v128h128v-128h-128zM1024 1024v128h128v-128h-128zM1280 0v128h128v-128h-128z" /> +<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M0 0v1408h63v-1408h-63zM94 1v1407h32v-1407h-32zM189 1v1407h31v-1407h-31zM346 1v1407h31v-1407h-31zM472 1v1407h62v-1407h-62zM629 1v1407h31v-1407h-31zM692 1v1407h31v-1407h-31zM755 1v1407h31v-1407h-31zM880 1v1407h63v-1407h-63zM1037 1v1407h63v-1407h-63z M1163 1v1407h63v-1407h-63zM1289 1v1407h63v-1407h-63zM1383 1v1407h63v-1407h-63zM1541 1v1407h94v-1407h-94zM1666 1v1407h32v-1407h-32zM1729 0v1408h63v-1408h-63z" /> +<glyph unicode="&#xf02b;" d="M0 864v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117zM192 1088q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5z" /> +<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M0 864v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117zM192 1088q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5zM704 1408h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5z" /> +<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M10 184q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23 t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57 q38 -15 59 -43q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5zM575 1056 q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" /> +<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M0 7v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62z" /> +<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M0 160v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v160h-224 q-13 0 -22.5 9.5t-9.5 22.5zM384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1408 576q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45z" /> +<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M0 128v896q0 106 75 181t181 75h224l51 136q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181zM512 576q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5 t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5zM672 576q0 119 84.5 203.5t203.5 84.5t203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5z" /> +<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M0 -128l2 79q23 7 56 12.5t57 10.5t49.5 14.5t44.5 29t31 50.5l237 616l280 724h75h53q8 -14 11 -21l205 -480q33 -78 106 -257.5t114 -274.5q15 -34 58 -144.5t72 -168.5q20 -45 35 -57q19 -15 88 -29.5t84 -20.5q6 -38 6 -57q0 -4 -0.5 -13t-0.5 -13q-63 0 -190 8 t-191 8q-76 0 -215 -7t-178 -8q0 43 4 78l131 28q1 0 12.5 2.5t15.5 3.5t14.5 4.5t15 6.5t11 8t9 11t2.5 14q0 16 -31 96.5t-72 177.5t-42 100l-450 2q-26 -58 -76.5 -195.5t-50.5 -162.5q0 -22 14 -37.5t43.5 -24.5t48.5 -13.5t57 -8.5t41 -4q1 -19 1 -58q0 -9 -2 -27 q-58 0 -174.5 10t-174.5 10q-8 0 -26.5 -4t-21.5 -4q-80 -14 -188 -14zM555 527q33 0 136.5 -2t160.5 -2q19 0 57 2q-87 253 -184 452z" /> +<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M0 -128l2 94q15 4 85 16t106 27q7 12 12.5 27t8.5 33.5t5.5 32.5t3 37.5t0.5 34v35.5v30q0 982 -22 1025q-4 8 -22 14.5t-44.5 11t-49.5 7t-48.5 4.5t-30.5 3l-4 83q98 2 340 11.5t373 9.5q23 0 68.5 -0.5t67.5 -0.5q70 0 136.5 -13t128.5 -42t108 -71t74 -104.5 t28 -137.5q0 -52 -16.5 -95.5t-39 -72t-64.5 -57.5t-73 -45t-84 -40q154 -35 256.5 -134t102.5 -248q0 -100 -35 -179.5t-93.5 -130.5t-138 -85.5t-163.5 -48.5t-176 -14q-44 0 -132 3t-132 3q-106 0 -307 -11t-231 -12zM533 1292q0 -50 4 -151t4 -152q0 -27 -0.5 -80 t-0.5 -79q0 -46 1 -69q42 -7 109 -7q82 0 143 13t110 44.5t74.5 89.5t25.5 142q0 70 -29 122.5t-79 82t-108 43.5t-124 14q-50 0 -130 -13zM538.5 165q0.5 -37 4.5 -83.5t12 -66.5q74 -32 140 -32q376 0 376 335q0 114 -41 180q-27 44 -61.5 74t-67.5 46.5t-80.5 25 t-84 10.5t-94.5 2q-73 0 -101 -10q0 -53 -0.5 -159t-0.5 -158q0 -8 -1 -67.5t-0.5 -96.5z" /> +<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q6 2 81.5 21.5t111.5 37.5q28 35 41 101q1 7 62 289t114 543.5t52 296.5v25q-24 13 -54.5 18.5t-69.5 8t-58 5.5l19 103q33 -2 120 -6.5t149.5 -7t120.5 -2.5q48 0 98.5 2.5t121 7t98.5 6.5q-5 -39 -19 -89q-30 -10 -101.5 -28.5t-108.5 -33.5 q-8 -19 -14 -42.5t-9 -40t-7.5 -45.5t-6.5 -42q-27 -148 -87.5 -419.5t-77.5 -355.5q-2 -9 -13 -58t-20 -90t-16 -83.5t-6 -57.5l1 -18q17 -4 185 -31q-3 -44 -16 -99q-11 0 -32.5 -1.5t-32.5 -1.5q-29 0 -87 10t-86 10q-138 2 -206 2q-51 0 -143 -9t-121 -11z" /> +<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M0 1023v383l81 1l54 -27q12 -5 211 -5q44 0 132 2t132 2q36 0 107.5 -0.5t107.5 -0.5h293q6 0 21 -0.5t20.5 0t16 3t17.5 9t15 17.5l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 48t-14.5 73.5t-7.5 35.5 q-6 8 -12 12.5t-15.5 6t-13 2.5t-18 0.5t-16.5 -0.5q-17 0 -66.5 0.5t-74.5 0.5t-64 -2t-71 -6q-9 -81 -8 -136q0 -94 2 -388t2 -455q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9 t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27q19 42 19 383q0 101 -3 303t-3 303v117q0 2 0.5 15.5t0.5 25t-1 25.5t-3 24t-5 14q-11 12 -162 12q-33 0 -93 -12t-80 -26q-19 -13 -34 -72.5t-31.5 -111t-42.5 -53.5q-42 26 -56 44zM1414 109.5q9 18.5 42 18.5h80v1024 h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80q33 0 42 -18.5t-11 -44.5l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5z" /> +<glyph unicode="&#xf035;" d="M0 1023v383l81 1l54 -27q12 -5 211 -5q44 0 132 2t132 2q70 0 246.5 1t304.5 0.5t247 -4.5q33 -1 56 31l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 47.5t-15 73.5t-7 36q-10 13 -27 19q-5 2 -66 2q-30 0 -93 1 t-103 1t-94 -2t-96 -7q-9 -81 -8 -136l1 -152v52q0 -55 1 -154t1.5 -180t0.5 -153q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29 t78 27q7 16 11.5 74t6 145.5t1.5 155t-0.5 153.5t-0.5 89q0 7 -2.5 21.5t-2.5 22.5q0 7 0.5 44t1 73t0 76.5t-3 67.5t-6.5 32q-11 12 -162 12q-41 0 -163 -13.5t-138 -24.5q-19 -12 -34 -71.5t-31.5 -111.5t-42.5 -54q-42 26 -56 44zM5 -64q0 28 26 49q4 3 36 30t59.5 49 t57.5 41.5t42 19.5q13 0 20.5 -10.5t10 -28.5t2.5 -33.5t-1.5 -33t-1.5 -19.5h1024q0 2 -1.5 19.5t-1.5 33t2.5 33.5t10 28.5t20.5 10.5q12 0 42 -19.5t57.5 -41.5t59.5 -49t36 -30q26 -21 26 -49t-26 -49q-4 -3 -36 -30t-59.5 -49t-57.5 -41.5t-42 -19.5q-13 0 -20.5 10.5 t-10 28.5t-2.5 33.5t1.5 33t1.5 19.5h-1024q0 -2 1.5 -19.5t1.5 -33t-2.5 -33.5t-10 -28.5t-20.5 -10.5q-12 0 -42 19.5t-57.5 41.5t-59.5 49t-36 30q-26 21 -26 49z" /> +<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M0 64v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45zM0 448v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45zM0 832v128q0 26 19 45t45 19h1536 q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1536q-26 0 -45 19t-19 45zM0 1216v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M0 64v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45zM128 832v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45zM384 448v128q0 26 19 45t45 19h896 q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45zM512 1216v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M0 64v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45zM128 832v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1536q-26 0 -45 19t-19 45zM384 448v128q0 26 19 45t45 19h1280 q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45zM512 1216v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M0 64v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45zM0 448v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45zM0 832v128q0 26 19 45t45 19h1664 q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45zM0 1216v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M0 32v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5zM0 416v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5 t-9.5 22.5zM0 800v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5zM0 1184v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192 q-13 0 -22.5 9.5t-9.5 22.5zM384 32v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5zM384 416v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5zM384 800v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5zM384 1184v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5v-192 q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M0 32v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5zM0 1184v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5 t-9.5 22.5zM32 704q0 14 9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23zM640 416v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088 q-13 0 -22.5 9.5t-9.5 22.5zM640 800v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M0 32v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5zM0 416v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23t-9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5z M0 1184v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5zM640 416v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5 t-9.5 22.5zM640 800v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf03d;" horiz-adv-x="1792" d="M0 288v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5q39 -17 39 -59v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5 t-84.5 203.5z" /> +<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M0 32v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113zM128 32q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216z M256 128v192l320 320l160 -160l512 512l416 -416v-448h-1408zM256 960q0 80 56 136t136 56t136 -56t56 -136t-56 -136t-136 -56t-136 56t-56 136z" /> +<glyph unicode="&#xf040;" d="M0 -128v416l832 832l416 -416l-832 -832h-416zM128 128h128v-128h107l91 91l-235 235l-91 -91v-107zM298 384q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17zM896 1184l166 165q36 38 90 38q53 0 91 -38l235 -234 q37 -39 37 -91q0 -53 -37 -90l-166 -166z" /> +<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M0 896q0 212 150 362t362 150t362 -150t150 -362q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179zM256 896q0 -106 75 -181t181 -75t181 75t75 181t-75 181t-181 75t-181 -75t-75 -181z" /> +<glyph unicode="&#xf042;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73v1088q-148 0 -273 -73t-198 -198t-73 -273z" /> +<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M0 512q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275q0 -212 -150 -362t-362 -150t-362 150t-150 362zM256 384q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5 t37.5 90.5q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69z" /> +<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M0 288v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29v-190 q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5zM640 256v288l672 672l288 -288l-672 -672h-288zM736 448h96v-96h56l116 116l-152 152l-116 -116v-56zM944 688q16 -16 33 1l350 350q17 17 1 33t-33 -1l-350 -350q-17 -17 -1 -33zM1376 1280l92 92 q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68l-92 -92z" /> +<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M0 288v832q0 119 84.5 203.5t203.5 84.5h255q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29v-259 q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5zM256 704q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45l-384 -384 q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5t-38.5 114t-17.5 122z" /> +<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M0 288v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3 q20 -8 20 -29v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5zM257 768q0 33 24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110q24 -24 24 -57t-24 -57l-814 -814q-24 -24 -57 -24t-57 24l-430 430 q-24 24 -24 57z" /> +<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M0 640q0 26 19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45t-19 -45l-256 -256 q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45z" /> +<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M0 -64v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M0 -64v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710q19 19 32 13t13 -32v-710q4 11 13 19l710 710q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45 t-45 -19h-128q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M122 640q0 26 19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19l710 710q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45z" /> +<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M0 -96v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31l-1328 -738q-23 -13 -39.5 -3t-16.5 36z" /> +<glyph unicode="&#xf04c;" d="M0 -64v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45zM896 -64v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf04d;" d="M0 -64v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M0 -96v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19l-710 -710q-19 -19 -32 -13t-13 32z" /> +<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M0 -96v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710q-19 -19 -32 -13t-13 32v710 q-5 -10 -13 -19l-710 -710q-19 -19 -32 -13t-13 32z" /> +<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M0 -96v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710q-19 -19 -32 -13t-13 32z" /> +<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M1 64v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45zM1 525q-6 13 13 32l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13z" /> +<glyph unicode="&#xf053;" horiz-adv-x="1280" d="M154 704q0 26 19 45l742 742q19 19 45 19t45 -19l166 -166q19 -19 19 -45t-19 -45l-531 -531l531 -531q19 -19 19 -45t-19 -45l-166 -166q-19 -19 -45 -19t-45 19l-742 742q-19 19 -19 45z" /> +<glyph unicode="&#xf054;" horiz-adv-x="1280" d="M90 128q0 26 19 45l531 531l-531 531q-19 19 -19 45t19 45l166 166q19 19 45 19t45 -19l742 -742q19 -19 19 -45t-19 -45l-742 -742q-19 -19 -45 -19t-45 19l-166 166q-19 19 -19 45z" /> +<glyph unicode="&#xf055;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM320 576q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19 t19 45v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128z" /> +<glyph unicode="&#xf056;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM320 576q0 -26 19 -45t45 -19h768q26 0 45 19t19 45v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19 t-19 -45v-128z" /> +<glyph unicode="&#xf057;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM387 414q0 -27 19 -46l90 -90q19 -19 46 -19q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19 l90 90q19 19 19 46q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45z" /> +<glyph unicode="&#xf058;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM252 621q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45q0 28 -18 46l-91 90 q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46z" /> +<glyph unicode="&#xf059;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM417 939q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26 t37.5 -59q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213zM640 160q0 -14 9 -23t23 -9 h192q14 0 23 9t9 23v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192z" /> +<glyph unicode="&#xf05a;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM512 160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320 q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160zM640 1056q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160z" /> +<glyph unicode="&#xf05b;" d="M0 576v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143 q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45zM339 512q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5h-109q-26 0 -45 19 t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109z" /> +<glyph unicode="&#xf05c;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73 t-198 -198t-73 -273zM429 480q0 13 10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23l-137 -137l137 -137q10 -10 10 -23t-10 -23l-146 -146q-10 -10 -23 -10t-23 10l-137 137 l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23z" /> +<glyph unicode="&#xf05d;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73 t-198 -198t-73 -273zM346 640q0 26 19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45z" /> +<glyph unicode="&#xf05e;" d="M0 643q0 157 61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5t-61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61t-245 164t-163.5 246t-61 300zM224 643q0 -162 89 -299l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199 t-73 -274zM471 185q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5q0 161 -87 295z" /> +<glyph unicode="&#xf060;" d="M64 576q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5t32.5 -90.5v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90 z" /> +<glyph unicode="&#xf061;" d="M0 512v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5z" /> +<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M53 565q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651q37 -39 37 -91q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75 q-38 38 -38 90z" /> +<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M53 704q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90z" /> +<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M0 416q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45t-19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123 q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22t-13.5 30t-10.5 24q-127 285 -127 451z" /> +<glyph unicode="&#xf065;" d="M0 -64v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23t-10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45zM781 800q0 13 10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448 q26 0 45 -19t19 -45v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23z" /> +<glyph unicode="&#xf066;" d="M13 32q0 13 10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23zM768 704v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10 t23 -10l114 -114q10 -10 10 -23t-10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M0 608v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68z" /> +<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M0 608v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68z" /> +<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M122.5 408.5q13.5 51.5 59.5 77.5l266 154l-266 154q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5 l-266 -154l266 -154q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5z" /> +<glyph unicode="&#xf06a;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM624 1126l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5l18 621q0 12 -10 18 q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18zM640 161q0 -13 10 -23t23 -10h192q13 0 22 9.5t9 23.5v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190z" /> +<glyph unicode="&#xf06b;" d="M0 544v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68 t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23zM376 1120q0 -40 28 -68t68 -28h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68zM608 180q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5v56v468v192h-320v-192v-468v-56zM870 1024h194q40 0 68 28 t28 68t-28 68t-68 28q-43 0 -69 -31z" /> +<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M0 121q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96 q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5zM384 448q0 -26 19 -45t45 -19q24 0 45 19 q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45t-19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45z" /> +<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M0 -160q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64zM256 640q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100 t113.5 -122.5t72.5 -150.5t27.5 -184q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184z" /> +<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M0 576q0 34 20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69t-20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69zM128 576q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5q-152 236 -381 353 q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353zM592 704q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34t-14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5z" /> +<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M0 576q0 38 20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5q16 -10 16 -27q0 -7 -1 -9q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87 q-143 65 -263.5 173t-208.5 245q-20 31 -20 69zM128 576q167 -258 427 -375l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353zM592 704q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34t-14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5zM896 0l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69t-20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95zM1056 286l280 502q8 -45 8 -84q0 -139 -79 -253.5t-209 -164.5z" /> +<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M16 61l768 1408q17 31 47 49t65 18t65 -18t47 -49l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126zM752 992l17 -457q0 -10 10 -16.5t24 -6.5h185q14 0 23.5 6.5t10.5 16.5l18 459q0 12 -10 19q-13 11 -24 11h-220 q-11 0 -24 -11q-10 -7 -10 -21zM768 161q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190z" /> +<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M0 477q-1 13 9 25l96 97q9 9 23 9q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16 l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23z" /> +<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M0 -128v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90zM128 -128h288v288h-288v-288zM128 224 h288v320h-288v-320zM128 608h288v288h-288v-288zM384 1088q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288zM480 -128h320v288h-320v-288zM480 224h320v320h-320v-320zM480 608h320v288h-320 v-288zM864 -128h320v288h-320v-288zM864 224h320v320h-320v-320zM864 608h320v288h-320v-288zM1152 1088q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288zM1248 -128h288v288h-288v-288z M1248 224h288v320h-288v-320zM1248 608h288v288h-288v-288z" /> +<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M0 160v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23t-9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192 h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23zM0 1056v192q0 14 9 23t23 9h224q250 0 410 -225q-60 -92 -137 -273q-22 45 -37 72.5 t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23zM743 353q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23t-9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192 q-32 0 -85 -0.5t-81 -1t-73 1t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5z" /> +<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M0 640q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5t-120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5 t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281z" /> +<glyph unicode="&#xf076;" d="M0 576v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5 t-98.5 362zM0 960v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45zM1024 960v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf077;" horiz-adv-x="1792" d="M90 250.5q0 26.5 19 45.5l742 741q19 19 45 19t45 -19l742 -741q19 -19 19 -45.5t-19 -45.5l-166 -165q-19 -19 -45 -19t-45 19l-531 531l-531 -531q-19 -19 -45 -19t-45 19l-166 165q-19 19 -19 45.5z" /> +<glyph unicode="&#xf078;" horiz-adv-x="1792" d="M90 773.5q0 26.5 19 45.5l166 165q19 19 45 19t45 -19l531 -531l531 531q19 19 45 19t45 -19l166 -165q19 -19 19 -45.5t-19 -45.5l-742 -741q-19 -19 -45 -19t-45 19l-742 741q-19 19 -19 45.5z" /> +<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M0 704q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45z M640 1120q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20z " /> +<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M0 1216q0 26 19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024 q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45zM384 0q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5zM1280 0q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5t-37.5 -90.5 t-90.5 -37.5t-90.5 37.5t-37.5 90.5z" /> +<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M0 224v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158z" /> +<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M0 224v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5t-0.5 12.5zM73 56q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43 q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43z" /> +<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M64 64q0 26 19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45z" /> +<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M0 640q0 26 19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45z" /> +<glyph unicode="&#xf080;" horiz-adv-x="1920" d="M0 32v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113zM128 32q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216z M256 128v384h256v-384h-256zM640 128v896h256v-896h-256zM1024 128v640h256v-640h-256zM1408 128v1024h256v-1024h-256z" /> +<glyph unicode="&#xf081;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 286q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109 q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4q21 -63 74.5 -104 t121.5 -42q-116 -90 -261 -90q-26 0 -50 3z" /> +<glyph unicode="&#xf082;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-192v608h203l30 224h-233v143q0 54 28 83t96 29l132 1v207q-96 9 -180 9q-136 0 -218 -80.5t-82 -225.5v-166h-224v-224h224v-608h-544 q-119 0 -203.5 84.5t-84.5 203.5z" /> +<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M0 0v1280q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5zM128 0h1536v128h-1536v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM256 1216h384v128h-384v-128zM512 574 q0 -159 112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5zM640 574q0 106 75 181t181 75t181 -75t75 -181t-75 -181t-181 -75t-181 75t-75 181zM736 576q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9 t9 23t-9 23t-23 9q-66 0 -113 -47t-47 -113z" /> +<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M0 752q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41q0 -17 -49 -66t-66 -49 q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5zM192 768q0 -80 56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56 t56 136t-56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136z" /> +<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M0 549v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8 q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90 q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5zM384 640q0 -106 75 -181t181 -75 t181 75t75 181t-75 181t-181 75t-181 -75t-75 -181zM1152 58v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31 v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31zM1152 1082v140q0 16 149 31q13 29 30 52 q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71 q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31zM1408 128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5q0 52 -38 90t-90 38t-90 -38t-38 -90zM1408 1152q0 -53 37.5 -90.5 t90.5 -37.5t90.5 37.5t37.5 90.5q0 52 -38 90t-90 38t-90 -38t-38 -90z" /> +<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M0 768q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257t-94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25 t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224zM616 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5 t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132z" /> +<glyph unicode="&#xf087;" d="M0 128v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5zM128 192q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45zM384 128h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5 t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85 t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640z" /> +<glyph unicode="&#xf088;" d="M0 512v640q0 53 37.5 90.5t90.5 37.5h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186 q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5zM128 1088q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45zM384 512h32q16 0 35.5 -9 t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5 t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640z" /> +<glyph unicode="&#xf089;" horiz-adv-x="896" d="M0 889q0 37 56 46l502 73l225 455q19 41 49 41v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48z" /> +<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M0 940q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138z M128 940q0 -168 187 -355l581 -560l580 559q188 188 188 356q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5 t-21.5 -143z" /> +<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M0 288v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5q0 -4 1 -20t0.5 -26.5t-3 -23.5 t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5zM384 448v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45t-19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf08c;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM223 1030q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86z M237 122h231v694h-231v-694zM595 122h231v388q0 38 7 56q15 35 45 59.5t74 24.5q116 0 116 -157v-371h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694z" /> +<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M0 320q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19 t-19 45zM416 672q0 -14 9 -23t23 -9t23 9t9 23v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448z" /> +<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M0 288v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832 q-119 0 -203.5 84.5t-84.5 203.5zM685 576q0 13 10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23z" /> +<glyph unicode="&#xf090;" d="M0 448v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45t-19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45zM894.5 78.5q0.5 10.5 3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113 t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5q0 4 -1 20t-0.5 26.5z" /> +<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M0 928v128q0 40 28 68t68 28h288v96q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91t97.5 -37q75 0 133.5 -45.5 t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143zM128 928q0 -78 94.5 -162t235.5 -113q-74 162 -74 371 h-256v-96zM1206 653q141 29 235.5 113t94.5 162v96h-256q0 -209 -74 -371z" /> +<glyph unicode="&#xf092;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-224q-16 0 -24.5 1t-19.5 5t-16 14.5t-5 27.5v239q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204 q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52 t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -103t0.5 -68q0 -22 -11 -33.5t-22 -13t-33 -1.5h-224q-119 0 -203.5 84.5t-84.5 203.5zM271 315q3 5 13 2 q10 -5 7 -12q-5 -7 -13 -2q-10 5 -7 12zM304 290q6 6 16 -3q9 -11 2 -16q-6 -7 -16 3q-9 11 -2 16zM335 233q-9 13 0 18q9 7 17 -6q9 -12 0 -19q-8 -6 -17 7zM370 206q8 9 20 -3q12 -11 4 -19q-8 -9 -20 3q-13 11 -4 19zM419 168q4 11 19 7q16 -5 13 -16q-4 -12 -19 -6 q-17 4 -13 15zM481 154q0 11 16 11q17 2 17 -11q0 -11 -16 -11q-17 -2 -17 11zM540 158q-2 12 14 15q16 2 18 -9q2 -10 -14 -14t-18 8z" /> +<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M0 -32v320q0 40 28 68t68 28h427q21 -56 70.5 -92t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68zM325 936q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69q-17 -40 -59 -40 h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40zM1152 64q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45zM1408 64q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45z" /> +<glyph unicode="&#xf094;" d="M0 433q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5q0 -165 -70 -327.5 t-196 -288t-281 -180.5q-124 -44 -326 -44q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5zM128 434q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5 q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24 q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5z" /> +<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M0 1069q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235 t235 -174q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5 t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5z" /> +<glyph unicode="&#xf096;" horiz-adv-x="1408" d="M0 288v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5zM128 288q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47 t-47 -113v-832z" /> +<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M0 7v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62zM128 38l423 406l89 85l89 -85l423 -406 v1242h-1024v-1242z" /> +<glyph unicode="&#xf098;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 905q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5 q6 -2 30 -11t33 -12.5t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5 t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5z" /> +<glyph unicode="&#xf099;" horiz-adv-x="1664" d="M44 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5 q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145z" /> +<glyph unicode="&#xf09a;" horiz-adv-x="1024" d="M95 631v296h255v218q0 186 104 288.5t277 102.5q147 0 228 -12v-264h-157q-86 0 -116 -36t-30 -108v-189h293l-39 -296h-254v-759h-306v759h-255z" /> +<glyph unicode="&#xf09b;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -39.5 7t-12.5 30v211q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44 l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3 q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -89t0.5 -54q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5z" /> +<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M0 96v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68z" /> +<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M0 32v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113zM128 32q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v608h-1664v-608zM128 1024h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600 q-13 0 -22.5 -9.5t-9.5 -22.5v-224zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" /> +<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M0 192q0 80 56 136t136 56t136 -56t56 -136t-56 -136t-136 -56t-136 56t-56 136zM0 697v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5t259 -181.5q114 -113 181.5 -259t80.5 -306q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5 t-391.5 184.5q-25 2 -41.5 20t-16.5 43zM0 1201v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294q187 -186 294 -425.5t120 -501.5q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102 q-25 1 -42.5 19.5t-17.5 43.5z" /> +<glyph unicode="&#xf0a0;" d="M0 160v320q0 25 16 75l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113zM128 160q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5v320q0 13 -9.5 22.5t-22.5 9.5h-1216 q-13 0 -22.5 -9.5t-9.5 -22.5v-320zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM880 320q0 33 23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5t-23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5zM1136 320q0 33 23.5 56.5t56.5 23.5 t56.5 -23.5t23.5 -56.5t-23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5z" /> +<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M0 672v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50 t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113zM768 633q377 -42 768 -341v954q-394 -302 -768 -343v-270z" /> +<glyph unicode="&#xf0a2;" horiz-adv-x="1664" d="M0 128q190 161 287 397.5t97 498.5q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38 t-38 90zM183 128h1298q-164 181 -246.5 411.5t-82.5 484.5q0 256 -320 256t-320 -256q0 -254 -82.5 -484.5t-246.5 -411.5zM656 0q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16z" /> +<glyph unicode="&#xf0a3;" d="M2 435q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70l-53 -186l188 -48 q40 -10 52 -51q10 -42 -20 -70l-138 -135l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53 q-41 -12 -70 19q-31 29 -19 70l53 186l-188 48q-40 10 -52 51z" /> +<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M0 128v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179q0 -105 -75.5 -181 t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5zM128 192q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45zM384 128h32q72 0 167 -32 t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139 q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106q-69 -57 -140 -57h-32v-640z" /> +<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M0 769q0 103 76 179t180 76h374q-22 60 -22 128q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5v-640 q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181zM128 768q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119 q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5 t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576q-50 0 -89 -38.5t-39 -89.5zM1536 192q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45z" /> +<glyph unicode="&#xf0a6;" d="M0 640q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5t-90.5 -37.5h-640 q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5zM128 640q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140 v-32h640v32q0 72 32 167t64 193.5t32 179.5q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576q-20 0 -48.5 15t-55 33t-68 33t-84.5 15 q-67 0 -97.5 -44.5t-30.5 -115.5zM1152 -64q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45z" /> +<glyph unicode="&#xf0a7;" d="M0 640q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317q0 -142 -77.5 -230t-217.5 -87 l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5zM128 640q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33t55 33t48.5 15v-576q0 -50 38.5 -89 t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112 q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5zM1152 1344q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45z" /> +<glyph unicode="&#xf0a8;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM251 640q0 -27 18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502 q26 0 45 19t19 45v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45z" /> +<glyph unicode="&#xf0a9;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM256 576q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18 l362 362l91 91q18 18 18 45t-18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128z" /> +<glyph unicode="&#xf0aa;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM252 641q0 -27 18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19 t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45t-18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45z" /> +<glyph unicode="&#xf0ab;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM252 639q0 -27 18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45t-18 45l-91 91 q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45z" /> +<glyph unicode="&#xf0ac;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM226 979q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18 q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13 q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10t17 -20q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5 t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13 q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25 t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5 t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q7 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4 q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5q15 10 -7 16q-17 5 -43 -12q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8 q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 10.5t-9.5 10.5q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5 q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26 q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-5 7 -8 9q-12 4 -27 -5 q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14 q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5 q-16 0 -22 -1q-146 -80 -235 -222zM877 26q0 -6 2 -16q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7 t-10 1.5t-11.5 -7q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5z" /> +<glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M21 0q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90zM256 64q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45zM768 960q0 185 131.5 316.5t316.5 131.5q58 0 121.5 -16.5 t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25q0 -39 -23 -106q-47 -134 -164.5 -217.5t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5z" /> +<glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M0 64v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45zM0 576v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45zM0 1088v256q0 26 19 45t45 19h1664 q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45zM640 640h1024v128h-1024v-128zM1024 128h640v128h-640v-128zM1280 1152h384v128h-384v-128z" /> +<glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M5 1241q17 39 59 39h1280q42 0 59 -39q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70z" /> +<glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M0 160v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113zM0 736v384q0 66 47 113t113 47h352v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113v-384h-1792z M640 1280h512v128h-512v-128zM768 512v128h256v-128h-256z" /> +<glyph unicode="&#xf0b2;" d="M0 -64v448q0 42 40 59q39 17 69 -14l144 -144l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45 v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19l-144 144l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19 t-19 45z" /> +<glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M0 671q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5zM128 1280q0 106 75 181t181 75t181 -75t75 -181t-75 -181t-181 -75t-181 75t-75 181zM256 3q0 53 3.5 103.5 t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5 zM576 896q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5zM1280 1280q0 106 75 181t181 75t181 -75t75 -181t-75 -181t-181 -75t-181 75t-75 181zM1327 640q81 117 81 256q0 29 -5 66q66 -23 133 -23 q59 0 119 21.5t97.5 42.5t43.5 21q124 0 124 -353q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128z" /> +<glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M16 1088q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l206 -207q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204t-85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88 q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204zM208 1088q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15t21.5 -21.5t18.5 -19q33 31 33 73 q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67zM911 383q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26l147 146q28 28 28 67q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5 q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73z" /> +<glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M0 448q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5z" /> +<glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M115.5 -64.5q-34.5 63.5 21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399l503 -793q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5zM476 384h712l-272 429l-20 31v37v399h-128v-399v-37 l-20 -31z" /> +<glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M1 157q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148q4 -48 -10 -97q4 -1 12 -5 l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56l-507 -398l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207zM168 176q-25 -66 21 -108q39 -36 113 -36q100 0 192 59q81 51 106 117t-21 108q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117zM168 976q25 -66 106 -117q92 -59 192 -59q74 0 113 36q46 42 21 108t-106 117q-92 59 -192 59 q-74 0 -113 -36q-46 -42 -21 -108zM672 448l9 -8q2 -2 7 -6q4 -4 11 -12t11 -12l26 -26l160 96l96 -32l736 576l-128 64l-768 -431v-113zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 576q0 26 19 45t45 19t45 -19 t19 -45t-19 -45t-45 -19t-45 19t-19 45zM1018 391l582 -327l128 64l-520 408l-177 -138q-2 -3 -13 -7z" /> +<glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M0 224v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68zM128 256h512v256q0 40 20 88t48 76l316 316v416h-384 v-416q0 -40 -28 -68t-68 -28h-416v-640zM213 1024h299v299zM768 -128h896v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640zM853 640h299v299z" /> +<glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M4 1023q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581 q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776 q-113 115 -113 271z" /> +<glyph unicode="&#xf0c7;" d="M0 -32v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 0h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20 t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280zM384 0h768v384h-768v-384zM640 928q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v320q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320z" /> +<glyph unicode="&#xf0c8;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5z" /> +<glyph unicode="&#xf0c9;" d="M0 64v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45zM0 576v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45zM0 1088v128q0 26 19 45t45 19h1408 q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M0 128q0 80 56 136t136 56t136 -56t56 -136t-56 -136t-136 -56t-136 56t-56 136zM0 640q0 80 56 136t136 56t136 -56t56 -136t-56 -136t-136 -56t-136 56t-56 136zM0 1152q0 80 56 136t136 56t136 -56t56 -136t-56 -136t-136 -56t-136 56t-56 136zM512 32v192 q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5zM512 544v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5z M512 1056v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M15 438q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105v-159h-362q-6 36 -6 54zM19 -190 l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66zM34 1400l136 127h106v-404h108v-99 h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54zM512 32v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5zM512 544v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5v-192 q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5zM512 1056v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M0 544v64q0 14 9 23t23 9h1728q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23zM384 972q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6l-14 2q-50 149 -103 205 q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743q-28 35 -51 80q-48 97 -48 188zM414 154q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22 q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156z" /> +<glyph unicode="&#xf0cd;" d="M0 -32v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-1472q-14 0 -23 -9t-9 -23zM0 1405q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5 t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2 q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195 q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39q-37 2 -45 4z" /> +<glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M0 160v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113zM128 160q0 -14 9 -23t23 -9h320q14 0 23 9t9 23v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192zM128 544q0 -14 9 -23t23 -9h320 q14 0 23 9t9 23v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192zM128 928q0 -14 9 -23t23 -9h320q14 0 23 9t9 23v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192zM640 160q0 -14 9 -23t23 -9h320q14 0 23 9t9 23v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9 t-9 -23v-192zM640 544q0 -14 9 -23t23 -9h320q14 0 23 9t9 23v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192zM640 928q0 -14 9 -23t23 -9h320q14 0 23 9t9 23v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192zM1152 160q0 -14 9 -23t23 -9h320q14 0 23 9t9 23 v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192zM1152 544q0 -14 9 -23t23 -9h320q14 0 23 9t9 23v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192zM1152 928q0 -14 9 -23t23 -9h320q14 0 23 9t9 23v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192z" /> +<glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M27 160q0 27 18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45t-18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45zM128 1408l98 30l30 98l30 -98l98 -30l-98 -30l-30 -98l-30 98zM320 1216l196 60l60 196l60 -196l196 -60l-196 -60 l-60 -196l-60 196zM768 1408l98 30l30 98l30 -98l98 -30l-98 -30l-30 -98l-30 98zM1083 1062l107 -107l293 293l-107 107zM1408 768l98 30l30 98l30 -98l98 -30l-98 -30l-30 -98l-30 98z" /> +<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M64 192q0 26 19 45t45 19v320q0 8 -0.5 35t0 38t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45v-1024q0 -15 -4 -26.5t-13.5 -18.5t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5 q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM384 128q0 -52 38 -90t90 -38 t90 38t38 90t-38 90t-90 38t-90 -38t-38 -90zM1280 128q0 -52 38 -90t90 -38t90 38t38 90t-38 90t-90 38t-90 -38t-38 -90z" /> +<glyph unicode="&#xf0d2;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63 q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5 q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423z" /> +<glyph unicode="&#xf0d3;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5 q-104 0 -194.5 -28.5t-153 -76.5t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118 q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5z" /> +<glyph unicode="&#xf0d4;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM276 309q0 -43 18.5 -77.5t48.5 -56.5t69 -37t77.5 -21t76.5 -6q60 0 120.5 15.5t113.5 46t86 82.5t33 117 q0 49 -20 89.5t-49 66.5t-58 47.5t-49 44t-20 44.5t15.5 42.5t37.5 39.5t44 42t37.5 59.5t15.5 82.5q0 60 -22.5 99.5t-72.5 90.5h83l88 64h-265q-85 0 -161 -32t-127.5 -98t-51.5 -153q0 -93 64.5 -154.5t158.5 -61.5q22 0 43 3q-13 -29 -13 -54q0 -44 40 -94 q-175 -12 -257 -63q-47 -29 -75.5 -73t-28.5 -95zM395 338q0 46 25 80t65.5 51.5t82 25t84.5 7.5q20 0 31 -2q2 -1 23 -16.5t26 -19t23 -18t24.5 -22t19 -22.5t17 -26t9 -26.5t4.5 -31.5q0 -76 -58.5 -112.5t-139.5 -36.5q-41 0 -80.5 9.5t-75.5 28.5t-58 53t-22 78z M462 969q0 61 32 104t92 43q53 0 93.5 -45t58 -101t17.5 -107q0 -60 -33 -99.5t-92 -39.5q-53 0 -93 42.5t-57.5 96.5t-17.5 106zM960 672h128v-160h64v160h128v64h-128v128h-64v-128h-128v-64z" /> +<glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M32 182q0 81 44.5 150t118.5 115q131 82 404 100q-32 42 -47.5 74t-15.5 73q0 36 21 85q-46 -4 -68 -4q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q77 66 182.5 98t217.5 32h418l-138 -88h-131q74 -63 112 -133t38 -160q0 -72 -24.5 -129.5t-59 -93t-69.5 -65 t-59.5 -61.5t-24.5 -66q0 -36 32 -70.5t77.5 -68t90.5 -73.5t77 -104t32 -142q0 -90 -48 -173q-72 -122 -211 -179.5t-298 -57.5q-132 0 -246.5 41.5t-171.5 137.5q-37 60 -37 131zM218 228q0 -70 35 -123.5t91.5 -83t119 -44t127.5 -14.5q58 0 111.5 13t99 39t73 73 t27.5 109q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -48 2q-53 0 -105 -7t-107.5 -25t-97 -46t-68.5 -74.5t-27 -105.5zM324 1222q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26q38 0 78 16.5t66 43.5q53 57 53 159 q0 58 -17 125t-48.5 129.5t-84.5 103.5t-117 41q-42 0 -82.5 -19.5t-65.5 -52.5q-47 -59 -47 -160zM1084 731v108h212v217h105v-217h213v-108h-213v-219h-105v219h-212z" /> +<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M0 64v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45zM128 384q106 0 181 -75t75 -181h1152q0 106 75 181t181 75v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512zM640 640q0 70 21 142 t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142t-21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142zM762 791l77 -80q42 37 55 57h2v-288h-128v-96h384v96h-128v448h-114z" /> +<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M0 832q0 26 19 45t45 19h896q26 0 45 -19t19 -45t-19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45z" /> +<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M0 320q0 26 19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M64 640q0 26 19 45l448 448q19 19 45 19t45 -19t19 -45v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45z" /> +<glyph unicode="&#xf0da;" horiz-adv-x="640" d="M0 192v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45t-19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45z" /> +<glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M0 32v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113zM128 32q0 -13 9.5 -22.5t22.5 -9.5h608v1152h-640v-1120zM896 0h608q13 0 22.5 9.5t9.5 22.5v1120h-640v-1152z" /> +<glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M0 448q0 26 19 45t45 19h896q26 0 45 -19t19 -45t-19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45zM0 832q0 26 19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M0 448q0 26 19 45t45 19h896q26 0 45 -19t19 -45t-19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45z" /> +<glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M0 832q0 26 19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M0 32v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113zM0 1098q0 78 41.5 130t118.5 52h1472 q65 0 112.5 -47t47.5 -113q0 -79 -49 -151t-122 -123q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5z" /> +<glyph unicode="&#xf0e1;" d="M0 1217q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122zM19 -80v991h330v-991h-330zM531 -80q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5v-568 h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329z" /> +<glyph unicode="&#xf0e2;" d="M0 832v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298t-61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12 q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M40 736q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18 q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5 q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5 t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68z" /> +<glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M0 384q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29q-141 221 -141 483zM128 384q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5z M320 832q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5zM710 241q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91l101 382q6 26 -7.5 48.5t-38.5 29.5t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5 t-63 -98.5zM768 1024q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5zM1216 832q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5zM1408 384q0 -53 37.5 -90.5 t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5z" /> +<glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M0 640q0 174 120 321.5t326 233t450 85.5t450 -85.5t326 -233t120 -321.5t-120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5 t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281zM128 640q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5t-381.5 -69.5 t-282 -187.5t-104.5 -255z" /> +<glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M0 768q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257t-94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25 t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224zM128 768q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52t-286 -52t-211.5 -141t-78.5 -191zM616 132 q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22 t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132z" /> +<glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M1 551l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39z" /> +<glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M0 -32v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68z" /> +<glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M0 681q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17 q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5z M384 128q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180zM768 1310v98q0 26 19 45t45 19t45 -19t19 -45v-98q-42 2 -64 2t-64 -2z" /> +<glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M0 96v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88v-672q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68zM256 1312q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5v64 q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64zM768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1280 640h299l-299 299v-299z" /> +<glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M0 960q0 99 44.5 184.5t117 142t164 89t186.5 32.5t186.5 -32.5t164 -89t117 -142t44.5 -184.5q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47q0 -46 -31.5 -71t-77.5 -25 q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268zM128 960q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228 q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134zM480 1088q0 13 9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5 q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M0 256q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22zM0 800v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23 t23 9q12 0 24 -10l319 -319q9 -9 9 -23t-9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M0 448q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5z M512 608q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5z" /> +<glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M0 448q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5z M512 672q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24z" /> +<glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M0 131q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89 q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5 t81 -103t47.5 -132.5t24 -138t5.5 -131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190zM256 192q0 26 19 45t45 19t45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45zM320 1024q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5 t-271.5 112.5t-112.5 271.5z" /> +<glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M0 768v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48 q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5 t-131.5 271.5v132q-164 20 -274 128t-110 252zM1152 832q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45z" /> +<glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M0 96v832q0 92 66 158t158 66h64v-1280h-64q-92 0 -158 66t-66 158zM384 -128v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128v-1280h-1024zM640 1152h512v128h-512v-128zM1504 -128v1280h64q92 0 158 -66t66 -158v-832q0 -92 -66 -158t-158 -66h-64z " /> +<glyph unicode="&#xf0f3;" horiz-adv-x="1664" d="M0 128q190 161 287 397.5t97 498.5q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38 t-38 90zM656 0q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16z" /> +<glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM256 480v736q0 26 19 45t45 19h1152q159 0 271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158zM1408 704h64q80 0 136 56t56 136 t-56 136t-136 56h-64v-384z" /> +<glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M0 832v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128 q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111zM768 416v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf0f6;" d="M0 -160v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 -128h1280v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536zM384 160v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64 q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23zM384 416v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23zM384 672v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23zM1024 1024h376 q-10 29 -22 41l-313 313q-12 12 -41 22v-376z" /> +<glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M0 -192v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45zM128 -128h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224h384v1536h-1152v-1536zM256 160v64q0 13 9.5 22.5t22.5 9.5h64 q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM256 416v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM256 672v64q0 13 9.5 22.5t22.5 9.5h64 q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM256 928v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM256 1184v64q0 13 9.5 22.5t22.5 9.5h64 q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM512 416v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM512 672v64q0 13 9.5 22.5t22.5 9.5h64 q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM512 928v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM512 1184v64q0 13 9.5 22.5t22.5 9.5h64 q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM768 416v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM768 672v64q0 13 9.5 22.5t22.5 9.5h64 q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM768 928v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM768 1184v64q0 13 9.5 22.5t22.5 9.5h64 q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM1024 160v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM1024 416v64q0 13 9.5 22.5t22.5 9.5h64 q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM1024 672v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM1024 928v64q0 13 9.5 22.5t22.5 9.5h64 q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM1024 1184v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M0 -192v1280q0 26 19 45t45 19h320v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45zM128 -128h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224h384v1152h-256 v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152zM256 160v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM256 416v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5 v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM256 672v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM512 416v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64 q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM512 672v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM512 1056q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128 v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320zM768 416v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5 v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM768 672v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM1024 160v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5 v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM1024 416v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5zM1024 672v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5 v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M64 192q0 26 19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45v-1152q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128 q-26 0 -45 19t-19 45zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM384 128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5zM896 800q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192 q14 0 23 9t9 23v224h224q14 0 23 9t9 23v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192zM1280 128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5z" /> +<glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M0 96v832q0 92 66 158t158 66h32v-1280h-32q-92 0 -158 66t-66 158zM352 -128v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160v-1280h-1088zM512 416q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23v192 q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192zM640 1152h512v128h-512v-128zM1536 -128v1280h32q92 0 158 -66t66 -158v-832q0 -92 -66 -158t-158 -66h-32z" /> +<glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M0 512v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q261 -58 287 -93l1 -3q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5 t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8z" /> +<glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M64 1152l32 128h480l32 128h960l32 -192l-64 -32v-800l128 -192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320zM384 768q0 -53 37.5 -90.5t90.5 -37.5h128v384h-256v-256z" /> +<glyph unicode="&#xf0fd;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 192q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45 v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896z" /> +<glyph unicode="&#xf0fe;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 576q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45 v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128z" /> +<glyph unicode="&#xf100;" horiz-adv-x="1024" d="M45 576q0 13 10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23zM429 576q0 13 10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23 l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23z" /> +<glyph unicode="&#xf101;" horiz-adv-x="1024" d="M13 160q0 13 10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23zM397 160q0 13 10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10 l466 -466q10 -10 10 -23t-10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23z" /> +<glyph unicode="&#xf102;" horiz-adv-x="1152" d="M77 224q0 13 10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23zM77 608q0 13 10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23 l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23z" /> +<glyph unicode="&#xf103;" horiz-adv-x="1152" d="M77 672q0 13 10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23zM77 1056q0 13 10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10 l50 -50q10 -10 10 -23t-10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23z" /> +<glyph unicode="&#xf104;" horiz-adv-x="640" d="M45 576q0 13 10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23z" /> +<glyph unicode="&#xf105;" horiz-adv-x="640" d="M13 160q0 13 10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23z" /> +<glyph unicode="&#xf106;" horiz-adv-x="1152" d="M77 352q0 13 10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23z" /> +<glyph unicode="&#xf107;" horiz-adv-x="1152" d="M77 800q0 13 10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23z" /> +<glyph unicode="&#xf108;" horiz-adv-x="1920" d="M0 288v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113zM128 544q0 -13 9.5 -22.5 t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832z" /> +<glyph unicode="&#xf109;" horiz-adv-x="1920" d="M0 96v96h160h1600h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68zM256 416v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088q-66 0 -113 47t-47 113zM384 416q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5 t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-704zM864 112q0 -16 16 -16h160q16 0 16 16t-16 16h-160q-16 0 -16 -16z" /> +<glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M0 160v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-832q-66 0 -113 47t-47 113zM128 288q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960zM512 128 q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45z" /> +<glyph unicode="&#xf10b;" horiz-adv-x="768" d="M0 128v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90zM96 288q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704zM288 1136 q0 -16 16 -16h160q16 0 16 16t-16 16h-160q-16 0 -16 -16zM304 128q0 -33 23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5t-23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5z" /> +<glyph unicode="&#xf10c;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73 t-198 -198t-73 -273z" /> +<glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M0 192v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136z M896 192v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136z" /> +<glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M0 832v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136zM896 832v384 q0 80 56 136t136 56h384q80 0 136 -56t56 -136v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136z" /> +<glyph unicode="&#xf110;" horiz-adv-x="1568" d="M0 640q0 66 47 113t113 47t113 -47t47 -113t-47 -113t-113 -47t-113 47t-47 113zM176 1088q0 73 51.5 124.5t124.5 51.5t124.5 -51.5t51.5 -124.5t-51.5 -124.5t-124.5 -51.5t-124.5 51.5t-51.5 124.5zM208 192q0 60 42 102t102 42q59 0 101.5 -42t42.5 -102t-42.5 -102 t-101.5 -42q-60 0 -102 42t-42 102zM608 1280q0 80 56 136t136 56t136 -56t56 -136t-56 -136t-136 -56t-136 56t-56 136zM672 0q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5zM1136 192q0 46 33 79t79 33t79 -33t33 -79 t-33 -79t-79 -33t-79 33t-33 79zM1168 1088q0 33 23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5t-23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5zM1344 640q0 40 28 68t68 28t68 -28t28 -68t-28 -68t-68 -28t-68 28t-28 68z" /> +<glyph unicode="&#xf111;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5z" /> +<glyph unicode="&#xf112;" horiz-adv-x="1792" d="M0 896q0 26 19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101 t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19l-512 512q-19 19 -19 45z" /> +<glyph unicode="&#xf113;" horiz-adv-x="1664" d="M0 496q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218q0 -87 -27 -168q136 -160 136 -398q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86t-170 -47.5t-171.5 -22t-167 -4.5 q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331zM224 320q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11 q-152 21 -195 21q-118 0 -187 -84t-69 -204zM384 320q0 40 12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82t-12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82zM1024 320q0 40 12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82t-12.5 -82t-43 -76t-72.5 -34t-72.5 34 t-43 76t-12.5 82z" /> +<glyph unicode="&#xf114;" horiz-adv-x="1664" d="M0 224v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158zM128 224q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64 q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960z" /> +<glyph unicode="&#xf115;" horiz-adv-x="1920" d="M0 224v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158zM128 331l256 315q44 53 116 87.5 t140 34.5h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-853zM171 163q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40z " /> +<glyph unicode="&#xf116;" horiz-adv-x="1792" /> +<glyph unicode="&#xf117;" horiz-adv-x="1792" /> +<glyph unicode="&#xf118;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM128 640q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 t-51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5zM384 896q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5zM402 461q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38 q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5q-37 -121 -138 -195t-228 -74t-228 74t-138 195zM896 896q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5z" /> +<glyph unicode="&#xf119;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM128 640q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 t-51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5zM384 896q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5zM402 307q37 121 138 195t228 74t228 -74t138 -195q8 -25 -4 -48.5 t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5zM896 896q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5z" /> +<glyph unicode="&#xf11a;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM128 640q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 t-51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5zM384 448q0 26 19 45t45 19h640q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45zM384 896q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5t-37.5 -90.5 t-90.5 -37.5t-90.5 37.5t-37.5 90.5zM896 896q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5z" /> +<glyph unicode="&#xf11b;" horiz-adv-x="1920" d="M0 512q0 212 150 362t362 150h896q212 0 362 -150t150 -362t-150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150t-150 362zM192 448q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23v128 q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128zM1152 384q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5zM1408 640q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5z" /> +<glyph unicode="&#xf11c;" horiz-adv-x="1920" d="M0 128v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5zM128 128h1664v896h-1664v-896zM256 272v96q0 16 16 16h96q16 0 16 -16v-96q0 -16 -16 -16h-96q-16 0 -16 16zM256 528v96 q0 16 16 16h224q16 0 16 -16v-96q0 -16 -16 -16h-224q-16 0 -16 16zM256 784v96q0 16 16 16h96q16 0 16 -16v-96q0 -16 -16 -16h-96q-16 0 -16 16zM512 272v96q0 16 16 16h864q16 0 16 -16v-96q0 -16 -16 -16h-864q-16 0 -16 16zM512 784v96q0 16 16 16h96q16 0 16 -16v-96 q0 -16 -16 -16h-96q-16 0 -16 16zM640 528v96q0 16 16 16h96q16 0 16 -16v-96q0 -16 -16 -16h-96q-16 0 -16 16zM768 784v96q0 16 16 16h96q16 0 16 -16v-96q0 -16 -16 -16h-96q-16 0 -16 16zM896 528v96q0 16 16 16h96q16 0 16 -16v-96q0 -16 -16 -16h-96q-16 0 -16 16z M1024 784v96q0 16 16 16h96q16 0 16 -16v-96q0 -16 -16 -16h-96q-16 0 -16 16zM1152 528v96q0 16 16 16h96q16 0 16 -16v-96q0 -16 -16 -16h-96q-16 0 -16 16zM1280 784v96q0 16 16 16h96q16 0 16 -16v-96q0 -16 -16 -16h-96q-16 0 -16 16zM1408 528v96q0 16 16 16h112v240 q0 16 16 16h96q16 0 16 -16v-352q0 -16 -16 -16h-224q-16 0 -16 16zM1536 272v96q0 16 16 16h96q16 0 16 -16v-96q0 -16 -16 -16h-96q-16 0 -16 16z" /> +<glyph unicode="&#xf11d;" horiz-adv-x="1792" d="M64 1280q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64zM320 320v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86 q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56zM448 426 q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599z" /> +<glyph unicode="&#xf11e;" horiz-adv-x="1792" d="M64 1280q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64zM320 320v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86 q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56zM448 426 q205 96 384 110v192q-181 -16 -384 -117v-185zM448 836q215 111 384 118v197q-172 -8 -384 -126v-189zM832 730h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15 t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2q-23 0 -49 -3v-222zM1280 828q148 -42 384 90v189q-169 -91 -306 -91q-45 0 -78 8v-196z" /> +<glyph unicode="&#xf120;" horiz-adv-x="1664" d="M13 160q0 13 10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23zM640 32v64q0 14 9 23t23 9h960q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-960 q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf121;" horiz-adv-x="1920" d="M45 576q0 13 10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23zM712 -52l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5 l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5zM1293 160q0 13 10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23z" /> +<glyph unicode="&#xf122;" horiz-adv-x="1792" d="M0 896q0 26 19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45l397 -397v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45zM384 896q0 26 19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221 q169 -173 169 -509q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45z" /> +<glyph unicode="&#xf123;" horiz-adv-x="1664" d="M2 900.5q9 27.5 54 34.5l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5z M832 310l59 -31l318 -168l-60 355l-12 66l49 47l257 250l-356 52l-66 10l-30 60l-159 322v-963z" /> +<glyph unicode="&#xf124;" horiz-adv-x="1408" d="M2 561q-5 22 4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5z" /> +<glyph unicode="&#xf125;" horiz-adv-x="1664" d="M0 928v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864 q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23zM512 301l595 595h-595v-595zM557 256h595v595z" /> +<glyph unicode="&#xf126;" horiz-adv-x="1024" d="M0 64q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136 q0 -52 -26 -96.5t-70 -69.5q-2 -287 -226 -414q-68 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136zM96 64q0 -40 28 -68t68 -28t68 28t28 68t-28 68t-68 28t-68 -28t-28 -68zM96 1216q0 -40 28 -68 t68 -28t68 28t28 68t-28 68t-68 28t-68 -28t-28 -68zM736 1088q0 -40 28 -68t68 -28t68 28t28 68t-28 68t-68 28t-68 -28t-28 -68z" /> +<glyph unicode="&#xf127;" horiz-adv-x="1664" d="M0 448q0 14 9 23t23 9h320q14 0 23 -9t9 -23t-9 -23t-23 -9h-320q-14 0 -23 9t-9 23zM16 1088q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56l-239 -18l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68 l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204zM128 32q0 13 9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-256 -256q-10 -9 -23 -9q-12 0 -23 9q-9 10 -9 23zM544 -96v320q0 14 9 23t23 9t23 -9t9 -23v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23zM633 364 l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56zM1056 1184v320q0 14 9 23t23 9t23 -9t9 -23v-320 q0 -14 -9 -23t-23 -9t-23 9t-9 23zM1216 1120q0 13 9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23zM1280 960q0 14 9 23t23 9h320q14 0 23 -9t9 -23t-9 -23t-23 -9h-320q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf128;" horiz-adv-x="1024" d="M96.5 986q-2.5 15 5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5t-10.5 37.5v45q0 83 65 156.5 t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25zM384 40v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28z" /> +<glyph unicode="&#xf129;" horiz-adv-x="640" d="M0 64v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45zM128 1152v192q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-192 q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf12a;" horiz-adv-x="640" d="M98 1344q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45zM128 64v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf12b;" d="M5 0v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258zM1013 713q0 64 26 117t65 86.5 t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5t-65.5 -51.5t-30.5 -63h232v80h126v-206h-514l-3 27q-4 28 -4 46z " /> +<glyph unicode="&#xf12c;" d="M5 0v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258zM1015 -183q0 64 26 117t65 86.5 t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73h232v80h126v-206h-514l-4 27q-3 45 -3 46z" /> +<glyph unicode="&#xf12d;" horiz-adv-x="1920" d="M1.5 146.5q5.5 37.5 30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5zM128 128h768l336 384h-768z" /> +<glyph unicode="&#xf12e;" horiz-adv-x="1664" d="M0 0v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5 q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124 q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89 q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1z" /> +<glyph unicode="&#xf130;" horiz-adv-x="1152" d="M0 704v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45 t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5zM256 704v512q0 132 94 226t226 94t226 -94t94 -226v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226z" /> +<glyph unicode="&#xf131;" horiz-adv-x="1408" d="M13 64q0 13 10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23t-10 -23l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -221 -147.5 -384.5 t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23zM128 704v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113l-101 -101 q-42 103 -42 214zM384 704v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" /> +<glyph unicode="&#xf132;" horiz-adv-x="1280" d="M0 576v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150t-33.5 170.5zM640 79 q119 63 213 137q235 184 235 360v640h-448v-1137z" /> +<glyph unicode="&#xf133;" horiz-adv-x="1664" d="M0 -128v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90zM128 -128h1408v1024h-1408v-1024z M384 1088q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288zM1152 1088q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288z" /> +<glyph unicode="&#xf134;" horiz-adv-x="1408" d="M3.5 940q-8.5 25 3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96 q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37 zM384 1344q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45z" /> +<glyph unicode="&#xf135;" horiz-adv-x="1664" d="M36 464l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85 q-3 -1 -9 -1q-14 0 -23 9l-64 64q-17 19 -5 39zM1248 1088q0 -40 28 -68t68 -28t68 28t28 68t-28 68t-68 28t-68 -28t-28 -68z" /> +<glyph unicode="&#xf136;" horiz-adv-x="1792" d="M0 0l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334z" /> +<glyph unicode="&#xf137;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM346 640q0 -26 19 -45l454 -454q19 -19 45 -19t45 19l102 102q19 19 19 45t-19 45l-307 307l307 307 q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45z" /> +<glyph unicode="&#xf138;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM506 288q0 -26 19 -45l102 -102q19 -19 45 -19t45 19l454 454q19 19 19 45t-19 45l-454 454 q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45z" /> +<glyph unicode="&#xf139;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM250 544q0 -26 19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19l102 102 q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45z" /> +<glyph unicode="&#xf13a;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM250 736q0 -26 19 -45l454 -454q19 -19 45 -19t45 19l454 454q19 19 19 45t-19 45l-102 102 q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45z" /> +<glyph unicode="&#xf13b;" horiz-adv-x="1408" d="M0 1408h1408l-128 -1438l-578 -162l-574 162zM262 1114l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674l16 175h-884z" /> +<glyph unicode="&#xf13c;" horiz-adv-x="1792" d="M12 75l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208l59 297h1505l-266 -1333l-804 -267z" /> +<glyph unicode="&#xf13d;" horiz-adv-x="1792" d="M0 0v352q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192 q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23v-352q0 -22 -20 -30q-8 -2 -12 -2q-13 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5 l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30zM832 1280q0 -26 19 -45t45 -19t45 19t19 45t-19 45t-45 19t-45 -19t-19 -45z" /> +<glyph unicode="&#xf13e;" horiz-adv-x="1152" d="M0 96v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181v-320h736q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28 t-28 68z" /> +<glyph unicode="&#xf140;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM128 640q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 t-51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5zM256 640q0 212 150 362t362 150t362 -150t150 -362t-150 -362t-362 -150t-362 150t-150 362zM384 640q0 -159 112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5t-112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5zM512 640q0 106 75 181t181 75t181 -75t75 -181t-75 -181t-181 -75t-181 75t-75 181z" /> +<glyph unicode="&#xf141;" horiz-adv-x="1408" d="M0 608v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68zM512 608v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68zM1024 608v192q0 40 28 68t68 28h192 q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68z" /> +<glyph unicode="&#xf142;" horiz-adv-x="384" d="M0 96v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68zM0 608v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68zM0 1120v192q0 40 28 68t68 28h192q40 0 68 -28 t28 -68v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68z" /> +<glyph unicode="&#xf143;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 256q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5z M256 575q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128q13 0 23 10t9 24q-13 232 -177 396t-396 177q-14 1 -24 -9t-10 -23v-128zM256 959q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128 q13 0 23 10q11 9 9 23q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128z" /> +<glyph unicode="&#xf144;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM512 320q0 -37 32 -56q16 -8 32 -8q17 0 32 9l544 320q32 18 32 55t-32 55l-544 320q-31 19 -64 1 q-32 -19 -32 -56v-640z" /> +<glyph unicode="&#xf145;" horiz-adv-x="1792" d="M54 448.5q0 53.5 37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136t-136 56t-136 -56l-125 126q-37 37 -37 90.5z M342 512q0 -26 19 -45l362 -362q18 -18 45 -18t45 18l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45zM452 512l572 572l316 -316l-572 -572z" /> +<glyph unicode="&#xf146;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 576q0 -26 19 -45t45 -19h896q26 0 45 19t19 45v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128 z" /> +<glyph unicode="&#xf147;" horiz-adv-x="1408" d="M0 288v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5zM128 288q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47 t-47 -113v-832zM256 672v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf148;" horiz-adv-x="1024" d="M3 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18z" /> +<glyph unicode="&#xf149;" horiz-adv-x="1024" d="M3 1261q9 19 29 19h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34z" /> +<glyph unicode="&#xf14a;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM218 640q0 -26 19 -45l358 -358q19 -19 45 -19t45 19l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19 t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45z" /> +<glyph unicode="&#xf14b;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 128h288l544 544l-288 288l-544 -544v-288zM352 320v56l52 52l152 -152l-52 -52h-56v96h-96zM494 494 q-14 13 3 30l291 291q17 17 30 3q14 -13 -3 -30l-291 -291q-17 -17 -30 -3zM864 1024l288 -288l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28z" /> +<glyph unicode="&#xf14c;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM282 320q0 -26 19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59 v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45z" /> +<glyph unicode="&#xf14d;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 448q0 -181 167 -404q10 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5t224 23.5v-160 q0 -42 40 -59q12 -5 24 -5q26 0 45 19l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5z" /> +<glyph unicode="&#xf14e;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73 t-198 -198t-73 -273zM512 241v542l512 256v-542zM640 448l256 128l-256 128v-256z" /> +<glyph unicode="&#xf150;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 160q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5v960q0 13 -9.5 22.5t-22.5 9.5h-960 q-13 0 -22.5 -9.5t-9.5 -22.5v-960zM391 861q17 35 57 35h640q40 0 57 -35q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66z" /> +<glyph unicode="&#xf151;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 160q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5v960q0 13 -9.5 22.5t-22.5 9.5h-960 q-13 0 -22.5 -9.5t-9.5 -22.5v-960zM391 419q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66q-17 -35 -57 -35h-640q-40 0 -57 35z" /> +<glyph unicode="&#xf152;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 160q0 -14 9 -23t23 -9h960q14 0 23 9t9 23v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960z M512 320v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52t-27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57z" /> +<glyph unicode="&#xf153;" horiz-adv-x="1024" d="M0 514v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5 t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5 l12 3l5 2q13 5 26 -2q12 -7 15 -21l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf154;" horiz-adv-x="1024" d="M0 32v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215 h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf155;" horiz-adv-x="1024" d="M52 171l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242 t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48 t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50t53 -63.5t31.5 -76.5t13 -94q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5 t-17.5 18q-17 21 -2 41z" /> +<glyph unicode="&#xf156;" horiz-adv-x="898" d="M0 605v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171 q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22z" /> +<glyph unicode="&#xf157;" horiz-adv-x="1027" d="M4 1360q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103 q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214z" /> +<glyph unicode="&#xf158;" horiz-adv-x="1280" d="M0 256v128q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315t-126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9 h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23zM487 747h320q106 0 171 62t65 162t-65 162t-171 62h-320v-448z" /> +<glyph unicode="&#xf159;" horiz-adv-x="1792" d="M0 672v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111 q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23z M373 896l32 -128h225l35 128h-292zM436 640l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5l81 299h-159zM822 768h139l-35 128h-70zM1118 896l34 -128h230l33 128h-297zM1187 640l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3l78 300h-162z" /> +<glyph unicode="&#xf15a;" horiz-adv-x="1280" d="M56 0l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89 t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200zM522 182q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30t24.5 40t9.5 51q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1 t-47.5 -1v-338zM522 674q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307z" /> +<glyph unicode="&#xf15b;" d="M0 -160v1600q0 40 28 68t68 28h800v-544q0 -40 28 -68t68 -28h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM1024 1024v472q22 -14 36 -28l408 -408q14 -14 28 -36h-472z" /> +<glyph unicode="&#xf15c;" d="M0 -160v1600q0 40 28 68t68 28h800v-544q0 -40 28 -68t68 -28h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM384 160q0 -14 9 -23t23 -9h704q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64zM384 416q0 -14 9 -23t23 -9h704 q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64zM384 672q0 -14 9 -23t23 -9h704q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64zM1024 1024v472q22 -14 36 -28l408 -408q14 -14 28 -36h-472z" /> +<glyph unicode="&#xf15d;" horiz-adv-x="1664" d="M34 108q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35zM899 768v106h70l230 662h162l230 -662h70v-106h-288v106h75l-47 144h-243l-47 -144h75v-106 h-287zM988 -166l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121v-233h-584v90zM1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18 t-7.5 -29z" /> +<glyph unicode="&#xf15e;" horiz-adv-x="1664" d="M34 108q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35zM899 -150h70l230 662h162l230 -662h70v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287 v106zM988 768v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248v119h121v-233h-584zM1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29 z" /> +<glyph unicode="&#xf160;" horiz-adv-x="1792" d="M34 108q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35zM896 -32q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9 t-9 23v192zM896 288v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23zM896 800v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23zM896 1312v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23 v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf161;" horiz-adv-x="1792" d="M34 108q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35zM896 -32q0 14 9 23t23 9h256q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9 t-9 23v192zM896 288v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23zM896 800v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23zM896 1312v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23 v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf162;" d="M34 108q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35zM946 261q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5q0 -62 -13 -121.5t-41 -114 t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5zM976 1351l192 185h123v-654h165v-114h-469v114h167v432q0 7 0.5 19t0.5 17 v16h-2l-7 -12q-8 -13 -26 -31l-62 -58zM1085 261q0 -57 36.5 -95t104.5 -38q50 0 85 27t35 68q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94z" /> +<glyph unicode="&#xf163;" d="M34 108q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35zM946 1285q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5q0 -62 -13 -121.5t-41 -114 t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5zM976 327l192 185h123v-654h165v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16 h-2l-7 -12q-8 -13 -26 -31l-62 -58zM1085 1285q0 -57 36.5 -95t104.5 -38q50 0 85 27t35 68q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94z" /> +<glyph unicode="&#xf164;" horiz-adv-x="1664" d="M0 64v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45zM128 192q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45zM480 64v641q0 25 18 43.5t43 20.5q24 2 76 59 t101 121q68 87 101 120q18 18 31 48t17.5 48.5t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135 q0 -86 -55 -149q15 -44 15 -76q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5z" /> +<glyph unicode="&#xf165;" horiz-adv-x="1664" d="M0 448q0 -26 19 -45t45 -19h288q26 0 45 19t19 45v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640zM128 960q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45zM480 447v641q0 26 19 44.5t45 19.5q35 1 158 44 q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76q55 -61 55 -149q-1 -78 -57.5 -135t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39 t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121t-76 59q-25 2 -43 20.5t-18 43.5z" /> +<glyph unicode="&#xf166;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM218 366q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73 q20 84 20 260q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5q-20 -87 -20 -260zM300 551v70h232v-70h-80v-423h-74v423h-78zM396 1313l24 -69t23 -69q35 -103 46 -158v-201h74v201l90 296h-75l-51 -195l-53 195 h-78zM542 205v290h66v-270q0 -24 1 -26q1 -15 15 -15q20 0 42 31v280h67v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 16 -6 54zM654 936q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87v130q0 58 -21 87q-29 38 -78 38q-51 0 -78 -38q-21 -29 -21 -87v-130zM721 923 v156q0 52 32 52t32 -52v-156q0 -51 -32 -51t-32 51zM790 128v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67zM857 200q16 -16 33 -16q29 0 29 49v157q0 50 -29 50q-17 0 -33 -16v-224zM907 893q0 -37 6 -55 q11 -27 43 -27q36 0 77 45v-40h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293zM1037 247v129q0 59 20 86q29 38 80 38t78 -38q21 -28 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68v-9q0 -29 -2 -43q-3 -22 -15 -40 q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86zM1103 355h66v34q0 51 -33 51t-33 -51v-34z" /> +<glyph unicode="&#xf167;" d="M27 260q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99q-26 112 -26 350zM138 509h105v-569h100v569h107v94h-312 v-94zM266 1536h106l71 -263l68 263h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187zM463 43q0 -49 8 -73q12 -37 58 -37q48 0 102 61v-54h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391zM614 1028v175q0 80 28 117q38 51 105 51 q69 0 106 -51q28 -37 28 -117v-175q0 -81 -28 -118q-37 -51 -106 -51q-67 0 -105 51q-28 38 -28 118zM704 1011q0 -70 43 -70t43 70v210q0 69 -43 69t-43 -69v-210zM798 -60h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89 v-663zM887 36v301q22 22 45 22q39 0 39 -67v-211q0 -67 -39 -67q-23 0 -45 22zM955 971v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75zM1130 100q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54 q2 9 2 58v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51q-28 -37 -28 -116v-173zM1219 245v46q0 68 45 68t45 -68v-46h-90z" /> +<glyph unicode="&#xf168;" horiz-adv-x="1408" d="M5 384q-10 17 0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45l164 -286q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17zM536 539q18 32 531 942q25 45 64 45h241q22 0 31 -15q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37 q-10 -15 -32 -15h-239q-42 0 -66 45z" /> +<glyph unicode="&#xf169;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM227 396q8 -13 24 -13h185q31 0 50 36l199 352q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29 l125 -216v-1l-196 -346q-9 -14 0 -28zM638 516q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1l409 723q8 16 0 28q-7 12 -24 12h-187q-30 0 -49 -35z" /> +<glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M0 640q0 96 1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150t-1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58 t-69.5 123q-14 65 -21.5 147.5t-8.5 136.5t-1 150zM640 320q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54t-30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640z" /> +<glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M64 558l338 271l494 -305l-342 -285zM64 1099l490 319l342 -285l-494 -304zM407 166v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284l147 96v-108l-490 -293v-1l-1 1l-1 -1v1zM896 524l494 305l338 -271l-489 -319zM896 1133l343 285l489 -319l-338 -270z" /> +<glyph unicode="&#xf16c;" horiz-adv-x="1408" d="M0 -255v736h121v-618h928v618h120v-701l-1 -35v-1h-1132l-35 1h-1zM221 -17v151l707 1v-151zM227 243l14 150l704 -65l-13 -150zM270 563l39 146l683 -183l-39 -146zM395 928l77 130l609 -360l-77 -130zM707 1303l125 86l398 -585l-124 -85zM1136 1510l149 26l121 -697 l-149 -26z" /> +<glyph unicode="&#xf16d;" d="M0 69v1142q0 81 58 139t139 58h1142q81 0 139 -58t58 -139v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139zM171 110q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62 q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648zM461 643q0 -124 90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5t-90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5zM1050 1003q0 -29 20 -49t49 -20h174q29 0 49 20t20 49v165q0 28 -20 48.5 t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165z" /> +<glyph unicode="&#xf16e;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM274 640q0 -88 62 -150t150 -62t150 62t62 150t-62 150t-150 62t-150 -62t-62 -150zM838 640q0 -88 62 -150 t150 -62t150 62t62 150t-62 150t-150 62t-150 -62t-62 -150z" /> +<glyph unicode="&#xf170;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM309 384h94l104 160h522l104 -160h94l-459 691zM567 608l201 306l201 -306h-402z" /> +<glyph unicode="&#xf171;" horiz-adv-x="1408" d="M0 1222q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34 t-6 39.5t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158zM173 285l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18t-76.5 27 t-73 43.5t-52 61.5q-25 96 -57 292zM243 1240q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5q-20 27 -56 44.5t-58 22t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43zM481 657q4 -91 77.5 -155t165.5 -56q91 8 152 84 t50 168q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5zM599 710q14 41 52 58q36 18 72.5 12t64 -35.5t27.5 -67.5q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82z" /> +<glyph unicode="&#xf172;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM260 1060q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63 q24 13 39.5 23t31 29t19.5 40q48 267 80 473q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54zM385 384q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71q0 7 5.5 26.5t3 32 t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6zM436 1073q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5t-52.5 16t-54.5 32.5zM607 653q-2 49 25.5 93t72.5 64 q70 31 141.5 -10t81.5 -118q8 -66 -36 -121t-110 -61t-119 40t-56 113zM687.5 660.5q0.5 -52.5 43.5 -70.5q39 -23 81 4t36 72q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5z" /> +<glyph unicode="&#xf173;" horiz-adv-x="1024" d="M78 779v217q91 30 155 84q64 55 103 132q39 78 54 196h219v-388h364v-241h-364v-394q0 -136 14 -172q13 -37 52 -60q50 -31 117 -31q117 0 232 76v-242q-102 -48 -178 -65q-77 -19 -173 -19q-105 0 -186 27q-78 25 -138 75q-58 51 -79 105q-22 54 -22 161v539h-170z" /> +<glyph unicode="&#xf174;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM413 744h127v-404q0 -78 17 -121q17 -42 59 -78q43 -37 104 -57q62 -20 140 -20q67 0 129 14q57 13 134 49v181 q-88 -56 -174 -56q-51 0 -88 23q-29 17 -39 45q-11 30 -11 129v295h274v181h-274v291h-164q-11 -90 -40 -147t-78 -99q-48 -40 -116 -63v-163z" /> +<glyph unicode="&#xf175;" horiz-adv-x="768" d="M3 237q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19t-5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35z" /> +<glyph unicode="&#xf176;" horiz-adv-x="768" d="M3 1043q-8 19 5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19z" /> +<glyph unicode="&#xf177;" horiz-adv-x="1792" d="M64 637q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23z" /> +<glyph unicode="&#xf178;" horiz-adv-x="1792" d="M0 544v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf179;" horiz-adv-x="1408" d="M0 634q0 228 113 374q112 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32 q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503zM683 1131q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17z" /> +<glyph unicode="&#xf17a;" horiz-adv-x="1664" d="M0 -27v557h682v-651zM0 614v565l682 94v-659h-682zM757 -131v661h907v-786zM757 614v669l907 125v-794h-907z" /> +<glyph unicode="&#xf17b;" horiz-adv-x="1408" d="M0 337v430q0 42 30 72t73 30q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30t-73 30t-30 73zM241 886q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20l-71 -131q107 -55 171 -153.5t64 -215.5 h-925zM245 184v666h918v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78zM455 1092q0 -16 11 -27.5t27 -11.5t27.5 11.5t11.5 27.5t-11.5 27.5 t-27.5 11.5t-27 -11.5t-11 -27.5zM876 1092q0 -16 11.5 -27.5t27.5 -11.5t27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5zM1203 337v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73z" /> +<glyph unicode="&#xf17c;" d="M11 -115q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49t-14 -48q3 -17 37 -26q20 -6 84.5 -18.5 t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54q110 143 124 195q-12 112 -16 310q-2 90 24 151.5 t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5t-40.5 -33.5t-61 -14q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5 t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5t15.5 47.5q1 -31 8 -56.5t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13 t16.5 -9.5q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5t-30 -18.5t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5 q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43q-19 4 -51 9.5t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5zM321 495q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54 t7 -70.5q46 24 7 92q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5 t60 -22.5q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7 q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15 q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5 t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19 q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63 q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18zM372 630q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-7 -10 -1 -12zM603 1190q2 -5 5 -6 q10 0 7 -15q-3 -20 8 -20q3 0 3 3q3 17 -2.5 30t-11.5 15q-9 2 -9 -7zM634 1110q0 12 19 15h10q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5zM721 1122q24 11 32 -2q3 -6 -3 -9q-4 -1 -11.5 6.5t-17.5 4.5zM835 1196l4 -2q14 -4 18 -31q0 -3 8 2l2 3q0 11 -5 19.5t-11 12.5 t-9 3q-14 -1 -7 -7zM851 1381.5q-1 -2.5 3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9zM981 1002q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20q-2 8 -6.5 11.5t-13 5 t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5z" /> +<glyph unicode="&#xf17d;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM112 640q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81t99.5 48l37 13 q4 1 13 3.5t13 4.5q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21zM126 775q302 0 606 80q-120 213 -244 378q-138 -65 -234 -186t-128 -272zM350 134q184 -150 418 -150q132 0 256 52q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5 t-103 -148zM609 1276q1 1 2 1q-1 0 -2 -1zM613 1277q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5l12.5 17.5q-185 164 -433 164q-76 0 -155 -19zM909 797q25 -53 44 -95q2 -6 6.5 -17.5t7.5 -16.5q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5 t36.5 -6t25 -4.5l10 -2q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5zM1007 565q87 -239 128 -469q111 75 185 189.5t96 250.5q-210 60 -409 29z" /> +<glyph unicode="&#xf17e;" d="M0 1024q0 159 112.5 271.5t271.5 112.5q130 0 234 -80q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225 t-55.5 273.5q0 73 16 150q-80 104 -80 234zM376 399q0 -92 122 -157.5t291 -65.5q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12 t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5 q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75z" /> +<glyph unicode="&#xf180;" horiz-adv-x="1664" d="M0 640q0 75 53 128l587 587q53 53 128 53t128 -53l265 -265l-398 -399l-188 188q-42 42 -99 42q-59 0 -100 -41l-120 -121q-42 -40 -42 -99q0 -58 42 -100l406 -408q30 -28 67 -37l6 -4h28q60 0 99 41l619 619l2 -3q53 -53 53 -128t-53 -128l-587 -587 q-52 -53 -127.5 -53t-128.5 53l-587 587q-53 53 -53 128zM302 660q0 21 14 35l121 120q13 15 35 15t36 -15l252 -252l574 575q15 15 36 15t36 -15l120 -120q14 -15 14 -36t-14 -36l-730 -730q-17 -15 -37 -15q-4 0 -6 1q-18 2 -30 14l-407 408q-14 15 -14 36z" /> +<glyph unicode="&#xf181;" d="M0 -64v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45zM160 192q0 -14 9 -23t23 -9h480q14 0 23 9t9 23v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024zM832 576q0 -14 9 -23t23 -9h480q14 0 23 9t9 23 v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640z" /> +<glyph unicode="&#xf182;" horiz-adv-x="1280" d="M0 480q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192 q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43q-40 0 -68 28t-28 68zM416 1280q0 93 65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5t-65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5z" /> +<glyph unicode="&#xf183;" horiz-adv-x="1024" d="M0 416v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68z M288 1280q0 93 65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5t-65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5z" /> +<glyph unicode="&#xf184;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM399.5 766q8.5 -37 24.5 -59l349 -473l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5 t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85z" /> +<glyph unicode="&#xf185;" horiz-adv-x="1792" d="M44 363q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29q-4 -15 -20 -20 l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20zM320 640q0 -117 45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5 t-45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5z" /> +<glyph unicode="&#xf186;" d="M0 640q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61 t-245 164t-164 245t-61 298zM128 640q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384z" /> +<glyph unicode="&#xf187;" horiz-adv-x="1792" d="M64 1088v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1536q-26 0 -45 19t-19 45zM128 -64v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45zM704 704q0 -26 19 -45t45 -19h256 q26 0 45 19t19 45t-19 45t-45 19h-256q-26 0 -45 -19t-19 -45z" /> +<glyph unicode="&#xf188;" horiz-adv-x="1664" d="M32 576q0 26 19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19t19 -45t-19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19 t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45z M512 1152q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5h-640z" /> +<glyph unicode="&#xf189;" horiz-adv-x="1920" d="M-1 1004q0 11 3 16l4 6q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24 q17 19 38 30q53 26 239 24q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5 t13 3t20 0.5l288 2q39 5 64 -2.5t31 -16.5l6 -10q23 -64 -150 -294q-24 -32 -65 -85q-78 -100 -90 -131q-17 -41 14 -81q17 -21 81 -82h1l1 -1l1 -1l2 -2q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12 q-30 21 -70 64t-68.5 77.5t-61 58t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211 t-130.5 272q-6 16 -6 27z" /> +<glyph unicode="&#xf18a;" horiz-adv-x="1792" d="M0 391q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5q0 -68 -37 -139.5 t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5zM181 320q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5zM413.5 230.5 q-40.5 92.5 6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5q-45 -102 -158 -150t-224 -12q-107 34 -147.5 126.5zM495 257.5q9 -34.5 43 -50.5t74.5 -2.5t62.5 47.5q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5zM705 399 q-17 -31 13 -45q14 -5 29 0.5t22 18.5q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5zM1165 1274q-6 28 9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158 q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5zM1224 1047q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5t54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37z" /> +<glyph unicode="&#xf18b;" d="M0 638q0 187 83.5 349.5t229.5 269.5t325 137v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495zM398 -34q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211q-171 -94 -368 -94q-196 0 -367 94zM898 909v485q179 -30 325 -137t229.5 -269.5 t83.5 -349.5q0 -280 -181 -495q-204 99 -330.5 306.5t-126.5 459.5z" /> +<glyph unicode="&#xf18c;" horiz-adv-x="1408" d="M0 -211q0 19 13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23 t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89 t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -5 1 -50.5t-1 -71.5q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283 q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32z" /> +<glyph unicode="&#xf18d;" horiz-adv-x="1280" d="M21 217v66h1238v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5zM21 354v255h1238v-255h-1238zM21 682v255h1238v-255h-1238zM21 1010v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5v-67h-1238z" /> +<glyph unicode="&#xf18e;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73 t-198 -198t-73 -273zM384 544v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23t-9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5z" /> +<glyph unicode="&#xf190;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73 t-198 -198t-73 -273zM384 640q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23z" /> +<glyph unicode="&#xf191;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 160q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5v960q0 13 -9.5 22.5t-22.5 9.5h-960 q-13 0 -22.5 -9.5t-9.5 -22.5v-960zM448 640q0 33 27 52l448 320q17 12 37 12q26 0 45 -19t19 -45v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52z" /> +<glyph unicode="&#xf192;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM224 640q0 -148 73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73 t-198 -198t-73 -273zM512 640q0 106 75 181t181 75t181 -75t75 -181t-75 -181t-181 -75t-181 75t-75 181z" /> +<glyph unicode="&#xf193;" horiz-adv-x="1664" d="M0 320q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5zM416 1348q-2 16 6 42 q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455l198 99l58 -114l-256 -128q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5z" /> +<glyph unicode="&#xf194;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM128 806q16 -8 25.5 -26t21.5 -20q21 -3 54.5 8.5t58 10.5t41.5 -30q11 -18 18.5 -38.5t15 -48t12.5 -40.5 q17 -46 53 -187q36 -146 57 -197q42 -99 103 -125q43 -12 85 -1.5t76 31.5q131 77 250 237q104 139 172.5 292.5t82.5 226.5q16 85 -21 132q-52 65 -187 45q-17 -3 -41 -12.5t-57.5 -30.5t-64.5 -48.5t-59.5 -70t-44.5 -91.5q80 7 113.5 -16t26.5 -99q-5 -52 -52 -143 q-43 -78 -71 -99q-44 -32 -87 14q-23 24 -37.5 64.5t-19 73t-10 84t-8.5 71.5q-23 129 -34 164q-12 37 -35.5 69t-50.5 40q-57 16 -127 -25q-54 -32 -136.5 -106t-122.5 -102v-7z" /> +<glyph unicode="&#xf195;" horiz-adv-x="1152" d="M0 608v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31 l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26z" /> +<glyph unicode="&#xf196;" horiz-adv-x="1408" d="M0 288v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5zM128 288q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47 t-47 -113v-832zM256 672v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf197;" horiz-adv-x="2176" d="M0 576q0 12 38.5 20.5t96.5 10.5q-7 25 -7 49q0 33 9.5 56.5t22.5 23.5h64v64h128q158 0 268 -64h1113q42 -7 106.5 -18t80.5 -14q89 -15 150 -40.5t83.5 -47.5t22.5 -40t-22.5 -40t-83.5 -47.5t-150 -40.5q-16 -3 -80.5 -14t-106.5 -18h-1113q-110 -64 -268 -64h-128v64 h-64q-13 0 -22.5 23.5t-9.5 56.5q0 24 7 49q-58 2 -96.5 10.5t-38.5 20.5zM323 336h29q157 0 273 64h1015q-217 -38 -456 -80q-57 0 -113 -24t-83 -48l-28 -24l-288 -288q-26 -26 -70.5 -45t-89.5 -19h-96zM323 816l93 464h96q46 0 90 -19t70 -45l288 -288q4 -4 11 -10.5 t30.5 -23t48.5 -29t61.5 -23t72.5 -10.5l456 -80h-1015q-116 64 -273 64h-29zM1739 484l81 -30q68 48 68 122t-68 122l-81 -30q53 -36 53 -92t-53 -92z" /> +<glyph unicode="&#xf198;" horiz-adv-x="1664" d="M0 796q0 47 27.5 85t71.5 53l157 53l-53 159q-8 24 -8 47q0 60 42 102.5t102 42.5q47 0 85 -27t53 -72l54 -160l310 105l-54 160q-8 24 -8 47q0 59 42.5 102t101.5 43q47 0 85.5 -27.5t53.5 -71.5l53 -161l162 55q21 6 43 6q60 0 102.5 -39.5t42.5 -98.5q0 -45 -30 -81.5 t-74 -51.5l-157 -54l105 -316l164 56q24 8 46 8q62 0 103.5 -40.5t41.5 -101.5q0 -97 -93 -130l-172 -59l56 -167q7 -21 7 -47q0 -59 -42 -102t-101 -43q-47 0 -85.5 27t-53.5 72l-55 165l-310 -106l55 -164q8 -24 8 -47q0 -59 -42 -102t-102 -43q-47 0 -85 27t-53 72 l-55 163l-153 -53q-29 -9 -50 -9q-61 0 -101.5 40t-40.5 101q0 47 27.5 85t71.5 53l156 53l-105 313l-156 -54q-26 -8 -48 -8q-60 0 -101 40.5t-41 100.5zM620 811l105 -313l310 105l-105 315z" /> +<glyph unicode="&#xf199;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 352q0 -40 28 -68t68 -28h832q40 0 68 28t28 68v436q-31 -35 -64 -55q-34 -22 -132.5 -85t-151.5 -99 q-98 -69 -164 -69t-164 69q-46 32 -141.5 92.5t-142.5 92.5q-12 8 -33 27t-31 27v-436zM256 928q0 -37 30.5 -76.5t67.5 -64.5q47 -32 137.5 -89t129.5 -83q3 -2 17 -11.5t21 -14t21 -13t23.5 -13t21.5 -9.5t22.5 -7.5t20.5 -2.5t20.5 2.5t22.5 7.5t21.5 9.5t23.5 13t21 13 t21 14t17 11.5l267 174q35 23 66.5 62.5t31.5 73.5q0 41 -27.5 70t-68.5 29h-832q-40 0 -68 -28t-28 -68z" /> +<glyph unicode="&#xf19a;" horiz-adv-x="1792" d="M0 640q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348zM41 640q0 -173 68 -331.5t182.5 -273t273 -182.5t331.5 -68t331.5 68t273 182.5t182.5 273t68 331.5 t-68 331.5t-182.5 273t-273 182.5t-331.5 68t-331.5 -68t-273 -182.5t-182.5 -273t-68 -331.5zM127 640q0 163 67 313l367 -1005q-196 95 -315 281t-119 411zM254 1062q105 160 274.5 253.5t367.5 93.5q147 0 280.5 -53t238.5 -149h-10q-55 0 -92 -40.5t-37 -95.5 q0 -12 2 -24t4 -21.5t8 -23t9 -21t12 -22.5t12.5 -21t14.5 -24t14 -23q63 -107 63 -212q0 -19 -2.5 -38.5t-10 -49.5t-11.5 -44t-17.5 -59t-17.5 -58l-76 -256l-278 826q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-75 1 -202 10q-12 1 -20.5 -5t-11.5 -15 t-1.5 -18.5t9 -16.5t19.5 -8l80 -8l120 -328l-168 -504l-280 832q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-7 0 -23 0.5t-26 0.5zM679 -97l230 670l237 -647q1 -6 5 -11q-126 -44 -255 -44q-112 0 -217 32zM1282 -24l235 678q59 169 59 276q0 42 -6 79 q95 -174 95 -369q0 -209 -104 -385.5t-279 -278.5z" /> +<glyph unicode="&#xf19b;" horiz-adv-x="1792" d="M0 455q0 140 100.5 263.5t275 205.5t391.5 108v-172q-217 -38 -356.5 -150t-139.5 -255q0 -152 154.5 -267t388.5 -145v1360l272 133v-1536l-272 -128q-228 20 -414 102t-293 208.5t-107 272.5zM1134 860v172q277 -33 481 -157l140 79l37 -390l-525 114l147 83 q-119 70 -280 99z" /> +<glyph unicode="&#xf19c;" horiz-adv-x="2048" d="M0 -128q0 26 20.5 45t48.5 19h1782q28 0 48.5 -19t20.5 -45v-128h-1920v128zM0 1024v128l960 384l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128zM128 0v64q0 26 20.5 45t48.5 19h59v768h256v-768h128v768h256v-768h128v768h256 v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664z" /> +<glyph unicode="&#xf19d;" horiz-adv-x="2304" d="M0 1024q0 23 22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31t-22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433 q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31zM512 384l18 316l574 -181q22 -7 48 -7t48 7l574 181l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128z" /> +<glyph unicode="&#xf19e;" d="M109 1536q58 -15 108 -15q43 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610l13 -707q-62 11 -105 11 q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287z" /> +<glyph unicode="&#xf1a0;" horiz-adv-x="1280" d="M111 182q0 81 44.5 150t118.5 115q131 82 404 100q-32 41 -47.5 73.5t-15.5 73.5q0 40 21 85q-46 -4 -68 -4q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q76 66 182 98t218 32h417l-137 -88h-132q75 -63 113 -133t38 -160q0 -72 -24.5 -129.5t-59.5 -93 t-69.5 -65t-59 -61.5t-24.5 -66q0 -36 32 -70.5t77 -68t90.5 -73.5t77.5 -104t32 -142q0 -91 -49 -173q-71 -122 -209.5 -179.5t-298.5 -57.5q-132 0 -246.5 41.5t-172.5 137.5q-36 59 -36 131zM297 228q0 -56 23.5 -102t61 -75.5t87 -50t100 -29t101.5 -8.5q58 0 111.5 13 t99 39t73 73t27.5 109q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -49 2q-53 0 -104.5 -7t-107 -25t-97 -46t-68.5 -74.5t-27 -105.5zM403 1222q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26q37 0 77.5 16.5t65.5 43.5 q53 56 53 159q0 59 -17 125.5t-48 129t-84 103.5t-117 41q-42 0 -82.5 -19.5t-66.5 -52.5q-46 -59 -46 -160z" /> +<glyph unicode="&#xf1a1;" horiz-adv-x="1984" d="M0 722q0 94 66 160t160 66q83 0 148 -55q248 158 592 164l134 423q4 14 17.5 21.5t28.5 4.5l347 -82q22 50 68.5 81t102.5 31q77 0 131.5 -54.5t54.5 -131.5t-54.5 -132t-131.5 -55q-76 0 -130.5 54t-55.5 131l-315 74l-116 -366q327 -14 560 -166q64 58 151 58 q94 0 160 -66t66 -160q0 -62 -31 -114t-83 -82q5 -33 5 -61q0 -121 -68.5 -230.5t-197.5 -193.5q-125 -82 -285.5 -125.5t-335.5 -43.5q-176 0 -336.5 43.5t-284.5 125.5q-129 84 -197.5 193t-68.5 231q0 29 5 66q-48 31 -77 81.5t-29 109.5zM77 722q0 -67 51 -111 q49 131 180 235q-36 25 -82 25q-62 0 -105.5 -43.5t-43.5 -105.5zM178 465q0 -101 59.5 -194t171.5 -166q116 -75 265.5 -115.5t313.5 -40.5t313.5 40.5t265.5 115.5q112 73 171.5 166t59.5 194t-59.5 193.5t-171.5 165.5q-116 75 -265.5 115.5t-313.5 40.5t-313.5 -40.5 t-265.5 -115.5q-112 -73 -171.5 -165.5t-59.5 -193.5zM555 572q0 57 41.5 98t97.5 41t96.5 -41t40.5 -98q0 -56 -40.5 -96t-96.5 -40q-57 0 -98 40t-41 96zM661 209.5q0 16.5 11 27.5t27 11t27 -11q77 -77 265 -77h2q188 0 265 77q11 11 27 11t27 -11t11 -27.5t-11 -27.5 q-99 -99 -319 -99h-2q-220 0 -319 99q-11 11 -11 27.5zM1153 572q0 57 41.5 98t97.5 41t96.5 -41t40.5 -98q0 -56 -40.5 -96t-96.5 -40q-57 0 -98 40t-41 96zM1555 1350q0 -45 32 -77t77 -32t77 32t32 77t-32 77t-77 32t-77 -32t-32 -77zM1672 843q131 -105 178 -238 q57 46 57 117q0 62 -43.5 105.5t-105.5 43.5q-49 0 -86 -28z" /> +<glyph unicode="&#xf1a2;" d="M0 193v894q0 133 94 227t226 94h896q132 0 226 -94t94 -227v-894q0 -133 -94 -227t-226 -94h-896q-132 0 -226 94t-94 227zM155 709q0 -37 19.5 -67.5t52.5 -45.5q-7 -25 -7 -54q0 -98 74 -181.5t201.5 -132t278.5 -48.5q150 0 277.5 48.5t201.5 132t74 181.5q0 27 -6 54 q35 14 57 45.5t22 70.5q0 51 -36 87.5t-87 36.5q-60 0 -98 -48q-151 107 -375 115l83 265l206 -49q1 -50 36.5 -85t84.5 -35q50 0 86 35.5t36 85.5t-36 86t-86 36q-36 0 -66 -20.5t-45 -53.5l-227 54q-9 2 -17.5 -2.5t-11.5 -14.5l-95 -302q-224 -4 -381 -113q-36 43 -93 43 q-51 0 -87 -36.5t-36 -87.5zM493 613q0 37 26 63t63 26t63 -26t26 -63t-26 -64t-63 -27t-63 27t-26 64zM560 375q0 11 8 18q7 7 17.5 7t17.5 -7q49 -51 172 -51h1h1q122 0 173 51q7 7 17.5 7t17.5 -7t7 -18t-7 -18q-65 -64 -208 -64h-1h-1q-143 0 -207 64q-8 7 -8 18z M882 613q0 37 26 63t63 26t63 -26t26 -63t-26 -64t-63 -27t-63 27t-26 64zM1143 1120q0 30 21 51t50 21q30 0 51 -21t21 -51q0 -29 -21 -50t-51 -21q-29 0 -50 21t-21 50z" /> +<glyph unicode="&#xf1a3;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM320 502q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14 q19 0 32.5 -14t13.5 -33v-54l60 -28l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122zM806 500q0 -80 58 -137t139 -57t138.5 57t57.5 139v122h-150v-126q0 -20 -13.5 -33.5t-33.5 -13.5 q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123z" /> +<glyph unicode="&#xf1a4;" horiz-adv-x="1920" d="M0 336v266h328v-262q0 -43 30 -72.5t72 -29.5t72 29.5t30 72.5v620q0 171 126.5 292t301.5 121q176 0 302 -122t126 -294v-136l-195 -58l-131 61v118q0 42 -30 72t-72 30t-72 -30t-30 -72v-612q0 -175 -126 -299t-303 -124q-178 0 -303.5 125.5t-125.5 303.5zM1062 332 v268l131 -61l195 58v-270q0 -42 30 -71.5t72 -29.5t72 29.5t30 71.5v275h328v-266q0 -178 -125.5 -303.5t-303.5 -125.5q-177 0 -303 124.5t-126 300.5z" /> +<glyph unicode="&#xf1a5;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM64 640h704v-704h480q93 0 158.5 65.5t65.5 158.5v480h-704v704h-480q-93 0 -158.5 -65.5t-65.5 -158.5v-480z " /> +<glyph unicode="&#xf1a6;" horiz-adv-x="2048" d="M0 271v697h328v286h204v-983h-532zM205 435h123v369h-123v-369zM614 271h205v697h-205v-697zM614 1050h205v204h-205v-204zM901 26v163h328v82h-328v697h533v-942h-533zM1106 435h123v369h-123v-369zM1516 26v163h327v82h-327v697h532v-942h-532zM1720 435h123v369h-123 v-369z" /> +<glyph unicode="&#xf1a7;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM293 388l211 41v206q55 -19 116 -19q125 0 213.5 95t88.5 229t-88.5 229t-213.5 95q-74 0 -141 -36h-186v-840z M504 804v277q28 17 70 17q53 0 91 -45t38 -109t-38 -109.5t-91 -45.5q-43 0 -70 15zM636 -39l211 41v206q51 -19 117 -19q125 0 213 95t88 229t-88 229t-213 95q-20 0 -39 -3q-23 -78 -78 -136q-87 -95 -211 -101v-636zM847 377v277q28 17 70 17q53 0 91 -45.5t38 -109.5 t-38 -109t-91 -45q-43 0 -70 15z" /> +<glyph unicode="&#xf1a8;" horiz-adv-x="2038" d="M41 455q0 15 8.5 26.5t22.5 14.5l486 106q-8 14 -8 25t5.5 17.5t16 11.5t20 7t23 4.5t18.5 4.5q4 1 15.5 7.5t17.5 6.5q15 0 28 -16t20 -33q163 37 172 37q17 0 29.5 -11t12.5 -28q0 -15 -8.5 -26t-23.5 -14l-182 -40l-1 -16q-1 -26 81.5 -117.5t104.5 -91.5q47 0 119 80 t72 129q0 36 -23.5 53t-51 18.5t-51 11.5t-23.5 34q0 16 10 34l-68 19q43 44 43 117q0 26 -5 58q82 16 144 16q44 0 71.5 -1.5t48.5 -8.5t31 -13.5t20.5 -24.5t15.5 -33.5t17 -47.5t24 -60l50 25q-3 -40 -23 -60t-42.5 -21t-40 -6.5t-16.5 -20.5l1 -21q75 3 143.5 -20.5 t118 -58.5t101 -94.5t84 -108t75.5 -120.5q33 -56 78.5 -109t75.5 -80.5t99 -88.5q-48 -30 -108.5 -57.5t-138.5 -59t-114 -47.5q-44 37 -74 115t-43.5 164.5t-33 180.5t-42.5 168.5t-72.5 123t-122.5 48.5l-10 -2l-6 -4q4 -5 13 -14q6 -5 28 -23.5t25.5 -22t19 -18 t18 -20.5t11.5 -21t10.5 -27.5t4.5 -31t4 -40.5l1 -33q1 -26 -2.5 -57.5t-7.5 -52t-12.5 -58.5t-11.5 -53q-35 1 -101 -9.5t-98 -10.5q-39 0 -72 10q-2 16 -2 47q0 74 3 96q2 13 31.5 41.5t57 59t26.5 51.5q-24 2 -43 -24q-36 -53 -111.5 -99.5t-136.5 -46.5q-25 0 -75.5 63 t-106.5 139.5t-84 96.5q-6 4 -27 30q-482 -112 -513 -112q-16 0 -28 11t-12 27zM764 676q10 1 32.5 7t34.5 6q19 0 35 -10l-96 -20zM822 568l48 12l109 -177l-73 -48zM859 884q16 30 36 46.5t54 29.5t65.5 36t46 36.5t50 55t43.5 50.5q12 -9 28 -31.5t32 -36.5t38 -13l12 1 v-76l22 -1q247 95 371 190q28 21 50 39t42.5 37.5t33 31t29.5 34t24 31t24.5 37t23 38t27 47.5t29.5 53l7 9q-2 -53 -43 -139q-79 -165 -205 -264t-306 -142q-14 -3 -42 -7.5t-50 -9.5t-39 -14q3 -19 24.5 -46t21.5 -34q0 -11 -26 -30q-5 5 -13.5 15.5t-12 14.5t-10.5 11.5 t-10 10.5l-8 8t-8.5 7.5t-8 5t-8.5 4.5q-7 3 -14.5 5t-20.5 2.5t-22 0.5h-32.5h-37.5q-126 0 -217 -43zM1061 45h31l10 -83l-41 -12v95zM1061 -79q39 26 131.5 47.5t146.5 21.5q9 0 22.5 -15.5t28 -42.5t26 -50t24 -51t14.5 -33q-121 -45 -244 -45q-61 0 -125 11zM1116 29 q21 2 60.5 8.5t72 10t60.5 3.5h14q3 -15 3 -16q0 -7 -17.5 -14.5t-46 -13t-54 -9.5t-53.5 -7.5t-32 -4.5zM1947 1528l1 3l2 4l-1 -5zM1950 1535v1v-1zM1950 1535l1 1z" /> +<glyph unicode="&#xf1a9;" d="M0 520q0 89 19.5 172.5t49 145.5t70.5 118.5t78.5 94t78.5 69.5t64.5 46.5t42.5 24.5q14 8 51 26.5t54.5 28.5t48 30t60.5 44q36 28 58 72.5t30 125.5q129 -155 186 -193q44 -29 130 -68t129 -66q21 -13 39 -25t60.5 -46.5t76 -70.5t75 -95t69 -122t47 -148.5 t19.5 -177.5q0 -164 -62 -304.5t-166 -236t-242.5 -149.5t-290.5 -54t-293 57.5t-247.5 157t-170.5 241.5t-64 302zM333 256q-2 -112 74 -164q29 -20 62.5 -28.5t103.5 -8.5q57 0 132 32.5t134 71t120 70.5t93 31q26 -1 65 -31.5t71.5 -67t68 -67.5t55.5 -32q35 -3 58.5 14 t55.5 63q28 41 42.5 101t14.5 106q0 22 -5 44.5t-16.5 45t-34 36.5t-52.5 14q-33 0 -97 -41.5t-129 -83.5t-101 -42q-27 -1 -63.5 19t-76 49t-83.5 58t-100 49t-111 19q-115 -1 -197 -78.5t-84 -178.5zM685.5 -76q-0.5 -10 7.5 -20q34 -32 87.5 -46t102.5 -12.5t99 4.5 q41 4 84.5 20.5t65 30t28.5 20.5q12 12 7 29q-5 19 -24 5q-30 -22 -87 -39t-131 -17q-129 0 -193 49q-5 4 -13 4q-11 0 -26 -12q-7 -6 -7.5 -16zM852 31q9 -8 17.5 -4.5t31.5 23.5q3 2 10.5 8.5t10.5 8.5t10 7t11.5 7t12.5 5t15 4.5t16.5 2.5t20.5 1q27 0 44.5 -7.5 t23 -14.5t13.5 -22q10 -17 12.5 -20t12.5 1q23 12 14 34q-19 47 -39 61q-23 15 -76 15q-47 0 -71 -10q-29 -12 -78 -56q-26 -24 -12 -44z" /> +<glyph unicode="&#xf1aa;" d="M0 78q0 72 44.5 128t113.5 72q-22 86 1 173t88 152l12 12l151 -152l-11 -11q-37 -37 -37 -89t37 -90q37 -37 89 -37t89 37l30 30l151 152l161 160l151 -152l-160 -160l-151 -152l-30 -30q-65 -64 -151.5 -87t-171.5 -2q-16 -70 -72 -115t-129 -45q-85 0 -145 60.5 t-60 145.5zM2 1202q0 85 60 145.5t145 60.5q76 0 133.5 -49t69.5 -123q84 20 169.5 -3.5t149.5 -87.5l12 -12l-152 -152l-12 12q-37 37 -89 37t-89 -37t-37 -89.5t37 -89.5l29 -29l152 -152l160 -160l-151 -152l-161 160l-151 152l-30 30q-68 67 -90 159.5t5 179.5 q-70 15 -115 71t-45 129zM446 803l161 160l152 152l29 30q67 67 159 89.5t178 -3.5q11 75 68.5 126t135.5 51q85 0 145 -60.5t60 -145.5q0 -77 -51 -135t-127 -69q26 -85 3 -176.5t-90 -158.5l-12 -12l-151 152l12 12q37 37 37 89t-37 89t-89 37t-89 -37l-30 -30l-152 -152 l-160 -160zM776 793l152 152l160 -160l152 -152l29 -30q64 -64 87.5 -150.5t2.5 -171.5q76 -11 126.5 -68.5t50.5 -134.5q0 -85 -60 -145.5t-145 -60.5q-74 0 -131 47t-71 118q-86 -28 -179.5 -6t-161.5 90l-11 12l151 152l12 -12q37 -37 89 -37t89 37t37 89t-37 89l-30 30 l-152 152z" /> +<glyph unicode="&#xf1ab;" d="M0 -16v1078q3 9 4 10q5 6 20 11q106 35 149 50v384l558 -198q2 0 160.5 55t316 108.5t161.5 53.5q20 0 20 -21v-418l147 -47v-1079l-774 246q-14 -6 -375 -127.5t-368 -121.5q-13 0 -18 13q0 1 -1 3zM39 15l694 232v1032l-694 -233v-1031zM147 293q6 4 82 92 q21 24 85.5 115t78.5 118q17 30 51 98.5t36 77.5q-8 1 -110 -33q-8 -2 -27.5 -7.5t-34.5 -9.5t-17 -5q-2 -2 -2 -10.5t-1 -9.5q-5 -10 -31 -15q-23 -7 -47 0q-18 4 -28 21q-4 6 -5 23q6 2 24.5 5t29.5 6q58 16 105 32q100 35 102 35q10 2 43 19.5t44 21.5q9 3 21.5 8 t14.5 5.5t6 -0.5q2 -12 -1 -33q0 -2 -12.5 -27t-26.5 -53.5t-17 -33.5q-25 -50 -77 -131l64 -28q12 -6 74.5 -32t67.5 -28q4 -1 10.5 -25.5t4.5 -30.5q-1 -3 -12.5 0.5t-31.5 11.5l-20 9q-44 20 -87 49q-7 5 -41 31.5t-38 28.5q-67 -103 -134 -181q-81 -95 -105 -110 q-4 -2 -19.5 -4t-18.5 0zM268 933l1 3q3 -3 19.5 -5t26.5 0t58 16q36 12 55 14q17 0 21 -17q3 -15 -4 -28q-12 -23 -50 -38q-30 -12 -60 -12q-26 3 -49 26q-14 15 -18 41zM310 -116q0 8 5 13.5t13 5.5q4 0 18 -7.5t30.5 -16.5t20.5 -11q73 -37 159.5 -61.5t157.5 -24.5 q95 0 167 14.5t157 50.5q15 7 30.5 15.5t34 19t28.5 16.5l-43 73l158 -13l-54 -160l-40 66q-130 -83 -276 -108q-58 -12 -91 -12h-84q-79 0 -199.5 39t-183.5 85q-8 7 -8 16zM777 1294l573 -184v380zM885 453l102 -31l45 110l211 -65l37 -135l102 -31l-181 657l-100 31z M1071 630l76 185l63 -227z" /> +<glyph unicode="&#xf1ac;" horiz-adv-x="1792" d="M0 -96v1088q0 66 47 113t113 47h128q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-128q-66 0 -113 47t-47 113zM512 -96v1536q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-163q58 -34 93 -93t35 -128v-768q0 -106 -75 -181 t-181 -75h-864q-66 0 -113 47t-47 113zM640 896h896v256h-160q-40 0 -68 28t-28 68v160h-640v-512zM736 0q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128zM736 256q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v128q0 14 -9 23t-23 9 h-128q-14 0 -23 -9t-9 -23v-128zM736 512q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128zM992 0q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128zM992 256q0 -14 9 -23t23 -9h128 q14 0 23 9t9 23v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128zM992 512q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128zM1248 0q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23 v-128zM1248 256q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128zM1248 512q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128z" /> +<glyph unicode="&#xf1ad;" d="M0 -192v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45zM256 160q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM256 416q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64 q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM256 672q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM256 928q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM256 1184q0 -14 9 -23 t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM512 96v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23zM512 416q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9 t-9 -23v-64zM512 672q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM512 928q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM512 1184q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64 q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM768 416q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM768 672q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM768 928q0 -14 9 -23 t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM768 1184q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM1024 160q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9 t-9 -23v-64zM1024 416q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM1024 672q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM1024 928q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64 q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64zM1024 1184q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64z" /> +<glyph unicode="&#xf1ae;" horiz-adv-x="1280" d="M64 1056q0 40 28 68t68 28t68 -28l228 -228h368l228 228q28 28 68 28t68 -28t28 -68t-28 -68l-292 -292v-824q0 -46 -33 -79t-79 -33t-79 33t-33 79v384h-64v-384q0 -46 -33 -79t-79 -33t-79 33t-33 79v824l-292 292q-28 28 -28 68zM416 1152q0 93 65.5 158.5t158.5 65.5 t158.5 -65.5t65.5 -158.5t-65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5z" /> +<glyph unicode="&#xf1b0;" horiz-adv-x="1664" d="M0 724q0 80 42 139.5t119 59.5q76 0 141.5 -55.5t100.5 -134t35 -152.5q0 -80 -42 -139t-119 -59q-76 0 -141.5 55.5t-100.5 133.5t-35 152zM256 19q0 86 56 191.5t139.5 192.5t187.5 146t193 59q118 0 255 -97.5t229 -237t92 -254.5q0 -46 -17 -76.5t-48.5 -45 t-64.5 -20t-76 -5.5q-68 0 -187.5 45t-182.5 45q-66 0 -192.5 -44.5t-200.5 -44.5q-183 0 -183 146zM333 1163q0 60 19 113.5t63 92.5t105 39q77 0 138.5 -57.5t91.5 -135t30 -151.5q0 -60 -19 -113.5t-63 -92.5t-105 -39q-76 0 -138 57.5t-92 135.5t-30 151zM884 1064 q0 74 30 151.5t91.5 135t138.5 57.5q61 0 105 -39t63 -92.5t19 -113.5q0 -73 -30 -151t-92 -135.5t-138 -57.5q-61 0 -105 39t-63 92.5t-19 113.5zM1226 581q0 74 35 152.5t100.5 134t141.5 55.5q77 0 119 -59.5t42 -139.5q0 -74 -35 -152t-100.5 -133.5t-141.5 -55.5 q-77 0 -119 59t-42 139z" /> +<glyph unicode="&#xf1b1;" horiz-adv-x="768" d="M64 1008q0 128 42.5 249.5t117.5 200t160 78.5t160 -78.5t117.5 -200t42.5 -249.5q0 -145 -57 -243.5t-152 -135.5l45 -821q2 -26 -16 -45t-44 -19h-192q-26 0 -44 19t-16 45l45 821q-95 37 -152 135.5t-57 243.5z" /> +<glyph unicode="&#xf1b2;" horiz-adv-x="1792" d="M0 256v768q0 40 23 73t61 47l704 256q22 8 44 8t44 -8l704 -256q38 -14 61 -47t23 -73v-768q0 -35 -18 -65t-49 -47l-704 -384q-28 -16 -61 -16t-61 16l-704 384q-31 17 -49 47t-18 65zM134 1026l698 -254l698 254l-698 254zM896 -93l640 349v636l-640 -233v-752z" /> +<glyph unicode="&#xf1b3;" horiz-adv-x="2304" d="M0 96v416q0 38 21.5 70t56.5 48l434 186v400q0 38 21.5 70t56.5 48l448 192q23 10 50 10t50 -10l448 -192q35 -16 56.5 -48t21.5 -70v-400l434 -186q36 -16 57 -48t21 -70v-416q0 -36 -19 -67t-52 -47l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-5 2 -7 4q-2 -2 -7 -4 l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-33 16 -52 47t-19 67zM172 531l404 -173l404 173l-404 173zM640 -96l384 192v314l-384 -164v-342zM647 1219l441 -189l441 189l-441 189zM1152 651l384 165v266l-384 -164v-267zM1196 531l404 -173l404 173l-404 173zM1664 -96 l384 192v314l-384 -164v-342z" /> +<glyph unicode="&#xf1b4;" horiz-adv-x="2048" d="M0 22v1260h594q87 0 155 -14t126.5 -47.5t90 -96.5t31.5 -154q0 -181 -172 -263q114 -32 172 -115t58 -204q0 -75 -24.5 -136.5t-66 -103.5t-98.5 -71t-121 -42t-134 -13h-611zM277 236h296q205 0 205 167q0 180 -199 180h-302v-347zM277 773h281q78 0 123.5 36.5 t45.5 113.5q0 144 -190 144h-260v-294zM1137 477q0 208 130.5 345.5t336.5 137.5q138 0 240.5 -68t153 -179t50.5 -248q0 -17 -2 -47h-658q0 -111 57.5 -171.5t166.5 -60.5q63 0 122 32t76 87h221q-100 -307 -427 -307q-214 0 -340.5 132t-126.5 347zM1337 1073h511v124 h-511v-124zM1388 576h408q-18 195 -200 195q-90 0 -146 -52.5t-62 -142.5z" /> +<glyph unicode="&#xf1b5;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM128 254h382q117 0 197 57.5t80 170.5q0 158 -143 200q107 52 107 164q0 57 -19.5 96.5t-56.5 60.5t-79 29.5 t-97 8.5h-371v-787zM301 388v217h189q124 0 124 -113q0 -104 -128 -104h-185zM301 723v184h163q119 0 119 -90q0 -94 -106 -94h-176zM838 538q0 -135 79 -217t213 -82q205 0 267 191h-138q-11 -34 -47.5 -54t-75.5 -20q-68 0 -104 38t-36 107h411q1 10 1 30 q0 132 -74.5 220.5t-203.5 88.5q-128 0 -210 -86t-82 -216zM964 911v77h319v-77h-319zM996 600q4 56 39 89t91 33q113 0 124 -122h-254z" /> +<glyph unicode="&#xf1b6;" horiz-adv-x="2048" d="M0 764q0 86 61 146.5t146 60.5q73 0 130 -46t73 -117l783 -315q49 29 106 29q14 0 21 -1l173 248q1 114 82 194.5t195 80.5q115 0 196.5 -81t81.5 -196t-81.5 -196.5t-196.5 -81.5l-265 -194q-8 -80 -67.5 -133.5t-138.5 -53.5q-73 0 -130 46t-73 117l-783 315 q-51 -30 -106 -30q-85 0 -146 61t-61 147zM55 764q0 -64 44.5 -108.5t107.5 -44.5q11 0 33 4l-64 26q-33 14 -52.5 44.5t-19.5 66.5q0 50 35.5 85.5t85.5 35.5q20 0 41 -8v1l76 -31q-20 37 -56.5 59t-78.5 22q-63 0 -107.5 -44.5t-44.5 -107.5zM1164 244q19 -37 55.5 -59 t79.5 -22q63 0 107.5 44.5t44.5 107.5t-44.5 108t-107.5 45q-13 0 -33 -4q2 -1 20 -8t21.5 -8.5t18.5 -8.5t19 -10t16 -11t15.5 -13.5t11 -14.5t10 -18t5 -21t2.5 -25q0 -50 -35.5 -85.5t-85.5 -35.5q-14 0 -31.5 4.5t-29 9t-31.5 13.5t-28 12zM1584 767q0 -77 54.5 -131.5 t131.5 -54.5t132 54.5t55 131.5t-55 131.5t-132 54.5q-76 0 -131 -54.5t-55 -131.5zM1623 767q0 62 43.5 105.5t104.5 43.5t105 -44t44 -105t-43.5 -104.5t-105.5 -43.5q-61 0 -104.5 43.5t-43.5 104.5z" /> +<glyph unicode="&#xf1b7;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM128 693q0 -53 38 -91t92 -38q36 0 66 18l489 -197q10 -44 45.5 -73t81.5 -29q50 0 86.5 34t41.5 83l167 122 q71 0 122 50.5t51 122.5t-51 123t-122 51q-72 0 -122.5 -50.5t-51.5 -121.5l-108 -155q-2 0 -6.5 0.5t-6.5 0.5q-35 0 -67 -19l-489 197q-10 44 -45.5 73t-80.5 29q-54 0 -92 -38t-38 -92zM162 693q0 40 28 68t68 28q27 0 49.5 -14t34.5 -37l-48 19q-29 11 -56.5 -2 t-38.5 -41q-12 -29 -0.5 -57t39.5 -40v-1l40 -16q-14 -2 -20 -2q-40 0 -68 27.5t-28 67.5zM855 369q5 -2 47 -19q29 -12 58 0.5t41 41.5q11 29 -1 57.5t-41 40.5l-40 16q14 2 21 2q39 0 67 -27.5t28 -67.5t-28 -67.5t-67 -27.5q-59 0 -85 51zM1118 695q0 48 34 82t83 34 q48 0 82 -34t34 -82t-34 -82t-82 -34q-49 0 -83 34t-34 82zM1142 696q0 -39 27.5 -66t65.5 -27t65.5 27t27.5 66q0 38 -27.5 65.5t-65.5 27.5t-65.5 -27.5t-27.5 -65.5z" /> +<glyph unicode="&#xf1b8;" horiz-adv-x="1792" d="M16 970l433 -17l180 -379l-147 92q-63 -72 -111.5 -144.5t-72.5 -125t-39.5 -94.5t-18.5 -63l-4 -21l-190 357q-17 26 -18 56t6 47l8 18q35 63 114 188zM270.5 158q-3.5 28 4 65t12 55t21.5 64t19 53q78 -12 509 -28l-15 -368l-2 -22l-420 29q-36 3 -67 31.5t-47 65.5 q-11 27 -14.5 55zM294 1124l225 356q20 31 60 45t80 10q24 -2 48.5 -12t42 -21t41.5 -33t36 -34.5t36 -39.5t32 -35q-47 -63 -265 -435l-317 187zM782 1524l405 -1q31 3 58 -10.5t39 -28.5l11 -15q39 -61 112 -190l142 83l-220 -373l-419 20l151 86q-34 89 -75 166 t-75.5 123.5t-64.5 80t-47 46.5zM953 197l211 362l7 -173q170 -16 283 -5t170 33l56 22l-188 -359q-12 -29 -36.5 -46.5t-43.5 -20.5l-18 -4q-71 -7 -219 -12l8 -164zM1218 847l313 195l19 11l212 -363q18 -37 12.5 -76t-27.5 -74q-13 -20 -33 -37t-38 -28t-48.5 -22 t-47 -16t-51.5 -14t-46 -12q-34 72 -265 436z" /> +<glyph unicode="&#xf1b9;" horiz-adv-x="1984" d="M0 160v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5t179 63.5h704q98 0 179 -63.5t104 -157.5l105 -419h28q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-128v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-928v-128q0 -80 -56 -136 t-136 -56t-136 56t-56 136v128h-96q-14 0 -23 9t-9 23zM160 448q0 -66 47 -113t113 -47t113 47t47 113t-47 113t-113 47t-113 -47t-47 -113zM516 768h952l-89 357q-2 8 -14 17.5t-21 9.5h-704q-9 0 -21 -9.5t-14 -17.5zM1472 448q0 -66 47 -113t113 -47t113 47t47 113 t-47 113t-113 47t-113 -47t-47 -113z" /> +<glyph unicode="&#xf1ba;" horiz-adv-x="1984" d="M0 32v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5t179 63.5h128v224q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-224h64q98 0 179 -63.5t104 -157.5l105 -419h28q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-128v-64q0 -80 -56 -136t-136 -56 t-136 56t-56 136v64h-928v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-96q-14 0 -23 9t-9 23zM160 320q0 -66 47 -113t113 -47t113 47t47 113t-47 113t-113 47t-113 -47t-47 -113zM516 640h952l-89 357q-2 8 -14 17.5t-21 9.5h-704q-9 0 -21 -9.5t-14 -17.5zM1472 320 q0 -66 47 -113t113 -47t113 47t47 113t-47 113t-113 47t-113 -47t-47 -113z" /> +<glyph unicode="&#xf1bb;" d="M32 64q0 26 19 45l402 403h-229q-26 0 -45 19t-19 45t19 45l402 403h-197q-26 0 -45 19t-19 45t19 45l384 384q19 19 45 19t45 -19l384 -384q19 -19 19 -45t-19 -45t-45 -19h-197l402 -403q19 -19 19 -45t-19 -45t-45 -19h-229l402 -403q19 -19 19 -45t-19 -45t-45 -19 h-462q1 -17 6 -87.5t5 -108.5q0 -25 -18 -42.5t-43 -17.5h-320q-25 0 -43 17.5t-18 42.5q0 38 5 108.5t6 87.5h-462q-26 0 -45 19t-19 45z" /> +<glyph unicode="&#xf1bc;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM237 886q0 -31 20.5 -52t51.5 -21q11 0 40 8q133 37 307 37q159 0 309.5 -34t253.5 -95q21 -12 40 -12 q29 0 50.5 20.5t21.5 51.5q0 47 -40 70q-126 73 -293 110.5t-343 37.5q-204 0 -364 -47q-23 -7 -38.5 -25.5t-15.5 -48.5zM289 637q0 -25 17.5 -42.5t42.5 -17.5q7 0 37 8q122 33 251 33q279 0 488 -124q24 -13 38 -13q25 0 42.5 17.5t17.5 42.5q0 40 -35 61 q-237 141 -548 141q-153 0 -303 -42q-48 -13 -48 -64zM321 406q0 -20 13.5 -34.5t35.5 -14.5q5 0 37 8q132 27 243 27q226 0 397 -103q19 -11 33 -11q19 0 33 13.5t14 34.5q0 32 -30 51q-193 115 -447 115q-133 0 -287 -34q-42 -9 -42 -52z" /> +<glyph unicode="&#xf1bd;" d="M0 11v1258q0 58 40.5 98.5t98.5 40.5h1258q58 0 98.5 -40.5t40.5 -98.5v-1258q0 -58 -40.5 -98.5t-98.5 -40.5h-1258q-58 0 -98.5 40.5t-40.5 98.5zM71 11q0 -28 20 -48t48 -20h1258q28 0 48 20t20 48v1258q0 28 -20 48t-48 20h-1258q-28 0 -48 -20t-20 -48v-1258z M121 11v141l711 195l-212 439q4 1 12 2.5t12 1.5q170 32 303.5 21.5t221 -46t143.5 -94.5q27 -28 -25 -42q-64 -16 -256 -62l-97 198q-111 7 -240 -16l188 -387l533 145v-496q0 -7 -5.5 -12.5t-12.5 -5.5h-1258q-7 0 -12.5 5.5t-5.5 12.5zM121 709v560q0 7 5.5 12.5 t12.5 5.5h1258q7 0 12.5 -5.5t5.5 -12.5v-428q-85 30 -188 52q-294 64 -645 12l-18 -3l-65 134h-233l85 -190q-132 -51 -230 -137zM246 413q-24 203 166 305l129 -270l-255 -61q-14 -3 -26 4.5t-14 21.5z" /> +<glyph unicode="&#xf1be;" horiz-adv-x="2304" d="M0 405l17 128q2 9 9 9t9 -9l20 -128l-20 -126q-2 -9 -9 -9t-9 9zM79 405l23 207q0 9 9 9q8 0 10 -9l26 -207l-26 -203q-2 -9 -10 -9q-9 0 -9 10zM169 405l21 245q2 12 12 12q11 0 11 -12l25 -245l-25 -237q0 -11 -11 -11q-10 0 -12 11zM259 405l21 252q0 13 13 13 q12 0 14 -13l23 -252l-23 -244q-2 -13 -14 -13q-13 0 -13 13zM350 405l20 234q0 6 4.5 10.5t10.5 4.5q14 0 16 -15l21 -234l-21 -246q-2 -16 -16 -16q-6 0 -10.5 4.5t-4.5 11.5zM401 159zM442 405l18 380q2 18 18 18q7 0 12 -5.5t5 -12.5l21 -380l-21 -246q0 -7 -5 -12.5 t-12 -5.5q-16 0 -18 18zM534 403l16 468q2 19 20 19q8 0 13.5 -5.5t5.5 -13.5l19 -468l-19 -244q0 -8 -5.5 -13.5t-13.5 -5.5q-18 0 -20 19zM628 405l16 506q0 9 6.5 15.5t14.5 6.5q9 0 15 -6.5t7 -15.5l18 -506l-18 -242q-2 -21 -22 -21q-19 0 -21 21zM723 405l14 -241 q1 -10 7.5 -16.5t15.5 -6.5q22 0 24 23l16 241l-16 523q-1 10 -7.5 17t-16.5 7q-9 0 -16 -7t-7 -17zM784 164zM817 405l14 510q0 11 7.5 18t17.5 7t17.5 -7t7.5 -18l15 -510l-15 -239q0 -10 -7.5 -17.5t-17.5 -7.5t-17 7t-8 18zM913 404l12 492q1 12 9 20t19 8t18.5 -8 t8.5 -20l14 -492l-14 -236q0 -11 -8 -19t-19 -8t-19 8t-9 19zM1010 405q0 -1 11 -236v-1q0 -10 6 -17q9 -11 23 -11q11 0 20 9q9 7 9 20l1 24l11 211l-12 586q0 16 -13 24q-8 5 -16 5t-16 -5q-13 -8 -13 -24l-1 -6zM1079 169zM1103 404l12 636v3q2 15 12 24q9 7 20 7 q8 0 15 -5q14 -8 16 -26l14 -639l-14 -231q0 -13 -9 -22t-22 -9t-22 9t-10 22l-6 114zM1204 174v899q0 23 28 33q85 34 181 34q195 0 338 -131.5t160 -323.5q53 22 110 22q117 0 200 -83t83 -201q0 -117 -83 -199.5t-200 -82.5h-786q-13 2 -22 11t-9 22z" /> +<glyph unicode="&#xf1c0;" d="M0 0v170q119 -84 325 -127t443 -43t443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128zM0 384v170q119 -84 325 -127t443 -43t443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128zM0 768 v170q119 -84 325 -127t443 -43t443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128zM0 1152v128q0 69 103 128t280 93.5t385 34.5t385 -34.5t280 -93.5t103 -128v-128q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5 t-103 128z" /> +<glyph unicode="&#xf1c1;" d="M0 -160v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 -128h1280v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536zM257 60q9 40 56 91.5t132 96.5q14 9 23 -6q2 -2 2 -4 q52 85 107 197q68 136 104 262q-24 82 -30.5 159.5t6.5 127.5q11 40 42 40h21h1q23 0 35 -15q18 -21 9 -68q-2 -6 -4 -8q1 -3 1 -8v-30q-2 -123 -14 -192q55 -164 146 -238q33 -26 84 -56q59 7 117 7q147 0 177 -49q16 -22 2 -52q0 -1 -1 -2l-2 -2v-1q-6 -38 -71 -38 q-48 0 -115 20t-130 53q-221 -24 -392 -83q-153 -262 -242 -262q-15 0 -28 7l-24 12q-1 1 -6 5q-10 10 -6 36zM318 54q52 24 137 158q-51 -40 -87.5 -84t-49.5 -74zM592 313q135 54 284 81q-2 1 -13 9.5t-16 13.5q-76 67 -127 176q-27 -86 -83 -197q-30 -56 -45 -83z M714 842q1 7 7 44q0 3 7 43q1 4 4 8q-1 1 -1 2t-0.5 1.5t-0.5 1.5q-1 22 -13 36q0 -1 -1 -2v-2q-15 -42 -2 -132zM1024 1024h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376zM1098 353q76 -28 124 -28q14 0 18 1q0 1 -2 3q-24 24 -140 24z" /> +<glyph unicode="&#xf1c2;" d="M0 -160v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 -128h1280v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536zM233 661h70l164 -661h159l128 485q7 20 10 46q2 16 2 24 h4l3 -24q1 -3 3.5 -20t5.5 -26l128 -485h159l164 661h70v107h-300v-107h90l-99 -438q-5 -20 -7 -46l-2 -21h-4l-3 21q-1 5 -4 21t-5 25l-144 545h-114l-144 -545q-2 -9 -4.5 -24.5t-3.5 -21.5l-4 -21h-4l-2 21q-2 26 -7 46l-99 438h90v107h-300v-107zM1024 1024h376 q-10 29 -22 41l-313 313q-12 12 -41 22v-376z" /> +<glyph unicode="&#xf1c3;" d="M0 -160v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 -128h1280v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536zM429 0h281v106h-75l103 161q5 7 10 16.5t7.5 13.5t3.5 4 h2q1 -4 5 -10q2 -4 4.5 -7.5t6 -8t6.5 -8.5l107 -161h-76v-106h291v106h-68l-192 273l195 282h67v107h-279v-107h74l-103 -159q-4 -7 -10 -16.5t-9 -13.5l-2 -3h-2q-1 4 -5 10q-6 11 -17 23l-106 159h76v107h-290v-107h68l189 -272l-194 -283h-68v-106zM1024 1024h376 q-10 29 -22 41l-313 313q-12 12 -41 22v-376z" /> +<glyph unicode="&#xf1c4;" d="M0 -160v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 -128h1280v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536zM416 0h327v106h-93v167h137q76 0 118 15q67 23 106.5 87 t39.5 146q0 81 -37 141t-100 87q-48 19 -130 19h-368v-107h92v-555h-92v-106zM650 386v268h120q52 0 83 -18q56 -33 56 -115q0 -89 -62 -120q-31 -15 -78 -15h-119zM1024 1024h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376z" /> +<glyph unicode="&#xf1c5;" d="M0 -160v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 -128h1280v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536zM256 0v192l192 192l128 -128l384 384l320 -320v-320 h-1024zM256 704q0 80 56 136t136 56t136 -56t56 -136t-56 -136t-136 -56t-136 56t-56 136zM1024 1024h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376z" /> +<glyph unicode="&#xf1c6;" d="M0 -160v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 -128h1280v1024h-416q-40 0 -68 28t-28 68v416h-128v-128h-128v128h-512v-1536zM384 192q0 25 8 52q21 63 120 396 v128h128v-128h79q22 0 39 -13t23 -34l107 -349q8 -27 8 -52q0 -83 -72.5 -137.5t-183.5 -54.5t-183.5 54.5t-72.5 137.5zM512 192q0 -26 37.5 -45t90.5 -19t90.5 19t37.5 45t-37.5 45t-90.5 19t-90.5 -19t-37.5 -45zM512 896h128v128h-128v-128zM512 1152h128v128h-128v-128 zM640 768h128v128h-128v-128zM640 1024h128v128h-128v-128zM1024 1024h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376z" /> +<glyph unicode="&#xf1c7;" d="M0 -160v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 -128h1280v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536zM256 288v192q0 14 9 23t23 9h131l166 167q16 15 35 7 q20 -8 20 -30v-544q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-166 167h-131q-14 0 -23 9t-9 23zM762 206.5q1 -26.5 20 -44.5q20 -17 44 -17q27 0 47 20q87 93 87 219t-87 219q-18 19 -45 20t-46 -17t-20 -44.5t18 -46.5q52 -57 52 -131t-52 -131q-19 -20 -18 -46.5z M973.5 54.5q2.5 -26.5 23.5 -42.5q18 -15 40 -15q31 0 50 24q129 159 129 363t-129 363q-16 21 -43 24t-47 -14q-21 -17 -23.5 -43.5t14.5 -47.5q100 -123 100 -282t-100 -282q-17 -21 -14.5 -47.5zM1024 1024h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376z" /> +<glyph unicode="&#xf1c8;" d="M0 -160v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 -128h1280v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536zM256 256v384q0 52 38 90t90 38h384q52 0 90 -38t38 -90 v-384q0 -52 -38 -90t-90 -38h-384q-52 0 -90 38t-38 90zM960 403v90l265 266q9 9 23 9q4 0 12 -2q20 -8 20 -30v-576q0 -22 -20 -30q-8 -2 -12 -2q-14 0 -23 9zM1024 1024h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376z" /> +<glyph unicode="&#xf1c9;" d="M0 -160v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68zM128 -128h1280v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536zM254 429q-14 19 0 38l226 301q8 11 21 12.5t24 -6.5 l51 -38q11 -8 12.5 -21t-6.5 -24l-182 -243l182 -243q8 -11 6.5 -24t-12.5 -21l-51 -38q-11 -8 -24 -6.5t-21 12.5zM636 43l138 831q2 13 13 20.5t24 5.5l63 -10q13 -2 20.5 -13t5.5 -24l-138 -831q-2 -13 -13 -20.5t-24 -5.5l-63 10q-13 2 -20.5 13t-5.5 24zM947.5 181 q-1.5 13 6.5 24l182 243l-182 243q-8 11 -6.5 24t12.5 21l51 38q11 8 24 6.5t21 -12.5l226 -301q14 -19 0 -38l-226 -301q-8 -11 -21 -12.5t-24 6.5l-51 38q-11 8 -12.5 21zM1024 1024h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376z" /> +<glyph unicode="&#xf1ca;" d="M39 1286h283q26 -218 70 -398.5t104.5 -317t121.5 -235.5t140 -195q169 169 287 406q-142 72 -223 220t-81 333q0 192 104 314.5t284 122.5q178 0 273 -105.5t95 -297.5q0 -159 -58 -286q-7 -1 -19.5 -3t-46 -2t-63 6t-62 25.5t-50.5 51.5q31 103 31 184q0 87 -29 132 t-79 45q-53 0 -85 -49.5t-32 -140.5q0 -186 105 -293.5t267 -107.5q62 0 121 14v-198q-101 -23 -198 -23q-65 -136 -165.5 -271t-181.5 -215.5t-128 -106.5q-80 -45 -162 3q-28 17 -60.5 43.5t-85 83.5t-102.5 128.5t-107.5 184t-105.5 244t-91.5 314.5t-70.5 390z" /> +<glyph unicode="&#xf1cb;" horiz-adv-x="1792" d="M0 367v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64v-546q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64zM154 511l193 129l-193 129v-258zM216 367l603 -402v359l-334 223zM216 913l269 -180l334 223v359zM624 640 l272 -182l272 182l-272 182zM973 -35l603 402l-269 180l-334 -223v-359zM973 956l334 -223l269 180l-603 402v-359zM1445 640l193 -129v258z" /> +<glyph unicode="&#xf1cc;" horiz-adv-x="2048" d="M0 407q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5 h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55t121.5 -21 q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97q14 -16 29.5 -34t34.5 -40t29 -34q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5t-85 -189.5z " /> +<glyph unicode="&#xf1cd;" horiz-adv-x="1792" d="M0 640q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348zM128 640q0 -190 90 -361l194 194q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361zM512 640 q0 -159 112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5zM535 -38q171 -90 361 -90t361 90l-194 194q-82 -28 -167 -28t-167 28zM535 1318l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90t-361 -90z M1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" /> +<glyph unicode="&#xf1ce;" horiz-adv-x="1792" d="M0 640q0 222 101 414.5t276.5 317t390.5 155.5v-260q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5q0 230 -145.5 406t-366.5 221v260q215 -31 390.5 -155.5t276.5 -317t101 -414.5 q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348z" /> +<glyph unicode="&#xf1d0;" horiz-adv-x="1792" d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41 t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170 t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136 q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" /> +<glyph unicode="&#xf1d1;" horiz-adv-x="1792" d="M0 640q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348zM44 640q0 -173 67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331 t-67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331zM87 640q0 205 98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385zM206 217l58 34q29 -49 73 -99 l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13v-66q-208 6 -385 109.5t-283 275.5zM207 1063q106 172 282 275.5t385 109.5v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98zM415 805q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10 t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162q-67 77 -98 169l232 80q-14 42 -14 85t14 85zM918 -102 q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99l58 -34q-106 -172 -283 -275.5t-385 -109.5v66zM918 1382v66q209 -6 385 -109.5t282 -275.5l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13zM1516 428q36 103 36 212q0 112 -35 212l82 28 q-19 56 -49 112l57 33q98 -180 98 -385t-98 -385l-57 33q27 52 49 112z" /> +<glyph unicode="&#xf1d2;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 218q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5 t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85q0 -53 41 -77v-3q-113 -37 -113 -139zM382 225q0 64 98 64q102 0 102 -61q0 -66 -93 -66 q-107 0 -107 63zM395 693q0 90 77 90q36 0 55 -25.5t19 -63.5q0 -85 -74 -85q-77 0 -77 84zM755 1072q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392q0 -50 -3 -75z M966 771q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117z" /> +<glyph unicode="&#xf1d3;" horiz-adv-x="1792" d="M68 7q0 165 182 225v4q-67 41 -67 126q0 109 63 137v4q-72 24 -119.5 108.5t-47.5 165.5q0 139 95 231.5t235 92.5q96 0 178 -47q98 0 218 47v-202q-36 -12 -79 -22q16 -43 16 -84q0 -127 -73 -216.5t-197 -112.5q-40 -8 -59.5 -27t-19.5 -58q0 -31 22.5 -51.5t58 -32 t78.5 -22t86 -25.5t78.5 -37.5t58 -64t22.5 -98.5q0 -304 -363 -304q-69 0 -130 12.5t-116 41t-87.5 82t-32.5 127.5zM272 18q0 -101 172 -101q151 0 151 105q0 100 -165 100q-158 0 -158 -104zM293 775q0 -135 124 -135q119 0 119 137q0 61 -30 102t-89 41 q-124 0 -124 -145zM875 1389q0 59 39.5 103t98.5 44q58 0 96.5 -44.5t38.5 -102.5t-39 -101.5t-96 -43.5q-58 0 -98 43.5t-40 101.5zM901 220q4 45 4 134v609q0 94 -4 128h222q-4 -33 -4 -124v-613q0 -89 4 -134h-222zM1217 901v190h96v76q0 54 -6 89h227q-6 -41 -6 -165 h171v-190q-15 0 -43.5 2t-42.5 2h-85v-365q0 -131 87 -131q61 0 109 33v-196q-71 -39 -174 -39q-62 0 -107 20t-70 50t-39.5 78t-18.5 92t-4 103v351h2v4q-7 0 -19 1t-18 1q-21 0 -59 -6z" /> +<glyph unicode="&#xf1d4;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM368 1135l323 -589v-435h134v436l343 588h-150q-21 -39 -63.5 -118.5t-68 -128.5t-59.5 -118.5t-60 -128.5h-3 q-21 48 -44.5 97t-52 105.5t-46.5 92t-54 104.5t-49 95h-150z" /> +<glyph unicode="&#xf1d5;" horiz-adv-x="1280" d="M57 953q0 119 46.5 227t124.5 186t186 124t226 46q158 0 292.5 -78t212.5 -212.5t78 -292.5t-78 -292t-212.5 -212t-292.5 -78q-64 0 -131 14q-21 5 -32.5 23.5t-6.5 39.5q5 20 23 31.5t39 7.5q51 -13 108 -13q97 0 186 38t153 102t102 153t38 186t-38 186t-102 153 t-153 102t-186 38t-186 -38t-153 -102t-102 -153t-38 -186q0 -114 52 -218q10 -20 3.5 -40t-25.5 -30t-39.5 -3t-30.5 26q-64 123 -64 265zM113.5 38.5q10.5 121.5 29.5 217t54 186t69 155.5t74 125q61 90 132 165q-16 35 -16 77q0 80 56.5 136.5t136.5 56.5t136.5 -56.5 t56.5 -136.5t-57 -136.5t-136 -56.5q-60 0 -111 35q-62 -67 -115 -146q-247 -371 -202 -859q1 -22 -12.5 -38.5t-34.5 -18.5h-5q-20 0 -35 13.5t-17 33.5q-14 126 -3.5 247.5z" /> +<glyph unicode="&#xf1d6;" horiz-adv-x="1792" d="M18 264q0 275 252 466q-8 19 -8 52q0 20 11 49t24 45q-1 22 7.5 53t22.5 43q0 139 92.5 288.5t217.5 209.5q139 66 324 66q133 0 266 -55q49 -21 90 -48t71 -56t55 -68t42 -74t32.5 -84.5t25.5 -89.5t22 -98l1 -5q55 -83 55 -150q0 -14 -9 -40t-9 -38q0 -1 1.5 -3.5 t3.5 -5t2 -3.5q77 -114 120.5 -214.5t43.5 -208.5q0 -43 -19.5 -100t-55.5 -57q-9 0 -19.5 7.5t-19 17.5t-19 26t-16 26.5t-13.5 26t-9 17.5q-1 1 -3 1l-5 -4q-59 -154 -132 -223q20 -20 61.5 -38.5t69 -41.5t35.5 -65q-2 -4 -4 -16t-7 -18q-64 -97 -302 -97q-53 0 -110.5 9 t-98 20t-104.5 30q-15 5 -23 7q-14 4 -46 4.5t-40 1.5q-41 -45 -127.5 -65t-168.5 -20q-35 0 -69 1.5t-93 9t-101 20.5t-74.5 40t-32.5 64q0 40 10 59.5t41 48.5q11 2 40.5 13t49.5 12q4 0 14 2q2 2 2 4l-2 3q-48 11 -108 105.5t-73 156.5l-5 3q-4 0 -12 -20 q-18 -41 -54.5 -74.5t-77.5 -37.5h-1q-4 0 -6 4.5t-5 5.5q-23 54 -23 100z" /> +<glyph unicode="&#xf1d7;" horiz-adv-x="2048" d="M0 858q0 169 97.5 311t264 223.5t363.5 81.5q176 0 332.5 -66t262 -182.5t136.5 -260.5q-31 4 -70 4q-169 0 -311 -77t-223.5 -208.5t-81.5 -287.5q0 -78 23 -152q-35 -3 -68 -3q-26 0 -50 1.5t-55 6.5t-44.5 7t-54.5 10.5t-50 10.5l-253 -127l72 218q-290 203 -290 490z M380 1075q0 -39 33 -64.5t76 -25.5q41 0 66 24.5t25 65.5t-25 66t-66 25q-43 0 -76 -25.5t-33 -65.5zM816 404q0 143 81.5 264t223.5 191.5t311 70.5q161 0 303 -70.5t227.5 -192t85.5 -263.5q0 -117 -68.5 -223.5t-185.5 -193.5l55 -181l-199 109q-150 -37 -218 -37 q-169 0 -311 70.5t-223.5 191.5t-81.5 264zM888 1075q0 -39 33 -64.5t76 -25.5q41 0 65.5 24.5t24.5 65.5t-24.5 66t-65.5 25q-43 0 -76 -25.5t-33 -65.5zM1160 568q0 -28 22.5 -50.5t49.5 -22.5q40 0 65.5 22t25.5 51q0 28 -25.5 50t-65.5 22q-27 0 -49.5 -22.5 t-22.5 -49.5zM1559 568q0 -28 22.5 -50.5t49.5 -22.5q39 0 65 22t26 51q0 28 -26 50t-65 22q-27 0 -49.5 -22.5t-22.5 -49.5z" /> +<glyph unicode="&#xf1d8;" horiz-adv-x="1792" d="M0 508q-2 40 32 59l1664 960q15 9 32 9q20 0 36 -11q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-453 185l-242 -295q-18 -23 -49 -23q-13 0 -22 4q-19 7 -30.5 23.5t-11.5 36.5v349l864 1059l-1069 -925l-395 162q-37 14 -40 55z" /> +<glyph unicode="&#xf1d9;" horiz-adv-x="1792" d="M0 508q-3 39 32 59l1664 960q35 21 68 -2q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-527 215l-298 -327q-18 -21 -47 -21q-14 0 -23 4q-19 7 -30 23.5t-11 36.5v452l-472 193q-37 14 -40 55zM209 522l336 -137l863 639l-478 -797l492 -201 l221 1323z" /> +<glyph unicode="&#xf1da;" d="M0 832v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298t-61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12 q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45zM512 480v64q0 14 9 23t23 9h224v352 q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf1db;" d="M0 640q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM128 640q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 t-51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5z" /> +<glyph unicode="&#xf1dc;" horiz-adv-x="1792" d="M62 1338q0 26 12 48t36 22q46 0 138.5 -3.5t138.5 -3.5q42 0 126.5 3.5t126.5 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17 -43.5t-38.5 -14.5t-49.5 -4t-43 -13q-35 -21 -35 -160l1 -320q0 -21 1 -32q13 -3 39 -3h699q25 0 38 3q1 11 1 32l1 320q0 139 -35 160 q-18 11 -58.5 12.5t-66 13t-25.5 49.5q0 26 12.5 48t37.5 22q44 0 132 -3.5t132 -3.5q43 0 129 3.5t129 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17.5 -44t-40 -14.5t-51.5 -3t-44 -12.5q-35 -23 -35 -161l1 -943q0 -119 34 -140q16 -10 46 -13.5t53.5 -4.5t41.5 -15.5t18 -44.5 q0 -26 -12 -48t-36 -22q-44 0 -132.5 3.5t-133.5 3.5q-44 0 -132 -3.5t-132 -3.5q-24 0 -37 20.5t-13 45.5q0 31 17 46t39 17t51 7t45 15q33 21 33 140l-1 391q0 21 -1 31q-13 4 -50 4h-675q-38 0 -51 -4q-1 -10 -1 -31l-1 -371q0 -142 37 -164q16 -10 48 -13t57 -3.5 t45 -15t20 -45.5q0 -26 -12.5 -48t-36.5 -22q-47 0 -139.5 3.5t-138.5 3.5q-43 0 -128 -3.5t-127 -3.5q-23 0 -35.5 21t-12.5 45q0 30 15.5 45t36 17.5t47.5 7.5t42 15q33 23 33 143l-1 57v813q0 3 0.5 26t0 36.5t-1.5 38.5t-3.5 42t-6.5 36.5t-11 31.5t-16 18 q-15 10 -45 12t-53 2t-41 14t-18 45z" /> +<glyph unicode="&#xf1dd;" horiz-adv-x="1280" d="M24 926q0 166 88 286q88 118 209 159q111 37 417 37h479q25 0 43 -18t18 -43v-73q0 -29 -18.5 -61t-42.5 -32q-50 0 -54 -1q-26 -6 -32 -31q-3 -11 -3 -64v-1152q0 -25 -18 -43t-43 -18h-108q-25 0 -43 18t-18 43v1218h-143v-1218q0 -25 -17.5 -43t-43.5 -18h-108 q-26 0 -43.5 18t-17.5 43v496q-147 12 -245 59q-126 58 -192 179q-64 117 -64 259z" /> +<glyph unicode="&#xf1de;" d="M0 736v64q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-64q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM128 -96v672h256v-672q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23zM128 960v416q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-416h-256zM512 224v64q0 40 28 68 t68 28h320q40 0 68 -28t28 -68v-64q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM640 64h256v-160q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v160zM640 448v928q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-928h-256zM1024 992v64q0 40 28 68t68 28h320q40 0 68 -28 t28 -68v-64q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68zM1152 -96v928h256v-928q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23zM1152 1216v160q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-160h-256z" /> +<glyph unicode="&#xf1e0;" d="M0 640q0 133 93.5 226.5t226.5 93.5q126 0 218 -86l360 180q-2 22 -2 34q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5q-126 0 -218 86l-360 -180q2 -22 2 -34t-2 -34l360 -180q92 86 218 86q133 0 226.5 -93.5t93.5 -226.5 t-93.5 -226.5t-226.5 -93.5t-226.5 93.5t-93.5 226.5q0 12 2 34l-360 180q-92 -86 -218 -86q-133 0 -226.5 93.5t-93.5 226.5z" /> +<glyph unicode="&#xf1e1;" d="M0 160v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5zM256 640q0 -88 62.5 -150.5t150.5 -62.5q83 0 145 57l241 -120q-2 -16 -2 -23q0 -88 63 -150.5t151 -62.5 t150.5 62.5t62.5 150.5t-62.5 151t-150.5 63q-84 0 -145 -58l-241 120q2 16 2 23t-2 23l241 120q61 -58 145 -58q88 0 150.5 63t62.5 151t-62.5 150.5t-150.5 62.5t-151 -62.5t-63 -150.5q0 -7 2 -23l-241 -120q-62 57 -145 57q-88 0 -150.5 -62.5t-62.5 -150.5z" /> +<glyph unicode="&#xf1e2;" horiz-adv-x="1792" d="M0 448q0 143 55.5 273.5t150 225t225 150t273.5 55.5q182 0 343 -89l64 64q19 19 45.5 19t45.5 -19l68 -68l243 244l46 -46l-244 -243l68 -68q19 -19 19 -45.5t-19 -45.5l-64 -64q89 -161 89 -343q0 -143 -55.5 -273.5t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5 t-225 150t-150 225t-55.5 273.5zM170 615q10 -24 35 -34q13 -5 24 -5q42 0 60 40q34 84 98.5 148.5t148.5 98.5q25 11 35 35t0 49t-34 35t-49 0q-108 -44 -191 -127t-127 -191q-10 -25 0 -49zM1376 1472q0 13 9 23q10 9 23 9t23 -9l90 -91q10 -9 10 -22.5t-10 -22.5 q-10 -10 -22 -10q-13 0 -23 10l-91 90q-9 10 -9 23zM1536 1408v96q0 14 9 23t23 9t23 -9t9 -23v-96q0 -14 -9 -23t-23 -9t-23 9t-9 23zM1605 1242.5q0 13.5 10 22.5q9 10 22.5 10t22.5 -10l91 -90q9 -10 9 -23t-9 -23q-11 -9 -23 -9t-23 9l-90 91q-10 9 -10 22.5z M1605 1381.5q0 13.5 10 22.5l90 91q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-91 -90q-10 -10 -22 -10q-13 0 -23 10q-10 9 -10 22.5zM1632 1312q0 14 9 23t23 9h96q14 0 23 -9t9 -23t-9 -23t-23 -9h-96q-14 0 -23 9t-9 23z" /> +<glyph unicode="&#xf1e3;" horiz-adv-x="1792" /> +<glyph unicode="&#xf1e4;" horiz-adv-x="1792" /> +<glyph unicode="&#xf1e5;" horiz-adv-x="1792" /> +<glyph unicode="&#xf1e6;" horiz-adv-x="1792" /> +<glyph unicode="&#xf1e7;" horiz-adv-x="1792" /> +<glyph unicode="&#xf1e8;" horiz-adv-x="1792" /> +<glyph unicode="&#xf1e9;" horiz-adv-x="1792" /> +<glyph unicode="&#xf1ea;" horiz-adv-x="1792" /> +<glyph unicode="&#xf1eb;" horiz-adv-x="1792" /> +<glyph unicode="&#xf1ec;" horiz-adv-x="1792" /> +<glyph unicode="&#xf1ed;" horiz-adv-x="1792" /> +<glyph unicode="&#xf1ee;" horiz-adv-x="1792" /> +<glyph unicode="&#xf500;" horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +<glyph horiz-adv-x="1792" /> +</font> +</defs></svg> \ No newline at end of file diff --git a/src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.ttf b/src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.ttf new file mode 100755 index 0000000000000000000000000000000000000000..5cd6cff6d6f6cf438a882e366420dbcc5dddd3f1 GIT binary patch literal 141564 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 I|8sWsA3C_2MF0Q* literal 0 HcmV?d00001 diff --git a/src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.woff b/src/core/libs/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.woff new file mode 100755 index 0000000000000000000000000000000000000000..9eaecb37996e205f1027fce2df59fbaa500657a8 GIT binary patch literal 83760 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%0D%8GQ!Ai?6y^fVUY%4hi><Jn7or4|r4~4->cI9O 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 literal 0 HcmV?d00001 diff --git a/src/core/libs/DebugBar/Resources/vendor/highlightjs/highlight.pack.js b/src/core/libs/DebugBar/Resources/vendor/highlightjs/highlight.pack.js new file mode 100755 index 0000000..cf7215a --- /dev/null +++ b/src/core/libs/DebugBar/Resources/vendor/highlightjs/highlight.pack.js @@ -0,0 +1 @@ +var hljs=new function(){function k(v){return v.replace(/&/gm,"&amp;").replace(/</gm,"&lt;").replace(/>/gm,"&gt;")}function t(v){return v.nodeName.toLowerCase()}function i(w,x){var v=w&&w.exec(x);return v&&v.index==0}function d(v){return Array.prototype.map.call(v.childNodes,function(w){if(w.nodeType==3){return b.useBR?w.nodeValue.replace(/\n/g,""):w.nodeValue}if(t(w)=="br"){return"\n"}return d(w)}).join("")}function r(w){var v=(w.className+" "+(w.parentNode?w.parentNode.className:"")).split(/\s+/);v=v.map(function(x){return x.replace(/^language-/,"")});return v.filter(function(x){return j(x)||x=="no-highlight"})[0]}function o(x,y){var v={};for(var w in x){v[w]=x[w]}if(y){for(var w in y){v[w]=y[w]}}return v}function u(x){var v=[];(function w(y,z){for(var A=y.firstChild;A;A=A.nextSibling){if(A.nodeType==3){z+=A.nodeValue.length}else{if(t(A)=="br"){z+=1}else{if(A.nodeType==1){v.push({event:"start",offset:z,node:A});z=w(A,z);v.push({event:"stop",offset:z,node:A})}}}}return z})(x,0);return v}function q(w,y,C){var x=0;var F="";var z=[];function B(){if(!w.length||!y.length){return w.length?w:y}if(w[0].offset!=y[0].offset){return(w[0].offset<y[0].offset)?w:y}return y[0].event=="start"?w:y}function A(H){function G(I){return" "+I.nodeName+'="'+k(I.value)+'"'}F+="<"+t(H)+Array.prototype.map.call(H.attributes,G).join("")+">"}function E(G){F+="</"+t(G)+">"}function v(G){(G.event=="start"?A:E)(G.node)}while(w.length||y.length){var D=B();F+=k(C.substr(x,D[0].offset-x));x=D[0].offset;if(D==w){z.reverse().forEach(E);do{v(D.splice(0,1)[0]);D=B()}while(D==w&&D.length&&D[0].offset==x);z.reverse().forEach(A)}else{if(D[0].event=="start"){z.push(D[0].node)}else{z.pop()}v(D.splice(0,1)[0])}}return F+k(C.substr(x))}function m(y){function v(z){return(z&&z.source)||z}function w(A,z){return RegExp(v(A),"m"+(y.cI?"i":"")+(z?"g":""))}function x(D,C){if(D.compiled){return}D.compiled=true;D.k=D.k||D.bK;if(D.k){var z={};function E(G,F){if(y.cI){F=F.toLowerCase()}F.split(" ").forEach(function(H){var I=H.split("|");z[I[0]]=[G,I[1]?Number(I[1]):1]})}if(typeof D.k=="string"){E("keyword",D.k)}else{Object.keys(D.k).forEach(function(F){E(F,D.k[F])})}D.k=z}D.lR=w(D.l||/\b[A-Za-z0-9_]+\b/,true);if(C){if(D.bK){D.b=D.bK.split(" ").join("|")}if(!D.b){D.b=/\B|\b/}D.bR=w(D.b);if(!D.e&&!D.eW){D.e=/\B|\b/}if(D.e){D.eR=w(D.e)}D.tE=v(D.e)||"";if(D.eW&&C.tE){D.tE+=(D.e?"|":"")+C.tE}}if(D.i){D.iR=w(D.i)}if(D.r===undefined){D.r=1}if(!D.c){D.c=[]}var B=[];D.c.forEach(function(F){if(F.v){F.v.forEach(function(G){B.push(o(F,G))})}else{B.push(F=="self"?D:F)}});D.c=B;D.c.forEach(function(F){x(F,D)});if(D.starts){x(D.starts,C)}var A=D.c.map(function(F){return F.bK?"\\.?\\b("+F.b+")\\b\\.?":F.b}).concat([D.tE]).concat([D.i]).map(v).filter(Boolean);D.t=A.length?w(A.join("|"),true):{exec:function(F){return null}};D.continuation={}}x(y)}function c(S,L,J,R){function v(U,V){for(var T=0;T<V.c.length;T++){if(i(V.c[T].bR,U)){return V.c[T]}}}function z(U,T){if(i(U.eR,T)){return U}if(U.eW){return z(U.parent,T)}}function A(T,U){return !J&&i(U.iR,T)}function E(V,T){var U=M.cI?T[0].toLowerCase():T[0];return V.k.hasOwnProperty(U)&&V.k[U]}function w(Z,X,W,V){var T=V?"":b.classPrefix,U='<span class="'+T,Y=W?"":"</span>";U+=Z+'">';return U+X+Y}function N(){var U=k(C);if(!I.k){return U}var T="";var X=0;I.lR.lastIndex=0;var V=I.lR.exec(U);while(V){T+=U.substr(X,V.index-X);var W=E(I,V);if(W){H+=W[1];T+=w(W[0],V[0])}else{T+=V[0]}X=I.lR.lastIndex;V=I.lR.exec(U)}return T+U.substr(X)}function F(){if(I.sL&&!f[I.sL]){return k(C)}var T=I.sL?c(I.sL,C,true,I.continuation.top):g(C);if(I.r>0){H+=T.r}if(I.subLanguageMode=="continuous"){I.continuation.top=T.top}return w(T.language,T.value,false,true)}function Q(){return I.sL!==undefined?F():N()}function P(V,U){var T=V.cN?w(V.cN,"",true):"";if(V.rB){D+=T;C=""}else{if(V.eB){D+=k(U)+T;C=""}else{D+=T;C=U}}I=Object.create(V,{parent:{value:I}})}function G(T,X){C+=T;if(X===undefined){D+=Q();return 0}var V=v(X,I);if(V){D+=Q();P(V,X);return V.rB?0:X.length}var W=z(I,X);if(W){var U=I;if(!(U.rE||U.eE)){C+=X}D+=Q();do{if(I.cN){D+="</span>"}H+=I.r;I=I.parent}while(I!=W.parent);if(U.eE){D+=k(X)}C="";if(W.starts){P(W.starts,"")}return U.rE?0:X.length}if(A(X,I)){throw new Error('Illegal lexeme "'+X+'" for mode "'+(I.cN||"<unnamed>")+'"')}C+=X;return X.length||1}var M=j(S);if(!M){throw new Error('Unknown language: "'+S+'"')}m(M);var I=R||M;var D="";for(var K=I;K!=M;K=K.parent){if(K.cN){D=w(K.cN,D,true)}}var C="";var H=0;try{var B,y,x=0;while(true){I.t.lastIndex=x;B=I.t.exec(L);if(!B){break}y=G(L.substr(x,B.index-x),B[0]);x=B.index+y}G(L.substr(x));for(var K=I;K.parent;K=K.parent){if(K.cN){D+="</span>"}}return{r:H,value:D,language:S,top:I}}catch(O){if(O.message.indexOf("Illegal")!=-1){return{r:0,value:k(L)}}else{throw O}}}function g(y,x){x=x||b.languages||Object.keys(f);var v={r:0,value:k(y)};var w=v;x.forEach(function(z){if(!j(z)){return}var A=c(z,y,false);A.language=z;if(A.r>w.r){w=A}if(A.r>v.r){w=v;v=A}});if(w.language){v.second_best=w}return v}function h(v){if(b.tabReplace){v=v.replace(/^((<[^>]+>|\t)+)/gm,function(w,z,y,x){return z.replace(/\t/g,b.tabReplace)})}if(b.useBR){v=v.replace(/\n/g,"<br>")}return v}function p(z){var y=d(z);var A=r(z);if(A=="no-highlight"){return}var v=A?c(A,y,true):g(y);var w=u(z);if(w.length){var x=document.createElementNS("http://www.w3.org/1999/xhtml","pre");x.innerHTML=v.value;v.value=q(w,u(x),y)}v.value=h(v.value);z.innerHTML=v.value;z.className+=" hljs "+(!A&&v.language||"");z.result={language:v.language,re:v.r};if(v.second_best){z.second_best={language:v.second_best.language,re:v.second_best.r}}}var b={classPrefix:"hljs-",tabReplace:null,useBR:false,languages:undefined};function s(v){b=o(b,v)}function l(){if(l.called){return}l.called=true;var v=document.querySelectorAll("pre code");Array.prototype.forEach.call(v,p)}function a(){addEventListener("DOMContentLoaded",l,false);addEventListener("load",l,false)}var f={};var n={};function e(v,x){var w=f[v]=x(this);if(w.aliases){w.aliases.forEach(function(y){n[y]=v})}}function j(v){return f[v]||f[n[v]]}this.highlight=c;this.highlightAuto=g;this.fixMarkup=h;this.highlightBlock=p;this.configure=s;this.initHighlighting=l;this.initHighlightingOnLoad=a;this.registerLanguage=e;this.getLanguage=j;this.inherit=o;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\\b\\d+(\\.\\d+)?";this.CNR="(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)";this.BNR="\\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\[\\s\\S]",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE]};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE]};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.BNM={cN:"number",b:this.BNR,r:0};this.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gim]*/,i:/\n/,c:[this.BE,{b:/\[/,e:/\]/,r:0,c:[this.BE]}]};this.TM={cN:"title",b:this.IR,r:0};this.UTM={cN:"title",b:this.UIR,r:0}}();hljs.registerLanguage("scilab",function(a){var b=[a.CNM,{cN:"string",b:"'|\"",e:"'|\"",c:[a.BE,{b:"''"}]}];return{k:{keyword:"abort break case clear catch continue do elseif else endfunction end for functionglobal if pause return resume select try then while%f %F %t %T %pi %eps %inf %nan %e %i %z %s",built_in:"abs and acos asin atan ceil cd chdir clearglobal cosh cos cumprod deff disp errorexec execstr exists exp eye gettext floor fprintf fread fsolve imag isdef isemptyisinfisnan isvector lasterror length load linspace list listfiles log10 log2 logmax min msprintf mclose mopen ones or pathconvert poly printf prod pwd rand realround sinh sin size gsort sprintf sqrt strcat strcmps tring sum system tanh tantype typename warning zeros matrix"},i:'("|#|/\\*|\\s+/\\w+)',c:[{cN:"function",bK:"function endfunction",e:"$",k:"function endfunction|10",c:[a.UTM,{cN:"params",b:"\\(",e:"\\)"},],},{cN:"transposed_variable",b:"[a-zA-Z_][a-zA-Z_0-9]*('+[\\.']*|[\\.']+)",e:"",r:0},{cN:"matrix",b:"\\[",e:"\\]'*[\\.']*",r:0,c:b},{cN:"comment",b:"//",e:"$"}].concat(b)}});hljs.registerLanguage("xml",function(a){var c="[A-Za-z0-9\\._:-]+";var d={b:/<\?(php)?(?!\w)/,e:/\?>/,sL:"php",subLanguageMode:"continuous"};var b={eW:true,i:/</,r:0,c:[d,{cN:"attribute",b:c,r:0},{b:"=",r:0,c:[{cN:"value",v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s\/>]+/}]}]}]};return{aliases:["html"],cI:true,c:[{cN:"doctype",b:"<!DOCTYPE",e:">",r:10,c:[{b:"\\[",e:"\\]"}]},{cN:"comment",b:"<!--",e:"-->",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"<style(?=\\s|>|$)",e:">",k:{title:"style"},c:[b],starts:{e:"</style>",rE:true,sL:"css"}},{cN:"tag",b:"<script(?=\\s|>|$)",e:">",k:{title:"script"},c:[b],starts:{e:"<\/script>",rE:true,sL:"javascript"}},{b:"<%",e:"%>",sL:"vbscript"},d,{cN:"pi",b:/<\?\w+/,e:/\?>/,r:10},{cN:"tag",b:"</?",e:"/?>",c:[{cN:"title",b:"[^ /><]+",r:0},b]}]}});hljs.registerLanguage("asciidoc",function(a){return{c:[{cN:"comment",b:"^/{4,}\\n",e:"\\n/{4,}$",r:10},{cN:"comment",b:"^//",e:"$",r:0},{cN:"title",b:"^\\.\\w.*$"},{b:"^[=\\*]{4,}\\n",e:"\\n^[=\\*]{4,}$",r:10},{cN:"header",b:"^(={1,5}) .+?( \\1)?$",r:10},{cN:"header",b:"^[^\\[\\]\\n]+?\\n[=\\-~\\^\\+]{2,}$",r:10},{cN:"attribute",b:"^:.+?:",e:"\\s",eE:true,r:10},{cN:"attribute",b:"^\\[.+?\\]$",r:0},{cN:"blockquote",b:"^_{4,}\\n",e:"\\n_{4,}$",r:10},{cN:"code",b:"^[\\-\\.]{4,}\\n",e:"\\n[\\-\\.]{4,}$",r:10},{b:"^\\+{4,}\\n",e:"\\n\\+{4,}$",c:[{b:"<",e:">",sL:"xml",r:0}],r:10},{cN:"bullet",b:"^(\\*+|\\-+|\\.+|[^\\n]+?::)\\s+"},{cN:"label",b:"^(NOTE|TIP|IMPORTANT|WARNING|CAUTION):\\s+",r:10},{cN:"strong",b:"\\B\\*(?![\\*\\s])",e:"(\\n{2}|\\*)",c:[{b:"\\\\*\\w",r:0}]},{cN:"emphasis",b:"\\B'(?!['\\s])",e:"(\\n{2}|')",c:[{b:"\\\\'\\w",r:0}],r:0},{cN:"emphasis",b:"_(?![_\\s])",e:"(\\n{2}|_)",r:0},{cN:"smartquote",b:"``.+?''",r:10},{cN:"smartquote",b:"`.+?'",r:10},{cN:"code",b:"(`.+?`|\\+.+?\\+)",r:0},{cN:"code",b:"^[ \\t]",e:"$",r:0},{cN:"horizontal_rule",b:"^'{3,}[ \\t]*$",r:10},{b:"(link:)?(http|https|ftp|file|irc|image:?):\\S+\\[.*?\\]",rB:true,c:[{b:"(link|image:?):",r:0},{cN:"link_url",b:"\\w",e:"[^\\[]+",r:0},{cN:"link_label",b:"\\[",e:"\\]",eB:true,eE:true,r:0}],r:10}]}});hljs.registerLanguage("coffeescript",function(c){var b={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",reserved:"case default function var void with const let enum export import native __hasProp __extends __slice __bind __indexOf",built_in:"npm require console print module exports global window document"};var a="[A-Za-z$_][0-9A-Za-z$_]*";var f=c.inherit(c.TM,{b:a});var e={cN:"subst",b:/#\{/,e:/}/,k:b};var d=[c.BNM,c.inherit(c.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[c.BE]},{b:/'/,e:/'/,c:[c.BE]},{b:/"""/,e:/"""/,c:[c.BE,e]},{b:/"/,e:/"/,c:[c.BE,e]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[e,c.HCM]},{b:"//[gim]*",r:0},{b:"/\\S(\\\\.|[^\\n])*?/[gim]*(?=\\s|\\W|$)"}]},{cN:"property",b:"@"+a},{b:"`",e:"`",eB:true,eE:true,sL:"javascript"}];e.c=d;return{k:b,c:d.concat([{cN:"comment",b:"###",e:"###"},c.HCM,{cN:"function",b:"("+a+"\\s*=\\s*)?(\\(.*\\))?\\s*\\B[-=]>",e:"[-=]>",rB:true,c:[f,{cN:"params",b:"\\(",rB:true,c:[{b:/\(/,e:/\)/,k:b,c:["self"].concat(d)}]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:true,i:/[:="\[\]]/,c:[f]},f]},{cN:"attribute",b:a+":",e:":",rB:true,eE:true,r:0}])}});hljs.registerLanguage("fix",function(a){return{c:[{b:/[^\u2401\u0001]+/,e:/[\u2401\u0001]/,eE:true,rB:true,rE:false,c:[{b:/([^\u2401\u0001=]+)/,e:/=([^\u2401\u0001=]+)/,rE:true,rB:false,cN:"attribute"},{b:/=/,e:/([\u2401\u0001])/,eE:true,eB:true,cN:"string"}]}],cI:true}});hljs.registerLanguage("mel",function(a){return{k:"int float string vector matrix if else switch case default while do for in break continue global proc return about abs addAttr addAttributeEditorNodeHelp addDynamic addNewShelfTab addPP addPanelCategory addPrefixToName advanceToNextDrivenKey affectedNet affects aimConstraint air alias aliasAttr align alignCtx alignCurve alignSurface allViewFit ambientLight angle angleBetween animCone animCurveEditor animDisplay animView annotate appendStringArray applicationName applyAttrPreset applyTake arcLenDimContext arcLengthDimension arclen arrayMapper art3dPaintCtx artAttrCtx artAttrPaintVertexCtx artAttrSkinPaintCtx artAttrTool artBuildPaintMenu artFluidAttrCtx artPuttyCtx artSelectCtx artSetPaintCtx artUserPaintCtx assignCommand assignInputDevice assignViewportFactories attachCurve attachDeviceAttr attachSurface attrColorSliderGrp attrCompatibility attrControlGrp attrEnumOptionMenu attrEnumOptionMenuGrp attrFieldGrp attrFieldSliderGrp attrNavigationControlGrp attrPresetEditWin attributeExists attributeInfo attributeMenu attributeQuery autoKeyframe autoPlace bakeClip bakeFluidShading bakePartialHistory bakeResults bakeSimulation basename basenameEx batchRender bessel bevel bevelPlus binMembership bindSkin blend2 blendShape blendShapeEditor blendShapePanel blendTwoAttr blindDataType boneLattice boundary boxDollyCtx boxZoomCtx bufferCurve buildBookmarkMenu buildKeyframeMenu button buttonManip CBG cacheFile cacheFileCombine cacheFileMerge cacheFileTrack camera cameraView canCreateManip canvas capitalizeString catch catchQuiet ceil changeSubdivComponentDisplayLevel changeSubdivRegion channelBox character characterMap characterOutlineEditor characterize chdir checkBox checkBoxGrp checkDefaultRenderGlobals choice circle circularFillet clamp clear clearCache clip clipEditor clipEditorCurrentTimeCtx clipSchedule clipSchedulerOutliner clipTrimBefore closeCurve closeSurface cluster cmdFileOutput cmdScrollFieldExecuter cmdScrollFieldReporter cmdShell coarsenSubdivSelectionList collision color colorAtPoint colorEditor colorIndex colorIndexSliderGrp colorSliderButtonGrp colorSliderGrp columnLayout commandEcho commandLine commandPort compactHairSystem componentEditor compositingInterop computePolysetVolume condition cone confirmDialog connectAttr connectControl connectDynamic connectJoint connectionInfo constrain constrainValue constructionHistory container containsMultibyte contextInfo control convertFromOldLayers convertIffToPsd convertLightmap convertSolidTx convertTessellation convertUnit copyArray copyFlexor copyKey copySkinWeights cos cpButton cpCache cpClothSet cpCollision cpConstraint cpConvClothToMesh cpForces cpGetSolverAttr cpPanel cpProperty cpRigidCollisionFilter cpSeam cpSetEdit cpSetSolverAttr cpSolver cpSolverTypes cpTool cpUpdateClothUVs createDisplayLayer createDrawCtx createEditor createLayeredPsdFile createMotionField createNewShelf createNode createRenderLayer createSubdivRegion cross crossProduct ctxAbort ctxCompletion ctxEditMode ctxTraverse currentCtx currentTime currentTimeCtx currentUnit curve curveAddPtCtx curveCVCtx curveEPCtx curveEditorCtx curveIntersect curveMoveEPCtx curveOnSurface curveSketchCtx cutKey cycleCheck cylinder dagPose date defaultLightListCheckBox defaultNavigation defineDataServer defineVirtualDevice deformer deg_to_rad delete deleteAttr deleteShadingGroupsAndMaterials deleteShelfTab deleteUI deleteUnusedBrushes delrandstr detachCurve detachDeviceAttr detachSurface deviceEditor devicePanel dgInfo dgdirty dgeval dgtimer dimWhen directKeyCtx directionalLight dirmap dirname disable disconnectAttr disconnectJoint diskCache displacementToPoly displayAffected displayColor displayCull displayLevelOfDetail displayPref displayRGBColor displaySmoothness displayStats displayString displaySurface distanceDimContext distanceDimension doBlur dolly dollyCtx dopeSheetEditor dot dotProduct doubleProfileBirailSurface drag dragAttrContext draggerContext dropoffLocator duplicate duplicateCurve duplicateSurface dynCache dynControl dynExport dynExpression dynGlobals dynPaintEditor dynParticleCtx dynPref dynRelEdPanel dynRelEditor dynamicLoad editAttrLimits editDisplayLayerGlobals editDisplayLayerMembers editRenderLayerAdjustment editRenderLayerGlobals editRenderLayerMembers editor editorTemplate effector emit emitter enableDevice encodeString endString endsWith env equivalent equivalentTol erf error eval evalDeferred evalEcho event exactWorldBoundingBox exclusiveLightCheckBox exec executeForEachObject exists exp expression expressionEditorListen extendCurve extendSurface extrude fcheck fclose feof fflush fgetline fgetword file fileBrowserDialog fileDialog fileExtension fileInfo filetest filletCurve filter filterCurve filterExpand filterStudioImport findAllIntersections findAnimCurves findKeyframe findMenuItem findRelatedSkinCluster finder firstParentOf fitBspline flexor floatEq floatField floatFieldGrp floatScrollBar floatSlider floatSlider2 floatSliderButtonGrp floatSliderGrp floor flow fluidCacheInfo fluidEmitter fluidVoxelInfo flushUndo fmod fontDialog fopen formLayout format fprint frameLayout fread freeFormFillet frewind fromNativePath fwrite gamma gauss geometryConstraint getApplicationVersionAsFloat getAttr getClassification getDefaultBrush getFileList getFluidAttr getInputDeviceRange getMayaPanelTypes getModifiers getPanel getParticleAttr getPluginResource getenv getpid glRender glRenderEditor globalStitch gmatch goal gotoBindPose grabColor gradientControl gradientControlNoAttr graphDollyCtx graphSelectContext graphTrackCtx gravity grid gridLayout group groupObjectsByName HfAddAttractorToAS HfAssignAS HfBuildEqualMap HfBuildFurFiles HfBuildFurImages HfCancelAFR HfConnectASToHF HfCreateAttractor HfDeleteAS HfEditAS HfPerformCreateAS HfRemoveAttractorFromAS HfSelectAttached HfSelectAttractors HfUnAssignAS hardenPointCurve hardware hardwareRenderPanel headsUpDisplay headsUpMessage help helpLine hermite hide hilite hitTest hotBox hotkey hotkeyCheck hsv_to_rgb hudButton hudSlider hudSliderButton hwReflectionMap hwRender hwRenderLoad hyperGraph hyperPanel hyperShade hypot iconTextButton iconTextCheckBox iconTextRadioButton iconTextRadioCollection iconTextScrollList iconTextStaticLabel ikHandle ikHandleCtx ikHandleDisplayScale ikSolver ikSplineHandleCtx ikSystem ikSystemInfo ikfkDisplayMethod illustratorCurves image imfPlugins inheritTransform insertJoint insertJointCtx insertKeyCtx insertKnotCurve insertKnotSurface instance instanceable instancer intField intFieldGrp intScrollBar intSlider intSliderGrp interToUI internalVar intersect iprEngine isAnimCurve isConnected isDirty isParentOf isSameObject isTrue isValidObjectName isValidString isValidUiName isolateSelect itemFilter itemFilterAttr itemFilterRender itemFilterType joint jointCluster jointCtx jointDisplayScale jointLattice keyTangent keyframe keyframeOutliner keyframeRegionCurrentTimeCtx keyframeRegionDirectKeyCtx keyframeRegionDollyCtx keyframeRegionInsertKeyCtx keyframeRegionMoveKeyCtx keyframeRegionScaleKeyCtx keyframeRegionSelectKeyCtx keyframeRegionSetKeyCtx keyframeRegionTrackCtx keyframeStats lassoContext lattice latticeDeformKeyCtx launch launchImageEditor layerButton layeredShaderPort layeredTexturePort layout layoutDialog lightList lightListEditor lightListPanel lightlink lineIntersection linearPrecision linstep listAnimatable listAttr listCameras listConnections listDeviceAttachments listHistory listInputDeviceAxes listInputDeviceButtons listInputDevices listMenuAnnotation listNodeTypes listPanelCategories listRelatives listSets listTransforms listUnselected listerEditor loadFluid loadNewShelf loadPlugin loadPluginLanguageResources loadPrefObjects localizedPanelLabel lockNode loft log longNameOf lookThru ls lsThroughFilter lsType lsUI Mayatomr mag makeIdentity makeLive makePaintable makeRoll makeSingleSurface makeTubeOn makebot manipMoveContext manipMoveLimitsCtx manipOptions manipRotateContext manipRotateLimitsCtx manipScaleContext manipScaleLimitsCtx marker match max memory menu menuBarLayout menuEditor menuItem menuItemToShelf menuSet menuSetPref messageLine min minimizeApp mirrorJoint modelCurrentTimeCtx modelEditor modelPanel mouse movIn movOut move moveIKtoFK moveKeyCtx moveVertexAlongDirection multiProfileBirailSurface mute nParticle nameCommand nameField namespace namespaceInfo newPanelItems newton nodeCast nodeIconButton nodeOutliner nodePreset nodeType noise nonLinear normalConstraint normalize nurbsBoolean nurbsCopyUVSet nurbsCube nurbsEditUV nurbsPlane nurbsSelect nurbsSquare nurbsToPoly nurbsToPolygonsPref nurbsToSubdiv nurbsToSubdivPref nurbsUVSet nurbsViewDirectionVector objExists objectCenter objectLayer objectType objectTypeUI obsoleteProc oceanNurbsPreviewPlane offsetCurve offsetCurveOnSurface offsetSurface openGLExtension openMayaPref optionMenu optionMenuGrp optionVar orbit orbitCtx orientConstraint outlinerEditor outlinerPanel overrideModifier paintEffectsDisplay pairBlend palettePort paneLayout panel panelConfiguration panelHistory paramDimContext paramDimension paramLocator parent parentConstraint particle particleExists particleInstancer particleRenderInfo partition pasteKey pathAnimation pause pclose percent performanceOptions pfxstrokes pickWalk picture pixelMove planarSrf plane play playbackOptions playblast plugAttr plugNode pluginInfo pluginResourceUtil pointConstraint pointCurveConstraint pointLight pointMatrixMult pointOnCurve pointOnSurface pointPosition poleVectorConstraint polyAppend polyAppendFacetCtx polyAppendVertex polyAutoProjection polyAverageNormal polyAverageVertex polyBevel polyBlendColor polyBlindData polyBoolOp polyBridgeEdge polyCacheMonitor polyCheck polyChipOff polyClipboard polyCloseBorder polyCollapseEdge polyCollapseFacet polyColorBlindData polyColorDel polyColorPerVertex polyColorSet polyCompare polyCone polyCopyUV polyCrease polyCreaseCtx polyCreateFacet polyCreateFacetCtx polyCube polyCut polyCutCtx polyCylinder polyCylindricalProjection polyDelEdge polyDelFacet polyDelVertex polyDuplicateAndConnect polyDuplicateEdge polyEditUV polyEditUVShell polyEvaluate polyExtrudeEdge polyExtrudeFacet polyExtrudeVertex polyFlipEdge polyFlipUV polyForceUV polyGeoSampler polyHelix polyInfo polyInstallAction polyLayoutUV polyListComponentConversion polyMapCut polyMapDel polyMapSew polyMapSewMove polyMergeEdge polyMergeEdgeCtx polyMergeFacet polyMergeFacetCtx polyMergeUV polyMergeVertex polyMirrorFace polyMoveEdge polyMoveFacet polyMoveFacetUV polyMoveUV polyMoveVertex polyNormal polyNormalPerVertex polyNormalizeUV polyOptUvs polyOptions polyOutput polyPipe polyPlanarProjection polyPlane polyPlatonicSolid polyPoke polyPrimitive polyPrism polyProjection polyPyramid polyQuad polyQueryBlindData polyReduce polySelect polySelectConstraint polySelectConstraintMonitor polySelectCtx polySelectEditCtx polySeparate polySetToFaceNormal polySewEdge polyShortestPathCtx polySmooth polySoftEdge polySphere polySphericalProjection polySplit polySplitCtx polySplitEdge polySplitRing polySplitVertex polyStraightenUVBorder polySubdivideEdge polySubdivideFacet polyToSubdiv polyTorus polyTransfer polyTriangulate polyUVSet polyUnite polyWedgeFace popen popupMenu pose pow preloadRefEd print progressBar progressWindow projFileViewer projectCurve projectTangent projectionContext projectionManip promptDialog propModCtx propMove psdChannelOutliner psdEditTextureFile psdExport psdTextureFile putenv pwd python querySubdiv quit rad_to_deg radial radioButton radioButtonGrp radioCollection radioMenuItemCollection rampColorPort rand randomizeFollicles randstate rangeControl readTake rebuildCurve rebuildSurface recordAttr recordDevice redo reference referenceEdit referenceQuery refineSubdivSelectionList refresh refreshAE registerPluginResource rehash reloadImage removeJoint removeMultiInstance removePanelCategory rename renameAttr renameSelectionList renameUI render renderGlobalsNode renderInfo renderLayerButton renderLayerParent renderLayerPostProcess renderLayerUnparent renderManip renderPartition renderQualityNode renderSettings renderThumbnailUpdate renderWindowEditor renderWindowSelectContext renderer reorder reorderDeformers requires reroot resampleFluid resetAE resetPfxToPolyCamera resetTool resolutionNode retarget reverseCurve reverseSurface revolve rgb_to_hsv rigidBody rigidSolver roll rollCtx rootOf rot rotate rotationInterpolation roundConstantRadius rowColumnLayout rowLayout runTimeCommand runup sampleImage saveAllShelves saveAttrPreset saveFluid saveImage saveInitialState saveMenu savePrefObjects savePrefs saveShelf saveToolSettings scale scaleBrushBrightness scaleComponents scaleConstraint scaleKey scaleKeyCtx sceneEditor sceneUIReplacement scmh scriptCtx scriptEditorInfo scriptJob scriptNode scriptTable scriptToShelf scriptedPanel scriptedPanelType scrollField scrollLayout sculpt searchPathArray seed selLoadSettings select selectContext selectCurveCV selectKey selectKeyCtx selectKeyframeRegionCtx selectMode selectPref selectPriority selectType selectedNodes selectionConnection separator setAttr setAttrEnumResource setAttrMapping setAttrNiceNameResource setConstraintRestPosition setDefaultShadingGroup setDrivenKeyframe setDynamic setEditCtx setEditor setFluidAttr setFocus setInfinity setInputDeviceMapping setKeyCtx setKeyPath setKeyframe setKeyframeBlendshapeTargetWts setMenuMode setNodeNiceNameResource setNodeTypeFlag setParent setParticleAttr setPfxToPolyCamera setPluginResource setProject setStampDensity setStartupMessage setState setToolTo setUITemplate setXformManip sets shadingConnection shadingGeometryRelCtx shadingLightRelCtx shadingNetworkCompare shadingNode shapeCompare shelfButton shelfLayout shelfTabLayout shellField shortNameOf showHelp showHidden showManipCtx showSelectionInTitle showShadingGroupAttrEditor showWindow sign simplify sin singleProfileBirailSurface size sizeBytes skinCluster skinPercent smoothCurve smoothTangentSurface smoothstep snap2to2 snapKey snapMode snapTogetherCtx snapshot soft softMod softModCtx sort sound soundControl source spaceLocator sphere sphrand spotLight spotLightPreviewPort spreadSheetEditor spring sqrt squareSurface srtContext stackTrace startString startsWith stitchAndExplodeShell stitchSurface stitchSurfacePoints strcmp stringArrayCatenate stringArrayContains stringArrayCount stringArrayInsertAtIndex stringArrayIntersector stringArrayRemove stringArrayRemoveAtIndex stringArrayRemoveDuplicates stringArrayRemoveExact stringArrayToString stringToStringArray strip stripPrefixFromName stroke subdAutoProjection subdCleanTopology subdCollapse subdDuplicateAndConnect subdEditUV subdListComponentConversion subdMapCut subdMapSewMove subdMatchTopology subdMirror subdToBlind subdToPoly subdTransferUVsToCache subdiv subdivCrease subdivDisplaySmoothness substitute substituteAllString substituteGeometry substring surface surfaceSampler surfaceShaderList swatchDisplayPort switchTable symbolButton symbolCheckBox sysFile system tabLayout tan tangentConstraint texLatticeDeformContext texManipContext texMoveContext texMoveUVShellContext texRotateContext texScaleContext texSelectContext texSelectShortestPathCtx texSmudgeUVContext texWinToolCtx text textCurves textField textFieldButtonGrp textFieldGrp textManip textScrollList textToShelf textureDisplacePlane textureHairColor texturePlacementContext textureWindow threadCount threePointArcCtx timeControl timePort timerX toNativePath toggle toggleAxis toggleWindowVisibility tokenize tokenizeList tolerance tolower toolButton toolCollection toolDropped toolHasOptions toolPropertyWindow torus toupper trace track trackCtx transferAttributes transformCompare transformLimits translator trim trunc truncateFluidCache truncateHairCache tumble tumbleCtx turbulence twoPointArcCtx uiRes uiTemplate unassignInputDevice undo undoInfo ungroup uniform unit unloadPlugin untangleUV untitledFileName untrim upAxis updateAE userCtx uvLink uvSnapshot validateShelfName vectorize view2dToolCtx viewCamera viewClipPlane viewFit viewHeadOn viewLookAt viewManip viewPlace viewSet visor volumeAxis vortex waitCursor warning webBrowser webBrowserPrefs whatIs window windowPref wire wireContext workspace wrinkle wrinkleContext writeTake xbmLangPathList xform",i:"</",c:[a.CNM,a.ASM,a.QSM,{cN:"string",b:"`",e:"`",c:[a.BE]},{cN:"variable",v:[{b:"\\$\\d"},{b:"[\\$\\%\\@](\\^\\w\\b|#\\w+|[^\\s\\w{]|{\\w+}|\\w+)"},{b:"\\*(\\^\\w\\b|#\\w+|[^\\s\\w{]|{\\w+}|\\w+)",r:0}]},a.CLCM,a.CBLCLM]}});hljs.registerLanguage("objectivec",function(a){var d={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign self synchronized id nonatomic super unichar IBOutlet IBAction strong weak @private @protected @public @try @property @end @throw @catch @finally @synthesize @dynamic @selector @optional @required",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"NSString NSDictionary CGRect CGPoint UIButton UILabel UITextView UIWebView MKMapView UISegmentedControl NSObject UITableViewDelegate UITableViewDataSource NSThread UIActivityIndicator UITabbar UIToolBar UIBarButtonItem UIImageView NSAutoreleasePool UITableView BOOL NSInteger CGFloat NSException NSLog NSMutableString NSMutableArray NSMutableDictionary NSURL NSIndexPath CGSize UITableViewCell UIView UIViewController UINavigationBar UINavigationController UITabBarController UIPopoverController UIPopoverControllerDelegate UIImage NSNumber UISearchBar NSFetchedResultsController NSFetchedResultsChangeType UIScrollView UIScrollViewDelegate UIEdgeInsets UIColor UIFont UIApplication NSNotFound NSNotificationCenter NSNotification UILocalNotification NSBundle NSFileManager NSTimeInterval NSDate NSCalendar NSUserDefaults UIWindow NSRange NSArray NSError NSURLRequest NSURLConnection UIInterfaceOrientation MPMoviePlayerController dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"};var c=/[a-zA-Z@][a-zA-Z0-9_]*/;var b="@interface @class @protocol @implementation";return{k:d,l:c,i:"</",c:[a.CLCM,a.CBLCLM,a.CNM,a.QSM,{cN:"string",b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"},{cN:"preprocessor",b:"#import",e:"$",c:[{cN:"title",b:'"',e:'"'},{cN:"title",b:"<",e:">"}]},{cN:"preprocessor",b:"#",e:"$"},{cN:"class",b:"("+b.split(" ").join("|")+")\\b",e:"({|$)",k:b,l:c,c:[a.UTM]},{cN:"variable",b:"\\."+a.UIR,r:0}]}});hljs.registerLanguage("apache",function(a){var b={cN:"number",b:"[\\$%]\\d+"};return{cI:true,c:[a.HCM,{cN:"tag",b:"</?",e:">"},{cN:"keyword",b:/\w+/,r:0,k:{common:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"sqbracket",b:"\\s\\[",e:"\\]$"},{cN:"cbracket",b:"[\\$%]\\{",e:"\\}",c:["self",b]},b,a.QSM]}}],i:/\S/}});hljs.registerLanguage("livecodeserver",function(a){var e={cN:"variable",b:"\\b[gtps][A-Z]+[A-Za-z0-9_\\-]*\\b|\\$_[A-Z]+",r:0};var b={cN:"comment",e:"$",v:[a.CBLCLM,a.HCM,{b:"--",},{b:"[^:]//",}]};var d=a.inherit(a.TM,{v:[{b:"\\b_*rig[A-Z]+[A-Za-z0-9_\\-]*"},{b:"\\b_[a-z0-9\\-]+"}]});var c=a.inherit(a.TM,{b:"\\b([A-Za-z0-9_\\-]+)\\b"});return{cI:false,k:{keyword:"after byte bytes english the until http forever descending using line real8 with seventh for stdout finally element word fourth before black ninth sixth characters chars stderr uInt1 uInt1s uInt2 uInt2s stdin string lines relative rel any fifth items from middle mid at else of catch then third it file milliseconds seconds second secs sec int1 int1s int4 int4s internet int2 int2s normal text item last long detailed effective uInt4 uInt4s repeat end repeat URL in try into switch to words https token binfile each tenth as ticks tick system real4 by dateItems without char character ascending eighth whole dateTime numeric short first ftp integer abbreviated abbr abbrev private case while if",constant:"SIX TEN FORMFEED NINE ZERO NONE SPACE FOUR FALSE COLON CRLF PI COMMA ENDOFFILE EOF EIGHT FIVE QUOTE EMPTY ONE TRUE RETURN CR LINEFEED RIGHT BACKSLASH NULL SEVEN TAB THREE TWO six ten formfeed nine zero none space four false colon crlf pi comma endoffile eof eight five quote empty one true return cr linefeed right backslash null seven tab three two RIVERSION RISTATE FILE_READ_MODE FILE_WRITE_MODE FILE_WRITE_MODE DIR_WRITE_MODE FILE_READ_UMASK FILE_WRITE_UMASK DIR_READ_UMASK DIR_WRITE_UMASK",operator:"div mod wrap and or bitAnd bitNot bitOr bitXor among not in a an within contains ends with begins the keys of keys",built_in:"put abs acos aliasReference annuity arrayDecode arrayEncode asin atan atan2 average avg base64Decode base64Encode baseConvert binaryDecode binaryEncode byteToNum cachedURL cachedURLs charToNum cipherNames commandNames compound compress constantNames cos date dateFormat decompress directories diskSpace DNSServers exp exp1 exp2 exp10 extents files flushEvents folders format functionNames global globals hasMemory hostAddress hostAddressToName hostName hostNameToAddress isNumber ISOToMac itemOffset keys len length libURLErrorData libUrlFormData libURLftpCommand libURLLastHTTPHeaders libURLLastRHHeaders libUrlMultipartFormAddPart libUrlMultipartFormData libURLVersion lineOffset ln ln1 localNames log log2 log10 longFilePath lower macToISO matchChunk matchText matrixMultiply max md5Digest median merge millisec millisecs millisecond milliseconds min monthNames num number numToByte numToChar offset open openfiles openProcesses openProcessIDs openSockets paramCount param params peerAddress pendingMessages platform processID random randomBytes replaceText result revCreateXMLTree revCreateXMLTreeFromFile revCurrentRecord revCurrentRecordIsFirst revCurrentRecordIsLast revDatabaseColumnCount revDatabaseColumnIsNull revDatabaseColumnLengths revDatabaseColumnNames revDatabaseColumnNamed revDatabaseColumnNumbered revDatabaseColumnTypes revDatabaseConnectResult revDatabaseCursors revDatabaseID revDatabaseTableNames revDatabaseType revDataFromQuery revdb_closeCursor revdb_columnbynumber revdb_columncount revdb_columnisnull revdb_columnlengths revdb_columnnames revdb_columntypes revdb_commit revdb_connect revdb_connections revdb_connectionerr revdb_currentrecord revdb_cursorconnection revdb_cursorerr revdb_cursors revdb_dbtype revdb_disconnect revdb_execute revdb_iseof revdb_isbof revdb_movefirst revdb_movelast revdb_movenext revdb_moveprev revdb_query revdb_querylist revdb_recordcount revdb_rollback revdb_tablenames revGetDatabaseDriverPath revNumberOfRecords revOpenDatabase revOpenDatabases revQueryDatabase revQueryDatabaseBlob revQueryResult revQueryIsAtStart revQueryIsAtEnd revUnixFromMacPath revXMLAttribute revXMLAttributes revXMLAttributeValues revXMLChildContents revXMLChildNames revXMLFirstChild revXMLMatchingNode revXMLNextSibling revXMLNodeContents revXMLNumberOfChildren revXMLParent revXMLPreviousSibling revXMLRootNode revXMLRPC_CreateRequest revXMLRPC_Documents revXMLRPC_Error revXMLRPC_Execute revXMLRPC_GetHost revXMLRPC_GetMethod revXMLRPC_GetParam revXMLText revXMLRPC_GetParamCount revXMLRPC_GetParamNode revXMLRPC_GetParamType revXMLRPC_GetPath revXMLRPC_GetPort revXMLRPC_GetProtocol revXMLRPC_GetRequest revXMLRPC_GetResponse revXMLRPC_GetSocket revXMLTree revXMLTrees revXMLValidateDTD revZipDescribeItem revZipEnumerateItems revZipOpenArchives round sec secs seconds sha1Digest shell shortFilePath sin specialFolderPath sqrt standardDeviation statRound stdDev sum sysError systemVersion tan tempName tick ticks time to toLower toUpper transpose trunc uniDecode uniEncode upper URLDecode URLEncode URLStatus value variableNames version waitDepth weekdayNames wordOffset add breakpoint cancel clear local variable file word line folder directory URL close socket process combine constant convert create new alias folder directory decrypt delete variable word line folder directory URL dispatch divide do encrypt filter get include intersect kill libURLDownloadToFile libURLFollowHttpRedirects libURLftpUpload libURLftpUploadFile libURLresetAll libUrlSetAuthCallback libURLSetCustomHTTPHeaders libUrlSetExpect100 libURLSetFTPListCommand libURLSetFTPMode libURLSetFTPStopTime libURLSetStatusCallback load multiply socket process post seek rel relative read from process rename replace require resetAll revAddXMLNode revAppendXML revCloseCursor revCloseDatabase revCommitDatabase revCopyFile revCopyFolder revCopyXMLNode revDeleteFolder revDeleteXMLNode revDeleteAllXMLTrees revDeleteXMLTree revExecuteSQL revGoURL revInsertXMLNode revMoveFolder revMoveToFirstRecord revMoveToLastRecord revMoveToNextRecord revMoveToPreviousRecord revMoveToRecord revMoveXMLNode revPutIntoXMLNode revRollBackDatabase revSetDatabaseDriverPath revSetXMLAttribute revXMLRPC_AddParam revXMLRPC_DeleteAllDocuments revXMLAddDTD revXMLRPC_Free revXMLRPC_FreeAll revXMLRPC_DeleteDocument revXMLRPC_DeleteParam revXMLRPC_SetHost revXMLRPC_SetMethod revXMLRPC_SetPort revXMLRPC_SetProtocol revXMLRPC_SetSocket revZipAddItemWithData revZipAddItemWithFile revZipAddUncompressedItemWithData revZipAddUncompressedItemWithFile revZipCancel revZipCloseArchive revZipDeleteItem revZipExtractItemToFile revZipExtractItemToVariable revZipSetProgressCallback revZipRenameItem revZipReplaceItemWithData revZipReplaceItemWithFile revZipOpenArchive send set sort split subtract union unload wait write"},c:[e,{cN:"keyword",b:"\\bend\\sif\\b"},{cN:"function",bK:"function",e:"$",c:[e,c,a.ASM,a.QSM,a.BNM,a.CNM,d]},{cN:"function",bK:"end",e:"$",c:[c,d]},{cN:"command",bK:"command on",e:"$",c:[e,c,a.ASM,a.QSM,a.BNM,a.CNM,d]},{cN:"command",bK:"end",e:"$",c:[c,d]},{cN:"preprocessor",b:"<\\?rev|<\\?lc|<\\?livecode",r:10},{cN:"preprocessor",b:"<\\?"},{cN:"preprocessor",b:"\\?>"},b,a.ASM,a.QSM,a.BNM,a.CNM,d],i:";$|^\\[|^="}});hljs.registerLanguage("glsl",function(a){return{k:{keyword:"atomic_uint attribute bool break bvec2 bvec3 bvec4 case centroid coherent const continue default discard dmat2 dmat2x2 dmat2x3 dmat2x4 dmat3 dmat3x2 dmat3x3 dmat3x4 dmat4 dmat4x2 dmat4x3 dmat4x4 do double dvec2 dvec3 dvec4 else flat float for highp if iimage1D iimage1DArray iimage2D iimage2DArray iimage2DMS iimage2DMSArray iimage2DRect iimage3D iimageBuffer iimageCube iimageCubeArray image1D image1DArray image2D image2DArray image2DMS image2DMSArray image2DRect image3D imageBuffer imageCube imageCubeArray in inout int invariant isampler1D isampler1DArray isampler2D isampler2DArray isampler2DMS isampler2DMSArray isampler2DRect isampler3D isamplerBuffer isamplerCube isamplerCubeArray ivec2 ivec3 ivec4 layout lowp mat2 mat2x2 mat2x3 mat2x4 mat3 mat3x2 mat3x3 mat3x4 mat4 mat4x2 mat4x3 mat4x4 mediump noperspective out patch precision readonly restrict return sample sampler1D sampler1DArray sampler1DArrayShadow sampler1DShadow sampler2D sampler2DArray sampler2DArrayShadow sampler2DMS sampler2DMSArray sampler2DRect sampler2DRectShadow sampler2DShadow sampler3D samplerBuffer samplerCube samplerCubeArray samplerCubeArrayShadow samplerCubeShadow smooth struct subroutine switch uimage1D uimage1DArray uimage2D uimage2DArray uimage2DMS uimage2DMSArray uimage2DRect uimage3D uimageBuffer uimageCube uimageCubeArray uint uniform usampler1D usampler1DArray usampler2D usampler2DArray usampler2DMS usampler2DMSArray usampler2DRect usampler3D usamplerBuffer usamplerCube usamplerCubeArray uvec2 uvec3 uvec4 varying vec2 vec3 vec4 void volatile while writeonly",built_in:"gl_BackColor gl_BackLightModelProduct gl_BackLightProduct gl_BackMaterial gl_BackSecondaryColor gl_ClipDistance gl_ClipPlane gl_ClipVertex gl_Color gl_DepthRange gl_EyePlaneQ gl_EyePlaneR gl_EyePlaneS gl_EyePlaneT gl_Fog gl_FogCoord gl_FogFragCoord gl_FragColor gl_FragCoord gl_FragData gl_FragDepth gl_FrontColor gl_FrontFacing gl_FrontLightModelProduct gl_FrontLightProduct gl_FrontMaterial gl_FrontSecondaryColor gl_InstanceID gl_InvocationID gl_Layer gl_LightModel gl_LightSource gl_MaxAtomicCounterBindings gl_MaxAtomicCounterBufferSize gl_MaxClipDistances gl_MaxClipPlanes gl_MaxCombinedAtomicCounterBuffers gl_MaxCombinedAtomicCounters gl_MaxCombinedImageUniforms gl_MaxCombinedImageUnitsAndFragmentOutputs gl_MaxCombinedTextureImageUnits gl_MaxDrawBuffers gl_MaxFragmentAtomicCounterBuffers gl_MaxFragmentAtomicCounters gl_MaxFragmentImageUniforms gl_MaxFragmentInputComponents gl_MaxFragmentUniformComponents gl_MaxFragmentUniformVectors gl_MaxGeometryAtomicCounterBuffers gl_MaxGeometryAtomicCounters gl_MaxGeometryImageUniforms gl_MaxGeometryInputComponents gl_MaxGeometryOutputComponents gl_MaxGeometryOutputVertices gl_MaxGeometryTextureImageUnits gl_MaxGeometryTotalOutputComponents gl_MaxGeometryUniformComponents gl_MaxGeometryVaryingComponents gl_MaxImageSamples gl_MaxImageUnits gl_MaxLights gl_MaxPatchVertices gl_MaxProgramTexelOffset gl_MaxTessControlAtomicCounterBuffers gl_MaxTessControlAtomicCounters gl_MaxTessControlImageUniforms gl_MaxTessControlInputComponents gl_MaxTessControlOutputComponents gl_MaxTessControlTextureImageUnits gl_MaxTessControlTotalOutputComponents gl_MaxTessControlUniformComponents gl_MaxTessEvaluationAtomicCounterBuffers gl_MaxTessEvaluationAtomicCounters gl_MaxTessEvaluationImageUniforms gl_MaxTessEvaluationInputComponents gl_MaxTessEvaluationOutputComponents gl_MaxTessEvaluationTextureImageUnits gl_MaxTessEvaluationUniformComponents gl_MaxTessGenLevel gl_MaxTessPatchComponents gl_MaxTextureCoords gl_MaxTextureImageUnits gl_MaxTextureUnits gl_MaxVaryingComponents gl_MaxVaryingFloats gl_MaxVaryingVectors gl_MaxVertexAtomicCounterBuffers gl_MaxVertexAtomicCounters gl_MaxVertexAttribs gl_MaxVertexImageUniforms gl_MaxVertexOutputComponents gl_MaxVertexTextureImageUnits gl_MaxVertexUniformComponents gl_MaxVertexUniformVectors gl_MaxViewports gl_MinProgramTexelOffsetgl_ModelViewMatrix gl_ModelViewMatrixInverse gl_ModelViewMatrixInverseTranspose gl_ModelViewMatrixTranspose gl_ModelViewProjectionMatrix gl_ModelViewProjectionMatrixInverse gl_ModelViewProjectionMatrixInverseTranspose gl_ModelViewProjectionMatrixTranspose gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 gl_Normal gl_NormalMatrix gl_NormalScale gl_ObjectPlaneQ gl_ObjectPlaneR gl_ObjectPlaneS gl_ObjectPlaneT gl_PatchVerticesIn gl_PerVertex gl_Point gl_PointCoord gl_PointSize gl_Position gl_PrimitiveID gl_PrimitiveIDIn gl_ProjectionMatrix gl_ProjectionMatrixInverse gl_ProjectionMatrixInverseTranspose gl_ProjectionMatrixTranspose gl_SampleID gl_SampleMask gl_SampleMaskIn gl_SamplePosition gl_SecondaryColor gl_TessCoord gl_TessLevelInner gl_TessLevelOuter gl_TexCoord gl_TextureEnvColor gl_TextureMatrixInverseTranspose gl_TextureMatrixTranspose gl_Vertex gl_VertexID gl_ViewportIndex gl_in gl_out EmitStreamVertex EmitVertex EndPrimitive EndStreamPrimitive abs acos acosh all any asin asinh atan atanh atomicCounter atomicCounterDecrement atomicCounterIncrement barrier bitCount bitfieldExtract bitfieldInsert bitfieldReverse ceil clamp cos cosh cross dFdx dFdy degrees determinant distance dot equal exp exp2 faceforward findLSB findMSB floatBitsToInt floatBitsToUint floor fma fract frexp ftransform fwidth greaterThan greaterThanEqual imageAtomicAdd imageAtomicAnd imageAtomicCompSwap imageAtomicExchange imageAtomicMax imageAtomicMin imageAtomicOr imageAtomicXor imageLoad imageStore imulExtended intBitsToFloat interpolateAtCentroid interpolateAtOffset interpolateAtSample inverse inversesqrt isinf isnan ldexp length lessThan lessThanEqual log log2 matrixCompMult max memoryBarrier min mix mod modf noise1 noise2 noise3 noise4 normalize not notEqual outerProduct packDouble2x32 packHalf2x16 packSnorm2x16 packSnorm4x8 packUnorm2x16 packUnorm4x8 pow radians reflect refract round roundEven shadow1D shadow1DLod shadow1DProj shadow1DProjLod shadow2D shadow2DLod shadow2DProj shadow2DProjLod sign sin sinh smoothstep sqrt step tan tanh texelFetch texelFetchOffset texture texture1D texture1DLod texture1DProj texture1DProjLod texture2D texture2DLod texture2DProj texture2DProjLod texture3D texture3DLod texture3DProj texture3DProjLod textureCube textureCubeLod textureGather textureGatherOffset textureGatherOffsets textureGrad textureGradOffset textureLod textureLodOffset textureOffset textureProj textureProjGrad textureProjGradOffset textureProjLod textureProjLodOffset textureProjOffset textureQueryLod textureSize transpose trunc uaddCarry uintBitsToFloat umulExtended unpackDouble2x32 unpackHalf2x16 unpackSnorm2x16 unpackSnorm4x8 unpackUnorm2x16 unpackUnorm4x8 usubBorrow gl_TextureMatrix gl_TextureMatrixInverse",literal:"true false"},i:'"',c:[a.CLCM,a.CBLCLM,a.CNM,{cN:"preprocessor",b:"#",e:"$"}]}});hljs.registerLanguage("lasso",function(d){var b="[a-zA-Z_][a-zA-Z0-9_.]*";var i="<\\?(lasso(script)?|=)";var c="\\]|\\?>";var g={literal:"true false none minimal full all void and or not bw nbw ew new cn ncn lt lte gt gte eq neq rx nrx ft",built_in:"array date decimal duration integer map pair string tag xml null bytes list queue set stack staticarray tie local var variable global data self inherited",keyword:"error_code error_msg error_pop error_push error_reset cache database_names database_schemanames database_tablenames define_tag define_type email_batch encode_set html_comment handle handle_error header if inline iterate ljax_target link link_currentaction link_currentgroup link_currentrecord link_detail link_firstgroup link_firstrecord link_lastgroup link_lastrecord link_nextgroup link_nextrecord link_prevgroup link_prevrecord log loop namespace_using output_none portal private protect records referer referrer repeating resultset rows search_args search_arguments select sort_args sort_arguments thread_atomic value_list while abort case else if_empty if_false if_null if_true loop_abort loop_continue loop_count params params_up return return_value run_children soap_definetag soap_lastrequest soap_lastresponse tag_name ascending average by define descending do equals frozen group handle_failure import in into join let match max min on order parent protected provide public require returnhome skip split_thread sum take thread to trait type where with yield yieldhome"};var a={cN:"comment",b:"<!--",e:"-->",r:0};var j={cN:"preprocessor",b:"\\[noprocess\\]",starts:{cN:"markup",e:"\\[/noprocess\\]",rE:true,c:[a]}};var e={cN:"preprocessor",b:"\\[/noprocess|"+i};var h={cN:"variable",b:"'"+b+"'"};var f=[d.CLCM,{cN:"javadoc",b:"/\\*\\*!",e:"\\*/"},d.CBLCLM,d.inherit(d.CNM,{b:d.CNR+"|-?(infinity|nan)\\b"}),d.inherit(d.ASM,{i:null}),d.inherit(d.QSM,{i:null}),{cN:"string",b:"`",e:"`"},{cN:"variable",v:[{b:"[#$]"+b},{b:"#",e:"\\d+",i:"\\W"}]},{cN:"tag",b:"::\\s*",e:b,i:"\\W"},{cN:"attribute",b:"\\.\\.\\.|-"+d.UIR},{cN:"subst",v:[{b:"->\\s*",c:[h]},{b:":=|/(?!\\w)=?|[-+*%=<>&|!?\\\\]+",r:0}]},{cN:"built_in",b:"\\.\\.?",r:0,c:[h]},{cN:"class",bK:"define",rE:true,e:"\\(|=>",c:[d.inherit(d.TM,{b:d.UIR+"(=(?!>))?"})]}];return{aliases:["ls","lassoscript"],cI:true,l:b+"|&[lg]t;",k:g,c:[{cN:"preprocessor",b:c,r:0,starts:{cN:"markup",e:"\\[|"+i,rE:true,r:0,c:[a]}},j,e,{cN:"preprocessor",b:"\\[no_square_brackets",starts:{e:"\\[/no_square_brackets\\]",l:b+"|&[lg]t;",k:g,c:[{cN:"preprocessor",b:c,r:0,starts:{cN:"markup",e:i,rE:true,c:[a]}},j,e].concat(f)}},{cN:"preprocessor",b:"\\[",r:0},{cN:"shebang",b:"^#!.+lasso9\\b",r:10}].concat(f)}});hljs.registerLanguage("mathematica",function(a){return{aliases:["mma"],l:"(\\$|\\b)"+a.IR+"\\b",k:"AbelianGroup Abort AbortKernels AbortProtect Above Abs Absolute AbsoluteCorrelation AbsoluteCorrelationFunction AbsoluteCurrentValue AbsoluteDashing AbsoluteFileName AbsoluteOptions AbsolutePointSize AbsoluteThickness AbsoluteTime AbsoluteTiming AccountingForm Accumulate Accuracy AccuracyGoal ActionDelay ActionMenu ActionMenuBox ActionMenuBoxOptions Active ActiveItem ActiveStyle AcyclicGraphQ AddOnHelpPath AddTo AdjacencyGraph AdjacencyList AdjacencyMatrix AdjustmentBox AdjustmentBoxOptions AdjustTimeSeriesForecast AffineTransform After AiryAi AiryAiPrime AiryAiZero AiryBi AiryBiPrime AiryBiZero AlgebraicIntegerQ AlgebraicNumber AlgebraicNumberDenominator AlgebraicNumberNorm AlgebraicNumberPolynomial AlgebraicNumberTrace AlgebraicRules AlgebraicRulesData Algebraics AlgebraicUnitQ Alignment AlignmentMarker AlignmentPoint All AllowedDimensions AllowGroupClose AllowInlineCells AllowKernelInitialization AllowReverseGroupClose AllowScriptLevelChange AlphaChannel AlternatingGroup AlternativeHypothesis Alternatives AmbientLight Analytic AnchoredSearch And AndersonDarlingTest AngerJ AngleBracket AngularGauge Animate AnimationCycleOffset AnimationCycleRepetitions AnimationDirection AnimationDisplayTime AnimationRate AnimationRepetitions AnimationRunning Animator AnimatorBox AnimatorBoxOptions AnimatorElements Annotation Annuity AnnuityDue Antialiasing Antisymmetric Apart ApartSquareFree Appearance AppearanceElements AppellF1 Append AppendTo Apply ArcCos ArcCosh ArcCot ArcCoth ArcCsc ArcCsch ArcSec ArcSech ArcSin ArcSinDistribution ArcSinh ArcTan ArcTanh Arg ArgMax ArgMin ArgumentCountQ ARIMAProcess ArithmeticGeometricMean ARMAProcess ARProcess Array ArrayComponents ArrayDepth ArrayFlatten ArrayPad ArrayPlot ArrayQ ArrayReshape ArrayRules Arrays Arrow Arrow3DBox ArrowBox Arrowheads AspectRatio AspectRatioFixed Assert Assuming Assumptions AstronomicalData Asynchronous AsynchronousTaskObject AsynchronousTasks AtomQ Attributes AugmentedSymmetricPolynomial AutoAction AutoDelete AutoEvaluateEvents AutoGeneratedPackage AutoIndent AutoIndentSpacings AutoItalicWords AutoloadPath AutoMatch Automatic AutomaticImageSize AutoMultiplicationSymbol AutoNumberFormatting AutoOpenNotebooks AutoOpenPalettes AutorunSequencing AutoScaling AutoScroll AutoSpacing AutoStyleOptions AutoStyleWords Axes AxesEdge AxesLabel AxesOrigin AxesStyle Axis BabyMonsterGroupB Back Background BackgroundTasksSettings Backslash Backsubstitution Backward Band BandpassFilter BandstopFilter BarabasiAlbertGraphDistribution BarChart BarChart3D BarLegend BarlowProschanImportance BarnesG BarOrigin BarSpacing BartlettHannWindow BartlettWindow BaseForm Baseline BaselinePosition BaseStyle BatesDistribution BattleLemarieWavelet Because BeckmannDistribution Beep Before Begin BeginDialogPacket BeginFrontEndInteractionPacket BeginPackage BellB BellY Below BenfordDistribution BeniniDistribution BenktanderGibratDistribution BenktanderWeibullDistribution BernoulliB BernoulliDistribution BernoulliGraphDistribution BernoulliProcess BernsteinBasis BesselFilterModel BesselI BesselJ BesselJZero BesselK BesselY BesselYZero Beta BetaBinomialDistribution BetaDistribution BetaNegativeBinomialDistribution BetaPrimeDistribution BetaRegularized BetweennessCentrality BezierCurve BezierCurve3DBox BezierCurve3DBoxOptions BezierCurveBox BezierCurveBoxOptions BezierFunction BilateralFilter Binarize BinaryFormat BinaryImageQ BinaryRead BinaryReadList BinaryWrite BinCounts BinLists Binomial BinomialDistribution BinomialProcess BinormalDistribution BiorthogonalSplineWavelet BipartiteGraphQ BirnbaumImportance BirnbaumSaundersDistribution BitAnd BitClear BitGet BitLength BitNot BitOr BitSet BitShiftLeft BitShiftRight BitXor Black BlackmanHarrisWindow BlackmanNuttallWindow BlackmanWindow Blank BlankForm BlankNullSequence BlankSequence Blend Block BlockRandom BlomqvistBeta BlomqvistBetaTest Blue Blur BodePlot BohmanWindow Bold Bookmarks Boole BooleanConsecutiveFunction BooleanConvert BooleanCountingFunction BooleanFunction BooleanGraph BooleanMaxterms BooleanMinimize BooleanMinterms Booleans BooleanTable BooleanVariables BorderDimensions BorelTannerDistribution Bottom BottomHatTransform BoundaryStyle Bounds Box BoxBaselineShift BoxData BoxDimensions Boxed Boxes BoxForm BoxFormFormatTypes BoxFrame BoxID BoxMargins BoxMatrix BoxRatios BoxRotation BoxRotationPoint BoxStyle BoxWhiskerChart Bra BracketingBar BraKet BrayCurtisDistance BreadthFirstScan Break Brown BrownForsytheTest BrownianBridgeProcess BrowserCategory BSplineBasis BSplineCurve BSplineCurve3DBox BSplineCurveBox BSplineCurveBoxOptions BSplineFunction BSplineSurface BSplineSurface3DBox BubbleChart BubbleChart3D BubbleScale BubbleSizes BulletGauge BusinessDayQ ButterflyGraph ButterworthFilterModel Button ButtonBar ButtonBox ButtonBoxOptions ButtonCell ButtonContents ButtonData ButtonEvaluator ButtonExpandable ButtonFrame ButtonFunction ButtonMargins ButtonMinHeight ButtonNote ButtonNotebook ButtonSource ButtonStyle ButtonStyleMenuListing Byte ByteCount ByteOrdering C CachedValue CacheGraphics CalendarData CalendarType CallPacket CanberraDistance Cancel CancelButton CandlestickChart Cap CapForm CapitalDifferentialD CardinalBSplineBasis CarmichaelLambda Cases Cashflow Casoratian Catalan CatalanNumber Catch CauchyDistribution CauchyWindow CayleyGraph CDF CDFDeploy CDFInformation CDFWavelet Ceiling Cell CellAutoOverwrite CellBaseline CellBoundingBox CellBracketOptions CellChangeTimes CellContents CellContext CellDingbat CellDynamicExpression CellEditDuplicate CellElementsBoundingBox CellElementSpacings CellEpilog CellEvaluationDuplicate CellEvaluationFunction CellEventActions CellFrame CellFrameColor CellFrameLabelMargins CellFrameLabels CellFrameMargins CellGroup CellGroupData CellGrouping CellGroupingRules CellHorizontalScrolling CellID CellLabel CellLabelAutoDelete CellLabelMargins CellLabelPositioning CellMargins CellObject CellOpen CellPrint CellProlog Cells CellSize CellStyle CellTags CellularAutomaton CensoredDistribution Censoring Center CenterDot CentralMoment CentralMomentGeneratingFunction CForm ChampernowneNumber ChanVeseBinarize Character CharacterEncoding CharacterEncodingsPath CharacteristicFunction CharacteristicPolynomial CharacterRange Characters ChartBaseStyle ChartElementData ChartElementDataFunction ChartElementFunction ChartElements ChartLabels ChartLayout ChartLegends ChartStyle Chebyshev1FilterModel Chebyshev2FilterModel ChebyshevDistance ChebyshevT ChebyshevU Check CheckAbort CheckAll Checkbox CheckboxBar CheckboxBox CheckboxBoxOptions ChemicalData ChessboardDistance ChiDistribution ChineseRemainder ChiSquareDistribution ChoiceButtons ChoiceDialog CholeskyDecomposition Chop Circle CircleBox CircleDot CircleMinus CirclePlus CircleTimes CirculantGraph CityData Clear ClearAll ClearAttributes ClearSystemCache ClebschGordan ClickPane Clip ClipboardNotebook ClipFill ClippingStyle ClipPlanes ClipRange Clock ClockGauge ClockwiseContourIntegral Close Closed CloseKernels ClosenessCentrality Closing ClosingAutoSave ClosingEvent ClusteringComponents CMYKColor Coarse Coefficient CoefficientArrays CoefficientDomain CoefficientList CoefficientRules CoifletWavelet Collect Colon ColonForm ColorCombine ColorConvert ColorData ColorDataFunction ColorFunction ColorFunctionScaling Colorize ColorNegate ColorOutput ColorProfileData ColorQuantize ColorReplace ColorRules ColorSelectorSettings ColorSeparate ColorSetter ColorSetterBox ColorSetterBoxOptions ColorSlider ColorSpace Column ColumnAlignments ColumnBackgrounds ColumnForm ColumnLines ColumnsEqual ColumnSpacings ColumnWidths CommonDefaultFormatTypes Commonest CommonestFilter CommonUnits CommunityBoundaryStyle CommunityGraphPlot CommunityLabels CommunityRegionStyle CompatibleUnitQ CompilationOptions CompilationTarget Compile Compiled CompiledFunction Complement CompleteGraph CompleteGraphQ CompleteKaryTree CompletionsListPacket Complex Complexes ComplexExpand ComplexInfinity ComplexityFunction ComponentMeasurements ComponentwiseContextMenu Compose ComposeList ComposeSeries Composition CompoundExpression CompoundPoissonDistribution CompoundPoissonProcess CompoundRenewalProcess Compress CompressedData Condition ConditionalExpression Conditioned Cone ConeBox ConfidenceLevel ConfidenceRange ConfidenceTransform ConfigurationPath Congruent Conjugate ConjugateTranspose Conjunction Connect ConnectedComponents ConnectedGraphQ ConnesWindow ConoverTest ConsoleMessage ConsoleMessagePacket ConsolePrint Constant ConstantArray Constants ConstrainedMax ConstrainedMin ContentPadding ContentsBoundingBox ContentSelectable ContentSize Context ContextMenu Contexts ContextToFilename ContextToFileName Continuation Continue ContinuedFraction ContinuedFractionK ContinuousAction ContinuousMarkovProcess ContinuousTimeModelQ ContinuousWaveletData ContinuousWaveletTransform ContourDetect ContourGraphics ContourIntegral ContourLabels ContourLines ContourPlot ContourPlot3D Contours ContourShading ContourSmoothing ContourStyle ContraharmonicMean Control ControlActive ControlAlignment ControllabilityGramian ControllabilityMatrix ControllableDecomposition ControllableModelQ ControllerDuration ControllerInformation ControllerInformationData ControllerLinking ControllerManipulate ControllerMethod ControllerPath ControllerState ControlPlacement ControlsRendering ControlType Convergents ConversionOptions ConversionRules ConvertToBitmapPacket ConvertToPostScript ConvertToPostScriptPacket Convolve ConwayGroupCo1 ConwayGroupCo2 ConwayGroupCo3 CoordinateChartData CoordinatesToolOptions CoordinateTransform CoordinateTransformData CoprimeQ Coproduct CopulaDistribution Copyable CopyDirectory CopyFile CopyTag CopyToClipboard CornerFilter CornerNeighbors Correlation CorrelationDistance CorrelationFunction CorrelationTest Cos Cosh CoshIntegral CosineDistance CosineWindow CosIntegral Cot Coth Count CounterAssignments CounterBox CounterBoxOptions CounterClockwiseContourIntegral CounterEvaluator CounterFunction CounterIncrements CounterStyle CounterStyleMenuListing CountRoots CountryData Covariance CovarianceEstimatorFunction CovarianceFunction CoxianDistribution CoxIngersollRossProcess CoxModel CoxModelFit CramerVonMisesTest CreateArchive CreateDialog CreateDirectory CreateDocument CreateIntermediateDirectories CreatePalette CreatePalettePacket CreateScheduledTask CreateTemporary CreateWindow CriticalityFailureImportance CriticalitySuccessImportance CriticalSection Cross CrossingDetect CrossMatrix Csc Csch CubeRoot Cubics Cuboid CuboidBox Cumulant CumulantGeneratingFunction Cup CupCap Curl CurlyDoubleQuote CurlyQuote CurrentImage CurrentlySpeakingPacket CurrentValue CurvatureFlowFilter CurveClosed Cyan CycleGraph CycleIndexPolynomial Cycles CyclicGroup Cyclotomic Cylinder CylinderBox CylindricalDecomposition D DagumDistribution DamerauLevenshteinDistance DampingFactor Darker Dashed Dashing DataCompression DataDistribution DataRange DataReversed Date DateDelimiters DateDifference DateFunction DateList DateListLogPlot DateListPlot DatePattern DatePlus DateRange DateString DateTicksFormat DaubechiesWavelet DavisDistribution DawsonF DayCount DayCountConvention DayMatchQ DayName DayPlus DayRange DayRound DeBruijnGraph Debug DebugTag Decimal DeclareKnownSymbols DeclarePackage Decompose Decrement DedekindEta Default DefaultAxesStyle DefaultBaseStyle DefaultBoxStyle DefaultButton DefaultColor DefaultControlPlacement DefaultDuplicateCellStyle DefaultDuration DefaultElement DefaultFaceGridsStyle DefaultFieldHintStyle DefaultFont DefaultFontProperties DefaultFormatType DefaultFormatTypeForStyle DefaultFrameStyle DefaultFrameTicksStyle DefaultGridLinesStyle DefaultInlineFormatType DefaultInputFormatType DefaultLabelStyle DefaultMenuStyle DefaultNaturalLanguage DefaultNewCellStyle DefaultNewInlineCellStyle DefaultNotebook DefaultOptions DefaultOutputFormatType DefaultStyle DefaultStyleDefinitions DefaultTextFormatType DefaultTextInlineFormatType DefaultTicksStyle DefaultTooltipStyle DefaultValues Defer DefineExternal DefineInputStreamMethod DefineOutputStreamMethod Definition Degree DegreeCentrality DegreeGraphDistribution DegreeLexicographic DegreeReverseLexicographic Deinitialization Del Deletable Delete DeleteBorderComponents DeleteCases DeleteContents DeleteDirectory DeleteDuplicates DeleteFile DeleteSmallComponents DeleteWithContents DeletionWarning Delimiter DelimiterFlashTime DelimiterMatching Delimiters Denominator DensityGraphics DensityHistogram DensityPlot DependentVariables Deploy Deployed Depth DepthFirstScan Derivative DerivativeFilter DescriptorStateSpace DesignMatrix Det DGaussianWavelet DiacriticalPositioning Diagonal DiagonalMatrix Dialog DialogIndent DialogInput DialogLevel DialogNotebook DialogProlog DialogReturn DialogSymbols Diamond DiamondMatrix DiceDissimilarity DictionaryLookup DifferenceDelta DifferenceOrder DifferenceRoot DifferenceRootReduce Differences DifferentialD DifferentialRoot DifferentialRootReduce DifferentiatorFilter DigitBlock DigitBlockMinimum DigitCharacter DigitCount DigitQ DihedralGroup Dilation Dimensions DiracComb DiracDelta DirectedEdge DirectedEdges DirectedGraph DirectedGraphQ DirectedInfinity Direction Directive Directory DirectoryName DirectoryQ DirectoryStack DirichletCharacter DirichletConvolve DirichletDistribution DirichletL DirichletTransform DirichletWindow DisableConsolePrintPacket DiscreteChirpZTransform DiscreteConvolve DiscreteDelta DiscreteHadamardTransform DiscreteIndicator DiscreteLQEstimatorGains DiscreteLQRegulatorGains DiscreteLyapunovSolve DiscreteMarkovProcess DiscretePlot DiscretePlot3D DiscreteRatio DiscreteRiccatiSolve DiscreteShift DiscreteTimeModelQ DiscreteUniformDistribution DiscreteVariables DiscreteWaveletData DiscreteWaveletPacketTransform DiscreteWaveletTransform Discriminant Disjunction Disk DiskBox DiskMatrix Dispatch DispersionEstimatorFunction Display DisplayAllSteps DisplayEndPacket DisplayFlushImagePacket DisplayForm DisplayFunction DisplayPacket DisplayRules DisplaySetSizePacket DisplayString DisplayTemporary DisplayWith DisplayWithRef DisplayWithVariable DistanceFunction DistanceTransform Distribute Distributed DistributedContexts DistributeDefinitions DistributionChart DistributionDomain DistributionFitTest DistributionParameterAssumptions DistributionParameterQ Dithering Div Divergence Divide DivideBy Dividers Divisible Divisors DivisorSigma DivisorSum DMSList DMSString Do DockedCells DocumentNotebook DominantColors DOSTextFormat Dot DotDashed DotEqual Dotted DoubleBracketingBar DoubleContourIntegral DoubleDownArrow DoubleLeftArrow DoubleLeftRightArrow DoubleLeftTee DoubleLongLeftArrow DoubleLongLeftRightArrow DoubleLongRightArrow DoubleRightArrow DoubleRightTee DoubleUpArrow DoubleUpDownArrow DoubleVerticalBar DoublyInfinite Down DownArrow DownArrowBar DownArrowUpArrow DownLeftRightVector DownLeftTeeVector DownLeftVector DownLeftVectorBar DownRightTeeVector DownRightVector DownRightVectorBar Downsample DownTee DownTeeArrow DownValues DragAndDrop DrawEdges DrawFrontFaces DrawHighlighted Drop DSolve Dt DualLinearProgramming DualSystemsModel DumpGet DumpSave DuplicateFreeQ Dynamic DynamicBox DynamicBoxOptions DynamicEvaluationTimeout DynamicLocation DynamicModule DynamicModuleBox DynamicModuleBoxOptions DynamicModuleParent DynamicModuleValues DynamicName DynamicNamespace DynamicReference DynamicSetting DynamicUpdating DynamicWrapper DynamicWrapperBox DynamicWrapperBoxOptions E EccentricityCentrality EdgeAdd EdgeBetweennessCentrality EdgeCapacity EdgeCapForm EdgeColor EdgeConnectivity EdgeCost EdgeCount EdgeCoverQ EdgeDashing EdgeDelete EdgeDetect EdgeForm EdgeIndex EdgeJoinForm EdgeLabeling EdgeLabels EdgeLabelStyle EdgeList EdgeOpacity EdgeQ EdgeRenderingFunction EdgeRules EdgeShapeFunction EdgeStyle EdgeThickness EdgeWeight Editable EditButtonSettings EditCellTagsSettings EditDistance EffectiveInterest Eigensystem Eigenvalues EigenvectorCentrality Eigenvectors Element ElementData Eliminate EliminationOrder EllipticE EllipticExp EllipticExpPrime EllipticF EllipticFilterModel EllipticK EllipticLog EllipticNomeQ EllipticPi EllipticReducedHalfPeriods EllipticTheta EllipticThetaPrime EmitSound EmphasizeSyntaxErrors EmpiricalDistribution Empty EmptyGraphQ EnableConsolePrintPacket Enabled Encode End EndAdd EndDialogPacket EndFrontEndInteractionPacket EndOfFile EndOfLine EndOfString EndPackage EngineeringForm Enter EnterExpressionPacket EnterTextPacket Entropy EntropyFilter Environment Epilog Equal EqualColumns EqualRows EqualTilde EquatedTo Equilibrium EquirippleFilterKernel Equivalent Erf Erfc Erfi ErlangB ErlangC ErlangDistribution Erosion ErrorBox ErrorBoxOptions ErrorNorm ErrorPacket ErrorsDialogSettings EstimatedDistribution EstimatedProcess EstimatorGains EstimatorRegulator EuclideanDistance EulerE EulerGamma EulerianGraphQ EulerPhi Evaluatable Evaluate Evaluated EvaluatePacket EvaluationCell EvaluationCompletionAction EvaluationElements EvaluationMode EvaluationMonitor EvaluationNotebook EvaluationObject EvaluationOrder Evaluator EvaluatorNames EvenQ EventData EventEvaluator EventHandler EventHandlerTag EventLabels ExactBlackmanWindow ExactNumberQ ExactRootIsolation ExampleData Except ExcludedForms ExcludePods Exclusions ExclusionsStyle Exists Exit ExitDialog Exp Expand ExpandAll ExpandDenominator ExpandFileName ExpandNumerator Expectation ExpectationE ExpectedValue ExpGammaDistribution ExpIntegralE ExpIntegralEi Exponent ExponentFunction ExponentialDistribution ExponentialFamily ExponentialGeneratingFunction ExponentialMovingAverage ExponentialPowerDistribution ExponentPosition ExponentStep Export ExportAutoReplacements ExportPacket ExportString Expression ExpressionCell ExpressionPacket ExpToTrig ExtendedGCD Extension ExtentElementFunction ExtentMarkers ExtentSize ExternalCall ExternalDataCharacterEncoding Extract ExtractArchive ExtremeValueDistribution FaceForm FaceGrids FaceGridsStyle Factor FactorComplete Factorial Factorial2 FactorialMoment FactorialMomentGeneratingFunction FactorialPower FactorInteger FactorList FactorSquareFree FactorSquareFreeList FactorTerms FactorTermsList Fail FailureDistribution False FARIMAProcess FEDisableConsolePrintPacket FeedbackSector FeedbackSectorStyle FeedbackType FEEnableConsolePrintPacket Fibonacci FieldHint FieldHintStyle FieldMasked FieldSize File FileBaseName FileByteCount FileDate FileExistsQ FileExtension FileFormat FileHash FileInformation FileName FileNameDepth FileNameDialogSettings FileNameDrop FileNameJoin FileNames FileNameSetter FileNameSplit FileNameTake FilePrint FileType FilledCurve FilledCurveBox Filling FillingStyle FillingTransform FilterRules FinancialBond FinancialData FinancialDerivative FinancialIndicator Find FindArgMax FindArgMin FindClique FindClusters FindCurvePath FindDistributionParameters FindDivisions FindEdgeCover FindEdgeCut FindEulerianCycle FindFaces FindFile FindFit FindGeneratingFunction FindGeoLocation FindGeometricTransform FindGraphCommunities FindGraphIsomorphism FindGraphPartition FindHamiltonianCycle FindIndependentEdgeSet FindIndependentVertexSet FindInstance FindIntegerNullVector FindKClan FindKClique FindKClub FindKPlex FindLibrary FindLinearRecurrence FindList FindMaximum FindMaximumFlow FindMaxValue FindMinimum FindMinimumCostFlow FindMinimumCut FindMinValue FindPermutation FindPostmanTour FindProcessParameters FindRoot FindSequenceFunction FindSettings FindShortestPath FindShortestTour FindThreshold FindVertexCover FindVertexCut Fine FinishDynamic FiniteAbelianGroupCount FiniteGroupCount FiniteGroupData First FirstPassageTimeDistribution FischerGroupFi22 FischerGroupFi23 FischerGroupFi24Prime FisherHypergeometricDistribution FisherRatioTest FisherZDistribution Fit FitAll FittedModel FixedPoint FixedPointList FlashSelection Flat Flatten FlattenAt FlatTopWindow FlipView Floor FlushPrintOutputPacket Fold FoldList Font FontColor FontFamily FontForm FontName FontOpacity FontPostScriptName FontProperties FontReencoding FontSize FontSlant FontSubstitutions FontTracking FontVariations FontWeight For ForAll Format FormatRules FormatType FormatTypeAutoConvert FormatValues FormBox FormBoxOptions FortranForm Forward ForwardBackward Fourier FourierCoefficient FourierCosCoefficient FourierCosSeries FourierCosTransform FourierDCT FourierDCTFilter FourierDCTMatrix FourierDST FourierDSTMatrix FourierMatrix FourierParameters FourierSequenceTransform FourierSeries FourierSinCoefficient FourierSinSeries FourierSinTransform FourierTransform FourierTrigSeries FractionalBrownianMotionProcess FractionalPart FractionBox FractionBoxOptions FractionLine Frame FrameBox FrameBoxOptions Framed FrameInset FrameLabel Frameless FrameMargins FrameStyle FrameTicks FrameTicksStyle FRatioDistribution FrechetDistribution FreeQ FrequencySamplingFilterKernel FresnelC FresnelS Friday FrobeniusNumber FrobeniusSolve FromCharacterCode FromCoefficientRules FromContinuedFraction FromDate FromDigits FromDMS Front FrontEndDynamicExpression FrontEndEventActions FrontEndExecute FrontEndObject FrontEndResource FrontEndResourceString FrontEndStackSize FrontEndToken FrontEndTokenExecute FrontEndValueCache FrontEndVersion FrontFaceColor FrontFaceOpacity Full FullAxes FullDefinition FullForm FullGraphics FullOptions FullSimplify Function FunctionExpand FunctionInterpolation FunctionSpace FussellVeselyImportance GaborFilter GaborMatrix GaborWavelet GainMargins GainPhaseMargins Gamma GammaDistribution GammaRegularized GapPenalty Gather GatherBy GaugeFaceElementFunction GaugeFaceStyle GaugeFrameElementFunction GaugeFrameSize GaugeFrameStyle GaugeLabels GaugeMarkers GaugeStyle GaussianFilter GaussianIntegers GaussianMatrix GaussianWindow GCD GegenbauerC General GeneralizedLinearModelFit GenerateConditions GeneratedCell GeneratedParameters GeneratingFunction Generic GenericCylindricalDecomposition GenomeData GenomeLookup GeodesicClosing GeodesicDilation GeodesicErosion GeodesicOpening GeoDestination GeodesyData GeoDirection GeoDistance GeoGridPosition GeometricBrownianMotionProcess GeometricDistribution GeometricMean GeometricMeanFilter GeometricTransformation GeometricTransformation3DBox GeometricTransformation3DBoxOptions GeometricTransformationBox GeometricTransformationBoxOptions GeoPosition GeoPositionENU GeoPositionXYZ GeoProjectionData GestureHandler GestureHandlerTag Get GetBoundingBoxSizePacket GetContext GetEnvironment GetFileName GetFrontEndOptionsDataPacket GetLinebreakInformationPacket GetMenusPacket GetPageBreakInformationPacket Glaisher GlobalClusteringCoefficient GlobalPreferences GlobalSession Glow GoldenRatio GompertzMakehamDistribution GoodmanKruskalGamma GoodmanKruskalGammaTest Goto Grad Gradient GradientFilter GradientOrientationFilter Graph GraphAssortativity GraphCenter GraphComplement GraphData GraphDensity GraphDiameter GraphDifference GraphDisjointUnion GraphDistance GraphDistanceMatrix GraphElementData GraphEmbedding GraphHighlight GraphHighlightStyle GraphHub Graphics Graphics3D Graphics3DBox Graphics3DBoxOptions GraphicsArray GraphicsBaseline GraphicsBox GraphicsBoxOptions GraphicsColor GraphicsColumn GraphicsComplex GraphicsComplex3DBox GraphicsComplex3DBoxOptions GraphicsComplexBox GraphicsComplexBoxOptions GraphicsContents GraphicsData GraphicsGrid GraphicsGridBox GraphicsGroup GraphicsGroup3DBox GraphicsGroup3DBoxOptions GraphicsGroupBox GraphicsGroupBoxOptions GraphicsGrouping GraphicsHighlightColor GraphicsRow GraphicsSpacing GraphicsStyle GraphIntersection GraphLayout GraphLinkEfficiency GraphPeriphery GraphPlot GraphPlot3D GraphPower GraphPropertyDistribution GraphQ GraphRadius GraphReciprocity GraphRoot GraphStyle GraphUnion Gray GrayLevel GreatCircleDistance Greater GreaterEqual GreaterEqualLess GreaterFullEqual GreaterGreater GreaterLess GreaterSlantEqual GreaterTilde Green Grid GridBaseline GridBox GridBoxAlignment GridBoxBackground GridBoxDividers GridBoxFrame GridBoxItemSize GridBoxItemStyle GridBoxOptions GridBoxSpacings GridCreationSettings GridDefaultElement GridElementStyleOptions GridFrame GridFrameMargins GridGraph GridLines GridLinesStyle GroebnerBasis GroupActionBase GroupCentralizer GroupElementFromWord GroupElementPosition GroupElementQ GroupElements GroupElementToWord GroupGenerators GroupMultiplicationTable GroupOrbits GroupOrder GroupPageBreakWithin GroupSetwiseStabilizer GroupStabilizer GroupStabilizerChain Gudermannian GumbelDistribution HaarWavelet HadamardMatrix HalfNormalDistribution HamiltonianGraphQ HammingDistance HammingWindow HankelH1 HankelH2 HankelMatrix HannPoissonWindow HannWindow HaradaNortonGroupHN HararyGraph HarmonicMean HarmonicMeanFilter HarmonicNumber Hash HashTable Haversine HazardFunction Head HeadCompose Heads HeavisideLambda HeavisidePi HeavisideTheta HeldGroupHe HeldPart HelpBrowserLookup HelpBrowserNotebook HelpBrowserSettings HermiteDecomposition HermiteH HermitianMatrixQ HessenbergDecomposition Hessian HexadecimalCharacter Hexahedron HexahedronBox HexahedronBoxOptions HiddenSurface HighlightGraph HighlightImage HighpassFilter HigmanSimsGroupHS HilbertFilter HilbertMatrix Histogram Histogram3D HistogramDistribution HistogramList HistogramTransform HistogramTransformInterpolation HitMissTransform HITSCentrality HodgeDual HoeffdingD HoeffdingDTest Hold HoldAll HoldAllComplete HoldComplete HoldFirst HoldForm HoldPattern HoldRest HolidayCalendar HomeDirectory HomePage Horizontal HorizontalForm HorizontalGauge HorizontalScrollPosition HornerForm HotellingTSquareDistribution HoytDistribution HTMLSave Hue HumpDownHump HumpEqual HurwitzLerchPhi HurwitzZeta HyperbolicDistribution HypercubeGraph HyperexponentialDistribution Hyperfactorial Hypergeometric0F1 Hypergeometric0F1Regularized Hypergeometric1F1 Hypergeometric1F1Regularized Hypergeometric2F1 Hypergeometric2F1Regularized HypergeometricDistribution HypergeometricPFQ HypergeometricPFQRegularized HypergeometricU Hyperlink HyperlinkCreationSettings Hyphenation HyphenationOptions HypoexponentialDistribution HypothesisTestData I Identity IdentityMatrix If IgnoreCase Im Image Image3D Image3DSlices ImageAccumulate ImageAdd ImageAdjust ImageAlign ImageApply ImageAspectRatio ImageAssemble ImageCache ImageCacheValid ImageCapture ImageChannels ImageClip ImageColorSpace ImageCompose ImageConvolve ImageCooccurrence ImageCorners ImageCorrelate ImageCorrespondingPoints ImageCrop ImageData ImageDataPacket ImageDeconvolve ImageDemosaic ImageDifference ImageDimensions ImageDistance ImageEffect ImageFeatureTrack ImageFileApply ImageFileFilter ImageFileScan ImageFilter ImageForestingComponents ImageForwardTransformation ImageHistogram ImageKeypoints ImageLevels ImageLines ImageMargins ImageMarkers ImageMeasurements ImageMultiply ImageOffset ImagePad ImagePadding ImagePartition ImagePeriodogram ImagePerspectiveTransformation ImageQ ImageRangeCache ImageReflect ImageRegion ImageResize ImageResolution ImageRotate ImageRotated ImageScaled ImageScan ImageSize ImageSizeAction ImageSizeCache ImageSizeMultipliers ImageSizeRaw ImageSubtract ImageTake ImageTransformation ImageTrim ImageType ImageValue ImageValuePositions Implies Import ImportAutoReplacements ImportString ImprovementImportance In IncidenceGraph IncidenceList IncidenceMatrix IncludeConstantBasis IncludeFileExtension IncludePods IncludeSingularTerm Increment Indent IndentingNewlineSpacings IndentMaxFraction IndependenceTest IndependentEdgeSetQ IndependentUnit IndependentVertexSetQ Indeterminate IndexCreationOptions Indexed IndexGraph IndexTag Inequality InexactNumberQ InexactNumbers Infinity Infix Information Inherited InheritScope Initialization InitializationCell InitializationCellEvaluation InitializationCellWarning InlineCounterAssignments InlineCounterIncrements InlineRules Inner Inpaint Input InputAliases InputAssumptions InputAutoReplacements InputField InputFieldBox InputFieldBoxOptions InputForm InputGrouping InputNamePacket InputNotebook InputPacket InputSettings InputStream InputString InputStringPacket InputToBoxFormPacket Insert InsertionPointObject InsertResults Inset Inset3DBox Inset3DBoxOptions InsetBox InsetBoxOptions Install InstallService InString Integer IntegerDigits IntegerExponent IntegerLength IntegerPart IntegerPartitions IntegerQ Integers IntegerString Integral Integrate Interactive InteractiveTradingChart Interlaced Interleaving InternallyBalancedDecomposition InterpolatingFunction InterpolatingPolynomial Interpolation InterpolationOrder InterpolationPoints InterpolationPrecision Interpretation InterpretationBox InterpretationBoxOptions InterpretationFunction InterpretTemplate InterquartileRange Interrupt InterruptSettings Intersection Interval IntervalIntersection IntervalMemberQ IntervalUnion Inverse InverseBetaRegularized InverseCDF InverseChiSquareDistribution InverseContinuousWaveletTransform InverseDistanceTransform InverseEllipticNomeQ InverseErf InverseErfc InverseFourier InverseFourierCosTransform InverseFourierSequenceTransform InverseFourierSinTransform InverseFourierTransform InverseFunction InverseFunctions InverseGammaDistribution InverseGammaRegularized InverseGaussianDistribution InverseGudermannian InverseHaversine InverseJacobiCD InverseJacobiCN InverseJacobiCS InverseJacobiDC InverseJacobiDN InverseJacobiDS InverseJacobiNC InverseJacobiND InverseJacobiNS InverseJacobiSC InverseJacobiSD InverseJacobiSN InverseLaplaceTransform InversePermutation InverseRadon InverseSeries InverseSurvivalFunction InverseWaveletTransform InverseWeierstrassP InverseZTransform Invisible InvisibleApplication InvisibleTimes IrreduciblePolynomialQ IsolatingInterval IsomorphicGraphQ IsotopeData Italic Item ItemBox ItemBoxOptions ItemSize ItemStyle ItoProcess JaccardDissimilarity JacobiAmplitude Jacobian JacobiCD JacobiCN JacobiCS JacobiDC JacobiDN JacobiDS JacobiNC JacobiND JacobiNS JacobiP JacobiSC JacobiSD JacobiSN JacobiSymbol JacobiZeta JankoGroupJ1 JankoGroupJ2 JankoGroupJ3 JankoGroupJ4 JarqueBeraALMTest JohnsonDistribution Join Joined JoinedCurve JoinedCurveBox JoinForm JordanDecomposition JordanModelDecomposition K KagiChart KaiserBesselWindow KaiserWindow KalmanEstimator KalmanFilter KarhunenLoeveDecomposition KaryTree KatzCentrality KCoreComponents KDistribution KelvinBei KelvinBer KelvinKei KelvinKer KendallTau KendallTauTest KernelExecute KernelMixtureDistribution KernelObject Kernels Ket Khinchin KirchhoffGraph KirchhoffMatrix KleinInvariantJ KnightTourGraph KnotData KnownUnitQ KolmogorovSmirnovTest KroneckerDelta KroneckerModelDecomposition KroneckerProduct KroneckerSymbol KuiperTest KumaraswamyDistribution Kurtosis KuwaharaFilter Label Labeled LabeledSlider LabelingFunction LabelStyle LaguerreL LambdaComponents LambertW LanczosWindow LandauDistribution Language LanguageCategory LaplaceDistribution LaplaceTransform Laplacian LaplacianFilter LaplacianGaussianFilter Large Larger Last Latitude LatitudeLongitude LatticeData LatticeReduce Launch LaunchKernels LayeredGraphPlot LayerSizeFunction LayoutInformation LCM LeafCount LeapYearQ LeastSquares LeastSquaresFilterKernel Left LeftArrow LeftArrowBar LeftArrowRightArrow LeftDownTeeVector LeftDownVector LeftDownVectorBar LeftRightArrow LeftRightVector LeftTee LeftTeeArrow LeftTeeVector LeftTriangle LeftTriangleBar LeftTriangleEqual LeftUpDownVector LeftUpTeeVector LeftUpVector LeftUpVectorBar LeftVector LeftVectorBar LegendAppearance Legended LegendFunction LegendLabel LegendLayout LegendMargins LegendMarkers LegendMarkerSize LegendreP LegendreQ LegendreType Length LengthWhile LerchPhi Less LessEqual LessEqualGreater LessFullEqual LessGreater LessLess LessSlantEqual LessTilde LetterCharacter LetterQ Level LeveneTest LeviCivitaTensor LevyDistribution Lexicographic LibraryFunction LibraryFunctionError LibraryFunctionInformation LibraryFunctionLoad LibraryFunctionUnload LibraryLoad LibraryUnload LicenseID LiftingFilterData LiftingWaveletTransform LightBlue LightBrown LightCyan Lighter LightGray LightGreen Lighting LightingAngle LightMagenta LightOrange LightPink LightPurple LightRed LightSources LightYellow Likelihood Limit LimitsPositioning LimitsPositioningTokens LindleyDistribution Line Line3DBox LinearFilter LinearFractionalTransform LinearModelFit LinearOffsetFunction LinearProgramming LinearRecurrence LinearSolve LinearSolveFunction LineBox LineBreak LinebreakAdjustments LineBreakChart LineBreakWithin LineColor LineForm LineGraph LineIndent LineIndentMaxFraction LineIntegralConvolutionPlot LineIntegralConvolutionScale LineLegend LineOpacity LineSpacing LineWrapParts LinkActivate LinkClose LinkConnect LinkConnectedQ LinkCreate LinkError LinkFlush LinkFunction LinkHost LinkInterrupt LinkLaunch LinkMode LinkObject LinkOpen LinkOptions LinkPatterns LinkProtocol LinkRead LinkReadHeld LinkReadyQ Links LinkWrite LinkWriteHeld LiouvilleLambda List Listable ListAnimate ListContourPlot ListContourPlot3D ListConvolve ListCorrelate ListCurvePathPlot ListDeconvolve ListDensityPlot Listen ListFourierSequenceTransform ListInterpolation ListLineIntegralConvolutionPlot ListLinePlot ListLogLinearPlot ListLogLogPlot ListLogPlot ListPicker ListPickerBox ListPickerBoxBackground ListPickerBoxOptions ListPlay ListPlot ListPlot3D ListPointPlot3D ListPolarPlot ListQ ListStreamDensityPlot ListStreamPlot ListSurfacePlot3D ListVectorDensityPlot ListVectorPlot ListVectorPlot3D ListZTransform Literal LiteralSearch LocalClusteringCoefficient LocalizeVariables LocationEquivalenceTest LocationTest Locator LocatorAutoCreate LocatorBox LocatorBoxOptions LocatorCentering LocatorPane LocatorPaneBox LocatorPaneBoxOptions LocatorRegion Locked Log Log10 Log2 LogBarnesG LogGamma LogGammaDistribution LogicalExpand LogIntegral LogisticDistribution LogitModelFit LogLikelihood LogLinearPlot LogLogisticDistribution LogLogPlot LogMultinormalDistribution LogNormalDistribution LogPlot LogRankTest LogSeriesDistribution LongEqual Longest LongestAscendingSequence LongestCommonSequence LongestCommonSequencePositions LongestCommonSubsequence LongestCommonSubsequencePositions LongestMatch LongForm Longitude LongLeftArrow LongLeftRightArrow LongRightArrow Loopback LoopFreeGraphQ LowerCaseQ LowerLeftArrow LowerRightArrow LowerTriangularize LowpassFilter LQEstimatorGains LQGRegulator LQOutputRegulatorGains LQRegulatorGains LUBackSubstitution LucasL LuccioSamiComponents LUDecomposition LyapunovSolve LyonsGroupLy MachineID MachineName MachineNumberQ MachinePrecision MacintoshSystemPageSetup Magenta Magnification Magnify MainSolve MaintainDynamicCaches Majority MakeBoxes MakeExpression MakeRules MangoldtLambda ManhattanDistance Manipulate Manipulator MannWhitneyTest MantissaExponent Manual Map MapAll MapAt MapIndexed MAProcess MapThread MarcumQ MardiaCombinedTest MardiaKurtosisTest MardiaSkewnessTest MarginalDistribution MarkovProcessProperties Masking MatchingDissimilarity MatchLocalNameQ MatchLocalNames MatchQ Material MathematicaNotation MathieuC MathieuCharacteristicA MathieuCharacteristicB MathieuCharacteristicExponent MathieuCPrime MathieuGroupM11 MathieuGroupM12 MathieuGroupM22 MathieuGroupM23 MathieuGroupM24 MathieuS MathieuSPrime MathMLForm MathMLText Matrices MatrixExp MatrixForm MatrixFunction MatrixLog MatrixPlot MatrixPower MatrixQ MatrixRank Max MaxBend MaxDetect MaxExtraBandwidths MaxExtraConditions MaxFeatures MaxFilter Maximize MaxIterations MaxMemoryUsed MaxMixtureKernels MaxPlotPoints MaxPoints MaxRecursion MaxStableDistribution MaxStepFraction MaxSteps MaxStepSize MaxValue MaxwellDistribution McLaughlinGroupMcL Mean MeanClusteringCoefficient MeanDegreeConnectivity MeanDeviation MeanFilter MeanGraphDistance MeanNeighborDegree MeanShift MeanShiftFilter Median MedianDeviation MedianFilter Medium MeijerG MeixnerDistribution MemberQ MemoryConstrained MemoryInUse Menu MenuAppearance MenuCommandKey MenuEvaluator MenuItem MenuPacket MenuSortingValue MenuStyle MenuView MergeDifferences Mesh MeshFunctions MeshRange MeshShading MeshStyle Message MessageDialog MessageList MessageName MessageOptions MessagePacket Messages MessagesNotebook MetaCharacters MetaInformation Method MethodOptions MexicanHatWavelet MeyerWavelet Min MinDetect MinFilter MinimalPolynomial MinimalStateSpaceModel Minimize Minors MinRecursion MinSize MinStableDistribution Minus MinusPlus MinValue Missing MissingDataMethod MittagLefflerE MixedRadix MixedRadixQuantity MixtureDistribution Mod Modal Mode Modular ModularLambda Module Modulus MoebiusMu Moment Momentary MomentConvert MomentEvaluate MomentGeneratingFunction Monday Monitor MonomialList MonomialOrder MonsterGroupM MorletWavelet MorphologicalBinarize MorphologicalBranchPoints MorphologicalComponents MorphologicalEulerNumber MorphologicalGraph MorphologicalPerimeter MorphologicalTransform Most MouseAnnotation MouseAppearance MouseAppearanceTag MouseButtons Mouseover MousePointerNote MousePosition MovingAverage MovingMedian MoyalDistribution MultiedgeStyle MultilaunchWarning MultiLetterItalics MultiLetterStyle MultilineFunction Multinomial MultinomialDistribution MultinormalDistribution MultiplicativeOrder Multiplicity Multiselection MultivariateHypergeometricDistribution MultivariatePoissonDistribution MultivariateTDistribution N NakagamiDistribution NameQ Names NamespaceBox Nand NArgMax NArgMin NBernoulliB NCache NDSolve NDSolveValue Nearest NearestFunction NeedCurrentFrontEndPackagePacket NeedCurrentFrontEndSymbolsPacket NeedlemanWunschSimilarity Needs Negative NegativeBinomialDistribution NegativeMultinomialDistribution NeighborhoodGraph Nest NestedGreaterGreater NestedLessLess NestedScriptRules NestList NestWhile NestWhileList NevilleThetaC NevilleThetaD NevilleThetaN NevilleThetaS NewPrimitiveStyle NExpectation Next NextPrime NHoldAll NHoldFirst NHoldRest NicholsGridLines NicholsPlot NIntegrate NMaximize NMaxValue NMinimize NMinValue NominalVariables NonAssociative NoncentralBetaDistribution NoncentralChiSquareDistribution NoncentralFRatioDistribution NoncentralStudentTDistribution NonCommutativeMultiply NonConstants None NonlinearModelFit NonlocalMeansFilter NonNegative NonPositive Nor NorlundB Norm Normal NormalDistribution NormalGrouping Normalize NormalizedSquaredEuclideanDistance NormalsFunction NormFunction Not NotCongruent NotCupCap NotDoubleVerticalBar Notebook NotebookApply NotebookAutoSave NotebookClose NotebookConvertSettings NotebookCreate NotebookCreateReturnObject NotebookDefault NotebookDelete NotebookDirectory NotebookDynamicExpression NotebookEvaluate NotebookEventActions NotebookFileName NotebookFind NotebookFindReturnObject NotebookGet NotebookGetLayoutInformationPacket NotebookGetMisspellingsPacket NotebookInformation NotebookInterfaceObject NotebookLocate NotebookObject NotebookOpen NotebookOpenReturnObject NotebookPath NotebookPrint NotebookPut NotebookPutReturnObject NotebookRead NotebookResetGeneratedCells Notebooks NotebookSave NotebookSaveAs NotebookSelection NotebookSetupLayoutInformationPacket NotebooksMenu NotebookWrite NotElement NotEqualTilde NotExists NotGreater NotGreaterEqual NotGreaterFullEqual NotGreaterGreater NotGreaterLess NotGreaterSlantEqual NotGreaterTilde NotHumpDownHump NotHumpEqual NotLeftTriangle NotLeftTriangleBar NotLeftTriangleEqual NotLess NotLessEqual NotLessFullEqual NotLessGreater NotLessLess NotLessSlantEqual NotLessTilde NotNestedGreaterGreater NotNestedLessLess NotPrecedes NotPrecedesEqual NotPrecedesSlantEqual NotPrecedesTilde NotReverseElement NotRightTriangle NotRightTriangleBar NotRightTriangleEqual NotSquareSubset NotSquareSubsetEqual NotSquareSuperset NotSquareSupersetEqual NotSubset NotSubsetEqual NotSucceeds NotSucceedsEqual NotSucceedsSlantEqual NotSucceedsTilde NotSuperset NotSupersetEqual NotTilde NotTildeEqual NotTildeFullEqual NotTildeTilde NotVerticalBar NProbability NProduct NProductFactors NRoots NSolve NSum NSumTerms Null NullRecords NullSpace NullWords Number NumberFieldClassNumber NumberFieldDiscriminant NumberFieldFundamentalUnits NumberFieldIntegralBasis NumberFieldNormRepresentatives NumberFieldRegulator NumberFieldRootsOfUnity NumberFieldSignature NumberForm NumberFormat NumberMarks NumberMultiplier NumberPadding NumberPoint NumberQ NumberSeparator NumberSigns NumberString Numerator NumericFunction NumericQ NuttallWindow NValues NyquistGridLines NyquistPlot O ObservabilityGramian ObservabilityMatrix ObservableDecomposition ObservableModelQ OddQ Off Offset OLEData On ONanGroupON OneIdentity Opacity Open OpenAppend Opener OpenerBox OpenerBoxOptions OpenerView OpenFunctionInspectorPacket Opening OpenRead OpenSpecialOptions OpenTemporary OpenWrite Operate OperatingSystem OptimumFlowData Optional OptionInspectorSettings OptionQ Options OptionsPacket OptionsPattern OptionValue OptionValueBox OptionValueBoxOptions Or Orange Order OrderDistribution OrderedQ Ordering Orderless OrnsteinUhlenbeckProcess Orthogonalize Out Outer OutputAutoOverwrite OutputControllabilityMatrix OutputControllableModelQ OutputForm OutputFormData OutputGrouping OutputMathEditExpression OutputNamePacket OutputResponse OutputSizeLimit OutputStream Over OverBar OverDot Overflow OverHat Overlaps Overlay OverlayBox OverlayBoxOptions Overscript OverscriptBox OverscriptBoxOptions OverTilde OverVector OwenT OwnValues PackingMethod PaddedForm Padding PadeApproximant PadLeft PadRight PageBreakAbove PageBreakBelow PageBreakWithin PageFooterLines PageFooters PageHeaderLines PageHeaders PageHeight PageRankCentrality PageWidth PairedBarChart PairedHistogram PairedSmoothHistogram PairedTTest PairedZTest PaletteNotebook PalettePath Pane PaneBox PaneBoxOptions Panel PanelBox PanelBoxOptions Paneled PaneSelector PaneSelectorBox PaneSelectorBoxOptions PaperWidth ParabolicCylinderD ParagraphIndent ParagraphSpacing ParallelArray ParallelCombine ParallelDo ParallelEvaluate Parallelization Parallelize ParallelMap ParallelNeeds ParallelProduct ParallelSubmit ParallelSum ParallelTable ParallelTry Parameter ParameterEstimator ParameterMixtureDistribution ParameterVariables ParametricFunction ParametricNDSolve ParametricNDSolveValue ParametricPlot ParametricPlot3D ParentConnect ParentDirectory ParentForm Parenthesize ParentList ParetoDistribution Part PartialCorrelationFunction PartialD ParticleData Partition PartitionsP PartitionsQ ParzenWindow PascalDistribution PassEventsDown PassEventsUp Paste PasteBoxFormInlineCells PasteButton Path PathGraph PathGraphQ Pattern PatternSequence PatternTest PauliMatrix PaulWavelet Pause PausedTime PDF PearsonChiSquareTest PearsonCorrelationTest PearsonDistribution PerformanceGoal PeriodicInterpolation Periodogram PeriodogramArray PermutationCycles PermutationCyclesQ PermutationGroup PermutationLength PermutationList PermutationListQ PermutationMax PermutationMin PermutationOrder PermutationPower PermutationProduct PermutationReplace Permutations PermutationSupport Permute PeronaMalikFilter Perpendicular PERTDistribution PetersenGraph PhaseMargins Pi Pick PIDData PIDDerivativeFilter PIDFeedforward PIDTune Piecewise PiecewiseExpand PieChart PieChart3D PillaiTrace PillaiTraceTest Pink Pivoting PixelConstrained PixelValue PixelValuePositions Placed Placeholder PlaceholderReplace Plain PlanarGraphQ Play PlayRange Plot Plot3D Plot3Matrix PlotDivision PlotJoined PlotLabel PlotLayout PlotLegends PlotMarkers PlotPoints PlotRange PlotRangeClipping PlotRangePadding PlotRegion PlotStyle Plus PlusMinus Pochhammer PodStates PodWidth Point Point3DBox PointBox PointFigureChart PointForm PointLegend PointSize PoissonConsulDistribution PoissonDistribution PoissonProcess PoissonWindow PolarAxes PolarAxesOrigin PolarGridLines PolarPlot PolarTicks PoleZeroMarkers PolyaAeppliDistribution PolyGamma Polygon Polygon3DBox Polygon3DBoxOptions PolygonBox PolygonBoxOptions PolygonHoleScale PolygonIntersections PolygonScale PolyhedronData PolyLog PolynomialExtendedGCD PolynomialForm PolynomialGCD PolynomialLCM PolynomialMod PolynomialQ PolynomialQuotient PolynomialQuotientRemainder PolynomialReduce PolynomialRemainder Polynomials PopupMenu PopupMenuBox PopupMenuBoxOptions PopupView PopupWindow Position Positive PositiveDefiniteMatrixQ PossibleZeroQ Postfix PostScript Power PowerDistribution PowerExpand PowerMod PowerModList PowerSpectralDensity PowersRepresentations PowerSymmetricPolynomial Precedence PrecedenceForm Precedes PrecedesEqual PrecedesSlantEqual PrecedesTilde Precision PrecisionGoal PreDecrement PredictionRoot PreemptProtect PreferencesPath Prefix PreIncrement Prepend PrependTo PreserveImageOptions Previous PriceGraphDistribution PrimaryPlaceholder Prime PrimeNu PrimeOmega PrimePi PrimePowerQ PrimeQ Primes PrimeZetaP PrimitiveRoot PrincipalComponents PrincipalValue Print PrintAction PrintForm PrintingCopies PrintingOptions PrintingPageRange PrintingStartingPageNumber PrintingStyleEnvironment PrintPrecision PrintTemporary Prism PrismBox PrismBoxOptions PrivateCellOptions PrivateEvaluationOptions PrivateFontOptions PrivateFrontEndOptions PrivateNotebookOptions PrivatePaths Probability ProbabilityDistribution ProbabilityPlot ProbabilityPr ProbabilityScalePlot ProbitModelFit ProcessEstimator ProcessParameterAssumptions ProcessParameterQ ProcessStateDomain ProcessTimeDomain Product ProductDistribution ProductLog ProgressIndicator ProgressIndicatorBox ProgressIndicatorBoxOptions Projection Prolog PromptForm Properties Property PropertyList PropertyValue Proportion Proportional Protect Protected ProteinData Pruning PseudoInverse Purple Put PutAppend Pyramid PyramidBox PyramidBoxOptions QBinomial QFactorial QGamma QHypergeometricPFQ QPochhammer QPolyGamma QRDecomposition QuadraticIrrationalQ Quantile QuantilePlot Quantity QuantityForm QuantityMagnitude QuantityQ QuantityUnit Quartics QuartileDeviation Quartiles QuartileSkewness QueueingNetworkProcess QueueingProcess QueueProperties Quiet Quit Quotient QuotientRemainder RadialityCentrality RadicalBox RadicalBoxOptions RadioButton RadioButtonBar RadioButtonBox RadioButtonBoxOptions Radon RamanujanTau RamanujanTauL RamanujanTauTheta RamanujanTauZ Random RandomChoice RandomComplex RandomFunction RandomGraph RandomImage RandomInteger RandomPermutation RandomPrime RandomReal RandomSample RandomSeed RandomVariate RandomWalkProcess Range RangeFilter RangeSpecification RankedMax RankedMin Raster Raster3D Raster3DBox Raster3DBoxOptions RasterArray RasterBox RasterBoxOptions Rasterize RasterSize Rational RationalFunctions Rationalize Rationals Ratios Raw RawArray RawBoxes RawData RawMedium RayleighDistribution Re Read ReadList ReadProtected Real RealBlockDiagonalForm RealDigits RealExponent Reals Reap Record RecordLists RecordSeparators Rectangle RectangleBox RectangleBoxOptions RectangleChart RectangleChart3D RecurrenceFilter RecurrenceTable RecurringDigitsForm Red Reduce RefBox ReferenceLineStyle ReferenceMarkers ReferenceMarkerStyle Refine ReflectionMatrix ReflectionTransform Refresh RefreshRate RegionBinarize RegionFunction RegionPlot RegionPlot3D RegularExpression Regularization Reinstall Release ReleaseHold ReliabilityDistribution ReliefImage ReliefPlot Remove RemoveAlphaChannel RemoveAsynchronousTask Removed RemoveInputStreamMethod RemoveOutputStreamMethod RemoveProperty RemoveScheduledTask RenameDirectory RenameFile RenderAll RenderingOptions RenewalProcess RenkoChart Repeated RepeatedNull RepeatedString Replace ReplaceAll ReplaceHeldPart ReplaceImageValue ReplaceList ReplacePart ReplacePixelValue ReplaceRepeated Resampling Rescale RescalingTransform ResetDirectory ResetMenusPacket ResetScheduledTask Residue Resolve Rest Resultant ResumePacket Return ReturnExpressionPacket ReturnInputFormPacket ReturnPacket ReturnTextPacket Reverse ReverseBiorthogonalSplineWavelet ReverseElement ReverseEquilibrium ReverseGraph ReverseUpEquilibrium RevolutionAxis RevolutionPlot3D RGBColor RiccatiSolve RiceDistribution RidgeFilter RiemannR RiemannSiegelTheta RiemannSiegelZ Riffle Right RightArrow RightArrowBar RightArrowLeftArrow RightCosetRepresentative RightDownTeeVector RightDownVector RightDownVectorBar RightTee RightTeeArrow RightTeeVector RightTriangle RightTriangleBar RightTriangleEqual RightUpDownVector RightUpTeeVector RightUpVector RightUpVectorBar RightVector RightVectorBar RiskAchievementImportance RiskReductionImportance RogersTanimotoDissimilarity Root RootApproximant RootIntervals RootLocusPlot RootMeanSquare RootOfUnityQ RootReduce Roots RootSum Rotate RotateLabel RotateLeft RotateRight RotationAction RotationBox RotationBoxOptions RotationMatrix RotationTransform Round RoundImplies RoundingRadius Row RowAlignments RowBackgrounds RowBox RowHeights RowLines RowMinHeight RowReduce RowsEqual RowSpacings RSolve RudvalisGroupRu Rule RuleCondition RuleDelayed RuleForm RulerUnits Run RunScheduledTask RunThrough RuntimeAttributes RuntimeOptions RussellRaoDissimilarity SameQ SameTest SampleDepth SampledSoundFunction SampledSoundList SampleRate SamplingPeriod SARIMAProcess SARMAProcess SatisfiabilityCount SatisfiabilityInstances SatisfiableQ Saturday Save Saveable SaveAutoDelete SaveDefinitions SawtoothWave Scale Scaled ScaleDivisions ScaledMousePosition ScaleOrigin ScalePadding ScaleRanges ScaleRangeStyle ScalingFunctions ScalingMatrix ScalingTransform Scan ScheduledTaskActiveQ ScheduledTaskData ScheduledTaskObject ScheduledTasks SchurDecomposition ScientificForm ScreenRectangle ScreenStyleEnvironment ScriptBaselineShifts ScriptLevel ScriptMinSize ScriptRules ScriptSizeMultipliers Scrollbars ScrollingOptions ScrollPosition Sec Sech SechDistribution SectionGrouping SectorChart SectorChart3D SectorOrigin SectorSpacing SeedRandom Select Selectable SelectComponents SelectedCells SelectedNotebook Selection SelectionAnimate SelectionCell SelectionCellCreateCell SelectionCellDefaultStyle SelectionCellParentStyle SelectionCreateCell SelectionDebuggerTag SelectionDuplicateCell SelectionEvaluate SelectionEvaluateCreateCell SelectionMove SelectionPlaceholder SelectionSetStyle SelectWithContents SelfLoops SelfLoopStyle SemialgebraicComponentInstances SendMail Sequence SequenceAlignment SequenceForm SequenceHold SequenceLimit Series SeriesCoefficient SeriesData SessionTime Set SetAccuracy SetAlphaChannel SetAttributes Setbacks SetBoxFormNamesPacket SetDelayed SetDirectory SetEnvironment SetEvaluationNotebook SetFileDate SetFileLoadingContext SetNotebookStatusLine SetOptions SetOptionsPacket SetPrecision SetProperty SetSelectedNotebook SetSharedFunction SetSharedVariable SetSpeechParametersPacket SetStreamPosition SetSystemOptions Setter SetterBar SetterBox SetterBoxOptions Setting SetValue Shading Shallow ShannonWavelet ShapiroWilkTest Share Sharpen ShearingMatrix ShearingTransform ShenCastanMatrix Short ShortDownArrow Shortest ShortestMatch ShortestPathFunction ShortLeftArrow ShortRightArrow ShortUpArrow Show ShowAutoStyles ShowCellBracket ShowCellLabel ShowCellTags ShowClosedCellArea ShowContents ShowControls ShowCursorTracker ShowGroupOpenCloseIcon ShowGroupOpener ShowInvisibleCharacters ShowPageBreaks ShowPredictiveInterface ShowSelection ShowShortBoxForm ShowSpecialCharacters ShowStringCharacters ShowSyntaxStyles ShrinkingDelay ShrinkWrapBoundingBox SiegelTheta SiegelTukeyTest Sign Signature SignedRankTest SignificanceLevel SignPadding SignTest SimilarityRules SimpleGraph SimpleGraphQ Simplify Sin Sinc SinghMaddalaDistribution SingleEvaluation SingleLetterItalics SingleLetterStyle SingularValueDecomposition SingularValueList SingularValuePlot SingularValues Sinh SinhIntegral SinIntegral SixJSymbol Skeleton SkeletonTransform SkellamDistribution Skewness SkewNormalDistribution Skip SliceDistribution Slider Slider2D Slider2DBox Slider2DBoxOptions SliderBox SliderBoxOptions SlideView Slot SlotSequence Small SmallCircle Smaller SmithDelayCompensator SmithWatermanSimilarity SmoothDensityHistogram SmoothHistogram SmoothHistogram3D SmoothKernelDistribution SocialMediaData Socket SokalSneathDissimilarity Solve SolveAlways SolveDelayed Sort SortBy Sound SoundAndGraphics SoundNote SoundVolume Sow Space SpaceForm Spacer Spacings Span SpanAdjustments SpanCharacterRounding SpanFromAbove SpanFromBoth SpanFromLeft SpanLineThickness SpanMaxSize SpanMinSize SpanningCharacters SpanSymmetric SparseArray SpatialGraphDistribution Speak SpeakTextPacket SpearmanRankTest SpearmanRho Spectrogram SpectrogramArray Specularity SpellingCorrection SpellingDictionaries SpellingDictionariesPath SpellingOptions SpellingSuggestionsPacket Sphere SphereBox SphericalBesselJ SphericalBesselY SphericalHankelH1 SphericalHankelH2 SphericalHarmonicY SphericalPlot3D SphericalRegion SpheroidalEigenvalue SpheroidalJoiningFactor SpheroidalPS SpheroidalPSPrime SpheroidalQS SpheroidalQSPrime SpheroidalRadialFactor SpheroidalS1 SpheroidalS1Prime SpheroidalS2 SpheroidalS2Prime Splice SplicedDistribution SplineClosed SplineDegree SplineKnots SplineWeights Split SplitBy SpokenString Sqrt SqrtBox SqrtBoxOptions Square SquaredEuclideanDistance SquareFreeQ SquareIntersection SquaresR SquareSubset SquareSubsetEqual SquareSuperset SquareSupersetEqual SquareUnion SquareWave StabilityMargins StabilityMarginsStyle StableDistribution Stack StackBegin StackComplete StackInhibit StandardDeviation StandardDeviationFilter StandardForm Standardize StandbyDistribution Star StarGraph StartAsynchronousTask StartingStepSize StartOfLine StartOfString StartScheduledTask StartupSound StateDimensions StateFeedbackGains StateOutputEstimator StateResponse StateSpaceModel StateSpaceRealization StateSpaceTransform StationaryDistribution StationaryWaveletPacketTransform StationaryWaveletTransform StatusArea StatusCentrality StepMonitor StieltjesGamma StirlingS1 StirlingS2 StopAsynchronousTask StopScheduledTask StrataVariables StratonovichProcess StreamColorFunction StreamColorFunctionScaling StreamDensityPlot StreamPlot StreamPoints StreamPosition Streams StreamScale StreamStyle String StringBreak StringByteCount StringCases StringCount StringDrop StringExpression StringForm StringFormat StringFreeQ StringInsert StringJoin StringLength StringMatchQ StringPosition StringQ StringReplace StringReplaceList StringReplacePart StringReverse StringRotateLeft StringRotateRight StringSkeleton StringSplit StringTake StringToStream StringTrim StripBoxes StripOnInput StripWrapperBoxes StrokeForm StructuralImportance StructuredArray StructuredSelection StruveH StruveL Stub StudentTDistribution Style StyleBox StyleBoxAutoDelete StyleBoxOptions StyleData StyleDefinitions StyleForm StyleKeyMapping StyleMenuListing StyleNameDialogSettings StyleNames StylePrint StyleSheetPath Subfactorial Subgraph SubMinus SubPlus SubresultantPolynomialRemainders SubresultantPolynomials Subresultants Subscript SubscriptBox SubscriptBoxOptions Subscripted Subset SubsetEqual Subsets SubStar Subsuperscript SubsuperscriptBox SubsuperscriptBoxOptions Subtract SubtractFrom SubValues Succeeds SucceedsEqual SucceedsSlantEqual SucceedsTilde SuchThat Sum SumConvergence Sunday SuperDagger SuperMinus SuperPlus Superscript SuperscriptBox SuperscriptBoxOptions Superset SupersetEqual SuperStar Surd SurdForm SurfaceColor SurfaceGraphics SurvivalDistribution SurvivalFunction SurvivalModel SurvivalModelFit SuspendPacket SuzukiDistribution SuzukiGroupSuz SwatchLegend Switch Symbol SymbolName SymletWavelet Symmetric SymmetricGroup SymmetricMatrixQ SymmetricPolynomial SymmetricReduction Symmetrize SymmetrizedArray SymmetrizedArrayRules SymmetrizedDependentComponents SymmetrizedIndependentComponents SymmetrizedReplacePart SynchronousInitialization SynchronousUpdating Syntax SyntaxForm SyntaxInformation SyntaxLength SyntaxPacket SyntaxQ SystemDialogInput SystemException SystemHelpPath SystemInformation SystemInformationData SystemOpen SystemOptions SystemsModelDelay SystemsModelDelayApproximate SystemsModelDelete SystemsModelDimensions SystemsModelExtract SystemsModelFeedbackConnect SystemsModelLabels SystemsModelOrder SystemsModelParallelConnect SystemsModelSeriesConnect SystemsModelStateFeedbackConnect SystemStub Tab TabFilling Table TableAlignments TableDepth TableDirections TableForm TableHeadings TableSpacing TableView TableViewBox TabSpacings TabView TabViewBox TabViewBoxOptions TagBox TagBoxNote TagBoxOptions TaggingRules TagSet TagSetDelayed TagStyle TagUnset Take TakeWhile Tally Tan Tanh TargetFunctions TargetUnits TautologyQ TelegraphProcess TemplateBox TemplateBoxOptions TemplateSlotSequence TemporalData Temporary TemporaryVariable TensorContract TensorDimensions TensorExpand TensorProduct TensorQ TensorRank TensorReduce TensorSymmetry TensorTranspose TensorWedge Tetrahedron TetrahedronBox TetrahedronBoxOptions TeXForm TeXSave Text Text3DBox Text3DBoxOptions TextAlignment TextBand TextBoundingBox TextBox TextCell TextClipboardType TextData TextForm TextJustification TextLine TextPacket TextParagraph TextRecognize TextRendering TextStyle Texture TextureCoordinateFunction TextureCoordinateScaling Therefore ThermometerGauge Thick Thickness Thin Thinning ThisLink ThompsonGroupTh Thread ThreeJSymbol Threshold Through Throw Thumbnail Thursday Ticks TicksStyle Tilde TildeEqual TildeFullEqual TildeTilde TimeConstrained TimeConstraint Times TimesBy TimeSeriesForecast TimeSeriesInvertibility TimeUsed TimeValue TimeZone Timing Tiny TitleGrouping TitsGroupT ToBoxes ToCharacterCode ToColor ToContinuousTimeModel ToDate ToDiscreteTimeModel ToeplitzMatrix ToExpression ToFileName Together Toggle ToggleFalse Toggler TogglerBar TogglerBox TogglerBoxOptions ToHeldExpression ToInvertibleTimeSeries TokenWords Tolerance ToLowerCase ToNumberField TooBig Tooltip TooltipBox TooltipBoxOptions TooltipDelay TooltipStyle Top TopHatTransform TopologicalSort ToRadicals ToRules ToString Total TotalHeight TotalVariationFilter TotalWidth TouchscreenAutoZoom TouchscreenControlPlacement ToUpperCase Tr Trace TraceAbove TraceAction TraceBackward TraceDepth TraceDialog TraceForward TraceInternal TraceLevel TraceOff TraceOn TraceOriginal TracePrint TraceScan TrackedSymbols TradingChart TraditionalForm TraditionalFunctionNotation TraditionalNotation TraditionalOrder TransferFunctionCancel TransferFunctionExpand TransferFunctionFactor TransferFunctionModel TransferFunctionPoles TransferFunctionTransform TransferFunctionZeros TransformationFunction TransformationFunctions TransformationMatrix TransformedDistribution TransformedField Translate TranslationTransform TransparentColor Transpose TreeForm TreeGraph TreeGraphQ TreePlot TrendStyle TriangleWave TriangularDistribution Trig TrigExpand TrigFactor TrigFactorList Trigger TrigReduce TrigToExp TrimmedMean True TrueQ TruncatedDistribution TsallisQExponentialDistribution TsallisQGaussianDistribution TTest Tube TubeBezierCurveBox TubeBezierCurveBoxOptions TubeBox TubeBSplineCurveBox TubeBSplineCurveBoxOptions Tuesday TukeyLambdaDistribution TukeyWindow Tuples TuranGraph TuringMachine Transparent UnateQ Uncompress Undefined UnderBar Underflow Underlined Underoverscript UnderoverscriptBox UnderoverscriptBoxOptions Underscript UnderscriptBox UnderscriptBoxOptions UndirectedEdge UndirectedGraph UndirectedGraphQ UndocumentedTestFEParserPacket UndocumentedTestGetSelectionPacket Unequal Unevaluated UniformDistribution UniformGraphDistribution UniformSumDistribution Uninstall Union UnionPlus Unique UnitBox UnitConvert UnitDimensions Unitize UnitRootTest UnitSimplify UnitStep UnitTriangle UnitVector Unprotect UnsameQ UnsavedVariables Unset UnsetShared UntrackedVariables Up UpArrow UpArrowBar UpArrowDownArrow Update UpdateDynamicObjects UpdateDynamicObjectsSynchronous UpdateInterval UpDownArrow UpEquilibrium UpperCaseQ UpperLeftArrow UpperRightArrow UpperTriangularize Upsample UpSet UpSetDelayed UpTee UpTeeArrow UpValues URL URLFetch URLFetchAsynchronous URLSave URLSaveAsynchronous UseGraphicsRange Using UsingFrontEnd V2Get ValidationLength Value ValueBox ValueBoxOptions ValueForm ValueQ ValuesData Variables Variance VarianceEquivalenceTest VarianceEstimatorFunction VarianceGammaDistribution VarianceTest VectorAngle VectorColorFunction VectorColorFunctionScaling VectorDensityPlot VectorGlyphData VectorPlot VectorPlot3D VectorPoints VectorQ Vectors VectorScale VectorStyle Vee Verbatim Verbose VerboseConvertToPostScriptPacket VerifyConvergence VerifySolutions VerifyTestAssumptions Version VersionNumber VertexAdd VertexCapacity VertexColors VertexComponent VertexConnectivity VertexCoordinateRules VertexCoordinates VertexCorrelationSimilarity VertexCosineSimilarity VertexCount VertexCoverQ VertexDataCoordinates VertexDegree VertexDelete VertexDiceSimilarity VertexEccentricity VertexInComponent VertexInDegree VertexIndex VertexJaccardSimilarity VertexLabeling VertexLabels VertexLabelStyle VertexList VertexNormals VertexOutComponent VertexOutDegree VertexQ VertexRenderingFunction VertexReplace VertexShape VertexShapeFunction VertexSize VertexStyle VertexTextureCoordinates VertexWeight Vertical VerticalBar VerticalForm VerticalGauge VerticalSeparator VerticalSlider VerticalTilde ViewAngle ViewCenter ViewMatrix ViewPoint ViewPointSelectorSettings ViewPort ViewRange ViewVector ViewVertical VirtualGroupData Visible VisibleCell VoigtDistribution VonMisesDistribution WaitAll WaitAsynchronousTask WaitNext WaitUntil WakebyDistribution WalleniusHypergeometricDistribution WaringYuleDistribution WatershedComponents WatsonUSquareTest WattsStrogatzGraphDistribution WaveletBestBasis WaveletFilterCoefficients WaveletImagePlot WaveletListPlot WaveletMapIndexed WaveletMatrixPlot WaveletPhi WaveletPsi WaveletScale WaveletScalogram WaveletThreshold WeaklyConnectedComponents WeaklyConnectedGraphQ WeakStationarity WeatherData WeberE Wedge Wednesday WeibullDistribution WeierstrassHalfPeriods WeierstrassInvariants WeierstrassP WeierstrassPPrime WeierstrassSigma WeierstrassZeta WeightedAdjacencyGraph WeightedAdjacencyMatrix WeightedData WeightedGraphQ Weights WelchWindow WheelGraph WhenEvent Which While White Whitespace WhitespaceCharacter WhittakerM WhittakerW WienerFilter WienerProcess WignerD WignerSemicircleDistribution WilksW WilksWTest WindowClickSelect WindowElements WindowFloating WindowFrame WindowFrameElements WindowMargins WindowMovable WindowOpacity WindowSelected WindowSize WindowStatusArea WindowTitle WindowToolbars WindowWidth With WolframAlpha WolframAlphaDate WolframAlphaQuantity WolframAlphaResult Word WordBoundary WordCharacter WordData WordSearch WordSeparators WorkingPrecision Write WriteString Wronskian XMLElement XMLObject Xnor Xor Yellow YuleDissimilarity ZernikeR ZeroSymmetric ZeroTest ZeroWidthTimes Zeta ZetaZero ZipfDistribution ZTest ZTransform $Aborted $ActivationGroupID $ActivationKey $ActivationUserRegistered $AddOnsDirectory $AssertFunction $Assumptions $AsynchronousTask $BaseDirectory $BatchInput $BatchOutput $BoxForms $ByteOrdering $Canceled $CharacterEncoding $CharacterEncodings $CommandLine $CompilationTarget $ConditionHold $ConfiguredKernels $Context $ContextPath $ControlActiveSetting $CreationDate $CurrentLink $DateStringFormat $DefaultFont $DefaultFrontEnd $DefaultImagingDevice $DefaultPath $Display $DisplayFunction $DistributedContexts $DynamicEvaluation $Echo $Epilog $ExportFormats $Failed $FinancialDataSource $FormatType $FrontEnd $FrontEndSession $GeoLocation $HistoryLength $HomeDirectory $HTTPCookies $IgnoreEOF $ImagingDevices $ImportFormats $InitialDirectory $Input $InputFileName $InputStreamMethods $Inspector $InstallationDate $InstallationDirectory $InterfaceEnvironment $IterationLimit $KernelCount $KernelID $Language $LaunchDirectory $LibraryPath $LicenseExpirationDate $LicenseID $LicenseProcesses $LicenseServer $LicenseSubprocesses $LicenseType $Line $Linked $LinkSupported $LoadedFiles $MachineAddresses $MachineDomain $MachineDomains $MachineEpsilon $MachineID $MachineName $MachinePrecision $MachineType $MaxExtraPrecision $MaxLicenseProcesses $MaxLicenseSubprocesses $MaxMachineNumber $MaxNumber $MaxPiecewiseCases $MaxPrecision $MaxRootDegree $MessageGroups $MessageList $MessagePrePrint $Messages $MinMachineNumber $MinNumber $MinorReleaseNumber $MinPrecision $ModuleNumber $NetworkLicense $NewMessage $NewSymbol $Notebooks $NumberMarks $Off $OperatingSystem $Output $OutputForms $OutputSizeLimit $OutputStreamMethods $Packages $ParentLink $ParentProcessID $PasswordFile $PatchLevelID $Path $PathnameSeparator $PerformanceGoal $PipeSupported $Post $Pre $PreferencesDirectory $PrePrint $PreRead $PrintForms $PrintLiteral $ProcessID $ProcessorCount $ProcessorType $ProductInformation $ProgramName $RandomState $RecursionLimit $ReleaseNumber $RootDirectory $ScheduledTask $ScriptCommandLine $SessionID $SetParentLink $SharedFunctions $SharedVariables $SoundDisplay $SoundDisplayFunction $SuppressInputFormHeads $SynchronousEvaluation $SyntaxHandler $System $SystemCharacterEncoding $SystemID $SystemWordLength $TemporaryDirectory $TemporaryPrefix $TextStyle $TimedOut $TimeUnit $TimeZone $TopDirectory $TraceOff $TraceOn $TracePattern $TracePostAction $TracePreAction $Urgent $UserAddOnsDirectory $UserBaseDirectory $UserDocumentsDirectory $UserName $Version $VersionNumber",c:[{cN:"comment",b:/\(\*/,e:/\*\)/},a.ASM,a.QSM,a.CNM,{cN:"list",b:/\{/,e:/\}/,i:/:/}]}});hljs.registerLanguage("tex",function(a){var d={cN:"command",b:"\\\\[a-zA-Zа-ÑÐ-Ñ]+[\\*]?"};var c={cN:"command",b:"\\\\[^a-zA-Zа-ÑÐ-Ñ0-9]"};var b={cN:"special",b:"[{}\\[\\]\\&#~]",r:0};return{c:[{b:"\\\\[a-zA-Zа-ÑÐ-Ñ]+[\\*]? *= *-?\\d*\\.?\\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?",rB:true,c:[d,c,{cN:"number",b:" *=",e:"-?\\d*\\.?\\d+(pt|pc|mm|cm|in|dd|cc|ex|em)?",eB:true}],r:10},d,c,b,{cN:"formula",b:"\\$\\$",e:"\\$\\$",c:[d,c,b],r:0},{cN:"formula",b:"\\$",e:"\\$",c:[d,c,b],r:0},{cN:"comment",b:"%",e:"$",r:0}]}});hljs.registerLanguage("cs",function(b){var a="abstract as base bool break byte case catch char checked const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long new null object operator out override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual volatile void while async await ascending descending from get group into join let orderby partial select set value var where yield";return{k:a,c:[{cN:"comment",b:"///",e:"$",rB:true,c:[{cN:"xmlDocTag",b:"///|<!--|-->"},{cN:"xmlDocTag",b:"</?",e:">"}]},b.CLCM,b.CBLCLM,{cN:"preprocessor",b:"#",e:"$",k:"if else elif endif define undef warning error line region endregion pragma checksum"},{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},b.ASM,b.QSM,b.CNM,{bK:"protected public private internal",e:/[{;=]/,k:a,c:[{bK:"class namespace interface",starts:{c:[b.TM]}},{b:b.IR+"\\s*\\(",rB:true,c:[b.TM]}]}]}});hljs.registerLanguage("css",function(a){var b="[a-zA-Z-][a-zA-Z0-9_-]*";var c={cN:"function",b:b+"\\(",e:"\\)",c:["self",a.NM,a.ASM,a.QSM]};return{cI:true,i:"[=/|']",c:[a.CBLCLM,{cN:"id",b:"\\#[A-Za-z0-9_-]+"},{cN:"class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"attr_selector",b:"\\[",e:"\\]",i:"$"},{cN:"pseudo",b:":(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\\\"\\']+"},{cN:"at_rule",b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{cN:"at_rule",b:"@",e:"[{;]",c:[{cN:"keyword",b:/\S+/},{b:/\s/,eW:true,eE:true,r:0,c:[c,a.ASM,a.QSM,a.NM]}]},{cN:"tag",b:b,r:0},{cN:"rules",b:"{",e:"}",i:"[^\\s]",r:0,c:[a.CBLCLM,{cN:"rule",b:"[^\\s]",rB:true,e:";",eW:true,c:[{cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:true,i:"[^\\s]",starts:{cN:"value",eW:true,eE:true,c:[c,a.NM,a.QSM,a.ASM,a.CBLCLM,{cN:"hexcolor",b:"#[0-9A-Fa-f]+"},{cN:"important",b:"!important"}]}}]}]}]}});hljs.registerLanguage("python",function(a){var f={cN:"prompt",b:/^(>>>|\.\.\.) /};var b={cN:"string",c:[a.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[f],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[f],r:10},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/,},{b:/(b|br)"/,e:/"/,},a.ASM,a.QSM]};var d={cN:"number",r:0,v:[{b:a.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:a.CNR+"[lLjJ]?"}]};var e={cN:"params",b:/\(/,e:/\)/,c:["self",f,d,b]};var c={e:/:/,i:/[${=;\n]/,c:[a.UTM,e]};return{k:{keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},i:/(<\/|->|\?)/,c:[f,d,b,a.HCM,a.inherit(c,{cN:"function",bK:"def",r:10}),a.inherit(c,{cN:"class",bK:"class"}),{cN:"decorator",b:/@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("profile",function(a){return{c:[a.CNM,{cN:"built_in",b:"{",e:"}$",eB:true,eE:true,c:[a.ASM,a.QSM],r:0},{cN:"filename",b:"[a-zA-Z_][\\da-zA-Z_]+\\.[\\da-zA-Z_]{1,3}",e:":",eE:true},{cN:"header",b:"(ncalls|tottime|cumtime)",e:"$",k:"ncalls tottime|10 cumtime|10 filename",r:10},{cN:"summary",b:"function calls",e:"$",c:[a.CNM],r:10},a.ASM,a.QSM,{cN:"function",b:"\\(",e:"\\)$",c:[a.UTM],r:0}]}});hljs.registerLanguage("django",function(a){var b={cN:"filter",b:/\|[A-Za-z]+\:?/,k:"truncatewords removetags linebreaksbr yesno get_digit timesince random striptags filesizeformat escape linebreaks length_is ljust rjust cut urlize fix_ampersands title floatformat capfirst pprint divisibleby add make_list unordered_list urlencode timeuntil urlizetrunc wordcount stringformat linenumbers slice date dictsort dictsortreversed default_if_none pluralize lower join center default truncatewords_html upper length phone2numeric wordwrap time addslashes slugify first escapejs force_escape iriencode last safe safeseq truncatechars localize unlocalize localtime utc timezone",c:[{cN:"argument",b:/"/,e:/"/},{cN:"argument",b:/'/,e:/'/}]};return{cI:true,sL:"xml",subLanguageMode:"continuous",c:[{cN:"template_comment",b:/\{%\s*comment\s*%}/,e:/\{%\s*endcomment\s*%}/},{cN:"template_comment",b:/\{#/,e:/#}/},{cN:"template_tag",b:/\{%/,e:/%}/,k:"comment endcomment load templatetag ifchanged endifchanged if endif firstof for endfor in ifnotequal endifnotequal widthratio extends include spaceless endspaceless regroup by as ifequal endifequal ssi now with cycle url filter endfilter debug block endblock else autoescape endautoescape csrf_token empty elif endwith static trans blocktrans endblocktrans get_static_prefix get_media_prefix plural get_current_language language get_available_languages get_current_language_bidi get_language_info get_language_info_list localize endlocalize localtime endlocaltime timezone endtimezone get_current_timezone verbatim",c:[b]},{cN:"variable",b:/\{\{/,e:/}}/,c:[b]}]}});hljs.registerLanguage("nginx",function(c){var b={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+c.UIR}]};var a={eW:true,l:"[a-z/_]+",k:{built_in:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[c.HCM,{cN:"string",c:[c.BE,b],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{cN:"url",b:"([a-z]+):/",e:"\\s",eW:true,eE:true},{cN:"regexp",c:[c.BE,b],v:[{b:"\\s\\^",e:"\\s|{|;",rE:true},{b:"~\\*?\\s+",e:"\\s|{|;",rE:true},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},b]};return{c:[c.HCM,{b:c.UIR+"\\s",e:";|{",rB:true,c:[c.inherit(c.UTM,{starts:a})],r:0}],i:"[^\\s\\}]"}});hljs.registerLanguage("smalltalk",function(a){var b="[a-z][a-zA-Z0-9_]*";var d={cN:"char",b:"\\$.{1}"};var c={cN:"symbol",b:"#"+a.UIR};return{k:"self super nil true false thisContext",c:[{cN:"comment",b:'"',e:'"'},a.ASM,{cN:"class",b:"\\b[A-Z][A-Za-z0-9_]*",r:0},{cN:"method",b:b+":",r:0},a.CNM,c,d,{cN:"localvars",b:"\\|[ ]*"+b+"([ ]+"+b+")*[ ]*\\|",rB:true,e:/\|/,i:/\S/,c:[{b:"(\\|[ ]*)?"+b}]},{cN:"array",b:"\\#\\(",e:"\\)",c:[a.ASM,d,a.CNM,c]}]}});hljs.registerLanguage("sql",function(a){return{cI:true,i:/[<>]/,c:[{cN:"operator",b:"\\b(begin|end|start|commit|rollback|savepoint|lock|alter|create|drop|rename|call|delete|do|handler|insert|load|replace|select|truncate|update|set|show|pragma|grant|merge)\\b(?!:)",e:";",eW:true,k:{keyword:"all partial global month current_timestamp using go revoke smallint indicator end-exec disconnect zone with character assertion to add current_user usage input local alter match collate real then rollback get read timestamp session_user not integer bit unique day minute desc insert execute like ilike|2 level decimal drop continue isolation found where constraints domain right national some module transaction relative second connect escape close system_user for deferred section cast current sqlstate allocate intersect deallocate numeric public preserve full goto initially asc no key output collation group by union session both last language constraint column of space foreign deferrable prior connection unknown action commit view or first into float year primary cascaded except restrict set references names table outer open select size are rows from prepare distinct leading create only next inner authorization schema corresponding option declare precision immediate else timezone_minute external varying translation true case exception join hour default double scroll value cursor descriptor values dec fetch procedure delete and false int is describe char as at in varchar null trailing any absolute current_time end grant privileges when cross check write current_date pad begin temporary exec time update catalog user sql date on identity timezone_hour natural whenever interval work order cascade diagnostics nchar having left call do handler load replace truncate start lock show pragma exists number trigger if before after each row merge matched database",aggregate:"count sum min max avg"},c:[{cN:"string",b:"'",e:"'",c:[a.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[a.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[a.BE]},a.CNM]},a.CBLCLM,{cN:"comment",b:"--",e:"$"}]}});hljs.registerLanguage("oxygene",function(b){var g="abstract add and array as asc aspect assembly async begin break block by case class concat const copy constructor continue create default delegate desc distinct div do downto dynamic each else empty end ensure enum equals event except exit extension external false final finalize finalizer finally flags for forward from function future global group has if implementation implements implies in index inherited inline interface into invariants is iterator join locked locking loop matching method mod module namespace nested new nil not notify nullable of old on operator or order out override parallel params partial pinned private procedure property protected public queryable raise read readonly record reintroduce remove repeat require result reverse sealed select self sequence set shl shr skip static step soft take then to true try tuple type union unit unsafe until uses using var virtual raises volatile where while with write xor yield await mapped deprecated stdcall cdecl pascal register safecall overload library platform reference packed strict published autoreleasepool selector strong weak unretained";var a={cN:"comment",b:"{",e:"}",r:0};var e={cN:"comment",b:"\\(\\*",e:"\\*\\)",r:10};var c={cN:"string",b:"'",e:"'",c:[{b:"''"}]};var d={cN:"string",b:"(#\\d+)+"};var f={cN:"function",bK:"function constructor destructor procedure method",e:"[:;]",k:"function constructor|10 destructor|10 procedure|10 method|10",c:[b.TM,{cN:"params",b:"\\(",e:"\\)",k:g,c:[c,d]},a,e]};return{cI:true,k:g,i:'("|\\$[G-Zg-z]|\\/\\*|</)',c:[a,e,b.CLCM,c,d,b.NM,f,{cN:"class",b:"=\\bclass\\b",e:"end;",k:g,c:[c,d,a,e,b.CLCM,f]}]}});hljs.registerLanguage("actionscript",function(a){var c="[a-zA-Z_$][a-zA-Z0-9_$]*";var b="([*]|[a-zA-Z_$][a-zA-Z0-9_$]*)";var d={cN:"rest_arg",b:"[.]{3}",e:c,r:10};return{k:{keyword:"as break case catch class const continue default delete do dynamic each else extends final finally for function get if implements import in include instanceof interface internal is namespace native new override package private protected public return set static super switch this throw try typeof use var void while with",literal:"true false null undefined"},c:[a.ASM,a.QSM,a.CLCM,a.CBLCLM,a.CNM,{cN:"package",bK:"package",e:"{",c:[a.TM]},{cN:"class",bK:"class interface",e:"{",c:[{bK:"extends implements"},a.TM]},{cN:"preprocessor",bK:"import include",e:";"},{cN:"function",bK:"function",e:"[{;]",i:"\\S",c:[a.TM,{cN:"params",b:"\\(",e:"\\)",c:[a.ASM,a.QSM,a.CLCM,a.CBLCLM,d]},{cN:"type",b:":",e:b,r:10}]}]}});hljs.registerLanguage("ruleslanguage",function(a){return{k:{keyword:"BILL_PERIOD BILL_START BILL_STOP RS_EFFECTIVE_START RS_EFFECTIVE_STOP RS_JURIS_CODE RS_OPCO_CODE INTDADDATTRIBUTE|5 INTDADDVMSG|5 INTDBLOCKOP|5 INTDBLOCKOPNA|5 INTDCLOSE|5 INTDCOUNT|5 INTDCOUNTSTATUSCODE|5 INTDCREATEMASK|5 INTDCREATEDAYMASK|5 INTDCREATEFACTORMASK|5 INTDCREATEHANDLE|5 INTDCREATEOVERRIDEDAYMASK|5 INTDCREATEOVERRIDEMASK|5 INTDCREATESTATUSCODEMASK|5 INTDCREATETOUPERIOD|5 INTDDELETE|5 INTDDIPTEST|5 INTDEXPORT|5 INTDGETERRORCODE|5 INTDGETERRORMESSAGE|5 INTDISEQUAL|5 INTDJOIN|5 INTDLOAD|5 INTDLOADACTUALCUT|5 INTDLOADDATES|5 INTDLOADHIST|5 INTDLOADLIST|5 INTDLOADLISTDATES|5 INTDLOADLISTENERGY|5 INTDLOADLISTHIST|5 INTDLOADRELATEDCHANNEL|5 INTDLOADSP|5 INTDLOADSTAGING|5 INTDLOADUOM|5 INTDLOADUOMDATES|5 INTDLOADUOMHIST|5 INTDLOADVERSION|5 INTDOPEN|5 INTDREADFIRST|5 INTDREADNEXT|5 INTDRECCOUNT|5 INTDRELEASE|5 INTDREPLACE|5 INTDROLLAVG|5 INTDROLLPEAK|5 INTDSCALAROP|5 INTDSCALE|5 INTDSETATTRIBUTE|5 INTDSETDSTPARTICIPANT|5 INTDSETSTRING|5 INTDSETVALUE|5 INTDSETVALUESTATUS|5 INTDSHIFTSTARTTIME|5 INTDSMOOTH|5 INTDSORT|5 INTDSPIKETEST|5 INTDSUBSET|5 INTDTOU|5 INTDTOURELEASE|5 INTDTOUVALUE|5 INTDUPDATESTATS|5 INTDVALUE|5 STDEV INTDDELETEEX|5 INTDLOADEXACTUAL|5 INTDLOADEXCUT|5 INTDLOADEXDATES|5 INTDLOADEX|5 INTDLOADEXRELATEDCHANNEL|5 INTDSAVEEX|5 MVLOAD|5 MVLOADACCT|5 MVLOADACCTDATES|5 MVLOADACCTHIST|5 MVLOADDATES|5 MVLOADHIST|5 MVLOADLIST|5 MVLOADLISTDATES|5 MVLOADLISTHIST|5 IF FOR NEXT DONE SELECT END CALL ABORT CLEAR CHANNEL FACTOR LIST NUMBER OVERRIDE SET WEEK DISTRIBUTIONNODE ELSE WHEN THEN OTHERWISE IENUM CSV INCLUDE LEAVE RIDER SAVE DELETE NOVALUE SECTION WARN SAVE_UPDATE DETERMINANT LABEL REPORT REVENUE EACH IN FROM TOTAL CHARGE BLOCK AND OR CSV_FILE RATE_CODE AUXILIARY_DEMAND UIDACCOUNT RS BILL_PERIOD_SELECT HOURS_PER_MONTH INTD_ERROR_STOP SEASON_SCHEDULE_NAME ACCOUNTFACTOR ARRAYUPPERBOUND CALLSTOREDPROC GETADOCONNECTION GETCONNECT GETDATASOURCE GETQUALIFIER GETUSERID HASVALUE LISTCOUNT LISTOP LISTUPDATE LISTVALUE PRORATEFACTOR RSPRORATE SETBINPATH SETDBMONITOR WQ_OPEN BILLINGHOURS DATE DATEFROMFLOAT DATETIMEFROMSTRING DATETIMETOSTRING DATETOFLOAT DAY DAYDIFF DAYNAME DBDATETIME HOUR MINUTE MONTH MONTHDIFF MONTHHOURS MONTHNAME ROUNDDATE SAMEWEEKDAYLASTYEAR SECOND WEEKDAY WEEKDIFF YEAR YEARDAY YEARSTR COMPSUM HISTCOUNT HISTMAX HISTMIN HISTMINNZ HISTVALUE MAXNRANGE MAXRANGE MINRANGE COMPIKVA COMPKVA COMPKVARFROMKQKW COMPLF IDATTR FLAG LF2KW LF2KWH MAXKW POWERFACTOR READING2USAGE AVGSEASON MAXSEASON MONTHLYMERGE SEASONVALUE SUMSEASON ACCTREADDATES ACCTTABLELOAD CONFIGADD CONFIGGET CREATEOBJECT CREATEREPORT EMAILCLIENT EXPBLKMDMUSAGE EXPMDMUSAGE EXPORT_USAGE FACTORINEFFECT GETUSERSPECIFIEDSTOP INEFFECT ISHOLIDAY RUNRATE SAVE_PROFILE SETREPORTTITLE USEREXIT WATFORRUNRATE TO TABLE ACOS ASIN ATAN ATAN2 BITAND CEIL COS COSECANT COSH COTANGENT DIVQUOT DIVREM EXP FABS FLOOR FMOD FREPM FREXPN LOG LOG10 MAX MAXN MIN MINNZ MODF POW ROUND ROUND2VALUE ROUNDINT SECANT SIN SINH SQROOT TAN TANH FLOAT2STRING FLOAT2STRINGNC INSTR LEFT LEN LTRIM MID RIGHT RTRIM STRING STRINGNC TOLOWER TOUPPER TRIM NUMDAYS READ_DATE STAGING",built_in:"IDENTIFIER OPTIONS XML_ELEMENT XML_OP XML_ELEMENT_OF DOMDOCCREATE DOMDOCLOADFILE DOMDOCLOADXML DOMDOCSAVEFILE DOMDOCGETROOT DOMDOCADDPI DOMNODEGETNAME DOMNODEGETTYPE DOMNODEGETVALUE DOMNODEGETCHILDCT DOMNODEGETFIRSTCHILD DOMNODEGETSIBLING DOMNODECREATECHILDELEMENT DOMNODESETATTRIBUTE DOMNODEGETCHILDELEMENTCT DOMNODEGETFIRSTCHILDELEMENT DOMNODEGETSIBLINGELEMENT DOMNODEGETATTRIBUTECT DOMNODEGETATTRIBUTEI DOMNODEGETATTRIBUTEBYNAME DOMNODEGETBYNAME"},c:[a.CLCM,a.CBLCLM,a.ASM,a.QSM,a.CNM,{cN:"array",b:"#[a-zA-Z .]+"}]}});hljs.registerLanguage("mizar",function(a){return{k:["environ vocabularies notations constructors definitions registrations theorems schemes requirements","begin end definition registration cluster existence pred func defpred deffunc theorem proof","let take assume then thus hence ex for st holds consider reconsider such that and in provided of as from","be being by means equals implies iff redefine define now not or attr is mode suppose per cases set","thesis contradiction scheme reserve struct","correctness compatibility coherence symmetry assymetry reflexivity irreflexivity","connectedness uniqueness commutativity idempotence involutiveness projectivity"].join(" "),c:[{cN:"comment",b:"::",e:"$"}]}});hljs.registerLanguage("handlebars",function(b){var a="each in with if else unless bindattr action collection debugger log outlet template unbound view yield";return{cI:true,sL:"xml",subLanguageMode:"continuous",c:[{cN:"expression",b:"{{",e:"}}",c:[{cN:"begin-block",b:"#[a-zA-Z- .]+",k:a},{cN:"string",b:'"',e:'"'},{cN:"end-block",b:"\\/[a-zA-Z- .]+",k:a},{cN:"variable",b:"[a-zA-Z-.]+",k:a}]}]}});hljs.registerLanguage("scss",function(a){var c="[a-zA-Z-][a-zA-Z0-9_-]*";var d={cN:"function",b:c+"\\(",e:"\\)",c:["self",a.NM,a.ASM,a.QSM]};var b={cN:"hexcolor",b:"#[0-9A-Fa-f]+"};var e={cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:true,i:"[^\\s]",starts:{cN:"value",eW:true,eE:true,c:[d,b,a.NM,a.QSM,a.ASM,a.CBLCLM,{cN:"important",b:"!important"}]}};return{cI:true,i:"[=/|']",c:[a.CLCM,a.CBLCLM,{cN:"function",b:c+"\\(",e:"\\)",c:["self",a.NM,a.ASM,a.QSM]},{cN:"id",b:"\\#[A-Za-z0-9_-]+",r:0},{cN:"class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"attr_selector",b:"\\[",e:"\\]",i:"$"},{cN:"tag",b:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b",r:0},{cN:"pseudo",b:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)"},{cN:"pseudo",b:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)"},{cN:"attribute",b:"\\b(z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b",i:"[^\\s]"},{cN:"value",b:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{cN:"value",b:":",e:";",c:[b,a.NM,a.QSM,a.ASM,{cN:"important",b:"!important"}]},{cN:"at_rule",b:"@",e:"[{;]",k:"mixin include extend for if else each while charset import debug media page content font-face namespace warn",c:[d,a.QSM,a.ASM,b,a.NM,{cN:"preprocessor",b:"\\s[A-Za-z0-9_.-]+",r:0}]}]}});hljs.registerLanguage("perl",function(c){var d="getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when";var f={cN:"subst",b:"[$@]\\{",e:"\\}",k:d};var g={b:"->{",e:"}"};var a={cN:"variable",v:[{b:/\$\d/},{b:/[\$\%\@\*](\^\w\b|#\w+(\:\:\w+)*|{\w+}|\w+(\:\:\w*)*)/},{b:/[\$\%\@\*][^\s\w{]/,r:0}]};var e={cN:"comment",b:"^(__END__|__DATA__)",e:"\\n$",r:5};var h=[c.BE,f,a];var b=[a,c.HCM,e,{cN:"comment",b:"^\\=\\w",e:"\\=cut",eW:true},g,{cN:"string",c:h,v:[{b:"q[qwxr]?\\s*\\(",e:"\\)",r:5},{b:"q[qwxr]?\\s*\\[",e:"\\]",r:5},{b:"q[qwxr]?\\s*\\{",e:"\\}",r:5},{b:"q[qwxr]?\\s*\\|",e:"\\|",r:5},{b:"q[qwxr]?\\s*\\<",e:"\\>",r:5},{b:"qw\\s+q",e:"q",r:5},{b:"'",e:"'",c:[c.BE]},{b:'"',e:'"'},{b:"`",e:"`",c:[c.BE]},{b:"{\\w+}",c:[],r:0},{b:"-?\\w+\\s*\\=\\>",c:[],r:0}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\/\\/|"+c.RSR+"|\\b(split|return|print|reverse|grep)\\b)\\s*",k:"split return print reverse grep",r:0,c:[c.HCM,e,{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[c.BE],r:0}]},{cN:"sub",bK:"sub",e:"(\\s*\\(.*?\\))?[;{]",r:5},{cN:"operator",b:"-\\w\\b",r:0}];f.c=b;g.c=b;return{k:d,c:b}});hljs.registerLanguage("ini",function(a){return{cI:true,i:/\S/,c:[{cN:"comment",b:";",e:"$"},{cN:"title",b:"^\\[",e:"\\]"},{cN:"setting",b:"^[a-z0-9\\[\\]_-]+[ \\t]*=[ \\t]*",e:"$",c:[{cN:"value",eW:true,k:"on off true false yes no",c:[a.QSM,a.NM],r:0}]}]}});hljs.registerLanguage("erlang",function(i){var c="[a-z'][a-zA-Z0-9_']*";var o="("+c+":"+c+"|"+c+")";var f={keyword:"after and andalso|10 band begin bnot bor bsl bzr bxor case catch cond div end fun let not of orelse|10 query receive rem try when xor",literal:"false true"};var l={cN:"comment",b:"%",e:"$",r:0};var e={cN:"number",b:"\\b(\\d+#[a-fA-F0-9]+|\\d+(\\.\\d+)?([eE][-+]?\\d+)?)",r:0};var g={b:"fun\\s+"+c+"/\\d+"};var n={b:o+"\\(",e:"\\)",rB:true,r:0,c:[{cN:"function_name",b:o,r:0},{b:"\\(",e:"\\)",eW:true,rE:true,r:0}]};var h={cN:"tuple",b:"{",e:"}",r:0};var a={cN:"variable",b:"\\b_([A-Z][A-Za-z0-9_]*)?",r:0};var m={cN:"variable",b:"[A-Z][a-zA-Z0-9_]*",r:0};var b={b:"#"+i.UIR,r:0,rB:true,c:[{cN:"record_name",b:"#"+i.UIR,r:0},{b:"{",e:"}",r:0}]};var k={bK:"fun receive if try case",e:"end",k:f};k.c=[l,g,i.inherit(i.ASM,{cN:""}),k,n,i.QSM,e,h,a,m,b];var j=[l,g,k,n,i.QSM,e,h,a,m,b];n.c[1].c=j;h.c=j;b.c[1].c=j;var d={cN:"params",b:"\\(",e:"\\)",c:j};return{k:f,i:"(</|\\*=|\\+=|-=|/=|/\\*|\\*/|\\(\\*|\\*\\))",c:[{cN:"function",b:"^"+c+"\\s*\\(",e:"->",rB:true,i:"\\(|#|//|/\\*|\\\\|:|;",c:[d,i.inherit(i.TM,{b:c})],starts:{e:";|\\.",k:f,c:j}},l,{cN:"pp",b:"^-",e:"\\.",r:0,eE:true,rB:true,l:"-"+i.IR,k:"-module -record -undef -export -ifdef -ifndef -author -copyright -doc -vsn -import -include -include_lib -compile -define -else -endif -file -behaviour -behavior",c:[d]},e,i.QSM,b,a,m,h]}});hljs.registerLanguage("1c",function(b){var f="[a-zA-Zа-ÑÐ-Я][a-zA-Z0-9_а-ÑÐ-Я]*";var c="возврат дата Ð´Ð»Ñ ÐµÑли и или иначе иначееÑли иÑключение конецеÑли конецпопытки конецпроцедуры конецфункции конеццикла конÑтанта не перейти перем перечиÑление по пока попытка прервать продолжить процедура Ñтрока тогда Ñ„Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ñ†Ð¸ÐºÐ» чиÑло ÑкÑпорт";var e="ansitooem oemtoansi ввеÑтивидÑубконто ввеÑтидату ввеÑтизначение ввеÑтиперечиÑление ввеÑтипериод ввеÑтипланÑчетов ввеÑтиÑтроку ввеÑтичиÑло Ð²Ð¾Ð¿Ñ€Ð¾Ñ Ð²Ð¾ÑÑтановитьзначение врег выбранныйпланÑчетов вызватьиÑключение датагод датамеÑÑц датачиÑло добавитьмеÑÑц завершитьработуÑиÑтемы заголовокÑиÑтемы запиÑьжурналарегиÑтрации запуÑтитьприложение зафикÑироватьтранзакцию значениевÑтроку значениевÑтрокувнутр значениевфайл значениеизÑтроки значениеизÑтрокивнутр значениеизфайла имÑкомпьютера имÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð²Ñ€ÐµÐ¼ÐµÐ½Ð½Ñ‹Ñ…Ñ„Ð°Ð¹Ð»Ð¾Ð² каталогиб ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ñ‹ кодÑимв командаÑиÑтемы конгода конецпериодаби конецраÑÑчитанногопериодаби конецÑтандартногоинтервала конквартала конмеÑÑца коннедели лев лог лог10 Ð¼Ð°ÐºÑ Ð¼Ð°ÐºÑимальноеколичеÑтвоÑубконто мин монопольныйрежим названиеинтерфейÑа названиенабораправ назначитьвид назначитьÑчет найти найтипомеченныенаудаление найтиÑÑылки началопериодаби началоÑтандартногоинтервала начатьтранзакцию начгода начквартала начмеÑÑца начнедели номерднÑгода номерднÑнедели номернеделигода нрег Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ°Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ð¾ÐºÑ€ опиÑаниеошибки оÑновнойжурналраÑчетов оÑновнойпланÑчетов оÑновнойÑзык открытьформу открытьформумодально отменитьтранзакцию очиÑтитьокноÑообщений периодÑÑ‚Ñ€ полноеимÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒÐ²Ñ€ÐµÐ¼Ñта получитьдатута получитьдокументта получитьзначениÑотбора получитьпозициюта получитьпуÑтоезначение получитьта прав праводоÑтупа предупреждение префикÑавтонумерации пуÑтаÑÑтрока пуÑтоезначение рабочаÑдаттьпуÑтоезначение рабочаÑдата разделительÑтраниц разделительÑтрок разм разобратьпозициюдокумента раÑÑчитатьрегиÑтрына раÑÑчитатьрегиÑтрыпо Ñигнал Ñимв ÑимволтабулÑции Ñоздатьобъект Ñокрл Ñокрлп Ñокрп Ñообщить ÑоÑтоÑние Ñохранитьзначение Ñред ÑтатуÑвозврата Ñтрдлина Ñтрзаменить ÑтрколичеÑтвоÑтрок ÑтрполучитьÑтроку ÑтрчиÑловхождений Ñформироватьпозициюдокумента Ñчетпокоду текущаÑдата Ñ‚ÐµÐºÑƒÑ‰ÐµÐµÐ²Ñ€ÐµÐ¼Ñ Ñ‚Ð¸Ð¿Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ñ‚Ð¸Ð¿Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸ÑÑÑ‚Ñ€ удалитьобъекты уÑтановитьтана уÑтановитьтапо фикÑшаблон формат цел шаблон";var a={cN:"dquote",b:'""'};var d={cN:"string",b:'"',e:'"|$',c:[a]};var g={cN:"string",b:"\\|",e:'"|$',c:[a]};return{cI:true,l:f,k:{keyword:c,built_in:e},c:[b.CLCM,b.NM,d,g,{cN:"function",b:"(процедура|функциÑ)",e:"$",l:f,k:"процедура функциÑ",c:[b.inherit(b.TM,{b:f}),{cN:"tail",eW:true,c:[{cN:"params",b:"\\(",e:"\\)",l:f,k:"знач",c:[d,g]},{cN:"export",b:"ÑкÑпорт",eW:true,l:f,k:"ÑкÑпорт",c:[b.CLCM]}]},b.CLCM]},{cN:"preprocessor",b:"#",e:"$"},{cN:"date",b:"'\\d{2}\\.\\d{2}\\.(\\d{2}|\\d{4})'"}]}});hljs.registerLanguage("haskell",function(f){var g={cN:"comment",v:[{b:"--",e:"$"},{b:"{-",e:"-}",c:["self"]}]};var e={cN:"pragma",b:"{-#",e:"#-}"};var b={cN:"preprocessor",b:"^#",e:"$"};var d={cN:"type",b:"\\b[A-Z][\\w']*",r:0};var c={cN:"container",b:"\\(",e:"\\)",i:'"',c:[e,g,b,{cN:"type",b:"\\b[A-Z][\\w]*(\\((\\.\\.|,|\\w+)\\))?"},f.inherit(f.TM,{b:"[_a-z][\\w']*"})]};var a={cN:"container",b:"{",e:"}",c:c.c};return{k:"let in if then else case of where do module import hiding qualified type data newtype deriving class instance as default infix infixl infixr foreign export ccall stdcall cplusplus jvm dotnet safe unsafe family forall mdo proc rec",c:[{cN:"module",b:"\\bmodule\\b",e:"where",k:"module where",c:[c,g],i:"\\W\\.|;"},{cN:"import",b:"\\bimport\\b",e:"$",k:"import|0 qualified as hiding",c:[c,g],i:"\\W\\.|;"},{cN:"class",b:"^(\\s*)?(class|instance)\\b",e:"where",k:"class family instance where",c:[d,c,g]},{cN:"typedef",b:"\\b(data|(new)?type)\\b",e:"$",k:"data family type newtype deriving",c:[e,g,d,c,a]},{cN:"default",bK:"default",e:"$",c:[d,c,g]},{cN:"infix",bK:"infix infixl infixr",e:"$",c:[f.CNM,g]},{cN:"foreign",b:"\\bforeign\\b",e:"$",k:"foreign import export ccall stdcall cplusplus jvm dotnet safe unsafe",c:[d,f.QSM,g]},{cN:"shebang",b:"#!\\/usr\\/bin\\/env runhaskell",e:"$"},e,g,b,f.QSM,f.CNM,d,f.inherit(f.TM,{b:"^[_a-z][\\w']*"}),{b:"->|<-"}]}});hljs.registerLanguage("delphi",function(b){var a="exports register file shl array record property for mod while set ally label uses raise not stored class safecall var interface or private static exit index inherited to else stdcall override shr asm far resourcestring finalization packed virtual out and protected library do xorwrite goto near function end div overload object unit begin string on inline repeat until destructor write message program with read initialization except default nil if case cdecl in downto threadvar of try pascal const external constructor type public then implementation finally published procedure";var e={cN:"comment",v:[{b:/\{/,e:/\}/,r:0},{b:/\(\*/,e:/\*\)/,r:10}]};var c={cN:"string",b:/'/,e:/'/,c:[{b:/''/}]};var d={cN:"string",b:/(#\d+)+/};var f={b:b.IR+"\\s*=\\s*class\\s*\\(",rB:true,c:[b.TM]};var g={cN:"function",bK:"function constructor destructor procedure",e:/[:;]/,k:"function constructor|10 destructor|10 procedure|10",c:[b.TM,{cN:"params",b:/\(/,e:/\)/,k:a,c:[c,d]},e]};return{cI:true,k:a,i:/("|\$[G-Zg-z]|\/\*|<\/)/,c:[e,b.CLCM,c,d,b.NM,f,g]}});hljs.registerLanguage("markdown",function(a){return{c:[{cN:"header",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"blockquote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"`.+?`"},{b:"^( {4}|\t)",e:"$",r:0}]},{cN:"horizontal_rule",b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].+?[\\)\\]]",rB:true,c:[{cN:"link_label",b:"\\[",e:"\\]",eB:true,rE:true,r:0},{cN:"link_url",b:"\\]\\(",e:"\\)",eB:true,eE:true},{cN:"link_reference",b:"\\]\\[",e:"\\]",eB:true,eE:true,}],r:10},{b:"^\\[.+\\]:",e:"$",rB:true,c:[{cN:"link_reference",b:"\\[",e:"\\]",eB:true,eE:true},{cN:"link_url",b:"\\s",e:"$"}]}]}});hljs.registerLanguage("avrasm",function(a){return{cI:true,k:{keyword:"adc add adiw and andi asr bclr bld brbc brbs brcc brcs break breq brge brhc brhs brid brie brlo brlt brmi brne brpl brsh brtc brts brvc brvs bset bst call cbi cbr clc clh cli cln clr cls clt clv clz com cp cpc cpi cpse dec eicall eijmp elpm eor fmul fmuls fmulsu icall ijmp in inc jmp ld ldd ldi lds lpm lsl lsr mov movw mul muls mulsu neg nop or ori out pop push rcall ret reti rjmp rol ror sbc sbr sbrc sbrs sec seh sbi sbci sbic sbis sbiw sei sen ser ses set sev sez sleep spm st std sts sub subi swap tst wdr",built_in:"r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15 r16 r17 r18 r19 r20 r21 r22 r23 r24 r25 r26 r27 r28 r29 r30 r31 x|0 xh xl y|0 yh yl z|0 zh zl ucsr1c udr1 ucsr1a ucsr1b ubrr1l ubrr1h ucsr0c ubrr0h tccr3c tccr3a tccr3b tcnt3h tcnt3l ocr3ah ocr3al ocr3bh ocr3bl ocr3ch ocr3cl icr3h icr3l etimsk etifr tccr1c ocr1ch ocr1cl twcr twdr twar twsr twbr osccal xmcra xmcrb eicra spmcsr spmcr portg ddrg ping portf ddrf sreg sph spl xdiv rampz eicrb eimsk gimsk gicr eifr gifr timsk tifr mcucr mcucsr tccr0 tcnt0 ocr0 assr tccr1a tccr1b tcnt1h tcnt1l ocr1ah ocr1al ocr1bh ocr1bl icr1h icr1l tccr2 tcnt2 ocr2 ocdr wdtcr sfior eearh eearl eedr eecr porta ddra pina portb ddrb pinb portc ddrc pinc portd ddrd pind spdr spsr spcr udr0 ucsr0a ucsr0b ubrr0l acsr admux adcsr adch adcl porte ddre pine pinf"},c:[a.CBLCLM,{cN:"comment",b:";",e:"$",r:0},a.CNM,a.BNM,{cN:"number",b:"\\b(\\$[a-zA-Z0-9]+|0o[0-7]+)"},a.QSM,{cN:"string",b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"},{cN:"label",b:"^[A-Za-z0-9_.$]+:"},{cN:"preprocessor",b:"#",e:"$"},{cN:"preprocessor",b:"\\.[a-zA-Z]+"},{cN:"localvars",b:"@[0-9]+"}]}});hljs.registerLanguage("lisp",function(h){var k="[a-zA-Z_\\-\\+\\*\\/\\<\\=\\>\\&\\#][a-zA-Z0-9_\\-\\+\\*\\/\\<\\=\\>\\&\\#!]*";var l="(\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s)(\\+|\\-)?\\d+)?";var j={cN:"shebang",b:"^#!",e:"$"};var b={cN:"literal",b:"\\b(t{1}|nil)\\b"};var d={cN:"number",v:[{b:l,r:0},{b:"#b[0-1]+(/[0-1]+)?"},{b:"#o[0-7]+(/[0-7]+)?"},{b:"#x[0-9a-f]+(/[0-9a-f]+)?"},{b:"#c\\("+l+" +"+l,e:"\\)"}]};var g=h.inherit(h.QSM,{i:null});var m={cN:"comment",b:";",e:"$"};var f={cN:"variable",b:"\\*",e:"\\*"};var n={cN:"keyword",b:"[:&]"+k};var c={b:"\\(",e:"\\)",c:["self",b,g,d]};var a={cN:"quoted",c:[d,g,f,n,c],v:[{b:"['`]\\(",e:"\\)",},{b:"\\(quote ",e:"\\)",k:{title:"quote"},}]};var i={cN:"list",b:"\\(",e:"\\)"};var e={eW:true,r:0};i.c=[{cN:"title",b:k},e];e.c=[a,i,b,d,g,m,f,n];return{i:/\S/,c:[d,j,b,g,m,a,i]}});hljs.registerLanguage("vbnet",function(a){return{cI:true,k:{keyword:"addhandler addressof alias and andalso aggregate ansi as assembly auto binary by byref byval call case catch class compare const continue custom declare default delegate dim distinct do each equals else elseif end enum erase error event exit explicit finally for friend from function get global goto group handles if implements imports in inherits interface into is isfalse isnot istrue join key let lib like loop me mid mod module mustinherit mustoverride mybase myclass namespace narrowing new next not notinheritable notoverridable of off on operator option optional or order orelse overloads overridable overrides paramarray partial preserve private property protected public raiseevent readonly redim rem removehandler resume return select set shadows shared skip static step stop structure strict sub synclock take text then throw to try unicode until using when where while widening with withevents writeonly xor",built_in:"boolean byte cbool cbyte cchar cdate cdec cdbl char cint clng cobj csbyte cshort csng cstr ctype date decimal directcast double gettype getxmlnamespace iif integer long object sbyte short single string trycast typeof uinteger ulong ushort",literal:"true false nothing"},i:"//|{|}|endif|gosub|variant|wend",c:[a.inherit(a.QSM,{c:[{b:'""'}]}),{cN:"comment",b:"'",e:"$",rB:true,c:[{cN:"xmlDocTag",b:"'''|<!--|-->"},{cN:"xmlDocTag",b:"</?",e:">"},]},a.CNM,{cN:"preprocessor",b:"#",e:"$",k:"if else elseif end region externalsource"},]}});hljs.registerLanguage("axapta",function(a){return{k:"false int abstract private char boolean static null if for true while long throw finally protected final return void enum else break new catch byte super case short default double public try this switch continue reverse firstfast firstonly forupdate nofetch sum avg minof maxof count order group by asc desc index hint like dispaly edit client server ttsbegin ttscommit str real date container anytype common div mod",c:[a.CLCM,a.CBLCLM,a.ASM,a.QSM,a.CNM,{cN:"preprocessor",b:"#",e:"$"},{cN:"class",bK:"class interface",e:"{",i:":",c:[{cN:"inheritance",bK:"extends implements",r:10},a.UTM]}]}});hljs.registerLanguage("ocaml",function(a){return{k:{keyword:"and as assert asr begin class constraint do done downto else end exception external false for fun function functor if in include inherit initializer land lazy let lor lsl lsr lxor match method mod module mutable new object of open or private rec ref sig struct then to true try type val virtual when while with parser value",built_in:"bool char float int list unit array exn option int32 int64 nativeint format4 format6 lazy_t in_channel out_channel string",},i:/\/\//,c:[{cN:"string",b:'"""',e:'"""'},{cN:"comment",b:"\\(\\*",e:"\\*\\)",c:["self"]},{cN:"class",bK:"type",e:"\\(|=|$",c:[a.UTM]},{cN:"annotation",b:"\\[<",e:">\\]"},a.CBLCLM,a.inherit(a.ASM,{i:null}),a.inherit(a.QSM,{i:null}),a.CNM]}});hljs.registerLanguage("erlang-repl",function(a){return{k:{special_functions:"spawn spawn_link self",reserved:"after and andalso|10 band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse|10 query receive rem try when xor"},c:[{cN:"prompt",b:"^[0-9]+> ",r:10},{cN:"comment",b:"%",e:"$"},{cN:"number",b:"\\b(\\d+#[a-fA-F0-9]+|\\d+(\\.\\d+)?([eE][-+]?\\d+)?)",r:0},a.ASM,a.QSM,{cN:"constant",b:"\\?(::)?([A-Z]\\w*(::)?)+"},{cN:"arrow",b:"->"},{cN:"ok",b:"ok"},{cN:"exclamation_mark",b:"!"},{cN:"function_or_atom",b:"(\\b[a-z'][a-zA-Z0-9_']*:[a-z'][a-zA-Z0-9_']*)|(\\b[a-z'][a-zA-Z0-9_']*)",r:0},{cN:"variable",b:"[A-Z][a-zA-Z0-9_']*",r:0}]}});hljs.registerLanguage("vala",function(a){return{k:{keyword:"char uchar unichar int uint long ulong short ushort int8 int16 int32 int64 uint8 uint16 uint32 uint64 float double bool struct enum string void weak unowned owned async signal static abstract interface override while do for foreach else switch case break default return try catch public private protected internal using new this get set const stdout stdin stderr var",built_in:"DBus GLib CCode Gee Object",literal:"false true null"},c:[{cN:"class",bK:"class interface delegate namespace",e:"{",i:"[^,:\\n\\s\\.]",c:[a.UTM]},a.CLCM,a.CBLCLM,{cN:"string",b:'"""',e:'"""',r:5},a.ASM,a.QSM,a.CNM,{cN:"preprocessor",b:"^#",e:"$",r:2},{cN:"constant",b:" [A-Z_]+ ",r:0}]}});hljs.registerLanguage("dos",function(a){return{cI:true,k:{flow:"if else goto for in do call exit not exist errorlevel defined equ neq lss leq gtr geq",keyword:"shift cd dir echo setlocal endlocal set pause copy",stream:"prn nul lpt3 lpt2 lpt1 con com4 com3 com2 com1 aux",winutils:"ping net ipconfig taskkill xcopy ren del"},c:[{cN:"envvar",b:"%%[^ ]"},{cN:"envvar",b:"%[^ ]+?%"},{cN:"envvar",b:"![^ ]+?!"},{cN:"number",b:"\\b\\d+",r:0},{cN:"comment",b:"@?rem",e:"$"}]}});hljs.registerLanguage("clojure",function(l){var e={built_in:"def cond apply if-not if-let if not not= = &lt; < > &lt;= <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize"};var f="[a-zA-Z_0-9\\!\\.\\?\\-\\+\\*\\/\\<\\=\\>\\&\\#\\$';]+";var a="[\\s:\\(\\{]+\\d+(\\.\\d+)?";var d={cN:"number",b:a,r:0};var j=l.inherit(l.QSM,{i:null});var o={cN:"comment",b:";",e:"$",r:0};var n={cN:"collection",b:"[\\[\\{]",e:"[\\]\\}]"};var c={cN:"comment",b:"\\^"+f};var b={cN:"comment",b:"\\^\\{",e:"\\}"};var h={cN:"attribute",b:"[:]"+f};var m={cN:"list",b:"\\(",e:"\\)"};var g={eW:true,k:{literal:"true false nil"},r:0};var i={k:e,l:f,cN:"title",b:f,starts:g};m.c=[{cN:"comment",b:"comment"},i,g];g.c=[m,j,c,b,o,h,n,d];n.c=[m,j,c,o,h,n,d];return{i:/\S/,c:[o,m,{cN:"prompt",b:/^=> /,starts:{e:/\n\n|\Z/}}]}});hljs.registerLanguage("go",function(a){var b={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer",constant:"true false iota nil",typename:"bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};return{aliases:["golang"],k:b,i:"</",c:[a.CLCM,a.CBLCLM,a.QSM,{cN:"string",b:"'",e:"[^\\\\]'"},{cN:"string",b:"`",e:"`"},{cN:"number",b:"[^a-zA-Z_0-9](\\-|\\+)?\\d+(\\.\\d+|\\/\\d+)?((d|e|f|l|s)(\\+|\\-)?\\d+)?",r:0},a.CNM]}});hljs.registerLanguage("json",function(a){var e={literal:"true false null"};var d=[a.QSM,a.CNM];var c={cN:"value",e:",",eW:true,eE:true,c:d,k:e};var b={b:"{",e:"}",c:[{cN:"attribute",b:'\\s*"',e:'"\\s*:\\s*',eB:true,eE:true,c:[a.BE],i:"\\n",starts:c}],i:"\\S"};var f={b:"\\[",e:"\\]",c:[a.inherit(c,{cN:null})],i:"\\S"};d.splice(d.length,0,b,f);return{c:d,k:e,i:"\\S"}});hljs.registerLanguage("rust",function(b){var c={cN:"number",b:"\\b(0[xb][A-Za-z0-9_]+|[0-9_]+(\\.[0-9_]+)?([uif](8|16|32|64)?)?)",r:0};var a="assert bool break char check claim comm const cont copy dir do drop else enum extern export f32 f64 fail false float fn for i16 i32 i64 i8 if impl int let log loop match mod move mut priv pub pure ref return self static str struct task true trait type u16 u32 u64 u8 uint unsafe use vec while";return{k:a,i:"</",c:[b.CLCM,b.CBLCLM,b.inherit(b.QSM,{i:null}),b.ASM,c,{cN:"function",bK:"fn",e:"(\\(|<)",c:[b.UTM]},{cN:"preprocessor",b:"#\\[",e:"\\]"},{bK:"type",e:"(=|<)",c:[b.UTM],i:"\\S"},{bK:"trait enum",e:"({|<)",c:[b.UTM],i:"\\S"}]}});hljs.registerLanguage("java",function(b){var a="false synchronized int abstract float private char boolean static null if const for true while long throw strictfp finally protected import native final return void enum else break transient new catch instanceof byte super volatile case assert short package default double public try this switch continue throws";return{k:a,i:/<\//,c:[{cN:"javadoc",b:"/\\*\\*",e:"\\*/",c:[{cN:"javadoctag",b:"(^|\\s)@[A-Za-z]+"}],r:10},b.CLCM,b.CBLCLM,b.ASM,b.QSM,{bK:"protected public private",e:/[{;=]/,k:a,c:[{cN:"class",bK:"class interface",eW:true,i:/[:"<>]/,c:[{bK:"extends implements",r:10},b.UTM]},{b:b.UIR+"\\s*\\(",rB:true,c:[b.UTM]}]},b.CNM,{cN:"annotation",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("lua",function(b){var a="\\[=*\\[";var e="\\]=*\\]";var c={b:a,e:e,c:["self"]};var d=[{cN:"comment",b:"--(?!"+a+")",e:"$"},{cN:"comment",b:"--"+a,e:e,c:[c],r:10}];return{l:b.UIR,k:{keyword:"and break do else elseif end false for if in local nil not or repeat return then true until while",built_in:"_G _VERSION assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall coroutine debug io math os package string table"},c:d.concat([{cN:"function",bK:"function",e:"\\)",c:[b.inherit(b.TM,{b:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{cN:"params",b:"\\(",eW:true,c:d}].concat(d)},b.CNM,b.ASM,b.QSM,{cN:"string",b:a,e:e,c:[c],r:10}])}});hljs.registerLanguage("rsl",function(a){return{k:{keyword:"float color point normal vector matrix while for if do return else break extern continue",built_in:"abs acos ambient area asin atan atmosphere attribute calculatenormal ceil cellnoise clamp comp concat cos degrees depth Deriv diffuse distance Du Dv environment exp faceforward filterstep floor format fresnel incident length lightsource log match max min mod noise normalize ntransform opposite option phong pnoise pow printf ptlined radians random reflect refract renderinfo round setcomp setxcomp setycomp setzcomp shadow sign sin smoothstep specular specularbrdf spline sqrt step tan texture textureinfo trace transform vtransform xcomp ycomp zcomp"},i:"</",c:[a.CLCM,a.CBLCLM,a.QSM,a.ASM,a.CNM,{cN:"preprocessor",b:"#",e:"$"},{cN:"shader",bK:"surface displacement light volume imager",e:"\\("},{cN:"shading",bK:"illuminate illuminance gather",e:"\\("}]}});hljs.registerLanguage("d",function(x){var b={keyword:"abstract alias align asm assert auto body break byte case cast catch class const continue debug default delete deprecated do else enum export extern final finally for foreach foreach_reverse|10 goto if immutable import in inout int interface invariant is lazy macro mixin module new nothrow out override package pragma private protected public pure ref return scope shared static struct super switch synchronized template this throw try typedef typeid typeof union unittest version void volatile while with __FILE__ __LINE__ __gshared|10 __thread __traits __DATE__ __EOF__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__",built_in:"bool cdouble cent cfloat char creal dchar delegate double dstring float function idouble ifloat ireal long real short string ubyte ucent uint ulong ushort wchar wstring",literal:"false null true"};var c="(0|[1-9][\\d_]*)",q="(0|[1-9][\\d_]*|\\d[\\d_]*|[\\d_]+?\\d)",h="0[bB][01_]+",v="([\\da-fA-F][\\da-fA-F_]*|_[\\da-fA-F][\\da-fA-F_]*)",y="0[xX]"+v,p="([eE][+-]?"+q+")",o="("+q+"(\\.\\d*|"+p+")|\\d+\\."+q+q+"|\\."+c+p+"?)",k="(0[xX]("+v+"\\."+v+"|\\.?"+v+")[pP][+-]?"+q+")",l="("+c+"|"+h+"|"+y+")",n="("+k+"|"+o+")";var z="\\\\(['\"\\?\\\\abfnrtv]|u[\\dA-Fa-f]{4}|[0-7]{1,3}|x[\\dA-Fa-f]{2}|U[\\dA-Fa-f]{8})|&[a-zA-Z\\d]{2,};";var m={cN:"number",b:"\\b"+l+"(L|u|U|Lu|LU|uL|UL)?",r:0};var j={cN:"number",b:"\\b("+n+"([fF]|L|i|[fF]i|Li)?|"+l+"(i|[fF]i|Li))",r:0};var s={cN:"string",b:"'("+z+"|.)",e:"'",i:"."};var r={b:z,r:0};var w={cN:"string",b:'"',c:[r],e:'"[cwd]?'};var f={cN:"string",b:'[rq]"',e:'"[cwd]?',r:5};var u={cN:"string",b:"`",e:"`[cwd]?"};var i={cN:"string",b:'x"[\\da-fA-F\\s\\n\\r]*"[cwd]?',r:10};var t={cN:"string",b:'q"\\{',e:'\\}"'};var e={cN:"shebang",b:"^#!",e:"$",r:5};var g={cN:"preprocessor",b:"#(line)",e:"$",r:5};var d={cN:"keyword",b:"@[a-zA-Z_][a-zA-Z_\\d]*"};var a={cN:"comment",b:"\\/\\+",c:["self"],e:"\\+\\/",r:10};return{l:x.UIR,k:b,c:[x.CLCM,x.CBLCLM,a,i,w,f,u,t,j,m,s,e,g,d]}});hljs.registerLanguage("javascript",function(a){return{aliases:["js"],k:{keyword:"in if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const class",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require"},c:[{cN:"pi",b:/^\s*('|")use strict('|")/,r:10},a.ASM,a.QSM,a.CLCM,a.CBLCLM,a.CNM,{b:"("+a.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[a.CLCM,a.CBLCLM,a.REGEXP_MODE,{b:/</,e:/>;/,r:0,sL:"xml"}],r:0},{cN:"function",bK:"function",e:/\{/,c:[a.inherit(a.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:"params",b:/\(/,e:/\)/,c:[a.CLCM,a.CBLCLM],i:/["'\(]/}],i:/\[|%/},{b:/\$[(.]/},{b:"\\."+a.IR,r:0}]}});hljs.registerLanguage("r",function(a){var b="([a-zA-Z]|\\.[a-zA-Z.])[a-zA-Z0-9._]*";return{c:[a.HCM,{b:b,l:b,k:{keyword:"function if in break next repeat else for return switch while try tryCatch|10 stop warning require library attach detach source setMethod setGeneric setGroupGeneric setClass ...|10",literal:"NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10"},r:0},{cN:"number",b:"0[xX][0-9a-fA-F]+[Li]?\\b",r:0},{cN:"number",b:"\\d+(?:[eE][+\\-]?\\d*)?L\\b",r:0},{cN:"number",b:"\\d+\\.(?!\\d)(?:i\\b)?",r:0},{cN:"number",b:"\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b",r:0},{cN:"number",b:"\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b",r:0},{b:"`",e:"`",r:0},{cN:"string",c:[a.BE],v:[{b:'"',e:'"'},{b:"'",e:"'"}]}]}});hljs.registerLanguage("ruby",function(e){var h="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?";var g="and false then defined module in return redo if BEGIN retry end for true self when next until do begin unless END rescue nil else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor";var a={cN:"yardoctag",b:"@[A-Za-z]+"};var i={cN:"comment",v:[{b:"#",e:"$",c:[a]},{b:"^\\=begin",e:"^\\=end",c:[a],r:10},{b:"^__END__",e:"\\n$"}]};var c={cN:"subst",b:"#\\{",e:"}",k:g};var d={cN:"string",c:[e.BE,c],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:"%[qw]?\\(",e:"\\)"},{b:"%[qw]?\\[",e:"\\]"},{b:"%[qw]?{",e:"}"},{b:"%[qw]?<",e:">",r:10},{b:"%[qw]?/",e:"/",r:10},{b:"%[qw]?%",e:"%",r:10},{b:"%[qw]?-",e:"-",r:10},{b:"%[qw]?\\|",e:"\\|",r:10},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/}]};var b={cN:"params",b:"\\(",e:"\\)",k:g};var f=[d,i,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{cN:"inheritance",b:"<\\s*",c:[{cN:"parent",b:"("+e.IR+"::)?"+e.IR}]},i]},{cN:"function",bK:"def",e:" |$|;",r:0,c:[e.inherit(e.TM,{b:h}),b,i]},{cN:"constant",b:"(::)?(\\b[A-Z]\\w*(::)?)+",r:0},{cN:"symbol",b:":",c:[d,{b:h}],r:0},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{cN:"variable",b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{b:"("+e.RSR+")\\s*",c:[i,{cN:"regexp",c:[e.BE,c],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}],r:0}];c.c=f;b.c=f;return{k:g,c:f}});hljs.registerLanguage("haml",function(a){return{cI:true,c:[{cN:"doctype",b:"^!!!( (5|1\\.1|Strict|Frameset|Basic|Mobile|RDFa|XML\\b.*))?$",r:10},{cN:"comment",b:"^\\s*(!=#|=#|-#|/).*$",r:0},{b:"^\\s*(-|=|!=)(?!#)",starts:{e:"\\n",sL:"ruby"}},{cN:"tag",b:"^\\s*%",c:[{cN:"title",b:"\\w+"},{cN:"value",b:"[#\\.]\\w+"},{b:"{\\s*",e:"\\s*}",eE:true,c:[{b:":\\w+\\s*=>",e:",\\s+",rB:true,eW:true,c:[{cN:"symbol",b:":\\w+"},{cN:"string",b:'"',e:'"'},{cN:"string",b:"'",e:"'"},{b:"\\w+",r:0}]}]},{b:"\\(\\s*",e:"\\s*\\)",eE:true,c:[{b:"\\w+\\s*=",e:"\\s+",rB:true,eW:true,c:[{cN:"attribute",b:"\\w+",r:0},{cN:"string",b:'"',e:'"'},{cN:"string",b:"'",e:"'"},{b:"\\w+",r:0}]},]}]},{cN:"bullet",b:"^\\s*[=~]\\s*",r:0},{b:"#{",starts:{e:"}",sL:"ruby"}}]}});hljs.registerLanguage("brainfuck",function(b){var a={cN:"literal",b:"[\\+\\-]",r:0};return{c:[{cN:"comment",b:"[^\\[\\]\\.,\\+\\-<> \r\n]",rE:true,e:"[\\[\\]\\.,\\+\\-<> \r\n]",r:0},{cN:"title",b:"[\\[\\]]",r:0},{cN:"string",b:"[\\.,]",r:0},{b:/\+\+|\-\-/,rB:true,c:[a]},a]}});hljs.registerLanguage("matlab",function(a){var b=[a.CNM,{cN:"string",b:"'",e:"'",c:[a.BE,{b:"''"}]}];return{k:{keyword:"break case catch classdef continue else elseif end enumerated events for function global if methods otherwise parfor persistent properties return spmd switch try while",built_in:"sin sind sinh asin asind asinh cos cosd cosh acos acosd acosh tan tand tanh atan atand atan2 atanh sec secd sech asec asecd asech csc cscd csch acsc acscd acsch cot cotd coth acot acotd acoth hypot exp expm1 log log1p log10 log2 pow2 realpow reallog realsqrt sqrt nthroot nextpow2 abs angle complex conj imag real unwrap isreal cplxpair fix floor ceil round mod rem sign airy besselj bessely besselh besseli besselk beta betainc betaln ellipj ellipke erf erfc erfcx erfinv expint gamma gammainc gammaln psi legendre cross dot factor isprime primes gcd lcm rat rats perms nchoosek factorial cart2sph cart2pol pol2cart sph2cart hsv2rgb rgb2hsv zeros ones eye repmat rand randn linspace logspace freqspace meshgrid accumarray size length ndims numel disp isempty isequal isequalwithequalnans cat reshape diag blkdiag tril triu fliplr flipud flipdim rot90 find sub2ind ind2sub bsxfun ndgrid permute ipermute shiftdim circshift squeeze isscalar isvector ans eps realmax realmin pi i inf nan isnan isinf isfinite j why compan gallery hadamard hankel hilb invhilb magic pascal rosser toeplitz vander wilkinson"},i:'(//|"|#|/\\*|\\s+/\\w+)',c:[{cN:"function",bK:"function",e:"$",c:[a.UTM,{cN:"params",b:"\\(",e:"\\)"},{cN:"params",b:"\\[",e:"\\]"}]},{cN:"transposed_variable",b:"[a-zA-Z_][a-zA-Z_0-9]*('+[\\.']*|[\\.']+)",e:"",r:0},{cN:"matrix",b:"\\[",e:"\\]'*[\\.']*",c:b,r:0},{cN:"cell",b:"\\{",e:"\\}'*[\\.']*",c:b,i:/:/},{cN:"comment",b:"\\%",e:"$"}].concat(b)}});hljs.registerLanguage("vbscript",function(a){return{cI:true,k:{keyword:"call class const dim do loop erase execute executeglobal exit for each next function if then else on error option explicit new private property let get public randomize redim rem select case set stop sub while wend with end to elseif is or xor and not class_initialize class_terminate default preserve in me byval byref step resume goto",built_in:"lcase month vartype instrrev ubound setlocale getobject rgb getref string weekdayname rnd dateadd monthname now day minute isarray cbool round formatcurrency conversions csng timevalue second year space abs clng timeserial fixs len asc isempty maths dateserial atn timer isobject filter weekday datevalue ccur isdate instr datediff formatdatetime replace isnull right sgn array snumeric log cdbl hex chr lbound msgbox ucase getlocale cos cdate cbyte rtrim join hour oct typename trim strcomp int createobject loadpicture tan formatnumber mid scriptenginebuildversion scriptengine split scriptengineminorversion cint sin datepart ltrim sqr scriptenginemajorversion time derived eval date formatpercent exp inputbox left ascw chrw regexp server response request cstr err",literal:"true false null nothing empty"},i:"//",c:[a.inherit(a.QSM,{c:[{b:'""'}]}),{cN:"comment",b:/'/,e:/$/,r:0},a.CNM]}});hljs.registerLanguage("fsharp",function(a){return{k:"abstract and as assert base begin class default delegate do done downcast downto elif else end exception extern false finally for fun function global if in inherit inline interface internal lazy let match member module mutable namespace new null of open or override private public rec return sig static struct then to true try type upcast use val void when while with yield",c:[{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},{cN:"string",b:'"""',e:'"""'},{cN:"comment",b:"\\(\\*",e:"\\*\\)"},{cN:"class",bK:"type",e:"\\(|=|$",c:[a.UTM]},{cN:"annotation",b:"\\[<",e:">\\]"},{cN:"attribute",b:"\\B('[A-Za-z])\\b",c:[a.BE]},a.CLCM,a.inherit(a.QSM,{i:null}),a.CNM]}});hljs.registerLanguage("makefile",function(a){var b={cN:"variable",b:/\$\(/,e:/\)/,c:[a.BE]};return{c:[a.HCM,{b:/^\w+\s*\W*=/,rB:true,r:0,starts:{cN:"constant",e:/\s*\W*=/,eE:true,starts:{e:/$/,r:0,c:[b],}}},{cN:"title",b:/^[\w]+:\s*$/},{cN:"phony",b:/^\.PHONY:/,e:/$/,k:".PHONY",l:/[\.\w]+/},{b:/^\t+/,e:/$/,c:[a.QSM,b]}]}});hljs.registerLanguage("diff",function(a){return{c:[{cN:"chunk",r:10,v:[{b:/^\@\@ +\-\d+,\d+ +\+\d+,\d+ +\@\@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"header",v:[{b:/Index: /,e:/$/},{b:/=====/,e:/=====$/},{b:/^\-\-\-/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+\+\+/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"change",b:"^\\!",e:"$"}]}});hljs.registerLanguage("rib",function(a){return{k:"ArchiveRecord AreaLightSource Atmosphere Attribute AttributeBegin AttributeEnd Basis Begin Blobby Bound Clipping ClippingPlane Color ColorSamples ConcatTransform Cone CoordinateSystem CoordSysTransform CropWindow Curves Cylinder DepthOfField Detail DetailRange Disk Displacement Display End ErrorHandler Exposure Exterior Format FrameAspectRatio FrameBegin FrameEnd GeneralPolygon GeometricApproximation Geometry Hider Hyperboloid Identity Illuminate Imager Interior LightSource MakeCubeFaceEnvironment MakeLatLongEnvironment MakeShadow MakeTexture Matte MotionBegin MotionEnd NuPatch ObjectBegin ObjectEnd ObjectInstance Opacity Option Orientation Paraboloid Patch PatchMesh Perspective PixelFilter PixelSamples PixelVariance Points PointsGeneralPolygons PointsPolygons Polygon Procedural Projection Quantize ReadArchive RelativeDetail ReverseOrientation Rotate Scale ScreenWindow ShadingInterpolation ShadingRate Shutter Sides Skew SolidBegin SolidEnd Sphere SubdivisionMesh Surface TextureCoordinates Torus Transform TransformBegin TransformEnd TransformPoints Translate TrimCurve WorldBegin WorldEnd",i:"</",c:[a.HCM,a.CNM,a.ASM,a.QSM]}});hljs.registerLanguage("http",function(a){return{i:"\\S",c:[{cN:"status",b:"^HTTP/[0-9\\.]+",e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{cN:"request",b:"^[A-Z]+ (.*?) HTTP/[0-9\\.]+$",rB:true,e:"$",c:[{cN:"string",b:" ",e:" ",eB:true,eE:true}]},{cN:"attribute",b:"^\\w",e:": ",eE:true,i:"\\n|\\s|=",starts:{cN:"string",e:"$"}},{b:"\\n\\n",starts:{sL:"",eW:true}}]}});hljs.registerLanguage("autohotkey",function(b){var d={cN:"escape",b:"`[\\s\\S]"};var c={cN:"comment",b:";",e:"$",r:0};var a=[{cN:"built_in",b:"A_[a-zA-Z0-9]+"},{cN:"built_in",bK:"ComSpec Clipboard ClipboardAll ErrorLevel"}];return{cI:true,k:{keyword:"Break Continue Else Gosub If Loop Return While",literal:"A true false NOT AND OR"},c:a.concat([d,b.inherit(b.QSM,{c:[d]}),c,{cN:"number",b:b.NR,r:0},{cN:"var_expand",b:"%",e:"%",i:"\\n",c:[d]},{cN:"label",c:[d],v:[{b:'^[^\\n";]+::(?!=)'},{b:'^[^\\n";]+:(?!=)',r:0}]},{b:",\\s*,",r:10}])}});hljs.registerLanguage("php",function(b){var e={cN:"variable",b:"\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*"};var a={cN:"preprocessor",b:/<\?(php)?|\?>/};var c={cN:"string",c:[b.BE,a],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},b.inherit(b.ASM,{i:null}),b.inherit(b.QSM,{i:null})]};var d={v:[b.BNM,b.CNM]};return{cI:true,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[b.CLCM,b.HCM,{cN:"comment",b:"/\\*",e:"\\*/",c:[{cN:"phpdoc",b:"\\s@[A-Za-z]+"},a]},{cN:"comment",b:"__halt_compiler.+?;",eW:true,k:"__halt_compiler",l:b.UIR},{cN:"string",b:"<<<['\"]?\\w+['\"]?$",e:"^\\w+;",c:[b.BE]},a,e,{cN:"function",bK:"function",e:/[;{]/,i:"\\$|\\[|%",c:[b.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",e,b.CBLCLM,c,d]}]},{cN:"class",bK:"class interface",e:"{",i:/[:\(\$"]/,c:[{bK:"extends implements",r:10},b.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[b.UTM]},{bK:"use",e:";",c:[b.UTM]},{b:"=>"},c,d]}});hljs.registerLanguage("cmake",function(a){return{cI:true,k:{keyword:"add_custom_command add_custom_target add_definitions add_dependencies add_executable add_library add_subdirectory add_test aux_source_directory break build_command cmake_minimum_required cmake_policy configure_file create_test_sourcelist define_property else elseif enable_language enable_testing endforeach endfunction endif endmacro endwhile execute_process export find_file find_library find_package find_path find_program fltk_wrap_ui foreach function get_cmake_property get_directory_property get_filename_component get_property get_source_file_property get_target_property get_test_property if include include_directories include_external_msproject include_regular_expression install link_directories load_cache load_command macro mark_as_advanced message option output_required_files project qt_wrap_cpp qt_wrap_ui remove_definitions return separate_arguments set set_directory_properties set_property set_source_files_properties set_target_properties set_tests_properties site_name source_group string target_link_libraries try_compile try_run unset variable_watch while build_name exec_program export_library_dependencies install_files install_programs install_targets link_libraries make_directory remove subdir_depends subdirs use_mangled_mesa utility_source variable_requires write_file qt5_use_modules qt5_use_package qt5_wrap_cpp on off true false and or",operator:"equal less greater strless strgreater strequal matches"},c:[{cN:"envvar",b:"\\${",e:"}"},a.HCM,a.QSM,a.NM]}});hljs.registerLanguage("bash",function(b){var a={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)\}/}]};var d={cN:"string",b:/"/,e:/"/,c:[b.BE,a,{cN:"variable",b:/\$\(/,e:/\)/,c:[b.BE]}]};var c={cN:"string",b:/'/,e:/'/};return{l:/-?[a-z\.]+/,k:{keyword:"if then else elif fi for break continue while in do done exit return set declare case esac export exec",literal:"true false",built_in:"printf echo read cd pwd pushd popd dirs let eval unset typeset readonly getopts source shopt caller type hash bind help sudo",operator:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"shebang",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:true,c:[b.inherit(b.TM,{b:/\w[\w\d_]*/})],r:0},b.HCM,b.NM,d,c,a]}});hljs.registerLanguage("applescript",function(a){var b=a.inherit(a.QSM,{i:""});var d={cN:"params",b:"\\(",e:"\\)",c:["self",a.CNM,b]};var c=[{cN:"comment",b:"--",e:"$",},{cN:"comment",b:"\\(\\*",e:"\\*\\)",c:["self",{b:"--",e:"$"}]},a.HCM];return{k:{keyword:"about above after against and around as at back before beginning behind below beneath beside between but by considering contain contains continue copy div does eighth else end equal equals error every exit fifth first for fourth from front get given global if ignoring in into is it its last local me middle mod my ninth not of on onto or over prop property put ref reference repeat returning script second set seventh since sixth some tell tenth that the then third through thru timeout times to transaction try until where while whose with without",constant:"AppleScript false linefeed return pi quote result space tab true",type:"alias application boolean class constant date file integer list number real record string text",command:"activate beep count delay launch log offset read round run say summarize write",property:"character characters contents day frontmost id item length month name paragraph paragraphs rest reverse running time version weekday word words year"},c:[b,a.CNM,{cN:"type",b:"\\bPOSIX file\\b"},{cN:"command",b:"\\b(clipboard info|the clipboard|info for|list (disks|folder)|mount volume|path to|(close|open for) access|(get|set) eof|current date|do shell script|get volume settings|random number|set volume|system attribute|system info|time to GMT|(load|run|store) script|scripting components|ASCII (character|number)|localized string|choose (application|color|file|file name|folder|from list|remote application|URL)|display (alert|dialog))\\b|^\\s*return\\b"},{cN:"constant",b:"\\b(text item delimiters|current application|missing value)\\b"},{cN:"keyword",b:"\\b(apart from|aside from|instead of|out of|greater than|isn't|(doesn't|does not) (equal|come before|come after|contain)|(greater|less) than( or equal)?|(starts?|ends|begins?) with|contained by|comes (before|after)|a (ref|reference))\\b"},{cN:"property",b:"\\b(POSIX path|(date|time) string|quoted form)\\b"},{cN:"function_start",bK:"on",i:"[${=;\\n]",c:[a.UTM,d]}].concat(c),i:"//"}});hljs.registerLanguage("vhdl",function(a){return{cI:true,k:{keyword:"abs access after alias all and architecture array assert attribute begin block body buffer bus case component configuration constant context cover disconnect downto default else elsif end entity exit fairness file for force function generate generic group guarded if impure in inertial inout is label library linkage literal loop map mod nand new next nor not null of on open or others out package port postponed procedure process property protected pure range record register reject release rem report restrict restrict_guarantee return rol ror select sequence severity shared signal sla sll sra srl strong subtype then to transport type unaffected units until use variable vmode vprop vunit wait when while with xnor xor",typename:"boolean bit character severity_level integer time delay_length natural positive string bit_vector file_open_kind file_open_status std_ulogic std_ulogic_vector std_logic std_logic_vector unsigned signed boolean_vector integer_vector real_vector time_vector"},i:"{",c:[a.CBLCLM,{cN:"comment",b:"--",e:"$"},a.QSM,a.CNM,{cN:"literal",b:"'(U|X|0|1|Z|W|L|H|-)'",c:[a.BE]},{cN:"attribute",b:"'[A-Za-z](_?[A-Za-z0-9])*",c:[a.BE]}]}});hljs.registerLanguage("parser3",function(a){return{sL:"xml",r:0,c:[{cN:"comment",b:"^#",e:"$"},{cN:"comment",b:"\\^rem{",e:"}",r:10,c:[{b:"{",e:"}",c:["self"]}]},{cN:"preprocessor",b:"^@(?:BASE|USE|CLASS|OPTIONS)$",r:10},{cN:"title",b:"@[\\w\\-]+\\[[\\w^;\\-]*\\](?:\\[[\\w^;\\-]*\\])?(?:.*)$"},{cN:"variable",b:"\\$\\{?[\\w\\-\\.\\:]+\\}?"},{cN:"keyword",b:"\\^[\\w\\-\\.\\:]+"},{cN:"number",b:"\\^#[0-9a-fA-F]+"},a.CNM]}});hljs.registerLanguage("scala",function(a){var c={cN:"annotation",b:"@[A-Za-z]+"};var b={cN:"string",b:'u?r?"""',e:'"""',r:10};return{k:"type yield lazy override def with val var false true sealed abstract private trait object null if for while throw finally protected extends import final return else break new catch super class case package default try this match continue throws",c:[{cN:"javadoc",b:"/\\*\\*",e:"\\*/",c:[{cN:"javadoctag",b:"@[A-Za-z]+"}],r:10},a.CLCM,a.CBLCLM,b,a.ASM,a.QSM,{cN:"class",b:"((case )?class |object |trait )",e:"({|$)",i:":",k:"case class trait object",c:[{bK:"extends with",r:10},a.UTM,{cN:"params",b:"\\(",e:"\\)",c:[a.ASM,a.QSM,b,c]}]},a.CNM,c]}});hljs.registerLanguage("cpp",function(a){var b={keyword:"false int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct for static_cast|10 union namespace unsigned long throw volatile static protected bool template mutable if public friend do return goto auto void enum else break new extern using true class asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue wchar_t inline delete alignof char16_t char32_t constexpr decltype noexcept nullptr static_assert thread_local restrict _Bool complex _Complex _Imaginary",built_in:"std string cin cout cerr clog stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf"};return{aliases:["c"],k:b,i:"</",c:[a.CLCM,a.CBLCLM,a.QSM,{cN:"string",b:"'\\\\?.",e:"'",i:"."},{cN:"number",b:"\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)"},a.CNM,{cN:"preprocessor",b:"#",e:"$",c:[{b:"include\\s*<",e:">",i:"\\n"},a.CLCM]},{cN:"stl_container",b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:b,r:10,c:["self"]}]}}); \ No newline at end of file diff --git a/src/core/libs/DebugBar/Resources/vendor/highlightjs/styles/github.css b/src/core/libs/DebugBar/Resources/vendor/highlightjs/styles/github.css new file mode 100755 index 0000000..71967a3 --- /dev/null +++ b/src/core/libs/DebugBar/Resources/vendor/highlightjs/styles/github.css @@ -0,0 +1,125 @@ +/* + +github.com style (c) Vasily Polovnyov <vast@whiteants.net> + +*/ + +.hljs { + display: block; padding: 0.5em; + color: #333; + background: #f8f8f8 +} + +.hljs-comment, +.hljs-template_comment, +.diff .hljs-header, +.hljs-javadoc { + color: #998; + font-style: italic +} + +.hljs-keyword, +.css .rule .hljs-keyword, +.hljs-winutils, +.javascript .hljs-title, +.nginx .hljs-title, +.hljs-subst, +.hljs-request, +.hljs-status { + color: #333; + font-weight: bold +} + +.hljs-number, +.hljs-hexcolor, +.ruby .hljs-constant { + color: #099; +} + +.hljs-string, +.hljs-tag .hljs-value, +.hljs-phpdoc, +.tex .hljs-formula { + color: #d14 +} + +.hljs-title, +.hljs-id, +.coffeescript .hljs-params, +.scss .hljs-preprocessor { + color: #900; + font-weight: bold +} + +.javascript .hljs-title, +.lisp .hljs-title, +.clojure .hljs-title, +.hljs-subst { + font-weight: normal +} + +.hljs-class .hljs-title, +.haskell .hljs-type, +.vhdl .hljs-literal, +.tex .hljs-command { + color: #458; + font-weight: bold +} + +.hljs-tag, +.hljs-tag .hljs-title, +.hljs-rules .hljs-property, +.django .hljs-tag .hljs-keyword { + color: #000080; + font-weight: normal +} + +.hljs-attribute, +.hljs-variable, +.lisp .hljs-body { + color: #008080 +} + +.hljs-regexp { + color: #009926 +} + +.hljs-symbol, +.ruby .hljs-symbol .hljs-string, +.lisp .hljs-keyword, +.tex .hljs-special, +.hljs-prompt { + color: #990073 +} + +.hljs-built_in, +.lisp .hljs-title, +.clojure .hljs-built_in { + color: #0086b3 +} + +.hljs-preprocessor, +.hljs-pragma, +.hljs-pi, +.hljs-doctype, +.hljs-shebang, +.hljs-cdata { + color: #999; + font-weight: bold +} + +.hljs-deletion { + background: #fdd +} + +.hljs-addition { + background: #dfd +} + +.diff .hljs-change { + background: #0086b3 +} + +.hljs-chunk { + color: #aaa +} diff --git a/src/core/libs/DebugBar/Resources/vendor/jquery/dist/jquery.min.js b/src/core/libs/DebugBar/Resources/vendor/jquery/dist/jquery.min.js new file mode 100755 index 0000000..ab28a24 --- /dev/null +++ b/src/core/libs/DebugBar/Resources/vendor/jquery/dist/jquery.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="<select msallowclip=''><option selected=''></option></select>",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=lb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=mb(b);function pb(){}pb.prototype=d.filters=d.pseudos,d.setFilters=new pb,g=fb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fb.error(a):z(a,i).slice(0)};function qb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; +if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==cb()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===cb()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ab:bb):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:bb,isPropagationStopped:bb,isImmediatePropagationStopped:bb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ab,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ab,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ab,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=bb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,m(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=bb),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function db(a){var b=eb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var eb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fb=/ jQuery\d+="(?:null|\d+)"/g,gb=new RegExp("<(?:"+eb+")[\\s/>]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/<tbody/i,lb=/<|&#?\w+;/,mb=/<(?:script|style|link)/i,nb=/checked\s*(?:[^=]|=\s*.checked.)/i,ob=/^$|\/(?:java|ecma)script/i,pb=/^true\/(.*)/,qb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,rb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?"<table>"!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Cb[0].contentWindow||Cb[0].contentDocument).document,b.write(),b.close(),c=Eb(a,b),Cb.detach()),Db[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Gb=/^margin/,Hb=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ib,Jb,Kb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ib=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Hb.test(g)&&Gb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ib=function(a){return a.currentStyle},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Hb.test(g)&&!Kb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Lb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Mb=/alpha\([^)]*\)/i,Nb=/opacity\s*=\s*([^)]*)/,Ob=/^(none|table(?!-c[ea]).+)/,Pb=new RegExp("^("+S+")(.*)$","i"),Qb=new RegExp("^([+-])=("+S+")","i"),Rb={position:"absolute",visibility:"hidden",display:"block"},Sb={letterSpacing:"0",fontWeight:"400"},Tb=["Webkit","O","Moz","ms"];function Ub(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Tb.length;while(e--)if(b=Tb[e]+c,b in a)return b;return d}function Vb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fb(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wb(a,b,c){var d=Pb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Yb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ib(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Jb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Hb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xb(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Jb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ub(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ub(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Jb(a,b,d)),"normal"===f&&b in Sb&&(f=Sb[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Ob.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Rb,function(){return Yb(a,b,d)}):Yb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ib(a);return Wb(a,c,d?Xb(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Nb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Mb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Mb.test(f)?f.replace(Mb,e):f+" "+e)}}),m.cssHooks.marginRight=Lb(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Jb,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Gb.test(a)||(m.cssHooks[a+b].set=Wb)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ib(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Vb(this,!0)},hide:function(){return Vb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Zb(a,b,c,d,e){return new Zb.prototype.init(a,b,c,d,e)}m.Tween=Zb,Zb.prototype={constructor:Zb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px") +},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Zb.propHooks.scrollTop=Zb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Zb.prototype.init,m.fx.step={};var $b,_b,ac=/^(?:toggle|show|hide)$/,bc=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cc=/queueHooks$/,dc=[ic],ec={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bc.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bc.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fc(){return setTimeout(function(){$b=void 0}),$b=m.now()}function gc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hc(a,b,c){for(var d,e=(ec[b]||[]).concat(ec["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ic(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fb(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fb(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ac.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fb(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hc(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jc(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kc(a,b,c){var d,e,f=0,g=dc.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$b||fc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$b||fc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jc(k,j.opts.specialEasing);g>f;f++)if(d=dc[f].call(j,a,k,j.opts))return d;return m.map(k,hc,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kc,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],ec[c]=ec[c]||[],ec[c].unshift(b)},prefilter:function(a,b){b?dc.unshift(a):dc.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kc(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gc(b,!0),a,d,e)}}),m.each({slideDown:gc("show"),slideUp:gc("hide"),slideToggle:gc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($b=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$b=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_b||(_b=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_b),_b=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lc=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lc,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mc,nc,oc=m.expr.attrHandle,pc=/^(?:checked|selected)$/i,qc=k.getSetAttribute,rc=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nc:mc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rc&&qc||!pc.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qc?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nc={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rc&&qc||!pc.test(c)?a.setAttribute(!qc&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=oc[b]||m.find.attr;oc[b]=rc&&qc||!pc.test(b)?function(a,b,d){var e,f;return d||(f=oc[b],oc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,oc[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rc&&qc||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mc&&mc.set(a,b,c)}}),qc||(mc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},oc.id=oc.name=oc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mc.set},m.attrHooks.contenteditable={set:function(a,b,c){mc.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sc=/^(?:input|select|textarea|button|object)$/i,tc=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sc.test(a.nodeName)||tc.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var uc=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(uc," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vc=m.now(),wc=/\?/,xc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yc,zc,Ac=/#.*$/,Bc=/([?&])_=[^&]*/,Cc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Dc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Ec=/^(?:GET|HEAD)$/,Fc=/^\/\//,Gc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hc={},Ic={},Jc="*/".concat("*");try{zc=location.href}catch(Kc){zc=y.createElement("a"),zc.href="",zc=zc.href}yc=Gc.exec(zc.toLowerCase())||[];function Lc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mc(a,b,c,d){var e={},f=a===Ic;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nc(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Oc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zc,type:"GET",isLocal:Dc.test(yc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nc(Nc(a,m.ajaxSettings),b):Nc(m.ajaxSettings,a)},ajaxPrefilter:Lc(Hc),ajaxTransport:Lc(Ic),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zc)+"").replace(Ac,"").replace(Fc,yc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yc[1]&&c[2]===yc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yc[3]||("http:"===yc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mc(Hc,k,b,v),2===t)return v;h=k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Ec.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bc.test(e)?e.replace(Bc,"$1_="+vc++):e+(wc.test(e)?"&":"?")+"_="+vc++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mc(Ic,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Oc(k,v,c)),u=Pc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qc=/%20/g,Rc=/\[\]$/,Sc=/\r?\n/g,Tc=/^(?:submit|button|image|reset|file)$/i,Uc=/^(?:input|select|textarea|keygen)/i;function Vc(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rc.test(a)?d(a,e):Vc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vc(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vc(c,a[c],b,e);return d.join("&").replace(Qc,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Uc.test(this.nodeName)&&!Tc.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sc,"\r\n")}}):{name:b.name,value:c.replace(Sc,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zc()||$c()}:Zc;var Wc=0,Xc={},Yc=m.ajaxSettings.xhr();a.ActiveXObject&&m(a).on("unload",function(){for(var a in Xc)Xc[a](void 0,!0)}),k.cors=!!Yc&&"withCredentials"in Yc,Yc=k.ajax=!!Yc,Yc&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xc[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zc(){try{return new a.XMLHttpRequest}catch(b){}}function $c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _c=[],ad=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_c.pop()||m.expando+"_"+vc++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ad.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ad.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ad,"$1"+e):b.jsonp!==!1&&(b.url+=(wc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_c.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bd=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bd)return bd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cd=a.document.documentElement;function dd(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dd(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cd;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cd})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dd(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=Lb(k.pixelPosition,function(a,c){return c?(c=Jb(a,b),Hb.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ed=a.jQuery,fd=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fd),b&&a.jQuery===m&&(a.jQuery=ed),m},typeof b===K&&(a.jQuery=a.$=m),m}); diff --git a/src/core/libs/DebugBar/Resources/widgets.css b/src/core/libs/DebugBar/Resources/widgets.css new file mode 100755 index 0000000..e4dd342 --- /dev/null +++ b/src/core/libs/DebugBar/Resources/widgets.css @@ -0,0 +1,186 @@ +ul.phpdebugbar-widgets-list { + margin: 0; + padding: 0; + list-style: none; + font-family: monospace; +} + ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item { + padding: 3px 6px; + border-bottom: 1px solid #eee; + position: relative; + overflow: hidden; + } + ul.phpdebugbar-widgets-list li.phpdebugbar-widgets-list-item:hover { + background: #fafafa; + } + +/* -------------------------------------- */ + +div.phpdebugbar-widgets-messages { + position: relative; + height: 100%; +} + div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-list { + padding-bottom: 20px; + } + div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-warning:before { + font-family: FontAwesome; + content: "\f071"; + margin-right: 8px; + font-size: 11px; + color: #ecb03d; + } + div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-error { + color: red; + } + div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-value.phpdebugbar-widgets-error:before { + font-family: FontAwesome; + content: "\f057"; + margin-right: 8px; + font-size: 11px; + color: red; + } + div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-collector, + div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-label { + float: right; + font-size: 12px; + padding: 2px 4px; + color: #888; + margin: 0 2px; + text-decoration: none; + text-shadow: none; + background: none; + font-weight: normal; + } + div.phpdebugbar-widgets-messages li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-collector { + color: #555; + font-style: italic; + } + div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar { + position: fixed; + bottom: 0; + width: 100%; + background: #fff; + } + div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar input { + border: 0; + margin: 0; + margin-left: 7px; + width: 50%; + box-shadow: none; + } + div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar input:focus { + outline: none; + } + div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter { + float: right; + font-size: 12px; + padding: 2px 4px; + background: #7cacd5; + margin: 0 2px; + border-radius: 4px; + color: #fff; + text-decoration: none; + } + div.phpdebugbar-widgets-messages div.phpdebugbar-widgets-toolbar a.phpdebugbar-widgets-filter.phpdebugbar-widgets-excluded { + background: #eee; + color: #888; + } + +/* -------------------------------------- */ + +dl.phpdebugbar-widgets-kvlist { + margin: 0; +} + dl.phpdebugbar-widgets-kvlist dt { + float: left; + width: 150px; + padding: 5px; + border-top: 1px solid #eee; + font-weight: bold; + clear: both; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + dl.phpdebugbar-widgets-kvlist dd { + margin-left: 160px; + padding: 5px; + border-top: 1px solid #eee; + cursor: pointer; + min-height: 17px; + } + +/* -------------------------------------- */ + +dl.phpdebugbar-widgets-varlist { + font-family: monospace; +} + +/* -------------------------------------- */ + +ul.phpdebugbar-widgets-timeline { + margin: 0; + padding: 0; + list-style: none; +} + ul.phpdebugbar-widgets-timeline li { + height: 20px; + position: relative; + border-bottom: 1px solid #eee; + display: block; + } + ul.phpdebugbar-widgets-timeline li:hover { + background: #fafafa; + } + ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-label { + position: absolute; + font-size: 12px; + font-family: monospace; + color: #555; + top: 4px; + left: 5px; + background: none; + text-shadow: none; + font-weight: normal; + } + ul.phpdebugbar-widgets-timeline li span.phpdebugbar-widgets-value { + display: block; + position: absolute; + height: 10px; + background: #3db9ec; + top: 5px; + border-radius: 2px; + } + +/* -------------------------------------- */ + +div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item { + cursor: pointer; +} + div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-message { + display: block; + color: red; + } + + div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-filename { + display: block; + font-style: italic; + color: #555; + } + + div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-type { + display: block; + position: absolute; + right: 4px; + top: 4px; + font-weight: bold; + } + + div.phpdebugbar-widgets-exceptions li.phpdebugbar-widgets-list-item pre.phpdebugbar-widgets-file { + display: none; + margin: 10px; + padding: 5px; + border: 1px solid #ddd; + font-family: monospace; + } diff --git a/src/core/libs/DebugBar/Resources/widgets.js b/src/core/libs/DebugBar/Resources/widgets.js new file mode 100755 index 0000000..a3ba2b9 --- /dev/null +++ b/src/core/libs/DebugBar/Resources/widgets.js @@ -0,0 +1,430 @@ +if (typeof(PhpDebugBar) == 'undefined') { + // namespace + var PhpDebugBar = {}; + PhpDebugBar.$ = jQuery; +} + +(function($) { + + /** + * @namespace + */ + PhpDebugBar.Widgets = {}; + + /** + * Replaces spaces with &nbsp; and line breaks with <br> + * + * @param {String} text + * @return {String} + */ + var htmlize = PhpDebugBar.Widgets.htmlize = function(text) { + return text.replace(/\n/g, '<br>').replace(/\s/g, "&nbsp;") + }; + + /** + * Returns a string representation of value, using JSON.stringify + * if it's an object. + * + * @param {Object} value + * @param {Boolean} prettify Uses htmlize() if true + * @return {String} + */ + var renderValue = PhpDebugBar.Widgets.renderValue = function(value, prettify) { + if (typeof(value) !== 'string') { + if (prettify) { + return htmlize(JSON.stringify(value, undefined, 2)); + } + return JSON.stringify(value); + } + return value; + }; + + /** + * Highlights a block of code + * + * @param {String} code + * @param {String} lang + * @return {String} + */ + var highlight = PhpDebugBar.Widgets.highlight = function(code, lang) { + if (typeof(code) === 'string') { + if (typeof(hljs) === 'undefined') { + return htmlize(code); + } + if (lang) { + return hljs.highlight(lang, code).value; + } + return hljs.highlightAuto(code).value; + } + + if (typeof(hljs) === 'object') { + code.each(function(i, e) { hljs.highlightBlock(e); }); + } + return code; + }; + + /** + * Creates a <pre> element with a block of code + * + * @param {String} code + * @param {String} lang + * @return {String} + */ + var createCodeBlock = PhpDebugBar.Widgets.createCodeBlock = function(code, lang) { + var pre = $('<pre />'); + $('<code />').text(code).appendTo(pre); + if (lang) { + pre.addClass("language-" + lang); + } + highlight(pre); + return pre; + }; + + var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-'); + + + // ------------------------------------------------------------------ + // Generic widgets + // ------------------------------------------------------------------ + + /** + * Displays array element in a <ul> list + * + * Options: + * - data + * - itemRenderer: a function used to render list items (optional) + */ + var ListWidget = PhpDebugBar.Widgets.ListWidget = PhpDebugBar.Widget.extend({ + + tagName: 'ul', + + className: csscls('list'), + + initialize: function(options) { + if (!options['itemRenderer']) { + options['itemRenderer'] = this.itemRenderer; + } + this.set(options); + }, + + render: function() { + this.bindAttr(['itemRenderer', 'data'], function() { + this.$el.empty(); + if (!this.has('data')) { + return; + } + + var data = this.get('data'); + for (var i = 0; i < data.length; i++) { + var li = $('<li />').addClass(csscls('list-item')).appendTo(this.$el); + this.get('itemRenderer')(li, data[i]); + } + }); + }, + + /** + * Renders the content of a <li> element + * + * @param {jQuery} li The <li> element as a jQuery Object + * @param {Object} value An item from the data array + */ + itemRenderer: function(li, value) { + li.html(renderValue(value)); + } + + }); + + // ------------------------------------------------------------------ + + /** + * Displays object property/value paris in a <dl> list + * + * Options: + * - data + * - itemRenderer: a function used to render list items (optional) + */ + var KVListWidget = PhpDebugBar.Widgets.KVListWidget = ListWidget.extend({ + + tagName: 'dl', + + className: csscls('kvlist'), + + render: function() { + this.bindAttr(['itemRenderer', 'data'], function() { + this.$el.empty(); + if (!this.has('data')) { + return; + } + + var self = this; + $.each(this.get('data'), function(key, value) { + var dt = $('<dt />').addClass(csscls('key')).appendTo(self.$el); + var dd = $('<dd />').addClass(csscls('value')).appendTo(self.$el); + self.get('itemRenderer')(dt, dd, key, value); + }); + }); + }, + + /** + * Renders the content of the <dt> and <dd> elements + * + * @param {jQuery} dt The <dt> element as a jQuery Object + * @param {jQuery} dd The <dd> element as a jQuery Object + * @param {String} key Property name + * @param {Object} value Property value + */ + itemRenderer: function(dt, dd, key, value) { + dt.text(key); + dd.html(htmlize(value)); + } + + }); + + // ------------------------------------------------------------------ + + /** + * An extension of KVListWidget where the data represents a list + * of variables + * + * Options: + * - data + */ + var VariableListWidget = PhpDebugBar.Widgets.VariableListWidget = KVListWidget.extend({ + + className: csscls('kvlist varlist'), + + itemRenderer: function(dt, dd, key, value) { + $('<span />').attr('title', key).text(key).appendTo(dt); + + var v = value; + if (v && v.length > 100) { + v = v.substr(0, 100) + "..."; + } + var prettyVal = null; + dd.text(v).click(function() { + if (dd.hasClass(csscls('pretty'))) { + dd.text(v).removeClass(csscls('pretty')); + } else { + prettyVal = prettyVal || createCodeBlock(value); + dd.addClass(csscls('pretty')).empty().append(prettyVal); + } + }); + } + + }); + + // ------------------------------------------------------------------ + + /** + * Iframe widget + * + * Options: + * - data + */ + var IFrameWidget = PhpDebugBar.Widgets.IFrameWidget = PhpDebugBar.Widget.extend({ + + tagName: 'iframe', + + className: csscls('iframe'), + + render: function() { + this.$el.attr({ + seamless: "seamless", + border: "0", + width: "100%", + height: "100%" + }); + this.bindAttr('data', function(url) { this.$el.attr('src', url); }); + } + + }); + + + // ------------------------------------------------------------------ + // Collector specific widgets + // ------------------------------------------------------------------ + + /** + * Widget for the MessagesCollector + * + * Uses ListWidget under the hood + * + * Options: + * - data + */ + var MessagesWidget = PhpDebugBar.Widgets.MessagesWidget = PhpDebugBar.Widget.extend({ + + className: csscls('messages'), + + render: function() { + var self = this; + + this.$list = new ListWidget({ itemRenderer: function(li, value) { + var m = value.message; + if (m.length > 100) { + m = m.substr(0, 100) + "..."; + } + + var val = $('<span />').addClass(csscls('value')).text(m).appendTo(li); + if (!value.is_string || value.message.length > 100) { + var prettyVal = value.message; + if (!value.is_string) { + prettyVal = null; + } + li.css('cursor', 'pointer').click(function() { + if (val.hasClass(csscls('pretty'))) { + val.text(m).removeClass(csscls('pretty')); + } else { + prettyVal = prettyVal || createCodeBlock(value.message, 'php'); + val.addClass(csscls('pretty')).empty().append(prettyVal); + } + }); + } + + if (value.label) { + val.addClass(csscls(value.label)); + $('<span />').addClass(csscls('label')).text(value.label).appendTo(li); + } + if (value.collector) { + $('<span />').addClass(csscls('collector')).text(value.collector).appendTo(li); + } + }}); + + this.$list.$el.appendTo(this.$el); + this.$toolbar = $('<div><i class="fa fa-search"></i></div>').addClass(csscls('toolbar')).appendTo(this.$el); + + $('<input type="text" />') + .on('change', function() { self.set('search', this.value); }) + .appendTo(this.$toolbar); + + this.bindAttr('data', function(data) { + this.set({ exclude: [], search: '' }); + this.$toolbar.find(csscls('.filter')).remove(); + + var filters = [], self = this; + for (var i = 0; i < data.length; i++) { + if (!data[i].label || $.inArray(data[i].label, filters) > -1) { + continue; + } + filters.push(data[i].label); + $('<a href="javascript:" />') + .addClass(csscls('filter')) + .text(data[i].label) + .attr('rel', data[i].label) + .on('click', function() { self.onFilterClick(this); }) + .appendTo(this.$toolbar); + } + }); + + this.bindAttr(['exclude', 'search'], function() { + var data = this.get('data'), + exclude = this.get('exclude'), + search = this.get('search'), + fdata = []; + + for (var i = 0; i < data.length; i++) { + if ((!data[i].label || $.inArray(data[i].label, exclude) === -1) && (!search || data[i].message.indexOf(search) > -1)) { + fdata.push(data[i]); + } + } + + this.$list.set('data', fdata); + }); + }, + + onFilterClick: function(el) { + $(el).toggleClass(csscls('excluded')); + + var excludedLabels = []; + this.$toolbar.find(csscls('.filter') + csscls('.excluded')).each(function() { + excludedLabels.push(this.rel); + }); + + this.set('exclude', excludedLabels); + } + + }); + + // ------------------------------------------------------------------ + + /** + * Widget for the TimeDataCollector + * + * Options: + * - data + */ + var TimelineWidget = PhpDebugBar.Widgets.TimelineWidget = PhpDebugBar.Widget.extend({ + + tagName: 'ul', + + className: csscls('timeline'), + + render: function() { + this.bindAttr('data', function(data) { + this.$el.empty(); + if (data.measures) { + for (var i = 0; i < data.measures.length; i++) { + var li = $('<li />').addClass(csscls('measure')), + left = Math.round(data.measures[i].relative_start * 100 / data.duration), + width = Math.min(Math.round(data.measures[i].duration * 100 / data.duration), 100 - left); + + li.append($('<span />').addClass(csscls('value')).css({ + left: left + "%", + width: width + "%" + })); + li.append($('<span />').addClass(csscls('label')).text(data.measures[i].label + " (" + data.measures[i].duration_str + ")")); + this.$el.append(li); + } + } + }); + } + + }); + + // ------------------------------------------------------------------ + + /** + * Widget for the displaying exceptions + * + * Options: + * - data + */ + var ExceptionsWidget = PhpDebugBar.Widgets.ExceptionsWidget = PhpDebugBar.Widget.extend({ + + className: csscls('exceptions'), + + render: function() { + this.$list = new ListWidget({ itemRenderer: function(li, e) { + $('<span />').addClass(csscls('message')).text(e.message).appendTo(li); + if (e.file) { + $('<span />').addClass(csscls('filename')).text(e.file + "#" + e.line).appendTo(li); + } + if (e.type) { + $('<span />').addClass(csscls('type')).text(e.type).appendTo(li); + } + if (e.surrounding_lines) { + var pre = createCodeBlock(e.surrounding_lines.join(""), 'php').addClass(csscls('file')).appendTo(li); + li.click(function() { + if (pre.is(':visible')) { + pre.hide(); + } else { + pre.show(); + } + }); + } + }}); + this.$list.$el.appendTo(this.$el); + + this.bindAttr('data', function(data) { + this.$list.set('data', data); + if (data.length == 1) { + this.$list.$el.children().first().find(csscls('.file')).show(); + } + }); + + } + + }); + + +})(PhpDebugBar.$); diff --git a/src/core/libs/DebugBar/Resources/widgets/mails/widget.css b/src/core/libs/DebugBar/Resources/widgets/mails/widget.css new file mode 100755 index 0000000..a43957a --- /dev/null +++ b/src/core/libs/DebugBar/Resources/widgets/mails/widget.css @@ -0,0 +1,12 @@ + +div.phpdebugbar-widgets-mails span.phpdebugbar-widgets-subject { + display: block; +} + +div.phpdebugbar-widgets-mails li.phpdebugbar-widgets-list-item pre.phpdebugbar-widgets-headers { + display: none; + margin: 10px; + padding: 5px; + border: 1px solid #ddd; + font-family: monospace; +} diff --git a/src/core/libs/DebugBar/Resources/widgets/mails/widget.js b/src/core/libs/DebugBar/Resources/widgets/mails/widget.js new file mode 100755 index 0000000..7a1a694 --- /dev/null +++ b/src/core/libs/DebugBar/Resources/widgets/mails/widget.js @@ -0,0 +1,40 @@ +(function($) { + + var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-'); + + /** + * Widget for the displaying mails data + * + * Options: + * - data + */ + var MailsWidget = PhpDebugBar.Widgets.MailsWidget = PhpDebugBar.Widget.extend({ + + className: csscls('mails'), + + render: function() { + this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function(li, mail) { + $('<span />').addClass(csscls('subject')).text(mail.subject).appendTo(li); + $('<span />').addClass(csscls('to')).text(mail.to).appendTo(li); + if (mail.headers) { + var headers = $('<pre />').addClass(csscls('headers')).appendTo(li); + $('<code />').text(mail.headers).appendTo(headers); + li.click(function() { + if (headers.is(':visible')) { + headers.hide(); + } else { + headers.show(); + } + }); + } + }}); + this.$list.$el.appendTo(this.$el); + + this.bindAttr('data', function(data) { + this.$list.set('data', data); + }); + } + + }); + +})(PhpDebugBar.$); diff --git a/src/core/libs/DebugBar/Resources/widgets/sqlqueries/widget.css b/src/core/libs/DebugBar/Resources/widgets/sqlqueries/widget.css new file mode 100755 index 0000000..322f2ba --- /dev/null +++ b/src/core/libs/DebugBar/Resources/widgets/sqlqueries/widget.css @@ -0,0 +1,82 @@ +div.phpdebugbar-widgets-sqlqueries .phpdebugbar-widgets-status { + font-family: monospace; + padding: 6px 6px; + border-bottom: 1px solid #ddd; + font-weight: bold; + color: #555; + background: #fafafa; +} + +div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-error { + color: red; +} + +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-duration, +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-memory, +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-row-count, +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id { + float: right; + margin-left: 8px; + color: #888; +} +div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-duration, +div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-memory, +div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-row-count, +div.phpdebugbar-widgets-sqlqueries div.phpdebugbar-widgets-status span.phpdebugbar-widgets-stmt-id { + color: #555; +} +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-duration:before, +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-memory:before, +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-row-count:before, +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id:before { + font-family: FontAwesome; + margin-right: 4px; + font-size: 12px; +} +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-duration:before { + content: "\f017"; +} +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-memory:before { + content: "\f085"; +} +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-row-count:before { + content: "\f0ce"; +} +div.phpdebugbar-widgets-sqlqueries span.phpdebugbar-widgets-stmt-id:before { + content: "\f08d"; +} +div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params { + display: none; + width: 70%; + margin: 10px; + border: 1px solid #ddd; + font-family: monospace; + border-collapse: collapse; +} + div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params td { + border: 1px solid #ddd; + text-align: center; + } + div.phpdebugbar-widgets-sqlqueries table.phpdebugbar-widgets-params .phpdebugbar-widgets-name { + width: 20%; + font-weight: bold; + } + +div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item span.phpdebugbar-widgets-error { + display: block; + font-weight: bold; +} + +code.phpdebugbar-widgets-sql { + white-space: pre-wrap; + overflow-wrap: break-word; + word-wrap: break-word; +} + +div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate { + background-color: #edeff0; +} + +div.phpdebugbar-widgets-sqlqueries li.phpdebugbar-widgets-list-item.phpdebugbar-widgets-sql-duplicate:hover { + background-color: #ffc; +} diff --git a/src/core/libs/DebugBar/Resources/widgets/sqlqueries/widget.js b/src/core/libs/DebugBar/Resources/widgets/sqlqueries/widget.js new file mode 100755 index 0000000..80be93b --- /dev/null +++ b/src/core/libs/DebugBar/Resources/widgets/sqlqueries/widget.js @@ -0,0 +1,96 @@ +(function($) { + + var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-'); + + /** + * Widget for the displaying sql queries + * + * Options: + * - data + */ + var SQLQueriesWidget = PhpDebugBar.Widgets.SQLQueriesWidget = PhpDebugBar.Widget.extend({ + + className: csscls('sqlqueries'), + + render: function() { + this.$status = $('<div />').addClass(csscls('status')).appendTo(this.$el); + + this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function(li, stmt) { + $('<code />').addClass(csscls('sql')).html(PhpDebugBar.Widgets.highlight(stmt.sql, 'sql')).appendTo(li); + if (stmt.duration_str) { + $('<span title="Duration" />').addClass(csscls('duration')).text(stmt.duration_str).appendTo(li); + } + if (stmt.memory_str) { + $('<span title="Memory usage" />').addClass(csscls('memory')).text(stmt.memory_str).appendTo(li); + } + if (typeof(stmt.is_success) != 'undefined' && !stmt.is_success) { + li.addClass(csscls('error')); + li.append($('<span />').addClass(csscls('error')).text("[" + stmt.error_code + "] " + stmt.error_message)); + } else if (typeof(stmt.row_count) != 'undefined') { + $('<span title="Row count" />').addClass(csscls('row-count')).text(stmt.row_count).appendTo(li); + } + if (typeof(stmt.stmt_id) != 'undefined' && stmt.stmt_id) { + $('<span title="Prepared statement ID" />').addClass(csscls('stmt-id')).text(stmt.stmt_id).appendTo(li); + } + if (stmt.params && !$.isEmptyObject(stmt.params)) { + var table = $('<table><tr><th colspan="2">Params</th></tr></table>').addClass(csscls('params')).appendTo(li); + for (var key in stmt.params) { + if (typeof stmt.params[key] !== 'function') { + table.append('<tr><td class="' + csscls('name') + '">' + key + '</td><td class="' + csscls('value') + + '">' + stmt.params[key] + '</td></tr>'); + } + } + li.css('cursor', 'pointer').click(function() { + if (table.is(':visible')) { + table.hide(); + } else { + table.show(); + } + }); + } + }}); + this.$list.$el.appendTo(this.$el); + + this.bindAttr('data', function(data) { + this.$list.set('data', data.statements); + this.$status.empty(); + + // Search for duplicate statements. + for (var sql = {}, duplicate = 0, i = 0; i < data.statements.length; i++) { + var stmt = data.statements[i].sql; + if (data.statements[i].params && !$.isEmptyObject(data.statements[i].params)) { + stmt += ' {' + $.param(data.statements[i].params, false) + '}'; + } + sql[stmt] = sql[stmt] || { keys: [] }; + sql[stmt].keys.push(i); + } + // Add classes to all duplicate SQL statements. + for (var stmt in sql) { + if (sql[stmt].keys.length > 1) { + duplicate++; + for (var i = 0; i < sql[stmt].keys.length; i++) { + this.$list.$el.find('.' + csscls('list-item')).eq(sql[stmt].keys[i]) + .addClass(csscls('sql-duplicate')).addClass(csscls('sql-duplicate-'+duplicate)); + } + } + } + + var t = $('<span />').text(data.nb_statements + " statements were executed").appendTo(this.$status); + if (data.nb_failed_statements) { + t.append(", " + data.nb_failed_statements + " of which failed"); + } + if (duplicate) { + t.append(", " + duplicate + " of which were duplicated"); + } + if (data.accumulated_duration_str) { + this.$status.append($('<span title="Accumulated duration" />').addClass(csscls('duration')).text(data.accumulated_duration_str)); + } + if (data.memory_usage_str) { + this.$status.append($('<span title="Memory usage" />').addClass(csscls('memory')).text(data.memory_usage_str)); + } + }); + } + + }); + +})(PhpDebugBar.$); diff --git a/src/core/libs/DebugBar/Resources/widgets/templates/widget.css b/src/core/libs/DebugBar/Resources/widgets/templates/widget.css new file mode 100755 index 0000000..fde40c8 --- /dev/null +++ b/src/core/libs/DebugBar/Resources/widgets/templates/widget.css @@ -0,0 +1,23 @@ + +div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status { + font-family: monospace; + padding: 6px 6px; + border-bottom: 1px solid #ddd; + font-weight: bold; + color: #555; + background: #fafafa; +} + +div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-render_time { + float: right; +} +div.phpdebugbar-widgets-templates span.phpdebugbar-widgets-render_time:before { + content: "\f017"; + font-family: FontAwesome; + font-size: 12px; + margin-right: 4px; +} + +div.phpdebugbar-widgets-templates div.phpdebugbar-widgets-status span.phpdebugbar-widgets-render_time { + color: #555; +} \ No newline at end of file diff --git a/src/core/libs/DebugBar/Resources/widgets/templates/widget.js b/src/core/libs/DebugBar/Resources/widgets/templates/widget.js new file mode 100755 index 0000000..6fdecbe --- /dev/null +++ b/src/core/libs/DebugBar/Resources/widgets/templates/widget.js @@ -0,0 +1,38 @@ +(function($) { + + var csscls = PhpDebugBar.utils.makecsscls('phpdebugbar-widgets-'); + + /** + * Widget for the displaying templates data + * + * Options: + * - data + */ + var TemplatesWidget = PhpDebugBar.Widgets.TemplatesWidget = PhpDebugBar.Widget.extend({ + + className: csscls('templates'), + + render: function() { + this.$status = $('<div />').addClass(csscls('status')).appendTo(this.$el); + + this.$list = new PhpDebugBar.Widgets.ListWidget({ itemRenderer: function(li, tpl) { + $('<span />').addClass(csscls('name')).text(tpl.name).appendTo(li); + if (tpl.render_time_str) { + $('<span title="Render time" />').addClass(csscls('render_time')).text(tpl.render_time_str).appendTo(li); + } + }}); + this.$list.$el.appendTo(this.$el); + + this.bindAttr('data', function(data) { + this.$list.set('data', data.templates); + var sentence = data.sentence || "templates were rendered"; + this.$status.empty().append($('<span />').text(data.templates.length + " " + sentence)); + if (data.accumulated_render_time_str) { + this.$status.append($('<span title="Accumulated render time" />').addClass(csscls('render_time')).text(data.accumulated_render_time_str)); + } + }); + } + + }); + +})(PhpDebugBar.$); \ No newline at end of file diff --git a/src/core/libs/DebugBar/StandardDebugBar.php b/src/core/libs/DebugBar/StandardDebugBar.php new file mode 100755 index 0000000..0be22df --- /dev/null +++ b/src/core/libs/DebugBar/StandardDebugBar.php @@ -0,0 +1,34 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar; + +use DebugBar\DataCollector\PhpInfoCollector; +use DebugBar\DataCollector\MessagesCollector; +use DebugBar\DataCollector\TimeDataCollector; +use DebugBar\DataCollector\RequestDataCollector; +use DebugBar\DataCollector\MemoryCollector; +use DebugBar\DataCollector\ExceptionsCollector; + +/** + * Debug bar subclass which adds all included collectors + */ +class StandardDebugBar extends DebugBar +{ + public function __construct() + { + $this->addCollector(new PhpInfoCollector()); + $this->addCollector(new MessagesCollector()); + $this->addCollector(new RequestDataCollector()); + $this->addCollector(new TimeDataCollector()); + $this->addCollector(new MemoryCollector()); + $this->addCollector(new ExceptionsCollector()); + } +} diff --git a/src/core/libs/DebugBar/Storage/FileStorage.php b/src/core/libs/DebugBar/Storage/FileStorage.php new file mode 100755 index 0000000..a893665 --- /dev/null +++ b/src/core/libs/DebugBar/Storage/FileStorage.php @@ -0,0 +1,108 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Storage; + +/** + * Stores collected data into files + */ +class FileStorage implements StorageInterface +{ + protected $dirname; + + /** + * @param string $dirname Directories where to store files + */ + public function __construct($dirname) + { + $this->dirname = rtrim($dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + } + + public function save($id, $data) + { + if (!file_exists($this->dirname)) { + mkdir($this->dirname, 0777, true); + } + file_put_contents($this->makeFilename($id), json_encode($data)); + } + + public function get($id) + { + return json_decode(file_get_contents($this->makeFilename($id)), true); + } + + public function find(array $filters = array(), $max = 20, $offset = 0) + { + //Loop through all .json files and remember the modified time and id. + $files = array(); + foreach (new \DirectoryIterator($this->dirname) as $file) { + if ($file->getExtension() == 'json') { + $files[] = array( + 'time' => $file->getMTime(), + 'id' => $file->getBasename('.json') + ); + } + } + + //Sort the files, newest first + usort($files, function($a, $b) { + return $a['time'] < $b['time']; + }); + + //Load the metadata and filter the results. + $results = array(); + $i = 0; + foreach ($files as $file) { + //When filter is empty, skip loading the offset + if ($i++ < $offset && empty($filters)) { + $results[] = null; + continue; + } + $data = $this->get($file['id']); + $meta = $data['__meta']; + unset($data); + if ($this->filter($meta, $filters)) { + $results[] = $meta; + } + if (count($results) >= ($max + $offset)) { + break; + } + } + + return array_slice($results, $offset, $max); + } + + /** + * Filter the metadata for matches. + */ + protected function filter($meta, $filters) + { + foreach ($filters as $key => $value) { + if (!isset($meta[$key]) || fnmatch($value, $meta[$key]) === false) { + return false; + } + } + return true; + } + + public function clear() + { + foreach (new \DirectoryIterator($this->dirname) as $file) { + if (substr($file->getFilename(), 0, 1) !== '.') { + unlink($file->getPathname()); + } + } + } + + public function makeFilename($id) + { + return $this->dirname . basename($id). ".json"; + } +} diff --git a/src/core/libs/DebugBar/Storage/MemcachedStorage.php b/src/core/libs/DebugBar/Storage/MemcachedStorage.php new file mode 100755 index 0000000..9c2eef7 --- /dev/null +++ b/src/core/libs/DebugBar/Storage/MemcachedStorage.php @@ -0,0 +1,91 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Storage; + +use Memcached; + +/** + * Stores collected data into Memcache using the Memcached extension + */ +class MemcachedStorage implements StorageInterface +{ + protected $memcached; + + protected $keyNamespace; + + /** + * @param Memcached $memcached + */ + public function __construct(Memcached $memcached, $keyNamespace = 'phpdebugbar') + { + $this->memcached = $memcached; + $this->keyNamespace = $keyNamespace; + } + + public function save($id, $data) + { + $key = $this->createKey($id); + $this->memcached->set($key, $data); + if (!$this->memcached->append($this->keyNamespace, "|$key")) { + $this->memcached->set($this->keyNamespace, $key); + } + } + + public function get($id) + { + return $this->memcached->get($this->createKey($id)); + } + + public function find(array $filters = array(), $max = 20, $offset = 0) + { + if (!($keys = $this->memcached->get($this->keyNamespace))) { + return array(); + } + + $results = array(); + foreach (explode('|', $keys) as $key) { + if ($data = $this->memcached->get($key)) { + $meta = $data['__meta']; + if ($this->filter($meta, $filters)) { + $results[] = $meta; + } + } + } + return array_slice($results, $offset, $max); + } + + /** + * Filter the metadata for matches. + */ + protected function filter($meta, $filters) + { + foreach ($filters as $key => $value) { + if (!isset($meta[$key]) || fnmatch($value, $meta[$key]) === false) { + return false; + } + } + return true; + } + + public function clear() + { + if (!($keys = $this->memcached->get($this->keyNamespace))) { + return; + } + $this->memcached->delete($this->keyNamespace); + $this->memcached->deleteMulti(explode('|', $keys)); + } + + protected function createKey($id) + { + return md5("{$this->keyNamespace}.$id"); + } +} diff --git a/src/core/libs/DebugBar/Storage/PdoStorage.php b/src/core/libs/DebugBar/Storage/PdoStorage.php new file mode 100755 index 0000000..e7695ef --- /dev/null +++ b/src/core/libs/DebugBar/Storage/PdoStorage.php @@ -0,0 +1,117 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Storage; + +use PDO; + +/** + * Stores collected data into a database using PDO + */ +class PdoStorage implements StorageInterface +{ + protected $pdo; + + protected $tableName; + + protected $sqlQueries = array( + 'save' => "INSERT INTO %tablename% (id, data, meta_utime, meta_datetime, meta_uri, meta_ip, meta_method) VALUES (?, ?, ?, ?, ?, ?, ?)", + 'get' => "SELECT data FROM %tablename% WHERE id = ?", + 'find' => "SELECT data FROM %tablename% %where% LIMIT %limit% OFFSET %offset%", + 'clear' => "DELETE FROM %tablename%" + ); + + /** + * @param string $dirname Directories where to store files + * @param array $sqlQueries + */ + public function __construct(PDO $pdo, $tableName = 'phpdebugbar', array $sqlQueries = array()) + { + $this->pdo = $pdo; + $this->tableName = $tableName; + $this->setSqlQueries($sqlQueries); + } + + /** + * Sets the sql queries to be used + * + * @param array $queries + */ + public function setSqlQueries(array $queries) + { + $this->sqlQueries = array_merge($this->sqlQueries, $queries); + } + + public function save($id, $data) + { + $sql = $this->getSqlQuery('save'); + $stmt = $this->pdo->prepare($sql); + $meta = $data['__meta']; + $stmt->execute(array($id, serialize($data), $meta['utime'], $meta['datetime'], $meta['uri'], $meta['ip'], $meta['method'])); + } + + public function get($id) + { + $sql = $this->getSqlQuery('get'); + $stmt = $this->pdo->prepare($sql); + $stmt->execute(array($id)); + if (($data = $stmt->fetchColumn(0)) !== false) { + return unserialize($data); + } + return null; + } + + public function find(array $filters = array(), $max = 20, $offset = 0) + { + $where = array(); + $params = array(); + foreach ($filters as $key => $value) { + $where[] = "meta_$key = ?"; + $params[] = $value; + } + if (count($where)) { + $where = " WHERE " . implode(' AND ', $where); + } else { + $where = ''; + } + + $sql = $this->getSqlQuery('find', array( + 'where' => $where, + 'offset' => $offset, + 'limit' => $max + )); + + $stmt = $this->pdo->prepare($sql); + $stmt->execute($params); + + $results = array(); + foreach ($stmt->fetchAll() as $row) { + $data = unserialize($row['data']); + $results[] = $data['__meta']; + unset($data); + } + return $results; + } + + public function clear() + { + $this->pdo->exec($this->getSqlQuery('clear')); + } + + protected function getSqlQuery($name, array $vars = array()) + { + $sql = $this->sqlQueries[$name]; + $vars = array_merge(array('tablename' => $this->tableName), $vars); + foreach ($vars as $k => $v) { + $sql = str_replace("%$k%", $v, $sql); + } + return $sql; + } +} diff --git a/src/core/libs/DebugBar/Storage/RedisStorage.php b/src/core/libs/DebugBar/Storage/RedisStorage.php new file mode 100755 index 0000000..42d8e3c --- /dev/null +++ b/src/core/libs/DebugBar/Storage/RedisStorage.php @@ -0,0 +1,74 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Storage; + +use Predis\Client; + +/** + * Stores collected data into Redis + */ +class RedisStorage implements StorageInterface +{ + protected $redis; + + protected $hash; + + /** + * @param string $dirname Directories where to store files + */ + public function __construct(Client $redis, $hash = 'phpdebugbar') + { + $this->redis = $redis; + $this->hash = $hash; + } + + public function save($id, $data) + { + $this->redis->hset($this->hash, $id, serialize($data)); + } + + public function get($id) + { + return unserialize($this->redis->hget($this->hash, $id)); + } + + public function find(array $filters = array(), $max = 20, $offset = 0) + { + $results = array(); + foreach ($this->redis->hgetall($this->hash) as $id => $data) { + if ($data = unserialize($data)) { + $meta = $data['__meta']; + if ($this->filter($meta, $filters)) { + $results[] = $meta; + } + } + } + return array_slice($results, $offset, $max); + } + + /** + * Filter the metadata for matches. + */ + protected function filter($meta, $filters) + { + foreach ($filters as $key => $value) { + if (!isset($meta[$key]) || fnmatch($value, $meta[$key]) === false) { + return false; + } + } + return true; + } + + public function clear() + { + $this->redis->del($this->hash); + } +} diff --git a/src/core/libs/DebugBar/Storage/StorageInterface.php b/src/core/libs/DebugBar/Storage/StorageInterface.php new file mode 100755 index 0000000..aef89bc --- /dev/null +++ b/src/core/libs/DebugBar/Storage/StorageInterface.php @@ -0,0 +1,45 @@ +<?php +/* + * This file is part of the DebugBar package. + * + * (c) 2013 Maxime Bouroumeau-Fuseau + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace DebugBar\Storage; + +interface StorageInterface +{ + /** + * Saves collected data + * + * @param string $id + * @param string $data + */ + function save($id, $data); + + /** + * Returns collected data with the specified id + * + * @param string $id + * @return array + */ + function get($id); + + /** + * Returns a metadata about collected data + * + * @param array $filters + * @param integer $max + * @param integer $offset + * @return array + */ + function find(array $filters = array(), $max = 20, $offset = 0); + + /** + * Clears all the collected data + */ + function clear(); +} diff --git a/src/core/libs/DebugBar/Storage/pdo_storage_schema.sql b/src/core/libs/DebugBar/Storage/pdo_storage_schema.sql new file mode 100755 index 0000000..4c1c107 --- /dev/null +++ b/src/core/libs/DebugBar/Storage/pdo_storage_schema.sql @@ -0,0 +1,16 @@ +CREATE TABLE phpdebugbar ( + id TEXT PRIMARY KEY, + data TEXT, + meta_utime TEXT, + meta_datetime TEXT, + meta_uri TEXT, + meta_ip TEXT, + meta_method TEXT +); + +CREATE INDEX idx_debugbar_id ON phpdebugbar (id); +CREATE INDEX idx_debugbar_meta_utime ON phpdebugbar (meta_utime); +CREATE INDEX idx_debugbar_meta_datetime ON phpdebugbar (meta_datetime); +CREATE INDEX idx_debugbar_meta_uri ON phpdebugbar (meta_uri); +CREATE INDEX idx_debugbar_meta_ip ON phpdebugbar (meta_ip); +CREATE INDEX idx_debugbar_meta_method ON phpdebugbar (meta_method); diff --git a/src/core/libs/Diff/Diff.php b/src/core/libs/Diff/Diff.php new file mode 100755 index 0000000..d1eb9da --- /dev/null +++ b/src/core/libs/Diff/Diff.php @@ -0,0 +1,179 @@ +<?php +/** + * Diff + * + * A comprehensive library for generating differences between two strings + * in multiple formats (unified, side by side HTML etc) + * + * PHP version 5 + * + * Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Chris Boulton nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package Diff + * @author Chris Boulton <chris.boulton@interspire.com> + * @copyright (c) 2009 Chris Boulton + * @license New BSD License http://www.opensource.org/licenses/bsd-license.php + * @version 1.1 + * @link http://github.com/chrisboulton/php-diff + */ + +class Diff +{ + /** + * @var array The "old" sequence to use as the basis for the comparison. + */ + private $a = null; + + /** + * @var array The "new" sequence to generate the changes for. + */ + private $b = null; + + /** + * @var array Array containing the generated opcodes for the differences between the two items. + */ + private $groupedCodes = null; + + /** + * @var array Associative array of the default options available for the diff class and their default value. + */ + private $defaultOptions = array( + 'context' => 3, + 'ignoreNewLines' => false, + 'ignoreWhitespace' => false, + 'ignoreCase' => false + ); + + /** + * @var array Array of the options that have been applied for generating the diff. + */ + private $options = array(); + + /** + * The constructor. + * + * @param array $a Array containing the lines of the first string to compare. + * @param array $b Array containing the lines for the second string to compare. + */ + public function __construct($a, $b, $options=array()) + { + $this->a = $a; + $this->b = $b; + + if (is_array($options)) + $this->options = array_merge($this->defaultOptions, $options); + else + $this->options = $this->defaultOptions; + } + + /** + * Render a diff using the supplied rendering class and return it. + * + * @param object $renderer An instance of the rendering object to use for generating the diff. + * @return mixed The generated diff. Exact return value depends on the rendered. + */ + public function render(Diff_Renderer_Abstract $renderer) + { + $renderer->diff = $this; + return $renderer->render(); + } + + /** + * Get a range of lines from $start to $end from the first comparison string + * and return them as an array. If no values are supplied, the entire string + * is returned. It's also possible to specify just one line to return only + * that line. + * + * @param int $start The starting number. + * @param int $end The ending number. If not supplied, only the item in $start will be returned. + * @return array Array of all of the lines between the specified range. + */ + public function getA($start=0, $end=null) + { + if($start == 0 && $end === null) { + return $this->a; + } + + if($end === null) { + $length = 1; + } + else { + $length = $end - $start; + } + + return array_slice($this->a, $start, $length); + + } + + /** + * Get a range of lines from $start to $end from the second comparison string + * and return them as an array. If no values are supplied, the entire string + * is returned. It's also possible to specify just one line to return only + * that line. + * + * @param int $start The starting number. + * @param int $end The ending number. If not supplied, only the item in $start will be returned. + * @return array Array of all of the lines between the specified range. + */ + public function getB($start=0, $end=null) + { + if($start == 0 && $end === null) { + return $this->b; + } + + if($end === null) { + $length = 1; + } + else { + $length = $end - $start; + } + + return array_slice($this->b, $start, $length); + } + + /** + * Generate a list of the compiled and grouped opcodes for the differences between the + * two strings. Generally called by the renderer, this class instantiates the sequence + * matcher and performs the actual diff generation and return an array of the opcodes + * for it. Once generated, the results are cached in the diff class instance. + * + * @return array Array of the grouped opcodes for the generated diff. + */ + public function getGroupedOpcodes() + { + if(!is_null($this->groupedCodes)) { + return $this->groupedCodes; + } + + require_once dirname(__FILE__).'/Diff/SequenceMatcher.php'; + $sequenceMatcher = new Diff_SequenceMatcher($this->a, $this->b, null, $this->options); + $this->groupedCodes = $sequenceMatcher->getGroupedOpcodes($this->options['context']); + return $this->groupedCodes; + } +} \ No newline at end of file diff --git a/src/core/libs/Diff/Diff/Renderer/Abstract.php b/src/core/libs/Diff/Diff/Renderer/Abstract.php new file mode 100755 index 0000000..f63c3e7 --- /dev/null +++ b/src/core/libs/Diff/Diff/Renderer/Abstract.php @@ -0,0 +1,82 @@ +<?php +/** + * Abstract class for diff renderers in PHP DiffLib. + * + * PHP version 5 + * + * Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Chris Boulton nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package DiffLib + * @author Chris Boulton <chris.boulton@interspire.com> + * @copyright (c) 2009 Chris Boulton + * @license New BSD License http://www.opensource.org/licenses/bsd-license.php + * @version 1.1 + * @link http://github.com/chrisboulton/php-diff + */ + +abstract class Diff_Renderer_Abstract +{ + /** + * @var object Instance of the diff class that this renderer is generating the rendered diff for. + */ + public $diff; + + /** + * @var array Array of the default options that apply to this renderer. + */ + protected $defaultOptions = array(); + + /** + * @var array Array containing the user applied and merged default options for the renderer. + */ + protected $options = array(); + + /** + * The constructor. Instantiates the rendering engine and if options are passed, + * sets the options for the renderer. + * + * @param array $options Optionally, an array of the options for the renderer. + */ + public function __construct(array $options = array()) + { + $this->setOptions($options); + } + + /** + * Set the options of the renderer to those supplied in the passed in array. + * Options are merged with the default to ensure that there aren't any missing + * options. + * + * @param array $options Array of options to set. + */ + public function setOptions(array $options) + { + $this->options = array_merge($this->defaultOptions, $options); + } +} \ No newline at end of file diff --git a/src/core/libs/Diff/Diff/Renderer/Html/Array.php b/src/core/libs/Diff/Diff/Renderer/Html/Array.php new file mode 100755 index 0000000..0b3f1d5 --- /dev/null +++ b/src/core/libs/Diff/Diff/Renderer/Html/Array.php @@ -0,0 +1,224 @@ +<?php +/** + * Base renderer for rendering HTML based diffs for PHP DiffLib. + * + * PHP version 5 + * + * Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Chris Boulton nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package DiffLib + * @author Chris Boulton <chris.boulton@interspire.com> + * @copyright (c) 2009 Chris Boulton + * @license New BSD License http://www.opensource.org/licenses/bsd-license.php + * @version 1.1 + * @link http://github.com/chrisboulton/php-diff + */ + +require_once dirname(__FILE__).'/../Abstract.php'; + +class Diff_Renderer_Html_Array extends Diff_Renderer_Abstract +{ + /** + * @var array Array of the default options that apply to this renderer. + */ + protected $defaultOptions = array( + 'tabSize' => 4 + ); + + /** + * Render and return an array structure suitable for generating HTML + * based differences. Generally called by subclasses that generate a + * HTML based diff and return an array of the changes to show in the diff. + * + * @return array An array of the generated chances, suitable for presentation in HTML. + */ + public function render() + { + // As we'll be modifying a & b to include our change markers, + // we need to get the contents and store them here. That way + // we're not going to destroy the original data + $a = $this->diff->getA(); + $b = $this->diff->getB(); + + $changes = array(); + $opCodes = $this->diff->getGroupedOpcodes(); + foreach($opCodes as $group) { + $blocks = array(); + $lastTag = null; + $lastBlock = 0; + foreach($group as $code) { + list($tag, $i1, $i2, $j1, $j2) = $code; + + if($tag == 'replace' && $i2 - $i1 == $j2 - $j1) { + for($i = 0; $i < ($i2 - $i1); ++$i) { + $fromLine = $a[$i1 + $i]; + $toLine = $b[$j1 + $i]; + + list($start, $end) = $this->getChangeExtent($fromLine, $toLine); + if($start != 0 || $end != 0) { + $last = $end + strlen($fromLine); + $fromLine = substr_replace($fromLine, "\0", $start, 0); + $fromLine = substr_replace($fromLine, "\1", $last + 1, 0); + $last = $end + strlen($toLine); + $toLine = substr_replace($toLine, "\0", $start, 0); + $toLine = substr_replace($toLine, "\1", $last + 1, 0); + $a[$i1 + $i] = $fromLine; + $b[$j1 + $i] = $toLine; + } + } + } + + if($tag != $lastTag) { + $blocks[] = array( + 'tag' => $tag, + 'base' => array( + 'offset' => $i1, + 'lines' => array() + ), + 'changed' => array( + 'offset' => $j1, + 'lines' => array() + ) + ); + $lastBlock = count($blocks)-1; + } + + $lastTag = $tag; + + if($tag == 'equal') { + $lines = array_slice($a, $i1, ($i2 - $i1)); + $blocks[$lastBlock]['base']['lines'] += $this->formatLines($lines); + $lines = array_slice($b, $j1, ($j2 - $j1)); + $blocks[$lastBlock]['changed']['lines'] += $this->formatLines($lines); + } + else { + if($tag == 'replace' || $tag == 'delete') { + $lines = array_slice($a, $i1, ($i2 - $i1)); + $lines = $this->formatLines($lines); + $lines = str_replace(array("\0", "\1"), array('<del>', '</del>'), $lines); + $blocks[$lastBlock]['base']['lines'] += $lines; + } + + if($tag == 'replace' || $tag == 'insert') { + $lines = array_slice($b, $j1, ($j2 - $j1)); + $lines = $this->formatLines($lines); + $lines = str_replace(array("\0", "\1"), array('<ins>', '</ins>'), $lines); + $blocks[$lastBlock]['changed']['lines'] += $lines; + } + } + } + $changes[] = $blocks; + } + return $changes; + } + + /** + * Given two strings, determine where the changes in the two strings + * begin, and where the changes in the two strings end. + * + * @param string $fromLine The first string. + * @param string $toLine The second string. + * @return array Array containing the starting position (0 by default) and the ending position (-1 by default) + */ + private function getChangeExtent($fromLine, $toLine) + { + $start = 0; + $limit = min(strlen($fromLine), strlen($toLine)); + while($start < $limit && $fromLine{$start} == $toLine{$start}) { + ++$start; + } + $end = -1; + $limit = $limit - $start; + while(-$end <= $limit && substr($fromLine, $end, 1) == substr($toLine, $end, 1)) { + --$end; + } + return array( + $start, + $end + 1 + ); + } + + /** + * Format a series of lines suitable for output in a HTML rendered diff. + * This involves replacing tab characters with spaces, making the HTML safe + * for output, ensuring that double spaces are replaced with &nbsp; etc. + * + * @param array $lines Array of lines to format. + * @return array Array of the formatted lines. + */ + private function formatLines($lines) + { + $lines = array_map(array($this, 'ExpandTabs'), $lines); + $lines = array_map(array($this, 'HtmlSafe'), $lines); + foreach($lines as &$line) { + $line = preg_replace('# ( +)|^ #e', "\$this->fixSpaces('\\1')", $line); + } + return $lines; + } + + /** + * Replace a string containing spaces with a HTML representation using &nbsp;. + * + * @param string $spaces The string of spaces. + * @return string The HTML representation of the string. + */ + function fixSpaces($spaces='') + { + $count = strlen($spaces); + if($count == 0) { + return ''; + } + + $div = floor($count / 2); + $mod = $count % 2; + return str_repeat('&nbsp; ', $div).str_repeat('&nbsp;', $mod); + } + + /** + * Replace tabs in a single line with a number of spaces as defined by the tabSize option. + * + * @param string $line The containing tabs to convert. + * @return string The line with the tabs converted to spaces. + */ + private function expandTabs($line) + { + return str_replace("\t", str_repeat(' ', $this->options['tabSize']), $line); + } + + /** + * Make a string containing HTML safe for output on a page. + * + * @param string $string The string. + * @return string The string with the HTML characters replaced by entities. + */ + private function htmlSafe($string) + { + return htmlspecialchars($string, ENT_NOQUOTES, 'UTF-8'); + } +} \ No newline at end of file diff --git a/src/core/libs/Diff/Diff/Renderer/Html/Inline.php b/src/core/libs/Diff/Diff/Renderer/Html/Inline.php new file mode 100755 index 0000000..60e8005 --- /dev/null +++ b/src/core/libs/Diff/Diff/Renderer/Html/Inline.php @@ -0,0 +1,143 @@ +<?php +/** + * Inline HTML diff generator for PHP DiffLib. + * + * PHP version 5 + * + * Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Chris Boulton nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package DiffLib + * @author Chris Boulton <chris.boulton@interspire.com> + * @copyright (c) 2009 Chris Boulton + * @license New BSD License http://www.opensource.org/licenses/bsd-license.php + * @version 1.1 + * @link http://github.com/chrisboulton/php-diff + */ + +require_once dirname(__FILE__).'/Array.php'; + +class Diff_Renderer_Html_Inline extends Diff_Renderer_Html_Array +{ + /** + * Render a and return diff with changes between the two sequences + * displayed inline (under each other) + * + * @return string The generated inline diff. + */ + public function render() + { + $changes = parent::render(); + $html = ''; + if(empty($changes)) { + return $html; + } + + $html .= '<table class="Differences DifferencesInline">'; + $html .= '<thead>'; + $html .= '<tr>'; + $html .= '<th>Old</th>'; + $html .= '<th>New</th>'; + $html .= '<th>Differences</th>'; + $html .= '</tr>'; + $html .= '</thead>'; + foreach($changes as $i => $blocks) { + // If this is a separate block, we're condensing code so output ..., + // indicating a significant portion of the code has been collapsed as + // it is the same + if($i > 0) { + $html .= '<tbody class="Skipped">'; + $html .= '<th>&hellip;</th>'; + $html .= '<th>&hellip;</th>'; + $html .= '<td>&nbsp;</td>'; + $html .= '</tbody>'; + } + + foreach($blocks as $change) { + $html .= '<tbody class="Change'.ucfirst($change['tag']).'">'; + // Equal changes should be shown on both sides of the diff + if($change['tag'] == 'equal') { + foreach($change['base']['lines'] as $no => $line) { + $fromLine = $change['base']['offset'] + $no + 1; + $toLine = $change['changed']['offset'] + $no + 1; + $html .= '<tr>'; + $html .= '<th>'.$fromLine.'</th>'; + $html .= '<th>'.$toLine.'</th>'; + $html .= '<td class="Left">'.$line.'</td>'; + $html .= '</tr>'; + } + } + // Added lines only on the right side + else if($change['tag'] == 'insert') { + foreach($change['changed']['lines'] as $no => $line) { + $toLine = $change['changed']['offset'] + $no + 1; + $html .= '<tr>'; + $html .= '<th>&nbsp;</th>'; + $html .= '<th>'.$toLine.'</th>'; + $html .= '<td class="Right"><ins>'.$line.'</ins>&nbsp;</td>'; + $html .= '</tr>'; + } + } + // Show deleted lines only on the left side + else if($change['tag'] == 'delete') { + foreach($change['base']['lines'] as $no => $line) { + $fromLine = $change['base']['offset'] + $no + 1; + $html .= '<tr>'; + $html .= '<th>'.$fromLine.'</th>'; + $html .= '<th>&nbsp;</th>'; + $html .= '<td class="Left"><del>'.$line.'</del>&nbsp;</td>'; + $html .= '</tr>'; + } + } + // Show modified lines on both sides + else if($change['tag'] == 'replace') { + foreach($change['base']['lines'] as $no => $line) { + $fromLine = $change['base']['offset'] + $no + 1; + $html .= '<tr>'; + $html .= '<th>'.$fromLine.'</th>'; + $html .= '<th>&nbsp;</th>'; + $html .= '<td class="Left"><span>'.$line.'</span></td>'; + $html .= '</tr>'; + } + + foreach($change['changed']['lines'] as $no => $line) { + $toLine = $change['changed']['offset'] + $no + 1; + $html .= '<tr>'; + $html .= '<th>'.$toLine.'</th>'; + $html .= '<th>&nbsp;</th>'; + $html .= '<td class="Right"><span>'.$line.'</span></td>'; + $html .= '</tr>'; + } + } + $html .= '</tbody>'; + } + } + $html .= '</table>'; + return $html; + } +} \ No newline at end of file diff --git a/src/core/libs/Diff/Diff/Renderer/Html/SideBySide.php b/src/core/libs/Diff/Diff/Renderer/Html/SideBySide.php new file mode 100755 index 0000000..ce8a5e5 --- /dev/null +++ b/src/core/libs/Diff/Diff/Renderer/Html/SideBySide.php @@ -0,0 +1,163 @@ +<?php +/** + * Side by Side HTML diff generator for PHP DiffLib. + * + * PHP version 5 + * + * Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Chris Boulton nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package DiffLib + * @author Chris Boulton <chris.boulton@interspire.com> + * @copyright (c) 2009 Chris Boulton + * @license New BSD License http://www.opensource.org/licenses/bsd-license.php + * @version 1.1 + * @link http://github.com/chrisboulton/php-diff + */ + +require_once dirname(__FILE__).'/Array.php'; + +class Diff_Renderer_Html_SideBySide extends Diff_Renderer_Html_Array +{ + /** + * Render a and return diff with changes between the two sequences + * displayed side by side. + * + * @return string The generated side by side diff. + */ + public function render() + { + $changes = parent::render(); + + $html = ''; + if(empty($changes)) { + return $html; + } + + $html .= '<table class="Differences DifferencesSideBySide">'; + $html .= '<thead>'; + $html .= '<tr>'; + $html .= '<th colspan="2">Versione A</th>'; + $html .= '<th colspan="2">Versione B</th>'; + $html .= '</tr>'; + $html .= '</thead>'; + foreach($changes as $i => $blocks) { + if($i > 0) { + $html .= '<tbody class="Skipped">'; + $html .= '<th>&hellip;</th><td>&nbsp;</td>'; + $html .= '<th>&hellip;</th><td>&nbsp;</td>'; + $html .= '</tbody>'; + } + + foreach($blocks as $change) { + $html .= '<tbody class="Change'.ucfirst($change['tag']).'">'; + // Equal changes should be shown on both sides of the diff + if($change['tag'] == 'equal') { + foreach($change['base']['lines'] as $no => $line) { + $fromLine = $change['base']['offset'] + $no + 1; + $toLine = $change['changed']['offset'] + $no + 1; + $html .= '<tr>'; + $html .= '<th>'.$fromLine.'</th>'; + $html .= '<td class="Left"><span>'.$line.'</span>&nbsp;</span></td>'; + $html .= '<th>'.$toLine.'</th>'; + $html .= '<td class="Right"><span>'.$line.'</span>&nbsp;</span></td>'; + $html .= '</tr>'; + } + } + // Added lines only on the right side + else if($change['tag'] == 'insert') { + foreach($change['changed']['lines'] as $no => $line) { + $toLine = $change['changed']['offset'] + $no + 1; + $html .= '<tr>'; + $html .= '<th>&nbsp;</th>'; + $html .= '<td class="Left">&nbsp;</td>'; + $html .= '<th>'.$toLine.'</th>'; + $html .= '<td class="Right"><ins>'.$line.'</ins>&nbsp;</td>'; + $html .= '</tr>'; + } + } + // Show deleted lines only on the left side + else if($change['tag'] == 'delete') { + foreach($change['base']['lines'] as $no => $line) { + $fromLine = $change['base']['offset'] + $no + 1; + $html .= '<tr>'; + $html .= '<th>'.$fromLine.'</th>'; + $html .= '<td class="Left"><del>'.$line.'</del>&nbsp;</td>'; + $html .= '<th>&nbsp;</th>'; + $html .= '<td class="Right">&nbsp;</td>'; + $html .= '</tr>'; + } + } + // Show modified lines on both sides + else if($change['tag'] == 'replace') { + if(count($change['base']['lines']) >= count($change['changed']['lines'])) { + foreach($change['base']['lines'] as $no => $line) { + $fromLine = $change['base']['offset'] + $no + 1; + $html .= '<tr>'; + $html .= '<th>'.$fromLine.'</th>'; + $html .= '<td class="Left"><span>'.$line.'</span>&nbsp;</td>'; + if(!isset($change['changed']['lines'][$no])) { + $toLine = '&nbsp;'; + $changedLine = '&nbsp;'; + } + else { + $toLine = $change['base']['offset'] + $no + 1; + $changedLine = '<span>'.$change['changed']['lines'][$no].'</span>'; + } + $html .= '<th>'.$toLine.'</th>'; + $html .= '<td class="Right">'.$changedLine.'</td>'; + $html .= '</tr>'; + } + } + else { + foreach($change['changed']['lines'] as $no => $changedLine) { + if(!isset($change['base']['lines'][$no])) { + $fromLine = '&nbsp;'; + $line = '&nbsp;'; + } + else { + $fromLine = $change['base']['offset'] + $no + 1; + $line = '<span>'.$change['base']['lines'][$no].'</span>'; + } + $html .= '<tr>'; + $html .= '<th>'.$fromLine.'</th>'; + $html .= '<td class="Left"><span>'.$line.'</span>&nbsp;</td>'; + $toLine = $change['changed']['offset'] + $no + 1; + $html .= '<th>'.$toLine.'</th>'; + $html .= '<td class="Right">'.$changedLine.'</td>'; + $html .= '</tr>'; + } + } + } + $html .= '</tbody>'; + } + } + $html .= '</table>'; + return $html; + } +} \ No newline at end of file diff --git a/src/core/libs/Diff/Diff/Renderer/Text/Context.php b/src/core/libs/Diff/Diff/Renderer/Text/Context.php new file mode 100755 index 0000000..1200b01 --- /dev/null +++ b/src/core/libs/Diff/Diff/Renderer/Text/Context.php @@ -0,0 +1,128 @@ +<?php +/** + * Context diff generator for PHP DiffLib. + * + * PHP version 5 + * + * Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Chris Boulton nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package DiffLib + * @author Chris Boulton <chris.boulton@interspire.com> + * @copyright (c) 2009 Chris Boulton + * @license New BSD License http://www.opensource.org/licenses/bsd-license.php + * @version 1.1 + * @link http://github.com/chrisboulton/php-diff + */ + +require_once dirname(__FILE__).'/../Abstract.php'; + +class Diff_Renderer_Text_Context extends Diff_Renderer_Abstract +{ + /** + * @var array Array of the different opcode tags and how they map to the context diff equivalent. + */ + private $tagMap = array( + 'insert' => '+', + 'delete' => '-', + 'replace' => '!', + 'equal' => ' ' + ); + + /** + * Render and return a context formatted (old school!) diff file. + * + * @return string The generated context diff. + */ + public function render() + { + $diff = ''; + $opCodes = $this->diff->getGroupedOpcodes(); + foreach($opCodes as $group) { + $diff .= "***************\n"; + $lastItem = count($group)-1; + $i1 = $group[0][1]; + $i2 = $group[$lastItem][2]; + $j1 = $group[0][3]; + $j2 = $group[$lastItem][4]; + + if($i2 - $i1 >= 2) { + $diff .= '*** '.($group[0][1] + 1).','.$i2." ****\n"; + } + else { + $diff .= '*** '.$i2." ****\n"; + } + + if($j2 - $j1 >= 2) { + $separator = '--- '.($j1 + 1).','.$j2." ----\n"; + } + else { + $separator = '--- '.$j2." ----\n"; + } + + $hasVisible = false; + foreach($group as $code) { + if($code[0] == 'replace' || $code[0] == 'delete') { + $hasVisible = true; + break; + } + } + + if($hasVisible) { + foreach($group as $code) { + list($tag, $i1, $i2, $j1, $j2) = $code; + if($tag == 'insert') { + continue; + } + $diff .= $this->tagMap[$tag].' '.implode("\n".$this->tagMap[$tag].' ', $this->diff->GetA($i1, $i2))."\n"; + } + } + + $hasVisible = false; + foreach($group as $code) { + if($code[0] == 'replace' || $code[0] == 'insert') { + $hasVisible = true; + break; + } + } + + $diff .= $separator; + + if($hasVisible) { + foreach($group as $code) { + list($tag, $i1, $i2, $j1, $j2) = $code; + if($tag == 'delete') { + continue; + } + $diff .= $this->tagMap[$tag].' '.implode("\n".$this->tagMap[$tag].' ', $this->diff->GetB($j1, $j2))."\n"; + } + } + } + return $diff; + } +} \ No newline at end of file diff --git a/src/core/libs/Diff/Diff/Renderer/Text/Unified.php b/src/core/libs/Diff/Diff/Renderer/Text/Unified.php new file mode 100755 index 0000000..e94d951 --- /dev/null +++ b/src/core/libs/Diff/Diff/Renderer/Text/Unified.php @@ -0,0 +1,87 @@ +<?php +/** + * Unified diff generator for PHP DiffLib. + * + * PHP version 5 + * + * Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Chris Boulton nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package DiffLib + * @author Chris Boulton <chris.boulton@interspire.com> + * @copyright (c) 2009 Chris Boulton + * @license New BSD License http://www.opensource.org/licenses/bsd-license.php + * @version 1.1 + * @link http://github.com/chrisboulton/php-diff + */ + +require_once dirname(__FILE__).'/../Abstract.php'; + +class Diff_Renderer_Text_Unified extends Diff_Renderer_Abstract +{ + /** + * Render and return a unified diff. + * + * @return string The unified diff. + */ + public function render() + { + $diff = ''; + $opCodes = $this->diff->getGroupedOpcodes(); + foreach($opCodes as $group) { + $lastItem = count($group)-1; + $i1 = $group[0][1]; + $i2 = $group[$lastItem][2]; + $j1 = $group[0][3]; + $j2 = $group[$lastItem][4]; + + if($i1 == 0 && $i2 == 0) { + $i1 = -1; + $i2 = -1; + } + + $diff .= '@@ -'.($i1 + 1).','.($i2 - $i1).' +'.($j1 + 1).','.($j2 - $j1)." @@\n"; + foreach($group as $code) { + list($tag, $i1, $i2, $j1, $j2) = $code; + if($tag == 'equal') { + $diff .= ' '.implode("\n ", $this->diff->GetA($i1, $i2))."\n"; + } + else { + if($tag == 'replace' || $tag == 'delete') { + $diff .= '-'.implode("\n-", $this->diff->GetA($i1, $i2))."\n"; + } + + if($tag == 'replace' || $tag == 'insert') { + $diff .= '+'.implode("\n+", $this->diff->GetB($j1, $j2))."\n"; + } + } + } + } + return $diff; + } +} \ No newline at end of file diff --git a/src/core/libs/Diff/Diff/SequenceMatcher.php b/src/core/libs/Diff/Diff/SequenceMatcher.php new file mode 100755 index 0000000..e819e81 --- /dev/null +++ b/src/core/libs/Diff/Diff/SequenceMatcher.php @@ -0,0 +1,742 @@ +<?php +/** + * Sequence matcher for Diff + * + * PHP version 5 + * + * Copyright (c) 2009 Chris Boulton <chris.boulton@interspire.com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the Chris Boulton nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * @package Diff + * @author Chris Boulton <chris.boulton@interspire.com> + * @copyright (c) 2009 Chris Boulton + * @license New BSD License http://www.opensource.org/licenses/bsd-license.php + * @version 1.1 + * @link http://github.com/chrisboulton/php-diff + */ + +class Diff_SequenceMatcher +{ + /** + * @var string|array Either a string or an array containing a callback function to determine if a line is "junk" or not. + */ + private $junkCallback = null; + + /** + * @var array The first sequence to compare against. + */ + private $a = null; + + /** + * @var array The second sequence. + */ + private $b = null; + + /** + * @var array Array of characters that are considered junk from the second sequence. Characters are the array key. + */ + private $junkDict = array(); + + /** + * @var array Array of indices that do not contain junk elements. + */ + private $b2j = array(); + + private $options = array(); + + private $defaultOptions = array( + 'ignoreNewLines' => false, + 'ignoreWhitespace' => false, + 'ignoreCase' => false + ); + + /** + * The constructor. With the sequences being passed, they'll be set for the + * sequence matcher and it will perform a basic cleanup & calculate junk + * elements. + * + * @param string|array $a A string or array containing the lines to compare against. + * @param string|array $b A string or array containing the lines to compare. + * @param string|array $junkCallback Either an array or string that references a callback function (if there is one) to determine 'junk' characters. + */ + public function __construct($a, $b, $junkCallback=null, $options) + { + $this->a = null; + $this->b = null; + $this->junkCallback = $junkCallback; + $this->setOptions($options); + $this->setSequences($a, $b); + } + + public function setOptions($options) + { + $this->options = array_merge($this->defaultOptions, $options); + } + + /** + * Set the first and second sequences to use with the sequence matcher. + * + * @param string|array $a A string or array containing the lines to compare against. + * @param string|array $b A string or array containing the lines to compare. + */ + public function setSequences($a, $b) + { + $this->setSeq1($a); + $this->setSeq2($b); + } + + /** + * Set the first sequence ($a) and reset any internal caches to indicate that + * when calling the calculation methods, we need to recalculate them. + * + * @param string|array $a The sequence to set as the first sequence. + */ + public function setSeq1($a) + { + if(!is_array($a)) { + $a = str_split($a); + } + if($a == $this->a) { + return; + } + + $this->a= $a; + $this->matchingBlocks = null; + $this->opCodes = null; + } + + /** + * Set the second sequence ($b) and reset any internal caches to indicate that + * when calling the calculation methods, we need to recalculate them. + * + * @param string|array $b The sequence to set as the second sequence. + */ + public function setSeq2($b) + { + if(!is_array($b)) { + $b = str_split($b); + } + if($b == $this->b) { + return; + } + + $this->b = $b; + $this->matchingBlocks = null; + $this->opCodes = null; + $this->fullBCount = null; + $this->chainB(); + } + + /** + * Generate the internal arrays containing the list of junk and non-junk + * characters for the second ($b) sequence. + */ + private function chainB() + { + $length = count ($this->b); + $this->b2j = array(); + $popularDict = array(); + + for($i = 0; $i < $length; ++$i) { + $char = $this->b[$i]; + if(isset($this->b2j[$char])) { + if($length >= 200 && count($this->b2j[$char]) * 100 > $length) { + $popularDict[$char] = 1; + unset($this->b2j[$char]); + } + else { + $this->b2j[$char][] = $i; + } + } + else { + $this->b2j[$char] = array( + $i + ); + } + } + + // Remove leftovers + foreach(array_keys($popularDict) as $char) { + unset($this->b2j[$char]); + } + + $this->junkDict = array(); + if(is_callable($this->junkCallback)) { + foreach(array_keys($popularDict) as $char) { + if(call_user_func($this->junkCallback, $char)) { + $this->junkDict[$char] = 1; + unset($popularDict[$char]); + } + } + + foreach(array_keys($this->b2j) as $char) { + if(call_user_func($this->junkCallback, $char)) { + $this->junkDict[$char] = 1; + unset($this->b2j[$char]); + } + } + } + } + + /** + * Checks if a particular character is in the junk dictionary + * for the list of junk characters. + * + * @return boolean $b True if the character is considered junk. False if not. + */ + private function isBJunk($b) + { + if(isset($this->juncDict[$b])) { + return true; + } + + return false; + } + + /** + * Find the longest matching block in the two sequences, as defined by the + * lower and upper constraints for each sequence. (for the first sequence, + * $alo - $ahi and for the second sequence, $blo - $bhi) + * + * Essentially, of all of the maximal matching blocks, return the one that + * startest earliest in $a, and all of those maximal matching blocks that + * start earliest in $a, return the one that starts earliest in $b. + * + * If the junk callback is defined, do the above but with the restriction + * that the junk element appears in the block. Extend it as far as possible + * by matching only junk elements in both $a and $b. + * + * @param int $alo The lower constraint for the first sequence. + * @param int $ahi The upper constraint for the first sequence. + * @param int $blo The lower constraint for the second sequence. + * @param int $bhi The upper constraint for the second sequence. + * @return array Array containing the longest match that includes the starting position in $a, start in $b and the length/size. + */ + public function findLongestMatch($alo, $ahi, $blo, $bhi) + { + $a = $this->a; + $b = $this->b; + + $bestI = $alo; + $bestJ = $blo; + $bestSize = 0; + + $j2Len = array(); + $nothing = array(); + + for($i = $alo; $i < $ahi; ++$i) { + $newJ2Len = array(); + $jDict = $this->arrayGetDefault($this->b2j, $a[$i], $nothing); + foreach($jDict as $jKey => $j) { + if($j < $blo) { + continue; + } + else if($j >= $bhi) { + break; + } + + $k = $this->arrayGetDefault($j2Len, $j -1, 0) + 1; + $newJ2Len[$j] = $k; + if($k > $bestSize) { + $bestI = $i - $k + 1; + $bestJ = $j - $k + 1; + $bestSize = $k; + } + } + + $j2Len = $newJ2Len; + } + + while($bestI > $alo && $bestJ > $blo && !$this->isBJunk($b[$bestJ - 1]) && + !$this->linesAreDifferent($bestI - 1, $bestJ - 1)) { + --$bestI; + --$bestJ; + ++$bestSize; + } + + while($bestI + $bestSize < $ahi && ($bestJ + $bestSize) < $bhi && + !$this->isBJunk($b[$bestJ + $bestSize]) && !$this->linesAreDifferent($bestI + $bestSize, $bestJ + $bestSize)) { + ++$bestSize; + } + + while($bestI > $alo && $bestJ > $blo && $this->isBJunk($b[$bestJ - 1]) && + !$this->isLineDifferent($bestI - 1, $bestJ - 1)) { + --$bestI; + --$bestJ; + ++$bestSize; + } + + while($bestI + $bestSize < $ahi && $bestJ + $bestSize < $bhi && + $this->isBJunk($b[$bestJ + $bestSize]) && !$this->linesAreDifferent($bestI + $bestSize, $bestJ + $bestSize)) { + ++$bestSize; + } + + return array( + $bestI, + $bestJ, + $bestSize + ); + } + + /** + * Check if the two lines at the given indexes are different or not. + * + * @param int $aIndex Line number to check against in a. + * @param int $bIndex Line number to check against in b. + * @return boolean True if the lines are different and false if not. + */ + public function linesAreDifferent($aIndex, $bIndex) + { + $lineA = $this->a[$aIndex]; + $lineB = $this->b[$bIndex]; + + if($this->options['ignoreWhitespace']) { + $replace = array("\t", ' '); + $lineA = str_replace($replace, '', $lineA); + $lineB = str_replace($replace, '', $lineB); + } + + if($this->options['ignoreCase']) { + $lineA = strtolower($lineA); + $lineB = strtolower($lineB); + } + + if($lineA != $lineB) { + return true; + } + + return false; + } + + /** + * Return a nested set of arrays for all of the matching sub-sequences + * in the strings $a and $b. + * + * Each block contains the lower constraint of the block in $a, the lower + * constraint of the block in $b and finally the number of lines that the + * block continues for. + * + * @return array Nested array of the matching blocks, as described by the function. + */ + public function getMatchingBlocks() + { + if(!empty($this->matchingBlocks)) { + return $this->matchingBlocks; + } + + $aLength = count($this->a); + $bLength = count($this->b); + + $queue = array( + array( + 0, + $aLength, + 0, + $bLength + ) + ); + + $matchingBlocks = array(); + while(!empty($queue)) { + list($alo, $ahi, $blo, $bhi) = array_pop($queue); + $x = $this->findLongestMatch($alo, $ahi, $blo, $bhi); + list($i, $j, $k) = $x; + if($k) { + $matchingBlocks[] = $x; + if($alo < $i && $blo < $j) { + $queue[] = array( + $alo, + $i, + $blo, + $j + ); + } + + if($i + $k < $ahi && $j + $k < $bhi) { + $queue[] = array( + $i + $k, + $ahi, + $j + $k, + $bhi + ); + } + } + } + + usort($matchingBlocks, array($this, 'tupleSort')); + + $i1 = 0; + $j1 = 0; + $k1 = 0; + $nonAdjacent = array(); + foreach($matchingBlocks as $block) { + list($i2, $j2, $k2) = $block; + if($i1 + $k1 == $i2 && $j1 + $k1 == $j2) { + $k1 += $k2; + } + else { + if($k1) { + $nonAdjacent[] = array( + $i1, + $j1, + $k1 + ); + } + + $i1 = $i2; + $j1 = $j2; + $k1 = $k2; + } + } + + if($k1) { + $nonAdjacent[] = array( + $i1, + $j1, + $k1 + ); + } + + $nonAdjacent[] = array( + $aLength, + $bLength, + 0 + ); + + $this->matchingBlocks = $nonAdjacent; + return $this->matchingBlocks; + } + + /** + * Return a list of all of the opcodes for the differences between the + * two strings. + * + * The nested array returned contains an array describing the opcode + * which includes: + * 0 - The type of tag (as described below) for the opcode. + * 1 - The beginning line in the first sequence. + * 2 - The end line in the first sequence. + * 3 - The beginning line in the second sequence. + * 4 - The end line in the second sequence. + * + * The different types of tags include: + * replace - The string from $i1 to $i2 in $a should be replaced by + * the string in $b from $j1 to $j2. + * delete - The string in $a from $i1 to $j2 should be deleted. + * insert - The string in $b from $j1 to $j2 should be inserted at + * $i1 in $a. + * equal - The two strings with the specified ranges are equal. + * + * @return array Array of the opcodes describing the differences between the strings. + */ + public function getOpCodes() + { + if(!empty($this->opCodes)) { + return $this->opCodes; + } + + $i = 0; + $j = 0; + $this->opCodes = array(); + + $blocks = $this->getMatchingBlocks(); + foreach($blocks as $block) { + list($ai, $bj, $size) = $block; + $tag = ''; + if($i < $ai && $j < $bj) { + $tag = 'replace'; + } + else if($i < $ai) { + $tag = 'delete'; + } + else if($j < $bj) { + $tag = 'insert'; + } + + if($tag) { + $this->opCodes[] = array( + $tag, + $i, + $ai, + $j, + $bj + ); + } + + $i = $ai + $size; + $j = $bj + $size; + + if($size) { + $this->opCodes[] = array( + 'equal', + $ai, + $i, + $bj, + $j + ); + } + } + return $this->opCodes; + } + + /** + * Return a series of nested arrays containing different groups of generated + * opcodes for the differences between the strings with up to $context lines + * of surrounding content. + * + * Essentially what happens here is any big equal blocks of strings are stripped + * out, the smaller subsets of changes are then arranged in to their groups. + * This means that the sequence matcher and diffs do not need to include the full + * content of the different files but can still provide context as to where the + * changes are. + * + * @param int $context The number of lines of context to provide around the groups. + * @return array Nested array of all of the grouped opcodes. + */ + public function getGroupedOpcodes($context=3) + { + $opCodes = $this->getOpCodes(); + if(empty($opCodes)) { + $opCodes = array( + array( + 'equal', + 0, + 1, + 0, + 1 + ) + ); + } + + if($opCodes[0][0] == 'equal') { + $opCodes[0] = array( + $opCodes[0][0], + max($opCodes[0][1], $opCodes[0][2] - $context), + $opCodes[0][2], + max($opCodes[0][3], $opCodes[0][4] - $context), + $opCodes[0][4] + ); + } + + $lastItem = count($opCodes) - 1; + if($opCodes[$lastItem][0] == 'equal') { + list($tag, $i1, $i2, $j1, $j2) = $opCodes[$lastItem]; + $opCodes[$lastItem] = array( + $tag, + $i1, + min($i2, $i1 + $context), + $j1, + min($j2, $j1 + $context) + ); + } + + $maxRange = $context * 2; + $groups = array(); + $group = array(); + foreach($opCodes as $code) { + list($tag, $i1, $i2, $j1, $j2) = $code; + if($tag == 'equal' && $i2 - $i1 > $maxRange) { + $group[] = array( + $tag, + $i1, + min($i2, $i1 + $context), + $j1, + min($j2, $j1 + $context) + ); + $groups[] = $group; + $group = array(); + $i1 = max($i1, $i2 - $context); + $j1 = max($j1, $j2 - $context); + } + $group[] = array( + $tag, + $i1, + $i2, + $j1, + $j2 + ); + } + + if(!empty($group) && !(count($group) == 1 && $group[0][0] == 'equal')) { + $groups[] = $group; + } + + return $groups; + } + + /** + * Return a measure of the similarity between the two sequences. + * This will be a float value between 0 and 1. + * + * Out of all of the ratio calculation functions, this is the most + * expensive to call if getMatchingBlocks or getOpCodes is yet to be + * called. The other calculation methods (quickRatio and realquickRatio) + * can be used to perform quicker calculations but may be less accurate. + * + * The ratio is calculated as (2 * number of matches) / total number of + * elements in both sequences. + * + * @return float The calculated ratio. + */ + public function Ratio() + { + $matches = array_reduce($this->getMatchingBlocks(), array($this, 'ratioReduce'), 0); + return $this->calculateRatio($matches, count ($this->a) + count ($this->b)); + } + + /** + * Helper function to calculate the number of matches for Ratio(). + * + * @param int $sum The running total for the number of matches. + * @param array $triple Array containing the matching block triple to add to the running total. + * @return int The new running total for the number of matches. + */ + private function ratioReduce($sum, $triple) + { + return $sum + ($triple[count($triple) - 1]); + } + + /** + * Quickly return an upper bound ratio for the similarity of the strings. + * This is quicker to compute than Ratio(). + * + * @return float The calculated ratio. + */ + private function quickRatio() + { + if($this->fullBCount === null) { + $this->fullBCount = array(); + $bLength = count ($b); + for($i = 0; $i < $bLength; ++$i) { + $char = $this->b[$i]; + $this->fullBCount[$char] = $this->arrayGetDefault($this->fullBCount, $char, 0) + 1; + } + } + + $avail = array(); + $matches = 0; + $aLength = count ($this->a); + for($i = 0; $i < $aLength; ++$i) { + $char = $this->a[$i]; + if(isset($avail[$char])) { + $numb = $avail[$char]; + } + else { + $numb = $this->arrayGetDefault($this->fullBCount, $char, 0); + } + $avail[$char] = $numb - 1; + if($numb > 0) { + ++$matches; + } + } + + $this->calculateRatio($matches, count ($this->a) + count ($this->b)); + } + + /** + * Return an upper bound ratio really quickly for the similarity of the strings. + * This is quicker to compute than Ratio() and quickRatio(). + * + * @return float The calculated ratio. + */ + private function realquickRatio() + { + $aLength = count ($this->a); + $bLength = count ($this->b); + + return $this->calculateRatio(min($aLength, $bLength), $aLength + $bLength); + } + + /** + * Helper function for calculating the ratio to measure similarity for the strings. + * The ratio is defined as being 2 * (number of matches / total length) + * + * @param int $matches The number of matches in the two strings. + * @param int $length The length of the two strings. + * @return float The calculated ratio. + */ + private function calculateRatio($matches, $length=0) + { + if($length) { + return 2 * ($matches / $length); + } + else { + return 1; + } + } + + /** + * Helper function that provides the ability to return the value for a key + * in an array of it exists, or if it doesn't then return a default value. + * Essentially cleaner than doing a series of if(isset()) {} else {} calls. + * + * @param array $array The array to search. + * @param string $key The key to check that exists. + * @param mixed $default The value to return as the default value if the key doesn't exist. + * @return mixed The value from the array if the key exists or otherwise the default. + */ + private function arrayGetDefault($array, $key, $default) + { + if(isset($array[$key])) { + return $array[$key]; + } + else { + return $default; + } + } + + /** + * Sort an array by the nested arrays it contains. Helper function for getMatchingBlocks + * + * @param array $a First array to compare. + * @param array $b Second array to compare. + * @return int -1, 0 or 1, as expected by the usort function. + */ + private function tupleSort($a, $b) + { + $max = max(count($a), count($b)); + for($i = 0; $i < $max; ++$i) { + if($a[$i] < $b[$i]) { + return -1; + } + else if($a[$i] > $b[$i]) { + return 1; + } + } + + if(count($a) == $count($b)) { + return 0; + } + else if(count($a) < count($b)) { + return -1; + } + else { + return 1; + } + } +} \ No newline at end of file diff --git a/src/core/libs/Doctrine/Common/Annotations/Annotation.php b/src/core/libs/Doctrine/Common/Annotations/Annotation.php new file mode 100644 index 0000000..6a1390a --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/Annotation.php @@ -0,0 +1,79 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +/** + * Annotations class + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class Annotation +{ + /** + * Value property. Common among all derived classes. + * + * @var string + */ + public $value; + + /** + * Constructor + * + * @param array $data Key-value for properties to be defined in this class + */ + public final function __construct(array $data) + { + foreach ($data as $key => $value) { + $this->$key = $value; + } + } + + /** + * Error handler for unknown property accessor in Annotation class. + * + * @param string $name Unknown property name + * + * @throws \BadMethodCallException + */ + public function __get($name) + { + throw new \BadMethodCallException( + sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this)) + ); + } + + /** + * Error handler for unknown property mutator in Annotation class. + * + * @param string $name Unkown property name + * @param mixed $value Property value + * + * @throws \BadMethodCallException + */ + public function __set($name, $value) + { + throw new \BadMethodCallException( + sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this)) + ); + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/Annotation/Attribute.php b/src/core/libs/Doctrine/Common/Annotations/Annotation/Attribute.php new file mode 100644 index 0000000..dbef6df --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/Annotation/Attribute.php @@ -0,0 +1,47 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations\Annotation; + +/** + * Annotation that can be used to signal to the parser + * to check the attribute type during the parsing process. + * + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> + * + * @Annotation + */ +final class Attribute +{ + /** + * @var string + */ + public $name; + + /** + * @var string + */ + public $type; + + /** + * @var boolean + */ + public $required = false; +} diff --git a/src/core/libs/Doctrine/Common/Annotations/Annotation/Attributes.php b/src/core/libs/Doctrine/Common/Annotations/Annotation/Attributes.php new file mode 100644 index 0000000..53134e3 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/Annotation/Attributes.php @@ -0,0 +1,37 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations\Annotation; + +/** + * Annotation that can be used to signal to the parser + * to check the types of all declared attributes during the parsing process. + * + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> + * + * @Annotation + */ +final class Attributes +{ + /** + * @var array<Doctrine\Common\Annotations\Annotation\Attribute> + */ + public $value; +} diff --git a/src/core/libs/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php b/src/core/libs/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php new file mode 100644 index 0000000..a84a4f5 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php @@ -0,0 +1,54 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations\Annotation; + +/** + * Annotation that can be used to signal to the parser to ignore specific + * annotations during the parsing process. + * + * @Annotation + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +final class IgnoreAnnotation +{ + /** + * @var array + */ + public $names; + + /** + * Constructor + * + * @param array $values + * + * @throws \RuntimeException + */ + public function __construct(array $values) + { + if (is_string($values['value'])) { + $values['value'] = array($values['value']); + } + if (!is_array($values['value'])) { + throw new \RuntimeException(sprintf('@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.', json_encode($values['value']))); + } + + $this->names = $values['value']; + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/Annotation/Required.php b/src/core/libs/Doctrine/Common/Annotations/Annotation/Required.php new file mode 100644 index 0000000..d67f960 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/Annotation/Required.php @@ -0,0 +1,33 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations\Annotation; + +/** + * Annotation that can be used to signal to the parser + * to check if that attribute is required during the parsing process. + * + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> + * + * @Annotation + */ +final class Required +{ +} diff --git a/src/core/libs/Doctrine/Common/Annotations/Annotation/Target.php b/src/core/libs/Doctrine/Common/Annotations/Annotation/Target.php new file mode 100644 index 0000000..64655ef --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/Annotation/Target.php @@ -0,0 +1,107 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations\Annotation; + +/** + * Annotation that can be used to signal to the parser + * to check the annotation target during the parsing process. + * + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> + * + * @Annotation + */ +final class Target +{ + const TARGET_CLASS = 1; + const TARGET_METHOD = 2; + const TARGET_PROPERTY = 4; + const TARGET_ANNOTATION = 8; + const TARGET_ALL = 15; + + /** + * @var array + */ + private static $map = array( + 'ALL' => self::TARGET_ALL, + 'CLASS' => self::TARGET_CLASS, + 'METHOD' => self::TARGET_METHOD, + 'PROPERTY' => self::TARGET_PROPERTY, + 'ANNOTATION' => self::TARGET_ANNOTATION, + ); + + /** + * @var array + */ + public $value; + + /** + * Targets as bitmask. + * + * @var integer + */ + public $targets; + + /** + * Literal target declaration. + * + * @var integer + */ + public $literal; + + /** + * Annotation construct + * + * @param array $values + * + * @throws \InvalidArgumentException + */ + public function __construct(array $values) + { + if (!isset($values['value'])){ + $values['value'] = null; + } + if (is_string($values['value'])){ + $values['value'] = array($values['value']); + } + if (!is_array($values['value'])){ + throw new \InvalidArgumentException( + sprintf('@Target expects either a string value, or an array of strings, "%s" given.', + is_object($values['value']) ? get_class($values['value']) : gettype($values['value']) + ) + ); + } + + $bitmask = 0; + foreach ($values['value'] as $literal) { + if(!isset(self::$map[$literal])){ + throw new \InvalidArgumentException( + sprintf('Invalid Target "%s". Available targets: [%s]', + $literal, implode(', ', array_keys(self::$map))) + ); + } + $bitmask += self::$map[$literal]; + } + + $this->targets = $bitmask; + $this->value = $values['value']; + $this->literal = implode(', ', $this->value); + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/AnnotationException.php b/src/core/libs/Doctrine/Common/Annotations/AnnotationException.php new file mode 100644 index 0000000..109beeb --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/AnnotationException.php @@ -0,0 +1,127 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +/** + * Description of AnnotationException + * + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class AnnotationException extends \Exception +{ + /** + * Creates a new AnnotationException describing a Syntax error. + * + * @param string $message Exception message + * @return AnnotationException + */ + public static function syntaxError($message) + { + return new self('[Syntax Error] ' . $message); + } + + /** + * Creates a new AnnotationException describing a Semantical error. + * + * @param string $message Exception message + * @return AnnotationException + */ + public static function semanticalError($message) + { + return new self('[Semantical Error] ' . $message); + } + + /** + * Creates a new AnnotationException describing a constant semantical error. + * + * @since 2.3 + * @param string $identifier + * @param string $context + * @return AnnotationException + */ + public static function semanticalErrorConstants($identifier, $context = null) + { + return self::semanticalError(sprintf( + "Couldn't find constant %s%s", $identifier, + $context ? ", $context." : "." + )); + } + + /** + * Creates a new AnnotationException describing an error which occurred during + * the creation of the annotation. + * + * @since 2.2 + * @param string $message + * @return AnnotationException + */ + public static function creationError($message) + { + return new self('[Creation Error] ' . $message); + } + + /** + * Creates a new AnnotationException describing an type error of an attribute. + * + * @since 2.2 + * @param string $attributeName + * @param string $annotationName + * @param string $context + * @param string $expected + * @param mixed $actual + * @return AnnotationException + */ + public static function typeError($attributeName, $annotationName, $context, $expected, $actual) + { + return new self(sprintf( + '[Type Error] Attribute "%s" of @%s declared on %s expects %s, but got %s.', + $attributeName, + $annotationName, + $context, + $expected, + is_object($actual) ? 'an instance of '.get_class($actual) : gettype($actual) + )); + } + + /** + * Creates a new AnnotationException describing an required error of an attribute. + * + * @since 2.2 + * @param string $attributeName + * @param string $annotationName + * @param string $context + * @param string $expected + * @return AnnotationException + */ + public static function requiredError($attributeName, $annotationName, $context, $expected) + { + return new self(sprintf( + '[Type Error] Attribute "%s" of @%s declared on %s expects %s. This value should not be null.', + $attributeName, + $annotationName, + $context, + $expected + )); + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/AnnotationReader.php b/src/core/libs/Doctrine/Common/Annotations/AnnotationReader.php new file mode 100644 index 0000000..286e7d0 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/AnnotationReader.php @@ -0,0 +1,310 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +use Doctrine\Common\Annotations\Annotation\IgnoreAnnotation; +use Doctrine\Common\Annotations\Annotation\Target; +use Closure; +use ReflectionClass; +use ReflectionMethod; +use ReflectionProperty; + +/** + * A reader for docblock annotations. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class AnnotationReader implements Reader +{ + /** + * Global map for imports. + * + * @var array + */ + private static $globalImports = array( + 'ignoreannotation' => 'Doctrine\Common\Annotations\Annotation\IgnoreAnnotation', + ); + + /** + * A list with annotations that are not causing exceptions when not resolved to an annotation class. + * + * The names are case sensitive. + * + * @var array + */ + private static $globalIgnoredNames = array( + 'access'=> true, 'author'=> true, 'copyright'=> true, 'deprecated'=> true, + 'example'=> true, 'ignore'=> true, 'internal'=> true, 'link'=> true, 'see'=> true, + 'since'=> true, 'tutorial'=> true, 'version'=> true, 'package'=> true, + 'subpackage'=> true, 'name'=> true, 'global'=> true, 'param'=> true, + 'return'=> true, 'staticvar'=> true, 'category'=> true, 'staticVar'=> true, + 'static'=> true, 'var'=> true, 'throws'=> true, 'inheritdoc'=> true, + 'inheritDoc'=> true, 'license'=> true, 'todo'=> true, + 'deprec'=> true, 'property' => true, 'method' => true, + 'abstract'=> true, 'exception'=> true, 'magic' => true, 'api' => true, + 'final'=> true, 'filesource'=> true, 'throw' => true, 'uses' => true, + 'usedby'=> true, 'private' => true, 'Annotation' => true, 'override' => true, + 'codeCoverageIgnore' => true, 'codeCoverageIgnoreStart' => true, 'codeCoverageIgnoreEnd' => true, + 'Required' => true, 'Attribute' => true, 'Attributes' => true, + 'Target' => true, 'SuppressWarnings' => true, + 'ingroup' => true, 'code' => true, 'endcode' => true, + 'package_version' => true, + ); + + /** + * Add a new annotation to the globally ignored annotation names with regard to exception handling. + * + * @param string $name + */ + static public function addGlobalIgnoredName($name) + { + self::$globalIgnoredNames[$name] = true; + } + + /** + * Annotations Parser + * + * @var \Doctrine\Common\Annotations\DocParser + */ + private $parser; + + /** + * Annotations Parser used to collect parsing metadata + * + * @var \Doctrine\Common\Annotations\DocParser + */ + private $preParser; + + /** + * PHP Parser used to collect imports. + * + * @var \Doctrine\Common\Annotations\PhpParser + */ + private $phpParser; + + /** + * In-memory cache mechanism to store imported annotations per class. + * + * @var array + */ + private $imports = array(); + + /** + * In-memory cache mechanism to store ignored annotations per class. + * + * @var array + */ + private $ignoredAnnotationNames = array(); + + /** + * Constructor. + * + * Initializes a new AnnotationReader. + */ + public function __construct() + { + AnnotationRegistry::registerFile(__DIR__ . '/Annotation/IgnoreAnnotation.php'); + + $this->parser = new DocParser; + + $this->preParser = new DocParser; + $this->preParser->setImports(self::$globalImports); + $this->preParser->setIgnoreNotImportedAnnotations(true); + + $this->phpParser = new PhpParser; + } + + /** + * Gets the annotations applied to a class. + * + * @param ReflectionClass $class The ReflectionClass of the class from which + * the class annotations should be read. + * @return array An array of Annotations. + */ + public function getClassAnnotations(ReflectionClass $class) + { + $this->parser->setTarget(Target::TARGET_CLASS); + $this->parser->setImports($this->getImports($class)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + + return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName()); + } + + /** + * Gets a class annotation. + * + * @param ReflectionClass $class The ReflectionClass of the class from which + * the class annotations should be read. + * @param string $annotationName The name of the annotation. + * @return mixed The Annotation or NULL, if the requested annotation does not exist. + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + $annotations = $this->getClassAnnotations($class); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Gets the annotations applied to a property. + * + * @param ReflectionProperty $property The ReflectionProperty of the property + * from which the annotations should be read. + * @return array An array of Annotations. + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $context = 'property ' . $class->getName() . "::\$" . $property->getName(); + $this->parser->setTarget(Target::TARGET_PROPERTY); + $this->parser->setImports($this->getImports($class)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + + return $this->parser->parse($property->getDocComment(), $context); + } + + /** + * Gets a property annotation. + * + * @param ReflectionProperty $property + * @param string $annotationName The name of the annotation. + * @return mixed The Annotation or NULL, if the requested annotation does not exist. + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + $annotations = $this->getPropertyAnnotations($property); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Gets the annotations applied to a method. + * + * @param \ReflectionMethod $method The ReflectionMethod of the method from which + * the annotations should be read. + * + * @return array An array of Annotations. + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $context = 'method ' . $class->getName() . '::' . $method->getName() . '()'; + $this->parser->setTarget(Target::TARGET_METHOD); + $this->parser->setImports($this->getImports($class)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + + return $this->parser->parse($method->getDocComment(), $context); + } + + /** + * Gets a method annotation. + * + * @param ReflectionMethod $method + * @param string $annotationName The name of the annotation. + * @return mixed The Annotation or NULL, if the requested annotation does not exist. + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + $annotations = $this->getMethodAnnotations($method); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Returns the ignored annotations for the given class. + * + * @param ReflectionClass $class + * @return array + */ + private function getIgnoredAnnotationNames(ReflectionClass $class) + { + if (isset($this->ignoredAnnotationNames[$name = $class->getName()])) { + return $this->ignoredAnnotationNames[$name]; + } + $this->collectParsingMetadata($class); + + return $this->ignoredAnnotationNames[$name]; + } + + /** + * Retrieve imports + * + * @param \ReflectionClass $class + * @return array + */ + private function getImports(ReflectionClass $class) + { + if (isset($this->imports[$name = $class->getName()])) { + return $this->imports[$name]; + } + $this->collectParsingMetadata($class); + + return $this->imports[$name]; + } + + /** + * Collects parsing metadata for a given class + * + * @param ReflectionClass $class + */ + private function collectParsingMetadata(ReflectionClass $class) + { + $ignoredAnnotationNames = self::$globalIgnoredNames; + + $annotations = $this->preParser->parse($class->getDocComment(), 'class '.$class->name); + foreach ($annotations as $annotation) { + if ($annotation instanceof IgnoreAnnotation) { + foreach ($annotation->names AS $annot) { + $ignoredAnnotationNames[$annot] = true; + } + } + } + + $name = $class->getName(); + $this->imports[$name] = array_merge( + self::$globalImports, + $this->phpParser->parseClass($class), + array('__NAMESPACE__' => $class->getNamespaceName()) + ); + $this->ignoredAnnotationNames[$name] = $ignoredAnnotationNames; + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/AnnotationRegistry.php b/src/core/libs/Doctrine/Common/Annotations/AnnotationRegistry.php new file mode 100644 index 0000000..dfa846a --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/AnnotationRegistry.php @@ -0,0 +1,139 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +/** + * AnnotationRegistry + */ +final class AnnotationRegistry +{ + /** + * A map of namespaces to use for autoloading purposes based on a PSR-0 convention. + * + * Contains the namespace as key and an array of directories as value. If the value is NULL + * the include path is used for checking for the corresponding file. + * + * This autoloading mechanism does not utilize the PHP autoloading but implements autoloading on its own. + * + * @var array + */ + static private $autoloadNamespaces = array(); + + /** + * A map of autoloader callables. + * + * @var array + */ + static private $loaders = array(); + + static public function reset() + { + self::$autoloadNamespaces = array(); + self::$loaders = array(); + } + + /** + * Register file + * + * @param string $file + */ + static public function registerFile($file) + { + require_once $file; + } + + /** + * Add a namespace with one or many directories to look for files or null for the include path. + * + * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. + * + * @param string $namespace + * @param string|array|null $dirs + */ + static public function registerAutoloadNamespace($namespace, $dirs = null) + { + self::$autoloadNamespaces[$namespace] = $dirs; + } + + /** + * Register multiple namespaces + * + * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. + * + * @param array $namespaces + */ + static public function registerAutoloadNamespaces(array $namespaces) + { + self::$autoloadNamespaces = array_merge(self::$autoloadNamespaces, $namespaces); + } + + /** + * Register an autoloading callable for annotations, much like spl_autoload_register(). + * + * NOTE: These class loaders HAVE to be silent when a class was not found! + * IMPORTANT: Loaders have to return true if they loaded a class that could contain the searched annotation class. + * + * @param callable $callable + * + * @throws \InvalidArgumentException + */ + static public function registerLoader($callable) + { + if (!is_callable($callable)) { + throw new \InvalidArgumentException("A callable is expected in AnnotationRegistry::registerLoader()."); + } + self::$loaders[] = $callable; + } + + /** + * Autoload an annotation class silently. + * + * @param string $class + * @return boolean + */ + static public function loadAnnotationClass($class) + { + foreach (self::$autoloadNamespaces AS $namespace => $dirs) { + if (strpos($class, $namespace) === 0) { + $file = str_replace("\\", DIRECTORY_SEPARATOR, $class) . ".php"; + if ($dirs === null) { + if ($path = stream_resolve_include_path($file)) { + require $path; + return true; + } + } else { + foreach((array)$dirs AS $dir) { + if (file_exists($dir . DIRECTORY_SEPARATOR . $file)) { + require $dir . DIRECTORY_SEPARATOR . $file; + return true; + } + } + } + } + } + + foreach (self::$loaders AS $loader) { + if (call_user_func($loader, $class) === true) { + return true; + } + } + return false; + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/CachedReader.php b/src/core/libs/Doctrine/Common/Annotations/CachedReader.php new file mode 100644 index 0000000..e377e3b --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/CachedReader.php @@ -0,0 +1,250 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +use Doctrine\Common\Cache\Cache; + +/** + * A cache aware annotation reader. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +final class CachedReader implements Reader +{ + /** + * @var string + */ + private static $CACHE_SALT = '@[Annot]'; + + /** + * @var Reader + */ + private $delegate; + + /** + * @var Cache + */ + private $cache; + + /** + * @var boolean + */ + private $debug; + + /** + * @var array + */ + private $loadedAnnotations; + + /** + * Constructor + * + * @param Reader $reader + * @param Cache $cache + * @param bool $debug + */ + public function __construct(Reader $reader, Cache $cache, $debug = false) + { + $this->delegate = $reader; + $this->cache = $cache; + $this->debug = (Boolean) $debug; + } + + /** + * Get annotations for class + * + * @param \ReflectionClass $class + * @return array + */ + public function getClassAnnotations(\ReflectionClass $class) + { + $cacheKey = $class->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { + $annots = $this->delegate->getClassAnnotations($class); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * Get selected annotation for class + * + * @param \ReflectionClass $class + * @param string $annotationName + * @return null + */ + public function getClassAnnotation(\ReflectionClass $class, $annotationName) + { + foreach ($this->getClassAnnotations($class) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * Get annotations for property + * + * @param \ReflectionProperty $property + * @return array + */ + public function getPropertyAnnotations(\ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $cacheKey = $class->getName().'$'.$property->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { + $annots = $this->delegate->getPropertyAnnotations($property); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * Get selected annotation for property + * + * @param \ReflectionProperty $property + * @param string $annotationName + * @return null + */ + public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) + { + foreach ($this->getPropertyAnnotations($property) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * Get method annotations + * + * @param \ReflectionMethod $method + * @return array + */ + public function getMethodAnnotations(\ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $cacheKey = $class->getName().'#'.$method->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { + $annots = $this->delegate->getMethodAnnotations($method); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * Get selected method annotation + * + * @param \ReflectionMethod $method + * @param string $annotationName + * @return null + */ + public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) + { + foreach ($this->getMethodAnnotations($method) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * Clear loaded annotations + */ + public function clearLoadedAnnotations() + { + $this->loadedAnnotations = array(); + } + + /** + * Fetches a value from the cache. + * + * @param string $rawCacheKey The cache key. + * @param \ReflectionClass $class The related class. + * @return mixed|boolean The cached value or false when the value is not in cache. + */ + private function fetchFromCache($rawCacheKey, \ReflectionClass $class) + { + $cacheKey = $rawCacheKey . self::$CACHE_SALT; + if (($data = $this->cache->fetch($cacheKey)) !== false) { + if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) { + return $data; + } + } + + return false; + } + + /** + * Saves a value to the cache + * + * @param string $rawCacheKey The cache key. + * @param mixed $value The value. + */ + private function saveToCache($rawCacheKey, $value) + { + $cacheKey = $rawCacheKey . self::$CACHE_SALT; + $this->cache->save($cacheKey, $value); + if ($this->debug) { + $this->cache->save('[C]'.$cacheKey, time()); + } + } + + /** + * Check if cache is fresh + * + * @param string $cacheKey + * @param \ReflectionClass $class + * @return bool + */ + private function isCacheFresh($cacheKey, \ReflectionClass $class) + { + if (false === $filename = $class->getFilename()) { + return true; + } + + return $this->cache->fetch('[C]'.$cacheKey) >= filemtime($filename); + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/DocLexer.php b/src/core/libs/Doctrine/Common/Annotations/DocLexer.php new file mode 100644 index 0000000..c9a6f7a --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/DocLexer.php @@ -0,0 +1,132 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +use Doctrine\Common\Lexer; + +/** + * Simple lexer for docblock annotations. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +final class DocLexer extends Lexer +{ + const T_NONE = 1; + const T_INTEGER = 2; + const T_STRING = 3; + const T_FLOAT = 4; + + // All tokens that are also identifiers should be >= 100 + const T_IDENTIFIER = 100; + const T_AT = 101; + const T_CLOSE_CURLY_BRACES = 102; + const T_CLOSE_PARENTHESIS = 103; + const T_COMMA = 104; + const T_EQUALS = 105; + const T_FALSE = 106; + const T_NAMESPACE_SEPARATOR = 107; + const T_OPEN_CURLY_BRACES = 108; + const T_OPEN_PARENTHESIS = 109; + const T_TRUE = 110; + const T_NULL = 111; + const T_COLON = 112; + + protected $noCase = array( + '@' => self::T_AT, + ',' => self::T_COMMA, + '(' => self::T_OPEN_PARENTHESIS, + ')' => self::T_CLOSE_PARENTHESIS, + '{' => self::T_OPEN_CURLY_BRACES, + '}' => self::T_CLOSE_CURLY_BRACES, + '=' => self::T_EQUALS, + ':' => self::T_COLON, + '\\' => self::T_NAMESPACE_SEPARATOR + ); + + protected $withCase = array( + 'true' => self::T_TRUE, + 'false' => self::T_FALSE, + 'null' => self::T_NULL + ); + + /** + * {@inheritdoc} + */ + protected function getCatchablePatterns() + { + return array( + '[a-z_\\\][a-z0-9_\:\\\]*[a-z]{1}', + '(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?', + '"(?:[^"]|"")*"', + ); + } + + /** + * {@inheritdoc} + */ + protected function getNonCatchablePatterns() + { + return array('\s+', '\*+', '(.)'); + } + + /** + * {@inheritdoc} + * + * @param string $value + * + * @return int + */ + protected function getType(&$value) + { + $type = self::T_NONE; + + if ($value[0] === '"') { + $value = str_replace('""', '"', substr($value, 1, strlen($value) - 2)); + + return self::T_STRING; + } + + if (isset($this->noCase[$value])) { + return $this->noCase[$value]; + } + + if ($value[0] === '_' || $value[0] === '\\' || ctype_alpha($value[0])) { + return self::T_IDENTIFIER; + } + + $lowerValue = strtolower($value); + + if (isset($this->withCase[$lowerValue])) { + return $this->withCase[$lowerValue]; + } + + // Checking numeric value + if (is_numeric($value)) { + return (strpos($value, '.') !== false || stripos($value, 'e') !== false) + ? self::T_FLOAT : self::T_INTEGER; + } + + return $type; + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/DocParser.php b/src/core/libs/Doctrine/Common/Annotations/DocParser.php new file mode 100644 index 0000000..de31e0b --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/DocParser.php @@ -0,0 +1,988 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +use Closure; +use ReflectionClass; +use Doctrine\Common\Annotations\Annotation\Target; +use Doctrine\Common\Annotations\Annotation\Attribute; +use Doctrine\Common\Annotations\Annotation\Attributes; + +/** + * A parser for docblock annotations. + * + * It is strongly discouraged to change the default annotation parsing process. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> + */ +final class DocParser +{ + /** + * An array of all valid tokens for a class name. + * + * @var array + */ + private static $classIdentifiers = array(DocLexer::T_IDENTIFIER, DocLexer::T_TRUE, DocLexer::T_FALSE, DocLexer::T_NULL); + + /** + * The lexer. + * + * @var \Doctrine\Common\Annotations\DocLexer + */ + private $lexer; + + /** + * Current target context + * + * @var string + */ + private $target; + + /** + * Doc Parser used to collect annotation target + * + * @var \Doctrine\Common\Annotations\DocParser + */ + private static $metadataParser; + + /** + * Flag to control if the current annotation is nested or not. + * + * @var boolean + */ + private $isNestedAnnotation = false; + + /** + * Hashmap containing all use-statements that are to be used when parsing + * the given doc block. + * + * @var array + */ + private $imports = array(); + + /** + * This hashmap is used internally to cache results of class_exists() + * look-ups. + * + * @var array + */ + private $classExists = array(); + + /** + * Whether annotations that have not been imported should be ignored. + * + * @var boolean + */ + private $ignoreNotImportedAnnotations = false; + + /** + * An array of default namespaces if operating in simple mode. + * + * @var array + */ + private $namespaces = array(); + + /** + * A list with annotations that are not causing exceptions when not resolved to an annotation class. + * + * The names must be the raw names as used in the class, not the fully qualified + * class names. + * + * @var array + */ + private $ignoredAnnotationNames = array(); + + /** + * @var string + */ + private $context = ''; + + /** + * Hash-map for caching annotation metadata + * @var array + */ + private static $annotationMetadata = array( + 'Doctrine\Common\Annotations\Annotation\Target' => array( + 'is_annotation' => true, + 'has_constructor' => true, + 'properties' => array(), + 'targets_literal' => 'ANNOTATION_CLASS', + 'targets' => Target::TARGET_CLASS, + 'default_property' => 'value', + 'attribute_types' => array( + 'value' => array( + 'required' => false, + 'type' =>'array', + 'array_type'=>'string', + 'value' =>'array<string>' + ) + ), + ), + 'Doctrine\Common\Annotations\Annotation\Attribute' => array( + 'is_annotation' => true, + 'has_constructor' => false, + 'targets_literal' => 'ANNOTATION_ANNOTATION', + 'targets' => Target::TARGET_ANNOTATION, + 'default_property' => 'name', + 'properties' => array( + 'name' => 'name', + 'type' => 'type', + 'required' => 'required' + ), + 'attribute_types' => array( + 'value' => array( + 'required' => true, + 'type' =>'string', + 'value' =>'string' + ), + 'type' => array( + 'required' =>true, + 'type' =>'string', + 'value' =>'string' + ), + 'required' => array( + 'required' =>false, + 'type' =>'boolean', + 'value' =>'boolean' + ) + ), + ), + 'Doctrine\Common\Annotations\Annotation\Attributes' => array( + 'is_annotation' => true, + 'has_constructor' => false, + 'targets_literal' => 'ANNOTATION_CLASS', + 'targets' => Target::TARGET_CLASS, + 'default_property' => 'value', + 'properties' => array( + 'value' => 'value' + ), + 'attribute_types' => array( + 'value' => array( + 'type' =>'array', + 'required' =>true, + 'array_type'=>'Doctrine\Common\Annotations\Annotation\Attribute', + 'value' =>'array<Doctrine\Common\Annotations\Annotation\Attribute>' + ) + ), + ), + ); + + /** + * Hash-map for handle types declaration + * + * @var array + */ + private static $typeMap = array( + 'float' => 'double', + 'bool' => 'boolean', + // allow uppercase Boolean in honor of George Boole + 'Boolean' => 'boolean', + 'int' => 'integer', + ); + + /** + * Constructs a new DocParser. + */ + public function __construct() + { + $this->lexer = new DocLexer; + } + + /** + * Sets the annotation names that are ignored during the parsing process. + * + * The names are supposed to be the raw names as used in the class, not the + * fully qualified class names. + * + * @param array $names + */ + public function setIgnoredAnnotationNames(array $names) + { + $this->ignoredAnnotationNames = $names; + } + + /** + * Sets ignore on not-imported annotations + * + * @param $bool + */ + public function setIgnoreNotImportedAnnotations($bool) + { + $this->ignoreNotImportedAnnotations = (Boolean) $bool; + } + + /** + * Sets the default namespaces. + * + * @param array $namespace + * + * @throws \RuntimeException + */ + public function addNamespace($namespace) + { + if ($this->imports) { + throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); + } + $this->namespaces[] = $namespace; + } + + /** + * Sets the imports + * + * @param array $imports + * @throws \RuntimeException + */ + public function setImports(array $imports) + { + if ($this->namespaces) { + throw new \RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); + } + $this->imports = $imports; + } + + /** + * Sets current target context as bitmask. + * + * @param integer $target + */ + public function setTarget($target) + { + $this->target = $target; + } + + /** + * Parses the given docblock string for annotations. + * + * @param string $input The docblock string to parse. + * @param string $context The parsing context. + * @return array Array of annotations. If no annotations are found, an empty array is returned. + */ + public function parse($input, $context = '') + { + if (false === $pos = strpos($input, '@')) { + return array(); + } + + // also parse whatever character is before the @ + if ($pos > 0) { + $pos -= 1; + } + + $this->context = $context; + $this->lexer->setInput(trim(substr($input, $pos), '* /')); + $this->lexer->moveNext(); + + return $this->Annotations(); + } + + /** + * Attempts to match the given token with the current lookahead token. + * If they match, updates the lookahead token; otherwise raises a syntax error. + * + * @param int $token type of Token. + * @return bool True if tokens match; false otherwise. + */ + private function match($token) + { + if ( ! $this->lexer->isNextToken($token) ) { + $this->syntaxError($this->lexer->getLiteral($token)); + } + + return $this->lexer->moveNext(); + } + + /** + * Attempts to match the current lookahead token with any of the given tokens. + * + * If any of them matches, this method updates the lookahead token; otherwise + * a syntax error is raised. + * + * @param array $tokens + * @return bool + */ + private function matchAny(array $tokens) + { + if ( ! $this->lexer->isNextTokenAny($tokens)) { + $this->syntaxError(implode(' or ', array_map(array($this->lexer, 'getLiteral'), $tokens))); + } + + return $this->lexer->moveNext(); + } + + /** + * Generates a new syntax error. + * + * @param string $expected Expected string. + * @param array $token Optional token. + * + * @throws AnnotationException + */ + private function syntaxError($expected, $token = null) + { + if ($token === null) { + $token = $this->lexer->lookahead; + } + + $message = "Expected {$expected}, got "; + + if ($this->lexer->lookahead === null) { + $message .= 'end of string'; + } else { + $message .= "'{$token['value']}' at position {$token['position']}"; + } + + if (strlen($this->context)) { + $message .= ' in ' . $this->context; + } + + $message .= '.'; + + throw AnnotationException::syntaxError($message); + } + + /** + * Attempt to check if a class exists or not. This never goes through the PHP autoloading mechanism + * but uses the {@link AnnotationRegistry} to load classes. + * + * @param string $fqcn + * @return boolean + */ + private function classExists($fqcn) + { + if (isset($this->classExists[$fqcn])) { + return $this->classExists[$fqcn]; + } + + // first check if the class already exists, maybe loaded through another AnnotationReader + if (class_exists($fqcn, false)) { + return $this->classExists[$fqcn] = true; + } + + // final check, does this class exist? + return $this->classExists[$fqcn] = AnnotationRegistry::loadAnnotationClass($fqcn); + } + + /** + * Collects parsing metadata for a given annotation class + * + * @param string $name The annotation name + */ + private function collectAnnotationMetadata($name) + { + if (self::$metadataParser == null){ + self::$metadataParser = new self(); + self::$metadataParser->setTarget(Target::TARGET_CLASS); + self::$metadataParser->setIgnoreNotImportedAnnotations(true); + self::$metadataParser->setImports(array( + 'target' => 'Doctrine\Common\Annotations\Annotation\Target', + 'attribute' => 'Doctrine\Common\Annotations\Annotation\Attribute', + 'attributes' => 'Doctrine\Common\Annotations\Annotation\Attributes' + )); + AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Target.php'); + AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attribute.php'); + AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attributes.php'); + } + + $class = new \ReflectionClass($name); + $docComment = $class->getDocComment(); + + // Sets default values for annotation metadata + $metadata = array( + 'default_property' => null, + 'has_constructor' => (null !== $constructor = $class->getConstructor()) && $constructor->getNumberOfParameters() > 0, + 'properties' => array(), + 'property_types' => array(), + 'attribute_types' => array(), + 'targets_literal' => null, + 'targets' => Target::TARGET_ALL, + 'is_annotation' => false !== strpos($docComment, '@Annotation'), + ); + + // verify that the class is really meant to be an annotation + if ($metadata['is_annotation']) { + foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) { + if ($annotation instanceof Target) { + $metadata['targets'] = $annotation->targets; + $metadata['targets_literal'] = $annotation->literal; + + } elseif ($annotation instanceof Attributes) { + foreach ($annotation->value as $attrib) { + // handle internal type declaration + $type = isset(self::$typeMap[$attrib->type]) ? self::$typeMap[$attrib->type] : $attrib->type; + + // handle the case if the property type is mixed + if ('mixed' !== $type) { + // Checks if the property has array<type> + if (false !== $pos = strpos($type, '<')) { + $arrayType = substr($type, $pos+1, -1); + $type = 'array'; + + if (isset(self::$typeMap[$arrayType])) { + $arrayType = self::$typeMap[$arrayType]; + } + + $metadata['attribute_types'][$attrib->name]['array_type'] = $arrayType; + } + + $metadata['attribute_types'][$attrib->name]['type'] = $type; + $metadata['attribute_types'][$attrib->name]['value'] = $attrib->type; + $metadata['attribute_types'][$attrib->name]['required'] = $attrib->required; + } + } + } + } + + // if not has a constructor will inject values into public properties + if (false === $metadata['has_constructor']) { + // collect all public properties + foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) { + $metadata['properties'][$property->name] = $property->name; + + // checks if the property has @var annotation + if ((false !== $propertyComment = $property->getDocComment()) + && false !== strpos($propertyComment, '@var') + && preg_match('/@var\s+([^\s]+)/',$propertyComment, $matches)) { + // literal type declaration + $value = $matches[1]; + + // handle internal type declaration + $type = isset(self::$typeMap[$value]) ? self::$typeMap[$value] : $value; + + // handle the case if the property type is mixed + if ('mixed' !== $type) { + // Checks if the property has @var array<type> annotation + if (false !== $pos = strpos($type, '<')) { + $arrayType = substr($type, $pos+1, -1); + $type = 'array'; + + if (isset(self::$typeMap[$arrayType])) { + $arrayType = self::$typeMap[$arrayType]; + } + + $metadata['attribute_types'][$property->name]['array_type'] = $arrayType; + } + + $metadata['attribute_types'][$property->name]['type'] = $type; + $metadata['attribute_types'][$property->name]['value'] = $value; + $metadata['attribute_types'][$property->name]['required'] = false !== strpos($propertyComment, '@Required'); + } + } + } + + // choose the first property as default property + $metadata['default_property'] = reset($metadata['properties']); + } + } + + self::$annotationMetadata[$name] = $metadata; + } + + /** + * Annotations ::= Annotation {[ "*" ]* [Annotation]}* + * + * @return array + */ + private function Annotations() + { + $annotations = array(); + + while (null !== $this->lexer->lookahead) { + if (DocLexer::T_AT !== $this->lexer->lookahead['type']) { + $this->lexer->moveNext(); + continue; + } + + // make sure the @ is preceded by non-catchable pattern + if (null !== $this->lexer->token && $this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen($this->lexer->token['value'])) { + $this->lexer->moveNext(); + continue; + } + + // make sure the @ is followed by either a namespace separator, or + // an identifier token + if ((null === $peek = $this->lexer->glimpse()) + || (DocLexer::T_NAMESPACE_SEPARATOR !== $peek['type'] && !in_array($peek['type'], self::$classIdentifiers, true)) + || $peek['position'] !== $this->lexer->lookahead['position'] + 1) { + $this->lexer->moveNext(); + continue; + } + + $this->isNestedAnnotation = false; + if (false !== $annot = $this->Annotation()) { + $annotations[] = $annot; + } + } + + return $annotations; + } + + /** + * Annotation ::= "@" AnnotationName ["(" [Values] ")"] + * AnnotationName ::= QualifiedName | SimpleName + * QualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName + * NameSpacePart ::= identifier | null | false | true + * SimpleName ::= identifier | null | false | true + * + * @throws AnnotationException + * @return mixed False if it is not a valid annotation. + */ + private function Annotation() + { + $this->match(DocLexer::T_AT); + + // check if we have an annotation + $name = $this->Identifier(); + + // only process names which are not fully qualified, yet + // fully qualified names must start with a \ + $originalName = $name; + if ('\\' !== $name[0]) { + $alias = (false === $pos = strpos($name, '\\'))? $name : substr($name, 0, $pos); + + $found = false; + if ($this->namespaces) { + foreach ($this->namespaces as $namespace) { + if ($this->classExists($namespace.'\\'.$name)) { + $name = $namespace.'\\'.$name; + $found = true; + break; + } + } + } elseif (isset($this->imports[$loweredAlias = strtolower($alias)])) { + if (false !== $pos) { + $name = $this->imports[$loweredAlias].substr($name, $pos); + } else { + $name = $this->imports[$loweredAlias]; + } + $found = true; + } elseif (isset($this->imports['__NAMESPACE__']) && $this->classExists($this->imports['__NAMESPACE__'].'\\'.$name)) { + $name = $this->imports['__NAMESPACE__'].'\\'.$name; + $found = true; + } elseif ($this->classExists($name)) { + $found = true; + } + + if (!$found) { + if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) { + return false; + } + + throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation?', $name, $this->context)); + } + } + + if (!$this->classExists($name)) { + throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s does not exist, or could not be auto-loaded.', $name, $this->context)); + } + + // at this point, $name contains the fully qualified class name of the + // annotation, and it is also guaranteed that this class exists, and + // that it is loaded + + + // collects the metadata annotation only if there is not yet + if (!isset(self::$annotationMetadata[$name])) { + $this->collectAnnotationMetadata($name); + } + + // verify that the class is really meant to be an annotation and not just any ordinary class + if (self::$annotationMetadata[$name]['is_annotation'] === false) { + if (isset($this->ignoredAnnotationNames[$originalName])) { + return false; + } + + throw AnnotationException::semanticalError(sprintf('The class "%s" is not annotated with @Annotation. Are you sure this class can be used as annotation? If so, then you need to add @Annotation to the _class_ doc comment of "%s". If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s.', $name, $name, $originalName, $this->context)); + } + + //if target is nested annotation + $target = $this->isNestedAnnotation ? Target::TARGET_ANNOTATION : $this->target; + + // Next will be nested + $this->isNestedAnnotation = true; + + //if annotation does not support current target + if (0 === (self::$annotationMetadata[$name]['targets'] & $target) && $target) { + throw AnnotationException::semanticalError( + sprintf('Annotation @%s is not allowed to be declared on %s. You may only use this annotation on these code elements: %s.', + $originalName, $this->context, self::$annotationMetadata[$name]['targets_literal']) + ); + } + + $values = array(); + if ($this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) { + $this->match(DocLexer::T_OPEN_PARENTHESIS); + + if ( ! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { + $values = $this->Values(); + } + + $this->match(DocLexer::T_CLOSE_PARENTHESIS); + } + + // checks all declared attributes + foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) { + if ($property === self::$annotationMetadata[$name]['default_property'] + && !isset($values[$property]) && isset($values['value'])) { + $property = 'value'; + } + + // handle a not given attribute or null value + if (!isset($values[$property])) { + if ($type['required']) { + throw AnnotationException::requiredError($property, $originalName, $this->context, 'a(n) '.$type['value']); + } + + continue; + } + + if ($type['type'] === 'array') { + // handle the case of a single value + if (!is_array($values[$property])) { + $values[$property] = array($values[$property]); + } + + // checks if the attribute has array type declaration, such as "array<string>" + if (isset($type['array_type'])) { + foreach ($values[$property] as $item) { + if (gettype($item) !== $type['array_type'] && !$item instanceof $type['array_type']) { + throw AnnotationException::typeError($property, $originalName, $this->context, 'either a(n) '.$type['array_type'].', or an array of '.$type['array_type'].'s', $item); + } + } + } + } elseif (gettype($values[$property]) !== $type['type'] && !$values[$property] instanceof $type['type']) { + throw AnnotationException::typeError($property, $originalName, $this->context, 'a(n) '.$type['value'], $values[$property]); + } + } + + // check if the annotation expects values via the constructor, + // or directly injected into public properties + if (self::$annotationMetadata[$name]['has_constructor'] === true) { + return new $name($values); + } + + $instance = new $name(); + foreach ($values as $property => $value) { + if (!isset(self::$annotationMetadata[$name]['properties'][$property])) { + if ('value' !== $property) { + throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not have a property named "%s". Available properties: %s', $originalName, $this->context, $property, implode(', ', self::$annotationMetadata[$name]['properties']))); + } + + // handle the case if the property has no annotations + if (!$property = self::$annotationMetadata[$name]['default_property']) { + throw AnnotationException::creationError(sprintf('The annotation @%s declared on %s does not accept any values, but got %s.', $originalName, $this->context, json_encode($values))); + } + } + + $instance->{$property} = $value; + } + + return $instance; + } + + /** + * Values ::= Array | Value {"," Value}* + * + * @return array + */ + private function Values() + { + $values = array(); + + // Handle the case of a single array as value, i.e. @Foo({....}) + if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) { + $values['value'] = $this->Value(); + return $values; + } + + $values[] = $this->Value(); + + while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { + $this->match(DocLexer::T_COMMA); + $token = $this->lexer->lookahead; + $value = $this->Value(); + + if ( ! is_object($value) && ! is_array($value)) { + $this->syntaxError('Value', $token); + } + + $values[] = $value; + } + + foreach ($values as $k => $value) { + if (is_object($value) && $value instanceof \stdClass) { + $values[$value->name] = $value->value; + } else if ( ! isset($values['value'])){ + $values['value'] = $value; + } else { + if ( ! is_array($values['value'])) { + $values['value'] = array($values['value']); + } + + $values['value'][] = $value; + } + + unset($values[$k]); + } + + return $values; + } + + /** + * Constant ::= integer | string | float | boolean + * + * @throws AnnotationException + * @return mixed + */ + private function Constant() + { + $identifier = $this->Identifier(); + + if (!defined($identifier) && false !== strpos($identifier, '::') && '\\' !== $identifier[0]) { + + list($className, $const) = explode('::', $identifier); + $alias = (false === $pos = strpos($className, '\\'))? $className : substr($className, 0, $pos); + + $found = false; + switch (true) { + case !empty ($this->namespaces): + foreach ($this->namespaces as $ns) { + if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) { + $className = $ns.'\\'.$className; + $found = true; + break; + } + } + break; + + case isset($this->imports[$loweredAlias = strtolower($alias)]): + $found = true; + if (false !== $pos) { + $className = $this->imports[$loweredAlias].substr($className, $pos); + } else { + $className = $this->imports[$loweredAlias]; + } + break; + + default: + if(isset($this->imports['__NAMESPACE__'])) { + $ns = $this->imports['__NAMESPACE__']; + if (class_exists($ns.'\\'.$className) || interface_exists($ns.'\\'.$className)) { + $className = $ns.'\\'.$className; + $found = true; + } + } + break; + } + + if ($found) { + $identifier = $className . '::' . $const; + } + } + + if (!defined($identifier)) { + throw AnnotationException::semanticalErrorConstants($identifier, $this->context); + } + + return constant($identifier); + } + + /** + * Identifier ::= string + * + * @return string + */ + private function Identifier() + { + // check if we have an annotation + if ($this->lexer->isNextTokenAny(self::$classIdentifiers)) { + $this->lexer->moveNext(); + $className = $this->lexer->token['value']; + } else { + $this->syntaxError('namespace separator or identifier'); + } + + while ($this->lexer->lookahead['position'] === ($this->lexer->token['position'] + strlen($this->lexer->token['value'])) + && $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR)) { + + $this->match(DocLexer::T_NAMESPACE_SEPARATOR); + $this->matchAny(self::$classIdentifiers); + $className .= '\\' . $this->lexer->token['value']; + } + + return $className; + } + + /** + * Value ::= PlainValue | FieldAssignment + * + * @return mixed + */ + private function Value() + { + $peek = $this->lexer->glimpse(); + + if (DocLexer::T_EQUALS === $peek['type']) { + return $this->FieldAssignment(); + } + + return $this->PlainValue(); + } + + /** + * PlainValue ::= integer | string | float | boolean | Array | Annotation + * + * @return mixed + */ + private function PlainValue() + { + if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) { + return $this->Arrayx(); + } + + if ($this->lexer->isNextToken(DocLexer::T_AT)) { + return $this->Annotation(); + } + + if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { + return $this->Constant(); + } + + switch ($this->lexer->lookahead['type']) { + case DocLexer::T_STRING: + $this->match(DocLexer::T_STRING); + return $this->lexer->token['value']; + + case DocLexer::T_INTEGER: + $this->match(DocLexer::T_INTEGER); + return (int)$this->lexer->token['value']; + + case DocLexer::T_FLOAT: + $this->match(DocLexer::T_FLOAT); + return (float)$this->lexer->token['value']; + + case DocLexer::T_TRUE: + $this->match(DocLexer::T_TRUE); + return true; + + case DocLexer::T_FALSE: + $this->match(DocLexer::T_FALSE); + return false; + + case DocLexer::T_NULL: + $this->match(DocLexer::T_NULL); + return null; + + default: + $this->syntaxError('PlainValue'); + } + } + + /** + * FieldAssignment ::= FieldName "=" PlainValue + * FieldName ::= identifier + * + * @return array + */ + private function FieldAssignment() + { + $this->match(DocLexer::T_IDENTIFIER); + $fieldName = $this->lexer->token['value']; + + $this->match(DocLexer::T_EQUALS); + + $item = new \stdClass(); + $item->name = $fieldName; + $item->value = $this->PlainValue(); + + return $item; + } + + /** + * Array ::= "{" ArrayEntry {"," ArrayEntry}* [","] "}" + * + * @return array + */ + private function Arrayx() + { + $array = $values = array(); + + $this->match(DocLexer::T_OPEN_CURLY_BRACES); + $values[] = $this->ArrayEntry(); + + while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { + $this->match(DocLexer::T_COMMA); + + // optional trailing comma + if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { + break; + } + + $values[] = $this->ArrayEntry(); + } + + $this->match(DocLexer::T_CLOSE_CURLY_BRACES); + + foreach ($values as $value) { + list ($key, $val) = $value; + + if ($key !== null) { + $array[$key] = $val; + } else { + $array[] = $val; + } + } + + return $array; + } + + /** + * ArrayEntry ::= Value | KeyValuePair + * KeyValuePair ::= Key ("=" | ":") PlainValue | Constant + * Key ::= string | integer | Constant + * + * @return array + */ + private function ArrayEntry() + { + $peek = $this->lexer->glimpse(); + + if (DocLexer::T_EQUALS === $peek['type'] + || DocLexer::T_COLON === $peek['type']) { + + if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { + $key = $this->Constant(); + } else { + $this->matchAny(array(DocLexer::T_INTEGER, DocLexer::T_STRING)); + $key = $this->lexer->token['value']; + } + + $this->matchAny(array(DocLexer::T_EQUALS, DocLexer::T_COLON)); + + return array($key, $this->PlainValue()); + } + + return array(null, $this->Value()); + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/FileCacheReader.php b/src/core/libs/Doctrine/Common/Annotations/FileCacheReader.php new file mode 100644 index 0000000..3934861 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/FileCacheReader.php @@ -0,0 +1,258 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + + +/** + * File cache reader for annotations. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class FileCacheReader implements Reader +{ + /** + * @var Reader + */ + private $reader; + + /** + * @var string + */ + private $dir; + + /** + * @var bool + */ + private $debug; + + /** + * @var array + */ + private $loadedAnnotations = array(); + + /** + * Constructor + * + * @param Reader $reader + * @param string $cacheDir + * @param bool $debug + * + * @throws \InvalidArgumentException + */ + public function __construct(Reader $reader, $cacheDir, $debug = false) + { + $this->reader = $reader; + if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true)) { + throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $cacheDir)); + } + if (!is_writable($cacheDir)) { + throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable. Both, the webserver and the console user need access. You can manage access rights for multiple users with "chmod +a". If your system does not support this, check out the acl package.', $cacheDir)); + } + + $this->dir = rtrim($cacheDir, '\\/'); + $this->debug = $debug; + } + + /** + * Retrieve annotations for class + * + * @param \ReflectionClass $class + * @return array + */ + public function getClassAnnotations(\ReflectionClass $class) + { + $key = $class->getName(); + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; + if (!file_exists($path)) { + $annot = $this->reader->getClassAnnotations($class); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + if ($this->debug + && (false !== $filename = $class->getFilename()) + && filemtime($path) < filemtime($filename)) { + @unlink($path); + + $annot = $this->reader->getClassAnnotations($class); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * Get annotations for property + * + * @param \ReflectionProperty $property + * @return array + */ + public function getPropertyAnnotations(\ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $key = $class->getName().'$'.$property->getName(); + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; + if (!file_exists($path)) { + $annot = $this->reader->getPropertyAnnotations($property); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + if ($this->debug + && (false !== $filename = $class->getFilename()) + && filemtime($path) < filemtime($filename)) { + unlink($path); + + $annot = $this->reader->getPropertyAnnotations($property); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * Retrieve annotations for method + * + * @param \ReflectionMethod $method + * @return array + */ + public function getMethodAnnotations(\ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $key = $class->getName().'#'.$method->getName(); + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; + if (!file_exists($path)) { + $annot = $this->reader->getMethodAnnotations($method); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + if ($this->debug + && (false !== $filename = $class->getFilename()) + && filemtime($path) < filemtime($filename)) { + unlink($path); + + $annot = $this->reader->getMethodAnnotations($method); + $this->saveCacheFile($path, $annot); + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * Save cache file + * + * @param string $path + * @param mixed $data + */ + private function saveCacheFile($path, $data) + { + file_put_contents($path, '<?php return unserialize('.var_export(serialize($data), true).');'); + } + + /** + * Gets a class annotation. + * + * @param \ReflectionClass $class The ReflectionClass of the class from which + * the class annotations should be read. + * @param string $annotationName The name of the annotation. + * + * @return mixed The Annotation or NULL, if the requested annotation does not exist. + */ + public function getClassAnnotation(\ReflectionClass $class, $annotationName) + { + $annotations = $this->getClassAnnotations($class); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Gets a method annotation. + * + * @param \ReflectionMethod $method + * @param string $annotationName The name of the annotation. + * @return mixed The Annotation or NULL, if the requested annotation does not exist. + */ + public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) + { + $annotations = $this->getMethodAnnotations($method); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Gets a property annotation. + * + * @param \ReflectionProperty $property + * @param string $annotationName The name of the annotation. + * @return mixed The Annotation or NULL, if the requested annotation does not exist. + */ + public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) + { + $annotations = $this->getPropertyAnnotations($property); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Clear stores annotations + */ + public function clearLoadedAnnotations() + { + $this->loadedAnnotations = array(); + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/IndexedReader.php b/src/core/libs/Doctrine/Common/Annotations/IndexedReader.php new file mode 100644 index 0000000..2dfdd4d --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/IndexedReader.php @@ -0,0 +1,141 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +use Doctrine\Common\Annotations\Reader; + +/** + * Allows the reader to be used in-place of Doctrine's reader. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class IndexedReader implements Reader +{ + /** + * @var Reader + */ + private $delegate; + + /** + * Constructor + * + * @param Reader $reader + */ + public function __construct(Reader $reader) + { + $this->delegate = $reader; + } + + /** + * Get Annotations for class + * + * @param \ReflectionClass $class + * @return array + */ + public function getClassAnnotations(\ReflectionClass $class) + { + $annotations = array(); + foreach ($this->delegate->getClassAnnotations($class) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * Get selected annotation for class + * + * @param \ReflectionClass $class + * @param string $annotation + * @return mixed + */ + public function getClassAnnotation(\ReflectionClass $class, $annotation) + { + return $this->delegate->getClassAnnotation($class, $annotation); + } + + /** + * Get Annotations for method + * + * @param \ReflectionMethod $method + * @return array + */ + public function getMethodAnnotations(\ReflectionMethod $method) + { + $annotations = array(); + foreach ($this->delegate->getMethodAnnotations($method) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * Get selected annotation for method + * + * @param \ReflectionMethod $method + * @param string $annotation + * @return mixed + */ + public function getMethodAnnotation(\ReflectionMethod $method, $annotation) + { + return $this->delegate->getMethodAnnotation($method, $annotation); + } + + /** + * Get annotations for property + * + * @param \ReflectionProperty $property + * @return array + */ + public function getPropertyAnnotations(\ReflectionProperty $property) + { + $annotations = array(); + foreach ($this->delegate->getPropertyAnnotations($property) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * Get selected annotation for property + * + * @param \ReflectionProperty $property + * @param string $annotation + * @return mixed + */ + public function getPropertyAnnotation(\ReflectionProperty $property, $annotation) + { + return $this->delegate->getPropertyAnnotation($property, $annotation); + } + + /** + * Proxy all methods to the delegate. + * + * @param string $method + * @param array $args + * @return mixed + */ + public function __call($method, $args) + { + return call_user_func_array(array($this->delegate, $method), $args); + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/PhpParser.php b/src/core/libs/Doctrine/Common/Annotations/PhpParser.php new file mode 100644 index 0000000..c09dd51 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/PhpParser.php @@ -0,0 +1,80 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +use SplFileObject; + +/** + * Parses a file for namespaces/use/class declarations. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Christian Kaps <christian.kaps@mohiva.com> + */ +final class PhpParser +{ + /** + * Parses a class. + * + * @param \ReflectionClass $class A <code>ReflectionClass</code> object. + * @return array A list with use statements in the form (Alias => FQN). + */ + public function parseClass(\ReflectionClass $class) + { + if (method_exists($class, 'getUseStatements')) { + return $class->getUseStatements(); + } + + if (false === $filename = $class->getFilename()) { + return array(); + } + + $content = $this->getFileContent($filename, $class->getStartLine()); + $namespace = str_replace('\\', '\\\\', $class->getNamespaceName()); + $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content); + $tokenizer = new TokenParser('<?php ' . $content); + + $statements = $tokenizer->parseUseStatements($class->getNamespaceName()); + + return $statements; + } + + /** + * Get the content of the file right up to the given line number. + * + * @param string $filename The name of the file to load. + * @param int $lineNumber The number of lines to read from file. + * @return string The content of the file. + */ + private function getFileContent($filename, $lineNumber) + { + $content = ''; + $lineCnt = 0; + $file = new SplFileObject($filename); + while (!$file->eof()) { + if ($lineCnt++ == $lineNumber) { + break; + } + + $content .= $file->fgets(); + } + + return $content; + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/Reader.php b/src/core/libs/Doctrine/Common/Annotations/Reader.php new file mode 100644 index 0000000..6a01cb4 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/Reader.php @@ -0,0 +1,67 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +/** + * Interface for annotation readers. + * + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +interface Reader +{ + /** + * @param \ReflectionClass $class + * @return mixed + */ + function getClassAnnotations(\ReflectionClass $class); + + /** + * @param \ReflectionClass $class + * @param string $annotationName + * @return mixed + */ + function getClassAnnotation(\ReflectionClass $class, $annotationName); + + /** + * @param \ReflectionMethod $method + * @return mixed + */ + function getMethodAnnotations(\ReflectionMethod $method); + + /** + * @param \ReflectionMethod $method + * @param string $annotationName + * @return mixed + */ + function getMethodAnnotation(\ReflectionMethod $method, $annotationName); + + /** + * @param \ReflectionProperty $property + * @return mixed + */ + function getPropertyAnnotations(\ReflectionProperty $property); + + /** + * @param \ReflectionProperty $property + * @param string $annotationName + * @return mixed + */ + function getPropertyAnnotation(\ReflectionProperty $property, $annotationName); +} diff --git a/src/core/libs/Doctrine/Common/Annotations/SimpleAnnotationReader.php b/src/core/libs/Doctrine/Common/Annotations/SimpleAnnotationReader.php new file mode 100644 index 0000000..4210d90 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/SimpleAnnotationReader.php @@ -0,0 +1,157 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +use Doctrine\Common\Annotations\Annotation\Target; + +/** + * Simple Annotation Reader. + * + * This annotation reader is intended to be used in projects where you have + * full-control over all annotations that are available. + * + * @since 2.2 + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> + */ +class SimpleAnnotationReader implements Reader +{ + /** + * @var DocParser + */ + private $parser; + + /** + * Constructor. + * + * Initializes a new SimpleAnnotationReader. + */ + public function __construct() + { + $this->parser = new DocParser(); + $this->parser->setIgnoreNotImportedAnnotations(true); + } + + /** + * Adds a namespace in which we will look for annotations. + * + * @param string $namespace + */ + public function addNamespace($namespace) + { + $this->parser->addNamespace($namespace); + } + + /** + * Gets the annotations applied to a class. + * + * @param \ReflectionClass $class The ReflectionClass of the class from which + * the class annotations should be read. + * + * @return array An array of Annotations. + */ + public function getClassAnnotations(\ReflectionClass $class) + { + return $this->parser->parse($class->getDocComment(), 'class '.$class->getName()); + } + + /** + * Gets the annotations applied to a method. + * + * @param \ReflectionMethod $method The ReflectionMethod of the method from which + * the annotations should be read. + * + * @return array An array of Annotations. + */ + public function getMethodAnnotations(\ReflectionMethod $method) + { + return $this->parser->parse($method->getDocComment(), 'method '.$method->getDeclaringClass()->name.'::'.$method->getName().'()'); + } + + /** + * Gets the annotations applied to a property. + * + * @param \ReflectionProperty $property The ReflectionProperty of the property + * from which the annotations should be read. + * + * @return array An array of Annotations. + */ + public function getPropertyAnnotations(\ReflectionProperty $property) + { + return $this->parser->parse($property->getDocComment(), 'property '.$property->getDeclaringClass()->name.'::$'.$property->getName()); + } + + /** + * Gets a class annotation. + * + * @param \ReflectionClass $class The ReflectionClass of the class from which + * the class annotations should be read. + * @param string $annotationName The name of the annotation. + * + * @return mixed The Annotation or NULL, if the requested annotation does not exist. + */ + public function getClassAnnotation(\ReflectionClass $class, $annotationName) + { + foreach ($this->getClassAnnotations($class) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * Gets a method annotation. + * + * @param \ReflectionMethod $method + * @param string $annotationName The name of the annotation. + * + * @return mixed The Annotation or NULL, if the requested annotation does not exist. + */ + public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) + { + foreach ($this->getMethodAnnotations($method) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * Gets a property annotation. + * + * @param \ReflectionProperty $property + * @param string $annotationName The name of the annotation. + * @return mixed The Annotation or NULL, if the requested annotation does not exist. + */ + public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) + { + foreach ($this->getPropertyAnnotations($property) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } +} diff --git a/src/core/libs/Doctrine/Common/Annotations/TokenParser.php b/src/core/libs/Doctrine/Common/Annotations/TokenParser.php new file mode 100644 index 0000000..a1ef115 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Annotations/TokenParser.php @@ -0,0 +1,175 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Annotations; + +/** + * Parses a file for namespaces/use/class declarations. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Christian Kaps <christian.kaps@mohiva.com> + */ +class TokenParser +{ + /** + * The token list. + * + * @var array + */ + private $tokens; + + /** + * The number of tokens. + * + * @var int + */ + private $numTokens = 0; + + /** + * The current array pointer. + * + * @var int + */ + private $pointer = 0; + + public function __construct($contents) + { + $this->tokens = token_get_all($contents); + $this->numTokens = count($this->tokens); + $this->pointer = 0; + } + + /** + * Gets the next non whitespace and non comment token. + * + * @param $docCommentIsComment + * If TRUE then a doc comment is considered a comment and skipped. + * If FALSE then only whitespace and normal comments are skipped. + * + * @return array The token if exists, null otherwise. + */ + public function next($docCommentIsComment = TRUE) + { + for ($i = $this->pointer; $i < $this->numTokens; $i++) { + $this->pointer++; + if ($this->tokens[$i][0] === T_WHITESPACE || + $this->tokens[$i][0] === T_COMMENT || + ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT)) { + + continue; + } + + return $this->tokens[$i]; + } + + return null; + } + + /** + * Parse a single use statement. + * + * @return array A list with all found class names for a use statement. + */ + public function parseUseStatement() + { + $class = ''; + $alias = ''; + $statements = array(); + $explicitAlias = false; + while (($token = $this->next())) { + $isNameToken = $token[0] === T_STRING || $token[0] === T_NS_SEPARATOR; + if (!$explicitAlias && $isNameToken) { + $class .= $token[1]; + $alias = $token[1]; + } else if ($explicitAlias && $isNameToken) { + $alias .= $token[1]; + } else if ($token[0] === T_AS) { + $explicitAlias = true; + $alias = ''; + } else if ($token === ',') { + $statements[strtolower($alias)] = $class; + $class = ''; + $alias = ''; + $explicitAlias = false; + } else if ($token === ';') { + $statements[strtolower($alias)] = $class; + break; + } else { + break; + } + } + + return $statements; + } + + /** + * Get all use statements. + * + * @param string $namespaceName The namespace name of the reflected class. + * @return array A list with all found use statements. + */ + public function parseUseStatements($namespaceName) + { + $statements = array(); + while (($token = $this->next())) { + if ($token[0] === T_USE) { + $statements = array_merge($statements, $this->parseUseStatement()); + continue; + } + if ($token[0] !== T_NAMESPACE || $this->parseNamespace() != $namespaceName) { + continue; + } + + // Get fresh array for new namespace. This is to prevent the parser to collect the use statements + // for a previous namespace with the same name. This is the case if a namespace is defined twice + // or if a namespace with the same name is commented out. + $statements = array(); + } + + return $statements; + } + + /** + * Get the namespace. + * + * @return string The found namespace. + */ + public function parseNamespace() + { + $name = ''; + while (($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) { + $name .= $token[1]; + } + + return $name; + } + + /** + * Get the class name. + * + * @return string The foundclass name. + */ + public function parseClass() + { + // Namespaces and class names are tokenized the same: T_STRINGs + // separated by T_NS_SEPARATOR so we can use one function to provide + // both. + return $this->parseNamespace(); + } +} diff --git a/src/core/libs/Doctrine/Common/Cache/ApcCache.php b/src/core/libs/Doctrine/Common/Cache/ApcCache.php new file mode 100644 index 0000000..2d0cd23 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/ApcCache.php @@ -0,0 +1,93 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +/** + * APC cache provider. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author David Abdemoulaie <dave@hobodave.com> + */ +class ApcCache extends CacheProvider +{ + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return apc_fetch($id); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return apc_exists($id); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + return (bool) apc_store($id, $data, (int) $lifeTime); + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return apc_delete($id); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return apc_clear_cache() && apc_clear_cache('user'); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $info = apc_cache_info(); + $sma = apc_sma_info(); + + return array( + Cache::STATS_HITS => $info['num_hits'], + Cache::STATS_MISSES => $info['num_misses'], + Cache::STATS_UPTIME => $info['start_time'], + Cache::STATS_MEMORY_USAGE => $info['mem_size'], + Cache::STATS_MEMORY_AVAILIABLE => $sma['avail_mem'], + ); + } +} diff --git a/src/core/libs/Doctrine/Common/Cache/ArrayCache.php b/src/core/libs/Doctrine/Common/Cache/ArrayCache.php new file mode 100644 index 0000000..a7a70aa --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/ArrayCache.php @@ -0,0 +1,96 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +/** + * Array cache driver. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author David Abdemoulaie <dave@hobodave.com> + */ +class ArrayCache extends CacheProvider +{ + /** + * @var array $data + */ + private $data = array(); + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return (isset($this->data[$id])) ? $this->data[$id] : false; + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return isset($this->data[$id]); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + $this->data[$id] = $data; + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + unset($this->data[$id]); + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + $this->data = array(); + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + return null; + } +} diff --git a/src/core/libs/Doctrine/Common/Cache/Cache.php b/src/core/libs/Doctrine/Common/Cache/Cache.php new file mode 100644 index 0000000..5493562 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/Cache.php @@ -0,0 +1,102 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +/** + * Interface for cache drivers. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> + */ +interface Cache +{ + const STATS_HITS = 'hits'; + const STATS_MISSES = 'misses'; + const STATS_UPTIME = 'uptime'; + const STATS_MEMORY_USAGE = 'memory_usage'; + const STATS_MEMORY_AVAILIABLE = 'memory_available'; + + /** + * Fetches an entry from the cache. + * + * @param string $id cache id The id of the cache entry to fetch. + * @return mixed The cached data or FALSE, if no cache entry exists for the given id. + */ + function fetch($id); + + /** + * Test if an entry exists in the cache. + * + * @param string $id cache id The cache id of the entry to check for. + * @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise. + */ + function contains($id); + + /** + * Puts data into the cache. + * + * @param string $id The cache id. + * @param mixed $data The cache entry/data. + * @param int $lifeTime The lifetime. If != 0, sets a specific lifetime for this cache entry (0 => infinite lifeTime). + * @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise. + */ + function save($id, $data, $lifeTime = 0); + + /** + * Deletes a cache entry. + * + * @param string $id cache id + * @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise. + */ + function delete($id); + + /** + * Retrieves cached information from data store + * + * The server's statistics array has the following values: + * + * - <b>hits</b> + * Number of keys that have been requested and found present. + * + * - <b>misses</b> + * Number of items that have been requested and not found. + * + * - <b>uptime</b> + * Time that the server is running. + * + * - <b>memory_usage</b> + * Memory used by this server to store items. + * + * - <b>memory_available</b> + * Memory allowed to use for storage. + * + * @since 2.2 + * @var array Associative array with server's statistics if available, NULL otherwise. + */ + function getStats(); +} diff --git a/src/core/libs/Doctrine/Common/Cache/CacheProvider.php b/src/core/libs/Doctrine/Common/Cache/CacheProvider.php new file mode 100644 index 0000000..4221a62 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/CacheProvider.php @@ -0,0 +1,231 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +/** + * Base class for cache provider implementations. + * + * @since 2.2 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> + */ +abstract class CacheProvider implements Cache +{ + const DOCTRINE_NAMESPACE_CACHEKEY = 'DoctrineNamespaceCacheKey[%s]'; + + /** + * @var string The namespace to prefix all cache ids with + */ + private $namespace = ''; + + /** + * @var string The namespace version + */ + private $namespaceVersion; + + /** + * Set the namespace to prefix all cache ids with. + * + * @param string $namespace + * @return void + */ + public function setNamespace($namespace) + { + $this->namespace = (string) $namespace; + } + + /** + * Retrieve the namespace that prefixes all cache ids. + * + * @return string + */ + public function getNamespace() + { + return $this->namespace; + } + + /** + * {@inheritdoc} + */ + public function fetch($id) + { + return $this->doFetch($this->getNamespacedId($id)); + } + + /** + * {@inheritdoc} + */ + public function contains($id) + { + return $this->doContains($this->getNamespacedId($id)); + } + + /** + * {@inheritdoc} + */ + public function save($id, $data, $lifeTime = 0) + { + return $this->doSave($this->getNamespacedId($id), $data, $lifeTime); + } + + /** + * {@inheritdoc} + */ + public function delete($id) + { + return $this->doDelete($this->getNamespacedId($id)); + } + + /** + * {@inheritdoc} + */ + public function getStats() + { + return $this->doGetStats(); + } + + /** + * Deletes all cache entries. + * + * @return boolean TRUE if the cache entries were successfully flushed, FALSE otherwise. + */ + public function flushAll() + { + return $this->doFlush(); + } + + /** + * Delete all cache entries. + * + * @return boolean TRUE if the cache entries were successfully deleted, FALSE otherwise. + */ + public function deleteAll() + { + $namespaceCacheKey = $this->getNamespaceCacheKey(); + $namespaceVersion = $this->getNamespaceVersion() + 1; + + $this->namespaceVersion = $namespaceVersion; + + return $this->doSave($namespaceCacheKey, $namespaceVersion); + } + + /** + * Prefix the passed id with the configured namespace value + * + * @param string $id The id to namespace + * @return string $id The namespaced id + */ + private function getNamespacedId($id) + { + $namespaceVersion = $this->getNamespaceVersion(); + + return sprintf('%s[%s][%s]', $this->namespace, $id, $namespaceVersion); + } + + /** + * Namespace cache key + * + * @return string $namespaceCacheKey + */ + private function getNamespaceCacheKey() + { + return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY, $this->namespace); + } + + /** + * Namespace version + * + * @return string $namespaceVersion + */ + private function getNamespaceVersion() + { + if (null !== $this->namespaceVersion) { + return $this->namespaceVersion; + } + + $namespaceCacheKey = $this->getNamespaceCacheKey(); + $namespaceVersion = $this->doFetch($namespaceCacheKey); + + if (false === $namespaceVersion) { + $namespaceVersion = 1; + + $this->doSave($namespaceCacheKey, $namespaceVersion); + } + + $this->namespaceVersion = $namespaceVersion; + + return $this->namespaceVersion; + } + + /** + * Fetches an entry from the cache. + * + * @param string $id cache id The id of the cache entry to fetch. + * @return string The cached data or FALSE, if no cache entry exists for the given id. + */ + abstract protected function doFetch($id); + + /** + * Test if an entry exists in the cache. + * + * @param string $id cache id The cache id of the entry to check for. + * @return boolean TRUE if a cache entry exists for the given cache id, FALSE otherwise. + */ + abstract protected function doContains($id); + + /** + * Puts data into the cache. + * + * @param string $id The cache id. + * @param string $data The cache entry/data. + * @param bool|int $lifeTime The lifetime. If != false, sets a specific lifetime for this + * cache entry (null => infinite lifeTime). + * + * @return boolean TRUE if the entry was successfully stored in the cache, FALSE otherwise. + */ + abstract protected function doSave($id, $data, $lifeTime = false); + + /** + * Deletes a cache entry. + * + * @param string $id cache id + * @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise. + */ + abstract protected function doDelete($id); + + /** + * Deletes all cache entries. + * + * @return boolean TRUE if the cache entry was successfully deleted, FALSE otherwise. + */ + abstract protected function doFlush(); + + /** + * Retrieves cached information from data store + * + * @since 2.2 + * @return array An associative array with server's statistics if available, NULL otherwise. + */ + abstract protected function doGetStats(); +} diff --git a/src/core/libs/Doctrine/Common/Cache/FileCache.php b/src/core/libs/Doctrine/Common/Cache/FileCache.php new file mode 100644 index 0000000..da650b4 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/FileCache.php @@ -0,0 +1,132 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +/** + * Base file cache driver. + * + * @since 2.3 + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> + */ +abstract class FileCache extends CacheProvider +{ + /** + * @var string Cache directory. + */ + protected $directory; + + /** + * @var string Cache file extension. + */ + protected $extension; + + /** + * Constructor + * + * @param string $directory Cache directory. + * @param string $directory Cache file extension. + * + * @throws \InvalidArgumentException + */ + public function __construct($directory, $extension = null) + { + if ( ! is_dir($directory) && ! @mkdir($directory, 0777, true)) { + throw new \InvalidArgumentException(sprintf( + 'The directory "%s" does not exist and could not be created.', + $directory + )); + } + + if ( ! is_writable($directory)) { + throw new \InvalidArgumentException(sprintf( + 'The directory "%s" is not writable.', + $directory + )); + } + + $this->directory = realpath($directory); + $this->extension = $extension ?: $this->extension; + } + + /** + * Gets the cache directory. + * + * @return string + */ + public function getDirectory() + { + return $this->directory; + } + + /** + * Gets the cache file extension. + * + * @return string + */ + public function getExtension() + { + return $this->extension; + } + + /** + * @return string + */ + protected function getFilename($id) + { + $path = implode(str_split(md5($id), 12), DIRECTORY_SEPARATOR); + $path = $this->directory . DIRECTORY_SEPARATOR . $path; + + return $path . DIRECTORY_SEPARATOR . $id . $this->extension; + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return @unlink($this->getFilename($id)); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + $pattern = '/^.+\\' . $this->extension . '$/i'; + $iterator = new \RecursiveDirectoryIterator($this->directory); + $iterator = new \RecursiveIteratorIterator($iterator); + $iterator = new \RegexIterator($iterator, $pattern); + + foreach ($iterator as $name => $file) { + @unlink($name); + } + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + return null; + } +} \ No newline at end of file diff --git a/src/core/libs/Doctrine/Common/Cache/FilesystemCache.php b/src/core/libs/Doctrine/Common/Cache/FilesystemCache.php new file mode 100644 index 0000000..a27a717 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/FilesystemCache.php @@ -0,0 +1,114 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +/** + * Filesystem cache driver. + * + * @since 2.3 + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> + */ +class FilesystemCache extends FileCache +{ + const EXTENSION = '.doctrinecache.data'; + + /** + * {@inheritdoc} + */ + protected $extension = self::EXTENSION; + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + $data = ''; + $lifetime = -1; + $filename = $this->getFilename($id); + + if ( ! file_exists($filename)) { + return false; + } + + $resource = fopen($filename, "r"); + + if (false !== ($line = fgets($resource))) { + $lifetime = (integer) $line; + } + + if ($lifetime !== 0 && $lifetime < time()) { + fclose($resource); + + return false; + } + + while (false !== ($line = fgets($resource))) { + $data .= $line; + } + + fclose($resource); + + return unserialize($data); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + $lifetime = -1; + $filename = $this->getFilename($id); + + if ( ! file_exists($filename)) { + return false; + } + + $resource = fopen($filename, "r"); + + if (false !== ($line = fgets($resource))) { + $lifetime = (integer) $line; + } + + fclose($resource); + + return $lifetime === 0 || $lifetime > time(); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + if ($lifeTime > 0) { + $lifeTime = time() + $lifeTime; + } + + $data = serialize($data); + $filename = $this->getFilename($id); + $filepath = pathinfo($filename, PATHINFO_DIRNAME); + + if ( ! is_dir($filepath)) { + mkdir($filepath, 0777, true); + } + + return file_put_contents($filename, $lifeTime . PHP_EOL . $data); + } +} \ No newline at end of file diff --git a/src/core/libs/Doctrine/Common/Cache/MemcacheCache.php b/src/core/libs/Doctrine/Common/Cache/MemcacheCache.php new file mode 100644 index 0000000..5687b96 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/MemcacheCache.php @@ -0,0 +1,121 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +use \Memcache; + +/** + * Memcache cache provider. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author David Abdemoulaie <dave@hobodave.com> + */ +class MemcacheCache extends CacheProvider +{ + /** + * @var Memcache + */ + private $memcache; + + /** + * Sets the memcache instance to use. + * + * @param Memcache $memcache + */ + public function setMemcache(Memcache $memcache) + { + $this->memcache = $memcache; + } + + /** + * Gets the memcache instance used by the cache. + * + * @return Memcache + */ + public function getMemcache() + { + return $this->memcache; + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return $this->memcache->get($id); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return (bool) $this->memcache->get($id); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + if ($lifeTime > 30 * 24 * 3600) { + $lifeTime = time() + $lifeTime; + } + return $this->memcache->set($id, $data, 0, (int) $lifeTime); + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return $this->memcache->delete($id); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return $this->memcache->flush(); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $stats = $this->memcache->getStats(); + return array( + Cache::STATS_HITS => $stats['get_hits'], + Cache::STATS_MISSES => $stats['get_misses'], + Cache::STATS_UPTIME => $stats['uptime'], + Cache::STATS_MEMORY_USAGE => $stats['bytes'], + Cache::STATS_MEMORY_AVAILIABLE => $stats['limit_maxbytes'], + ); + } +} diff --git a/src/core/libs/Doctrine/Common/Cache/MemcachedCache.php b/src/core/libs/Doctrine/Common/Cache/MemcachedCache.php new file mode 100644 index 0000000..75f1345 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/MemcachedCache.php @@ -0,0 +1,124 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +use \Memcached; + +/** + * Memcached cache provider. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.2 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author David Abdemoulaie <dave@hobodave.com> + */ +class MemcachedCache extends CacheProvider +{ + /** + * @var Memcached + */ + private $memcached; + + /** + * Sets the memcache instance to use. + * + * @param Memcached $memcached + */ + public function setMemcached(Memcached $memcached) + { + $this->memcached = $memcached; + } + + /** + * Gets the memcached instance used by the cache. + * + * @return Memcached + */ + public function getMemcached() + { + return $this->memcached; + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return $this->memcached->get($id); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return (false !== $this->memcached->get($id)); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + if ($lifeTime > 30 * 24 * 3600) { + $lifeTime = time() + $lifeTime; + } + return $this->memcached->set($id, $data, (int) $lifeTime); + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return $this->memcached->delete($id); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return $this->memcached->flush(); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $stats = $this->memcached->getStats(); + $servers = $this->memcached->getServerList(); + $key = $servers[0]['host'] . ':' . $servers[0]['port']; + $stats = $stats[$key]; + return array( + Cache::STATS_HITS => $stats['get_hits'], + Cache::STATS_MISSES => $stats['get_misses'], + Cache::STATS_UPTIME => $stats['uptime'], + Cache::STATS_MEMORY_USAGE => $stats['bytes'], + Cache::STATS_MEMORY_AVAILIABLE => $stats['limit_maxbytes'], + ); + } +} diff --git a/src/core/libs/Doctrine/Common/Cache/PhpFileCache.php b/src/core/libs/Doctrine/Common/Cache/PhpFileCache.php new file mode 100644 index 0000000..0971cd9 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/PhpFileCache.php @@ -0,0 +1,108 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +/** + * Php file cache driver. + * + * @since 2.3 + * @author Fabio B. Silva <fabio.bat.silva@gmail.com> + */ +class PhpFileCache extends FileCache +{ + const EXTENSION = '.doctrinecache.php'; + + /** + * {@inheritdoc} + */ + protected $extension = self::EXTENSION; + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + $filename = $this->getFilename($id); + + if ( ! file_exists($filename)) { + return false; + } + + $value = include $filename; + + if ($value['lifetime'] !== 0 && $value['lifetime'] < time()) { + return false; + } + + return $value['data']; + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + $filename = $this->getFilename($id); + + if ( ! file_exists($filename)) { + return false; + } + + $value = include $filename; + + return $value['lifetime'] === 0 || $value['lifetime'] > time(); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + if ($lifeTime > 0) { + $lifeTime = time() + $lifeTime; + } + + if (is_object($data) && ! method_exists($data, '__set_state')) { + throw new \InvalidArgumentException( + "Invalid argument given, PhpFileCache only allows objects that implement __set_state() " . + "and fully support var_export(). You can use the FilesystemCache to save arbitrary object " . + "graphs using serialize()/deserialize()." + ); + } + + $filename = $this->getFilename($id); + $filepath = pathinfo($filename, PATHINFO_DIRNAME); + + if ( ! is_dir($filepath)) { + mkdir($filepath, 0777, true); + } + + $value = array( + 'lifetime' => $lifeTime, + 'data' => $data + ); + + $value = var_export($value, true); + $code = sprintf('<?php return %s;', $value); + + return file_put_contents($filename, $code); + } +} diff --git a/src/core/libs/Doctrine/Common/Cache/RedisCache.php b/src/core/libs/Doctrine/Common/Cache/RedisCache.php new file mode 100644 index 0000000..5d4814b --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/RedisCache.php @@ -0,0 +1,119 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +use Redis; + +/** + * Redis cache provider. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.2 + * @author Osman Ungur <osmanungur@gmail.com> + */ +class RedisCache extends CacheProvider +{ + /** + * @var Redis + */ + private $redis; + + /** + * Sets the redis instance to use. + * + * @param Redis $redis + */ + public function setRedis(Redis $redis) + { + $redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_IGBINARY); + $this->redis = $redis; + } + + /** + * Gets the redis instance used by the cache. + * + * @return Redis + */ + public function getRedis() + { + return $this->redis; + } + + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return $this->redis->get($id); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return $this->redis->exists($id); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + $result = $this->redis->set($id, $data); + if ($lifeTime > 0) { + $this->redis->expire($id, $lifeTime); + } + return $result; + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return $this->redis->delete($id); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return $this->redis->flushDB(); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $info = $this->redis->info(); + return array( + Cache::STATS_HITS => false, + Cache::STATS_MISSES => false, + Cache::STATS_UPTIME => $info['uptime_in_seconds'], + Cache::STATS_MEMORY_USAGE => $info['used_memory'], + Cache::STATS_MEMORY_AVAILIABLE => false + ); + } +} diff --git a/src/core/libs/Doctrine/Common/Cache/WinCacheCache.php b/src/core/libs/Doctrine/Common/Cache/WinCacheCache.php new file mode 100644 index 0000000..777d0fd --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/WinCacheCache.php @@ -0,0 +1,93 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +/** + * WinCache cache provider. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.2 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author David Abdemoulaie <dave@hobodave.com> + */ +class WinCacheCache extends CacheProvider +{ + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return wincache_ucache_get($id); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return wincache_ucache_exists($id); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + return (bool) wincache_ucache_set($id, $data, (int) $lifeTime); + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return wincache_ucache_delete($id); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + return wincache_ucache_clear(); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $info = wincache_ucache_info(); + $meminfo = wincache_ucache_meminfo(); + + return array( + Cache::STATS_HITS => $info['total_hit_count'], + Cache::STATS_MISSES => $info['total_miss_count'], + Cache::STATS_UPTIME => $info['total_cache_uptime'], + Cache::STATS_MEMORY_USAGE => $meminfo['memory_total'], + Cache::STATS_MEMORY_AVAILIABLE => $meminfo['memory_free'], + ); + } +} diff --git a/src/core/libs/Doctrine/Common/Cache/XcacheCache.php b/src/core/libs/Doctrine/Common/Cache/XcacheCache.php new file mode 100644 index 0000000..8733e26 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/XcacheCache.php @@ -0,0 +1,110 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +/** + * Xcache cache driver. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author David Abdemoulaie <dave@hobodave.com> + */ +class XcacheCache extends CacheProvider +{ + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return $this->doContains($id) ? unserialize(xcache_get($id)) : false; + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return xcache_isset($id); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + return xcache_set($id, serialize($data), (int) $lifeTime); + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return xcache_unset($id); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + $this->checkAuthorization(); + + xcache_clear_cache(XC_TYPE_VAR, 0); + + return true; + } + + /** + * Checks that xcache.admin.enable_auth is Off + * + * @throws \BadMethodCallException When xcache.admin.enable_auth is On + * @return void + */ + protected function checkAuthorization() + { + if (ini_get('xcache.admin.enable_auth')) { + throw new \BadMethodCallException('To use all features of \Doctrine\Common\Cache\XcacheCache, you must set "xcache.admin.enable_auth" to "Off" in your php.ini.'); + } + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + $this->checkAuthorization(); + + $info = xcache_info(XC_TYPE_VAR, 0); + return array( + Cache::STATS_HITS => $info['hits'], + Cache::STATS_MISSES => $info['misses'], + Cache::STATS_UPTIME => null, + Cache::STATS_MEMORY_USAGE => $info['size'], + Cache::STATS_MEMORY_AVAILIABLE => $info['avail'], + ); + } +} diff --git a/src/core/libs/Doctrine/Common/Cache/ZendDataCache.php b/src/core/libs/Doctrine/Common/Cache/ZendDataCache.php new file mode 100644 index 0000000..fc90bc6 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Cache/ZendDataCache.php @@ -0,0 +1,84 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Cache; + +/** + * Zend Data Cache cache driver. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Ralph Schindler <ralph.schindler@zend.com> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + */ +class ZendDataCache extends CacheProvider +{ + /** + * {@inheritdoc} + */ + protected function doFetch($id) + { + return zend_shm_cache_fetch($id); + } + + /** + * {@inheritdoc} + */ + protected function doContains($id) + { + return (false !== zend_shm_cache_fetch($id)); + } + + /** + * {@inheritdoc} + */ + protected function doSave($id, $data, $lifeTime = 0) + { + return zend_shm_cache_store($id, $data, $lifeTime); + } + + /** + * {@inheritdoc} + */ + protected function doDelete($id) + { + return zend_shm_cache_delete($id); + } + + /** + * {@inheritdoc} + */ + protected function doFlush() + { + $namespace = $this->getNamespace(); + if (empty($namespace)) { + return zend_shm_cache_clear(); + } + return zend_shm_cache_clear($namespace); + } + + /** + * {@inheritdoc} + */ + protected function doGetStats() + { + return null; + } +} diff --git a/src/core/libs/Doctrine/Common/ClassLoader.php b/src/core/libs/Doctrine/Common/ClassLoader.php new file mode 100644 index 0000000..45024e1 --- /dev/null +++ b/src/core/libs/Doctrine/Common/ClassLoader.php @@ -0,0 +1,263 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common; + +/** + * A <tt>ClassLoader</tt> is an autoloader for class files that can be + * installed on the SPL autoload stack. It is a class loader that either loads only classes + * of a specific namespace or all namespaces and it is suitable for working together + * with other autoloaders in the SPL autoload stack. + * + * If no include path is configured through the constructor or {@link setIncludePath}, a ClassLoader + * relies on the PHP <code>include_path</code>. + * + * @author Roman Borschel <roman@code-factory.org> + * @since 2.0 + */ +class ClassLoader +{ + /** + * @var string PHP file extension + */ + protected $fileExtension = '.php'; + + /** + * @var string Current namespace + */ + protected $namespace; + + /** + * @var string Current include path + */ + protected $includePath; + + /** + * @var string PHP namespace separator + */ + protected $namespaceSeparator = '\\'; + + /** + * Creates a new <tt>ClassLoader</tt> that loads classes of the + * specified namespace from the specified include path. + * + * If no include path is given, the ClassLoader relies on the PHP include_path. + * If neither a namespace nor an include path is given, the ClassLoader will + * be responsible for loading all classes, thereby relying on the PHP include_path. + * + * @param string $ns The namespace of the classes to load. + * @param string $includePath The base include path to use. + */ + public function __construct($ns = null, $includePath = null) + { + $this->namespace = $ns; + $this->includePath = $includePath; + } + + /** + * Sets the namespace separator used by classes in the namespace of this ClassLoader. + * + * @param string $sep The separator to use. + */ + public function setNamespaceSeparator($sep) + { + $this->namespaceSeparator = $sep; + } + + /** + * Gets the namespace separator used by classes in the namespace of this ClassLoader. + * + * @return string + */ + public function getNamespaceSeparator() + { + return $this->namespaceSeparator; + } + + /** + * Sets the base include path for all class files in the namespace of this ClassLoader. + * + * @param string $includePath + */ + public function setIncludePath($includePath) + { + $this->includePath = $includePath; + } + + /** + * Gets the base include path for all class files in the namespace of this ClassLoader. + * + * @return string + */ + public function getIncludePath() + { + return $this->includePath; + } + + /** + * Sets the file extension of class files in the namespace of this ClassLoader. + * + * @param string $fileExtension + */ + public function setFileExtension($fileExtension) + { + $this->fileExtension = $fileExtension; + } + + /** + * Gets the file extension of class files in the namespace of this ClassLoader. + * + * @return string + */ + public function getFileExtension() + { + return $this->fileExtension; + } + + /** + * Registers this ClassLoader on the SPL autoload stack. + */ + public function register() + { + spl_autoload_register(array($this, 'loadClass')); + } + + /** + * Removes this ClassLoader from the SPL autoload stack. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $className The name of the class to load. + + * @return boolean TRUE if the class has been successfully loaded, FALSE otherwise. + */ + public function loadClass($className) + { + if ($this->namespace !== null && strpos($className, $this->namespace.$this->namespaceSeparator) !== 0) { + return false; + } + + require ($this->includePath !== null ? $this->includePath . DIRECTORY_SEPARATOR : '') + . str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) + . $this->fileExtension; + + return true; + } + + /** + * Asks this ClassLoader whether it can potentially load the class (file) with + * the given name. + * + * @param string $className The fully-qualified name of the class. + * @return boolean TRUE if this ClassLoader can load the class, FALSE otherwise. + */ + public function canLoadClass($className) + { + if ($this->namespace !== null && strpos($className, $this->namespace.$this->namespaceSeparator) !== 0) { + return false; + } + + $file = str_replace($this->namespaceSeparator, DIRECTORY_SEPARATOR, $className) . $this->fileExtension; + + if ($this->includePath !== null) { + return file_exists($this->includePath . DIRECTORY_SEPARATOR . $file); + } + + return (false !== stream_resolve_include_path($file)); + } + + /** + * Checks whether a class with a given name exists. A class "exists" if it is either + * already defined in the current request or if there is an autoloader on the SPL + * autoload stack that is a) responsible for the class in question and b) is able to + * load a class file in which the class definition resides. + * + * If the class is not already defined, each autoloader in the SPL autoload stack + * is asked whether it is able to tell if the class exists. If the autoloader is + * a <tt>ClassLoader</tt>, {@link canLoadClass} is used, otherwise the autoload + * function of the autoloader is invoked and expected to return a value that + * evaluates to TRUE if the class (file) exists. As soon as one autoloader reports + * that the class exists, TRUE is returned. + * + * Note that, depending on what kinds of autoloaders are installed on the SPL + * autoload stack, the class (file) might already be loaded as a result of checking + * for its existence. This is not the case with a <tt>ClassLoader</tt>, who separates + * these responsibilities. + * + * @param string $className The fully-qualified name of the class. + * @return boolean TRUE if the class exists as per the definition given above, FALSE otherwise. + */ + public static function classExists($className) + { + if (class_exists($className, false) || interface_exists($className, false)) { + return true; + } + + foreach (spl_autoload_functions() as $loader) { + if (is_array($loader)) { // array(???, ???) + if (is_object($loader[0])) { + if ($loader[0] instanceof ClassLoader) { // array($obj, 'methodName') + if ($loader[0]->canLoadClass($className)) { + return true; + } + } else if ($loader[0]->{$loader[1]}($className)) { + return true; + } + } else if ($loader[0]::$loader[1]($className)) { // array('ClassName', 'methodName') + return true; + } + } else if ($loader instanceof \Closure) { // function($className) {..} + if ($loader($className)) { + return true; + } + } else if (is_string($loader) && $loader($className)) { // "MyClass::loadClass" + return true; + } + } + + return class_exists($className, false) || interface_exists($className, false); + } + + /** + * Gets the <tt>ClassLoader</tt> from the SPL autoload stack that is responsible + * for (and is able to load) the class with the given name. + * + * @param string $className The name of the class. + * @return ClassLoader The <tt>ClassLoader</tt> for the class or NULL if no such <tt>ClassLoader</tt> exists. + */ + public static function getClassLoader($className) + { + foreach (spl_autoload_functions() as $loader) { + if (is_array($loader) + && $loader[0] instanceof ClassLoader + && $loader[0]->canLoadClass($className) + ) { + return $loader[0]; + } + } + + return null; + } +} diff --git a/src/core/libs/Doctrine/Common/Collections/ArrayCollection.php b/src/core/libs/Doctrine/Common/Collections/ArrayCollection.php new file mode 100644 index 0000000..7c2b13e --- /dev/null +++ b/src/core/libs/Doctrine/Common/Collections/ArrayCollection.php @@ -0,0 +1,500 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Collections; + +use Closure, ArrayIterator; +use Doctrine\Common\Collections\Expr\Expression; +use Doctrine\Common\Collections\Expr\ClosureExpressionVisitor; + +/** + * An ArrayCollection is a Collection implementation that wraps a regular PHP array. + * + * @since 2.0 + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class ArrayCollection implements Collection, Selectable +{ + /** + * An array containing the entries of this collection. + * + * @var array + */ + private $_elements; + + /** + * Initializes a new ArrayCollection. + * + * @param array $elements + */ + public function __construct(array $elements = array()) + { + $this->_elements = $elements; + } + + /** + * Gets the PHP array representation of this collection. + * + * @return array The PHP array representation of this collection. + */ + public function toArray() + { + return $this->_elements; + } + + /** + * Sets the internal iterator to the first element in the collection and + * returns this element. + * + * @return mixed + */ + public function first() + { + return reset($this->_elements); + } + + /** + * Sets the internal iterator to the last element in the collection and + * returns this element. + * + * @return mixed + */ + public function last() + { + return end($this->_elements); + } + + /** + * Gets the current key/index at the current internal iterator position. + * + * @return mixed + */ + public function key() + { + return key($this->_elements); + } + + /** + * Moves the internal iterator position to the next element. + * + * @return mixed + */ + public function next() + { + return next($this->_elements); + } + + /** + * Gets the element of the collection at the current internal iterator position. + * + * @return mixed + */ + public function current() + { + return current($this->_elements); + } + + /** + * Removes an element with a specific key/index from the collection. + * + * @param mixed $key + * @return mixed The removed element or NULL, if no element exists for the given key. + */ + public function remove($key) + { + if (isset($this->_elements[$key])) { + $removed = $this->_elements[$key]; + unset($this->_elements[$key]); + + return $removed; + } + + return null; + } + + /** + * Removes the specified element from the collection, if it is found. + * + * @param mixed $element The element to remove. + * @return boolean TRUE if this collection contained the specified element, FALSE otherwise. + */ + public function removeElement($element) + { + $key = array_search($element, $this->_elements, true); + + if ($key !== false) { + unset($this->_elements[$key]); + + return true; + } + + return false; + } + + /** + * ArrayAccess implementation of offsetExists() + * + * @see containsKey() + * + * @param mixed $offset + * @return bool + */ + public function offsetExists($offset) + { + return $this->containsKey($offset); + } + + /** + * ArrayAccess implementation of offsetGet() + * + * @see get() + * + * @param mixed $offset + * @return mixed + */ + public function offsetGet($offset) + { + return $this->get($offset); + } + + /** + * ArrayAccess implementation of offsetSet() + * + * @see add() + * @see set() + * + * @param mixed $offset + * @param mixed $value + * @return bool + */ + public function offsetSet($offset, $value) + { + if ( ! isset($offset)) { + return $this->add($value); + } + return $this->set($offset, $value); + } + + /** + * ArrayAccess implementation of offsetUnset() + * + * @see remove() + * + * @param mixed $offset + * @return mixed + */ + public function offsetUnset($offset) + { + return $this->remove($offset); + } + + /** + * Checks whether the collection contains a specific key/index. + * + * @param mixed $key The key to check for. + * @return boolean TRUE if the given key/index exists, FALSE otherwise. + */ + public function containsKey($key) + { + return isset($this->_elements[$key]); + } + + /** + * Checks whether the given element is contained in the collection. + * Only element values are compared, not keys. The comparison of two elements + * is strict, that means not only the value but also the type must match. + * For objects this means reference equality. + * + * @param mixed $element + * @return boolean TRUE if the given element is contained in the collection, + * FALSE otherwise. + */ + public function contains($element) + { + foreach ($this->_elements as $collectionElement) { + if ($element === $collectionElement) { + return true; + } + } + + return false; + } + + /** + * Tests for the existence of an element that satisfies the given predicate. + * + * @param Closure $p The predicate. + * @return boolean TRUE if the predicate is TRUE for at least one element, FALSE otherwise. + */ + public function exists(Closure $p) + { + foreach ($this->_elements as $key => $element) { + if ($p($key, $element)) { + return true; + } + } + return false; + } + + /** + * Searches for a given element and, if found, returns the corresponding key/index + * of that element. The comparison of two elements is strict, that means not + * only the value but also the type must match. + * For objects this means reference equality. + * + * @param mixed $element The element to search for. + * @return mixed The key/index of the element or FALSE if the element was not found. + */ + public function indexOf($element) + { + return array_search($element, $this->_elements, true); + } + + /** + * Gets the element with the given key/index. + * + * @param mixed $key The key. + * @return mixed The element or NULL, if no element exists for the given key. + */ + public function get($key) + { + if (isset($this->_elements[$key])) { + return $this->_elements[$key]; + } + return null; + } + + /** + * Gets all keys/indexes of the collection elements. + * + * @return array + */ + public function getKeys() + { + return array_keys($this->_elements); + } + + /** + * Gets all elements. + * + * @return array + */ + public function getValues() + { + return array_values($this->_elements); + } + + /** + * Returns the number of elements in the collection. + * + * Implementation of the Countable interface. + * + * @return integer The number of elements in the collection. + */ + public function count() + { + return count($this->_elements); + } + + /** + * Adds/sets an element in the collection at the index / with the specified key. + * + * When the collection is a Map this is like put(key,value)/add(key,value). + * When the collection is a List this is like add(position,value). + * + * @param mixed $key + * @param mixed $value + */ + public function set($key, $value) + { + $this->_elements[$key] = $value; + } + + /** + * Adds an element to the collection. + * + * @param mixed $value + * @return boolean Always TRUE. + */ + public function add($value) + { + $this->_elements[] = $value; + return true; + } + + /** + * Checks whether the collection is empty. + * + * Note: This is preferable over count() == 0. + * + * @return boolean TRUE if the collection is empty, FALSE otherwise. + */ + public function isEmpty() + { + return ! $this->_elements; + } + + /** + * Gets an iterator for iterating over the elements in the collection. + * + * @return ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->_elements); + } + + /** + * Applies the given function to each element in the collection and returns + * a new collection with the elements returned by the function. + * + * @param Closure $func + * @return Collection + */ + public function map(Closure $func) + { + return new static(array_map($func, $this->_elements)); + } + + /** + * Returns all the elements of this collection that satisfy the predicate p. + * The order of the elements is preserved. + * + * @param Closure $p The predicate used for filtering. + * @return Collection A collection with the results of the filter operation. + */ + public function filter(Closure $p) + { + return new static(array_filter($this->_elements, $p)); + } + + /** + * Applies the given predicate p to all elements of this collection, + * returning true, if the predicate yields true for all elements. + * + * @param Closure $p The predicate. + * @return boolean TRUE, if the predicate yields TRUE for all elements, FALSE otherwise. + */ + public function forAll(Closure $p) + { + foreach ($this->_elements as $key => $element) { + if ( ! $p($key, $element)) { + return false; + } + } + + return true; + } + + /** + * Partitions this collection in two collections according to a predicate. + * Keys are preserved in the resulting collections. + * + * @param Closure $p The predicate on which to partition. + * @return array An array with two elements. The first element contains the collection + * of elements where the predicate returned TRUE, the second element + * contains the collection of elements where the predicate returned FALSE. + */ + public function partition(Closure $p) + { + $coll1 = $coll2 = array(); + foreach ($this->_elements as $key => $element) { + if ($p($key, $element)) { + $coll1[$key] = $element; + } else { + $coll2[$key] = $element; + } + } + return array(new static($coll1), new static($coll2)); + } + + /** + * Returns a string representation of this object. + * + * @return string + */ + public function __toString() + { + return __CLASS__ . '@' . spl_object_hash($this); + } + + /** + * Clears the collection. + */ + public function clear() + { + $this->_elements = array(); + } + + /** + * Extract a slice of $length elements starting at position $offset from the Collection. + * + * If $length is null it returns all elements from $offset to the end of the Collection. + * Keys have to be preserved by this method. Calling this method will only return the + * selected slice and NOT change the elements contained in the collection slice is called on. + * + * @param int $offset + * @param int $length + * @return array + */ + public function slice($offset, $length = null) + { + return array_slice($this->_elements, $offset, $length, true); + } + + /** + * Select all elements from a selectable that match the criteria and + * return a new collection containing these elements. + * + * @param Criteria $criteria + * @return Collection + */ + public function matching(Criteria $criteria) + { + $expr = $criteria->getWhereExpression(); + $filtered = $this->_elements; + + if ($expr) { + $visitor = new ClosureExpressionVisitor(); + $filter = $visitor->dispatch($expr); + $filtered = array_filter($filtered, $filter); + } + + if ($orderings = $criteria->getOrderings()) { + $next = null; + foreach (array_reverse($orderings) as $field => $ordering) { + $next = ClosureExpressionVisitor::sortByField($field, $ordering == 'DESC' ? -1 : 1, $next); + } + + usort($filtered, $next); + } + + $offset = $criteria->getFirstResult(); + $length = $criteria->getMaxResults(); + + if ($offset || $length) { + $filtered = array_slice($filtered, (int)$offset, $length); + } + + return new static($filtered); + } +} + diff --git a/src/core/libs/Doctrine/Common/Collections/Collection.php b/src/core/libs/Doctrine/Common/Collections/Collection.php new file mode 100644 index 0000000..51eb9e7 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Collections/Collection.php @@ -0,0 +1,243 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Collections; + +use Closure, Countable, IteratorAggregate, ArrayAccess; + +/** + * The missing (SPL) Collection/Array/OrderedMap interface. + * + * A Collection resembles the nature of a regular PHP array. That is, + * it is essentially an <b>ordered map</b> that can also be used + * like a list. + * + * A Collection has an internal iterator just like a PHP array. In addition, + * a Collection can be iterated with external iterators, which is preferrable. + * To use an external iterator simply use the foreach language construct to + * iterate over the collection (which calls {@link getIterator()} internally) or + * explicitly retrieve an iterator though {@link getIterator()} which can then be + * used to iterate over the collection. + * You can not rely on the internal iterator of the collection being at a certain + * position unless you explicitly positioned it before. Prefer iteration with + * external iterators. + * + * @since 2.0 + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +interface Collection extends Countable, IteratorAggregate, ArrayAccess +{ + /** + * Adds an element at the end of the collection. + * + * @param mixed $element The element to add. + * @return boolean Always TRUE. + */ + function add($element); + + /** + * Clears the collection, removing all elements. + */ + function clear(); + + /** + * Checks whether an element is contained in the collection. + * This is an O(n) operation, where n is the size of the collection. + * + * @param mixed $element The element to search for. + * @return boolean TRUE if the collection contains the element, FALSE otherwise. + */ + function contains($element); + + /** + * Checks whether the collection is empty (contains no elements). + * + * @return boolean TRUE if the collection is empty, FALSE otherwise. + */ + function isEmpty(); + + /** + * Removes the element at the specified index from the collection. + * + * @param string|integer $key The kex/index of the element to remove. + * @return mixed The removed element or NULL, if the collection did not contain the element. + */ + function remove($key); + + /** + * Removes the specified element from the collection, if it is found. + * + * @param mixed $element The element to remove. + * @return boolean TRUE if this collection contained the specified element, FALSE otherwise. + */ + function removeElement($element); + + /** + * Checks whether the collection contains an element with the specified key/index. + * + * @param string|integer $key The key/index to check for. + * @return boolean TRUE if the collection contains an element with the specified key/index, + * FALSE otherwise. + */ + function containsKey($key); + + /** + * Gets the element at the specified key/index. + * + * @param string|integer $key The key/index of the element to retrieve. + * @return mixed + */ + function get($key); + + /** + * Gets all keys/indices of the collection. + * + * @return array The keys/indices of the collection, in the order of the corresponding + * elements in the collection. + */ + function getKeys(); + + /** + * Gets all values of the collection. + * + * @return array The values of all elements in the collection, in the order they + * appear in the collection. + */ + function getValues(); + + /** + * Sets an element in the collection at the specified key/index. + * + * @param string|integer $key The key/index of the element to set. + * @param mixed $value The element to set. + */ + function set($key, $value); + + /** + * Gets a native PHP array representation of the collection. + * + * @return array + */ + function toArray(); + + /** + * Sets the internal iterator to the first element in the collection and + * returns this element. + * + * @return mixed + */ + function first(); + + /** + * Sets the internal iterator to the last element in the collection and + * returns this element. + * + * @return mixed + */ + function last(); + + /** + * Gets the key/index of the element at the current iterator position. + * + */ + function key(); + + /** + * Gets the element of the collection at the current iterator position. + * + */ + function current(); + + /** + * Moves the internal iterator position to the next element. + * + */ + function next(); + + /** + * Tests for the existence of an element that satisfies the given predicate. + * + * @param Closure $p The predicate. + * @return boolean TRUE if the predicate is TRUE for at least one element, FALSE otherwise. + */ + function exists(Closure $p); + + /** + * Returns all the elements of this collection that satisfy the predicate p. + * The order of the elements is preserved. + * + * @param Closure $p The predicate used for filtering. + * @return Collection A collection with the results of the filter operation. + */ + function filter(Closure $p); + + /** + * Applies the given predicate p to all elements of this collection, + * returning true, if the predicate yields true for all elements. + * + * @param Closure $p The predicate. + * @return boolean TRUE, if the predicate yields TRUE for all elements, FALSE otherwise. + */ + function forAll(Closure $p); + + /** + * Applies the given function to each element in the collection and returns + * a new collection with the elements returned by the function. + * + * @param Closure $func + * @return Collection + */ + function map(Closure $func); + + /** + * Partitions this collection in two collections according to a predicate. + * Keys are preserved in the resulting collections. + * + * @param Closure $p The predicate on which to partition. + * @return array An array with two elements. The first element contains the collection + * of elements where the predicate returned TRUE, the second element + * contains the collection of elements where the predicate returned FALSE. + */ + function partition(Closure $p); + + /** + * Gets the index/key of a given element. The comparison of two elements is strict, + * that means not only the value but also the type must match. + * For objects this means reference equality. + * + * @param mixed $element The element to search for. + * @return mixed The key/index of the element or FALSE if the element was not found. + */ + function indexOf($element); + + /** + * Extract a slice of $length elements starting at position $offset from the Collection. + * + * If $length is null it returns all elements from $offset to the end of the Collection. + * Keys have to be preserved by this method. Calling this method will only return the + * selected slice and NOT change the elements contained in the collection slice is called on. + * + * @param int $offset + * @param int $length + * @return array + */ + function slice($offset, $length = null); +} diff --git a/src/core/libs/Doctrine/Common/Collections/Criteria.php b/src/core/libs/Doctrine/Common/Collections/Criteria.php new file mode 100644 index 0000000..3b05549 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Collections/Criteria.php @@ -0,0 +1,240 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Collections; + +use Doctrine\Common\Collections\Expr\Expression; +use Doctrine\Common\Collections\Expr\CompositeExpression; + +/** + * Criteria for filtering Selectable collections. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.3 + */ +class Criteria +{ + /** + * @var string + */ + const ASC = 'ASC'; + + /** + * @var string + */ + const DESC = 'DESC'; + + /** + * @var \Doctrine\Common\Collections\ExpressionBuilder + */ + private static $expressionBuilder; + + /** + * @var \Doctrine\Common\Collections\Expr\Expression + */ + private $expression; + + /** + * @var array|null + */ + private $orderings; + + /** + * @var int + */ + private $firstResult; + + /** + * @var int + */ + private $maxResults; + + /** + * Creates an instance of the class. + * + * @return Criteria + */ + public static function create() + { + return new static(); + } + + /** + * Return the expression builder. + * + * @return \Doctrine\Common\Collections\ExpressionBuilder + */ + public static function expr() + { + if (self::$expressionBuilder === null) { + self::$expressionBuilder = new ExpressionBuilder(); + } + return self::$expressionBuilder; + } + + /** + * Construct new criteria + * + * @param Expression $expression + * @param array $orderings + * @param int $firstResult + * @param int $maxResults + */ + public function __construct(Expression $expression = null, array $orderings = null, $firstResult = null, $maxResults = null) + { + $this->expression = $expression; + $this->orderings = $orderings; + $this->firstResult = $firstResult; + $this->maxResults = $maxResults; + } + + /** + * Set the where expression to evaluate when this criteria is searched for. + * + * @param Expression + * @return Criteria + */ + public function where(Expression $expression) + { + $this->expression = $expression; + return $this; + } + + /** + * Append the where expression to evaluate when this criteria is searched for + * using an AND with previous expression. + * + * @param Expression + * @return Criteria + */ + public function andWhere(Expression $expression) + { + if ($this->expression === null) { + return $this->where($expression); + } + + $this->expression = new CompositeExpression(CompositeExpression::TYPE_AND, array( + $this->expression, $expression + )); + + return $this; + } + + /** + * Append the where expression to evaluate when this criteria is searched for + * using an OR with previous expression. + * + * @param Expression + * @return Criteria + */ + public function orWhere(Expression $expression) + { + if ($this->expression === null) { + return $this->where($expression); + } + + $this->expression = new CompositeExpression(CompositeExpression::TYPE_OR, array( + $this->expression, $expression + )); + + return $this; + } + + /** + * Get the expression attached to this criteria. + * + * @return Expression|null + */ + public function getWhereExpression() + { + return $this->expression; + } + + /** + * Get current orderings of this Criteria + * + * @return array + */ + public function getOrderings() + { + return $this->orderings; + } + + /** + * Set the ordering of the result of this criteria. + * + * Keys are field and values are the order, being either ASC or DESC. + * + * @see Criteria::ASC + * @see Criteria::DESC + * + * @param array + * @return Criteria + */ + public function orderBy(array $orderings) + { + $this->orderings = $orderings; + return $this; + } + + /** + * Get current first result option of the critera. + * + * @return firstResult. + */ + public function getFirstResult() + { + return $this->firstResult; + } + + /** + * Set number of first result that this criteria should return. + * + * @param firstResult the value to set. + * @return Criteria + */ + public function setFirstResult($firstResult) + { + $this->firstResult = $firstResult; + return $this; + } + + /** + * Get maxResults. + * + * @return maxResults. + */ + public function getMaxResults() + { + return $this->maxResults; + } + + /** + * Set maxResults. + * + * @param maxResults the value to set. + * @return Criteria + */ + public function setMaxResults($maxResults) + { + $this->maxResults = $maxResults; + return $this; + } +} + diff --git a/src/core/libs/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php b/src/core/libs/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php new file mode 100644 index 0000000..06ccb04 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Collections/Expr/ClosureExpressionVisitor.php @@ -0,0 +1,195 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Collections\Expr; + +/** + * Walks an expression graph and turns it into a PHP closure. + * + * This closure can be used with {@Collection#filter()} and is used internally + * by {@ArrayCollection#select()}. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.3 + */ +class ClosureExpressionVisitor extends ExpressionVisitor +{ + /** + * Access the field of a given object. This field has to be public directly + * or indirectly (through an accessor get* or a magic method, __get, __call). + * + * is*() is not supported. + * + * @return mixed + */ + static public function getObjectFieldValue($object, $field) + { + $accessor = "get" . $field; + + if (method_exists($object, $accessor) || method_exists($object, '__call')) { + return $object->$accessor(); + } + + if ($object instanceof \ArrayAccess) { + return $object[$field]; + } + + return $object->$field; + } + + /** + * Helper for sorting arrays of objects based on multiple fields + + * orientations. + * + * @param string $name + * @param int $orientation + * @param Closure $next + * @return Closure + */ + static public function sortByField($name, $orientation = 1, \Closure $next = null) + { + if (!$next) { + $next = function() { + return 0; + }; + } + + return function ($a, $b) use ($name, $next, $orientation) { + $aValue = ClosureExpressionVisitor::getObjectFieldValue($a, $name); + $bValue = ClosureExpressionVisitor::getObjectFieldValue($b, $name); + + if ($aValue === $bValue) { + return $next($a, $b); + } + + return (($aValue > $bValue) ? 1 : -1) * $orientation; + }; + } + + /** + * {@inheritDoc} + */ + public function walkComparison(Comparison $comparison) + { + $field = $comparison->getField(); + $value = $comparison->getValue()->getValue(); // shortcut for walkValue() + + switch ($comparison->getOperator()) { + case Comparison::EQ: + case Comparison::IS: + return function ($object) use ($field, $value) { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) === $value; + }; + + case Comparison::NEQ: + return function ($object) use ($field, $value) { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) !== $value; + }; + + case Comparison::LT: + return function ($object) use ($field, $value) { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) < $value; + }; + + case Comparison::LTE: + return function ($object) use ($field, $value) { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) <= $value; + }; + + case Comparison::GT: + return function ($object) use ($field, $value) { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) > $value; + }; + + case Comparison::GTE: + return function ($object) use ($field, $value) { + return ClosureExpressionVisitor::getObjectFieldValue($object, $field) >= $value; + }; + + case Comparison::IN: + return function ($object) use ($field, $value) { + return in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value); + }; + + case Comparison::NIN: + return function ($object) use ($field, $value) { + return ! in_array(ClosureExpressionVisitor::getObjectFieldValue($object, $field), $value); + }; + + default: + throw new \RuntimeException("Unknown comparison operator: " . $comparison->getOperator()); + } + } + + /** + * {@inheritDoc} + */ + public function walkValue(Value $value) + { + return $value->getValue(); + } + + /** + * {@inheritDoc} + */ + public function walkCompositeExpression(CompositeExpression $expr) + { + $expressionList = array(); + + foreach ($expr->getExpressionList() as $child) { + $expressionList[] = $this->dispatch($child); + } + + switch($expr->getType()) { + case CompositeExpression::TYPE_AND: + return $this->andExpressions($expressionList); + + case CompositeExpression::TYPE_OR: + return $this->orExpressions($expressionList); + + default: + throw new \RuntimeException("Unknown composite " . $expr->getType()); + } + } + + private function andExpressions($expressions) + { + return function ($object) use ($expressions) { + foreach ($expressions as $expression) { + if ( ! $expression($object)) { + return false; + } + } + return true; + }; + } + + private function orExpressions($expressions) + { + return function ($object) use ($expressions) { + foreach ($expressions as $expression) { + if ($expression($object)) { + return true; + } + } + return false; + }; + } +} + diff --git a/src/core/libs/Doctrine/Common/Collections/Expr/Comparison.php b/src/core/libs/Doctrine/Common/Collections/Expr/Comparison.php new file mode 100644 index 0000000..29cfcff --- /dev/null +++ b/src/core/libs/Doctrine/Common/Collections/Expr/Comparison.php @@ -0,0 +1,75 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Collections\Expr; + +/** + * Comparison of a field with a value by the given operator. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.3 + */ +class Comparison implements Expression +{ + const EQ = '='; + const NEQ = '<>'; + const LT = '<'; + const LTE = '<='; + const GT = '>'; + const GTE = '>='; + const IS = 'IS'; + const IN = 'IN'; + const NIN = 'NIN'; + + private $field; + private $op; + private $value; + + public function __construct($field, $operator, $value) + { + if ( ! ($value instanceof Value)) { + $value = new Value($value); + } + + $this->field = $field; + $this->op = $operator; + $this->value = $value; + } + + public function getField() + { + return $this->field; + } + + public function getValue() + { + return $this->value; + } + + public function getOperator() + { + return $this->op; + } + + public function visit(ExpressionVisitor $visitor) + { + return $visitor->walkComparison($this); + } +} + diff --git a/src/core/libs/Doctrine/Common/Collections/Expr/CompositeExpression.php b/src/core/libs/Doctrine/Common/Collections/Expr/CompositeExpression.php new file mode 100644 index 0000000..fe917cf --- /dev/null +++ b/src/core/libs/Doctrine/Common/Collections/Expr/CompositeExpression.php @@ -0,0 +1,72 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Collections\Expr; + +/** + * Expression of Expressions combined by AND or OR operation. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.3 + */ +class CompositeExpression implements Expression +{ + const TYPE_AND = 'AND'; + const TYPE_OR = 'OR'; + + private $type; + private $expressions = array(); + + public function __construct($type, array $expressions) + { + $this->type = $type; + + foreach ($expressions as $expr) { + if ($expr instanceof Value) { + throw new \RuntimeException("Values are not supported expressions as children of and/or expressions."); + } + if ( ! ($expr instanceof Expression)) { + throw new \RuntimeException("No expression given to CompositeExpression."); + } + + $this->expressions[] = $expr; + } + } + + /** + * Return the list of expressions nested in this composite. + * + * @return Expression[] + */ + public function getExpressionList() + { + return $this->expressions; + } + + public function getType() + { + return $this->type; + } + + public function visit(ExpressionVisitor $visitor) + { + return $visitor->walkCompositeExpression($this); + } +} + diff --git a/src/core/libs/Doctrine/Common/Collections/Expr/Expression.php b/src/core/libs/Doctrine/Common/Collections/Expr/Expression.php new file mode 100644 index 0000000..b0762ad --- /dev/null +++ b/src/core/libs/Doctrine/Common/Collections/Expr/Expression.php @@ -0,0 +1,31 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Collections\Expr; + +/** + * Expression for the {@link Selectable} interface. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +interface Expression +{ + public function visit(ExpressionVisitor $visitor); +} + diff --git a/src/core/libs/Doctrine/Common/Collections/Expr/ExpressionVisitor.php b/src/core/libs/Doctrine/Common/Collections/Expr/ExpressionVisitor.php new file mode 100644 index 0000000..5e69b98 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Collections/Expr/ExpressionVisitor.php @@ -0,0 +1,81 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Collections\Expr; + +/** + * An Expression visitor walks a graph of expressions and turns them into a + * query for the underlying implementation. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +abstract class ExpressionVisitor +{ + /** + * Convert a comparison expression into the target query language output + * + * @param Comparison $comparison + * + * @return mixed + */ + abstract public function walkComparison(Comparison $comparison); + + /** + * Convert a value expression into the target query language part. + * + * @param Value $value + * + * @return mixed + */ + abstract public function walkValue(Value $value); + + /** + * Convert a composite expression into the target query language output + * + * @param CompositeExpression $expr + * + * @return mixed + */ + abstract public function walkCompositeExpression(CompositeExpression $expr); + + /** + * Dispatch walking an expression to the appropriate handler. + * + * @param Expression + * + * @return mixed + */ + public function dispatch(Expression $expr) + { + switch (true) { + case ($expr instanceof Comparison): + return $this->walkComparison($expr); + + case ($expr instanceof Value): + return $this->walkValue($expr); + + case ($expr instanceof CompositeExpression): + return $this->walkCompositeExpression($expr); + + default: + throw new \RuntimeException("Unknown Expression " . get_class($expr)); + } + } +} + diff --git a/src/core/libs/Doctrine/Common/Collections/Expr/Value.php b/src/core/libs/Doctrine/Common/Collections/Expr/Value.php new file mode 100644 index 0000000..f0df11a --- /dev/null +++ b/src/core/libs/Doctrine/Common/Collections/Expr/Value.php @@ -0,0 +1,41 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Collections\Expr; + +class Value implements Expression +{ + private $value; + + public function __construct($value) + { + $this->value = $value; + } + + public function getValue() + { + return $this->value; + } + + public function visit(ExpressionVisitor $visitor) + { + return $visitor->walkValue($this); + } +} + diff --git a/src/core/libs/Doctrine/Common/Collections/ExpressionBuilder.php b/src/core/libs/Doctrine/Common/Collections/ExpressionBuilder.php new file mode 100644 index 0000000..b53f0cd --- /dev/null +++ b/src/core/libs/Doctrine/Common/Collections/ExpressionBuilder.php @@ -0,0 +1,149 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYvalue HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYvalue + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Collections; + +use Doctrine\Common\Collections\Expr\Comparison; +use Doctrine\Common\Collections\Expr\CompositeExpression; +use Doctrine\Common\Collections\Expr\Value; + +/** + * Builder for Expressions in the {@link Selectable} interface. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.3 + */ +class ExpressionBuilder +{ + /** + * @return CompositeExpression + */ + public function andX($x = null) + { + return new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); + } + + /** + * @return CompositeExpression + */ + public function orX($x = null) + { + return new CompositeExpression(CompositeExpression::TYPE_OR, func_get_args()); + } + + /** + * @param string $field + * @param mixed $value + * + * @return Comparison + */ + public function eq($field, $value) + { + return new Comparison($field, Comparison::EQ, new Value($value)); + } + + /** + * @param string $field + * @param mixed $value + * + * @return Comparison + */ + public function gt($field, $value) + { + return new Comparison($field, Comparison::GT, new Value($value)); + } + + /** + * @param string $field + * @param mixed $value + * + * @return Comparison + */ + public function lt($field, $value) + { + return new Comparison($field, Comparison::LT, new Value($value)); + } + + /** + * @param string $field + * @param mixed $value + * + * @return Comparison + */ + public function gte($field, $value) + { + return new Comparison($field, Comparison::GTE, new Value($value)); + } + + /** + * @param string $field + * @param mixed $value + * + * @return Comparison + */ + public function lte($field, $value) + { + return new Comparison($field, Comparison::LTE, new Value($value)); + } + + /** + * @param string $field + * @param mixed $value + * + * @return Comparison + */ + public function neq($field, $value) + { + return new Comparison($field, Comparison::NEQ, new Value($value)); + } + + /** + * @param string $field + * @param mixed $value + * + * @return Comparison + */ + public function isNull($field) + { + return new Comparison($field, Comparison::IS, new Value(null)); + } + + /** + * @param string $field + * @param mixed $value + * + * @return Comparison + */ + public function in($field, array $values) + { + return new Comparison($field, Comparison::IN, new Value($values)); + } + + /** + * @param string $field + * @param mixed $value + * + * @return Comparison + */ + public function notIn($field, array $values) + { + return new Comparison($field, Comparison::NIN, new Value($values)); + } +} + diff --git a/src/core/libs/Doctrine/Common/Collections/Selectable.php b/src/core/libs/Doctrine/Common/Collections/Selectable.php new file mode 100644 index 0000000..675d6ea --- /dev/null +++ b/src/core/libs/Doctrine/Common/Collections/Selectable.php @@ -0,0 +1,48 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Collections; + +/** + * Interface for collections that allow efficient filtering with an expression API. + * + * Goal of this interface is a backend independent method to fetch elements + * from a collections. {@link Expression} is crafted in a way that you can + * implement queries from both in-memory and database-backed collections. + * + * For database backed collections this allows very efficient access by + * utilizing the query APIs, for example SQL in the ORM. Applications using + * this API can implement efficient database access without having to ask the + * EntityManager or Repositories. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.3 + */ +interface Selectable +{ + /** + * Select all elements from a selectable that match the expression and + * return a new collection containing these elements. + * + * @param Criteria $criteria + * @return Collection + */ + function matching(Criteria $criteria); +} + diff --git a/src/core/libs/Doctrine/Common/CommonException.php b/src/core/libs/Doctrine/Common/CommonException.php new file mode 100644 index 0000000..6db7675 --- /dev/null +++ b/src/core/libs/Doctrine/Common/CommonException.php @@ -0,0 +1,28 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common; + +/** + * Base exception class for package Doctrine\Common + * @author heinrich + * + */ +class CommonException extends \Exception { +} diff --git a/src/core/libs/Doctrine/Common/Comparable.php b/src/core/libs/Doctrine/Common/Comparable.php new file mode 100644 index 0000000..20d065e --- /dev/null +++ b/src/core/libs/Doctrine/Common/Comparable.php @@ -0,0 +1,49 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\Common; + +/** + * Comparable interface that allows to compare two value objects to each other for similarity. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + */ +interface Comparable +{ + /** + * Compare the current object to the passed $other. + * + * Returns 0 if they are semantically equal, 1 if the other object + * is less than the current one, or -1 if its more than the current one. + * + * This method should not check for identity using ===, only for semantical equality for example + * when two different DateTime instances point to the exact same Date + TZ. + * + * @param mixed $other + * + * @return int + */ + public function compareTo($other); +} + diff --git a/src/core/libs/Doctrine/Common/EventArgs.php b/src/core/libs/Doctrine/Common/EventArgs.php new file mode 100644 index 0000000..a87eee8 --- /dev/null +++ b/src/core/libs/Doctrine/Common/EventArgs.php @@ -0,0 +1,67 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common; + +/** + * EventArgs is the base class for classes containing event data. + * + * This class contains no event data. It is used by events that do not pass state + * information to an event handler when an event is raised. The single empty EventArgs + * instance can be obtained through {@link getEmptyInstance}. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision: 3938 $ + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class EventArgs +{ + /** + * @var EventArgs Single instance of EventArgs + */ + private static $_emptyEventArgsInstance; + + /** + * Gets the single, empty and immutable EventArgs instance. + * + * This instance will be used when events are dispatched without any parameter, + * like this: EventManager::dispatchEvent('eventname'); + * + * The benefit from this is that only one empty instance is instantiated and shared + * (otherwise there would be instances for every dispatched in the abovementioned form) + * + * @see EventManager::dispatchEvent + * @link http://msdn.microsoft.com/en-us/library/system.eventargs.aspx + * @return EventArgs + */ + public static function getEmptyInstance() + { + if ( ! self::$_emptyEventArgsInstance) { + self::$_emptyEventArgsInstance = new EventArgs; + } + + return self::$_emptyEventArgsInstance; + } +} diff --git a/src/core/libs/Doctrine/Common/EventManager.php b/src/core/libs/Doctrine/Common/EventManager.php new file mode 100644 index 0000000..25aac44 --- /dev/null +++ b/src/core/libs/Doctrine/Common/EventManager.php @@ -0,0 +1,147 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common; + +/** + * The EventManager is the central point of Doctrine's event listener system. + * Listeners are registered on the manager and events are dispatched through the + * manager. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision: 3938 $ + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class EventManager +{ + /** + * Map of registered listeners. + * <event> => <listeners> + * + * @var array + */ + private $_listeners = array(); + + /** + * Dispatches an event to all registered listeners. + * + * @param string $eventName The name of the event to dispatch. The name of the event is + * the name of the method that is invoked on listeners. + * @param EventArgs $eventArgs The event arguments to pass to the event handlers/listeners. + * If not supplied, the single empty EventArgs instance is used. + * @return boolean + */ + public function dispatchEvent($eventName, EventArgs $eventArgs = null) + { + if (isset($this->_listeners[$eventName])) { + $eventArgs = $eventArgs === null ? EventArgs::getEmptyInstance() : $eventArgs; + + foreach ($this->_listeners[$eventName] as $listener) { + $listener->$eventName($eventArgs); + } + } + } + + /** + * Gets the listeners of a specific event or all listeners. + * + * @param string $event The name of the event. + * @return array The event listeners for the specified event, or all event listeners. + */ + public function getListeners($event = null) + { + return $event ? $this->_listeners[$event] : $this->_listeners; + } + + /** + * Checks whether an event has any registered listeners. + * + * @param string $event + * @return boolean TRUE if the specified event has any listeners, FALSE otherwise. + */ + public function hasListeners($event) + { + return isset($this->_listeners[$event]) && $this->_listeners[$event]; + } + + /** + * Adds an event listener that listens on the specified events. + * + * @param string|array $events The event(s) to listen on. + * @param object $listener The listener object. + */ + public function addEventListener($events, $listener) + { + // Picks the hash code related to that listener + $hash = spl_object_hash($listener); + + foreach ((array) $events as $event) { + // Overrides listener if a previous one was associated already + // Prevents duplicate listeners on same event (same instance only) + $this->_listeners[$event][$hash] = $listener; + } + } + + /** + * Removes an event listener from the specified events. + * + * @param string|array $events + * @param object $listener + */ + public function removeEventListener($events, $listener) + { + // Picks the hash code related to that listener + $hash = spl_object_hash($listener); + + foreach ((array) $events as $event) { + // Check if actually have this listener associated + if (isset($this->_listeners[$event][$hash])) { + unset($this->_listeners[$event][$hash]); + } + } + } + + /** + * Adds an EventSubscriber. The subscriber is asked for all the events he is + * interested in and added as a listener for these events. + * + * @param \Doctrine\Common\EventSubscriber $subscriber The subscriber. + */ + public function addEventSubscriber(EventSubscriber $subscriber) + { + $this->addEventListener($subscriber->getSubscribedEvents(), $subscriber); + } + + /** + * Removes an EventSubscriber. The subscriber is asked for all the events it is + * interested in and removed as a listener for these events. + * + * @param \Doctrine\Common\EventSubscriber $subscriber The subscriber. + */ + public function removeEventSubscriber(EventSubscriber $subscriber) + { + $this->removeEventListener($subscriber->getSubscribedEvents(), $subscriber); + } +} diff --git a/src/core/libs/Doctrine/Common/EventSubscriber.php b/src/core/libs/Doctrine/Common/EventSubscriber.php new file mode 100644 index 0000000..1458791 --- /dev/null +++ b/src/core/libs/Doctrine/Common/EventSubscriber.php @@ -0,0 +1,45 @@ +<?php +/* + * $Id: EventListener.php 4653 2008-07-10 17:17:58Z romanb $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common; + +/** + * An EventSubscriber knows himself what events he is interested in. + * If an EventSubscriber is added to an EventManager, the manager invokes + * {@link getSubscribedEvents} and registers the subscriber as a listener for all + * returned events. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +interface EventSubscriber +{ + /** + * Returns an array of events this subscriber wants to listen to. + * + * @return array + */ + function getSubscribedEvents(); +} diff --git a/src/core/libs/Doctrine/Common/Lexer.php b/src/core/libs/Doctrine/Common/Lexer.php new file mode 100644 index 0000000..8e2554c --- /dev/null +++ b/src/core/libs/Doctrine/Common/Lexer.php @@ -0,0 +1,266 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common; + +/** + * Base class for writing simple lexers, i.e. for creating small DSLs. + * + * @since 2.0 + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @todo Rename: AbstractLexer + */ +abstract class Lexer +{ + /** + * @var array Array of scanned tokens + */ + private $tokens = array(); + + /** + * @var integer Current lexer position in input string + */ + private $position = 0; + + /** + * @var integer Current peek of current lexer position + */ + private $peek = 0; + + /** + * @var array The next token in the input. + */ + public $lookahead; + + /** + * @var array The last matched/seen token. + */ + public $token; + + /** + * Sets the input data to be tokenized. + * + * The Lexer is immediately reset and the new input tokenized. + * Any unprocessed tokens from any previous input are lost. + * + * @param string $input The input to be tokenized. + */ + public function setInput($input) + { + $this->tokens = array(); + $this->reset(); + $this->scan($input); + } + + /** + * Resets the lexer. + */ + public function reset() + { + $this->lookahead = null; + $this->token = null; + $this->peek = 0; + $this->position = 0; + } + + /** + * Resets the peek pointer to 0. + */ + public function resetPeek() + { + $this->peek = 0; + } + + /** + * Resets the lexer position on the input to the given position. + * + * @param integer $position Position to place the lexical scanner + */ + public function resetPosition($position = 0) + { + $this->position = $position; + } + + /** + * Checks whether a given token matches the current lookahead. + * + * @param integer|string $token + * @return boolean + */ + public function isNextToken($token) + { + return null !== $this->lookahead && $this->lookahead['type'] === $token; + } + + /** + * Checks whether any of the given tokens matches the current lookahead + * + * @param array $tokens + * @return boolean + */ + public function isNextTokenAny(array $tokens) + { + return null !== $this->lookahead && in_array($this->lookahead['type'], $tokens, true); + } + + /** + * Moves to the next token in the input string. + * + * A token is an associative array containing three items: + * - 'value' : the string value of the token in the input string + * - 'type' : the type of the token (identifier, numeric, string, input + * parameter, none) + * - 'position' : the position of the token in the input string + * + * @return array|null the next token; null if there is no more tokens left + */ + public function moveNext() + { + $this->peek = 0; + $this->token = $this->lookahead; + $this->lookahead = (isset($this->tokens[$this->position])) + ? $this->tokens[$this->position++] : null; + + return $this->lookahead !== null; + } + + /** + * Tells the lexer to skip input tokens until it sees a token with the given value. + * + * @param string $type The token type to skip until. + */ + public function skipUntil($type) + { + while ($this->lookahead !== null && $this->lookahead['type'] !== $type) { + $this->moveNext(); + } + } + + /** + * Checks if given value is identical to the given token + * + * @param mixed $value + * @param integer $token + * @return boolean + */ + public function isA($value, $token) + { + return $this->getType($value) === $token; + } + + /** + * Moves the lookahead token forward. + * + * @return array | null The next token or NULL if there are no more tokens ahead. + */ + public function peek() + { + if (isset($this->tokens[$this->position + $this->peek])) { + return $this->tokens[$this->position + $this->peek++]; + } else { + return null; + } + } + + /** + * Peeks at the next token, returns it and immediately resets the peek. + * + * @return array|null The next token or NULL if there are no more tokens ahead. + */ + public function glimpse() + { + $peek = $this->peek(); + $this->peek = 0; + return $peek; + } + + /** + * Scans the input string for tokens. + * + * @param string $input a query string + */ + protected function scan($input) + { + static $regex; + + if ( ! isset($regex)) { + $regex = '/(' . implode(')|(', $this->getCatchablePatterns()) . ')|' + . implode('|', $this->getNonCatchablePatterns()) . '/i'; + } + + $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; + $matches = preg_split($regex, $input, -1, $flags); + + foreach ($matches as $match) { + // Must remain before 'value' assignment since it can change content + $type = $this->getType($match[0]); + + $this->tokens[] = array( + 'value' => $match[0], + 'type' => $type, + 'position' => $match[1], + ); + } + } + + /** + * Gets the literal for a given token. + * + * @param integer $token + * @return string + */ + public function getLiteral($token) + { + $className = get_class($this); + $reflClass = new \ReflectionClass($className); + $constants = $reflClass->getConstants(); + + foreach ($constants as $name => $value) { + if ($value === $token) { + return $className . '::' . $name; + } + } + + return $token; + } + + /** + * Lexical catchable patterns. + * + * @return array + */ + abstract protected function getCatchablePatterns(); + + /** + * Lexical non-catchable patterns. + * + * @return array + */ + abstract protected function getNonCatchablePatterns(); + + /** + * Retrieve token type. Also processes the token value if necessary. + * + * @param string $value + * @return integer + */ + abstract protected function getType(&$value); +} diff --git a/src/core/libs/Doctrine/Common/NotifyPropertyChanged.php b/src/core/libs/Doctrine/Common/NotifyPropertyChanged.php new file mode 100644 index 0000000..e32c0b9 --- /dev/null +++ b/src/core/libs/Doctrine/Common/NotifyPropertyChanged.php @@ -0,0 +1,45 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common; + +/** + * Contract for classes that provide the service of notifying listeners of + * changes to their properties. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision: 3938 $ + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +interface NotifyPropertyChanged +{ + /** + * Adds a listener that wants to be notified about property changes. + * + * @param PropertyChangedListener $listener + */ + function addPropertyChangedListener(PropertyChangedListener $listener); +} + diff --git a/src/core/libs/Doctrine/Common/Persistence/AbstractManagerRegistry.php b/src/core/libs/Doctrine/Common/Persistence/AbstractManagerRegistry.php new file mode 100644 index 0000000..94fcd05 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/AbstractManagerRegistry.php @@ -0,0 +1,259 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence; + +use Doctrine\Common\Persistence\ManagerRegistry; + +/** + * Abstract implementation of the ManagerRegistry contract. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.2 + * @author Fabien Potencier <fabien@symfony.com> + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Lukas Kahwe Smith <smith@pooteeweet.org> + */ +abstract class AbstractManagerRegistry implements ManagerRegistry +{ + /** + * @var string + */ + private $name; + + /** + * @var array + */ + private $connections; + + /** + * @var array + */ + private $managers; + + /** + * @var string + */ + private $defaultConnection; + + /** + * @var string + */ + private $defaultManager; + + /** + * @var string + */ + private $proxyInterfaceName; + + /** + * Constructor + * + * @param string $name + * @param array $connections + * @param array $managers + * @param string $defaultConnection + * @param string $defaultManager + * @param string $proxyInterfaceName + */ + public function __construct($name, array $connections, array $managers, $defaultConnection, $defaultManager, $proxyInterfaceName) + { + $this->name = $name; + $this->connections = $connections; + $this->managers = $managers; + $this->defaultConnection = $defaultConnection; + $this->defaultManager = $defaultManager; + $this->proxyInterfaceName = $proxyInterfaceName; + } + + /** + * Fetches/creates the given services + * + * A service in this context is connection or a manager instance + * + * @param string $name name of the service + * @return object instance of the given service + */ + abstract protected function getService($name); + + /** + * Resets the given services + * + * A service in this context is connection or a manager instance + * + * @param string $name name of the service + * @return void + */ + abstract protected function resetService($name); + + /** + * Get the name of the registry + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function getConnection($name = null) + { + if (null === $name) { + $name = $this->defaultConnection; + } + + if (!isset($this->connections[$name])) { + throw new \InvalidArgumentException(sprintf('Doctrine %s Connection named "%s" does not exist.', $this->name, $name)); + } + + return $this->getService($this->connections[$name]); + } + + /** + * {@inheritdoc} + */ + public function getConnectionNames() + { + return $this->connections; + } + + /** + * {@inheritdoc} + */ + public function getConnections() + { + $connections = array(); + foreach ($this->connections as $name => $id) { + $connections[$name] = $this->getService($id); + } + + return $connections; + } + + /** + * {@inheritdoc} + */ + public function getDefaultConnectionName() + { + return $this->defaultConnection; + } + + /** + * {@inheritdoc} + */ + public function getDefaultManagerName() + { + return $this->defaultManager; + } + + /** + * {@inheritdoc} + * + * @throws \InvalidArgumentException + */ + public function getManager($name = null) + { + if (null === $name) { + $name = $this->defaultManager; + } + + if (!isset($this->managers[$name])) { + throw new \InvalidArgumentException(sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name)); + } + + return $this->getService($this->managers[$name]); + } + + /** + * {@inheritdoc} + */ + public function getManagerForClass($class) + { + // Check for namespace alias + if (strpos($class, ':') !== false) { + list($namespaceAlias, $simpleClassName) = explode(':', $class); + $class = $this->getAliasNamespace($namespaceAlias) . '\\' . $simpleClassName; + } + + $proxyClass = new \ReflectionClass($class); + if ($proxyClass->implementsInterface($this->proxyInterfaceName)) { + $class = $proxyClass->getParentClass()->getName(); + } + + foreach ($this->managers as $id) { + $manager = $this->getService($id); + + if (!$manager->getMetadataFactory()->isTransient($class)) { + return $manager; + } + } + } + + /** + * {@inheritdoc} + */ + public function getManagerNames() + { + return $this->managers; + } + + /** + * {@inheritdoc} + */ + public function getManagers() + { + $dms = array(); + foreach ($this->managers as $name => $id) { + $dms[$name] = $this->getService($id); + } + + return $dms; + } + + /** + * {@inheritdoc} + */ + public function getRepository($persistentObjectName, $persistentManagerName = null) + { + return $this->getManager($persistentManagerName)->getRepository($persistentObjectName); + } + + /** + * {@inheritdoc} + */ + public function resetManager($name = null) + { + if (null === $name) { + $name = $this->defaultManager; + } + + if (!isset($this->managers[$name])) { + throw new \InvalidArgumentException(sprintf('Doctrine %s Manager named "%s" does not exist.', $this->name, $name)); + } + + // force the creation of a new document manager + // if the current one is closed + $this->resetService($this->managers[$name]); + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/ConnectionRegistry.php b/src/core/libs/Doctrine/Common/Persistence/ConnectionRegistry.php new file mode 100644 index 0000000..7d6f0cf --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/ConnectionRegistry.php @@ -0,0 +1,63 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence; + +/** + * Contract covering connection for a Doctrine persistence layer ManagerRegistry class to implement. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.2 + * @author Fabien Potencier <fabien@symfony.com> + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Lukas Kahwe Smith <smith@pooteeweet.org> + */ +interface ConnectionRegistry +{ + /** + * Gets the default connection name. + * + * @return string The default connection name + */ + function getDefaultConnectionName(); + + /** + * Gets the named connection. + * + * @param string $name The connection name (null for the default one) + * + * @return object + */ + function getConnection($name = null); + + /** + * Gets an array of all registered connections + * + * @return array An array of Connection instances + */ + function getConnections(); + + /** + * Gets all connection names. + * + * @return array An array of connection names + */ + function getConnectionNames(); +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Event/LifecycleEventArgs.php b/src/core/libs/Doctrine/Common/Persistence/Event/LifecycleEventArgs.php new file mode 100644 index 0000000..2fb7c47 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Event/LifecycleEventArgs.php @@ -0,0 +1,77 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\Common\Persistence\Event; + +use Doctrine\Common\EventArgs; +use Doctrine\Common\Persistence\ObjectManager; + +/** + * Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions + * of entities. + * + * @link www.doctrine-project.org + * @since 2.2 + * @author Roman Borschel <roman@code-factory.de> + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class LifecycleEventArgs extends EventArgs +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * @var object + */ + private $entity; + + /** + * Constructor + * + * @param object $entity + * @param ObjectManager $objectManager + */ + public function __construct($entity, ObjectManager $objectManager) + { + $this->entity = $entity; + $this->objectManager = $objectManager; + } + + /** + * Retrieve associated Entity. + * + * @return object + */ + public function getEntity() + { + return $this->entity; + } + + /** + * Retrieve associated ObjectManager. + * + * @return ObjectManager + */ + public function getObjectManager() + { + return $this->objectManager; + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Event/LoadClassMetadataEventArgs.php b/src/core/libs/Doctrine/Common/Persistence/Event/LoadClassMetadataEventArgs.php new file mode 100644 index 0000000..c014d73 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Event/LoadClassMetadataEventArgs.php @@ -0,0 +1,76 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Event; + +use Doctrine\Common\EventArgs; +use Doctrine\Common\Persistence\ObjectManager; +use Doctrine\Common\Persistence\Mapping\ClassMetadata; + +/** + * Class that holds event arguments for a loadMetadata event. + * + * @author Jonathan H. Wage <jonwage@gmail.com> + * @since 2.2 + */ +class LoadClassMetadataEventArgs extends EventArgs +{ + /** + * @var ClassMetadata + */ + private $classMetadata; + + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * Constructor. + * + * @param ClassMetadata $classMetadata + * @param ObjectManager $objectManager + */ + public function __construct(ClassMetadata $classMetadata, ObjectManager $objectManager) + { + $this->classMetadata = $classMetadata; + $this->objectManager = $objectManager; + } + + /** + * Retrieve associated ClassMetadata. + * + * @return ClassMetadata + */ + public function getClassMetadata() + { + return $this->classMetadata; + } + + /** + * Retrieve associated ObjectManager. + * + * @return ObjectManager + */ + public function getObjectManager() + { + return $this->objectManager; + } +} + diff --git a/src/core/libs/Doctrine/Common/Persistence/Event/ManagerEventArgs.php b/src/core/libs/Doctrine/Common/Persistence/Event/ManagerEventArgs.php new file mode 100644 index 0000000..f139365 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Event/ManagerEventArgs.php @@ -0,0 +1,59 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\Common\Persistence\Event; + +use Doctrine\Common\Persistence\ObjectManager; + +/** + * Provides event arguments for the preFlush event. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.2 + * @author Roman Borschel <roman@code-factory.de> + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class ManagerEventArgs extends \Doctrine\Common\EventArgs +{ + /** + * @var ObjectManager + */ + private $objectManager; + + /** + * Constructor. + * + * @param ObjectManager $objectManager + */ + public function __construct(ObjectManager $objectManager) + { + $this->objectManager = $objectManager; + } + + /** + * Retrieve associated ObjectManager. + * + * @return ObjectManager + */ + public function getObjectManager() + { + return $this->objectManager; + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Event/OnClearEventArgs.php b/src/core/libs/Doctrine/Common/Persistence/Event/OnClearEventArgs.php new file mode 100644 index 0000000..18b6554 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Event/OnClearEventArgs.php @@ -0,0 +1,84 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Event; + +/** + * Provides event arguments for the onClear event. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.2 + * @author Roman Borschel <roman@code-factory.de> + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class OnClearEventArgs extends \Doctrine\Common\EventArgs +{ + /** + * @var \Doctrine\Common\Persistence\ObjectManager + */ + private $objectManager; + + /** + * @var string + */ + private $entityClass; + + /** + * Constructor. + * + * @param \Doctrine\Common\Persistence\ObjectManager $objectManager + * @param string $entityClass Optional entity class + */ + public function __construct($objectManager, $entityClass = null) + { + $this->objectManager = $objectManager; + $this->entityClass = $entityClass; + } + + /** + * Retrieve associated ObjectManager. + * + * @return \Doctrine\Common\Persistence\ObjectManager + */ + public function getObjectManager() + { + return $this->objectManager; + } + + /** + * Name of the entity class that is cleared, or empty if all are cleared. + * + * @return string + */ + public function getEntityClass() + { + return $this->entityClass; + } + + /** + * Check if event clears all entities. + * + * @return bool + */ + public function clearsAllEntities() + { + return ($this->entityClass === null); + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Event/PreUpdateEventArgs.php b/src/core/libs/Doctrine/Common/Persistence/Event/PreUpdateEventArgs.php new file mode 100644 index 0000000..86ac819 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Event/PreUpdateEventArgs.php @@ -0,0 +1,133 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Event; + +use Doctrine\Common\EventArgs, + Doctrine\Common\Persistence\ObjectManager; + +/** + * Class that holds event arguments for a preUpdate event. + * + * @author Guilherme Blanco <guilehrmeblanco@hotmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.2 + */ +class PreUpdateEventArgs extends LifecycleEventArgs +{ + /** + * @var array + */ + private $entityChangeSet; + + /** + * Constructor. + * + * @param object $entity + * @param ObjectManager $objectManager + * @param array $changeSet + */ + public function __construct($entity, ObjectManager $objectManager, array &$changeSet) + { + parent::__construct($entity, $objectManager); + + $this->entityChangeSet = &$changeSet; + } + + /** + * Retrieve entity changeset. + * + * @return array + */ + public function getEntityChangeSet() + { + return $this->entityChangeSet; + } + + /** + * Check if field has a changeset. + * + * @param string $field + * + * @return boolean + */ + public function hasChangedField($field) + { + return isset($this->entityChangeSet[$field]); + } + + /** + * Get the old value of the changeset of the changed field. + * + * @param string $field + * @return mixed + */ + public function getOldValue($field) + { + $this->assertValidField($field); + + return $this->entityChangeSet[$field][0]; + } + + /** + * Get the new value of the changeset of the changed field. + * + * @param string $field + * @return mixed + */ + public function getNewValue($field) + { + $this->assertValidField($field); + + return $this->entityChangeSet[$field][1]; + } + + /** + * Set the new value of this field. + * + * @param string $field + * @param mixed $value + */ + public function setNewValue($field, $value) + { + $this->assertValidField($field); + + $this->entityChangeSet[$field][1] = $value; + } + + /** + * Assert the field exists in changeset. + * + * @param string $field + * + * @throws \InvalidArgumentException + */ + private function assertValidField($field) + { + if ( ! isset($this->entityChangeSet[$field])) { + throw new \InvalidArgumentException(sprintf( + 'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.', + $field, + get_class($this->getEntity()) + )); + } + } +} + diff --git a/src/core/libs/Doctrine/Common/Persistence/ManagerRegistry.php b/src/core/libs/Doctrine/Common/Persistence/ManagerRegistry.php new file mode 100644 index 0000000..bdb23bd --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/ManagerRegistry.php @@ -0,0 +1,112 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence; + +/** + * Contract covering object managers for a Doctrine persistence layer ManagerRegistry class to implement. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.2 + * @author Fabien Potencier <fabien@symfony.com> + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Lukas Kahwe Smith <smith@pooteeweet.org> + */ +interface ManagerRegistry extends ConnectionRegistry +{ + /** + * Gets the default object manager name. + * + * @return string The default object manager name + */ + function getDefaultManagerName(); + + /** + * Gets a named object manager. + * + * @param string $name The object manager name (null for the default one) + * + * @return \Doctrine\Common\Persistence\ObjectManager + */ + function getManager($name = null); + + /** + * Gets an array of all registered object managers + * + * @return \Doctrine\Common\Persistence\ObjectManager[] An array of ObjectManager instances + */ + function getManagers(); + + /** + * Resets a named object manager. + * + * This method is useful when an object manager has been closed + * because of a rollbacked transaction AND when you think that + * it makes sense to get a new one to replace the closed one. + * + * Be warned that you will get a brand new object manager as + * the existing one is not useable anymore. This means that any + * other object with a dependency on this object manager will + * hold an obsolete reference. You can inject the registry instead + * to avoid this problem. + * + * @param string $name The object manager name (null for the default one) + * + * @return \Doctrine\Common\Persistence\ObjectManager + */ + function resetManager($name = null); + + /** + * Resolves a registered namespace alias to the full namespace. + * + * This method looks for the alias in all registered object managers. + * + * @param string $alias The alias + * + * @return string The full namespace + */ + function getAliasNamespace($alias); + + /** + * Gets all connection names. + * + * @return array An array of connection names + */ + function getManagerNames(); + + /** + * Gets the ObjectRepository for an persistent object. + * + * @param string $persistentObject The name of the persistent object. + * @param string $persistentManagerName The object manager name (null for the default one) + * + * @return \Doctrine\Common\Persistence\ObjectRepository + */ + function getRepository($persistentObject, $persistentManagerName = null); + + /** + * Gets the object manager associated with a given class. + * + * @param string $class A persistent object class name + * + * @return \Doctrine\Common\Persistence\ObjectManager|null + */ + function getManagerForClass($class); +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php new file mode 100644 index 0000000..1ace1cc --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php @@ -0,0 +1,383 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping; + +use Doctrine\Common\Cache\Cache, + Doctrine\Common\Util\ClassUtils; + +/** + * The ClassMetadataFactory is used to create ClassMetadata objects that contain all the + * metadata mapping informations of a class which describes how a class should be mapped + * to a relational database. + * + * This class was abstracted from the ORM ClassMetadataFactory + * + * @since 2.2 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +abstract class AbstractClassMetadataFactory implements ClassMetadataFactory +{ + /** + * Salt used by specific Object Manager implementation. + * + * @var string + */ + protected $cacheSalt = "\$CLASSMETADATA"; + + /** + * @var \Doctrine\Common\Cache\Cache + */ + private $cacheDriver; + + /** + * @var array + */ + private $loadedMetadata = array(); + + /** + * @var bool + */ + protected $initialized = false; + + /** + * @var ReflectionService + */ + private $reflectionService; + + /** + * Sets the cache driver used by the factory to cache ClassMetadata instances. + * + * @param Doctrine\Common\Cache\Cache $cacheDriver + */ + public function setCacheDriver(Cache $cacheDriver = null) + { + $this->cacheDriver = $cacheDriver; + } + + /** + * Gets the cache driver used by the factory to cache ClassMetadata instances. + * + * @return Doctrine\Common\Cache\Cache + */ + public function getCacheDriver() + { + return $this->cacheDriver; + } + + /** + * Return an array of all the loaded metadata currently in memory. + * + * @return array + */ + public function getLoadedMetadata() + { + return $this->loadedMetadata; + } + + /** + * Forces the factory to load the metadata of all classes known to the underlying + * mapping driver. + * + * @return array The ClassMetadata instances of all mapped classes. + */ + public function getAllMetadata() + { + if ( ! $this->initialized) { + $this->initialize(); + } + + $driver = $this->getDriver(); + $metadata = array(); + foreach ($driver->getAllClassNames() as $className) { + $metadata[] = $this->getMetadataFor($className); + } + + return $metadata; + } + + /** + * Lazy initialization of this stuff, especially the metadata driver, + * since these are not needed at all when a metadata cache is active. + * + * @return void + */ + abstract protected function initialize(); + + /** + * Get the fully qualified class-name from the namespace alias. + * + * @param string $namespaceAlias + * @param string $simpleClassName + * @return string + */ + abstract protected function getFqcnFromAlias($namespaceAlias, $simpleClassName); + + /** + * Return the mapping driver implementation. + * + * @return \Doctrine\Common\Persistence\Mapping\Driver\MappingDriver + */ + abstract protected function getDriver(); + + /** + * Wakeup reflection after ClassMetadata gets unserialized from cache. + * + * @param ClassMetadata $class + * @param ReflectionService $reflService + * @return void + */ + abstract protected function wakeupReflection(ClassMetadata $class, ReflectionService $reflService); + + /** + * Initialize Reflection after ClassMetadata was constructed. + * + * @param ClassMetadata $class + * @param ReflectionService $reflService + * @return void + */ + abstract protected function initializeReflection(ClassMetadata $class, ReflectionService $reflService); + + /** + * Checks whether the class metadata is an entity. + * + * This method should false for mapped superclasses or + * embedded classes. + * + * @param ClassMetadata $class + * @return boolean + */ + abstract protected function isEntity(ClassMetadata $class); + + /** + * Gets the class metadata descriptor for a class. + * + * @param string $className The name of the class. + * @return \Doctrine\Common\Persistence\Mapping\ClassMetadata + */ + public function getMetadataFor($className) + { + if (isset($this->loadedMetadata[$className])) { + return $this->loadedMetadata[$className]; + } + + $realClassName = $className; + + // Check for namespace alias + if (strpos($className, ':') !== false) { + list($namespaceAlias, $simpleClassName) = explode(':', $className); + $realClassName = $this->getFqcnFromAlias($namespaceAlias, $simpleClassName); + } else { + $realClassName = ClassUtils::getRealClass($realClassName); + } + + if (isset($this->loadedMetadata[$realClassName])) { + // We do not have the alias name in the map, include it + $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; + + return $this->loadedMetadata[$realClassName]; + } + + if ($this->cacheDriver) { + if (($cached = $this->cacheDriver->fetch($realClassName . $this->cacheSalt)) !== false) { + $this->loadedMetadata[$realClassName] = $cached; + $this->wakeupReflection($cached, $this->getReflectionService()); + } else { + foreach ($this->loadMetadata($realClassName) as $loadedClassName) { + $this->cacheDriver->save( + $loadedClassName . $this->cacheSalt, $this->loadedMetadata[$loadedClassName], null + ); + } + } + } else { + $this->loadMetadata($realClassName); + } + + if ($className != $realClassName) { + // We do not have the alias name in the map, include it + $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; + } + + return $this->loadedMetadata[$className]; + } + + /** + * Checks whether the factory has the metadata for a class loaded already. + * + * @param string $className + * @return boolean TRUE if the metadata of the class in question is already loaded, FALSE otherwise. + */ + public function hasMetadataFor($className) + { + return isset($this->loadedMetadata[$className]); + } + + /** + * Sets the metadata descriptor for a specific class. + * + * NOTE: This is only useful in very special cases, like when generating proxy classes. + * + * @param string $className + * @param ClassMetadata $class + */ + public function setMetadataFor($className, $class) + { + $this->loadedMetadata[$className] = $class; + } + + /** + * Get array of parent classes for the given entity class + * + * @param string $name + * @return array $parentClasses + */ + protected function getParentClasses($name) + { + // Collect parent classes, ignoring transient (not-mapped) classes. + $parentClasses = array(); + foreach (array_reverse($this->getReflectionService()->getParentClasses($name)) as $parentClass) { + if ( ! $this->getDriver()->isTransient($parentClass)) { + $parentClasses[] = $parentClass; + } + } + return $parentClasses; + } + + /** + * Loads the metadata of the class in question and all it's ancestors whose metadata + * is still not loaded. + * + * @param string $name The name of the class for which the metadata should get loaded. + * + * @return array + */ + protected function loadMetadata($name) + { + if ( ! $this->initialized) { + $this->initialize(); + } + + $loaded = array(); + + $parentClasses = $this->getParentClasses($name); + $parentClasses[] = $name; + + // Move down the hierarchy of parent classes, starting from the topmost class + $parent = null; + $rootEntityFound = false; + $visited = array(); + $reflService = $this->getReflectionService(); + foreach ($parentClasses as $className) { + if (isset($this->loadedMetadata[$className])) { + $parent = $this->loadedMetadata[$className]; + if ($this->isEntity($parent)) { + $rootEntityFound = true; + array_unshift($visited, $className); + } + continue; + } + + $class = $this->newClassMetadataInstance($className); + $this->initializeReflection($class, $reflService); + + $this->doLoadMetadata($class, $parent, $rootEntityFound, $visited); + + $this->loadedMetadata[$className] = $class; + + $parent = $class; + + if ($this->isEntity($class)) { + $rootEntityFound = true; + array_unshift($visited, $className); + } + + $this->wakeupReflection($class, $reflService); + + $loaded[] = $className; + } + + return $loaded; + } + + /** + * Actually load the metadata from the underlying metadata + * + * @param ClassMetadata $class + * @param ClassMetadata|null $parent + * @param bool $rootEntityFound + * @param array $nonSuperclassParents classnames all parent classes that are not marked as mapped superclasses + * @return void + */ + abstract protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents); + + /** + * Creates a new ClassMetadata instance for the given class name. + * + * @param string $className + * @return ClassMetadata + */ + abstract protected function newClassMetadataInstance($className); + + /** + * Check if this class is mapped by this Object Manager + ClassMetadata configuration + * + * @param $class + * @return bool + */ + public function isTransient($class) + { + if ( ! $this->initialized) { + $this->initialize(); + } + + // Check for namespace alias + if (strpos($class, ':') !== false) { + list($namespaceAlias, $simpleClassName) = explode(':', $class); + $class = $this->getFqcnFromAlias($namespaceAlias, $simpleClassName); + } + + return $this->getDriver()->isTransient($class); + } + + /** + * Set reflectionService. + * + * @param ReflectionService $reflectionService + */ + public function setReflectionService(ReflectionService $reflectionService) + { + $this->reflectionService = $reflectionService; + } + + /** + * Get the reflection service associated with this metadata factory. + * + * @return ReflectionService + */ + public function getReflectionService() + { + if ($this->reflectionService === null) { + $this->reflectionService = new RuntimeReflectionService(); + } + return $this->reflectionService; + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/ClassMetadata.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/ClassMetadata.php new file mode 100644 index 0000000..4836bf8 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/ClassMetadata.php @@ -0,0 +1,165 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping; + +/** + * Contract for a Doctrine persistence layer ClassMetadata class to implement. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.1 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Jonathan Wage <jonwage@gmail.com> + */ +interface ClassMetadata +{ + /** + * Get fully-qualified class name of this persistent class. + * + * @return string + */ + function getName(); + + /** + * Gets the mapped identifier field name. + * + * The returned structure is an array of the identifier field names. + * + * @return array + */ + function getIdentifier(); + + /** + * Gets the ReflectionClass instance for this mapped class. + * + * @return \ReflectionClass + */ + function getReflectionClass(); + + /** + * Checks if the given field name is a mapped identifier for this class. + * + * @param string $fieldName + * @return boolean + */ + function isIdentifier($fieldName); + + /** + * Checks if the given field is a mapped property for this class. + * + * @param string $fieldName + * @return boolean + */ + function hasField($fieldName); + + /** + * Checks if the given field is a mapped association for this class. + * + * @param string $fieldName + * @return boolean + */ + function hasAssociation($fieldName); + + /** + * Checks if the given field is a mapped single valued association for this class. + * + * @param string $fieldName + * @return boolean + */ + function isSingleValuedAssociation($fieldName); + + /** + * Checks if the given field is a mapped collection valued association for this class. + * + * @param string $fieldName + * @return boolean + */ + function isCollectionValuedAssociation($fieldName); + + /** + * A numerically indexed list of field names of this persistent class. + * + * This array includes identifier fields if present on this class. + * + * @return array + */ + function getFieldNames(); + + /** + * Returns an array of identifier field names numerically indexed. + * + * @return array + */ + function getIdentifierFieldNames(); + + /** + * A numerically indexed list of association names of this persistent class. + * + * This array includes identifier associations if present on this class. + * + * @return array + */ + function getAssociationNames(); + + /** + * Returns a type name of this field. + * + * This type names can be implementation specific but should at least include the php types: + * integer, string, boolean, float/double, datetime. + * + * @param string $fieldName + * @return string + */ + function getTypeOfField($fieldName); + + /** + * Returns the target class name of the given association. + * + * @param string $assocName + * @return string + */ + function getAssociationTargetClass($assocName); + + /** + * Checks if the association is the inverse side of a bidirectional association + * + * @param string $assocName + * @return boolean + */ + function isAssociationInverseSide($assocName); + + /** + * Returns the target field of the owning side of the association + * + * @param string $assocName + * @return string + */ + function getAssociationMappedByTargetField($assocName); + + /** + * Return the identifier of this object as an array with field name as key. + * + * Has to return an empty array if no identifier isset. + * + * @param object $object + * @return array + */ + function getIdentifierValues($object); +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/ClassMetadataFactory.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/ClassMetadataFactory.php new file mode 100644 index 0000000..3fa39bc --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/ClassMetadataFactory.php @@ -0,0 +1,74 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping; + +/** + * Contract for a Doctrine persistence layer ClassMetadata class to implement. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.1 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Jonathan Wage <jonwage@gmail.com> + */ +interface ClassMetadataFactory +{ + /** + * Forces the factory to load the metadata of all classes known to the underlying + * mapping driver. + * + * @return array The ClassMetadata instances of all mapped classes. + */ + function getAllMetadata(); + + /** + * Gets the class metadata descriptor for a class. + * + * @param string $className The name of the class. + * @return ClassMetadata + */ + function getMetadataFor($className); + + /** + * Checks whether the factory has the metadata for a class loaded already. + * + * @param string $className + * @return boolean TRUE if the metadata of the class in question is already loaded, FALSE otherwise. + */ + function hasMetadataFor($className); + + /** + * Sets the metadata descriptor for a specific class. + * + * @param string $className + * @param ClassMetadata $class + */ + function setMetadataFor($className, $class); + + /** + * Whether the class with the specified name should have its metadata loaded. + * This is only the case if it is either mapped directly or as a + * MappedSuperclass. + * + * @param string $className + * @return boolean + */ + function isTransient($className); +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php new file mode 100644 index 0000000..1131add --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php @@ -0,0 +1,214 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping\Driver; + +use Doctrine\Common\Cache\ArrayCache, + Doctrine\Common\Annotations\AnnotationReader, + Doctrine\Common\Annotations\AnnotationRegistry, + Doctrine\Common\Persistence\Mapping\MappingException; + +/** + * The AnnotationDriver reads the mapping metadata from docblock annotations. + * + * @since 2.2 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan H. Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +abstract class AnnotationDriver implements MappingDriver +{ + /** + * The AnnotationReader. + * + * @var AnnotationReader + */ + protected $reader; + + /** + * The paths where to look for mapping files. + * + * @var array + */ + protected $paths = array(); + + /** + * The file extension of mapping documents. + * + * @var string + */ + protected $fileExtension = '.php'; + + /** + * Cache for AnnotationDriver#getAllClassNames() + * + * @var array + */ + protected $classNames; + + /** + * Name of the entity annotations as keys + * + * @var array + */ + protected $entityAnnotationClasses = array(); + + /** + * Initializes a new AnnotationDriver that uses the given AnnotationReader for reading + * docblock annotations. + * + * @param AnnotationReader $reader The AnnotationReader to use, duck-typed. + * @param string|array $paths One or multiple paths where mapping classes can be found. + */ + public function __construct($reader, $paths = null) + { + $this->reader = $reader; + if ($paths) { + $this->addPaths((array) $paths); + } + } + + /** + * Append lookup paths to metadata driver. + * + * @param array $paths + */ + public function addPaths(array $paths) + { + $this->paths = array_unique(array_merge($this->paths, $paths)); + } + + /** + * Retrieve the defined metadata lookup paths. + * + * @return array + */ + public function getPaths() + { + return $this->paths; + } + + /** + * Retrieve the current annotation reader + * + * @return AnnotationReader + */ + public function getReader() + { + return $this->reader; + } + + /** + * Get the file extension used to look for mapping files under + * + * @return string + */ + public function getFileExtension() + { + return $this->fileExtension; + } + + /** + * Set the file extension used to look for mapping files under + * + * @param string $fileExtension The file extension to set + * @return void + */ + public function setFileExtension($fileExtension) + { + $this->fileExtension = $fileExtension; + } + + /** + * Whether the class with the specified name is transient. Only non-transient + * classes, that is entities and mapped superclasses, should have their metadata loaded. + * + * A class is non-transient if it is annotated with an annotation + * from the {@see AnnotationDriver::entityAnnotationClasses}. + * + * @param string $className + * @return boolean + */ + public function isTransient($className) + { + $classAnnotations = $this->reader->getClassAnnotations(new \ReflectionClass($className)); + + foreach ($classAnnotations as $annot) { + if (isset($this->entityAnnotationClasses[get_class($annot)])) { + return false; + } + } + return true; + } + + /** + * {@inheritDoc} + */ + public function getAllClassNames() + { + if ($this->classNames !== null) { + return $this->classNames; + } + + if (!$this->paths) { + throw MappingException::pathRequired(); + } + + $classes = array(); + $includedFiles = array(); + + foreach ($this->paths as $path) { + if ( ! is_dir($path)) { + throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); + } + + $iterator = new \RegexIterator( + new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS), + \RecursiveIteratorIterator::LEAVES_ONLY + ), + '/^.+' . str_replace('.', '\.', $this->fileExtension) . '$/i', + \RecursiveRegexIterator::GET_MATCH + ); + + foreach ($iterator as $file) { + $sourceFile = realpath($file[0]); + + require_once $sourceFile; + + $includedFiles[] = $sourceFile; + } + } + + $declared = get_declared_classes(); + + foreach ($declared as $className) { + $rc = new \ReflectionClass($className); + $sourceFile = $rc->getFileName(); + if (in_array($sourceFile, $includedFiles) && ! $this->isTransient($className)) { + $classes[] = $className; + } + } + + $this->classNames = $classes; + + return $classes; + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/DefaultFileLocator.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/DefaultFileLocator.php new file mode 100644 index 0000000..0d61174 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/DefaultFileLocator.php @@ -0,0 +1,170 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\Common\Persistence\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\MappingException; + +/** + * Locate the file that contains the metadata information for a given class name. + * + * This behavior is inpependent of the actual content of the file. It just detects + * the file which is responsible for the given class name. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class DefaultFileLocator implements FileLocator +{ + /** + * The paths where to look for mapping files. + * + * @var array + */ + protected $paths = array(); + + /** + * The file extension of mapping documents. + * + * @var string + */ + protected $fileExtension; + + /** + * Initializes a new FileDriver that looks in the given path(s) for mapping + * documents and operates in the specified operating mode. + * + * @param string|array $paths One or multiple paths where mapping documents can be found. + * @param string|null $fileExtension + */ + public function __construct($paths, $fileExtension = null) + { + $this->addPaths((array) $paths); + $this->fileExtension = $fileExtension; + } + + /** + * Append lookup paths to metadata driver. + * + * @param array $paths + */ + public function addPaths(array $paths) + { + $this->paths = array_unique(array_merge($this->paths, $paths)); + } + + /** + * Retrieve the defined metadata lookup paths. + * + * @return array + */ + public function getPaths() + { + return $this->paths; + } + + /** + * Get the file extension used to look for mapping files under + * + * @return string + */ + public function getFileExtension() + { + return $this->fileExtension; + } + + /** + * Set the file extension used to look for mapping files under + * + * @param string $fileExtension The file extension to set + * @return void + */ + public function setFileExtension($fileExtension) + { + $this->fileExtension = $fileExtension; + } + + /** + * {@inheritDoc} + */ + public function findMappingFile($className) + { + $fileName = str_replace('\\', '.', $className) . $this->fileExtension; + + // Check whether file exists + foreach ($this->paths as $path) { + if (file_exists($path . DIRECTORY_SEPARATOR . $fileName)) { + return $path . DIRECTORY_SEPARATOR . $fileName; + } + } + + throw MappingException::mappingFileNotFound($className, $fileName); + } + + /** + * {@inheritDoc} + */ + public function getAllClassNames($globalBasename) + { + $classes = array(); + + if ($this->paths) { + foreach ($this->paths as $path) { + if ( ! is_dir($path)) { + throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); + } + + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($path), + \RecursiveIteratorIterator::LEAVES_ONLY + ); + + foreach ($iterator as $file) { + $fileName = $file->getBasename($this->fileExtension); + + if ($fileName == $file->getBasename() || $fileName == $globalBasename) { + continue; + } + + // NOTE: All files found here means classes are not transient! + $classes[] = str_replace('.', '\\', $fileName); + } + } + } + + return $classes; + } + + /** + * {@inheritDoc} + */ + public function fileExists($className) + { + $fileName = str_replace('\\', '.', $className) . $this->fileExtension; + + // Check whether file exists + foreach ((array) $this->paths as $path) { + if (file_exists($path . DIRECTORY_SEPARATOR . $fileName)) { + return true; + } + } + + return false; + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/FileDriver.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/FileDriver.php new file mode 100644 index 0000000..b0a7685 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/FileDriver.php @@ -0,0 +1,214 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\MappingException; + +/** + * Base driver for file-based metadata drivers. + * + * A file driver operates in a mode where it loads the mapping files of individual + * classes on demand. This requires the user to adhere to the convention of 1 mapping + * file per class and the file names of the mapping files must correspond to the full + * class name, including namespace, with the namespace delimiters '\', replaced by dots '.'. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan H. Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +abstract class FileDriver implements MappingDriver +{ + /** + * @var FileLocator + */ + protected $locator; + + /** + * @var array + */ + protected $classCache; + + /** + * @var string + */ + protected $globalBasename; + + /** + * Initializes a new FileDriver that looks in the given path(s) for mapping + * documents and operates in the specified operating mode. + * + * @param string|array|FileLocator $locator A FileLocator or one/multiple paths where mapping documents can be found. + * @param string $fileExtension + */ + public function __construct($locator, $fileExtension = null) + { + if ($locator instanceof FileLocator) { + $this->locator = $locator; + } else { + $this->locator = new DefaultFileLocator((array)$locator, $fileExtension); + } + } + + /** + * Set global basename + * + * @param string $file + */ + public function setGlobalBasename($file) + { + $this->globalBasename = $file; + } + + /** + * Retrieve global basename + * + * @return string + */ + public function getGlobalBasename() + { + return $this->globalBasename; + } + + /** + * Get the element of schema meta data for the class from the mapping file. + * This will lazily load the mapping file if it is not loaded yet + * + * @param string $className + * + * @throws MappingException + * @return array The element of schema meta data + */ + public function getElement($className) + { + if ($this->classCache === null) { + $this->initialize(); + } + + if (isset($this->classCache[$className])) { + return $this->classCache[$className]; + } + + $result = $this->loadMappingFile($this->locator->findMappingFile($className)); + if (!isset($result[$className])) { + throw MappingException::invalidMappingFile($className, str_replace('\\', '.', $className) . $this->locator->getFileExtension()); + } + + return $result[$className]; + } + + /** + * Whether the class with the specified name should have its metadata loaded. + * This is only the case if it is either mapped as an Entity or a + * MappedSuperclass. + * + * @param string $className + * @return boolean + */ + public function isTransient($className) + { + if ($this->classCache === null) { + $this->initialize(); + } + + if (isset($this->classCache[$className])) { + return false; + } + + return !$this->locator->fileExists($className); + } + + /** + * Gets the names of all mapped classes known to this driver. + * + * @return array The names of all mapped classes known to this driver. + */ + public function getAllClassNames() + { + if ($this->classCache === null) { + $this->initialize(); + } + + $classNames = (array)$this->locator->getAllClassNames($this->globalBasename); + if ($this->classCache) { + $classNames = array_merge(array_keys($this->classCache), $classNames); + } + return $classNames; + } + + /** + * Loads a mapping file with the given name and returns a map + * from class/entity names to their corresponding file driver elements. + * + * @param string $file The mapping file to load. + * @return array + */ + abstract protected function loadMappingFile($file); + + /** + * Initialize the class cache from all the global files. + * + * Using this feature adds a substantial performance hit to file drivers as + * more metadata has to be loaded into memory than might actually be + * necessary. This may not be relevant to scenarios where caching of + * metadata is in place, however hits very hard in scenarios where no + * caching is used. + * + * @return void + */ + protected function initialize() + { + $this->classCache = array(); + if (null !== $this->globalBasename) { + foreach ($this->locator->getPaths() as $path) { + $file = $path.'/'.$this->globalBasename.$this->locator->getFileExtension(); + if (is_file($file)) { + $this->classCache = array_merge( + $this->classCache, + $this->loadMappingFile($file) + ); + } + } + } + } + + /** + * Retrieve the locator used to discover mapping files by className + * + * @return FileLocator + */ + public function getLocator() + { + return $this->locator; + } + + /** + * Set the locator used to discover mapping files by className + * + * @param FileLocator $locator + */ + public function setLocator(FileLocator $locator) + { + $this->locator = $locator; + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/FileLocator.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/FileLocator.php new file mode 100644 index 0000000..ec2b606 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/FileLocator.php @@ -0,0 +1,71 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\Common\Persistence\Mapping\Driver; + +/** + * Locate the file that contains the metadata information for a given class name. + * + * This behavior is independent of the actual content of the file. It just detects + * the file which is responsible for the given class name. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +interface FileLocator +{ + /** + * Locate mapping file for the given class name. + * + * @param string $className + * @return string + */ + function findMappingFile($className); + + /** + * Get all class names that are found with this file locator. + * + * @param string $globalBasename Passed to allow excluding the basename + * @return array + */ + function getAllClassNames($globalBasename); + + /** + * Check if a file can be found for this class name. + * + * @param string $className + * + * @return bool + */ + function fileExists($className); + + /** + * Get all the paths that this file locator looks for mapping files. + * + * @return array + */ + function getPaths(); + + /** + * Get the file extension that mapping files are suffixed with. + * + * @return string + */ + function getFileExtension(); +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/MappingDriver.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/MappingDriver.php new file mode 100644 index 0000000..955d831 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/MappingDriver.php @@ -0,0 +1,56 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\ClassMetadata; + +/** + * Contract for metadata drivers. + * + * @since 2.2 + * @author Jonathan H. Wage <jonwage@gmail.com> + */ +interface MappingDriver +{ + /** + * Loads the metadata for the specified class into the provided container. + * + * @param string $className + * @param ClassMetadata $metadata + */ + function loadMetadataForClass($className, ClassMetadata $metadata); + + /** + * Gets the names of all mapped classes known to this driver. + * + * @return array The names of all mapped classes known to this driver. + */ + function getAllClassNames(); + + /** + * Whether the class with the specified name should have its metadata loaded. + * This is only the case if it is either mapped as an Entity or a + * MappedSuperclass. + * + * @param string $className + * @return boolean + */ + function isTransient($className); +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php new file mode 100644 index 0000000..3b1049d --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/MappingDriverChain.php @@ -0,0 +1,168 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver, + Doctrine\Common\Persistence\Mapping\ClassMetadata, + Doctrine\Common\Persistence\Mapping\MappingException; + +/** + * The DriverChain allows you to add multiple other mapping drivers for + * certain namespaces + * + * @since 2.2 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan H. Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class MappingDriverChain implements MappingDriver +{ + /** + * The default driver + * + * @var MappingDriver + */ + private $defaultDriver; + + /** + * @var array + */ + private $drivers = array(); + + /** + * Get the default driver. + * + * @return MappingDriver|null + */ + public function getDefaultDriver() + { + return $this->defaultDriver; + } + + /** + * Set the default driver. + * + * @param MappingDriver $driver + */ + public function setDefaultDriver(MappingDriver $driver) + { + $this->defaultDriver = $driver; + } + + /** + * Add a nested driver. + * + * @param MappingDriver $nestedDriver + * @param string $namespace + */ + public function addDriver(MappingDriver $nestedDriver, $namespace) + { + $this->drivers[$namespace] = $nestedDriver; + } + + /** + * Get the array of nested drivers. + * + * @return array $drivers + */ + public function getDrivers() + { + return $this->drivers; + } + + /** + * Loads the metadata for the specified class into the provided container. + * + * @param string $className + * @param ClassMetadata $metadata + * + * @throws MappingException + */ + public function loadMetadataForClass($className, ClassMetadata $metadata) + { + /* @var $driver MappingDriver */ + foreach ($this->drivers as $namespace => $driver) { + if (strpos($className, $namespace) === 0) { + $driver->loadMetadataForClass($className, $metadata); + return; + } + } + + if (null !== $this->defaultDriver) { + $this->defaultDriver->loadMetadataForClass($className, $metadata); + return; + } + + throw MappingException::classNotFoundInNamespaces($className, array_keys($this->drivers)); + } + + /** + * Gets the names of all mapped classes known to this driver. + * + * @return array The names of all mapped classes known to this driver. + */ + public function getAllClassNames() + { + $classNames = array(); + $driverClasses = array(); + + /* @var $driver MappingDriver */ + foreach ($this->drivers AS $namespace => $driver) { + $oid = spl_object_hash($driver); + + if (!isset($driverClasses[$oid])) { + $driverClasses[$oid] = $driver->getAllClassNames(); + } + + foreach ($driverClasses[$oid] AS $className) { + if (strpos($className, $namespace) === 0) { + $classNames[$className] = true; + } + } + } + + return array_keys($classNames); + } + + /** + * Whether the class with the specified name should have its metadata loaded. + * + * This is only the case for non-transient classes either mapped as an Entity or MappedSuperclass. + * + * @param string $className + * @return boolean + */ + public function isTransient($className) + { + /* @var $driver MappingDriver */ + foreach ($this->drivers AS $namespace => $driver) { + if (strpos($className, $namespace) === 0) { + return $driver->isTransient($className); + } + } + + if ($this->defaultDriver !== null) { + return $this->defaultDriver->isTransient($className); + } + + return true; + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/PHPDriver.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/PHPDriver.php new file mode 100644 index 0000000..e0c8611 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/PHPDriver.php @@ -0,0 +1,72 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\ClassMetadata; + +/** + * The PHPDriver includes php files which just populate ClassMetadataInfo + * instances with plain php code + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan H. Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class PHPDriver extends FileDriver +{ + /** + * {@inheritdoc} + */ + protected $metadata; + + /** + * {@inheritDoc} + */ + public function __construct($locator, $fileExtension = null) + { + $fileExtension = ".php"; + parent::__construct($locator, $fileExtension); + } + + /** + * {@inheritdoc} + */ + public function loadMetadataForClass($className, ClassMetadata $metadata) + { + $this->metadata = $metadata; + $this->loadMappingFile($this->locator->findMappingFile($className)); + } + + /** + * {@inheritdoc} + */ + protected function loadMappingFile($file) + { + $metadata = $this->metadata; + include $file; + + return array($metadata->getName() => $metadata); + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/StaticPHPDriver.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/StaticPHPDriver.php new file mode 100644 index 0000000..e3cea73 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/StaticPHPDriver.php @@ -0,0 +1,141 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\Common\Persistence\Mapping\MappingException; + +/** + * The StaticPHPDriver calls a static loadMetadata() method on your entity + * classes where you can manually populate the ClassMetadata instance. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.2 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan H. Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class StaticPHPDriver implements MappingDriver +{ + /** + * Paths of entity directories. + * + * @var array + */ + private $paths = array(); + + /** + * Map of all class names. + * + * @var array + */ + private $classNames; + + /** + * Constructor + * + * @param array|string $paths + */ + public function __construct($paths) + { + $this->addPaths((array) $paths); + } + + /** + * Add paths + * + * @param array $paths + */ + public function addPaths(array $paths) + { + $this->paths = array_unique(array_merge($this->paths, $paths)); + } + + /** + * {@inheritdoc} + */ + public function loadMetadataForClass($className, ClassMetadata $metadata) + { + $className::loadMetadata($metadata); + } + + /** + * {@inheritDoc} + * @todo Same code exists in AnnotationDriver, should we re-use it somehow or not worry about it? + */ + public function getAllClassNames() + { + if ($this->classNames !== null) { + return $this->classNames; + } + + if (!$this->paths) { + throw MappingException::pathRequired(); + } + + $classes = array(); + $includedFiles = array(); + + foreach ($this->paths as $path) { + if (!is_dir($path)) { + throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); + } + + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($path), + \RecursiveIteratorIterator::LEAVES_ONLY + ); + + foreach ($iterator as $file) { + if ($file->getBasename('.php') == $file->getBasename()) { + continue; + } + + $sourceFile = realpath($file->getPathName()); + require_once $sourceFile; + $includedFiles[] = $sourceFile; + } + } + + $declared = get_declared_classes(); + + foreach ($declared as $className) { + $rc = new \ReflectionClass($className); + $sourceFile = $rc->getFileName(); + if (in_array($sourceFile, $includedFiles) && !$this->isTransient($className)) { + $classes[] = $className; + } + } + + $this->classNames = $classes; + + return $classes; + } + + /** + * {@inheritdoc} + */ + public function isTransient($className) + { + return ! method_exists($className, 'loadMetadata'); + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/SymfonyFileLocator.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/SymfonyFileLocator.php new file mode 100644 index 0000000..9095187 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/Driver/SymfonyFileLocator.php @@ -0,0 +1,214 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\Common\Persistence\Mapping\Driver; + +use Doctrine\Common\Persistence\Mapping\MappingException; + +/** + * The Symfony File Locator makes a simplifying assumptions compared + * to the DefaultFileLocator. By assuming paths only contain entities of a certain + * namespace the mapping files consists of the short classname only. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @license MIT + */ +class SymfonyFileLocator implements FileLocator +{ + /** + * The paths where to look for mapping files. + * + * @var array + */ + protected $paths = array(); + + /** + * A map of mapping directory path to namespace prefix used to expand class shortnames. + * + * @var array + */ + protected $prefixes = array(); + + /** + * File extension that is searched for. + * + * @var string + */ + protected $fileExtension; + + /** + * Constructor + * + * @param array $prefixes + * @param string|null $fileExtension + */ + public function __construct(array $prefixes, $fileExtension = null) + { + $this->addNamespacePrefixes($prefixes); + $this->fileExtension = $fileExtension; + } + + /** + * Add Namespace Prefixes + * + * @param array $prefixes + */ + public function addNamespacePrefixes(array $prefixes) + { + $this->prefixes = array_merge($this->prefixes, $prefixes); + $this->paths = array_merge($this->paths, array_keys($prefixes)); + } + + /** + * Get Namespace Prefixes + * + * @return array + */ + public function getNamespacePrefixes() + { + return $this->prefixes; + } + + /** + * {@inheritDoc} + */ + public function getPaths() + { + return $this->paths; + } + + /** + * {@inheritDoc} + */ + public function getFileExtension() + { + return $this->fileExtension; + } + + /** + * Set the file extension used to look for mapping files under + * + * @param string $fileExtension The file extension to set + * @return void + */ + public function setFileExtension($fileExtension) + { + $this->fileExtension = $fileExtension; + } + + /** + * {@inheritDoc} + */ + public function fileExists($className) + { + $defaultFileName = str_replace('\\', '.', $className).$this->fileExtension; + foreach ($this->paths as $path) { + if (!isset($this->prefixes[$path])) { + // global namespace class + if (is_file($path.DIRECTORY_SEPARATOR.$defaultFileName)) { + return true; + } + + continue; + } + + $prefix = $this->prefixes[$path]; + + if (0 !== strpos($className, $prefix.'\\')) { + continue; + } + + $filename = $path.'/'.strtr(substr($className, strlen($prefix)+1), '\\', '.').$this->fileExtension; + return is_file($filename); + } + + return false; + } + + /** + * {@inheritDoc} + */ + public function getAllClassNames($globalBasename = null) + { + $classes = array(); + + if ($this->paths) { + foreach ((array) $this->paths as $path) { + if (!is_dir($path)) { + throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path); + } + + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($path), + \RecursiveIteratorIterator::LEAVES_ONLY + ); + + foreach ($iterator as $file) { + $fileName = $file->getBasename($this->fileExtension); + + if ($fileName == $file->getBasename() || $fileName == $globalBasename) { + continue; + } + + // NOTE: All files found here means classes are not transient! + if (isset($this->prefixes[$path])) { + $classes[] = $this->prefixes[$path].'\\'.str_replace('.', '\\', $fileName); + } else { + $classes[] = str_replace('.', '\\', $fileName); + } + } + } + } + + return $classes; + } + + /** + * {@inheritDoc} + */ + public function findMappingFile($className) + { + $defaultFileName = str_replace('\\', '.', $className).$this->fileExtension; + foreach ($this->paths as $path) { + if (!isset($this->prefixes[$path])) { + if (is_file($path.DIRECTORY_SEPARATOR.$defaultFileName)) { + return $path.DIRECTORY_SEPARATOR.$defaultFileName; + } + + continue; + } + + $prefix = $this->prefixes[$path]; + + if (0 !== strpos($className, $prefix.'\\')) { + continue; + } + + $filename = $path.'/'.strtr(substr($className, strlen($prefix)+1), '\\', '.').$this->fileExtension; + if (is_file($filename)) { + return $filename; + } + + throw MappingException::mappingFileNotFound($className, $filename); + } + + throw MappingException::mappingFileNotFound($className, substr($className, strrpos($className, '\\') + 1).$this->fileExtension); + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/MappingException.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/MappingException.php new file mode 100644 index 0000000..c1e7ad5 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/MappingException.php @@ -0,0 +1,86 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.phpdoctrine.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping; + +/** + * A MappingException indicates that something is wrong with the mapping setup. + * + * @since 2.2 + */ +class MappingException extends \Exception +{ + /** + * + * @param string $className + * @param array $namespaces + * + * @return MappingException + */ + public static function classNotFoundInNamespaces($className, $namespaces) + { + return new self("The class '" . $className . "' was not found in the ". + "chain configured namespaces " . implode(", ", $namespaces)); + } + + /** + * @return MappingException + */ + public static function pathRequired() + { + return new self("Specifying the paths to your entities is required ". + "in the AnnotationDriver to retrieve all class names."); + } + + /** + * @param string|null $path + * @return MappingException + */ + public static function fileMappingDriversRequireConfiguredDirectoryPath($path = null) + { + if ( ! empty($path)) { + $path = '[' . $path . ']'; + } + + return new self( + 'File mapping drivers must have a valid directory path, ' . + 'however the given path ' . $path . ' seems to be incorrect!' + ); + } + + /** + * @param string $entityName + * @param string $fileName + * @return MappingException + */ + public static function mappingFileNotFound($entityName, $fileName) + { + return new self("No mapping file found named '$fileName' for class '$entityName'."); + } + + /** + * @param string $entityName + * @param string $fileName + * @return MappingException + */ + public static function invalidMappingFile($entityName, $fileName) + { + return new self("Invalid mapping file '$fileName' for class '$entityName'."); + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/ReflectionService.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/ReflectionService.php new file mode 100644 index 0000000..3db85d9 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/ReflectionService.php @@ -0,0 +1,80 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping; + +/** + * Very simple reflection service abstraction. + * + * This is required inside metadata layers that may require either + * static or runtime reflection. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +interface ReflectionService +{ + /** + * Return an array of the parent classes (not interfaces) for the given class. + * + * @param string $class + * @return array + */ + function getParentClasses($class); + + /** + * Return the shortname of a class. + * + * @param string $class + * @return string + */ + function getClassShortName($class); + + /** + * @param string $class + * @return string + */ + function getClassNamespace($class); + + /** + * Return a reflection class instance or null + * + * @param string $class + * @return \ReflectionClass|null + */ + function getClass($class); + + /** + * Return an accessible property (setAccessible(true)) or null. + * + * @param string $class + * @param string $property + * @return \ReflectionProperty|null + */ + function getAccessibleProperty($class, $property); + + /** + * Check if the class have a public method with the given name. + * + * @param mixed $class + * @param mixed $method + * @return bool + */ + function hasPublicMethod($class, $method); +} + diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php new file mode 100644 index 0000000..77b9e76 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php @@ -0,0 +1,102 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping; + +use ReflectionClass; +use ReflectionProperty; + +/** + * PHP Runtime Reflection Service + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class RuntimeReflectionService implements ReflectionService +{ + /** + * Return an array of the parent classes (not interfaces) for the given class. + * + * @param string $class + * @return array + */ + public function getParentClasses($class) + { + return class_parents($class); + } + + /** + * Return the shortname of a class. + * + * @param string $class + * @return string + */ + public function getClassShortName($class) + { + $r = new ReflectionClass($class); + return $r->getShortName(); + } + + /** + * @param string $class + * @return string + */ + public function getClassNamespace($class) + { + $r = new ReflectionClass($class); + return $r->getNamespaceName(); + } + + /** + * Return a reflection class instance or null + * + * @param string $class + * @return ReflectionClass|null + */ + public function getClass($class) + { + return new ReflectionClass($class); + } + + /** + * Return an accessible property (setAccessible(true)) or null. + * + * @param string $class + * @param string $property + * @return ReflectionProperty|null + */ + public function getAccessibleProperty($class, $property) + { + $property = new ReflectionProperty($class, $property); + $property->setAccessible(true); + return $property; + } + + /** + * Check if the class have a public method with the given name. + * + * @param mixed $class + * @param mixed $method + * @return bool + */ + public function hasPublicMethod($class, $method) + { + return method_exists($class, $method) && is_callable(array($class, $method)); + } +} + diff --git a/src/core/libs/Doctrine/Common/Persistence/Mapping/StaticReflectionService.php b/src/core/libs/Doctrine/Common/Persistence/Mapping/StaticReflectionService.php new file mode 100644 index 0000000..4f6d1cf --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Mapping/StaticReflectionService.php @@ -0,0 +1,107 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence\Mapping; + +use ReflectionClass; +use ReflectionProperty; + +/** + * PHP Runtime Reflection Service + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class StaticReflectionService implements ReflectionService +{ + /** + * Return an array of the parent classes (not interfaces) for the given class. + * + * @param string $class + * @return array + */ + public function getParentClasses($class) + { + return array(); + } + + /** + * Return the shortname of a class. + * + * @param string $className + * @return string + */ + public function getClassShortName($className) + { + if (strpos($className, '\\') !== false) { + $className = substr($className, strrpos($className, "\\")+1); + } + return $className; + } + + /** + * Return the namespace of a class. + * + * @param string $className + * @return string + */ + public function getClassNamespace($className) + { + $namespace = ''; + if (strpos($className, '\\') !== false) { + $namespace = strrev(substr( strrev($className), strpos(strrev($className), '\\')+1 )); + } + return $namespace; + } + + /** + * Return a reflection class instance or null + * + * @param string $class + * @return ReflectionClass|null + */ + public function getClass($class) + { + return null; + } + + /** + * Return an accessible property (setAccessible(true)) or null. + * + * @param string $class + * @param string $property + * @return ReflectionProperty|null + */ + public function getAccessibleProperty($class, $property) + { + return null; + } + + /** + * Check if the class have a public method with the given name. + * + * @param mixed $class + * @param mixed $method + * @return bool + */ + public function hasPublicMethod($class, $method) + { + return method_exists($class, $method) && is_callable(array($class, $method)); + } +} + diff --git a/src/core/libs/Doctrine/Common/Persistence/ObjectManager.php b/src/core/libs/Doctrine/Common/Persistence/ObjectManager.php new file mode 100644 index 0000000..2bb8722 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/ObjectManager.php @@ -0,0 +1,152 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence; + +/** + * Contract for a Doctrine persistence layer ObjectManager class to implement. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.1 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Jonathan Wage <jonwage@gmail.com> + */ +interface ObjectManager +{ + /** + * Finds a object by its identifier. + * + * This is just a convenient shortcut for getRepository($className)->find($id). + * + * @param string + * @param mixed + * @return object + */ + function find($className, $id); + + /** + * Tells the ObjectManager to make an instance managed and persistent. + * + * The object will be entered into the database as a result of the flush operation. + * + * NOTE: The persist operation always considers objects that are not yet known to + * this ObjectManager as NEW. Do not pass detached objects to the persist operation. + * + * @param object $object The instance to make managed and persistent. + */ + function persist($object); + + /** + * Removes an object instance. + * + * A removed object will be removed from the database as a result of the flush operation. + * + * @param object $object The object instance to remove. + */ + function remove($object); + + /** + * Merges the state of a detached object into the persistence context + * of this ObjectManager and returns the managed copy of the object. + * The object passed to merge will not become associated/managed with this ObjectManager. + * + * @param object $object + * @return object + */ + function merge($object); + + /** + * Clears the ObjectManager. All objects that are currently managed + * by this ObjectManager become detached. + * + * @param string $objectName if given, only objects of this type will get detached + */ + function clear($objectName = null); + + /** + * Detaches an object from the ObjectManager, causing a managed object to + * become detached. Unflushed changes made to the object if any + * (including removal of the object), will not be synchronized to the database. + * Objects which previously referenced the detached object will continue to + * reference it. + * + * @param object $object The object to detach. + */ + function detach($object); + + /** + * Refreshes the persistent state of an object from the database, + * overriding any local changes that have not yet been persisted. + * + * @param object $object The object to refresh. + */ + function refresh($object); + + /** + * Flushes all changes to objects that have been queued up to now to the database. + * This effectively synchronizes the in-memory state of managed objects with the + * database. + */ + function flush(); + + /** + * Gets the repository for a class. + * + * @param string $className + * @return \Doctrine\Common\Persistence\ObjectRepository + */ + function getRepository($className); + + /** + * Returns the ClassMetadata descriptor for a class. + * + * The class name must be the fully-qualified class name without a leading backslash + * (as it is returned by get_class($obj)). + * + * @param string $className + * @return \Doctrine\Common\Persistence\Mapping\ClassMetadata + */ + function getClassMetadata($className); + + /** + * Gets the metadata factory used to gather the metadata of classes. + * + * @return \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory + */ + function getMetadataFactory(); + + /** + * Helper method to initialize a lazy loading proxy or persistent collection. + * + * This method is a no-op for other objects. + * + * @param object $obj + */ + function initializeObject($obj); + + /** + * Check if the object is part of the current UnitOfWork and therefore + * managed. + * + * @param object $object + * @return bool + */ + function contains($object); +} diff --git a/src/core/libs/Doctrine/Common/Persistence/ObjectManagerAware.php b/src/core/libs/Doctrine/Common/Persistence/ObjectManagerAware.php new file mode 100644 index 0000000..69fba78 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/ObjectManagerAware.php @@ -0,0 +1,49 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence; + +use Doctrine\Common\Persistence\Mapping\ClassMetadata; + +/** + * Makes a Persistent Objects aware of its own object-manager. + * + * Using this interface the managing object manager and class metadata instances + * are injected into the persistent object after construction. This allows + * you to implement ActiveRecord functionality on top of the persistance-ignorance + * that Doctrine propagates. + * + * Word of Warning: This is a very powerful hook to change how you can work with your domain models. + * Using this hook will break the Single Responsibility Principle inside your Domain Objects + * and increase the coupling of database and objects. + * + * Every ObjectManager has to implement this functionality itself. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +interface ObjectManagerAware +{ + /** + * Injects responsible ObjectManager and the ClassMetadata into this persistent object. + * + * @param ObjectManager $objectManager + * @param ClassMetadata $classMetadata + */ + public function injectObjectManager(ObjectManager $objectManager, ClassMetadata $classMetadata); +} diff --git a/src/core/libs/Doctrine/Common/Persistence/ObjectRepository.php b/src/core/libs/Doctrine/Common/Persistence/ObjectRepository.php new file mode 100644 index 0000000..9a3e5b6 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/ObjectRepository.php @@ -0,0 +1,78 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence; + +/** + * Contract for a Doctrine persistence layer ObjectRepository class to implement. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.1 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Jonathan Wage <jonwage@gmail.com> + */ +interface ObjectRepository +{ + /** + * Finds an object by its primary key / identifier. + * + * @param int $id The identifier. + * @return object The object. + */ + function find($id); + + /** + * Finds all objects in the repository. + * + * @return mixed The objects. + */ + function findAll(); + + /** + * Finds objects by a set of criteria. + * + * Optionally sorting and limiting details can be passed. An implementation may throw + * an UnexpectedValueException if certain values of the sorting or limiting details are + * not supported. + * + * @throws \UnexpectedValueException + * @param array $criteria + * @param array|null $orderBy + * @param int|null $limit + * @param int|null $offset + * @return mixed The objects. + */ + function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null); + + /** + * Finds a single object by a set of criteria. + * + * @param array $criteria + * @return object The object. + */ + function findOneBy(array $criteria); + + /** + * Returns the class name of the object managed by the repository + * + * @return string + */ + function getClassName(); +} diff --git a/src/core/libs/Doctrine/Common/Persistence/PersistentObject.php b/src/core/libs/Doctrine/Common/Persistence/PersistentObject.php new file mode 100644 index 0000000..9fcc4cb --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/PersistentObject.php @@ -0,0 +1,244 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence; + +use Doctrine\Common\Persistence\Mapping\ClassMetadata; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; + +/** + * PersistentObject base class that implements getter/setter methods for all mapped fields and associations + * by overriding __call. + * + * This class is a forward compatible implementation of the PersistentObject trait. + * + * + * Limitations: + * + * 1. All persistent objects have to be associated with a single ObjectManager, multiple + * ObjectManagers are not supported. You can set the ObjectManager with `PersistentObject#setObjectManager()`. + * 2. Setters and getters only work if a ClassMetadata instance was injected into the PersistentObject. + * This is either done on `postLoad` of an object or by accessing the global object manager. + * 3. There are no hooks for setters/getters. Just implement the method yourself instead of relying on __call(). + * 4. Slower than handcoded implementations: An average of 7 method calls per access to a field and 11 for an association. + * 5. Only the inverse side associations get autoset on the owning side aswell. Setting objects on the owning side + * will not set the inverse side associations. + * + * @example + * + * PersistentObject::setObjectManager($em); + * + * class Foo extends PersistentObject + * { + * private $id; + * } + * + * $foo = new Foo(); + * $foo->getId(); // method exists through __call + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +abstract class PersistentObject implements ObjectManagerAware +{ + /** + * @var ObjectManager + */ + private static $objectManager; + + /** + * @var ClassMetadata + */ + private $cm; + + /** + * Set the object manager responsible for all persistent object base classes. + * + * @param ObjectManager $objectManager + */ + static public function setObjectManager(ObjectManager $objectManager = null) + { + self::$objectManager = $objectManager; + } + + /** + * @return ObjectManager + */ + static public function getObjectManager() + { + return self::$objectManager; + } + + /** + * Inject Doctrine Object Manager + * + * @param ObjectManager $objectManager + * @param ClassMetadata $classMetadata + * + * @throws \RuntimeException + */ + public function injectObjectManager(ObjectManager $objectManager, ClassMetadata $classMetadata) + { + if ($objectManager !== self::$objectManager) { + throw new \RuntimeException("Trying to use PersistentObject with different ObjectManager instances. " . + "Was PersistentObject::setObjectManager() called?"); + } + + $this->cm = $classMetadata; + } + + /** + * Sets a persistent fields value. + * + * @param string $field + * @param array $args + * + * @throws \BadMethodCallException - When no persistent field exists by that name. + * @throws \InvalidArgumentException - When the wrong target object type is passed to an association + * @return void + */ + private function set($field, $args) + { + $this->initializeDoctrine(); + + if ($this->cm->hasField($field) && !$this->cm->isIdentifier($field)) { + $this->$field = $args[0]; + } else if ($this->cm->hasAssociation($field) && $this->cm->isSingleValuedAssociation($field)) { + $targetClass = $this->cm->getAssociationTargetClass($field); + if (!($args[0] instanceof $targetClass) && $args[0] !== null) { + throw new \InvalidArgumentException("Expected persistent object of type '".$targetClass."'"); + } + $this->$field = $args[0]; + $this->completeOwningSide($field, $targetClass, $args[0]); + } else { + throw new \BadMethodCallException("no field with name '".$field."' exists on '".$this->cm->getName()."'"); + } + } + + /** + * Get persistent field value. + * + * + * @param string $field + * + * @throws \BadMethodCallException - When no persistent field exists by that name. + * @return mixed + */ + private function get($field) + { + $this->initializeDoctrine(); + + if ( $this->cm->hasField($field) || $this->cm->hasAssociation($field) ) { + return $this->$field; + } else { + throw new \BadMethodCallException("no field with name '".$field."' exists on '".$this->cm->getName()."'"); + } + } + + /** + * If this is an inverse side association complete the owning side. + * + * @param string $field + * @param ClassMetadata $targetClass + * @param object $targetObject + */ + private function completeOwningSide($field, $targetClass, $targetObject) + { + // add this object on the owning side aswell, for obvious infinite recursion + // reasons this is only done when called on the inverse side. + if ($this->cm->isAssociationInverseSide($field)) { + $mappedByField = $this->cm->getAssociationMappedByTargetField($field); + $targetMetadata = self::$objectManager->getClassMetadata($targetClass); + + $setter = ($targetMetadata->isCollectionValuedAssociation($mappedByField) ? "add" : "set").$mappedByField; + $targetObject->$setter($this); + } + } + + /** + * Add an object to a collection + * + * @param string $field + * @param array $args + * + * @throws \BadMethodCallException + * @throws \InvalidArgumentException + */ + private function add($field, $args) + { + $this->initializeDoctrine(); + + if ($this->cm->hasAssociation($field) && $this->cm->isCollectionValuedAssociation($field)) { + $targetClass = $this->cm->getAssociationTargetClass($field); + if (!($args[0] instanceof $targetClass)) { + throw new \InvalidArgumentException("Expected persistent object of type '".$targetClass."'"); + } + if (!($this->$field instanceof Collection)) { + $this->$field = new ArrayCollection($this->$field ?: array()); + } + $this->$field->add($args[0]); + $this->completeOwningSide($field, $targetClass, $args[0]); + } else { + throw new \BadMethodCallException("There is no method add".$field."() on ".$this->cm->getName()); + } + } + + /** + * Initialize Doctrine Metadata for this class. + * + * @throws \RuntimeException + * @return void + */ + private function initializeDoctrine() + { + if ($this->cm !== null) { + return; + } + + if (!self::$objectManager) { + throw new \RuntimeException("No runtime object manager set. Call PersistentObject#setObjectManager()."); + } + + $this->cm = self::$objectManager->getClassMetadata(get_class($this)); + } + + /** + * Magic method that implements + * + * @param string $method + * @param array $args + * + * @throws \BadMethodCallException + * @return mixed + */ + public function __call($method, $args) + { + $command = substr($method, 0, 3); + $field = lcfirst(substr($method, 3)); + if ($command == "set") { + $this->set($field, $args); + } else if ($command == "get") { + return $this->get($field); + } else if ($command == "add") { + $this->add($field, $args); + } else { + throw new \BadMethodCallException("There is no method ".$method." on ".$this->cm->getName()); + } + } +} diff --git a/src/core/libs/Doctrine/Common/Persistence/Proxy.php b/src/core/libs/Doctrine/Common/Persistence/Proxy.php new file mode 100644 index 0000000..e25598c --- /dev/null +++ b/src/core/libs/Doctrine/Common/Persistence/Proxy.php @@ -0,0 +1,60 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Persistence; + +/** + * Interface for proxy classes. + * + * @author Roman Borschel <roman@code-factory.org> + * @since 2.2 + */ +interface Proxy +{ + /** + * Marker for Proxy class names. + * + * @var string + */ + const MARKER = '__CG__'; + + /** + * Length of the proxy marker + * + * @var int + */ + const MARKER_LENGTH = 6; + + /** + * Initialize this proxy if its not yet initialized. + * + * Acts as a no-op if already initialized. + * + * @return void + */ + public function __load(); + + /** + * Is this proxy initialized or not. + * + * @return bool + */ + public function __isInitialized(); +} diff --git a/src/core/libs/Doctrine/Common/PropertyChangedListener.php b/src/core/libs/Doctrine/Common/PropertyChangedListener.php new file mode 100644 index 0000000..1171874 --- /dev/null +++ b/src/core/libs/Doctrine/Common/PropertyChangedListener.php @@ -0,0 +1,48 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common; + +/** + * Contract for classes that are potential listeners of a <tt>NotifyPropertyChanged</tt> + * implementor. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision: 3938 $ + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +interface PropertyChangedListener +{ + /** + * Notifies the listener of a property change. + * + * @param object $sender The object on which the property changed. + * @param string $propertyName The name of the property that changed. + * @param mixed $oldValue The old value of the property that changed. + * @param mixed $newValue The new value of the property that changed. + */ + function propertyChanged($sender, $propertyName, $oldValue, $newValue); +} + diff --git a/src/core/libs/Doctrine/Common/Reflection/ClassFinderInterface.php b/src/core/libs/Doctrine/Common/Reflection/ClassFinderInterface.php new file mode 100644 index 0000000..ae69607 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Reflection/ClassFinderInterface.php @@ -0,0 +1,38 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Reflection; + +/** + * Finds a class in a PSR-0 structure. + * + * @author Karoly Negyesi <karoly@negyesi.net> + */ +interface ClassFinderInterface +{ + /** + * Finds a class. + * + * @param string $class The name of the class. + * + * @return + * The name of the class or NULL if not found. + */ + public function findFile($class); +} diff --git a/src/core/libs/Doctrine/Common/Reflection/Psr0FindFile.php b/src/core/libs/Doctrine/Common/Reflection/Psr0FindFile.php new file mode 100644 index 0000000..b6a5fd1 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Reflection/Psr0FindFile.php @@ -0,0 +1,83 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Reflection; + +/** + * Finds a class in a PSR-0 structure. + * + * @author Karoly Negyesi <karoly@negyesi.net> + */ +class Psr0FindFile implements ClassFinderInterface +{ + /** + * The PSR-0 prefixes. + * + * @var string + */ + protected $prefixes; + + /** + * @param string $prefixes + * An array of prefixes. Each key is a PHP namespace and each value is + * a list of directories. + */ + public function __construct($prefixes) + { + $this->prefixes = $prefixes; + } + + /** + * Finds a class. + * + * @param string $class The name of the class. + * + * @return + * The name of the class or NULL if not found. + */ + public function findFile($class) + { + $lastNsPos = strrpos($class, '\\'); + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + if (false !== $lastNsPos) { + // namespaced class name + $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $lastNsPos)) . DIRECTORY_SEPARATOR; + $className = substr($class, $lastNsPos + 1); + } else { + // PEAR-like class name + $classPath = null; + $className = $class; + } + + $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; + + foreach ($this->prefixes as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) { + return $dir . DIRECTORY_SEPARATOR . $classPath; + } + } + } + } + } +} diff --git a/src/core/libs/Doctrine/Common/Reflection/ReflectionProviderInterface.php b/src/core/libs/Doctrine/Common/Reflection/ReflectionProviderInterface.php new file mode 100644 index 0000000..a436a2d --- /dev/null +++ b/src/core/libs/Doctrine/Common/Reflection/ReflectionProviderInterface.php @@ -0,0 +1,45 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Reflection; + +interface ReflectionProviderInterface +{ + /** + * Get the ReflectionClass equivalent for this class. + * + * @return ReflectionClass + */ + public function getReflectionClass(); + + /** + * Get the ReflectionClass equivalent for this class. + * + * @return ReflectionMethod + */ + public function getReflectionMethod($name); + + /** + * Get the ReflectionClass equivalent for this class. + * + * @return ReflectionMethod + */ + public function getReflectionProperty($name); +} diff --git a/src/core/libs/Doctrine/Common/Reflection/StaticReflectionClass.php b/src/core/libs/Doctrine/Common/Reflection/StaticReflectionClass.php new file mode 100644 index 0000000..12e45d5 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Reflection/StaticReflectionClass.php @@ -0,0 +1,112 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Reflection; + +use ReflectionClass; +use ReflectionException; + +class StaticReflectionClass extends ReflectionClass +{ + /** + * The static reflection parser object. + * + * @var StaticReflectionParser + */ + private $staticReflectionParser; + + public function __construct(StaticReflectionParser $staticReflectionParser) + { + $this->staticReflectionParser = $staticReflectionParser; + } + + public function getName() + { + return $this->staticReflectionParser->getClassName(); + } + + public function getDocComment() + { + return $this->staticReflectionParser->getDocComment(); + } + + public function getNamespaceName() + { + return $this->staticReflectionParser->getNamespaceName(); + } + + public function getUseStatements() + { + return $this->staticReflectionParser->getUseStatements(); + } + + public function getMethod($name) + { + return $this->staticReflectionParser->getReflectionMethod($name); + } + + public function getProperty($name) + { + return $this->staticReflectionParser->getReflectionProperty($name); + } + + public static function export($argument, $return = false) { throw new ReflectionException('Method not implemented'); } + public function getConstant($name) { throw new ReflectionException('Method not implemented'); } + public function getConstants() { throw new ReflectionException('Method not implemented'); } + public function getConstructor() { throw new ReflectionException('Method not implemented'); } + public function getDefaultProperties() { throw new ReflectionException('Method not implemented'); } + public function getEndLine() { throw new ReflectionException('Method not implemented'); } + public function getExtension() { throw new ReflectionException('Method not implemented'); } + public function getExtensionName() { throw new ReflectionException('Method not implemented'); } + public function getFileName() { throw new ReflectionException('Method not implemented'); } + public function getInterfaceNames() { throw new ReflectionException('Method not implemented'); } + public function getInterfaces() { throw new ReflectionException('Method not implemented'); } + public function getMethods($filter = NULL) { throw new ReflectionException('Method not implemented'); } + public function getModifiers() { throw new ReflectionException('Method not implemented'); } + public function getParentClass() { throw new ReflectionException('Method not implemented'); } + public function getProperties($filter = NULL) { throw new ReflectionException('Method not implemented'); } + public function getShortName() { throw new ReflectionException('Method not implemented'); } + public function getStartLine() { throw new ReflectionException('Method not implemented'); } + public function getStaticProperties() { throw new ReflectionException('Method not implemented'); } + public function getStaticPropertyValue($name, $default = '') { throw new ReflectionException('Method not implemented'); } + public function getTraitAliases() { throw new ReflectionException('Method not implemented'); } + public function getTraitNames() { throw new ReflectionException('Method not implemented'); } + public function getTraits() { throw new ReflectionException('Method not implemented'); } + public function hasConstant($name) { throw new ReflectionException('Method not implemented'); } + public function hasMethod($name) { throw new ReflectionException('Method not implemented'); } + public function hasProperty($name) { throw new ReflectionException('Method not implemented'); } + public function implementsInterface($interface) { throw new ReflectionException('Method not implemented'); } + public function inNamespace() { throw new ReflectionException('Method not implemented'); } + public function isAbstract() { throw new ReflectionException('Method not implemented'); } + public function isCloneable() { throw new ReflectionException('Method not implemented'); } + public function isFinal() { throw new ReflectionException('Method not implemented'); } + public function isInstance($object) { throw new ReflectionException('Method not implemented'); } + public function isInstantiable() { throw new ReflectionException('Method not implemented'); } + public function isInterface() { throw new ReflectionException('Method not implemented'); } + public function isInternal() { throw new ReflectionException('Method not implemented'); } + public function isIterateable() { throw new ReflectionException('Method not implemented'); } + public function isSubclassOf($class) { throw new ReflectionException('Method not implemented'); } + public function isTrait() { throw new ReflectionException('Method not implemented'); } + public function isUserDefined() { throw new ReflectionException('Method not implemented'); } + public function newInstance($args) { throw new ReflectionException('Method not implemented'); } + public function newInstanceArgs(array $args = array()) { throw new ReflectionException('Method not implemented'); } + public function newInstanceWithoutConstructor() { throw new ReflectionException('Method not implemented'); } + public function setStaticPropertyValue($name, $value) { throw new ReflectionException('Method not implemented'); } + public function __toString() { throw new ReflectionException('Method not implemented'); } +} diff --git a/src/core/libs/Doctrine/Common/Reflection/StaticReflectionMethod.php b/src/core/libs/Doctrine/Common/Reflection/StaticReflectionMethod.php new file mode 100644 index 0000000..6482036 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Reflection/StaticReflectionMethod.php @@ -0,0 +1,103 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Reflection; + +use ReflectionMethod; +use ReflectionException; + +class StaticReflectionMethod extends ReflectionMethod +{ + /** + * The PSR-0 parser object. + * + * @var StaticReflectionParser + */ + protected $staticReflectionParser; + + /** + * The name of the method. + * + * @var string + */ + protected $methodName; + + public function __construct(StaticReflectionParser $staticReflectionParser, $methodName) + { + $this->staticReflectionParser = $staticReflectionParser; + $this->methodName = $methodName; + } + public function getName() + { + return $this->methodName; + } + protected function getStaticReflectionParser() + { + return $this->staticReflectionParser->getStaticReflectionParserForDeclaringClass('method', $this->methodName); + } + public function getDeclaringClass() + { + return $this->getStaticReflectionParser()->getReflectionClass(); + } + public function getNamespaceName() + { + return $this->getStaticReflectionParser()->getNamespaceName(); + } + public function getDocComment() + { + return $this->getStaticReflectionParser()->getDocComment('method', $this->methodName); + } + public function getUseStatements() + { + return $this->getStaticReflectionParser()->getUseStatements(); + } + public static function export($class, $name, $return = false) { throw new ReflectionException('Method not implemented'); } + public function getClosure($object) { throw new ReflectionException('Method not implemented'); } + public function getModifiers() { throw new ReflectionException('Method not implemented'); } + public function getPrototype() { throw new ReflectionException('Method not implemented'); } + public function invoke($object, $parameter = NULL) { throw new ReflectionException('Method not implemented'); } + public function invokeArgs($object, array $args) { throw new ReflectionException('Method not implemented'); } + public function isAbstract() { throw new ReflectionException('Method not implemented'); } + public function isConstructor() { throw new ReflectionException('Method not implemented'); } + public function isDestructor() { throw new ReflectionException('Method not implemented'); } + public function isFinal() { throw new ReflectionException('Method not implemented'); } + public function isPrivate() { throw new ReflectionException('Method not implemented'); } + public function isProtected() { throw new ReflectionException('Method not implemented'); } + public function isPublic() { throw new ReflectionException('Method not implemented'); } + public function isStatic() { throw new ReflectionException('Method not implemented'); } + public function setAccessible($accessible) { throw new ReflectionException('Method not implemented'); } + public function __toString() { throw new ReflectionException('Method not implemented'); } + public function getClosureThis() { throw new ReflectionException('Method not implemented'); } + public function getEndLine() { throw new ReflectionException('Method not implemented'); } + public function getExtension() { throw new ReflectionException('Method not implemented'); } + public function getExtensionName() { throw new ReflectionException('Method not implemented'); } + public function getFileName() { throw new ReflectionException('Method not implemented'); } + public function getNumberOfParameters() { throw new ReflectionException('Method not implemented'); } + public function getNumberOfRequiredParameters() { throw new ReflectionException('Method not implemented'); } + public function getParameters() { throw new ReflectionException('Method not implemented'); } + public function getShortName() { throw new ReflectionException('Method not implemented'); } + public function getStartLine() { throw new ReflectionException('Method not implemented'); } + public function getStaticVariables() { throw new ReflectionException('Method not implemented'); } + public function inNamespace() { throw new ReflectionException('Method not implemented'); } + public function isClosure() { throw new ReflectionException('Method not implemented'); } + public function isDeprecated() { throw new ReflectionException('Method not implemented'); } + public function isInternal() { throw new ReflectionException('Method not implemented'); } + public function isUserDefined() { throw new ReflectionException('Method not implemented'); } + public function returnsReference() { throw new ReflectionException('Method not implemented'); } +} diff --git a/src/core/libs/Doctrine/Common/Reflection/StaticReflectionParser.php b/src/core/libs/Doctrine/Common/Reflection/StaticReflectionParser.php new file mode 100644 index 0000000..7f3e41f --- /dev/null +++ b/src/core/libs/Doctrine/Common/Reflection/StaticReflectionParser.php @@ -0,0 +1,282 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Reflection; + +use ReflectionException; +use Doctrine\Common\Annotations\TokenParser; + +/** + * Parses a file for namespaces/use/class declarations. + * + * @author Karoly Negyesi <karoly@negyesi.net> + */ +class StaticReflectionParser implements ReflectionProviderInterface +{ + + /** + * The name of the class. + * + * @var string + */ + protected $className; + + /** + * TRUE if the caller only wants class annotations. + * + * @var boolean. + */ + protected $classAnnotationOptimize; + + /** + * TRUE when the parser has ran. + * + * @var boolean + */ + protected $parsed = false; + + /** + * The namespace of the class + * + * @var string + */ + protected $namespace = ''; + + /** + * The use statements of this class. + * + * @var array + */ + protected $useStatements = array(); + + /** + * The docComment of the class. + * + * @var string + */ + protected $docComment = array( + 'class' => '', + 'property' => array(), + 'method' => array(), + ); + + /** + * The name of the class this class extends, if any. + * + * @var string + */ + protected $parentClassName = ''; + + /** + * The parent PSR-0 Parser. + * + * @var \Doctrine\Common\Annotations\StaticReflectionParser + */ + protected $parentStaticReflectionParser; + + /** + * Parses a class residing in a PSR-0 hierarchy. + * + * @param string $class + * The full, namespaced class name. + * @param ClassFinder $finder + * A ClassFinder object which finds the class. + * @param boolean $classAnnotationOptimize + * Only retrieve the class docComment. Presumes there is only one + * statement per line. + */ + public function __construct($className, $finder, $classAnnotationOptimize = false) + { + $this->className = ltrim($className, '\\'); + if ($lastNsPos = strrpos($this->className, '\\')) { + $this->namespace = substr($this->className, 0, $lastNsPos); + } + $this->finder = $finder; + $this->classAnnotationOptimize = $classAnnotationOptimize; + } + + protected function parse() + { + if ($this->parsed || !$fileName = $this->finder->findFile($this->className)) { + return; + } + $this->parsed = true; + $contents = file_get_contents($fileName); + if ($this->classAnnotationOptimize) { + if (preg_match("/(\A.*)^\s+(abstract|final)?\s+class\s+$className\s+{/sm", $contents, $matches)) { + $contents = $matches[1]; + } + } + $tokenParser = new TokenParser($contents); + $docComment = ''; + while ($token = $tokenParser->next(false)) { + if (is_array($token)) { + switch ($token[0]) { + case T_USE: + $this->useStatements = array_merge($this->useStatements, $tokenParser->parseUseStatement()); + break; + case T_DOC_COMMENT: + $docComment = $token[1]; + break; + case T_CLASS: + $this->docComment['class'] = $docComment; + $docComment = ''; + break; + case T_VAR: + case T_PRIVATE: + case T_PROTECTED: + case T_PUBLIC: + $token = $tokenParser->next(); + if ($token[0] === T_VARIABLE) { + $propertyName = substr($token[1], 1); + $this->docComment['property'][$propertyName] = $docComment; + continue 2; + } + if ($token[0] !== T_FUNCTION) { + // For example, it can be T_FINAL. + continue 2; + } + // No break. + case T_FUNCTION: + // The next string after function is the name, but + // there can be & before the function name so find the + // string. + while (($token = $tokenParser->next()) && $token[0] !== T_STRING); + $methodName = $token[1]; + $this->docComment['method'][$methodName] = $docComment; + $docComment = ''; + break; + case T_EXTENDS: + $this->parentClassName = $tokenParser->parseClass(); + $nsPos = strpos($this->parentClassName, '\\'); + $fullySpecified = false; + if ($nsPos === 0) { + $fullySpecified = true; + } else { + if ($nsPos) { + $prefix = strtolower(substr($this->parentClassName, 0, $nsPos)); + $postfix = substr($this->parentClassName, $nsPos); + } else { + $prefix = strtolower($this->parentClassName); + $postfix = ''; + } + foreach ($this->useStatements as $alias => $use) { + if ($alias == $prefix) { + $this->parentClassName = '\\' . $use . $postfix; + $fullySpecified = true; + } + } + } + if (!$fullySpecified) { + $this->parentClassName = '\\' . $this->namespace . '\\' . $this->parentClassName; + } + break; + } + } + } + } + + protected function getParentStaticReflectionParser() + { + if (empty($this->parentStaticReflectionParser)) { + $this->parentStaticReflectionParser = new static($this->parentClassName, $this->finder); + } + + return $this->parentStaticReflectionParser; + } + + public function getClassName() + { + return $this->className; + } + + public function getNamespaceName() + { + return $this->namespace; + } + + /** + * Get the ReflectionClass equivalent for this file / class. + */ + public function getReflectionClass() + { + return new StaticReflectionClass($this); + } + + /** + * Get the ReflectionMethod equivalent for the method of this file / class. + */ + public function getReflectionMethod($methodName) + { + return new StaticReflectionMethod($this, $methodName); + } + + /** + * Get the ReflectionProperty equivalent for the method of this file / class. + */ + public function getReflectionProperty($propertyName) + { + return new StaticReflectionProperty($this, $propertyName); + } + + /** + * Get the use statements from this file. + */ + public function getUseStatements() + { + $this->parse(); + + return $this->useStatements; + } + + /** + * Get docComment. + * + * @param string $type class, property or method. + * @param string $name Name of the property or method, not needed for class. + * + * @return string the doc comment or empty string if none. + */ + public function getDocComment($type = 'class', $name = '') + { + $this->parse(); + + return $name ? $this->docComment[$type][$name] : $this->docComment[$type]; + } + + /** + * Get the PSR-0 parser for the declaring class. + * + * @param string $type property or method. + * @param string $name Name of the property or method. + * + * @return StaticReflectionParser A static reflection parser for the declaring class. + */ + public function getStaticReflectionParserForDeclaringClass($type, $name) + { + $this->parse(); + if (isset($this->docComment[$type][$name])) { + return $this; + } + if (!empty($this->parentClassName)) { + return $this->getParentStaticReflectionParser()->getStaticReflectionParserForDeclaringClass($type, $name); + } + throw new ReflectionException('Invalid ' . $type . ' "' . $name . '"'); + } +} diff --git a/src/core/libs/Doctrine/Common/Reflection/StaticReflectionProperty.php b/src/core/libs/Doctrine/Common/Reflection/StaticReflectionProperty.php new file mode 100644 index 0000000..7c6411a --- /dev/null +++ b/src/core/libs/Doctrine/Common/Reflection/StaticReflectionProperty.php @@ -0,0 +1,77 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Reflection; + +use ReflectionProperty; +use ReflectionException; + +class StaticReflectionProperty extends ReflectionProperty +{ + /** + * The PSR-0 parser object. + * + * @var StaticReflectionParser + */ + protected $staticReflectionParser; + + /** + * The name of the property. + * + * @var string + */ + protected $propertyName; + + public function __construct(StaticReflectionParser $staticReflectionParser, $propertyName) + { + $this->staticReflectionParser = $staticReflectionParser; + $this->propertyName = $propertyName; + } + public function getName() + { + return $this->propertyName; + } + protected function getStaticReflectionParser() + { + return $this->staticReflectionParser->getStaticReflectionParserForDeclaringClass('property', $this->propertyName); + } + public function getDeclaringClass() + { + return $this->getStaticReflectionParser()->getReflectionClass(); + } + public function getDocComment() + { + return $this->getStaticReflectionParser()->getDocComment('property', $this->propertyName); + } + public function getUseStatements() + { + return $this->getStaticReflectionParser()->getUseStatements(); + } + public static function export ($class, $name, $return = false) { throw new ReflectionException('Method not implemented'); } + public function getModifiers() { throw new ReflectionException('Method not implemented'); } + public function getValue($object = NULL) { throw new ReflectionException('Method not implemented'); } + public function isDefault() { throw new ReflectionException('Method not implemented'); } + public function isPrivate() { throw new ReflectionException('Method not implemented'); } + public function isProtected() { throw new ReflectionException('Method not implemented'); } + public function isPublic() { throw new ReflectionException('Method not implemented'); } + public function isStatic() { throw new ReflectionException('Method not implemented'); } + public function setAccessible ($accessible) { throw new ReflectionException('Method not implemented'); } + public function setValue ($object, $value = NULL) { throw new ReflectionException('Method not implemented'); } + public function __toString() { throw new ReflectionException('Method not implemented'); } +} diff --git a/src/core/libs/Doctrine/Common/Util/ClassUtils.php b/src/core/libs/Doctrine/Common/Util/ClassUtils.php new file mode 100644 index 0000000..078a8db --- /dev/null +++ b/src/core/libs/Doctrine/Common/Util/ClassUtils.php @@ -0,0 +1,103 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Util; + +use Doctrine\Common\Persistence\Proxy; + +/** + * Class and reflection related functionality for objects that + * might or not be proxy objects at the moment. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Johannes Schmitt <schmittjoh@gmail.com> + */ +class ClassUtils +{ + /** + * Get the real class name of a class name that could be a proxy. + * + * @param string + * @return string + */ + public static function getRealClass($class) + { + if (false === $pos = strrpos($class, '\\'.Proxy::MARKER.'\\')) { + return $class; + } + + return substr($class, $pos + Proxy::MARKER_LENGTH + 2); + } + + /** + * Get the real class name of an object (even if its a proxy) + * + * @param object + * @return string + */ + public static function getClass($object) + { + return self::getRealClass(get_class($object)); + } + + /** + * Get the real parent class name of a class or object + * + * @param string + * @return string + */ + public static function getParentClass($className) + { + return get_parent_class( self::getRealClass( $className ) ); + } + + /** + * Create a new reflection class + * + * @param string + * @return \ReflectionClass + */ + public static function newReflectionClass($class) + { + return new \ReflectionClass( self::getRealClass( $class ) ); + } + + /** + * Create a new reflection object + * + * @param object + * @return \ReflectionObject + */ + public static function newReflectionObject($object) + { + return self::newReflectionClass( self::getClass( $object ) ); + } + + /** + * Given a class name and a proxy namespace return the proxy name. + * + * @param string $className + * @param string $proxyNamespace + * @return string + */ + public static function generateProxyClassName($className, $proxyNamespace) + { + return rtrim($proxyNamespace, '\\') . '\\'.Proxy::MARKER.'\\' . ltrim($className, '\\'); + } +} diff --git a/src/core/libs/Doctrine/Common/Util/Debug.php b/src/core/libs/Doctrine/Common/Util/Debug.php new file mode 100644 index 0000000..458e5c8 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Util/Debug.php @@ -0,0 +1,135 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Util; + +/** + * Static class containing most used debug methods. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author Giorgio Sironi <piccoloprincipeazzurro@gmail.com> + */ +final class Debug +{ + /** + * Private constructor (prevents from instantiation) + * + */ + private function __construct() {} + + /** + * Prints a dump of the public, protected and private properties of $var. + * + * @link http://xdebug.org/ + * @param mixed $var + * @param integer $maxDepth Maximum nesting level for object properties + * @param boolean $stripTags Flag that indicate if output should strip HTML tags + */ + public static function dump($var, $maxDepth = 2, $stripTags = true) + { + ini_set('html_errors', 'On'); + + if (extension_loaded('xdebug')) { + ini_set('xdebug.var_display_max_depth', $maxDepth); + } + + $var = self::export($var, $maxDepth++); + + ob_start(); + var_dump($var); + $dump = ob_get_contents(); + ob_end_clean(); + + echo ($stripTags ? strip_tags(html_entity_decode($dump)) : $dump); + + ini_set('html_errors', 'Off'); + } + + /** + * Export + * + * @param mixed $var + * @param int $maxDepth + * @return mixed + */ + public static function export($var, $maxDepth) + { + $return = null; + $isObj = is_object($var); + + if ($isObj && in_array('Doctrine\Common\Collections\Collection', class_implements($var))) { + $var = $var->toArray(); + } + + if ($maxDepth) { + if (is_array($var)) { + $return = array(); + + foreach ($var as $k => $v) { + $return[$k] = self::export($v, $maxDepth - 1); + } + } else if ($isObj) { + $return = new \stdclass(); + if ($var instanceof \DateTime) { + $return->__CLASS__ = "DateTime"; + $return->date = $var->format('c'); + $return->timezone = $var->getTimeZone()->getName(); + } else { + $reflClass = ClassUtils::newReflectionObject($var); + $return->__CLASS__ = ClassUtils::getClass($var); + + if ($var instanceof \Doctrine\Common\Persistence\Proxy) { + $return->__IS_PROXY__ = true; + $return->__PROXY_INITIALIZED__ = $var->__isInitialized(); + } + + foreach ($reflClass->getProperties() as $reflProperty) { + $name = $reflProperty->getName(); + + $reflProperty->setAccessible(true); + $return->$name = self::export($reflProperty->getValue($var), $maxDepth - 1); + } + } + } else { + $return = $var; + } + } else { + $return = is_object($var) ? get_class($var) + : (is_array($var) ? 'Array(' . count($var) . ')' : $var); + } + + return $return; + } + + /** + * Convert to string + * + * @param object $obj + * @return string + */ + public static function toString($obj) + { + return method_exists('__toString', $obj) ? (string) $obj : get_class($obj) . '@' . spl_object_hash($obj); + } +} diff --git a/src/core/libs/Doctrine/Common/Util/Inflector.php b/src/core/libs/Doctrine/Common/Util/Inflector.php new file mode 100644 index 0000000..214ed57 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Util/Inflector.php @@ -0,0 +1,72 @@ +<?php +/* + * $Id: Inflector.php 3189 2007-11-18 20:37:44Z meus $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common\Util; + +/** + * Doctrine inflector has static methods for inflecting text + * + * The methods in these classes are from several different sources collected + * across several different php projects and several different authors. The + * original author names and emails are not known + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 1.0 + * @version $Revision: 3189 $ + * @author Konsta Vesterinen <kvesteri@cc.hut.fi> + * @author Jonathan H. Wage <jonwage@gmail.com> + */ +class Inflector +{ + /** + * Convert word in to the format for a Doctrine table name. Converts 'ModelName' to 'model_name' + * + * @param string $word Word to tableize + * @return string $word Tableized word + */ + public static function tableize($word) + { + return strtolower(preg_replace('~(?<=\\w)([A-Z])~', '_$1', $word)); + } + + /** + * Convert a word in to the format for a Doctrine class name. Converts 'table_name' to 'TableName' + * + * @param string $word Word to classify + * @return string $word Classified word + */ + public static function classify($word) + { + return str_replace(" ", "", ucwords(strtr($word, "_-", " "))); + } + + /** + * Camelize a word. This uses the classify() method and turns the first character to lowercase + * + * @param string $word + * @return string $word + */ + public static function camelize($word) + { + return lcfirst(self::classify($word)); + } +} diff --git a/src/core/libs/Doctrine/Common/Version.php b/src/core/libs/Doctrine/Common/Version.php new file mode 100644 index 0000000..cca4894 --- /dev/null +++ b/src/core/libs/Doctrine/Common/Version.php @@ -0,0 +1,55 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\Common; + +/** + * Class to store and retrieve the version of Doctrine + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class Version +{ + /** + * Current Doctrine Version + */ + const VERSION = '2.3.0'; + + /** + * Compares a Doctrine version with the current one. + * + * @param string $version Doctrine version to compare. + * @return int Returns -1 if older, 0 if it is the same, 1 if version + * passed as argument is newer. + */ + public static function compare($version) + { + $currentVersion = str_replace(' ', '', strtolower(self::VERSION)); + $version = str_replace(' ', '', $version); + + return version_compare($version, $currentVersion); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Cache/ArrayStatement.php b/src/core/libs/Doctrine/DBAL/Cache/ArrayStatement.php new file mode 100644 index 0000000..c408d21 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Cache/ArrayStatement.php @@ -0,0 +1,108 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Cache; + +use Doctrine\DBAL\Driver\ResultStatement; +use PDO; + +class ArrayStatement implements \IteratorAggregate, ResultStatement +{ + private $data; + private $columnCount = 0; + private $num = 0; + private $defaultFetchMode = PDO::FETCH_BOTH; + + public function __construct(array $data) + { + $this->data = $data; + if (count($data)) { + $this->columnCount = count($data[0]); + } + } + + public function closeCursor() + { + unset ($this->data); + } + + public function columnCount() + { + return $this->columnCount; + } + + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + if ($arg2 !== null || $arg3 !== null) { + throw new \InvalidArgumentException("Caching layer does not support 2nd/3rd argument to setFetchMode()"); + } + + $this->defaultFetchMode = $fetchMode; + } + + public function getIterator() + { + $data = $this->fetchAll(); + return new \ArrayIterator($data); + } + + public function fetch($fetchMode = null) + { + if (isset($this->data[$this->num])) { + $row = $this->data[$this->num++]; + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + if ($fetchMode === PDO::FETCH_ASSOC) { + return $row; + } else if ($fetchMode === PDO::FETCH_NUM) { + return array_values($row); + } else if ($fetchMode === PDO::FETCH_BOTH) { + return array_merge($row, array_values($row)); + } else if ($fetchMode === PDO::FETCH_COLUMN) { + return reset($row); + } else { + throw new \InvalidArgumentException("Invalid fetch-style given for fetching result."); + } + } + return false; + } + + public function fetchAll($fetchMode = null) + { + $rows = array(); + while ($row = $this->fetch($fetchMode)) { + $rows[] = $row; + } + return $rows; + } + + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(PDO::FETCH_NUM); + if (!isset($row[$columnIndex])) { + // TODO: verify this is correct behavior + return false; + } + return $row[$columnIndex]; + } + + public function rowCount() + { + return $this->num; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Cache/CacheException.php b/src/core/libs/Doctrine/DBAL/Cache/CacheException.php new file mode 100644 index 0000000..dd27477 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Cache/CacheException.php @@ -0,0 +1,37 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Cache; + +/** + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.2 + */ +class CacheException extends \Doctrine\DBAL\DBALException +{ + static public function noCacheKey() + { + return new self("No cache key was set."); + } + + static public function noResultDriverConfigured() + { + return new self("Trying to cache a query but no result driver is configured."); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Cache/QueryCacheProfile.php b/src/core/libs/Doctrine/DBAL/Cache/QueryCacheProfile.php new file mode 100644 index 0000000..54c34b9 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Cache/QueryCacheProfile.php @@ -0,0 +1,131 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Cache; + +use Doctrine\Common\Cache\Cache; + +/** + * Query Cache Profile handles the data relevant for query caching. + * + * It is a value object, setter methods return NEW instances. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class QueryCacheProfile +{ + /** + * @var Cache + */ + private $resultCacheDriver; + /** + * @var int + */ + private $lifetime = 0; + /** + * @var string + */ + private $cacheKey; + + /** + * @param int $lifetime + * @param string $cacheKey + * @param Cache $resultCache + */ + public function __construct($lifetime = 0, $cacheKey = null, Cache $resultCache = null) + { + $this->lifetime = $lifetime; + $this->cacheKey = $cacheKey; + $this->resultCacheDriver = $resultCache; + } + + /** + * @return Cache + */ + public function getResultCacheDriver() + { + return $this->resultCacheDriver; + } + + /** + * @return int + */ + public function getLifetime() + { + return $this->lifetime; + } + + /** + * @return string + */ + public function getCacheKey() + { + if ($this->cacheKey === null) { + throw CacheException::noCacheKey(); + } + return $this->cacheKey; + } + + /** + * Generate the real cache key from query, params and types. + * + * @param string $query + * @param array $params + * @param array $types + * @return array + */ + public function generateCacheKeys($query, $params, $types) + { + $realCacheKey = $query . "-" . serialize($params) . "-" . serialize($types); + // should the key be automatically generated using the inputs or is the cache key set? + if ($this->cacheKey === null) { + $cacheKey = sha1($realCacheKey); + } else { + $cacheKey = $this->cacheKey; + } + return array($cacheKey, $realCacheKey); + } + + /** + * @param Cache $cache + * @return QueryCacheProfile + */ + public function setResultCacheDriver(Cache $cache) + { + return new QueryCacheProfile($this->lifetime, $this->cacheKey, $cache); + } + + /** + * @param string|null $cacheKey + * @return QueryCacheProfile + */ + public function setCacheKey($cacheKey) + { + return new QueryCacheProfile($this->lifetime, $cacheKey, $this->resultCacheDriver); + } + + /** + * @param int $lifetime + * @return QueryCacheProfile + */ + public function setLifetime($lifetime) + { + return new QueryCacheProfile($lifetime, $this->cacheKey, $this->resultCacheDriver); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Cache/ResultCacheStatement.php b/src/core/libs/Doctrine/DBAL/Cache/ResultCacheStatement.php new file mode 100644 index 0000000..f118e7c --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Cache/ResultCacheStatement.php @@ -0,0 +1,239 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Cache; + +use Doctrine\DBAL\Driver\Statement; +use Doctrine\DBAL\Driver\ResultStatement; +use Doctrine\DBAL\Connection; +use Doctrine\Common\Cache\Cache; +use PDO; + +/** + * Cache statement for SQL results. + * + * A result is saved in multiple cache keys, there is the originally specified + * cache key which is just pointing to result rows by key. The following things + * have to be ensured: + * + * 1. lifetime of the original key has to be longer than that of all the individual rows keys + * 2. if any one row key is missing the query has to be re-executed. + * + * Also you have to realize that the cache will load the whole result into memory at once to ensure 2. + * This means that the memory usage for cached results might increase by using this feature. + */ +class ResultCacheStatement implements \IteratorAggregate, ResultStatement +{ + /** + * @var \Doctrine\Common\Cache\Cache + */ + private $resultCache; + + /** + * + * @var string + */ + private $cacheKey; + + /** + * @var string + */ + private $realKey; + + /** + * @var int + */ + private $lifetime; + + /** + * @var Doctrine\DBAL\Driver\Statement + */ + private $statement; + + /** + * Did we reach the end of the statement? + * + * @var bool + */ + private $emptied = false; + + /** + * @var array + */ + private $data; + + /** + * @var int + */ + private $defaultFetchMode = PDO::FETCH_BOTH; + + /** + * @param Statement $stmt + * @param Cache $resultCache + * @param string $cacheKey + * @param string $realKey + * @param int $lifetime + */ + public function __construct(Statement $stmt, Cache $resultCache, $cacheKey, $realKey, $lifetime) + { + $this->statement = $stmt; + $this->resultCache = $resultCache; + $this->cacheKey = $cacheKey; + $this->realKey = $realKey; + $this->lifetime = $lifetime; + } + + /** + * Closes the cursor, enabling the statement to be executed again. + * + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function closeCursor() + { + $this->statement->closeCursor(); + if ($this->emptied && $this->data !== null) { + $data = $this->resultCache->fetch($this->cacheKey); + if ( ! $data) { + $data = array(); + } + $data[$this->realKey] = $this->data; + + $this->resultCache->save($this->cacheKey, $data, $this->lifetime); + unset($this->data); + } + } + + /** + * columnCount + * Returns the number of columns in the result set + * + * @return integer Returns the number of columns in the result set represented + * by the PDOStatement object. If there is no result set, + * this method should return 0. + */ + public function columnCount() + { + return $this->statement->columnCount(); + } + + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->defaultFetchMode = $fetchMode; + } + + public function getIterator() + { + $data = $this->fetchAll(); + return new \ArrayIterator($data); + } + + /** + * fetch + * + * @see Query::HYDRATE_* constants + * @param integer $fetchMode Controls how the next row will be returned to the caller. + * This value must be one of the Query::HYDRATE_* constants, + * defaulting to Query::HYDRATE_BOTH + * + * @return mixed + */ + public function fetch($fetchMode = null) + { + if ($this->data === null) { + $this->data = array(); + } + + $row = $this->statement->fetch(PDO::FETCH_ASSOC); + if ($row) { + $this->data[] = $row; + + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + + if ($fetchMode == PDO::FETCH_ASSOC) { + return $row; + } else if ($fetchMode == PDO::FETCH_NUM) { + return array_values($row); + } else if ($fetchMode == PDO::FETCH_BOTH) { + return array_merge($row, array_values($row)); + } else if ($fetchMode == PDO::FETCH_COLUMN) { + return reset($row); + } else { + throw new \InvalidArgumentException("Invalid fetch-style given for caching result."); + } + } + $this->emptied = true; + return false; + } + + /** + * Returns an array containing all of the result set rows + * + * @param integer $fetchMode Controls how the next row will be returned to the caller. + * This value must be one of the Query::HYDRATE_* constants, + * defaulting to Query::HYDRATE_BOTH + * + * @return array + */ + public function fetchAll($fetchMode = null) + { + $rows = array(); + while ($row = $this->fetch($fetchMode)) { + $rows[] = $row; + } + return $rows; + } + + /** + * fetchColumn + * Returns a single column from the next row of a + * result set or FALSE if there are no more rows. + * + * @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row. If no + * value is supplied, PDOStatement->fetchColumn() + * fetches the first column. + * + * @return string returns a single column in the next row of a result set. + */ + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(PDO::FETCH_NUM); + if (!isset($row[$columnIndex])) { + // TODO: verify this is correct behavior + return false; + } + return $row[$columnIndex]; + } + + /** + * rowCount + * rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement + * executed by the corresponding object. + * + * If the last SQL statement executed by the associated Statement object was a SELECT statement, + * some databases may return the number of rows returned by that statement. However, + * this behaviour is not guaranteed for all databases and should not be + * relied on for portable applications. + * + * @return integer Returns the number of rows. + */ + public function rowCount() + { + return $this->statement->rowCount(); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Configuration.php b/src/core/libs/Doctrine/DBAL/Configuration.php new file mode 100644 index 0000000..53f7b5e --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Configuration.php @@ -0,0 +1,113 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL; + +use Doctrine\DBAL\Logging\SQLLogger; +use Doctrine\Common\Cache\Cache; + +/** + * Configuration container for the Doctrine DBAL. + * + * @since 2.0 + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @internal When adding a new configuration option just write a getter/setter + * pair and add the option to the _attributes array with a proper default value. + */ +class Configuration +{ + /** + * The attributes that are contained in the configuration. + * Values are default values. + * + * @var array + */ + protected $_attributes = array(); + + /** + * Sets the SQL logger to use. Defaults to NULL which means SQL logging is disabled. + * + * @param SQLLogger $logger + */ + public function setSQLLogger(SQLLogger $logger = null) + { + $this->_attributes['sqlLogger'] = $logger; + } + + /** + * Gets the SQL logger that is used. + * + * @return SQLLogger + */ + public function getSQLLogger() + { + return isset($this->_attributes['sqlLogger']) ? + $this->_attributes['sqlLogger'] : null; + } + + /** + * Gets the cache driver implementation that is used for query result caching. + * + * @return \Doctrine\Common\Cache\Cache + */ + public function getResultCacheImpl() + { + return isset($this->_attributes['resultCacheImpl']) ? + $this->_attributes['resultCacheImpl'] : null; + } + + /** + * Sets the cache driver implementation that is used for query result caching. + * + * @param \Doctrine\Common\Cache\Cache $cacheImpl + */ + public function setResultCacheImpl(Cache $cacheImpl) + { + $this->_attributes['resultCacheImpl'] = $cacheImpl; + } + + /** + * Filter schema assets expression. + * + * Only include tables/sequences matching the filter expression regexp in + * schema instances generated for the active connection when calling + * {AbstractSchemaManager#createSchema()}. + * + * @param string $filterExpression + */ + public function setFilterSchemaAssetsExpression($filterExpression) + { + $this->_attributes['filterSchemaAssetsExpression'] = $filterExpression; + } + + /** + * Return filter schema assets expression. + * + * @return string|null + */ + public function getFilterSchemaAssetsExpression() + { + if (isset($this->_attributes['filterSchemaAssetsExpression'])) { + return $this->_attributes['filterSchemaAssetsExpression']; + } + return null; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Connection.php b/src/core/libs/Doctrine/DBAL/Connection.php new file mode 100644 index 0000000..80efa94 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Connection.php @@ -0,0 +1,1308 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL; + +use PDO, Closure, Exception, + Doctrine\DBAL\Types\Type, + Doctrine\DBAL\Driver\Connection as DriverConnection, + Doctrine\Common\EventManager, + Doctrine\DBAL\DBALException, + Doctrine\DBAL\Cache\ResultCacheStatement, + Doctrine\DBAL\Cache\QueryCacheProfile, + Doctrine\DBAL\Cache\ArrayStatement, + Doctrine\DBAL\Cache\CacheException; + +/** + * A wrapper around a Doctrine\DBAL\Driver\Connection that adds features like + * events, transaction isolation levels, configuration, emulated transaction nesting, + * lazy connecting and more. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author Konsta Vesterinen <kvesteri@cc.hut.fi> + * @author Lukas Smith <smith@pooteeweet.org> (MDB2 library) + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class Connection implements DriverConnection +{ + /** + * Constant for transaction isolation level READ UNCOMMITTED. + */ + const TRANSACTION_READ_UNCOMMITTED = 1; + + /** + * Constant for transaction isolation level READ COMMITTED. + */ + const TRANSACTION_READ_COMMITTED = 2; + + /** + * Constant for transaction isolation level REPEATABLE READ. + */ + const TRANSACTION_REPEATABLE_READ = 3; + + /** + * Constant for transaction isolation level SERIALIZABLE. + */ + const TRANSACTION_SERIALIZABLE = 4; + + /** + * Represents an array of ints to be expanded by Doctrine SQL parsing. + * + * @var int + */ + const PARAM_INT_ARRAY = 101; + + /** + * Represents an array of strings to be expanded by Doctrine SQL parsing. + * + * @var int + */ + const PARAM_STR_ARRAY = 102; + + /** + * Offset by which PARAM_* constants are detected as arrays of the param type. + * + * @var int + */ + const ARRAY_PARAM_OFFSET = 100; + + /** + * The wrapped driver connection. + * + * @var \Doctrine\DBAL\Driver\Connection + */ + protected $_conn; + + /** + * @var \Doctrine\DBAL\Configuration + */ + protected $_config; + + /** + * @var \Doctrine\Common\EventManager + */ + protected $_eventManager; + + /** + * @var \Doctrine\DBAL\Query\Expression\ExpressionBuilder + */ + protected $_expr; + + /** + * Whether or not a connection has been established. + * + * @var boolean + */ + private $_isConnected = false; + + /** + * The transaction nesting level. + * + * @var integer + */ + private $_transactionNestingLevel = 0; + + /** + * The currently active transaction isolation level. + * + * @var integer + */ + private $_transactionIsolationLevel; + + /** + * If nested transations should use savepoints + * + * @var integer + */ + private $_nestTransactionsWithSavepoints; + + /** + * The parameters used during creation of the Connection instance. + * + * @var array + */ + private $_params = array(); + + /** + * The DatabasePlatform object that provides information about the + * database platform used by the connection. + * + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + protected $_platform; + + /** + * The schema manager. + * + * @var \Doctrine\DBAL\Schema\AbstractSchemaManager + */ + protected $_schemaManager; + + /** + * The used DBAL driver. + * + * @var \Doctrine\DBAL\Driver + */ + protected $_driver; + + /** + * Flag that indicates whether the current transaction is marked for rollback only. + * + * @var boolean + */ + private $_isRollbackOnly = false; + + private $_defaultFetchMode = PDO::FETCH_ASSOC; + + /** + * Initializes a new instance of the Connection class. + * + * @param array $params The connection parameters. + * @param Driver $driver + * @param Configuration $config + * @param EventManager $eventManager + */ + public function __construct(array $params, Driver $driver, Configuration $config = null, + EventManager $eventManager = null) + { + $this->_driver = $driver; + $this->_params = $params; + + if (isset($params['pdo'])) { + $this->_conn = $params['pdo']; + $this->_isConnected = true; + } + + // Create default config and event manager if none given + if ( ! $config) { + $config = new Configuration(); + } + + if ( ! $eventManager) { + $eventManager = new EventManager(); + } + + $this->_config = $config; + $this->_eventManager = $eventManager; + + $this->_expr = new Query\Expression\ExpressionBuilder($this); + + if ( ! isset($params['platform'])) { + $this->_platform = $driver->getDatabasePlatform(); + } else if ($params['platform'] instanceof Platforms\AbstractPlatform) { + $this->_platform = $params['platform']; + } else { + throw DBALException::invalidPlatformSpecified(); + } + + $this->_platform->setEventManager($eventManager); + + $this->_transactionIsolationLevel = $this->_platform->getDefaultTransactionIsolationLevel(); + } + + /** + * Gets the parameters used during instantiation. + * + * @return array $params + */ + public function getParams() + { + return $this->_params; + } + + /** + * Gets the name of the database this Connection is connected to. + * + * @return string $database + */ + public function getDatabase() + { + return $this->_driver->getDatabase($this); + } + + /** + * Gets the hostname of the currently connected database. + * + * @return string + */ + public function getHost() + { + return isset($this->_params['host']) ? $this->_params['host'] : null; + } + + /** + * Gets the port of the currently connected database. + * + * @return mixed + */ + public function getPort() + { + return isset($this->_params['port']) ? $this->_params['port'] : null; + } + + /** + * Gets the username used by this connection. + * + * @return string + */ + public function getUsername() + { + return isset($this->_params['user']) ? $this->_params['user'] : null; + } + + /** + * Gets the password used by this connection. + * + * @return string + */ + public function getPassword() + { + return isset($this->_params['password']) ? $this->_params['password'] : null; + } + + /** + * Gets the DBAL driver instance. + * + * @return \Doctrine\DBAL\Driver + */ + public function getDriver() + { + return $this->_driver; + } + + /** + * Gets the Configuration used by the Connection. + * + * @return \Doctrine\DBAL\Configuration + */ + public function getConfiguration() + { + return $this->_config; + } + + /** + * Gets the EventManager used by the Connection. + * + * @return \Doctrine\Common\EventManager + */ + public function getEventManager() + { + return $this->_eventManager; + } + + /** + * Gets the DatabasePlatform for the connection. + * + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getDatabasePlatform() + { + return $this->_platform; + } + + /** + * Gets the ExpressionBuilder for the connection. + * + * @return \Doctrine\DBAL\Query\Expression\ExpressionBuilder + */ + public function getExpressionBuilder() + { + return $this->_expr; + } + + /** + * Establishes the connection with the database. + * + * @return boolean TRUE if the connection was successfully established, FALSE if + * the connection is already open. + */ + public function connect() + { + if ($this->_isConnected) return false; + + $driverOptions = isset($this->_params['driverOptions']) ? + $this->_params['driverOptions'] : array(); + $user = isset($this->_params['user']) ? $this->_params['user'] : null; + $password = isset($this->_params['password']) ? + $this->_params['password'] : null; + + $this->_conn = $this->_driver->connect($this->_params, $user, $password, $driverOptions); + $this->_isConnected = true; + + if ($this->_eventManager->hasListeners(Events::postConnect)) { + $eventArgs = new Event\ConnectionEventArgs($this); + $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); + } + + return true; + } + + /** + * setFetchMode + * + * @param integer $fetchMode + */ + public function setFetchMode($fetchMode) + { + $this->_defaultFetchMode = $fetchMode; + } + + /** + * Prepares and executes an SQL query and returns the first row of the result + * as an associative array. + * + * @param string $statement The SQL query. + * @param array $params The query parameters. + * @return array + */ + public function fetchAssoc($statement, array $params = array()) + { + return $this->executeQuery($statement, $params)->fetch(PDO::FETCH_ASSOC); + } + + /** + * Prepares and executes an SQL query and returns the first row of the result + * as a numerically indexed array. + * + * @param string $statement sql query to be executed + * @param array $params prepared statement params + * @return array + */ + public function fetchArray($statement, array $params = array()) + { + return $this->executeQuery($statement, $params)->fetch(PDO::FETCH_NUM); + } + + /** + * Prepares and executes an SQL query and returns the value of a single column + * of the first row of the result. + * + * @param string $statement sql query to be executed + * @param array $params prepared statement params + * @param int $colnum 0-indexed column number to retrieve + * @return mixed + */ + public function fetchColumn($statement, array $params = array(), $colnum = 0) + { + return $this->executeQuery($statement, $params)->fetchColumn($colnum); + } + + /** + * Whether an actual connection to the database is established. + * + * @return boolean + */ + public function isConnected() + { + return $this->_isConnected; + } + + /** + * Checks whether a transaction is currently active. + * + * @return boolean TRUE if a transaction is currently active, FALSE otherwise. + */ + public function isTransactionActive() + { + return $this->_transactionNestingLevel > 0; + } + + /** + * Executes an SQL DELETE statement on a table. + * + * @param string $tableName The name of the table on which to delete. + * @param array $identifier The deletion criteria. An associative array containing column-value pairs. + * @return integer The number of affected rows. + */ + public function delete($tableName, array $identifier) + { + $this->connect(); + + $criteria = array(); + + foreach (array_keys($identifier) as $columnName) { + $criteria[] = $columnName . ' = ?'; + } + + $query = 'DELETE FROM ' . $tableName . ' WHERE ' . implode(' AND ', $criteria); + + return $this->executeUpdate($query, array_values($identifier)); + } + + /** + * Closes the connection. + * + * @return void + */ + public function close() + { + unset($this->_conn); + + $this->_isConnected = false; + } + + /** + * Sets the transaction isolation level. + * + * @param integer $level The level to set. + * @return integer + */ + public function setTransactionIsolation($level) + { + $this->_transactionIsolationLevel = $level; + + return $this->executeUpdate($this->_platform->getSetTransactionIsolationSQL($level)); + } + + /** + * Gets the currently active transaction isolation level. + * + * @return integer The current transaction isolation level. + */ + public function getTransactionIsolation() + { + return $this->_transactionIsolationLevel; + } + + /** + * Executes an SQL UPDATE statement on a table. + * + * @param string $tableName The name of the table to update. + * @param array $data + * @param array $identifier The update criteria. An associative array containing column-value pairs. + * @param array $types Types of the merged $data and $identifier arrays in that order. + * @return integer The number of affected rows. + */ + public function update($tableName, array $data, array $identifier, array $types = array()) + { + $this->connect(); + $set = array(); + foreach ($data as $columnName => $value) { + $set[] = $columnName . ' = ?'; + } + + $params = array_merge(array_values($data), array_values($identifier)); + + $sql = 'UPDATE ' . $tableName . ' SET ' . implode(', ', $set) + . ' WHERE ' . implode(' = ? AND ', array_keys($identifier)) + . ' = ?'; + + return $this->executeUpdate($sql, $params, $types); + } + + /** + * Inserts a table row with specified data. + * + * @param string $tableName The name of the table to insert data into. + * @param array $data An associative array containing column-value pairs. + * @param array $types Types of the inserted data. + * @return integer The number of affected rows. + */ + public function insert($tableName, array $data, array $types = array()) + { + $this->connect(); + + // column names are specified as array keys + $cols = array(); + $placeholders = array(); + + foreach ($data as $columnName => $value) { + $cols[] = $columnName; + $placeholders[] = '?'; + } + + $query = 'INSERT INTO ' . $tableName + . ' (' . implode(', ', $cols) . ')' + . ' VALUES (' . implode(', ', $placeholders) . ')'; + + return $this->executeUpdate($query, array_values($data), $types); + } + + /** + * Quote a string so it can be safely used as a table or column name, even if + * it is a reserved name. + * + * Delimiting style depends on the underlying database platform that is being used. + * + * NOTE: Just because you CAN use quoted identifiers does not mean + * you SHOULD use them. In general, they end up causing way more + * problems than they solve. + * + * @param string $str The name to be quoted. + * @return string The quoted name. + */ + public function quoteIdentifier($str) + { + return $this->_platform->quoteIdentifier($str); + } + + /** + * Quotes a given input parameter. + * + * @param mixed $input Parameter to be quoted. + * @param string $type Type of the parameter. + * @return string The quoted parameter. + */ + public function quote($input, $type = null) + { + $this->connect(); + + list($value, $bindingType) = $this->getBindingInfo($input, $type); + return $this->_conn->quote($value, $bindingType); + } + + /** + * Prepares and executes an SQL query and returns the result as an associative array. + * + * @param string $sql The SQL query. + * @param array $params The query parameters. + * @return array + */ + public function fetchAll($sql, array $params = array()) + { + return $this->executeQuery($sql, $params)->fetchAll(); + } + + /** + * Prepares an SQL statement. + * + * @param string $statement The SQL statement to prepare. + * @return \Doctrine\DBAL\Driver\Statement The prepared statement. + */ + public function prepare($statement) + { + $this->connect(); + + try { + $stmt = new Statement($statement, $this); + } catch (\Exception $ex) { + throw DBALException::driverExceptionDuringQuery($ex, $statement); + } + + $stmt->setFetchMode($this->_defaultFetchMode); + + return $stmt; + } + + /** + * Executes an, optionally parameterized, SQL query. + * + * If the query is parameterized, a prepared statement is used. + * If an SQLLogger is configured, the execution is logged. + * + * @param string $query The SQL query to execute. + * @param array $params The parameters to bind to the query, if any. + * @param array $types The types the previous parameters are in. + * @param QueryCacheProfile $qcp + * @return \Doctrine\DBAL\Driver\Statement The executed statement. + * @internal PERF: Directly prepares a driver statement, not a wrapper. + */ + public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null) + { + if ($qcp !== null) { + return $this->executeCacheQuery($query, $params, $types, $qcp); + } + + $this->connect(); + + $logger = $this->_config->getSQLLogger(); + if ($logger) { + $logger->startQuery($query, $params, $types); + } + + try { + if ($params) { + list($query, $params, $types) = SQLParserUtils::expandListParameters($query, $params, $types); + + $stmt = $this->_conn->prepare($query); + if ($types) { + $this->_bindTypedValues($stmt, $params, $types); + $stmt->execute(); + } else { + $stmt->execute($params); + } + } else { + $stmt = $this->_conn->query($query); + } + } catch (\Exception $ex) { + throw DBALException::driverExceptionDuringQuery($ex, $query, $this->resolveParams($params, $types)); + } + + $stmt->setFetchMode($this->_defaultFetchMode); + + if ($logger) { + $logger->stopQuery(); + } + + return $stmt; + } + + /** + * Execute a caching query and + * + * @param string $query + * @param array $params + * @param array $types + * @param QueryCacheProfile $qcp + * @return \Doctrine\DBAL\Driver\ResultStatement + */ + public function executeCacheQuery($query, $params, $types, QueryCacheProfile $qcp) + { + $resultCache = $qcp->getResultCacheDriver() ?: $this->_config->getResultCacheImpl(); + if ( ! $resultCache) { + throw CacheException::noResultDriverConfigured(); + } + + list($cacheKey, $realKey) = $qcp->generateCacheKeys($query, $params, $types); + + // fetch the row pointers entry + if ($data = $resultCache->fetch($cacheKey)) { + // is the real key part of this row pointers map or is the cache only pointing to other cache keys? + if (isset($data[$realKey])) { + $stmt = new ArrayStatement($data[$realKey]); + } else if (array_key_exists($realKey, $data)) { + $stmt = new ArrayStatement(array()); + } + } + + if (!isset($stmt)) { + $stmt = new ResultCacheStatement($this->executeQuery($query, $params, $types), $resultCache, $cacheKey, $realKey, $qcp->getLifetime()); + } + + $stmt->setFetchMode($this->_defaultFetchMode); + + return $stmt; + } + + /** + * Executes an, optionally parameterized, SQL query and returns the result, + * applying a given projection/transformation function on each row of the result. + * + * @param string $query The SQL query to execute. + * @param array $params The parameters, if any. + * @param Closure $mapper The transformation function that is applied on each row. + * The function receives a single paramater, an array, that + * represents a row of the result set. + * @return mixed The projected result of the query. + */ + public function project($query, array $params, Closure $function) + { + $result = array(); + $stmt = $this->executeQuery($query, $params ?: array()); + + while ($row = $stmt->fetch()) { + $result[] = $function($row); + } + + $stmt->closeCursor(); + + return $result; + } + + /** + * Executes an SQL statement, returning a result set as a Statement object. + * + * @param string $statement + * @param integer $fetchType + * @return \Doctrine\DBAL\Driver\Statement + */ + public function query() + { + $this->connect(); + + $args = func_get_args(); + + $logger = $this->_config->getSQLLogger(); + if ($logger) { + $logger->startQuery($args[0]); + } + + try { + $statement = call_user_func_array(array($this->_conn, 'query'), $args); + } catch (\Exception $ex) { + throw DBALException::driverExceptionDuringQuery($ex, func_get_arg(0)); + } + + $statement->setFetchMode($this->_defaultFetchMode); + + if ($logger) { + $logger->stopQuery(); + } + + return $statement; + } + + /** + * Executes an SQL INSERT/UPDATE/DELETE query with the given parameters + * and returns the number of affected rows. + * + * This method supports PDO binding types as well as DBAL mapping types. + * + * @param string $query The SQL query. + * @param array $params The query parameters. + * @param array $types The parameter types. + * @return integer The number of affected rows. + * @internal PERF: Directly prepares a driver statement, not a wrapper. + */ + public function executeUpdate($query, array $params = array(), array $types = array()) + { + $this->connect(); + + $logger = $this->_config->getSQLLogger(); + if ($logger) { + $logger->startQuery($query, $params, $types); + } + + try { + if ($params) { + list($query, $params, $types) = SQLParserUtils::expandListParameters($query, $params, $types); + + $stmt = $this->_conn->prepare($query); + if ($types) { + $this->_bindTypedValues($stmt, $params, $types); + $stmt->execute(); + } else { + $stmt->execute($params); + } + $result = $stmt->rowCount(); + } else { + $result = $this->_conn->exec($query); + } + } catch (\Exception $ex) { + throw DBALException::driverExceptionDuringQuery($ex, $query, $this->resolveParams($params, $types)); + } + + if ($logger) { + $logger->stopQuery(); + } + + return $result; + } + + /** + * Execute an SQL statement and return the number of affected rows. + * + * @param string $statement + * @return integer The number of affected rows. + */ + public function exec($statement) + { + $this->connect(); + + $logger = $this->_config->getSQLLogger(); + if ($logger) { + $logger->startQuery($statement); + } + + try { + $result = $this->_conn->exec($statement); + } catch (\Exception $ex) { + throw DBALException::driverExceptionDuringQuery($ex, $statement); + } + + if ($logger) { + $logger->stopQuery(); + } + + return $result; + } + + /** + * Returns the current transaction nesting level. + * + * @return integer The nesting level. A value of 0 means there's no active transaction. + */ + public function getTransactionNestingLevel() + { + return $this->_transactionNestingLevel; + } + + /** + * Fetch the SQLSTATE associated with the last database operation. + * + * @return integer The last error code. + */ + public function errorCode() + { + $this->connect(); + return $this->_conn->errorCode(); + } + + /** + * Fetch extended error information associated with the last database operation. + * + * @return array The last error information. + */ + public function errorInfo() + { + $this->connect(); + return $this->_conn->errorInfo(); + } + + /** + * Returns the ID of the last inserted row, or the last value from a sequence object, + * depending on the underlying driver. + * + * Note: This method may not return a meaningful or consistent result across different drivers, + * because the underlying database may not even support the notion of AUTO_INCREMENT/IDENTITY + * columns or sequences. + * + * @param string $seqName Name of the sequence object from which the ID should be returned. + * @return string A string representation of the last inserted ID. + */ + public function lastInsertId($seqName = null) + { + $this->connect(); + return $this->_conn->lastInsertId($seqName); + } + + /** + * Executes a function in a transaction. + * + * The function gets passed this Connection instance as an (optional) parameter. + * + * If an exception occurs during execution of the function or transaction commit, + * the transaction is rolled back and the exception re-thrown. + * + * @param Closure $func The function to execute transactionally. + */ + public function transactional(Closure $func) + { + $this->beginTransaction(); + try { + $func($this); + $this->commit(); + } catch (Exception $e) { + $this->rollback(); + throw $e; + } + } + + /** + * Set if nested transactions should use savepoints + * + * @param boolean $nestTransactionsWithSavepoints + * @return void + */ + public function setNestTransactionsWithSavepoints($nestTransactionsWithSavepoints) + { + if ($this->_transactionNestingLevel > 0) { + throw ConnectionException::mayNotAlterNestedTransactionWithSavepointsInTransaction(); + } + + if ( ! $this->_platform->supportsSavepoints()) { + throw ConnectionException::savepointsNotSupported(); + } + + $this->_nestTransactionsWithSavepoints = $nestTransactionsWithSavepoints; + } + + /** + * Get if nested transactions should use savepoints + * + * @return boolean + */ + public function getNestTransactionsWithSavepoints() + { + return $this->_nestTransactionsWithSavepoints; + } + + /** + * Returns the savepoint name to use for nested transactions are false if they are not supported + * "savepointFormat" parameter is not set + * + * @return mixed a string with the savepoint name or false + */ + protected function _getNestedTransactionSavePointName() + { + return 'DOCTRINE2_SAVEPOINT_'.$this->_transactionNestingLevel; + } + + /** + * Starts a transaction by suspending auto-commit mode. + * + * @return void + */ + public function beginTransaction() + { + $this->connect(); + + ++$this->_transactionNestingLevel; + + $logger = $this->_config->getSQLLogger(); + + if ($this->_transactionNestingLevel == 1) { + if ($logger) { + $logger->startQuery('"START TRANSACTION"'); + } + $this->_conn->beginTransaction(); + if ($logger) { + $logger->stopQuery(); + } + } else if ($this->_nestTransactionsWithSavepoints) { + if ($logger) { + $logger->startQuery('"SAVEPOINT"'); + } + $this->createSavepoint($this->_getNestedTransactionSavePointName()); + if ($logger) { + $logger->stopQuery(); + } + } + } + + /** + * Commits the current transaction. + * + * @return void + * @throws ConnectionException If the commit failed due to no active transaction or + * because the transaction was marked for rollback only. + */ + public function commit() + { + if ($this->_transactionNestingLevel == 0) { + throw ConnectionException::noActiveTransaction(); + } + if ($this->_isRollbackOnly) { + throw ConnectionException::commitFailedRollbackOnly(); + } + + $this->connect(); + + $logger = $this->_config->getSQLLogger(); + + if ($this->_transactionNestingLevel == 1) { + if ($logger) { + $logger->startQuery('"COMMIT"'); + } + $this->_conn->commit(); + if ($logger) { + $logger->stopQuery(); + } + } else if ($this->_nestTransactionsWithSavepoints) { + if ($logger) { + $logger->startQuery('"RELEASE SAVEPOINT"'); + } + $this->releaseSavepoint($this->_getNestedTransactionSavePointName()); + if ($logger) { + $logger->stopQuery(); + } + } + + --$this->_transactionNestingLevel; + } + + /** + * Cancel any database changes done during the current transaction. + * + * this method can be listened with onPreTransactionRollback and onTransactionRollback + * eventlistener methods + * + * @throws ConnectionException If the rollback operation failed. + */ + public function rollBack() + { + if ($this->_transactionNestingLevel == 0) { + throw ConnectionException::noActiveTransaction(); + } + + $this->connect(); + + $logger = $this->_config->getSQLLogger(); + + if ($this->_transactionNestingLevel == 1) { + if ($logger) { + $logger->startQuery('"ROLLBACK"'); + } + $this->_transactionNestingLevel = 0; + $this->_conn->rollback(); + $this->_isRollbackOnly = false; + if ($logger) { + $logger->stopQuery(); + } + } else if ($this->_nestTransactionsWithSavepoints) { + if ($logger) { + $logger->startQuery('"ROLLBACK TO SAVEPOINT"'); + } + $this->rollbackSavepoint($this->_getNestedTransactionSavePointName()); + --$this->_transactionNestingLevel; + if ($logger) { + $logger->stopQuery(); + } + } else { + $this->_isRollbackOnly = true; + --$this->_transactionNestingLevel; + } + } + + /** + * createSavepoint + * creates a new savepoint + * + * @param string $savepoint name of a savepoint to set + * @return void + */ + public function createSavepoint($savepoint) + { + if ( ! $this->_platform->supportsSavepoints()) { + throw ConnectionException::savepointsNotSupported(); + } + + $this->_conn->exec($this->_platform->createSavePoint($savepoint)); + } + + /** + * releaseSavePoint + * releases given savepoint + * + * @param string $savepoint name of a savepoint to release + * @return void + */ + public function releaseSavepoint($savepoint) + { + if ( ! $this->_platform->supportsSavepoints()) { + throw ConnectionException::savepointsNotSupported(); + } + + if ($this->_platform->supportsReleaseSavepoints()) { + $this->_conn->exec($this->_platform->releaseSavePoint($savepoint)); + } + } + + /** + * rollbackSavePoint + * releases given savepoint + * + * @param string $savepoint name of a savepoint to rollback to + * @return void + */ + public function rollbackSavepoint($savepoint) + { + if ( ! $this->_platform->supportsSavepoints()) { + throw ConnectionException::savepointsNotSupported(); + } + + $this->_conn->exec($this->_platform->rollbackSavePoint($savepoint)); + } + + /** + * Gets the wrapped driver connection. + * + * @return \Doctrine\DBAL\Driver\Connection + */ + public function getWrappedConnection() + { + $this->connect(); + + return $this->_conn; + } + + /** + * Gets the SchemaManager that can be used to inspect or change the + * database schema through the connection. + * + * @return \Doctrine\DBAL\Schema\AbstractSchemaManager + */ + public function getSchemaManager() + { + if ( ! $this->_schemaManager) { + $this->_schemaManager = $this->_driver->getSchemaManager($this); + } + + return $this->_schemaManager; + } + + /** + * Marks the current transaction so that the only possible + * outcome for the transaction to be rolled back. + * + * @throws ConnectionException If no transaction is active. + */ + public function setRollbackOnly() + { + if ($this->_transactionNestingLevel == 0) { + throw ConnectionException::noActiveTransaction(); + } + $this->_isRollbackOnly = true; + } + + /** + * Check whether the current transaction is marked for rollback only. + * + * @return boolean + * @throws ConnectionException If no transaction is active. + */ + public function isRollbackOnly() + { + if ($this->_transactionNestingLevel == 0) { + throw ConnectionException::noActiveTransaction(); + } + return $this->_isRollbackOnly; + } + + /** + * Converts a given value to its database representation according to the conversion + * rules of a specific DBAL mapping type. + * + * @param mixed $value The value to convert. + * @param string $type The name of the DBAL mapping type. + * @return mixed The converted value. + */ + public function convertToDatabaseValue($value, $type) + { + return Type::getType($type)->convertToDatabaseValue($value, $this->_platform); + } + + /** + * Converts a given value to its PHP representation according to the conversion + * rules of a specific DBAL mapping type. + * + * @param mixed $value The value to convert. + * @param string $type The name of the DBAL mapping type. + * @return mixed The converted type. + */ + public function convertToPHPValue($value, $type) + { + return Type::getType($type)->convertToPHPValue($value, $this->_platform); + } + + /** + * Binds a set of parameters, some or all of which are typed with a PDO binding type + * or DBAL mapping type, to a given statement. + * + * @param string $stmt The statement to bind the values to. + * @param array $params The map/list of named/positional parameters. + * @param array $types The parameter types (PDO binding types or DBAL mapping types). + * @internal Duck-typing used on the $stmt parameter to support driver statements as well as + * raw PDOStatement instances. + */ + private function _bindTypedValues($stmt, array $params, array $types) + { + // Check whether parameters are positional or named. Mixing is not allowed, just like in PDO. + if (is_int(key($params))) { + // Positional parameters + $typeOffset = array_key_exists(0, $types) ? -1 : 0; + $bindIndex = 1; + foreach ($params as $value) { + $typeIndex = $bindIndex + $typeOffset; + if (isset($types[$typeIndex])) { + $type = $types[$typeIndex]; + list($value, $bindingType) = $this->getBindingInfo($value, $type); + $stmt->bindValue($bindIndex, $value, $bindingType); + } else { + $stmt->bindValue($bindIndex, $value); + } + ++$bindIndex; + } + } else { + // Named parameters + foreach ($params as $name => $value) { + if (isset($types[$name])) { + $type = $types[$name]; + list($value, $bindingType) = $this->getBindingInfo($value, $type); + $stmt->bindValue($name, $value, $bindingType); + } else { + $stmt->bindValue($name, $value); + } + } + } + } + + /** + * Gets the binding type of a given type. The given type can be a PDO or DBAL mapping type. + * + * @param mixed $value The value to bind + * @param mixed $type The type to bind (PDO or DBAL) + * @return array [0] => the (escaped) value, [1] => the binding type + */ + private function getBindingInfo($value, $type) + { + if (is_string($type)) { + $type = Type::getType($type); + } + if ($type instanceof Type) { + $value = $type->convertToDatabaseValue($value, $this->_platform); + $bindingType = $type->getBindingType(); + } else { + $bindingType = $type; // PDO::PARAM_* constants + } + return array($value, $bindingType); + } + + /** + * Resolves the parameters to a format which can be displayed. + * + * @internal This is a purely internal method. If you rely on this method, you are advised to + * copy/paste the code as this method may change, or be removed without prior notice. + * + * @param array $params + * @param array $types + * + * @return array + */ + public function resolveParams(array $params, array $types) + { + $resolvedParams = array(); + + // Check whether parameters are positional or named. Mixing is not allowed, just like in PDO. + if (is_int(key($params))) { + // Positional parameters + $typeOffset = array_key_exists(0, $types) ? -1 : 0; + $bindIndex = 1; + foreach ($params as $value) { + $typeIndex = $bindIndex + $typeOffset; + if (isset($types[$typeIndex])) { + $type = $types[$typeIndex]; + list($value,) = $this->getBindingInfo($value, $type); + $resolvedParams[$bindIndex] = $value; + } else { + $resolvedParams[$bindIndex] = $value; + } + ++$bindIndex; + } + } else { + // Named parameters + foreach ($params as $name => $value) { + if (isset($types[$name])) { + $type = $types[$name]; + list($value,) = $this->getBindingInfo($value, $type); + $resolvedParams[$name] = $value; + } else { + $resolvedParams[$name] = $value; + } + } + } + + return $resolvedParams; + } + + /** + * Create a new instance of a SQL query builder. + * + * @return \Doctrine\DBAL\Query\QueryBuilder + */ + public function createQueryBuilder() + { + return new Query\QueryBuilder($this); + } +} diff --git a/src/core/libs/Doctrine/DBAL/ConnectionException.php b/src/core/libs/Doctrine/DBAL/ConnectionException.php new file mode 100644 index 0000000..4b41ef2 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/ConnectionException.php @@ -0,0 +1,54 @@ +<?php +/* + * $Id: Exception.php 4628 2008-07-04 16:32:19Z romanb $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL; + +/** + * Doctrine\DBAL\ConnectionException + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision: 4628 $ + * @author Jonathan H. Wage <jonwage@gmail.com + */ +class ConnectionException extends DBALException +{ + public static function commitFailedRollbackOnly() + { + return new self("Transaction commit failed because the transaction has been marked for rollback only."); + } + + public static function noActiveTransaction() + { + return new self("There is no active transaction."); + } + + public static function savepointsNotSupported() + { + return new self("Savepoints are not supported by this driver."); + } + + public static function mayNotAlterNestedTransactionWithSavepointsInTransaction() + { + return new self("May not alter the nested transaction with savepoints behavior while a transaction is open."); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Connections/MasterSlaveConnection.php b/src/core/libs/Doctrine/DBAL/Connections/MasterSlaveConnection.php new file mode 100644 index 0000000..5b145e7 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Connections/MasterSlaveConnection.php @@ -0,0 +1,353 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Connections; + + +use Doctrine\DBAL\Connection, + Doctrine\DBAL\Driver, + Doctrine\DBAL\Configuration, + Doctrine\Common\EventManager, + Doctrine\DBAL\Event\ConnectionEventArgs, + Doctrine\DBAL\Events; + +/** + * Master-Slave Connection + * + * Connection can be used with master-slave setups. + * + * Important for the understanding of this connection should be how and when + * it picks the slave or master. + * + * 1. Slave if master was never picked before and ONLY if 'getWrappedConnection' + * or 'executeQuery' is used. + * 2. Master picked when 'exec', 'executeUpdate', 'insert', 'delete', 'update', 'createSavepoint', + * 'releaseSavepoint', 'beginTransaction', 'rollback', 'commit', 'query' or + * 'prepare' is called. + * 3. If master was picked once during the lifetime of the connection it will always get picked afterwards. + * 4. One slave connection is randomly picked ONCE during a request. + * + * ATTENTION: You can write to the slave with this connection if you execute a write query without + * opening up a transaction. For example: + * + * $conn = DriverManager::getConnection(...); + * $conn->executeQuery("DELETE FROM table"); + * + * Be aware that Connection#executeQuery is a method specifically for READ + * operations only. + * + * This connection is limited to slave operations using the + * Connection#executeQuery operation only, because it wouldn't be compatible + * with the ORM or SchemaManager code otherwise. Both use all the other + * operations in a context where writes could happen to a slave, which makes + * this restricted approach necessary. + * + * You can manually connect to the master at any time by calling: + * + * $conn->connect('master'); + * + * Instantiation through the DriverManager looks like: + * + * @example + * + * $conn = DriverManager::getConnection(array( + * 'wrapperClass' => 'Doctrine\DBAL\Connections\MasterSlaveConnection', + * 'driver' => 'pdo_mysql', + * 'master' => array('user' => '', 'password' => '', 'host' => '', 'dbname' => ''), + * 'slaves' => array( + * array('user' => 'slave1', 'password', 'host' => '', 'dbname' => ''), + * array('user' => 'slave2', 'password', 'host' => '', 'dbname' => ''), + * ) + * )); + * + * You can also pass 'driverOptions' and any other documented option to each of this drivers to pass additional information. + * + * @author Lars Strojny <lstrojny@php.net> + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class MasterSlaveConnection extends Connection +{ + /** + * Master and slave connection (one of the randomly picked slaves) + * + * @var Doctrine\DBAL\Driver\Connection[] + */ + protected $connections = array('master' => null, 'slave' => null); + + /** + * You can keep the slave connection and then switch back to it + * during the request if you know what you are doing. + * + * @var bool + */ + protected $keepSlave = false; + + /** + * Create Master Slave Connection + * + * @param array $params + * @param Driver $driver + * @param Configuration $config + * @param EventManager $eventManager + */ + public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null) + { + if ( !isset($params['slaves']) || !isset($params['master']) ) { + throw new \InvalidArgumentException('master or slaves configuration missing'); + } + if ( count($params['slaves']) == 0 ) { + throw new \InvalidArgumentException('You have to configure at least one slaves.'); + } + + $params['master']['driver'] = $params['driver']; + foreach ($params['slaves'] as $slaveKey => $slave) { + $params['slaves'][$slaveKey]['driver'] = $params['driver']; + } + + $this->keepSlave = isset($params['keepSlave']) ? (bool)$params['keepSlave'] : false; + + parent::__construct($params, $driver, $config, $eventManager); + } + + /** + * Check if the connection is currently towards the master or not. + * + * @return bool + */ + public function isConnectedToMaster() + { + return $this->_conn !== null && $this->_conn === $this->connections['master']; + } + + /** + * {@inheritDoc} + */ + public function connect($connectionName = null) + { + $requestedConnectionChange = ($connectionName !== null); + $connectionName = $connectionName ?: 'slave'; + + if ( $connectionName !== 'slave' && $connectionName !== 'master' ) { + throw new \InvalidArgumentException("Invalid option to connect(), only master or slave allowed."); + } + + // If we have a connection open, and this is not an explicit connection + // change request, then abort right here, because we are already done. + // This prevents writes to the slave in case of "keepSlave" option enabled. + if ($this->_conn && !$requestedConnectionChange) { + return false; + } + + $forceMasterAsSlave = false; + + if ($this->getTransactionNestingLevel() > 0) { + $connectionName = 'master'; + $forceMasterAsSlave = true; + } + + if ($this->connections[$connectionName]) { + if ($forceMasterAsSlave) { + $this->connections['slave'] = $this->_conn = $this->connections['master']; + } else { + $this->_conn = $this->connections[$connectionName]; + } + return false; + } + + if ($connectionName === 'master') { + // Set slave connection to master to avoid invalid reads + if ($this->connections['slave'] && ! $this->keepSlave) { + unset($this->connections['slave']); + } + + $this->connections['master'] = $this->_conn = $this->connectTo($connectionName); + + if ( ! $this->keepSlave) { + $this->connections['slave'] = $this->connections['master']; + } + } else { + $this->connections['slave'] = $this->_conn = $this->connectTo($connectionName); + } + + if ($this->_eventManager->hasListeners(Events::postConnect)) { + $eventArgs = new ConnectionEventArgs($this); + $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); + } + + return true; + } + + /** + * Connect to a specific connection + * + * @param string $connectionName + * @return Driver + */ + protected function connectTo($connectionName) + { + $params = $this->getParams(); + + $driverOptions = isset($params['driverOptions']) ? $params['driverOptions'] : array(); + + $connectionParams = $this->chooseConnectionConfiguration($connectionName, $params); + + $user = isset($connectionParams['user']) ? $connectionParams['user'] : null; + $password = isset($connectionParams['password']) ? $connectionParams['password'] : null; + + return $this->_driver->connect($connectionParams, $user, $password, $driverOptions); + } + + protected function chooseConnectionConfiguration($connectionName, $params) + { + if ($connectionName === 'master') { + return $params['master']; + } + + return $params['slaves'][array_rand($params['slaves'])]; + } + + /** + * {@inheritDoc} + */ + public function executeUpdate($query, array $params = array(), array $types = array()) + { + $this->connect('master'); + return parent::executeUpdate($query, $params, $types); + } + + /** + * {@inheritDoc} + */ + public function beginTransaction() + { + $this->connect('master'); + return parent::beginTransaction(); + } + + /** + * {@inheritDoc} + */ + public function commit() + { + $this->connect('master'); + return parent::commit(); + } + + /** + * {@inheritDoc} + */ + public function rollBack() + { + $this->connect('master'); + return parent::rollBack(); + } + + /** + * {@inheritDoc} + */ + public function delete($tableName, array $identifier) + { + $this->connect('master'); + return parent::delete($tableName, $identifier); + } + + /** + * {@inheritDoc} + */ + public function update($tableName, array $data, array $identifier, array $types = array()) + { + $this->connect('master'); + return parent::update($tableName, $data, $identifier, $types); + } + + /** + * {@inheritDoc} + */ + public function insert($tableName, array $data, array $types = array()) + { + $this->connect('master'); + return parent::insert($tableName, $data, $types); + } + + /** + * {@inheritDoc} + */ + public function exec($statement) + { + $this->connect('master'); + return parent::exec($statement); + } + + /** + * {@inheritDoc} + */ + public function createSavepoint($savepoint) + { + $this->connect('master'); + + return parent::createSavepoint($savepoint); + } + + /** + * {@inheritDoc} + */ + public function releaseSavepoint($savepoint) + { + $this->connect('master'); + + return parent::releaseSavepoint($savepoint); + } + + /** + * {@inheritDoc} + */ + public function rollbackSavepoint($savepoint) + { + $this->connect('master'); + + return parent::rollbackSavepoint($savepoint); + } + + public function query() + { + $this->connect('master'); + + $args = func_get_args(); + + $logger = $this->getConfiguration()->getSQLLogger(); + if ($logger) { + $logger->startQuery($args[0]); + } + + $statement = call_user_func_array(array($this->_conn, 'query'), $args); + + if ($logger) { + $logger->stopQuery(); + } + + return $statement; + } + + public function prepare($statement) + { + $this->connect('master'); + + return parent::prepare($statement); + } +} diff --git a/src/core/libs/Doctrine/DBAL/DBALException.php b/src/core/libs/Doctrine/DBAL/DBALException.php new file mode 100644 index 0000000..c8e430b --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/DBALException.php @@ -0,0 +1,106 @@ +<?php + +namespace Doctrine\DBAL; + +class DBALException extends \Exception +{ + public static function notSupported($method) + { + return new self("Operation '$method' is not supported by platform."); + } + + public static function invalidPlatformSpecified() + { + return new self( + "Invalid 'platform' option specified, need to give an instance of ". + "\Doctrine\DBAL\Platforms\AbstractPlatform."); + } + + public static function invalidPdoInstance() + { + return new self( + "The 'pdo' option was used in DriverManager::getConnection() but no ". + "instance of PDO was given." + ); + } + + public static function driverRequired() + { + return new self("The options 'driver' or 'driverClass' are mandatory if no PDO ". + "instance is given to DriverManager::getConnection()."); + } + + public static function unknownDriver($unknownDriverName, array $knownDrivers) + { + return new self("The given 'driver' ".$unknownDriverName." is unknown, ". + "Doctrine currently supports only the following drivers: ".implode(", ", $knownDrivers)); + } + + public static function driverExceptionDuringQuery(\Exception $driverEx, $sql, array $params = array()) + { + $msg = "An exception occurred while executing '".$sql."'"; + if ($params) { + $msg .= " with params ".json_encode($params); + } + $msg .= ":\n\n".$driverEx->getMessage(); + + return new self($msg, 0, $driverEx); + } + + public static function invalidWrapperClass($wrapperClass) + { + return new self("The given 'wrapperClass' ".$wrapperClass." has to be a ". + "subtype of \Doctrine\DBAL\Connection."); + } + + public static function invalidDriverClass($driverClass) + { + return new self("The given 'driverClass' ".$driverClass." has to implement the ". + "\Doctrine\DBAL\Driver interface."); + } + + /** + * @param string $tableName + * @return DBALException + */ + public static function invalidTableName($tableName) + { + return new self("Invalid table name specified: ".$tableName); + } + + /** + * @param string $tableName + * @return DBALException + */ + public static function noColumnsSpecifiedForTable($tableName) + { + return new self("No columns specified for table ".$tableName); + } + + public static function limitOffsetInvalid() + { + return new self("Invalid Offset in Limit Query, it has to be larger or equal to 0."); + } + + public static function typeExists($name) + { + return new self('Type '.$name.' already exists.'); + } + + public static function unknownColumnType($name) + { + return new self('Unknown column type "'.$name.'" requested. Any Doctrine type that you use has ' . + 'to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the ' . + 'known types with \Doctrine\DBAL\Types\Type::getTypeMap(). If this error occurs during database ' . + 'introspection then you might have forgot to register all database types for a Doctrine Type. Use ' . + 'AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement ' . + 'Type#getMappedDatabaseTypes(). If the type name is empty you might ' . + 'have a problem with the cache or forgot some mapping information.' + ); + } + + public static function typeNotFound($name) + { + return new self('Type to be overwritten '.$name.' does not exist.'); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver.php b/src/core/libs/Doctrine/DBAL/Driver.php new file mode 100644 index 0000000..8364990 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver.php @@ -0,0 +1,72 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL; + +/** + * Driver interface. + * Interface that all DBAL drivers must implement. + * + * @since 2.0 + */ +interface Driver +{ + /** + * Attempts to create a connection with the database. + * + * @param array $params All connection parameters passed by the user. + * @param string $username The username to use when connecting. + * @param string $password The password to use when connecting. + * @param array $driverOptions The driver options to use when connecting. + * @return \Doctrine\DBAL\Driver\Connection The database connection. + */ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()); + + /** + * Gets the DatabasePlatform instance that provides all the metadata about + * the platform this driver connects to. + * + * @return \Doctrine\DBAL\Platforms\AbstractPlatform The database platform. + */ + public function getDatabasePlatform(); + + /** + * Gets the SchemaManager that can be used to inspect and change the underlying + * database schema of the platform this driver connects to. + * + * @param \Doctrine\DBAL\Connection $conn + * @return \Doctrine\DBAL\Schema\AbstractSchemaManager + */ + public function getSchemaManager(Connection $conn); + + /** + * Gets the name of the driver. + * + * @return string The name of the driver. + */ + public function getName(); + + /** + * Get the name of the database connected to for this driver. + * + * @param \Doctrine\DBAL\Connection $conn + * @return string $database + */ + public function getDatabase(Connection $conn); +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/Connection.php b/src/core/libs/Doctrine/DBAL/Driver/Connection.php new file mode 100644 index 0000000..a618487 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/Connection.php @@ -0,0 +1,42 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver; + +/** + * Connection interface. + * Driver connections must implement this interface. + * + * This resembles (a subset of) the PDO interface. + * + * @since 2.0 + */ +interface Connection +{ + function prepare($prepareString); + function query(); + function quote($input, $type=\PDO::PARAM_STR); + function exec($statement); + function lastInsertId($name = null); + function beginTransaction(); + function commit(); + function rollBack(); + function errorCode(); + function errorInfo(); +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php b/src/core/libs/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php new file mode 100644 index 0000000..2b46c99 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/DrizzlePDOMySql/Connection.php @@ -0,0 +1,41 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\DrizzlePDOMySql; + +/** + * @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com> + */ +class Connection extends \Doctrine\DBAL\Driver\PDOConnection +{ + /** + * {@inheritdoc} + */ + public function quote($value, $type=\PDO::PARAM_STR) + { + if (\PDO::PARAM_BOOL === $type) { + if ($value) { + return 'true'; + } else { + return 'false'; + } + } + return parent::quote($value, $type); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php b/src/core/libs/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php new file mode 100644 index 0000000..8030bbc --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/DrizzlePDOMySql/Driver.php @@ -0,0 +1,99 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\DrizzlePDOMySql; + +/** + * Drizzle driver using PDO MySql. + * + * @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com> + */ +class Driver implements \Doctrine\DBAL\Driver +{ + /** + * {@inheritdoc} + */ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + $conn = new Connection( + $this->_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + return $conn; + } + + /** + * Constructs the Drizzle MySql PDO DSN. + * + * @return string The DSN. + */ + private function _constructPdoDsn(array $params) + { + $dsn = 'mysql:'; + if (isset($params['host']) && $params['host'] != '') { + $dsn .= 'host=' . $params['host'] . ';'; + } + if (isset($params['port'])) { + $dsn .= 'port=' . $params['port'] . ';'; + } + if (isset($params['dbname'])) { + $dsn .= 'dbname=' . $params['dbname'] . ';'; + } + if (isset($params['unix_socket'])) { + $dsn .= 'unix_socket=' . $params['unix_socket'] . ';'; + } + + return $dsn; + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\DrizzlePlatform(); + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new \Doctrine\DBAL\Schema\DrizzleSchemaManager($conn); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'drizzle_pdo_mysql'; + } + + /** + * {@inheritdoc} + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + return $params['dbname']; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php b/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php new file mode 100644 index 0000000..c1c2212 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Connection.php @@ -0,0 +1,115 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Driver\IBMDB2; + +class DB2Connection implements \Doctrine\DBAL\Driver\Connection +{ + private $_conn = null; + + public function __construct(array $params, $username, $password, $driverOptions = array()) + { + $isPersistant = (isset($params['persistent']) && $params['persistent'] == true); + + if ($isPersistant) { + $this->_conn = db2_pconnect($params['dbname'], $username, $password, $driverOptions); + } else { + $this->_conn = db2_connect($params['dbname'], $username, $password, $driverOptions); + } + if ( ! $this->_conn) { + throw new DB2Exception(db2_conn_errormsg()); + } + } + + public function prepare($sql) + { + $stmt = @db2_prepare($this->_conn, $sql); + if ( ! $stmt) { + throw new DB2Exception(db2_stmt_errormsg()); + } + return new DB2Statement($stmt); + } + + public function query() + { + $args = func_get_args(); + $sql = $args[0]; + $stmt = $this->prepare($sql); + $stmt->execute(); + return $stmt; + } + + public function quote($input, $type=\PDO::PARAM_STR) + { + $input = db2_escape_string($input); + if ($type == \PDO::PARAM_INT ) { + return $input; + } else { + return "'".$input."'"; + } + } + + public function exec($statement) + { + $stmt = $this->prepare($statement); + $stmt->execute(); + return $stmt->rowCount(); + } + + public function lastInsertId($name = null) + { + return db2_last_insert_id($this->_conn); + } + + public function beginTransaction() + { + db2_autocommit($this->_conn, DB2_AUTOCOMMIT_OFF); + } + + public function commit() + { + if (!db2_commit($this->_conn)) { + throw new DB2Exception(db2_conn_errormsg($this->_conn)); + } + db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON); + } + + public function rollBack() + { + if (!db2_rollback($this->_conn)) { + throw new DB2Exception(db2_conn_errormsg($this->_conn)); + } + db2_autocommit($this->_conn, DB2_AUTOCOMMIT_ON); + } + + public function errorCode() + { + return db2_conn_error($this->_conn); + } + + public function errorInfo() + { + return array( + 0 => db2_conn_errormsg($this->_conn), + 1 => $this->errorCode(), + ); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php b/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php new file mode 100644 index 0000000..82c71e5 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Driver.php @@ -0,0 +1,111 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Driver\IBMDB2; + +use Doctrine\DBAL\Driver, + Doctrine\DBAL\Connection; + +/** + * IBM DB2 Driver + * + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class DB2Driver implements Driver +{ + /** + * Attempts to create a connection with the database. + * + * @param array $params All connection parameters passed by the user. + * @param string $username The username to use when connecting. + * @param string $password The password to use when connecting. + * @param array $driverOptions The driver options to use when connecting. + * @return \Doctrine\DBAL\Driver\Connection The database connection. + */ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + if ( ! isset($params['protocol'])) { + $params['protocol'] = 'TCPIP'; + } + + if ($params['host'] !== 'localhost' && $params['host'] != '127.0.0.1') { + // if the host isn't localhost, use extended connection params + $params['dbname'] = 'DRIVER={IBM DB2 ODBC DRIVER}' . + ';DATABASE=' . $params['dbname'] . + ';HOSTNAME=' . $params['host'] . + ';PROTOCOL=' . $params['protocol'] . + ';UID=' . $username . + ';PWD=' . $password .';'; + if (isset($params['port'])) { + $params['dbname'] .= 'PORT=' . $params['port']; + } + + $username = null; + $password = null; + } + + return new DB2Connection($params, $username, $password, $driverOptions); + } + + /** + * Gets the DatabasePlatform instance that provides all the metadata about + * the platform this driver connects to. + * + * @return \Doctrine\DBAL\Platforms\AbstractPlatform The database platform. + */ + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\DB2Platform; + } + + /** + * Gets the SchemaManager that can be used to inspect and change the underlying + * database schema of the platform this driver connects to. + * + * @param \Doctrine\DBAL\Connection $conn + * @return \Doctrine\DBAL\Schema\DB2SchemaManager + */ + public function getSchemaManager(Connection $conn) + { + return new \Doctrine\DBAL\Schema\DB2SchemaManager($conn); + } + + /** + * Gets the name of the driver. + * + * @return string The name of the driver. + */ + public function getName() + { + return 'ibm_db2'; + } + + /** + * Get the name of the database connected to for this driver. + * + * @param \Doctrine\DBAL\Connection $conn + * @return string $database + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + return $params['dbname']; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Exception.php b/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Exception.php new file mode 100644 index 0000000..3d07658 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Exception.php @@ -0,0 +1,27 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Driver\IBMDB2; + +class DB2Exception extends \Exception +{ + +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php b/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php new file mode 100644 index 0000000..9a43f9f --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/IBMDB2/DB2Statement.php @@ -0,0 +1,214 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Driver\IBMDB2; + +use \Doctrine\DBAL\Driver\Statement; + +class DB2Statement implements \IteratorAggregate, Statement +{ + private $_stmt = null; + + private $_bindParam = array(); + + private $_defaultFetchMode = \PDO::FETCH_BOTH; + + /** + * DB2_BINARY, DB2_CHAR, DB2_DOUBLE, or DB2_LONG + * @var array + */ + static private $_typeMap = array( + \PDO::PARAM_INT => DB2_LONG, + \PDO::PARAM_STR => DB2_CHAR, + ); + + public function __construct($stmt) + { + $this->_stmt = $stmt; + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = null) + { + return $this->bindParam($param, $value, $type); + } + + /** + * {@inheritdoc} + */ + public function bindParam($column, &$variable, $type = null, $length = null) + { + $this->_bindParam[$column] =& $variable; + + if ($type && isset(self::$_typeMap[$type])) { + $type = self::$_typeMap[$type]; + } else { + $type = DB2_CHAR; + } + + if (!db2_bind_param($this->_stmt, $column, "variable", DB2_PARAM_IN, $type)) { + throw new DB2Exception(db2_stmt_errormsg()); + } + return true; + } + + /** + * {@inheritdoc} + */ + public function closeCursor() + { + if ( ! $this->_stmt) { + return false; + } + + $this->_bindParam = array(); + db2_free_result($this->_stmt); + $ret = db2_free_stmt($this->_stmt); + $this->_stmt = false; + return $ret; + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + if ( ! $this->_stmt) { + return false; + } + return db2_num_fields($this->_stmt); + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + return db2_stmt_error(); + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return array( + 0 => db2_stmt_errormsg(), + 1 => db2_stmt_error(), + ); + } + + /** + * {@inheritdoc} + */ + public function execute($params = null) + { + if ( ! $this->_stmt) { + return false; + } + + /*$retval = true; + if ($params !== null) { + $retval = @db2_execute($this->_stmt, $params); + } else { + $retval = @db2_execute($this->_stmt); + }*/ + if ($params === null) { + ksort($this->_bindParam); + $params = array_values($this->_bindParam); + } + $retval = @db2_execute($this->_stmt, $params); + + if ($retval === false) { + throw new DB2Exception(db2_stmt_errormsg()); + } + return $retval; + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->_defaultFetchMode = $fetchMode; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + $data = $this->fetchAll(); + return new \ArrayIterator($data); + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null) + { + $fetchMode = $fetchMode ?: $this->_defaultFetchMode; + switch ($fetchMode) { + case \PDO::FETCH_BOTH: + return db2_fetch_both($this->_stmt); + case \PDO::FETCH_ASSOC: + return db2_fetch_assoc($this->_stmt); + case \PDO::FETCH_NUM: + return db2_fetch_array($this->_stmt); + default: + throw new DB2Exception("Given Fetch-Style " . $fetchMode . " is not supported."); + } + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null) + { + $rows = array(); + while ($row = $this->fetch($fetchMode)) { + $rows[] = $row; + } + return $rows; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(\PDO::FETCH_NUM); + if ($row && isset($row[$columnIndex])) { + return $row[$columnIndex]; + } + return false; + } + + /** + * {@inheritdoc} + */ + public function rowCount() + { + return (@db2_num_rows($this->_stmt))?:0; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/Mysqli/Driver.php b/src/core/libs/Doctrine/DBAL/Driver/Mysqli/Driver.php new file mode 100644 index 0000000..60defba --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/Mysqli/Driver.php @@ -0,0 +1,69 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\Mysqli; + +use Doctrine\DBAL\Driver as DriverInterface; + +/** + * @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com> + */ +class Driver implements DriverInterface +{ + /** + * {@inheritdoc} + */ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + return new MysqliConnection($params, $username, $password, $driverOptions); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'mysqli'; + } + + /** + * {@inheritdoc} + */ + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new \Doctrine\DBAL\Schema\MySqlSchemaManager($conn); + } + + /** + * {@inheritdoc} + */ + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\MySqlPlatform(); + } + + /** + * {@inheritdoc} + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + return $params['dbname']; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php b/src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php new file mode 100644 index 0000000..7ffa2ca --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliConnection.php @@ -0,0 +1,146 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\Mysqli; + +use Doctrine\DBAL\Driver\Connection as Connection; + +/** + * @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com> + */ +class MysqliConnection implements Connection +{ + /** + * @var \mysqli + */ + private $_conn; + + public function __construct(array $params, $username, $password, array $driverOptions = array()) + { + $port = isset($params['port']) ? $params['port'] : ini_get('mysqli.default_port'); + $socket = isset($params['unix_socket']) ? $params['unix_socket'] : ini_get('mysqli.default_socket'); + + $this->_conn = mysqli_init(); + if ( ! $this->_conn->real_connect($params['host'], $username, $password, $params['dbname'], $port, $socket)) { + throw new MysqliException($this->_conn->connect_error, $this->_conn->connect_errno); + } + + if (isset($params['charset'])) { + $this->_conn->set_charset($params['charset']); + } + } + + /** + * Retrieve mysqli native resource handle. + * + * Could be used if part of your application is not using DBAL + * + * @return \mysqli + */ + public function getWrappedResourceHandle() + { + return $this->_conn; + } + + /** + * {@inheritdoc} + */ + public function prepare($prepareString) + { + return new MysqliStatement($this->_conn, $prepareString); + } + + /** + * {@inheritdoc} + */ + public function query() + { + $args = func_get_args(); + $sql = $args[0]; + $stmt = $this->prepare($sql); + $stmt->execute(); + return $stmt; + } + + /** + * {@inheritdoc} + */ + public function quote($input, $type=\PDO::PARAM_STR) + { + return "'". $this->_conn->escape_string($input) ."'"; + } + + /** + * {@inheritdoc} + */ + public function exec($statement) + { + $this->_conn->query($statement); + return $this->_conn->affected_rows; + } + + /** + * {@inheritdoc} + */ + public function lastInsertId($name = null) + { + return $this->_conn->insert_id; + } + + /** + * {@inheritdoc} + */ + public function beginTransaction() + { + $this->_conn->query('START TRANSACTION'); + return true; + } + + /** + * {@inheritdoc} + */ + public function commit() + { + return $this->_conn->commit(); + } + + /** + * {@inheritdoc}non-PHPdoc) + */ + public function rollBack() + { + return $this->_conn->rollback(); + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + return $this->_conn->errno; + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return $this->_conn->error; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliException.php b/src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliException.php new file mode 100644 index 0000000..139ce8f --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliException.php @@ -0,0 +1,26 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Driver\Mysqli; + +/** + * @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com> + */ +class MysqliException extends \Exception +{} diff --git a/src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php b/src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php new file mode 100644 index 0000000..2eaa8fd --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/Mysqli/MysqliStatement.php @@ -0,0 +1,342 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\Mysqli; + +use Doctrine\DBAL\Driver\Statement; +use PDO; + +/** + * @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com> + */ +class MysqliStatement implements \IteratorAggregate, Statement +{ + protected static $_paramTypeMap = array( + PDO::PARAM_STR => 's', + PDO::PARAM_BOOL => 'i', + PDO::PARAM_NULL => 's', + PDO::PARAM_INT => 'i', + PDO::PARAM_LOB => 's' // TODO Support LOB bigger then max package size. + ); + + protected $_conn; + protected $_stmt; + + /** + * @var null|false|array + */ + protected $_columnNames; + + /** + * @var null|array + */ + protected $_rowBindedValues; + + /** + * @var array + */ + protected $_bindedValues; + + /** + * Contains ref values for bindValue() + * + * @var array + */ + protected $_values = array(); + + protected $_defaultFetchMode = PDO::FETCH_BOTH; + + public function __construct(\mysqli $conn, $prepareString) + { + $this->_conn = $conn; + $this->_stmt = $conn->prepare($prepareString); + if (false === $this->_stmt) { + throw new MysqliException($this->_conn->error, $this->_conn->errno); + } + + $paramCount = $this->_stmt->param_count; + if (0 < $paramCount) { + // Index 0 is types + // Need to init the string else php think we are trying to access it as a array. + $bindedValues = array(0 => str_repeat('s', $paramCount)); + $null = null; + for ($i = 1; $i < $paramCount; $i++) { + $bindedValues[] =& $null; + } + $this->_bindedValues = $bindedValues; + } + } + + /** + * {@inheritdoc} + */ + public function bindParam($column, &$variable, $type = null, $length = null) + { + if (null === $type) { + $type = 's'; + } else { + if (isset(self::$_paramTypeMap[$type])) { + $type = self::$_paramTypeMap[$type]; + } else { + throw new MysqliException("Unkown type: '{$type}'"); + } + } + + $this->_bindedValues[$column] =& $variable; + $this->_bindedValues[0][$column - 1] = $type; + return true; + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = null) + { + if (null === $type) { + $type = 's'; + } else { + if (isset(self::$_paramTypeMap[$type])) { + $type = self::$_paramTypeMap[$type]; + } else { + throw new MysqliException("Unknown type: '{$type}'"); + } + } + + $this->_values[$param] = $value; + $this->_bindedValues[$param] =& $this->_values[$param]; + $this->_bindedValues[0][$param - 1] = $type; + return true; + } + + /** + * {@inheritdoc} + */ + public function execute($params = null) + { + if (null !== $this->_bindedValues) { + if (null !== $params) { + if ( ! $this->_bindValues($params)) { + throw new MysqliException($this->_stmt->error, $this->_stmt->errno); + } + } else { + if (!call_user_func_array(array($this->_stmt, 'bind_param'), $this->_bindedValues)) { + throw new MysqliException($this->_stmt->error, $this->_stmt->errno); + } + } + } + + if ( ! $this->_stmt->execute()) { + throw new MysqliException($this->_stmt->error, $this->_stmt->errno); + } + + if (null === $this->_columnNames) { + $meta = $this->_stmt->result_metadata(); + if (false !== $meta) { + $columnNames = array(); + foreach ($meta->fetch_fields() as $col) { + $columnNames[] = $col->name; + } + $meta->free(); + + $this->_columnNames = $columnNames; + $this->_rowBindedValues = array_fill(0, count($columnNames), NULL); + + $refs = array(); + foreach ($this->_rowBindedValues as $key => &$value) { + $refs[$key] =& $value; + } + + if (!call_user_func_array(array($this->_stmt, 'bind_result'), $refs)) { + throw new MysqliException($this->_stmt->error, $this->_stmt->errno); + } + } else { + $this->_columnNames = false; + } + } + + // We have a result. + if (false !== $this->_columnNames) { + $this->_stmt->store_result(); + } + return true; + } + + /** + * Bind a array of values to bound parameters + * + * @param array $values + * @return boolean + */ + private function _bindValues($values) + { + $params = array(); + $types = str_repeat('s', count($values)); + $params[0] = $types; + + foreach ($values as &$v) { + $params[] =& $v; + } + return call_user_func_array(array($this->_stmt, 'bind_param'), $params); + } + + /** + * @return boolean|array + */ + private function _fetch() + { + $ret = $this->_stmt->fetch(); + + if (true === $ret) { + $values = array(); + foreach ($this->_rowBindedValues as $v) { + // Mysqli converts them to a scalar type it can fit in. + $values[] = null === $v ? null : (string)$v; + } + return $values; + } + return $ret; + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null) + { + $values = $this->_fetch(); + if (null === $values) { + return null; + } + + if (false === $values) { + throw new MysqliException($this->_stmt->error, $this->_stmt->errno); + } + + $fetchMode = $fetchMode ?: $this->_defaultFetchMode; + + switch ($fetchMode) { + case PDO::FETCH_NUM: + return $values; + + case PDO::FETCH_ASSOC: + return array_combine($this->_columnNames, $values); + + case PDO::FETCH_BOTH: + $ret = array_combine($this->_columnNames, $values); + $ret += $values; + return $ret; + + default: + throw new MysqliException("Unknown fetch type '{$fetchMode}'"); + } + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null) + { + $fetchMode = $fetchMode ?: $this->_defaultFetchMode; + + $rows = array(); + if (PDO::FETCH_COLUMN == $fetchMode) { + while (($row = $this->fetchColumn()) !== false) { + $rows[] = $row; + } + } else { + while (($row = $this->fetch($fetchMode)) !== null) { + $rows[] = $row; + } + } + + return $rows; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(PDO::FETCH_NUM); + if (null === $row) { + return false; + } + return $row[$columnIndex]; + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + return $this->_stmt->errno; + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return $this->_stmt->error; + } + + /** + * {@inheritdoc} + */ + public function closeCursor() + { + $this->_stmt->free_result(); + return true; + } + + /** + * {@inheritdoc} + */ + public function rowCount() + { + if (false === $this->_columnNames) { + return $this->_stmt->affected_rows; + } + return $this->_stmt->num_rows; + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + return $this->_stmt->field_count; + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->_defaultFetchMode = $fetchMode; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + $data = $this->fetchAll(); + return new \ArrayIterator($data); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/OCI8/Driver.php b/src/core/libs/Doctrine/DBAL/Driver/OCI8/Driver.php new file mode 100644 index 0000000..d512610 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/OCI8/Driver.php @@ -0,0 +1,99 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\OCI8; + +use Doctrine\DBAL\Platforms; + +/** + * A Doctrine DBAL driver for the Oracle OCI8 PHP extensions. + * + * @author Roman Borschel <roman@code-factory.org> + * @since 2.0 + */ +class Driver implements \Doctrine\DBAL\Driver +{ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + return new OCI8Connection( + $username, + $password, + $this->_constructDsn($params), + isset($params['charset']) ? $params['charset'] : null, + isset($params['sessionMode']) ? $params['sessionMode'] : OCI_DEFAULT, + isset($params['persistent']) ? $params['persistent'] : false + ); + } + + /** + * Constructs the Oracle DSN. + * + * @return string The DSN. + */ + protected function _constructDsn(array $params) + { + $dsn = ''; + if (isset($params['host']) && $params['host'] != '') { + $dsn .= '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' . + '(HOST=' . $params['host'] . ')'; + + if (isset($params['port'])) { + $dsn .= '(PORT=' . $params['port'] . ')'; + } else { + $dsn .= '(PORT=1521)'; + } + + if (isset($params['service']) && $params['service'] == true) { + $dsn .= '))(CONNECT_DATA=(SERVICE_NAME=' . $params['dbname'] . '))'; + } else { + $dsn .= '))(CONNECT_DATA=(SID=' . $params['dbname'] . '))'; + } + if (isset($params['pooled']) && $params['pooled'] == true) { + $dsn .= '(SERVER=POOLED)'; + } + $dsn .= ')'; + } else { + $dsn .= $params['dbname']; + } + return $dsn; + } + + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\OraclePlatform(); + } + + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new \Doctrine\DBAL\Schema\OracleSchemaManager($conn); + } + + public function getName() + { + return 'oci8'; + } + + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + return $params['user']; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php b/src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php new file mode 100644 index 0000000..bc74787 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Connection.php @@ -0,0 +1,200 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\OCI8; + +use Doctrine\DBAL\Platforms\OraclePlatform; + +/** + * OCI8 implementation of the Connection interface. + * + * @since 2.0 + */ +class OCI8Connection implements \Doctrine\DBAL\Driver\Connection +{ + /** + * @var resource + */ + protected $dbh; + + /** + * @var int + */ + protected $executeMode = OCI_COMMIT_ON_SUCCESS; + + /** + * Create a Connection to an Oracle Database using oci8 extension. + * + * @param string $username + * @param string $password + * @param string $db + */ + public function __construct($username, $password, $db, $charset = null, $sessionMode = OCI_DEFAULT, $persistent = false) + { + if (!defined('OCI_NO_AUTO_COMMIT')) { + define('OCI_NO_AUTO_COMMIT', 0); + } + + $this->dbh = $persistent + ? @oci_pconnect($username, $password, $db, $charset, $sessionMode) + : @oci_connect($username, $password, $db, $charset, $sessionMode); + + if ( ! $this->dbh) { + throw OCI8Exception::fromErrorInfo(oci_error()); + } + } + + /** + * Create a non-executed prepared statement. + * + * @param string $prepareString + * @return OCI8Statement + */ + public function prepare($prepareString) + { + return new OCI8Statement($this->dbh, $prepareString, $this); + } + + /** + * @param string $sql + * @return OCI8Statement + */ + public function query() + { + $args = func_get_args(); + $sql = $args[0]; + //$fetchMode = $args[1]; + $stmt = $this->prepare($sql); + $stmt->execute(); + return $stmt; + } + + /** + * Quote input value. + * + * @param mixed $input + * @param int $type PDO::PARAM* + * @return mixed + */ + public function quote($value, $type=\PDO::PARAM_STR) + { + if (is_int($value) || is_float($value)) { + return $value; + } + $value = str_replace("'", "''", $value); + return "'" . addcslashes($value, "\000\n\r\\\032") . "'"; + } + + /** + * + * @param string $statement + * @return int + */ + public function exec($statement) + { + $stmt = $this->prepare($statement); + $stmt->execute(); + return $stmt->rowCount(); + } + + /** + * {@inheritDoc} + */ + public function lastInsertId($name = null) + { + if ($name === null) { + return false; + } + + OraclePlatform::assertValidIdentifier($name); + + $sql = 'SELECT ' . $name . '.CURRVAL FROM DUAL'; + $stmt = $this->query($sql); + $result = $stmt->fetch(\PDO::FETCH_ASSOC); + + if ($result === false || !isset($result['CURRVAL'])) { + throw new OCI8Exception("lastInsertId failed: Query was executed but no result was returned."); + } + + return (int) $result['CURRVAL']; + } + + /** + * Return the current execution mode. + */ + public function getExecuteMode() + { + return $this->executeMode; + } + + /** + * Start a transactiom + * + * Oracle has to explicitly set the autocommit mode off. That means + * after connection, a commit or rollback there is always automatically + * opened a new transaction. + * + * @return bool + */ + public function beginTransaction() + { + $this->executeMode = OCI_NO_AUTO_COMMIT; + return true; + } + + /** + * @throws OCI8Exception + * @return bool + */ + public function commit() + { + if (!oci_commit($this->dbh)) { + throw OCI8Exception::fromErrorInfo($this->errorInfo()); + } + $this->executeMode = OCI_COMMIT_ON_SUCCESS; + return true; + } + + /** + * @throws OCI8Exception + * @return bool + */ + public function rollBack() + { + if (!oci_rollback($this->dbh)) { + throw OCI8Exception::fromErrorInfo($this->errorInfo()); + } + $this->executeMode = OCI_COMMIT_ON_SUCCESS; + return true; + } + + public function errorCode() + { + $error = oci_error($this->dbh); + if ($error !== false) { + $error = $error['code']; + } + return $error; + } + + public function errorInfo() + { + return oci_error($this->dbh); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php b/src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php new file mode 100644 index 0000000..adeb13f --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Exception.php @@ -0,0 +1,30 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Driver\OCI8; + +class OCI8Exception extends \Exception +{ + static public function fromErrorInfo($error) + { + return new self($error['message'], $error['code']); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php b/src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php new file mode 100644 index 0000000..8bf3121 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/OCI8/OCI8Statement.php @@ -0,0 +1,268 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\OCI8; + +use PDO; +use IteratorAggregate; +use Doctrine\DBAL\Driver\Statement; + +/** + * The OCI8 implementation of the Statement interface. + * + * @since 2.0 + * @author Roman Borschel <roman@code-factory.org> + */ +class OCI8Statement implements \IteratorAggregate, Statement +{ + /** Statement handle. */ + protected $_dbh; + protected $_sth; + protected $_conn; + protected static $_PARAM = ':param'; + protected static $fetchModeMap = array( + PDO::FETCH_BOTH => OCI_BOTH, + PDO::FETCH_ASSOC => OCI_ASSOC, + PDO::FETCH_NUM => OCI_NUM, + PDO::PARAM_LOB => OCI_B_BLOB, + PDO::FETCH_COLUMN => OCI_NUM, + ); + protected $_defaultFetchMode = PDO::FETCH_BOTH; + protected $_paramMap = array(); + + /** + * Creates a new OCI8Statement that uses the given connection handle and SQL statement. + * + * @param resource $dbh The connection handle. + * @param string $statement The SQL statement. + */ + public function __construct($dbh, $statement, OCI8Connection $conn) + { + list($statement, $paramMap) = self::convertPositionalToNamedPlaceholders($statement); + $this->_sth = oci_parse($dbh, $statement); + $this->_dbh = $dbh; + $this->_paramMap = $paramMap; + $this->_conn = $conn; + } + + /** + * Convert positional (?) into named placeholders (:param<num>) + * + * Oracle does not support positional parameters, hence this method converts all + * positional parameters into artificially named parameters. Note that this conversion + * is not perfect. All question marks (?) in the original statement are treated as + * placeholders and converted to a named parameter. + * + * The algorithm uses a state machine with two possible states: InLiteral and NotInLiteral. + * Question marks inside literal strings are therefore handled correctly by this method. + * This comes at a cost, the whole sql statement has to be looped over. + * + * @todo extract into utility class in Doctrine\DBAL\Util namespace + * @todo review and test for lost spaces. we experienced missing spaces with oci8 in some sql statements. + * @param string $statement The SQL statement to convert. + * @return string + */ + static public function convertPositionalToNamedPlaceholders($statement) + { + $count = 1; + $inLiteral = false; // a valid query never starts with quotes + $stmtLen = strlen($statement); + $paramMap = array(); + for ($i = 0; $i < $stmtLen; $i++) { + if ($statement[$i] == '?' && !$inLiteral) { + // real positional parameter detected + $paramMap[$count] = ":param$count"; + $len = strlen($paramMap[$count]); + $statement = substr_replace($statement, ":param$count", $i, 1); + $i += $len-1; // jump ahead + $stmtLen = strlen($statement); // adjust statement length + ++$count; + } else if ($statement[$i] == "'" || $statement[$i] == '"') { + $inLiteral = ! $inLiteral; // switch state! + } + } + + return array($statement, $paramMap); + } + + /** + * {@inheritdoc} + */ + public function bindValue($param, $value, $type = null) + { + return $this->bindParam($param, $value, $type, null); + } + + /** + * {@inheritdoc} + */ + public function bindParam($column, &$variable, $type = null,$length = null) + { + $column = isset($this->_paramMap[$column]) ? $this->_paramMap[$column] : $column; + + if ($type == \PDO::PARAM_LOB) { + $lob = oci_new_descriptor($this->_dbh, OCI_D_LOB); + $lob->writeTemporary($variable, OCI_TEMP_BLOB); + + return oci_bind_by_name($this->_sth, $column, $lob, -1, OCI_B_BLOB); + } else { + return oci_bind_by_name($this->_sth, $column, $variable); + } + } + + /** + * Closes the cursor, enabling the statement to be executed again. + * + * @return boolean Returns TRUE on success or FALSE on failure. + */ + public function closeCursor() + { + return oci_free_statement($this->_sth); + } + + /** + * {@inheritdoc} + */ + public function columnCount() + { + return oci_num_fields($this->_sth); + } + + /** + * {@inheritdoc} + */ + public function errorCode() + { + $error = oci_error($this->_sth); + if ($error !== false) { + $error = $error['code']; + } + return $error; + } + + /** + * {@inheritdoc} + */ + public function errorInfo() + { + return oci_error($this->_sth); + } + + /** + * {@inheritdoc} + */ + public function execute($params = null) + { + if ($params) { + $hasZeroIndex = array_key_exists(0, $params); + foreach ($params as $key => $val) { + if ($hasZeroIndex && is_numeric($key)) { + $this->bindValue($key + 1, $val); + } else { + $this->bindValue($key, $val); + } + } + } + + $ret = @oci_execute($this->_sth, $this->_conn->getExecuteMode()); + if ( ! $ret) { + throw OCI8Exception::fromErrorInfo($this->errorInfo()); + } + return $ret; + } + + /** + * {@inheritdoc} + */ + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->_defaultFetchMode = $fetchMode; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + $data = $this->fetchAll(); + return new \ArrayIterator($data); + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null) + { + $fetchMode = $fetchMode ?: $this->_defaultFetchMode; + if ( ! isset(self::$fetchModeMap[$fetchMode])) { + throw new \InvalidArgumentException("Invalid fetch style: " . $fetchMode); + } + + return oci_fetch_array($this->_sth, self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | OCI_RETURN_LOBS); + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null) + { + $fetchMode = $fetchMode ?: $this->_defaultFetchMode; + if ( ! isset(self::$fetchModeMap[$fetchMode])) { + throw new \InvalidArgumentException("Invalid fetch style: " . $fetchMode); + } + + $result = array(); + if (self::$fetchModeMap[$fetchMode] === OCI_BOTH) { + while ($row = $this->fetch($fetchMode)) { + $result[] = $row; + } + } else { + $fetchStructure = OCI_FETCHSTATEMENT_BY_ROW; + if ($fetchMode == PDO::FETCH_COLUMN) { + $fetchStructure = OCI_FETCHSTATEMENT_BY_COLUMN; + } + + oci_fetch_all($this->_sth, $result, 0, -1, + self::$fetchModeMap[$fetchMode] | OCI_RETURN_NULLS | $fetchStructure | OCI_RETURN_LOBS); + + if ($fetchMode == PDO::FETCH_COLUMN) { + $result = $result[0]; + } + } + + return $result; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $row = oci_fetch_array($this->_sth, OCI_NUM | OCI_RETURN_NULLS | OCI_RETURN_LOBS); + return isset($row[$columnIndex]) ? $row[$columnIndex] : false; + } + + /** + * {@inheritdoc} + */ + public function rowCount() + { + return oci_num_rows($this->_sth); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/PDOConnection.php b/src/core/libs/Doctrine/DBAL/Driver/PDOConnection.php new file mode 100644 index 0000000..4595e5a --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/PDOConnection.php @@ -0,0 +1,40 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver; + +use \PDO; + +/** + * PDO implementation of the Connection interface. + * Used by all PDO-based drivers. + * + * @since 2.0 + */ +class PDOConnection extends PDO implements Connection +{ + public function __construct($dsn, $user = null, $password = null, array $options = null) + { + parent::__construct($dsn, $user, $password, $options); + $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Doctrine\DBAL\Driver\PDOStatement', array())); + $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/PDOIbm/Driver.php b/src/core/libs/Doctrine/DBAL/Driver/PDOIbm/Driver.php new file mode 100644 index 0000000..de30757 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/PDOIbm/Driver.php @@ -0,0 +1,126 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Driver\PDOIbm; + +use Doctrine\DBAL\Connection; + +/** + * Driver for the PDO IBM extension + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 1.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class Driver implements \Doctrine\DBAL\Driver +{ + /** + * Attempts to establish a connection with the underlying driver. + * + * @param array $params + * @param string $username + * @param string $password + * @param array $driverOptions + * @return \Doctrine\DBAL\Driver\Connection + */ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + $conn = new \Doctrine\DBAL\Driver\PDOConnection( + $this->_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + return $conn; + } + + /** + * Constructs the MySql PDO DSN. + * + * @return string The DSN. + */ + private function _constructPdoDsn(array $params) + { + $dsn = 'ibm:'; + if (isset($params['host'])) { + $dsn .= 'HOSTNAME=' . $params['host'] . ';'; + } + if (isset($params['port'])) { + $dsn .= 'PORT=' . $params['port'] . ';'; + } + $dsn .= 'PROTOCOL=TCPIP;'; + if (isset($params['dbname'])) { + $dsn .= 'DATABASE=' . $params['dbname'] . ';'; + } + + return $dsn; + } + + /** + * Gets the DatabasePlatform instance that provides all the metadata about + * the platform this driver connects to. + * + * @return \Doctrine\DBAL\Platforms\AbstractPlatform The database platform. + */ + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\DB2Platform; + } + + /** + * Gets the SchemaManager that can be used to inspect and change the underlying + * database schema of the platform this driver connects to. + * + * @param \Doctrine\DBAL\Connection $conn + * @return \Doctrine\DBAL\Schema\DB2SchemaManager + */ + public function getSchemaManager(Connection $conn) + { + return new \Doctrine\DBAL\Schema\DB2SchemaManager($conn); + } + + /** + * Gets the name of the driver. + * + * @return string The name of the driver. + */ + public function getName() + { + return 'pdo_ibm'; + } + + /** + * Get the name of the database connected to for this driver. + * + * @param \Doctrine\DBAL\Connection $conn + * @return string $database + */ + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + return $params['dbname']; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/PDOMySql/Driver.php b/src/core/libs/Doctrine/DBAL/Driver/PDOMySql/Driver.php new file mode 100644 index 0000000..eeb6727 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/PDOMySql/Driver.php @@ -0,0 +1,102 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\PDOMySql; + +use Doctrine\DBAL\Connection; + +/** + * PDO MySql driver. + * + * @since 2.0 + */ +class Driver implements \Doctrine\DBAL\Driver +{ + /** + * Attempts to establish a connection with the underlying driver. + * + * @param array $params + * @param string $username + * @param string $password + * @param array $driverOptions + * @return \Doctrine\DBAL\Driver\Connection + */ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + $conn = new \Doctrine\DBAL\Driver\PDOConnection( + $this->_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + return $conn; + } + + /** + * Constructs the MySql PDO DSN. + * + * @return string The DSN. + */ + private function _constructPdoDsn(array $params) + { + $dsn = 'mysql:'; + if (isset($params['host']) && $params['host'] != '') { + $dsn .= 'host=' . $params['host'] . ';'; + } + if (isset($params['port'])) { + $dsn .= 'port=' . $params['port'] . ';'; + } + if (isset($params['dbname'])) { + $dsn .= 'dbname=' . $params['dbname'] . ';'; + } + if (isset($params['unix_socket'])) { + $dsn .= 'unix_socket=' . $params['unix_socket'] . ';'; + } + if (isset($params['charset'])) { + $dsn .= 'charset=' . $params['charset'] . ';'; + } + + return $dsn; + } + + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\MySqlPlatform(); + } + + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new \Doctrine\DBAL\Schema\MySqlSchemaManager($conn); + } + + public function getName() + { + return 'pdo_mysql'; + } + + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + + if (isset($params['dbname'])) { + return $params['dbname']; + } + return $conn->query('SELECT DATABASE()')->fetchColumn(); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/PDOOracle/Driver.php b/src/core/libs/Doctrine/DBAL/Driver/PDOOracle/Driver.php new file mode 100644 index 0000000..cb2e6b0 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/PDOOracle/Driver.php @@ -0,0 +1,98 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\PDOOracle; + +use Doctrine\DBAL\Platforms; + +/** + * PDO Oracle driver + * + * WARNING: This driver gives us segfauls in our testsuites on CLOB and other + * stuff. PDO Oracle is not maintained by Oracle or anyone in the PHP community, + * which leads us to the recommendation to use the "oci8" driver to connect + * to Oracle instead. + */ +class Driver implements \Doctrine\DBAL\Driver +{ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + return new \Doctrine\DBAL\Driver\PDOConnection( + $this->_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + } + + /** + * Constructs the Oracle PDO DSN. + * + * @return string The DSN. + */ + private function _constructPdoDsn(array $params) + { + $dsn = 'oci:'; + if (isset($params['host']) && $params['host'] != '') { + $dsn .= 'dbname=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)' . + '(HOST=' . $params['host'] . ')'; + + if (isset($params['port'])) { + $dsn .= '(PORT=' . $params['port'] . ')'; + } else { + $dsn .= '(PORT=1521)'; + } + + if (isset($params['service']) && $params['service'] == true) { + $dsn .= '))(CONNECT_DATA=(SERVICE_NAME=' . $params['dbname'] . ')))'; + } else { + $dsn .= '))(CONNECT_DATA=(SID=' . $params['dbname'] . ')))'; + } + } else { + $dsn .= 'dbname=' . $params['dbname']; + } + + if (isset($params['charset'])) { + $dsn .= ';charset=' . $params['charset']; + } + + return $dsn; + } + + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\OraclePlatform(); + } + + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new \Doctrine\DBAL\Schema\OracleSchemaManager($conn); + } + + public function getName() + { + return 'pdo_oracle'; + } + + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + return $params['user']; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/PDOPgSql/Driver.php b/src/core/libs/Doctrine/DBAL/Driver/PDOPgSql/Driver.php new file mode 100644 index 0000000..951406d --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/PDOPgSql/Driver.php @@ -0,0 +1,70 @@ +<?php + +namespace Doctrine\DBAL\Driver\PDOPgSql; + +use Doctrine\DBAL\Platforms; + +/** + * Driver that connects through pdo_pgsql. + * + * @since 2.0 + */ +class Driver implements \Doctrine\DBAL\Driver +{ + /** + * Attempts to connect to the database and returns a driver connection on success. + * + * @return \Doctrine\DBAL\Driver\Connection + */ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + return new \Doctrine\DBAL\Driver\PDOConnection( + $this->_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + } + + /** + * Constructs the Postgres PDO DSN. + * + * @return string The DSN. + */ + private function _constructPdoDsn(array $params) + { + $dsn = 'pgsql:'; + if (isset($params['host']) && $params['host'] != '') { + $dsn .= 'host=' . $params['host'] . ' '; + } + if (isset($params['port']) && $params['port'] != '') { + $dsn .= 'port=' . $params['port'] . ' '; + } + if (isset($params['dbname'])) { + $dsn .= 'dbname=' . $params['dbname'] . ' '; + } + + return $dsn; + } + + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\PostgreSqlPlatform(); + } + + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new \Doctrine\DBAL\Schema\PostgreSqlSchemaManager($conn); + } + + public function getName() + { + return 'pdo_pgsql'; + } + + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + return $params['dbname']; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/PDOSqlite/Driver.php b/src/core/libs/Doctrine/DBAL/Driver/PDOSqlite/Driver.php new file mode 100644 index 0000000..903d999 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/PDOSqlite/Driver.php @@ -0,0 +1,116 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\PDOSqlite; + +/** + * The PDO Sqlite driver. + * + * @since 2.0 + */ +class Driver implements \Doctrine\DBAL\Driver +{ + /** + * @var array + */ + protected $_userDefinedFunctions = array( + 'sqrt' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfSqrt'), 'numArgs' => 1), + 'mod' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfMod'), 'numArgs' => 2), + 'locate' => array('callback' => array('Doctrine\DBAL\Platforms\SqlitePlatform', 'udfLocate'), 'numArgs' => -1), + ); + + /** + * Tries to establish a database connection to SQLite. + * + * @param array $params + * @param string $username + * @param string $password + * @param array $driverOptions + * @return \Doctrine\DBAL\Driver\PDOConnection + */ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + if (isset($driverOptions['userDefinedFunctions'])) { + $this->_userDefinedFunctions = array_merge( + $this->_userDefinedFunctions, $driverOptions['userDefinedFunctions']); + unset($driverOptions['userDefinedFunctions']); + } + + $pdo = new \Doctrine\DBAL\Driver\PDOConnection( + $this->_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + + foreach ($this->_userDefinedFunctions as $fn => $data) { + $pdo->sqliteCreateFunction($fn, $data['callback'], $data['numArgs']); + } + + return $pdo; + } + + /** + * Constructs the Sqlite PDO DSN. + * + * @return string The DSN. + * @override + */ + protected function _constructPdoDsn(array $params) + { + $dsn = 'sqlite:'; + if (isset($params['path'])) { + $dsn .= $params['path']; + } else if (isset($params['memory'])) { + $dsn .= ':memory:'; + } + + return $dsn; + } + + /** + * Gets the database platform that is relevant for this driver. + */ + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\SqlitePlatform(); + } + + /** + * Gets the schema manager that is relevant for this driver. + * + * @param \Doctrine\DBAL\Connection $conn + * @return \Doctrine\DBAL\Schema\SqliteSchemaManager + */ + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new \Doctrine\DBAL\Schema\SqliteSchemaManager($conn); + } + + public function getName() + { + return 'pdo_sqlite'; + } + + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + return isset($params['path']) ? $params['path'] : null; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php b/src/core/libs/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php new file mode 100644 index 0000000..01a5769 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/PDOSqlsrv/Connection.php @@ -0,0 +1,45 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\PDOSqlsrv; + +/** + * Sqlsrv Connection implementation. + * + * @since 2.0 + */ +class Connection extends \Doctrine\DBAL\Driver\PDOConnection implements \Doctrine\DBAL\Driver\Connection +{ + /** + * @override + */ + public function quote($value, $type=\PDO::PARAM_STR) + { + $val = parent::quote($value, $type); + + // Fix for a driver version terminating all values with null byte + if (strpos($val, "\0") !== false) { + $val = substr($val, 0, -1); + } + + return $val; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php b/src/core/libs/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php new file mode 100644 index 0000000..7072b5f --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/PDOSqlsrv/Driver.php @@ -0,0 +1,87 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\PDOSqlsrv; + +/** + * The PDO-based Sqlsrv driver. + * + * @since 2.0 + */ +class Driver implements \Doctrine\DBAL\Driver +{ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + return new Connection( + $this->_constructPdoDsn($params), + $username, + $password, + $driverOptions + ); + } + + /** + * Constructs the Sqlsrv PDO DSN. + * + * @return string The DSN. + */ + private function _constructPdoDsn(array $params) + { + $dsn = 'sqlsrv:server='; + + if (isset($params['host'])) { + $dsn .= $params['host']; + } + + if (isset($params['port']) && !empty($params['port'])) { + $dsn .= ',' . $params['port']; + } + + if (isset($params['dbname'])) {; + $dsn .= ';Database=' . $params['dbname']; + } + + if (isset($params['MultipleActiveResultSets'])) { + $dsn .= '; MultipleActiveResultSets=' . ($params['MultipleActiveResultSets'] ? 'true' : 'false'); + } + + return $dsn; + } + + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\SQLServer2008Platform(); + } + + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new \Doctrine\DBAL\Schema\SQLServerSchemaManager($conn); + } + + public function getName() + { + return 'pdo_sqlsrv'; + } + + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + return $params['dbname']; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/PDOStatement.php b/src/core/libs/Doctrine/DBAL/Driver/PDOStatement.php new file mode 100644 index 0000000..2673ae9 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/PDOStatement.php @@ -0,0 +1,50 @@ +<?php +/* + * $Id: Interface.php 3882 2008-02-22 18:11:35Z jwage $ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver; + +/** + * The PDO implementation of the Statement interface. + * Used by all PDO-based drivers. + * + * @since 2.0 + */ +class PDOStatement extends \PDOStatement implements Statement +{ + private function __construct() {} + + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + // This thin wrapper is necessary to shield against the weird signature + // of PDOStatement::setFetchMode(): even if the second and third + // parameters are optional, PHP will not let us remove it from this + // declaration. + if ($arg2 === null && $arg3 === null) { + return parent::setFetchMode($fetchMode); + } + + if ($arg3 === null) { + return parent::setFetchMode($fetchMode, $arg2); + } + + return parent::setFetchMode($fetchMode, $arg2, $arg3); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Driver/ResultStatement.php b/src/core/libs/Doctrine/DBAL/Driver/ResultStatement.php new file mode 100644 index 0000000..561dc35 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/ResultStatement.php @@ -0,0 +1,93 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver; + +use PDO; + +/** + * Interface for the reading part of a prepare statement only. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +interface ResultStatement extends \Traversable +{ + /** + * Closes the cursor, enabling the statement to be executed again. + * + * @return boolean Returns TRUE on success or FALSE on failure. + */ + function closeCursor(); + + + /** + * columnCount + * Returns the number of columns in the result set + * + * @return integer Returns the number of columns in the result set represented + * by the PDOStatement object. If there is no result set, + * this method should return 0. + */ + function columnCount(); + + /** + * setFetchMode + * Set the fetch mode to use while iterating this statement. + * + * @param integer $fetchMode + */ + function setFetchMode($fetchMode, $arg2 = null, $arg3 = null); + + /** + * fetch + * + * @see Query::HYDRATE_* constants + * @param integer $fetchMode Controls how the next row will be returned to the caller. + * This value must be one of the Query::HYDRATE_* constants, + * defaulting to Query::HYDRATE_BOTH + * + * @return mixed + */ + function fetch($fetchMode = null); + + /** + * Returns an array containing all of the result set rows + * + * @param integer $fetchMode Controls how the next row will be returned to the caller. + * This value must be one of the Query::HYDRATE_* constants, + * defaulting to Query::HYDRATE_BOTH + * + * @return array + */ + function fetchAll($fetchMode = null); + + /** + * fetchColumn + * Returns a single column from the next row of a + * result set or FALSE if there are no more rows. + * + * @param integer $columnIndex 0-indexed number of the column you wish to retrieve from the row. If no + * value is supplied, PDOStatement->fetchColumn() + * fetches the first column. + * + * @return string returns a single column in the next row of a result set. + */ + function fetchColumn($columnIndex = 0); +} + diff --git a/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/Driver.php b/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/Driver.php new file mode 100644 index 0000000..c7043cc --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/Driver.php @@ -0,0 +1,72 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\SQLSrv; + +/** + * Driver for ext/sqlsrv + */ +class Driver implements \Doctrine\DBAL\Driver +{ + public function connect(array $params, $username = null, $password = null, array $driverOptions = array()) + { + if (!isset($params['host'])) { + throw new SQLSrvException("Missing 'host' in configuration for sqlsrv driver."); + } + if (!isset($params['dbname'])) { + throw new SQLSrvException("Missing 'dbname' in configuration for sqlsrv driver."); + } + + $serverName = $params['host']; + if (isset($params['port'])) { + $serverName .= ', ' . $params['port']; + } + $driverOptions['Database'] = $params['dbname']; + $driverOptions['UID'] = $username; + $driverOptions['PWD'] = $password; + + if (!isset($driverOptions['ReturnDatesAsStrings'])) { + $driverOptions['ReturnDatesAsStrings'] = 1; + } + + return new SQLSrvConnection($serverName, $driverOptions); + } + + public function getDatabasePlatform() + { + return new \Doctrine\DBAL\Platforms\SQLServer2008Platform(); + } + + public function getSchemaManager(\Doctrine\DBAL\Connection $conn) + { + return new \Doctrine\DBAL\Schema\SQLServerSchemaManager($conn); + } + + public function getName() + { + return 'sqlsrv'; + } + + public function getDatabase(\Doctrine\DBAL\Connection $conn) + { + $params = $conn->getParams(); + return $params['dbname']; + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/LastInsertId.php b/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/LastInsertId.php new file mode 100644 index 0000000..421d071 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/LastInsertId.php @@ -0,0 +1,42 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\SQLSrv; + +/** + * Last Id Data Container + * + * @since 2.3 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class LastInsertId +{ + private $id; + + public function setId($id) + { + $this->id = $id; + } + + public function getId() + { + return $this->id; + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php b/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php new file mode 100644 index 0000000..82544ca --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvConnection.php @@ -0,0 +1,161 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\SQLSrv; + +/** + * SQL Server implementation for the Connection interface. + * + * @since 2.3 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class SQLSrvConnection implements \Doctrine\DBAL\Driver\Connection +{ + /** + * @var resource + */ + protected $conn; + + /** + * @var LastInsertId + */ + protected $lastInsertId; + + + public function __construct($serverName, $connectionOptions) + { + $this->conn = sqlsrv_connect($serverName, $connectionOptions); + if ( ! $this->conn) { + throw SQLSrvException::fromSqlSrvErrors(); + } + $this->lastInsertId = new LastInsertId(); + } + + /** + * {@inheritDoc} + */ + public function prepare($sql) + { + return new SQLSrvStatement($this->conn, $sql, $this->lastInsertId); + } + + /** + * {@inheritDoc} + */ + public function query() + { + $args = func_get_args(); + $sql = $args[0]; + $stmt = $this->prepare($sql); + $stmt->execute(); + return $stmt; + } + + /** + * {@inheritDoc} + * @license New BSD, code from Zend Framework + */ + public function quote($value, $type=\PDO::PARAM_STR) + { + if (is_int($value)) { + return $value; + } else if (is_float($value)) { + return sprintf('%F', $value); + } + + return "'" . str_replace("'", "''", $value) . "'"; + } + + /** + * {@inheritDoc} + */ + public function exec($statement) + { + $stmt = $this->prepare($statement); + $stmt->execute(); + return $stmt->rowCount(); + } + + /** + * {@inheritDoc} + */ + public function lastInsertId($name = null) + { + if ($name !== null) { + $sql = "SELECT IDENT_CURRENT(".$this->quote($name).") AS LastInsertId"; + $stmt = $this->prepare($sql); + $stmt->execute(); + + return $stmt->fetchColumn(); + } + + return $this->lastInsertId->getId(); + } + + /** + * {@inheritDoc} + */ + public function beginTransaction() + { + if ( ! sqlsrv_begin_transaction($this->conn)) { + throw SQLSrvException::fromSqlSrvErrors(); + } + } + + /** + * {@inheritDoc} + */ + public function commit() + { + if ( ! sqlsrv_commit($this->conn)) { + throw SQLSrvException::fromSqlSrvErrors(); + } + } + + /** + * {@inheritDoc} + */ + public function rollBack() + { + if ( ! sqlsrv_rollback($this->conn)) { + throw SQLSrvException::fromSqlSrvErrors(); + } + } + + /** + * {@inheritDoc} + */ + public function errorCode() + { + $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); + if ($errors) { + return $errors[0]['code']; + } + return false; + } + + /** + * {@inheritDoc} + */ + public function errorInfo() + { + return sqlsrv_errors(SQLSRV_ERR_ERRORS); + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php b/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php new file mode 100644 index 0000000..6777877 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvException.php @@ -0,0 +1,43 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\SQLSrv; + +class SQLSrvException extends \Doctrine\DBAL\DBALException +{ + /** + * Helper method to turn sql server errors into exception. + * + * @return SQLSrvException + */ + static public function fromSqlSrvErrors() + { + $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); + $message = ""; + foreach ($errors as $error) { + $message .= "SQLSTATE [".$error['SQLSTATE'].", ".$error['code']."]: ". $error['message']."\n"; + } + if ( ! $message) { + $message = "SQL Server error occured but no error message was retrieved from driver."; + } + + return new self(rtrim($message)); + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php b/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php new file mode 100644 index 0000000..76a156b --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/SQLSrv/SQLSrvStatement.php @@ -0,0 +1,251 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver\SQLSrv; + +use PDO; +use IteratorAggregate; +use Doctrine\DBAL\Driver\Statement; + +/** + * SQL Server Statement + * + * @since 2.3 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class SQLSrvStatement implements IteratorAggregate, Statement +{ + /** + * SQLSRV Resource + * + * @var resource + */ + private $conn; + + /** + * SQL Statement to execute + * + * @var string + */ + private $sql; + + /** + * SQLSRV Statement Resource + * + * @var resource + */ + private $stmt; + + /** + * Parameters to bind + * + * @var array + */ + private $params = array(); + + /** + * Translations + * + * @var array + */ + private static $fetchMap = array( + PDO::FETCH_BOTH => SQLSRV_FETCH_BOTH, + PDO::FETCH_ASSOC => SQLSRV_FETCH_ASSOC, + PDO::FETCH_NUM => SQLSRV_FETCH_NUMERIC, + ); + + /** + * Fetch Style + * + * @param int + */ + private $defaultFetchMode = PDO::FETCH_BOTH; + + /** + * @var int|null + */ + private $lastInsertId; + + /** + * Append to any INSERT query to retrieve the last insert id. + * + * @var string + */ + const LAST_INSERT_ID_SQL = ';SELECT SCOPE_IDENTITY() AS LastInsertId;'; + + public function __construct($conn, $sql, $lastInsertId = null) + { + $this->conn = $conn; + $this->sql = $sql; + + if (stripos($sql, 'INSERT INTO ') === 0) { + $this->sql .= self::LAST_INSERT_ID_SQL; + $this->lastInsertId = $lastInsertId; + } + } + + public function bindValue($param, $value, $type = null) + { + return $this->bindParam($param, $value, $type,null); + } + + /** + * {@inheritdoc} + */ + public function bindParam($column, &$variable, $type = null, $length = null) + { + if (!is_numeric($column)) { + throw new SQLSrvException("sqlsrv does not support named parameters to queries, use question mark (?) placeholders instead."); + } + + if ($type === \PDO::PARAM_LOB) { + $this->params[$column-1] = array($variable, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY), SQLSRV_SQLTYPE_VARBINARY('max')); + } else { + $this->params[$column-1] = $variable; + } + } + + public function closeCursor() + { + if ($this->stmt) { + sqlsrv_free_stmt($this->stmt); + } + } + + public function columnCount() + { + return sqlsrv_num_fields($this->stmt); + } + + /** + * {@inheritDoc} + */ + public function errorCode() + { + $errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); + if ($errors) { + return $errors[0]['code']; + } + return false; + } + + /** + * {@inheritDoc} + */ + public function errorInfo() + { + return sqlsrv_errors(SQLSRV_ERR_ERRORS); + } + + public function execute($params = null) + { + if ($params) { + $hasZeroIndex = array_key_exists(0, $params); + foreach ($params as $key => $val) { + $key = ($hasZeroIndex && is_numeric($key)) ? $key + 1 : $key; + $this->bindValue($key, $val); + } + } + + $this->stmt = sqlsrv_query($this->conn, $this->sql, $this->params); + if ( ! $this->stmt) { + throw SQLSrvException::fromSqlSrvErrors(); + } + + if ($this->lastInsertId) { + sqlsrv_next_result($this->stmt); + sqlsrv_fetch($this->stmt); + $this->lastInsertId->setId( sqlsrv_get_field($this->stmt, 0) ); + } + } + + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + $this->defaultFetchMode = $fetchMode; + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + $data = $this->fetchAll(); + return new \ArrayIterator($data); + } + + /** + * {@inheritdoc} + */ + public function fetch($fetchMode = null) + { + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + if (isset(self::$fetchMap[$fetchMode])) { + return sqlsrv_fetch_array($this->stmt, self::$fetchMap[$fetchMode]); + } else if ($fetchMode == PDO::FETCH_OBJ || $fetchMode == PDO::FETCH_CLASS) { + $className = null; + $ctorArgs = null; + if (func_num_args() >= 2) { + $args = func_get_args(); + $className = $args[1]; + $ctorArgs = (isset($args[2])) ? $args[2] : array(); + } + return sqlsrv_fetch_object($this->stmt, $className, $ctorArgs); + } + + throw new SQLSrvException("Fetch mode is not supported!"); + } + + /** + * {@inheritdoc} + */ + public function fetchAll($fetchMode = null) + { + $className = null; + $ctorArgs = null; + if (func_num_args() >= 2) { + $args = func_get_args(); + $className = $args[1]; + $ctorArgs = (isset($args[2])) ? $args[2] : array(); + } + + $rows = array(); + while ($row = $this->fetch($fetchMode, $className, $ctorArgs)) { + $rows[] = $row; + } + return $rows; + } + + /** + * {@inheritdoc} + */ + public function fetchColumn($columnIndex = 0) + { + $row = $this->fetch(PDO::FETCH_NUM); + return $row[$columnIndex]; + } + + /** + * {@inheritdoc} + */ + public function rowCount() + { + return sqlsrv_rows_affected($this->stmt); + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Driver/Statement.php b/src/core/libs/Doctrine/DBAL/Driver/Statement.php new file mode 100644 index 0000000..718614d --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Driver/Statement.php @@ -0,0 +1,125 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Driver; + +use \PDO; + +/** + * Statement interface. + * Drivers must implement this interface. + * + * This resembles (a subset of) the PDOStatement interface. + * + * @author Konsta Vesterinen <kvesteri@cc.hut.fi> + * @author Roman Borschel <roman@code-factory.org> + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.0 + */ +interface Statement extends ResultStatement +{ + /** + * Binds a value to a corresponding named or positional + * placeholder in the SQL statement that was used to prepare the statement. + * + * @param mixed $param Parameter identifier. For a prepared statement using named placeholders, + * this will be a parameter name of the form :name. For a prepared statement + * using question mark placeholders, this will be the 1-indexed position of the parameter + * + * @param mixed $value The value to bind to the parameter. + * @param integer $type Explicit data type for the parameter using the PDO::PARAM_* constants. + * + * @return boolean Returns TRUE on success or FALSE on failure. + */ + function bindValue($param, $value, $type = null); + + /** + * Binds a PHP variable to a corresponding named or question mark placeholder in the + * SQL statement that was use to prepare the statement. Unlike PDOStatement->bindValue(), + * the variable is bound as a reference and will only be evaluated at the time + * that PDOStatement->execute() is called. + * + * Most parameters are input parameters, that is, parameters that are + * used in a read-only fashion to build up the query. Some drivers support the invocation + * of stored procedures that return data as output parameters, and some also as input/output + * parameters that both send in data and are updated to receive it. + * + * @param mixed $column Parameter identifier. For a prepared statement using named placeholders, + * this will be a parameter name of the form :name. For a prepared statement + * using question mark placeholders, this will be the 1-indexed position of the parameter + * + * @param mixed $variable Name of the PHP variable to bind to the SQL statement parameter. + * + * @param integer $type Explicit data type for the parameter using the PDO::PARAM_* constants. To return + * an INOUT parameter from a stored procedure, use the bitwise OR operator to set the + * PDO::PARAM_INPUT_OUTPUT bits for the data_type parameter. + * @param integer $length You must specify maxlength when using an OUT bind so that PHP allocates enough memory to hold the returned value. + * @return boolean Returns TRUE on success or FALSE on failure. + */ + function bindParam($column, &$variable, $type = null, $length = null); + + /** + * errorCode + * Fetch the SQLSTATE associated with the last operation on the statement handle + * + * @see Doctrine_Adapter_Interface::errorCode() + * @return string error code string + */ + function errorCode(); + + /** + * errorInfo + * Fetch extended error information associated with the last operation on the statement handle + * + * @see Doctrine_Adapter_Interface::errorInfo() + * @return array error info array + */ + function errorInfo(); + + /** + * Executes a prepared statement + * + * If the prepared statement included parameter markers, you must either: + * call PDOStatement->bindParam() to bind PHP variables to the parameter markers: + * bound variables pass their value as input and receive the output value, + * if any, of their associated parameter markers or pass an array of input-only + * parameter values + * + * + * @param array $params An array of values with as many elements as there are + * bound parameters in the SQL statement being executed. + * @return boolean Returns TRUE on success or FALSE on failure. + */ + function execute($params = null); + + /** + * rowCount + * rowCount() returns the number of rows affected by the last DELETE, INSERT, or UPDATE statement + * executed by the corresponding object. + * + * If the last SQL statement executed by the associated Statement object was a SELECT statement, + * some databases may return the number of rows returned by that statement. However, + * this behaviour is not guaranteed for all databases and should not be + * relied on for portable applications. + * + * @return integer Returns the number of rows. + */ + function rowCount(); +} diff --git a/src/core/libs/Doctrine/DBAL/DriverManager.php b/src/core/libs/Doctrine/DBAL/DriverManager.php new file mode 100644 index 0000000..7cdde95 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/DriverManager.php @@ -0,0 +1,176 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL; + +use Doctrine\Common\EventManager; + +/** + * Factory for creating Doctrine\DBAL\Connection instances. + * + * @author Roman Borschel <roman@code-factory.org> + * @since 2.0 + */ +final class DriverManager +{ + /** + * List of supported drivers and their mappings to the driver classes. + * + * To add your own driver use the 'driverClass' parameter to + * {@link DriverManager::getConnection()}. + * + * @var array + */ + private static $_driverMap = array( + 'pdo_mysql' => 'Doctrine\DBAL\Driver\PDOMySql\Driver', + 'pdo_sqlite' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver', + 'pdo_pgsql' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver', + 'pdo_oci' => 'Doctrine\DBAL\Driver\PDOOracle\Driver', + 'oci8' => 'Doctrine\DBAL\Driver\OCI8\Driver', + 'ibm_db2' => 'Doctrine\DBAL\Driver\IBMDB2\DB2Driver', + 'pdo_ibm' => 'Doctrine\DBAL\Driver\PDOIbm\Driver', + 'pdo_sqlsrv' => 'Doctrine\DBAL\Driver\PDOSqlsrv\Driver', + 'mysqli' => 'Doctrine\DBAL\Driver\Mysqli\Driver', + 'drizzle_pdo_mysql' => 'Doctrine\DBAL\Driver\DrizzlePDOMySql\Driver', + 'sqlsrv' => 'Doctrine\DBAL\Driver\SQLSrv\Driver', + ); + + /** Private constructor. This class cannot be instantiated. */ + private function __construct() { } + + /** + * Creates a connection object based on the specified parameters. + * This method returns a Doctrine\DBAL\Connection which wraps the underlying + * driver connection. + * + * $params must contain at least one of the following. + * + * Either 'driver' with one of the following values: + * + * pdo_mysql + * pdo_sqlite + * pdo_pgsql + * pdo_oci (unstable) + * pdo_sqlsrv + * pdo_ibm (unstable) + * pdo_sqlsrv + * mysqli + * sqlsrv + * ibm_db2 (unstable) + * drizzle_pdo_mysql + * + * OR 'driverClass' that contains the full class name (with namespace) of the + * driver class to instantiate. + * + * Other (optional) parameters: + * + * <b>user (string)</b>: + * The username to use when connecting. + * + * <b>password (string)</b>: + * The password to use when connecting. + * + * <b>driverOptions (array)</b>: + * Any additional driver-specific options for the driver. These are just passed + * through to the driver. + * + * <b>pdo</b>: + * You can pass an existing PDO instance through this parameter. The PDO + * instance will be wrapped in a Doctrine\DBAL\Connection. + * + * <b>wrapperClass</b>: + * You may specify a custom wrapper class through the 'wrapperClass' + * parameter but this class MUST inherit from Doctrine\DBAL\Connection. + * + * <b>driverClass</b>: + * The driver class to use. + * + * @param array $params The parameters. + * @param \Doctrine\DBAL\Configuration The configuration to use. + * @param \Doctrine\Common\EventManager The event manager to use. + * @return \Doctrine\DBAL\Connection + */ + public static function getConnection( + array $params, + Configuration $config = null, + EventManager $eventManager = null) + { + // create default config and event manager, if not set + if ( ! $config) { + $config = new Configuration(); + } + if ( ! $eventManager) { + $eventManager = new EventManager(); + } + + // check for existing pdo object + if (isset($params['pdo']) && ! $params['pdo'] instanceof \PDO) { + throw DBALException::invalidPdoInstance(); + } else if (isset($params['pdo'])) { + $params['pdo']->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); + $params['driver'] = 'pdo_' . $params['pdo']->getAttribute(\PDO::ATTR_DRIVER_NAME); + } else { + self::_checkParams($params); + } + if (isset($params['driverClass'])) { + $className = $params['driverClass']; + } else { + $className = self::$_driverMap[$params['driver']]; + } + + $driver = new $className(); + + $wrapperClass = 'Doctrine\DBAL\Connection'; + if (isset($params['wrapperClass'])) { + if (is_subclass_of($params['wrapperClass'], $wrapperClass)) { + $wrapperClass = $params['wrapperClass']; + } else { + throw DBALException::invalidWrapperClass($params['wrapperClass']); + } + } + + return new $wrapperClass($params, $driver, $config, $eventManager); + } + + /** + * Checks the list of parameters. + * + * @param array $params + */ + private static function _checkParams(array $params) + { + // check existance of mandatory parameters + + // driver + if ( ! isset($params['driver']) && ! isset($params['driverClass'])) { + throw DBALException::driverRequired(); + } + + // check validity of parameters + + // driver + if ( isset($params['driver']) && ! isset(self::$_driverMap[$params['driver']])) { + throw DBALException::unknownDriver($params['driver'], array_keys(self::$_driverMap)); + } + + if (isset($params['driverClass']) && ! in_array('Doctrine\DBAL\Driver', class_implements($params['driverClass'], true))) { + throw DBALException::invalidDriverClass($params['driverClass']); + } + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/ConnectionEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/ConnectionEventArgs.php new file mode 100644 index 0000000..f4cb1cd --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/ConnectionEventArgs.php @@ -0,0 +1,79 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\Common\EventArgs, + Doctrine\DBAL\Connection; + +/** + * Event Arguments used when a Driver connection is established inside Doctrine\DBAL\Connection. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 1.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class ConnectionEventArgs extends EventArgs +{ + /** + * @var Connection + */ + private $_connection = null; + + public function __construct(Connection $connection) + { + $this->_connection = $connection; + } + + /** + * @return \Doctrine\DBAL\Connection + */ + public function getConnection() + { + return $this->_connection; + } + + /** + * @return \Doctrine\DBAL\Driver + */ + public function getDriver() + { + return $this->_connection->getDriver(); + } + + /** + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getDatabasePlatform() + { + return $this->_connection->getDatabasePlatform(); + } + + /** + * @return \Doctrine\DBAL\Schema\AbstractSchemaManager + */ + public function getSchemaManager() + { + return $this->_connection->getSchemaManager(); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php b/src/core/libs/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php new file mode 100644 index 0000000..fc22744 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/Listeners/MysqlSessionInit.php @@ -0,0 +1,74 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event\Listeners; + +use Doctrine\DBAL\Event\ConnectionEventArgs; +use Doctrine\DBAL\Events; +use Doctrine\Common\EventSubscriber; + +/** + * MySQL Session Init Event Subscriber which allows to set the Client Encoding of the Connection + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 1.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @deprecated Use "charset" option to PDO MySQL Connection instead. + */ +class MysqlSessionInit implements EventSubscriber +{ + /** + * @var string + */ + private $_charset; + + /** + * @var string + */ + private $_collation; + + /** + * Configure Charset and Collation options of MySQL Client for each Connection + * + * @param string $charset + * @param string $collation + */ + public function __construct($charset = 'utf8', $collation = false) + { + $this->_charset = $charset; + $this->_collation = $collation; + } + + /** + * @param ConnectionEventArgs $args + * @return void + */ + public function postConnect(ConnectionEventArgs $args) + { + $collation = ($this->_collation) ? " COLLATE ".$this->_collation : ""; + $args->getConnection()->executeUpdate("SET NAMES ".$this->_charset . $collation); + } + + public function getSubscribedEvents() + { + return array(Events::postConnect); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php b/src/core/libs/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php new file mode 100644 index 0000000..8355403 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/Listeners/OracleSessionInit.php @@ -0,0 +1,80 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event\Listeners; + +use Doctrine\DBAL\Event\ConnectionEventArgs; +use Doctrine\DBAL\Events; +use Doctrine\Common\EventSubscriber; + +/** + * Should be used when Oracle Server default enviroment does not match the Doctrine requirements. + * + * The following enviroment variables are required for the Doctrine default date format: + * + * NLS_TIME_FORMAT="HH24:MI:SS" + * NLS_DATE_FORMAT="YYYY-MM-DD HH24:MI:SS" + * NLS_TIMESTAMP_FORMAT="YYYY-MM-DD HH24:MI:SS" + * NLS_TIMESTAMP_TZ_FORMAT="YYYY-MM-DD HH24:MI:SS TZH:TZM" + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class OracleSessionInit implements EventSubscriber +{ + protected $_defaultSessionVars = array( + 'NLS_TIME_FORMAT' => "HH24:MI:SS", + 'NLS_DATE_FORMAT' => "YYYY-MM-DD HH24:MI:SS", + 'NLS_TIMESTAMP_FORMAT' => "YYYY-MM-DD HH24:MI:SS", + 'NLS_TIMESTAMP_TZ_FORMAT' => "YYYY-MM-DD HH24:MI:SS TZH:TZM", + 'NLS_NUMERIC_CHARACTERS' => ".,", + ); + + /** + * @param array $oracleSessionVars + */ + public function __construct(array $oracleSessionVars = array()) + { + $this->_defaultSessionVars = array_merge($this->_defaultSessionVars, $oracleSessionVars); + } + + /** + * @param ConnectionEventArgs $args + * @return void + */ + public function postConnect(ConnectionEventArgs $args) + { + if (count($this->_defaultSessionVars)) { + array_change_key_case($this->_defaultSessionVars, \CASE_UPPER); + $vars = array(); + foreach ($this->_defaultSessionVars as $option => $value) { + $vars[] = $option." = '".$value."'"; + } + $sql = "ALTER SESSION SET ".implode(" ", $vars); + $args->getConnection()->executeUpdate($sql); + } + } + + public function getSubscribedEvents() + { + return array(Events::postConnect); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php b/src/core/libs/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php new file mode 100644 index 0000000..8dfde62 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/Listeners/SQLSessionInit.php @@ -0,0 +1,63 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event\Listeners; + +use Doctrine\DBAL\Event\ConnectionEventArgs; +use Doctrine\DBAL\Events; +use Doctrine\Common\EventSubscriber; + +/** + * Session init listener for executing a single SQL statement right after a connection is opened. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class SQLSessionInit implements EventSubscriber +{ + /** + * @var string + */ + protected $sql; + + /** + * @param string $sql + */ + public function __construct($sql) + { + $this->sql = $sql; + } + + /** + * @param ConnectionEventArgs $args + * @return void + */ + public function postConnect(ConnectionEventArgs $args) + { + $conn = $args->getConnection(); + $conn->exec($this->sql); + } + + public function getSubscribedEvents() + { + return array(Events::postConnect); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php new file mode 100644 index 0000000..0200ce7 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableAddColumnEventArgs.php @@ -0,0 +1,114 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\TableDiff; + +/** + * Event Arguments used when SQL queries for adding table columns are generated inside Doctrine\DBAL\Platform\*Platform. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Jan Sorgalla <jsorgalla@googlemail.com> + */ +class SchemaAlterTableAddColumnEventArgs extends SchemaEventArgs +{ + /** + * @var \Doctrine\DBAL\Schema\Column + */ + private $_column = null; + + /** + * @var \Doctrine\DBAL\Schema\TableDiff + */ + private $_tableDiff = null; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $_platform = null; + + /** + * @var array + */ + private $_sql = array(); + + /** + * @param \Doctrine\DBAL\Schema\Column $column + * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function __construct(Column $column, TableDiff $tableDiff, AbstractPlatform $platform) + { + $this->_column = $column; + $this->_tableDiff = $tableDiff; + $this->_platform = $platform; + } + + /** + * @return \Doctrine\DBAL\Schema\Column + */ + public function getColumn() + { + return $this->_column; + } + + /** + * @return \Doctrine\DBAL\Schema\TableDiff + */ + public function getTableDiff() + { + return $this->_tableDiff; + } + + /** + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getPlatform() + { + return $this->_platform; + } + + /** + * @param string|array $sql + * @return \Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs + */ + public function addSql($sql) + { + if (is_array($sql)) { + $this->_sql = array_merge($this->_sql, $sql); + } else { + $this->_sql[] = $sql; + } + + return $this; + } + + /** + * @return array + */ + public function getSql() + { + return $this->_sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php new file mode 100644 index 0000000..bd59d7d --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableChangeColumnEventArgs.php @@ -0,0 +1,114 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\ColumnDiff, + Doctrine\DBAL\Schema\TableDiff; + +/** + * Event Arguments used when SQL queries for changing table columns are generated inside Doctrine\DBAL\Platform\*Platform. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Jan Sorgalla <jsorgalla@googlemail.com> + */ +class SchemaAlterTableChangeColumnEventArgs extends SchemaEventArgs +{ + /** + * @var \Doctrine\DBAL\Schema\ColumnDiff + */ + private $_columnDiff = null; + + /** + * @var \Doctrine\DBAL\Schema\TableDiff + */ + private $_tableDiff = null; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $_platform = null; + + /** + * @var array + */ + private $_sql = array(); + + /** + * @param \Doctrine\DBAL\Schema\ColumnDiff $columnDiff + * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function __construct(ColumnDiff $columnDiff, TableDiff $tableDiff, AbstractPlatform $platform) + { + $this->_columnDiff = $columnDiff; + $this->_tableDiff = $tableDiff; + $this->_platform = $platform; + } + + /** + * @return \Doctrine\DBAL\Schema\ColumnDiff + */ + public function getColumnDiff() + { + return $this->_columnDiff; + } + + /** + * @return \Doctrine\DBAL\Schema\TableDiff + */ + public function getTableDiff() + { + return $this->_tableDiff; + } + + /** + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getPlatform() + { + return $this->_platform; + } + + /** + * @param string|array $sql + * @return \Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs + */ + public function addSql($sql) + { + if (is_array($sql)) { + $this->_sql = array_merge($this->_sql, $sql); + } else { + $this->_sql[] = $sql; + } + + return $this; + } + + /** + * @return array + */ + public function getSql() + { + return $this->_sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php new file mode 100644 index 0000000..9f85338 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableEventArgs.php @@ -0,0 +1,99 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\TableDiff; + +/** + * Event Arguments used when SQL queries for creating tables are generated inside Doctrine\DBAL\Platform\*Platform. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Jan Sorgalla <jsorgalla@googlemail.com> + */ +class SchemaAlterTableEventArgs extends SchemaEventArgs +{ + /** + * @var \Doctrine\DBAL\Schema\TableDiff + */ + private $_tableDiff = null; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $_platform = null; + + /** + * @var array + */ + private $_sql = array(); + + /** + * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function __construct(TableDiff $tableDiff, AbstractPlatform $platform) + { + $this->_tableDiff = $tableDiff; + $this->_platform = $platform; + } + + /** + * @return \Doctrine\DBAL\Schema\TableDiff + */ + public function getTableDiff() + { + return $this->_tableDiff; + } + + /** + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getPlatform() + { + return $this->_platform; + } + + /** + * @param string|array $sql + * @return \Doctrine\DBAL\Event\SchemaAlterTableEventArgs + */ + public function addSql($sql) + { + if (is_array($sql)) { + $this->_sql = array_merge($this->_sql, $sql); + } else { + $this->_sql[] = $sql; + } + + return $this; + } + + /** + * @return array + */ + public function getSql() + { + return $this->_sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php new file mode 100644 index 0000000..4b981f8 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableRemoveColumnEventArgs.php @@ -0,0 +1,114 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\TableDiff; + +/** + * Event Arguments used when SQL queries for removing table columns are generated inside Doctrine\DBAL\Platform\*Platform. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Jan Sorgalla <jsorgalla@googlemail.com> + */ +class SchemaAlterTableRemoveColumnEventArgs extends SchemaEventArgs +{ + /** + * @var \Doctrine\DBAL\Schema\Column + */ + private $_column = null; + + /** + * @var \Doctrine\DBAL\Schema\TableDiff + */ + private $_tableDiff = null; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $_platform = null; + + /** + * @var array + */ + private $_sql = array(); + + /** + * @param \Doctrine\DBAL\Schema\Column $column + * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function __construct(Column $column, TableDiff $tableDiff, AbstractPlatform $platform) + { + $this->_column = $column; + $this->_tableDiff = $tableDiff; + $this->_platform = $platform; + } + + /** + * @return \Doctrine\DBAL\Schema\Column + */ + public function getColumn() + { + return $this->_column; + } + + /** + * @return \Doctrine\DBAL\Schema\TableDiff + */ + public function getTableDiff() + { + return $this->_tableDiff; + } + + /** + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getPlatform() + { + return $this->_platform; + } + + /** + * @param string|array $sql + * @return \Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs + */ + public function addSql($sql) + { + if (is_array($sql)) { + $this->_sql = array_merge($this->_sql, $sql); + } else { + $this->_sql[] = $sql; + } + + return $this; + } + + /** + * @return array + */ + public function getSql() + { + return $this->_sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php new file mode 100644 index 0000000..90e6a38 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/SchemaAlterTableRenameColumnEventArgs.php @@ -0,0 +1,129 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\TableDiff; + +/** + * Event Arguments used when SQL queries for renaming table columns are generated inside Doctrine\DBAL\Platform\*Platform. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Jan Sorgalla <jsorgalla@googlemail.com> + */ +class SchemaAlterTableRenameColumnEventArgs extends SchemaEventArgs +{ + /** + * @var string + */ + private $_oldColumnName = null; + + /** + * @var \Doctrine\DBAL\Schema\Column + */ + private $_column = null; + + /** + * @var \Doctrine\DBAL\Schema\TableDiff + */ + private $_tableDiff = null; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $_platform = null; + + /** + * @var array + */ + private $_sql = array(); + + /** + * @param string $oldColumnName + * @param \Doctrine\DBAL\Schema\Column $column + * @param \Doctrine\DBAL\Schema\TableDiff $tableDiff + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function __construct($oldColumnName, Column $column, TableDiff $tableDiff, AbstractPlatform $platform) + { + $this->_oldColumnName = $oldColumnName; + $this->_column = $column; + $this->_tableDiff = $tableDiff; + $this->_platform = $platform; + } + + /** + * @return string + */ + public function getOldColumnName() + { + return $this->_oldColumnName; + } + + /** + * @return \Doctrine\DBAL\Schema\Column + */ + public function getColumn() + { + return $this->_column; + } + + /** + * @return \Doctrine\DBAL\Schema\TableDiff + */ + public function getTableDiff() + { + return $this->_tableDiff; + } + + /** + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getPlatform() + { + return $this->_platform; + } + + /** + * @param string|array $sql + * @return \Doctrine\DBAL\Event\SchemaAlterTableRenameColumnEventArgs + */ + public function addSql($sql) + { + if (is_array($sql)) { + $this->_sql = array_merge($this->_sql, $sql); + } else { + $this->_sql[] = $sql; + } + + return $this; + } + + /** + * @return array + */ + public function getSql() + { + return $this->_sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php new file mode 100644 index 0000000..fecb015 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/SchemaColumnDefinitionEventArgs.php @@ -0,0 +1,137 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\DBAL\Connection, + Doctrine\DBAL\Schema\Column; + +/** + * Event Arguments used when the portable column definition is generated inside Doctrine\DBAL\Schema\AbstractSchemaManager. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Jan Sorgalla <jsorgalla@googlemail.com> + */ +class SchemaColumnDefinitionEventArgs extends SchemaEventArgs +{ + /** + * @var \Doctrine\DBAL\Schema\Column + */ + private $_column = null; + + /** + * Raw column data as fetched from the database + * + * @var array + */ + private $_tableColumn = null; + + /** + * @var string + */ + private $_table = null; + + /** + * @var string + */ + private $_database = null; + + /** + * @var \Doctrine\DBAL\Connection + */ + private $_connection = null; + + /** + * @param array $tableColumn + * @param string $table + * @param string $database + * @param \Doctrine\DBAL\Connection $conn + */ + public function __construct(array $tableColumn, $table, $database, Connection $connection) + { + $this->_tableColumn = $tableColumn; + $this->_table = $table; + $this->_database = $database; + $this->_connection = $connection; + } + + /** + * Allows to clear the column which means the column will be excluded from + * tables column list. + * + * @param null|\Doctrine\DBAL\Schema\Column $column + * @return SchemaColumnDefinitionEventArgs + */ + public function setColumn(Column $column = null) + { + $this->_column = $column; + + return $this; + } + + /** + * @return \Doctrine\DBAL\Schema\Column + */ + public function getColumn() + { + return $this->_column; + } + + /** + * @return array + */ + public function getTableColumn() + { + return $this->_tableColumn; + } + + /** + * @return string + */ + public function getTable() + { + return $this->_table; + } + + /** + * @return string + */ + public function getDatabase() + { + return $this->_database; + } + + /** + * @return \Doctrine\DBAL\Connection + */ + public function getConnection() + { + return $this->_connection; + } + + /** + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getDatabasePlatform() + { + return $this->_connection->getDatabasePlatform(); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php new file mode 100644 index 0000000..5e7383c --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/SchemaCreateTableColumnEventArgs.php @@ -0,0 +1,114 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\Table; + +/** + * Event Arguments used when SQL queries for creating table columns are generated inside Doctrine\DBAL\Platform\AbstractPlatform. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Jan Sorgalla <jsorgalla@googlemail.com> + */ +class SchemaCreateTableColumnEventArgs extends SchemaEventArgs +{ + /** + * @var \Doctrine\DBAL\Schema\Column + */ + private $_column = null; + + /** + * @var \Doctrine\DBAL\Schema\Table + */ + private $_table = null; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $_platform = null; + + /** + * @var array + */ + private $_sql = array(); + + /** + * @param \Doctrine\DBAL\Schema\Column $column + * @param \Doctrine\DBAL\Schema\Table $table + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function __construct(Column $column, Table $table, AbstractPlatform $platform) + { + $this->_column = $column; + $this->_table = $table; + $this->_platform = $platform; + } + + /** + * @return \Doctrine\DBAL\Schema\Column + */ + public function getColumn() + { + return $this->_column; + } + + /** + * @return \Doctrine\DBAL\Schema\Table + */ + public function getTable() + { + return $this->_table; + } + + /** + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getPlatform() + { + return $this->_platform; + } + + /** + * @param string|array $sql + * @return \Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs + */ + public function addSql($sql) + { + if (is_array($sql)) { + $this->_sql = array_merge($this->_sql, $sql); + } else { + $this->_sql[] = $sql; + } + + return $this; + } + + /** + * @return array + */ + public function getSql() + { + return $this->_sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php new file mode 100644 index 0000000..3149faa --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/SchemaCreateTableEventArgs.php @@ -0,0 +1,128 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Table; + +/** + * Event Arguments used when SQL queries for creating tables are generated inside Doctrine\DBAL\Platform\AbstractPlatform. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Jan Sorgalla <jsorgalla@googlemail.com> + */ +class SchemaCreateTableEventArgs extends SchemaEventArgs +{ + /** + * @var \Doctrine\DBAL\Schema\Table + */ + private $_table = null; + + /** + * @var array + */ + private $_columns = null; + + /** + * @var array + */ + private $_options = null; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $_platform = null; + + /** + * @var array + */ + private $_sql = array(); + + /** + * @param \Doctrine\DBAL\Schema\Table $table + * @param array $columns + * @param array $options + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function __construct(Table $table, array $columns, array $options, AbstractPlatform $platform) + { + $this->_table = $table; + $this->_columns = $columns; + $this->_options = $options; + $this->_platform = $platform; + } + + /** + * @return \Doctrine\DBAL\Schema\Table + */ + public function getTable() + { + return $this->_table; + } + + /** + * @return array + */ + public function getColumns() + { + return $this->_columns; + } + + /** + * @return array + */ + public function getOptions() + { + return $this->_options; + } + + /** + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getPlatform() + { + return $this->_platform; + } + + /** + * @param string|array $sql + * @return \Doctrine\DBAL\Event\SchemaCreateTableEventArgs + */ + public function addSql($sql) + { + if (is_array($sql)) { + $this->_sql = array_merge($this->_sql, $sql); + } else { + $this->_sql[] = $sql; + } + + return $this; + } + + /** + * @return array + */ + public function getSql() + { + return $this->_sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php new file mode 100644 index 0000000..55133be --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/SchemaDropTableEventArgs.php @@ -0,0 +1,98 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Table; + +/** + * Event Arguments used when the SQL query for dropping tables are generated inside Doctrine\DBAL\Platform\AbstractPlatform. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Jan Sorgalla <jsorgalla@googlemail.com> + */ +class SchemaDropTableEventArgs extends SchemaEventArgs +{ + /** + * @var string|\Doctrine\DBAL\Schema\Table + */ + private $_table = null; + + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $_platform = null; + + /** + * @var string + */ + private $_sql = null; + + /** + * @param string|\Doctrine\DBAL\Schema\Table $table + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function __construct($table, AbstractPlatform $platform) + { + if ( ! $table instanceof Table && !is_string($table)) { + throw new \InvalidArgumentException('SchemaCreateTableEventArgs expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + } + + $this->_table = $table; + $this->_platform = $platform; + } + + /** + * @return string|\Doctrine\DBAL\Schema\Table + */ + public function getTable() + { + return $this->_table; + } + + /** + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getPlatform() + { + return $this->_platform; + } + + /** + * @param string $sql + * @return \Doctrine\DBAL\Event\SchemaDropTableEventArgs + */ + public function setSql($sql) + { + $this->_sql = $sql; + + return $this; + } + + /** + * @return string + */ + public function getSql() + { + return $this->_sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/SchemaEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/SchemaEventArgs.php new file mode 100644 index 0000000..a3509fb --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/SchemaEventArgs.php @@ -0,0 +1,56 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\Common\EventArgs; + +/** + * Base class for schema related events. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Jan Sorgalla <jsorgalla@googlemail.com> + */ +class SchemaEventArgs extends EventArgs +{ + /** + * @var boolean + */ + private $_preventDefault = false; + + /** + * @return \Doctrine\DBAL\Event\SchemaEventArgs + */ + public function preventDefault() + { + $this->_preventDefault = true; + + return $this; + } + + /** + * @return boolean + */ + public function isDefaultPrevented() + { + return $this->_preventDefault; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php b/src/core/libs/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php new file mode 100644 index 0000000..248d43e --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Event/SchemaIndexDefinitionEventArgs.php @@ -0,0 +1,122 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Event; + +use Doctrine\DBAL\Connection, + Doctrine\DBAL\Schema\Index; + +/** + * Event Arguments used when the portable index definition is generated inside Doctrine\DBAL\Schema\AbstractSchemaManager. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.2 + * @author Jan Sorgalla <jsorgalla@googlemail.com> + */ +class SchemaIndexDefinitionEventArgs extends SchemaEventArgs +{ + /** + * @var \Doctrine\DBAL\Schema\Index + */ + private $_index = null; + + /** + * Raw index data as fetched from the database + * + * @var array + */ + private $_tableIndex = null; + + /** + * @var string + */ + private $_table = null; + + /** + * @var \Doctrine\DBAL\Connection + */ + private $_connection = null; + + /** + * @param array $tableIndex + * @param string $table + * @param \Doctrine\DBAL\Connection $conn + */ + public function __construct(array $tableIndex, $table, Connection $connection) + { + $this->_tableIndex = $tableIndex; + $this->_table = $table; + $this->_connection = $connection; + } + + /** + * Allows to clear the index which means the index will be excluded from + * tables index list. + * + * @param null|\Doctrine\DBAL\Schema\Index $index + * @return SchemaIndexDefinitionEventArgs + */ + public function setIndex(Index $index = null) + { + $this->_index = $index; + + return $this; + } + + /** + * @return \Doctrine\DBAL\Schema\Index + */ + public function getIndex() + { + return $this->_index; + } + + /** + * @return array + */ + public function getTableIndex() + { + return $this->_tableIndex; + } + + /** + * @return string + */ + public function getTable() + { + return $this->_table; + } + + /** + * @return \Doctrine\DBAL\Connection + */ + public function getConnection() + { + return $this->_connection; + } + + /** + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getDatabasePlatform() + { + return $this->_connection->getDatabasePlatform(); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Events.php b/src/core/libs/Doctrine/DBAL/Events.php new file mode 100644 index 0000000..0869dd9 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Events.php @@ -0,0 +1,48 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL; + +/** + * Container for all DBAL events. + * + * This class cannot be instantiated. + * + * @author Roman Borschel <roman@code-factory.org> + * @since 2.0 + */ +final class Events +{ + private function __construct() {} + + const postConnect = 'postConnect'; + + const onSchemaCreateTable = 'onSchemaCreateTable'; + const onSchemaCreateTableColumn = 'onSchemaCreateTableColumn'; + const onSchemaDropTable = 'onSchemaDropTable'; + const onSchemaAlterTable = 'onSchemaAlterTable'; + const onSchemaAlterTableAddColumn = 'onSchemaAlterTableAddColumn'; + const onSchemaAlterTableRemoveColumn = 'onSchemaAlterTableRemoveColumn'; + const onSchemaAlterTableChangeColumn = 'onSchemaAlterTableChangeColumn'; + const onSchemaAlterTableRenameColumn = 'onSchemaAlterTableRenameColumn'; + const onSchemaColumnDefinition = 'onSchemaColumnDefinition'; + const onSchemaIndexDefinition = 'onSchemaIndexDefinition'; +} diff --git a/src/core/libs/Doctrine/DBAL/Id/TableGenerator.php b/src/core/libs/Doctrine/DBAL/Id/TableGenerator.php new file mode 100644 index 0000000..c52a40b --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Id/TableGenerator.php @@ -0,0 +1,160 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Id; + +use Doctrine\DBAL\DriverManager; +use Doctrine\DBAL\Connection; + +/** + * Table ID Generator for those poor languages that are missing sequences. + * + * WARNING: The Table Id Generator clones a second independent database + * connection to work correctly. This means using the generator requests that + * generate IDs will have two open database connections. This is necessary to + * be safe from transaction failures in the main connection. Make sure to only + * ever use one TableGenerator otherwise you end up with many connections. + * + * TableID Generator does not work with SQLite. + * + * The TableGenerator does not take care of creating the SQL Table itself. You + * should look at the `TableGeneratorSchemaVisitor` to do this for you. + * Otherwise the schema for a table looks like: + * + * CREATE sequences ( + * sequence_name VARCHAR(255) NOT NULL, + * sequence_value INT NOT NULL DEFAULT '1', + * sequence_increment_by INT NOT NULL DEFAULT '1', + * PRIMARY KEY (table_name) + * ); + * + * Technically this generator works as follows: + * + * 1. Use a robust transaction serialization level. + * 2. Open transaction + * 3. Acquire a read lock on the table row (SELECT .. FOR UPDATE) + * 4. Increment current value by one and write back to database + * 5. Commit transaction + * + * If you are using a sequence_increment_by value that is larger than one the + * ID Generator will keep incrementing values until it hits the incrementation + * gap before issuing another query. + * + * If no row is present for a given sequence a new one will be created with the + * default values 'value' = 1 and 'increment_by' = 1 + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class TableGenerator +{ + /** + * @var \Doctrine\DBAL\Connection + */ + private $conn; + + /** + * @var string + */ + private $generatorTableName; + + /** + * @var array + */ + private $sequences = array(); + + /** + * @param Connection $conn + * @param string $generatorTableName + */ + public function __construct(Connection $conn, $generatorTableName = 'sequences') + { + $params = $conn->getParams(); + if ($params['driver'] == 'pdo_sqlite') { + throw new \Doctrine\DBAL\DBALException("Cannot use TableGenerator with SQLite."); + } + $this->conn = DriverManager::getConnection($params, $conn->getConfiguration(), $conn->getEventManager()); + $this->generatorTableName = $generatorTableName; + } + + /** + * Generate the next unused value for the given sequence name + * + * @param string + * @return int + */ + public function nextValue($sequenceName) + { + if (isset($this->sequences[$sequenceName])) { + $value = $this->sequences[$sequenceName]['value']; + $this->sequences[$sequenceName]['value']++; + if ($this->sequences[$sequenceName]['value'] >= $this->sequences[$sequenceName]['max']) { + unset ($this->sequences[$sequenceName]); + } + return $value; + } + + $this->conn->beginTransaction(); + + try { + $platform = $this->conn->getDatabasePlatform(); + $sql = "SELECT sequence_value, sequence_increment_by " . + "FROM " . $platform->appendLockHint($this->generatorTableName, \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE) . " " . + "WHERE sequence_name = ? " . $platform->getWriteLockSQL(); + $stmt = $this->conn->executeQuery($sql, array($sequenceName)); + + if ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) { + $row = array_change_key_case($row, CASE_LOWER); + + $value = $row['sequence_value']; + $value++; + + if ($row['sequence_increment_by'] > 1) { + $this->sequences[$sequenceName] = array( + 'value' => $value, + 'max' => $row['sequence_value'] + $row['sequence_increment_by'] + ); + } + + $sql = "UPDATE " . $this->generatorTableName . " ". + "SET sequence_value = sequence_value + sequence_increment_by " . + "WHERE sequence_name = ? AND sequence_value = ?"; + $rows = $this->conn->executeUpdate($sql, array($sequenceName, $row['sequence_value'])); + + if ($rows != 1) { + throw new \Doctrine\DBAL\DBALException("Race-condition detected while updating sequence. Aborting generation"); + } + } else { + $this->conn->insert( + $this->generatorTableName, + array('sequence_name' => $sequenceName, 'sequence_value' => 1, 'sequence_increment_by' => 1) + ); + $value = 1; + } + + $this->conn->commit(); + + } catch(\Exception $e) { + $this->conn->rollback(); + throw new \Doctrine\DBAL\DBALException("Error occured while generating ID with TableGenerator, aborted generation: " . $e->getMessage(), 0, $e); + } + + return $value; + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php b/src/core/libs/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php new file mode 100644 index 0000000..e340397 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Id/TableGeneratorSchemaVisitor.php @@ -0,0 +1,90 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Id; + +use Doctrine\DBAL\Schema\Table, + Doctrine\DBAL\Schema\Schema, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\ForeignKeyConstraint, + Doctrine\DBAL\Schema\Constraint, + Doctrine\DBAL\Schema\Sequence, + Doctrine\DBAL\Schema\Index; + +class TableGeneratorSchemaVisitor implements \Doctrine\DBAL\Schema\Visitor\Visitor +{ + /** + * @var string + */ + private $generatorTableName; + + public function __construct($generatorTableName = 'sequences') + { + $this->generatorTableName = $generatorTableName; + } + + /** + * @param Schema $schema + */ + public function acceptSchema(Schema $schema) + { + $table = $schema->createTable($this->generatorTableName); + $table->addColumn('sequence_name', 'string'); + $table->addColumn('sequence_value', 'integer', array('default' => 1)); + $table->addColumn('sequence_increment_by', 'integer', array('default' => 1)); + } + + /** + * @param Table $table + */ + public function acceptTable(Table $table) + { + } + + /** + * @param Column $column + */ + public function acceptColumn(Table $table, Column $column) + { + } + + /** + * @param Table $localTable + * @param ForeignKeyConstraint $fkConstraint + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + } + + /** + * @param Table $table + * @param Index $index + */ + public function acceptIndex(Table $table, Index $index) + { + } + + /** + * @param Sequence $sequence + */ + public function acceptSequence(Sequence $sequence) + { + } +} + diff --git a/src/core/libs/Doctrine/DBAL/LockMode.php b/src/core/libs/Doctrine/DBAL/LockMode.php new file mode 100644 index 0000000..52d87d2 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/LockMode.php @@ -0,0 +1,42 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL; + +/** + * Contains all DBAL LockModes + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 1.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Roman Borschel <roman@code-factory.org> + */ +class LockMode +{ + const NONE = 0; + const OPTIMISTIC = 1; + const PESSIMISTIC_READ = 2; + const PESSIMISTIC_WRITE = 4; + + final private function __construct() { } +} diff --git a/src/core/libs/Doctrine/DBAL/Logging/DebugStack.php b/src/core/libs/Doctrine/DBAL/Logging/DebugStack.php new file mode 100644 index 0000000..7d70b90 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Logging/DebugStack.php @@ -0,0 +1,69 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Logging; + +/** + * Includes executed SQLs in a Debug Stack + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class DebugStack implements SQLLogger +{ + /** @var array $queries Executed SQL queries. */ + public $queries = array(); + + /** @var boolean $enabled If Debug Stack is enabled (log queries) or not. */ + public $enabled = true; + + public $start = null; + + public $currentQuery = 0; + + /** + * {@inheritdoc} + */ + public function startQuery($sql, array $params = null, array $types = null) + { + if ($this->enabled) { + $this->start = microtime(true); + $this->queries[++$this->currentQuery] = array('sql' => $sql, 'params' => $params, 'types' => $types, 'executionMS' => 0); + } + } + + /** + * {@inheritdoc} + */ + public function stopQuery() + { + if ($this->enabled) { + $this->queries[$this->currentQuery]['executionMS'] = microtime(true) - $this->start; + } + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Logging/EchoSQLLogger.php b/src/core/libs/Doctrine/DBAL/Logging/EchoSQLLogger.php new file mode 100644 index 0000000..a332258 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Logging/EchoSQLLogger.php @@ -0,0 +1,61 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Logging; + +/** + * A SQL logger that logs to the standard output using echo/var_dump. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class EchoSQLLogger implements SQLLogger +{ + /** + * {@inheritdoc} + */ + public function startQuery($sql, array $params = null, array $types = null) + { + echo $sql . PHP_EOL; + + if ($params) { + var_dump($params); + } + + if ($types) { + var_dump($types); + } + } + + /** + * {@inheritdoc} + */ + public function stopQuery() + { + + } +} diff --git a/src/core/libs/Doctrine/DBAL/Logging/LoggerChain.php b/src/core/libs/Doctrine/DBAL/Logging/LoggerChain.php new file mode 100644 index 0000000..6725cc5 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Logging/LoggerChain.php @@ -0,0 +1,64 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Logging; + +/** + * Chains multiple SQLLogger + * + * + * @link www.doctrine-project.org + * @since 2.2 + * @author Christophe Coevoet <stof@notk.org> + */ +class LoggerChain implements SQLLogger +{ + private $loggers = array(); + + /** + * Adds a logger in the chain + * + * @param SQLLogger $logger + */ + public function addLogger(SQLLogger $logger) + { + $this->loggers[] = $logger; + } + + /** + * {@inheritdoc} + */ + public function startQuery($sql, array $params = null, array $types = null) + { + foreach ($this->loggers as $logger) { + $logger->startQuery($sql, $params, $types); + } + } + + /** + * {@inheritdoc} + */ + public function stopQuery() + { + foreach ($this->loggers as $logger) { + $logger->stopQuery(); + } + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Logging/SQLLogger.php b/src/core/libs/Doctrine/DBAL/Logging/SQLLogger.php new file mode 100644 index 0000000..9564f4c --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Logging/SQLLogger.php @@ -0,0 +1,54 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Logging; + +/** + * Interface for SQL loggers. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +interface SQLLogger +{ + /** + * Logs a SQL statement somewhere. + * + * @param string $sql The SQL to be executed. + * @param array $params The SQL parameters. + * @param array $types The SQL parameter types. + * @return void + */ + public function startQuery($sql, array $params = null, array $types = null); + + /** + * Mark the last started query as stopped. This can be used for timing of queries. + * + * @return void + */ + public function stopQuery(); +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/AbstractPlatform.php b/src/core/libs/Doctrine/DBAL/Platforms/AbstractPlatform.php new file mode 100644 index 0000000..b983c4a --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/AbstractPlatform.php @@ -0,0 +1,2854 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\DBALException, + Doctrine\DBAL\Connection, + Doctrine\DBAL\Types, + Doctrine\DBAL\Schema\Constraint, + Doctrine\DBAL\Schema\Sequence, + Doctrine\DBAL\Schema\Table, + Doctrine\DBAL\Schema\Index, + Doctrine\DBAL\Schema\ForeignKeyConstraint, + Doctrine\DBAL\Schema\TableDiff, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\ColumnDiff, + Doctrine\DBAL\Types\Type, + Doctrine\DBAL\Events, + Doctrine\Common\EventManager, + Doctrine\DBAL\Event\SchemaCreateTableEventArgs, + Doctrine\DBAL\Event\SchemaCreateTableColumnEventArgs, + Doctrine\DBAL\Event\SchemaDropTableEventArgs, + Doctrine\DBAL\Event\SchemaAlterTableEventArgs, + Doctrine\DBAL\Event\SchemaAlterTableAddColumnEventArgs, + Doctrine\DBAL\Event\SchemaAlterTableRemoveColumnEventArgs, + Doctrine\DBAL\Event\SchemaAlterTableChangeColumnEventArgs, + Doctrine\DBAL\Event\SchemaAlterTableRenameColumnEventArgs; + +/** + * Base class for all DatabasePlatforms. The DatabasePlatforms are the central + * point of abstraction of platform-specific behaviors, features and SQL dialects. + * They are a passive source of information. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @todo Remove any unnecessary methods. + */ +abstract class AbstractPlatform +{ + /** + * @var integer + */ + const CREATE_INDEXES = 1; + + /** + * @var integer + */ + const CREATE_FOREIGNKEYS = 2; + + /** + * @var integer + */ + const TRIM_UNSPECIFIED = 0; + + /** + * @var integer + */ + const TRIM_LEADING = 1; + + /** + * @var integer + */ + const TRIM_TRAILING = 2; + + /** + * @var integer + */ + const TRIM_BOTH = 3; + + /** + * @var array + */ + protected $doctrineTypeMapping = null; + + /** + * Contains a list of all columns that should generate parseable column comments for type-detection + * in reverse engineering scenarios. + * + * @var array + */ + protected $doctrineTypeComments = null; + + /** + * @var Doctrine\Common\EventManager + */ + protected $_eventManager; + + /** + * Holds the KeywordList instance for the current platform. + * + * @var \Doctrine\DBAL\Platforms\Keywords\KeywordList + */ + protected $_keywords; + + /** + * Constructor. + */ + public function __construct() {} + + /** + * Sets the EventManager used by the Platform. + * + * @param \Doctrine\Common\EventManager + */ + public function setEventManager(EventManager $eventManager) + { + $this->_eventManager = $eventManager; + } + + /** + * Gets the EventManager used by the Platform. + * + * @return \Doctrine\Common\EventManager + */ + public function getEventManager() + { + return $this->_eventManager; + } + + /** + * Gets the SQL snippet that declares a boolean column. + * + * @param array $columnDef + * + * @return string + */ + abstract public function getBooleanTypeDeclarationSQL(array $columnDef); + + /** + * Gets the SQL snippet that declares a 4 byte integer column. + * + * @param array $columnDef + * + * @return string + */ + abstract public function getIntegerTypeDeclarationSQL(array $columnDef); + + /** + * Gets the SQL snippet that declares an 8 byte integer column. + * + * @param array $columnDef + * + * @return string + */ + abstract public function getBigIntTypeDeclarationSQL(array $columnDef); + + /** + * Gets the SQL snippet that declares a 2 byte integer column. + * + * @param array $columnDef + * + * @return string + */ + abstract public function getSmallIntTypeDeclarationSQL(array $columnDef); + + /** + * Gets the SQL snippet that declares common properties of an integer column. + * + * @param array $columnDef + * @return string + */ + abstract protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef); + + /** + * Lazy load Doctrine Type Mappings + * + * @return void + */ + abstract protected function initializeDoctrineTypeMappings(); + + /** + * Initialize Doctrine Type Mappings with the platform defaults + * and with all additional type mappings. + */ + private function initializeAllDoctrineTypeMappings() + { + $this->initializeDoctrineTypeMappings(); + + foreach (Type::getTypesMap() as $typeName => $className) { + foreach (Type::getType($typeName)->getMappedDatabaseTypes($this) as $dbType) { + $this->doctrineTypeMapping[$dbType] = $typeName; + } + } + } + + /** + * Gets the SQL snippet used to declare a VARCHAR column type. + * + * @param array $field + * + * @return string + */ + public function getVarcharTypeDeclarationSQL(array $field) + { + if ( !isset($field['length'])) { + $field['length'] = $this->getVarcharDefaultLength(); + } + + $fixed = (isset($field['fixed'])) ? $field['fixed'] : false; + + if ($field['length'] > $this->getVarcharMaxLength()) { + return $this->getClobTypeDeclarationSQL($field); + } + + return $this->getVarcharTypeDeclarationSQLSnippet($field['length'], $fixed); + } + + /** + * Get the SQL Snippet to create a GUID/UUID field. + * + * By default this maps directly to a VARCHAR and only maps to more + * special datatypes when the underlying databases support this datatype. + * + * @param array $field + * + * @return string + */ + public function getGuidTypeDeclarationSQL(array $field) + { + return $this->getVarcharTypeDeclarationSQL($field); + } + + /** + * @param integer $length + * @param boolean $fixed + * + * @return string + * + * @throws \Doctrine\DBAL\DBALException + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + throw DBALException::notSupported('VARCHARs not supported by Platform.'); + } + + /** + * Gets the SQL snippet used to declare a CLOB column type. + * + * @param array $field + * + * @return string + */ + abstract public function getClobTypeDeclarationSQL(array $field); + + /** + * Gets the SQL Snippet used to declare a BLOB column type. + * + * @param array $field + * + * @return string + */ + abstract public function getBlobTypeDeclarationSQL(array $field); + + /** + * Gets the name of the platform. + * + * @return string + */ + abstract public function getName(); + + /** + * Register a doctrine type to be used in conjunction with a column type of this platform. + * + * @param string $dbType + * @param string $doctrineType + * + * @throws \Doctrine\DBAL\DBALException if the type is not found + */ + public function registerDoctrineTypeMapping($dbType, $doctrineType) + { + if ($this->doctrineTypeMapping === null) { + $this->initializeAllDoctrineTypeMappings(); + } + + if (!Types\Type::hasType($doctrineType)) { + throw DBALException::typeNotFound($doctrineType); + } + + $dbType = strtolower($dbType); + $this->doctrineTypeMapping[$dbType] = $doctrineType; + } + + /** + * Get the Doctrine type that is mapped for the given database column type. + * + * @param string $dbType + * + * @return string + */ + public function getDoctrineTypeMapping($dbType) + { + if ($this->doctrineTypeMapping === null) { + $this->initializeAllDoctrineTypeMappings(); + } + + $dbType = strtolower($dbType); + + if (!isset($this->doctrineTypeMapping[$dbType])) { + throw new \Doctrine\DBAL\DBALException("Unknown database type ".$dbType." requested, " . get_class($this) . " may not support it."); + } + + return $this->doctrineTypeMapping[$dbType]; + } + + /** + * Check if a database type is currently supported by this platform. + * + * @param string $dbType + * + * @return boolean + */ + public function hasDoctrineTypeMappingFor($dbType) + { + if ($this->doctrineTypeMapping === null) { + $this->initializeAllDoctrineTypeMappings(); + } + + $dbType = strtolower($dbType); + return isset($this->doctrineTypeMapping[$dbType]); + } + + /** + * Initialize the Doctrine Type comments instance variable for in_array() checks. + * + * @return void + */ + protected function initializeCommentedDoctrineTypes() + { + $this->doctrineTypeComments = array(); + + foreach (Type::getTypesMap() as $typeName => $className) { + $type = Type::getType($typeName); + + if ($type->requiresSQLCommentHint($this)) { + $this->doctrineTypeComments[] = $typeName; + } + } + } + + /** + * Is it necessary for the platform to add a parsable type comment to allow reverse engineering the given type? + * + * @param Type $doctrineType + * + * @return boolean + */ + public function isCommentedDoctrineType(Type $doctrineType) + { + if ($this->doctrineTypeComments === null) { + $this->initializeCommentedDoctrineTypes(); + } + + return in_array($doctrineType->getName(), $this->doctrineTypeComments); + } + + /** + * Mark this type as to be commented in ALTER TABLE and CREATE TABLE statements. + * + * @param string|Type $doctrineType + * + * @return void + */ + public function markDoctrineTypeCommented($doctrineType) + { + if ($this->doctrineTypeComments === null) { + $this->initializeCommentedDoctrineTypes(); + } + + $this->doctrineTypeComments[] = $doctrineType instanceof Type ? $doctrineType->getName() : $doctrineType; + } + + /** + * Get the comment to append to a column comment that helps parsing this type in reverse engineering. + * + * @param Type $doctrineType + * @return string + */ + public function getDoctrineTypeComment(Type $doctrineType) + { + return '(DC2Type:' . $doctrineType->getName() . ')'; + } + + /** + * Return the comment of a passed column modified by potential doctrine type comment hints. + * + * @param Column $column + * @return string + */ + protected function getColumnComment(Column $column) + { + $comment = $column->getComment(); + + if ($this->isCommentedDoctrineType($column->getType())) { + $comment .= $this->getDoctrineTypeComment($column->getType()); + } + + return $comment; + } + + /** + * Gets the character used for identifier quoting. + * + * @return string + */ + public function getIdentifierQuoteCharacter() + { + return '"'; + } + + /** + * Gets the string portion that starts an SQL comment. + * + * @return string + */ + public function getSqlCommentStartString() + { + return "--"; + } + + /** + * Gets the string portion that ends an SQL comment. + * + * @return string + */ + public function getSqlCommentEndString() + { + return "\n"; + } + + /** + * Gets the maximum length of a varchar field. + * + * @return integer + */ + public function getVarcharMaxLength() + { + return 4000; + } + + /** + * Gets the default length of a varchar field. + * + * @return integer + */ + public function getVarcharDefaultLength() + { + return 255; + } + + /** + * Gets all SQL wildcard characters of the platform. + * + * @return array + */ + public function getWildcards() + { + return array('%', '_'); + } + + /** + * Returns the regular expression operator. + * + * @return string + */ + public function getRegexpExpression() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns global unique identifier + * + * @return string to get global unique identifier + */ + public function getGuidExpression() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the average value of a column + * + * @param string $column the column to use + * + * @return string generated sql including an AVG aggregate function + */ + public function getAvgExpression($column) + { + return 'AVG(' . $column . ')'; + } + + /** + * Returns the number of rows (without a NULL value) of a column + * + * If a '*' is used instead of a column the number of selected rows + * is returned. + * + * @param string|integer $column the column to use + * + * @return string generated sql including a COUNT aggregate function + */ + public function getCountExpression($column) + { + return 'COUNT(' . $column . ')'; + } + + /** + * Returns the highest value of a column + * + * @param string $column the column to use + * @return string generated sql including a MAX aggregate function + */ + public function getMaxExpression($column) + { + return 'MAX(' . $column . ')'; + } + + /** + * Returns the lowest value of a column + * + * @param string $column the column to use + * @return string + */ + public function getMinExpression($column) + { + return 'MIN(' . $column . ')'; + } + + /** + * Returns the total sum of a column + * + * @param string $column the column to use + * @return string + */ + public function getSumExpression($column) + { + return 'SUM(' . $column . ')'; + } + + // scalar functions + + /** + * Returns the md5 sum of a field. + * + * Note: Not SQL92, but common functionality + * + * @param string $column + * @return string + */ + public function getMd5Expression($column) + { + return 'MD5(' . $column . ')'; + } + + /** + * Returns the length of a text field. + * + * @param string $column + * + * @return string + */ + public function getLengthExpression($column) + { + return 'LENGTH(' . $column . ')'; + } + + /** + * Returns the squared value of a column + * + * @param string $column the column to use + * + * @return string generated sql including an SQRT aggregate function + */ + public function getSqrtExpression($column) + { + return 'SQRT(' . $column . ')'; + } + + /** + * Rounds a numeric field to the number of decimals specified. + * + * @param string $column + * @param integer $decimals + * + * @return string + */ + public function getRoundExpression($column, $decimals = 0) + { + return 'ROUND(' . $column . ', ' . $decimals . ')'; + } + + /** + * Returns the remainder of the division operation + * $expression1 / $expression2. + * + * @param string $expression1 + * @param string $expression2 + * + * @return string + */ + public function getModExpression($expression1, $expression2) + { + return 'MOD(' . $expression1 . ', ' . $expression2 . ')'; + } + + /** + * Trim a string, leading/trailing/both and with a given char which defaults to space. + * + * @param string $str + * @param integer $pos + * @param string $char has to be quoted already + * + * @return string + */ + public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) + { + $posStr = ''; + $trimChar = ($char != false) ? $char . ' FROM ' : ''; + + switch ($pos) { + case self::TRIM_LEADING: + $posStr = 'LEADING '.$trimChar; + break; + + case self::TRIM_TRAILING: + $posStr = 'TRAILING '.$trimChar; + break; + + case self::TRIM_BOTH: + $posStr = 'BOTH '.$trimChar; + break; + } + + return 'TRIM(' . $posStr . $str . ')'; + } + + /** + * rtrim + * returns the string $str with proceeding space characters removed + * + * @param string $str literal string or column name + * + * @return string + */ + public function getRtrimExpression($str) + { + return 'RTRIM(' . $str . ')'; + } + + /** + * ltrim + * returns the string $str with leading space characters removed + * + * @param string $str literal string or column name + * + * @return string + */ + public function getLtrimExpression($str) + { + return 'LTRIM(' . $str . ')'; + } + + /** + * upper + * Returns the string $str with all characters changed to + * uppercase according to the current character set mapping. + * + * @param string $str literal string or column name + * + * @return string + */ + public function getUpperExpression($str) + { + return 'UPPER(' . $str . ')'; + } + + /** + * lower + * Returns the string $str with all characters changed to + * lowercase according to the current character set mapping. + * + * @param string $str literal string or column name + * + * @return string + */ + public function getLowerExpression($str) + { + return 'LOWER(' . $str . ')'; + } + + /** + * returns the position of the first occurrence of substring $substr in string $str + * + * @param string $str literal string + * @param string $substr literal string to find + * @param integer $startPos position to start at, beginning of string by default + * + * @return string + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Returns the current system date. + * + * @return string + */ + public function getNowExpression() + { + return 'NOW()'; + } + + /** + * return string to call a function to get a substring inside an SQL statement + * + * Note: Not SQL92, but common functionality. + * + * SQLite only supports the 2 parameter variant of this function + * + * @param string $value an sql string literal or column name/alias + * @param integer $from where to start the substring portion + * @param integer $length the substring portion length + * + * @return string + */ + public function getSubstringExpression($value, $from, $length = null) + { + if ($length === null) { + return 'SUBSTRING(' . $value . ' FROM ' . $from . ')'; + } + + return 'SUBSTRING(' . $value . ' FROM ' . $from . ' FOR ' . $length . ')'; + } + + /** + * Returns a series of strings concatinated + * + * concat() accepts an arbitrary number of parameters. Each parameter + * must contain an expression + * + * @param string $arg1, $arg2 ... $argN strings that will be concatenated. + * + * @return string + */ + public function getConcatExpression() + { + return join(' || ' , func_get_args()); + } + + /** + * Returns the SQL for a logical not. + * + * Example: + * <code> + * $q = new Doctrine_Query(); + * $e = $q->expr; + * $q->select('*')->from('table') + * ->where($e->eq('id', $e->not('null')); + * </code> + * + * @param string $expression + * + * @return string a logical expression + */ + public function getNotExpression($expression) + { + return 'NOT(' . $expression . ')'; + } + + /** + * Returns the SQL to check if a value is one in a set of + * given values. + * + * in() accepts an arbitrary number of parameters. The first parameter + * must always specify the value that should be matched against. Successive + * must contain a logical expression or an array with logical expressions. + * These expressions will be matched against the first parameter. + * + * @param string $column the value that should be matched against + * @param string|array<string> $values values that will be matched against $column + * + * @return string logical expression + */ + public function getInExpression($column, $values) + { + if ( ! is_array($values)) { + $values = array($values); + } + + // TODO: fix this code: the method does not exist + $values = $this->getIdentifiers($values); + + if (count($values) == 0) { + throw new \InvalidArgumentException('Values must not be empty.'); + } + + return $column . ' IN (' . implode(', ', $values) . ')'; + } + + /** + * Returns SQL that checks if a expression is null. + * + * @param string $expression the expression that should be compared to null + * + * @return string logical expression + */ + public function getIsNullExpression($expression) + { + return $expression . ' IS NULL'; + } + + /** + * Returns SQL that checks if a expression is not null. + * + * @param string $expression the expression that should be compared to null + * + * @return string logical expression + */ + public function getIsNotNullExpression($expression) + { + return $expression . ' IS NOT NULL'; + } + + /** + * Returns SQL that checks if an expression evaluates to a value between + * two values. + * + * The parameter $expression is checked if it is between $value1 and $value2. + * + * Note: There is a slight difference in the way BETWEEN works on some databases. + * http://www.w3schools.com/sql/sql_between.asp. If you want complete database + * independence you should avoid using between(). + * + * @param string $expression the value to compare to + * @param string $value1 the lower value to compare with + * @param string $value2 the higher value to compare with + * + * @return string logical expression + */ + public function getBetweenExpression($expression, $value1, $value2) + { + return $expression . ' BETWEEN ' .$value1 . ' AND ' . $value2; + } + + public function getAcosExpression($value) + { + return 'ACOS(' . $value . ')'; + } + + public function getSinExpression($value) + { + return 'SIN(' . $value . ')'; + } + + public function getPiExpression() + { + return 'PI()'; + } + + public function getCosExpression($value) + { + return 'COS(' . $value . ')'; + } + + /** + * Calculate the difference in days between the two passed dates. + * + * Computes diff = date1 - date2 + * + * @param string $date1 + * @param string $date2 + * + * @return string + */ + public function getDateDiffExpression($date1, $date2) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Add the number of given days to a date. + * + * @param string $date + * @param integer $days + * + * @return string + */ + public function getDateAddDaysExpression($date, $days) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Substract the number of given days to a date. + * + * @param string $date + * @param integer $days + * + * @return string + */ + public function getDateSubDaysExpression($date, $days) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Add the number of given months to a date. + * + * @param string $date + * @param integer $months + * + * @return string + */ + public function getDateAddMonthExpression($date, $months) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Substract the number of given months to a date. + * + * @param string $date + * @param integer $months + * + * @return string + */ + public function getDateSubMonthExpression($date, $months) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Gets SQL bit AND comparison expression + * + * @param string $value1 + * @param string $value2 + * + * @return string + */ + public function getBitAndComparisonExpression($value1, $value2) + { + return '(' . $value1 . ' & ' . $value2 . ')'; + } + + /** + * Gets SQL bit OR comparison expression + * + * @param string $value1 + * @param string $value2 + * + * @return string + */ + public function getBitOrComparisonExpression($value1, $value2) + { + return '(' . $value1 . ' | ' . $value2 . ')'; + } + + public function getForUpdateSQL() + { + return 'FOR UPDATE'; + } + + /** + * Honors that some SQL vendors such as MsSql use table hints for locking instead of the ANSI SQL FOR UPDATE specification. + * + * @param string $fromClause + * @param integer $lockMode + * + * @return string + */ + public function appendLockHint($fromClause, $lockMode) + { + return $fromClause; + } + + /** + * Get the sql snippet to append to any SELECT statement which locks rows in shared read lock. + * + * This defaults to the ASNI SQL "FOR UPDATE", which is an exclusive lock (Write). Some database + * vendors allow to lighten this constraint up to be a real read lock. + * + * @return string + */ + public function getReadLockSQL() + { + return $this->getForUpdateSQL(); + } + + /** + * Get the SQL snippet to append to any SELECT statement which obtains an exclusive lock on the rows. + * + * The semantics of this lock mode should equal the SELECT .. FOR UPDATE of the ASNI SQL standard. + * + * @return string + */ + public function getWriteLockSQL() + { + return $this->getForUpdateSQL(); + } + + /** + * Get the SQL snippet to drop an existing database + * + * @param string $database name of the database that should be dropped + * + * @return string + */ + public function getDropDatabaseSQL($database) + { + return 'DROP DATABASE ' . $database; + } + + /** + * Drop a Table + * + * @throws \InvalidArgumentException + * + * @param Table|string $table + * + * @return string + */ + public function getDropTableSQL($table) + { + $tableArg = $table; + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } else if(!is_string($table)) { + throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + } + + if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaDropTable)) { + $eventArgs = new SchemaDropTableEventArgs($tableArg, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaDropTable, $eventArgs); + + if ($eventArgs->isDefaultPrevented()) { + return $eventArgs->getSql(); + } + } + + return 'DROP TABLE ' . $table; + } + + /** + * Get SQL to safely drop a temporary table WITHOUT implicitly committing an open transaction. + * + * @param Table|string $table + * + * @return string + */ + public function getDropTemporaryTableSQL($table) + { + return $this->getDropTableSQL($table); + } + + /** + * Drop index from a table + * + * @param Index|string $name + * @param string|Table $table + * + * @return string + */ + public function getDropIndexSQL($index, $table = null) + { + if ($index instanceof Index) { + $index = $index->getQuotedName($this); + } else if(!is_string($index)) { + throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); + } + + return 'DROP INDEX ' . $index; + } + + /** + * Get drop constraint sql + * + * @param \Doctrine\DBAL\Schema\Constraint $constraint + * @param string|Table $table + * + * @return string + */ + public function getDropConstraintSQL($constraint, $table) + { + if ($constraint instanceof Constraint) { + $constraint = $constraint->getQuotedName($this); + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $constraint; + } + + /** + * @param ForeignKeyConstraint|string $foreignKey + * @param Table|string $table + * + * @return string + */ + public function getDropForeignKeySQL($foreignKey, $table) + { + if ($foreignKey instanceof ForeignKeyConstraint) { + $foreignKey = $foreignKey->getQuotedName($this); + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return 'ALTER TABLE ' . $table . ' DROP FOREIGN KEY ' . $foreignKey; + } + + /** + * Gets the SQL statement(s) to create a table with the specified name, columns and constraints + * on this platform. + * + * @param string $table The name of the table. + * @param integer $createFlags + * + * @return array The sequence of SQL statements. + */ + public function getCreateTableSQL(Table $table, $createFlags = self::CREATE_INDEXES) + { + if ( ! is_int($createFlags)) { + throw new \InvalidArgumentException("Second argument of AbstractPlatform::getCreateTableSQL() has to be integer."); + } + + if (count($table->getColumns()) === 0) { + throw DBALException::noColumnsSpecifiedForTable($table->getName()); + } + + $tableName = $table->getQuotedName($this); + $options = $table->getOptions(); + $options['uniqueConstraints'] = array(); + $options['indexes'] = array(); + $options['primary'] = array(); + + if (($createFlags&self::CREATE_INDEXES) > 0) { + foreach ($table->getIndexes() as $index) { + /* @var $index Index */ + if ($index->isPrimary()) { + $options['primary'] = $index->getColumns(); + $options['primary_index'] = $index; + } else { + $options['indexes'][$index->getName()] = $index; + } + } + } + + $columnSql = array(); + $columns = array(); + + foreach ($table->getColumns() as $column) { + /* @var \Doctrine\DBAL\Schema\Column $column */ + + if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTableColumn)) { + $eventArgs = new SchemaCreateTableColumnEventArgs($column, $table, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaCreateTableColumn, $eventArgs); + + $columnSql = array_merge($columnSql, $eventArgs->getSql()); + + if ($eventArgs->isDefaultPrevented()) { + continue; + } + } + + $columnData = array(); + $columnData['name'] = $column->getQuotedName($this); + $columnData['type'] = $column->getType(); + $columnData['length'] = $column->getLength(); + $columnData['notnull'] = $column->getNotNull(); + $columnData['fixed'] = $column->getFixed(); + $columnData['unique'] = false; // TODO: what do we do about this? + $columnData['version'] = $column->hasPlatformOption("version") ? $column->getPlatformOption('version') : false; + + if (strtolower($columnData['type']) == "string" && $columnData['length'] === null) { + $columnData['length'] = 255; + } + + $columnData['unsigned'] = $column->getUnsigned(); + $columnData['precision'] = $column->getPrecision(); + $columnData['scale'] = $column->getScale(); + $columnData['default'] = $column->getDefault(); + $columnData['columnDefinition'] = $column->getColumnDefinition(); + $columnData['autoincrement'] = $column->getAutoincrement(); + $columnData['comment'] = $this->getColumnComment($column); + + if (in_array($column->getName(), $options['primary'])) { + $columnData['primary'] = true; + } + + $columns[$columnData['name']] = $columnData; + } + + if (($createFlags&self::CREATE_FOREIGNKEYS) > 0) { + $options['foreignKeys'] = array(); + foreach ($table->getForeignKeys() as $fkConstraint) { + $options['foreignKeys'][] = $fkConstraint; + } + } + + if (null !== $this->_eventManager && $this->_eventManager->hasListeners(Events::onSchemaCreateTable)) { + $eventArgs = new SchemaCreateTableEventArgs($table, $columns, $options, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaCreateTable, $eventArgs); + + if ($eventArgs->isDefaultPrevented()) { + return array_merge($eventArgs->getSql(), $columnSql); + } + } + + $sql = $this->_getCreateTableSQL($tableName, $columns, $options); + if ($this->supportsCommentOnStatement()) { + foreach ($table->getColumns() as $column) { + if ($this->getColumnComment($column)) { + $sql[] = $this->getCommentOnColumnSQL($tableName, $column->getName(), $this->getColumnComment($column)); + } + } + } + + return array_merge($sql, $columnSql); + } + + public function getCommentOnColumnSQL($tableName, $columnName, $comment) + { + return "COMMENT ON COLUMN " . $tableName . "." . $columnName . " IS '" . $comment . "'"; + } + + /** + * Gets the SQL used to create a table. + * + * @param string $tableName + * @param array $columns + * @param array $options + * + * @return array + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) + { + $columnListSql = $this->getColumnDeclarationListSQL($columns); + + if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) { + foreach ($options['uniqueConstraints'] as $name => $definition) { + $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition); + } + } + + if (isset($options['primary']) && ! empty($options['primary'])) { + $columnListSql .= ', PRIMARY KEY(' . implode(', ', array_unique(array_values($options['primary']))) . ')'; + } + + if (isset($options['indexes']) && ! empty($options['indexes'])) { + foreach($options['indexes'] as $index => $definition) { + $columnListSql .= ', ' . $this->getIndexDeclarationSQL($index, $definition); + } + } + + $query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql; + + $check = $this->getCheckDeclarationSQL($columns); + if ( ! empty($check)) { + $query .= ', ' . $check; + } + $query .= ')'; + + $sql[] = $query; + + if (isset($options['foreignKeys'])) { + foreach ((array) $options['foreignKeys'] as $definition) { + $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); + } + } + + return $sql; + } + + public function getCreateTemporaryTableSnippetSQL() + { + return "CREATE TEMPORARY TABLE"; + } + + /** + * Gets the SQL to create a sequence on this platform. + * + * @param \Doctrine\DBAL\Schema\Sequence $sequence + * + * @return string + * + * @throws DBALException + */ + public function getCreateSequenceSQL(Sequence $sequence) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Gets the SQL statement to change a sequence on this platform. + * + * @param \Doctrine\DBAL\Schema\Sequence $sequence + * + * @return string + */ + public function getAlterSequenceSQL(Sequence $sequence) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Gets the SQL to create a constraint on a table on this platform. + * + * @param \Doctrine\DBAL\Schema\Constraint $constraint + * @param string|Table $table + * + * @return string + */ + public function getCreateConstraintSQL(Constraint $constraint, $table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + $query = 'ALTER TABLE ' . $table . ' ADD CONSTRAINT ' . $constraint->getQuotedName($this); + + $columns = array(); + foreach ($constraint->getColumns() as $column) { + $columns[] = $column; + } + $columnList = '('. implode(', ', $columns) . ')'; + + $referencesClause = ''; + if ($constraint instanceof Index) { + if($constraint->isPrimary()) { + $query .= ' PRIMARY KEY'; + } elseif ($constraint->isUnique()) { + $query .= ' UNIQUE'; + } else { + throw new \InvalidArgumentException( + 'Can only create primary or unique constraints, no common indexes with getCreateConstraintSQL().' + ); + } + } else if ($constraint instanceof ForeignKeyConstraint) { + $query .= ' FOREIGN KEY'; + + $foreignColumns = array(); + foreach ($constraint->getForeignColumns() as $column) { + $foreignColumns[] = $column; + } + + $referencesClause = ' REFERENCES '.$constraint->getForeignTableName(). ' ('.implode(', ', $foreignColumns).')'; + } + $query .= ' '.$columnList.$referencesClause; + + return $query; + } + + /** + * Gets the SQL to create an index on a table on this platform. + * + * @param Index $index + * @param string|Table $table name of the table on which the index is to be created + * + * @return string + */ + public function getCreateIndexSQL(Index $index, $table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + $name = $index->getQuotedName($this); + $columns = $index->getColumns(); + + if (count($columns) == 0) { + throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); + } + + if ($index->isPrimary()) { + return $this->getCreatePrimaryKeySQL($index, $table); + } + + $query = 'CREATE ' . $this->getCreateIndexSQLFlags($index) . 'INDEX ' . $name . ' ON ' . $table; + $query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')'; + + return $query; + } + + /** + * Adds additional flags for index generation + * + * @param Index $index + * + * @return string + */ + protected function getCreateIndexSQLFlags(Index $index) + { + return $index->isUnique() ? 'UNIQUE ' : ''; + } + + /** + * Get SQL to create an unnamed primary key constraint. + * + * @param Index $index + * @param string|Table $table + * + * @return string + */ + public function getCreatePrimaryKeySQL(Index $index, $table) + { + return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY (' . $this->getIndexFieldDeclarationListSQL($index->getColumns()) . ')'; + } + + /** + * Quotes a string so that it can be safely used as a table or column name, + * even if it is a reserved word of the platform. This also detects identifier + * chains separated by dot and quotes them independently. + * + * NOTE: Just because you CAN use quoted identifiers doesn't mean + * you SHOULD use them. In general, they end up causing way more + * problems than they solve. + * + * @param string $str identifier name to be quoted + * + * @return string quoted identifier string + */ + public function quoteIdentifier($str) + { + if (strpos($str, ".") !== false) { + $parts = array_map(array($this, "quoteIdentifier"), explode(".", $str)); + + return implode(".", $parts); + } + + return $this->quoteSingleIdentifier($str); + } + + /** + * Quote a single identifier (no dot chain separation) + * + * @param string $str + * + * @return string + */ + public function quoteSingleIdentifier($str) + { + $c = $this->getIdentifierQuoteCharacter(); + + return $c . str_replace($c, $c.$c, $str) . $c; + } + + /** + * Create a new foreign key + * + * @param ForeignKeyConstraint $foreignKey ForeignKey instance + * @param string|Table $table name of the table on which the foreign key is to be created + * + * @return string + */ + public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + $query = 'ALTER TABLE ' . $table . ' ADD ' . $this->getForeignKeyDeclarationSQL($foreignKey); + + return $query; + } + + /** + * Gets the sql statements for altering an existing table. + * + * The method returns an array of sql statements, since some platforms need several statements. + * + * @param TableDiff $diff + * + * @return array + */ + public function getAlterTableSQL(TableDiff $diff) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * @param Column $column + * @param TableDiff $diff + * @param array $columnSql + * + * @return boolean + */ + protected function onSchemaAlterTableAddColumn(Column $column, TableDiff $diff, &$columnSql) + { + if (null === $this->_eventManager) { + return false; + } + + if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableAddColumn)) { + return false; + } + + $eventArgs = new SchemaAlterTableAddColumnEventArgs($column, $diff, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableAddColumn, $eventArgs); + + $columnSql = array_merge($columnSql, $eventArgs->getSql()); + + return $eventArgs->isDefaultPrevented(); + } + + /** + * @param Column $column + * @param TableDiff $diff + * @param array $columnSql + * + * @return boolean + */ + protected function onSchemaAlterTableRemoveColumn(Column $column, TableDiff $diff, &$columnSql) + { + if (null === $this->_eventManager) { + return false; + } + + if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRemoveColumn)) { + return false; + } + + $eventArgs = new SchemaAlterTableRemoveColumnEventArgs($column, $diff, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRemoveColumn, $eventArgs); + + $columnSql = array_merge($columnSql, $eventArgs->getSql()); + + return $eventArgs->isDefaultPrevented(); + } + + /** + * @param ColumnDiff $columnDiff + * @param TableDiff $diff + * @param array $columnSql + * + * @return boolean + */ + protected function onSchemaAlterTableChangeColumn(ColumnDiff $columnDiff, TableDiff $diff, &$columnSql) + { + if (null === $this->_eventManager) { + return false; + } + + if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableChangeColumn)) { + return false; + } + + $eventArgs = new SchemaAlterTableChangeColumnEventArgs($columnDiff, $diff, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableChangeColumn, $eventArgs); + + $columnSql = array_merge($columnSql, $eventArgs->getSql()); + + return $eventArgs->isDefaultPrevented(); + } + + /** + * @param string $oldColumnName + * @param Column $column + * @param TableDiff $diff + * @param array $columnSql + * + * @return boolean + */ + protected function onSchemaAlterTableRenameColumn($oldColumnName, Column $column, TableDiff $diff, &$columnSql) + { + if (null === $this->_eventManager) { + return false; + } + + if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTableRenameColumn)) { + return false; + } + + $eventArgs = new SchemaAlterTableRenameColumnEventArgs($oldColumnName, $column, $diff, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableRenameColumn, $eventArgs); + + $columnSql = array_merge($columnSql, $eventArgs->getSql()); + + return $eventArgs->isDefaultPrevented(); + } + + /** + * @param TableDiff $diff + * @param array $sql + * + * @return boolean + */ + protected function onSchemaAlterTable(TableDiff $diff, &$sql) + { + if (null === $this->_eventManager) { + return false; + } + + if ( ! $this->_eventManager->hasListeners(Events::onSchemaAlterTable)) { + return false; + } + + $eventArgs = new SchemaAlterTableEventArgs($diff, $this); + $this->_eventManager->dispatchEvent(Events::onSchemaAlterTable, $eventArgs); + + $sql = array_merge($sql, $eventArgs->getSql()); + + return $eventArgs->isDefaultPrevented(); + } + + protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) + { + $tableName = $diff->name; + + $sql = array(); + if ($this->supportsForeignKeyConstraints()) { + foreach ($diff->removedForeignKeys as $foreignKey) { + $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); + } + foreach ($diff->changedForeignKeys as $foreignKey) { + $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName); + } + } + + foreach ($diff->removedIndexes as $index) { + $sql[] = $this->getDropIndexSQL($index, $tableName); + } + foreach ($diff->changedIndexes as $index) { + $sql[] = $this->getDropIndexSQL($index, $tableName); + } + + return $sql; + } + + protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) + { + $tableName = false !== $diff->newName ? $diff->newName : $diff->name; + + $sql = array(); + if ($this->supportsForeignKeyConstraints()) { + foreach ($diff->addedForeignKeys as $foreignKey) { + $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); + } + foreach ($diff->changedForeignKeys as $foreignKey) { + $sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableName); + } + } + + foreach ($diff->addedIndexes as $index) { + $sql[] = $this->getCreateIndexSQL($index, $tableName); + } + foreach ($diff->changedIndexes as $index) { + $sql[] = $this->getCreateIndexSQL($index, $tableName); + } + + return $sql; + } + + /** + * Common code for alter table statement generation that updates the changed Index and Foreign Key definitions. + * + * @param TableDiff $diff + * + * @return array + */ + protected function _getAlterTableIndexForeignKeySQL(TableDiff $diff) + { + return array_merge($this->getPreAlterTableIndexForeignKeySQL($diff), $this->getPostAlterTableIndexForeignKeySQL($diff)); + } + + /** + * Get declaration of a number of fields in bulk + * + * @param array $fields a multidimensional associative array. + * The first dimension determines the field name, while the second + * dimension is keyed with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * charset + * Text value with the default CHARACTER SET for this field. + * collation + * Text value with the default COLLATION for this field. + * unique + * unique constraint + * + * @return string + */ + public function getColumnDeclarationListSQL(array $fields) + { + $queryFields = array(); + + foreach ($fields as $fieldName => $field) { + $queryFields[] = $this->getColumnDeclarationSQL($fieldName, $field); + } + + return implode(', ', $queryFields); + } + + /** + * Obtain DBMS specific SQL code portion needed to declare a generic type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * charset + * Text value with the default CHARACTER SET for this field. + * collation + * Text value with the default COLLATION for this field. + * unique + * unique constraint + * check + * column check constraint + * columnDefinition + * a string that defines the complete column + * + * @return string DBMS specific SQL code portion that should be used to declare the column. + */ + public function getColumnDeclarationSQL($name, array $field) + { + if (isset($field['columnDefinition'])) { + $columnDef = $this->getCustomTypeDeclarationSQL($field); + } else { + $default = $this->getDefaultValueDeclarationSQL($field); + + $charset = (isset($field['charset']) && $field['charset']) ? + ' ' . $this->getColumnCharsetDeclarationSQL($field['charset']) : ''; + + $collation = (isset($field['collation']) && $field['collation']) ? + ' ' . $this->getColumnCollationDeclarationSQL($field['collation']) : ''; + + $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; + + $unique = (isset($field['unique']) && $field['unique']) ? + ' ' . $this->getUniqueFieldDeclarationSQL() : ''; + + $check = (isset($field['check']) && $field['check']) ? + ' ' . $field['check'] : ''; + + $typeDecl = $field['type']->getSqlDeclaration($field, $this); + $columnDef = $typeDecl . $charset . $default . $notnull . $unique . $check . $collation; + } + + if ($this->supportsInlineColumnComments() && isset($field['comment']) && $field['comment']) { + $columnDef .= " COMMENT '" . $field['comment'] . "'"; + } + + return $name . ' ' . $columnDef; + } + + /** + * Gets the SQL snippet that declares a floating point column of arbitrary precision. + * + * @param array $columnDef + * + * @return string + */ + public function getDecimalTypeDeclarationSQL(array $columnDef) + { + $columnDef['precision'] = ( ! isset($columnDef['precision']) || empty($columnDef['precision'])) + ? 10 : $columnDef['precision']; + $columnDef['scale'] = ( ! isset($columnDef['scale']) || empty($columnDef['scale'])) + ? 0 : $columnDef['scale']; + + return 'NUMERIC(' . $columnDef['precision'] . ', ' . $columnDef['scale'] . ')'; + } + + /** + * Obtain DBMS specific SQL code portion needed to set a default value + * declaration to be used in statements like CREATE TABLE. + * + * @param array $field field definition array + * + * @return string DBMS specific SQL code portion needed to set a default value + */ + public function getDefaultValueDeclarationSQL($field) + { + $default = empty($field['notnull']) ? ' DEFAULT NULL' : ''; + + if (isset($field['default'])) { + $default = " DEFAULT '".$field['default']."'"; + if (isset($field['type'])) { + if (in_array((string)$field['type'], array("Integer", "BigInteger", "SmallInteger"))) { + $default = " DEFAULT ".$field['default']; + } else if ((string)$field['type'] == 'DateTime' && $field['default'] == $this->getCurrentTimestampSQL()) { + $default = " DEFAULT ".$this->getCurrentTimestampSQL(); + } else if ((string) $field['type'] == 'Boolean') { + $default = " DEFAULT '" . $this->convertBooleans($field['default']) . "'"; + } + } + } + return $default; + } + + /** + * Obtain DBMS specific SQL code portion needed to set a CHECK constraint + * declaration to be used in statements like CREATE TABLE. + * + * @param array $definition check definition + * + * @return string DBMS specific SQL code portion needed to set a CHECK constraint + */ + public function getCheckDeclarationSQL(array $definition) + { + $constraints = array(); + foreach ($definition as $field => $def) { + if (is_string($def)) { + $constraints[] = 'CHECK (' . $def . ')'; + } else { + if (isset($def['min'])) { + $constraints[] = 'CHECK (' . $field . ' >= ' . $def['min'] . ')'; + } + + if (isset($def['max'])) { + $constraints[] = 'CHECK (' . $field . ' <= ' . $def['max'] . ')'; + } + } + } + + return implode(', ', $constraints); + } + + /** + * Obtain DBMS specific SQL code portion needed to set a unique + * constraint declaration to be used in statements like CREATE TABLE. + * + * @param string $name name of the unique constraint + * @param Index $index index definition + * + * @return string DBMS specific SQL code portion needed + * to set a constraint + */ + public function getUniqueConstraintDeclarationSQL($name, Index $index) + { + if (count($index->getColumns()) === 0) { + throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); + } + + return 'CONSTRAINT ' . $name . ' UNIQUE (' + . $this->getIndexFieldDeclarationListSQL($index->getColumns()) + . ')'; + } + + /** + * Obtain DBMS specific SQL code portion needed to set an index + * declaration to be used in statements like CREATE TABLE. + * + * @param string $name name of the index + * @param Index $index index definition + * + * @return string DBMS specific SQL code portion needed to set an index + */ + public function getIndexDeclarationSQL($name, Index $index) + { + $type = ''; + + if ($index->isUnique()) { + $type = 'UNIQUE '; + } + + if (count($index->getColumns()) === 0) { + throw new \InvalidArgumentException("Incomplete definition. 'columns' required."); + } + + return $type . 'INDEX ' . $name . ' (' + . $this->getIndexFieldDeclarationListSQL($index->getColumns()) + . ')'; + } + + /** + * getCustomTypeDeclarationSql + * Obtail SQL code portion needed to create a custom column, + * e.g. when a field has the "columnDefinition" keyword. + * Only "AUTOINCREMENT" and "PRIMARY KEY" are added if appropriate. + * + * @param array $columnDef + * + * @return string + */ + public function getCustomTypeDeclarationSQL(array $columnDef) + { + return $columnDef['columnDefinition']; + } + + /** + * getIndexFieldDeclarationList + * Obtain DBMS specific SQL code portion needed to set an index + * declaration to be used in statements like CREATE TABLE. + * + * @param array $fields + * + * @return string + */ + public function getIndexFieldDeclarationListSQL(array $fields) + { + $ret = array(); + + foreach ($fields as $field => $definition) { + if (is_array($definition)) { + $ret[] = $field; + } else { + $ret[] = $definition; + } + } + + return implode(', ', $ret); + } + + /** + * A method to return the required SQL string that fits between CREATE ... TABLE + * to create the table as a temporary table. + * + * Should be overridden in driver classes to return the correct string for the + * specific database type. + * + * The default is to return the string "TEMPORARY" - this will result in a + * SQL error for any database that does not support temporary tables, or that + * requires a different SQL command from "CREATE TEMPORARY TABLE". + * + * @return string The string required to be placed between "CREATE" and "TABLE" + * to generate a temporary table, if possible. + */ + public function getTemporaryTableSQL() + { + return 'TEMPORARY'; + } + + /** + * Some vendors require temporary table names to be qualified specially. + * + * @param string $tableName + * + * @return string + */ + public function getTemporaryTableName($tableName) + { + return $tableName; + } + + /** + * Get sql query to show a list of database. + * + * @return string + */ + public function getShowDatabasesSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey + * + * @return string DBMS specific SQL code portion needed to set the FOREIGN KEY constraint + * of a field declaration. + */ + public function getForeignKeyDeclarationSQL(ForeignKeyConstraint $foreignKey) + { + $sql = $this->getForeignKeyBaseDeclarationSQL($foreignKey); + $sql .= $this->getAdvancedForeignKeyOptionsSQL($foreignKey); + + return $sql; + } + + /** + * Return the FOREIGN KEY query section dealing with non-standard options + * as MATCH, INITIALLY DEFERRED, ON UPDATE, ... + * + * @param ForeignKeyConstraint $foreignKey foreign key definition + * + * @return string + */ + public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) + { + $query = ''; + if ($this->supportsForeignKeyOnUpdate() && $foreignKey->hasOption('onUpdate')) { + $query .= ' ON UPDATE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onUpdate')); + } + if ($foreignKey->hasOption('onDelete')) { + $query .= ' ON DELETE ' . $this->getForeignKeyReferentialActionSQL($foreignKey->getOption('onDelete')); + } + return $query; + } + + /** + * returns given referential action in uppercase if valid, otherwise throws + * an exception + * + * @throws \InvalidArgumentException if unknown referential action given + * + * @param string $action foreign key referential action + * + * @return string + */ + public function getForeignKeyReferentialActionSQL($action) + { + $upper = strtoupper($action); + switch ($upper) { + case 'CASCADE': + case 'SET NULL': + case 'NO ACTION': + case 'RESTRICT': + case 'SET DEFAULT': + return $upper; + default: + throw new \InvalidArgumentException('Invalid foreign key action: ' . $upper); + } + } + + /** + * Obtain DBMS specific SQL code portion needed to set the FOREIGN KEY constraint + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param ForeignKeyConstraint $foreignKey + * + * @return string + */ + public function getForeignKeyBaseDeclarationSQL(ForeignKeyConstraint $foreignKey) + { + $sql = ''; + if (strlen($foreignKey->getName())) { + $sql .= 'CONSTRAINT ' . $foreignKey->getQuotedName($this) . ' '; + } + $sql .= 'FOREIGN KEY ('; + + if (count($foreignKey->getLocalColumns()) === 0) { + throw new \InvalidArgumentException("Incomplete definition. 'local' required."); + } + if (count($foreignKey->getForeignColumns()) === 0) { + throw new \InvalidArgumentException("Incomplete definition. 'foreign' required."); + } + if (strlen($foreignKey->getForeignTableName()) === 0) { + throw new \InvalidArgumentException("Incomplete definition. 'foreignTable' required."); + } + + $sql .= implode(', ', $foreignKey->getLocalColumns()) + . ') REFERENCES ' + . $foreignKey->getQuotedForeignTableName($this) . ' (' + . implode(', ', $foreignKey->getForeignColumns()) . ')'; + + return $sql; + } + + /** + * Obtain DBMS specific SQL code portion needed to set the UNIQUE constraint + * of a field declaration to be used in statements like CREATE TABLE. + * + * @return string DBMS specific SQL code portion needed to set the UNIQUE constraint + * of a field declaration. + */ + public function getUniqueFieldDeclarationSQL() + { + return 'UNIQUE'; + } + + /** + * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $charset name of the charset + * + * @return string DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration. + */ + public function getColumnCharsetDeclarationSQL($charset) + { + return ''; + } + + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + public function getColumnCollationDeclarationSQL($collation) + { + return ''; + } + + /** + * Whether the platform prefers sequences for ID generation. + * Subclasses should override this method to return TRUE if they prefer sequences. + * + * @return boolean + */ + public function prefersSequences() + { + return false; + } + + /** + * Whether the platform prefers identity columns (eg. autoincrement) for ID generation. + * Subclasses should override this method to return TRUE if they prefer identity columns. + * + * @return boolean + */ + public function prefersIdentityColumns() + { + return false; + } + + /** + * Some platforms need the boolean values to be converted. + * + * The default conversion in this implementation converts to integers (false => 0, true => 1). + * + * @param mixed $item + * + * @return mixed + */ + public function convertBooleans($item) + { + if (is_array($item)) { + foreach ($item as $k => $value) { + if (is_bool($value)) { + $item[$k] = (int) $value; + } + } + } else if (is_bool($item)) { + $item = (int) $item; + } + + return $item; + } + + /** + * Gets the SQL specific for the platform to get the current date. + * + * @return string + */ + public function getCurrentDateSQL() + { + return 'CURRENT_DATE'; + } + + /** + * Gets the SQL specific for the platform to get the current time. + * + * @return string + */ + public function getCurrentTimeSQL() + { + return 'CURRENT_TIME'; + } + + /** + * Gets the SQL specific for the platform to get the current timestamp + * + * @return string + */ + public function getCurrentTimestampSQL() + { + return 'CURRENT_TIMESTAMP'; + } + + /** + * Get sql for transaction isolation level Connection constant + * + * @param integer $level + * + * @return string + */ + protected function _getTransactionIsolationLevelSQL($level) + { + switch ($level) { + case Connection::TRANSACTION_READ_UNCOMMITTED: + return 'READ UNCOMMITTED'; + case Connection::TRANSACTION_READ_COMMITTED: + return 'READ COMMITTED'; + case Connection::TRANSACTION_REPEATABLE_READ: + return 'REPEATABLE READ'; + case Connection::TRANSACTION_SERIALIZABLE: + return 'SERIALIZABLE'; + default: + throw new \InvalidArgumentException('Invalid isolation level:' . $level); + } + } + + public function getListDatabasesSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListSequencesSQL($database) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListTableConstraintsSQL($table) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListTableColumnsSQL($table, $database = null) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListTablesSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListUsersSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Get the SQL to list all views of a database or user. + * + * @param string $database + * + * @return string + */ + public function getListViewsSQL($database) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Get the list of indexes for the current database. + * + * The current database parameter is optional but will always be passed + * when using the SchemaManager API and is the database the given table is in. + * + * Attention: Some platforms only support currentDatabase when they + * are connected with that database. Cross-database information schema + * requests may be impossible. + * + * @param string $table + * @param string $currentDatabase + * + * @return string + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListTableForeignKeysSQL($table) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getCreateViewSQL($name, $sql) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getDropViewSQL($name) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Get the SQL snippet to drop an existing sequence + * + * @param \Doctrine\DBAL\Schema\Sequence $sequence + * + * @return string + */ + public function getDropSequenceSQL($sequence) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getSequenceNextValSQL($sequenceName) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * create a new database + * + * @param string $database name of the database that should be created + * + * @return string + */ + public function getCreateDatabaseSQL($database) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Get sql to set the transaction isolation level + * + * @param integer $level + * + * @return string + */ + public function getSetTransactionIsolationSQL($level) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Obtain DBMS specific SQL to be used to create datetime fields in + * statements like CREATE TABLE + * + * @param array $fieldDeclaration + * + * @return string + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Obtain DBMS specific SQL to be used to create datetime with timezone offset fields. + * + * @param array $fieldDeclaration + * + * @return string + */ + public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) + { + return $this->getDateTimeTypeDeclarationSQL($fieldDeclaration); + } + + + /** + * Obtain DBMS specific SQL to be used to create date fields in statements + * like CREATE TABLE. + * + * @param array $fieldDeclaration + * + * @return string + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * Obtain DBMS specific SQL to be used to create time fields in statements + * like CREATE TABLE. + * + * @param array $fieldDeclaration + * + * @return string + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getFloatDeclarationSQL(array $fieldDeclaration) + { + return 'DOUBLE PRECISION'; + } + + /** + * Gets the default transaction isolation level of the platform. + * + * @return integer The default isolation level. + * + * @see Doctrine\DBAL\Connection\TRANSACTION_* constants. + */ + public function getDefaultTransactionIsolationLevel() + { + return Connection::TRANSACTION_READ_COMMITTED; + } + + /* supports*() methods */ + + /** + * Whether the platform supports sequences. + * + * @return boolean + */ + public function supportsSequences() + { + return false; + } + + /** + * Whether the platform supports identity columns. + * Identity columns are columns that recieve an auto-generated value from the + * database on insert of a row. + * + * @return boolean + */ + public function supportsIdentityColumns() + { + return false; + } + + /** + * Whether the platform supports indexes. + * + * @return boolean + */ + public function supportsIndexes() + { + return true; + } + + /** + * Whether the platform supports altering tables. + * + * @return boolean + */ + public function supportsAlterTable() + { + return true; + } + + /** + * Whether the platform supports transactions. + * + * @return boolean + */ + public function supportsTransactions() + { + return true; + } + + /** + * Whether the platform supports savepoints. + * + * @return boolean + */ + public function supportsSavepoints() + { + return true; + } + + /** + * Whether the platform supports releasing savepoints. + * + * @return boolean + */ + public function supportsReleaseSavepoints() + { + return $this->supportsSavepoints(); + } + + /** + * Whether the platform supports primary key constraints. + * + * @return boolean + */ + public function supportsPrimaryConstraints() + { + return true; + } + + /** + * Does the platform supports foreign key constraints? + * + * @return boolean + */ + public function supportsForeignKeyConstraints() + { + return true; + } + + /** + * Does this platform supports onUpdate in foreign key constraints? + * + * @return boolean + */ + public function supportsForeignKeyOnUpdate() + { + return ($this->supportsForeignKeyConstraints() && true); + } + + /** + * Whether the platform supports database schemas. + * + * @return boolean + */ + public function supportsSchemas() + { + return false; + } + + /** + * Can this platform emulate schemas? + * + * Platforms that either support or emulate schemas don't automatically + * filter a schema for the namespaced elements in {@link + * AbstractManager#createSchema}. + * + * @return boolean + */ + public function canEmulateSchemas() + { + return false; + } + + /** + * Some databases don't allow to create and drop databases at all or only with certain tools. + * + * @return boolean + */ + public function supportsCreateDropDatabase() + { + return true; + } + + /** + * Whether the platform supports getting the affected rows of a recent + * update/delete type query. + * + * @return boolean + */ + public function supportsGettingAffectedRows() + { + return true; + } + + /** + * Does this plaform support to add inline column comments as postfix. + * + * @return boolean + */ + public function supportsInlineColumnComments() + { + return false; + } + + /** + * Does this platform support the propriortary synatx "COMMENT ON asset" + * + * @return boolean + */ + public function supportsCommentOnStatement() + { + return false; + } + + public function getIdentityColumnNullInsertSQL() + { + return ""; + } + + /** + * Does this platform views ? + * + * @return boolean + */ + public function supportsViews() + { + return true; + } + + /** + * Gets the format string, as accepted by the date() function, that describes + * the format of a stored datetime value of this platform. + * + * @return string The format string. + */ + public function getDateTimeFormatString() + { + return 'Y-m-d H:i:s'; + } + + /** + * Gets the format string, as accepted by the date() function, that describes + * the format of a stored datetime with timezone value of this platform. + * + * @return string The format string. + */ + public function getDateTimeTzFormatString() + { + return 'Y-m-d H:i:s'; + } + + /** + * Gets the format string, as accepted by the date() function, that describes + * the format of a stored date value of this platform. + * + * @return string The format string. + */ + public function getDateFormatString() + { + return 'Y-m-d'; + } + + /** + * Gets the format string, as accepted by the date() function, that describes + * the format of a stored time value of this platform. + * + * @return string The format string. + */ + public function getTimeFormatString() + { + return 'H:i:s'; + } + + /** + * Modify limit query + * + * @param string $query + * @param integer $limit + * @param integer $offset + * + * @return string + */ + final public function modifyLimitQuery($query, $limit, $offset = null) + { + if ($limit !== null) { + $limit = (int)$limit; + } + + if ($offset !== null) { + $offset = (int)$offset; + + if ($offset < 0) { + throw new DBALException("LIMIT argument offset=$offset is not valid"); + } + if ($offset > 0 && ! $this->supportsLimitOffset()) { + throw new DBALException(sprintf("Platform %s does not support offset values in limit queries.", $this->getName())); + } + } + + return $this->doModifyLimitQuery($query, $limit, $offset); + } + + /** + * Adds an driver-specific LIMIT clause to the query + * + * @param string $query + * @param integer $limit + * @param integer $offset + * + * @return string + */ + protected function doModifyLimitQuery($query, $limit, $offset) + { + if ($limit !== null) { + $query .= ' LIMIT ' . $limit; + } + + if ($offset !== null) { + $query .= ' OFFSET ' . $offset; + } + + return $query; + } + + /** + * Does the database platform support offsets in modify limit clauses? + * + * @return boolean + */ + public function supportsLimitOffset() + { + return true; + } + + /** + * Gets the character casing of a column in an SQL result set of this platform. + * + * @param string $column The column name for which to get the correct character casing. + * + * @return string The column name in the character casing used in SQL result sets. + */ + public function getSQLResultCasing($column) + { + return $column; + } + + /** + * Makes any fixes to a name of a schema element (table, sequence, ...) that are required + * by restrictions of the platform, like a maximum length. + * + * @param string $schemaElementName + * + * @return string + */ + public function fixSchemaElementName($schemaElementName) + { + return $schemaElementName; + } + + /** + * Maximum length of any given databse identifier, like tables or column names. + * + * @return integer + */ + public function getMaxIdentifierLength() + { + return 63; + } + + /** + * Get the insert sql for an empty insert statement + * + * @param string $tableName + * @param string $identifierColumnName + * + * @return string $sql + */ + public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) + { + return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (null)'; + } + + /** + * Generate a Truncate Table SQL statement for a given table. + * + * Cascade is not supported on many platforms but would optionally cascade the truncate by + * following the foreign keys. + * + * @param string $tableName + * @param boolean $cascade + * + * @return string + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + return 'TRUNCATE '.$tableName; + } + + /** + * This is for test reasons, many vendors have special requirements for dummy statements. + * + * @return string + */ + public function getDummySelectSQL() + { + return 'SELECT 1'; + } + + /** + * Generate SQL to create a new savepoint + * + * @param string $savepoint + * + * @return string + */ + public function createSavePoint($savepoint) + { + return 'SAVEPOINT ' . $savepoint; + } + + /** + * Generate SQL to release a savepoint + * + * @param string $savepoint + * + * @return string + */ + public function releaseSavePoint($savepoint) + { + return 'RELEASE SAVEPOINT ' . $savepoint; + } + + /** + * Generate SQL to rollback a savepoint + * + * @param string $savepoint + * + * @return string + */ + public function rollbackSavePoint($savepoint) + { + return 'ROLLBACK TO SAVEPOINT ' . $savepoint; + } + + /** + * Return the keyword list instance of this platform. + * + * Throws exception if no keyword list is specified. + * + * @throws DBALException + * + * @return \Doctrine\DBAL\Platforms\Keywords\KeywordList + */ + final public function getReservedKeywordsList() + { + // Check for an existing instantiation of the keywords class. + if ($this->_keywords) { + return $this->_keywords; + } + + $class = $this->getReservedKeywordsClass(); + $keywords = new $class; + if ( ! $keywords instanceof \Doctrine\DBAL\Platforms\Keywords\KeywordList) { + throw DBALException::notSupported(__METHOD__); + } + + // Store the instance so it doesn't need to be generated on every request. + $this->_keywords = $keywords; + + return $keywords; + } + + /** + * The class name of the reserved keywords list. + * + * @return string + */ + protected function getReservedKeywordsClass() + { + throw DBALException::notSupported(__METHOD__); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/DB2Platform.php b/src/core/libs/Doctrine/DBAL/Platforms/DB2Platform.php new file mode 100644 index 0000000..114cd7d --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/DB2Platform.php @@ -0,0 +1,545 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Schema\Index; +use Doctrine\DBAL\Schema\TableDiff; + +class DB2Platform extends AbstractPlatform +{ + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * {@inheritDoc} + */ + public function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = array( + 'smallint' => 'smallint', + 'bigint' => 'bigint', + 'integer' => 'integer', + 'time' => 'time', + 'date' => 'date', + 'varchar' => 'string', + 'character' => 'string', + 'clob' => 'text', + 'decimal' => 'decimal', + 'double' => 'float', + 'real' => 'float', + 'timestamp' => 'datetime', + ); + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') + : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + // todo clob(n) with $field['length']; + return 'CLOB(1M)'; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'db2'; + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $columnDef) + { + return 'SMALLINT'; + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $columnDef) + { + return 'INTEGER' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $columnDef) + { + return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $columnDef) + { + return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($columnDef); + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + $autoinc = ''; + if ( ! empty($columnDef['autoincrement'])) { + $autoinc = ' GENERATED BY DEFAULT AS IDENTITY'; + } + + return $autoinc; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) { + return "TIMESTAMP(0) WITH DEFAULT"; + } + + return 'TIMESTAMP(0)'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME'; + } + + public function getListDatabasesSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListSequencesSQL($database) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getListTableConstraintsSQL($table) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * This code fragment is originally from the Zend_Db_Adapter_Db2 class. + * + * @license New BSD License + * @param string $table + * @param string $database + * @return string + */ + public function getListTableColumnsSQL($table, $database = null) + { + return "SELECT DISTINCT c.tabschema, c.tabname, c.colname, c.colno, + c.typename, c.default, c.nulls, c.length, c.scale, + c.identity, tc.type AS tabconsttype, k.colseq + FROM syscat.columns c + LEFT JOIN (syscat.keycoluse k JOIN syscat.tabconst tc + ON (k.tabschema = tc.tabschema + AND k.tabname = tc.tabname + AND tc.type = 'P')) + ON (c.tabschema = k.tabschema + AND c.tabname = k.tabname + AND c.colname = k.colname) + WHERE UPPER(c.tabname) = UPPER('" . $table . "') ORDER BY c.colno"; + } + + public function getListTablesSQL() + { + return "SELECT NAME FROM SYSIBM.SYSTABLES WHERE TYPE = 'T'"; + } + + public function getListUsersSQL() + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * {@inheritDoc} + */ + public function getListViewsSQL($database) + { + return "SELECT NAME, TEXT FROM SYSIBM.SYSVIEWS"; + } + + /** + * {@inheritDoc} + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + return "SELECT NAME, COLNAMES, UNIQUERULE FROM SYSIBM.SYSINDEXES WHERE TBNAME = UPPER('" . $table . "')"; + } + + public function getListTableForeignKeysSQL($table) + { + return "SELECT TBNAME, RELNAME, REFTBNAME, DELETERULE, UPDATERULE, FKCOLNAMES, PKCOLNAMES ". + "FROM SYSIBM.SYSRELS WHERE TBNAME = UPPER('".$table."')"; + } + + public function getCreateViewSQL($name, $sql) + { + return "CREATE VIEW ".$name." AS ".$sql; + } + + public function getDropViewSQL($name) + { + return "DROP VIEW ".$name; + } + + /** + * {@inheritDoc} + */ + public function getDropSequenceSQL($sequence) + { + throw DBALException::notSupported(__METHOD__); + } + + public function getSequenceNextValSQL($sequenceName) + { + throw DBALException::notSupported(__METHOD__); + } + + /** + * {@inheritDoc} + */ + public function getCreateDatabaseSQL($database) + { + return "CREATE DATABASE ".$database; + } + + /** + * {@inheritDoc} + */ + public function getDropDatabaseSQL($database) + { + return "DROP DATABASE ".$database.";"; + } + + /** + * {@inheritDoc} + */ + public function supportsCreateDropDatabase() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function supportsReleaseSavepoints() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function getCurrentDateSQL() + { + return 'VALUES CURRENT DATE'; + } + + /** + * {@inheritDoc} + */ + public function getCurrentTimeSQL() + { + return 'VALUES CURRENT TIME'; + } + + /** + * {@inheritDoc} + */ + public function getCurrentTimestampSQL() + { + return "VALUES CURRENT TIMESTAMP"; + } + + /** + * {@inheritDoc} + */ + public function getIndexDeclarationSQL($name, Index $index) + { + return $this->getUniqueConstraintDeclarationSQL($name, $index); + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) + { + $indexes = array(); + if (isset($options['indexes'])) { + $indexes = $options['indexes']; + } + $options['indexes'] = array(); + + $sqls = parent::_getCreateTableSQL($tableName, $columns, $options); + + foreach ($indexes as $definition) { + $sqls[] = $this->getCreateIndexSQL($definition, $tableName); + } + return $sqls; + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $sql = array(); + $columnSql = array(); + + $queryParts = array(); + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $queryParts[] = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + } + + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this); + } + + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ + $column = $columnDiff->column; + $queryParts[] = 'ALTER ' . ($columnDiff->oldColumnName) . ' ' + . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $queryParts[] = 'RENAME ' . $oldColumnName . ' TO ' . $column->getQuotedName($this); + } + + $tableSql = array(); + + if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { + if (count($queryParts) > 0) { + $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(" ", $queryParts); + } + + $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff)); + + if ($diff->newName !== false) { + $sql[] = 'RENAME TABLE TO ' . $diff->newName; + } + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * {@inheritDoc} + */ + public function getDefaultValueDeclarationSQL($field) + { + if (isset($field['notnull']) && $field['notnull'] && !isset($field['default'])) { + if (in_array((string)$field['type'], array("Integer", "BigInteger", "SmallInteger"))) { + $field['default'] = 0; + } else if((string)$field['type'] == "DateTime") { + $field['default'] = "00-00-00 00:00:00"; + } else if ((string)$field['type'] == "Date") { + $field['default'] = "00-00-00"; + } else if((string)$field['type'] == "Time") { + $field['default'] = "00:00:00"; + } else { + $field['default'] = ''; + } + } + + unset($field['default']); // @todo this needs fixing + if (isset($field['version']) && $field['version']) { + if ((string)$field['type'] != "DateTime") { + $field['default'] = "1"; + } + } + + return parent::getDefaultValueDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getEmptyIdentityInsertSQL($tableName, $identifierColumnName) + { + return 'INSERT INTO ' . $tableName . ' (' . $identifierColumnName . ') VALUES (DEFAULT)'; + } + + public function getCreateTemporaryTableSnippetSQL() + { + return "DECLARE GLOBAL TEMPORARY TABLE"; + } + + /** + * {@inheritDoc} + */ + public function getTemporaryTableName($tableName) + { + return "SESSION." . $tableName; + } + + /** + * {@inheritDoc} + */ + protected function doModifyLimitQuery($query, $limit, $offset = null) + { + if ($limit === null && $offset === null) { + return $query; + } + + $limit = (int)$limit; + $offset = (int)(($offset)?:0); + + // Todo OVER() needs ORDER BY data! + $sql = 'SELECT db22.* FROM (SELECT ROW_NUMBER() OVER() AS DC_ROWNUM, db21.* '. + 'FROM (' . $query . ') db21) db22 WHERE db22.DC_ROWNUM BETWEEN ' . ($offset+1) .' AND ' . ($offset+$limit); + + return $sql; + } + + /** + * {@inheritDoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos == false) { + return 'LOCATE(' . $substr . ', ' . $str . ')'; + } + + return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')'; + } + + /** + * {@inheritDoc} + */ + public function getSubstringExpression($value, $from, $length = null) + { + if ($length === null) { + return 'SUBSTR(' . $value . ', ' . $from . ')'; + } + + return 'SUBSTR(' . $value . ', ' . $from . ', ' . $length . ')'; + } + + /** + * {@inheritDoc} + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + * + * DB2 returns all column names in SQL result sets in uppercase. + */ + public function getSQLResultCasing($column) + { + return strtoupper($column); + } + + public function getForUpdateSQL() + { + return ' WITH RR USE AND KEEP UPDATE LOCKS'; + } + + /** + * {@inheritDoc} + */ + public function getDummySelectSQL() + { + return 'SELECT 1 FROM sysibm.sysdummy1'; + } + + /** + * {@inheritDoc} + * + * DB2 supports savepoints, but they work semantically different than on other vendor platforms. + * + * TODO: We have to investigate how to get DB2 up and running with savepoints. + */ + public function supportsSavepoints() + { + return false; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords'; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/DrizzlePlatform.php b/src/core/libs/Doctrine/DBAL/Platforms/DrizzlePlatform.php new file mode 100644 index 0000000..47bb364 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/DrizzlePlatform.php @@ -0,0 +1,495 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\DBALException, + Doctrine\DBAL\Schema\TableDiff, + Doctrine\DBAL\Schema\Index, + Doctrine\DBAL\Schema\Table; + +/** + * Drizzle platform + * + * @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com> + */ +class DrizzlePlatform extends AbstractPlatform +{ + /** + * {@inheritDoc} + */ + public function getName() + { + return 'drizzle'; + } + + /** + * {@inheritDoc} + */ + public function getIdentifierQuoteCharacter() + { + return '`'; + } + + + /** + * {@inheritDoc} + */ public function getConcatExpression() + { + $args = func_get_args(); + + return 'CONCAT(' . join(', ', (array) $args) . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateDiffExpression($date1, $date2) + { + return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateAddDaysExpression($date, $days) + { + return 'DATE_ADD(' . $date . ', INTERVAL ' . $days . ' DAY)'; + } + + /** + * {@inheritDoc} + */ + public function getDateSubDaysExpression($date, $days) + { + return 'DATE_SUB(' . $date . ', INTERVAL ' . $days . ' DAY)'; + } + + /** + * {@inheritDoc} + */ + public function getDateAddMonthExpression($date, $months) + { + return 'DATE_ADD(' . $date . ', INTERVAL ' . $months . ' MONTH)'; + } + + /** + * {@inheritDoc} + */ + public function getDateSubMonthExpression($date, $months) + { + return 'DATE_SUB(' . $date . ', INTERVAL ' . $months . ' MONTH)'; + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $field) + { + return 'BOOLEAN'; + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $field) + { + return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + $autoinc = ''; + if ( ! empty($columnDef['autoincrement'])) { + $autoinc = ' AUTO_INCREMENT'; + } + return $autoinc; + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = array( + 'boolean' => 'boolean', + 'varchar' => 'string', + 'integer' => 'integer', + 'blob' => 'text', + 'decimal' => 'decimal', + 'datetime' => 'datetime', + 'date' => 'date', + 'time' => 'time', + 'text' => 'text', + 'timestamp' => 'datetime', + 'double' => 'float', + 'bigint' => 'bigint', + ); + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'TEXT'; + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'BLOB'; + } + + /** + * {@inheritDoc} + */ + public function getCreateDatabaseSQL($name) + { + return 'CREATE DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + public function getDropDatabaseSQL($name) + { + return 'DROP DATABASE ' . $name; + } + + public function getListDatabasesSQL() + { + return "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE CATALOG_NAME='LOCAL'"; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\DrizzleKeywords'; + } + + public function getListTablesSQL() + { + return "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE' AND TABLE_SCHEMA=DATABASE()"; + } + + public function getListTableColumnsSQL($table, $database = null) + { + if ($database) { + $database = "'" . $database . "'"; + } else { + $database = 'DATABASE()'; + } + + return "SELECT COLUMN_NAME, DATA_TYPE, COLUMN_COMMENT, IS_NULLABLE, IS_AUTO_INCREMENT, CHARACTER_MAXIMUM_LENGTH, COLUMN_DEFAULT," . + " NUMERIC_PRECISION, NUMERIC_SCALE" . + " FROM DATA_DICTIONARY.COLUMNS" . + " WHERE TABLE_SCHEMA=" . $database . " AND TABLE_NAME = '" . $table . "'"; + } + + public function getListTableForeignKeysSQL($table, $database = null) + { + if ($database) { + $database = "'" . $database . "'"; + } else { + $database = 'DATABASE()'; + } + + return "SELECT CONSTRAINT_NAME, CONSTRAINT_COLUMNS, REFERENCED_TABLE_NAME, REFERENCED_TABLE_COLUMNS, UPDATE_RULE, DELETE_RULE" . + " FROM DATA_DICTIONARY.FOREIGN_KEYS" . + " WHERE CONSTRAINT_SCHEMA=" . $database . " AND CONSTRAINT_TABLE='" . $table . "'"; + } + + /** + * {@inheritDoc} + */ + public function getListTableIndexesSQL($table, $database = null) + { + if ($database) { + $database = "'" . $database . "'"; + } else { + $database = 'DATABASE()'; + } + + return "SELECT INDEX_NAME AS 'key_name', COLUMN_NAME AS 'column_name', IS_USED_IN_PRIMARY AS 'primary', IS_UNIQUE=0 AS 'non_unique'" . + " FROM DATA_DICTIONARY.INDEX_PARTS" . + " WHERE TABLE_SCHEMA=" . $database . " AND TABLE_NAME='" . $table . "'"; + } + + /** + * {@inheritDoc} + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsInlineColumnComments() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsViews() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function getDropIndexSQL($index, $table=null) + { + if ($index instanceof Index) { + $indexName = $index->getQuotedName($this); + } else if (is_string($index)) { + $indexName = $index; + } else { + throw new \InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } else if(!is_string($table)) { + throw new \InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + } + + if ($index instanceof Index && $index->isPrimary()) { + // drizzle primary keys are always named "PRIMARY", + // so we cannot use them in statements because of them being keyword. + return $this->getDropPrimaryKeySQL($table); + } + + return 'DROP INDEX ' . $indexName . ' ON ' . $table; + } + + /** + * @param Index $index + * @param Table $table + * + * @return string + */ + protected function getDropPrimaryKeySQL($table) + { + return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) { + return 'TIMESTAMP'; + } + + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $columnSql = array(); + $queryParts = array(); + + if ($diff->newName !== false) { + $queryParts[] = 'RENAME TO ' . $diff->newName; + } + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $columnArray = $column->toArray(); + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $queryParts[] = 'DROP ' . $column->getQuotedName($this); + } + + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ + $column = $columnDiff->column; + $columnArray = $column->toArray(); + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'CHANGE ' . ($columnDiff->oldColumnName) . ' ' + . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $columnArray = $column->toArray(); + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'CHANGE ' . $oldColumnName . ' ' + . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + $sql = array(); + $tableSql = array(); + + if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { + if (count($queryParts) > 0) { + $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(", ", $queryParts); + } + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * {@inheritDoc} + */ + public function getDropTemporaryTableSQL($table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } else if(!is_string($table)) { + throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + } + + return 'DROP TEMPORARY TABLE ' . $table; + } + + /** + * {@inheritDoc} + */ + public function convertBooleans($item) + { + if (is_array($item)) { + foreach ($item as $key => $value) { + if (is_bool($value) || is_numeric($item)) { + $item[$key] = ($value) ? 'true' : 'false'; + } + } + } else if (is_bool($item) || is_numeric($item)) { + $item = ($item) ? 'true' : 'false'; + } + + return $item; + } + + /** + * {@inheritDoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos == false) { + return 'LOCATE(' . $substr . ', ' . $str . ')'; + } + + return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')'; + } + + /** + * {@inheritDoc} + */ + public function getGuidExpression() + { + return 'UUID()'; + } + + /** + * {@inheritDoc} + */ + public function getRegexpExpression() + { + return 'RLIKE'; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php new file mode 100644 index 0000000..77c1c67 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/DB2Keywords.php @@ -0,0 +1,438 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * DB2 Keywords + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class DB2Keywords extends KeywordList +{ + public function getName() + { + return 'DB2'; + } + + protected function getKeywords() + { + return array( + 'ACTIVATE', + 'ADD', + 'AFTER', + 'ALIAS', + 'ALL', + 'ALLOCATE', + 'DOCUMENT', + 'DOUBLE', + 'DROP', + 'DSSIZE', + 'DYNAMIC', + 'EACH', + 'LOCK', + 'LOCKMAX', + 'LOCKSIZE', + 'LONG', + 'LOOP', + 'MAINTAINED', + 'ROUND_CEILING', + 'ROUND_DOWN', + 'ROUND_FLOOR', + 'ROUND_HALF_DOWN', + 'ROUND_HALF_EVEN', + 'ROUND_HALF_UP', + 'ALLOW', + 'ALTER', + 'AND', + 'ANY', + 'AS', + 'ASENSITIVE', + 'ASSOCIATE', + 'ASUTIME', + 'AT', + 'ATTRIBUTES', + 'AUDIT', + 'AUTHORIZATION', + 'AUX', + 'AUXILIARY', + 'BEFORE', + 'BEGIN', + 'BETWEEN', + 'BINARY', + 'BUFFERPOOL', + 'BY', + 'CACHE', + 'CALL', + 'CALLED', + 'CAPTURE', + 'CARDINALITY', + 'CASCADED', + 'CASE', + 'CAST', + 'CCSID', + 'CHAR', + 'CHARACTER', + 'CHECK', + 'CLONE', + 'CLOSE', + 'CLUSTER', + 'COLLECTION', + 'COLLID', + 'COLUMN', + 'COMMENT', + 'COMMIT', + 'CONCAT', + 'CONDITION', + 'CONNECT', + 'CONNECTION', + 'CONSTRAINT', + 'CONTAINS', + 'CONTINUE', + 'COUNT', + 'COUNT_BIG', + 'CREATE', + 'CROSS', + 'CURRENT', + 'CURRENT_DATE', + 'CURRENT_LC_CTYPE', + 'CURRENT_PATH', + 'CURRENT_SCHEMA', + 'CURRENT_SERVER', + 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', + 'CURRENT_TIMEZONE', + 'CURRENT_USER', + 'CURSOR', + 'CYCLE', + 'DATA', + 'DATABASE', + 'DATAPARTITIONNAME', + 'DATAPARTITIONNUM', + 'EDITPROC', + 'ELSE', + 'ELSEIF', + 'ENABLE', + 'ENCODING', + 'ENCRYPTION', + 'END', + 'END-EXEC', + 'ENDING', + 'ERASE', + 'ESCAPE', + 'EVERY', + 'EXCEPT', + 'EXCEPTION', + 'EXCLUDING', + 'EXCLUSIVE', + 'EXECUTE', + 'EXISTS', + 'EXIT', + 'EXPLAIN', + 'EXTERNAL', + 'EXTRACT', + 'FENCED', + 'FETCH', + 'FIELDPROC', + 'FILE', + 'FINAL', + 'FOR', + 'FOREIGN', + 'FREE', + 'FROM', + 'FULL', + 'FUNCTION', + 'GENERAL', + 'GENERATED', + 'GET', + 'GLOBAL', + 'GO', + 'GOTO', + 'GRANT', + 'GRAPHIC', + 'GROUP', + 'HANDLER', + 'HASH', + 'HASHED_VALUE', + 'HAVING', + 'HINT', + 'HOLD', + 'HOUR', + 'HOURS', + 'IDENTITY', + 'IF', + 'IMMEDIATE', + 'IN', + 'INCLUDING', + 'INCLUSIVE', + 'INCREMENT', + 'INDEX', + 'INDICATOR', + 'INF', + 'INFINITY', + 'INHERIT', + 'INNER', + 'INOUT', + 'INSENSITIVE', + 'INSERT', + 'INTEGRITY', + 'MATERIALIZED', + 'MAXVALUE', + 'MICROSECOND', + 'MICROSECONDS', + 'MINUTE', + 'MINUTES', + 'MINVALUE', + 'MODE', + 'MODIFIES', + 'MONTH', + 'MONTHS', + 'NAN', + 'NEW', + 'NEW_TABLE', + 'NEXTVAL', + 'NO', + 'NOCACHE', + 'NOCYCLE', + 'NODENAME', + 'NODENUMBER', + 'NOMAXVALUE', + 'NOMINVALUE', + 'NONE', + 'NOORDER', + 'NORMALIZED', + 'NOT', + 'NULL', + 'NULLS', + 'NUMPARTS', + 'OBID', + 'OF', + 'OLD', + 'OLD_TABLE', + 'ON', + 'OPEN', + 'OPTIMIZATION', + 'OPTIMIZE', + 'OPTION', + 'OR', + 'ORDER', + 'OUT', + 'OUTER', + 'OVER', + 'OVERRIDING', + 'PACKAGE', + 'PADDED', + 'PAGESIZE', + 'PARAMETER', + 'PART', + 'PARTITION', + 'PARTITIONED', + 'PARTITIONING', + 'PARTITIONS', + 'PASSWORD', + 'PATH', + 'PIECESIZE', + 'PLAN', + 'POSITION', + 'PRECISION', + 'PREPARE', + 'PREVVAL', + 'PRIMARY', + 'PRIQTY', + 'PRIVILEGES', + 'PROCEDURE', + 'PROGRAM', + 'PSID', + 'ROUND_UP', + 'ROUTINE', + 'ROW', + 'ROW_NUMBER', + 'ROWNUMBER', + 'ROWS', + 'ROWSET', + 'RRN', + 'RUN', + 'SAVEPOINT', + 'SCHEMA', + 'SCRATCHPAD', + 'SCROLL', + 'SEARCH', + 'SECOND', + 'SECONDS', + 'SECQTY', + 'SECURITY', + 'SELECT', + 'SENSITIVE', + 'SEQUENCE', + 'SESSION', + 'SESSION_USER', + 'SET', + 'SIGNAL', + 'SIMPLE', + 'SNAN', + 'SOME', + 'SOURCE', + 'SPECIFIC', + 'SQL', + 'SQLID', + 'STACKED', + 'STANDARD', + 'START', + 'STARTING', + 'STATEMENT', + 'STATIC', + 'STATMENT', + 'STAY', + 'STOGROUP', + 'STORES', + 'STYLE', + 'SUBSTRING', + 'SUMMARY', + 'SYNONYM', + 'SYSFUN', + 'SYSIBM', + 'SYSPROC', + 'SYSTEM', + 'SYSTEM_USER', + 'TABLE', + 'TABLESPACE', + 'THEN', + 'TIME', + 'TIMESTAMP', + 'TO', + 'TRANSACTION', + 'TRIGGER', + 'TRIM', + 'TRUNCATE', + 'TYPE', + 'UNDO', + 'UNION', + 'UNIQUE', + 'UNTIL', + 'UPDATE', + 'DATE', + 'DAY', + 'DAYS', + 'DB2GENERAL', + 'DB2GENRL', + 'DB2SQL', + 'DBINFO', + 'DBPARTITIONNAME', + 'DBPARTITIONNUM', + 'DEALLOCATE', + 'DECLARE', + 'DEFAULT', + 'DEFAULTS', + 'DEFINITION', + 'DELETE', + 'DENSE_RANK', + 'DENSERANK', + 'DESCRIBE', + 'DESCRIPTOR', + 'DETERMINISTIC', + 'DIAGNOSTICS', + 'DISABLE', + 'DISALLOW', + 'DISCONNECT', + 'DISTINCT', + 'DO', + 'INTERSECT', + 'PUBLIC', + 'USAGE', + 'INTO', + 'QUERY', + 'USER', + 'IS', + 'QUERYNO', + 'USING', + 'ISOBID', + 'RANGE', + 'VALIDPROC', + 'ISOLATION', + 'RANK', + 'VALUE', + 'ITERATE', + 'READ', + 'VALUES', + 'JAR', + 'READS', + 'VARIABLE', + 'JAVA', + 'RECOVERY', + 'VARIANT', + 'JOIN', + 'REFERENCES', + 'VCAT', + 'KEEP', + 'REFERENCING', + 'VERSION', + 'KEY', + 'REFRESH', + 'VIEW', + 'LABEL', + 'RELEASE', + 'VOLATILE', + 'LANGUAGE', + 'RENAME', + 'VOLUMES', + 'LATERAL', + 'REPEAT', + 'WHEN', + 'LC_CTYPE', + 'RESET', + 'WHENEVER', + 'LEAVE', + 'RESIGNAL', + 'WHERE', + 'LEFT', + 'RESTART', + 'WHILE', + 'LIKE', + 'RESTRICT', + 'WITH', + 'LINKTYPE', + 'RESULT', + 'WITHOUT', + 'LOCAL', + 'RESULT_SET_LOCATOR WLM', + 'LOCALDATE', + 'RETURN', + 'WRITE', + 'LOCALE', + 'RETURNS', + 'XMLELEMENT', + 'LOCALTIME', + 'REVOKE', + 'XMLEXISTS', + 'LOCALTIMESTAMP RIGHT', + 'XMLNAMESPACES', + 'LOCATOR', + 'ROLE', + 'YEAR', + 'LOCATORS', + 'ROLLBACK', + 'YEARS', + ); + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php new file mode 100644 index 0000000..c6d3187 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/DrizzleKeywords.php @@ -0,0 +1,340 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * Drizzle Keywordlist + * + * @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com> + */ +class DrizzleKeywords extends KeywordList +{ + public function getName() + { + return 'drizzle'; + } + + protected function getKeywords() + { + return array( + 'ABS', + 'ALL', + 'ALLOCATE', + 'ALTER', + 'AND', + 'ANY', + 'ARE', + 'ARRAY', + 'AS', + 'ASENSITIVE', + 'ASYMMETRIC', + 'AT', + 'ATOMIC', + 'AUTHORIZATION', + 'AVG', + 'BEGIN', + 'BETWEEN', + 'BIGINT', + 'BINARY', + 'BLOB', + 'BOOLEAN', + 'BOTH', + 'BY', + 'CALL', + 'CALLED', + 'CARDINALITY', + 'CASCADED', + 'CASE', + 'CAST', + 'CEIL', + 'CEILING', + 'CHAR', + 'CHARACTER', + 'CHARACTER_LENGTH', + 'CHAR_LENGTH', + 'CHECK', + 'CLOB', + 'CLOSE', + 'COALESCE', + 'COLLATE', + 'COLLECT', + 'COLUMN', + 'COMMIT', + 'CONDITION', + 'CONNECT', + 'CONSTRAINT', + 'CONVERT', + 'CORR', + 'CORRESPONDING', + 'COUNT', + 'COVAR_POP', + 'COVAR_SAMP', + 'CREATE', + 'CROSS', + 'CUBE', + 'CUME_DIST', + 'CURRENT', + 'CURRENT_DATE', + 'CURRENT_DEFAULT_TRANSFORM_GROUP', + 'CURRENT_PATH', + 'CURRENT_ROLE', + 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', + 'CURRENT_TRANSFORM_GROUP_FOR_TYPE', + 'CURRENT_USER', + 'CURSOR', + 'CYCLE', + 'DATE', + 'DAY', + 'DEALLOCATE', + 'DEC', + 'DECIMAL', + 'DECLARE', + 'DEFAULT', + 'DELETE', + 'DENSE_RANK', + 'DEREF', + 'DESCRIBE', + 'DETERMINISTIC', + 'DISCONNECT', + 'DISTINCT', + 'DOUBLE', + 'DROP', + 'DYNAMIC', + 'EACH', + 'ELEMENT', + 'ELSE', + 'END', + 'ESCAPE', + 'EVERY', + 'EXCEPT', + 'EXEC', + 'EXECUTE', + 'EXISTS', + 'EXP', + 'EXTERNAL', + 'EXTRACT', + 'FALSE', + 'FETCH', + 'FILTER', + 'FLOAT', + 'FLOOR', + 'FOR', + 'FOREIGN', + 'FREE', + 'FROM', + 'FULL', + 'FUNCTION', + 'FUSION', + 'GET', + 'GLOBAL', + 'GRANT', + 'GROUP', + 'GROUPING', + 'HAVING', + 'HOLD', + 'HOUR', + 'IDENTITY', + 'IN', + 'INDICATOR', + 'INNER', + 'INOUT', + 'INSENSITIVE', + 'INSERT', + 'INT', + 'INTEGER', + 'INTERSECT', + 'INTERSECTION', + 'INTERVAL', + 'INTO', + 'IS', + 'JOIN', + 'LANGUAGE', + 'LARGE', + 'LATERAL', + 'LEADING', + 'LEFT', + 'LIKE', + 'LN', + 'LOCAL', + 'LOCALTIME', + 'LOCALTIMESTAMP', + 'LOWER', + 'MATCH', + 'MAX', + 'MEMBER', + 'MERGE', + 'METHOD', + 'MIN', + 'MINUTE', + 'MOD', + 'MODIFIES', + 'MODULE', + 'MONTH', + 'MULTISET', + 'NATIONAL', + 'NATURAL', + 'NCHAR', + 'NCLOB', + 'NEW', + 'NO', + 'NONE', + 'NORMALIZE', + 'NOT', + 'NULL_SYM', + 'NULLIF', + 'NUMERIC', + 'OCTET_LENGTH', + 'OF', + 'OLD', + 'ON', + 'ONLY', + 'OPEN', + 'OR', + 'ORDER', + 'OUT', + 'OUTER', + 'OVER', + 'OVERLAPS', + 'OVERLAY', + 'PARAMETER', + 'PARTITION', + 'PERCENTILE_CONT', + 'PERCENTILE_DISC', + 'PERCENT_RANK', + 'POSITION', + 'POWER', + 'PRECISION', + 'PREPARE', + 'PRIMARY', + 'PROCEDURE', + 'RANGE', + 'RANK', + 'READS', + 'REAL', + 'RECURSIVE', + 'REF', + 'REFERENCES', + 'REFERENCING', + 'REGR_AVGX', + 'REGR_AVGY', + 'REGR_COUNT', + 'REGR_INTERCEPT', + 'REGR_R2', + 'REGR_SLOPE', + 'REGR_SXX', + 'REGR_SXY', + 'REGR_SYY', + 'RELEASE', + 'RESULT', + 'RETURN', + 'RETURNS', + 'REVOKE', + 'RIGHT', + 'ROLLBACK', + 'ROLLUP', + 'ROW', + 'ROWS', + 'ROW_NUMBER', + 'SAVEPOINT', + 'SCOPE', + 'SCROLL', + 'SEARCH', + 'SECOND', + 'SELECT', + 'SENSITIVE', + 'SESSION_USER', + 'SET', + 'SIMILAR', + 'SMALLINT', + 'SOME', + 'SPECIFIC', + 'SPECIFICTYPE', + 'SQL', + 'SQLEXCEPTION', + 'SQLSTATE', + 'SQLWARNING', + 'SQRT', + 'START', + 'STATIC', + 'STDDEV_POP', + 'STDDEV_SAMP', + 'SUBMULTISET', + 'SUBSTRING', + 'SUM', + 'SYMMETRIC', + 'SYSTEM', + 'SYSTEM_USER', + 'TABLE', + 'TABLESAMPLE', + 'THEN', + 'TIME', + 'TIMESTAMP', + 'TIMEZONE_HOUR', + 'TIMEZONE_MINUTE', + 'TO', + 'TRAILING', + 'TRANSLATE', + 'TRANSLATION', + 'TREAT', + 'TRIGGER', + 'TRIM', + 'TRUE', + 'UESCAPE', + 'UNION', + 'UNIQUE', + 'UNKNOWN', + 'UNNEST', + 'UPDATE', + 'UPPER', + 'USER', + 'USING', + 'VALUE', + 'VALUES', + 'VARCHAR', + 'VARYING', + 'VAR_POP', + 'VAR_SAMP', + 'WHEN', + 'WHENEVER', + 'WHERE', + 'WIDTH_BUCKET', + 'WINDOW', + 'WITH', + 'WITHIN', + 'WITHOUT', + 'XML', + 'XMLAGG', + 'XMLATTRIBUTES', + 'XMLBINARY', + 'XMLCOMMENT', + 'XMLCONCAT', + 'XMLELEMENT', + 'XMLFOREST', + 'XMLNAMESPACES', + 'XMLPARSE', + 'XMLPI', + 'XMLROOT', + 'XMLSERIALIZE', + 'YEAR', + ); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/Keywords/KeywordList.php b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/KeywordList.php new file mode 100644 index 0000000..f30bb36 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/KeywordList.php @@ -0,0 +1,63 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * Abstract interface for a SQL reserved keyword dictionary. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +abstract class KeywordList +{ + private $keywords = null; + + /** + * Check if the given word is a keyword of this dialect/vendor platform. + * + * @param string $word + * @return bool + */ + public function isKeyword($word) + { + if ($this->keywords === null) { + $this->initializeKeywords(); + } + + return isset($this->keywords[strtoupper($word)]); + } + + protected function initializeKeywords() + { + $this->keywords = array_flip(array_map('strtoupper', $this->getKeywords())); + } + + abstract protected function getKeywords(); + + /** + * Name of this keyword list. + * + * @return string + */ + abstract public function getName(); +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/Keywords/MsSQLKeywords.php b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/MsSQLKeywords.php new file mode 100644 index 0000000..8adac11 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/MsSQLKeywords.php @@ -0,0 +1,243 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * MsSQL Keywordlist + * + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author David Coallier <davidc@php.net> + */ +class MsSQLKeywords extends KeywordList +{ + public function getName() + { + return 'MsSQL'; + } + + protected function getKeywords() + { + return array( + 'ADD', + 'CURRENT_TIMESTAMP', + 'GROUP', + 'OPENQUERY', + 'SERIALIZABLE', + 'ALL', + 'CURRENT_USER', + 'HAVING', + 'OPENROWSET', + 'SESSION_USER', + 'ALTER', + 'CURSOR', + 'HOLDLOCK', + 'OPTION', + 'SET', + 'AND', + 'DATABASE', + 'IDENTITY', + 'OR', + 'SETUSER', + 'ANY', + 'DBCC', + 'IDENTITYCOL', + 'ORDER', + 'SHUTDOWN', + 'AS', + 'DEALLOCATE', + 'IDENTITY_INSERT', + 'OUTER', + 'SOME', + 'ASC', + 'DECLARE', + 'IF', + 'OVER', + 'STATISTICS', + 'AUTHORIZATION', + 'DEFAULT', + 'IN', + 'PERCENT', + 'SUM', + 'AVG', + 'DELETE', + 'INDEX', + 'PERM', + 'SYSTEM_USER', + 'BACKUP', + 'DENY', + 'INNER', + 'PERMANENT', + 'TABLE', + 'BEGIN', + 'DESC', + 'INSERT', + 'PIPE', + 'TAPE', + 'BETWEEN', + 'DISK', + 'INTERSECT', + 'PLAN', + 'TEMP', + 'BREAK', + 'DISTINCT', + 'INTO', + 'PRECISION', + 'TEMPORARY', + 'BROWSE', + 'DISTRIBUTED', + 'IS', + 'PREPARE', + 'TEXTSIZE', + 'BULK', + 'DOUBLE', + 'ISOLATION', + 'PRIMARY', + 'THEN', + 'BY', + 'DROP', + 'JOIN', + 'PRINT', + 'TO', + 'CASCADE', + 'DUMMY', + 'KEY', + 'PRIVILEGES', + 'TOP', + 'CASE', + 'DUMP', + 'KILL', + 'PROC', + 'TRAN', + 'CHECK', + 'ELSE', + 'LEFT', + 'PROCEDURE', + 'TRANSACTION', + 'CHECKPOINT', + 'END', + 'LEVEL', + 'PROCESSEXIT', + 'TRIGGER', + 'CLOSE', + 'ERRLVL', + 'LIKE', + 'PUBLIC', + 'TRUNCATE', + 'CLUSTERED', + 'ERROREXIT', + 'LINENO', + 'RAISERROR', + 'TSEQUAL', + 'COALESCE', + 'ESCAPE', + 'LOAD', + 'READ', + 'UNCOMMITTED', + 'COLUMN', + 'EXCEPT', + 'MAX', + 'READTEXT', + 'UNION', + 'COMMIT', + 'EXEC', + 'MIN', + 'RECONFIGURE', + 'UNIQUE', + 'COMMITTED', + 'EXECUTE', + 'MIRROREXIT', + 'REFERENCES', + 'UPDATE', + 'COMPUTE', + 'EXISTS', + 'NATIONAL', + 'REPEATABLE', + 'UPDATETEXT', + 'CONFIRM', + 'EXIT', + 'NOCHECK', + 'REPLICATION', + 'USE', + 'CONSTRAINT', + 'FETCH', + 'NONCLUSTERED', + 'RESTORE', + 'USER', + 'CONTAINS', + 'FILE', + 'NOT', + 'RESTRICT', + 'VALUES', + 'CONTAINSTABLE', + 'FILLFACTOR', + 'NULL', + 'RETURN', + 'VARYING', + 'CONTINUE', + 'FLOPPY', + 'NULLIF', + 'REVOKE', + 'VIEW', + 'CONTROLROW', + 'FOR', + 'OF', + 'RIGHT', + 'WAITFOR', + 'CONVERT', + 'FOREIGN', + 'OFF', + 'ROLLBACK', + 'WHEN', + 'COUNT', + 'FREETEXT', + 'OFFSETS', + 'ROWCOUNT', + 'WHERE', + 'CREATE', + 'FREETEXTTABLE', + 'ON', + 'ROWGUIDCOL', + 'WHILE', + 'CROSS', + 'FROM', + 'ONCE', + 'RULE', + 'WITH', + 'CURRENT', + 'FULL', + 'ONLY', + 'SAVE', + 'WORK', + 'CURRENT_DATE', + 'GOTO', + 'OPEN', + 'SCHEMA', + 'WRITETEXT', + 'CURRENT_TIME', + 'GRANT', + 'OPENDATASOURCE', + 'SELECT', + ); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/Keywords/MySQLKeywords.php b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/MySQLKeywords.php new file mode 100644 index 0000000..71704f6 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/MySQLKeywords.php @@ -0,0 +1,268 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * MySQL Keywordlist + * + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author David Coallier <davidc@php.net> + */ +class MySQLKeywords extends KeywordList +{ + public function getName() + { + return 'MySQL'; + } + + protected function getKeywords() + { + return array( + 'ADD', + 'ALL', + 'ALTER', + 'ANALYZE', + 'AND', + 'AS', + 'ASC', + 'ASENSITIVE', + 'BEFORE', + 'BETWEEN', + 'BIGINT', + 'BINARY', + 'BLOB', + 'BOTH', + 'BY', + 'CALL', + 'CASCADE', + 'CASE', + 'CHANGE', + 'CHAR', + 'CHARACTER', + 'CHECK', + 'COLLATE', + 'COLUMN', + 'CONDITION', + 'CONNECTION', + 'CONSTRAINT', + 'CONTINUE', + 'CONVERT', + 'CREATE', + 'CROSS', + 'CURRENT_DATE', + 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', + 'CURRENT_USER', + 'CURSOR', + 'DATABASE', + 'DATABASES', + 'DAY_HOUR', + 'DAY_MICROSECOND', + 'DAY_MINUTE', + 'DAY_SECOND', + 'DEC', + 'DECIMAL', + 'DECLARE', + 'DEFAULT', + 'DELAYED', + 'DELETE', + 'DESC', + 'DESCRIBE', + 'DETERMINISTIC', + 'DISTINCT', + 'DISTINCTROW', + 'DIV', + 'DOUBLE', + 'DROP', + 'DUAL', + 'EACH', + 'ELSE', + 'ELSEIF', + 'ENCLOSED', + 'ESCAPED', + 'EXISTS', + 'EXIT', + 'EXPLAIN', + 'FALSE', + 'FETCH', + 'FLOAT', + 'FLOAT4', + 'FLOAT8', + 'FOR', + 'FORCE', + 'FOREIGN', + 'FROM', + 'FULLTEXT', + 'GOTO', + 'GRANT', + 'GROUP', + 'HAVING', + 'HIGH_PRIORITY', + 'HOUR_MICROSECOND', + 'HOUR_MINUTE', + 'HOUR_SECOND', + 'IF', + 'IGNORE', + 'IN', + 'INDEX', + 'INFILE', + 'INNER', + 'INOUT', + 'INSENSITIVE', + 'INSERT', + 'INT', + 'INT1', + 'INT2', + 'INT3', + 'INT4', + 'INT8', + 'INTEGER', + 'INTERVAL', + 'INTO', + 'IS', + 'ITERATE', + 'JOIN', + 'KEY', + 'KEYS', + 'KILL', + 'LABEL', + 'LEADING', + 'LEAVE', + 'LEFT', + 'LIKE', + 'LIMIT', + 'LINES', + 'LOAD', + 'LOCALTIME', + 'LOCALTIMESTAMP', + 'LOCK', + 'LONG', + 'LONGBLOB', + 'LONGTEXT', + 'LOOP', + 'LOW_PRIORITY', + 'MATCH', + 'MEDIUMBLOB', + 'MEDIUMINT', + 'MEDIUMTEXT', + 'MIDDLEINT', + 'MINUTE_MICROSECOND', + 'MINUTE_SECOND', + 'MOD', + 'MODIFIES', + 'NATURAL', + 'NOT', + 'NO_WRITE_TO_BINLOG', + 'NULL', + 'NUMERIC', + 'ON', + 'OPTIMIZE', + 'OPTION', + 'OPTIONALLY', + 'OR', + 'ORDER', + 'OUT', + 'OUTER', + 'OUTFILE', + 'PRECISION', + 'PRIMARY', + 'PROCEDURE', + 'PURGE', + 'RAID0', + 'READ', + 'READS', + 'REAL', + 'REFERENCES', + 'REGEXP', + 'RELEASE', + 'RENAME', + 'REPEAT', + 'REPLACE', + 'REQUIRE', + 'RESTRICT', + 'RETURN', + 'REVOKE', + 'RIGHT', + 'RLIKE', + 'SCHEMA', + 'SCHEMAS', + 'SECOND_MICROSECOND', + 'SELECT', + 'SENSITIVE', + 'SEPARATOR', + 'SET', + 'SHOW', + 'SMALLINT', + 'SONAME', + 'SPATIAL', + 'SPECIFIC', + 'SQL', + 'SQLEXCEPTION', + 'SQLSTATE', + 'SQLWARNING', + 'SQL_BIG_RESULT', + 'SQL_CALC_FOUND_ROWS', + 'SQL_SMALL_RESULT', + 'SSL', + 'STARTING', + 'STRAIGHT_JOIN', + 'TABLE', + 'TERMINATED', + 'THEN', + 'TINYBLOB', + 'TINYINT', + 'TINYTEXT', + 'TO', + 'TRAILING', + 'TRIGGER', + 'TRUE', + 'UNDO', + 'UNION', + 'UNIQUE', + 'UNLOCK', + 'UNSIGNED', + 'UPDATE', + 'USAGE', + 'USE', + 'USING', + 'UTC_DATE', + 'UTC_TIME', + 'UTC_TIMESTAMP', + 'VALUES', + 'VARBINARY', + 'VARCHAR', + 'VARCHARACTER', + 'VARYING', + 'WHEN', + 'WHERE', + 'WHILE', + 'WITH', + 'WRITE', + 'X509', + 'XOR', + 'YEAR_MONTH', + 'ZEROFILL', + ); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/Keywords/OracleKeywords.php b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/OracleKeywords.php new file mode 100644 index 0000000..525286e --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/OracleKeywords.php @@ -0,0 +1,156 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * Oracle Keywordlist + * + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author David Coallier <davidc@php.net> + */ +class OracleKeywords extends KeywordList +{ + public function getName() + { + return 'Oracle'; + } + + protected function getKeywords() + { + return array( + 'ACCESS', + 'ELSE', + 'MODIFY', + 'START', + 'ADD', + 'EXCLUSIVE', + 'NOAUDIT', + 'SELECT', + 'ALL', + 'EXISTS', + 'NOCOMPRESS', + 'SESSION', + 'ALTER', + 'FILE', + 'NOT', + 'SET', + 'AND', + 'FLOAT', + 'NOTFOUND ', + 'SHARE', + 'ANY', + 'FOR', + 'NOWAIT', + 'SIZE', + 'ARRAYLEN', + 'FROM', + 'NULL', + 'SMALLINT', + 'AS', + 'GRANT', + 'NUMBER', + 'SQLBUF', + 'ASC', + 'GROUP', + 'OF', + 'SUCCESSFUL', + 'AUDIT', + 'HAVING', + 'OFFLINE ', + 'SYNONYM', + 'BETWEEN', + 'IDENTIFIED', + 'ON', + 'SYSDATE', + 'BY', + 'IMMEDIATE', + 'ONLINE', + 'TABLE', + 'CHAR', + 'IN', + 'OPTION', + 'THEN', + 'CHECK', + 'INCREMENT', + 'OR', + 'TO', + 'CLUSTER', + 'INDEX', + 'ORDER', + 'TRIGGER', + 'COLUMN', + 'INITIAL', + 'PCTFREE', + 'UID', + 'COMMENT', + 'INSERT', + 'PRIOR', + 'UNION', + 'COMPRESS', + 'INTEGER', + 'PRIVILEGES', + 'UNIQUE', + 'CONNECT', + 'INTERSECT', + 'PUBLIC', + 'UPDATE', + 'CREATE', + 'INTO', + 'RAW', + 'USER', + 'CURRENT', + 'IS', + 'RENAME', + 'VALIDATE', + 'DATE', + 'LEVEL', + 'RESOURCE', + 'VALUES', + 'DECIMAL', + 'LIKE', + 'REVOKE', + 'VARCHAR', + 'DEFAULT', + 'LOCK', + 'ROW', + 'VARCHAR2', + 'DELETE', + 'LONG', + 'ROWID', + 'VIEW', + 'DESC', + 'MAXEXTENTS', + 'ROWLABEL', + 'WHENEVER', + 'DISTINCT', + 'MINUS', + 'ROWNUM', + 'WHERE', + 'DROP', + 'MODE', + 'ROWS', + 'WITH', + ); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/Keywords/PostgreSQLKeywords.php b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/PostgreSQLKeywords.php new file mode 100644 index 0000000..7950f6a --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/PostgreSQLKeywords.php @@ -0,0 +1,131 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * PostgreSQL Keywordlist + * + * @license BSD http://www.opensource.org/licenses/bsd-license.php + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Marcelo Santos Araujo <msaraujo@php.net> + */ +class PostgreSQLKeywords extends KeywordList +{ + public function getName() + { + return 'PostgreSQL'; + } + + protected function getKeywords() + { + return array( + 'ALL', + 'ANALYSE', + 'ANALYZE', + 'AND', + 'ANY', + 'AS', + 'ASC', + 'AUTHORIZATION', + 'BETWEEN', + 'BINARY', + 'BOTH', + 'CASE', + 'CAST', + 'CHECK', + 'COLLATE', + 'COLUMN', + 'CONSTRAINT', + 'CREATE', + 'CURRENT_DATE', + 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', + 'CURRENT_USER', + 'DEFAULT', + 'DEFERRABLE', + 'DESC', + 'DISTINCT', + 'DO', + 'ELSE', + 'END', + 'EXCEPT', + 'FALSE', + 'FOR', + 'FOREIGN', + 'FREEZE', + 'FROM', + 'FULL', + 'GRANT', + 'GROUP', + 'HAVING', + 'ILIKE', + 'IN', + 'INITIALLY', + 'INNER', + 'INTERSECT', + 'INTO', + 'IS', + 'ISNULL', + 'JOIN', + 'LEADING', + 'LEFT', + 'LIKE', + 'LIMIT', + 'LOCALTIME', + 'LOCALTIMESTAMP', + 'NATURAL', + 'NEW', + 'NOT', + 'NOTNULL', + 'NULL', + 'OFF', + 'OFFSET', + 'OLD', + 'ON', + 'ONLY', + 'OR', + 'ORDER', + 'OUTER', + 'OVERLAPS', + 'PLACING', + 'PRIMARY', + 'REFERENCES', + 'SELECT', + 'SESSION_USER', + 'SIMILAR', + 'SOME', + 'TABLE', + 'THEN', + 'TO', + 'TRAILING', + 'TRUE', + 'UNION', + 'UNIQUE', + 'USER', + 'USING', + 'VERBOSE', + 'WHEN', + 'WHERE' + ); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php new file mode 100644 index 0000000..a61922b --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/ReservedKeywordsValidator.php @@ -0,0 +1,116 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Platforms\Keywords; + +use Doctrine\DBAL\Schema\Visitor\Visitor; +use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Schema\Column; +use Doctrine\DBAL\Schema\ForeignKeyConstraint; +use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Schema\Sequence; +use Doctrine\DBAL\Schema\Index; + +class ReservedKeywordsValidator implements Visitor +{ + /** + * @var KeywordList[] + */ + private $keywordLists = array(); + + /** + * @var array + */ + private $violations = array(); + + public function __construct(array $keywordLists) + { + $this->keywordLists = $keywordLists; + } + + public function getViolations() + { + return $this->violations; + } + + /** + * @param string $word + * @return array + */ + private function isReservedWord($word) + { + if ($word[0] == "`") { + $word = str_replace('`', '', $word); + } + + $keywordLists = array(); + foreach ($this->keywordLists as $keywordList) { + if ($keywordList->isKeyword($word)) { + $keywordLists[] = $keywordList->getName(); + } + } + return $keywordLists; + } + + private function addViolation($asset, $violatedPlatforms) + { + if ( ! $violatedPlatforms) { + return; + } + + $this->violations[] = $asset . ' keyword violations: ' . implode(', ', $violatedPlatforms); + } + + public function acceptColumn(Table $table, Column $column) + { + $this->addViolation( + 'Table ' . $table->getName() . ' column ' . $column->getName(), + $this->isReservedWord($column->getName()) + ); + } + + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + + } + + public function acceptIndex(Table $table, Index $index) + { + + } + + public function acceptSchema(Schema $schema) + { + + } + + public function acceptSequence(Sequence $sequence) + { + + } + + public function acceptTable(Table $table) + { + $this->addViolation( + 'Table ' . $table->getName(), + $this->isReservedWord($table->getName()) + ); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/Keywords/SQLiteKeywords.php b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/SQLiteKeywords.php new file mode 100644 index 0000000..d45b994 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/Keywords/SQLiteKeywords.php @@ -0,0 +1,164 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Platforms\Keywords; + +/** + * SQLite Keywords + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class SQLiteKeywords extends KeywordList +{ + public function getName() + { + return 'SQLite'; + } + + protected function getKeywords() + { + return array( + 'ABORT', + 'ACTION', + 'ADD', + 'AFTER', + 'ALL', + 'ALTER', + 'ANALYZE', + 'AND', + 'AS', + 'ASC', + 'ATTACH', + 'AUTOINCREMENT', + 'BEFORE', + 'BEGIN', + 'BETWEEN', + 'BY', + 'CASCADE', + 'CASE', + 'CAST', + 'CHECK', + 'COLLATE', + 'COLUMN', + 'COMMIT', + 'CONFLICT', + 'CONSTRAINT', + 'CREATE', + 'CROSS', + 'CURRENT_DATE', + 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', + 'DATABASE', + 'DEFAULT', + 'DEFERRABLE', + 'DEFERRED', + 'DELETE', + 'DESC', + 'DETACH', + 'DISTINCT', + 'DROP', + 'EACH', + 'ELSE', + 'END', + 'ESCAPE', + 'EXCEPT', + 'EXCLUSIVE', + 'EXISTS', + 'EXPLAIN', + 'FAIL', + 'FOR', + 'FOREIGN', + 'FROM', + 'FULL', + 'GLOB', + 'GROUP', + 'HAVING', + 'IF', + 'IGNORE', + 'IMMEDIATE', + 'IN', + 'INDEX', + 'INDEXED', + 'INITIALLY', + 'INNER', + 'INSERT', + 'INSTEAD', + 'INTERSECT', + 'INTO', + 'IS', + 'ISNULL', + 'JOIN', + 'KEY', + 'LEFT', + 'LIKE', + 'LIMIT', + 'MATCH', + 'NATURAL', + 'NO', + 'NOT', + 'NOTNULL', + 'NULL', + 'OF', + 'OFFSET', + 'ON', + 'OR', + 'ORDER', + 'OUTER', + 'PLAN', + 'PRAGMA', + 'PRIMARY', + 'QUERY', + 'RAISE', + 'REFERENCES', + 'REGEXP', + 'REINDEX', + 'RELEASE', + 'RENAME', + 'REPLACE', + 'RESTRICT', + 'RIGHT', + 'ROLLBACK', + 'ROW', + 'SAVEPOINT', + 'SELECT', + 'SET', + 'TABLE', + 'TEMP', + 'TEMPORARY', + 'THEN', + 'TO', + 'TRANSACTION', + 'TRIGGER', + 'UNION', + 'UNIQUE', + 'UPDATE', + 'USING', + 'VACUUM', + 'VALUES', + 'VIEW', + 'VIRTUAL', + 'WHEN', + 'WHERE' + ); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/MySqlPlatform.php b/src/core/libs/Doctrine/DBAL/Platforms/MySqlPlatform.php new file mode 100644 index 0000000..d803589 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/MySqlPlatform.php @@ -0,0 +1,720 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\DBALException, + Doctrine\DBAL\Schema\TableDiff, + Doctrine\DBAL\Schema\Index, + Doctrine\DBAL\Schema\Table; + +/** + * The MySqlPlatform provides the behavior, features and SQL dialect of the + * MySQL database platform. This platform represents a MySQL 5.0 or greater platform that + * uses the InnoDB storage engine. + * + * @since 2.0 + * @author Roman Borschel <roman@code-factory.org> + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @todo Rename: MySQLPlatform + */ +class MySqlPlatform extends AbstractPlatform +{ + /** + * {@inheritDoc} + */ + public function getIdentifierQuoteCharacter() + { + return '`'; + } + + /** + * {@inheritDoc} + */ + public function getRegexpExpression() + { + return 'RLIKE'; + } + + /** + * {@inheritDoc} + */ + public function getGuidExpression() + { + return 'UUID()'; + } + + /** + * {@inheritDoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos == false) { + return 'LOCATE(' . $substr . ', ' . $str . ')'; + } + + return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')'; + } + + /** + * {@inheritDoc} + */ + public function getConcatExpression() + { + $args = func_get_args(); + return 'CONCAT(' . join(', ', (array) $args) . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateDiffExpression($date1, $date2) + { + return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateAddDaysExpression($date, $days) + { + return 'DATE_ADD(' . $date . ', INTERVAL ' . $days . ' DAY)'; + } + + /** + * {@inheritDoc} + */ + public function getDateSubDaysExpression($date, $days) + { + return 'DATE_SUB(' . $date . ', INTERVAL ' . $days . ' DAY)'; + } + + /** + * {@inheritDoc} + */ + public function getDateAddMonthExpression($date, $months) + { + return 'DATE_ADD(' . $date . ', INTERVAL ' . $months . ' MONTH)'; + } + + /** + * {@inheritDoc} + */ + public function getDateSubMonthExpression($date, $months) + { + return 'DATE_SUB(' . $date . ', INTERVAL ' . $months . ' MONTH)'; + } + + public function getListDatabasesSQL() + { + return 'SHOW DATABASES'; + } + + public function getListTableConstraintsSQL($table) + { + return 'SHOW INDEX FROM ' . $table; + } + + /** + * {@inheritDoc} + * + * Two approaches to listing the table indexes. The information_schema is + * preferred, because it doesn't cause problems with SQL keywords such as "order" or "table". + * + * @param string $table + * @param string $currentDatabase + * @return string + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + if ($currentDatabase) { + return "SELECT TABLE_NAME AS `Table`, NON_UNIQUE AS Non_Unique, INDEX_NAME AS Key_name, ". + "SEQ_IN_INDEX AS Seq_in_index, COLUMN_NAME AS Column_Name, COLLATION AS Collation, ". + "CARDINALITY AS Cardinality, SUB_PART AS Sub_Part, PACKED AS Packed, " . + "NULLABLE AS `Null`, INDEX_TYPE AS Index_Type, COMMENT AS Comment " . + "FROM information_schema.STATISTICS WHERE TABLE_NAME = '" . $table . "' AND TABLE_SCHEMA = '" . $currentDatabase . "'"; + } + + return 'SHOW INDEX FROM ' . $table; + } + + public function getListViewsSQL($database) + { + return "SELECT * FROM information_schema.VIEWS WHERE TABLE_SCHEMA = '".$database."'"; + } + + public function getListTableForeignKeysSQL($table, $database = null) + { + $sql = "SELECT DISTINCT k.`CONSTRAINT_NAME`, k.`COLUMN_NAME`, k.`REFERENCED_TABLE_NAME`, ". + "k.`REFERENCED_COLUMN_NAME` /*!50116 , c.update_rule, c.delete_rule */ ". + "FROM information_schema.key_column_usage k /*!50116 ". + "INNER JOIN information_schema.referential_constraints c ON ". + " c.constraint_name = k.constraint_name AND ". + " c.table_name = '$table' */ WHERE k.table_name = '$table'"; + + if ($database) { + $sql .= " AND k.table_schema = '$database' /*!50116 AND c.constraint_schema = '$database' */"; + } + + $sql .= " AND k.`REFERENCED_COLUMN_NAME` is not NULL"; + + return $sql; + } + + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + public function getDropViewSQL($name) + { + return 'DROP VIEW '. $name; + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') + : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + if ( ! empty($field['length']) && is_numeric($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYTEXT'; + } + + if ($length <= 65532) { + return 'TEXT'; + } + + if ($length <= 16777215) { + return 'MEDIUMTEXT'; + } + } + + return 'LONGTEXT'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] == true) { + return 'TIMESTAMP'; + } + + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME'; + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $field) + { + return 'TINYINT(1)'; + } + + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + public function getCollationFieldDeclaration($collation) + { + return 'COLLATE ' . $collation; + } + + /** + * {@inheritDoc} + * + * MySql prefers "autoincrement" identity columns since sequences can only + * be emulated with a table. + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + * + * MySql supports this through AUTO_INCREMENT columns. + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsInlineColumnComments() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getShowDatabasesSQL() + { + return 'SHOW DATABASES'; + } + + public function getListTablesSQL() + { + return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'"; + } + + public function getListTableColumnsSQL($table, $database = null) + { + if ($database) { + return "SELECT COLUMN_NAME AS Field, COLUMN_TYPE AS Type, IS_NULLABLE AS `Null`, ". + "COLUMN_KEY AS `Key`, COLUMN_DEFAULT AS `Default`, EXTRA AS Extra, COLUMN_COMMENT AS Comment, " . + "CHARACTER_SET_NAME AS CharacterSet, COLLATION_NAME AS CollactionName ". + "FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '" . $database . "' AND TABLE_NAME = '" . $table . "'"; + } + + return 'DESCRIBE ' . $table; + } + + /** + * {@inheritDoc} + */ + public function getCreateDatabaseSQL($name) + { + return 'CREATE DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + public function getDropDatabaseSQL($name) + { + return 'DROP DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) + { + $queryFields = $this->getColumnDeclarationListSQL($columns); + + if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) { + foreach ($options['uniqueConstraints'] as $index => $definition) { + $queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($index, $definition); + } + } + + // add all indexes + if (isset($options['indexes']) && ! empty($options['indexes'])) { + foreach($options['indexes'] as $index => $definition) { + $queryFields .= ', ' . $this->getIndexDeclarationSQL($index, $definition); + } + } + + // attach all primary keys + if (isset($options['primary']) && ! empty($options['primary'])) { + $keyColumns = array_unique(array_values($options['primary'])); + $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; + } + + $query = 'CREATE '; + if (!empty($options['temporary'])) { + $query .= 'TEMPORARY '; + } + $query .= 'TABLE ' . $tableName . ' (' . $queryFields . ') '; + + if (isset($options['comment'])) { + $query .= 'COMMENT = ' . $options['comment'] . ' '; + } + + if ( ! isset($options['charset'])) { + $options['charset'] = 'utf8'; + } + + if ( ! isset($options['collate'])) { + $options['collate'] = 'utf8_unicode_ci'; + } + + $query .= 'DEFAULT CHARACTER SET ' . $options['charset']; + $query .= ' COLLATE ' . $options['collate']; + + if ( ! isset($options['engine'])) { + $options['engine'] = 'InnoDB'; + } + $query .= ' ENGINE = ' . $options['engine']; + + $sql[] = $query; + + if (isset($options['foreignKeys'])) { + foreach ((array) $options['foreignKeys'] as $definition) { + $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); + } + } + + return $sql; + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $columnSql = array(); + $queryParts = array(); + if ($diff->newName !== false) { + $queryParts[] = 'RENAME TO ' . $diff->newName; + } + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $columnArray = $column->toArray(); + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $queryParts[] = 'DROP ' . $column->getQuotedName($this); + } + + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ + $column = $columnDiff->column; + $columnArray = $column->toArray(); + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'CHANGE ' . ($columnDiff->oldColumnName) . ' ' + . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $columnArray = $column->toArray(); + $columnArray['comment'] = $this->getColumnComment($column); + $queryParts[] = 'CHANGE ' . $oldColumnName . ' ' + . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); + } + + $sql = array(); + $tableSql = array(); + + if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { + if (count($queryParts) > 0) { + $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . implode(", ", $queryParts); + } + $sql = array_merge( + $this->getPreAlterTableIndexForeignKeySQL($diff), + $sql, + $this->getPostAlterTableIndexForeignKeySQL($diff) + ); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * {@inheritDoc} + */ + protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) + { + $sql = array(); + $table = $diff->name; + + foreach ($diff->removedIndexes as $remKey => $remIndex) { + + foreach ($diff->addedIndexes as $addKey => $addIndex) { + if ($remIndex->getColumns() == $addIndex->getColumns()) { + + $columns = $addIndex->getColumns(); + $type = ''; + if ($addIndex->isUnique()) { + $type = 'UNIQUE '; + } + + $query = 'ALTER TABLE ' . $table . ' DROP INDEX ' . $remIndex->getName() . ', '; + $query .= 'ADD ' . $type . 'INDEX ' . $addIndex->getName(); + $query .= ' (' . $this->getIndexFieldDeclarationListSQL($columns) . ')'; + + $sql[] = $query; + + unset($diff->removedIndexes[$remKey]); + unset($diff->addedIndexes[$addKey]); + + break; + } + } + } + + $sql = array_merge($sql, parent::getPreAlterTableIndexForeignKeySQL($diff)); + + return $sql; + } + + /** + * {@inheritDoc} + */ + protected function getCreateIndexSQLFlags(Index $index) + { + $type = ''; + if ($index->isUnique()) { + $type .= 'UNIQUE '; + } else if ($index->hasFlag('fulltext')) { + $type .= 'FULLTEXT '; + } + + return $type; + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $field) + { + return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + $autoinc = ''; + if ( ! empty($columnDef['autoincrement'])) { + $autoinc = ' AUTO_INCREMENT'; + } + $unsigned = (isset($columnDef['unsigned']) && $columnDef['unsigned']) ? ' UNSIGNED' : ''; + + return $unsigned . $autoinc; + } + + /** + * {@inheritDoc} + */ + public function getAdvancedForeignKeyOptionsSQL(\Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey) + { + $query = ''; + if ($foreignKey->hasOption('match')) { + $query .= ' MATCH ' . $foreignKey->getOption('match'); + } + $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey); + return $query; + } + + /** + * {@inheritDoc} + */ + public function getDropIndexSQL($index, $table=null) + { + if ($index instanceof Index) { + $indexName = $index->getQuotedName($this); + } else if(is_string($index)) { + $indexName = $index; + } else { + throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } else if(!is_string($table)) { + throw new \InvalidArgumentException('MysqlPlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + } + + if ($index instanceof Index && $index->isPrimary()) { + // mysql primary keys are always named "PRIMARY", + // so we cannot use them in statements because of them being keyword. + return $this->getDropPrimaryKeySQL($table); + } + + return 'DROP INDEX ' . $indexName . ' ON ' . $table; + } + + /** + * @param string $table + * + * @return string + */ + protected function getDropPrimaryKeySQL($table) + { + return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; + } + + /** + * {@inheritDoc} + */ + public function getSetTransactionIsolationSQL($level) + { + return 'SET SESSION TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'mysql'; + } + + /** + * {@inheritDoc} + */ + public function getReadLockSQL() + { + return 'LOCK IN SHARE MODE'; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = array( + 'tinyint' => 'boolean', + 'smallint' => 'smallint', + 'mediumint' => 'integer', + 'int' => 'integer', + 'integer' => 'integer', + 'bigint' => 'bigint', + 'tinytext' => 'text', + 'mediumtext' => 'text', + 'longtext' => 'text', + 'text' => 'text', + 'varchar' => 'string', + 'string' => 'string', + 'char' => 'string', + 'date' => 'date', + 'datetime' => 'datetime', + 'timestamp' => 'datetime', + 'time' => 'time', + 'float' => 'float', + 'double' => 'float', + 'real' => 'float', + 'decimal' => 'decimal', + 'numeric' => 'decimal', + 'year' => 'date', + 'longblob' => 'blob', + 'blob' => 'blob', + 'mediumblob' => 'blob', + 'tinyblob' => 'blob', + 'binary' => 'blob', + 'varbinary' => 'blob', + 'set' => 'simple_array', + ); + } + + /** + * {@inheritDoc} + */ + public function getVarcharMaxLength() + { + return 65535; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\MySQLKeywords'; + } + + /** + * {@inheritDoc} + * + * MySQL commits a transaction implicitly when DROP TABLE is executed, however not + * if DROP TEMPORARY TABLE is executed. + */ + public function getDropTemporaryTableSQL($table) + { + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } else if(!is_string($table)) { + throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); + } + + return 'DROP TEMPORARY TABLE ' . $table; + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'LONGBLOB'; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/OraclePlatform.php b/src/core/libs/Doctrine/DBAL/Platforms/OraclePlatform.php new file mode 100644 index 0000000..cd5c774 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/OraclePlatform.php @@ -0,0 +1,822 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\Schema\ForeignKeyConstraint; +use Doctrine\DBAL\Schema\Index; +use Doctrine\DBAL\Schema\Sequence; +use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Schema\TableDiff; +use Doctrine\DBAL\DBALException; + +/** + * OraclePlatform. + * + * @since 2.0 + * @author Roman Borschel <roman@code-factory.org> + * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class OraclePlatform extends AbstractPlatform +{ + /** + * Assertion for Oracle identifiers + * + * @link http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements008.htm + * + * @param string + * + * @throws DBALException + */ + static public function assertValidIdentifier($identifier) + { + if ( ! preg_match('(^(([a-zA-Z]{1}[a-zA-Z0-9_$#]{0,})|("[^"]+"))$)', $identifier)) { + throw new DBALException("Invalid Oracle identifier"); + } + } + + /** + * {@inheritDoc} + */ + public function getSubstringExpression($value, $position, $length = null) + { + if ($length !== null) { + return "SUBSTR($value, $position, $length)"; + } + + return "SUBSTR($value, $position)"; + } + + /** + * {@inheritDoc} + */ + public function getNowExpression($type = 'timestamp') + { + switch ($type) { + case 'date': + case 'time': + case 'timestamp': + default: + return 'TO_CHAR(CURRENT_TIMESTAMP, \'YYYY-MM-DD HH24:MI:SS\')'; + } + } + + /** + * {@inheritDoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos == false) { + return 'INSTR('.$str.', '.$substr.')'; + } + + return 'INSTR('.$str.', '.$substr.', '.$startPos.')'; + } + + /** + * {@inheritDoc} + */ + public function getGuidExpression() + { + return 'SYS_GUID()'; + } + + /** + * {@inheritDoc} + * + * Note: Since Oracle timestamp differences are calculated down to the microsecond we have to truncate + * them to the difference in days. This is obviously a restriction of the original functionality, but we + * need to make this a portable function. + */ + public function getDateDiffExpression($date1, $date2) + { + return "TRUNC(TO_NUMBER(SUBSTR((" . $date1 . "-" . $date2 . "), 1, INSTR(" . $date1 . "-" . $date2 .", ' '))))"; + } + + /** + * {@inheritDoc} + */ + public function getDateAddDaysExpression($date, $days) + { + return '(' . $date . '+' . $days . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateSubDaysExpression($date, $days) + { + return '(' . $date . '-' . $days . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateAddMonthExpression($date, $months) + { + return "ADD_MONTHS(" . $date . ", " . $months . ")"; + } + + /** + * {@inheritDoc} + */ + public function getDateSubMonthExpression($date, $months) + { + return "ADD_MONTHS(" . $date . ", -" . $months . ")"; + } + + /** + * {@inheritDoc} + */ + public function getBitAndComparisonExpression($value1, $value2) + { + return 'BITAND('.$value1 . ', ' . $value2 . ')'; + } + + /** + * {@inheritDoc} + */ + public function getBitOrComparisonExpression($value1, $value2) + { + return '(' . $value1 . '-' . + $this->getBitAndComparisonExpression($value1, $value2) + . '+' . $value2 . ')'; + } + + /** + * {@inheritDoc} + * + * Need to specifiy minvalue, since start with is hidden in the system and MINVALUE <= START WITH. + * Therefore we can use MINVALUE to be able to get a hint what START WITH was for later introspection + * in {@see listSequences()} + */ + public function getCreateSequenceSQL(Sequence $sequence) + { + return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . + ' START WITH ' . $sequence->getInitialValue() . + ' MINVALUE ' . $sequence->getInitialValue() . + ' INCREMENT BY ' . $sequence->getAllocationSize(); + } + + /** + * {@inheritDoc} + */ + public function getAlterSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence) + { + return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . + ' INCREMENT BY ' . $sequence->getAllocationSize(); + } + + /** + * {@inheritDoc} + */ + public function getSequenceNextValSQL($sequenceName) + { + return 'SELECT ' . $sequenceName . '.nextval FROM DUAL'; + } + + /** + * {@inheritDoc} + */ + public function getSetTransactionIsolationSQL($level) + { + return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritDoc} + */ + protected function _getTransactionIsolationLevelSQL($level) + { + switch ($level) { + case \Doctrine\DBAL\Connection::TRANSACTION_READ_UNCOMMITTED: + return 'READ UNCOMMITTED'; + case \Doctrine\DBAL\Connection::TRANSACTION_READ_COMMITTED: + return 'READ COMMITTED'; + case \Doctrine\DBAL\Connection::TRANSACTION_REPEATABLE_READ: + case \Doctrine\DBAL\Connection::TRANSACTION_SERIALIZABLE: + return 'SERIALIZABLE'; + default: + return parent::_getTransactionIsolationLevelSQL($level); + } + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $field) + { + return 'NUMBER(1)'; + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $field) + { + return 'NUMBER(10)'; + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + return 'NUMBER(20)'; + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + return 'NUMBER(5)'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIMESTAMP(0)'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIMESTAMP(0) WITH TIME ZONE'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + return ''; + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(2000)') + : ($length ? 'VARCHAR2(' . $length . ')' : 'VARCHAR2(4000)'); + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'CLOB'; + } + + public function getListDatabasesSQL() + { + return 'SELECT username FROM all_users'; + } + + public function getListSequencesSQL($database) + { + return "SELECT sequence_name, min_value, increment_by FROM sys.all_sequences ". + "WHERE SEQUENCE_OWNER = '".strtoupper($database)."'"; + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($table, array $columns, array $options = array()) + { + $indexes = isset($options['indexes']) ? $options['indexes'] : array(); + $options['indexes'] = array(); + $sql = parent::_getCreateTableSQL($table, $columns, $options); + + foreach ($columns as $name => $column) { + if (isset($column['sequence'])) { + $sql[] = $this->getCreateSequenceSQL($column['sequence'], 1); + } + + if (isset($column['autoincrement']) && $column['autoincrement'] || + (isset($column['autoinc']) && $column['autoinc'])) { + $sql = array_merge($sql, $this->getCreateAutoincrementSql($name, $table)); + } + } + + if (isset($indexes) && ! empty($indexes)) { + foreach ($indexes as $index) { + $sql[] = $this->getCreateIndexSQL($index, $table); + } + } + + return $sql; + } + + /** + * {@inheritDoc} + * + * @license New BSD License + * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaOracleReader.html + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + $table = strtoupper($table); + + return "SELECT uind.index_name AS name, " . + " uind.index_type AS type, " . + " decode( uind.uniqueness, 'NONUNIQUE', 0, 'UNIQUE', 1 ) AS is_unique, " . + " uind_col.column_name AS column_name, " . + " uind_col.column_position AS column_pos, " . + " (SELECT ucon.constraint_type FROM user_constraints ucon WHERE ucon.constraint_name = uind.index_name) AS is_primary ". + "FROM user_indexes uind, user_ind_columns uind_col " . + "WHERE uind.index_name = uind_col.index_name AND uind_col.table_name = '$table' ORDER BY uind_col.column_position ASC"; + } + + public function getListTablesSQL() + { + return 'SELECT * FROM sys.user_tables'; + } + + /** + * {@inheritDoc} + */ + public function getListViewsSQL($database) + { + return 'SELECT view_name, text FROM sys.user_views'; + } + + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + public function getDropViewSQL($name) + { + return 'DROP VIEW '. $name; + } + + public function getCreateAutoincrementSql($name, $table, $start = 1) + { + $table = strtoupper($table); + $sql = array(); + + $indexName = $table . '_AI_PK'; + + $idx = new Index($indexName, array($name), true, true); + + $sql[] = 'DECLARE + constraints_Count NUMBER; +BEGIN + SELECT COUNT(CONSTRAINT_NAME) INTO constraints_Count FROM USER_CONSTRAINTS WHERE TABLE_NAME = \''.$table.'\' AND CONSTRAINT_TYPE = \'P\'; + IF constraints_Count = 0 OR constraints_Count = \'\' THEN + EXECUTE IMMEDIATE \''.$this->getCreateConstraintSQL($idx, $table).'\'; + END IF; +END;'; + + $sequenceName = $table . '_SEQ'; + $sequence = new Sequence($sequenceName, $start); + $sql[] = $this->getCreateSequenceSQL($sequence); + + $triggerName = $table . '_AI_PK'; + $sql[] = 'CREATE TRIGGER ' . $triggerName . ' + BEFORE INSERT + ON ' . $table . ' + FOR EACH ROW +DECLARE + last_Sequence NUMBER; + last_InsertID NUMBER; +BEGIN + SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL; + IF (:NEW.' . $name . ' IS NULL OR :NEW.'.$name.' = 0) THEN + SELECT ' . $sequenceName . '.NEXTVAL INTO :NEW.' . $name . ' FROM DUAL; + ELSE + SELECT NVL(Last_Number, 0) INTO last_Sequence + FROM User_Sequences + WHERE Sequence_Name = \'' . $sequenceName . '\'; + SELECT :NEW.' . $name . ' INTO last_InsertID FROM DUAL; + WHILE (last_InsertID > last_Sequence) LOOP + SELECT ' . $sequenceName . '.NEXTVAL INTO last_Sequence FROM DUAL; + END LOOP; + END IF; +END;'; + + return $sql; + } + + public function getDropAutoincrementSql($table) + { + $table = strtoupper($table); + $trigger = $table . '_AI_PK'; + + $sql[] = 'DROP TRIGGER ' . $trigger; + $sql[] = $this->getDropSequenceSQL($table.'_SEQ'); + + $indexName = $table . '_AI_PK'; + $sql[] = $this->getDropConstraintSQL($indexName, $table); + + return $sql; + } + + public function getListTableForeignKeysSQL($table) + { + $table = strtoupper($table); + + return "SELECT alc.constraint_name, + alc.DELETE_RULE, + alc.search_condition, + cols.column_name \"local_column\", + cols.position, + r_alc.table_name \"references_table\", + r_cols.column_name \"foreign_column\" + FROM user_cons_columns cols +LEFT JOIN user_constraints alc + ON alc.constraint_name = cols.constraint_name +LEFT JOIN user_constraints r_alc + ON alc.r_constraint_name = r_alc.constraint_name +LEFT JOIN user_cons_columns r_cols + ON r_alc.constraint_name = r_cols.constraint_name + AND cols.position = r_cols.position + WHERE alc.constraint_name = cols.constraint_name + AND alc.constraint_type = 'R' + AND alc.table_name = '".$table."'"; + } + + public function getListTableConstraintsSQL($table) + { + $table = strtoupper($table); + return 'SELECT * FROM user_constraints WHERE table_name = \'' . $table . '\''; + } + + public function getListTableColumnsSQL($table, $database = null) + { + $table = strtoupper($table); + + $tabColumnsTableName = "user_tab_columns"; + $ownerCondition = ''; + + if (null !== $database){ + $database = strtoupper($database); + $tabColumnsTableName = "all_tab_columns"; + $ownerCondition = "AND c.owner = '".$database."'"; + } + + return "SELECT c.*, d.comments FROM $tabColumnsTableName c ". + "INNER JOIN user_col_comments d ON d.TABLE_NAME = c.TABLE_NAME AND d.COLUMN_NAME = c.COLUMN_NAME ". + "WHERE c.table_name = '" . $table . "' ".$ownerCondition." ORDER BY c.column_name"; + } + + /** + * {@inheritDoc} + */ + public function getDropSequenceSQL($sequence) + { + if ($sequence instanceof Sequence) { + $sequence = $sequence->getQuotedName($this); + } + + return 'DROP SEQUENCE ' . $sequence; + } + + /** + * {@inheritDoc} + */ + public function getDropForeignKeySQL($foreignKey, $table) + { + if ($foreignKey instanceof ForeignKeyConstraint) { + $foreignKey = $foreignKey->getQuotedName($this); + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey; + } + + /** + * {@inheritDoc} + */ + public function getDropDatabaseSQL($database) + { + return 'DROP USER ' . $database . ' CASCADE'; + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $sql = array(); + $commentsSQL = array(); + $columnSql = array(); + + $fields = array(); + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $fields[] = $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + if ($comment = $this->getColumnComment($column)) { + $commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment); + } + } + + if (count($fields)) { + $sql[] = 'ALTER TABLE ' . $diff->name . ' ADD (' . implode(', ', $fields) . ')'; + } + + $fields = array(); + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + $column = $columnDiff->column; + $fields[] = $column->getQuotedName($this). ' ' . $this->getColumnDeclarationSQL('', $column->toArray()); + if ($columnDiff->hasChanged('comment') && $comment = $this->getColumnComment($column)) { + $commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment); + } + } + + if (count($fields)) { + $sql[] = 'ALTER TABLE ' . $diff->name . ' MODIFY (' . implode(', ', $fields) . ')'; + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName .' TO ' . $column->getQuotedName($this); + } + + $fields = array(); + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $fields[] = $column->getQuotedName($this); + } + + if (count($fields)) { + $sql[] = 'ALTER TABLE ' . $diff->name . ' DROP (' . implode(', ', $fields).')'; + } + + $tableSql = array(); + + if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { + if ($diff->newName !== false) { + $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName; + } + + $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff), $commentsSQL); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * {@inheritDoc} + */ + public function prefersSequences() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsCommentOnStatement() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'oracle'; + } + + /** + * {@inheritDoc} + */ + protected function doModifyLimitQuery($query, $limit, $offset = null) + { + $limit = (int) $limit; + $offset = (int) $offset; + + if (preg_match('/^\s*SELECT/i', $query)) { + if (!preg_match('/\sFROM\s/i', $query)) { + $query .= " FROM dual"; + } + if ($limit > 0) { + $max = $offset + $limit; + $column = '*'; + if ($offset > 0) { + $min = $offset + 1; + $query = 'SELECT * FROM (SELECT a.' . $column . ', rownum AS doctrine_rownum FROM (' . + $query . + ') a WHERE rownum <= ' . $max . ') WHERE doctrine_rownum >= ' . $min; + } else { + $query = 'SELECT a.' . $column . ' FROM (' . $query . ') a WHERE ROWNUM <= ' . $max; + } + } + } + + return $query; + } + + /** + * {@inheritDoc} + * + * Oracle returns all column names in SQL result sets in uppercase. + */ + public function getSQLResultCasing($column) + { + return strtoupper($column); + } + + public function getCreateTemporaryTableSnippetSQL() + { + return "CREATE GLOBAL TEMPORARY TABLE"; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTzFormatString() + { + return 'Y-m-d H:i:sP'; + } + + /** + * {@inheritDoc} + */ + public function getDateFormatString() + { + return 'Y-m-d 00:00:00'; + } + + /** + * {@inheritDoc} + */ + public function getTimeFormatString() + { + return '1900-01-01 H:i:s'; + } + + /** + * {@inheritDoc} + */ + public function fixSchemaElementName($schemaElementName) + { + if (strlen($schemaElementName) > 30) { + // Trim it + return substr($schemaElementName, 0, 30); + } + + return $schemaElementName; + } + + /** + * {@inheritDoc} + */ + public function getMaxIdentifierLength() + { + return 30; + } + + /** + * {@inheritDoc} + */ + public function supportsSequences() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsForeignKeyOnUpdate() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function supportsReleaseSavepoints() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + return 'TRUNCATE TABLE '.$tableName; + } + + /** + * {@inheritDoc} + */ + public function getDummySelectSQL() + { + return 'SELECT 1 FROM DUAL'; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = array( + 'integer' => 'integer', + 'number' => 'integer', + 'pls_integer' => 'boolean', + 'binary_integer' => 'boolean', + 'varchar' => 'string', + 'varchar2' => 'string', + 'nvarchar2' => 'string', + 'char' => 'string', + 'nchar' => 'string', + 'date' => 'datetime', + 'timestamp' => 'datetime', + 'timestamptz' => 'datetimetz', + 'float' => 'float', + 'long' => 'string', + 'clob' => 'text', + 'nclob' => 'text', + 'raw' => 'text', + 'long raw' => 'text', + 'rowid' => 'string', + 'urowid' => 'string', + 'blob' => 'blob', + ); + } + + /** + * {@inheritDoc} + */ + public function releaseSavePoint($savepoint) + { + return ''; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\OracleKeywords'; + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'BLOB'; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php b/src/core/libs/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php new file mode 100644 index 0000000..0dbdb1b --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/PostgreSqlPlatform.php @@ -0,0 +1,762 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\Schema\TableDiff, + Doctrine\DBAL\Schema\Table; + +/** + * PostgreSqlPlatform. + * + * @since 2.0 + * @author Roman Borschel <roman@code-factory.org> + * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @todo Rename: PostgreSQLPlatform + */ +class PostgreSqlPlatform extends AbstractPlatform +{ + /** + * {@inheritDoc} + */ + public function getSubstringExpression($value, $from, $length = null) + { + if ($length === null) { + return 'SUBSTR(' . $value . ', ' . $from . ')'; + } + + return 'SUBSTR(' . $value . ', ' . $from . ', ' . $length . ')'; + } + + /** + * {@inheritDoc} + */ + public function getNowExpression() + { + return 'LOCALTIMESTAMP(0)'; + } + + /** + * {@inheritDoc} + */ + public function getRegexpExpression() + { + return 'SIMILAR TO'; + } + + /** + * {@inheritDoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos !== false) { + $str = $this->getSubstringExpression($str, $startPos); + + return 'CASE WHEN (POSITION('.$substr.' IN '.$str.') = 0) THEN 0 ELSE (POSITION('.$substr.' IN '.$str.') + '.($startPos-1).') END'; + } + + return 'POSITION('.$substr.' IN '.$str.')'; + } + + /** + * {@inheritDoc} + */ + public function getDateDiffExpression($date1, $date2) + { + return '(DATE(' . $date1 . ')-DATE(' . $date2 . '))'; + } + + /** + * {@inheritDoc} + */ + public function getDateAddDaysExpression($date, $days) + { + return "(" . $date ." + (" . $days . " || ' day')::interval)"; + } + + /** + * {@inheritDoc} + */ + public function getDateSubDaysExpression($date, $days) + { + return "(" . $date ." - (" . $days . " || ' day')::interval)"; + } + + /** + * {@inheritDoc} + */ + public function getDateAddMonthExpression($date, $months) + { + return "(" . $date ." + (" . $months . " || ' month')::interval)"; + } + + /** + * {@inheritDoc} + */ + public function getDateSubMonthExpression($date, $months) + { + return "(" . $date ." - (" . $months . " || ' month')::interval)"; + } + + /** + * {@inheritDoc} + */ + public function supportsSequences() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsSchemas() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsCommentOnStatement() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function prefersSequences() + { + return true; + } + + public function getListDatabasesSQL() + { + return 'SELECT datname FROM pg_database'; + } + + public function getListSequencesSQL($database) + { + return "SELECT + c.relname, n.nspname AS schemaname + FROM + pg_class c, pg_namespace n + WHERE relkind = 'S' AND n.oid = c.relnamespace AND + (n.nspname NOT LIKE 'pg_%' AND n.nspname != 'information_schema')"; + } + + public function getListTablesSQL() + { + return "SELECT tablename AS table_name, schemaname AS schema_name + FROM pg_tables WHERE schemaname NOT LIKE 'pg_%' AND schemaname != 'information_schema' AND tablename != 'geometry_columns' AND tablename != 'spatial_ref_sys'"; + } + + /** + * {@inheritDoc} + */ + public function getListViewsSQL($database) + { + return 'SELECT viewname, definition FROM pg_views'; + } + + public function getListTableForeignKeysSQL($table, $database = null) + { + return "SELECT r.conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef + FROM pg_catalog.pg_constraint r + WHERE r.conrelid = + ( + SELECT c.oid + FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n + WHERE " .$this->getTableWhereClause($table) ." AND n.oid = c.relnamespace + ) + AND r.contype = 'f'"; + } + + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + public function getDropViewSQL($name) + { + return 'DROP VIEW '. $name; + } + + public function getListTableConstraintsSQL($table) + { + return "SELECT + relname + FROM + pg_class + WHERE oid IN ( + SELECT indexrelid + FROM pg_index, pg_class + WHERE pg_class.relname = '$table' + AND pg_class.oid = pg_index.indrelid + AND (indisunique = 't' OR indisprimary = 't') + )"; + } + + /** + * {@inheritDoc} + * + * @license New BSD License + * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + return "SELECT relname, pg_index.indisunique, pg_index.indisprimary, + pg_index.indkey, pg_index.indrelid + FROM pg_class, pg_index + WHERE oid IN ( + SELECT indexrelid + FROM pg_index si, pg_class sc, pg_namespace sn + WHERE " . $this->getTableWhereClause($table, 'sc', 'sn')." AND sc.oid=si.indrelid AND sc.relnamespace = sn.oid + ) AND pg_index.indexrelid = oid"; + } + + /** + * @param string $table + * @param string $classAlias + * @param string $namespaceAlias + * + * @return string + */ + private function getTableWhereClause($table, $classAlias = 'c', $namespaceAlias = 'n') + { + $whereClause = $namespaceAlias.".nspname NOT IN ('pg_catalog', 'information_schema', 'pg_toast') AND "; + if (strpos($table, ".") !== false) { + list($schema, $table) = explode(".", $table); + $schema = "'" . $schema . "'"; + } else { + $schema = "ANY(string_to_array((select setting from pg_catalog.pg_settings where name = 'search_path'),','))"; + } + $whereClause .= "$classAlias.relname = '" . $table . "' AND $namespaceAlias.nspname = $schema"; + + return $whereClause; + } + + public function getListTableColumnsSQL($table, $database = null) + { + return "SELECT + a.attnum, + a.attname AS field, + t.typname AS type, + format_type(a.atttypid, a.atttypmod) AS complete_type, + (SELECT t1.typname FROM pg_catalog.pg_type t1 WHERE t1.oid = t.typbasetype) AS domain_type, + (SELECT format_type(t2.typbasetype, t2.typtypmod) FROM pg_catalog.pg_type t2 + WHERE t2.typtype = 'd' AND t2.typname = format_type(a.atttypid, a.atttypmod)) AS domain_complete_type, + a.attnotnull AS isnotnull, + (SELECT 't' + FROM pg_index + WHERE c.oid = pg_index.indrelid + AND pg_index.indkey[0] = a.attnum + AND pg_index.indisprimary = 't' + ) AS pri, + (SELECT pg_attrdef.adsrc + FROM pg_attrdef + WHERE c.oid = pg_attrdef.adrelid + AND pg_attrdef.adnum=a.attnum + ) AS default, + (SELECT pg_description.description + FROM pg_description WHERE pg_description.objoid = c.oid AND a.attnum = pg_description.objsubid + ) AS comment + FROM pg_attribute a, pg_class c, pg_type t, pg_namespace n + WHERE ".$this->getTableWhereClause($table, 'c', 'n') ." + AND a.attnum > 0 + AND a.attrelid = c.oid + AND a.atttypid = t.oid + AND n.oid = c.relnamespace + ORDER BY a.attnum"; + } + + /** + * {@inheritDoc} + */ + public function getCreateDatabaseSQL($name) + { + return 'CREATE DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + public function getAdvancedForeignKeyOptionsSQL(\Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey) + { + $query = ''; + + if ($foreignKey->hasOption('match')) { + $query .= ' MATCH ' . $foreignKey->getOption('match'); + } + + $query .= parent::getAdvancedForeignKeyOptionsSQL($foreignKey); + + if ($foreignKey->hasOption('deferrable') && $foreignKey->getOption('deferrable') !== false) { + $query .= ' DEFERRABLE'; + } else { + $query .= ' NOT DEFERRABLE'; + } + + if ($foreignKey->hasOption('feferred') && $foreignKey->getOption('feferred') !== false) { + $query .= ' INITIALLY DEFERRED'; + } else { + $query .= ' INITIALLY IMMEDIATE'; + } + + return $query; + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $sql = array(); + $commentsSQL = array(); + $columnSql = array(); + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $query = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + if ($comment = $this->getColumnComment($column)) { + $commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment); + } + } + + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $query = 'DROP ' . $column->getQuotedName($this); + $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + } + + foreach ($diff->changedColumns as $columnDiff) { + /** @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + $oldColumnName = $columnDiff->oldColumnName; + $column = $columnDiff->column; + + if ($columnDiff->hasChanged('type')) { + $type = $column->getType(); + + // here was a server version check before, but DBAL API does not support this anymore. + $query = 'ALTER ' . $oldColumnName . ' TYPE ' . $type->getSqlDeclaration($column->toArray(), $this); + $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + } + + if ($columnDiff->hasChanged('default')) { + $query = 'ALTER ' . $oldColumnName . ' SET ' . $this->getDefaultValueDeclarationSQL($column->toArray()); + $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + } + + if ($columnDiff->hasChanged('notnull')) { + $query = 'ALTER ' . $oldColumnName . ' ' . ($column->getNotNull() ? 'SET' : 'DROP') . ' NOT NULL'; + $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + } + + if ($columnDiff->hasChanged('autoincrement')) { + if ($column->getAutoincrement()) { + // add autoincrement + $seqName = $diff->name . '_' . $oldColumnName . '_seq'; + + $sql[] = "CREATE SEQUENCE " . $seqName; + $sql[] = "SELECT setval('" . $seqName . "', (SELECT MAX(" . $oldColumnName . ") FROM " . $diff->name . "))"; + $query = "ALTER " . $oldColumnName . " SET DEFAULT nextval('" . $seqName . "')"; + $sql[] = "ALTER TABLE " . $diff->name . " " . $query; + } else { + // Drop autoincrement, but do NOT drop the sequence. It might be re-used by other tables or have + $query = "ALTER " . $oldColumnName . " " . "DROP DEFAULT"; + $sql[] = "ALTER TABLE " . $diff->name . " " . $query; + } + } + + if ($columnDiff->hasChanged('comment') && $comment = $this->getColumnComment($column)) { + $commentsSQL[] = $this->getCommentOnColumnSQL($diff->name, $column->getName(), $comment); + } + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME COLUMN ' . $oldColumnName . ' TO ' . $column->getQuotedName($this); + } + + $tableSql = array(); + + if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { + if ($diff->newName !== false) { + $sql[] = 'ALTER TABLE ' . $diff->name . ' RENAME TO ' . $diff->newName; + } + + $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff), $commentsSQL); + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * {@inheritDoc} + */ + public function getCreateSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence) + { + return 'CREATE SEQUENCE ' . $sequence->getQuotedName($this) . + ' INCREMENT BY ' . $sequence->getAllocationSize() . + ' MINVALUE ' . $sequence->getInitialValue() . + ' START ' . $sequence->getInitialValue(); + } + + /** + * {@inheritDoc} + */ + public function getAlterSequenceSQL(\Doctrine\DBAL\Schema\Sequence $sequence) + { + return 'ALTER SEQUENCE ' . $sequence->getQuotedName($this) . + ' INCREMENT BY ' . $sequence->getAllocationSize(); + } + + /** + * {@inheritDoc} + */ + public function getDropSequenceSQL($sequence) + { + if ($sequence instanceof \Doctrine\DBAL\Schema\Sequence) { + $sequence = $sequence->getQuotedName($this); + } + return 'DROP SEQUENCE ' . $sequence; + } + + /** + * {@inheritDoc} + */ + public function getDropForeignKeySQL($foreignKey, $table) + { + return $this->getDropConstraintSQL($foreignKey, $table); + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) + { + $queryFields = $this->getColumnDeclarationListSQL($columns); + + if (isset($options['primary']) && ! empty($options['primary'])) { + $keyColumns = array_unique(array_values($options['primary'])); + $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; + } + + $query = 'CREATE TABLE ' . $tableName . ' (' . $queryFields . ')'; + + $sql[] = $query; + + if (isset($options['indexes']) && ! empty($options['indexes'])) { + foreach ($options['indexes'] as $index) { + $sql[] = $this->getCreateIndexSQL($index, $tableName); + } + } + + if (isset($options['foreignKeys'])) { + foreach ((array) $options['foreignKeys'] as $definition) { + $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); + } + } + + return $sql; + } + + /** + * {@inheritDoc} + * + * Postgres wants boolean values converted to the strings 'true'/'false'. + */ + public function convertBooleans($item) + { + if (is_array($item)) { + foreach ($item as $key => $value) { + if (is_bool($value) || is_numeric($item)) { + $item[$key] = ($value) ? 'true' : 'false'; + } + } + } else { + if (is_bool($item) || is_numeric($item)) { + $item = ($item) ? 'true' : 'false'; + } + } + + return $item; + } + + public function getSequenceNextValSQL($sequenceName) + { + return "SELECT NEXTVAL('" . $sequenceName . "')"; + } + + /** + * {@inheritDoc} + */ + public function getSetTransactionIsolationSQL($level) + { + return 'SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL ' + . $this->_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $field) + { + return 'BOOLEAN'; + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $field) + { + if ( ! empty($field['autoincrement'])) { + return 'SERIAL'; + } + + return 'INT'; + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + if ( ! empty($field['autoincrement'])) { + return 'BIGSERIAL'; + } + return 'BIGINT'; + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + return 'SMALLINT'; + } + + /** + * {@inheritDoc} + */ + public function getGuidTypeDeclarationSQL(array $field) + { + return 'UUID'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIMESTAMP(0) WITHOUT TIME ZONE'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTzTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIMESTAMP(0) WITH TIME ZONE'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME(0) WITHOUT TIME ZONE'; + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + return ''; + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') + : ($length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'); + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'TEXT'; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'postgresql'; + } + + /** + * {@inheritDoc} + * + * PostgreSQL returns all column names in SQL result sets in lowercase. + */ + public function getSQLResultCasing($column) + { + return strtolower($column); + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTzFormatString() + { + return 'Y-m-d H:i:sO'; + } + + /** + * {@inheritDoc} + */ + public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName) + { + return 'INSERT INTO ' . $quotedTableName . ' (' . $quotedIdentifierColumnName . ') VALUES (DEFAULT)'; + } + + /** + * {@inheritDoc} + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + return 'TRUNCATE '.$tableName.' '.(($cascade)?'CASCADE':''); + } + + /** + * {@inheritDoc} + */ + public function getReadLockSQL() + { + return 'FOR SHARE'; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = array( + 'smallint' => 'smallint', + 'int2' => 'smallint', + 'serial' => 'integer', + 'serial4' => 'integer', + 'int' => 'integer', + 'int4' => 'integer', + 'integer' => 'integer', + 'bigserial' => 'bigint', + 'serial8' => 'bigint', + 'bigint' => 'bigint', + 'int8' => 'bigint', + 'bool' => 'boolean', + 'boolean' => 'boolean', + 'text' => 'text', + 'varchar' => 'string', + 'interval' => 'string', + '_varchar' => 'string', + 'char' => 'string', + 'bpchar' => 'string', + 'date' => 'date', + 'datetime' => 'datetime', + 'timestamp' => 'datetime', + 'timestamptz' => 'datetimetz', + 'time' => 'time', + 'timetz' => 'time', + 'float' => 'float', + 'float4' => 'float', + 'float8' => 'float', + 'double' => 'float', + 'double precision' => 'float', + 'real' => 'float', + 'decimal' => 'decimal', + 'money' => 'decimal', + 'numeric' => 'decimal', + 'year' => 'date', + 'uuid' => 'guid', + 'bytea' => 'blob', + ); + } + + /** + * {@inheritDoc} + */ + public function getVarcharMaxLength() + { + return 65535; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords'; + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'BYTEA'; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/SQLAzurePlatform.php b/src/core/libs/Doctrine/DBAL/Platforms/SQLAzurePlatform.php new file mode 100644 index 0000000..238e54f --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/SQLAzurePlatform.php @@ -0,0 +1,51 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\Schema\Table; + +/** + * Platform to ensure compatibility of Doctrine with SQL Azure + * + * On top of SQL Server 2008 the following functionality is added: + * + * - Create tables with the FEDERATED ON syntax. + */ +class SQLAzurePlatform extends SQLServer2008Platform +{ + /** + * {@inheritDoc} + */ + public function getCreateTableSQL(Table $table, $createFlags=self::CREATE_INDEXES) + { + $sql = parent::getCreateTableSQL($table, $createFlags); + + if ($table->hasOption('azure.federatedOnColumnName')) { + $distributionName = $table->getOption('azure.federatedOnDistributionName'); + $columnName = $table->getOption('azure.federatedOnColumnName'); + $stmt = ' FEDERATED ON (' . $distributionName . ' = ' . $columnName . ')'; + + $sql[0] = $sql[0] . $stmt; + } + + return $sql; + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Platforms/SQLServer2005Platform.php b/src/core/libs/Doctrine/DBAL/Platforms/SQLServer2005Platform.php new file mode 100644 index 0000000..be3725b --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/SQLServer2005Platform.php @@ -0,0 +1,54 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Platforms; + +/** + * Platform to ensure compatibility of Doctrine with SQLServer2005 version and + * higher. + * + * Differences to SQL Server 2008 are: + * + * - DATETIME2 datatype does not exist, only DATETIME which has a precision of + * 3. This is not supported by PHP DateTime, so we are emulating it by + * setting .000 manually. + * - Starting with SQLServer2005 VARCHAR(MAX), VARBINARY(MAX) and + * NVARCHAR(max) replace the old TEXT, NTEXT and IMAGE types. See + * {@link http://www.sql-server-helper.com/faq/sql-server-2005-varchar-max-p01.aspx} + * for more information. + */ +class SQLServer2005Platform extends SQLServerPlatform +{ + /** + * {@inheritDoc} + */ + public function supportsLimitOffset() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'VARCHAR(MAX)'; + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Platforms/SQLServer2008Platform.php b/src/core/libs/Doctrine/DBAL/Platforms/SQLServer2008Platform.php new file mode 100644 index 0000000..909ab84 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/SQLServer2008Platform.php @@ -0,0 +1,100 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Platforms; + +/** + * Platform to ensure compatibility of Doctrine with SQLServer2008 version. + * + * Differences to SQL Server 2005 and before are that a new DATETIME2 type was + * introduced that has a higher precision. + */ +class SQLServer2008Platform extends SQLServer2005Platform +{ + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + // 3 - microseconds precision length + // http://msdn.microsoft.com/en-us/library/ms187819.aspx + return 'DATETIME2(6)'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME(0)'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeFormatString() + { + return 'Y-m-d H:i:s.u'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTzFormatString() + { + return 'Y-m-d H:i:s.u P'; + } + + /** + * {@inheritDoc} + */ + public function getDateFormatString() + { + return 'Y-m-d'; + } + + /** + * {@inheritDoc} + */ + public function getTimeFormatString() + { + return 'H:i:s'; + } + + /** + * {@inheritDoc} + * + * Adding Datetime2 Type + */ + protected function initializeDoctrineTypeMappings() + { + parent::initializeDoctrineTypeMappings(); + $this->doctrineTypeMapping['datetime2'] = 'datetime'; + $this->doctrineTypeMapping['date'] = 'date'; + $this->doctrineTypeMapping['time'] = 'time'; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/SQLServerPlatform.php b/src/core/libs/Doctrine/DBAL/Platforms/SQLServerPlatform.php new file mode 100644 index 0000000..6557fed --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/SQLServerPlatform.php @@ -0,0 +1,905 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\Schema\TableDiff; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Schema\ForeignKeyConstraint; +use Doctrine\DBAL\Schema\Index; +use Doctrine\DBAL\Schema\Table; + +/** + * The SQLServerPlatform provides the behavior, features and SQL dialect of the + * Microsoft SQL Server database platform. + * + * @since 2.0 + * @author Roman Borschel <roman@code-factory.org> + * @author Jonathan H. Wage <jonwage@gmail.com> + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class SQLServerPlatform extends AbstractPlatform +{ + /** + * {@inheritDoc} + */ + public function getDateDiffExpression($date1, $date2) + { + return 'DATEDIFF(day, ' . $date2 . ',' . $date1 . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateAddDaysExpression($date, $days) + { + return 'DATEADD(day, ' . $days . ', ' . $date . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateSubDaysExpression($date, $days) + { + return 'DATEADD(day, -1 * ' . $days . ', ' . $date . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateAddMonthExpression($date, $months) + { + return 'DATEADD(month, ' . $months . ', ' . $date . ')'; + } + + /** + * {@inheritDoc} + */ + public function getDateSubMonthExpression($date, $months) + { + return 'DATEADD(month, -1 * ' . $months . ', ' . $date . ')'; + } + + /** + * {@inheritDoc} + * + * MsSql prefers "autoincrement" identity columns since sequences can only + * be emulated with a table. + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + * + * MsSql supports this through AUTO_INCREMENT columns. + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function supportsReleaseSavepoints() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function getCreateDatabaseSQL($name) + { + return 'CREATE DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + public function getDropDatabaseSQL($name) + { + return 'DROP DATABASE ' . $name; + } + + /** + * {@inheritDoc} + */ + public function supportsCreateDropDatabase() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function getDropForeignKeySQL($foreignKey, $table) + { + if ($foreignKey instanceof ForeignKeyConstraint) { + $foreignKey = $foreignKey->getQuotedName($this); + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return 'ALTER TABLE ' . $table . ' DROP CONSTRAINT ' . $foreignKey; + } + + /** + * {@inheritDoc} + */ + public function getDropIndexSQL($index, $table = null) + { + if ($index instanceof Index) { + $index = $index->getQuotedName($this); + } else if (!is_string($index)) { + throw new \InvalidArgumentException('AbstractPlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); + } + + if (!isset($table)) { + return 'DROP INDEX ' . $index; + } + + if ($table instanceof Table) { + $table = $table->getQuotedName($this); + } + + return "IF EXISTS (SELECT * FROM sysobjects WHERE name = '$index') + ALTER TABLE " . $table . " DROP CONSTRAINT " . $index . " + ELSE + DROP INDEX " . $index . " ON " . $table; + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($tableName, array $columns, array $options = array()) + { + // @todo does other code breaks because of this? + // force primary keys to be not null + foreach ($columns as &$column) { + if (isset($column['primary']) && $column['primary']) { + $column['notnull'] = true; + } + } + + $columnListSql = $this->getColumnDeclarationListSQL($columns); + + if (isset($options['uniqueConstraints']) && !empty($options['uniqueConstraints'])) { + foreach ($options['uniqueConstraints'] as $name => $definition) { + $columnListSql .= ', ' . $this->getUniqueConstraintDeclarationSQL($name, $definition); + } + } + + if (isset($options['primary']) && !empty($options['primary'])) { + $flags = ''; + if (isset($options['primary_index']) && $options['primary_index']->hasFlag('nonclustered')) { + $flags = ' NONCLUSTERED'; + } + $columnListSql .= ', PRIMARY KEY' . $flags . ' (' . implode(', ', array_unique(array_values($options['primary']))) . ')'; + } + + $query = 'CREATE TABLE ' . $tableName . ' (' . $columnListSql; + + $check = $this->getCheckDeclarationSQL($columns); + if (!empty($check)) { + $query .= ', ' . $check; + } + $query .= ')'; + + $sql[] = $query; + + if (isset($options['indexes']) && !empty($options['indexes'])) { + foreach ($options['indexes'] as $index) { + $sql[] = $this->getCreateIndexSQL($index, $tableName); + } + } + + if (isset($options['foreignKeys'])) { + foreach ((array) $options['foreignKeys'] as $definition) { + $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); + } + } + + return $sql; + } + + /** + * {@inheritDoc} + */ + public function getCreatePrimaryKeySQL(Index $index, $table) + { + $flags = ''; + if ($index->hasFlag('nonclustered')) { + $flags = ' NONCLUSTERED'; + } + return 'ALTER TABLE ' . $table . ' ADD PRIMARY KEY' . $flags . ' (' . $this->getIndexFieldDeclarationListSQL($index->getColumns()) . ')'; + } + + /** + * {@inheritDoc} + */ + public function getUniqueConstraintDeclarationSQL($name, Index $index) + { + $constraint = parent::getUniqueConstraintDeclarationSQL($name, $index); + + $constraint = $this->_appendUniqueConstraintDefinition($constraint, $index); + + return $constraint; + } + + /** + * {@inheritDoc} + */ + public function getCreateIndexSQL(Index $index, $table) + { + $constraint = parent::getCreateIndexSQL($index, $table); + + if ($index->isUnique()) { + $constraint = $this->_appendUniqueConstraintDefinition($constraint, $index); + } + + return $constraint; + } + + /** + * {@inheritDoc} + */ + protected function getCreateIndexSQLFlags(Index $index) + { + $type = ''; + if ($index->isUnique()) { + $type .= 'UNIQUE '; + } + + if ($index->hasFlag('clustered')) { + $type .= 'CLUSTERED '; + } else if ($index->hasFlag('nonclustered')) { + $type .= 'NONCLUSTERED '; + } + + return $type; + } + + /** + * Extend unique key constraint with required filters + * + * @param string $sql + * @param Index $index + * + * @return string + */ + private function _appendUniqueConstraintDefinition($sql, Index $index) + { + $fields = array(); + foreach ($index->getColumns() as $field => $definition) { + if (!is_array($definition)) { + $field = $definition; + } + + $fields[] = $field . ' IS NOT NULL'; + } + + return $sql . ' WHERE ' . implode(' AND ', $fields); + } + + /** + * {@inheritDoc} + */ + public function getAlterTableSQL(TableDiff $diff) + { + $queryParts = array(); + $sql = array(); + $columnSql = array(); + + foreach ($diff->addedColumns as $column) { + if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { + continue; + } + + $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + } + + foreach ($diff->removedColumns as $column) { + if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { + continue; + } + + $queryParts[] = 'DROP COLUMN ' . $column->getQuotedName($this); + } + + foreach ($diff->changedColumns as $columnDiff) { + if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { + continue; + } + + /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ + $column = $columnDiff->column; + $queryParts[] = 'ALTER COLUMN ' . + $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + } + + foreach ($diff->renamedColumns as $oldColumnName => $column) { + if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { + continue; + } + + $sql[] = "sp_RENAME '". $diff->name. ".". $oldColumnName . "' , '".$column->getQuotedName($this)."', 'COLUMN'"; + $queryParts[] = 'ALTER COLUMN ' . + $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + } + + $tableSql = array(); + + if ($this->onSchemaAlterTable($diff, $tableSql)) { + return array_merge($tableSql, $columnSql); + } + + foreach ($queryParts as $query) { + $sql[] = 'ALTER TABLE ' . $diff->name . ' ' . $query; + } + + $sql = array_merge($sql, $this->_getAlterTableIndexForeignKeySQL($diff)); + + if ($diff->newName !== false) { + $sql[] = "sp_RENAME '" . $diff->name . "', '" . $diff->newName . "'"; + } + + return array_merge($sql, $tableSql, $columnSql); + } + + /** + * {@inheritDoc} + */ + public function getEmptyIdentityInsertSQL($quotedTableName, $quotedIdentifierColumnName) + { + return 'INSERT INTO ' . $quotedTableName . ' DEFAULT VALUES'; + } + + /** + * {@inheritDoc} + */ + public function getShowDatabasesSQL() + { + return 'SHOW DATABASES'; + } + + /** + * {@inheritDoc} + */ + public function getListTablesSQL() + { + // "sysdiagrams" table must be ignored as it's internal SQL Server table for Database Diagrams + return "SELECT name FROM sysobjects WHERE type = 'U' AND name != 'sysdiagrams' ORDER BY name"; + } + + /** + * {@inheritDoc} + */ + public function getListTableColumnsSQL($table, $database = null) + { + return "exec sp_columns @table_name = '" . $table . "'"; + } + + /** + * {@inheritDoc} + */ + public function getListTableForeignKeysSQL($table, $database = null) + { + return "SELECT f.name AS ForeignKey, + SCHEMA_NAME (f.SCHEMA_ID) AS SchemaName, + OBJECT_NAME (f.parent_object_id) AS TableName, + COL_NAME (fc.parent_object_id,fc.parent_column_id) AS ColumnName, + SCHEMA_NAME (o.SCHEMA_ID) ReferenceSchemaName, + OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName, + COL_NAME(fc.referenced_object_id,fc.referenced_column_id) AS ReferenceColumnName, + f.delete_referential_action_desc, + f.update_referential_action_desc + FROM sys.foreign_keys AS f + INNER JOIN sys.foreign_key_columns AS fc + INNER JOIN sys.objects AS o ON o.OBJECT_ID = fc.referenced_object_id + ON f.OBJECT_ID = fc.constraint_object_id + WHERE OBJECT_NAME (f.parent_object_id) = '" . $table . "'"; + } + + /** + * {@inheritDoc} + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + return "exec sp_helpindex '" . $table . "'"; + } + + /** + * {@inheritDoc} + */ + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + /** + * {@inheritDoc} + */ + public function getListViewsSQL($database) + { + return "SELECT name FROM sysobjects WHERE type = 'V' ORDER BY name"; + } + + /** + * {@inheritDoc} + */ + public function getDropViewSQL($name) + { + return 'DROP VIEW ' . $name; + } + + /** + * {@inheritDoc} + */ + public function getRegexpExpression() + { + return 'RLIKE'; + } + + /** + * {@inheritDoc} + */ + public function getGuidExpression() + { + return 'UUID()'; + } + + /** + * {@inheritDoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos == false) { + return 'CHARINDEX(' . $substr . ', ' . $str . ')'; + } + + return 'CHARINDEX(' . $substr . ', ' . $str . ', ' . $startPos . ')'; + } + + /** + * {@inheritDoc} + */ + public function getModExpression($expression1, $expression2) + { + return $expression1 . ' % ' . $expression2; + } + + /** + * {@inheritDoc} + */ + public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) + { + if ( ! $char) { + switch ($pos) { + case self::TRIM_LEADING: + $trimFn = 'LTRIM'; + break; + + case self::TRIM_TRAILING: + $trimFn = 'RTRIM'; + break; + + default: + return 'LTRIM(RTRIM(' . $str . '))'; + } + + return $trimFn . '(' . $str . ')'; + } + + /** Original query used to get those expressions + declare @c varchar(100) = 'xxxBarxxx', @trim_char char(1) = 'x'; + declare @pat varchar(10) = '%[^' + @trim_char + ']%'; + select @c as string + , @trim_char as trim_char + , stuff(@c, 1, patindex(@pat, @c) - 1, null) as trim_leading + , reverse(stuff(reverse(@c), 1, patindex(@pat, reverse(@c)) - 1, null)) as trim_trailing + , reverse(stuff(reverse(stuff(@c, 1, patindex(@pat, @c) - 1, null)), 1, patindex(@pat, reverse(stuff(@c, 1, patindex(@pat, @c) - 1, null))) - 1, null)) as trim_both; + */ + $pattern = "'%[^' + $char + ']%'"; + + if ($pos == self::TRIM_LEADING) { + return 'stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null)'; + } + + if ($pos == self::TRIM_TRAILING) { + return 'reverse(stuff(reverse(' . $str . '), 1, patindex(' . $pattern . ', reverse(' . $str . ')) - 1, null))'; + } + + return 'reverse(stuff(reverse(stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null)), 1, patindex(' . $pattern . ', reverse(stuff(' . $str . ', 1, patindex(' . $pattern . ', ' . $str . ') - 1, null))) - 1, null))'; + } + + /** + * {@inheritDoc} + */ + public function getConcatExpression() + { + $args = func_get_args(); + + return '(' . implode(' + ', $args) . ')'; + } + + public function getListDatabasesSQL() + { + return 'SELECT * FROM SYS.DATABASES'; + } + + /** + * {@inheritDoc} + */ + public function getSubstringExpression($value, $from, $length = null) + { + if (!is_null($length)) { + return 'SUBSTRING(' . $value . ', ' . $from . ', ' . $length . ')'; + } + + return 'SUBSTRING(' . $value . ', ' . $from . ', LEN(' . $value . ') - ' . $from . ' + 1)'; + } + + /** + * {@inheritDoc} + */ + public function getLengthExpression($column) + { + return 'LEN(' . $column . ')'; + } + + /** + * {@inheritDoc} + */ + public function getSetTransactionIsolationSQL($level) + { + return 'SET TRANSACTION ISOLATION LEVEL ' . $this->_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $field) + { + return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + return 'SMALLINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getGuidTypeDeclarationSQL(array $field) + { + return 'UNIQUEIDENTIFIER'; + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'NCHAR(' . $length . ')' : 'CHAR(255)') : ($length ? 'NVARCHAR(' . $length . ')' : 'NVARCHAR(255)'); + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'TEXT'; + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + $autoinc = ''; + if (!empty($columnDef['autoincrement'])) { + $autoinc = ' IDENTITY'; + } + $unsigned = (isset($columnDef['unsigned']) && $columnDef['unsigned']) ? ' UNSIGNED' : ''; + + return $unsigned . $autoinc; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $field) + { + return 'BIT'; + } + + /** + * {@inheritDoc} + * + * @link http://lists.bestpractical.com/pipermail/rt-devel/2005-June/007339.html + */ + protected function doModifyLimitQuery($query, $limit, $offset = null) + { + if ($limit > 0) { + if ($offset == 0) { + $query = preg_replace('/^(SELECT\s(DISTINCT\s)?)/i', '\1TOP ' . $limit . ' ', $query); + } else { + $orderby = stristr($query, 'ORDER BY'); + + if ( ! $orderby) { + $over = 'ORDER BY (SELECT 0)'; + } else { + $over = preg_replace('/\"[^,]*\".\"([^,]*)\"/i', '"inner_tbl"."$1"', $orderby); + } + + // Remove ORDER BY clause from $query + $query = preg_replace('/\s+ORDER BY(.*)/', '', $query); + $query = preg_replace('/^SELECT\s/', '', $query); + + $start = $offset + 1; + $end = $offset + $limit; + + $query = "SELECT * FROM (SELECT ROW_NUMBER() OVER ($over) AS doctrine_rownum, $query) AS doctrine_tbl WHERE doctrine_rownum BETWEEN $start AND $end"; + } + } + + return $query; + } + + /** + * {@inheritDoc} + */ + public function supportsLimitOffset() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function convertBooleans($item) + { + if (is_array($item)) { + foreach ($item as $key => $value) { + if (is_bool($value) || is_numeric($item)) { + $item[$key] = ($value) ? 1 : 0; + } + } + } else if (is_bool($item) || is_numeric($item)) { + $item = ($item) ? 1 : 0; + } + + return $item; + } + + /** + * {@inheritDoc} + */ + public function getCreateTemporaryTableSnippetSQL() + { + return "CREATE TABLE"; + } + + /** + * {@inheritDoc} + */ + public function getTemporaryTableName($tableName) + { + return '#' . $tableName; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeFormatString() + { + return 'Y-m-d H:i:s.000'; + } + + /** + * {@inheritDoc} + */ + public function getDateFormatString() + { + return 'Y-m-d H:i:s.000'; + } + + /** + * {@inheritDoc} + */ + public function getTimeFormatString() + { + return 'Y-m-d H:i:s.000'; + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTzFormatString() + { + return $this->getDateTimeFormatString(); + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'mssql'; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = array( + 'bigint' => 'bigint', + 'numeric' => 'decimal', + 'bit' => 'boolean', + 'smallint' => 'smallint', + 'decimal' => 'decimal', + 'smallmoney' => 'integer', + 'int' => 'integer', + 'tinyint' => 'smallint', + 'money' => 'integer', + 'float' => 'float', + 'real' => 'float', + 'double' => 'float', + 'double precision' => 'float', + 'datetimeoffset' => 'datetimetz', + 'smalldatetime' => 'datetime', + 'datetime' => 'datetime', + 'char' => 'string', + 'varchar' => 'string', + 'text' => 'text', + 'nchar' => 'string', + 'nvarchar' => 'string', + 'ntext' => 'text', + 'binary' => 'text', + 'varbinary' => 'blob', + 'image' => 'text', + 'uniqueidentifier' => 'guid', + ); + } + + /** + * {@inheritDoc} + */ + public function createSavePoint($savepoint) + { + return 'SAVE TRANSACTION ' . $savepoint; + } + + /** + * {@inheritDoc} + */ + public function releaseSavePoint($savepoint) + { + return ''; + } + + /** + * {@inheritDoc} + */ + public function rollbackSavePoint($savepoint) + { + return 'ROLLBACK TRANSACTION ' . $savepoint; + } + + /** + * {@inheritDoc} + */ + public function appendLockHint($fromClause, $lockMode) + { + // @todo coorect + if ($lockMode == \Doctrine\DBAL\LockMode::PESSIMISTIC_READ) { + return $fromClause . ' WITH (tablockx)'; + } + + if ($lockMode == \Doctrine\DBAL\LockMode::PESSIMISTIC_WRITE) { + return $fromClause . ' WITH (tablockx)'; + } + + return $fromClause; + } + + /** + * {@inheritDoc} + */ + public function getForUpdateSQL() + { + return ' '; + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\MsSQLKeywords'; + } + + /** + * {@inheritDoc} + */ + public function quoteSingleIdentifier($str) + { + return "[" . str_replace("]", "][", $str) . "]"; + } + + /** + * {@inheritDoc} + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + return 'TRUNCATE TABLE '.$tableName; + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'VARBINARY(MAX)'; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Platforms/SqlitePlatform.php b/src/core/libs/Doctrine/DBAL/Platforms/SqlitePlatform.php new file mode 100644 index 0000000..7ed5201 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Platforms/SqlitePlatform.php @@ -0,0 +1,529 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Platforms; + +use Doctrine\DBAL\DBALException; + +/** + * The SqlitePlatform class describes the specifics and dialects of the SQLite + * database platform. + * + * @since 2.0 + * @author Roman Borschel <roman@code-factory.org> + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @todo Rename: SQLitePlatform + */ +class SqlitePlatform extends AbstractPlatform +{ + /** + * {@inheritDoc} + */ + public function getRegexpExpression() + { + return 'RLIKE'; + } + + /** + * {@inheritDoc} + */ + public function getNowExpression($type = 'timestamp') + { + switch ($type) { + case 'time': + return 'time(\'now\')'; + case 'date': + return 'date(\'now\')'; + case 'timestamp': + default: + return 'datetime(\'now\')'; + } + } + + /** + * {@inheritDoc} + */ + public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) + { + $trimChar = ($char != false) ? (', ' . $char) : ''; + + switch ($pos) { + case self::TRIM_LEADING: + $trimFn = 'LTRIM'; + break; + + case self::TRIM_TRAILING: + $trimFn = 'RTRIM'; + break; + + default: + $trimFn = 'TRIM'; + } + + return $trimFn . '(' . $str . $trimChar . ')'; + } + + /** + * {@inheritDoc} + * + * SQLite only supports the 2 parameter variant of this function + */ + public function getSubstringExpression($value, $position, $length = null) + { + if ($length !== null) { + return 'SUBSTR(' . $value . ', ' . $position . ', ' . $length . ')'; + } + + return 'SUBSTR(' . $value . ', ' . $position . ', LENGTH(' . $value . '))'; + } + + /** + * {@inheritDoc} + */ + public function getLocateExpression($str, $substr, $startPos = false) + { + if ($startPos == false) { + return 'LOCATE('.$str.', '.$substr.')'; + } + + return 'LOCATE('.$str.', '.$substr.', '.$startPos.')'; + } + + /** + * {@inheritDoc} + */ + public function getDateDiffExpression($date1, $date2) + { + return 'ROUND(JULIANDAY('.$date1 . ')-JULIANDAY('.$date2.'))'; + } + + /** + * {@inheritDoc} + */ + public function getDateAddDaysExpression($date, $days) + { + return "DATE(" . $date . ",'+". $days . " day')"; + } + + /** + * {@inheritDoc} + */ + public function getDateSubDaysExpression($date, $days) + { + return "DATE(" . $date . ",'-". $days . " day')"; + } + + /** + * {@inheritDoc} + */ + public function getDateAddMonthExpression($date, $months) + { + return "DATE(" . $date . ",'+". $months . " month')"; + } + + /** + * {@inheritDoc} + */ + public function getDateSubMonthExpression($date, $months) + { + return "DATE(" . $date . ",'-". $months . " month')"; + } + + /** + * {@inheritDoc} + */ + protected function _getTransactionIsolationLevelSQL($level) + { + switch ($level) { + case \Doctrine\DBAL\Connection::TRANSACTION_READ_UNCOMMITTED: + return 0; + case \Doctrine\DBAL\Connection::TRANSACTION_READ_COMMITTED: + case \Doctrine\DBAL\Connection::TRANSACTION_REPEATABLE_READ: + case \Doctrine\DBAL\Connection::TRANSACTION_SERIALIZABLE: + return 1; + default: + return parent::_getTransactionIsolationLevelSQL($level); + } + } + + /** + * {@inheritDoc} + */ + public function getSetTransactionIsolationSQL($level) + { + return 'PRAGMA read_uncommitted = ' . $this->_getTransactionIsolationLevelSQL($level); + } + + /** + * {@inheritDoc} + */ + public function prefersIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getBooleanTypeDeclarationSQL(array $field) + { + return 'BOOLEAN'; + } + + /** + * {@inheritDoc} + */ + public function getIntegerTypeDeclarationSQL(array $field) + { + return $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getBigIntTypeDeclarationSQL(array $field) + { + return $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getTinyIntTypeDeclarationSql(array $field) + { + return $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getSmallIntTypeDeclarationSQL(array $field) + { + return $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getMediumIntTypeDeclarationSql(array $field) + { + return $this->_getCommonIntegerTypeDeclarationSQL($field); + } + + /** + * {@inheritDoc} + */ + public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATETIME'; + } + + /** + * {@inheritDoc} + */ + public function getDateTypeDeclarationSQL(array $fieldDeclaration) + { + return 'DATE'; + } + + /** + * {@inheritDoc} + */ + public function getTimeTypeDeclarationSQL(array $fieldDeclaration) + { + return 'TIME'; + } + + /** + * {@inheritDoc} + */ + protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) + { + return 'INTEGER'; + } + + /** + * {@inheritDoc} + */ + protected function _getCreateTableSQL($name, array $columns, array $options = array()) + { + $name = str_replace(".", "__", $name); + $queryFields = $this->getColumnDeclarationListSQL($columns); + + if (isset($options['primary']) && ! empty($options['primary'])) { + $keyColumns = array_unique(array_values($options['primary'])); + $queryFields.= ', PRIMARY KEY('.implode(', ', $keyColumns).')'; + } + + $query[] = 'CREATE TABLE ' . $name . ' (' . $queryFields . ')'; + + if (isset($options['indexes']) && ! empty($options['indexes'])) { + foreach ($options['indexes'] as $index => $indexDef) { + $query[] = $this->getCreateIndexSQL($indexDef, $name); + } + } + + if (isset($options['unique']) && ! empty($options['unique'])) { + foreach ($options['unique'] as $index => $indexDef) { + $query[] = $this->getCreateIndexSQL($indexDef, $name); + } + } + + return $query; + } + + /** + * {@inheritDoc} + */ + protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) + { + return $fixed ? ($length ? 'CHAR(' . $length . ')' : 'CHAR(255)') + : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT'); + } + + /** + * {@inheritDoc} + */ + public function getClobTypeDeclarationSQL(array $field) + { + return 'CLOB'; + } + + public function getListTableConstraintsSQL($table) + { + $table = str_replace(".", "__", $table); + + return "SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name = '$table' AND sql NOT NULL ORDER BY name"; + } + + public function getListTableColumnsSQL($table, $currentDatabase = null) + { + $table = str_replace(".", "__", $table); + + return "PRAGMA table_info($table)"; + } + + /** + * {@inheritDoc} + */ + public function getListTableIndexesSQL($table, $currentDatabase = null) + { + $table = str_replace(".", "__", $table); + + return "PRAGMA index_list($table)"; + } + + public function getListTablesSQL() + { + return "SELECT name FROM sqlite_master WHERE type = 'table' AND name != 'sqlite_sequence' AND name != 'geometry_columns' AND name != 'spatial_ref_sys' " + . "UNION ALL SELECT name FROM sqlite_temp_master " + . "WHERE type = 'table' ORDER BY name"; + } + + /** + * {@inheritDoc} + */ + public function getListViewsSQL($database) + { + return "SELECT name, sql FROM sqlite_master WHERE type='view' AND sql NOT NULL"; + } + + public function getCreateViewSQL($name, $sql) + { + return 'CREATE VIEW ' . $name . ' AS ' . $sql; + } + + public function getDropViewSQL($name) + { + return 'DROP VIEW '. $name; + } + + /** + * {@inheritDoc} + * + * SQLite does support foreign key constraints, but only in CREATE TABLE statements... + * This really limits their usefulness and requires SQLite specific handling, so + * we simply say that SQLite does NOT support foreign keys for now... + */ + public function supportsForeignKeyConstraints() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function supportsAlterTable() + { + return false; + } + + /** + * {@inheritDoc} + */ + public function supportsIdentityColumns() + { + return true; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return 'sqlite'; + } + + /** + * {@inheritDoc} + */ + public function getTruncateTableSQL($tableName, $cascade = false) + { + $tableName = str_replace(".", "__", $tableName); + return 'DELETE FROM '.$tableName; + } + + /** + * User-defined function for Sqlite that is used with PDO::sqliteCreateFunction() + * + * @param int|float $value + * + * @return float + */ + static public function udfSqrt($value) + { + return sqrt($value); + } + + /** + * User-defined function for Sqlite that implements MOD(a, b) + * + * @param integer $a + * @param integer $b + * + * @return integer + */ + static public function udfMod($a, $b) + { + return ($a % $b); + } + + /** + * @param string $str + * @param string $substr + * @param integer $offset + * + * @return integer + */ + static public function udfLocate($str, $substr, $offset = 0) + { + $pos = strpos($str, $substr, $offset); + if ($pos !== false) { + return $pos+1; + } + + return 0; + } + + public function getForUpdateSql() + { + return ''; + } + + /** + * {@inheritDoc} + */ + protected function initializeDoctrineTypeMappings() + { + $this->doctrineTypeMapping = array( + 'boolean' => 'boolean', + 'tinyint' => 'boolean', + 'smallint' => 'smallint', + 'mediumint' => 'integer', + 'int' => 'integer', + 'integer' => 'integer', + 'serial' => 'integer', + 'bigint' => 'bigint', + 'bigserial' => 'bigint', + 'clob' => 'text', + 'tinytext' => 'text', + 'mediumtext' => 'text', + 'longtext' => 'text', + 'text' => 'text', + 'varchar' => 'string', + 'longvarchar' => 'string', + 'varchar2' => 'string', + 'nvarchar' => 'string', + 'image' => 'string', + 'ntext' => 'string', + 'char' => 'string', + 'date' => 'date', + 'datetime' => 'datetime', + 'timestamp' => 'datetime', + 'time' => 'time', + 'float' => 'float', + 'double' => 'float', + 'double precision' => 'float', + 'real' => 'float', + 'decimal' => 'decimal', + 'numeric' => 'decimal', + 'blob' => 'blob', + ); + } + + /** + * {@inheritDoc} + */ + protected function getReservedKeywordsClass() + { + return 'Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords'; + } + + /** + * {@inheritDoc} + */ + public function getBlobTypeDeclarationSQL(array $field) + { + return 'BLOB'; + } + + /** + * {@inheritDoc} + */ + public function getTemporaryTableName($tableName) + { + $tableName = str_replace(".", "__", $tableName); + + return $tableName; + } + + /** + * {@inheritDoc} + * + * Sqlite Platform emulates schema by underscoring each dot and generating tables + * into the default database. + * + * This hack is implemented to be able to use SQLite as testdriver when + * using schema supporting databases. + */ + public function canEmulateSchemas() + { + return true; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Portability/Connection.php b/src/core/libs/Doctrine/DBAL/Portability/Connection.php new file mode 100644 index 0000000..410fa82 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Portability/Connection.php @@ -0,0 +1,119 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Portability; + +use Doctrine\Common\EventManager; +use Doctrine\DBAL\Configuration; +use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Cache\QueryCacheProfile; + +class Connection extends \Doctrine\DBAL\Connection +{ + const PORTABILITY_ALL = 255; + const PORTABILITY_NONE = 0; + const PORTABILITY_RTRIM = 1; + const PORTABILITY_EMPTY_TO_NULL = 4; + const PORTABILITY_FIX_CASE = 8; + + const PORTABILITY_ORACLE = 9; + const PORTABILITY_POSTGRESQL = 13; + const PORTABILITY_SQLITE = 13; + const PORTABILITY_OTHERVENDORS = 12; + const PORTABILITY_DRIZZLE = 13; + const PORTABILITY_SQLSRV = 13; + + /** + * @var int + */ + private $portability = self::PORTABILITY_NONE; + + /** + * @var int + */ + private $case; + + public function connect() + { + $ret = parent::connect(); + if ($ret) { + $params = $this->getParams(); + if (isset($params['portability'])) { + if ($this->_platform->getName() === "oracle") { + $params['portability'] = $params['portability'] & self::PORTABILITY_ORACLE; + } else if ($this->_platform->getName() === "postgresql") { + $params['portability'] = $params['portability'] & self::PORTABILITY_POSTGRESQL; + } else if ($this->_platform->getName() === "sqlite") { + $params['portability'] = $params['portability'] & self::PORTABILITY_SQLITE; + } else if ($this->_platform->getName() === "drizzle") { + $params['portability'] = self::PORTABILITY_DRIZZLE; + } else if ($this->_platform->getName() === 'sqlsrv') { + $params['portability'] = $params['portabililty'] & self::PORTABILITY_SQLSRV; + } else { + $params['portability'] = $params['portability'] & self::PORTABILITY_OTHERVENDORS; + } + $this->portability = $params['portability']; + } + if (isset($params['fetch_case']) && $this->portability & self::PORTABILITY_FIX_CASE) { + if ($this->_conn instanceof \Doctrine\DBAL\Driver\PDOConnection) { + // make use of c-level support for case handling + $this->_conn->setAttribute(\PDO::ATTR_CASE, $params['fetch_case']); + } else { + $this->case = ($params['fetch_case'] == \PDO::CASE_LOWER) ? CASE_LOWER : CASE_UPPER; + } + } + } + return $ret; + } + + public function getPortability() + { + return $this->portability; + } + + public function getFetchCase() + { + return $this->case; + } + + public function executeQuery($query, array $params = array(), $types = array(), QueryCacheProfile $qcp = null) + { + return new Statement(parent::executeQuery($query, $params, $types, $qcp), $this); + } + + /** + * Prepares an SQL statement. + * + * @param string $statement The SQL statement to prepare. + * @return \Doctrine\DBAL\Driver\Statement The prepared statement. + */ + public function prepare($statement) + { + return new Statement(parent::prepare($statement), $this); + } + + public function query() + { + $this->connect(); + + $stmt = call_user_func_array(array($this->_conn, 'query'), func_get_args()); + return new Statement($stmt, $this); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Portability/Statement.php b/src/core/libs/Doctrine/DBAL/Portability/Statement.php new file mode 100644 index 0000000..98076bd --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Portability/Statement.php @@ -0,0 +1,195 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Portability; + +use PDO; + +/** + * Portability Wrapper for a Statement + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class Statement implements \IteratorAggregate, \Doctrine\DBAL\Driver\Statement +{ + + /** + * @var int + */ + private $portability; + + /** + * @var \Doctrine\DBAL\Driver\Statement + */ + private $stmt; + + /** + * @var int + */ + private $case; + + /** + * @var int + */ + private $defaultFetchMode = PDO::FETCH_BOTH; + + /** + * Wraps <tt>Statement</tt> and applies portability measures + * + * @param \Doctrine\DBAL\Driver\Statement $stmt + * @param \Doctrine\DBAL\Connection $conn + */ + public function __construct($stmt, Connection $conn) + { + $this->stmt = $stmt; + $this->portability = $conn->getPortability(); + $this->case = $conn->getFetchCase(); + } + + public function bindParam($column, &$variable, $type = null,$length = null) + { + return $this->stmt->bindParam($column, $variable, $type); + } + + public function bindValue($param, $value, $type = null) + { + return $this->stmt->bindValue($param, $value, $type); + } + + public function closeCursor() + { + return $this->stmt->closeCursor(); + } + + public function columnCount() + { + return $this->stmt->columnCount(); + } + + public function errorCode() + { + return $this->stmt->errorCode(); + } + + public function errorInfo() + { + return $this->stmt->errorInfo(); + } + + public function execute($params = null) + { + return $this->stmt->execute($params); + } + + public function setFetchMode($fetchMode, $arg1 = null, $arg2 = null) + { + $this->defaultFetchMode = $fetchMode; + $this->stmt->setFetchMode($fetchMode, $arg1, $arg2); + } + + public function getIterator() + { + $data = $this->fetchAll(); + return new \ArrayIterator($data); + } + + public function fetch($fetchMode = null) + { + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + + $row = $this->stmt->fetch($fetchMode); + + $row = $this->fixRow($row, + $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM), + !is_null($this->case) && ($fetchMode == PDO::FETCH_ASSOC || $fetchMode == PDO::FETCH_BOTH) && ($this->portability & Connection::PORTABILITY_FIX_CASE) + ); + + return $row; + } + + public function fetchAll($fetchMode = null, $columnIndex = 0) + { + $fetchMode = $fetchMode ?: $this->defaultFetchMode; + + if ($columnIndex != 0) { + $rows = $this->stmt->fetchAll($fetchMode, $columnIndex); + } else { + $rows = $this->stmt->fetchAll($fetchMode); + } + + $iterateRow = $this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM); + $fixCase = !is_null($this->case) && ($fetchMode == PDO::FETCH_ASSOC || $fetchMode == PDO::FETCH_BOTH) && ($this->portability & Connection::PORTABILITY_FIX_CASE); + if ( ! $iterateRow && !$fixCase) { + return $rows; + } + + foreach ($rows as $num => $row) { + $rows[$num] = $this->fixRow($row, $iterateRow, $fixCase); + } + + return $rows; + } + + protected function fixRow($row, $iterateRow, $fixCase) + { + if ( ! $row) { + return $row; + } + + if ($fixCase) { + $row = array_change_key_case($row, $this->case); + } + + if ($iterateRow) { + foreach ($row as $k => $v) { + if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $v === '') { + $row[$k] = null; + } else if (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($v)) { + $row[$k] = rtrim($v); + } + } + } + return $row; + } + + public function fetchColumn($columnIndex = 0) + { + $value = $this->stmt->fetchColumn($columnIndex); + + if ($this->portability & (Connection::PORTABILITY_EMPTY_TO_NULL|Connection::PORTABILITY_RTRIM)) { + if (($this->portability & Connection::PORTABILITY_EMPTY_TO_NULL) && $value === '') { + $value = null; + } else if (($this->portability & Connection::PORTABILITY_RTRIM) && is_string($value)) { + $value = rtrim($value); + } + } + + return $value; + } + + public function rowCount() + { + return $this->stmt->rowCount(); + } + +} diff --git a/src/core/libs/Doctrine/DBAL/Query/Expression/CompositeExpression.php b/src/core/libs/Doctrine/DBAL/Query/Expression/CompositeExpression.php new file mode 100644 index 0000000..5d55b22 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Query/Expression/CompositeExpression.php @@ -0,0 +1,130 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Query\Expression; + +/** + * Composite expression is responsible to build a group of similar expression. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.org + * @since 2.1 + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class CompositeExpression implements \Countable +{ + /** + * Constant that represents an AND composite expression + */ + const TYPE_AND = 'AND'; + + /** + * Constant that represents an OR composite expression + */ + const TYPE_OR = 'OR'; + + /** + * @var string Holds the instance type of composite expression + */ + private $type; + + /** + * @var array Each expression part of the composite expression + */ + private $parts = array(); + + /** + * Constructor. + * + * @param string $type Instance type of composite expression + * @param array $parts Composition of expressions to be joined on composite expression + */ + public function __construct($type, array $parts = array()) + { + $this->type = $type; + + $this->addMultiple($parts); + } + + /** + * Adds multiple parts to composite expression. + * + * @param array $parts + * + * @return CompositeExpression + */ + public function addMultiple(array $parts = array()) + { + foreach ((array) $parts as $part) { + $this->add($part); + } + + return $this; + } + + /** + * Adds an expression to composite expression. + * + * @param mixed $part + * @return CompositeExpression + */ + public function add($part) + { + if ( ! empty($part) || ($part instanceof self && $part->count() > 0)) { + $this->parts[] = $part; + } + + return $this; + } + + /** + * Retrieves the amount of expressions on composite expression. + * + * @return integer + */ + public function count() + { + return count($this->parts); + } + + /** + * Retrieve the string representation of this composite expression. + * + * @return string + */ + public function __toString() + { + if (count($this->parts) === 1) { + return (string) $this->parts[0]; + } + + return '(' . implode(') ' . $this->type . ' (', $this->parts) . ')'; + } + + /** + * Return type of this composite expression (AND/OR) + * + * @return string + */ + public function getType() + { + return $this->type; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php b/src/core/libs/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php new file mode 100644 index 0000000..4f50232 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Query/Expression/ExpressionBuilder.php @@ -0,0 +1,264 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Query\Expression; + +use Doctrine\DBAL\Connection; + +/** + * ExpressionBuilder class is responsible to dynamically create SQL query parts. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.1 + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class ExpressionBuilder +{ + const EQ = '='; + const NEQ = '<>'; + const LT = '<'; + const LTE = '<='; + const GT = '>'; + const GTE = '>='; + + /** + * @var Doctrine\DBAL\Connection DBAL Connection + */ + private $connection = null; + + /** + * Initializes a new <tt>ExpressionBuilder</tt>. + * + * @param \Doctrine\DBAL\Connection $connection DBAL Connection + */ + public function __construct(Connection $connection) + { + $this->connection = $connection; + } + + /** + * Creates a conjunction of the given boolean expressions. + * + * Example: + * + * [php] + * // (u.type = ?) AND (u.role = ?) + * $expr->andX('u.type = ?', 'u.role = ?')); + * + * @param mixed $x Optional clause. Defaults = null, but requires + * at least one defined when converting to string. + * @return CompositeExpression + */ + public function andX($x = null) + { + return new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); + } + + /** + * Creates a disjunction of the given boolean expressions. + * + * Example: + * + * [php] + * // (u.type = ?) OR (u.role = ?) + * $qb->where($qb->expr()->orX('u.type = ?', 'u.role = ?')); + * + * @param mixed $x Optional clause. Defaults = null, but requires + * at least one defined when converting to string. + * @return CompositeExpression + */ + public function orX($x = null) + { + return new CompositeExpression(CompositeExpression::TYPE_OR, func_get_args()); + } + + /** + * Creates a comparison expression. + * + * @param mixed $x Left expression + * @param string $operator One of the ExpressionBuilder::* constants. + * @param mixed $y Right expression + * @return string + */ + public function comparison($x, $operator, $y) + { + return $x . ' ' . $operator . ' ' . $y; + } + + /** + * Creates an equality comparison expression with the given arguments. + * + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a <left expr> = <right expr>. Example: + * + * [php] + * // u.id = ? + * $expr->eq('u.id', '?'); + * + * @param mixed $x Left expression + * @param mixed $y Right expression + * @return string + */ + public function eq($x, $y) + { + return $this->comparison($x, self::EQ, $y); + } + + /** + * Creates a non equality comparison expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a <left expr> <> <right expr>. Example: + * + * [php] + * // u.id <> 1 + * $q->where($q->expr()->neq('u.id', '1')); + * + * @param mixed $x Left expression + * @param mixed $y Right expression + * @return string + */ + public function neq($x, $y) + { + return $this->comparison($x, self::NEQ, $y); + } + + /** + * Creates a lower-than comparison expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a <left expr> < <right expr>. Example: + * + * [php] + * // u.id < ? + * $q->where($q->expr()->lt('u.id', '?')); + * + * @param mixed $x Left expression + * @param mixed $y Right expression + * @return string + */ + public function lt($x, $y) + { + return $this->comparison($x, self::LT, $y); + } + + /** + * Creates a lower-than-equal comparison expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a <left expr> <= <right expr>. Example: + * + * [php] + * // u.id <= ? + * $q->where($q->expr()->lte('u.id', '?')); + * + * @param mixed $x Left expression + * @param mixed $y Right expression + * @return string + */ + public function lte($x, $y) + { + return $this->comparison($x, self::LTE, $y); + } + + /** + * Creates a greater-than comparison expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a <left expr> > <right expr>. Example: + * + * [php] + * // u.id > ? + * $q->where($q->expr()->gt('u.id', '?')); + * + * @param mixed $x Left expression + * @param mixed $y Right expression + * @return string + */ + public function gt($x, $y) + { + return $this->comparison($x, self::GT, $y); + } + + /** + * Creates a greater-than-equal comparison expression with the given arguments. + * First argument is considered the left expression and the second is the right expression. + * When converted to string, it will generated a <left expr> >= <right expr>. Example: + * + * [php] + * // u.id >= ? + * $q->where($q->expr()->gte('u.id', '?')); + * + * @param mixed $x Left expression + * @param mixed $y Right expression + * @return string + */ + public function gte($x, $y) + { + return $this->comparison($x, self::GTE, $y); + } + + /** + * Creates an IS NULL expression with the given arguments. + * + * @param string $x Field in string format to be restricted by IS NULL + * + * @return string + */ + public function isNull($x) + { + return $x . ' IS NULL'; + } + + /** + * Creates an IS NOT NULL expression with the given arguments. + * + * @param string $x Field in string format to be restricted by IS NOT NULL + * + * @return string + */ + public function isNotNull($x) + { + return $x . ' IS NOT NULL'; + } + + /** + * Creates a LIKE() comparison expression with the given arguments. + * + * @param string $x Field in string format to be inspected by LIKE() comparison. + * @param mixed $y Argument to be used in LIKE() comparison. + * + * @return string + */ + public function like($x, $y) + { + return $this->comparison($x, 'LIKE', $y); + } + + /** + * Quotes a given input parameter. + * + * @param mixed $input Parameter to be quoted. + * @param string $type Type of the parameter. + * + * @return string + */ + public function literal($input, $type = null) + { + return $this->connection->quote($input, $type); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Query/QueryBuilder.php b/src/core/libs/Doctrine/DBAL/Query/QueryBuilder.php new file mode 100644 index 0000000..6c4fd68 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Query/QueryBuilder.php @@ -0,0 +1,1087 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Query; + +use Doctrine\DBAL\Query\Expression\CompositeExpression, + Doctrine\DBAL\Connection; + +/** + * QueryBuilder class is responsible to dynamically create SQL queries. + * + * Important: Verify that every feature you use will work with your database vendor. + * SQL Query Builder does not attempt to validate the generated SQL at all. + * + * The query builder does no validation whatsoever if certain features even work with the + * underlying database vendor. Limit queries and joins are NOT applied to UPDATE and DELETE statements + * even if some vendors such as MySQL support it. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.1 + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class QueryBuilder +{ + /* The query types. */ + const SELECT = 0; + const DELETE = 1; + const UPDATE = 2; + + /** The builder states. */ + const STATE_DIRTY = 0; + const STATE_CLEAN = 1; + + /** + * @var Doctrine\DBAL\Connection DBAL Connection + */ + protected $connection = null; + + /** + * @var array The array of SQL parts collected. + */ + protected $sqlParts = array( + 'select' => array(), + 'from' => array(), + 'join' => array(), + 'set' => array(), + 'where' => null, + 'groupBy' => array(), + 'having' => null, + 'orderBy' => array() + ); + + /** + * @var string The complete SQL string for this query. + */ + protected $sql; + + /** + * @var array The query parameters. + */ + protected $params = array(); + + /** + * @var array The parameter type map of this query. + */ + protected $paramTypes = array(); + + /** + * @var integer The type of query this is. Can be select, update or delete. + */ + protected $type = self::SELECT; + + /** + * @var integer The state of the query object. Can be dirty or clean. + */ + protected $state = self::STATE_CLEAN; + + /** + * @var integer The index of the first result to retrieve. + */ + protected $firstResult = null; + + /** + * @var integer The maximum number of results to retrieve. + */ + protected $maxResults = null; + + /** + * The counter of bound parameters used with {@see bindValue) + * + * @var int + */ + protected $boundCounter = 0; + + /** + * Initializes a new <tt>QueryBuilder</tt>. + * + * @param \Doctrine\DBAL\Connection $connection DBAL Connection + */ + public function __construct(Connection $connection) + { + $this->connection = $connection; + } + + /** + * Gets an ExpressionBuilder used for object-oriented construction of query expressions. + * This producer method is intended for convenient inline usage. Example: + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u') + * ->from('users', 'u') + * ->where($qb->expr()->eq('u.id', 1)); + * </code> + * + * For more complex expression construction, consider storing the expression + * builder object in a local variable. + * + * @return \Doctrine\DBAL\Query\Expression\ExpressionBuilder + */ + public function expr() + { + return $this->connection->getExpressionBuilder(); + } + + /** + * Get the type of the currently built query. + * + * @return integer + */ + public function getType() + { + return $this->type; + } + + /** + * Get the associated DBAL Connection for this query builder. + * + * @return \Doctrine\DBAL\Connection + */ + public function getConnection() + { + return $this->connection; + } + + /** + * Get the state of this query builder instance. + * + * @return integer Either QueryBuilder::STATE_DIRTY or QueryBuilder::STATE_CLEAN. + */ + public function getState() + { + return $this->state; + } + + /** + * Execute this query using the bound parameters and their types. + * + * Uses {@see Connection::executeQuery} for select statements and {@see Connection::executeUpdate} + * for insert, update and delete statements. + * + * @return mixed + */ + public function execute() + { + if ($this->type == self::SELECT) { + return $this->connection->executeQuery($this->getSQL(), $this->params, $this->paramTypes); + } else { + return $this->connection->executeUpdate($this->getSQL(), $this->params, $this->paramTypes); + } + } + + /** + * Get the complete SQL string formed by the current specifications of this QueryBuilder. + * + * <code> + * $qb = $em->createQueryBuilder() + * ->select('u') + * ->from('User', 'u') + * echo $qb->getSQL(); // SELECT u FROM User u + * </code> + * + * @return string The sql query string. + */ + public function getSQL() + { + if ($this->sql !== null && $this->state === self::STATE_CLEAN) { + return $this->sql; + } + + $sql = ''; + + switch ($this->type) { + case self::DELETE: + $sql = $this->getSQLForDelete(); + break; + + case self::UPDATE: + $sql = $this->getSQLForUpdate(); + break; + + case self::SELECT: + default: + $sql = $this->getSQLForSelect(); + break; + } + + $this->state = self::STATE_CLEAN; + $this->sql = $sql; + + return $sql; + } + + /** + * Sets a query parameter for the query being constructed. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u') + * ->from('users', 'u') + * ->where('u.id = :user_id') + * ->setParameter(':user_id', 1); + * </code> + * + * @param string|integer $key The parameter position or name. + * @param mixed $value The parameter value. + * @param string|null $type PDO::PARAM_* + * @return QueryBuilder This QueryBuilder instance. + */ + public function setParameter($key, $value, $type = null) + { + if ($type !== null) { + $this->paramTypes[$key] = $type; + } + + $this->params[$key] = $value; + + return $this; + } + + /** + * Sets a collection of query parameters for the query being constructed. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u') + * ->from('users', 'u') + * ->where('u.id = :user_id1 OR u.id = :user_id2') + * ->setParameters(array( + * ':user_id1' => 1, + * ':user_id2' => 2 + * )); + * </code> + * + * @param array $params The query parameters to set. + * @param array $types The query parameters types to set. + * @return QueryBuilder This QueryBuilder instance. + */ + public function setParameters(array $params, array $types = array()) + { + $this->paramTypes = $types; + $this->params = $params; + + return $this; + } + + /** + * Gets all defined query parameters for the query being constructed. + * + * @return array The currently defined query parameters. + */ + public function getParameters() + { + return $this->params; + } + + /** + * Gets a (previously set) query parameter of the query being constructed. + * + * @param mixed $key The key (index or name) of the bound parameter. + * @return mixed The value of the bound parameter. + */ + public function getParameter($key) + { + return isset($this->params[$key]) ? $this->params[$key] : null; + } + + /** + * Sets the position of the first result to retrieve (the "offset"). + * + * @param integer $firstResult The first result to return. + * @return \Doctrine\DBAL\Query\QueryBuilder This QueryBuilder instance. + */ + public function setFirstResult($firstResult) + { + $this->state = self::STATE_DIRTY; + $this->firstResult = $firstResult; + return $this; + } + + /** + * Gets the position of the first result the query object was set to retrieve (the "offset"). + * Returns NULL if {@link setFirstResult} was not applied to this QueryBuilder. + * + * @return integer The position of the first result. + */ + public function getFirstResult() + { + return $this->firstResult; + } + + /** + * Sets the maximum number of results to retrieve (the "limit"). + * + * @param integer $maxResults The maximum number of results to retrieve. + * @return \Doctrine\DBAL\Query\QueryBuilder This QueryBuilder instance. + */ + public function setMaxResults($maxResults) + { + $this->state = self::STATE_DIRTY; + $this->maxResults = $maxResults; + return $this; + } + + /** + * Gets the maximum number of results the query object was set to retrieve (the "limit"). + * Returns NULL if {@link setMaxResults} was not applied to this query builder. + * + * @return integer Maximum number of results. + */ + public function getMaxResults() + { + return $this->maxResults; + } + + /** + * Either appends to or replaces a single, generic query part. + * + * The available parts are: 'select', 'from', 'set', 'where', + * 'groupBy', 'having' and 'orderBy'. + * + * @param string $sqlPartName + * @param string $sqlPart + * @param boolean $append + * @return \Doctrine\DBAL\Query\QueryBuilder This QueryBuilder instance. + */ + public function add($sqlPartName, $sqlPart, $append = false) + { + $isArray = is_array($sqlPart); + $isMultiple = is_array($this->sqlParts[$sqlPartName]); + + if ($isMultiple && !$isArray) { + $sqlPart = array($sqlPart); + } + + $this->state = self::STATE_DIRTY; + + if ($append) { + if ($sqlPartName == "orderBy" || $sqlPartName == "groupBy" || $sqlPartName == "select" || $sqlPartName == "set") { + foreach ($sqlPart as $part) { + $this->sqlParts[$sqlPartName][] = $part; + } + } else if ($isArray && is_array($sqlPart[key($sqlPart)])) { + $key = key($sqlPart); + $this->sqlParts[$sqlPartName][$key][] = $sqlPart[$key]; + } else if ($isMultiple) { + $this->sqlParts[$sqlPartName][] = $sqlPart; + } else { + $this->sqlParts[$sqlPartName] = $sqlPart; + } + + return $this; + } + + $this->sqlParts[$sqlPartName] = $sqlPart; + + return $this; + } + + /** + * Specifies an item that is to be returned in the query result. + * Replaces any previously specified selections, if any. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u.id', 'p.id') + * ->from('users', 'u') + * ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id'); + * </code> + * + * @param mixed $select The selection expressions. + * @return QueryBuilder This QueryBuilder instance. + */ + public function select($select = null) + { + $this->type = self::SELECT; + + if (empty($select)) { + return $this; + } + + $selects = is_array($select) ? $select : func_get_args(); + + return $this->add('select', $selects, false); + } + + /** + * Adds an item that is to be returned in the query result. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u.id') + * ->addSelect('p.id') + * ->from('users', 'u') + * ->leftJoin('u', 'phonenumbers', 'u.id = p.user_id'); + * </code> + * + * @param mixed $select The selection expression. + * @return QueryBuilder This QueryBuilder instance. + */ + public function addSelect($select = null) + { + $this->type = self::SELECT; + + if (empty($select)) { + return $this; + } + + $selects = is_array($select) ? $select : func_get_args(); + + return $this->add('select', $selects, true); + } + + /** + * Turns the query being built into a bulk delete query that ranges over + * a certain table. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->delete('users', 'u') + * ->where('u.id = :user_id'); + * ->setParameter(':user_id', 1); + * </code> + * + * @param string $delete The table whose rows are subject to the deletion. + * @param string $alias The table alias used in the constructed query. + * @return QueryBuilder This QueryBuilder instance. + */ + public function delete($delete = null, $alias = null) + { + $this->type = self::DELETE; + + if ( ! $delete) { + return $this; + } + + return $this->add('from', array( + 'table' => $delete, + 'alias' => $alias + )); + } + + /** + * Turns the query being built into a bulk update query that ranges over + * a certain table + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->update('users', 'u') + * ->set('u.password', md5('password')) + * ->where('u.id = ?'); + * </code> + * + * @param string $update The table whose rows are subject to the update. + * @param string $alias The table alias used in the constructed query. + * @return QueryBuilder This QueryBuilder instance. + */ + public function update($update = null, $alias = null) + { + $this->type = self::UPDATE; + + if ( ! $update) { + return $this; + } + + return $this->add('from', array( + 'table' => $update, + 'alias' => $alias + )); + } + + /** + * Create and add a query root corresponding to the table identified by the + * given alias, forming a cartesian product with any existing query roots. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u.id') + * ->from('users', 'u') + * </code> + * + * @param string $from The table + * @param string $alias The alias of the table + * @return QueryBuilder This QueryBuilder instance. + */ + public function from($from, $alias) + { + return $this->add('from', array( + 'table' => $from, + 'alias' => $alias + ), true); + } + + /** + * Creates and adds a join to the query. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->join('u', 'phonenumbers', 'p', 'p.is_primary = 1'); + * </code> + * + * @param string $fromAlias The alias that points to a from clause + * @param string $join The table name to join + * @param string $alias The alias of the join table + * @param string $condition The condition for the join + * @return QueryBuilder This QueryBuilder instance. + */ + public function join($fromAlias, $join, $alias, $condition = null) + { + return $this->innerJoin($fromAlias, $join, $alias, $condition); + } + + /** + * Creates and adds a join to the query. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->innerJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); + * </code> + * + * @param string $fromAlias The alias that points to a from clause + * @param string $join The table name to join + * @param string $alias The alias of the join table + * @param string $condition The condition for the join + * @return QueryBuilder This QueryBuilder instance. + */ + public function innerJoin($fromAlias, $join, $alias, $condition = null) + { + return $this->add('join', array( + $fromAlias => array( + 'joinType' => 'inner', + 'joinTable' => $join, + 'joinAlias' => $alias, + 'joinCondition' => $condition + ) + ), true); + } + + /** + * Creates and adds a left join to the query. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->leftJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); + * </code> + * + * @param string $fromAlias The alias that points to a from clause + * @param string $join The table name to join + * @param string $alias The alias of the join table + * @param string $condition The condition for the join + * @return QueryBuilder This QueryBuilder instance. + */ + public function leftJoin($fromAlias, $join, $alias, $condition = null) + { + return $this->add('join', array( + $fromAlias => array( + 'joinType' => 'left', + 'joinTable' => $join, + 'joinAlias' => $alias, + 'joinCondition' => $condition + ) + ), true); + } + + /** + * Creates and adds a right join to the query. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->rightJoin('u', 'phonenumbers', 'p', 'p.is_primary = 1'); + * </code> + * + * @param string $fromAlias The alias that points to a from clause + * @param string $join The table name to join + * @param string $alias The alias of the join table + * @param string $condition The condition for the join + * @return QueryBuilder This QueryBuilder instance. + */ + public function rightJoin($fromAlias, $join, $alias, $condition = null) + { + return $this->add('join', array( + $fromAlias => array( + 'joinType' => 'right', + 'joinTable' => $join, + 'joinAlias' => $alias, + 'joinCondition' => $condition + ) + ), true); + } + + /** + * Sets a new value for a column in a bulk update query. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->update('users', 'u') + * ->set('u.password', md5('password')) + * ->where('u.id = ?'); + * </code> + * + * @param string $key The column to set. + * @param string $value The value, expression, placeholder, etc. + * @return QueryBuilder This QueryBuilder instance. + */ + public function set($key, $value) + { + return $this->add('set', $key .' = ' . $value, true); + } + + /** + * Specifies one or more restrictions to the query result. + * Replaces any previously specified restrictions, if any. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->where('u.id = ?'); + * + * // You can optionally programatically build and/or expressions + * $qb = $conn->createQueryBuilder(); + * + * $or = $qb->expr()->orx(); + * $or->add($qb->expr()->eq('u.id', 1)); + * $or->add($qb->expr()->eq('u.id', 2)); + * + * $qb->update('users', 'u') + * ->set('u.password', md5('password')) + * ->where($or); + * </code> + * + * @param mixed $predicates The restriction predicates. + * @return QueryBuilder This QueryBuilder instance. + */ + public function where($predicates) + { + if ( ! (func_num_args() == 1 && $predicates instanceof CompositeExpression) ) { + $predicates = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); + } + + return $this->add('where', $predicates); + } + + /** + * Adds one or more restrictions to the query results, forming a logical + * conjunction with any previously specified restrictions. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u') + * ->from('users', 'u') + * ->where('u.username LIKE ?') + * ->andWhere('u.is_active = 1'); + * </code> + * + * @param mixed $where The query restrictions. + * @return QueryBuilder This QueryBuilder instance. + * @see where() + */ + public function andWhere($where) + { + $where = $this->getQueryPart('where'); + $args = func_get_args(); + + if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_AND) { + $where->addMultiple($args); + } else { + array_unshift($args, $where); + $where = new CompositeExpression(CompositeExpression::TYPE_AND, $args); + } + + return $this->add('where', $where, true); + } + + /** + * Adds one or more restrictions to the query results, forming a logical + * disjunction with any previously specified restrictions. + * + * <code> + * $qb = $em->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->where('u.id = 1') + * ->orWhere('u.id = 2'); + * </code> + * + * @param mixed $where The WHERE statement + * @return QueryBuilder $qb + * @see where() + */ + public function orWhere($where) + { + $where = $this->getQueryPart('where'); + $args = func_get_args(); + + if ($where instanceof CompositeExpression && $where->getType() === CompositeExpression::TYPE_OR) { + $where->addMultiple($args); + } else { + array_unshift($args, $where); + $where = new CompositeExpression(CompositeExpression::TYPE_OR, $args); + } + + return $this->add('where', $where, true); + } + + /** + * Specifies a grouping over the results of the query. + * Replaces any previously specified groupings, if any. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->groupBy('u.id'); + * </code> + * + * @param mixed $groupBy The grouping expression. + * @return QueryBuilder This QueryBuilder instance. + */ + public function groupBy($groupBy) + { + if (empty($groupBy)) { + return $this; + } + + $groupBy = is_array($groupBy) ? $groupBy : func_get_args(); + + return $this->add('groupBy', $groupBy, false); + } + + + /** + * Adds a grouping expression to the query. + * + * <code> + * $qb = $conn->createQueryBuilder() + * ->select('u.name') + * ->from('users', 'u') + * ->groupBy('u.lastLogin'); + * ->addGroupBy('u.createdAt') + * </code> + * + * @param mixed $groupBy The grouping expression. + * @return QueryBuilder This QueryBuilder instance. + */ + public function addGroupBy($groupBy) + { + if (empty($groupBy)) { + return $this; + } + + $groupBy = is_array($groupBy) ? $groupBy : func_get_args(); + + return $this->add('groupBy', $groupBy, true); + } + + /** + * Specifies a restriction over the groups of the query. + * Replaces any previous having restrictions, if any. + * + * @param mixed $having The restriction over the groups. + * @return QueryBuilder This QueryBuilder instance. + */ + public function having($having) + { + if ( ! (func_num_args() == 1 && $having instanceof CompositeExpression)) { + $having = new CompositeExpression(CompositeExpression::TYPE_AND, func_get_args()); + } + + return $this->add('having', $having); + } + + /** + * Adds a restriction over the groups of the query, forming a logical + * conjunction with any existing having restrictions. + * + * @param mixed $having The restriction to append. + * @return QueryBuilder This QueryBuilder instance. + */ + public function andHaving($having) + { + $having = $this->getQueryPart('having'); + $args = func_get_args(); + + if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_AND) { + $having->addMultiple($args); + } else { + array_unshift($args, $having); + $having = new CompositeExpression(CompositeExpression::TYPE_AND, $args); + } + + return $this->add('having', $having); + } + + /** + * Adds a restriction over the groups of the query, forming a logical + * disjunction with any existing having restrictions. + * + * @param mixed $having The restriction to add. + * @return QueryBuilder This QueryBuilder instance. + */ + public function orHaving($having) + { + $having = $this->getQueryPart('having'); + $args = func_get_args(); + + if ($having instanceof CompositeExpression && $having->getType() === CompositeExpression::TYPE_OR) { + $having->addMultiple($args); + } else { + array_unshift($args, $having); + $having = new CompositeExpression(CompositeExpression::TYPE_OR, $args); + } + + return $this->add('having', $having); + } + + /** + * Specifies an ordering for the query results. + * Replaces any previously specified orderings, if any. + * + * @param string $sort The ordering expression. + * @param string $order The ordering direction. + * @return QueryBuilder This QueryBuilder instance. + */ + public function orderBy($sort, $order = null) + { + return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), false); + } + + /** + * Adds an ordering to the query results. + * + * @param string $sort The ordering expression. + * @param string $order The ordering direction. + * @return QueryBuilder This QueryBuilder instance. + */ + public function addOrderBy($sort, $order = null) + { + return $this->add('orderBy', $sort . ' ' . (! $order ? 'ASC' : $order), true); + } + + /** + * Get a query part by its name. + * + * @param string $queryPartName + * @return mixed $queryPart + */ + public function getQueryPart($queryPartName) + { + return $this->sqlParts[$queryPartName]; + } + + /** + * Get all query parts. + * + * @return array $sqlParts + */ + public function getQueryParts() + { + return $this->sqlParts; + } + + /** + * Reset SQL parts + * + * @param array $queryPartNames + * @return QueryBuilder + */ + public function resetQueryParts($queryPartNames = null) + { + if (is_null($queryPartNames)) { + $queryPartNames = array_keys($this->sqlParts); + } + + foreach ($queryPartNames as $queryPartName) { + $this->resetQueryPart($queryPartName); + } + + return $this; + } + + /** + * Reset single SQL part + * + * @param string $queryPartName + * @return QueryBuilder + */ + public function resetQueryPart($queryPartName) + { + $this->sqlParts[$queryPartName] = is_array($this->sqlParts[$queryPartName]) + ? array() : null; + + $this->state = self::STATE_DIRTY; + + return $this; + } + + protected function getSQLForSelect() + { + $query = 'SELECT ' . implode(', ', $this->sqlParts['select']) . ' FROM '; + + $fromClauses = array(); + + // Loop through all FROM clauses + foreach ($this->sqlParts['from'] as $from) { + $fromClause = $from['table'] . ' ' . $from['alias']; + + if (isset($this->sqlParts['join'][$from['alias']])) { + foreach ($this->sqlParts['join'][$from['alias']] as $join) { + $fromClause .= ' ' . strtoupper($join['joinType']) + . ' JOIN ' . $join['joinTable'] . ' ' . $join['joinAlias'] + . ' ON ' . ((string) $join['joinCondition']); + } + } + + $fromClauses[$from['alias']] = $fromClause; + } + + // loop through all JOIN clasues for validation purpose + foreach ($this->sqlParts['join'] as $fromAlias => $joins) { + if ( ! isset($fromClauses[$fromAlias]) ) { + throw QueryException::unknownFromAlias($fromAlias, array_keys($fromClauses)); + } + } + + $query .= implode(', ', $fromClauses) + . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : '') + . ($this->sqlParts['groupBy'] ? ' GROUP BY ' . implode(', ', $this->sqlParts['groupBy']) : '') + . ($this->sqlParts['having'] !== null ? ' HAVING ' . ((string) $this->sqlParts['having']) : '') + . ($this->sqlParts['orderBy'] ? ' ORDER BY ' . implode(', ', $this->sqlParts['orderBy']) : ''); + + return ($this->maxResults === null && $this->firstResult == null) + ? $query + : $this->connection->getDatabasePlatform()->modifyLimitQuery($query, $this->maxResults, $this->firstResult); + } + + /** + * Converts this instance into an UPDATE string in SQL. + * + * @return string + */ + protected function getSQLForUpdate() + { + $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : ''); + $query = 'UPDATE ' . $table + . ' SET ' . implode(", ", $this->sqlParts['set']) + . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); + + return $query; + } + + /** + * Converts this instance into a DELETE string in SQL. + * + * @return string + */ + protected function getSQLForDelete() + { + $table = $this->sqlParts['from']['table'] . ($this->sqlParts['from']['alias'] ? ' ' . $this->sqlParts['from']['alias'] : ''); + $query = 'DELETE FROM ' . $table . ($this->sqlParts['where'] !== null ? ' WHERE ' . ((string) $this->sqlParts['where']) : ''); + + return $query; + } + + /** + * Gets a string representation of this QueryBuilder which corresponds to + * the final SQL query being constructed. + * + * @return string The string representation of this QueryBuilder. + */ + public function __toString() + { + return $this->getSQL(); + } + + /** + * Create a new named parameter and bind the value $value to it. + * + * This method provides a shortcut for PDOStatement::bindValue + * when using prepared statements. + * + * The parameter $value specifies the value that you want to bind. If + * $placeholder is not provided bindValue() will automatically create a + * placeholder for you. An automatic placeholder will be of the name + * ':dcValue1', ':dcValue2' etc. + * + * For more information see {@link http://php.net/pdostatement-bindparam} + * + * Example: + * <code> + * $value = 2; + * $q->eq( 'id', $q->bindValue( $value ) ); + * $stmt = $q->executeQuery(); // executed with 'id = 2' + * </code> + * + * @license New BSD License + * @link http://www.zetacomponents.org + * @param mixed $value + * @param mixed $type + * @param string $placeHolder the name to bind with. The string must start with a colon ':'. + * @return string the placeholder name used. + */ + public function createNamedParameter( $value, $type = \PDO::PARAM_STR, $placeHolder = null ) + { + if ( $placeHolder === null ) { + $this->boundCounter++; + $placeHolder = ":dcValue" . $this->boundCounter; + } + $this->setParameter(substr($placeHolder, 1), $value, $type); + + return $placeHolder; + } + + /** + * Create a new positional parameter and bind the given value to it. + * + * Attention: If you are using positional parameters with the query builder you have + * to be very careful to bind all parameters in the order they appear in the SQL + * statement , otherwise they get bound in the wrong order which can lead to serious + * bugs in your code. + * + * Example: + * <code> + * $qb = $conn->createQueryBuilder(); + * $qb->select('u.*') + * ->from('users', 'u') + * ->where('u.username = ' . $qb->createPositionalParameter('Foo', PDO::PARAM_STR)) + * ->orWhere('u.username = ' . $qb->createPositionalParameter('Bar', PDO::PARAM_STR)) + * </code> + * + * @param mixed $value + * @param mixed $type + * @return string + */ + public function createPositionalParameter($value, $type = \PDO::PARAM_STR) + { + $this->boundCounter++; + $this->setParameter($this->boundCounter, $value, $type); + return "?"; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Query/QueryException.php b/src/core/libs/Doctrine/DBAL/Query/QueryException.php new file mode 100644 index 0000000..addc745 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Query/QueryException.php @@ -0,0 +1,40 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Query; + +use Doctrine\DBAL\DBALException; + +/** + * Driver interface. + * Interface that all DBAL drivers must implement. + * + * @since 2.1.4 + */ +class QueryException extends DBALException +{ + static public function unknownFromAlias($alias, $registeredAliases) + { + return new self("The given alias '" . $alias . "' is not part of " . + "any FROM clause table. The currently registered FROM-clause " . + "aliases are: " . implode(", ", $registeredAliases) . ". Join clauses " . + "are bound to from clauses to provide support for mixing of multiple " . + "from and join clauses."); + } +} diff --git a/src/core/libs/Doctrine/DBAL/README.markdown b/src/core/libs/Doctrine/DBAL/README.markdown new file mode 100644 index 0000000..e69de29 diff --git a/src/core/libs/Doctrine/DBAL/SQLParserUtils.php b/src/core/libs/Doctrine/DBAL/SQLParserUtils.php new file mode 100644 index 0000000..65ba25e --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/SQLParserUtils.php @@ -0,0 +1,183 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL; + +use Doctrine\DBAL\Connection; + +/** + * Utility class that parses sql statements with regard to types and parameters. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class SQLParserUtils +{ + /** + * Get an array of the placeholders in an sql statements as keys and their positions in the query string. + * + * Returns an integer => integer pair (indexed from zero) for a positional statement + * and a string => int[] pair for a named statement. + * + * @param string $statement + * @param bool $isPositional + * @return array + */ + static public function getPlaceholderPositions($statement, $isPositional = true) + { + $match = ($isPositional) ? '?' : ':'; + if (strpos($statement, $match) === false) { + return array(); + } + + $count = 0; + $inLiteral = false; // a valid query never starts with quotes + $stmtLen = strlen($statement); + $paramMap = array(); + for ($i = 0; $i < $stmtLen; $i++) { + if ($statement[$i] == $match && !$inLiteral) { + // real positional parameter detected + if ($isPositional) { + $paramMap[$count] = $i; + } else { + $name = ""; + // TODO: Something faster/better to match this than regex? + for ($j = $i + 1; ($j < $stmtLen && preg_match('(([a-zA-Z0-9_]{1}))', $statement[$j])); $j++) { + $name .= $statement[$j]; + } + $paramMap[$i] = $name; // named parameters can be duplicated! + $i = $j; + } + ++$count; + } else if ($statement[$i] == "'" || $statement[$i] == '"') { + $inLiteral = ! $inLiteral; // switch state! + } + } + + return $paramMap; + } + + /** + * For a positional query this method can rewrite the sql statement with regard to array parameters. + * + * @param string $query The SQL query to execute. + * @param array $params The parameters to bind to the query. + * @param array $types The types the previous parameters are in. + * + * @return array + */ + static public function expandListParameters($query, $params, $types) + { + $isPositional = is_int(key($params)); + $arrayPositions = array(); + $bindIndex = -1; + + foreach ($types as $name => $type) { + ++$bindIndex; + + if ($type !== Connection::PARAM_INT_ARRAY && $type !== Connection::PARAM_STR_ARRAY) { + continue; + } + + if ($isPositional) { + $name = $bindIndex; + } + + $arrayPositions[$name] = false; + } + + if (( ! $arrayPositions && $isPositional) || (count($params) != count($types))) { + return array($query, $params, $types); + } + + $paramPos = self::getPlaceholderPositions($query, $isPositional); + + if ($isPositional) { + $paramOffset = 0; + $queryOffset = 0; + + foreach ($paramPos as $needle => $needlePos) { + if ( ! isset($arrayPositions[$needle])) { + continue; + } + + $needle += $paramOffset; + $needlePos += $queryOffset; + $count = count($params[$needle]); + + $params = array_merge( + array_slice($params, 0, $needle), + $params[$needle], + array_slice($params, $needle + 1) + ); + + $types = array_merge( + array_slice($types, 0, $needle), + array_fill(0, $count, $types[$needle] - Connection::ARRAY_PARAM_OFFSET), // array needles are at PDO::PARAM_* + 100 + array_slice($types, $needle + 1) + ); + + $expandStr = implode(", ", array_fill(0, $count, "?")); + $query = substr($query, 0, $needlePos) . $expandStr . substr($query, $needlePos + 1); + + $paramOffset += ($count - 1); // Grows larger by number of parameters minus the replaced needle. + $queryOffset += (strlen($expandStr) - 1); + } + + return array($query, $params, $types); + } + + + $queryOffset = 0; + $typesOrd = array(); + $paramsOrd = array(); + + foreach ($paramPos as $pos => $paramName) { + $paramLen = strlen($paramName) + 1; + $value = $params[$paramName]; + + if ( ! isset($arrayPositions[$paramName])) { + $pos += $queryOffset; + $queryOffset -= ($paramLen - 1); + $paramsOrd[] = $value; + $typesOrd[] = $types[$paramName]; + $query = substr($query, 0, $pos) . '?' . substr($query, ($pos + $paramLen)); + + continue; + } + + $count = count($value); + $expandStr = $count > 0 ? implode(', ', array_fill(0, $count, '?')) : '?'; + + foreach ($value as $val) { + $paramsOrd[] = $val; + $typesOrd[] = $types[$paramName] - Connection::ARRAY_PARAM_OFFSET; + } + + $pos += $queryOffset; + $queryOffset += (strlen($expandStr) - $paramLen); + $query = substr($query, 0, $pos) . $expandStr . substr($query, ($pos + $paramLen)); + } + + return array($query, $paramsOrd, $typesOrd); + } +} \ No newline at end of file diff --git a/src/core/libs/Doctrine/DBAL/Schema/AbstractAsset.php b/src/core/libs/Doctrine/DBAL/Schema/AbstractAsset.php new file mode 100644 index 0000000..17a9c0f --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/AbstractAsset.php @@ -0,0 +1,214 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * The abstract asset allows to reset the name of all assets without publishing this to the public userland. + * + * This encapsulation hack is necessary to keep a consistent state of the database schema. Say we have a list of tables + * array($tableName => Table($tableName)); if you want to rename the table, you have to make sure + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +abstract class AbstractAsset +{ + /** + * @var string + */ + protected $_name; + + /** + * Namespace of the asset. If none isset the default namespace is assumed. + * + * @var string + */ + protected $_namespace; + + /** + * @var bool + */ + protected $_quoted = false; + + /** + * Set name of this asset + * + * @param string $name + */ + protected function _setName($name) + { + if ($this->isIdentifierQuoted($name)) { + $this->_quoted = true; + $name = $this->trimQuotes($name); + } + if (strpos($name, ".") !== false) { + $parts = explode(".", $name); + $this->_namespace = $parts[0]; + $name = $parts[1]; + } + $this->_name = $name; + } + + /** + * Is this asset in the default namespace? + * + * @param string $defaultNamespaceName + * @return bool + */ + public function isInDefaultNamespace($defaultNamespaceName) + { + return $this->_namespace == $defaultNamespaceName || $this->_namespace === null; + } + + /** + * Get namespace name of this asset. + * + * If NULL is returned this means the default namespace is used. + * + * @return string + */ + public function getNamespaceName() + { + return $this->_namespace; + } + + /** + * The shortest name is stripped of the default namespace. All other + * namespaced elements are returned as full-qualified names. + * + * @param string + * @return string + */ + public function getShortestName($defaultNamespaceName) + { + $shortestName = $this->getName(); + if ($this->_namespace == $defaultNamespaceName) { + $shortestName = $this->_name; + } + return strtolower($shortestName); + } + + /** + * The normalized name is full-qualified and lowerspaced. Lowerspacing is + * actually wrong, but we have to do it to keep our sanity. If you are + * using database objects that only differentiate in the casing (FOO vs + * Foo) then you will NOT be able to use Doctrine Schema abstraction. + * + * Every non-namespaced element is prefixed with the default namespace + * name which is passed as argument to this method. + * + * @return string + */ + public function getFullQualifiedName($defaultNamespaceName) + { + $name = $this->getName(); + if ( ! $this->_namespace) { + $name = $defaultNamespaceName . "." . $name; + } + return strtolower($name); + } + + /** + * Check if this asset's name is quoted + * + * @return bool + */ + public function isQuoted() + { + return $this->_quoted; + } + + /** + * Check if this identifier is quoted. + * + * @param string $identifier + * @return bool + */ + protected function isIdentifierQuoted($identifier) + { + return (isset($identifier[0]) && ($identifier[0] == '`' || $identifier[0] == '"')); + } + + /** + * Trim quotes from the identifier. + * + * @param string $identifier + * @return string + */ + protected function trimQuotes($identifier) + { + return str_replace(array('`', '"'), '', $identifier); + } + + /** + * Return name of this schema asset. + * + * @return string + */ + public function getName() + { + if ($this->_namespace) { + return $this->_namespace . "." . $this->_name; + } + return $this->_name; + } + + /** + * Get the quoted representation of this asset but only if it was defined with one. Otherwise + * return the plain unquoted value as inserted. + * + * @param AbstractPlatform $platform + * @return string + */ + public function getQuotedName(AbstractPlatform $platform) + { + $keywords = $platform->getReservedKeywordsList(); + $parts = explode(".", $this->getName()); + foreach ($parts as $k => $v) { + $parts[$k] = ($this->_quoted || $keywords->isKeyword($v)) ? $platform->quoteIdentifier($v) : $v; + } + + return implode(".", $parts); + } + + /** + * Generate an identifier from a list of column names obeying a certain string length. + * + * This is especially important for Oracle, since it does not allow identifiers larger than 30 chars, + * however building idents automatically for foreign keys, composite keys or such can easily create + * very long names. + * + * @param array $columnNames + * @param string $prefix + * @param int $maxSize + * @return string + */ + protected function _generateIdentifierName($columnNames, $prefix='', $maxSize=30) + { + $hash = implode("", array_map(function($column) { + return dechex(crc32($column)); + }, $columnNames)); + return substr(strtoupper($prefix . "_" . $hash), 0, $maxSize); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/AbstractSchemaManager.php b/src/core/libs/Doctrine/DBAL/Schema/AbstractSchemaManager.php new file mode 100644 index 0000000..7c64acc --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/AbstractSchemaManager.php @@ -0,0 +1,896 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +use Doctrine\DBAL\Events; +use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs; +use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs; +use Doctrine\DBAL\Types; +use Doctrine\DBAL\DBALException; +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Base class for schema managers. Schema managers are used to inspect and/or + * modify the database schema/structure. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen <kvesteri@cc.hut.fi> + * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) + * @author Roman Borschel <roman@code-factory.org> + * @author Jonathan H. Wage <jonwage@gmail.com> + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.0 + */ +abstract class AbstractSchemaManager +{ + /** + * Holds instance of the Doctrine connection for this schema manager + * + * @var \Doctrine\DBAL\Connection + */ + protected $_conn; + + /** + * Holds instance of the database platform used for this schema manager + * + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + protected $_platform; + + /** + * Constructor. Accepts the Connection instance to manage the schema for + * + * @param \Doctrine\DBAL\Connection $conn + */ + public function __construct(\Doctrine\DBAL\Connection $conn) + { + $this->_conn = $conn; + $this->_platform = $this->_conn->getDatabasePlatform(); + } + + /** + * Return associated platform. + * + * @return \Doctrine\DBAL\Platforms\AbstractPlatform + */ + public function getDatabasePlatform() + { + return $this->_platform; + } + + /** + * Try any method on the schema manager. Normally a method throws an + * exception when your DBMS doesn't support it or if an error occurs. + * This method allows you to try and method on your SchemaManager + * instance and will return false if it does not work or is not supported. + * + * <code> + * $result = $sm->tryMethod('dropView', 'view_name'); + * </code> + * + * @return mixed + */ + public function tryMethod() + { + $args = func_get_args(); + $method = $args[0]; + unset($args[0]); + $args = array_values($args); + + try { + return call_user_func_array(array($this, $method), $args); + } catch (\Exception $e) { + return false; + } + } + + /** + * List the available databases for this connection + * + * @return array $databases + */ + public function listDatabases() + { + $sql = $this->_platform->getListDatabasesSQL(); + + $databases = $this->_conn->fetchAll($sql); + + return $this->_getPortableDatabasesList($databases); + } + + /** + * List the available sequences for this connection + * + * @return Sequence[] + */ + public function listSequences($database = null) + { + if (is_null($database)) { + $database = $this->_conn->getDatabase(); + } + $sql = $this->_platform->getListSequencesSQL($database); + + $sequences = $this->_conn->fetchAll($sql); + + return $this->filterAssetNames($this->_getPortableSequencesList($sequences)); + } + + /** + * List the columns for a given table. + * + * In contrast to other libraries and to the old version of Doctrine, + * this column definition does try to contain the 'primary' field for + * the reason that it is not portable accross different RDBMS. Use + * {@see listTableIndexes($tableName)} to retrieve the primary key + * of a table. We're a RDBMS specifies more details these are held + * in the platformDetails array. + * + * @param string $table The name of the table. + * @param string $database + * @return Column[] + */ + public function listTableColumns($table, $database = null) + { + if ( ! $database) { + $database = $this->_conn->getDatabase(); + } + + $sql = $this->_platform->getListTableColumnsSQL($table, $database); + + $tableColumns = $this->_conn->fetchAll($sql); + + return $this->_getPortableTableColumnList($table, $database, $tableColumns); + } + + /** + * List the indexes for a given table returning an array of Index instances. + * + * Keys of the portable indexes list are all lower-cased. + * + * @param string $table The name of the table + * @return Index[] $tableIndexes + */ + public function listTableIndexes($table) + { + $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); + + $tableIndexes = $this->_conn->fetchAll($sql); + + return $this->_getPortableTableIndexesList($tableIndexes, $table); + } + + /** + * Return true if all the given tables exist. + * + * @param array $tableNames + * @return bool + */ + public function tablesExist($tableNames) + { + $tableNames = array_map('strtolower', (array)$tableNames); + return count($tableNames) == count(\array_intersect($tableNames, array_map('strtolower', $this->listTableNames()))); + } + + /** + * Return a list of all tables in the current database + * + * @return array + */ + public function listTableNames() + { + $sql = $this->_platform->getListTablesSQL(); + + $tables = $this->_conn->fetchAll($sql); + $tableNames = $this->_getPortableTablesList($tables); + return $this->filterAssetNames($tableNames); + } + + /** + * Filter asset names if they are configured to return only a subset of all + * the found elements. + * + * @param array $assetNames + * @return array + */ + protected function filterAssetNames($assetNames) + { + $filterExpr = $this->getFilterSchemaAssetsExpression(); + if ( ! $filterExpr) { + return $assetNames; + } + return array_values ( + array_filter($assetNames, function ($assetName) use ($filterExpr) { + $assetName = ($assetName instanceof AbstractAsset) ? $assetName->getName() : $assetName; + return preg_match($filterExpr, $assetName); + }) + ); + } + + protected function getFilterSchemaAssetsExpression() + { + return $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression(); + } + + /** + * List the tables for this connection + * + * @return Table[] + */ + public function listTables() + { + $tableNames = $this->listTableNames(); + + $tables = array(); + foreach ($tableNames as $tableName) { + $tables[] = $this->listTableDetails($tableName); + } + + return $tables; + } + + /** + * @param string $tableName + * @return Table + */ + public function listTableDetails($tableName) + { + $columns = $this->listTableColumns($tableName); + $foreignKeys = array(); + if ($this->_platform->supportsForeignKeyConstraints()) { + $foreignKeys = $this->listTableForeignKeys($tableName); + } + $indexes = $this->listTableIndexes($tableName); + + return new Table($tableName, $columns, $indexes, $foreignKeys, false, array()); + } + + /** + * List the views this connection has + * + * @return View[] + */ + public function listViews() + { + $database = $this->_conn->getDatabase(); + $sql = $this->_platform->getListViewsSQL($database); + $views = $this->_conn->fetchAll($sql); + + return $this->_getPortableViewsList($views); + } + + /** + * List the foreign keys for the given table + * + * @param string $table The name of the table + * @return ForeignKeyConstraint[] + */ + public function listTableForeignKeys($table, $database = null) + { + if (is_null($database)) { + $database = $this->_conn->getDatabase(); + } + $sql = $this->_platform->getListTableForeignKeysSQL($table, $database); + $tableForeignKeys = $this->_conn->fetchAll($sql); + + return $this->_getPortableTableForeignKeysList($tableForeignKeys); + } + + /* drop*() Methods */ + + /** + * Drops a database. + * + * NOTE: You can not drop the database this SchemaManager is currently connected to. + * + * @param string $database The name of the database to drop + */ + public function dropDatabase($database) + { + $this->_execSql($this->_platform->getDropDatabaseSQL($database)); + } + + /** + * Drop the given table + * + * @param string $table The name of the table to drop + */ + public function dropTable($table) + { + $this->_execSql($this->_platform->getDropTableSQL($table)); + } + + /** + * Drop the index from the given table + * + * @param Index|string $index The name of the index + * @param string|Table $table The name of the table + */ + public function dropIndex($index, $table) + { + if($index instanceof Index) { + $index = $index->getQuotedName($this->_platform); + } + + $this->_execSql($this->_platform->getDropIndexSQL($index, $table)); + } + + /** + * Drop the constraint from the given table + * + * @param Constraint $constraint + * @param string $table The name of the table + */ + public function dropConstraint(Constraint $constraint, $table) + { + $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table)); + } + + /** + * Drops a foreign key from a table. + * + * @param ForeignKeyConstraint|string $table The name of the table with the foreign key. + * @param Table|string $name The name of the foreign key. + * @return boolean $result + */ + public function dropForeignKey($foreignKey, $table) + { + $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table)); + } + + /** + * Drops a sequence with a given name. + * + * @param string $name The name of the sequence to drop. + */ + public function dropSequence($name) + { + $this->_execSql($this->_platform->getDropSequenceSQL($name)); + } + + /** + * Drop a view + * + * @param string $name The name of the view + * @return boolean $result + */ + public function dropView($name) + { + $this->_execSql($this->_platform->getDropViewSQL($name)); + } + + /* create*() Methods */ + + /** + * Creates a new database. + * + * @param string $database The name of the database to create. + */ + public function createDatabase($database) + { + $this->_execSql($this->_platform->getCreateDatabaseSQL($database)); + } + + /** + * Create a new table. + * + * @param Table $table + * @param int $createFlags + */ + public function createTable(Table $table) + { + $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS; + $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags)); + } + + /** + * Create a new sequence + * + * @param Sequence $sequence + * @throws \Doctrine\DBAL\ConnectionException if something fails at database level + */ + public function createSequence($sequence) + { + $this->_execSql($this->_platform->getCreateSequenceSQL($sequence)); + } + + /** + * Create a constraint on a table + * + * @param Constraint $constraint + * @param string|Table $table + */ + public function createConstraint(Constraint $constraint, $table) + { + $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table)); + } + + /** + * Create a new index on a table + * + * @param Index $index + * @param string $table name of the table on which the index is to be created + */ + public function createIndex(Index $index, $table) + { + $this->_execSql($this->_platform->getCreateIndexSQL($index, $table)); + } + + /** + * Create a new foreign key + * + * @param ForeignKeyConstraint $foreignKey ForeignKey instance + * @param string|Table $table name of the table on which the foreign key is to be created + */ + public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) + { + $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table)); + } + + /** + * Create a new view + * + * @param View $view + */ + public function createView(View $view) + { + $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql())); + } + + /* dropAndCreate*() Methods */ + + /** + * Drop and create a constraint + * + * @param Constraint $constraint + * @param string $table + * @see dropConstraint() + * @see createConstraint() + */ + public function dropAndCreateConstraint(Constraint $constraint, $table) + { + $this->tryMethod('dropConstraint', $constraint, $table); + $this->createConstraint($constraint, $table); + } + + /** + * Drop and create a new index on a table + * + * @param string|Table $table name of the table on which the index is to be created + * @param Index $index + */ + public function dropAndCreateIndex(Index $index, $table) + { + $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table); + $this->createIndex($index, $table); + } + + /** + * Drop and create a new foreign key + * + * @param ForeignKeyConstraint $foreignKey associative array that defines properties of the foreign key to be created. + * @param string|Table $table name of the table on which the foreign key is to be created + */ + public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) + { + $this->tryMethod('dropForeignKey', $foreignKey, $table); + $this->createForeignKey($foreignKey, $table); + } + + /** + * Drop and create a new sequence + * + * @param Sequence $sequence + * @throws \Doctrine\DBAL\ConnectionException if something fails at database level + */ + public function dropAndCreateSequence(Sequence $sequence) + { + $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform)); + $this->createSequence($sequence); + } + + /** + * Drop and create a new table. + * + * @param Table $table + */ + public function dropAndCreateTable(Table $table) + { + $this->tryMethod('dropTable', $table->getQuotedName($this->_platform)); + $this->createTable($table); + } + + /** + * Drop and creates a new database. + * + * @param string $database The name of the database to create. + */ + public function dropAndCreateDatabase($database) + { + $this->tryMethod('dropDatabase', $database); + $this->createDatabase($database); + } + + /** + * Drop and create a new view + * + * @param View $view + */ + public function dropAndCreateView(View $view) + { + $this->tryMethod('dropView', $view->getQuotedName($this->_platform)); + $this->createView($view); + } + + /* alterTable() Methods */ + + /** + * Alter an existing tables schema + * + * @param TableDiff $tableDiff + */ + public function alterTable(TableDiff $tableDiff) + { + $queries = $this->_platform->getAlterTableSQL($tableDiff); + if (is_array($queries) && count($queries)) { + foreach ($queries as $ddlQuery) { + $this->_execSql($ddlQuery); + } + } + } + + /** + * Rename a given table to another name + * + * @param string $name The current name of the table + * @param string $newName The new name of the table + */ + public function renameTable($name, $newName) + { + $tableDiff = new TableDiff($name); + $tableDiff->newName = $newName; + $this->alterTable($tableDiff); + } + + /** + * Methods for filtering return values of list*() methods to convert + * the native DBMS data definition to a portable Doctrine definition + */ + + protected function _getPortableDatabasesList($databases) + { + $list = array(); + foreach ($databases as $value) { + if ($value = $this->_getPortableDatabaseDefinition($value)) { + $list[] = $value; + } + } + return $list; + } + + protected function _getPortableDatabaseDefinition($database) + { + return $database; + } + + protected function _getPortableFunctionsList($functions) + { + $list = array(); + foreach ($functions as $value) { + if ($value = $this->_getPortableFunctionDefinition($value)) { + $list[] = $value; + } + } + return $list; + } + + protected function _getPortableFunctionDefinition($function) + { + return $function; + } + + protected function _getPortableTriggersList($triggers) + { + $list = array(); + foreach ($triggers as $value) { + if ($value = $this->_getPortableTriggerDefinition($value)) { + $list[] = $value; + } + } + return $list; + } + + protected function _getPortableTriggerDefinition($trigger) + { + return $trigger; + } + + protected function _getPortableSequencesList($sequences) + { + $list = array(); + foreach ($sequences as $value) { + if ($value = $this->_getPortableSequenceDefinition($value)) { + $list[] = $value; + } + } + return $list; + } + + /** + * @param array $sequence + * @return Sequence + */ + protected function _getPortableSequenceDefinition($sequence) + { + throw DBALException::notSupported('Sequences'); + } + + /** + * Independent of the database the keys of the column list result are lowercased. + * + * The name of the created column instance however is kept in its case. + * + * @param string $table The name of the table. + * @param string $database + * @param array $tableColumns + * @return array + */ + protected function _getPortableTableColumnList($table, $database, $tableColumns) + { + $eventManager = $this->_platform->getEventManager(); + + $list = array(); + foreach ($tableColumns as $tableColumn) { + $column = null; + $defaultPrevented = false; + + if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) { + $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn); + $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs); + + $defaultPrevented = $eventArgs->isDefaultPrevented(); + $column = $eventArgs->getColumn(); + } + + if ( ! $defaultPrevented) { + $column = $this->_getPortableTableColumnDefinition($tableColumn); + } + + if ($column) { + $name = strtolower($column->getQuotedName($this->_platform)); + $list[$name] = $column; + } + } + return $list; + } + + /** + * Get Table Column Definition + * + * @param array $tableColumn + * @return Column + */ + abstract protected function _getPortableTableColumnDefinition($tableColumn); + + /** + * Aggregate and group the index results according to the required data result. + * + * @param array $tableIndexRows + * @param string $tableName + * @return array + */ + protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null) + { + $result = array(); + foreach($tableIndexRows as $tableIndex) { + $indexName = $keyName = $tableIndex['key_name']; + if($tableIndex['primary']) { + $keyName = 'primary'; + } + $keyName = strtolower($keyName); + + if(!isset($result[$keyName])) { + $result[$keyName] = array( + 'name' => $indexName, + 'columns' => array($tableIndex['column_name']), + 'unique' => $tableIndex['non_unique'] ? false : true, + 'primary' => $tableIndex['primary'], + 'flags' => isset($tableIndex['flags']) ? $tableIndex['flags'] : array(), + ); + } else { + $result[$keyName]['columns'][] = $tableIndex['column_name']; + } + } + + $eventManager = $this->_platform->getEventManager(); + + $indexes = array(); + foreach($result as $indexKey => $data) { + $index = null; + $defaultPrevented = false; + + if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) { + $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn); + $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs); + + $defaultPrevented = $eventArgs->isDefaultPrevented(); + $index = $eventArgs->getIndex(); + } + + if ( ! $defaultPrevented) { + $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags']); + } + + if ($index) { + $indexes[$indexKey] = $index; + } + } + + return $indexes; + } + + protected function _getPortableTablesList($tables) + { + $list = array(); + foreach ($tables as $value) { + if ($value = $this->_getPortableTableDefinition($value)) { + $list[] = $value; + } + } + return $list; + } + + protected function _getPortableTableDefinition($table) + { + return $table; + } + + protected function _getPortableUsersList($users) + { + $list = array(); + foreach ($users as $value) { + if ($value = $this->_getPortableUserDefinition($value)) { + $list[] = $value; + } + } + return $list; + } + + protected function _getPortableUserDefinition($user) + { + return $user; + } + + protected function _getPortableViewsList($views) + { + $list = array(); + foreach ($views as $value) { + if ($view = $this->_getPortableViewDefinition($value)) { + $viewName = strtolower($view->getQuotedName($this->_platform)); + $list[$viewName] = $view; + } + } + return $list; + } + + protected function _getPortableViewDefinition($view) + { + return false; + } + + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $list = array(); + foreach ($tableForeignKeys as $value) { + if ($value = $this->_getPortableTableForeignKeyDefinition($value)) { + $list[] = $value; + } + } + return $list; + } + + protected function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + return $tableForeignKey; + } + + protected function _execSql($sql) + { + foreach ((array) $sql as $query) { + $this->_conn->executeUpdate($query); + } + } + + /** + * Create a schema instance for the current database. + * + * @return Schema + */ + public function createSchema() + { + $sequences = array(); + if($this->_platform->supportsSequences()) { + $sequences = $this->listSequences(); + } + $tables = $this->listTables(); + + return new Schema($tables, $sequences, $this->createSchemaConfig()); + } + + /** + * Create the configuration for this schema. + * + * @return SchemaConfig + */ + public function createSchemaConfig() + { + $schemaConfig = new SchemaConfig(); + $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength()); + + $searchPaths = $this->getSchemaSearchPaths(); + if (isset($searchPaths[0])) { + $schemaConfig->setName($searchPaths[0]); + } + + $params = $this->_conn->getParams(); + if (isset($params['defaultTableOptions'])) { + $schemaConfig->setDefaultTableOptions($params['defautTableOptions']); + } + + return $schemaConfig; + } + + /** + * The search path for namespaces in the currently connected database. + * + * The first entry is usually the default namespace in the Schema. All + * further namespaces contain tables/sequences which can also be addressed + * with a short, not full-qualified name. + * + * For databases that don't support subschema/namespaces this method + * returns the name of the currently connected database. + * + * @return array + */ + public function getSchemaSearchPaths() + { + return array($this->_conn->getDatabase()); + } + + /** + * Given a table comment this method tries to extract a typehint for Doctrine Type, or returns + * the type given as default. + * + * @param string $comment + * @param string $currentType + * @return string + */ + public function extractDoctrineTypeFromComment($comment, $currentType) + { + if (preg_match("(\(DC2Type:([a-zA-Z0-9_]+)\))", $comment, $match)) { + $currentType = $match[1]; + } + return $currentType; + } + + public function removeDoctrineTypeFromComment($comment, $type) + { + return str_replace('(DC2Type:'.$type.')', '', $comment); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/Column.php b/src/core/libs/Doctrine/DBAL/Schema/Column.php new file mode 100644 index 0000000..fa6f70b --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Column.php @@ -0,0 +1,423 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +use \Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Schema\Visitor\Visitor; + +/** + * Object representation of a database column + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class Column extends AbstractAsset +{ + /** + * @var \Doctrine\DBAL\Types\Type + */ + protected $_type; + + /** + * @var int + */ + protected $_length = null; + + /** + * @var int + */ + protected $_precision = 10; + + /** + * @var int + */ + protected $_scale = 0; + + /** + * @var bool + */ + protected $_unsigned = false; + + /** + * @var bool + */ + protected $_fixed = false; + + /** + * @var bool + */ + protected $_notnull = true; + + /** + * @var string + */ + protected $_default = null; + + /** + * @var bool + */ + protected $_autoincrement = false; + + /** + * @var array + */ + protected $_platformOptions = array(); + + /** + * @var string + */ + protected $_columnDefinition = null; + + /** + * @var string + */ + protected $_comment = null; + + /** + * @var array + */ + protected $_customSchemaOptions = array(); + + /** + * Create a new Column + * + * @param string $columnName + * @param \Doctrine\DBAL\Types\Type $type + * @param int $length + * @param bool $notNull + * @param mixed $default + * @param bool $unsigned + * @param bool $fixed + * @param int $precision + * @param int $scale + * @param array $platformOptions + */ + public function __construct($columnName, Type $type, array $options=array()) + { + $this->_setName($columnName); + $this->setType($type); + $this->setOptions($options); + } + + /** + * @param array $options + * @return Column + */ + public function setOptions(array $options) + { + foreach ($options as $name => $value) { + $method = "set".$name; + if (method_exists($this, $method)) { + $this->$method($value); + } + } + return $this; + } + + /** + * @param Type $type + * @return Column + */ + public function setType(Type $type) + { + $this->_type = $type; + return $this; + } + + /** + * @param int $length + * @return Column + */ + public function setLength($length) + { + if($length !== null) { + $this->_length = (int)$length; + } else { + $this->_length = null; + } + return $this; + } + + /** + * @param int $precision + * @return Column + */ + public function setPrecision($precision) + { + if (!is_numeric($precision)) { + $precision = 10; // defaults to 10 when no valid precision is given. + } + + $this->_precision = (int)$precision; + return $this; + } + + /** + * @param int $scale + * @return Column + */ + public function setScale($scale) + { + if (!is_numeric($scale)) { + $scale = 0; + } + + $this->_scale = (int)$scale; + return $this; + } + + /** + * + * @param bool $unsigned + * @return Column + */ + public function setUnsigned($unsigned) + { + $this->_unsigned = (bool)$unsigned; + return $this; + } + + /** + * + * @param bool $fixed + * @return Column + */ + public function setFixed($fixed) + { + $this->_fixed = (bool)$fixed; + return $this; + } + + /** + * @param bool $notnull + * @return Column + */ + public function setNotnull($notnull) + { + $this->_notnull = (bool)$notnull; + return $this; + } + + /** + * + * @param mixed $default + * @return Column + */ + public function setDefault($default) + { + $this->_default = $default; + return $this; + } + + /** + * + * @param array $platformOptions + * @return Column + */ + public function setPlatformOptions(array $platformOptions) + { + $this->_platformOptions = $platformOptions; + return $this; + } + + /** + * + * @param string $name + * @param mixed $value + * @return Column + */ + public function setPlatformOption($name, $value) + { + $this->_platformOptions[$name] = $value; + return $this; + } + + /** + * + * @param string + * @return Column + */ + public function setColumnDefinition($value) + { + $this->_columnDefinition = $value; + return $this; + } + + public function getType() + { + return $this->_type; + } + + public function getLength() + { + return $this->_length; + } + + public function getPrecision() + { + return $this->_precision; + } + + public function getScale() + { + return $this->_scale; + } + + public function getUnsigned() + { + return $this->_unsigned; + } + + public function getFixed() + { + return $this->_fixed; + } + + public function getNotnull() + { + return $this->_notnull; + } + + public function getDefault() + { + return $this->_default; + } + + public function getPlatformOptions() + { + return $this->_platformOptions; + } + + public function hasPlatformOption($name) + { + return isset($this->_platformOptions[$name]); + } + + public function getPlatformOption($name) + { + return $this->_platformOptions[$name]; + } + + public function getColumnDefinition() + { + return $this->_columnDefinition; + } + + public function getAutoincrement() + { + return $this->_autoincrement; + } + + public function setAutoincrement($flag) + { + $this->_autoincrement = $flag; + return $this; + } + + public function setComment($comment) + { + $this->_comment = $comment; + return $this; + } + + public function getComment() + { + return $this->_comment; + } + + /** + * @param string $name + * @param mixed $value + * @return Column + */ + public function setCustomSchemaOption($name, $value) + { + $this->_customSchemaOptions[$name] = $value; + return $this; + } + + /** + * @param string $name + * @return boolean + */ + public function hasCustomSchemaOption($name) + { + return isset($this->_customSchemaOptions[$name]); + } + + /** + * @param string $name + * @return mixed + */ + public function getCustomSchemaOption($name) + { + return $this->_customSchemaOptions[$name]; + } + + /** + * @param array $customSchemaOptions + * @return Column + */ + public function setCustomSchemaOptions(array $customSchemaOptions) + { + $this->_customSchemaOptions = $customSchemaOptions; + return $this; + } + + /** + * @return array + */ + public function getCustomSchemaOptions() + { + return $this->_customSchemaOptions; + } + + /** + * @param Visitor $visitor + */ + public function visit(\Doctrine\DBAL\Schema\Visitor $visitor) + { + $visitor->accept($this); + } + + /** + * @return array + */ + public function toArray() + { + return array_merge(array( + 'name' => $this->_name, + 'type' => $this->_type, + 'default' => $this->_default, + 'notnull' => $this->_notnull, + 'length' => $this->_length, + 'precision' => $this->_precision, + 'scale' => $this->_scale, + 'fixed' => $this->_fixed, + 'unsigned' => $this->_unsigned, + 'autoincrement' => $this->_autoincrement, + 'columnDefinition' => $this->_columnDefinition, + 'comment' => $this->_comment, + ), $this->_platformOptions, $this->_customSchemaOptions); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/ColumnDiff.php b/src/core/libs/Doctrine/DBAL/Schema/ColumnDiff.php new file mode 100644 index 0000000..4fc4b9c --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/ColumnDiff.php @@ -0,0 +1,58 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +/** + * Represent the change of a column + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class ColumnDiff +{ + public $oldColumnName; + + /** + * @var Column + */ + public $column; + + /** + * @var array + */ + public $changedProperties = array(); + + public function __construct($oldColumnName, Column $column, array $changedProperties = array()) + { + $this->oldColumnName = $oldColumnName; + $this->column = $column; + $this->changedProperties = $changedProperties; + } + + public function hasChanged($propertyName) + { + return in_array($propertyName, $this->changedProperties); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/Comparator.php b/src/core/libs/Doctrine/DBAL/Schema/Comparator.php new file mode 100644 index 0000000..a1c4951 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Comparator.php @@ -0,0 +1,415 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +/** + * Compare to Schemas and return an instance of SchemaDiff + * + * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class Comparator +{ + /** + * @param Schema $fromSchema + * @param Schema $toSchema + * @return SchemaDiff + */ + static public function compareSchemas( Schema $fromSchema, Schema $toSchema ) + { + $c = new self(); + return $c->compare($fromSchema, $toSchema); + } + + /** + * Returns a SchemaDiff object containing the differences between the schemas $fromSchema and $toSchema. + * + * The returned diferences are returned in such a way that they contain the + * operations to change the schema stored in $fromSchema to the schema that is + * stored in $toSchema. + * + * @param Schema $fromSchema + * @param Schema $toSchema + * + * @return SchemaDiff + */ + public function compare(Schema $fromSchema, Schema $toSchema) + { + $diff = new SchemaDiff(); + + $foreignKeysToTable = array(); + + foreach ( $toSchema->getTables() as $table ) { + $tableName = $table->getShortestName($toSchema->getName()); + if ( ! $fromSchema->hasTable($tableName)) { + $diff->newTables[$tableName] = $toSchema->getTable($tableName); + } else { + $tableDifferences = $this->diffTable($fromSchema->getTable($tableName), $toSchema->getTable($tableName)); + if ($tableDifferences !== false) { + $diff->changedTables[$tableName] = $tableDifferences; + } + } + } + + /* Check if there are tables removed */ + foreach ($fromSchema->getTables() as $table) { + $tableName = $table->getShortestName($fromSchema->getName()); + + $table = $fromSchema->getTable($tableName); + if ( ! $toSchema->hasTable($tableName) ) { + $diff->removedTables[$tableName] = $table; + } + + // also remember all foreign keys that point to a specific table + foreach ($table->getForeignKeys() as $foreignKey) { + $foreignTable = strtolower($foreignKey->getForeignTableName()); + if (!isset($foreignKeysToTable[$foreignTable])) { + $foreignKeysToTable[$foreignTable] = array(); + } + $foreignKeysToTable[$foreignTable][] = $foreignKey; + } + } + + foreach ($diff->removedTables as $tableName => $table) { + if (isset($foreignKeysToTable[$tableName])) { + $diff->orphanedForeignKeys = array_merge($diff->orphanedForeignKeys, $foreignKeysToTable[$tableName]); + } + } + + foreach ($toSchema->getSequences() as $sequence) { + $sequenceName = $sequence->getShortestName($toSchema->getName()); + if ( ! $fromSchema->hasSequence($sequenceName)) { + $diff->newSequences[] = $sequence; + } else { + if ($this->diffSequence($sequence, $fromSchema->getSequence($sequenceName))) { + $diff->changedSequences[] = $toSchema->getSequence($sequenceName); + } + } + } + + foreach ($fromSchema->getSequences() as $sequence) { + if ($this->isAutoIncrementSequenceInSchema($toSchema, $sequence)) { + continue; + } + + $sequenceName = $sequence->getShortestName($fromSchema->getName()); + + if ( ! $toSchema->hasSequence($sequenceName)) { + $diff->removedSequences[] = $sequence; + } + } + + return $diff; + } + + private function isAutoIncrementSequenceInSchema($schema, $sequence) + { + foreach ($schema->getTables() as $table) { + if ($sequence->isAutoIncrementsFor($table)) { + return true; + } + } + + return false; + } + + /** + * + * @param Sequence $sequence1 + * @param Sequence $sequence2 + */ + public function diffSequence(Sequence $sequence1, Sequence $sequence2) + { + if($sequence1->getAllocationSize() != $sequence2->getAllocationSize()) { + return true; + } + + if($sequence1->getInitialValue() != $sequence2->getInitialValue()) { + return true; + } + + return false; + } + + /** + * Returns the difference between the tables $table1 and $table2. + * + * If there are no differences this method returns the boolean false. + * + * @param Table $table1 + * @param Table $table2 + * + * @return bool|TableDiff + */ + public function diffTable(Table $table1, Table $table2) + { + $changes = 0; + $tableDifferences = new TableDiff($table1->getName()); + + $table1Columns = $table1->getColumns(); + $table2Columns = $table2->getColumns(); + + /* See if all the fields in table 1 exist in table 2 */ + foreach ( $table2Columns as $columnName => $column ) { + if ( !$table1->hasColumn($columnName) ) { + $tableDifferences->addedColumns[$columnName] = $column; + $changes++; + } + } + /* See if there are any removed fields in table 2 */ + foreach ( $table1Columns as $columnName => $column ) { + if ( !$table2->hasColumn($columnName) ) { + $tableDifferences->removedColumns[$columnName] = $column; + $changes++; + } + } + + foreach ( $table1Columns as $columnName => $column ) { + if ( $table2->hasColumn($columnName) ) { + $changedProperties = $this->diffColumn( $column, $table2->getColumn($columnName) ); + if (count($changedProperties) ) { + $columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties); + $tableDifferences->changedColumns[$column->getName()] = $columnDiff; + $changes++; + } + } + } + + $this->detectColumnRenamings($tableDifferences); + + $table1Indexes = $table1->getIndexes(); + $table2Indexes = $table2->getIndexes(); + + foreach ($table2Indexes as $index2Name => $index2Definition) { + foreach ($table1Indexes as $index1Name => $index1Definition) { + if ($this->diffIndex($index1Definition, $index2Definition) === false) { + unset($table1Indexes[$index1Name]); + unset($table2Indexes[$index2Name]); + } else { + if ($index1Name == $index2Name) { + $tableDifferences->changedIndexes[$index2Name] = $table2Indexes[$index2Name]; + unset($table1Indexes[$index1Name]); + unset($table2Indexes[$index2Name]); + $changes++; + } + } + } + } + + foreach ($table1Indexes as $index1Name => $index1Definition) { + $tableDifferences->removedIndexes[$index1Name] = $index1Definition; + $changes++; + } + + foreach ($table2Indexes as $index2Name => $index2Definition) { + $tableDifferences->addedIndexes[$index2Name] = $index2Definition; + $changes++; + } + + $fromFkeys = $table1->getForeignKeys(); + $toFkeys = $table2->getForeignKeys(); + + foreach ($fromFkeys as $key1 => $constraint1) { + foreach ($toFkeys as $key2 => $constraint2) { + if($this->diffForeignKey($constraint1, $constraint2) === false) { + unset($fromFkeys[$key1]); + unset($toFkeys[$key2]); + } else { + if (strtolower($constraint1->getName()) == strtolower($constraint2->getName())) { + $tableDifferences->changedForeignKeys[] = $constraint2; + $changes++; + unset($fromFkeys[$key1]); + unset($toFkeys[$key2]); + } + } + } + } + + foreach ($fromFkeys as $key1 => $constraint1) { + $tableDifferences->removedForeignKeys[] = $constraint1; + $changes++; + } + + foreach ($toFkeys as $key2 => $constraint2) { + $tableDifferences->addedForeignKeys[] = $constraint2; + $changes++; + } + + return $changes ? $tableDifferences : false; + } + + /** + * Try to find columns that only changed their name, rename operations maybe cheaper than add/drop + * however ambiguouties between different possibilites should not lead to renaming at all. + * + * @param TableDiff $tableDifferences + */ + private function detectColumnRenamings(TableDiff $tableDifferences) + { + $renameCandidates = array(); + foreach ($tableDifferences->addedColumns as $addedColumnName => $addedColumn) { + foreach ($tableDifferences->removedColumns as $removedColumnName => $removedColumn) { + if (count($this->diffColumn($addedColumn, $removedColumn)) == 0) { + $renameCandidates[$addedColumn->getName()][] = array($removedColumn, $addedColumn, $addedColumnName); + } + } + } + + foreach ($renameCandidates as $candidateColumns) { + if (count($candidateColumns) == 1) { + list($removedColumn, $addedColumn) = $candidateColumns[0]; + $removedColumnName = strtolower($removedColumn->getName()); + $addedColumnName = strtolower($addedColumn->getName()); + + $tableDifferences->renamedColumns[$removedColumnName] = $addedColumn; + unset($tableDifferences->addedColumns[$addedColumnName]); + unset($tableDifferences->removedColumns[$removedColumnName]); + } + } + } + + /** + * @param ForeignKeyConstraint $key1 + * @param ForeignKeyConstraint $key2 + * @return bool + */ + public function diffForeignKey(ForeignKeyConstraint $key1, ForeignKeyConstraint $key2) + { + if (array_map('strtolower', $key1->getLocalColumns()) != array_map('strtolower', $key2->getLocalColumns())) { + return true; + } + + if (array_map('strtolower', $key1->getForeignColumns()) != array_map('strtolower', $key2->getForeignColumns())) { + return true; + } + + if ($key1->onUpdate() != $key2->onUpdate()) { + return true; + } + + if ($key1->onDelete() != $key2->onDelete()) { + return true; + } + + return false; + } + + /** + * Returns the difference between the fields $field1 and $field2. + * + * If there are differences this method returns $field2, otherwise the + * boolean false. + * + * @param Column $column1 + * @param Column $column2 + * + * @return array + */ + public function diffColumn(Column $column1, Column $column2) + { + $changedProperties = array(); + if ( $column1->getType() != $column2->getType() ) { + $changedProperties[] = 'type'; + } + + if ($column1->getNotnull() != $column2->getNotnull()) { + $changedProperties[] = 'notnull'; + } + + if ($column1->getDefault() != $column2->getDefault()) { + $changedProperties[] = 'default'; + } + + if ($column1->getUnsigned() != $column2->getUnsigned()) { + $changedProperties[] = 'unsigned'; + } + + if ($column1->getType() instanceof \Doctrine\DBAL\Types\StringType) { + // check if value of length is set at all, default value assumed otherwise. + $length1 = $column1->getLength() ?: 255; + $length2 = $column2->getLength() ?: 255; + if ($length1 != $length2) { + $changedProperties[] = 'length'; + } + + if ($column1->getFixed() != $column2->getFixed()) { + $changedProperties[] = 'fixed'; + } + } + + if ($column1->getType() instanceof \Doctrine\DBAL\Types\DecimalType) { + if (($column1->getPrecision()?:10) != ($column2->getPrecision()?:10)) { + $changedProperties[] = 'precision'; + } + if ($column1->getScale() != $column2->getScale()) { + $changedProperties[] = 'scale'; + } + } + + if ($column1->getAutoincrement() != $column2->getAutoincrement()) { + $changedProperties[] = 'autoincrement'; + } + + // only allow to delete comment if its set to '' not to null. + if ($column1->getComment() !== null && $column1->getComment() != $column2->getComment()) { + $changedProperties[] = 'comment'; + } + + $options1 = $column1->getCustomSchemaOptions(); + $options2 = $column2->getCustomSchemaOptions(); + + $commonKeys = array_keys(array_intersect_key($options1, $options2)); + + foreach ($commonKeys as $key) { + if ($options1[$key] !== $options2[$key]) { + $changedProperties[] = $key; + } + } + + $diffKeys = array_keys(array_diff_key($options1, $options2) + array_diff_key($options2, $options1)); + + $changedProperties = array_merge($changedProperties, $diffKeys); + + return $changedProperties; + } + + /** + * Finds the difference between the indexes $index1 and $index2. + * + * Compares $index1 with $index2 and returns $index2 if there are any + * differences or false in case there are no differences. + * + * @param Index $index1 + * @param Index $index2 + * @return bool + */ + public function diffIndex(Index $index1, Index $index2) + { + if ($index1->isFullfilledBy($index2) && $index2->isFullfilledBy($index1)) { + return false; + } + return true; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/Constraint.php b/src/core/libs/Doctrine/DBAL/Schema/Constraint.php new file mode 100644 index 0000000..f80410f --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Constraint.php @@ -0,0 +1,42 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Marker interface for contraints + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +interface Constraint +{ + public function getName(); + + public function getQuotedName(AbstractPlatform $platform); + + public function getColumns(); +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/DB2SchemaManager.php b/src/core/libs/Doctrine/DBAL/Schema/DB2SchemaManager.php new file mode 100644 index 0000000..e11c64c --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/DB2SchemaManager.php @@ -0,0 +1,214 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Schema; + +use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs; +use Doctrine\DBAL\Events; + +/** + * IBM Db2 Schema Manager + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 1.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class DB2SchemaManager extends AbstractSchemaManager +{ + /** + * Return a list of all tables in the current database + * + * Apparently creator is the schema not the user who created it: + * {@link http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.sqlref/db2z_sysibmsystablestable.htm} + * + * @return array + */ + public function listTableNames() + { + $sql = $this->_platform->getListTablesSQL(); + $sql .= " AND CREATOR = UPPER('".$this->_conn->getUsername()."')"; + + $tables = $this->_conn->fetchAll($sql); + + return $this->_getPortableTablesList($tables); + } + + + /** + * Get Table Column Definition + * + * @param array $tableColumn + * @return Column + */ + protected function _getPortableTableColumnDefinition($tableColumn) + { + $tableColumn = array_change_key_case($tableColumn, \CASE_LOWER); + + $length = null; + $fixed = null; + $unsigned = false; + $scale = false; + $precision = false; + + $type = $this->_platform->getDoctrineTypeMapping($tableColumn['typename']); + + switch (strtolower($tableColumn['typename'])) { + case 'varchar': + $length = $tableColumn['length']; + $fixed = false; + break; + case 'character': + $length = $tableColumn['length']; + $fixed = true; + break; + case 'clob': + $length = $tableColumn['length']; + break; + case 'decimal': + case 'double': + case 'real': + $scale = $tableColumn['scale']; + $precision = $tableColumn['length']; + break; + } + + $options = array( + 'length' => $length, + 'unsigned' => (bool)$unsigned, + 'fixed' => (bool)$fixed, + 'default' => ($tableColumn['default'] == "NULL") ? null : $tableColumn['default'], + 'notnull' => (bool) ($tableColumn['nulls'] == 'N'), + 'scale' => null, + 'precision' => null, + 'platformOptions' => array(), + ); + + if ($scale !== null && $precision !== null) { + $options['scale'] = $scale; + $options['precision'] = $precision; + } + + return new Column($tableColumn['colname'], \Doctrine\DBAL\Types\Type::getType($type), $options); + } + + protected function _getPortableTablesList($tables) + { + $tableNames = array(); + foreach ($tables as $tableRow) { + $tableRow = array_change_key_case($tableRow, \CASE_LOWER); + $tableNames[] = $tableRow['name']; + } + return $tableNames; + } + + protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) + { + $eventManager = $this->_platform->getEventManager(); + + $indexes = array(); + foreach($tableIndexes as $indexKey => $data) { + $data = array_change_key_case($data, \CASE_LOWER); + $unique = ($data['uniquerule'] == "D") ? false : true; + $primary = ($data['uniquerule'] == "P"); + + $indexName = strtolower($data['name']); + if ($primary) { + $keyName = 'primary'; + } else { + $keyName = $indexName; + } + + $data = array( + 'name' => $indexName, + 'columns' => explode("+", ltrim($data['colnames'], '+')), + 'unique' => $unique, + 'primary' => $primary + ); + + $index = null; + $defaultPrevented = false; + + if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) { + $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn); + $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs); + + $defaultPrevented = $eventArgs->isDefaultPrevented(); + $index = $eventArgs->getIndex(); + } + + if ( ! $defaultPrevented) { + $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']); + } + + if ($index) { + $indexes[$indexKey] = $index; + } + } + + return $indexes; + } + + protected function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + $tableForeignKey = array_change_key_case($tableForeignKey, CASE_LOWER); + + $tableForeignKey['deleterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['deleterule']); + $tableForeignKey['updaterule'] = $this->_getPortableForeignKeyRuleDef($tableForeignKey['updaterule']); + + return new ForeignKeyConstraint( + array_map('trim', (array)$tableForeignKey['fkcolnames']), + $tableForeignKey['reftbname'], + array_map('trim', (array)$tableForeignKey['pkcolnames']), + $tableForeignKey['relname'], + array( + 'onUpdate' => $tableForeignKey['updaterule'], + 'onDelete' => $tableForeignKey['deleterule'], + ) + ); + } + + protected function _getPortableForeignKeyRuleDef($def) + { + if ($def == "C") { + return "CASCADE"; + } else if ($def == "N") { + return "SET NULL"; + } + return null; + } + + protected function _getPortableViewDefinition($view) + { + $view = array_change_key_case($view, \CASE_LOWER); + // sadly this still segfaults on PDO_IBM, see http://pecl.php.net/bugs/bug.php?id=17199 + //$view['text'] = (is_resource($view['text']) ? stream_get_contents($view['text']) : $view['text']); + if (!is_resource($view['text'])) { + $pos = strpos($view['text'], ' AS '); + $sql = substr($view['text'], $pos+4); + } else { + $sql = ''; + } + + return new View($view['name'], $sql); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/DrizzleSchemaManager.php b/src/core/libs/Doctrine/DBAL/Schema/DrizzleSchemaManager.php new file mode 100644 index 0000000..f73b223 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/DrizzleSchemaManager.php @@ -0,0 +1,96 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +/** + * Schema manager for the Drizzle RDBMS. + * + * @author Kim Hemsø Rasmussen <kimhemsoe@gmail.com> + */ +class DrizzleSchemaManager extends AbstractSchemaManager +{ + protected function _getPortableTableColumnDefinition($tableColumn) + { + $tableName = $tableColumn['COLUMN_NAME']; + $dbType = strtolower($tableColumn['DATA_TYPE']); + + $type = $this->_platform->getDoctrineTypeMapping($dbType); + $type = $this->extractDoctrineTypeFromComment($tableColumn['COLUMN_COMMENT'], $type); + $tableColumn['COLUMN_COMMENT'] = $this->removeDoctrineTypeFromComment($tableColumn['COLUMN_COMMENT'], $type); + + $options = array( + 'notnull' => !(bool)$tableColumn['IS_NULLABLE'], + 'length' => (int)$tableColumn['CHARACTER_MAXIMUM_LENGTH'], + 'default' => empty($tableColumn['COLUMN_DEFAULT']) ? null : $tableColumn['COLUMN_DEFAULT'], + 'autoincrement' => (bool)$tableColumn['IS_AUTO_INCREMENT'], + 'scale' => (int)$tableColumn['NUMERIC_SCALE'], + 'precision' => (int)$tableColumn['NUMERIC_PRECISION'], + 'comment' => (isset($tableColumn['COLUMN_COMMENT']) ? $tableColumn['COLUMN_COMMENT'] : null), + ); + + return new Column($tableName, \Doctrine\DBAL\Types\Type::getType($type), $options); + } + + protected function _getPortableDatabaseDefinition($database) + { + return $database['SCHEMA_NAME']; + } + + protected function _getPortableTableDefinition($table) + { + return $table['TABLE_NAME']; + } + + public function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + $columns = array(); + foreach (explode(',', $tableForeignKey['CONSTRAINT_COLUMNS']) as $value) { + $columns[] = trim($value, ' `'); + } + + $ref_columns = array(); + foreach (explode(',', $tableForeignKey['REFERENCED_TABLE_COLUMNS']) as $value) { + $ref_columns[] = trim($value, ' `'); + } + + return new ForeignKeyConstraint( + $columns, + $tableForeignKey['REFERENCED_TABLE_NAME'], + $ref_columns, + $tableForeignKey['CONSTRAINT_NAME'], + array( + 'onUpdate' => $tableForeignKey['UPDATE_RULE'], + 'onDelete' => $tableForeignKey['DELETE_RULE'], + ) + ); + } + + protected function _getPortableTableIndexesList($tableIndexes, $tableName = null) + { + $indexes = array(); + foreach ($tableIndexes as $k) { + $k['primary'] = (boolean)$k['primary']; + $indexes[] = $k; + } + + return parent::_getPortableTableIndexesList($indexes, $tableName); + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Schema/ForeignKeyConstraint.php b/src/core/libs/Doctrine/DBAL/Schema/ForeignKeyConstraint.php new file mode 100644 index 0000000..481d693 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/ForeignKeyConstraint.php @@ -0,0 +1,193 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +use Doctrine\DBAL\Schema\Visitor\Visitor; +use Doctrine\DBAL\Platforms\AbstractPlatform; + +class ForeignKeyConstraint extends AbstractAsset implements Constraint +{ + /** + * @var Table + */ + protected $_localTable; + + /** + * @var array + */ + protected $_localColumnNames; + + /** + * @var string + */ + protected $_foreignTableName; + + /** + * @var array + */ + protected $_foreignColumnNames; + + /** + * @var string + */ + protected $_cascade = ''; + + /** + * @var array + */ + protected $_options; + + /** + * + * @param array $localColumnNames + * @param string $foreignTableName + * @param array $foreignColumnNames + * @param string $cascade + * @param string|null $name + */ + public function __construct(array $localColumnNames, $foreignTableName, array $foreignColumnNames, $name=null, array $options=array()) + { + $this->_setName($name); + $this->_localColumnNames = $localColumnNames; + $this->_foreignTableName = $foreignTableName; + $this->_foreignColumnNames = $foreignColumnNames; + $this->_options = $options; + } + + /** + * @return string + */ + public function getLocalTableName() + { + return $this->_localTable->getName(); + } + + /** + * @param Table $table + */ + public function setLocalTable(Table $table) + { + $this->_localTable = $table; + } + + /** + * @return array + */ + public function getLocalColumns() + { + return $this->_localColumnNames; + } + + public function getColumns() + { + return $this->_localColumnNames; + } + + /** + * @return string + */ + public function getForeignTableName() + { + return $this->_foreignTableName; + } + + /** + * Get the quoted representation of this asset but only if it was defined with one. Otherwise + * return the plain unquoted value as inserted. + * + * @param AbstractPlatform $platform + * @return string + */ + public function getQuotedForeignTableName(AbstractPlatform $platform) + { + $keywords = $platform->getReservedKeywordsList(); + $parts = explode(".", $this->getForeignTableName()); + foreach ($parts AS $k => $v) { + $parts[$k] = ($this->_quoted || $keywords->isKeyword($v)) ? $platform->quoteIdentifier($v) : $v; + } + + return implode(".", $parts); + } + + /** + * @return array + */ + public function getForeignColumns() + { + return $this->_foreignColumnNames; + } + + public function hasOption($name) + { + return isset($this->_options[$name]); + } + + public function getOption($name) + { + return $this->_options[$name]; + } + + /** + * Gets the options associated with this constraint + * + * @return array + */ + public function getOptions() + { + return $this->_options; + } + + /** + * Foreign Key onUpdate status + * + * @return string|null + */ + public function onUpdate() + { + return $this->_onEvent('onUpdate'); + } + + /** + * Foreign Key onDelete status + * + * @return string|null + */ + public function onDelete() + { + return $this->_onEvent('onDelete'); + } + + /** + * @param string $event + * @return string|null + */ + private function _onEvent($event) + { + if (isset($this->_options[$event])) { + $onEvent = strtoupper($this->_options[$event]); + if (!in_array($onEvent, array('NO ACTION', 'RESTRICT'))) { + return $onEvent; + } + } + return false; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/Index.php b/src/core/libs/Doctrine/DBAL/Schema/Index.php new file mode 100644 index 0000000..56b9ea8 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Index.php @@ -0,0 +1,242 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +use Doctrine\DBAL\Schema\Visitor\Visitor; + +class Index extends AbstractAsset implements Constraint +{ + /** + * @var array + */ + protected $_columns; + + /** + * @var bool + */ + protected $_isUnique = false; + + /** + * @var bool + */ + protected $_isPrimary = false; + + /** + * Platform specific flags for indexes. + * + * @var array + */ + protected $_flags = array(); + + /** + * @param string $indexName + * @param array $column + * @param bool $isUnique + * @param bool $isPrimary + */ + public function __construct($indexName, array $columns, $isUnique = false, $isPrimary = false, array $flags = array()) + { + $isUnique = ($isPrimary)?true:$isUnique; + + $this->_setName($indexName); + $this->_isUnique = $isUnique; + $this->_isPrimary = $isPrimary; + + foreach ($columns as $column) { + $this->_addColumn($column); + } + foreach ($flags as $flag) { + $this->addFlag($flag); + } + } + + /** + * @param string $column + */ + protected function _addColumn($column) + { + if(is_string($column)) { + $this->_columns[] = $column; + } else { + throw new \InvalidArgumentException("Expecting a string as Index Column"); + } + } + + /** + * @return array + */ + public function getColumns() + { + return $this->_columns; + } + + /** + * @return array + */ + public function getUnquotedColumns() + { + return array_map(array($this, 'trimQuotes'), $this->getColumns()); + } + + /** + * Is the index neither unique nor primary key? + * + * @return bool + */ + public function isSimpleIndex() + { + return !$this->_isPrimary && !$this->_isUnique; + } + + /** + * @return bool + */ + public function isUnique() + { + return $this->_isUnique; + } + + /** + * @return bool + */ + public function isPrimary() + { + return $this->_isPrimary; + } + + /** + * @param string $columnName + * @param int $pos + * @return bool + */ + public function hasColumnAtPosition($columnName, $pos = 0) + { + $columnName = $this->trimQuotes(strtolower($columnName)); + $indexColumns = array_map('strtolower', $this->getUnquotedColumns()); + return array_search($columnName, $indexColumns) === $pos; + } + + /** + * Check if this index exactly spans the given column names in the correct order. + * + * @param array $columnNames + * @return boolean + */ + public function spansColumns(array $columnNames) + { + $sameColumns = true; + for ($i = 0; $i < count($this->_columns); $i++) { + if (!isset($columnNames[$i]) || $this->trimQuotes(strtolower($this->_columns[$i])) != $this->trimQuotes(strtolower($columnNames[$i]))) { + $sameColumns = false; + } + } + return $sameColumns; + } + + /** + * Check if the other index already fullfills all the indexing and constraint needs of the current one. + * + * @param Index $other + * @return bool + */ + public function isFullfilledBy(Index $other) + { + // allow the other index to be equally large only. It being larger is an option + // but it creates a problem with scenarios of the kind PRIMARY KEY(foo,bar) UNIQUE(foo) + if (count($other->getColumns()) != count($this->getColumns())) { + return false; + } + + // Check if columns are the same, and even in the same order + $sameColumns = $this->spansColumns($other->getColumns()); + + if ($sameColumns) { + if ( ! $this->isUnique() && !$this->isPrimary()) { + // this is a special case: If the current key is neither primary or unique, any uniqe or + // primary key will always have the same effect for the index and there cannot be any constraint + // overlaps. This means a primary or unique index can always fullfill the requirements of just an + // index that has no constraints. + return true; + } else if ($other->isPrimary() != $this->isPrimary()) { + return false; + } else if ($other->isUnique() != $this->isUnique()) { + return false; + } + return true; + } + return false; + } + + /** + * Detect if the other index is a non-unique, non primary index that can be overwritten by this one. + * + * @param Index $other + * @return bool + */ + public function overrules(Index $other) + { + if ($other->isPrimary()) { + return false; + } else if ($this->isSimpleIndex() && $other->isUnique()) { + return false; + } + + if ($this->spansColumns($other->getColumns()) && ($this->isPrimary() || $this->isUnique())) { + return true; + } + return false; + } + + /** + * Add Flag for an index that translates to platform specific handling. + * + * @example $index->addFlag('CLUSTERED') + * @param string $flag + * @return Index + */ + public function addFlag($flag) + { + $this->flags[strtolower($flag)] = true; + return $this; + } + + /** + * Does this index have a specific flag? + * + * @param string $flag + * @return bool + */ + public function hasFlag($flag) + { + return isset($this->flags[strtolower($flag)]); + } + + /** + * Remove a flag + * + * @param string $flag + * @return void + */ + public function removeFlag($flag) + { + unset($this->flags[strtolower($flag)]); + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Schema/MySqlSchemaManager.php b/src/core/libs/Doctrine/DBAL/Schema/MySqlSchemaManager.php new file mode 100644 index 0000000..a9a5964 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/MySqlSchemaManager.php @@ -0,0 +1,208 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +/** + * Schema manager for the MySql RDBMS. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen <kvesteri@cc.hut.fi> + * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) + * @author Roman Borschel <roman@code-factory.org> + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @version $Revision$ + * @since 2.0 + */ +class MySqlSchemaManager extends AbstractSchemaManager +{ + protected function _getPortableViewDefinition($view) + { + return new View($view['TABLE_NAME'], $view['VIEW_DEFINITION']); + } + + protected function _getPortableTableDefinition($table) + { + return array_shift($table); + } + + protected function _getPortableUserDefinition($user) + { + return array( + 'user' => $user['User'], + 'password' => $user['Password'], + ); + } + + protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) + { + foreach($tableIndexes as $k => $v) { + $v = array_change_key_case($v, CASE_LOWER); + if($v['key_name'] == 'PRIMARY') { + $v['primary'] = true; + } else { + $v['primary'] = false; + } + if (strpos($v['index_type'], 'FULLTEXT') !== false) { + $v['flags'] = array('FULLTEXT'); + } + $tableIndexes[$k] = $v; + } + + return parent::_getPortableTableIndexesList($tableIndexes, $tableName); + } + + protected function _getPortableSequenceDefinition($sequence) + { + return end($sequence); + } + + protected function _getPortableDatabaseDefinition($database) + { + return $database['Database']; + } + + /** + * Gets a portable column definition. + * + * The database type is mapped to a corresponding Doctrine mapping type. + * + * @param $tableColumn + * @return array + */ + protected function _getPortableTableColumnDefinition($tableColumn) + { + $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); + + $dbType = strtolower($tableColumn['type']); + $dbType = strtok($dbType, '(), '); + if (isset($tableColumn['length'])) { + $length = $tableColumn['length']; + $decimal = ''; + } else { + $length = strtok('(), '); + $decimal = strtok('(), ') ? strtok('(), '):null; + } + $type = array(); + $fixed = null; + + if ( ! isset($tableColumn['name'])) { + $tableColumn['name'] = ''; + } + + $scale = null; + $precision = null; + + $type = $this->_platform->getDoctrineTypeMapping($dbType); + $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); + $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); + + switch ($dbType) { + case 'char': + $fixed = true; + break; + case 'float': + case 'double': + case 'real': + case 'numeric': + case 'decimal': + if(preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['type'], $match)) { + $precision = $match[1]; + $scale = $match[2]; + $length = null; + } + break; + case 'tinyint': + case 'smallint': + case 'mediumint': + case 'int': + case 'integer': + case 'bigint': + case 'tinyblob': + case 'mediumblob': + case 'longblob': + case 'blob': + case 'year': + $length = null; + break; + } + + $length = ((int) $length == 0) ? null : (int) $length; + + $options = array( + 'length' => $length, + 'unsigned' => (bool) (strpos($tableColumn['type'], 'unsigned') !== false), + 'fixed' => (bool) $fixed, + 'default' => isset($tableColumn['default']) ? $tableColumn['default'] : null, + 'notnull' => (bool) ($tableColumn['null'] != 'YES'), + 'scale' => null, + 'precision' => null, + 'autoincrement' => (bool) (strpos($tableColumn['extra'], 'auto_increment') !== false), + 'comment' => (isset($tableColumn['comment'])) ? $tableColumn['comment'] : null + ); + + if ($scale !== null && $precision !== null) { + $options['scale'] = $scale; + $options['precision'] = $precision; + } + + return new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options); + } + + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $list = array(); + foreach ($tableForeignKeys as $key => $value) { + $value = array_change_key_case($value, CASE_LOWER); + if (!isset($list[$value['constraint_name']])) { + if (!isset($value['delete_rule']) || $value['delete_rule'] == "RESTRICT") { + $value['delete_rule'] = null; + } + if (!isset($value['update_rule']) || $value['update_rule'] == "RESTRICT") { + $value['update_rule'] = null; + } + + $list[$value['constraint_name']] = array( + 'name' => $value['constraint_name'], + 'local' => array(), + 'foreign' => array(), + 'foreignTable' => $value['referenced_table_name'], + 'onDelete' => $value['delete_rule'], + 'onUpdate' => $value['update_rule'], + ); + } + $list[$value['constraint_name']]['local'][] = $value['column_name']; + $list[$value['constraint_name']]['foreign'][] = $value['referenced_column_name']; + } + + $result = array(); + foreach($list as $constraint) { + $result[] = new ForeignKeyConstraint( + array_values($constraint['local']), $constraint['foreignTable'], + array_values($constraint['foreign']), $constraint['name'], + array( + 'onDelete' => $constraint['onDelete'], + 'onUpdate' => $constraint['onUpdate'], + ) + ); + } + + return $result; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/OracleSchemaManager.php b/src/core/libs/Doctrine/DBAL/Schema/OracleSchemaManager.php new file mode 100644 index 0000000..2a880d9 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/OracleSchemaManager.php @@ -0,0 +1,286 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.phpdoctrine.org>. + */ + +namespace Doctrine\DBAL\Schema; + +/** + * Oracle Schema Manager + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen <kvesteri@cc.hut.fi> + * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @version $Revision$ + * @since 2.0 + */ +class OracleSchemaManager extends AbstractSchemaManager +{ + protected function _getPortableViewDefinition($view) + { + $view = \array_change_key_case($view, CASE_LOWER); + + return new View($view['view_name'], $view['text']); + } + + protected function _getPortableUserDefinition($user) + { + $user = \array_change_key_case($user, CASE_LOWER); + + return array( + 'user' => $user['username'], + ); + } + + protected function _getPortableTableDefinition($table) + { + $table = \array_change_key_case($table, CASE_LOWER); + + return $table['table_name']; + } + + /** + * @license New BSD License + * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html + * @param array $tableIndexes + * @param string $tableName + * @return array + */ + protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) + { + $indexBuffer = array(); + foreach ( $tableIndexes as $tableIndex ) { + $tableIndex = \array_change_key_case($tableIndex, CASE_LOWER); + + $keyName = strtolower($tableIndex['name']); + + if ( strtolower($tableIndex['is_primary']) == "p" ) { + $keyName = 'primary'; + $buffer['primary'] = true; + $buffer['non_unique'] = false; + } else { + $buffer['primary'] = false; + $buffer['non_unique'] = ( $tableIndex['is_unique'] == 0 ) ? true : false; + } + $buffer['key_name'] = $keyName; + $buffer['column_name'] = $tableIndex['column_name']; + $indexBuffer[] = $buffer; + } + return parent::_getPortableTableIndexesList($indexBuffer, $tableName); + } + + protected function _getPortableTableColumnDefinition($tableColumn) + { + $tableColumn = \array_change_key_case($tableColumn, CASE_LOWER); + + $dbType = strtolower($tableColumn['data_type']); + if(strpos($dbType, "timestamp(") === 0) { + if (strpos($dbType, "WITH TIME ZONE")) { + $dbType = "timestamptz"; + } else { + $dbType = "timestamp"; + } + } + + $type = array(); + $length = $unsigned = $fixed = null; + if ( ! empty($tableColumn['data_length'])) { + $length = $tableColumn['data_length']; + } + + if ( ! isset($tableColumn['column_name'])) { + $tableColumn['column_name'] = ''; + } + + if (stripos($tableColumn['data_default'], 'NULL') !== null) { + $tableColumn['data_default'] = null; + } + + $precision = null; + $scale = null; + + $type = $this->_platform->getDoctrineTypeMapping($dbType); + $type = $this->extractDoctrineTypeFromComment($tableColumn['comments'], $type); + $tableColumn['comments'] = $this->removeDoctrineTypeFromComment($tableColumn['comments'], $type); + + switch ($dbType) { + case 'number': + if ($tableColumn['data_precision'] == 20 && $tableColumn['data_scale'] == 0) { + $precision = 20; + $scale = 0; + $type = 'bigint'; + } elseif ($tableColumn['data_precision'] == 5 && $tableColumn['data_scale'] == 0) { + $type = 'smallint'; + $precision = 5; + $scale = 0; + } elseif ($tableColumn['data_precision'] == 1 && $tableColumn['data_scale'] == 0) { + $precision = 1; + $scale = 0; + $type = 'boolean'; + } elseif ($tableColumn['data_scale'] > 0) { + $precision = $tableColumn['data_precision']; + $scale = $tableColumn['data_scale']; + $type = 'decimal'; + } + $length = null; + break; + case 'pls_integer': + case 'binary_integer': + $length = null; + break; + case 'varchar': + case 'varchar2': + case 'nvarchar2': + $length = $tableColumn['char_length']; + $fixed = false; + break; + case 'char': + case 'nchar': + $length = $tableColumn['char_length']; + $fixed = true; + break; + case 'date': + case 'timestamp': + $length = null; + break; + case 'float': + $precision = $tableColumn['data_precision']; + $scale = $tableColumn['data_scale']; + $length = null; + break; + case 'clob': + case 'nclob': + $length = null; + break; + case 'blob': + case 'raw': + case 'long raw': + case 'bfile': + $length = null; + break; + case 'rowid': + case 'urowid': + default: + $length = null; + } + + $options = array( + 'notnull' => (bool) ($tableColumn['nullable'] === 'N'), + 'fixed' => (bool) $fixed, + 'unsigned' => (bool) $unsigned, + 'default' => $tableColumn['data_default'], + 'length' => $length, + 'precision' => $precision, + 'scale' => $scale, + 'comment' => (isset($tableColumn['comments'])) ? $tableColumn['comments'] : null, + 'platformDetails' => array(), + ); + + return new Column($tableColumn['column_name'], \Doctrine\DBAL\Types\Type::getType($type), $options); + } + + protected function _getPortableTableForeignKeysList($tableForeignKeys) + { + $list = array(); + foreach ($tableForeignKeys as $value) { + $value = \array_change_key_case($value, CASE_LOWER); + if (!isset($list[$value['constraint_name']])) { + if ($value['delete_rule'] == "NO ACTION") { + $value['delete_rule'] = null; + } + + $list[$value['constraint_name']] = array( + 'name' => $value['constraint_name'], + 'local' => array(), + 'foreign' => array(), + 'foreignTable' => $value['references_table'], + 'onDelete' => $value['delete_rule'], + ); + } + $list[$value['constraint_name']]['local'][$value['position']] = $value['local_column']; + $list[$value['constraint_name']]['foreign'][$value['position']] = $value['foreign_column']; + } + + $result = array(); + foreach($list as $constraint) { + $result[] = new ForeignKeyConstraint( + array_values($constraint['local']), $constraint['foreignTable'], + array_values($constraint['foreign']), $constraint['name'], + array('onDelete' => $constraint['onDelete']) + ); + } + + return $result; + } + + protected function _getPortableSequenceDefinition($sequence) + { + $sequence = \array_change_key_case($sequence, CASE_LOWER); + return new Sequence($sequence['sequence_name'], $sequence['increment_by'], $sequence['min_value']); + } + + protected function _getPortableFunctionDefinition($function) + { + $function = \array_change_key_case($function, CASE_LOWER); + return $function['name']; + } + + protected function _getPortableDatabaseDefinition($database) + { + $database = \array_change_key_case($database, CASE_LOWER); + return $database['username']; + } + + public function createDatabase($database = null) + { + if (is_null($database)) { + $database = $this->_conn->getDatabase(); + } + + $params = $this->_conn->getParams(); + $username = $database; + $password = $params['password']; + + $query = 'CREATE USER ' . $username . ' IDENTIFIED BY ' . $password; + $result = $this->_conn->executeUpdate($query); + + $query = 'GRANT CREATE SESSION, CREATE TABLE, UNLIMITED TABLESPACE, CREATE SEQUENCE, CREATE TRIGGER TO ' . $username; + $result = $this->_conn->executeUpdate($query); + + return true; + } + + public function dropAutoincrement($table) + { + $sql = $this->_platform->getDropAutoincrementSql($table); + foreach ($sql as $query) { + $this->_conn->executeUpdate($query); + } + + return true; + } + + public function dropTable($name) + { + $this->dropAutoincrement($name); + + return parent::dropTable($name); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php b/src/core/libs/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php new file mode 100644 index 0000000..b306fe0 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/PostgreSqlSchemaManager.php @@ -0,0 +1,365 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +/** + * PostgreSQL Schema Manager + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen <kvesteri@cc.hut.fi> + * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.0 + */ +class PostgreSqlSchemaManager extends AbstractSchemaManager +{ + /** + * @var array + */ + private $existingSchemaPaths; + + /** + * Get all the existing schema names. + * + * @return array + */ + public function getSchemaNames() + { + $rows = $this->_conn->fetchAll("SELECT nspname as schema_name FROM pg_namespace WHERE nspname !~ '^pg_.*' and nspname != 'information_schema'"); + return array_map(function($v) { return $v['schema_name']; }, $rows); + } + + /** + * Return an array of schema search paths + * + * This is a PostgreSQL only function. + * + * @return array + */ + public function getSchemaSearchPaths() + { + $params = $this->_conn->getParams(); + $schema = explode(",", $this->_conn->fetchColumn('SHOW search_path')); + if (isset($params['user'])) { + $schema = str_replace('"$user"', $params['user'], $schema); + } + return $schema; + } + + /** + * Get names of all existing schemas in the current users search path. + * + * This is a PostgreSQL only function. + * + * @return array + */ + public function getExistingSchemaSearchPaths() + { + if ($this->existingSchemaPaths === null) { + $this->determineExistingSchemaSearchPaths(); + } + return $this->existingSchemaPaths; + } + + /** + * Use this to set or reset the order of the existing schemas in the current search path of the user + * + * This is a PostgreSQL only function. + * + * @return void + */ + public function determineExistingSchemaSearchPaths() + { + $names = $this->getSchemaNames(); + $paths = $this->getSchemaSearchPaths(); + + $this->existingSchemaPaths = array_filter($paths, function ($v) use ($names) { + return in_array($v, $names); + }); + } + + protected function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + $onUpdate = null; + $onDelete = null; + + if (preg_match('(ON UPDATE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) { + $onUpdate = $match[1]; + } + if (preg_match('(ON DELETE ([a-zA-Z0-9]+( (NULL|ACTION|DEFAULT))?))', $tableForeignKey['condef'], $match)) { + $onDelete = $match[1]; + } + + if (preg_match('/FOREIGN KEY \((.+)\) REFERENCES (.+)\((.+)\)/', $tableForeignKey['condef'], $values)) { + // PostgreSQL returns identifiers that are keywords with quotes, we need them later, don't get + // the idea to trim them here. + $localColumns = array_map('trim', explode(",", $values[1])); + $foreignColumns = array_map('trim', explode(",", $values[3])); + $foreignTable = $values[2]; + } + + return new ForeignKeyConstraint( + $localColumns, $foreignTable, $foreignColumns, $tableForeignKey['conname'], + array('onUpdate' => $onUpdate, 'onDelete' => $onDelete) + ); + } + + public function dropDatabase($database) + { + $params = $this->_conn->getParams(); + $params["dbname"] = "postgres"; + $tmpPlatform = $this->_platform; + $tmpConn = $this->_conn; + + $this->_conn = \Doctrine\DBAL\DriverManager::getConnection($params); + $this->_platform = $this->_conn->getDatabasePlatform(); + + parent::dropDatabase($database); + + $this->_platform = $tmpPlatform; + $this->_conn = $tmpConn; + } + + public function createDatabase($database) + { + $params = $this->_conn->getParams(); + $params["dbname"] = "postgres"; + $tmpPlatform = $this->_platform; + $tmpConn = $this->_conn; + + $this->_conn = \Doctrine\DBAL\DriverManager::getConnection($params); + $this->_platform = $this->_conn->getDatabasePlatform(); + + parent::createDatabase($database); + + $this->_platform = $tmpPlatform; + $this->_conn = $tmpConn; + } + + protected function _getPortableTriggerDefinition($trigger) + { + return $trigger['trigger_name']; + } + + protected function _getPortableViewDefinition($view) + { + return new View($view['viewname'], $view['definition']); + } + + protected function _getPortableUserDefinition($user) + { + return array( + 'user' => $user['usename'], + 'password' => $user['passwd'] + ); + } + + protected function _getPortableTableDefinition($table) + { + $schemas = $this->getExistingSchemaSearchPaths(); + $firstSchema = array_shift($schemas); + + if ($table['schema_name'] == $firstSchema) { + return $table['table_name']; + } else { + return $table['schema_name'] . "." . $table['table_name']; + } + } + + /** + * @license New BSD License + * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html + * @param array $tableIndexes + * @param string $tableName + * @return array + */ + protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) + { + $buffer = array(); + foreach ($tableIndexes as $row) { + $colNumbers = explode(' ', $row['indkey']); + $colNumbersSql = 'IN (' . join(' ,', $colNumbers) . ' )'; + $columnNameSql = "SELECT attnum, attname FROM pg_attribute + WHERE attrelid={$row['indrelid']} AND attnum $colNumbersSql ORDER BY attnum ASC;"; + + $stmt = $this->_conn->executeQuery($columnNameSql); + $indexColumns = $stmt->fetchAll(); + + // required for getting the order of the columns right. + foreach ($colNumbers as $colNum) { + foreach ($indexColumns as $colRow) { + if ($colNum == $colRow['attnum']) { + $buffer[] = array( + 'key_name' => $row['relname'], + 'column_name' => trim($colRow['attname']), + 'non_unique' => !$row['indisunique'], + 'primary' => $row['indisprimary'] + ); + } + } + } + } + return parent::_getPortableTableIndexesList($buffer, $tableName); + } + + protected function _getPortableDatabaseDefinition($database) + { + return $database['datname']; + } + + protected function _getPortableSequenceDefinition($sequence) + { + if ($sequence['schemaname'] != 'public') { + $sequenceName = $sequence['schemaname'] . "." . $sequence['relname']; + } else { + $sequenceName = $sequence['relname']; + } + + $data = $this->_conn->fetchAll('SELECT min_value, increment_by FROM ' . $sequenceName); + return new Sequence($sequenceName, $data[0]['increment_by'], $data[0]['min_value']); + } + + protected function _getPortableTableColumnDefinition($tableColumn) + { + $tableColumn = array_change_key_case($tableColumn, CASE_LOWER); + + if (strtolower($tableColumn['type']) === 'varchar') { + // get length from varchar definition + $length = preg_replace('~.*\(([0-9]*)\).*~', '$1', $tableColumn['complete_type']); + $tableColumn['length'] = $length; + } + + $matches = array(); + + $autoincrement = false; + if (preg_match("/^nextval\('(.*)'(::.*)?\)$/", $tableColumn['default'], $matches)) { + $tableColumn['sequence'] = $matches[1]; + $tableColumn['default'] = null; + $autoincrement = true; + } + + if (stripos($tableColumn['default'], 'NULL') === 0) { + $tableColumn['default'] = null; + } + + $length = (isset($tableColumn['length'])) ? $tableColumn['length'] : null; + if ($length == '-1' && isset($tableColumn['atttypmod'])) { + $length = $tableColumn['atttypmod'] - 4; + } + if ((int) $length <= 0) { + $length = null; + } + $fixed = null; + + if (!isset($tableColumn['name'])) { + $tableColumn['name'] = ''; + } + + $precision = null; + $scale = null; + + $dbType = strtolower($tableColumn['type']); + if (strlen($tableColumn['domain_type']) && !$this->_platform->hasDoctrineTypeMappingFor($tableColumn['type'])) { + $dbType = strtolower($tableColumn['domain_type']); + $tableColumn['complete_type'] = $tableColumn['domain_complete_type']; + } + + $type = $this->_platform->getDoctrineTypeMapping($dbType); + $type = $this->extractDoctrineTypeFromComment($tableColumn['comment'], $type); + $tableColumn['comment'] = $this->removeDoctrineTypeFromComment($tableColumn['comment'], $type); + + switch ($dbType) { + case 'smallint': + case 'int2': + $length = null; + break; + case 'int': + case 'int4': + case 'integer': + $length = null; + break; + case 'bigint': + case 'int8': + $length = null; + break; + case 'bool': + case 'boolean': + $length = null; + break; + case 'text': + $fixed = false; + break; + case 'varchar': + case 'interval': + case '_varchar': + $fixed = false; + break; + case 'char': + case 'bpchar': + $fixed = true; + break; + case 'float': + case 'float4': + case 'float8': + case 'double': + case 'double precision': + case 'real': + case 'decimal': + case 'money': + case 'numeric': + if (preg_match('([A-Za-z]+\(([0-9]+)\,([0-9]+)\))', $tableColumn['complete_type'], $match)) { + $precision = $match[1]; + $scale = $match[2]; + $length = null; + } + break; + case 'year': + $length = null; + break; + } + + if ($tableColumn['default'] && preg_match("('([^']+)'::)", $tableColumn['default'], $match)) { + $tableColumn['default'] = $match[1]; + } + + $options = array( + 'length' => $length, + 'notnull' => (bool) $tableColumn['isnotnull'], + 'default' => $tableColumn['default'], + 'primary' => (bool) ($tableColumn['pri'] == 't'), + 'precision' => $precision, + 'scale' => $scale, + 'fixed' => $fixed, + 'unsigned' => false, + 'autoincrement' => $autoincrement, + 'comment' => $tableColumn['comment'], + ); + + $column = new Column($tableColumn['field'], \Doctrine\DBAL\Types\Type::getType($type), $options); + + if (isset($tableColumn['sequence'])) { + $column->setPlatformOption('sequence', $tableColumn['sequence']); + } + + return $column; + } + +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/SQLServerSchemaManager.php b/src/core/libs/Doctrine/DBAL/Schema/SQLServerSchemaManager.php new file mode 100644 index 0000000..174dc11 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/SQLServerSchemaManager.php @@ -0,0 +1,263 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.phpdoctrine.org>. + */ + +namespace Doctrine\DBAL\Schema; + +use Doctrine\DBAL\Events; +use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs; +use Doctrine\DBAL\Driver\SQLSrv\SQLSrvException; + +/** + * SQL Server Schema Manager + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen <kvesteri@cc.hut.fi> + * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) + * @author Juozas Kaziukenas <juozas@juokaz.com> + * @since 2.0 + */ +class SQLServerSchemaManager extends AbstractSchemaManager +{ + /** + * @override + */ + protected function _getPortableTableColumnDefinition($tableColumn) + { + $dbType = strtolower($tableColumn['TYPE_NAME']); + + $autoincrement = false; + if (stripos($dbType, 'identity')) { + $dbType = trim(str_ireplace('identity', '', $dbType)); + $autoincrement = true; + } + + $type = array(); + $unsigned = $fixed = null; + + if (!isset($tableColumn['name'])) { + $tableColumn['name'] = ''; + } + + $default = $tableColumn['COLUMN_DEF']; + + while ($default != ($default2 = preg_replace("/^\((.*)\)$/", '$1', $default))) { + $default = trim($default2, "'"); + } + + $length = (int) $tableColumn['LENGTH']; + + $type = $this->_platform->getDoctrineTypeMapping($dbType); + switch ($type) { + case 'char': + if ($tableColumn['LENGTH'] == '1') { + $type = 'boolean'; + if (preg_match('/^(is|has)/', $tableColumn['name'])) { + $type = array_reverse($type); + } + } + $fixed = true; + break; + case 'text': + $fixed = false; + break; + } + switch ($dbType) { + case 'nchar': + case 'nvarchar': + case 'ntext': + // Unicode data requires 2 bytes per character + $length = $length / 2; + break; + } + + $options = array( + 'length' => ($length == 0 || !in_array($type, array('text', 'string'))) ? null : $length, + 'unsigned' => (bool) $unsigned, + 'fixed' => (bool) $fixed, + 'default' => $default !== 'NULL' ? $default : null, + 'notnull' => (bool) ($tableColumn['IS_NULLABLE'] != 'YES'), + 'scale' => $tableColumn['SCALE'], + 'precision' => $tableColumn['PRECISION'], + 'autoincrement' => $autoincrement, + ); + + return new Column($tableColumn['COLUMN_NAME'], \Doctrine\DBAL\Types\Type::getType($type), $options); + } + + /** + * @override + */ + protected function _getPortableTableIndexesList($tableIndexRows, $tableName=null) + { + // TODO: Remove code duplication with AbstractSchemaManager; + $result = array(); + foreach ($tableIndexRows as $tableIndex) { + $indexName = $keyName = $tableIndex['index_name']; + if (strpos($tableIndex['index_description'], 'primary key') !== false) { + $keyName = 'primary'; + } + $keyName = strtolower($keyName); + + $flags = array(); + if (strpos($tableIndex['index_description'], 'clustered') !== false) { + $flags[] = 'clustered'; + } else if (strpos($tableIndex['index_description'], 'nonclustered') !== false) { + $flags[] = 'nonclustered'; + } + + $result[$keyName] = array( + 'name' => $indexName, + 'columns' => explode(', ', $tableIndex['index_keys']), + 'unique' => strpos($tableIndex['index_description'], 'unique') !== false, + 'primary' => strpos($tableIndex['index_description'], 'primary key') !== false, + 'flags' => $flags, + ); + } + + $eventManager = $this->_platform->getEventManager(); + + $indexes = array(); + foreach ($result as $indexKey => $data) { + $index = null; + $defaultPrevented = false; + + if (null !== $eventManager && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) { + $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn); + $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs); + + $defaultPrevented = $eventArgs->isDefaultPrevented(); + $index = $eventArgs->getIndex(); + } + + if ( ! $defaultPrevented) { + $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary']); + } + + if ($index) { + $indexes[$indexKey] = $index; + } + } + + return $indexes; + } + + /** + * @override + */ + public function _getPortableTableForeignKeyDefinition($tableForeignKey) + { + return new ForeignKeyConstraint( + (array) $tableForeignKey['ColumnName'], + $tableForeignKey['ReferenceTableName'], + (array) $tableForeignKey['ReferenceColumnName'], + $tableForeignKey['ForeignKey'], + array( + 'onUpdate' => str_replace('_', ' ', $tableForeignKey['update_referential_action_desc']), + 'onDelete' => str_replace('_', ' ', $tableForeignKey['delete_referential_action_desc']), + ) + ); + } + + /** + * @override + */ + protected function _getPortableTableDefinition($table) + { + return $table['name']; + } + + /** + * @override + */ + protected function _getPortableDatabaseDefinition($database) + { + return $database['name']; + } + + /** + * @override + */ + protected function _getPortableViewDefinition($view) + { + // @todo + return new View($view['name'], null); + } + + /** + * List the indexes for a given table returning an array of Index instances. + * + * Keys of the portable indexes list are all lower-cased. + * + * @param string $table The name of the table + * @return Index[] $tableIndexes + */ + public function listTableIndexes($table) + { + $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase()); + + try { + $tableIndexes = $this->_conn->fetchAll($sql); + } catch(\PDOException $e) { + if ($e->getCode() == "IMSSP") { + return array(); + } else { + throw $e; + } + } catch(SQLSrvException $e) { + if (strpos($e->getMessage(), 'SQLSTATE [01000, 15472]') === 0) { + return array(); + } else { + throw $e; + } + } + + return $this->_getPortableTableIndexesList($tableIndexes, $table); + } + + /** + * @override + */ + public function alterTable(TableDiff $tableDiff) + { + if(count($tableDiff->removedColumns) > 0) { + foreach($tableDiff->removedColumns as $col){ + $columnConstraintSql = $this->getColumnConstraintSQL($tableDiff->name, $col->getName()); + foreach ($this->_conn->fetchAll($columnConstraintSql) as $constraint) { + $this->_conn->exec("ALTER TABLE $tableDiff->name DROP CONSTRAINT " . $constraint['Name']); + } + } + } + + return parent::alterTable($tableDiff); + } + + /** + * This function retrieves the constraints for a given column. + */ + private function getColumnConstraintSQL($table, $column) + { + return "SELECT SysObjects.[Name] + FROM SysObjects INNER JOIN (SELECT [Name],[ID] FROM SysObjects WHERE XType = 'U') AS Tab + ON Tab.[ID] = Sysobjects.[Parent_Obj] + INNER JOIN sys.default_constraints DefCons ON DefCons.[object_id] = Sysobjects.[ID] + INNER JOIN SysColumns Col ON Col.[ColID] = DefCons.[parent_column_id] AND Col.[ID] = Tab.[ID] + WHERE Col.[Name] = " . $this->_conn->quote($column) ." AND Tab.[Name] = " . $this->_conn->quote($table) . " + ORDER BY Col.[Name]"; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/Schema.php b/src/core/libs/Doctrine/DBAL/Schema/Schema.php new file mode 100644 index 0000000..5a6ff75 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Schema.php @@ -0,0 +1,373 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +use Doctrine\DBAL\Schema\Visitor\CreateSchemaSqlCollector; +use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector; +use Doctrine\DBAL\Schema\Visitor\Visitor; + +/** + * Object representation of a database schema + * + * Different vendors have very inconsistent naming with regard to the concept + * of a "schema". Doctrine understands a schema as the entity that conceptually + * wraps a set of database objects such as tables, sequences, indexes and + * foreign keys that belong to each other into a namespace. A Doctrine Schema + * has nothing to do with the "SCHEMA" defined as in PostgreSQL, it is more + * related to the concept of "DATABASE" that exists in MySQL and PostgreSQL. + * + * Every asset in the doctrine schema has a name. A name consists of either a + * namespace.local name pair or just a local unqualified name. + * + * The abstraction layer that covers a PostgreSQL schema is the namespace of an + * database object (asset). A schema can have a name, which will be used as + * default namespace for the unqualified database objects that are created in + * the schema. + * + * In the case of MySQL where cross-database queries are allowed this leads to + * databases being "misinterpreted" as namespaces. This is intentional, however + * the CREATE/DROP SQL visitors will just filter this queries and do not + * execute them. Only the queries for the currently connected database are + * executed. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class Schema extends AbstractAsset +{ + /** + * @var array + */ + protected $_tables = array(); + + /** + * @var array + */ + protected $_sequences = array(); + + /** + * @var SchemaConfig + */ + protected $_schemaConfig = false; + + /** + * @param array $tables + * @param array $sequences + * @param array $views + * @param array $triggers + * @param SchemaConfig $schemaConfig + */ + public function __construct(array $tables=array(), array $sequences=array(), SchemaConfig $schemaConfig=null) + { + if ($schemaConfig == null) { + $schemaConfig = new SchemaConfig(); + } + $this->_schemaConfig = $schemaConfig; + $this->_setName($schemaConfig->getName() ?: 'public'); + + foreach ($tables as $table) { + $this->_addTable($table); + } + + foreach ($sequences as $sequence) { + $this->_addSequence($sequence); + } + } + + /** + * @return bool + */ + public function hasExplicitForeignKeyIndexes() + { + return $this->_schemaConfig->hasExplicitForeignKeyIndexes(); + } + + /** + * @param Table $table + */ + protected function _addTable(Table $table) + { + $tableName = $table->getFullQualifiedName($this->getName()); + if(isset($this->_tables[$tableName])) { + throw SchemaException::tableAlreadyExists($tableName); + } + + $this->_tables[$tableName] = $table; + $table->setSchemaConfig($this->_schemaConfig); + } + + /** + * @param Sequence $sequence + */ + protected function _addSequence(Sequence $sequence) + { + $seqName = $sequence->getFullQualifiedName($this->getName()); + if (isset($this->_sequences[$seqName])) { + throw SchemaException::sequenceAlreadyExists($seqName); + } + $this->_sequences[$seqName] = $sequence; + } + + /** + * Get all tables of this schema. + * + * @return array + */ + public function getTables() + { + return $this->_tables; + } + + /** + * @param string $tableName + * @return Table + */ + public function getTable($tableName) + { + $tableName = $this->getFullQualifiedAssetName($tableName); + if (!isset($this->_tables[$tableName])) { + throw SchemaException::tableDoesNotExist($tableName); + } + + return $this->_tables[$tableName]; + } + + /** + * @return string + */ + private function getFullQualifiedAssetName($name) + { + if ($this->isIdentifierQuoted($name)) { + $name = $this->trimQuotes($name); + } + if (strpos($name, ".") === false) { + $name = $this->getName() . "." . $name; + } + return strtolower($name); + } + + /** + * Does this schema have a table with the given name? + * + * @param string $tableName + * @return Schema + */ + public function hasTable($tableName) + { + $tableName = $this->getFullQualifiedAssetName($tableName); + return isset($this->_tables[$tableName]); + } + + /** + * Get all table names, prefixed with a schema name, even the default one + * if present. + * + * @return array + */ + public function getTableNames() + { + return array_keys($this->_tables); + } + + public function hasSequence($sequenceName) + { + $sequenceName = $this->getFullQualifiedAssetName($sequenceName); + return isset($this->_sequences[$sequenceName]); + } + + /** + * @throws SchemaException + * @param string $sequenceName + * @return \Doctrine\DBAL\Schema\Sequence + */ + public function getSequence($sequenceName) + { + $sequenceName = $this->getFullQualifiedAssetName($sequenceName); + if(!$this->hasSequence($sequenceName)) { + throw SchemaException::sequenceDoesNotExist($sequenceName); + } + return $this->_sequences[$sequenceName]; + } + + /** + * @return \Doctrine\DBAL\Schema\Sequence[] + */ + public function getSequences() + { + return $this->_sequences; + } + + /** + * Create a new table + * + * @param string $tableName + * @return Table + */ + public function createTable($tableName) + { + $table = new Table($tableName); + $this->_addTable($table); + + foreach ($this->_schemaConfig->getDefaultTableOptions() as $name => $value) { + $table->addOption($name, $value); + } + + return $table; + } + + /** + * Rename a table + * + * @param string $oldTableName + * @param string $newTableName + * @return Schema + */ + public function renameTable($oldTableName, $newTableName) + { + $table = $this->getTable($oldTableName); + $table->_setName($newTableName); + + $this->dropTable($oldTableName); + $this->_addTable($table); + return $this; + } + + /** + * Drop a table from the schema. + * + * @param string $tableName + * @return Schema + */ + public function dropTable($tableName) + { + $tableName = $this->getFullQualifiedAssetName($tableName); + $table = $this->getTable($tableName); + unset($this->_tables[$tableName]); + return $this; + } + + /** + * Create a new sequence + * + * @param string $sequenceName + * @param int $allocationSize + * @param int $initialValue + * @return Sequence + */ + public function createSequence($sequenceName, $allocationSize=1, $initialValue=1) + { + $seq = new Sequence($sequenceName, $allocationSize, $initialValue); + $this->_addSequence($seq); + return $seq; + } + + /** + * @param string $sequenceName + * @return Schema + */ + public function dropSequence($sequenceName) + { + $sequenceName = $this->getFullQualifiedAssetName($sequenceName); + unset($this->_sequences[$sequenceName]); + return $this; + } + + /** + * Return an array of necessary sql queries to create the schema on the given platform. + * + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + * @return array + */ + public function toSql(\Doctrine\DBAL\Platforms\AbstractPlatform $platform) + { + $sqlCollector = new CreateSchemaSqlCollector($platform); + $this->visit($sqlCollector); + + return $sqlCollector->getQueries(); + } + + /** + * Return an array of necessary sql queries to drop the schema on the given platform. + * + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + * @return array + */ + public function toDropSql(\Doctrine\DBAL\Platforms\AbstractPlatform $platform) + { + $dropSqlCollector = new DropSchemaSqlCollector($platform); + $this->visit($dropSqlCollector); + + return $dropSqlCollector->getQueries(); + } + + /** + * @param Schema $toSchema + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function getMigrateToSql(Schema $toSchema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) + { + $comparator = new Comparator(); + $schemaDiff = $comparator->compare($this, $toSchema); + return $schemaDiff->toSql($platform); + } + + /** + * @param Schema $fromSchema + * @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform + */ + public function getMigrateFromSql(Schema $fromSchema, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) + { + $comparator = new Comparator(); + $schemaDiff = $comparator->compare($fromSchema, $this); + return $schemaDiff->toSql($platform); + } + + /** + * @param Visitor $visitor + */ + public function visit(Visitor $visitor) + { + $visitor->acceptSchema($this); + + foreach ($this->_tables as $table) { + $table->visit($visitor); + } + foreach ($this->_sequences as $sequence) { + $sequence->visit($visitor); + } + } + + /** + * Cloning a Schema triggers a deep clone of all related assets. + * + * @return void + */ + public function __clone() + { + foreach ($this->_tables as $k => $table) { + $this->_tables[$k] = clone $table; + } + foreach ($this->_sequences as $k => $sequence) { + $this->_sequences[$k] = clone $sequence; + } + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/SchemaConfig.php b/src/core/libs/Doctrine/DBAL/Schema/SchemaConfig.php new file mode 100644 index 0000000..d90da20 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/SchemaConfig.php @@ -0,0 +1,119 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +/** + * Configuration for a Schema + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class SchemaConfig +{ + /** + * @var bool + */ + protected $hasExplicitForeignKeyIndexes = false; + + /** + * @var int + */ + protected $maxIdentifierLength = 63; + + /** + * @var string + */ + protected $name; + + /** + * @var array + */ + protected $defaultTableOptions = array(); + + /** + * @return bool + */ + public function hasExplicitForeignKeyIndexes() + { + return $this->hasExplicitForeignKeyIndexes; + } + + /** + * @param bool $flag + */ + public function setExplicitForeignKeyIndexes($flag) + { + $this->hasExplicitForeignKeyIndexes = (bool)$flag; + } + + /** + * @param int $length + */ + public function setMaxIdentifierLength($length) + { + $this->maxIdentifierLength = (int)$length; + } + + /** + * @return int + */ + public function getMaxIdentifierLength() + { + return $this->maxIdentifierLength; + } + + /** + * Get default namespace of schema objects. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * set default namespace name of schema objects. + * + * @param string $name the value to set. + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * Get the default options that are passed to Table instances created with + * Schema#createTable(). + * + * @return array + */ + public function getDefaultTableOptions() + { + return $this->defaultTableOptions; + } + + public function setDefaultTableOptions(array $defaultTableOptions) + { + $this->defaultTableOptions = $defaultTableOptions; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/SchemaDiff.php b/src/core/libs/Doctrine/DBAL/Schema/SchemaDiff.php new file mode 100644 index 0000000..ba0d9e6 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/SchemaDiff.php @@ -0,0 +1,176 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +use \Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Schema Diff + * + * + * @link www.doctrine-project.org + * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class SchemaDiff +{ + /** + * All added tables + * + * @var array(string=>ezcDbSchemaTable) + */ + public $newTables = array(); + + /** + * All changed tables + * + * @var array(string=>ezcDbSchemaTableDiff) + */ + public $changedTables = array(); + + /** + * All removed tables + * + * @var array(string=>Table) + */ + public $removedTables = array(); + + /** + * @var array + */ + public $newSequences = array(); + + /** + * @var array + */ + public $changedSequences = array(); + + /** + * @var array + */ + public $removedSequences = array(); + + /** + * @var array + */ + public $orphanedForeignKeys = array(); + + /** + * Constructs an SchemaDiff object. + * + * @param array(string=>Table) $newTables + * @param array(string=>TableDiff) $changedTables + * @param array(string=>bool) $removedTables + */ + public function __construct($newTables = array(), $changedTables = array(), $removedTables = array()) + { + $this->newTables = $newTables; + $this->changedTables = $changedTables; + $this->removedTables = $removedTables; + } + + /** + * The to save sql mode ensures that the following things don't happen: + * + * 1. Tables are deleted + * 2. Sequences are deleted + * 3. Foreign Keys which reference tables that would otherwise be deleted. + * + * This way it is ensured that assets are deleted which might not be relevant to the metadata schema at all. + * + * @param AbstractPlatform $platform + * @return array + */ + public function toSaveSql(AbstractPlatform $platform) + { + return $this->_toSql($platform, true); + } + + /** + * @param AbstractPlatform $platform + * @return array + */ + public function toSql(AbstractPlatform $platform) + { + return $this->_toSql($platform, false); + } + + /** + * @param AbstractPlatform $platform + * @param bool $saveMode + * @return array + */ + protected function _toSql(AbstractPlatform $platform, $saveMode = false) + { + $sql = array(); + + if ($platform->supportsForeignKeyConstraints() && $saveMode == false) { + foreach ($this->orphanedForeignKeys as $orphanedForeignKey) { + $sql[] = $platform->getDropForeignKeySQL($orphanedForeignKey, $orphanedForeignKey->getLocalTableName()); + } + } + + if ($platform->supportsSequences() == true) { + foreach ($this->changedSequences as $sequence) { + $sql[] = $platform->getAlterSequenceSQL($sequence); + } + + if ($saveMode === false) { + foreach ($this->removedSequences as $sequence) { + $sql[] = $platform->getDropSequenceSQL($sequence); + } + } + + foreach ($this->newSequences as $sequence) { + $sql[] = $platform->getCreateSequenceSQL($sequence); + } + } + + $foreignKeySql = array(); + foreach ($this->newTables as $table) { + $sql = array_merge( + $sql, + $platform->getCreateTableSQL($table, AbstractPlatform::CREATE_INDEXES) + ); + + if ($platform->supportsForeignKeyConstraints()) { + foreach ($table->getForeignKeys() as $foreignKey) { + $foreignKeySql[] = $platform->getCreateForeignKeySQL($foreignKey, $table); + } + } + } + $sql = array_merge($sql, $foreignKeySql); + + if ($saveMode === false) { + foreach ($this->removedTables as $table) { + $sql[] = $platform->getDropTableSQL($table); + } + } + + foreach ($this->changedTables as $tableDiff) { + $sql = array_merge($sql, $platform->getAlterTableSQL($tableDiff)); + } + + return $sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/SchemaException.php b/src/core/libs/Doctrine/DBAL/Schema/SchemaException.php new file mode 100644 index 0000000..a8cb93d --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/SchemaException.php @@ -0,0 +1,126 @@ +<?php + +namespace Doctrine\DBAL\Schema; + +class SchemaException extends \Doctrine\DBAL\DBALException +{ + const TABLE_DOESNT_EXIST = 10; + const TABLE_ALREADY_EXISTS = 20; + const COLUMN_DOESNT_EXIST = 30; + const COLUMN_ALREADY_EXISTS = 40; + const INDEX_DOESNT_EXIST = 50; + const INDEX_ALREADY_EXISTS = 60; + const SEQUENCE_DOENST_EXIST = 70; + const SEQUENCE_ALREADY_EXISTS = 80; + const INDEX_INVALID_NAME = 90; + const FOREIGNKEY_DOESNT_EXIST = 100; + + /** + * @param string $tableName + * @return SchemaException + */ + static public function tableDoesNotExist($tableName) + { + return new self("There is no table with name '".$tableName."' in the schema.", self::TABLE_DOESNT_EXIST); + } + + /** + * @param string $indexName + * @return SchemaException + */ + static public function indexNameInvalid($indexName) + { + return new self("Invalid index-name $indexName given, has to be [a-zA-Z0-9_]", self::INDEX_INVALID_NAME); + } + + /** + * @param string $indexName + * @return SchemaException + */ + static public function indexDoesNotExist($indexName, $table) + { + return new self("Index '$indexName' does not exist on table '$table'.", self::INDEX_DOESNT_EXIST); + } + + /** + * @param string $indexName + * @return SchemaException + */ + static public function indexAlreadyExists($indexName, $table) + { + return new self("An index with name '$indexName' was already defined on table '$table'.", self::INDEX_ALREADY_EXISTS); + } + + /** + * @param string $columnName + * @return SchemaException + */ + static public function columnDoesNotExist($columnName, $table) + { + return new self("There is no column with name '$columnName' on table '$table'.", self::COLUMN_DOESNT_EXIST); + } + + /** + * + * @param string $tableName + * @return SchemaException + */ + static public function tableAlreadyExists($tableName) + { + return new self("The table with name '".$tableName."' already exists.", self::TABLE_ALREADY_EXISTS); + } + + /** + * + * @param string $tableName + * @param string $columnName + * @return SchemaException + */ + static public function columnAlreadyExists($tableName, $columnName) + { + return new self( + "The column '".$columnName."' on table '".$tableName."' already exists.", self::COLUMN_ALREADY_EXISTS + ); + } + + /** + * @param string $sequenceName + * @return SchemaException + */ + static public function sequenceAlreadyExists($sequenceName) + { + return new self("The sequence '".$sequenceName."' already exists.", self::SEQUENCE_ALREADY_EXISTS); + } + + /** + * @param string $sequenceName + * @return SchemaException + */ + static public function sequenceDoesNotExist($sequenceName) + { + return new self("There exists no sequence with the name '".$sequenceName."'.", self::SEQUENCE_DOENST_EXIST); + } + + /** + * @param string $fkName + * @return SchemaException + */ + static public function foreignKeyDoesNotExist($fkName, $table) + { + return new self("There exists no foreign key with the name '$fkName' on table '$table'.", self::FOREIGNKEY_DOESNT_EXIST); + } + + static public function namedForeignKeyRequired(Table $localTable, ForeignKeyConstraint $foreignKey) + { + return new self( + "The performed schema operation on ".$localTable->getName()." requires a named foreign key, ". + "but the given foreign key from (".implode(", ", $foreignKey->getColumns()).") onto foreign table ". + "'".$foreignKey->getForeignTableName()."' (".implode(", ", $foreignKey->getForeignColumns()).") is currently ". + "unnamed." + ); + } + + static public function alterTableChangeNotSupported($changeName) { + return new self ("Alter table change not supported, given '$changeName'"); + } +} \ No newline at end of file diff --git a/src/core/libs/Doctrine/DBAL/Schema/Sequence.php b/src/core/libs/Doctrine/DBAL/Schema/Sequence.php new file mode 100644 index 0000000..87ff0fa --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Sequence.php @@ -0,0 +1,120 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +use Doctrine\DBAL\Schema\Visitor\Visitor; + +/** + * Sequence Structure + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class Sequence extends AbstractAsset +{ + /** + * @var int + */ + protected $_allocationSize = 1; + + /** + * @var int + */ + protected $_initialValue = 1; + + /** + * + * @param string $name + * @param int $allocationSize + * @param int $initialValue + */ + public function __construct($name, $allocationSize=1, $initialValue=1) + { + $this->_setName($name); + $this->_allocationSize = (is_numeric($allocationSize))?$allocationSize:1; + $this->_initialValue = (is_numeric($initialValue))?$initialValue:1; + } + + public function getAllocationSize() + { + return $this->_allocationSize; + } + + public function getInitialValue() + { + return $this->_initialValue; + } + + public function setAllocationSize($allocationSize) + { + $this->_allocationSize = (is_numeric($allocationSize))?$allocationSize:1; + } + + public function setInitialValue($initialValue) + { + $this->_initialValue = (is_numeric($initialValue))?$initialValue:1; + } + + /** + * Check if this sequence is an autoincrement sequence for a given table. + * + * This is used inside the comparator to not report sequences as missing, + * when the "from" schema implicitly creates the sequences. + * + * @param Table $table + * + * @return bool + */ + public function isAutoIncrementsFor(Table $table) + { + if ( ! $table->hasPrimaryKey()) { + return false; + } + + $pkColumns = $table->getPrimaryKey()->getColumns(); + + if (count($pkColumns) != 1) { + return false; + } + + $column = $table->getColumn($pkColumns[0]); + + if ( ! $column->getAutoincrement()) { + return false; + } + + $sequenceName = $this->getShortestName($table->getNamespaceName()); + $tableName = $table->getShortestName($table->getNamespaceName()); + $tableSequenceName = sprintf('%s_%s_seq', $tableName, $pkColumns[0]); + + return $tableSequenceName === $sequenceName; + } + + /** + * @param Visitor $visitor + */ + public function visit(Visitor $visitor) + { + $visitor->acceptSequence($this); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/SqliteSchemaManager.php b/src/core/libs/Doctrine/DBAL/Schema/SqliteSchemaManager.php new file mode 100644 index 0000000..41a941d --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/SqliteSchemaManager.php @@ -0,0 +1,190 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +/** + * SqliteSchemaManager + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen <kvesteri@cc.hut.fi> + * @author Lukas Smith <smith@pooteeweet.org> (PEAR MDB2 library) + * @author Jonathan H. Wage <jonwage@gmail.com> + * @version $Revision$ + * @since 2.0 + */ +class SqliteSchemaManager extends AbstractSchemaManager +{ + /** + * {@inheritdoc} + * + * @override + */ + public function dropDatabase($database) + { + if (file_exists($database)) { + unlink($database); + } + } + + /** + * {@inheritdoc} + * + * @override + */ + public function createDatabase($database) + { + $params = $this->_conn->getParams(); + $driver = $params['driver']; + $options = array( + 'driver' => $driver, + 'path' => $database + ); + $conn = \Doctrine\DBAL\DriverManager::getConnection($options); + $conn->connect(); + $conn->close(); + } + + protected function _getPortableTableDefinition($table) + { + return $table['name']; + } + + /** + * @license New BSD License + * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html + * @param array $tableIndexes + * @param string $tableName + * @return array + */ + protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) + { + $indexBuffer = array(); + + // fetch primary + $stmt = $this->_conn->executeQuery( "PRAGMA TABLE_INFO ('$tableName')" ); + $indexArray = $stmt->fetchAll(\PDO::FETCH_ASSOC); + foreach($indexArray as $indexColumnRow) { + if($indexColumnRow['pk'] == "1") { + $indexBuffer[] = array( + 'key_name' => 'primary', + 'primary' => true, + 'non_unique' => false, + 'column_name' => $indexColumnRow['name'] + ); + } + } + + // fetch regular indexes + foreach($tableIndexes as $tableIndex) { + // Ignore indexes with reserved names, e.g. autoindexes + if (strpos($tableIndex['name'], 'sqlite_') !== 0) { + $keyName = $tableIndex['name']; + $idx = array(); + $idx['key_name'] = $keyName; + $idx['primary'] = false; + $idx['non_unique'] = $tableIndex['unique']?false:true; + + $stmt = $this->_conn->executeQuery( "PRAGMA INDEX_INFO ( '{$keyName}' )" ); + $indexArray = $stmt->fetchAll(\PDO::FETCH_ASSOC); + + foreach ( $indexArray as $indexColumnRow ) { + $idx['column_name'] = $indexColumnRow['name']; + $indexBuffer[] = $idx; + } + } + } + + return parent::_getPortableTableIndexesList($indexBuffer, $tableName); + } + + protected function _getPortableTableIndexDefinition($tableIndex) + { + return array( + 'name' => $tableIndex['name'], + 'unique' => (bool) $tableIndex['unique'] + ); + } + + protected function _getPortableTableColumnDefinition($tableColumn) + { + $e = explode('(', $tableColumn['type']); + $tableColumn['type'] = $e[0]; + if (isset($e[1])) { + $length = trim($e[1], ')'); + $tableColumn['length'] = $length; + } + + $dbType = strtolower($tableColumn['type']); + $length = isset($tableColumn['length']) ? $tableColumn['length'] : null; + $unsigned = (boolean) isset($tableColumn['unsigned']) ? $tableColumn['unsigned'] : false; + $fixed = false; + $type = $this->_platform->getDoctrineTypeMapping($dbType); + $default = $tableColumn['dflt_value']; + if ($default == 'NULL') { + $default = null; + } + if ($default !== null) { + // SQLite returns strings wrapped in single quotes, so we need to strip them + $default = preg_replace("/^'(.*)'$/", '\1', $default); + } + $notnull = (bool) $tableColumn['notnull']; + + if ( ! isset($tableColumn['name'])) { + $tableColumn['name'] = ''; + } + + $precision = null; + $scale = null; + + switch ($dbType) { + case 'char': + $fixed = true; + break; + case 'float': + case 'double': + case 'real': + case 'decimal': + case 'numeric': + if (isset($tableColumn['length'])) { + list($precision, $scale) = array_map('trim', explode(', ', $tableColumn['length'])); + } + $length = null; + break; + } + + $options = array( + 'length' => $length, + 'unsigned' => (bool) $unsigned, + 'fixed' => $fixed, + 'notnull' => $notnull, + 'default' => $default, + 'precision' => $precision, + 'scale' => $scale, + 'autoincrement' => false, + ); + + return new Column($tableColumn['name'], \Doctrine\DBAL\Types\Type::getType($type), $options); + } + + protected function _getPortableViewDefinition($view) + { + return new View($view['name'], $view['sql']); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php b/src/core/libs/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php new file mode 100644 index 0000000..16fb033 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Synchronizer/AbstractSchemaSynchronizer.php @@ -0,0 +1,58 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema\Synchronizer; + +use Doctrine\DBAL\Connection; + +/** + * Abstract schema synchronizer with methods for executing batches of SQL. + */ +abstract class AbstractSchemaSynchronizer implements SchemaSynchronizer +{ + /** + * @var Connection + */ + protected $conn; + + public function __construct(Connection $conn) + { + $this->conn = $conn; + } + + protected function processSqlSafely(array $sql) + { + foreach ($sql as $s) { + try { + $this->conn->exec($s); + } catch(\Exception $e) { + + } + } + } + + protected function processSql(array $sql) + { + foreach ($sql as $s) { + $this->conn->exec($s); + } + } + +} + diff --git a/src/core/libs/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php b/src/core/libs/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php new file mode 100644 index 0000000..c249815 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Synchronizer/SchemaSynchronizer.php @@ -0,0 +1,96 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema\Synchronizer; + +use Doctrine\DBAL\Schema\Schema; + +/** + * The synchronizer knows how to synchronize a schema with the configured + * database. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +interface SchemaSynchronizer +{ + /** + * Get the SQL statements that can be executed to create the schema. + * + * @param Schema $createSchema + * @return array + */ + function getCreateSchema(Schema $createSchema); + + /** + * Get the SQL Statements to update given schema with the underlying db. + * + * @param Schema $toSchema + * @param bool $noDrops + * @return array + */ + function getUpdateSchema(Schema $toSchema, $noDrops = false); + + /** + * Get the SQL Statements to drop the given schema from underlying db. + * + * @param Schema $dropSchema + * @return array + */ + function getDropSchema(Schema $dropSchema); + + /** + * Get the SQL statements to drop all schema assets from underlying db. + * + * @return array + */ + function getDropAllSchema(); + + /** + * Create the Schema + * + * @param Schema $createSchema + * @return void + */ + function createSchema(Schema $createSchema); + + /** + * Update the Schema to new schema version. + * + * @param Schema $toSchema + * @param bool $noDrops + * @return void + */ + function updateSchema(Schema $toSchema, $noDrops = false); + + /** + * Drop the given database schema from the underlying db. + * + * @param Schema $dropSchema + * @return void + */ + function dropSchema(Schema $dropSchema); + + /** + * Drop all assets from the underyling db. + * + * @return void + */ + function dropAllSchema(); +} + diff --git a/src/core/libs/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php b/src/core/libs/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php new file mode 100644 index 0000000..38ea53a --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Synchronizer/SingleDatabaseSynchronizer.php @@ -0,0 +1,197 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ +namespace Doctrine\DBAL\Schema\Synchronizer; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Schema\Comparator; +use Doctrine\DBAL\Schema\Visitor\DropSchemaSqlCollector; + +/** + * Schema Synchronizer for Default DBAL Connection + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class SingleDatabaseSynchronizer extends AbstractSchemaSynchronizer +{ + /** + * @var Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $platform; + + public function __construct(Connection $conn) + { + parent::__construct($conn); + $this->platform = $conn->getDatabasePlatform(); + } + + /** + * Get the SQL statements that can be executed to create the schema. + * + * @param Schema $createSchema + * @return array + */ + public function getCreateSchema(Schema $createSchema) + { + return $createSchema->toSql($this->platform); + } + + /** + * Get the SQL Statements to update given schema with the underlying db. + * + * @param Schema $toSchema + * @param bool $noDrops + * @return array + */ + public function getUpdateSchema(Schema $toSchema, $noDrops = false) + { + $comparator = new Comparator(); + $sm = $this->conn->getSchemaManager(); + + $fromSchema = $sm->createSchema(); + $schemaDiff = $comparator->compare($fromSchema, $toSchema); + + if ($noDrops) { + return $schemaDiff->toSaveSql($this->platform); + } + + return $schemaDiff->toSql($this->platform); + } + + /** + * Get the SQL Statements to drop the given schema from underlying db. + * + * @param Schema $dropSchema + * @return array + */ + public function getDropSchema(Schema $dropSchema) + { + $visitor = new DropSchemaSqlCollector($this->platform); + $sm = $this->conn->getSchemaManager(); + + $fullSchema = $sm->createSchema(); + + foreach ($fullSchema->getTables() as $table) { + if ( $dropSchema->hasTable($table->getName())) { + $visitor->acceptTable($table); + } + + foreach ($table->getForeignKeys() as $foreignKey) { + if ( ! $dropSchema->hasTable($table->getName())) { + continue; + } + + if ( ! $dropSchema->hasTable($foreignKey->getForeignTableName())) { + continue; + } + + $visitor->acceptForeignKey($table, $foreignKey); + } + } + + if ( ! $this->platform->supportsSequences()) { + return $visitor->getQueries(); + } + + foreach ($dropSchema->getSequences() as $sequence) { + $visitor->acceptSequence($sequence); + } + + foreach ($dropSchema->getTables() as $table) { + /* @var $sequence Table */ + if ( ! $table->hasPrimaryKey()) { + continue; + } + + $columns = $table->getPrimaryKey()->getColumns(); + if (count($columns) > 1) { + continue; + } + + $checkSequence = $table->getName() . "_" . $columns[0] . "_seq"; + if ($fullSchema->hasSequence($checkSequence)) { + $visitor->acceptSequence($fullSchema->getSequence($checkSequence)); + } + } + + return $visitor->getQueries(); + } + + /** + * Get the SQL statements to drop all schema assets from underlying db. + * + * @return array + */ + public function getDropAllSchema() + { + $sm = $this->conn->getSchemaManager(); + $visitor = new DropSchemaSqlCollector($this->platform); + + /* @var $schema \Doctrine\DBAL\Schema\Schema */ + $schema = $sm->createSchema(); + $schema->visit($visitor); + + return $visitor->getQueries(); + } + + /** + * Create the Schema + * + * @param Schema $createSchema + * @return void + */ + public function createSchema(Schema $createSchema) + { + $this->processSql($this->getCreateSchema($createSchema)); + } + + /** + * Update the Schema to new schema version. + * + * @param Schema $toSchema + * @param bool $noDrops + * @return void + */ + public function updateSchema(Schema $toSchema, $noDrops = false) + { + $this->processSql($this->getUpdateSchema($toSchema, $noDrops)); + } + + /** + * Drop the given database schema from the underlying db. + * + * @param Schema $dropSchema + * @return void + */ + public function dropSchema(Schema $dropSchema) + { + $this->processSqlSafely($this->getDropSchema($dropSchema)); + } + + /** + * Drop all assets from the underyling db. + * + * @return void + */ + public function dropAllSchema() + { + $this->processSql($this->getDropAllSchema()); + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Schema/Table.php b/src/core/libs/Doctrine/DBAL/Schema/Table.php new file mode 100644 index 0000000..d0763c5 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Table.php @@ -0,0 +1,678 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +use Doctrine\DBAL\Types\Type; +use Doctrine\DBAL\Schema\Visitor\Visitor; +use Doctrine\DBAL\DBALException; + +/** + * Object Representation of a table + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class Table extends AbstractAsset +{ + /** + * @var string + */ + protected $_name = null; + + /** + * @var array + */ + protected $_columns = array(); + + /** + * @var array + */ + protected $_indexes = array(); + + /** + * @var string + */ + protected $_primaryKeyName = false; + + /** + * @var array + */ + protected $_fkConstraints = array(); + + /** + * @var array + */ + protected $_options = array(); + + /** + * @var SchemaConfig + */ + protected $_schemaConfig = null; + + /** + * + * @param string $tableName + * @param array $columns + * @param array $indexes + * @param array $fkConstraints + * @param int $idGeneratorType + * @param array $options + */ + public function __construct($tableName, array $columns=array(), array $indexes=array(), array $fkConstraints=array(), $idGeneratorType = 0, array $options=array()) + { + if (strlen($tableName) == 0) { + throw DBALException::invalidTableName($tableName); + } + + $this->_setName($tableName); + $this->_idGeneratorType = $idGeneratorType; + + foreach ($columns as $column) { + $this->_addColumn($column); + } + + foreach ($indexes as $idx) { + $this->_addIndex($idx); + } + + foreach ($fkConstraints as $constraint) { + $this->_addForeignKeyConstraint($constraint); + } + + $this->_options = $options; + } + + /** + * @param SchemaConfig $schemaConfig + */ + public function setSchemaConfig(SchemaConfig $schemaConfig) + { + $this->_schemaConfig = $schemaConfig; + } + + /** + * @return int + */ + protected function _getMaxIdentifierLength() + { + if ($this->_schemaConfig instanceof SchemaConfig) { + return $this->_schemaConfig->getMaxIdentifierLength(); + } else { + return 63; + } + } + + /** + * Set Primary Key + * + * @param array $columns + * @param string $indexName + * @return Table + */ + public function setPrimaryKey(array $columns, $indexName = false) + { + $primaryKey = $this->_createIndex($columns, $indexName ?: "primary", true, true); + + foreach ($columns as $columnName) { + $column = $this->getColumn($columnName); + $column->setNotnull(true); + } + + return $primaryKey; + } + + /** + * @param array $columnNames + * @param string $indexName + * @return Table + */ + public function addIndex(array $columnNames, $indexName = null) + { + if($indexName == null) { + $indexName = $this->_generateIdentifierName( + array_merge(array($this->getName()), $columnNames), "idx", $this->_getMaxIdentifierLength() + ); + } + + return $this->_createIndex($columnNames, $indexName, false, false); + } + + /** + * Drop an index from this table. + * + * @param string $indexName + * @return void + */ + public function dropPrimaryKey() + { + $this->dropIndex($this->_primaryKeyName); + $this->_primaryKeyName = false; + } + + /** + * Drop an index from this table. + * + * @param string $indexName + * @return void + */ + public function dropIndex($indexName) + { + $indexName = strtolower($indexName); + if ( ! $this->hasIndex($indexName)) { + throw SchemaException::indexDoesNotExist($indexName, $this->_name); + } + unset($this->_indexes[$indexName]); + } + + /** + * + * @param array $columnNames + * @param string $indexName + * @return Table + */ + public function addUniqueIndex(array $columnNames, $indexName = null) + { + if ($indexName === null) { + $indexName = $this->_generateIdentifierName( + array_merge(array($this->getName()), $columnNames), "uniq", $this->_getMaxIdentifierLength() + ); + } + + return $this->_createIndex($columnNames, $indexName, true, false); + } + + /** + * Check if an index begins in the order of the given columns. + * + * @param array $columnsNames + * @return bool + */ + public function columnsAreIndexed(array $columnsNames) + { + foreach ($this->getIndexes() as $index) { + /* @var $index Index */ + if ($index->spansColumns($columnsNames)) { + return true; + } + } + return false; + } + + /** + * + * @param array $columnNames + * @param string $indexName + * @param bool $isUnique + * @param bool $isPrimary + * @return Table + */ + private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary) + { + if (preg_match('(([^a-zA-Z0-9_]+))', $indexName)) { + throw SchemaException::indexNameInvalid($indexName); + } + + foreach ($columnNames as $columnName => $indexColOptions) { + if (is_numeric($columnName) && is_string($indexColOptions)) { + $columnName = $indexColOptions; + } + + if ( ! $this->hasColumn($columnName)) { + throw SchemaException::columnDoesNotExist($columnName, $this->_name); + } + } + $this->_addIndex(new Index($indexName, $columnNames, $isUnique, $isPrimary)); + return $this; + } + + /** + * @param string $columnName + * @param string $columnType + * @param array $options + * @return Column + */ + public function addColumn($columnName, $typeName, array $options=array()) + { + $column = new Column($columnName, Type::getType($typeName), $options); + + $this->_addColumn($column); + return $column; + } + + /** + * Rename Column + * + * @param string $oldColumnName + * @param string $newColumnName + * @return Table + */ + public function renameColumn($oldColumnName, $newColumnName) + { + throw new DBALException("Table#renameColumn() was removed, because it drops and recreates " . + "the column instead. There is no fix available, because a schema diff cannot reliably detect if a " . + "column was renamed or one column was created and another one dropped."); + } + + /** + * Change Column Details + * + * @param string $columnName + * @param array $options + * @return Table + */ + public function changeColumn($columnName, array $options) + { + $column = $this->getColumn($columnName); + $column->setOptions($options); + return $this; + } + + /** + * Drop Column from Table + * + * @param string $columnName + * @return Table + */ + public function dropColumn($columnName) + { + $columnName = strtolower($columnName); + $column = $this->getColumn($columnName); + unset($this->_columns[$columnName]); + return $this; + } + + + /** + * Add a foreign key constraint + * + * Name is inferred from the local columns + * + * @param Table $foreignTable + * @param array $localColumns + * @param array $foreignColumns + * @param array $options + * @param string $constraintName + * @return Table + */ + public function addForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array(), $constraintName = null) + { + $constraintName = $constraintName ?: $this->_generateIdentifierName(array_merge((array)$this->getName(), $localColumnNames), "fk", $this->_getMaxIdentifierLength()); + return $this->addNamedForeignKeyConstraint($constraintName, $foreignTable, $localColumnNames, $foreignColumnNames, $options); + } + + /** + * Add a foreign key constraint + * + * Name is to be generated by the database itsself. + * + * @deprecated Use {@link addForeignKeyConstraint} + * @param Table $foreignTable + * @param array $localColumns + * @param array $foreignColumns + * @param array $options + * @return Table + */ + public function addUnnamedForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array()) + { + return $this->addForeignKeyConstraint($foreignTable, $localColumnNames, $foreignColumnNames, $options); + } + + /** + * Add a foreign key constraint with a given name + * + * @deprecated Use {@link addForeignKeyConstraint} + * @param string $name + * @param Table $foreignTable + * @param array $localColumns + * @param array $foreignColumns + * @param array $options + * @return Table + */ + public function addNamedForeignKeyConstraint($name, $foreignTable, array $localColumnNames, array $foreignColumnNames, array $options=array()) + { + if ($foreignTable instanceof Table) { + $foreignTableName = $foreignTable->getName(); + + foreach ($foreignColumnNames as $columnName) { + if ( ! $foreignTable->hasColumn($columnName)) { + throw SchemaException::columnDoesNotExist($columnName, $foreignTable->getName()); + } + } + } else { + $foreignTableName = $foreignTable; + } + + foreach ($localColumnNames as $columnName) { + if ( ! $this->hasColumn($columnName)) { + throw SchemaException::columnDoesNotExist($columnName, $this->_name); + } + } + + $constraint = new ForeignKeyConstraint( + $localColumnNames, $foreignTableName, $foreignColumnNames, $name, $options + ); + $this->_addForeignKeyConstraint($constraint); + + return $this; + } + + /** + * @param string $name + * @param string $value + * @return Table + */ + public function addOption($name, $value) + { + $this->_options[$name] = $value; + return $this; + } + + /** + * @param Column $column + */ + protected function _addColumn(Column $column) + { + $columnName = $column->getName(); + $columnName = strtolower($columnName); + + if (isset($this->_columns[$columnName])) { + throw SchemaException::columnAlreadyExists($this->getName(), $columnName); + } + + $this->_columns[$columnName] = $column; + } + + /** + * Add index to table + * + * @param Index $indexCandidate + * @return Table + */ + protected function _addIndex(Index $indexCandidate) + { + // check for duplicates + foreach ($this->_indexes as $existingIndex) { + if ($indexCandidate->isFullfilledBy($existingIndex)) { + return $this; + } + } + + $indexName = $indexCandidate->getName(); + $indexName = strtolower($indexName); + + if (isset($this->_indexes[$indexName]) || ($this->_primaryKeyName != false && $indexCandidate->isPrimary())) { + throw SchemaException::indexAlreadyExists($indexName, $this->_name); + } + + // remove overruled indexes + foreach ($this->_indexes as $idxKey => $existingIndex) { + if ($indexCandidate->overrules($existingIndex)) { + unset($this->_indexes[$idxKey]); + } + } + + if ($indexCandidate->isPrimary()) { + $this->_primaryKeyName = $indexName; + } + + $this->_indexes[$indexName] = $indexCandidate; + return $this; + } + + /** + * @param ForeignKeyConstraint $constraint + */ + protected function _addForeignKeyConstraint(ForeignKeyConstraint $constraint) + { + $constraint->setLocalTable($this); + + if(strlen($constraint->getName())) { + $name = $constraint->getName(); + } else { + $name = $this->_generateIdentifierName( + array_merge((array)$this->getName(), $constraint->getLocalColumns()), "fk", $this->_getMaxIdentifierLength() + ); + } + $name = strtolower($name); + + $this->_fkConstraints[$name] = $constraint; + // add an explicit index on the foreign key columns. If there is already an index that fullfils this requirements drop the request. + // In the case of __construct calling this method during hydration from schema-details all the explicitly added indexes + // lead to duplicates. This creates compuation overhead in this case, however no duplicate indexes are ever added (based on columns). + $this->addIndex($constraint->getColumns()); + } + + /** + * Does Table have a foreign key constraint with the given name? + * * + * @param string $constraintName + * @return bool + */ + public function hasForeignKey($constraintName) + { + $constraintName = strtolower($constraintName); + return isset($this->_fkConstraints[$constraintName]); + } + + /** + * @param string $constraintName + * @return ForeignKeyConstraint + */ + public function getForeignKey($constraintName) + { + $constraintName = strtolower($constraintName); + if(!$this->hasForeignKey($constraintName)) { + throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); + } + + return $this->_fkConstraints[$constraintName]; + } + + public function removeForeignKey($constraintName) + { + $constraintName = strtolower($constraintName); + if(!$this->hasForeignKey($constraintName)) { + throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name); + } + + unset($this->_fkConstraints[$constraintName]); + } + + /** + * @return Column[] + */ + public function getColumns() + { + $columns = $this->_columns; + + $pkCols = array(); + $fkCols = array(); + + if ($this->hasPrimaryKey()) { + $pkCols = $this->getPrimaryKey()->getColumns(); + } + foreach ($this->getForeignKeys() as $fk) { + /* @var $fk ForeignKeyConstraint */ + $fkCols = array_merge($fkCols, $fk->getColumns()); + } + $colNames = array_unique(array_merge($pkCols, $fkCols, array_keys($columns))); + + uksort($columns, function($a, $b) use($colNames) { + return (array_search($a, $colNames) >= array_search($b, $colNames)); + }); + return $columns; + } + + + /** + * Does this table have a column with the given name? + * + * @param string $columnName + * @return bool + */ + public function hasColumn($columnName) + { + $columnName = $this->trimQuotes(strtolower($columnName)); + return isset($this->_columns[$columnName]); + } + + /** + * Get a column instance + * + * @param string $columnName + * @return Column + */ + public function getColumn($columnName) + { + $columnName = strtolower($this->trimQuotes($columnName)); + if ( ! $this->hasColumn($columnName)) { + throw SchemaException::columnDoesNotExist($columnName, $this->_name); + } + + return $this->_columns[$columnName]; + } + + /** + * @return Index|null + */ + public function getPrimaryKey() + { + if ( ! $this->hasPrimaryKey()) { + return null; + } + return $this->getIndex($this->_primaryKeyName); + } + + public function getPrimaryKeyColumns() + { + if ( ! $this->hasPrimaryKey()) { + throw new DBALException("Table " . $this->getName() . " has no primary key."); + } + return $this->getPrimaryKey()->getColumns(); + } + + /** + * Check if this table has a primary key. + * + * @return bool + */ + public function hasPrimaryKey() + { + return ($this->_primaryKeyName && $this->hasIndex($this->_primaryKeyName)); + } + + /** + * @param string $indexName + * @return bool + */ + public function hasIndex($indexName) + { + $indexName = strtolower($indexName); + return (isset($this->_indexes[$indexName])); + } + + /** + * @param string $indexName + * @return Index + */ + public function getIndex($indexName) + { + $indexName = strtolower($indexName); + if ( ! $this->hasIndex($indexName)) { + throw SchemaException::indexDoesNotExist($indexName, $this->_name); + } + return $this->_indexes[$indexName]; + } + + /** + * @return array + */ + public function getIndexes() + { + return $this->_indexes; + } + + /** + * Get Constraints + * + * @return array + */ + public function getForeignKeys() + { + return $this->_fkConstraints; + } + + public function hasOption($name) + { + return isset($this->_options[$name]); + } + + public function getOption($name) + { + return $this->_options[$name]; + } + + public function getOptions() + { + return $this->_options; + } + + /** + * @param Visitor $visitor + */ + public function visit(Visitor $visitor) + { + $visitor->acceptTable($this); + + foreach ($this->getColumns() as $column) { + $visitor->acceptColumn($this, $column); + } + + foreach ($this->getIndexes() as $index) { + $visitor->acceptIndex($this, $index); + } + + foreach ($this->getForeignKeys() as $constraint) { + $visitor->acceptForeignKey($this, $constraint); + } + } + + /** + * Clone of a Table triggers a deep clone of all affected assets + */ + public function __clone() + { + foreach ($this->_columns as $k => $column) { + $this->_columns[$k] = clone $column; + } + foreach ($this->_indexes as $k => $index) { + $this->_indexes[$k] = clone $index; + } + foreach ($this->_fkConstraints as $k => $fk) { + $this->_fkConstraints[$k] = clone $fk; + $this->_fkConstraints[$k]->setLocalTable($this); + } + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/TableDiff.php b/src/core/libs/Doctrine/DBAL/Schema/TableDiff.php new file mode 100644 index 0000000..257a3bd --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/TableDiff.php @@ -0,0 +1,136 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema; + +/** + * Table Diff + * + * + * @link www.doctrine-project.org + * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved. + * @license http://ez.no/licenses/new_bsd New BSD License + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class TableDiff +{ + /** + * @var string + */ + public $name = null; + + /** + * @var string + */ + public $newName = false; + + /** + * All added fields + * + * @var array(string=>Column) + */ + public $addedColumns; + + /** + * All changed fields + * + * @var array(string=>Column) + */ + public $changedColumns = array(); + + /** + * All removed fields + * + * @var array(string=>Column) + */ + public $removedColumns = array(); + + /** + * Columns that are only renamed from key to column instance name. + * + * @var array(string=>Column) + */ + public $renamedColumns = array(); + + /** + * All added indexes + * + * @var array(string=>Index) + */ + public $addedIndexes = array(); + + /** + * All changed indexes + * + * @var array(string=>Index) + */ + public $changedIndexes = array(); + + /** + * All removed indexes + * + * @var array(string=>bool) + */ + public $removedIndexes = array(); + + /** + * All added foreign key definitions + * + * @var array + */ + public $addedForeignKeys = array(); + + /** + * All changed foreign keys + * + * @var array + */ + public $changedForeignKeys = array(); + + /** + * All removed foreign keys + * + * @var array + */ + public $removedForeignKeys = array(); + + /** + * Constructs an TableDiff object. + * + * @param array(string=>Column) $addedColumns + * @param array(string=>Column) $changedColumns + * @param array(string=>bool) $removedColumns + * @param array(string=>Index) $addedIndexes + * @param array(string=>Index) $changedIndexes + * @param array(string=>bool) $removedIndexes + */ + public function __construct($tableName, $addedColumns = array(), + $changedColumns = array(), $removedColumns = array(), $addedIndexes = array(), + $changedIndexes = array(), $removedIndexes = array()) + { + $this->name = $tableName; + $this->addedColumns = $addedColumns; + $this->changedColumns = $changedColumns; + $this->removedColumns = $removedColumns; + $this->addedIndexes = $addedIndexes; + $this->changedIndexes = $changedIndexes; + $this->removedIndexes = $removedIndexes; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/View.php b/src/core/libs/Doctrine/DBAL/Schema/View.php new file mode 100644 index 0000000..8283d07 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/View.php @@ -0,0 +1,53 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. +*/ + +namespace Doctrine\DBAL\Schema; + +/** + * Representation of a Database View + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 1.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class View extends AbstractAsset +{ + /** + * @var string + */ + private $_sql; + + public function __construct($name, $sql) + { + $this->_setName($name); + $this->_sql = $sql; + } + + /** + * @return string + */ + public function getSql() + { + return $this->_sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php b/src/core/libs/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php new file mode 100644 index 0000000..51228c1 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Visitor/CreateSchemaSqlCollector.php @@ -0,0 +1,178 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema\Visitor; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Table, + Doctrine\DBAL\Schema\Schema, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\ForeignKeyConstraint, + Doctrine\DBAL\Schema\Constraint, + Doctrine\DBAL\Schema\Sequence, + Doctrine\DBAL\Schema\Index; + +class CreateSchemaSqlCollector implements Visitor +{ + /** + * @var array + */ + private $_createTableQueries = array(); + + /** + * @var array + */ + private $_createSequenceQueries = array(); + + /** + * @var array + */ + private $_createFkConstraintQueries = array(); + + /** + * + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $_platform = null; + + /** + * @param AbstractPlatform $platform + */ + public function __construct(AbstractPlatform $platform) + { + $this->_platform = $platform; + } + + /** + * @param Schema $schema + */ + public function acceptSchema(Schema $schema) + { + + } + + /** + * Generate DDL Statements to create the accepted table with all its dependencies. + * + * @param Table $table + */ + public function acceptTable(Table $table) + { + $namespace = $this->getNamespace($table); + + $this->_createTableQueries[$namespace] = array_merge( + $this->_createTableQueries[$namespace], + $this->_platform->getCreateTableSQL($table) + ); + } + + public function acceptColumn(Table $table, Column $column) + { + + } + + /** + * @param Table $localTable + * @param ForeignKeyConstraint $fkConstraint + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + $namespace = $this->getNamespace($localTable); + + if ($this->_platform->supportsForeignKeyConstraints()) { + $this->_createFkConstraintQueries[$namespace] = array_merge( + $this->_createFkConstraintQueries[$namespace], + (array) $this->_platform->getCreateForeignKeySQL( + $fkConstraint, $localTable + ) + ); + } + } + + /** + * @param Table $table + * @param Index $index + */ + public function acceptIndex(Table $table, Index $index) + { + + } + + /** + * @param Sequence $sequence + */ + public function acceptSequence(Sequence $sequence) + { + $namespace = $this->getNamespace($sequence); + + $this->_createSequenceQueries[$namespace] = array_merge( + $this->_createSequenceQueries[$namespace], + (array)$this->_platform->getCreateSequenceSQL($sequence) + ); + } + + private function getNamespace($asset) + { + $namespace = $asset->getNamespaceName() ?: 'default'; + if ( !isset($this->_createTableQueries[$namespace])) { + $this->_createTableQueries[$namespace] = array(); + $this->_createSequenceQueries[$namespace] = array(); + $this->_createFkConstraintQueries[$namespace] = array(); + } + + return $namespace; + } + + /** + * @return array + */ + public function resetQueries() + { + $this->_createTableQueries = array(); + $this->_createSequenceQueries = array(); + $this->_createFkConstraintQueries = array(); + } + + /** + * Get all queries collected so far. + * + * @return array + */ + public function getQueries() + { + $sql = array(); + foreach (array_keys($this->_createTableQueries) as $namespace) { + if ($this->_platform->supportsSchemas()) { + // TODO: Create Schema here + } + } + foreach ($this->_createTableQueries as $schemaSql) { + $sql = array_merge($sql, $schemaSql); + } + foreach ($this->_createSequenceQueries as $schemaSql) { + $sql = array_merge($sql, $schemaSql); + } + foreach ($this->_createFkConstraintQueries as $schemaSql) { + $sql = array_merge($sql, $schemaSql); + } + return $sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php b/src/core/libs/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php new file mode 100644 index 0000000..3d74cb9 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Visitor/DropSchemaSqlCollector.php @@ -0,0 +1,160 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema\Visitor; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Table, + Doctrine\DBAL\Schema\Schema, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\ForeignKeyConstraint, + Doctrine\DBAL\Schema\Constraint, + Doctrine\DBAL\Schema\Sequence, + Doctrine\DBAL\Schema\SchemaException, + Doctrine\DBAL\Schema\Index; + +/** + * Gather SQL statements that allow to completly drop the current schema. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class DropSchemaSqlCollector implements Visitor +{ + /** + * @var \SplObjectStorage + */ + private $constraints; + + /** + * @var \SplObjectStorage + */ + private $sequences; + + /** + * @var \SplObjectStorage + */ + private $tables; + + /** + * + * @var \Doctrine\DBAL\Platforms\AbstractPlatform + */ + private $platform; + + /** + * @param AbstractPlatform $platform + */ + public function __construct(AbstractPlatform $platform) + { + $this->platform = $platform; + $this->clearQueries(); + } + + /** + * @param Schema $schema + */ + public function acceptSchema(Schema $schema) + { + + } + + /** + * @param Table $table + */ + public function acceptTable(Table $table) + { + $this->tables->attach($table); + } + + /** + * @param Column $column + */ + public function acceptColumn(Table $table, Column $column) + { + + } + + /** + * @param Table $localTable + * @param ForeignKeyConstraint $fkConstraint + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + if (strlen($fkConstraint->getName()) == 0) { + throw SchemaException::namedForeignKeyRequired($localTable, $fkConstraint); + } + + $this->constraints->attach($fkConstraint); + $this->constraints[$fkConstraint] = $localTable; + } + + /** + * @param Table $table + * @param Index $index + */ + public function acceptIndex(Table $table, Index $index) + { + + } + + /** + * @param Sequence $sequence + */ + public function acceptSequence(Sequence $sequence) + { + $this->sequences->attach($sequence); + } + + /** + * @return void + */ + public function clearQueries() + { + $this->constraints = new \SplObjectStorage(); + $this->sequences = new \SplObjectStorage(); + $this->tables = new \SplObjectStorage(); + } + + /** + * @return array + */ + public function getQueries() + { + $sql = array(); + foreach ($this->constraints as $fkConstraint) { + $localTable = $this->constraints[$fkConstraint]; + $sql[] = $this->platform->getDropForeignKeySQL($fkConstraint, $localTable); + } + + foreach ($this->sequences as $sequence) { + $sql[] = $this->platform->getDropSequenceSQL($sequence); + } + + foreach ($this->tables as $table) { + $sql[] = $this->platform->getDropTableSQL($table); + } + + return $sql; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/Visitor/Graphviz.php b/src/core/libs/Doctrine/DBAL/Schema/Visitor/Graphviz.php new file mode 100644 index 0000000..8ae69a2 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Visitor/Graphviz.php @@ -0,0 +1,151 @@ +<?php + +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema\Visitor; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Table, + Doctrine\DBAL\Schema\Schema, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\ForeignKeyConstraint, + Doctrine\DBAL\Schema\Constraint, + Doctrine\DBAL\Schema\Sequence, + Doctrine\DBAL\Schema\Index; + +class Graphviz implements \Doctrine\DBAL\Schema\Visitor\Visitor +{ + private $output = ''; + + public function acceptColumn(Table $table, Column $column) + { + + } + + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + $this->output .= $this->createNodeRelation( + $fkConstraint->getLocalTableName() . ":col" . current($fkConstraint->getLocalColumns()).":se", + $fkConstraint->getForeignTableName() . ":col" . current($fkConstraint->getForeignColumns()).":se", + array( + 'dir' => 'back', + 'arrowtail' => 'dot', + 'arrowhead' => 'normal', + ) + ); + } + + public function acceptIndex(Table $table, Index $index) + { + + } + + public function acceptSchema(Schema $schema) + { + $this->output = 'digraph "' . sha1( mt_rand() ) . '" {' . "\n"; + $this->output .= 'splines = true;' . "\n"; + $this->output .= 'overlap = false;' . "\n"; + $this->output .= 'outputorder=edgesfirst;'."\n"; + $this->output .= 'mindist = 0.6;' . "\n"; + $this->output .= 'sep = .2;' . "\n"; + } + + public function acceptSequence(Sequence $sequence) + { + + } + + public function acceptTable(Table $table) + { + $this->output .= $this->createNode( + $table->getName(), + array( + 'label' => $this->createTableLabel( $table ), + 'shape' => 'plaintext', + ) + ); + } + + private function createTableLabel( Table $table ) + { + // Start the table + $label = '<<TABLE CELLSPACING="0" BORDER="1" ALIGN="LEFT">'; + + // The title + $label .= '<TR><TD BORDER="1" COLSPAN="3" ALIGN="CENTER" BGCOLOR="#fcaf3e"><FONT COLOR="#2e3436" FACE="Helvetica" POINT-SIZE="12">' . $table->getName() . '</FONT></TD></TR>'; + + // The attributes block + foreach( $table->getColumns() as $column ) { + $columnLabel = $column->getName(); + + $label .= '<TR>'; + $label .= '<TD BORDER="0" ALIGN="LEFT" BGCOLOR="#eeeeec">'; + $label .= '<FONT COLOR="#2e3436" FACE="Helvetica" POINT-SIZE="12">' . $columnLabel . '</FONT>'; + $label .= '</TD><TD BORDER="0" ALIGN="LEFT" BGCOLOR="#eeeeec"><FONT COLOR="#2e3436" FACE="Helvetica" POINT-SIZE="10">' . strtolower($column->getType()) . '</FONT></TD>'; + $label .= '<TD BORDER="0" ALIGN="RIGHT" BGCOLOR="#eeeeec" PORT="col'.$column->getName().'">'; + if ($table->hasPrimaryKey() && in_array($column->getName(), $table->getPrimaryKey()->getColumns())) { + $label .= "\xe2\x9c\xb7"; + } + $label .= '</TD></TR>'; + } + + // End the table + $label .= '</TABLE>>'; + + return $label; + } + + private function createNode( $name, $options ) + { + $node = $name . " ["; + foreach( $options as $key => $value ) + { + $node .= $key . '=' . $value . ' '; + } + $node .= "]\n"; + return $node; + } + + private function createNodeRelation( $node1, $node2, $options ) + { + $relation = $node1 . ' -> ' . $node2 . ' ['; + foreach( $options as $key => $value ) + { + $relation .= $key . '=' . $value . ' '; + } + $relation .= "]\n"; + return $relation; + } + + /** + * Write dot language output to a file. This should usually be a *.dot file. + * + * You have to convert the output into a viewable format. For example use "neato" on linux systems + * and execute: + * + * neato -Tpng -o er.png er.dot + * + * @param string $filename + * @return void + */ + public function write($filename) + { + file_put_contents($filename, $this->output . "}"); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php b/src/core/libs/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php new file mode 100644 index 0000000..348b2b7 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Visitor/RemoveNamespacedAssets.php @@ -0,0 +1,113 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema\Visitor; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Table, + Doctrine\DBAL\Schema\Schema, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\ForeignKeyConstraint, + Doctrine\DBAL\Schema\Constraint, + Doctrine\DBAL\Schema\Sequence, + Doctrine\DBAL\Schema\Index; + +/** + * Remove assets from a schema that are not in the default namespace. + * + * Some databases such as MySQL support cross databases joins, but don't + * allow to call DDLs to a database from another connected database. + * Before a schema is serialized into SQL this visitor can cleanup schemas with + * non default namespaces. + * + * This visitor filters all these non-default namespaced tables and sequences + * and removes them from the SChema instance. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.2 + */ +class RemoveNamespacedAssets implements Visitor +{ + /** + * @var Schema + */ + private $schema; + + /** + * @param Schema $schema + */ + public function acceptSchema(Schema $schema) + { + $this->schema = $schema; + } + + /** + * @param Table $table + */ + public function acceptTable(Table $table) + { + if ( ! $table->isInDefaultNamespace($this->schema->getName()) ) { + $this->schema->dropTable($table->getName()); + } + } + /** + * @param Sequence $sequence + */ + public function acceptSequence(Sequence $sequence) + { + if ( ! $sequence->isInDefaultNamespace($this->schema->getName()) ) { + $this->schema->dropSequence($sequence->getName()); + } + } + + /** + * @param Column $column + */ + public function acceptColumn(Table $table, Column $column) + { + } + + /** + * @param Table $localTable + * @param ForeignKeyConstraint $fkConstraint + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + // The table may already be deleted in a previous + // RemoveNamespacedAssets#acceptTable call. Removing Foreign keys that + // point to nowhere. + if ( ! $this->schema->hasTable($fkConstraint->getForeignTableName())) { + $localTable->removeForeignKey($fkConstraint->getName()); + return; + } + + $foreignTable = $this->schema->getTable($fkConstraint->getForeignTableName()); + if ( ! $foreignTable->isInDefaultNamespace($this->schema->getName()) ) { + $localTable->removeForeignKey($fkConstraint->getName()); + } + } + + /** + * @param Table $table + * @param Index $index + */ + public function acceptIndex(Table $table, Index $index) + { + } +} diff --git a/src/core/libs/Doctrine/DBAL/Schema/Visitor/Visitor.php b/src/core/libs/Doctrine/DBAL/Schema/Visitor/Visitor.php new file mode 100644 index 0000000..45eff81 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Schema/Visitor/Visitor.php @@ -0,0 +1,75 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Schema\Visitor; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\Schema\Table, + Doctrine\DBAL\Schema\Schema, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\ForeignKeyConstraint, + Doctrine\DBAL\Schema\Constraint, + Doctrine\DBAL\Schema\Sequence, + Doctrine\DBAL\Schema\Index; + +/** + * Schema Visitor used for Validation or Generation purposes. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +interface Visitor +{ + /** + * @param Schema $schema + */ + public function acceptSchema(Schema $schema); + + /** + * @param Table $table + */ + public function acceptTable(Table $table); + + /** + * @param Column $column + */ + public function acceptColumn(Table $table, Column $column); + + /** + * @param Table $localTable + * @param ForeignKeyConstraint $fkConstraint + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint); + + /** + * @param Table $table + * @param Index $index + */ + public function acceptIndex(Table $table, Index $index); + + /** + * @param Sequence $sequence + */ + public function acceptSequence(Sequence $sequence); +} diff --git a/src/core/libs/Doctrine/DBAL/Sharding/PoolingShardConnection.php b/src/core/libs/Doctrine/DBAL/Sharding/PoolingShardConnection.php new file mode 100644 index 0000000..6453e63 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Sharding/PoolingShardConnection.php @@ -0,0 +1,201 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Sharding; + +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Event\ConnectionEventArgs; +use Doctrine\DBAL\Events; +use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Configuration; + +use Doctrine\Common\EventManager; + +use Doctrine\DBAL\Sharding\ShardChoser\ShardChoser; + +/** + * Sharding implementation that pools many different connections + * internally and serves data from the currently active connection. + * + * The internals of this class are: + * + * - All sharding clients are specified and given a shard-id during + * configuration. + * - By default, the global shard is selected. If no global shard is configured + * an exception is thrown on access. + * - Selecting a shard by distribution value delegates the mapping + * "distributionValue" => "client" to the ShardChooser interface. + * - An exception is thrown if trying to switch shards during an open + * transaction. + * + * Instantiation through the DriverManager looks like: + * + * @example + * + * $conn = DriverManager::getConnection(array( + * 'wrapperClass' => 'Doctrine\DBAL\Sharding\PoolingShardConnection', + * 'driver' => 'pdo_mysql', + * 'global' => array('user' => '', 'password' => '', 'host' => '', 'dbname' => ''), + * 'shards' => array( + * array('id' => 1, 'user' => 'slave1', 'password', 'host' => '', 'dbname' => ''), + * array('id' => 2, 'user' => 'slave2', 'password', 'host' => '', 'dbname' => ''), + * ), + * 'shardChoser' => 'Doctrine\DBAL\Sharding\ShardChoser\MultiTenantShardChoser', + * )); + * $shardManager = $conn->getShardManager(); + * $shardManager->selectGlobal(); + * $shardManager->selectShard($value); + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class PoolingShardConnection extends Connection +{ + /** + * @var array + */ + private $activeConnections; + + /** + * @var int + */ + private $activeShardId; + + /** + * @var array + */ + private $connections; + + /** + * @var ShardManager + */ + private $shardManager; + + public function __construct(array $params, Driver $driver, Configuration $config = null, EventManager $eventManager = null) + { + if ( !isset($params['global']) || !isset($params['shards'])) { + throw new \InvalidArgumentException("Connection Parameters require 'global' and 'shards' configurations."); + } + + if ( !isset($params['shardChoser'])) { + throw new \InvalidArgumentException("Missing Shard Choser configuration 'shardChoser'"); + } + + if (is_string($params['shardChoser'])) { + $params['shardChoser'] = new $params['shardChoser']; + } + + if ( ! ($params['shardChoser'] instanceof ShardChoser)) { + throw new \InvalidArgumentException("The 'shardChoser' configuration is not a valid instance of Doctrine\DBAL\Sharding\ShardChoser\ShardChoser"); + } + + $this->connections[0] = array_merge($params, $params['global']); + + foreach ($params['shards'] as $shard) { + if ( ! isset($shard['id'])) { + throw new \InvalidArgumentException("Missing 'id' for one configured shard. Please specificy a unique shard-id."); + } + + if ( !is_numeric($shard['id']) || $shard['id'] < 1) { + throw new \InvalidArgumentException("Shard Id has to be a non-negative number."); + } + + if (isset($this->connections[$shard['id']])) { + throw new \InvalidArgumentException("Shard " . $shard['id'] . " is duplicated in the configuration."); + } + + $this->connections[$shard['id']] = array_merge($params, $shard); + } + + parent::__construct($params, $driver, $config, $eventManager); + } + + /** + * Connect to a given shard + * + * @param mixed $shardId + * @return bool + */ + public function connect($shardId = null) + { + if ($shardId === null && $this->_conn) { + return false; + } + + if ($shardId !== null && $shardId === $this->activeShardId) { + return false; + } + + if ($this->getTransactionNestingLevel() > 0) { + throw new ShardingException("Cannot switch shard when transaction is active."); + } + + $this->activeShardId = (int)$shardId; + + if (isset($this->activeConnections[$this->activeShardId])) { + $this->_conn = $this->activeConnections[$this->activeShardId]; + return false; + } + + $this->_conn = $this->activeConnections[$this->activeShardId] = $this->connectTo($this->activeShardId); + + if ($this->_eventManager->hasListeners(Events::postConnect)) { + $eventArgs = new Event\ConnectionEventArgs($this); + $this->_eventManager->dispatchEvent(Events::postConnect, $eventArgs); + } + + return true; + } + + + /** + * Connect to a specific connection + * + * @param string $shardId + * @return Driver + */ + protected function connectTo($shardId) + { + $params = $this->getParams(); + + $driverOptions = isset($params['driverOptions']) ? $params['driverOptions'] : array(); + + $connectionParams = $this->connections[$shardId]; + + $user = isset($connectionParams['user']) ? $connectionParams['user'] : null; + $password = isset($connectionParams['password']) ? $connectionParams['password'] : null; + + return $this->_driver->connect($connectionParams, $user, $password, $driverOptions); + } + + public function isConnected($shardId = null) + { + if ($shardId === null) { + return $this->_conn !== null; + } + + return isset($this->activeConnections[$shardId]); + } + + public function close() + { + $this->_conn = null; + $this->activeConnections = null; + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Sharding/PoolingShardManager.php b/src/core/libs/Doctrine/DBAL/Sharding/PoolingShardManager.php new file mode 100644 index 0000000..6f6c5d2 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Sharding/PoolingShardManager.php @@ -0,0 +1,98 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Sharding; + +use Doctrine\DBAL\Sharding\ShardChoser\ShardChoser; + +/** + * Shard Manager for the Connection Pooling Shard Strategy + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class PoolingShardManager implements ShardManager +{ + private $conn; + private $choser; + private $currentDistributionValue; + + public function __construct(PoolingShardConnection $conn) + { + $params = $conn->getParams(); + $this->conn = $conn; + $this->choser = $params['shardChoser']; + } + + public function selectGlobal() + { + $this->conn->connect(0); + $this->currentDistributionValue = null; + } + + public function selectShard($distributionValue) + { + $shardId = $this->choser->pickShard($distributionValue, $this->conn); + $this->conn->connect($shardId); + $this->currentDistributionValue = $distributionValue; + } + + public function getCurrentDistributionValue() + { + return $this->currentDistributionValue; + } + + public function getShards() + { + $params = $this->conn->getParams(); + $shards = array(); + + foreach ($params['shards'] as $shard) { + $shards[] = array('id' => $shard['id']); + } + + return $shards; + } + + public function queryAll($sql, array $params, array $types) + { + $shards = $this->getShards(); + if (!$shards) { + throw new \RuntimeException("No shards found."); + } + + $result = array(); + $oldDistribution = $this->getCurrentDistributionValue(); + + foreach ($shards as $shard) { + $this->selectShard($shard['id']); + foreach ($this->conn->fetchAll($sql, $params, $types) as $row) { + $result[] = $row; + } + } + + if ($oldDistribution === null) { + $this->selectGlobal(); + } else { + $this->selectShard($oldDistribution); + } + + return $result; + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php b/src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php new file mode 100644 index 0000000..4001379 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureFederationsSynchronizer.php @@ -0,0 +1,296 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Sharding\SQLAzure; + +use Doctrine\DBAL\Schema\Schema; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Types\Type; + +use Doctrine\DBAL\Schema\Synchronizer\AbstractSchemaSynchronizer; +use Doctrine\DBAL\Sharding\SingleDatabaseSynchronizer; + +/** + * SQL Azure Schema Synchronizer + * + * Will iterate over all shards when performing schema operations. This is done + * by partitioning the passed schema into subschemas for the federation and the + * global database and then applying the operations step by step using the + * {@see \Doctrine\DBAL\Sharding\SingleDatabaseSynchronizer}. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class SQLAzureFederationsSynchronizer extends AbstractSchemaSynchronizer +{ + const FEDERATION_TABLE_FEDERATED = 'azure.federated'; + const FEDERATION_DISTRIBUTION_NAME = 'azure.federatedOnDistributionName'; + + + /** + * @var SQLAzureShardManager + */ + private $shardManager; + + /** + * @var SchemaSynchronizer + */ + private $synchronizer; + + public function __construct(Connection $conn, SQLAzureShardManager $shardManager, SchemaSynchronizer $sync = null) + { + parent::__construct($conn); + $this->shardManager = $shardManager; + $this->synchronizer = $sync ?: new SingleDatabaseSynchronizer($conn); + } + + /** + * Get the SQL statements that can be executed to create the schema. + * + * @param Schema $createSchema + * @return array + */ + public function getCreateSchema(Schema $createSchema) + { + $sql = array(); + + list($global, $federation) = $this->partitionSchema($createSchema); + + $globalSql = $this->synchronizer->getCreateSchema($global); + if ($globalSql) { + $sql[] = "-- Create Root Federation\n" . + "USE FEDERATION ROOT WITH RESET;"; + $sql = array_merge($sql, $globalSql); + } + + $federationSql = $this->synchronizer->getCreateSchema($federation); + + if ($federationSql) { + $defaultValue = $this->getFederationTypeDefaultValue(); + + $sql[] = $this->getCreateFederationStatement(); + $sql[] = "USE FEDERATION " . $this->shardManager->getFederationName() . " (" . $this->shardManager->getDistributionKey() . " = " . $defaultValue . ") WITH RESET, FILTERING = OFF;"; + $sql = array_merge($sql, $federationSql); + } + + return $sql; + } + + /** + * Get the SQL Statements to update given schema with the underlying db. + * + * @param Schema $toSchema + * @param bool $noDrops + * @return array + */ + public function getUpdateSchema(Schema $toSchema, $noDrops = false) + { + return $this->work($toSchema, function($synchronizer, $schema) use ($noDrops) { + return $synchronizer->getUpdateSchema($schema, $noDrops); + }); + } + + /** + * Get the SQL Statements to drop the given schema from underlying db. + * + * @param Schema $dropSchema + * @return array + */ + public function getDropSchema(Schema $dropSchema) + { + return $this->work($dropSchema, function($synchronizer, $schema) { + return $synchronizer->getDropSchema($schema); + }); + } + + /** + * Create the Schema + * + * @param Schema $createSchema + * @return void + */ + public function createSchema(Schema $createSchema) + { + $this->processSql($this->getCreateSchema($createSchema)); + } + + /** + * Update the Schema to new schema version. + * + * @param Schema $toSchema + * @return void + */ + public function updateSchema(Schema $toSchema, $noDrops = false) + { + $this->processSql($this->getUpdateSchema($toSchema, $noDrops)); + } + + /** + * Drop the given database schema from the underlying db. + * + * @param Schema $dropSchema + * @return void + */ + public function dropSchema(Schema $dropSchema) + { + $this->processSqlSafely($this->getDropSchema($dropSchema)); + } + + /** + * Get the SQL statements to drop all schema assets from underlying db. + * + * @return array + */ + public function getDropAllSchema() + { + $this->shardManager->selectGlobal(); + $globalSql = $this->synchronizer->getDropAllSchema(); + + if ($globalSql) { + $sql[] = "-- Work on Root Federation\nUSE FEDERATION ROOT WITH RESET;"; + $sql = array_merge($sql, $globalSql); + } + + $shards = $this->shardManager->getShards(); + foreach ($shards as $shard) { + $this->shardManager->selectShard($shard['rangeLow']); + + $federationSql = $this->synchronizer->getDropAllSchema(); + if ($federationSql) { + $sql[] = "-- Work on Federation ID " . $shard['id'] . "\n" . + "USE FEDERATION " . $this->shardManager->getFederationName() . " (" . $this->shardManager->getDistributionKey() . " = " . $shard['rangeLow'].") WITH RESET, FILTERING = OFF;"; + $sql = array_merge($sql, $federationSql); + } + } + + $sql[] = "USE FEDERATION ROOT WITH RESET;"; + $sql[] = "DROP FEDERATION " . $this->shardManager->getFederationName(); + + return $sql; + } + + /** + * Drop all assets from the underyling db. + * + * @return void + */ + public function dropAllSchema() + { + $this->processSqlSafely($this->getDropAllSchema()); + } + + private function partitionSchema(Schema $schema) + { + return array( + $this->extractSchemaFederation($schema, false), + $this->extractSchemaFederation($schema, true), + ); + } + + private function extractSchemaFederation(Schema $schema, $isFederation) + { + $partionedSchema = clone $schema; + + foreach ($partionedSchema->getTables() as $table) { + if ($isFederation) { + $table->addOption(self::FEDERATION_DISTRIBUTION_NAME, $this->shardManager->getDistributionKey()); + } + + if ( $table->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) { + $partionedSchema->dropTable($table->getName()); + } else { + foreach ($table->getForeignKeys() as $fk) { + $foreignTable = $schema->getTable($fk->getForeignTableName()); + if ($foreignTable->hasOption(self::FEDERATION_TABLE_FEDERATED) !== $isFederation) { + throw new \RuntimeException("Cannot have foreign key between global/federation."); + } + } + } + } + + return $partionedSchema; + } + + /** + * Work on the Global/Federation based on currently existing shards and + * perform the given operation on the underyling schema synchronizer given + * the different partioned schema instances. + * + * @param Schema $schema + * @param Closure $operation + * @return array + */ + private function work(Schema $schema, \Closure $operation) + { + list($global, $federation) = $this->partitionSchema($schema); + $sql = array(); + + $this->shardManager->selectGlobal(); + $globalSql = $operation($this->synchronizer, $global); + + if ($globalSql) { + $sql[] = "-- Work on Root Federation\nUSE FEDERATION ROOT WITH RESET;"; + $sql = array_merge($sql, $globalSql); + } + + $shards = $this->shardManager->getShards(); + + foreach ($shards as $shard) { + $this->shardManager->selectShard($shard['rangeLow']); + + $federationSql = $operation($this->synchronizer, $federation); + if ($federationSql) { + $sql[] = "-- Work on Federation ID " . $shard['id'] . "\n" . + "USE FEDERATION " . $this->shardManager->getFederationName() . " (" . $this->shardManager->getDistributionKey() . " = " . $shard['rangeLow'].") WITH RESET, FILTERING = OFF;"; + $sql = array_merge($sql, $federationSql); + } + } + + return $sql; + } + + private function getFederationTypeDefaultValue() + { + $federationType = Type::getType($this->shardManager->getDistributionType()); + + switch ($federationType->getName()) { + case Type::GUID: + $defaultValue = '00000000-0000-0000-0000-000000000000'; + break; + case Type::INTEGER: + case Type::SMALLINT: + case Type::BIGINT: + $defaultValue = '0'; + break; + default: + $defaultValue = ''; + break; + } + return $defaultValue; + } + + private function getCreateFederationStatement() + { + $federationType = Type::getType($this->shardManager->getDistributionType()); + $federationTypeSql = $federationType->getSqlDeclaration(array(), $this->conn->getDatabasePlatform()); + + return "--Create Federation\n" . + "CREATE FEDERATION " . $this->shardManager->getFederationName() . " (" . $this->shardManager->getDistributionKey() . " " . $federationTypeSql ." RANGE)"; + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php b/src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php new file mode 100644 index 0000000..80ca3d9 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/SQLAzureShardManager.php @@ -0,0 +1,238 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Sharding\SQLAzure; + +use Doctrine\DBAL\Sharding\ShardManager; +use Doctrine\DBAL\Sharding\ShardingException; +use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Types\Type; + +/** + * Sharding using the SQL Azure Federations support. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class SQLAzureShardManager implements ShardManager +{ + /** + * @var string + */ + private $federationName; + + /** + * @var bool + */ + private $filteringEnabled; + + /** + * @var string + */ + private $distributionKey; + + /** + * @var string + */ + private $distributionType; + + /** + * @var Connection + */ + private $conn; + + /** + * @var string + */ + private $currentDistributionValue; + + /** + * @param Connection $conn + */ + public function __construct(Connection $conn) + { + $this->conn = $conn; + $params = $conn->getParams(); + + if ( ! isset($params['sharding']['federationName'])) { + throw ShardingException::missingDefaultFederationName(); + } + + if ( ! isset($params['sharding']['distributionKey'])) { + throw ShardingException::missingDefaultDistributionKey(); + } + + if ( ! isset($params['sharding']['distributionType'])) { + throw ShardingException::missingDistributionType(); + } + + $this->federationName = $params['sharding']['federationName']; + $this->distributionKey = $params['sharding']['distributionKey']; + $this->distributionType = $params['sharding']['distributionType']; + $this->filteringEnabled = (isset($params['sharding']['filteringEnabled'])) ? (bool)$params['sharding']['filteringEnabled'] : false; + } + + /** + * Get name of the federation + * + * @return string + */ + public function getFederationName() + { + return $this->federationName; + } + + /** + * Get the distribution key + * + * @return string + */ + public function getDistributionKey() + { + return $this->distributionKey; + } + + /** + * Get the Doctrine Type name used for the distribution + * + * @return string + */ + public function getDistributionType() + { + return $this->distributionType; + } + + /** + * Enabled/Disable filtering on the fly. + * + * @param bool $flag + * @return void + */ + public function setFilteringEnabled($flag) + { + $this->filteringEnabled = (bool)$flag; + } + + /** + * {@inheritDoc} + */ + public function selectGlobal() + { + if ($this->conn->isTransactionActive()) { + throw ShardingException::activeTransaction(); + } + + $sql = "USE FEDERATION ROOT WITH RESET"; + $this->conn->exec($sql); + $this->currentDistributionValue = null; + } + + /** + * {@inheritDoc} + */ + public function selectShard($distributionValue) + { + if ($this->conn->isTransactionActive()) { + throw ShardingException::activeTransaction(); + } + + if ($distributionValue === null || is_bool($distributionValue) || !is_scalar($distributionValue)) { + throw ShardingException::noShardDistributionValue(); + } + + $platform = $this->conn->getDatabasePlatform(); + $sql = sprintf( + "USE FEDERATION %s (%s = %s) WITH RESET, FILTERING = %s;", + $platform->quoteIdentifier($this->federationName), + $platform->quoteIdentifier($this->distributionKey), + $this->conn->quote($distributionValue), + ($this->filteringEnabled ? 'ON' : 'OFF') + ); + + $this->conn->exec($sql); + $this->currentDistributionValue = $distributionValue; + } + + /** + * {@inheritDoc} + */ + public function getCurrentDistributionValue() + { + return $this->currentDistributionValue; + } + + /** + * {@inheritDoc} + */ + public function getShards() + { + $sql = "SELECT member_id as id, + distribution_name as distribution_key, + CAST(range_low AS CHAR) AS rangeLow, + CAST(range_high AS CHAR) AS rangeHigh + FROM sys.federation_member_distributions d + INNER JOIN sys.federations f ON f.federation_id = d.federation_id + WHERE f.name = " . $this->conn->quote($this->federationName); + return $this->conn->fetchAll($sql); + } + + /** + * {@inheritDoc} + */ + public function queryAll($sql, array $params = array(), array $types = array()) + { + $shards = $this->getShards(); + if (!$shards) { + throw new \RuntimeException("No shards found for " . $this->federationName); + } + + $result = array(); + $oldDistribution = $this->getCurrentDistributionValue(); + + foreach ($shards as $shard) { + $this->selectShard($shard['rangeLow']); + foreach ($this->conn->fetchAll($sql, $params, $types) as $row) { + $result[] = $row; + } + } + + if ($oldDistribution === null) { + $this->selectGlobal(); + } else { + $this->selectShard($oldDistribution); + } + + return $result; + } + + /** + * Split Federation at a given distribution value. + * + * @param mixed $splitDistributionValue + */ + public function splitFederation($splitDistributionValue) + { + $type = Type::getType($this->distributionType); + + $sql = "ALTER FEDERATION " . $this->getFederationName() . " " . + "SPLIT AT (" . $this->getDistributionKey() . " = " . + $this->conn->quote($splitDistributionValue, $type->getBindingType()) . ")"; + $this->conn->exec($sql); + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php b/src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php new file mode 100644 index 0000000..2b2b457 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Sharding/SQLAzure/Schema/MultiTenantVisitor.php @@ -0,0 +1,161 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Sharding\SQLAzure\Schema; + +use Doctrine\DBAL\Schema\Visitor\Visitor, + Doctrine\DBAL\Schema\Table, + Doctrine\DBAL\Schema\Schema, + Doctrine\DBAL\Schema\Column, + Doctrine\DBAL\Schema\ForeignKeyConstraint, + Doctrine\DBAL\Schema\Constraint, + Doctrine\DBAL\Schema\Sequence, + Doctrine\DBAL\Schema\Index; + +/** + * Converts a single tenant schema into a multi-tenant schema for SQL Azure + * Federations under the following assumptions: + * + * - Every table is part of the multi-tenant application, only explicitly + * excluded tables are non-federated. The behavior of the tables being in + * global or federated database is undefined. It depends on you selecting a + * federation before DDL statements or not. + * - Every Primary key of a federated table is extended by another column + * 'tenant_id' with a default value of the SQLAzure function + * `federation_filtering_value('tenant_id')`. + * - You always have to work with `filtering=On` when using federations with this + * multi-tenant approach. + * - Primary keys are either using globally unique ids (GUID, Table Generator) + * or you explicitly add the tenent_id in every UPDATE or DELETE statement + * (otherwise they will affect the same-id rows from other tenents as well). + * SQLAzure throws errors when you try to create IDENTIY columns on federated + * tables. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class MultiTenantVisitor implements Visitor +{ + /** + * @var array + */ + private $excludedTables = array(); + + /** + * @var string + */ + private $tenantColumnName; + + /** + * @var string + */ + private $tenantColumnType = 'integer'; + + /** + * Name of the federation distribution, defaulting to the tenantColumnName + * if not specified. + * + * @var string + */ + private $distributionName; + + public function __construct(array $excludedTables = array(), $tenantColumnName = 'tenant_id', $distributionName = null) + { + $this->excludedTables = $excludedTables; + $this->tenantColumnName = $tenantColumnName; + $this->distributionName = $distributionName ?: $tenantColumnName; + } + + /** + * @param Table $table + */ + public function acceptTable(Table $table) + { + if (in_array($table->getName(), $this->excludedTables)) { + return; + } + + $table->addColumn($this->tenantColumnName, $this->tenantColumnType, array( + 'default' => "federation_filtering_value('". $this->distributionName ."')", + )); + + $clusteredIndex = $this->getClusteredIndex($table); + + $indexColumns = $clusteredIndex->getColumns(); + $indexColumns[] = $this->tenantColumnName; + + if ($clusteredIndex->isPrimary()) { + $table->dropPrimaryKey(); + $table->setPrimaryKey($indexColumns); + } else { + $table->dropIndex($clusteredIndex->getName()); + $table->addIndex($indexColumns, $clusteredIndex->getName()); + $table->getIndex($clusteredIndex->getName())->addFlag('clustered'); + } + } + + private function getClusteredIndex($table) + { + foreach ($table->getIndexes() as $index) { + if ($index->isPrimary() && ! $index->hasFlag('nonclustered')) { + return $index; + } else if ($index->hasFlag('clustered')) { + return $index; + } + } + throw new \RuntimeException("No clustered index found on table " . $table->getName()); + } + + /** + * @param Schema $schema + */ + public function acceptSchema(Schema $schema) + { + } + + /** + * @param Column $column + */ + public function acceptColumn(Table $table, Column $column) + { + } + + /** + * @param Table $localTable + * @param ForeignKeyConstraint $fkConstraint + */ + public function acceptForeignKey(Table $localTable, ForeignKeyConstraint $fkConstraint) + { + } + + /** + * @param Table $table + * @param Index $index + */ + public function acceptIndex(Table $table, Index $index) + { + } + + /** + * @param Sequence $sequence + */ + public function acceptSequence(Sequence $sequence) + { + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php b/src/core/libs/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php new file mode 100644 index 0000000..c6cdabf --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Sharding/ShardChoser/MultiTenantShardChoser.php @@ -0,0 +1,37 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Sharding\ShardChoser; + +use Doctrine\DBAL\Sharding\PoolingShardConnection; + +/** + * The MultiTenant Shard choser assumes that the distribution value directly + * maps to the shard id. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +class MultiTenantShardChoser implements ShardChoser +{ + public function pickShard($distributionValue, PoolingShardConnection $conn) + { + return $distributionValue; + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php b/src/core/libs/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php new file mode 100644 index 0000000..2aa9f74 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Sharding/ShardChoser/ShardChoser.php @@ -0,0 +1,41 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Sharding\ShardChoser; + +use Doctrine\DBAL\Sharding\PoolingShardConnection; + +/** + * Given a distribution value this shard-choser strategy will pick the shard to + * connect to for retrieving rows with the distribution value. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +interface ShardChoser +{ + /** + * Pick a shard for the given distribution value + * + * @param string $distributionValue + * @param PoolingShardConnection $conn + * @return int + */ + function pickShard($distributionValue, PoolingShardConnection $conn); +} + diff --git a/src/core/libs/Doctrine/DBAL/Sharding/ShardManager.php b/src/core/libs/Doctrine/DBAL/Sharding/ShardManager.php new file mode 100644 index 0000000..aa67992 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Sharding/ShardManager.php @@ -0,0 +1,95 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Sharding; + +use Doctrine\DBAL\Connection; + +/** + * Sharding Manager gives access to APIs to implementing sharding on top of + * Doctrine\DBAL\Connection instances. + * + * For simplicity and developer ease-of-use (and understanding) the sharding + * API only covers single shard queries, no fan-out support. It is primarily + * suited for multi-tenant applications. + * + * The assumption about sharding here + * is that a distribution value can be found that gives access to all the + * necessary data for all use-cases. Switching between shards should be done with + * caution, especially if lazy loading is implemented. Any query is always + * executed against the last shard that was selected. If a query is created for + * a shard Y but then a shard X is selected when its actually excecuted you + * will hit the wrong shard. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + */ +interface ShardManager +{ + /** + * Select global database with global data. + * + * This is the default database that is connected when no shard is + * selected. + * + * @return void + */ + function selectGlobal(); + + /** + * SELECT queries after this statement will be issued against the selected + * shard. + * + * @throws ShardingException If no value is passed as shard identifier. + * @param mixed $distributionValue + * @param array $options + * @return void + */ + function selectShard($distributionValue); + + /** + * Get the distribution value currently used for sharding. + * + * @return string + */ + function getCurrentDistributionValue(); + + /** + * Get information about the amount of shards and other details. + * + * Format is implementation specific, each shard is one element and has a + * 'name' attribute at least. + * + * @return array + */ + function getShards(); + + /** + * Query all shards in undefined order and return the results appended to + * each other. Restore the previous distribution value after execution. + * + * Using {@link Connection::fetchAll} to retrieve rows internally. + * + * @param string $sql + * @param array $params + * @param array $types + * @return array + */ + function queryAll($sql, array $params, array $types); +} + diff --git a/src/core/libs/Doctrine/DBAL/Sharding/ShardingException.php b/src/core/libs/Doctrine/DBAL/Sharding/ShardingException.php new file mode 100644 index 0000000..06dd169 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Sharding/ShardingException.php @@ -0,0 +1,61 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Sharding; + +use Doctrine\DBAL\DBALException; + +/** + * Sharding related Exceptions + * + * @since 2.3 + */ +class ShardingException extends DBALException +{ + static public function notImplemented() + { + return new self("This functionality is not implemented with this sharding provider.", 1331557937); + } + + static public function missingDefaultFederationName() + { + return new self("SQLAzure requires a federation name to be set during sharding configuration.", 1332141280); + } + + static public function missingDefaultDistributionKey() + { + return new self("SQLAzure requires a distribution key to be set during sharding configuration.", 1332141329); + } + + static public function activeTransaction() + { + return new self("Cannot switch shard during an active transaction.", 1332141766); + } + + static public function noShardDistributionValue() + { + return new self("You have to specify a string or integer as shard distribution value.", 1332142103); + } + + static public function missingDistributionType() + { + return new self("You have to specify a sharding distribution type such as 'integer', 'string', 'guid'."); + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Statement.php b/src/core/libs/Doctrine/DBAL/Statement.php new file mode 100644 index 0000000..1bf9d74 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Statement.php @@ -0,0 +1,264 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL; + +use PDO, + Doctrine\DBAL\Types\Type, + Doctrine\DBAL\Driver\Statement as DriverStatement; + +/** + * A thin wrapper around a Doctrine\DBAL\Driver\Statement that adds support + * for logging, DBAL mapping types, etc. + * + * @author Roman Borschel <roman@code-factory.org> + * @since 2.0 + */ +class Statement implements \IteratorAggregate, DriverStatement +{ + /** + * @var string The SQL statement. + */ + protected $sql; + /** + * @var array The bound parameters. + */ + protected $params = array(); + /** + * @var array The parameter types + */ + protected $types = array(); + /** + * @var \Doctrine\DBAL\Driver\Statement The underlying driver statement. + */ + protected $stmt; + /** + * @var \Doctrine\DBAL\Platforms\AbstractPlatform The underlying database platform. + */ + protected $platform; + /** + * @var \Doctrine\DBAL\Connection The connection this statement is bound to and executed on. + */ + protected $conn; + + /** + * Creates a new <tt>Statement</tt> for the given SQL and <tt>Connection</tt>. + * + * @param string $sql The SQL of the statement. + * @param \Doctrine\DBAL\Connection The connection on which the statement should be executed. + */ + public function __construct($sql, Connection $conn) + { + $this->sql = $sql; + $this->stmt = $conn->getWrappedConnection()->prepare($sql); + $this->conn = $conn; + $this->platform = $conn->getDatabasePlatform(); + } + + /** + * Binds a parameter value to the statement. + * + * The value can optionally be bound with a PDO binding type or a DBAL mapping type. + * If bound with a DBAL mapping type, the binding type is derived from the mapping + * type and the value undergoes the conversion routines of the mapping type before + * being bound. + * + * @param string $name The name or position of the parameter. + * @param mixed $value The value of the parameter. + * @param mixed $type Either a PDO binding type or a DBAL mapping type name or instance. + * @return boolean TRUE on success, FALSE on failure. + */ + public function bindValue($name, $value, $type = null) + { + $this->params[$name] = $value; + $this->types[$name] = $type; + if ($type !== null) { + if (is_string($type)) { + $type = Type::getType($type); + } + if ($type instanceof Type) { + $value = $type->convertToDatabaseValue($value, $this->platform); + $bindingType = $type->getBindingType(); + } else { + $bindingType = $type; // PDO::PARAM_* constants + } + return $this->stmt->bindValue($name, $value, $bindingType); + } else { + return $this->stmt->bindValue($name, $value); + } + } + + /** + * Binds a parameter to a value by reference. + * + * Binding a parameter by reference does not support DBAL mapping types. + * + * @param string $name The name or position of the parameter. + * @param mixed $var The reference to the variable to bind + * @param integer $type The PDO binding type. + * @return boolean TRUE on success, FALSE on failure. + */ + public function bindParam($name, &$var, $type = PDO::PARAM_STR, $length = null) + { + return $this->stmt->bindParam($name, $var, $type, $length ); + } + + /** + * Executes the statement with the currently bound parameters. + * + * @param array $params + * @return boolean TRUE on success, FALSE on failure. + */ + public function execute($params = null) + { + $logger = $this->conn->getConfiguration()->getSQLLogger(); + if ($logger) { + $logger->startQuery($this->sql, $this->params, $this->types); + } + + try { + $stmt = $this->stmt->execute($params); + } catch (\Exception $ex) { + throw DBALException::driverExceptionDuringQuery($ex, $this->sql, $this->conn->resolveParams($this->params, $this->types)); + } + + if ($logger) { + $logger->stopQuery(); + } + $this->params = array(); + $this->types = array(); + return $stmt; + } + + /** + * Closes the cursor, freeing the database resources used by this statement. + * + * @return boolean TRUE on success, FALSE on failure. + */ + public function closeCursor() + { + return $this->stmt->closeCursor(); + } + + /** + * Returns the number of columns in the result set. + * + * @return integer + */ + public function columnCount() + { + return $this->stmt->columnCount(); + } + + /** + * Fetches the SQLSTATE associated with the last operation on the statement. + * + * @return string + */ + public function errorCode() + { + return $this->stmt->errorCode(); + } + + /** + * Fetches extended error information associated with the last operation on the statement. + * + * @return array + */ + public function errorInfo() + { + return $this->stmt->errorInfo(); + } + + public function setFetchMode($fetchMode, $arg2 = null, $arg3 = null) + { + if ($arg2 === null) { + return $this->stmt->setFetchMode($fetchMode); + } else if ($arg3 === null) { + return $this->stmt->setFetchMode($fetchMode, $arg2); + } + + return $this->stmt->setFetchMode($fetchMode, $arg2, $arg3); + } + + public function getIterator() + { + return $this->stmt; + } + + /** + * Fetches the next row from a result set. + * + * @param integer $fetchMode + * @return mixed The return value of this function on success depends on the fetch type. + * In all cases, FALSE is returned on failure. + */ + public function fetch($fetchMode = null) + { + return $this->stmt->fetch($fetchMode); + } + + /** + * Returns an array containing all of the result set rows. + * + * @param integer $fetchMode + * @param mixed $fetchArgument + * @return array An array containing all of the remaining rows in the result set. + */ + public function fetchAll($fetchMode = null, $fetchArgument = 0) + { + if ($fetchArgument !== 0) { + return $this->stmt->fetchAll($fetchMode, $fetchArgument); + } + return $this->stmt->fetchAll($fetchMode); + } + + /** + * Returns a single column from the next row of a result set. + * + * @param integer $columnIndex + * @return mixed A single column from the next row of a result set or FALSE if there are no more rows. + */ + public function fetchColumn($columnIndex = 0) + { + return $this->stmt->fetchColumn($columnIndex); + } + + /** + * Returns the number of rows affected by the last execution of this statement. + * + * @return integer The number of affected rows. + */ + public function rowCount() + { + return $this->stmt->rowCount(); + } + + /** + * Gets the wrapped driver statement. + * + * @return \Doctrine\DBAL\Driver\Statement + */ + public function getWrappedStatement() + { + return $this->stmt; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php b/src/core/libs/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php new file mode 100644 index 0000000..6b2b8c2 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Tools/Console/Command/ImportCommand.php @@ -0,0 +1,124 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Tools\Console\Command; + +use Symfony\Component\Console\Input\InputArgument, + Symfony\Component\Console; + +/** + * Task for executing arbitrary SQL that can come from a file or directly from + * the command line. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class ImportCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('dbal:import') + ->setDescription('Import SQL file(s) directly to Database.') + ->setDefinition(array( + new InputArgument( + 'file', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'File path(s) of SQL to be executed.' + ) + )) + ->setHelp(<<<EOT +Import SQL file(s) directly to Database. +EOT + ); + } + + /** + * @see Console\Command\Command + */ + protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output) + { + $conn = $this->getHelper('db')->getConnection(); + + if (($fileNames = $input->getArgument('file')) !== null) { + foreach ((array) $fileNames as $fileName) { + $fileName = realpath($fileName); + + if ( ! file_exists($fileName)) { + throw new \InvalidArgumentException( + sprintf("SQL file '<info>%s</info>' does not exist.", $fileName) + ); + } else if ( ! is_readable($fileName)) { + throw new \InvalidArgumentException( + sprintf("SQL file '<info>%s</info>' does not have read permissions.", $fileName) + ); + } + + $output->write(sprintf("Processing file '<info>%s</info>'... ", $fileName)); + $sql = file_get_contents($fileName); + + if ($conn instanceof \Doctrine\DBAL\Driver\PDOConnection) { + // PDO Drivers + try { + $lines = 0; + + $stmt = $conn->prepare($sql); + $stmt->execute(); + + do { + // Required due to "MySQL has gone away!" issue + $stmt->fetch(); + $stmt->closeCursor(); + + $lines++; + } while ($stmt->nextRowset()); + + $output->write(sprintf('%d statements executed!', $lines) . PHP_EOL); + } catch (\PDOException $e) { + $output->write('error!' . PHP_EOL); + + throw new \RuntimeException($e->getMessage(), $e->getCode(), $e); + } + } else { + // Non-PDO Drivers (ie. OCI8 driver) + $stmt = $conn->prepare($sql); + $rs = $stmt->execute(); + + if ($rs) { + $output->writeln('OK!' . PHP_EOL); + } else { + $error = $stmt->errorInfo(); + + $output->write('error!' . PHP_EOL); + + throw new \RuntimeException($error[2], $error[0]); + } + + $stmt->closeCursor(); + } + } + } + } +} diff --git a/src/core/libs/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php b/src/core/libs/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php new file mode 100644 index 0000000..7b1bb1c --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Tools/Console/Command/ReservedWordsCommand.php @@ -0,0 +1,133 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Tools\Console\Command; + +use Symfony\Component\Console\Input\InputArgument, + Symfony\Component\Console\Input\InputOption, + Symfony\Component\Console\Command\Command, + Symfony\Component\Console\Input\InputInterface, + Symfony\Component\Console\Output\OutputInterface; +use Doctrine\DBAL\Platforms\Keywords\ReservedKeywordsValidator; + +class ReservedWordsCommand extends Command +{ + private $keywordListClasses = array( + 'mysql' => 'Doctrine\DBAL\Platforms\Keywords\MySQLKeywords', + 'mssql' => 'Doctrine\DBAL\Platforms\Keywords\MsSQLKeywords', + 'sqlite' => 'Doctrine\DBAL\Platforms\Keywords\SQLiteKeywords', + 'pgsql' => 'Doctrine\DBAL\Platforms\Keywords\PostgreSQLKeywords', + 'oracle' => 'Doctrine\DBAL\Platforms\Keywords\OracleKeywords', + 'db2' => 'Doctrine\DBAL\Platforms\Keywords\DB2Keywords', + ); + + /** + * If you want to add or replace a keywords list use this command + * + * @param string $name + * @param string $class + */ + public function setKeywordListClass($name, $class) + { + $this->keywordListClasses[$name] = $class; + } + + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('dbal:reserved-words') + ->setDescription('Checks if the current database contains identifiers that are reserved.') + ->setDefinition(array( + new InputOption( + 'list', 'l', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Keyword-List name.' + ) + )) + ->setHelp(<<<EOT +Checks if the current database contains tables and columns +with names that are identifiers in this dialect or in other SQL dialects. + +By default SQLite, MySQL, PostgreSQL, MsSQL and Oracle +keywords are checked: + + <info>%command.full_name%</info> + +If you want to check against specific dialects you can +pass them to the command: + + <info>%command.full_name% mysql pgsql</info> + +The following keyword lists are currently shipped with Doctrine: + + * mysql + * pgsql + * sqlite + * oracle + * mssql + * db2 (Not checked by default) +EOT + ); + } + + /** + * @see Console\Command\Command + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + /* @var $conn \Doctrine\DBAL\Connection */ + $conn = $this->getHelper('db')->getConnection(); + + $keywordLists = (array)$input->getOption('list'); + if ( ! $keywordLists) { + $keywordLists = array('mysql', 'pgsql', 'sqlite', 'oracle', 'mssql'); + } + + $keywords = array(); + foreach ($keywordLists as $keywordList) { + if (!isset($this->keywordListClasses[$keywordList])) { + throw new \InvalidArgumentException( + "There exists no keyword list with name '" . $keywordList . "'. ". + "Known lists: " . implode(", ", array_keys($this->keywordListClasses)) + ); + } + $class = $this->keywordListClasses[$keywordList]; + $keywords[] = new $class; + } + + $output->write('Checking keyword violations for <comment>' . implode(", ", $keywordLists) . "</comment>...", true); + + /* @var $schema \Doctrine\DBAL\Schema\Schema */ + $schema = $conn->getSchemaManager()->createSchema(); + $visitor = new ReservedKeywordsValidator($keywords); + $schema->visit($visitor); + + $violations = $visitor->getViolations(); + if (count($violations) == 0) { + $output->write("No reserved keywords violations have been found!", true); + } else { + $output->write('There are <error>' . count($violations) . '</error> reserved keyword violations in your database schema:', true); + foreach ($violations as $violation) { + $output->write(' - ' . $violation, true); + } + } + } +} diff --git a/src/core/libs/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php b/src/core/libs/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php new file mode 100644 index 0000000..b1af34b --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Tools/Console/Command/RunSqlCommand.php @@ -0,0 +1,87 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Tools\Console\Command; + +use Symfony\Component\Console\Input\InputArgument, + Symfony\Component\Console\Input\InputOption, + Symfony\Component\Console; + +/** + * Task for executing arbitrary SQL that can come from a file or directly from + * the command line. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class RunSqlCommand extends Console\Command\Command +{ + /** + * @see Console\Command\Command + */ + protected function configure() + { + $this + ->setName('dbal:run-sql') + ->setDescription('Executes arbitrary SQL directly from the command line.') + ->setDefinition(array( + new InputArgument('sql', InputArgument::REQUIRED, 'The SQL statement to execute.'), + new InputOption('depth', null, InputOption::VALUE_REQUIRED, 'Dumping depth of result set.', 7) + )) + ->setHelp(<<<EOT +Executes arbitrary SQL directly from the command line. +EOT + ); + } + + /** + * @see Console\Command\Command + */ + protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output) + { + $conn = $this->getHelper('db')->getConnection(); + + if (($sql = $input->getArgument('sql')) === null) { + throw new \RuntimeException("Argument 'SQL' is required in order to execute this command correctly."); + } + + $depth = $input->getOption('depth'); + + if ( ! is_numeric($depth)) { + throw new \LogicException("Option 'depth' must contains an integer value"); + } + + if (stripos($sql, 'select') === 0) { + $resultSet = $conn->fetchAll($sql); + } else { + $resultSet = $conn->executeUpdate($sql); + } + + ob_start(); + \Doctrine\Common\Util\Debug::dump($resultSet, (int) $depth); + $message = ob_get_clean(); + + $output->write($message); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.php b/src/core/libs/Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.php new file mode 100644 index 0000000..877cb64 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Tools/Console/Helper/ConnectionHelper.php @@ -0,0 +1,74 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Tools\Console\Helper; + +use Symfony\Component\Console\Helper\Helper, + Doctrine\DBAL\Connection; + +/** + * Doctrine CLI Connection Helper. + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class ConnectionHelper extends Helper +{ + /** + * Doctrine Database Connection + * @var Connection + */ + protected $_connection; + + /** + * Constructor + * + * @param Connection $connection Doctrine Database Connection + */ + public function __construct(Connection $connection) + { + $this->_connection = $connection; + } + + /** + * Retrieves Doctrine Database Connection + * + * @return Connection + */ + public function getConnection() + { + return $this->_connection; + } + + /** + * @see Helper + */ + public function getName() + { + return 'connection'; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/ArrayType.php b/src/core/libs/Doctrine/DBAL/Types/ArrayType.php new file mode 100644 index 0000000..447f9ee --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/ArrayType.php @@ -0,0 +1,64 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps a PHP array to a clob SQL type. + * + * @since 2.0 + */ +class ArrayType extends Type +{ + public function getSQLDeclaration(array $fieldDeclaration, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) + { + return $platform->getClobTypeDeclarationSQL($fieldDeclaration); + } + + public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) + { + return serialize($value); + } + + public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) + { + if ($value === null) { + return null; + } + + $value = (is_resource($value)) ? stream_get_contents($value) : $value; + $val = unserialize($value); + if ($val === false && $value != 'b:0;') { + throw ConversionException::conversionFailed($value, $this->getName()); + } + return $val; + } + + public function getName() + { + return Type::TARRAY; + } + + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/BigIntType.php b/src/core/libs/Doctrine/DBAL/Types/BigIntType.php new file mode 100644 index 0000000..7648bef --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/BigIntType.php @@ -0,0 +1,56 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps a database BIGINT to a PHP string. + * + * @author robo + * @since 2.0 + */ +class BigIntType extends Type +{ + public function getName() + { + return Type::BIGINT; + } + + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getBigIntTypeDeclarationSQL($fieldDeclaration); + } + + public function getBindingType() + { + return \PDO::PARAM_STR; + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return (null === $value) ? null : (string) $value; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/BlobType.php b/src/core/libs/Doctrine/DBAL/Types/BlobType.php new file mode 100644 index 0000000..32c93a1 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/BlobType.php @@ -0,0 +1,67 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps an SQL BLOB to a PHP resource stream + * + * @since 2.2 + */ +class BlobType extends Type +{ + /** @override */ + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getBlobTypeDeclarationSQL($fieldDeclaration); + } + + /** + * Converts a value from its database representation to its PHP representation + * of this type. + * + * @param mixed $value The value to convert. + * @param AbstractPlatform $platform The currently used database platform. + * @return mixed The PHP representation of the value. + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if (null === $value) { + return null; + } + if (is_string($value)) { + $value = fopen('data://text/plain;base64,' . base64_encode($value), 'r'); + } else if ( ! is_resource($value)) { + throw ConversionException::conversionFailed($value, self::BLOB); + } + return $value; + } + + public function getName() + { + return Type::BLOB; + } + + public function getBindingType() + { + return \PDO::PARAM_LOB; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/BooleanType.php b/src/core/libs/Doctrine/DBAL/Types/BooleanType.php new file mode 100644 index 0000000..f1a968d --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/BooleanType.php @@ -0,0 +1,57 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps an SQL boolean to a PHP boolean. + * + * @since 2.0 + */ +class BooleanType extends Type +{ + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getBooleanTypeDeclarationSQL($fieldDeclaration); + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + return $platform->convertBooleans($value); + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return (null === $value) ? null : (bool) $value; + } + + public function getName() + { + return Type::BOOLEAN; + } + + public function getBindingType() + { + return \PDO::PARAM_BOOL; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/ConversionException.php b/src/core/libs/Doctrine/DBAL/Types/ConversionException.php new file mode 100644 index 0000000..3a19d1a --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/ConversionException.php @@ -0,0 +1,65 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +/** + * Conversion Exception is thrown when the database to PHP conversion fails + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +namespace Doctrine\DBAL\Types; + +class ConversionException extends \Doctrine\DBAL\DBALException +{ + /** + * Thrown when a Database to Doctrine Type Conversion fails. + * + * @param string $value + * @param string $toType + * @return ConversionException + */ + static public function conversionFailed($value, $toType) + { + $value = (strlen($value) > 32) ? substr($value, 0, 20) . "..." : $value; + return new self('Could not convert database value "' . $value . '" to Doctrine Type ' . $toType); + } + + /** + * Thrown when a Database to Doctrine Type Conversion fails and we can make a statement + * about the expected format. + * + * @param string $value + * @param string $toType + * @return ConversionException + */ + static public function conversionFailedFormat($value, $toType, $expectedFormat) + { + $value = (strlen($value) > 32) ? substr($value, 0, 20) . "..." : $value; + return new self( + 'Could not convert database value "' . $value . '" to Doctrine Type ' . + $toType . '. Expected format: ' . $expectedFormat + ); + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/DateTimeType.php b/src/core/libs/Doctrine/DBAL/Types/DateTimeType.php new file mode 100644 index 0000000..06de729 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/DateTimeType.php @@ -0,0 +1,59 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps an SQL DATETIME/TIMESTAMP to a PHP DateTime object. + * + * @since 2.0 + */ +class DateTimeType extends Type +{ + public function getName() + { + return Type::DATETIME; + } + + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getDateTimeTypeDeclarationSQL($fieldDeclaration); + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + return ($value !== null) + ? $value->format($platform->getDateTimeFormatString()) : null; + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof \DateTime) { + return $value; + } + + $val = \DateTime::createFromFormat($platform->getDateTimeFormatString(), $value); + if ( ! $val) { + throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeFormatString()); + } + return $val; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/DateTimeTzType.php b/src/core/libs/Doctrine/DBAL/Types/DateTimeTzType.php new file mode 100644 index 0000000..e0a786c --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/DateTimeTzType.php @@ -0,0 +1,79 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * DateTime type saving additional timezone information. + * + * Caution: Databases are not necessarily experts at storing timezone related + * data of dates. First, of all the supported vendors only PostgreSQL and Oracle + * support storing Timezone data. But those two don't save the actual timezone + * attached to a DateTime instance (for example "Europe/Berlin" or "America/Montreal") + * but the current offset of them related to UTC. That means depending on daylight saving times + * or not you may get different offsets. + * + * This datatype makes only sense to use, if your application works with an offset, not + * with an actual timezone that uses transitions. Otherwise your DateTime instance + * attached with a timezone such as Europe/Berlin gets saved into the database with + * the offset and re-created from persistence with only the offset, not the original timezone + * attached. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 1.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class DateTimeTzType extends Type +{ + public function getName() + { + return Type::DATETIMETZ; + } + + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getDateTimeTzTypeDeclarationSQL($fieldDeclaration); + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + return ($value !== null) + ? $value->format($platform->getDateTimeTzFormatString()) : null; + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof \DateTime) { + return $value; + } + + $val = \DateTime::createFromFormat($platform->getDateTimeTzFormatString(), $value); + if ( ! $val) { + throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateTimeTzFormatString()); + } + return $val; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/DateType.php b/src/core/libs/Doctrine/DBAL/Types/DateType.php new file mode 100644 index 0000000..a3f7018 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/DateType.php @@ -0,0 +1,59 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps an SQL DATE to a PHP Date object. + * + * @since 2.0 + */ +class DateType extends Type +{ + public function getName() + { + return Type::DATE; + } + + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getDateTypeDeclarationSQL($fieldDeclaration); + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + return ($value !== null) + ? $value->format($platform->getDateFormatString()) : null; + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof \DateTime) { + return $value; + } + + $val = \DateTime::createFromFormat('!'.$platform->getDateFormatString(), $value); + if ( ! $val) { + throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getDateFormatString()); + } + return $val; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/DecimalType.php b/src/core/libs/Doctrine/DBAL/Types/DecimalType.php new file mode 100644 index 0000000..fd61b53 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/DecimalType.php @@ -0,0 +1,45 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps an SQL DECIMAL to a PHP double. + * + * @since 2.0 + */ +class DecimalType extends Type +{ + public function getName() + { + return Type::DECIMAL; + } + + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getDecimalTypeDeclarationSQL($fieldDeclaration); + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return (null === $value) ? null : $value; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/FloatType.php b/src/core/libs/Doctrine/DBAL/Types/FloatType.php new file mode 100644 index 0000000..d02ca0c --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/FloatType.php @@ -0,0 +1,54 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +class FloatType extends Type +{ + public function getName() + { + return Type::FLOAT; + } + + /** + * @param array $fieldDeclaration + * @param AbstractPlatform $platform + * @return string + */ + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getFloatDeclarationSQL($fieldDeclaration); + } + + /** + * Converts a value from its database representation to its PHP representation + * of this type. + * + * @param mixed $value The value to convert. + * @param AbstractPlatform $platform The currently used database platform. + * @return mixed The PHP representation of the value. + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return (null === $value) ? null : (double) $value; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/GuidType.php b/src/core/libs/Doctrine/DBAL/Types/GuidType.php new file mode 100644 index 0000000..a8251dd --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/GuidType.php @@ -0,0 +1,42 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Represents a GUID/UUID datatype (both are actually synomys) in the database. + * + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.3 + */ +class GuidType extends StringType +{ + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getGuidTypeDeclarationSQL($fieldDeclaration); + } + + public function getName() + { + return Type::GUID; + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Types/IntegerType.php b/src/core/libs/Doctrine/DBAL/Types/IntegerType.php new file mode 100644 index 0000000..bac9b3f --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/IntegerType.php @@ -0,0 +1,53 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps an SQL INT to a PHP integer. + * + * @author Roman Borschel <roman@code-factory.org> + * @since 2.0 + */ +class IntegerType extends Type +{ + public function getName() + { + return Type::INTEGER; + } + + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getIntegerTypeDeclarationSQL($fieldDeclaration); + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return (null === $value) ? null : (int) $value; + } + + public function getBindingType() + { + return \PDO::PARAM_INT; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/JsonArrayType.php b/src/core/libs/Doctrine/DBAL/Types/JsonArrayType.php new file mode 100644 index 0000000..ca00557 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/JsonArrayType.php @@ -0,0 +1,66 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Array Type which can be used to generate json arrays. + * + * @since 2.3 + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class JsonArrayType extends Type +{ + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getClobTypeDeclarationSQL($fieldDeclaration); + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if (null === $value) { + return null; + } + + return json_encode($value); + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return array(); + } + + $value = (is_resource($value)) ? stream_get_contents($value) : $value; + + return json_decode($value, true); + } + + public function getName() + { + return Type::JSON_ARRAY; + } + + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/ObjectType.php b/src/core/libs/Doctrine/DBAL/Types/ObjectType.php new file mode 100644 index 0000000..9510d29 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/ObjectType.php @@ -0,0 +1,64 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps a PHP object to a clob SQL type. + * + * @since 2.0 + */ +class ObjectType extends Type +{ + public function getSQLDeclaration(array $fieldDeclaration, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) + { + return $platform->getClobTypeDeclarationSQL($fieldDeclaration); + } + + public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) + { + return serialize($value); + } + + public function convertToPHPValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform) + { + if ($value === null) { + return null; + } + + $value = (is_resource($value)) ? stream_get_contents($value) : $value; + $val = unserialize($value); + if ($val === false && $value !== 'b:0;') { + throw ConversionException::conversionFailed($value, $this->getName()); + } + return $val; + } + + public function getName() + { + return Type::OBJECT; + } + + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/SimpleArrayType.php b/src/core/libs/Doctrine/DBAL/Types/SimpleArrayType.php new file mode 100644 index 0000000..719d7f1 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/SimpleArrayType.php @@ -0,0 +1,69 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Array Type which can be used for simple values. + * + * Only use this type if you are sure that your values cannot contain a ",". + * + * @since 2.3 + * @author Johannes M. Schmitt <schmittjoh@gmail.com> + */ +class SimpleArrayType extends Type +{ + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getClobTypeDeclarationSQL($fieldDeclaration); + } + + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + if (!$value) { + return null; + } + + return implode(',', $value); + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null) { + return array(); + } + + $value = (is_resource($value)) ? stream_get_contents($value) : $value; + + return explode(',', $value); + } + + public function getName() + { + return Type::SIMPLE_ARRAY; + } + + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return true; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/SmallIntType.php b/src/core/libs/Doctrine/DBAL/Types/SmallIntType.php new file mode 100644 index 0000000..97e9aaf --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/SmallIntType.php @@ -0,0 +1,52 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps a database SMALLINT to a PHP integer. + * + * @author robo + */ +class SmallIntType extends Type +{ + public function getName() + { + return Type::SMALLINT; + } + + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getSmallIntTypeDeclarationSQL($fieldDeclaration); + } + + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return (null === $value) ? null : (int) $value; + } + + public function getBindingType() + { + return \PDO::PARAM_INT; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/StringType.php b/src/core/libs/Doctrine/DBAL/Types/StringType.php new file mode 100644 index 0000000..48c76d6 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/StringType.php @@ -0,0 +1,50 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps an SQL VARCHAR to a PHP string. + * + * @since 2.0 + */ +class StringType extends Type +{ + /** @override */ + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration); + } + + /** @override */ + public function getDefaultLength(AbstractPlatform $platform) + { + return $platform->getVarcharDefaultLength(); + } + + /** @override */ + public function getName() + { + return Type::STRING; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/TextType.php b/src/core/libs/Doctrine/DBAL/Types/TextType.php new file mode 100644 index 0000000..98ecbe6 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/TextType.php @@ -0,0 +1,56 @@ +<?php +/* + * $Id$ + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps an SQL CLOB to a PHP string. + * + * @since 2.0 + */ +class TextType extends Type +{ + /** @override */ + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getClobTypeDeclarationSQL($fieldDeclaration); + } + + /** + * Converts a value from its database representation to its PHP representation + * of this type. + * + * @param mixed $value The value to convert. + * @param AbstractPlatform $platform The currently used database platform. + * @return mixed The PHP representation of the value. + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return (is_resource($value)) ? stream_get_contents($value) : $value; + } + + public function getName() + { + return Type::TEXT; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/TimeType.php b/src/core/libs/Doctrine/DBAL/Types/TimeType.php new file mode 100644 index 0000000..8653750 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/TimeType.php @@ -0,0 +1,68 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Type that maps an SQL TIME to a PHP DateTime object. + * + * @since 2.0 + */ +class TimeType extends Type +{ + public function getName() + { + return Type::TIME; + } + + /** + * {@inheritdoc} + */ + public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) + { + return $platform->getTimeTypeDeclarationSQL($fieldDeclaration); + } + + /** + * {@inheritdoc} + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + return ($value !== null) + ? $value->format($platform->getTimeFormatString()) : null; + } + + /** + * {@inheritdoc} + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof \DateTime) { + return $value; + } + + $val = \DateTime::createFromFormat($platform->getTimeFormatString(), $value); + if ( ! $val) { + throw ConversionException::conversionFailedFormat($value, $this->getName(), $platform->getTimeFormatString()); + } + return $val; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Types/Type.php b/src/core/libs/Doctrine/DBAL/Types/Type.php new file mode 100644 index 0000000..29947be --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/Type.php @@ -0,0 +1,306 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform, + Doctrine\DBAL\DBALException; + +/** + * The base class for so-called Doctrine mapping types. + * + * A Type object is obtained by calling the static {@link getType()} method. + * + * @author Roman Borschel <roman@code-factory.org> + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @since 2.0 + */ +abstract class Type +{ + const TARRAY = 'array'; + const SIMPLE_ARRAY = 'simple_array'; + const JSON_ARRAY = 'json_array'; + const BIGINT = 'bigint'; + const BOOLEAN = 'boolean'; + const DATETIME = 'datetime'; + const DATETIMETZ = 'datetimetz'; + const DATE = 'date'; + const TIME = 'time'; + const DECIMAL = 'decimal'; + const INTEGER = 'integer'; + const OBJECT = 'object'; + const SMALLINT = 'smallint'; + const STRING = 'string'; + const TEXT = 'text'; + const BLOB = 'blob'; + const FLOAT = 'float'; + const GUID = 'guid'; + + /** Map of already instantiated type objects. One instance per type (flyweight). */ + private static $_typeObjects = array(); + + /** The map of supported doctrine mapping types. */ + private static $_typesMap = array( + self::TARRAY => 'Doctrine\DBAL\Types\ArrayType', + self::SIMPLE_ARRAY => 'Doctrine\DBAL\Types\SimpleArrayType', + self::JSON_ARRAY => 'Doctrine\DBAL\Types\JsonArrayType', + self::OBJECT => 'Doctrine\DBAL\Types\ObjectType', + self::BOOLEAN => 'Doctrine\DBAL\Types\BooleanType', + self::INTEGER => 'Doctrine\DBAL\Types\IntegerType', + self::SMALLINT => 'Doctrine\DBAL\Types\SmallIntType', + self::BIGINT => 'Doctrine\DBAL\Types\BigIntType', + self::STRING => 'Doctrine\DBAL\Types\StringType', + self::TEXT => 'Doctrine\DBAL\Types\TextType', + self::DATETIME => 'Doctrine\DBAL\Types\DateTimeType', + self::DATETIMETZ => 'Doctrine\DBAL\Types\DateTimeTzType', + self::DATE => 'Doctrine\DBAL\Types\DateType', + self::TIME => 'Doctrine\DBAL\Types\TimeType', + self::DECIMAL => 'Doctrine\DBAL\Types\DecimalType', + self::FLOAT => 'Doctrine\DBAL\Types\FloatType', + self::BLOB => 'Doctrine\DBAL\Types\BlobType', + self::GUID => 'Doctrine\DBAL\Types\GuidType', + ); + + /* Prevent instantiation and force use of the factory method. */ + final private function __construct() {} + + /** + * Converts a value from its PHP representation to its database representation + * of this type. + * + * @param mixed $value The value to convert. + * @param AbstractPlatform $platform The currently used database platform. + * @return mixed The database representation of the value. + */ + public function convertToDatabaseValue($value, AbstractPlatform $platform) + { + return $value; + } + + /** + * Converts a value from its database representation to its PHP representation + * of this type. + * + * @param mixed $value The value to convert. + * @param AbstractPlatform $platform The currently used database platform. + * @return mixed The PHP representation of the value. + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + return $value; + } + + /** + * Gets the default length of this type. + * + * @todo Needed? + */ + public function getDefaultLength(AbstractPlatform $platform) + { + return null; + } + + /** + * Gets the SQL declaration snippet for a field of this type. + * + * @param array $fieldDeclaration The field declaration. + * @param AbstractPlatform $platform The currently used database platform. + */ + abstract public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform); + + /** + * Gets the name of this type. + * + * @return string + * @todo Needed? + */ + abstract public function getName(); + + /** + * Factory method to create type instances. + * Type instances are implemented as flyweights. + * + * @static + * @throws DBALException + * @param string $name The name of the type (as returned by getName()). + * @return \Doctrine\DBAL\Types\Type + */ + public static function getType($name) + { + if ( ! isset(self::$_typeObjects[$name])) { + if ( ! isset(self::$_typesMap[$name])) { + throw DBALException::unknownColumnType($name); + } + self::$_typeObjects[$name] = new self::$_typesMap[$name](); + } + + return self::$_typeObjects[$name]; + } + + /** + * Adds a custom type to the type map. + * + * @static + * @param string $name Name of the type. This should correspond to what getName() returns. + * @param string $className The class name of the custom type. + * @throws DBALException + */ + public static function addType($name, $className) + { + if (isset(self::$_typesMap[$name])) { + throw DBALException::typeExists($name); + } + + self::$_typesMap[$name] = $className; + } + + /** + * Checks if exists support for a type. + * + * @static + * @param string $name Name of the type + * @return boolean TRUE if type is supported; FALSE otherwise + */ + public static function hasType($name) + { + return isset(self::$_typesMap[$name]); + } + + /** + * Overrides an already defined type to use a different implementation. + * + * @static + * @param string $name + * @param string $className + * @throws DBALException + */ + public static function overrideType($name, $className) + { + if ( ! isset(self::$_typesMap[$name])) { + throw DBALException::typeNotFound($name); + } + + if (isset(self::$_typeObjects[$name])) { + unset(self::$_typeObjects[$name]); + } + + self::$_typesMap[$name] = $className; + } + + /** + * Gets the (preferred) binding type for values of this type that + * can be used when binding parameters to prepared statements. + * + * This method should return one of the PDO::PARAM_* constants, that is, one of: + * + * PDO::PARAM_BOOL + * PDO::PARAM_NULL + * PDO::PARAM_INT + * PDO::PARAM_STR + * PDO::PARAM_LOB + * + * @return integer + */ + public function getBindingType() + { + return \PDO::PARAM_STR; + } + + /** + * Get the types array map which holds all registered types and the corresponding + * type class + * + * @return array $typesMap + */ + public static function getTypesMap() + { + return self::$_typesMap; + } + + public function __toString() + { + $e = explode('\\', get_class($this)); + return str_replace('Type', '', end($e)); + } + + /** + * Does working with this column require SQL conversion functions? + * + * This is a metadata function that is required for example in the ORM. + * Usage of {@link convertToDatabaseValueSQL} and + * {@link convertToPHPValueSQL} works for any type and mostly + * does nothing. This method can additionally be used for optimization purposes. + * + * @return bool + */ + public function canRequireSQLConversion() + { + return false; + } + + /** + * Modifies the SQL expression (identifier, parameter) to convert to a database value. + * + * @param string $sqlExpr + * @param AbstractPlatform $platform + * @return string + */ + public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform) + { + return $sqlExpr; + } + + /** + * Modifies the SQL expression (identifier, parameter) to convert to a PHP value. + * + * @param string $sqlExpr + * @param AbstractPlatform $platform + * @return string + */ + public function convertToPHPValueSQL($sqlExpr, $platform) + { + return $sqlExpr; + } + + /** + * Get an array of database types that map to this Doctrine type. + * + * @param AbstractPlatform $platform + * @return array + */ + public function getMappedDatabaseTypes(AbstractPlatform $platform) + { + return array(); + } + + /** + * If this Doctrine Type maps to an already mapped database type, + * reverse schema engineering can't take them apart. You need to mark + * one of those types as commented, which will have Doctrine use an SQL + * comment to typehint the actual Doctrine Type. + * + * @param AbstractPlatform $platform + * @return bool + */ + public function requiresSQLCommentHint(AbstractPlatform $platform) + { + return false; + } +} + diff --git a/src/core/libs/Doctrine/DBAL/Types/VarDateTimeType.php b/src/core/libs/Doctrine/DBAL/Types/VarDateTimeType.php new file mode 100644 index 0000000..7085822 --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Types/VarDateTimeType.php @@ -0,0 +1,60 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + + +namespace Doctrine\DBAL\Types; + +use Doctrine\DBAL\Platforms\AbstractPlatform; + +/** + * Variable DateTime Type using date_create() instead of DateTime::createFromFormat() + * + * This type has performance implications as it runs twice as long as the regular + * {@see DateTimeType}, however in certain PostgreSQL configurations with + * TIMESTAMP(n) columns where n > 0 it is necessary to use this type. + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.0 + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class VarDateTimeType extends DateTimeType +{ + /** + * @throws ConversionException + * @param string $value + * @param AbstractPlatform $platform + * @return \DateTime + */ + public function convertToPHPValue($value, AbstractPlatform $platform) + { + if ($value === null || $value instanceof \DateTime) { + return $value; + } + + $val = date_create($value); + if ( ! $val) { + throw ConversionException::conversionFailed($value, $this->getName()); + } + return $val; + } +} diff --git a/src/core/libs/Doctrine/DBAL/Version.php b/src/core/libs/Doctrine/DBAL/Version.php new file mode 100644 index 0000000..4dc3f1c --- /dev/null +++ b/src/core/libs/Doctrine/DBAL/Version.php @@ -0,0 +1,55 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. For more information, see + * <http://www.doctrine-project.org>. + */ + +namespace Doctrine\DBAL; + +/** + * Class to store and retrieve the version of Doctrine + * + * + * @link www.doctrine-project.org + * @since 2.0 + * @version $Revision$ + * @author Benjamin Eberlei <kontakt@beberlei.de> + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + */ +class Version +{ + /** + * Current Doctrine Version + */ + const VERSION = '2.3.0'; + + /** + * Compares a Doctrine version with the current one. + * + * @param string $version Doctrine version to compare. + * @return int Returns -1 if older, 0 if it is the same, 1 if version + * passed as argument is newer. + */ + public static function compare($version) + { + $currentVersion = str_replace(' ', '', strtolower(self::VERSION)); + $version = str_replace(' ', '', $version); + + return version_compare($version, $currentVersion); + } +} diff --git a/src/core/libs/PHPTAL5/COPYING b/src/core/libs/PHPTAL5/COPYING new file mode 100644 index 0000000..d3a38e5 --- /dev/null +++ b/src/core/libs/PHPTAL5/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/core/libs/PHPTAL5/PHPTAL.php b/src/core/libs/PHPTAL5/PHPTAL.php new file mode 100644 index 0000000..1e3a846 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL.php @@ -0,0 +1,1226 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +define('PHPTAL_VERSION', '1_3_0'); + +PHPTAL::autoloadRegister(); + +/** + * PHPTAL template entry point. + * + * <code> + * <?php + * require_once 'PHPTAL.php'; + * try { + * $tpl = new PHPTAL('mytemplate.html'); + * $tpl->title = 'Welcome here'; + * $tpl->result = range(1, 100); + * ... + * echo $tpl->execute(); + * } + * catch (Exception $e) { + * echo $e; + * } + * ?> + * </code> + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @link http://phptal.org/ + */ +class PHPTAL +{ + //{{{ + /** + * constants for output mode + * @see setOutputMode() + */ + const XHTML = 11; + const XML = 22; + const HTML5 = 55; + + /** + * @see getPreFilters() + */ + protected $prefilters = array(); + + /** + * Prefilters have been redesigned. Old property is no longer used. + * + * @deprecated + */ + private $_prefilter = 'REMOVED: DO NOT USE'; + protected $_postfilter = null; + + /** + * list of template source repositories given to file source resolver + */ + protected $_repositories = array(); + + /** + * template path (path that has been set, not necessarily loaded) + */ + protected $_path = null; + + /** + * template source resolvers (classes that search for templates by name) + */ + protected $resolvers = array(); + + /** + * template source (only set when not working with file) + */ + protected $_source = null; + + /** + * destination of PHP intermediate file + */ + protected $_codeFile = null; + + /** + * php function generated for the template + */ + protected $_functionName = null; + + /** + * set to true when template is ready for execution + */ + protected $_prepared = false; + + /** + * associative array of phptal:id => PHPTAL_Trigger + */ + protected $_triggers = array(); + + /** + * i18n translator + */ + protected $_translator = null; + + /** + * global execution context + */ + protected $_globalContext = null; + + /** + * current execution context + */ + protected $_context = null; + + /** + * list of on-error caught exceptions + */ + protected $_errors = array(); + + /** + * encoding used throughout + */ + protected $_encoding = 'UTF-8'; + + /** + * type of syntax used in generated templates + */ + protected $_outputMode = PHPTAL::XHTML; + /** + * should all comments be stripped + */ + + // configuration properties + + /** + * don't use code cache + */ + protected $_forceReparse = null; + + /** + * directory where code cache is + */ + private $_phpCodeDestination; + private $_phpCodeExtension = 'php'; + + /** + * number of days + */ + private $_cacheLifetime = 30; + + /** + * 1/x + */ + private $_cachePurgeFrequency = 30; + + /** + * speeds up calls to external templates + */ + private $externalMacroTemplatesCache = array(); + + //}}} + + /** + * PHPTAL Constructor. + * + * @param string $path Template file path. + */ + public function __construct($path=false) + { + $this->_path = $path; + $this->_globalContext = new stdClass(); + $this->_context = new PHPTAL_Context(); + $this->_context->setGlobal($this->_globalContext); + + if (function_exists('sys_get_temp_dir')) { + $this->setPhpCodeDestination(sys_get_temp_dir()); + } elseif (substr(PHP_OS, 0, 3) == 'WIN') { + if (file_exists('c:\\WINNT\\Temp\\')) { + $this->setPhpCodeDestination('c:\\WINNT\\Temp\\'); + } else { + $this->setPhpCodeDestination('c:\\WINDOWS\\Temp\\'); + } + } else { + $this->setPhpCodeDestination('/tmp/'); + } + } + + /** + * create + * returns a new PHPTAL object + * + * @param string $path Template file path. + * + * @return PHPTAL + */ + public static function create($path=false) + { + return new PHPTAL($path); + } + + /** + * Clone template state and context. + * + * @return void + */ + public function __clone() + { + $this->_context = $this->_context->pushContext(); + } + + /** + * Set template from file path. + * + * @param string $path filesystem path, + * or any path that will be accepted by source resolver + * + * @return $this + */ + public function setTemplate($path) + { + $this->_prepared = false; + $this->_functionName = null; + $this->_codeFile = null; + $this->_path = $path; + $this->_source = null; + $this->_context->_docType = null; + $this->_context->_xmlDeclaration = null; + return $this; + } + + /** + * Set template from source. + * + * Should be used only with temporary template sources. + * Use setTemplate() or addSourceResolver() whenever possible. + * + * @param string $src The phptal template source. + * @param string $path Fake and 'unique' template path. + * + * @return $this + */ + public function setSource($src, $path = null) + { + $this->_prepared = false; + $this->_functionName = null; + $this->_codeFile = null; + $this->_source = new PHPTAL_StringSource($src, $path); + $this->_path = $this->_source->getRealPath(); + $this->_context->_docType = null; + $this->_context->_xmlDeclaration = null; + return $this; + } + + /** + * Specify where to look for templates. + * + * @param mixed $rep string or Array of repositories + * + * @return $this + */ + public function setTemplateRepository($rep) + { + if (is_array($rep)) { + $this->_repositories = $rep; + } else { + $this->_repositories[] = $rep; + } + return $this; + } + + /** + * Get template repositories. + * + * @return array + */ + public function getTemplateRepositories() + { + return $this->_repositories; + } + + /** + * Clears the template repositories. + * + * @return $this + */ + public function clearTemplateRepositories() + { + $this->_repositories = array(); + return $this; + } + + /** + * Specify how to look for templates. + * + * @param PHPTAL_SourceResolver $resolver instance of resolver + * + * @return $this + */ + public function addSourceResolver(PHPTAL_SourceResolver $resolver) + { + $this->resolvers[] = $resolver; + return $this; + } + + /** + * Ignore XML/XHTML comments on parsing. + * Comments starting with <!--! are always stripped. + * + * @param bool $bool if true all comments are stripped during parse + * + * @return $this + */ + public function stripComments($bool) + { + $this->resetPrepared(); + + if ($bool) { + $this->prefilters['_phptal_strip_comments_'] = new PHPTAL_PreFilter_StripComments(); + } else { + unset($this->prefilters['_phptal_strip_comments_']); + } + return $this; + } + + /** + * Set output mode + * XHTML output mode will force elements like <link/>, <meta/> and <img/>, etc. + * to be empty and threats attributes like selected, checked to be + * boolean attributes. + * + * XML output mode outputs XML without such modifications + * and is neccessary to generate RSS feeds properly. + * + * @param int $mode (PHPTAL::XML, PHPTAL::XHTML or PHPTAL::HTML5). + * + * @return $this + */ + public function setOutputMode($mode) + { + $this->resetPrepared(); + + if ($mode != PHPTAL::XHTML && $mode != PHPTAL::XML && $mode != PHPTAL::HTML5) { + throw new PHPTAL_ConfigurationException('Unsupported output mode '.$mode); + } + $this->_outputMode = $mode; + return $this; + } + + /** + * Get output mode + * @see setOutputMode() + * + * @return output mode constant + */ + public function getOutputMode() + { + return $this->_outputMode; + } + + /** + * Set input and ouput encoding. Encoding is case-insensitive. + * + * @param string $enc example: 'UTF-8' + * + * @return $this + */ + public function setEncoding($enc) + { + $enc = strtoupper($enc); + if ($enc != $this->_encoding) { + $this->_encoding = $enc; + if ($this->_translator) $this->_translator->setEncoding($enc); + + $this->resetPrepared(); + } + return $this; + } + + /** + * Get input and ouput encoding. + * + * @param string $enc example: 'UTF-8' + * + * @return $this + */ + public function getEncoding() + { + return $this->_encoding; + } + + /** + * Set the storage location for intermediate PHP files. + * The path cannot contain characters that would be interpreted by glob() (e.g. *[]?) + * + * @param string $path Intermediate file path. + * + * @return $this + */ + public function setPhpCodeDestination($path) + { + $this->_phpCodeDestination = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; + $this->resetPrepared(); + return $this; + } + + /** + * Get the storage location for intermediate PHP files. + * + * @return string + */ + public function getPhpCodeDestination() + { + return $this->_phpCodeDestination; + } + + /** + * Set the file extension for intermediate PHP files. + * + * @param string $extension The file extension. + * + * @return $this + */ + public function setPhpCodeExtension($extension) + { + $this->_phpCodeExtension = $extension; + $this->resetPrepared(); + return $this; + } + + /** + * Get the file extension for intermediate PHP files. + */ + public function getPhpCodeExtension() + { + return $this->_phpCodeExtension; + } + + /** + * Flags whether to ignore intermediate php files and to + * reparse templates every time (if set to true). + * + * DON'T USE IN PRODUCTION - this makes PHPTAL many times slower. + * + * @param bool $bool Forced reparse state. + * + * @return $this + */ + public function setForceReparse($bool) + { + $this->_forceReparse = (bool) $bool; + return $this; + } + + /** + * Get the value of the force reparse state. + */ + public function getForceReparse() + { + return $this->_forceReparse; + } + + /** + * Set I18N translator. + * + * This sets encoding used by the translator, so be sure to use encoding-dependent + * features of the translator (e.g. addDomain) _after_ calling setTranslator. + * + * @param PHPTAL_TranslationService $t instance + * + * @return $this + */ + public function setTranslator(PHPTAL_TranslationService $t) + { + $this->_translator = $t; + $t->setEncoding($this->getEncoding()); + return $this; + } + + + /** + * Please use addPreFilter instead. + * + * This method and use of PHPTAL_Filter for prefilters are deprecated. + * + * @see PHPTAL::addPreFilter() + * @deprecated + */ + final public function setPreFilter(PHPTAL_Filter $filter) + { + $this->resetPrepared(); + $this->prefilters['_phptal_old_filter_'] = $filter; + } + + /** + * Add new prefilter to filter chain. + * Prefilters are called only once template is compiled. + * + * PreFilters must inherit PHPTAL_PreFilter class. + * (in future this method will allow string with filter name instead of object) + * + * @param mixed $filter PHPTAL_PreFilter object or name of prefilter to add + * + * @return PHPTAL + */ + final public function addPreFilter($filter) + { + $this->resetPrepared(); + + if (!$filter instanceof PHPTAL_PreFilter) { + throw new PHPTAL_ConfigurationException("addPreFilter expects PHPTAL_PreFilter object"); + } + + $this->prefilters[] = $filter; + return $this; + } + + /** + * Array with all prefilter objects *or strings* that are names of prefilter classes. + * (the latter is not implemented in 1.2.1) + * + * Array keys may be non-numeric! + * + * @return array + */ + protected function getPreFilters() + { + return $this->prefilters; + } + + /** + * Returns string that is unique for every different configuration of prefilters. + * Result of prefilters may be cached until this string changes. + * + * You can override this function. + * + * @return string + */ + private function getPreFiltersCacheId() + { + $cacheid = ''; + foreach($this->getPreFilters() as $key => $prefilter) { + if ($prefilter instanceof PHPTAL_PreFilter) { + $cacheid .= $key.$prefilter->getCacheId(); + } elseif ($prefilter instanceof PHPTAL_Filter) { + $cacheid .= $key.get_class($prefilter); + } else { + $cacheid .= $key.$prefilter; + } + } + return $cacheid; + } + + /** + * Instantiate prefilters + * + * @return array of PHPTAL_[Pre]Filter objects + */ + private function getPreFilterInstances() + { + $prefilters = $this->getPreFilters(); + + foreach($prefilters as $prefilter) { + if ($prefilter instanceof PHPTAL_PreFilter) { + $prefilter->setPHPTAL($this); + } + } + return $prefilters; + } + + /** + * Set template post filter. + * It will be called every time after template generates output. + * + * See PHPTAL_PostFilter class. + * + * @param PHPTAL_Filter $filter filter instance + */ + public function setPostFilter(PHPTAL_Filter $filter) + { + $this->_postfilter = $filter; + return $this; + } + + /** + * Register a trigger for specified phptal:id. + * @param string $id phptal:id to look for + */ + public function addTrigger($id, PHPTAL_Trigger $trigger) + { + $this->_triggers[$id] = $trigger; + return $this; + } + + /** + * Returns trigger for specified phptal:id. + * + * @param string $id phptal:id + * + * @return PHPTAL_Trigger or NULL + */ + public function getTrigger($id) + { + if (array_key_exists($id, $this->_triggers)) { + return $this->_triggers[$id]; + } + return null; + } + + /** + * Set a context variable. + * Use it by setting properties on PHPTAL object. + * + * @param string $varname + * @param mixed $value + * + * @return void + */ + public function __set($varname, $value) + { + $this->_context->__set($varname, $value); + } + + /** + * Set a context variable. + * + * @see PHPTAL::__set() + * @param string $varname name of the variable + * @param mixed $value value of the variable + * + * @return $this + */ + public function set($varname, $value) + { + $this->_context->__set($varname, $value); + return $this; + } + + /** + * Execute the template code and return generated markup. + * + * @return string + */ + public function execute() + { + try + { + if (!$this->_prepared) { + // includes generated template PHP code + $this->prepare(); + } + $this->_context->echoDeclarations(false); + + $templateFunction = $this->getFunctionName(); + + try { + ob_start(); + $templateFunction($this, $this->_context); + $res = ob_get_clean(); + } + catch (Exception $e) + { + ob_end_clean(); + throw $e; + } + + // unshift doctype + if ($this->_context->_docType) { + $res = $this->_context->_docType . $res; + } + + // unshift xml declaration + if ($this->_context->_xmlDeclaration) { + $res = $this->_context->_xmlDeclaration . "\n" . $res; + } + + if ($this->_postfilter) { + return $this->_postfilter->filter($res); + } + } + catch (Exception $e) + { + PHPTAL_ExceptionHandler::handleException($e, $this->getEncoding()); + } + + return $res; + } + + /** + * Execute and echo template without buffering of the output. + * This function does not allow postfilters nor DOCTYPE/XML declaration. + * + * @return NULL + */ + public function echoExecute() + { + try { + if (!$this->_prepared) { + // includes generated template PHP code + $this->prepare(); + } + + if ($this->_postfilter) { + throw new PHPTAL_ConfigurationException("echoExecute() does not support postfilters"); + } + + $this->_context->echoDeclarations(true); + + $templateFunction = $this->getFunctionName(); + $templateFunction($this, $this->_context); + } + catch (Exception $e) + { + PHPTAL_ExceptionHandler::handleException($e, $this->getEncoding()); + } + } + + /** + * Execute a template macro. + * Should be used only from within generated template code! + * + * @param string $path Template macro path + */ + public function executeMacro($path) + { + $this->_executeMacroOfTemplate($path, $this); + } + + /** + * This is PHPTAL's internal function that handles + * execution of macros from templates. + * + * $this is caller's context (the file where execution had originally started) + * + * @param PHPTAL $local_tpl is PHPTAL instance of the file in which macro is defined + * (it will be different from $this if it's external macro call) + * @access private + */ + final public function _executeMacroOfTemplate($path, PHPTAL $local_tpl) + { + // extract macro source file from macro name, if macro path does not + // contain filename, then the macro is assumed to be local + + if (preg_match('/^(.*?)\/([a-z0-9_-]*)$/i', $path, $m)) { + list(, $file, $macroName) = $m; + + if (isset($this->externalMacroTemplatesCache[$file])) { + $tpl = $this->externalMacroTemplatesCache[$file]; + } else { + $tpl = clone $this; + array_unshift($tpl->_repositories, dirname($this->_source->getRealPath())); + $tpl->setTemplate($file); + $tpl->prepare(); + + // keep it small (typically only 1 or 2 external files are used) + if (count($this->externalMacroTemplatesCache) > 10) { + $this->externalMacroTemplatesCache = array(); + } + $this->externalMacroTemplatesCache[$file] = $tpl; + } + + $fun = $tpl->getFunctionName() . '_' . strtr($macroName, "-", "_"); + if (!function_exists($fun)) { + throw new PHPTAL_MacroMissingException("Macro '$macroName' is not defined in $file", $this->_source->getRealPath()); + } + + $fun($tpl, $this); + + } else { + // call local macro + $fun = $local_tpl->getFunctionName() . '_' . strtr($path, "-", "_"); + if (!function_exists($fun)) { + throw new PHPTAL_MacroMissingException("Macro '$path' is not defined", $local_tpl->_source->getRealPath()); + } + $fun( $local_tpl, $this); + } + } + + /** + * ensure that getCodePath will return up-to-date path + */ + private function setCodeFile() + { + $this->findTemplate(); + $this->_codeFile = $this->getPhpCodeDestination() . $this->getFunctionName() . '.' . $this->getPhpCodeExtension(); + } + + protected function resetPrepared() + { + $this->_prepared = false; + $this->_functionName = null; + $this->_codeFile = null; + } + + /** + * Prepare template without executing it. + */ + public function prepare() + { + // clear just in case settings changed and cache is out of date + $this->externalMacroTemplatesCache = array(); + + // find the template source file and update function name + $this->setCodeFile(); + + if (!function_exists($this->getFunctionName())) { + // parse template if php generated code does not exists or template + // source file modified since last generation or force reparse is set + if ($this->getForceReparse() || !file_exists($this->getCodePath())) { + + // i'm not sure where that belongs, but not in normal path of execution + // because some sites have _a lot_ of files in temp + if ($this->getCachePurgeFrequency() && mt_rand()%$this->getCachePurgeFrequency() == 0) { + $this->cleanUpGarbage(); + } + + $result = $this->parse(); + + if (!file_put_contents($this->getCodePath(), $result)) { + throw new PHPTAL_IOException('Unable to open '.$this->getCodePath().' for writing'); + } + + // the awesome thing about eval() is that parse errors don't stop PHP. + // when PHP dies during eval, fatal error is printed and + // can be captured with output buffering + ob_start(); + try { + eval("?>\n".$result); + } + catch(Exception $e) { + ob_end_clean(); + throw $e; + } + + if (!function_exists($this->getFunctionName())) { + $msg = str_replace('eval()\'d code', $this->getCodePath(), ob_get_clean()); + + // greedy .* ensures last match + if (preg_match('/.*on line (\d+)$/m', $msg, $m)) $line=$m[1]; else $line=0; + throw new PHPTAL_TemplateException(trim($msg), $this->getCodePath(), $line); + } + ob_end_clean(); + + } else { + // eval trick is used only on first run, + // just in case it causes any problems with opcode accelerators + require $this->getCodePath(); + } + } + + $this->_prepared = true; + return $this; + } + + /** + * get how long compiled templates and phptal:cache files are kept, in days + */ + public function getCacheLifetime() + { + return $this->_cacheLifetime; + } + + /** + * set how long compiled templates and phptal:cache files are kept + * + * @param $days number of days + */ + public function setCacheLifetime($days) + { + $this->_cacheLifetime = max(0.5, $days); + return $this; + } + + /** + * PHPTAL will scan cache and remove old files on every nth compile + * Set to 0 to disable cleanups + */ + public function setCachePurgeFrequency($n) + { + $this->_cachePurgeFrequency = (int)$n; + return $this; + } + + /** + * how likely cache cleaning can happen + * @see self::setCachePurgeFrequency() + */ + public function getCachePurgeFrequency() + { + return $this->_cachePurgeFrequency; + } + + + /** + * Removes all compiled templates from cache that + * are older than getCacheLifetime() days + */ + public function cleanUpGarbage() + { + $cacheFilesExpire = time() - $this->getCacheLifetime() * 3600 * 24; + + // relies on templates sorting order being related to their modification dates + $upperLimit = $this->getPhpCodeDestination() . $this->getFunctionNamePrefix($cacheFilesExpire) . '_'; + $lowerLimit = $this->getPhpCodeDestination() . $this->getFunctionNamePrefix(0); + + // second * gets phptal:cache + $cacheFiles = glob($this->getPhpCodeDestination() . 'tpl_????????_*.' . $this->getPhpCodeExtension() . '*'); + + if ($cacheFiles) { + foreach ($cacheFiles as $index => $file) { + + // comparison here skips filenames that are certainly too new + if (strcmp($file, $upperLimit) <= 0 || substr($file, 0, strlen($lowerLimit)) === $lowerLimit) { + $time = filemtime($file); + if ($time && $time < $cacheFilesExpire) { + @unlink($file); + } + } + } + } + } + + /** + * Removes content cached with phptal:cache for currently set template + * Must be called after setSource/setTemplate. + */ + public function cleanUpCache() + { + $filename = $this->getCodePath(); + $cacheFiles = glob($filename . '?*'); + if ($cacheFiles) { + foreach ($cacheFiles as $file) { + if (substr($file, 0, strlen($filename)) !== $filename) continue; // safety net + @unlink($file); + } + } + $this->_prepared = false; + } + + /** + * Returns the path of the intermediate PHP code file. + * + * The returned file may be used to cleanup (unlink) temporary files + * generated by temporary templates or more simply for debug. + * + * @return string + */ + public function getCodePath() + { + if (!$this->_codeFile) $this->setCodeFile(); + return $this->_codeFile; + } + + /** + * Returns the generated template function name. + * @return string + */ + public function getFunctionName() + { + // function name is used as base for caching, so it must be unique for + // every combination of settings that changes code in compiled template + + if (!$this->_functionName) { + + // just to make tempalte name recognizable + $basename = preg_replace('/\.[a-z]{3,5}$/', '', basename($this->_source->getRealPath())); + $basename = substr(trim(preg_replace('/[^a-zA-Z0-9]+/', '_', $basename), "_"), 0, 20); + + $hash = md5(PHPTAL_VERSION . PHP_VERSION + . $this->_source->getRealPath() + . $this->getEncoding() + . $this->getPrefiltersCacheId() + . $this->getOutputMode(), + true + ); + + // uses base64 rather than hex to make filename shorter. + // there is loss of some bits due to name constraints and case-insensivity, + // but that's still over 110 bits in addition to basename and timestamp. + $hash = strtr(rtrim(base64_encode($hash),"="),"+/=","_A_"); + + $this->_functionName = $this->getFunctionNamePrefix($this->_source->getLastModifiedTime()) . + $basename . '__' . $hash; + } + return $this->_functionName; + } + + /** + * Returns prefix used for function name. + * Function name is also base name for the template. + * + * @param int $timestamp unix timestamp with template modification date + * + * @return string + */ + private function getFunctionNamePrefix($timestamp) + { + // tpl_ prefix and last modified time must not be changed, + // because cache cleanup relies on that + return 'tpl_' . sprintf("%08x", $timestamp) .'_'; + } + + /** + * Returns template translator. + * @return PHPTAL_TranslationService + */ + public function getTranslator() + { + return $this->_translator; + } + + /** + * Returns array of exceptions caught by tal:on-error attribute. + * + * @return array<Exception> + */ + public function getErrors() + { + return $this->_errors; + } + + /** + * Public for phptal templates, private for user. + * + * @return void + * @access private + */ + public function addError(Exception $error) + { + $this->_errors[] = $error; + } + + /** + * Returns current context object. + * Use only in Triggers. + * + * @return PHPTAL_Context + */ + public function getContext() + { + return $this->_context; + } + + /** + * only for use in generated template code + * + * @access private + */ + public function getGlobalContext() + { + return $this->_globalContext; + } + + /** + * only for use in generated template code + * + * @access private + */ + final public function pushContext() + { + $this->_context = $this->_context->pushContext(); + return $this->_context; + } + + /** + * only for use in generated template code + * + * @access private + */ + final public function popContext() + { + $this->_context = $this->_context->popContext(); + return $this->_context; + } + + /** + * Parse currently set template, prefilter and generate PHP code. + * + * @return string (compiled PHP code) + */ + protected function parse() + { + $data = $this->_source->getData(); + + $prefilters = $this->getPreFilterInstances(); + foreach($prefilters as $prefilter) { + $data = $prefilter->filter($data); + } + + $realpath = $this->_source->getRealPath(); + $parser = new PHPTAL_Dom_SaxXmlParser($this->_encoding); + + $builder = new PHPTAL_Dom_PHPTALDocumentBuilder(); + $tree = $parser->parseString($builder, $data, $realpath)->getResult(); + + foreach($prefilters as $prefilter) { + if ($prefilter instanceof PHPTAL_PreFilter) { + if ($prefilter->filterDOM($tree) !== NULL) { + throw new PHPTAL_ConfigurationException("Don't return value from filterDOM()"); + } + } + } + + $state = new PHPTAL_Php_State($this); + + $codewriter = new PHPTAL_Php_CodeWriter($state); + $codewriter->doTemplateFile($this->getFunctionName(), $tree); + + return $codewriter->getResult(); + } + + /** + * Search template source location. + * @return void + */ + protected function findTemplate() + { + if ($this->_path == false) { + throw new PHPTAL_ConfigurationException('No template file specified'); + } + + // template source already defined + if ($this->_source) { + return; + } + + if (!$this->resolvers && !$this->_repositories) { + $this->_source = new PHPTAL_FileSource($this->_path); + } else { + foreach ($this->resolvers as $resolver) { + $source = $resolver->resolve($this->_path); + if ($source) { + $this->_source = $source; + return; + } + } + + $resolver = new PHPTAL_FileSourceResolver($this->_repositories); + $this->_source = $resolver->resolve($this->_path); + } + + if (!$this->_source) { + throw new PHPTAL_IOException('Unable to locate template file '.$this->_path); + } + } + + /** + * Removed + * + * @deprecated + * @return void + */ + final public static function setIncludePath() + { + } + + /** + * Restore include path to state before PHPTAL modified it. + * + * @deprecated + * @return void + */ + final public static function restoreIncludePath() + { + } + + /** + * Suitable for callbacks from SPL autoload + * + * @param string $class class name to load + * + * @return void + */ + final public static function autoload($class) + { + if (version_compare(PHP_VERSION, '5.3', '>=') && __NAMESPACE__) { + $class = str_replace(__NAMESPACE__, 'PHPTAL', $class); + $class = strtr($class, '\\', '_'); + } + + if (substr($class, 0, 7) !== 'PHPTAL_') return; + + $path = dirname(__FILE__) . strtr("_".$class, "_", DIRECTORY_SEPARATOR) . '.php'; + + require $path; + } + + /** + * Sets up PHPTAL's autoloader. + * + * If you have to use your own autoloader to load PHPTAL files, + * use spl_autoload_unregister(array('PHPTAL','autoload')); + * + * @return void + */ + final public static function autoloadRegister() + { + // spl_autoload_register disables oldschool autoload + // even if it was added using spl_autoload_register! + // this is intended to preserve old autoloader + + $uses_autoload = function_exists('__autoload') + && (!($tmp = spl_autoload_functions()) || ($tmp[0] === '__autoload')); + + // Prepending PHPTAL's autoloader helps if there are other autoloaders + // that throw/die when file is not found. Only >5.3 though. + if (version_compare(PHP_VERSION, '5.3', '>=')) { + spl_autoload_register(array(__CLASS__,'autoload'), false, true); + } else { + spl_autoload_register(array(__CLASS__,'autoload')); + } + + if ($uses_autoload) { + spl_autoload_register('__autoload'); + } + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/ConfigurationException.php b/src/core/libs/PHPTAL5/PHPTAL/ConfigurationException.php new file mode 100644 index 0000000..28e760a --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/ConfigurationException.php @@ -0,0 +1,24 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * You're probably not using PHPTAL class properly + * + * @package PHPTAL + * @subpackage Exception + */ +class PHPTAL_ConfigurationException extends PHPTAL_Exception +{ +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Context.php b/src/core/libs/PHPTAL5/PHPTAL/Context.php new file mode 100644 index 0000000..470d521 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Context.php @@ -0,0 +1,563 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * This class handles template execution context. + * Holds template variables and carries state/scope across macro executions. + * + */ +class PHPTAL_Context +{ + public $repeat; + public $_xmlDeclaration; + public $_docType; + private $_nothrow; + private $_slots = array(); + private $_slotsStack = array(); + private $_parentContext = null; + private $_globalContext = null; + private $_echoDeclarations = false; + + public function __construct() + { + $this->repeat = new stdClass(); + } + + public function __clone() + { + $this->repeat = clone $this->repeat; + } + + /** + * will switch to this context when popContext() is called + * + * @return void + */ + public function setParent(PHPTAL_Context $parent) + { + $this->_parentContext = $parent; + } + + /** + * set stdClass object which has property of every global variable + * It can use __isset() and __get() [none of them or both] + * + * @return void + */ + public function setGlobal(stdClass $globalContext) + { + $this->_globalContext = $globalContext; + } + + /** + * save current execution context + * + * @return Context (new) + */ + public function pushContext() + { + $res = clone $this; + $res->setParent($this); + return $res; + } + + /** + * get previously saved execution context + * + * @return Context (old) + */ + public function popContext() + { + return $this->_parentContext; + } + + /** + * @param bool $tf true if DOCTYPE and XML declaration should be echoed immediately, false if buffered + */ + public function echoDeclarations($tf) + { + $this->_echoDeclarations = $tf; + } + + /** + * Set output document type if not already set. + * + * This method ensure PHPTAL uses the first DOCTYPE encountered (main + * template or any macro template source containing a DOCTYPE. + * + * @param bool $called_from_macro will do nothing if _echoDeclarations is also set + * + * @return void + */ + public function setDocType($doctype,$called_from_macro) + { + // FIXME: this is temporary workaround for problem of DOCTYPE disappearing in cloned PHPTAL object (because clone keeps _parentContext) + if (!$this->_docType) { + $this->_docType = $doctype; + } + + if ($this->_parentContext) { + $this->_parentContext->setDocType($doctype, $called_from_macro); + } else if ($this->_echoDeclarations) { + if (!$called_from_macro) { + echo $doctype; + } else { + throw new PHPTAL_ConfigurationException("Executed macro in file with DOCTYPE when using echoExecute(). This is not supported yet. Remove DOCTYPE or use PHPTAL->execute()."); + } + } + else if (!$this->_docType) { + $this->_docType = $doctype; + } + } + + /** + * Set output document xml declaration. + * + * This method ensure PHPTAL uses the first xml declaration encountered + * (main template or any macro template source containing an xml + * declaration) + * + * @param bool $called_from_macro will do nothing if _echoDeclarations is also set + * + * @return void + */ + public function setXmlDeclaration($xmldec, $called_from_macro) + { + // FIXME + if (!$this->_xmlDeclaration) { + $this->_xmlDeclaration = $xmldec; + } + + if ($this->_parentContext) { + $this->_parentContext->setXmlDeclaration($xmldec, $called_from_macro); + } else if ($this->_echoDeclarations) { + if (!$called_from_macro) { + echo $xmldec."\n"; + } else { + throw new PHPTAL_ConfigurationException("Executed macro in file with XML declaration when using echoExecute(). This is not supported yet. Remove XML declaration or use PHPTAL->execute()."); + } + } else if (!$this->_xmlDeclaration) { + $this->_xmlDeclaration = $xmldec; + } + } + + /** + * Activate or deactivate exception throwing during unknown path + * resolution. + * + * @return void + */ + public function noThrow($bool) + { + $this->_nothrow = $bool; + } + + /** + * Returns true if specified slot is filled. + * + * @return bool + */ + public function hasSlot($key) + { + return isset($this->_slots[$key]) || ($this->_parentContext && $this->_parentContext->hasSlot($key)); + } + + /** + * Returns the content of specified filled slot. + * + * Use echoSlot() whenever you just want to output the slot + * + * @return string + */ + public function getSlot($key) + { + if (isset($this->_slots[$key])) { + if (is_string($this->_slots[$key])) { + return $this->_slots[$key]; + } + ob_start(); + call_user_func($this->_slots[$key][0], $this->_slots[$key][1], $this->_slots[$key][2]); + return ob_get_clean(); + } else if ($this->_parentContext) { + return $this->_parentContext->getSlot($key); + } + } + + /** + * Immediately echoes content of specified filled slot. + * + * Equivalent of echo $this->getSlot(); + * + * @return string + */ + public function echoSlot($key) + { + if (isset($this->_slots[$key])) { + if (is_string($this->_slots[$key])) { + echo $this->_slots[$key]; + } else { + call_user_func($this->_slots[$key][0], $this->_slots[$key][1], $this->_slots[$key][2]); + } + } else if ($this->_parentContext) { + return $this->_parentContext->echoSlot($key); + } + } + + /** + * Fill a macro slot. + * + * @return void + */ + public function fillSlot($key, $content) + { + $this->_slots[$key] = $content; + if ($this->_parentContext) { + // Works around bug with tal:define popping context after fillslot + $this->_parentContext->_slots[$key] = $content; + } + } + + public function fillSlotCallback($key, $callback, $_thistpl, $tpl) + { + assert('is_callable($callback)'); + $this->_slots[$key] = array($callback, $_thistpl, $tpl); + if ($this->_parentContext) { + // Works around bug with tal:define popping context after fillslot + $this->_parentContext->_slots[$key] = array($callback, $_thistpl, $tpl); + } + } + + /** + * Push current filled slots on stack. + * + * @return void + */ + public function pushSlots() + { + $this->_slotsStack[] = $this->_slots; + $this->_slots = array(); + } + + /** + * Restore filled slots stack. + * + * @return void + */ + public function popSlots() + { + $this->_slots = array_pop($this->_slotsStack); + } + + /** + * Context setter. + * + * @return void + */ + public function __set($varname, $value) + { + if (preg_match('/^_|\s/', $varname)) { + throw new PHPTAL_InvalidVariableNameException('Template variable error \''.$varname.'\' must not begin with underscore or contain spaces'); + } + $this->$varname = $value; + } + + /** + * @return bool + */ + public function __isset($varname) + { + // it doesn't need to check isset($this->$varname), because PHP does that _before_ calling __isset() + return isset($this->_globalContext->$varname) || defined($varname); + } + + /** + * Context getter. + * If variable doesn't exist, it will throw an exception, unless noThrow(true) has been called + * + * @return mixed + */ + public function __get($varname) + { + // PHP checks public properties first, there's no need to support them here + + // must use isset() to allow custom global contexts with __isset()/__get() + if (isset($this->_globalContext->$varname)) { + return $this->_globalContext->$varname; + } + + if (defined($varname)) { + return constant($varname); + } + + if ($this->_nothrow) { + return null; + } + + throw new PHPTAL_VariableNotFoundException("Unable to find variable '$varname' in current scope"); + } + + /** + * helper method for PHPTAL_Context::path() + * + * @access private + */ + private static function pathError($base, $path, $current, $basename) + { + if ($current !== $path) { + $pathinfo = " (in path '.../$path')"; + } else $pathinfo = ''; + + if (!empty($basename)) { + $basename = "'" . $basename . "' "; + } + + if (is_array($base)) { + throw new PHPTAL_VariableNotFoundException("Array {$basename}doesn't have key named '$current'$pathinfo"); + } + if (is_object($base)) { + throw new PHPTAL_VariableNotFoundException(ucfirst(get_class($base))." object {$basename}doesn't have method/property named '$current'$pathinfo"); + } + throw new PHPTAL_VariableNotFoundException(trim("Attempt to read property '$current'$pathinfo from ".gettype($base)." value {$basename}")); + } + + /** + * Resolve TALES path starting from the first path element. + * The TALES path : object/method1/10/method2 + * will call : $ctx->path($ctx->object, 'method1/10/method2') + * + * This function is very important for PHPTAL performance. + * + * This function will become non-static in the future + * + * @param mixed $base first element of the path ($ctx) + * @param string $path rest of the path + * @param bool $nothrow is used by phptal_exists(). Prevents this function from + * throwing an exception when a part of the path cannot be resolved, null is + * returned instead. + * + * @access private + * @return mixed + */ + public static function path($base, $path, $nothrow=false) + { + if ($base === null) { + if ($nothrow) return null; + PHPTAL_Context::pathError($base, $path, $path, $path); + } + + $chunks = explode('/', $path); + $current = null; + + for ($i = 0; $i < count($chunks); $i++) { + $prev = $current; + $current = $chunks[$i]; + + // object handling + if (is_object($base)) { + $base = phptal_unravel_closure($base); + + // look for method. Both method_exists and is_callable are required because of __call() and protected methods + if (method_exists($base, $current) && is_callable(array($base, $current))) { + $base = $base->$current(); + continue; + } + + // look for property + if (property_exists($base, $current)) { + $base = $base->$current; + continue; + } + + if ($base instanceof ArrayAccess && $base->offsetExists($current)) { + $base = $base->offsetGet($current); + continue; + } + + if (($current === 'length' || $current === 'size') && $base instanceof Countable) { + $base = count($base); + continue; + } + + // look for isset (priority over __get) + if (method_exists($base, '__isset')) { + if ($base->__isset($current)) { + $base = $base->$current; + continue; + } + } + // ask __get and discard if it returns null + elseif (method_exists($base, '__get')) { + $tmp = $base->$current; + if (null !== $tmp) { + $base = $tmp; + continue; + } + } + + // magic method call + if (method_exists($base, '__call')) { + try + { + $base = $base->__call($current, array()); + continue; + } + catch(BadMethodCallException $e) {} + } + + if ($nothrow) { + return null; + } + + PHPTAL_Context::pathError($base, $path, $current, $prev); + } + + // array handling + if (is_array($base)) { + // key or index + if (array_key_exists((string)$current, $base)) { + $base = $base[$current]; + continue; + } + + // virtual methods provided by phptal + if ($current == 'length' || $current == 'size') { + $base = count($base); + continue; + } + + if ($nothrow) + return null; + + PHPTAL_Context::pathError($base, $path, $current, $prev); + } + + // string handling + if (is_string($base)) { + // virtual methods provided by phptal + if ($current == 'length' || $current == 'size') { + $base = strlen($base); + continue; + } + + // access char at index + if (is_numeric($current)) { + $base = $base[$current]; + continue; + } + } + + // if this point is reached, then the part cannot be resolved + + if ($nothrow) + return null; + + PHPTAL_Context::pathError($base, $path, $current, $prev); + } + + return $base; + } +} + +/** + * @see PHPTAL_Context::path() + * @deprecated + */ +function phptal_path($base, $path, $nothrow=false) +{ + return PHPTAL_Context::path($base, $path, $nothrow); +} + +/** + * helper function for chained expressions + * + * @param mixed $var value to check + * @return bool + * @access private + */ +function phptal_isempty($var) +{ + return $var === null || $var === false || $var === '' + || ((is_array($var) || $var instanceof Countable) && count($var)===0); +} + +/** + * helper function for conditional expressions + * + * @param mixed $var value to check + * @return bool + * @access private + */ +function phptal_true($var) +{ + $var = phptal_unravel_closure($var); + return $var && (!$var instanceof Countable || count($var)); +} + +/** + * convert to string and html-escape given value (of any type) + * + * @access private + */ +function phptal_escape($var, $encoding) +{ + if (is_string($var)) { + return htmlspecialchars($var, ENT_QUOTES, $encoding); + } + return htmlspecialchars(phptal_tostring($var), ENT_QUOTES, $encoding); +} + +/** + * convert anything to string + * + * @access private + */ +function phptal_tostring($var) +{ + if (is_string($var)) { + return $var; + } elseif (is_bool($var)) { + return (int)$var; + } elseif (is_array($var)) { + return implode(', ', array_map('phptal_tostring', $var)); + } elseif ($var instanceof SimpleXMLElement) { + + /* There is no sane way to tell apart element and attribute nodes + in SimpleXML, so here's a guess that if something has no attributes + or children, and doesn't output <, then it's an attribute */ + + $xml = $var->asXML(); + if ($xml[0] === '<' || $var->attributes() || $var->children()) { + return $xml; + } + } + return (string)phptal_unravel_closure($var); +} + +/** + * unravel the provided expression if it is a closure + * + * This will call the base expression and its result + * as long as it is a Closure. Once the base (non-Closure) + * value is found it is returned. + * + * This function has no effect on non-Closure expressions + */ +function phptal_unravel_closure($var) +{ + while ($var instanceof Closure) { + $var = $var(); + } + return $var; +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/DefaultKeyword.php b/src/core/libs/PHPTAL5/PHPTAL/DefaultKeyword.php new file mode 100644 index 0000000..28d11e2 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/DefaultKeyword.php @@ -0,0 +1,39 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Andrew Crites <explosion-pills@aysites.com> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * Representation of the template 'default' keyword + * + * @package PHPTAL + * @subpackage Keywords + */ +class PHPTAL_DefaultKeyword implements Countable +{ + public function __toString() + { + return "''"; + } + + public function count() + { + return 1; + } + + public function jsonSerialize() + { + return new stdClass; + } +} +?> diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/Attr.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/Attr.php new file mode 100644 index 0000000..64ffe03 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/Attr.php @@ -0,0 +1,196 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * node that represents element's attribute + * + * @package PHPTAL + * @subpackage Dom + */ +class PHPTAL_Dom_Attr +{ + private $value_escaped, $qualified_name, $namespace_uri, $encoding; + /** + * attribute's value can be overriden with a variable + */ + private $phpVariable; + const HIDDEN = -1; + const NOT_REPLACED = 0; + const VALUE_REPLACED = 1; + const FULLY_REPLACED = 2; + private $replacedState = 0; + + /** + * @param string $qualified_name attribute name with prefix + * @param string $namespace_uri full namespace URI or empty string + * @param string $value_escaped value with HTML-escaping + * @param string $encoding character encoding used by the value + */ + function __construct($qualified_name, $namespace_uri, $value_escaped, $encoding) + { + $this->value_escaped = $value_escaped; + $this->qualified_name = $qualified_name; + $this->namespace_uri = $namespace_uri; + $this->encoding = $encoding; + } + + /** + * get character encoding used by this attribute. + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * get full namespace URI. "" for default namespace. + */ + function getNamespaceURI() + { + return $this->namespace_uri; + } + + /** + * get attribute name including namespace prefix, if any + */ + function getQualifiedName() + { + return $this->qualified_name; + } + + /** + * get "foo" of "ns:foo" attribute name + */ + function getLocalName() + { + $n = explode(':', $this->qualified_name, 2); + return end($n); + } + + /** + * Returns true if this attribute is ns declaration (xmlns="...") + * + * @return bool + */ + function isNamespaceDeclaration() + { + return preg_match('/^xmlns(?:$|:)/', $this->qualified_name); + } + + + /** + * get value as plain text + * + * @return string + */ + function getValue() + { + return html_entity_decode($this->value_escaped, ENT_QUOTES, $this->encoding); + } + + /** + * set plain text as value + */ + function setValue($val) + { + $this->value_escaped = htmlspecialchars($val, ENT_QUOTES, $this->encoding); + } + + /** + * Depends on replaced state. + * If value is not replaced, it will return it with HTML escapes. + * + * @see getReplacedState() + * @see overwriteValueWithVariable() + */ + function getValueEscaped() + { + return $this->value_escaped; + } + + /** + * Set value of the attribute to this exact string. + * String must be HTML-escaped and use attribute's encoding. + * + * @param string $value_escaped new content + */ + function setValueEscaped($value_escaped) + { + $this->replacedState = self::NOT_REPLACED; + $this->value_escaped = $value_escaped; + } + + /** + * set PHP code as value of this attribute. Code is expected to echo the value. + */ + private function setPHPCode($code) + { + $this->value_escaped = '<?php '.$code." ?>\n"; + } + + /** + * hide this attribute. It won't be generated. + */ + function hide() + { + $this->replacedState = self::HIDDEN; + } + + /** + * generate value of this attribute from variable + */ + function overwriteValueWithVariable($phpVariable) + { + $this->replacedState = self::VALUE_REPLACED; + $this->phpVariable = $phpVariable; + $this->setPHPCode('echo '.$phpVariable); + } + + /** + * generate complete syntax of this attribute using variable + */ + function overwriteFullWithVariable($phpVariable) + { + $this->replacedState = self::FULLY_REPLACED; + $this->phpVariable = $phpVariable; + $this->setPHPCode('echo '.$phpVariable); + } + + /** + * use any PHP code to generate this attribute's value + */ + function overwriteValueWithCode($code) + { + $this->replacedState = self::VALUE_REPLACED; + $this->phpVariable = null; + $this->setPHPCode($code); + } + + /** + * if value was overwritten with variable, get its name + */ + function getOverwrittenVariableName() + { + return $this->phpVariable; + } + + /** + * whether getValueEscaped() returns real value or PHP code + */ + function getReplacedState() + { + return $this->replacedState; + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/CDATASection.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/CDATASection.php new file mode 100644 index 0000000..838429b --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/CDATASection.php @@ -0,0 +1,49 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * Outputs <![CDATA[ ]]> blocks, sometimes converts them to text + * @todo this might be moved to CDATA processing in Element + * + * @package PHPTAL + * @subpackage Dom + */ +class PHPTAL_Dom_CDATASection extends PHPTAL_Dom_Node +{ + public function generateCode(PHPTAL_Php_CodeWriter $codewriter) + { + $mode = $codewriter->getOutputMode(); + $value = $this->getValueEscaped(); + $inCDATAelement = PHPTAL_Dom_Defs::getInstance()->isCDATAElementInHTML($this->parentNode->getNamespaceURI(), $this->parentNode->getLocalName()); + + // in HTML5 must limit it to <script> and <style> + if ($mode === PHPTAL::HTML5 && $inCDATAelement) { + $codewriter->pushHTML($codewriter->interpolateCDATA(str_replace('</', '<\/', $value))); + } elseif (($mode === PHPTAL::XHTML && $inCDATAelement) // safe for text/html + || ($mode === PHPTAL::XML && preg_match('/[<>&]/', $value)) // non-useless in XML + || ($mode !== PHPTAL::HTML5 && preg_match('/<\?|\${structure/', $value))) // hacks with structure (in X[HT]ML) may need it + { + // in text/html "</" is dangerous and the only sensible way to escape is ECMAScript string escapes. + if ($mode === PHPTAL::XHTML) $value = str_replace('</', '<\/', $value); + + $codewriter->pushHTML($codewriter->interpolateCDATA('<![CDATA['.$value.']]>')); + } else { + $codewriter->pushHTML($codewriter->interpolateHTML( + htmlspecialchars($value, ENT_QUOTES, $codewriter->getEncoding()) + )); + } + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/Comment.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/Comment.php new file mode 100644 index 0000000..4a3ba3c --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/Comment.php @@ -0,0 +1,28 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * @package PHPTAL + * @subpackage Dom + */ +class PHPTAL_Dom_Comment extends PHPTAL_Dom_Node +{ + public function generateCode(PHPTAL_Php_CodeWriter $codewriter) + { + if (!preg_match('/^\s*!/', $this->getValueEscaped())) { + $codewriter->pushHTML('<!--'.$this->getValueEscaped().'-->'); + } + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/Defs.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/Defs.php new file mode 100644 index 0000000..4d12ed6 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/Defs.php @@ -0,0 +1,246 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * PHPTAL constants. + * + * This is a pseudo singleton class, a user may decide to provide + * his own singleton instance which will then be used by PHPTAL. + * + * This behaviour is mainly useful to remove builtin namespaces + * and provide custom ones. + * + * @package PHPTAL + * @subpackage Dom + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Dom_Defs +{ + /** + * this is a singleton + */ + public static function getInstance() + { + if (!self::$_instance) { + self::$_instance = new PHPTAL_Dom_Defs(); + } + return self::$_instance; + } + + protected function __construct() + { + $this->registerNamespace(new PHPTAL_Namespace_TAL()); + $this->registerNamespace(new PHPTAL_Namespace_METAL()); + $this->registerNamespace(new PHPTAL_Namespace_I18N()); + $this->registerNamespace(new PHPTAL_Namespace_PHPTAL()); + } + + /** + * true if it's empty in XHTML (e.g. <img/>) + * it will assume elements with no namespace may be XHTML too. + * + * @param string $tagName local name of the tag + * + * @return bool + */ + public function isEmptyTagNS($namespace_uri, $local_name) + { + return ($namespace_uri === 'http://www.w3.org/1999/xhtml' || $namespace_uri === '') + && in_array(strtolower($local_name), self::$XHTML_EMPTY_TAGS); + } + + /** + * gives namespace URI for given registered (built-in) prefix + */ + public function prefixToNamespaceURI($prefix) + { + return isset($this->prefix_to_uri[$prefix]) ? $this->prefix_to_uri[$prefix] : false; + } + + /** + * gives typical prefix for given (built-in) namespace + */ + public function namespaceURIToPrefix($uri) + { + return array_search($uri, $this->prefix_to_uri, true); + } + + /** + * array prefix => uri for prefixes that don't have to be declared in PHPTAL + * @return array + */ + public function getPredefinedPrefixes() + { + return $this->prefix_to_uri; + } + + /** + * Returns true if the attribute is an xhtml boolean attribute. + * + * @param string $att local name + * + * @return bool + */ + public function isBooleanAttribute($att) + { + return in_array($att, self::$XHTML_BOOLEAN_ATTRIBUTES); + } + + /** + * true if elements content is parsed as CDATA in text/html + * and also accepts /* * / as comments. + */ + public function isCDATAElementInHTML($namespace_uri, $local_name) + { + return ($local_name === 'script' || $local_name === 'style') + && ($namespace_uri === 'http://www.w3.org/1999/xhtml' || $namespace_uri === ''); + } + + /** + * Returns true if the attribute is a valid phptal attribute + * + * Examples of valid attributes: tal:content, metal:use-slot + * Examples of invalid attributes: tal:unknown, metal:content + * + * @return bool + */ + public function isValidAttributeNS($namespace_uri, $local_name) + { + if (!$this->isHandledNamespace($namespace_uri)) return false; + + $attrs = $this->namespaces_by_uri[$namespace_uri]->getAttributes(); + return isset($attrs[$local_name]); + } + + /** + * is URI registered (built-in) namespace + */ + public function isHandledNamespace($namespace_uri) + { + return isset($this->namespaces_by_uri[$namespace_uri]); + } + + /** + * Returns true if the attribute is a phptal handled xml namespace + * declaration. + * + * Examples of handled xmlns: xmlns:tal, xmlns:metal + * + * @return bool + */ + public function isHandledXmlNs($qname, $value) + { + return substr(strtolower($qname), 0, 6) == 'xmlns:' && $this->isHandledNamespace($value); + } + + /** + * return objects that holds information about given TAL attribute + */ + public function getNamespaceAttribute($namespace_uri, $local_name) + { + $attrs = $this->namespaces_by_uri[$namespace_uri]->getAttributes(); + return $attrs[$local_name]; + } + + /** + * Register a PHPTAL_Namespace and its attribute into PHPTAL. + */ + public function registerNamespace(PHPTAL_Namespace $ns) + { + $this->namespaces_by_uri[$ns->getNamespaceURI()] = $ns; + $this->prefix_to_uri[$ns->getPrefix()] = $ns->getNamespaceURI(); + $prefix = strtolower($ns->getPrefix()); + foreach ($ns->getAttributes() as $name => $attribute) { + $key = $prefix.':'.strtolower($name); + $this->_dictionary[$key] = $attribute; + } + } + + private static $_instance = null; + private $_dictionary = array(); + /** + * list of PHPTAL_Namespace objects + */ + private $namespaces_by_uri = array(); + private $prefix_to_uri = array( + 'xml'=>'http://www.w3.org/XML/1998/namespace', + 'xmlns'=>'http://www.w3.org/2000/xmlns/', + ); + + /** + * This array contains XHTML tags that must be echoed in a &lt;tag/&gt; form + * instead of the &lt;tag&gt;&lt;/tag&gt; form. + * + * In fact, some browsers does not support the later form so PHPTAL + * ensure these tags are correctly echoed. + */ + private static $XHTML_EMPTY_TAGS = array( + 'area', + 'base', + 'basefont', + 'br', + 'col', + 'command', + 'embed', + 'frame', + 'hr', + 'img', + 'input', + 'isindex', + 'keygen', + 'link', + 'meta', + 'param', + 'wbr', + 'source', + 'track', + ); + + /** + * This array contains XHTML boolean attributes, their value is self + * contained (ie: they are present or not). + */ + private static $XHTML_BOOLEAN_ATTRIBUTES = array( + 'autoplay', + 'async', + 'autofocus', + 'checked', + 'compact', + 'controls', + 'declare', + 'default', + 'defer', + 'disabled', + 'formnovalidate', + 'hidden', + 'ismap', + 'itemscope', + 'loop', + 'multiple', + 'noresize', + 'noshade', + 'novalidate', + 'nowrap', + 'open', + 'pubdate', + 'readonly', + 'required', + 'reversed', + 'scoped', + 'seamless', + 'selected', + ); +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/DocumentBuilder.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/DocumentBuilder.php new file mode 100644 index 0000000..c08587f --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/DocumentBuilder.php @@ -0,0 +1,63 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * DOM Builder + * + * @package PHPTAL + * @subpackage Dom + */ +abstract class PHPTAL_Dom_DocumentBuilder +{ + protected $_stack; /* array<PHPTAL_Dom_Node> */ + protected $_current; /* PHPTAL_Dom_Node */ + + protected $file, $line; + + public function __construct() + { + $this->_stack = array(); + } + + abstract public function getResult(); + + abstract public function onDocumentStart(); + + abstract public function onDocumentEnd(); + + abstract public function onDocType($doctype); + + abstract public function onXmlDecl($decl); + + abstract public function onComment($data); + + abstract public function onCDATASection($data); + + abstract public function onProcessingInstruction($data); + + abstract public function onElementStart($element_qname, array $attributes); + + abstract public function onElementData($data); + + abstract public function onElementClose($qname); + + public function setSource($file, $line) + { + $this->file = $file; $this->line = $line; + } + + abstract public function setEncoding($encoding); +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/DocumentType.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/DocumentType.php new file mode 100644 index 0000000..38b49e4 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/DocumentType.php @@ -0,0 +1,33 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Document doctype representation. + * + * @package PHPTAL + * @subpackage Dom + */ +class PHPTAL_Dom_DocumentType extends PHPTAL_Dom_Node +{ + public function generateCode(PHPTAL_Php_CodeWriter $codewriter) + { + if ($codewriter->getOutputMode() === PHPTAL::HTML5) { + $codewriter->setDocType('<!DOCTYPE html>'); + } else { + $codewriter->setDocType($this->getValueEscaped()); + } + $codewriter->doDoctype(); + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/Element.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/Element.php new file mode 100644 index 0000000..574c830 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/Element.php @@ -0,0 +1,521 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * Document Tag representation. + * + * @package PHPTAL + * @subpackage Dom + */ +class PHPTAL_Dom_Element extends PHPTAL_Dom_Node +{ + protected $qualifiedName, $namespace_uri; + private $attribute_nodes = array(); + protected $replaceAttributes = array(); + protected $contentAttributes = array(); + protected $surroundAttributes = array(); + public $headFootDisabled = false; + public $headPrintCondition = false; + public $footPrintCondition = false; + public $hidden = false; + + // W3C DOM interface + public $childNodes = array(); + public $parentNode; + + /** + * @param string $qname qualified name of the element, e.g. "tal:block" + * @param string $namespace_uri namespace of this element + * @param array $attribute_nodes array of PHPTAL_Dom_Attr elements + * @param object $xmlns object that represents namespaces/prefixes known in element's context + */ + public function __construct($qname, $namespace_uri, array $attribute_nodes, PHPTAL_Dom_XmlnsState $xmlns) + { + $this->qualifiedName = $qname; + $this->attribute_nodes = $attribute_nodes; + $this->namespace_uri = $namespace_uri; + $this->xmlns = $xmlns; + + // implements inheritance of element's namespace to tal attributes (<metal: use-macro>) + foreach ($attribute_nodes as $index => $attr) { + // it'll work only when qname == localname, which is good + if ($this->xmlns->isValidAttributeNS($namespace_uri, $attr->getQualifiedName())) { + $this->attribute_nodes[$index] = new PHPTAL_Dom_Attr($attr->getQualifiedName(), $namespace_uri, $attr->getValueEscaped(), $attr->getEncoding()); + } + } + + if ($this->xmlns->isHandledNamespace($this->namespace_uri)) { + $this->headFootDisabled = true; + } + + $talAttributes = $this->separateAttributes(); + $this->orderTalAttributes($talAttributes); + } + + /** + * returns object that represents namespaces known in element's context + */ + public function getXmlnsState() + { + return $this->xmlns; + } + + /** + * Replace <script> foo &gt; bar </script> + * with <script>/*<![CDATA[* / foo > bar /*]]>* /</script> + * This avoids gotcha in text/html. + * + * Note that PHPTAL_Dom_CDATASection::generate() does reverse operation, if needed! + * + * @return void + */ + private function replaceTextWithCDATA() + { + $isCDATAelement = PHPTAL_Dom_Defs::getInstance()->isCDATAElementInHTML($this->getNamespaceURI(), $this->getLocalName()); + + if (!$isCDATAelement) { + return; + } + + $valueEscaped = ''; // sometimes parser generates split text nodes. "normalisation" is needed. + $value = ''; + foreach ($this->childNodes as $node) { + // leave it alone if there is CDATA, comment, or anything else. + if (!$node instanceof PHPTAL_Dom_Text) return; + + $value .= $node->getValue(); + $valueEscaped .= $node->getValueEscaped(); + + $encoding = $node->getEncoding(); // encoding of all nodes is the same + } + + // only add cdata if there are entities + // and there's no ${structure} (because it may rely on cdata syntax) + if (false === strpos($valueEscaped, '&') || preg_match('/<\?|\${structure/', $value)) { + return; + } + + $this->childNodes = array(); + + // appendChild sets parent + $this->appendChild(new PHPTAL_Dom_Text('/*', $encoding)); + $this->appendChild(new PHPTAL_Dom_CDATASection('*/'.$value.'/*', $encoding)); + $this->appendChild(new PHPTAL_Dom_Text('*/', $encoding)); + } + + public function appendChild(PHPTAL_Dom_Node $child) + { + if ($child->parentNode) $child->parentNode->removeChild($child); + $child->parentNode = $this; + $this->childNodes[] = $child; + } + + public function removeChild(PHPTAL_Dom_Node $child) + { + foreach ($this->childNodes as $k => $node) { + if ($child === $node) { + $child->parentNode = null; + array_splice($this->childNodes, $k, 1); + return; + } + } + throw new PHPTAL_Exception("Given node is not child of ".$this->getQualifiedName()); + } + + public function replaceChild(PHPTAL_Dom_Node $newElement, PHPTAL_Dom_Node $oldElement) + { + foreach ($this->childNodes as $k => $node) { + if ($node === $oldElement) { + $oldElement->parentNode = NULL; + + if ($newElement->parentNode) $newElement->parentNode->removeChild($child); + $newElement->parentNode = $this; + + $this->childNodes[$k] = $newElement; + return; + } + } + throw new PHPTAL_Exception("Given node is not child of ".$this->getQualifiedName()); + } + + public function generateCode(PHPTAL_Php_CodeWriter $codewriter) + { + try + { + /// self-modifications + + if ($codewriter->getOutputMode() === PHPTAL::XHTML) { + $this->replaceTextWithCDATA(); + } + + /// code generation + + if ($this->getSourceLine()) { + $codewriter->doComment('tag "'.$this->qualifiedName.'" from line '.$this->getSourceLine()); + } + + $this->generateSurroundHead($codewriter); + + if (count($this->replaceAttributes)) { + foreach ($this->replaceAttributes as $att) { + $att->before($codewriter); + $att->after($codewriter); + } + } elseif (!$this->hidden) { + // a surround tag may decide to hide us (tal:define for example) + $this->generateHead($codewriter); + $this->generateContent($codewriter); + $this->generateFoot($codewriter); + } + + $this->generateSurroundFoot($codewriter); + } + catch(PHPTAL_TemplateException $e) { + $e->hintSrcPosition($this->getSourceFile(), $this->getSourceLine()); + throw $e; + } + } + + /** + * Array with PHPTAL_Dom_Attr objects + * + * @return array + */ + public function getAttributeNodes() + { + return $this->attribute_nodes; + } + + /** + * Replace all attributes + * + * @param array $nodes array of PHPTAL_Dom_Attr objects + */ + public function setAttributeNodes(array $nodes) + { + $this->attribute_nodes = $nodes; + } + + /** Returns true if the element contains specified PHPTAL attribute. */ + public function hasAttribute($qname) + { + foreach($this->attribute_nodes as $attr) if ($attr->getQualifiedName() == $qname) return true; + return false; + } + + public function hasAttributeNS($ns_uri, $localname) + { + return null !== $this->getAttributeNodeNS($ns_uri, $localname); + } + + public function getAttributeNodeNS($ns_uri, $localname) + { + foreach ($this->attribute_nodes as $attr) { + if ($attr->getNamespaceURI() === $ns_uri && $attr->getLocalName() === $localname) return $attr; + } + return null; + } + + public function removeAttributeNS($ns_uri, $localname) + { + foreach ($this->attribute_nodes as $k => $attr) { + if ($attr->getNamespaceURI() === $ns_uri && $attr->getLocalName() === $localname) { + unset($this->attribute_nodes[$k]); + return; + } + } + } + + public function getAttributeNode($qname) + { + foreach($this->attribute_nodes as $attr) if ($attr->getQualifiedName() === $qname) return $attr; + return null; + } + + /** + * If possible, use getAttributeNodeNS and setAttributeNS. + * + * NB: This method doesn't handle namespaces properly. + */ + public function getOrCreateAttributeNode($qname) + { + if ($attr = $this->getAttributeNode($qname)) return $attr; + + $attr = new PHPTAL_Dom_Attr($qname, "", null, 'UTF-8'); // FIXME: should find namespace and encoding + $this->attribute_nodes[] = $attr; + return $attr; + } + + /** Returns textual (unescaped) value of specified element attribute. */ + public function getAttributeNS($namespace_uri, $localname) + { + if ($n = $this->getAttributeNodeNS($namespace_uri, $localname)) { + return $n->getValue(); + } + return ''; + } + + /** + * Set attribute value. Creates new attribute if it doesn't exist yet. + * + * @param string $namespace_uri full namespace URI. "" for default namespace + * @param string $qname prefixed qualified name (e.g. "atom:feed") or local name (e.g. "p") + * @param string $value unescaped value + * + * @return void + */ + public function setAttributeNS($namespace_uri, $qname, $value) + { + $localname = preg_replace('/^[^:]*:/', '', $qname); + if (!($n = $this->getAttributeNodeNS($namespace_uri, $localname))) { + $this->attribute_nodes[] = $n = new PHPTAL_Dom_Attr($qname, $namespace_uri, null, 'UTF-8'); // FIXME: find encoding + } + $n->setValue($value); + } + + /** + * Returns true if this element or one of its PHPTAL attributes has some + * content to print (an empty text node child does not count). + * + * @return bool + */ + public function hasRealContent() + { + if (count($this->contentAttributes) > 0) return true; + + foreach ($this->childNodes as $node) { + if (!$node instanceof PHPTAL_Dom_Text || $node->getValueEscaped() !== '') return true; + } + return false; + } + + public function hasRealAttributes() + { + if ($this->hasAttributeNS('http://xml.zope.org/namespaces/tal', 'attributes')) return true; + foreach ($this->attribute_nodes as $attr) { + if ($attr->getReplacedState() !== PHPTAL_Dom_Attr::HIDDEN) return true; + } + return false; + } + + // ~~~~~ Generation methods may be called by some PHPTAL attributes ~~~~~ + + public function generateSurroundHead(PHPTAL_Php_CodeWriter $codewriter) + { + foreach ($this->surroundAttributes as $att) { + $att->before($codewriter); + } + } + + public function generateHead(PHPTAL_Php_CodeWriter $codewriter) + { + if ($this->headFootDisabled) return; + if ($this->headPrintCondition) { + $codewriter->doIf($this->headPrintCondition); + } + + $html5mode = ($codewriter->getOutputMode() === PHPTAL::HTML5); + + if ($html5mode) { + $codewriter->pushHTML('<'.$this->getLocalName()); + } else { + $codewriter->pushHTML('<'.$this->qualifiedName); + } + + $this->generateAttributes($codewriter); + + if (!$html5mode && $this->isEmptyNode($codewriter->getOutputMode())) { + $codewriter->pushHTML('/>'); + } else { + $codewriter->pushHTML('>'); + } + + if ($this->headPrintCondition) { + $codewriter->doEnd('if'); + } + } + + public function generateContent(PHPTAL_Php_CodeWriter $codewriter = null, $realContent=false) + { + if (!$this->isEmptyNode($codewriter->getOutputMode())) { + if ($realContent || !count($this->contentAttributes)) { + foreach($this->childNodes as $child) { + $child->generateCode($codewriter); + } + } + else foreach($this->contentAttributes as $att) { + $att->before($codewriter); + $att->after($codewriter); + } + } + } + + public function generateFoot(PHPTAL_Php_CodeWriter $codewriter) + { + if ($this->headFootDisabled) + return; + if ($this->isEmptyNode($codewriter->getOutputMode())) + return; + + if ($this->footPrintCondition) { + $codewriter->doIf($this->footPrintCondition); + } + + if ($codewriter->getOutputMode() === PHPTAL::HTML5) { + $codewriter->pushHTML('</'.$this->getLocalName().'>'); + } else { + $codewriter->pushHTML('</'.$this->getQualifiedName().'>'); + } + + if ($this->footPrintCondition) { + $codewriter->doEnd('if'); + } + } + + public function generateSurroundFoot(PHPTAL_Php_CodeWriter $codewriter) + { + for ($i = (count($this->surroundAttributes)-1); $i >= 0; $i--) { + $this->surroundAttributes[$i]->after($codewriter); + } + } + + // ~~~~~ Private members ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + private function generateAttributes(PHPTAL_Php_CodeWriter $codewriter) + { + $html5mode = ($codewriter->getOutputMode() === PHPTAL::HTML5); + + foreach ($this->getAttributeNodes() as $attr) { + + // xmlns:foo is not allowed in text/html + if ($html5mode && $attr->isNamespaceDeclaration()) { + continue; + } + + switch ($attr->getReplacedState()) { + case PHPTAL_Dom_Attr::NOT_REPLACED: + $codewriter->pushHTML(' '.$attr->getQualifiedName()); + if ($codewriter->getOutputMode() !== PHPTAL::HTML5 + || !PHPTAL_Dom_Defs::getInstance()->isBooleanAttribute($attr->getQualifiedName())) { + $html = $codewriter->interpolateHTML($attr->getValueEscaped()); + $codewriter->pushHTML('='.$codewriter->quoteAttributeValue($html)); + } + break; + + case PHPTAL_Dom_Attr::HIDDEN: + break; + + case PHPTAL_Dom_Attr::FULLY_REPLACED: + $codewriter->pushHTML($attr->getValueEscaped()); + break; + + case PHPTAL_Dom_Attr::VALUE_REPLACED: + $codewriter->pushHTML(' '.$attr->getQualifiedName().'="'); + $codewriter->pushHTML($attr->getValueEscaped()); + $codewriter->pushHTML('"'); + break; + } + } + } + + private function isEmptyNode($mode) + { + return (($mode === PHPTAL::XHTML || $mode === PHPTAL::HTML5) && PHPTAL_Dom_Defs::getInstance()->isEmptyTagNS($this->getNamespaceURI(), $this->getLocalName())) || + ( $mode === PHPTAL::XML && !$this->hasContent()); + } + + private function hasContent() + { + return count($this->childNodes) > 0 || count($this->contentAttributes) > 0; + } + + private function separateAttributes() + { + $talAttributes = array(); + foreach ($this->attribute_nodes as $index => $attr) { + // remove handled xml namespaces + if (PHPTAL_Dom_Defs::getInstance()->isHandledXmlNs($attr->getQualifiedName(), $attr->getValueEscaped())) { + unset($this->attribute_nodes[$index]); + } else if ($this->xmlns->isHandledNamespace($attr->getNamespaceURI())) { + $talAttributes[$attr->getQualifiedName()] = $attr; + $attr->hide(); + } else if (PHPTAL_Dom_Defs::getInstance()->isBooleanAttribute($attr->getQualifiedName())) { + $attr->setValue($attr->getLocalName()); + } + } + return $talAttributes; + } + + private function orderTalAttributes(array $talAttributes) + { + $temp = array(); + foreach ($talAttributes as $key => $domattr) { + $nsattr = PHPTAL_Dom_Defs::getInstance()->getNamespaceAttribute($domattr->getNamespaceURI(), $domattr->getLocalName()); + if (array_key_exists($nsattr->getPriority(), $temp)) { + throw new PHPTAL_TemplateException(sprintf("Attribute conflict in < %s > '%s' cannot appear with '%s'", + $this->qualifiedName, + $key, + $temp[$nsattr->getPriority()][0]->getNamespace()->getPrefix() . ':' . $temp[$nsattr->getPriority()][0]->getLocalName() + ), $this->getSourceFile(), $this->getSourceLine()); + } + $temp[$nsattr->getPriority()] = array($nsattr, $domattr); + } + ksort($temp); + + $this->talHandlers = array(); + foreach ($temp as $prio => $dat) { + list($nsattr, $domattr) = $dat; + $handler = $nsattr->createAttributeHandler($this, $domattr->getValue()); + $this->talHandlers[$prio] = $handler; + + if ($nsattr instanceof PHPTAL_NamespaceAttributeSurround) + $this->surroundAttributes[] = $handler; + else if ($nsattr instanceof PHPTAL_NamespaceAttributeReplace) + $this->replaceAttributes[] = $handler; + else if ($nsattr instanceof PHPTAL_NamespaceAttributeContent) + $this->contentAttributes[] = $handler; + else + throw new PHPTAL_ParserException("Unknown namespace attribute class ".get_class($nsattr), + $this->getSourceFile(), $this->getSourceLine()); + + } + } + + function getQualifiedName() + { + return $this->qualifiedName; + } + + function getNamespaceURI() + { + return $this->namespace_uri; + } + + function getLocalName() + { + $n = explode(':', $this->qualifiedName, 2); + return end($n); + } + + function __toString() + { + return '<{'.$this->getNamespaceURI().'}:'.$this->getLocalName().'>'; + } + + function setValueEscaped($e) { + throw new PHPTAL_Exception("Not supported"); + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/Node.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/Node.php new file mode 100644 index 0000000..5858df6 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/Node.php @@ -0,0 +1,105 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Document node abstract class. + * + * @package PHPTAL + * @subpackage Dom + */ +abstract class PHPTAL_Dom_Node +{ + public $parentNode; + + private $value_escaped, $source_file, $source_line, $encoding; + + public function __construct($value_escaped, $encoding) + { + $this->value_escaped = $value_escaped; + $this->encoding = $encoding; + } + + /** + * hint where this node is in source code + */ + public function setSource($file, $line) + { + $this->source_file = $file; + $this->source_line = $line; + } + + /** + * file from which this node comes from + */ + public function getSourceFile() + { + return $this->source_file; + } + + /** + * line on which this node was defined + */ + public function getSourceLine() + { + return $this->source_line; + } + + /** + * depends on node type. Value will be escaped according to context that node comes from. + */ + function getValueEscaped() + { + return $this->value_escaped; + } + + /** + * Set value of the node (type-dependent) to this exact string. + * String must be HTML-escaped and use node's encoding. + * + * @param string $value_escaped new content + */ + function setValueEscaped($value_escaped) + { + $this->value_escaped = $value_escaped; + } + + + /** + * get value as plain text. Depends on node type. + */ + function getValue() + { + return html_entity_decode($this->getValueEscaped(), ENT_QUOTES, $this->encoding); + } + + /** + * encoding used by vaule of this node. + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * use CodeWriter to compile this element to PHP code + */ + public abstract function generateCode(PHPTAL_Php_CodeWriter $gen); + + function __toString() + { + return " “".$this->getValue()."†"; + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/PHPTALDocumentBuilder.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/PHPTALDocumentBuilder.php new file mode 100644 index 0000000..a3157be --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/PHPTALDocumentBuilder.php @@ -0,0 +1,167 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * DOM Builder + * + * @package PHPTAL + * @subpackage Dom + */ +class PHPTAL_Dom_PHPTALDocumentBuilder extends PHPTAL_Dom_DocumentBuilder +{ + private $_xmlns; /* PHPTAL_Dom_XmlnsState */ + private $encoding; + + public function __construct() + { + $this->_xmlns = new PHPTAL_Dom_XmlnsState(array(), ''); + } + + public function getResult() + { + return $this->documentElement; + } + + protected function getXmlnsState() + { + return $this->_xmlns; + } + + // ~~~~~ XmlParser implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + public function onDocumentStart() + { + $this->documentElement = new PHPTAL_Dom_Element('documentElement', 'http://xml.zope.org/namespaces/tal', array(), $this->getXmlnsState()); + $this->documentElement->setSource($this->file, $this->line); + $this->_current = $this->documentElement; + } + + public function onDocumentEnd() + { + if (count($this->_stack) > 0) { + $left='</'.$this->_current->getQualifiedName().'>'; + for ($i = count($this->_stack)-1; $i>0; $i--) $left .= '</'.$this->_stack[$i]->getQualifiedName().'>'; + throw new PHPTAL_ParserException("Not all elements were closed before end of the document. Missing: ".$left, + $this->file, $this->line); + } + } + + public function onDocType($doctype) + { + $this->pushNode(new PHPTAL_Dom_DocumentType($doctype, $this->encoding)); + } + + public function onXmlDecl($decl) + { + if (!$this->encoding) { + throw new PHPTAL_Exception("Encoding not set"); + } + $this->pushNode(new PHPTAL_Dom_XmlDeclaration($decl, $this->encoding)); + } + + public function onComment($data) + { + $this->pushNode(new PHPTAL_Dom_Comment($data, $this->encoding)); + } + + public function onCDATASection($data) + { + $this->pushNode(new PHPTAL_Dom_CDATASection($data, $this->encoding)); + } + + public function onProcessingInstruction($data) + { + $this->pushNode(new PHPTAL_Dom_ProcessingInstruction($data, $this->encoding)); + } + + public function onElementStart($element_qname, array $attributes) + { + $this->_xmlns = $this->_xmlns->newElement($attributes); + + if (preg_match('/^([^:]+):/', $element_qname, $m)) { + $prefix = $m[1]; + $namespace_uri = $this->_xmlns->prefixToNamespaceURI($prefix); + if (false === $namespace_uri) { + throw new PHPTAL_ParserException("There is no namespace declared for prefix of element < $element_qname >. You must have xmlns:$prefix declaration in the same document.", + $this->file, $this->line); + } + } else { + $namespace_uri = $this->_xmlns->getCurrentDefaultNamespaceURI(); + } + + $attrnodes = array(); + foreach ($attributes as $qname=>$value) { + + if (preg_match('/^([^:]+):(.+)$/', $qname, $m)) { + list(,$prefix, $local_name) = $m; + $attr_namespace_uri = $this->_xmlns->prefixToNamespaceURI($prefix); + + if (false === $attr_namespace_uri) { + throw new PHPTAL_ParserException("There is no namespace declared for prefix of attribute $qname of element < $element_qname >. You must have xmlns:$prefix declaration in the same document.", + $this->file, $this->line); + } + } else { + $local_name = $qname; + $attr_namespace_uri = ''; // default NS. Attributes don't inherit namespace per XMLNS spec + } + + if ($this->_xmlns->isHandledNamespace($attr_namespace_uri) + && !$this->_xmlns->isValidAttributeNS($attr_namespace_uri, $local_name)) { + throw new PHPTAL_ParserException("Attribute '$qname' is in '$attr_namespace_uri' namespace, but is not a supported PHPTAL attribute", + $this->file, $this->line); + } + + $attrnodes[] = new PHPTAL_Dom_Attr($qname, $attr_namespace_uri, $value, $this->encoding); + } + + $node = new PHPTAL_Dom_Element($element_qname, $namespace_uri, $attrnodes, $this->getXmlnsState()); + $this->pushNode($node); + $this->_stack[] = $this->_current; + $this->_current = $node; + } + + public function onElementData($data) + { + $this->pushNode(new PHPTAL_Dom_Text($data, $this->encoding)); + } + + public function onElementClose($qname) + { + if ($this->_current === $this->documentElement) { + throw new PHPTAL_ParserException("Found closing tag for < $qname > where there are no open tags", + $this->file, $this->line); + } + if ($this->_current->getQualifiedName() != $qname) { + throw new PHPTAL_ParserException("Tag closure mismatch, expected < /".$this->_current->getQualifiedName()." > (opened in line ".$this->_current->getSourceLine().") but found < /".$qname." >", + $this->file, $this->line); + } + $this->_current = array_pop($this->_stack); + if ($this->_current instanceof PHPTAL_Dom_Element) { + $this->_xmlns = $this->_current->getXmlnsState(); // restore namespace prefixes info to previous state + } + } + + private function pushNode(PHPTAL_Dom_Node $node) + { + $node->setSource($this->file, $this->line); + $this->_current->appendChild($node); + } + + public function setEncoding($encoding) + { + $this->encoding = $encoding; + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/ProcessingInstruction.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/ProcessingInstruction.php new file mode 100644 index 0000000..552462c --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/ProcessingInstruction.php @@ -0,0 +1,34 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * processing instructions, including <?php blocks + * + * @package PHPTAL + * @subpackage Dom + */ +class PHPTAL_Dom_ProcessingInstruction extends PHPTAL_Dom_Node +{ + public function generateCode(PHPTAL_Php_CodeWriter $codewriter) + { + if (preg_match('/^<\?(?:php|[=\s])/i', $this->getValueEscaped())) { + // block will be executed as PHP + $codewriter->pushHTML($this->getValueEscaped()); + } else { + $codewriter->doEchoRaw("'<'"); + $codewriter->pushHTML(substr($codewriter->interpolateHTML($this->getValueEscaped()), 1)); + } + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/SaxXmlParser.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/SaxXmlParser.php new file mode 100644 index 0000000..b59a26d --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/SaxXmlParser.php @@ -0,0 +1,480 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Simple sax like xml parser for PHPTAL + * ("Dom" in the class name comes from name of the directory, not mode of operation) + * + * At the time this parser was created, standard PHP libraries were not suitable + * (could not retrieve doctypes, xml declaration, problems with comments and CDATA). + * + * There are still some problems: XML parsers don't care about exact format of enties + * or CDATA sections (PHPTAL tries to preserve them), + * <?php ?> blocks are not allowed in attributes. + * + * This parser failed to enforce some XML well-formedness constraints, + * and there are ill-formed templates "in the wild" because of this. + * + * @package PHPTAL + * @subpackage Dom + * @see PHPTAL_DOM_DocumentBuilder + */ +class PHPTAL_Dom_SaxXmlParser +{ + private $_file; + private $_line; + private $_source; + + // available parser states + const ST_ROOT = 0; + const ST_TEXT = 1; + const ST_LT = 2; + const ST_TAG_NAME = 3; + const ST_TAG_CLOSE = 4; + const ST_TAG_SINGLE = 5; + const ST_TAG_ATTRIBUTES = 6; + const ST_TAG_BETWEEN_ATTRIBUTE = 7; + const ST_CDATA = 8; + const ST_COMMENT = 9; + const ST_DOCTYPE = 10; + const ST_XMLDEC = 11; + const ST_PREPROC = 12; + const ST_ATTR_KEY = 13; + const ST_ATTR_EQ = 14; + const ST_ATTR_QUOTE = 15; + const ST_ATTR_VALUE = 16; + + const BOM_STR = "\xef\xbb\xbf"; + + + static $state_names = array( + self::ST_ROOT => 'root node', + self::ST_TEXT => 'text', + self::ST_LT => 'start of tag', + self::ST_TAG_NAME => 'tag name', + self::ST_TAG_CLOSE => 'closing tag', + self::ST_TAG_SINGLE => 'self-closing tag', + self::ST_TAG_ATTRIBUTES => 'tag', + self::ST_TAG_BETWEEN_ATTRIBUTE => 'tag attributes', + self::ST_CDATA => 'CDATA', + self::ST_COMMENT => 'comment', + self::ST_DOCTYPE => 'doctype', + self::ST_XMLDEC => 'XML declaration', + self::ST_PREPROC => 'preprocessor directive', + self::ST_ATTR_KEY => 'attribute name', + self::ST_ATTR_EQ => 'attribute value', + self::ST_ATTR_QUOTE => 'quoted attribute value', + self::ST_ATTR_VALUE => 'unquoted attribute value', + ); + + private $input_encoding; + public function __construct($input_encoding) + { + $this->input_encoding = $input_encoding; + $this->_file = "<string>"; + } + + public function parseFile(PHPTAL_Dom_DocumentBuilder $builder, $src) + { + if (!file_exists($src)) { + throw new PHPTAL_IOException("file $src not found"); + } + return $this->parseString($builder, file_get_contents($src), $src); + } + + public function parseString(PHPTAL_Dom_DocumentBuilder $builder, $src, $filename = '<string>') + { + try + { + $builder->setEncoding($this->input_encoding); + $this->_file = $filename; + + $this->_line = 1; + $state = self::ST_ROOT; + $mark = 0; + $len = strlen($src); + + $quoteStyle = '"'; + $tagname = ""; + $attribute = ""; + $attributes = array(); + + $customDoctype = false; + + $builder->setSource($this->_file, $this->_line); + $builder->onDocumentStart(); + + $i=0; + // remove BOM (UTF-8 byte order mark)... + if (substr($src, 0, 3) === self::BOM_STR) { + $i=3; + } + for (; $i<$len; $i++) { + $c = $src[$i]; // Change to substr($src, $i, 1); if you want to use mb_string.func_overload + + if ($c === "\n") $builder->setSource($this->_file, ++$this->_line); + + switch ($state) { + case self::ST_ROOT: + if ($c === '<') { + $mark = $i; // mark tag start + $state = self::ST_LT; + } elseif (!self::isWhiteChar($c)) { + $this->raiseError("Characters found before beginning of the document! (wrap document in < tal:block > to avoid this error)"); + } + break; + + case self::ST_TEXT: + if ($c === '<') { + if ($mark != $i) { + $builder->onElementData($this->sanitizeEscapedText($this->checkEncoding(substr($src, $mark, $i-$mark)))); + } + $mark = $i; + $state = self::ST_LT; + } + break; + + case self::ST_LT: + if ($c === '/') { + $mark = $i+1; + $state = self::ST_TAG_CLOSE; + } elseif ($c === '?' and strtolower(substr($src, $i, 5)) === '?xml ') { + $state = self::ST_XMLDEC; + } elseif ($c === '?') { + $state = self::ST_PREPROC; + } elseif ($c === '!' and substr($src, $i, 3) === '!--') { + $state = self::ST_COMMENT; + } elseif ($c === '!' and substr($src, $i, 8) === '![CDATA[') { + $state = self::ST_CDATA; + $mark = $i+8; // past opening tag + } elseif ($c === '!' and strtoupper(substr($src, $i, 8)) === '!DOCTYPE') { + $state = self::ST_DOCTYPE; + } elseif (self::isWhiteChar($c)) { + $state = self::ST_TEXT; + } else { + $mark = $i; // mark node name start + $attributes = array(); + $attribute = ""; + $state = self::ST_TAG_NAME; + } + break; + + case self::ST_TAG_NAME: + if (self::isWhiteChar($c) || $c === '/' || $c === '>') { + $tagname = substr($src, $mark, $i-$mark); + if (!$this->isValidQName($tagname)) $this->raiseError("Invalid tag name '$tagname'"); + + if ($c === '/') { + $state = self::ST_TAG_SINGLE; + } elseif ($c === '>') { + $mark = $i+1; // mark text start + $state = self::ST_TEXT; + $builder->onElementStart($tagname, $attributes); + } else /* isWhiteChar */ { + $state = self::ST_TAG_ATTRIBUTES; + } + } + break; + + case self::ST_TAG_CLOSE: + if ($c === '>') { + $tagname = rtrim(substr($src, $mark, $i-$mark)); + $builder->onElementClose($tagname); + $mark = $i+1; // mark text start + $state = self::ST_TEXT; + } + break; + + case self::ST_TAG_SINGLE: + if ($c !== '>') { + $this->raiseError("Expected '/>', but found '/$c' inside tag < $tagname >"); + } + $mark = $i+1; // mark text start + $state = self::ST_TEXT; + $builder->onElementStart($tagname, $attributes); + $builder->onElementClose($tagname); + break; + + case self::ST_TAG_BETWEEN_ATTRIBUTE: + case self::ST_TAG_ATTRIBUTES: + if ($c === '>') { + $mark = $i+1; // mark text start + $state = self::ST_TEXT; + $builder->onElementStart($tagname, $attributes); + } elseif ($c === '/') { + $state = self::ST_TAG_SINGLE; + } elseif (self::isWhiteChar($c)) { + $state = self::ST_TAG_ATTRIBUTES; + } elseif ($state === self::ST_TAG_ATTRIBUTES && $this->isValidQName($c)) { + $mark = $i; // mark attribute key start + $state = self::ST_ATTR_KEY; + } else $this->raiseError("Unexpected character '$c' between attributes of < $tagname >"); + break; + + case self::ST_COMMENT: + if ($c === '>' && $i > $mark+4 && substr($src, $i-2, 2) === '--') { + + if (preg_match('/^-|--|-$/', substr($src, $mark +4, $i-$mark+1 -7))) { + $this->raiseError("Ill-formed comment. XML comments are not allowed to contain '--' or start/end with '-': ".substr($src, $mark+4, $i-$mark+1-7)); + } + + $builder->onComment($this->checkEncoding(substr($src, $mark+4, $i-$mark+1-7))); + $mark = $i+1; // mark text start + $state = self::ST_TEXT; + } + break; + + case self::ST_CDATA: + if ($c === '>' and substr($src, $i-2, 2) === ']]') { + $builder->onCDATASection($this->checkEncoding(substr($src, $mark, $i-$mark-2))); + $mark = $i+1; // mark text start + $state = self::ST_TEXT; + } + break; + + case self::ST_XMLDEC: + if ($c === '?' && substr($src, $i, 2) === '?>') { + $builder->onXmlDecl($this->checkEncoding(substr($src, $mark, $i-$mark+2))); + $i++; // skip '>' + $mark = $i+1; // mark text start + $state = self::ST_TEXT; + } + break; + + case self::ST_DOCTYPE: + if ($c === '[') { + $customDoctype = true; + } elseif ($customDoctype && $c === '>' && substr($src, $i-1, 2) === ']>') { + $customDoctype = false; + $builder->onDocType($this->checkEncoding(substr($src, $mark, $i-$mark+1))); + $mark = $i+1; // mark text start + $state = self::ST_TEXT; + } elseif (!$customDoctype && $c === '>') { + $customDoctype = false; + $builder->onDocType($this->checkEncoding(substr($src, $mark, $i-$mark+1))); + $mark = $i+1; // mark text start + $state = self::ST_TEXT; + } + break; + + case self::ST_PREPROC: + if ($c === '>' and substr($src, $i-1, 1) === '?') { + $builder->onProcessingInstruction($this->checkEncoding(substr($src, $mark, $i-$mark+1))); + $mark = $i+1; // mark text start + $state = self::ST_TEXT; + } + break; + + case self::ST_ATTR_KEY: + if ($c === '=' || self::isWhiteChar($c)) { + $attribute = substr($src, $mark, $i-$mark); + if (!$this->isValidQName($attribute)) { + $this->raiseError("Invalid attribute name '$attribute' in < $tagname >"); + } + if (isset($attributes[$attribute])) { + $this->raiseError("Attribute $attribute in < $tagname > is defined more than once"); + } + + if ($c === '=') $state = self::ST_ATTR_VALUE; + else /* white char */ $state = self::ST_ATTR_EQ; + } elseif ($c === '/' || $c==='>') { + $attribute = substr($src, $mark, $i-$mark); + if (!$this->isValidQName($attribute)) { + $this->raiseError("Invalid attribute name '$attribute'"); + } + $this->raiseError("Attribute $attribute does not have value (found end of tag instead of '=')"); + } + break; + + case self::ST_ATTR_EQ: + if ($c === '=') { + $state = self::ST_ATTR_VALUE; + } elseif (!self::isWhiteChar($c)) { + $this->raiseError("Attribute $attribute in < $tagname > does not have value (found character '$c' instead of '=')"); + } + break; + + case self::ST_ATTR_VALUE: + if (self::isWhiteChar($c)) { + } elseif ($c === '"' or $c === '\'') { + $quoteStyle = $c; + $state = self::ST_ATTR_QUOTE; + $mark = $i+1; // mark attribute real value start + } else { + $this->raiseError("Value of attribute $attribute in < $tagname > is not in quotes (found character '$c' instead of quote)"); + } + break; + + case self::ST_ATTR_QUOTE: + if ($c === $quoteStyle) { + $attributes[$attribute] = $this->sanitizeEscapedText($this->checkEncoding(substr($src, $mark, $i-$mark))); + + // PHPTAL's code generator assumes input is escaped for double-quoted strings. Single-quoted attributes need to be converted. + // FIXME: it should be escaped at later stage. + $attributes[$attribute] = str_replace('"',"&quot;", $attributes[$attribute]); + $state = self::ST_TAG_BETWEEN_ATTRIBUTE; + } + break; + } + } + + if ($state === self::ST_TEXT) // allows text past root node, which is in violation of XML spec + { + if ($i > $mark) { + $text = substr($src, $mark, $i-$mark); + if (!ctype_space($text)) $this->raiseError("Characters found after end of the root element (wrap document in < tal:block > to avoid this error)"); + } + } else { + if ($state === self::ST_ROOT) { + $msg = "Document does not have any tags"; + } else { + $msg = "Finished document in unexpected state: ".self::$state_names[$state]." is not finished"; + } + $this->raiseError($msg); + } + + $builder->onDocumentEnd(); + } + catch(PHPTAL_TemplateException $e) + { + $e->hintSrcPosition($this->_file, $this->_line); + throw $e; + } + return $builder; + } + + private function isValidQName($name) + { + $name = $this->checkEncoding($name); + return preg_match('/^([a-z_\x80-\xff]+[a-z0-9._\x80-\xff-]*:)?[a-z_\x80-\xff]+[a-z0-9._\x80-\xff-]*$/i', $name); + } + + private function checkEncoding($str) + { + if ($str === '') return ''; + + if ($this->input_encoding === 'UTF-8') { + + // $match expression below somehow triggers quite deep recurrency and stack overflow in preg + // to avoid this, check string bit by bit, omitting ASCII fragments. + if (strlen($str) > 200) { + $chunks = preg_split('/(?>[\x09\x0A\x0D\x20-\x7F]+)/',$str,null,PREG_SPLIT_NO_EMPTY); + foreach ($chunks as $chunk) { + if (strlen($chunk) < 200) { + $this->checkEncoding($chunk); + } + } + return $str; + } + + // http://www.w3.org/International/questions/qa-forms-utf-8 + $match = '[\x09\x0A\x0D\x20-\x7F]' // ASCII + . '|[\xC2-\xDF][\x80-\xBF]' // non-overlong 2-byte + . '|\xE0[\xA0-\xBF][\x80-\xBF]' // excluding overlongs + . '|[\xE1-\xEC\xEE\xEE][\x80-\xBF]{2}' // straight 3-byte (exclude FFFE and FFFF) + . '|\xEF[\x80-\xBE][\x80-\xBF]' // straight 3-byte + . '|\xEF\xBF[\x80-\xBD]' // straight 3-byte + . '|\xED[\x80-\x9F][\x80-\xBF]' // excluding surrogates + . '|\xF0[\x90-\xBF][\x80-\xBF]{2}' // planes 1-3 + . '|[\xF1-\xF3][\x80-\xBF]{3}' // planes 4-15 + . '|\xF4[\x80-\x8F][\x80-\xBF]{2}'; // plane 16 + + if (!preg_match('/^(?:(?>'.$match.'))+$/s',$str)) { + $res = preg_split('/((?>'.$match.')+)/s',$str,null,PREG_SPLIT_DELIM_CAPTURE); + for($i=0; $i < count($res); $i+=2) + { + $res[$i] = self::convertBytesToEntities(array(1=>$res[$i])); + } + $this->raiseError("Invalid UTF-8 bytes: ".implode('', $res)); + } + } + if ($this->input_encoding === 'ISO-8859-1') { + + // http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-RestrictedChar + $forbid = '/((?>[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F]+))/s'; + + if (preg_match($forbid, $str)) { + $str = preg_replace_callback($forbid, array('self', 'convertBytesToEntities'), $str); + $this->raiseError("Invalid ISO-8859-1 characters: ".$str); + } + } + + return $str; + } + + /** + * preg callback + * Changes all bytes to hexadecimal XML entities + * + * @param array $m first array element is used for input + * + * @return string + */ + private static function convertBytesToEntities(array $m) + { + $m = $m[1]; $out = ''; + for($i=0; $i < strlen($m); $i++) + { + $out .= '&#X'.strtoupper(dechex(ord($m[$i]))).';'; + } + return $out; + } + + /** + * This is where this parser violates XML and refuses to be an annoying bastard. + */ + private function sanitizeEscapedText($str) + { + $str = str_replace('&apos;', '&#39;', $str); // PHP's html_entity_decode doesn't seem to support that! + + /* <?php ?> blocks can't reliably work in attributes (due to escaping impossible in XML) + so they have to be converted into special TALES expression + */ + $types = ini_get('short_open_tag')?'php|=|':'php'; + $str = preg_replace_callback("/<\?($types)(.*?)\?>/", array('self', 'convertPHPBlockToTALES'), $str); + + // corrects all non-entities and neutralizes potentially problematic CDATA end marker + $str = strtr(preg_replace('/&(?!(?:#x?[a-f0-9]+|[a-z][a-z0-9]*);)/i', '&amp;', $str), array('<'=>'&lt;', ']]>'=>']]&gt;')); + + return $str; + } + + private static function convertPHPBlockToTALES($m) + { + list(, $type, $code) = $m; + if ($type === '=') $code = 'echo '.$code; + return '${structure phptal-internal-php-block:'.rawurlencode($code).'}'; + } + + public function getSourceFile() + { + return $this->_file; + } + + public function getLineNumber() + { + return $this->_line; + } + + public static function isWhiteChar($c) + { + return strpos(" \t\n\r\0", $c) !== false; + } + + protected function raiseError($errStr) + { + throw new PHPTAL_ParserException($errStr, $this->_file, $this->_line); + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/Text.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/Text.php new file mode 100644 index 0000000..f8ef2ab --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/Text.php @@ -0,0 +1,31 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * Document text data representation. + * + * @package PHPTAL + * @subpackage Dom + */ +class PHPTAL_Dom_Text extends PHPTAL_Dom_Node +{ + public function generateCode(PHPTAL_Php_CodeWriter $codewriter) + { + if ($this->getValueEscaped() !== '') { + $codewriter->pushHTML($codewriter->interpolateHTML($this->getValueEscaped())); + } + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/XmlDeclaration.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/XmlDeclaration.php new file mode 100644 index 0000000..e28dfb9 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/XmlDeclaration.php @@ -0,0 +1,29 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * XML declaration node. + * + * @package PHPTAL + * @subpackage Dom + */ +class PHPTAL_Dom_XmlDeclaration extends PHPTAL_Dom_Node +{ + public function generateCode(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->setXmlDeclaration($this->getValueEscaped()); + $codewriter->doXmlDeclaration(); + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Dom/XmlnsState.php b/src/core/libs/PHPTAL5/PHPTAL/Dom/XmlnsState.php new file mode 100644 index 0000000..4e9288f --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Dom/XmlnsState.php @@ -0,0 +1,95 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ +/** + * Stores XMLNS aliases fluctuation in the xml flow. + * + * This class is used to bind a PHPTAL namespace to an alias, for example using + * xmlns:t="http://xml.zope.org/namespaces/tal" and later use t:repeat instead + * of tal:repeat. + * + * @package PHPTAL + * @subpackage Dom + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Dom_XmlnsState +{ + /** Create a new XMLNS state inheriting provided aliases. */ + public function __construct(array $prefix_to_uri, $current_default) + { + $this->prefix_to_uri = $prefix_to_uri; + $this->current_default = $current_default; + } + + public function prefixToNamespaceURI($prefix) + { + if ($prefix === 'xmlns') return 'http://www.w3.org/2000/xmlns/'; + if ($prefix === 'xml') return 'http://www.w3.org/XML/1998/namespace'; + + // domdefs provides fallback for all known phptal ns + if (isset($this->prefix_to_uri[$prefix])) { + return $this->prefix_to_uri[$prefix]; + } else { + return PHPTAL_Dom_Defs::getInstance()->prefixToNamespaceURI($prefix); + } + } + + /** Returns true if $attName is a valid attribute name, false otherwise. */ + public function isValidAttributeNS($namespace_uri, $local_name) + { + return PHPTAL_Dom_Defs::getInstance()->isValidAttributeNS($namespace_uri, $local_name); + } + + public function isHandledNamespace($namespace_uri) + { + return PHPTAL_Dom_Defs::getInstance()->isHandledNamespace($namespace_uri); + } + + /** + * Returns a new XmlnsState inheriting of $this if $nodeAttributes contains + * xmlns attributes, returns $this otherwise. + * + * This method is used by the PHPTAL parser to keep track of xmlns fluctuation for + * each encountered node. + */ + public function newElement(array $nodeAttributes) + { + $prefix_to_uri = $this->prefix_to_uri; + $current_default = $this->current_default; + + $changed = false; + foreach ($nodeAttributes as $qname => $value) { + if (preg_match('/^xmlns:(.+)$/', $qname, $m)) { + $changed = true; + list(, $prefix) = $m; + $prefix_to_uri[$prefix] = $value; + } + + if ($qname == 'xmlns') {$changed=true;$current_default = $value;} + } + + if ($changed) { + return new PHPTAL_Dom_XmlnsState($prefix_to_uri, $current_default); + } else { + return $this; + } + } + + function getCurrentDefaultNamespaceURI() + { + return $this->current_default; + } + + private $prefix_to_uri, $current_default; +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Exception.php b/src/core/libs/PHPTAL5/PHPTAL/Exception.php new file mode 100644 index 0000000..6d4f312 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Exception.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ +/** + * @package PHPTAL + * @subpackage Exception + */ +class PHPTAL_Exception extends Exception +{ +} + + diff --git a/src/core/libs/PHPTAL5/PHPTAL/ExceptionHandler.php b/src/core/libs/PHPTAL5/PHPTAL/ExceptionHandler.php new file mode 100644 index 0000000..dca7bb7 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/ExceptionHandler.php @@ -0,0 +1,81 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id: $ + * @link http://phptal.org/ + */ + +class PHPTAL_ExceptionHandler +{ + private $encoding; + function __construct($encoding) + { + $this->encoding = $encoding; + } + + /** + * PHP's default exception handler allows error pages to be indexed and can reveal too much information, + * so if possible PHPTAL sets up its own handler to fix this. + * + * Doesn't change exception handler if non-default one is set. + * + * @param Exception e exception to re-throw and display + * + * @return void + * @throws Exception + */ + public static function handleException(Exception $e, $encoding) + { + // PHPTAL's handler is only useful on fresh HTTP response + if (PHP_SAPI !== 'cli' && !headers_sent()) { + $old_exception_handler = set_exception_handler(array(new PHPTAL_ExceptionHandler($encoding), '_defaultExceptionHandler')); + + if ($old_exception_handler !== NULL) { + restore_exception_handler(); // if there's user's exception handler, let it work + } + } + throw $e; // throws instead of outputting immediately to support user's try/catch + } + + + /** + * Generates simple error page. Sets appropriate HTTP status to prevent page being indexed. + * + * @param Exception e exception to display + */ + public function _defaultExceptionHandler($e) + { + if (!headers_sent()) { + header('HTTP/1.1 500 PHPTAL Exception'); + header('Content-Type:text/html;charset='.$this->encoding); + } + + $line = $e->getFile(); + if ($e->getLine()) { + $line .= ' line '.$e->getLine(); + } + + if (ini_get('display_errors')) { + $title = get_class($e).': '.htmlspecialchars($e->getMessage()); + $body = "<p><strong>\n".htmlspecialchars($e->getMessage()).'</strong></p>' . + '<p>In '.htmlspecialchars($line)."</p><pre>\n".htmlspecialchars($e->getTraceAsString()).'</pre>'; + } else { + $title = "PHPTAL Exception"; + $body = "<p>This page cannot be displayed.</p><hr/>" . + "<p><small>Enable <code>display_errors</code> to see detailed message.</small></p>"; + } + + echo "<!DOCTYPE html><html xmlns='http://www.w3.org/1999/xhtml'><head><style>body{font-family:sans-serif}</style><title>\n"; + echo $title.'</title></head><body><h1>PHPTAL Exception</h1>'.$body; + error_log($e->getMessage().' in '.$line); + echo '</body></html>'.str_repeat(' ', 100)."\n"; // IE won't display error pages < 512b + exit(1); + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/FileSource.php b/src/core/libs/PHPTAL5/PHPTAL/FileSource.php new file mode 100644 index 0000000..84d8719 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/FileSource.php @@ -0,0 +1,51 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Reads template from the filesystem + * + * @package PHPTAL + */ +class PHPTAL_FileSource implements PHPTAL_Source +{ + private $_path; + + public function __construct($path) + { + $this->_path = realpath($path); + if ($this->_path === false) throw new PHPTAL_IOException("Unable to find real path of file '$path' (in ".getcwd().')'); + } + + public function getRealPath() + { + return $this->_path; + } + + public function getLastModifiedTime() + { + return filemtime($this->_path); + } + + public function getData() + { + $content = file_get_contents($this->_path); + + // file_get_contents returns "" when loading directory!? + if (false === $content || ("" === $content && is_dir($this->_path))) { + throw new PHPTAL_IOException("Unable to load file ".$this->_path); + } + return $content; + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/FileSourceResolver.php b/src/core/libs/PHPTAL5/PHPTAL/FileSourceResolver.php new file mode 100644 index 0000000..3cb001a --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/FileSourceResolver.php @@ -0,0 +1,46 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * Finds template on disk by looking through repositories first + * + * @package PHPTAL + */ +class PHPTAL_FileSourceResolver implements PHPTAL_SourceResolver +{ + public function __construct($repositories) + { + $this->_repositories = $repositories; + } + + public function resolve($path) + { + foreach ($this->_repositories as $repository) { + $file = $repository . DIRECTORY_SEPARATOR . $path; + if (file_exists($file)) { + return new PHPTAL_FileSource($file); + } + } + + if (file_exists($path)) { + return new PHPTAL_FileSource($path); + } + + return null; + } + + private $_repositories; +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Filter.php b/src/core/libs/PHPTAL5/PHPTAL/Filter.php new file mode 100644 index 0000000..813c746 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Filter.php @@ -0,0 +1,32 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Objects passed to PHPTAL::setPre/PostFilter() must implement this interface + * + * @package PHPTAL + */ +interface PHPTAL_Filter +{ + /** + * In prefilter it gets template source file and is expected to return new source. + * Prefilters are called only once before template is compiled, so they can be slow. + * + * In postfilter template output is passed to this method, and final output goes to the browser. + * TAL or PHP tags won't be executed. Postfilters should be fast. + */ + public function filter($str); +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/GetTextTranslator.php b/src/core/libs/PHPTAL5/PHPTAL/GetTextTranslator.php new file mode 100644 index 0000000..108e8f5 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/GetTextTranslator.php @@ -0,0 +1,183 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * PHPTAL_TranslationService gettext implementation. + * + * Because gettext is the most common translation library in use, this + * implementation is shipped with the PHPTAL library. + * + * Please refer to the PHPTAL documentation for usage examples. + * + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_GetTextTranslator implements PHPTAL_TranslationService +{ + private $_vars = array(); + private $_currentDomain; + private $_encoding = 'UTF-8'; + private $_canonicalize = false; + + public function __construct() + { + if (!function_exists('gettext')) throw new PHPTAL_ConfigurationException("Gettext not installed"); + $this->useDomain("messages"); // PHP bug #21965 + } + + /** + * set encoding that is used by template and is expected from gettext + * the default is UTF-8 + * + * @param string $enc encoding name + */ + public function setEncoding($enc) + { + $this->_encoding = $enc; + } + + /** + * if true, all non-ASCII characters in keys will be converted to C<xxx> form. This impacts performance. + * by default keys will be passed to gettext unmodified. + * + * This function is only for backwards compatibility + * + * @param bool $bool enable old behavior + */ + public function setCanonicalize($bool) + { + $this->_canonicalize = $bool; + } + + /** + * It expects locale names as arguments. + * Choses first one that works. + * + * setLanguage("en_US.utf8","en_US","en_GB","en") + * + * @return string - chosen language + */ + public function setLanguage(/*...*/) + { + $langs = func_get_args(); + + $langCode = $this->trySettingLanguages(LC_ALL, $langs); + if ($langCode) return $langCode; + + if (defined("LC_MESSAGES")) { + $langCode = $this->trySettingLanguages(LC_MESSAGES, $langs); + if ($langCode) return $langCode; + } + + throw new PHPTAL_ConfigurationException('Language(s) code(s) "'.implode(', ', $langs).'" not supported by your system'); + } + + private function trySettingLanguages($category, array $langs) + { + foreach ($langs as $langCode) { + putenv("LANG=$langCode"); + putenv("LC_ALL=$langCode"); + putenv("LANGUAGE=$langCode"); + if (setlocale($category, $langCode)) { + return $langCode; + } + } + return null; + } + + /** + * Adds translation domain (usually it's the same as name of .po file [without extension]) + * + * Encoding must be set before calling addDomain! + */ + public function addDomain($domain, $path='./locale/') + { + bindtextdomain($domain, $path); + if ($this->_encoding) { + bind_textdomain_codeset($domain, $this->_encoding); + } + $this->useDomain($domain); + } + + /** + * Switches to one of the domains previously set via addDomain() + * + * @param string $domain name of translation domain to be used. + * + * @return string - old domain + */ + public function useDomain($domain) + { + $old = $this->_currentDomain; + $this->_currentDomain = $domain; + textdomain($domain); + return $old; + } + + /** + * used by generated PHP code. Don't use directly. + */ + public function setVar($key, $value) + { + $this->_vars[$key] = $value; + } + + /** + * translate given key. + * + * @param bool $htmlencode if true, output will be HTML-escaped. + */ + public function translate($key, $htmlencode=true) + { + if ($this->_canonicalize) $key = self::_canonicalizeKey($key); + + $value = gettext($key); + + if ($htmlencode) { + $value = htmlspecialchars($value, ENT_QUOTES, $this->_encoding); + } + while (preg_match('/\${(.*?)\}/sm', $value, $m)) { + list($src, $var) = $m; + if (!array_key_exists($var, $this->_vars)) { + throw new PHPTAL_VariableNotFoundException('Interpolation error. Translation uses ${'.$var.'}, which is not defined in the template (via i18n:name)'); + } + $value = str_replace($src, $this->_vars[$var], $value); + } + return $value; + } + + /** + * For backwards compatibility only. + */ + private static function _canonicalizeKey($key_) + { + $result = ""; + $key_ = trim($key_); + $key_ = str_replace("\n", "", $key_); + $key_ = str_replace("\r", "", $key_); + for ($i = 0; $i<strlen($key_); $i++) { + $c = $key_[$i]; + $o = ord($c); + if ($o < 5 || $o > 127) { + $result .= 'C<'.$o.'>'; + } else { + $result .= $c; + } + } + return $result; + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/IOException.php b/src/core/libs/PHPTAL5/PHPTAL/IOException.php new file mode 100644 index 0000000..166290d --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/IOException.php @@ -0,0 +1,25 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * PHPTAL failed to load template + * + * @package PHPTAL + * @subpackage Exception + */ +class PHPTAL_IOException extends PHPTAL_Exception +{ +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/InvalidVariableNameException.php b/src/core/libs/PHPTAL5/PHPTAL/InvalidVariableNameException.php new file mode 100644 index 0000000..427e138 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/InvalidVariableNameException.php @@ -0,0 +1,25 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * Parse error in TALES expression. + * + * @package PHPTAL + * @subpackage Exception + */ +class PHPTAL_InvalidVariableNameException extends PHPTAL_Exception +{ +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Keywords.php b/src/core/libs/PHPTAL5/PHPTAL/Keywords.php new file mode 100644 index 0000000..bee7b7a --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Keywords.php @@ -0,0 +1,26 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Andrew Crites <explosion-pills@aysites.com> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * Interface for template keywords + * + * @package PHPTAL + * @subpackage Keywords + */ +interface PHPTAL_Keywords extends Countable +{ + public function __toString(); +} +?> diff --git a/src/core/libs/PHPTAL5/PHPTAL/MacroMissingException.php b/src/core/libs/PHPTAL5/PHPTAL/MacroMissingException.php new file mode 100644 index 0000000..0e3a057 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/MacroMissingException.php @@ -0,0 +1,24 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Wrong macro name in metal:use-macro + * + * @package PHPTAL + * @subpackage Exception + */ +class PHPTAL_MacroMissingException extends PHPTAL_TemplateException +{ +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Namespace.php b/src/core/libs/PHPTAL5/PHPTAL/Namespace.php new file mode 100644 index 0000000..17d5911 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Namespace.php @@ -0,0 +1,70 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * @see PHPTAL_NamespaceAttribute + * @package PHPTAL + * @subpackage Namespace + */ +abstract class PHPTAL_Namespace +{ + private $prefix, $namespace_uri; + protected $_attributes; + + public function __construct($prefix, $namespace_uri) + { + if (!$namespace_uri || !$prefix) { + throw new PHPTAL_ConfigurationException("Can't create namespace with empty prefix or namespace URI"); + } + + $this->_attributes = array(); + $this->prefix = $prefix; + $this->namespace_uri = $namespace_uri; + } + + public function getPrefix() + { + return $this->prefix; + } + + public function getNamespaceURI() + { + return $this->namespace_uri; + } + + public function hasAttribute($attributeName) + { + return array_key_exists(strtolower($attributeName), $this->_attributes); + } + + public function getAttribute($attributeName) + { + return $this->_attributes[strtolower($attributeName)]; + } + + public function addAttribute(PHPTAL_NamespaceAttribute $attribute) + { + $attribute->setNamespace($this); + $this->_attributes[strtolower($attribute->getLocalName())] = $attribute; + } + + public function getAttributes() + { + return $this->_attributes; + } + + abstract public function createAttributeHandler(PHPTAL_NamespaceAttribute $att, PHPTAL_Dom_Element $tag, $expression); +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Namespace/Builtin.php b/src/core/libs/PHPTAL5/PHPTAL/Namespace/Builtin.php new file mode 100644 index 0000000..5cec74d --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Namespace/Builtin.php @@ -0,0 +1,38 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * @package PHPTAL + * @subpackage Namespace + */ +class PHPTAL_Namespace_Builtin extends PHPTAL_Namespace +{ + public function createAttributeHandler(PHPTAL_NamespaceAttribute $att, PHPTAL_Dom_Element $tag, $expression) + { + $name = $att->getLocalName(); + + // change define-macro to "define macro" and capitalize words + $name = str_replace(' ', '', ucwords(strtr($name, '-', ' '))); + + // case is important when using autoload on case-sensitive filesystems + if (version_compare(PHP_VERSION, '5.3', '>=') && __NAMESPACE__) { + $class = 'PHPTALNAMESPACE\\Php\\Attribute\\'.strtoupper($this->getPrefix()).'\\'.$name; + } else { + $class = 'PHPTAL_Php_Attribute_'.strtoupper($this->getPrefix()).'_'.$name; + } + $result = new $class($tag, $expression); + return $result; + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Namespace/I18N.php b/src/core/libs/PHPTAL5/PHPTAL/Namespace/I18N.php new file mode 100644 index 0000000..81dd8e6 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Namespace/I18N.php @@ -0,0 +1,32 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * @package PHPTAL + * @subpackage Namespace + */ +class PHPTAL_Namespace_I18N extends PHPTAL_Namespace_Builtin +{ + public function __construct() + { + parent::__construct('i18n', 'http://xml.zope.org/namespaces/i18n'); + $this->addAttribute(new PHPTAL_NamespaceAttributeContent('translate', 5)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('name', 5)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('attributes', 10)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('domain', 3)); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Namespace/METAL.php b/src/core/libs/PHPTAL5/PHPTAL/Namespace/METAL.php new file mode 100644 index 0000000..2773667 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Namespace/METAL.php @@ -0,0 +1,31 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * @package PHPTAL + * @subpackage Namespace + */ +class PHPTAL_Namespace_METAL extends PHPTAL_Namespace_Builtin +{ + public function __construct() + { + parent::__construct('metal', 'http://xml.zope.org/namespaces/metal'); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('define-macro', 1)); + $this->addAttribute(new PHPTAL_NamespaceAttributeReplace('use-macro', 9)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('define-slot', 9)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('fill-slot', 9)); + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Namespace/PHPTAL.php b/src/core/libs/PHPTAL5/PHPTAL/Namespace/PHPTAL.php new file mode 100644 index 0000000..4d4270a --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Namespace/PHPTAL.php @@ -0,0 +1,31 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * @package PHPTAL + * @subpackage Namespace + */ +class PHPTAL_Namespace_PHPTAL extends PHPTAL_Namespace_Builtin +{ + public function __construct() + { + parent::__construct('phptal', 'http://phptal.org/ns/phptal'); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('tales', -1)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('debug', -2)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('id', 7)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('cache', -3)); + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Namespace/TAL.php b/src/core/libs/PHPTAL5/PHPTAL/Namespace/TAL.php new file mode 100644 index 0000000..74cd90a --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Namespace/TAL.php @@ -0,0 +1,36 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * @package PHPTAL + * @subpackage Namespace + */ +class PHPTAL_Namespace_TAL extends PHPTAL_Namespace_Builtin +{ + public function __construct() + { + parent::__construct('tal', 'http://xml.zope.org/namespaces/tal'); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('define', 4)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('condition', 6)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('repeat', 8)); + $this->addAttribute(new PHPTAL_NamespaceAttributeContent('content', 11)); + $this->addAttribute(new PHPTAL_NamespaceAttributeReplace('replace', 9)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('attributes', 9)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('omit-tag', 0)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('comment', 12)); + $this->addAttribute(new PHPTAL_NamespaceAttributeSurround('on-error', 2)); + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttribute.php b/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttribute.php new file mode 100644 index 0000000..db1fd95 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttribute.php @@ -0,0 +1,99 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Information about TAL attributes (in which order they are executed and how they generate the code) + * + * From http://dev.zope.org/Wikis/DevSite/Projects/ZPT/TAL%20Specification%201.4 + * + * Order of Operations + * + * When there is only one TAL statement per element, the order in which + * they are executed is simple. Starting with the root element, each + * element's statements are executed, then each of its child elements is + * visited, in order, to do the same. + * + * Any combination of statements may appear on the same elements, except + * that the content and replace statements may not appear together. + * + * When an element has multiple statements, they are executed in this + * order: + * + * * define + * * condition + * * repeat + * * content or replace + * * attributes + * * omit-tag + * + * Since the on-error statement is only invoked when an error occurs, it + * does not appear in the list. + * + * The reasoning behind this ordering goes like this: You often want to set + * up variables for use in other statements, so define comes first. The + * very next thing to do is decide whether this element will be included at + * all, so condition is next; since the condition may depend on variables + * you just set, it comes after define. It is valuable be able to replace + * various parts of an element with different values on each iteration of a + * repeat, so repeat is next. It makes no sense to replace attributes and + * then throw them away, so attributes is last. The remaining statements + * clash, because they each replace or edit the statement element. + * + * If you want to override this ordering, you must do so by enclosing the + * element in another element, possibly div or span, and placing some of + * the statements on this new element. + * + * + * @package PHPTAL + * @subpackage Namespace + */ +abstract class PHPTAL_NamespaceAttribute +{ + /** Attribute name without the namespace: prefix */ + private $local_name; + + /** [0 - 1000] */ + private $_priority; + + /** PHPTAL_Namespace */ + private $_namespace; + + /** + * @param string $name The attribute name + * @param int $priority Attribute execution priority + */ + public function __construct($local_name, $priority) + { + $this->local_name = $local_name; + $this->_priority = $priority; + } + + /** + * @return string + */ + public function getLocalName() + { + return $this->local_name; + } + + public function getPriority() { return $this->_priority; } + public function getNamespace() { return $this->_namespace; } + public function setNamespace(PHPTAL_Namespace $ns) { $this->_namespace = $ns; } + + public function createAttributeHandler(PHPTAL_Dom_Element $tag, $expression) + { + return $this->_namespace->createAttributeHandler($this, $tag, $expression); + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeContent.php b/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeContent.php new file mode 100644 index 0000000..de33521 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeContent.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * This type of attribute replaces element's content entirely + * @package PHPTAL + * @subpackage Namespace + */ +class PHPTAL_NamespaceAttributeContent extends PHPTAL_NamespaceAttribute +{ +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeReplace.php b/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeReplace.php new file mode 100644 index 0000000..defc360 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeReplace.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * This type of attribute replaces element entirely + * @package PHPTAL + * @subpackage Namespace + */ +class PHPTAL_NamespaceAttributeReplace extends PHPTAL_NamespaceAttribute +{ +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeSurround.php b/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeSurround.php new file mode 100644 index 0000000..fca87d6 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/NamespaceAttributeSurround.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * This type of attribute wraps element + * @package PHPTAL + * @subpackage Namespace + */ +class PHPTAL_NamespaceAttributeSurround extends PHPTAL_NamespaceAttribute +{ +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/NothingKeyword.php b/src/core/libs/PHPTAL5/PHPTAL/NothingKeyword.php new file mode 100644 index 0000000..22a79b0 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/NothingKeyword.php @@ -0,0 +1,39 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Andrew Crites <explosion-pills@aysites.com> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * Representation of the template 'nothing' keyword + * + * @package PHPTAL + * @subpackage Keywords + */ +class PHPTAL_NothingKeyword implements PHPTAL_Keywords +{ + public function __toString() + { + return 'null'; + } + + public function count() + { + return 0; + } + + public function jsonSerialize() + { + return null; + } +} +?> diff --git a/src/core/libs/PHPTAL5/PHPTAL/ParserException.php b/src/core/libs/PHPTAL5/PHPTAL/ParserException.php new file mode 100644 index 0000000..225ad54 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/ParserException.php @@ -0,0 +1,24 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * XML well-formedness errors and alike. + * + * @package PHPTAL + * @subpackage Exception + */ +class PHPTAL_ParserException extends PHPTAL_TemplateException +{ +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute.php new file mode 100644 index 0000000..ceb8a12 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute.php @@ -0,0 +1,98 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Base class for all PHPTAL attributes. + * + * Attributes are first ordered by PHPTAL then called depending on their + * priority before and after the element printing. + * + * An attribute must implements start() and end(). + * + * @package PHPTAL + * @subpackage Php + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +abstract class PHPTAL_Php_Attribute +{ + const ECHO_TEXT = 'text'; + const ECHO_STRUCTURE = 'structure'; + + /** Attribute value specified by the element. */ + protected $expression; + + /** Element using this attribute (PHPTAL's counterpart of XML node) */ + protected $phpelement; + + /** + * Called before element printing. + */ + abstract function before(PHPTAL_Php_CodeWriter $codewriter); + + /** + * Called after element printing. + */ + abstract function after(PHPTAL_Php_CodeWriter $codewriter); + + function __construct(PHPTAL_Dom_Element $phpelement, $expression) + { + $this->expression = $expression; + $this->phpelement = $phpelement; + } + + /** + * Remove structure|text keyword from expression and stores it for later + * doEcho() usage. + * + * $expression = 'stucture my/path'; + * $expression = $this->extractEchoType($expression); + * + * ... + * + * $this->doEcho($code); + */ + protected function extractEchoType($expression) + { + $echoType = self::ECHO_TEXT; + $expression = trim($expression); + if (preg_match('/^(text|structure)\s+(.*?)$/ism', $expression, $m)) { + list(, $echoType, $expression) = $m; + } + $this->_echoType = strtolower($echoType); + return trim($expression); + } + + protected function doEchoAttribute(PHPTAL_Php_CodeWriter $codewriter, $code) + { + if ($this->_echoType === self::ECHO_TEXT) + $codewriter->doEcho($code); + else + $codewriter->doEchoRaw($code); + } + + protected function parseSetExpression($exp) + { + $exp = trim($exp); + // (dest) (value) + if (preg_match('/^([a-z0-9:\-_]+)\s+(.*?)$/si', $exp, $m)) { + return array($m[1], trim($m[2])); + } + // (dest) + return array($exp, null); + } + + protected $_echoType = PHPTAL_Php_Attribute::ECHO_TEXT; +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Attributes.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Attributes.php new file mode 100644 index 0000000..5eb3fac --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Attributes.php @@ -0,0 +1,118 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * i18n:attributes + * + * This attribute will allow us to translate attributes of HTML tags, such + * as the alt attribute in the img tag. The i18n:attributes attribute + * specifies a list of attributes to be translated with optional message + * IDs? for each; if multiple attribute names are given, they must be + * separated by semi-colons. Message IDs? used in this context must not + * include whitespace. + * + * Note that the value of the particular attributes come either from the + * HTML attribute value itself or from the data inserted by tal:attributes. + * + * If an attibute is to be both computed using tal:attributes and translated, + * the translation service is passed the result of the TALES expression for + * that attribute. + * + * An example: + * + * <img src="http://foo.com/logo" alt="Visit us" + * tal:attributes="alt here/greeting" + * i18n:attributes="alt" + * /> + * + * + * In this example, let tal:attributes set the value of the alt attribute to + * the text "Stop by for a visit!". This text will be passed to the + * translation service, which uses the result of language negotiation to + * translate "Stop by for a visit!" into the requested language. The example + * text in the template, "Visit us", will simply be discarded. + * + * Another example, with explicit message IDs: + * + * <img src="../icons/uparrow.png" alt="Up" + * i18n:attributes="src up-arrow-icon; alt up-arrow-alttext" + * > + * + * Here, the message ID up-arrow-icon will be used to generate the link to + * an icon image file, and the message ID up-arrow-alttext will be used for + * the "alt" text. + * + * + * + * @package PHPTAL + * @subpackage Php.attribute.i18n + */ +class PHPTAL_Php_Attribute_I18N_Attributes extends PHPTAL_Php_Attribute +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + // split attributes to translate + foreach ($codewriter->splitExpression($this->expression) as $exp) { + list($qname, $key) = $this->parseSetExpression($exp); + + // if the translation key is specified and not empty (but may be '0') + if (strlen($key)) { + // we use it and replace the tag attribute with the result of the translation + $code = $this->_getTranslationCode($codewriter, $key); + } else { + $attr = $this->phpelement->getAttributeNode($qname); + if (!$attr) throw new PHPTAL_TemplateException("Unable to translate attribute $qname, because there is no translation key specified", + $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + + if ($attr->getReplacedState() === PHPTAL_Dom_Attr::NOT_REPLACED) { + $code = $this->_getTranslationCode($codewriter, $attr->getValue()); + } elseif ($attr->getReplacedState() === PHPTAL_Dom_Attr::VALUE_REPLACED && $attr->getOverwrittenVariableName()) { + // sadly variables won't be interpolated in this translation + $code = 'echo '.$codewriter->escapeCode($codewriter->getTranslatorReference(). '->translate('.$attr->getOverwrittenVariableName().', false)'); + } else { + throw new PHPTAL_TemplateException("Unable to translate attribute $qname, because other TAL attributes are using it", + $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + } + } + $this->phpelement->getOrCreateAttributeNode($qname)->overwriteValueWithCode($code); + } + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + } + + /** + * @param key - unescaped string (not PHP code) for the key + */ + private function _getTranslationCode(PHPTAL_Php_CodeWriter $codewriter, $key) + { + $code = ''; + if (preg_match_all('/\$\{(.*?)\}/', $key, $m)) { + array_shift($m); + $m = array_shift($m); + foreach ($m as $name) { + $code .= "\n".$codewriter->getTranslatorReference(). '->setVar('.$codewriter->str($name).','.PHPTAL_Php_TalesInternal::compileToPHPExpression($name).');'; // allow more complex TAL expressions + } + $code .= "\n"; + } + + // notice the false boolean which indicate that the html is escaped + // elsewhere looks like an hack doesn't it ? :) + $code .= 'echo '.$codewriter->escapeCode($codewriter->getTranslatorReference().'->translate('.$codewriter->str($key).', false)'); + return $code; + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Data.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Data.php new file mode 100644 index 0000000..bad310f --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Data.php @@ -0,0 +1,36 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * i18n:data + * + * Since TAL always returns strings, we need a way in ZPT to translate + * objects, the most obvious case being DateTime objects. The data attribute + * will allow us to specify such an object, and i18n:translate will provide + * us with a legal format string for that object. If data is used, + * i18n:translate must be used to give an explicit message ID, rather than + * relying on a message ID computed from the content. + * + * + * + * @package PHPTAL + * @subpackage Php.attribute.i18n + */ +class PHPTAL_Php_Attribute_I18N_Data extends PHPTAL_Php_Attribute +{ + public function before(PHPTAL_Php_CodeWriter $codewriter){} + public function after(PHPTAL_Php_CodeWriter $codewriter){} +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Domain.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Domain.php new file mode 100644 index 0000000..92ece11 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Domain.php @@ -0,0 +1,50 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * i18n:domain + * + * The i18n:domain attribute is used to specify the domain to be used to get + * the translation. If not specified, the translation services will use a + * default domain. The value of the attribute is used directly; it is not + * a TALES expression. + * + * @package PHPTAL + * @subpackage Php.attribute.i18n + */ +class PHPTAL_Php_Attribute_I18N_Domain extends PHPTAL_Php_Attribute +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + // ensure a domain stack exists or create it + $codewriter->doIf('!isset($_i18n_domains)'); + $codewriter->pushCode('$_i18n_domains = array()'); + $codewriter->doEnd('if'); + + $expression = $codewriter->interpolateTalesVarsInString($this->expression); + + // push current domain and use new domain + $code = '$_i18n_domains[] = '.$codewriter->getTranslatorReference().'->useDomain('.$expression.')'; + $codewriter->pushCode($code); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + // restore domain + $code = $codewriter->getTranslatorReference().'->useDomain(array_pop($_i18n_domains))'; + $codewriter->pushCode($code); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Name.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Name.php new file mode 100644 index 0000000..8a8f4e7 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Name.php @@ -0,0 +1,47 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** i18n:name + * + * Name the content of the current element for use in interpolation within + * translated content. This allows a replaceable component in content to be + * re-ordered by translation. For example: + * + * <span i18n:translate=''> + * <span tal:replace='here/name' i18n:name='name' /> was born in + * <span tal:replace='here/country_of_birth' i18n:name='country' />. + * </span> + * + * would cause this text to be passed to the translation service: + * + * "${name} was born in ${country}." + * + * + * @package PHPTAL + * @subpackage Php.attribute.i18n + */ +class PHPTAL_Php_Attribute_I18N_Name extends PHPTAL_Php_Attribute +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->pushCode('ob_start()'); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->pushCode($codewriter->getTranslatorReference().'->setVar('.$codewriter->str($this->expression).', ob_get_clean())'); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Source.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Source.php new file mode 100644 index 0000000..9575fae --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Source.php @@ -0,0 +1,48 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * i18n:source + * + * The i18n:source attribute specifies the language of the text to be + * translated. The default is "nothing", which means we don't provide + * this information to the translation services. + * + * + * @package PHPTAL + * @subpackage Php.attribute.i18n + */ +class PHPTAL_Php_Attribute_I18N_Source extends PHPTAL_Php_Attribute +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + // ensure that a sources stack exists or create it + $codewriter->doIf('!isset($_i18n_sources)'); + $codewriter->pushCode('$_i18n_sources = array()'); + $codewriter->end(); + + // push current source and use new one + $codewriter->pushCode('$_i18n_sources[] = ' . $codewriter->getTranslatorReference(). '->setSource('.$codewriter->str($this->expression).')'); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + // restore source + $code = $codewriter->getTranslatorReference().'->setSource(array_pop($_i18n_sources))'; + $codewriter->pushCode($code); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Target.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Target.php new file mode 100644 index 0000000..9cf2a67 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Target.php @@ -0,0 +1,43 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * i18n:target + * + * The i18n:target attribute specifies the language of the translation we + * want to get. If the value is "default", the language negotiation services + * will be used to choose the destination language. If the value is + * "nothing", no translation will be performed; this can be used to suppress + * translation within a larger translated unit. Any other value must be a + * language code. + * + * The attribute value is a TALES expression; the result of evaluating the + * expression is the language code or one of the reserved values. + * + * Note that i18n:target is primarily used for hints to text extraction + * tools and translation teams. If you had some text that should only be + * translated to e.g. German, then it probably shouldn't be wrapped in an + * i18n:translate span. + * + * + * @package PHPTAL + * @subpackage Php.attribute.i18n + */ +class PHPTAL_Php_Attribute_I18N_Target extends PHPTAL_Php_Attribute +{ + public function before(PHPTAL_Php_CodeWriter $codewriter){} + public function after(PHPTAL_Php_CodeWriter $codewriter){} +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Translate.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Translate.php new file mode 100644 index 0000000..a0e26c2 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/I18N/Translate.php @@ -0,0 +1,130 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * ZPTInternationalizationSupport + * + * i18n:translate + * + * This attribute is used to mark units of text for translation. If this + * attribute is specified with an empty string as the value, the message ID + * is computed from the content of the element bearing this attribute. + * Otherwise, the value of the element gives the message ID. + * + * + * @package PHPTAL + * @subpackage Php.attribute.i18n + */ +class PHPTAL_Php_Attribute_I18N_Translate extends PHPTAL_Php_Attribute_TAL_Content +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $escape = true; + $this->_echoType = PHPTAL_Php_Attribute::ECHO_TEXT; + if (preg_match('/^(text|structure)(?:\s+(.*)|\s*$)/', $this->expression, $m)) { + if ($m[1]=='structure') { $escape=false; $this->_echoType = PHPTAL_Php_Attribute::ECHO_STRUCTURE; } + $this->expression = isset($m[2])?$m[2]:''; + } + + $this->_prepareNames($codewriter, $this->phpelement); + + // if no expression is given, the content of the node is used as + // a translation key + if (strlen(trim($this->expression)) == 0) { + $key = $this->_getTranslationKey($this->phpelement, !$escape, $codewriter->getEncoding()); + $key = trim(preg_replace('/\s+/sm'.($codewriter->getEncoding()=='UTF-8'?'u':''), ' ', $key)); + if ('' === trim($key)) { + throw new PHPTAL_TemplateException("Empty translation key", + $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + } + $code = $codewriter->str($key); + } else { + $code = $codewriter->evaluateExpression($this->expression); + if (is_array($code)) + return $this->generateChainedContent($codewriter, $code); + + $code = $codewriter->evaluateExpression($this->expression); + } + + $codewriter->pushCode('echo '.$codewriter->getTranslatorReference().'->translate('.$code.','.($escape ? 'true':'false').');'); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + } + + public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $exp, $islast) + { + $codewriter = $executor->getCodeWriter(); + + $escape = !($this->_echoType == PHPTAL_Php_Attribute::ECHO_STRUCTURE); + $exp = $codewriter->getTranslatorReference()."->translate($exp, " . ($escape ? 'true':'false') . ')'; + if (!$islast) { + $var = $codewriter->createTempVariable(); + $executor->doIf('!phptal_isempty('.$var.' = '.$exp.')'); + $codewriter->pushCode("echo $var"); + $codewriter->recycleTempVariable($var); + } else { + $executor->doElse(); + $codewriter->pushCode("echo $exp"); + } + } + + private function _getTranslationKey(PHPTAL_Dom_Node $tag, $preserve_tags, $encoding) + { + $result = ''; + foreach ($tag->childNodes as $child) { + if ($child instanceof PHPTAL_Dom_Text) { + if ($preserve_tags) { + $result .= $child->getValueEscaped(); + } else { + $result .= $child->getValue($encoding); + } + } elseif ($child instanceof PHPTAL_Dom_Element) { + if ($attr = $child->getAttributeNodeNS('http://xml.zope.org/namespaces/i18n', 'name')) { + $result .= '${' . $attr->getValue() . '}'; + } else { + + if ($preserve_tags) { + $result .= '<'.$child->getQualifiedName(); + foreach ($child->getAttributeNodes() as $attr) { + if ($attr->getReplacedState() === PHPTAL_Dom_Attr::HIDDEN) continue; + + $result .= ' '.$attr->getQualifiedName().'="'.$attr->getValueEscaped().'"'; + } + $result .= '>'.$this->_getTranslationKey($child, $preserve_tags, $encoding) . '</'.$child->getQualifiedName().'>'; + } else { + $result .= $this->_getTranslationKey($child, $preserve_tags, $encoding); + } + } + } + } + return $result; + } + + private function _prepareNames(PHPTAL_Php_CodeWriter $codewriter, PHPTAL_Dom_Node $tag) + { + foreach ($tag->childNodes as $child) { + if ($child instanceof PHPTAL_Dom_Element) { + if ($child->hasAttributeNS('http://xml.zope.org/namespaces/i18n', 'name')) { + $child->generateCode($codewriter); + } else { + $this->_prepareNames($codewriter, $child); + } + } + } + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/DefineMacro.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/DefineMacro.php new file mode 100644 index 0000000..ef04840 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/DefineMacro.php @@ -0,0 +1,67 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * METAL Specification 1.0 + * + * argument ::= Name + * + * Example: + * + * <p metal:define-macro="copyright"> + * Copyright 2001, <em>Foobar</em> Inc. + * </p> + * + * PHPTAL: + * + * <?php function XXX_macro_copyright($tpl) { ? > + * <p> + * Copyright 2001, <em>Foobar</em> Inc. + * </p> + * <?php } ? > + * + * @package PHPTAL + * @subpackage Php.attribute.metal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_METAL_DefineMacro extends PHPTAL_Php_Attribute +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $macroname = strtr(trim($this->expression), '-', '_'); + if (!preg_match('/^[a-z0-9_]+$/i', $macroname)) { + throw new PHPTAL_ParserException('Bad macro name "'.$macroname.'"', + $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + } + + if ($codewriter->functionExists($macroname)) { + throw new PHPTAL_TemplateException("Macro $macroname is defined twice", + $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + } + + $codewriter->doFunction($macroname, 'PHPTAL $_thistpl, PHPTAL $tpl'); + $codewriter->doSetVar('$tpl', 'clone $tpl'); + $codewriter->doSetVar('$ctx', '$tpl->getContext()'); + $codewriter->doInitTranslator(); + $codewriter->doXmlDeclaration(true); + $codewriter->doDoctype(true); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->doEnd('function'); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/DefineSlot.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/DefineSlot.php new file mode 100644 index 0000000..010849a --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/DefineSlot.php @@ -0,0 +1,70 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * METAL Specification 1.0 + * + * argument ::= Name + * + * Example: + * + * <table metal:define-macro="sidebar"> + * <tr><th>Links</th></tr> + * <tr><td metal:define-slot="links"> + * <a href="/">A Link</a> + * </td></tr> + * </table> + * + * PHPTAL: (access to slots may be renamed) + * + * <?php function XXXX_macro_sidebar($tpl) { ? > + * <table> + * <tr><th>Links</th></tr> + * <tr> + * <?php if (isset($tpl->slots->links)): ? > + * <?php echo $tpl->slots->links ? > + * <?php else: ? > + * <td> + * <a href="/">A Link</a> + * </td></tr> + * </table> + * <?php } ? > + * + * @package PHPTAL + * @subpackage Php.attribute.metal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_METAL_DefineSlot extends PHPTAL_Php_Attribute +{ + private $tmp_var; + + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $this->tmp_var = $codewriter->createTempVariable(); + + $codewriter->doSetVar($this->tmp_var, $codewriter->interpolateTalesVarsInString($this->expression)); + $codewriter->doIf('$ctx->hasSlot('.$this->tmp_var.')'); + $codewriter->pushCode('$ctx->echoSlot('.$this->tmp_var.')'); + $codewriter->doElse(); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->doEnd('if'); + + $codewriter->recycleTempVariable($this->tmp_var); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/FillSlot.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/FillSlot.php new file mode 100644 index 0000000..2dfda3a --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/FillSlot.php @@ -0,0 +1,148 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * METAL Specification 1.0 + * + * argument ::= Name + * + * Example: + * + * <table metal:use-macro="here/doc1/macros/sidebar"> + * <tr><th>Links</th></tr> + * <tr><td metal:fill-slot="links"> + * <a href="http://www.goodplace.com">Good Place</a><br> + * <a href="http://www.badplace.com">Bad Place</a><br> + * <a href="http://www.otherplace.com">Other Place</a> + * </td></tr> + * </table> + * + * PHPTAL: + * + * 1. evaluate slots + * + * <?php ob_start(); ? > + * <td> + * <a href="http://www.goodplace.com">Good Place</a><br> + * <a href="http://www.badplace.com">Bad Place</a><br> + * <a href="http://www.otherplace.com">Other Place</a> + * </td> + * <?php $tpl->slots->links = ob_get_contents(); ob_end_clean(); ? > + * + * 2. call the macro (here not supported) + * + * <?php echo phptal_macro($tpl, 'master_page.html/macros/sidebar'); ? > + * + * + * @package PHPTAL + * @subpackage Php.attribute.metal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_METAL_FillSlot extends PHPTAL_Php_Attribute +{ + private static $uid = 0; + private $function_name; + + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + if ($this->shouldUseCallback()) { + $function_base_name = 'slot_'.preg_replace('/[^a-z0-9]/', '_', $this->expression).'_'.(self::$uid++); + $codewriter->doFunction($function_base_name, 'PHPTAL $_thistpl, PHPTAL $tpl'); + $this->function_name = $codewriter->getFunctionPrefix().$function_base_name; + + $codewriter->doSetVar('$ctx', '$tpl->getContext()'); + $codewriter->doInitTranslator(); + } else { + $codewriter->pushCode('ob_start()'); + $this->function_name = null; + } + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + if ($this->function_name !== null) { + $codewriter->doEnd(); + $codewriter->pushCode('$ctx->fillSlotCallback('.$codewriter->str($this->expression).', '.$codewriter->str($this->function_name).', $_thistpl, clone $tpl)'); + } else { + $codewriter->pushCode('$ctx->fillSlot('.$codewriter->str($this->expression).', ob_get_clean())'); + } + } + + // rough guess + const CALLBACK_THRESHOLD = 10000; + + /** + * inspects contents of the element to decide whether callback makes sense + */ + private function shouldUseCallback() + { + // since callback is slightly slower than buffering, + // use callback only for content that is large to offset speed loss by memory savings + return $this->estimateNumberOfBytesOutput($this->phpelement, false) > self::CALLBACK_THRESHOLD; + } + + /** + * @param bool $is_nested_in_repeat true if any parent element has tal:repeat + * + * @return rough guess + */ + private function estimateNumberOfBytesOutput(PHPTAL_Dom_Element $element, $is_nested_in_repeat) + { + // macros don't output anything on their own + if ($element->hasAttributeNS('http://xml.zope.org/namespaces/metal', 'define-macro')) { + return 0; + } + + $estimated_bytes = 2*(3+strlen($element->getQualifiedName())); + + foreach ($element->getAttributeNodes() as $attr) { + $estimated_bytes += 4+strlen($attr->getQualifiedName()); + if ($attr->getReplacedState() === PHPTAL_Dom_Attr::NOT_REPLACED) { + $estimated_bytes += strlen($attr->getValueEscaped()); // this is shoddy for replaced attributes + } + } + + $has_repeat_attr = $element->hasAttributeNS('http://xml.zope.org/namespaces/tal', 'repeat'); + + if ($element->hasAttributeNS('http://xml.zope.org/namespaces/tal', 'content') || + $element->hasAttributeNS('http://xml.zope.org/namespaces/tal', 'replace')) { + // assume that output in loops is shorter (e.g. table rows) than outside (main content) + $estimated_bytes += ($has_repeat_attr || $is_nested_in_repeat) ? 500 : 2000; + } else { + foreach ($element->childNodes as $node) { + if ($node instanceof PHPTAL_Dom_Element) { + $estimated_bytes += $this->estimateNumberOfBytesOutput($node, $has_repeat_attr || $is_nested_in_repeat); + } else { + $estimated_bytes += strlen($node->getValueEscaped()); + } + } + } + + if ($element->hasAttributeNS('http://xml.zope.org/namespaces/metal', 'use-macro')) { + $estimated_bytes += ($has_repeat_attr || $is_nested_in_repeat) ? 500 : 2000; + } + + if ($element->hasAttributeNS('http://xml.zope.org/namespaces/tal', 'condition')) { + $estimated_bytes /= 2; // naively assuming 50% chance, that works well with if/else pattern + } + + if ($element->hasAttributeNS('http://xml.zope.org/namespaces/tal', 'repeat')) { + // assume people don't write big nested loops + $estimated_bytes *= $is_nested_in_repeat ? 5 : 10; + } + + return $estimated_bytes; + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/UseMacro.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/UseMacro.php new file mode 100644 index 0000000..83e8144 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/METAL/UseMacro.php @@ -0,0 +1,135 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * METAL Specification 1.0 + * + * argument ::= expression + * + * Example: + * + * <hr /> + * <p metal:use-macro="here/master_page/macros/copyright"> + * <hr /> + * + * PHPTAL: (here not supported) + * + * <?php echo phptal_macro( $tpl, 'master_page.html/macros/copyright'); ? > + * + * + * + * @package PHPTAL + * @subpackage Php.attribute.metal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_METAL_UseMacro extends PHPTAL_Php_Attribute +{ + static $ALLOWED_ATTRIBUTES = array( + 'fill-slot'=>'http://xml.zope.org/namespaces/metal', + 'define-macro'=>'http://xml.zope.org/namespaces/metal', + 'define'=>'http://xml.zope.org/namespaces/tal', + ); + + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $this->pushSlots($codewriter); + + foreach ($this->phpelement->childNodes as $child) { + $this->generateFillSlots($codewriter, $child); + } + + $macroname = strtr($this->expression, '-', '_'); + + // throw error if attempting to define and use macro at same time + // [should perhaps be a TemplateException? but I don't know how to set that up...] + if ($defineAttr = $this->phpelement->getAttributeNodeNS( + 'http://xml.zope.org/namespaces/metal', 'define-macro')) { + if ($defineAttr->getValue() == $macroname) + throw new PHPTAL_TemplateException("Cannot simultaneously define and use macro '$macroname'", + $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + } + + // local macro (no filename specified) and non dynamic macro name + // can be called directly if it's a known function (just generated or seen in previous compilation) + if (preg_match('/^[a-z0-9_]+$/i', $macroname) && $codewriter->functionExists($macroname)) { + $code = $codewriter->getFunctionPrefix() . $macroname . '($_thistpl, $tpl)'; + $codewriter->pushCode($code); + } + // external macro or ${macroname}, use PHPTAL at runtime to resolve it + else { + $code = $codewriter->interpolateTalesVarsInString($this->expression); + $codewriter->pushCode('$tpl->_executeMacroOfTemplate('.$code.', $_thistpl)'); + } + + $this->popSlots($codewriter); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + } + + /** + * reset template slots on each macro call ? + * + * NOTE: defining a macro and using another macro on the same tag + * means inheriting from the used macro, thus slots are shared, it + * is a little tricky to understand but very natural to use. + * + * For example, we may have a main design.html containing our main + * website presentation with some slots (menu, content, etc...) then + * we may define a member.html macro which use the design.html macro + * for the general layout, fill the menu slot and let caller templates + * fill the parent content slot without interfering. + */ + private function pushSlots(PHPTAL_Php_CodeWriter $codewriter) + { + if (!$this->phpelement->hasAttributeNS('http://xml.zope.org/namespaces/metal', 'define-macro')) { + $codewriter->pushCode('$ctx->pushSlots()'); + } + } + + /** + * generate code that pops macro slots + * (restore slots if not inherited macro) + */ + private function popSlots(PHPTAL_Php_CodeWriter $codewriter) + { + if (!$this->phpelement->hasAttributeNS('http://xml.zope.org/namespaces/metal', 'define-macro')) { + $codewriter->pushCode('$ctx->popSlots()'); + } + } + + /** + * recursively generates code for slots + */ + private function generateFillSlots(PHPTAL_Php_CodeWriter $codewriter, PHPTAL_Dom_Node $phpelement) + { + if (false == ($phpelement instanceof PHPTAL_Dom_Element)) { + return; + } + + // if the tag contains one of the allowed attribute, we generate it + foreach (self::$ALLOWED_ATTRIBUTES as $qname => $uri) { + if ($phpelement->hasAttributeNS($uri, $qname)) { + $phpelement->generateCode($codewriter); + return; + } + } + + foreach ($phpelement->childNodes as $child) { + $this->generateFillSlots($codewriter, $child); + } + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Cache.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Cache.php new file mode 100644 index 0000000..3504a22 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Cache.php @@ -0,0 +1,97 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * phptal:cache (note that's not tal:cache) caches element's HTML for a given time. Time is a number with 'd', 'h', 'm' or 's' suffix. + * There's optional parameter that defines how cache should be shared. By default cache is not sensitive to template's context at all + * - it's shared between all pages that use that template. + * You can add per url to have separate copy of given element for every URL. + * + * You can add per expression to have different cache copy for every different value of an expression (which MUST evaluate to a string). + * Expression cannot refer to variables defined using tal:define on the same element. + * + * NB: + * * phptal:cache blocks can be nested, but outmost block will cache other blocks regardless of their freshness. + * * you cannot use metal:fill-slot inside elements with phptal:cache + * + * Examples: + * <div phptal:cache="3h">...</div> <!-- <div> to be evaluated at most once per 3 hours. --> + * <ul phptal:cache="1d per object/id">...</ul> <!-- <ul> be cached for one day, separately for each object. --> + * + * @package PHPTAL + * @subpackage Php.attribute.phptal +*/ +class PHPTAL_Php_Attribute_PHPTAL_Cache extends PHPTAL_Php_Attribute +{ + private $cache_filename_var; + + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + // number or variable name followed by time unit + // optional per expression + if (!preg_match('/^\s*([0-9]+\s*|[a-zA-Z][\/a-zA-Z0-9_]*\s+)([dhms])\s*(?:\;?\s*per\s+([^;]+)|)\s*$/', $this->expression, $matches)) { + throw new PHPTAL_ParserException("Cache attribute syntax error: ".$this->expression, + $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + } + + $cache_len = $matches[1]; + if (!is_numeric($cache_len)) { + $cache_len = $codewriter->evaluateExpression($cache_len); + + if (is_array($cache_len)) throw new PHPTAL_ParserException("Chained expressions in cache length are not supported", + $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + } + switch ($matches[2]) { + case 'd': $cache_len .= '*24'; /* no break */ + case 'h': $cache_len .= '*60'; /* no break */ + case 'm': $cache_len .= '*60'; /* no break */ + } + + $cache_tag = '"'.addslashes( $this->phpelement->getQualifiedName() . ':' . $this->phpelement->getSourceLine()).'"'; + + $cache_per_expression = isset($matches[3])?trim($matches[3]):null; + if ($cache_per_expression == 'url') { + $cache_tag .= '.$_SERVER["REQUEST_URI"]'; + } elseif ($cache_per_expression == 'nothing') { + /* do nothing */ + } elseif ($cache_per_expression) { + $code = $codewriter->evaluateExpression($cache_per_expression); + + if (is_array($code)) throw new PHPTAL_ParserException("Chained expressions in per-cache directive are not supported", + $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + + $cache_tag = '('.$code.')."@".' . $cache_tag; + } + + $this->cache_filename_var = $codewriter->createTempVariable(); + $codewriter->doSetVar($this->cache_filename_var, $codewriter->str($codewriter->getCacheFilesBaseName()).'.md5('.$cache_tag.')' ); + + $cond = '!file_exists('.$this->cache_filename_var.') || time() - '.$cache_len.' >= filemtime('.$this->cache_filename_var.')'; + + $codewriter->doIf($cond); + $codewriter->doEval('ob_start()'); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->doEval('file_put_contents('.$this->cache_filename_var.', ob_get_flush())'); + $codewriter->doElse(); + $codewriter->doEval('readfile('.$this->cache_filename_var.')'); + $codewriter->doEnd('if'); + + $codewriter->recycleTempVariable($this->cache_filename_var); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Debug.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Debug.php new file mode 100644 index 0000000..d0e9c9b --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Debug.php @@ -0,0 +1,34 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ +/** + * @package PHPTAL + * @subpackage Php.attribute.phptal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_PHPTAL_Debug extends PHPTAL_Php_Attribute +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $this->_oldMode = $codewriter->setDebug(true); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->setDebug($this->_oldMode); + } + + private $_oldMode; +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Id.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Id.php new file mode 100644 index 0000000..dbee2a9 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Id.php @@ -0,0 +1,53 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ +/** + * @package PHPTAL + * @subpackage Php.attribute.phptal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_PHPTAL_ID extends PHPTAL_Php_Attribute +{ + private $var; + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + // retrieve trigger + $this->var = $codewriter->createTempVariable(); + + $codewriter->doSetVar( + $this->var, + '$tpl->getTrigger('.$codewriter->str($this->expression).')' + ); + + // if trigger found and trigger tells to proceed, we execute + // the node content + $codewriter->doIf($this->var.' && + '.$this->var.'->start('.$codewriter->str($this->expression).', $tpl) === PHPTAL_Trigger::PROCEED'); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + // end of if PROCEED + $codewriter->doEnd('if'); + + // if trigger found, notify the end of the node + $codewriter->doIf($this->var); + $codewriter->pushCode( + $this->var.'->end('.$codewriter->str($this->expression).', $tpl)' + ); + $codewriter->doEnd('if'); + $codewriter->recycleTempVariable($this->var); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Tales.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Tales.php new file mode 100644 index 0000000..f1fb4d7 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/PHPTAL/Tales.php @@ -0,0 +1,45 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ +/** + * @package PHPTAL + * @subpackage Php.attribute.phptal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_PHPTAL_TALES extends PHPTAL_Php_Attribute +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $mode = trim($this->expression); + $mode = strtolower($mode); + + if ($mode == '' || $mode == 'default') + $mode = 'tales'; + + if ($mode != 'php' && $mode != 'tales') { + throw new PHPTAL_TemplateException("Unsupported TALES mode '$mode'", + $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + } + + $this->_oldMode = $codewriter->setTalesMode($mode); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->setTalesMode($this->_oldMode); + } + + private $_oldMode; +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Attributes.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Attributes.php new file mode 100644 index 0000000..158d079 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Attributes.php @@ -0,0 +1,213 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * TAL Specifications 1.4 + * + * argument ::= attribute_statement [';' attribute_statement]* + * attribute_statement ::= attribute_name expression + * attribute_name ::= [namespace ':'] Name + * namespace ::= Name + * + * examples: + * + * <a href="/sample/link.html" + * tal:attributes="href here/sub/absolute_url"> + * <textarea rows="80" cols="20" + * tal:attributes="rows request/rows;cols request/cols"> + * + * IN PHPTAL: attributes will not work on structured replace. + * + * @package PHPTAL + * @subpackage Php.attribute.tal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_TAL_Attributes +extends PHPTAL_Php_Attribute +implements PHPTAL_Php_TalesChainReader +{ + /** before creates several variables that need to be freed in after */ + private $vars_to_recycle = array(); + + /** + * value for default keyword + */ + private $_default_escaped; + + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + // split attributes using ; delimiter + $attrs = $codewriter->splitExpression($this->expression); + foreach ($attrs as $exp) { + list($qname, $expression) = $this->parseSetExpression($exp); + if ($expression) { + $this->prepareAttribute($codewriter, $qname, $expression); + } + } + } + + private function prepareAttribute(PHPTAL_Php_CodeWriter $codewriter, $qname, $expression) + { + $tales_code = $this->extractEchoType($expression); + $code = $codewriter->evaluateExpression($tales_code); + + // XHTML boolean attribute does not appear when empty or false + if (PHPTAL_Dom_Defs::getInstance()->isBooleanAttribute($qname)) { + + // I don't want to mix code for boolean with chained executor + // so compile it again to simple expression + if (is_array($code)) { + $code = PHPTAL_Php_TalesInternal::compileToPHPExpression($tales_code); + } + return $this->prepareBooleanAttribute($codewriter, $qname, $code); + } + + // if $code is an array then the attribute value is decided by a + // tales chained expression + if (is_array($code)) { + return $this->prepareChainedAttribute($codewriter, $qname, $code); + } + + // i18n needs to read replaced value of the attribute, which is not possible if attribute is completely replaced with conditional code + if ($this->phpelement->hasAttributeNS('http://xml.zope.org/namespaces/i18n', 'attributes')) { + $this->prepareAttributeUnconditional($codewriter, $qname, $code); + } else { + $this->prepareAttributeConditional($codewriter, $qname, $code); + } + } + + /** + * attribute will be output regardless of its evaluated value. NULL behaves just like "". + */ + private function prepareAttributeUnconditional(PHPTAL_Php_CodeWriter $codewriter, $qname, $code) + { + // regular attribute which value is the evaluation of $code + $attkey = $this->getVarName($qname, $codewriter); + if ($this->_echoType == PHPTAL_Php_Attribute::ECHO_STRUCTURE) { + $value = $codewriter->stringifyCode($code); + } else { + $value = $codewriter->escapeCode($code); + } + $codewriter->doSetVar($attkey, $value); + $this->phpelement->getOrCreateAttributeNode($qname)->overwriteValueWithVariable($attkey); + } + + /** + * If evaluated value of attribute is NULL, it will not be output at all. + */ + private function prepareAttributeConditional(PHPTAL_Php_CodeWriter $codewriter, $qname, $code) + { + // regular attribute which value is the evaluation of $code + $attkey = $this->getVarName($qname, $codewriter); + + $codewriter->doIf("null !== ($attkey = ($code))"); + + if ($this->_echoType !== PHPTAL_Php_Attribute::ECHO_STRUCTURE) + $codewriter->doSetVar($attkey, $codewriter->str(" $qname=\"").".".$codewriter->escapeCode($attkey).".'\"'"); + else + $codewriter->doSetVar($attkey, $codewriter->str(" $qname=\"").".".$codewriter->stringifyCode($attkey).".'\"'"); + + $codewriter->doElse(); + $codewriter->doSetVar($attkey, "''"); + $codewriter->doEnd('if'); + + $this->phpelement->getOrCreateAttributeNode($qname)->overwriteFullWithVariable($attkey); + } + + private function prepareChainedAttribute(PHPTAL_Php_CodeWriter $codewriter, $qname, $chain) + { + $this->_default_escaped = false; + $this->_attribute = $qname; + if ($default_attr = $this->phpelement->getAttributeNode($qname)) { + $this->_default_escaped = $default_attr->getValueEscaped(); + } + $this->_attkey = $this->getVarName($qname, $codewriter); + $executor = new PHPTAL_Php_TalesChainExecutor($codewriter, $chain, $this); + $this->phpelement->getOrCreateAttributeNode($qname)->overwriteFullWithVariable($this->_attkey); + } + + private function prepareBooleanAttribute(PHPTAL_Php_CodeWriter $codewriter, $qname, $code) + { + $attkey = $this->getVarName($qname, $codewriter); + + if ($codewriter->getOutputMode() === PHPTAL::HTML5) { + $value = "' $qname'"; + } else { + $value = "' $qname=\"$qname\"'"; + } + $codewriter->doIf($code); + $codewriter->doSetVar($attkey, $value); + $codewriter->doElse(); + $codewriter->doSetVar($attkey, '\'\''); + $codewriter->doEnd('if'); + $this->phpelement->getOrCreateAttributeNode($qname)->overwriteFullWithVariable($attkey); + } + + private function getVarName($qname, PHPTAL_Php_CodeWriter $codewriter) + { + $var = $codewriter->createTempVariable(); + $this->vars_to_recycle[] = $var; + return $var; + } + + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + foreach ($this->vars_to_recycle as $var) $codewriter->recycleTempVariable($var); + } + + public function talesChainNothingKeyword(PHPTAL_Php_TalesChainExecutor $executor) + { + $codewriter = $executor->getCodeWriter(); + $executor->doElse(); + $codewriter->doSetVar( + $this->_attkey, + "''" + ); + $executor->breakChain(); + } + + public function talesChainDefaultKeyword(PHPTAL_Php_TalesChainExecutor $executor) + { + $codewriter = $executor->getCodeWriter(); + $executor->doElse(); + $attr_str = ($this->_default_escaped !== false) + ? ' '.$this->_attribute.'='.$codewriter->quoteAttributeValue($this->_default_escaped) // default value + : ''; // do not print attribute + $codewriter->doSetVar($this->_attkey, $codewriter->str($attr_str)); + $executor->breakChain(); + } + + public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $exp, $islast) + { + $codewriter = $executor->getCodeWriter(); + + if (!$islast) { + $condition = "!phptal_isempty($this->_attkey = ($exp))"; + } else { + $condition = "null !== ($this->_attkey = ($exp))"; + } + $executor->doIf($condition); + + if ($this->_echoType == PHPTAL_Php_Attribute::ECHO_STRUCTURE) + $value = $codewriter->stringifyCode($this->_attkey); + else + $value = $codewriter->escapeCode($this->_attkey); + + $codewriter->doSetVar($this->_attkey, $codewriter->str(" {$this->_attribute}=\"").".$value.'\"'"); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Comment.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Comment.php new file mode 100644 index 0000000..4e5896e --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Comment.php @@ -0,0 +1,30 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ +/** + * @package PHPTAL + * @subpackage Php.attribute.tal + */ +class PHPTAL_Php_Attribute_TAL_Comment extends PHPTAL_Php_Attribute +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->doComment($this->expression); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Condition.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Condition.php new file mode 100644 index 0000000..d86b94b --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Condition.php @@ -0,0 +1,93 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * TAL Specifications 1.4 + * + * argument ::= expression + * + * Example: + * + * <p tal:condition="here/copyright" + * tal:content="here/copyright">(c) 2000</p> + * + * + * + * + * @package PHPTAL + * @subpackage Php.attribute.tal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_TAL_Condition +extends PHPTAL_Php_Attribute +implements PHPTAL_Php_TalesChainReader +{ + private $expressions = array(); + + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $code = $codewriter->evaluateExpression($this->expression); + + // If it's a chained expression build a new code path + if (is_array($code)) { + $this->expressions = array(); + $executor = new PHPTAL_Php_TalesChainExecutor($codewriter, $code, $this); + return; + } + + // Force a falsy condition if the nothing keyword is active + if ($code == PHPTAL_Php_TalesInternal::NOTHING_KEYWORD) { + $code = 'false'; + } + + $codewriter->doIf('phptal_true(' . $code . ')'); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->doEnd('if'); + } + + + public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $exp, $islast) + { + // check if the expression is empty + if ($exp !== 'false') { + $this->expressions[] = '!phptal_isempty(' . $exp . ')'; + } + + if ($islast) { + // for the last one in the chain build a ORed condition + $executor->getCodeWriter()->doIf( implode(' || ', $this->expressions ) ); + // The executor will always end an if so we output a dummy if + $executor->doIf('false'); + } + } + + public function talesChainNothingKeyword(PHPTAL_Php_TalesChainExecutor $executor) + { + // end the chain + $this->talesChainPart($executor, 'false', true); + $executor->breakChain(); + } + + public function talesChainDefaultKeyword(PHPTAL_Php_TalesChainExecutor $executor) + { + throw new PHPTAL_ParserException('\'default\' keyword not allowed on conditional expressions', + $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + } + +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Content.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Content.php new file mode 100644 index 0000000..aef5865 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Content.php @@ -0,0 +1,95 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** TAL Specifications 1.4 + * + * argument ::= (['text'] | 'structure') expression + * + * Example: + * + * <p tal:content="user/name">Fred Farkas</p> + * + * + * + * + * @package PHPTAL + * @subpackage Php.attribute.tal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_TAL_Content +extends PHPTAL_Php_Attribute +implements PHPTAL_Php_TalesChainReader +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $expression = $this->extractEchoType($this->expression); + + $code = $codewriter->evaluateExpression($expression); + + if (is_array($code)) { + return $this->generateChainedContent($codewriter, $code); + } + + if ($code == PHPTAL_Php_TalesInternal::NOTHING_KEYWORD) { + return; + } + + if ($code == PHPTAL_Php_TalesInternal::DEFAULT_KEYWORD) { + return $this->generateDefault($codewriter); + } + + $this->doEchoAttribute($codewriter, $code); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + } + + private function generateDefault(PHPTAL_Php_CodeWriter $codewriter) + { + $this->phpelement->generateContent($codewriter, true); + } + + protected function generateChainedContent(PHPTAL_Php_CodeWriter $codewriter, $code) + { + $executor = new PHPTAL_Php_TalesChainExecutor($codewriter, $code, $this); + } + + public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $exp, $islast) + { + if (!$islast) { + $var = $executor->getCodeWriter()->createTempVariable(); + $executor->doIf('!phptal_isempty('.$var.' = '.$exp.')'); + $this->doEchoAttribute($executor->getCodeWriter(), $var); + $executor->getCodeWriter()->recycleTempVariable($var); + } else { + $executor->doElse(); + $this->doEchoAttribute($executor->getCodeWriter(), $exp); + } + } + + public function talesChainNothingKeyword(PHPTAL_Php_TalesChainExecutor $executor) + { + $executor->breakChain(); + } + + public function talesChainDefaultKeyword(PHPTAL_Php_TalesChainExecutor $executor) + { + $executor->doElse(); + $this->generateDefault($executor->getCodeWriter()); + $executor->breakChain(); + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Define.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Define.php new file mode 100644 index 0000000..f5c074b --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Define.php @@ -0,0 +1,193 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * TAL spec 1.4 for tal:define content + * + * argument ::= define_scope [';' define_scope]* + * define_scope ::= (['local'] | 'global') define_var + * define_var ::= variable_name expression + * variable_name ::= Name + * + * Note: If you want to include a semi-colon (;) in an expression, it must be escaped by doubling it (;;).* + * + * examples: + * + * tal:define="mytitle template/title; tlen python:len(mytitle)" + * tal:define="global company_name string:Digital Creations, Inc." + * + * + * + * @package PHPTAL + * @subpackage Php.attribute.tal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_TAL_Define +extends PHPTAL_Php_Attribute +implements PHPTAL_Php_TalesChainReader +{ + private $tmp_content_var; + private $_buffered = false; + private $_defineScope = null; + private $_defineVar = null; + private $_pushedContext = false; + /** + * Prevents generation of invalid PHP code when given invalid TALES + */ + private $_chainPartGenerated=false; + + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $expressions = $codewriter->splitExpression($this->expression); + $definesAnyNonGlobalVars = false; + + foreach ($expressions as $exp) { + list($defineScope, $defineVar, $expression) = $this->parseExpression($exp); + if (!$defineVar) { + continue; + } + + $this->_defineScope = $defineScope; + + // <span tal:define="global foo" /> should be invisible, but <img tal:define="bar baz" /> not + if ($defineScope != 'global') $definesAnyNonGlobalVars = true; + + if ($this->_defineScope != 'global' && !$this->_pushedContext) { + $codewriter->pushContext(); + $this->_pushedContext = true; + } + + $this->_defineVar = $defineVar; + if ($expression === null) { + // no expression give, use content of tag as value for newly defined var. + $this->bufferizeContent($codewriter); + continue; + } + + $code = $codewriter->evaluateExpression($expression); + if (is_array($code)) { + $this->chainedDefine($codewriter, $code); + } elseif ( $code == PHPTAL_Php_TalesInternal::NOTHING_KEYWORD) { + $this->doDefineVarWith($codewriter, 'null'); + } else { + $this->doDefineVarWith($codewriter, $code); + } + } + + // if the content of the tag was buffered or the tag has nothing to tell, we hide it. + if ($this->_buffered || (!$definesAnyNonGlobalVars && !$this->phpelement->hasRealContent() && !$this->phpelement->hasRealAttributes())) { + $this->phpelement->hidden = true; + } + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + if ($this->tmp_content_var) $codewriter->recycleTempVariable($this->tmp_content_var); + if ($this->_pushedContext) { + $codewriter->popContext(); + } + } + + private function chainedDefine(PHPTAL_Php_CodeWriter $codewriter, $parts) + { + $executor = new PHPTAL_Php_TalesChainExecutor( + $codewriter, $parts, $this + ); + } + + public function talesChainNothingKeyword(PHPTAL_Php_TalesChainExecutor $executor) + { + if (!$this->_chainPartGenerated) throw new PHPTAL_TemplateException("Invalid expression in tal:define", $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + + $executor->doElse(); + $this->doDefineVarWith($executor->getCodeWriter(), 'null'); + $executor->breakChain(); + } + + public function talesChainDefaultKeyword(PHPTAL_Php_TalesChainExecutor $executor) + { + if (!$this->_chainPartGenerated) throw new PHPTAL_TemplateException("Invalid expression in tal:define", $this->phpelement->getSourceFile(), $this->phpelement->getSourceLine()); + + $executor->doElse(); + $this->bufferizeContent($executor->getCodeWriter()); + $executor->breakChain(); + } + + public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $exp, $islast) + { + $this->_chainPartGenerated=true; + + if ($this->_defineScope == 'global') { + $var = '$tpl->getGlobalContext()->'.$this->_defineVar; + } else { + $var = '$ctx->'.$this->_defineVar; + } + + $cw = $executor->getCodeWriter(); + + if (!$islast) { + // must use temp variable, because expression could refer to itself + $tmp = $cw->createTempVariable(); + $executor->doIf('('.$tmp.' = '.$exp.') !== null'); + $cw->doSetVar($var, $tmp); + $cw->recycleTempVariable($tmp); + } else { + $executor->doIf('('.$var.' = '.$exp.') !== null'); + } + } + + /** + * Parse the define expression, already splitted in sub parts by ';'. + */ + public function parseExpression($exp) + { + $defineScope = false; // (local | global) + $defineVar = false; // var to define + + // extract defineScope from expression + $exp = trim($exp); + if (preg_match('/^(local|global)\s+(.*?)$/ism', $exp, $m)) { + list(, $defineScope, $exp) = $m; + $exp = trim($exp); + } + + // extract varname and expression from remaining of expression + list($defineVar, $exp) = $this->parseSetExpression($exp); + if ($exp !== null) $exp = trim($exp); + return array($defineScope, $defineVar, $exp); + } + + private function bufferizeContent(PHPTAL_Php_CodeWriter $codewriter) + { + if (!$this->_buffered) { + $this->tmp_content_var = $codewriter->createTempVariable(); + $codewriter->pushCode( 'ob_start()' ); + $this->phpelement->generateContent($codewriter); + $codewriter->doSetVar($this->tmp_content_var, 'ob_get_clean()'); + $this->_buffered = true; + } + $this->doDefineVarWith($codewriter, $this->tmp_content_var); + } + + private function doDefineVarWith(PHPTAL_Php_CodeWriter $codewriter, $code) + { + if ($this->_defineScope == 'global') { + $codewriter->doSetVar('$tpl->getGlobalContext()->'.$this->_defineVar, $code); + } else { + $codewriter->doSetVar('$ctx->'.$this->_defineVar, $code); + } + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/OmitTag.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/OmitTag.php new file mode 100644 index 0000000..d7530b3 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/OmitTag.php @@ -0,0 +1,70 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * TAL Specifications 1.4 + * + * argument ::= [expression] + * + * Example: + * + * <div tal:omit-tag="" comment="This tag will be removed"> + * <i>...but this text will remain.</i> + * </div> + * + * <b tal:omit-tag="not:bold">I may not be bold.</b> + * + * To leave the contents of a tag in place while omitting the surrounding + * start and end tag, use the omit-tag statement. + * + * If its expression evaluates to a false value, then normal processing + * of the element continues. + * + * If the expression evaluates to a true value, or there is no + * expression, the statement tag is replaced with its contents. It is up to + * the interface between TAL and the expression engine to determine the + * value of true and false. For these purposes, the value nothing is false, + * and cancellation of the action has the same effect as returning a + * false value. + * + * + * @package PHPTAL + * @subpackage Php.attribute.tal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_TAL_OmitTag extends PHPTAL_Php_Attribute +{ + private $varname; + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + if (trim($this->expression) == '') { + $this->phpelement->headFootDisabled = true; + } else { + + $this->varname = $codewriter->createTempVariable(); + + // print tag header/foot only if condition is false + $cond = $codewriter->evaluateExpression($this->expression); + $this->phpelement->headPrintCondition = '('.$this->varname.' = !phptal_unravel_closure('.$cond.'))'; + $this->phpelement->footPrintCondition = $this->varname; + } + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + if ($this->varname) $codewriter->recycleTempVariable($this->varname); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/OnError.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/OnError.php new file mode 100644 index 0000000..382d387 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/OnError.php @@ -0,0 +1,73 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * TAL Specifications 1.4 + * + * argument ::= (['text'] | 'structure') expression + * + * Example: + * + * <p tal:on-error="string: Error! This paragraph is buggy!"> + * My name is <span tal:replace="here/SlimShady" />.<br /> + * (My login name is + * <b tal:on-error="string: Username is not defined!" + * tal:content="user">Unknown</b>) + * </p> + * + * @package PHPTAL + * @subpackage Php.attribute.tal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_TAL_OnError extends PHPTAL_Php_Attribute +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->doTry(); + $codewriter->pushCode('ob_start()'); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + $var = $codewriter->createTempVariable(); + + $codewriter->pushCode('ob_end_flush()'); + $codewriter->doCatch('Exception '.$var); + $codewriter->pushCode('$tpl->addError('.$var.')'); + $codewriter->pushCode('ob_end_clean()'); + + $expression = $this->extractEchoType($this->expression); + + $code = $codewriter->evaluateExpression($expression); + switch ($code) { + case PHPTAL_Php_TalesInternal::NOTHING_KEYWORD: + break; + + case PHPTAL_Php_TalesInternal::DEFAULT_KEYWORD: + $codewriter->pushHTML('<pre class="phptalError">'); + $codewriter->doEcho($var); + $codewriter->pushHTML('</pre>'); + break; + + default: + $this->doEchoAttribute($codewriter, $code); + break; + } + $codewriter->doEnd('catch'); + + $codewriter->recycleTempVariable($var); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Repeat.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Repeat.php new file mode 100644 index 0000000..d0e4c2d --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Repeat.php @@ -0,0 +1,99 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * TAL Specifications 1.4 + * + * argument ::= variable_name expression + * variable_name ::= Name + * + * Example: + * + * <p tal:repeat="txt python:'one', 'two', 'three'"> + * <span tal:replace="txt" /> + * </p> + * <table> + * <tr tal:repeat="item here/cart"> + * <td tal:content="repeat/item/index">1</td> + * <td tal:content="item/description">Widget</td> + * <td tal:content="item/price">$1.50</td> + * </tr> + * </table> + * + * The following information is available from an Iterator: + * + * * index - repetition number, starting from zero. + * * number - repetition number, starting from one. + * * even - true for even-indexed repetitions (0, 2, 4, ...). + * * odd - true for odd-indexed repetitions (1, 3, 5, ...). + * * start - true for the starting repetition (index 0). + * * end - true for the ending, or final, repetition. + * * length - length of the sequence, which will be the total number of repetitions. + * + * * letter - count reps with lower-case letters: "a" - "z", "aa" - "az", "ba" - "bz", ..., "za" - "zz", "aaa" - "aaz", and so forth. + * * Letter - upper-case version of letter. + * * roman - count reps with lower-case roman numerals: "i", "ii", "iii", "iv", "v", "vi" ... + * * Roman - upper-case version of roman numerals. + * * first - true for the first item in a group - see note below + * * lasst - true for the last item in a group - see note below + * + * Note: first and last are intended for use with sorted sequences. They try to + * divide the sequence into group of items with the same value. If you provide + * a path, then the value obtained by following that path from a sequence item + * is used for grouping, otherwise the value of the item is used. You can + * provide the path by appending it to the path from the repeat variable, + * as in "repeat/item/first/color". + * + * PHPTAL: index, number, even, etc... will be stored in the + * $ctx->repeat->'item' object. Thus $ctx->repeat->item->odd + * + * + * + * + * @package PHPTAL + * @subpackage Php.attribute.tal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_TAL_Repeat extends PHPTAL_Php_Attribute +{ + private $var; + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + $this->var = $codewriter->createTempVariable(); + + // alias to repeats handler to avoid calling extra getters on each variable access + $codewriter->doSetVar($this->var, '$ctx->repeat'); + + list($varName, $expression) = $this->parseSetExpression($this->expression); + $code = $codewriter->evaluateExpression($expression); + + // instantiate controller using expression + $codewriter->doSetVar( $this->var.'->'.$varName, 'new PHPTAL_RepeatController('.$code.')'."\n" ); + + $codewriter->pushContext(); + + // Lets loop the iterator with a foreach construct + $codewriter->doForeach('$ctx->'.$varName, $this->var.'->'.$varName); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + $codewriter->doEnd('foreach'); + $codewriter->popContext(); + + $codewriter->recycleTempVariable($this->var); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Replace.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Replace.php new file mode 100644 index 0000000..b72cafa --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Attribute/TAL/Replace.php @@ -0,0 +1,117 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ +/** + * TAL Specifications 1.4 + * + * argument ::= (['text'] | 'structure') expression + * + * Default behaviour : text + * + * <span tal:replace="template/title">Title</span> + * <span tal:replace="text template/title">Title</span> + * <span tal:replace="structure table" /> + * <span tal:replace="nothing">This element is a comment.</span> + * + * + * + * @package PHPTAL + * @subpackage Php.attribute.tal + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Attribute_TAL_Replace +extends PHPTAL_Php_Attribute +implements PHPTAL_Php_TalesChainReader +{ + public function before(PHPTAL_Php_CodeWriter $codewriter) + { + // tal:replace="" => do nothing and ignore node + if (trim($this->expression) == "") { + return; + } + + $expression = $this->extractEchoType($this->expression); + $code = $codewriter->evaluateExpression($expression); + + // chained expression + if (is_array($code)) { + return $this->replaceByChainedExpression($codewriter, $code); + } + + // nothing do nothing + if ($code == PHPTAL_Php_TalesInternal::NOTHING_KEYWORD) { + return; + } + + // default generate default tag content + if ($code == PHPTAL_Php_TalesInternal::DEFAULT_KEYWORD) { + return $this->generateDefault($codewriter); + } + + // replace tag with result of expression + $this->doEchoAttribute($codewriter, $code); + } + + public function after(PHPTAL_Php_CodeWriter $codewriter) + { + } + + /** + * support expressions like "foo | bar" + */ + private function replaceByChainedExpression(PHPTAL_Php_CodeWriter $codewriter, $expArray) + { + $executor = new PHPTAL_Php_TalesChainExecutor( + $codewriter, $expArray, $this + ); + } + + public function talesChainNothingKeyword(PHPTAL_Php_TalesChainExecutor $executor) + { + $executor->continueChain(); + } + + public function talesChainDefaultKeyword(PHPTAL_Php_TalesChainExecutor $executor) + { + $executor->doElse(); + $this->generateDefault($executor->getCodeWriter()); + $executor->breakChain(); + } + + public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $exp, $islast) + { + if (!$islast) { + $var = $executor->getCodeWriter()->createTempVariable(); + $executor->doIf('!phptal_isempty('.$var.' = '.$exp.')'); + $this->doEchoAttribute($executor->getCodeWriter(), $var); + $executor->getCodeWriter()->recycleTempVariable($var); + } else { + $executor->doElse(); + $this->doEchoAttribute($executor->getCodeWriter(), $exp); + } + } + + /** + * don't replace - re-generate default content + */ + private function generateDefault(PHPTAL_Php_CodeWriter $codewriter) + { + $this->phpelement->generateSurroundHead($codewriter); + $this->phpelement->generateHead($codewriter); + $this->phpelement->generateContent($codewriter); + $this->phpelement->generateFoot($codewriter); + $this->phpelement->generateSurroundFoot($codewriter); + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/CodeWriter.php b/src/core/libs/PHPTAL5/PHPTAL/Php/CodeWriter.php new file mode 100644 index 0000000..44ee063 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/CodeWriter.php @@ -0,0 +1,511 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ +/** + * Helps generate php representation of a template. + * + * @package PHPTAL + * @subpackage Php + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_CodeWriter +{ + /** + * max id of variable to give as temp + */ + private $temp_var_counter=0; + /** + * stack with free'd variables + */ + private $temp_recycling=array(); + + /** + * keeps track of seen functions for function_exists + */ + private $known_functions = array(); + + + public function __construct(PHPTAL_Php_State $state) + { + $this->_state = $state; + } + + public function createTempVariable() + { + if (count($this->temp_recycling)) return array_shift($this->temp_recycling); + return '$_tmp_'.(++$this->temp_var_counter); + } + + public function recycleTempVariable($var) + { + if (substr($var, 0, 6)!=='$_tmp_') throw new PHPTAL_Exception("Invalid variable recycled"); + $this->temp_recycling[] = $var; + } + + public function getCacheFilesBaseName() + { + return $this->_state->getCacheFilesBaseName(); + } + + public function getResult() + { + $this->flush(); + if (version_compare(PHP_VERSION, '5.3', '>=') && __NAMESPACE__) { + return '<?php use '.'PHPTALNAMESPACE as P; ?>'.trim($this->_result); + } else { + return trim($this->_result); + } + } + + /** + * set full '<!DOCTYPE...>' string to output later + * + * @param string $dt + * + * @return void + */ + public function setDocType($dt) + { + $this->_doctype = $dt; + } + + /** + * set full '<?xml ?>' string to output later + * + * @param string $dt + * + * @return void + */ + public function setXmlDeclaration($dt) + { + $this->_xmldeclaration = $dt; + } + + /** + * functions later generated and checked for existence will have this prefix added + * (poor man's namespace) + * + * @param string $prefix + * + * @return void + */ + public function setFunctionPrefix($prefix) + { + $this->_functionPrefix = $prefix; + } + + /** + * @return string + */ + public function getFunctionPrefix() + { + return $this->_functionPrefix; + } + + /** + * @see PHPTAL_Php_State::setTalesMode() + * + * @param string $mode + * + * @return string + */ + public function setTalesMode($mode) + { + return $this->_state->setTalesMode($mode); + } + + public function splitExpression($src) + { + preg_match_all('/(?:[^;]+|;;)+/sm', $src, $array); + $array = $array[0]; + foreach ($array as &$a) $a = str_replace(';;', ';', $a); + return $array; + } + + public function evaluateExpression($src) + { + return $this->_state->evaluateExpression($src); + } + + public function indent() + { + $this->_indentation ++; + } + + public function unindent() + { + $this->_indentation --; + } + + public function flush() + { + $this->flushCode(); + $this->flushHtml(); + } + + public function noThrow($bool) + { + if ($bool) { + $this->pushCode('$ctx->noThrow(true)'); + } else { + $this->pushCode('$ctx->noThrow(false)'); + } + } + + public function flushCode() + { + if (count($this->_codeBuffer) == 0) return; + + // special treatment for one code line + if (count($this->_codeBuffer) == 1) { + $codeLine = $this->_codeBuffer[0]; + // avoid adding ; after } and { + if (!preg_match('/\}\s*$|\{\s*$/', $codeLine)) + $this->_result .= '<?php '.$codeLine."; ?>\n"; // PHP consumes newline + else + $this->_result .= '<?php '.$codeLine." ?>\n"; // PHP consumes newline + $this->_codeBuffer = array(); + return; + } + + $this->_result .= '<?php '."\n"; + foreach ($this->_codeBuffer as $codeLine) { + // avoid adding ; after } and { + if (!preg_match('/[{};]\s*$/', $codeLine)) { + $codeLine .= ' ;'."\n"; + } + $this->_result .= $codeLine; + } + $this->_result .= "?>\n";// PHP consumes newline + $this->_codeBuffer = array(); + } + + public function flushHtml() + { + if (count($this->_htmlBuffer) == 0) return; + + $this->_result .= implode('', $this->_htmlBuffer); + $this->_htmlBuffer = array(); + } + + /** + * Generate code for setting DOCTYPE + * + * @param bool $called_from_macro for error checking: unbuffered output doesn't support that + */ + public function doDoctype($called_from_macro = false) + { + if ($this->_doctype) { + $code = '$ctx->setDocType('.$this->str($this->_doctype).','.($called_from_macro?'true':'false').')'; + $this->pushCode($code); + } + } + + /** + * Generate XML declaration + * + * @param bool $called_from_macro for error checking: unbuffered output doesn't support that + */ + public function doXmlDeclaration($called_from_macro = false) + { + if ($this->_xmldeclaration && $this->getOutputMode() !== PHPTAL::HTML5) { + $code = '$ctx->setXmlDeclaration('.$this->str($this->_xmldeclaration).','.($called_from_macro?'true':'false').')'; + $this->pushCode($code); + } + } + + public function functionExists($name) + { + return isset($this->known_functions[$this->_functionPrefix . $name]); + } + + public function doTemplateFile($functionName, PHPTAL_Dom_Element $treeGen) + { + $this->doComment("\n*** DO NOT EDIT THIS FILE ***\n\nGenerated by PHPTAL from ".$treeGen->getSourceFile()." (edit that file instead)"); + $this->doFunction($functionName, 'PHPTAL $tpl, PHPTAL_Context $ctx'); + $this->setFunctionPrefix($functionName . "_"); + $this->doSetVar('$_thistpl', '$tpl'); + $this->doInitTranslator(); + $treeGen->generateCode($this); + $this->doComment("end"); + $this->doEnd('function'); + } + + public function doFunction($name, $params) + { + $name = $this->_functionPrefix . $name; + $this->known_functions[$name] = true; + + $this->pushCodeWriterContext(); + $this->pushCode("function $name($params) {\n"); + $this->indent(); + $this->_segments[] = 'function'; + } + + public function doComment($comment) + { + $comment = str_replace('*/', '* /', $comment); + $this->pushCode("/* $comment */"); + } + + public function doInitTranslator() + { + if ($this->_state->isTranslationOn()) { + $this->doSetVar('$_translator', '$tpl->getTranslator()'); + } + } + + public function getTranslatorReference() + { + if (!$this->_state->isTranslationOn()) { + throw new PHPTAL_ConfigurationException("i18n used, but Translator has not been set"); + } + return '$_translator'; + } + + public function doEval($code) + { + $this->pushCode($code); + } + + public function doForeach($out, $source) + { + $this->_segments[] = 'foreach'; + $this->pushCode("foreach ($source as $out):"); + $this->indent(); + } + + public function doEnd($expects = null) + { + if (!count($this->_segments)) { + if (!$expects) $expects = 'anything'; + throw new PHPTAL_Exception("Bug: CodeWriter generated end of block without $expects open"); + } + + $segment = array_pop($this->_segments); + if ($expects !== null && $segment !== $expects) { + throw new PHPTAL_Exception("Bug: CodeWriter generated end of $expects, but needs to close $segment"); + } + + $this->unindent(); + if ($segment == 'function') { + $this->pushCode("\n}\n\n"); + $this->flush(); + $functionCode = $this->_result; + $this->popCodeWriterContext(); + $this->_result = $functionCode . $this->_result; + } elseif ($segment == 'try') + $this->pushCode('}'); + elseif ($segment == 'catch') + $this->pushCode('}'); + else + $this->pushCode("end$segment"); + } + + public function doTry() + { + $this->_segments[] = 'try'; + $this->pushCode('try {'); + $this->indent(); + } + + public function doSetVar($varname, $code) + { + $this->pushCode($varname.' = '.$code); + } + + public function doCatch($catch) + { + $this->doEnd('try'); + $this->_segments[] = 'catch'; + $this->pushCode('catch('.$catch.') {'); + $this->indent(); + } + + public function doIf($condition) + { + $this->_segments[] = 'if'; + $this->pushCode('if ('.$condition.'): '); + $this->indent(); + } + + public function doElseIf($condition) + { + if (end($this->_segments) !== 'if') { + throw new PHPTAL_Exception("Bug: CodeWriter generated elseif without if"); + } + $this->unindent(); + $this->pushCode('elseif ('.$condition.'): '); + $this->indent(); + } + + public function doElse() + { + if (end($this->_segments) !== 'if') { + throw new PHPTAL_Exception("Bug: CodeWriter generated else without if"); + } + $this->unindent(); + $this->pushCode('else: '); + $this->indent(); + } + + public function doEcho($code) + { + if ($code === "''") return; + $this->flush(); + $this->pushCode('echo '.$this->escapeCode($code)); + } + + public function doEchoRaw($code) + { + if ($code === "''") return; + $this->pushCode('echo '.$this->stringifyCode($code)); + } + + public function interpolateHTML($html) + { + return $this->_state->interpolateTalesVarsInHtml($html); + } + + public function interpolateCDATA($str) + { + return $this->_state->interpolateTalesVarsInCDATA($str); + } + + public function pushHTML($html) + { + if ($html === "") return; + $this->flushCode(); + $this->_htmlBuffer[] = $html; + } + + public function pushCode($codeLine) + { + $this->flushHtml(); + $codeLine = $this->indentSpaces() . $codeLine; + $this->_codeBuffer[] = $codeLine; + } + + /** + * php string with escaped text + */ + public function str($string) + { + return "'".strtr($string,array("'"=>'\\\'','\\'=>'\\\\'))."'"; + } + + public function escapeCode($code) + { + return $this->_state->htmlchars($code); + } + + public function stringifyCode($code) + { + return $this->_state->stringify($code); + } + + public function getEncoding() + { + return $this->_state->getEncoding(); + } + + public function interpolateTalesVarsInString($src) + { + return $this->_state->interpolateTalesVarsInString($src); + } + + public function setDebug($bool) + { + return $this->_state->setDebug($bool); + } + + public function isDebugOn() + { + return $this->_state->isDebugOn(); + } + + public function getOutputMode() + { + return $this->_state->getOutputMode(); + } + + public function quoteAttributeValue($value) + { + // FIXME: interpolation is done _after_ that function, so ${} must be forbidden for now + + if ($this->getEncoding() == 'UTF-8') // HTML 5: 8.1.2.3 Attributes ; http://code.google.com/p/html5lib/issues/detail?id=93 + { + // regex excludes unicode control characters, all kinds of whitespace and unsafe characters + // and trailing / to avoid confusion with self-closing syntax + $unsafe_attr_regex = '/^$|[&=\'"><\s`\pM\pC\pZ\p{Pc}\p{Sk}]|\/$|\${/u'; + } else { + $unsafe_attr_regex = '/^$|[&=\'"><\s`\0177-\377]|\/$|\${/'; + } + + if ($this->getOutputMode() == PHPTAL::HTML5 && !preg_match($unsafe_attr_regex, $value)) { + return $value; + } else { + return '"'.$value.'"'; + } + } + + public function pushContext() + { + $this->doSetVar('$ctx', '$tpl->pushContext()'); + } + + public function popContext() + { + $this->doSetVar('$ctx', '$tpl->popContext()'); + } + + // ~~~~~ Private members ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + private function indentSpaces() + { + return str_repeat("\t", $this->_indentation); + } + + private function pushCodeWriterContext() + { + $this->_contexts[] = clone $this; + $this->_result = ""; + $this->_indentation = 0; + $this->_codeBuffer = array(); + $this->_htmlBuffer = array(); + $this->_segments = array(); + } + + private function popCodeWriterContext() + { + $oldContext = array_pop($this->_contexts); + $this->_result = $oldContext->_result; + $this->_indentation = $oldContext->_indentation; + $this->_codeBuffer = $oldContext->_codeBuffer; + $this->_htmlBuffer = $oldContext->_htmlBuffer; + $this->_segments = $oldContext->_segments; + } + + private $_state; + private $_result = ""; + private $_indentation = 0; + private $_codeBuffer = array(); + private $_htmlBuffer = array(); + private $_segments = array(); + private $_contexts = array(); + private $_functionPrefix = ""; + private $_doctype = ""; + private $_xmldeclaration = ""; +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/State.php b/src/core/libs/PHPTAL5/PHPTAL/Php/State.php new file mode 100644 index 0000000..cc4f193 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/State.php @@ -0,0 +1,254 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * @package PHPTAL + * @subpackage Php + */ +class PHPTAL_Php_State +{ + private $debug = false; + private $tales_mode = 'tales'; + private $encoding; + private $output_mode; + private $phptal; + + function __construct(PHPTAL $phptal) + { + $this->phptal = $phptal; + $this->encoding = $phptal->getEncoding(); + $this->output_mode = $phptal->getOutputMode(); + } + + /** + * used by codewriter to get information for phptal:cache + */ + public function getCacheFilesBaseName() + { + return $this->phptal->getCodePath(); + } + + /** + * true if PHPTAL has translator set + */ + public function isTranslationOn() + { + return !!$this->phptal->getTranslator(); + } + + /** + * controlled by phptal:debug + */ + public function setDebug($bool) + { + $old = $this->debug; + $this->debug = $bool; + return $old; + } + + /** + * if true, add additional diagnostic information to generated code + */ + public function isDebugOn() + { + return $this->debug; + } + + /** + * Sets new and returns old TALES mode. + * Valid modes are 'tales' and 'php' + * + * @param string $mode + * + * @return string + */ + public function setTalesMode($mode) + { + $old = $this->tales_mode; + $this->tales_mode = $mode; + return $old; + } + + public function getTalesMode() + { + return $this->tales_mode; + } + + /** + * encoding used for both template input and output + */ + public function getEncoding() + { + return $this->encoding; + } + + /** + * Syntax rules to follow in generated code + * + * @return one of PHPTAL::XHTML, PHPTAL::XML, PHPTAL::HTML5 + */ + public function getOutputMode() + { + return $this->output_mode; + } + + /** + * Load prefilter + */ + public function getPreFilterByName($name) + { + return $this->phptal->getPreFilterByName($name); + } + + /** + * compile TALES expression according to current talesMode + * @return string with PHP code or array with expressions for TalesChainExecutor + */ + public function evaluateExpression($expression) + { + if ($this->getTalesMode() === 'php') { + return PHPTAL_Php_TalesInternal::php($expression); + } + return PHPTAL_Php_TalesInternal::compileToPHPExpressions($expression, false); + } + + /** + * compile TALES expression according to current talesMode + * @return string with PHP code + */ + private function compileTalesToPHPExpression($expression) + { + if ($this->getTalesMode() === 'php') { + return PHPTAL_Php_TalesInternal::php($expression); + } + return PHPTAL_Php_TalesInternal::compileToPHPExpression($expression, false); + } + + /** + * returns PHP code that generates given string, including dynamic replacements + * + * It's almost unused. + */ + public function interpolateTalesVarsInString($string) + { + return PHPTAL_Php_TalesInternal::parseString($string, false, ($this->getTalesMode() === 'tales') ? '' : 'php:' ); + } + + /** + * replaces ${} in string, expecting HTML-encoded input and HTML-escapes output + */ + public function interpolateTalesVarsInHTML($src) + { + return preg_replace_callback('/((?:\$\$)*)\$\{(structure |text )?(.*?)\}|((?:\$\$)+)\{/isS', + array($this,'_interpolateTalesVarsInHTMLCallback'), $src); + } + + /** + * callback for interpolating TALES with HTML-escaping + */ + private function _interpolateTalesVarsInHTMLCallback($matches) + { + return $this->_interpolateTalesVarsCallback($matches, 'html'); + } + + /** + * replaces ${} in string, expecting CDATA (basically unescaped) input, + * generates output protected against breaking out of CDATA in XML/HTML + * (depending on current output mode). + */ + public function interpolateTalesVarsInCDATA($src) + { + return preg_replace_callback('/((?:\$\$)*)\$\{(structure |text )?(.*?)\}|((?:\$\$)+)\{/isS', + array($this,'_interpolateTalesVarsInCDATACallback'), $src); + } + + /** + * callback for interpolating TALES with CDATA escaping + */ + private function _interpolateTalesVarsInCDATACallback($matches) + { + return $this->_interpolateTalesVarsCallback($matches, 'cdata'); + } + + private function _interpolateTalesVarsCallback($matches, $format) + { + // replaces $${ with literal ${ (or $$$${ with $${ etc) + if (!empty($matches[4])) { + return substr($matches[4], strlen($matches[4])/2).'{'; + } + + // same replacement, but before executed expression + $dollars = substr($matches[1], strlen($matches[1])/2); + + $code = $matches[3]; + if ($format == 'html') { + $code = html_entity_decode($code, ENT_QUOTES, $this->getEncoding()); + } + + $code = $this->compileTalesToPHPExpression($code); + + if (rtrim($matches[2]) == 'structure') { // regex captures a space there + return $dollars.'<?php echo '.$this->stringify($code)." ?>\n"; + } else { + if ($format == 'html') { + return $dollars.'<?php echo '.$this->htmlchars($code)." ?>\n"; + } + if ($format == 'cdata') { + // quite complex for an "unescaped" section, isn't it? + if ($this->getOutputMode() === PHPTAL::HTML5) { + return $dollars."<?php echo str_replace('</','<\\\\/', ".$this->stringify($code).") ?>\n"; + } elseif ($this->getOutputMode() === PHPTAL::XHTML) { + // both XML and HMTL, because people will inevitably send it as text/html :( + return $dollars."<?php echo strtr(".$this->stringify($code)." ,array(']]>'=>']]]]><![CDATA[>','</'=>'<\\/')) ?>\n"; + } else { + return $dollars."<?php echo str_replace(']]>',']]]]><![CDATA[>', ".$this->stringify($code).") ?>\n"; + } + } + assert(0); + } + } + + /** + * expects PHP code and returns PHP code that will generate escaped string + * Optimizes case when PHP string is given. + * + * @return php code + */ + public function htmlchars($php) + { + // PHP strings can be escaped at compile time + if (preg_match('/^\'((?:[^\'{]+|\\\\.)*)\'$/s', $php, $m)) { + return "'".htmlspecialchars(str_replace('\\\'', "'", $m[1]), ENT_QUOTES, $this->encoding)."'"; + } + return 'phptal_escape('.$php.', \''.$this->encoding.'\')'; + } + + /** + * allow proper printing of any object + * (without escaping - for use with structure keyword) + * + * @return php code + */ + public function stringify($php) + { + // PHP strings don't need to be changed + if (preg_match('/^\'(?>[^\'\\\\]+|\\\\.)*\'$|^\s*"(?>[^"\\\\]+|\\\\.)*"\s*$/s', $php)) { + return $php; + } + return 'phptal_tostring('.$php.')'; + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/TalesChainExecutor.php b/src/core/libs/PHPTAL5/PHPTAL/Php/TalesChainExecutor.php new file mode 100644 index 0000000..da94724 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/TalesChainExecutor.php @@ -0,0 +1,96 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * @package PHPTAL + * @subpackage Php + */ +class PHPTAL_Php_TalesChainExecutor +{ + const CHAIN_BREAK = 1; + const CHAIN_CONT = 2; + + public function __construct(PHPTAL_Php_CodeWriter $codewriter, array $chain, PHPTAL_Php_TalesChainReader $reader) + { + $this->_chain = $chain; + $this->_chainStarted = false; + $this->codewriter = $codewriter; + $this->_reader = $reader; + $this->_executeChain(); + } + + public function getCodeWriter() + { + return $this->codewriter; + } + + public function doIf($condition) + { + if ($this->_chainStarted == false) { + $this->_chainStarted = true; + $this->codewriter->doIf($condition); + } else { + $this->codewriter->doElseIf($condition); + } + } + + public function doElse() + { + $this->codewriter->doElse(); + } + + public function breakChain() + { + $this->_state = self::CHAIN_BREAK; + } + + public function continueChain() + { + $this->_state = self::CHAIN_CONT; + } + + private function _executeChain() + { + $this->codewriter->noThrow(true); + + end($this->_chain); $lastkey = key($this->_chain); + + foreach ($this->_chain as $key => $exp) { + $this->_state = 0; + + if ($exp == PHPTAL_Php_TalesInternal::NOTHING_KEYWORD) { + $this->_reader->talesChainNothingKeyword($this); + } elseif ($exp == PHPTAL_Php_TalesInternal::DEFAULT_KEYWORD) { + $this->_reader->talesChainDefaultKeyword($this); + } else { + $this->_reader->talesChainPart($this, $exp, $lastkey === $key); + } + + if ($this->_state == self::CHAIN_BREAK) + break; + if ($this->_state == self::CHAIN_CONT) + continue; + } + + $this->codewriter->doEnd('if'); + $this->codewriter->noThrow(false); + } + + private $_state = 0; + private $_chain; + private $_chainStarted = false; + private $codewriter = null; +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/TalesChainReader.php b/src/core/libs/PHPTAL5/PHPTAL/Php/TalesChainReader.php new file mode 100644 index 0000000..4992bfe --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/TalesChainReader.php @@ -0,0 +1,25 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * @package PHPTAL + * @subpackage Php + */ +interface PHPTAL_Php_TalesChainReader +{ + public function talesChainNothingKeyword(PHPTAL_Php_TalesChainExecutor $executor); + public function talesChainDefaultKeyword(PHPTAL_Php_TalesChainExecutor $executor); + public function talesChainPart(PHPTAL_Php_TalesChainExecutor $executor, $expression, $islast); +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/TalesInternal.php b/src/core/libs/PHPTAL5/PHPTAL/Php/TalesInternal.php new file mode 100644 index 0000000..4e84a66 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/TalesInternal.php @@ -0,0 +1,503 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Moritz Bechler <mbechler@eenterphace.org> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * TALES Specification 1.3 + * + * Expression ::= [type_prefix ':'] String + * type_prefix ::= Name + * + * Examples: + * + * a/b/c + * path:a/b/c + * nothing + * path:nothing + * python: 1 + 2 + * string:Hello, ${username} + * + * + * Builtin Names in Page Templates (for PHPTAL) + * + * * nothing - special singleton value used by TAL to represent a + * non-value (e.g. void, None, Nil, NULL). + * + * * default - special singleton value used by TAL to specify that + * existing text should not be replaced. + * + * * repeat - the repeat variables (see RepeatVariable). + * + * + */ + +/** + * @package PHPTAL + * @subpackage Php + */ +class PHPTAL_Php_TalesInternal implements PHPTAL_Tales +{ + const DEFAULT_KEYWORD = 'new PHPTAL_DefaultKeyword'; + const NOTHING_KEYWORD = 'new PHPTAL_NothingKeyword'; + + static public function true($src, $nothrow) + { + return 'phptal_true(' . self::compileToPHPExpression($src, true) . ')'; + } + + /** + * not: + * + * not: Expression + * + * evaluate the expression string (recursively) as a full expression, + * and returns the boolean negation of its value + * + * return boolean based on the following rules: + * + * 1. integer 0 is false + * 2. integer > 0 is true + * 3. an empty string or other sequence is false + * 4. a non-empty string or other sequence is true + * 5. a non-value (e.g. void, None, Nil, NULL, etc) is false + * 6. all other values are implementation-dependent. + * + * Examples: + * + * not: exists: foo/bar/baz + * not: php: object.hasChildren() + * not: string:${foo} + * not: foo/bar/booleancomparable + */ + static public function not($expression, $nothrow) + { + return '!phptal_true(' . self::compileToPHPExpression($expression, $nothrow) . ')'; + } + + + /** + * path: + * + * PathExpr ::= Path [ '|' Path ]* + * Path ::= variable [ '/' URL_Segment ]* + * variable ::= Name + * + * Examples: + * + * path: username + * path: user/name + * path: object/method/10/method/member + * path: object/${dynamicmembername}/method + * path: maybethis | path: maybethat | path: default + * + * PHPTAL: + * + * 'default' may lead to some 'difficult' attributes implementation + * + * For example, the tal:content will have to insert php code like: + * + * if (isset($ctx->maybethis)) { + * echo $ctx->maybethis; + * } + * elseif (isset($ctx->maybethat) { + * echo $ctx->maybethat; + * } + * else { + * // process default tag content + * } + * + * @returns string or array + */ + static public function path($expression, $nothrow=false) + { + $expression = trim($expression); + if ($expression == 'default') return self::DEFAULT_KEYWORD; + if ($expression == 'nothing') return self::NOTHING_KEYWORD; + if ($expression == '') return self::NOTHING_KEYWORD; + + // split OR expressions terminated by a string + if (preg_match('/^(.*?)\s*\|\s*?(string:.*)$/sm', $expression, $m)) { + list(, $expression, $string) = $m; + } + // split OR expressions terminated by a 'fast' string + elseif (preg_match('/^(.*?)\s*\|\s*\'((?:[^\'\\\\]|\\\\.)*)\'\s*$/sm', $expression, $m)) { + list(, $expression, $string) = $m; + $string = 'string:'.stripslashes($string); + } + + // split OR expressions + $exps = preg_split('/\s*\|\s*/sm', $expression); + + // if (many expressions) or (expressions or terminating string) found then + // generate the array of sub expressions and return it. + if (count($exps) > 1 || isset($string)) { + $result = array(); + foreach ($exps as $i=>$exp) { + if(isset($string) || $i < count($exps) - 1) { + $result[] = self::compileToPHPExpressions(trim($exp), true); + } + else { + // the last expression can thorw exception. + $result[] = self::compileToPHPExpressions(trim($exp), false); + } + } + if (isset($string)) { + $result[] = self::compileToPHPExpressions($string, true); + } + return $result; + } + + + // see if there are subexpressions, but skip interpolated parts, i.e. ${a/b}/c is 2 parts + if (preg_match('/^((?:[^$\/]+|\$\$|\${[^}]+}|\$))\/(.+)$/s', $expression, $m)) + { + if (!self::checkExpressionPart($m[1])) { + throw new PHPTAL_ParserException("Invalid TALES path: '$expression', expected '{$m[1]}' to be variable name"); + } + + $next = self::string($m[1]); + $expression = self::string($m[2]); + } else { + if (!self::checkExpressionPart($expression)) { + throw new PHPTAL_ParserException("Invalid TALES path: '$expression', expected variable name. Complex expressions need php: modifier."); + } + + $next = self::string($expression); + $expression = null; + } + + if ($nothrow) { + return '$ctx->path($ctx, ' . $next . ($expression === null ? '' : '."/".'.$expression) . ', true)'; + } + + if (preg_match('/^\'[a-z][a-z0-9_]*\'$/i', $next)) $next = substr($next, 1, -1); else $next = '{'.$next.'}'; + + // if no sub part for this expression, just optimize the generated code + // and access the $ctx->var + if ($expression === null) { + return '$ctx->'.$next; + } + + // otherwise we have to call PHPTAL_Context::path() to resolve the path at runtime + // extract the first part of the expression (it will be the PHPTAL_Context::path() + // $base and pass the remaining of the path to PHPTAL_Context::path() + return '$ctx->path($ctx->'.$next.', '.$expression.')'; + } + + /** + * check if part of exprssion (/foo/ or /foo${bar}/) is alphanumeric + */ + private static function checkExpressionPart($expression) + { + $expression = preg_replace('/\${[^}]+}/', 'a', $expression); // pretend interpolation is done + return preg_match('/^[a-z_][a-z0-9_]*$/i', $expression); + } + + /** + * string: + * + * string_expression ::= ( plain_string | [ varsub ] )* + * varsub ::= ( '$' Path ) | ( '${' Path '}' ) + * plain_string ::= ( '$$' | non_dollar )* + * non_dollar ::= any character except '$' + * + * Examples: + * + * string:my string + * string:hello, $username how are you + * string:hello, ${user/name} + * string:you have $$130 in your bank account + */ + static public function string($expression, $nothrow=false) + { + return self::parseString($expression, $nothrow, ''); + } + + /** + * @param string $tales_prefix prefix added to all TALES in the string + */ + static public function parseString($expression, $nothrow, $tales_prefix) + { + // This is a simple parser which evaluates ${foo} inside + // 'string:foo ${foo} bar' expressions, it returns the php code which will + // print the string with correct interpollations. + // Nothing special there :) + + $inPath = false; + $inAccoladePath = false; + $lastWasDollar = false; + $result = ''; + $len = strlen($expression); + for ($i=0; $i<$len; $i++) { + $c = $expression[$i]; + switch ($c) { + case '$': + if ($lastWasDollar) { + $lastWasDollar = false; + } elseif ($inAccoladePath) { + $subPath .= $c; + $c = ''; + } else { + $lastWasDollar = true; + $c = ''; + } + break; + + case '\\': + if ($inAccoladePath) { + $subPath .= $c; + $c = ''; + } + else { + $c = '\\\\'; + } + break; + + case '\'': + if ($inAccoladePath) { + $subPath .= $c; + $c = ''; + } + else { + $c = '\\\''; + } + break; + + case '{': + if ($inAccoladePath) { + $subPath .= $c; + $c = ''; + } elseif ($lastWasDollar) { + $lastWasDollar = false; + $inAccoladePath = true; + $subPath = ''; + $c = ''; + } + break; + + case '}': + if ($inAccoladePath) { + $inAccoladePath = false; + $subEval = self::compileToPHPExpression($tales_prefix.$subPath,false); + $result .= "'.(" . $subEval . ").'"; + $subPath = ''; + $lastWasDollar = false; + $c = ''; + } + break; + + default: + if ($lastWasDollar) { + $lastWasDollar = false; + $inPath = true; + $subPath = $c; + $c = ''; + } elseif ($inAccoladePath) { + $subPath .= $c; + $c = ''; + } elseif ($inPath) { + $t = strtolower($c); + if (($t >= 'a' && $t <= 'z') || ($t >= '0' && $t <= '9') || ($t == '_')) { + $subPath .= $c; + $c = ''; + } else { + $inPath = false; + $subEval = self::compileToPHPExpression($tales_prefix.$subPath,false); + $result .= "'.(" . $subEval . ").'"; + } + } + break; + } + $result .= $c; + } + if ($inPath) { + $subEval = self::compileToPHPExpression($tales_prefix.$subPath, false); + $result .= "'.(" . $subEval . ").'"; + } + + // optimize ''.foo.'' to foo + $result = preg_replace("/^(?:''\.)?(.*?)(?:\.'')?$/", '\1', '\''.$result.'\''); + + /* + The following expression (with + in first alternative): + "/^\(((?:[^\(\)]+|\([^\(\)]*\))*)\)$/" + + did work properly for (aaaaaaa)aa, but not for (aaaaaaaaaaaaaaaaaaaaa)aa + WTF!? + */ + + // optimize (foo()) to foo() + $result = preg_replace("/^\(((?:[^\(\)]|\([^\(\)]*\))*)\)$/", '\1', $result); + + return $result; + } + + /** + * php: modifier. + * + * Transform the expression into a regular PHP expression. + */ + static public function php($src) + { + return PHPTAL_Php_Transformer::transform($src, '$ctx->'); + } + + /** + * phptal-internal-php-block: modifier for emulation of <?php ?> in attributes. + * + * Please don't use it in the templates! + */ + static public function phptal_internal_php_block($src) + { + $src = rawurldecode($src); + + // Simple echo can be supported via regular method + if (preg_match('/^\s*echo\s+((?:[^;]+|"[^"\\\\]*"|\'[^\'\\\\]*\'|\/\*.*?\*\/)+);*\s*$/s',$src,$m)) + { + return $m[1]; + } + + // <?php block expects statements, but modifiers must return expressions. + // unfortunately this ugliness is the only way to support it currently. + // ? > keeps semicolon optional + return "eval(".self::string($src.'?>').")"; + } + + /** + * exists: modifier. + * + * Returns the code required to invoke Context::exists() on specified path. + */ + static public function exists($src, $nothrow) + { + $src = trim($src); + if (ctype_alnum($src)) return 'isset($ctx->'.$src.')'; + return '(null !== ' . self::compileToPHPExpression($src, true) . ')'; + } + + /** + * number: modifier. + * + * Returns the number as is. + */ + static public function number($src, $nothrow) + { + if (!is_numeric(trim($src))) throw new PHPTAL_ParserException("'$src' is not a number"); + return trim($src); + } + + /** + * json: modifier. Serializes anything as JSON. + */ + static public function json($src, $nothrow) + { + return 'json_encode('.phptal_tale($src,$nothrow).')'; + } + + /** + * urlencode: modifier. Escapes a string. + */ + static public function urlencode($src, $nothrow) + { + return 'rawurlencode('.phptal_tale($src,$nothrow).')'; + } + + /** + * translates TALES expression with alternatives into single PHP expression. + * Identical to compileToPHPExpressions() for singular expressions. + * + * @see PHPTAL_Php_TalesInternal::compileToPHPExpressions() + * @return string + */ + public static function compileToPHPExpression($expression, $nothrow=false) + { + $r = self::compileToPHPExpressions($expression, $nothrow); + if (!is_array($r)) return $r; + + // this weird ternary operator construct is to execute noThrow inside the expression + return '($ctx->noThrow(true)||1?'.self::convertExpressionsToExpression($r, $nothrow).':"")'; + } + + /* + * helper function for compileToPHPExpression + * @access private + */ + private static function convertExpressionsToExpression(array $array, $nothrow) + { + if (count($array)==1) return '($ctx->noThrow('.($nothrow?'true':'false').')||1?('. + ($array[0]==self::NOTHING_KEYWORD?'null':$array[0]). + '):"")'; + + $expr = array_shift($array); + + return "(!phptal_isempty(\$_tmp5=$expr) && (\$ctx->noThrow(false)||1)?\$_tmp5:".self::convertExpressionsToExpression($array, $nothrow).')'; + } + + /** + * returns PHP code that will evaluate given TALES expression. + * e.g. "string:foo${bar}" may be transformed to "'foo'.phptal_escape($ctx->bar)" + * + * Expressions with alternatives ("foo | bar") will cause it to return array + * Use PHPTAL_Php_TalesInternal::compileToPHPExpression() if you always want string. + * + * @param bool $nothrow if true, invalid expression will return NULL (at run time) rather than throwing exception + * + * @return string or array + */ + public static function compileToPHPExpressions($expression, $nothrow=false) + { + $expression = trim($expression); + + // Look for tales modifier (string:, exists:, Namespaced\Tale:, etc...) + if (preg_match('/^([a-z](?:[a-z0-9._\\\\-]*[a-z0-9])?):(.*)$/si', $expression, $m)) { + list(, $typePrefix, $expression) = $m; + } + // may be a 'string' + elseif (preg_match('/^\'((?:[^\']|\\\\.)*)\'$/s', $expression, $m)) { + $expression = stripslashes($m[1]); + $typePrefix = 'string'; + } + // failback to path: + else { + $typePrefix = 'path'; + } + + // is a registered TALES expression modifier + $callback = PHPTAL_TalesRegistry::getInstance()->getCallback($typePrefix); + if ($callback !== NULL) + { + $result = call_user_func($callback, $expression, $nothrow); + self::verifyPHPExpressions($typePrefix, $result); + return $result; + } + + $func = 'phptal_tales_'.str_replace('-', '_', $typePrefix); + throw new PHPTAL_UnknownModifierException("Unknown phptal modifier '$typePrefix'. Function '$func' does not exist", $typePrefix); + } + + private static function verifyPHPExpressions($typePrefix,$expressions) + { + if (!is_array($expressions)) { + $expressions = array($expressions); + } + + foreach($expressions as $expr) { + if (preg_match('/;\s*$/', $expr)) { + throw new PHPTAL_ParserException("Modifier $typePrefix generated PHP statement rather than expression (don't add semicolons)"); + } + } + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Php/Transformer.php b/src/core/libs/PHPTAL5/PHPTAL/Php/Transformer.php new file mode 100644 index 0000000..c07608d --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Php/Transformer.php @@ -0,0 +1,418 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Tranform php: expressions into their php equivalent. + * + * This transformer produce php code for expressions like : + * + * - a.b["key"].c().someVar[10].foo() + * - (a or b) and (c or d) + * - not myBool + * - ... + * + * The $prefix variable may be changed to change the context lookup. + * + * example: + * + * $res = PHPTAL_Php_Transformer::transform('a.b.c[x]', '$ctx->'); + * $res == '$ctx->a->b->c[$ctx->x]'; + * + * @package PHPTAL + * @subpackage Php + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_Php_Transformer +{ + const ST_WHITE = -1; // start of string or whitespace + const ST_NONE = 0; // pass through (operators, parens, etc.) + const ST_STR = 1; // 'foo' + const ST_ESTR = 2; // "foo ${x} bar" + const ST_VAR = 3; // abcd + const ST_NUM = 4; // 123.02 + const ST_EVAL = 5; // $somevar + const ST_MEMBER = 6; // abcd.x + const ST_STATIC = 7; // class::[$]static|const + const ST_DEFINE = 8; // @MY_DEFINE + + /** + * transform PHPTAL's php-like syntax into real PHP + */ + public static function transform($str, $prefix='$') + { + $len = strlen($str); + $state = self::ST_WHITE; + $result = ''; + $i = 0; + $inString = false; + $backslashed = false; + $instanceof = false; + $eval = false; + + + for ($i = 0; $i <= $len; $i++) { + if ($i == $len) $c = "\0"; + else $c = $str[$i]; + + switch ($state) { + + // after whitespace a variable-variable may start, ${var} → $ctx->{$ctx->var} + case self::ST_WHITE: + if ($c === '$' && $i+1 < $len && $str[$i+1] === '{') + { + $result .= $prefix; + $state = self::ST_NONE; + continue; + } + /* NO BREAK - ST_WHITE is almost the same as ST_NONE */ + + // no specific state defined, just eat char and see what to do with it. + case self::ST_NONE: + // begin of eval without { + if ($c === '$' && $i+1 < $len && self::isAlpha($str[$i+1])) { + $state = self::ST_EVAL; + $mark = $i+1; + $result .= $prefix.'{'; + } + elseif (self::isDigit($c)) + { + $state = self::ST_NUM; + $mark = $i; + } + // that an alphabetic char, then it should be the begining + // of a var or static + // && !self::isDigit($c) checked earlier + elseif (self::isVarNameChar($c)) { + $state = self::ST_VAR; + $mark = $i; + } + // begining of double quoted string + elseif ($c === '"') { + $state = self::ST_ESTR; + $mark = $i; + $inString = true; + } + // begining of single quoted string + elseif ($c === '\'') { + $state = self::ST_STR; + $mark = $i; + $inString = true; + } + // closing a method, an array access or an evaluation + elseif ($c === ')' || $c === ']' || $c === '}') { + $result .= $c; + // if next char is dot then an object member must + // follow + if ($i+1 < $len && $str[$i+1] === '.') { + $result .= '->'; + $state = self::ST_MEMBER; + $mark = $i+2; + $i+=2; + } + } + // @ is an access to some defined variable + elseif ($c === '@') { + $state = self::ST_DEFINE; + $mark = $i+1; + } + elseif (ctype_space($c)) { + $state = self::ST_WHITE; + $result .= $c; + } + // character we don't mind about + else { + $result .= $c; + } + break; + + // $xxx + case self::ST_EVAL: + if (!self::isVarNameChar($c)) { + $result .= $prefix . substr($str, $mark, $i-$mark); + $result .= '}'; + $state = self::ST_NONE; + } + break; + + // single quoted string + case self::ST_STR: + if ($c === '\\') { + $backslashed = true; + } elseif ($backslashed) { + $backslashed = false; + } + // end of string, back to none state + elseif ($c === '\'') { + $result .= substr($str, $mark, $i-$mark+1); + $inString = false; + $state = self::ST_NONE; + } + break; + + // double quoted string + case self::ST_ESTR: + if ($c === '\\') { + $backslashed = true; + } elseif ($backslashed) { + $backslashed = false; + } + // end of string, back to none state + elseif ($c === '"') { + $result .= substr($str, $mark, $i-$mark+1); + $inString = false; + $state = self::ST_NONE; + } + // instring interpolation, search } and transform the + // interpollation to insert it into the string + elseif ($c === '$' && $i+1 < $len && $str[$i+1] === '{') { + $result .= substr($str, $mark, $i-$mark) . '{'; + + $sub = 0; + for ($j = $i; $j<$len; $j++) { + if ($str[$j] === '{') { + $sub++; + } elseif ($str[$j] === '}' && (--$sub) == 0) { + $part = substr($str, $i+2, $j-$i-2); + $result .= self::transform($part, $prefix); + $i = $j; + $mark = $i; + } + } + } + break; + + // var state + case self::ST_VAR: + if (self::isVarNameChar($c)) { + } + // end of var, begin of member (method or var) + elseif ($c === '.') { + $result .= $prefix . substr($str, $mark, $i-$mark); + $result .= '->'; + $state = self::ST_MEMBER; + $mark = $i+1; + } + // static call, the var is a class name + elseif ($c === ':' && $i+1 < $len && $str[$i+1] === ':') { + $result .= substr($str, $mark, $i-$mark+1); + $mark = $i+1; + $i++; + $state = self::ST_STATIC; + break; + } + // function invocation, the var is a function name + elseif ($c === '(') { + $result .= substr($str, $mark, $i-$mark+1); + $state = self::ST_NONE; + } + // array index, the var is done + elseif ($c === '[') { + if ($str[$mark]==='_') { // superglobal? + $result .= '$' . substr($str, $mark, $i-$mark+1); + } else { + $result .= $prefix . substr($str, $mark, $i-$mark+1); + } + $state = self::ST_NONE; + } + // end of var with non-var-name character, handle keywords + // and populate the var name + else { + $var = substr($str, $mark, $i-$mark); + $low = strtolower($var); + // boolean and null + if ($low === 'true' || $low === 'false' || $low === 'null') { + $result .= $var; + } + // lt, gt, ge, eq, ... + elseif (array_key_exists($low, self::$TranslationTable)) { + $result .= self::$TranslationTable[$low]; + } + // instanceof keyword + elseif ($low === 'instanceof') { + $result .= $var; + $instanceof = true; + } + // previous was instanceof + elseif ($instanceof) { + // last was instanceof, this var is a class name + $result .= $var; + $instanceof = false; + } + // regular variable + else { + $result .= $prefix . $var; + } + $i--; + $state = self::ST_NONE; + } + break; + + // object member + case self::ST_MEMBER: + if (self::isVarNameChar($c)) { + } + // eval mode ${foo} + elseif ($c === '$' && ($i >= $len-2 || $str[$i+1] !== '{')) { + $result .= '{' . $prefix; + $mark++; + $eval = true; + } + // x.${foo} x->{foo} + elseif ($c === '$') { + $mark++; + } + // end of var member var, begin of new member + elseif ($c === '.') { + $result .= substr($str, $mark, $i-$mark); + if ($eval) { $result .='}'; $eval = false; } + $result .= '->'; + $mark = $i+1; + $state = self::ST_MEMBER; + } + // begin of static access + elseif ($c === ':') { + $result .= substr($str, $mark, $i-$mark+1); + if ($eval) { $result .='}'; $eval = false; } + $state = self::ST_STATIC; + break; + } + // the member is a method or an array + elseif ($c === '(' || $c === '[') { + $result .= substr($str, $mark, $i-$mark+1); + if ($eval) { $result .='}'; $eval = false; } + $state = self::ST_NONE; + } + // regular end of member, it is a var + else { + $var = substr($str, $mark, $i-$mark); + if ($var !== '' && !preg_match('/^[a-z][a-z0-9_\x7f-\xff]*$/i',$var)) { + throw new PHPTAL_ParserException("Invalid field name '$var' in expression php:$str"); + } + $result .= $var; + if ($eval) { $result .='}'; $eval = false; } + $state = self::ST_NONE; + $i--; + } + break; + + // wait for separator + case self::ST_DEFINE: + if (self::isVarNameChar($c)) { + } else { + $state = self::ST_NONE; + $result .= substr($str, $mark, $i-$mark); + $i--; + } + break; + + // static call, can be const, static var, static method + // Klass::$static + // Klass::const + // Kclass::staticMethod() + // + case self::ST_STATIC: + if (self::isVarNameChar($c)) { + } + // static var + elseif ($c === '$') { + } + // end of static var which is an object and begin of member + elseif ($c === '.') { + $result .= substr($str, $mark, $i-$mark); + $result .= '->'; + $mark = $i+1; + $state = self::ST_MEMBER; + } + // end of static var which is a class name + elseif ($c === ':') { + $result .= substr($str, $mark, $i-$mark+1); + $state = self::ST_STATIC; + break; + } + // static method or array + elseif ($c === '(' || $c === '[') { + $result .= substr($str, $mark, $i-$mark+1); + $state = self::ST_NONE; + } + // end of static var or const + else { + $result .= substr($str, $mark, $i-$mark); + $state = self::ST_NONE; + $i--; + } + break; + + // numeric value + case self::ST_NUM: + if (!self::isDigitCompound($c)) { + $var = substr($str, $mark, $i-$mark); + + if (self::isAlpha($c) || $c === '_') { + throw new PHPTAL_ParserException("Syntax error in number '$var$c' in expression php:$str"); + } + if (!is_numeric($var)) { + throw new PHPTAL_ParserException("Syntax error in number '$var' in expression php:$str"); + } + + $result .= $var; + $state = self::ST_NONE; + $i--; + } + break; + } + } + + $result = trim($result); + + // CodeWriter doesn't like expressions that look like blocks + if ($result[strlen($result)-1] === '}') return '('.$result.')'; + + return $result; + } + + private static function isAlpha($c) + { + $c = strtolower($c); + return $c >= 'a' && $c <= 'z'; + } + + private static function isDigit($c) + { + return ($c >= '0' && $c <= '9'); + } + + private static function isDigitCompound($c) + { + return ($c >= '0' && $c <= '9' || $c === '.'); + } + + private static function isVarNameChar($c) + { + return self::isAlpha($c) || ($c >= '0' && $c <= '9') || $c === '_' || $c === '\\'; + } + + private static $TranslationTable = array( + 'not' => '!', + 'ne' => '!=', + 'and' => '&&', + 'or' => '||', + 'lt' => '<', + 'gt' => '>', + 'ge' => '>=', + 'le' => '<=', + 'eq' => '==', + ); +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/PreFilter.php b/src/core/libs/PHPTAL5/PHPTAL/PreFilter.php new file mode 100644 index 0000000..25c7969 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/PreFilter.php @@ -0,0 +1,132 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id: $ + * @link http://phptal.org/ + */ + +/** + * Base class for prefilters. + * + * You should extend this class and override methods you're interested in. + * + * Order of calls is undefined and may change. + * + * @package PHPTAL + */ +abstract class PHPTAL_PreFilter implements PHPTAL_Filter +{ + /** + * @see getPHPTAL() + */ + private $phptal; + + + /** + * Receives DOMElement (of PHP5 DOM API) of parsed file (documentElement), or element + * that has phptal:filter attribute. Should edit DOM in place. + * Prefilters are called only once before template is compiled, so they can be slow. + * + * Default implementation does nothing. Override it. + * + * @param DOMElement $node PHP5 DOM node to modify in place + * + * @return void + */ + public function filterElement(DOMElement $node) + { + } + + /** + * Receives root PHPTAL DOM node of parsed file and should edit it in place. + * Prefilters are called only once before template is compiled, so they can be slow. + * + * Default implementation does nothing. Override it. + * + * @see PHPTAL_Dom_Element class for methods and fields available. + * + * @param PHPTAL_Dom_Element $root PHPTAL DOM node to modify in place + * + * @return void + */ + public function filterDOM(PHPTAL_Dom_Element $root) + { + } + + /** + * Receives DOM node that had phptal:filter attribute calling this filter. + * Should modify node in place. + * Prefilters are called only once before template is compiled, so they can be slow. + * + * Default implementation calls filterDOM(). Override it. + * + * @param PHPTAL_Dom_Element $node PHPTAL DOM node to modify in place + * + * @return void + */ + public function filterDOMFragment(PHPTAL_Dom_Element $node) + { + $this->filterDOM($node); + } + + /** + * Receives template source code and is expected to return new source. + * Prefilters are called only once before template is compiled, so they can be slow. + * + * Default implementation does nothing. Override it. + * + * @param string $src markup to filter + * + * @return string + */ + public function filter($src) + { + return $src; + } + + /** + * Returns (any) string that uniquely identifies this filter and its settings, + * which is used to (in)validate template cache. + * + * Unlike other filter methods, this one is called on every execution. + * + * Override this method if result of the filter depends on its configuration. + * + * @return string + */ + public function getCacheId() + { + return get_class($this); + } + + /** + * Returns PHPTAL class instance that is currently using this prefilter. + * May return NULL if PHPTAL didn't start filtering yet. + * + * @return PHPTAL or NULL + */ + final protected function getPHPTAL() + { + return $this->phptal; + } + + /** + * Set which instance of PHPTAL is using this filter. + * Must be done before calling any filter* methods. + * + * @param PHPTAL $phptal instance + */ + final function setPHPTAL(PHPTAL $phptal) + { + $this->phptal = $phptal; + } +} + + diff --git a/src/core/libs/PHPTAL5/PHPTAL/PreFilter/Compress.php b/src/core/libs/PHPTAL5/PHPTAL/PreFilter/Compress.php new file mode 100644 index 0000000..c1cedbc --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/PreFilter/Compress.php @@ -0,0 +1,282 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id: $ + * @link http://phptal.org/ + */ + +/** + * Removes all unnecessary whitespace from XHTML documents. + * + * extends Normalize only to re-use helper methods + */ +class PHPTAL_PreFilter_Compress extends PHPTAL_PreFilter_Normalize +{ + /** + * keeps track whether last element had trailing whitespace (or didn't need it). + * If had_space==false, next element must keep leading space. + */ + private $had_space=false; + + /** + * last text node before closing tag that may need trailing whitespace trimmed. + * It's often last-child, but comments, multiple end tags make that trickier. + */ + private $most_recent_text_node=null; + + function filterDOM(PHPTAL_Dom_Element $root) + { + // let xml:space=preserve preserve everything + if ($root->getAttributeNS("http://www.w3.org/XML/1998/namespace", 'space') == 'preserve') { + $this->most_recent_text_node = null; + $this->findElementToFilter($root); + return; + } + + // tal:replace makes element behave like text + if ($root->getAttributeNS('http://xml.zope.org/namespaces/tal','replace')) { + $this->most_recent_text_node = null; + $this->had_space = false; + return; + } + + $this->normalizeAttributes($root); + $this->elementSpecificOptimizations($root); + + // <head>, <tr> don't have any significant whitespace + $no_spaces = $this->hasNoInterelementSpace($root); + + // mostly block-level elements + // if element is conditional, it may not always break the line + $breaks_line = $no_spaces || ($this->breaksLine($root) && !$root->getAttributeNS('http://xml.zope.org/namespaces/tal','condition')); + + // start tag newline + if ($breaks_line) { + if ($this->most_recent_text_node) { + $this->most_recent_text_node->setValueEscaped(rtrim($this->most_recent_text_node->getValueEscaped())); + $this->most_recent_text_node = null; + } + $this->had_space = true; + } else if ($this->isInlineBlock($root)) { + // spaces around <img> must be kept + $this->most_recent_text_node = null; + $this->had_space = false; + } + + // <pre>, <textarea> are handled separately from xml:space, because they may have attributes normalized + if ($this->isSpaceSensitiveInXHTML($root)) { + $this->most_recent_text_node = null; + + // HTML 5 (9.1.2.5) specifies quirk that a first *single* newline in <pre> can be removed + if (count($root->childNodes) && $root->childNodes[0] instanceof PHPTAL_Dom_Text) { + if (preg_match('/^\n[^\n]/', $root->childNodes[0]->getValueEscaped())) { + $root->childNodes[0]->setValueEscaped(substr($root->childNodes[0]->getValueEscaped(),1)); + } + } + $this->findElementToFilter($root); + return; + } + + foreach ($root->childNodes as $node) { + + if ($node instanceof PHPTAL_Dom_Text) { + // replaces runs of whitespace with ' ' + $norm = $this->normalizeSpace($node->getValueEscaped(), $node->getEncoding()); + + if ($no_spaces) { + $norm = trim($norm); + } elseif ($this->had_space) { + $norm = ltrim($norm); + } + + $node->setValueEscaped($norm); + + // collapsed whitespace-only nodes are ignored (otherwise trimming of most_recent_text_node would be useless) + if ($norm !== '') { + $this->most_recent_text_node = $node; + $this->had_space = (substr($norm,-1) == ' '); + } + } else if ($node instanceof PHPTAL_Dom_Element) { + $this->filterDOM($node); + } else if ($node instanceof PHPTAL_Dom_DocumentType || $node instanceof PHPTAL_Dom_XMLDeclaration) { + $this->had_space = true; + } else if ($node instanceof PHPTAL_Dom_ProcessingInstruction) { + // PI may output something requiring spaces + $this->most_recent_text_node = null; + $this->had_space = false; + } + } + + // repeated element may need trailing space. + if (!$breaks_line && $root->getAttributeNS('http://xml.zope.org/namespaces/tal','repeat')) { + $this->most_recent_text_node = null; + } + + // tal:content may replace element with something without space + if (!$breaks_line && $root->getAttributeNS('http://xml.zope.org/namespaces/tal','content')) { + $this->had_space = false; + $this->most_recent_text_node = null; + } + + // line break caused by end tag + if ($breaks_line) { + if ($this->most_recent_text_node) { + $this->most_recent_text_node->setValueEscaped(rtrim($this->most_recent_text_node->getValueEscaped())); + $this->most_recent_text_node = null; + } + $this->had_space = true; + } + } + + private static $no_interelement_space = array( + 'html','head','table','thead','tfoot','select','optgroup','dl','ol','ul','tr','datalist', + ); + + private function hasNoInterelementSpace(PHPTAL_Dom_Element $element) + { + if ($element->getLocalName() === 'block' + && $element->parentNode + && $element->getNamespaceURI() === 'http://xml.zope.org/namespaces/tal') { + return $this->hasNoInterelementSpace($element->parentNode); + } + + return in_array($element->getLocalName(), self::$no_interelement_space) + && ($element->getNamespaceURI() === 'http://www.w3.org/1999/xhtml' || $element->getNamespaceURI() === ''); + } + + /** + * li is deliberately omitted, as it's commonly used with display:inline in menus. + */ + private static $breaks_line = array( + 'address','article','aside','base','blockquote','body','br','dd','div','dl','dt','fieldset','figure', + 'footer','form','h1','h2','h3','h4','h5','h6','head','header','hgroup','hr','html','legend','link', + 'meta','nav','ol','option','p','param','pre','section','style','table','tbody','td','th','thead', + 'title','tr','ul','details', + ); + + private function breaksLine(PHPTAL_Dom_Element $element) + { + if ($element->getAttributeNS('http://xml.zope.org/namespaces/metal','define-macro')) { + return true; + } + + if (!$element->parentNode) { + return true; + } + + if ($element->getNamespaceURI() !== 'http://www.w3.org/1999/xhtml' + && $element->getNamespaceURI() !== '') { + return false; + } + + return in_array($element->getLocalName(), self::$breaks_line); + } + + /** + * replaced elements need to preserve spaces before and after + */ + private static $inline_blocks = array( + 'select','input','button','img','textarea','output','progress','meter', + ); + + private function isInlineBlock(PHPTAL_Dom_Element $element) + { + if ($element->getNamespaceURI() !== 'http://www.w3.org/1999/xhtml' + && $element->getNamespaceURI() !== '') { + return false; + } + + return in_array($element->getLocalName(), self::$inline_blocks); + } + + /** + * Consistent sorting of attributes might give slightly better gzip performance + */ + protected function normalizeAttributes(PHPTAL_Dom_Element $element) + { + parent::normalizeAttributes($element); + + $attrs_by_qname = array(); + foreach ($element->getAttributeNodes() as $attrnode) { + // safe, as there can't be two attrs with same qname + $attrs_by_qname[$attrnode->getQualifiedName()] = $attrnode; + } + + if (count($attrs_by_qname) > 1) { + uksort($attrs_by_qname, array($this, 'compareQNames')); + $element->setAttributeNodes(array_values($attrs_by_qname)); + } + } + + /** + * pre-defined order of attributes roughly by popularity + */ + private static $attributes_order = array( + 'href','src','class','rel','type','title','width','height','alt','content','name','style','lang','id', + ); + + /** + * compare names according to $attributes_order array. + * Elements that are not in array, are considered greater than all elements in array, + * and are sorted alphabetically. + */ + private static function compareQNames($a, $b) { + $a_index = array_search($a, self::$attributes_order); + $b_index = array_search($b, self::$attributes_order); + + if ($a_index !== false && $b_index !== false) { + return $a_index - $b_index; + } + if ($a_index === false && $b_index === false) { + return strcmp($a, $b); + } + return ($a_index === false) ? 1 : -1; + } + + /** + * HTML5 doesn't care about boilerplate + */ + private function elementSpecificOptimizations(PHPTAL_Dom_Element $element) + { + if ($element->getNamespaceURI() !== 'http://www.w3.org/1999/xhtml' + && $element->getNamespaceURI() !== '') { + return; + } + + if ($this->getPHPTAL()->getOutputMode() !== PHPTAL::HTML5) { + return; + } + + // <meta charset> + if ('meta' === $element->getLocalName() && + $element->getAttributeNS('','http-equiv') === 'Content-Type') { + $element->removeAttributeNS('','http-equiv'); + $element->removeAttributeNS('','content'); + $element->setAttributeNS('','charset',strtolower($this->getPHPTAL()->getEncoding())); + } + elseif (('link' === $element->getLocalName() && $element->getAttributeNS('','rel') === 'stylesheet') || + ('style' === $element->getLocalName())) { + // There's only one type of stylesheets that works. + $element->removeAttributeNS('','type'); + + } elseif ('script' === $element->getLocalName()) { + $element->removeAttributeNS('','language'); + + // Only remove type that matches default. E4X, vbscript, coffeescript, etc. must be preserved + $type = $element->getAttributeNS('','type'); + $is_std = preg_match('/^(?:text|application)\/(?:ecma|java)script(\s*;\s*charset\s*=\s*[^;]*)?$/', $type); + + // Remote scripts should have type specified in HTTP headers. + if ($is_std || $element->getAttributeNS('','src')) { + $element->removeAttributeNS('','type'); + } + } + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/PreFilter/Normalize.php b/src/core/libs/PHPTAL5/PHPTAL/PreFilter/Normalize.php new file mode 100644 index 0000000..dd6f46e --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/PreFilter/Normalize.php @@ -0,0 +1,108 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id: $ + * @link http://phptal.org/ + */ + +/** + * Collapses conscutive whitespace, trims attributes, merges adjacent text nodes + */ +class PHPTAL_PreFilter_Normalize extends PHPTAL_PreFilter +{ + function filter($src) + { + return str_replace("\r\n", "\n", $src); + } + + function filterDOM(PHPTAL_Dom_Element $root) + { + // let xml:space=preserve preserve attributes as well + if ($root->getAttributeNS("http://www.w3.org/XML/1998/namespace", 'space') == 'preserve') { + $this->findElementToFilter($root); + return; + } + + $this->normalizeAttributes($root); + + // <pre> may have attributes normalized + if ($this->isSpaceSensitiveInXHTML($root)) { + $this->findElementToFilter($root); + return; + } + + $lastTextNode = null; + foreach ($root->childNodes as $node) { + + // CDATA is not normalized by design + if ($node instanceof PHPTAL_Dom_Text) { + $norm = $this->normalizeSpace($node->getValueEscaped(), $node->getEncoding()); + $node->setValueEscaped($norm); + + if ('' === $norm) { + $root->removeChild($node); + } else if ($lastTextNode) { + // "foo " . " bar" gives 2 spaces. + $norm = $lastTextNode->getValueEscaped().ltrim($norm,' '); + + $lastTextNode->setValueEscaped($norm); // assumes all nodes use same encoding (they do) + $root->removeChild($node); + } else { + $lastTextNode = $node; + } + } else { + $lastTextNode = null; + if ($node instanceof PHPTAL_Dom_Element) { + $this->filterDOM($node); + } + } + } + } + + protected function isSpaceSensitiveInXHTML(PHPTAL_Dom_Element $element) + { + $ln = $element->getLocalName(); + return ($ln === 'script' || $ln === 'pre' || $ln === 'textarea') + && ($element->getNamespaceURI() === 'http://www.w3.org/1999/xhtml' || $element->getNamespaceURI() === ''); + } + + protected function findElementToFilter(PHPTAL_Dom_Element $root) + { + foreach ($root->childNodes as $node) { + if (!$node instanceof PHPTAL_Dom_Element) continue; + + if ($node->getAttributeNS("http://www.w3.org/XML/1998/namespace", 'space') == 'default') { + $this->filterDOM($node); + } + } + } + + /** + * does not trim + */ + protected function normalizeSpace($text, $encoding) + { + $utf_regex_mod = ($encoding=='UTF-8'?'u':''); + + return preg_replace('/[ \t\r\n]+/'.$utf_regex_mod, ' ', $text); // \s removes nbsp + } + + protected function normalizeAttributes(PHPTAL_Dom_Element $element) + { + foreach ($element->getAttributeNodes() as $attrnode) { + + // skip replaced attributes (because getValueEscaped on them is meaningless) + if ($attrnode->getReplacedState() !== PHPTAL_Dom_Attr::NOT_REPLACED) continue; + + $val = $this->normalizeSpace($attrnode->getValueEscaped(), $attrnode->getEncoding()); + $attrnode->setValueEscaped(trim($val, ' ')); + } + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/PreFilter/StripComments.php b/src/core/libs/PHPTAL5/PHPTAL/PreFilter/StripComments.php new file mode 100644 index 0000000..89aaabe --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/PreFilter/StripComments.php @@ -0,0 +1,34 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id: $ + * @link http://phptal.org/ + */ + +class PHPTAL_PreFilter_StripComments extends PHPTAL_PreFilter +{ + function filterDOM(PHPTAL_Dom_Element $element) + { + $defs = PHPTAL_Dom_Defs::getInstance(); + + foreach ($element->childNodes as $node) { + if ($node instanceof PHPTAL_Dom_Comment) { + if ($defs->isCDATAElementInHTML($element->getNamespaceURI(), $element->getLocalName())) { + $textNode = new PHPTAL_Dom_CDATASection($node->getValueEscaped(), $node->getEncoding()); + $node->parentNode->replaceChild($textNode, $node); + } else { + $node->parentNode->removeChild($node); + } + } else if ($node instanceof PHPTAL_Dom_Element) { + $this->filterDOM($node); + } + } + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/RepeatController.php b/src/core/libs/PHPTAL5/PHPTAL/RepeatController.php new file mode 100644 index 0000000..5d33914 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/RepeatController.php @@ -0,0 +1,323 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @author Iván Montes <drslump@pollinimini.net> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Stores tal:repeat information during template execution. + * + * An instance of this class is created and stored into PHPTAL context on each + * tal:repeat usage. + * + * repeat/item/index + * repeat/item/number + * ... + * are provided by this instance. + * + * 'repeat' is an stdClass instance created to handle RepeatControllers, + * 'item' is an instance of this class. + * + * @package PHPTAL + * @subpackage Php + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + */ +class PHPTAL_RepeatController implements Iterator +{ + public $key; + private $current; + private $valid; + private $validOnNext; + + private $uses_groups = false; + + protected $iterator; + public $index; + public $end; + + /** + * computed lazily + */ + private $length = null; + + /** + * Construct a new RepeatController. + * + * @param $source array, string, iterator, iterable. + */ + public function __construct($source) + { + if ( is_string($source) ) { + $this->iterator = new ArrayIterator( str_split($source) ); // FIXME: invalid for UTF-8 encoding, use preg_match_all('/./u') trick + } elseif ( is_array($source) ) { + $this->iterator = new ArrayIterator($source); + } elseif ($source instanceof IteratorAggregate) { + $this->iterator = $source->getIterator(); + } elseif ($source instanceof DOMNodeList) { + $array = array(); + foreach ($source as $k=>$v) { + $array[$k] = $v; + } + $this->iterator = new ArrayIterator($array); + } elseif ($source instanceof Iterator) { + $this->iterator = $source; + } elseif ($source instanceof Traversable) { + $this->iterator = new IteratorIterator($source); + } elseif ($source instanceof Closure) { + $this->iterator = new ArrayIterator( (array) $source() ); + } elseif ($source instanceof stdClass) { + $this->iterator = new ArrayIterator( (array) $source ); + } else { + $this->iterator = new ArrayIterator( array() ); + } + } + + /** + * Returns the current element value in the iteration + * + * @return Mixed The current element value + */ + public function current() + { + return $this->current; + } + + /** + * Returns the current element key in the iteration + * + * @return String/Int The current element key + */ + public function key() + { + return $this->key; + } + + /** + * Tells if the iteration is over + * + * @return bool True if the iteration is not finished yet + */ + public function valid() + { + $valid = $this->valid || $this->validOnNext; + $this->validOnNext = $this->valid; + + return $valid; + } + + public function length() + { + if ($this->length === null) { + if ($this->iterator instanceof Countable) { + return $this->length = count($this->iterator); + } elseif ( is_object($this->iterator) ) { + // for backwards compatibility with existing PHPTAL templates + if ( method_exists($this->iterator, 'size') ) { + return $this->length = $this->iterator->size(); + } elseif ( method_exists($this->iterator, 'length') ) { + return $this->length = $this->iterator->length(); + } + } + $this->length = '_PHPTAL_LENGTH_UNKNOWN_'; + } + + if ($this->length === '_PHPTAL_LENGTH_UNKNOWN_') // return length if end is discovered + { + return $this->end ? $this->index + 1 : null; + } + return $this->length; + } + + /** + * Restarts the iteration process going back to the first element + * + */ + public function rewind() + { + $this->index = 0; + $this->length = null; + $this->end = false; + + $this->iterator->rewind(); + + // Prefetch the next element + if ($this->iterator->valid()) { + $this->validOnNext = true; + $this->prefetch(); + } else { + $this->validOnNext = false; + } + + if ($this->uses_groups) { + // Notify the grouping helper of the change + $this->groups->reset(); + } + } + + /** + * Fetches the next element in the iteration and advances the pointer + * + */ + public function next() + { + $this->index++; + + // Prefetch the next element + if ($this->validOnNext) $this->prefetch(); + + if ($this->uses_groups) { + // Notify the grouping helper of the change + $this->groups->reset(); + } + } + + /** + * Ensures that $this->groups works. + * + * Groups are rarely-used feature, which is why they're lazily loaded. + */ + private function initializeGroups() + { + if (!$this->uses_groups) { + $this->groups = new PHPTAL_RepeatControllerGroups(); + $this->uses_groups = true; + } + } + + /** + * Gets an object property + * + * @return $var Mixed The variable value + */ + public function __get($var) + { + switch ($var) { + case 'number': + return $this->index + 1; + case 'start': + return $this->index === 0; + case 'even': + return ($this->index % 2) === 0; + case 'odd': + return ($this->index % 2) === 1; + case 'length': + return $this->length(); + case 'letter': + return strtolower( $this->int2letter($this->index+1) ); + case 'Letter': + return strtoupper( $this->int2letter($this->index+1) ); + case 'roman': + return strtolower( $this->int2roman($this->index+1) ); + case 'Roman': + return strtoupper( $this->int2roman($this->index+1) ); + + case 'groups': + $this->initializeGroups(); + return $this->groups; + + case 'first': + $this->initializeGroups(); + // Compare the current one with the previous in the dictionary + $res = $this->groups->first($this->current); + return is_bool($res) ? $res : $this->groups; + + case 'last': + $this->initializeGroups(); + // Compare the next one with the dictionary + $res = $this->groups->last( $this->iterator->current() ); + return is_bool($res) ? $res : $this->groups; + + default: + throw new PHPTAL_VariableNotFoundException("Unable to find part '$var' in repeat variable"); + } + } + + /** + * Fetches the next element from the source data store and + * updates the end flag if needed. + * + * @access protected + */ + protected function prefetch() + { + $this->valid = true; + $this->current = $this->iterator->current(); + $this->key = $this->iterator->key(); + + $this->iterator->next(); + if ( !$this->iterator->valid() ) { + $this->valid = false; + $this->end = true; + } + } + + /** + * Converts an integer number (1 based) to a sequence of letters + * + * @param int $int The number to convert + * + * @return String The letters equivalent as a, b, c-z ... aa, ab, ac-zz ... + * @access protected + */ + protected function int2letter($int) + { + $lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $size = strlen($lookup); + + $letters = ''; + while ($int > 0) { + $int--; + $letters = $lookup[$int % $size] . $letters; + $int = floor($int / $size); + } + return $letters; + } + + /** + * Converts an integer number (1 based) to a roman numeral + * + * @param int $int The number to convert + * + * @return String The roman numeral + * @access protected + */ + protected function int2roman($int) + { + $lookup = array( + '1000' => 'M', + '900' => 'CM', + '500' => 'D', + '400' => 'CD', + '100' => 'C', + '90' => 'XC', + '50' => 'L', + '40' => 'XL', + '10' => 'X', + '9' => 'IX', + '5' => 'V', + '4' => 'IV', + '1' => 'I', + ); + + $roman = ''; + foreach ($lookup as $max => $letters) { + while ($int >= $max) { + $roman .= $letters; + $int -= $max; + } + } + + return $roman; + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/RepeatControllerGroups.php b/src/core/libs/PHPTAL5/PHPTAL/RepeatControllerGroups.php new file mode 100644 index 0000000..e6690ba --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/RepeatControllerGroups.php @@ -0,0 +1,199 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @author Iván Montes <drslump@pollinimini.net> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Keeps track of variable contents when using grouping in a path (first/ and last/) + * + * @package PHPTAL + * @subpackage Php + */ +class PHPTAL_RepeatControllerGroups +{ + protected $dict = array(); + protected $cache = array(); + protected $data = null; + protected $vars = array(); + protected $branch; + + + public function __construct() + { + $this->dict = array(); + $this->reset(); + } + + /** + * Resets the result caches. Use it to signal an iteration in the loop + * + */ + public function reset() + { + $this->cache = array(); + } + + /** + * Checks if the data passed is the first one in a group + * + * @param mixed $data The data to evaluate + * + * @return Mixed True if the first item in the group, false if not and + * this same object if the path is not finished + */ + public function first($data) + { + if ( !is_array($data) && !is_object($data) && !is_null($data) ) { + + if ( !isset($this->cache['F']) ) { + + $hash = md5($data); + + if ( !isset($this->dict['F']) || $this->dict['F'] !== $hash ) { + $this->dict['F'] = $hash; + $res = true; + } else { + $res = false; + } + + $this->cache['F'] = $res; + } + + return $this->cache['F']; + } + + $this->data = $data; + $this->branch = 'F'; + $this->vars = array(); + return $this; + } + + /** + * Checks if the data passed is the last one in a group + * + * @param mixed $data The data to evaluate + * + * @return Mixed True if the last item in the group, false if not and + * this same object if the path is not finished + */ + public function last($data) + { + if ( !is_array($data) && !is_object($data) && !is_null($data) ) { + + if ( !isset($this->cache['L']) ) { + + $hash = md5($data); + + if (empty($this->dict['L'])) { + $this->dict['L'] = $hash; + $res = false; + } elseif ($this->dict['L'] !== $hash) { + $this->dict['L'] = $hash; + $res = true; + } else { + $res = false; + } + + $this->cache['L'] = $res; + } + + return $this->cache['L']; + } + + $this->data = $data; + $this->branch = 'L'; + $this->vars = array(); + return $this; + } + + /** + * Handles variable accesses for the tal path resolver + * + * @param string $var The variable name to check + * + * @return Mixed An object/array if the path is not over or a boolean + * + * @todo replace the PHPTAL_Context::path() with custom code + */ + public function __get($var) + { + // When the iterator item is empty we just let the tal + // expression consume by continuously returning this + // same object which should evaluate to true for 'last' + if ( is_null($this->data) ) { + return $this; + } + + // Find the requested variable + $value = PHPTAL_Context::path($this->data, $var, true); + + // Check if it's an object or an array + if ( is_array($value) || is_object($value) ) { + // Move the context to the requested variable and return + $this->data = $value; + $this->addVarName($var); + return $this; + } + + // get a hash of the variable contents + $hash = md5($value); + + // compute a path for the variable to use as dictionary key + $path = $this->branch . $this->getVarPath() . $var; + + // If we don't know about this var store in the dictionary + if ( !isset($this->cache[$path]) ) { + + if ( !isset($this->dict[$path]) ) { + $this->dict[$path] = $hash; + $res = $this->branch === 'F'; + } else { + // Check if the value has changed + if ($this->dict[$path] !== $hash) { + $this->dict[$path] = $hash; + $res = true; + } else { + $res = false; + } + } + + $this->cache[$path] = $res; + } + + return $this->cache[$path]; + + } + + /** + * Adds a variable name to the current path of variables + * + * @param string $varname The variable name to store as a path part + * @access protected + */ + protected function addVarName($varname) + { + $this->vars[] = $varname; + } + + /** + * Returns the current variable path separated by a slash + * + * @return String The current variable path + * @access protected + */ + protected function getVarPath() + { + return implode('/', $this->vars) . '/'; + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Source.php b/src/core/libs/PHPTAL5/PHPTAL/Source.php new file mode 100644 index 0000000..5d54e08 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Source.php @@ -0,0 +1,52 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * You can implement this interface to load templates from various sources (see SourceResolver) + * + * @package PHPTAL + */ +interface PHPTAL_Source +{ + /** + * unique path identifying the template source. + * must not be empty. must be as unique as possible. + * + * it doesn't have to be path on disk. + * + * @return string + */ + public function getRealPath(); + + /** + * template source last modified time (unix timestamp) + * Return 0 if unknown. + * + * If you return 0: + * • PHPTAL won't know when to reparse the template, + * unless you change realPath whenever template changes. + * • clearing of cache will be marginally slower. + * + * @return long + */ + public function getLastModifiedTime(); + + /** + * the template source + * + * @return string + */ + public function getData(); +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/SourceResolver.php b/src/core/libs/PHPTAL5/PHPTAL/SourceResolver.php new file mode 100644 index 0000000..1b03190 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/SourceResolver.php @@ -0,0 +1,25 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * @package PHPTAL + */ +interface PHPTAL_SourceResolver +{ + /** + * Returns PHPTAL_Source or null. + */ + public function resolve($path); +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/StringSource.php b/src/core/libs/PHPTAL5/PHPTAL/StringSource.php new file mode 100644 index 0000000..b2de2cb --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/StringSource.php @@ -0,0 +1,51 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ +/** + * Fake template source that makes PHPTAL->setString() work + * + * @package PHPTAL + */ +class PHPTAL_StringSource implements PHPTAL_Source +{ + const NO_PATH_PREFIX = '<string '; + + public function __construct($data, $realpath = null) + { + $this->_data = $data; + $this->_realpath = $realpath ? $realpath : self::NO_PATH_PREFIX.md5($data).'>'; + } + + public function getLastModifiedTime() + { + if (substr($this->_realpath, 0, 8) !== self::NO_PATH_PREFIX && file_exists($this->_realpath)) { + return @filemtime($this->_realpath); + } + return 0; + } + + public function getData() + { + return $this->_data; + } + + /** + * well, this is not always a real path. If it starts with self::NO_PATH_PREFIX, then it's fake. + */ + public function getRealPath() + { + return $this->_realpath; + } +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/Tales.php b/src/core/libs/PHPTAL5/PHPTAL/Tales.php new file mode 100644 index 0000000..571e85e --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Tales.php @@ -0,0 +1,58 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * You can implement this interface to create custom tales modifiers + * + * Methods suitable for modifiers must be static. + * + * @package PHPTAL + * @subpackage Php + */ +interface PHPTAL_Tales +{ +} + + +/** + * translates TALES expression with alternatives into single PHP expression. + * Identical to phptal_tales() for singular expressions. + * + * Please use this function rather than PHPTAL_Php_TalesInternal methods. + * + * @see PHPTAL_Php_TalesInternal::compileToPHPExpressions() + * @return string + */ +function phptal_tale($expression, $nothrow=false) +{ + return PHPTAL_Php_TalesInternal::compileToPHPExpression($expression, $nothrow); +} + +/** + * returns PHP code that will evaluate given TALES expression. + * e.g. "string:foo${bar}" may be transformed to "'foo'.phptal_escape($ctx->bar)" + * + * Expressions with alternatives ("foo | bar") will cause it to return array + * Use phptal_tale() if you always want string. + * + * @param bool $nothrow if true, invalid expression will return NULL (at run time) rather than throwing exception + * @return string or array + */ +function phptal_tales($expression, $nothrow=false) +{ + return PHPTAL_Php_TalesInternal::compileToPHPExpressions($expression, $nothrow); +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/TalesRegistry.php b/src/core/libs/PHPTAL5/PHPTAL/TalesRegistry.php new file mode 100644 index 0000000..f519a1a --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/TalesRegistry.php @@ -0,0 +1,185 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Global registry of TALES expression modifiers + * + * @package PHPTAL + * @subpackage Php + */ +class PHPTAL_TalesRegistry +{ + private static $instance; + + /** + * This is a singleton + * + * @return PHPTAL_TalesRegistry + */ + static public function getInstance() + { + if (!self::$instance) { + self::$instance = new PHPTAL_TalesRegistry(); + } + + return self::$instance; + } + + protected function __construct() + { + $this->registerPrefix('not', array('PHPTAL_Php_TalesInternal', 'not')); + $this->registerPrefix('path', array('PHPTAL_Php_TalesInternal', 'path')); + $this->registerPrefix('string', array('PHPTAL_Php_TalesInternal', 'string')); + $this->registerPrefix('php', array('PHPTAL_Php_TalesInternal', 'php')); + $this->registerPrefix('phptal-internal-php-block', array('PHPTAL_Php_TalesInternal', 'phptal_internal_php_block')); + $this->registerPrefix('exists', array('PHPTAL_Php_TalesInternal', 'exists')); + $this->registerPrefix('number', array('PHPTAL_Php_TalesInternal', 'number')); + $this->registerPrefix('true', array('PHPTAL_Php_TalesInternal', 'true')); + + // these are added as fallbacks + $this->registerPrefix('json', array('PHPTAL_Php_TalesInternal', 'json'), true); + $this->registerPrefix('urlencode', array('PHPTAL_Php_TalesInternal', 'urlencode'), true); + } + + /** + * Unregisters a expression modifier + * + * @param string $prefix + * + * @throws PHPTAL_ConfigurationException + */ + public function unregisterPrefix($prefix) + { + if (!$this->isRegistered($prefix)) { + throw new PHPTAL_ConfigurationException("Expression modifier '$prefix' is not registered"); + } + + unset($this->_callbacks[$prefix]); + } + + /** + * + * Expects an either a function name or an array of class and method as + * callback. + * + * @param string $prefix + * @param mixed $callback + * @param bool $is_fallback if true, method will be used as last resort (if there's no phptal_tales_foo) + */ + public function registerPrefix($prefix, $callback, $is_fallback = false) + { + if ($this->isRegistered($prefix) && !$this->_callbacks[$prefix]['is_fallback']) { + if ($is_fallback) { + return; // simply ignored + } + throw new PHPTAL_ConfigurationException("Expression modifier '$prefix' is already registered"); + } + + // Check if valid callback + + if (is_array($callback)) { + + $class = new ReflectionClass($callback[0]); + + if (!$class->isSubclassOf('PHPTAL_Tales')) { + throw new PHPTAL_ConfigurationException('The class you want to register does not implement "PHPTAL_Tales".'); + } + + $method = new ReflectionMethod($callback[0], $callback[1]); + + if (!$method->isStatic()) { + throw new PHPTAL_ConfigurationException('The method you want to register is not static.'); + } + + // maybe we want to check the parameters the method takes + + } else { + if (!function_exists($callback)) { + throw new PHPTAL_ConfigurationException('The function you are trying to register does not exist.'); + } + } + + $this->_callbacks[$prefix] = array('callback'=>$callback, 'is_fallback'=>$is_fallback); + } + + /** + * true if given prefix is taken + */ + public function isRegistered($prefix) + { + if (array_key_exists($prefix, $this->_callbacks)) { + return true; + } + } + + private function findUnregisteredCallback($typePrefix) + { + // class method + if (strpos($typePrefix, '.')) { + $classCallback = explode('.', $typePrefix, 2); + $callbackName = null; + if (!is_callable($classCallback, false, $callbackName)) { + throw new PHPTAL_UnknownModifierException("Unknown phptal modifier $typePrefix. Function $callbackName does not exists or is not statically callable", $typePrefix); + } + $ref = new ReflectionClass($classCallback[0]); + if (!$ref->implementsInterface('PHPTAL_Tales')) { + throw new PHPTAL_UnknownModifierException("Unable to use phptal modifier $typePrefix as the class $callbackName does not implement the PHPTAL_Tales interface", $typePrefix); + } + return $classCallback; + } + + // check if it is implemented via code-generating function + $func = 'phptal_tales_'.str_replace('-', '_', $typePrefix); + if (function_exists($func)) { + return $func; + } + + // The following code is automatically modified in version for PHP 5.3 + $func = 'PHPTALNAMESPACE\\phptal_tales_'.str_replace('-', '_', $typePrefix); + if (function_exists($func)) { + return $func; + } + + return null; + } + + /** + * get callback for the prefix + * + * @return callback or NULL + */ + public function getCallback($prefix) + { + if ($this->isRegistered($prefix) && !$this->_callbacks[$prefix]['is_fallback']) { + return $this->_callbacks[$prefix]['callback']; + } + + if ($callback = $this->findUnregisteredCallback($prefix)) { + return $callback; + } + + if ($this->isRegistered($prefix)) { + return $this->_callbacks[$prefix]['callback']; + } + + return null; + } + + /** + * {callback, bool is_fallback} + */ + private $_callbacks = array(); +} + diff --git a/src/core/libs/PHPTAL5/PHPTAL/TemplateException.php b/src/core/libs/PHPTAL5/PHPTAL/TemplateException.php new file mode 100644 index 0000000..ce72b6b --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/TemplateException.php @@ -0,0 +1,160 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Exception that is related to location within a template. + * You can check srcFile and srcLine to find source of the error. + * + * @package PHPTAL + * @subpackage Exception + */ +class PHPTAL_TemplateException extends PHPTAL_Exception +{ + public $srcFile; + public $srcLine; + private $is_src_accurate; + + public function __construct($msg, $srcFile='', $srcLine=0) + { + parent::__construct($msg); + + if ($srcFile && $srcLine) { + $this->srcFile = $srcFile; + $this->srcLine = $srcLine; + $this->is_src_accurate = true; + } else { + $this->is_src_accurate = $this->setTemplateSource(); + } + + if ($this->is_src_accurate) { + $this->file = $this->srcFile; + $this->line = (int)$this->srcLine; + } + } + + public function __toString() + { + if (!$this->srcFile || $this->is_src_accurate) return parent::__toString(); + return "From {$this->srcFile} around line {$this->srcLine}\n".parent::__toString(); + } + + /** + * Set new TAL source file/line if it isn't known already + */ + public function hintSrcPosition($srcFile, $srcLine) + { + if ($srcFile && $srcLine) { + if (!$this->is_src_accurate) { + $this->srcFile = $srcFile; + $this->srcLine = $srcLine; + $this->is_src_accurate = true; + } else if ($this->srcLine <= 1 && $this->srcFile === $srcFile) { + $this->srcLine = $srcLine; + } + } + + if ($this->is_src_accurate) { + $this->file = $this->srcFile; + $this->line = (int)$this->srcLine; + } + } + + private function isTemplatePath($path) + { + return preg_match('/[\\\\\/]tpl_[0-9a-f]{8}_[^\\\\]+$/', $path); + } + + private function findFileAndLine() + { + if ($this->isTemplatePath($this->file)) { + return array($this->file, $this->line); + } + + $eval_line = 0; + $eval_path = NULL; + + // searches backtrace to find template file + foreach($this->getTrace() as $tr) { + if (!isset($tr['file'],$tr['line'])) continue; + + if ($this->isTemplatePath($tr['file'])) { + return array($tr['file'], $tr['line']); + } + + // PHPTAL.php uses eval() on first run to catch fatal errors. This makes template path invisible. + // However, function name matches template path and eval() is visible in backtrace. + if (false !== strpos($tr['file'], 'eval()')) { + $eval_line = $tr['line']; + } + else if ($eval_line && isset($tr['function'],$tr['args'],$tr['args'][0]) && + $this->isTemplatePath("/".$tr['function'].".php") && $tr['args'][0] instanceof PHPTAL) { + return array($tr['args'][0]->getCodePath(), $eval_line); + } + } + + return array(NULL,NULL); + } + + /** + * sets srcLine and srcFile to template path and source line + * by checking error backtrace and scanning PHP code file + * + * @return bool true if found accurate data + */ + private function setTemplateSource() + { + // not accurate, but better than null + $this->srcFile = $this->file; + $this->srcLine = $this->line; + + list($file,$line) = $this->findFileAndLine(); + + if (NULL === $file) { + return false; + } + + // this is not accurate yet, hopefully will be overwritten later + $this->srcFile = $file; + $this->srcLine = $line; + + $lines = @file($file); + if (!$lines) { + return false; + } + + $found_line=false; + $found_file=false; + + // scan lines backwards looking for "from line" comments + $end = min(count($lines), $line)-1; + for($i=$end; $i >= 0; $i--) { + if (preg_match('/tag "[^"]*" from line (\d+)/', $lines[$i], $m)) { + $this->srcLine = intval($m[1]); + $found_line=true; + break; + } + } + + foreach(preg_grep('/Generated by PHPTAL from/',$lines) as $line) { + if (preg_match('/Generated by PHPTAL from (.*) \(/', $line, $m)) { + $this->srcFile = $m[1]; + $found_file=true; + break; + } + } + + return $found_line && $found_file; + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Tokenizer.php b/src/core/libs/PHPTAL5/PHPTAL/Tokenizer.php new file mode 100644 index 0000000..25ff332 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Tokenizer.php @@ -0,0 +1,69 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id:$ + * @link http://phptal.org/ + */ + +class PHPTAL_Tokenizer +{ + private $regex, $names, $offset, $str; + + private $current_token, $current_value; + + function __construct($str, array $tokens) + { + $this->offset = 0; + $this->str = $str; + $this->end = strlen($str); + + $this->regex = '/('.str_replace('/', '\/', implode(')|(', $tokens)).')|(.)/Ssi'; + $this->names = array_keys($tokens); + $this->names[] = 'OTHER'; + } + + function eof() + { + return $this->offset >= $this->end; + } + + function skipSpace() + { + while ($this->current_token === 'SPACE') $this->nextToken(); + } + + function nextToken() + { + if ($this->offset >= $this->end) { + $this->current_value = null; + return $this->current_token = 'EOF'; + } + + //if (!preg_match_all($this->regex, $this->str, $m, PREG_SET_ORDER, $this->offset)) throw new Exception("FAIL {$this->regex} at {$this->offset}"); + if (!preg_match($this->regex, $this->str, $m, null, $this->offset)) throw new Exception("FAIL {$this->regex} didn't match '{$this->str}' at {$this->offset}"); + + $this->offset += strlen($m[0]); // in bytes + + $this->current_value = $m[0]; + $this->current_token = $this->names[count($m)-2]; // -1 for usual length/offset confusion, and minus one extra for $m[0] + + return $this->current_token; + } + + function token() + { + return $this->current_token; + } + + function tokenValue() + { + return $this->current_value; + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/TranslationService.php b/src/core/libs/PHPTAL5/PHPTAL/TranslationService.php new file mode 100644 index 0000000..0a63e3f --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/TranslationService.php @@ -0,0 +1,62 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * @package PHPTAL + */ +interface PHPTAL_TranslationService +{ + /** + * Set the target language for translations. + * + * When set to '' no translation will be done. + * + * You can specify a list of possible language for exemple : + * + * setLanguage('fr_FR', 'fr_FR@euro') + * + * @return string - chosen language + */ + function setLanguage(/*...*/); + + /** + * PHPTAL will inform translation service what encoding page uses. + * Output of translate() must be in this encoding. + */ + function setEncoding($encoding); + + /** + * Set the domain to use for translations (if different parts of application are translated in different files. This is not for language selection). + */ + function useDomain($domain); + + /** + * Set XHTML-escaped value of a variable used in translation key. + * + * You should use it to replace all ${key}s with values in translated strings. + * + * @param string $key - name of the variable + * @param string $value_escaped - XHTML markup + */ + function setVar($key, $value_escaped); + + /** + * Translate a gettext key and interpolate variables. + * + * @param string $key - translation key, e.g. "hello ${username}!" + * @param string $htmlescape - if true, you should HTML-escape translated string. You should never HTML-escape interpolated variables. + */ + function translate($key, $htmlescape=true); +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/Trigger.php b/src/core/libs/PHPTAL5/PHPTAL/Trigger.php new file mode 100644 index 0000000..4eef8fc --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/Trigger.php @@ -0,0 +1,29 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + + +/** + * Interface for Triggers (phptal:id) + * + * @package PHPTAL + */ +interface PHPTAL_Trigger +{ + const SKIPTAG = 1; + const PROCEED = 2; + + public function start($id, $tpl); + + public function end($id, $tpl); +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/UnknownModifierException.php b/src/core/libs/PHPTAL5/PHPTAL/UnknownModifierException.php new file mode 100644 index 0000000..4430a51 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/UnknownModifierException.php @@ -0,0 +1,35 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * ${unknown:foo} found in template + * + * @package PHPTAL + * @subpackage Exception + */ +class PHPTAL_UnknownModifierException extends PHPTAL_TemplateException +{ + private $modifier_name; + public function __construct($msg, $modifier_name = null) + { + $this->modifier_name = $modifier_name; + parent::__construct($msg); + } + + public function getModifierName() + { + return $this->modifier_name; + } +} diff --git a/src/core/libs/PHPTAL5/PHPTAL/VariableNotFoundException.php b/src/core/libs/PHPTAL5/PHPTAL/VariableNotFoundException.php new file mode 100644 index 0000000..dfadaf2 --- /dev/null +++ b/src/core/libs/PHPTAL5/PHPTAL/VariableNotFoundException.php @@ -0,0 +1,24 @@ +<?php +/** + * PHPTAL templating engine + * + * PHP Version 5 + * + * @category HTML + * @package PHPTAL + * @author Laurent Bedubourg <lbedubourg@motion-twin.com> + * @author Kornel Lesiński <kornel@aardvarkmedia.co.uk> + * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License + * @version SVN: $Id$ + * @link http://phptal.org/ + */ + +/** + * Runtime error in TALES expression + * + * @package PHPTAL + * @subpackage Exception + */ +class PHPTAL_VariableNotFoundException extends PHPTAL_TemplateException +{ +} diff --git a/src/core/libs/PHPTAL5/phptal_lint.php b/src/core/libs/PHPTAL5/phptal_lint.php new file mode 100755 index 0000000..f6bc76b --- /dev/null +++ b/src/core/libs/PHPTAL5/phptal_lint.php @@ -0,0 +1,283 @@ +#!/usr/bin/env php +<?php +/** + * This is lint tool for checking corectness of template syntax. + * + * You can run it on all your templates after upgrade of PHPTAL to check + * for potential incompatibilities. + * + * Another good idea is to use it as SVN hook to ensure that you + * commit only good templates to your repository. + * + * See more: + * http://phptal.org/wiki/doku.php/lint + * + * or run + * + * ./phptal_lint.php -h + * + */ + +$lint = new PHPTAL_Lint_CLI(); +$lint->main(); + +class PHPTAL_Lint_CLI +{ + function main() + { + try + { + if (! empty($_SERVER['REQUEST_URI'])) { + throw new Exception("Please use this tool from command line"); + } + + $options = $this->extended_getopt(array('-i', '-e')); + + if (isset($options['i'])) { + $this->include_path($options['i']); + } + + $this->require_phptal(); + + if (isset($options['--filenames--'])) { + $paths = $options['--filenames--']; + } + + if (!count($paths)) { + $this->usage(); + exit(1); + } + + $lint = new PHPTAL_Lint(); + + if (empty($options['i'])) { + $lint->skipUnknownModifiers(true); + } + + $custom_extensions = NULL; + if (isset($options['e'])) { + $custom_extensions = preg_split('/[\s,.]+/', $options['e'][0]); + $lint->acceptExtensions($custom_extensions); + echo "Looking for *.", implode(', *.', $custom_extensions), " files:\n"; + } + + foreach ($paths as $arg) { + if (is_dir($arg)) { + $lint->scan(rtrim($arg, DIRECTORY_SEPARATOR)); + } else { + $lint->testFile($arg); + } + } + + echo "\n\n"; + echo "Checked ".$this->plural($lint->checked, 'file')."."; + + if ($lint->skipped) { + echo " Skipped ".$this->plural($lint->skipped, "non-template file")."."; + } + echo "\n"; + if (! $custom_extensions && count($lint->skipped_filenames)) { + echo "Skipped file(s): ", implode(', ', array_keys($lint->skipped_filenames)), ".\n"; + } + + if (count($lint->errors)) { + echo "Found ".$this->plural(count($lint->errors), "error").":\n"; + $this->display_erorr_array($lint->errors); + echo "\n"; + exit(2); + } else if (count($lint->warnings)) { + echo "Found ".$this->plural(count($lint->warnings),"warning").":\n"; + $this->display_erorr_array($lint->warnings); + echo "\n"; + exit(0); + } else { + echo "No errors found!\n"; + exit($lint->checked ? 0 : 1); + } + } + catch(Exception $e) { + fwrite(STDERR, $e->getMessage() . "\n"); + $errcode = $e->getCode(); + exit($errcode ? $errcode : 1); + } + } + + + function display_erorr_array(array $errors) + { + $last_dir = '.'; + foreach ($errors as $errinfo) { + if ($errinfo[0] !== $last_dir) { + echo "In ", $errinfo[0], ":\n"; + $last_dir = $errinfo[0]; + } + echo $errinfo[1], ": ", $errinfo[2], ' (line ', $errinfo[3], ')'; + echo "\n"; + } + } + + function usage() + { + $this->require_phptal(); + echo "PHPTAL Lint 1.1.3 (PHPTAL ", strtr(PHPTAL_VERSION,"_","."), ")\n"; + + echo "Usage: phptal_lint.php [-e extensions] [-i php_file_or_directory] file_or_directory_to_check ...\n"; + echo " -e comma-separated list of extensions\n"; + echo " -i phptales file/include file, or directory\n"; + echo " Use 'phptal_lint.php .' to scan current directory\n\n"; + } + + function plural($num, $word) + { + if ($num == 1) return "$num $word"; + return "$num {$word}s"; + } + + function extended_getopt(array $options) + { + $results = array('--filenames--'=>array()); + for ($i = 1; $i < count($_SERVER['argv']); $i ++) { + if (in_array($_SERVER['argv'][$i], $options)) { + $results[substr($_SERVER['argv'][$i], 1)][] = $_SERVER['argv'][++ $i]; + } else if ($_SERVER['argv'][$i] == '--') { + $results['--filenames--'] = array_merge($results['--filenames--'], array_slice($_SERVER['argv'],$i+1)); + break; + } else if (substr($_SERVER['argv'][$i], 0, 1) == '-') { + $this->usage(); + throw new Exception("{$_SERVER['argv'][$i]} is not a valid option\n\n"); + } else { + $results['--filenames--'][] = $_SERVER['argv'][$i]; + } + } + return $results; + } + + function include_path($tales) + { + foreach ($tales as $path) { + if (is_dir($path)) { + foreach (new DirectoryIterator($path) as $file) { + if (preg_match('/\.php$/', "$path/$file") && is_file("$path/$file")) { + include_once ("$path/$file"); + } + } + } else if (preg_match('/\.php$/', $path) && is_file($path)) { + include_once ("$path"); + } + } + } + + function require_phptal() + { + if (class_exists('PHPTAL', false)) return; + + $myphptal = dirname(__FILE__) . '/../classes/PHPTAL.php'; + if (file_exists($myphptal)) { + require_once $myphptal; + } else { + require_once "PHPTAL.php"; + } + + if (!class_exists('PHPTAL') || !defined('PHPTAL_VERSION')) { + throw new Exception("Your PHPTAL installation is broken or too new for this tool"); + } + } +} + +class PHPTAL_Lint +{ + private $ignore_pattern = '/^\.|\.(?i:php|inc|jpe?g|gif|png|mo|po|txt|orig|rej|xsl|xsd|sh|in|ini|conf|css|js|py|pdf|swf|csv|ico|jar|htc)$|^Makefile|^[A-Z]+$/'; + private $accept_pattern = '/\.(?:xml|[px]?html|zpt|phptal|tal|tpl)$/i'; + private $skipUnknownModifiers = false; + + public $errors = array(); + public $warnings = array(); + public $ignored = array(); + public $skipped = 0, $skipped_filenames = array(); + public $checked = 0; + + function skipUnknownModifiers($bool) + { + $this->skipUnknownModifiers = $bool; + } + + function acceptExtensions(array $ext) { + $this->accept_pattern = '/\.(?:' . implode('|', $ext) . ')$/i'; + } + + protected function reportProgress($symbol) + { + echo $symbol; + } + + function scan($path) + { + foreach (new DirectoryIterator($path) as $entry) { + $filename = $entry->getFilename(); + + if ($filename === '.' || $filename === '..') { + continue; + } + + if (preg_match($this->ignore_pattern, $filename)) { + $this->skipped++; + continue; + } + + if ($entry->isDir()) { + $this->reportProgress('.'); + $this->scan($path . DIRECTORY_SEPARATOR . $filename); + continue; + } + + if (! preg_match($this->accept_pattern, $filename)) { + $this->skipped++; + $this->skipped_filenames[$filename] = true; + continue; + } + + $result = $this->testFile($path . DIRECTORY_SEPARATOR . $filename); + + if (self::TEST_OK == $result) { + $this->reportProgress('.'); + } else if (self::TEST_ERROR == $result) { + $this->reportProgress('E'); + } else if (self::TEST_SKIPPED == $result) { + $this->reportProgress('S'); + } + } + } + + const TEST_OK = 1; + const TEST_ERROR = 2; + const TEST_SKIPPED = 3; + + /** + * @return int - one of TEST_* constants + */ + function testFile($fullpath) + { + try { + $this->checked ++; + $phptal = new PHPTAL($fullpath); + $phptal->setForceReparse(true); + $phptal->prepare(); + return self::TEST_OK; + } + catch(PHPTAL_UnknownModifierException $e) { + if ($this->skipUnknownModifiers && is_callable(array($e, 'getModifierName'))) { + $this->warnings[] = array(dirname($fullpath), basename($fullpath), "Unknown expression modifier: ".$e->getModifierName()." (use -i to include your custom modifier functions)", $e->getLine()); + return self::TEST_SKIPPED; + } + $log_exception = $e; + } + catch(Exception $e) { + $log_exception = $e; + } + + // Takes exception from either of the two catch blocks above + $this->errors[] = array(dirname($fullpath) , basename($fullpath) , $log_exception->getMessage() , $log_exception->getLine()); + return self::TEST_ERROR; + } +} + diff --git a/src/core/libs/Psr/Log/AbstractLogger.php b/src/core/libs/Psr/Log/AbstractLogger.php new file mode 100755 index 0000000..00f9034 --- /dev/null +++ b/src/core/libs/Psr/Log/AbstractLogger.php @@ -0,0 +1,120 @@ +<?php + +namespace Psr\Log; + +/** + * This is a simple Logger implementation that other Loggers can inherit from. + * + * It simply delegates all log-level-specific methods to the `log` method to + * reduce boilerplate code that a simple Logger that does the same thing with + * messages regardless of the error level has to implement. + */ +abstract class AbstractLogger implements LoggerInterface +{ + /** + * System is unusable. + * + * @param string $message + * @param array $context + * @return null + */ + public function emergency($message, array $context = array()) + { + $this->log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * @return null + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * @return null + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * @return null + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * @return null + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * @return null + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * @return null + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * @return null + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } +} diff --git a/src/core/libs/Psr/Log/InvalidArgumentException.php b/src/core/libs/Psr/Log/InvalidArgumentException.php new file mode 100755 index 0000000..67f852d --- /dev/null +++ b/src/core/libs/Psr/Log/InvalidArgumentException.php @@ -0,0 +1,7 @@ +<?php + +namespace Psr\Log; + +class InvalidArgumentException extends \InvalidArgumentException +{ +} diff --git a/src/core/libs/Psr/Log/LogLevel.php b/src/core/libs/Psr/Log/LogLevel.php new file mode 100755 index 0000000..e32c151 --- /dev/null +++ b/src/core/libs/Psr/Log/LogLevel.php @@ -0,0 +1,18 @@ +<?php + +namespace Psr\Log; + +/** + * Describes log levels + */ +class LogLevel +{ + const EMERGENCY = 'emergency'; + const ALERT = 'alert'; + const CRITICAL = 'critical'; + const ERROR = 'error'; + const WARNING = 'warning'; + const NOTICE = 'notice'; + const INFO = 'info'; + const DEBUG = 'debug'; +} diff --git a/src/core/libs/Psr/Log/LoggerAwareInterface.php b/src/core/libs/Psr/Log/LoggerAwareInterface.php new file mode 100755 index 0000000..2eebc4e --- /dev/null +++ b/src/core/libs/Psr/Log/LoggerAwareInterface.php @@ -0,0 +1,17 @@ +<?php + +namespace Psr\Log; + +/** + * Describes a logger-aware instance + */ +interface LoggerAwareInterface +{ + /** + * Sets a logger instance on the object + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger); +} diff --git a/src/core/libs/Psr/Log/LoggerAwareTrait.php b/src/core/libs/Psr/Log/LoggerAwareTrait.php new file mode 100755 index 0000000..31de587 --- /dev/null +++ b/src/core/libs/Psr/Log/LoggerAwareTrait.php @@ -0,0 +1,22 @@ +<?php + +namespace Psr\Log; + +/** + * Basic Implementation of LoggerAwareInterface. + */ +trait LoggerAwareTrait +{ + /** @var LoggerInterface */ + protected $logger; + + /** + * Sets a logger. + * + * @param LoggerInterface $logger + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + } +} diff --git a/src/core/libs/Psr/Log/LoggerInterface.php b/src/core/libs/Psr/Log/LoggerInterface.php new file mode 100755 index 0000000..476bb96 --- /dev/null +++ b/src/core/libs/Psr/Log/LoggerInterface.php @@ -0,0 +1,114 @@ +<?php + +namespace Psr\Log; + +/** + * Describes a logger instance + * + * The message MUST be a string or object implementing __toString(). + * + * The message MAY contain placeholders in the form: {foo} where foo + * will be replaced by the context data in key "foo". + * + * The context array can contain arbitrary data, the only assumption that + * can be made by implementors is that if an Exception instance is given + * to produce a stack trace, it MUST be in a key named "exception". + * + * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md + * for the full interface specification. + */ +interface LoggerInterface +{ + /** + * System is unusable. + * + * @param string $message + * @param array $context + * @return null + */ + public function emergency($message, array $context = array()); + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * @return null + */ + public function alert($message, array $context = array()); + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * @return null + */ + public function critical($message, array $context = array()); + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * @return null + */ + public function error($message, array $context = array()); + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * @return null + */ + public function warning($message, array $context = array()); + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * @return null + */ + public function notice($message, array $context = array()); + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * @return null + */ + public function info($message, array $context = array()); + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * @return null + */ + public function debug($message, array $context = array()); + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + public function log($level, $message, array $context = array()); +} diff --git a/src/core/libs/Psr/Log/LoggerTrait.php b/src/core/libs/Psr/Log/LoggerTrait.php new file mode 100755 index 0000000..85597f5 --- /dev/null +++ b/src/core/libs/Psr/Log/LoggerTrait.php @@ -0,0 +1,131 @@ +<?php + +namespace Psr\Log; + +/** + * This is a simple Logger trait that classes unable to extend AbstractLogger + * (because they extend another class, etc) can include. + * + * It simply delegates all log-level-specific methods to the `log` method to + * reduce boilerplate code that a simple Logger that does the same thing with + * messages regardless of the error level has to implement. + */ +trait LoggerTrait +{ + /** + * System is unusable. + * + * @param string $message + * @param array $context + * @return null + */ + public function emergency($message, array $context = array()) + { + $this->log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * @return null + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * @return null + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * @return null + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * @return null + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * @return null + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * @return null + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * @return null + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + abstract public function log($level, $message, array $context = array()); +} diff --git a/src/core/libs/Psr/Log/NullLogger.php b/src/core/libs/Psr/Log/NullLogger.php new file mode 100755 index 0000000..553a3c5 --- /dev/null +++ b/src/core/libs/Psr/Log/NullLogger.php @@ -0,0 +1,27 @@ +<?php + +namespace Psr\Log; + +/** + * This Logger can be used to avoid conditional log calls + * + * Logging should always be optional, and if no logger is provided to your + * library creating a NullLogger instance to have something to throw logs at + * is a good way to avoid littering your code with `if ($this->logger) { }` + * blocks. + */ +class NullLogger extends AbstractLogger +{ + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + public function log($level, $message, array $context = array()) + { + // noop + } +} diff --git a/src/core/libs/Psr/Log/Test/LoggerInterfaceTest.php b/src/core/libs/Psr/Log/Test/LoggerInterfaceTest.php new file mode 100755 index 0000000..7f8cabc --- /dev/null +++ b/src/core/libs/Psr/Log/Test/LoggerInterfaceTest.php @@ -0,0 +1,130 @@ +<?php + +namespace Psr\Log\Test; + +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; + +/** + * Provides a base test class for ensuring compliance with the LoggerInterface + * + * Implementors can extend the class and implement abstract methods to run this as part of their test suite + */ +abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase +{ + /** + * @return LoggerInterface + */ + abstract function getLogger(); + + /** + * This must return the log messages in order with a simple formatting: "<LOG LEVEL> <MESSAGE>" + * + * Example ->error('Foo') would yield "error Foo" + * + * @return string[] + */ + abstract function getLogs(); + + public function testImplements() + { + $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger()); + } + + /** + * @dataProvider provideLevelsAndMessages + */ + public function testLogsAtAllLevels($level, $message) + { + $logger = $this->getLogger(); + $logger->{$level}($message, array('user' => 'Bob')); + $logger->log($level, $message, array('user' => 'Bob')); + + $expected = array( + $level.' message of level '.$level.' with context: Bob', + $level.' message of level '.$level.' with context: Bob', + ); + $this->assertEquals($expected, $this->getLogs()); + } + + public function provideLevelsAndMessages() + { + return array( + LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), + LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), + LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), + LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), + LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), + LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), + LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), + LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), + ); + } + + /** + * @expectedException \Psr\Log\InvalidArgumentException + */ + public function testThrowsOnInvalidLevel() + { + $logger = $this->getLogger(); + $logger->log('invalid level', 'Foo'); + } + + public function testContextReplacement() + { + $logger = $this->getLogger(); + $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); + + $expected = array('info {Message {nothing} Bob Bar a}'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testObjectCastToString() + { + $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString')); + $dummy->expects($this->once()) + ->method('__toString') + ->will($this->returnValue('DUMMY')); + + $this->getLogger()->warning($dummy); + + $expected = array('warning DUMMY'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextCanContainAnything() + { + $context = array( + 'bool' => true, + 'null' => null, + 'string' => 'Foo', + 'int' => 0, + 'float' => 0.5, + 'nested' => array('with object' => new DummyTest), + 'object' => new \DateTime, + 'resource' => fopen('php://memory', 'r'), + ); + + $this->getLogger()->warning('Crazy context data', $context); + + $expected = array('warning Crazy context data'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextExceptionKeyCanBeExceptionOrOtherValues() + { + $logger = $this->getLogger(); + $logger->warning('Random message', array('exception' => 'oops')); + $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); + + $expected = array( + 'warning Random message', + 'critical Uncaught Exception!' + ); + $this->assertEquals($expected, $this->getLogs()); + } +} + +class DummyTest +{ +} diff --git a/src/core/libs/Twig/Autoloader.php b/src/core/libs/Twig/Autoloader.php new file mode 100755 index 0000000..0ae1127 --- /dev/null +++ b/src/core/libs/Twig/Autoloader.php @@ -0,0 +1,48 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Autoloads Twig classes. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Autoloader +{ + /** + * Registers Twig_Autoloader as an SPL autoloader. + * + * @param Boolean $prepend Whether to prepend the autoloader or not. + */ + public static function register($prepend = false) + { + if (version_compare(phpversion(), '5.3.0', '>=')) { + spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend); + } else { + spl_autoload_register(array(__CLASS__, 'autoload')); + } + } + + /** + * Handles autoloading of classes. + * + * @param string $class A class name. + */ + public static function autoload($class) + { + if (0 !== strpos($class, 'Twig')) { + return; + } + + if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) { + require $file; + } + } +} diff --git a/src/core/libs/Twig/Compiler.php b/src/core/libs/Twig/Compiler.php new file mode 100755 index 0000000..bb6b129 --- /dev/null +++ b/src/core/libs/Twig/Compiler.php @@ -0,0 +1,270 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Compiles a node to PHP code. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Compiler implements Twig_CompilerInterface +{ + protected $lastLine; + protected $source; + protected $indentation; + protected $env; + protected $debugInfo; + protected $sourceOffset; + protected $sourceLine; + protected $filename; + + /** + * Constructor. + * + * @param Twig_Environment $env The twig environment instance + */ + public function __construct(Twig_Environment $env) + { + $this->env = $env; + $this->debugInfo = array(); + } + + public function getFilename() + { + return $this->filename; + } + + /** + * Returns the environment instance related to this compiler. + * + * @return Twig_Environment The environment instance + */ + public function getEnvironment() + { + return $this->env; + } + + /** + * Gets the current PHP code after compilation. + * + * @return string The PHP code + */ + public function getSource() + { + return $this->source; + } + + /** + * Compiles a node. + * + * @param Twig_NodeInterface $node The node to compile + * @param integer $indentation The current indentation + * + * @return Twig_Compiler The current compiler instance + */ + public function compile(Twig_NodeInterface $node, $indentation = 0) + { + $this->lastLine = null; + $this->source = ''; + $this->sourceOffset = 0; + // source code starts at 1 (as we then increment it when we encounter new lines) + $this->sourceLine = 1; + $this->indentation = $indentation; + + if ($node instanceof Twig_Node_Module) { + $this->filename = $node->getAttribute('filename'); + } + + $node->compile($this); + + return $this; + } + + public function subcompile(Twig_NodeInterface $node, $raw = true) + { + if (false === $raw) { + $this->addIndentation(); + } + + $node->compile($this); + + return $this; + } + + /** + * Adds a raw string to the compiled code. + * + * @param string $string The string + * + * @return Twig_Compiler The current compiler instance + */ + public function raw($string) + { + $this->source .= $string; + + return $this; + } + + /** + * Writes a string to the compiled code by adding indentation. + * + * @return Twig_Compiler The current compiler instance + */ + public function write() + { + $strings = func_get_args(); + foreach ($strings as $string) { + $this->addIndentation(); + $this->source .= $string; + } + + return $this; + } + + /** + * Appends an indentation to the current PHP code after compilation. + * + * @return Twig_Compiler The current compiler instance + */ + public function addIndentation() + { + $this->source .= str_repeat(' ', $this->indentation * 4); + + return $this; + } + + /** + * Adds a quoted string to the compiled code. + * + * @param string $value The string + * + * @return Twig_Compiler The current compiler instance + */ + public function string($value) + { + $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\")); + + return $this; + } + + /** + * Returns a PHP representation of a given value. + * + * @param mixed $value The value to convert + * + * @return Twig_Compiler The current compiler instance + */ + public function repr($value) + { + if (is_int($value) || is_float($value)) { + if (false !== $locale = setlocale(LC_NUMERIC, 0)) { + setlocale(LC_NUMERIC, 'C'); + } + + $this->raw($value); + + if (false !== $locale) { + setlocale(LC_NUMERIC, $locale); + } + } elseif (null === $value) { + $this->raw('null'); + } elseif (is_bool($value)) { + $this->raw($value ? 'true' : 'false'); + } elseif (is_array($value)) { + $this->raw('array('); + $first = true; + foreach ($value as $key => $value) { + if (!$first) { + $this->raw(', '); + } + $first = false; + $this->repr($key); + $this->raw(' => '); + $this->repr($value); + } + $this->raw(')'); + } else { + $this->string($value); + } + + return $this; + } + + /** + * Adds debugging information. + * + * @param Twig_NodeInterface $node The related twig node + * + * @return Twig_Compiler The current compiler instance + */ + public function addDebugInfo(Twig_NodeInterface $node) + { + if ($node->getLine() != $this->lastLine) { + $this->write(sprintf("// line %d\n", $node->getLine())); + + // when mbstring.func_overload is set to 2 + // mb_substr_count() replaces substr_count() + // but they have different signatures! + if (((int) ini_get('mbstring.func_overload')) & 2) { + // this is much slower than the "right" version + $this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n"); + } else { + $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset); + } + $this->sourceOffset = strlen($this->source); + $this->debugInfo[$this->sourceLine] = $node->getLine(); + + $this->lastLine = $node->getLine(); + } + + return $this; + } + + public function getDebugInfo() + { + return $this->debugInfo; + } + + /** + * Indents the generated code. + * + * @param integer $step The number of indentation to add + * + * @return Twig_Compiler The current compiler instance + */ + public function indent($step = 1) + { + $this->indentation += $step; + + return $this; + } + + /** + * Outdents the generated code. + * + * @param integer $step The number of indentation to remove + * + * @return Twig_Compiler The current compiler instance + * + * @throws LogicException When trying to outdent too much so the indentation would become negative + */ + public function outdent($step = 1) + { + // can't outdent by more steps than the current indentation level + if ($this->indentation < $step) { + throw new LogicException('Unable to call outdent() as the indentation would become negative'); + } + + $this->indentation -= $step; + + return $this; + } +} diff --git a/src/core/libs/Twig/CompilerInterface.php b/src/core/libs/Twig/CompilerInterface.php new file mode 100755 index 0000000..e293ec9 --- /dev/null +++ b/src/core/libs/Twig/CompilerInterface.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Interface implemented by compiler classes. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_CompilerInterface +{ + /** + * Compiles a node. + * + * @param Twig_NodeInterface $node The node to compile + * + * @return Twig_CompilerInterface The current compiler instance + */ + public function compile(Twig_NodeInterface $node); + + /** + * Gets the current PHP code after compilation. + * + * @return string The PHP code + */ + public function getSource(); +} diff --git a/src/core/libs/Twig/Environment.php b/src/core/libs/Twig/Environment.php new file mode 100755 index 0000000..1fec1a3 --- /dev/null +++ b/src/core/libs/Twig/Environment.php @@ -0,0 +1,1254 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Stores the Twig configuration. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Environment +{ + const VERSION = '1.15.1'; + + protected $charset; + protected $loader; + protected $debug; + protected $autoReload; + protected $cache; + protected $lexer; + protected $parser; + protected $compiler; + protected $baseTemplateClass; + protected $extensions; + protected $parsers; + protected $visitors; + protected $filters; + protected $tests; + protected $functions; + protected $globals; + protected $runtimeInitialized; + protected $extensionInitialized; + protected $loadedTemplates; + protected $strictVariables; + protected $unaryOperators; + protected $binaryOperators; + protected $templateClassPrefix = '__TwigTemplate_'; + protected $functionCallbacks; + protected $filterCallbacks; + protected $staging; + + /** + * Constructor. + * + * Available options: + * + * * debug: When set to true, it automatically set "auto_reload" to true as + * well (default to false). + * + * * charset: The charset used by the templates (default to UTF-8). + * + * * base_template_class: The base template class to use for generated + * templates (default to Twig_Template). + * + * * cache: An absolute path where to store the compiled templates, or + * false to disable compilation cache (default). + * + * * auto_reload: Whether to reload the template if the original source changed. + * If you don't provide the auto_reload option, it will be + * determined automatically based on the debug value. + * + * * strict_variables: Whether to ignore invalid variables in templates + * (default to false). + * + * * autoescape: Whether to enable auto-escaping (default to html): + * * false: disable auto-escaping + * * true: equivalent to html + * * html, js: set the autoescaping to one of the supported strategies + * * PHP callback: a PHP callback that returns an escaping strategy based on the template "filename" + * + * * optimizations: A flag that indicates which optimizations to apply + * (default to -1 which means that all optimizations are enabled; + * set it to 0 to disable). + * + * @param Twig_LoaderInterface $loader A Twig_LoaderInterface instance + * @param array $options An array of options + */ + public function __construct(Twig_LoaderInterface $loader = null, $options = array()) + { + if (null !== $loader) { + $this->setLoader($loader); + } + + $options = array_merge(array( + 'debug' => false, + 'charset' => 'UTF-8', + 'base_template_class' => 'Twig_Template', + 'strict_variables' => false, + 'autoescape' => 'html', + 'cache' => false, + 'auto_reload' => null, + 'optimizations' => -1, + ), $options); + + $this->debug = (bool) $options['debug']; + $this->charset = strtoupper($options['charset']); + $this->baseTemplateClass = $options['base_template_class']; + $this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload']; + $this->strictVariables = (bool) $options['strict_variables']; + $this->runtimeInitialized = false; + $this->setCache($options['cache']); + $this->functionCallbacks = array(); + $this->filterCallbacks = array(); + + $this->addExtension(new Twig_Extension_Core()); + $this->addExtension(new Twig_Extension_Escaper($options['autoescape'])); + $this->addExtension(new Twig_Extension_Optimizer($options['optimizations'])); + $this->extensionInitialized = false; + $this->staging = new Twig_Extension_Staging(); + } + + /** + * Gets the base template class for compiled templates. + * + * @return string The base template class name + */ + public function getBaseTemplateClass() + { + return $this->baseTemplateClass; + } + + /** + * Sets the base template class for compiled templates. + * + * @param string $class The base template class name + */ + public function setBaseTemplateClass($class) + { + $this->baseTemplateClass = $class; + } + + /** + * Enables debugging mode. + */ + public function enableDebug() + { + $this->debug = true; + } + + /** + * Disables debugging mode. + */ + public function disableDebug() + { + $this->debug = false; + } + + /** + * Checks if debug mode is enabled. + * + * @return Boolean true if debug mode is enabled, false otherwise + */ + public function isDebug() + { + return $this->debug; + } + + /** + * Enables the auto_reload option. + */ + public function enableAutoReload() + { + $this->autoReload = true; + } + + /** + * Disables the auto_reload option. + */ + public function disableAutoReload() + { + $this->autoReload = false; + } + + /** + * Checks if the auto_reload option is enabled. + * + * @return Boolean true if auto_reload is enabled, false otherwise + */ + public function isAutoReload() + { + return $this->autoReload; + } + + /** + * Enables the strict_variables option. + */ + public function enableStrictVariables() + { + $this->strictVariables = true; + } + + /** + * Disables the strict_variables option. + */ + public function disableStrictVariables() + { + $this->strictVariables = false; + } + + /** + * Checks if the strict_variables option is enabled. + * + * @return Boolean true if strict_variables is enabled, false otherwise + */ + public function isStrictVariables() + { + return $this->strictVariables; + } + + /** + * Gets the cache directory or false if cache is disabled. + * + * @return string|false + */ + public function getCache() + { + return $this->cache; + } + + /** + * Sets the cache directory or false if cache is disabled. + * + * @param string|false $cache The absolute path to the compiled templates, + * or false to disable cache + */ + public function setCache($cache) + { + $this->cache = $cache ? $cache : false; + } + + /** + * Gets the cache filename for a given template. + * + * @param string $name The template name + * + * @return string|false The cache file name or false when caching is disabled + */ + public function getCacheFilename($name) + { + if (false === $this->cache) { + return false; + } + + $class = substr($this->getTemplateClass($name), strlen($this->templateClassPrefix)); + + return $this->getCache().'/'.substr($class, 0, 2).'/'.substr($class, 2, 2).'/'.substr($class, 4).'.php'; + } + + /** + * Gets the template class associated with the given string. + * + * @param string $name The name for which to calculate the template class name + * @param integer $index The index if it is an embedded template + * + * @return string The template class name + */ + public function getTemplateClass($name, $index = null) + { + return $this->templateClassPrefix.hash('sha256', $this->getLoader()->getCacheKey($name)).(null === $index ? '' : '_'.$index); + } + + /** + * Gets the template class prefix. + * + * @return string The template class prefix + */ + public function getTemplateClassPrefix() + { + return $this->templateClassPrefix; + } + + /** + * Renders a template. + * + * @param string $name The template name + * @param array $context An array of parameters to pass to the template + * + * @return string The rendered template + * + * @throws Twig_Error_Loader When the template cannot be found + * @throws Twig_Error_Syntax When an error occurred during compilation + * @throws Twig_Error_Runtime When an error occurred during rendering + */ + public function render($name, array $context = array()) + { + return $this->loadTemplate($name)->render($context); + } + + /** + * Displays a template. + * + * @param string $name The template name + * @param array $context An array of parameters to pass to the template + * + * @throws Twig_Error_Loader When the template cannot be found + * @throws Twig_Error_Syntax When an error occurred during compilation + * @throws Twig_Error_Runtime When an error occurred during rendering + */ + public function display($name, array $context = array()) + { + $this->loadTemplate($name)->display($context); + } + + /** + * Loads a template by name. + * + * @param string $name The template name + * @param integer $index The index if it is an embedded template + * + * @return Twig_TemplateInterface A template instance representing the given template name + * + * @throws Twig_Error_Loader When the template cannot be found + * @throws Twig_Error_Syntax When an error occurred during compilation + */ + public function loadTemplate($name, $index = null) + { + $cls = $this->getTemplateClass($name, $index); + + if (isset($this->loadedTemplates[$cls])) { + return $this->loadedTemplates[$cls]; + } + + if (!class_exists($cls, false)) { + if (false === $cache = $this->getCacheFilename($name)) { + eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name)); + } else { + if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) { + $this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name)); + } + + require_once $cache; + } + } + + if (!$this->runtimeInitialized) { + $this->initRuntime(); + } + + return $this->loadedTemplates[$cls] = new $cls($this); + } + + /** + * Returns true if the template is still fresh. + * + * Besides checking the loader for freshness information, + * this method also checks if the enabled extensions have + * not changed. + * + * @param string $name The template name + * @param timestamp $time The last modification time of the cached template + * + * @return Boolean true if the template is fresh, false otherwise + */ + public function isTemplateFresh($name, $time) + { + foreach ($this->extensions as $extension) { + $r = new ReflectionObject($extension); + if (filemtime($r->getFileName()) > $time) { + return false; + } + } + + return $this->getLoader()->isFresh($name, $time); + } + + /** + * Tries to load a template consecutively from an array. + * + * Similar to loadTemplate() but it also accepts Twig_TemplateInterface instances and an array + * of templates where each is tried to be loaded. + * + * @param string|Twig_Template|array $names A template or an array of templates to try consecutively + * + * @return Twig_Template + * + * @throws Twig_Error_Loader When none of the templates can be found + * @throws Twig_Error_Syntax When an error occurred during compilation + */ + public function resolveTemplate($names) + { + if (!is_array($names)) { + $names = array($names); + } + + foreach ($names as $name) { + if ($name instanceof Twig_Template) { + return $name; + } + + try { + return $this->loadTemplate($name); + } catch (Twig_Error_Loader $e) { + } + } + + if (1 === count($names)) { + throw $e; + } + + throw new Twig_Error_Loader(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names))); + } + + /** + * Clears the internal template cache. + */ + public function clearTemplateCache() + { + $this->loadedTemplates = array(); + } + + /** + * Clears the template cache files on the filesystem. + */ + public function clearCacheFiles() + { + if (false === $this->cache) { + return; + } + + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->cache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + if ($file->isFile()) { + @unlink($file->getPathname()); + } + } + } + + /** + * Gets the Lexer instance. + * + * @return Twig_LexerInterface A Twig_LexerInterface instance + */ + public function getLexer() + { + if (null === $this->lexer) { + $this->lexer = new Twig_Lexer($this); + } + + return $this->lexer; + } + + /** + * Sets the Lexer instance. + * + * @param Twig_LexerInterface A Twig_LexerInterface instance + */ + public function setLexer(Twig_LexerInterface $lexer) + { + $this->lexer = $lexer; + } + + /** + * Tokenizes a source code. + * + * @param string $source The template source code + * @param string $name The template name + * + * @return Twig_TokenStream A Twig_TokenStream instance + * + * @throws Twig_Error_Syntax When the code is syntactically wrong + */ + public function tokenize($source, $name = null) + { + return $this->getLexer()->tokenize($source, $name); + } + + /** + * Gets the Parser instance. + * + * @return Twig_ParserInterface A Twig_ParserInterface instance + */ + public function getParser() + { + if (null === $this->parser) { + $this->parser = new Twig_Parser($this); + } + + return $this->parser; + } + + /** + * Sets the Parser instance. + * + * @param Twig_ParserInterface A Twig_ParserInterface instance + */ + public function setParser(Twig_ParserInterface $parser) + { + $this->parser = $parser; + } + + /** + * Converts a token stream to a node tree. + * + * @param Twig_TokenStream $stream A token stream instance + * + * @return Twig_Node_Module A node tree + * + * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong + */ + public function parse(Twig_TokenStream $stream) + { + return $this->getParser()->parse($stream); + } + + /** + * Gets the Compiler instance. + * + * @return Twig_CompilerInterface A Twig_CompilerInterface instance + */ + public function getCompiler() + { + if (null === $this->compiler) { + $this->compiler = new Twig_Compiler($this); + } + + return $this->compiler; + } + + /** + * Sets the Compiler instance. + * + * @param Twig_CompilerInterface $compiler A Twig_CompilerInterface instance + */ + public function setCompiler(Twig_CompilerInterface $compiler) + { + $this->compiler = $compiler; + } + + /** + * Compiles a node and returns the PHP code. + * + * @param Twig_NodeInterface $node A Twig_NodeInterface instance + * + * @return string The compiled PHP source code + */ + public function compile(Twig_NodeInterface $node) + { + return $this->getCompiler()->compile($node)->getSource(); + } + + /** + * Compiles a template source code. + * + * @param string $source The template source code + * @param string $name The template name + * + * @return string The compiled PHP source code + * + * @throws Twig_Error_Syntax When there was an error during tokenizing, parsing or compiling + */ + public function compileSource($source, $name = null) + { + try { + return $this->compile($this->parse($this->tokenize($source, $name))); + } catch (Twig_Error $e) { + $e->setTemplateFile($name); + throw $e; + } catch (Exception $e) { + throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $name, $e); + } + } + + /** + * Sets the Loader instance. + * + * @param Twig_LoaderInterface $loader A Twig_LoaderInterface instance + */ + public function setLoader(Twig_LoaderInterface $loader) + { + $this->loader = $loader; + } + + /** + * Gets the Loader instance. + * + * @return Twig_LoaderInterface A Twig_LoaderInterface instance + */ + public function getLoader() + { + if (null === $this->loader) { + throw new LogicException('You must set a loader first.'); + } + + return $this->loader; + } + + /** + * Sets the default template charset. + * + * @param string $charset The default charset + */ + public function setCharset($charset) + { + $this->charset = strtoupper($charset); + } + + /** + * Gets the default template charset. + * + * @return string The default charset + */ + public function getCharset() + { + return $this->charset; + } + + /** + * Initializes the runtime environment. + */ + public function initRuntime() + { + $this->runtimeInitialized = true; + + foreach ($this->getExtensions() as $extension) { + $extension->initRuntime($this); + } + } + + /** + * Returns true if the given extension is registered. + * + * @param string $name The extension name + * + * @return Boolean Whether the extension is registered or not + */ + public function hasExtension($name) + { + return isset($this->extensions[$name]); + } + + /** + * Gets an extension by name. + * + * @param string $name The extension name + * + * @return Twig_ExtensionInterface A Twig_ExtensionInterface instance + */ + public function getExtension($name) + { + if (!isset($this->extensions[$name])) { + throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.', $name)); + } + + return $this->extensions[$name]; + } + + /** + * Registers an extension. + * + * @param Twig_ExtensionInterface $extension A Twig_ExtensionInterface instance + */ + public function addExtension(Twig_ExtensionInterface $extension) + { + if ($this->extensionInitialized) { + throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName())); + } + + $this->extensions[$extension->getName()] = $extension; + } + + /** + * Removes an extension by name. + * + * This method is deprecated and you should not use it. + * + * @param string $name The extension name + * + * @deprecated since 1.12 (to be removed in 2.0) + */ + public function removeExtension($name) + { + if ($this->extensionInitialized) { + throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name)); + } + + unset($this->extensions[$name]); + } + + /** + * Registers an array of extensions. + * + * @param array $extensions An array of extensions + */ + public function setExtensions(array $extensions) + { + foreach ($extensions as $extension) { + $this->addExtension($extension); + } + } + + /** + * Returns all registered extensions. + * + * @return array An array of extensions + */ + public function getExtensions() + { + return $this->extensions; + } + + /** + * Registers a Token Parser. + * + * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance + */ + public function addTokenParser(Twig_TokenParserInterface $parser) + { + if ($this->extensionInitialized) { + throw new LogicException('Unable to add a token parser as extensions have already been initialized.'); + } + + $this->staging->addTokenParser($parser); + } + + /** + * Gets the registered Token Parsers. + * + * @return Twig_TokenParserBrokerInterface A broker containing token parsers + */ + public function getTokenParsers() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->parsers; + } + + /** + * Gets registered tags. + * + * Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes. + * + * @return Twig_TokenParserInterface[] An array of Twig_TokenParserInterface instances + */ + public function getTags() + { + $tags = array(); + foreach ($this->getTokenParsers()->getParsers() as $parser) { + if ($parser instanceof Twig_TokenParserInterface) { + $tags[$parser->getTag()] = $parser; + } + } + + return $tags; + } + + /** + * Registers a Node Visitor. + * + * @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance + */ + public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) + { + if ($this->extensionInitialized) { + throw new LogicException('Unable to add a node visitor as extensions have already been initialized.'); + } + + $this->staging->addNodeVisitor($visitor); + } + + /** + * Gets the registered Node Visitors. + * + * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances + */ + public function getNodeVisitors() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->visitors; + } + + /** + * Registers a Filter. + * + * @param string|Twig_SimpleFilter $name The filter name or a Twig_SimpleFilter instance + * @param Twig_FilterInterface|Twig_SimpleFilter $filter A Twig_FilterInterface instance or a Twig_SimpleFilter instance + */ + public function addFilter($name, $filter = null) + { + if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) { + throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter'); + } + + if ($name instanceof Twig_SimpleFilter) { + $filter = $name; + $name = $filter->getName(); + } + + if ($this->extensionInitialized) { + throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name)); + } + + $this->staging->addFilter($name, $filter); + } + + /** + * Get a filter by name. + * + * Subclasses may override this method and load filters differently; + * so no list of filters is available. + * + * @param string $name The filter name + * + * @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exist + */ + public function getFilter($name) + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + if (isset($this->filters[$name])) { + return $this->filters[$name]; + } + + foreach ($this->filters as $pattern => $filter) { + $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); + + if ($count) { + if (preg_match('#^'.$pattern.'$#', $name, $matches)) { + array_shift($matches); + $filter->setArguments($matches); + + return $filter; + } + } + } + + foreach ($this->filterCallbacks as $callback) { + if (false !== $filter = call_user_func($callback, $name)) { + return $filter; + } + } + + return false; + } + + public function registerUndefinedFilterCallback($callable) + { + $this->filterCallbacks[] = $callable; + } + + /** + * Gets the registered Filters. + * + * Be warned that this method cannot return filters defined with registerUndefinedFunctionCallback. + * + * @return Twig_FilterInterface[] An array of Twig_FilterInterface instances + * + * @see registerUndefinedFilterCallback + */ + public function getFilters() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->filters; + } + + /** + * Registers a Test. + * + * @param string|Twig_SimpleTest $name The test name or a Twig_SimpleTest instance + * @param Twig_TestInterface|Twig_SimpleTest $test A Twig_TestInterface instance or a Twig_SimpleTest instance + */ + public function addTest($name, $test = null) + { + if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) { + throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest'); + } + + if ($name instanceof Twig_SimpleTest) { + $test = $name; + $name = $test->getName(); + } + + if ($this->extensionInitialized) { + throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name)); + } + + $this->staging->addTest($name, $test); + } + + /** + * Gets the registered Tests. + * + * @return Twig_TestInterface[] An array of Twig_TestInterface instances + */ + public function getTests() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->tests; + } + + /** + * Gets a test by name. + * + * @param string $name The test name + * + * @return Twig_Test|false A Twig_Test instance or false if the test does not exist + */ + public function getTest($name) + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + if (isset($this->tests[$name])) { + return $this->tests[$name]; + } + + return false; + } + + /** + * Registers a Function. + * + * @param string|Twig_SimpleFunction $name The function name or a Twig_SimpleFunction instance + * @param Twig_FunctionInterface|Twig_SimpleFunction $function A Twig_FunctionInterface instance or a Twig_SimpleFunction instance + */ + public function addFunction($name, $function = null) + { + if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) { + throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction'); + } + + if ($name instanceof Twig_SimpleFunction) { + $function = $name; + $name = $function->getName(); + } + + if ($this->extensionInitialized) { + throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name)); + } + + $this->staging->addFunction($name, $function); + } + + /** + * Get a function by name. + * + * Subclasses may override this method and load functions differently; + * so no list of functions is available. + * + * @param string $name function name + * + * @return Twig_Function|false A Twig_Function instance or false if the function does not exist + */ + public function getFunction($name) + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + if (isset($this->functions[$name])) { + return $this->functions[$name]; + } + + foreach ($this->functions as $pattern => $function) { + $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); + + if ($count) { + if (preg_match('#^'.$pattern.'$#', $name, $matches)) { + array_shift($matches); + $function->setArguments($matches); + + return $function; + } + } + } + + foreach ($this->functionCallbacks as $callback) { + if (false !== $function = call_user_func($callback, $name)) { + return $function; + } + } + + return false; + } + + public function registerUndefinedFunctionCallback($callable) + { + $this->functionCallbacks[] = $callable; + } + + /** + * Gets registered functions. + * + * Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback. + * + * @return Twig_FunctionInterface[] An array of Twig_FunctionInterface instances + * + * @see registerUndefinedFunctionCallback + */ + public function getFunctions() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->functions; + } + + /** + * Registers a Global. + * + * New globals can be added before compiling or rendering a template; + * but after, you can only update existing globals. + * + * @param string $name The global name + * @param mixed $value The global value + */ + public function addGlobal($name, $value) + { + if ($this->extensionInitialized || $this->runtimeInitialized) { + if (null === $this->globals) { + $this->globals = $this->initGlobals(); + } + + /* This condition must be uncommented in Twig 2.0 + if (!array_key_exists($name, $this->globals)) { + throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name)); + } + */ + } + + if ($this->extensionInitialized || $this->runtimeInitialized) { + // update the value + $this->globals[$name] = $value; + } else { + $this->staging->addGlobal($name, $value); + } + } + + /** + * Gets the registered Globals. + * + * @return array An array of globals + */ + public function getGlobals() + { + if (!$this->runtimeInitialized && !$this->extensionInitialized) { + return $this->initGlobals(); + } + + if (null === $this->globals) { + $this->globals = $this->initGlobals(); + } + + return $this->globals; + } + + /** + * Merges a context with the defined globals. + * + * @param array $context An array representing the context + * + * @return array The context merged with the globals + */ + public function mergeGlobals(array $context) + { + // we don't use array_merge as the context being generally + // bigger than globals, this code is faster. + foreach ($this->getGlobals() as $key => $value) { + if (!array_key_exists($key, $context)) { + $context[$key] = $value; + } + } + + return $context; + } + + /** + * Gets the registered unary Operators. + * + * @return array An array of unary operators + */ + public function getUnaryOperators() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->unaryOperators; + } + + /** + * Gets the registered binary Operators. + * + * @return array An array of binary operators + */ + public function getBinaryOperators() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->binaryOperators; + } + + public function computeAlternatives($name, $items) + { + $alternatives = array(); + foreach ($items as $item) { + $lev = levenshtein($name, $item); + if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { + $alternatives[$item] = $lev; + } + } + asort($alternatives); + + return array_keys($alternatives); + } + + protected function initGlobals() + { + $globals = array(); + foreach ($this->extensions as $extension) { + $extGlob = $extension->getGlobals(); + if (!is_array($extGlob)) { + throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', get_class($extension))); + } + + $globals[] = $extGlob; + } + + $globals[] = $this->staging->getGlobals(); + + return call_user_func_array('array_merge', $globals); + } + + protected function initExtensions() + { + if ($this->extensionInitialized) { + return; + } + + $this->extensionInitialized = true; + $this->parsers = new Twig_TokenParserBroker(); + $this->filters = array(); + $this->functions = array(); + $this->tests = array(); + $this->visitors = array(); + $this->unaryOperators = array(); + $this->binaryOperators = array(); + + foreach ($this->extensions as $extension) { + $this->initExtension($extension); + } + $this->initExtension($this->staging); + } + + protected function initExtension(Twig_ExtensionInterface $extension) + { + // filters + foreach ($extension->getFilters() as $name => $filter) { + if ($name instanceof Twig_SimpleFilter) { + $filter = $name; + $name = $filter->getName(); + } elseif ($filter instanceof Twig_SimpleFilter) { + $name = $filter->getName(); + } + + $this->filters[$name] = $filter; + } + + // functions + foreach ($extension->getFunctions() as $name => $function) { + if ($name instanceof Twig_SimpleFunction) { + $function = $name; + $name = $function->getName(); + } elseif ($function instanceof Twig_SimpleFunction) { + $name = $function->getName(); + } + + $this->functions[$name] = $function; + } + + // tests + foreach ($extension->getTests() as $name => $test) { + if ($name instanceof Twig_SimpleTest) { + $test = $name; + $name = $test->getName(); + } elseif ($test instanceof Twig_SimpleTest) { + $name = $test->getName(); + } + + $this->tests[$name] = $test; + } + + // token parsers + foreach ($extension->getTokenParsers() as $parser) { + if ($parser instanceof Twig_TokenParserInterface) { + $this->parsers->addTokenParser($parser); + } elseif ($parser instanceof Twig_TokenParserBrokerInterface) { + $this->parsers->addTokenParserBroker($parser); + } else { + throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances'); + } + } + + // node visitors + foreach ($extension->getNodeVisitors() as $visitor) { + $this->visitors[] = $visitor; + } + + // operators + if ($operators = $extension->getOperators()) { + if (2 !== count($operators)) { + throw new InvalidArgumentException(sprintf('"%s::getOperators()" does not return a valid operators array.', get_class($extension))); + } + + $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]); + $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]); + } + } + + protected function writeCacheFile($file, $content) + { + $dir = dirname($file); + if (!is_dir($dir)) { + if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) { + throw new RuntimeException(sprintf("Unable to create the cache directory (%s).", $dir)); + } + } elseif (!is_writable($dir)) { + throw new RuntimeException(sprintf("Unable to write in the cache directory (%s).", $dir)); + } + + $tmpFile = tempnam($dir, basename($file)); + if (false !== @file_put_contents($tmpFile, $content)) { + // rename does not work on Win32 before 5.2.6 + if (@rename($tmpFile, $file) || (@copy($tmpFile, $file) && unlink($tmpFile))) { + @chmod($file, 0666 & ~umask()); + + return; + } + } + + throw new RuntimeException(sprintf('Failed to write cache file "%s".', $file)); + } +} diff --git a/src/core/libs/Twig/Error.php b/src/core/libs/Twig/Error.php new file mode 100755 index 0000000..914b3ed --- /dev/null +++ b/src/core/libs/Twig/Error.php @@ -0,0 +1,248 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Twig base exception. + * + * This exception class and its children must only be used when + * an error occurs during the loading of a template, when a syntax error + * is detected in a template, or when rendering a template. Other + * errors must use regular PHP exception classes (like when the template + * cache directory is not writable for instance). + * + * To help debugging template issues, this class tracks the original template + * name and line where the error occurred. + * + * Whenever possible, you must set these information (original template name + * and line number) yourself by passing them to the constructor. If some or all + * these information are not available from where you throw the exception, then + * this class will guess them automatically (when the line number is set to -1 + * and/or the filename is set to null). As this is a costly operation, this + * can be disabled by passing false for both the filename and the line number + * when creating a new instance of this class. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Error extends Exception +{ + protected $lineno; + protected $filename; + protected $rawMessage; + protected $previous; + + /** + * Constructor. + * + * Set both the line number and the filename to false to + * disable automatic guessing of the original template name + * and line number. + * + * Set the line number to -1 to enable its automatic guessing. + * Set the filename to null to enable its automatic guessing. + * + * By default, automatic guessing is enabled. + * + * @param string $message The error message + * @param integer $lineno The template line where the error occurred + * @param string $filename The template file name where the error occurred + * @param Exception $previous The previous exception + */ + public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null) + { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + $this->previous = $previous; + parent::__construct(''); + } else { + parent::__construct('', 0, $previous); + } + + $this->lineno = $lineno; + $this->filename = $filename; + + if (-1 === $this->lineno || null === $this->filename) { + $this->guessTemplateInfo(); + } + + $this->rawMessage = $message; + + $this->updateRepr(); + } + + /** + * Gets the raw message. + * + * @return string The raw message + */ + public function getRawMessage() + { + return $this->rawMessage; + } + + /** + * Gets the filename where the error occurred. + * + * @return string The filename + */ + public function getTemplateFile() + { + return $this->filename; + } + + /** + * Sets the filename where the error occurred. + * + * @param string $filename The filename + */ + public function setTemplateFile($filename) + { + $this->filename = $filename; + + $this->updateRepr(); + } + + /** + * Gets the template line where the error occurred. + * + * @return integer The template line + */ + public function getTemplateLine() + { + return $this->lineno; + } + + /** + * Sets the template line where the error occurred. + * + * @param integer $lineno The template line + */ + public function setTemplateLine($lineno) + { + $this->lineno = $lineno; + + $this->updateRepr(); + } + + public function guess() + { + $this->guessTemplateInfo(); + $this->updateRepr(); + } + + /** + * For PHP < 5.3.0, provides access to the getPrevious() method. + * + * @param string $method The method name + * @param array $arguments The parameters to be passed to the method + * + * @return Exception The previous exception or null + * + * @throws BadMethodCallException + */ + public function __call($method, $arguments) + { + if ('getprevious' == strtolower($method)) { + return $this->previous; + } + + throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method)); + } + + protected function updateRepr() + { + $this->message = $this->rawMessage; + + $dot = false; + if ('.' === substr($this->message, -1)) { + $this->message = substr($this->message, 0, -1); + $dot = true; + } + + if ($this->filename) { + if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) { + $filename = sprintf('"%s"', $this->filename); + } else { + $filename = json_encode($this->filename); + } + $this->message .= sprintf(' in %s', $filename); + } + + if ($this->lineno && $this->lineno >= 0) { + $this->message .= sprintf(' at line %d', $this->lineno); + } + + if ($dot) { + $this->message .= '.'; + } + } + + protected function guessTemplateInfo() + { + $template = null; + $templateClass = null; + + if (version_compare(phpversion(), '5.3.6', '>=')) { + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT); + } else { + $backtrace = debug_backtrace(); + } + + foreach ($backtrace as $trace) { + if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) { + $currentClass = get_class($trace['object']); + $isEmbedContainer = 0 === strpos($templateClass, $currentClass); + if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) { + $template = $trace['object']; + $templateClass = get_class($trace['object']); + } + } + } + + // update template filename + if (null !== $template && null === $this->filename) { + $this->filename = $template->getTemplateName(); + } + + if (null === $template || $this->lineno > -1) { + return; + } + + $r = new ReflectionObject($template); + $file = $r->getFileName(); + + // hhvm has a bug where eval'ed files comes out as the current directory + if (is_dir($file)) { + $file = ''; + } + + $exceptions = array($e = $this); + while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) { + $exceptions[] = $e; + } + + while ($e = array_pop($exceptions)) { + $traces = $e->getTrace(); + while ($trace = array_shift($traces)) { + if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) { + continue; + } + + foreach ($template->getDebugInfo() as $codeLine => $templateLine) { + if ($codeLine <= $trace['line']) { + // update template line + $this->lineno = $templateLine; + + return; + } + } + } + } + } +} diff --git a/src/core/libs/Twig/Error/Loader.php b/src/core/libs/Twig/Error/Loader.php new file mode 100755 index 0000000..68efb57 --- /dev/null +++ b/src/core/libs/Twig/Error/Loader.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Exception thrown when an error occurs during template loading. + * + * Automatic template information guessing is always turned off as + * if a template cannot be loaded, there is nothing to guess. + * However, when a template is loaded from another one, then, we need + * to find the current context and this is automatically done by + * Twig_Template::displayWithErrorHandling(). + * + * This strategy makes Twig_Environment::resolveTemplate() much faster. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Error_Loader extends Twig_Error +{ + public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null) + { + parent::__construct($message, false, false, $previous); + } +} diff --git a/src/core/libs/Twig/Error/Runtime.php b/src/core/libs/Twig/Error/Runtime.php new file mode 100755 index 0000000..8b6cedd --- /dev/null +++ b/src/core/libs/Twig/Error/Runtime.php @@ -0,0 +1,20 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Exception thrown when an error occurs at runtime. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Error_Runtime extends Twig_Error +{ +} diff --git a/src/core/libs/Twig/Error/Syntax.php b/src/core/libs/Twig/Error/Syntax.php new file mode 100755 index 0000000..0f5c579 --- /dev/null +++ b/src/core/libs/Twig/Error/Syntax.php @@ -0,0 +1,20 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Exception thrown when a syntax error occurs during lexing or parsing of a template. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Error_Syntax extends Twig_Error +{ +} diff --git a/src/core/libs/Twig/ExistsLoaderInterface.php b/src/core/libs/Twig/ExistsLoaderInterface.php new file mode 100755 index 0000000..da05a54 --- /dev/null +++ b/src/core/libs/Twig/ExistsLoaderInterface.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Adds an exists() method for loaders. + * + * @author Florin Patan <florinpatan@gmail.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_ExistsLoaderInterface +{ + /** + * Check if we have the source code of a template, given its name. + * + * @param string $name The name of the template to check if we can load + * + * @return Boolean If the template source code is handled by this loader or not + */ + public function exists($name); +} diff --git a/src/core/libs/Twig/ExpressionParser.php b/src/core/libs/Twig/ExpressionParser.php new file mode 100755 index 0000000..25f47a1 --- /dev/null +++ b/src/core/libs/Twig/ExpressionParser.php @@ -0,0 +1,598 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Parses expressions. + * + * This parser implements a "Precedence climbing" algorithm. + * + * @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm + * @see http://en.wikipedia.org/wiki/Operator-precedence_parser + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_ExpressionParser +{ + const OPERATOR_LEFT = 1; + const OPERATOR_RIGHT = 2; + + protected $parser; + protected $unaryOperators; + protected $binaryOperators; + + public function __construct(Twig_Parser $parser, array $unaryOperators, array $binaryOperators) + { + $this->parser = $parser; + $this->unaryOperators = $unaryOperators; + $this->binaryOperators = $binaryOperators; + } + + public function parseExpression($precedence = 0) + { + $expr = $this->getPrimary(); + $token = $this->parser->getCurrentToken(); + while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) { + $op = $this->binaryOperators[$token->getValue()]; + $this->parser->getStream()->next(); + + if (isset($op['callable'])) { + $expr = call_user_func($op['callable'], $this->parser, $expr); + } else { + $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']); + $class = $op['class']; + $expr = new $class($expr, $expr1, $token->getLine()); + } + + $token = $this->parser->getCurrentToken(); + } + + if (0 === $precedence) { + return $this->parseConditionalExpression($expr); + } + + return $expr; + } + + protected function getPrimary() + { + $token = $this->parser->getCurrentToken(); + + if ($this->isUnary($token)) { + $operator = $this->unaryOperators[$token->getValue()]; + $this->parser->getStream()->next(); + $expr = $this->parseExpression($operator['precedence']); + $class = $operator['class']; + + return $this->parsePostfixExpression(new $class($expr, $token->getLine())); + } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '(')) { + $this->parser->getStream()->next(); + $expr = $this->parseExpression(); + $this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed'); + + return $this->parsePostfixExpression($expr); + } + + return $this->parsePrimaryExpression(); + } + + protected function parseConditionalExpression($expr) + { + while ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, '?')) { + if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { + $expr2 = $this->parseExpression(); + if ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { + $expr3 = $this->parseExpression(); + } else { + $expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine()); + } + } else { + $expr2 = $expr; + $expr3 = $this->parseExpression(); + } + + $expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine()); + } + + return $expr; + } + + protected function isUnary(Twig_Token $token) + { + return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]); + } + + protected function isBinary(Twig_Token $token) + { + return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]); + } + + public function parsePrimaryExpression() + { + $token = $this->parser->getCurrentToken(); + switch ($token->getType()) { + case Twig_Token::NAME_TYPE: + $this->parser->getStream()->next(); + switch ($token->getValue()) { + case 'true': + case 'TRUE': + $node = new Twig_Node_Expression_Constant(true, $token->getLine()); + break; + + case 'false': + case 'FALSE': + $node = new Twig_Node_Expression_Constant(false, $token->getLine()); + break; + + case 'none': + case 'NONE': + case 'null': + case 'NULL': + $node = new Twig_Node_Expression_Constant(null, $token->getLine()); + break; + + default: + if ('(' === $this->parser->getCurrentToken()->getValue()) { + $node = $this->getFunctionNode($token->getValue(), $token->getLine()); + } else { + $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine()); + } + } + break; + + case Twig_Token::NUMBER_TYPE: + $this->parser->getStream()->next(); + $node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); + break; + + case Twig_Token::STRING_TYPE: + case Twig_Token::INTERPOLATION_START_TYPE: + $node = $this->parseStringExpression(); + break; + + case Twig_Token::OPERATOR_TYPE: + if (preg_match(Twig_Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) { + // in this context, string operators are variable names + $this->parser->getStream()->next(); + $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine()); + break; + } + + default: + if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) { + $node = $this->parseArrayExpression(); + } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) { + $node = $this->parseHashExpression(); + } else { + throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getFilename()); + } + } + + return $this->parsePostfixExpression($node); + } + + public function parseStringExpression() + { + $stream = $this->parser->getStream(); + + $nodes = array(); + // a string cannot be followed by another string in a single expression + $nextCanBeString = true; + while (true) { + if ($nextCanBeString && $token = $stream->nextIf(Twig_Token::STRING_TYPE)) { + $nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); + $nextCanBeString = false; + } elseif ($stream->nextIf(Twig_Token::INTERPOLATION_START_TYPE)) { + $nodes[] = $this->parseExpression(); + $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); + $nextCanBeString = true; + } else { + break; + } + } + + $expr = array_shift($nodes); + foreach ($nodes as $node) { + $expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getLine()); + } + + return $expr; + } + + public function parseArrayExpression() + { + $stream = $this->parser->getStream(); + $stream->expect(Twig_Token::PUNCTUATION_TYPE, '[', 'An array element was expected'); + + $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); + $first = true; + while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { + if (!$first) { + $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma'); + + // trailing ,? + if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { + break; + } + } + $first = false; + + $node->addElement($this->parseExpression()); + } + $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed'); + + return $node; + } + + public function parseHashExpression() + { + $stream = $this->parser->getStream(); + $stream->expect(Twig_Token::PUNCTUATION_TYPE, '{', 'A hash element was expected'); + + $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); + $first = true; + while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) { + if (!$first) { + $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma'); + + // trailing ,? + if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) { + break; + } + } + $first = false; + + // a hash key can be: + // + // * a number -- 12 + // * a string -- 'a' + // * a name, which is equivalent to a string -- a + // * an expression, which must be enclosed in parentheses -- (1 + 2) + if (($token = $stream->nextIf(Twig_Token::STRING_TYPE)) || ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) || $token = $stream->nextIf(Twig_Token::NUMBER_TYPE)) { + $key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); + } elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { + $key = $this->parseExpression(); + } else { + $current = $stream->getCurrent(); + + throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $this->parser->getFilename()); + } + + $stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); + $value = $this->parseExpression(); + + $node->addElement($value, $key); + } + $stream->expect(Twig_Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed'); + + return $node; + } + + public function parsePostfixExpression($node) + { + while (true) { + $token = $this->parser->getCurrentToken(); + if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) { + if ('.' == $token->getValue() || '[' == $token->getValue()) { + $node = $this->parseSubscriptExpression($node); + } elseif ('|' == $token->getValue()) { + $node = $this->parseFilterExpression($node); + } else { + break; + } + } else { + break; + } + } + + return $node; + } + + public function getFunctionNode($name, $line) + { + switch ($name) { + case 'parent': + $args = $this->parseArguments(); + if (!count($this->parser->getBlockStack())) { + throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename()); + } + + if (!$this->parser->getParent() && !$this->parser->hasTraits()) { + throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line, $this->parser->getFilename()); + } + + return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line); + case 'block': + return new Twig_Node_Expression_BlockReference($this->parseArguments()->getNode(0), false, $line); + case 'attribute': + $args = $this->parseArguments(); + if (count($args) < 2) { + throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line, $this->parser->getFilename()); + } + + return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_Template::ANY_CALL, $line); + default: + if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) { + $arguments = new Twig_Node_Expression_Array(array(), $line); + foreach ($this->parseArguments() as $n) { + $arguments->addElement($n); + } + + $node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line); + $node->setAttribute('safe', true); + + return $node; + } + + $args = $this->parseArguments(true); + $class = $this->getFunctionNodeClass($name, $line); + + return new $class($name, $args, $line); + } + } + + public function parseSubscriptExpression($node) + { + $stream = $this->parser->getStream(); + $token = $stream->next(); + $lineno = $token->getLine(); + $arguments = new Twig_Node_Expression_Array(array(), $lineno); + $type = Twig_Template::ANY_CALL; + if ($token->getValue() == '.') { + $token = $stream->next(); + if ( + $token->getType() == Twig_Token::NAME_TYPE + || + $token->getType() == Twig_Token::NUMBER_TYPE + || + ($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue())) + ) { + $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); + + if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { + $type = Twig_TemplateInterface::METHOD_CALL; + foreach ($this->parseArguments() as $n) { + $arguments->addElement($n); + } + } + } else { + throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename()); + } + + if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { + if (!$arg instanceof Twig_Node_Expression_Constant) { + throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename()); + } + + $node = new Twig_Node_Expression_MethodCall($node, 'get'.$arg->getAttribute('value'), $arguments, $lineno); + $node->setAttribute('safe', true); + + return $node; + } + } else { + $type = Twig_Template::ARRAY_CALL; + + // slice? + $slice = false; + if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) { + $slice = true; + $arg = new Twig_Node_Expression_Constant(0, $token->getLine()); + } else { + $arg = $this->parseExpression(); + } + + if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { + $slice = true; + } + + if ($slice) { + if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { + $length = new Twig_Node_Expression_Constant(null, $token->getLine()); + } else { + $length = $this->parseExpression(); + } + + $class = $this->getFilterNodeClass('slice', $token->getLine()); + $arguments = new Twig_Node(array($arg, $length)); + $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine()); + + $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); + + return $filter; + } + + $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); + } + + return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno); + } + + public function parseFilterExpression($node) + { + $this->parser->getStream()->next(); + + return $this->parseFilterExpressionRaw($node); + } + + public function parseFilterExpressionRaw($node, $tag = null) + { + while (true) { + $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE); + + $name = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); + if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) { + $arguments = new Twig_Node(); + } else { + $arguments = $this->parseArguments(true); + } + + $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine()); + + $node = new $class($node, $name, $arguments, $token->getLine(), $tag); + + if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) { + break; + } + + $this->parser->getStream()->next(); + } + + return $node; + } + + /** + * Parses arguments. + * + * @param Boolean $namedArguments Whether to allow named arguments or not + * @param Boolean $definition Whether we are parsing arguments for a function definition + */ + public function parseArguments($namedArguments = false, $definition = false) + { + $args = array(); + $stream = $this->parser->getStream(); + + $stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); + while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) { + if (!empty($args)) { + $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); + } + + if ($definition) { + $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'An argument must be a name'); + $value = new Twig_Node_Expression_Name($token->getValue(), $this->parser->getCurrentToken()->getLine()); + } else { + $value = $this->parseExpression(); + } + + $name = null; + if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) { + if (!$value instanceof Twig_Node_Expression_Name) { + throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given', get_class($value)), $token->getLine(), $this->parser->getFilename()); + } + $name = $value->getAttribute('name'); + + if ($definition) { + $value = $this->parsePrimaryExpression(); + + if (!$this->checkConstantExpression($value)) { + throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $this->parser->getFilename()); + } + } else { + $value = $this->parseExpression(); + } + } + + if ($definition) { + if (null === $name) { + $name = $value->getAttribute('name'); + $value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine()); + } + $args[$name] = $value; + } else { + if (null === $name) { + $args[] = $value; + } else { + $args[$name] = $value; + } + } + } + $stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); + + return new Twig_Node($args); + } + + public function parseAssignmentExpression() + { + $targets = array(); + while (true) { + $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to'); + if (in_array($token->getValue(), array('true', 'false', 'none'))) { + throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine(), $this->parser->getFilename()); + } + $targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine()); + + if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { + break; + } + } + + return new Twig_Node($targets); + } + + public function parseMultitargetExpression() + { + $targets = array(); + while (true) { + $targets[] = $this->parseExpression(); + if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { + break; + } + } + + return new Twig_Node($targets); + } + + protected function getFunctionNodeClass($name, $line) + { + $env = $this->parser->getEnvironment(); + + if (false === $function = $env->getFunction($name)) { + $message = sprintf('The function "%s" does not exist', $name); + if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFunctions()))) { + $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); + } + + throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename()); + } + + if ($function instanceof Twig_SimpleFunction) { + return $function->getNodeClass(); + } + + return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function'; + } + + protected function getFilterNodeClass($name, $line) + { + $env = $this->parser->getEnvironment(); + + if (false === $filter = $env->getFilter($name)) { + $message = sprintf('The filter "%s" does not exist', $name); + if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFilters()))) { + $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); + } + + throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename()); + } + + if ($filter instanceof Twig_SimpleFilter) { + return $filter->getNodeClass(); + } + + return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter'; + } + + // checks that the node only contains "constant" elements + protected function checkConstantExpression(Twig_NodeInterface $node) + { + if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array)) { + return false; + } + + foreach ($node as $n) { + if (!$this->checkConstantExpression($n)) { + return false; + } + } + + return true; + } +} diff --git a/src/core/libs/Twig/Extension.php b/src/core/libs/Twig/Extension.php new file mode 100755 index 0000000..5c8ad5c --- /dev/null +++ b/src/core/libs/Twig/Extension.php @@ -0,0 +1,93 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +abstract class Twig_Extension implements Twig_ExtensionInterface +{ + /** + * Initializes the runtime environment. + * + * This is where you can load some file that contains filter functions for instance. + * + * @param Twig_Environment $environment The current Twig_Environment instance + */ + public function initRuntime(Twig_Environment $environment) + { + } + + /** + * Returns the token parser instances to add to the existing list. + * + * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances + */ + public function getTokenParsers() + { + return array(); + } + + /** + * Returns the node visitor instances to add to the existing list. + * + * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances + */ + public function getNodeVisitors() + { + return array(); + } + + /** + * Returns a list of filters to add to the existing list. + * + * @return array An array of filters + */ + public function getFilters() + { + return array(); + } + + /** + * Returns a list of tests to add to the existing list. + * + * @return array An array of tests + */ + public function getTests() + { + return array(); + } + + /** + * Returns a list of functions to add to the existing list. + * + * @return array An array of functions + */ + public function getFunctions() + { + return array(); + } + + /** + * Returns a list of operators to add to the existing list. + * + * @return array An array of operators + */ + public function getOperators() + { + return array(); + } + + /** + * Returns a list of global variables to add to the existing list. + * + * @return array An array of global variables + */ + public function getGlobals() + { + return array(); + } +} diff --git a/src/core/libs/Twig/Extension/Core.php b/src/core/libs/Twig/Extension/Core.php new file mode 100755 index 0000000..922b5ea --- /dev/null +++ b/src/core/libs/Twig/Extension/Core.php @@ -0,0 +1,1463 @@ +<?php + +if (!defined('ENT_SUBSTITUTE')) { + // use 0 as hhvm does not support several flags yet + define('ENT_SUBSTITUTE', 0); +} + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Extension_Core extends Twig_Extension +{ + protected $dateFormats = array('F j, Y H:i', '%d days'); + protected $numberFormat = array(0, '.', ','); + protected $timezone = null; + protected $escapers = array(); + + /** + * Defines a new escaper to be used via the escape filter. + * + * @param string $strategy The strategy name that should be used as a strategy in the escape call + * @param callable $callable A valid PHP callable + */ + public function setEscaper($strategy, $callable) + { + $this->escapers[$strategy] = $callable; + } + + /** + * Gets all defined escapers. + * + * @return array An array of escapers + */ + public function getEscapers() + { + return $this->escapers; + } + + /** + * Sets the default format to be used by the date filter. + * + * @param string $format The default date format string + * @param string $dateIntervalFormat The default date interval format string + */ + public function setDateFormat($format = null, $dateIntervalFormat = null) + { + if (null !== $format) { + $this->dateFormats[0] = $format; + } + + if (null !== $dateIntervalFormat) { + $this->dateFormats[1] = $dateIntervalFormat; + } + } + + /** + * Gets the default format to be used by the date filter. + * + * @return array The default date format string and the default date interval format string + */ + public function getDateFormat() + { + return $this->dateFormats; + } + + /** + * Sets the default timezone to be used by the date filter. + * + * @param DateTimeZone|string $timezone The default timezone string or a DateTimeZone object + */ + public function setTimezone($timezone) + { + $this->timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone); + } + + /** + * Gets the default timezone to be used by the date filter. + * + * @return DateTimeZone The default timezone currently in use + */ + public function getTimezone() + { + if (null === $this->timezone) { + $this->timezone = new DateTimeZone(date_default_timezone_get()); + } + + return $this->timezone; + } + + /** + * Sets the default format to be used by the number_format filter. + * + * @param integer $decimal The number of decimal places to use. + * @param string $decimalPoint The character(s) to use for the decimal point. + * @param string $thousandSep The character(s) to use for the thousands separator. + */ + public function setNumberFormat($decimal, $decimalPoint, $thousandSep) + { + $this->numberFormat = array($decimal, $decimalPoint, $thousandSep); + } + + /** + * Get the default format used by the number_format filter. + * + * @return array The arguments for number_format() + */ + public function getNumberFormat() + { + return $this->numberFormat; + } + + /** + * Returns the token parser instance to add to the existing list. + * + * @return Twig_TokenParser[] An array of Twig_TokenParser instances + */ + public function getTokenParsers() + { + return array( + new Twig_TokenParser_For(), + new Twig_TokenParser_If(), + new Twig_TokenParser_Extends(), + new Twig_TokenParser_Include(), + new Twig_TokenParser_Block(), + new Twig_TokenParser_Use(), + new Twig_TokenParser_Filter(), + new Twig_TokenParser_Macro(), + new Twig_TokenParser_Import(), + new Twig_TokenParser_From(), + new Twig_TokenParser_Set(), + new Twig_TokenParser_Spaceless(), + new Twig_TokenParser_Flush(), + new Twig_TokenParser_Do(), + new Twig_TokenParser_Embed(), + ); + } + + /** + * Returns a list of filters to add to the existing list. + * + * @return array An array of filters + */ + public function getFilters() + { + $filters = array( + // formatting filters + new Twig_SimpleFilter('date', 'twig_date_format_filter', array('needs_environment' => true)), + new Twig_SimpleFilter('date_modify', 'twig_date_modify_filter', array('needs_environment' => true)), + new Twig_SimpleFilter('format', 'sprintf'), + new Twig_SimpleFilter('replace', 'strtr'), + new Twig_SimpleFilter('number_format', 'twig_number_format_filter', array('needs_environment' => true)), + new Twig_SimpleFilter('abs', 'abs'), + new Twig_SimpleFilter('round', 'twig_round'), + + // encoding + new Twig_SimpleFilter('url_encode', 'twig_urlencode_filter'), + new Twig_SimpleFilter('json_encode', 'twig_jsonencode_filter'), + new Twig_SimpleFilter('convert_encoding', 'twig_convert_encoding'), + + // string filters + new Twig_SimpleFilter('title', 'twig_title_string_filter', array('needs_environment' => true)), + new Twig_SimpleFilter('capitalize', 'twig_capitalize_string_filter', array('needs_environment' => true)), + new Twig_SimpleFilter('upper', 'strtoupper'), + new Twig_SimpleFilter('lower', 'strtolower'), + new Twig_SimpleFilter('striptags', 'strip_tags'), + new Twig_SimpleFilter('trim', 'trim'), + new Twig_SimpleFilter('nl2br', 'nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))), + + // array helpers + new Twig_SimpleFilter('join', 'twig_join_filter'), + new Twig_SimpleFilter('split', 'twig_split_filter'), + new Twig_SimpleFilter('sort', 'twig_sort_filter'), + new Twig_SimpleFilter('merge', 'twig_array_merge'), + new Twig_SimpleFilter('batch', 'twig_array_batch'), + + // string/array filters + new Twig_SimpleFilter('reverse', 'twig_reverse_filter', array('needs_environment' => true)), + new Twig_SimpleFilter('length', 'twig_length_filter', array('needs_environment' => true)), + new Twig_SimpleFilter('slice', 'twig_slice', array('needs_environment' => true)), + new Twig_SimpleFilter('first', 'twig_first', array('needs_environment' => true)), + new Twig_SimpleFilter('last', 'twig_last', array('needs_environment' => true)), + + // iteration and runtime + new Twig_SimpleFilter('default', '_twig_default_filter', array('node_class' => 'Twig_Node_Expression_Filter_Default')), + new Twig_SimpleFilter('keys', 'twig_get_array_keys_filter'), + + // escaping + new Twig_SimpleFilter('escape', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')), + new Twig_SimpleFilter('e', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')), + ); + + if (function_exists('mb_get_info')) { + $filters[] = new Twig_SimpleFilter('upper', 'twig_upper_filter', array('needs_environment' => true)); + $filters[] = new Twig_SimpleFilter('lower', 'twig_lower_filter', array('needs_environment' => true)); + } + + return $filters; + } + + /** + * Returns a list of global functions to add to the existing list. + * + * @return array An array of global functions + */ + public function getFunctions() + { + return array( + new Twig_SimpleFunction('max', 'max'), + new Twig_SimpleFunction('min', 'min'), + new Twig_SimpleFunction('range', 'range'), + new Twig_SimpleFunction('constant', 'twig_constant'), + new Twig_SimpleFunction('cycle', 'twig_cycle'), + new Twig_SimpleFunction('random', 'twig_random', array('needs_environment' => true)), + new Twig_SimpleFunction('date', 'twig_date_converter', array('needs_environment' => true)), + new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true, 'is_safe' => array('all'))), + new Twig_SimpleFunction('source', 'twig_source', array('needs_environment' => true, 'is_safe' => array('all'))), + ); + } + + /** + * Returns a list of tests to add to the existing list. + * + * @return array An array of tests + */ + public function getTests() + { + return array( + new Twig_SimpleTest('even', null, array('node_class' => 'Twig_Node_Expression_Test_Even')), + new Twig_SimpleTest('odd', null, array('node_class' => 'Twig_Node_Expression_Test_Odd')), + new Twig_SimpleTest('defined', null, array('node_class' => 'Twig_Node_Expression_Test_Defined')), + new Twig_SimpleTest('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')), + new Twig_SimpleTest('same as', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')), + new Twig_SimpleTest('none', null, array('node_class' => 'Twig_Node_Expression_Test_Null')), + new Twig_SimpleTest('null', null, array('node_class' => 'Twig_Node_Expression_Test_Null')), + new Twig_SimpleTest('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')), + new Twig_SimpleTest('divisible by', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')), + new Twig_SimpleTest('constant', null, array('node_class' => 'Twig_Node_Expression_Test_Constant')), + new Twig_SimpleTest('empty', 'twig_test_empty'), + new Twig_SimpleTest('iterable', 'twig_test_iterable'), + ); + } + + /** + * Returns a list of operators to add to the existing list. + * + * @return array An array of operators + */ + public function getOperators() + { + return array( + array( + 'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'), + '-' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Neg'), + '+' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'), + ), + array( + 'or' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'and' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'b-or' => array('precedence' => 16, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'b-xor' => array('precedence' => 17, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'b-and' => array('precedence' => 18, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '==' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '!=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '<' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '>=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '<=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'not in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'matches' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Matches', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'starts with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_StartsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'ends with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_EndsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '..' => array('precedence' => 25, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '+' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '-' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '~' => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '*' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '/' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '//' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '%' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'is' => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + 'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + '**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT), + ), + ); + } + + public function parseNotTestExpression(Twig_Parser $parser, Twig_NodeInterface $node) + { + return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($parser, $node), $parser->getCurrentToken()->getLine()); + } + + public function parseTestExpression(Twig_Parser $parser, Twig_NodeInterface $node) + { + $stream = $parser->getStream(); + $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); + $class = $this->getTestNodeClass($parser, $name, $node->getLine()); + $arguments = null; + if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { + $arguments = $parser->getExpressionParser()->parseArguments(true); + } + + return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine()); + } + + protected function getTestNodeClass(Twig_Parser $parser, $name, $line) + { + $env = $parser->getEnvironment(); + $testMap = $env->getTests(); + $testName = null; + if (isset($testMap[$name])) { + $testName = $name; + } elseif ($parser->getStream()->test(Twig_Token::NAME_TYPE)) { + // try 2-words tests + $name = $name.' '.$parser->getCurrentToken()->getValue(); + + if (isset($testMap[$name])) { + $parser->getStream()->next(); + + $testName = $name; + } + } + + if (null === $testName) { + $message = sprintf('The test "%s" does not exist', $name); + if ($alternatives = $env->computeAlternatives($name, array_keys($env->getTests()))) { + $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); + } + + throw new Twig_Error_Syntax($message, $line, $parser->getFilename()); + } + + if ($testMap[$name] instanceof Twig_SimpleTest) { + return $testMap[$name]->getNodeClass(); + } + + return $testMap[$name] instanceof Twig_Test_Node ? $testMap[$name]->getClass() : 'Twig_Node_Expression_Test'; + } + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return 'core'; + } +} + +/** + * Cycles over a value. + * + * @param ArrayAccess|array $values An array or an ArrayAccess instance + * @param integer $position The cycle position + * + * @return string The next value in the cycle + */ +function twig_cycle($values, $position) +{ + if (!is_array($values) && !$values instanceof ArrayAccess) { + return $values; + } + + return $values[$position % count($values)]; +} + +/** + * Returns a random value depending on the supplied parameter type: + * - a random item from a Traversable or array + * - a random character from a string + * - a random integer between 0 and the integer parameter + * + * @param Twig_Environment $env A Twig_Environment instance + * @param Traversable|array|integer|string $values The values to pick a random item from + * + * @throws Twig_Error_Runtime When $values is an empty array (does not apply to an empty string which is returned as is). + * + * @return mixed A random value from the given sequence + */ +function twig_random(Twig_Environment $env, $values = null) +{ + if (null === $values) { + return mt_rand(); + } + + if (is_int($values) || is_float($values)) { + return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values); + } + + if ($values instanceof Traversable) { + $values = iterator_to_array($values); + } elseif (is_string($values)) { + if ('' === $values) { + return ''; + } + if (null !== $charset = $env->getCharset()) { + if ('UTF-8' != $charset) { + $values = twig_convert_encoding($values, 'UTF-8', $charset); + } + + // unicode version of str_split() + // split at all positions, but not after the start and not before the end + $values = preg_split('/(?<!^)(?!$)/u', $values); + + if ('UTF-8' != $charset) { + foreach ($values as $i => $value) { + $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8'); + } + } + } else { + return $values[mt_rand(0, strlen($values) - 1)]; + } + } + + if (!is_array($values)) { + return $values; + } + + if (0 === count($values)) { + throw new Twig_Error_Runtime('The random function cannot pick from an empty array.'); + } + + return $values[array_rand($values, 1)]; +} + +/** + * Converts a date to the given format. + * + * <pre> + * {{ post.published_at|date("m/d/Y") }} + * </pre> + * + * @param Twig_Environment $env A Twig_Environment instance + * @param DateTime|DateInterval|string $date A date + * @param string $format A format + * @param DateTimeZone|string $timezone A timezone + * + * @return string The formatted date + */ +function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null) +{ + if (null === $format) { + $formats = $env->getExtension('core')->getDateFormat(); + $format = $date instanceof DateInterval ? $formats[1] : $formats[0]; + } + + if ($date instanceof DateInterval) { + return $date->format($format); + } + + return twig_date_converter($env, $date, $timezone)->format($format); +} + +/** + * Returns a new date object modified + * + * <pre> + * {{ post.published_at|date_modify("-1day")|date("m/d/Y") }} + * </pre> + * + * @param Twig_Environment $env A Twig_Environment instance + * @param DateTime|string $date A date + * @param string $modifier A modifier string + * + * @return DateTime A new date object + */ +function twig_date_modify_filter(Twig_Environment $env, $date, $modifier) +{ + $date = twig_date_converter($env, $date, false); + $date->modify($modifier); + + return $date; +} + +/** + * Converts an input to a DateTime instance. + * + * <pre> + * {% if date(user.created_at) < date('+2days') %} + * {# do something #} + * {% endif %} + * </pre> + * + * @param Twig_Environment $env A Twig_Environment instance + * @param DateTime|string $date A date + * @param DateTimeZone|string $timezone A timezone + * + * @return DateTime A DateTime instance + */ +function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null) +{ + // determine the timezone + if (!$timezone) { + $defaultTimezone = $env->getExtension('core')->getTimezone(); + } elseif (!$timezone instanceof DateTimeZone) { + $defaultTimezone = new DateTimeZone($timezone); + } else { + $defaultTimezone = $timezone; + } + + // immutable dates + if ($date instanceof DateTimeImmutable) { + return false !== $timezone ? $date->setTimezone($defaultTimezone) : $date; + } + + if ($date instanceof DateTime || $date instanceof DateTimeInterface) { + $date = clone $date; + if (false !== $timezone) { + $date->setTimezone($defaultTimezone); + } + + return $date; + } + + $asString = (string) $date; + if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) { + $date = '@'.$date; + } + + $date = new DateTime($date, $defaultTimezone); + if (false !== $timezone) { + $date->setTimezone($defaultTimezone); + } + + return $date; +} + +/** + * Rounds a number. + * + * @param integer|float $value The value to round + * @param integer|float $precision The rounding precision + * @param string $method The method to use for rounding + * + * @return integer|float The rounded number + */ +function twig_round($value, $precision = 0, $method = 'common') +{ + if ('common' == $method) { + return round($value, $precision); + } + + if ('ceil' != $method && 'floor' != $method) { + throw new Twig_Error_Runtime('The round filter only supports the "common", "ceil", and "floor" methods.'); + } + + return $method($value * pow(10, $precision)) / pow(10, $precision); +} + +/** + * Number format filter. + * + * All of the formatting options can be left null, in that case the defaults will + * be used. Supplying any of the parameters will override the defaults set in the + * environment object. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param mixed $number A float/int/string of the number to format + * @param integer $decimal The number of decimal points to display. + * @param string $decimalPoint The character(s) to use for the decimal point. + * @param string $thousandSep The character(s) to use for the thousands separator. + * + * @return string The formatted number + */ +function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null) +{ + $defaults = $env->getExtension('core')->getNumberFormat(); + if (null === $decimal) { + $decimal = $defaults[0]; + } + + if (null === $decimalPoint) { + $decimalPoint = $defaults[1]; + } + + if (null === $thousandSep) { + $thousandSep = $defaults[2]; + } + + return number_format((float) $number, $decimal, $decimalPoint, $thousandSep); +} + +/** + * URL encodes a string as a path segment or an array as a query string. + * + * @param string|array $url A URL or an array of query parameters + * @param Boolean $raw true to use rawurlencode() instead of urlencode + * + * @return string The URL encoded value + */ +function twig_urlencode_filter($url, $raw = false) +{ + if (is_array($url)) { + return http_build_query($url, '', '&'); + } + + if ($raw) { + return rawurlencode($url); + } + + return urlencode($url); +} + +if (version_compare(PHP_VERSION, '5.3.0', '<')) { + /** + * JSON encodes a variable. + * + * @param mixed $value The value to encode. + * @param integer $options Not used on PHP 5.2.x + * + * @return mixed The JSON encoded value + */ + function twig_jsonencode_filter($value, $options = 0) + { + if ($value instanceof Twig_Markup) { + $value = (string) $value; + } elseif (is_array($value)) { + array_walk_recursive($value, '_twig_markup2string'); + } + + return json_encode($value); + } +} else { + /** + * JSON encodes a variable. + * + * @param mixed $value The value to encode. + * @param integer $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT + * + * @return mixed The JSON encoded value + */ + function twig_jsonencode_filter($value, $options = 0) + { + if ($value instanceof Twig_Markup) { + $value = (string) $value; + } elseif (is_array($value)) { + array_walk_recursive($value, '_twig_markup2string'); + } + + return json_encode($value, $options); + } +} + +function _twig_markup2string(&$value) +{ + if ($value instanceof Twig_Markup) { + $value = (string) $value; + } +} + +/** + * Merges an array with another one. + * + * <pre> + * {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %} + * + * {% set items = items|merge({ 'peugeot': 'car' }) %} + * + * {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #} + * </pre> + * + * @param array $arr1 An array + * @param array $arr2 An array + * + * @return array The merged array + */ +function twig_array_merge($arr1, $arr2) +{ + if (!is_array($arr1) || !is_array($arr2)) { + throw new Twig_Error_Runtime('The merge filter only works with arrays or hashes.'); + } + + return array_merge($arr1, $arr2); +} + +/** + * Slices a variable. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param mixed $item A variable + * @param integer $start Start of the slice + * @param integer $length Size of the slice + * @param Boolean $preserveKeys Whether to preserve key or not (when the input is an array) + * + * @return mixed The sliced variable + */ +function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false) +{ + if ($item instanceof Traversable) { + $item = iterator_to_array($item, false); + } + + if (is_array($item)) { + return array_slice($item, $start, $length, $preserveKeys); + } + + $item = (string) $item; + + if (function_exists('mb_get_info') && null !== $charset = $env->getCharset()) { + return mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset); + } + + return null === $length ? substr($item, $start) : substr($item, $start, $length); +} + +/** + * Returns the first element of the item. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param mixed $item A variable + * + * @return mixed The first element of the item + */ +function twig_first(Twig_Environment $env, $item) +{ + $elements = twig_slice($env, $item, 0, 1, false); + + return is_string($elements) ? $elements : current($elements); +} + +/** + * Returns the last element of the item. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param mixed $item A variable + * + * @return mixed The last element of the item + */ +function twig_last(Twig_Environment $env, $item) +{ + $elements = twig_slice($env, $item, -1, 1, false); + + return is_string($elements) ? $elements : current($elements); +} + +/** + * Joins the values to a string. + * + * The separator between elements is an empty string per default, you can define it with the optional parameter. + * + * <pre> + * {{ [1, 2, 3]|join('|') }} + * {# returns 1|2|3 #} + * + * {{ [1, 2, 3]|join }} + * {# returns 123 #} + * </pre> + * + * @param array $value An array + * @param string $glue The separator + * + * @return string The concatenated string + */ +function twig_join_filter($value, $glue = '') +{ + if ($value instanceof Traversable) { + $value = iterator_to_array($value, false); + } + + return implode($glue, (array) $value); +} + +/** + * Splits the string into an array. + * + * <pre> + * {{ "one,two,three"|split(',') }} + * {# returns [one, two, three] #} + * + * {{ "one,two,three,four,five"|split(',', 3) }} + * {# returns [one, two, "three,four,five"] #} + * + * {{ "123"|split('') }} + * {# returns [1, 2, 3] #} + * + * {{ "aabbcc"|split('', 2) }} + * {# returns [aa, bb, cc] #} + * </pre> + * + * @param string $value A string + * @param string $delimiter The delimiter + * @param integer $limit The limit + * + * @return array The split string as an array + */ +function twig_split_filter($value, $delimiter, $limit = null) +{ + if (empty($delimiter)) { + return str_split($value, null === $limit ? 1 : $limit); + } + + return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit); +} + +// The '_default' filter is used internally to avoid using the ternary operator +// which costs a lot for big contexts (before PHP 5.4). So, on average, +// a function call is cheaper. +function _twig_default_filter($value, $default = '') +{ + if (twig_test_empty($value)) { + return $default; + } + + return $value; +} + +/** + * Returns the keys for the given array. + * + * It is useful when you want to iterate over the keys of an array: + * + * <pre> + * {% for key in array|keys %} + * {# ... #} + * {% endfor %} + * </pre> + * + * @param array $array An array + * + * @return array The keys + */ +function twig_get_array_keys_filter($array) +{ + if (is_object($array) && $array instanceof Traversable) { + return array_keys(iterator_to_array($array)); + } + + if (!is_array($array)) { + return array(); + } + + return array_keys($array); +} + +/** + * Reverses a variable. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param array|Traversable|string $item An array, a Traversable instance, or a string + * @param Boolean $preserveKeys Whether to preserve key or not + * + * @return mixed The reversed input + */ +function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false) +{ + if (is_object($item) && $item instanceof Traversable) { + return array_reverse(iterator_to_array($item), $preserveKeys); + } + + if (is_array($item)) { + return array_reverse($item, $preserveKeys); + } + + if (null !== $charset = $env->getCharset()) { + $string = (string) $item; + + if ('UTF-8' != $charset) { + $item = twig_convert_encoding($string, 'UTF-8', $charset); + } + + preg_match_all('/./us', $item, $matches); + + $string = implode('', array_reverse($matches[0])); + + if ('UTF-8' != $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + } + + return strrev((string) $item); +} + +/** + * Sorts an array. + * + * @param array $array An array + */ +function twig_sort_filter($array) +{ + asort($array); + + return $array; +} + +/* used internally */ +function twig_in_filter($value, $compare) +{ + if (is_array($compare)) { + return in_array($value, $compare, is_object($value)); + } elseif (is_string($compare)) { + if (!strlen($value)) { + return empty($compare); + } + + return false !== strpos($compare, (string) $value); + } elseif ($compare instanceof Traversable) { + return in_array($value, iterator_to_array($compare, false), is_object($value)); + } + + return false; +} + +/** + * Escapes a string. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param string $string The value to be escaped + * @param string $strategy The escaping strategy + * @param string $charset The charset + * @param Boolean $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false) + */ +function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false) +{ + if ($autoescape && $string instanceof Twig_Markup) { + return $string; + } + + if (!is_string($string)) { + if (is_object($string) && method_exists($string, '__toString')) { + $string = (string) $string; + } else { + return $string; + } + } + + if (null === $charset) { + $charset = $env->getCharset(); + } + + switch ($strategy) { + case 'html': + // see http://php.net/htmlspecialchars + + // Using a static variable to avoid initializing the array + // each time the function is called. Moving the declaration on the + // top of the function slow downs other escaping strategies. + static $htmlspecialcharsCharsets; + + if (null === $htmlspecialcharsCharsets) { + if ('hiphop' === substr(PHP_VERSION, -6)) { + $htmlspecialcharsCharsets = array('utf-8' => true, 'UTF-8' => true); + } else { + $htmlspecialcharsCharsets = array( + 'ISO-8859-1' => true, 'ISO8859-1' => true, + 'ISO-8859-15' => true, 'ISO8859-15' => true, + 'utf-8' => true, 'UTF-8' => true, + 'CP866' => true, 'IBM866' => true, '866' => true, + 'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true, + '1251' => true, + 'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true, + 'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true, + 'BIG5' => true, '950' => true, + 'GB2312' => true, '936' => true, + 'BIG5-HKSCS' => true, + 'SHIFT_JIS' => true, 'SJIS' => true, '932' => true, + 'EUC-JP' => true, 'EUCJP' => true, + 'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true, + ); + } + } + + if (isset($htmlspecialcharsCharsets[$charset])) { + return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset); + } + + if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) { + // cache the lowercase variant for future iterations + $htmlspecialcharsCharsets[$charset] = true; + + return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset); + } + + $string = twig_convert_encoding($string, 'UTF-8', $charset); + $string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); + + return twig_convert_encoding($string, $charset, 'UTF-8'); + + case 'js': + // escape all non-alphanumeric characters + // into their \xHH or \uHHHH representations + if ('UTF-8' != $charset) { + $string = twig_convert_encoding($string, 'UTF-8', $charset); + } + + if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) { + throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.'); + } + + $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string); + + if ('UTF-8' != $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + + case 'css': + if ('UTF-8' != $charset) { + $string = twig_convert_encoding($string, 'UTF-8', $charset); + } + + if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) { + throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.'); + } + + $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string); + + if ('UTF-8' != $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + + case 'html_attr': + if ('UTF-8' != $charset) { + $string = twig_convert_encoding($string, 'UTF-8', $charset); + } + + if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) { + throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.'); + } + + $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string); + + if ('UTF-8' != $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + + case 'url': + // hackish test to avoid version_compare that is much slower, this works unless PHP releases a 5.10.* + // at that point however PHP 5.2.* support can be removed + if (PHP_VERSION < '5.3.0') { + return str_replace('%7E', '~', rawurlencode($string)); + } + + return rawurlencode($string); + + default: + static $escapers; + + if (null === $escapers) { + $escapers = $env->getExtension('core')->getEscapers(); + } + + if (isset($escapers[$strategy])) { + return call_user_func($escapers[$strategy], $env, $string, $charset); + } + + $validStrategies = implode(', ', array_merge(array('html', 'js', 'url', 'css', 'html_attr'), array_keys($escapers))); + + throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies)); + } +} + +/* used internally */ +function twig_escape_filter_is_safe(Twig_Node $filterArgs) +{ + foreach ($filterArgs as $arg) { + if ($arg instanceof Twig_Node_Expression_Constant) { + return array($arg->getAttribute('value')); + } + + return array(); + } + + return array('html'); +} + +if (function_exists('mb_convert_encoding')) { + function twig_convert_encoding($string, $to, $from) + { + return mb_convert_encoding($string, $to, $from); + } +} elseif (function_exists('iconv')) { + function twig_convert_encoding($string, $to, $from) + { + return iconv($from, $to, $string); + } +} else { + function twig_convert_encoding($string, $to, $from) + { + throw new Twig_Error_Runtime('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).'); + } +} + +function _twig_escape_js_callback($matches) +{ + $char = $matches[0]; + + // \xHH + if (!isset($char[1])) { + return '\\x'.strtoupper(substr('00'.bin2hex($char), -2)); + } + + // \uHHHH + $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8'); + + return '\\u'.strtoupper(substr('0000'.bin2hex($char), -4)); +} + +function _twig_escape_css_callback($matches) +{ + $char = $matches[0]; + + // \xHH + if (!isset($char[1])) { + $hex = ltrim(strtoupper(bin2hex($char)), '0'); + if (0 === strlen($hex)) { + $hex = '0'; + } + + return '\\'.$hex.' '; + } + + // \uHHHH + $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8'); + + return '\\'.ltrim(strtoupper(bin2hex($char)), '0').' '; +} + +/** + * This function is adapted from code coming from Zend Framework. + * + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ +function _twig_escape_html_attr_callback($matches) +{ + /* + * While HTML supports far more named entities, the lowest common denominator + * has become HTML5's XML Serialisation which is restricted to the those named + * entities that XML supports. Using HTML entities would result in this error: + * XML Parsing Error: undefined entity + */ + static $entityMap = array( + 34 => 'quot', /* quotation mark */ + 38 => 'amp', /* ampersand */ + 60 => 'lt', /* less-than sign */ + 62 => 'gt', /* greater-than sign */ + ); + + $chr = $matches[0]; + $ord = ord($chr); + + /** + * The following replaces characters undefined in HTML with the + * hex entity for the Unicode replacement character. + */ + if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") || ($ord >= 0x7f && $ord <= 0x9f)) { + return '&#xFFFD;'; + } + + /** + * Check if the current character to escape has a name entity we should + * replace it with while grabbing the hex value of the character. + */ + if (strlen($chr) == 1) { + $hex = strtoupper(substr('00'.bin2hex($chr), -2)); + } else { + $chr = twig_convert_encoding($chr, 'UTF-16BE', 'UTF-8'); + $hex = strtoupper(substr('0000'.bin2hex($chr), -4)); + } + + $int = hexdec($hex); + if (array_key_exists($int, $entityMap)) { + return sprintf('&%s;', $entityMap[$int]); + } + + /** + * Per OWASP recommendations, we'll use hex entities for any other + * characters where a named entity does not exist. + */ + + return sprintf('&#x%s;', $hex); +} + +// add multibyte extensions if possible +if (function_exists('mb_get_info')) { + /** + * Returns the length of a variable. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param mixed $thing A variable + * + * @return integer The length of the value + */ + function twig_length_filter(Twig_Environment $env, $thing) + { + return is_scalar($thing) ? mb_strlen($thing, $env->getCharset()) : count($thing); + } + + /** + * Converts a string to uppercase. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param string $string A string + * + * @return string The uppercased string + */ + function twig_upper_filter(Twig_Environment $env, $string) + { + if (null !== ($charset = $env->getCharset())) { + return mb_strtoupper($string, $charset); + } + + return strtoupper($string); + } + + /** + * Converts a string to lowercase. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param string $string A string + * + * @return string The lowercased string + */ + function twig_lower_filter(Twig_Environment $env, $string) + { + if (null !== ($charset = $env->getCharset())) { + return mb_strtolower($string, $charset); + } + + return strtolower($string); + } + + /** + * Returns a titlecased string. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param string $string A string + * + * @return string The titlecased string + */ + function twig_title_string_filter(Twig_Environment $env, $string) + { + if (null !== ($charset = $env->getCharset())) { + return mb_convert_case($string, MB_CASE_TITLE, $charset); + } + + return ucwords(strtolower($string)); + } + + /** + * Returns a capitalized string. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param string $string A string + * + * @return string The capitalized string + */ + function twig_capitalize_string_filter(Twig_Environment $env, $string) + { + if (null !== ($charset = $env->getCharset())) { + return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset). + mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset); + } + + return ucfirst(strtolower($string)); + } +} +// and byte fallback +else { + /** + * Returns the length of a variable. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param mixed $thing A variable + * + * @return integer The length of the value + */ + function twig_length_filter(Twig_Environment $env, $thing) + { + return is_scalar($thing) ? strlen($thing) : count($thing); + } + + /** + * Returns a titlecased string. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param string $string A string + * + * @return string The titlecased string + */ + function twig_title_string_filter(Twig_Environment $env, $string) + { + return ucwords(strtolower($string)); + } + + /** + * Returns a capitalized string. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param string $string A string + * + * @return string The capitalized string + */ + function twig_capitalize_string_filter(Twig_Environment $env, $string) + { + return ucfirst(strtolower($string)); + } +} + +/* used internally */ +function twig_ensure_traversable($seq) +{ + if ($seq instanceof Traversable || is_array($seq)) { + return $seq; + } + + return array(); +} + +/** + * Checks if a variable is empty. + * + * <pre> + * {# evaluates to true if the foo variable is null, false, or the empty string #} + * {% if foo is empty %} + * {# ... #} + * {% endif %} + * </pre> + * + * @param mixed $value A variable + * + * @return Boolean true if the value is empty, false otherwise + */ +function twig_test_empty($value) +{ + if ($value instanceof Countable) { + return 0 == count($value); + } + + return '' === $value || false === $value || null === $value || array() === $value; +} + +/** + * Checks if a variable is traversable. + * + * <pre> + * {# evaluates to true if the foo variable is an array or a traversable object #} + * {% if foo is traversable %} + * {# ... #} + * {% endif %} + * </pre> + * + * @param mixed $value A variable + * + * @return Boolean true if the value is traversable + */ +function twig_test_iterable($value) +{ + return $value instanceof Traversable || is_array($value); +} + +/** + * Renders a template. + * + * @param string|array $template The template to render or an array of templates to try consecutively + * @param array $variables The variables to pass to the template + * @param Boolean $with_context Whether to pass the current context variables or not + * @param Boolean $ignore_missing Whether to ignore missing templates or not + * @param Boolean $sandboxed Whether to sandbox the template or not + * + * @return string The rendered template + */ +function twig_include(Twig_Environment $env, $context, $template, $variables = array(), $withContext = true, $ignoreMissing = false, $sandboxed = false) +{ + $alreadySandboxed = false; + $sandbox = null; + if ($withContext) { + $variables = array_merge($context, $variables); + } + + if ($isSandboxed = $sandboxed && $env->hasExtension('sandbox')) { + $sandbox = $env->getExtension('sandbox'); + if (!$alreadySandboxed = $sandbox->isSandboxed()) { + $sandbox->enableSandbox(); + } + } + + try { + return $env->resolveTemplate($template)->render($variables); + } catch (Twig_Error_Loader $e) { + if (!$ignoreMissing) { + throw $e; + } + } + + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } +} + +/** + * Returns a template content without rendering it. + * + * @param string $name The template name + * + * @return string The template source + */ +function twig_source(Twig_Environment $env, $name) +{ + return $env->getLoader()->getSource($name); +} + +/** + * Provides the ability to get constants from instances as well as class/global constants. + * + * @param string $constant The name of the constant + * @param null|object $object The object to get the constant from + * + * @return string + */ +function twig_constant($constant, $object = null) +{ + if (null !== $object) { + $constant = get_class($object).'::'.$constant; + } + + return constant($constant); +} + +/** + * Batches item. + * + * @param array $items An array of items + * @param integer $size The size of the batch + * @param mixed $fill A value used to fill missing items + * + * @return array + */ +function twig_array_batch($items, $size, $fill = null) +{ + if ($items instanceof Traversable) { + $items = iterator_to_array($items, false); + } + + $size = ceil($size); + + $result = array_chunk($items, $size, true); + + if (null !== $fill) { + $last = count($result) - 1; + if ($fillCount = $size - count($result[$last])) { + $result[$last] = array_merge( + $result[$last], + array_fill(0, $fillCount, $fill) + ); + } + } + + return $result; +} diff --git a/src/core/libs/Twig/Extension/Debug.php b/src/core/libs/Twig/Extension/Debug.php new file mode 100755 index 0000000..e3a85bf --- /dev/null +++ b/src/core/libs/Twig/Extension/Debug.php @@ -0,0 +1,71 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Extension_Debug extends Twig_Extension +{ + /** + * Returns a list of global functions to add to the existing list. + * + * @return array An array of global functions + */ + public function getFunctions() + { + // dump is safe if var_dump is overridden by xdebug + $isDumpOutputHtmlSafe = extension_loaded('xdebug') + // false means that it was not set (and the default is on) or it explicitly enabled + && (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump')) + // false means that it was not set (and the default is on) or it explicitly enabled + // xdebug.overload_var_dump produces HTML only when html_errors is also enabled + && (false === ini_get('html_errors') || ini_get('html_errors')) + || 'cli' === php_sapi_name() + ; + + return array( + new Twig_SimpleFunction('dump', 'twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)), + ); + } + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return 'debug'; + } +} + +function twig_var_dump(Twig_Environment $env, $context) +{ + if (!$env->isDebug()) { + return; + } + + ob_start(); + + $count = func_num_args(); + if (2 === $count) { + $vars = array(); + foreach ($context as $key => $value) { + if (!$value instanceof Twig_Template) { + $vars[$key] = $value; + } + } + + var_dump($vars); + } else { + for ($i = 2; $i < $count; $i++) { + var_dump(func_get_arg($i)); + } + } + + return ob_get_clean(); +} diff --git a/src/core/libs/Twig/Extension/Escaper.php b/src/core/libs/Twig/Extension/Escaper.php new file mode 100755 index 0000000..d3e5ad0 --- /dev/null +++ b/src/core/libs/Twig/Extension/Escaper.php @@ -0,0 +1,107 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Extension_Escaper extends Twig_Extension +{ + protected $defaultStrategy; + + public function __construct($defaultStrategy = 'html') + { + $this->setDefaultStrategy($defaultStrategy); + } + + /** + * Returns the token parser instances to add to the existing list. + * + * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances + */ + public function getTokenParsers() + { + return array(new Twig_TokenParser_AutoEscape()); + } + + /** + * Returns the node visitor instances to add to the existing list. + * + * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances + */ + public function getNodeVisitors() + { + return array(new Twig_NodeVisitor_Escaper()); + } + + /** + * Returns a list of filters to add to the existing list. + * + * @return array An array of filters + */ + public function getFilters() + { + return array( + new Twig_SimpleFilter('raw', 'twig_raw_filter', array('is_safe' => array('all'))), + ); + } + + /** + * Sets the default strategy to use when not defined by the user. + * + * The strategy can be a valid PHP callback that takes the template + * "filename" as an argument and returns the strategy to use. + * + * @param mixed $defaultStrategy An escaping strategy + */ + public function setDefaultStrategy($defaultStrategy) + { + // for BC + if (true === $defaultStrategy) { + $defaultStrategy = 'html'; + } + + $this->defaultStrategy = $defaultStrategy; + } + + /** + * Gets the default strategy to use when not defined by the user. + * + * @param string $filename The template "filename" + * + * @return string The default strategy to use for the template + */ + public function getDefaultStrategy($filename) + { + // disable string callables to avoid calling a function named html or js, + // or any other upcoming escaping strategy + if (!is_string($this->defaultStrategy) && is_callable($this->defaultStrategy)) { + return call_user_func($this->defaultStrategy, $filename); + } + + return $this->defaultStrategy; + } + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return 'escaper'; + } +} + +/** + * Marks a variable as being safe. + * + * @param string $string A PHP variable + */ +function twig_raw_filter($string) +{ + return $string; +} diff --git a/src/core/libs/Twig/Extension/Optimizer.php b/src/core/libs/Twig/Extension/Optimizer.php new file mode 100755 index 0000000..013fcb6 --- /dev/null +++ b/src/core/libs/Twig/Extension/Optimizer.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Extension_Optimizer extends Twig_Extension +{ + protected $optimizers; + + public function __construct($optimizers = -1) + { + $this->optimizers = $optimizers; + } + + /** + * {@inheritdoc} + */ + public function getNodeVisitors() + { + return array(new Twig_NodeVisitor_Optimizer($this->optimizers)); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'optimizer'; + } +} diff --git a/src/core/libs/Twig/Extension/Sandbox.php b/src/core/libs/Twig/Extension/Sandbox.php new file mode 100755 index 0000000..c59609f --- /dev/null +++ b/src/core/libs/Twig/Extension/Sandbox.php @@ -0,0 +1,112 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Extension_Sandbox extends Twig_Extension +{ + protected $sandboxedGlobally; + protected $sandboxed; + protected $policy; + + public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false) + { + $this->policy = $policy; + $this->sandboxedGlobally = $sandboxed; + } + + /** + * Returns the token parser instances to add to the existing list. + * + * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances + */ + public function getTokenParsers() + { + return array(new Twig_TokenParser_Sandbox()); + } + + /** + * Returns the node visitor instances to add to the existing list. + * + * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances + */ + public function getNodeVisitors() + { + return array(new Twig_NodeVisitor_Sandbox()); + } + + public function enableSandbox() + { + $this->sandboxed = true; + } + + public function disableSandbox() + { + $this->sandboxed = false; + } + + public function isSandboxed() + { + return $this->sandboxedGlobally || $this->sandboxed; + } + + public function isSandboxedGlobally() + { + return $this->sandboxedGlobally; + } + + public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy) + { + $this->policy = $policy; + } + + public function getSecurityPolicy() + { + return $this->policy; + } + + public function checkSecurity($tags, $filters, $functions) + { + if ($this->isSandboxed()) { + $this->policy->checkSecurity($tags, $filters, $functions); + } + } + + public function checkMethodAllowed($obj, $method) + { + if ($this->isSandboxed()) { + $this->policy->checkMethodAllowed($obj, $method); + } + } + + public function checkPropertyAllowed($obj, $method) + { + if ($this->isSandboxed()) { + $this->policy->checkPropertyAllowed($obj, $method); + } + } + + public function ensureToStringAllowed($obj) + { + if (is_object($obj)) { + $this->policy->checkMethodAllowed($obj, '__toString'); + } + + return $obj; + } + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return 'sandbox'; + } +} diff --git a/src/core/libs/Twig/Extension/Staging.php b/src/core/libs/Twig/Extension/Staging.php new file mode 100755 index 0000000..8ab0f45 --- /dev/null +++ b/src/core/libs/Twig/Extension/Staging.php @@ -0,0 +1,113 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Internal class. + * + * This class is used by Twig_Environment as a staging area and must not be used directly. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Extension_Staging extends Twig_Extension +{ + protected $functions = array(); + protected $filters = array(); + protected $visitors = array(); + protected $tokenParsers = array(); + protected $globals = array(); + protected $tests = array(); + + public function addFunction($name, $function) + { + $this->functions[$name] = $function; + } + + /** + * {@inheritdoc} + */ + public function getFunctions() + { + return $this->functions; + } + + public function addFilter($name, $filter) + { + $this->filters[$name] = $filter; + } + + /** + * {@inheritdoc} + */ + public function getFilters() + { + return $this->filters; + } + + public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) + { + $this->visitors[] = $visitor; + } + + /** + * {@inheritdoc} + */ + public function getNodeVisitors() + { + return $this->visitors; + } + + public function addTokenParser(Twig_TokenParserInterface $parser) + { + $this->tokenParsers[] = $parser; + } + + /** + * {@inheritdoc} + */ + public function getTokenParsers() + { + return $this->tokenParsers; + } + + public function addGlobal($name, $value) + { + $this->globals[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function getGlobals() + { + return $this->globals; + } + + public function addTest($name, $test) + { + $this->tests[$name] = $test; + } + + /** + * {@inheritdoc} + */ + public function getTests() + { + return $this->tests; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'staging'; + } +} diff --git a/src/core/libs/Twig/Extension/StringLoader.php b/src/core/libs/Twig/Extension/StringLoader.php new file mode 100755 index 0000000..5e1a60d --- /dev/null +++ b/src/core/libs/Twig/Extension/StringLoader.php @@ -0,0 +1,64 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Extension_StringLoader extends Twig_Extension +{ + /** + * {@inheritdoc} + */ + public function getFunctions() + { + return array( + new Twig_SimpleFunction('template_from_string', 'twig_template_from_string', array('needs_environment' => true)), + ); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'string_loader'; + } +} + +/** + * Loads a template from a string. + * + * <pre> + * {{ include(template_from_string("Hello {{ name }}")) }} + * </pre> + * + * @param Twig_Environment $env A Twig_Environment instance + * @param string $template A template as a string + * + * @return Twig_Template A Twig_Template instance + */ +function twig_template_from_string(Twig_Environment $env, $template) +{ + $name = sprintf('__string_template__%s', hash('sha256', uniqid(mt_rand(), true), false)); + + $loader = new Twig_Loader_Chain(array( + new Twig_Loader_Array(array($name => $template)), + $current = $env->getLoader(), + )); + + $env->setLoader($loader); + try { + $template = $env->loadTemplate($name); + } catch (Exception $e) { + $env->setLoader($current); + + throw $e; + } + $env->setLoader($current); + + return $template; +} diff --git a/src/core/libs/Twig/ExtensionInterface.php b/src/core/libs/Twig/ExtensionInterface.php new file mode 100755 index 0000000..49541b0 --- /dev/null +++ b/src/core/libs/Twig/ExtensionInterface.php @@ -0,0 +1,83 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Interface implemented by extension classes. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface Twig_ExtensionInterface +{ + /** + * Initializes the runtime environment. + * + * This is where you can load some file that contains filter functions for instance. + * + * @param Twig_Environment $environment The current Twig_Environment instance + */ + public function initRuntime(Twig_Environment $environment); + + /** + * Returns the token parser instances to add to the existing list. + * + * @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances + */ + public function getTokenParsers(); + + /** + * Returns the node visitor instances to add to the existing list. + * + * @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances + */ + public function getNodeVisitors(); + + /** + * Returns a list of filters to add to the existing list. + * + * @return array An array of filters + */ + public function getFilters(); + + /** + * Returns a list of tests to add to the existing list. + * + * @return array An array of tests + */ + public function getTests(); + + /** + * Returns a list of functions to add to the existing list. + * + * @return array An array of functions + */ + public function getFunctions(); + + /** + * Returns a list of operators to add to the existing list. + * + * @return array An array of operators + */ + public function getOperators(); + + /** + * Returns a list of global variables to add to the existing list. + * + * @return array An array of global variables + */ + public function getGlobals(); + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName(); +} diff --git a/src/core/libs/Twig/Filter.php b/src/core/libs/Twig/Filter.php new file mode 100755 index 0000000..5cfbb66 --- /dev/null +++ b/src/core/libs/Twig/Filter.php @@ -0,0 +1,81 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template filter. + * + * Use Twig_SimpleFilter instead. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface +{ + protected $options; + protected $arguments = array(); + + public function __construct(array $options = array()) + { + $this->options = array_merge(array( + 'needs_environment' => false, + 'needs_context' => false, + 'pre_escape' => null, + 'preserves_safety' => null, + 'callable' => null, + ), $options); + } + + public function setArguments($arguments) + { + $this->arguments = $arguments; + } + + public function getArguments() + { + return $this->arguments; + } + + public function needsEnvironment() + { + return $this->options['needs_environment']; + } + + public function needsContext() + { + return $this->options['needs_context']; + } + + public function getSafe(Twig_Node $filterArgs) + { + if (isset($this->options['is_safe'])) { + return $this->options['is_safe']; + } + + if (isset($this->options['is_safe_callback'])) { + return call_user_func($this->options['is_safe_callback'], $filterArgs); + } + } + + public function getPreservesSafety() + { + return $this->options['preserves_safety']; + } + + public function getPreEscape() + { + return $this->options['pre_escape']; + } + + public function getCallable() + { + return $this->options['callable']; + } +} diff --git a/src/core/libs/Twig/Filter/Function.php b/src/core/libs/Twig/Filter/Function.php new file mode 100755 index 0000000..ad374a5 --- /dev/null +++ b/src/core/libs/Twig/Filter/Function.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a function template filter. + * + * Use Twig_SimpleFilter instead. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +class Twig_Filter_Function extends Twig_Filter +{ + protected $function; + + public function __construct($function, array $options = array()) + { + $options['callable'] = $function; + + parent::__construct($options); + + $this->function = $function; + } + + public function compile() + { + return $this->function; + } +} diff --git a/src/core/libs/Twig/Filter/Method.php b/src/core/libs/Twig/Filter/Method.php new file mode 100755 index 0000000..63c8c3b --- /dev/null +++ b/src/core/libs/Twig/Filter/Method.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a method template filter. + * + * Use Twig_SimpleFilter instead. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +class Twig_Filter_Method extends Twig_Filter +{ + protected $extension; + protected $method; + + public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) + { + $options['callable'] = array($extension, $method); + + parent::__construct($options); + + $this->extension = $extension; + $this->method = $method; + } + + public function compile() + { + return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method); + } +} diff --git a/src/core/libs/Twig/Filter/Node.php b/src/core/libs/Twig/Filter/Node.php new file mode 100755 index 0000000..8744c5e --- /dev/null +++ b/src/core/libs/Twig/Filter/Node.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template filter as a node. + * + * Use Twig_SimpleFilter instead. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +class Twig_Filter_Node extends Twig_Filter +{ + protected $class; + + public function __construct($class, array $options = array()) + { + parent::__construct($options); + + $this->class = $class; + } + + public function getClass() + { + return $this->class; + } + + public function compile() + { + } +} diff --git a/src/core/libs/Twig/FilterCallableInterface.php b/src/core/libs/Twig/FilterCallableInterface.php new file mode 100755 index 0000000..145534d --- /dev/null +++ b/src/core/libs/Twig/FilterCallableInterface.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a callable template filter. + * + * Use Twig_SimpleFilter instead. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_FilterCallableInterface +{ + public function getCallable(); +} diff --git a/src/core/libs/Twig/FilterInterface.php b/src/core/libs/Twig/FilterInterface.php new file mode 100755 index 0000000..5319ecc --- /dev/null +++ b/src/core/libs/Twig/FilterInterface.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template filter. + * + * Use Twig_SimpleFilter instead. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_FilterInterface +{ + /** + * Compiles a filter. + * + * @return string The PHP code for the filter + */ + public function compile(); + + public function needsEnvironment(); + + public function needsContext(); + + public function getSafe(Twig_Node $filterArgs); + + public function getPreservesSafety(); + + public function getPreEscape(); + + public function setArguments($arguments); + + public function getArguments(); +} diff --git a/src/core/libs/Twig/Function.php b/src/core/libs/Twig/Function.php new file mode 100755 index 0000000..b5ffb2b --- /dev/null +++ b/src/core/libs/Twig/Function.php @@ -0,0 +1,71 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template function. + * + * Use Twig_SimpleFunction instead. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface +{ + protected $options; + protected $arguments = array(); + + public function __construct(array $options = array()) + { + $this->options = array_merge(array( + 'needs_environment' => false, + 'needs_context' => false, + 'callable' => null, + ), $options); + } + + public function setArguments($arguments) + { + $this->arguments = $arguments; + } + + public function getArguments() + { + return $this->arguments; + } + + public function needsEnvironment() + { + return $this->options['needs_environment']; + } + + public function needsContext() + { + return $this->options['needs_context']; + } + + public function getSafe(Twig_Node $functionArgs) + { + if (isset($this->options['is_safe'])) { + return $this->options['is_safe']; + } + + if (isset($this->options['is_safe_callback'])) { + return call_user_func($this->options['is_safe_callback'], $functionArgs); + } + + return array(); + } + + public function getCallable() + { + return $this->options['callable']; + } +} diff --git a/src/core/libs/Twig/Function/Function.php b/src/core/libs/Twig/Function/Function.php new file mode 100755 index 0000000..d1e1b96 --- /dev/null +++ b/src/core/libs/Twig/Function/Function.php @@ -0,0 +1,38 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2010 Arnaud Le Blanc + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a function template function. + * + * Use Twig_SimpleFunction instead. + * + * @author Arnaud Le Blanc <arnaud.lb@gmail.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +class Twig_Function_Function extends Twig_Function +{ + protected $function; + + public function __construct($function, array $options = array()) + { + $options['callable'] = $function; + + parent::__construct($options); + + $this->function = $function; + } + + public function compile() + { + return $this->function; + } +} diff --git a/src/core/libs/Twig/Function/Method.php b/src/core/libs/Twig/Function/Method.php new file mode 100755 index 0000000..67039a9 --- /dev/null +++ b/src/core/libs/Twig/Function/Method.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2010 Arnaud Le Blanc + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a method template function. + * + * Use Twig_SimpleFunction instead. + * + * @author Arnaud Le Blanc <arnaud.lb@gmail.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +class Twig_Function_Method extends Twig_Function +{ + protected $extension; + protected $method; + + public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) + { + $options['callable'] = array($extension, $method); + + parent::__construct($options); + + $this->extension = $extension; + $this->method = $method; + } + + public function compile() + { + return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method); + } +} diff --git a/src/core/libs/Twig/Function/Node.php b/src/core/libs/Twig/Function/Node.php new file mode 100755 index 0000000..06a0d0d --- /dev/null +++ b/src/core/libs/Twig/Function/Node.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template function as a node. + * + * Use Twig_SimpleFunction instead. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +class Twig_Function_Node extends Twig_Function +{ + protected $class; + + public function __construct($class, array $options = array()) + { + parent::__construct($options); + + $this->class = $class; + } + + public function getClass() + { + return $this->class; + } + + public function compile() + { + } +} diff --git a/src/core/libs/Twig/FunctionCallableInterface.php b/src/core/libs/Twig/FunctionCallableInterface.php new file mode 100755 index 0000000..0aab4f5 --- /dev/null +++ b/src/core/libs/Twig/FunctionCallableInterface.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a callable template function. + * + * Use Twig_SimpleFunction instead. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_FunctionCallableInterface +{ + public function getCallable(); +} diff --git a/src/core/libs/Twig/FunctionInterface.php b/src/core/libs/Twig/FunctionInterface.php new file mode 100755 index 0000000..67f4f89 --- /dev/null +++ b/src/core/libs/Twig/FunctionInterface.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * (c) 2010 Arnaud Le Blanc + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template function. + * + * Use Twig_SimpleFunction instead. + * + * @author Arnaud Le Blanc <arnaud.lb@gmail.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_FunctionInterface +{ + /** + * Compiles a function. + * + * @return string The PHP code for the function + */ + public function compile(); + + public function needsEnvironment(); + + public function needsContext(); + + public function getSafe(Twig_Node $filterArgs); + + public function setArguments($arguments); + + public function getArguments(); +} diff --git a/src/core/libs/Twig/Lexer.php b/src/core/libs/Twig/Lexer.php new file mode 100755 index 0000000..ad3ec7d --- /dev/null +++ b/src/core/libs/Twig/Lexer.php @@ -0,0 +1,409 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Lexes a template string. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Lexer implements Twig_LexerInterface +{ + protected $tokens; + protected $code; + protected $cursor; + protected $lineno; + protected $end; + protected $state; + protected $states; + protected $brackets; + protected $env; + protected $filename; + protected $options; + protected $regexes; + protected $position; + protected $positions; + protected $currentVarBlockLine; + + const STATE_DATA = 0; + const STATE_BLOCK = 1; + const STATE_VAR = 2; + const STATE_STRING = 3; + const STATE_INTERPOLATION = 4; + + const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A'; + const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A'; + const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As'; + const REGEX_DQ_STRING_DELIM = '/"/A'; + const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As'; + const PUNCTUATION = '()[]{}?:.,|'; + + public function __construct(Twig_Environment $env, array $options = array()) + { + $this->env = $env; + + $this->options = array_merge(array( + 'tag_comment' => array('{#', '#}'), + 'tag_block' => array('{%', '%}'), + 'tag_variable' => array('{{', '}}'), + 'whitespace_trim' => '-', + 'interpolation' => array('#{', '}'), + ), $options); + + $this->regexes = array( + 'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A', + 'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A', + 'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s', + 'operator' => $this->getOperatorRegex(), + 'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s', + 'lex_block_raw' => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As', + 'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As', + 'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s', + 'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A', + 'interpolation_end' => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A', + ); + } + + /** + * {@inheritdoc} + */ + public function tokenize($code, $filename = null) + { + if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { + $mbEncoding = mb_internal_encoding(); + mb_internal_encoding('ASCII'); + } else { + $mbEncoding = null; + } + + $this->code = str_replace(array("\r\n", "\r"), "\n", $code); + $this->filename = $filename; + $this->cursor = 0; + $this->lineno = 1; + $this->end = strlen($this->code); + $this->tokens = array(); + $this->state = self::STATE_DATA; + $this->states = array(); + $this->brackets = array(); + $this->position = -1; + + // find all token starts in one go + preg_match_all($this->regexes['lex_tokens_start'], $this->code, $matches, PREG_OFFSET_CAPTURE); + $this->positions = $matches; + + while ($this->cursor < $this->end) { + // dispatch to the lexing functions depending + // on the current state + switch ($this->state) { + case self::STATE_DATA: + $this->lexData(); + break; + + case self::STATE_BLOCK: + $this->lexBlock(); + break; + + case self::STATE_VAR: + $this->lexVar(); + break; + + case self::STATE_STRING: + $this->lexString(); + break; + + case self::STATE_INTERPOLATION: + $this->lexInterpolation(); + break; + } + } + + $this->pushToken(Twig_Token::EOF_TYPE); + + if (!empty($this->brackets)) { + list($expect, $lineno) = array_pop($this->brackets); + throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename); + } + + if ($mbEncoding) { + mb_internal_encoding($mbEncoding); + } + + return new Twig_TokenStream($this->tokens, $this->filename); + } + + protected function lexData() + { + // if no matches are left we return the rest of the template as simple text token + if ($this->position == count($this->positions[0]) - 1) { + $this->pushToken(Twig_Token::TEXT_TYPE, substr($this->code, $this->cursor)); + $this->cursor = $this->end; + + return; + } + + // Find the first token after the current cursor + $position = $this->positions[0][++$this->position]; + while ($position[1] < $this->cursor) { + if ($this->position == count($this->positions[0]) - 1) { + return; + } + $position = $this->positions[0][++$this->position]; + } + + // push the template text first + $text = $textContent = substr($this->code, $this->cursor, $position[1] - $this->cursor); + if (isset($this->positions[2][$this->position][0])) { + $text = rtrim($text); + } + $this->pushToken(Twig_Token::TEXT_TYPE, $text); + $this->moveCursor($textContent.$position[0]); + + switch ($this->positions[1][$this->position][0]) { + case $this->options['tag_comment'][0]: + $this->lexComment(); + break; + + case $this->options['tag_block'][0]: + // raw data? + if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, null, $this->cursor)) { + $this->moveCursor($match[0]); + $this->lexRawData($match[1]); + // {% line \d+ %} + } elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, null, $this->cursor)) { + $this->moveCursor($match[0]); + $this->lineno = (int) $match[1]; + } else { + $this->pushToken(Twig_Token::BLOCK_START_TYPE); + $this->pushState(self::STATE_BLOCK); + $this->currentVarBlockLine = $this->lineno; + } + break; + + case $this->options['tag_variable'][0]: + $this->pushToken(Twig_Token::VAR_START_TYPE); + $this->pushState(self::STATE_VAR); + $this->currentVarBlockLine = $this->lineno; + break; + } + } + + protected function lexBlock() + { + if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, null, $this->cursor)) { + $this->pushToken(Twig_Token::BLOCK_END_TYPE); + $this->moveCursor($match[0]); + $this->popState(); + } else { + $this->lexExpression(); + } + } + + protected function lexVar() + { + if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, null, $this->cursor)) { + $this->pushToken(Twig_Token::VAR_END_TYPE); + $this->moveCursor($match[0]); + $this->popState(); + } else { + $this->lexExpression(); + } + } + + protected function lexExpression() + { + // whitespace + if (preg_match('/\s+/A', $this->code, $match, null, $this->cursor)) { + $this->moveCursor($match[0]); + + if ($this->cursor >= $this->end) { + throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $this->state === self::STATE_BLOCK ? 'block' : 'variable'), $this->currentVarBlockLine, $this->filename); + } + } + + // operators + if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) { + $this->pushToken(Twig_Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0])); + $this->moveCursor($match[0]); + } + // names + elseif (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor)) { + $this->pushToken(Twig_Token::NAME_TYPE, $match[0]); + $this->moveCursor($match[0]); + } + // numbers + elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor)) { + $number = (float) $match[0]; // floats + if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) { + $number = (int) $match[0]; // integers lower than the maximum + } + $this->pushToken(Twig_Token::NUMBER_TYPE, $number); + $this->moveCursor($match[0]); + } + // punctuation + elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) { + // opening bracket + if (false !== strpos('([{', $this->code[$this->cursor])) { + $this->brackets[] = array($this->code[$this->cursor], $this->lineno); + } + // closing bracket + elseif (false !== strpos(')]}', $this->code[$this->cursor])) { + if (empty($this->brackets)) { + throw new Twig_Error_Syntax(sprintf('Unexpected "%s"', $this->code[$this->cursor]), $this->lineno, $this->filename); + } + + list($expect, $lineno) = array_pop($this->brackets); + if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) { + throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename); + } + } + + $this->pushToken(Twig_Token::PUNCTUATION_TYPE, $this->code[$this->cursor]); + ++$this->cursor; + } + // strings + elseif (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor)) { + $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1))); + $this->moveCursor($match[0]); + } + // opening double quoted string + elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) { + $this->brackets[] = array('"', $this->lineno); + $this->pushState(self::STATE_STRING); + $this->moveCursor($match[0]); + } + // unlexable + else { + throw new Twig_Error_Syntax(sprintf('Unexpected character "%s"', $this->code[$this->cursor]), $this->lineno, $this->filename); + } + } + + protected function lexRawData($tag) + { + if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) { + throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s" block', $tag), $this->lineno, $this->filename); + } + + $text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor); + $this->moveCursor($text.$match[0][0]); + + if (false !== strpos($match[1][0], $this->options['whitespace_trim'])) { + $text = rtrim($text); + } + + $this->pushToken(Twig_Token::TEXT_TYPE, $text); + } + + protected function lexComment() + { + if (!preg_match($this->regexes['lex_comment'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) { + throw new Twig_Error_Syntax('Unclosed comment', $this->lineno, $this->filename); + } + + $this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]); + } + + protected function lexString() + { + if (preg_match($this->regexes['interpolation_start'], $this->code, $match, null, $this->cursor)) { + $this->brackets[] = array($this->options['interpolation'][0], $this->lineno); + $this->pushToken(Twig_Token::INTERPOLATION_START_TYPE); + $this->moveCursor($match[0]); + $this->pushState(self::STATE_INTERPOLATION); + + } elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, null, $this->cursor) && strlen($match[0]) > 0) { + $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes($match[0])); + $this->moveCursor($match[0]); + + } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) { + list($expect, $lineno) = array_pop($this->brackets); + if ($this->code[$this->cursor] != '"') { + throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $expect), $lineno, $this->filename); + } + + $this->popState(); + ++$this->cursor; + } + } + + protected function lexInterpolation() + { + $bracket = end($this->brackets); + if ($this->options['interpolation'][0] === $bracket[0] && preg_match($this->regexes['interpolation_end'], $this->code, $match, null, $this->cursor)) { + array_pop($this->brackets); + $this->pushToken(Twig_Token::INTERPOLATION_END_TYPE); + $this->moveCursor($match[0]); + $this->popState(); + } else { + $this->lexExpression(); + } + } + + protected function pushToken($type, $value = '') + { + // do not push empty text tokens + if (Twig_Token::TEXT_TYPE === $type && '' === $value) { + return; + } + + $this->tokens[] = new Twig_Token($type, $value, $this->lineno); + } + + protected function moveCursor($text) + { + $this->cursor += strlen($text); + $this->lineno += substr_count($text, "\n"); + } + + protected function getOperatorRegex() + { + $operators = array_merge( + array('='), + array_keys($this->env->getUnaryOperators()), + array_keys($this->env->getBinaryOperators()) + ); + + $operators = array_combine($operators, array_map('strlen', $operators)); + arsort($operators); + + $regex = array(); + foreach ($operators as $operator => $length) { + // an operator that ends with a character must be followed by + // a whitespace or a parenthesis + if (ctype_alpha($operator[$length - 1])) { + $r = preg_quote($operator, '/').'(?=[\s()])'; + } else { + $r = preg_quote($operator, '/'); + } + + // an operator with a space can be any amount of whitespaces + $r = preg_replace('/\s+/', '\s+', $r); + + $regex[] = $r; + } + + return '/'.implode('|', $regex).'/A'; + } + + protected function pushState($state) + { + $this->states[] = $this->state; + $this->state = $state; + } + + protected function popState() + { + if (0 === count($this->states)) { + throw new Exception('Cannot pop state without a previous state'); + } + + $this->state = array_pop($this->states); + } +} diff --git a/src/core/libs/Twig/LexerInterface.php b/src/core/libs/Twig/LexerInterface.php new file mode 100755 index 0000000..dd51cae --- /dev/null +++ b/src/core/libs/Twig/LexerInterface.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Interface implemented by lexer classes. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_LexerInterface +{ + /** + * Tokenizes a source code. + * + * @param string $code The source code + * @param string $filename A unique identifier for the source code + * + * @return Twig_TokenStream A token stream instance + * + * @throws Twig_Error_Syntax When the code is syntactically wrong + */ + public function tokenize($code, $filename = null); +} diff --git a/src/core/libs/Twig/Loader/Array.php b/src/core/libs/Twig/Loader/Array.php new file mode 100755 index 0000000..ac56104 --- /dev/null +++ b/src/core/libs/Twig/Loader/Array.php @@ -0,0 +1,95 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Loads a template from an array. + * + * When using this loader with a cache mechanism, you should know that a new cache + * key is generated each time a template content "changes" (the cache key being the + * source code of the template). If you don't want to see your cache grows out of + * control, you need to take care of clearing the old cache file by yourself. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface +{ + protected $templates = array(); + + /** + * Constructor. + * + * @param array $templates An array of templates (keys are the names, and values are the source code) + * + * @see Twig_Loader + */ + public function __construct(array $templates) + { + $this->templates = $templates; + } + + /** + * Adds or overrides a template. + * + * @param string $name The template name + * @param string $template The template source + */ + public function setTemplate($name, $template) + { + $this->templates[(string) $name] = $template; + } + + /** + * {@inheritdoc} + */ + public function getSource($name) + { + $name = (string) $name; + if (!isset($this->templates[$name])) { + throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); + } + + return $this->templates[$name]; + } + + /** + * {@inheritdoc} + */ + public function exists($name) + { + return isset($this->templates[(string) $name]); + } + + /** + * {@inheritdoc} + */ + public function getCacheKey($name) + { + $name = (string) $name; + if (!isset($this->templates[$name])) { + throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); + } + + return $this->templates[$name]; + } + + /** + * {@inheritdoc} + */ + public function isFresh($name, $time) + { + $name = (string) $name; + if (!isset($this->templates[$name])) { + throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); + } + + return true; + } +} diff --git a/src/core/libs/Twig/Loader/Chain.php b/src/core/libs/Twig/Loader/Chain.php new file mode 100755 index 0000000..7919eda --- /dev/null +++ b/src/core/libs/Twig/Loader/Chain.php @@ -0,0 +1,138 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Loads templates from other loaders. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface +{ + private $hasSourceCache = array(); + protected $loaders = array(); + + /** + * Constructor. + * + * @param Twig_LoaderInterface[] $loaders An array of loader instances + */ + public function __construct(array $loaders = array()) + { + foreach ($loaders as $loader) { + $this->addLoader($loader); + } + } + + /** + * Adds a loader instance. + * + * @param Twig_LoaderInterface $loader A Loader instance + */ + public function addLoader(Twig_LoaderInterface $loader) + { + $this->loaders[] = $loader; + $this->hasSourceCache = array(); + } + + /** + * {@inheritdoc} + */ + public function getSource($name) + { + $exceptions = array(); + foreach ($this->loaders as $loader) { + if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { + continue; + } + + try { + return $loader->getSource($name); + } catch (Twig_Error_Loader $e) { + $exceptions[] = $e->getMessage(); + } + } + + throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(', ', $exceptions))); + } + + /** + * {@inheritdoc} + */ + public function exists($name) + { + $name = (string) $name; + + if (isset($this->hasSourceCache[$name])) { + return $this->hasSourceCache[$name]; + } + + foreach ($this->loaders as $loader) { + if ($loader instanceof Twig_ExistsLoaderInterface) { + if ($loader->exists($name)) { + return $this->hasSourceCache[$name] = true; + } + + continue; + } + + try { + $loader->getSource($name); + + return $this->hasSourceCache[$name] = true; + } catch (Twig_Error_Loader $e) { + } + } + + return $this->hasSourceCache[$name] = false; + } + + /** + * {@inheritdoc} + */ + public function getCacheKey($name) + { + $exceptions = array(); + foreach ($this->loaders as $loader) { + if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { + continue; + } + + try { + return $loader->getCacheKey($name); + } catch (Twig_Error_Loader $e) { + $exceptions[] = get_class($loader).': '.$e->getMessage(); + } + } + + throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions))); + } + + /** + * {@inheritdoc} + */ + public function isFresh($name, $time) + { + $exceptions = array(); + foreach ($this->loaders as $loader) { + if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { + continue; + } + + try { + return $loader->isFresh($name, $time); + } catch (Twig_Error_Loader $e) { + $exceptions[] = get_class($loader).': '.$e->getMessage(); + } + } + + throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions))); + } +} diff --git a/src/core/libs/Twig/Loader/Filesystem.php b/src/core/libs/Twig/Loader/Filesystem.php new file mode 100755 index 0000000..2d6170c --- /dev/null +++ b/src/core/libs/Twig/Loader/Filesystem.php @@ -0,0 +1,229 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Loads template from the filesystem. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface +{ + /** Identifier of the main namespace. */ + const MAIN_NAMESPACE = '__main__'; + + protected $paths = array(); + protected $cache = array(); + + /** + * Constructor. + * + * @param string|array $paths A path or an array of paths where to look for templates + */ + public function __construct($paths = array()) + { + if ($paths) { + $this->setPaths($paths); + } + } + + /** + * Returns the paths to the templates. + * + * @param string $namespace A path namespace + * + * @return array The array of paths where to look for templates + */ + public function getPaths($namespace = self::MAIN_NAMESPACE) + { + return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array(); + } + + /** + * Returns the path namespaces. + * + * The main namespace is always defined. + * + * @return array The array of defined namespaces + */ + public function getNamespaces() + { + return array_keys($this->paths); + } + + /** + * Sets the paths where templates are stored. + * + * @param string|array $paths A path or an array of paths where to look for templates + * @param string $namespace A path namespace + */ + public function setPaths($paths, $namespace = self::MAIN_NAMESPACE) + { + if (!is_array($paths)) { + $paths = array($paths); + } + + $this->paths[$namespace] = array(); + foreach ($paths as $path) { + $this->addPath($path, $namespace); + } + } + + /** + * Adds a path where templates are stored. + * + * @param string $path A path where to look for templates + * @param string $namespace A path name + * + * @throws Twig_Error_Loader + */ + public function addPath($path, $namespace = self::MAIN_NAMESPACE) + { + // invalidate the cache + $this->cache = array(); + + if (!is_dir($path)) { + throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path)); + } + + $this->paths[$namespace][] = rtrim($path, '/\\'); + } + + /** + * Prepends a path where templates are stored. + * + * @param string $path A path where to look for templates + * @param string $namespace A path name + * + * @throws Twig_Error_Loader + */ + public function prependPath($path, $namespace = self::MAIN_NAMESPACE) + { + // invalidate the cache + $this->cache = array(); + + if (!is_dir($path)) { + throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path)); + } + + $path = rtrim($path, '/\\'); + + if (!isset($this->paths[$namespace])) { + $this->paths[$namespace][] = $path; + } else { + array_unshift($this->paths[$namespace], $path); + } + } + + /** + * {@inheritdoc} + */ + public function getSource($name) + { + return file_get_contents($this->findTemplate($name)); + } + + /** + * {@inheritdoc} + */ + public function getCacheKey($name) + { + return $this->findTemplate($name); + } + + /** + * {@inheritdoc} + */ + public function exists($name) + { + $name = $this->normalizeName($name); + + if (isset($this->cache[$name])) { + return true; + } + + try { + $this->findTemplate($name); + + return true; + } catch (Twig_Error_Loader $exception) { + return false; + } + } + + /** + * {@inheritdoc} + */ + public function isFresh($name, $time) + { + return filemtime($this->findTemplate($name)) <= $time; + } + + protected function findTemplate($name) + { + $name = $this->normalizeName($name); + + if (isset($this->cache[$name])) { + return $this->cache[$name]; + } + + $this->validateName($name); + + $namespace = self::MAIN_NAMESPACE; + $shortname = $name; + if (isset($name[0]) && '@' == $name[0]) { + if (false === $pos = strpos($name, '/')) { + throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name)); + } + + $namespace = substr($name, 1, $pos - 1); + $shortname = substr($name, $pos + 1); + } + + if (!isset($this->paths[$namespace])) { + throw new Twig_Error_Loader(sprintf('There are no registered paths for namespace "%s".', $namespace)); + } + + foreach ($this->paths[$namespace] as $path) { + if (is_file($path.'/'.$shortname)) { + return $this->cache[$name] = $path.'/'.$shortname; + } + } + + throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace]))); + } + + protected function normalizeName($name) + { + return preg_replace('#/{2,}#', '/', strtr((string) $name, '\\', '/')); + } + + protected function validateName($name) + { + if (false !== strpos($name, "\0")) { + throw new Twig_Error_Loader('A template name cannot contain NUL bytes.'); + } + + $name = ltrim($name, '/'); + $parts = explode('/', $name); + $level = 0; + foreach ($parts as $part) { + if ('..' === $part) { + --$level; + } elseif ('.' !== $part) { + ++$level; + } + + if ($level < 0) { + throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); + } + } + } +} diff --git a/src/core/libs/Twig/Loader/String.php b/src/core/libs/Twig/Loader/String.php new file mode 100755 index 0000000..8ad9856 --- /dev/null +++ b/src/core/libs/Twig/Loader/String.php @@ -0,0 +1,59 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Loads a template from a string. + * + * This loader should only be used for unit testing as it has many limitations + * (for instance, the include or extends tag does not make any sense for a string + * loader). + * + * When using this loader with a cache mechanism, you should know that a new cache + * key is generated each time a template content "changes" (the cache key being the + * source code of the template). If you don't want to see your cache grows out of + * control, you need to take care of clearing the old cache file by yourself. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface +{ + /** + * {@inheritdoc} + */ + public function getSource($name) + { + return $name; + } + + /** + * {@inheritdoc} + */ + public function exists($name) + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getCacheKey($name) + { + return $name; + } + + /** + * {@inheritdoc} + */ + public function isFresh($name, $time) + { + return true; + } +} diff --git a/src/core/libs/Twig/LoaderInterface.php b/src/core/libs/Twig/LoaderInterface.php new file mode 100755 index 0000000..927786d --- /dev/null +++ b/src/core/libs/Twig/LoaderInterface.php @@ -0,0 +1,52 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Interface all loaders must implement. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface Twig_LoaderInterface +{ + /** + * Gets the source code of a template, given its name. + * + * @param string $name The name of the template to load + * + * @return string The template source code + * + * @throws Twig_Error_Loader When $name is not found + */ + public function getSource($name); + + /** + * Gets the cache key to use for the cache for a given template name. + * + * @param string $name The name of the template to load + * + * @return string The cache key + * + * @throws Twig_Error_Loader When $name is not found + */ + public function getCacheKey($name); + + /** + * Returns true if the template is still fresh. + * + * @param string $name The template name + * @param timestamp $time The last modification time of the cached template + * + * @return Boolean true if the template is fresh, false otherwise + * + * @throws Twig_Error_Loader When $name is not found + */ + public function isFresh($name, $time); +} diff --git a/src/core/libs/Twig/Markup.php b/src/core/libs/Twig/Markup.php new file mode 100755 index 0000000..69871fc --- /dev/null +++ b/src/core/libs/Twig/Markup.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Marks a content as safe. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Markup implements Countable +{ + protected $content; + protected $charset; + + public function __construct($content, $charset) + { + $this->content = (string) $content; + $this->charset = $charset; + } + + public function __toString() + { + return $this->content; + } + + public function count() + { + return function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : strlen($this->content); + } +} diff --git a/src/core/libs/Twig/Node.php b/src/core/libs/Twig/Node.php new file mode 100755 index 0000000..931b463 --- /dev/null +++ b/src/core/libs/Twig/Node.php @@ -0,0 +1,226 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a node in the AST. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node implements Twig_NodeInterface +{ + protected $nodes; + protected $attributes; + protected $lineno; + protected $tag; + + /** + * Constructor. + * + * The nodes are automatically made available as properties ($this->node). + * The attributes are automatically made available as array items ($this['name']). + * + * @param array $nodes An array of named nodes + * @param array $attributes An array of attributes (should not be nodes) + * @param integer $lineno The line number + * @param string $tag The tag name associated with the Node + */ + public function __construct(array $nodes = array(), array $attributes = array(), $lineno = 0, $tag = null) + { + $this->nodes = $nodes; + $this->attributes = $attributes; + $this->lineno = $lineno; + $this->tag = $tag; + } + + public function __toString() + { + $attributes = array(); + foreach ($this->attributes as $name => $value) { + $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true))); + } + + $repr = array(get_class($this).'('.implode(', ', $attributes)); + + if (count($this->nodes)) { + foreach ($this->nodes as $name => $node) { + $len = strlen($name) + 4; + $noderepr = array(); + foreach (explode("\n", (string) $node) as $line) { + $noderepr[] = str_repeat(' ', $len).$line; + } + + $repr[] = sprintf(' %s: %s', $name, ltrim(implode("\n", $noderepr))); + } + + $repr[] = ')'; + } else { + $repr[0] .= ')'; + } + + return implode("\n", $repr); + } + + public function toXml($asDom = false) + { + $dom = new DOMDocument('1.0', 'UTF-8'); + $dom->formatOutput = true; + $dom->appendChild($xml = $dom->createElement('twig')); + + $xml->appendChild($node = $dom->createElement('node')); + $node->setAttribute('class', get_class($this)); + + foreach ($this->attributes as $name => $value) { + $node->appendChild($attribute = $dom->createElement('attribute')); + $attribute->setAttribute('name', $name); + $attribute->appendChild($dom->createTextNode($value)); + } + + foreach ($this->nodes as $name => $n) { + if (null === $n) { + continue; + } + + $child = $n->toXml(true)->getElementsByTagName('node')->item(0); + $child = $dom->importNode($child, true); + $child->setAttribute('name', $name); + + $node->appendChild($child); + } + + return $asDom ? $dom : $dom->saveXml(); + } + + public function compile(Twig_Compiler $compiler) + { + foreach ($this->nodes as $node) { + $node->compile($compiler); + } + } + + public function getLine() + { + return $this->lineno; + } + + public function getNodeTag() + { + return $this->tag; + } + + /** + * Returns true if the attribute is defined. + * + * @param string The attribute name + * + * @return Boolean true if the attribute is defined, false otherwise + */ + public function hasAttribute($name) + { + return array_key_exists($name, $this->attributes); + } + + /** + * Gets an attribute. + * + * @param string The attribute name + * + * @return mixed The attribute value + */ + public function getAttribute($name) + { + if (!array_key_exists($name, $this->attributes)) { + throw new LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this))); + } + + return $this->attributes[$name]; + } + + /** + * Sets an attribute. + * + * @param string The attribute name + * @param mixed The attribute value + */ + public function setAttribute($name, $value) + { + $this->attributes[$name] = $value; + } + + /** + * Removes an attribute. + * + * @param string The attribute name + */ + public function removeAttribute($name) + { + unset($this->attributes[$name]); + } + + /** + * Returns true if the node with the given identifier exists. + * + * @param string The node name + * + * @return Boolean true if the node with the given name exists, false otherwise + */ + public function hasNode($name) + { + return array_key_exists($name, $this->nodes); + } + + /** + * Gets a node by name. + * + * @param string The node name + * + * @return Twig_Node A Twig_Node instance + */ + public function getNode($name) + { + if (!array_key_exists($name, $this->nodes)) { + throw new LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this))); + } + + return $this->nodes[$name]; + } + + /** + * Sets a node. + * + * @param string The node name + * @param Twig_Node A Twig_Node instance + */ + public function setNode($name, $node = null) + { + $this->nodes[$name] = $node; + } + + /** + * Removes a node by name. + * + * @param string The node name + */ + public function removeNode($name) + { + unset($this->nodes[$name]); + } + + public function count() + { + return count($this->nodes); + } + + public function getIterator() + { + return new ArrayIterator($this->nodes); + } +} diff --git a/src/core/libs/Twig/Node/AutoEscape.php b/src/core/libs/Twig/Node/AutoEscape.php new file mode 100755 index 0000000..8f190e0 --- /dev/null +++ b/src/core/libs/Twig/Node/AutoEscape.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents an autoescape node. + * + * The value is the escaping strategy (can be html, js, ...) + * + * The true value is equivalent to html. + * + * If autoescaping is disabled, then the value is false. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_AutoEscape extends Twig_Node +{ + public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape') + { + parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler->subcompile($this->getNode('body')); + } +} diff --git a/src/core/libs/Twig/Node/Block.php b/src/core/libs/Twig/Node/Block.php new file mode 100755 index 0000000..50eb67e --- /dev/null +++ b/src/core/libs/Twig/Node/Block.php @@ -0,0 +1,44 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a block node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Block extends Twig_Node +{ + public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null) + { + parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write(sprintf("public function block_%s(\$context, array \$blocks = array())\n", $this->getAttribute('name')), "{\n") + ->indent() + ; + + $compiler + ->subcompile($this->getNode('body')) + ->outdent() + ->write("}\n\n") + ; + } +} diff --git a/src/core/libs/Twig/Node/BlockReference.php b/src/core/libs/Twig/Node/BlockReference.php new file mode 100755 index 0000000..013e369 --- /dev/null +++ b/src/core/libs/Twig/Node/BlockReference.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a block call node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface +{ + public function __construct($name, $lineno, $tag = null) + { + parent::__construct(array(), array('name' => $name), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write(sprintf("\$this->displayBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name'))) + ; + } +} diff --git a/src/core/libs/Twig/Node/Body.php b/src/core/libs/Twig/Node/Body.php new file mode 100755 index 0000000..3ffb134 --- /dev/null +++ b/src/core/libs/Twig/Node/Body.php @@ -0,0 +1,19 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a body node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Body extends Twig_Node +{ +} diff --git a/src/core/libs/Twig/Node/Do.php b/src/core/libs/Twig/Node/Do.php new file mode 100755 index 0000000..c528066 --- /dev/null +++ b/src/core/libs/Twig/Node/Do.php @@ -0,0 +1,38 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a do node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Do extends Twig_Node +{ + public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) + { + parent::__construct(array('expr' => $expr), array(), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write('') + ->subcompile($this->getNode('expr')) + ->raw(";\n") + ; + } +} diff --git a/src/core/libs/Twig/Node/Embed.php b/src/core/libs/Twig/Node/Embed.php new file mode 100755 index 0000000..4c9456d --- /dev/null +++ b/src/core/libs/Twig/Node/Embed.php @@ -0,0 +1,38 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents an embed node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Embed extends Twig_Node_Include +{ + // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module) + public function __construct($filename, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) + { + parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag); + + $this->setAttribute('filename', $filename); + $this->setAttribute('index', $index); + } + + protected function addGetTemplate(Twig_Compiler $compiler) + { + $compiler + ->write("\$this->env->loadTemplate(") + ->string($this->getAttribute('filename')) + ->raw(', ') + ->string($this->getAttribute('index')) + ->raw(")") + ; + } +} diff --git a/src/core/libs/Twig/Node/Expression.php b/src/core/libs/Twig/Node/Expression.php new file mode 100755 index 0000000..a7382e7 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression.php @@ -0,0 +1,20 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Abstract class for all nodes that represents an expression. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +abstract class Twig_Node_Expression extends Twig_Node +{ +} diff --git a/src/core/libs/Twig/Node/Expression/Array.php b/src/core/libs/Twig/Node/Expression/Array.php new file mode 100755 index 0000000..1da785f --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Array.php @@ -0,0 +1,86 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Array extends Twig_Node_Expression +{ + protected $index; + + public function __construct(array $elements, $lineno) + { + parent::__construct($elements, array(), $lineno); + + $this->index = -1; + foreach ($this->getKeyValuePairs() as $pair) { + if ($pair['key'] instanceof Twig_Node_Expression_Constant && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) { + $this->index = $pair['key']->getAttribute('value'); + } + } + } + + public function getKeyValuePairs() + { + $pairs = array(); + + foreach (array_chunk($this->nodes, 2) as $pair) { + $pairs[] = array( + 'key' => $pair[0], + 'value' => $pair[1], + ); + } + + return $pairs; + } + + public function hasElement(Twig_Node_Expression $key) + { + foreach ($this->getKeyValuePairs() as $pair) { + // we compare the string representation of the keys + // to avoid comparing the line numbers which are not relevant here. + if ((string) $key == (string) $pair['key']) { + return true; + } + } + + return false; + } + + public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null) + { + if (null === $key) { + $key = new Twig_Node_Expression_Constant(++$this->index, $value->getLine()); + } + + array_push($this->nodes, $key, $value); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler->raw('array('); + $first = true; + foreach ($this->getKeyValuePairs() as $pair) { + if (!$first) { + $compiler->raw(', '); + } + $first = false; + + $compiler + ->subcompile($pair['key']) + ->raw(' => ') + ->subcompile($pair['value']) + ; + } + $compiler->raw(')'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/AssignName.php b/src/core/libs/Twig/Node/Expression/AssignName.php new file mode 100755 index 0000000..2ddea78 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/AssignName.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name +{ + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('$context[') + ->string($this->getAttribute('name')) + ->raw(']') + ; + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary.php b/src/core/libs/Twig/Node/Expression/Binary.php new file mode 100755 index 0000000..9dd5de2 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression +{ + public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno) + { + parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('(') + ->subcompile($this->getNode('left')) + ->raw(' ') + ; + $this->operator($compiler); + $compiler + ->raw(' ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; + } + + abstract public function operator(Twig_Compiler $compiler); +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Add.php b/src/core/libs/Twig/Node/Expression/Binary/Add.php new file mode 100755 index 0000000..0ef8e11 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Add.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('+'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/And.php b/src/core/libs/Twig/Node/Expression/Binary/And.php new file mode 100755 index 0000000..d5752eb --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/And.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('&&'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/BitwiseAnd.php b/src/core/libs/Twig/Node/Expression/Binary/BitwiseAnd.php new file mode 100755 index 0000000..9a46d84 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/BitwiseAnd.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_BitwiseAnd extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('&'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/BitwiseOr.php b/src/core/libs/Twig/Node/Expression/Binary/BitwiseOr.php new file mode 100755 index 0000000..058a20b --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/BitwiseOr.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_BitwiseOr extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('|'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/BitwiseXor.php b/src/core/libs/Twig/Node/Expression/Binary/BitwiseXor.php new file mode 100755 index 0000000..f4da73d --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/BitwiseXor.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_BitwiseXor extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('^'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Concat.php b/src/core/libs/Twig/Node/Expression/Binary/Concat.php new file mode 100755 index 0000000..f9a6462 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Concat.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('.'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Div.php b/src/core/libs/Twig/Node/Expression/Binary/Div.php new file mode 100755 index 0000000..e0797a6 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Div.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('/'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/EndsWith.php b/src/core/libs/Twig/Node/Expression/Binary/EndsWith.php new file mode 100755 index 0000000..5de6c72 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/EndsWith.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2013 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary +{ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('(0 === substr_compare(') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw(', -strlen(') + ->subcompile($this->getNode('right')) + ->raw(')))') + ; + } + + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw(''); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Equal.php b/src/core/libs/Twig/Node/Expression/Binary/Equal.php new file mode 100755 index 0000000..7b1236d --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Equal.php @@ -0,0 +1,17 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Equal extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('=='); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/FloorDiv.php b/src/core/libs/Twig/Node/Expression/Binary/FloorDiv.php new file mode 100755 index 0000000..7fbd055 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/FloorDiv.php @@ -0,0 +1,29 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary +{ + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler->raw('intval(floor('); + parent::compile($compiler); + $compiler->raw('))'); + } + + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('/'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Greater.php b/src/core/libs/Twig/Node/Expression/Binary/Greater.php new file mode 100755 index 0000000..a110bd9 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Greater.php @@ -0,0 +1,17 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Greater extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('>'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/GreaterEqual.php b/src/core/libs/Twig/Node/Expression/Binary/GreaterEqual.php new file mode 100755 index 0000000..3754fed --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/GreaterEqual.php @@ -0,0 +1,17 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_GreaterEqual extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('>='); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/In.php b/src/core/libs/Twig/Node/Expression/Binary/In.php new file mode 100755 index 0000000..788f937 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/In.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary +{ + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('twig_in_filter(') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; + } + + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('in'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Less.php b/src/core/libs/Twig/Node/Expression/Binary/Less.php new file mode 100755 index 0000000..45fd300 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Less.php @@ -0,0 +1,17 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Less extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('<'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/LessEqual.php b/src/core/libs/Twig/Node/Expression/Binary/LessEqual.php new file mode 100755 index 0000000..e38e257 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/LessEqual.php @@ -0,0 +1,17 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_LessEqual extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('<='); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Matches.php b/src/core/libs/Twig/Node/Expression/Binary/Matches.php new file mode 100755 index 0000000..93bb292 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Matches.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2013 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary +{ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('preg_match(') + ->subcompile($this->getNode('right')) + ->raw(', ') + ->subcompile($this->getNode('left')) + ->raw(')') + ; + } + + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw(''); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Mod.php b/src/core/libs/Twig/Node/Expression/Binary/Mod.php new file mode 100755 index 0000000..9924114 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Mod.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('%'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Mul.php b/src/core/libs/Twig/Node/Expression/Binary/Mul.php new file mode 100755 index 0000000..c91529c --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Mul.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('*'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/NotEqual.php b/src/core/libs/Twig/Node/Expression/Binary/NotEqual.php new file mode 100755 index 0000000..26867ba --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/NotEqual.php @@ -0,0 +1,17 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_NotEqual extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('!='); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/NotIn.php b/src/core/libs/Twig/Node/Expression/Binary/NotIn.php new file mode 100755 index 0000000..f347b7b --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/NotIn.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary +{ + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('!twig_in_filter(') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; + } + + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('not in'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Or.php b/src/core/libs/Twig/Node/Expression/Binary/Or.php new file mode 100755 index 0000000..adba49c --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Or.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('||'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Power.php b/src/core/libs/Twig/Node/Expression/Binary/Power.php new file mode 100755 index 0000000..b2c5904 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Power.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary +{ + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('pow(') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; + } + + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('**'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Range.php b/src/core/libs/Twig/Node/Expression/Binary/Range.php new file mode 100755 index 0000000..bea4f2a --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Range.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary +{ + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('range(') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; + } + + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('..'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/StartsWith.php b/src/core/libs/Twig/Node/Expression/Binary/StartsWith.php new file mode 100755 index 0000000..eb8c107 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/StartsWith.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2013 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary +{ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('(0 === strpos(') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw('))') + ; + } + + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw(''); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Binary/Sub.php b/src/core/libs/Twig/Node/Expression/Binary/Sub.php new file mode 100755 index 0000000..d446399 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Binary/Sub.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary +{ + public function operator(Twig_Compiler $compiler) + { + return $compiler->raw('-'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/BlockReference.php b/src/core/libs/Twig/Node/Expression/BlockReference.php new file mode 100755 index 0000000..647196e --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/BlockReference.php @@ -0,0 +1,51 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a block call node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Expression_BlockReference extends Twig_Node_Expression +{ + public function __construct(Twig_NodeInterface $name, $asString = false, $lineno, $tag = null) + { + parent::__construct(array('name' => $name), array('as_string' => $asString, 'output' => false), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + if ($this->getAttribute('as_string')) { + $compiler->raw('(string) '); + } + + if ($this->getAttribute('output')) { + $compiler + ->addDebugInfo($this) + ->write("\$this->displayBlock(") + ->subcompile($this->getNode('name')) + ->raw(", \$context, \$blocks);\n") + ; + } else { + $compiler + ->raw("\$this->renderBlock(") + ->subcompile($this->getNode('name')) + ->raw(", \$context, \$blocks)") + ; + } + } +} diff --git a/src/core/libs/Twig/Node/Expression/Call.php b/src/core/libs/Twig/Node/Expression/Call.php new file mode 100755 index 0000000..d019696 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Call.php @@ -0,0 +1,178 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +abstract class Twig_Node_Expression_Call extends Twig_Node_Expression +{ + protected function compileCallable(Twig_Compiler $compiler) + { + $callable = $this->getAttribute('callable'); + + $closingParenthesis = false; + if ($callable) { + if (is_string($callable)) { + $compiler->raw($callable); + } elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) { + $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $callable[1])); + } else { + $type = ucfirst($this->getAttribute('type')); + $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name'))); + $closingParenthesis = true; + } + } else { + $compiler->raw($this->getAttribute('thing')->compile()); + } + + $this->compileArguments($compiler); + + if ($closingParenthesis) { + $compiler->raw(')'); + } + } + + protected function compileArguments(Twig_Compiler $compiler) + { + $compiler->raw('('); + + $first = true; + + if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { + $compiler->raw('$this->env'); + $first = false; + } + + if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { + if (!$first) { + $compiler->raw(', '); + } + $compiler->raw('$context'); + $first = false; + } + + if ($this->hasAttribute('arguments')) { + foreach ($this->getAttribute('arguments') as $argument) { + if (!$first) { + $compiler->raw(', '); + } + $compiler->string($argument); + $first = false; + } + } + + if ($this->hasNode('node')) { + if (!$first) { + $compiler->raw(', '); + } + $compiler->subcompile($this->getNode('node')); + $first = false; + } + + if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) { + $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null; + + $arguments = $this->getArguments($callable, $this->getNode('arguments')); + + foreach ($arguments as $node) { + if (!$first) { + $compiler->raw(', '); + } + $compiler->subcompile($node); + $first = false; + } + } + + $compiler->raw(')'); + } + + protected function getArguments($callable, $arguments) + { + $parameters = array(); + $named = false; + foreach ($arguments as $name => $node) { + if (!is_int($name)) { + $named = true; + $name = $this->normalizeName($name); + } elseif ($named) { + throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name'))); + } + + $parameters[$name] = $node; + } + + if (!$named) { + return $parameters; + } + + if (!$callable) { + throw new LogicException(sprintf('Named arguments are not supported for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name'))); + } + + // manage named arguments + if (is_array($callable)) { + $r = new ReflectionMethod($callable[0], $callable[1]); + } elseif (is_object($callable) && !$callable instanceof Closure) { + $r = new ReflectionObject($callable); + $r = $r->getMethod('__invoke'); + } else { + $r = new ReflectionFunction($callable); + } + + $definition = $r->getParameters(); + if ($this->hasNode('node')) { + array_shift($definition); + } + if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { + array_shift($definition); + } + if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { + array_shift($definition); + } + if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) { + foreach ($this->getAttribute('arguments') as $argument) { + array_shift($definition); + } + } + + $arguments = array(); + $pos = 0; + foreach ($definition as $param) { + $name = $this->normalizeName($param->name); + + if (array_key_exists($name, $parameters)) { + if (array_key_exists($pos, $parameters)) { + throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name'))); + } + + $arguments[] = $parameters[$name]; + unset($parameters[$name]); + } elseif (array_key_exists($pos, $parameters)) { + $arguments[] = $parameters[$pos]; + unset($parameters[$pos]); + ++$pos; + } elseif ($param->isDefaultValueAvailable()) { + $arguments[] = new Twig_Node_Expression_Constant($param->getDefaultValue(), -1); + } elseif ($param->isOptional()) { + break; + } else { + throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name'))); + } + } + + if (!empty($parameters)) { + throw new Twig_Error_Syntax(sprintf('Unknown argument%s "%s" for %s "%s".', count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $this->getAttribute('type'), $this->getAttribute('name'))); + } + + return $arguments; + } + + protected function normalizeName($name) + { + return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name)); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Conditional.php b/src/core/libs/Twig/Node/Expression/Conditional.php new file mode 100755 index 0000000..edcb1e2 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Conditional.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Conditional extends Twig_Node_Expression +{ + public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno) + { + parent::__construct(array('expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3), array(), $lineno); + } + + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('((') + ->subcompile($this->getNode('expr1')) + ->raw(') ? (') + ->subcompile($this->getNode('expr2')) + ->raw(') : (') + ->subcompile($this->getNode('expr3')) + ->raw('))') + ; + } +} diff --git a/src/core/libs/Twig/Node/Expression/Constant.php b/src/core/libs/Twig/Node/Expression/Constant.php new file mode 100755 index 0000000..a91dc69 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Constant.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Constant extends Twig_Node_Expression +{ + public function __construct($value, $lineno) + { + parent::__construct(array(), array('value' => $value), $lineno); + } + + public function compile(Twig_Compiler $compiler) + { + $compiler->repr($this->getAttribute('value')); + } +} diff --git a/src/core/libs/Twig/Node/Expression/ExtensionReference.php b/src/core/libs/Twig/Node/Expression/ExtensionReference.php new file mode 100755 index 0000000..00ac670 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/ExtensionReference.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents an extension call node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression +{ + public function __construct($name, $lineno, $tag = null) + { + parent::__construct(array(), array('name' => $name), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name'))); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Filter.php b/src/core/libs/Twig/Node/Expression/Filter.php new file mode 100755 index 0000000..207b062 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Filter.php @@ -0,0 +1,36 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call +{ + public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null) + { + parent::__construct(array('node' => $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag); + } + + public function compile(Twig_Compiler $compiler) + { + $name = $this->getNode('filter')->getAttribute('value'); + $filter = $compiler->getEnvironment()->getFilter($name); + + $this->setAttribute('name', $name); + $this->setAttribute('type', 'filter'); + $this->setAttribute('thing', $filter); + $this->setAttribute('needs_environment', $filter->needsEnvironment()); + $this->setAttribute('needs_context', $filter->needsContext()); + $this->setAttribute('arguments', $filter->getArguments()); + if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) { + $this->setAttribute('callable', $filter->getCallable()); + } + + $this->compileCallable($compiler); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Filter/Default.php b/src/core/libs/Twig/Node/Expression/Filter/Default.php new file mode 100755 index 0000000..1827c88 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Filter/Default.php @@ -0,0 +1,43 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Returns the value or the default value when it is undefined or empty. + * + * <pre> + * {{ var.foo|default('foo item on var is not defined') }} + * </pre> + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter +{ + public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null) + { + $default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getLine()), $arguments, $node->getLine()); + + if ('default' === $filterName->getAttribute('value') && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) { + $test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getLine()); + $false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getLine()); + + $node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getLine()); + } else { + $node = $default; + } + + parent::__construct($node, $filterName, $arguments, $lineno, $tag); + } + + public function compile(Twig_Compiler $compiler) + { + $compiler->subcompile($this->getNode('node')); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Function.php b/src/core/libs/Twig/Node/Expression/Function.php new file mode 100755 index 0000000..3e1f6b5 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Function.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Function extends Twig_Node_Expression_Call +{ + public function __construct($name, Twig_NodeInterface $arguments, $lineno) + { + parent::__construct(array('arguments' => $arguments), array('name' => $name), $lineno); + } + + public function compile(Twig_Compiler $compiler) + { + $name = $this->getAttribute('name'); + $function = $compiler->getEnvironment()->getFunction($name); + + $this->setAttribute('name', $name); + $this->setAttribute('type', 'function'); + $this->setAttribute('thing', $function); + $this->setAttribute('needs_environment', $function->needsEnvironment()); + $this->setAttribute('needs_context', $function->needsContext()); + $this->setAttribute('arguments', $function->getArguments()); + if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) { + $this->setAttribute('callable', $function->getCallable()); + } + + $this->compileCallable($compiler); + } +} diff --git a/src/core/libs/Twig/Node/Expression/GetAttr.php b/src/core/libs/Twig/Node/Expression/GetAttr.php new file mode 100755 index 0000000..55d9fcc --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/GetAttr.php @@ -0,0 +1,53 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_GetAttr extends Twig_Node_Expression +{ + public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type, $lineno) + { + parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno); + } + + public function compile(Twig_Compiler $compiler) + { + if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) { + $compiler->raw('twig_template_get_attributes($this, '); + } else { + $compiler->raw('$this->getAttribute('); + } + + if ($this->getAttribute('ignore_strict_check')) { + $this->getNode('node')->setAttribute('ignore_strict_check', true); + } + + $compiler->subcompile($this->getNode('node')); + + $compiler->raw(', ')->subcompile($this->getNode('attribute')); + + if (count($this->getNode('arguments')) || Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) { + $compiler->raw(', ')->subcompile($this->getNode('arguments')); + + if (Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) { + $compiler->raw(', ')->repr($this->getAttribute('type')); + } + + if ($this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) { + $compiler->raw(', '.($this->getAttribute('is_defined_test') ? 'true' : 'false')); + } + + if ($this->getAttribute('ignore_strict_check')) { + $compiler->raw(', '.($this->getAttribute('ignore_strict_check') ? 'true' : 'false')); + } + } + + $compiler->raw(')'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/MethodCall.php b/src/core/libs/Twig/Node/Expression/MethodCall.php new file mode 100755 index 0000000..620b02b --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/MethodCall.php @@ -0,0 +1,41 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_MethodCall extends Twig_Node_Expression +{ + public function __construct(Twig_Node_Expression $node, $method, Twig_Node_Expression_Array $arguments, $lineno) + { + parent::__construct(array('node' => $node, 'arguments' => $arguments), array('method' => $method, 'safe' => false), $lineno); + + if ($node instanceof Twig_Node_Expression_Name) { + $node->setAttribute('always_defined', true); + } + } + + public function compile(Twig_Compiler $compiler) + { + $compiler + ->subcompile($this->getNode('node')) + ->raw('->') + ->raw($this->getAttribute('method')) + ->raw('(') + ; + $first = true; + foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) { + if (!$first) { + $compiler->raw(', '); + } + $first = false; + + $compiler->subcompile($pair['value']); + } + $compiler->raw(')'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Name.php b/src/core/libs/Twig/Node/Expression/Name.php new file mode 100755 index 0000000..3b8fae0 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Name.php @@ -0,0 +1,88 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Name extends Twig_Node_Expression +{ + protected $specialVars = array( + '_self' => '$this', + '_context' => '$context', + '_charset' => '$this->env->getCharset()', + ); + + public function __construct($name, $lineno) + { + parent::__construct(array(), array('name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false), $lineno); + } + + public function compile(Twig_Compiler $compiler) + { + $name = $this->getAttribute('name'); + + if ($this->getAttribute('is_defined_test')) { + if ($this->isSpecial()) { + $compiler->repr(true); + } else { + $compiler->raw('array_key_exists(')->repr($name)->raw(', $context)'); + } + } elseif ($this->isSpecial()) { + $compiler->raw($this->specialVars[$name]); + } elseif ($this->getAttribute('always_defined')) { + $compiler + ->raw('$context[') + ->string($name) + ->raw(']') + ; + } else { + // remove the non-PHP 5.4 version when PHP 5.3 support is dropped + // as the non-optimized version is just a workaround for slow ternary operator + // when the context has a lot of variables + if (version_compare(phpversion(), '5.4.0RC1', '>=')) { + // PHP 5.4 ternary operator performance was optimized + $compiler + ->raw('(isset($context[') + ->string($name) + ->raw(']) ? $context[') + ->string($name) + ->raw('] : ') + ; + + if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) { + $compiler->raw('null)'); + } else { + $compiler->raw('$this->getContext($context, ')->string($name)->raw('))'); + } + } else { + $compiler + ->raw('$this->getContext($context, ') + ->string($name) + ; + + if ($this->getAttribute('ignore_strict_check')) { + $compiler->raw(', true'); + } + + $compiler + ->raw(')') + ; + } + } + } + + public function isSpecial() + { + return isset($this->specialVars[$this->getAttribute('name')]); + } + + public function isSimple() + { + return !$this->isSpecial() && !$this->getAttribute('is_defined_test'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Parent.php b/src/core/libs/Twig/Node/Expression/Parent.php new file mode 100755 index 0000000..dcf618c --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Parent.php @@ -0,0 +1,47 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a parent node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Expression_Parent extends Twig_Node_Expression +{ + public function __construct($name, $lineno, $tag = null) + { + parent::__construct(array(), array('output' => false, 'name' => $name), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + if ($this->getAttribute('output')) { + $compiler + ->addDebugInfo($this) + ->write("\$this->displayParentBlock(") + ->string($this->getAttribute('name')) + ->raw(", \$context, \$blocks);\n") + ; + } else { + $compiler + ->raw("\$this->renderParentBlock(") + ->string($this->getAttribute('name')) + ->raw(", \$context, \$blocks)") + ; + } + } +} diff --git a/src/core/libs/Twig/Node/Expression/TempName.php b/src/core/libs/Twig/Node/Expression/TempName.php new file mode 100755 index 0000000..e6b058e --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/TempName.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_TempName extends Twig_Node_Expression +{ + public function __construct($name, $lineno) + { + parent::__construct(array(), array('name' => $name), $lineno); + } + + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('$_') + ->raw($this->getAttribute('name')) + ->raw('_') + ; + } +} diff --git a/src/core/libs/Twig/Node/Expression/Test.php b/src/core/libs/Twig/Node/Expression/Test.php new file mode 100755 index 0000000..639f501 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Test.php @@ -0,0 +1,32 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Test extends Twig_Node_Expression_Call +{ + public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno) + { + parent::__construct(array('node' => $node, 'arguments' => $arguments), array('name' => $name), $lineno); + } + + public function compile(Twig_Compiler $compiler) + { + $name = $this->getAttribute('name'); + $test = $compiler->getEnvironment()->getTest($name); + + $this->setAttribute('name', $name); + $this->setAttribute('type', 'test'); + $this->setAttribute('thing', $test); + if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) { + $this->setAttribute('callable', $test->getCallable()); + } + + $this->compileCallable($compiler); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Test/Constant.php b/src/core/libs/Twig/Node/Expression/Test/Constant.php new file mode 100755 index 0000000..de55f5f --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Test/Constant.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Checks if a variable is the exact same value as a constant. + * + * <pre> + * {% if post.status is constant('Post::PUBLISHED') %} + * the status attribute is exactly the same as Post::PUBLISHED + * {% endif %} + * </pre> + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test +{ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('(') + ->subcompile($this->getNode('node')) + ->raw(' === constant(') + ; + + if ($this->getNode('arguments')->hasNode(1)) { + $compiler + ->raw('get_class(') + ->subcompile($this->getNode('arguments')->getNode(1)) + ->raw(')."::".') + ; + } + + $compiler + ->subcompile($this->getNode('arguments')->getNode(0)) + ->raw('))') + ; + } +} diff --git a/src/core/libs/Twig/Node/Expression/Test/Defined.php b/src/core/libs/Twig/Node/Expression/Test/Defined.php new file mode 100755 index 0000000..247b2e2 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Test/Defined.php @@ -0,0 +1,54 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Checks if a variable is defined in the current context. + * + * <pre> + * {# defined works with variable names and variable attributes #} + * {% if foo is defined %} + * {# ... #} + * {% endif %} + * </pre> + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test +{ + public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno) + { + parent::__construct($node, $name, $arguments, $lineno); + + if ($node instanceof Twig_Node_Expression_Name) { + $node->setAttribute('is_defined_test', true); + } elseif ($node instanceof Twig_Node_Expression_GetAttr) { + $node->setAttribute('is_defined_test', true); + + $this->changeIgnoreStrictCheck($node); + } else { + throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine()); + } + } + + protected function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node) + { + $node->setAttribute('ignore_strict_check', true); + + if ($node->getNode('node') instanceof Twig_Node_Expression_GetAttr) { + $this->changeIgnoreStrictCheck($node->getNode('node')); + } + } + + public function compile(Twig_Compiler $compiler) + { + $compiler->subcompile($this->getNode('node')); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Test/Divisibleby.php b/src/core/libs/Twig/Node/Expression/Test/Divisibleby.php new file mode 100755 index 0000000..0aceb53 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Test/Divisibleby.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Checks if a variable is divisible by a number. + * + * <pre> + * {% if loop.index is divisibleby(3) %} + * </pre> + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test +{ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('(0 == ') + ->subcompile($this->getNode('node')) + ->raw(' % ') + ->subcompile($this->getNode('arguments')->getNode(0)) + ->raw(')') + ; + } +} diff --git a/src/core/libs/Twig/Node/Expression/Test/Even.php b/src/core/libs/Twig/Node/Expression/Test/Even.php new file mode 100755 index 0000000..d7853e8 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Test/Even.php @@ -0,0 +1,32 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Checks if a number is even. + * + * <pre> + * {{ var is even }} + * </pre> + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test +{ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('(') + ->subcompile($this->getNode('node')) + ->raw(' % 2 == 0') + ->raw(')') + ; + } +} diff --git a/src/core/libs/Twig/Node/Expression/Test/Null.php b/src/core/libs/Twig/Node/Expression/Test/Null.php new file mode 100755 index 0000000..1c83825 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Test/Null.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Checks that a variable is null. + * + * <pre> + * {{ var is none }} + * </pre> + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test +{ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('(null === ') + ->subcompile($this->getNode('node')) + ->raw(')') + ; + } +} diff --git a/src/core/libs/Twig/Node/Expression/Test/Odd.php b/src/core/libs/Twig/Node/Expression/Test/Odd.php new file mode 100755 index 0000000..421c19e --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Test/Odd.php @@ -0,0 +1,32 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Checks if a number is odd. + * + * <pre> + * {{ var is odd }} + * </pre> + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test +{ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('(') + ->subcompile($this->getNode('node')) + ->raw(' % 2 == 1') + ->raw(')') + ; + } +} diff --git a/src/core/libs/Twig/Node/Expression/Test/Sameas.php b/src/core/libs/Twig/Node/Expression/Test/Sameas.php new file mode 100755 index 0000000..b48905e --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Test/Sameas.php @@ -0,0 +1,29 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Checks if a variable is the same as another one (=== in PHP). + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test +{ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->raw('(') + ->subcompile($this->getNode('node')) + ->raw(' === ') + ->subcompile($this->getNode('arguments')->getNode(0)) + ->raw(')') + ; + } +} diff --git a/src/core/libs/Twig/Node/Expression/Unary.php b/src/core/libs/Twig/Node/Expression/Unary.php new file mode 100755 index 0000000..c514388 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Unary.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression +{ + public function __construct(Twig_NodeInterface $node, $lineno) + { + parent::__construct(array('node' => $node), array(), $lineno); + } + + public function compile(Twig_Compiler $compiler) + { + $compiler->raw('('); + $this->operator($compiler); + $compiler + ->subcompile($this->getNode('node')) + ->raw(')') + ; + } + + abstract public function operator(Twig_Compiler $compiler); +} diff --git a/src/core/libs/Twig/Node/Expression/Unary/Neg.php b/src/core/libs/Twig/Node/Expression/Unary/Neg.php new file mode 100755 index 0000000..2a3937e --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Unary/Neg.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary +{ + public function operator(Twig_Compiler $compiler) + { + $compiler->raw('-'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Unary/Not.php b/src/core/libs/Twig/Node/Expression/Unary/Not.php new file mode 100755 index 0000000..f94073c --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Unary/Not.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary +{ + public function operator(Twig_Compiler $compiler) + { + $compiler->raw('!'); + } +} diff --git a/src/core/libs/Twig/Node/Expression/Unary/Pos.php b/src/core/libs/Twig/Node/Expression/Unary/Pos.php new file mode 100755 index 0000000..04edb52 --- /dev/null +++ b/src/core/libs/Twig/Node/Expression/Unary/Pos.php @@ -0,0 +1,18 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary +{ + public function operator(Twig_Compiler $compiler) + { + $compiler->raw('+'); + } +} diff --git a/src/core/libs/Twig/Node/Flush.php b/src/core/libs/Twig/Node/Flush.php new file mode 100755 index 0000000..0467ddc --- /dev/null +++ b/src/core/libs/Twig/Node/Flush.php @@ -0,0 +1,36 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a flush node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Flush extends Twig_Node +{ + public function __construct($lineno, $tag) + { + parent::__construct(array(), array(), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write("flush();\n") + ; + } +} diff --git a/src/core/libs/Twig/Node/For.php b/src/core/libs/Twig/Node/For.php new file mode 100755 index 0000000..d1ff371 --- /dev/null +++ b/src/core/libs/Twig/Node/For.php @@ -0,0 +1,112 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a for node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_For extends Twig_Node +{ + protected $loop; + + public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_Node_Expression $ifexpr = null, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $lineno, $tag = null) + { + $body = new Twig_Node(array($body, $this->loop = new Twig_Node_ForLoop($lineno, $tag))); + + if (null !== $ifexpr) { + $body = new Twig_Node_If(new Twig_Node(array($ifexpr, $body)), null, $lineno, $tag); + } + + parent::__construct(array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body, 'else' => $else), array('with_loop' => true, 'ifexpr' => null !== $ifexpr), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + // the (array) cast bypasses a PHP 5.2.6 bug + ->write("\$context['_parent'] = (array) \$context;\n") + ->write("\$context['_seq'] = twig_ensure_traversable(") + ->subcompile($this->getNode('seq')) + ->raw(");\n") + ; + + if (null !== $this->getNode('else')) { + $compiler->write("\$context['_iterated'] = false;\n"); + } + + if ($this->getAttribute('with_loop')) { + $compiler + ->write("\$context['loop'] = array(\n") + ->write(" 'parent' => \$context['_parent'],\n") + ->write(" 'index0' => 0,\n") + ->write(" 'index' => 1,\n") + ->write(" 'first' => true,\n") + ->write(");\n") + ; + + if (!$this->getAttribute('ifexpr')) { + $compiler + ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {\n") + ->indent() + ->write("\$length = count(\$context['_seq']);\n") + ->write("\$context['loop']['revindex0'] = \$length - 1;\n") + ->write("\$context['loop']['revindex'] = \$length;\n") + ->write("\$context['loop']['length'] = \$length;\n") + ->write("\$context['loop']['last'] = 1 === \$length;\n") + ->outdent() + ->write("}\n") + ; + } + } + + $this->loop->setAttribute('else', null !== $this->getNode('else')); + $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop')); + $this->loop->setAttribute('ifexpr', $this->getAttribute('ifexpr')); + + $compiler + ->write("foreach (\$context['_seq'] as ") + ->subcompile($this->getNode('key_target')) + ->raw(" => ") + ->subcompile($this->getNode('value_target')) + ->raw(") {\n") + ->indent() + ->subcompile($this->getNode('body')) + ->outdent() + ->write("}\n") + ; + + if (null !== $this->getNode('else')) { + $compiler + ->write("if (!\$context['_iterated']) {\n") + ->indent() + ->subcompile($this->getNode('else')) + ->outdent() + ->write("}\n") + ; + } + + $compiler->write("\$_parent = \$context['_parent'];\n"); + + // remove some "private" loop variables (needed for nested loops) + $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n"); + + // keep the values set in the inner context for variables defined in the outer context + $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n"); + } +} diff --git a/src/core/libs/Twig/Node/ForLoop.php b/src/core/libs/Twig/Node/ForLoop.php new file mode 100755 index 0000000..b884158 --- /dev/null +++ b/src/core/libs/Twig/Node/ForLoop.php @@ -0,0 +1,55 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Internal node used by the for node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_ForLoop extends Twig_Node +{ + public function __construct($lineno, $tag = null) + { + parent::__construct(array(), array('with_loop' => false, 'ifexpr' => false, 'else' => false), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + if ($this->getAttribute('else')) { + $compiler->write("\$context['_iterated'] = true;\n"); + } + + if ($this->getAttribute('with_loop')) { + $compiler + ->write("++\$context['loop']['index0'];\n") + ->write("++\$context['loop']['index'];\n") + ->write("\$context['loop']['first'] = false;\n") + ; + + if (!$this->getAttribute('ifexpr')) { + $compiler + ->write("if (isset(\$context['loop']['length'])) {\n") + ->indent() + ->write("--\$context['loop']['revindex0'];\n") + ->write("--\$context['loop']['revindex'];\n") + ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n") + ->outdent() + ->write("}\n") + ; + } + } + } +} diff --git a/src/core/libs/Twig/Node/If.php b/src/core/libs/Twig/Node/If.php new file mode 100755 index 0000000..b42d107 --- /dev/null +++ b/src/core/libs/Twig/Node/If.php @@ -0,0 +1,66 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents an if node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_If extends Twig_Node +{ + public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null) + { + parent::__construct(array('tests' => $tests, 'else' => $else), array(), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler->addDebugInfo($this); + for ($i = 0, $count = count($this->getNode('tests')); $i < $count; $i += 2) { + if ($i > 0) { + $compiler + ->outdent() + ->write("} elseif (") + ; + } else { + $compiler + ->write('if (') + ; + } + + $compiler + ->subcompile($this->getNode('tests')->getNode($i)) + ->raw(") {\n") + ->indent() + ->subcompile($this->getNode('tests')->getNode($i + 1)) + ; + } + + if ($this->hasNode('else') && null !== $this->getNode('else')) { + $compiler + ->outdent() + ->write("} else {\n") + ->indent() + ->subcompile($this->getNode('else')) + ; + } + + $compiler + ->outdent() + ->write("}\n"); + } +} diff --git a/src/core/libs/Twig/Node/Import.php b/src/core/libs/Twig/Node/Import.php new file mode 100755 index 0000000..99efc09 --- /dev/null +++ b/src/core/libs/Twig/Node/Import.php @@ -0,0 +1,50 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents an import node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Import extends Twig_Node +{ + public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $var, $lineno, $tag = null) + { + parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write('') + ->subcompile($this->getNode('var')) + ->raw(' = ') + ; + + if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) { + $compiler->raw("\$this"); + } else { + $compiler + ->raw('$this->env->loadTemplate(') + ->subcompile($this->getNode('expr')) + ->raw(")") + ; + } + + $compiler->raw(";\n"); + } +} diff --git a/src/core/libs/Twig/Node/Include.php b/src/core/libs/Twig/Node/Include.php new file mode 100755 index 0000000..ed4a375 --- /dev/null +++ b/src/core/libs/Twig/Node/Include.php @@ -0,0 +1,99 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents an include node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface +{ + public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) + { + parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (Boolean) $only, 'ignore_missing' => (Boolean) $ignoreMissing), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler->addDebugInfo($this); + + if ($this->getAttribute('ignore_missing')) { + $compiler + ->write("try {\n") + ->indent() + ; + } + + $this->addGetTemplate($compiler); + + $compiler->raw('->display('); + + $this->addTemplateArguments($compiler); + + $compiler->raw(");\n"); + + if ($this->getAttribute('ignore_missing')) { + $compiler + ->outdent() + ->write("} catch (Twig_Error_Loader \$e) {\n") + ->indent() + ->write("// ignore missing template\n") + ->outdent() + ->write("}\n\n") + ; + } + } + + protected function addGetTemplate(Twig_Compiler $compiler) + { + if ($this->getNode('expr') instanceof Twig_Node_Expression_Constant) { + $compiler + ->write("\$this->env->loadTemplate(") + ->subcompile($this->getNode('expr')) + ->raw(")") + ; + } else { + $compiler + ->write("\$template = \$this->env->resolveTemplate(") + ->subcompile($this->getNode('expr')) + ->raw(");\n") + ->write('$template') + ; + } + } + + protected function addTemplateArguments(Twig_Compiler $compiler) + { + if (false === $this->getAttribute('only')) { + if (null === $this->getNode('variables')) { + $compiler->raw('$context'); + } else { + $compiler + ->raw('array_merge($context, ') + ->subcompile($this->getNode('variables')) + ->raw(')') + ; + } + } else { + if (null === $this->getNode('variables')) { + $compiler->raw('array()'); + } else { + $compiler->subcompile($this->getNode('variables')); + } + } + } +} diff --git a/src/core/libs/Twig/Node/Macro.php b/src/core/libs/Twig/Node/Macro.php new file mode 100755 index 0000000..8991061 --- /dev/null +++ b/src/core/libs/Twig/Node/Macro.php @@ -0,0 +1,96 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a macro node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Macro extends Twig_Node +{ + public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null) + { + parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write(sprintf("public function get%s(", $this->getAttribute('name'))) + ; + + $count = count($this->getNode('arguments')); + $pos = 0; + foreach ($this->getNode('arguments') as $name => $default) { + $compiler + ->raw('$_'.$name.' = ') + ->subcompile($default) + ; + + if (++$pos < $count) { + $compiler->raw(', '); + } + } + + $compiler + ->raw(")\n") + ->write("{\n") + ->indent() + ; + + if (!count($this->getNode('arguments'))) { + $compiler->write("\$context = \$this->env->getGlobals();\n\n"); + } else { + $compiler + ->write("\$context = \$this->env->mergeGlobals(array(\n") + ->indent() + ; + + foreach ($this->getNode('arguments') as $name => $default) { + $compiler + ->write('') + ->string($name) + ->raw(' => $_'.$name) + ->raw(",\n") + ; + } + + $compiler + ->outdent() + ->write("));\n\n") + ; + } + + $compiler + ->write("\$blocks = array();\n\n") + ->write("ob_start();\n") + ->write("try {\n") + ->indent() + ->subcompile($this->getNode('body')) + ->outdent() + ->write("} catch (Exception \$e) {\n") + ->indent() + ->write("ob_end_clean();\n\n") + ->write("throw \$e;\n") + ->outdent() + ->write("}\n\n") + ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());\n") + ->outdent() + ->write("}\n\n") + ; + } +} diff --git a/src/core/libs/Twig/Node/Module.php b/src/core/libs/Twig/Node/Module.php new file mode 100755 index 0000000..3f80175 --- /dev/null +++ b/src/core/libs/Twig/Node/Module.php @@ -0,0 +1,383 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a module node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Module extends Twig_Node +{ + public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $filename) + { + // embedded templates are set as attributes so that they are only visited once by the visitors + parent::__construct(array('parent' => $parent, 'body' => $body, 'blocks' => $blocks, 'macros' => $macros, 'traits' => $traits), array('filename' => $filename, 'index' => null, 'embedded_templates' => $embeddedTemplates), 1); + } + + public function setIndex($index) + { + $this->setAttribute('index', $index); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $this->compileTemplate($compiler); + + foreach ($this->getAttribute('embedded_templates') as $template) { + $compiler->subcompile($template); + } + } + + protected function compileTemplate(Twig_Compiler $compiler) + { + if (!$this->getAttribute('index')) { + $compiler->write('<?php'); + } + + $this->compileClassHeader($compiler); + + if (count($this->getNode('blocks')) || count($this->getNode('traits')) || null === $this->getNode('parent') || $this->getNode('parent') instanceof Twig_Node_Expression_Constant) { + $this->compileConstructor($compiler); + } + + $this->compileGetParent($compiler); + + $this->compileDisplayHeader($compiler); + + $this->compileDisplayBody($compiler); + + $this->compileDisplayFooter($compiler); + + $compiler->subcompile($this->getNode('blocks')); + + $this->compileMacros($compiler); + + $this->compileGetTemplateName($compiler); + + $this->compileIsTraitable($compiler); + + $this->compileDebugInfo($compiler); + + $this->compileClassFooter($compiler); + } + + protected function compileGetParent(Twig_Compiler $compiler) + { + if (null === $this->getNode('parent')) { + return; + } + + $compiler + ->write("protected function doGetParent(array \$context)\n", "{\n") + ->indent() + ->write("return ") + ; + + if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) { + $compiler->subcompile($this->getNode('parent')); + } else { + $compiler + ->raw("\$this->env->resolveTemplate(") + ->subcompile($this->getNode('parent')) + ->raw(")") + ; + } + + $compiler + ->raw(";\n") + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileDisplayBody(Twig_Compiler $compiler) + { + $compiler->subcompile($this->getNode('body')); + + if (null !== $this->getNode('parent')) { + if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) { + $compiler->write("\$this->parent"); + } else { + $compiler->write("\$this->getParent(\$context)"); + } + $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n"); + } + } + + protected function compileClassHeader(Twig_Compiler $compiler) + { + $compiler + ->write("\n\n") + // if the filename contains */, add a blank to avoid a PHP parse error + ->write("/* ".str_replace('*/', '* /', $this->getAttribute('filename'))." */\n") + ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index'))) + ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass())) + ->write("{\n") + ->indent() + ; + } + + protected function compileConstructor(Twig_Compiler $compiler) + { + $compiler + ->write("public function __construct(Twig_Environment \$env)\n", "{\n") + ->indent() + ->write("parent::__construct(\$env);\n\n") + ; + + // parent + if (null === $this->getNode('parent')) { + $compiler->write("\$this->parent = false;\n\n"); + } elseif ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) { + $compiler + ->write("\$this->parent = \$this->env->loadTemplate(") + ->subcompile($this->getNode('parent')) + ->raw(");\n\n") + ; + } + + $countTraits = count($this->getNode('traits')); + if ($countTraits) { + // traits + foreach ($this->getNode('traits') as $i => $trait) { + $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i)); + + $compiler + ->addDebugInfo($trait->getNode('template')) + ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i)) + ->indent() + ->write("throw new Twig_Error_Runtime('Template \"'.") + ->subcompile($trait->getNode('template')) + ->raw(".'\" cannot be used as a trait.');\n") + ->outdent() + ->write("}\n") + ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i)) + ; + + foreach ($trait->getNode('targets') as $key => $value) { + $compiler + ->write(sprintf("if (!isset(\$_trait_%s_blocks[", $i)) + ->string($key) + ->raw("])) {\n") + ->indent() + ->write("throw new Twig_Error_Runtime(sprintf('Block ") + ->string($key) + ->raw(" is not defined in trait ") + ->subcompile($trait->getNode('template')) + ->raw(".'));\n") + ->outdent() + ->write("}\n\n") + + ->write(sprintf("\$_trait_%s_blocks[", $i)) + ->subcompile($value) + ->raw(sprintf("] = \$_trait_%s_blocks[", $i)) + ->string($key) + ->raw(sprintf("]; unset(\$_trait_%s_blocks[", $i)) + ->string($key) + ->raw("]);\n\n") + ; + } + } + + if ($countTraits > 1) { + $compiler + ->write("\$this->traits = array_merge(\n") + ->indent() + ; + + for ($i = 0; $i < $countTraits; $i++) { + $compiler + ->write(sprintf("\$_trait_%s_blocks".($i == $countTraits - 1 ? '' : ',')."\n", $i)) + ; + } + + $compiler + ->outdent() + ->write(");\n\n") + ; + } else { + $compiler + ->write("\$this->traits = \$_trait_0_blocks;\n\n") + ; + } + + $compiler + ->write("\$this->blocks = array_merge(\n") + ->indent() + ->write("\$this->traits,\n") + ->write("array(\n") + ; + } else { + $compiler + ->write("\$this->blocks = array(\n") + ; + } + + // blocks + $compiler + ->indent() + ; + + foreach ($this->getNode('blocks') as $name => $node) { + $compiler + ->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name)) + ; + } + + if ($countTraits) { + $compiler + ->outdent() + ->write(")\n") + ; + } + + $compiler + ->outdent() + ->write(");\n") + ->outdent() + ->write("}\n\n"); + ; + } + + protected function compileDisplayHeader(Twig_Compiler $compiler) + { + $compiler + ->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n") + ->indent() + ; + } + + protected function compileDisplayFooter(Twig_Compiler $compiler) + { + $compiler + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileClassFooter(Twig_Compiler $compiler) + { + $compiler + ->outdent() + ->write("}\n") + ; + } + + protected function compileMacros(Twig_Compiler $compiler) + { + $compiler->subcompile($this->getNode('macros')); + } + + protected function compileGetTemplateName(Twig_Compiler $compiler) + { + $compiler + ->write("public function getTemplateName()\n", "{\n") + ->indent() + ->write('return ') + ->repr($this->getAttribute('filename')) + ->raw(";\n") + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileIsTraitable(Twig_Compiler $compiler) + { + // A template can be used as a trait if: + // * it has no parent + // * it has no macros + // * it has no body + // + // Put another way, a template can be used as a trait if it + // only contains blocks and use statements. + $traitable = null === $this->getNode('parent') && 0 === count($this->getNode('macros')); + if ($traitable) { + if ($this->getNode('body') instanceof Twig_Node_Body) { + $nodes = $this->getNode('body')->getNode(0); + } else { + $nodes = $this->getNode('body'); + } + + if (!count($nodes)) { + $nodes = new Twig_Node(array($nodes)); + } + + foreach ($nodes as $node) { + if (!count($node)) { + continue; + } + + if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) { + continue; + } + + if ($node instanceof Twig_Node_BlockReference) { + continue; + } + + $traitable = false; + break; + } + } + + if ($traitable) { + return; + } + + $compiler + ->write("public function isTraitable()\n", "{\n") + ->indent() + ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false')) + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileDebugInfo(Twig_Compiler $compiler) + { + $compiler + ->write("public function getDebugInfo()\n", "{\n") + ->indent() + ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true)))) + ->outdent() + ->write("}\n") + ; + } + + protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var) + { + if ($node instanceof Twig_Node_Expression_Constant) { + $compiler + ->write(sprintf("%s = \$this->env->loadTemplate(", $var)) + ->subcompile($node) + ->raw(");\n") + ; + } else { + $compiler + ->write(sprintf("%s = ", $var)) + ->subcompile($node) + ->raw(";\n") + ->write(sprintf("if (!%s", $var)) + ->raw(" instanceof Twig_Template) {\n") + ->indent() + ->write(sprintf("%s = \$this->env->loadTemplate(%s);\n", $var, $var)) + ->outdent() + ->write("}\n") + ; + } + } +} diff --git a/src/core/libs/Twig/Node/Print.php b/src/core/libs/Twig/Node/Print.php new file mode 100755 index 0000000..b0c41d1 --- /dev/null +++ b/src/core/libs/Twig/Node/Print.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a node that outputs an expression. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface +{ + public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) + { + parent::__construct(array('expr' => $expr), array(), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write('echo ') + ->subcompile($this->getNode('expr')) + ->raw(";\n") + ; + } +} diff --git a/src/core/libs/Twig/Node/Sandbox.php b/src/core/libs/Twig/Node/Sandbox.php new file mode 100755 index 0000000..8cf3ed4 --- /dev/null +++ b/src/core/libs/Twig/Node/Sandbox.php @@ -0,0 +1,47 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a sandbox node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Sandbox extends Twig_Node +{ + public function __construct(Twig_NodeInterface $body, $lineno, $tag = null) + { + parent::__construct(array('body' => $body), array(), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write("\$sandbox = \$this->env->getExtension('sandbox');\n") + ->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n") + ->indent() + ->write("\$sandbox->enableSandbox();\n") + ->outdent() + ->write("}\n") + ->subcompile($this->getNode('body')) + ->write("if (!\$alreadySandboxed) {\n") + ->indent() + ->write("\$sandbox->disableSandbox();\n") + ->outdent() + ->write("}\n") + ; + } +} diff --git a/src/core/libs/Twig/Node/SandboxedModule.php b/src/core/libs/Twig/Node/SandboxedModule.php new file mode 100755 index 0000000..be1f5da --- /dev/null +++ b/src/core/libs/Twig/Node/SandboxedModule.php @@ -0,0 +1,60 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a module node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_SandboxedModule extends Twig_Node_Module +{ + protected $usedFilters; + protected $usedTags; + protected $usedFunctions; + + public function __construct(Twig_Node_Module $node, array $usedFilters, array $usedTags, array $usedFunctions) + { + parent::__construct($node->getNode('body'), $node->getNode('parent'), $node->getNode('blocks'), $node->getNode('macros'), $node->getNode('traits'), $node->getAttribute('embedded_templates'), $node->getAttribute('filename'), $node->getLine(), $node->getNodeTag()); + + $this->setAttribute('index', $node->getAttribute('index')); + + $this->usedFilters = $usedFilters; + $this->usedTags = $usedTags; + $this->usedFunctions = $usedFunctions; + } + + protected function compileDisplayBody(Twig_Compiler $compiler) + { + $compiler->write("\$this->checkSecurity();\n"); + + parent::compileDisplayBody($compiler); + } + + protected function compileDisplayFooter(Twig_Compiler $compiler) + { + parent::compileDisplayFooter($compiler); + + $compiler + ->write("protected function checkSecurity()\n", "{\n") + ->indent() + ->write("\$this->env->getExtension('sandbox')->checkSecurity(\n") + ->indent() + ->write(!$this->usedTags ? "array(),\n" : "array('".implode('\', \'', $this->usedTags)."'),\n") + ->write(!$this->usedFilters ? "array(),\n" : "array('".implode('\', \'', $this->usedFilters)."'),\n") + ->write(!$this->usedFunctions ? "array()\n" : "array('".implode('\', \'', $this->usedFunctions)."')\n") + ->outdent() + ->write(");\n") + ->outdent() + ->write("}\n\n") + ; + } +} diff --git a/src/core/libs/Twig/Node/SandboxedPrint.php b/src/core/libs/Twig/Node/SandboxedPrint.php new file mode 100755 index 0000000..73dfaa9 --- /dev/null +++ b/src/core/libs/Twig/Node/SandboxedPrint.php @@ -0,0 +1,59 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Twig_Node_SandboxedPrint adds a check for the __toString() method + * when the variable is an object and the sandbox is activated. + * + * When there is a simple Print statement, like {{ article }}, + * and if the sandbox is enabled, we need to check that the __toString() + * method is allowed if 'article' is an object. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_SandboxedPrint extends Twig_Node_Print +{ + public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) + { + parent::__construct($expr, $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write('echo $this->env->getExtension(\'sandbox\')->ensureToStringAllowed(') + ->subcompile($this->getNode('expr')) + ->raw(");\n") + ; + } + + /** + * Removes node filters. + * + * This is mostly needed when another visitor adds filters (like the escaper one). + * + * @param Twig_Node $node A Node + */ + protected function removeNodeFilter($node) + { + if ($node instanceof Twig_Node_Expression_Filter) { + return $this->removeNodeFilter($node->getNode('node')); + } + + return $node; + } +} diff --git a/src/core/libs/Twig/Node/Set.php b/src/core/libs/Twig/Node/Set.php new file mode 100755 index 0000000..4c9c16c --- /dev/null +++ b/src/core/libs/Twig/Node/Set.php @@ -0,0 +1,101 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a set node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Set extends Twig_Node +{ + public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null) + { + parent::__construct(array('names' => $names, 'values' => $values), array('capture' => $capture, 'safe' => false), $lineno, $tag); + + /* + * Optimizes the node when capture is used for a large block of text. + * + * {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig_Markup("foo"); + */ + if ($this->getAttribute('capture')) { + $this->setAttribute('safe', true); + + $values = $this->getNode('values'); + if ($values instanceof Twig_Node_Text) { + $this->setNode('values', new Twig_Node_Expression_Constant($values->getAttribute('data'), $values->getLine())); + $this->setAttribute('capture', false); + } + } + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler->addDebugInfo($this); + + if (count($this->getNode('names')) > 1) { + $compiler->write('list('); + foreach ($this->getNode('names') as $idx => $node) { + if ($idx) { + $compiler->raw(', '); + } + + $compiler->subcompile($node); + } + $compiler->raw(')'); + } else { + if ($this->getAttribute('capture')) { + $compiler + ->write("ob_start();\n") + ->subcompile($this->getNode('values')) + ; + } + + $compiler->subcompile($this->getNode('names'), false); + + if ($this->getAttribute('capture')) { + $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())"); + } + } + + if (!$this->getAttribute('capture')) { + $compiler->raw(' = '); + + if (count($this->getNode('names')) > 1) { + $compiler->write('array('); + foreach ($this->getNode('values') as $idx => $value) { + if ($idx) { + $compiler->raw(', '); + } + + $compiler->subcompile($value); + } + $compiler->raw(')'); + } else { + if ($this->getAttribute('safe')) { + $compiler + ->raw("('' === \$tmp = ") + ->subcompile($this->getNode('values')) + ->raw(") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())") + ; + } else { + $compiler->subcompile($this->getNode('values')); + } + } + } + + $compiler->raw(";\n"); + } +} diff --git a/src/core/libs/Twig/Node/SetTemp.php b/src/core/libs/Twig/Node/SetTemp.php new file mode 100755 index 0000000..3bdd1cb --- /dev/null +++ b/src/core/libs/Twig/Node/SetTemp.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +class Twig_Node_SetTemp extends Twig_Node +{ + public function __construct($name, $lineno) + { + parent::__construct(array(), array('name' => $name), $lineno); + } + + public function compile(Twig_Compiler $compiler) + { + $name = $this->getAttribute('name'); + $compiler + ->addDebugInfo($this) + ->write('if (isset($context[') + ->string($name) + ->raw('])) { $_') + ->raw($name) + ->raw('_ = $context[') + ->repr($name) + ->raw(']; } else { $_') + ->raw($name) + ->raw("_ = null; }\n") + ; + } +} diff --git a/src/core/libs/Twig/Node/Spaceless.php b/src/core/libs/Twig/Node/Spaceless.php new file mode 100755 index 0000000..7555fa0 --- /dev/null +++ b/src/core/libs/Twig/Node/Spaceless.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a spaceless node. + * + * It removes spaces between HTML tags. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Spaceless extends Twig_Node +{ + public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless') + { + parent::__construct(array('body' => $body), array(), $lineno, $tag); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write("ob_start();\n") + ->subcompile($this->getNode('body')) + ->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n") + ; + } +} diff --git a/src/core/libs/Twig/Node/Text.php b/src/core/libs/Twig/Node/Text.php new file mode 100755 index 0000000..21bdcea --- /dev/null +++ b/src/core/libs/Twig/Node/Text.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a text node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface +{ + public function __construct($data, $lineno) + { + parent::__construct(array(), array('data' => $data), $lineno); + } + + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write('echo ') + ->string($this->getAttribute('data')) + ->raw(";\n") + ; + } +} diff --git a/src/core/libs/Twig/NodeInterface.php b/src/core/libs/Twig/NodeInterface.php new file mode 100755 index 0000000..f0ef725 --- /dev/null +++ b/src/core/libs/Twig/NodeInterface.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a node in the AST. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_NodeInterface extends Countable, IteratorAggregate +{ + /** + * Compiles the node to PHP. + * + * @param Twig_Compiler A Twig_Compiler instance + */ + public function compile(Twig_Compiler $compiler); + + public function getLine(); + + public function getNodeTag(); +} diff --git a/src/core/libs/Twig/NodeOutputInterface.php b/src/core/libs/Twig/NodeOutputInterface.php new file mode 100755 index 0000000..22172c0 --- /dev/null +++ b/src/core/libs/Twig/NodeOutputInterface.php @@ -0,0 +1,19 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a displayable node in the AST. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface Twig_NodeOutputInterface +{ +} diff --git a/src/core/libs/Twig/NodeTraverser.php b/src/core/libs/Twig/NodeTraverser.php new file mode 100755 index 0000000..aacaf29 --- /dev/null +++ b/src/core/libs/Twig/NodeTraverser.php @@ -0,0 +1,88 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Twig_NodeTraverser is a node traverser. + * + * It visits all nodes and their children and calls the given visitor for each. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_NodeTraverser +{ + protected $env; + protected $visitors; + + /** + * Constructor. + * + * @param Twig_Environment $env A Twig_Environment instance + * @param Twig_NodeVisitorInterface[] $visitors An array of Twig_NodeVisitorInterface instances + */ + public function __construct(Twig_Environment $env, array $visitors = array()) + { + $this->env = $env; + $this->visitors = array(); + foreach ($visitors as $visitor) { + $this->addVisitor($visitor); + } + } + + /** + * Adds a visitor. + * + * @param Twig_NodeVisitorInterface $visitor A Twig_NodeVisitorInterface instance + */ + public function addVisitor(Twig_NodeVisitorInterface $visitor) + { + if (!isset($this->visitors[$visitor->getPriority()])) { + $this->visitors[$visitor->getPriority()] = array(); + } + + $this->visitors[$visitor->getPriority()][] = $visitor; + } + + /** + * Traverses a node and calls the registered visitors. + * + * @param Twig_NodeInterface $node A Twig_NodeInterface instance + */ + public function traverse(Twig_NodeInterface $node) + { + ksort($this->visitors); + foreach ($this->visitors as $visitors) { + foreach ($visitors as $visitor) { + $node = $this->traverseForVisitor($visitor, $node); + } + } + + return $node; + } + + protected function traverseForVisitor(Twig_NodeVisitorInterface $visitor, Twig_NodeInterface $node = null) + { + if (null === $node) { + return null; + } + + $node = $visitor->enterNode($node, $this->env); + + foreach ($node as $k => $n) { + if (false !== $n = $this->traverseForVisitor($visitor, $n)) { + $node->setNode($k, $n); + } else { + $node->removeNode($k); + } + } + + return $visitor->leaveNode($node, $this->env); + } +} diff --git a/src/core/libs/Twig/NodeVisitor/Escaper.php b/src/core/libs/Twig/NodeVisitor/Escaper.php new file mode 100755 index 0000000..cc4b3d7 --- /dev/null +++ b/src/core/libs/Twig/NodeVisitor/Escaper.php @@ -0,0 +1,167 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Twig_NodeVisitor_Escaper implements output escaping. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface +{ + protected $statusStack = array(); + protected $blocks = array(); + protected $safeAnalysis; + protected $traverser; + protected $defaultStrategy = false; + protected $safeVars = array(); + + public function __construct() + { + $this->safeAnalysis = new Twig_NodeVisitor_SafeAnalysis(); + } + + /** + * Called before child nodes are visited. + * + * @param Twig_NodeInterface $node The node to visit + * @param Twig_Environment $env The Twig environment instance + * + * @return Twig_NodeInterface The modified node + */ + public function enterNode(Twig_NodeInterface $node, Twig_Environment $env) + { + if ($node instanceof Twig_Node_Module) { + if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) { + $this->defaultStrategy = $defaultStrategy; + } + $this->safeVars = array(); + } elseif ($node instanceof Twig_Node_AutoEscape) { + $this->statusStack[] = $node->getAttribute('value'); + } elseif ($node instanceof Twig_Node_Block) { + $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env); + } elseif ($node instanceof Twig_Node_Import) { + $this->safeVars[] = $node->getNode('var')->getAttribute('name'); + } + + return $node; + } + + /** + * Called after child nodes are visited. + * + * @param Twig_NodeInterface $node The node to visit + * @param Twig_Environment $env The Twig environment instance + * + * @return Twig_NodeInterface The modified node + */ + public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env) + { + if ($node instanceof Twig_Node_Module) { + $this->defaultStrategy = false; + $this->safeVars = array(); + } elseif ($node instanceof Twig_Node_Expression_Filter) { + return $this->preEscapeFilterNode($node, $env); + } elseif ($node instanceof Twig_Node_Print) { + return $this->escapePrintNode($node, $env, $this->needEscaping($env)); + } + + if ($node instanceof Twig_Node_AutoEscape || $node instanceof Twig_Node_Block) { + array_pop($this->statusStack); + } elseif ($node instanceof Twig_Node_BlockReference) { + $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env); + } + + return $node; + } + + protected function escapePrintNode(Twig_Node_Print $node, Twig_Environment $env, $type) + { + if (false === $type) { + return $node; + } + + $expression = $node->getNode('expr'); + + if ($this->isSafeFor($type, $expression, $env)) { + return $node; + } + + $class = get_class($node); + + return new $class( + $this->getEscaperFilter($type, $expression), + $node->getLine() + ); + } + + protected function preEscapeFilterNode(Twig_Node_Expression_Filter $filter, Twig_Environment $env) + { + $name = $filter->getNode('filter')->getAttribute('value'); + + $type = $env->getFilter($name)->getPreEscape(); + if (null === $type) { + return $filter; + } + + $node = $filter->getNode('node'); + if ($this->isSafeFor($type, $node, $env)) { + return $filter; + } + + $filter->setNode('node', $this->getEscaperFilter($type, $node)); + + return $filter; + } + + protected function isSafeFor($type, Twig_NodeInterface $expression, $env) + { + $safe = $this->safeAnalysis->getSafe($expression); + + if (null === $safe) { + if (null === $this->traverser) { + $this->traverser = new Twig_NodeTraverser($env, array($this->safeAnalysis)); + } + + $this->safeAnalysis->setSafeVars($this->safeVars); + + $this->traverser->traverse($expression); + $safe = $this->safeAnalysis->getSafe($expression); + } + + return in_array($type, $safe) || in_array('all', $safe); + } + + protected function needEscaping(Twig_Environment $env) + { + if (count($this->statusStack)) { + return $this->statusStack[count($this->statusStack) - 1]; + } + + return $this->defaultStrategy ? $this->defaultStrategy : false; + } + + protected function getEscaperFilter($type, Twig_NodeInterface $node) + { + $line = $node->getLine(); + $name = new Twig_Node_Expression_Constant('escape', $line); + $args = new Twig_Node(array(new Twig_Node_Expression_Constant((string) $type, $line), new Twig_Node_Expression_Constant(null, $line), new Twig_Node_Expression_Constant(true, $line))); + + return new Twig_Node_Expression_Filter($node, $name, $args, $line); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 0; + } +} diff --git a/src/core/libs/Twig/NodeVisitor/Optimizer.php b/src/core/libs/Twig/NodeVisitor/Optimizer.php new file mode 100755 index 0000000..5bf8eb0 --- /dev/null +++ b/src/core/libs/Twig/NodeVisitor/Optimizer.php @@ -0,0 +1,246 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Twig_NodeVisitor_Optimizer tries to optimizes the AST. + * + * This visitor is always the last registered one. + * + * You can configure which optimizations you want to activate via the + * optimizer mode. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface +{ + const OPTIMIZE_ALL = -1; + const OPTIMIZE_NONE = 0; + const OPTIMIZE_FOR = 2; + const OPTIMIZE_RAW_FILTER = 4; + const OPTIMIZE_VAR_ACCESS = 8; + + protected $loops = array(); + protected $optimizers; + protected $prependedNodes = array(); + protected $inABody = false; + + /** + * Constructor. + * + * @param integer $optimizers The optimizer mode + */ + public function __construct($optimizers = -1) + { + if (!is_int($optimizers) || $optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_VAR_ACCESS)) { + throw new InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers)); + } + + $this->optimizers = $optimizers; + } + + /** + * {@inheritdoc} + */ + public function enterNode(Twig_NodeInterface $node, Twig_Environment $env) + { + if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { + $this->enterOptimizeFor($node, $env); + } + + if (!version_compare(phpversion(), '5.4.0RC1', '>=') && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) { + if ($this->inABody) { + if (!$node instanceof Twig_Node_Expression) { + if (get_class($node) !== 'Twig_Node') { + array_unshift($this->prependedNodes, array()); + } + } else { + $node = $this->optimizeVariables($node, $env); + } + } elseif ($node instanceof Twig_Node_Body) { + $this->inABody = true; + } + } + + return $node; + } + + /** + * {@inheritdoc} + */ + public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env) + { + $expression = $node instanceof Twig_Node_Expression; + + if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { + $this->leaveOptimizeFor($node, $env); + } + + if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) { + $node = $this->optimizeRawFilter($node, $env); + } + + $node = $this->optimizePrintNode($node, $env); + + if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) { + if ($node instanceof Twig_Node_Body) { + $this->inABody = false; + } elseif ($this->inABody) { + if (!$expression && get_class($node) !== 'Twig_Node' && $prependedNodes = array_shift($this->prependedNodes)) { + $nodes = array(); + foreach (array_unique($prependedNodes) as $name) { + $nodes[] = new Twig_Node_SetTemp($name, $node->getLine()); + } + + $nodes[] = $node; + $node = new Twig_Node($nodes); + } + } + } + + return $node; + } + + protected function optimizeVariables(Twig_NodeInterface $node, Twig_Environment $env) + { + if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) { + $this->prependedNodes[0][] = $node->getAttribute('name'); + + return new Twig_Node_Expression_TempName($node->getAttribute('name'), $node->getLine()); + } + + return $node; + } + + /** + * Optimizes print nodes. + * + * It replaces: + * + * * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()" + * + * @param Twig_NodeInterface $node A Node + * @param Twig_Environment $env The current Twig environment + */ + protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env) + { + if (!$node instanceof Twig_Node_Print) { + return $node; + } + + if ( + $node->getNode('expr') instanceof Twig_Node_Expression_BlockReference || + $node->getNode('expr') instanceof Twig_Node_Expression_Parent + ) { + $node->getNode('expr')->setAttribute('output', true); + + return $node->getNode('expr'); + } + + return $node; + } + + /** + * Removes "raw" filters. + * + * @param Twig_NodeInterface $node A Node + * @param Twig_Environment $env The current Twig environment + */ + protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env) + { + if ($node instanceof Twig_Node_Expression_Filter && 'raw' == $node->getNode('filter')->getAttribute('value')) { + return $node->getNode('node'); + } + + return $node; + } + + /** + * Optimizes "for" tag by removing the "loop" variable creation whenever possible. + * + * @param Twig_NodeInterface $node A Node + * @param Twig_Environment $env The current Twig environment + */ + protected function enterOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env) + { + if ($node instanceof Twig_Node_For) { + // disable the loop variable by default + $node->setAttribute('with_loop', false); + array_unshift($this->loops, $node); + } elseif (!$this->loops) { + // we are outside a loop + return; + } + + // when do we need to add the loop variable back? + + // the loop variable is referenced for the current loop + elseif ($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) { + $this->addLoopToCurrent(); + } + + // block reference + elseif ($node instanceof Twig_Node_BlockReference || $node instanceof Twig_Node_Expression_BlockReference) { + $this->addLoopToCurrent(); + } + + // include without the only attribute + elseif ($node instanceof Twig_Node_Include && !$node->getAttribute('only')) { + $this->addLoopToAll(); + } + + // the loop variable is referenced via an attribute + elseif ($node instanceof Twig_Node_Expression_GetAttr + && (!$node->getNode('attribute') instanceof Twig_Node_Expression_Constant + || 'parent' === $node->getNode('attribute')->getAttribute('value') + ) + && (true === $this->loops[0]->getAttribute('with_loop') + || ($node->getNode('node') instanceof Twig_Node_Expression_Name + && 'loop' === $node->getNode('node')->getAttribute('name') + ) + ) + ) { + $this->addLoopToAll(); + } + } + + /** + * Optimizes "for" tag by removing the "loop" variable creation whenever possible. + * + * @param Twig_NodeInterface $node A Node + * @param Twig_Environment $env The current Twig environment + */ + protected function leaveOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env) + { + if ($node instanceof Twig_Node_For) { + array_shift($this->loops); + } + } + + protected function addLoopToCurrent() + { + $this->loops[0]->setAttribute('with_loop', true); + } + + protected function addLoopToAll() + { + foreach ($this->loops as $loop) { + $loop->setAttribute('with_loop', true); + } + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 255; + } +} diff --git a/src/core/libs/Twig/NodeVisitor/SafeAnalysis.php b/src/core/libs/Twig/NodeVisitor/SafeAnalysis.php new file mode 100755 index 0000000..a5d06de --- /dev/null +++ b/src/core/libs/Twig/NodeVisitor/SafeAnalysis.php @@ -0,0 +1,139 @@ +<?php + +class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface +{ + protected $data = array(); + protected $safeVars = array(); + + public function setSafeVars($safeVars) + { + $this->safeVars = $safeVars; + } + + public function getSafe(Twig_NodeInterface $node) + { + $hash = spl_object_hash($node); + if (!isset($this->data[$hash])) { + return; + } + + foreach ($this->data[$hash] as $bucket) { + if ($bucket['key'] !== $node) { + continue; + } + + if (in_array('html_attr', $bucket['value'])) { + $bucket['value'][] = 'html'; + } + + return $bucket['value']; + } + } + + protected function setSafe(Twig_NodeInterface $node, array $safe) + { + $hash = spl_object_hash($node); + if (isset($this->data[$hash])) { + foreach ($this->data[$hash] as &$bucket) { + if ($bucket['key'] === $node) { + $bucket['value'] = $safe; + + return; + } + } + } + $this->data[$hash][] = array( + 'key' => $node, + 'value' => $safe, + ); + } + + public function enterNode(Twig_NodeInterface $node, Twig_Environment $env) + { + return $node; + } + + public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env) + { + if ($node instanceof Twig_Node_Expression_Constant) { + // constants are marked safe for all + $this->setSafe($node, array('all')); + } elseif ($node instanceof Twig_Node_Expression_BlockReference) { + // blocks are safe by definition + $this->setSafe($node, array('all')); + } elseif ($node instanceof Twig_Node_Expression_Parent) { + // parent block is safe by definition + $this->setSafe($node, array('all')); + } elseif ($node instanceof Twig_Node_Expression_Conditional) { + // intersect safeness of both operands + $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3'))); + $this->setSafe($node, $safe); + } elseif ($node instanceof Twig_Node_Expression_Filter) { + // filter expression is safe when the filter is safe + $name = $node->getNode('filter')->getAttribute('value'); + $args = $node->getNode('arguments'); + if (false !== $filter = $env->getFilter($name)) { + $safe = $filter->getSafe($args); + if (null === $safe) { + $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety()); + } + $this->setSafe($node, $safe); + } else { + $this->setSafe($node, array()); + } + } elseif ($node instanceof Twig_Node_Expression_Function) { + // function expression is safe when the function is safe + $name = $node->getAttribute('name'); + $args = $node->getNode('arguments'); + $function = $env->getFunction($name); + if (false !== $function) { + $this->setSafe($node, $function->getSafe($args)); + } else { + $this->setSafe($node, array()); + } + } elseif ($node instanceof Twig_Node_Expression_MethodCall) { + if ($node->getAttribute('safe')) { + $this->setSafe($node, array('all')); + } else { + $this->setSafe($node, array()); + } + } elseif ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name) { + $name = $node->getNode('node')->getAttribute('name'); + // attributes on template instances are safe + if ('_self' == $name || in_array($name, $this->safeVars)) { + $this->setSafe($node, array('all')); + } else { + $this->setSafe($node, array()); + } + } else { + $this->setSafe($node, array()); + } + + return $node; + } + + protected function intersectSafe(array $a = null, array $b = null) + { + if (null === $a || null === $b) { + return array(); + } + + if (in_array('all', $a)) { + return $b; + } + + if (in_array('all', $b)) { + return $a; + } + + return array_intersect($a, $b); + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 0; + } +} diff --git a/src/core/libs/Twig/NodeVisitor/Sandbox.php b/src/core/libs/Twig/NodeVisitor/Sandbox.php new file mode 100755 index 0000000..fb27045 --- /dev/null +++ b/src/core/libs/Twig/NodeVisitor/Sandbox.php @@ -0,0 +1,92 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Twig_NodeVisitor_Sandbox implements sandboxing. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface +{ + protected $inAModule = false; + protected $tags; + protected $filters; + protected $functions; + + /** + * Called before child nodes are visited. + * + * @param Twig_NodeInterface $node The node to visit + * @param Twig_Environment $env The Twig environment instance + * + * @return Twig_NodeInterface The modified node + */ + public function enterNode(Twig_NodeInterface $node, Twig_Environment $env) + { + if ($node instanceof Twig_Node_Module) { + $this->inAModule = true; + $this->tags = array(); + $this->filters = array(); + $this->functions = array(); + + return $node; + } elseif ($this->inAModule) { + // look for tags + if ($node->getNodeTag()) { + $this->tags[] = $node->getNodeTag(); + } + + // look for filters + if ($node instanceof Twig_Node_Expression_Filter) { + $this->filters[] = $node->getNode('filter')->getAttribute('value'); + } + + // look for functions + if ($node instanceof Twig_Node_Expression_Function) { + $this->functions[] = $node->getAttribute('name'); + } + + // wrap print to check __toString() calls + if ($node instanceof Twig_Node_Print) { + return new Twig_Node_SandboxedPrint($node->getNode('expr'), $node->getLine(), $node->getNodeTag()); + } + } + + return $node; + } + + /** + * Called after child nodes are visited. + * + * @param Twig_NodeInterface $node The node to visit + * @param Twig_Environment $env The Twig environment instance + * + * @return Twig_NodeInterface The modified node + */ + public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env) + { + if ($node instanceof Twig_Node_Module) { + $this->inAModule = false; + + return new Twig_Node_SandboxedModule($node, array_unique($this->filters), array_unique($this->tags), array_unique($this->functions)); + } + + return $node; + } + + /** + * {@inheritdoc} + */ + public function getPriority() + { + return 0; + } +} diff --git a/src/core/libs/Twig/NodeVisitorInterface.php b/src/core/libs/Twig/NodeVisitorInterface.php new file mode 100755 index 0000000..f33c13f --- /dev/null +++ b/src/core/libs/Twig/NodeVisitorInterface.php @@ -0,0 +1,47 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Twig_NodeVisitorInterface is the interface the all node visitor classes must implement. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface Twig_NodeVisitorInterface +{ + /** + * Called before child nodes are visited. + * + * @param Twig_NodeInterface $node The node to visit + * @param Twig_Environment $env The Twig environment instance + * + * @return Twig_NodeInterface The modified node + */ + public function enterNode(Twig_NodeInterface $node, Twig_Environment $env); + + /** + * Called after child nodes are visited. + * + * @param Twig_NodeInterface $node The node to visit + * @param Twig_Environment $env The Twig environment instance + * + * @return Twig_NodeInterface|false The modified node or false if the node must be removed + */ + public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env); + + /** + * Returns the priority for this visitor. + * + * Priority should be between -10 and 10 (0 is the default). + * + * @return integer The priority level + */ + public function getPriority(); +} diff --git a/src/core/libs/Twig/Parser.php b/src/core/libs/Twig/Parser.php new file mode 100755 index 0000000..549ce2b --- /dev/null +++ b/src/core/libs/Twig/Parser.php @@ -0,0 +1,390 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Default parser implementation. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Parser implements Twig_ParserInterface +{ + protected $stack = array(); + protected $stream; + protected $parent; + protected $handlers; + protected $visitors; + protected $expressionParser; + protected $blocks; + protected $blockStack; + protected $macros; + protected $env; + protected $reservedMacroNames; + protected $importedSymbols; + protected $traits; + protected $embeddedTemplates = array(); + + /** + * Constructor. + * + * @param Twig_Environment $env A Twig_Environment instance + */ + public function __construct(Twig_Environment $env) + { + $this->env = $env; + } + + public function getEnvironment() + { + return $this->env; + } + + public function getVarName() + { + return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); + } + + public function getFilename() + { + return $this->stream->getFilename(); + } + + /** + * {@inheritdoc} + */ + public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false) + { + // push all variables into the stack to keep the current state of the parser + $vars = get_object_vars($this); + unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser']); + $this->stack[] = $vars; + + // tag handlers + if (null === $this->handlers) { + $this->handlers = $this->env->getTokenParsers(); + $this->handlers->setParser($this); + } + + // node visitors + if (null === $this->visitors) { + $this->visitors = $this->env->getNodeVisitors(); + } + + if (null === $this->expressionParser) { + $this->expressionParser = new Twig_ExpressionParser($this, $this->env->getUnaryOperators(), $this->env->getBinaryOperators()); + } + + $this->stream = $stream; + $this->parent = null; + $this->blocks = array(); + $this->macros = array(); + $this->traits = array(); + $this->blockStack = array(); + $this->importedSymbols = array(array()); + $this->embeddedTemplates = array(); + + try { + $body = $this->subparse($test, $dropNeedle); + + if (null !== $this->parent) { + if (null === $body = $this->filterBodyNodes($body)) { + $body = new Twig_Node(); + } + } + } catch (Twig_Error_Syntax $e) { + if (!$e->getTemplateFile()) { + $e->setTemplateFile($this->getFilename()); + } + + if (!$e->getTemplateLine()) { + $e->setTemplateLine($this->stream->getCurrent()->getLine()); + } + + throw $e; + } + + $node = new Twig_Node_Module(new Twig_Node_Body(array($body)), $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), new Twig_Node($this->traits), $this->embeddedTemplates, $this->getFilename()); + + $traverser = new Twig_NodeTraverser($this->env, $this->visitors); + + $node = $traverser->traverse($node); + + // restore previous stack so previous parse() call can resume working + foreach (array_pop($this->stack) as $key => $val) { + $this->$key = $val; + } + + return $node; + } + + public function subparse($test, $dropNeedle = false) + { + $lineno = $this->getCurrentToken()->getLine(); + $rv = array(); + while (!$this->stream->isEOF()) { + switch ($this->getCurrentToken()->getType()) { + case Twig_Token::TEXT_TYPE: + $token = $this->stream->next(); + $rv[] = new Twig_Node_Text($token->getValue(), $token->getLine()); + break; + + case Twig_Token::VAR_START_TYPE: + $token = $this->stream->next(); + $expr = $this->expressionParser->parseExpression(); + $this->stream->expect(Twig_Token::VAR_END_TYPE); + $rv[] = new Twig_Node_Print($expr, $token->getLine()); + break; + + case Twig_Token::BLOCK_START_TYPE: + $this->stream->next(); + $token = $this->getCurrentToken(); + + if ($token->getType() !== Twig_Token::NAME_TYPE) { + throw new Twig_Error_Syntax('A block must start with a tag name', $token->getLine(), $this->getFilename()); + } + + if (null !== $test && call_user_func($test, $token)) { + if ($dropNeedle) { + $this->stream->next(); + } + + if (1 === count($rv)) { + return $rv[0]; + } + + return new Twig_Node($rv, array(), $lineno); + } + + $subparser = $this->handlers->getTokenParser($token->getValue()); + if (null === $subparser) { + if (null !== $test) { + $error = sprintf('Unexpected tag name "%s"', $token->getValue()); + if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) { + $error .= sprintf(' (expecting closing tag for the "%s" tag defined near line %s)', $test[0]->getTag(), $lineno); + } + + throw new Twig_Error_Syntax($error, $token->getLine(), $this->getFilename()); + } + + $message = sprintf('Unknown tag name "%s"', $token->getValue()); + if ($alternatives = $this->env->computeAlternatives($token->getValue(), array_keys($this->env->getTags()))) { + $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives)); + } + + throw new Twig_Error_Syntax($message, $token->getLine(), $this->getFilename()); + } + + $this->stream->next(); + + $node = $subparser->parse($token); + if (null !== $node) { + $rv[] = $node; + } + break; + + default: + throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', 0, $this->getFilename()); + } + } + + if (1 === count($rv)) { + return $rv[0]; + } + + return new Twig_Node($rv, array(), $lineno); + } + + public function addHandler($name, $class) + { + $this->handlers[$name] = $class; + } + + public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) + { + $this->visitors[] = $visitor; + } + + public function getBlockStack() + { + return $this->blockStack; + } + + public function peekBlockStack() + { + return $this->blockStack[count($this->blockStack) - 1]; + } + + public function popBlockStack() + { + array_pop($this->blockStack); + } + + public function pushBlockStack($name) + { + $this->blockStack[] = $name; + } + + public function hasBlock($name) + { + return isset($this->blocks[$name]); + } + + public function getBlock($name) + { + return $this->blocks[$name]; + } + + public function setBlock($name, Twig_Node_Block $value) + { + $this->blocks[$name] = new Twig_Node_Body(array($value), array(), $value->getLine()); + } + + public function hasMacro($name) + { + return isset($this->macros[$name]); + } + + public function setMacro($name, Twig_Node_Macro $node) + { + if (null === $this->reservedMacroNames) { + $this->reservedMacroNames = array(); + $r = new ReflectionClass($this->env->getBaseTemplateClass()); + foreach ($r->getMethods() as $method) { + $this->reservedMacroNames[] = $method->getName(); + } + } + + if (in_array($name, $this->reservedMacroNames)) { + throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword', $name), $node->getLine(), $this->getFilename()); + } + + $this->macros[$name] = $node; + } + + public function addTrait($trait) + { + $this->traits[] = $trait; + } + + public function hasTraits() + { + return count($this->traits) > 0; + } + + public function embedTemplate(Twig_Node_Module $template) + { + $template->setIndex(mt_rand()); + + $this->embeddedTemplates[] = $template; + } + + public function addImportedSymbol($type, $alias, $name = null, Twig_Node_Expression $node = null) + { + $this->importedSymbols[0][$type][$alias] = array('name' => $name, 'node' => $node); + } + + public function getImportedSymbol($type, $alias) + { + foreach ($this->importedSymbols as $functions) { + if (isset($functions[$type][$alias])) { + return $functions[$type][$alias]; + } + } + } + + public function isMainScope() + { + return 1 === count($this->importedSymbols); + } + + public function pushLocalScope() + { + array_unshift($this->importedSymbols, array()); + } + + public function popLocalScope() + { + array_shift($this->importedSymbols); + } + + /** + * Gets the expression parser. + * + * @return Twig_ExpressionParser The expression parser + */ + public function getExpressionParser() + { + return $this->expressionParser; + } + + public function getParent() + { + return $this->parent; + } + + public function setParent($parent) + { + $this->parent = $parent; + } + + /** + * Gets the token stream. + * + * @return Twig_TokenStream The token stream + */ + public function getStream() + { + return $this->stream; + } + + /** + * Gets the current token. + * + * @return Twig_Token The current token + */ + public function getCurrentToken() + { + return $this->stream->getCurrent(); + } + + protected function filterBodyNodes(Twig_NodeInterface $node) + { + // check that the body does not contain non-empty output nodes + if ( + ($node instanceof Twig_Node_Text && !ctype_space($node->getAttribute('data'))) + || + (!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface) + ) { + if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) { + throw new Twig_Error_Syntax('A template that extends another one cannot have a body but a byte order mark (BOM) has been detected; it must be removed.', $node->getLine(), $this->getFilename()); + } + + throw new Twig_Error_Syntax('A template that extends another one cannot have a body.', $node->getLine(), $this->getFilename()); + } + + // bypass "set" nodes as they "capture" the output + if ($node instanceof Twig_Node_Set) { + return $node; + } + + if ($node instanceof Twig_NodeOutputInterface) { + return; + } + + foreach ($node as $k => $n) { + if (null !== $n && null === $this->filterBodyNodes($n)) { + $node->removeNode($k); + } + } + + return $node; + } +} diff --git a/src/core/libs/Twig/ParserInterface.php b/src/core/libs/Twig/ParserInterface.php new file mode 100755 index 0000000..bfe60a3 --- /dev/null +++ b/src/core/libs/Twig/ParserInterface.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Interface implemented by parser classes. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_ParserInterface +{ + /** + * Converts a token stream to a node tree. + * + * @param Twig_TokenStream $stream A token stream instance + * + * @return Twig_Node_Module A node tree + * + * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong + */ + public function parse(Twig_TokenStream $stream); +} diff --git a/src/core/libs/Twig/Sandbox/SecurityError.php b/src/core/libs/Twig/Sandbox/SecurityError.php new file mode 100755 index 0000000..015bfae --- /dev/null +++ b/src/core/libs/Twig/Sandbox/SecurityError.php @@ -0,0 +1,19 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Exception thrown when a security error occurs at runtime. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Sandbox_SecurityError extends Twig_Error +{ +} diff --git a/src/core/libs/Twig/Sandbox/SecurityPolicy.php b/src/core/libs/Twig/Sandbox/SecurityPolicy.php new file mode 100755 index 0000000..66ee233 --- /dev/null +++ b/src/core/libs/Twig/Sandbox/SecurityPolicy.php @@ -0,0 +1,119 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a security policy which need to be enforced when sandbox mode is enabled. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterface +{ + protected $allowedTags; + protected $allowedFilters; + protected $allowedMethods; + protected $allowedProperties; + protected $allowedFunctions; + + public function __construct(array $allowedTags = array(), array $allowedFilters = array(), array $allowedMethods = array(), array $allowedProperties = array(), array $allowedFunctions = array()) + { + $this->allowedTags = $allowedTags; + $this->allowedFilters = $allowedFilters; + $this->setAllowedMethods($allowedMethods); + $this->allowedProperties = $allowedProperties; + $this->allowedFunctions = $allowedFunctions; + } + + public function setAllowedTags(array $tags) + { + $this->allowedTags = $tags; + } + + public function setAllowedFilters(array $filters) + { + $this->allowedFilters = $filters; + } + + public function setAllowedMethods(array $methods) + { + $this->allowedMethods = array(); + foreach ($methods as $class => $m) { + $this->allowedMethods[$class] = array_map('strtolower', is_array($m) ? $m : array($m)); + } + } + + public function setAllowedProperties(array $properties) + { + $this->allowedProperties = $properties; + } + + public function setAllowedFunctions(array $functions) + { + $this->allowedFunctions = $functions; + } + + public function checkSecurity($tags, $filters, $functions) + { + foreach ($tags as $tag) { + if (!in_array($tag, $this->allowedTags)) { + throw new Twig_Sandbox_SecurityError(sprintf('Tag "%s" is not allowed.', $tag)); + } + } + + foreach ($filters as $filter) { + if (!in_array($filter, $this->allowedFilters)) { + throw new Twig_Sandbox_SecurityError(sprintf('Filter "%s" is not allowed.', $filter)); + } + } + + foreach ($functions as $function) { + if (!in_array($function, $this->allowedFunctions)) { + throw new Twig_Sandbox_SecurityError(sprintf('Function "%s" is not allowed.', $function)); + } + } + } + + public function checkMethodAllowed($obj, $method) + { + if ($obj instanceof Twig_TemplateInterface || $obj instanceof Twig_Markup) { + return true; + } + + $allowed = false; + $method = strtolower($method); + foreach ($this->allowedMethods as $class => $methods) { + if ($obj instanceof $class) { + $allowed = in_array($method, $methods); + + break; + } + } + + if (!$allowed) { + throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj))); + } + } + + public function checkPropertyAllowed($obj, $property) + { + $allowed = false; + foreach ($this->allowedProperties as $class => $properties) { + if ($obj instanceof $class) { + $allowed = in_array($property, is_array($properties) ? $properties : array($properties)); + + break; + } + } + + if (!$allowed) { + throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, get_class($obj))); + } + } +} diff --git a/src/core/libs/Twig/Sandbox/SecurityPolicyInterface.php b/src/core/libs/Twig/Sandbox/SecurityPolicyInterface.php new file mode 100755 index 0000000..6ab48e3 --- /dev/null +++ b/src/core/libs/Twig/Sandbox/SecurityPolicyInterface.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Interfaces that all security policy classes must implements. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface Twig_Sandbox_SecurityPolicyInterface +{ + public function checkSecurity($tags, $filters, $functions); + + public function checkMethodAllowed($obj, $method); + + public function checkPropertyAllowed($obj, $method); +} diff --git a/src/core/libs/Twig/SimpleFilter.php b/src/core/libs/Twig/SimpleFilter.php new file mode 100755 index 0000000..d35c563 --- /dev/null +++ b/src/core/libs/Twig/SimpleFilter.php @@ -0,0 +1,94 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009-2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template filter. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_SimpleFilter +{ + protected $name; + protected $callable; + protected $options; + protected $arguments = array(); + + public function __construct($name, $callable, array $options = array()) + { + $this->name = $name; + $this->callable = $callable; + $this->options = array_merge(array( + 'needs_environment' => false, + 'needs_context' => false, + 'is_safe' => null, + 'is_safe_callback' => null, + 'pre_escape' => null, + 'preserves_safety' => null, + 'node_class' => 'Twig_Node_Expression_Filter', + ), $options); + } + + public function getName() + { + return $this->name; + } + + public function getCallable() + { + return $this->callable; + } + + public function getNodeClass() + { + return $this->options['node_class']; + } + + public function setArguments($arguments) + { + $this->arguments = $arguments; + } + + public function getArguments() + { + return $this->arguments; + } + + public function needsEnvironment() + { + return $this->options['needs_environment']; + } + + public function needsContext() + { + return $this->options['needs_context']; + } + + public function getSafe(Twig_Node $filterArgs) + { + if (null !== $this->options['is_safe']) { + return $this->options['is_safe']; + } + + if (null !== $this->options['is_safe_callback']) { + return call_user_func($this->options['is_safe_callback'], $filterArgs); + } + } + + public function getPreservesSafety() + { + return $this->options['preserves_safety']; + } + + public function getPreEscape() + { + return $this->options['pre_escape']; + } +} diff --git a/src/core/libs/Twig/SimpleFunction.php b/src/core/libs/Twig/SimpleFunction.php new file mode 100755 index 0000000..8ef6aca --- /dev/null +++ b/src/core/libs/Twig/SimpleFunction.php @@ -0,0 +1,84 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010-2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template function. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_SimpleFunction +{ + protected $name; + protected $callable; + protected $options; + protected $arguments = array(); + + public function __construct($name, $callable, array $options = array()) + { + $this->name = $name; + $this->callable = $callable; + $this->options = array_merge(array( + 'needs_environment' => false, + 'needs_context' => false, + 'is_safe' => null, + 'is_safe_callback' => null, + 'node_class' => 'Twig_Node_Expression_Function', + ), $options); + } + + public function getName() + { + return $this->name; + } + + public function getCallable() + { + return $this->callable; + } + + public function getNodeClass() + { + return $this->options['node_class']; + } + + public function setArguments($arguments) + { + $this->arguments = $arguments; + } + + public function getArguments() + { + return $this->arguments; + } + + public function needsEnvironment() + { + return $this->options['needs_environment']; + } + + public function needsContext() + { + return $this->options['needs_context']; + } + + public function getSafe(Twig_Node $functionArgs) + { + if (null !== $this->options['is_safe']) { + return $this->options['is_safe']; + } + + if (null !== $this->options['is_safe_callback']) { + return call_user_func($this->options['is_safe_callback'], $functionArgs); + } + + return array(); + } +} diff --git a/src/core/libs/Twig/SimpleTest.php b/src/core/libs/Twig/SimpleTest.php new file mode 100755 index 0000000..225459c --- /dev/null +++ b/src/core/libs/Twig/SimpleTest.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010-2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template test. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_SimpleTest +{ + protected $name; + protected $callable; + protected $options; + + public function __construct($name, $callable, array $options = array()) + { + $this->name = $name; + $this->callable = $callable; + $this->options = array_merge(array( + 'node_class' => 'Twig_Node_Expression_Test', + ), $options); + } + + public function getName() + { + return $this->name; + } + + public function getCallable() + { + return $this->callable; + } + + public function getNodeClass() + { + return $this->options['node_class']; + } +} diff --git a/src/core/libs/Twig/Template.php b/src/core/libs/Twig/Template.php new file mode 100755 index 0000000..b13df5d --- /dev/null +++ b/src/core/libs/Twig/Template.php @@ -0,0 +1,484 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Default base class for compiled templates. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +abstract class Twig_Template implements Twig_TemplateInterface +{ + protected static $cache = array(); + + protected $parent; + protected $parents; + protected $env; + protected $blocks; + protected $traits; + + /** + * Constructor. + * + * @param Twig_Environment $env A Twig_Environment instance + */ + public function __construct(Twig_Environment $env) + { + $this->env = $env; + $this->blocks = array(); + $this->traits = array(); + } + + /** + * Returns the template name. + * + * @return string The template name + */ + abstract public function getTemplateName(); + + /** + * {@inheritdoc} + */ + public function getEnvironment() + { + return $this->env; + } + + /** + * Returns the parent template. + * + * This method is for internal use only and should never be called + * directly. + * + * @return Twig_TemplateInterface|false The parent template or false if there is no parent + */ + public function getParent(array $context) + { + if (null !== $this->parent) { + return $this->parent; + } + + $parent = $this->doGetParent($context); + if (false === $parent) { + return false; + } elseif ($parent instanceof Twig_Template) { + $name = $parent->getTemplateName(); + $this->parents[$name] = $parent; + $parent = $name; + } elseif (!isset($this->parents[$parent])) { + $this->parents[$parent] = $this->env->loadTemplate($parent); + } + + return $this->parents[$parent]; + } + + protected function doGetParent(array $context) + { + return false; + } + + public function isTraitable() + { + return true; + } + + /** + * Displays a parent block. + * + * This method is for internal use only and should never be called + * directly. + * + * @param string $name The block name to display from the parent + * @param array $context The context + * @param array $blocks The current set of blocks + */ + public function displayParentBlock($name, array $context, array $blocks = array()) + { + $name = (string) $name; + + if (isset($this->traits[$name])) { + $this->traits[$name][0]->displayBlock($name, $context, $blocks); + } elseif (false !== $parent = $this->getParent($context)) { + $parent->displayBlock($name, $context, $blocks); + } else { + throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block', $name), -1, $this->getTemplateName()); + } + } + + /** + * Displays a block. + * + * This method is for internal use only and should never be called + * directly. + * + * @param string $name The block name to display + * @param array $context The context + * @param array $blocks The current set of blocks + */ + public function displayBlock($name, array $context, array $blocks = array()) + { + $name = (string) $name; + + if (isset($blocks[$name])) { + $template = $blocks[$name][0]; + $block = $blocks[$name][1]; + unset($blocks[$name]); + } elseif (isset($this->blocks[$name])) { + $template = $this->blocks[$name][0]; + $block = $this->blocks[$name][1]; + } else { + $template = null; + $block = null; + } + + if (null !== $template) { + try { + $template->$block($context, $blocks); + } catch (Twig_Error $e) { + throw $e; + } catch (Exception $e) { + throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getTemplateName(), $e); + } + } elseif (false !== $parent = $this->getParent($context)) { + $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks)); + } + } + + /** + * Renders a parent block. + * + * This method is for internal use only and should never be called + * directly. + * + * @param string $name The block name to render from the parent + * @param array $context The context + * @param array $blocks The current set of blocks + * + * @return string The rendered block + */ + public function renderParentBlock($name, array $context, array $blocks = array()) + { + ob_start(); + $this->displayParentBlock($name, $context, $blocks); + + return ob_get_clean(); + } + + /** + * Renders a block. + * + * This method is for internal use only and should never be called + * directly. + * + * @param string $name The block name to render + * @param array $context The context + * @param array $blocks The current set of blocks + * + * @return string The rendered block + */ + public function renderBlock($name, array $context, array $blocks = array()) + { + ob_start(); + $this->displayBlock($name, $context, $blocks); + + return ob_get_clean(); + } + + /** + * Returns whether a block exists or not. + * + * This method is for internal use only and should never be called + * directly. + * + * This method does only return blocks defined in the current template + * or defined in "used" traits. + * + * It does not return blocks from parent templates as the parent + * template name can be dynamic, which is only known based on the + * current context. + * + * @param string $name The block name + * + * @return Boolean true if the block exists, false otherwise + */ + public function hasBlock($name) + { + return isset($this->blocks[(string) $name]); + } + + /** + * Returns all block names. + * + * This method is for internal use only and should never be called + * directly. + * + * @return array An array of block names + * + * @see hasBlock + */ + public function getBlockNames() + { + return array_keys($this->blocks); + } + + /** + * Returns all blocks. + * + * This method is for internal use only and should never be called + * directly. + * + * @return array An array of blocks + * + * @see hasBlock + */ + public function getBlocks() + { + return $this->blocks; + } + + /** + * {@inheritdoc} + */ + public function display(array $context, array $blocks = array()) + { + $this->displayWithErrorHandling($this->env->mergeGlobals($context), $blocks); + } + + /** + * {@inheritdoc} + */ + public function render(array $context) + { + $level = ob_get_level(); + ob_start(); + try { + $this->display($context); + } catch (Exception $e) { + while (ob_get_level() > $level) { + ob_end_clean(); + } + + throw $e; + } + + return ob_get_clean(); + } + + protected function displayWithErrorHandling(array $context, array $blocks = array()) + { + try { + $this->doDisplay($context, $blocks); + } catch (Twig_Error $e) { + if (!$e->getTemplateFile()) { + $e->setTemplateFile($this->getTemplateName()); + } + + // this is mostly useful for Twig_Error_Loader exceptions + // see Twig_Error_Loader + if (false === $e->getTemplateLine()) { + $e->setTemplateLine(-1); + $e->guess(); + } + + throw $e; + } catch (Exception $e) { + throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getTemplateName(), $e); + } + } + + /** + * Auto-generated method to display the template with the given context. + * + * @param array $context An array of parameters to pass to the template + * @param array $blocks An array of blocks to pass to the template + */ + abstract protected function doDisplay(array $context, array $blocks = array()); + + /** + * Returns a variable from the context. + * + * This method is for internal use only and should never be called + * directly. + * + * This method should not be overridden in a sub-class as this is an + * implementation detail that has been introduced to optimize variable + * access for versions of PHP before 5.4. This is not a way to override + * the way to get a variable value. + * + * @param array $context The context + * @param string $item The variable to return from the context + * @param Boolean $ignoreStrictCheck Whether to ignore the strict variable check or not + * + * @return The content of the context variable + * + * @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode + */ + final protected function getContext($context, $item, $ignoreStrictCheck = false) + { + if (!array_key_exists($item, $context)) { + if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { + return null; + } + + throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist', $item), -1, $this->getTemplateName()); + } + + return $context[$item]; + } + + /** + * Returns the attribute value for a given array/object. + * + * @param mixed $object The object or array from where to get the item + * @param mixed $item The item to get from the array or object + * @param array $arguments An array of arguments to pass if the item is an object method + * @param string $type The type of attribute (@see Twig_Template constants) + * @param Boolean $isDefinedTest Whether this is only a defined check + * @param Boolean $ignoreStrictCheck Whether to ignore the strict attribute check or not + * + * @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true + * + * @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false + */ + protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false) + { + // array + if (Twig_Template::METHOD_CALL !== $type) { + $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item; + + if ((is_array($object) && array_key_exists($arrayItem, $object)) + || ($object instanceof ArrayAccess && isset($object[$arrayItem])) + ) { + if ($isDefinedTest) { + return true; + } + + return $object[$arrayItem]; + } + + if (Twig_Template::ARRAY_CALL === $type || !is_object($object)) { + if ($isDefinedTest) { + return false; + } + + if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { + return null; + } + + if ($object instanceof ArrayAccess) { + $message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist', $arrayItem, get_class($object)); + } elseif (is_object($object)) { + $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface', $item, get_class($object)); + } elseif (is_array($object)) { + $message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object))); + } elseif (Twig_Template::ARRAY_CALL === $type) { + $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object); + } else { + $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object); + } + + throw new Twig_Error_Runtime($message, -1, $this->getTemplateName()); + } + } + + if (!is_object($object)) { + if ($isDefinedTest) { + return false; + } + + if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { + return null; + } + + throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName()); + } + + $class = get_class($object); + + // object property + if (Twig_Template::METHOD_CALL !== $type) { + if (isset($object->$item) || array_key_exists((string) $item, $object)) { + if ($isDefinedTest) { + return true; + } + + if ($this->env->hasExtension('sandbox')) { + $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item); + } + + return $object->$item; + } + } + + // object method + if (!isset(self::$cache[$class]['methods'])) { + self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object))); + } + + $call = false; + $lcItem = strtolower($item); + if (isset(self::$cache[$class]['methods'][$lcItem])) { + $method = (string) $item; + } elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) { + $method = 'get'.$item; + } elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) { + $method = 'is'.$item; + } elseif (isset(self::$cache[$class]['methods']['__call'])) { + $method = (string) $item; + $call = true; + } else { + if ($isDefinedTest) { + return false; + } + + if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { + return null; + } + + throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)), -1, $this->getTemplateName()); + } + + if ($isDefinedTest) { + return true; + } + + if ($this->env->hasExtension('sandbox')) { + $this->env->getExtension('sandbox')->checkMethodAllowed($object, $method); + } + + // Some objects throw exceptions when they have __call, and the method we try + // to call is not supported. If ignoreStrictCheck is true, we should return null. + try { + $ret = call_user_func_array(array($object, $method), $arguments); + } catch (BadMethodCallException $e) { + if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) { + return null; + } + throw $e; + } + + // useful when calling a template method from a template + // this is not supported but unfortunately heavily used in the Symfony profiler + if ($object instanceof Twig_TemplateInterface) { + return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset()); + } + + return $ret; + } + + /** + * This method is only useful when testing Twig. Do not use it. + */ + public static function clearCache() + { + self::$cache = array(); + } +} diff --git a/src/core/libs/Twig/TemplateInterface.php b/src/core/libs/Twig/TemplateInterface.php new file mode 100755 index 0000000..879f503 --- /dev/null +++ b/src/core/libs/Twig/TemplateInterface.php @@ -0,0 +1,47 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Interface implemented by all compiled templates. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_TemplateInterface +{ + const ANY_CALL = 'any'; + const ARRAY_CALL = 'array'; + const METHOD_CALL = 'method'; + + /** + * Renders the template with the given context and returns it as string. + * + * @param array $context An array of parameters to pass to the template + * + * @return string The rendered template + */ + public function render(array $context); + + /** + * Displays the template with the given context. + * + * @param array $context An array of parameters to pass to the template + * @param array $blocks An array of blocks to pass to the template + */ + public function display(array $context, array $blocks = array()); + + /** + * Returns the bound environment for this template. + * + * @return Twig_Environment The current environment + */ + public function getEnvironment(); +} diff --git a/src/core/libs/Twig/Test.php b/src/core/libs/Twig/Test.php new file mode 100755 index 0000000..3baff88 --- /dev/null +++ b/src/core/libs/Twig/Test.php @@ -0,0 +1,34 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template test. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +abstract class Twig_Test implements Twig_TestInterface, Twig_TestCallableInterface +{ + protected $options; + protected $arguments = array(); + + public function __construct(array $options = array()) + { + $this->options = array_merge(array( + 'callable' => null, + ), $options); + } + + public function getCallable() + { + return $this->options['callable']; + } +} diff --git a/src/core/libs/Twig/Test/Function.php b/src/core/libs/Twig/Test/Function.php new file mode 100755 index 0000000..4be6b9b --- /dev/null +++ b/src/core/libs/Twig/Test/Function.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a function template test. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +class Twig_Test_Function extends Twig_Test +{ + protected $function; + + public function __construct($function, array $options = array()) + { + $options['callable'] = $function; + + parent::__construct($options); + + $this->function = $function; + } + + public function compile() + { + return $this->function; + } +} diff --git a/src/core/libs/Twig/Test/IntegrationTestCase.php b/src/core/libs/Twig/Test/IntegrationTestCase.php new file mode 100755 index 0000000..724f094 --- /dev/null +++ b/src/core/libs/Twig/Test/IntegrationTestCase.php @@ -0,0 +1,154 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Integration test helper + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Karma Dordrak <drak@zikula.org> + */ +abstract class Twig_Test_IntegrationTestCase extends PHPUnit_Framework_TestCase +{ + abstract protected function getExtensions(); + abstract protected function getFixturesDir(); + + /** + * @dataProvider getTests + */ + public function testIntegration($file, $message, $condition, $templates, $exception, $outputs) + { + $this->doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs); + } + + public function getTests() + { + $fixturesDir = realpath($this->getFixturesDir()); + $tests = array(); + + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + if (!preg_match('/\.test$/', $file)) { + continue; + } + + $test = file_get_contents($file->getRealpath()); + + if (preg_match('/ + --TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)\s*(?:--DATA--\s*(.*))?\s*--EXCEPTION--\s*(.*)/sx', $test, $match)) { + $message = $match[1]; + $condition = $match[2]; + $templates = $this->parseTemplates($match[3]); + $exception = $match[5]; + $outputs = array(array(null, $match[4], null, '')); + } elseif (preg_match('/--TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)--DATA--.*?--EXPECT--.*/s', $test, $match)) { + $message = $match[1]; + $condition = $match[2]; + $templates = $this->parseTemplates($match[3]); + $exception = false; + preg_match_all('/--DATA--(.*?)(?:--CONFIG--(.*?))?--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $outputs, PREG_SET_ORDER); + } else { + throw new InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file))); + } + + $tests[] = array(str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs); + } + + return $tests; + } + + protected function doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs) + { + if ($condition) { + eval('$ret = '.$condition.';'); + if (!$ret) { + $this->markTestSkipped($condition); + } + } + + $loader = new Twig_Loader_Array($templates); + + foreach ($outputs as $match) { + $config = array_merge(array( + 'cache' => false, + 'strict_variables' => true, + ), $match[2] ? eval($match[2].';') : array()); + $twig = new Twig_Environment($loader, $config); + $twig->addGlobal('global', 'global'); + foreach ($this->getExtensions() as $extension) { + $twig->addExtension($extension); + } + + try { + $template = $twig->loadTemplate('index.twig'); + } catch (Exception $e) { + if (false !== $exception) { + $this->assertEquals(trim($exception), trim(sprintf('%s: %s', get_class($e), $e->getMessage()))); + + return; + } + + if ($e instanceof Twig_Error_Syntax) { + $e->setTemplateFile($file); + + throw $e; + } + + throw new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e); + } + + try { + $output = trim($template->render(eval($match[1].';')), "\n "); + } catch (Exception $e) { + if (false !== $exception) { + $this->assertEquals(trim($exception), trim(sprintf('%s: %s', get_class($e), $e->getMessage()))); + + return; + } + + if ($e instanceof Twig_Error_Syntax) { + $e->setTemplateFile($file); + } else { + $e = new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e); + } + + $output = trim(sprintf('%s: %s', get_class($e), $e->getMessage())); + } + + if (false !== $exception) { + list($class, ) = explode(':', $exception); + $this->assertThat(NULL, new PHPUnit_Framework_Constraint_Exception($class)); + } + + $expected = trim($match[3], "\n "); + + if ($expected != $output) { + echo 'Compiled template that failed:'; + + foreach (array_keys($templates) as $name) { + echo "Template: $name\n"; + $source = $loader->getSource($name); + echo $twig->compile($twig->parse($twig->tokenize($source, $name))); + } + } + $this->assertEquals($expected, $output, $message.' (in '.$file.')'); + } + } + + protected static function parseTemplates($test) + { + $templates = array(); + preg_match_all('/--TEMPLATE(?:\((.*?)\))?--(.*?)(?=\-\-TEMPLATE|$)/s', $test, $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $templates[($match[1] ? $match[1] : 'index.twig')] = $match[2]; + } + + return $templates; + } +} diff --git a/src/core/libs/Twig/Test/Method.php b/src/core/libs/Twig/Test/Method.php new file mode 100755 index 0000000..17c6c04 --- /dev/null +++ b/src/core/libs/Twig/Test/Method.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a method template test. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +class Twig_Test_Method extends Twig_Test +{ + protected $extension; + protected $method; + + public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) + { + $options['callable'] = array($extension, $method); + + parent::__construct($options); + + $this->extension = $extension; + $this->method = $method; + } + + public function compile() + { + return sprintf('$this->env->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method); + } +} diff --git a/src/core/libs/Twig/Test/Node.php b/src/core/libs/Twig/Test/Node.php new file mode 100755 index 0000000..c832a57 --- /dev/null +++ b/src/core/libs/Twig/Test/Node.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template test as a Node. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +class Twig_Test_Node extends Twig_Test +{ + protected $class; + + public function __construct($class, array $options = array()) + { + parent::__construct($options); + + $this->class = $class; + } + + public function getClass() + { + return $this->class; + } + + public function compile() + { + } +} diff --git a/src/core/libs/Twig/Test/NodeTestCase.php b/src/core/libs/Twig/Test/NodeTestCase.php new file mode 100755 index 0000000..b15c85f --- /dev/null +++ b/src/core/libs/Twig/Test/NodeTestCase.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ +abstract class Twig_Test_NodeTestCase extends PHPUnit_Framework_TestCase +{ + abstract public function getTests(); + + /** + * @dataProvider getTests + */ + public function testCompile($node, $source, $environment = null) + { + $this->assertNodeCompilation($source, $node, $environment); + } + + public function assertNodeCompilation($source, Twig_Node $node, Twig_Environment $environment = null) + { + $compiler = $this->getCompiler($environment); + $compiler->compile($node); + + $this->assertEquals($source, trim($compiler->getSource())); + } + + protected function getCompiler(Twig_Environment $environment = null) + { + return new Twig_Compiler(null === $environment ? $this->getEnvironment() : $environment); + } + + protected function getEnvironment() + { + return new Twig_Environment(); + } + + protected function getVariableGetter($name) + { + if (version_compare(phpversion(), '5.4.0RC1', '>=')) { + return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name); + } + + return sprintf('$this->getContext($context, "%s")', $name); + } + + protected function getAttributeGetter() + { + if (function_exists('twig_template_get_attributes')) { + return 'twig_template_get_attributes($this, '; + } + + return '$this->getAttribute('; + } +} diff --git a/src/core/libs/Twig/TestCallableInterface.php b/src/core/libs/Twig/TestCallableInterface.php new file mode 100755 index 0000000..0db4368 --- /dev/null +++ b/src/core/libs/Twig/TestCallableInterface.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a callable template test. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_TestCallableInterface +{ + public function getCallable(); +} diff --git a/src/core/libs/Twig/TestInterface.php b/src/core/libs/Twig/TestInterface.php new file mode 100755 index 0000000..30d8a2c --- /dev/null +++ b/src/core/libs/Twig/TestInterface.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a template test. + * + * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_TestInterface +{ + /** + * Compiles a test. + * + * @return string The PHP code for the test + */ + public function compile(); +} diff --git a/src/core/libs/Twig/Token.php b/src/core/libs/Twig/Token.php new file mode 100755 index 0000000..4411d7b --- /dev/null +++ b/src/core/libs/Twig/Token.php @@ -0,0 +1,216 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a Token. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_Token +{ + protected $value; + protected $type; + protected $lineno; + + const EOF_TYPE = -1; + const TEXT_TYPE = 0; + const BLOCK_START_TYPE = 1; + const VAR_START_TYPE = 2; + const BLOCK_END_TYPE = 3; + const VAR_END_TYPE = 4; + const NAME_TYPE = 5; + const NUMBER_TYPE = 6; + const STRING_TYPE = 7; + const OPERATOR_TYPE = 8; + const PUNCTUATION_TYPE = 9; + const INTERPOLATION_START_TYPE = 10; + const INTERPOLATION_END_TYPE = 11; + + /** + * Constructor. + * + * @param integer $type The type of the token + * @param string $value The token value + * @param integer $lineno The line position in the source + */ + public function __construct($type, $value, $lineno) + { + $this->type = $type; + $this->value = $value; + $this->lineno = $lineno; + } + + /** + * Returns a string representation of the token. + * + * @return string A string representation of the token + */ + public function __toString() + { + return sprintf('%s(%s)', self::typeToString($this->type, true), $this->value); + } + + /** + * Tests the current token for a type and/or a value. + * + * Parameters may be: + * * just type + * * type and value (or array of possible values) + * * just value (or array of possible values) (NAME_TYPE is used as type) + * + * @param array|integer $type The type to test + * @param array|string|null $values The token value + * + * @return Boolean + */ + public function test($type, $values = null) + { + if (null === $values && !is_int($type)) { + $values = $type; + $type = self::NAME_TYPE; + } + + return ($this->type === $type) && ( + null === $values || + (is_array($values) && in_array($this->value, $values)) || + $this->value == $values + ); + } + + /** + * Gets the line. + * + * @return integer The source line + */ + public function getLine() + { + return $this->lineno; + } + + /** + * Gets the token type. + * + * @return integer The token type + */ + public function getType() + { + return $this->type; + } + + /** + * Gets the token value. + * + * @return string The token value + */ + public function getValue() + { + return $this->value; + } + + /** + * Returns the constant representation (internal) of a given type. + * + * @param integer $type The type as an integer + * @param Boolean $short Whether to return a short representation or not + * + * @return string The string representation + */ + public static function typeToString($type, $short = false) + { + switch ($type) { + case self::EOF_TYPE: + $name = 'EOF_TYPE'; + break; + case self::TEXT_TYPE: + $name = 'TEXT_TYPE'; + break; + case self::BLOCK_START_TYPE: + $name = 'BLOCK_START_TYPE'; + break; + case self::VAR_START_TYPE: + $name = 'VAR_START_TYPE'; + break; + case self::BLOCK_END_TYPE: + $name = 'BLOCK_END_TYPE'; + break; + case self::VAR_END_TYPE: + $name = 'VAR_END_TYPE'; + break; + case self::NAME_TYPE: + $name = 'NAME_TYPE'; + break; + case self::NUMBER_TYPE: + $name = 'NUMBER_TYPE'; + break; + case self::STRING_TYPE: + $name = 'STRING_TYPE'; + break; + case self::OPERATOR_TYPE: + $name = 'OPERATOR_TYPE'; + break; + case self::PUNCTUATION_TYPE: + $name = 'PUNCTUATION_TYPE'; + break; + case self::INTERPOLATION_START_TYPE: + $name = 'INTERPOLATION_START_TYPE'; + break; + case self::INTERPOLATION_END_TYPE: + $name = 'INTERPOLATION_END_TYPE'; + break; + default: + throw new LogicException(sprintf('Token of type "%s" does not exist.', $type)); + } + + return $short ? $name : 'Twig_Token::'.$name; + } + + /** + * Returns the english representation of a given type. + * + * @param integer $type The type as an integer + * + * @return string The string representation + */ + public static function typeToEnglish($type) + { + switch ($type) { + case self::EOF_TYPE: + return 'end of template'; + case self::TEXT_TYPE: + return 'text'; + case self::BLOCK_START_TYPE: + return 'begin of statement block'; + case self::VAR_START_TYPE: + return 'begin of print statement'; + case self::BLOCK_END_TYPE: + return 'end of statement block'; + case self::VAR_END_TYPE: + return 'end of print statement'; + case self::NAME_TYPE: + return 'name'; + case self::NUMBER_TYPE: + return 'number'; + case self::STRING_TYPE: + return 'string'; + case self::OPERATOR_TYPE: + return 'operator'; + case self::PUNCTUATION_TYPE: + return 'punctuation'; + case self::INTERPOLATION_START_TYPE: + return 'begin of string interpolation'; + case self::INTERPOLATION_END_TYPE: + return 'end of string interpolation'; + default: + throw new LogicException(sprintf('Token of type "%s" does not exist.', $type)); + } + } +} diff --git a/src/core/libs/Twig/TokenParser.php b/src/core/libs/Twig/TokenParser.php new file mode 100755 index 0000000..decebd5 --- /dev/null +++ b/src/core/libs/Twig/TokenParser.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Base class for all token parsers. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +abstract class Twig_TokenParser implements Twig_TokenParserInterface +{ + /** + * @var Twig_Parser + */ + protected $parser; + + /** + * Sets the parser associated with this token parser + * + * @param $parser A Twig_Parser instance + */ + public function setParser(Twig_Parser $parser) + { + $this->parser = $parser; + } +} diff --git a/src/core/libs/Twig/TokenParser/AutoEscape.php b/src/core/libs/Twig/TokenParser/AutoEscape.php new file mode 100755 index 0000000..2756028 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/AutoEscape.php @@ -0,0 +1,89 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Marks a section of a template to be escaped or not. + * + * <pre> + * {% autoescape true %} + * Everything will be automatically escaped in this block + * {% endautoescape %} + * + * {% autoescape false %} + * Everything will be outputed as is in this block + * {% endautoescape %} + * + * {% autoescape true js %} + * Everything will be automatically escaped in this block + * using the js escaping strategy + * {% endautoescape %} + * </pre> + */ +class Twig_TokenParser_AutoEscape extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + + if ($stream->test(Twig_Token::BLOCK_END_TYPE)) { + $value = 'html'; + } else { + $expr = $this->parser->getExpressionParser()->parseExpression(); + if (!$expr instanceof Twig_Node_Expression_Constant) { + throw new Twig_Error_Syntax('An escaping strategy must be a string or a Boolean.', $stream->getCurrent()->getLine(), $stream->getFilename()); + } + $value = $expr->getAttribute('value'); + + $compat = true === $value || false === $value; + + if (true === $value) { + $value = 'html'; + } + + if ($compat && $stream->test(Twig_Token::NAME_TYPE)) { + if (false === $value) { + throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getFilename()); + } + + $value = $stream->next()->getValue(); + } + } + + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); + $stream->expect(Twig_Token::BLOCK_END_TYPE); + + return new Twig_Node_AutoEscape($value, $body, $lineno, $this->getTag()); + } + + public function decideBlockEnd(Twig_Token $token) + { + return $token->test('endautoescape'); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'autoescape'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Block.php b/src/core/libs/Twig/TokenParser/Block.php new file mode 100755 index 0000000..81e6b1c --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Block.php @@ -0,0 +1,81 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Marks a section of a template as being reusable. + * + * <pre> + * {% block head %} + * <link rel="stylesheet" href="style.css" /> + * <title>{% block title %}{% endblock %} - My Webpage</title> + * {% endblock %} + * </pre> + */ +class Twig_TokenParser_Block extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); + if ($this->parser->hasBlock($name)) { + throw new Twig_Error_Syntax(sprintf("The block '$name' has already been defined line %d", $this->parser->getBlock($name)->getLine()), $stream->getCurrent()->getLine(), $stream->getFilename()); + } + $this->parser->setBlock($name, $block = new Twig_Node_Block($name, new Twig_Node(array()), $lineno)); + $this->parser->pushLocalScope(); + $this->parser->pushBlockStack($name); + + if ($stream->nextIf(Twig_Token::BLOCK_END_TYPE)) { + $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); + if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) { + $value = $token->getValue(); + + if ($value != $name) { + throw new Twig_Error_Syntax(sprintf("Expected endblock for block '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename()); + } + } + } else { + $body = new Twig_Node(array( + new Twig_Node_Print($this->parser->getExpressionParser()->parseExpression(), $lineno), + )); + } + $stream->expect(Twig_Token::BLOCK_END_TYPE); + + $block->setNode('body', $body); + $this->parser->popBlockStack(); + $this->parser->popLocalScope(); + + return new Twig_Node_BlockReference($name, $lineno, $this->getTag()); + } + + public function decideBlockEnd(Twig_Token $token) + { + return $token->test('endblock'); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'block'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Do.php b/src/core/libs/Twig/TokenParser/Do.php new file mode 100755 index 0000000..f50939d --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Do.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Evaluates an expression, discarding the returned value. + */ +class Twig_TokenParser_Do extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $expr = $this->parser->getExpressionParser()->parseExpression(); + + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + + return new Twig_Node_Do($expr, $token->getLine(), $this->getTag()); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'do'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Embed.php b/src/core/libs/Twig/TokenParser/Embed.php new file mode 100755 index 0000000..69cb5f3 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Embed.php @@ -0,0 +1,66 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2012 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Embeds a template. + */ +class Twig_TokenParser_Embed extends Twig_TokenParser_Include +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $stream = $this->parser->getStream(); + + $parent = $this->parser->getExpressionParser()->parseExpression(); + + list($variables, $only, $ignoreMissing) = $this->parseArguments(); + + // inject a fake parent to make the parent() function work + $stream->injectTokens(array( + new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', $token->getLine()), + new Twig_Token(Twig_Token::NAME_TYPE, 'extends', $token->getLine()), + new Twig_Token(Twig_Token::STRING_TYPE, '__parent__', $token->getLine()), + new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $token->getLine()), + )); + + $module = $this->parser->parse($stream, array($this, 'decideBlockEnd'), true); + + // override the parent with the correct one + $module->setNode('parent', $parent); + + $this->parser->embedTemplate($module); + + $stream->expect(Twig_Token::BLOCK_END_TYPE); + + return new Twig_Node_Embed($module->getAttribute('filename'), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); + } + + public function decideBlockEnd(Twig_Token $token) + { + return $token->test('endembed'); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'embed'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Extends.php b/src/core/libs/Twig/TokenParser/Extends.php new file mode 100755 index 0000000..f5ecee2 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Extends.php @@ -0,0 +1,52 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Extends a template by another one. + * + * <pre> + * {% extends "base.html" %} + * </pre> + */ +class Twig_TokenParser_Extends extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + if (!$this->parser->isMainScope()) { + throw new Twig_Error_Syntax('Cannot extend from a block', $token->getLine(), $this->parser->getFilename()); + } + + if (null !== $this->parser->getParent()) { + throw new Twig_Error_Syntax('Multiple extends tags are forbidden', $token->getLine(), $this->parser->getFilename()); + } + $this->parser->setParent($this->parser->getExpressionParser()->parseExpression()); + + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'extends'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Filter.php b/src/core/libs/Twig/TokenParser/Filter.php new file mode 100755 index 0000000..2b97475 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Filter.php @@ -0,0 +1,61 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Filters a section of a template by applying filters. + * + * <pre> + * {% filter upper %} + * This text becomes uppercase + * {% endfilter %} + * </pre> + */ +class Twig_TokenParser_Filter extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $name = $this->parser->getVarName(); + $ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()), true, $token->getLine(), $this->getTag()); + + $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag()); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + + $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + + $block = new Twig_Node_Block($name, $body, $token->getLine()); + $this->parser->setBlock($name, $block); + + return new Twig_Node_Print($filter, $token->getLine(), $this->getTag()); + } + + public function decideBlockEnd(Twig_Token $token) + { + return $token->test('endfilter'); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'filter'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Flush.php b/src/core/libs/Twig/TokenParser/Flush.php new file mode 100755 index 0000000..4e15e78 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Flush.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Flushes the output to the client. + * + * @see flush() + */ +class Twig_TokenParser_Flush extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + + return new Twig_Node_Flush($token->getLine(), $this->getTag()); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'flush'; + } +} diff --git a/src/core/libs/Twig/TokenParser/For.php b/src/core/libs/Twig/TokenParser/For.php new file mode 100755 index 0000000..5c07d63 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/For.php @@ -0,0 +1,135 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Loops over each item of a sequence. + * + * <pre> + * <ul> + * {% for user in users %} + * <li>{{ user.username|e }}</li> + * {% endfor %} + * </ul> + * </pre> + */ +class Twig_TokenParser_For extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $targets = $this->parser->getExpressionParser()->parseAssignmentExpression(); + $stream->expect(Twig_Token::OPERATOR_TYPE, 'in'); + $seq = $this->parser->getExpressionParser()->parseExpression(); + + $ifexpr = null; + if ($stream->nextIf(Twig_Token::NAME_TYPE, 'if')) { + $ifexpr = $this->parser->getExpressionParser()->parseExpression(); + } + + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideForFork')); + if ($stream->next()->getValue() == 'else') { + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $else = $this->parser->subparse(array($this, 'decideForEnd'), true); + } else { + $else = null; + } + $stream->expect(Twig_Token::BLOCK_END_TYPE); + + if (count($targets) > 1) { + $keyTarget = $targets->getNode(0); + $keyTarget = new Twig_Node_Expression_AssignName($keyTarget->getAttribute('name'), $keyTarget->getLine()); + $valueTarget = $targets->getNode(1); + $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine()); + } else { + $keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno); + $valueTarget = $targets->getNode(0); + $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getLine()); + } + + if ($ifexpr) { + $this->checkLoopUsageCondition($stream, $ifexpr); + $this->checkLoopUsageBody($stream, $body); + } + + return new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag()); + } + + public function decideForFork(Twig_Token $token) + { + return $token->test(array('else', 'endfor')); + } + + public function decideForEnd(Twig_Token $token) + { + return $token->test('endfor'); + } + + // the loop variable cannot be used in the condition + protected function checkLoopUsageCondition(Twig_TokenStream $stream, Twig_NodeInterface $node) + { + if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) { + throw new Twig_Error_Syntax('The "loop" variable cannot be used in a looping condition', $node->getLine(), $stream->getFilename()); + } + + foreach ($node as $n) { + if (!$n) { + continue; + } + + $this->checkLoopUsageCondition($stream, $n); + } + } + + // check usage of non-defined loop-items + // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include) + protected function checkLoopUsageBody(Twig_TokenStream $stream, Twig_NodeInterface $node) + { + if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) { + $attribute = $node->getNode('attribute'); + if ($attribute instanceof Twig_Node_Expression_Constant && in_array($attribute->getAttribute('value'), array('length', 'revindex0', 'revindex', 'last'))) { + throw new Twig_Error_Syntax(sprintf('The "loop.%s" variable is not defined when looping with a condition', $attribute->getAttribute('value')), $node->getLine(), $stream->getFilename()); + } + } + + // should check for parent.loop.XXX usage + if ($node instanceof Twig_Node_For) { + return; + } + + foreach ($node as $n) { + if (!$n) { + continue; + } + + $this->checkLoopUsageBody($stream, $n); + } + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'for'; + } +} diff --git a/src/core/libs/Twig/TokenParser/From.php b/src/core/libs/Twig/TokenParser/From.php new file mode 100755 index 0000000..dd73f99 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/From.php @@ -0,0 +1,70 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Imports macros. + * + * <pre> + * {% from 'forms.html' import forms %} + * </pre> + */ +class Twig_TokenParser_From extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $macro = $this->parser->getExpressionParser()->parseExpression(); + $stream = $this->parser->getStream(); + $stream->expect('import'); + + $targets = array(); + do { + $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); + + $alias = $name; + if ($stream->nextIf('as')) { + $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); + } + + $targets[$name] = $alias; + + if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { + break; + } + } while (true); + + $stream->expect(Twig_Token::BLOCK_END_TYPE); + + $node = new Twig_Node_Import($macro, new Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag()); + + foreach ($targets as $name => $alias) { + $this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var')); + } + + return $node; + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'from'; + } +} diff --git a/src/core/libs/Twig/TokenParser/If.php b/src/core/libs/Twig/TokenParser/If.php new file mode 100755 index 0000000..3d7d1f5 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/If.php @@ -0,0 +1,94 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Tests a condition. + * + * <pre> + * {% if users %} + * <ul> + * {% for user in users %} + * <li>{{ user.username|e }}</li> + * {% endfor %} + * </ul> + * {% endif %} + * </pre> + */ +class Twig_TokenParser_If extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $lineno = $token->getLine(); + $expr = $this->parser->getExpressionParser()->parseExpression(); + $stream = $this->parser->getStream(); + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideIfFork')); + $tests = array($expr, $body); + $else = null; + + $end = false; + while (!$end) { + switch ($stream->next()->getValue()) { + case 'else': + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $else = $this->parser->subparse(array($this, 'decideIfEnd')); + break; + + case 'elseif': + $expr = $this->parser->getExpressionParser()->parseExpression(); + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideIfFork')); + $tests[] = $expr; + $tests[] = $body; + break; + + case 'endif': + $end = true; + break; + + default: + throw new Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d)', $lineno), $stream->getCurrent()->getLine(), $stream->getFilename()); + } + } + + $stream->expect(Twig_Token::BLOCK_END_TYPE); + + return new Twig_Node_If(new Twig_Node($tests), $else, $lineno, $this->getTag()); + } + + public function decideIfFork(Twig_Token $token) + { + return $token->test(array('elseif', 'else', 'endif')); + } + + public function decideIfEnd(Twig_Token $token) + { + return $token->test(array('endif')); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'if'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Import.php b/src/core/libs/Twig/TokenParser/Import.php new file mode 100755 index 0000000..e7050c7 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Import.php @@ -0,0 +1,49 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Imports macros. + * + * <pre> + * {% import 'forms.html' as forms %} + * </pre> + */ +class Twig_TokenParser_Import extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $macro = $this->parser->getExpressionParser()->parseExpression(); + $this->parser->getStream()->expect('as'); + $var = new Twig_Node_Expression_AssignName($this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(), $token->getLine()); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + + $this->parser->addImportedSymbol('template', $var->getAttribute('name')); + + return new Twig_Node_Import($macro, $var, $token->getLine(), $this->getTag()); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'import'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Include.php b/src/core/libs/Twig/TokenParser/Include.php new file mode 100755 index 0000000..9c3099a --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Include.php @@ -0,0 +1,75 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Includes a template. + * + * <pre> + * {% include 'header.html' %} + * Body + * {% include 'footer.html' %} + * </pre> + */ +class Twig_TokenParser_Include extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $expr = $this->parser->getExpressionParser()->parseExpression(); + + list($variables, $only, $ignoreMissing) = $this->parseArguments(); + + return new Twig_Node_Include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); + } + + protected function parseArguments() + { + $stream = $this->parser->getStream(); + + $ignoreMissing = false; + if ($stream->nextIf(Twig_Token::NAME_TYPE, 'ignore')) { + $stream->expect(Twig_Token::NAME_TYPE, 'missing'); + + $ignoreMissing = true; + } + + $variables = null; + if ($stream->nextIf(Twig_Token::NAME_TYPE, 'with')) { + $variables = $this->parser->getExpressionParser()->parseExpression(); + } + + $only = false; + if ($stream->nextIf(Twig_Token::NAME_TYPE, 'only')) { + $only = true; + } + + $stream->expect(Twig_Token::BLOCK_END_TYPE); + + return array($variables, $only, $ignoreMissing); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'include'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Macro.php b/src/core/libs/Twig/TokenParser/Macro.php new file mode 100755 index 0000000..87a299d --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Macro.php @@ -0,0 +1,68 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Defines a macro. + * + * <pre> + * {% macro input(name, value, type, size) %} + * <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" /> + * {% endmacro %} + * </pre> + */ +class Twig_TokenParser_Macro extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); + + $arguments = $this->parser->getExpressionParser()->parseArguments(true, true); + + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $this->parser->pushLocalScope(); + $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); + if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) { + $value = $token->getValue(); + + if ($value != $name) { + throw new Twig_Error_Syntax(sprintf("Expected endmacro for macro '$name' (but %s given)", $value), $stream->getCurrent()->getLine(), $stream->getFilename()); + } + } + $this->parser->popLocalScope(); + $stream->expect(Twig_Token::BLOCK_END_TYPE); + + $this->parser->setMacro($name, new Twig_Node_Macro($name, new Twig_Node_Body(array($body)), $arguments, $lineno, $this->getTag())); + } + + public function decideBlockEnd(Twig_Token $token) + { + return $token->test('endmacro'); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'macro'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Sandbox.php b/src/core/libs/Twig/TokenParser/Sandbox.php new file mode 100755 index 0000000..9457325 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Sandbox.php @@ -0,0 +1,68 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Marks a section of a template as untrusted code that must be evaluated in the sandbox mode. + * + * <pre> + * {% sandbox %} + * {% include 'user.html' %} + * {% endsandbox %} + * </pre> + * + * @see http://www.twig-project.org/doc/api.html#sandbox-extension for details + */ +class Twig_TokenParser_Sandbox extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + + // in a sandbox tag, only include tags are allowed + if (!$body instanceof Twig_Node_Include) { + foreach ($body as $node) { + if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) { + continue; + } + + if (!$node instanceof Twig_Node_Include) { + throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section', $node->getLine(), $this->parser->getFilename()); + } + } + } + + return new Twig_Node_Sandbox($body, $token->getLine(), $this->getTag()); + } + + public function decideBlockEnd(Twig_Token $token) + { + return $token->test('endsandbox'); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'sandbox'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Set.php b/src/core/libs/Twig/TokenParser/Set.php new file mode 100755 index 0000000..84f7e94 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Set.php @@ -0,0 +1,83 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Defines a variable. + * + * <pre> + * {% set foo = 'foo' %} + * + * {% set foo = [1, 2] %} + * + * {% set foo = {'foo': 'bar'} %} + * + * {% set foo = 'foo' ~ 'bar' %} + * + * {% set foo, bar = 'foo', 'bar' %} + * + * {% set foo %}Some content{% endset %} + * </pre> + */ +class Twig_TokenParser_Set extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $names = $this->parser->getExpressionParser()->parseAssignmentExpression(); + + $capture = false; + if ($stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) { + $values = $this->parser->getExpressionParser()->parseMultitargetExpression(); + + $stream->expect(Twig_Token::BLOCK_END_TYPE); + + if (count($names) !== count($values)) { + throw new Twig_Error_Syntax("When using set, you must have the same number of variables and assignments.", $stream->getCurrent()->getLine(), $stream->getFilename()); + } + } else { + $capture = true; + + if (count($names) > 1) { + throw new Twig_Error_Syntax("When using set with a block, you cannot have a multi-target.", $stream->getCurrent()->getLine(), $stream->getFilename()); + } + + $stream->expect(Twig_Token::BLOCK_END_TYPE); + + $values = $this->parser->subparse(array($this, 'decideBlockEnd'), true); + $stream->expect(Twig_Token::BLOCK_END_TYPE); + } + + return new Twig_Node_Set($capture, $names, $values, $lineno, $this->getTag()); + } + + public function decideBlockEnd(Twig_Token $token) + { + return $token->test('endset'); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'set'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Spaceless.php b/src/core/libs/Twig/TokenParser/Spaceless.php new file mode 100755 index 0000000..1e3fa8f --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Spaceless.php @@ -0,0 +1,59 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Remove whitespaces between HTML tags. + * + * <pre> + * {% spaceless %} + * <div> + * <strong>foo</strong> + * </div> + * {% endspaceless %} + * + * {# output will be <div><strong>foo</strong></div> #} + * </pre> + */ +class Twig_TokenParser_Spaceless extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $lineno = $token->getLine(); + + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideSpacelessEnd'), true); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + + return new Twig_Node_Spaceless($body, $lineno, $this->getTag()); + } + + public function decideSpacelessEnd(Twig_Token $token) + { + return $token->test('endspaceless'); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'spaceless'; + } +} diff --git a/src/core/libs/Twig/TokenParser/Use.php b/src/core/libs/Twig/TokenParser/Use.php new file mode 100755 index 0000000..3ea68b1 --- /dev/null +++ b/src/core/libs/Twig/TokenParser/Use.php @@ -0,0 +1,76 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2011 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Imports blocks defined in another template into the current template. + * + * <pre> + * {% extends "base.html" %} + * + * {% use "blocks.html" %} + * + * {% block title %}{% endblock %} + * {% block content %}{% endblock %} + * </pre> + * + * @see http://www.twig-project.org/doc/templates.html#horizontal-reuse for details. + */ +class Twig_TokenParser_Use extends Twig_TokenParser +{ + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + */ + public function parse(Twig_Token $token) + { + $template = $this->parser->getExpressionParser()->parseExpression(); + $stream = $this->parser->getStream(); + + if (!$template instanceof Twig_Node_Expression_Constant) { + throw new Twig_Error_Syntax('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getFilename()); + } + + $targets = array(); + if ($stream->nextIf('with')) { + do { + $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); + + $alias = $name; + if ($stream->nextIf('as')) { + $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); + } + + $targets[$name] = new Twig_Node_Expression_Constant($alias, -1); + + if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { + break; + } + } while (true); + } + + $stream->expect(Twig_Token::BLOCK_END_TYPE); + + $this->parser->addTrait(new Twig_Node(array('template' => $template, 'targets' => new Twig_Node($targets)))); + } + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag() + { + return 'use'; + } +} diff --git a/src/core/libs/Twig/TokenParserBroker.php b/src/core/libs/Twig/TokenParserBroker.php new file mode 100755 index 0000000..ec3fba6 --- /dev/null +++ b/src/core/libs/Twig/TokenParserBroker.php @@ -0,0 +1,136 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * (c) 2010 Arnaud Le Blanc + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Default implementation of a token parser broker. + * + * @author Arnaud Le Blanc <arnaud.lb@gmail.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface +{ + protected $parser; + protected $parsers = array(); + protected $brokers = array(); + + /** + * Constructor. + * + * @param array|Traversable $parsers A Traversable of Twig_TokenParserInterface instances + * @param array|Traversable $brokers A Traversable of Twig_TokenParserBrokerInterface instances + */ + public function __construct($parsers = array(), $brokers = array()) + { + foreach ($parsers as $parser) { + if (!$parser instanceof Twig_TokenParserInterface) { + throw new LogicException('$parsers must a an array of Twig_TokenParserInterface'); + } + $this->parsers[$parser->getTag()] = $parser; + } + foreach ($brokers as $broker) { + if (!$broker instanceof Twig_TokenParserBrokerInterface) { + throw new LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface'); + } + $this->brokers[] = $broker; + } + } + + /** + * Adds a TokenParser. + * + * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance + */ + public function addTokenParser(Twig_TokenParserInterface $parser) + { + $this->parsers[$parser->getTag()] = $parser; + } + + /** + * Removes a TokenParser. + * + * @param Twig_TokenParserInterface $parser A Twig_TokenParserInterface instance + */ + public function removeTokenParser(Twig_TokenParserInterface $parser) + { + $name = $parser->getTag(); + if (isset($this->parsers[$name]) && $parser === $this->parsers[$name]) { + unset($this->parsers[$name]); + } + } + + /** + * Adds a TokenParserBroker. + * + * @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance + */ + public function addTokenParserBroker(Twig_TokenParserBroker $broker) + { + $this->brokers[] = $broker; + } + + /** + * Removes a TokenParserBroker. + * + * @param Twig_TokenParserBroker $broker A Twig_TokenParserBroker instance + */ + public function removeTokenParserBroker(Twig_TokenParserBroker $broker) + { + if (false !== $pos = array_search($broker, $this->brokers)) { + unset($this->brokers[$pos]); + } + } + + /** + * Gets a suitable TokenParser for a tag. + * + * First looks in parsers, then in brokers. + * + * @param string $tag A tag name + * + * @return null|Twig_TokenParserInterface A Twig_TokenParserInterface or null if no suitable TokenParser was found + */ + public function getTokenParser($tag) + { + if (isset($this->parsers[$tag])) { + return $this->parsers[$tag]; + } + $broker = end($this->brokers); + while (false !== $broker) { + $parser = $broker->getTokenParser($tag); + if (null !== $parser) { + return $parser; + } + $broker = prev($this->brokers); + } + } + + public function getParsers() + { + return $this->parsers; + } + + public function getParser() + { + return $this->parser; + } + + public function setParser(Twig_ParserInterface $parser) + { + $this->parser = $parser; + foreach ($this->parsers as $tokenParser) { + $tokenParser->setParser($parser); + } + foreach ($this->brokers as $broker) { + $broker->setParser($parser); + } + } +} diff --git a/src/core/libs/Twig/TokenParserBrokerInterface.php b/src/core/libs/Twig/TokenParserBrokerInterface.php new file mode 100755 index 0000000..3f006e3 --- /dev/null +++ b/src/core/libs/Twig/TokenParserBrokerInterface.php @@ -0,0 +1,45 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * (c) 2010 Arnaud Le Blanc + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Interface implemented by token parser brokers. + * + * Token parser brokers allows to implement custom logic in the process of resolving a token parser for a given tag name. + * + * @author Arnaud Le Blanc <arnaud.lb@gmail.com> + * @deprecated since 1.12 (to be removed in 2.0) + */ +interface Twig_TokenParserBrokerInterface +{ + /** + * Gets a TokenParser suitable for a tag. + * + * @param string $tag A tag name + * + * @return null|Twig_TokenParserInterface A Twig_TokenParserInterface or null if no suitable TokenParser was found + */ + public function getTokenParser($tag); + + /** + * Calls Twig_TokenParserInterface::setParser on all parsers the implementation knows of. + * + * @param Twig_ParserInterface $parser A Twig_ParserInterface interface + */ + public function setParser(Twig_ParserInterface $parser); + + /** + * Gets the Twig_ParserInterface. + * + * @return null|Twig_ParserInterface A Twig_ParserInterface instance or null + */ + public function getParser(); +} diff --git a/src/core/libs/Twig/TokenParserInterface.php b/src/core/libs/Twig/TokenParserInterface.php new file mode 100755 index 0000000..31e8d5d --- /dev/null +++ b/src/core/libs/Twig/TokenParserInterface.php @@ -0,0 +1,43 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2010 Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Interface implemented by token parsers. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface Twig_TokenParserInterface +{ + /** + * Sets the parser associated with this token parser + * + * @param $parser A Twig_Parser instance + */ + public function setParser(Twig_Parser $parser); + + /** + * Parses a token and returns a node. + * + * @param Twig_Token $token A Twig_Token instance + * + * @return Twig_NodeInterface A Twig_NodeInterface instance + * + * @throws Twig_Error_Syntax + */ + public function parse(Twig_Token $token); + + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag(); +} diff --git a/src/core/libs/Twig/TokenStream.php b/src/core/libs/Twig/TokenStream.php new file mode 100755 index 0000000..22f0428 --- /dev/null +++ b/src/core/libs/Twig/TokenStream.php @@ -0,0 +1,156 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) 2009 Fabien Potencier + * (c) 2009 Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +/** + * Represents a token stream. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Twig_TokenStream +{ + protected $tokens; + protected $current; + protected $filename; + + /** + * Constructor. + * + * @param array $tokens An array of tokens + * @param string $filename The name of the filename which tokens are associated with + */ + public function __construct(array $tokens, $filename = null) + { + $this->tokens = $tokens; + $this->current = 0; + $this->filename = $filename; + } + + /** + * Returns a string representation of the token stream. + * + * @return string + */ + public function __toString() + { + return implode("\n", $this->tokens); + } + + public function injectTokens(array $tokens) + { + $this->tokens = array_merge(array_slice($this->tokens, 0, $this->current), $tokens, array_slice($this->tokens, $this->current)); + } + + /** + * Sets the pointer to the next token and returns the old one. + * + * @return Twig_Token + */ + public function next() + { + if (!isset($this->tokens[++$this->current])) { + throw new Twig_Error_Syntax('Unexpected end of template', $this->tokens[$this->current - 1]->getLine(), $this->filename); + } + + return $this->tokens[$this->current - 1]; + } + + /** + * Tests a token, sets the pointer to the next one and returns it or throws a syntax error. + * + * @return Twig_Token|null The next token if the condition is true, null otherwise + */ + public function nextIf($primary, $secondary = null) + { + if ($this->tokens[$this->current]->test($primary, $secondary)) { + return $this->next(); + } + } + + /** + * Tests a token and returns it or throws a syntax error. + * + * @return Twig_Token + */ + public function expect($type, $value = null, $message = null) + { + $token = $this->tokens[$this->current]; + if (!$token->test($type, $value)) { + $line = $token->getLine(); + throw new Twig_Error_Syntax(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s)', + $message ? $message.'. ' : '', + Twig_Token::typeToEnglish($token->getType()), $token->getValue(), + Twig_Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''), + $line, + $this->filename + ); + } + $this->next(); + + return $token; + } + + /** + * Looks at the next token. + * + * @param integer $number + * + * @return Twig_Token + */ + public function look($number = 1) + { + if (!isset($this->tokens[$this->current + $number])) { + throw new Twig_Error_Syntax('Unexpected end of template', $this->tokens[$this->current + $number - 1]->getLine(), $this->filename); + } + + return $this->tokens[$this->current + $number]; + } + + /** + * Tests the current token + * + * @return Boolean + */ + public function test($primary, $secondary = null) + { + return $this->tokens[$this->current]->test($primary, $secondary); + } + + /** + * Checks if end of stream was reached + * + * @return Boolean + */ + public function isEOF() + { + return $this->tokens[$this->current]->getType() === Twig_Token::EOF_TYPE; + } + + /** + * Gets the current token + * + * @return Twig_Token + */ + public function getCurrent() + { + return $this->tokens[$this->current]; + } + + /** + * Gets the filename associated with this stream + * + * @return string + */ + public function getFilename() + { + return $this->filename; + } +} diff --git a/src/core/libs/Whoops/Exception/ErrorException.php b/src/core/libs/Whoops/Exception/ErrorException.php new file mode 100644 index 0000000..8a770af --- /dev/null +++ b/src/core/libs/Whoops/Exception/ErrorException.php @@ -0,0 +1,14 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Exception; +use ErrorException as BaseErrorException; + +/** + * Wraps ErrorException; mostly used for typing (at least now) + * to easily cleanup the stack trace of redundant info. + */ +class ErrorException extends BaseErrorException {} diff --git a/src/core/libs/Whoops/Exception/Frame.php b/src/core/libs/Whoops/Exception/Frame.php new file mode 100644 index 0000000..8895f26 --- /dev/null +++ b/src/core/libs/Whoops/Exception/Frame.php @@ -0,0 +1,252 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Exception; +use InvalidArgumentException; +use Serializable; + +class Frame implements Serializable +{ + /** + * @var array + */ + protected $frame; + + /** + * @var string + */ + protected $fileContentsCache; + + /** + * @var array[] + */ + protected $comments = array(); + + /** + * @param array[] + */ + public function __construct(array $frame) + { + $this->frame = $frame; + } + + /** + * @param bool $shortened + * @return string|null + */ + public function getFile($shortened = false) + { + if(empty($this->frame['file'])) { + return null; + } + + $file = $this->frame['file']; + + // Check if this frame occurred within an eval(). + // @todo: This can be made more reliable by checking if we've entered + // eval() in a previous trace, but will need some more work on the upper + // trace collector(s). + if(preg_match('/^(.*)\((\d+)\) : eval\(\)\'d code$/', $file, $matches)) { + $file = $this->frame['file'] = $matches[1]; + $this->frame['line'] = (int) $matches[2]; + } + + if($shortened && is_string($file)) { + // Replace the part of the path that all frames have in common, and add 'soft hyphens' for smoother line-breaks. + $dirname = dirname(dirname(dirname(dirname(dirname(dirname(__DIR__)))))); + $file = str_replace($dirname, "…", $file); + $file = str_replace("/", "/&shy;", $file); + } + + return $file; + } + + /** + * @return int|null + */ + public function getLine() + { + return isset($this->frame['line']) ? $this->frame['line'] : null; + } + + /** + * @return string|null + */ + public function getClass() + { + return isset($this->frame['class']) ? $this->frame['class'] : null; + } + + /** + * @return string|null + */ + public function getFunction() + { + return isset($this->frame['function']) ? $this->frame['function'] : null; + } + + /** + * @return array + */ + public function getArgs() + { + return isset($this->frame['args']) ? (array) $this->frame['args'] : array(); + } + + /** + * Returns the full contents of the file for this frame, + * if it's known. + * @return string|null + */ + public function getFileContents() + { + if($this->fileContentsCache === null && $filePath = $this->getFile()) { + + // Return null if the file doesn't actually exist - this may + // happen in cases where the filename is provided as, for + // example, 'Unknown' + if(!is_file($filePath)) { + return null; + } + + $this->fileContentsCache = file_get_contents($filePath); + } + + return $this->fileContentsCache; + } + + /** + * Adds a comment to this frame, that can be received and + * used by other handlers. For example, the PrettyPage handler + * can attach these comments under the code for each frame. + * + * An interesting use for this would be, for example, code analysis + * & annotations. + * + * @param string $comment + * @param string $context Optional string identifying the origin of the comment + */ + public function addComment($comment, $context = 'global') + { + $this->comments[] = array( + 'comment' => $comment, + 'context' => $context + ); + } + + /** + * Returns all comments for this frame. Optionally allows + * a filter to only retrieve comments from a specific + * context. + * + * @param string $filter + * @return array[] + */ + public function getComments($filter = null) + { + $comments = $this->comments; + + if($filter !== null) { + $comments = array_filter($comments, function($c) use($filter) { + return $c['context'] == $filter; + }); + } + + return $comments; + } + + /** + * Returns the array containing the raw frame data from which + * this Frame object was built + * + * @return array + */ + public function getRawFrame() + { + return $this->frame; + } + + /** + * Returns the contents of the file for this frame as an + * array of lines, and optionally as a clamped range of lines. + * + * NOTE: lines are 0-indexed + * + * @example + * Get all lines for this file + * $frame->getFileLines(); // => array( 0 => '<?php', 1 => '...', ...) + * @example + * Get one line for this file, starting at line 10 (zero-indexed, remember!) + * $frame->getFileLines(9, 1); // array( 10 => '...', 11 => '...') + * + * @throws InvalidArgumentException if $length is less than or equal to 0 + * @param int $start + * @param int $length + * @return string[]|null + */ + public function getFileLines($start = 0, $length = null) + { + if(null !== ($contents = $this->getFileContents())) { + $lines = explode("\n", $contents); + + // Get a subset of lines from $start to $end + if($length !== null) + { + $start = (int) $start; + $length = (int) $length; + if ($start < 0) { + $start = 0; + } + + if($length <= 0) { + throw new InvalidArgumentException( + "\$length($length) cannot be lower or equal to 0" + ); + } + + $lines = array_slice($lines, $start, $length, true); + } + + return $lines; + } + } + + /** + * Implements the Serializable interface, with special + * steps to also save the existing comments. + * + * @see Serializable::serialize + * @return string + */ + public function serialize() + { + $frame = $this->frame; + if(!empty($this->comments)) { + $frame['_comments'] = $this->comments; + } + + return serialize($frame); + } + + /** + * Unserializes the frame data, while also preserving + * any existing comment data. + * + * @see Serializable::unserialize + * @param string $serializedFrame + */ + public function unserialize($serializedFrame) + { + $frame = unserialize($serializedFrame); + + if(!empty($frame['_comments'])) { + $this->comments = $frame['_comments']; + unset($frame['_comments']); + } + + $this->frame = $frame; + } +} diff --git a/src/core/libs/Whoops/Exception/FrameCollection.php b/src/core/libs/Whoops/Exception/FrameCollection.php new file mode 100644 index 0000000..5708712 --- /dev/null +++ b/src/core/libs/Whoops/Exception/FrameCollection.php @@ -0,0 +1,122 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Exception; +use Whoops\Exception\Frame; +use UnexpectedValueException; +use IteratorAggregate; +use ArrayIterator; +use Serializable; +use Countable; + +/** + * Exposes a fluent interface for dealing with an ordered list + * of stack-trace frames. + */ +class FrameCollection implements IteratorAggregate, Serializable, Countable +{ + /** + * @var array[] + */ + private $frames; + + /** + * @param array $frames + */ + public function __construct(array $frames) + { + $this->frames = array_map(function($frame) { + return new Frame($frame); + }, $frames); + } + + /** + * Filters frames using a callable, returns the same FrameCollection + * + * @param callable $callable + * @return FrameCollection + */ + public function filter($callable) + { + $this->frames = array_filter($this->frames, $callable); + return $this; + } + + /** + * Map the collection of frames + * + * @param callable $callable + * @return FrameCollection + */ + public function map($callable) + { + // Contain the map within a higher-order callable + // that enforces type-correctness for the $callable + $this->frames = array_map(function($frame) use($callable) { + $frame = call_user_func($callable, $frame); + + if(!$frame instanceof Frame) { + throw new UnexpectedValueException( + "Callable to " . __METHOD__ . " must return a Frame object" + ); + } + + return $frame; + }, $this->frames); + + return $this; + } + + /** + * Returns an array with all frames, does not affect + * the internal array. + * + * @todo If this gets any more complex than this, + * have getIterator use this method. + * @see FrameCollection::getIterator + * @return array + */ + public function getArray() + { + return $this->frames; + } + + /** + * @see IteratorAggregate::getIterator + * @return ArrayIterator + */ + public function getIterator() + { + return new ArrayIterator($this->frames); + } + + /** + * @see Countable::count + * @return int + */ + public function count() + { + return count($this->frames); + } + + /** + * @see Serializable::serialize + * @return string + */ + public function serialize() + { + return serialize($this->frames); + } + + /** + * @see Serializable::unserialize + * @param string $serializedFrames + */ + public function unserialize($serializedFrames) + { + $this->frames = unserialize($serializedFrames); + } +} diff --git a/src/core/libs/Whoops/Exception/Inspector.php b/src/core/libs/Whoops/Exception/Inspector.php new file mode 100644 index 0000000..2ecf757 --- /dev/null +++ b/src/core/libs/Whoops/Exception/Inspector.php @@ -0,0 +1,115 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Exception; +use Whoops\Exception\FrameCollection; +use Whoops\Exception\ErrorException; +use Exception; + +class Inspector +{ + /** + * @var Exception + */ + private $exception; + + /** + * @var FrameCollection + */ + private $frames; + + /** + * @param Exception $exception The exception to inspect + */ + public function __construct(Exception $exception) + { + $this->exception = $exception; + } + + /** + * @return Exception + */ + public function getException() + { + return $this->exception; + } + + /** + * @return string + */ + public function getExceptionName() + { + return get_class($this->exception); + } + + /** + * @return string + */ + public function getExceptionMessage() + { + return $this->exception->getMessage(); + } + + /** + * Returns an iterator for the inspected exception's + * frames. + * @return FrameCollection + */ + public function getFrames() + { + if($this->frames === null) { + $frames = $this->exception->getTrace(); + + // If we're handling an ErrorException thrown by Whoops, + // get rid of the last frame, which matches the handleError method, + // and do not add the current exception to trace. We ensure that + // the next frame does have a filename / linenumber, though. + if($this->exception instanceof ErrorException && empty($frames[1]['line'])) { + $frames = array($this->getFrameFromError($this->exception)); + } else { + $firstFrame = $this->getFrameFromException($this->exception); + array_unshift($frames, $firstFrame); + } + $this->frames = new FrameCollection($frames); + } + + return $this->frames; + } + + /** + * Given an exception, generates an array in the format + * generated by Exception::getTrace() + * @param Exception $exception + * @return array + */ + protected function getFrameFromException(Exception $exception) + { + return array( + 'file' => $exception->getFile(), + 'line' => $exception->getLine(), + 'class' => get_class($exception), + 'args' => array( + $exception->getMessage() + ) + ); + } + + /** + * Given an error, generates an array in the format + * generated by ErrorException + * @param ErrorException $exception + * @return array + */ + protected function getFrameFromError(ErrorException $exception) + { + return array( + 'file' => $exception->getFile(), + 'line' => $exception->getLine(), + 'class' => null, + 'args' => array() + ); + } +} diff --git a/src/core/libs/Whoops/Handler/CallbackHandler.php b/src/core/libs/Whoops/Handler/CallbackHandler.php new file mode 100644 index 0000000..b039be8 --- /dev/null +++ b/src/core/libs/Whoops/Handler/CallbackHandler.php @@ -0,0 +1,49 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Handler; +use Whoops\Handler\Handler; +use InvalidArgumentException; + +/** + * Wrapper for Closures passed as handlers. Can be used + * directly, or will be instantiated automagically by Whoops\Run + * if passed to Run::pushHandler + */ +class CallbackHandler extends Handler +{ + /** + * @var callable + */ + protected $callable; + + /** + * @throws InvalidArgumentException If argument is not callable + * @param callable $callable + */ + public function __construct($callable) + { + if(!is_callable($callable)) { + throw new InvalidArgumentException( + 'Argument to ' . __METHOD__ . ' must be valid callable' + ); + } + + $this->callable = $callable; + } + + /** + * @return int|null + */ + public function handle() + { + $exception = $this->getException(); + $inspector = $this->getInspector(); + $run = $this->getRun(); + + return call_user_func($this->callable, $exception, $inspector, $run); + } +} diff --git a/src/core/libs/Whoops/Handler/Handler.php b/src/core/libs/Whoops/Handler/Handler.php new file mode 100644 index 0000000..a6ca5c4 --- /dev/null +++ b/src/core/libs/Whoops/Handler/Handler.php @@ -0,0 +1,89 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Handler; +use Whoops\Handler\HandlerInterface; +use Whoops\Exception\Inspector; +use Whoops\Run; +use Exception; + +/** + * Abstract implementation of a Handler. + */ +abstract class Handler implements HandlerInterface +{ + /** + * Return constants that can be returned from Handler::handle + * to message the handler walker. + */ + const DONE = 0x10; // returning this is optional, only exists for + // semantic purposes + const LAST_HANDLER = 0x20; + const QUIT = 0x30; + + /** + * @var Run + */ + private $run; + + /** + * @var Inspector $inspector + */ + private $inspector; + + /** + * @var Exception $exception + */ + private $exception; + + /** + * @param Run $run + */ + public function setRun(Run $run) + { + $this->run = $run; + } + + /** + * @return Run + */ + protected function getRun() + { + return $this->run; + } + + /** + * @param Inspector $inspector + */ + public function setInspector(Inspector $inspector) + { + $this->inspector = $inspector; + } + + /** + * @return Inspector + */ + protected function getInspector() + { + return $this->inspector; + } + + /** + * @param Exception $exception + */ + public function setException(Exception $exception) + { + $this->exception = $exception; + } + + /** + * @return Exception + */ + protected function getException() + { + return $this->exception; + } +} diff --git a/src/core/libs/Whoops/Handler/HandlerInterface.php b/src/core/libs/Whoops/Handler/HandlerInterface.php new file mode 100644 index 0000000..abb4078 --- /dev/null +++ b/src/core/libs/Whoops/Handler/HandlerInterface.php @@ -0,0 +1,33 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Handler; +use Whoops\Exception\Inspector; +use Whoops\Run; +use Exception; + +interface HandlerInterface +{ + /** + * @return int|null A handler may return nothing, or a Handler::HANDLE_* constant + */ + public function handle(); + + /** + * @param Run $run + */ + public function setRun(Run $run); + + /** + * @param Exception $exception + */ + public function setException(Exception $exception); + + /** + * @param Inspector $inspector + */ + public function setInspector(Inspector $inspector); +} diff --git a/src/core/libs/Whoops/Handler/JsonResponseHandler.php b/src/core/libs/Whoops/Handler/JsonResponseHandler.php new file mode 100644 index 0000000..a5e8d62 --- /dev/null +++ b/src/core/libs/Whoops/Handler/JsonResponseHandler.php @@ -0,0 +1,109 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Handler; +use Whoops\Handler\Handler; +use Whoops\Exception\Frame; + +/** + * Catches an exception and converts it to a JSON + * response. Additionally can also return exception + * frames for consumption by an API. + */ +class JsonResponseHandler extends Handler +{ + /** + * @var bool + */ + private $returnFrames = false; + + /** + * @var bool + */ + private $onlyForAjaxRequests = false; + + /** + * @param bool|null $returnFrames + * @return null|bool + */ + public function addTraceToOutput($returnFrames = null) + { + if(func_num_args() == 0) { + return $this->returnFrames; + } + + $this->returnFrames = (bool) $returnFrames; + } + + /** + * @param bool|null $onlyForAjaxRequests + * @return null|bool + */ + public function onlyForAjaxRequests($onlyForAjaxRequests = null) + { + if(func_num_args() == 0) { + return $this->onlyForAjaxRequests; + } + + $this->onlyForAjaxRequests = (bool) $onlyForAjaxRequests; + } + + /** + * Check, if possible, that this execution was triggered by an AJAX request. + * + * @return bool + */ + private function isAjaxRequest() + { + return ( + !empty($_SERVER['HTTP_X_REQUESTED_WITH']) + && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') + ; + } + + /** + * @return int + */ + public function handle() + { + if($this->onlyForAjaxRequests() && !$this->isAjaxRequest()) { + return Handler::DONE; + } + + $exception = $this->getException(); + + $response = array( + 'error' => array( + 'type' => get_class($exception), + 'message' => $exception->getMessage(), + 'file' => $exception->getFile(), + 'line' => $exception->getLine() + ) + ); + + if($this->addTraceToOutput()) { + $inspector = $this->getInspector(); + $frames = $inspector->getFrames(); + $frameData = array(); + + foreach($frames as $frame) { + /** @var Frame $frame */ + $frameData[] = array( + 'file' => $frame->getFile(), + 'line' => $frame->getLine(), + 'function' => $frame->getFunction(), + 'class' => $frame->getClass(), + 'args' => $frame->getArgs() + ); + } + + $response['error']['trace'] = $frameData; + } + + echo json_encode($response); + return Handler::QUIT; + } +} diff --git a/src/core/libs/Whoops/Handler/PrettyPageHandler.php b/src/core/libs/Whoops/Handler/PrettyPageHandler.php new file mode 100644 index 0000000..33c215f --- /dev/null +++ b/src/core/libs/Whoops/Handler/PrettyPageHandler.php @@ -0,0 +1,333 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Handler; +use Whoops\Handler\Handler; +use InvalidArgumentException; + +class PrettyPageHandler extends Handler +{ + /** + * @var string + */ + private $resourcesPath; + + /** + * @var array[] + */ + private $extraTables = array(); + + /** + * @var string + */ + private $pageTitle = 'Whoops! There was an error.'; + + /** + * A string identifier for a known IDE/text editor, or a closure + * that resolves a string that can be used to open a given file + * in an editor. If the string contains the special substrings + * %file or %line, they will be replaced with the correct data. + * + * @example + * "txmt://open?url=%file&line=%line" + * @var mixed $editor + */ + protected $editor; + + /** + * A list of known editor strings + * @var array + */ + protected $editors = array( + 'sublime' => 'subl://open?url=file://%file&line=%line', + 'textmate' => 'txmt://open?url=file://%file&line=%line', + 'emacs' => 'emacs://open?url=file://%file&line=%line', + 'macvim' => 'mvim://open/?url=file://%file&line=%line' + ); + + /** + * Constructor. + */ + public function __construct() + { + if (ini_get('xdebug.file_link_format') || extension_loaded('xdebug')) { + // Register editor using xdebug's file_link_format option. + $this->editors['xdebug'] = function($file, $line) { + return str_replace(array('%f', '%l'), array($file, $line), ini_get('xdebug.file_link_format')); + }; + } + } + + /** + * @return int|null + */ + public function handle() + { + // Check conditions for outputting HTML: + // @todo: make this more robust + if(php_sapi_name() === 'cli' && !isset($_ENV['whoops-test'])) { + return Handler::DONE; + } + + // Get the 'pretty-template.php' template file + // @todo: this can be made more dynamic &&|| cleaned-up + if(!($resources = $this->getResourcesPath())) { + $resources = __DIR__ . '/../Resources'; + } + + $templateFile = "$resources/pretty-template.php"; + + // @todo: Make this more reliable, + // possibly by adding methods to append CSS & JS to the page + $cssFile = "$resources/pretty-page.css"; + + // Prepare the $v global variable that will pass relevant + // information to the template + $inspector = $this->getInspector(); + $frames = $inspector->getFrames(); + + $v = (object) array( + 'title' => $this->getPageTitle(), + 'name' => explode('\\', $inspector->getExceptionName()), + 'message' => $inspector->getException()->getMessage(), + 'frames' => $frames, + 'hasFrames' => !!count($frames), + 'handler' => $this, + 'handlers' => $this->getRun()->getHandlers(), + 'pageStyle' => file_get_contents($cssFile), + + 'tables' => array( + 'Server/Request Data' => $_SERVER, + 'GET Data' => $_GET, + 'POST Data' => $_POST, + 'Files' => $_FILES, + 'Cookies' => $_COOKIE, + 'Session' => isset($_SESSION) ? $_SESSION: array(), + 'Environment Variables' => $_ENV + ) + ); + + $extraTables = array_map(function($table) { + return $table instanceof \Closure ? $table() : $table; + }, $this->getDataTables()); + + // Add extra entries list of data tables: + $v->tables = array_merge($extraTables, $v->tables); + + call_user_func(function() use($templateFile, $v) { + // $e -> cleanup output, optionally preserving URIs as anchors: + $e = function($_, $allowLinks = false) { + $escaped = htmlspecialchars($_, ENT_QUOTES, 'UTF-8'); + + // convert URIs to clickable anchor elements: + if($allowLinks) { + $escaped = preg_replace( + '@([A-z]+?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@', + "<a href=\"$1\" target=\"_blank\">$1</a>", $escaped + ); + } + + return $escaped; + }; + + // $slug -> sluggify string (i.e: Hello world! -> hello-world) + $slug = function($_) { + $_ = str_replace(" ", "-", $_); + $_ = preg_replace('/[^\w\d\-\_]/i', '', $_); + return strtolower($_); + }; + + require $templateFile; + }); + + + return Handler::QUIT; + } + + /** + * Adds an entry to the list of tables displayed in the template. + * The expected data is a simple associative array. Any nested arrays + * will be flattened with print_r + * @param string $label + * @param array $data + */ + public function addDataTable($label, array $data) + { + $this->extraTables[$label] = $data; + } + + /** + * Lazily adds an entry to the list of tables displayed in the table. + * The supplied callback argument will be called when the error is rendered, + * it should produce a simple associative array. Any nested arrays will + * be flattened with print_r. + * + * @throws InvalidArgumentException If $callback is not callable + * @param string $label + * @param callable $callback Callable returning an associative array + */ + public function addDataTableCallback($label, /* callable */ $callback) + { + if (!is_callable($callback)) { + throw new InvalidArgumentException('Expecting callback argument to be callable'); + } + + $this->extraTables[$label] = function() use ($callback) { + try { + $result = call_user_func($callback); + + // Only return the result if it can be iterated over by foreach(). + return is_array($result) || $result instanceof \Traversable ? $result : array(); + } catch (\Exception $e) { + // Don't allow failure to break the rendering of the original exception. + return array(); + } + }; + } + + /** + * Returns all the extra data tables registered with this handler. + * Optionally accepts a 'label' parameter, to only return the data + * table under that label. + * @param string|null $label + * @return array[] + */ + public function getDataTables($label = null) + { + if($label !== null) { + return isset($this->extraTables[$label]) ? + $this->extraTables[$label] : array(); + } + + return $this->extraTables; + } + + /** + * Adds an editor resolver, identified by a string + * name, and that may be a string path, or a callable + * resolver. If the callable returns a string, it will + * be set as the file reference's href attribute. + * + * @example + * $run->addEditor('macvim', "mvim://open?url=file://%file&line=%line") + * @example + * $run->addEditor('remove-it', function($file, $line) { + * unlink($file); + * return "http://stackoverflow.com"; + * }); + * @param string $identifier + * @param string $resolver + */ + public function addEditor($identifier, $resolver) + { + $this->editors[$identifier] = $resolver; + } + + /** + * Set the editor to use to open referenced files, by a string + * identifier, or a callable that will be executed for every + * file reference, with a $file and $line argument, and should + * return a string. + * + * @example + * $run->setEditor(function($file, $line) { return "file:///{$file}"; }); + * @example + * $run->setEditor('sublime'); + * + * @throws InvalidArgumentException If invalid argument identifier provided + * @param string|callable $editor + */ + public function setEditor($editor) + { + if(!is_callable($editor) && !isset($this->editors[$editor])) { + throw new InvalidArgumentException( + "Unknown editor identifier: $editor. Known editors:" . + implode(",", array_keys($this->editors)) + ); + } + + $this->editor = $editor; + } + + /** + * Given a string file path, and an integer file line, + * executes the editor resolver and returns, if available, + * a string that may be used as the href property for that + * file reference. + * + * @throws InvalidArgumentException If editor resolver does not return a string + * @param string $filePath + * @param int $line + * @return string|bool + */ + public function getEditorHref($filePath, $line) + { + if($this->editor === null) { + return false; + } + + $editor = $this->editor; + if(is_string($editor)) { + $editor = $this->editors[$editor]; + } + + if(is_callable($editor)) { + $editor = call_user_func($editor, $filePath, $line); + } + + // Check that the editor is a string, and replace the + // %line and %file placeholders: + if(!is_string($editor)) { + throw new InvalidArgumentException( + __METHOD__ . " should always resolve to a string; got something else instead" + ); + } + + $editor = str_replace("%line", rawurlencode($line), $editor); + $editor = str_replace("%file", rawurlencode($filePath), $editor); + + return $editor; + } + + /** + * @var string + */ + public function setPageTitle($title) + { + $this->pageTitle = (string) $title; + } + + /** + * @return string + */ + public function getPageTitle() + { + return $this->pageTitle; + } + + /** + * @return string + */ + public function getResourcesPath() + { + return $this->resourcesPath; + } + + /** + * @throws InvalidArgumentException If argument is not a valid directory + * @param string $resourcesPath + */ + public function setResourcesPath($resourcesPath) + { + if(!is_dir($resourcesPath)) { + throw new InvalidArgumentException( + "$resourcesPath is not a valid directory" + ); + } + + $this->resourcesPath = $resourcesPath; + } +} diff --git a/src/core/libs/Whoops/Handler/XmlResponseHandler.php b/src/core/libs/Whoops/Handler/XmlResponseHandler.php new file mode 100644 index 0000000..d79331e --- /dev/null +++ b/src/core/libs/Whoops/Handler/XmlResponseHandler.php @@ -0,0 +1,137 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Handler; + +use SimpleXMLElement; +use Whoops\Exception\Frame; +use Whoops\Handler\Handler; + +/** + * Catches an exception and converts it to an XML + * response. Additionally can also return exception + * frames for consumption by an API. + */ +class XmlResponseHandler extends Handler +{ + /** + * @var bool + */ + private $returnFrames = false; + + /** + * @param bool|null $returnFrames + * @return null|bool + */ + public function addTraceToOutput($returnFrames = null) + { + if(func_num_args() == 0) { + return $this->returnFrames; + } + + $this->returnFrames = (bool) $returnFrames; + } + + /** + * @return int + */ + public function handle() + { + $exception = $this->getException(); + + $response = array( + 'error' => array( + 'type' => get_class($exception), + 'message' => $exception->getMessage(), + 'file' => $exception->getFile(), + 'line' => $exception->getLine() + ) + ); + + if($this->addTraceToOutput()) { + $inspector = $this->getInspector(); + $frames = $inspector->getFrames(); + $frameData = array(); + + foreach($frames as $frame) { + /** @var Frame $frame */ + $frameData[] = array( + 'file' => $frame->getFile(), + 'line' => $frame->getLine(), + 'function' => $frame->getFunction(), + 'class' => $frame->getClass(), + 'args' => $frame->getArgs() + ); + } + + $response['error']['trace'] = array_flip($frameData); + } + + echo $this->toXml($response); + + return Handler::QUIT; + } + + /** + * @param SimpleXMLElement $node Node to append data to, will be modified in place + * @param array|Traversable $data + * @return SimpleXMLElement The modified node, for chaining + */ + private static function addDataToNode(\SimpleXMLElement $node, $data) + { + assert('is_array($data) || $node instanceof Traversable'); + + foreach($data as $key => $value) + { + if (is_numeric($key)) + { + // Convert the key to a valid string + $key = "unknownNode_". (string) $key; + } + + // Delete any char not allowed in XML element names + $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key); + + if (is_array($value)) + { + $child = $node->addChild($key); + self::addDataToNode($child, $value); + } + else + { + $value = str_replace('&', '&amp;', print_r($value, true)); + $node->addChild($key, $value); + } + } + + return $node; + } + + /** + * The main function for converting to an XML document. + * + * @param array|Traversable $data + * @return string XML + */ + private static function toXml($data) + { + assert('is_array($data) || $node instanceof Traversable'); + + // turn off compatibility mode as simple xml throws a wobbly if you don't. + $compatibilityMode = ini_get('zend.ze1_compatibility_mode'); + if ($compatibilityMode) { + ini_set('zend.ze1_compatibility_mode', 0); + } + + $node = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><root />"); + $xml = self::addDataToNode($node, $data)->asXML(); + + if ($compatibilityMode) { + ini_set('zend.ze1_compatibility_mode', $compatibilityMode); + } + return $xml; + } +} diff --git a/src/core/libs/Whoops/LICENSE.md b/src/core/libs/Whoops/LICENSE.md new file mode 100644 index 0000000..17707b3 --- /dev/null +++ b/src/core/libs/Whoops/LICENSE.md @@ -0,0 +1,19 @@ +#The MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/core/libs/Whoops/Provider/Phalcon/WhoopsServiceProvider.php b/src/core/libs/Whoops/Provider/Phalcon/WhoopsServiceProvider.php new file mode 100644 index 0000000..89dc8f7 --- /dev/null +++ b/src/core/libs/Whoops/Provider/Phalcon/WhoopsServiceProvider.php @@ -0,0 +1,78 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Provider\Phalcon; + +use Whoops\Run; +use Whoops\Handler\PrettyPageHandler; +use Whoops\Handler\JsonResponseHandler; +use Phalcon\DI; +use Phalcon\DI\Exception; + +class WhoopsServiceProvider +{ + /** + * @param DI $di + */ + public function __construct(DI $di = null) + { + if (!$di) { + $di = DI::getDefault(); + } + + // There's only ever going to be one error page...right? + $di->setShared('whoops.pretty_page_handler', function() { + return new PrettyPageHandler; + }); + + // There's only ever going to be one error page...right? + $di->setShared('whoops.json_response_handler', function() { + $jsonHandler = new JsonResponseHandler; + $jsonHandler->onlyForAjaxRequests(true); + return $jsonHandler; + }); + + // Retrieves info on the Phalcon environment and ships it off + // to the PrettyPageHandler's data tables: + // This works by adding a new handler to the stack that runs + // before the error page, retrieving the shared page handler + // instance, and working with it to add new data tables + $phalcon_info_handler = function() use($di) { + try { + $request = $di['request']; + } catch (Exception $e) { + // This error occurred too early in the application's life + // and the request instance is not yet available. + return; + } + + // Request info: + $di['whoops.pretty_page_handler']->addDataTable('Phalcon Application (Request)', array( + 'URI' => $request->getScheme().'://'.$request->getServer('HTTP_HOST').$request->getServer('REQUEST_URI'), + 'Request URI' => $request->getServer('REQUEST_URI'), + 'Path Info' => $request->getServer('PATH_INFO'), + 'Query String'=> $request->getServer('QUERY_STRING') ?: '<none>', + 'HTTP Method' => $request->getMethod(), + 'Script Name' => $request->getServer('SCRIPT_NAME'), + //'Base Path' => $request->getBasePath(), + //'Base URL' => $request->getBaseUrl(), + 'Scheme' => $request->getScheme(), + 'Port' => $request->getServer('SERVER_PORT'), + 'Host' => $request->getServerName(), + )); + }; + + $di->setShared('whoops', function() use($di, $phalcon_info_handler) { + $run = new Run; + $run->pushHandler($di['whoops.pretty_page_handler']); + $run->pushHandler($phalcon_info_handler); + $run->pushHandler($di['whoops.json_response_handler']); + return $run; + }); + + $di['whoops']->register(); + } +} diff --git a/src/core/libs/Whoops/Provider/Silex/WhoopsServiceProvider.php b/src/core/libs/Whoops/Provider/Silex/WhoopsServiceProvider.php new file mode 100644 index 0000000..519ddfc --- /dev/null +++ b/src/core/libs/Whoops/Provider/Silex/WhoopsServiceProvider.php @@ -0,0 +1,85 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops\Provider\Silex; +use Whoops\Run; +use Whoops\Handler\PrettyPageHandler; +use Silex\ServiceProviderInterface; +use Silex\Application; +use Symfony\Component\HttpFoundation\Request; +use RuntimeException; + +class WhoopsServiceProvider implements ServiceProviderInterface +{ + /** + * @param Application $app + */ + public function register(Application $app) + { + // There's only ever going to be one error page...right? + $app['whoops.error_page_handler'] = $app->share(function() { + return new PrettyPageHandler; + }); + + // Retrieves info on the Silex environment and ships it off + // to the PrettyPageHandler's data tables: + // This works by adding a new handler to the stack that runs + // before the error page, retrieving the shared page handler + // instance, and working with it to add new data tables + $app['whoops.silex_info_handler'] = $app->protect(function() use($app) { + try { + /** @var Request $request */ + $request = $app['request']; + } catch (RuntimeException $e) { + // This error occurred too early in the application's life + // and the request instance is not yet available. + return; + } + + /** @var PrettyPageHandler $errorPageHandler */ + $errorPageHandler = $app["whoops.error_page_handler"]; + + // General application info: + $errorPageHandler->addDataTable('Silex Application', array( + 'Charset' => $app['charset'], + 'Locale' => $app['locale'], + 'Route Class' => $app['route_class'], + 'Dispatcher Class' => $app['dispatcher_class'], + 'Application Class'=> get_class($app) + )); + + // Request info: + $errorPageHandler->addDataTable('Silex Application (Request)', array( + 'URI' => $request->getUri(), + 'Request URI' => $request->getRequestUri(), + 'Path Info' => $request->getPathInfo(), + 'Query String'=> $request->getQueryString() ?: '<none>', + 'HTTP Method' => $request->getMethod(), + 'Script Name' => $request->getScriptName(), + 'Base Path' => $request->getBasePath(), + 'Base URL' => $request->getBaseUrl(), + 'Scheme' => $request->getScheme(), + 'Port' => $request->getPort(), + 'Host' => $request->getHost(), + )); + }); + + $app['whoops'] = $app->share(function() use($app) { + $run = new Run; + $run->pushHandler($app['whoops.error_page_handler']); + $run->pushHandler($app['whoops.silex_info_handler']); + return $run; + }); + + $app->error(array($app['whoops'], Run::EXCEPTION_HANDLER)); + $app['whoops']->register(); + } + + /** + * @see Silex\ServiceProviderInterface::boot + */ + public function boot(Application $app) {} +} diff --git a/src/core/libs/Whoops/Provider/Zend/ExceptionStrategy.php b/src/core/libs/Whoops/Provider/Zend/ExceptionStrategy.php new file mode 100644 index 0000000..e0731de --- /dev/null +++ b/src/core/libs/Whoops/Provider/Zend/ExceptionStrategy.php @@ -0,0 +1,59 @@ +<?php +/** + * ZF2 Integration for Whoops + * @author Balázs Németh <zsilbi@zsilbi.hu> + */ + +namespace Whoops\Provider\Zend; + +use Whoops\Run; + +use Zend\Mvc\View\Http\ExceptionStrategy as BaseExceptionStrategy; +use Zend\Mvc\MvcEvent; +use Zend\Mvc\Application; + +class ExceptionStrategy extends BaseExceptionStrategy { + + protected $run; + + public function __construct(Run $run) { + $this->run = $run; + return $this; + } + + public function prepareExceptionViewModel(MvcEvent $event) { + // Do nothing if no error in the event + $error = $event->getError(); + if (empty($error)) { + return; + } + + // Do nothing if the result is a response object + $result = $event->getResult(); + if ($result instanceof Response) { + return; + } + + switch ($error) { + case Application::ERROR_CONTROLLER_NOT_FOUND: + case Application::ERROR_CONTROLLER_INVALID: + case Application::ERROR_ROUTER_NO_MATCH: + // Specifically not handling these + return; + + case Application::ERROR_EXCEPTION: + default: + $exception = $event->getParam('exception'); + if($exception) { + $response = $event->getResponse(); + if (!$response || $response->getStatusCode() === 200) { + header('HTTP/1.0 500 Internal Server Error', true, 500); + } + ob_clean(); + $this->run->handleException($event->getParam('exception')); + } + break; + } + } + +} diff --git a/src/core/libs/Whoops/Provider/Zend/Module.php b/src/core/libs/Whoops/Provider/Zend/Module.php new file mode 100644 index 0000000..44f14ca --- /dev/null +++ b/src/core/libs/Whoops/Provider/Zend/Module.php @@ -0,0 +1,106 @@ +<?php +/** + * ZF2 Integration for Whoops + * @author Balázs Németh <zsilbi@zsilbi.hu> + * + * The Whoops directory should be added as a module to ZF2 (/vendor/Whoops) + * + * Whoops must be added as the first module + * For example: + * 'modules' => array( + * 'Whoops', + * 'Application', + * ), + * + * This file should be moved next to Whoops/Run.php (/vendor/Whoops/Module.php) + * + */ + +namespace Whoops; + +use Whoops\Run; +use Whoops\Provider\Zend\ExceptionStrategy; +use Whoops\Provider\Zend\RouteNotFoundStrategy; +use Whoops\Handler\JsonResponseHandler; +use Whoops\Handler\PrettyPageHandler; +use Zend\EventManager\EventInterface; +use Zend\Console\Request as ConsoleRequest; + +class Module +{ + protected $run; + + public function onBootstrap(EventInterface $event) + { + $prettyPageHandler = new PrettyPageHandler(); + + // Set editor + $config = $event->getApplication()->getServiceManager()->get('Config'); + if (isset($config['view_manager']['editor'])) { + $prettyPageHandler->setEditor($config['view_manager']['editor']); + } + + + $this->run = new Run(); + $this->run->register(); + $this->run->pushHandler($prettyPageHandler); + + $this->attachListeners($event); + } + + public function getAutoloaderConfig() + { + return array( + 'Zend\Loader\StandardAutoloader' => array( + 'namespaces' => array( + __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__, + ), + ), + ); + } + + private function attachListeners(EventInterface $event) + { + $request = $event->getRequest(); + $application = $event->getApplication(); + $services = $application->getServiceManager(); + $events = $application->getEventManager(); + $config = $services->get('Config'); + + //Display exceptions based on configuration and console mode + if ($request instanceof ConsoleRequest || empty($config['view_manager']['display_exceptions'])) + return; + + $jsonHandler = new JsonResponseHandler(); + + if (!empty($config['view_manager']['json_exceptions']['show_trace'])) { + //Add trace to the JSON output + $jsonHandler->addTraceToOutput(true); + } + + if (!empty($config['view_manager']['json_exceptions']['ajax_only'])) { + //Only return JSON response for AJAX requests + $jsonHandler->onlyForAjaxRequests(true); + } + + if (!empty($config['view_manager']['json_exceptions']['display'])) { + //Turn on JSON handler + $this->run->pushHandler($jsonHandler); + } + + //Attach the Whoops ExceptionStrategy + $exceptionStrategy = new ExceptionStrategy($this->run); + $exceptionStrategy->attach($events); + + //Attach the Whoops RouteNotFoundStrategy + $routeNotFoundStrategy = new RouteNotFoundStrategy($this->run); + $routeNotFoundStrategy->attach($events); + + //Detach default ExceptionStrategy + $services->get('Zend\Mvc\View\Http\ExceptionStrategy')->detach($events); + + //Detach default RouteNotFoundStrategy + $services->get('Zend\Mvc\View\Http\RouteNotFoundStrategy')->detach($events); + } + +} diff --git a/src/core/libs/Whoops/Provider/Zend/RouteNotFoundStrategy.php b/src/core/libs/Whoops/Provider/Zend/RouteNotFoundStrategy.php new file mode 100644 index 0000000..6c0b3de --- /dev/null +++ b/src/core/libs/Whoops/Provider/Zend/RouteNotFoundStrategy.php @@ -0,0 +1,64 @@ +<?php +/** + * ZF2 Integration for Whoops + * @author Balázs Németh <zsilbi@zsilbi.hu> + */ + +namespace Whoops\Provider\Zend; + +use Whoops\Run; + +use Zend\Mvc\View\Http\RouteNotFoundStrategy as BaseRouteNotFoundStrategy; +use Zend\Mvc\MvcEvent; +use Zend\Stdlib\ResponseInterface as Response; +use Zend\View\Model\ViewModel; + +class RouteNotFoundStrategy extends BaseRouteNotFoundStrategy { + + protected $run; + + public function __construct(Run $run) { + $this->run = $run; + } + + public function prepareNotFoundViewModel(MvcEvent $e) { + $vars = $e->getResult(); + if ($vars instanceof Response) { + // Already have a response as the result + return; + } + + $response = $e->getResponse(); + if ($response->getStatusCode() != 404) { + // Only handle 404 responses + return; + } + + if (!$vars instanceof ViewModel) { + $model = new ViewModel(); + if (is_string($vars)) { + $model->setVariable('message', $vars); + } else { + $model->setVariable('message', 'Page not found.'); + } + } else { + $model = $vars; + if ($model->getVariable('message') === null) { + $model->setVariable('message', 'Page not found.'); + } + } + // If displaying reasons, inject the reason + $this->injectNotFoundReason($model, $e); + + // If displaying exceptions, inject + $this->injectException($model, $e); + + // Inject controller if we're displaying either the reason or the exception + $this->injectController($model, $e); + + ob_clean(); + + throw new \Exception($model->getVariable('message') . ' ' . $model->getVariable('reason')); + } + +} diff --git a/src/core/libs/Whoops/Provider/Zend/module.config.example.php b/src/core/libs/Whoops/Provider/Zend/module.config.example.php new file mode 100644 index 0000000..13198a8 --- /dev/null +++ b/src/core/libs/Whoops/Provider/Zend/module.config.example.php @@ -0,0 +1,20 @@ +<?php +/** + * ZF2 Integration for Whoops + * @author Balázs Németh <zsilbi@zsilbi.hu> + * + * Example controller configuration + */ + +return array( + 'view_manager' => array( + 'editor' => 'sublime', + 'display_not_found_reason' => true, + 'display_exceptions' => true, + 'json_exceptions' => array( + 'display' => true, + 'ajax_only' => true, + 'show_trace' => true + ) + ), +); diff --git a/src/core/libs/Whoops/README.md b/src/core/libs/Whoops/README.md new file mode 100644 index 0000000..3ee890b --- /dev/null +++ b/src/core/libs/Whoops/README.md @@ -0,0 +1,248 @@ +# whoops +php errors for cool kids + +[![Build Status](https://travis-ci.org/filp/whoops.png?branch=master)](https://travis-ci.org/filp/whoops) [![Total Downloads](https://poser.pugx.org/filp/whoops/downloads.png)](https://packagist.org/packages/filp/whoops) [![Latest Stable Version](https://poser.pugx.org/filp/whoops/v/stable.png)](https://packagist.org/packages/filp/whoops) + + +----- + +![Whoops!](http://i.imgur.com/xiZ1tUU.png) + +**whoops** is an error handler base/framework for PHP. Out-of-the-box, it provides a pretty +error interface that helps you debug your web projects, but at heart it's a simple yet +powerful stacked error handling system. + +## (current) Features + +- Flexible, stack-based error handling +- Stand-alone library with (currently) no required dependencies +- Simple API for dealing with exceptions, trace frames & their data +- Includes a pretty rad error page for your webapp projects +- **NEW** Includes the ability to open referenced files directly in your editor and IDE +- Includes a Silex Service Provider for painless integration with [Silex](http://silex.sensiolabs.org/) +- Includes a Phalcon Service Provider for painless integration with [Phalcon](http://phalconphp.com/) +- Includes a Module for equally painless integration with [Zend Framework 2](http://framework.zend.com/) +- Easy to extend and integrate with existing libraries +- Clean, well-structured & tested code-base (well, except `pretty-template.php`, for now...) + +## Installing + +- Install [Composer](http://getcomposer.org) and place the executable somewhere in your `$PATH` (for the rest of this README, +I'll reference it as just `composer`) + +- Add `filp/whoops` to your project's `composer.json` file: + +```json +{ + "require": { + "filp/whoops": "1.*" + } +} +``` + +- Install/update your dependencies + +```bash +$ cd my_project +$ composer install +``` + +And you're good to go! Have a look at the **example files** in `examples/` to get a feel for how things work. +I promise it's really simple! + +## API Documentation + +Initial API documentation of the whoops library is available here: +https://github.com/filp/whoops/wiki/API-Documentation + +## Usage + +### Integrating with Silex + +**whoops** comes packaged with a Silex Service Provider: `Whoops\Provider\Silex\WhoopsServiceProvider`. Using it +in your existing Silex project is easy: + +```php + +require 'vendor/autoload.php'; + +use Silex\Application; + +// ... some awesome code here ... + +if($app['debug']) { + $app->register(new Whoops\Provider\Silex\WhoopsServiceProvider); +} + +// ... + +$app->run(); +``` + +And that's about it. By default, you'll get the pretty error pages if something goes awry in your development +environment, but you also have full access to the **whoops** library, obviously. For example, adding a new handler +into your app is as simple as extending `whoops`: + +```php +$app['whoops'] = $app->extend('whoops', function($whoops) { + $whoops->pushHandler(new DeleteWholeProjectHandler); + return $whoops; +}); +``` +### Integrating with Phalcon + +**whoops** comes packaged with a Phalcon Service Provider: `Whoops\Provider\Phalcon\WhoopsServiceProvider`. Using it +in your existing Phalcon project is easy. The provider uses the default Phalcon DI unless you pass a DI instance into the constructor. + +```php +new Whoops\Provider\Phalcon\WhoopsServiceProvider; + +// --- or --- + +$di = Phalcon\DI\FactoryDefault; +new Whoops\Provider\Phalcon\WhoopsServiceProvider($di); +``` + +### Integrating with Laravel 4/Illuminate + +If you're using Laravel 4, as of [this commit to laravel/framework](https://github.com/laravel/framework/commit/64f3a79aae254b71550a8097880f0b0e09062d24), you're already using Whoops! Yay! + +### Integrating with Laravel 3 + +User [@hugomrdias](https://github.com/hugomrdias) contributed a simple guide/example to help you integrate **whoops** with Laravel 3's IoC container, available at: + +https://gist.github.com/hugomrdias/5169713#file-start-php + +### Integrating with Zend Framework 2 + +User [@zsilbi](https://github.com/zsilbi) contributed a provider for ZF2 integration, +available in the following location: + +https://github.com/filp/whoops/tree/master/src/Whoops/Provider/Zend + +**Instructions:** + +- Add Whoops as a module to you app (/vendor/Whoops) +- Whoops must be the first module: + +```php +'modules' => array( + 'Whoops', + 'Application' + ) +``` + +- Move Module.php from /Whoops/Provider/Zend/Module.php to /Whoops/Module.php +- Use optional configurations in your controller config: + +```php +return array( + 'view_manager' => array( + 'display_not_found_reason' => true, + 'display_exceptions' => true, + 'json_exceptions' => array( + 'display' => true, + 'ajax_only' => true, + 'show_trace' => true + ) + ), +); +``` + +- NOTE: ob_clean(); is used to remove previous output, so you may use ob_start(); at the beginning of your app (index.php) + +### Opening referenced files with your favorite editor or IDE + +When using the pretty error page feature, whoops comes with the ability to +open referenced files directly in your IDE or editor. + +```php +<?php + +use Whoops\Handler\PrettyPageHandler; + +$handler = new PrettyPageHandler; +$handler->setEditor('sublime'); +``` + +The following editors are currently supported by default. + +- `sublime` - Sublime Text 2 +- `emacs` - Emacs +- `textmate` - Textmate +- `macvim` - MacVim +- `xdebug` - xdebug (uses [xdebug.file_link_format](http://xdebug.org/docs/all_settings#file_link_format)) + +Adding your own editor is simple: + +```php + +$handler->setEditor(function($file, $line) { + return "whatever://open?file=$file&line=$line"; +}); + +``` + +You can add PhpStorm support with [PhpStormOpener](https://github.com/pinepain/PhpStormOpener#phpstormopener) (Mac OS X only): +```php + +$handler->setEditor( + function ($file, $line) { + // if your development server is not local it's good to map remote files to local + $translations = array('^' . __DIR__ => '~/Development/PhpStormOpener'); // change to your path + + foreach ($translations as $from => $to) { + $file = preg_replace('#' . $from . '#', $to, $file, 1); + } + + return "pstorm://$file:$line"; + } +); + +``` + +### Available Handlers + +**whoops** currently ships with the following built-in handlers, available in the `Whoops\Handler` namespace: + +- [`PrettyPageHandler`](https://github.com/filp/whoops/blob/master/src/Whoops/Handler/PrettyPageHandler.php) - Shows a pretty error page when something goes pants-up +- [`CallbackHandler`](https://github.com/filp/whoops/blob/master/src/Whoops/Handler/CallbackHandler.php) - Wraps a closure or other callable as a handler. You do not need to use this handler explicitly, **whoops** will automatically wrap any closure or callable you pass to `Whoops\Run::pushHandler` +- [`JsonResponseHandler`](https://github.com/filp/whoops/blob/master/src/Whoops/Handler/JsonResponseHandler.php) - Captures exceptions and returns information on them as a JSON string. Can be used to, for example, play nice with AJAX requests. + +## Contributing + +If you want to give me some feedback or make a suggestion, send me a message through +twitter: [@imfilp](https://twitter.com/imfilp) + +If you want to get your hands dirty, great! Here's a couple of steps/guidelines: + +- Fork/clone this repo, and update dev dependencies using Composer + +```bash +$ git clone git@github.com:filp/whoops.git +$ cd whoops +$ composer install --dev +``` + +- Create a new branch for your feature or fix + +```bash +$ git checkout -b feature/flames-on-the-side +``` + +- Add your changes & tests for those changes (in `tests/`). +- Remember to stick to the existing code style as best as possible. When in doubt, follow `PSR-2`. +- Send me a pull request! + +If you don't want to go through all this, but still found something wrong or missing, please +let me know, and/or **open a new issue report** so that I or others may take care of it. + +## Authors + +This library was primarily developed by [Filipe Dobreira](https://github.com/filp). + +A lot of awesome fixes and enhancements were also sent in by contributors, which you can find **[in this page right here](https://github.com/filp/whoops/contributors)**. + + +[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/filp/whoops/trend.png)](https://bitdeli.com/free "Bitdeli Badge") + diff --git a/src/core/libs/Whoops/Resources/pretty-page.css b/src/core/libs/Whoops/Resources/pretty-page.css new file mode 100644 index 0000000..56a073d --- /dev/null +++ b/src/core/libs/Whoops/Resources/pretty-page.css @@ -0,0 +1,319 @@ +.cf:before, .cf:after {content: " ";display: table;} .cf:after {clear: both;} .cf {*zoom: 1;} +body { + font: 14px helvetica, arial, sans-serif; + color: #2B2B2B; + background-color: #D4D4D4; + padding:0; + margin: 0; + max-height: 100%; +} + a { + text-decoration: none; + } + +.container{ + height: 100%; + width: 100%; + position: fixed; + margin: 0; + padding: 0; + left: 0; + top: 0; +} + +.branding { + position: absolute; + top: 10px; + right: 20px; + color: #777777; + font-size: 10px; + z-index: 100; +} + .branding a { + color: #CD3F3F; + } + +header { + padding: 30px 20px; + color: white; + background: #272727; + box-sizing: border-box; + border-left: 5px solid #CD3F3F; +} + .exc-title { + margin: 0; + color: #616161; + text-shadow: 0 1px 2px rgba(0, 0, 0, .1); + } + .exc-title-primary { color: #CD3F3F; } + .exc-message { + font-size: 32px; + margin: 5px 0; + word-wrap: break-word; + } + +.stack-container { + height: 100%; + position: relative; +} + +.details-container { + height: 100%; + overflow: auto; + float: right; + width: 70%; + background: #DADADA; +} + .details { + padding: 10px; + padding-left: 5px; + border-left: 5px solid rgba(0, 0, 0, .1); + } + +.frames-container { + height: 100%; + overflow: auto; + float: left; + width: 30%; + background: #FFF; +} + .frame { + padding: 14px; + background: #F3F3F3; + border-right: 1px solid rgba(0, 0, 0, .2); + cursor: pointer; + } + .frame.active { + background-color: #4288CE; + color: #F3F3F3; + box-shadow: inset -2px 0 0 rgba(255, 255, 255, .1); + text-shadow: 0 1px 0 rgba(0, 0, 0, .2); + } + + .frame:not(.active):hover { + background: #BEE9EA; + } + + .frame-class, .frame-function, .frame-index { + font-weight: bold; + } + + .frame-index { + font-size: 11px; + color: #BDBDBD; + } + + .frame-class { + color: #4288CE; + } + .active .frame-class { + color: #BEE9EA; + } + + .frame-file { + font-family: consolas, monospace; + word-wrap:break-word; + } + + .frame-file .editor-link { + color: #272727; + } + + .frame-line { + font-weight: bold; + color: #4288CE; + } + + .active .frame-line { color: #BEE9EA; } + .frame-line:before { + content: ":"; + } + + .frame-code { + padding: 10px; + padding-left: 5px; + background: #BDBDBD; + display: none; + border-left: 5px solid #4288CE; + } + + .frame-code.active { + display: block; + } + + .frame-code .frame-file { + background: #C6C6C6; + color: #525252; + text-shadow: 0 1px 0 #E7E7E7; + padding: 10px 10px 5px 10px; + + border-top-right-radius: 6px; + border-top-left-radius: 6px; + + border: 1px solid rgba(0, 0, 0, .1); + border-bottom: none; + box-shadow: inset 0 1px 0 #DADADA; + } + + .code-block { + padding: 10px; + margin: 0; + box-shadow: inset 0 0 6px rgba(0, 0, 0, .3); + } + + .linenums { + margin: 0; + margin-left: 10px; + } + + .frame-comments { + box-shadow: inset 0 0 6px rgba(0, 0, 0, .3); + border: 1px solid rgba(0, 0, 0, .2); + border-top: none; + + border-bottom-right-radius: 6px; + border-bottom-left-radius: 6px; + + padding: 5px; + font-size: 12px; + background: #404040; + } + + .frame-comments.empty { + padding: 8px 15px; + } + + .frame-comments.empty:before { + content: "No comments for this stack frame."; + font-style: italic; + color: #828282; + } + + .frame-comment { + padding: 10px; + color: #D2D2D2; + } + .frame-comment a { + color: #BEE9EA; + font-weight: bold; + text-decoration: none; + } + .frame-comment a:hover { + color: #4bb1b1; + } + + .frame-comment:not(:last-child) { + border-bottom: 1px dotted rgba(0, 0, 0, .3); + } + + .frame-comment-context { + font-size: 10px; + font-weight: bold; + color: #86D2B6; + } + +.data-table-container label { + font-size: 16px; + font-weight: bold; + color: #4288CE; + margin: 10px 0; + padding: 10px 0; + + display: block; + margin-bottom: 5px; + padding-bottom: 5px; + border-bottom: 1px dotted rgba(0, 0, 0, .2); +} + .data-table { + width: 100%; + margin: 10px 0; + } + + .data-table tbody { + font: 13px consolas, monospace; + } + + .data-table thead { + display: none; + } + + .data-table tr { + padding: 5px 0; + } + + .data-table td:first-child { + width: 20%; + min-width: 130px; + overflow: hidden; + font-weight: bold; + color: #463C54; + padding-right: 5px; + + } + + .data-table td:last-child { + width: 80%; + -ms-word-break: break-all; + word-break: break-all; + word-break: break-word; + -webkit-hyphens: auto; + -moz-hyphens: auto; + hyphens: auto; + } + + .data-table .empty { + color: rgba(0, 0, 0, .3); + font-style: italic; + } + +.handler { + padding: 10px; + font: 14px monospace; +} + +.handler.active { + color: #BBBBBB; + background: #989898; + font-weight: bold; +} + +/* prettify code style +Uses the Doxy theme as a base */ +pre .str, code .str { color: #BCD42A; } /* string */ +pre .kwd, code .kwd { color: #4bb1b1; font-weight: bold; } /* keyword*/ +pre .com, code .com { color: #888; font-weight: bold; } /* comment */ +pre .typ, code .typ { color: #ef7c61; } /* type */ +pre .lit, code .lit { color: #BCD42A; } /* literal */ +pre .pun, code .pun { color: #fff; font-weight: bold; } /* punctuation */ +pre .pln, code .pln { color: #e9e4e5; } /* plaintext */ +pre .tag, code .tag { color: #4bb1b1; } /* html/xml tag */ +pre .htm, code .htm { color: #dda0dd; } /* html tag */ +pre .xsl, code .xsl { color: #d0a0d0; } /* xslt tag */ +pre .atn, code .atn { color: #ef7c61; font-weight: normal;} /* html/xml attribute name */ +pre .atv, code .atv { color: #bcd42a; } /* html/xml attribute value */ +pre .dec, code .dec { color: #606; } /* decimal */ +pre.prettyprint, code.prettyprint { + font-family: 'Source Code Pro', Monaco, Consolas, "Lucida Console", monospace;; + background: #333; + color: #e9e4e5; +} + pre.prettyprint { + white-space: pre-wrap; + } + + pre.prettyprint a, code.prettyprint a { + text-decoration:none; + } + + .linenums li { + color: #A5A5A5; + } + + .linenums li.current{ + background: rgba(255, 100, 100, .07); + padding-top: 4px; + padding-left: 1px; + } + .linenums li.current.active { + background: rgba(255, 100, 100, .17); + } diff --git a/src/core/libs/Whoops/Resources/pretty-template.php b/src/core/libs/Whoops/Resources/pretty-template.php new file mode 100644 index 0000000..e5ab982 --- /dev/null +++ b/src/core/libs/Whoops/Resources/pretty-template.php @@ -0,0 +1,216 @@ +<?php +/** +* Template file for Whoops's pretty error output. +* Check the $v global variable (stdClass) for what's available +* to work with. +* @var stdClass $v +* @var callable $e +* @var callable $slug +*/ +?> +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title><?php echo $e($v->title) ?></title> + + <style><?php echo $v->pageStyle ?></style> + </head> + <body> + <div class="container"> + + <div class="stack-container"> + + <div class="frames-container cf <?php echo (!$v->hasFrames ? 'empty' : '') ?>"> + + <?php /* List file names & line numbers for all stack frames; + clicking these links/buttons will display the code view + for that particular frame */ ?> + <?php foreach($v->frames as $i => $frame): ?> + <?php /** @var \Whoops\Exception\Frame $frame */ ?> + <div class="frame <?php echo ($i == 0 ? 'active' : '') ?>" id="frame-line-<?php echo $i ?>"> + <div class="frame-method-info"> + <span class="frame-index"><?php echo (count($v->frames) - $i - 1) ?>.</span> + <span class="frame-class"><?php echo $e($frame->getClass() ?: '') ?></span> + <span class="frame-function"><?php echo $e($frame->getFunction() ?: '') ?></span> + </div> + + <span class="frame-file"> + <?php echo ($frame->getFile(true) ?: '<#unknown>') ?><!-- + --><span class="frame-line"><?php echo (int) $frame->getLine() ?></span> + </span> + </div> + <?php endforeach ?> + + </div> + + <div class="details-container cf"> + + <header> + <div class="exception"> + <h3 class="exc-title"> + <?php foreach($v->name as $i => $nameSection): ?> + <?php if($i == count($v->name) - 1): ?> + <span class="exc-title-primary"><?php echo $e($nameSection) ?></span> + <?php else: ?> + <?php echo $e($nameSection) . ' \\' ?> + <?php endif ?> + <?php endforeach ?> + </h3> + <p class="exc-message"> + <?php echo $e($v->message) ?> + </p> + </div> + </header> + + <?php /* Display a code block for all frames in the stack. + * @todo: This should PROBABLY be done on-demand, lest + * we get 200 frames to process. */ ?> + <div class="frame-code-container <?php echo (!$v->hasFrames ? 'empty' : '') ?>"> + <?php foreach($v->frames as $i => $frame): ?> + <?php /** @var \Whoops\Exception\Frame $frame */ ?> + <?php $line = $frame->getLine(); ?> + <div class="frame-code <?php echo ($i == 0 ) ? 'active' : '' ?>" id="frame-code-<?php echo $i ?>"> + <div class="frame-file"> + <?php $filePath = $frame->getFile(); ?> + <?php if($filePath && $editorHref = $v->handler->getEditorHref($filePath, (int) $line)): ?> + Open: + <a href="<?php echo $editorHref ?>" class="editor-link"> + <strong><?php echo $e($filePath ?: '<#unknown>') ?></strong> + </a> + <?php else: ?> + <strong><?php echo $e($filePath ?: '<#unknown>') ?></strong> + <?php endif ?> + </div> + <?php + // Do nothing if there's no line to work off + if($line !== null): + + // the $line is 1-indexed, we nab -1 where needed to account for this + $range = $frame->getFileLines($line - 8, 10); + $range = array_map(function($line){ return empty($line) ? ' ' : $line;}, $range); + $start = key($range) + 1; + $code = join("\n", $range); + ?> + <pre class="code-block prettyprint linenums:<?php echo $start ?>"><?php echo $e($code) ?></pre> + <?php endif ?> + + <?php + // Append comments for this frame */ + $comments = $frame->getComments(); + ?> + <div class="frame-comments <?php echo empty($comments) ? 'empty' : '' ?>"> + <?php foreach($comments as $commentNo => $comment): ?> + <?php + extract($comment) + + /** + * @var string $context + * @var string $comment + */ + ?> + <div class="frame-comment" id="comment-<?php echo $i . '-' . $commentNo ?>"> + <span class="frame-comment-context"><?php echo $e($context) ?></span> + <?php echo $e($comment, true) ?> + </div> + <?php endforeach ?> + </div> + + </div> + <?php endforeach ?> + </div> + + <?php /* List data-table values, i.e: $_SERVER, $_GET, .... */ ?> + <div class="details"> + <div class="data-table-container" id="data-tables"> + <?php foreach($v->tables as $label => $data): ?> + <div class="data-table" id="sg-<?php echo $e($slug($label)) ?>"> + <label><?php echo $e($label) ?></label> + <?php if(!empty($data)): ?> + <table class="data-table"> + <thead> + <tr> + <td class="data-table-k">Key</td> + <td class="data-table-v">Value</td> + </tr> + </thead> + <?php foreach($data as $k => $value): ?> + <tr> + <td><?php echo $e($k) ?></td> + <td><?php echo $e(print_r($value, true)) ?></td> + </tr> + <?php endforeach ?> + </table> + <?php else: ?> + <span class="empty">empty</span> + <?php endif ?> + </div> + <?php endforeach ?> + </div> + + <?php /* List registered handlers, in order of first to last registered */ ?> + <div class="data-table-container" id="handlers"> + <label>Registered Handlers</label> + <?php foreach($v->handlers as $i => $handler): ?> + <div class="handler <?php echo ($handler === $v->handler) ? 'active' : ''?>"> + <?php echo $i ?>. <?php echo $e(get_class($handler)) ?> + </div> + <?php endforeach ?> + </div> + + </div> <!-- .details --> + </div> + + </div> + </div> + + <script src="//cdnjs.cloudflare.com/ajax/libs/prettify/r224/prettify.js"></script> + <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> + <script> + $(function() { + prettyPrint(); + + var $frameLines = $('[id^="frame-line-"]'); + var $activeLine = $('.frames-container .active'); + var $activeFrame = $('.active[id^="frame-code-"]').show(); + var $container = $('.details-container'); + var headerHeight = $('header').css('height'); + + var highlightCurrentLine = function() { + // Highlight the active and neighboring lines for this frame: + var activeLineNumber = +($activeLine.find('.frame-line').text()); + var $lines = $activeFrame.find('.linenums li'); + var firstLine = +($lines.first().val()); + + $($lines[activeLineNumber - firstLine - 1]).addClass('current'); + $($lines[activeLineNumber - firstLine]).addClass('current active'); + $($lines[activeLineNumber - firstLine + 1]).addClass('current'); + }; + + // Highlight the active for the first frame: + highlightCurrentLine(); + + $frameLines.click(function() { + var $this = $(this); + var id = /frame\-line\-([\d]*)/.exec($this.attr('id'))[1]; + var $codeFrame = $('#frame-code-' + id); + + if($codeFrame) { + $activeLine.removeClass('active'); + $activeFrame.removeClass('active'); + + $this.addClass('active'); + $codeFrame.addClass('active'); + + $activeLine = $this; + $activeFrame = $codeFrame; + + highlightCurrentLine(); + + $container.animate({ scrollTop: headerHeight }, "fast"); + } + }); + }); + </script> + </body> +</html> diff --git a/src/core/libs/Whoops/Run.php b/src/core/libs/Whoops/Run.php new file mode 100644 index 0000000..dacbf30 --- /dev/null +++ b/src/core/libs/Whoops/Run.php @@ -0,0 +1,382 @@ +<?php +/** + * Whoops - php errors for cool kids + * @author Filipe Dobreira <http://github.com/filp> + */ + +namespace Whoops; +use Whoops\Handler\HandlerInterface; +use Whoops\Handler\Handler; +use Whoops\Handler\CallbackHandler; +use Whoops\Exception\Inspector; +use Whoops\Exception\ErrorException; +use InvalidArgumentException; +use Exception; + +class Run +{ + const EXCEPTION_HANDLER = "handleException"; + const ERROR_HANDLER = "handleError"; + const SHUTDOWN_HANDLER = "handleShutdown"; + + protected $isRegistered; + protected $allowQuit = true; + protected $sendOutput = true; + protected $sendHttpCode = 500; + + /** + * @var HandlerInterface[] + */ + protected $handlerStack = array(); + + protected $silencedPatterns = array(); + + /** + * Pushes a handler to the end of the stack + * + * @throws InvalidArgumentException If argument is not callable or instance of HandlerInterface + * @param Callable|HandlerInterface $handler + * @return Run + */ + public function pushHandler($handler) + { + if(is_callable($handler)) { + $handler = new CallbackHandler($handler); + } + + if(!$handler instanceof HandlerInterface) { + throw new InvalidArgumentException( + "Argument to " . __METHOD__ . " must be a callable, or instance of" + . "Whoops\\Handler\\HandlerInterface" + ); + } + + $this->handlerStack[] = $handler; + return $this; + } + + /** + * Removes the last handler in the stack and returns it. + * Returns null if there"s nothing else to pop. + * @return null|HandlerInterface + */ + public function popHandler() + { + return array_pop($this->handlerStack); + } + + /** + * Returns an array with all handlers, in the + * order they were added to the stack. + * @return array + */ + public function getHandlers() + { + return $this->handlerStack; + } + + /** + * Clears all handlers in the handlerStack, including + * the default PrettyPage handler. + * @return Run + */ + public function clearHandlers() + { + $this->handlerStack = array(); + return $this; + } + + /** + * @param Exception $exception + * @return Inspector + */ + protected function getInspector(Exception $exception) + { + return new Inspector($exception); + } + + /** + * Registers this instance as an error handler. + * @return Run + */ + public function register() + { + if(!$this->isRegistered) { + // Workaround PHP bug 42098 + // https://bugs.php.net/bug.php?id=42098 + class_exists("\\Whoops\\Exception\\ErrorException"); + class_exists("\\Whoops\\Exception\\FrameCollection"); + class_exists("\\Whoops\\Exception\\Frame"); + class_exists("\\Whoops\\Exception\\Inspector"); + + set_error_handler(array($this, self::ERROR_HANDLER)); + set_exception_handler(array($this, self::EXCEPTION_HANDLER)); + register_shutdown_function(array($this, self::SHUTDOWN_HANDLER)); + + $this->isRegistered = true; + } + + return $this; + } + + /** + * Unregisters all handlers registered by this Whoops\Run instance + * @return Run + */ + public function unregister() + { + if($this->isRegistered) { + restore_exception_handler(); + restore_error_handler(); + + $this->isRegistered = false; + } + + return $this; + } + + /** + * Should Whoops allow Handlers to force the script to quit? + * @param bool|int $exit + * @return bool + */ + public function allowQuit($exit = null) + { + if(func_num_args() == 0) { + return $this->allowQuit; + } + + return $this->allowQuit = (bool) $exit; + } + + /** + * Silence particular errors in particular files + * @param array|string $patterns List or a single regex pattern to match + * @param integer $levels Defaults to E_STRICT | E_DEPRECATED + * @return \Whoops\Run + */ + public function silenceErrorsInPaths($patterns, $levels = 10240) + { + $this->silencedPatterns = array_merge( + $this->silencedPatterns, + array_map( + function ($pattern) use ($levels) { + return array( + "pattern" => $pattern, + "levels" => $levels, + ); + }, + (array) $patterns + ) + ); + return $this; + } + + /* + * Should Whoops send HTTP error code to the browser if possible? + * Whoops will by default send HTTP code 500, but you may wish to + * use 502, 503, or another 5xx family code. + * + * @param bool|int $code + * @return bool + */ + public function sendHttpCode($code = null) + { + if(func_num_args() == 0) { + return $this->sendHttpCode; + } + + if(!$code) { + return $this->sendHttpCode = false; + } + + if($code === true) { + $code = 500; + } + + if ($code < 400 || 600 <= $code) { + throw new InvalidArgumentException( + "Invalid status code '$code', must be 4xx or 5xx" + ); + } + + return $this->sendHttpCode = $code; + } + + /** + * Should Whoops push output directly to the client? + * If this is false, output will be returned by handleException + * @param bool|int $send + * @return bool + */ + public function writeToOutput($send = null) + { + if(func_num_args() == 0) { + return $this->sendOutput; + } + + return $this->sendOutput = (bool) $send; + } + + /** + * Handles an exception, ultimately generating a Whoops error + * page. + * + * @param Exception $exception + * @return string Output generated by handlers + */ + public function handleException(Exception $exception) + { + // Walk the registered handlers in the reverse order + // they were registered, and pass off the exception + $inspector = $this->getInspector($exception); + + // Capture output produced while handling the exception, + // we might want to send it straight away to the client, + // or return it silently. + ob_start(); + + // Just in case there are no handlers: + $handlerResponse = null; + + for($i = count($this->handlerStack) - 1; $i >= 0; $i--) { + $handler = $this->handlerStack[$i]; + + $handler->setRun($this); + $handler->setInspector($inspector); + $handler->setException($exception); + + $handlerResponse = $handler->handle($exception); + + if(in_array($handlerResponse, array(Handler::LAST_HANDLER, Handler::QUIT))) { + // The Handler has handled the exception in some way, and + // wishes to quit execution (Handler::QUIT), or skip any + // other handlers (Handler::LAST_HANDLER). If $this->allowQuit + // is false, Handler::QUIT behaves like Handler::LAST_HANDLER + break; + } + } + + $output = ob_get_clean(); + + // If we're allowed to, send output generated by handlers directly + // to the output, otherwise, and if the script doesn't quit, return + // it so that it may be used by the caller + if($this->writeToOutput()) { + // @todo Might be able to clean this up a bit better + // If we're going to quit execution, cleanup all other output + // buffers before sending our own output: + if($handlerResponse == Handler::QUIT && $this->allowQuit()) { + while (ob_get_level() > 0) ob_end_clean(); + } + + if($this->sendHttpCode() && isset($_SERVER["REQUEST_URI"]) && !headers_sent()) { + $httpCode = $this->sendHttpCode(); + + if (function_exists('http_response_code')) { + http_response_code($httpCode); + } else { + // http_response_code is added in 5.4. + // For compatibility with 5.3 we use the third argument in header call + // First argument must be a real header. + // If it is empty, PHP will ignore the third argument. + // If it is invalid, such as a single space, Apache will handle it well, + // but the PHP development server will hang. + // Setting a full status line would require us to hardcode + // string values for all different status code, and detect the protocol. + // which is an extra error-prone complexity. + header('X-Ignore-This: 1', true, $httpCode); + } + } + + echo $output; + } + + // Handlers are done! Check if we got here because of Handler::QUIT + // ($handlerResponse will be the response from the last queried handler) + // and if so, try to quit execution. + if($handlerResponse == Handler::QUIT && $this->allowQuit()) { + exit; + } + + return $output; + } + + /** + * Converts generic PHP errors to \ErrorException + * instances, before passing them off to be handled. + * + * This method MUST be compatible with set_error_handler. + * + * @param int $level + * @param string $message + * @param string $file + * @param int $line + * + * @return bool + */ + public function handleError($level, $message, $file = null, $line = null) + { + if ($level & error_reporting()) { + foreach ($this->silencedPatterns as $entry) { + $pathMatches = (bool) preg_match($entry["pattern"], $file); + $levelMatches = $level & $entry["levels"]; + if ($pathMatches && $levelMatches) { + // Ignore the error, abort handling + return true; + } + } + + $exception = new ErrorException($message, $level, 0, $file, $line); + if ($this->canThrowExceptions) { + throw $exception; + } else { + $this->handleException($exception); + } + } + } + + /** + * Special case to deal with Fatal errors and the like. + */ + public function handleShutdown() + { + // If we reached this step, we are in shutdown handler. + // An exception thrown in a shutdown handler will not be propagated + // to the exception handler. Pass that information along. + $this->canThrowExceptions = false; + + $error = error_get_last(); + if ($error && $this->isLevelFatal($error['type'])) { + // If there was a fatal error, + // it was not handled in handleError yet. + $this->handleError( + $error['type'], + $error['message'], + $error['file'], + $error['line'] + ); + } + } + + /** + * In certain scenarios, like in shutdown handler, we can not throw exceptions + * @var boolean + */ + private $canThrowExceptions = true; + + private static function isLevelFatal($level) + { + return in_array( + $level, + array( + E_ERROR, + E_PARSE, + E_CORE_ERROR, + E_CORE_WARNING, + E_COMPILE_ERROR, + E_COMPILE_WARNING + ) + ); + } +} diff --git a/src/core/libs/jsmin/jsmin.php b/src/core/libs/jsmin/jsmin.php new file mode 100755 index 0000000..75609ae --- /dev/null +++ b/src/core/libs/jsmin/jsmin.php @@ -0,0 +1,291 @@ +<?php +/** + * jsmin.php - PHP implementation of Douglas Crockford's JSMin. + * + * This is pretty much a direct port of jsmin.c to PHP with just a few + * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and + * outputs to stdout, this library accepts a string as input and returns another + * string as output. + * + * PHP 5 or higher is required. + * + * Permission is hereby granted to use this version of the library under the + * same terms as jsmin.c, which has the following license: + * + * -- + * Copyright (c) 2002 Douglas Crockford (www.crockford.com) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * The Software shall be used for Good, not Evil. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * -- + * + * @package JSMin + * @author Ryan Grove <ryan@wonko.com> + * @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c) + * @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port) + * @license http://opensource.org/licenses/mit-license.php MIT License + * @version 1.1.1 (2008-03-02) + * @link http://code.google.com/p/jsmin-php/ + */ + +class JSMin { + const ORD_LF = 10; + const ORD_SPACE = 32; + + protected $a = ''; + protected $b = ''; + protected $input = ''; + protected $inputIndex = 0; + protected $inputLength = 0; + protected $lookAhead = null; + protected $output = ''; + + // -- Public Static Methods -------------------------------------------------- + + public static function minify($js) { + $jsmin = new JSMin($js); + return $jsmin->min(); + } + + // -- Public Instance Methods ------------------------------------------------ + + public function __construct($input) { + $this->input = str_replace("\r\n", "\n", $input); + $this->inputLength = strlen($this->input); + } + + // -- Protected Instance Methods --------------------------------------------- + + protected function action($d) { + switch($d) { + case 1: + $this->output .= $this->a; + + case 2: + $this->a = $this->b; + + if ($this->a === "'" || $this->a === '"') { + for (;;) { + $this->output .= $this->a; + $this->a = $this->get(); + + if ($this->a === $this->b) { + break; + } + + if (ord($this->a) <= self::ORD_LF) { + throw new JSMinException('Unterminated string literal.'); + } + + if ($this->a === '\\') { + $this->output .= $this->a; + $this->a = $this->get(); + } + } + } + + case 3: + $this->b = $this->next(); + + if ($this->b === '/' && ( + $this->a === '(' || $this->a === ',' || $this->a === '=' || + $this->a === ':' || $this->a === '[' || $this->a === '!' || + $this->a === '&' || $this->a === '|' || $this->a === '?')) { + + $this->output .= $this->a . $this->b; + + for (;;) { + $this->a = $this->get(); + + if ($this->a === '/') { + break; + } elseif ($this->a === '\\') { + $this->output .= $this->a; + $this->a = $this->get(); + } elseif (ord($this->a) <= self::ORD_LF) { + throw new JSMinException('Unterminated regular expression '. + 'literal.'); + } + + $this->output .= $this->a; + } + + $this->b = $this->next(); + } + } + } + + protected function get() { + $c = $this->lookAhead; + $this->lookAhead = null; + + if ($c === null) { + if ($this->inputIndex < $this->inputLength) { + $c = substr($this->input, $this->inputIndex, 1); + $this->inputIndex += 1; + } else { + $c = null; + } + } + + if ($c === "\r") { + return "\n"; + } + + if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) { + return $c; + } + + return ' '; + } + + protected function isAlphaNum($c) { + return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1; + } + + protected function min() { + $this->a = "\n"; + $this->action(3); + + while ($this->a !== null) { + switch ($this->a) { + case ' ': + if ($this->isAlphaNum($this->b)) { + $this->action(1); + } else { + $this->action(2); + } + break; + + case "\n": + switch ($this->b) { + case '{': + case '[': + case '(': + case '+': + case '-': + $this->action(1); + break; + + case ' ': + $this->action(3); + break; + + default: + if ($this->isAlphaNum($this->b)) { + $this->action(1); + } + else { + $this->action(2); + } + } + break; + + default: + switch ($this->b) { + case ' ': + if ($this->isAlphaNum($this->a)) { + $this->action(1); + break; + } + + $this->action(3); + break; + + case "\n": + switch ($this->a) { + case '}': + case ']': + case ')': + case '+': + case '-': + case '"': + case "'": + $this->action(1); + break; + + default: + if ($this->isAlphaNum($this->a)) { + $this->action(1); + } + else { + $this->action(3); + } + } + break; + + default: + $this->action(1); + break; + } + } + } + + return $this->output; + } + + protected function next() { + $c = $this->get(); + + if ($c === '/') { + switch($this->peek()) { + case '/': + for (;;) { + $c = $this->get(); + + if (ord($c) <= self::ORD_LF) { + return $c; + } + } + + case '*': + $this->get(); + + for (;;) { + switch($this->get()) { + case '*': + if ($this->peek() === '/') { + $this->get(); + return ' '; + } + break; + + case null: + throw new JSMinException('Unterminated comment.'); + } + } + + default: + return $c; + } + } + + return $c; + } + + protected function peek() { + $this->lookAhead = $this->get(); + return $this->lookAhead; + } +} + +// -- Exceptions --------------------------------------------------------------- +class JSMinException extends Exception {} +?> \ No newline at end of file diff --git a/src/core/libs/lessphp/LICENSE b/src/core/libs/lessphp/LICENSE new file mode 100755 index 0000000..49c9ea4 --- /dev/null +++ b/src/core/libs/lessphp/LICENSE @@ -0,0 +1,660 @@ +For ease of distribution, lessphp 0.4.0 is under a dual license. +You are free to pick which one suits your needs. + + + + +MIT LICENSE + + + + +Copyright (c) 2013 Leaf Corcoran, http://leafo.net/lessphp + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + + +GPL VERSION 3 + + + + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + diff --git a/src/core/libs/lessphp/README.md b/src/core/libs/lessphp/README.md new file mode 100755 index 0000000..d39c3f8 --- /dev/null +++ b/src/core/libs/lessphp/README.md @@ -0,0 +1,96 @@ +# lessphp v0.4.0 +### <http://leafo.net/lessphp> + +[![Build Status](https://secure.travis-ci.org/leafo/lessphp.png)](http://travis-ci.org/leafo/lessphp) + +`lessphp` is a compiler for LESS written in PHP. The documentation is great, +so check it out: <http://leafo.net/lessphp/docs/>. + +Here's a quick tutorial: + +### How to use in your PHP project + +The only file required is `lessc.inc.php`, so copy that to your include directory. + +The typical flow of **lessphp** is to create a new instance of `lessc`, +configure it how you like, then tell it to compile something using one built in +compile methods. + +The `compile` method compiles a string of LESS code to CSS. + +```php +<?php +require "lessc.inc.php"; + +$less = new lessc; +echo $less->compile(".block { padding: 3 + 4px }"); +``` + +The `compileFile` method reads and compiles a file. It will either return the +result or write it to the path specified by an optional second argument. + +```php +<?php +echo $less->compileFile("input.less"); +``` + +The `compileChecked` method is like `compileFile`, but it only compiles if the output +file doesn't exist or it's older than the input file: + +```php +<?php +$less->checkedCompile("input.less", "output.css"); +``` + +If there any problem compiling your code, an exception is thrown with a helpful message: + +```php +<?php +try { + $less->compile("invalid LESS } {"); +} catch (exception $e) { + echo "fatal error: " . $e->getMessage(); +} +``` + +The `lessc` object can be configured through an assortment of instance methods. +Some possible configuration options include [changing the output format][1], +[setting variables from PHP][2], and [controlling the preservation of +comments][3], writing [custom functions][4] and much more. It's all described +in [the documentation][0]. + + + [0]: http://leafo.net/lessphp/docs/ + [1]: http://leafo.net/lessphp/docs/#output_formatting + [2]: http://leafo.net/lessphp/docs/#setting_variables_from_php + [3]: http://leafo.net/lessphp/docs/#preserving_comments + [4]: http://leafo.net/lessphp/docs/#custom_functions + + +### How to use from the command line + +An additional script has been included to use the compiler from the command +line. In the simplest invocation, you specify an input file and the compiled +css is written to standard out: + + $ plessc input.less > output.css + +Using the -r flag, you can specify LESS code directly as an argument or, if +the argument is left off, from standard in: + + $ plessc -r "my less code here" + +Finally, by using the -w flag you can watch a specified input file and have it +compile as needed to the output file: + + $ plessc -w input-file output-file + +Errors from watch mode are written to standard out. + +The -f flag sets the [output formatter][1]. For example, to compress the +output run this: + + $ plessc -f=compressed myfile.less + +For more help, run `plessc --help` + diff --git a/src/core/libs/lessphp/composer.json b/src/core/libs/lessphp/composer.json new file mode 100755 index 0000000..0f06ba0 --- /dev/null +++ b/src/core/libs/lessphp/composer.json @@ -0,0 +1,25 @@ +{ + "name": "leafo/lessphp", + "type": "library", + "description": "lessphp is a compiler for LESS written in PHP.", + "homepage": "http://leafo.net/lessphp/", + "license": [ + "MIT", + "GPL-3.0" + ], + "authors": [ + { + "name": "Leaf Corcoran", + "email": "leafot@gmail.com", + "homepage": "http://leafo.net" + } + ], + "autoload": { + "classmap": ["lessc.inc.php"] + }, + "extra": { + "branch-alias": { + "dev-master": "0.4.x-dev" + } + } +} diff --git a/src/core/libs/lessphp/lessc.inc.php b/src/core/libs/lessphp/lessc.inc.php new file mode 100755 index 0000000..6ad6c64 --- /dev/null +++ b/src/core/libs/lessphp/lessc.inc.php @@ -0,0 +1,3734 @@ +<?php + +/** + * lessphp v0.4.0 + * http://leafo.net/lessphp + * + * LESS CSS compiler, adapted from http://lesscss.org + * + * Copyright 2013, Leaf Corcoran <leafot@gmail.com> + * Licensed under MIT or GPLv3, see LICENSE + */ + + +/** + * The LESS compiler and parser. + * + * Converting LESS to CSS is a three stage process. The incoming file is parsed + * by `lessc_parser` into a syntax tree, then it is compiled into another tree + * representing the CSS structure by `lessc`. The CSS tree is fed into a + * formatter, like `lessc_formatter` which then outputs CSS as a string. + * + * During the first compile, all values are *reduced*, which means that their + * types are brought to the lowest form before being dump as strings. This + * handles math equations, variable dereferences, and the like. + * + * The `parse` function of `lessc` is the entry point. + * + * In summary: + * + * The `lessc` class creates an instance of the parser, feeds it LESS code, + * then transforms the resulting tree to a CSS tree. This class also holds the + * evaluation context, such as all available mixins and variables at any given + * time. + * + * The `lessc_parser` class is only concerned with parsing its input. + * + * The `lessc_formatter` takes a CSS tree, and dumps it to a formatted string, + * handling things like indentation. + */ +class lessc { + static public $VERSION = "v0.4.0"; + + static public $TRUE = array("keyword", "true"); + static public $FALSE = array("keyword", "false"); + + protected $libFunctions = array(); + protected $registeredVars = array(); + protected $preserveComments = false; + + public $vPrefix = '@'; // prefix of abstract properties + public $mPrefix = '$'; // prefix of abstract blocks + public $parentSelector = '&'; + + public $importDisabled = false; + public $importDir = ''; + + protected $numberPrecision = null; + + protected $allParsedFiles = array(); + + // set to the parser that generated the current line when compiling + // so we know how to create error messages + protected $sourceParser = null; + protected $sourceLoc = null; + + static protected $nextImportId = 0; // uniquely identify imports + + // attempts to find the path of an import url, returns null for css files + protected function findImport($url) { + foreach ((array)$this->importDir as $dir) { + $full = $dir.(substr($dir, -1) != '/' ? '/' : '').$url; + if ($this->fileExists($file = $full.'.less') || $this->fileExists($file = $full)) { + return $file; + } + } + + return null; + } + + protected function fileExists($name) { + return is_file($name); + } + + static public function compressList($items, $delim) { + if (!isset($items[1]) && isset($items[0])) return $items[0]; + else return array('list', $delim, $items); + } + + static public function preg_quote($what) { + return preg_quote($what, '/'); + } + + protected function tryImport($importPath, $parentBlock, $out) { + if ($importPath[0] == "function" && $importPath[1] == "url") { + $importPath = $this->flattenList($importPath[2]); + } + + $str = $this->coerceString($importPath); + if ($str === null) return false; + + $url = $this->compileValue($this->lib_e($str)); + + // don't import if it ends in css + if (substr_compare($url, '.css', -4, 4) === 0) return false; + + $realPath = $this->findImport($url); + + if ($realPath === null) return false; + + if ($this->importDisabled) { + return array(false, "/* import disabled */"); + } + + if (isset($this->allParsedFiles[realpath($realPath)])) { + return array(false, null); + } + + $this->addParsedFile($realPath); + $parser = $this->makeParser($realPath); + $root = $parser->parse(file_get_contents($realPath)); + + // set the parents of all the block props + foreach ($root->props as $prop) { + if ($prop[0] == "block") { + $prop[1]->parent = $parentBlock; + } + } + + // copy mixins into scope, set their parents + // bring blocks from import into current block + // TODO: need to mark the source parser these came from this file + foreach ($root->children as $childName => $child) { + if (isset($parentBlock->children[$childName])) { + $parentBlock->children[$childName] = array_merge( + $parentBlock->children[$childName], + $child); + } else { + $parentBlock->children[$childName] = $child; + } + } + + $pi = pathinfo($realPath); + $dir = $pi["dirname"]; + + list($top, $bottom) = $this->sortProps($root->props, true); + $this->compileImportedProps($top, $parentBlock, $out, $parser, $dir); + + return array(true, $bottom, $parser, $dir); + } + + protected function compileImportedProps($props, $block, $out, $sourceParser, $importDir) { + $oldSourceParser = $this->sourceParser; + + $oldImport = $this->importDir; + + // TODO: this is because the importDir api is stupid + $this->importDir = (array)$this->importDir; + array_unshift($this->importDir, $importDir); + + foreach ($props as $prop) { + $this->compileProp($prop, $block, $out); + } + + $this->importDir = $oldImport; + $this->sourceParser = $oldSourceParser; + } + + /** + * Recursively compiles a block. + * + * A block is analogous to a CSS block in most cases. A single LESS document + * is encapsulated in a block when parsed, but it does not have parent tags + * so all of it's children appear on the root level when compiled. + * + * Blocks are made up of props and children. + * + * Props are property instructions, array tuples which describe an action + * to be taken, eg. write a property, set a variable, mixin a block. + * + * The children of a block are just all the blocks that are defined within. + * This is used to look up mixins when performing a mixin. + * + * Compiling the block involves pushing a fresh environment on the stack, + * and iterating through the props, compiling each one. + * + * See lessc::compileProp() + * + */ + protected function compileBlock($block) { + switch ($block->type) { + case "root": + $this->compileRoot($block); + break; + case null: + $this->compileCSSBlock($block); + break; + case "media": + $this->compileMedia($block); + break; + case "directive": + $name = "@" . $block->name; + if (!empty($block->value)) { + $name .= " " . $this->compileValue($this->reduce($block->value)); + } + + $this->compileNestedBlock($block, array($name)); + break; + default: + $this->throwError("unknown block type: $block->type\n"); + } + } + + protected function compileCSSBlock($block) { + $env = $this->pushEnv(); + + $selectors = $this->compileSelectors($block->tags); + $env->selectors = $this->multiplySelectors($selectors); + $out = $this->makeOutputBlock(null, $env->selectors); + + $this->scope->children[] = $out; + $this->compileProps($block, $out); + + $block->scope = $env; // mixins carry scope with them! + $this->popEnv(); + } + + protected function compileMedia($media) { + $env = $this->pushEnv($media); + $parentScope = $this->mediaParent($this->scope); + + $query = $this->compileMediaQuery($this->multiplyMedia($env)); + + $this->scope = $this->makeOutputBlock($media->type, array($query)); + $parentScope->children[] = $this->scope; + + $this->compileProps($media, $this->scope); + + if (count($this->scope->lines) > 0) { + $orphanSelelectors = $this->findClosestSelectors(); + if (!is_null($orphanSelelectors)) { + $orphan = $this->makeOutputBlock(null, $orphanSelelectors); + $orphan->lines = $this->scope->lines; + array_unshift($this->scope->children, $orphan); + $this->scope->lines = array(); + } + } + + $this->scope = $this->scope->parent; + $this->popEnv(); + } + + protected function mediaParent($scope) { + while (!empty($scope->parent)) { + if (!empty($scope->type) && $scope->type != "media") { + break; + } + $scope = $scope->parent; + } + + return $scope; + } + + protected function compileNestedBlock($block, $selectors) { + $this->pushEnv($block); + $this->scope = $this->makeOutputBlock($block->type, $selectors); + $this->scope->parent->children[] = $this->scope; + + $this->compileProps($block, $this->scope); + + $this->scope = $this->scope->parent; + $this->popEnv(); + } + + protected function compileRoot($root) { + $this->pushEnv(); + $this->scope = $this->makeOutputBlock($root->type); + $this->compileProps($root, $this->scope); + $this->popEnv(); + } + + protected function compileProps($block, $out) { + foreach ($this->sortProps($block->props) as $prop) { + $this->compileProp($prop, $block, $out); + } + $out->lines = $this->deduplicate($out->lines); + } + + /** + * Deduplicate lines in a block. Comments are not deduplicated. If a + * duplicate rule is detected, the comments immediately preceding each + * occurence are consolidated. + */ + protected function deduplicate($lines) { + $unique = array(); + $comments = array(); + + foreach($lines as $line) { + if (strpos($line, '/*') === 0) { + $comments[] = $line; + continue; + } + if (!in_array($line, $unique)) { + $unique[] = $line; + } + array_splice($unique, array_search($line, $unique), 0, $comments); + $comments = array(); + } + return array_merge($unique, $comments); + } + + protected function sortProps($props, $split = false) { + $vars = array(); + $imports = array(); + $other = array(); + $stack = array(); + + foreach ($props as $prop) { + switch ($prop[0]) { + case "comment": + $stack[] = $prop; + break; + case "assign": + $stack[] = $prop; + if (isset($prop[1][0]) && $prop[1][0] == $this->vPrefix) { + $vars = array_merge($vars, $stack); + } else { + $other = array_merge($other, $stack); + } + $stack = array(); + break; + case "import": + $id = self::$nextImportId++; + $prop[] = $id; + $stack[] = $prop; + $imports = array_merge($imports, $stack); + $other[] = array("import_mixin", $id); + $stack = array(); + break; + default: + $stack[] = $prop; + $other = array_merge($other, $stack); + $stack = array(); + break; + } + } + $other = array_merge($other, $stack); + + if ($split) { + return array(array_merge($vars, $imports), $other); + } else { + return array_merge($vars, $imports, $other); + } + } + + protected function compileMediaQuery($queries) { + $compiledQueries = array(); + foreach ($queries as $query) { + $parts = array(); + foreach ($query as $q) { + switch ($q[0]) { + case "mediaType": + $parts[] = implode(" ", array_slice($q, 1)); + break; + case "mediaExp": + if (isset($q[2])) { + $parts[] = "($q[1]: " . + $this->compileValue($this->reduce($q[2])) . ")"; + } else { + $parts[] = "($q[1])"; + } + break; + case "variable": + $parts[] = $this->compileValue($this->reduce($q)); + break; + } + } + + if (count($parts) > 0) { + $compiledQueries[] = implode(" and ", $parts); + } + } + + $out = "@media"; + if (!empty($parts)) { + $out .= " " . + implode($this->formatter->selectorSeparator, $compiledQueries); + } + return $out; + } + + protected function multiplyMedia($env, $childQueries = null) { + if (is_null($env) || + !empty($env->block->type) && $env->block->type != "media") + { + return $childQueries; + } + + // plain old block, skip + if (empty($env->block->type)) { + return $this->multiplyMedia($env->parent, $childQueries); + } + + $out = array(); + $queries = $env->block->queries; + if (is_null($childQueries)) { + $out = $queries; + } else { + foreach ($queries as $parent) { + foreach ($childQueries as $child) { + $out[] = array_merge($parent, $child); + } + } + } + + return $this->multiplyMedia($env->parent, $out); + } + + protected function expandParentSelectors(&$tag, $replace) { + $parts = explode("$&$", $tag); + $count = 0; + foreach ($parts as &$part) { + $part = str_replace($this->parentSelector, $replace, $part, $c); + $count += $c; + } + $tag = implode($this->parentSelector, $parts); + return $count; + } + + protected function findClosestSelectors() { + $env = $this->env; + $selectors = null; + while ($env !== null) { + if (isset($env->selectors)) { + $selectors = $env->selectors; + break; + } + $env = $env->parent; + } + + return $selectors; + } + + + // multiply $selectors against the nearest selectors in env + protected function multiplySelectors($selectors) { + // find parent selectors + + $parentSelectors = $this->findClosestSelectors(); + if (is_null($parentSelectors)) { + // kill parent reference in top level selector + foreach ($selectors as &$s) { + $this->expandParentSelectors($s, ""); + } + + return $selectors; + } + + $out = array(); + foreach ($parentSelectors as $parent) { + foreach ($selectors as $child) { + $count = $this->expandParentSelectors($child, $parent); + + // don't prepend the parent tag if & was used + if ($count > 0) { + $out[] = trim($child); + } else { + $out[] = trim($parent . ' ' . $child); + } + } + } + + return $out; + } + + // reduces selector expressions + protected function compileSelectors($selectors) { + $out = array(); + + foreach ($selectors as $s) { + if (is_array($s)) { + list(, $value) = $s; + $out[] = trim($this->compileValue($this->reduce($value))); + } else { + $out[] = $s; + } + } + + return $out; + } + + protected function eq($left, $right) { + return $left == $right; + } + + protected function patternMatch($block, $orderedArgs, $keywordArgs) { + // match the guards if it has them + // any one of the groups must have all its guards pass for a match + if (!empty($block->guards)) { + $groupPassed = false; + foreach ($block->guards as $guardGroup) { + foreach ($guardGroup as $guard) { + $this->pushEnv(); + $this->zipSetArgs($block->args, $orderedArgs, $keywordArgs); + + $negate = false; + if ($guard[0] == "negate") { + $guard = $guard[1]; + $negate = true; + } + + $passed = $this->reduce($guard) == self::$TRUE; + if ($negate) $passed = !$passed; + + $this->popEnv(); + + if ($passed) { + $groupPassed = true; + } else { + $groupPassed = false; + break; + } + } + + if ($groupPassed) break; + } + + if (!$groupPassed) { + return false; + } + } + + if (empty($block->args)) { + return $block->isVararg || empty($orderedArgs) && empty($keywordArgs); + } + + $remainingArgs = $block->args; + if ($keywordArgs) { + $remainingArgs = array(); + foreach ($block->args as $arg) { + if ($arg[0] == "arg" && isset($keywordArgs[$arg[1]])) { + continue; + } + + $remainingArgs[] = $arg; + } + } + + $i = -1; // no args + // try to match by arity or by argument literal + foreach ($remainingArgs as $i => $arg) { + switch ($arg[0]) { + case "lit": + if (empty($orderedArgs[$i]) || !$this->eq($arg[1], $orderedArgs[$i])) { + return false; + } + break; + case "arg": + // no arg and no default value + if (!isset($orderedArgs[$i]) && !isset($arg[2])) { + return false; + } + break; + case "rest": + $i--; // rest can be empty + break 2; + } + } + + if ($block->isVararg) { + return true; // not having enough is handled above + } else { + $numMatched = $i + 1; + // greater than becuase default values always match + return $numMatched >= count($orderedArgs); + } + } + + protected function patternMatchAll($blocks, $orderedArgs, $keywordArgs, $skip=array()) { + $matches = null; + foreach ($blocks as $block) { + // skip seen blocks that don't have arguments + if (isset($skip[$block->id]) && !isset($block->args)) { + continue; + } + + if ($this->patternMatch($block, $orderedArgs, $keywordArgs)) { + $matches[] = $block; + } + } + + return $matches; + } + + // attempt to find blocks matched by path and args + protected function findBlocks($searchIn, $path, $orderedArgs, $keywordArgs, $seen=array()) { + if ($searchIn == null) return null; + if (isset($seen[$searchIn->id])) return null; + $seen[$searchIn->id] = true; + + $name = $path[0]; + + if (isset($searchIn->children[$name])) { + $blocks = $searchIn->children[$name]; + if (count($path) == 1) { + $matches = $this->patternMatchAll($blocks, $orderedArgs, $keywordArgs, $seen); + if (!empty($matches)) { + // This will return all blocks that match in the closest + // scope that has any matching block, like lessjs + return $matches; + } + } else { + $matches = array(); + foreach ($blocks as $subBlock) { + $subMatches = $this->findBlocks($subBlock, + array_slice($path, 1), $orderedArgs, $keywordArgs, $seen); + + if (!is_null($subMatches)) { + foreach ($subMatches as $sm) { + $matches[] = $sm; + } + } + } + + return count($matches) > 0 ? $matches : null; + } + } + if ($searchIn->parent === $searchIn) return null; + return $this->findBlocks($searchIn->parent, $path, $orderedArgs, $keywordArgs, $seen); + } + + // sets all argument names in $args to either the default value + // or the one passed in through $values + protected function zipSetArgs($args, $orderedValues, $keywordValues) { + $assignedValues = array(); + + $i = 0; + foreach ($args as $a) { + if ($a[0] == "arg") { + if (isset($keywordValues[$a[1]])) { + // has keyword arg + $value = $keywordValues[$a[1]]; + } elseif (isset($orderedValues[$i])) { + // has ordered arg + $value = $orderedValues[$i]; + $i++; + } elseif (isset($a[2])) { + // has default value + $value = $a[2]; + } else { + $this->throwError("Failed to assign arg " . $a[1]); + $value = null; // :( + } + + $value = $this->reduce($value); + $this->set($a[1], $value); + $assignedValues[] = $value; + } else { + // a lit + $i++; + } + } + + // check for a rest + $last = end($args); + if ($last[0] == "rest") { + $rest = array_slice($orderedValues, count($args) - 1); + $this->set($last[1], $this->reduce(array("list", " ", $rest))); + } + + // wow is this the only true use of PHP's + operator for arrays? + $this->env->arguments = $assignedValues + $orderedValues; + } + + // compile a prop and update $lines or $blocks appropriately + protected function compileProp($prop, $block, $out) { + // set error position context + $this->sourceLoc = isset($prop[-1]) ? $prop[-1] : -1; + + switch ($prop[0]) { + case 'assign': + list(, $name, $value) = $prop; + if ($name[0] == $this->vPrefix) { + $this->set($name, $value); + } else { + $out->lines[] = $this->formatter->property($name, + $this->compileValue($this->reduce($value))); + } + break; + case 'block': + list(, $child) = $prop; + $this->compileBlock($child); + break; + case 'mixin': + list(, $path, $args, $suffix) = $prop; + + $orderedArgs = array(); + $keywordArgs = array(); + foreach ((array)$args as $arg) { + $argval = null; + switch ($arg[0]) { + case "arg": + if (!isset($arg[2])) { + $orderedArgs[] = $this->reduce(array("variable", $arg[1])); + } else { + $keywordArgs[$arg[1]] = $this->reduce($arg[2]); + } + break; + + case "lit": + $orderedArgs[] = $this->reduce($arg[1]); + break; + default: + $this->throwError("Unknown arg type: " . $arg[0]); + } + } + + $mixins = $this->findBlocks($block, $path, $orderedArgs, $keywordArgs); + + if ($mixins === null) { + $this->throwError("{$prop[1][0]} is undefined"); + } + + foreach ($mixins as $mixin) { + if ($mixin === $block && !$orderedArgs) { + continue; + } + + $haveScope = false; + if (isset($mixin->parent->scope)) { + $haveScope = true; + $mixinParentEnv = $this->pushEnv(); + $mixinParentEnv->storeParent = $mixin->parent->scope; + } + + $haveArgs = false; + if (isset($mixin->args)) { + $haveArgs = true; + $this->pushEnv(); + $this->zipSetArgs($mixin->args, $orderedArgs, $keywordArgs); + } + + $oldParent = $mixin->parent; + if ($mixin != $block) $mixin->parent = $block; + + foreach ($this->sortProps($mixin->props) as $subProp) { + if ($suffix !== null && + $subProp[0] == "assign" && + is_string($subProp[1]) && + $subProp[1]{0} != $this->vPrefix) + { + $subProp[2] = array( + 'list', ' ', + array($subProp[2], array('keyword', $suffix)) + ); + } + + $this->compileProp($subProp, $mixin, $out); + } + + $mixin->parent = $oldParent; + + if ($haveArgs) $this->popEnv(); + if ($haveScope) $this->popEnv(); + } + + break; + case 'raw': + $out->lines[] = $prop[1]; + break; + case "directive": + list(, $name, $value) = $prop; + $out->lines[] = "@$name " . $this->compileValue($this->reduce($value)).';'; + break; + case "comment": + $out->lines[] = $prop[1]; + break; + case "import"; + list(, $importPath, $importId) = $prop; + $importPath = $this->reduce($importPath); + + if (!isset($this->env->imports)) { + $this->env->imports = array(); + } + + $result = $this->tryImport($importPath, $block, $out); + + $this->env->imports[$importId] = $result === false ? + array(false, "@import " . $this->compileValue($importPath).";") : + $result; + + break; + case "import_mixin": + list(,$importId) = $prop; + $import = $this->env->imports[$importId]; + if ($import[0] === false) { + if (isset($import[1])) { + $out->lines[] = $import[1]; + } + } else { + list(, $bottom, $parser, $importDir) = $import; + $this->compileImportedProps($bottom, $block, $out, $parser, $importDir); + } + + break; + default: + $this->throwError("unknown op: {$prop[0]}\n"); + } + } + + + /** + * Compiles a primitive value into a CSS property value. + * + * Values in lessphp are typed by being wrapped in arrays, their format is + * typically: + * + * array(type, contents [, additional_contents]*) + * + * The input is expected to be reduced. This function will not work on + * things like expressions and variables. + */ + protected function compileValue($value) { + switch ($value[0]) { + case 'list': + // [1] - delimiter + // [2] - array of values + return implode($value[1], array_map(array($this, 'compileValue'), $value[2])); + case 'raw_color': + if (!empty($this->formatter->compressColors)) { + return $this->compileValue($this->coerceColor($value)); + } + return $value[1]; + case 'keyword': + // [1] - the keyword + return $value[1]; + case 'number': + list(, $num, $unit) = $value; + // [1] - the number + // [2] - the unit + if ($this->numberPrecision !== null) { + $num = round($num, $this->numberPrecision); + } + return $num . $unit; + case 'string': + // [1] - contents of string (includes quotes) + list(, $delim, $content) = $value; + foreach ($content as &$part) { + if (is_array($part)) { + $part = $this->compileValue($part); + } + } + return $delim . implode($content) . $delim; + case 'color': + // [1] - red component (either number or a %) + // [2] - green component + // [3] - blue component + // [4] - optional alpha component + list(, $r, $g, $b) = $value; + $r = round($r); + $g = round($g); + $b = round($b); + + if (count($value) == 5 && $value[4] != 1) { // rgba + return 'rgba('.$r.','.$g.','.$b.','.$value[4].')'; + } + + $h = sprintf("#%02x%02x%02x", $r, $g, $b); + + if (!empty($this->formatter->compressColors)) { + // Converting hex color to short notation (e.g. #003399 to #039) + if ($h[1] === $h[2] && $h[3] === $h[4] && $h[5] === $h[6]) { + $h = '#' . $h[1] . $h[3] . $h[5]; + } + } + + return $h; + + case 'function': + list(, $name, $args) = $value; + return $name.'('.$this->compileValue($args).')'; + default: // assumed to be unit + $this->throwError("unknown value type: $value[0]"); + } + } + + protected function lib_pow($args) { + list($base, $exp) = $this->assertArgs($args, 2, "pow"); + return pow($this->assertNumber($base), $this->assertNumber($exp)); + } + + protected function lib_pi() { + return pi(); + } + + protected function lib_mod($args) { + list($a, $b) = $this->assertArgs($args, 2, "mod"); + return $this->assertNumber($a) % $this->assertNumber($b); + } + + protected function lib_tan($num) { + return tan($this->assertNumber($num)); + } + + protected function lib_sin($num) { + return sin($this->assertNumber($num)); + } + + protected function lib_cos($num) { + return cos($this->assertNumber($num)); + } + + protected function lib_atan($num) { + $num = atan($this->assertNumber($num)); + return array("number", $num, "rad"); + } + + protected function lib_asin($num) { + $num = asin($this->assertNumber($num)); + return array("number", $num, "rad"); + } + + protected function lib_acos($num) { + $num = acos($this->assertNumber($num)); + return array("number", $num, "rad"); + } + + protected function lib_sqrt($num) { + return sqrt($this->assertNumber($num)); + } + + protected function lib_extract($value) { + list($list, $idx) = $this->assertArgs($value, 2, "extract"); + $idx = $this->assertNumber($idx); + // 1 indexed + if ($list[0] == "list" && isset($list[2][$idx - 1])) { + return $list[2][$idx - 1]; + } + } + + protected function lib_isnumber($value) { + return $this->toBool($value[0] == "number"); + } + + protected function lib_isstring($value) { + return $this->toBool($value[0] == "string"); + } + + protected function lib_iscolor($value) { + return $this->toBool($this->coerceColor($value)); + } + + protected function lib_iskeyword($value) { + return $this->toBool($value[0] == "keyword"); + } + + protected function lib_ispixel($value) { + return $this->toBool($value[0] == "number" && $value[2] == "px"); + } + + protected function lib_ispercentage($value) { + return $this->toBool($value[0] == "number" && $value[2] == "%"); + } + + protected function lib_isem($value) { + return $this->toBool($value[0] == "number" && $value[2] == "em"); + } + + protected function lib_isrem($value) { + return $this->toBool($value[0] == "number" && $value[2] == "rem"); + } + + protected function lib_rgbahex($color) { + $color = $this->coerceColor($color); + if (is_null($color)) + $this->throwError("color expected for rgbahex"); + + return sprintf("#%02x%02x%02x%02x", + isset($color[4]) ? $color[4]*255 : 255, + $color[1],$color[2], $color[3]); + } + + protected function lib_argb($color){ + return $this->lib_rgbahex($color); + } + + // utility func to unquote a string + protected function lib_e($arg) { + switch ($arg[0]) { + case "list": + $items = $arg[2]; + if (isset($items[0])) { + return $this->lib_e($items[0]); + } + $this->throwError("unrecognised input"); + case "string": + $arg[1] = ""; + return $arg; + case "keyword": + return $arg; + default: + return array("keyword", $this->compileValue($arg)); + } + } + + protected function lib__sprintf($args) { + if ($args[0] != "list") return $args; + $values = $args[2]; + $string = array_shift($values); + $template = $this->compileValue($this->lib_e($string)); + + $i = 0; + if (preg_match_all('/%[dsa]/', $template, $m)) { + foreach ($m[0] as $match) { + $val = isset($values[$i]) ? + $this->reduce($values[$i]) : array('keyword', ''); + + // lessjs compat, renders fully expanded color, not raw color + if ($color = $this->coerceColor($val)) { + $val = $color; + } + + $i++; + $rep = $this->compileValue($this->lib_e($val)); + $template = preg_replace('/'.self::preg_quote($match).'/', + $rep, $template, 1); + } + } + + $d = $string[0] == "string" ? $string[1] : '"'; + return array("string", $d, array($template)); + } + + protected function lib_floor($arg) { + $value = $this->assertNumber($arg); + return array("number", floor($value), $arg[2]); + } + + protected function lib_ceil($arg) { + $value = $this->assertNumber($arg); + return array("number", ceil($value), $arg[2]); + } + + protected function lib_round($arg) { + if($arg[0] != "list") { + $value = $this->assertNumber($arg); + return array("number", round($value), $arg[2]); + } else { + $value = $this->assertNumber($arg[2][0]); + $precision = $this->assertNumber($arg[2][1]); + return array("number", round($value, $precision), $arg[2][0][2]); + } + } + + protected function lib_unit($arg) { + if ($arg[0] == "list") { + list($number, $newUnit) = $arg[2]; + return array("number", $this->assertNumber($number), + $this->compileValue($this->lib_e($newUnit))); + } else { + return array("number", $this->assertNumber($arg), ""); + } + } + + /** + * Helper function to get arguments for color manipulation functions. + * takes a list that contains a color like thing and a percentage + */ + public function colorArgs($args) { + if ($args[0] != 'list' || count($args[2]) < 2) { + return array(array('color', 0, 0, 0), 0); + } + list($color, $delta) = $args[2]; + $color = $this->assertColor($color); + $delta = floatval($delta[1]); + + return array($color, $delta); + } + + protected function lib_darken($args) { + list($color, $delta) = $this->colorArgs($args); + + $hsl = $this->toHSL($color); + $hsl[3] = $this->clamp($hsl[3] - $delta, 100); + return $this->toRGB($hsl); + } + + protected function lib_lighten($args) { + list($color, $delta) = $this->colorArgs($args); + + $hsl = $this->toHSL($color); + $hsl[3] = $this->clamp($hsl[3] + $delta, 100); + return $this->toRGB($hsl); + } + + protected function lib_saturate($args) { + list($color, $delta) = $this->colorArgs($args); + + $hsl = $this->toHSL($color); + $hsl[2] = $this->clamp($hsl[2] + $delta, 100); + return $this->toRGB($hsl); + } + + protected function lib_desaturate($args) { + list($color, $delta) = $this->colorArgs($args); + + $hsl = $this->toHSL($color); + $hsl[2] = $this->clamp($hsl[2] - $delta, 100); + return $this->toRGB($hsl); + } + + protected function lib_spin($args) { + list($color, $delta) = $this->colorArgs($args); + + $hsl = $this->toHSL($color); + + $hsl[1] = $hsl[1] + $delta % 360; + if ($hsl[1] < 0) $hsl[1] += 360; + + return $this->toRGB($hsl); + } + + protected function lib_fadeout($args) { + list($color, $delta) = $this->colorArgs($args); + $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) - $delta/100); + return $color; + } + + protected function lib_fadein($args) { + list($color, $delta) = $this->colorArgs($args); + $color[4] = $this->clamp((isset($color[4]) ? $color[4] : 1) + $delta/100); + return $color; + } + + protected function lib_hue($color) { + $hsl = $this->toHSL($this->assertColor($color)); + return round($hsl[1]); + } + + protected function lib_saturation($color) { + $hsl = $this->toHSL($this->assertColor($color)); + return round($hsl[2]); + } + + protected function lib_lightness($color) { + $hsl = $this->toHSL($this->assertColor($color)); + return round($hsl[3]); + } + + // get the alpha of a color + // defaults to 1 for non-colors or colors without an alpha + protected function lib_alpha($value) { + if (!is_null($color = $this->coerceColor($value))) { + return isset($color[4]) ? $color[4] : 1; + } + } + + // set the alpha of the color + protected function lib_fade($args) { + list($color, $alpha) = $this->colorArgs($args); + $color[4] = $this->clamp($alpha / 100.0); + return $color; + } + + protected function lib_percentage($arg) { + $num = $this->assertNumber($arg); + return array("number", $num*100, "%"); + } + + // mixes two colors by weight + // mix(@color1, @color2, [@weight: 50%]); + // http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#mix-instance_method + protected function lib_mix($args) { + if ($args[0] != "list" || count($args[2]) < 2) + $this->throwError("mix expects (color1, color2, weight)"); + + list($first, $second) = $args[2]; + $first = $this->assertColor($first); + $second = $this->assertColor($second); + + $first_a = $this->lib_alpha($first); + $second_a = $this->lib_alpha($second); + + if (isset($args[2][2])) { + $weight = $args[2][2][1] / 100.0; + } else { + $weight = 0.5; + } + + $w = $weight * 2 - 1; + $a = $first_a - $second_a; + + $w1 = (($w * $a == -1 ? $w : ($w + $a)/(1 + $w * $a)) + 1) / 2.0; + $w2 = 1.0 - $w1; + + $new = array('color', + $w1 * $first[1] + $w2 * $second[1], + $w1 * $first[2] + $w2 * $second[2], + $w1 * $first[3] + $w2 * $second[3], + ); + + if ($first_a != 1.0 || $second_a != 1.0) { + $new[] = $first_a * $weight + $second_a * ($weight - 1); + } + + return $this->fixColor($new); + } + + protected function lib_contrast($args) { + $darkColor = array('color', 0, 0, 0); + $lightColor = array('color', 255, 255, 255); + $threshold = 0.43; + + if ( $args[0] == 'list' ) { + $inputColor = ( isset($args[2][0]) ) ? $this->assertColor($args[2][0]) : $lightColor; + $darkColor = ( isset($args[2][1]) ) ? $this->assertColor($args[2][1]) : $darkColor; + $lightColor = ( isset($args[2][2]) ) ? $this->assertColor($args[2][2]) : $lightColor; + $threshold = ( isset($args[2][3]) ) ? $this->assertNumber($args[2][3]) : $threshold; + } + else { + $inputColor = $this->assertColor($args); + } + + $inputColor = $this->coerceColor($inputColor); + $darkColor = $this->coerceColor($darkColor); + $lightColor = $this->coerceColor($lightColor); + + //Figure out which is actually light and dark! + if ( $this->lib_luma($darkColor) > $this->lib_luma($lightColor) ) { + $t = $lightColor; + $lightColor = $darkColor; + $darkColor = $t; + } + + $inputColor_alpha = $this->lib_alpha($inputColor); + if ( ( $this->lib_luma($inputColor) * $inputColor_alpha) < $threshold) { + return $lightColor; + } + return $darkColor; + } + + protected function lib_luma($color) { + $color = $this->coerceColor($color); + return (0.2126 * $color[0] / 255) + (0.7152 * $color[1] / 255) + (0.0722 * $color[2] / 255); + } + + + public function assertColor($value, $error = "expected color value") { + $color = $this->coerceColor($value); + if (is_null($color)) $this->throwError($error); + return $color; + } + + public function assertNumber($value, $error = "expecting number") { + if ($value[0] == "number") return $value[1]; + $this->throwError($error); + } + + public function assertArgs($value, $expectedArgs, $name="") { + if ($expectedArgs == 1) { + return $value; + } else { + if ($value[0] !== "list" || $value[1] != ",") $this->throwError("expecting list"); + $values = $value[2]; + $numValues = count($values); + if ($expectedArgs != $numValues) { + if ($name) { + $name = $name . ": "; + } + + $this->throwError("${name}expecting $expectedArgs arguments, got $numValues"); + } + + return $values; + } + } + + protected function toHSL($color) { + if ($color[0] == 'hsl') return $color; + + $r = $color[1] / 255; + $g = $color[2] / 255; + $b = $color[3] / 255; + + $min = min($r, $g, $b); + $max = max($r, $g, $b); + + $L = ($min + $max) / 2; + if ($min == $max) { + $S = $H = 0; + } else { + if ($L < 0.5) + $S = ($max - $min)/($max + $min); + else + $S = ($max - $min)/(2.0 - $max - $min); + + if ($r == $max) $H = ($g - $b)/($max - $min); + elseif ($g == $max) $H = 2.0 + ($b - $r)/($max - $min); + elseif ($b == $max) $H = 4.0 + ($r - $g)/($max - $min); + + } + + $out = array('hsl', + ($H < 0 ? $H + 6 : $H)*60, + $S*100, + $L*100, + ); + + if (count($color) > 4) $out[] = $color[4]; // copy alpha + return $out; + } + + protected function toRGB_helper($comp, $temp1, $temp2) { + if ($comp < 0) $comp += 1.0; + elseif ($comp > 1) $comp -= 1.0; + + if (6 * $comp < 1) return $temp1 + ($temp2 - $temp1) * 6 * $comp; + if (2 * $comp < 1) return $temp2; + if (3 * $comp < 2) return $temp1 + ($temp2 - $temp1)*((2/3) - $comp) * 6; + + return $temp1; + } + + /** + * Converts a hsl array into a color value in rgb. + * Expects H to be in range of 0 to 360, S and L in 0 to 100 + */ + protected function toRGB($color) { + if ($color[0] == 'color') return $color; + + $H = $color[1] / 360; + $S = $color[2] / 100; + $L = $color[3] / 100; + + if ($S == 0) { + $r = $g = $b = $L; + } else { + $temp2 = $L < 0.5 ? + $L*(1.0 + $S) : + $L + $S - $L * $S; + + $temp1 = 2.0 * $L - $temp2; + + $r = $this->toRGB_helper($H + 1/3, $temp1, $temp2); + $g = $this->toRGB_helper($H, $temp1, $temp2); + $b = $this->toRGB_helper($H - 1/3, $temp1, $temp2); + } + + // $out = array('color', round($r*255), round($g*255), round($b*255)); + $out = array('color', $r*255, $g*255, $b*255); + if (count($color) > 4) $out[] = $color[4]; // copy alpha + return $out; + } + + protected function clamp($v, $max = 1, $min = 0) { + return min($max, max($min, $v)); + } + + /** + * Convert the rgb, rgba, hsl color literals of function type + * as returned by the parser into values of color type. + */ + protected function funcToColor($func) { + $fname = $func[1]; + if ($func[2][0] != 'list') return false; // need a list of arguments + $rawComponents = $func[2][2]; + + if ($fname == 'hsl' || $fname == 'hsla') { + $hsl = array('hsl'); + $i = 0; + foreach ($rawComponents as $c) { + $val = $this->reduce($c); + $val = isset($val[1]) ? floatval($val[1]) : 0; + + if ($i == 0) $clamp = 360; + elseif ($i < 3) $clamp = 100; + else $clamp = 1; + + $hsl[] = $this->clamp($val, $clamp); + $i++; + } + + while (count($hsl) < 4) $hsl[] = 0; + return $this->toRGB($hsl); + + } elseif ($fname == 'rgb' || $fname == 'rgba') { + $components = array(); + $i = 1; + foreach ($rawComponents as $c) { + $c = $this->reduce($c); + if ($i < 4) { + if ($c[0] == "number" && $c[2] == "%") { + $components[] = 255 * ($c[1] / 100); + } else { + $components[] = floatval($c[1]); + } + } elseif ($i == 4) { + if ($c[0] == "number" && $c[2] == "%") { + $components[] = 1.0 * ($c[1] / 100); + } else { + $components[] = floatval($c[1]); + } + } else break; + + $i++; + } + while (count($components) < 3) $components[] = 0; + array_unshift($components, 'color'); + return $this->fixColor($components); + } + + return false; + } + + protected function reduce($value, $forExpression = false) { + switch ($value[0]) { + case "interpolate": + $reduced = $this->reduce($value[1]); + $var = $this->compileValue($reduced); + $res = $this->reduce(array("variable", $this->vPrefix . $var)); + + if ($res[0] == "raw_color") { + $res = $this->coerceColor($res); + } + + if (empty($value[2])) $res = $this->lib_e($res); + + return $res; + case "variable": + $key = $value[1]; + if (is_array($key)) { + $key = $this->reduce($key); + $key = $this->vPrefix . $this->compileValue($this->lib_e($key)); + } + + $seen =& $this->env->seenNames; + + if (!empty($seen[$key])) { + $this->throwError("infinite loop detected: $key"); + } + + $seen[$key] = true; + $out = $this->reduce($this->get($key)); + $seen[$key] = false; + return $out; + case "list": + foreach ($value[2] as &$item) { + $item = $this->reduce($item, $forExpression); + } + return $value; + case "expression": + return $this->evaluate($value); + case "string": + foreach ($value[2] as &$part) { + if (is_array($part)) { + $strip = $part[0] == "variable"; + $part = $this->reduce($part); + if ($strip) $part = $this->lib_e($part); + } + } + return $value; + case "escape": + list(,$inner) = $value; + return $this->lib_e($this->reduce($inner)); + case "function": + $color = $this->funcToColor($value); + if ($color) return $color; + + list(, $name, $args) = $value; + if ($name == "%") $name = "_sprintf"; + $f = isset($this->libFunctions[$name]) ? + $this->libFunctions[$name] : array($this, 'lib_'.$name); + + if (is_callable($f)) { + if ($args[0] == 'list') + $args = self::compressList($args[2], $args[1]); + + $ret = call_user_func($f, $this->reduce($args, true), $this); + + if (is_null($ret)) { + return array("string", "", array( + $name, "(", $args, ")" + )); + } + + // convert to a typed value if the result is a php primitive + if (is_numeric($ret)) $ret = array('number', $ret, ""); + elseif (!is_array($ret)) $ret = array('keyword', $ret); + + return $ret; + } + + // plain function, reduce args + $value[2] = $this->reduce($value[2]); + return $value; + case "unary": + list(, $op, $exp) = $value; + $exp = $this->reduce($exp); + + if ($exp[0] == "number") { + switch ($op) { + case "+": + return $exp; + case "-": + $exp[1] *= -1; + return $exp; + } + } + return array("string", "", array($op, $exp)); + } + + if ($forExpression) { + switch ($value[0]) { + case "keyword": + if ($color = $this->coerceColor($value)) { + return $color; + } + break; + case "raw_color": + return $this->coerceColor($value); + } + } + + return $value; + } + + + // coerce a value for use in color operation + protected function coerceColor($value) { + switch($value[0]) { + case 'color': return $value; + case 'raw_color': + $c = array("color", 0, 0, 0); + $colorStr = substr($value[1], 1); + $num = hexdec($colorStr); + $width = strlen($colorStr) == 3 ? 16 : 256; + + for ($i = 3; $i > 0; $i--) { // 3 2 1 + $t = $num % $width; + $num /= $width; + + $c[$i] = $t * (256/$width) + $t * floor(16/$width); + } + + return $c; + case 'keyword': + $name = $value[1]; + if (isset(self::$cssColors[$name])) { + $rgba = explode(',', self::$cssColors[$name]); + + if(isset($rgba[3])) + return array('color', $rgba[0], $rgba[1], $rgba[2], $rgba[3]); + + return array('color', $rgba[0], $rgba[1], $rgba[2]); + } + return null; + } + } + + // make something string like into a string + protected function coerceString($value) { + switch ($value[0]) { + case "string": + return $value; + case "keyword": + return array("string", "", array($value[1])); + } + return null; + } + + // turn list of length 1 into value type + protected function flattenList($value) { + if ($value[0] == "list" && count($value[2]) == 1) { + return $this->flattenList($value[2][0]); + } + return $value; + } + + public function toBool($a) { + if ($a) return self::$TRUE; + else return self::$FALSE; + } + + // evaluate an expression + protected function evaluate($exp) { + list(, $op, $left, $right, $whiteBefore, $whiteAfter) = $exp; + + $left = $this->reduce($left, true); + $right = $this->reduce($right, true); + + if ($leftColor = $this->coerceColor($left)) { + $left = $leftColor; + } + + if ($rightColor = $this->coerceColor($right)) { + $right = $rightColor; + } + + $ltype = $left[0]; + $rtype = $right[0]; + + // operators that work on all types + if ($op == "and") { + return $this->toBool($left == self::$TRUE && $right == self::$TRUE); + } + + if ($op == "=") { + return $this->toBool($this->eq($left, $right) ); + } + + if ($op == "+" && !is_null($str = $this->stringConcatenate($left, $right))) { + return $str; + } + + // type based operators + $fname = "op_${ltype}_${rtype}"; + if (is_callable(array($this, $fname))) { + $out = $this->$fname($op, $left, $right); + if (!is_null($out)) return $out; + } + + // make the expression look it did before being parsed + $paddedOp = $op; + if ($whiteBefore) $paddedOp = " " . $paddedOp; + if ($whiteAfter) $paddedOp .= " "; + + return array("string", "", array($left, $paddedOp, $right)); + } + + protected function stringConcatenate($left, $right) { + if ($strLeft = $this->coerceString($left)) { + if ($right[0] == "string") { + $right[1] = ""; + } + $strLeft[2][] = $right; + return $strLeft; + } + + if ($strRight = $this->coerceString($right)) { + array_unshift($strRight[2], $left); + return $strRight; + } + } + + + // make sure a color's components don't go out of bounds + protected function fixColor($c) { + foreach (range(1, 3) as $i) { + if ($c[$i] < 0) $c[$i] = 0; + if ($c[$i] > 255) $c[$i] = 255; + } + + return $c; + } + + protected function op_number_color($op, $lft, $rgt) { + if ($op == '+' || $op == '*') { + return $this->op_color_number($op, $rgt, $lft); + } + } + + protected function op_color_number($op, $lft, $rgt) { + if ($rgt[0] == '%') $rgt[1] /= 100; + + return $this->op_color_color($op, $lft, + array_fill(1, count($lft) - 1, $rgt[1])); + } + + protected function op_color_color($op, $left, $right) { + $out = array('color'); + $max = count($left) > count($right) ? count($left) : count($right); + foreach (range(1, $max - 1) as $i) { + $lval = isset($left[$i]) ? $left[$i] : 0; + $rval = isset($right[$i]) ? $right[$i] : 0; + switch ($op) { + case '+': + $out[] = $lval + $rval; + break; + case '-': + $out[] = $lval - $rval; + break; + case '*': + $out[] = $lval * $rval; + break; + case '%': + $out[] = $lval % $rval; + break; + case '/': + if ($rval == 0) $this->throwError("evaluate error: can't divide by zero"); + $out[] = $lval / $rval; + break; + default: + $this->throwError('evaluate error: color op number failed on op '.$op); + } + } + return $this->fixColor($out); + } + + function lib_red($color){ + $color = $this->coerceColor($color); + if (is_null($color)) { + $this->throwError('color expected for red()'); + } + + return $color[1]; + } + + function lib_green($color){ + $color = $this->coerceColor($color); + if (is_null($color)) { + $this->throwError('color expected for green()'); + } + + return $color[2]; + } + + function lib_blue($color){ + $color = $this->coerceColor($color); + if (is_null($color)) { + $this->throwError('color expected for blue()'); + } + + return $color[3]; + } + + + // operator on two numbers + protected function op_number_number($op, $left, $right) { + $unit = empty($left[2]) ? $right[2] : $left[2]; + + $value = 0; + switch ($op) { + case '+': + $value = $left[1] + $right[1]; + break; + case '*': + $value = $left[1] * $right[1]; + break; + case '-': + $value = $left[1] - $right[1]; + break; + case '%': + $value = $left[1] % $right[1]; + break; + case '/': + if ($right[1] == 0) $this->throwError('parse error: divide by zero'); + $value = $left[1] / $right[1]; + break; + case '<': + return $this->toBool($left[1] < $right[1]); + case '>': + return $this->toBool($left[1] > $right[1]); + case '>=': + return $this->toBool($left[1] >= $right[1]); + case '=<': + return $this->toBool($left[1] <= $right[1]); + default: + $this->throwError('parse error: unknown number operator: '.$op); + } + + return array("number", $value, $unit); + } + + + /* environment functions */ + + protected function makeOutputBlock($type, $selectors = null) { + $b = new stdclass; + $b->lines = array(); + $b->children = array(); + $b->selectors = $selectors; + $b->type = $type; + $b->parent = $this->scope; + return $b; + } + + // the state of execution + protected function pushEnv($block = null) { + $e = new stdclass; + $e->parent = $this->env; + $e->store = array(); + $e->block = $block; + + $this->env = $e; + return $e; + } + + // pop something off the stack + protected function popEnv() { + $old = $this->env; + $this->env = $this->env->parent; + return $old; + } + + // set something in the current env + protected function set($name, $value) { + $this->env->store[$name] = $value; + } + + + // get the highest occurrence entry for a name + protected function get($name) { + $current = $this->env; + + $isArguments = $name == $this->vPrefix . 'arguments'; + while ($current) { + if ($isArguments && isset($current->arguments)) { + return array('list', ' ', $current->arguments); + } + + if (isset($current->store[$name])) + return $current->store[$name]; + else { + $current = isset($current->storeParent) ? + $current->storeParent : $current->parent; + } + } + + $this->throwError("variable $name is undefined"); + } + + // inject array of unparsed strings into environment as variables + protected function injectVariables($args) { + $this->pushEnv(); + $parser = new lessc_parser($this, __METHOD__); + foreach ($args as $name => $strValue) { + if ($name{0} != '@') $name = '@'.$name; + $parser->count = 0; + $parser->buffer = (string)$strValue; + if (!$parser->propertyValue($value)) { + throw new Exception("failed to parse passed in variable $name: $strValue"); + } + + $this->set($name, $value); + } + } + + /** + * Initialize any static state, can initialize parser for a file + * $opts isn't used yet + */ + public function __construct($fname = null) { + if ($fname !== null) { + // used for deprecated parse method + $this->_parseFile = $fname; + } + } + + public function compile($string, $name = null) { + $locale = setlocale(LC_NUMERIC, 0); + setlocale(LC_NUMERIC, "C"); + + $this->parser = $this->makeParser($name); + $root = $this->parser->parse($string); + + $this->env = null; + $this->scope = null; + + $this->formatter = $this->newFormatter(); + + if (!empty($this->registeredVars)) { + $this->injectVariables($this->registeredVars); + } + + $this->sourceParser = $this->parser; // used for error messages + $this->compileBlock($root); + + ob_start(); + $this->formatter->block($this->scope); + $out = ob_get_clean(); + setlocale(LC_NUMERIC, $locale); + return $out; + } + + public function compileFile($fname, $outFname = null) { + if (!is_readable($fname)) { + throw new Exception('load error: failed to find '.$fname); + } + + $pi = pathinfo($fname); + + $oldImport = $this->importDir; + + $this->importDir = (array)$this->importDir; + $this->importDir[] = $pi['dirname'].'/'; + + $this->addParsedFile($fname); + + $out = $this->compile(file_get_contents($fname), $fname); + + $this->importDir = $oldImport; + + if ($outFname !== null) { + return file_put_contents($outFname, $out); + } + + return $out; + } + + // compile only if changed input has changed or output doesn't exist + public function checkedCompile($in, $out) { + if (!is_file($out) || filemtime($in) > filemtime($out)) { + $this->compileFile($in, $out); + return true; + } + return false; + } + + /** + * Execute lessphp on a .less file or a lessphp cache structure + * + * The lessphp cache structure contains information about a specific + * less file having been parsed. It can be used as a hint for future + * calls to determine whether or not a rebuild is required. + * + * The cache structure contains two important keys that may be used + * externally: + * + * compiled: The final compiled CSS + * updated: The time (in seconds) the CSS was last compiled + * + * The cache structure is a plain-ol' PHP associative array and can + * be serialized and unserialized without a hitch. + * + * @param mixed $in Input + * @param bool $force Force rebuild? + * @return array lessphp cache structure + */ + public function cachedCompile($in, $force = false) { + // assume no root + $root = null; + + if (is_string($in)) { + $root = $in; + } elseif (is_array($in) and isset($in['root'])) { + if ($force or ! isset($in['files'])) { + // If we are forcing a recompile or if for some reason the + // structure does not contain any file information we should + // specify the root to trigger a rebuild. + $root = $in['root']; + } elseif (isset($in['files']) and is_array($in['files'])) { + foreach ($in['files'] as $fname => $ftime ) { + if (!file_exists($fname) or filemtime($fname) > $ftime) { + // One of the files we knew about previously has changed + // so we should look at our incoming root again. + $root = $in['root']; + break; + } + } + } + } else { + // TODO: Throw an exception? We got neither a string nor something + // that looks like a compatible lessphp cache structure. + return null; + } + + if ($root !== null) { + // If we have a root value which means we should rebuild. + $out = array(); + $out['root'] = $root; + $out['compiled'] = $this->compileFile($root); + $out['files'] = $this->allParsedFiles(); + $out['updated'] = time(); + return $out; + } else { + // No changes, pass back the structure + // we were given initially. + return $in; + } + + } + + // parse and compile buffer + // This is deprecated + public function parse($str = null, $initialVariables = null) { + if (is_array($str)) { + $initialVariables = $str; + $str = null; + } + + $oldVars = $this->registeredVars; + if ($initialVariables !== null) { + $this->setVariables($initialVariables); + } + + if ($str == null) { + if (empty($this->_parseFile)) { + throw new exception("nothing to parse"); + } + + $out = $this->compileFile($this->_parseFile); + } else { + $out = $this->compile($str); + } + + $this->registeredVars = $oldVars; + return $out; + } + + protected function makeParser($name) { + $parser = new lessc_parser($this, $name); + $parser->writeComments = $this->preserveComments; + + return $parser; + } + + public function setFormatter($name) { + $this->formatterName = $name; + } + + protected function newFormatter() { + $className = "lessc_formatter_lessjs"; + if (!empty($this->formatterName)) { + if (!is_string($this->formatterName)) + return $this->formatterName; + $className = "lessc_formatter_$this->formatterName"; + } + + return new $className; + } + + public function setPreserveComments($preserve) { + $this->preserveComments = $preserve; + } + + public function registerFunction($name, $func) { + $this->libFunctions[$name] = $func; + } + + public function unregisterFunction($name) { + unset($this->libFunctions[$name]); + } + + public function setVariables($variables) { + $this->registeredVars = array_merge($this->registeredVars, $variables); + } + + public function unsetVariable($name) { + unset($this->registeredVars[$name]); + } + + public function setImportDir($dirs) { + $this->importDir = (array)$dirs; + } + + public function addImportDir($dir) { + $this->importDir = (array)$this->importDir; + $this->importDir[] = $dir; + } + + public function allParsedFiles() { + return $this->allParsedFiles; + } + + public function addParsedFile($file) { + $this->allParsedFiles[realpath($file)] = filemtime($file); + } + + /** + * Uses the current value of $this->count to show line and line number + */ + public function throwError($msg = null) { + if ($this->sourceLoc >= 0) { + $this->sourceParser->throwError($msg, $this->sourceLoc); + } + throw new exception($msg); + } + + // compile file $in to file $out if $in is newer than $out + // returns true when it compiles, false otherwise + public static function ccompile($in, $out, $less = null) { + if ($less === null) { + $less = new self; + } + return $less->checkedCompile($in, $out); + } + + public static function cexecute($in, $force = false, $less = null) { + if ($less === null) { + $less = new self; + } + return $less->cachedCompile($in, $force); + } + + static protected $cssColors = array( + 'aliceblue' => '240,248,255', + 'antiquewhite' => '250,235,215', + 'aqua' => '0,255,255', + 'aquamarine' => '127,255,212', + 'azure' => '240,255,255', + 'beige' => '245,245,220', + 'bisque' => '255,228,196', + 'black' => '0,0,0', + 'blanchedalmond' => '255,235,205', + 'blue' => '0,0,255', + 'blueviolet' => '138,43,226', + 'brown' => '165,42,42', + 'burlywood' => '222,184,135', + 'cadetblue' => '95,158,160', + 'chartreuse' => '127,255,0', + 'chocolate' => '210,105,30', + 'coral' => '255,127,80', + 'cornflowerblue' => '100,149,237', + 'cornsilk' => '255,248,220', + 'crimson' => '220,20,60', + 'cyan' => '0,255,255', + 'darkblue' => '0,0,139', + 'darkcyan' => '0,139,139', + 'darkgoldenrod' => '184,134,11', + 'darkgray' => '169,169,169', + 'darkgreen' => '0,100,0', + 'darkgrey' => '169,169,169', + 'darkkhaki' => '189,183,107', + 'darkmagenta' => '139,0,139', + 'darkolivegreen' => '85,107,47', + 'darkorange' => '255,140,0', + 'darkorchid' => '153,50,204', + 'darkred' => '139,0,0', + 'darksalmon' => '233,150,122', + 'darkseagreen' => '143,188,143', + 'darkslateblue' => '72,61,139', + 'darkslategray' => '47,79,79', + 'darkslategrey' => '47,79,79', + 'darkturquoise' => '0,206,209', + 'darkviolet' => '148,0,211', + 'deeppink' => '255,20,147', + 'deepskyblue' => '0,191,255', + 'dimgray' => '105,105,105', + 'dimgrey' => '105,105,105', + 'dodgerblue' => '30,144,255', + 'firebrick' => '178,34,34', + 'floralwhite' => '255,250,240', + 'forestgreen' => '34,139,34', + 'fuchsia' => '255,0,255', + 'gainsboro' => '220,220,220', + 'ghostwhite' => '248,248,255', + 'gold' => '255,215,0', + 'goldenrod' => '218,165,32', + 'gray' => '128,128,128', + 'green' => '0,128,0', + 'greenyellow' => '173,255,47', + 'grey' => '128,128,128', + 'honeydew' => '240,255,240', + 'hotpink' => '255,105,180', + 'indianred' => '205,92,92', + 'indigo' => '75,0,130', + 'ivory' => '255,255,240', + 'khaki' => '240,230,140', + 'lavender' => '230,230,250', + 'lavenderblush' => '255,240,245', + 'lawngreen' => '124,252,0', + 'lemonchiffon' => '255,250,205', + 'lightblue' => '173,216,230', + 'lightcoral' => '240,128,128', + 'lightcyan' => '224,255,255', + 'lightgoldenrodyellow' => '250,250,210', + 'lightgray' => '211,211,211', + 'lightgreen' => '144,238,144', + 'lightgrey' => '211,211,211', + 'lightpink' => '255,182,193', + 'lightsalmon' => '255,160,122', + 'lightseagreen' => '32,178,170', + 'lightskyblue' => '135,206,250', + 'lightslategray' => '119,136,153', + 'lightslategrey' => '119,136,153', + 'lightsteelblue' => '176,196,222', + 'lightyellow' => '255,255,224', + 'lime' => '0,255,0', + 'limegreen' => '50,205,50', + 'linen' => '250,240,230', + 'magenta' => '255,0,255', + 'maroon' => '128,0,0', + 'mediumaquamarine' => '102,205,170', + 'mediumblue' => '0,0,205', + 'mediumorchid' => '186,85,211', + 'mediumpurple' => '147,112,219', + 'mediumseagreen' => '60,179,113', + 'mediumslateblue' => '123,104,238', + 'mediumspringgreen' => '0,250,154', + 'mediumturquoise' => '72,209,204', + 'mediumvioletred' => '199,21,133', + 'midnightblue' => '25,25,112', + 'mintcream' => '245,255,250', + 'mistyrose' => '255,228,225', + 'moccasin' => '255,228,181', + 'navajowhite' => '255,222,173', + 'navy' => '0,0,128', + 'oldlace' => '253,245,230', + 'olive' => '128,128,0', + 'olivedrab' => '107,142,35', + 'orange' => '255,165,0', + 'orangered' => '255,69,0', + 'orchid' => '218,112,214', + 'palegoldenrod' => '238,232,170', + 'palegreen' => '152,251,152', + 'paleturquoise' => '175,238,238', + 'palevioletred' => '219,112,147', + 'papayawhip' => '255,239,213', + 'peachpuff' => '255,218,185', + 'peru' => '205,133,63', + 'pink' => '255,192,203', + 'plum' => '221,160,221', + 'powderblue' => '176,224,230', + 'purple' => '128,0,128', + 'red' => '255,0,0', + 'rosybrown' => '188,143,143', + 'royalblue' => '65,105,225', + 'saddlebrown' => '139,69,19', + 'salmon' => '250,128,114', + 'sandybrown' => '244,164,96', + 'seagreen' => '46,139,87', + 'seashell' => '255,245,238', + 'sienna' => '160,82,45', + 'silver' => '192,192,192', + 'skyblue' => '135,206,235', + 'slateblue' => '106,90,205', + 'slategray' => '112,128,144', + 'slategrey' => '112,128,144', + 'snow' => '255,250,250', + 'springgreen' => '0,255,127', + 'steelblue' => '70,130,180', + 'tan' => '210,180,140', + 'teal' => '0,128,128', + 'thistle' => '216,191,216', + 'tomato' => '255,99,71', + 'transparent' => '0,0,0,0', + 'turquoise' => '64,224,208', + 'violet' => '238,130,238', + 'wheat' => '245,222,179', + 'white' => '255,255,255', + 'whitesmoke' => '245,245,245', + 'yellow' => '255,255,0', + 'yellowgreen' => '154,205,50' + ); +} + +// responsible for taking a string of LESS code and converting it into a +// syntax tree +class lessc_parser { + static protected $nextBlockId = 0; // used to uniquely identify blocks + + static protected $precedence = array( + '=<' => 0, + '>=' => 0, + '=' => 0, + '<' => 0, + '>' => 0, + + '+' => 1, + '-' => 1, + '*' => 2, + '/' => 2, + '%' => 2, + ); + + static protected $whitePattern; + static protected $commentMulti; + + static protected $commentSingle = "//"; + static protected $commentMultiLeft = "/*"; + static protected $commentMultiRight = "*/"; + + // regex string to match any of the operators + static protected $operatorString; + + // these properties will supress division unless it's inside parenthases + static protected $supressDivisionProps = + array('/border-radius$/i', '/^font$/i'); + + protected $blockDirectives = array("font-face", "keyframes", "page", "-moz-document", "viewport", "-moz-viewport", "-o-viewport", "-ms-viewport"); + protected $lineDirectives = array("charset"); + + /** + * if we are in parens we can be more liberal with whitespace around + * operators because it must evaluate to a single value and thus is less + * ambiguous. + * + * Consider: + * property1: 10 -5; // is two numbers, 10 and -5 + * property2: (10 -5); // should evaluate to 5 + */ + protected $inParens = false; + + // caches preg escaped literals + static protected $literalCache = array(); + + public function __construct($lessc, $sourceName = null) { + $this->eatWhiteDefault = true; + // reference to less needed for vPrefix, mPrefix, and parentSelector + $this->lessc = $lessc; + + $this->sourceName = $sourceName; // name used for error messages + + $this->writeComments = false; + + if (!self::$operatorString) { + self::$operatorString = + '('.implode('|', array_map(array('lessc', 'preg_quote'), + array_keys(self::$precedence))).')'; + + $commentSingle = lessc::preg_quote(self::$commentSingle); + $commentMultiLeft = lessc::preg_quote(self::$commentMultiLeft); + $commentMultiRight = lessc::preg_quote(self::$commentMultiRight); + + self::$commentMulti = $commentMultiLeft.'.*?'.$commentMultiRight; + self::$whitePattern = '/'.$commentSingle.'[^\n]*\s*|('.self::$commentMulti.')\s*|\s+/Ais'; + } + } + + public function parse($buffer) { + $this->count = 0; + $this->line = 1; + + $this->env = null; // block stack + $this->buffer = $this->writeComments ? $buffer : $this->removeComments($buffer); + $this->pushSpecialBlock("root"); + $this->eatWhiteDefault = true; + $this->seenComments = array(); + + // trim whitespace on head + // if (preg_match('/^\s+/', $this->buffer, $m)) { + // $this->line += substr_count($m[0], "\n"); + // $this->buffer = ltrim($this->buffer); + // } + $this->whitespace(); + + // parse the entire file + while (false !== $this->parseChunk()); + + if ($this->count != strlen($this->buffer)) + $this->throwError(); + + // TODO report where the block was opened + if ( !property_exists($this->env, 'parent') || !is_null($this->env->parent) ) + throw new exception('parse error: unclosed block'); + + return $this->env; + } + + /** + * Parse a single chunk off the head of the buffer and append it to the + * current parse environment. + * Returns false when the buffer is empty, or when there is an error. + * + * This function is called repeatedly until the entire document is + * parsed. + * + * This parser is most similar to a recursive descent parser. Single + * functions represent discrete grammatical rules for the language, and + * they are able to capture the text that represents those rules. + * + * Consider the function lessc::keyword(). (all parse functions are + * structured the same) + * + * The function takes a single reference argument. When calling the + * function it will attempt to match a keyword on the head of the buffer. + * If it is successful, it will place the keyword in the referenced + * argument, advance the position in the buffer, and return true. If it + * fails then it won't advance the buffer and it will return false. + * + * All of these parse functions are powered by lessc::match(), which behaves + * the same way, but takes a literal regular expression. Sometimes it is + * more convenient to use match instead of creating a new function. + * + * Because of the format of the functions, to parse an entire string of + * grammatical rules, you can chain them together using &&. + * + * But, if some of the rules in the chain succeed before one fails, then + * the buffer position will be left at an invalid state. In order to + * avoid this, lessc::seek() is used to remember and set buffer positions. + * + * Before parsing a chain, use $s = $this->seek() to remember the current + * position into $s. Then if a chain fails, use $this->seek($s) to + * go back where we started. + */ + protected function parseChunk() { + if (empty($this->buffer)) return false; + $s = $this->seek(); + + if ($this->whitespace()) { + return true; + } + + // setting a property + if ($this->keyword($key) && $this->assign() && + $this->propertyValue($value, $key) && $this->end()) + { + $this->append(array('assign', $key, $value), $s); + return true; + } else { + $this->seek($s); + } + + + // look for special css blocks + if ($this->literal('@', false)) { + $this->count--; + + // media + if ($this->literal('@media')) { + if (($this->mediaQueryList($mediaQueries) || true) + && $this->literal('{')) + { + $media = $this->pushSpecialBlock("media"); + $media->queries = is_null($mediaQueries) ? array() : $mediaQueries; + return true; + } else { + $this->seek($s); + return false; + } + } + + if ($this->literal("@", false) && $this->keyword($dirName)) { + if ($this->isDirective($dirName, $this->blockDirectives)) { + if (($this->openString("{", $dirValue, null, array(";")) || true) && + $this->literal("{")) + { + $dir = $this->pushSpecialBlock("directive"); + $dir->name = $dirName; + if (isset($dirValue)) $dir->value = $dirValue; + return true; + } + } elseif ($this->isDirective($dirName, $this->lineDirectives)) { + if ($this->propertyValue($dirValue) && $this->end()) { + $this->append(array("directive", $dirName, $dirValue)); + return true; + } + } + } + + $this->seek($s); + } + + // setting a variable + if ($this->variable($var) && $this->assign() && + $this->propertyValue($value) && $this->end()) + { + $this->append(array('assign', $var, $value), $s); + return true; + } else { + $this->seek($s); + } + + if ($this->import($importValue)) { + $this->append($importValue, $s); + return true; + } + + // opening parametric mixin + if ($this->tag($tag, true) && $this->argumentDef($args, $isVararg) && + ($this->guards($guards) || true) && + $this->literal('{')) + { + $block = $this->pushBlock($this->fixTags(array($tag))); + $block->args = $args; + $block->isVararg = $isVararg; + if (!empty($guards)) $block->guards = $guards; + return true; + } else { + $this->seek($s); + } + + // opening a simple block + if ($this->tags($tags) && $this->literal('{', false)) { + $tags = $this->fixTags($tags); + $this->pushBlock($tags); + return true; + } else { + $this->seek($s); + } + + // closing a block + if ($this->literal('}', false)) { + try { + $block = $this->pop(); + } catch (exception $e) { + $this->seek($s); + $this->throwError($e->getMessage()); + } + + $hidden = false; + if (is_null($block->type)) { + $hidden = true; + if (!isset($block->args)) { + foreach ($block->tags as $tag) { + if (!is_string($tag) || $tag{0} != $this->lessc->mPrefix) { + $hidden = false; + break; + } + } + } + + foreach ($block->tags as $tag) { + if (is_string($tag)) { + $this->env->children[$tag][] = $block; + } + } + } + + if (!$hidden) { + $this->append(array('block', $block), $s); + } + + // this is done here so comments aren't bundled into he block that + // was just closed + $this->whitespace(); + return true; + } + + // mixin + if ($this->mixinTags($tags) && + ($this->argumentDef($argv, $isVararg) || true) && + ($this->keyword($suffix) || true) && $this->end()) + { + $tags = $this->fixTags($tags); + $this->append(array('mixin', $tags, $argv, $suffix), $s); + return true; + } else { + $this->seek($s); + } + + // spare ; + if ($this->literal(';')) return true; + + return false; // got nothing, throw error + } + + protected function isDirective($dirname, $directives) { + // TODO: cache pattern in parser + $pattern = implode("|", + array_map(array("lessc", "preg_quote"), $directives)); + $pattern = '/^(-[a-z-]+-)?(' . $pattern . ')$/i'; + + return preg_match($pattern, $dirname); + } + + protected function fixTags($tags) { + // move @ tags out of variable namespace + foreach ($tags as &$tag) { + if ($tag{0} == $this->lessc->vPrefix) + $tag[0] = $this->lessc->mPrefix; + } + return $tags; + } + + // a list of expressions + protected function expressionList(&$exps) { + $values = array(); + + while ($this->expression($exp)) { + $values[] = $exp; + } + + if (count($values) == 0) return false; + + $exps = lessc::compressList($values, ' '); + return true; + } + + /** + * Attempt to consume an expression. + * @link http://en.wikipedia.org/wiki/Operator-precedence_parser#Pseudo-code + */ + protected function expression(&$out) { + if ($this->value($lhs)) { + $out = $this->expHelper($lhs, 0); + + // look for / shorthand + if (!empty($this->env->supressedDivision)) { + unset($this->env->supressedDivision); + $s = $this->seek(); + if ($this->literal("/") && $this->value($rhs)) { + $out = array("list", "", + array($out, array("keyword", "/"), $rhs)); + } else { + $this->seek($s); + } + } + + return true; + } + return false; + } + + /** + * recursively parse infix equation with $lhs at precedence $minP + */ + protected function expHelper($lhs, $minP) { + $this->inExp = true; + $ss = $this->seek(); + + while (true) { + $whiteBefore = isset($this->buffer[$this->count - 1]) && + ctype_space($this->buffer[$this->count - 1]); + + // If there is whitespace before the operator, then we require + // whitespace after the operator for it to be an expression + $needWhite = $whiteBefore && !$this->inParens; + + if ($this->match(self::$operatorString.($needWhite ? '\s' : ''), $m) && self::$precedence[$m[1]] >= $minP) { + if (!$this->inParens && isset($this->env->currentProperty) && $m[1] == "/" && empty($this->env->supressedDivision)) { + foreach (self::$supressDivisionProps as $pattern) { + if (preg_match($pattern, $this->env->currentProperty)) { + $this->env->supressedDivision = true; + break 2; + } + } + } + + + $whiteAfter = isset($this->buffer[$this->count - 1]) && + ctype_space($this->buffer[$this->count - 1]); + + if (!$this->value($rhs)) break; + + // peek for next operator to see what to do with rhs + if ($this->peek(self::$operatorString, $next) && self::$precedence[$next[1]] > self::$precedence[$m[1]]) { + $rhs = $this->expHelper($rhs, self::$precedence[$next[1]]); + } + + $lhs = array('expression', $m[1], $lhs, $rhs, $whiteBefore, $whiteAfter); + $ss = $this->seek(); + + continue; + } + + break; + } + + $this->seek($ss); + + return $lhs; + } + + // consume a list of values for a property + public function propertyValue(&$value, $keyName = null) { + $values = array(); + + if ($keyName !== null) $this->env->currentProperty = $keyName; + + $s = null; + while ($this->expressionList($v)) { + $values[] = $v; + $s = $this->seek(); + if (!$this->literal(',')) break; + } + + if ($s) $this->seek($s); + + if ($keyName !== null) unset($this->env->currentProperty); + + if (count($values) == 0) return false; + + $value = lessc::compressList($values, ', '); + return true; + } + + protected function parenValue(&$out) { + $s = $this->seek(); + + // speed shortcut + if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "(") { + return false; + } + + $inParens = $this->inParens; + if ($this->literal("(") && + ($this->inParens = true) && $this->expression($exp) && + $this->literal(")")) + { + $out = $exp; + $this->inParens = $inParens; + return true; + } else { + $this->inParens = $inParens; + $this->seek($s); + } + + return false; + } + + // a single value + protected function value(&$value) { + $s = $this->seek(); + + // speed shortcut + if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "-") { + // negation + if ($this->literal("-", false) && + (($this->variable($inner) && $inner = array("variable", $inner)) || + $this->unit($inner) || + $this->parenValue($inner))) + { + $value = array("unary", "-", $inner); + return true; + } else { + $this->seek($s); + } + } + + if ($this->parenValue($value)) return true; + if ($this->unit($value)) return true; + if ($this->color($value)) return true; + if ($this->func($value)) return true; + if ($this->string($value)) return true; + + if ($this->keyword($word)) { + $value = array('keyword', $word); + return true; + } + + // try a variable + if ($this->variable($var)) { + $value = array('variable', $var); + return true; + } + + // unquote string (should this work on any type? + if ($this->literal("~") && $this->string($str)) { + $value = array("escape", $str); + return true; + } else { + $this->seek($s); + } + + // css hack: \0 + if ($this->literal('\\') && $this->match('([0-9]+)', $m)) { + $value = array('keyword', '\\'.$m[1]); + return true; + } else { + $this->seek($s); + } + + return false; + } + + // an import statement + protected function import(&$out) { + if (!$this->literal('@import')) return false; + + // @import "something.css" media; + // @import url("something.css") media; + // @import url(something.css) media; + + if ($this->propertyValue($value)) { + $out = array("import", $value); + return true; + } + } + + protected function mediaQueryList(&$out) { + if ($this->genericList($list, "mediaQuery", ",", false)) { + $out = $list[2]; + return true; + } + return false; + } + + protected function mediaQuery(&$out) { + $s = $this->seek(); + + $expressions = null; + $parts = array(); + + if (($this->literal("only") && ($only = true) || $this->literal("not") && ($not = true) || true) && $this->keyword($mediaType)) { + $prop = array("mediaType"); + if (isset($only)) $prop[] = "only"; + if (isset($not)) $prop[] = "not"; + $prop[] = $mediaType; + $parts[] = $prop; + } else { + $this->seek($s); + } + + + if (!empty($mediaType) && !$this->literal("and")) { + // ~ + } else { + $this->genericList($expressions, "mediaExpression", "and", false); + if (is_array($expressions)) $parts = array_merge($parts, $expressions[2]); + } + + if (count($parts) == 0) { + $this->seek($s); + return false; + } + + $out = $parts; + return true; + } + + protected function mediaExpression(&$out) { + $s = $this->seek(); + $value = null; + if ($this->literal("(") && + $this->keyword($feature) && + ($this->literal(":") && $this->expression($value) || true) && + $this->literal(")")) + { + $out = array("mediaExp", $feature); + if ($value) $out[] = $value; + return true; + } elseif ($this->variable($variable)) { + $out = array('variable', $variable); + return true; + } + + $this->seek($s); + return false; + } + + // an unbounded string stopped by $end + protected function openString($end, &$out, $nestingOpen=null, $rejectStrs = null) { + $oldWhite = $this->eatWhiteDefault; + $this->eatWhiteDefault = false; + + $stop = array("'", '"', "@{", $end); + $stop = array_map(array("lessc", "preg_quote"), $stop); + // $stop[] = self::$commentMulti; + + if (!is_null($rejectStrs)) { + $stop = array_merge($stop, $rejectStrs); + } + + $patt = '(.*?)('.implode("|", $stop).')'; + + $nestingLevel = 0; + + $content = array(); + while ($this->match($patt, $m, false)) { + if (!empty($m[1])) { + $content[] = $m[1]; + if ($nestingOpen) { + $nestingLevel += substr_count($m[1], $nestingOpen); + } + } + + $tok = $m[2]; + + $this->count-= strlen($tok); + if ($tok == $end) { + if ($nestingLevel == 0) { + break; + } else { + $nestingLevel--; + } + } + + if (($tok == "'" || $tok == '"') && $this->string($str)) { + $content[] = $str; + continue; + } + + if ($tok == "@{" && $this->interpolation($inter)) { + $content[] = $inter; + continue; + } + + if (!empty($rejectStrs) && in_array($tok, $rejectStrs)) { + break; + } + + $content[] = $tok; + $this->count+= strlen($tok); + } + + $this->eatWhiteDefault = $oldWhite; + + if (count($content) == 0) return false; + + // trim the end + if (is_string(end($content))) { + $content[count($content) - 1] = rtrim(end($content)); + } + + $out = array("string", "", $content); + return true; + } + + protected function string(&$out) { + $s = $this->seek(); + if ($this->literal('"', false)) { + $delim = '"'; + } elseif ($this->literal("'", false)) { + $delim = "'"; + } else { + return false; + } + + $content = array(); + + // look for either ending delim , escape, or string interpolation + $patt = '([^\n]*?)(@\{|\\\\|' . + lessc::preg_quote($delim).')'; + + $oldWhite = $this->eatWhiteDefault; + $this->eatWhiteDefault = false; + + while ($this->match($patt, $m, false)) { + $content[] = $m[1]; + if ($m[2] == "@{") { + $this->count -= strlen($m[2]); + if ($this->interpolation($inter, false)) { + $content[] = $inter; + } else { + $this->count += strlen($m[2]); + $content[] = "@{"; // ignore it + } + } elseif ($m[2] == '\\') { + $content[] = $m[2]; + if ($this->literal($delim, false)) { + $content[] = $delim; + } + } else { + $this->count -= strlen($delim); + break; // delim + } + } + + $this->eatWhiteDefault = $oldWhite; + + if ($this->literal($delim)) { + $out = array("string", $delim, $content); + return true; + } + + $this->seek($s); + return false; + } + + protected function interpolation(&$out) { + $oldWhite = $this->eatWhiteDefault; + $this->eatWhiteDefault = true; + + $s = $this->seek(); + if ($this->literal("@{") && + $this->openString("}", $interp, null, array("'", '"', ";")) && + $this->literal("}", false)) + { + $out = array("interpolate", $interp); + $this->eatWhiteDefault = $oldWhite; + if ($this->eatWhiteDefault) $this->whitespace(); + return true; + } + + $this->eatWhiteDefault = $oldWhite; + $this->seek($s); + return false; + } + + protected function unit(&$unit) { + // speed shortcut + if (isset($this->buffer[$this->count])) { + $char = $this->buffer[$this->count]; + if (!ctype_digit($char) && $char != ".") return false; + } + + if ($this->match('([0-9]+(?:\.[0-9]*)?|\.[0-9]+)([%a-zA-Z]+)?', $m)) { + $unit = array("number", $m[1], empty($m[2]) ? "" : $m[2]); + return true; + } + return false; + } + + // a # color + protected function color(&$out) { + if ($this->match('(#(?:[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{3}))', $m)) { + if (strlen($m[1]) > 7) { + $out = array("string", "", array($m[1])); + } else { + $out = array("raw_color", $m[1]); + } + return true; + } + + return false; + } + + // consume an argument definition list surrounded by () + // each argument is a variable name with optional value + // or at the end a ... or a variable named followed by ... + // arguments are separated by , unless a ; is in the list, then ; is the + // delimiter. + protected function argumentDef(&$args, &$isVararg) { + $s = $this->seek(); + if (!$this->literal('(')) return false; + + $values = array(); + $delim = ","; + $method = "expressionList"; + + $isVararg = false; + while (true) { + if ($this->literal("...")) { + $isVararg = true; + break; + } + + if ($this->$method($value)) { + if ($value[0] == "variable") { + $arg = array("arg", $value[1]); + $ss = $this->seek(); + + if ($this->assign() && $this->$method($rhs)) { + $arg[] = $rhs; + } else { + $this->seek($ss); + if ($this->literal("...")) { + $arg[0] = "rest"; + $isVararg = true; + } + } + + $values[] = $arg; + if ($isVararg) break; + continue; + } else { + $values[] = array("lit", $value); + } + } + + + if (!$this->literal($delim)) { + if ($delim == "," && $this->literal(";")) { + // found new delim, convert existing args + $delim = ";"; + $method = "propertyValue"; + + // transform arg list + if (isset($values[1])) { // 2 items + $newList = array(); + foreach ($values as $i => $arg) { + switch($arg[0]) { + case "arg": + if ($i) { + $this->throwError("Cannot mix ; and , as delimiter types"); + } + $newList[] = $arg[2]; + break; + case "lit": + $newList[] = $arg[1]; + break; + case "rest": + $this->throwError("Unexpected rest before semicolon"); + } + } + + $newList = array("list", ", ", $newList); + + switch ($values[0][0]) { + case "arg": + $newArg = array("arg", $values[0][1], $newList); + break; + case "lit": + $newArg = array("lit", $newList); + break; + } + + } elseif ($values) { // 1 item + $newArg = $values[0]; + } + + if ($newArg) { + $values = array($newArg); + } + } else { + break; + } + } + } + + if (!$this->literal(')')) { + $this->seek($s); + return false; + } + + $args = $values; + + return true; + } + + // consume a list of tags + // this accepts a hanging delimiter + protected function tags(&$tags, $simple = false, $delim = ',') { + $tags = array(); + while ($this->tag($tt, $simple)) { + $tags[] = $tt; + if (!$this->literal($delim)) break; + } + if (count($tags) == 0) return false; + + return true; + } + + // list of tags of specifying mixin path + // optionally separated by > (lazy, accepts extra >) + protected function mixinTags(&$tags) { + $tags = array(); + while ($this->tag($tt, true)) { + $tags[] = $tt; + $this->literal(">"); + } + + if (count($tags) == 0) return false; + + return true; + } + + // a bracketed value (contained within in a tag definition) + protected function tagBracket(&$parts, &$hasExpression) { + // speed shortcut + if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] != "[") { + return false; + } + + $s = $this->seek(); + + $hasInterpolation = false; + + if ($this->literal("[", false)) { + $attrParts = array("["); + // keyword, string, operator + while (true) { + if ($this->literal("]", false)) { + $this->count--; + break; // get out early + } + + if ($this->match('\s+', $m)) { + $attrParts[] = " "; + continue; + } + if ($this->string($str)) { + // escape parent selector, (yuck) + foreach ($str[2] as &$chunk) { + $chunk = str_replace($this->lessc->parentSelector, "$&$", $chunk); + } + + $attrParts[] = $str; + $hasInterpolation = true; + continue; + } + + if ($this->keyword($word)) { + $attrParts[] = $word; + continue; + } + + if ($this->interpolation($inter, false)) { + $attrParts[] = $inter; + $hasInterpolation = true; + continue; + } + + // operator, handles attr namespace too + if ($this->match('[|-~\$\*\^=]+', $m)) { + $attrParts[] = $m[0]; + continue; + } + + break; + } + + if ($this->literal("]", false)) { + $attrParts[] = "]"; + foreach ($attrParts as $part) { + $parts[] = $part; + } + $hasExpression = $hasExpression || $hasInterpolation; + return true; + } + $this->seek($s); + } + + $this->seek($s); + return false; + } + + // a space separated list of selectors + protected function tag(&$tag, $simple = false) { + if ($simple) + $chars = '^@,:;{}\][>\(\) "\''; + else + $chars = '^@,;{}["\''; + + $s = $this->seek(); + + $hasExpression = false; + $parts = array(); + while ($this->tagBracket($parts, $hasExpression)); + + $oldWhite = $this->eatWhiteDefault; + $this->eatWhiteDefault = false; + + while (true) { + if ($this->match('(['.$chars.'0-9]['.$chars.']*)', $m)) { + $parts[] = $m[1]; + if ($simple) break; + + while ($this->tagBracket($parts, $hasExpression)); + continue; + } + + if (isset($this->buffer[$this->count]) && $this->buffer[$this->count] == "@") { + if ($this->interpolation($interp)) { + $hasExpression = true; + $interp[2] = true; // don't unescape + $parts[] = $interp; + continue; + } + + if ($this->literal("@")) { + $parts[] = "@"; + continue; + } + } + + if ($this->unit($unit)) { // for keyframes + $parts[] = $unit[1]; + $parts[] = $unit[2]; + continue; + } + + break; + } + + $this->eatWhiteDefault = $oldWhite; + if (!$parts) { + $this->seek($s); + return false; + } + + if ($hasExpression) { + $tag = array("exp", array("string", "", $parts)); + } else { + $tag = trim(implode($parts)); + } + + $this->whitespace(); + return true; + } + + // a css function + protected function func(&$func) { + $s = $this->seek(); + + if ($this->match('(%|[\w\-_][\w\-_:\.]+|[\w_])', $m) && $this->literal('(')) { + $fname = $m[1]; + + $sPreArgs = $this->seek(); + + $args = array(); + while (true) { + $ss = $this->seek(); + // this ugly nonsense is for ie filter properties + if ($this->keyword($name) && $this->literal('=') && $this->expressionList($value)) { + $args[] = array("string", "", array($name, "=", $value)); + } else { + $this->seek($ss); + if ($this->expressionList($value)) { + $args[] = $value; + } + } + + if (!$this->literal(',')) break; + } + $args = array('list', ',', $args); + + if ($this->literal(')')) { + $func = array('function', $fname, $args); + return true; + } elseif ($fname == 'url') { + // couldn't parse and in url? treat as string + $this->seek($sPreArgs); + if ($this->openString(")", $string) && $this->literal(")")) { + $func = array('function', $fname, $string); + return true; + } + } + } + + $this->seek($s); + return false; + } + + // consume a less variable + protected function variable(&$name) { + $s = $this->seek(); + if ($this->literal($this->lessc->vPrefix, false) && + ($this->variable($sub) || $this->keyword($name))) + { + if (!empty($sub)) { + $name = array('variable', $sub); + } else { + $name = $this->lessc->vPrefix.$name; + } + return true; + } + + $name = null; + $this->seek($s); + return false; + } + + /** + * Consume an assignment operator + * Can optionally take a name that will be set to the current property name + */ + protected function assign($name = null) { + if ($name) $this->currentProperty = $name; + return $this->literal(':') || $this->literal('='); + } + + // consume a keyword + protected function keyword(&$word) { + if ($this->match('([\w_\-\*!"][\w\-_"]*)', $m)) { + $word = $m[1]; + return true; + } + return false; + } + + // consume an end of statement delimiter + protected function end() { + if ($this->literal(';', false)) { + return true; + } elseif ($this->count == strlen($this->buffer) || $this->buffer[$this->count] == '}') { + // if there is end of file or a closing block next then we don't need a ; + return true; + } + return false; + } + + protected function guards(&$guards) { + $s = $this->seek(); + + if (!$this->literal("when")) { + $this->seek($s); + return false; + } + + $guards = array(); + + while ($this->guardGroup($g)) { + $guards[] = $g; + if (!$this->literal(",")) break; + } + + if (count($guards) == 0) { + $guards = null; + $this->seek($s); + return false; + } + + return true; + } + + // a bunch of guards that are and'd together + // TODO rename to guardGroup + protected function guardGroup(&$guardGroup) { + $s = $this->seek(); + $guardGroup = array(); + while ($this->guard($guard)) { + $guardGroup[] = $guard; + if (!$this->literal("and")) break; + } + + if (count($guardGroup) == 0) { + $guardGroup = null; + $this->seek($s); + return false; + } + + return true; + } + + protected function guard(&$guard) { + $s = $this->seek(); + $negate = $this->literal("not"); + + if ($this->literal("(") && $this->expression($exp) && $this->literal(")")) { + $guard = $exp; + if ($negate) $guard = array("negate", $guard); + return true; + } + + $this->seek($s); + return false; + } + + /* raw parsing functions */ + + protected function literal($what, $eatWhitespace = null) { + if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault; + + // shortcut on single letter + if (!isset($what[1]) && isset($this->buffer[$this->count])) { + if ($this->buffer[$this->count] == $what) { + if (!$eatWhitespace) { + $this->count++; + return true; + } + // goes below... + } else { + return false; + } + } + + if (!isset(self::$literalCache[$what])) { + self::$literalCache[$what] = lessc::preg_quote($what); + } + + return $this->match(self::$literalCache[$what], $m, $eatWhitespace); + } + + protected function genericList(&$out, $parseItem, $delim="", $flatten=true) { + $s = $this->seek(); + $items = array(); + while ($this->$parseItem($value)) { + $items[] = $value; + if ($delim) { + if (!$this->literal($delim)) break; + } + } + + if (count($items) == 0) { + $this->seek($s); + return false; + } + + if ($flatten && count($items) == 1) { + $out = $items[0]; + } else { + $out = array("list", $delim, $items); + } + + return true; + } + + + // advance counter to next occurrence of $what + // $until - don't include $what in advance + // $allowNewline, if string, will be used as valid char set + protected function to($what, &$out, $until = false, $allowNewline = false) { + if (is_string($allowNewline)) { + $validChars = $allowNewline; + } else { + $validChars = $allowNewline ? "." : "[^\n]"; + } + if (!$this->match('('.$validChars.'*?)'.lessc::preg_quote($what), $m, !$until)) return false; + if ($until) $this->count -= strlen($what); // give back $what + $out = $m[1]; + return true; + } + + // try to match something on head of buffer + protected function match($regex, &$out, $eatWhitespace = null) { + if ($eatWhitespace === null) $eatWhitespace = $this->eatWhiteDefault; + + $r = '/'.$regex.($eatWhitespace && !$this->writeComments ? '\s*' : '').'/Ais'; + if (preg_match($r, $this->buffer, $out, null, $this->count)) { + $this->count += strlen($out[0]); + if ($eatWhitespace && $this->writeComments) $this->whitespace(); + return true; + } + return false; + } + + // match some whitespace + protected function whitespace() { + if ($this->writeComments) { + $gotWhite = false; + while (preg_match(self::$whitePattern, $this->buffer, $m, null, $this->count)) { + if (isset($m[1]) && empty($this->seenComments[$this->count])) { + $this->append(array("comment", $m[1])); + $this->seenComments[$this->count] = true; + } + $this->count += strlen($m[0]); + $gotWhite = true; + } + return $gotWhite; + } else { + $this->match("", $m); + return strlen($m[0]) > 0; + } + } + + // match something without consuming it + protected function peek($regex, &$out = null, $from=null) { + if (is_null($from)) $from = $this->count; + $r = '/'.$regex.'/Ais'; + $result = preg_match($r, $this->buffer, $out, null, $from); + + return $result; + } + + // seek to a spot in the buffer or return where we are on no argument + protected function seek($where = null) { + if ($where === null) return $this->count; + else $this->count = $where; + return true; + } + + /* misc functions */ + + public function throwError($msg = "parse error", $count = null) { + $count = is_null($count) ? $this->count : $count; + + $line = $this->line + + substr_count(substr($this->buffer, 0, $count), "\n"); + + if (!empty($this->sourceName)) { + $loc = "$this->sourceName on line $line"; + } else { + $loc = "line: $line"; + } + + // TODO this depends on $this->count + if ($this->peek("(.*?)(\n|$)", $m, $count)) { + throw new exception("$msg: failed at `$m[1]` $loc"); + } else { + throw new exception("$msg: $loc"); + } + } + + protected function pushBlock($selectors=null, $type=null) { + $b = new stdclass; + $b->parent = $this->env; + + $b->type = $type; + $b->id = self::$nextBlockId++; + + $b->isVararg = false; // TODO: kill me from here + $b->tags = $selectors; + + $b->props = array(); + $b->children = array(); + + $this->env = $b; + return $b; + } + + // push a block that doesn't multiply tags + protected function pushSpecialBlock($type) { + return $this->pushBlock(null, $type); + } + + // append a property to the current block + protected function append($prop, $pos = null) { + if ($pos !== null) $prop[-1] = $pos; + $this->env->props[] = $prop; + } + + // pop something off the stack + protected function pop() { + $old = $this->env; + $this->env = $this->env->parent; + return $old; + } + + // remove comments from $text + // todo: make it work for all functions, not just url + protected function removeComments($text) { + $look = array( + 'url(', '//', '/*', '"', "'" + ); + + $out = ''; + $min = null; + while (true) { + // find the next item + foreach ($look as $token) { + $pos = strpos($text, $token); + if ($pos !== false) { + if (!isset($min) || $pos < $min[1]) $min = array($token, $pos); + } + } + + if (is_null($min)) break; + + $count = $min[1]; + $skip = 0; + $newlines = 0; + switch ($min[0]) { + case 'url(': + if (preg_match('/url\(.*?\)/', $text, $m, 0, $count)) + $count += strlen($m[0]) - strlen($min[0]); + break; + case '"': + case "'": + if (preg_match('/'.$min[0].'.*?(?<!\\\\)'.$min[0].'/', $text, $m, 0, $count)) + $count += strlen($m[0]) - 1; + break; + case '//': + $skip = strpos($text, "\n", $count); + if ($skip === false) $skip = strlen($text) - $count; + else $skip -= $count; + break; + case '/*': + if (preg_match('/\/\*.*?\*\//s', $text, $m, 0, $count)) { + $skip = strlen($m[0]); + $newlines = substr_count($m[0], "\n"); + } + break; + } + + if ($skip == 0) $count += strlen($min[0]); + + $out .= substr($text, 0, $count).str_repeat("\n", $newlines); + $text = substr($text, $count + $skip); + + $min = null; + } + + return $out.$text; + } + +} + +class lessc_formatter_classic { + public $indentChar = " "; + + public $break = "\n"; + public $open = " {"; + public $close = "}"; + public $selectorSeparator = ", "; + public $assignSeparator = ":"; + + public $openSingle = " { "; + public $closeSingle = " }"; + + public $disableSingle = false; + public $breakSelectors = false; + + public $compressColors = false; + + public function __construct() { + $this->indentLevel = 0; + } + + public function indentStr($n = 0) { + return str_repeat($this->indentChar, max($this->indentLevel + $n, 0)); + } + + public function property($name, $value) { + return $name . $this->assignSeparator . $value . ";"; + } + + protected function isEmpty($block) { + if (empty($block->lines)) { + foreach ($block->children as $child) { + if (!$this->isEmpty($child)) return false; + } + + return true; + } + return false; + } + + public function block($block) { + if ($this->isEmpty($block)) return; + + $inner = $pre = $this->indentStr(); + + $isSingle = !$this->disableSingle && + is_null($block->type) && count($block->lines) == 1; + + if (!empty($block->selectors)) { + $this->indentLevel++; + + if ($this->breakSelectors) { + $selectorSeparator = $this->selectorSeparator . $this->break . $pre; + } else { + $selectorSeparator = $this->selectorSeparator; + } + + echo $pre . + implode($selectorSeparator, $block->selectors); + if ($isSingle) { + echo $this->openSingle; + $inner = ""; + } else { + echo $this->open . $this->break; + $inner = $this->indentStr(); + } + + } + + if (!empty($block->lines)) { + $glue = $this->break.$inner; + echo $inner . implode($glue, $block->lines); + if (!$isSingle && !empty($block->children)) { + echo $this->break; + } + } + + foreach ($block->children as $child) { + $this->block($child); + } + + if (!empty($block->selectors)) { + if (!$isSingle && empty($block->children)) echo $this->break; + + if ($isSingle) { + echo $this->closeSingle . $this->break; + } else { + echo $pre . $this->close . $this->break; + } + + $this->indentLevel--; + } + } +} + +class lessc_formatter_compressed extends lessc_formatter_classic { + public $disableSingle = true; + public $open = "{"; + public $selectorSeparator = ","; + public $assignSeparator = ":"; + public $break = ""; + public $compressColors = true; + + public function indentStr($n = 0) { + return ""; + } +} + +class lessc_formatter_lessjs extends lessc_formatter_classic { + public $disableSingle = true; + public $breakSelectors = true; + public $assignSeparator = ": "; + public $selectorSeparator = ","; +} + + diff --git a/src/core/libs/phpUnsharpMask/phpUnsharpMask.php b/src/core/libs/phpUnsharpMask/phpUnsharpMask.php new file mode 100644 index 0000000..3b348b6 --- /dev/null +++ b/src/core/libs/phpUnsharpMask/phpUnsharpMask.php @@ -0,0 +1,149 @@ +<?php +////////////////////////////////////////////////////////////// +//// +//// Unsharp Mask for PHP - version 2.1.1 +//// +//// Unsharp mask algorithm by Torstein Hønsi 2003-07. +//// thoensi_at_netcom_dot_no. +//// Please leave this notice. +//// +////////////////////////////////////////////////////////////// +// From: http://vikjavev.no/computing/ump.php // +// // +// Reformatted by James Heinrich <info@silisoftware.com> // +// for use in phpThumb() on 3 February 2003. // +// updated to v2.1.1 on 24 April 2011 // +// // +// phpThumb() is found at http://phpthumb.sourceforge.net // +// and/or https://github.com/JamesHeinrich/phpThumb // +////////////////////////////////////////////////////////////// + +/* +New: +- In version 2.1 (February 26 2007) Tom Bishop has done some important speed enhancements. +- From version 2 (July 17 2006) the script uses the imageconvolution function in PHP + version >= 5.1, which improves the performance considerably. + +Unsharp masking is a traditional darkroom technique that has proven very suitable for +digital imaging. The principle of unsharp masking is to create a blurred copy of the image +and compare it to the underlying original. The difference in colour values +between the two images is greatest for the pixels near sharp edges. When this +difference is subtracted from the original image, the edges will be +accentuated. + +The Amount parameter simply says how much of the effect you want. 100 is 'normal'. +Radius is the radius of the blurring circle of the mask. 'Threshold' is the least +difference in colour values that is allowed between the original and the mask. In practice +this means that low-contrast areas of the picture are left unrendered whereas edges +are treated normally. This is good for pictures of e.g. skin or blue skies. + +Any suggenstions for improvement of the algorithm, expecially regarding the speed +and the roundoff errors in the Gaussian blur process, are welcome. +*/ + +class phpUnsharpMask { + + static function applyUnsharpMask(&$img, $amount, $radius, $threshold) { + + // $img is an image that is already created within php using + // imgcreatetruecolor. No url! $img must be a truecolor image. + + // Attempt to calibrate the parameters to Photoshop: + $amount = min($amount, 500) * 0.016; + $radius = abs(round(min(50, $radius) * 2)); // Only integers make sense. + $threshold = min(255, $threshold); + if ($radius == 0) { + return true; + } + $w = ImageSX($img); + $h = ImageSY($img); + $imgCanvas = ImageCreateTrueColor($w, $h); + $imgBlur = ImageCreateTrueColor($w, $h); + + // Gaussian blur matrix: + // + // 1 2 1 + // 2 4 2 + // 1 2 1 + // + ////////////////////////////////////////////////// + + if (function_exists('imageconvolution')) { // PHP >= 5.1 + $matrix = array( + array(1, 2, 1), + array(2, 4, 2), + array(1, 2, 1) + ); + ImageCopy($imgBlur, $img, 0, 0, 0, 0, $w, $h); + ImageConvolution($imgBlur, $matrix, 16, 0); + + } else { + + // Move copies of the image around one pixel at the time and merge them with weight + // according to the matrix. The same matrix is simply repeated for higher radii. + for ($i = 0; $i < $radius; $i++) { + ImageCopy( $imgBlur, $img, 0, 0, 1, 0, $w - 1, $h); // left + ImageCopyMerge($imgBlur, $img, 1, 0, 0, 0, $w , $h, 50); // right + ImageCopyMerge($imgBlur, $img, 0, 0, 0, 0, $w , $h, 50); // center + ImageCopy( $imgCanvas, $imgBlur, 0, 0, 0, 0, $w , $h); + ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w , $h - 1, 33.33333); // up + ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 0, 0, $w , $h, 25); // down + } + } + + if ($threshold > 0){ + // Calculate the difference between the blurred pixels and the original + // and set the pixels + for ($x = 0; $x < $w-1; $x++) { // each row + for ($y = 0; $y < $h; $y++) { // each pixel + + $rgbOrig = ImageColorAt($img, $x, $y); + $rOrig = (($rgbOrig >> 16) & 0xFF); + $gOrig = (($rgbOrig >> 8) & 0xFF); + $bOrig = ($rgbOrig & 0xFF); + + $rgbBlur = ImageColorAt($imgBlur, $x, $y); + + $rBlur = (($rgbBlur >> 16) & 0xFF); + $gBlur = (($rgbBlur >> 8) & 0xFF); + $bBlur = ($rgbBlur & 0xFF); + + // When the masked pixels differ less from the original + // than the threshold specifies, they are set to their original value. + $rNew = ((abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig); + $gNew = ((abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig); + $bNew = ((abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig); + + if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) { + $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew); + ImageSetPixel($img, $x, $y, $pixCol); + } + } + } + } else { + for ($x = 0; $x < $w; $x++) { // each row + for ($y = 0; $y < $h; $y++) { // each pixel + $rgbOrig = ImageColorAt($img, $x, $y); + $rOrig = (($rgbOrig >> 16) & 0xFF); + $gOrig = (($rgbOrig >> 8) & 0xFF); + $bOrig = ($rgbOrig & 0xFF); + + $rgbBlur = ImageColorAt($imgBlur, $x, $y); + + $rBlur = (($rgbBlur >> 16) & 0xFF); + $gBlur = (($rgbBlur >> 8) & 0xFF); + $bBlur = ($rgbBlur & 0xFF); + + $rNew = min(255, max(0, ($amount * ($rOrig - $rBlur)) + $rOrig)); + $gNew = min(255, max(0, ($amount * ($gOrig - $gBlur)) + $gOrig)); + $bNew = min(255, max(0, ($amount * ($bOrig - $bBlur)) + $bOrig)); + $rgbNew = ($rNew << 16) + ($gNew <<8) + $bNew; + ImageSetPixel($img, $x, $y, $rgbNew); + } + } + } + ImageDestroy($imgCanvas); + ImageDestroy($imgBlur); + return true; + } +} diff --git a/src/core/libs/phpmailer/class.phpmailer.php b/src/core/libs/phpmailer/class.phpmailer.php new file mode 100755 index 0000000..a870451 --- /dev/null +++ b/src/core/libs/phpmailer/class.phpmailer.php @@ -0,0 +1,1921 @@ +<?php +/*~ class.phpmailer.php +.---------------------------------------------------------------------------. +| Software: PHPMailer - PHP email class | +| Version: 2.0.4 | +| Contact: via sourceforge.net support pages (also www.codeworxtech.com) | +| Info: http://phpmailer.sourceforge.net | +| Support: http://sourceforge.net/projects/phpmailer/ | +| ------------------------------------------------------------------------- | +| Author: Andy Prevost (project admininistrator) | +| Author: Brent R. Matzelle (original founder) | +| Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved. | +| Copyright (c) 2001-2003, Brent R. Matzelle | +| ------------------------------------------------------------------------- | +| License: Distributed under the Lesser General Public License (LGPL) | +| http://www.gnu.org/copyleft/lesser.html | +| This program is distributed in the hope that it will be useful - WITHOUT | +| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | +| FITNESS FOR A PARTICULAR PURPOSE. | +| ------------------------------------------------------------------------- | +| We offer a number of paid services (www.codeworxtech.com): | +| - Web Hosting on highly optimized fast and secure servers | +| - Technology Consulting | +| - Oursourcing (highly qualified programmers and graphic designers) | +'---------------------------------------------------------------------------' + */ +/** + * PHPMailer - PHP email transport class + * @package PHPMailer + * @author Andy Prevost + * @copyright 2004 - 2009 Andy Prevost + */ + +class PHPMailer { + + ///////////////////////////////////////////////// + // PROPERTIES, PUBLIC + ///////////////////////////////////////////////// + + /** + * Email priority (1 = High, 3 = Normal, 5 = low). + * @var int + */ + var $Priority = 3; + + /** + * Sets the CharSet of the message. + * @var string + */ + var $CharSet = 'iso-8859-1'; + + /** + * Sets the Content-type of the message. + * @var string + */ + var $ContentType = 'text/plain'; + + /** + * Sets the Encoding of the message. Options for this are "8bit", + * "7bit", "binary", "base64", and "quoted-printable". + * @var string + */ + var $Encoding = '8bit'; + + /** + * Holds the most recent mailer error message. + * @var string + */ + var $ErrorInfo = ''; + + /** + * Sets the From email address for the message. + * @var string + */ + var $From = 'root@localhost'; + + /** + * Sets the From name of the message. + * @var string + */ + var $FromName = 'Root User'; + + /** + * Sets the Sender email (Return-Path) of the message. If not empty, + * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. + * @var string + */ + var $Sender = ''; + + /** + * Sets the Subject of the message. + * @var string + */ + var $Subject = ''; + + /** + * Sets the Body of the message. This can be either an HTML or text body. + * If HTML then run IsHTML(true). + * @var string + */ + var $Body = ''; + + /** + * Sets the text-only body of the message. This automatically sets the + * email to multipart/alternative. This body can be read by mail + * clients that do not have HTML email capability such as mutt. Clients + * that can read HTML will view the normal Body. + * @var string + */ + var $AltBody = ''; + + /** + * Sets word wrapping on the body of the message to a given number of + * characters. + * @var int + */ + var $WordWrap = 0; + + /** + * Method to send mail: ("mail", "sendmail", or "smtp"). + * @var string + */ + var $Mailer = 'mail'; + + /** + * Sets the path of the sendmail program. + * @var string + */ + var $Sendmail = '/usr/sbin/sendmail'; + + /** + * Path to PHPMailer plugins. This is now only useful if the SMTP class + * is in a different directory than the PHP include path. + * @var string + */ + var $PluginDir = ''; + + /** + * Holds PHPMailer version. + * @var string + */ + var $Version = "2.0.4"; + + /** + * Sets the email address that a reading confirmation will be sent. + * @var string + */ + var $ConfirmReadingTo = ''; + + /** + * Sets the hostname to use in Message-Id and Received headers + * and as default HELO string. If empty, the value returned + * by SERVER_NAME is used or 'localhost.localdomain'. + * @var string + */ + var $Hostname = ''; + + /** + * Sets the message ID to be used in the Message-Id header. + * If empty, a unique id will be generated. + * @var string + */ + var $MessageID = ''; + + ///////////////////////////////////////////////// + // PROPERTIES FOR SMTP + ///////////////////////////////////////////////// + + /** + * Sets the SMTP hosts. All hosts must be separated by a + * semicolon. You can also specify a different port + * for each host by using this format: [hostname:port] + * (e.g. "smtp1.example.com:25;smtp2.example.com"). + * Hosts will be tried in order. + * @var string + */ + var $Host = 'localhost'; + + /** + * Sets the default SMTP server port. + * @var int + */ + var $Port = 25; + + /** + * Sets the SMTP HELO of the message (Default is $Hostname). + * @var string + */ + var $Helo = ''; + + /** + * Sets connection prefix. + * Options are "", "ssl" or "tls" + * @var string + */ + var $SMTPSecure = ""; + + /** + * Sets SMTP authentication. Utilizes the Username and Password variables. + * @var bool + */ + var $SMTPAuth = false; + + /** + * Sets SMTP username. + * @var string + */ + var $Username = ''; + + /** + * Sets SMTP password. + * @var string + */ + var $Password = ''; + + /** + * Sets the SMTP server timeout in seconds. This function will not + * work with the win32 version. + * @var int + */ + var $Timeout = 10; + + /** + * Sets SMTP class debugging on or off. + * @var bool + */ + var $SMTPDebug = false; + + /** + * Prevents the SMTP connection from being closed after each mail + * sending. If this is set to true then to close the connection + * requires an explicit call to SmtpClose(). + * @var bool + */ + var $SMTPKeepAlive = false; + + /** + * Provides the ability to have the TO field process individual + * emails, instead of sending to entire TO addresses + * @var bool + */ + var $SingleTo = false; + + ///////////////////////////////////////////////// + // PROPERTIES, PRIVATE + ///////////////////////////////////////////////// + + var $smtp = NULL; + var $to = array(); + var $cc = array(); + var $bcc = array(); + var $ReplyTo = array(); + var $attachment = array(); + var $CustomHeader = array(); + var $message_type = ''; + var $boundary = array(); + var $language = array(); + var $error_count = 0; + var $LE = "\n"; + var $sign_cert_file = ""; + var $sign_key_file = ""; + var $sign_key_pass = ""; + + ///////////////////////////////////////////////// + // METHODS, VARIABLES + ///////////////////////////////////////////////// + + /** + * Sets message type to HTML. + * @param bool $bool + * @return void + */ + function IsHTML($bool) { + if($bool == true) { + $this->ContentType = 'text/html'; + } else { + $this->ContentType = 'text/plain'; + } + } + + /** + * Sets Mailer to send message using SMTP. + * @return void + */ + function IsSMTP() { + $this->Mailer = 'smtp'; + } + + /** + * Sets Mailer to send message using PHP mail() function. + * @return void + */ + function IsMail() { + $this->Mailer = 'mail'; + } + + /** + * Sets Mailer to send message using the $Sendmail program. + * @return void + */ + function IsSendmail() { + $this->Mailer = 'sendmail'; + } + + /** + * Sets Mailer to send message using the qmail MTA. + * @return void + */ + function IsQmail() { + $this->Sendmail = '/var/qmail/bin/sendmail'; + $this->Mailer = 'sendmail'; + } + + ///////////////////////////////////////////////// + // METHODS, RECIPIENTS + ///////////////////////////////////////////////// + + /** + * Adds a "To" address. + * @param string $address + * @param string $name + * @return void + */ + function AddAddress($address, $name = '') { + $cur = count($this->to); + $this->to[$cur][0] = trim($address); + $this->to[$cur][1] = $name; + } + + /** + * Adds a "Cc" address. Note: this function works + * with the SMTP mailer on win32, not with the "mail" + * mailer. + * @param string $address + * @param string $name + * @return void + */ + function AddCC($address, $name = '') { + $cur = count($this->cc); + $this->cc[$cur][0] = trim($address); + $this->cc[$cur][1] = $name; + } + + /** + * Adds a "Bcc" address. Note: this function works + * with the SMTP mailer on win32, not with the "mail" + * mailer. + * @param string $address + * @param string $name + * @return void + */ + function AddBCC($address, $name = '') { + $cur = count($this->bcc); + $this->bcc[$cur][0] = trim($address); + $this->bcc[$cur][1] = $name; + } + + /** + * Adds a "Reply-To" address. + * @param string $address + * @param string $name + * @return void + */ + function AddReplyTo($address, $name = '') { + $cur = count($this->ReplyTo); + $this->ReplyTo[$cur][0] = trim($address); + $this->ReplyTo[$cur][1] = $name; + } + + ///////////////////////////////////////////////// + // METHODS, MAIL SENDING + ///////////////////////////////////////////////// + + /** + * Creates message and assigns Mailer. If the message is + * not sent successfully then it returns false. Use the ErrorInfo + * variable to view description of the error. + * @return bool + */ + function Send() { + $header = ''; + $body = ''; + $result = true; + + if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { + $this->SetError($this->Lang('provide_address')); + return false; + } + + /* Set whether the message is multipart/alternative */ + if(!empty($this->AltBody)) { + $this->ContentType = 'multipart/alternative'; + } + + $this->error_count = 0; // reset errors + $this->SetMessageType(); + $header .= $this->CreateHeader(); + $body = $this->CreateBody(); + + if($body == '') { + return false; + } + + /* Choose the mailer */ + switch($this->Mailer) { + case 'sendmail': + $result = $this->SendmailSend($header, $body); + break; + case 'smtp': + $result = $this->SmtpSend($header, $body); + break; + case 'mail': + $result = $this->MailSend($header, $body); + break; + default: + $result = $this->MailSend($header, $body); + break; + //$this->SetError($this->Mailer . $this->Lang('mailer_not_supported')); + //$result = false; + //break; + } + + return $result; + } + + /** + * Sends mail using the $Sendmail program. + * @access private + * @return bool + */ + function SendmailSend($header, $body) { + if ($this->Sender != '') { + $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); + } else { + $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); + } + + if(!@$mail = popen($sendmail, 'w')) { + $this->SetError($this->Lang('execute') . $this->Sendmail); + return false; + } + + fputs($mail, $header); + fputs($mail, $body); + + $result = pclose($mail); + if (version_compare(phpversion(), '4.2.3') == -1) { + $result = $result >> 8 & 0xFF; + } + if($result != 0) { + $this->SetError($this->Lang('execute') . $this->Sendmail); + return false; + } + return true; + } + + /** + * Sends mail using the PHP mail() function. + * @access private + * @return bool + */ + function MailSend($header, $body) { + + $to = ''; + for($i = 0; $i < count($this->to); $i++) { + if($i != 0) { $to .= ', '; } + $to .= $this->AddrFormat($this->to[$i]); + } + + $toArr = split(',', $to); + + $params = sprintf("-oi -f %s", $this->Sender); + if ($this->Sender != '' && strlen(ini_get('safe_mode')) < 1) { + $old_from = ini_get('sendmail_from'); + ini_set('sendmail_from', $this->Sender); + if ($this->SingleTo === true && count($toArr) > 1) { + foreach ($toArr as $key => $val) { + $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); + } + } else { + $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); + } + } else { + if ($this->SingleTo === true && count($toArr) > 1) { + foreach ($toArr as $key => $val) { + $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); + } + } else { + $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header); + } + } + + if (isset($old_from)) { + ini_set('sendmail_from', $old_from); + } + + if(!$rt) { + $this->SetError($this->Lang('instantiate')); + return false; + } + + return true; + } + + /** + * Sends mail via SMTP using PhpSMTP (Author: + * Chris Ryan). Returns bool. Returns false if there is a + * bad MAIL FROM, RCPT, or DATA input. + * @access private + * @return bool + */ + function SmtpSend($header, $body) { + include_once($this->PluginDir . 'class.smtp.php'); + $error = ''; + $bad_rcpt = array(); + + if(!$this->SmtpConnect()) { + return false; + } + + $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender; + if(!$this->smtp->Mail($smtp_from)) { + $error = $this->Lang('from_failed') . $smtp_from; + $this->SetError($error); + $this->smtp->Reset(); + return false; + } + + /* Attempt to send attach all recipients */ + for($i = 0; $i < count($this->to); $i++) { + if(!$this->smtp->Recipient($this->to[$i][0])) { + $bad_rcpt[] = $this->to[$i][0]; + } + } + for($i = 0; $i < count($this->cc); $i++) { + if(!$this->smtp->Recipient($this->cc[$i][0])) { + $bad_rcpt[] = $this->cc[$i][0]; + } + } + for($i = 0; $i < count($this->bcc); $i++) { + if(!$this->smtp->Recipient($this->bcc[$i][0])) { + $bad_rcpt[] = $this->bcc[$i][0]; + } + } + + if(count($bad_rcpt) > 0) { // Create error message + for($i = 0; $i < count($bad_rcpt); $i++) { + if($i != 0) { + $error .= ', '; + } + $error .= $bad_rcpt[$i]; + } + $error = $this->Lang('recipients_failed') . $error; + $this->SetError($error); + $this->smtp->Reset(); + return false; + } + + if(!$this->smtp->Data($header . $body)) { + $this->SetError($this->Lang('data_not_accepted')); + $this->smtp->Reset(); + return false; + } + if($this->SMTPKeepAlive == true) { + $this->smtp->Reset(); + } else { + $this->SmtpClose(); + } + + return true; + } + + /** + * Initiates a connection to an SMTP server. Returns false if the + * operation failed. + * @access private + * @return bool + */ + function SmtpConnect() { + if($this->smtp == NULL) { + $this->smtp = new SMTP(); + } + + $this->smtp->do_debug = $this->SMTPDebug; + $hosts = explode(';', $this->Host); + $index = 0; + $connection = ($this->smtp->Connected()); + + /* Retry while there is no connection */ + while($index < count($hosts) && $connection == false) { + $hostinfo = array(); + if(eregi('^(.+):([0-9]+)$', $hosts[$index], $hostinfo)) { + $host = $hostinfo[1]; + $port = $hostinfo[2]; + } else { + $host = $hosts[$index]; + $port = $this->Port; + } + + if($this->smtp->Connect(((!empty($this->SMTPSecure))?$this->SMTPSecure.'://':'').$host, $port, $this->Timeout)) { + if ($this->Helo != '') { + $this->smtp->Hello($this->Helo); + } else { + $this->smtp->Hello($this->ServerHostname()); + } + + $connection = true; + if($this->SMTPAuth) { + if(!$this->smtp->Authenticate($this->Username, $this->Password)) { + $this->SetError($this->Lang('authenticate')); + $this->smtp->Reset(); + $connection = false; + } + } + } + $index++; + } + if(!$connection) { + $this->SetError($this->Lang('connect_host')); + } + + return $connection; + } + + /** + * Closes the active SMTP session if one exists. + * @return void + */ + function SmtpClose() { + if($this->smtp != NULL) { + if($this->smtp->Connected()) { + $this->smtp->Quit(); + $this->smtp->Close(); + } + } + } + + /** + * Sets the language for all class error messages. Returns false + * if it cannot load the language file. The default language type + * is English. + * @param string $lang_type Type of language (e.g. Portuguese: "br") + * @param string $lang_path Path to the language file directory + * @access public + * @return bool + */ + function SetLanguage($lang_type, $lang_path = 'language/') { + if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php')) { + include($lang_path.'phpmailer.lang-'.$lang_type.'.php'); + } elseif (file_exists($lang_path.'phpmailer.lang-en.php')) { + include($lang_path.'phpmailer.lang-en.php'); + } else { + $PHPMAILER_LANG = array(); + $PHPMAILER_LANG["provide_address"] = 'You must provide at least one ' . + $PHPMAILER_LANG["mailer_not_supported"] = ' mailer is not supported.'; + $PHPMAILER_LANG["execute"] = 'Could not execute: '; + $PHPMAILER_LANG["instantiate"] = 'Could not instantiate mail function.'; + $PHPMAILER_LANG["authenticate"] = 'SMTP Error: Could not authenticate.'; + $PHPMAILER_LANG["from_failed"] = 'The following From address failed: '; + $PHPMAILER_LANG["recipients_failed"] = 'SMTP Error: The following ' . + $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Error: Data not accepted.'; + $PHPMAILER_LANG["connect_host"] = 'SMTP Error: Could not connect to SMTP host.'; + $PHPMAILER_LANG["file_access"] = 'Could not access file: '; + $PHPMAILER_LANG["file_open"] = 'File Error: Could not open file: '; + $PHPMAILER_LANG["encoding"] = 'Unknown encoding: '; + $PHPMAILER_LANG["signing"] = 'Signing Error: '; + } + $this->language = $PHPMAILER_LANG; + + return true; + } + + ///////////////////////////////////////////////// + // METHODS, MESSAGE CREATION + ///////////////////////////////////////////////// + + /** + * Creates recipient headers. + * @access private + * @return string + */ + function AddrAppend($type, $addr) { + $addr_str = $type . ': '; + $addr_str .= $this->AddrFormat($addr[0]); + if(count($addr) > 1) { + for($i = 1; $i < count($addr); $i++) { + $addr_str .= ', ' . $this->AddrFormat($addr[$i]); + } + } + $addr_str .= $this->LE; + + return $addr_str; + } + + /** + * Formats an address correctly. + * @access private + * @return string + */ + function AddrFormat($addr) { + if(empty($addr[1])) { + $formatted = $this->SecureHeader($addr[0]); + } else { + $formatted = $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">"; + } + + return $formatted; + } + + /** + * Wraps message for use with mailers that do not + * automatically perform wrapping and for quoted-printable. + * Original written by philippe. + * @access private + * @return string + */ + function WrapText($message, $length, $qp_mode = false) { + $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE; + // If utf-8 encoding is used, we will need to make sure we don't + // split multibyte characters when we wrap + $is_utf8 = (strtolower($this->CharSet) == "utf-8"); + + $message = $this->FixEOL($message); + if (substr($message, -1) == $this->LE) { + $message = substr($message, 0, -1); + } + + $line = explode($this->LE, $message); + $message = ''; + for ($i=0 ;$i < count($line); $i++) { + $line_part = explode(' ', $line[$i]); + $buf = ''; + for ($e = 0; $e<count($line_part); $e++) { + $word = $line_part[$e]; + if ($qp_mode and (strlen($word) > $length)) { + $space_left = $length - strlen($buf) - 1; + if ($e != 0) { + if ($space_left > 20) { + $len = $space_left; + if ($is_utf8) { + $len = $this->UTF8CharBoundary($word, $len); + } elseif (substr($word, $len - 1, 1) == "=") { + $len--; + } elseif (substr($word, $len - 2, 1) == "=") { + $len -= 2; + } + $part = substr($word, 0, $len); + $word = substr($word, $len); + $buf .= ' ' . $part; + $message .= $buf . sprintf("=%s", $this->LE); + } else { + $message .= $buf . $soft_break; + } + $buf = ''; + } + while (strlen($word) > 0) { + $len = $length; + if ($is_utf8) { + $len = $this->UTF8CharBoundary($word, $len); + } elseif (substr($word, $len - 1, 1) == "=") { + $len--; + } elseif (substr($word, $len - 2, 1) == "=") { + $len -= 2; + } + $part = substr($word, 0, $len); + $word = substr($word, $len); + + if (strlen($word) > 0) { + $message .= $part . sprintf("=%s", $this->LE); + } else { + $buf = $part; + } + } + } else { + $buf_o = $buf; + $buf .= ($e == 0) ? $word : (' ' . $word); + + if (strlen($buf) > $length and $buf_o != '') { + $message .= $buf_o . $soft_break; + $buf = $word; + } + } + } + $message .= $buf . $this->LE; + } + + return $message; + } + + /** + * Finds last character boundary prior to maxLength in a utf-8 + * quoted (printable) encoded string. + * Original written by Colin Brown. + * @access private + * @param string $encodedText utf-8 QP text + * @param int $maxLength find last character boundary prior to this length + * @return int + */ + function UTF8CharBoundary($encodedText, $maxLength) { + $foundSplitPos = false; + $lookBack = 3; + while (!$foundSplitPos) { + $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); + $encodedCharPos = strpos($lastChunk, "="); + if ($encodedCharPos !== false) { + // Found start of encoded character byte within $lookBack block. + // Check the encoded byte value (the 2 chars after the '=') + $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2); + $dec = hexdec($hex); + if ($dec < 128) { // Single byte character. + // If the encoded char was found at pos 0, it will fit + // otherwise reduce maxLength to start of the encoded char + $maxLength = ($encodedCharPos == 0) ? $maxLength : + $maxLength - ($lookBack - $encodedCharPos); + $foundSplitPos = true; + } elseif ($dec >= 192) { // First byte of a multi byte character + // Reduce maxLength to split at start of character + $maxLength = $maxLength - ($lookBack - $encodedCharPos); + $foundSplitPos = true; + } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back + $lookBack += 3; + } + } else { + // No encoded character found + $foundSplitPos = true; + } + } + return $maxLength; + } + + /** + * Set the body wrapping. + * @access private + * @return void + */ + function SetWordWrap() { + if($this->WordWrap < 1) { + return; + } + + switch($this->message_type) { + case 'alt': + /* fall through */ + case 'alt_attachments': + $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap); + break; + default: + $this->Body = $this->WrapText($this->Body, $this->WordWrap); + break; + } + } + + /** + * Assembles message header. + * @access private + * @return string + */ + function CreateHeader() { + $result = ''; + + /* Set the boundaries */ + $uniq_id = md5(uniqid(time())); + $this->boundary[1] = 'b1_' . $uniq_id; + $this->boundary[2] = 'b2_' . $uniq_id; + + $result .= $this->HeaderLine('Date', $this->RFCDate()); + if($this->Sender == '') { + $result .= $this->HeaderLine('Return-Path', trim($this->From)); + } else { + $result .= $this->HeaderLine('Return-Path', trim($this->Sender)); + } + + /* To be created automatically by mail() */ + if($this->Mailer != 'mail') { + if(count($this->to) > 0) { + $result .= $this->AddrAppend('To', $this->to); + } elseif (count($this->cc) == 0) { + $result .= $this->HeaderLine('To', 'undisclosed-recipients:;'); + } + } + + $from = array(); + $from[0][0] = trim($this->From); + $from[0][1] = $this->FromName; + $result .= $this->AddrAppend('From', $from); + + /* sendmail and mail() extract Cc from the header before sending */ + if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->cc) > 0)) { + $result .= $this->AddrAppend('Cc', $this->cc); + } + + /* sendmail and mail() extract Bcc from the header before sending */ + if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) { + $result .= $this->AddrAppend('Bcc', $this->bcc); + } + + if(count($this->ReplyTo) > 0) { + $result .= $this->AddrAppend('Reply-To', $this->ReplyTo); + } + + /* mail() sets the subject itself */ + if($this->Mailer != 'mail') { + $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject))); + } + + if($this->MessageID != '') { + $result .= $this->HeaderLine('Message-ID',$this->MessageID); + } else { + $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE); + } + $result .= $this->HeaderLine('X-Priority', $this->Priority); + $result .= $this->HeaderLine('X-Mailer', 'PHPMailer (phpmailer.sourceforge.net) [version ' . $this->Version . ']'); + + if($this->ConfirmReadingTo != '') { + $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>'); + } + + // Add custom headers + for($index = 0; $index < count($this->CustomHeader); $index++) { + $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1]))); + } + if (!$this->sign_key_file) { + $result .= $this->HeaderLine('MIME-Version', '1.0'); + $result .= $this->GetMailMIME(); + } + + return $result; + } + + /** + * Returns the message MIME. + * @access private + * @return string + */ + function GetMailMIME() { + $result = ''; + switch($this->message_type) { + case 'plain': + $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding); + $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet); + break; + case 'attachments': + /* fall through */ + case 'alt_attachments': + if($this->InlineImageExists()){ + $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE); + } else { + $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;'); + $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); + } + break; + case 'alt': + $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); + $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + } + + if($this->Mailer != 'mail') { + $result .= $this->LE.$this->LE; + } + + return $result; + } + + /** + * Assembles the message body. Returns an empty string on failure. + * @access private + * @return string + */ + function CreateBody() { + $result = ''; + if ($this->sign_key_file) { + $result .= $this->GetMailMIME(); + } + + $this->SetWordWrap(); + + switch($this->message_type) { + case 'alt': + $result .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); + $result .= $this->EncodeString($this->AltBody, $this->Encoding); + $result .= $this->LE.$this->LE; + $result .= $this->GetBoundary($this->boundary[1], '', 'text/html', ''); + $result .= $this->EncodeString($this->Body, $this->Encoding); + $result .= $this->LE.$this->LE; + $result .= $this->EndBoundary($this->boundary[1]); + break; + case 'plain': + $result .= $this->EncodeString($this->Body, $this->Encoding); + break; + case 'attachments': + $result .= $this->GetBoundary($this->boundary[1], '', '', ''); + $result .= $this->EncodeString($this->Body, $this->Encoding); + $result .= $this->LE; + $result .= $this->AttachAll(); + break; + case 'alt_attachments': + $result .= sprintf("--%s%s", $this->boundary[1], $this->LE); + $result .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE); + $result .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body + $result .= $this->EncodeString($this->AltBody, $this->Encoding); + $result .= $this->LE.$this->LE; + $result .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body + $result .= $this->EncodeString($this->Body, $this->Encoding); + $result .= $this->LE.$this->LE; + $result .= $this->EndBoundary($this->boundary[2]); + $result .= $this->AttachAll(); + break; + } + + if($this->IsError()) { + $result = ''; + } else if ($this->sign_key_file) { + $file = tempnam("", "mail"); + $fp = fopen($file, "w"); + fwrite($fp, $result); + fclose($fp); + $signed = tempnam("", "signed"); + + if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), null)) { + $fp = fopen($signed, "r"); + $result = fread($fp, filesize($this->sign_key_file)); + $result = ''; + while(!feof($fp)){ + $result = $result . fread($fp, 1024); + } + fclose($fp); + } else { + $this->SetError($this->Lang("signing").openssl_error_string()); + $result = ''; + } + + unlink($file); + unlink($signed); + } + + return $result; + } + + /** + * Returns the start of a message boundary. + * @access private + */ + function GetBoundary($boundary, $charSet, $contentType, $encoding) { + $result = ''; + if($charSet == '') { + $charSet = $this->CharSet; + } + if($contentType == '') { + $contentType = $this->ContentType; + } + if($encoding == '') { + $encoding = $this->Encoding; + } + $result .= $this->TextLine('--' . $boundary); + $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet); + $result .= $this->LE; + $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding); + $result .= $this->LE; + + return $result; + } + + /** + * Returns the end of a message boundary. + * @access private + */ + function EndBoundary($boundary) { + return $this->LE . '--' . $boundary . '--' . $this->LE; + } + + /** + * Sets the message type. + * @access private + * @return void + */ + function SetMessageType() { + if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) { + $this->message_type = 'plain'; + } else { + if(count($this->attachment) > 0) { + $this->message_type = 'attachments'; + } + if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) { + $this->message_type = 'alt'; + } + if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) { + $this->message_type = 'alt_attachments'; + } + } + } + + /* Returns a formatted header line. + * @access private + * @return string + */ + function HeaderLine($name, $value) { + return $name . ': ' . $value . $this->LE; + } + + /** + * Returns a formatted mail line. + * @access private + * @return string + */ + function TextLine($value) { + return $value . $this->LE; + } + + ///////////////////////////////////////////////// + // CLASS METHODS, ATTACHMENTS + ///////////////////////////////////////////////// + + /** + * Adds an attachment from a path on the filesystem. + * Returns false if the file could not be found + * or accessed. + * @param string $path Path to the attachment. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @return bool + */ + function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { + if(!@is_file($path)) { + $this->SetError($this->Lang('file_access') . $path); + return false; + } + + $filename = basename($path); + if($name == '') { + $name = $filename; + } + + $cur = count($this->attachment); + $this->attachment[$cur][0] = $path; + $this->attachment[$cur][1] = $filename; + $this->attachment[$cur][2] = $name; + $this->attachment[$cur][3] = $encoding; + $this->attachment[$cur][4] = $type; + $this->attachment[$cur][5] = false; // isStringAttachment + $this->attachment[$cur][6] = 'attachment'; + $this->attachment[$cur][7] = 0; + + return true; + } + + /** + * Attaches all fs, string, and binary attachments to the message. + * Returns an empty string on failure. + * @access private + * @return string + */ + function AttachAll() { + /* Return text of body */ + $mime = array(); + + /* Add all attachments */ + for($i = 0; $i < count($this->attachment); $i++) { + /* Check for string attachment */ + $bString = $this->attachment[$i][5]; + if ($bString) { + $string = $this->attachment[$i][0]; + } else { + $path = $this->attachment[$i][0]; + } + + $filename = $this->attachment[$i][1]; + $name = $this->attachment[$i][2]; + $encoding = $this->attachment[$i][3]; + $type = $this->attachment[$i][4]; + $disposition = $this->attachment[$i][6]; + $cid = $this->attachment[$i][7]; + + $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE); + $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE); + $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE); + + if($disposition == 'inline') { + $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); + } + + $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); + + /* Encode as string attachment */ + if($bString) { + $mime[] = $this->EncodeString($string, $encoding); + if($this->IsError()) { + return ''; + } + $mime[] = $this->LE.$this->LE; + } else { + $mime[] = $this->EncodeFile($path, $encoding); + if($this->IsError()) { + return ''; + } + $mime[] = $this->LE.$this->LE; + } + } + + $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE); + + return join('', $mime); + } + + /** + * Encodes attachment in requested format. Returns an + * empty string on failure. + * @access private + * @return string + */ + function EncodeFile ($path, $encoding = 'base64') { + if(!@$fd = fopen($path, 'rb')) { + $this->SetError($this->Lang('file_open') . $path); + return ''; + } + $magic_quotes = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + $file_buffer = fread($fd, filesize($path)); + $file_buffer = $this->EncodeString($file_buffer, $encoding); + fclose($fd); + set_magic_quotes_runtime($magic_quotes); + + return $file_buffer; + } + + /** + * Encodes string to requested format. Returns an + * empty string on failure. + * @access private + * @return string + */ + function EncodeString ($str, $encoding = 'base64') { + $encoded = ''; + switch(strtolower($encoding)) { + case 'base64': + /* chunk_split is found in PHP >= 3.0.6 */ + $encoded = chunk_split(base64_encode($str), 76, $this->LE); + break; + case '7bit': + case '8bit': + $encoded = $this->FixEOL($str); + if (substr($encoded, -(strlen($this->LE))) != $this->LE) + $encoded .= $this->LE; + break; + case 'binary': + $encoded = $str; + break; + case 'quoted-printable': + $encoded = $this->EncodeQP($str); + break; + default: + $this->SetError($this->Lang('encoding') . $encoding); + break; + } + return $encoded; + } + + /** + * Encode a header string to best of Q, B, quoted or none. + * @access private + * @return string + */ + function EncodeHeader ($str, $position = 'text') { + $x = 0; + + switch (strtolower($position)) { + case 'phrase': + if (!preg_match('/[\200-\377]/', $str)) { + /* Can't use addslashes as we don't know what value has magic_quotes_sybase. */ + $encoded = addcslashes($str, "\0..\37\177\\\""); + if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { + return ($encoded); + } else { + return ("\"$encoded\""); + } + } + $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); + break; + case 'comment': + $x = preg_match_all('/[()"]/', $str, $matches); + /* Fall-through */ + case 'text': + default: + $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); + break; + } + + if ($x == 0) { + return ($str); + } + + $maxlen = 75 - 7 - strlen($this->CharSet); + /* Try to select the encoding which should produce the shortest output */ + if (strlen($str)/3 < $x) { + $encoding = 'B'; + if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) { + // Use a custom function which correctly encodes and wraps long + // multibyte strings without breaking lines within a character + $encoded = $this->Base64EncodeWrapMB($str); + } else { + $encoded = base64_encode($str); + $maxlen -= $maxlen % 4; + $encoded = trim(chunk_split($encoded, $maxlen, "\n")); + } + } else { + $encoding = 'Q'; + $encoded = $this->EncodeQ($str, $position); + $encoded = $this->WrapText($encoded, $maxlen, true); + $encoded = str_replace('='.$this->LE, "\n", trim($encoded)); + } + + $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded); + $encoded = trim(str_replace("\n", $this->LE, $encoded)); + + return $encoded; + } + + /** + * Checks if a string contains multibyte characters. + * @access private + * @param string $str multi-byte text to wrap encode + * @return bool + */ + function HasMultiBytes($str) { + if (function_exists('mb_strlen')) { + return (strlen($str) > mb_strlen($str, $this->CharSet)); + } else { // Assume no multibytes (we can't handle without mbstring functions anyway) + return False; + } + } + + /** + * Correctly encodes and wraps long multibyte strings for mail headers + * without breaking lines within a character. + * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php + * @access private + * @param string $str multi-byte text to wrap encode + * @return string + */ + function Base64EncodeWrapMB($str) { + $start = "=?".$this->CharSet."?B?"; + $end = "?="; + $encoded = ""; + + $mb_length = mb_strlen($str, $this->CharSet); + // Each line must have length <= 75, including $start and $end + $length = 75 - strlen($start) - strlen($end); + // Average multi-byte ratio + $ratio = $mb_length / strlen($str); + // Base64 has a 4:3 ratio + $offset = $avgLength = floor($length * $ratio * .75); + + for ($i = 0; $i < $mb_length; $i += $offset) { + $lookBack = 0; + + do { + $offset = $avgLength - $lookBack; + $chunk = mb_substr($str, $i, $offset, $this->CharSet); + $chunk = base64_encode($chunk); + $lookBack++; + } + while (strlen($chunk) > $length); + + $encoded .= $chunk . $this->LE; + } + + // Chomp the last linefeed + $encoded = substr($encoded, 0, -strlen($this->LE)); + return $encoded; + } + + /** + * Encode string to quoted-printable. + * @access private + * @return string + */ + function EncodeQP( $input = '', $line_max = 76, $space_conv = false ) { + $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); + $lines = preg_split('/(?:\r\n|\r|\n)/', $input); + $eol = "\r\n"; + $escape = '='; + $output = ''; + while( list(, $line) = each($lines) ) { + $linlen = strlen($line); + $newline = ''; + for($i = 0; $i < $linlen; $i++) { + $c = substr( $line, $i, 1 ); + $dec = ord( $c ); + if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E + $c = '=2E'; + } + if ( $dec == 32 ) { + if ( $i == ( $linlen - 1 ) ) { // convert space at eol only + $c = '=20'; + } else if ( $space_conv ) { + $c = '=20'; + } + } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required + $h2 = floor($dec/16); + $h1 = floor($dec%16); + $c = $escape.$hex[$h2].$hex[$h1]; + } + if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted + $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay + $newline = ''; + // check if newline first character will be point or not + if ( $dec == 46 ) { + $c = '=2E'; + } + } + $newline .= $c; + } // end of for + $output .= $newline.$eol; + } // end of while + return $output; + } + + /** + * Callback for converting to "=XX". + * @access private + * @return string + */ + function EncodeQ_callback ($matches) { + return sprintf('=%02X', ord($matches[1])); + } + + /** + * Encode string to q encoding. + * @access private + * @return string + */ + function EncodeQ ($str, $position = 'text') { + /* There should not be any EOL in the string */ + $encoded = preg_replace("/[\r\n]/", '', $str); + + switch (strtolower($position)) { + case 'phrase': + $encoded = preg_replace_callback("/([^A-Za-z0-9!*+\/ -])/", + array('PHPMailer', 'EncodeQ_callback'), $encoded); + break; + case 'comment': + $encoded = preg_replace_callback("/([\(\)\"])/", + array('PHPMailer', 'EncodeQ_callback'), $encoded); + break; + case 'text': + default: + /* Replace every high ascii, control =, ? and _ characters */ + $encoded = preg_replace_callback('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/', + array('PHPMailer', 'EncodeQ_callback'), $encoded); + break; + } + + /* Replace every spaces to _ (more readable than =20) */ + $encoded = str_replace(' ', '_', $encoded); + + return $encoded; + } + + /** + * Adds a string or binary attachment (non-filesystem) to the list. + * This method can be used to attach ascii or binary data, + * such as a BLOB record from a database. + * @param string $string String attachment data. + * @param string $filename Name of the attachment. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @return void + */ + function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') { + /* Append to $attachment array */ + $cur = count($this->attachment); + $this->attachment[$cur][0] = $string; + $this->attachment[$cur][1] = $filename; + $this->attachment[$cur][2] = $filename; + $this->attachment[$cur][3] = $encoding; + $this->attachment[$cur][4] = $type; + $this->attachment[$cur][5] = true; // isString + $this->attachment[$cur][6] = 'attachment'; + $this->attachment[$cur][7] = 0; + } + + /** + * Adds an embedded attachment. This can include images, sounds, and + * just about any other document. Make sure to set the $type to an + * image type. For JPEG images use "image/jpeg" and for GIF images + * use "image/gif". + * @param string $path Path to the attachment. + * @param string $cid Content ID of the attachment. Use this to identify + * the Id for accessing the image in an HTML form. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @return bool + */ + function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { + + if(!@is_file($path)) { + $this->SetError($this->Lang('file_access') . $path); + return false; + } + + $filename = basename($path); + if($name == '') { + $name = $filename; + } + + /* Append to $attachment array */ + $cur = count($this->attachment); + $this->attachment[$cur][0] = $path; + $this->attachment[$cur][1] = $filename; + $this->attachment[$cur][2] = $name; + $this->attachment[$cur][3] = $encoding; + $this->attachment[$cur][4] = $type; + $this->attachment[$cur][5] = false; + $this->attachment[$cur][6] = 'inline'; + $this->attachment[$cur][7] = $cid; + + return true; + } + + /** + * Returns true if an inline attachment is present. + * @access private + * @return bool + */ + function InlineImageExists() { + $result = false; + for($i = 0; $i < count($this->attachment); $i++) { + if($this->attachment[$i][6] == 'inline') { + $result = true; + break; + } + } + + return $result; + } + + ///////////////////////////////////////////////// + // CLASS METHODS, MESSAGE RESET + ///////////////////////////////////////////////// + + /** + * Clears all recipients assigned in the TO array. Returns void. + * @return void + */ + function ClearAddresses() { + $this->to = array(); + } + + /** + * Clears all recipients assigned in the CC array. Returns void. + * @return void + */ + function ClearCCs() { + $this->cc = array(); + } + + /** + * Clears all recipients assigned in the BCC array. Returns void. + * @return void + */ + function ClearBCCs() { + $this->bcc = array(); + } + + /** + * Clears all recipients assigned in the ReplyTo array. Returns void. + * @return void + */ + function ClearReplyTos() { + $this->ReplyTo = array(); + } + + /** + * Clears all recipients assigned in the TO, CC and BCC + * array. Returns void. + * @return void + */ + function ClearAllRecipients() { + $this->to = array(); + $this->cc = array(); + $this->bcc = array(); + } + + /** + * Clears all previously set filesystem, string, and binary + * attachments. Returns void. + * @return void + */ + function ClearAttachments() { + $this->attachment = array(); + } + + /** + * Clears all custom headers. Returns void. + * @return void + */ + function ClearCustomHeaders() { + $this->CustomHeader = array(); + } + + ///////////////////////////////////////////////// + // CLASS METHODS, MISCELLANEOUS + ///////////////////////////////////////////////// + + /** + * Adds the error message to the error container. + * Returns void. + * @access private + * @return void + */ + function SetError($msg) { + $this->error_count++; + $this->ErrorInfo = $msg; + } + + /** + * Returns the proper RFC 822 formatted date. + * @access private + * @return string + */ + function RFCDate() { + $tz = date('Z'); + $tzs = ($tz < 0) ? '-' : '+'; + $tz = abs($tz); + $tz = (int)($tz/3600)*100 + ($tz%3600)/60; + $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz); + + return $result; + } + + /** + * Returns the appropriate server variable. Should work with both + * PHP 4.1.0+ as well as older versions. Returns an empty string + * if nothing is found. + * @access private + * @return mixed + */ + function ServerVar($varName) { + global $HTTP_SERVER_VARS; + global $HTTP_ENV_VARS; + + if(!isset($_SERVER)) { + $_SERVER = $HTTP_SERVER_VARS; + if(!isset($_SERVER['REMOTE_ADDR'])) { + $_SERVER = $HTTP_ENV_VARS; // must be Apache + } + } + + if(isset($_SERVER[$varName])) { + return $_SERVER[$varName]; + } else { + return ''; + } + } + + /** + * Returns the server hostname or 'localhost.localdomain' if unknown. + * @access private + * @return string + */ + function ServerHostname() { + if ($this->Hostname != '') { + $result = $this->Hostname; + } elseif ($this->ServerVar('SERVER_NAME') != '') { + $result = $this->ServerVar('SERVER_NAME'); + } else { + $result = 'localhost.localdomain'; + } + + return $result; + } + + /** + * Returns a message in the appropriate language. + * @access private + * @return string + */ + function Lang($key) { + if(count($this->language) < 1) { + $this->SetLanguage('en'); // set the default language + } + + if(isset($this->language[$key])) { + return $this->language[$key]; + } else { + return 'Language string failed to load: ' . $key; + } + } + + /** + * Returns true if an error occurred. + * @return bool + */ + function IsError() { + return ($this->error_count > 0); + } + + /** + * Changes every end of line from CR or LF to CRLF. + * @access private + * @return string + */ + function FixEOL($str) { + $str = str_replace("\r\n", "\n", $str); + $str = str_replace("\r", "\n", $str); + $str = str_replace("\n", $this->LE, $str); + return $str; + } + + /** + * Adds a custom header. + * @return void + */ + function AddCustomHeader($custom_header) { + $this->CustomHeader[] = explode(':', $custom_header, 2); + } + + /** + * Evaluates the message and returns modifications for inline images and backgrounds + * @access public + * @return $message + */ + function MsgHTML($message,$basedir='') { + preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images); + if(isset($images[2])) { + foreach($images[2] as $i => $url) { + // do not change urls for absolute images (thanks to corvuscorax) + if (!preg_match('/^[A-z][A-z]*:\/\//',$url)) { + $filename = basename($url); + $directory = dirname($url); + ($directory == '.')?$directory='':''; + $cid = 'cid:' . md5($filename); + $fileParts = split("\.", $filename); + $ext = $fileParts[1]; + $mimeType = $this->_mime_types($ext); + if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; } + if ( strlen($directory) > 1 && substr($directory,-1) != '/') { $directory .= '/'; } + if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) { + $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message); + } + } + } + } + $this->IsHTML(true); + $this->Body = $message; + $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message))); + if ( !empty($textMsg) && empty($this->AltBody) ) { + $this->AltBody = html_entity_decode($textMsg); + } + if ( empty($this->AltBody) ) { + $this->AltBody = 'To view this email message, open the email in with HTML compatibility!' . "\n\n"; + } + } + + /** + * Gets the mime type of the embedded or inline image + * @access private + * @return mime type of ext + */ + function _mime_types($ext = '') { + $mimes = array( + 'ai' => 'application/postscript', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'avi' => 'video/x-msvideo', + 'bin' => 'application/macbinary', + 'bmp' => 'image/bmp', + 'class' => 'application/octet-stream', + 'cpt' => 'application/mac-compactpro', + 'css' => 'text/css', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dll' => 'application/octet-stream', + 'dms' => 'application/octet-stream', + 'doc' => 'application/msword', + 'dvi' => 'application/x-dvi', + 'dxr' => 'application/x-director', + 'eml' => 'message/rfc822', + 'eps' => 'application/postscript', + 'exe' => 'application/octet-stream', + 'gif' => 'image/gif', + 'gtar' => 'application/x-gtar', + 'htm' => 'text/html', + 'html' => 'text/html', + 'jpe' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'hqx' => 'application/mac-binhex40', + 'js' => 'application/x-javascript', + 'lha' => 'application/octet-stream', + 'log' => 'text/plain', + 'lzh' => 'application/octet-stream', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mif' => 'application/vnd.mif', + 'mov' => 'video/quicktime', + 'movie' => 'video/x-sgi-movie', + 'mp2' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mpe' => 'video/mpeg', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpga' => 'audio/mpeg', + 'oda' => 'application/oda', + 'pdf' => 'application/pdf', + 'php' => 'application/x-httpd-php', + 'php3' => 'application/x-httpd-php', + 'php4' => 'application/x-httpd-php', + 'phps' => 'application/x-httpd-php-source', + 'phtml' => 'application/x-httpd-php', + 'png' => 'image/png', + 'ppt' => 'application/vnd.ms-powerpoint', + 'ps' => 'application/postscript', + 'psd' => 'application/octet-stream', + 'qt' => 'video/quicktime', + 'ra' => 'audio/x-realaudio', + 'ram' => 'audio/x-pn-realaudio', + 'rm' => 'audio/x-pn-realaudio', + 'rpm' => 'audio/x-pn-realaudio-plugin', + 'rtf' => 'text/rtf', + 'rtx' => 'text/richtext', + 'rv' => 'video/vnd.rn-realvideo', + 'sea' => 'application/octet-stream', + 'shtml' => 'text/html', + 'sit' => 'application/x-stuffit', + 'so' => 'application/octet-stream', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'swf' => 'application/x-shockwave-flash', + 'tar' => 'application/x-tar', + 'text' => 'text/plain', + 'txt' => 'text/plain', + 'tgz' => 'application/x-tar', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'wav' => 'audio/x-wav', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'word' => 'application/msword', + 'xht' => 'application/xhtml+xml', + 'xhtml' => 'application/xhtml+xml', + 'xl' => 'application/excel', + 'xls' => 'application/vnd.ms-excel', + 'xml' => 'text/xml', + 'xsl' => 'text/xml', + 'zip' => 'application/zip' + ); + return ( ! isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)]; + } + + /** + * Set (or reset) Class Objects (variables) + * + * Usage Example: + * $page->set('X-Priority', '3'); + * + * @access public + * @param string $name Parameter Name + * @param mixed $value Parameter Value + * NOTE: will not work with arrays, there are no arrays to set/reset + */ + function set ( $name, $value = '' ) { + if ( isset($this->$name) ) { + $this->$name = $value; + } else { + $this->SetError('Cannot set or reset variable ' . $name); + return false; + } + } + + /** + * Read a file from a supplied filename and return it. + * + * @access public + * @param string $filename Parameter File Name + */ + function getFile($filename) { + $return = ''; + if ($fp = fopen($filename, 'rb')) { + while (!feof($fp)) { + $return .= fread($fp, 1024); + } + fclose($fp); + return $return; + } else { + return false; + } + } + + /** + * Strips newlines to prevent header injection. + * @access private + * @param string $str String + * @return string + */ + function SecureHeader($str) { + $str = trim($str); + $str = str_replace("\r", "", $str); + $str = str_replace("\n", "", $str); + return $str; + } + + /** + * Set the private key file and password to sign the message. + * + * @access public + * @param string $key_filename Parameter File Name + * @param string $key_pass Password for private key + */ + function Sign($cert_filename, $key_filename, $key_pass) { + $this->sign_cert_file = $cert_filename; + $this->sign_key_file = $key_filename; + $this->sign_key_pass = $key_pass; + } + +} + +?> diff --git a/src/core/libs/phpmailer/class.smtp.php b/src/core/libs/phpmailer/class.smtp.php new file mode 100755 index 0000000..e14b579 --- /dev/null +++ b/src/core/libs/phpmailer/class.smtp.php @@ -0,0 +1,1062 @@ +<?php +/*~ class.smtp.php +.---------------------------------------------------------------------------. +| Software: PHPMailer - PHP email class | +| Version: 2.0.4 | +| Contact: via sourceforge.net support pages (also www.codeworxtech.com) | +| Info: http://phpmailer.sourceforge.net | +| Support: http://sourceforge.net/projects/phpmailer/ | +| ------------------------------------------------------------------------- | +| Author: Andy Prevost (project admininistrator) | +| Author: Brent R. Matzelle (original founder) | +| Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved. | +| Copyright (c) 2001-2003, Brent R. Matzelle | +| ------------------------------------------------------------------------- | +| License: Distributed under the Lesser General Public License (LGPL) | +| http://www.gnu.org/copyleft/lesser.html | +| This program is distributed in the hope that it will be useful - WITHOUT | +| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | +| FITNESS FOR A PARTICULAR PURPOSE. | +| ------------------------------------------------------------------------- | +| We offer a number of paid services (www.codeworxtech.com): | +| - Web Hosting on highly optimized fast and secure servers | +| - Technology Consulting | +| - Oursourcing (highly qualified programmers and graphic designers) | +'---------------------------------------------------------------------------' + */ +/** + * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP + * commands except TURN which will always return a not implemented + * error. SMTP also provides some utility methods for sending mail + * to an SMTP server. + * @package PHPMailer + * @author Chris Ryan + */ + +class SMTP +{ + /** + * SMTP server port + * @var int + */ + var $SMTP_PORT = 25; + + /** + * SMTP reply line ending + * @var string + */ + var $CRLF = "\r\n"; + + /** + * Sets whether debugging is turned on + * @var bool + */ + var $do_debug; # the level of debug to perform + + /** + * Sets VERP use on/off (default is off) + * @var bool + */ + var $do_verp = false; + + /**#@+ + * @access private + */ + var $smtp_conn; # the socket to the server + var $error; # error if any on the last call + var $helo_rply; # the reply the server sent to us for HELO + /**#@-*/ + + /** + * Initialize the class so that the data is in a known state. + * @access public + * @return void + */ + function SMTP() { + $this->smtp_conn = 0; + $this->error = null; + $this->helo_rply = null; + + $this->do_debug = 0; + } + + /************************************************************* + * CONNECTION FUNCTIONS * + ***********************************************************/ + + /** + * Connect to the server specified on the port specified. + * If the port is not specified use the default SMTP_PORT. + * If tval is specified then a connection will try and be + * established with the server for that number of seconds. + * If tval is not specified the default is 30 seconds to + * try on the connection. + * + * SMTP CODE SUCCESS: 220 + * SMTP CODE FAILURE: 421 + * @access public + * @return bool + */ + function Connect($host,$port=0,$tval=30) { + # set the error val to null so there is no confusion + $this->error = null; + + # make sure we are __not__ connected + if($this->connected()) { + # ok we are connected! what should we do? + # for now we will just give an error saying we + # are already connected + $this->error = array("error" => "Already connected to a server"); + return false; + } + + if(empty($port)) { + $port = $this->SMTP_PORT; + } + + #connect to the smtp server + $this->smtp_conn = fsockopen($host, # the host of the server + $port, # the port to use + $errno, # error number if any + $errstr, # error message if any + $tval); # give up after ? secs + # verify we connected properly + if(empty($this->smtp_conn)) { + $this->error = array("error" => "Failed to connect to server", + "errno" => $errno, + "errstr" => $errstr); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": $errstr ($errno)" . $this->CRLF; + } + return false; + } + + # sometimes the SMTP server takes a little longer to respond + # so we will give it a longer timeout for the first read + // Windows still does not have support for this timeout function + if(substr(PHP_OS, 0, 3) != "WIN") + socket_set_timeout($this->smtp_conn, $tval, 0); + + # get any announcement stuff + $announce = $this->get_lines(); + + # set the timeout of any socket functions at 1/10 of a second + //if(function_exists("socket_set_timeout")) + // socket_set_timeout($this->smtp_conn, 0, 100000); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce; + } + + return true; + } + + /** + * Performs SMTP authentication. Must be run after running the + * Hello() method. Returns true if successfully authenticated. + * @access public + * @return bool + */ + function Authenticate($username, $password) { + // Start authentication + fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 334) { + $this->error = + array("error" => "AUTH not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + // Send encoded username + fputs($this->smtp_conn, base64_encode($username) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 334) { + $this->error = + array("error" => "Username not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + // Send encoded password + fputs($this->smtp_conn, base64_encode($password) . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($code != 235) { + $this->error = + array("error" => "Password not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + return true; + } + + /** + * Returns true if connected to a server otherwise false + * @access private + * @return bool + */ + function Connected() { + if(!empty($this->smtp_conn)) { + $sock_status = socket_get_status($this->smtp_conn); + if($sock_status["eof"]) { + # hmm this is an odd situation... the socket is + # valid but we are not connected anymore + if($this->do_debug >= 1) { + echo "SMTP -> NOTICE:" . $this->CRLF . + "EOF caught while checking if connected"; + } + $this->Close(); + return false; + } + return true; # everything looks good + } + return false; + } + + /** + * Closes the socket and cleans up the state of the class. + * It is not considered good to use this function without + * first trying to use QUIT. + * @access public + * @return void + */ + function Close() { + $this->error = null; # so there is no confusion + $this->helo_rply = null; + if(!empty($this->smtp_conn)) { + # close the connection and cleanup + fclose($this->smtp_conn); + $this->smtp_conn = 0; + } + } + + /*************************************************************** + * SMTP COMMANDS * + *************************************************************/ + + /** + * Issues a data command and sends the msg_data to the server + * finializing the mail transaction. $msg_data is the message + * that is to be send with the headers. Each header needs to be + * on a single line followed by a <CRLF> with the message headers + * and the message body being separated by and additional <CRLF>. + * + * Implements rfc 821: DATA <CRLF> + * + * SMTP CODE INTERMEDIATE: 354 + * [data] + * <CRLF>.<CRLF> + * SMTP CODE SUCCESS: 250 + * SMTP CODE FAILURE: 552,554,451,452 + * SMTP CODE FAILURE: 451,554 + * SMTP CODE ERROR : 500,501,503,421 + * @access public + * @return bool + */ + function Data($msg_data) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Data() without being connected"); + return false; + } + + fputs($this->smtp_conn,"DATA" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 354) { + $this->error = + array("error" => "DATA command not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + # the server is ready to accept data! + # according to rfc 821 we should not send more than 1000 + # including the CRLF + # characters on a single line so we will break the data up + # into lines by \r and/or \n then if needed we will break + # each of those into smaller lines to fit within the limit. + # in addition we will be looking for lines that start with + # a period '.' and append and additional period '.' to that + # line. NOTE: this does not count towards are limit. + + # normalize the line breaks so we know the explode works + $msg_data = str_replace("\r\n","\n",$msg_data); + $msg_data = str_replace("\r","\n",$msg_data); + $lines = explode("\n",$msg_data); + + # we need to find a good way to determine is headers are + # in the msg_data or if it is a straight msg body + # currently I am assuming rfc 822 definitions of msg headers + # and if the first field of the first line (':' sperated) + # does not contain a space then it _should_ be a header + # and we can process all lines before a blank "" line as + # headers. + $field = substr($lines[0],0,strpos($lines[0],":")); + $in_headers = false; + if(!empty($field) && !strstr($field," ")) { + $in_headers = true; + } + + $max_line_length = 998; # used below; set here for ease in change + + while(list(,$line) = @each($lines)) { + $lines_out = null; + if($line == "" && $in_headers) { + $in_headers = false; + } + # ok we need to break this line up into several + # smaller lines + while(strlen($line) > $max_line_length) { + $pos = strrpos(substr($line,0,$max_line_length)," "); + + # Patch to fix DOS attack + if(!$pos) { + $pos = $max_line_length - 1; + } + + $lines_out[] = substr($line,0,$pos); + $line = substr($line,$pos + 1); + # if we are processing headers we need to + # add a LWSP-char to the front of the new line + # rfc 822 on long msg headers + if($in_headers) { + $line = "\t" . $line; + } + } + $lines_out[] = $line; + + # now send the lines to the server + while(list(,$line_out) = @each($lines_out)) { + if(strlen($line_out) > 0) + { + if(substr($line_out, 0, 1) == ".") { + $line_out = "." . $line_out; + } + } + fputs($this->smtp_conn,$line_out . $this->CRLF); + } + } + + # ok all the message data has been sent so lets get this + # over with aleady + fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "DATA not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Expand takes the name and asks the server to list all the + * people who are members of the _list_. Expand will return + * back and array of the result or false if an error occurs. + * Each value in the array returned has the format of: + * [ <full-name> <sp> ] <path> + * The definition of <path> is defined in rfc 821 + * + * Implements rfc 821: EXPN <SP> <string> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE FAILURE: 550 + * SMTP CODE ERROR : 500,501,502,504,421 + * @access public + * @return string array + */ + function Expand($name) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Expand() without being connected"); + return false; + } + + fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "EXPN not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + # parse the reply and place in our array to return to user + $entries = explode($this->CRLF,$rply); + while(list(,$l) = @each($entries)) { + $list[] = substr($l,4); + } + + return $list; + } + + /** + * Sends the HELO command to the smtp server. + * This makes sure that we and the server are in + * the same known state. + * + * Implements from rfc 821: HELO <SP> <domain> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE ERROR : 500, 501, 504, 421 + * @access public + * @return bool + */ + function Hello($host="") { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Hello() without being connected"); + return false; + } + + # if a hostname for the HELO was not specified determine + # a suitable one to send + if(empty($host)) { + # we need to determine some sort of appopiate default + # to send to the server + $host = "localhost"; + } + + // Send extended hello first (RFC 2821) + if(!$this->SendHello("EHLO", $host)) + { + if(!$this->SendHello("HELO", $host)) + return false; + } + + return true; + } + + /** + * Sends a HELO/EHLO command. + * @access private + * @return bool + */ + function SendHello($hello, $host) { + fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => $hello . " not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + $this->helo_rply = $rply; + + return true; + } + + /** + * Gets help information on the keyword specified. If the keyword + * is not specified then returns generic help, ussually contianing + * A list of keywords that help is available on. This function + * returns the results back to the user. It is up to the user to + * handle the returned data. If an error occurs then false is + * returned with $this->error set appropiately. + * + * Implements rfc 821: HELP [ <SP> <string> ] <CRLF> + * + * SMTP CODE SUCCESS: 211,214 + * SMTP CODE ERROR : 500,501,502,504,421 + * @access public + * @return string + */ + function Help($keyword="") { + $this->error = null; # to avoid confusion + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Help() without being connected"); + return false; + } + + $extra = ""; + if(!empty($keyword)) { + $extra = " " . $keyword; + } + + fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 211 && $code != 214) { + $this->error = + array("error" => "HELP not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + return $rply; + } + + /** + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more Recipient + * commands may be called followed by a Data command. + * + * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE SUCCESS: 552,451,452 + * SMTP CODE SUCCESS: 500,501,421 + * @access public + * @return bool + */ + function Mail($from) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Mail() without being connected"); + return false; + } + + $useVerp = ($this->do_verp ? "XVERP" : ""); + fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "MAIL not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Sends the command NOOP to the SMTP server. + * + * Implements from rfc 821: NOOP <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE ERROR : 500, 421 + * @access public + * @return bool + */ + function Noop() { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Noop() without being connected"); + return false; + } + + fputs($this->smtp_conn,"NOOP" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "NOOP not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Sends the quit command to the server and then closes the socket + * if there is no error or the $close_on_error argument is true. + * + * Implements from rfc 821: QUIT <CRLF> + * + * SMTP CODE SUCCESS: 221 + * SMTP CODE ERROR : 500 + * @access public + * @return bool + */ + function Quit($close_on_error=true) { + $this->error = null; # so there is no confusion + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Quit() without being connected"); + return false; + } + + # send the quit command to the server + fputs($this->smtp_conn,"quit" . $this->CRLF); + + # get any good-bye messages + $byemsg = $this->get_lines(); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg; + } + + $rval = true; + $e = null; + + $code = substr($byemsg,0,3); + if($code != 221) { + # use e as a tmp var cause Close will overwrite $this->error + $e = array("error" => "SMTP server rejected quit command", + "smtp_code" => $code, + "smtp_rply" => substr($byemsg,4)); + $rval = false; + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $e["error"] . ": " . + $byemsg . $this->CRLF; + } + } + + if(empty($e) || $close_on_error) { + $this->Close(); + } + + return $rval; + } + + /** + * Sends the command RCPT to the SMTP server with the TO: argument of $to. + * Returns true if the recipient was accepted false if it was rejected. + * + * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF> + * + * SMTP CODE SUCCESS: 250,251 + * SMTP CODE FAILURE: 550,551,552,553,450,451,452 + * SMTP CODE ERROR : 500,501,503,421 + * @access public + * @return bool + */ + function Recipient($to) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Recipient() without being connected"); + return false; + } + + fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250 && $code != 251) { + $this->error = + array("error" => "RCPT not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Sends the RSET command to abort and transaction that is + * currently in progress. Returns true if successful false + * otherwise. + * + * Implements rfc 821: RSET <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE ERROR : 500,501,504,421 + * @access public + * @return bool + */ + function Reset() { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Reset() without being connected"); + return false; + } + + fputs($this->smtp_conn,"RSET" . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "RSET failed", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + + return true; + } + + /** + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more Recipient + * commands may be called followed by a Data command. This command + * will send the message to the users terminal if they are logged + * in. + * + * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE SUCCESS: 552,451,452 + * SMTP CODE SUCCESS: 500,501,502,421 + * @access public + * @return bool + */ + function Send($from) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Send() without being connected"); + return false; + } + + fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "SEND not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more Recipient + * commands may be called followed by a Data command. This command + * will send the message to the users terminal if they are logged + * in and send them an email. + * + * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE SUCCESS: 552,451,452 + * SMTP CODE SUCCESS: 500,501,502,421 + * @access public + * @return bool + */ + function SendAndMail($from) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called SendAndMail() without being connected"); + return false; + } + + fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "SAML not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more Recipient + * commands may be called followed by a Data command. This command + * will send the message to the users terminal if they are logged + * in or mail it to them if they are not. + * + * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE SUCCESS: 552,451,452 + * SMTP CODE SUCCESS: 500,501,502,421 + * @access public + * @return bool + */ + function SendOrMail($from) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called SendOrMail() without being connected"); + return false; + } + + fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250) { + $this->error = + array("error" => "SOML not accepted from server", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return true; + } + + /** + * This is an optional command for SMTP that this class does not + * support. This method is here to make the RFC821 Definition + * complete for this class and __may__ be implimented in the future + * + * Implements from rfc 821: TURN <CRLF> + * + * SMTP CODE SUCCESS: 250 + * SMTP CODE FAILURE: 502 + * SMTP CODE ERROR : 500, 503 + * @access public + * @return bool + */ + function Turn() { + $this->error = array("error" => "This method, TURN, of the SMTP ". + "is not implemented"); + if($this->do_debug >= 1) { + echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF; + } + return false; + } + + /** + * Verifies that the name is recognized by the server. + * Returns false if the name could not be verified otherwise + * the response from the server is returned. + * + * Implements rfc 821: VRFY <SP> <string> <CRLF> + * + * SMTP CODE SUCCESS: 250,251 + * SMTP CODE FAILURE: 550,551,553 + * SMTP CODE ERROR : 500,501,502,421 + * @access public + * @return int + */ + function Verify($name) { + $this->error = null; # so no confusion is caused + + if(!$this->connected()) { + $this->error = array( + "error" => "Called Verify() without being connected"); + return false; + } + + fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF); + + $rply = $this->get_lines(); + $code = substr($rply,0,3); + + if($this->do_debug >= 2) { + echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply; + } + + if($code != 250 && $code != 251) { + $this->error = + array("error" => "VRFY failed on name '$name'", + "smtp_code" => $code, + "smtp_msg" => substr($rply,4)); + if($this->do_debug >= 1) { + echo "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF; + } + return false; + } + return $rply; + } + + /******************************************************************* + * INTERNAL FUNCTIONS * + ******************************************************************/ + + /** + * Read in as many lines as possible + * either before eof or socket timeout occurs on the operation. + * With SMTP we can tell if we have more lines to read if the + * 4th character is '-' symbol. If it is a space then we don't + * need to read anything else. + * @access private + * @return string + */ + function get_lines() { + $data = ""; + while($str = @fgets($this->smtp_conn,515)) { + if($this->do_debug >= 4) { + echo "SMTP -> get_lines(): \$data was \"$data\"" . + $this->CRLF; + echo "SMTP -> get_lines(): \$str is \"$str\"" . + $this->CRLF; + } + $data .= $str; + if($this->do_debug >= 4) { + echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF; + } + # if the 4th character is a space then we are done reading + # so just break the loop + if(substr($str,3,1) == " ") { break; } + } + return $data; + } + +} + + + ?> diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-br.php b/src/core/libs/phpmailer/language/phpmailer.lang-br.php new file mode 100755 index 0000000..b948c26 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-br.php @@ -0,0 +1,21 @@ +<?php +/** + * PHPMailer language file. + * Portuguese Version + * By Paulo Henrique Garcia - paulo@controllerweb.com.br + */ + +$PHPMAILER_LANG = array(); +$PHPMAILER_LANG["provide_address"] = 'Você deve fornecer pelo menos um endereço de destinatário de email.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailer não suportado.'; +$PHPMAILER_LANG["execute"] = 'Não foi possível executar: '; +$PHPMAILER_LANG["instantiate"] = 'Não foi possível instanciar a função mail.'; +$PHPMAILER_LANG["authenticate"] = 'Erro de SMTP: Não foi possível autenticar.'; +$PHPMAILER_LANG["from_failed"] = 'Os endereços de rementente a seguir falharam: '; +$PHPMAILER_LANG["recipients_failed"] = 'Erro de SMTP: Os endereços de destinatário a seguir falharam: '; +$PHPMAILER_LANG["data_not_accepted"] = 'Erro de SMTP: Dados não aceitos.'; +$PHPMAILER_LANG["connect_host"] = 'Erro de SMTP: Não foi possível conectar com o servidor SMTP.'; +$PHPMAILER_LANG["file_access"] = 'Não foi possível acessar o arquivo: '; +$PHPMAILER_LANG["file_open"] = 'Erro de Arquivo: Não foi possível abrir o arquivo: '; +$PHPMAILER_LANG["encoding"] = 'Codificação desconhecida: '; +?> diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-ca.php b/src/core/libs/phpmailer/language/phpmailer.lang-ca.php new file mode 100755 index 0000000..fdd4207 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-ca.php @@ -0,0 +1,22 @@ +<?php +/** + * PHPMailer language file. + * Catalan Version + * By Ivan: web AT microstudi DOT com + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'S\'ha de proveir almenys una adreça d\'email com a destinatari.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailer no està suportat'; +$PHPMAILER_LANG["execute"] = 'No es pot executar: '; +$PHPMAILER_LANG["instantiate"] = 'No s\'ha pogut crear una instància de la funció Mail.'; +$PHPMAILER_LANG["authenticate"] = 'Error SMTP: No s\'hapogut autenticar.'; +$PHPMAILER_LANG["from_failed"] = 'La(s) següent(s) adreces de remitent han fallat: '; +$PHPMAILER_LANG["recipients_failed"] = 'Error SMTP: Els següents destinataris han fallat: '; +$PHPMAILER_LANG["data_not_accepted"] = 'Error SMTP: Dades no acceptades.'; +$PHPMAILER_LANG["connect_host"] = 'Error SMTP: No es pot connectar al servidor SMTP.'; +$PHPMAILER_LANG["file_access"] = 'No es pot accedir a l\'arxiu: '; +$PHPMAILER_LANG["file_open"] = 'Error d\'Arxiu: No es pot obrir l\'arxiu: '; +$PHPMAILER_LANG["encoding"] = 'Codificació desconeguda: '; +?> \ No newline at end of file diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-cz.php b/src/core/libs/phpmailer/language/phpmailer.lang-cz.php new file mode 100755 index 0000000..f272f92 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-cz.php @@ -0,0 +1,24 @@ +<?php +/** + * PHPMailer language file. + * Czech Version + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Musíte zadat alespoò jednu ' . + 'emailovou adresu pøíjemce.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailový klient není podporován.'; +$PHPMAILER_LANG["execute"] = 'Nelze provést: '; +$PHPMAILER_LANG["instantiate"] = 'Nelze vytvoøit instanci emailové funkce.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP Error: Chyba autentikace.'; +$PHPMAILER_LANG["from_failed"] = 'Následující adresa From je nesprávná: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP Error: Adresy pøíjemcù ' . + 'nejsou správné ' . +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP Error: Data nebyla pøijata'; +$PHPMAILER_LANG["connect_host"] = 'SMTP Error: Nelze navázat spojení se ' . + ' SMTP serverem.'; +$PHPMAILER_LANG["file_access"] = 'Soubor nenalezen: '; +$PHPMAILER_LANG["file_open"] = 'File Error: Nelze otevøít soubor pro ètení: '; +$PHPMAILER_LANG["encoding"] = 'Neznámé kódování: '; +?> \ No newline at end of file diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-de.php b/src/core/libs/phpmailer/language/phpmailer.lang-de.php new file mode 100755 index 0000000..3eabaed --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-de.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPMailer language file. + * German Version + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Bitte geben Sie mindestens eine ' . + 'Empf&auml;nger Emailadresse an.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailer wird nicht unterst&uuml;tzt.'; +$PHPMAILER_LANG["execute"] = 'Konnte folgenden Befehl nicht ausf&uuml;hren: '; +$PHPMAILER_LANG["instantiate"] = 'Mail Funktion konnte nicht initialisiert werden.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP Fehler: Authentifizierung fehlgeschlagen.'; +$PHPMAILER_LANG["from_failed"] = 'Die folgende Absenderadresse ist nicht korrekt: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP Fehler: Die folgenden ' . + 'Empf&auml;nger sind nicht korrekt: '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP Fehler: Daten werden nicht akzeptiert.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP Fehler: Konnte keine Verbindung zum SMTP-Host herstellen.'; +$PHPMAILER_LANG["file_access"] = 'Zugriff auf folgende Datei fehlgeschlagen: '; +$PHPMAILER_LANG["file_open"] = 'Datei Fehler: Konnte Date nicht &ouml;ffnen: '; +$PHPMAILER_LANG["encoding"] = 'Unbekanntes Encoding-Format: '; +?> diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-dk.php b/src/core/libs/phpmailer/language/phpmailer.lang-dk.php new file mode 100755 index 0000000..a027c27 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-dk.php @@ -0,0 +1,24 @@ +<?php +/** + * PHPMailer language file. + * Danish Version + * Author: Mikael Stokkebro <info@stokkebro.dk> + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Du skal indtaste mindst en ' . + 'modtagers emailadresse.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailer understøttes ikke.'; +$PHPMAILER_LANG["execute"] = 'Kunne ikke køre: '; +$PHPMAILER_LANG["instantiate"] = 'Kunne ikke initialisere email funktionen.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP fejl: Kunne ikke logge på.'; +$PHPMAILER_LANG["from_failed"] = 'Følgende afsenderadresse er forkert: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP fejl: Følgende' . + 'modtagere er forkerte: '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP fejl: Data kunne ikke accepteres.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP fejl: Kunne ikke tilslutte SMTP serveren.'; +$PHPMAILER_LANG["file_access"] = 'Ingen adgang til fil: '; +$PHPMAILER_LANG["file_open"] = 'Fil fejl: Kunne ikke åbne filen: '; +$PHPMAILER_LANG["encoding"] = 'Ukendt encode-format: '; +?> \ No newline at end of file diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-en.php b/src/core/libs/phpmailer/language/phpmailer.lang-en.php new file mode 100755 index 0000000..2f45383 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-en.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPMailer language file. + * English Version + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'You must provide at least one ' . + 'recipient email address.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailer is not supported.'; +$PHPMAILER_LANG["execute"] = 'Could not execute: '; +$PHPMAILER_LANG["instantiate"] = 'Could not instantiate mail function.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP Error: Could not authenticate.'; +$PHPMAILER_LANG["from_failed"] = 'The following From address failed: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP Error: The following ' . + 'recipients failed: '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP Error: Data not accepted.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP Error: Could not connect to SMTP host.'; +$PHPMAILER_LANG["file_access"] = 'Could not access file: '; +$PHPMAILER_LANG["file_open"] = 'File Error: Could not open file: '; +$PHPMAILER_LANG["encoding"] = 'Unknown encoding: '; +?> diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-es.php b/src/core/libs/phpmailer/language/phpmailer.lang-es.php new file mode 100755 index 0000000..9e77137 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-es.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPMailer language file. + * Versión en español + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Debe proveer al menos una ' . + 'dirección de email como destinatario.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailer no está soportado.'; +$PHPMAILER_LANG["execute"] = 'No puedo ejecutar: '; +$PHPMAILER_LANG["instantiate"] = 'No pude crear una instancia de la función Mail.'; +$PHPMAILER_LANG["authenticate"] = 'Error SMTP: No se pudo autentificar.'; +$PHPMAILER_LANG["from_failed"] = 'La(s) siguiente(s) direcciones de remitente fallaron: '; +$PHPMAILER_LANG["recipients_failed"] = 'Error SMTP: Los siguientes ' . + 'destinatarios fallaron: '; +$PHPMAILER_LANG["data_not_accepted"] = 'Error SMTP: Datos no aceptados.'; +$PHPMAILER_LANG["connect_host"] = 'Error SMTP: No puedo conectar al servidor SMTP.'; +$PHPMAILER_LANG["file_access"] = 'No puedo acceder al archivo: '; +$PHPMAILER_LANG["file_open"] = 'Error de Archivo: No puede abrir el archivo: '; +$PHPMAILER_LANG["encoding"] = 'Codificación desconocida: '; +?> \ No newline at end of file diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-et.php b/src/core/libs/phpmailer/language/phpmailer.lang-et.php new file mode 100755 index 0000000..eb56de7 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-et.php @@ -0,0 +1,22 @@ +<?php +/** + * PHPMailer language file. + * Estonian Version + * By Indrek P&auml;ri + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Te peate m&auml;&auml;rama v&auml;hemalt &uuml;he saaja e-posti aadressi.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' maileri tugi puudub.'; +$PHPMAILER_LANG["execute"] = 'Tegevus eba&otilde;nnestus: '; +$PHPMAILER_LANG["instantiate"] = 'mail funktiooni k&auml;ivitamine eba&otilde;nnestus.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP Viga: Autoriseerimise viga.'; +$PHPMAILER_LANG["from_failed"] = 'J&auml;rgnev saatja e-posti aadress on vigane: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP Viga: J&auml;rgnevate saajate e-posti aadressid on vigased: '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP Viga: Vigased andmed.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP Viga: Ei &otilde;nnestunud luua &uuml;hendust SMTP serveriga.'; +$PHPMAILER_LANG["file_access"] = 'Pole piisavalt &otilde;iguseid j&auml;rgneva faili avamiseks: '; +$PHPMAILER_LANG["file_open"] = 'Faili Viga: Faili avamine eba&otilde;nnestus: '; +$PHPMAILER_LANG["encoding"] = 'Tundmatu Unknown kodeering: '; +?> diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-fi.php b/src/core/libs/phpmailer/language/phpmailer.lang-fi.php new file mode 100755 index 0000000..d881080 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-fi.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPMailer language file. + * Finnish Version + * By Jyry Kuukanen + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Aseta v&auml;hint&auml;&auml;n yksi vastaanottajan ' . + 's&auml;hk&ouml;postiosoite.'; +$PHPMAILER_LANG["mailer_not_supported"] = 'postiv&auml;litintyyppi&auml; ei tueta.'; +$PHPMAILER_LANG["execute"] = 'Suoritus ep&auml;onnistui: '; +$PHPMAILER_LANG["instantiate"] = 'mail-funktion luonti ep&auml;onnistui.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP-virhe: k&auml;ytt&auml;j&auml;tunnistus ep&auml;onnistui.'; +$PHPMAILER_LANG["from_failed"] = 'Seuraava l&auml;hett&auml;j&auml;n osoite on virheellinen: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP-virhe: seuraava vastaanottaja osoite on virheellinen.'; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP-virhe: data on virheellinen.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP-virhe: yhteys palvelimeen ei onnistu.'; +$PHPMAILER_LANG["file_access"] = 'Seuraavaan tiedostoon ei ole oikeuksia: '; +$PHPMAILER_LANG["file_open"] = 'Tiedostovirhe: Ei voida avata tiedostoa: '; +$PHPMAILER_LANG["encoding"] = 'Tuntematon koodaustyyppi: '; +?> \ No newline at end of file diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-fo.php b/src/core/libs/phpmailer/language/phpmailer.lang-fo.php new file mode 100755 index 0000000..fb257ad --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-fo.php @@ -0,0 +1,25 @@ +<?php +/** + * PHPMailer language file. + * Faroese Version [language of the Faroe Islands, a Danish dominion] + * This file created: 11-06-2004 + * Supplied by Dávur Sørensen [www.profo-webdesign.dk] + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Tú skal uppgeva minst ' . + 'móttakara-emailadressu(r).'; +$PHPMAILER_LANG["mailer_not_supported"] = ' er ikki supporterað.'; +$PHPMAILER_LANG["execute"] = 'Kundi ikki útføra: '; +$PHPMAILER_LANG["instantiate"] = 'Kuni ikki instantiera mail funktión.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP feilur: Kundi ikki góðkenna.'; +$PHPMAILER_LANG["from_failed"] = 'fylgjandi Frá/From adressa miseydnaðist: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP Feilur: Fylgjandi ' . + 'móttakarar miseydnaðust: '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP feilur: Data ikki góðkent.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP feilur: Kundi ikki knýta samband við SMTP vert.'; +$PHPMAILER_LANG["file_access"] = 'Kundi ikki tilganga fílu: '; +$PHPMAILER_LANG["file_open"] = 'Fílu feilur: Kundi ikki opna fílu: '; +$PHPMAILER_LANG["encoding"] = 'Ókend encoding: '; +?> diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-fr.php b/src/core/libs/phpmailer/language/phpmailer.lang-fr.php new file mode 100755 index 0000000..2c2f81b --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-fr.php @@ -0,0 +1,24 @@ +<?php +/** + * PHPMailer language file. + * French Version + * bruno@ioda-net.ch 09.08.2003 + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Vous devez fournir au moins ' . + 'une adresse de destinataire.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailer non supporté.'; +$PHPMAILER_LANG["execute"] = 'Ne peut pas lancer l\'exécution: '; +$PHPMAILER_LANG["instantiate"] = 'Impossible d\'instancier la fonction mail.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP Erreur: Echec de l\'authentification.'; +$PHPMAILER_LANG["from_failed"] = 'L\'adresse From suivante a échoué : '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP Erreur: Les destinataires ' . + 'suivants sont en erreur : '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP Erreur: Data non acceptée.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP Erreur: Impossible de connecter le serveur SMTP .'; +$PHPMAILER_LANG["file_access"] = 'N\'arrive pas à accéder au fichier: '; +$PHPMAILER_LANG["file_open"] = 'Erreur Fichier: ouverture impossible: '; +$PHPMAILER_LANG["encoding"] = 'Encodage inconnu: '; +?> diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-hu.php b/src/core/libs/phpmailer/language/phpmailer.lang-hu.php new file mode 100755 index 0000000..5c7fc8b --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-hu.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPMailer language file. + * Hungarian Version + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Meg kell adnod legalább egy ' . + 'címzett email címet.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' levelezõ nem támogatott.'; +$PHPMAILER_LANG["execute"] = 'Nem tudtam végrehajtani: '; +$PHPMAILER_LANG["instantiate"] = 'Nem sikerült példányosítani a mail funkciót.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP Hiba: Sikertelen autentikáció.'; +$PHPMAILER_LANG["from_failed"] = 'Az alábbi Feladó cím hibás: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP Hiba: Az alábbi ' . + 'címzettek hibásak: '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP Hiba: Nem elfogadható adat.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP Hiba: Nem tudtam csatlakozni az SMTP host-hoz.'; +$PHPMAILER_LANG["file_access"] = 'Nem sikerült elérni a következõ fájlt: '; +$PHPMAILER_LANG["file_open"] = 'Fájl Hiba: Nem sikerült megnyitni a következõ fájlt: '; +$PHPMAILER_LANG["encoding"] = 'Ismeretlen kódolás: '; +?> \ No newline at end of file diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-it.php b/src/core/libs/phpmailer/language/phpmailer.lang-it.php new file mode 100755 index 0000000..26ef64d --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-it.php @@ -0,0 +1,28 @@ +<?php +/** +* PHPMailer language file. +* Italian version +* @package PHPMailer +* @author Ilias Bartolini <brain79@inwind.it> +*/ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Deve essere fornito almeno un'. + ' indirizzo ricevente'; +$PHPMAILER_LANG["mailer_not_supported"] = 'Mailer non supportato'; +$PHPMAILER_LANG["execute"] = "Impossibile eseguire l'operazione: "; +$PHPMAILER_LANG["instantiate"] = 'Impossibile istanziare la funzione mail'; +$PHPMAILER_LANG["authenticate"] = 'SMTP Error: Impossibile autenticarsi.'; +$PHPMAILER_LANG["from_failed"] = 'I seguenti indirizzi mittenti hanno'. + ' generato errore: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP Error: I seguenti indirizzi'. + 'destinatari hanno generato errore: '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP Error: Data non accettati dal'. + 'server.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP Error: Impossibile connettersi'. + ' all\'host SMTP.'; +$PHPMAILER_LANG["file_access"] = 'Impossibile accedere al file: '; +$PHPMAILER_LANG["file_open"] = 'File Error: Impossibile aprire il file: '; +$PHPMAILER_LANG["encoding"] = 'Encoding set dei caratteri sconosciuto: '; +?> diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-ja.php b/src/core/libs/phpmailer/language/phpmailer.lang-ja.php new file mode 100755 index 0000000..9e90d63 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-ja.php @@ -0,0 +1,25 @@ +<?php +/** + * PHPMailer language file. + * Japanese Version + * By Mitsuhiro Yoshida - http://mitstek.com/ + * This file is written in EUC-JP. + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = '¾¯¤Ê¤¯¤È¤â1¤Ä¥á¡¼¥ë¥¢¥É¥ì¥¹¤ò' . + '»ØÄꤹ¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£'; +$PHPMAILER_LANG["mailer_not_supported"] = ' ¥á¡¼¥é¡¼¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Æ¤¤¤Þ¤»¤ó¡£'; +$PHPMAILER_LANG["execute"] = '¼Â¹Ô¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿: '; +$PHPMAILER_LANG["instantiate"] = '¥á¡¼¥ë´Ø¿ô¤¬Àµ¾ï¤ËÆ°ºî¤·¤Þ¤»¤ó¤Ç¤·¤¿¡£'; +$PHPMAILER_LANG["authenticate"] = 'SMTP¥¨¥é¡¼: ǧ¾Ú¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿¡£'; +$PHPMAILER_LANG["from_failed"] = '¼¡¤ÎFrom¥¢¥É¥ì¥¹¤Ë´Ö°ã¤¤¤¬¤¢¤ê¤Þ¤¹: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP¥¨¥é¡¼: ¼¡¤Î¼õ¿®¼Ô¥¢¥É¥ì¥¹¤Ë ' . + '´Ö°ã¤¤¤¬¤¢¤ê¤Þ¤¹: '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP¥¨¥é¡¼: ¥Ç¡¼¥¿¤¬¼õ¤±ÉÕ¤±¤é¤ì¤Þ¤»¤ó¤Ç¤·¤¿¡£'; +$PHPMAILER_LANG["connect_host"] = 'SMTP¥¨¥é¡¼: SMTP¥Û¥¹¥È¤ËÀܳ¤Ç¤­¤Þ¤»¤ó¤Ç¤·¤¿¡£'; +$PHPMAILER_LANG["file_access"] = '¥Õ¥¡¥¤¥ë¤Ë¥¢¥¯¥»¥¹¤Ç¤­¤Þ¤»¤ó: '; +$PHPMAILER_LANG["file_open"] = '¥Õ¥¡¥¤¥ë¥¨¥é¡¼: ¥Õ¥¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó: '; +$PHPMAILER_LANG["encoding"] = 'ÉÔÌÀ¤Ê¥¨¥ó¥³¡¼¥Ç¥£¥ó¥°: '; +?> \ No newline at end of file diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-nl.php b/src/core/libs/phpmailer/language/phpmailer.lang-nl.php new file mode 100755 index 0000000..f759a4d --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-nl.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPMailer language file. + * Dutch Version + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'U moet op zijn minst één ontvanger ' . + 'opgeven'; +$PHPMAILER_LANG["mailer_not_supported"] = ' e-mail service wordt niet ondersteund.'; +$PHPMAILER_LANG["execute"] = 'Kan niet worden uitgevoerd: '; +$PHPMAILER_LANG["instantiate"] = 'Kan mail functie niet op gang brengen.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP fout: Ongeldige gebruikersnaam of wachtwoord.'; +$PHPMAILER_LANG["from_failed"] = 'De volgende afzenders zijn ongeldig: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP Fout: Kon email niet verzend ' . + 'naar de volgende ontvangers : '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP Fout: Data niet geaccepteerd.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP Fout: Kan geen verbinding maken met de SMTP server.'; +$PHPMAILER_LANG["file_access"] = 'Bijlage kon niet worden geopend: '; +$PHPMAILER_LANG["file_open"] = 'Bijlage kon niet worden geopend: '; +$PHPMAILER_LANG["encoding"] = 'Onbekende codering: '; +?> diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-no.php b/src/core/libs/phpmailer/language/phpmailer.lang-no.php new file mode 100755 index 0000000..e9a35e4 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-no.php @@ -0,0 +1,23 @@ +<?php +/** + * Norwegian language file. + * English Version + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Du må ha med minst en' . + 'mottager adresse.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailer er ikke supportert.'; +$PHPMAILER_LANG["execute"] = 'Kunne ikke utføre: '; +$PHPMAILER_LANG["instantiate"] = 'Kunne ikke instantiate mail funksjonen.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP Feil: Kunne ikke authentisere.'; +$PHPMAILER_LANG["from_failed"] = 'Følgende Fra feilet: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP Feil: Følgende' . + 'mottagere feilet: '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP Feil: Data ble ikke akseptert.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP Feil: Kunne ikke koble til SMTP host.'; +$PHPMAILER_LANG["file_access"] = 'Kunne ikke få tilgang til filen: '; +$PHPMAILER_LANG["file_open"] = 'Fil feil: Kunne ikke åpne filen: '; +$PHPMAILER_LANG["encoding"] = 'Ukjent encoding: '; +?> diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-pl.php b/src/core/libs/phpmailer/language/phpmailer.lang-pl.php new file mode 100755 index 0000000..3322941 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-pl.php @@ -0,0 +1,24 @@ +<?php +/** + * PHPMailer language file. + * Polish Version, encoding: windows-1250 + * translated from english lang file ver. 1.72 + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Nale¿y podaæ prawid³owy adres email Odbiorcy.'; +$PHPMAILER_LANG["mailer_not_supported"] = 'Wybrana metoda wysy³ki wiadomoœci nie jest obs³ugiwana.'; +$PHPMAILER_LANG["execute"] = 'Nie mo¿na uruchomiæ: '; +$PHPMAILER_LANG["instantiate"] = 'Nie mo¿na wywo³aæ funkcji mail(). SprawdŸ konfiguracjê serwera.'; +$PHPMAILER_LANG["authenticate"] = 'B³¹d SMTP: Nie mo¿na przeprowadziæ autentykacji.'; +$PHPMAILER_LANG["from_failed"] = 'Nastêpuj¹cy adres Nadawcy jest jest nieprawid³owy: '; +$PHPMAILER_LANG["recipients_failed"] = 'B³¹d SMTP: Nastêpuj¹cy ' . + 'odbiorcy s¹ nieprawid³owi: '; +$PHPMAILER_LANG["data_not_accepted"] = 'B³¹d SMTP: Dane nie zosta³y przyjête.'; +$PHPMAILER_LANG["connect_host"] = 'B³¹d SMTP: Nie mo¿na po³¹czyæ siê z wybranym hostem.'; +$PHPMAILER_LANG["file_access"] = 'Brak dostêpu do pliku: '; +$PHPMAILER_LANG["file_open"] = 'Nie mo¿na otworzyæ pliku: '; +$PHPMAILER_LANG["encoding"] = 'Nieznany sposób kodowania znaków: '; + +?> \ No newline at end of file diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-ro.php b/src/core/libs/phpmailer/language/phpmailer.lang-ro.php new file mode 100755 index 0000000..a330b4a --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-ro.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPMailer language file. + * Romanian Version + * @package PHPMailer + * @author Catalin Constantin <catalin@dazoot.ro> + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Trebuie sa adaugati cel putin un recipient (adresa de mail).'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailer nu este suportat.'; +$PHPMAILER_LANG["execute"] = 'Nu pot executa: '; +$PHPMAILER_LANG["instantiate"] = 'Nu am putut instantia functia mail.'; +$PHPMAILER_LANG["authenticate"] = 'Eroare SMTP: Nu a functionat autentificarea.'; +$PHPMAILER_LANG["from_failed"] = 'Urmatoarele adrese From au dat eroare: '; +$PHPMAILER_LANG["recipients_failed"] = 'Eroare SMTP: Urmatoarele adrese de mail au dat eroare: '; +$PHPMAILER_LANG["data_not_accepted"] = 'Eroare SMTP: Continutul mailului nu a fost acceptat.'; +$PHPMAILER_LANG["connect_host"] = 'Eroare SMTP: Nu m-am putut conecta la adresa SMTP.'; +$PHPMAILER_LANG["file_access"] = 'Nu pot accesa fisierul: '; +$PHPMAILER_LANG["file_open"] = 'Eroare de fisier: Nu pot deschide fisierul: '; +$PHPMAILER_LANG["encoding"] = 'Encodare necunoscuta: '; +?> diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-ru.php b/src/core/libs/phpmailer/language/phpmailer.lang-ru.php new file mode 100755 index 0000000..3caf528 --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-ru.php @@ -0,0 +1,23 @@ +<?php +/** + * PHPMailer language file. + * Russian Version by Alexey Chumakov <alex@chumakov.ru> + */ + +$PHPMAILER_LANG = array(); +$PHPMAILER_LANG["provide_address"] = 'Ïîæàëóéñòà, ââåäèòå õîòÿ áû îäèí àäðåñ e-mail ' . + 'ïîëó÷àòåëÿ.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' - ïî÷òîâûé ñåðâåð íå ïîääåðæèâàåòñÿ.'; +$PHPMAILER_LANG["execute"] = 'Íåâîçìîæíî âûïîëíèòü êîìàíäó: '; +$PHPMAILER_LANG["instantiate"] = 'Íåâîçìîæíî çàïóñòèòü ôóíêöèþ mail.'; +$PHPMAILER_LANG["authenticate"] = 'Îøèáêà SMTP: îøèáêà àâòîðèçàöèè.'; +$PHPMAILER_LANG["from_failed"] = 'Íåâåðíûé àäðåñ îòïðàâèòåëÿ: '; +$PHPMAILER_LANG["recipients_failed"] = 'Îøèáêà SMTP: îòïðàâêà ïî ñëåäóþùèì ' . + 'àäðåñàì ïîëó÷àòåëåé íå óäàëàñü: '; +$PHPMAILER_LANG["data_not_accepted"] = 'Îøèáêà SMTP: äàííûå íå ïðèíÿòû.'; +$PHPMAILER_LANG["connect_host"] = 'Îøèáêà SMTP: íå óäàåòñÿ ïîäêëþ÷èòüñÿ ê ñåðâåðó SMTP.'; +$PHPMAILER_LANG["file_access"] = 'Íåò äîñòóïà ê ôàéëó: '; +$PHPMAILER_LANG["file_open"] = 'Ôàéëîâàÿ îøèáêà: íå óäàåòñÿ îòêðûòü ôàéë: '; +$PHPMAILER_LANG["encoding"] = 'Íåèçâåñòíûé âèä êîäèðîâêè: '; +?> + diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-se.php b/src/core/libs/phpmailer/language/phpmailer.lang-se.php new file mode 100755 index 0000000..349c2ce --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-se.php @@ -0,0 +1,24 @@ +<?php +/** + * PHPMailer language file. + * Swedish Version + * Author: Johan Linnér <johan@linner.biz> + */ + +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'Du måste ange minst en ' . + 'mottagares e-postadress.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailer stöds inte.'; +$PHPMAILER_LANG["execute"] = 'Kunde inte köra: '; +$PHPMAILER_LANG["instantiate"] = 'Kunde inte initiera e-postfunktion.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP fel: Kunde inte autentisera.'; +$PHPMAILER_LANG["from_failed"] = 'Följande avsändaradress är felaktig: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP fel: Följande ' . + 'mottagare är felaktig: '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP fel: Data accepterades inte.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP fel: Kunde inte ansluta till SMTP-server.'; +$PHPMAILER_LANG["file_access"] = 'Ingen åtkomst till fil: '; +$PHPMAILER_LANG["file_open"] = 'Fil fel: Kunde inte öppna fil: '; +$PHPMAILER_LANG["encoding"] = 'Okänt encode-format: '; +?> \ No newline at end of file diff --git a/src/core/libs/phpmailer/language/phpmailer.lang-tr.php b/src/core/libs/phpmailer/language/phpmailer.lang-tr.php new file mode 100755 index 0000000..b5f9b5f --- /dev/null +++ b/src/core/libs/phpmailer/language/phpmailer.lang-tr.php @@ -0,0 +1,24 @@ +<?php +/** + * PHPMailer dil dosyasý. + * Türkçe Versiyonu + * ZYAZILIM - Elçin Özel - Can Yýlmaz - Mehmet Benlioðlu +*/ +$PHPMAILER_LANG = array(); + +$PHPMAILER_LANG["provide_address"] = 'En az bir tane mail adresi belirtmek zorundasýnýz ' . + 'alýcýnýn email adresi.'; +$PHPMAILER_LANG["mailer_not_supported"] = ' mailler desteklenmemektedir.'; +$PHPMAILER_LANG["execute"] = 'Çalýþtýrýlamýyor: '; +$PHPMAILER_LANG["instantiate"] = 'Örnek mail fonksiyonu yaratýlamadý.'; +$PHPMAILER_LANG["authenticate"] = 'SMTP Hatasý: Doðrulanamýyor.'; +$PHPMAILER_LANG["from_failed"] = 'Baþarýsýz olan gönderici adresi: '; +$PHPMAILER_LANG["recipients_failed"] = 'SMTP Hatasý: ' . + 'alýcýlara ulaþmadý: '; +$PHPMAILER_LANG["data_not_accepted"] = 'SMTP Hatasý: Veri kabul edilmedi.'; +$PHPMAILER_LANG["connect_host"] = 'SMTP Hatasý: SMTP hosta baðlanýlamýyor.'; +$PHPMAILER_LANG["file_access"] = 'Dosyaya eriþilemiyor: '; +$PHPMAILER_LANG["file_open"] = 'Dosya Hatasý: Dosya açýlamýyor: '; +$PHPMAILER_LANG["encoding"] = 'Bilinmeyen þifreleme: '; + +?> diff --git a/src/core/libs/sql-formatter/lib/SqlFormatter.php b/src/core/libs/sql-formatter/lib/SqlFormatter.php new file mode 100755 index 0000000..82927e4 --- /dev/null +++ b/src/core/libs/sql-formatter/lib/SqlFormatter.php @@ -0,0 +1,1085 @@ +<?php +/** + * SQL Formatter is a collection of utilities for debugging SQL queries. + * It includes methods for formatting, syntax highlighting, removing comments, etc. + * + * @package SqlFormatter + * @author Jeremy Dorn <jeremy@jeremydorn.com> + * @author Florin Patan <florinpatan@gmail.com> + * @copyright 2013 Jeremy Dorn + * @license http://opensource.org/licenses/MIT + * @link http://github.com/jdorn/sql-formatter + * @version 1.2.18 + */ +class SqlFormatter +{ + // Constants for token types + const TOKEN_TYPE_WHITESPACE = 0; + const TOKEN_TYPE_WORD = 1; + const TOKEN_TYPE_QUOTE = 2; + const TOKEN_TYPE_BACKTICK_QUOTE = 3; + const TOKEN_TYPE_RESERVED = 4; + const TOKEN_TYPE_RESERVED_TOPLEVEL = 5; + const TOKEN_TYPE_RESERVED_NEWLINE = 6; + const TOKEN_TYPE_BOUNDARY = 7; + const TOKEN_TYPE_COMMENT = 8; + const TOKEN_TYPE_BLOCK_COMMENT = 9; + const TOKEN_TYPE_NUMBER = 10; + const TOKEN_TYPE_ERROR = 11; + const TOKEN_TYPE_VARIABLE = 12; + + // Constants for different components of a token + const TOKEN_TYPE = 0; + const TOKEN_VALUE = 1; + + // Reserved words (for syntax highlighting) + protected static $reserved = array( + 'ACCESSIBLE', 'ACTION', 'AGAINST', 'AGGREGATE', 'ALGORITHM', 'ALL', 'ALTER', 'ANALYSE', 'ANALYZE', 'AS', 'ASC', + 'AUTOCOMMIT', 'AUTO_INCREMENT', 'BACKUP', 'BEGIN', 'BETWEEN', 'BINLOG', 'BOTH', 'CASCADE', 'CASE', 'CHANGE', 'CHANGED', 'CHARACTER SET', + 'CHARSET', 'CHECK', 'CHECKSUM', 'COLLATE', 'COLLATION', 'COLUMN', 'COLUMNS', 'COMMENT', 'COMMIT', 'COMMITTED', 'COMPRESSED', 'CONCURRENT', + 'CONSTRAINT', 'CONTAINS', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT_TIMESTAMP', 'DATABASE', 'DATABASES', 'DAY', 'DAY_HOUR', 'DAY_MINUTE', + 'DAY_SECOND', 'DEFAULT', 'DEFINER', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DIV', + 'DO', 'DUMPFILE', 'DUPLICATE', 'DYNAMIC', 'ELSE', 'ENCLOSED', 'END', 'ENGINE', 'ENGINE_TYPE', 'ENGINES', 'ESCAPE', 'ESCAPED', 'EVENTS', 'EXEC', + 'EXECUTE', 'EXISTS', 'EXPLAIN', 'EXTENDED', 'FAST', 'FIELDS', 'FILE', 'FIRST', 'FIXED', 'FLUSH', 'FOR', 'FORCE', 'FOREIGN', 'FULL', 'FULLTEXT', + 'FUNCTION', 'GLOBAL', 'GRANT', 'GRANTS', 'GROUP_CONCAT', 'HEAP', 'HIGH_PRIORITY', 'HOSTS', 'HOUR', 'HOUR_MINUTE', + 'HOUR_SECOND', 'IDENTIFIED', 'IF', 'IFNULL', 'IGNORE', 'IN', 'INDEX', 'INDEXES', 'INFILE', 'INSERT', 'INSERT_ID', 'INSERT_METHOD', 'INTERVAL', + 'INTO', 'INVOKER', 'IS', 'ISOLATION', 'KEY', 'KEYS', 'KILL', 'LAST_INSERT_ID', 'LEADING', 'LEVEL', 'LIKE', 'LINEAR', + 'LINES', 'LOAD', 'LOCAL', 'LOCK', 'LOCKS', 'LOGS', 'LOW_PRIORITY', 'MARIA', 'MASTER', 'MASTER_CONNECT_RETRY', 'MASTER_HOST', 'MASTER_LOG_FILE', + 'MATCH','MAX_CONNECTIONS_PER_HOUR', 'MAX_QUERIES_PER_HOUR', 'MAX_ROWS', 'MAX_UPDATES_PER_HOUR', 'MAX_USER_CONNECTIONS', + 'MEDIUM', 'MERGE', 'MINUTE', 'MINUTE_SECOND', 'MIN_ROWS', 'MODE', 'MODIFY', + 'MONTH', 'MRG_MYISAM', 'MYISAM', 'NAMES', 'NATURAL', 'NOT', 'NOW()','NULL', 'OFFSET', 'ON', 'OPEN', 'OPTIMIZE', 'OPTION', 'OPTIONALLY', + 'ON UPDATE', 'ON DELETE', 'OUTFILE', 'PACK_KEYS', 'PAGE', 'PARTIAL', 'PARTITION', 'PARTITIONS', 'PASSWORD', 'PRIMARY', 'PRIVILEGES', 'PROCEDURE', + 'PROCESS', 'PROCESSLIST', 'PURGE', 'QUICK', 'RANGE', 'RAID0', 'RAID_CHUNKS', 'RAID_CHUNKSIZE','RAID_TYPE', 'READ', 'READ_ONLY', + 'READ_WRITE', 'REFERENCES', 'REGEXP', 'RELOAD', 'RENAME', 'REPAIR', 'REPEATABLE', 'REPLACE', 'REPLICATION', 'RESET', 'RESTORE', 'RESTRICT', + 'RETURN', 'RETURNS', 'REVOKE', 'RLIKE', 'ROLLBACK', 'ROW', 'ROWS', 'ROW_FORMAT', 'SECOND', 'SECURITY', 'SEPARATOR', + 'SERIALIZABLE', 'SESSION', 'SHARE', 'SHOW', 'SHUTDOWN', 'SLAVE', 'SONAME', 'SOUNDS', 'SQL', 'SQL_AUTO_IS_NULL', 'SQL_BIG_RESULT', + 'SQL_BIG_SELECTS', 'SQL_BIG_TABLES', 'SQL_BUFFER_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_LOG_BIN', 'SQL_LOG_OFF', 'SQL_LOG_UPDATE', + 'SQL_LOW_PRIORITY_UPDATES', 'SQL_MAX_JOIN_SIZE', 'SQL_QUOTE_SHOW_CREATE', 'SQL_SAFE_UPDATES', 'SQL_SELECT_LIMIT', 'SQL_SLAVE_SKIP_COUNTER', + 'SQL_SMALL_RESULT', 'SQL_WARNINGS', 'SQL_CACHE', 'SQL_NO_CACHE', 'START', 'STARTING', 'STATUS', 'STOP', 'STORAGE', + 'STRAIGHT_JOIN', 'STRING', 'STRIPED', 'SUPER', 'TABLE', 'TABLES', 'TEMPORARY', 'TERMINATED', 'THEN', 'TO', 'TRAILING', 'TRANSACTIONAL', 'TRUE', + 'TRUNCATE', 'TYPE', 'TYPES', 'UNCOMMITTED', 'UNIQUE', 'UNLOCK', 'UNSIGNED', 'USAGE', 'USE', 'USING', 'VARIABLES', + 'VIEW', 'WHEN', 'WITH', 'WORK', 'WRITE', 'YEAR_MONTH' + ); + + // For SQL formatting + // These keywords will all be on their own line + protected static $reserved_toplevel = array( + 'SELECT', 'FROM', 'WHERE', 'SET', 'ORDER BY', 'GROUP BY', 'LIMIT', 'DROP', + 'VALUES', 'UPDATE', 'HAVING', 'ADD', 'AFTER', 'ALTER TABLE', 'DELETE FROM', 'UNION ALL', 'UNION', 'EXCEPT', 'INTERSECT' + ); + + protected static $reserved_newline = array( + 'LEFT OUTER JOIN', 'RIGHT OUTER JOIN', 'LEFT JOIN', 'RIGHT JOIN', 'OUTER JOIN', 'INNER JOIN', 'JOIN', 'XOR', 'OR', 'AND' + ); + + protected static $functions = array ( + 'ABS', 'ACOS', 'ADDDATE', 'ADDTIME', 'AES_DECRYPT', 'AES_ENCRYPT', 'AREA', 'ASBINARY', 'ASCII', 'ASIN', 'ASTEXT', 'ATAN', 'ATAN2', + 'AVG', 'BDMPOLYFROMTEXT', 'BDMPOLYFROMWKB', 'BDPOLYFROMTEXT', 'BDPOLYFROMWKB', 'BENCHMARK', 'BIN', 'BIT_AND', 'BIT_COUNT', 'BIT_LENGTH', + 'BIT_OR', 'BIT_XOR', 'BOUNDARY', 'BUFFER', 'CAST', 'CEIL', 'CEILING', 'CENTROID', 'CHAR', 'CHARACTER_LENGTH', 'CHARSET', 'CHAR_LENGTH', + 'COALESCE', 'COERCIBILITY', 'COLLATION', 'COMPRESS', 'CONCAT', 'CONCAT_WS', 'CONNECTION_ID', 'CONTAINS', 'CONV', 'CONVERT', 'CONVERT_TZ', + 'CONVEXHULL', 'COS', 'COT', 'COUNT', 'CRC32', 'CROSSES', 'CURDATE', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER', + 'CURTIME', 'DATABASE', 'DATE', 'DATEDIFF', 'DATE_ADD', 'DATE_DIFF', 'DATE_FORMAT', 'DATE_SUB', 'DAY', 'DAYNAME', 'DAYOFMONTH', 'DAYOFWEEK', + 'DAYOFYEAR', 'DECODE', 'DEFAULT', 'DEGREES', 'DES_DECRYPT', 'DES_ENCRYPT', 'DIFFERENCE', 'DIMENSION', 'DISJOINT', 'DISTANCE', 'ELT', 'ENCODE', + 'ENCRYPT', 'ENDPOINT', 'ENVELOPE', 'EQUALS', 'EXP', 'EXPORT_SET', 'EXTERIORRING', 'EXTRACT', 'EXTRACTVALUE', 'FIELD', 'FIND_IN_SET', 'FLOOR', + 'FORMAT', 'FOUND_ROWS', 'FROM_DAYS', 'FROM_UNIXTIME', 'GEOMCOLLFROMTEXT', 'GEOMCOLLFROMWKB', 'GEOMETRYCOLLECTION', 'GEOMETRYCOLLECTIONFROMTEXT', + 'GEOMETRYCOLLECTIONFROMWKB', 'GEOMETRYFROMTEXT', 'GEOMETRYFROMWKB', 'GEOMETRYN', 'GEOMETRYTYPE', 'GEOMFROMTEXT', 'GEOMFROMWKB', 'GET_FORMAT', + 'GET_LOCK', 'GLENGTH', 'GREATEST', 'GROUP_CONCAT', 'GROUP_UNIQUE_USERS', 'HEX', 'HOUR', 'IF', 'IFNULL', 'INET_ATON', 'INET_NTOA', 'INSERT', 'INSTR', + 'INTERIORRINGN', 'INTERSECTION', 'INTERSECTS', 'INTERVAL', 'ISCLOSED', 'ISEMPTY', 'ISNULL', 'ISRING', 'ISSIMPLE', 'IS_FREE_LOCK', 'IS_USED_LOCK', + 'LAST_DAY', 'LAST_INSERT_ID', 'LCASE', 'LEAST', 'LEFT', 'LENGTH', 'LINEFROMTEXT', 'LINEFROMWKB', 'LINESTRING', 'LINESTRINGFROMTEXT', 'LINESTRINGFROMWKB', + 'LN', 'LOAD_FILE', 'LOCALTIME', 'LOCALTIMESTAMP', 'LOCATE', 'LOG', 'LOG10', 'LOG2', 'LOWER', 'LPAD', 'LTRIM', 'MAKEDATE', 'MAKETIME', 'MAKE_SET', + 'MASTER_POS_WAIT', 'MAX', 'MBRCONTAINS', 'MBRDISJOINT', 'MBREQUAL', 'MBRINTERSECTS', 'MBROVERLAPS', 'MBRTOUCHES', 'MBRWITHIN', 'MD5', 'MICROSECOND', + 'MID', 'MIN', 'MINUTE', 'MLINEFROMTEXT', 'MLINEFROMWKB', 'MOD', 'MONTH', 'MONTHNAME', 'MPOINTFROMTEXT', 'MPOINTFROMWKB', 'MPOLYFROMTEXT', 'MPOLYFROMWKB', + 'MULTILINESTRING', 'MULTILINESTRINGFROMTEXT', 'MULTILINESTRINGFROMWKB', 'MULTIPOINT', 'MULTIPOINTFROMTEXT', 'MULTIPOINTFROMWKB', 'MULTIPOLYGON', + 'MULTIPOLYGONFROMTEXT', 'MULTIPOLYGONFROMWKB', 'NAME_CONST', 'NULLIF', 'NUMGEOMETRIES', 'NUMINTERIORRINGS', 'NUMPOINTS', 'OCT', 'OCTET_LENGTH', + 'OLD_PASSWORD', 'ORD', 'OVERLAPS', 'PASSWORD', 'PERIOD_ADD', 'PERIOD_DIFF', 'PI', 'POINT', 'POINTFROMTEXT', 'POINTFROMWKB', 'POINTN', 'POINTONSURFACE', + 'POLYFROMTEXT', 'POLYFROMWKB', 'POLYGON', 'POLYGONFROMTEXT', 'POLYGONFROMWKB', 'POSITION', 'POW', 'POWER', 'QUARTER', 'QUOTE', 'RADIANS', 'RAND', + 'RELATED', 'RELEASE_LOCK', 'REPEAT', 'REPLACE', 'REVERSE', 'RIGHT', 'ROUND', 'ROW_COUNT', 'RPAD', 'RTRIM', 'SCHEMA', 'SECOND', 'SEC_TO_TIME', + 'SESSION_USER', 'SHA', 'SHA1', 'SIGN', 'SIN', 'SLEEP', 'SOUNDEX', 'SPACE', 'SQRT', 'SRID', 'STARTPOINT', 'STD', 'STDDEV', 'STDDEV_POP', 'STDDEV_SAMP', + 'STRCMP', 'STR_TO_DATE', 'SUBDATE', 'SUBSTR', 'SUBSTRING', 'SUBSTRING_INDEX', 'SUBTIME', 'SUM', 'SYMDIFFERENCE', 'SYSDATE', 'SYSTEM_USER', 'TAN', + 'TIME', 'TIMEDIFF', 'TIMESTAMP', 'TIMESTAMPADD', 'TIMESTAMPDIFF', 'TIME_FORMAT', 'TIME_TO_SEC', 'TOUCHES', 'TO_DAYS', 'TRIM', 'TRUNCATE', 'UCASE', + 'UNCOMPRESS', 'UNCOMPRESSED_LENGTH', 'UNHEX', 'UNIQUE_USERS', 'UNIX_TIMESTAMP', 'UPDATEXML', 'UPPER', 'USER', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', + 'UUID', 'VARIANCE', 'VAR_POP', 'VAR_SAMP', 'VERSION', 'WEEK', 'WEEKDAY', 'WEEKOFYEAR', 'WITHIN', 'X', 'Y', 'YEAR', 'YEARWEEK' + ); + + // Punctuation that can be used as a boundary between other tokens + protected static $boundaries = array(',', ';',':', ')', '(', '.', '=', '<', '>', '+', '-', '*', '/', '!', '^', '%', '|', '&', '#'); + + // For HTML syntax highlighting + // Styles applied to different token types + public static $quote_attributes = 'style="color: blue;"'; + public static $backtick_quote_attributes = 'style="color: purple;"'; + public static $reserved_attributes = 'style="font-weight:bold;"'; + public static $boundary_attributes = ''; + public static $number_attributes = 'style="color: green;"'; + public static $word_attributes = 'style="color: #333;"'; + public static $error_attributes = 'style="background-color: red;"'; + public static $comment_attributes = 'style="color: #aaa;"'; + public static $variable_attributes = 'style="color: orange;"'; + public static $pre_attributes = 'style="color: black; background-color: white;"'; + + // Boolean - whether or not the current environment is the CLI + // This affects the type of syntax highlighting + // If not defined, it will be determined automatically + public static $cli; + + // For CLI syntax highlighting + public static $cli_quote = "\x1b[34;1m"; + public static $cli_backtick_quote = "\x1b[35;1m"; + public static $cli_reserved = "\x1b[37m"; + public static $cli_boundary = ""; + public static $cli_number = "\x1b[32;1m"; + public static $cli_word = ""; + public static $cli_error = "\x1b[31;1;7m"; + public static $cli_comment = "\x1b[30;1m"; + public static $cli_functions = "\x1b[37m"; + public static $cli_variable = "\x1b[36;1m"; + + // The tab character to use when formatting SQL + public static $tab = ' '; + + // This flag tells us if queries need to be enclosed in <pre> tags + public static $use_pre = true; + + // This flag tells us if SqlFormatted has been initialized + protected static $init; + + // Regular expressions for tokenizing + protected static $regex_boundaries; + protected static $regex_reserved; + protected static $regex_reserved_newline; + protected static $regex_reserved_toplevel; + protected static $regex_function; + + // Cache variables + // Only tokens shorter than this size will be cached. Somewhere between 10 and 20 seems to work well for most cases. + public static $max_cachekey_size = 15; + protected static $token_cache = array(); + protected static $cache_hits = 0; + protected static $cache_misses = 0; + + /** + * Get stats about the token cache + * @return Array An array containing the keys 'hits', 'misses', 'entries', and 'size' in bytes + */ + public static function getCacheStats() + { + return array( + 'hits'=>self::$cache_hits, + 'misses'=>self::$cache_misses, + 'entries'=>count(self::$token_cache), + 'size'=>strlen(serialize(self::$token_cache)) + ); + } + + /** + * Stuff that only needs to be done once. Builds regular expressions and sorts the reserved words. + */ + protected static function init() + { + if (self::$init) return; + + // Sort reserved word list from longest word to shortest, 3x faster than usort + $reservedMap = array_combine(self::$reserved, array_map('strlen', self::$reserved)); + arsort($reservedMap); + self::$reserved = array_keys($reservedMap); + + // Set up regular expressions + self::$regex_boundaries = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$boundaries)).')'; + self::$regex_reserved = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved)).')'; + self::$regex_reserved_toplevel = str_replace(' ','\\s+','('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved_toplevel)).')'); + self::$regex_reserved_newline = str_replace(' ','\\s+','('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$reserved_newline)).')'); + + self::$regex_function = '('.implode('|',array_map(array(__CLASS__, 'quote_regex'),self::$functions)).')'; + + self::$init = true; + } + + /** + * Return the next token and token type in a SQL string. + * Quoted strings, comments, reserved words, whitespace, and punctuation are all their own tokens. + * + * @param String $string The SQL string + * @param array $previous The result of the previous getNextToken() call + * + * @return Array An associative array containing the type and value of the token. + */ + protected static function getNextToken($string, $previous = null) + { + // Whitespace + if (preg_match('/^\s+/',$string,$matches)) { + return array( + self::TOKEN_VALUE => $matches[0], + self::TOKEN_TYPE=>self::TOKEN_TYPE_WHITESPACE + ); + } + + // Comment + if ($string[0] === '#' || (isset($string[1])&&($string[0]==='-'&&$string[1]==='-') || ($string[0]==='/'&&$string[1]==='*'))) { + // Comment until end of line + if ($string[0] === '-' || $string[0] === '#') { + $last = strpos($string, "\n"); + $type = self::TOKEN_TYPE_COMMENT; + } else { // Comment until closing comment tag + $last = strpos($string, "*/", 2) + 2; + $type = self::TOKEN_TYPE_BLOCK_COMMENT; + } + + if ($last === false) { + $last = strlen($string); + } + + return array( + self::TOKEN_VALUE => substr($string, 0, $last), + self::TOKEN_TYPE => $type + ); + } + + // Quoted String + if ($string[0]==='"' || $string[0]==='\'' || $string[0]==='`' || $string[0]==='[') { + $return = array( + self::TOKEN_TYPE => (($string[0]==='`' || $string[0]==='[')? self::TOKEN_TYPE_BACKTICK_QUOTE : self::TOKEN_TYPE_QUOTE), + self::TOKEN_VALUE => self::getQuotedString($string) + ); + + return $return; + } + + // User-defined Variable + if ($string[0] === '@' && isset($string[1])) { + $ret = array( + self::TOKEN_VALUE => null, + self::TOKEN_TYPE => self::TOKEN_TYPE_VARIABLE + ); + + // If the variable name is quoted + if ($string[1]==='"' || $string[1]==='\'' || $string[1]==='`') { + $ret[self::TOKEN_VALUE] = '@'.self::getQuotedString(substr($string,1)); + } + // Non-quoted variable name + else { + preg_match('/^(@[a-zA-Z0-9\._\$]+)/',$string,$matches); + if ($matches) { + $ret[self::TOKEN_VALUE] = $matches[1]; + } + } + + if($ret[self::TOKEN_VALUE] !== null) return $ret; + } + + // Number (decimal, binary, or hex) + if (preg_match('/^([0-9]+(\.[0-9]+)?|0x[0-9a-fA-F]+|0b[01]+)($|\s|"\'`|'.self::$regex_boundaries.')/',$string,$matches)) { + return array( + self::TOKEN_VALUE => $matches[1], + self::TOKEN_TYPE=>self::TOKEN_TYPE_NUMBER + ); + } + + // Boundary Character (punctuation and symbols) + if (preg_match('/^('.self::$regex_boundaries.')/',$string,$matches)) { + return array( + self::TOKEN_VALUE => $matches[1], + self::TOKEN_TYPE => self::TOKEN_TYPE_BOUNDARY + ); + } + + // A reserved word cannot be preceded by a '.' + // this makes it so in "mytable.from", "from" is not considered a reserved word + if (!$previous || !isset($previous[self::TOKEN_VALUE]) || $previous[self::TOKEN_VALUE] !== '.') { + $upper = strtoupper($string); + // Top Level Reserved Word + if (preg_match('/^('.self::$regex_reserved_toplevel.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) { + return array( + self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED_TOPLEVEL, + self::TOKEN_VALUE=>substr($string,0,strlen($matches[1])) + ); + } + // Newline Reserved Word + if (preg_match('/^('.self::$regex_reserved_newline.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) { + return array( + self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED_NEWLINE, + self::TOKEN_VALUE=>substr($string,0,strlen($matches[1])) + ); + } + // Other Reserved Word + if (preg_match('/^('.self::$regex_reserved.')($|\s|'.self::$regex_boundaries.')/', $upper,$matches)) { + return array( + self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED, + self::TOKEN_VALUE=>substr($string,0,strlen($matches[1])) + ); + } + } + + // A function must be suceeded by '(' + // this makes it so "count(" is considered a function, but "count" alone is not + $upper = strtoupper($string); + // function + if (preg_match('/^('.self::$regex_function.'[(]|\s|[)])/', $upper,$matches)) { + return array( + self::TOKEN_TYPE=>self::TOKEN_TYPE_RESERVED, + self::TOKEN_VALUE=>substr($string,0,strlen($matches[1])-1) + ); + } + + // Non reserved word + preg_match('/^(.*?)($|\s|["\'`]|'.self::$regex_boundaries.')/',$string,$matches); + + return array( + self::TOKEN_VALUE => $matches[1], + self::TOKEN_TYPE => self::TOKEN_TYPE_WORD + ); + } + + protected static function getQuotedString($string) + { + $ret = null; + + // This checks for the following patterns: + // 1. backtick quoted string using `` to escape + // 2. square bracket quoted string (SQL Server) using ]] to escape + // 3. double quoted string using "" or \" to escape + // 4. single quoted string using '' or \' to escape + if ( preg_match('/^(((`[^`]*($|`))+)|((\[[^\]]*($|\]))(\][^\]]*($|\]))*)|(("[^"\\\\]*(?:\\\\.[^"\\\\]*)*("|$))+)|((\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*(\'|$))+))/s', $string, $matches)) { + $ret = $matches[1]; + } + + return $ret; + } + + /** + * Takes a SQL string and breaks it into tokens. + * Each token is an associative array with type and value. + * + * @param String $string The SQL string + * + * @return Array An array of tokens. + */ + protected static function tokenize($string) + { + self::init(); + + $tokens = array(); + + // Used for debugging if there is an error while tokenizing the string + $original_length = strlen($string); + + // Used to make sure the string keeps shrinking on each iteration + $old_string_len = strlen($string) + 1; + + $token = null; + + $current_length = strlen($string); + + // Keep processing the string until it is empty + while ($current_length) { + // If the string stopped shrinking, there was a problem + if ($old_string_len <= $current_length) { + $tokens[] = array( + self::TOKEN_VALUE=>$string, + self::TOKEN_TYPE=>self::TOKEN_TYPE_ERROR + ); + + return $tokens; + } + $old_string_len = $current_length; + + // Determine if we can use caching + if ($current_length >= self::$max_cachekey_size) { + $cacheKey = substr($string,0,self::$max_cachekey_size); + } else { + $cacheKey = false; + } + + // See if the token is already cached + if ($cacheKey && isset(self::$token_cache[$cacheKey])) { + // Retrieve from cache + $token = self::$token_cache[$cacheKey]; + $token_length = strlen($token[self::TOKEN_VALUE]); + self::$cache_hits++; + } else { + // Get the next token and the token type + $token = self::getNextToken($string, $token); + $token_length = strlen($token[self::TOKEN_VALUE]); + self::$cache_misses++; + + // If the token is shorter than the max length, store it in cache + if ($cacheKey && $token_length < self::$max_cachekey_size) { + self::$token_cache[$cacheKey] = $token; + } + } + + $tokens[] = $token; + + // Advance the string + $string = substr($string, $token_length); + + $current_length -= $token_length; + } + + return $tokens; + } + + /** + * Format the whitespace in a SQL string to make it easier to read. + * + * @param String $string The SQL string + * @param boolean $highlight If true, syntax highlighting will also be performed + * + * @return String The SQL string with HTML styles and formatting wrapped in a <pre> tag + */ + public static function format($string, $highlight=true) + { + // This variable will be populated with formatted html + $return = ''; + + // Use an actual tab while formatting and then switch out with self::$tab at the end + $tab = "\t"; + + $indent_level = 0; + $newline = false; + $inline_parentheses = false; + $increase_special_indent = false; + $increase_block_indent = false; + $indent_types = array(); + $added_newline = false; + $inline_count = 0; + $inline_indented = false; + $clause_limit = false; + + // Tokenize String + $original_tokens = self::tokenize($string); + + // Remove existing whitespace + $tokens = array(); + foreach ($original_tokens as $i=>$token) { + if ($token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) { + $token['i'] = $i; + $tokens[] = $token; + } + } + + // Format token by token + foreach ($tokens as $i=>$token) { + // Get highlighted token if doing syntax highlighting + if ($highlight) { + $highlighted = self::highlightToken($token); + } else { // If returning raw text + $highlighted = $token[self::TOKEN_VALUE]; + } + + // If we are increasing the special indent level now + if ($increase_special_indent) { + $indent_level++; + $increase_special_indent = false; + array_unshift($indent_types,'special'); + } + // If we are increasing the block indent level now + if ($increase_block_indent) { + $indent_level++; + $increase_block_indent = false; + array_unshift($indent_types,'block'); + } + + // If we need a new line before the token + if ($newline) { + $return .= "\n" . str_repeat($tab, $indent_level); + $newline = false; + $added_newline = true; + } else { + $added_newline = false; + } + + // Display comments directly where they appear in the source + if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) { + if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) { + $indent = str_repeat($tab,$indent_level); + $return .= "\n" . $indent; + $highlighted = str_replace("\n","\n".$indent,$highlighted); + } + + $return .= $highlighted; + $newline = true; + continue; + } + + if ($inline_parentheses) { + // End of inline parentheses + if ($token[self::TOKEN_VALUE] === ')') { + $return = rtrim($return,' '); + + if ($inline_indented) { + array_shift($indent_types); + $indent_level --; + $return .= "\n" . str_repeat($tab, $indent_level); + } + + $inline_parentheses = false; + + $return .= $highlighted . ' '; + continue; + } + + if ($token[self::TOKEN_VALUE] === ',') { + if ($inline_count >= 30) { + $inline_count = 0; + $newline = true; + } + } + + $inline_count += strlen($token[self::TOKEN_VALUE]); + } + + // Opening parentheses increase the block indent level and start a new line + if ($token[self::TOKEN_VALUE] === '(') { + // First check if this should be an inline parentheses block + // Examples are "NOW()", "COUNT(*)", "int(10)", key(`somecolumn`), DECIMAL(7,2) + // Allow up to 3 non-whitespace tokens inside inline parentheses + $length = 0; + for ($j=1;$j<=250;$j++) { + // Reached end of string + if (!isset($tokens[$i+$j])) break; + + $next = $tokens[$i+$j]; + + // Reached closing parentheses, able to inline it + if ($next[self::TOKEN_VALUE] === ')') { + $inline_parentheses = true; + $inline_count = 0; + $inline_indented = false; + break; + } + + // Reached an invalid token for inline parentheses + if ($next[self::TOKEN_VALUE]===';' || $next[self::TOKEN_VALUE]==='(') { + break; + } + + // Reached an invalid token type for inline parentheses + if ($next[self::TOKEN_TYPE]===self::TOKEN_TYPE_RESERVED_TOPLEVEL || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_RESERVED_NEWLINE || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_COMMENT || $next[self::TOKEN_TYPE]===self::TOKEN_TYPE_BLOCK_COMMENT) { + break; + } + + $length += strlen($next[self::TOKEN_VALUE]); + } + + if ($inline_parentheses && $length > 30) { + $increase_block_indent = true; + $inline_indented = true; + $newline = true; + } + + // Take out the preceding space unless there was whitespace there in the original query + if (isset($original_tokens[$token['i']-1]) && $original_tokens[$token['i']-1][self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) { + $return = rtrim($return,' '); + } + + if (!$inline_parentheses) { + $increase_block_indent = true; + // Add a newline after the parentheses + $newline = true; + } + + } + + // Closing parentheses decrease the block indent level + elseif ($token[self::TOKEN_VALUE] === ')') { + // Remove whitespace before the closing parentheses + $return = rtrim($return,' '); + + $indent_level--; + + // Reset indent level + while ($j=array_shift($indent_types)) { + if ($j==='special') { + $indent_level--; + } else { + break; + } + } + + if ($indent_level < 0) { + // This is an error + $indent_level = 0; + + if ($highlight) { + $return .= "\n".self::highlightError($token[self::TOKEN_VALUE]); + continue; + } + } + + // Add a newline before the closing parentheses (if not already added) + if (!$added_newline) { + $return .= "\n" . str_repeat($tab, $indent_level); + } + } + + // Top level reserved words start a new line and increase the special indent level + elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_TOPLEVEL) { + $increase_special_indent = true; + + // If the last indent type was 'special', decrease the special indent for this round + reset($indent_types); + if (current($indent_types)==='special') { + $indent_level--; + array_shift($indent_types); + } + + // Add a newline after the top level reserved word + $newline = true; + // Add a newline before the top level reserved word (if not already added) + if (!$added_newline) { + $return .= "\n" . str_repeat($tab, $indent_level); + } + // If we already added a newline, redo the indentation since it may be different now + else { + $return = rtrim($return,$tab).str_repeat($tab, $indent_level); + } + + // If the token may have extra whitespace + if (strpos($token[self::TOKEN_VALUE],' ')!==false || strpos($token[self::TOKEN_VALUE],"\n")!==false || strpos($token[self::TOKEN_VALUE],"\t")!==false) { + $highlighted = preg_replace('/\s+/',' ',$highlighted); + } + //if SQL 'LIMIT' clause, start variable to reset newline + if ($token[self::TOKEN_VALUE] === 'LIMIT' && !$inline_parentheses) { + $clause_limit = true; + } + } + + // Checks if we are out of the limit clause + elseif ($clause_limit && $token[self::TOKEN_VALUE] !== "," && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_NUMBER && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) { + $clause_limit = false; + } + + // Commas start a new line (unless within inline parentheses or SQL 'LIMIT' clause) + elseif ($token[self::TOKEN_VALUE] === ',' && !$inline_parentheses) { + //If the previous TOKEN_VALUE is 'LIMIT', resets new line + if ($clause_limit === true) { + $newline = false; + $clause_limit = false; + } + // All other cases of commas + else { + $newline = true; + } + } + + // Newline reserved words start a new line + elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_NEWLINE) { + // Add a newline before the reserved word (if not already added) + if (!$added_newline) { + $return .= "\n" . str_repeat($tab, $indent_level); + } + + // If the token may have extra whitespace + if (strpos($token[self::TOKEN_VALUE],' ')!==false || strpos($token[self::TOKEN_VALUE],"\n")!==false || strpos($token[self::TOKEN_VALUE],"\t")!==false) { + $highlighted = preg_replace('/\s+/',' ',$highlighted); + } + } + + // Multiple boundary characters in a row should not have spaces between them (not including parentheses) + elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BOUNDARY) { + if (isset($tokens[$i-1]) && $tokens[$i-1][self::TOKEN_TYPE] === self::TOKEN_TYPE_BOUNDARY) { + if (isset($original_tokens[$token['i']-1]) && $original_tokens[$token['i']-1][self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE) { + $return = rtrim($return,' '); + } + } + } + + // If the token shouldn't have a space before it + if ($token[self::TOKEN_VALUE] === '.' || $token[self::TOKEN_VALUE] === ',' || $token[self::TOKEN_VALUE] === ';') { + $return = rtrim($return, ' '); + } + + $return .= $highlighted.' '; + + // If the token shouldn't have a space after it + if ($token[self::TOKEN_VALUE] === '(' || $token[self::TOKEN_VALUE] === '.') { + $return = rtrim($return,' '); + } + + // If this is the "-" of a negative number, it shouldn't have a space after it + if($token[self::TOKEN_VALUE] === '-' && isset($tokens[$i+1]) && $tokens[$i+1][self::TOKEN_TYPE] === self::TOKEN_TYPE_NUMBER && isset($tokens[$i-1])) { + $prev = $tokens[$i-1][self::TOKEN_TYPE]; + if($prev !== self::TOKEN_TYPE_QUOTE && $prev !== self::TOKEN_TYPE_BACKTICK_QUOTE && $prev !== self::TOKEN_TYPE_WORD && $prev !== self::TOKEN_TYPE_NUMBER) { + $return = rtrim($return,' '); + } + } + } + + // If there are unmatched parentheses + if ($highlight && array_search('block',$indent_types) !== false) { + $return .= "\n".self::highlightError("WARNING: unclosed parentheses or section"); + } + + // Replace tab characters with the configuration tab character + $return = trim(str_replace("\t",self::$tab,$return)); + + if ($highlight) { + $return = self::output($return); + } + + return $return; + } + + /** + * Add syntax highlighting to a SQL string + * + * @param String $string The SQL string + * + * @return String The SQL string with HTML styles applied + */ + public static function highlight($string) + { + $tokens = self::tokenize($string); + + $return = ''; + + foreach ($tokens as $token) { + $return .= self::highlightToken($token); + } + + return self::output($return); + } + + /** + * Split a SQL string into multiple queries. + * Uses ";" as a query delimiter. + * + * @param String $string The SQL string + * + * @return Array An array of individual query strings without trailing semicolons + */ + public static function splitQuery($string) + { + $queries = array(); + $current_query = ''; + $empty = true; + + $tokens = self::tokenize($string); + + foreach ($tokens as $token) { + // If this is a query separator + if ($token[self::TOKEN_VALUE] === ';') { + if (!$empty) { + $queries[] = $current_query.';'; + } + $current_query = ''; + $empty = true; + continue; + } + + // If this is a non-empty character + if ($token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_WHITESPACE && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_COMMENT && $token[self::TOKEN_TYPE] !== self::TOKEN_TYPE_BLOCK_COMMENT) { + $empty = false; + } + + $current_query .= $token[self::TOKEN_VALUE]; + } + + if (!$empty) { + $queries[] = trim($current_query); + } + + return $queries; + } + + /** + * Remove all comments from a SQL string + * + * @param String $string The SQL string + * + * @return String The SQL string without comments + */ + public static function removeComments($string) + { + $result = ''; + + $tokens = self::tokenize($string); + + foreach ($tokens as $token) { + // Skip comment tokens + if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) { + continue; + } + + $result .= $token[self::TOKEN_VALUE]; + } + $result = self::format( $result,false); + + return $result; + } + + /** + * Compress a query by collapsing white space and removing comments + * + * @param String $string The SQL string + * + * @return String The SQL string without comments + */ + public static function compress($string) + { + $result = ''; + + $tokens = self::tokenize($string); + + $whitespace = true; + foreach ($tokens as $token) { + // Skip comment tokens + if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_COMMENT || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_BLOCK_COMMENT) { + continue; + } + // Remove extra whitespace in reserved words (e.g "OUTER JOIN" becomes "OUTER JOIN") + elseif ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_NEWLINE || $token[self::TOKEN_TYPE] === self::TOKEN_TYPE_RESERVED_TOPLEVEL) { + $token[self::TOKEN_VALUE] = preg_replace('/\s+/',' ',$token[self::TOKEN_VALUE]); + } + + if ($token[self::TOKEN_TYPE] === self::TOKEN_TYPE_WHITESPACE) { + // If the last token was whitespace, don't add another one + if ($whitespace) { + continue; + } else { + $whitespace = true; + // Convert all whitespace to a single space + $token[self::TOKEN_VALUE] = ' '; + } + } else { + $whitespace = false; + } + + $result .= $token[self::TOKEN_VALUE]; + } + + return rtrim($result); + } + + /** + * Highlights a token depending on its type. + * + * @param Array $token An associative array containing type and value. + * + * @return String HTML code of the highlighted token. + */ + protected static function highlightToken($token) + { + $type = $token[self::TOKEN_TYPE]; + + if (self::is_cli()) { + $token = $token[self::TOKEN_VALUE]; + } else { + if (defined('ENT_IGNORE')) { + $token = htmlentities($token[self::TOKEN_VALUE],ENT_COMPAT | ENT_IGNORE ,'UTF-8'); + } else { + $token = htmlentities($token[self::TOKEN_VALUE],ENT_COMPAT,'UTF-8'); + } + } + + if ($type===self::TOKEN_TYPE_BOUNDARY) { + return self::highlightBoundary($token); + } elseif ($type===self::TOKEN_TYPE_WORD) { + return self::highlightWord($token); + } elseif ($type===self::TOKEN_TYPE_BACKTICK_QUOTE) { + return self::highlightBacktickQuote($token); + } elseif ($type===self::TOKEN_TYPE_QUOTE) { + return self::highlightQuote($token); + } elseif ($type===self::TOKEN_TYPE_RESERVED) { + return self::highlightReservedWord($token); + } elseif ($type===self::TOKEN_TYPE_RESERVED_TOPLEVEL) { + return self::highlightReservedWord($token); + } elseif ($type===self::TOKEN_TYPE_RESERVED_NEWLINE) { + return self::highlightReservedWord($token); + } elseif ($type===self::TOKEN_TYPE_NUMBER) { + return self::highlightNumber($token); + } elseif ($type===self::TOKEN_TYPE_VARIABLE) { + return self::highlightVariable($token); + } elseif ($type===self::TOKEN_TYPE_COMMENT || $type===self::TOKEN_TYPE_BLOCK_COMMENT) { + return self::highlightComment($token); + } + + return $token; + } + + /** + * Highlights a quoted string + * + * @param String $value The token's value + * + * @return String HTML code of the highlighted token. + */ + protected static function highlightQuote($value) + { + if (self::is_cli()) { + return self::$cli_quote . $value . "\x1b[0m"; + } else { + return '<span ' . self::$quote_attributes . '>' . $value . '</span>'; + } + } + + /** + * Highlights a backtick quoted string + * + * @param String $value The token's value + * + * @return String HTML code of the highlighted token. + */ + protected static function highlightBacktickQuote($value) + { + if (self::is_cli()) { + return self::$cli_backtick_quote . $value . "\x1b[0m"; + } else { + return '<span ' . self::$backtick_quote_attributes . '>' . $value . '</span>'; + } + } + + /** + * Highlights a reserved word + * + * @param String $value The token's value + * + * @return String HTML code of the highlighted token. + */ + protected static function highlightReservedWord($value) + { + if (self::is_cli()) { + return self::$cli_reserved . $value . "\x1b[0m"; + } else { + return '<span ' . self::$reserved_attributes . '>' . $value . '</span>'; + } + } + + /** + * Highlights a boundary token + * + * @param String $value The token's value + * + * @return String HTML code of the highlighted token. + */ + protected static function highlightBoundary($value) + { + if ($value==='(' || $value===')') return $value; + + if (self::is_cli()) { + return self::$cli_boundary . $value . "\x1b[0m"; + } else { + return '<span ' . self::$boundary_attributes . '>' . $value . '</span>'; + } + } + + /** + * Highlights a number + * + * @param String $value The token's value + * + * @return String HTML code of the highlighted token. + */ + protected static function highlightNumber($value) + { + if (self::is_cli()) { + return self::$cli_number . $value . "\x1b[0m"; + } else { + return '<span ' . self::$number_attributes . '>' . $value . '</span>'; + } + } + + /** + * Highlights an error + * + * @param String $value The token's value + * + * @return String HTML code of the highlighted token. + */ + protected static function highlightError($value) + { + if (self::is_cli()) { + return self::$cli_error . $value . "\x1b[0m"; + } else { + return '<span ' . self::$error_attributes . '>' . $value . '</span>'; + } + } + + /** + * Highlights a comment + * + * @param String $value The token's value + * + * @return String HTML code of the highlighted token. + */ + protected static function highlightComment($value) + { + if (self::is_cli()) { + return self::$cli_comment . $value . "\x1b[0m"; + } else { + return '<span ' . self::$comment_attributes . '>' . $value . '</span>'; + } + } + + /** + * Highlights a word token + * + * @param String $value The token's value + * + * @return String HTML code of the highlighted token. + */ + protected static function highlightWord($value) + { + if (self::is_cli()) { + return self::$cli_word . $value . "\x1b[0m"; + } else { + return '<span ' . self::$word_attributes . '>' . $value . '</span>'; + } + } + + /** + * Highlights a variable token + * + * @param String $value The token's value + * + * @return String HTML code of the highlighted token. + */ + protected static function highlightVariable($value) + { + if (self::is_cli()) { + return self::$cli_variable . $value . "\x1b[0m"; + } else { + return '<span ' . self::$variable_attributes . '>' . $value . '</span>'; + } + } + + /** + * Helper function for building regular expressions for reserved words and boundary characters + * + * @param String $a The string to be quoted + * + * @return String The quoted string + */ + private static function quote_regex($a) + { + return preg_quote($a,'/'); + } + + /** + * Helper function for building string output + * + * @param String $string The string to be quoted + * + * @return String The quoted string + */ + private static function output($string) + { + if (self::is_cli()) { + return $string."\n"; + } else { + $string=trim($string); + if (!self::$use_pre) { + return $string; + } + + return '<pre '.self::$pre_attributes.'>' . $string . '</pre>'; + } + } + + private static function is_cli() + { + if (isset(self::$cli)) return self::$cli; + else return php_sapi_name() === 'cli'; + } + +} diff --git a/src/core/pages/.htaccess b/src/core/pages/.htaccess new file mode 100755 index 0000000..5482215 --- /dev/null +++ b/src/core/pages/.htaccess @@ -0,0 +1,4 @@ +<Files *> + Order deny,allow + Allow from all +</Files> diff --git a/src/core/pages/admin_bootstrap.php b/src/core/pages/admin_bootstrap.php new file mode 100755 index 0000000..e06bca3 --- /dev/null +++ b/src/core/pages/admin_bootstrap.php @@ -0,0 +1,29 @@ +<?php +/* SVN FILE: $Id: admin_bootstrap.php 78 2006-12-19 14:59:02Z ugoletti $ */ + +/** + * + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2006 Daniele Ugoletti <daniele@ugoletti.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + * + * @copyright Copyright (c) 2005, 2006 Daniele Ugoletti + * @link http://www.glizy.org Glizy Project + * @license http://www.gnu.org/copyleft/lesser.html GNU LESSER GENERAL PUBLIC LICENSE + * @package glizy + * @subpackage pages + * @author Daniele Ugoletti <daniele@ugoletti.com> + * @category script + * @since Glizy v 0.4.0 + * @version $Rev: 78 $ + * @modifiedby $LastChangedBy: ugoletti $ + * @lastmodified $Date: 2006-12-19 15:59:02 +0100 (mar, 19 dic 2006) $ + */ + +require_once('../core/core.inc.php'); + +$application = &org_glizy_ObjectFactory::createObject('org.glizy.admin.AdminApplication', 'INSERT HERE THE ADMIN APPLICATION FOLDER', 'INSERT HERE THE CORE FOLDER', 'INSERT HERE THE APPLICATION FOLDER'); +$application->run(); \ No newline at end of file diff --git a/src/core/pages/ajaxadmin_bootstrap.php b/src/core/pages/ajaxadmin_bootstrap.php new file mode 100755 index 0000000..07ed453 --- /dev/null +++ b/src/core/pages/ajaxadmin_bootstrap.php @@ -0,0 +1,14 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +ob_start(); +require_once("../core/core.inc.php"); + +$application = &org_glizy_ObjectFactory::createObject('org.glizy.admin.Ajax', 'INSERT HERE THE ADMIN APPLICATION FOLDER', 'INSERT HERE THE CORE FOLDER', 'INSERT HERE THE APPLICATION FOLDER'); +$application->runAjax(); \ No newline at end of file diff --git a/src/core/pages/bootstrap.php b/src/core/pages/bootstrap.php new file mode 100755 index 0000000..d3a9377 --- /dev/null +++ b/src/core/pages/bootstrap.php @@ -0,0 +1,14 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +require_once("core/core.inc.php"); + +$application = &org_glizy_ObjectFactory::createObject('org.glizy.application.ApplicationDB', 'INSERT HERE THE APPLICATION FOLDER'); +$application->run(); + diff --git a/src/core/pages/errors/404.php b/src/core/pages/errors/404.php new file mode 100755 index 0000000..e439f63 --- /dev/null +++ b/src/core/pages/errors/404.php @@ -0,0 +1,51 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ +?> +<?php header("HTTP/1.1 404 Not Found"); ?> +<html> +<head> +<title>404 Page Not Found</title> +<style type="text/css"> +body { + background-color: #fff; + margin: 40px; + font-family: Lucida Grande, Verdana, Sans-serif; + font-size: 12px; + color: #000; +} + +#content { + min-height: 400px; + width: 500px; + margin: auto; + background: #fff url( core/pages/errors/monsterError.gif) no-repeat center bottom; +} + +h1 { + font-size: 3em; + color: #990000; + margin: 0 0 4px 0; + text-align: center; +} +h2 { + text-align: center; + font-size: 2em; + color: #0; + margin: 0 0 4px 0; +} +</style> +</head> +<body> + <div id="content"> + <h1>GLIZY framework</h1> + <h2><?php echo $e['code'].' : '.$e['description'];?></h2> + <p><?php echo $e['message'] ?></p> + </div> +</body> +</html> \ No newline at end of file diff --git a/src/core/pages/errors/debug.php b/src/core/pages/errors/debug.php new file mode 100755 index 0000000..d4b5cbb --- /dev/null +++ b/src/core/pages/errors/debug.php @@ -0,0 +1,118 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +?> +<?php @header("HTTP/1.1 500 Internal Server Error"); ?> +<html> +<head> +<title>Internal Server Error</title> +<style type="text/css"> + +body { + background-color: #fff; + margin: 40px; + font-family: Lucida Grande, Verdana, Sans-serif; + font-size: 12px; + color: #000; +} + +#content { + margin: auto; + padding-bottom: 200px; + background: #fff; +} + +h1 { + font-size: 3em; + color: #990000; + margin: 0 0 4px 0; + text-align: center; +} +h2 { + text-align: center; + font-size: 2em; + color: #0; + margin: 0 0 4px 0; +} +.code { + margin: 1em; + background: #eee; + border: 1px solid #ccc; +} +.currentLine { + background: #ff6600; +} +</style> +</head> +<body> + <div id="content"> + <h1>GLIZY framework</h1> + <h2><?php echo $e['code'].' : '.$e['description'];?></h2> + <h3>Stacktrace</h3> + <ul> +<?php +$realPathCore = realPath( dirname( __FILE__ ).'/../../../' ); +echo '<li>'; +echo '1# '.str_replace( $realPathCore, '', $e['file'] ).':'.$e['line'].'<div class="code">'; +$fileSrc = highlight_file( $e['file'], true ); +$fileSrc = explode("<br />", $fileSrc); +$start = $e['line'] < 5 ? 0 : $e['line'] - 5; +$end = $start + 10; +$out = ''; +foreach ( $fileSrc as $k => $line ) +{ + $k++; + if ( $k > $end ) break; + $line = trim( strip_tags( $line ) ); + if ( $k >= $start ) + { + if ( $k != $e['line'] ) + { + echo '<code>'.trim(strip_tags($line)).'</code><br />'; + } + else + { + echo '<div class="currentLine"><code>'.trim(strip_tags($line)).'</code></div>'; + } + } +} +echo '</div></li>'; + +ob_start(); +debug_print_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); +$string .= ob_get_clean(); +$errors = explode("\n", $string ); +for ( $i = 3; $i < count( $errors); $i++ ) +{ + if ( !empty( $errors[ $i ] ) ) + { + $err = str_replace( $realPathCore, '', $errors[ $i ] ); + $err = str_replace( '#'.$i, '#'.($i-1), $err ); + echo '<li>'.$err.'</li>'; + } +} + +?> + </ul> + <h3>Request variables</h3> + <ul> +<?php +$params = __Request::getAllAsArray(); +foreach ( $params as $k => $v ) +{ + if ( !empty( $v ) ) + { + echo '<li><strong>'.$k.'</strong> '.$v.'</li>'; + } +} +?> + </ul> + </div> +</body> +</html> \ No newline at end of file diff --git a/src/core/pages/errors/general.php b/src/core/pages/errors/general.php new file mode 100755 index 0000000..5fc3b75 --- /dev/null +++ b/src/core/pages/errors/general.php @@ -0,0 +1,52 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ +?> +<?php header("HTTP/1.1 500 Internal Server Error"); ?> +<html> +<head> +<title>Internal Server Error</title> +<style type="text/css"> + +body { + background-color: #fff; + margin: 40px; + font-family: Lucida Grande, Verdana, Sans-serif; + font-size: 12px; + color: #000; +} + +#content { + min-height: 400px; + width: 500px; + margin: auto; + background: #fff url( core/pages/errors/monsterError.gif) no-repeat center bottom; +} + +h1 { + font-size: 3em; + color: #990000; + margin: 0 0 4px 0; + text-align: center; +} +h2 { + text-align: center; + font-size: 2em; + color: #0; + margin: 0 0 4px 0; +} +</style> +</head> +<body> + <div id="content"> + <h1>GLIZY framework</h1> + <h2><?php echo $e['code'].' : '.$e['description'];?></h2> + <p><?php echo $e['message'] ?></p> + </div> +</body> +</html> \ No newline at end of file diff --git a/src/core/pages/getImage.php b/src/core/pages/getImage.php new file mode 100755 index 0000000..8c51d23 --- /dev/null +++ b/src/core/pages/getImage.php @@ -0,0 +1,43 @@ +<?php +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2012 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +function getImage($applicationPath, $corePath='') +{ + require_once($corePath.'core/core.inc.php'); + org_glizy_Paths::init($applicationPath, $corePath); + org_glizy_Config::init(); + + $id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : NULL; + $w = isset($_REQUEST['w']) ? intval($_REQUEST['w']) : NULL; + $h = isset($_REQUEST['h']) ? intval($_REQUEST['h']) : NULL; + $force = isset($_REQUEST['f']) ? $_REQUEST['f']=='true' || $_REQUEST['f']=='1': false; + $crop = isset($_REQUEST['c']) ? $_REQUEST['c']=='true' || $_REQUEST['c']=='1' : false; + + if (is_null($id)) exit; + + glz_import('org.glizycms.mediaArchive.MediaManager'); + $media = org_glizycms_mediaArchive_MediaManager::getMediaById($id); + + if ($media->type!='IMAGE') exit; + + if (!is_null($w) && !is_null($h)) + { + //resize the image + $mediaInfo = $media->getResizeImage($w, $h, $crop, 0, $force); + } + else + { + // get the full image + $mediaInfo = $media->getImageInfo(); + } + + $ext = array(IMG_GIF => '.gif', IMG_JPG => '.jpeg', IMG_PNG => '.png', IMG_WBMP => '.wbmp'); + + header("location: ".GLZ_HOST.'/'.$mediaInfo['fileName'] ); +} \ No newline at end of file diff --git a/src/core/static/.htaccess b/src/core/static/.htaccess new file mode 100755 index 0000000..a842017 --- /dev/null +++ b/src/core/static/.htaccess @@ -0,0 +1,4 @@ +<Files *> + Order deny,allow + Allow from all +</Files> diff --git a/src/core/static/images/calendar.gif b/src/core/static/images/calendar.gif new file mode 100755 index 0000000000000000000000000000000000000000..cd2c4a521774c70473f11c88642543751a812d6f GIT binary patch literal 223 zcmY+8F$w}P5Jmsu1X2mY7Pj^lfoWE3A`H5AX$H3SCIQzYcmogOL2?Q^tGEd(=x;uM z{$plN=VQ0Kv{>RraL#2QrIhnCSD|Y2rlx_xwxq&h@fcKZs#?v!0&(grG%|C?d}R)U zD^^qZLqwz(8AZb2F@n7Ht1*~)C_QN;j~*1;!-N#FcEOM(A3fUjg#2vzUPlb`OU3Tk Fe*i=yIHv#r literal 0 HcmV?d00001 diff --git a/src/core/static/images/close_button.gif b/src/core/static/images/close_button.gif new file mode 100755 index 0000000000000000000000000000000000000000..e340fa10ed6407c37ec4b51e66b4608711fd6956 GIT binary patch literal 85 zcmZ?wbhEHb<Y(Y#n8*ME|G@yrQ2fcl$iTqFpaT*G$ulsi_4G>~dYd~hB`{=1j$K9i e-hwOaakrF{{5I9aL>=7Nekr*2`YAaP25SH`Y#hG; literal 0 HcmV?d00001 diff --git a/src/core/static/images/colorPicker.gif b/src/core/static/images/colorPicker.gif new file mode 100755 index 0000000000000000000000000000000000000000..d9b31bb43ef3394fe156c15359fbc82f2afe7e44 GIT binary patch literal 5346 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 ANB{r; literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_add.gif b/src/core/static/images/icon_add.gif new file mode 100755 index 0000000000000000000000000000000000000000..24cd174501b05e3d88ef39bc1ff5a23e57fdd052 GIT binary patch literal 106 zcmZ?wbhEHb6krfwSj51<pu}MOpW*fE*9^NE&iqefC}&^@W%&R9zv538RuKj!1|6Uh zph^J-24;PYU3dN&oC<oPr7oe(C3(Q5mf>rHi`5dx8zKi4&Ob<IXz1BJAv}7+{HMn> KrTUv#7_0&1JtRE< literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_addThesaurus.gif b/src/core/static/images/icon_addThesaurus.gif new file mode 100644 index 0000000000000000000000000000000000000000..71282beb24b1ecb854d4c58352eeb8df36728697 GIT binary patch literal 372 zcmZ?wbhEHb6krfwxT?f3bLPx<KmIZ7X0T7|W+-R)|NlRO62rGY|DJvQd***y(X73D zuf4kW@sE4nWaIw~5p|36rtV@0Wk~8?AJej;dD)STS3jM7^~<wxnqSGRz{+{){hPC= zY`^~g_u}JEwr|~#(7tB%$@>M<_kfJ04N&~a!pH!0vJS|2ke?XXCOS;?aMW>9kXsnE zLc?NicNfcs6uX7(r<!;1$nLv;bo=CoT#D_ERT~xr7)Wf+5MFUzvYYjV(sdTLdS+%0 z7M2=sp)y8}7FIsNBKi78W)@B+wj$xOme%QPtzN<$%`B{(E0|XBu{rVgwD2))-ZEp| q5*{8wHnz=s)~?&hBO@j@ZAOtK@9EQ1H_Z%XxOACe_a!Gs25SI~%y~Ef literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_add_off.gif b/src/core/static/images/icon_add_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..a688f53e83a8b2d88917ce356b1bd939dc36653f GIT binary patch literal 106 zcmZ?wbhEHb6krfwSj52a|Ns974<4L3b7tSZeH%A!T(xS|f&~kJf{H&`7}*)v8FUzc z0Hl_IS-)b}oqq;iPEV8^M5;X`j=9vbeNAw*TH<s=;E=-k2f-3;J-a7_M{k(_^q8hp Je>)3<H2|_*Ed&4n literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_checked.gif b/src/core/static/images/icon_checked.gif new file mode 100755 index 0000000000000000000000000000000000000000..32c9afcdf0efaa6023f45840cc3e08b9b6a85c3c GIT binary patch literal 231 zcmV<D02u#ANk%w1VGsZi0K^>tJY$K&-|$CnlN5FZzu)lC>-kuIqc>fIQF)$jmAdBf z_}%gQ>ht)+;qpmwmTQ!^T!g4jbei1m_viKeKW2*?-U@P>z3le<P~Hk0qX!2r0u4$7 znVFgY|Nj6000000A^8LW0012TEC2ui01yBW000GKU?+}bX`b75np=fwq$SHq(qb7r zTGz!Wl3T81N&SQxPHB_Lq+B_KlC&A%pqfBrI(k$wI87tq;EEuZYOX*CP|O`ePor6| h0|2<ZH?g<#B?tn80sw{w2XGx6jE#;fkdY@L06W@}WDEcR literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_checked_off.gif b/src/core/static/images/icon_checked_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..319e46f874b213d893c9e4d13cbdae9d3161f6cf GIT binary patch literal 229 zcmZ?wbhEHb6krfwIKsg2>({TJKYxDz{{7pxZ(qKA`S9Vx`}gm!UAuPm>eVY(u3Wx+ z`Rv)Vr%#_gdGh4(<HwI4J$mrq!2<^l?Ay0*_wL;rH*Q?9V#VUci~s-s&wv9c{$ycf zXAo!50m*~xWMEBtpxT#`IWM$y*3`!lDoUq4FIfrOC@~1IG)J#%@%Y;^&3UEK%q1~9 z+a`r9e6V0zQ?gZ1$i~(~&Dv26t1O!qGAPDN*mk=v&~v%-A+BNHzUfl@jr@WwLPB}s P>|NbG+I{`%iVW5OIiG0y literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_delete.gif b/src/core/static/images/icon_delete.gif new file mode 100644 index 0000000000000000000000000000000000000000..8a43c33e129201737b41641605ab04825097b615 GIT binary patch literal 323 zcmZ?wbhEHb6krfwxXQrLB_j0t_3N24XFf47JgTGjv7_~Ubo5&Xr^AMZ-=|LbUR3-e zB)DBv^qh^&w~VykWtI2Uls~3sytA?C5f%S2bL!{TmTpnO=hoI|jEzs(*?*3Yeedq_ zwZHd!X2v}=jjwZOe@)9^pe0cJ$-*kaz{sEjvIOKO2DXF)4Fw)LQvD~M1R5xE>6|{v zt|(%lG4oMyp{4>$!||p|7no$GbGdDdn9}RhuCnQ7!lZ<sja^%^^u*a^YNB}9<iyj3 kI9o!+xC8{4!xY4OqJ+8RLV09aym|Z>yp}9=c4V*y00JLZNdN!< literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_delete_off.gif b/src/core/static/images/icon_delete_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..2442c51f9c66740485dd4b977f60e2ba37c76327 GIT binary patch literal 213 zcmZ?wbhEHb6krfwIKsg2^5x4HFJ3%*_Uy@%CyyULe)#a={rmUt-Me@9?%g|g?%ck8 z``Wc@SFc{ZeEIT)3m49vJ9qZ%*)wO(oIH7Q=gyrwcI^27|33p>p!k!8k)1)5K?kG? zWG4e_P=ab-O6I(bDm~$y0k2s+9!WbqjW%iiBGh$2+1>Di5^HNxMv|mN$5Ew8Rko5Q sSF|r?7_dYxV!EVZ#Pm>VDMO=0TsxbUdE#o`mlsd72LJr8q{v_m00hij`v3p{ literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_document.gif b/src/core/static/images/icon_document.gif new file mode 100755 index 0000000000000000000000000000000000000000..8c96488cfff0a4b929bb94040e1a7472ba1e7490 GIT binary patch literal 354 zcmZ?wbhEHb6krfwxXQp_9^10<>Zkt<|7Xse`Rwc8z{+_=v-X~U{i}J|k)-bRi;q9~ z_UGS$r$1bCCvD%l;oiqT*;BSh)GfA2?tJ&--}U#u|NsB*SvYO)wO40f{Yq$GW1rSt zFn!Op_uu#4dzRk6Ii_XB>XY~VN@g8>{?k2ga^BQkPMLiSR0WDZSs2+Fm>6_Grh@#$ zz*g_jc)&qtk_X?ypo|q3bEi8bZAh_O*zM4=>yFO8`=`SLA8>g-Fklkon#nq$Gv?op z7>8-w)9n<0$n#fvbJo=Ji}2=4)-;IpspiWUv-I{!O{|;J$3ADex8O|vIdhbR@)t~5 lv}Eb>hIR=FB_*C^-mJ<yc1Q^cF)-vaF&{d7B*u}!8UT;yf}sEa literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_down.gif b/src/core/static/images/icon_down.gif new file mode 100755 index 0000000000000000000000000000000000000000..f2b522436da0dcc19b4097ff954aac7cce2becb0 GIT binary patch literal 124 zcmZ?wbhEHb6krfw*v!Ddpu+I__3N4cXEN+(VA#sQP|oo3)l1|53}^nQ{r~@;se*|? zjp5bnS3rdjp!k!8RfK_&K?lSInZdxKX>h`G^<InDXLtXXUflB}Bf`~a&1*xQ=}jB- WCY*HM%h;Y!%)r3xvc`ph!5RQv^(u4# literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_down_off.gif b/src/core/static/images/icon_down_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..ff4c0b8483eef357797e3ec0eb82c6703ed13e91 GIT binary patch literal 124 zcmZ?wbhEHb6krfw*v!E2|NsB*-@kwR_U-lS*AE^%ICJLA{{8zmZrr$V;lc$A764@# zP=Vr47DjdkE(RTtFvtuB7R`W@o~!p-ygs}8e{@056O9P=gf-cT3fCPs<V`y1wpaCN PLUE@HgUcEh1_o;Y%S|(R literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_download.gif b/src/core/static/images/icon_download.gif new file mode 100755 index 0000000000000000000000000000000000000000..b5cf96c4930808ff045308588917ca877c8ef4b1 GIT binary patch literal 339 zcmZ?wbhEHb<YVAtxT?qS{gU*r=Wf5Bx&OGK`Ry$K@3$d8ADBOT_U!-P%7X_FUcGwd z|G%mK{}z5dEAV^<>;J#a>(;G%xsc=2r%(U?^}O3G^kOdC|9^9S+|+ozitF7*?w|L~ z|NqJS^~~-5g9opdaXy>O{QLKxTeoigeiQO+0@I&Q2|vDnfAi+e|34{eYHAlQT+r9o z|NsAgT3Q+d0|Sr&BuNE|KUo+V81xu)KpH`QVqhz9m{#DCva@f^l&qsEtERY%dvA<c zx=w>b>l9aL@Y)SKRNvM_FaM(HoF>bsCAw;>q6x?1ZJGIATO=47<#UA!i*z}}nVI== yRlVE!+1R8+a}~Ucg&CP-<_M;=wR0=6vdX0duF@4#kyyEEwaA8zt5-QPSOWmip^bw8 literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_download_off.gif b/src/core/static/images/icon_download_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..b5cf96c4930808ff045308588917ca877c8ef4b1 GIT binary patch literal 339 zcmZ?wbhEHb<YVAtxT?qS{gU*r=Wf5Bx&OGK`Ry$K@3$d8ADBOT_U!-P%7X_FUcGwd z|G%mK{}z5dEAV^<>;J#a>(;G%xsc=2r%(U?^}O3G^kOdC|9^9S+|+ozitF7*?w|L~ z|NqJS^~~-5g9opdaXy>O{QLKxTeoigeiQO+0@I&Q2|vDnfAi+e|34{eYHAlQT+r9o z|NsAgT3Q+d0|Sr&BuNE|KUo+V81xu)KpH`QVqhz9m{#DCva@f^l&qsEtERY%dvA<c zx=w>b>l9aL@Y)SKRNvM_FaM(HoF>bsCAw;>q6x?1ZJGIATO=47<#UA!i*z}}nVI== yRlVE!+1R8+a}~Ucg&CP-<_M;=wR0=6vdX0duF@4#kyyEEwaA8zt5-QPSOWmip^bw8 literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_edit.gif b/src/core/static/images/icon_edit.gif new file mode 100755 index 0000000000000000000000000000000000000000..66ba8940ca4360d6d95b3c079bde50cdc8bfc013 GIT binary patch literal 198 zcmZ?wbhEHb6krfwIKlt|uV26Ze}>`AOosnwX3jKb=;-M9pO)t0;&R5=_{_|-yLa#Y z2TG(d7&9>Z|Id(SZ2bQWkZZhZ)he)V0)*mE7FH1kMg|>_I*^?Vtj-AveJPpqR&cI; z$>DnO;g*g<nUg(Y$C^}j%06zKp-{5yP=J92m;4#FO-ow%mRL85c25%ExW1CpAwc6u OGK0gVtlhzi4Aub26F`dq literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_editDraft.gif b/src/core/static/images/icon_editDraft.gif new file mode 100755 index 0000000000000000000000000000000000000000..34adba42da8804d3cf93e54c52c96da0620fd161 GIT binary patch literal 211 zcmZ?wbhEHb6krfwIKsg2|Noi){~7Myz5D;nng3^I{y)R8YSpSUGt<t@Wa#MV_@9<G zGtGEr8p9c5<C(?`E-o%<#>U1BAn+fkjR>IllZ91;L6|`Yq!wf+18cwomA;hBd8sBV z*Kq9B;N)#y)MfrtrR&lYHFu{E8Gqay*cCn)*fgl5E@-G&<`Sg!n5|S`S;t$?tqKB% c99FaxSU7lUb=D+S9e=R8W_783D+7Zy05{`Db^rhX literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_editDraft_off.gif b/src/core/static/images/icon_editDraft_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..30047defc63de60b4eb7a9724609266e5a7bd514 GIT binary patch literal 157 zcmZ?wbhEHb6krfw*v!E2>C>lo@7_Iq`t-()8&|GeIdkUB;lqdb@87>^)25|Mmo8km zu&1Y|zP|qd|NjhNp!k!8RfK_;K?lSGnZdx~wc(`a>b<3=XH$PkOl3H*z*Bvx#NmP^ zVM#2fKKgyA&}d=mW{^HK{UZy1$B~!Q1vsXP^ExSb9IE4ST=-#ehD1WkQt3~5=jQtT J6k=qs1^_Q&Mi>A9 literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_edit_off.gif b/src/core/static/images/icon_edit_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..c55f98bd0619ae23706ad500db6401a296da759c GIT binary patch literal 145 zcmZ?wbhEHb6krfw*v!E2_3PJ<A3wf+{rbU!2Y2t@y>{)|`Sa(`oH=vo(4p<yw{O|9 zW%1(0GiT2H|NlP&7%2W^VPt3EWzYffKxQzo*ljrJxq9!7WpmS+4s0mtGUPelq3X6k w<|UU5*TNOIY81BfD09X<{mi|N#Wj&tQGj8pXxoB-1~*9_m-N$TT^Jaw0gt;sq5uE@ literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_folder.gif b/src/core/static/images/icon_folder.gif new file mode 100755 index 0000000000000000000000000000000000000000..38a8901872af7c51a5dbb455909e372d4074e244 GIT binary patch literal 342 zcmZ?wbhEHb6krfwxXQq=w2=Eh!~eg3fB(9geQcW8)g2E1KhF90xN1(7<e5D&n>(d1 zEKqs2H{|1^>TmDc|NozPbf(DLo%Vl@MgG0s^8aJc!vntiW@!I=)^c-y_KErO|G!W9 z_ptij28aJ&x{uD1`v3p`zkf@X74iPRmUC{Q!oSxo4>mb7P!%ZtWMO1yU}Vq%nF{g~ z16%Qdh5`>Ass3XVi&|v#SOOTAy!>giuAe_~_g5ayw!Vlzn$vAL6k9?X9c(^S#0V<* z*vu$0srtFZmRXK3qJ>{bs$Nx6L8`Z}mxq&~l$(`bWyZ`If-Fu2y!`Bo7B7;?WX$7N YTD@kC*kmV$O`ErD^4-3})sev(04fxFZ2$lO literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_go.gif b/src/core/static/images/icon_go.gif new file mode 100755 index 0000000000000000000000000000000000000000..a2b5d5416b60ba525f6f061fb7c251f2c8fb2feb GIT binary patch literal 268 zcmV+n0rUPxNk%w1VGsZi0K^{vB~KP@%SUO+M0C$febrJ)p)B_M^oiS9fYwxww16mA z7>?dtiriW+XB<9<CPb7d)bGnSbRoUwuVuzTam`6z!ajP_PqN~nchOD7>9~d2R!*uf zBTN<S_~`%t|NsC0A^8LW0018VEC2ui01yBW000Gv;P-iCX?mjQZERZ<&*PxumKa^G zcg7W=E5l;JIA{<A3kK2vZaPGxCW#qj6wXdj<3T6~lq;~%k&>#EKn5`GXpW_{U=4J1 zkQP!vFqvF9bsbb56ast|e?So(Uuk_6h=3yv255T|kQEY=9t{Z)8KD^$q!I~|BMJbk S9IdXXDkmo?w6(S$ApkpTb!;I3 literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_go_off.gif b/src/core/static/images/icon_go_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..29d7fe22fad2c6bdbd07b8fe6bfa54625f25af21 GIT binary patch literal 976 zcmZ?wbhEHb6krfw_%6?|dGqEICr(_sa^=#cOH-yyIeGHro;`d1{P}bC?AcGBKFysw zckSA>7cN}5eEIVA>({ScyLR>J)r%J|?%1*8^y$-Q&YbD*?>~S3{E{V0UcY_~lzRUB z`P;W|dwY9-{rdI)|9^&2Fd71bI|LMevM@3*$TR4GoC(Sk3><42>}x(aY*^sP&%|0~ zaA3ni7ET5R9S4gG4sFb`Mp<tP91gR#aPwOfd{Ag^U}IJ?@L0gGq>)d>m&@bifkSLe zde&1!9xQD1;^xR}nsUKW?cgj9jhqz*TbdgtvrhJl;3{%tpCZT+G$UX^0~=qc^@T4D z2~5`+;vM5&d@#<u&X94CFQkCs<u#@P=7b5a9Ua?Pq?z(BI7m3N?PTT*i8!-xWAYI$ RemNhHotvKWGcqz*0{|RCjeY<C literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_invisible.gif b/src/core/static/images/icon_invisible.gif new file mode 100755 index 0000000000000000000000000000000000000000..f6432c9e61553d5d61e1e0e1c62523b1cde77e75 GIT binary patch literal 218 zcmZ?wbhEHb6krfwIKlt|Pq(gE&%kgaEa1({8y6Mjv=|u9FfiP$D*FHb|2bZs*SmII z(%0U@z;IDb<>}5fhZq=)85pi9DxMb-+z!@`pHTeC!YabR!k`0E2C|cZHC#clFGZ8h zBVpZ%z!ln(BJD{G76R-S9v;{kdZ4i3j*ErxfeXSele`X1^62zPZaC6Zl(C}3D`v^V m>W0G&93MY$Oy*&iUo+*hZO7!w9)TG$64gdL%#GTL4AuZ&R6@f5 literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_invisible_off.gif b/src/core/static/images/icon_invisible_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..a519c335dd4deb356d33fd4b1006f9b0c4ade103 GIT binary patch literal 214 zcmZ?wbhEHb6krfwIKsg2|NsBDZ{NOr`SQh!7kBR5xpL*o>C>lAo;-Q%*s-HWj~+U7 z=)i#k`}gnPyLa!NJ$n`}Uc7MO!kIH?0(CJE2NZv@FtRfUG3bDlgY0Br4PKzqm!ipc zBw<}k(F$!#880T+3K9Np?&qs#CKU=l^bzzp|ItE8)idfbW3MYiV_Vb0ONxd3ZQc+5 hy2+WeKJaeRs98P7&%yaXl6uRbhUt=Awc3gd)&OD8Q#$|v literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_lock.gif b/src/core/static/images/icon_lock.gif new file mode 100755 index 0000000000000000000000000000000000000000..af072f5e668426006e0a47f105f992c783747e6b GIT binary patch literal 288 zcmV+*0pI>dNk%w1VGsZi0K^{v|LK+a<g>}i$@0lns;a8puuS{=`;?TFySuyClq~70 zKG1au|M%DZ^2qPIMflZe`rUBexmV%AU*)Mv?(Xi>g&MDiQQw_0{^NpvdUX5jzW?s2 z-KIV7zgwuFi2wipA^8LW0018VEC2ui01yBW000G@;3s~DfDi;C7-LJNLVO-nOA;n= z?C8OcrW3_rpd3($mWogtQ8K6&&et+P4<m_Z7wHzhnQ%fRX*3w<bVI`)f65RH0I=Br z9)m%^9ce&19RM5?023T~6(W5PasU?=7<di=i5~?G4-SC|kP{b^l?56PadQ9|0}hi5 mA{-h63J!Ux9G?NKAFga?Xbl0sw;~q_#1+OB3(3kKApkqB<$50g literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_lock_off.gif b/src/core/static/images/icon_lock_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..603ab650446fc78c261604e031c64206f97cf1dc GIT binary patch literal 312 zcmV-80muGFNk%w1VGsZi0K^{vwY9bV{r$bYy}7x$=jZ3Kv9YYItir;=;NalZ)z#9{ z(#FQd?(Xi*&CTlS>h$#V-QC^E$;s&G=-S%a(9qE0;^NNE&g|^$*x1<e^76pI!1wp} z@bK`;%F4vV#Q*>QA^8LW0018VEC2ui01yBW000HG;3s|ofhkIY1Y`Rs6H+0NvOF!R zKvU-(3zUa7GEEwrKwxvQL?EpRq=Oqh1e8WgfjAIF0RY7_>MRbL#o~ts6aWKJhr!7_ z9-GaBb8$H09}x@~5HbV=6$uRy4gewx3<(_;6#^az3mS}$ACNFI0s}Q>4h13}3^ol2 z0ss&P0t*tR9|so{2{AJh6lV?wA{rMB9uW-|iy8t41i&8xeisZG)C>+1ht8n`0Nn-O K2I1i!Apko8orKT; literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_orderDown.gif b/src/core/static/images/icon_orderDown.gif new file mode 100644 index 0000000000000000000000000000000000000000..1b95cf14f0910630719b04a1a5cc1b0081373b2e GIT binary patch literal 59 zcmZ?wbhEHb<YVAtXkY+=|Ns9h{$ybl0Wx(!e2@$SlTb_l%F}Q6H_ZvYD7Esi^e=uR HRt9STtJx4{ literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_orderDownBlack.gif b/src/core/static/images/icon_orderDownBlack.gif new file mode 100644 index 0000000000000000000000000000000000000000..14850a423f06cb722687ea8a4d47de6fda86f5d3 GIT binary patch literal 59 zcmZ?wbhEHb<YVAtXkY+=|Ns9h{$ycfXJBN|0r5dH3`{~j{VPwu-QO@L_@dOx!_vR_ IjaV710jd`eTmS$7 literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_orderUp.gif b/src/core/static/images/icon_orderUp.gif new file mode 100644 index 0000000000000000000000000000000000000000..a5efff3660f565f7ae6916069efd20da23f565fd GIT binary patch literal 60 zcmZ?wbhEHb<YVAtXkY+=|Ns9h{$ybl0Wx(!e2@$SlW<G_%F}QEGx1!xczRvfuEYFo I9*hju0KsVyVE_OC literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_orderUpBlack.gif b/src/core/static/images/icon_orderUpBlack.gif new file mode 100644 index 0000000000000000000000000000000000000000..a5a725ae9c21a46fb5e81d67070eb4e1c8f3e4a4 GIT binary patch literal 60 zcmZ?wbhEHb<YVAtXkY+=|Ns9h{$ycfXJBN|0r5dH3{1j3{VPwu{m;O1<>KjeVY?3V Kw|Ou!SOWmREfG%u literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_preview.gif b/src/core/static/images/icon_preview.gif new file mode 100755 index 0000000000000000000000000000000000000000..7c00d5936ca1a3401b5cfd3cd8071d3d2e25d4bf GIT binary patch literal 208 zcmZ?wbhEHb6krfwIKsdnCMGs}_xJyi46k3mPD@J*)nhn!=i~qX|971G(&5GMe<s7d z=kMQr`o8Y?*F6_MUw-i6z~#@2_J3m_8Yuo`VHIIuX3zoY0NKgF>ia;UFC}x{3x+ig zT1<{ITQu%C9Q%AhRYtL`wZPHfphVyC2^l;F4X2aNpFCjObV*3@P=yswr0_w<G69iJ Ykwjk&jtlE1O3TTMaDCmQ&B9;}0J)n;CIA2c literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_preview_off.gif b/src/core/static/images/icon_preview_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..dd188676680ff1ecfe85540ea6f7147ceab632f8 GIT binary patch literal 156 zcmV;N0Av40Nk%w1VGsZi0J8u9`uh6y_4V`f^YZfY@bK{O@9*yJ?(OaE>+9?3>FLbO z%)-LLw6wIUs;Z)*qW}N@A^8LW2LKNMEC2ui01yBW000C@@X1N5z4*E9vUEw9bQpLL zgCLL<h!{g42a5#)g)q~00>Hak%LhOSV#3M-0r(XLNz0-@Ei4p_%woG}D6pQ17aV>x K8s)Sn0suR+hfGZX literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_publish.gif b/src/core/static/images/icon_publish.gif new file mode 100755 index 0000000000000000000000000000000000000000..32c9afcdf0efaa6023f45840cc3e08b9b6a85c3c GIT binary patch literal 231 zcmV<D02u#ANk%w1VGsZi0K^>tJY$K&-|$CnlN5FZzu)lC>-kuIqc>fIQF)$jmAdBf z_}%gQ>ht)+;qpmwmTQ!^T!g4jbei1m_viKeKW2*?-U@P>z3le<P~Hk0qX!2r0u4$7 znVFgY|Nj6000000A^8LW0012TEC2ui01yBW000GKU?+}bX`b75np=fwq$SHq(qb7r zTGz!Wl3T81N&SQxPHB_Lq+B_KlC&A%pqfBrI(k$wI87tq;EEuZYOX*CP|O`ePor6| h0|2<ZH?g<#B?tn80sw{w2XGx6jE#;fkdY@L06W@}WDEcR literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_publish_off.gif b/src/core/static/images/icon_publish_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..319e46f874b213d893c9e4d13cbdae9d3161f6cf GIT binary patch literal 229 zcmZ?wbhEHb6krfwIKsg2>({TJKYxDz{{7pxZ(qKA`S9Vx`}gm!UAuPm>eVY(u3Wx+ z`Rv)Vr%#_gdGh4(<HwI4J$mrq!2<^l?Ay0*_wL;rH*Q?9V#VUci~s-s&wv9c{$ycf zXAo!50m*~xWMEBtpxT#`IWM$y*3`!lDoUq4FIfrOC@~1IG)J#%@%Y;^&3UEK%q1~9 z+a`r9e6V0zQ?gZ1$i~(~&Dv26t1O!qGAPDN*mk=v&~v%-A+BNHzUfl@jr@WwLPB}s P>|NbG+I{`%iVW5OIiG0y literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_unchecked.gif b/src/core/static/images/icon_unchecked.gif new file mode 100755 index 0000000000000000000000000000000000000000..958c28839fe380359779c122b83c38db4fc5780c GIT binary patch literal 223 zcmV<503iQINk%w1VGsZi0K^{v*6#W}WQj*_l)vBb=k@&E@%zy0`8QpJQF)%~^Y~bP zqtNK~-0t`0@%Zxj{owQb<MjN;<MZ$M{al2oPIQ{;_x;oD`f!)L#NzU6l(%x4y>6Ad z!{6}i_WYTdng9R)A^8LW0018VEC2ui01yBW000GC;3tk`X`X0mYAn0G@7i@q!z>)P zd8Ibjx7@CDnK?QTK!k(fkv2vo0K=g;N12(V@~}_^SJ7nFAruS)P9XeIkj-c{+dYG) Z*Cm8tF9`S#2W%f6goTDGh>0H|06WP(cIyBD literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_unchecked_off.gif b/src/core/static/images/icon_unchecked_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..a21be46dadb94b19714d74d91114a394a21cb272 GIT binary patch literal 218 zcmZ?wbhEHb6krfwIKsg2=g*(tzkmPw_3P))pFe*5`2PL-w{PFRe*OC8%a@NIKYsY| z;r;vf*REZ=diCm+D_1UGzI^uV+0&;_pFDZ;`0?XMj~+d6;K06p`~Ls`&wv9c{$ycf zXAo!50m*~xWMB<{pxT#`IWHs2Oy~8U_gWl>6BN208KfFt-+pJEIr9Y`&ej(9B9Z=+ zoW);eu(Gr`Pcjm9Oxwbgv~Wd<zTgK3AG7I~?8|=YEWDvPb<feFeFpy;8nv2R#1$E= E0e{_VF#rGn literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_unpublish.gif b/src/core/static/images/icon_unpublish.gif new file mode 100755 index 0000000000000000000000000000000000000000..958c28839fe380359779c122b83c38db4fc5780c GIT binary patch literal 223 zcmV<503iQINk%w1VGsZi0K^{v*6#W}WQj*_l)vBb=k@&E@%zy0`8QpJQF)%~^Y~bP zqtNK~-0t`0@%Zxj{owQb<MjN;<MZ$M{al2oPIQ{;_x;oD`f!)L#NzU6l(%x4y>6Ad z!{6}i_WYTdng9R)A^8LW0018VEC2ui01yBW000GC;3tk`X`X0mYAn0G@7i@q!z>)P zd8Ibjx7@CDnK?QTK!k(fkv2vo0K=g;N12(V@~}_^SJ7nFAruS)P9XeIkj-c{+dYG) Z*Cm8tF9`S#2W%f6goTDGh>0H|06WP(cIyBD literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_unpublish_off.gif b/src/core/static/images/icon_unpublish_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..a21be46dadb94b19714d74d91114a394a21cb272 GIT binary patch literal 218 zcmZ?wbhEHb6krfwIKsg2=g*(tzkmPw_3P))pFe*5`2PL-w{PFRe*OC8%a@NIKYsY| z;r;vf*REZ=diCm+D_1UGzI^uV+0&;_pFDZ;`0?XMj~+d6;K06p`~Ls`&wv9c{$ycf zXAo!50m*~xWMB<{pxT#`IWHs2Oy~8U_gWl>6BN208KfFt-+pJEIr9Y`&ej(9B9Z=+ zoW);eu(Gr`Pcjm9Oxwbgv~Wd<zTgK3AG7I~?8|=YEWDvPb<feFeFpy;8nv2R#1$E= E0e{_VF#rGn literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_up.gif b/src/core/static/images/icon_up.gif new file mode 100755 index 0000000000000000000000000000000000000000..a1c03babcaff776071dd8cce19c7bbe0cf96812a GIT binary patch literal 124 zcmZ?wbhEHb6krfw*v!Ddpv3U{_3N4cXG+~+WZ22TP|oo3<xAuL3=I1iUcG+BSjh-f zf(#UYvapIUFf!<X1VLsnuxJ{b@LavOLMvgD9n*77=0b%<Qzy7oFAE9WrdP#S(Wf5w P{{Mjm1s-c$7#OSpz&s^- literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_up_off.gif b/src/core/static/images/icon_up_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..bf5fc877b8d6889a4df8ee0588dd00c247d7a52d GIT binary patch literal 123 zcmZ?wbhEHb6krfw*v!E2{rmTC-@d(m{rb$AGe?ge-M@eTzJ2>PZrr$F!Giz)|1)3! z#h)yU><pX?Iv^R484N5M1}8mN@2!v%*(AsGT(-qfWD)BGx9Vjgw|Bj0z4L>&qUQbo M0}BcwIvE(O0aW`i8vp<R literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_visible.gif b/src/core/static/images/icon_visible.gif new file mode 100755 index 0000000000000000000000000000000000000000..56dd46806aa0feb531b14fc9c4e389834511b5e8 GIT binary patch literal 83 zcmZ?wbhEHb6krfwn8*MEZ(iQ`|NlRbq4<-9RfK_&K?fuXl4oF2>FHm2`Yc1@WOYAj gjV>7-e$Hv%Ih9=1WM{65h~9du-SS(nJ}ZMY0HVYg7XSbN literal 0 HcmV?d00001 diff --git a/src/core/static/images/icon_visible_off.gif b/src/core/static/images/icon_visible_off.gif new file mode 100755 index 0000000000000000000000000000000000000000..0d69919b1c06b58de28a7f05f6720f6e86f0510d GIT binary patch literal 83 zcmZ?wbhEHb6krfwn8?8J|NsA)GiL%x1_lPjpDc{*3``6<KsHcTfPsNYWlI0b(`OkI kC#(BuYjoM@@H0;P&Zy+7COdOgMD*5M?Uvtq^;sFL0XQ!jO8@`> literal 0 HcmV?d00001 diff --git a/src/core/static/images/mediaArchive.png b/src/core/static/images/mediaArchive.png new file mode 100644 index 0000000000000000000000000000000000000000..51a136d6771b8143fadf57dc01d42eb0955f3a81 GIT binary patch literal 3650 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 Ysa4Rs*t3@3^l<>NroKj<+Vk-L1Lvvi?*IS* literal 0 HcmV?d00001 diff --git a/src/core/static/images/mediaAudio.png b/src/core/static/images/mediaAudio.png new file mode 100644 index 0000000000000000000000000000000000000000..73f152847ff401fb59e2544cd6f515d038e51c66 GIT binary patch literal 6052 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 literal 0 HcmV?d00001 diff --git a/src/core/static/images/mediaFlash.png b/src/core/static/images/mediaFlash.png new file mode 100644 index 0000000000000000000000000000000000000000..ef85c2e93c8dd77f8d8b80ea0b0a73f2dc1e637c GIT binary patch literal 2499 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 Q!6F4f+BjHOBd`ho1^!~Z2mk;8 literal 0 HcmV?d00001 diff --git a/src/core/static/images/mediaImage.png b/src/core/static/images/mediaImage.png new file mode 100644 index 0000000000000000000000000000000000000000..53aae03eed455a0804d03c38e62a3b56b3c2565d GIT binary patch literal 2632 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 literal 0 HcmV?d00001 diff --git a/src/core/static/images/mediaOffice.png b/src/core/static/images/mediaOffice.png new file mode 100644 index 0000000000000000000000000000000000000000..f0836de0104f47a3f1e828b9b14f81c649d1dd09 GIT binary patch literal 2677 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 JEJt`G{0q2B5Ags1 literal 0 HcmV?d00001 diff --git a/src/core/static/images/mediaOther.png b/src/core/static/images/mediaOther.png new file mode 100644 index 0000000000000000000000000000000000000000..69c65bfa8e2cf9268c11d0077c1585a64fe25a15 GIT binary patch literal 1614 zcmai!eKga17{I5}9WE)UD3VGiX39$}W|^(LN2Fy#i%pVY7M8c06m1G=o33}I7Zyu- zjq4IA8#;&_+ti8`C7ZFl)%`igb<ery-qZJdp6~Peeg1l$?^SoVBdW^U${-L()zJZU z4A9Ia0j~va8-)lFpw>hp9lgN7i310w0=`nX!^ubxNM*y4DD(&t7J%S33K~Q43?ova z@nizXE->sgLGN%dnGhXD4vEyW_cY7yKfD^K+p<(=PbT0g!C@plui#Ju$n=2mJ_}>h zef!NFLXU7kAjLb5C_As1+%Npj5U&$kev`=g)>&2oJXR(XnhaHj(rTj#>n)AJ#+RAe zrF4A~q@>FIV@sl4y`eAI19t*fRg7F+j;kR#IcL1cJ|l|j&f`bcbE+TQ)%!Rvj3wp| zn<`D|5_L!O`MGH-JHV5ryU`|~+gCY-Nk60bG>iw6Hx19v_CK`mI-Z_dyIRC&*Jfx# zJ5d1vi}y6z(|@@4#c{JBU6eO!cmd{*MLhUBR@`%msIvEkfPr|%^ID{ML|j8-xLj`J zr3@%cEHuL&YMv-x*r8v}sfGBDBWExJ<${wR=Vh!2+L(VcoD|*E6gNE<gswnkQ8D7~ zf(n<eK!m~7*r5wi)U*WLC|<{w{JE^J?pc2%H|WWGQ`PagX=^jL7E7iXH<SYSMlLc0 z+0ir<_ITm28MK#kBcmY%W}<t0GwX}4ktD@Mj3zu0RW@#1E3Y4E_?G5|t7f(Adf?MV z?>*Dnw!O%C@Aq18*%Q%qI>*Ua2$(Wa8l6+D?vG2>yjCmHXWwtt*o;T-xn2u4avDho zQpYE1!CZHd-*m4pP|tO*DwYgKjR22+eQjXC(5;J$SkEkiPYY=2e&s;^)r60$L74_k zqXX!p6&p&bkS3E`(U|9BPorM8@N%U$Mep_5s~|jHhY)Vo;Yqtj=O|Z(k^F?1H+zDM zXNwNDwGrm_AO2SHY3`=W>#@qgvmL~HI|ui9W=oIa^!16`QAmuUGfsc1_pvDgZiJ;m z2m9TneEJKc#lS6_8*u6^+D94Y45!klV0JKk((O%vog#h-v{x*fSmP_(plsn=V0b~v z1X9ZJ9vGncA&c(H+ch?^koWZ<%cP#2N;vf+2W_HYk{bPYa3#B9q>go2iyw(#2Q-dj za@%QpAkfS1c9><>zaGt-!bslgs2GC(hvNFFE-E|bdM8SA6VOMA?!3cGebX|iDyrDV z+a{(xNx9{}q1~Toh}1R84>0q%+y?Y%5gh|-CMz!E5h{eGYpxSM`uQ%bEK7?yTRmyS z>RiwQKj#W#o=@IZtu<QR-588nv?IdQhGb?#Vxc)ZswoI?D04c!)Vp|#r=gN&?Dgc- zn6D*+TJJbg8~Hj*OXDL*RDaIaO2!bWk{xDw&gLAPIZ+s96BT!UE}q(V_NvOe%n{r; zXM&c>$A)Bw8MJ#KxPj*zB_F))Z!8dDL*Hzf{Ebv{r$05^|9AM%_;;(|sG-Up41<pl z^j_J@oN|38#SWIJ=YJM9$}8(<4oy6?yu(t3u=e-N4FZlu;Q4shg<(syJ=iv4qH^S5 z?uZ~<oEsPYsfV%45s@$xtHCJk3$eJx_S)@wEP_}@!)EB!$#1Bp^k~U;ZB;9nzr{}} zc}y>eJ3H%>^Mk(VT{BOp@<xpHP=;qJg0S{4eYz2QV_?nm&kF?ygWv-T>972AZR3Z< z(u?aZ`l~V&zsA-j%e(VnQ-5BF+Hr4dSH2HU%{~$GVKycaRZ#pkekUtjHr3WPgyxxi ze#0B|q;mznS--?jp2#PClt__aTRHy007(a8XqdU`z*p<KaES;DeVFgi+W0<in?o+o zT5M%Bv#LQ(Rj<jknzdL{H^@z4HQ7?7^1Ot8S=DITM)S#X&_4sQG8z9e5*48FPVo9d ST^jJGgB;OrsB+|~q`v@m4g+=o literal 0 HcmV?d00001 diff --git a/src/core/static/images/mediaPdf.png b/src/core/static/images/mediaPdf.png new file mode 100644 index 0000000000000000000000000000000000000000..2d2b355f145e0cac1e2079aaf87c71cf788698da GIT binary patch literal 3852 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 VwVpwD`i~S~e%Z?8g^^3*e*hSWF)siB literal 0 HcmV?d00001 diff --git a/src/core/static/images/mediaVideo.png b/src/core/static/images/mediaVideo.png new file mode 100644 index 0000000000000000000000000000000000000000..6c850c5b2c8d121ababcde493160e4410c7b06c2 GIT binary patch literal 2713 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 literal 0 HcmV?d00001 diff --git a/src/core/static/images/noimage.jpg b/src/core/static/images/noimage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e91748bf0119b668fab3e5dd999991f8ae42d471 GIT binary patch literal 1315 zcmex=<NpH&0WUXCHwH!~28I+MWcdGvLC~c%IlGd9k%5JQfgu1W^p1hgF(p4Kl_BK- zP=xXSZH5*GCOBXQvY1(bBr^*u3ka~Xv4Q~`8#_A(J3AXECl?ndCl4xMWM*b&WntxH zW8>uI=H%w(=K}(Mey}1a#RK7?>VxzCA7BvV0J)i&QILU2kdaxC@&6Hq44|`_m>C&? z?t}q0cA&#JI8nsFasmvDEKE#bhd|VVv;ti(D5Pj8%&sINYNRaYnCPS`E{JR#Sn2;; z3_Q$0<$}zD4E7Aae>6}Enxoz}ht1vXxc6*E$`pfnmM<>7v;6l*VW~m9(VX+gBy}JD zu-|Yl@zwRs6R$0u{bkc*<#}s*Czwx`xp3<G*1NTp`K!G+v$xgGx14tN@s~GgmRC$q ztF<{BPn(ryRK2!$k|%4$!rmj>3_i#!&;7MCBlGbT*<S06$*HR+_kFYe@bhln?~m1N z8eVECVG+l?WJUHy#EVQkb$sK|wJP$uECNmI&ec3rQ(7whpW)cySF+bNS3i~gZZjkE zk*wwB3G&-6KGJ$OVZ$$e+5T0WeRn@8f8BfD?TXf;{mN=r6VINEF)GQG@V_j4;=#9) z^?bbf{k(<$I*j6f3QpPQa_ptLRDAz-k%HUjr%&6&Gj+!DjbZcS_6YsRI`OFT<7xKQ zO+269+?Go>oqZ&8i{T~5wO*%Y_M8igoGrX=pPK)-3+~J^v6n0*QYs60)mLQq=Pf*Y z;=Q%4j~bhM)`rL5V)h-lTbGmi+Q@9Nitfz&g}iM}u{!>OOvkGeCe$=IIvO1E-f=Q1 zaZ}*o&{fKR+aKpfY*d^)@!{E7dldLAKXE#$IXE~joz&$m@%n?yy-#POA|B-{6g@X+ zu(aV1YCiK@{OIrcKbL*_V~-y*=i0SSJMvCJ-YhY*s}YOZH+=8@yI9roR?P9T2U|{D zsN2wVW`UWkxc262X{+ng4?O?0IjzuqBmc^G2X(h?y`~-6b+zkB-RqcVwoA{xdMA6O zU-9n64KuCePj0?>>&^1ncZ!y)=F7`81%^qiKJ2%K&8^|O<%a8-mHB;7?+7tyXzh}h ze!eE=c=(xzhc^nnzugzCbJ>PZzVpoGla6tIEG_fP-$ht8-YEWRQc%Go^{;uac!JSw zT`}Le$KLGd+U#@kVfil`S#8lrTl{yp8=tqCEXKd0x}o%mh~%1@#H~+C&o-yl`K$Kd zH>#{Gn-z6n-ppmUuPl-8U9Ympe7@*|F7=7#@mK$;v<Owac(y^z?AP=yXZkL#e|P;@ z(jJSOtGGqe=j|~(?{{I^)jEqwa%U%*Tkf%L7d-Gp;r@Yb?O7MDoXa?S_FDfF{&Ty1 zQ&*MGGI+Nt>O}MU^CJ3&I}fhQo@2MbyE31pb^GGS1wU?w&+h!ud0&R}QRc>q@Iwx_ eZDqe4s~0aid{VYk_7?m4c>$3eR0j6{Zvp^uEBSW- literal 0 HcmV?d00001 diff --git a/src/core/static/images/picker.gif b/src/core/static/images/picker.gif new file mode 100755 index 0000000000000000000000000000000000000000..d42895f29d932684b6b3620e9d678db60974c107 GIT binary patch literal 332 zcmZ?wbhEHb6lM@)xT?XhefxGXF|mF7_KAv$+S%D{*s$UI_wV1neQR%Tzjx=NgoK2d znORLu&ECCx{r&ydu3dZY&IMarTRS`36)RROTC`~Y{{2rLUJMTppV;5JW#f`{>())5 z(iIvKvSaJYA3uKFxpls+t?lmZ3&Fv`=H_OGhK6QlrUnKE|NsAIpb}90$->CMpuwO6 zG7sb@2ewRyDFq%XvwV&wE-J7xVADt`@><K~%Wx!BQ7X4<!DL5<t+RY3b((@#waHCh ztf{1{ca*7h=Oa#*GY!sS5h_AyEDYR{d}^{`@@hRSf)Zf@{OTe+?ku64QWf>neAsyx RrSY<-G&)tS(Qst21^_QCW{Us- literal 0 HcmV?d00001 diff --git a/src/core/static/images/preload.gif b/src/core/static/images/preload.gif new file mode 100755 index 0000000000000000000000000000000000000000..283622fcaa19a09f7f08c59b99978a7232130593 GIT binary patch literal 735 zcmZ?wbhEHb6krfw*v!jdZ*RYU|9&kkt<ccW`uciNQBem6hlGTL0|yT1>+4ULFya6I z{|pQa5E95x{Lk&@8WQa67~pE8XTZz|68g!)$-uzNpaWzB4HaNuV6onC(sT7*i`QqX zWjTxrPHa+G(wVp5g=AM!fa@fYDMBn<QyCgu@|Fw8@HNFxV45t;(c=8Jt<ufXZHX!q zHuG%2=9MX!7`UEpsu0$gH0jvHwnY*di&+|l&X?ZVw^2og-SLfsf=t^{XT^yc33Ufq z7$$UhuH2Y<S%?vvfp!~CS_()RXKxX^G<l&0+w;arLM&dT3wuu;n(1+=w?KwTPnPA- z!RriMomO&zK^`hxM?ePpt={*n_~ctRtbPU>nK{MCI9s&o(qy0k&v`kFQrI13uD0rM zAKK+^c73Ktn#R;66Ffv5768q1$eQAl-j*>XYW<BhWv5GV8mW0s(D=3UiHpG#Ral<` z12Bb?LFMXFmc~Q7JRwGkX55fa5MWMX+ZdrRMR=L8mZ8#0kdb$>8)>`YWMq(*@oN@` zO9_W74;6AG2FC(jnR#vB$B=oYX&PM<&AS{NK63Nb?~coDaNw!yILgF0HK^F<dA@Wv zR)0g{=Ek%sUh{x%n=jIry18_vicI?iIhMjRUt{-uOxNIY_7ddKFkog$axh5}=w^K+ zUgIXX^2sIaaRV_Bn0R*22d0)7CI-*SWziO1%uPH~fZ+-ZPA6d8I39PF5aD7D@aQ}% R(%5jQ?XbhrImsXctpPIn>cRj3 literal 0 HcmV?d00001 diff --git a/src/core/static/images/slider_cursor.gif b/src/core/static/images/slider_cursor.gif new file mode 100755 index 0000000000000000000000000000000000000000..d9b02af59a18b40877cb6fdb6612b3b7f4e3a762 GIT binary patch literal 60 zcmZ?wbhEHb<Yr)Fn8*ME|NsAYSqLQlEB<6*WME)s&;f~p<QbTF=jbli*m?O;*Ov?2 I?{yih0V#eHO#lD@ literal 0 HcmV?d00001 diff --git a/src/core/static/js/Glizy.js b/src/core/static/js/Glizy.js new file mode 100644 index 0000000..dba5d9d --- /dev/null +++ b/src/core/static/js/Glizy.js @@ -0,0 +1,333 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +var Glizy = new (function(){ + this.slideShowSpeed = 20; + this.modulesMap = {}; + + var oopManager = function(){ + this.classMap = {}; + this.declare = function(name, def) { + this.classMap[name] = dejavu.Class.declare(def); + }; + + this.get = function(name) { + return this.classMap[name]; + }; + + this.create = function(name) { + var args = Array.prototype.slice.call(arguments, 0); + var name = args.shift(); + return !this.classMap[name] ? null : new this.classMap[name]( + args[0] !== undefined ? args[0] : undefined, + args[1] !== undefined ? args[1] : undefined, + args[2] !== undefined ? args[2] : undefined, + args[3] !== undefined ? args[3] : undefined, + args[4] !== undefined ? args[4] : undefined + ); + }; + + }; + this.oop = new oopManager(); + + + this.module = function(name, def) { + if (def) { + this.modulesMap[name] = def; + } else { + return new this.modulesMap[name]; + } + }; + + this.confirm = function (message, buttons, callback) { + callback(confirm(message)); + }; + + var eventMap; + this.events = {}; + this.events.broadcast = function(type, message) { + if (window.postMessage) { + window.top.postMessage({type: type, message: message}, window.top.location.href); + if (window.top!==window) window.postMessage({type: type, message: message}, window.top.location.href); + $('iframe', window.top.document).each(function(index, el){ + el.contentWindow.postMessage({type: type, message: message}, window.top.location.href); + }); + } + }; + + this.events.on = function(type, callback) { + $(document).on(type, callback); + if (window.postMessage) { + if (eventMap===undefined) { + eventMap = {}; + var triggeredFunction = function(e) { + if (eventMap[e.data.type]!==undefined) { + $(eventMap[e.data.type]).each(function(index, el){ + if (el) { + el({ + type: e.data.type, + message: e.data.message, + time: new Date() + }); + } + }); + } + } + + if (typeof window.addEventListener != 'undefined') { + window.addEventListener('message', triggeredFunction, false); + } else if (typeof window.attachEvent != 'undefined') { + window.attachEvent('onmessage', triggeredFunction); + } + } + + var pos; + if (eventMap[type]===undefined) { + eventMap[type] = []; + } + pos = eventMap[type].length; + eventMap[type].push(callback); + + return pos; + } + return null; + }; + + this.events.unbind = function(type, pos) { + $(document).unbind(type); + if (window.postMessage) { + if (eventMap[type]===undefined) { + eventMap[type] = []; + } + eventMap[type][pos] = null; + } + }; + + this.responder = function( owner, method ) { + return function( a, b, c, d ) { + if (typeof method=='function') { + method.call(owner, a, b, c, d ); + } else { + owner[method].call(owner, a, b, c, d ); + } + }; + }; + + var uiDialog = null; + + this.openDialog = function(el, options) { + if (window.self !== window.top) { + window.top.Glizy.openDialog(el, options); + return; + } + + uiDialog = jQuery(el).dialog(options); + } + + this.closeDialog = function() { + if (window.self !== window.top) { + window.top.Glizy.closeDialog(); + return; + } + + if (uiDialog) { + var result = {}; + uiDialog.find('select, input, textarea').each(function(index, el){ + var $el = jQuery(el); + result[$el.attr('id')] = $el.val(); + }); + this.events.broadcast("glizy.closeDialog", result); + uiDialog.dialog("destroy"); + } + } + + + this.openIFrameDialog = function(title, url, minWidth, widthOffset, heightOffset, openCallback, closeCallback) { + if (window.self !== window.top) { + window.top.Glizy.openIFrameDialog(title, url, minWidth, widthOffset, heightOffset, openCallback); + return; + } + if (!jQuery('#modalDiv').length) { + jQuery('body').append('<div id="modalDiv" style="display: none; padding: 0; overflow: hidden;"><iframe src="" id="modalIFrame" width="100%" height="100%" marginWidth="0" marginHeight="0" frameBorder="0" scrolling="auto"></iframe></div>'); + } + + if ( jQuery("#modalDiv").data( "isDialog" ) != "true" ) { + jQuery("#modalDiv").dialog({ + modal: true, + autoOpen: false, + draggable: true, + resizable: false, + open: openCallback, + close: closeCallback + }); + jQuery("#modalDiv").data( 'isDialog', 'true' ); + } + var w = Math.max( jQuery( window ).width() - widthOffset, minWidth ), + h = jQuery( window ).height() - heightOffset; + jQuery("#modalDiv").dialog( "option", { height: h, width: w, title: title } ); + jQuery("#modalDiv").dialog( "open" ); + + if ( jQuery("#modalIFrame").attr( "src") != url ) + { + jQuery("#modalIFrame").attr( "src", url ); + } + }; + + this.closeIFrameDialog= function(removeFromDom) { + if (window.self !== window.top) { + window.top.Glizy.closeIFrameDialog(removeFromDom); + return; + } + jQuery("#modalDiv").dialog('close'); + + if (removeFromDom) { + jQuery("#modalDiv").remove(); + } + }; + + this.externalLinks = function() { + jQuery("a[rel='external']").attr("target", "_blank"); + }; + + +})(); + +Glizy.superzoom = new(function() { + var self = this; + this.zoomViewer = null; + + this.init = function() { + jQuery('span.js-glizySuperZoom') + .each(function(index, el){ + var $el = jQuery(el); + var $img = $el.prev(); + $el.parent().css({position: 'relative', display: 'inline-block'}); + $el.hide(); + var setPos = function() { + if ($img.width()<300) { + $el.addClass('small'); + } + $el.css({ + position: 'absolute', + top: $img.height() - parseInt($img.css('border-top-width').replace('px')) - parseInt($img.css('padding-top').replace('px')) - $el.height(), + left: parseInt($img.css('padding-left').replace('px')) + parseInt($img.css('border-left-width').replace('px')) + }); + $el.show(); + } + if ($img.width()) { + setPos(); + } else { + setTimeout(setPos, 500); + } + }) + .click(function(e){ + e.preventDefault(); + e.stopPropagation(); + self.openZoom(jQuery(this).data('mediaid'), jQuery(this).data('mediawatermark')); + }); + }; + + this.openZoom = function( id, watermark ) { + var zoomContainer = jQuery('#zoomContainer'); + var zoomFile = zoomContainer.data('cache')+"/zoom_"+id+"_"+watermark+".xml"; + if ( this.zoomViewer == null ) { + SeadragonConfig.imgPath = "static/"; + this.zoomViewer = new Seadragon.Viewer("zoomContainer"); + this.zoomViewer.setFullPage( true ); + this.zoomViewer.onFullPage = function() { + self.zoomViewer.close(); + zoomContainer.hide(); + } + } + var url = "zoom.php?id="+id+"&w="+watermark; + Seadragon.Utils.makeAjaxRequest(url, function(xhr) { + zoomContainer.show(); + self.zoomViewer.setFullPage( true ); + self.zoomViewer.openDzi(zoomFile); + }); + }; +}); + +Glizy.template = new(function(){ + var templatesCache = {}; + var templates = {}; + + this.define = function(name, tpl) { + templates[name] = tpl; + templatesCache[name] = undefined; + } + + this.render = function(name, data) { + if (!templates[name]) { + console.error('Template not defined: '+name); + return ''; + } + if (!templatesCache[name]) { + templatesCache[name] = _.template(templates[name]); + } + return templatesCache[name](data); + } +}); + +Glizy.message = new(function() { + var notify = { + history: false, + type: "success", + animate_speed: "fast", + sticker: false, + delay: 3000, + addclass: "stack-bar-top", + styling: "fontawesome", + cornerclass: "", + width: "100%", + stack: {"dir1": "down", "dir2": "right", "push": "top", "spacing1": 0, "spacing2": 0} + }; + + this.showSuccess = function(title, message) { + notify.title = title; + notify.text = message; + notify.type = "success"; + $.pnotify(notify); + }; + this.showError = function(title, message) { + notify.title = title; + notify.text = message; + notify.type = "error"; + $.pnotify(notify); + }; + this.showWarning = function(title, message) { + notify.title = title; + notify.text = message; + notify.type = "notice"; + $.pnotify(notify); + }; + this.confirm = function(title, message) { + return confirm(message); + }; + + if (window==window.top) { + var self = this; + Glizy.events.on("glizy.message.showSuccess", function(e){ + self.showSuccess(e.message.title, e.message.message); + }); + Glizy.events.on("glizy.message.showError", function(e){ + self.showError(e.message.title, e.message.message); + }); + Glizy.events.on("glizy.message.showWarning", function(e){ + self.showWarning(e.message.title, e.message.message); + }); + } +}); + +try { + Glizy.$ = jQuery; + jQuery(function(){ + Glizy.externalLinks(); + Glizy.superzoom.init(); + }) +} catch (e) {} diff --git a/src/core/static/js/Glizy_pageContent.js b/src/core/static/js/Glizy_pageContent.js new file mode 100644 index 0000000..d9b3152 --- /dev/null +++ b/src/core/static/js/Glizy_pageContent.js @@ -0,0 +1,2620 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +Glizy.pageContent.$ = function( sel) { + return jQuery( sel )[ 0 ]; +} + +Glizy.pageContent.$all = function( sel) { + return jQuery( sel ); +} + +if ( !Glizy.pageContent_widgets ) +{ + Glizy.pageContent_widgets = {}; +} + +Glizy.pageContent_widgets._registredWidgets = {}; +Glizy.pageContent_widgets.callMethod = function( id, method, arg ) +{ + var widget = Glizy.pageContent_widgets._registredWidgets[ id ]; + if ( widget ) + { + widget[ method ].call( widget, arg ); + } +} + +Glizy.pageContent_widgets.Text = function() +{ + this.properties = null; + this.element = null; + this.elementId = null; + this.self = this; + this.init = function(oEl) + { + this.properties = oEl; + this.elementId = oEl.name; + oEl._obj = this; + var html = '<input type="text" id="'+oEl.name+'" value="'+oEl.value.replace(/\"/gi,"&quot;")+'" alt="" size="'+oEl.size+'"'+(oEl.disabled?' disabled="disabled"':'')+(oEl.readOnly?' readOnly="true"':'')+(oEl.maxLength?' maxlength="'+oEl.maxLength+'"':'')+'/>'; + return html; + }; + + this.getValue = function() + { + if (!this.element) this.element = document.getElementById(this.properties.name); + return this.element.value; + } + + this.setValue = function(val) + { + if (!this.element) this.element = document.getElementById(this.properties.name); + this.element.value = val; + } +} + +Glizy.pageContent_widgets.Date = function() +{ + this.properties = null; + this.element = null; + this.elementId = null; + this.self = this; + this.init = function(oEl) + { + Glizy.pageContent_widgets._registredWidgets[ oEl.name ] = this; + this.properties = oEl; + this.elementId = oEl.name; + oEl._obj = this; + var html = '<input type="text" id="'+oEl.name+'" value="'+oEl.value+'" autocomplete="off" size="'+( oEl.type == "date" ? '10' : '20' )+'" />'; + return html; + }; + + this.refine = function() + { + $( "#"+this.properties.name ).datepicker().datepicker( "option", "dateFormat", "dd/mm/yy" ); + $( "#"+this.properties.name ).val( this.properties.value ); + } + + this.getValue = function() + { + if (!this.element) this.element = document.getElementById(this.properties.name); + return this.element.value; + } + + this.setValue = function(val) + { + if (!this.element) this.element = document.getElementById(this.properties.name); + this.element.value = val; + } +} + +Glizy.pageContent_widgets.ImageSelect = function() +{ + this.properties = null; + this.element = null; + this.elementId = null; + this.self = this; + this.init = function(oEl) + { + this.properties = oEl; + this.elementId = oEl.name; + oEl._obj = this; + + var html = ''; + var value = ''; + html += '<div id="cpanel_'+oEl.name+'" class="cpanel">'; + for (var i=0;i<oEl.options.length;i++) + { + html += '<div class="icon"><a href="#" class="'+(oEl.options[i][2] ? 'selected' : '')+'" onclick="return Glizy.pageContent_widgets.ImageSelect_onclick(this, \''+oEl.name+'\', \''+oEl.options[i][1]+'\');">'; + html += '<img src="'+oEl.options[i][3]+'" alt="'+oEl.options[i][0]+'" align="middle" border="0">'; + html += '<span>'+oEl.options[i][0]+'</span></a></div>'; + + if (oEl.options[i][2]) + { + var value = oEl.options[i][1]; + } + } + + html += '<input type="hidden" id="'+oEl.name+'" value="'+value+'" alt="" /><div class="clear"></div></div>'; + return html; + }; + + this.getValue = function() + { + if (!this.element) this.element = document.getElementById(this.properties.name); + return this.element.value; + }; + + this.setValue = function(val) + { + if (!this.element) this.element = document.getElementById(this.properties.name); + this.element.value = val; + }; + +} + +Glizy.pageContent_widgets.ImageSelect_onclick = function(el, elName, val) +{ + var olEl = Glizy.pageContent.$all('#cpanel_'+elName+' a.selected'); + if (olEl.length) olEl[0].className = ''; + el.className = 'selected'; + var el = document.getElementById(elName); + el.value = val; + return false; +} + +Glizy.pageContent_widgets.EditableSelect = function() +{ + this.properties = null; + this.element = null; + this.elementId = null; + this.self = this; + this.init = function(oEl) + { + this.properties = oEl; + this.elementId = oEl.name; + oEl._obj = this; + + var html = ''; + + html += '<input type="text" id="'+oEl.name+'" value="'+oEl.value.replace(/\"/gi,"&quot;")+'" size="'+oEl.size+'"'+(oEl.disabled?' disabled="disabled"':'')+'/>'; + html += '<img src="../static/org_glizy/assets/images/icon_add.gif" onclick="Glizy.pageContent_widgets.EditableSelect_onclick('+(oEl.append ? true:false)+', \''+oEl.name+'\',\''+oEl.delimiter+'\')" class="iconAction" />'; + html += '<select id="sel__'+oEl.name+'" size="'+(oEl.options.length>10 ? 10 : oEl.options.length+1)+'" style="position: absolute; display: none;">'; + html += '<option value=""></option>'; + + for (var i=0;i<oEl.options.length;i++) + { + + html += '<option value="'+oEl.options[i][1]+'">'+oEl.options[i][0]+'</option>'; + } + + html += '</select>'; + return html; + }; + + this.getValue = function() + { + if (!this.element) this.element = document.getElementById(this.properties.name); + return this.element.value; + }; + + this.setValue = function(val) + { + if (!this.element) this.element = document.getElementById(this.properties.name); + this.element.value = val; + }; + +} + +Glizy.pageContent_widgets.EditableSelect_onclick = function(append, elName, delimiter) +{ + var inputEl = Glizy.pageContent.$("#"+elName); + if (inputEl) + { + var selectEl = Glizy.pageContent.$('#sel__'+elName); + if (selectEl) + { + Glizy.pageContent.aSelect = document.getElementsByTagName("select"); + for (var i=0; i< Glizy.pageContent.aSelect.length; i++) + { + Glizy.pageContent.aSelect[i].style.visibility = "hidden"; + } + + var sb = Glizy.pageContent.$all(".mceToolbar"); + if ( sb.length ) + { + for( var i=0; i < sb.length; i++ ) + { + sb[i].style.visibility = "hidden"; + } + } + var offset = jQuery(inputEl).offset(); + selectEl.style.left = ( offset.left - 2 )+"px"; + selectEl.style.top = ( offset.top -2)+"px"; + selectEl.style.width = jQuery(inputEl).width() +"px"; + selectEl.style.display = "inline"; + selectEl.style.visibility = "visible"; + selectEl.style.zIndex = 100; + selectEl.style.height = "auto"; + selectEl._parentObj = inputEl; + selectEl._append = append; + selectEl.selectedIndex = 0; + selectEl.focus(); + selectEl.onchange = function() + { + for (var i=0; i< Glizy.pageContent.aSelect.length; i++) + { + Glizy.pageContent.aSelect[i].style.visibility = "visible"; + } + var sb = Glizy.pageContent.$all(".mceToolbar"); + if ( sb.length ) + { + for( var i=0; i < sb.length; i++ ) + { + sb[i].style.visibility = "visible"; + } + } + this.style.display = "none"; + if (this.selectedIndex==0) return false; + if (this._append) + { + this._parentObj.value += (this._parentObj.value=='' ? '' : delimiter)+this.options[this.selectedIndex].text; + } + else + { + this._parentObj.value = this.options[this.selectedIndex].text; + } + this._parentObj.focus(); + return false; + }; + selectEl.onblur = function() + { + for (var i=0; i< Glizy.pageContent.aSelect.length; i++) + { + Glizy.pageContent.aSelect[i].style.visibility = "visible"; + } + var sb = Glizy.pageContent.$all(".mceToolbar"); + if ( sb.length ) + { + for( var i=0; i < sb.length; i++ ) + { + sb[i].style.visibility = "visible"; + } + } + this.style.display = "none"; + this._parentObj.focus(); + }; + } + } +} + + + +Glizy.pageContent_widgets.EditableSelectThesaurus = function() +{ + this.elForPicker = null; + this.properties = null; + this.element = null; + this.elementId = null; + this.self = this; + this.mode = "0"; + this.init = function(oEl) + { + Glizy.pageContent_widgets._registredWidgets[ oEl.name ] = this; + this.properties = oEl; + this.elementId = oEl.name; + oEl._obj = this; + + var html = '<input type="hidden" id="'+oEl.name+'" value="'+oEl.value.replace(/\"/gi,"&quot;")+'" />'; + html += '<div id="'+oEl.name+'_thesaurus" class="thesaurus"></div>'; + html += '<img id="'+oEl.name+'_btn2" src="../static/org_glizy/assets/images/icon_addThesaurus.gif" onclick="Glizy.pageContent_widgets.callMethod( \''+oEl.name+'\', \'openThesaurus\')" class="iconAction" />'; + + return html; + }; + + this.refine = function() + { + this.updateState(); + }; + + this.updateState = function() + { + var value = document.getElementById(this.properties.name).value + var html = ""; + // disegna i valori + // __pico__http://culturaitalia.it/pico/thesaurus/4.1#web_designer"Web designer",http://culturaitalia.it/pico/thesaurus/4.1#designer_di_interni_e_allestimenti"Designer di interni e allestimenti" + if ( value != "" ) + { + value = value.substring( 8 ) + var aValues = value.split( "," ); + for( var i=0; i < aValues.length; i++ ) + { + var part = aValues[ i ].split( "\"" ); + html += "<div class=\"thesaurusItem\">"+part[ 1 ]+"<a href=\"#\" onclick=\"Glizy.pageContent_widgets.callMethod( '"+this.properties.name+"', 'removeThesaurus', '"+part[ 0 ]+"');return false;\"></a></div>"; + } + } + + document.getElementById(this.properties.name+"_thesaurus").innerHTML = html; + }; + + this.removeThesaurus = function( id ) + { + var value = document.getElementById(this.properties.name).value; + value = value.substring( 8 ) + var aValues = value.split( "," ); + var newValues = []; + for( var i=0; i < aValues.length; i++ ) + { + var part = aValues[ i ].split( "\"" ); + if ( part[ 0 ] != id ) + { + newValues.push( aValues[ i ] ); + } + } + + if ( newValues.length ) + { + document.getElementById(this.properties.name).value = "__pico__"+newValues.join(",") + } + else + { + document.getElementById(this.properties.name).value = ""; + } + this.updateState(); + }; + + this.openThesaurus = function() + { + Glizy.pageContent_widgets.EditableSelectThesaurus.elForPicker = this.elementId; + Glizy.pageContent.openModalPicker( Glizy.pageContent.thesaurusSrc, "Seleziona voci da aggiungere al thesaurus PICO" ); + }; + + this.addThesaurus = function( newVal ) + { + var value = document.getElementById(this.properties.name).value; + if ( value.indexOf( newVal ) != -1 ) return; + if ( value == "" ) value = "__pico__"; + else value += ","; + value += newVal; + document.getElementById(this.properties.name).value = value; + this.updateState(); + Glizy.pageContent.closeModalPicker(); + }, + + this.getValue = function() + { + if (!this.element) this.element = document.getElementById(this.properties.name); + return this.element.value; + }; + + this.setValue = function(val) + { + if (!this.element) this.element = document.getElementById(this.properties.name); + this.element.value = val; + }; +} + + +// code based on http://code.google.com/p/locationpicker/ +Glizy.pageContent_widgets.Map = function() +{ + this.properties = null; + this.element = null; + this.elementId = null; + this.elementMap = null; + this.self = this; + this.map = null; + this.marker = null; + this.geocoder = null; + this.init = function(oEl) + { + Glizy.pageContent_widgets._registredWidgets[ oEl.name ] = this; + this.properties = oEl; + this.elementId = oEl.name; + oEl._obj = this; + + + var html = '<input type="text" id="'+oEl.name+'" value="'+oEl.value.replace(/\"/gi,"&quot;")+'" alt="" size="30" />'; + html += '<input id="'+oEl.name+'-search"class="mapPickerSearch" type="button" value="Cerca"/>'; + html += '<div id="'+oEl.name+'-picker" class="mapPicker" style="left: 230px; width: 400px; height: 400px; background: #fff; border: 1px solid #ccc; padding: 5px; position: absolute; z-index: 3000; display: none;"></div>'; + return html; + }; + + this.refine = function() + { + var self = this; + this.geocoder = new google.maps.Geocoder(); + this.element = document.getElementById( this.properties.name ); + + this.elementMap = document.getElementById(this.properties.name+"-picker"); + + var pos = this.getDefaultCurrentPosition(); + var latlng = new google.maps.LatLng(pos[ 0 ], pos[ 1 ]); + var myOptions = { + zoom: pos[ 2 ], + center: latlng, + mapTypeId: google.maps.MapTypeId.HYBRID, + mapTypeControl: false, + disableDoubleClickZoom: true, + streetViewControl: false + } + this.map = new google.maps.Map( this.elementMap, myOptions); + this.marker = new google.maps.Marker({ + position: latlng, + map: this.map, + title: "Trascinami", + draggable: true + }); + + + var self = this; + google.maps.event.addListener( this.map, 'dblclick', function(event) { + self.setPosition( event.latLng ); + }); + + google.maps.event.addListener( this.marker, 'dragend', function(event) { + self.setPosition( self.marker.position ); + }); + + google.maps.event.addListener( this.map, 'idle', function(event) { + self.setPositionValues(); + }); + + Glizy.pageContent.addEvent( this.elementMap, "click", function( e ) { + if ( e.stopPropagation ) { + e.stopPropagation(); + } + e.cancelBubble = true; + } ); + + Glizy.pageContent.addEvent( this.element, "click", function( e ) { + if ( e.stopPropagation ) { + e.stopPropagation(); + } + e.cancelBubble = true; + } ); + + Glizy.pageContent.addEvent( document, "click", function( e ) { + self.elementMap.style.display = "none"; + } ); + + + var elementBtn = document.getElementById(this.properties.name+"-search"); + Glizy.pageContent.addEvent( elementBtn, "click", function( e ) { + if ( e.stopPropagation ) { + e.stopPropagation(); + } + e.cancelBubble = true; + self.search(); + } ); + }; + + this.trim = function (str) + { + var str = str.replace(/^\s\s*/, ''), + ws = /\s/, + i = str.length; + while (ws.test(str.charAt(--i))); + return str.slice(0, i + 1); + } + + this.roundDecimal = function( num, decimals ) + { + var mag = Math.pow(10, decimals); + return Math.round(num * mag)/mag; + }; + + this.getDefaultCurrentPosition = function() + { + var posStr = this.getValue(); + if(posStr != "") + { + var posArr = posStr.split(","); + if(posArr.length == 2 || posArr.length == 3 ) + { + var lat = this.trim( posArr[0] ); + var lng = this.trim( posArr[1] ); + var zoom = posArr.length == 3 ? parseInt( this.trim( posArr[2] ) ) : 15; + return [lat, lng, zoom ]; + } + } + return [ 51.500152, -0.126236, 15 ]; + } + + this.getCurrentPosition = function() + { + var pos = this.getDefaultCurrentPosition(); + var latlng = new google.maps.LatLng(pos[ 0 ], pos[ 1 ]); + this.setPosition(latlng); + } + + this.setPosition = function(latLng, viewport) + { + var lat = this.roundDecimal( latLng.lat(), 6 ); + var lng = this.roundDecimal( latLng.lng(), 6 ); + this.marker.setPosition( latLng ); + var zoom; + if ( viewport ) + { + this.map.fitBounds( viewport ); + this.map.setZoom( this.map.getZoom() + 2); + zoom = this.map.getZoom() + 2; + } + else + { + this.map.panTo(latLng); + zoom = this.map.getZoom(); + } + this.map.setZoom( zoom ); + this.setValue( lat + "," + lng+","+zoom ); + } + + this.setPositionValues = function() + { + if( this.elementMap.style.display != "none") + { + var pos = this.getDefaultCurrentPosition(); + pos[ 2 ] = this.map.getZoom(); + this.setValue( pos.join( "," ) ); + } + } + + this.isLngLat = function (val) + { + var lngLatArr = val.split(","); + if(lngLatArr.length == 2 || lngLatArr.length == 3 ){ + if(isNaN(lngLatArr[0]) || isNaN(lngLatArr[1])){ + return false; + }else{ + return true; + } + } + return false; + } + + this.openMap = function() + { + this.elementMap.style.display = "block"; + google.maps.event.trigger( this.map, 'resize'); + this.getCurrentPosition(); + this.map.setCenter( this.marker.position ); + }; + + this.search = function() + { + this.findAddress(); + } + + this.findAddress = function() + { + var self = this; + var address = this.getValue(); + if(address == ""){ + alert("Inserire un indirizzo o le coordinate longitudine/latitudine."); + }else{ + if(this.isLngLat(address)){ + this.openMap(); + }else{ + this.geocoder.geocode( {'address': address, 'region': 'it'}, function(results, status) { + if (status == google.maps.GeocoderStatus.OK) { + self.setPosition( + results[0].geometry.location, + results[0].geometry.viewport + ); + self.openMap(); + } else { + alert("Geocode was not successful for the following reason: " + status); + } + }); + } + this.focus(); + } + } + + this.focus = function() + { + this.element.focus(); + } + + this.getValue = function() + { + return this.element.value; + } + + this.setValue = function(val) + { + this.element.value = val; + } +} + +with(navigator){ + Glizy.pageContent.b=0; + if(appName=="Microsoft Internet Explorer"){if(userAgent.indexOf("MSIE 6.0"))Glizy.pageContent.b=1} + else{if(product=="Gecko"&&appVersion.substring(0,1)=="5")Glizy.pageContent.b=2}; +} +if(self.Node) { + Node.prototype.swapNode = function (node) { + var nextSibling = this.nextSibling; + var parentNode = this.parentNode; + node.parentNode.replaceChild(this, node); + parentNode.insertBefore(node, nextSibling); + } +} + +if ( Glizy.tinyMCE_options ) +{ + Glizy.tinyMCE_options.internal_links = Glizy.pageContent.internalLinks || []; + Glizy.tinyMCE_options.image_picker = Glizy.pageContent.editorImgPicker || ""; + Glizy.tinyMCE_options.image_resizer = Glizy.pageContent.editorImgResizer || ""; + Glizy.tinyMCE_options.media_picker = Glizy.pageContent.editorMediaPicker || ""; + Glizy.tinyMCE_options.glizy_admin_path = Glizy.pageContent.editorAdminPath || ""; +} + +Glizy.pageContent.aHTML = []; +Glizy.pageContent.hO = []; +Glizy.pageContent.nF = 0; +Glizy.pageContent.nE = 0; +Glizy.pageContent.origMediaSrc = Glizy.pageContent.mediaSrc; + +Glizy.pageContent.buildHTML = function(name,oEl,loopItm) { + oEl.name = "elID"+Glizy.pageContent.nF; + this.aHTML.push('<div id="s'+oEl.name+'" class="formItem clearfix"'+( oEl.type == "hidden" ? ' style="display: none"' : '' )+'>'); + if (oEl.id) { + Glizy.pageContent.aId[oEl.id] = oEl.name; + } + Glizy.pageContent.nF++; + if ("repeater record static hidden".indexOf(oEl.type)<0 && oEl.label != false ) { + // MODIFICA DANIELE + this.aHTML.push('<label id="label_'+oEl.id+'" for="'+oEl.name+'" class="'+(oEl.required && oEl.required!=false ? 'required':'')+'">'+(oEl.label || name+"????")+'</label>'); + } + switch (oEl.type) { + // case "hidden": + // this.aHTML.push('</div>'); + // return; + case "text": + this.aHTML.push('<input type="text" id="'+oEl.name+'" value="'+oEl.value.replace(/\"/gi,"&quot;")+'" alt="" size="'+oEl.size+'"'+(oEl.disabled?' disabled="disabled"':'')+(oEl.readOnly?' readOnly="true"':'')+(oEl.maxLength?' maxlength="'+oEl.maxLength+'"':'')+'/>'); + //this.aHTML.push(new Glizy.pageContent_widgets.Text().init(oEl)); + break; + case "imageSelect": + this.aHTML.push(new Glizy.pageContent_widgets.ImageSelect().init(oEl)); + break; + case "editableSelect": + this.aHTML.push(new Glizy.pageContent_widgets.EditableSelect().init(oEl)); + break; + case "editableSelectThesaurus": + this.aHTML.push(new Glizy.pageContent_widgets.EditableSelectThesaurus().init(oEl)); + break; + case "map": + this.aHTML.push(new Glizy.pageContent_widgets.Map().init(oEl)); + break; + case "longtext": + this.aHTML.push('<textarea id="'+oEl.name+'"'); + this.aHTML.push(' rows="'+oEl.rows+'" cols="'+oEl.cols+'"'); + + if (!oEl.htmlEditor) + { + oEl.value = oEl.value.replace(/<br>/g, "\n"); + oEl.value = oEl.value.replace(/<br \/>/g, "\n"); + } + else + { + oEl.value = unescape( oEl.value ); + } + this.aHTML.push(oEl.maxLength ? ' onkeypress="event.keyCode=(this.value.length>='+oEl.maxLength+'?0:event.keyCode)"':''); + this.aHTML.push(' wrap="VIRTUAL">'+oEl.value+'</textarea>'); + if (oEl.htmlEditor) { + this.aHtmlEditables.push(oEl.name); + } + break; + case "image": + oEl.value = oEl.img_id; + this.aHTML.push(oEl.template.replace("##src##",oEl.src).replace("##title##",oEl.title).replace("></div"," onmousedown=\"Glizy.pageContent.changeImg(event,this,"+loopItm+")\" id=\""+oEl.name+"\"></div")); + break; + case "media": + this.aHTML.push('<input type="text" id="'+oEl.name+'" value="'+oEl.value+'" alt="" size="'+(oEl.size || 50)+'" readonly="readonly" style="cursor:pointer" onmousedown="Glizy.pageContent.changeMedia(event,this,'+loopItm+', \''+oEl.mediaType+'\')"/>'); + oEl.value = oEl.media_id; + break; + case "date": + case "datetime": + this.aHTML.push(new Glizy.pageContent_widgets.Date().init(oEl)); + + // this.aHTML.push('<input type="text" id="'+oEl.name+'" value="'+oEl.value+'" autocomplete="off" size="'+( oEl.type == "date" ? '10' : '20' )+'" />'); + // this.aHTML.push('<img src="'+Glizy.pageContent.iconPath+'calendar.gif" style="cursor: pointer; border: 1px solid red;" title="Date selector" onmouseover="this.style.background=\'red\';" onmouseout="this.style.background=\'\'" id="'+oEl.name+'bt"/>'); + // this.aCalendarAttach.push([ oEl.name, oEl.type ]); + break; + case "checkbox": + this.aHTML.push('<input id="'+oEl.name+'" type="checkbox"'+(oEl.value=="1"?' checked':'')+'/>'); + break; + case "radio": + this.aHTML.push('<input id="'+oEl.name+'" name="'+oEl.formName+'" type="radio"'+(oEl.value=="1"?' checked':'')+'/>'); + break; + case "helpedselect": + this.aHTML.push('<table class="listSimple" style="width:500px;table-layout:fixed"><tr>'); + + this.aHTML.push('<td width="33%" style="border:1px solid #CCC;border-bottom:0;padding:5px"><select id="'+oEl.name+'P0" style="margin-bottom:0;width:100%" onchange="Glizy.pageContent.helpedChange(\''+oEl.name+'P0\',\''+oEl.name+'S0\')"><option selected value="">'+pageTexts.searchOn+'</option>'); + for (var h=0;h<oEl.headers.length;h++) { + this.aHTML.push('<option value="'+oEl.headers[h][1]+'">'+oEl.headers[h][0]+'</option>'); + } + this.aHTML.push('</select></td>'); + this.aHTML.push('<td width="66%"><input id="'+oEl.name+'S0" style="margin-top:0;width:97%" disabled="disabled"/></td>'); + this.aHTML.push("</tr><tr>") + + this.aHTML.push('</tr><tr><td colSpan="3" style="background-color:#44A1FF;text-align:center"><button class="popupButton" onclick="Glizy.pageContent.getResult(\''+name+'\','+oEl.iconWidth+')">'+pageTexts.goSearch+'</button></tr>'); + this.aHTML.push('<tr><td colspan="3"><div id="'+oEl.name+'R" style="overflow: auto; width: 100%; height: 150px;"></div></td></tr>'); + this.aHTML.push('<tr><td colspan="3" style="background-color:#44A1FF;color:#FFF;text-align:center">'+pageTexts.selItems+'</tr>'); + this.aHTML.push('<tr><td colspan="3"><div style="width: 100%;">'); + this.aHTML.push('<table class="list" style="table-layout:fixed;width:100%" id="'+oEl.name+'V">'); + this.aHTML.push('<tr class="_ph"'+(oEl.options.length?' style="display:none"':'')+'><td width="'+oEl.iconWidth+'"></td><td></td></tr>'); + for (var s=0;s<oEl.options.length;s++) { + this.aHTML.push('<tr class="'+(s%2?"odd":"even")+'" value="'+oEl.options[s][1]+'">'); + this.aHTML.push('<td width="'+oEl.iconWidth+'">'); + if (oEl.options[s][2]) { + this.aHTML.push('<img style="width:'+oEl.iconWidth+'px;" src="'+oEl.options[s][2]+'"/>'); + } + this.aHTML.push('</td><td width="100%">'); + this.aHTML.push('<img style="float:right" onclick="Glizy.pageContent.delOption(event,\''+oEl.name+'\')" alt="'+pageTexts.del+'" src="'+Glizy.pageContent.iconPath+'icon_delete.gif" width="16" height="16" border="0"/>'); + if (oEl.options[s][3]) { + this.aHTML.push('<img style="float:right;cursor:pointer" onclick="Glizy.pageContent.pagePreview(\''+oEl.options[s][3]+'\')" alt="'+pageTexts.preview+'" src="'+Glizy.pageContent.iconPath+'icon_preview.gif" width="16" height="16" border="0"/>'); + } + this.aHTML.push('<span>'+oEl.options[s][0]+'</span>'); + this.aHTML.push('</td></tr>'); + } + this.aHTML.push('</table>'); + this.aHTML.push('</div></td></tr></table>'); + break; + case "select": + case "multipleselect": + this.aHTML.push('<select id="'+oEl.name+'"'+(oEl.target?' onchange="Glizy.pageContent.applyOpt(\''+oEl.target+'\',\''+name+'\',event)"':'')+(oEl.type=="multipleselect"?" multiple":"")+(oEl.size?" size='"+oEl.size+"'":"")+'>'); + oEl.value = ""; + if (oEl.options.length) { + for (var i=0;i<oEl.options.length;i++) { + this.aHTML.push('<option value="'+oEl.options[i][1]+'"'+(oEl.options[i][2]?' selected="selected"':'')+(oEl.options[i][4]?' disabled="disabled"':'')+'>'+oEl.options[i][0]+'</option>'); + if (oEl.options[i][2]) { + if (oEl.type=="select") { + oEl.value = oEl.options[i][1]; + } + else { + oEl.value += (","+i); + } + } + } + } + else { + for (var i in oEl.options) { + this.aHTML.push('<option value="'+oEl.options[i][1]+'"'+(oEl.options[i][2]?' selected="selected"':'')+(oEl.options[i][4]?' disabled="disabled"':'')+'>'+oEl.options[i][0]+'</option>'); + if (oEl.options[i][2]) { + if (oEl.type=="select") { + oEl.value = oEl.options[i][1]; + } + else { + oEl.value += ","+i; + } + } + } + } + this.aHTML.push('</select>'); + if (oEl.insertInto) { + this.aHTML.push('<button onclick="Glizy.pageContent.insertTag(\''+oEl.name+'\',\''+oEl.insertInto+'\')">'+pageTexts.ins+'</button>'); + } + if (oEl.target) { + this.aApplyOpts.push(name); + } + break; + case "colorPicker": + this.aHTML.push("<table cellpadding='2' class='colorpicker'><tr><td style=\"width:14px;border:1px solid #000000;background-color:"+oEl.value+";padding:2px;cursor:pointer\" onmousedown=\"Glizy.pageContent.changeColor(event)\">&nbsp;</td><td width=\"16\"></td><td style=\"padding:0px;\"><input style=\"border:1px solid #CCCCCC;font-family:monospace;width:60px;margin:0px\" id=\""+oEl.name+"\" value=\""+oEl.value+"\" onchange=\"Glizy.pageContent.chkColor(event)\"/></td><td width=\"16\"></td><td style=\"padding:0px;cursor:pointer\"><img src=\""+Glizy.pageContent.iconPath+"picker.gif\"/ onmousedown=\"Glizy.pageContent.changeColor(event)\"></td></tr></table>"); + break; + case "repeater": + this.aHTML.push("<fieldset class=\"repeater\">"); + if (oEl.title!='') this.aHTML.push("<legend>"+oEl.title+"</legend>"); + this.aHTML.push("<table width=\"100%\" class=\"list\">"); + if (!oEl.repeaterCmd) { + var aBld = []; + aBld.push("<img onclick=\"Glizy.pageContent.manageItem(event,'"+name+"',0)\" title=\""+pageTexts.addBefore+"\" src=\""+Glizy.pageContent.iconPath+"icon_add.gif\" width=\"16\" height=\"16\" border=\"0\"/>"); + aBld.push("<img onclick=\"Glizy.pageContent.manageItem(event,'"+name+"',1)\" title=\""+pageTexts.moveUp+"\" src=\""+Glizy.pageContent.iconPath+"icon_up.gif\" width=\"16\" height=\"16\" border=\"0\"/>"); + aBld.push("<img onclick=\"Glizy.pageContent.manageItem(event,'"+name+"',2)\" title=\""+pageTexts.moveDn+"\" src=\""+Glizy.pageContent.iconPath+"icon_down.gif\" width=\"16\" height=\"16\" border=\"0\"/>"); + aBld.push("<img onclick=\"Glizy.pageContent.manageItem(event,'"+name+"',3)\" title=\""+pageTexts.edit+"\" src=\""+Glizy.pageContent.iconPath+"icon_edit.gif\" width=\"16\" height=\"16\" border=\"0\"/>"); + aBld.push("<img onclick=\"if (confirm('"+pageTexts.confirmDel+"'))Glizy.pageContent.manageItem(event,'"+name+"',4)\" title=\""+pageTexts.del+"\" src=\""+Glizy.pageContent.iconPath+"icon_delete.gif\" width=\"16\" height=\"16\" border=\"0\"/>"); + oEl.repeaterCmd = aBld.join(""); + } + for (var i=0;i<oEl.items.length;i++) { + this.aHTML.push("<tr class=\""+(i%2?"odd":"even")+"\">"); + this.aHTML.push("<td title=\""+oEl.title+"\">"); + var n = 0; + for (var o in oEl.items[i]) { + n++; + if (n==1) { + var el = o; + } + } + var elName = name //+(i?"@"+i:"")+"-"+el + if (n==1) { + //if (oEl.items[i][el].type=="image") { + Glizy.pageContent.buildHTML(elName,oEl.items[i][el],true); + // } + // else { + // n = 2; + // oEl.emptyItem.type = "record"; + // oEl.emptyItem.dummy = {type:"hidden",value:""}; + // oEl.items[i].dummy = {type:"hidden",value:""}; + // } + } + if (n>1) { + with (oEl.items[i][el]) { + switch (type) { + case "date": + case "datetime": + case "media": + case "colorPicker": + case "text": + oEl.items[i].label = value; + break; + case "longtext": + oEl.items[i].label = value.substring(0,50)+(value.length>50?"...":""); + break; + case "image": + oEl.items[i].label = title; + break; + case "chekbox": + oEl.items[i].label = value?"true":"false"; + break; + case "select": + for (var o=0;o<options.length;o++) { + if (options[o][2]) break; + } + if (o>=options.length) o = 0; + oEl.items[i].label = options[o][0]; + break; + case "multipleselect": + var t = []; + for (var o=0;o<options.length;o++) { + if (options[o][2]) t.push(options[o][0]); + } + t = t.join(","); + oEl.items[i].label = t.substring(0,50)+t.length>50?"...":""; + break; + } + } + oEl.items[i].type = "record"; + oEl.items[i].repeaterName = elName+".items["+i+"]"; + Glizy.pageContent.buildHTML(elName,oEl.items[i],true); + } + this.aHTML.push("<td style=\"text-align: right\">"); + this.aHTML.push(oEl.repeaterCmd); + this.aHTML.push("</td>"); + this.aHTML.push("</tr>"); + } + this.aHTML.push("</table>"); + this.aHTML.push("<div class=\"formButtons\">"); + this.aHTML.push("<input type=\"button\" value=\""+pageTexts.addFirst+"\" class=\"button\" onClick=\"Glizy.pageContent.manageItem(event,'"+name+"',-1,null,0)\"/></td>"); + this.aHTML.push("<input type=\"button\" value=\""+pageTexts.addLast+"\" class=\"button\" onClick=\"Glizy.pageContent.manageItem(event,'"+name+"',-1,null,-1)\"/></td>"); + this.aHTML.push("</div>"); + // this.aHTML.push("<HR class=\"formRuler\" width=\"100%\">"); + this.aHTML.push("</fieldset>"); + break; + case "record": + this.aHTML.push('<label for="'+name+'" style=\"cursor:pointer\" onmousedown = \"Glizy.pageContent.manageItem(event,\''+name+'\',3)\">'+oEl.label+'</label>'); + this.aHTML.push('<table><tr><td style="border: 0; heigth: auto; padding: 0;" id="'+oEl.name+'"></td></tr></table>'); + break; + case "static": + // MODIFICA DANIELE + this.aHTML.push(oEl.value); + return; + default: + var comp = eval( "Glizy.pageContent_widgets."+oEl.type ); + if ( comp ) + { + this.aHTML.push( new comp().init(oEl) ); + } + } + //this.aHTML.push('<br class="return" />'); + this.aHTML.push('</div>'); +// oEl.value = oEl.type=="image"?oEl.src:oEl.value; + Glizy.pageContent.aSource.push(oEl); +} +Glizy.pageContent.aHtmlEditables = []; +Glizy.pageContent.aCalendarAttach = []; +Glizy.pageContent.aApplyOpts = []; +Glizy.pageContent.aSource = []; +Glizy.pageContent.clone = function(obj) { + var newObj = obj.length>=0?[]:{}; + for (var i in obj) { + if (typeof obj[i] != "object") { + newObj[i] = obj[i]; + } + else { + newObj[i] = Glizy.pageContent.clone(obj[i]); + } + } + return newObj; +} +Glizy.pageContent.manageItem = function(e,obj,op,isNew,newPos) { + var addNew = function(pCrepeater,row,e,index) { + var modalSim = Glizy.pageContent.modalSim || Glizy.pageContent.createElements("modalSim"); + modalSim.newRepeaterElement = [pCrepeater,row] + var newObj = Glizy.pageContent.clone(pCrepeater.emptyItem); + newObj.repeaterName = pCrepeater.objName+".items["+index+"]"; + newObj.name = "elID"+Glizy.pageContent.nF; + var els = 0; + var el; + for (var x in newObj) { + if (typeof newObj[x] == "object") { + els++; + el = el || newObj[x]; + newObj[x].name = "elID"+Glizy.pageContent.nF; + } + } + if (els>1) { + for (var x in newObj) { + if (typeof newObj[x] == "object") { + } + newObj.label = newObj.label || newObj[x].value+" "; + break; + } + } + Glizy.pageContent.nF++; + var cell = row.insertCell(-1); + if (els==1 && el.type=='image') + { + cell.innerHTML = '<span><label></label>'+el.template.replace("##src##",el.src).replace("##title##",el.title).replace("></div"," onmousedown=\"Glizy.pageContent.changeImg(event,this,true)\" id=\""+el.name+"\"></div")+'</span>'; + with (Glizy.pageContent) { + aSource.push(el); + refine(); + changeImg(null,cell.getElementsByTagName("img")[0],true); + } + } + else if (els==1 && el.type=='media') + { + cell.innerHTML = '<span><label>'+el.label+'</label><input type="text" id="'+el.name+'" value="'+el.value+'" alt="" size="'+(el.size || 50)+'" readonly="readonly" style="cursor:pointer" onmousedown="Glizy.pageContent.changeMedia(event,this,false, \''+el.mediaType+'\')"/>'+'</span>'; + with (Glizy.pageContent) { + aSource.push(el); + refine(); + changeMedia(null,cell.getElementsByTagName("input")[0],false,el.mediaType); + } + } + else + { + cell.innerHTML = '<span><label for="'+newObj.name+'" style=\"cursor:pointer\" onmousedown = \"Glizy.pageContent.manageItem(event,\''+pCrepeater.objName+'\',3)\">'+newObj.label+'</label><table><tr><td id="'+newObj.name+'"></td></tr></table>'+'</span>'; + Glizy.pageContent.manageItem(e,newObj,3,true); + } + cell = row.insertCell(-1); + cell.style.textAlign = "right"; + cell.innerHTML = pCrepeater.repeaterCmd; + Glizy.tablerulerReset( row ); + return newObj; + } + var pCrepeater,repeaterItm; + if (typeof obj == "object") { + repeaterItm = obj; + pCrepeater = obj.repeater; + } + else { + pCrepeater = eval("Glizy.pageContent."+obj); + pCrepeater.objName = obj; + } + obj = e?e.target||e.srcElement:document.getElementById(repeaterItm.name) + if (op<0) { + obj = obj.parentNode.previousSibling; + obj = obj.insertRow(newPos); + var newContent = addNew(pCrepeater,obj,null,newPos?pCrepeater.items.length:0); + if (newPos) { + pCrepeater.items.push(newContent); + } + else { + pCrepeater.items.unshift(newContent); + } + Glizy.pageContent.refine(); + } + else { + var row = obj; + while (row.tagName!="TR") { + row = row.parentNode; + } + var i = 0; + while (row.previousSibling) { + i++; + row = row.previousSibling; + } + repeaterItm = repeaterItm || pCrepeater.items[i]; + var els = 0; + var elType = ''; + var elMediaType = ''; + for (var k in repeaterItm) { + if (typeof repeaterItm[k] == "object") { + var pCelement = repeaterItm[k]; + elType = repeaterItm[k].type; + if ( repeaterItm[k].mediaType ) elMediaType = repeaterItm[k].mediaType; + els++; + } + } + switch (op) { + case 0: + var aL = []; + for (var j=0;j<i;j++) { + aL.push(pCrepeater.items[j]); + } + var o = obj.parentNode.parentNode; + var iIndex = 0; + while (o.previousSibling) { + iIndex ++; + o = o.previousSibling; + } + var row = o.parentNode.parentNode.insertRow(iIndex); + aL.push(addNew(pCrepeater,row,els>1?e || event:null,aL.length)); + for (var j=i;j<pCrepeater.items.length;j++) { + aL.push(pCrepeater.items[j]); + } + pCrepeater.items = aL; + break; + case 1: + if (i>0) { + var aL = []; + for (var j=0;j<i-1;j++) { + aL.push(pCrepeater.items[j]); + } + aL.push(pCrepeater.items[i]); + aL.push(pCrepeater.items[i-1]); + for (var j=i+1;j<pCrepeater.items.length;j++) { + aL.push(pCrepeater.items[j]); + } + pCrepeater.items = aL; + row = obj.parentNode.parentNode; + var pRow = row.previousSibling; + row.swapNode(pRow) + } + break; + case 2: + if (i<pCrepeater.items.length-1) { + var aL = []; + for (var j=0;j<i;j++) { + aL.push(pCrepeater.items[j]); + } + aL.push(pCrepeater.items[i+1]); + aL.push(pCrepeater.items[i]); + for (var j=i+2;j<pCrepeater.items.length;j++) { + aL.push(pCrepeater.items[j]); + } + pCrepeater.items = aL; + row = obj.parentNode.parentNode; + var nRow = row.nextSibling; + nRow.swapNode(row) + } + break; + case 3: + if (els==1 && elType=='image') { + Glizy.pageContent.changeImg(null,obj.parentNode.previousSibling.getElementsByTagName("img")[0],true); + } + else if (els==1 && elType=='media') + { + Glizy.pageContent.changeMedia(null,obj.parentNode.previousSibling.getElementsByTagName("input")[0],true,elMediaType) + } + else + { + Glizy.pageContent.popup(repeaterItm,isNew?repeaterItm:null); + } + break; + case 4: + var aL = []; + for (var j=0;j<i;j++) { + aL.push(pCrepeater.items[j]); + } + for (var j=i+1;j<pCrepeater.items.length;j++) { + aL.push(pCrepeater.items[j]); + } + pCrepeater.items = aL; + row.parentNode.parentNode.deleteRow(i); + break; + } + + if ( row ) Glizy.tablerulerReset( row ); + + } + if (op!=3) { + for (var i=0;i<pCrepeater.items.length;i++) { + for (o in pCrepeater.items[i]) { + var obj = pCrepeater.items[i]; + if (obj.type!="record") obj = obj[o]; + var obj = document.getElementById(obj.name); + while (obj.tagName!="TR") { + obj = obj.parentNode; + } + obj.className = i%2?"odd":"even" + break; + } + + } + } +} +Glizy.pageContent.changeImg = function(e,src,loopItm) { + var z = Glizy.pageContent.modal(true); + var imgPicker = Glizy.pageContent.imgPicker || Glizy.pageContent.createElements("imgPicker"); + var obj = src || e.target || e.srcElement; + with (imgPicker.style) { + top = (document.documentElement.scrollTop+20)+"px"; + left = ((document.documentElement.clientWidth-imgPicker.style.pixelWidth)/2)+"px"; + zIndex = z*10+5+100; + display = "block"; + } + var value = "0"; + if (src.source) { + value = src.source.value; + } + src.value = src.cur_id = value; + imgPicker.ico = src; + var label; + if (loopItm) { + label = src.parentNode.parentNode.getElementsByTagName("label")[0] + } + imgPicker.label = label +} +Glizy.pageContent.changeMedia = function(e,src,loopItm,mediaType) { + Glizy.pageContent.mediaSrc = Glizy.pageContent.origMediaSrc+"&mediaType="+mediaType; + var z = Glizy.pageContent.modal(true) + var mediaPicker = Glizy.pageContent.mediaPicker || Glizy.pageContent.createElements("mediaPicker"); + if ( mediaPicker.content.src != Glizy.pageContent.mediaSrc ) + { + mediaPicker.content.src = Glizy.pageContent.mediaSrc; + } + var obj = src || e.target || e.srcElement; + with (mediaPicker.style) { + top = (document.documentElement.scrollTop+20)+"px"; + left = ((document.documentElement.clientWidth-mediaPicker.style.pixelWidth)/2)+"px"; + zIndex = z*10+5+100; + display = "block"; + } + var label; + var value = "0"; + if (src.source) { + value = src.source.media_id; + } + src.media_id = src.cur_id = value; + mediaPicker.fld = src; + if (loopItm) { + label = src.parentNode.parentNode.getElementsByTagName("label")[0]; + } + mediaPicker.label = label +} +Glizy.pageContent.changeColor = function(e,src) { + var obj = src || e.target || e.srcElement; + while (obj.tagName!="TR") { + obj = obj.parentNode; + } + var z = Glizy.pageContent.modal(true) + var colorPicker = Glizy.pageContent.colorPicker || Glizy.pageContent.createElements("colorPicker"); + with (colorPicker.style) { + top = (document.documentElement.scrollTop+e.clientY)+"px"; + zIndex = z*10+5+100; + left = (document.documentElement.scrollLeft+e.clientX)+"px"; + display = "block"; + } + colorPicker.text = obj.getElementsByTagName("input")[0]; + var color = colorPicker.text.value; + colorPicker.setValue(color); + colorPicker.sample = obj.cells[0]; +} +Glizy.pageContent.chkColor = function(e) { + var obj = e.target || e.srcElement; + var sample = obj.parentNode.parentNode.firstChild; + var color = obj.value.toLowerCase(); + if (color.substring(0,1)!="#") { + color = "#"+color; + } + if (color.length!=7) { + obj.value = sample.style.backgroundColor; + } + else { + var pattern = "0123456789abcdef"; + for (var i=1;i<7;i++) { + if (pattern.indexOf(color.substring(i,i+1))<0) { + obj.value = sample.style.backgroundColor; + return; + } + } + obj.value = color; + sample.style.backgroundColor = color; + } +} +Glizy.pageContent.createElements = function(el,reference,newObj) { + var container = function(l,w,h,title,id) { + var obj = document.createElement("div"); + obj.className = "popupContainer"; + if( id) obj.id = "popupContainer_"+id; + with (obj.style) { + left = l+"px"; + width = w+"px"; + height = h+"px"; + } + var header = obj.header = document.createElement("div"); + obj.appendChild(header); + header.className = "popupHeader"; + header.onmousedown = function(e) { + e = e || event; + Glizy.pageContent.modalInfo = {x:e.screenX,y:e.screenY,o:obj}; + document.onmousemove = function(e) { + e = e || event; + with (Glizy.pageContent.modalInfo) { + o.style.top = (o.offsetTop+e.screenY-y)+"px"; + o.style.left = (o.offsetLeft+e.screenX-x)+"px"; + x = e.screenX; + y = e.screenY; + } + return false; + } + document.onmouseup = function(e) { + document.onmousemove = null; + if (Glizy.pageContent.modalInfo.o.header.contentFrame) { + Glizy.pageContent.modalInfo.o.header.contentFrame.contentWindow.document.onmousemove = null; + } + if (Glizy.pageContent.modalInfo.o.header.contentFrame) { + Glizy.pageContent.modalInfo.o.header.contentTopper.style.visibility = "hidden"; + } + } + if (this.contentFrame) { + this.contentTopper.style.visibility = "visible"; + } + /* + if (Glizy.pageContent.b==2 && this.contentFrame) { + this.contentFrame.contentWindow.document.onmousemove = function(e) { + with (Glizy.pageContent.modalInfo) { + o.style.top = (o.offsetTop+e.screenY-y)+"px"; + o.style.left = (o.offsetLeft+e.screenX-x)+"px"; + x = e.screenX; + y = e.screenY; + } + return false; + } + this.contentFrame.contentWindow.document.onmouseup = function() { + document.onmousemove = null; + this.contentFrame.contentWindow.document.onmousemove = null; + } + + } + */ + } + var bt = document.createElement("img"); + bt.className = "popupClose"; + bt.src = Glizy.pageContent.iconPath+"close_button.gif"; + bt.obj = obj; + bt.onmousedown = function() { + this.obj.style.display = "none"; + Glizy.pageContent.modal(false,true); + } + header.appendChild(bt); + var txt = document.createElement("span"); + txt.innerHTML = title; + header.appendChild(txt); + var footer = obj.footer = document.createElement("div"); + footer.className = "popupFooter"; + obj.appendChild(footer); + return obj; + } + switch (el) { + case "modalSim": + var obj = Glizy.pageContent.modalSim = document.createElement("div"); + obj.className = "modalSimulator"; + var cont = document.getElementById("container"); + obj.stack = []; + obj.resize = function(e) { + with (Glizy.pageContent.modalSim.style) { + width = document.documentElement.scrollWidth+"px"; + height = document.documentElement.scrollHeight+"px"; + } + } + if (window.addEventListener){ + addEventListener("resize",Glizy.pageContent.modalSim.resize,false); + } else if (window.attachEvent){ + attachEvent("onresize",Glizy.pageContent.modalSim.resize); + } + break; + case "imgPicker": + case "mediaPicker": + var obj = container(150,900,550,el=="imgPicker"?pageTexts.newImg:pageTexts.newMedia); + if (el=="imgPicker") { + Glizy.pageContent.imgPicker = obj; + } + else { + Glizy.pageContent.mediaPicker = obj; + } + obj.content = obj.header.contentFrame = document.createElement("iframe"); + obj.content.frameBorder = "0"; + with (obj.content.style) { + width = "100%"; + height = (parseFloat(obj.style.height)-20)+"px"; + } + obj.appendChild(obj.content); + obj.header.contentTopper = document.createElement("div"); + with (obj.header.contentTopper.style) { + position = "absolute"; + top = "16px"; + left = "0px"; + width = "100%"; + height = obj.content.style.height; + filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=0)"; + MozOpacity = opacity = 0; + backgroundColor = "#FFFFFF"; + visibility = "hidden"; + } + obj.appendChild(obj.header.contentTopper); + if (el=="imgPicker") { + obj.update = function(img_id,img_url,img_title,img_thumb) { + this.ico.src = img_thumb; + this.ico.title = img_title; + if (this.label) { + this.label.innerHTML = img_title; + } + this.ico.value = this.ico.source.value = img_id; + this.style.display = "none"; + Glizy.pageContent.modal(false); + } + } + else { + obj.update = function(media_id,media_url,media_title) { + this.fld.value = media_title; + this.fld.media_id = this.fld.source.media_id = media_id + this.style.display = "none"; + Glizy.pageContent.modal(false); + } + } + obj.content.src = el=="imgPicker"?Glizy.pageContent.imgSrc:Glizy.pageContent.mediaSrc; + break; + + case "colorPicker": + var cPslider = function(t,l,fc) { + var obj = document.createElement("div"); + obj.fc = fc; + with (obj.style) { + position = "absolute"; + top = t+"px"; + left = l+"px"; + width = (259-2*Glizy.pageContent.b)+"px"; + height = "6px"; + border = "1px inset threedhighlight"; + } + obj.onmousedown = function(e) { + var obj = e?e.target:event.srcElement; + obj.offsetParent.active = true; + } + for (var i=0;i<256;i++) { + var x = document.createElement("DIV"); + with (x.style) { + position = "absolute"; + left = i+"px"; + width = "1px"; + height = "6px"; + overflow = "hidden"; + } + x.sl = obj; + x.value = i; + x.onmousedown = function(e) { + var obj = e?e.target:event.srcElement; + Glizy.pageContent.CPon = true; + obj.sl.value = obj.value; + obj.sl.offsetParent.refresh(); + obj.sl.onmouseout = function() { + Glizy.pageContent.CPon = false; + } + } + x.onmouseover = function(e) { + var obj = e?e.target:event.srcElement; + if (Glizy.pageContent.CPon) { + obj.sl.value = obj.value; + obj.sl.parentElement.refresh(); + } + } + obj.appendChild(x) + } + obj.paint = function(a,k) { + var str0 = "#"; + for (var i=0;i<k;i++) { + str0 += (a[i]<16?"0":"")+a[i].toString(16); + } + var str1 = ""; + for (var i=k+1;i<3;i++) { + str1 += (a[i]<16?"0":"")+a[i].toString(16); + } + for (var i=0;i<256;i++) { + this.childNodes[i].style.backgroundColor = str0+(i<16?"0":"")+i.toString(16)+str1; + } + this.value = a[k]; + } + obj.value = 0; + obj.cursor = document.createElement("div"); + obj.cursor.obj = obj; + with (obj.cursor.style) { + position = "absolute"; + backgroundImage = "url("+Glizy.pageContent.iconPath+"slider_cursor.gif)"; + top = (t+7)+"px"; + left = l+"px"; + height = "6px"; + width = "11px"; + overflow = "hidden"; + } + obj.cursor.min = l-5; + obj.cursor.max = l+250; + obj.cursor.onmousedown = function(e) { + obj = e?e.target:event.srcElement; + e = e || event; + Glizy.pageContent.modalInfo = {x:e.screenX,o:obj}; + document.onmousemove = function(e) { + e = e || event; + with (Glizy.pageContent.modalInfo) { + o.style.left = Math.min(Math.max(o.offsetLeft+e.screenX-x,o.min),o.max)+"px"; + x = e.screenX; + o.result.style.backgroundColor = o.obj.childNodes[o.offsetLeft-o.min].style.backgroundColor; + } + return false; + } + document.onmouseup = function() { + document.onmousemove = null; + with (Glizy.pageContent.modalInfo) { + var code = o.obj.childNodes[o.offsetLeft-o.min].style.backgroundColor; + if (Glizy.pageContent.b==2) { + code = code.replace("rgb(","["); + code = code.replace(")","]"); + var rgb = eval(code); + code = "#"+(rgb[0]<16?"0":"")+rgb[0].toString(16)+(rgb[1]<16?"0":"")+rgb[1].toString(16)+(rgb[2]<16?"0":"")+rgb[2].toString(16); + } + o.picker.setValue(code); + } + } + } + return obj; + } + var cRainbow = function() { + var obj = document.createElement("img"); + obj.src = Glizy.pageContent.iconPath+"colorPicker.gif"; + with (obj.style) { + position = "absolute"; + border = "1px inset threedhighlight"; + } + var c = [0,1,2,3,4,5,6,7,8,9,"a","b","c","d","e","f"]; + var basic = [[15,15,15,0,0,0,15],[0,15,0,15,15,15,0],[0,0,15,15,15,0,0]]; + var palette = []; + var p = []; + for (var i=0;i<31;i++) { + palette[i] = []; + } + for (var i=0;i<6;i++) { + var cur = []; + for (var j=0;j<3;j++) { + cur.push(basic[j][i]) + } + var next = []; + for (var j=0;j<3;j++) { + next.push(basic[j][i+1]) + } + var d = []; + for (var j=0;j<3;j++) { + d[j] = cur[j]>next[j]?-1:cur[j]<next[j]?1:0; + } + while (cur[0]!=next[0] || cur[1]!=next[1] || cur[2]!=next[2]) { + p.push([cur[0],cur[1],cur[2]]); + palette[14].push("#"+c[cur[0]]+c[cur[0]]+c[cur[1]]+c[cur[1]]+c[cur[2]]+c[cur[2]]); + for (var j=0;j<3;j++) { + if (cur[j]!=next[j]) { + cur[j]+=d[j] //*2; + } + } + } + } + for (var i=0;i<p.length;i++) { + cur = [15,15,15]; + for (var j=0;j<3;j++) { + d[j] = (p[i][j]-cur[j])/14; + } + for (var r=0;r<14;r++) { + palette[r][i] = "#"+c[Math.round(cur[0])]+c[Math.round(cur[0])]+c[Math.round(cur[1])]+c[Math.round(cur[1])]+c[Math.round(cur[2])]+c[Math.round(cur[2])]; + for (var j=0;j<3;j++) { + cur[j]+=d[j]; + } + } + cur = p[i]; + for (var j=0;j<3;j++) { + d[j] = -p[i][j]/15; + } + for (var r=15;r<31;r++) { + palette[r][i] = "#"+c[Math.round(cur[0])]+c[Math.round(cur[0])]+c[Math.round(cur[1])]+c[Math.round(cur[1])]+c[Math.round(cur[2])]+c[Math.round(cur[2])]; + for (var j=0;j<3;j++) { + cur[j]+=d[j]; + } + } + } + var r = palette.length-2; + var c = palette[0].length; + with (obj.style) { + width = (c+1)*4-2*Glizy.pageContent.b; + height = r+2-2*Glizy.pageContent.b; + } + obj.palette = palette; + obj.onmousedown = function(e) { + if (e) { + var x = e.layerX; + var y = e.layerY; + } + else { + var x = event.offsetX; + var y = event.offsetY; + } + var obj = e?e.target:event.srcElement; + var color = obj.palette[y][Math.floor(x/4)]; + obj.offsetParent.setValue(color); + } + return obj; + } + Glizy.pageContent.CPon = false; + var obj = Glizy.pageContent.colorPicker = container(0,318-2*Glizy.pageContent.b,140-2*Glizy.pageContent.b,pageTexts.color); + obj.footer.style.height = "24px"; + var bts = document.createElement("div"); + obj.footer.appendChild(bts); + with (bts.style) { + cssFloat = "right"; + paddingTop = "3px"; + } + obj.result = document.createElement("div"); + obj.appendChild(obj.result); + with (obj.result.style) { + position = "absolute"; + top = "28px"; + left = "6px"; + width = "36px"; + height = "40px"; + border = "1px inset threedhighlight"; + } + obj.close = document.createElement("button"); + obj.close.className = "popupButton"; + bts.appendChild(obj.close); + obj.close.innerHTML = pageTexts.cancel; + obj.close.style.marginRight = "10px"; + obj.close.obj = obj; + obj.close.onmousedown = function() { + this.obj.style.display = "none"; + Glizy.pageContent.modal(false,true); + } + obj.ok = document.createElement("button"); + obj.ok.className = "popupButton"; + bts.appendChild(obj.ok); + obj.ok.innerHTML = pageTexts.ok; + obj.ok.style.marginRight = "2px"; + obj.ok.sample = obj.result; + obj.ok.onmousedown = function() { + var code = this.sample.style.backgroundColor; + if (Glizy.pageContent.b==2) { + code = code.replace("rgb(","["); + code = code.replace(")","]"); + var rgb = eval(code); + code = "#"+(rgb[0]<16?"0":"")+rgb[0].toString(16)+(rgb[1]<16?"0":"")+rgb[1].toString(16)+(rgb[2]<16?"0":"")+rgb[2].toString(16); + } + this.sample.parentNode.text.value = code; + this.sample.parentNode.sample.style.backgroundColor = this.sample.style.backgroundColor; + Glizy.pageContent.modal(false); + Glizy.pageContent.colorPicker.style.display = "none"; + } + obj.r = cPslider(28,51,"r"); + obj.g = cPslider(44,51,"g"); + obj.b = cPslider(60,51,"b"); + obj.appendChild(obj.r); + obj.appendChild(obj.g); + obj.appendChild(obj.b); + obj.appendChild(obj.r.cursor); + obj.appendChild(obj.g.cursor); + obj.appendChild(obj.b.cursor); + obj.r.cursor.picker = obj; + obj.g.cursor.picker = obj; + obj.b.cursor.picker = obj; + obj.r.cursor.result = obj.result; + obj.g.cursor.result = obj.result; + obj.b.cursor.result = obj.result; + obj.rb = cRainbow(); + with (obj.rb.style) { + top = "78px"; + left = "6px"; + } + obj.appendChild(obj.rb); + obj.hex = []; + var str = "0123456789ABCDEF"; + for (var i=0;i<16;i++) { + obj.hex[str.substring(i,i+1)] = i; + } + obj.setValue = function(rgb) { + rgb = rgb || "#ffffff"; + this.result.style.backgroundColor = rgb; + var r = this.htd(rgb.substring(1,3).toUpperCase()); + var g = this.htd(rgb.substring(3,5).toUpperCase()); + var b = this.htd(rgb.substring(5,7).toUpperCase()); + this.r.paint([r,g,b],0); + this.g.paint([r,g,b],1); + this.b.paint([r,g,b],2); + this.r.cursor.style.left = (r+46)+"px"; + this.g.cursor.style.left = (g+46)+"px"; + this.b.cursor.style.left = (b+46)+"px"; + } + obj.htd = function(str) { + return this.hex[str.substring(0,1)]*16+this.hex[str.substring(1)] + } + obj.refresh = function() { + var r = this.r.value; + var g = this.g.value; + var b = this.b.value; + //this.r.paint([r,g,b],0); + //this.g.paint([r,g,b],1); + //this.b.paint([r,g,b],2); + var str = "#"+(r<16?"0":"")+r.toString(16)+(g<16?"0":"")+g.toString(16)+(b<16?"0":"")+b.toString(16) + this.setValue(str); //this.result.style.backgroundColor = str; + } + break; + case "popup": + var element = document.getElementById(reference.name) || reference; + while (element.tagName != "FIELDSET") { + element = element.parentNode; + } + var popupHeight = document.documentElement.clientHeight-100; + var obj = container(0,element.offsetWidth,popupHeight,"", reference.name); + var l = 0; + while (element && element!=document.body) { + l += element.offsetLeft; + element = element.offsetParent; + } + var objBg = obj.body = document.createElement("div"); + obj.appendChild(objBg); + with (objBg.style) { + height = (popupHeight-60)+"px"; + padding = "8px"; + overflow = "auto"; + } + obj.style.left = l+"px"; + obj.footer.style.height = "24px"; + var bts = document.createElement("div"); + obj.footer.appendChild(bts); + with (bts.style) { + bottom = "0px"; + paddingTop = "3px"; + paddingLeft = "10px"; + } + var bt = document.createElement("button"); + bt.className = "popupButton"; + bts.appendChild(bt); + bt.innerHTML = pageTexts.save; + bt.reference = reference; + bt.onmousedown = function(e) { + // MODIFICA DANIELE + Glizy.hideMessage( Glizy.pageContent.$( '#popupContainer_'+reference.name+' div.message-box2' ) ); + var obj = e?e.target:event.srcElement; + var aE = []; + var label; + for (var o in obj.reference) { + if (typeof obj.reference[o]=="object") { + var objO = obj.reference[o]; + var objP = document.getElementById(objO.name); + if (objP) { + var lbl; + switch (objO.type) { + case "date": + case "datetime": + case "media": + case "colorPicker": + case "text": + lbl = objP.value; + objO.value = objP.value; + break; + case "image": + lbl = objP.title; + objO.value = objP.value; + break; + case "longtext": + lbl = objP.value.substring(0,50)+(objP.value.length>50?"...":""); + objO.value = objP.value; + break; + case "chekbox": + lbl = objP.value?"true":"false"; + objO.value = objP.value; + break; + case "select": + if (objP.selectedIndex>=0) { + lbl = objP.options[objP.selectedIndex].text; + } + objO.value = objP.value; + break; + case "multipleselect": + var t = []; + objO.value = ""; + for (var o=0;o<objP.options.length;o++) { + if (objP.options[o].selected) { + t.push(objP.options[o].text); + objO.value += (","+o); + } + } + t = t.join(","); + lbl = t.substring(0,50)+t.length>50?"...":""; + break; + } + label = label || lbl; + + var skip = false; + var obj2 = document.getElementById("s"+objO.name); + if (obj2 && obj2.style.display=='none') skip = true; + if (objO.required && !skip) { + if (objO.required==1) { + if (!objP.value) { + aE.push(objO.requiredMessage) + } + } + else { + var value = escape(objP.value); + // MODIFICA DANIELE + var message = eval(objO.required+"(\""+value+"\",\""+objO.label+"\",\""+objO.type+"\",\""+objO.requiredMessage+"\")"); + if (message) { + aE.push(message); + } + } + } + } + } + } + if (aE.length) { +// alert(aE.join("\n")); + // MODIFICA DANIELE + Glizy.showWarningMessage(GlizyLocale.REQUIREDFIELDS, aE, Glizy.pageContent.$( '#popupContainer_'+reference.name+' div.message-box2' ) ); + } + else { + document.getElementById(obj.reference.name).parentNode.parentNode.parentNode.parentNode.parentNode.firstChild.firstChild.innerHTML = label; + Glizy.pageContent.modal(false); + (e?e.target:event.srcElement).parentNode.parentNode.parentNode.style.display = "none"; + } + } + var bt = document.createElement("button"); + bt.className = "popupButton"; + bts.appendChild(bt); + bt.style.marginLeft = "10px"; + bt.innerHTML = pageTexts.cancel; + bt.reference = reference; + bt.onmousedown = function(e) { + var obj = e?e.target:event.srcElement; + var first = true; + var valid = ""; + for (var oEl in obj.reference) { + if (obj.reference[oEl]) { + if (first) { + valid = obj.reference[oEl].value; + } + var target = document.getElementById(obj.reference[oEl].name); + if (target) { + switch (obj.reference[oEl].type) { + case "image": + //target.src = obj.reference[oEl].value; + //alert( obj.reference[oEl].img_id+" "+ obj.reference[oEl].value+" "+ obj.reference[oEl].cur_id) + target.src = obj.reference[oEl].src; + target.value = obj.reference[oEl].img_id; + break; + case "colorPicker": + target.value = obj.reference[oEl].value; + target.parentNode.previousSibling.previousSibling.style.backgroundColor = obj.reference[oEl].value; + break; + case "multipleselect": + for (var o=0;o<options.length;o++) { + target.options[o].selected = false; + } + var selected = obj.reference[oEl].value.split(","); + for (var o=0;o<selected.length;o++) { + target.options[selected[o]].selected = true; + } + default: + if (target.isRichText) { + tinyMCE.activeEditor.setContent( jQuery("#"+target.id).val() ); + } + target.value = obj.reference[oEl].value; + if (obj.reference[oEl].type=="media") { + target.media_id = target.cur_id; + } + break; + } + } + first = false; + } + } + Glizy.pageContent.modal(false,true); + (e?e.target:event.srcElement).parentNode.parentNode.parentNode.style.display = "none"; + } + Glizy.pageContent.aHTML = ['<div class="message-box2"></div>']; + for (var oEl in reference) { + if (typeof reference[oEl]=="object") { + Glizy.pageContent.buildHTML((reference.repeaterName?reference.repeaterName+".":"")+oEl,reference[oEl]) + } + } + document.body.appendChild(obj); + with (Glizy.pageContent) { + objBg.innerHTML = aHTML.join(""); + /* + while (true) { + var editable = aHtmlEditables.pop(); + if (editable) { + var element_contenuto = tinyMCE._getElementById(editable); + if (element_contenuto) tinyMCE.addMCEControl(element_contenuto, editable); + } + else break; + } + */ + } + } + if (el!="popup") document.body.appendChild(obj); + return obj; +} +Glizy.pageContent.modal = function(active,isNew) { + modalSim = Glizy.pageContent.modalSim || Glizy.pageContent.createElements("modalSim"); + if (active) { + with (modalSim.style) { + width = document.body.scrollWidth+"px"; + height = Math.max(document.documentElement.clientHeight,document.body.scrollHeight)+"px"; + zIndex = modalSim.stack.length*10+100; + display = "block"; + } + var allS = []; + for (var i=0;i<modalSim.stack.length;i++) { + allS = allS.concat(modalSim.stack[i][0]); + } + var aS = Glizy.pageContent.aSelect = document.getElementsByTagName("select"); + var newS = []; + for (var i=0;i<aS.length;i++) { + var add = true; + for (var j=0;j<allS.length;j++) { + if (aS[i]==allS[j]) { + add = false; + break; + } + } + if (add) { + aS[i].style.visibility = "hidden"; + newS.push(aS[i]); + } + } + modalSim.stack.push([newS,modalSim.newRepeaterElement]); + modalSim.newRepeaterElement = null; + } + else { + show = modalSim.stack.pop(); + if (show) { + if (modalSim.stack.length) { + modalSim.style.zIndex = modalSim.stack.length*10+100; + } + else { + modalSim.style.display = "none"; + } + modalSim.newRepeaterElement = show[1]; + show = show[0]; + for (var i=0;i<show.length;i++) { + show[i].style.visibility = "inherit"; + } + if (isNew) { + if (modalSim.newRepeaterElement) { + var pCrepeater = modalSim.newRepeaterElement[0]; + var row = modalSim.newRepeaterElement[1]; + var tbl = row.parentNode.parentNode; + for (var i=0;i<tbl.rows.length;i++) { + if (tbl.rows[i]==row) { + break; + } + } + var aL = []; + for (var j=0;j<i;j++) { + aL.push(pCrepeater.items[j]); + } + for (var j=i+1;j<pCrepeater.items.length;j++) { + aL.push(pCrepeater.items[j]); + } + pCrepeater.items = aL; + tbl.deleteRow(i); + // newRepeaterElement = [pCrepeater,row] + } + } + } + modalSim.newRepeaterElement = null; + } + return modalSim.stack.length; +} +Glizy.pageContent.popup = function(element,newObj) { + var z = Glizy.pageContent.modal(true) + element.popup = element.popup || Glizy.pageContent.createElements("popup",element,newObj); + setTimeout("Glizy.pageContent.refine()",50); + with (element.popup.style) { + top = (document.documentElement.scrollTop+50)+"px"; + zIndex = z*10+5+100; + display = "block"; + } + var sel = element.popup.getElementsByTagName("select"); + for (var i=0;i<sel.length;i++) { + sel[i].style.visibility = "inherit"; + } +} +Glizy.pageContent.save = function(ask,test,param,resetSaved) { + var key = Glizy.pageContent.lastKey; + Glizy.pageContent.lastKey = -1; + if (key==13) { + return; + } + if (self.tinyMCE) { + if (test) { + try { + //tinyMCE.triggerSave(); + for (var i = 0; i < tinyMCE.editors.length; i++ ) + { + tinyMCE.editors[ i ].save(); + } + + } + catch(e) { + setTimeout("Glizy.pageContent.save(false,true)",50); + return; + } + } + else { + //tinyMCE.triggerSave(); + for (var i = 0; i < tinyMCE.editors.length; i++ ) + { + tinyMCE.editors[ i ].save(); + } + } + } + // MODIFICA DANIELE + var aS = []; + var aA = []; + var aE = []; + for (var oEl in Glizy.pageContent) { + if (typeof Glizy.pageContent[oEl] == "object" && typeof Glizy.pageContent[oEl].length != "number") { + Glizy.pageContent.buildSave(oEl, Glizy.pageContent[oEl],aS,aA,aE); + } + } + + if (param) + { + aS.push(param); + } + var ok = aS.length; // MODIFICA DANIELE + if (Glizy.pageContent.saved) { + if (!test) { + ok = ok && Glizy.pageContent.saved != aS.join("&"); + } + } + else { + ok = false; + } + if (ask && ok) { + var ok = confirm(pageTexts.confirmSave); + } + if (ok) { + Glizy.hideMessage(); + if (aS.length>0) { + if (aE.length) { + //alert(aE.join("\n")); + // MODIFICA DANIELE + Glizy.showWarningMessage(GlizyLocale.REQUIREDFIELDS, aE); + } + else { + for (var i=0;i<aA.length;i++) { + aA[i][0].value = aA[i][1]; + } + Glizy.pageContent.modal(true); + var action = aS.join("&"); + action = action.split("+").join("%2B"); + jQuery.ajax( { url: Glizy.pageContent.action, + type: 'POST', + data: aS.join("&"), + dataTypeString: 'json', + success: Glizy.pageContent.formResponse + }); + } + } + else { +// ok = false; + //alert(pageTexts.noSave) + } + } +// if (!ok) { + var aS = []; + var aA = []; + var aE = []; + for (var oEl in Glizy.pageContent) { + if (typeof Glizy.pageContent[oEl] == "object" && typeof Glizy.pageContent[oEl].length != "number") { + Glizy.pageContent.buildSave(oEl,Glizy.pageContent[oEl],aS,aA,aE); + } + } + Glizy.pageContent.saved = aS.join("&") || "empty"; +// } + if ( resetSaved ) + { + Glizy.pageContent.saved = "empty"; + } +} +Glizy.pageContent.buildSave = function(oEl,objO,aS,aA,aE,isLoop) { + if (objO._obj) + { + var value = objO._obj.getValue() || ""; + if (objO.required) + { + var message = eval(objO.required+"(\""+escape(value)+"\",\""+(objO.label)+"\",\""+objO.type+"\",\""+escape(objO.requiredMessage)+"\")"); + if (message) + { + aE.push(message); + return; + } + } + + aS.push(oEl+"="+escape(value)); + aA.push([objO,value]); + return; + } + + if (objO.name) { + var objP = document.getElementById(objO.name+(objO.type=="helpedselect"?"V":"")); + var skip = false; + var obj2 = document.getElementById("s"+objO.name); + if (obj2 && obj2.style.display=='none') skip = true; + if (objO.required && !skip) { + if (objO.required==1) { + if (!objP.value) { + aE.push(objO.requiredMessage) + } + } + else { + var value = escape(objP.value) || ""; + // MODIFICA DANIELE + var message = eval(objO.required+"(\""+value+"\",\""+objO.label+"\",\""+objO.type+"\",\""+objO.requiredMessage+"\")"); + if (message) { + aE.push(message); + } + } + } + switch (objO.type) { + case "hidden": + aS.push(oEl+"="+escape(objO.value)); + break; + case "checkbox": + case "radio": + objP.value = objP.checked?1:0; + case "text": + case "longtext": + case "colorPicker": + case "select": + case "date": + case "datetime": + var value = objP.value; + if ( value == "" && objO['textIfEmpty'] && objO['textIfEmpty'] != "" ) + { + value = objO['textIfEmpty']; + } + aS.push(oEl+"="+escape(value)); + aA.push([objO,value]); + break; + case "helpedselect": + var aMS = []; + for (var k=1;k<objP.rows.length;k++) { + aMS.push(objP.rows[k].getAttributeNode("value").value); + } + aS.push(oEl+"="+aMS.join(",")); + break; + case "multipleselect": + var aMS = []; + for (var k=0;k<objP.options.length;k++) { + if (objP.options[k].selected) { + aMS.push(objP.options[k].value); + } + } + aS.push(oEl+"="+aMS.join(",")); + break; + case "image": + if (objP.value) { + aS.push(oEl+"="+objP.value); + } + break; + case "media": + if (objP.media_id) { + aS.push(oEl+"="+objP.media_id); + } + break; + case "repeater": + aS.push(oEl+"="+objO.items.length); + var aL = []; + var toDo = []; + for (var i=0;i<objO.items.length;i++) { + var ok = false; + for (var o in objO.items[i]) { + if (typeof objO.items[i][o] == "object") { + var el = document.getElementById(objO.items[i][o].name); + if (el) { + el.value = el.value || objO.items[i][o].value; + if (el.value) ok = true; + else { + var row = el.parentNode.parentNode.parentNode; + var rowIndex = 0; + while (row.previousSibling) { + rowIndex++; + row = row.previousSibling; + } + toDo.push([row.parentNode.parentNode,rowIndex]); + } + } + else { + ok = true; + } + } + } + if (ok) aL.push(objO.items[i]); + } + objO.items = aL; + var IDs = new Array(); + for (var i=0;i<objO.items.length;i++) + { + if (objO.simpleMode) + { + oEl = objO.bindTo; + if (objO.items[i][oEl].type=='image') + { + IDs.push(objO.items[i][oEl].value); + } + else + { + IDs.push(objO.items[i][oEl].media_id); + } + } + else + { + for (var o in objO.items[i]) { + if (typeof objO.items[i][o] == "object") { + var name = oEl+(i?"@"+i:"")+"-"+o; + var el = document.getElementById(objO.items[i][o].name); + if (el) { + el.value = el.value || objO.items[i][o].value; + } + + Glizy.pageContent.buildSave(name,objO.items[i][o],aS,aA,aE,true); + } + } + } + } + if (objO.simpleMode) + { + aS.push(objO.id+"="+IDs.join(',')); + } + break; + case "record": + break; + } + } + else { + switch (objO.type) { + case "hidden": + case "checkbox": + case "radio": + case "text": + case "longtext": + case "colorPicker": + case "date": + case "datetime": + aS.push(oEl+"="+escape(objO.value)); + break; + case "select": + case "multipleselect": + if (objO.options.length) { + var aMS = []; + for (var k=0;k<objO.options.length;k++) { + if (objO.options[k][2]) { + aMS.push(objO.options[k][1]); + } + } + if (objO.type=="select") { + if (aMS.length) { + aS.push(oEl+"="+aMS[0]); + } + else { + aS.push(oEl+"="+objO.options[0][1]); + } + } + else { + aS.push(oEl+"="+aMS.join(",")); + } + } + break; + case "image": + aS.push(oEl+"="+objO.img_id); + break; + case "media": + aS.push(oEl+"="+objO.media_id); + break; + } + } +} +Glizy.pageContent.formResponse = function(response, response2) { + Glizy.pageContent.modal(false); + // console.log(response); + // response = jQuery.parseJSON( response ); + // console.log(response); + switch (response['status']) + { + case 'success': + switch (response['action']) + { + case 'redirect': + location.href = response['actionValue']; + return; + break; + case 'setValues': + for (a in response['actionValue']) + { + Glizy.pageContent[a]['value'] = response['actionValue'][a]; + } + var aS = []; + var aA = []; + var aE = []; + for (var oEl in Glizy.pageContent) { + if (typeof Glizy.pageContent[oEl] == "object" && typeof Glizy.pageContent[oEl].length != "number") { + Glizy.pageContent.buildSave(oEl,Glizy.pageContent[oEl],aS,aA,aE); + } + } + Glizy.pageContent.saved = aS.join("&") || "empty"; + break; + case 'call': + break; + } + //Glizy.pageContent.modal(false); + Glizy.showSuccessMessage(GlizyLocale.SUCCESSMSG) + break; + case 'error': + alert(response['message']); + break; + } +} +Glizy.pageContent.applyOpt = function(target,obj,e) { + target = target.split(","); + var index = (typeof e == "number"?e:(e.target||e.srcElement).selectedIndex); + var obj = "Glizy.pageContent."+obj; + var obj0 = eval(obj); + obj = obj.substring(0,obj.lastIndexOf(".")); + var opts = obj0.options[index][3]; + if (!opts.length) return; + var action = obj0.action || "value"; + for (var i=0;i<target.length;i++) { + var obj1 = eval(obj+"."+target[i]); + switch (action) { + case "value": + obj2 = document.getElementById(obj1.name); + obj2.value = opts[i]; + if (obj1.type=="colorPicker") { + obj2.parentNode.parentNode.cells[0].style.backgroundColor = opts[i]; + obj1.value = opts[i]; + } + break; + case "display": + obj2 = document.getElementById("s"+obj1.name); + if (obj2) {obj2.style.display = opts[i]}; + break; + } + } +} +Glizy.pageContent.aId = []; +Glizy.pageContent.insertTag = function(what,where) { + var tag = document.getElementById(what); + var target = Glizy.pageContent.aId[where]+"_ifr"; + if ( tinyMCE.editors[ Glizy.pageContent.aId[where] ] ) + { + tinyMCE.activeEditor.execCommand('mceFocus', false, target); + tinyMCE.activeEditor.execCommand('mceInsertContent', true, tag.value); + } + else + { + var targetField = document.getElementById(Glizy.pageContent.aId[where]); + if (targetField) targetField.value = tag.value; + } +} +Glizy.pageContent.refine = function() { + for (var i in this) { + if (this[i].name && this[i].type=="text") { + var el = document.getElementById(this[i].name); + el.value = el.value.replace(/\|\|/gi,'"'); + } + } + + with (Glizy.pageContent) { + while (true) { + var obj = aSource.pop(); + if (obj) { + var obj1 = document.getElementById(obj.name); + if (obj1) obj1.source = obj; + } + else break; + } + while (true) { + var editable = aHtmlEditables.pop(); + if (editable && self.tinyMCE) { + document.getElementById(editable).isRichText = true; + var element_contenuto = document.getElementById(editable); + if (element_contenuto) { + var nA = document.getElementsByTagName("A").length; + var options = Glizy.tinyMCE_options; + options.mode = "exact"; + options.elements = editable; + tinyMCE.init( options ); + for (var k in Glizy.pageContent.aId) { + if (Glizy.pageContent.aId[k]==editable) { + Glizy.pageContent.aId[k] = Glizy.pageContent.nE; + Glizy.pageContent.nE++ + } + } + /*var aElements = document.getElementsByTagName("A"); + for (var i=aElements.length-1;i>=nA;i--) { + if (aElements[i].href && aElements[i].href.indexOf("javascript:")==0) { + var href = aElements[i].href.substring(11); + var newHTML = "<span onmouseup=\""+href+"\">"+aElements[i].innerHTML+"</span>"; + newHTML = newHTML.replace(/%20/gi,""); + aElements[i].outerHTML = newHTML; + } + }*/ + } + } + else break; + } + while (true) { + var id = aCalendarAttach.pop(); + if (id) { + Calendar.setup({ + inputField : id[ 0 ], // id of the input field + ifFormat : id[ 1 ] == "date" ? GlizyLocale.DATE_FORMAT : GlizyLocale.DATETIME_FORMAT, // format of the input field + showsTime : id[ 1 ] != "date", // will display a time selector + button : id[ 0 ]+"bt", // trigger for the calendar (button ID) + singleClick : true, // double-click mode + step : 1, // show all years in drop-down boxes (instead of every other year as default) + firstDay : 1, + weekNumbers : false, + date : "", + showOthers : true + }); + } + else break; + } + while (true) { + var obj = aApplyOpts.pop(); + if (obj) { + var index = 0; + var obj0 = eval("Glizy.pageContent."+obj); + if (obj0) { + for (var i=0;i<obj0.options.length;i++) { + if (obj0.options[i][2]) { + index = i; + break + } + } + applyOpt(obj0.target,obj,index); + } + } + else break; + } + + for( var a in Glizy.pageContent_widgets._registredWidgets ) + { + Glizy.pageContent_widgets.callMethod( a, 'refine' ); + } + } +} +Glizy.pageContent.getThumb = function() { +} + + +Glizy.pageContent.helpedChange = function( sourceId, targetId ) { + var source = Glizy.pageContent.$("#"+sourceId); + var target = Glizy.pageContent.$("#"+targetId); + if ( source.value ) + { + target.disabled = ""; + + } + else + { + target.disabled = "disabled"; + target.value = ""; + } +} + +Glizy.pageContent.getResult = function(id,iconWidth) { + var obj = Glizy.pageContent[id]; + var url = obj.src; + var ok = false; + var source = Glizy.pageContent.$("#"+obj.name+"P0"); + var target = Glizy.pageContent.$("#"+obj.name+"S0"); + if ( source.value && target.value ) + { + target.disabled = ""; + url += "&"+source.value+"="+target.value; + ok = true; + } + + if (ok ) { + var target = Glizy.pageContent.$("#"+obj.name+"R"); + target.iconWidth = iconWidth; + target.refresh = Glizy.pageContent.setResult; + jQuery.ajax( { url: url, + type: 'POST', + dataTypeString: 'text', + success: function( responseText ) + { + target.refresh( responseText ); + } + }); + } +} +Glizy.pageContent.setResult = function(text) { + eval("var response = "+text+";"); + var aHTML = []; + var rows = response.rows; + if (rows.length) { + aHTML.push('<table id="elID'+Glizy.pageContent.nF+'" style="table-layout:fixed;" cellSpacing="0">'); + for (var i=0;i<rows.length;i++) { + aHTML.push('<tr class="'+(i%2?"odd":"even")+'" value="'+rows[i].v+'">'); + aHTML.push('<td width="'+this.iconWidth+'">'); + if (rows[i].ico) { + aHTML.push('<img style="width:'+this.iconWidth+'px;" src="'+rows[i].ico+'"/>'); + } + aHTML.push('</td><td><div style="width:100%">'); + aHTML.push('<img style="float:right;cursor:pointer" onclick="Glizy.pageContent.insOption(event,\''+this.id+'\')" alt="'+pageTexts.include+'" src="'+Glizy.pageContent.iconPath+'icon_add.gif" width="16" height="16" border="0"/>'); + if (rows[i].url) { + aHTML.push('<img style="float:right;cursor:pointer" onclick="Glizy.pageContent.pagePreview(\''+rows[i].url+'\')" alt="'+pageTexts.preview+'" src="'+Glizy.pageContent.iconPath+'icon_preview.gif" width="16" height="16" border="0"/>'); + } + aHTML.push('<span>'+rows[i].t+'</span>'); + aHTML.push('</div></td></tr>'); + } + aHTML.push('</table>'); + setTimeout('Glizy.pageContent.$("#elID'+Glizy.pageContent.nF+'").style.width=Glizy.pageContent.$("#'+this.id+'").clientWidth+"px";Glizy.pageContent.$("#'+this.id+'").style.visibility=""',50); + Glizy.pageContent.nF++; + } + else { + aHTML.push(pageTexts.noResult); + } + this.style.visibility = "hidden"; + this.innerHTML = aHTML.join(""); +} +Glizy.pageContent.insOption = function(e,id) { + var obj = (e.target||event.srcElement); + obj.src = Glizy.pageContent.iconPath+"icon_delete.gif"; + obj.alt = pageTexts.del; + obj.onclick = Glizy.pageContent.delOption; + while (obj.tagName!="TR") { + obj = obj.parentNode; + } + var o = Glizy.pageContent.$("#"+id.replace("R","V")); + for (var i=0;i<o.childNodes.length;i++) { + if (o.childNodes[i].tagName=="TBODY") { + var tb = o.childNodes[i]; + break + } + } + tb.appendChild(obj); + tb.rows[0].style.display = "none"; + o.value = Glizy.pageContent.altRows(o); + Glizy.pageContent.altRows(Glizy.pageContent.$("#"+id).firstChild); + // _.resize() +} +Glizy.pageContent.delOption = function(e) { + var obj = (e?(e.target||event.srcElement):event.srcElement); + while (obj.tagName!="TR") { + obj = obj.parentNode; + } + var o = obj; + while (o.tagName!="TBODY") { + o = o.parentNode; + } + if (o.rows.length==2) { + o.rows[0].style.display = ""; + } + o.removeChild(obj); + o.parentNode.value = Glizy.pageContent.altRows(o.parentNode); + // _.resize(); +} +Glizy.pageContent.altRows = function(obj) { + var aReturn = []; + var k = 0; + for (var i=0;i<obj.rows.length;i++) { + if (obj.rows[i].className=="_ph") { + k = 1; + } + else { + obj.rows[i].className = (i+k)%2?"odd":"even"; + aReturn.push(obj.rows[i].value); + } + } + return aReturn.join(","); +} +Glizy.pageContent.suggestFlt = function(obj) { + var ids = obj.id.split("S"); + ids[1] = parseFloat(ids[1]); + var aFlt,sB; + for (var i=0;i<3;i++) { + aFlt = []; + for (var j=0;j<3;j++) { + if (j!=i) { + sB = Glizy.pageContent.$("#"+ids[0]+"S"+j); + if (sB.value && sB.key) { + aFlt.push(sB.key+"="+sB.value+""); + } + } + } + sB = Glizy.pageContent.$("#"+ids[0]+"S"+i); + sB._extra = sB._extra || sB.extra; + sB.extra = aFlt.join("&"); + sB.extra += (sB.extra?"&":"")+sB._extra+"="+obj.key; + } +} + +Glizy.pageContent.pagePreview = function(id, draft, sessionprefix) +{ + Glizy.closeWindows(); + Glizy.openWindow("../index.php?pageId="+id+"&draft="+draft+"&sespre="+sessionprefix,"preview","width=800,height=600,innerWidth=800,innerHeight=600,toolbar=yes,location=yes,menubar=yes,scrollbars=yes,resizable=yes"); +} + +Glizy.pageContent.addEvent = function(el, e,fn) { + if(window.addEventListener){ + return el.addEventListener(e,fn,false); + } + else if(window.attachEvent){ + return el.attachEvent("on"+e,fn); + } +} +Glizy.pageContent.removeEvent = function(el, e,fn) { + if(window.addEventListener){ + return el.removeEventListener(e,fn,false); + } + else if(window.attachEvent){ + return el.detachEvent("on"+e,fn); + } +} +Glizy.pageContent.changeVisibility = function( elements, state ) +{ + jQuery( elements ).each( function( index, value ){ + if ( Glizy.pageContent.aId[ value ] ) + { + jQuery( "#s"+Glizy.pageContent.aId[ value ] ).css( "display", state ? "inline" : "none" ); + } + }); +} +Glizy.pageContent.cancel = function() +{ + location.href = Glizy.pageContent.editRecord_resetUrl.value; +} + +Glizy.pageContent.openModalPicker = function( url, title ) +{ + if ( jQuery("#modalDiv").data( "isDialog" ) != "true" ) + { + jQuery("#modalDiv").dialog({ + modal: true, + autoOpen: false, + draggable: true, + resizeable: true + }); + jQuery("#modalDiv").data( "isDialog", "true" ); + } + + var w = Math.min( jQuery( window ).width() - 50, 900 ); + var h = jQuery( window ).height() - 50; + $("#modalDiv").dialog( "option", { height: h, width: w, title: title } ); + $("#modalDiv").dialog( "open" ); + if ( $("#modalIFrame").attr( "src") != url ) + { + $("#modalIFrame").attr( "src", url ); + } +} + +Glizy.pageContent.closeModalPicker = function( url, title ) +{ + $("#modalDiv").dialog( "close" ); +} + +for (var oEl in Glizy.pageContent) { + if (Glizy.pageContent[oEl].type=="helpedselect") { + } + if (typeof Glizy.pageContent[oEl] == "object" && typeof Glizy.pageContent[oEl].length != "number") { + Glizy.pageContent.buildHTML(oEl, Glizy.pageContent[oEl]) + } +} + +Glizy.pageContent.aHTML.push( '<div id="modalDiv" style="display: none; margin: 0; padding: 0; overflow: hidden;"><iframe src="" id="modalIFrame" width="100%" height="100%" marginWidth="0" marginHeight="0" frameBorder="0" scrolling="auto" title="Seleziona Media"></iframe></div>' ); + + +document.write(Glizy.pageContent.aHTML.join("")); +Glizy.pageContent.refine(); + +if ( Glizy.pageContent.enableFirstSave ) +{ + setTimeout("Glizy.pageContent.save(false, true, null, true)",50); +} +else +{ + setTimeout("Glizy.pageContent.save(false, true )",50); +} + +onbeforeunload = function() { + Glizy.pageContent.save(true); +} +document.onkeydown = function() { + if (self.event) { + Glizy.pageContent.lastKey = event.keyCode; + } +} \ No newline at end of file diff --git a/src/core/static/js/Glizy_pageFilters.js b/src/core/static/js/Glizy_pageFilters.js new file mode 100644 index 0000000..f77e5a3 --- /dev/null +++ b/src/core/static/js/Glizy_pageFilters.js @@ -0,0 +1,170 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +var $F = function(el) +{ + return Glizy.$(el).val(); +} + +Glizy.pageFilters.draw = function() +{ + Glizy.pageFilters.rows = 1; + Glizy.pageFilters.aCalendarAttach = []; + aHTML = []; + + aHTML.push('<input type="hidden" id="'+Glizy.pageFilters.id+'_'+'count" name="'+Glizy.pageFilters.id+'_'+'count" value="'+name+'" />'); + aHTML.push('<table>'); + aHTML.push('<tr><td>'); + aHTML.push("<img onclick=\"Glizy.pageFilters.addRow(this)\" title=\""+pageTexts.addBefore+"\" src=\""+Glizy.pageFilters.iconPath+"icon_add.gif\" width=\"16\" height=\"16\" border=\"0\" style=\"cursor: pointer;\"/>"); + // aHTML.push('</td>'); + // aHTML.push('<td>'); + Glizy.pageFilters.drawItems(aHTML, Glizy.pageFilters.id+'_0', ''); + // aHTML.push('</td><td></td></tr>'); + aHTML.push('<div></div></td></tr>'); + + // disegna i campi già impostati + for (var i=0; i<Glizy.pageFilters.values.values.length; i++) + { + aHTML.push('<tr><td>'); + aHTML.push("<img onclick=\"Glizy.pageFilters.removeRow(this)\" title=\""+pageTexts.del+"\" src=\""+Glizy.pageFilters.iconPath+"icon_delete.gif\" width=\"16\" height=\"16\" border=\"0\" style=\"cursor: pointer;\"/>"); + // aHTML.push('</td>'); + // aHTML.push('<td>'); + Glizy.pageFilters.drawItems(aHTML, Glizy.pageFilters.id+'_'+(i+1), 'items.'+Glizy.pageFilters.values.values[i][0]); + aHTML.push('<div>'); + Glizy.pageFilters.drawFilterElement(aHTML, Glizy.pageFilters.id+'_'+(i+1), Glizy.pageFilters.values.values[i][0], Glizy.pageFilters.values.values[i][1]); + aHTML.push('</div></td></tr>'); + Glizy.pageFilters.rows++; + } + aHTML.push('</table>'); + document.write(aHTML.join('')); + Glizy.$(Glizy.pageFilters.id+'_'+'count').value = Glizy.pageFilters.rows-1; +} + + +Glizy.pageFilters.drawItems = function(aHTML, id, toSelect) +{ + aHTML.push('<select id="'+id+'" name="'+id+'" onchange="Glizy.pageFilters.changeType(this, event);">'); + aHTML.push('<option value="">-</option>'); + for (var i in Glizy.pageFilters.items) + { + el = Glizy.pageFilters.items[i]; + if (!el.id) continue; + aHTML.push('<option value="'+el.id+'"'+(el.id==toSelect ? ' selected="selected"':'')+'>'+el.label+'</option>'); + } + aHTML.push('</select>'); +} + +Glizy.pageFilters.drawFilterElement = function(aHTML, id, name, value) +{ + name = name.indexOf('.')>1 ? name.split('.')[1] : name; + fObj = Glizy.pageFilters.items[name]; + if (fObj) + { + if(!value) value = ''; + newId = id.replace(Glizy.pageFilters.id+'_', Glizy.pageFilters.id+'_value_'); + switch (fObj.type) + { + case 'select': + case 'editableSelect': + aHTML.push('<select id="'+newId+'" name="'+newId+'">'); + for (var i=0; i<fObj.options.length;i++) + { + aHTML.push('<option value="'+fObj.options[i][1]+'"'+(fObj.options[i][1]==value ? ' selected="selected"':'')+'>'+fObj.options[i][0]+'</option>'); + } + aHTML.push('</select>'); + break; + case 'checkbox': + aHTML.push('<input type="hidden" id="'+newId+'" name="'+newId+'" value="'+(value=="1" ? '1' : '0' )+'" />') + aHTML.push('<input onchange="Glizy.pageFilters.setCheckValue(this, \''+newId+'\')" value="1" type="checkbox"'+(value=="1"?' checked':'')+'/>') + break; + case 'date': + aHTML.push('<input type="text" id="'+newId+'" name="'+newId+'" value="'+value+'" autocomplete="off" size="10" />'); + aHTML.push('<img src="'+Glizy.pageFilters.iconPath+'calendar.gif" style="cursor: pointer; border: 1px solid red;" title="Date selector" onmouseover="this.style.background=\'red\';" onmouseout="this.style.background=\'\'" id="'+newId+'bt"/>'); + Glizy.pageFilters.aCalendarAttach.push(newId); + break; + default: + aHTML.push('<input type="text" id="'+newId+'" name="'+newId+'" value="'+value+'" />'); + } + + newId = id.replace(Glizy.pageFilters.id+'_', Glizy.pageFilters.id+'_type_'); + aHTML.push('<input type="hidden" id="'+newId+'" name="'+newId+'" value="'+name+'" />'); + } +} + +Glizy.pageFilters.addRow = function(el) +{ + tEl = el.parentNode.parentNode.parentNode; + row = tEl.insertRow(-1); + Glizy.$(Glizy.pageFilters.id+'_'+'count').value = Glizy.pageFilters.rows; + + cell = row.insertCell(-1); + aHTML = []; + aHTML.push( "<img onclick=\"Glizy.pageFilters.removeRow(this)\" title=\""+pageTexts.del+"\" src=\""+Glizy.pageFilters.iconPath+"icon_delete.gif\" width=\"16\" height=\"16\" border=\"0\" style=\"cursor: pointer;\"/>" ); + Glizy.pageFilters.drawItems(aHTML, Glizy.pageFilters.id+'_'+Glizy.pageFilters.rows, ''); + cell.innerHTML = aHTML.join('');; + cell = row.insertCell(-1); + + Glizy.pageFilters.rows++; + Glizy.pageFilters.initCalendar(); +} + +Glizy.pageFilters.removeRow = function(el, rowNum) +{ + rowEl = el.parentNode.parentNode; + rowEl.toDelete = true; + tEl = el.parentNode.parentNode.parentNode; + + for (var i=0; i<tEl.rows.length;i++) + { + if (tEl.rows[i].toDelete==true) + { + tEl.deleteRow(i); + break; + } + } +} + +Glizy.pageFilters.changeType = function(el, event) +{ + aHTML = []; + Glizy.pageFilters.drawFilterElement(aHTML, el.id, $F(el)); + var cell = el.nextSibling; + cell.innerHTML = aHTML.join(''); + Glizy.pageFilters.initCalendar(); +} + +Glizy.pageFilters.setCheckValue = function(el, targetId) +{ + Glizy.$(targetId).value = el.checked ? '1' : '0'; +} + +Glizy.pageFilters.initCalendar = function() +{ + while (true) { + var id = Glizy.pageFilters.aCalendarAttach.pop(); + el = Glizy.$(id); + if (id && el) { + Calendar.setup({ + inputField : id, // id of the input field + ifFormat : GlizyLocale.DATE_FORMAT, // format of the input field + showsTime : false, // will display a time selector + button : id+"bt", // trigger for the calendar (button ID) + singleClick : true, // double-click mode + step : 1, // show all years in drop-down boxes (instead of every other year as default) + firstDay : 1, + weekNumbers : false, + date : "", + showOthers : true + }); + } + else break; + } +} + +Glizy.pageFilters.draw(); +Glizy.pageFilters.initCalendar(); \ No newline at end of file diff --git a/src/core/static/js/Glizy_tiny_mce.js b/src/core/static/js/Glizy_tiny_mce.js new file mode 100644 index 0000000..e15a326 --- /dev/null +++ b/src/core/static/js/Glizy_tiny_mce.js @@ -0,0 +1,283 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +if ( Glizy.tinyMCE_btn3 != "" && Glizy.tinyMCE_pluginsNames != "" ) +{ + Glizy.tinyMCE_btn3 = Glizy.tinyMCE_btn3 != "" ? Glizy.tinyMCE_btn3 + "," + Glizy.tinyMCE_pluginsNames : Glizy.tinyMCE_pluginsNames; +} + +Glizy.tinyMCE_options = { + theme : "advanced", + mode : "exact", + elements : "", + language: GlizyLocale.LANGUAGE, + dialog_type: "modal", + paste_remove_spans: true, + paste_remove_styles: true, + paste_strip_class_attributes: "all", + remove_linebreaks: true, + remove_script_host: false, + tab_focus : ':prev,:next', + content_css : Glizy.tinyCSS, + plugins : Glizy.tinyMCE_plugins, + theme_advanced_buttons1 : Glizy.tinyMCE_btn1, + theme_advanced_buttons2 : Glizy.tinyMCE_btn2, + theme_advanced_buttons3 : Glizy.tinyMCE_btn3, + theme_advanced_resize_horizontal : false, + theme_advanced_resizing : true, + theme_advanced_toolbar_location : "top", + theme_advanced_toolbar_align : "left", + theme_advanced_path_location : "bottom", + + inline_styles : true, + verify_html : true, + extended_valid_elements : "a[name|href|title|style|class|rel|rev|tabindex|accesskey]", + valid_elements : "" ++"a[accesskey|charset|class|coords|dir<ltr?rtl|href|hreflang|id|lang|name" + +"|onblur|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|rel|rev" + +"|shape<circle?default?poly?rect|style|tabindex|title|target|type]," ++"abbr[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"acronym[class|dir<ltr?rtl|id|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"address[class|align|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"area[accesskey|alt|class|coords|dir<ltr?rtl|href|id|lang|nohref<nohref" + +"|onblur|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup" + +"|shape<circle?default?poly?rect|style|tabindex|title|target]," ++"bdo[class|dir<ltr?rtl|id|lang|style|title]," ++"big[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"blockquote[cite|class|dir<ltr?rtl|id|lang|onclick|ondblclick" + +"|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout" + +"|onmouseover|onmouseup|style|title]," ++"br[class|clear<all?left?none?right|id|style|title]," ++"button[accesskey|class|dir<ltr?rtl|disabled<disabled|id|lang|name|onblur" + +"|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|style|tabindex|title|type" + +"|value]," ++"caption[align<bottom?left?right?top|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"cite[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"col[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl|id" + +"|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|span|style|title" + +"|valign<baseline?bottom?middle?top|width]," ++"colgroup[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl" + +"|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|span|style|title" + +"|valign<baseline?bottom?middle?top|width]," ++"dd[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title]," ++"del[cite|class|datetime|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"dfn[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"dir[class|compact<compact|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"div[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"dl[class|compact<compact|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"dt[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title]," ++"em/i[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"embed[width|height|name|flashvars|src|bgcolor|align|play|loop|quality|allowscriptaccess|allowfullscreen|type|pluginspage]," ++"fieldset[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"font[class|color|dir<ltr?rtl|face|id|lang|size|style|title]," ++"form[accept|accept-charset|action|class|dir<ltr?rtl|enctype|id|lang" + +"|method<get?post|name|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onreset|onsubmit" + +"|style|title|target]," ++"frame[class|frameborder|id|longdesc|marginheight|marginwidth|name" + +"|noresize<noresize|scrolling<auto?no?yes|src|style|title]," ++"frameset[class|cols|id|onload|onunload|rows|style|title]," ++"h1[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"h2[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"h3[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"h4[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"h5[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"h6[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"head[dir<ltr?rtl|lang|profile]," ++"hr[align<center?left?right|class|dir<ltr?rtl|id|lang|noshade<noshade|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|size|style|title|width]," ++"html[dir<ltr?rtl|lang|version]," ++"iframe[align<bottom?left?middle?right?top|class|frameborder|height|id" + +"|longdesc|marginheight|marginwidth|name|scrolling<auto?no?yes|src|style" + +"|title|width]," ++"img[align<bottom?left?middle?right?top|alt|border|class|dir<ltr?rtl|height" + +"|hspace|id|ismap<ismap|lang|longdesc|name|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|src|style|title|usemap|vspace|width]," ++"input[accept|accesskey|align<bottom?left?middle?right?top|alt" + +"|checked<checked|class|dir<ltr?rtl|disabled<disabled|id|ismap<ismap|lang" + +"|maxlength|name|onblur|onclick|ondblclick|onfocus|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onselect" + +"|readonly<readonly|size|src|style|tabindex|title" + +"|type<button?checkbox?file?hidden?image?password?radio?reset?submit?text" + +"|usemap|value]," ++"ins[cite|class|datetime|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"isindex[class|dir<ltr?rtl|id|lang|prompt|style|title]," ++"kbd[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"label[accesskey|class|dir<ltr?rtl|for|id|lang|onblur|onclick|ondblclick" + +"|onfocus|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout" + +"|onmouseover|onmouseup|style|title]," ++"legend[align<bottom?left?right?top|accesskey|class|dir<ltr?rtl|id|lang" + +"|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"li[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title|type" + +"|value]," ++"link[charset|class|dir<ltr?rtl|href|hreflang|id|lang|media|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|rel|rev|style|title|target|type]," ++"map[class|dir<ltr?rtl|id|lang|name|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"menu[class|compact<compact|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"meta[content|dir<ltr?rtl|http-equiv|lang|name|scheme]," ++"noframes[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"noscript[class|dir<ltr?rtl|id|lang|style|title]," ++"object[align<bottom?left?middle?right?top|archive|border|class|classid" + +"|codebase|codetype|data|declare|dir<ltr?rtl|height|hspace|id|lang|name" + +"|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|standby|style|tabindex|title|type|usemap" + +"|vspace|width]," ++"ol[class|compact<compact|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|start|style|title|type]," ++"optgroup[class|dir<ltr?rtl|disabled<disabled|id|label|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"option[class|dir<ltr?rtl|disabled<disabled|id|label|lang|onclick|ondblclick" + +"|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout" + +"|onmouseover|onmouseup|selected<selected|style|title|value]," ++"p[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"param[id|name|type|value|valuetype<DATA?OBJECT?REF]," ++"pre/listing/plaintext/xmp[align|class|dir<ltr?rtl|id|lang|onclick|ondblclick" + +"|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout" + +"|onmouseover|onmouseup|style|title|width]," ++"q[cite|class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"s[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title]," ++"samp[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"script[charset|defer|language|src|type]," ++"select[class|dir<ltr?rtl|disabled<disabled|id|lang|multiple<multiple|name" + +"|onblur|onchange|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|size|style" + +"|tabindex|title]," ++"small[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"span[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"strike[class|class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"strong/b[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"style[dir<ltr?rtl|lang|media|title|type]," ++"sub[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"sup[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"table[align<center?left?right|bgcolor|border|cellpadding|cellspacing|class" + +"|dir<ltr?rtl|frame|height|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|rules" + +"|style|summary|title|width]," ++"tbody[align<center?char?justify?left?right|char|class|charoff|dir<ltr?rtl|id" + +"|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|style|title" + +"|valign<baseline?bottom?middle?top]," ++"td[abbr|align<center?char?justify?left?right|axis|bgcolor|char|charoff|class" + +"|colspan|dir<ltr?rtl|headers|height|id|lang|nowrap<nowrap|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|rowspan|scope<col?colgroup?row?rowgroup" + +"|style|title|valign<baseline?bottom?middle?top|width]," ++"textarea[accesskey|class|cols|dir<ltr?rtl|disabled<disabled|id|lang|name" + +"|onblur|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onselect" + +"|readonly<readonly|rows|style|tabindex|title]," ++"tfoot[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl|id" + +"|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|style|title" + +"|valign<baseline?bottom?middle?top]," ++"th[abbr|align<center?char?justify?left?right|axis|bgcolor|char|charoff|class" + +"|colspan|dir<ltr?rtl|headers|height|id|lang|nowrap<nowrap|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|rowspan|scope<col?colgroup?row?rowgroup" + +"|style|title|valign<baseline?bottom?middle?top|width]," ++"thead[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl|id" + +"|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|style|title" + +"|valign<baseline?bottom?middle?top]," ++"title[dir<ltr?rtl|lang]," ++"tr[abbr|align<center?char?justify?left?right|bgcolor|char|charoff|class" + +"|rowspan|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title|valign<baseline?bottom?middle?top]," ++"tt[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title]," ++"u[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title]," ++"ul[class|compact<compact|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title|type]," ++"var[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]" + }; \ No newline at end of file diff --git a/src/core/static/js/dejavu/LICENSE b/src/core/static/js/dejavu/LICENSE new file mode 100755 index 0000000..92b561c --- /dev/null +++ b/src/core/static/js/dejavu/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 IndigoUnited + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/src/core/static/js/dejavu/README.md b/src/core/static/js/dejavu/README.md new file mode 100755 index 0000000..b2aca00 --- /dev/null +++ b/src/core/static/js/dejavu/README.md @@ -0,0 +1,669 @@ +dejavu +------ + +[![Build Status](https://secure.travis-ci.org/IndigoUnited/dejavu.png)](http://travis-ci.org/IndigoUnited/dejavu) + +Have you ever had the feeling that you're seeing something you've already seen +before? That's the feeling you get when using `dejavu`. + +If you are a developer coming from a language like PHP, Java, ActionScript 3.0, +and others, it's likely that you are already familiar with Object Oriented +Programming. However, JavaScript uses prototypal inheritance which, although +powerful and flexible, can be difficult to unde +rstand, and specially to maintain +in large projects. + +`dejavu` is a library that delivers classical inheritance on top of JavaScript +prototypal inheritance, making it a breeze to move into JavaScript. + + + +## Why another? + +There are some libraries out there able to shim classical inheritance, +however none offers all the functionality that many programmers require. + +Also, even though being one of the most feature rich OOP libraries out there, it has an outstanding performance, rivaling with vanilla in production. + + + +## Features + +* Classes (concrete, abstract and final) +* Interfaces +* Mixins (so you can get some sort of multiple inheritance) +* Private and protected members +* Static members +* Constants +* Context binding for functions +* Method signature checks +* Possible to extend or borrow from vanilla classes +* Custom instanceOf with support for Interfaces +* Two builds, `regular` and `AMD` based + * `AMD` optimized for speeding up developer workflow, allowing testing + without the need to re-compile everything into a single file + * `regular` if you are not using `AMD` in your projects +* Two modes for each build, `strict` and `loose` + * `strict` best in development, enforcing a lot of checks, making sure you + don't make many typical mistakes + * `loose` best for production, without checks, improving performance + +Users are encouraged to declare +['use strict'](https://developer.mozilla.org/en/JavaScript/Strict_mode) while +using the `dejavu` in strict mode, otherwise some code might fail silently. +This can happen because `dejavu` uses `Object.freeze` and `Object.seal` to lock +classes and instances, guaranteeing that no one changes the behaviour of your +classes by replacing methods, etc, and possibly breaking your code, making it +really hard to pin point what's wrong. Although this is the default behaviour, it can be changed. + +You will read more on it later in this document. + +**Do not confuse 'use strict' with the dejavu strict mode.** + + + +## Getting started + +The quickest way to start using `dejavu` in your project, is by simply including +`dist/regular/strict/dejavu.js` (note that this is in __strict__ mode). + +If you're developing a __client-side__ app, simply put the file in some folder, +and include it in the HTML: + +```html +<!DOCTYPE html> +<html> + <head> + <meta http-equiv="Content-Type" + content="text/html; charset=UTF-8"> + <script type="text/javascript" src="dejavu.js"></script> + </head> + <body> + <script type="text/javascript"> + 'use strict'; + + // declare the "Person" class + var Person = dejavu.Class.declare({ + _name: null, + + initialize: function(name) { + this.setName(name); + }, + + setName: function(name) { + this._name = name; + + return this; + }, + + getName: function() { + return this._name; + } + }); + + // create a new instance of person + var indigo = new Person('Marco'); + console.log('A new indigo was born,', indigo.getName()); + </script> + </body> +</html> +``` + +This will make a `dejavu` global available for you. +If you're developing in __Node.js__, install it with `npm install dejavu` and use it like so: + +```js +var dejavu = require('dejavu'); + +// declare the "Person" class +var Person = dejavu.Class.declare({ + _name: null, + + initialize: function(name) { + this.setName(name); + }, + + setName: function(name) { + this._name = name; + + return this; + }, + + getName: function() { + return this._name; + } +}); + +// create a new instance of person +var indigo = new Person("Marco"); +console.log("A new indigo was born,", indigo.getName()); +``` + +The installation will create a `.dejavurc` in your package, where you can enable/disable the strict mode as well as change other dejavu options. +By default the strict mode is used. Still, you want to leverage your package with the loose mode. +Because dejavu reads`.dejavurc` from the process.cwd(), packages that require your package will be running the loose mode unless they also define a `.dejavurc` (which will only happen if they also depend on dejavu directly). + + + +## Performance + +Since all those nice features and common rules of classic OOP degrade +performance, `dejavu` has two separates modes, for different stages in the +development. + +The `strict` mode is suitable for __development__, and will do all sorts of +checks, throwing an error when you try to do something considered illegal. + +**Note that if your project works in strict mode, it will work in loose mode.** + +As for the `loose` mode, there is no overhead associated with checks, thus +making it suitable for __production__, since it will be more efficient and +have a __lower memory footprint and filesize__. + +Finally, in order to achieve that extra edge, that puts `dejavu` next to vanilla +JS in terms of performance, you should run the optimizer that is bundled with +the library. Note that this step is completely optional, and `dejavu` will still +perform faster than most libraries, even if you don't run the [optimizer](https://github.com/IndigoUnited/dejavu##optimizer). +The optimizer will analyse your code and make some improvements, +boosting it a bit further. + +You can check the benchmarks in [jsperf](http://jsperf.com/oop-benchmark/107) +comparing `dejavu` with other OOP libraries. Note that the loose mode +is used in this test, simulating a production environment, and both the normal +and optimized versions are tested. It is also important to mention that many libraries like +[JSFace](https://github.com/tnhu/jsface) does not chain prototypes. This gives +JSFace an extra edge in performance in some browsers, like Firefox, but renders +the `instanceof` operator useless. + + + +## Syntax + +### Overview + +Here's an overview of what most developers look for in an OOP library. You can find complete examples further down. + +```js +var Person = Class.declare({ + // although not mandatory, it's really useful to identify + // the class name, which simplifies debugging + $name: 'Person', + + // this is a protected property, which is identified by + // the single underscore. two underscores denotes a + // private property, and no underscore stands for public + _name: null, + __pinCode: null, + + // class constructor + initialize: function (name, pinCode) { + this._name = name; + this.__pinCode = pinCode; + + // note that we're binding to the current instance with `$bind`. + // this will be explained with great detail later on + setTimeout(this._logName.$bind(this), 1000); + }, + + // public method (follows the same visibility logic, in this case with no underscore) + getName: function () { + return this._name; + } + + _logName: function () { + console.log(this._name); + } +}); +``` + +### Complete example + +For those looking for something more, here's a more complete usage of `dejavu`. + +This example illustrates the usage of: + +- `$name` meta attribute +- `this.$self` vs `this.$static` +- `$super()` for accessing overridden methods +- `instanceOf` +- member visibility +- statics, abstracts, abstract statics, finals, final statics and constants +- `$extends` vs `$borrows` + +In this case, and keep in mind that this is just for illustration purposes, we'll create three interfaces, that are implemented by an abstract class, that is then extended by a concrete class. + + +```js +var dejavu = require('dejavu'); + +// ------------ AN INTERFACE ------------ +// this interface is useless, is only here to illustrate +// that interfaces can extend other interfaces +var UselessInterface = dejavu.Interface.declare({ + $name: 'UselessInterface' +}); + +var PersonInterface = dejavu.Interface.declare({ + $name: 'PersonInterface', + // if you need to extend multiple interfaces, + // just provide an array + $extends: UselessInterface, + + // interface methods can specify argument list, and any class + // that implements that interface will be automatically checked, + // to make sure it obeys the method signature. If you want to + // specify an optional argument, you should prepend it by a dollar + // sign, like so: someMethod(arg1, arg2, $thisArgIsOptional) + getName: function () {}, + setName: function (name) {} +}); + +// ------------ ANOTHER INTERFACE ------------ +var EngineerInterface = dejavu.Interface.declare({ + $name: 'EngineerInterface', + + think: function(subject) {} +}); + +// ------------ AN ABSTRACT CLASS ------------ +var AbstractIndigo = dejavu.AbstractClass.declare({ + $name: 'AbstractIndigo', + // implements multiple interfaces + $implements: [PersonInterface, EngineerInterface], + + $constants: { + INDIGO_WEBSITE: 'http://www.indigounited.com/', + INDIGO_EMAIL: 'hello@indigounited.com' + }, + + $statics: { + logIndigoInfo: function () { + // by using this.$static, we're making sure that dejavu + // uses late binding to resolve the member. If you're + // looking for early binding, you can use this.$self + // instead + console.log( + this.$static.INDIGO_WEBSITE, + this.$static.INDIGO_EMAIL + ); + } + }, + + // method/attribute visibility is controlled by + // the number of underscores that the identifier + // has: + // public: no underscores + // protected: 1 underscore + // private: 2 underscores + // + // the attribute below is protected + _name: null, + + getName: function () { + return this._name; + }, + + setName: function (name) { + this._name = name; + + return this; + }, + + // note that we're not implementing the method `think()` of the + // EngineerInterface. This will be automatically turned into an + // abstract method, since we're in an abstract class + $abstracts: { + beAwesome: function () {} + + // you can also put "$statics {}" here + // to create an abstract static method + }, + + // finals are not overridable + $finals: { + // you can also put "$statics {}" here + // to create a final static method + + thisIsFinal: function () { + console.log('Can\'t change this!'); + } + } +}); + +// ------------ A CONCRETE CLASS ------------ +// also, if you need this concrete class to be final, +// you can just use dejavu.FinalClass.declare instead +var Indigo = dejavu.Class.declare({ + $name: 'Indigo', + // class extends another one. + // + // in case you need to extend from several classes, + // you can instead use $borrows, and specify an + // array of identifiers. Still, note that borrowing + // will not allow you to perform dejavu.instanceOf + // tests, as the class is not technically extending + // the other, just borrowing its behaviour. + $extends: AbstractIndigo, + + _subject: 'nothing', + + initialize: function (name) { + // call the parent method, in this case the parent constructor, + // but can be applied to any method when you need to call the + // overridden method + this.$super(); + + this.setName(name); + + this._logThought(); + }, + + beAwesome: function () { + console.log(this._name, 'is being awesome!'); + this.$self.logIndigoInfo(); + this.think('the next big thing'); + }, + + think: function (subject) { + this._subject = subject; + }, + + _logThought: function () { + console.log(this._name, 'is thinking about', this._subject); + } +}); + +var indigo = new Indigo('André'); +indigo.beAwesome(); + +// check the type of an object +console.log( + dejavu.instanceOf(indigo, EngineerInterface) ? + 'we have an engineer!' + : 'say what now?' +); +console.log(dejavu.instanceOf(indigo, Indigo) ? + 'we have an indigo!' + : 'say what now?' +); +// native instanceof also works for classes, but not for interfaces +console.log((indigo instanceof Indigo) ? + 'we have an indigo!' + : 'say what now?' +); + +``` + + + +## Taking it to another level + +Front-end devs are encouraged to program using the AMD paradigm because of its obvious benefits. +Since dejavu is built on it, it will integrate seamlessly with your AMD loader. + +```js +{ + // your loader config + paths: { + 'mout': '../vendor/mout/src' + }, + packages: [ + { + name: 'dejavu', + // You can switch to the loose mode anytime + location: '/path/to/dejavu/dist/strict' + } + ] +} +``` + +With this setup, you can require the dejavu object or specific parts of it: + +```js +// Load dejavu completely +define(['dejavu'], function (dejavu) { + + // the dejavu variable is an object that contains: + // Class + // FinalClass + // AbstractClass + // Interface + // instanceOf + // options + + // example usage + var Person = dejavu.Class.declare({ + initialize: function () { + // ... + } + }); + + return Person; +}); + +// In this case, only the `Class` module of `dejavu` is included, +// which means all the other modules are not loaded. +define(['dejavu/Class'], function (Class) { + + // Example usage + var Person = Class.declare({ + initialize: function () { + // ... + } + }); + + return MyClass; +}); +``` + + + +## Additional details + +### Binding and anonymous members + +You will eventually run into a situation where you want to declare a callback that accesses class members. On traditional JavaScript, you would just `var that = this` or `.bind(this)`, and everything would be ok, because there is no restriction on visibility. Since `dejavu` enforces this, you will need to mark that callback as a member of the class, using something like the following: + +```js +// ... +var that = this; +setTimeout(function () { + that._someProperty = 'protected properties on callbacks'; +}.$member(), 1000); +``` + +```js +// ... +setTimeout(function () { + this._someProperty = 'protected properties on callbacks'; +}.$member().bind(this), 1000); +``` + +If the `$member().bind(this)` is too verbose for you, you can just `.$bind(this)`, which is equivalent. + +Finally, when defining a method directly on the class declaration that you know will always be used using the class context, you can bind it right there like so: + +```js +var MyClass = dejavu.Class.declare({ + $name: 'MyClass', + + doSomething: function () { + // notice that _someMethod is $bound() below, + // which is more efficient than $bind()ing on + // every execution of doSomething() + setTimeout(this._someMethod, 1000); + }, + + _someMethod: function () { + console.log('method efficiently bound'); + }.$bound() +}); +``` + +### Classes/instances are locked + +By default, constructors and instances are locked. This means that no one can monkey patch your code. + +This behaviour can be changed in two ways: + +#### With the $locked flag: + +```js +var UnlockedIndigo = Class.declare({ + $name: 'UnlockedIndigo', + $locked: false + + initialize: function () { + // Altough the foo property is not declared, + // it will not throw an error + + this.name = 'Filipe'; + }, + + talk: function () { + console.log('An indigo is talking!'); + } +}); +``` + +Members can be added, replaced and deleted from the prototype: + +```js +UnlockedIndigo.prototype.age = 20; +UnlockedIndigo.prototype.talk = function () { + console.log('... now is running'); +}; +``` + +Members can be added, replaced and deleted from the instance: + +```js +var filipe = new UnlockedIndigo(); +filipe.friends = ['Marco','Andre']; +filipe.talk = function () { + console.log('I am talking about dejavu!'); +}; +``` + +#### By setting the global option: + +This will change the default behaviour, but classes can still override it with the $locked flag. + +```js +dejavu.options.locked = false; +``` + +Note that once a class is unlocked, its subclasses cannot be locked. +Also, although undeclared members are allowed, they will not have their access controlled (they are interpreted as public). + + + +### Vanilla classes + +`dejavu` allows you to extend or borrow vanilla classes. In this case, constructors and instances are forcibly UNLOCKED. + +```js +function Person(name) { + this.name = name; +}; + +var Engineer = dejavu.Class.declare({ + $extends: Person +}); + +var filipe = new Engineer('Filipe'); +// Engineer class and filipe instance are unlocked + +``` + + +### Debugging + +In strict mode, logging instances with `console.log` will print some strange stuff (getters, setters, etc). +This happens because `dejavu` manages accesses to private/protected members as well as make other stuff work. +To get around this issue, `dejavu` provides a `console.inspect` method that works just like `console.log` but prints a friendly object representation of the instance. + + + +## Optimizer + +`dejavu` bundles an optimizer that makes your code faster and lighter. + +It specifically: + +- Improves `$super()`, `$self` and `$static` usage +- Removes the need for wrappers, improving performance by a great margin +- Removes abstract functions from abstract classes +- Removes functions from interfaces +- Removes all `$locked` and `$member()` because they are not used in the loose version + +The optimizer is located in the `bin` folder. +If you are optimizing your code for `nodejs` then pass the --closure option. This will boost the performance when running code in v8. +Please look at the jsperf results to see the difference in the different browsers. + +Example usage: + +`node optimizer < file_in.js > file_out.js` + +You can also use the optimizer programatically, please check `bin/optimizer` for an example. + +`dejavu` also comes with a automaton task. + +Below is a sample usage: + +```js +var dejavuOptimizer = require('dejavu/tasks/optimizer.autofile'); + +module.exports = { + tasks: [ + { + task: dejavuOptimizer, + options: { + files: { + 'src/myfile.js': 'dst/myfile.opt.js' + } + } + } + ] +} +``` + + + +## Works on + +* IE (6+) +* Chrome (4+) +* Safari (3+) +* Firefox (3.6+) +* Opera (9+) +* Node.js and Rhino + + + +## Dependencies + +dejavu depends on [mout](https://github.com/mout/mout). +If you use the regular build, you don't need to worry because all functions used from mout are bundled for you. +If you use the AMD build, learn [how](https://github.com/IndigoUnited/dejavu#taking-it-to-another-level) to setup your loader. +If you use dejavu on `node`, `npm` will take care of fetching everything for you. + + +## Building dejavu + +Simply run `npm install` to install all the tools needed. +Then just run `npm run-script build` or `node build`. + + + +## Testing dejavu + +`dejavu` has more than 250 tests. +Simply run `npm install` to install all the tools needed. +Then just run `npm test` to execute them. + + + +## License ## + +Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php). diff --git a/src/core/static/js/dejavu/loose/dejavu.js b/src/core/static/js/dejavu/loose/dejavu.js new file mode 100755 index 0000000..da6d6c9 --- /dev/null +++ b/src/core/static/js/dejavu/loose/dejavu.js @@ -0,0 +1,2307 @@ +(function() { +/** + * almond 0.2.4 Copyright (c) 2011-2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/almond for details + */ +//Going sloppy to avoid 'use strict' string cost, but strict practices should +//be followed. +/*jslint sloppy: true */ +/*global setTimeout: false */ + +var requirejs, require, define; +(function (undef) { + var main, req, makeMap, handlers, + defined = {}, + waiting = {}, + config = {}, + defining = {}, + hasOwn = Object.prototype.hasOwnProperty, + aps = [].slice; + + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); + } + + /** + * Given a relative module name, like ./something, normalize it to + * a real name that can be mapped to a path. + * @param {String} name the relative name + * @param {String} baseName a real name that the name arg is relative + * to. + * @returns {String} normalized name + */ + function normalize(name, baseName) { + var nameParts, nameSegment, mapValue, foundMap, + foundI, foundStarMap, starI, i, j, part, + baseParts = baseName && baseName.split("/"), + map = config.map, + starMap = (map && map['*']) || {}; + + //Adjust any relative paths. + if (name && name.charAt(0) === ".") { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + //Convert baseName to array, and lop off the last part, + //so that . matches that "directory" and not name of the baseName's + //module. For instance, baseName of "one/two/three", maps to + //"one/two/three.js", but we want the directory, "one/two" for + //this normalization. + baseParts = baseParts.slice(0, baseParts.length - 1); + + name = baseParts.concat(name.split("/")); + + //start trimDots + for (i = 0; i < name.length; i += 1) { + part = name[i]; + if (part === ".") { + name.splice(i, 1); + i -= 1; + } else if (part === "..") { + if (i === 1 && (name[2] === '..' || name[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + name.splice(i - 1, 2); + i -= 2; + } + } + } + //end trimDots + + name = name.join("/"); + } else if (name.indexOf('./') === 0) { + // No baseName, so this is ID is resolved relative + // to baseUrl, pull off the leading dot. + name = name.substring(2); + } + } + + //Apply map config if available. + if ((baseParts || starMap) && map) { + nameParts = name.split('/'); + + for (i = nameParts.length; i > 0; i -= 1) { + nameSegment = nameParts.slice(0, i).join("/"); + + if (baseParts) { + //Find the longest baseName segment match in the config. + //So, do joins on the biggest to smallest lengths of baseParts. + for (j = baseParts.length; j > 0; j -= 1) { + mapValue = map[baseParts.slice(0, j).join('/')]; + + //baseName segment has config, find if it has one for + //this name. + if (mapValue) { + mapValue = mapValue[nameSegment]; + if (mapValue) { + //Match, update name to the new value. + foundMap = mapValue; + foundI = i; + break; + } + } + } + } + + if (foundMap) { + break; + } + + //Check for a star map match, but just hold on to it, + //if there is a shorter segment match later in a matching + //config, then favor over this star map. + if (!foundStarMap && starMap && starMap[nameSegment]) { + foundStarMap = starMap[nameSegment]; + starI = i; + } + } + + if (!foundMap && foundStarMap) { + foundMap = foundStarMap; + foundI = starI; + } + + if (foundMap) { + nameParts.splice(0, foundI, foundMap); + name = nameParts.join('/'); + } + } + + return name; + } + + function makeRequire(relName, forceSync) { + return function () { + //A version of a require function that passes a moduleName + //value for items that may need to + //look up paths relative to the moduleName + return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync])); + }; + } + + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(depName) { + return function (value) { + defined[depName] = value; + }; + } + + function callDep(name) { + if (hasProp(waiting, name)) { + var args = waiting[name]; + delete waiting[name]; + defining[name] = true; + main.apply(undef, args); + } + + if (!hasProp(defined, name) && !hasProp(defining, name)) { + throw new Error('No ' + name); + } + return defined[name]; + } + + //Turns a plugin!resource to [plugin, resource] + //with the plugin being undefined if the name + //did not have a plugin prefix. + function splitPrefix(name) { + var prefix, + index = name ? name.indexOf('!') : -1; + if (index > -1) { + prefix = name.substring(0, index); + name = name.substring(index + 1, name.length); + } + return [prefix, name]; + } + + /** + * Makes a name map, normalizing the name, and using a plugin + * for normalization if necessary. Grabs a ref to plugin + * too, as an optimization. + */ + makeMap = function (name, relName) { + var plugin, + parts = splitPrefix(name), + prefix = parts[0]; + + name = parts[1]; + + if (prefix) { + prefix = normalize(prefix, relName); + plugin = callDep(prefix); + } + + //Normalize according + if (prefix) { + if (plugin && plugin.normalize) { + name = plugin.normalize(name, makeNormalize(relName)); + } else { + name = normalize(name, relName); + } + } else { + name = normalize(name, relName); + parts = splitPrefix(name); + prefix = parts[0]; + name = parts[1]; + if (prefix) { + plugin = callDep(prefix); + } + } + + //Using ridiculous property names for space reasons + return { + f: prefix ? prefix + '!' + name : name, //fullName + n: name, + pr: prefix, + p: plugin + }; + }; + + function makeConfig(name) { + return function () { + return (config && config.config && config.config[name]) || {}; + }; + } + + handlers = { + require: function (name) { + return makeRequire(name); + }, + exports: function (name) { + var e = defined[name]; + if (typeof e !== 'undefined') { + return e; + } else { + return (defined[name] = {}); + } + }, + module: function (name) { + return { + id: name, + uri: '', + exports: defined[name], + config: makeConfig(name) + }; + } + }; + + main = function (name, deps, callback, relName) { + var cjsModule, depName, ret, map, i, + args = [], + usingExports; + + //Use name if no relName + relName = relName || name; + + //Call the callback to define the module, if necessary. + if (typeof callback === 'function') { + + //Pull out the defined dependencies and pass the ordered + //values to the callback. + //Default to [require, exports, module] if no deps + deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; + for (i = 0; i < deps.length; i += 1) { + map = makeMap(deps[i], relName); + depName = map.f; + + //Fast path CommonJS standard dependencies. + if (depName === "require") { + args[i] = handlers.require(name); + } else if (depName === "exports") { + //CommonJS module spec 1.1 + args[i] = handlers.exports(name); + usingExports = true; + } else if (depName === "module") { + //CommonJS module spec 1.1 + cjsModule = args[i] = handlers.module(name); + } else if (hasProp(defined, depName) || + hasProp(waiting, depName) || + hasProp(defining, depName)) { + args[i] = callDep(depName); + } else if (map.p) { + map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); + args[i] = defined[depName]; + } else { + throw new Error(name + ' missing ' + depName); + } + } + + ret = callback.apply(defined[name], args); + + if (name) { + //If setting exports via "module" is in play, + //favor that over return value and exports. After that, + //favor a non-undefined return value over exports use. + if (cjsModule && cjsModule.exports !== undef && + cjsModule.exports !== defined[name]) { + defined[name] = cjsModule.exports; + } else if (ret !== undef || !usingExports) { + //Use the return value from the function. + defined[name] = ret; + } + } + } else if (name) { + //May just be an object definition for the module. Only + //worry about defining if have a module name. + defined[name] = callback; + } + }; + + requirejs = require = req = function (deps, callback, relName, forceSync, alt) { + if (typeof deps === "string") { + if (handlers[deps]) { + //callback in this case is really relName + return handlers[deps](callback); + } + //Just return the module wanted. In this scenario, the + //deps arg is the module name, and second arg (if passed) + //is just the relName. + //Normalize module name, if it contains . or .. + return callDep(makeMap(deps, callback).f); + } else if (!deps.splice) { + //deps is a config object, not an array. + config = deps; + if (callback.splice) { + //callback is an array, which means it is a dependency list. + //Adjust args if there are dependencies + deps = callback; + callback = relName; + relName = null; + } else { + deps = undef; + } + } + + //Support require(['a']) + callback = callback || function () {}; + + //If relName is a function, it is an errback handler, + //so remove it. + if (typeof relName === 'function') { + relName = forceSync; + forceSync = alt; + } + + //Simulate async callback; + if (forceSync) { + main(undef, deps, callback, relName); + } else { + //Using a non-zero value because of concern for what old browsers + //do, and latest browsers "upgrade" to 4 if lower value is used: + //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: + //If want a value immediately, use require('id') instead -- something + //that works in almond on the global level, but not guaranteed and + //unlikely to work in other AMD implementations. + setTimeout(function () { + main(undef, deps, callback, relName); + }, 4); + } + + return req; + }; + + /** + * Just drops the config on the floor, but returns req in case + * the config return value is used. + */ + req.config = function (cfg) { + config = cfg; + return req; + }; + + define = function (name, deps, callback) { + + //This module may not have dependencies + if (!deps.splice) { + //deps is not an array, so probably means + //an object literal or factory function for + //the value. Adjust args. + callback = deps; + deps = []; + } + + if (!hasProp(defined, name) && !hasProp(waiting, name)) { + waiting[name] = [name, deps, callback]; + } + }; + + define.amd = { + jQuery: true + }; +}()); + +define("almond", function(){}); + +define('lib/inspect',[ +], function ( +) { + + + + // TODO: Should inspect do something more? + // If the code is not optimized, they will see wrappers when clicking in functions + // and also some strange things like $bind and $static. + // But I think it does not compensate the extra bytes to support it + // If we ever do this, we must adjust the console.inspect bellow + + // Add inspect method to the console + if (typeof console === 'object' && !console.inspect) { + console.inspect = typeof navigator !== 'undefined' && /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent) ? + console.dir || console.log : // console.dir is better in IE + console.log; + } +}); +define('lib/printWarning',[], function () { + + + + /** + * Simple function to print warning in the console only if the console is available. + * + * @param {String} message The message to print + */ + function printWarning(message) { + if (typeof console !== 'undefined') { + console.warn(message); + } + } + + return printWarning; +}); + +define('mout/lang/kindOf',['require','exports','module'],function (require, exports, module) { + + var _rKind = /^\[object (.*)\]$/, + _toString = Object.prototype.toString, + UNDEF; + + /** + * Gets the "kind" of value. (e.g. "String", "Number", etc) + */ + function kindOf(val) { + if (val === null) { + return 'Null'; + } else if (val === UNDEF) { + return 'Undefined'; + } else { + return _rKind.exec( _toString.call(val) )[1]; + } + } + module.exports = kindOf; + + +}); + +define('mout/lang/isKind',['require','exports','module','./kindOf'],function (require, exports, module) {var kindOf = require('./kindOf'); + /** + * Check if value is from a specific "kind". + */ + function isKind(val, kind){ + return kindOf(val) === kind; + } + module.exports = isKind; + + +}); + +define('mout/lang/isFunction',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isFunction(val) { + return isKind(val, 'Function'); + } + module.exports = isFunction; + + +}); + +define('lib/hasDefineProperty',['mout/lang/isFunction'], function (isFunction) { + + + + /** + * Check if the environment supports Object.hasDefineProperty. + * There is some quirks related to IE that is handled inside. + * + * @return {Boolean} True if it supports, false otherwise + */ + function hasDefineProperty() { + if (!isFunction(Object.defineProperty)) { + return false; + } + + // Avoid IE8 bug + try { + Object.defineProperty({}, 'x', {}); + } catch (e) { + return false; + } + + return true; + } + + return hasDefineProperty(); +}); +define('lib/obfuscateProperty',['./hasDefineProperty'], function (hasDefineProperty) { + + + + /** + * Sets the key of object with the specified value. + * The property is obfuscated, by not being enumerable, configurable and writable. + * + * @param {Object} obj The object + * @param {String} key The key + * @param {Mixed} value The value + * @param {Boolean} [isWritable] True to be writable, false otherwise (defaults to false) + * @param {Boolean} [isDeletable] True to be deletable, false otherwise (defaults to false) + */ + function obfuscateProperty(obj, key, value, isWritable, isDeletable) { + if (hasDefineProperty) { + Object.defineProperty(obj, key, { + value: value, + configurable: isDeletable || false, + writable: isWritable || false, + enumerable: false + }); + } else { + obj[key] = value; + } + } + + return obfuscateProperty; +}); + +define('mout/lang/isNumber',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isNumber(val) { + return isKind(val, 'Number'); + } + module.exports = isNumber; + + +}); + +define('mout/lang/isString',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isString(val) { + return isKind(val, 'String'); + } + module.exports = isString; + + +}); + +define('mout/lang/isBoolean',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isBoolean(val) { + return isKind(val, 'Boolean'); + } + module.exports = isBoolean; + + +}); + +define('lib/isImmutable',[ + 'mout/lang/isNumber', + 'mout/lang/isString', + 'mout/lang/isBoolean' +], function ( + isNumber, + isString, + isBoolean +) { + + + + /** + * Checks if a value is immutable. + * + * @param {Mixed} value The value + * + * @return {Boolean} True if it is, false otherwise + */ + function isImmutable(value) { + return value == null || isBoolean(value) || isNumber(value) || isString(value); + } + + return isImmutable; +}); + +define('mout/lang/isObject',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isObject(val) { + return isKind(val, 'Object'); + } + module.exports = isObject; + + +}); + +define('mout/lang/isArray',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + var isArray = Array.isArray || function (val) { + return isKind(val, 'Array'); + }; + module.exports = isArray; + + +}); + +define('mout/lang/isDate',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isDate(val) { + return isKind(val, 'Date'); + } + module.exports = isDate; + + +}); + +define('mout/lang/isRegExp',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isRegExp(val) { + return isKind(val, 'RegExp'); + } + module.exports = isRegExp; + + +}); + +define('mout/object/hasOwn',['require','exports','module'],function (require, exports, module) { + + /** + * Safer Object.hasOwnProperty + */ + function hasOwn(obj, prop){ + return Object.prototype.hasOwnProperty.call(obj, prop); + } + + module.exports = hasOwn; + + + +}); + +define('mout/object/forIn',['require','exports','module'],function (require, exports, module) { + + var _hasDontEnumBug, + _dontEnums; + + function checkDontEnum(){ + _dontEnums = [ + 'toString', + 'toLocaleString', + 'valueOf', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'constructor' + ]; + + _hasDontEnumBug = true; + + for (var key in {'toString': null}) { + _hasDontEnumBug = false; + } + } + + /** + * Similar to Array/forEach but works over object properties and fixes Don't + * Enum bug on IE. + * based on: http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation + */ + function forIn(obj, fn, thisObj){ + var key, i = 0; + // no need to check if argument is a real object that way we can use + // it for arrays, functions, date, etc. + + //post-pone check till needed + if (_hasDontEnumBug == null) checkDontEnum(); + + for (key in obj) { + if (exec(fn, obj, key, thisObj) === false) { + break; + } + } + + if (_hasDontEnumBug) { + while (key = _dontEnums[i++]) { + // since we aren't using hasOwn check we need to make sure the + // property was overwritten + if (obj[key] !== Object.prototype[key]) { + if (exec(fn, obj, key, thisObj) === false) { + break; + } + } + } + } + } + + function exec(fn, obj, key, thisObj){ + return fn.call(thisObj, obj[key], key, obj); + } + + module.exports = forIn; + + + +}); + +define('mout/object/forOwn',['require','exports','module','./hasOwn','./forIn'],function (require, exports, module) {var hasOwn = require('./hasOwn'); +var forIn = require('./forIn'); + + /** + * Similar to Array/forEach but works over object properties and fixes Don't + * Enum bug on IE. + * based on: http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation + */ + function forOwn(obj, fn, thisObj){ + forIn(obj, function(val, key){ + if (hasOwn(obj, key)) { + return fn.call(thisObj, obj[key], key, obj); + } + }); + } + + module.exports = forOwn; + + + +}); + +define('mout/object/mixIn',['require','exports','module','./forOwn'],function (require, exports, module) {var forOwn = require('./forOwn'); + + /** + * Combine properties from all the objects into first one. + * - This method affects target object in place, if you want to create a new Object pass an empty object as first param. + * @param {object} target Target Object + * @param {...object} objects Objects to be combined (0...n objects). + * @return {object} Target Object. + */ + function mixIn(target, objects){ + var i = 0, + n = arguments.length, + obj; + while(++i < n){ + obj = arguments[i]; + if (obj != null) { + forOwn(obj, copyProp, target); + } + } + return target; + } + + function copyProp(val, key){ + this[key] = val; + } + + module.exports = mixIn; + + +}); + +define('mout/lang/createObject',['require','exports','module','../object/mixIn'],function (require, exports, module) {var mixIn = require('../object/mixIn'); + + /** + * Create Object using prototypal inheritance and setting custom properties. + * - Mix between Douglas Crockford Prototypal Inheritance <http://javascript.crockford.com/prototypal.html> and the EcmaScript 5 `Object.create()` method. + * @param {object} parent Parent Object. + * @param {object} [props] Object properties. + * @return {object} Created object. + */ + function createObject(parent, props){ + function F(){} + F.prototype = parent; + return mixIn(new F(), props); + + } + module.exports = createObject; + + + +}); + +define('mout/array/indexOf',['require','exports','module'],function (require, exports, module) { + + /** + * Array.indexOf + */ + function indexOf(arr, item, fromIndex) { + fromIndex = fromIndex || 0; + var n = arr.length, + i = fromIndex < 0? n + fromIndex : fromIndex; + while (i < n) { + // we iterate over sparse items since there is no way to make it + // work properly on IE 7-8. see #64 + if (arr[i] === item) { + return i; + } + i += 1; + } + return -1; + } + + module.exports = indexOf; + + +}); + +define('mout/array/combine',['require','exports','module','./indexOf'],function (require, exports, module) {var indexOf = require('./indexOf'); + + /** + * Combines an array with all the items of another. + * Does not allow duplicates and is case and type sensitive. + */ + function combine(arr1, arr2) { + + var x, length = arr2.length; + + for (x = 0; x < length; x++) { + if (indexOf(arr1, arr2[x]) === -1) { + arr1.push(arr2[x]); + } + } + + return arr1; + } + module.exports = combine; + + +}); + +define('mout/array/contains',['require','exports','module','./indexOf'],function (require, exports, module) {var indexOf = require('./indexOf'); + + /** + * If array contains values. + */ + function contains(arr, val) { + return indexOf(arr, val) !== -1; + } + module.exports = contains; + + +}); + +define('mout/lang/isPlainObject',['require','exports','module'],function (require, exports, module) { + + /** + * Checks if the value is created by the `Object` constructor. + */ + function isPlainObject(value) { + return (!!value + && typeof value === 'object' + && value.constructor === Object); + } + + module.exports = isPlainObject; + + + +}); + +define('mout/lang/clone',['require','exports','module','./kindOf','./isPlainObject','../object/mixIn'],function (require, exports, module) {var kindOf = require('./kindOf'); +var isPlainObject = require('./isPlainObject'); +var mixIn = require('../object/mixIn'); + + /** + * Clone native types. + */ + function clone(val){ + switch (kindOf(val)) { + case 'Object': + return cloneObject(val); + case 'Array': + return cloneArray(val); + case 'RegExp': + return cloneRegExp(val); + case 'Date': + return cloneDate(val); + default: + return val; + } + } + + function cloneObject(source) { + if (isPlainObject(source)) { + return mixIn({}, source); + } else { + return source; + } + } + + function cloneRegExp(r) { + var flags = ''; + flags += r.multiline ? 'm' : ''; + flags += r.global ? 'g' : ''; + flags += r.ignorecase ? 'i' : ''; + return new RegExp(r.source, flags); + } + + function cloneDate(date) { + return new Date(+date); + } + + function cloneArray(arr) { + return arr.slice(); + } + + module.exports = clone; + + + +}); + +define('mout/lang/deepClone',['require','exports','module','./clone','../object/forOwn','./kindOf','./isPlainObject'],function (require, exports, module) {var clone = require('./clone'); +var forOwn = require('../object/forOwn'); +var kindOf = require('./kindOf'); +var isPlainObject = require('./isPlainObject'); + + /** + * Recursively clone native types. + */ + function deepClone(val, instanceClone) { + switch ( kindOf(val) ) { + case 'Object': + return cloneObject(val, instanceClone); + case 'Array': + return cloneArray(val, instanceClone); + default: + return clone(val); + } + } + + function cloneObject(source, instanceClone) { + if (isPlainObject(source)) { + var out = {}; + forOwn(source, function(val, key) { + this[key] = deepClone(val, instanceClone); + }, out); + return out; + } else if (instanceClone) { + return instanceClone(source); + } else { + return source; + } + } + + function cloneArray(arr, instanceClone) { + var out = [], + i = -1, + n = arr.length, + val; + while (++i < n) { + out[i] = deepClone(arr[i], instanceClone); + } + return out; + } + + module.exports = deepClone; + + + + +}); + +define('lib/mixIn',[], function () { + + + + /** + * This method does exactly the same as the mout counterpart but + * does not perform hasOwn for each key in the objects. + * This is only done because the object prototype is guaranteed to be sealed. + * There is other ones that could be also optimized, but this is the most used + * one in the loose version. + * + * @param {object} target Target Object + * @param {...object} objects Objects to be combined (0...n objects) + * + * @return {object} Target Object + */ + function mixIn(target, objects) { + var x, + length = arguments.length, + key, + curr; + + for (x = 1; x < length; x += 1) { + curr = arguments[x]; + for (key in arguments[x]) { + target[key] = curr[key]; + } + } + + return target; + } + + return mixIn; +}); + +define('mout/array/append',['require','exports','module'],function (require, exports, module) { + + /** + * Appends an array to the end of another. + * The first array will be modified. + */ + function append(arr1, arr2) { + var pad = arr1.length, + i = -1, + n = arr2.length; + while (++i < n) { + arr1[pad + i] = arr2[i]; + } + return arr1; + } + module.exports = append; + + +}); + +define('mout/function/bind',['require','exports','module'],function (require, exports, module) { + + function slice(arr, offset){ + return Array.prototype.slice.call(arr, offset || 0); + } + + /** + * Return a function that will execute in the given context, optionally adding any additional supplied parameters to the beginning of the arguments collection. + * @param {Function} fn Function. + * @param {object} context Execution context. + * @param {rest} args Arguments (0...n arguments). + * @return {Function} Wrapped Function. + */ + function bind(fn, context, args){ + var argsArr = slice(arguments, 2); //curried args + return function(){ + return fn.apply(context, argsArr.concat(slice(arguments))); + }; + } + + module.exports = bind; + + + +}); + +define('mout/lang/toArray',['require','exports','module','./kindOf'],function (require, exports, module) {var kindOf = require('./kindOf'); + + var _win = this; + + /** + * Convert array-like object into array + */ + function toArray(val){ + var ret = [], + kind = kindOf(val), + n; + + if (val != null) { + if ( val.length == null || kind === 'String' || kind === 'Function' || kind === 'RegExp' || val === _win ) { + //string, regexp, function have .length but user probably just want + //to wrap value into an array.. + ret[ret.length] = val; + } else { + //window returns true on isObject in IE7 and may have length + //property. `typeof NodeList` returns `function` on Safari so + //we can't use it (#58) + n = val.length; + while (n--) { + ret[n] = val[n]; + } + } + } + return ret; + } + module.exports = toArray; + + +}); + +define('mout/array/forEach',['require','exports','module'],function (require, exports, module) { + + /** + * Array forEach + */ + function forEach(arr, callback, thisObj) { + if (arr == null) { + return; + } + var i = -1, + n = arr.length; + while (++i < n) { + // we iterate over sparse items since there is no way to make it + // work properly on IE 7-8. see #64 + if ( callback.call(thisObj, arr[i], i, arr) === false ) { + break; + } + } + } + + module.exports = forEach; + + + +}); + +define('mout/array/filter',['require','exports','module','./forEach'],function (require, exports, module) {var forEach = require('./forEach'); + + /** + * Array filter + */ + function filter(arr, callback, thisObj) { + var results = []; + forEach(arr, function (val, i, arr) { + if ( callback.call(thisObj, val, i, arr) ) { + results.push(val); + } + }); + return results; + } + + module.exports = filter; + + + +}); + +define('mout/array/unique',['require','exports','module','./indexOf','./filter'],function (require, exports, module) {var indexOf = require('./indexOf'); +var filter = require('./filter'); + + /** + * @return {array} Array of unique items + */ + function unique(arr){ + return filter(arr, isUnique); + } + + function isUnique(item, i, arr){ + return indexOf(arr, item, i+1) === -1; + } + + module.exports = unique; + + + +}); + +define('mout/array/some',['require','exports','module'],function (require, exports, module) { + + /** + * Array some + */ + function some(arr, callback, thisObj) { + var result = false, + i = -1, + n = arr.length; + while (++i < n) { + // we iterate over sparse items since there is no way to make it + // work properly on IE 7-8. see #64 + if ( callback.call(thisObj, arr[i], i, arr) ) { + result = true; + break; + } + } + return result; + } + + module.exports = some; + + +}); + +define('mout/array/difference',['require','exports','module','./unique','./filter','./some','./contains'],function (require, exports, module) {var unique = require('./unique'); +var filter = require('./filter'); +var some = require('./some'); +var contains = require('./contains'); + + + /** + * Return a new Array with elements that aren't present in the other Arrays. + */ + function difference(arr) { + var arrs = Array.prototype.slice.call(arguments, 1), + result = filter(unique(arr), function(needle){ + return !some(arrs, function(haystack){ + return contains(haystack, needle); + }); + }); + return result; + } + + module.exports = difference; + + + +}); + +define('mout/array/insert',['require','exports','module','./difference','../lang/toArray'],function (require, exports, module) {var difference = require('./difference'); +var toArray = require('../lang/toArray'); + + /** + * Insert item into array if not already present. + */ + function insert(arr, rest_items) { + var diff = difference(toArray(arguments).slice(1), arr); + if (diff.length) { + Array.prototype.push.apply(arr, diff); + } + return arr.length; + } + module.exports = insert; + + +}); + +define('Class',[ + './lib/inspect', + './lib/printWarning', + './lib/obfuscateProperty', + './lib/isImmutable', + 'mout/lang/isFunction', + 'mout/lang/isObject', + 'mout/lang/isArray', + 'mout/lang/isDate', + 'mout/lang/isRegExp', + 'mout/lang/createObject', + 'mout/object/hasOwn', + 'mout/array/combine', + 'mout/array/contains', + 'mout/lang/deepClone', + './lib/mixIn', + 'mout/array/append', + 'mout/function/bind', + 'mout/lang/toArray', + 'mout/array/insert' +], function ClassWrapper( + inspect, + printWarning, + obfuscateProperty, + isImmutable, + isFunction, + isObject, + isArray, + isDate, + isRegExp, + createObject, + hasOwn, + combine, + contains, + deepClone, + mixIn, + append, + bind, + toArray, + insert +) { + + + + var createClass, + Class = {}, + $class = '$class', + $interface = '$interface', + $bound = '$bound_dejavu', + $wrapped = '$wrapped_dejavu'; + + /** + * Function that does exactly the same as the mout counterpart, + * but is faster in firefox due to a bug: + * https://bugzilla.mozilla.org/show_bug.cgi?id=816439 + */ + function inheritPrototype(A, B) { + var F = function () {}; + F.prototype = B.prototype; + A.prototype = new F(); + A.prototype.constructor = A; + } + + /** + * Wraps a method. + * This is to make some alias such as $super and $self to work correctly. + * + * @param {Function} method The method to wrap + * @param {Function} constructor The constructor + * @param {Function} parent The parent method + * + * @return {Function} The wrapper + */ + function wrapMethod(method, constructor, parent) { + // Return the method if the class was created efficiently + if (constructor[$class].efficient) { + return method; + } + + var wrapper, + isWrapped = !!method[$wrapped]; + + if (isWrapped) { + method = method[$wrapped]; + } + + if (!parent) { + if (isWrapped || method.toString().indexOf('$self') !== -1) { + wrapper = function () { + var _self = this.$self, + ret; + + // TODO: We should be using a try finally here to ensure that $super is restored correctly but it slows down by a lot! + // Find a better solution? + this.$self = constructor; + ret = method.apply(this, arguments); + this.$self = _self; + + return ret; + }; + } else { + return method; + } + } else { + wrapper = function () { + var _super = this.$super, + _self = this.$self, + ret; + + // TODO: We should be using a try finally here to ensure that $super is restored correctly but it slows down by a lot! + // Find a better solution? + this.$super = parent; + this.$self = constructor; + ret = method.apply(this, arguments); + this.$super = _super; + this.$self = _self; + + return ret; + }; + } + + wrapper[$wrapped] = method; + + return wrapper; + } + + /** + * Borrows members from a vanilla object definition. + * + * @param {Object} params The parameters + * @param {Function} constructor The constructor + */ + function borrowFromVanilla(params, constructor) { + var key, + value; + + // Grab mixin members + for (key in params) { + // Ignore the constructor + if (/^(_){0,2}initialize$/.test(key)) { + continue; + } + + value = params[key]; + + if (!hasOwn(constructor.prototype, key)) { // Already defined members are not overwritten + if (isFunction(value) && !value[$class] && !value[$interface]) { + constructor.prototype[key] = wrapMethod(value, constructor, constructor.$parent ? constructor.$parent.prototype[key] : null); + + // If the function is specified to be bound, add it to the binds + if (value[$bound]) { + insert(constructor[$class].binds, key); + } + } else { + constructor.prototype[key] = value; + if (!isImmutable(value)) { + insert(constructor[$class].properties, key); + } + } + } + } + + } + + /** + * Parse borrows (mixins). + * + * @param {Object} params The parameters + * @param {Function} constructor The constructor + */ + function parseBorrows(params, constructor) { + if (hasOwn(params, '$borrows')) { + var current, + k, + key, + value, + mixins = toArray(params.$borrows), + i = mixins.length; + + for (i -= 1; i >= 0; i -= 1) { + current = mixins[i]; + // If it's a vanilla object + if (isObject(current)) { + borrowFromVanilla(current, constructor); + continue; + } + // If it's a vanilla class + if (isFunction(current) && !current[$class]) { + borrowFromVanilla(current.prototype, constructor); + continue; + } + + current = current.prototype; + + // Grab mixin members + borrowFromVanilla(current, constructor); + + // Grab mixin static methods + for (k = current.$static[$class].staticMethods.length - 1; k >= 0; k -= 1) { + key = current.$static[$class].staticMethods[k]; + + insert(constructor[$class].staticMethods, key); + constructor[key] = current.$static[key]; + } + + // Grab mixin static properties + for (key in current.$static[$class].staticProperties) { + value = current.$static[$class].staticProperties[key]; + + constructor[$class].staticProperties[key] = value; + constructor[key] = value; + } + + // Merge the binds + combine(constructor[$class].binds, current.$static[$class].binds); + } + + delete params.$borrows; + } + } + + /** + * Handle class interfaces. + * + * @param {Array} interfs The array of interfaces + * @param {Object} target The target that has the interfaces + */ + function handleInterfaces(interfs, target) { + interfs = toArray(interfs); + + var interf, + x = interfs.length, + k; + + for (x -= 1; x >= 0; x -= 1) { + interf = interfs[x]; + + // Inherit constants and add interface to the interfaces array + if (!contains(target[$class].interfaces, interf)) { + + for (k = interf[$interface].constants.length - 1; k >= 0; k -= 1) { + target[interf[$interface].constants[k]] = interf[interf[$interface].constants[k]]; + target[$class].staticProperties[interf[$interface].constants[k]] = interf[interf[$interface].constants[k]]; + } + + target[$class].interfaces.push(interf); + } + } + } + + /** + * Parse an object members. + * + * @param {Object} params The parameters + * @param {Function} constructor The constructor + * @param {Boolean} isFinal Parse the members as finals + */ + function parseMembers(params, constructor, isFinal) { + var key, + value, + cache = {}; + + if (hasOwn(params, '$statics')) { + for (key in params.$statics) { + value = params.$statics[key]; + + if (isFunction(value) && !value[$class] && !value[$interface]) { + insert(constructor[$class].staticMethods, key); + constructor[key] = wrapMethod(value, constructor, constructor.$parent ? constructor.$parent[key] : null); + } else { + constructor[$class].staticProperties[key] = value; + constructor[key] = value; + } + } + + delete params.$statics; + } + + // Save certain keywords in the cache for the loop bellow to work faster + if (hasOwn(params, '$implements')) { + cache.$implements = params.$implements; + delete params.$implements; + } + + if (hasOwn(params, '$abstracts')) { + cache.$abstracts = params.$abstracts; + delete params.$abstracts; + } + + for (key in params) { + value = params[key]; + + if (isFunction(value) && !value[$class] && !value[$interface]) { + constructor.prototype[key] = wrapMethod(value, constructor, constructor.$parent ? constructor.$parent.prototype[key] : null); + + // If the function is specified to be bound, add it to the binds + if (value[$bound]) { + insert(constructor[$class].binds, key); + delete value[$bound]; + } + + // We should remove the key here because a class may override from primitive to non primitive, + // but we skip it because the clone already handles it + } else { + constructor.prototype[key] = value; + + if (!isImmutable(value)) { + insert(constructor[$class].properties, key); + } + } + } + + // Restore from cache + mixIn(params, cache); + } + + /** + * Parse all the class members, including finals, static and constants. + * + * @param {Object} params The parameters + * @param {Function} constructor The constructor + */ + function parseClass(params, constructor) { + var key, + value, + saved = {}; + + delete params.$locked; + + // Check and save constants to parse later + if (hasOwn(params, '$constants')) { + saved.$constants = params.$constants; + delete params.$constants; + } + + // Check and save finals to parse later + if (hasOwn(params, '$finals')) { + saved.$finals = params.$finals; + delete params.$finals; + } + + // Parse members + parseMembers(params, constructor); + + // Parse constants + if (saved.$constants) { + for (key in saved.$constants) { + value = saved.$constants[key]; + + constructor[$class].staticProperties[key] = value; + constructor[key] = value; + } + } + + // Parse finals + if (saved.$finals) { + parseMembers(saved.$finals, constructor, true); + } + } + + /** + * Applies the context of given methods in the target. + * + * @param {Array} fns The array of functions to be bound + * @param {Object} instance The target instance + */ + function applyBinds(fns, instance) { + var i, + current; + + for (i = fns.length - 1; i >= 0; i -= 1) { + current = instance[fns[i]]; + instance[fns[i]] = bind(current, instance); + } + } + + + /** + * Builds the constructor function that calls the initialize and do + * more things internally. + * + * @param {Function} constructor The constructor function to assume and fill + * @param {Boolean} isAbstract Treat this class as abstract + * + * @return {Function} The constructor function + */ + function createConstructor(constructor, isAbstract) { + var Instance = constructor || function Instance() { + var x, + tmp; + + tmp = this.$static[$class]; + + // Reset some types of the object in order for each instance to have their variables + for (x = tmp.properties.length - 1; x >= 0; x -= 1) { + this[tmp.properties[x]] = deepClone(this[tmp.properties[x]]); + } + + if (!tmp.efficient) { + this.$super = this.$self = null; // Add the super & self to the instance object to speed lookup of the wrapper function + } + + // Apply binds + if (tmp.binds.length) { + applyBinds(tmp.binds, this, this); + } + + // Call initialize + this.initialize.apply(this, arguments); + }; + + if (!Instance[$class]) { + obfuscateProperty(Instance, $class, { staticMethods: [], staticProperties: {}, properties: [], interfaces: [], binds: [] }); + } + + return Instance; + } + + /** + * Marks a function as part of the class. + * + * @param {Function} func The function + */ + function doMember(func) { + /*jshint validthis:true*/ + func = func || this; + + return func; + } + + /** + * Bind. + * Works for anonymous functions also. + * + * @param {Function} func The function to be bound + * @param {...mixed} [args] The arguments to also be bound + * + * @return {Function} The bound function + */ + function doBind(func) { + /*jshint validthis:true*/ + var args = toArray(arguments), + bound; + + if (!func[$wrapped] && this.$static && this.$static[$class]) { + func = wrapMethod(func, this.$self || this.$static); + } + + args.splice(1, 0, this); + bound = bind.apply(func, args); + + return bound; + } + + /** + * Inherits aditional data from the parent, such as metadata, binds and static members. + * + * @param {Function} constructor The constructor + * @param {Function} parent The parent + */ + function inheritParent(constructor, parent) { + var x, + binds = parent[$class].binds, + key, + value; + + // Inherit binds + for (x = binds.length - 1; x >= 0; x -= 1) { + if (binds[x].substr(0, 2) !== '__') { + constructor[$class].binds.push(binds[x]); + } + } + + // Grab properties + append(constructor[$class].properties, parent[$class].properties); + + // Inherit static methods and properties + append(constructor[$class].staticMethods, parent[$class].staticMethods); + + for (x = parent[$class].staticMethods.length - 1; x >= 0; x -= 1) { + if (parent[$class].staticMethods[x].substr(0, 2) !== '__') { + constructor[parent[$class].staticMethods[x]] = parent[parent[$class].staticMethods[x]]; + } + } + + for (key in parent[$class].staticProperties) { + value = parent[$class].staticProperties[key]; + + if (key.substr(0, 2) !== '__') { + constructor[$class].staticProperties[key] = value; + constructor[key] = value; + } + } + + obfuscateProperty(constructor, '$parent', parent); + + // Inherit implemented interfaces + constructor[$class].interfaces = [].concat(parent[$class].interfaces); + } + + /** + * Attempts to optimize the constructor function. + * + * @param {Function} constructor The constructor + * + * @param {Function} The old or the new constructor + */ + function optimizeConstructor(constructor) { + var tmp = constructor[$class], + canOptimizeConst, + newConstructor, + parentInitialize; + + // Check if we can optimize the constructor + if (tmp.efficient) { + canOptimizeConst = constructor.$canOptimizeConst; + delete constructor.$canOptimizeConst; + + if (canOptimizeConst && !tmp.properties.length && !tmp.binds.length) { + if (hasOwn(constructor.prototype, 'initialize')) { + newConstructor = constructor.prototype.initialize; + } else { + parentInitialize = constructor.prototype.initialize; + + // Optimize common use cases + // Default to the slower apply.. + switch (parentInitialize.length) { + case 0: + newConstructor = function () { parentInitialize.call(this); }; + break; + case 1: + newConstructor = function (a) { parentInitialize.call(this, a); }; + break; + case 2: + newConstructor = function (a, b) { parentInitialize.call(this, a, b); }; + break; + case 3: + newConstructor = function (a, b, c) { parentInitialize.call(this, a, b, c); }; + break; + case 4: + newConstructor = function (a, b, c, d) { parentInitialize.call(this, a, b, c, d); }; + break; + default: + newConstructor = function () { parentInitialize.apply(this, arguments); }; + } + } + + if (constructor.$parent) { + inheritPrototype(newConstructor, constructor); + newConstructor.$parent = constructor.$parent; + } + + mixIn(newConstructor.prototype, constructor.prototype); + mixIn(newConstructor, constructor); + obfuscateProperty(newConstructor, $class, constructor[$class]); + + return newConstructor; + } + } + + return constructor; + } + + /** + * Function to easily extend another class. + * + * @param {Object|Function} params An object containing methods and properties or a function that returns it + * + * @return {Function} The new class constructor + */ + function extend(params, $arg) { + /*jshint validthis:true*/ + return Class.declare(this, params, $arg); + } + + /** + * Create a class definition. + * + * @param {Object} params An object containing methods and properties + * @param {Constructor} [constructor] Assume the passed constructor + * @param {Object} [opts] Options + * + * @return {Function} The constructor + */ + createClass = function (params, constructor, opts) { + opts = opts || {}; + + var dejavu, + parent, + isEfficient = !!constructor; + + + if (hasOwn(params, '$extends')) { + parent = params.$extends; + delete params.$extends; + + // If its a vanilla class create a dejavu class based on it + if (!parent[$class]) { + parent = createClass(parent.prototype, parent, { isVanilla: true }); + } + + params.initialize = opts.isVanilla ? dejavu : params.initialize || params._initialize || params.__initialize; + if (!params.initialize) { + delete params.initialize; + } + + dejavu = createConstructor(constructor); + inheritPrototype(dejavu, parent); + inheritParent(dejavu, parent); + } else { + dejavu = createConstructor(constructor); + params.initialize = opts.isVanilla ? dejavu : params.initialize || params._initialize || params.__initialize || function () {}; + } + + dejavu[$class].efficient = isEfficient; + if (!opts.isVanilla) { + delete params._initialize; + delete params.__initialize; + } + + // Parse mixins + parseBorrows(params, dejavu); + + // Parse class members + parseClass(params, dejavu); + + // Optimize constructor if possible + dejavu = optimizeConstructor(dejavu); + + // Assign aliases + obfuscateProperty(dejavu.prototype, '$static', dejavu); + obfuscateProperty(dejavu, '$static', dejavu); + obfuscateProperty(dejavu, '$self', null, true); + obfuscateProperty(dejavu, '$super', null, true); + obfuscateProperty(dejavu, '$member', doMember); + obfuscateProperty(dejavu, '$bind', doBind); + if (!dejavu.$parent) { + obfuscateProperty(dejavu.prototype, '$bind', doBind); + obfuscateProperty(dejavu.prototype, '$member', doMember); + } + + // Handle interfaces + if (hasOwn(params, '$implements')) { + handleInterfaces(params.$implements, dejavu); + delete dejavu.prototype.$implements; + } + + // Remove abstracts reference + if (hasOwn(params, '$abstracts')) { + delete params.$abstracts; + } + + // Supply .extend() to easily extend a class + dejavu.extend = extend; + + return dejavu; + }; + + /** + * Function to declare a class. + * This function can be called with various formats. + * + * @param {Function|Object} arg1 A class to extend or an object/function to obtain the members + * @param {Function|Object} arg2 Object/function to obtain the members + * + * @return {Function} The constructor + */ + Class.declare = function (arg1, arg2, $arg3) { + var params, + callable = isFunction(this) ? this : createClass, + tmp, + constructor; + + if (arg1 && arg2 && arg2 !== true) { + // create(parentClass, func | props, true | false) + if ((tmp = isFunction(arg2)) || $arg3) { + constructor = createConstructor(); + constructor.$canOptimizeConst = !!$arg3; + params = tmp ? arg2(arg1.prototype, arg1, constructor) : arg2; + // create(parentClass, props, false) + } else { + params = arg2; + } + + params.$extends = arg1; + // create(func | props, true | false) + } else if ((tmp = isFunction(arg1)) || arg2) { + constructor = createConstructor(); + constructor.$canOptimizeConst = !!arg2; + params = tmp ? arg1(constructor) : arg1; + // create (props) + } else { + params = arg1; + } + + // Validate params as an object + if (!isObject(params)) { + throw new Error('Expected class definition to be an object with the class members.'); + } + + return callable(params, constructor); + }; + + // Add a reference to the createFunction method to be used by other files + obfuscateProperty(Class, '$create', createClass); + + // Add custom bound function to supply binds + if (!Function.prototype.$bound || !Function.prototype.$bound.dejavu) { + try { + obfuscateProperty(Function.prototype, '$bound', function () { + this[$bound] = true; + + return this; + }); + Function.prototype.$bound.dejavu = true; + } catch (e) { + printWarning('Could not set Function.prototype.$bound.'); + } + } + + // Add custom bind function to supply binds + if (!Function.prototype.$bind || !Function.prototype.$bind.dejavu) { + try { + obfuscateProperty(Function.prototype, '$bind', function (context) { + var args = toArray(arguments); + args.splice(0, 1, this); + + return doBind.apply(context, args); + }); + Function.prototype.$bind.dejavu = true; + } catch (e) { + printWarning('Could not set Function.prototype.$bind.'); + } + } + + // Add custom member function to supply marking a function as part of the class + if (!Function.prototype.$member || !Function.prototype.$member.dejavu) { + try { + obfuscateProperty(Function.prototype, '$member', function () { + return doMember(this); + }); + Function.prototype.$member.dejavu = true; + } catch (e) { + printWarning('Could not set Function.prototype.$member.'); + } + } + + return Class; +}); + +define('AbstractClass',[ + 'mout/object/hasOwn', + 'mout/array/insert', + './Class' +], function AbstractClassWrapper( + hasOwn, + insert, + Class +) { + + + + var $abstract = '$abstract', + $class = '$class', + $bound = '$bound_dejavu', + AbstractClass = {}; + + /** + * Create an abstract class definition. + * + * @param {Object} params An object containing methods and properties + * @param {Constructor} [constructor] Assume the passed constructor + * + * @return {Function} The constructor + */ + function createAbstractClass(params, constructor) { + var def, + savedMembers, + key, + value; + + // Handle abstract methods + if (hasOwn(params, '$abstracts')) { + savedMembers = params.$abstracts; + delete params.$abstracts; + } + + // Create the class definition + def = Class.$create(params, constructor); + def[$abstract] = true; + + // Grab binds + if (savedMembers) { + for (key in savedMembers) { + value = savedMembers[key]; + + if (value[$bound]) { + insert(def[$class].binds, key); + } + } + } + + return def; + } + + /** + * Function to declare an abstract class. + * This function can be called with various formats. + * The first parameter can be a class to extend. + * The second parameter must be an object containing the class members or a function to obtain it. + * + * @param {Function|Object} arg1 A class, an object or a function + * @param {Function|Object} arg2 Object containing the class members or a function to obtain it. + * + * @return {Function} The constructor + */ + AbstractClass.declare = function (arg1, arg2, $arg3) { + return Class.declare.call(createAbstractClass, arg1, arg2, $arg3); + }; + + return AbstractClass; +}); + +define('Interface',[ + 'mout/lang/isFunction', + 'mout/object/hasOwn', + 'mout/lang/toArray' +], function InterfaceWrapper( + isFunction, + hasOwn, + toArray +) { + + + + var $interface = '$interface', + Interface = {}; + + /** + * Function to easily extend another interface. + * + * @param {Object} params An object containing methods and properties + * + * @return {Function} The new interface + */ + function extend(params) { + /*jshint validthis:true*/ + params.$extends = this; + + return Interface.declare(params); + } + + /** + * Create an interface definition. + * + * @param {Object} params An object containing methods and properties + * + * @return {Function} The constructor + */ + function createInterface(params) { + delete params.$name; + + var parents, + k, + i, + current, + interf = function () {}; + + interf[$interface] = { parents: [], constants: [] }; + + if (hasOwn(params, '$extends')) { + parents = toArray(params.$extends); + k = parents.length; + + for (k -= 1; k >= 0; k -= 1) { + current = parents[k]; + + // Add interface constants + for (i = current[$interface].constants.length - 1; i >= 0; i -= 1) { + interf[current[$interface].constants[i]] = current[current[$interface].constants[i]]; + } + + // Add interface to the parents + interf[$interface].parents.push(current); + } + + delete params.$extends; + } + + // Parse constants + if (hasOwn(params, '$constants')) { + for (k in params.$constants) { + interf[k] = params.$constants[k]; + interf[$interface].constants.push(k); + } + } + + // Supply .extend() to easily extend an interface + interf.extend = extend; + + return interf; + } + + /** + * Function to declare an Interface. + * + * @param {Object} obj An object containing the interface members. + * + * @return {Function} The Interface + */ + Interface.declare = createInterface; + + return Interface; +}); + +define('FinalClass',[ + './Class' +], function FinalClassWrapper( + Class +) { + + + + var FinalClass = {}; + + /** + * Create a final class definition. + * + * @param {Object} params An object containing methods and properties + * @param {Constructor} [constructor] Assume the passed constructor + * + * @return {Function} The constructor + */ + function createFinalClass(params, constructor) { + var def = Class.$create(params, constructor); + + return def; + } + + /** + * Function to declare a final class. + * This function can be called with various formats. + * + * @param {Function|Object} arg1 A class to extend or an object/function to obtain the members + * @param {Function|Object} arg2 Object/function to obtain the members + * + * @return {Function} The constructor + */ + FinalClass.declare = function (arg1, arg2, $arg3) { + return Class.declare.call(createFinalClass, arg1, arg2, $arg3); + }; + + return FinalClass; +}); + +define('instanceOf',[ +], function instanceOfWrapper( +) { + + + + var $class = '$class', + $interface = '$interface'; + + /** + * Check if an interface is descendant of another. + * + * @param {Function} interf1 The interface to be checked + * @param {Function} interf2 The interface to be expected as the ancestor + * + * @return {Boolean} True if it's a descendant, false otherwise + */ + function interfaceDescendantOf(interf1, interf2) { + var x, + parents = interf1[$interface].parents; + + for (x = parents.length - 1; x >= 0; x -= 1) { + if (parents[x] === interf2) { + return true; + } + if (interfaceDescendantOf(interf1, parents[x])) { + return true; + } + } + + return false; + } + + /** + * Check if an instance of a class is an instance of an interface. + * + * @param {Object} instance The instance to be checked + * @param {Function} target The interface + * + * @return {Boolean} True if it is, false otherwise + */ + function instanceOfInterface(instance, target) { + var x, + interfaces = instance.$static[$class].interfaces; + + for (x = interfaces.length - 1; x >= 0; x -= 1) { + if (interfaces[x] === target || interfaceDescendantOf(interfaces[x], target)) { + return true; + } + } + + return false; + } + + /** + * Custom instanceOf that also works on interfaces. + * + * @param {Object} instance The instance to be checked + * @param {Function} target The target + * + * @return {Boolean} True if it is a valid instance of target, false otherwise + */ + function instanceOf(instance, target) { + if (instance instanceof target) { + return true; + } + + if (instance && instance.$static && instance.$static[$class] && target && target[$interface]) { + return instanceOfInterface(instance, target); + } + + return false; + } + + return instanceOf; +}); +define('options',[], function () { + + + + return { + }; +}); + +define('dejavu',[ + './Class', + './AbstractClass', + './Interface', + './FinalClass', + './instanceOf', + './options' +], function ( + Class, + AbstractClass, + Interface, + FinalClass, + instanceOf, + options +) { + + + + var dejavu = {}; + + dejavu.Class = Class; + dejavu.AbstractClass = AbstractClass; + dejavu.Interface = Interface; + dejavu.FinalClass = FinalClass; + dejavu.instanceOf = instanceOf; + dejavu.options = options; + + dejavu.mode = 'loose'; + window.dejavu = dejavu; +}); + +require('dejavu', null, null, true); + +}()); \ No newline at end of file diff --git a/src/core/static/js/dejavu/loose/dejavu.min.js b/src/core/static/js/dejavu/loose/dejavu.min.js new file mode 100755 index 0000000..a649a1e --- /dev/null +++ b/src/core/static/js/dejavu/loose/dejavu.min.js @@ -0,0 +1,7 @@ +/** + * almond 0.2.4 Copyright (c) 2011-2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/almond for details + */ + +(function(){var e,t,n;(function(r){function d(e,t){return h.call(e,t)}function v(e,t){var n,r,i,s,o,u,a,f,c,h,p=t&&t.split("/"),d=l.map,v=d&&d["*"]||{};if(e&&e.charAt(0)===".")if(t){p=p.slice(0,p.length-1),e=p.concat(e.split("/"));for(f=0;f<e.length;f+=1){h=e[f];if(h===".")e.splice(f,1),f-=1;else if(h===".."){if(f===1&&(e[2]===".."||e[0]===".."))break;f>0&&(e.splice(f-1,2),f-=2)}}e=e.join("/")}else e.indexOf("./")===0&&(e=e.substring(2));if((p||v)&&d){n=e.split("/");for(f=n.length;f>0;f-=1){r=n.slice(0,f).join("/");if(p)for(c=p.length;c>0;c-=1){i=d[p.slice(0,c).join("/")];if(i){i=i[r];if(i){s=i,o=f;break}}}if(s)break;!u&&v&&v[r]&&(u=v[r],a=f)}!s&&u&&(s=u,o=a),s&&(n.splice(0,o,s),e=n.join("/"))}return e}function m(e,t){return function(){return s.apply(r,p.call(arguments,0).concat([e,t]))}}function g(e){return function(t){return v(t,e)}}function y(e){return function(t){a[e]=t}}function b(e){if(d(f,e)){var t=f[e];delete f[e],c[e]=!0,i.apply(r,t)}if(!d(a,e)&&!d(c,e))throw new Error("No "+e);return a[e]}function w(e){var t,n=e?e.indexOf("!"):-1;return n>-1&&(t=e.substring(0,n),e=e.substring(n+1,e.length)),[t,e]}function E(e){return function(){return l&&l.config&&l.config[e]||{}}}var i,s,o,u,a={},f={},l={},c={},h=Object.prototype.hasOwnProperty,p=[].slice;o=function(e,t){var n,r=w(e),i=r[0];return e=r[1],i&&(i=v(i,t),n=b(i)),i?n&&n.normalize?e=n.normalize(e,g(t)):e=v(e,t):(e=v(e,t),r=w(e),i=r[0],e=r[1],i&&(n=b(i))),{f:i?i+"!"+e:e,n:e,pr:i,p:n}},u={require:function(e){return m(e)},exports:function(e){var t=a[e];return typeof t!="undefined"?t:a[e]={}},module:function(e){return{id:e,uri:"",exports:a[e],config:E(e)}}},i=function(e,t,n,i){var s,l,h,p,v,g=[],w;i=i||e;if(typeof n=="function"){t=!t.length&&n.length?["require","exports","module"]:t;for(v=0;v<t.length;v+=1){p=o(t[v],i),l=p.f;if(l==="require")g[v]=u.require(e);else if(l==="exports")g[v]=u.exports(e),w=!0;else if(l==="module")s=g[v]=u.module(e);else if(d(a,l)||d(f,l)||d(c,l))g[v]=b(l);else{if(!p.p)throw new Error(e+" missing "+l);p.p.load(p.n,m(i,!0),y(l),{}),g[v]=a[l]}}h=n.apply(a[e],g);if(e)if(s&&s.exports!==r&&s.exports!==a[e])a[e]=s.exports;else if(h!==r||!w)a[e]=h}else e&&(a[e]=n)},e=t=s=function(e,t,n,a,f){return typeof e=="string"?u[e]?u[e](t):b(o(e,t).f):(e.splice||(l=e,t.splice?(e=t,t=n,n=null):e=r),t=t||function(){},typeof n=="function"&&(n=a,a=f),a?i(r,e,t,n):setTimeout(function(){i(r,e,t,n)},4),s)},s.config=function(e){return l=e,s},n=function(e,t,n){t.splice||(n=t,t=[]),!d(a,e)&&!d(f,e)&&(f[e]=[e,t,n])},n.amd={jQuery:!0}})(),n("almond",function(){}),n("lib/inspect",[],function(){typeof console=="object"&&!console.inspect&&(console.inspect=typeof navigator!="undefined"&&/msie/i.test(navigator.userAgent)&&!/opera/i.test(navigator.userAgent)?console.dir||console.log:console.log)}),n("lib/printWarning",[],function(){function e(e){typeof console!="undefined"&&console.warn(e)}return e}),n("mout/lang/kindOf",["require","exports","module"],function(e,t,n){function o(e){return e===null?"Null":e===s?"Undefined":r.exec(i.call(e))[1]}var r=/^\[object (.*)\]$/,i=Object.prototype.toString,s;n.exports=o}),n("mout/lang/isKind",["require","exports","module","./kindOf"],function(e,t,n){function i(e,t){return r(e)===t}var r=e("./kindOf");n.exports=i}),n("mout/lang/isFunction",["require","exports","module","./isKind"],function(e,t,n){function i(e){return r(e,"Function")}var r=e("./isKind");n.exports=i}),n("lib/hasDefineProperty",["mout/lang/isFunction"],function(e){function t(){if(!e(Object.defineProperty))return!1;try{Object.defineProperty({},"x",{})}catch(t){return!1}return!0}return t()}),n("lib/obfuscateProperty",["./hasDefineProperty"],function(e){function t(t,n,r,i,s){e?Object.defineProperty(t,n,{value:r,configurable:s||!1,writable:i||!1,enumerable:!1}):t[n]=r}return t}),n("mout/lang/isNumber",["require","exports","module","./isKind"],function(e,t,n){function i(e){return r(e,"Number")}var r=e("./isKind");n.exports=i}),n("mout/lang/isString",["require","exports","module","./isKind"],function(e,t,n){function i(e){return r(e,"String")}var r=e("./isKind");n.exports=i}),n("mout/lang/isBoolean",["require","exports","module","./isKind"],function(e,t,n){function i(e){return r(e,"Boolean")}var r=e("./isKind");n.exports=i}),n("lib/isImmutable",["mout/lang/isNumber","mout/lang/isString","mout/lang/isBoolean"],function(e,t,n){function r(r){return r==null||n(r)||e(r)||t(r)}return r}),n("mout/lang/isObject",["require","exports","module","./isKind"],function(e,t,n){function i(e){return r(e,"Object")}var r=e("./isKind");n.exports=i}),n("mout/lang/isArray",["require","exports","module","./isKind"],function(e,t,n){var r=e("./isKind"),i=Array.isArray||function(e){return r(e,"Array")};n.exports=i}),n("mout/lang/isDate",["require","exports","module","./isKind"],function(e,t,n){function i(e){return r(e,"Date")}var r=e("./isKind");n.exports=i}),n("mout/lang/isRegExp",["require","exports","module","./isKind"],function(e,t,n){function i(e){return r(e,"RegExp")}var r=e("./isKind");n.exports=i}),n("mout/object/hasOwn",["require","exports","module"],function(e,t,n){function r(e,t){return Object.prototype.hasOwnProperty.call(e,t)}n.exports=r}),n("mout/object/forIn",["require","exports","module"],function(e,t,n){function s(){i=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],r=!0;for(var e in{toString:null})r=!1}function o(e,t,n){var o,a=0;r==null&&s();for(o in e)if(u(t,e,o,n)===!1)break;if(r)while(o=i[a++])if(e[o]!==Object.prototype[o]&&u(t,e,o,n)===!1)break}function u(e,t,n,r){return e.call(r,t[n],n,t)}var r,i;n.exports=o}),n("mout/object/forOwn",["require","exports","module","./hasOwn","./forIn"],function(e,t,n){function s(e,t,n){i(e,function(i,s){if(r(e,s))return t.call(n,e[s],s,e)})}var r=e("./hasOwn"),i=e("./forIn");n.exports=s}),n("mout/object/mixIn",["require","exports","module","./forOwn"],function(e,t,n){function i(e,t){var n=0,i=arguments.length,o;while(++n<i)o=arguments[n],o!=null&&r(o,s,e);return e}function s(e,t){this[t]=e}var r=e("./forOwn");n.exports=i}),n("mout/lang/createObject",["require","exports","module","../object/mixIn"],function(e,t,n){function i(e,t){function n(){}return n.prototype=e,r(new n,t)}var r=e("../object/mixIn");n.exports=i}),n("mout/array/indexOf",["require","exports","module"],function(e,t,n){function r(e,t,n){n=n||0;var r=e.length,i=n<0?r+n:n;while(i<r){if(e[i]===t)return i;i+=1}return-1}n.exports=r}),n("mout/array/combine",["require","exports","module","./indexOf"],function(e,t,n){function i(e,t){var n,i=t.length;for(n=0;n<i;n++)r(e,t[n])===-1&&e.push(t[n]);return e}var r=e("./indexOf");n.exports=i}),n("mout/array/contains",["require","exports","module","./indexOf"],function(e,t,n){function i(e,t){return r(e,t)!==-1}var r=e("./indexOf");n.exports=i}),n("mout/lang/isPlainObject",["require","exports","module"],function(e,t,n){function r(e){return!!e&&typeof e=="object"&&e.constructor===Object}n.exports=r}),n("mout/lang/clone",["require","exports","module","./kindOf","./isPlainObject","../object/mixIn"],function(e,t,n){function o(e){switch(r(e)){case"Object":return u(e);case"Array":return l(e);case"RegExp":return a(e);case"Date":return f(e);default:return e}}function u(e){return i(e)?s({},e):e}function a(e){var t="";return t+=e.multiline?"m":"",t+=e.global?"g":"",t+=e.ignorecase?"i":"",new RegExp(e.source,t)}function f(e){return new Date(+e)}function l(e){return e.slice()}var r=e("./kindOf"),i=e("./isPlainObject"),s=e("../object/mixIn");n.exports=o}),n("mout/lang/deepClone",["require","exports","module","./clone","../object/forOwn","./kindOf","./isPlainObject"],function(e,t,n){function u(e,t){switch(s(e)){case"Object":return a(e,t);case"Array":return f(e,t);default:return r(e)}}function a(e,t){if(o(e)){var n={};return i(e,function(e,n){this[n]=u(e,t)},n),n}return t?t(e):e}function f(e,t){var n=[],r=-1,i=e.length,s;while(++r<i)n[r]=u(e[r],t);return n}var r=e("./clone"),i=e("../object/forOwn"),s=e("./kindOf"),o=e("./isPlainObject");n.exports=u}),n("lib/mixIn",[],function(){function e(e,t){var n,r=arguments.length,i,s;for(n=1;n<r;n+=1){s=arguments[n];for(i in arguments[n])e[i]=s[i]}return e}return e}),n("mout/array/append",["require","exports","module"],function(e,t,n){function r(e,t){var n=e.length,r=-1,i=t.length;while(++r<i)e[n+r]=t[r];return e}n.exports=r}),n("mout/function/bind",["require","exports","module"],function(e,t,n){function r(e,t){return Array.prototype.slice.call(e,t||0)}function i(e,t,n){var i=r(arguments,2);return function(){return e.apply(t,i.concat(r(arguments)))}}n.exports=i}),n("mout/lang/toArray",["require","exports","module","./kindOf"],function(e,t,n){function s(e){var t=[],n=r(e),s;if(e!=null)if(e.length==null||n==="String"||n==="Function"||n==="RegExp"||e===i)t[t.length]=e;else{s=e.length;while(s--)t[s]=e[s]}return t}var r=e("./kindOf"),i=this;n.exports=s}),n("mout/array/forEach",["require","exports","module"],function(e,t,n){function r(e,t,n){if(e==null)return;var r=-1,i=e.length;while(++r<i)if(t.call(n,e[r],r,e)===!1)break}n.exports=r}),n("mout/array/filter",["require","exports","module","./forEach"],function(e,t,n){function i(e,t,n){var i=[];return r(e,function(e,r,s){t.call(n,e,r,s)&&i.push(e)}),i}var r=e("./forEach");n.exports=i}),n("mout/array/unique",["require","exports","module","./indexOf","./filter"],function(e,t,n){function s(e){return i(e,o)}function o(e,t,n){return r(n,e,t+1)===-1}var r=e("./indexOf"),i=e("./filter");n.exports=s}),n("mout/array/some",["require","exports","module"],function(e,t,n){function r(e,t,n){var r=!1,i=-1,s=e.length;while(++i<s)if(t.call(n,e[i],i,e)){r=!0;break}return r}n.exports=r}),n("mout/array/difference",["require","exports","module","./unique","./filter","./some","./contains"],function(e,t,n){function u(e){var t=Array.prototype.slice.call(arguments,1),n=i(r(e),function(e){return!s(t,function(t){return o(t,e)})});return n}var r=e("./unique"),i=e("./filter"),s=e("./some"),o=e("./contains");n.exports=u}),n("mout/array/insert",["require","exports","module","./difference","../lang/toArray"],function(e,t,n){function s(e,t){var n=r(i(arguments).slice(1),e);return n.length&&Array.prototype.push.apply(e,n),e.length}var r=e("./difference"),i=e("../lang/toArray");n.exports=s}),n("Class",["./lib/inspect","./lib/printWarning","./lib/obfuscateProperty","./lib/isImmutable","mout/lang/isFunction","mout/lang/isObject","mout/lang/isArray","mout/lang/isDate","mout/lang/isRegExp","mout/lang/createObject","mout/object/hasOwn","mout/array/combine","mout/array/contains","mout/lang/deepClone","./lib/mixIn","mout/array/append","mout/function/bind","mout/lang/toArray","mout/array/insert"],function(t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b){function C(e,t){var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e}function k(e,t,n){if(t[S].efficient)return e;var r,i=!!e[N];i&&(e=e[N]);if(!n){if(!i&&e.toString().indexOf("$self")===-1)return e;r=function(){var n=this.$self,r;return this.$self=t,r=e.apply(this,arguments),this.$self=n,r}}else r=function(){var r=this.$super,i=this.$self,s;return this.$super=n,this.$self=t,s=e.apply(this,arguments),this.$super=r,this.$self=i,s};return r[N]=e,r}function L(e,t){var n,r;for(n in e){if(/^(_){0,2}initialize$/.test(n))continue;r=e[n],c(t.prototype,n)||(s(r)&&!r[S]&&!r[x]?(t.prototype[n]=k(r,t,t.$parent?t.$parent.prototype[n]:null),r[T]&&b(t[S].binds,n)):(t.prototype[n]=r,i(r)||b(t[S].properties,n)))}}function A(e,t){if(c(e,"$borrows")){var n,r,i,u,a=y(e.$borrows),f=a.length;for(f-=1;f>=0;f-=1){n=a[f];if(o(n)){L(n,t);continue}if(s(n)&&!n[S]){L(n.prototype,t);continue}n=n.prototype,L(n,t);for(r=n.$static[S].staticMethods.length-1;r>=0;r-=1)i=n.$static[S].staticMethods[r],b(t[S].staticMethods,i),t[i]=n.$static[i];for(i in n.$static[S].staticProperties)u=n.$static[S].staticProperties[i],t[S].staticProperties[i]=u,t[i]=u;h(t[S].binds,n.$static[S].binds)}delete e.$borrows}}function O(e,t){e=y(e);var n,r=e.length,i;for(r-=1;r>=0;r-=1){n=e[r];if(!p(t[S].interfaces,n)){for(i=n[x].constants.length-1;i>=0;i-=1)t[n[x].constants[i]]=n[n[x].constants[i]],t[S].staticProperties[n[x].constants[i]]=n[n[x].constants[i]];t[S].interfaces.push(n)}}}function M(e,t,n){var r,o,u={};if(c(e,"$statics")){for(r in e.$statics)o=e.$statics[r],s(o)&&!o[S]&&!o[x]?(b(t[S].staticMethods,r),t[r]=k(o,t,t.$parent?t.$parent[r]:null)):(t[S].staticProperties[r]=o,t[r]=o);delete e.$statics}c(e,"$implements")&&(u.$implements=e.$implements,delete e.$implements),c(e,"$abstracts")&&(u.$abstracts=e.$abstracts,delete e.$abstracts);for(r in e)o=e[r],s(o)&&!o[S]&&!o[x]?(t.prototype[r]=k(o,t,t.$parent?t.$parent.prototype[r]:null),o[T]&&(b(t[S].binds,r),delete o[T])):(t.prototype[r]=o,i(o)||b(t[S].properties,r));v(e,u)}function _(e,t){var n,r,i={};delete e.$locked,c(e,"$constants")&&(i.$constants=e.$constants,delete e.$constants),c(e,"$finals")&&(i.$finals=e.$finals,delete e.$finals),M(e,t);if(i.$constants)for(n in i.$constants)r=i.$constants[n],t[S].staticProperties[n]=r,t[n]=r;i.$finals&&M(i.$finals,t,!0)}function D(e,t){var n,r;for(n=e.length-1;n>=0;n-=1)r=t[e[n]],t[e[n]]=g(r,t)}function P(e,t){var n=e||function(){var t,n;n=this.$static[S];for(t=n.properties.length-1;t>=0;t-=1)this[n.properties[t]]=d(this[n.properties[t]]);n.efficient||(this.$super=this.$self=null),n.binds.length&&D(n.binds,this,this),this.initialize.apply(this,arguments)};return n[S]||r(n,S,{staticMethods:[],staticProperties:{},properties:[],interfaces:[],binds:[]}),n}function H(e){return e=e||this,e}function B(e){var t=y(arguments),n;return!e[N]&&this.$static&&this.$static[S]&&(e=k(e,this.$self||this.$static)),t.splice(1,0,this),n=g.apply(e,t),n}function j(e,t){var n,i=t[S].binds,s,o;for(n=i.length-1;n>=0;n-=1)i[n].substr(0,2)!=="__"&&e[S].binds.push(i[n]);m(e[S].properties,t[S].properties),m(e[S].staticMethods,t[S].staticMethods);for(n=t[S].staticMethods.length-1;n>=0;n-=1)t[S].staticMethods[n].substr(0,2)!=="__"&&(e[t[S].staticMethods[n]]=t[t[S].staticMethods[n]]);for(s in t[S].staticProperties)o=t[S].staticProperties[s],s.substr(0,2)!=="__"&&(e[S].staticProperties[s]=o,e[s]=o);r(e,"$parent",t),e[S].interfaces=[].concat(t[S].interfaces)}function F(e){var t=e[S],n,i,s;if(t.efficient){n=e.$canOptimizeConst,delete e.$canOptimizeConst;if(n&&!t.properties.length&&!t.binds.length){if(c(e.prototype,"initialize"))i=e.prototype.initialize;else{s=e.prototype.initialize;switch(s.length){case 0:i=function(){s.call(this)};break;case 1:i=function(e){s.call(this,e)};break;case 2:i=function(e,t){s.call(this,e,t)};break;case 3:i=function(e,t,n){s.call(this,e,t,n)};break;case 4:i=function(e,t,n,r){s.call(this,e,t,n,r)};break;default:i=function(){s.apply(this,arguments)}}}return e.$parent&&(C(i,e),i.$parent=e.$parent),v(i.prototype,e.prototype),v(i,e),r(i,S,e[S]),i}}return e}function I(e,t){return E.declare(this,e,t)}var w,E={},S="$class",x="$interface",T="$bound_dejavu",N="$wrapped_dejavu";w=function(e,t,n){n=n||{};var i,s,o=!!t;return c(e,"$extends")?(s=e.$extends,delete e.$extends,s[S]||(s=w(s.prototype,s,{isVanilla:!0})),e.initialize=n.isVanilla?i:e.initialize||e._initialize||e.__initialize,e.initialize||delete e.initialize,i=P(t),C(i,s),j(i,s)):(i=P(t),e.initialize=n.isVanilla?i:e.initialize||e._initialize||e.__initialize||function(){}),i[S].efficient=o,n.isVanilla||(delete e._initialize,delete e.__initialize),A(e,i),_(e,i),i=F(i),r(i.prototype,"$static",i),r(i,"$static",i),r(i,"$self",null,!0),r(i,"$super",null,!0),r(i,"$member",H),r(i,"$bind",B),i.$parent||(r(i.prototype,"$bind",B),r(i.prototype,"$member",H)),c(e,"$implements")&&(O(e.$implements,i),delete i.prototype.$implements),c(e,"$abstracts")&&delete e.$abstracts,i.extend=I,i},E.declare=function(e,t,n){var r,i=s(this)?this:w,u,a;e&&t&&t!==!0?((u=s(t))||n?(a=P(),a.$canOptimizeConst=!!n,r=u?t(e.prototype,e,a):t):r=t,r.$extends=e):(u=s(e))||t?(a=P(),a.$canOptimizeConst=!!t,r=u?e(a):e):r=e;if(!o(r))throw new Error("Expected class definition to be an object with the class members.");return i(r,a)},r(E,"$create",w);if(!Function.prototype.$bound||!Function.prototype.$bound.dejavu)try{r(Function.prototype,"$bound",function(){return this[T]=!0,this}),Function.prototype.$bound.dejavu=!0}catch(q){n("Could not set Function.prototype.$bound.")}if(!Function.prototype.$bind||!Function.prototype.$bind.dejavu)try{r(Function.prototype,"$bind",function(e){var t=y(arguments);return t.splice(0,1,this),B.apply(e,t)}),Function.prototype.$bind.dejavu=!0}catch(q){n("Could not set Function.prototype.$bind.")}if(!Function.prototype.$member||!Function.prototype.$member.dejavu)try{r(Function.prototype,"$member",function(){return H(this)}),Function.prototype.$member.dejavu=!0}catch(q){n("Could not set Function.prototype.$member.")}return E}),n("AbstractClass",["mout/object/hasOwn","mout/array/insert","./Class"],function(t,n,r){function a(e,u){var a,f,l,c;t(e,"$abstracts")&&(f=e.$abstracts,delete e.$abstracts),a=r.$create(e,u),a[i]=!0;if(f)for(l in f)c=f[l],c[o]&&n(a[s].binds,l);return a}var i="$abstract",s="$class",o="$bound_dejavu",u={};return u.declare=function(e,t,n){return r.declare.call(a,e,t,n)},u}),n("Interface",["mout/lang/isFunction","mout/object/hasOwn","mout/lang/toArray"],function(t,n,r){function o(e){return e.$extends=this,s.declare(e)}function u(e){delete e.$name;var t,s,u,a,f=function(){};f[i]={parents:[],constants:[]};if(n(e,"$extends")){t=r(e.$extends),s=t.length;for(s-=1;s>=0;s-=1){a=t[s];for(u=a[i].constants.length-1;u>=0;u-=1)f[a[i].constants[u]]=a[a[i].constants[u]];f[i].parents.push(a)}delete e.$extends}if(n(e,"$constants"))for(s in e.$constants)f[s]=e.$constants[s],f[i].constants.push(s);return f.extend=o,f}var i="$interface",s={};return s.declare=u,s}),n("FinalClass",["./Class"],function(t){function r(e,n){var r=t.$create(e,n);return r}var n={};return n.declare=function(e,n,i){return t.declare.call(r,e,n,i)},n}),n("instanceOf",[],function(){function r(e,t){var i,s=e[n].parents;for(i=s.length-1;i>=0;i-=1){if(s[i]===t)return!0;if(r(e,s[i]))return!0}return!1}function i(e,n){var i,s=e.$static[t].interfaces;for(i=s.length-1;i>=0;i-=1)if(s[i]===n||r(s[i],n))return!0;return!1}function s(e,r){return e instanceof r?!0:e&&e.$static&&e.$static[t]&&r&&r[n]?i(e,r):!1}var t="$class",n="$interface";return s}),n("options",[],function(){return{}}),n("dejavu",["./Class","./AbstractClass","./Interface","./FinalClass","./instanceOf","./options"],function(e,t,n,r,i,s){var o={};o.Class=e,o.AbstractClass=t,o.Interface=n,o.FinalClass=r,o.instanceOf=i,o.options=s,o.mode="loose",window.dejavu=o}),t("dejavu",null,null,!0)})(); \ No newline at end of file diff --git a/src/core/static/js/dejavu/strict/dejavu.js b/src/core/static/js/dejavu/strict/dejavu.js new file mode 100755 index 0000000..4a7ab3f --- /dev/null +++ b/src/core/static/js/dejavu/strict/dejavu.js @@ -0,0 +1,4822 @@ +(function() { +/** + * almond 0.2.4 Copyright (c) 2011-2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/almond for details + */ +//Going sloppy to avoid 'use strict' string cost, but strict practices should +//be followed. +/*jslint sloppy: true */ +/*global setTimeout: false */ + +var requirejs, require, define; +(function (undef) { + var main, req, makeMap, handlers, + defined = {}, + waiting = {}, + config = {}, + defining = {}, + hasOwn = Object.prototype.hasOwnProperty, + aps = [].slice; + + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); + } + + /** + * Given a relative module name, like ./something, normalize it to + * a real name that can be mapped to a path. + * @param {String} name the relative name + * @param {String} baseName a real name that the name arg is relative + * to. + * @returns {String} normalized name + */ + function normalize(name, baseName) { + var nameParts, nameSegment, mapValue, foundMap, + foundI, foundStarMap, starI, i, j, part, + baseParts = baseName && baseName.split("/"), + map = config.map, + starMap = (map && map['*']) || {}; + + //Adjust any relative paths. + if (name && name.charAt(0) === ".") { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + //Convert baseName to array, and lop off the last part, + //so that . matches that "directory" and not name of the baseName's + //module. For instance, baseName of "one/two/three", maps to + //"one/two/three.js", but we want the directory, "one/two" for + //this normalization. + baseParts = baseParts.slice(0, baseParts.length - 1); + + name = baseParts.concat(name.split("/")); + + //start trimDots + for (i = 0; i < name.length; i += 1) { + part = name[i]; + if (part === ".") { + name.splice(i, 1); + i -= 1; + } else if (part === "..") { + if (i === 1 && (name[2] === '..' || name[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + name.splice(i - 1, 2); + i -= 2; + } + } + } + //end trimDots + + name = name.join("/"); + } else if (name.indexOf('./') === 0) { + // No baseName, so this is ID is resolved relative + // to baseUrl, pull off the leading dot. + name = name.substring(2); + } + } + + //Apply map config if available. + if ((baseParts || starMap) && map) { + nameParts = name.split('/'); + + for (i = nameParts.length; i > 0; i -= 1) { + nameSegment = nameParts.slice(0, i).join("/"); + + if (baseParts) { + //Find the longest baseName segment match in the config. + //So, do joins on the biggest to smallest lengths of baseParts. + for (j = baseParts.length; j > 0; j -= 1) { + mapValue = map[baseParts.slice(0, j).join('/')]; + + //baseName segment has config, find if it has one for + //this name. + if (mapValue) { + mapValue = mapValue[nameSegment]; + if (mapValue) { + //Match, update name to the new value. + foundMap = mapValue; + foundI = i; + break; + } + } + } + } + + if (foundMap) { + break; + } + + //Check for a star map match, but just hold on to it, + //if there is a shorter segment match later in a matching + //config, then favor over this star map. + if (!foundStarMap && starMap && starMap[nameSegment]) { + foundStarMap = starMap[nameSegment]; + starI = i; + } + } + + if (!foundMap && foundStarMap) { + foundMap = foundStarMap; + foundI = starI; + } + + if (foundMap) { + nameParts.splice(0, foundI, foundMap); + name = nameParts.join('/'); + } + } + + return name; + } + + function makeRequire(relName, forceSync) { + return function () { + //A version of a require function that passes a moduleName + //value for items that may need to + //look up paths relative to the moduleName + return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync])); + }; + } + + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(depName) { + return function (value) { + defined[depName] = value; + }; + } + + function callDep(name) { + if (hasProp(waiting, name)) { + var args = waiting[name]; + delete waiting[name]; + defining[name] = true; + main.apply(undef, args); + } + + if (!hasProp(defined, name) && !hasProp(defining, name)) { + throw new Error('No ' + name); + } + return defined[name]; + } + + //Turns a plugin!resource to [plugin, resource] + //with the plugin being undefined if the name + //did not have a plugin prefix. + function splitPrefix(name) { + var prefix, + index = name ? name.indexOf('!') : -1; + if (index > -1) { + prefix = name.substring(0, index); + name = name.substring(index + 1, name.length); + } + return [prefix, name]; + } + + /** + * Makes a name map, normalizing the name, and using a plugin + * for normalization if necessary. Grabs a ref to plugin + * too, as an optimization. + */ + makeMap = function (name, relName) { + var plugin, + parts = splitPrefix(name), + prefix = parts[0]; + + name = parts[1]; + + if (prefix) { + prefix = normalize(prefix, relName); + plugin = callDep(prefix); + } + + //Normalize according + if (prefix) { + if (plugin && plugin.normalize) { + name = plugin.normalize(name, makeNormalize(relName)); + } else { + name = normalize(name, relName); + } + } else { + name = normalize(name, relName); + parts = splitPrefix(name); + prefix = parts[0]; + name = parts[1]; + if (prefix) { + plugin = callDep(prefix); + } + } + + //Using ridiculous property names for space reasons + return { + f: prefix ? prefix + '!' + name : name, //fullName + n: name, + pr: prefix, + p: plugin + }; + }; + + function makeConfig(name) { + return function () { + return (config && config.config && config.config[name]) || {}; + }; + } + + handlers = { + require: function (name) { + return makeRequire(name); + }, + exports: function (name) { + var e = defined[name]; + if (typeof e !== 'undefined') { + return e; + } else { + return (defined[name] = {}); + } + }, + module: function (name) { + return { + id: name, + uri: '', + exports: defined[name], + config: makeConfig(name) + }; + } + }; + + main = function (name, deps, callback, relName) { + var cjsModule, depName, ret, map, i, + args = [], + usingExports; + + //Use name if no relName + relName = relName || name; + + //Call the callback to define the module, if necessary. + if (typeof callback === 'function') { + + //Pull out the defined dependencies and pass the ordered + //values to the callback. + //Default to [require, exports, module] if no deps + deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; + for (i = 0; i < deps.length; i += 1) { + map = makeMap(deps[i], relName); + depName = map.f; + + //Fast path CommonJS standard dependencies. + if (depName === "require") { + args[i] = handlers.require(name); + } else if (depName === "exports") { + //CommonJS module spec 1.1 + args[i] = handlers.exports(name); + usingExports = true; + } else if (depName === "module") { + //CommonJS module spec 1.1 + cjsModule = args[i] = handlers.module(name); + } else if (hasProp(defined, depName) || + hasProp(waiting, depName) || + hasProp(defining, depName)) { + args[i] = callDep(depName); + } else if (map.p) { + map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); + args[i] = defined[depName]; + } else { + throw new Error(name + ' missing ' + depName); + } + } + + ret = callback.apply(defined[name], args); + + if (name) { + //If setting exports via "module" is in play, + //favor that over return value and exports. After that, + //favor a non-undefined return value over exports use. + if (cjsModule && cjsModule.exports !== undef && + cjsModule.exports !== defined[name]) { + defined[name] = cjsModule.exports; + } else if (ret !== undef || !usingExports) { + //Use the return value from the function. + defined[name] = ret; + } + } + } else if (name) { + //May just be an object definition for the module. Only + //worry about defining if have a module name. + defined[name] = callback; + } + }; + + requirejs = require = req = function (deps, callback, relName, forceSync, alt) { + if (typeof deps === "string") { + if (handlers[deps]) { + //callback in this case is really relName + return handlers[deps](callback); + } + //Just return the module wanted. In this scenario, the + //deps arg is the module name, and second arg (if passed) + //is just the relName. + //Normalize module name, if it contains . or .. + return callDep(makeMap(deps, callback).f); + } else if (!deps.splice) { + //deps is a config object, not an array. + config = deps; + if (callback.splice) { + //callback is an array, which means it is a dependency list. + //Adjust args if there are dependencies + deps = callback; + callback = relName; + relName = null; + } else { + deps = undef; + } + } + + //Support require(['a']) + callback = callback || function () {}; + + //If relName is a function, it is an errback handler, + //so remove it. + if (typeof relName === 'function') { + relName = forceSync; + forceSync = alt; + } + + //Simulate async callback; + if (forceSync) { + main(undef, deps, callback, relName); + } else { + //Using a non-zero value because of concern for what old browsers + //do, and latest browsers "upgrade" to 4 if lower value is used: + //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: + //If want a value immediately, use require('id') instead -- something + //that works in almond on the global level, but not guaranteed and + //unlikely to work in other AMD implementations. + setTimeout(function () { + main(undef, deps, callback, relName); + }, 4); + } + + return req; + }; + + /** + * Just drops the config on the floor, but returns req in case + * the config return value is used. + */ + req.config = function (cfg) { + config = cfg; + return req; + }; + + define = function (name, deps, callback) { + + //This module may not have dependencies + if (!deps.splice) { + //deps is not an array, so probably means + //an object literal or factory function for + //the value. Adjust args. + callback = deps; + deps = []; + } + + if (!hasProp(defined, name) && !hasProp(waiting, name)) { + waiting[name] = [name, deps, callback]; + } + }; + + define.amd = { + jQuery: true + }; +}()); + +define("almond", function(){}); + +define('mout/lang/kindOf',['require','exports','module'],function (require, exports, module) { + + var _rKind = /^\[object (.*)\]$/, + _toString = Object.prototype.toString, + UNDEF; + + /** + * Gets the "kind" of value. (e.g. "String", "Number", etc) + */ + function kindOf(val) { + if (val === null) { + return 'Null'; + } else if (val === UNDEF) { + return 'Undefined'; + } else { + return _rKind.exec( _toString.call(val) )[1]; + } + } + module.exports = kindOf; + + +}); + +define('mout/lang/isKind',['require','exports','module','./kindOf'],function (require, exports, module) {var kindOf = require('./kindOf'); + /** + * Check if value is from a specific "kind". + */ + function isKind(val, kind){ + return kindOf(val) === kind; + } + module.exports = isKind; + + +}); + +define('mout/lang/isString',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isString(val) { + return isKind(val, 'String'); + } + module.exports = isString; + + +}); + +define('mout/lang/isBoolean',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isBoolean(val) { + return isKind(val, 'Boolean'); + } + module.exports = isBoolean; + + +}); + +define('mout/array/indexOf',['require','exports','module'],function (require, exports, module) { + + /** + * Array.indexOf + */ + function indexOf(arr, item, fromIndex) { + fromIndex = fromIndex || 0; + var n = arr.length, + i = fromIndex < 0? n + fromIndex : fromIndex; + while (i < n) { + // we iterate over sparse items since there is no way to make it + // work properly on IE 7-8. see #64 + if (arr[i] === item) { + return i; + } + i += 1; + } + return -1; + } + + module.exports = indexOf; + + +}); + +define('mout/array/forEach',['require','exports','module'],function (require, exports, module) { + + /** + * Array forEach + */ + function forEach(arr, callback, thisObj) { + if (arr == null) { + return; + } + var i = -1, + n = arr.length; + while (++i < n) { + // we iterate over sparse items since there is no way to make it + // work properly on IE 7-8. see #64 + if ( callback.call(thisObj, arr[i], i, arr) === false ) { + break; + } + } + } + + module.exports = forEach; + + + +}); + +define('mout/array/filter',['require','exports','module','./forEach'],function (require, exports, module) {var forEach = require('./forEach'); + + /** + * Array filter + */ + function filter(arr, callback, thisObj) { + var results = []; + forEach(arr, function (val, i, arr) { + if ( callback.call(thisObj, val, i, arr) ) { + results.push(val); + } + }); + return results; + } + + module.exports = filter; + + + +}); + +define('mout/array/unique',['require','exports','module','./indexOf','./filter'],function (require, exports, module) {var indexOf = require('./indexOf'); +var filter = require('./filter'); + + /** + * @return {array} Array of unique items + */ + function unique(arr){ + return filter(arr, isUnique); + } + + function isUnique(item, i, arr){ + return indexOf(arr, item, i+1) === -1; + } + + module.exports = unique; + + + +}); + +define('mout/array/every',['require','exports','module'],function (require, exports, module) { + + /** + * Array every + */ + function every(arr, callback, thisObj) { + var result = true, + i = -1, + n = arr.length; + while (++i < n) { + // we iterate over sparse items since there is no way to make it + // work properly on IE 7-8. see #64 + if (!callback.call(thisObj, arr[i], i, arr) ) { + result = false; + break; + } + } + return result; + } + + module.exports = every; + + +}); + +define('mout/array/contains',['require','exports','module','./indexOf'],function (require, exports, module) {var indexOf = require('./indexOf'); + + /** + * If array contains values. + */ + function contains(arr, val) { + return indexOf(arr, val) !== -1; + } + module.exports = contains; + + +}); + +define('mout/array/intersection',['require','exports','module','./unique','./filter','./every','./contains'],function (require, exports, module) {var unique = require('./unique'); +var filter = require('./filter'); +var every = require('./every'); +var contains = require('./contains'); + + + /** + * Return a new Array with elements common to all Arrays. + * - based on underscore.js implementation + */ + function intersection(arr) { + var arrs = Array.prototype.slice.call(arguments, 1), + result = filter(unique(arr), function(needle){ + return every(arrs, function(haystack){ + return contains(haystack, needle); + }); + }); + return result; + } + + module.exports = intersection; + + + +}); + +define('mout/array/compact',['require','exports','module','./filter'],function (require, exports, module) {var filter = require('./filter'); + + /** + * Remove all null/undefined items from array. + */ + function compact(arr) { + return filter(arr, function(val){ + return (val != null); + }); + } + + module.exports = compact; + + +}); + +define('mout/array/remove',['require','exports','module','./indexOf'],function (require, exports, module) {var indexOf = require('./indexOf'); + + /** + * Remove a single item from the array. + * (it won't remove duplicates, just a single item) + */ + function remove(arr, item){ + var idx = indexOf(arr, item); + if (idx !== -1) arr.splice(idx, 1); + } + + module.exports = remove; + + +}); + +define('mout/object/hasOwn',['require','exports','module'],function (require, exports, module) { + + /** + * Safer Object.hasOwnProperty + */ + function hasOwn(obj, prop){ + return Object.prototype.hasOwnProperty.call(obj, prop); + } + + module.exports = hasOwn; + + + +}); + +define('mout/object/forIn',['require','exports','module'],function (require, exports, module) { + + var _hasDontEnumBug, + _dontEnums; + + function checkDontEnum(){ + _dontEnums = [ + 'toString', + 'toLocaleString', + 'valueOf', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'constructor' + ]; + + _hasDontEnumBug = true; + + for (var key in {'toString': null}) { + _hasDontEnumBug = false; + } + } + + /** + * Similar to Array/forEach but works over object properties and fixes Don't + * Enum bug on IE. + * based on: http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation + */ + function forIn(obj, fn, thisObj){ + var key, i = 0; + // no need to check if argument is a real object that way we can use + // it for arrays, functions, date, etc. + + //post-pone check till needed + if (_hasDontEnumBug == null) checkDontEnum(); + + for (key in obj) { + if (exec(fn, obj, key, thisObj) === false) { + break; + } + } + + if (_hasDontEnumBug) { + while (key = _dontEnums[i++]) { + // since we aren't using hasOwn check we need to make sure the + // property was overwritten + if (obj[key] !== Object.prototype[key]) { + if (exec(fn, obj, key, thisObj) === false) { + break; + } + } + } + } + } + + function exec(fn, obj, key, thisObj){ + return fn.call(thisObj, obj[key], key, obj); + } + + module.exports = forIn; + + + +}); + +define('mout/object/forOwn',['require','exports','module','./hasOwn','./forIn'],function (require, exports, module) {var hasOwn = require('./hasOwn'); +var forIn = require('./forIn'); + + /** + * Similar to Array/forEach but works over object properties and fixes Don't + * Enum bug on IE. + * based on: http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation + */ + function forOwn(obj, fn, thisObj){ + forIn(obj, function(val, key){ + if (hasOwn(obj, key)) { + return fn.call(thisObj, obj[key], key, obj); + } + }); + } + + module.exports = forOwn; + + + +}); + +define('mout/object/keys',['require','exports','module','./forOwn'],function (require, exports, module) {var forOwn = require('./forOwn'); + + /** + * Get object keys + */ + var keys = Object.keys || function (obj) { + var keys = []; + forOwn(obj, function(val, key){ + keys.push(key); + }); + return keys; + }; + + module.exports = keys; + + + +}); + +define('mout/object/size',['require','exports','module','./forOwn'],function (require, exports, module) {var forOwn = require('./forOwn'); + + /** + * Get object size + */ + function size(obj) { + var count = 0; + forOwn(obj, function(){ + count++; + }); + return count; + } + + module.exports = size; + + + +}); + +/*jshint regexp:false*/ + +define('lib/functionMeta',[], function () { + + 'use strict'; + + /** + * Extract meta data from a function. + * It returns an object containing the number of normal arguments, the number + * of optional arguments, the function signature, the function name and the visibility. + * + * Will return null if the function arguments are invalid. + * + * @param {Function} func The function + * @param {String} name The name of the function + * + * @return {Object|null} An object containg the function metadata + */ + function functionMeta(func, name) { + var matches = /^function(\s+[a-zA-Z0-9_\$]*)*\s*\(([^\(]*)\)/m.exec(func.toString()), + ret, + split, + optionalReached = false, + length, + x; + + // Analyze arguments + if (!matches) { + return null; + } + + split = (matches[2] || '').split(/\s*,\s*/gm); + length = split.length; + + ret = { mandatory: 0, optional: 0, signature: '' }; + + if (split[0] !== '') { + for (x = 0; x < length; x += 1) { + if (split[x].charAt(0) === '$') { + ret.optional += 1; + ret.signature += ' ' + split[x] + ', '; + optionalReached = true; + } else if (!optionalReached) { + ret.mandatory += 1; + ret.signature += split[x] + ', '; + } else { + return null; + } + } + + ret.signature = ret.signature.substr(0, ret.signature.length - 2); + } + + // Analyze visibility + if (name) { + if (name.charAt(0) === '_') { + if (name.charAt(1) === '_') { + ret.isPrivate = true; + } else { + ret.isProtected = true; + } + } else { + ret.isPublic = true; + } + } + + return ret; + } + + return functionMeta; +}); + +define('mout/lang/isNumber',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isNumber(val) { + return isKind(val, 'Number'); + } + module.exports = isNumber; + + +}); + +define('lib/isImmutable',[ + 'mout/lang/isNumber', + 'mout/lang/isString', + 'mout/lang/isBoolean' +], function ( + isNumber, + isString, + isBoolean +) { + + 'use strict'; + + /** + * Checks if a value is immutable. + * + * @param {Mixed} value The value + * + * @return {Boolean} True if it is, false otherwise + */ + function isImmutable(value) { + return value == null || isBoolean(value) || isNumber(value) || isString(value); + } + + return isImmutable; +}); + +define('lib/propertyMeta',['./isImmutable'], function (isImmutable) { + + 'use strict'; + + /** + * Extract meta data from a property. + * + * @param {Mixed} prop The property + * @param {String} name The name of the property + * + * @return {Object} An object containg the metadata + */ + function propertyMeta(prop, name) { + var ret = {}; + + // Is it undefined? + if (prop === undefined) { + return null; + } + + // Analyze visibility + if (name) { + if (name.charAt(0) === '_') { + if (name.charAt(1) === '_') { + ret.isPrivate = true; + } else { + ret.isProtected = true; + } + } else { + ret.isPublic = true; + } + } + + ret.isImmutable = isImmutable(prop); + ret.value = prop; + + return ret; + } + + return propertyMeta; +}); + +define('lib/isFunctionCompatible',[], function () { + + 'use strict'; + + /** + * Check if a function signature is compatible with another. + * + * @param {Function} func1 The function to be checked + * @param {Function} func2 The function to be compared with + * + * @return {Boolean} True if it's compatible, false otherwise + */ + function isFunctionCompatible(func1, func2) { + return func1.mandatory === func2.mandatory && func1.optional >= func2.optional; + } + + return isFunctionCompatible; +}); + +define('mout/array/append',['require','exports','module'],function (require, exports, module) { + + /** + * Appends an array to the end of another. + * The first array will be modified. + */ + function append(arr1, arr2) { + var pad = arr1.length, + i = -1, + n = arr2.length; + while (++i < n) { + arr1[pad + i] = arr2[i]; + } + return arr1; + } + module.exports = append; + + +}); + +define('lib/checkKeywords',[ + 'mout/object/hasOwn', + 'mout/array/append' +], function ( + hasOwn, + append +) { + + 'use strict'; + + var reservedNormal = ['$constructor', '$initializing', '$static', '$self', '$super', '$underStrict'], + reservedAll = append(['initialize'], reservedNormal), + reservedStatics = ['$parent', '$super', '$self', '$static', 'extend']; + + /** + * Verify reserved words found in classes/interfaces. + * The second parameter can be normal or statics. + * Normal will test for reserved words of the instance. + * $statics will test for reserved words in the ckass statics. + * + * Will throw an error if any reserved key is found. + * + * @param {Object} object The object to verify + * @param {String} [type] The list of reserved word to test (defaults to all) + */ + function checkKeywords(object, type) { + var reserved = type === 'normal' || !type ? reservedNormal : (type === 'all' ? reservedAll : reservedStatics), + x; + + for (x = reserved.length - 1; x >= 0; x -= 1) { + if (hasOwn(object, reserved[x])) { + throw new Error('"' + object.$name + '" is using a reserved keyword: ' + reserved[x]); + } + } + } + + return checkKeywords; +}); + +define('mout/array/some',['require','exports','module'],function (require, exports, module) { + + /** + * Array some + */ + function some(arr, callback, thisObj) { + var result = false, + i = -1, + n = arr.length; + while (++i < n) { + // we iterate over sparse items since there is no way to make it + // work properly on IE 7-8. see #64 + if ( callback.call(thisObj, arr[i], i, arr) ) { + result = true; + break; + } + } + return result; + } + + module.exports = some; + + +}); + +define('mout/array/difference',['require','exports','module','./unique','./filter','./some','./contains'],function (require, exports, module) {var unique = require('./unique'); +var filter = require('./filter'); +var some = require('./some'); +var contains = require('./contains'); + + + /** + * Return a new Array with elements that aren't present in the other Arrays. + */ + function difference(arr) { + var arrs = Array.prototype.slice.call(arguments, 1), + result = filter(unique(arr), function(needle){ + return !some(arrs, function(haystack){ + return contains(haystack, needle); + }); + }); + return result; + } + + module.exports = difference; + + + +}); + +define('lib/testKeywords',[ + 'mout/array/difference', + 'mout/object/hasOwn' +], function ( + difference, + hasOwn +) { + + 'use strict'; + + var keywords = [ + '$name', '$extends', '$implements', '$borrows', + '$statics', '$finals', '$abstracts', '$constants' + ]; + + /** + * Tests if an object contains an unallowed keyword in a given context. + * + * @param {String} object The object to verify + * @param {Array} [allowed The list of allowed keywords (defaults to []) + * + * @return {Mixed} False if is ok, or the key that is unallowed. + */ + function testKeywords(object, allowed) { + var test = allowed ? difference(keywords, allowed) : keywords, + x; + + for (x = test.length - 1; x >= 0; x -= 1) { + if (hasOwn(object, test[x])) { + return test[x]; + } + } + + return false; + } + + return testKeywords; +}); + +define('mout/lang/isFunction',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isFunction(val) { + return isKind(val, 'Function'); + } + module.exports = isFunction; + + +}); + +define('lib/hasDefineProperty',['mout/lang/isFunction'], function (isFunction) { + + 'use strict'; + + /** + * Check if the environment supports Object.hasDefineProperty. + * There is some quirks related to IE that is handled inside. + * + * @return {Boolean} True if it supports, false otherwise + */ + function hasDefineProperty() { + if (!isFunction(Object.defineProperty)) { + return false; + } + + // Avoid IE8 bug + try { + Object.defineProperty({}, 'x', {}); + } catch (e) { + return false; + } + + return true; + } + + return hasDefineProperty(); +}); +define('lib/isObjectPrototypeSpoiled',[], function () { + + 'use strict'; + + /** + * Checks if object prototype has non enumerable properties attached. + * + * @return {Boolean} True if it is, false otherwise + */ + function isObjectPrototypeSpoiled() { + var obj = {}, + key; + + for (key in obj) { + if (key) { // This is just to trick jslint.. + return true; + } + } + + return false; + } + + return isObjectPrototypeSpoiled; +}); + +define('lib/checkObjectPrototype',[ + './isObjectPrototypeSpoiled', + 'mout/lang/isFunction' +], function ( + isObjectPrototypeSpoiled, + isFunction +) { + + 'use strict'; + + /** + * Checks object prototype, throwing an error if it has enumerable properties. + * Also seals it, preventing any additions or deletions. + */ + function checkObjectPrototype() { + if (isObjectPrototypeSpoiled()) { + throw new Error('dejavu will not work properly if Object.prototype has enumerable properties!'); + } + + // TODO: should we really do this? the user could legitimately adding non enumerable properties.. + if (isFunction(Object.seal) && !Object.isSealed(Object.prototype)) { + Object.seal(Object.prototype); + } + } + + return checkObjectPrototype; +}); + +/*global process*/ + +define('lib/randomAccessor',['mout/array/contains'], function (contains) { + + 'use strict'; + + var random, + allowed = ['ClassWrapper', 'InterfaceWrapper', 'AbstractClassWrapper', 'FinalClassWrapper', 'instanceOfWrapper', 'inspectWrapper'], + nrAllowed = allowed.length, + nrAccesses = 0; + + if (!(typeof window !== 'undefined' && window.navigator && window.document)) { + random = process.pid; + } else { + random = new Date().getTime() + '_' + Math.floor((Math.random() * 100000000 + 1)); + } + + /** + * Provides access to a random string that allows acceess to some hidden properties + * used through this library. + * + * @param {Function} caller The function that is trying to access + * + * @return {String} The random string + */ + function randomAccessor(caller) { + if (nrAccesses > nrAllowed || !contains(allowed, caller)) { + throw new Error('Can\'t access random identifier.'); + } + + nrAccesses += 1; + + return random; + } + + return randomAccessor; +}); + +define('lib/hasFreezeBug',['mout/lang/isFunction'], function (isFunction) { + + 'use strict'; + + /** + * Checks if the browser has Object.freeze bug. + * + * @see https://bugzilla.mozilla.org/show_bug.cgi?id=744494 + * + * @return {Boolean} True if it has, false otherwise + */ + function checkHasFreezeBug() { + if (!isFunction(Object.freeze)) { + return false; + } + + // Create a constructor + var A = function () {}, + a; + + A.prototype.foo = ''; + Object.freeze(A.prototype); // Freeze prototype + + // Create an instance + a = new A(); + + try { + a.foo = 'baz'; // Throws a['foo'] is read only + if (a.foo !== 'baz') { // Or fails silently in at least IE9 + return true; + } + } catch (e) { + return true; + } + + return false; + } + + return checkHasFreezeBug(); +}); + +define('options',[], function () { + + 'use strict'; + + return { + locked: true + }; +}); + +define('mout/object/mixIn',['require','exports','module','./forOwn'],function (require, exports, module) {var forOwn = require('./forOwn'); + + /** + * Combine properties from all the objects into first one. + * - This method affects target object in place, if you want to create a new Object pass an empty object as first param. + * @param {object} target Target Object + * @param {...object} objects Objects to be combined (0...n objects). + * @return {object} Target Object. + */ + function mixIn(target, objects){ + var i = 0, + n = arguments.length, + obj; + while(++i < n){ + obj = arguments[i]; + if (obj != null) { + forOwn(obj, copyProp, target); + } + } + return target; + } + + function copyProp(val, key){ + this[key] = val; + } + + module.exports = mixIn; + + +}); + +define('mout/lang/createObject',['require','exports','module','../object/mixIn'],function (require, exports, module) {var mixIn = require('../object/mixIn'); + + /** + * Create Object using prototypal inheritance and setting custom properties. + * - Mix between Douglas Crockford Prototypal Inheritance <http://javascript.crockford.com/prototypal.html> and the EcmaScript 5 `Object.create()` method. + * @param {object} parent Parent Object. + * @param {object} [props] Object properties. + * @return {object} Created object. + */ + function createObject(parent, props){ + function F(){} + F.prototype = parent; + return mixIn(new F(), props); + + } + module.exports = createObject; + + + +}); + +define('mout/lang/isObject',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isObject(val) { + return isKind(val, 'Object'); + } + module.exports = isObject; + + +}); + +define('mout/lang/isArray',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + var isArray = Array.isArray || function (val) { + return isKind(val, 'Array'); + }; + module.exports = isArray; + + +}); + +define('lib/inspect',[ + './randomAccessor', + './hasDefineProperty', + 'mout/lang/createObject', + 'mout/lang/isObject', + 'mout/lang/isArray', + 'mout/lang/isFunction', + 'mout/object/hasOwn' +], function ( + randomAccessor, + hasDefineProperty, + createObject, + isObject, + isArray, + isFunction, + hasOwn +) { + + 'use strict'; + + var random = randomAccessor('inspectWrapper'), + $class = '$class_' + random, + $wrapped = '$wrapped_' + random, + cacheKeyword = '$cache_' + random, + redefinedCacheKeyword = '$redefined_cache_' + random, + prev, + tmp; + + // Function prototype bind shim + // Can't use mout bind because of IE's + if (!Function.prototype.bind) { + Function.prototype.bind = function (context) { + var fn = this, args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply(context, Array.prototype.concat.apply(args, arguments)); + }; + }; + } + + /** + * Fetches an already inspected target from the cache. + * Returns null if not in the cache. + * + * @param {Object|Function} target The instance or constructor. + * @param {Array} cache The cache + * + * @return {Object|Function} The inspected target + */ + function fetchCache(target, cache) { + var x, + length = cache.length, + curr; + + for (x = 0; x < length; x += 1) { + curr = cache[x]; + if (curr.target === target) { + return curr.inspect; + } + } + + return null; + } + + /** + * Inspects an instance. + * + * @param {Object} target The instance + * @param {Array} cache The cache + * + * @return {Object} The inspected instance + */ + function inspectInstance(target, cache) { + // If browser has no define property it means it is too old and + // in that case we return the target itself. + // This could be improved but I think it does not worth the trouble + if (!hasDefineProperty) { + return target; + } + + var cached = fetchCache(target, cache), + def, + simpleConstructor, + methodsCache, + propertiesCache, + obj, + tmp, + key; + + if (cached) { + return cached; + } + + def = target.$static[$class]; + simpleConstructor = def.simpleConstructor; + methodsCache = target[cacheKeyword].methods; + propertiesCache = target[cacheKeyword].properties; + + obj = createObject(simpleConstructor.prototype); + cache.push({ target: target, inspect: obj }); + + // Methods + for (key in target[redefinedCacheKeyword].methods) { + obj[key] = inspect(methodsCache[key], cache, true); + } + + // Properties + for (key in target[redefinedCacheKeyword].properties) { + tmp = hasOwn(propertiesCache, key) ? propertiesCache[key] : target[key]; + obj[key] = inspect(tmp, cache, true); + } + + // Handle undeclared properties + methodsCache = def.methods; + propertiesCache = def.properties; + for (key in target) { + if (hasOwn(target, key) && !hasOwn(obj, key) && !propertiesCache[key] && !methodsCache[key]) { + obj[key] = inspect(target[key], cache, true); + } + } + + // Fix the .constructor + tmp = obj.constructor.$constructor; + while (tmp) { + inspectConstructor(tmp, cache, true); + tmp = tmp.$parent; + } + + return obj; + } + + /** + * Inspects an constructor. + * + * @param {Function} target The constructor + * + * @return {Object} The inspected constructor + */ + function inspectConstructor(target, cache) { + // If browser has no define property it means it is too old and + // in that case we return the target itself. + // This could be improved but I think it does not worth the trouble + if (!hasDefineProperty) { + return target; + } + + var cached = fetchCache(target, cache), + def, + methodsCache, + propertiesCache, + membersCache, + obj, + tmp, + key; + + if (cached) { + return cached; + } + + def = target[$class]; + obj = def.simpleConstructor; + methodsCache = target[cacheKeyword].methods; + propertiesCache = target[cacheKeyword].properties; + + cache.push({ target: target, inspect: obj }); + + // Constructor methods + for (key in methodsCache) { + obj[key] = inspect(methodsCache[key], cache, true); + } + + // Constructor properties + for (key in propertiesCache) { + tmp = propertiesCache[key]; + obj[key] = inspect(tmp, cache, true); + } + + // Handle constructor undeclared properties + methodsCache = def.methods; + propertiesCache = def.properties; + for (key in target) { + if (hasOwn(target, key) && !hasOwn(obj, key) && !propertiesCache[key] && !methodsCache[key]) { + obj[key] = inspect(target[key], cache, true); + } + } + + obj = obj.prototype; + + // Prototype members + target = target.prototype; + membersCache = def.ownMembers; + methodsCache = def.methods; + propertiesCache = def.properties; + + for (key in membersCache) { + tmp = methodsCache[key] ? methodsCache[key].implementation : propertiesCache[key].value; + obj[key] = inspect(tmp, cache, true); + } + + // Handle undeclared prototype members + for (key in target) { + if (hasOwn(target, key) && !hasOwn(obj, key) && !membersCache[key]) { + obj[key] = inspect(target[key], cache, true); + } + } + + return obj; + } + + /** + * Inspects a property, recursively finding for instances/constructors. + * + * @param {Object} prop The property + * @param {Array} cache The cache + * @param {Boolean} clone True to clone findings, false otherwise + * + * @return {Object} The inspected property + */ + function inspect(prop, cache, clone) { + var key, + x, + length, + ret; + + cache = cache || []; + + if (isObject(prop)) { + if (prop.$static) { + return inspectInstance(prop, cache); + } + + ret = clone ? {} : prop; + for (key in prop) { + ret[key] = inspect(prop[key], cache, clone); + } + + return ret; + } + + if (isArray(prop)) { + length = prop.length; + ret = clone ? [] : prop; + for (x = 0; x < length; x += 1) { + ret[x] = inspect(prop[x], cache, clone); + } + + return ret; + } + + if (isFunction(prop)) { + if (prop[$class]) { + return inspectInstance(prop, cache); + } + + return prop[$wrapped] || prop; + } + + return prop; + } + + // Add inspect method to the console + if (typeof console === 'object' && (!console.inspect || !console.inspect.dejavu)) { + tmp = typeof navigator !== 'undefined' && /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent); + prev = console.inspect || (tmp ? console.dir || console.log : console.log); // console.dir is better in IE + + // Fix for IE.. + if (typeof prev === 'object') { + prev = Function.prototype.call.bind(prev, console); + } + + console.inspect = function () { + var args = [], + length = arguments.length, + x; + + for (x = 0; x < length; x += 1) { + args[x] = inspect(arguments[x]); + } + + return prev.apply(console, args); + }; + console.inspect.dejavu = true; + } +}); +define('lib/printWarning',[], function () { + + 'use strict'; + + /** + * Simple function to print warning in the console only if the console is available. + * + * @param {String} message The message to print + */ + function printWarning(message) { + if (typeof console !== 'undefined') { + console.warn(message); + } + } + + return printWarning; +}); + +define('lib/obfuscateProperty',['./hasDefineProperty'], function (hasDefineProperty) { + + 'use strict'; + + /** + * Sets the key of object with the specified value. + * The property is obfuscated, by not being enumerable, configurable and writable. + * + * @param {Object} obj The object + * @param {String} key The key + * @param {Mixed} value The value + * @param {Boolean} [isWritable] True to be writable, false otherwise (defaults to false) + * @param {Boolean} [isDeletable] True to be deletable, false otherwise (defaults to false) + */ + function obfuscateProperty(obj, key, value, isWritable, isDeletable) { + if (hasDefineProperty) { + Object.defineProperty(obj, key, { + value: value, + configurable: isDeletable || false, + writable: isWritable || false, + enumerable: false + }); + } else { + obj[key] = value; + } + } + + return obfuscateProperty; +}); + +define('mout/lang/isDate',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isDate(val) { + return isKind(val, 'Date'); + } + module.exports = isDate; + + +}); + +define('mout/lang/isRegExp',['require','exports','module','./isKind'],function (require, exports, module) {var isKind = require('./isKind'); + /** + */ + function isRegExp(val) { + return isKind(val, 'RegExp'); + } + module.exports = isRegExp; + + +}); + +define('mout/array/combine',['require','exports','module','./indexOf'],function (require, exports, module) {var indexOf = require('./indexOf'); + + /** + * Combines an array with all the items of another. + * Does not allow duplicates and is case and type sensitive. + */ + function combine(arr1, arr2) { + + var x, length = arr2.length; + + for (x = 0; x < length; x++) { + if (indexOf(arr1, arr2[x]) === -1) { + arr1.push(arr2[x]); + } + } + + return arr1; + } + module.exports = combine; + + +}); + +define('mout/lang/isPlainObject',['require','exports','module'],function (require, exports, module) { + + /** + * Checks if the value is created by the `Object` constructor. + */ + function isPlainObject(value) { + return (!!value + && typeof value === 'object' + && value.constructor === Object); + } + + module.exports = isPlainObject; + + + +}); + +define('mout/lang/clone',['require','exports','module','./kindOf','./isPlainObject','../object/mixIn'],function (require, exports, module) {var kindOf = require('./kindOf'); +var isPlainObject = require('./isPlainObject'); +var mixIn = require('../object/mixIn'); + + /** + * Clone native types. + */ + function clone(val){ + switch (kindOf(val)) { + case 'Object': + return cloneObject(val); + case 'Array': + return cloneArray(val); + case 'RegExp': + return cloneRegExp(val); + case 'Date': + return cloneDate(val); + default: + return val; + } + } + + function cloneObject(source) { + if (isPlainObject(source)) { + return mixIn({}, source); + } else { + return source; + } + } + + function cloneRegExp(r) { + var flags = ''; + flags += r.multiline ? 'm' : ''; + flags += r.global ? 'g' : ''; + flags += r.ignorecase ? 'i' : ''; + return new RegExp(r.source, flags); + } + + function cloneDate(date) { + return new Date(+date); + } + + function cloneArray(arr) { + return arr.slice(); + } + + module.exports = clone; + + + +}); + +define('mout/lang/deepClone',['require','exports','module','./clone','../object/forOwn','./kindOf','./isPlainObject'],function (require, exports, module) {var clone = require('./clone'); +var forOwn = require('../object/forOwn'); +var kindOf = require('./kindOf'); +var isPlainObject = require('./isPlainObject'); + + /** + * Recursively clone native types. + */ + function deepClone(val, instanceClone) { + switch ( kindOf(val) ) { + case 'Object': + return cloneObject(val, instanceClone); + case 'Array': + return cloneArray(val, instanceClone); + default: + return clone(val); + } + } + + function cloneObject(source, instanceClone) { + if (isPlainObject(source)) { + var out = {}; + forOwn(source, function(val, key) { + this[key] = deepClone(val, instanceClone); + }, out); + return out; + } else if (instanceClone) { + return instanceClone(source); + } else { + return source; + } + } + + function cloneArray(arr, instanceClone) { + var out = [], + i = -1, + n = arr.length, + val; + while (++i < n) { + out[i] = deepClone(arr[i], instanceClone); + } + return out; + } + + module.exports = deepClone; + + + + +}); + +define('lib/mixIn',[], function () { + + 'use strict'; + + /** + * This method does exactly the same as the mout counterpart but + * does not perform hasOwn for each key in the objects. + * This is only done because the object prototype is guaranteed to be sealed. + * There is other ones that could be also optimized, but this is the most used + * one in the loose version. + * + * @param {object} target Target Object + * @param {...object} objects Objects to be combined (0...n objects) + * + * @return {object} Target Object + */ + function mixIn(target, objects) { + var x, + length = arguments.length, + key, + curr; + + for (x = 1; x < length; x += 1) { + curr = arguments[x]; + for (key in arguments[x]) { + target[key] = curr[key]; + } + } + + return target; + } + + return mixIn; +}); + +define('mout/function/bind',['require','exports','module'],function (require, exports, module) { + + function slice(arr, offset){ + return Array.prototype.slice.call(arr, offset || 0); + } + + /** + * Return a function that will execute in the given context, optionally adding any additional supplied parameters to the beginning of the arguments collection. + * @param {Function} fn Function. + * @param {object} context Execution context. + * @param {rest} args Arguments (0...n arguments). + * @return {Function} Wrapped Function. + */ + function bind(fn, context, args){ + var argsArr = slice(arguments, 2); //curried args + return function(){ + return fn.apply(context, argsArr.concat(slice(arguments))); + }; + } + + module.exports = bind; + + + +}); + +define('mout/lang/toArray',['require','exports','module','./kindOf'],function (require, exports, module) {var kindOf = require('./kindOf'); + + var _win = this; + + /** + * Convert array-like object into array + */ + function toArray(val){ + var ret = [], + kind = kindOf(val), + n; + + if (val != null) { + if ( val.length == null || kind === 'String' || kind === 'Function' || kind === 'RegExp' || val === _win ) { + //string, regexp, function have .length but user probably just want + //to wrap value into an array.. + ret[ret.length] = val; + } else { + //window returns true on isObject in IE7 and may have length + //property. `typeof NodeList` returns `function` on Safari so + //we can't use it (#58) + n = val.length; + while (n--) { + ret[n] = val[n]; + } + } + } + return ret; + } + module.exports = toArray; + + +}); + +define('mout/array/insert',['require','exports','module','./difference','../lang/toArray'],function (require, exports, module) {var difference = require('./difference'); +var toArray = require('../lang/toArray'); + + /** + * Insert item into array if not already present. + */ + function insert(arr, rest_items) { + var diff = difference(toArray(arguments).slice(1), arr); + if (diff.length) { + Array.prototype.push.apply(arr, diff); + } + return arr.length; + } + module.exports = insert; + + +}); + +define('Class',[ + 'mout/lang/isString', + 'mout/lang/isBoolean', + 'mout/array/intersection', + 'mout/array/unique', + 'mout/array/compact', + 'mout/array/remove', + 'mout/object/keys', + 'mout/object/size', + './lib/functionMeta', + './lib/propertyMeta', + './lib/isFunctionCompatible', + './lib/checkKeywords', + './lib/testKeywords', + './lib/hasDefineProperty', + './lib/checkObjectPrototype', + './lib/randomAccessor', + './lib/hasFreezeBug', + './options', + './lib/inspect', + './lib/printWarning', + './lib/obfuscateProperty', + './lib/isImmutable', + 'mout/lang/isFunction', + 'mout/lang/isObject', + 'mout/lang/isArray', + 'mout/lang/isDate', + 'mout/lang/isRegExp', + 'mout/lang/createObject', + 'mout/object/hasOwn', + 'mout/array/combine', + 'mout/array/contains', + 'mout/lang/deepClone', + './lib/mixIn', + 'mout/function/bind', + 'mout/lang/toArray', + 'mout/array/insert' +], function ClassWrapper( + isString, + isBoolean, + intersection, + unique, + compact, + remove, + keys, + size, + functionMeta, + propertyMeta, + isFunctionCompatible, + checkKeywords, + testKeywords, + hasDefineProperty, + checkObjectPrototype, + randomAccessor, + hasFreezeBug, + options, + inspect, + printWarning, + obfuscateProperty, + isImmutable, + isFunction, + isObject, + isArray, + isDate, + isRegExp, + createObject, + hasOwn, + combine, + contains, + deepClone, + mixIn, + bind, + toArray, + insert +) { + + 'use strict'; + + checkObjectPrototype(); + + var createClass, + Class = {}, + random = randomAccessor('ClassWrapper'), + $class = '$class_' + random, + $interface = '$interface_' + random, + $abstract = '$abstract_' + random, + $bound = '$bound_' + random, + $name = '$name_' + random, + $anonymous = '$anonymous_' + random, + $wrapped = '$wrapped_' + random, + cacheKeyword = '$cache_' + random, + redefinedCacheKeyword = '$redefined_cache_' + random, + inheriting, + nextId = 0, + caller, + callerClass, + callerClassId, + toStringInstance, + toStringConstructor, + glob = typeof window !== 'undefined' && window.navigator && window.document ? window : global; + + /** + * Function that does exactly the same as the mout counterpart, + * but is faster in firefox due to a bug: + * https://bugzilla.mozilla.org/show_bug.cgi?id=816439 + */ + function inheritPrototype(A, B) { + var F = function () {}; + F.prototype = B.prototype; + A.prototype = new F(); + A.prototype.constructor = A; + } + + /** + * Wraps a method. + * This is to make some alias such as $super and $self to work correctly. + * + * @param {Function} method The method to wrap + * @param {Function} constructor The constructor + * @param {Object} parentMeta The parent method metada + * + * @return {Function} The wrapper + */ + function wrapMethod(method, constructor, parentMeta) { + if (method[$wrapped]) { + method = method[$wrapped]; + } + + var parent, + classId = constructor[$class].id, + wrapper; + + if (parentMeta) { + parent = parentMeta.isPrivate && method[$name] === 'initialize' ? callingPrivateConstructor : parentMeta.implementation; + } else { + parent = defaultSuper; + } + + wrapper = function () { + var that = this == null || this === glob ? {} : this, + _super = that.$super, + _self = that.$self, + prevCaller = caller, + prevCallerClass = callerClass, + prevCallerClassId = callerClassId, + ret; + + caller = method; + callerClassId = classId; + that.$super = parent; + that.$self = callerClass = constructor; + + try { + ret = method.apply(this, arguments); + } finally { + caller = prevCaller; + callerClassId = prevCallerClassId; + that.$super = _super; + that.$self = _self; + callerClass = prevCallerClass; + } + + return ret; + }; + + obfuscateProperty(wrapper, $wrapped, method); + + if (method[$name]) { + obfuscateProperty(wrapper, $name, method[$name]); + } + + return wrapper; + } + + /** + * Wraps a static method. + * This is to make some alias such as $super and $self to work correctly. + * + * @param {Function} method The method to wrap + * @param {Function} constructor The constructor + * @param {Object} parentMeta The parent method metadata + * + * @return {Function} The wrapper + */ + function wrapStaticMethod(method, constructor, parentMeta) { + if (method[$wrapped]) { + method = method[$wrapped]; + } + + var parent = parentMeta ? parentMeta.implementation : defaultSuper, + classId = constructor[$class].id, + wrapper; + + wrapper = function () { + var that = this == null || this === glob ? {} : this, + _super = that.$super, + _self = that.$self, + prevCaller = caller, + prevCallerClassId = callerClassId, + prevCallerClass = callerClass, + ret; + + caller = method; + callerClassId = classId; + that.$super = parent; + that.$self = callerClass = constructor; + + try { + ret = method.apply(this, arguments); + } finally { + caller = prevCaller; + callerClassId = prevCallerClassId; + that.$super = _super; + that.$self = _self; + callerClass = prevCallerClass; + } + + return ret; + }; + + obfuscateProperty(wrapper, $wrapped, method); + + if (method[$name]) { + obfuscateProperty(wrapper, $name, method[$name]); + } + + return wrapper; + } + + /** + * Default function to execute when a class atempts to call its parent private constructor. + */ + function callingPrivateConstructor() { + /*jshint validthis:true*/ + throw new Error('Cannot call parent constructor in class "' + this.$name + '" because it\'s declared as private.'); + } + + /** + * Adds a method to a class. + * This method will throw an error if something is not right. + * Valid options: + * - isStatic: true|false Defaults to false + * - isFinal: true|false Defaults to false + * - isConst: true|false Defaults to false + * + * @param {String} name The method name + * @param {Function} method The method itself + * @param {Function} constructor The class constructor in which the method metadata will be saved + * @param {Object} [opts] The options, defaults to {} + */ + function addMethod(name, method, constructor, opts) { + opts = opts || {}; + + var metadata, + isStatic = !!opts.isStatic, + forcePublic = !!(opts.forcePublic || constructor[$class].isVanilla), + isFinal, + target, + tmp, + originalMethod, + inherited; + + // Unwrap method if already wrapped + if (method[$wrapped]) { + method = method[$wrapped]; + } + + // Check if function is already being used by another class or within the same class + if (method[$name]) { + if (method[$name] !== name) { + tmp = method; + method = function () { + return tmp.apply(this, arguments); + }; + obfuscateProperty(method, $name, name); + } + } else { + obfuscateProperty(method, $name, name); + } + + // If the initialize is inherited, copy the metadata + if (!isStatic && name === 'initialize' && method.$inherited) { + metadata = mixIn({}, constructor.$parent[$class].methods[name]); + inherited = true; + delete method.$inherited; + } else if (opts.metadata) { + metadata = opts.metadata; + isFinal = metadata.isFinal; + } else { + // Grab function metadata and throw error if is not valid (it's invalid if the arguments are invalid) + if (method[$wrapped]) { + throw new Error('Cannot grab metadata from wrapped method.'); + } + metadata = functionMeta(method, name); + if (!metadata) { + throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '" contains optional arguments before mandatory ones in class "' + constructor.prototype.$name + '".'); + } + + metadata.isFinal = isFinal = !!opts.isFinal; + + if (isStatic) { + if (constructor[$class].staticMethods[name]) { + metadata.allowed = constructor[$class].staticMethods[name].allowed; + } + } else { + if (constructor[$class].methods[name]) { + metadata.allowed = constructor[$class].methods[name].allowed; + } + } + } + + // Force public if told so + if (forcePublic) { + forcePublicMetadata(metadata); + } + + // Take care of $prefix if the method is initialize + if (name === 'initialize' && method.$prefix != null) { + if (method.$prefix === '_') { + metadata.isProtected = true; + } else if (method.$prefix === '__') { + metadata.isPrivate = true; + } + + delete method.$prefix; + } + + // Check if it's a private method classified as final + if (metadata.isPrivate && isFinal) { + throw new Error('Private method "' + name + '" cannot be classified as final in class "' + constructor.prototype.$name + '".'); + } + + // Check if a property with the same name exists + target = isStatic ? constructor[$class].staticProperties : constructor[$class].properties; + if (isObject(target[name])) { + throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '" is overwriting a ' + (isStatic ? 'static ' : '') + 'property with the same name in class "' + constructor.prototype.$name + '".'); + } + + target = isStatic ? constructor[$class].staticMethods : constructor[$class].methods; + + // Check if the method already exists + if (isObject(target[name])) { + if (target[name].forcedPublic) { + forcePublicMetadata(metadata); + } else { + // Are we overriding a private method? + if (target[name].isPrivate && name !== 'initialize') { + throw new Error('Cannot override private ' + (isStatic ? 'static ' : '') + ' method "' + name + '" in class "' + constructor.prototype.$name + '".'); + } + } + + // Are we overriding a final method? + if (target[name].isFinal) { + throw new Error('Cannot override final method "' + name + '" in class "' + constructor.prototype.$name + '".'); + } + // Are they compatible? + if (metadata.checkCompatibility && !isFunctionCompatible(metadata, target[name])) { + throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '(' + metadata.signature + ')" defined in abstract class "' + constructor.prototype.$name + '" overrides its ancestor but it is not compatible with its signature: "' + name + '(' + target[name].signature + ')".'); + } + } + + target[name] = metadata; + + if (!isStatic) { + constructor[$class].ownMembers[name] = true; + } + + originalMethod = method; + method = !isStatic ? + wrapMethod(method, constructor, constructor.$parent ? constructor.$parent[$class].methods[name] : null) : + wrapStaticMethod(method, constructor, constructor.$parent ? constructor.$parent[$class].staticMethods[name] : null); + + obfuscateProperty(method, $name, name); + metadata.implementation = method; + + // Add it to the constructor or the prototype only if public + if (metadata.isPublic || !hasDefineProperty) { + target = isStatic ? constructor : constructor.prototype; + target[name] = method; + } + + // If the function is specified to be bound, add it to the binds + if (originalMethod[$bound]) { + if (!isStatic) { + insert(constructor[$class].binds, name); + } + delete originalMethod[$bound]; + } + + if (metadata.isProtected) { + if (metadata.allowed) { + insert(metadata.allowed, constructor[$class].id); + } else { + metadata.allowed = [constructor[$class].id]; + } + } else if (metadata.isPrivate) { + metadata.allowed = constructor[$class].id; + } + } + + /** + * Adds a property to the class methods metadata. + * This method will throw an error if something is not right. + * Valid options: + * - isStatic: true|false Defaults to false + * - isFinal: true|false Defaults to false + * - isConst: true|false Defaults to false + * + * @param {String} name The property name + * @param {Function} value The property itself + * @param {Function} constructor The class constructor in which the method metadata will be saved + * @param {Object} [opts] The options (defaults to {}) + */ + function addProperty(name, value, constructor, opts) { + opts = opts || {}; + + var metadata, + isStatic, + isFinal, + isConst, + forcePublic = !!(opts.forcePublic || constructor[$class].isVanilla), + target; + + if (opts.metadata) { + metadata = opts.metadata; + isFinal = metadata.isFinal; + isConst = metadata.isConst; + isStatic = !!opts.isStatic || isConst; + } else { + metadata = propertyMeta(value, name); + if (!metadata) { + throw new Error('Value of property "' + name + '" in class "' + constructor.prototype.$name + '" cannot be parsed (undefined values are not allowed).'); + } + metadata.isFinal = isFinal = !!opts.isFinal; + metadata.isConst = isConst = !!opts.isConst; + isStatic = !!opts.isStatic || isConst; + + if (isStatic) { + if (constructor[$class].staticProperties[name]) { + metadata.allowed = constructor[$class].staticProperties[name].allowed; + } + } else { + if (constructor[$class].properties[name]) { + metadata.allowed = constructor[$class].properties[name].allowed; + } + } + } + + // Force public if told so + if (forcePublic) { + forcePublicMetadata(metadata); + } + + // Check if the metadata was fine (if not then the property is undefined) + if (!metadata) { + throw new Error('Value of ' + (isConst ? 'constant ' : (isStatic ? 'static ' : '')) + ' property "' + name + '" defined in class "' + constructor.prototype.$name + '" can\'t be undefined (use null instead).'); + } + // Check if its a constant and its value is immutable + if (isConst && !metadata.isImmutable) { + throw new Error('Value for constant "' + name + '" defined in class "' + constructor.prototype.$name + '" must be a primitive type (immutable).'); + } + // Check if it's a private property classified as final + if (metadata.isPrivate && isFinal) { + throw new Error((isStatic ? 'Static property' : 'Property') + ' "' + name + '" cannot be classified as final in class "' + constructor.prototype.$name + '".'); + } + + target = isStatic ? constructor[$class].staticMethods : constructor[$class].methods; + + // Check if a method with the same name exists + if (isObject(target[name])) { + throw new Error((isConst ? 'Constant property' : (isStatic ? 'Static property' : 'Property')) + ' "' + name + '" is overwriting a ' + (isStatic ? 'static ' : '') + 'method with the same name in class "' + constructor.prototype.$name + '".'); + } + + target = isStatic ? constructor[$class].staticProperties : constructor[$class].properties; + + if (isObject(target[name])) { + // Force public if told so + if (target[name].forcedPublic) { + forcePublicMetadata(metadata); + } else { + // Are we overriding a private property? + if (target[name].isPrivate) { + throw new Error('Cannot override private ' + (isConst ? 'constant ' : (isStatic ? 'static ' : '')) + ' property "' + name + ' in class "' + constructor.prototype.$name + '".'); + } + } + // Are we overriding a constant? + if (target[name].isConst) { + throw new Error('Cannot override constant property "' + name + '" in class "' + constructor.prototype.$name + '".'); + } + // Are we overriding a final property? + if (target[name].isFinal) { + throw new Error('Cannot override final property "' + name + '" in class "' + constructor.prototype.$name + '".'); + } + } + + target[name] = metadata; + if (!isStatic) { + constructor[$class].ownMembers[name] = true; + } + + // Add it to the constructor or the prototype only if public + if (metadata.isPublic || !hasDefineProperty) { + target = isStatic ? constructor : constructor.prototype; + target[name] = value; + } + + if (isFinal) { + metadata.isFinal = isFinal; + } else if (isConst) { + metadata.isConst = isConst; + } + + if (metadata.isProtected) { + if (metadata.allowed) { + insert(metadata.allowed, constructor[$class].id); + } else { + metadata.allowed = [constructor[$class].id]; + } + } else if (metadata.isPrivate) { + metadata.allowed = constructor[$class].id; + } + } + + /** + * Forces the property/function visibility to public + * + * @param {Object} metadata The member metadata object + */ + function forcePublicMetadata(metadata) { + delete metadata.isProtected; + delete metadata.isPrivate; + metadata.isPublic = metadata.forcedPublic = true; + } + + /** + * Borrows members from a vanilla object definition. + * + * @param {Object} params The parameters + * @param {Function} constructor The constructor + */ + function borrowFromVanilla(params, constructor) { + // The members borrowed must be interpreted as public + // This is because they do not use the $binds and maybe calling protected/private members + // from anonymous functions + + var key, + value, + opts = { forcePublic: true }; + + // Grab mixin members + for (key in params) { + // Ignore the constructor + if (/^(_){0,2}initialize$/.test(key)) { + continue; + } + + value = params[key]; + + if (!hasOwn(constructor.prototype, key)) { // Already defined members are not overwritten + if (isFunction(value) && !value[$class] && !value[$interface]) { + addMethod(key, value, constructor, opts); + } else { + addProperty(key, value, constructor, opts); + } + } + } + + constructor[$class].forceUnlocked = true; + } + + /** + * Parse borrows (mixins). + * + * @param {Object} params The parameters + * @param {Function} constructor The constructor + */ + function parseBorrows(params, constructor) { + if (hasOwn(params, '$borrows')) { + var current, + mixins = toArray(params.$borrows), + i = mixins.length, + key, + opts = {}; + + // Verify argument type + if (!i && !isArray(params.$borrows)) { + throw new Error('$borrows of class "' + constructor.prototype.$name + '" must be a class/object or an array of classes/objects.'); + } + // Verify duplicate entries + if (i !== unique(mixins).length && compact(mixins).length === i) { + throw new Error('There are duplicate entries defined in $borrows of class "' + constructor.prototype.$name + '".'); + } + + for (i -= 1; i >= 0; i -= 1) { + current = mixins[i]; + + // If is a vanilla object + if (isObject(current)) { + if (current.$static) { + throw new Error('Entry at index ' + i + ' in $borrows of class "' + constructor.prototype.$name + '" is not a valid class/object.'); + } + borrowFromVanilla(current, constructor); + continue; + } + // If is a vanilla class + if (isFunction(current) && !current[$interface]) { + if (!current[$class]) { + borrowFromVanilla(current.prototype, constructor); + continue; + } + } else { + throw new Error('Entry at index ' + i + ' in $borrows of class "' + constructor.prototype.$name + '" is not a valid class/object.'); + } + + current = current.prototype; + + // Verify if is an abstract class with unimplemented members + if (current.$static[$abstract] && current.$static[$abstract].unimplemented) { + throw new Error('Entry at index ' + i + ' in $borrows of class "' + constructor.prototype.$name + '" is an abstract class with abstract members, which are not allowed.'); + } + + // Verify if it has parent + if (current.$static.$parent) { + throw new Error('Entry at index ' + i + ' in $borrows of class "' + constructor.prototype.$name + '" is an inherited class (only root classes are supported).'); + } + + delete opts.isStatic; + + // Grab mixin members + for (key in current.$static[$class].methods) { + if (!hasOwn(constructor.prototype, key)) { // Already defined members are not overwritten + // We need to clone the metadata and delete the allowed because otherwise multiple classes borrowing from the same would have access + // Same applies to the things bellow + opts.metadata = mixIn({}, current.$static[$class].methods[key]); + delete opts.metadata.allowed; + addMethod(key, opts.metadata.implementation || current[key], constructor, opts); + } + } + + for (key in current.$static[$class].properties) { + if (!hasOwn(constructor.prototype, key)) { // Already defined members are not overwritten + opts.metadata = mixIn({}, current.$static[$class].properties[key]); + delete opts.metadata.allowed; + addProperty(key, opts.metadata.value || current[key], constructor, opts); + } + } + + opts.isStatic = true; + + // Grab mixin static members + for (key in current.$static[$class].staticMethods) { + opts.metadata = mixIn({}, current.$static[$class].staticMethods[key]); + delete opts.metadata.allowed; + addMethod(key, opts.metadata.implementation || current.$static[key], constructor, opts); + } + + for (key in current.$static[$class].staticProperties) { + opts.metadata = mixIn({}, current.$static[$class].staticProperties[key]); + delete opts.metadata.allowed; + addProperty(key, opts.metadata.value || current.$static[key], constructor, opts); + } + + if (current.$static[$class].isVanilla) { + constructor[$class].forceUnlocked = true; + } + + // Merge the binds + combine(constructor[$class].binds, current.$static[$class].binds); + } + + delete params.$borrows; + } + } + + /** + * Handle class interfaces. + * + * @param {Array} interfs The array of interfaces + * @param {Object} target The target that has the interfaces + */ + function handleInterfaces(interfs, target) { + var interfaces = toArray(interfs), + interf, + x = interfaces.length, + k, + opts = { isConst: true }; + + // Verify argument type + if (!x && !isArray(interfs)) { + throw new Error('$implements of class "' + target.prototype.$name + '" must be an interface or an array of interfaces.'); + } + // Verify duplicate interfaces + if (x !== unique(interfaces).length && compact(interfaces).length === x) { + throw new Error('There are duplicate entries in $implements of class "' + target.prototype.$name + '".'); + } + + for (x -= 1; x >= 0; x -= 1) { + interf = interfaces[x]; + + // Verify if it's a valid interface + if (!isFunction(interf) || !interf[$interface]) { + throw new Error('Entry at index ' + x + ' in $implements of class "' + target.prototype.$name + '" is not a valid interface.'); + } + + // Inherit constants and add interface to the interfaces array + if (!contains(target[$class].interfaces, interf)) { + + // Inherit constants + for (k in interf[$interface].constants) { + addProperty(k, interf[k], target, opts); + } + + // Add to interfaces array + target[$class].interfaces.push(interf); + } + + if (!target[$abstract]) { + interfaces[x][$interface].check(target); + } + } + } + + /** + * Parse an object members. + * + * @param {Object} params The parameters + * @param {Function} constructor The constructor + * @param {Boolean} isFinal Parse the members as finals + */ + function parseMembers(params, constructor, isFinal) { + var opts = { isFinal: !!isFinal }, + key, + value, + cache = {}, + unallowed; + + // Add each method metadata, verifying its signature + if (hasOwn(params, '$statics')) { + // Check if is an object + if (!isObject(params.$statics)) { + throw new Error('$statics definition of class "' + params.$name + '" must be an object.'); + } + + // Check reserved keywords + checkKeywords(params.$statics, 'statics'); + + // Check unallowed keywords + unallowed = testKeywords(params.$statics); + if (unallowed) { + throw new Error('$statics ' + (isFinal ? 'inside $finals ' : '') + ' of class "' + constructor.prototype.$name + '" contains an unallowed keyword: "' + unallowed + '".'); + } + + opts.isStatic = true; + + for (key in params.$statics) { + value = params.$statics[key]; + + if (isFunction(value) && !value[$class] && !value[$interface]) { + addMethod(key, value, constructor, opts); + } else { + addProperty(key, value, constructor, opts); + } + } + + delete opts.isStatic; + delete params.$statics; + } + + // Save certain keywords in the cache for the loop bellow to work faster + if (hasOwn(params, '$implements')) { + cache.$implements = params.$implements; + delete params.$implements; + } + + if (hasOwn(params, '$abstracts')) { + cache.$abstracts = params.$abstracts; + delete params.$abstracts; + } + + for (key in params) { + value = params[key]; + + if (isFunction(value) && !value[$class] && !value[$interface]) { + addMethod(key, value, constructor, opts); + } else { + addProperty(key, value, constructor, opts); + } + } + + // Restore from cache + mixIn(params, cache); + } + + /** + * Parse all the class members, including finals, static and constants. + * + * @param {Object} params The parameters + * @param {Function} constructor The constructor + */ + function parseClass(params, constructor) { + var opts = {}, + key, + value, + saved = {}, + unallowed, + ambiguous; + + // Check and save constants to parse later + if (hasOwn(params, '$constants')) { + // Check argument + if (!isObject(params.$constants)) { + throw new Error('$constants of class "' + constructor.prototype.$name + '" must be an object.'); + } + + // Check reserved keywords + checkKeywords(params.$constants, 'statics'); + + // Check unallowed keywords + unallowed = testKeywords(params.$constants); + if (unallowed) { + throw new Error('$constants of class "' + constructor.prototype.$name + '" contains an unallowed keyword: "' + unallowed + '".'); + } + + // Check ambiguity + if (isObject(params.$statics)) { + ambiguous = intersection(keys(params.$constants), keys(params.$statics)); + if (ambiguous.length) { + throw new Error('There are members defined in class "' + constructor.prototype.$name + '" with the same name but with different modifiers: "' + ambiguous.join('", ') + '".'); + } + } + + saved.$constants = params.$constants; + delete params.$constants; + } + + // Check and save finals to parse later + if (hasOwn(params, '$finals')) { + // Check argument + if (!isObject(params.$finals)) { + throw new Error('$finals of class "' + constructor.prototype.$name + '" must be an object.'); + } + + // Check reserved keywords + checkKeywords(params.$finals); + + // Check unallowed keywords + unallowed = testKeywords(params.$finals, ['$statics']); + if (unallowed) { + throw new Error('$finals of class "' + constructor.prototype.$name + '" contains an unallowed keyword: "' + unallowed + '".'); + } + + // Check ambiguity + if (isObject(params.$finals.$statics)) { + if (isObject(params.$statics)) { + ambiguous = intersection(keys(params.$finals.$statics), keys(params.$statics)); + if (ambiguous.length) { + throw new Error('There are members defined in class "' + constructor.prototype.$name + '" with the same name but with different modifiers: "' + ambiguous.join('", ') + '".'); + } + } + if (saved.$constants) { + ambiguous = intersection(keys(params.$finals.$statics), keys(saved.$constants)); + if (ambiguous.length) { + throw new Error('There are members defined in class "' + constructor.prototype.$name + '" with the same name but with different modifiers: "' + ambiguous.join('", ') + '".'); + } + } + } + ambiguous = intersection(keys(params), keys(params.$finals)); + if (ambiguous.length) { + remove(ambiguous, '$statics'); + if (ambiguous.length) { + throw new Error('There are members defined in class "' + constructor.prototype.$name + '" with the same name but with different modifiers: "' + ambiguous.join('", ') + '".'); + } + } + + saved.$finals = params.$finals; + delete params.$finals; + } + + // Check and save locked to parse later + if (hasOwn(params, '$locked')) { + if (!isBoolean(params.$locked)) { + throw new Error('$locked of class "' + constructor.prototype.name + '" must be a boolean.'); + } + + saved.$locked = params.$locked; + delete params.$locked; + } + + // Parse members + parseMembers(params, constructor); + + // Parse constants + if (saved.$constants) { + opts.isConst = true; + + for (key in saved.$constants) { + value = saved.$constants[key]; + + addProperty(key, value, constructor, opts); + } + + delete opts.isConst; + } + + // Parse finals + if (saved.$finals) { + parseMembers(saved.$finals, constructor, true); + } + + // Parse locked + if (hasOwn(saved, '$locked')) { + if (constructor[$class].forceUnlocked && saved.$locked) { + throw new Error('Class "' + constructor.prototype.$name + '" cannot be locked because it borrows or extends from a vanilla class.'); + } + if (constructor[$class].locked === false && saved.$locked) { + throw new Error('Class "' + constructor.prototype.$name + '" inherits from an unlocked class, therefore its subclasses cannot be locked.'); + } + constructor[$class].locked = !!saved.$locked; + delete constructor.prototype.$locked; + } else if (!hasOwn(constructor[$class], 'locked')) { + constructor[$class].locked = !!options.locked; + } + } + + /** + * Applies the context of given methods in the target. + * + * @param {Array} fns The array of functions to be bound + * @param {Object} instance The target instance + */ + function applyBinds(fns, instance) { + var i, + current; + + for (i = fns.length - 1; i >= 0; i -= 1) { + current = instance[fns[i]]; + instance[fns[i]] = bind(current, instance); + instance[fns[i]][$name] = current.$name; + } + } + + /** + * Protects a method according to its visibility. + * + * @param {String} name The method name + * @param {Object} meta The function meta + * @param {Object} instance The instance that will have the method + */ + function protectMethod(name, meta, instance) { + instance[cacheKeyword].methods[name] = meta.implementation; + + if (meta.isPrivate) { + Object.defineProperty(instance, name, { + get: function get() { + var method = instance[cacheKeyword].methods[name], + currCaller = caller, + isConstructor = name === 'initialize'; + + if (instance.$initializing || (currCaller && (currCaller[$name] || currCaller[$anonymous]) && meta.allowed === callerClassId)) { + return method; + } + + if (!isConstructor) { + throw new Error('Cannot access private method "' + name + '" of class "' + instance.$name + '".'); + } else { + throw new Error('Constructor of class "' + instance.$name + '" is private.'); + } + }, + set: function set(newVal) { + if (instance.$initializing || !instance.$static[$class].locked || instance.$static[$class].forceUnlocked) { + instance[cacheKeyword].methods[name] = newVal; + instance[redefinedCacheKeyword].methods[name] = true; // This is just for the inspect + } else { + throw new Error('Cannot set private method "' + name + '" of class "' + instance.$name + '".'); + } + }, + configurable: false, + enumerable: true + }); + } else if (meta.isProtected) { + Object.defineProperty(instance, name, { + get: function get() { + var method = instance[cacheKeyword].methods[name], + currCaller = caller, + isConstructor = name === 'initialize'; + + if (instance.$initializing || (currCaller && (currCaller[$name] || currCaller[$anonymous]) && (contains(meta.allowed, callerClassId) || instance instanceof callerClass))) { + return method; + } + + if (!isConstructor) { + throw new Error('Cannot access protected method "' + name + '" of class "' + instance.$name + '".'); + } else { + throw new Error('Constructor of class "' + instance.$name + '" is protected.'); + } + }, + set: function set(newVal) { + + if (instance.$initializing || !instance.$static[$class].locked || instance.$static[$class].forceUnlocked) { + instance[cacheKeyword].methods[name] = newVal; + instance[redefinedCacheKeyword].methods[name] = true; // This is just for the inspect + } else { + throw new Error('Cannot set protected method "' + name + '" of class "' + instance.$name + '".'); + } + }, + configurable: false, + enumerable: true + }); + } else { + Object.defineProperty(instance, name, { + get: function get() { + return instance[cacheKeyword].methods[name]; + }, + set: function set(newVal) { + if (instance.$initializing || !instance.$static[$class].locked || instance.$static[$class].forceUnlocked) { + instance[cacheKeyword].methods[name] = newVal; + instance[redefinedCacheKeyword].methods[name] = true; + } else { + throw new Error('Cannot set public method "' + name + '" of class "' + instance.$name + '".'); + } + }, + configurable: false, + enumerable: true + }); + } + } + + /** + * Protects a static method according to its visibility. + * + * @param {String} name The method name + * @param {Object} meta The function meta + * @param {Function} constructor The constructor that will have the method + */ + function protectStaticMethod(name, meta, constructor) { + constructor[cacheKeyword].methods[name] = meta.implementation; + + if (meta.isPrivate) { + Object.defineProperty(constructor, name, { + get: function get() { + var method = constructor[cacheKeyword].methods[name], + currCaller = caller; + + if (inheriting || (currCaller && (currCaller[$name] || currCaller[$anonymous]) && meta.allowed === callerClassId)) { + return method; + } + + throw new Error('Cannot access private static method "' + name + '" of class "' + constructor.prototype.$name + '".'); + }, + set: function set(newVal) { + if (!constructor[$class].locked || constructor[$class].forceUnlocked) { + constructor[cacheKeyword].methods[name] = newVal; + } else { + throw new Error('Cannot set private static method "' + name + '" of class "' + constructor.prototype.$name + '".'); + } + }, + configurable: false, + enumerable: true + }); + } else if (meta.isProtected) { + Object.defineProperty(constructor, name, { + get: function get() { + var method = constructor[cacheKeyword].methods[name], + currCaller = caller; + + if (inheriting || (currCaller && (currCaller[$name] || currCaller[$anonymous]) && (contains(meta.allowed, callerClassId) || constructor.prototype instanceof callerClass))) { + return method; + } + + throw new Error('Cannot access protected static method "' + name + '" of class "' + constructor.prototype.$name + '".'); + }, + set: function set(newVal) { + if (!constructor[$class].locked || constructor[$class].forceUnlocked) { + constructor[cacheKeyword].methods[name] = newVal; + } else { + throw new Error('Cannot set protected static method "' + name + '" of class "' + constructor.prototype.$name + '".'); + } + }, + configurable: false, + enumerable: true + }); + } else { + Object.defineProperty(constructor, name, { + get: function get() { + return constructor[cacheKeyword].methods[name]; + }, + set: function set(newVal) { + if (!constructor[$class].locked || constructor[$class].forceUnlocked) { + constructor[cacheKeyword].methods[name] = newVal; + } else { + throw new Error('Cannot set public static method "' + name + '" of class "' + constructor.prototype.$name + '".'); + } + }, + configurable: false, + enumerable: true + }); + } + } + + /** + * Protects a property according to its visibility. + * + * @param {String} name The property name + * @param {Object} meta The property meta + * @param {Object} instance The instance that will have the property + */ + function protectProperty(name, meta, instance) { + if (meta.isPrivate) { + if (!meta.isImmutable) { + instance[cacheKeyword].properties[name] = deepClone(meta.value); + instance[redefinedCacheKeyword].properties[name] = true; // This is just for the inspect + } else { + instance[cacheKeyword].properties[name] = meta.value; + } + + Object.defineProperty(instance, name, { + get: function get() { + var currCaller = caller; + + if (instance.$initializing || (currCaller && (currCaller[$name] || currCaller[$anonymous]) && meta.allowed === callerClassId)) { + return instance[cacheKeyword].properties[name]; + } + + throw new Error('Cannot access private property "' + name + '" of class "' + instance.$name + '".'); + }, + set: function set(newVal) { + var currCaller = caller; + + if (instance.$initializing || (currCaller && (currCaller[$name] || currCaller[$anonymous]) && meta.allowed === callerClassId)) { + instance[cacheKeyword].properties[name] = newVal; + instance[redefinedCacheKeyword].properties[name] = true; + } else { + throw new Error('Cannot set private property "' + name + '" of class "' + instance.$name + '".'); + } + }, + configurable: false, + enumerable: true + }); + } else if (meta.isProtected) { + if (!meta.isImmutable) { + instance[cacheKeyword].properties[name] = deepClone(meta.value); + instance[redefinedCacheKeyword].properties[name] = true; // This is just for the inspect + } else { + instance[cacheKeyword].properties[name] = meta.value; + } + + Object.defineProperty(instance, name, { + get: function get() { + var currCaller = caller; + + if (instance.$initializing || (currCaller && (currCaller[$name] || currCaller[$anonymous]) && (contains(meta.allowed, callerClassId) || instance instanceof callerClass))) { + return instance[cacheKeyword].properties[name]; + } + + throw new Error('Cannot access protected property "' + name + '" of class "' + instance.$name + '".'); + }, + set: function set(newVal) { + var currCaller = caller; + + if (instance.$initializing || (currCaller && (currCaller[$name] || currCaller[$anonymous]) && (contains(meta.allowed, callerClassId) || instance instanceof callerClass))) { + instance[cacheKeyword].properties[name] = newVal; + instance[redefinedCacheKeyword].properties[name] = true; + } else { + throw new Error('Cannot set protected property "' + name + '" of class "' + instance.$name + '".'); + } + }, + configurable: false, + enumerable: true + }); + } else if (!meta.isImmutable) { + instance[name] = deepClone(instance[name]); + instance[redefinedCacheKeyword].properties[name] = true; // This is just for the inspect + } else { + instance[name] = meta.value; + } + } + + /** + * Protects a static property according to its visibility. + * + * @param {String} name The property name + * @param {Object} meta The property meta + * @param {Function} constructor The constructor that will have the property + */ + function protectStaticProperty(name, meta, constructor) { + constructor[cacheKeyword].properties[name] = meta.value; + + if (meta.isPrivate) { + Object.defineProperty(constructor, name, { + get: function get() { + var currCaller = caller; + + if (inheriting || (currCaller && (currCaller[$name] || currCaller[$anonymous]) && meta.allowed === callerClassId)) { + return constructor[cacheKeyword].properties[name]; + } + + throw new Error('Cannot access private static property "' + name + '" of class "' + constructor.prototype.$name + '".'); + }, + set: meta.isConst ? + function () { + throw new Error('Cannot change value of constant property "' + name + '" of class "' + constructor.prototype.$name + '".'); + } : + function set(newVal) { + var currCaller = caller; + + if (currCaller && (currCaller[$name] || currCaller[$anonymous]) && meta.allowed === callerClassId) { + constructor[cacheKeyword].properties[name] = newVal; + } else { + throw new Error('Cannot set private property "' + name + '" of class "' + constructor.prototype.$name + '".'); + } + }, + configurable: false, + enumerable: true + }); + } else if (meta.isProtected) { + Object.defineProperty(constructor, name, { + get: function get() { + var currCaller = caller; + + if (inheriting || (currCaller && (currCaller[$name] || currCaller[$anonymous]) && (contains(meta.allowed, callerClassId) || constructor.prototype instanceof callerClass))) { + return constructor[cacheKeyword].properties[name]; + } + + throw new Error('Cannot access protected static property "' + name + '" of class "' + constructor.prototype.$name + '".'); + }, + set: meta.isConst ? + function () { + throw new Error('Cannot change value of constant property "' + name + '" of class "' + constructor.prototype.$name + '".'); + } : + function set(newVal) { + var currCaller = caller; + + if (currCaller && (currCaller[$name] || currCaller[$anonymous]) && (contains(meta.allowed, callerClassId) || constructor.prototype instanceof callerClass)) { + constructor[cacheKeyword].properties[name] = newVal; + } else { + throw new Error('Cannot set protected static property "' + name + '" of class "' + constructor.prototype.$name + '".'); + } + }, + configurable: false, + enumerable: true + }); + } else if (meta.isConst) { + Object.defineProperty(constructor, name, { + get: function () { + return constructor[cacheKeyword].properties[name]; + }, + set: function () { + throw new Error('Cannot change value of constant property "' + name + '" of class "' + constructor.prototype.$name + '".'); + }, + configurable: false, + enumerable: true + }); + } + } + + /** + * Protects an instance. + * + * All its methods and properties will be secured according to their visibility. + * + * @param {Object} instance The instance to be protected + */ + function protectInstance(instance) { + var key; + + obfuscateProperty(instance, cacheKeyword, { properties: {}, methods: {} }); + obfuscateProperty(instance, redefinedCacheKeyword, { properties: {}, methods: {} }); // This is for the inspect + + for (key in instance.$static[$class].methods) { + protectMethod(key, instance.$static[$class].methods[key], instance); + } + + for (key in instance.$static[$class].properties) { + protectProperty(key, instance.$static[$class].properties[key], instance); + } + } + + /** + * Protects a constructor. + * + * All its methods and properties will be secured according to their visibility. + * + * @param {Function} constructor The constructor to be protected + */ + function protectConstructor(constructor) { + var key; + + obfuscateProperty(constructor, cacheKeyword, { properties: {}, methods: {} }); + + for (key in constructor[$class].staticMethods) { + protectStaticMethod(key, constructor[$class].staticMethods[key], constructor); + } + + for (key in constructor[$class].staticProperties) { + protectStaticProperty(key, constructor[$class].staticProperties[key], constructor); + } + + // Prevent any properties/methods to be added and deleted to the constructor + if (constructor[$class].locked && !constructor[$class].forceUnlocked) { + if (isFunction(Object.seal)) { + Object.seal(constructor); + } + + // Prevent any properties/methods to modified in the prototype + if (isFunction(Object.freeze) && !hasFreezeBug) { + Object.freeze(constructor.prototype); + } else if (isFunction(Object.seal)) { + Object.seal(constructor.prototype); + } + } + } + + /** + * Builds the constructor function that calls the initialize and do + * more things internally. + * + * @param {Function} constructor The constructor function to assume and fill + * @param {Boolean} isAbstract Treat this class as abstract + * + * @return {Function} The constructor function + */ + function createConstructor(constructor, isAbstract) { + var Instance = constructor || function Instance() { + var x, + tmp; + + // Check if the user forgot the new keyword + if (!(this instanceof Instance)) { + throw new Error('Constructor called as a function, use the new keyword instead.'); + } + + // If it's abstract, it cannot be instantiated + if (isAbstract) { + throw new Error('An abstract class cannot be instantiated.'); + } + + obfuscateProperty(this, '$initializing', true, true, true); // Mark it in order to let abstract classes run their initialize + obfuscateProperty(this, '$super', null, true); // Add the super to the instance object to speed lookup of the wrapper function + obfuscateProperty(this, '$self', null, true); // Add the self to the instance object to speed lookup of the wrapper function + + tmp = this.$static[$class]; + + // Apply private/protected members + if (hasDefineProperty) { + protectInstance(this); + } else { + // Reset some types of the object in order for each instance to have their variables + for (x in tmp.properties) { + if (!tmp.properties[x].isImmutable) { + this[x] = deepClone(this[x]); + } + } + } + + // Apply binds + if (tmp.binds.length) { + applyBinds(tmp.binds, this, this); + } + + delete this.$initializing; + + // Prevent any properties/methods to be added and deleted + if (!tmp.forceUnlocked && tmp.locked && isFunction(Object.seal)) { + Object.seal(this); + } + + // Call initialize + this.initialize.apply(this, arguments); + }; + + if (!Instance[$class]) { + obfuscateProperty(Instance, $class, { methods: {}, properties: {}, staticMethods: {}, staticProperties: {}, ownMembers: {}, interfaces: [], binds: [] }); + if (hasDefineProperty) { + Instance[$class].simpleConstructor = function () {}; + obfuscateProperty(Instance[$class].simpleConstructor, '$constructor', Instance); + } + } + + return Instance; + } + + /** + * Marks a function as part of the class. + * + * @param {Function} func The function + */ + function doMember(func) { + /*jshint validthis:true*/ + func = func || this; + + // Check if it is a named func already + if (func[$name]) { + return func; + } + + // Check if outside the instance/class + if (!callerClass) { + throw new Error('Attempting to mark a function as a member outside an instance/class.'); + } + + // Check if already marked as anonymous + if (func[$anonymous]) { + throw new Error('Function is already marked as an member.'); + } + + func[$anonymous] = true; + func = wrapMethod(func, callerClass); + func[$anonymous] = true; + + return func; + } + + /** + * Default implementation of the super function. + */ + function defaultSuper() { + throw new Error('Trying to call $super when there is no parent function.'); + } + + /** + * Bind. + * Works for anonymous functions also. + * + * @param {Function} func The function to be bound + * @param {...mixed} [args] The arguments to also be bound + * + * @return {Function} The bound function + */ + function doBind(func) { + /*jshint validthis:true*/ + var args = toArray(arguments), + bound, + isAnonymous; + + if (!func[$wrapped] && this.$static && this.$static[$class]) { + func[$anonymous] = true; + func = wrapMethod(func, this.$self || this.$static); + args[0] = func; + isAnonymous = true; + } + + args.splice(1, 0, this); + bound = bind.apply(func, args); + if (isAnonymous) { + bound[$anonymous] = func[$anonymous] = true; + } + + return bound; + } + + /** + * Static bind. + * Works for anonymous functions also. + * + * @param {Function} func The function to be bound + * @param {...mixed} [args] The arguments to also be bound + * + * @return {Function} The bound function + */ + function doBindStatic(func) { + /*jshint validthis:true*/ + var args = toArray(arguments), + bound, + isAnonymous; + + if (!func[$wrapped] && this.$static && this.$static[$class]) { + func[$anonymous] = true; + func = wrapStaticMethod(func, this.$self || this.$static); + args[0] = func; + isAnonymous = true; + } + + args.splice(1, 0, this); + bound = bind.apply(func, args); + if (isAnonymous) { + bound[$anonymous] = func[$anonymous] = true; + } + + return bound; + } + + /** + * Inherits aditional data from the parent, such as metadata, binds and static members. + * + * @param {Function} constructor The constructor + * @param {Function} parent The parent + */ + function inheritParent(constructor, parent) { + var x, + binds = parent[$class].binds, + key, + value, + classId = constructor[$class].id; + + // Inherit binds + for (x = binds.length - 1; x >= 0; x -= 1) { + if (binds[x].substr(0, 2) !== '__') { + constructor[$class].binds.push(binds[x]); + } + } + + inheriting = true; + + // Inherit methods and properties + for (key in parent[$class].methods) { + value = parent[$class].methods[key]; + constructor[$class].methods[key] = value; + + if (value.isProtected) { + value.allowed.push(classId); + } + } + + for (key in parent[$class].properties) { + value = parent[$class].properties[key]; + constructor[$class].properties[key] = value; + + if (value.isProtected) { + value.allowed.push(classId); + } + } + + // Inherit static methods and properties + for (key in parent[$class].staticMethods) { + value = parent[$class].staticMethods[key]; + + if (!value.isPrivate) { + constructor[$class].staticMethods[key] = value; + constructor[key] = value.implementation; + + if (value.isProtected) { + value.allowed.push(classId); + } + } + } + + for (key in parent[$class].staticProperties) { + value = parent[$class].staticProperties[key]; + + if (!value.isPrivate) { + constructor[$class].staticProperties[key] = value; + constructor[key] = value.value; + if (value.isProtected) { + value.allowed.push(classId); + } + + } + } + + // Make inheritance also for the simple constructor (for the inspect) + if (hasDefineProperty) { + inheritPrototype(constructor[$class].simpleConstructor, parent[$class].simpleConstructor); + } + + // Inherit locked and forceUnlocked + if (hasOwn(parent[$class], 'locked')) { + constructor[$class].locked = parent[$class].locked; + } + if (hasOwn(parent[$class], 'forceUnlocked')) { + constructor[$class].forceUnlocked = parent[$class].forceUnlocked; + } + + inheriting = false; + + obfuscateProperty(constructor, '$parent', parent); + + // Inherit implemented interfaces + constructor[$class].interfaces = [].concat(parent[$class].interfaces); + } + + /** + * Function to easily extend another class. + * + * @param {Object|Function} params An object containing methods and properties or a function that returns it + * + * @return {Function} The new class constructor + */ + function extend(params, $arg) { + /*jshint validthis:true*/ + return Class.declare(this, params, $arg); + } + + /** + * Method that will print a readable string describing an instance. + * + * @return {String} The readable string + */ + toStringInstance = function () { + return '[instance #' + this.$name + ']'; + }; + + /** + * Method that will print a readable string describing an instance. + * + * @return {String} The readable string + */ + toStringConstructor = function () { + return '[constructor #' + this.prototype.$name + ']'; + }; + + /** + * Create a class definition. + * + * @param {Object} params An object containing methods and properties + * @param {Constructor} [constructor] Assume the passed constructor + * @param {Object} [opts] Options + * + * @return {Function} The constructor + */ + createClass = function (params, constructor, opts) { + opts = opts || {}; + + var dejavu, + parent, + tmp, + key, + x, + found; + + // Validate class name + if (hasOwn(params, '$name')) { + if (!isString(params.$name)) { + throw new Error('Class name must be a string.'); + } else if (/\s+/.test(params.$name)) { + throw new Error('Class name cannot have spaces.'); + } + } else { + params.$name = 'Unnamed'; + } + + // Verify if the class has abstract methods but is not defined as abstract + if (hasOwn(params, '$abstracts') && !opts.isAbstract) { + throw new Error('Class "' + params.$name + '" has abstract methods, therefore it must be defined as abstract.'); + } + + // Verify if initialize is a method (only for non vanilla classes) + if (!opts.isVanilla) { + tmp = ['__', '_', '']; + found = false; + for (x = tmp.length - 1; x >= 0; x -= 1) { + key = tmp[x] + 'initialize'; + if (hasOwn(params, key)) { + if (!isFunction(params[key])) { + throw new Error('The "' + key + '" member of class "' + params.$name + '" must be a function.'); + } + if (found) { + throw new Error('Several constructors with different visibility where found in class "' + params.$name + '".'); + } + found = true; + + // Mark the initialize method with its real prefix to be used later to protect the method + params[key].$prefix = tmp[x]; + } + } + } + + // Verify reserved words + checkKeywords(params, 'normal'); + + if (hasOwn(params, '$extends')) { + parent = params.$extends; + delete params.$extends; + + // Verify if parent is a valid class + if (isFunction(parent) && !parent[$interface]) { + // If its a vanilla class create a dejavu class based on it + if (!parent[$class]) { + parent = createClass(parent.prototype, parent, { isVanilla: true }); + } + + // Verify if we are inheriting a final class + if (parent[$class].finalClass) { + throw new Error('Class "' + params.$name + '" cannot inherit from final class "' + parent.prototype.$name + '".'); + } + } else { + throw new Error('Specified parent class in $extends of "' + params.$name + '" is not a valid class.'); + } + + dejavu = createConstructor(constructor, opts.isAbstract); + dejavu[$class].id = nextId += 1; + + if (opts.isVanilla) { + params.initialize = function () { dejavu.apply(this, arguments); }; + dejavu[$class].forceUnlocked = true; + dejavu[$class].isVanilla = true; + } else if (!params.initialize && !params._initialize && !params.__initialize) { + params.initialize = function () { parent.prototype.initialize.apply(this, arguments); }; + params.initialize.$inherited = true; + } else { + params.initialize = params.initialize || params._initialize || params.__initialize; + } + inheritPrototype(dejavu, parent); + inheritParent(dejavu, parent); + } else { + dejavu = createConstructor(constructor, opts.isAbstract); + dejavu[$class].id = nextId += 1; + + if (opts.isVanilla) { + params.initialize = function () { dejavu.apply(this, arguments); }; + dejavu[$class].forceUnlocked = true; + dejavu[$class].isVanilla = true; + } else { + params.initialize = params.initialize || params._initialize || params.__initialize || function () {}; + } + } + + if (!opts.isVanilla) { + delete params._initialize; + delete params.__initialize; + } + + if (opts.isAbstract) { + obfuscateProperty(dejavu, $abstract, true, true); // Signal it has abstract + } + + dejavu.prototype.$name = params.$name; + delete params.$name; + + // Parse mixins + parseBorrows(params, dejavu); + + // Parse class members + parseClass(params, dejavu); + + // Assign aliases + obfuscateProperty(dejavu.prototype, '$static', dejavu); + obfuscateProperty(dejavu, '$static', dejavu); + obfuscateProperty(dejavu, '$self', null, true); + obfuscateProperty(dejavu, '$super', null, true); + obfuscateProperty(dejavu, '$member', doMember); + obfuscateProperty(dejavu, '$bind', doBindStatic); + if (!dejavu.$parent) { + obfuscateProperty(dejavu.prototype, '$bind', doBind); + obfuscateProperty(dejavu.prototype, '$member', doMember); + } + + // Add toString() if not defined yet + if (params.toString === Object.prototype.toString) { + obfuscateProperty(dejavu.prototype, 'toString', toStringInstance, true); + } + if (dejavu.toString === Function.prototype.toString) { + obfuscateProperty(dejavu, 'toString', toStringConstructor, true); + } + + // If we are a concrete class that extends an abstract class, we need to verify the methods existence + if (parent && parent[$abstract] && !opts.isAbstract) { + parent[$abstract].check(dejavu); + } + + // Handle interfaces + if (hasOwn(params, '$implements')) { + handleInterfaces(params.$implements, dejavu); + delete dejavu.prototype.$implements; + } + + // Remove abstracts reference + if (hasOwn(params, '$abstracts')) { + delete params.$abstracts; + } + + // Supply .extend() to easily extend a class + dejavu.extend = extend; + + // Prevent any properties/methods to be added and deleted + if (hasDefineProperty) { + protectConstructor(dejavu); + } + + return dejavu; + }; + + /** + * Function to declare a class. + * This function can be called with various formats. + * + * @param {Function|Object} arg1 A class to extend or an object/function to obtain the members + * @param {Function|Object} arg2 Object/function to obtain the members + * + * @return {Function} The constructor + */ + Class.declare = function (arg1, arg2, $arg3) { + var params, + callable = isFunction(this) ? this : createClass, + tmp, + constructor; + + if (arg1 && arg2 && arg2 !== true) { + if (!isFunction(arg1) || !arg1[$class]) { + throw new Error('Expected first argument to be a class.'); + } + + // create(parentClass, func | props, true | false) + if ((tmp = isFunction(arg2)) || $arg3) { + constructor = createConstructor(); + params = tmp ? arg2(arg1.prototype, arg1, constructor) : arg2; + // create(parentClass, props, false) + } else { + params = arg2; + } + + if (params.$extends) { + throw new Error('Object cannot contain an $extends property.'); + } + + params.$extends = arg1; + // create(func | props, true | false) + } else if ((tmp = isFunction(arg1)) || arg2) { + constructor = createConstructor(); + params = tmp ? arg1(constructor) : arg1; + // create (props) + } else { + params = arg1; + } + + // Validate params as an object + if (!isObject(params)) { + throw new Error('Expected class definition to be an object with the class members.'); + } + + return callable(params, constructor); + }; + + // Add a reference to the createFunction method to be used by other files + obfuscateProperty(Class, '$create', createClass); + + // Add custom bound function to supply binds + if (!Function.prototype.$bound || !Function.prototype.$bound.dejavu) { + try { + obfuscateProperty(Function.prototype, '$bound', function () { + this[$bound] = true; + + return this; + }); + Function.prototype.$bound.dejavu = true; + } catch (e) { + printWarning('Could not set Function.prototype.$bound.'); + } + } + + // Add custom bind function to supply binds + if (!Function.prototype.$bind || !Function.prototype.$bind.dejavu) { + try { + obfuscateProperty(Function.prototype, '$bind', function (context) { + var args = toArray(arguments); + args.splice(0, 1, this); + + if (isFunction(context)) { + return doBindStatic.apply(context, args); + } + + return doBind.apply(context, args); + }); + Function.prototype.$bind.dejavu = true; + } catch (e) { + printWarning('Could not set Function.prototype.$bind.'); + } + } + + // Add custom member function to supply marking a function as part of the class + if (!Function.prototype.$member || !Function.prototype.$member.dejavu) { + try { + obfuscateProperty(Function.prototype, '$member', function () { + return doMember(this); + }); + Function.prototype.$member.dejavu = true; + } catch (e) { + printWarning('Could not set Function.prototype.$member.'); + } + } + + return Class; +}); + +/*jshint regexp:false*/ + +define('lib/isFunctionEmpty',[], function () { + + 'use strict'; + + /** + * Check if a function has no body. + * + * @param {Function} func The function + * + * @return {Boolean} True if it's empty, false otherwise + */ + function isFunctionEmpty(func) { + return (/^function\s*\([^\(]*\)\s*\{\s*(["']use strict["'];)?\s*\}$/m).test(func.toString()); + } + + return isFunctionEmpty; +}); + +define('AbstractClass',[ + 'mout/lang/isObject', + 'mout/lang/isFunction', + 'mout/lang/isString', + 'mout/lang/toArray', + 'mout/function/bind', + './lib/functionMeta', + './lib/isFunctionEmpty', + './lib/isFunctionCompatible', + './lib/checkKeywords', + './lib/testKeywords', + './lib/checkObjectPrototype', + './lib/hasDefineProperty', + './lib/randomAccessor', + './lib/mixIn', + 'mout/object/hasOwn', + 'mout/array/insert', + './Class' +], function AbstractClassWrapper( + isObject, + isFunction, + isString, + toArray, + bind, + functionMeta, + isFunctionEmpty, + isFunctionCompatible, + checkKeywords, + testKeywords, + checkObjectPrototype, + hasDefineProperty, + randomAccessor, + mixIn, + hasOwn, + insert, + Class +) { + + 'use strict'; + + var random = randomAccessor('AbstractClassWrapper'), + $class = '$class_' + random, + $interface = '$interface_' + random, + $abstract = '$abstract_' + random, + $bound = '$bound_' + random, + AbstractClass = {}; + + checkObjectPrototype(); + + /** + * Add an abstract method to an abstract class. + * This method will throw an error if something is not right. + * Valid options: + * - isStatic: true|false Defaults to false + * + * @param {String} name The method name + * @param {Function} method The method itself + * @param {Object} constructor The class constructor + * @param {Object} [opts] The options, defaults to {} + */ + function addMethod(name, method, constructor, opts) { + var metadata, + isStatic = opts && opts.isStatic, + target; + + // Check if it is a private member + if (name.substr(0, 2) === '__') { + throw new Error('Abstract class "' + constructor.prototype.$name + '" contains an unallowed abstract ' + (isStatic ? 'static ' : '') + 'private method: "' + name + '".'); + } + // Check if it contains implementation + if (!isFunctionEmpty(method)) { + throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '" must be anonymous and contain no implementation in abstract class "' + constructor.prototype.$name + '".'); + } + + target = isStatic ? constructor : constructor.prototype; + + // Check if function is ok + metadata = functionMeta(method, name); + if (metadata === null) { + throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '" contains optional arguments before mandatory ones in abstract class "' + constructor.prototype.$name + '".'); + } + + // Check if a variable exists with the same name + target = isStatic ? constructor[$class].staticProperties : constructor[$class].properties; + if (isObject(target[name])) { + throw new Error('Abstract method "' + name + '" defined in abstract class "' + constructor.prototype.$name + '" conflicts with an already defined property.'); + } + + + target = isStatic ? constructor[$class].staticMethods : constructor[$class].methods; + + // Check if it is already implemented + if (isObject(target[name])) { + throw new Error('Abstract method "' + name + '" defined in abstract class "' + constructor.prototype.$name + '" seems to be already implemented and cannot be declared as abstract anymore.'); + } + + target = isStatic ? constructor[$abstract].staticMethods : constructor[$abstract].methods; + + // Check if the method already exists and if it's compatible + if (isObject(target[name])) { + if (!isFunctionCompatible(metadata, target[name])) { + throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '(' + metadata.signature + ')" defined in abstract class "' + constructor.prototype.$name + '" overrides its ancestor but it is not compatible with its signature: "' + name + '(' + target[name].signature + ')".'); + } + } + + if (!isStatic && method[$bound]) { + insert(constructor[$class].binds, name); + } + + metadata.checkCompatibility = true; + + target[name] = metadata; + } + + /** + * Checks if an abstract class is well implemented in a class. + * In order to this function to work, it must be bound to an abstract class definition. + * + * @param {Function} target The class to be checked + */ + function checkClass(target) { + /*jshint validthis:true*/ + var key, + value; + + // Check normal functions + for (key in this[$abstract].methods) { + + value = this[$abstract].methods[key]; + + if (!target[$class].methods[key]) { + throw new Error('Class "' + target.prototype.$name + '" does not implement abstract class "' + this.prototype.$name + '" correctly, method "' + key + '" was not found.'); + } + if (!isFunctionCompatible(target[$class].methods[key], value)) { + throw new Error('Method "' + key + '(' + target[$class].methods[key].signature + ')" defined in class "' + target.prototype.$name + '" is not compatible with the one found in abstract class "' + this.prototype.$name + '": "' + key + '(' + value.signature + ').'); + } + } + + // Check static functions + for (key in this[$abstract].staticMethods) { + + value = this[$abstract].staticMethods[key]; + + if (!target[$class].staticMethods[key]) { + throw new Error('Class "' + target.prototype.$name + '" does not implement abstract class "' + this.prototype.$name + '" correctly, static method "' + key + '" was not found.'); + } + if (!isFunctionCompatible(target[$class].staticMethods[key], value)) { + throw new Error('Static method "' + key + '(' + target[$class].staticMethods[key].signature + ')" defined in class "' + target.prototype.$name + '" is not compatible with the one found in abstract class "' + this.prototype.$name + '": "' + key + '(' + value.signature + ').'); + } + } + } + + /** + * Parse abstract methods. + * + * @param {Object} abstracts The object that contains the abstract methods + * @param {Function} constructor The constructor + */ + function parseAbstracts(abstracts, constructor) { + var optsStatic = { isStatic: true }, + key, + value, + unallowed; + + // Check argument + if (!isObject(abstracts)) { + throw new Error('$abstracts defined in abstract class "' + constructor.prototype.$name + '" must be an object.'); + } + + // Check reserved keywords + checkKeywords(abstracts); + + // Check unallowed keywords + unallowed = testKeywords(abstracts, ['$statics']); + if (unallowed) { + throw new Error('$statics inside $abstracts of abstract class "' + constructor.prototype.$name + '" contains an unallowed keyword: "' + unallowed + '".'); + } + + if (hasOwn(abstracts, '$statics')) { + // Check argument + if (!isObject(abstracts.$statics)) { + throw new Error('$statics definition in $abstracts of abstract class "' + constructor.prototype.$name + '" must be an object.'); + } + + // Check keywords + checkKeywords(abstracts.$statics, 'statics'); + + // Check unallowed keywords + unallowed = testKeywords(abstracts.$statics); + if (unallowed) { + throw new Error('$statics inside $abstracts of abstract class "' + constructor.prototype.$name + '" contains an unallowed keyword: "' + unallowed + '".'); + } + + for (key in abstracts.$statics) { + value = abstracts.$statics[key]; + + // Check if it is not a function + if (!isFunction(value) || value[$interface] || value[$class]) { + throw new Error('Abstract member "' + key + '" found in abstract class "' + constructor.prototype.$name + '" is not a function.'); + } + + addMethod(key, value, constructor, optsStatic); + } + + delete abstracts.$statics; + } + + for (key in abstracts) { + value = abstracts[key]; + + // Check if it is not a function + if (!isFunction(value) || value[$interface] || value[$class]) { + throw new Error('Abstract member "' + key + '" found in abstract class "' + constructor.prototype.$name + '" is not a function.'); + } + + addMethod(key, value, constructor); + } + } + + /** + * Parse interfaces. + * + * @param {Array} interfaces The interfaces + * @param {Function} constructor The constructor + */ + function parseInterfaces(interfaces, constructor) { + var interfs = toArray(interfaces), + x = interfs.length, + interf, + key, + value; + + for (x -= 1; x >= 0; x -= 1) { + interf = interfs[x]; + + // Grab methods + for (key in interf[$interface].methods) { + + value = interf[$interface].methods[key]; + + // Check if method is already defined as abstract and is compatible + if (constructor[$abstract].methods[key]) { + if (!isFunctionCompatible(constructor[$abstract].methods[key], value)) { + throw new Error('Method "' + key + '( ' + value.signature + ')" described in interface "' + interf.prototype.$name + '" is not compatible with the one already defined in "' + constructor.prototype.$name + '": "' + key + '(' + constructor[$abstract].methods[key].signature + ')".'); + } + } else { + constructor[$abstract].methods[key] = interf[$interface].methods[key]; + } + } + + // Grab static methods + for (key in interf[$interface].staticMethods) { + + value = interf[$interface].staticMethods[key]; + + // Check if method is already defined as abstract and is compatible + if (constructor[$abstract].staticMethods[key]) { + if (!isFunctionCompatible(constructor[$abstract].staticMethods[key], value)) { + throw new Error('Static method "' + key + '( ' + value.signature + ')" described in interface "' + interf.prototype.$name + '" is not compatible with the one already defined in "' + constructor.prototype.$name + '": "' + key + '(' + constructor[$abstract].staticMethods[key].signature + ')".'); + } + } else { + constructor[$abstract].staticMethods[key] = value; + } + } + } + } + + /** + * Create an abstract class definition. + * + * @param {Object} params An object containing methods and properties + * @param {Constructor} [constructor] Assume the passed constructor + * + * @return {Function} The constructor + */ + function createAbstractClass(params, constructor) { + if (!isObject(params)) { + throw new Error('Expected abstract class definition to be an object with the abstract class members.'); + } + // Validate class name + if (hasOwn(params, '$name')) { + if (!isString(params.$name)) { + throw new Error('Abstract class name must be a string.'); + } else if (/\s+/.test(params.$name)) { + throw new Error('Abstract class name cannot have spaces.'); + } + } else { + params.$name = 'Unnamed'; + } + + var def, + abstractObj = { methods: {}, staticMethods: {}, unimplemented: 0 }, + saved = {}, + key; + + // If we are extending an abstract class also, inherit the abstract methods + if (isFunction(params.$extends)) { + if (params.$extends[$abstract]) { + mixIn(abstractObj.methods, params.$extends[$abstract].methods); + mixIn(abstractObj.staticMethods, params.$extends[$abstract].staticMethods); + } + } + + // Handle abstract methods + if (hasOwn(params, '$abstracts')) { + saved.$abstracts = params.$abstracts; // Save them for later use + } + + // Handle interfaces + if (hasOwn(params, '$implements')) { + saved.$interfaces = params.$implements; // Save them for later use + } + + // Create the class definition + def = Class.$create(params, constructor, { isAbstract: true }); + + abstractObj.check = bind(checkClass, def); + + if (hasDefineProperty) { + Object.defineProperty(def, $abstract, { + value: abstractObj, + writable: false + }); + } else { + def[$abstract] = abstractObj; + } + + // Parse the saved interfaces + if (hasOwn(saved, '$interfaces')) { + parseInterfaces(saved.$interfaces, def); + } + + // Parse the abstract methods + if (hasOwn(saved, '$abstracts')) { + parseAbstracts(saved.$abstracts, def); + } + + // Finally update the unimplemented count + for (key in def[$abstract].methods) { + if (!def[$class].methods[key]) { + abstractObj.unimplemented += 1; + } + } + for (key in def[$abstract].staticMethods) { + if (!def[$class].staticMethods[key]) { + abstractObj.unimplemented += 1; + } + } + + return def; + } + + /** + * Function to declare an abstract class. + * This function can be called with various formats. + * The first parameter can be a class to extend. + * The second parameter must be an object containing the class members or a function to obtain it. + * + * @param {Function|Object} arg1 A class, an object or a function + * @param {Function|Object} arg2 Object containing the class members or a function to obtain it. + * + * @return {Function} The constructor + */ + AbstractClass.declare = function (arg1, arg2, $arg3) { + return Class.declare.call(createAbstractClass, arg1, arg2, $arg3); + }; + + return AbstractClass; +}); + +define('Interface',[ + 'mout/lang/isObject', + 'mout/lang/isArray', + 'mout/lang/isString', + 'mout/function/bind', + 'mout/array/intersection', + 'mout/array/unique', + 'mout/array/compact', + 'mout/object/keys', + './lib/checkKeywords', + './lib/testKeywords', + './lib/functionMeta', + './lib/isFunctionEmpty', + './lib/isFunctionCompatible', + './lib/checkObjectPrototype', + './lib/obfuscateProperty', + './lib/randomAccessor', + './lib/isImmutable', + './lib/hasDefineProperty', + './lib/mixIn', + 'mout/lang/isFunction', + 'mout/object/hasOwn', + 'mout/lang/toArray' +], function InterfaceWrapper( + isObject, + isArray, + isString, + bind, + intersection, + unique, + compact, + keys, + checkKeywords, + testKeywords, + functionMeta, + isFunctionEmpty, + isFunctionCompatible, + checkObjectPrototype, + obfuscateProperty, + randomAccessor, + isImmutable, + hasDefineProperty, + mixIn, + isFunction, + hasOwn, + toArray +) { + + 'use strict'; + + var random = randomAccessor('InterfaceWrapper'), + $class = '$class_' + random, + $interface = '$interface_' + random, + Interface = {}; + + checkObjectPrototype(); + + /** + * Checks if an interface is well implemented in a class. + * In order to this function to work, it must be bound to an interface definition. + * + * @param {Function} target The class to be checked + */ + function checkClass(target) { + /*jshint validthis:true*/ + var key, + value; + + // Check normal functions + for (key in this[$interface].methods) { + value = this[$interface].methods[key]; + + if (!target[$class].methods[key]) { + throw new Error('Class "' + target.prototype.$name + '" does not implement interface "' + this.prototype.$name + '" correctly, method "' + key + '" was not found.'); + } + if (!isFunctionCompatible(target[$class].methods[key], value)) { + throw new Error('Method "' + key + '(' + target[$class].methods[key].signature + ')" defined in class "' + target.prototype.$name + '" is not compatible with the one found in interface "' + this.prototype.$name + '": "' + key + '(' + value.signature + ').'); + } + } + + // Check static functions + for (key in this[$interface].staticMethods) { + + value = this[$interface].staticMethods[key]; + + if (!target[$class].staticMethods[key]) { + throw new Error('Class "' + target.prototype.$name + '" does not implement interface "' + this.prototype.$name + '" correctly, static method "' + key + '" was not found.'); + } + if (!isFunctionCompatible(target[$class].staticMethods[key], value)) { + throw new Error('Static method "' + key + '(' + target[$class].staticMethods[key].signature + ')" defined in class "' + target.prototype.$name + '" is not compatible with the one found in interface "' + this.prototype.$name + '": "' + key + '(' + value.signature + ').'); + } + } + } + + /** + * Adds a method to an interface. + * This method will throw an error if something is not right. + * Valid options: + * - isStatic: true|false Defaults to false + * + * @param {String} name The method name + * @param {Function} method The method itself + * @param {Function} interf The interface in which the method metadata will be saved + * @param {Object} [opts] The options (defaults to {}) + */ + function addMethod(name, method, interf, opts) { + var metadata, + isStatic = opts && opts.isStatic, + target; + + // Check if it is not a function + if (!isFunction(method) || method[$interface] || method[$class]) { + throw new Error('Member "' + name + '" found in interface "' + interf.prototype.$name + '" is not a function.'); + } + // Check if it is public + if (name.charAt(0) === '_') { + throw new Error('Interface "' + interf.prototype.$name + '" contains an unallowed non public method: "' + name + '".'); + } + // Check if it contains no implementation + if (!isFunctionEmpty(method)) { + throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '" must be anonymous and contain no implementation in interface "' + interf.prototype.$name + '".'); + } + // Check if function is ok + metadata = functionMeta(method, name); + if (metadata === null) { + throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '" contains optional arguments before mandatory ones in interface "' + interf.prototype.$name + '".'); + } + + target = isStatic ? interf[$interface].staticMethods : interf[$interface].methods; + + // Check if the method already exists and it's compatible + if (isObject(target[name])) { + if (!isFunctionCompatible(metadata, target[name])) { + throw new Error((isStatic ? 'Static method' : 'Method') + ' "' + name + '(' + metadata.signature + ')" defined in interface "' + interf.prototype.$name + '" overrides its ancestor but it is not compatible with its signature: "' + name + '(' + target[name].signature + ')".'); + } + } + + target[name] = metadata; + } + + /** + * Assigns a constant to the interface. + * This method will protect the constant from being changed. + * + * @param {String} name The constant name + * @param {Function} value The constant value + * @param {Function} interf The interface in which the constant will be saved + */ + function assignConstant(name, value, interf) { + if (hasDefineProperty) { + Object.defineProperty(interf, name, { + get: function () { + return value; + }, + set: function () { + throw new Error('Cannot change value of constant property "' + name + '" of interface "' + this.prototype.$name + '".'); + }, + configurable: false, + enumerable: true + }); + } else { + interf[name] = value; + } + } + + /** + * Adds a constant to an interface. + * This method will throw an error if something is not right. + * + * @param {String} name The constant name + * @param {Function} value The constant value + * @param {Function} interf The interface in which the constant will be saved + */ + function addConstant(name, value, interf) { + var target; + + // Check if it is public + if (name.charAt(0) === '_') { + throw new Error('Interface "' + interf.prototype.$name + '" contains an unallowed non public method: "' + name + '".'); + } + // Check if it is a primitive value + if (!isImmutable(value)) { + throw new Error('Value for constant property "' + name + '" defined in interface "' + interf.prototype.$name + '" must be a primitive type.'); + } + + target = interf[$interface].constants; + + // Check if the constant already exists + if (target[name]) { + throw new Error('Cannot override constant property "' + name + '" in interface "' + interf.prototype.$name + '".'); + } + + target[name] = true; + assignConstant(name, value, interf); + } + + /** + * Function to easily extend another interface. + * + * @param {Object} params An object containing methods and properties + * + * @return {Function} The new interface + */ + function extend(params) { + /*jshint validthis:true*/ + if (params.$extends) { + throw new Error('Object passed cannot contain an $extends property.'); + } + + params.$extends = this; + + return Interface.declare(params); + } + + /** + * Create an interface definition. + * + * @param {Object} params An object containing methods and properties + * + * @return {Function} The constructor + */ + function createInterface(params) { + // Validate params as an object + if (!isObject(params)) { + throw new Error('Expected interface definition to be an object with the interface members.'); + } + // Validate class name + if (hasOwn(params, '$name')) { + if (!isString(params.$name)) { + throw new Error('Interface name must be a string.'); + } else if (/\s+/.test(params.$name)) { + throw new Error('Interface name cannot have spaces.'); + } + } else { + params.$name = 'Unnamed'; + } + + checkKeywords(params); + + var parents, + current, + k, + i, + value, + duplicate, + opts = {}, + name, + ambiguous, + unallowed, + interf = function () { + throw new Error('Interfaces cannot be instantiated.'); + }; + + obfuscateProperty(interf, $interface, { parents: [], methods: {}, staticMethods: {}, constants: {}, check: bind(checkClass, interf) }); + interf.prototype.$name = params.$name; + + if (hasOwn(params, '$extends')) { + parents = toArray(params.$extends); + k = parents.length; + + // Verify argument type + if (!k && !isArray(params.$extends)) { + throw new Error('$extends of "' + params.$name + '" seems to point to an nonexistent interface.'); + } + // Verify duplicate entries + if (k !== unique(parents).length && compact(parents).length === k) { + throw new Error('There are duplicate entries defined in $extends of "' + params.$name + '".'); + } + + for (k -= 1; k >= 0; k -= 1) { + current = parents[k]; + + // Check if it is a valid interface + if (!isFunction(current) || !current[$interface]) { + throw new Error('Specified interface in $extends at index ' + k + ' of "' + params.$name + '" is not a valid interface.'); + } + + // Merge methods + duplicate = intersection(keys(interf[$interface].methods), keys(current[$interface].methods)); + i = duplicate.length; + if (i) { + for (i -= 1; i >= 0; i -= 1) { + if (!isFunctionCompatible(interf[$interface].methods[duplicate[i]], current[$interface].methods[duplicate[i]]) && + !isFunctionCompatible(current[$interface].methods[duplicate[i]], interf[$interface].methods[duplicate[i]])) { + throw new Error('Interface "' + params.$name + '" is inheriting method "' + duplicate[i] + '" from different parents with incompatible signatures.'); + } + } + } + mixIn(interf[$interface].methods, current[$interface].methods); + + // Merge static methods + duplicate = intersection(keys(interf[$interface].staticMethods), keys(current[$interface].staticMethods)); + i = duplicate.length; + if (i) { + for (i -= 1; i >= 0; i -= 1) { + if (!isFunctionCompatible(interf[$interface].staticMethods[duplicate[i]], current[$interface].staticMethods[duplicate[i]]) && + !isFunctionCompatible(current[$interface].staticMethods[duplicate[i]], interf[$interface].staticMethods[duplicate[i]])) { + throw new Error('Interface "' + params.$name + '" is inheriting static method "' + duplicate[i] + '" from different parents with incompatible signatures.'); + } + } + } + mixIn(interf[$interface].staticMethods, current[$interface].staticMethods); + + // Add interface constants + for (i in current[$interface].constants) { + if (interf[$interface].constants[i]) { + if (interf[i] !== current[i]) { + throw new Error('Interface "' + params.$name + '" is inheriting constant property "' + i + '" from different parents with different values.'); + } + } else { + interf[$interface].constants[i] = current[$interface].constants[i]; + assignConstant(i, current[i], interf); + } + } + + // Add interface to the parents + interf[$interface].parents.push(current); + } + + delete params.$extends; + } + + // Check if the interface defines the initialize function + if (hasOwn(params, 'initialize')) { + throw new Error('Interface "' + params.$name + '" can\'t define the initialize method.'); + } + + // Parse constants + if (hasOwn(params, '$constants')) { + // Check argument + if (!isObject(params.$constants)) { + throw new Error('$constants definition of interface "' + params.$name + '" must be an object.'); + } + + // Check reserved keywords + checkKeywords(params.$constants, 'statics'); + + // Check unallowed keywords + unallowed = testKeywords(params.$constants); + if (unallowed) { + throw new Error('$constants of interface "' + interf.prototype.$name + '" contains an unallowed keyword: "' + unallowed + '".'); + } + + // Check ambiguity + if (hasOwn(params, '$statics')) { + ambiguous = intersection(keys(params.$constants), keys(params.$statics)); + if (ambiguous.length) { + throw new Error('There are members defined in interface "' + params.$name + '" with the same name but with different modifiers: "' + ambiguous.join('", ') + '".'); + } + } + + for (k in params.$constants) { + addConstant(k, params.$constants[k], interf); + } + + delete params.$constants; + } + + // Parse statics + if (hasOwn(params, '$statics')) { + // Check argument + if (!isObject(params.$statics)) { + throw new Error('$statics definition of interface "' + params.$name + '" must be an object.'); + } + + // Check reserved keywords + checkKeywords(params.$statics, 'statics'); + + // Check unallowed keywords + unallowed = testKeywords(params.$statics); + if (unallowed) { + throw new Error('$statics of interface "' + interf.prototype.$name + '" contains an unallowed keyword: "' + unallowed + '".'); + } + + opts.isStatic = true; + + for (k in params.$statics) { + value = params.$statics[k]; + + // Check if it is not a function + if (!isFunction(value) || value[$interface] || value[$class]) { + throw new Error('Static member "' + k + '" found in interface "' + params.$name + '" is not a function.'); + } + + addMethod(k, value, interf, opts); + } + + delete opts.isStatic; + delete params.$statics; + } + + name = params.$name; + delete params.$name; + + // Check unallowed keywords + unallowed = testKeywords(params, ['$extends', '$statics', '$constants']); + if (unallowed) { + throw new Error('$statics of interface "' + interf.prototype.$name + '" contains an unallowed keyword: "' + unallowed + '".'); + } + + for (k in params) { + addMethod(k, params[k], interf); + } + + params.$name = name; + + // Supply .extend() to easily extend an interface + interf.extend = extend; + + return interf; + } + + /** + * Function to declare an Interface. + * + * @param {Object} obj An object containing the interface members. + * + * @return {Function} The Interface + */ + Interface.declare = createInterface; + + return Interface; +}); + +/*jshint laxcomma:true*/ + +define('FinalClass',[ + './Class' + , './lib/randomAccessor' + , './lib/checkObjectPrototype' +], function FinalClassWrapper( + Class + , randomAccessor + , checkObjectPrototype +) { + + 'use strict'; + + checkObjectPrototype(); + + var random = randomAccessor('FinalClassWrapper'), + $class = '$class_' + random, + FinalClass = {}; + + /** + * Create a final class definition. + * + * @param {Object} params An object containing methods and properties + * @param {Constructor} [constructor] Assume the passed constructor + * + * @return {Function} The constructor + */ + function createFinalClass(params, constructor) { + var def = Class.$create(params, constructor); + def[$class].finalClass = true; + + return def; + } + + /** + * Function to declare a final class. + * This function can be called with various formats. + * + * @param {Function|Object} arg1 A class to extend or an object/function to obtain the members + * @param {Function|Object} arg2 Object/function to obtain the members + * + * @return {Function} The constructor + */ + FinalClass.declare = function (arg1, arg2, $arg3) { + return Class.declare.call(createFinalClass, arg1, arg2, $arg3); + }; + + return FinalClass; +}); + +define('instanceOf',[ + './lib/randomAccessor' +], function instanceOfWrapper( + randomAccessor +) { + + 'use strict'; + + var random = randomAccessor('instanceOfWrapper'), + $class = '$class_' + random, + $interface = '$interface_' + random; + + /** + * Check if an interface is descendant of another. + * + * @param {Function} interf1 The interface to be checked + * @param {Function} interf2 The interface to be expected as the ancestor + * + * @return {Boolean} True if it's a descendant, false otherwise + */ + function interfaceDescendantOf(interf1, interf2) { + var x, + parents = interf1[$interface].parents; + + for (x = parents.length - 1; x >= 0; x -= 1) { + if (parents[x] === interf2) { + return true; + } + if (interfaceDescendantOf(interf1, parents[x])) { + return true; + } + } + + return false; + } + + /** + * Check if an instance of a class is an instance of an interface. + * + * @param {Object} instance The instance to be checked + * @param {Function} target The interface + * + * @return {Boolean} True if it is, false otherwise + */ + function instanceOfInterface(instance, target) { + var x, + interfaces = instance.$static[$class].interfaces; + + for (x = interfaces.length - 1; x >= 0; x -= 1) { + if (interfaces[x] === target || interfaceDescendantOf(interfaces[x], target)) { + return true; + } + } + + return false; + } + + /** + * Custom instanceOf that also works on interfaces. + * + * @param {Object} instance The instance to be checked + * @param {Function} target The target + * + * @return {Boolean} True if it is a valid instance of target, false otherwise + */ + function instanceOf(instance, target) { + if (instance instanceof target) { + return true; + } + + if (instance && instance.$static && instance.$static[$class] && target && target[$interface]) { + return instanceOfInterface(instance, target); + } + + return false; + } + + return instanceOf; +}); +define('dejavu',[ + './Class', + './AbstractClass', + './Interface', + './FinalClass', + './instanceOf', + './options' +], function ( + Class, + AbstractClass, + Interface, + FinalClass, + instanceOf, + options +) { + + 'use strict'; + + var dejavu = {}; + + dejavu.Class = Class; + dejavu.AbstractClass = AbstractClass; + dejavu.Interface = Interface; + dejavu.FinalClass = FinalClass; + dejavu.instanceOf = instanceOf; + dejavu.options = options; + + dejavu.mode = 'strict'; + window.dejavu = dejavu; +}); + +require('dejavu', null, null, true); + +}()); \ No newline at end of file diff --git a/src/core/static/js/formWithAjaxSteps.js b/src/core/static/js/formWithAjaxSteps.js new file mode 100644 index 0000000..58b27f9 --- /dev/null +++ b/src/core/static/js/formWithAjaxSteps.js @@ -0,0 +1,95 @@ +$(function(){ + // TODO: localizzare stringhe + var progressPart, progress, steps, stepPos, stepResult, ajaxUrl; + + function openExportDialog() { + window.onbeforeunload = exitWarning; + $( "#progress_bar" ).modal({ overlayCss: {background: "#000"}, overlayClose: false, closeHTML:'' }); + } + + function closeExportDialog() { + window.onbeforeunload = null; + $.modal.close(); + resetProgressBar(); + } + + function exitWarning(e) { + var msg = 'Attenzione, uscendo da questa pagina verra\' interrotto il processo!'; + e = e || window.event; + // For IE and Firefox prior to version 4 + if (e) { + e.returnValue = msg; + } + // For Safari + return msg; + }; + + function resetProgressBar() { + jQuery.fx.off = true; + $('#progress_bar .ui-progress').width("0%"); + $('#progress_bar .ui-label').hide(); + }; + + function execStep() { + progress += progressPart; + $('#progress_bar .ui-progress').animateProgress( progress ); + + if ( stepPos == steps.length-1 ) + { + closeExportDialog(); + if (steps[ stepPos ].url) { + location.href = steps[ stepPos ].url; + } else if (steps[ stepPos ].message) { + alert(steps[ stepPos ].message); + } + return; + } + + // per ogni azione esegue una richiesta ajax + jQuery.ajax( { + url: ajaxUrl+steps[ stepPos ].action, + data: steps[ stepPos ].params, + dataType: "json", + success: function( data ){ + stepResult = data; + stepPos++; + execStep(); + } } ); + + } + + Glizy.startAjaxSteps = function(data, cb, getSteps) { + ajaxUrl = $('.js-glizycms-FormEditWithAjaxSteps').data('ajaxurl'); + openExportDialog(); + getSteps = getSteps || 'getSteps'; + + $.ajax({ + url: ajaxUrl+getSteps, + data: data, + dataType: 'json', + success: function( data ) { + if (cb && !cb(data)) { + closeExportDialog(); + return; + } + if ( data.status) + { + if (data.result.length) { + progressPart = 100 / (data.result.length - 1); + progress = 0; + stepPos = 0; + steps = data.result; + execStep(); + } else { + closeExportDialog(); + } + } + else + { + closeExportDialog(); + alert( 'Si è verificato un errore' ); + } + } + }); + }; +}); \ No newline at end of file diff --git a/src/core/static/js/jquery-simplemodal/jquery.simplemodal.1.4.1.min.js b/src/core/static/js/jquery-simplemodal/jquery.simplemodal.1.4.1.min.js new file mode 100644 index 0000000..479721d --- /dev/null +++ b/src/core/static/js/jquery-simplemodal/jquery.simplemodal.1.4.1.min.js @@ -0,0 +1,25 @@ +/* + * SimpleModal 1.4.1 - jQuery Plugin + * http://www.ericmmartin.com/projects/simplemodal/ + * Copyright (c) 2010 Eric Martin (http://twitter.com/ericmmartin) + * Dual licensed under the MIT and GPL licenses + * Revision: $Id: jquery.simplemodal.js 261 2010-11-05 21:16:20Z emartin24 $ + */ +(function(d){var k=d.browser.msie&&parseInt(d.browser.version)===6&&typeof window.XMLHttpRequest!=="object",m=d.browser.msie&&parseInt(d.browser.version)===7,l=null,f=[];d.modal=function(a,b){return d.modal.impl.init(a,b)};d.modal.close=function(){d.modal.impl.close()};d.modal.focus=function(a){d.modal.impl.focus(a)};d.modal.setContainerDimensions=function(){d.modal.impl.setContainerDimensions()};d.modal.setPosition=function(){d.modal.impl.setPosition()};d.modal.update=function(a,b){d.modal.impl.update(a, +b)};d.fn.modal=function(a){return d.modal.impl.init(this,a)};d.modal.defaults={appendTo:"body",focus:true,opacity:50,overlayId:"simplemodal-overlay",overlayCss:{},containerId:"simplemodal-container",containerCss:{},dataId:"simplemodal-data",dataCss:{},minHeight:null,minWidth:null,maxHeight:null,maxWidth:null,autoResize:false,autoPosition:true,zIndex:1E3,close:true,closeHTML:'<a class="modalCloseImg" title="Close"></a>',closeClass:"simplemodal-close",escClose:true,overlayClose:false,position:null, +persist:false,modal:true,onOpen:null,onShow:null,onClose:null};d.modal.impl={d:{},init:function(a,b){var c=this;if(c.d.data)return false;l=d.browser.msie&&!d.boxModel;c.o=d.extend({},d.modal.defaults,b);c.zIndex=c.o.zIndex;c.occb=false;if(typeof a==="object"){a=a instanceof jQuery?a:d(a);c.d.placeholder=false;if(a.parent().parent().size()>0){a.before(d("<span></span>").attr("id","simplemodal-placeholder").css({display:"none"}));c.d.placeholder=true;c.display=a.css("display");if(!c.o.persist)c.d.orig= +a.clone(true)}}else if(typeof a==="string"||typeof a==="number")a=d("<div></div>").html(a);else{alert("SimpleModal Error: Unsupported data type: "+typeof a);return c}c.create(a);c.open();d.isFunction(c.o.onShow)&&c.o.onShow.apply(c,[c.d]);return c},create:function(a){var b=this;f=b.getDimensions();if(b.o.modal&&k)b.d.iframe=d('<iframe src="javascript:false;"></iframe>').css(d.extend(b.o.iframeCss,{display:"none",opacity:0,position:"fixed",height:f[0],width:f[1],zIndex:b.o.zIndex,top:0,left:0})).appendTo(b.o.appendTo); +b.d.overlay=d("<div></div>").attr("id",b.o.overlayId).addClass("simplemodal-overlay").css(d.extend(b.o.overlayCss,{display:"none",opacity:b.o.opacity/100,height:b.o.modal?f[0]:0,width:b.o.modal?f[1]:0,position:"fixed",left:0,top:0,zIndex:b.o.zIndex+1})).appendTo(b.o.appendTo);b.d.container=d("<div></div>").attr("id",b.o.containerId).addClass("simplemodal-container").css(d.extend(b.o.containerCss,{display:"none",position:"fixed",zIndex:b.o.zIndex+2})).append(b.o.close&&b.o.closeHTML?d(b.o.closeHTML).addClass(b.o.closeClass): +"").appendTo(b.o.appendTo);b.d.wrap=d("<div></div>").attr("tabIndex",-1).addClass("simplemodal-wrap").css({height:"100%",outline:0,width:"100%"}).appendTo(b.d.container);b.d.data=a.attr("id",a.attr("id")||b.o.dataId).addClass("simplemodal-data").css(d.extend(b.o.dataCss,{display:"none"})).appendTo("body");b.setContainerDimensions();b.d.data.appendTo(b.d.wrap);if(k||l)b.fixIE()},bindEvents:function(){var a=this;d("."+a.o.closeClass).bind("click.simplemodal",function(b){b.preventDefault();a.close()}); +a.o.modal&&a.o.close&&a.o.overlayClose&&a.d.overlay.bind("click.simplemodal",function(b){b.preventDefault();a.close()});d(document).bind("keydown.simplemodal",function(b){if(a.o.modal&&b.keyCode===9)a.watchTab(b);else if(a.o.close&&a.o.escClose&&b.keyCode===27){b.preventDefault();a.close()}});d(window).bind("resize.simplemodal",function(){f=a.getDimensions();a.o.autoResize?a.setContainerDimensions():a.o.autoPosition&&a.setPosition();if(k||l)a.fixIE();else if(a.o.modal){a.d.iframe&&a.d.iframe.css({height:f[0], +width:f[1]});a.d.overlay.css({height:f[0],width:f[1]})}})},unbindEvents:function(){d("."+this.o.closeClass).unbind("click.simplemodal");d(document).unbind("keydown.simplemodal");d(window).unbind("resize.simplemodal");this.d.overlay.unbind("click.simplemodal")},fixIE:function(){var a=this,b=a.o.position;d.each([a.d.iframe||null,!a.o.modal?null:a.d.overlay,a.d.container],function(c,h){if(h){var g=h[0].style;g.position="absolute";if(c<2){g.removeExpression("height");g.removeExpression("width");g.setExpression("height", +'document.body.scrollHeight > document.body.clientHeight ? document.body.scrollHeight : document.body.clientHeight + "px"');g.setExpression("width",'document.body.scrollWidth > document.body.clientWidth ? document.body.scrollWidth : document.body.clientWidth + "px"')}else{var e;if(b&&b.constructor===Array){c=b[0]?typeof b[0]==="number"?b[0].toString():b[0].replace(/px/,""):h.css("top").replace(/px/,"");c=c.indexOf("%")===-1?c+' + (t = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"': +parseInt(c.replace(/%/,""))+' * ((document.documentElement.clientHeight || document.body.clientHeight) / 100) + (t = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"';if(b[1]){e=typeof b[1]==="number"?b[1].toString():b[1].replace(/px/,"");e=e.indexOf("%")===-1?e+' + (t = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft) + "px"':parseInt(e.replace(/%/,""))+' * ((document.documentElement.clientWidth || document.body.clientWidth) / 100) + (t = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft) + "px"'}}else{c= +'(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (t = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"';e='(document.documentElement.clientWidth || document.body.clientWidth) / 2 - (this.offsetWidth / 2) + (t = document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft) + "px"'}g.removeExpression("top");g.removeExpression("left");g.setExpression("top", +c);g.setExpression("left",e)}}})},focus:function(a){var b=this;a=a&&d.inArray(a,["first","last"])!==-1?a:"first";var c=d(":input:enabled:visible:"+a,b.d.wrap);setTimeout(function(){c.length>0?c.focus():b.d.wrap.focus()},10)},getDimensions:function(){var a=d(window);return[d.browser.opera&&d.browser.version>"9.5"&&d.fn.jquery<"1.3"||d.browser.opera&&d.browser.version<"9.5"&&d.fn.jquery>"1.2.6"?a[0].innerHeight:a.height(),a.width()]},getVal:function(a,b){return a?typeof a==="number"?a:a==="auto"?0: +a.indexOf("%")>0?parseInt(a.replace(/%/,""))/100*(b==="h"?f[0]:f[1]):parseInt(a.replace(/px/,"")):null},update:function(a,b){var c=this;if(!c.d.data)return false;c.d.origHeight=c.getVal(a,"h");c.d.origWidth=c.getVal(b,"w");c.d.data.hide();a&&c.d.container.css("height",a);b&&c.d.container.css("width",b);c.setContainerDimensions();c.d.data.show();c.o.focus&&c.focus();c.unbindEvents();c.bindEvents()},setContainerDimensions:function(){var a=this,b=k||m,c=a.d.origHeight?a.d.origHeight:d.browser.opera? +a.d.container.height():a.getVal(b?a.d.container[0].currentStyle.height:a.d.container.css("height"),"h");b=a.d.origWidth?a.d.origWidth:d.browser.opera?a.d.container.width():a.getVal(b?a.d.container[0].currentStyle.width:a.d.container.css("width"),"w");var h=a.d.data.outerHeight(true),g=a.d.data.outerWidth(true);a.d.origHeight=a.d.origHeight||c;a.d.origWidth=a.d.origWidth||b;var e=a.o.maxHeight?a.getVal(a.o.maxHeight,"h"):null,i=a.o.maxWidth?a.getVal(a.o.maxWidth,"w"):null;e=e&&e<f[0]?e:f[0];i=i&&i< +f[1]?i:f[1];var j=a.o.minHeight?a.getVal(a.o.minHeight,"h"):"auto";c=c?a.o.autoResize&&c>e?e:c<j?j:c:h?h>e?e:a.o.minHeight&&j!=="auto"&&h<j?j:h:j;e=a.o.minWidth?a.getVal(a.o.minWidth,"w"):"auto";b=b?a.o.autoResize&&b>i?i:b<e?e:b:g?g>i?i:a.o.minWidth&&e!=="auto"&&g<e?e:g:e;a.d.container.css({height:c,width:b});a.d.wrap.css({overflow:h>c||g>b?"auto":"visible"});a.o.autoPosition&&a.setPosition()},setPosition:function(){var a=this,b,c;b=f[0]/2-a.d.container.outerHeight(true)/2;c=f[1]/2-a.d.container.outerWidth(true)/ +2;if(a.o.position&&Object.prototype.toString.call(a.o.position)==="[object Array]"){b=a.o.position[0]||b;c=a.o.position[1]||c}else{b=b;c=c}a.d.container.css({left:c,top:b})},watchTab:function(a){var b=this;if(d(a.target).parents(".simplemodal-container").length>0){b.inputs=d(":input:enabled:visible:first, :input:enabled:visible:last",b.d.data[0]);if(!a.shiftKey&&a.target===b.inputs[b.inputs.length-1]||a.shiftKey&&a.target===b.inputs[0]||b.inputs.length===0){a.preventDefault();b.focus(a.shiftKey?"last": +"first")}}else{a.preventDefault();b.focus()}},open:function(){var a=this;a.d.iframe&&a.d.iframe.show();if(d.isFunction(a.o.onOpen))a.o.onOpen.apply(a,[a.d]);else{a.d.overlay.show();a.d.container.show();a.d.data.show()}a.o.focus&&a.focus();a.bindEvents()},close:function(){var a=this;if(!a.d.data)return false;a.unbindEvents();if(d.isFunction(a.o.onClose)&&!a.occb){a.occb=true;a.o.onClose.apply(a,[a.d])}else{if(a.d.placeholder){var b=d("#simplemodal-placeholder");if(a.o.persist)b.replaceWith(a.d.data.removeClass("simplemodal-data").css("display", +a.display));else{a.d.data.hide().remove();b.replaceWith(a.d.orig)}}else a.d.data.hide().remove();a.d.container.hide().remove();a.d.overlay.hide();a.d.iframe&&a.d.iframe.hide().remove();setTimeout(function(){a.d.overlay.remove();a.d={}},10)}}}})(jQuery); diff --git a/src/core/static/js/jscalendar/ChangeLog.txt b/src/core/static/js/jscalendar/ChangeLog.txt new file mode 100755 index 0000000..dc54b04 --- /dev/null +++ b/src/core/static/js/jscalendar/ChangeLog.txt @@ -0,0 +1,500 @@ +2004-02-06 Mihai Bazon <mishoo@localhost.localdomain> + + * make-release.pl: ChangeLog included in the distribution (if found) + + * calendar.js, doc/reference.tex, index.html: switched to version 0.9.6 + + * doc/Calendar.setup.tex, doc/reference.tex: updated documentation + + * release-notes.html: updated release notes + + * calendar.js: Fixed bug: Feb/29 and year change now keeps Feb in view + + * calendar.js: fixed the "ESC" problem (call the close handler) + + * calendar.js: fixed day of year range (1 to 366 instead of 0 to 365) + + * calendar.js: fixed week number calculations + + * doc/reference.tex: fixed (date input format) + + * calendar.php: removed comment + + * calendar-blue.css, calendar-blue2.css, calendar-brown.css, calendar-green.css, calendar-system.css, calendar-tas.css, calendar-win2k-1.css, calendar-win2k-2.css, calendar-win2k-cold-1.css, calendar-win2k-cold-2.css, calendar.js: + workaround for IE bug (you can't normally specify through CSS the style for + an element having two classes or more; we had to change a classname) + + * calendar-blue.css, calendar-blue2.css, calendar-brown.css, calendar-green.css, calendar-system.css, calendar-tas.css, calendar-win2k-1.css, calendar-win2k-2.css, calendar-win2k-cold-1.css, calendar-win2k-cold-2.css: + smaller fonts on days that are in neighbor months + +2004-02-04 Mihai Bazon <mishoo@localhost.localdomain> + + * index.html: first demo shows the "showOtherMonths" capability + + * calendar-setup.js: support new parameters in the calendar. + added: firstDay, showOthers, cache. + + * calendar-blue.css, calendar-blue2.css, calendar-brown.css, calendar-green.css, calendar-system.css, calendar-win2k-1.css, calendar-win2k-2.css, calendar-win2k-cold-1.css, calendar-win2k-cold-2.css, calendar.js, lang/calendar-en.js, lang/calendar-ro.js: + new parameters: firstDayOfWeek, showsOtherMonths; removed mondayFirst. + This adds support for setting any day to be the first day of week (by just + clicking the day name in the display); also, if showsOtherMonths is enabled + then dates belonging to adjacent months that are in the current view will be + displayed and the calendar will have a fixed height. + + all themes updated. + + * test.php: test for calendar.php + + * calendar.php: fixed bug (pass numeric values as numbers) + +2004-02-01 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar.php: added PHP wrapper + + * img.gif: icon updated + + * TODO: updated TODO list + +2004-01-27 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar.js: + Janusz Piwowarski sent over a patch for IE5 compatibility which is much more + elegant than the atrocities that I had wrote :-D I'm gettin' old.. Thanks Janusz! + + * lang/calendar-fi.js: updated + +2004-01-15 Mihai Bazon <mishoo@localhost.localdomain> + + * TODO: updated TODO list + + * calendar-setup.js: default align changed to "Br" + + * doc/reference.tex: changed default value for "align" + + * calendar-setup.js: calling onchange event handler, if available + + * calendar-setup.js: added "position" option + + * simple-1.html: demonstrates "step" option + + * calendar-setup.js: added "step" option + + * calendar.js: added yearStep config parameter + + * calendar.js: + fixed parseDate routine (the NaN bug which occurred when there was a space + after the date and no time) + +2004-01-14 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-en.js: added "Time:" + + * test-position.html: test for the new position algorithm + + * index.html: do not destroy() the calendar + avoid bug in parseDate (%p must be separated by non-word characters) + + * menuarrow2.gif: for calendar-blue2.css + + * calendar-setup.js: honor "date" parameter if passed + + * calendar.js: IE5 support is back + performance improvements in IE6 (mouseover combo boxes) + display "Time:" beside the clock area, if defined in the language file + new positioning algorithm (try to keep the calendar in page) + rewrote parseDate a little cleaner + + * lang/calendar-el.js: + updated Greek translation (thanks Alexandros Pappas) + +2004-01-13 Mihai Bazon <mishoo@localhost.localdomain> + + * index.html: added style blue2, using utf-8 instead of iso-8859-2 + + * calendar.js: performance under IE (which sucks, by the way) + + * doc/reference.tex: Sunny added to sponsor list + + * doc/Calendar.setup.tex: documenting parameter 'electric' + + * calendar-blue.css, calendar-blue2.css, calendar-brown.css, calendar-green.css, calendar-system.css, calendar-win2k-1.css, calendar-win2k-2.css, calendar-win2k-cold-1.css, calendar-win2k-cold-2.css: + fixed IE text size problems + +2004-01-08 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-pl.js: + Polish translation updated to UTF-8 (thanks to Artur Filipiak) + +2004-01-07 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-si.js: updated (David Milost) + + * lang/calendar-si.js: Slovenian translation (thanks to David Milost) + +2003-12-21 Mihai Bazon <mishoo@localhost.localdomain> + + * TODO: updated TODO list + + * lang/calendar-de.js: German translation (thanks to Peter Strotmann) + +2003-12-19 Mihai Bazon <mishoo@localhost.localdomain> + + * doc/reference.tex: Thank you, Ian Barrak + +2003-12-18 Mihai Bazon <mishoo@localhost.localdomain> + + * doc/reference.tex: fixed documentation bug (thanks Mike) + +2003-12-05 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-ko-utf8.js: + UTF8 version of the Korean language (hopefully correct) + + * lang/calendar-pl-utf8.js, lang/calendar-pl.js: + updated Polish translation (thanks to Janusz Piwowarski) + +2003-12-04 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-fr.js: + French translation updated (thanks to Angiras Rama) + +2003-11-22 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-da.js: updated (thanks to Jesper M. Christensen) + +2003-11-20 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar-blue2.css, calendar-tas.css: + new styles (thanks to Wendall Mosemann for blue2, Mark Lynch for tas) + + * lang/calendar-lt-utf8.js, lang/calendar-lt.js: + Lithuanian translation (thanks to Martynas Majeris) + + * lang/calendar-sp.js: updated + +2003-11-17 Mihai Bazon <mishoo@localhost.localdomain> + + * TODO: added TODO list + +2003-11-14 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-ko.js: Korean translation (thanks to Yourim Yi) + +2003-11-12 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-jp.js: small bug fixed (thanks to TAHARA Yusei) + +2003-11-10 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-fr.js: translation updated, thanks to Florent Ramiere + + * calendar-setup.js: + added new parameter: electric (if false then the field will not get updated on each move) + + * index.html: fixed DOCTYPE + +2003-11-07 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar-setup.js: + fixed minor problem (maybe we're passing object reference instead of ID for + the flat calendar parent) + +2003-11-06 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-fi.js: + added Finnish translation (thanks to Antti Tuppurainen) + +2003-11-05 Mihai Bazon <mishoo@localhost.localdomain> + + * release-notes.html: fixed typo + + * doc/reference.tex, index.html, calendar.js: 0.9.5 + + * README: fixed license statement + + * release-notes.html: updated release notes (0.9.5) + +2003-11-03 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-de.js: + updated German translation (thanks to Gerhard Neiner) + + * calendar-setup.js: fixed license statement + + * calendar.js: whitespace + + * calendar.js: fixed license statement + + * calendar.js: + fixed positioning problem when input field is inside scrolled divs + +2003-11-01 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-af.js: Afrikaan language (thanks to Derick Olivier) + +2003-10-31 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-it.js: + updated IT translation (thanks to Christian Blaser) + + * lang/calendar-es.js: updated ES translation, thanks to Raul + +2003-10-30 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-hu.js: updated thanks to Istvan Karaszi + + * index.html, simple-1.html, simple-2.html, simple-3.html: + switched to utf-8 all encodings + + * lang/calendar-sk.js: + added Slovak translation (thanks to Peter Valach) + + * lang/calendar-ro.js: switched to utf-8 + +2003-10-29 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-es.js: + updated translation, thanks to Jose Ma. Martinez Miralles + + * doc/reference.tex: + fixed the footnote problem (thanks Dominique de Waleffe for the tip) + + * lang/calendar-ro.js: fixed typo + + * lang/calendar-sv.js: oops, license should be LGPL + + * lang/calendar-sw.js: new swedish translation is calendar-sv.js + + * menuarrow.gif, menuarrow.png: + oops, forgot little drop-down menu arrows + + * lang/calendar-sv.js: swedish translation thanks to Leonard Norrgard + + * index.html: oops, some other minor changes + + * index.html, release-notes.html: + latest changes in release-notes and index page for 0.9.4 + + * doc/reference.tex, calendar.js: + added %s date format (# of seconds since Epoch) + + * calendar.js: + A click on TODAY will not close the calendar, even in single-click mode + +2003-10-28 Mihai Bazon <mishoo@localhost.localdomain> + + * index.html: previous cal.html + + * cal.html: moved to index.html + + * README, cal.html, doc/reference.tex, lang/calendar-de.js, lang/calendar-en.js, lang/calendar-ro.js, release-notes.html: + LGPL license, forever. + + * doc/Calendar.setup.tex, simple-1.html: + doc updated for the onUpdate parameter to Calendar.setup + +2003-10-26 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar.js: fixed bug (correct display of the dropdown menus) + + * doc/Calendar.setup.tex, doc/reference.tex, lang/calendar-de.js, lang/calendar-en.js, lang/calendar-ro.js, README, cal.html, calendar-blue.css, calendar-brown.css, calendar-green.css, calendar-setup.js, calendar-system.css, calendar-win2k-1.css, calendar-win2k-2.css, calendar-win2k-cold-1.css, calendar-win2k-cold-2.css, calendar.js, release-notes.html, simple-1.html, simple-3.html: + lots of changes for the 0.9.4 release (see the release-notes.html) + +2003-10-15 Mihai Bazon <mishoo@localhost.localdomain> + + * doc/reference.tex: + documentation updated for 0.9.4 (not yet finished though) + +2003-10-07 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar.js, doc/reference.tex, release-notes.html, README, cal.html, calendar-setup.js: + modified project website + +2003-10-06 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar-setup.js: + added some properties (onSelect, onClose, date) (thanks altblue) + +2003-09-24 Mihai Bazon <mishoo@localhost.localdomain> + + * simple-3.html: dateIsSpecial does not need the "date" argument ;-) + +2003-09-24 fsoft <fsoft@mishoo> + + * calendar.js, simple-3.html: + added year, month, day to getDateStatus() function + +2003-09-24 Mihai Bazon <mishoo@localhost.localdomain> + + * simple-3.html: example on how to use special dates + + * calendar-setup.js, calendar.js, simple-1.html: + support for special dates (thanks fabio) + +2003-09-17 Mihai Bazon <mishoo@localhost.localdomain> + + * doc/reference.tex: fixed error in section 3. + +2003-08-01 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-jp.js: added Japanese translation + +2003-07-16 Mihai Bazon <mishoo@localhost.localdomain> + + * simple-1.html: fixed problem with first example [IE,Opera] + +2003-07-09 Mihai Bazon <mishoo@localhost.localdomain> + + * doc/Calendar.setup.tex: fixed typo (closing parenthesis) + + * lang/calendar-de.js: + added German translation, thanks to Hartwig Weinkauf + +2003-07-08 Mihai Bazon <mishoo@localhost.localdomain> + + * cal.html: added link to release-notes + + * release-notes.html: 0.9.3 release notes + + * make-release.pl: + Script to create distribution archive. It needs some additional packages: + + - LaTeX + - tex2page + - jscrunch (JS compressor) + + * doc/html/makedoc.sh, doc/html/reference.css, doc/reference.tex, doc/makedoc.sh: + documentation updates... + + * calendar.js: added semicolon to make the code "compressible" + +2003-07-06 Mihai Bazon <mishoo@localhost.localdomain> + + * doc/reference.tex: spell checked + + * doc/reference.tex: [minor] changed credits order + + * doc/reference.tex: various improvements and additions + + * doc/html/reference.css: minor eye-candy tweaks + +2003-07-05 Mihai Bazon <mishoo@localhost.localdomain> + + * doc/html/Calendar.setup.html.tex, doc/html/makedoc.sh, doc/html/reference.css, doc/html/reference.t2p, doc/hyperref.cfg, doc/makedoc.sh, doc/reference.tex, doc/Calendar.setup.tex, doc/Calendar.setup.pdf.tex: + full documentation in LaTeX, for PDF and HTML formats + + * simple-2.html: + added demonstration of flat calendar with Calendar.setup + + * simple-1.html: + modified some links, added link to documentation, added demonstration of + disableFunc property + + * calendar-setup.js: added the ability to create flat calendar too + + * cal.html: added links to documentation and simple-[12].html pages + + * README: up-to-date... + + * calendar-setup.html: removed: the documentation is unified + +2003-07-03 Mihai Bazon <mishoo@localhost.localdomain> + + * cal.html: some links to newly added files + + * calendar-setup.html, calendar-setup.js, img.gif, simple-1.html: + added some files to simplify calendar creation for non-(JS)-programmers + + * lang/calendar-zh.js: added simplified chinese (thanks ATang) + +2003-07-02 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar.js: * "yy"-related... [small fix] + + * calendar.js: + * #721833 fixed (yy format will understand years prior to 29 as 20xx) + + * calendar.js: * added refresh() function + + * calendar.js: * fixed bug when in single click mode + * added alignment options to "showAtElement" member function + +2003-06-25 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-pt.js: + added portugese translation (thanks Nuno Barreto) + +2003-06-24 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar.js: + call user handler when the date was changed using the keyboard + + * bugtest-hidden-selects.html: + file to test bug with hidden select-s (thanks Ying Zhang for reporting and for this test file) + + * lang/calendar-hr-utf8.js: + added croatian translation in utf8 (thanks Krunoslav Zubrinic) + +2003-06-23 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-hu.js: added hungarian translation + + * lang/calendar-hr.js: + added croatian translation (thanks to Krunoslav Zubrinic) + +2003-06-22 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar.js: + * #723335 fixed (clicking TODAY will not select the today date if the + disabledHandler rejects it) + + * cal.html: * new code for to work with fix for bug #703238 + * switch to new version + + * calendar.js: + * some patches to make code compatible with Opera 7 (well, almost compatible) + * bug #703238 fixed (fix breaks compatibility with older code that uses + calendar in single-click mode) + * bug #703814 fixed + +2003-04-09 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-tr.js: added turkish lang file + +2003-03-19 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-ru.js: russian translation added + + * lang/calendar-no.js: norwegian translation added + +2003-03-15 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-no.js: norwegian translation + +2003-03-12 Mihai Bazon <mishoo@localhost.localdomain> + + * lang/calendar-pl.js: added polish translation + +2003-03-11 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar.js: + bugfix in parseDate (added base to parseInt, thanks Alan!) + +2003-03-05 Mihai Bazon <mishoo@localhost.localdomain> + + * calendar.js, lang/calendar-br.js, lang/calendar-ca.js, lang/calendar-cs-win.js, lang/calendar-da.js, lang/calendar-du.js, lang/calendar-el.js, lang/calendar-en.js, lang/calendar-es.js, lang/calendar-fr.js, lang/calendar-it.js, lang/calendar-nl.js, lang/calendar-ro.js, lang/calendar-sp.js, lang/calendar-sw.js: + New file. + + * calendar.js, lang/calendar-br.js, lang/calendar-ca.js, lang/calendar-cs-win.js, lang/calendar-da.js, lang/calendar-du.js, lang/calendar-el.js, lang/calendar-en.js, lang/calendar-es.js, lang/calendar-fr.js, lang/calendar-it.js, lang/calendar-nl.js, lang/calendar-ro.js, lang/calendar-sp.js, lang/calendar-sw.js: + moved to CVS at sourceforge.net + release: 0.9.2 + new language packs + + + * README, cal.html, calendar-blue.css, calendar-brown.css, calendar-green.css, calendar-system.css, calendar-win2k-1.css, calendar-win2k-2.css, calendar-win2k-cold-1.css, calendar-win2k-cold-2.css: + New file. + + * README, cal.html, calendar-blue.css, calendar-brown.css, calendar-green.css, calendar-system.css, calendar-win2k-1.css, calendar-win2k-2.css, calendar-win2k-cold-1.css, calendar-win2k-cold-2.css: + moved to CVS at sourceforge.net + release: 0.9.2 + new language packs + + diff --git a/src/core/static/js/jscalendar/README.txt b/src/core/static/js/jscalendar/README.txt new file mode 100755 index 0000000..0c9421b --- /dev/null +++ b/src/core/static/js/jscalendar/README.txt @@ -0,0 +1,33 @@ +The DHTML Calendar +------------------- + + Author: Mihai Bazon, <mishoo@infoiasi.ro> + http://dynarch.com/mishoo/ + + This program is free software published under the + terms of the GNU Lesser General Public License. + + For the entire license text please refer to + http://www.gnu.org/licenses/lgpl.html + +Contents +--------- + + calendar.js -- the main program file + lang/*.js -- internalization files + *.css -- color themes + cal.html -- example usage file + doc/ -- documentation, in PDF and HTML + simple-1.html -- quick setup examples [popup calendars] + simple-2.html -- quick setup example for flat calendar + calendar.php -- PHP wrapper + test.php -- test file for the PHP wrapper + +Homepage +--------- + + For details and latest versions please refer to calendar + homepage, located on my website: + + http://dynarch.com/mishoo/calendar.epl + diff --git a/src/core/static/js/jscalendar/bugtest-hidden-selects.html b/src/core/static/js/jscalendar/bugtest-hidden-selects.html new file mode 100755 index 0000000..df35337 --- /dev/null +++ b/src/core/static/js/jscalendar/bugtest-hidden-selects.html @@ -0,0 +1,108 @@ +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ro" lang="ro"> + +<head> +<title>Bug</title> +<link rel="stylesheet" type="text/css" media="all" href="calendar-win2k-1.css" title="win2k-1" /> + +<!-- import the calendar script --> +<script type="text/javascript" src="calendar.js"></script> + +<!-- import the language module --> +<script type="text/javascript" src="lang/calendar-en.js"></script> + +<!-- helper script that uses the calendar --> +<script type="text/javascript"> +// This function gets called when the end-user clicks on some date. +function selected(cal, date) { + cal.sel.value = date; // just update the date in the input field. + if (cal.sel.id == "sel1" || cal.sel.id == "sel3") + // if we add this call we close the calendar on single-click. + // just to exemplify both cases, we are using this only for the 1st + // and the 3rd field, while 2nd and 4th will still require double-click. + cal.callCloseHandler(); +} + +// And this gets called when the end-user clicks on the _selected_ date, +// or clicks on the "Close" button. It just hides the calendar without +// destroying it. +function closeHandler(cal) { + cal.hide(); // hide the calendar +} + +// This function shows the calendar under the element having the given id. +// It takes care of catching "mousedown" signals on document and hiding the +// calendar if the click was outside. +function showCalendar(id, format) { + var el = document.getElementById(id); + if (calendar != null) { + // we already have some calendar created + calendar.hide(); // so we hide it first. + } else { + // first-time call, create the calendar. + var cal = new Calendar(false, null, selected, closeHandler); + // uncomment the following line to hide the week numbers + // cal.weekNumbers = false; + calendar = cal; // remember it in the global var + cal.setRange(1900, 2070); // min/max year allowed. + cal.create(); + } + calendar.setDateFormat(format); // set the specified date format + calendar.parseDate(el.value); // try to parse the text in field + calendar.sel = el; // inform it what input field we use + calendar.showAtElement(el); // show the calendar below it + + return false; +} + +var MINUTE = 60 * 1000; +var HOUR = 60 * MINUTE; +var DAY = 24 * HOUR; +var WEEK = 7 * DAY; + +// If this handler returns true then the "date" given as +// parameter will be disabled. In this example we enable +// only days within a range of 10 days from the current +// date. +// You can use the functions date.getFullYear() -- returns the year +// as 4 digit number, date.getMonth() -- returns the month as 0..11, +// and date.getDate() -- returns the date of the month as 1..31, to +// make heavy calculations here. However, beware that this function +// should be very fast, as it is called for each day in a month when +// the calendar is (re)constructed. +function isDisabled(date) { + var today = new Date(); + return (Math.abs(date.getTime() - today.getTime()) / DAY) > 10; +} +</script> +</head> + +<body> +<form> +<b>Date:</b> +<br> +<input type="text" name="date1" id="sel1" size="30"> +<input type="button" value="..." onclick="return showCalendar('sel1', 'y-m-d');"> +<p> +<br> +<br><b>Visible &lt;select&gt;, hides and unhides as expected</b> +<br> +<select name="foo" multiple> +<option value="1">can use the functions date.getFullYear() -- returns</option> +<option value="2">4 digit number, date.getMonth() -- returns the month</option> +<option value="3">heavy calculations here. However, beware that this</option> +</select> + +<p> +<br><b>Hidden &lt;select&gt;, it should stay hidden (but doesn't)</b> +<br> +<select name="foo2" multiple style="visibility: hidden"> +<option value="1">this should</option> +<option value="2">remain hidden right?</option> +</select> + +<p> +<br><b>Hidden textbox below, it stays hidden as expected</b> +<br> +<input type="text" name="foo3" value="this stays hidden just fine" style="visibility: hidden"> +</form> +</body></html> diff --git a/src/core/static/js/jscalendar/calendar-blue.css b/src/core/static/js/jscalendar/calendar-blue.css new file mode 100755 index 0000000..6033a9b --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-blue.css @@ -0,0 +1,231 @@ +/* The main calendar widget. DIV containing a table. */ + +div.calendar { position: relative; } + +.calendar, .calendar table { + border: 1px solid #556; + font-size: 11px; + color: #000; + cursor: default; + background: #eef; + font-family: tahoma,verdana,sans-serif; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; /* They are the navigation buttons */ + padding: 2px; /* Make the buttons seem like they're pressing */ +} + +.calendar .nav { + background: #778 url(menuarrow.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; /* Pressing it will take you to the current date */ + text-align: center; + background: #fff; + color: #000; + padding: 2px; +} + +.calendar thead .headrow { /* Row <TR> containing navigation buttons */ + background: #778; + color: #fff; +} + +.calendar thead .daynames { /* Row <TR> containing the day names */ + background: #bdf; +} + +.calendar thead .name { /* Cells <TD> containing the day names */ + border-bottom: 1px solid #556; + padding: 2px; + text-align: center; + color: #000; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #a66; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + background-color: #aaf; + color: #000; + border: 1px solid #04f; + padding: 1px; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + background-color: #77c; + padding: 2px 0px 0px 2px; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells <TD> containing month days dates */ + width: 2em; + color: #456; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #bbb; +} +.calendar tbody .day.othermonth.oweekend { + color: #fbb; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #000; + background: #bdf; +} + +.calendar tbody .rowhilite td { + background: #def; +} + +.calendar tbody .rowhilite td.wn { + background: #eef; +} + +.calendar tbody td.hilite { /* Hovered cells <TD> */ + background: #def; + padding: 1px 3px 1px 1px; + border: 1px solid #bbb; +} + +.calendar tbody td.active { /* Active (pressed) cells <TD> */ + background: #cde; + padding: 2px 2px 0px 2px; +} + +.calendar tbody td.selected { /* Cell showing today date */ + font-weight: bold; + border: 1px solid #000; + padding: 1px 3px 1px 1px; + background: #fff; + color: #000; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #a66; +} + +.calendar tbody td.today { /* Cell showing selected date */ + font-weight: bold; + color: #00f; +} + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ + text-align: center; + background: #556; + color: #fff; +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */ + background: #fff; + color: #445; + border-top: 1px solid #556; + padding: 1px; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + background: #aaf; + border: 1px solid #04f; + color: #000; + padding: 1px; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + background: #77c; + padding: 2px 0px 0px 2px; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + top: 0px; + left: 0px; + width: 4em; + cursor: default; + border: 1px solid #655; + background: #def; + color: #000; + font-size: 90%; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .hilite { + background: #acf; +} + +.calendar .combo .active { + border-top: 1px solid #46a; + border-bottom: 1px solid #46a; + background: #eef; + font-weight: bold; +} + +.calendar td.time { + border-top: 1px solid #000; + padding: 1px 0px; + text-align: center; + background-color: #f4f0e8; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #889; + font-weight: bold; + background-color: #fff; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: #667; + color: #fff; +} + +.calendar td.time span.active { + border-color: #f00; + background-color: #000; + color: #0f0; +} diff --git a/src/core/static/js/jscalendar/calendar-blue2.css b/src/core/static/js/jscalendar/calendar-blue2.css new file mode 100755 index 0000000..6046c81 --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-blue2.css @@ -0,0 +1,235 @@ +/* The main calendar widget. DIV containing a table. */ + +div.calendar { position: relative; } + +.calendar, .calendar table { + border: 1px solid #206A9B; + font-size: 11px; + color: #000; + cursor: default; + background: #F1F8FC; + font-family: tahoma,verdana,sans-serif; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; /* They are the navigation buttons */ + padding: 2px; /* Make the buttons seem like they're pressing */ +} + +.calendar .nav { + background: #007ED1 url(menuarrow2.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; /* Pressing it will take you to the current date */ + text-align: center; + background: #000; + color: #fff; + padding: 2px; +} + +.calendar thead tr { /* Row <TR> containing navigation buttons */ + background: #007ED1; + color: #fff; +} + +.calendar thead .daynames { /* Row <TR> containing the day names */ + background: #C7E1F3; +} + +.calendar thead .name { /* Cells <TD> containing the day names */ + border-bottom: 1px solid #206A9B; + padding: 2px; + text-align: center; + color: #000; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #a66; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + background-color: #34ABFA; + color: #000; + border: 1px solid #016DC5; + padding: 1px; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + background-color: #006AA9; + border: 1px solid #008AFF; + padding: 2px 0px 0px 2px; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells <TD> containing month days dates */ + width: 2em; + color: #456; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #bbb; +} +.calendar tbody .day.othermonth.oweekend { + color: #fbb; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #000; + background: #C7E1F3; +} + +.calendar tbody .rowhilite td { + background: #def; +} + +.calendar tbody .rowhilite td.wn { + background: #F1F8FC; +} + +.calendar tbody td.hilite { /* Hovered cells <TD> */ + background: #def; + padding: 1px 3px 1px 1px; + border: 1px solid #8FC4E8; +} + +.calendar tbody td.active { /* Active (pressed) cells <TD> */ + background: #cde; + padding: 2px 2px 0px 2px; +} + +.calendar tbody td.selected { /* Cell showing today date */ + font-weight: bold; + border: 1px solid #000; + padding: 1px 3px 1px 1px; + background: #fff; + color: #000; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #a66; +} + +.calendar tbody td.today { /* Cell showing selected date */ + font-weight: bold; + color: #D50000; +} + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ + text-align: center; + background: #206A9B; + color: #fff; +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */ + background: #000; + color: #fff; + border-top: 1px solid #206A9B; + padding: 1px; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + background: #B8DAF0; + border: 1px solid #178AEB; + color: #000; + padding: 1px; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + background: #006AA9; + padding: 2px 0px 0px 2px; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + top: 0px; + left: 0px; + width: 4em; + cursor: default; + border: 1px solid #655; + background: #def; + color: #000; + font-size: 90%; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .hilite { + background: #34ABFA; + border-top: 1px solid #46a; + border-bottom: 1px solid #46a; + font-weight: bold; +} + +.calendar .combo .active { + border-top: 1px solid #46a; + border-bottom: 1px solid #46a; + background: #F1F8FC; + font-weight: bold; +} + +.calendar td.time { + border-top: 1px solid #000; + padding: 1px 0px; + text-align: center; + background-color: #E3F0F9; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #889; + font-weight: bold; + background-color: #F1F8FC; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: #267DB7; + color: #fff; +} + +.calendar td.time span.active { + border-color: red; + background-color: #000; + color: #A5FF00; +} diff --git a/src/core/static/js/jscalendar/calendar-brown.css b/src/core/static/js/jscalendar/calendar-brown.css new file mode 100755 index 0000000..ce8d7ed --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-brown.css @@ -0,0 +1,224 @@ +/* The main calendar widget. DIV containing a table. */ + +div.calendar { position: relative; } + +.calendar, .calendar table { + border: 1px solid #655; + font-size: 11px; + color: #000; + cursor: default; + background: #ffd; + font-family: tahoma,verdana,sans-serif; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; /* They are the navigation buttons */ + padding: 2px; /* Make the buttons seem like they're pressing */ +} + +.calendar .nav { + background: #edc url(menuarrow.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; /* Pressing it will take you to the current date */ + text-align: center; + background: #654; + color: #fed; + padding: 2px; +} + +.calendar thead .headrow { /* Row <TR> containing navigation buttons */ + background: #edc; + color: #000; +} + +.calendar thead .name { /* Cells <TD> containing the day names */ + border-bottom: 1px solid #655; + padding: 2px; + text-align: center; + color: #000; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #f00; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + background-color: #faa; + color: #000; + border: 1px solid #f40; + padding: 1px; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + background-color: #c77; + padding: 2px 0px 0px 2px; +} + +.calendar thead .daynames { /* Row <TR> containing the day names */ + background: #fed; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells <TD> containing month days dates */ + width: 2em; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #bbb; +} +.calendar tbody .day.othermonth.oweekend { + color: #fbb; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #000; + background: #fed; +} + +.calendar tbody .rowhilite td { + background: #ddf; +} + +.calendar tbody .rowhilite td.wn { + background: #efe; +} + +.calendar tbody td.hilite { /* Hovered cells <TD> */ + background: #ffe; + padding: 1px 3px 1px 1px; + border: 1px solid #bbb; +} + +.calendar tbody td.active { /* Active (pressed) cells <TD> */ + background: #ddc; + padding: 2px 2px 0px 2px; +} + +.calendar tbody td.selected { /* Cell showing today date */ + font-weight: bold; + border: 1px solid #000; + padding: 1px 3px 1px 1px; + background: #fea; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #f00; +} + +.calendar tbody td.today { font-weight: bold; } + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ + text-align: center; + background: #988; + color: #000; +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */ + border-top: 1px solid #655; + background: #dcb; + color: #840; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + background: #faa; + border: 1px solid #f40; + padding: 1px; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + background: #c77; + padding: 2px 0px 0px 2px; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + top: 0px; + left: 0px; + width: 4em; + cursor: default; + border: 1px solid #655; + background: #ffe; + color: #000; + font-size: 90%; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .hilite { + background: #fc8; +} + +.calendar .combo .active { + border-top: 1px solid #a64; + border-bottom: 1px solid #a64; + background: #fee; + font-weight: bold; +} + +.calendar td.time { + border-top: 1px solid #a88; + padding: 1px 0px; + text-align: center; + background-color: #fed; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #988; + font-weight: bold; + background-color: #fff; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: #866; + color: #fff; +} + +.calendar td.time span.active { + border-color: #f00; + background-color: #000; + color: #0f0; +} diff --git a/src/core/static/js/jscalendar/calendar-green.css b/src/core/static/js/jscalendar/calendar-green.css new file mode 100755 index 0000000..5ade087 --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-green.css @@ -0,0 +1,228 @@ +/* The main calendar widget. DIV containing a table. */ + +div.calendar { position: relative; } + +.calendar, .calendar table { + border: 1px solid #565; + font-size: 11px; + color: #000; + cursor: default; + background: #efe; + font-family: tahoma,verdana,sans-serif; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; /* They are the navigation buttons */ + padding: 2px; /* Make the buttons seem like they're pressing */ + background: #676; + color: #fff; + font-size: 90%; +} + +.calendar .nav { + background: #676 url(menuarrow.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; /* Pressing it will take you to the current date */ + text-align: center; + padding: 2px; + background: #250; + color: #efa; +} + +.calendar thead .headrow { /* Row <TR> containing navigation buttons */ +} + +.calendar thead .name { /* Cells <TD> containing the day names */ + border-bottom: 1px solid #565; + padding: 2px; + text-align: center; + color: #000; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #a66; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + background-color: #afa; + color: #000; + border: 1px solid #084; + padding: 1px; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + background-color: #7c7; + padding: 2px 0px 0px 2px; +} + +.calendar thead .daynames { /* Row <TR> containing the day names */ + background: #dfb; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells <TD> containing month days dates */ + width: 2em; + color: #564; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #bbb; +} +.calendar tbody .day.othermonth.oweekend { + color: #fbb; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #8a8; + background: #dfb; +} + +.calendar tbody .rowhilite td { + background: #dfd; +} + +.calendar tbody .rowhilite td.wn { + background: #efe; +} + +.calendar tbody td.hilite { /* Hovered cells <TD> */ + background: #efd; + padding: 1px 3px 1px 1px; + border: 1px solid #bbb; +} + +.calendar tbody td.active { /* Active (pressed) cells <TD> */ + background: #dec; + padding: 2px 2px 0px 2px; +} + +.calendar tbody td.selected { /* Cell showing today date */ + font-weight: bold; + border: 1px solid #000; + padding: 1px 3px 1px 1px; + background: #f8fff8; + color: #000; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #a66; +} + +.calendar tbody td.today { font-weight: bold; color: #0a0; } + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ + text-align: center; + background: #565; + color: #fff; +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */ + padding: 2px; + background: #250; + color: #efa; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + background: #afa; + border: 1px solid #084; + color: #000; + padding: 1px; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + background: #7c7; + padding: 2px 0px 0px 2px; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + top: 0px; + left: 0px; + width: 4em; + cursor: default; + border: 1px solid #565; + background: #efd; + color: #000; + font-size: 90%; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .hilite { + background: #af8; +} + +.calendar .combo .active { + border-top: 1px solid #6a4; + border-bottom: 1px solid #6a4; + background: #efe; + font-weight: bold; +} + +.calendar td.time { + border-top: 1px solid #8a8; + padding: 1px 0px; + text-align: center; + background-color: #dfb; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #898; + font-weight: bold; + background-color: #fff; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: #686; + color: #fff; +} + +.calendar td.time span.active { + border-color: #f00; + background-color: #000; + color: #0f0; +} diff --git a/src/core/static/js/jscalendar/calendar-setup.js b/src/core/static/js/jscalendar/calendar-setup.js new file mode 100755 index 0000000..e5a0fdd --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-setup.js @@ -0,0 +1,181 @@ +/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/ + * --------------------------------------------------------------------------- + * + * The DHTML Calendar + * + * Details and latest version at: + * http://dynarch.com/mishoo/calendar.epl + * + * This script is distributed under the GNU Lesser General Public License. + * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html + * + * This file defines helper functions for setting up the calendar. They are + * intended to help non-programmers get a working calendar on their site + * quickly. This script should not be seen as part of the calendar. It just + * shows you what one can do with the calendar, while in the same time + * providing a quick and simple method for setting it up. If you need + * exhaustive customization of the calendar creation process feel free to + * modify this code to suit your needs (this is recommended and much better + * than modifying calendar.js itself). + */ + +// $Id: calendar-setup.js 22 2006-06-23 14:42:15Z ugoletti $ + +/** + * This function "patches" an input field (or other element) to use a calendar + * widget for date selection. + * + * The "params" is a single object that can have the following properties: + * + * prop. name | description + * ------------------------------------------------------------------------------------------------- + * inputField | the ID of an input field to store the date + * displayArea | the ID of a DIV or other element to show the date + * button | ID of a button or other element that will trigger the calendar + * eventName | event that will trigger the calendar, without the "on" prefix (default: "click") + * ifFormat | date format that will be stored in the input field + * daFormat | the date format that will be used to display the date in displayArea + * singleClick | (true/false) wether the calendar is in single click mode or not (default: true) + * firstDay | numeric: 0 to 6. "0" means display Sunday first, "1" means display Monday first, etc. + * align | alignment (default: "Br"); if you don't know what's this see the calendar documentation + * range | array with 2 elements. Default: [1900, 2999] -- the range of years available + * weekNumbers | (true/false) if it's true (default) the calendar will display week numbers + * flat | null or element ID; if not null the calendar will be a flat calendar having the parent with the given ID + * flatCallback | function that receives a JS Date object and returns an URL to point the browser to (for flat calendar) + * disableFunc | function that receives a JS Date object and should return true if that date has to be disabled in the calendar + * onSelect | function that gets called when a date is selected. You don't _have_ to supply this (the default is generally okay) + * onClose | function that gets called when the calendar is closed. [default] + * onUpdate | function that gets called after the date is updated in the input field. Receives a reference to the calendar. + * date | the date that the calendar will be initially displayed to + * showsTime | default: false; if true the calendar will include a time selector + * timeFormat | the time format; can be "12" or "24", default is "12" + * electric | if true (default) then given fields/date areas are updated for each move; otherwise they're updated only on close + * step | configures the step of the years in drop-down boxes; default: 2 + * position | configures the calendar absolute position; default: null + * cache | if "true" (but default: "false") it will reuse the same calendar object, where possible + * showOthers | if "true" (but default: "false") it will show days from other months too + * + * None of them is required, they all have default values. However, if you + * pass none of "inputField", "displayArea" or "button" you'll get a warning + * saying "nothing to setup". + */ +Calendar.setup = function (params) { + function param_default(pname, def) { if (typeof params[pname] == "undefined") { params[pname] = def; } }; + + param_default("inputField", null); + param_default("displayArea", null); + param_default("button", null); + param_default("eventName", "click"); + param_default("ifFormat", "%Y/%m/%d"); + param_default("daFormat", "%Y/%m/%d"); + param_default("singleClick", true); + param_default("disableFunc", null); + param_default("dateStatusFunc", params["disableFunc"]); // takes precedence if both are defined + param_default("firstDay", 0); // defaults to "Sunday" first + param_default("align", "Br"); + param_default("range", [1900, 2999]); + param_default("weekNumbers", true); + param_default("flat", null); + param_default("flatCallback", null); + param_default("onSelect", null); + param_default("onClose", null); + param_default("onUpdate", null); + param_default("date", null); + param_default("showsTime", false); + param_default("timeFormat", "24"); + param_default("electric", true); + param_default("step", 2); + param_default("position", null); + param_default("cache", false); + param_default("showOthers", false); + + var tmp = ["inputField", "displayArea", "button"]; + for (var i in tmp) { + if (typeof params[tmp[i]] == "string") { + params[tmp[i]] = document.getElementById(params[tmp[i]]); + } + } + if (!(params.flat || params.inputField || params.displayArea || params.button)) { + alert("Calendar.setup:\n Nothing to setup (no fields found). Please check your code"); + return false; + } + + function onSelect(cal) { + var p = cal.params; + var update = (cal.dateClicked || p.electric); + if (update && p.flat) { + if (typeof p.flatCallback == "function") + p.flatCallback(cal); + else + alert("No flatCallback given -- doing nothing."); + return false; + } + if (update && p.inputField) { + p.inputField.value = cal.date.print(p.ifFormat); + if (typeof p.inputField.onchange == "function") + p.inputField.onchange(); + } + if (update && p.displayArea) + p.displayArea.innerHTML = cal.date.print(p.daFormat); + if (update && p.singleClick && cal.dateClicked) + cal.callCloseHandler(); + if (update && typeof p.onUpdate == "function") + p.onUpdate(cal); + }; + + if (params.flat != null) { + if (typeof params.flat == "string") + params.flat = document.getElementById(params.flat); + if (!params.flat) { + alert("Calendar.setup:\n Flat specified but can't find parent."); + return false; + } + var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect); + cal.showsTime = params.showsTime; + cal.time24 = (params.timeFormat == "24"); + cal.params = params; + cal.weekNumbers = params.weekNumbers; + cal.setRange(params.range[0], params.range[1]); + cal.setDateStatusHandler(params.dateStatusFunc); + cal.create(params.flat); + cal.show(); + return false; + } + + var triggerEl = params.button || params.displayArea || params.inputField; + triggerEl["on" + params.eventName] = function() { + var dateEl = params.inputField || params.displayArea; + var dateFmt = params.inputField ? params.ifFormat : params.daFormat; + var mustCreate = false; + var cal = window.calendar; + if (!(cal && params.cache)) { + window.calendar = cal = new Calendar(params.firstDay, + params.date, + params.onSelect || onSelect, + params.onClose || function(cal) { cal.hide(); }); + cal.showsTime = params.showsTime; + cal.time24 = (params.timeFormat == "24"); + cal.weekNumbers = params.weekNumbers; + mustCreate = true; + } else { + if (params.date) + cal.setDate(params.date); + cal.hide(); + } + cal.showsOtherMonths = params.showOthers; + cal.yearStep = params.step; + cal.setRange(params.range[0], params.range[1]); + cal.params = params; + cal.setDateStatusHandler(params.dateStatusFunc); + cal.setDateFormat(dateFmt); + if (mustCreate) + cal.create(); + cal.parseDate(dateEl.value || dateEl.innerHTML); + cal.refresh(); + if (!params.position) + cal.showAtElement(params.button || params.displayArea || params.inputField, params.align); + else + cal.showAt(params.position[0], params.position[1]); + return false; + }; +}; diff --git a/src/core/static/js/jscalendar/calendar-setup_stripped.js b/src/core/static/js/jscalendar/calendar-setup_stripped.js new file mode 100755 index 0000000..1f1a3cd --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-setup_stripped.js @@ -0,0 +1,21 @@ +/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/ + * --------------------------------------------------------------------------- + * + * The DHTML Calendar + * + * Details and latest version at: + * http://dynarch.com/mishoo/calendar.epl + * + * This script is distributed under the GNU Lesser General Public License. + * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html + * + * This file defines helper functions for setting up the calendar. They are + * intended to help non-programmers get a working calendar on their site + * quickly. This script should not be seen as part of the calendar. It just + * shows you what one can do with the calendar, while in the same time + * providing a quick and simple method for setting it up. If you need + * exhaustive customization of the calendar creation process feel free to + * modify this code to suit your needs (this is recommended and much better + * than modifying calendar.js itself). + */ + Calendar.setup=function(params){function param_default(pname,def){if(typeof params[pname]=="undefined"){params[pname]=def;}};param_default("inputField",null);param_default("displayArea",null);param_default("button",null);param_default("eventName","click");param_default("ifFormat","%Y/%m/%d");param_default("daFormat","%Y/%m/%d");param_default("singleClick",true);param_default("disableFunc",null);param_default("dateStatusFunc",params["disableFunc"]);param_default("firstDay",0);param_default("align","Br");param_default("range",[1900,2999]);param_default("weekNumbers",true);param_default("flat",null);param_default("flatCallback",null);param_default("onSelect",null);param_default("onClose",null);param_default("onUpdate",null);param_default("date",null);param_default("showsTime",false);param_default("timeFormat","24");param_default("electric",true);param_default("step",2);param_default("position",null);param_default("cache",false);param_default("showOthers",false);var tmp=["inputField","displayArea","button"];for(var i in tmp){if(typeof params[tmp[i]]=="string"){params[tmp[i]]=document.getElementById(params[tmp[i]]);}}if(!(params.flat||params.inputField||params.displayArea||params.button)){alert("Calendar.setup:\n Nothing to setup (no fields found). Please check your code");return false;}function onSelect(cal){var p=cal.params;var update=(cal.dateClicked||p.electric);if(update&&p.flat){if(typeof p.flatCallback=="function")p.flatCallback(cal);else alert("No flatCallback given -- doing nothing.");return false;}if(update&&p.inputField){p.inputField.value=cal.date.print(p.ifFormat);if(typeof p.inputField.onchange=="function")p.inputField.onchange();}if(update&&p.displayArea)p.displayArea.innerHTML=cal.date.print(p.daFormat);if(update&&p.singleClick&&cal.dateClicked)cal.callCloseHandler();if(update&&typeof p.onUpdate=="function")p.onUpdate(cal);};if(params.flat!=null){if(typeof params.flat=="string")params.flat=document.getElementById(params.flat);if(!params.flat){alert("Calendar.setup:\n Flat specified but can't find parent.");return false;}var cal=new Calendar(params.firstDay,params.date,params.onSelect||onSelect);cal.showsTime=params.showsTime;cal.time24=(params.timeFormat=="24");cal.params=params;cal.weekNumbers=params.weekNumbers;cal.setRange(params.range[0],params.range[1]);cal.setDateStatusHandler(params.dateStatusFunc);cal.create(params.flat);cal.show();return false;}var triggerEl=params.button||params.displayArea||params.inputField;triggerEl["on"+params.eventName]=function(){var dateEl=params.inputField||params.displayArea;var dateFmt=params.inputField?params.ifFormat:params.daFormat;var mustCreate=false;var cal=window.calendar;if(!(cal&&params.cache)){window.calendar=cal=new Calendar(params.firstDay,params.date,params.onSelect||onSelect,params.onClose||function(cal){cal.hide();});cal.showsTime=params.showsTime;cal.time24=(params.timeFormat=="24");cal.weekNumbers=params.weekNumbers;mustCreate=true;}else{if(params.date)cal.setDate(params.date);cal.hide();}cal.showsOtherMonths=params.showOthers;cal.yearStep=params.step;cal.setRange(params.range[0],params.range[1]);cal.params=params;cal.setDateStatusHandler(params.dateStatusFunc);cal.setDateFormat(dateFmt);if(mustCreate)cal.create();cal.parseDate(dateEl.value||dateEl.innerHTML);cal.refresh();if(!params.position)cal.showAtElement(params.button||params.displayArea||params.inputField,params.align);else cal.showAt(params.position[0],params.position[1]);return false;};}; \ No newline at end of file diff --git a/src/core/static/js/jscalendar/calendar-system.css b/src/core/static/js/jscalendar/calendar-system.css new file mode 100755 index 0000000..a663d1a --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-system.css @@ -0,0 +1,250 @@ +/* The main calendar widget. DIV containing a table. */ + +.calendar { + position: relative; + display: none; + border: 1px solid; + border-color: #fff #000 #000 #fff; + font-size: 11px; + cursor: default; + background: Window; + color: WindowText; + font-family: tahoma,verdana,sans-serif; +} + +.calendar table { + border: 1px solid; + border-color: #fff #000 #000 #fff; + font-size: 11px; + cursor: default; + background: Window; + color: WindowText; + font-family: tahoma,verdana,sans-serif; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; + padding: 1px; + border: 1px solid; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; + background: ButtonFace; +} + +.calendar .nav { + background: ButtonFace url(menuarrow.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; + padding: 1px; + border: 1px solid #000; + background: ActiveCaption; + color: CaptionText; + text-align: center; +} + +.calendar thead .headrow { /* Row <TR> containing navigation buttons */ +} + +.calendar thead .daynames { /* Row <TR> containing the day names */ +} + +.calendar thead .name { /* Cells <TD> containing the day names */ + border-bottom: 1px solid ButtonShadow; + padding: 2px; + text-align: center; + background: ButtonFace; + color: ButtonText; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #f00; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + border: 2px solid; + padding: 0px; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + border-width: 1px; + padding: 2px 0px 0px 2px; + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells <TD> containing month days dates */ + width: 2em; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #aaa; +} +.calendar tbody .day.othermonth.oweekend { + color: #faa; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid ButtonShadow; + background: ButtonFace; + color: ButtonText; +} + +.calendar tbody .rowhilite td { + background: Highlight; + color: HighlightText; +} + +.calendar tbody td.hilite { /* Hovered cells <TD> */ + padding: 1px 3px 1px 1px; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; +} + +.calendar tbody td.active { /* Active (pressed) cells <TD> */ + padding: 2px 2px 0px 2px; + border: 1px solid; + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; +} + +.calendar tbody td.selected { /* Cell showing selected date */ + font-weight: bold; + border: 1px solid; + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; + padding: 2px 2px 0px 2px; + background: ButtonFace; + color: ButtonText; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #f00; +} + +.calendar tbody td.today { /* Cell showing today date */ + font-weight: bold; + color: #00f; +} + +.calendar tbody td.disabled { color: GrayText; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */ + background: ButtonFace; + padding: 1px; + border: 1px solid; + border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow; + color: ButtonText; + text-align: center; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; + padding: 1px; + background: #e4e0d8; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + padding: 2px 0px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + width: 4em; + top: 0px; + left: 0px; + cursor: default; + border: 1px solid; + border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight; + background: Menu; + color: MenuText; + font-size: 90%; + padding: 1px; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .active { + padding: 0px; + border: 1px solid #000; +} + +.calendar .combo .hilite { + background: Highlight; + color: HighlightText; +} + +.calendar td.time { + border-top: 1px solid ButtonShadow; + padding: 1px 0px; + text-align: center; + background-color: ButtonFace; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #889; + font-weight: bold; + background-color: Menu; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: Highlight; + color: HighlightText; +} + +.calendar td.time span.active { + border-color: #f00; + background-color: #000; + color: #0f0; +} diff --git a/src/core/static/js/jscalendar/calendar-tas.css b/src/core/static/js/jscalendar/calendar-tas.css new file mode 100755 index 0000000..5b74232 --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-tas.css @@ -0,0 +1,238 @@ +/* The main calendar widget. DIV containing a table. */ + +div.calendar { position: relative; } + +.calendar, .calendar table { + border: 1px solid #655; + font-size: 11px; + color: #000; + cursor: default; + background: #ffd; + font-family: tahoma,verdana,sans-serif; + filter: +progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#DDDCCC,EndColorStr=#FFFFFF); +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; /* They are the navigation buttons */ + padding: 2px; /* Make the buttons seem like they're pressing */ + color:#363636; +} + +.calendar .nav { + background: #edc url(menuarrow.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; /* Pressing it will take you to the current date */ + text-align: center; + background: #654; + color: #363636; + padding: 2px; + filter: +progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#ffffff,EndColorStr=#dddccc); +} + +.calendar thead .headrow { /* Row <TR> containing navigation buttons */ + /*background: #3B86A0;*/ + color: #363636; + font-weight: bold; +filter: +progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#ffffff,EndColorStr=#3b86a0); +} + +.calendar thead .name { /* Cells <TD> containing the day names */ + border-bottom: 1px solid #655; + padding: 2px; + text-align: center; + color: #363636; + filter: +progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#DDDCCC,EndColorStr=#FFFFFF); +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #f00; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + background-color: #ffcc86; + color: #000; + border: 1px solid #b59345; + padding: 1px; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + background-color: #c77; + padding: 2px 0px 0px 2px; +} + +.calendar thead .daynames { /* Row <TR> containing the day names */ + background: #fed; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells <TD> containing month days dates */ + width: 2em; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #aaa; +} +.calendar tbody .day.othermonth.oweekend { + color: #faa; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #000; + background: #fed; +} + +.calendar tbody .rowhilite td { + background: #ddf; + +} + +.calendar tbody .rowhilite td.wn { + background: #efe; +} + +.calendar tbody td.hilite { /* Hovered cells <TD> */ + background: #ffe; + padding: 1px 3px 1px 1px; + border: 1px solid #bbb; +} + +.calendar tbody td.active { /* Active (pressed) cells <TD> */ + background: #ddc; + padding: 2px 2px 0px 2px; +} + +.calendar tbody td.selected { /* Cell showing today date */ + font-weight: bold; + border: 1px solid #000; + padding: 1px 3px 1px 1px; + background: #fea; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #f00; +} + +.calendar tbody td.today { font-weight: bold; } + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ + text-align: center; + background: #988; + color: #000; + +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */ + border-top: 1px solid #655; + background: #dcb; + color: #363636; + font-weight: bold; + filter: +progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#FFFFFF,EndColorStr=#DDDCCC); +} +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + background: #faa; + border: 1px solid #f40; + padding: 1px; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + background: #c77; + padding: 2px 0px 0px 2px; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.combo { + position: absolute; + display: none; + top: 0px; + left: 0px; + width: 4em; + cursor: default; + border: 1px solid #655; + background: #ffe; + color: #000; + font-size: smaller; +} + +.combo .label, +.combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.combo .label-IEfix { + width: 4em; +} + +.combo .hilite { + background: #fc8; +} + +.combo .active { + border-top: 1px solid #a64; + border-bottom: 1px solid #a64; + background: #fee; + font-weight: bold; +} + +.calendar td.time { + border-top: 1px solid #a88; + padding: 1px 0px; + text-align: center; + background-color: #fed; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #988; + font-weight: bold; + background-color: #fff; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: #866; + color: #fff; +} + +.calendar td.time span.active { + border-color: #f00; + background-color: #000; + color: #0f0; +} diff --git a/src/core/static/js/jscalendar/calendar-win2k-1.css b/src/core/static/js/jscalendar/calendar-win2k-1.css new file mode 100755 index 0000000..dc48d8c --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-win2k-1.css @@ -0,0 +1,270 @@ +/* The main calendar widget. DIV containing a table. */ + +.calendar { + position: relative; + display: none; + border-top: 2px solid #fff; + border-right: 2px solid #000; + border-bottom: 2px solid #000; + border-left: 2px solid #fff; + font-size: 11px; + color: #000; + cursor: default; + background: #d4d0c8; + font-family: tahoma,verdana,sans-serif; +} + +.calendar table { + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; + font-size: 11px; + color: #000; + cursor: default; + background: #d4d0c8; + font-family: tahoma,verdana,sans-serif; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; + padding: 1px; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; +} + +.calendar .nav { + background: transparent url(menuarrow.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; + padding: 1px; + border: 1px solid #000; + background: #848078; + color: #fff; + text-align: center; +} + +.calendar thead .headrow { /* Row <TR> containing navigation buttons */ +} + +.calendar thead .daynames { /* Row <TR> containing the day names */ +} + +.calendar thead .name { /* Cells <TD> containing the day names */ + border-bottom: 1px solid #000; + padding: 2px; + text-align: center; + background: #f4f0e8; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #f00; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + border-top: 2px solid #fff; + border-right: 2px solid #000; + border-bottom: 2px solid #000; + border-left: 2px solid #fff; + padding: 0px; + background-color: #e4e0d8; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + padding: 2px 0px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; + background-color: #c4c0b8; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells <TD> containing month days dates */ + width: 2em; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #aaa; +} +.calendar tbody .day.othermonth.oweekend { + color: #faa; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #000; + background: #f4f0e8; +} + +.calendar tbody .rowhilite td { + background: #e4e0d8; +} + +.calendar tbody .rowhilite td.wn { + background: #d4d0c8; +} + +.calendar tbody td.hilite { /* Hovered cells <TD> */ + padding: 1px 3px 1px 1px; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; +} + +.calendar tbody td.active { /* Active (pressed) cells <TD> */ + padding: 2px 2px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +.calendar tbody td.selected { /* Cell showing selected date */ + font-weight: bold; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; + padding: 2px 2px 0px 2px; + background: #e4e0d8; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #f00; +} + +.calendar tbody td.today { /* Cell showing today date */ + font-weight: bold; + color: #00f; +} + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */ + background: #f4f0e8; + padding: 1px; + border: 1px solid #000; + background: #848078; + color: #fff; + text-align: center; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; + padding: 1px; + background: #e4e0d8; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + padding: 2px 0px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + width: 4em; + top: 0px; + left: 0px; + cursor: default; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; + background: #e4e0d8; + font-size: 90%; + padding: 1px; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .active { + background: #c4c0b8; + padding: 0px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +.calendar .combo .hilite { + background: #048; + color: #fea; +} + +.calendar td.time { + border-top: 1px solid #000; + padding: 1px 0px; + text-align: center; + background-color: #f4f0e8; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #889; + font-weight: bold; + background-color: #fff; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: #766; + color: #fff; +} + +.calendar td.time span.active { + border-color: #f00; + background-color: #000; + color: #0f0; +} diff --git a/src/core/static/js/jscalendar/calendar-win2k-2.css b/src/core/static/js/jscalendar/calendar-win2k-2.css new file mode 100755 index 0000000..d14420e --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-win2k-2.css @@ -0,0 +1,270 @@ +/* The main calendar widget. DIV containing a table. */ + +.calendar { + position: relative; + display: none; + border-top: 2px solid #fff; + border-right: 2px solid #000; + border-bottom: 2px solid #000; + border-left: 2px solid #fff; + font-size: 11px; + color: #000; + cursor: default; + background: #d4c8d0; + font-family: tahoma,verdana,sans-serif; +} + +.calendar table { + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; + font-size: 11px; + color: #000; + cursor: default; + background: #d4c8d0; + font-family: tahoma,verdana,sans-serif; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; + padding: 1px; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; +} + +.calendar .nav { + background: transparent url(menuarrow.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; + padding: 1px; + border: 1px solid #000; + background: #847880; + color: #fff; + text-align: center; +} + +.calendar thead .headrow { /* Row <TR> containing navigation buttons */ +} + +.calendar thead .daynames { /* Row <TR> containing the day names */ +} + +.calendar thead .name { /* Cells <TD> containing the day names */ + border-bottom: 1px solid #000; + padding: 2px; + text-align: center; + background: #f4e8f0; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #f00; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + border-top: 2px solid #fff; + border-right: 2px solid #000; + border-bottom: 2px solid #000; + border-left: 2px solid #fff; + padding: 0px; + background-color: #e4d8e0; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + padding: 2px 0px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; + background-color: #c4b8c0; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells <TD> containing month days dates */ + width: 2em; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #aaa; +} +.calendar tbody .day.othermonth.oweekend { + color: #faa; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #000; + background: #f4e8f0; +} + +.calendar tbody .rowhilite td { + background: #e4d8e0; +} + +.calendar tbody .rowhilite td.wn { + background: #d4c8d0; +} + +.calendar tbody td.hilite { /* Hovered cells <TD> */ + padding: 1px 3px 1px 1px; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; +} + +.calendar tbody td.active { /* Active (pressed) cells <TD> */ + padding: 2px 2px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +.calendar tbody td.selected { /* Cell showing selected date */ + font-weight: bold; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; + padding: 2px 2px 0px 2px; + background: #e4d8e0; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #f00; +} + +.calendar tbody td.today { /* Cell showing today date */ + font-weight: bold; + color: #00f; +} + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */ + background: #f4e8f0; + padding: 1px; + border: 1px solid #000; + background: #847880; + color: #fff; + text-align: center; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; + padding: 1px; + background: #e4d8e0; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + padding: 2px 0px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + width: 4em; + top: 0px; + left: 0px; + cursor: default; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; + background: #e4d8e0; + font-size: 90%; + padding: 1px; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .active { + background: #d4c8d0; + padding: 0px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +.calendar .combo .hilite { + background: #408; + color: #fea; +} + +.calendar td.time { + border-top: 1px solid #000; + padding: 1px 0px; + text-align: center; + background-color: #f4f0e8; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #889; + font-weight: bold; + background-color: #fff; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: #766; + color: #fff; +} + +.calendar td.time span.active { + border-color: #f00; + background-color: #000; + color: #0f0; +} diff --git a/src/core/static/js/jscalendar/calendar-win2k-cold-1.css b/src/core/static/js/jscalendar/calendar-win2k-cold-1.css new file mode 100755 index 0000000..4429f9a --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-win2k-cold-1.css @@ -0,0 +1,264 @@ +/* The main calendar widget. DIV containing a table. */ + +.calendar { + position: relative; + display: none; + border-top: 2px solid #fff; + border-right: 2px solid #000; + border-bottom: 2px solid #000; + border-left: 2px solid #fff; + font-size: 11px; + color: #000; + cursor: default; + background: #c8d0d4; + font-family: tahoma,verdana,sans-serif; +} + +.calendar table { + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; + font-size: 11px; + color: #000; + cursor: default; + background: #c8d0d4; + font-family: tahoma,verdana,sans-serif; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; + padding: 1px; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; +} + +.calendar .nav { + background: transparent url(menuarrow.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; + padding: 1px; + border: 1px solid #000; + background: #788084; + color: #fff; + text-align: center; +} + +.calendar thead .headrow { /* Row <TR> containing navigation buttons */ +} + +.calendar thead .daynames { /* Row <TR> containing the day names */ +} + +.calendar thead .name { /* Cells <TD> containing the day names */ + border-bottom: 1px solid #000; + padding: 2px; + text-align: center; + background: #e8f0f4; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #f00; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + border-top: 2px solid #fff; + border-right: 2px solid #000; + border-bottom: 2px solid #000; + border-left: 2px solid #fff; + padding: 0px; + background-color: #d8e0e4; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + padding: 2px 0px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; + background-color: #b8c0c4; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells <TD> containing month days dates */ + width: 2em; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #aaa; +} +.calendar tbody .day.othermonth.oweekend { + color: #faa; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #000; + background: #e8f4f0; +} + +.calendar tbody .rowhilite td { + background: #d8e4e0; +} + +.calendar tbody .rowhilite td.wn { + background: #c8d4d0; +} + +.calendar tbody td.hilite { /* Hovered cells <TD> */ + padding: 1px 3px 1px 1px; + border: 1px solid; + border-color: #fff #000 #000 #fff; +} + +.calendar tbody td.active { /* Active (pressed) cells <TD> */ + padding: 2px 2px 0px 2px; + border: 1px solid; + border-color: #000 #fff #fff #000; +} + +.calendar tbody td.selected { /* Cell showing selected date */ + font-weight: bold; + padding: 2px 2px 0px 2px; + border: 1px solid; + border-color: #000 #fff #fff #000; + background: #d8e0e4; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #f00; +} + +.calendar tbody td.today { /* Cell showing today date */ + font-weight: bold; + color: #00f; +} + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */ + background: #e8f0f4; + padding: 1px; + border: 1px solid #000; + background: #788084; + color: #fff; + text-align: center; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; + padding: 1px; + background: #d8e0e4; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + padding: 2px 0px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + width: 4em; + top: 0px; + left: 0px; + cursor: default; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; + background: #d8e0e4; + font-size: 90%; + padding: 1px; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .active { + background: #c8d0d4; + padding: 0px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +.calendar .combo .hilite { + background: #048; + color: #aef; +} + +.calendar td.time { + border-top: 1px solid #000; + padding: 1px 0px; + text-align: center; + background-color: #e8f0f4; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #889; + font-weight: bold; + background-color: #fff; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: #667; + color: #fff; +} + +.calendar td.time span.active { + border-color: #f00; + background-color: #000; + color: #0f0; +} diff --git a/src/core/static/js/jscalendar/calendar-win2k-cold-2.css b/src/core/static/js/jscalendar/calendar-win2k-cold-2.css new file mode 100755 index 0000000..ff35e72 --- /dev/null +++ b/src/core/static/js/jscalendar/calendar-win2k-cold-2.css @@ -0,0 +1,270 @@ +/* The main calendar widget. DIV containing a table. */ + +.calendar { + position: relative; + display: none; + border-top: 2px solid #fff; + border-right: 2px solid #000; + border-bottom: 2px solid #000; + border-left: 2px solid #fff; + font-size: 11px; + color: #000; + cursor: default; + background: #c8d4d0; + font-family: tahoma,verdana,sans-serif; +} + +.calendar table { + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; + font-size: 11px; + color: #000; + cursor: default; + background: #c8d4d0; + font-family: tahoma,verdana,sans-serif; +} + +/* Header part -- contains navigation buttons and day names. */ + +.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */ + text-align: center; + padding: 1px; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; +} + +.calendar .nav { + background: transparent url(menuarrow.gif) no-repeat 100% 100%; +} + +.calendar thead .title { /* This holds the current "month, year" */ + font-weight: bold; + padding: 1px; + border: 1px solid #000; + background: #788480; + color: #fff; + text-align: center; +} + +.calendar thead .headrow { /* Row <TR> containing navigation buttons */ +} + +.calendar thead .daynames { /* Row <TR> containing the day names */ +} + +.calendar thead .name { /* Cells <TD> containing the day names */ + border-bottom: 1px solid #000; + padding: 2px; + text-align: center; + background: #e8f4f0; +} + +.calendar thead .weekend { /* How a weekend day name shows in header */ + color: #f00; +} + +.calendar thead .hilite { /* How do the buttons in header appear when hover */ + border-top: 2px solid #fff; + border-right: 2px solid #000; + border-bottom: 2px solid #000; + border-left: 2px solid #fff; + padding: 0px; + background-color: #d8e4e0; +} + +.calendar thead .active { /* Active (pressed) buttons in header */ + padding: 2px 0px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; + background-color: #b8c4c0; +} + +/* The body part -- contains all the days in month. */ + +.calendar tbody .day { /* Cells <TD> containing month days dates */ + width: 2em; + text-align: right; + padding: 2px 4px 2px 2px; +} +.calendar tbody .day.othermonth { + font-size: 80%; + color: #aaa; +} +.calendar tbody .day.othermonth.oweekend { + color: #faa; +} + +.calendar table .wn { + padding: 2px 3px 2px 2px; + border-right: 1px solid #000; + background: #e8f4f0; +} + +.calendar tbody .rowhilite td { + background: #d8e4e0; +} + +.calendar tbody .rowhilite td.wn { + background: #c8d4d0; +} + +.calendar tbody td.hilite { /* Hovered cells <TD> */ + padding: 1px 3px 1px 1px; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; +} + +.calendar tbody td.active { /* Active (pressed) cells <TD> */ + padding: 2px 2px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +.calendar tbody td.selected { /* Cell showing selected date */ + font-weight: bold; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; + padding: 2px 2px 0px 2px; + background: #d8e4e0; +} + +.calendar tbody td.weekend { /* Cells showing weekend days */ + color: #f00; +} + +.calendar tbody td.today { /* Cell showing today date */ + font-weight: bold; + color: #00f; +} + +.calendar tbody .disabled { color: #999; } + +.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */ + visibility: hidden; +} + +.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */ + display: none; +} + +/* The footer part -- status bar and "Close" button */ + +.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */ +} + +.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */ + background: #e8f4f0; + padding: 1px; + border: 1px solid #000; + background: #788480; + color: #fff; + text-align: center; +} + +.calendar tfoot .hilite { /* Hover style for buttons in footer */ + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; + padding: 1px; + background: #d8e4e0; +} + +.calendar tfoot .active { /* Active (pressed) style for buttons in footer */ + padding: 2px 0px 0px 2px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +/* Combo boxes (menus that display months/years for direct selection) */ + +.calendar .combo { + position: absolute; + display: none; + width: 4em; + top: 0px; + left: 0px; + cursor: default; + border-top: 1px solid #fff; + border-right: 1px solid #000; + border-bottom: 1px solid #000; + border-left: 1px solid #fff; + background: #d8e4e0; + font-size: 90%; + padding: 1px; +} + +.calendar .combo .label, +.calendar .combo .label-IEfix { + text-align: center; + padding: 1px; +} + +.calendar .combo .label-IEfix { + width: 4em; +} + +.calendar .combo .active { + background: #c8d4d0; + padding: 0px; + border-top: 1px solid #000; + border-right: 1px solid #fff; + border-bottom: 1px solid #fff; + border-left: 1px solid #000; +} + +.calendar .combo .hilite { + background: #048; + color: #aef; +} + +.calendar td.time { + border-top: 1px solid #000; + padding: 1px 0px; + text-align: center; + background-color: #e8f0f4; +} + +.calendar td.time .hour, +.calendar td.time .minute, +.calendar td.time .ampm { + padding: 0px 3px 0px 4px; + border: 1px solid #889; + font-weight: bold; + background-color: #fff; +} + +.calendar td.time .ampm { + text-align: center; +} + +.calendar td.time .colon { + padding: 0px 2px 0px 3px; + font-weight: bold; +} + +.calendar td.time span.hilite { + border-color: #000; + background-color: #667; + color: #fff; +} + +.calendar td.time span.active { + border-color: #f00; + background-color: #000; + color: #0f0; +} diff --git a/src/core/static/js/jscalendar/calendar.js b/src/core/static/js/jscalendar/calendar.js new file mode 100755 index 0000000..e90b342 --- /dev/null +++ b/src/core/static/js/jscalendar/calendar.js @@ -0,0 +1,1715 @@ +/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/ + * ------------------------------------------------------------------ + * + * The DHTML Calendar, version 0.9.6 "Keep cool but don't freeze" + * + * Details and latest version at: + * http://dynarch.com/mishoo/calendar.epl + * + * This script is distributed under the GNU Lesser General Public License. + * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html + */ + +// $Id: calendar.js 22 2006-06-23 14:42:15Z ugoletti $ + +/** The Calendar object constructor. */ +Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) { + // member variables + this.activeDiv = null; + this.currentDateEl = null; + this.getDateStatus = null; + this.timeout = null; + this.onSelected = onSelected || null; + this.onClose = onClose || null; + this.dragging = false; + this.hidden = false; + this.minYear = 1970; + this.maxYear = 2050; + this.dateFormat = Calendar._TT["DEF_DATE_FORMAT"]; + this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"]; + this.isPopup = true; + this.weekNumbers = true; + this.firstDayOfWeek = firstDayOfWeek; // 0 for Sunday, 1 for Monday, etc. + this.showsOtherMonths = false; + this.dateStr = dateStr; + this.ar_days = null; + this.showsTime = false; + this.time24 = true; + this.yearStep = 2; + // HTML elements + this.table = null; + this.element = null; + this.tbody = null; + this.firstdayname = null; + // Combo boxes + this.monthsCombo = null; + this.yearsCombo = null; + this.hilitedMonth = null; + this.activeMonth = null; + this.hilitedYear = null; + this.activeYear = null; + // Information + this.dateClicked = false; + + // one-time initializations + if (typeof Calendar._SDN == "undefined") { + // table of short day names + if (typeof Calendar._SDN_len == "undefined") + Calendar._SDN_len = 3; + var ar = new Array(); + for (var i = 8; i > 0;) { + ar[--i] = Calendar._DN[i].substr(0, Calendar._SDN_len); + } + Calendar._SDN = ar; + // table of short month names + if (typeof Calendar._SMN_len == "undefined") + Calendar._SMN_len = 3; + ar = new Array(); + for (var i = 12; i > 0;) { + ar[--i] = Calendar._MN[i].substr(0, Calendar._SMN_len); + } + Calendar._SMN = ar; + } +}; + +// ** constants + +/// "static", needed for event handlers. +Calendar._C = null; + +/// detect a special case of "web browser" +Calendar.is_ie = ( /msie/i.test(navigator.userAgent) && + !/opera/i.test(navigator.userAgent) ); + +Calendar.is_ie5 = ( Calendar.is_ie && /msie 5\.0/i.test(navigator.userAgent) ); + +/// detect Opera browser +Calendar.is_opera = /opera/i.test(navigator.userAgent); + +/// detect KHTML-based browsers +Calendar.is_khtml = /Konqueror|Safari|KHTML/i.test(navigator.userAgent); + +// BEGIN: UTILITY FUNCTIONS; beware that these might be moved into a separate +// library, at some point. + +Calendar.getAbsolutePos = function(el) { + var SL = 0, ST = 0; + var is_div = /^div$/i.test(el.tagName); + if (is_div && el.scrollLeft) + SL = el.scrollLeft; + if (is_div && el.scrollTop) + ST = el.scrollTop; + var r = { x: el.offsetLeft - SL, y: el.offsetTop - ST }; + if (el.offsetParent) { + var tmp = this.getAbsolutePos(el.offsetParent); + r.x += tmp.x; + r.y += tmp.y; + } + return r; +}; + +Calendar.isRelated = function (el, evt) { + var related = evt.relatedTarget; + if (!related) { + var type = evt.type; + if (type == "mouseover") { + related = evt.fromElement; + } else if (type == "mouseout") { + related = evt.toElement; + } + } + while (related) { + if (related == el) { + return true; + } + related = related.parentNode; + } + return false; +}; + +Calendar.removeClass = function(el, className) { + if (!(el && el.className)) { + return; + } + var cls = el.className.split(" "); + var ar = new Array(); + for (var i = cls.length; i > 0;) { + if (cls[--i] != className) { + ar[ar.length] = cls[i]; + } + } + el.className = ar.join(" "); +}; + +Calendar.addClass = function(el, className) { + Calendar.removeClass(el, className); + el.className += " " + className; +}; + +Calendar.getElement = function(ev) { + if (Calendar.is_ie) { + return window.event.srcElement; + } else { + return ev.currentTarget; + } +}; + +Calendar.getTargetElement = function(ev) { + if (Calendar.is_ie) { + return window.event.srcElement; + } else { + return ev.target; + } +}; + +Calendar.stopEvent = function(ev) { + ev || (ev = window.event); + if (Calendar.is_ie) { + ev.cancelBubble = true; + ev.returnValue = false; + } else { + ev.preventDefault(); + ev.stopPropagation(); + } + return false; +}; + +Calendar.addEvent = function(el, evname, func) { + if (el.attachEvent) { // IE + el.attachEvent("on" + evname, func); + } else if (el.addEventListener) { // Gecko / W3C + el.addEventListener(evname, func, true); + } else { + el["on" + evname] = func; + } +}; + +Calendar.removeEvent = function(el, evname, func) { + if (el.detachEvent) { // IE + el.detachEvent("on" + evname, func); + } else if (el.removeEventListener) { // Gecko / W3C + el.removeEventListener(evname, func, true); + } else { + el["on" + evname] = null; + } +}; + +Calendar.createElement = function(type, parent) { + var el = null; + if (document.createElementNS) { + // use the XHTML namespace; IE won't normally get here unless + // _they_ "fix" the DOM2 implementation. + el = document.createElementNS("http://www.w3.org/1999/xhtml", type); + } else { + el = document.createElement(type); + } + if (typeof parent != "undefined") { + parent.appendChild(el); + } + return el; +}; + +// END: UTILITY FUNCTIONS + +// BEGIN: CALENDAR STATIC FUNCTIONS + +/** Internal -- adds a set of events to make some element behave like a button. */ +Calendar._add_evs = function(el) { + with (Calendar) { + addEvent(el, "mouseover", dayMouseOver); + addEvent(el, "mousedown", dayMouseDown); + addEvent(el, "mouseout", dayMouseOut); + if (is_ie) { + addEvent(el, "dblclick", dayMouseDblClick); + el.setAttribute("unselectable", true); + } + } +}; + +Calendar.findMonth = function(el) { + if (typeof el.month != "undefined") { + return el; + } else if (typeof el.parentNode.month != "undefined") { + return el.parentNode; + } + return null; +}; + +Calendar.findYear = function(el) { + if (typeof el.year != "undefined") { + return el; + } else if (typeof el.parentNode.year != "undefined") { + return el.parentNode; + } + return null; +}; + +Calendar.showMonthsCombo = function () { + var cal = Calendar._C; + if (!cal) { + return false; + } + var cal = cal; + var cd = cal.activeDiv; + var mc = cal.monthsCombo; + if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + if (cal.activeMonth) { + Calendar.removeClass(cal.activeMonth, "active"); + } + var mon = cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()]; + Calendar.addClass(mon, "active"); + cal.activeMonth = mon; + var s = mc.style; + s.display = "block"; + if (cd.navtype < 0) + s.left = cd.offsetLeft + "px"; + else { + var mcw = mc.offsetWidth; + if (typeof mcw == "undefined") + // Konqueror brain-dead techniques + mcw = 50; + s.left = (cd.offsetLeft + cd.offsetWidth - mcw) + "px"; + } + s.top = (cd.offsetTop + cd.offsetHeight) + "px"; +}; + +Calendar.showYearsCombo = function (fwd) { + var cal = Calendar._C; + if (!cal) { + return false; + } + var cal = cal; + var cd = cal.activeDiv; + var yc = cal.yearsCombo; + if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + if (cal.activeYear) { + Calendar.removeClass(cal.activeYear, "active"); + } + cal.activeYear = null; + var Y = cal.date.getFullYear() + (fwd ? 1 : -1); + var yr = yc.firstChild; + var show = false; + for (var i = 12; i > 0; --i) { + if (Y >= cal.minYear && Y <= cal.maxYear) { + yr.firstChild.data = Y; + yr.year = Y; + yr.style.display = "block"; + show = true; + } else { + yr.style.display = "none"; + } + yr = yr.nextSibling; + Y += fwd ? cal.yearStep : -cal.yearStep; + } + if (show) { + var s = yc.style; + s.display = "block"; + if (cd.navtype < 0) + s.left = cd.offsetLeft + "px"; + else { + var ycw = yc.offsetWidth; + if (typeof ycw == "undefined") + // Konqueror brain-dead techniques + ycw = 50; + s.left = (cd.offsetLeft + cd.offsetWidth - ycw) + "px"; + } + s.top = (cd.offsetTop + cd.offsetHeight) + "px"; + } +}; + +// event handlers + +Calendar.tableMouseUp = function(ev) { + var cal = Calendar._C; + if (!cal) { + return false; + } + if (cal.timeout) { + clearTimeout(cal.timeout); + } + var el = cal.activeDiv; + if (!el) { + return false; + } + var target = Calendar.getTargetElement(ev); + ev || (ev = window.event); + Calendar.removeClass(el, "active"); + if (target == el || target.parentNode == el) { + Calendar.cellClick(el, ev); + } + var mon = Calendar.findMonth(target); + var date = null; + if (mon) { + date = new Date(cal.date); + if (mon.month != date.getMonth()) { + date.setMonth(mon.month); + cal.setDate(date); + cal.dateClicked = false; + cal.callHandler(); + } + } else { + var year = Calendar.findYear(target); + if (year) { + date = new Date(cal.date); + if (year.year != date.getFullYear()) { + date.setFullYear(year.year); + cal.setDate(date); + cal.dateClicked = false; + cal.callHandler(); + } + } + } + with (Calendar) { + removeEvent(document, "mouseup", tableMouseUp); + removeEvent(document, "mouseover", tableMouseOver); + removeEvent(document, "mousemove", tableMouseOver); + cal._hideCombos(); + _C = null; + return stopEvent(ev); + } +}; + +Calendar.tableMouseOver = function (ev) { + var cal = Calendar._C; + if (!cal) { + return; + } + var el = cal.activeDiv; + var target = Calendar.getTargetElement(ev); + if (target == el || target.parentNode == el) { + Calendar.addClass(el, "hilite active"); + Calendar.addClass(el.parentNode, "rowhilite"); + } else { + if (typeof el.navtype == "undefined" || (el.navtype != 50 && (el.navtype == 0 || Math.abs(el.navtype) > 2))) + Calendar.removeClass(el, "active"); + Calendar.removeClass(el, "hilite"); + Calendar.removeClass(el.parentNode, "rowhilite"); + } + ev || (ev = window.event); + if (el.navtype == 50 && target != el) { + var pos = Calendar.getAbsolutePos(el); + var w = el.offsetWidth; + var x = ev.clientX; + var dx; + var decrease = true; + if (x > pos.x + w) { + dx = x - pos.x - w; + decrease = false; + } else + dx = pos.x - x; + + if (dx < 0) dx = 0; + var range = el._range; + var current = el._current; + var count = Math.floor(dx / 10) % range.length; + for (var i = range.length; --i >= 0;) + if (range[i] == current) + break; + while (count-- > 0) + if (decrease) { + if (--i < 0) + i = range.length - 1; + } else if ( ++i >= range.length ) + i = 0; + var newval = range[i]; + el.firstChild.data = newval; + + cal.onUpdateTime(); + } + var mon = Calendar.findMonth(target); + if (mon) { + if (mon.month != cal.date.getMonth()) { + if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + Calendar.addClass(mon, "hilite"); + cal.hilitedMonth = mon; + } else if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + } else { + if (cal.hilitedMonth) { + Calendar.removeClass(cal.hilitedMonth, "hilite"); + } + var year = Calendar.findYear(target); + if (year) { + if (year.year != cal.date.getFullYear()) { + if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + Calendar.addClass(year, "hilite"); + cal.hilitedYear = year; + } else if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + } else if (cal.hilitedYear) { + Calendar.removeClass(cal.hilitedYear, "hilite"); + } + } + return Calendar.stopEvent(ev); +}; + +Calendar.tableMouseDown = function (ev) { + if (Calendar.getTargetElement(ev) == Calendar.getElement(ev)) { + return Calendar.stopEvent(ev); + } +}; + +Calendar.calDragIt = function (ev) { + var cal = Calendar._C; + if (!(cal && cal.dragging)) { + return false; + } + var posX; + var posY; + if (Calendar.is_ie) { + posY = window.event.clientY + document.body.scrollTop; + posX = window.event.clientX + document.body.scrollLeft; + } else { + posX = ev.pageX; + posY = ev.pageY; + } + cal.hideShowCovered(); + var st = cal.element.style; + st.left = (posX - cal.xOffs) + "px"; + st.top = (posY - cal.yOffs) + "px"; + return Calendar.stopEvent(ev); +}; + +Calendar.calDragEnd = function (ev) { + var cal = Calendar._C; + if (!cal) { + return false; + } + cal.dragging = false; + with (Calendar) { + removeEvent(document, "mousemove", calDragIt); + removeEvent(document, "mouseup", calDragEnd); + tableMouseUp(ev); + } + cal.hideShowCovered(); +}; + +Calendar.dayMouseDown = function(ev) { + var el = Calendar.getElement(ev); + if (el.disabled) { + return false; + } + var cal = el.calendar; + cal.activeDiv = el; + Calendar._C = cal; + if (el.navtype != 300) with (Calendar) { + if (el.navtype == 50) { + el._current = el.firstChild.data; + addEvent(document, "mousemove", tableMouseOver); + } else + addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver); + addClass(el, "hilite active"); + addEvent(document, "mouseup", tableMouseUp); + } else if (cal.isPopup) { + cal._dragStart(ev); + } + if (el.navtype == -1 || el.navtype == 1) { + if (cal.timeout) clearTimeout(cal.timeout); + cal.timeout = setTimeout("Calendar.showMonthsCombo()", 250); + } else if (el.navtype == -2 || el.navtype == 2) { + if (cal.timeout) clearTimeout(cal.timeout); + cal.timeout = setTimeout((el.navtype > 0) ? "Calendar.showYearsCombo(true)" : "Calendar.showYearsCombo(false)", 250); + } else { + cal.timeout = null; + } + return Calendar.stopEvent(ev); +}; + +Calendar.dayMouseDblClick = function(ev) { + Calendar.cellClick(Calendar.getElement(ev), ev || window.event); + if (Calendar.is_ie) { + document.selection.empty(); + } +}; + +Calendar.dayMouseOver = function(ev) { + var el = Calendar.getElement(ev); + if (Calendar.isRelated(el, ev) || Calendar._C || el.disabled) { + return false; + } + if (el.ttip) { + if (el.ttip.substr(0, 1) == "_") { + el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1); + } + el.calendar.tooltips.firstChild.data = el.ttip; + } + if (el.navtype != 300) { + Calendar.addClass(el, "hilite"); + if (el.caldate) { + Calendar.addClass(el.parentNode, "rowhilite"); + } + } + return Calendar.stopEvent(ev); +}; + +Calendar.dayMouseOut = function(ev) { + with (Calendar) { + var el = getElement(ev); + if (isRelated(el, ev) || _C || el.disabled) { + return false; + } + removeClass(el, "hilite"); + if (el.caldate) { + removeClass(el.parentNode, "rowhilite"); + } + el.calendar.tooltips.firstChild.data = _TT["SEL_DATE"]; + return stopEvent(ev); + } +}; + +/** + * A generic "click" handler :) handles all types of buttons defined in this + * calendar. + */ +Calendar.cellClick = function(el, ev) { + var cal = el.calendar; + var closing = false; + var newdate = false; + var date = null; + if (typeof el.navtype == "undefined") { + Calendar.removeClass(cal.currentDateEl, "selected"); + Calendar.addClass(el, "selected"); + closing = (cal.currentDateEl == el); + if (!closing) { + cal.currentDateEl = el; + } + cal.date = new Date(el.caldate); + date = cal.date; + newdate = true; + // a date was clicked + if (!(cal.dateClicked = !el.otherMonth)) + cal._init(cal.firstDayOfWeek, date); + } else { + if (el.navtype == 200) { + Calendar.removeClass(el, "hilite"); + cal.callCloseHandler(); + return; + } + date = (el.navtype == 0) ? new Date() : new Date(cal.date); + // unless "today" was clicked, we assume no date was clicked so + // the selected handler will know not to close the calenar when + // in single-click mode. + // cal.dateClicked = (el.navtype == 0); + cal.dateClicked = false; + var year = date.getFullYear(); + var mon = date.getMonth(); + function setMonth(m) { + var day = date.getDate(); + var max = date.getMonthDays(m); + if (day > max) { + date.setDate(max); + } + date.setMonth(m); + }; + switch (el.navtype) { + case 400: + Calendar.removeClass(el, "hilite"); + var text = Calendar._TT["ABOUT"]; + if (typeof text != "undefined") { + text += cal.showsTime ? Calendar._TT["ABOUT_TIME"] : ""; + } else { + // FIXME: this should be removed as soon as lang files get updated! + text = "Help and about box text is not translated into this language.\n" + + "If you know this language and you feel generous please update\n" + + "the corresponding file in \"lang\" subdir to match calendar-en.js\n" + + "and send it back to <mishoo@infoiasi.ro> to get it into the distribution ;-)\n\n" + + "Thank you!\n" + + "http://dynarch.com/mishoo/calendar.epl\n"; + } + alert(text); + return; + case -2: + if (year > cal.minYear) { + date.setFullYear(year - 1); + } + break; + case -1: + if (mon > 0) { + setMonth(mon - 1); + } else if (year-- > cal.minYear) { + date.setFullYear(year); + setMonth(11); + } + break; + case 1: + if (mon < 11) { + setMonth(mon + 1); + } else if (year < cal.maxYear) { + date.setFullYear(year + 1); + setMonth(0); + } + break; + case 2: + if (year < cal.maxYear) { + date.setFullYear(year + 1); + } + break; + case 100: + cal.setFirstDayOfWeek(el.fdow); + return; + case 50: + var range = el._range; + var current = el.firstChild.data; + for (var i = range.length; --i >= 0;) + if (range[i] == current) + break; + if (ev && ev.shiftKey) { + if (--i < 0) + i = range.length - 1; + } else if ( ++i >= range.length ) + i = 0; + var newval = range[i]; + el.firstChild.data = newval; + cal.onUpdateTime(); + return; + case 0: + // TODAY will bring us here + if ((typeof cal.getDateStatus == "function") && cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) { + // remember, "date" was previously set to new + // Date() if TODAY was clicked; thus, it + // contains today date. + return false; + } + break; + } + if (!date.equalsTo(cal.date)) { + cal.setDate(date); + newdate = true; + } + } + if (newdate) { + cal.callHandler(); + } + if (closing) { + Calendar.removeClass(el, "hilite"); + cal.callCloseHandler(); + } +}; + +// END: CALENDAR STATIC FUNCTIONS + +// BEGIN: CALENDAR OBJECT FUNCTIONS + +/** + * This function creates the calendar inside the given parent. If _par is + * null than it creates a popup calendar inside the BODY element. If _par is + * an element, be it BODY, then it creates a non-popup calendar (still + * hidden). Some properties need to be set before calling this function. + */ +Calendar.prototype.create = function (_par) { + var parent = null; + if (! _par) { + // default parent is the document body, in which case we create + // a popup calendar. + parent = document.getElementsByTagName("body")[0]; + this.isPopup = true; + } else { + parent = _par; + this.isPopup = false; + } + this.date = this.dateStr ? new Date(this.dateStr) : new Date(); + + var table = Calendar.createElement("table"); + this.table = table; + table.cellSpacing = 0; + table.cellPadding = 0; + table.calendar = this; + Calendar.addEvent(table, "mousedown", Calendar.tableMouseDown); + + var div = Calendar.createElement("div"); + this.element = div; + div.className = "calendar"; + if (this.isPopup) { + div.style.position = "absolute"; + div.style.display = "none"; + } + div.appendChild(table); + + var thead = Calendar.createElement("thead", table); + var cell = null; + var row = null; + + var cal = this; + var hh = function (text, cs, navtype) { + cell = Calendar.createElement("td", row); + cell.colSpan = cs; + cell.className = "button"; + if (navtype != 0 && Math.abs(navtype) <= 2) + cell.className += " nav"; + Calendar._add_evs(cell); + cell.calendar = cal; + cell.navtype = navtype; + if (text.substr(0, 1) != "&") { + cell.appendChild(document.createTextNode(text)); + } + else { + // FIXME: dirty hack for entities + cell.innerHTML = text; + } + return cell; + }; + + row = Calendar.createElement("tr", thead); + var title_length = 6; + (this.isPopup) && --title_length; + (this.weekNumbers) && ++title_length; + + hh("?", 1, 400).ttip = Calendar._TT["INFO"]; + this.title = hh("", title_length, 300); + this.title.className = "title"; + if (this.isPopup) { + this.title.ttip = Calendar._TT["DRAG_TO_MOVE"]; + this.title.style.cursor = "move"; + hh("&#x00d7;", 1, 200).ttip = Calendar._TT["CLOSE"]; + } + + row = Calendar.createElement("tr", thead); + row.className = "headrow"; + + this._nav_py = hh("&#x00ab;", 1, -2); + this._nav_py.ttip = Calendar._TT["PREV_YEAR"]; + + this._nav_pm = hh("&#x2039;", 1, -1); + this._nav_pm.ttip = Calendar._TT["PREV_MONTH"]; + + this._nav_now = hh(Calendar._TT["TODAY"], this.weekNumbers ? 4 : 3, 0); + this._nav_now.ttip = Calendar._TT["GO_TODAY"]; + + this._nav_nm = hh("&#x203a;", 1, 1); + this._nav_nm.ttip = Calendar._TT["NEXT_MONTH"]; + + this._nav_ny = hh("&#x00bb;", 1, 2); + this._nav_ny.ttip = Calendar._TT["NEXT_YEAR"]; + + // day names + row = Calendar.createElement("tr", thead); + row.className = "daynames"; + if (this.weekNumbers) { + cell = Calendar.createElement("td", row); + cell.className = "name wn"; + cell.appendChild(document.createTextNode(Calendar._TT["WK"])); + } + for (var i = 7; i > 0; --i) { + cell = Calendar.createElement("td", row); + cell.appendChild(document.createTextNode("")); + if (!i) { + cell.navtype = 100; + cell.calendar = this; + Calendar._add_evs(cell); + } + } + this.firstdayname = (this.weekNumbers) ? row.firstChild.nextSibling : row.firstChild; + this._displayWeekdays(); + + var tbody = Calendar.createElement("tbody", table); + this.tbody = tbody; + + for (i = 6; i > 0; --i) { + row = Calendar.createElement("tr", tbody); + if (this.weekNumbers) { + cell = Calendar.createElement("td", row); + cell.appendChild(document.createTextNode("")); + } + for (var j = 7; j > 0; --j) { + cell = Calendar.createElement("td", row); + cell.appendChild(document.createTextNode("")); + cell.calendar = this; + Calendar._add_evs(cell); + } + } + + if (this.showsTime) { + row = Calendar.createElement("tr", tbody); + row.className = "time"; + + cell = Calendar.createElement("td", row); + cell.className = "time"; + cell.colSpan = 2; + cell.innerHTML = Calendar._TT["TIME"] || "&nbsp;"; + + cell = Calendar.createElement("td", row); + cell.className = "time"; + cell.colSpan = this.weekNumbers ? 4 : 3; + + (function(){ + function makeTimePart(className, init, range_start, range_end) { + var part = Calendar.createElement("span", cell); + part.className = className; + part.appendChild(document.createTextNode(init)); + part.calendar = cal; + part.ttip = Calendar._TT["TIME_PART"]; + part.navtype = 50; + part._range = []; + if (typeof range_start != "number") + part._range = range_start; + else { + for (var i = range_start; i <= range_end; ++i) { + var txt; + if (i < 10 && range_end >= 10) txt = '0' + i; + else txt = '' + i; + part._range[part._range.length] = txt; + } + } + Calendar._add_evs(part); + return part; + }; + var hrs = cal.date.getHours(); + var mins = cal.date.getMinutes(); + var t12 = !cal.time24; + var pm = (hrs > 12); + if (t12 && pm) hrs -= 12; + var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23); + var span = Calendar.createElement("span", cell); + span.appendChild(document.createTextNode(":")); + span.className = "colon"; + var M = makeTimePart("minute", mins, 0, 59); + var AP = null; + cell = Calendar.createElement("td", row); + cell.className = "time"; + cell.colSpan = 2; + if (t12) + AP = makeTimePart("ampm", pm ? "pm" : "am", ["am", "pm"]); + else + cell.innerHTML = "&nbsp;"; + + cal.onSetTime = function() { + var hrs = this.date.getHours(); + var mins = this.date.getMinutes(); + var pm = (hrs > 12); + if (pm && t12) hrs -= 12; + H.firstChild.data = (hrs < 10) ? ("0" + hrs) : hrs; + M.firstChild.data = (mins < 10) ? ("0" + mins) : mins; + if (t12) + AP.firstChild.data = pm ? "pm" : "am"; + }; + + cal.onUpdateTime = function() { + var date = this.date; + var h = parseInt(H.firstChild.data, 10); + if (t12) { + if (/pm/i.test(AP.firstChild.data) && h < 12) + h += 12; + else if (/am/i.test(AP.firstChild.data) && h == 12) + h = 0; + } + var d = date.getDate(); + var m = date.getMonth(); + var y = date.getFullYear(); + date.setHours(h); + date.setMinutes(parseInt(M.firstChild.data, 10)); + date.setFullYear(y); + date.setMonth(m); + date.setDate(d); + this.dateClicked = false; + this.callHandler(); + }; + })(); + } else { + this.onSetTime = this.onUpdateTime = function() {}; + } + + var tfoot = Calendar.createElement("tfoot", table); + + row = Calendar.createElement("tr", tfoot); + row.className = "footrow"; + + cell = hh(Calendar._TT["SEL_DATE"], this.weekNumbers ? 8 : 7, 300); + cell.className = "ttip"; + if (this.isPopup) { + cell.ttip = Calendar._TT["DRAG_TO_MOVE"]; + cell.style.cursor = "move"; + } + this.tooltips = cell; + + div = Calendar.createElement("div", this.element); + this.monthsCombo = div; + div.className = "combo"; + for (i = 0; i < Calendar._MN.length; ++i) { + var mn = Calendar.createElement("div"); + mn.className = Calendar.is_ie ? "label-IEfix" : "label"; + mn.month = i; + mn.appendChild(document.createTextNode(Calendar._SMN[i])); + div.appendChild(mn); + } + + div = Calendar.createElement("div", this.element); + this.yearsCombo = div; + div.className = "combo"; + for (i = 12; i > 0; --i) { + var yr = Calendar.createElement("div"); + yr.className = Calendar.is_ie ? "label-IEfix" : "label"; + yr.appendChild(document.createTextNode("")); + div.appendChild(yr); + } + + this._init(this.firstDayOfWeek, this.date); + parent.appendChild(this.element); +}; + +/** keyboard navigation, only for popup calendars */ +Calendar._keyEvent = function(ev) { + if (!window.calendar) { + return false; + } + (Calendar.is_ie) && (ev = window.event); + var cal = window.calendar; + var act = (Calendar.is_ie || ev.type == "keypress"); + if (ev.ctrlKey) { + switch (ev.keyCode) { + case 37: // KEY left + act && Calendar.cellClick(cal._nav_pm); + break; + case 38: // KEY up + act && Calendar.cellClick(cal._nav_py); + break; + case 39: // KEY right + act && Calendar.cellClick(cal._nav_nm); + break; + case 40: // KEY down + act && Calendar.cellClick(cal._nav_ny); + break; + default: + return false; + } + } else switch (ev.keyCode) { + case 32: // KEY space (now) + Calendar.cellClick(cal._nav_now); + break; + case 27: // KEY esc + act && cal.callCloseHandler(); + break; + case 37: // KEY left + case 38: // KEY up + case 39: // KEY right + case 40: // KEY down + if (act) { + var date = cal.date.getDate() - 1; + var el = cal.currentDateEl; + var ne = null; + var prev = (ev.keyCode == 37) || (ev.keyCode == 38); + switch (ev.keyCode) { + case 37: // KEY left + (--date >= 0) && (ne = cal.ar_days[date]); + break; + case 38: // KEY up + date -= 7; + (date >= 0) && (ne = cal.ar_days[date]); + break; + case 39: // KEY right + (++date < cal.ar_days.length) && (ne = cal.ar_days[date]); + break; + case 40: // KEY down + date += 7; + (date < cal.ar_days.length) && (ne = cal.ar_days[date]); + break; + } + if (!ne) { + if (prev) { + Calendar.cellClick(cal._nav_pm); + } else { + Calendar.cellClick(cal._nav_nm); + } + date = (prev) ? cal.date.getMonthDays() : 1; + el = cal.currentDateEl; + ne = cal.ar_days[date - 1]; + } + Calendar.removeClass(el, "selected"); + Calendar.addClass(ne, "selected"); + cal.date = new Date(ne.caldate); + cal.callHandler(); + cal.currentDateEl = ne; + } + break; + case 13: // KEY enter + if (act) { + cal.callHandler(); + cal.hide(); + } + break; + default: + return false; + } + return Calendar.stopEvent(ev); +}; + +/** + * (RE)Initializes the calendar to the given date and firstDayOfWeek + */ +Calendar.prototype._init = function (firstDayOfWeek, date) { + var today = new Date(); + this.table.style.visibility = "hidden"; + var year = date.getFullYear(); + if (year < this.minYear) { + year = this.minYear; + date.setFullYear(year); + } else if (year > this.maxYear) { + year = this.maxYear; + date.setFullYear(year); + } + this.firstDayOfWeek = firstDayOfWeek; + this.date = new Date(date); + var month = date.getMonth(); + var mday = date.getDate(); + var no_days = date.getMonthDays(); + + // calendar voodoo for computing the first day that would actually be + // displayed in the calendar, even if it's from the previous month. + // WARNING: this is magic. ;-) + date.setDate(1); + var day1 = (date.getDay() - this.firstDayOfWeek) % 7; + if (day1 < 0) + day1 += 7; + date.setDate(-day1); + date.setDate(date.getDate() + 1); + + var row = this.tbody.firstChild; + var MN = Calendar._SMN[month]; + var ar_days = new Array(); + var weekend = Calendar._TT["WEEKEND"]; + for (var i = 0; i < 6; ++i, row = row.nextSibling) { + var cell = row.firstChild; + if (this.weekNumbers) { + cell.className = "day wn"; + cell.firstChild.data = date.getWeekNumber(); + cell = cell.nextSibling; + } + row.className = "daysrow"; + var hasdays = false; + for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(date.getDate() + 1)) { + var iday = date.getDate(); + var wday = date.getDay(); + cell.className = "day"; + var current_month = (date.getMonth() == month); + if (!current_month) { + if (this.showsOtherMonths) { + cell.className += " othermonth"; + cell.otherMonth = true; + } else { + cell.className = "emptycell"; + cell.innerHTML = "&nbsp;"; + cell.disabled = true; + continue; + } + } else { + cell.otherMonth = false; + hasdays = true; + } + cell.disabled = false; + cell.firstChild.data = iday; + if (typeof this.getDateStatus == "function") { + var status = this.getDateStatus(date, year, month, iday); + if (status === true) { + cell.className += " disabled"; + cell.disabled = true; + } else { + if (/disabled/i.test(status)) + cell.disabled = true; + cell.className += " " + status; + } + } + if (!cell.disabled) { + ar_days[ar_days.length] = cell; + cell.caldate = new Date(date); + cell.ttip = "_"; + if (current_month && iday == mday) { + cell.className += " selected"; + this.currentDateEl = cell; + } + if (date.getFullYear() == today.getFullYear() && + date.getMonth() == today.getMonth() && + iday == today.getDate()) { + cell.className += " today"; + cell.ttip += Calendar._TT["PART_TODAY"]; + } + if (weekend.indexOf(wday.toString()) != -1) { + cell.className += cell.otherMonth ? " oweekend" : " weekend"; + } + } + } + if (!(hasdays || this.showsOtherMonths)) + row.className = "emptyrow"; + } + this.ar_days = ar_days; + this.title.firstChild.data = Calendar._MN[month] + ", " + year; + this.onSetTime(); + this.table.style.visibility = "visible"; + // PROFILE + // this.tooltips.firstChild.data = "Generated in " + ((new Date()) - today) + " ms"; +}; + +/** + * Calls _init function above for going to a certain date (but only if the + * date is different than the currently selected one). + */ +Calendar.prototype.setDate = function (date) { + if (!date.equalsTo(this.date)) { + this._init(this.firstDayOfWeek, date); + } +}; + +/** + * Refreshes the calendar. Useful if the "disabledHandler" function is + * dynamic, meaning that the list of disabled date can change at runtime. + * Just * call this function if you think that the list of disabled dates + * should * change. + */ +Calendar.prototype.refresh = function () { + this._init(this.firstDayOfWeek, this.date); +}; + +/** Modifies the "firstDayOfWeek" parameter (pass 0 for Synday, 1 for Monday, etc.). */ +Calendar.prototype.setFirstDayOfWeek = function (firstDayOfWeek) { + this._init(firstDayOfWeek, this.date); + this._displayWeekdays(); +}; + +/** + * Allows customization of what dates are enabled. The "unaryFunction" + * parameter must be a function object that receives the date (as a JS Date + * object) and returns a boolean value. If the returned value is true then + * the passed date will be marked as disabled. + */ +Calendar.prototype.setDateStatusHandler = Calendar.prototype.setDisabledHandler = function (unaryFunction) { + this.getDateStatus = unaryFunction; +}; + +/** Customization of allowed year range for the calendar. */ +Calendar.prototype.setRange = function (a, z) { + this.minYear = a; + this.maxYear = z; +}; + +/** Calls the first user handler (selectedHandler). */ +Calendar.prototype.callHandler = function () { + if (this.onSelected) { + this.onSelected(this, this.date.print(this.dateFormat)); + } +}; + +/** Calls the second user handler (closeHandler). */ +Calendar.prototype.callCloseHandler = function () { + if (this.onClose) { + this.onClose(this); + } + this.hideShowCovered(); +}; + +/** Removes the calendar object from the DOM tree and destroys it. */ +Calendar.prototype.destroy = function () { + var el = this.element.parentNode; + el.removeChild(this.element); + Calendar._C = null; + window.calendar = null; +}; + +/** + * Moves the calendar element to a different section in the DOM tree (changes + * its parent). + */ +Calendar.prototype.reparent = function (new_parent) { + var el = this.element; + el.parentNode.removeChild(el); + new_parent.appendChild(el); +}; + +// This gets called when the user presses a mouse button anywhere in the +// document, if the calendar is shown. If the click was outside the open +// calendar this function closes it. +Calendar._checkCalendar = function(ev) { + if (!window.calendar) { + return false; + } + var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev); + for (; el != null && el != calendar.element; el = el.parentNode); + if (el == null) { + // calls closeHandler which should hide the calendar. + window.calendar.callCloseHandler(); + return Calendar.stopEvent(ev); + } +}; + +/** Shows the calendar. */ +Calendar.prototype.show = function () { + var rows = this.table.getElementsByTagName("tr"); + for (var i = rows.length; i > 0;) { + var row = rows[--i]; + Calendar.removeClass(row, "rowhilite"); + var cells = row.getElementsByTagName("td"); + for (var j = cells.length; j > 0;) { + var cell = cells[--j]; + Calendar.removeClass(cell, "hilite"); + Calendar.removeClass(cell, "active"); + } + } + this.element.style.display = "block"; + this.hidden = false; + if (this.isPopup) { + window.calendar = this; + Calendar.addEvent(document, "keydown", Calendar._keyEvent); + Calendar.addEvent(document, "keypress", Calendar._keyEvent); + Calendar.addEvent(document, "mousedown", Calendar._checkCalendar); + } + this.hideShowCovered(); +}; + +/** + * Hides the calendar. Also removes any "hilite" from the class of any TD + * element. + */ +Calendar.prototype.hide = function () { + if (this.isPopup) { + Calendar.removeEvent(document, "keydown", Calendar._keyEvent); + Calendar.removeEvent(document, "keypress", Calendar._keyEvent); + Calendar.removeEvent(document, "mousedown", Calendar._checkCalendar); + } + this.element.style.display = "none"; + this.hidden = true; + this.hideShowCovered(); +}; + +/** + * Shows the calendar at a given absolute position (beware that, depending on + * the calendar element style -- position property -- this might be relative + * to the parent's containing rectangle). + */ +Calendar.prototype.showAt = function (x, y) { + var s = this.element.style; + s.left = x + "px"; + s.top = y + "px"; + this.show(); +}; + +/** Shows the calendar near a given element. */ +Calendar.prototype.showAtElement = function (el, opts) { + var self = this; + var p = Calendar.getAbsolutePos(el); + if (!opts || typeof opts != "string") { + this.showAt(p.x, p.y + el.offsetHeight); + return true; + } + function fixPosition(box) { + if (box.x < 0) + box.x = 0; + if (box.y < 0) + box.y = 0; + var cp = document.createElement("div"); + var s = cp.style; + s.position = "absolute"; + s.right = s.bottom = s.width = s.height = "0px"; + document.body.appendChild(cp); + var br = Calendar.getAbsolutePos(cp); + document.body.removeChild(cp); + if (Calendar.is_ie) { + br.y += document.body.scrollTop; + br.x += document.body.scrollLeft; + } else { + br.y += window.scrollY; + br.x += window.scrollX; + } + var tmp = box.x + box.width - br.x; + if (tmp > 0) box.x -= tmp; + tmp = box.y + box.height - br.y; + if (tmp > 0) box.y -= tmp; + }; + this.element.style.display = "block"; + Calendar.continuation_for_the_fucking_khtml_browser = function() { + var w = self.element.offsetWidth; + var h = self.element.offsetHeight; + self.element.style.display = "none"; + var valign = opts.substr(0, 1); + var halign = "l"; + if (opts.length > 1) { + halign = opts.substr(1, 1); + } + // vertical alignment + switch (valign) { + case "T": p.y -= h; break; + case "B": p.y += el.offsetHeight; break; + case "C": p.y += (el.offsetHeight - h) / 2; break; + case "t": p.y += el.offsetHeight - h; break; + case "b": break; // already there + } + // horizontal alignment + switch (halign) { + case "L": p.x -= w; break; + case "R": p.x += el.offsetWidth; break; + case "C": p.x += (el.offsetWidth - w) / 2; break; + case "r": p.x += el.offsetWidth - w; break; + case "l": break; // already there + } + p.width = w; + p.height = h + 40; + self.monthsCombo.style.display = "none"; + fixPosition(p); + self.showAt(p.x, p.y); + }; + if (Calendar.is_khtml) + setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10); + else + Calendar.continuation_for_the_fucking_khtml_browser(); +}; + +/** Customizes the date format. */ +Calendar.prototype.setDateFormat = function (str) { + this.dateFormat = str; +}; + +/** Customizes the tooltip date format. */ +Calendar.prototype.setTtDateFormat = function (str) { + this.ttDateFormat = str; +}; + +/** + * Tries to identify the date represented in a string. If successful it also + * calls this.setDate which moves the calendar to the given date. + */ +Calendar.prototype.parseDate = function (str, fmt) { + var y = 0; + var m = -1; + var d = 0; + var a = str.split(/\W+/); + if (!fmt) { + fmt = this.dateFormat; + } + var b = fmt.match(/%./g); + var i = 0, j = 0; + var hr = 0; + var min = 0; + for (i = 0; i < a.length; ++i) { + if (!a[i]) + continue; + switch (b[i]) { + case "%d": + case "%e": + d = parseInt(a[i], 10); + break; + + case "%m": + m = parseInt(a[i], 10) - 1; + break; + + case "%Y": + case "%y": + y = parseInt(a[i], 10); + (y < 100) && (y += (y > 29) ? 1900 : 2000); + break; + + case "%b": + case "%B": + for (j = 0; j < 12; ++j) { + if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { m = j; break; } + } + break; + + case "%H": + case "%I": + case "%k": + case "%l": + hr = parseInt(a[i], 10); + break; + + case "%P": + case "%p": + if (/pm/i.test(a[i]) && hr < 12) + hr += 12; + break; + + case "%M": + min = parseInt(a[i], 10); + break; + } + } + if (y != 0 && m != -1 && d != 0) { + this.setDate(new Date(y, m, d, hr, min, 0)); + return; + } + y = 0; m = -1; d = 0; + for (i = 0; i < a.length; ++i) { + if (a[i].search(/[a-zA-Z]+/) != -1) { + var t = -1; + for (j = 0; j < 12; ++j) { + if (Calendar._MN[j].substr(0, a[i].length).toLowerCase() == a[i].toLowerCase()) { t = j; break; } + } + if (t != -1) { + if (m != -1) { + d = m+1; + } + m = t; + } + } else if (parseInt(a[i], 10) <= 12 && m == -1) { + m = a[i]-1; + } else if (parseInt(a[i], 10) > 31 && y == 0) { + y = parseInt(a[i], 10); + (y < 100) && (y += (y > 29) ? 1900 : 2000); + } else if (d == 0) { + d = a[i]; + } + } + if (y == 0) { + var today = new Date(); + y = today.getFullYear(); + } + if (m != -1 && d != 0) { + this.setDate(new Date(y, m, d, hr, min, 0)); + } +}; + +Calendar.prototype.hideShowCovered = function () { + var self = this; + Calendar.continuation_for_the_fucking_khtml_browser = function() { + function getVisib(obj){ + var value = obj.style.visibility; + if (!value) { + if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C + if (!Calendar.is_khtml) + value = document.defaultView. + getComputedStyle(obj, "").getPropertyValue("visibility"); + else + value = ''; + } else if (obj.currentStyle) { // IE + value = obj.currentStyle.visibility; + } else + value = ''; + } + return value; + }; + + var tags = new Array("applet", "iframe", "select"); + var el = self.element; + + var p = Calendar.getAbsolutePos(el); + var EX1 = p.x; + var EX2 = el.offsetWidth + EX1; + var EY1 = p.y; + var EY2 = el.offsetHeight + EY1; + + for (var k = tags.length; k > 0; ) { + var ar = document.getElementsByTagName(tags[--k]); + var cc = null; + + for (var i = ar.length; i > 0;) { + cc = ar[--i]; + + p = Calendar.getAbsolutePos(cc); + var CX1 = p.x; + var CX2 = cc.offsetWidth + CX1; + var CY1 = p.y; + var CY2 = cc.offsetHeight + CY1; + + if (self.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) { + if (!cc.__msh_save_visibility) { + cc.__msh_save_visibility = getVisib(cc); + } + cc.style.visibility = cc.__msh_save_visibility; + } else { + if (!cc.__msh_save_visibility) { + cc.__msh_save_visibility = getVisib(cc); + } + cc.style.visibility = "hidden"; + } + } + } + }; + if (Calendar.is_khtml) + setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10); + else + Calendar.continuation_for_the_fucking_khtml_browser(); +}; + +/** Internal function; it displays the bar with the names of the weekday. */ +Calendar.prototype._displayWeekdays = function () { + var fdow = this.firstDayOfWeek; + var cell = this.firstdayname; + var weekend = Calendar._TT["WEEKEND"]; + for (var i = 0; i < 7; ++i) { + cell.className = "day name"; + var realday = (i + fdow) % 7; + if (i) { + cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]); + cell.navtype = 100; + cell.calendar = this; + cell.fdow = realday; + Calendar._add_evs(cell); + } + if (weekend.indexOf(realday.toString()) != -1) { + Calendar.addClass(cell, "weekend"); + } + cell.firstChild.data = Calendar._SDN[(i + fdow) % 7]; + cell = cell.nextSibling; + } +}; + +/** Internal function. Hides all combo boxes that might be displayed. */ +Calendar.prototype._hideCombos = function () { + this.monthsCombo.style.display = "none"; + this.yearsCombo.style.display = "none"; +}; + +/** Internal function. Starts dragging the element. */ +Calendar.prototype._dragStart = function (ev) { + if (this.dragging) { + return; + } + this.dragging = true; + var posX; + var posY; + if (Calendar.is_ie) { + posY = window.event.clientY + document.body.scrollTop; + posX = window.event.clientX + document.body.scrollLeft; + } else { + posY = ev.clientY + window.scrollY; + posX = ev.clientX + window.scrollX; + } + var st = this.element.style; + this.xOffs = posX - parseInt(st.left); + this.yOffs = posY - parseInt(st.top); + with (Calendar) { + addEvent(document, "mousemove", calDragIt); + addEvent(document, "mouseup", calDragEnd); + } +}; + +// BEGIN: DATE OBJECT PATCHES + +/** Adds the number of days array to the Date object. */ +Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); + +/** Constants used for time computations */ +Date.SECOND = 1000 /* milliseconds */; +Date.MINUTE = 60 * Date.SECOND; +Date.HOUR = 60 * Date.MINUTE; +Date.DAY = 24 * Date.HOUR; +Date.WEEK = 7 * Date.DAY; + +/** Returns the number of days in the current month */ +Date.prototype.getMonthDays = function(month) { + var year = this.getFullYear(); + if (typeof month == "undefined") { + month = this.getMonth(); + } + if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) { + return 29; + } else { + return Date._MD[month]; + } +}; + +/** Returns the number of day in the year. */ +Date.prototype.getDayOfYear = function() { + var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); + var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0); + var time = now - then; + return Math.floor(time / Date.DAY); +}; + +/** Returns the number of the week in year, as defined in ISO 8601. */ +Date.prototype.getWeekNumber = function() { + var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); + var DoW = d.getDay(); + d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu + var ms = d.valueOf(); // GMT + d.setMonth(0); + d.setDate(4); // Thu in Week 1 + return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1; +}; + +/** Checks dates equality (ignores time) */ +Date.prototype.equalsTo = function(date) { + return ((this.getFullYear() == date.getFullYear()) && + (this.getMonth() == date.getMonth()) && + (this.getDate() == date.getDate()) && + (this.getHours() == date.getHours()) && + (this.getMinutes() == date.getMinutes())); +}; + +/** Prints the date in a string according to the given format. */ +Date.prototype.print = function (str) { + var m = this.getMonth(); + var d = this.getDate(); + var y = this.getFullYear(); + var wn = this.getWeekNumber(); + var w = this.getDay(); + var s = {}; + var hr = this.getHours(); + var pm = (hr >= 12); + var ir = (pm) ? (hr - 12) : hr; + var dy = this.getDayOfYear(); + if (ir == 0) + ir = 12; + var min = this.getMinutes(); + var sec = this.getSeconds(); + s["%a"] = Calendar._SDN[w]; // abbreviated weekday name [FIXME: I18N] + s["%A"] = Calendar._DN[w]; // full weekday name + s["%b"] = Calendar._SMN[m]; // abbreviated month name [FIXME: I18N] + s["%B"] = Calendar._MN[m]; // full month name + // FIXME: %c : preferred date and time representation for the current locale + s["%C"] = 1 + Math.floor(y / 100); // the century number + s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31) + s["%e"] = d; // the day of the month (range 1 to 31) + // FIXME: %D : american date style: %m/%d/%y + // FIXME: %E, %F, %G, %g, %h (man strftime) + s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format) + s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format) + s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366) + s["%k"] = hr; // hour, range 0 to 23 (24h format) + s["%l"] = ir; // hour, range 1 to 12 (12h format) + s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12 + s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59 + s["%n"] = "\n"; // a newline character + s["%p"] = pm ? "PM" : "AM"; + s["%P"] = pm ? "pm" : "am"; + // FIXME: %r : the time in am/pm notation %I:%M:%S %p + // FIXME: %R : the time in 24-hour notation %H:%M + s["%s"] = Math.floor(this.getTime() / 1000); + s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59 + s["%t"] = "\t"; // a tab character + // FIXME: %T : the time in 24-hour notation (%H:%M:%S) + s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn; + s["%u"] = w + 1; // the day of the week (range 1 to 7, 1 = MON) + s["%w"] = w; // the day of the week (range 0 to 6, 0 = SUN) + // FIXME: %x : preferred date representation for the current locale without the time + // FIXME: %X : preferred time representation for the current locale without the date + s["%y"] = ('' + y).substr(2, 2); // year without the century (range 00 to 99) + s["%Y"] = y; // year with the century + s["%%"] = "%"; // a literal '%' character + + var re = /%./g; + if (!Calendar.is_ie5) + return str.replace(re, function (par) { return s[par] || par; }); + + var a = str.match(re); + for (var i = 0; i < a.length; i++) { + var tmp = s[a[i]]; + if (tmp) { + re = new RegExp(a[i], 'g'); + str = str.replace(re, tmp); + } + } + + return str; +}; + +Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; +Date.prototype.setFullYear = function(y) { + var d = new Date(this); + d.__msh_oldSetFullYear(y); + if (d.getMonth() != this.getMonth()) + this.setDate(28); + this.__msh_oldSetFullYear(y); +}; + +// END: DATE OBJECT PATCHES + + +// global object that remembers the calendar +window.calendar = null; diff --git a/src/core/static/js/jscalendar/calendar.php b/src/core/static/js/jscalendar/calendar.php new file mode 100755 index 0000000..c9d0406 --- /dev/null +++ b/src/core/static/js/jscalendar/calendar.php @@ -0,0 +1,119 @@ +<?php + +/** + * File: calendar.php | (c) dynarch.com 2004 + * Distributed as part of "The Coolest DHTML Calendar" + * under the same terms. + * ----------------------------------------------------------------- + * This file implements a simple PHP wrapper for the calendar. It + * allows you to easily include all the calendar files and setup the + * calendar by instantiating and calling a PHP object. + */ + +define('NEWLINE', "\n"); + +class DHTML_Calendar { + var $calendar_lib_path; + + var $calendar_file; + var $calendar_lang_file; + var $calendar_setup_file; + var $calendar_theme_file; + var $calendar_options; + + function DHTML_Calendar($calendar_lib_path = '/calendar/', + $lang = 'en', + $theme = 'calendar-win2k-1', + $stripped = true) { + if ($stripped) { + $this->calendar_file = 'calendar_stripped.js'; + $this->calendar_setup_file = 'calendar-setup_stripped.js'; + } else { + $this->calendar_file = 'calendar.js'; + $this->calendar_setup_file = 'calendar-setup.js'; + } + $this->calendar_lang_file = 'lang/calendar-' . $lang . '.js'; + $this->calendar_theme_file = $theme.'.css'; + $this->calendar_lib_path = preg_replace('/\/+$/', '/', $calendar_lib_path); + $this->calendar_options = array('ifFormat' => '%Y/%m/%d', + 'daFormat' => '%Y/%m/%d'); + } + + function set_option($name, $value) { + $this->calendar_options[$name] = $value; + } + + function load_files() { + echo $this->get_load_files_code(); + } + + function get_load_files_code() { + $code = ( '<link rel="stylesheet" type="text/css" media="all" href="' . + $this->calendar_lib_path . $this->calendar_theme_file . + '" />' . NEWLINE ); + $code .= ( '<script type="text/javascript" src="' . + $this->calendar_lib_path . $this->calendar_file . + '"></script>' . NEWLINE ); + $code .= ( '<script type="text/javascript" src="' . + $this->calendar_lib_path . $this->calendar_lang_file . + '"></script>' . NEWLINE ); + $code .= ( '<script type="text/javascript" src="' . + $this->calendar_lib_path . $this->calendar_setup_file . + '"></script>' ); + return $code; + } + + function _make_calendar($other_options = array()) { + $js_options = $this->_make_js_hash(array_merge($this->calendar_options, $other_options)); + $code = ( '<script type="text/javascript">Calendar.setup({' . + $js_options . + '});</script>' ); + return $code; + } + + function make_input_field($cal_options = array(), $field_attributes = array()) { + $id = $this->_gen_id(); + $attrstr = $this->_make_html_attr(array_merge($field_attributes, + array('id' => $this->_field_id($id), + 'type' => 'text'))); + echo '<input ' . $attrstr .'/>'; + echo '<a href="#" id="'. $this->_trigger_id($id) . '">' . + '<img align="middle" border="0" src="' . $this->calendar_lib_path . 'img.gif" alt="" /></a>'; + + $options = array_merge($cal_options, + array('inputField' => $this->_field_id($id), + 'button' => $this->_trigger_id($id))); + echo $this->_make_calendar($options); + } + + /// PRIVATE SECTION + + function _field_id($id) { return 'f-calendar-field-' . $id; } + function _trigger_id($id) { return 'f-calendar-trigger-' . $id; } + function _gen_id() { static $id = 0; return ++$id; } + + function _make_js_hash($array) { + $jstr = ''; + reset($array); + while (list($key, $val) = each($array)) { + if (is_bool($val)) + $val = $val ? 'true' : 'false'; + else if (!is_numeric($val)) + $val = '"'.$val.'"'; + if ($jstr) $jstr .= ','; + $jstr .= '"' . $key . '":' . $val; + } + return $jstr; + } + + function _make_html_attr($array) { + $attrstr = ''; + reset($array); + while (list($key, $val) = each($array)) { + $attrstr .= $key . '="' . $val . '" '; + } + return $attrstr; + } +}; + +?> \ No newline at end of file diff --git a/src/core/static/js/jscalendar/calendar_stripped.js b/src/core/static/js/jscalendar/calendar_stripped.js new file mode 100755 index 0000000..fdab0e1 --- /dev/null +++ b/src/core/static/js/jscalendar/calendar_stripped.js @@ -0,0 +1,12 @@ +/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/ + * ------------------------------------------------------------------ + * + * The DHTML Calendar, version 0.9.6 "Keep cool but don't freeze" + * + * Details and latest version at: + * http://dynarch.com/mishoo/calendar.epl + * + * This script is distributed under the GNU Lesser General Public License. + * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html + */ + Calendar=function(firstDayOfWeek,dateStr,onSelected,onClose){this.activeDiv=null;this.currentDateEl=null;this.getDateStatus=null;this.timeout=null;this.onSelected=onSelected||null;this.onClose=onClose||null;this.dragging=false;this.hidden=false;this.minYear=1970;this.maxYear=2050;this.dateFormat=Calendar._TT["DEF_DATE_FORMAT"];this.ttDateFormat=Calendar._TT["TT_DATE_FORMAT"];this.isPopup=true;this.weekNumbers=true;this.firstDayOfWeek=firstDayOfWeek;this.showsOtherMonths=false;this.dateStr=dateStr;this.ar_days=null;this.showsTime=false;this.time24=true;this.yearStep=2;this.table=null;this.element=null;this.tbody=null;this.firstdayname=null;this.monthsCombo=null;this.yearsCombo=null;this.hilitedMonth=null;this.activeMonth=null;this.hilitedYear=null;this.activeYear=null;this.dateClicked=false;if(typeof Calendar._SDN=="undefined"){if(typeof Calendar._SDN_len=="undefined")Calendar._SDN_len=3;var ar=new Array();for(var i=8;i>0;){ar[--i]=Calendar._DN[i].substr(0,Calendar._SDN_len);}Calendar._SDN=ar;if(typeof Calendar._SMN_len=="undefined")Calendar._SMN_len=3;ar=new Array();for(var i=12;i>0;){ar[--i]=Calendar._MN[i].substr(0,Calendar._SMN_len);}Calendar._SMN=ar;}};Calendar._C=null;Calendar.is_ie=(/msie/i.test(navigator.userAgent)&&!/opera/i.test(navigator.userAgent));Calendar.is_ie5=(Calendar.is_ie&&/msie 5\.0/i.test(navigator.userAgent));Calendar.is_opera=/opera/i.test(navigator.userAgent);Calendar.is_khtml=/Konqueror|Safari|KHTML/i.test(navigator.userAgent);Calendar.getAbsolutePos=function(el){var SL=0,ST=0;var is_div=/^div$/i.test(el.tagName);if(is_div&&el.scrollLeft)SL=el.scrollLeft;if(is_div&&el.scrollTop)ST=el.scrollTop;var r={x:el.offsetLeft-SL,y:el.offsetTop-ST};if(el.offsetParent){var tmp=this.getAbsolutePos(el.offsetParent);r.x+=tmp.x;r.y+=tmp.y;}return r;};Calendar.isRelated=function(el,evt){var related=evt.relatedTarget;if(!related){var type=evt.type;if(type=="mouseover"){related=evt.fromElement;}else if(type=="mouseout"){related=evt.toElement;}}while(related){if(related==el){return true;}related=related.parentNode;}return false;};Calendar.removeClass=function(el,className){if(!(el&&el.className)){return;}var cls=el.className.split(" ");var ar=new Array();for(var i=cls.length;i>0;){if(cls[--i]!=className){ar[ar.length]=cls[i];}}el.className=ar.join(" ");};Calendar.addClass=function(el,className){Calendar.removeClass(el,className);el.className+=" "+className;};Calendar.getElement=function(ev){if(Calendar.is_ie){return window.event.srcElement;}else{return ev.currentTarget;}};Calendar.getTargetElement=function(ev){if(Calendar.is_ie){return window.event.srcElement;}else{return ev.target;}};Calendar.stopEvent=function(ev){ev||(ev=window.event);if(Calendar.is_ie){ev.cancelBubble=true;ev.returnValue=false;}else{ev.preventDefault();ev.stopPropagation();}return false;};Calendar.addEvent=function(el,evname,func){if(el.attachEvent){el.attachEvent("on"+evname,func);}else if(el.addEventListener){el.addEventListener(evname,func,true);}else{el["on"+evname]=func;}};Calendar.removeEvent=function(el,evname,func){if(el.detachEvent){el.detachEvent("on"+evname,func);}else if(el.removeEventListener){el.removeEventListener(evname,func,true);}else{el["on"+evname]=null;}};Calendar.createElement=function(type,parent){var el=null;if(document.createElementNS){el=document.createElementNS("http://www.w3.org/1999/xhtml",type);}else{el=document.createElement(type);}if(typeof parent!="undefined"){parent.appendChild(el);}return el;};Calendar._add_evs=function(el){with(Calendar){addEvent(el,"mouseover",dayMouseOver);addEvent(el,"mousedown",dayMouseDown);addEvent(el,"mouseout",dayMouseOut);if(is_ie){addEvent(el,"dblclick",dayMouseDblClick);el.setAttribute("unselectable",true);}}};Calendar.findMonth=function(el){if(typeof el.month!="undefined"){return el;}else if(typeof el.parentNode.month!="undefined"){return el.parentNode;}return null;};Calendar.findYear=function(el){if(typeof el.year!="undefined"){return el;}else if(typeof el.parentNode.year!="undefined"){return el.parentNode;}return null;};Calendar.showMonthsCombo=function(){var cal=Calendar._C;if(!cal){return false;}var cal=cal;var cd=cal.activeDiv;var mc=cal.monthsCombo;if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}if(cal.activeMonth){Calendar.removeClass(cal.activeMonth,"active");}var mon=cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];Calendar.addClass(mon,"active");cal.activeMonth=mon;var s=mc.style;s.display="block";if(cd.navtype<0)s.left=cd.offsetLeft+"px";else{var mcw=mc.offsetWidth;if(typeof mcw=="undefined")mcw=50;s.left=(cd.offsetLeft+cd.offsetWidth-mcw)+"px";}s.top=(cd.offsetTop+cd.offsetHeight)+"px";};Calendar.showYearsCombo=function(fwd){var cal=Calendar._C;if(!cal){return false;}var cal=cal;var cd=cal.activeDiv;var yc=cal.yearsCombo;if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}if(cal.activeYear){Calendar.removeClass(cal.activeYear,"active");}cal.activeYear=null;var Y=cal.date.getFullYear()+(fwd?1:-1);var yr=yc.firstChild;var show=false;for(var i=12;i>0;--i){if(Y>=cal.minYear&&Y<=cal.maxYear){yr.firstChild.data=Y;yr.year=Y;yr.style.display="block";show=true;}else{yr.style.display="none";}yr=yr.nextSibling;Y+=fwd?cal.yearStep:-cal.yearStep;}if(show){var s=yc.style;s.display="block";if(cd.navtype<0)s.left=cd.offsetLeft+"px";else{var ycw=yc.offsetWidth;if(typeof ycw=="undefined")ycw=50;s.left=(cd.offsetLeft+cd.offsetWidth-ycw)+"px";}s.top=(cd.offsetTop+cd.offsetHeight)+"px";}};Calendar.tableMouseUp=function(ev){var cal=Calendar._C;if(!cal){return false;}if(cal.timeout){clearTimeout(cal.timeout);}var el=cal.activeDiv;if(!el){return false;}var target=Calendar.getTargetElement(ev);ev||(ev=window.event);Calendar.removeClass(el,"active");if(target==el||target.parentNode==el){Calendar.cellClick(el,ev);}var mon=Calendar.findMonth(target);var date=null;if(mon){date=new Date(cal.date);if(mon.month!=date.getMonth()){date.setMonth(mon.month);cal.setDate(date);cal.dateClicked=false;cal.callHandler();}}else{var year=Calendar.findYear(target);if(year){date=new Date(cal.date);if(year.year!=date.getFullYear()){date.setFullYear(year.year);cal.setDate(date);cal.dateClicked=false;cal.callHandler();}}}with(Calendar){removeEvent(document,"mouseup",tableMouseUp);removeEvent(document,"mouseover",tableMouseOver);removeEvent(document,"mousemove",tableMouseOver);cal._hideCombos();_C=null;return stopEvent(ev);}};Calendar.tableMouseOver=function(ev){var cal=Calendar._C;if(!cal){return;}var el=cal.activeDiv;var target=Calendar.getTargetElement(ev);if(target==el||target.parentNode==el){Calendar.addClass(el,"hilite active");Calendar.addClass(el.parentNode,"rowhilite");}else{if(typeof el.navtype=="undefined"||(el.navtype!=50&&(el.navtype==0||Math.abs(el.navtype)>2)))Calendar.removeClass(el,"active");Calendar.removeClass(el,"hilite");Calendar.removeClass(el.parentNode,"rowhilite");}ev||(ev=window.event);if(el.navtype==50&&target!=el){var pos=Calendar.getAbsolutePos(el);var w=el.offsetWidth;var x=ev.clientX;var dx;var decrease=true;if(x>pos.x+w){dx=x-pos.x-w;decrease=false;}else dx=pos.x-x;if(dx<0)dx=0;var range=el._range;var current=el._current;var count=Math.floor(dx/10)%range.length;for(var i=range.length;--i>=0;)if(range[i]==current)break;while(count-->0)if(decrease){if(--i<0)i=range.length-1;}else if(++i>=range.length)i=0;var newval=range[i];el.firstChild.data=newval;cal.onUpdateTime();}var mon=Calendar.findMonth(target);if(mon){if(mon.month!=cal.date.getMonth()){if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}Calendar.addClass(mon,"hilite");cal.hilitedMonth=mon;}else if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}}else{if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}var year=Calendar.findYear(target);if(year){if(year.year!=cal.date.getFullYear()){if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}Calendar.addClass(year,"hilite");cal.hilitedYear=year;}else if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}}else if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}}return Calendar.stopEvent(ev);};Calendar.tableMouseDown=function(ev){if(Calendar.getTargetElement(ev)==Calendar.getElement(ev)){return Calendar.stopEvent(ev);}};Calendar.calDragIt=function(ev){var cal=Calendar._C;if(!(cal&&cal.dragging)){return false;}var posX;var posY;if(Calendar.is_ie){posY=window.event.clientY+document.body.scrollTop;posX=window.event.clientX+document.body.scrollLeft;}else{posX=ev.pageX;posY=ev.pageY;}cal.hideShowCovered();var st=cal.element.style;st.left=(posX-cal.xOffs)+"px";st.top=(posY-cal.yOffs)+"px";return Calendar.stopEvent(ev);};Calendar.calDragEnd=function(ev){var cal=Calendar._C;if(!cal){return false;}cal.dragging=false;with(Calendar){removeEvent(document,"mousemove",calDragIt);removeEvent(document,"mouseup",calDragEnd);tableMouseUp(ev);}cal.hideShowCovered();};Calendar.dayMouseDown=function(ev){var el=Calendar.getElement(ev);if(el.disabled){return false;}var cal=el.calendar;cal.activeDiv=el;Calendar._C=cal;if(el.navtype!=300)with(Calendar){if(el.navtype==50){el._current=el.firstChild.data;addEvent(document,"mousemove",tableMouseOver);}else addEvent(document,Calendar.is_ie5?"mousemove":"mouseover",tableMouseOver);addClass(el,"hilite active");addEvent(document,"mouseup",tableMouseUp);}else if(cal.isPopup){cal._dragStart(ev);}if(el.navtype==-1||el.navtype==1){if(cal.timeout)clearTimeout(cal.timeout);cal.timeout=setTimeout("Calendar.showMonthsCombo()",250);}else if(el.navtype==-2||el.navtype==2){if(cal.timeout)clearTimeout(cal.timeout);cal.timeout=setTimeout((el.navtype>0)?"Calendar.showYearsCombo(true)":"Calendar.showYearsCombo(false)",250);}else{cal.timeout=null;}return Calendar.stopEvent(ev);};Calendar.dayMouseDblClick=function(ev){Calendar.cellClick(Calendar.getElement(ev),ev||window.event);if(Calendar.is_ie){document.selection.empty();}};Calendar.dayMouseOver=function(ev){var el=Calendar.getElement(ev);if(Calendar.isRelated(el,ev)||Calendar._C||el.disabled){return false;}if(el.ttip){if(el.ttip.substr(0,1)=="_"){el.ttip=el.caldate.print(el.calendar.ttDateFormat)+el.ttip.substr(1);}el.calendar.tooltips.firstChild.data=el.ttip;}if(el.navtype!=300){Calendar.addClass(el,"hilite");if(el.caldate){Calendar.addClass(el.parentNode,"rowhilite");}}return Calendar.stopEvent(ev);};Calendar.dayMouseOut=function(ev){with(Calendar){var el=getElement(ev);if(isRelated(el,ev)||_C||el.disabled){return false;}removeClass(el,"hilite");if(el.caldate){removeClass(el.parentNode,"rowhilite");}el.calendar.tooltips.firstChild.data=_TT["SEL_DATE"];return stopEvent(ev);}};Calendar.cellClick=function(el,ev){var cal=el.calendar;var closing=false;var newdate=false;var date=null;if(typeof el.navtype=="undefined"){Calendar.removeClass(cal.currentDateEl,"selected");Calendar.addClass(el,"selected");closing=(cal.currentDateEl==el);if(!closing){cal.currentDateEl=el;}cal.date=new Date(el.caldate);date=cal.date;newdate=true;if(!(cal.dateClicked=!el.otherMonth))cal._init(cal.firstDayOfWeek,date);}else{if(el.navtype==200){Calendar.removeClass(el,"hilite");cal.callCloseHandler();return;}date=(el.navtype==0)?new Date():new Date(cal.date);cal.dateClicked=false;var year=date.getFullYear();var mon=date.getMonth();function setMonth(m){var day=date.getDate();var max=date.getMonthDays(m);if(day>max){date.setDate(max);}date.setMonth(m);};switch(el.navtype){case 400:Calendar.removeClass(el,"hilite");var text=Calendar._TT["ABOUT"];if(typeof text!="undefined"){text+=cal.showsTime?Calendar._TT["ABOUT_TIME"]:"";}else{text="Help and about box text is not translated into this language.\n"+"If you know this language and you feel generous please update\n"+"the corresponding file in \"lang\" subdir to match calendar-en.js\n"+"and send it back to <mishoo@infoiasi.ro> to get it into the distribution ;-)\n\n"+"Thank you!\n"+"http://dynarch.com/mishoo/calendar.epl\n";}alert(text);return;case-2:if(year>cal.minYear){date.setFullYear(year-1);}break;case-1:if(mon>0){setMonth(mon-1);}else if(year-->cal.minYear){date.setFullYear(year);setMonth(11);}break;case 1:if(mon<11){setMonth(mon+1);}else if(year<cal.maxYear){date.setFullYear(year+1);setMonth(0);}break;case 2:if(year<cal.maxYear){date.setFullYear(year+1);}break;case 100:cal.setFirstDayOfWeek(el.fdow);return;case 50:var range=el._range;var current=el.firstChild.data;for(var i=range.length;--i>=0;)if(range[i]==current)break;if(ev&&ev.shiftKey){if(--i<0)i=range.length-1;}else if(++i>=range.length)i=0;var newval=range[i];el.firstChild.data=newval;cal.onUpdateTime();return;case 0:if((typeof cal.getDateStatus=="function")&&cal.getDateStatus(date,date.getFullYear(),date.getMonth(),date.getDate())){return false;}break;}if(!date.equalsTo(cal.date)){cal.setDate(date);newdate=true;}}if(newdate){cal.callHandler();}if(closing){Calendar.removeClass(el,"hilite");cal.callCloseHandler();}};Calendar.prototype.create=function(_par){var parent=null;if(!_par){parent=document.getElementsByTagName("body")[0];this.isPopup=true;}else{parent=_par;this.isPopup=false;}this.date=this.dateStr?new Date(this.dateStr):new Date();var table=Calendar.createElement("table");this.table=table;table.cellSpacing=0;table.cellPadding=0;table.calendar=this;Calendar.addEvent(table,"mousedown",Calendar.tableMouseDown);var div=Calendar.createElement("div");this.element=div;div.className="calendar";if(this.isPopup){div.style.position="absolute";div.style.display="none";}div.appendChild(table);var thead=Calendar.createElement("thead",table);var cell=null;var row=null;var cal=this;var hh=function(text,cs,navtype){cell=Calendar.createElement("td",row);cell.colSpan=cs;cell.className="button";if(navtype!=0&&Math.abs(navtype)<=2)cell.className+=" nav";Calendar._add_evs(cell);cell.calendar=cal;cell.navtype=navtype;if(text.substr(0,1)!="&"){cell.appendChild(document.createTextNode(text));}else{cell.innerHTML=text;}return cell;};row=Calendar.createElement("tr",thead);var title_length=6;(this.isPopup)&&--title_length;(this.weekNumbers)&&++title_length;hh("?",1,400).ttip=Calendar._TT["INFO"];this.title=hh("",title_length,300);this.title.className="title";if(this.isPopup){this.title.ttip=Calendar._TT["DRAG_TO_MOVE"];this.title.style.cursor="move";hh("&#x00d7;",1,200).ttip=Calendar._TT["CLOSE"];}row=Calendar.createElement("tr",thead);row.className="headrow";this._nav_py=hh("&#x00ab;",1,-2);this._nav_py.ttip=Calendar._TT["PREV_YEAR"];this._nav_pm=hh("&#x2039;",1,-1);this._nav_pm.ttip=Calendar._TT["PREV_MONTH"];this._nav_now=hh(Calendar._TT["TODAY"],this.weekNumbers?4:3,0);this._nav_now.ttip=Calendar._TT["GO_TODAY"];this._nav_nm=hh("&#x203a;",1,1);this._nav_nm.ttip=Calendar._TT["NEXT_MONTH"];this._nav_ny=hh("&#x00bb;",1,2);this._nav_ny.ttip=Calendar._TT["NEXT_YEAR"];row=Calendar.createElement("tr",thead);row.className="daynames";if(this.weekNumbers){cell=Calendar.createElement("td",row);cell.className="name wn";cell.appendChild(document.createTextNode(Calendar._TT["WK"]));}for(var i=7;i>0;--i){cell=Calendar.createElement("td",row);cell.appendChild(document.createTextNode(""));if(!i){cell.navtype=100;cell.calendar=this;Calendar._add_evs(cell);}}this.firstdayname=(this.weekNumbers)?row.firstChild.nextSibling:row.firstChild;this._displayWeekdays();var tbody=Calendar.createElement("tbody",table);this.tbody=tbody;for(i=6;i>0;--i){row=Calendar.createElement("tr",tbody);if(this.weekNumbers){cell=Calendar.createElement("td",row);cell.appendChild(document.createTextNode(""));}for(var j=7;j>0;--j){cell=Calendar.createElement("td",row);cell.appendChild(document.createTextNode(""));cell.calendar=this;Calendar._add_evs(cell);}}if(this.showsTime){row=Calendar.createElement("tr",tbody);row.className="time";cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=2;cell.innerHTML=Calendar._TT["TIME"]||"&nbsp;";cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=this.weekNumbers?4:3;(function(){function makeTimePart(className,init,range_start,range_end){var part=Calendar.createElement("span",cell);part.className=className;part.appendChild(document.createTextNode(init));part.calendar=cal;part.ttip=Calendar._TT["TIME_PART"];part.navtype=50;part._range=[];if(typeof range_start!="number")part._range=range_start;else{for(var i=range_start;i<=range_end;++i){var txt;if(i<10&&range_end>=10)txt='0'+i;else txt=''+i;part._range[part._range.length]=txt;}}Calendar._add_evs(part);return part;};var hrs=cal.date.getHours();var mins=cal.date.getMinutes();var t12=!cal.time24;var pm=(hrs>12);if(t12&&pm)hrs-=12;var H=makeTimePart("hour",hrs,t12?1:0,t12?12:23);var span=Calendar.createElement("span",cell);span.appendChild(document.createTextNode(":"));span.className="colon";var M=makeTimePart("minute",mins,0,59);var AP=null;cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=2;if(t12)AP=makeTimePart("ampm",pm?"pm":"am",["am","pm"]);else cell.innerHTML="&nbsp;";cal.onSetTime=function(){var hrs=this.date.getHours();var mins=this.date.getMinutes();var pm=(hrs>12);if(pm&&t12)hrs-=12;H.firstChild.data=(hrs<10)?("0"+hrs):hrs;M.firstChild.data=(mins<10)?("0"+mins):mins;if(t12)AP.firstChild.data=pm?"pm":"am";};cal.onUpdateTime=function(){var date=this.date;var h=parseInt(H.firstChild.data,10);if(t12){if(/pm/i.test(AP.firstChild.data)&&h<12)h+=12;else if(/am/i.test(AP.firstChild.data)&&h==12)h=0;}var d=date.getDate();var m=date.getMonth();var y=date.getFullYear();date.setHours(h);date.setMinutes(parseInt(M.firstChild.data,10));date.setFullYear(y);date.setMonth(m);date.setDate(d);this.dateClicked=false;this.callHandler();};})();}else{this.onSetTime=this.onUpdateTime=function(){};}var tfoot=Calendar.createElement("tfoot",table);row=Calendar.createElement("tr",tfoot);row.className="footrow";cell=hh(Calendar._TT["SEL_DATE"],this.weekNumbers?8:7,300);cell.className="ttip";if(this.isPopup){cell.ttip=Calendar._TT["DRAG_TO_MOVE"];cell.style.cursor="move";}this.tooltips=cell;div=Calendar.createElement("div",this.element);this.monthsCombo=div;div.className="combo";for(i=0;i<Calendar._MN.length;++i){var mn=Calendar.createElement("div");mn.className=Calendar.is_ie?"label-IEfix":"label";mn.month=i;mn.appendChild(document.createTextNode(Calendar._SMN[i]));div.appendChild(mn);}div=Calendar.createElement("div",this.element);this.yearsCombo=div;div.className="combo";for(i=12;i>0;--i){var yr=Calendar.createElement("div");yr.className=Calendar.is_ie?"label-IEfix":"label";yr.appendChild(document.createTextNode(""));div.appendChild(yr);}this._init(this.firstDayOfWeek,this.date);parent.appendChild(this.element);};Calendar._keyEvent=function(ev){if(!window.calendar){return false;}(Calendar.is_ie)&&(ev=window.event);var cal=window.calendar;var act=(Calendar.is_ie||ev.type=="keypress");if(ev.ctrlKey){switch(ev.keyCode){case 37:act&&Calendar.cellClick(cal._nav_pm);break;case 38:act&&Calendar.cellClick(cal._nav_py);break;case 39:act&&Calendar.cellClick(cal._nav_nm);break;case 40:act&&Calendar.cellClick(cal._nav_ny);break;default:return false;}}else switch(ev.keyCode){case 32:Calendar.cellClick(cal._nav_now);break;case 27:act&&cal.callCloseHandler();break;case 37:case 38:case 39:case 40:if(act){var date=cal.date.getDate()-1;var el=cal.currentDateEl;var ne=null;var prev=(ev.keyCode==37)||(ev.keyCode==38);switch(ev.keyCode){case 37:(--date>=0)&&(ne=cal.ar_days[date]);break;case 38:date-=7;(date>=0)&&(ne=cal.ar_days[date]);break;case 39:(++date<cal.ar_days.length)&&(ne=cal.ar_days[date]);break;case 40:date+=7;(date<cal.ar_days.length)&&(ne=cal.ar_days[date]);break;}if(!ne){if(prev){Calendar.cellClick(cal._nav_pm);}else{Calendar.cellClick(cal._nav_nm);}date=(prev)?cal.date.getMonthDays():1;el=cal.currentDateEl;ne=cal.ar_days[date-1];}Calendar.removeClass(el,"selected");Calendar.addClass(ne,"selected");cal.date=new Date(ne.caldate);cal.callHandler();cal.currentDateEl=ne;}break;case 13:if(act){cal.callHandler();cal.hide();}break;default:return false;}return Calendar.stopEvent(ev);};Calendar.prototype._init=function(firstDayOfWeek,date){var today=new Date();this.table.style.visibility="hidden";var year=date.getFullYear();if(year<this.minYear){year=this.minYear;date.setFullYear(year);}else if(year>this.maxYear){year=this.maxYear;date.setFullYear(year);}this.firstDayOfWeek=firstDayOfWeek;this.date=new Date(date);var month=date.getMonth();var mday=date.getDate();var no_days=date.getMonthDays();date.setDate(1);var day1=(date.getDay()-this.firstDayOfWeek)%7;if(day1<0)day1+=7;date.setDate(-day1);date.setDate(date.getDate()+1);var row=this.tbody.firstChild;var MN=Calendar._SMN[month];var ar_days=new Array();var weekend=Calendar._TT["WEEKEND"];for(var i=0;i<6;++i,row=row.nextSibling){var cell=row.firstChild;if(this.weekNumbers){cell.className="day wn";cell.firstChild.data=date.getWeekNumber();cell=cell.nextSibling;}row.className="daysrow";var hasdays=false;for(var j=0;j<7;++j,cell=cell.nextSibling,date.setDate(date.getDate()+1)){var iday=date.getDate();var wday=date.getDay();cell.className="day";var current_month=(date.getMonth()==month);if(!current_month){if(this.showsOtherMonths){cell.className+=" othermonth";cell.otherMonth=true;}else{cell.className="emptycell";cell.innerHTML="&nbsp;";cell.disabled=true;continue;}}else{cell.otherMonth=false;hasdays=true;}cell.disabled=false;cell.firstChild.data=iday;if(typeof this.getDateStatus=="function"){var status=this.getDateStatus(date,year,month,iday);if(status===true){cell.className+=" disabled";cell.disabled=true;}else{if(/disabled/i.test(status))cell.disabled=true;cell.className+=" "+status;}}if(!cell.disabled){ar_days[ar_days.length]=cell;cell.caldate=new Date(date);cell.ttip="_";if(current_month&&iday==mday){cell.className+=" selected";this.currentDateEl=cell;}if(date.getFullYear()==today.getFullYear()&&date.getMonth()==today.getMonth()&&iday==today.getDate()){cell.className+=" today";cell.ttip+=Calendar._TT["PART_TODAY"];}if(weekend.indexOf(wday.toString())!=-1){cell.className+=cell.otherMonth?" oweekend":" weekend";}}}if(!(hasdays||this.showsOtherMonths))row.className="emptyrow";}this.ar_days=ar_days;this.title.firstChild.data=Calendar._MN[month]+", "+year;this.onSetTime();this.table.style.visibility="visible";};Calendar.prototype.setDate=function(date){if(!date.equalsTo(this.date)){this._init(this.firstDayOfWeek,date);}};Calendar.prototype.refresh=function(){this._init(this.firstDayOfWeek,this.date);};Calendar.prototype.setFirstDayOfWeek=function(firstDayOfWeek){this._init(firstDayOfWeek,this.date);this._displayWeekdays();};Calendar.prototype.setDateStatusHandler=Calendar.prototype.setDisabledHandler=function(unaryFunction){this.getDateStatus=unaryFunction;};Calendar.prototype.setRange=function(a,z){this.minYear=a;this.maxYear=z;};Calendar.prototype.callHandler=function(){if(this.onSelected){this.onSelected(this,this.date.print(this.dateFormat));}};Calendar.prototype.callCloseHandler=function(){if(this.onClose){this.onClose(this);}this.hideShowCovered();};Calendar.prototype.destroy=function(){var el=this.element.parentNode;el.removeChild(this.element);Calendar._C=null;window.calendar=null;};Calendar.prototype.reparent=function(new_parent){var el=this.element;el.parentNode.removeChild(el);new_parent.appendChild(el);};Calendar._checkCalendar=function(ev){if(!window.calendar){return false;}var el=Calendar.is_ie?Calendar.getElement(ev):Calendar.getTargetElement(ev);for(;el!=null&&el!=calendar.element;el=el.parentNode);if(el==null){window.calendar.callCloseHandler();return Calendar.stopEvent(ev);}};Calendar.prototype.show=function(){var rows=this.table.getElementsByTagName("tr");for(var i=rows.length;i>0;){var row=rows[--i];Calendar.removeClass(row,"rowhilite");var cells=row.getElementsByTagName("td");for(var j=cells.length;j>0;){var cell=cells[--j];Calendar.removeClass(cell,"hilite");Calendar.removeClass(cell,"active");}}this.element.style.display="block";this.hidden=false;if(this.isPopup){window.calendar=this;Calendar.addEvent(document,"keydown",Calendar._keyEvent);Calendar.addEvent(document,"keypress",Calendar._keyEvent);Calendar.addEvent(document,"mousedown",Calendar._checkCalendar);}this.hideShowCovered();};Calendar.prototype.hide=function(){if(this.isPopup){Calendar.removeEvent(document,"keydown",Calendar._keyEvent);Calendar.removeEvent(document,"keypress",Calendar._keyEvent);Calendar.removeEvent(document,"mousedown",Calendar._checkCalendar);}this.element.style.display="none";this.hidden=true;this.hideShowCovered();};Calendar.prototype.showAt=function(x,y){var s=this.element.style;s.left=x+"px";s.top=y+"px";this.show();};Calendar.prototype.showAtElement=function(el,opts){var self=this;var p=Calendar.getAbsolutePos(el);if(!opts||typeof opts!="string"){this.showAt(p.x,p.y+el.offsetHeight);return true;}function fixPosition(box){if(box.x<0)box.x=0;if(box.y<0)box.y=0;var cp=document.createElement("div");var s=cp.style;s.position="absolute";s.right=s.bottom=s.width=s.height="0px";document.body.appendChild(cp);var br=Calendar.getAbsolutePos(cp);document.body.removeChild(cp);if(Calendar.is_ie){br.y+=document.body.scrollTop;br.x+=document.body.scrollLeft;}else{br.y+=window.scrollY;br.x+=window.scrollX;}var tmp=box.x+box.width-br.x;if(tmp>0)box.x-=tmp;tmp=box.y+box.height-br.y;if(tmp>0)box.y-=tmp;};this.element.style.display="block";Calendar.continuation_for_the_fucking_khtml_browser=function(){var w=self.element.offsetWidth;var h=self.element.offsetHeight;self.element.style.display="none";var valign=opts.substr(0,1);var halign="l";if(opts.length>1){halign=opts.substr(1,1);}switch(valign){case "T":p.y-=h;break;case "B":p.y+=el.offsetHeight;break;case "C":p.y+=(el.offsetHeight-h)/2;break;case "t":p.y+=el.offsetHeight-h;break;case "b":break;}switch(halign){case "L":p.x-=w;break;case "R":p.x+=el.offsetWidth;break;case "C":p.x+=(el.offsetWidth-w)/2;break;case "r":p.x+=el.offsetWidth-w;break;case "l":break;}p.width=w;p.height=h+40;self.monthsCombo.style.display="none";fixPosition(p);self.showAt(p.x,p.y);};if(Calendar.is_khtml)setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()",10);else Calendar.continuation_for_the_fucking_khtml_browser();};Calendar.prototype.setDateFormat=function(str){this.dateFormat=str;};Calendar.prototype.setTtDateFormat=function(str){this.ttDateFormat=str;};Calendar.prototype.parseDate=function(str,fmt){var y=0;var m=-1;var d=0;var a=str.split(/\W+/);if(!fmt){fmt=this.dateFormat;}var b=fmt.match(/%./g);var i=0,j=0;var hr=0;var min=0;for(i=0;i<a.length;++i){if(!a[i])continue;switch(b[i]){case "%d":case "%e":d=parseInt(a[i],10);break;case "%m":m=parseInt(a[i],10)-1;break;case "%Y":case "%y":y=parseInt(a[i],10);(y<100)&&(y+=(y>29)?1900:2000);break;case "%b":case "%B":for(j=0;j<12;++j){if(Calendar._MN[j].substr(0,a[i].length).toLowerCase()==a[i].toLowerCase()){m=j;break;}}break;case "%H":case "%I":case "%k":case "%l":hr=parseInt(a[i],10);break;case "%P":case "%p":if(/pm/i.test(a[i])&&hr<12)hr+=12;break;case "%M":min=parseInt(a[i],10);break;}}if(y!=0&&m!=-1&&d!=0){this.setDate(new Date(y,m,d,hr,min,0));return;}y=0;m=-1;d=0;for(i=0;i<a.length;++i){if(a[i].search(/[a-zA-Z]+/)!=-1){var t=-1;for(j=0;j<12;++j){if(Calendar._MN[j].substr(0,a[i].length).toLowerCase()==a[i].toLowerCase()){t=j;break;}}if(t!=-1){if(m!=-1){d=m+1;}m=t;}}else if(parseInt(a[i],10)<=12&&m==-1){m=a[i]-1;}else if(parseInt(a[i],10)>31&&y==0){y=parseInt(a[i],10);(y<100)&&(y+=(y>29)?1900:2000);}else if(d==0){d=a[i];}}if(y==0){var today=new Date();y=today.getFullYear();}if(m!=-1&&d!=0){this.setDate(new Date(y,m,d,hr,min,0));}};Calendar.prototype.hideShowCovered=function(){var self=this;Calendar.continuation_for_the_fucking_khtml_browser=function(){function getVisib(obj){var value=obj.style.visibility;if(!value){if(document.defaultView&&typeof(document.defaultView.getComputedStyle)=="function"){if(!Calendar.is_khtml)value=document.defaultView. getComputedStyle(obj,"").getPropertyValue("visibility");else value='';}else if(obj.currentStyle){value=obj.currentStyle.visibility;}else value='';}return value;};var tags=new Array("applet","iframe","select");var el=self.element;var p=Calendar.getAbsolutePos(el);var EX1=p.x;var EX2=el.offsetWidth+EX1;var EY1=p.y;var EY2=el.offsetHeight+EY1;for(var k=tags.length;k>0;){var ar=document.getElementsByTagName(tags[--k]);var cc=null;for(var i=ar.length;i>0;){cc=ar[--i];p=Calendar.getAbsolutePos(cc);var CX1=p.x;var CX2=cc.offsetWidth+CX1;var CY1=p.y;var CY2=cc.offsetHeight+CY1;if(self.hidden||(CX1>EX2)||(CX2<EX1)||(CY1>EY2)||(CY2<EY1)){if(!cc.__msh_save_visibility){cc.__msh_save_visibility=getVisib(cc);}cc.style.visibility=cc.__msh_save_visibility;}else{if(!cc.__msh_save_visibility){cc.__msh_save_visibility=getVisib(cc);}cc.style.visibility="hidden";}}}};if(Calendar.is_khtml)setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()",10);else Calendar.continuation_for_the_fucking_khtml_browser();};Calendar.prototype._displayWeekdays=function(){var fdow=this.firstDayOfWeek;var cell=this.firstdayname;var weekend=Calendar._TT["WEEKEND"];for(var i=0;i<7;++i){cell.className="day name";var realday=(i+fdow)%7;if(i){cell.ttip=Calendar._TT["DAY_FIRST"].replace("%s",Calendar._DN[realday]);cell.navtype=100;cell.calendar=this;cell.fdow=realday;Calendar._add_evs(cell);}if(weekend.indexOf(realday.toString())!=-1){Calendar.addClass(cell,"weekend");}cell.firstChild.data=Calendar._SDN[(i+fdow)%7];cell=cell.nextSibling;}};Calendar.prototype._hideCombos=function(){this.monthsCombo.style.display="none";this.yearsCombo.style.display="none";};Calendar.prototype._dragStart=function(ev){if(this.dragging){return;}this.dragging=true;var posX;var posY;if(Calendar.is_ie){posY=window.event.clientY+document.body.scrollTop;posX=window.event.clientX+document.body.scrollLeft;}else{posY=ev.clientY+window.scrollY;posX=ev.clientX+window.scrollX;}var st=this.element.style;this.xOffs=posX-parseInt(st.left);this.yOffs=posY-parseInt(st.top);with(Calendar){addEvent(document,"mousemove",calDragIt);addEvent(document,"mouseup",calDragEnd);}};Date._MD=new Array(31,28,31,30,31,30,31,31,30,31,30,31);Date.SECOND=1000;Date.MINUTE=60*Date.SECOND;Date.HOUR=60*Date.MINUTE;Date.DAY=24*Date.HOUR;Date.WEEK=7*Date.DAY;Date.prototype.getMonthDays=function(month){var year=this.getFullYear();if(typeof month=="undefined"){month=this.getMonth();}if(((0==(year%4))&&((0!=(year%100))||(0==(year%400))))&&month==1){return 29;}else{return Date._MD[month];}};Date.prototype.getDayOfYear=function(){var now=new Date(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0);var then=new Date(this.getFullYear(),0,0,0,0,0);var time=now-then;return Math.floor(time/Date.DAY);};Date.prototype.getWeekNumber=function(){var d=new Date(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0);var DoW=d.getDay();d.setDate(d.getDate()-(DoW+6)%7+3);var ms=d.valueOf();d.setMonth(0);d.setDate(4);return Math.round((ms-d.valueOf())/(7*864e5))+1;};Date.prototype.equalsTo=function(date){return((this.getFullYear()==date.getFullYear())&&(this.getMonth()==date.getMonth())&&(this.getDate()==date.getDate())&&(this.getHours()==date.getHours())&&(this.getMinutes()==date.getMinutes()));};Date.prototype.print=function(str){var m=this.getMonth();var d=this.getDate();var y=this.getFullYear();var wn=this.getWeekNumber();var w=this.getDay();var s={};var hr=this.getHours();var pm=(hr>=12);var ir=(pm)?(hr-12):hr;var dy=this.getDayOfYear();if(ir==0)ir=12;var min=this.getMinutes();var sec=this.getSeconds();s["%a"]=Calendar._SDN[w];s["%A"]=Calendar._DN[w];s["%b"]=Calendar._SMN[m];s["%B"]=Calendar._MN[m];s["%C"]=1+Math.floor(y/100);s["%d"]=(d<10)?("0"+d):d;s["%e"]=d;s["%H"]=(hr<10)?("0"+hr):hr;s["%I"]=(ir<10)?("0"+ir):ir;s["%j"]=(dy<100)?((dy<10)?("00"+dy):("0"+dy)):dy;s["%k"]=hr;s["%l"]=ir;s["%m"]=(m<9)?("0"+(1+m)):(1+m);s["%M"]=(min<10)?("0"+min):min;s["%n"]="\n";s["%p"]=pm?"PM":"AM";s["%P"]=pm?"pm":"am";s["%s"]=Math.floor(this.getTime()/1000);s["%S"]=(sec<10)?("0"+sec):sec;s["%t"]="\t";s["%U"]=s["%W"]=s["%V"]=(wn<10)?("0"+wn):wn;s["%u"]=w+1;s["%w"]=w;s["%y"]=(''+y).substr(2,2);s["%Y"]=y;s["%%"]="%";var re=/%./g;if(!Calendar.is_ie5)return str.replace(re,function(par){return s[par]||par;});var a=str.match(re);for(var i=0;i<a.length;i++){var tmp=s[a[i]];if(tmp){re=new RegExp(a[i],'g');str=str.replace(re,tmp);}}return str;};Date.prototype.__msh_oldSetFullYear=Date.prototype.setFullYear;Date.prototype.setFullYear=function(y){var d=new Date(this);d.__msh_oldSetFullYear(y);if(d.getMonth()!=this.getMonth())this.setDate(28);this.__msh_oldSetFullYear(y);};window.calendar=null; \ No newline at end of file diff --git a/src/core/static/js/jscalendar/img.gif b/src/core/static/js/jscalendar/img.gif new file mode 100755 index 0000000000000000000000000000000000000000..cd2c4a521774c70473f11c88642543751a812d6f GIT binary patch literal 223 zcmY+8F$w}P5Jmsu1X2mY7Pj^lfoWE3A`H5AX$H3SCIQzYcmogOL2?Q^tGEd(=x;uM z{$plN=VQ0Kv{>RraL#2QrIhnCSD|Y2rlx_xwxq&h@fcKZs#?v!0&(grG%|C?d}R)U zD^^qZLqwz(8AZb2F@n7Ht1*~)C_QN;j~*1;!-N#FcEOM(A3fUjg#2vzUPlb`OU3Tk Fe*i=yIHv#r literal 0 HcmV?d00001 diff --git a/src/core/static/js/jscalendar/index.html b/src/core/static/js/jscalendar/index.html new file mode 100755 index 0000000..96d8d52 --- /dev/null +++ b/src/core/static/js/jscalendar/index.html @@ -0,0 +1,333 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<!-- $Id: index.html 22 2006-06-23 14:42:15Z ugoletti $ --> + +<head> +<meta http-equiv="content-type" content="text/xml; charset=utf-8" /> +<title>The Coolest DHTML Calendar - Online Demo</title> +<link rel="alternate stylesheet" type="text/css" media="all" href="calendar-blue.css" title="winter" /> +<link rel="alternate stylesheet" type="text/css" media="all" href="calendar-blue2.css" title="blue" /> +<link rel="alternate stylesheet" type="text/css" media="all" href="calendar-brown.css" title="summer" /> +<link rel="alternate stylesheet" type="text/css" media="all" href="calendar-green.css" title="green" /> +<link rel="stylesheet" type="text/css" media="all" href="calendar-win2k-1.css" title="win2k-1" /> +<link rel="alternate stylesheet" type="text/css" media="all" href="calendar-win2k-2.css" title="win2k-2" /> +<link rel="alternate stylesheet" type="text/css" media="all" href="calendar-win2k-cold-1.css" title="win2k-cold-1" /> +<link rel="alternate stylesheet" type="text/css" media="all" href="calendar-win2k-cold-2.css" title="win2k-cold-2" /> +<link rel="alternate stylesheet" type="text/css" media="all" href="calendar-system.css" title="system" /> + +<!-- import the calendar script --> +<script type="text/javascript" src="calendar.js"></script> + +<!-- import the language module --> +<script type="text/javascript" src="lang/calendar-en.js"></script> + +<!-- other languages might be available in the lang directory; please check +your distribution archive. --> + +<!-- helper script that uses the calendar --> +<script type="text/javascript"> + +var oldLink = null; +// code to change the active stylesheet +function setActiveStyleSheet(link, title) { + var i, a, main; + for(i=0; (a = document.getElementsByTagName("link")[i]); i++) { + if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) { + a.disabled = true; + if(a.getAttribute("title") == title) a.disabled = false; + } + } + if (oldLink) oldLink.style.fontWeight = 'normal'; + oldLink = link; + link.style.fontWeight = 'bold'; + return false; +} + +// This function gets called when the end-user clicks on some date. +function selected(cal, date) { + cal.sel.value = date; // just update the date in the input field. + if (cal.dateClicked && (cal.sel.id == "sel1" || cal.sel.id == "sel3")) + // if we add this call we close the calendar on single-click. + // just to exemplify both cases, we are using this only for the 1st + // and the 3rd field, while 2nd and 4th will still require double-click. + cal.callCloseHandler(); +} + +// And this gets called when the end-user clicks on the _selected_ date, +// or clicks on the "Close" button. It just hides the calendar without +// destroying it. +function closeHandler(cal) { + cal.hide(); // hide the calendar +// cal.destroy(); + calendar = null; +} + +// This function shows the calendar under the element having the given id. +// It takes care of catching "mousedown" signals on document and hiding the +// calendar if the click was outside. +function showCalendar(id, format, showsTime, showsOtherMonths) { + var el = document.getElementById(id); + if (calendar != null) { + // we already have some calendar created + calendar.hide(); // so we hide it first. + } else { + // first-time call, create the calendar. + var cal = new Calendar(true, null, selected, closeHandler); + // uncomment the following line to hide the week numbers + // cal.weekNumbers = false; + if (typeof showsTime == "string") { + cal.showsTime = true; + cal.time24 = (showsTime == "24"); + } + if (showsOtherMonths) { + cal.showsOtherMonths = true; + } + calendar = cal; // remember it in the global var + cal.setRange(1900, 2070); // min/max year allowed. + cal.create(); + } + calendar.setDateFormat(format); // set the specified date format + calendar.parseDate(el.value); // try to parse the text in field + calendar.sel = el; // inform it what input field we use + + // the reference element that we pass to showAtElement is the button that + // triggers the calendar. In this example we align the calendar bottom-right + // to the button. + calendar.showAtElement(el.nextSibling, "Br"); // show the calendar + + return false; +} + +var MINUTE = 60 * 1000; +var HOUR = 60 * MINUTE; +var DAY = 24 * HOUR; +var WEEK = 7 * DAY; + +// If this handler returns true then the "date" given as +// parameter will be disabled. In this example we enable +// only days within a range of 10 days from the current +// date. +// You can use the functions date.getFullYear() -- returns the year +// as 4 digit number, date.getMonth() -- returns the month as 0..11, +// and date.getDate() -- returns the date of the month as 1..31, to +// make heavy calculations here. However, beware that this function +// should be very fast, as it is called for each day in a month when +// the calendar is (re)constructed. +function isDisabled(date) { + var today = new Date(); + return (Math.abs(date.getTime() - today.getTime()) / DAY) > 10; +} + +function flatSelected(cal, date) { + var el = document.getElementById("preview"); + el.innerHTML = date; +} + +function showFlatCalendar() { + var parent = document.getElementById("display"); + + // construct a calendar giving only the "selected" handler. + var cal = new Calendar(true, null, flatSelected); + + // hide week numbers + cal.weekNumbers = false; + + // We want some dates to be disabled; see function isDisabled above + cal.setDisabledHandler(isDisabled); + cal.setDateFormat("%A, %B %e"); + + // this call must be the last as it might use data initialized above; if + // we specify a parent, as opposite to the "showCalendar" function above, + // then we create a flat calendar -- not popup. Hidden, though, but... + cal.create(parent); + + // ... we can show it here. + cal.show(); +} +</script> + +<style type="text/css"> +.ex { font-weight: bold; background: #fed; color: #080 } +.help { color: #080; font-style: italic; } +body { background: #fea; font: 10pt tahoma,verdana,sans-serif; } +table { font: 13px verdana,tahoma,sans-serif; } +a { color: #00f; } +a:visited { color: #00f; } +a:hover { color: #f00; background: #fefaf0; } +a:active { color: #08f; } +.key { border: 1px solid #000; background: #fff; color: #008; +padding: 0px 5px; cursor: default; font-size: 80%; } +</style> + +</head> +<body onload="showFlatCalendar()"> + +<h2><a href="http://dynarch.com/mishoo/calendar.epl" +title="Visit the project website">jscalendar</a>-0.9.6 +"Keep cool but don't freeze"</h2> + +<p> +<div style="float: right; border: 1px solid #b87; padding: 2px; font-size: 90%; background: #ffb;"> +Theme:<br /> +<a href="#" onclick="return setActiveStyleSheet(this, 'winter');">winter</a> +| +<a href="#" onclick="return setActiveStyleSheet(this, 'blue');">blue</a> +| +<a href="#" onclick="return setActiveStyleSheet(this, 'summer');">summer</a> +| +<a href="#" onclick="return setActiveStyleSheet(this, 'green');">green</a> +<br /> +<a href="#" id="defaultTheme" onclick="return setActiveStyleSheet(this, 'win2k-1');">win2k-1</a> +| +<a href="#" onclick="return setActiveStyleSheet(this, 'win2k-2');">win2k-2</a> +| +<a href="#" onclick="return setActiveStyleSheet(this, 'win2k-cold-1');">win2k-cold-1</a> +| +<a href="#" onclick="return setActiveStyleSheet(this, 'win2k-cold-2');">win2k-cold-2</a> +<br /> +<a href="#" onclick="return setActiveStyleSheet(this, 'system');">system</a> +<script type="text/javascript"> +setActiveStyleSheet(document.getElementById("defaultTheme"), "win2k-1"); +</script> +</div> +<a href="release-notes.html">Release notes</a>. +<br /> +Set it up in minutes: + <a href="simple-1.html">popup calendar</a>, + <a href="simple-2.html">flat calendar</a>. +<br /> +Documentation: + <a href="doc/html/reference.html">HTML</a>, + <a href="doc/reference.pdf">PDF</a>. +<br /> +<b style="color: red">Donate! Keep me on it! Details on <a href="http://dynarch.com/mishoo/calendar.epl">the Calendar website</a>.</b> +</p> + +<div style="padding-left:20px; font-size: 90%; font-style: italic;"> + +</div> + +<table style="width: 100%"> +<tr valign="top"> +<td style="background: #ffa; padding: 5px; border: 1px solid #995;"> + +<form action="#"> +<div style="background: #995; color: #ffa; font-weight: bold; padding: 2px;"> +Popup examples +</div> + +<br /> + +<b>Date #1:</b> <input type="text" name="date1" id="sel1" size="30" +><input type="reset" value=" ... " +onclick="return showCalendar('sel1', '%Y-%m-%d [%W] %H:%M', '24', true);"> %Y-%m-%d [%W] %H:%M -- single +click<br /> + +<b>Date #2:</b> <input type="text" name="date2" id="sel2" size="30" +><input type="reset" value=" ... " +onclick="return showCalendar('sel2', '%a, %b %e, %Y [%I:%M %p]', '12');"> %a, %b %e, %Y [%I:%M %p] +-- double click + +<br /><br /> +<!-- +if you remove this comment and leave the following HTML code +you will see a horrible effect, in all supported browsers (IE and Mozilla). +--> +<SELECT multiple size="4" name="component-select"> + <OPTION selected value="Component_1_a">Component_1</OPTION> + <OPTION selected value="Component_1_b">Component_2</OPTION> + <OPTION>Component_3</OPTION> + <OPTION>Component_4</OPTION> + <OPTION>Component_5</OPTION> + <OPTION>Component_6</OPTION> + <OPTION>Component_7</OPTION> +</SELECT> +this select should hide when the calendar is above it. +<br /><br /> + +<b>Date #3:</b> <input type="text" name="date3" id="sel3" size="30" +><input type="reset" value=" ... " +onclick="return showCalendar('sel3', '%d/%m/%Y');"> %d/%m/%Y +-- single click +<br /> + +<b>Date #4:</b> <input type="text" name="date4" id="sel4" size="30" +><input type="reset" value=" ... " +onclick="return showCalendar('sel4', '%A, %B %e, %Y');"> %A, %B %e, %Y -- +double click + +</form> + +<p>This is release <b>0.9.6</b>. Works on MSIE/Win 5.0 or better (really), +Opera 7, Mozilla, Netscape 6.x, 7.0 and all other Gecko-s, Konqueror and +Safari.</p> + +<p class="help">You can click on "Mo"/"Su" (first day name displayed) to +change the first day of week (Sunday/Monday) (since 0.8 this is also mapped +on the "-" button in the top-left corner). Use the navigation buttons +("&lt;&lt;", "&lt;", "Today", "&gt;", "&gt;&gt;") to move to the prev/next +year/month. Keep the mouse button pressed for a short time over one of +these buttons to get a menu for faster selection. You can drag the "status +bar" (that's where the tooltips appear) or title bar (that's where the +currently selected month/year shows up) to move the whole calendar.</p> + +<h4>Keyboard navigation</h4> + +<p>Starting with version 0.9.2, you can also use the keyboard to select +dates (only for popup calendars; does <em>not</em> work with Opera +7 or Konqueror/Safari). The following keys are available:</p> + +<ul> + + <li><span class="key">&larr;</span> , <span class="key">&rarr;</span> , + <span class="key">&uarr;</span> , <span class="key">&darr;</span> -- select date</li> + <li><span class="key">CTRL</span> + <span class="key">&larr;</span> , + <span class="key">&rarr;</span> -- select month</li> + <li><span class="key">CTRL</span> + <span class="key">&uarr;</span> , + <span class="key">&darr;</span> -- select year</li> + <li><span class="key">SPACE</span> -- go to <em>today</em> date</li> + <li><span class="key">ENTER</span> -- accept the currently selected date</li> + <li><span class="key">ESC</span> -- cancel selection</li> + +</ul> + + </td> + + <td style="padding: 5px; margin: 5px; border: 1px solid #984; background: #ed9; width: 15em;"> + + <div style="background: #984; color: #fea; font-weight: bold; padding: 2px; text-align: center"> + Flat calendar + </div> + + <p style="width: 12em"><small>A non-popup version will appear below as soon + as the page is loaded. Note that it doesn't show the week number.</small></p> + + <!-- the calendar will be inserted here --> + <div id="display" style="float: right; clear: both;"></div> + <div id="preview" style="font-size: 80%; text-align: center; padding: 2px"></div> + + <p style="width: 12em"><small> + The example above uses the <code>setDisabledHandler()</code> member function + to setup a handler that would only enable days withing a range of 10 days, + forward or backward, from the current date. + </small></p> + + </div> + + </td> + + </tr> + </table> + +<hr /><address> +&copy; <a href="http://dynarch.com">dynarch.com</a> 2002-2003 <br /> +Author: <a href="http://dynarch.com/mishoo/">Mihai +Bazon</a><br /> Distributed under the <a +href="http://www.gnu.org/licenses/lgpl.html">GNU LGPL</a>.</address> + +<p style="font-size: smaller">If you use this script on a public page it +would be nice if you would <a href="mailto:mishoo@infoiasi.ro">let me +know</a>.</p> + +</body></html> diff --git a/src/core/static/js/jscalendar/lang/calendar-af.js b/src/core/static/js/jscalendar/lang/calendar-af.js new file mode 100755 index 0000000..ace710e --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-af.js @@ -0,0 +1,39 @@ +// ** I18N Afrikaans +Calendar._DN = new Array +("Sondag", + "Maandag", + "Dinsdag", + "Woensdag", + "Donderdag", + "Vrydag", + "Saterdag", + "Sondag"); +Calendar._MN = new Array +("Januarie", + "Februarie", + "Maart", + "April", + "Mei", + "Junie", + "Julie", + "Augustus", + "September", + "Oktober", + "November", + "Desember"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Verander eerste dag van die week"; +Calendar._TT["PREV_YEAR"] = "Vorige jaar (hou vir keuselys)"; +Calendar._TT["PREV_MONTH"] = "Vorige maand (hou vir keuselys)"; +Calendar._TT["GO_TODAY"] = "Gaan na vandag"; +Calendar._TT["NEXT_MONTH"] = "Volgende maand (hou vir keuselys)"; +Calendar._TT["NEXT_YEAR"] = "Volgende jaar (hou vir keuselys)"; +Calendar._TT["SEL_DATE"] = "Kies datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Sleep om te skuif"; +Calendar._TT["PART_TODAY"] = " (vandag)"; +Calendar._TT["MON_FIRST"] = "Vertoon Maandag eerste"; +Calendar._TT["SUN_FIRST"] = "Display Sunday first"; +Calendar._TT["CLOSE"] = "Close"; +Calendar._TT["TODAY"] = "Today"; diff --git a/src/core/static/js/jscalendar/lang/calendar-br.js b/src/core/static/js/jscalendar/lang/calendar-br.js new file mode 100755 index 0000000..7499af4 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-br.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("Domingo", + "Segunda", + "Terça", + "Quarta", + "Quinta", + "Sexta", + "Sábado", + "Domingo"); +Calendar._MN = new Array +("Janeiro", + "Fevereiro", + "Março", + "Abril", + "Maio", + "Junho", + "Julho", + "Agosto", + "Setembro", + "Outubro", + "Novembro", + "Dezembro"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Altera primeiro dia da semana"; +Calendar._TT["PREV_YEAR"] = "Ano anterior(hold for menu)"; +Calendar._TT["PREV_MONTH"] = "Mês anterior (hold for menu)"; +Calendar._TT["GO_TODAY"] = "Hoje"; +Calendar._TT["NEXT_MONTH"] = "Mês seguinte (hold for menu)"; +Calendar._TT["NEXT_YEAR"] = "ano seguinte (hold for menu)"; +Calendar._TT["SEL_DATE"] = "Seleciona uma data"; +Calendar._TT["DRAG_TO_MOVE"] = "Arrasta calendário"; +Calendar._TT["PART_TODAY"] = " (hoje)"; +Calendar._TT["MON_FIRST"] = "Inicia na segunda-feira"; +Calendar._TT["SUN_FIRST"] = "Inicia no domingo"; +Calendar._TT["CLOSE"] = "Fechar"; +Calendar._TT["TODAY"] = "Hoje"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "DD, dd de MM de y"; + +Calendar._TT["WK"] = "sem"; diff --git a/src/core/static/js/jscalendar/lang/calendar-ca.js b/src/core/static/js/jscalendar/lang/calendar-ca.js new file mode 100755 index 0000000..324c34b --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-ca.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("Diumenge", + "Dilluns", + "Dimarts", + "Dimecres", + "Dijous", + "Divendres", + "Dissabte", + "Diumenge"); +Calendar._MN = new Array +("Gener", + "Febrer", + "Març", + "Abril", + "Maig", + "Juny", + "Juliol", + "Agost", + "Setembre", + "Octubre", + "Novembre", + "Desembre"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Canvia el primer dia de la setmana"; +Calendar._TT["PREV_YEAR"] = "Any anterior (mantenir per a menu)"; +Calendar._TT["PREV_MONTH"] = "Mes anterior (mantenir per a menu)"; +Calendar._TT["GO_TODAY"] = "Anar a avui"; +Calendar._TT["NEXT_MONTH"] = "Mes següent (mantenir per a menu)"; +Calendar._TT["NEXT_YEAR"] = "Any següent (mantenir per a menu)"; +Calendar._TT["SEL_DATE"] = "Seleccionar data"; +Calendar._TT["DRAG_TO_MOVE"] = "Arrastrar per a moure"; +Calendar._TT["PART_TODAY"] = " (avui)"; +Calendar._TT["MON_FIRST"] = "Mostrar dilluns primer"; +Calendar._TT["SUN_FIRST"] = "Mostrar diumenge primer"; +Calendar._TT["CLOSE"] = "Tancar"; +Calendar._TT["TODAY"] = "Avui"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-yy"; +Calendar._TT["TT_DATE_FORMAT"] = "D, M d"; + +Calendar._TT["WK"] = "sem"; diff --git a/src/core/static/js/jscalendar/lang/calendar-cs-win.js b/src/core/static/js/jscalendar/lang/calendar-cs-win.js new file mode 100755 index 0000000..5f4b6d9 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-cs-win.js @@ -0,0 +1,34 @@ +/* + calendar-cs-win.js + language: Czech + encoding: windows-1250 + author: Lubos Jerabek (xnet@seznam.cz) +*/ + +// ** I18N +Calendar._DN = new Array('Nedìle','Pondìlí','Úterý','Støeda','Ètvrtek','Pátek','Sobota','Nedìle'); +Calendar._DN3 = new Array('Ne','Po','Út','St','Èt','Pá','So','Ne'); +Calendar._MN = new Array('Leden','Únor','Bøezen','Duben','Kvìten','Èerven','Èervenec','Srpen','Záøí','Øíjen','Listopad','Prosinec'); +Calendar._MN3 = new Array('Led','Úno','Bøe','Dub','Kvì','Èrv','Èvc','Srp','Záø','Øíj','Lis','Pro'); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Zmìna prvního dne v týdnu"; +Calendar._TT["PREV_YEAR"] = "Pøedchozí rok (pøidrž pro menu)"; +Calendar._TT["PREV_MONTH"] = "Pøedchozí mìsíc (pøidrž pro menu)"; +Calendar._TT["GO_TODAY"] = "Dnešní datum"; +Calendar._TT["NEXT_MONTH"] = "Další mìsíc (pøidrž pro menu)"; +Calendar._TT["NEXT_YEAR"] = "Další rok (pøidrž pro menu)"; +Calendar._TT["SEL_DATE"] = "Vyber datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Chy a táhni, pro pøesun"; +Calendar._TT["PART_TODAY"] = " (dnes)"; +Calendar._TT["MON_FIRST"] = "Ukaž jako první Pondìlí"; +Calendar._TT["SUN_FIRST"] = "Ukaž jako první Nedìli"; +Calendar._TT["CLOSE"] = "Zavøít"; +Calendar._TT["TODAY"] = "Dnes"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "d.m.yy"; +Calendar._TT["TT_DATE_FORMAT"] = "DD, 5.MM y"; + +Calendar._TT["WK"] = "wk"; diff --git a/src/core/static/js/jscalendar/lang/calendar-da.js b/src/core/static/js/jscalendar/lang/calendar-da.js new file mode 100755 index 0000000..5d9a001 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-da.js @@ -0,0 +1,63 @@ +// ** I18N +Calendar._DN = new Array +("Søndag", + "Mandag", + "Tirsdag", + "Onsdag", + "Torsdag", + "Fredag", + "Lørdag", + "Søndag"); +Calendar._MN = new Array +("January", + "Februar", + "Marts", + "April", + "Maj", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "December"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Om Kalenderen"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"For den seneste version besøg: http://dynarch.com/mishoo/calendar.epl\n" + +"Distribueret under GNU LGPL. Se http://gnu.org/licenses/lgpl.html for detajler." + +"\n\n" + +"Valg af dato:\n" + +"- Brug \xab, \xbb knapperne for at vælge år\n" + +"- Brug " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " knapperne for at vælge måned\n" + +"- Hold knappen på musen nede på knapperne ovenfor for hurtigere valg."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Valg af tid:\n" + +"- Klik på en vilkårlig del for større værdi\n" + +"- eller Shift-klik for for mindre værdi\n" + +"- eller klik og træk for hurtigere valg."; + +Calendar._TT["TOGGLE"] = "Skift første ugedag"; +Calendar._TT["PREV_YEAR"] = "Ét år tilbage (hold for menu)"; +Calendar._TT["PREV_MONTH"] = "Én måned tilbage (hold for menu)"; +Calendar._TT["GO_TODAY"] = "Gå til i dag"; +Calendar._TT["NEXT_MONTH"] = "Én måned frem (hold for menu)"; +Calendar._TT["NEXT_YEAR"] = "Ét år frem (hold for menu)"; +Calendar._TT["SEL_DATE"] = "Vælg dag"; +Calendar._TT["DRAG_TO_MOVE"] = "Træk vinduet"; +Calendar._TT["PART_TODAY"] = " (i dag)"; +Calendar._TT["MON_FIRST"] = "Vis mandag først"; +Calendar._TT["SUN_FIRST"] = "Vis søndag først"; +Calendar._TT["CLOSE"] = "Luk vinduet"; +Calendar._TT["TODAY"] = "I dag"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-yy"; +Calendar._TT["TT_DATE_FORMAT"] = "%d. %b, %Y"; + +Calendar._TT["WK"] = "wk"; diff --git a/src/core/static/js/jscalendar/lang/calendar-de.js b/src/core/static/js/jscalendar/lang/calendar-de.js new file mode 100755 index 0000000..163b346 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-de.js @@ -0,0 +1,123 @@ +// Author: Hartwig Weinkauf h_weinkauf@gmx.de +// �erarbeitet und fehlende Texte hinzugefgt von Gerhard Neinert (gerhard at neinert punkt de) +// Feel free to use / redistribute under the GNU LGPL. +// ** I18N + +// short day names +Calendar._SDN = new Array +("So", + "Mo", + "Di", + "Mi", + "Do", + "Fr", + "Sa", + "So"); + +// full day names +Calendar._DN = new Array +("Sonntag", + "Montag", + "Dienstag", + "Mittwoch", + "Donnerstag", + "Freitag", + "Samstag", + "Sonntag"); + +// short day names only use 2 letters instead of 3 +Calendar._SDN_len = 2; + +// full month names +Calendar._MN = new Array +("Januar", + "Februar", + "M\u00e4rz", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Dezember"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "M\u00e4r", + "Apr", + "Mai", + "Jun", + "Jul", + "Aug", + "Sep", + "Okt", + "Nov", + "Dez"); + +// tooltips +Calendar._TT = {}; + +Calendar._TT["ABOUT"] = +"DHTML Datum/Zeit Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"Donwload neueste Version: http://dynarch.com/mishoo/calendar.epl\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Datumsauswahl:\n" + +"- Jahr ausw\u00e4hlen mit \xab und \xbb\n" + +"- Monat ausw\u00e4hlen mit " + String.fromCharCode(0x2039) + " und " + String.fromCharCode(0x203a) + "\n" + +"- Fr Auswahl aus Liste Maustaste gedr\u00fcckt halten."; + +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Zeit w\u00e4hlen:\n" + +"- Stunde/Minute weiter mit Mausklick\n" + +"- Stunde/Minute zurck mit Shift-Mausklick\n" + +"- oder f\u00fcr schnellere Auswahl nach links oder rechts ziehen."; + + +Calendar._TT["TOGGLE"] = "Ersten Tag der Woche w\u00e4hlen"; +Calendar._TT["PREV_YEAR"] = "Jahr zur\u00fcck (halten -> Auswahlmen\u00fc)"; +Calendar._TT["PREV_MONTH"] = "Monat zur\u00fcck (halten -> Auswahlmen\u00fc)"; +Calendar._TT["GO_TODAY"] = "Gehe zum heutigen Datum"; +Calendar._TT["NEXT_MONTH"] = "Monat vor (halten -> Auswahlmen\u00fc)"; +Calendar._TT["NEXT_YEAR"] = "Jahr vor (halten -> Auswahlmen\u00fc)"; +Calendar._TT["SEL_DATE"] = "Datum ausw\u00e4hlen"; +Calendar._TT["DRAG_TO_MOVE"] = "Klicken und halten um zu verschieben"; +Calendar._TT["PART_TODAY"] = " (heute)"; +Calendar._TT["MON_FIRST"] = "Wochenanzeige mit Montag beginnen"; +Calendar._TT["SUN_FIRST"] = "Wochenanzeige mit Sonntag beginnen"; +Calendar._TT["CLOSE"] = "Schlie\u00dfen"; +Calendar._TT["TODAY"] = "Heute"; + + + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Display %s first"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Close"; +Calendar._TT["TODAY"] = "Today"; +Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Time:"; + + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "Datum ausw\u00e4hlen"; + +Calendar._TT["WK"] = "KW"; diff --git a/src/core/static/js/jscalendar/lang/calendar-du.js b/src/core/static/js/jscalendar/lang/calendar-du.js new file mode 100755 index 0000000..9c9051f --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-du.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("Zondag", + "Maandag", + "Dinsdag", + "Woensdag", + "Donderdag", + "Vrijdag", + "Zaterdag", + "Zondag"); +Calendar._MN = new Array +("Januari", + "Februari", + "Maart", + "April", + "Mei", + "Juni", + "Juli", + "Augustus", + "September", + "Oktober", + "November", + "December"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Toggle startdag van de week"; +Calendar._TT["PREV_YEAR"] = "Vorig jaar (indrukken voor menu)"; +Calendar._TT["PREV_MONTH"] = "Vorige month (indrukken voor menu)"; +Calendar._TT["GO_TODAY"] = "Naar Vandaag"; +Calendar._TT["NEXT_MONTH"] = "Volgende Maand (indrukken voor menu)"; +Calendar._TT["NEXT_YEAR"] = "Volgend jaar (indrukken voor menu)"; +Calendar._TT["SEL_DATE"] = "Selecteer datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Sleep om te verplaatsen"; +Calendar._TT["PART_TODAY"] = " (vandaag)"; +Calendar._TT["MON_FIRST"] = "Toon Maandag eerst"; +Calendar._TT["SUN_FIRST"] = "Toon Zondag eerst"; +Calendar._TT["CLOSE"] = "Sluiten"; +Calendar._TT["TODAY"] = "Vandaag"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "y-mm-dd"; +Calendar._TT["TT_DATE_FORMAT"] = "D, M d"; + +Calendar._TT["WK"] = "wk"; diff --git a/src/core/static/js/jscalendar/lang/calendar-el.js b/src/core/static/js/jscalendar/lang/calendar-el.js new file mode 100755 index 0000000..a8f34ad --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-el.js @@ -0,0 +1,89 @@ +// ** I18N +Calendar._DN = new Array +("ΚυÏιακή", + "ΔευτέÏα", + "ΤÏίτη", + "ΤετάÏτη", + "Πέμπτη", + "ΠαÏασκευή", + "Σάββατο", + "ΚυÏιακή"); + +Calendar._SDN = new Array +("Κυ", + "Δε", + "TÏ", + "Τε", + "Πε", + "Πα", + "Σα", + "Κυ"); + +Calendar._MN = new Array +("ΙανουάÏιος", + "ΦεβÏουάÏιος", + "ΜάÏτιος", + "ΑπÏίλιος", + "Μάϊος", + "ΙοÏνιος", + "ΙοÏλιος", + "ΑÏγουστος", + "ΣεπτέμβÏιος", + "ΟκτώβÏιος", + "ÎοέμβÏιος", + "ΔεκέμβÏιος"); + +Calendar._SMN = new Array +("Ιαν", + "Φεβ", + "ΜαÏ", + "ΑπÏ", + "Μαι", + "Ιουν", + "Ιουλ", + "Αυγ", + "Σεπ", + "Οκτ", + "Îοε", + "Δεκ"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Για το ημεÏολόγιο"; + +Calendar._TT["ABOUT"] = +"Επιλογέας ημεÏομηνίας/ÏŽÏας σε DHTML\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"Για τελευταία έκδοση: http://dynarch.com/mishoo/calendar.epl\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Επιλογή ημεÏομηνίας:\n" + +"- ΧÏησιμοποιείστε τα κουμπιά \xab, \xbb για επιλογή έτους\n" + +"- ΧÏησιμοποιείστε τα κουμπιά " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " για επιλογή μήνα\n" + +"- ΚÏατήστε κουμπί Ï€Î¿Î½Ï„Î¹ÎºÎ¿Ï Ï€Î±Ï„Î·Î¼Î­Î½Î¿ στα παÏαπάνω κουμπιά για πιο γÏήγοÏη επιλογή."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Επιλογή ÏŽÏας:\n" + +"- Κάντε κλικ σε ένα από τα μέÏη της ÏŽÏας για αÏξηση\n" + +"- ή Shift-κλικ για μείωση\n" + +"- ή κλικ και μετακίνηση για πιο γÏήγοÏη επιλογή."; +Calendar._TT["TOGGLE"] = "ΜπάÏα Ï€Ïώτης ημέÏας της εβδομάδας"; +Calendar._TT["PREV_YEAR"] = "ΠÏοηγ. έτος (κÏατήστε για το μενοÏ)"; +Calendar._TT["PREV_MONTH"] = "ΠÏοηγ. μήνας (κÏατήστε για το μενοÏ)"; +Calendar._TT["GO_TODAY"] = "ΣήμεÏα"; +Calendar._TT["NEXT_MONTH"] = "Επόμενος μήνας (κÏατήστε για το μενοÏ)"; +Calendar._TT["NEXT_YEAR"] = "Επόμενο έτος (κÏατήστε για το μενοÏ)"; +Calendar._TT["SEL_DATE"] = "Επιλέξτε ημεÏομηνία"; +Calendar._TT["DRAG_TO_MOVE"] = "ΣÏÏτε για να μετακινήσετε"; +Calendar._TT["PART_TODAY"] = " (σήμεÏα)"; +Calendar._TT["MON_FIRST"] = "Εμφάνιση ΔευτέÏας Ï€Ïώτα"; +Calendar._TT["SUN_FIRST"] = "Εμφάνιση ΚυÏιακής Ï€Ïώτα"; +Calendar._TT["CLOSE"] = "Κλείσιμο"; +Calendar._TT["TODAY"] = "ΣήμεÏα"; +Calendar._TT["TIME_PART"] = "(Shift-)κλικ ή μετακίνηση για αλλαγή"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "D, d M"; + +Calendar._TT["WK"] = "εβδ"; + diff --git a/src/core/static/js/jscalendar/lang/calendar-en.js b/src/core/static/js/jscalendar/lang/calendar-en.js new file mode 100755 index 0000000..185b8b9 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-en.js @@ -0,0 +1,123 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, <mishoo@infoiasi.ro> +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun"); + +// full month names +Calendar._MN = new Array +("January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "About the calendar"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"For latest version visit: http://dynarch.com/mishoo/calendar.epl\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Date selection:\n" + +"- Use the \xab, \xbb buttons to select year\n" + +"- Use the " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " buttons to select month\n" + +"- Hold mouse button on any of the above buttons for faster selection."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Time selection:\n" + +"- Click on any of the time parts to increase it\n" + +"- or Shift-click to decrease it\n" + +"- or click and drag for faster selection."; + +Calendar._TT["PREV_YEAR"] = "Prev. year (hold for menu)"; +Calendar._TT["PREV_MONTH"] = "Prev. month (hold for menu)"; +Calendar._TT["GO_TODAY"] = "Go Today"; +Calendar._TT["NEXT_MONTH"] = "Next month (hold for menu)"; +Calendar._TT["NEXT_YEAR"] = "Next year (hold for menu)"; +Calendar._TT["SEL_DATE"] = "Select date"; +Calendar._TT["DRAG_TO_MOVE"] = "Drag to move"; +Calendar._TT["PART_TODAY"] = " (today)"; + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Display %s first"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Close"; +Calendar._TT["TODAY"] = "Today"; +Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Time:"; diff --git a/src/core/static/js/jscalendar/lang/calendar-es.js b/src/core/static/js/jscalendar/lang/calendar-es.js new file mode 100755 index 0000000..a733d37 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-es.js @@ -0,0 +1,114 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, <mishoo@infoiasi.ro> +// Encoding: any +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Domingo", + "Lunes", + "Martes", + "Miircoles", + "Jueves", + "Viernes", + "Sabado", + "Domingo"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Dom", + "Lun", + "Mar", + "Mii", + "Jue", + "Vie", + "Sab", + "Dom"); + +// full month names +Calendar._MN = new Array +("Enero", + "Febrero", + "Marzo", + "Abril", + "Mayo", + "Junio", + "Julio", + "Agosto", + "Septiembre", + "Octubre", + "Noviembre", + "Diciembre"); + +// short month names +Calendar._SMN = new Array +("Ene", + "Feb", + "Mar", + "Abr", + "May", + "Jun", + "Jul", + "Ago", + "Sep", + "Oct", + "Nov", + "Dic"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Acerca del calendario"; + +Calendar._TT["ABOUT"] = +"Selector DHTML de Fecha/Hora\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"Para conseguir la zltima versisn visite: http://dynarch.com/mishoo/calendar.epl\n" + +"Distribuido bajo licencia GNU LGPL. Visite http://gnu.org/licenses/lgpl.html para mas detalles." + +"\n\n" + +"Seleccisn de fecha:\n" + +"- Use los botones \xab, \xbb para seleccionar el aqo\n" + +"- Use los botones " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " para seleccionar el mes\n" + +"- Mantenga pulsado el ratsn en cualquiera de estos botones para una seleccisn rapida."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Seleccisn de hora:\n" + +"- Pulse en cualquiera de las partes de la hora para incrementarla\n" + +"- s pulse las mayzsculas mientras hace clic para decrementarla\n" + +"- s haga clic y arrastre el ratsn para una seleccisn mas rapida."; + +Calendar._TT["PREV_YEAR"] = "Aqo anterior (mantener para menu)"; +Calendar._TT["PREV_MONTH"] = "Mes anterior (mantener para menu)"; +Calendar._TT["GO_TODAY"] = "Ir a hoy"; +Calendar._TT["NEXT_MONTH"] = "Mes siguiente (mantener para menu)"; +Calendar._TT["NEXT_YEAR"] = "Aqo siguiente (mantener para menu)"; +Calendar._TT["SEL_DATE"] = "Seleccionar fecha"; +Calendar._TT["DRAG_TO_MOVE"] = "Arrastrar para mover"; +Calendar._TT["PART_TODAY"] = " (hoy)"; +Calendar._TT["MON_FIRST"] = "Mostrar lunes primero"; +Calendar._TT["SUN_FIRST"] = "Mostrar domingo primero"; +Calendar._TT["CLOSE"] = "Cerrar"; +Calendar._TT["TODAY"] = "Hoy"; +Calendar._TT["TIME_PART"] = "(Mayzscula-)Clic o arrastre para cambiar valor"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d/%m/%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %e de %B de %Y"; + +Calendar._TT["WK"] = "sem"; diff --git a/src/core/static/js/jscalendar/lang/calendar-fi.js b/src/core/static/js/jscalendar/lang/calendar-fi.js new file mode 100755 index 0000000..1df7d75 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-fi.js @@ -0,0 +1,98 @@ +// ** I18N + +// Calendar FI language (Finnish, Suomi) +// Author: Jarno Käyhkö, <gambler@phnet.fi> +// Encoding: UTF-8 +// Distributed under the same terms as the calendar itself. + +// full day names +Calendar._DN = new Array +("Sunnuntai", + "Maanantai", + "Tiistai", + "Keskiviikko", + "Torstai", + "Perjantai", + "Lauantai", + "Sunnuntai"); + +// short day names +Calendar._SDN = new Array +("Su", + "Ma", + "Ti", + "Ke", + "To", + "Pe", + "La", + "Su"); + +// full month names +Calendar._MN = new Array +("Tammikuu", + "Helmikuu", + "Maaliskuu", + "Huhtikuu", + "Toukokuu", + "Kesäkuu", + "Heinäkuu", + "Elokuu", + "Syyskuu", + "Lokakuu", + "Marraskuu", + "Joulukuu"); + +// short month names +Calendar._SMN = new Array +("Tam", + "Hel", + "Maa", + "Huh", + "Tou", + "Kes", + "Hei", + "Elo", + "Syy", + "Lok", + "Mar", + "Jou"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Tietoja kalenterista"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"Uusin versio osoitteessa: http://dynarch.com/mishoo/calendar.epl\n" + +"Julkaistu GNU LGPL lisenssin alaisuudessa. Lisätietoja osoitteessa http://gnu.org/licenses/lgpl.html" + +"\n\n" + +"Päivämäärä valinta:\n" + +"- Käytä \xab, \xbb painikkeita valitaksesi vuosi\n" + +"- Käytä " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " painikkeita valitaksesi kuukausi\n" + +"- Pitämällä hiiren painiketta minkä tahansa yllä olevan painikkeen kohdalla, saat näkyviin valikon nopeampaan siirtymiseen."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Ajan valinta:\n" + +"- Klikkaa kellonajan numeroita lisätäksesi aikaa\n" + +"- tai pitämällä Shift-näppäintä pohjassa saat aikaa taaksepäin\n" + +"- tai klikkaa ja pidä hiiren painike pohjassa sekä liikuta hiirtä muuttaaksesi aikaa nopeasti eteen- ja taaksepäin."; + +Calendar._TT["PREV_YEAR"] = "Edell. vuosi (paina hetki, näet valikon)"; +Calendar._TT["PREV_MONTH"] = "Edell. kuukausi (paina hetki, näet valikon)"; +Calendar._TT["GO_TODAY"] = "Siirry tähän päivään"; +Calendar._TT["NEXT_MONTH"] = "Seur. kuukausi (paina hetki, näet valikon)"; +Calendar._TT["NEXT_YEAR"] = "Seur. vuosi (paina hetki, näet valikon)"; +Calendar._TT["SEL_DATE"] = "Valitse päivämäärä"; +Calendar._TT["DRAG_TO_MOVE"] = "Siirrä kalenterin paikkaa"; +Calendar._TT["PART_TODAY"] = " (tänään)"; +Calendar._TT["MON_FIRST"] = "Näytä maanantai ensimmäisenä"; +Calendar._TT["SUN_FIRST"] = "Näytä sunnuntai ensimmäisenä"; +Calendar._TT["CLOSE"] = "Sulje"; +Calendar._TT["TODAY"] = "Tänään"; +Calendar._TT["TIME_PART"] = "(Shift-) Klikkaa tai liikuta muuttaaksesi aikaa"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d.%m.%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%d.%m.%Y"; + +Calendar._TT["WK"] = "Vko"; diff --git a/src/core/static/js/jscalendar/lang/calendar-fr.js b/src/core/static/js/jscalendar/lang/calendar-fr.js new file mode 100755 index 0000000..f7a2243 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-fr.js @@ -0,0 +1,109 @@ +// ** I18N +Calendar._DN = new Array +("Dimanche", + "Lundi", + "Mardi", + "Mercredi", + "Jeudi", + "Vendredi", + "Samedi", + "Dimanche"); +Calendar._MN = new Array +("Janvier", + "Février", + "Mars", + "Avril", + "Mai", + "Juin", + "Juillet", + "Août", + "Septembre", + "Octobre", + "Novembre", + "Décembre"); +Calendar._SDN = new Array +("Lun", + "Mar", + "Mer", + "Jeu", + "Thu", + "Ven", + "Sam", + "Dim"); +Calendar._SMN = new Array +("Jan", + "Fev", + "Mar", + "Avr", + "Mai", + "Juin", + "Juil", + "Aout", + "Sep", + "Oct", + "Nov", + "Dec"); + +// tooltips +Calendar._TT = {}; + +Calendar._TT["INFO"] = "A propos du calendrier"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Heure Selecteur\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"Pour la derniere version visitez: http://dynarch.com/mishoo/calendar.epl\n" + +"Distribué par GNU LGPL. Voir http://gnu.org/licenses/lgpl.html pour les details." + +"\n\n" + +"Selection de la date :\n" + +"- Utiliser les bouttons \xab, \xbb pour selectionner l\'annee\n" + +"- Utiliser les bouttons " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " pour selectionner les mois\n" + +"- Garder la souris sur n'importe quels boutons pour un selection plus rapide"; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selection de l\'heure:\n" + +"- Cliquer sur heures ou minutes pour incrementer\n" + +"- ou Maj-clic pour decrementer\n" + +"- ou clic et glisser deplacer pour un selection plus rapide"; + +Calendar._TT["TOGGLE"] = "Changer le premier jour de la semaine"; +Calendar._TT["PREV_YEAR"] = "Année préc. (maintenir pour menu)"; +Calendar._TT["PREV_MONTH"] = "Mois préc. (maintenir pour menu)"; +Calendar._TT["GO_TODAY"] = "Atteindre date du jour"; +Calendar._TT["NEXT_MONTH"] = "Mois suiv. (maintenir pour menu)"; +Calendar._TT["NEXT_YEAR"] = "Année suiv. (maintenir pour menu)"; +Calendar._TT["SEL_DATE"] = "Choisir une date"; +Calendar._TT["DRAG_TO_MOVE"] = "Déplacer"; +Calendar._TT["PART_TODAY"] = " (Aujourd'hui)"; +Calendar._TT["MON_FIRST"] = "Commencer par lundi"; +Calendar._TT["SUN_FIRST"] = "Commencer par dimanche"; +Calendar._TT["CLOSE"] = "Fermer"; +Calendar._TT["TODAY"] = "Aujourd'hui"; + + +// the following is to inform that "%s" is to be the first day of week +// %s will be replaced with the day name. +Calendar._TT["DAY_FIRST"] = "Display %s first"; + +// This may be locale-dependent. It specifies the week-end days, as an array +// of comma-separated numbers. The numbers are from 0 to 6: 0 means Sunday, 1 +// means Monday, etc. +Calendar._TT["WEEKEND"] = "0,6"; + +Calendar._TT["CLOSE"] = "Close"; +Calendar._TT["TODAY"] = "Today"; +Calendar._TT["TIME_PART"] = "(Shift-)Click or drag to change value"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; +Calendar._TT["TIME"] = "Time:"; + + + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%y"; +Calendar._TT["TT_DATE_FORMAT"] = " %A %e %B %Y"; + +Calendar._TT["WK"] = "sem"; diff --git a/src/core/static/js/jscalendar/lang/calendar-hr-utf8.js b/src/core/static/js/jscalendar/lang/calendar-hr-utf8.js new file mode 100755 index 0000000..d569cfd --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-hr-utf8.js @@ -0,0 +1,49 @@ +/* Croatian language file for the DHTML Calendar version 0.9.2 +* Author Krunoslav Zubrinic <krunoslav.zubrinic@vip.hr>, June 2003. +* Feel free to use this script under the terms of the GNU Lesser General +* Public License, as long as you do not remove or alter this notice. +*/ +Calendar._DN = new Array +("Nedjelja", + "Ponedjeljak", + "Utorak", + "Srijeda", + "ÄŒetvrtak", + "Petak", + "Subota", + "Nedjelja"); +Calendar._MN = new Array +("SijeÄanj", + "VeljaÄa", + "Ožujak", + "Travanj", + "Svibanj", + "Lipanj", + "Srpanj", + "Kolovoz", + "Rujan", + "Listopad", + "Studeni", + "Prosinac"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Promjeni dan s kojim poÄinje tjedan"; +Calendar._TT["PREV_YEAR"] = "Prethodna godina (dugi pritisak za meni)"; +Calendar._TT["PREV_MONTH"] = "Prethodni mjesec (dugi pritisak za meni)"; +Calendar._TT["GO_TODAY"] = "Idi na tekući dan"; +Calendar._TT["NEXT_MONTH"] = "Slijedeći mjesec (dugi pritisak za meni)"; +Calendar._TT["NEXT_YEAR"] = "Slijedeća godina (dugi pritisak za meni)"; +Calendar._TT["SEL_DATE"] = "Izaberite datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Pritisni i povuci za promjenu pozicije"; +Calendar._TT["PART_TODAY"] = " (today)"; +Calendar._TT["MON_FIRST"] = "Prikaži ponedjeljak kao prvi dan"; +Calendar._TT["SUN_FIRST"] = "Prikaži nedjelju kao prvi dan"; +Calendar._TT["CLOSE"] = "Zatvori"; +Calendar._TT["TODAY"] = "Danas"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "DD, dd.mm.y"; + +Calendar._TT["WK"] = "Tje"; \ No newline at end of file diff --git a/src/core/static/js/jscalendar/lang/calendar-hr.js b/src/core/static/js/jscalendar/lang/calendar-hr.js new file mode 100755 index 0000000000000000000000000000000000000000..6c27f60c4f8d416145e316bdb92e455a04a26fc4 GIT binary patch literal 3088 zcmcJRZEq4$5QV3oOpN^xn|@MLX``QvFOd|BwX`K&TD8VBv|!x=g_MG!Mt{2coVhHp zKpTvj4cxc6GiS~{b9aCJT(gH3*@j(O+p2bD3I7+&G`&5u9_^Xcnfc6GbJ%NRA7TB) z#|3+172C0rd#bwCh1J+8t3EcD)@66wJ+E8Np7MLl+OpmC_<7>UTkyM$eGl6<yM&{U z<q<O{%qPqzcFN3iYs}c??0U-X6}uDb5bq1tFKv~bZ{53cdTi@FPgqTnY=X8<RONf= zedXC^+yjmF2xme+;&<wZI?QQZIV;yOGgm%txpf<l<CUWA+5zJd7G0jOuSk30eX*Eg zDtk`NVcsQgWv5-rr|SNj&hOc1JYd{oRCDxVQz(^Fi@r`Jq7_=j3P>lj3p>PheZ<e2 zW7_Z?LJ-b4XUA3`pU7VD6aKHXd3;}DIq*IAZ3T-uJI?uU@?T|U)z>0=Ww2=H<a#4x zaR5f)t#a;@J7eY&_bN1#EBBV_?CG<9HM6Tstl8PvnHE!7PqWA$*s~kC*ja#!c!+s< zN%eM~!F@PlNUM_>?b(l|o^zMwpyIsrK|Sp&cKx5sS&@!9bLPe8y!ma|m&W@1t~03i zVNK_Gk(rhME=;!FTP?E|GvDK^rJ*FVQYO0UUUgnYdn=YQt!h}~kw)7*(yTJ*-gpib zZl$2fZ}$C`^OD_1B2{e9iaaHI&FIr`ue2#lE!UXvs;0s%sav4I+Bvf=`W^bqOTsRd z3#r;*y|Ms;vh5T5kb3$+n`bnQL#ow1S#y3O?q>A^Tan$T-(yY~JD^USqb_J0%v{q( z;0&xk!1v7>PB|GP+JT*2IC^s{CPfZR>2^A0^zShhL2~S;Re+-p89ZCghHfF{s#~oA zBX>BH^wbu~dKdQJ6XBS*+Pth|)R*2l^`ZCwo%I;gJZ(%PQuhB_8!;@E{O-@gRkmif zTx}=tA5^GnP#vi5TMH?#fco=PV>sz>5{FY!RGF#9LuCf#>z3-FK8=FvRSn}B)_YO4 zdX0swRHcjPqU<#(UFfcuRiD(Z+ew)YxVaYb85DMGo3=&9F`lPuK0(7(ZvHg4+4rPw zp(=4h)$5DrPt+dsC9+FSiy_EH7n6SzdjkdSk#$x*N3ImTX>`7eusHub3i#1Y&>i_0 zzeR!?rOVGAr{ytkf1BtnQ2^`agzClH9w)bhHnL||LkEvgdyD_U2*JFsr}VZ}t8b}L hPd9rmV52WTMaX%C+(ZQBcw3Zrwhfx``>it4|8LNz+<O23 literal 0 HcmV?d00001 diff --git a/src/core/static/js/jscalendar/lang/calendar-hu.js b/src/core/static/js/jscalendar/lang/calendar-hu.js new file mode 100755 index 0000000..efa2c56 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-hu.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("Vasárnap", + "Hétfõ", + "Kedd", + "Szerda", + "Csütörtök", + "Péntek", + "Szombat", + "Vasárnap"); +Calendar._MN = new Array +("január", + "február", + "március", + "április", + "május", + "június", + "július", + "augusztus", + "szeptember", + "október", + "november", + "december"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "A hét elsõ napjának beállítása"; +Calendar._TT["PREV_YEAR"] = "Elõzõ év (tartsa nyomva a menühöz)"; +Calendar._TT["PREV_MONTH"] = "Elõzõ hónap (tartsa nyomva a menühöz)"; +Calendar._TT["GO_TODAY"] = "Mai napra ugrás"; +Calendar._TT["NEXT_MONTH"] = "Köv. hónap (tartsa nyomva a menühöz)"; +Calendar._TT["NEXT_YEAR"] = "Köv. év (tartsa nyomva a menühöz)"; +Calendar._TT["SEL_DATE"] = "Válasszon dátumot"; +Calendar._TT["DRAG_TO_MOVE"] = "Húzza a mozgatáshoz"; +Calendar._TT["PART_TODAY"] = " (ma)"; +Calendar._TT["MON_FIRST"] = "Hétfõ legyen a hét elsõ napja"; +Calendar._TT["SUN_FIRST"] = "Vasárnap legyen a hét elsõ napja"; +Calendar._TT["CLOSE"] = "Bezár"; +Calendar._TT["TODAY"] = "Ma"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "y-mm-dd"; +Calendar._TT["TT_DATE_FORMAT"] = "M d, D"; + +Calendar._TT["WK"] = "hét"; diff --git a/src/core/static/js/jscalendar/lang/calendar-it.js b/src/core/static/js/jscalendar/lang/calendar-it.js new file mode 100755 index 0000000..8d18388 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-it.js @@ -0,0 +1,86 @@ +// ** I18N +Calendar._DN = new Array +("Domenica", + "Lunedì", + "Martedì", + "Mercoledì", + "Giovedì", + "Venerdì", + "Sabato", + "Domenica"); +Calendar._MN = new Array +("Gennaio", + "Febbraio", + "Marzo", + "Aprile", + "Maggio", + "Giugno", + "Luglio", + "Agosto", + "Settembre", + "Ottobre", + "Novembre", + "Dicembre"); + +// short month names +Calendar._SMN = new Array +("Gen", + "Feb", + "Mar", + "Apr", + "Mag", + "Giu", + "Lug", + "Ago", + "Set", + "Ott", + "Nov", + "Dic"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "a proposito del calendario"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"Per le ultime versioni vai a: http://dynarch.com/mishoo/calendar.epl\n" + +"Distribuito su licenza GNU LGPL. Vedi http://gnu.org/licenses/lgpl.html per i dettagli." + +"\n\n" + +"selezione della data:\n" + +"- Usa i bottoni \xab, \xbb per selezionare l'anno\n" + +"- Usa i bottoni " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " per selezionare il mese\n" + +"- Utilizza il mouse per una selezione rapida."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"selezione dell'ora:\n" + +"- Clicca sull'ora visualizzata per aumentarla\n" + +"- o Shift-click per diminuirla\n" + +"- o click a trascina per la selezione rapida."; + + +Calendar._TT["TOGGLE"] = "Modifica il primo giorno della settimana"; +Calendar._TT["PREV_YEAR"] = "Anno prec. (tieni premuto per menu)"; +Calendar._TT["PREV_MONTH"] = "Mese prec. (tieni premuto per menu)"; +Calendar._TT["GO_TODAY"] = "Vai a oggi"; +Calendar._TT["NEXT_MONTH"] = "Mese succ. (tieni premuto per menu)"; +Calendar._TT["NEXT_YEAR"] = "Anno succ. (tieni premuto per menu)"; +Calendar._TT["SEL_DATE"] = "Seleziona data"; +Calendar._TT["DRAG_TO_MOVE"] = "Trascina per spostare"; +Calendar._TT["PART_TODAY"] = " (oggi)"; +Calendar._TT["MON_FIRST"] = "Parti da lunedì"; +Calendar._TT["SUN_FIRST"] = "Parti da domenica"; +Calendar._TT["CLOSE"] = "Chiudi"; +Calendar._TT["TODAY"] = "Oggi"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b "; + +Calendar._TT["WK"] = "Setti"; + + + +Calendar._TT["DAY_FIRST"] = "Visualizza %s giorni prima"; +Calendar._TT["WEEKEND"] = "0,6"; +Calendar._TT["TIME_PART"] = "(Shift-)Click o trascina per cambiare valori"; +Calendar._TT["TIME"] = "Ora:"; \ No newline at end of file diff --git a/src/core/static/js/jscalendar/lang/calendar-jp.js b/src/core/static/js/jscalendar/lang/calendar-jp.js new file mode 100755 index 0000000..b86f0da --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-jp.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("“ú", + "ŒŽ", + "‰Î", + "…", + "–Ø", + "‹à", + "“y", + "“ú"); +Calendar._MN = new Array +("1ŒŽ", + "2ŒŽ", + "3ŒŽ", + "4ŒŽ", + "5ŒŽ", + "6ŒŽ", + "7ŒŽ", + "8ŒŽ", + "9ŒŽ", + "10ŒŽ", + "11ŒŽ", + "12ŒŽ"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "T‚Ìʼn‚Ì—j“ú‚ðØ‚è‘Ö‚¦"; +Calendar._TT["PREV_YEAR"] = "‘O”N"; +Calendar._TT["PREV_MONTH"] = "‘OŒŽ"; +Calendar._TT["GO_TODAY"] = "¡“ú"; +Calendar._TT["NEXT_MONTH"] = "—‚ŒŽ"; +Calendar._TT["NEXT_YEAR"] = "—‚”N"; +Calendar._TT["SEL_DATE"] = "“ú•t‘I‘ð"; +Calendar._TT["DRAG_TO_MOVE"] = "ƒEƒBƒ“ƒhƒE‚̈ړ®"; +Calendar._TT["PART_TODAY"] = " (¡“ú)"; +Calendar._TT["MON_FIRST"] = "ŒŽ—j“ú‚ð擪‚É"; +Calendar._TT["SUN_FIRST"] = "“ú—j“ú‚ð擪‚É"; +Calendar._TT["CLOSE"] = "•Â‚¶‚é"; +Calendar._TT["TODAY"] = "¡“ú"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "y-mm-dd"; +Calendar._TT["TT_DATE_FORMAT"] = "%mŒŽ %d“ú (%a)"; + +Calendar._TT["WK"] = "T"; diff --git a/src/core/static/js/jscalendar/lang/calendar-ko-utf8.js b/src/core/static/js/jscalendar/lang/calendar-ko-utf8.js new file mode 100755 index 0000000..f75db6a --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-ko-utf8.js @@ -0,0 +1,120 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, <mishoo@infoiasi.ro> +// Translation: Yourim Yi <yyi@yourim.net> +// Encoding: EUC-KR +// lang : ko +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names + +Calendar._DN = new Array +("ì¼ìš”ì¼", + "월요ì¼", + "화요ì¼", + "수요ì¼", + "목요ì¼", + "금요ì¼", + "토요ì¼", + "ì¼ìš”ì¼"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("ì¼", + "ì›”", + "í™”", + "수", + "목", + "금", + "토", + "ì¼"); + +// full month names +Calendar._MN = new Array +("1ì›”", + "2ì›”", + "3ì›”", + "4ì›”", + "5ì›”", + "6ì›”", + "7ì›”", + "8ì›”", + "9ì›”", + "10ì›”", + "11ì›”", + "12ì›”"); + +// short month names +Calendar._SMN = new Array +("1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "calendar ì— ëŒ€í•´ì„œ"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"\n"+ +"최신 ë²„ì „ì„ ë°›ìœ¼ì‹œë ¤ë©´ http://dynarch.com/mishoo/calendar.epl ì— ë°©ë¬¸í•˜ì„¸ìš”\n" + +"\n"+ +"GNU LGPL ë¼ì´ì„¼ìŠ¤ë¡œ ë°°í¬ë©ë‹ˆë‹¤. \n"+ +"ë¼ì´ì„¼ìŠ¤ì— 대한 ìžì„¸í•œ ë‚´ìš©ì€ http://gnu.org/licenses/lgpl.html ì„ ì½ìœ¼ì„¸ìš”." + +"\n\n" + +"날짜 ì„ íƒ:\n" + +"- ì—°ë„를 ì„ íƒí•˜ë ¤ë©´ \xab, \xbb ë²„íŠ¼ì„ ì‚¬ìš©í•©ë‹ˆë‹¤\n" + +"- ë‹¬ì„ ì„ íƒí•˜ë ¤ë©´ " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ë²„íŠ¼ì„ ëˆ„ë¥´ì„¸ìš”\n" + +"- ê³„ì† ëˆ„ë¥´ê³  있으면 위 ê°’ë“¤ì„ ë¹ ë¥´ê²Œ ì„ íƒí•˜ì‹¤ 수 있습니다."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"시간 ì„ íƒ:\n" + +"- 마우스로 누르면 ì‹œê°„ì´ ì¦ê°€í•©ë‹ˆë‹¤\n" + +"- Shift 키와 함께 누르면 ê°ì†Œí•©ë‹ˆë‹¤\n" + +"- 누른 ìƒíƒœì—ì„œ 마우스를 움ì§ì´ë©´ 좀 ë” ë¹ ë¥´ê²Œ ê°’ì´ ë³€í•©ë‹ˆë‹¤.\n"; + +Calendar._TT["PREV_YEAR"] = "지난 í•´ (길게 누르면 목ë¡)"; +Calendar._TT["PREV_MONTH"] = "지난 달 (길게 누르면 목ë¡)"; +Calendar._TT["GO_TODAY"] = "오늘 날짜로"; +Calendar._TT["NEXT_MONTH"] = "ë‹¤ìŒ ë‹¬ (길게 누르면 목ë¡)"; +Calendar._TT["NEXT_YEAR"] = "ë‹¤ìŒ í•´ (길게 누르면 목ë¡)"; +Calendar._TT["SEL_DATE"] = "날짜를 ì„ íƒí•˜ì„¸ìš”"; +Calendar._TT["DRAG_TO_MOVE"] = "마우스 드래그로 ì´ë™ 하세요"; +Calendar._TT["PART_TODAY"] = " (오늘)"; +Calendar._TT["MON_FIRST"] = "월요ì¼ì„ í•œ ì£¼ì˜ ì‹œìž‘ ìš”ì¼ë¡œ"; +Calendar._TT["SUN_FIRST"] = "ì¼ìš”ì¼ì„ í•œ ì£¼ì˜ ì‹œìž‘ ìš”ì¼ë¡œ"; +Calendar._TT["CLOSE"] = "닫기"; +Calendar._TT["TODAY"] = "오늘"; +Calendar._TT["TIME_PART"] = "(Shift-)í´ë¦­ ë˜ëŠ” 드래그 하세요"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%b/%e [%a]"; + +Calendar._TT["WK"] = "주"; diff --git a/src/core/static/js/jscalendar/lang/calendar-ko.js b/src/core/static/js/jscalendar/lang/calendar-ko.js new file mode 100755 index 0000000..6c6946b --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-ko.js @@ -0,0 +1,120 @@ +// ** I18N + +// Calendar EN language +// Author: Mihai Bazon, <mishoo@infoiasi.ro> +// Translation: Yourim Yi <yyi@yourim.net> +// Encoding: EUC-KR +// lang : ko +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names + +Calendar._DN = new Array +("ÀÏ¿äÀÏ", + "¿ù¿äÀÏ", + "È­¿äÀÏ", + "¼ö¿äÀÏ", + "¸ñ¿äÀÏ", + "±Ý¿äÀÏ", + "Åä¿äÀÏ", + "ÀÏ¿äÀÏ"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("ÀÏ", + "¿ù", + "È­", + "¼ö", + "¸ñ", + "±Ý", + "Åä", + "ÀÏ"); + +// full month names +Calendar._MN = new Array +("1¿ù", + "2¿ù", + "3¿ù", + "4¿ù", + "5¿ù", + "6¿ù", + "7¿ù", + "8¿ù", + "9¿ù", + "10¿ù", + "11¿ù", + "12¿ù"); + +// short month names +Calendar._SMN = new Array +("1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "calendar ¿¡ ´ëÇؼ­"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"\n"+ +"ÃֽŠ¹öÀüÀ» ¹ÞÀ¸½Ã·Á¸é http://dynarch.com/mishoo/calendar.epl ¿¡ ¹æ¹®Çϼ¼¿ä\n" + +"\n"+ +"GNU LGPL ¶óÀ̼¾½º·Î ¹èÆ÷µË´Ï´Ù. \n"+ +"¶óÀ̼¾½º¿¡ ´ëÇÑ ÀÚ¼¼ÇÑ ³»¿ëÀº http://gnu.org/licenses/lgpl.html À» ÀÐÀ¸¼¼¿ä." + +"\n\n" + +"³¯Â¥ ¼±ÅÃ:\n" + +"- ¿¬µµ¸¦ ¼±ÅÃÇÏ·Á¸é \xab, \xbb ¹öÆ°À» »ç¿ëÇÕ´Ï´Ù\n" + +"- ´ÞÀ» ¼±ÅÃÇÏ·Á¸é " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ¹öÆ°À» ´©¸£¼¼¿ä\n" + +"- °è¼Ó ´©¸£°í ÀÖÀ¸¸é À§ °ªµéÀ» ºü¸£°Ô ¼±ÅÃÇÏ½Ç ¼ö ÀÖ½À´Ï´Ù."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"½Ã°£ ¼±ÅÃ:\n" + +"- ¸¶¿ì½º·Î ´©¸£¸é ½Ã°£ÀÌ Áõ°¡ÇÕ´Ï´Ù\n" + +"- Shift Å°¿Í ÇÔ²² ´©¸£¸é °¨¼ÒÇÕ´Ï´Ù\n" + +"- ´©¸¥ »óÅ¿¡¼­ ¸¶¿ì½º¸¦ ¿òÁ÷À̸é Á» ´õ ºü¸£°Ô °ªÀÌ º¯ÇÕ´Ï´Ù.\n"; + +Calendar._TT["PREV_YEAR"] = "Áö³­ ÇØ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["PREV_MONTH"] = "Áö³­ ´Þ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["GO_TODAY"] = "¿À´Ã ³¯Â¥·Î"; +Calendar._TT["NEXT_MONTH"] = "´ÙÀ½ ´Þ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["NEXT_YEAR"] = "´ÙÀ½ ÇØ (±æ°Ô ´©¸£¸é ¸ñ·Ï)"; +Calendar._TT["SEL_DATE"] = "³¯Â¥¸¦ ¼±ÅÃÇϼ¼¿ä"; +Calendar._TT["DRAG_TO_MOVE"] = "¸¶¿ì½º µå·¡±×·Î À̵¿ Çϼ¼¿ä"; +Calendar._TT["PART_TODAY"] = " (¿À´Ã)"; +Calendar._TT["MON_FIRST"] = "¿ù¿äÀÏÀ» ÇÑ ÁÖÀÇ ½ÃÀÛ ¿äÀÏ·Î"; +Calendar._TT["SUN_FIRST"] = "ÀÏ¿äÀÏÀ» ÇÑ ÁÖÀÇ ½ÃÀÛ ¿äÀÏ·Î"; +Calendar._TT["CLOSE"] = "´Ý±â"; +Calendar._TT["TODAY"] = "¿À´Ã"; +Calendar._TT["TIME_PART"] = "(Shift-)Ŭ¸¯ ¶Ç´Â µå·¡±× Çϼ¼¿ä"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%b/%e [%a]"; + +Calendar._TT["WK"] = "ÁÖ"; diff --git a/src/core/static/js/jscalendar/lang/calendar-lt-utf8.js b/src/core/static/js/jscalendar/lang/calendar-lt-utf8.js new file mode 100755 index 0000000..a9fa8aa --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-lt-utf8.js @@ -0,0 +1,114 @@ +// ** I18N + +// Calendar LT language +// Author: Martynas Majeris, <martynas@solmetra.lt> +// Encoding: UTF-8 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Sekmadienis", + "Pirmadienis", + "Antradienis", + "TreÄiadienis", + "Ketvirtadienis", + "Pentadienis", + "Å eÅ¡tadienis", + "Sekmadienis"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Sek", + "Pir", + "Ant", + "Tre", + "Ket", + "Pen", + "Å eÅ¡", + "Sek"); + +// full month names +Calendar._MN = new Array +("Sausis", + "Vasaris", + "Kovas", + "Balandis", + "Gegužė", + "Birželis", + "Liepa", + "RugpjÅ«tis", + "RugsÄ—jis", + "Spalis", + "Lapkritis", + "Gruodis"); + +// short month names +Calendar._SMN = new Array +("Sau", + "Vas", + "Kov", + "Bal", + "Geg", + "Bir", + "Lie", + "Rgp", + "Rgs", + "Spa", + "Lap", + "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Apie kalendorių"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"NaujausiÄ… versijÄ… rasite: http://dynarch.com/mishoo/calendar.epl\n" + +"Platinamas pagal GNU LGPL licencijÄ…. Aplankykite http://gnu.org/licenses/lgpl.html" + +"\n\n" + +"Datos pasirinkimas:\n" + +"- Metų pasirinkimas: \xab, \xbb\n" + +"- MÄ—nesio pasirinkimas: " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" + +"- Nuspauskite ir laikykite pelÄ—s klaviÅ¡Ä… greitesniam pasirinkimui."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Laiko pasirinkimas:\n" + +"- Spustelkite ant valandų arba minuÄių - skaiÄius padidÄ—s vienetu.\n" + +"- Jei spausite kartu su Shift, skaiÄius sumažės.\n" + +"- Greitam pasirinkimui spustelkite ir pajudinkite pelÄ™."; + +Calendar._TT["PREV_YEAR"] = "Ankstesni metai (laikykite, jei norite meniu)"; +Calendar._TT["PREV_MONTH"] = "Ankstesnis mÄ—nuo (laikykite, jei norite meniu)"; +Calendar._TT["GO_TODAY"] = "Pasirinkti Å¡iandienÄ…"; +Calendar._TT["NEXT_MONTH"] = "Kitas mÄ—nuo (laikykite, jei norite meniu)"; +Calendar._TT["NEXT_YEAR"] = "Kiti metai (laikykite, jei norite meniu)"; +Calendar._TT["SEL_DATE"] = "Pasirinkite datÄ…"; +Calendar._TT["DRAG_TO_MOVE"] = "Tempkite"; +Calendar._TT["PART_TODAY"] = " (Å¡iandien)"; +Calendar._TT["MON_FIRST"] = "Pirma savaitÄ—s diena - pirmadienis"; +Calendar._TT["SUN_FIRST"] = "Pirma savaitÄ—s diena - sekmadienis"; +Calendar._TT["CLOSE"] = "Uždaryti"; +Calendar._TT["TODAY"] = "Å iandien"; +Calendar._TT["TIME_PART"] = "Spustelkite arba tempkite jei norite pakeisti"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %Y-%m-%d"; + +Calendar._TT["WK"] = "sav"; diff --git a/src/core/static/js/jscalendar/lang/calendar-lt.js b/src/core/static/js/jscalendar/lang/calendar-lt.js new file mode 100755 index 0000000..dca66a2 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-lt.js @@ -0,0 +1,114 @@ +// ** I18N + +// Calendar LT language +// Author: Martynas Majeris, <martynas@solmetra.lt> +// Encoding: Windows-1257 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("Sekmadienis", + "Pirmadienis", + "Antradienis", + "Treèiadienis", + "Ketvirtadienis", + "Pentadienis", + "Ðeðtadienis", + "Sekmadienis"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. + +// short day names +Calendar._SDN = new Array +("Sek", + "Pir", + "Ant", + "Tre", + "Ket", + "Pen", + "Ðeð", + "Sek"); + +// full month names +Calendar._MN = new Array +("Sausis", + "Vasaris", + "Kovas", + "Balandis", + "Geguþë", + "Birþelis", + "Liepa", + "Rugpjûtis", + "Rugsëjis", + "Spalis", + "Lapkritis", + "Gruodis"); + +// short month names +Calendar._SMN = new Array +("Sau", + "Vas", + "Kov", + "Bal", + "Geg", + "Bir", + "Lie", + "Rgp", + "Rgs", + "Spa", + "Lap", + "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Apie kalendoriø"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"Naujausià versijà rasite: http://dynarch.com/mishoo/calendar.epl\n" + +"Platinamas pagal GNU LGPL licencijà. Aplankykite http://gnu.org/licenses/lgpl.html" + +"\n\n" + +"Datos pasirinkimas:\n" + +"- Metø pasirinkimas: \xab, \xbb\n" + +"- Mënesio pasirinkimas: " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" + +"- Nuspauskite ir laikykite pelës klaviðà greitesniam pasirinkimui."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Laiko pasirinkimas:\n" + +"- Spustelkite ant valandø arba minuèiø - skaièus padidës vienetu.\n" + +"- Jei spausite kartu su Shift, skaièius sumaþës.\n" + +"- Greitam pasirinkimui spustelkite ir pajudinkite pelæ."; + +Calendar._TT["PREV_YEAR"] = "Ankstesni metai (laikykite, jei norite meniu)"; +Calendar._TT["PREV_MONTH"] = "Ankstesnis mënuo (laikykite, jei norite meniu)"; +Calendar._TT["GO_TODAY"] = "Pasirinkti ðiandienà"; +Calendar._TT["NEXT_MONTH"] = "Kitas mënuo (laikykite, jei norite meniu)"; +Calendar._TT["NEXT_YEAR"] = "Kiti metai (laikykite, jei norite meniu)"; +Calendar._TT["SEL_DATE"] = "Pasirinkite datà"; +Calendar._TT["DRAG_TO_MOVE"] = "Tempkite"; +Calendar._TT["PART_TODAY"] = " (ðiandien)"; +Calendar._TT["MON_FIRST"] = "Pirma savaitës diena - pirmadienis"; +Calendar._TT["SUN_FIRST"] = "Pirma savaitës diena - sekmadienis"; +Calendar._TT["CLOSE"] = "Uþdaryti"; +Calendar._TT["TODAY"] = "Ðiandien"; +Calendar._TT["TIME_PART"] = "Spustelkite arba tempkite jei norite pakeisti"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %Y-%m-%d"; + +Calendar._TT["WK"] = "sav"; diff --git a/src/core/static/js/jscalendar/lang/calendar-nl.js b/src/core/static/js/jscalendar/lang/calendar-nl.js new file mode 100755 index 0000000..1190a2e --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-nl.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("Zondag", + "Maandag", + "Dinsdag", + "Woensdag", + "Donderdag", + "Vrijdag", + "Zaterdag", + "Zondag"); +Calendar._MN = new Array +("Januari", + "Februari", + "Maart", + "April", + "Mei", + "Juni", + "Juli", + "Augustus", + "September", + "Oktober", + "November", + "December"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Selecteer de eerste week-dag"; +Calendar._TT["PREV_YEAR"] = "Vorig jaar (ingedrukt voor menu)"; +Calendar._TT["PREV_MONTH"] = "Vorige maand (ingedrukt voor menu)"; +Calendar._TT["GO_TODAY"] = "Ga naar Vandaag"; +Calendar._TT["NEXT_MONTH"] = "Volgende maand (ingedrukt voor menu)"; +Calendar._TT["NEXT_YEAR"] = "Volgend jaar (ingedrukt voor menu)"; +Calendar._TT["SEL_DATE"] = "Selecteer datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Klik en sleep om te verplaatsen"; +Calendar._TT["PART_TODAY"] = " (vandaag)"; +Calendar._TT["MON_FIRST"] = "Toon Maandag eerst"; +Calendar._TT["SUN_FIRST"] = "Toon Zondag eerst"; +Calendar._TT["CLOSE"] = "Sluiten"; +Calendar._TT["TODAY"] = "Vandaag"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "DD, d MM"; + +Calendar._TT["WK"] = "wk"; diff --git a/src/core/static/js/jscalendar/lang/calendar-no.js b/src/core/static/js/jscalendar/lang/calendar-no.js new file mode 100755 index 0000000..ff4f98d --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-no.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("Søndag", + "Mandag", + "Tirsdag", + "Onsdag", + "Torsdag", + "Fredag", + "Lørdag", + "Søndag"); +Calendar._MN = new Array +("Januar", + "Februar", + "Mars", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Desember"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Skift første ukedag"; +Calendar._TT["PREV_YEAR"] = "Et år tilbake (hold for meny)"; +Calendar._TT["PREV_MONTH"] = "En måned tilbake (hold for meny)"; +Calendar._TT["GO_TODAY"] = "Gå til i dag"; +Calendar._TT["NEXT_MONTH"] = "En måned fram (hold for meny)"; +Calendar._TT["NEXT_YEAR"] = "Et år fram (hold for meny)"; +Calendar._TT["SEL_DATE"] = "Velg dag"; +Calendar._TT["DRAG_TO_MOVE"] = "Dra vinduet"; +Calendar._TT["PART_TODAY"] = " (i dag)"; +Calendar._TT["MON_FIRST"] = "Vis mandag først"; +Calendar._TT["SUN_FIRST"] = "Vis søndag først"; +Calendar._TT["CLOSE"] = "Lukk vinduet"; +Calendar._TT["TODAY"] = "I dag"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "y-mm-dd"; +Calendar._TT["TT_DATE_FORMAT"] = "D d. M, y"; + +Calendar._TT["WK"] = "wk"; diff --git a/src/core/static/js/jscalendar/lang/calendar-pl-utf8.js b/src/core/static/js/jscalendar/lang/calendar-pl-utf8.js new file mode 100755 index 0000000..98a0277 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-pl-utf8.js @@ -0,0 +1,93 @@ +// ** I18N + +// Calendar PL language +// Author: Dariusz Pietrzak, <eyck@ghost.anime.pl> +// Author: Janusz Piwowarski, <jpiw@go2.pl> +// Encoding: utf-8 +// Distributed under the same terms as the calendar itself. + +Calendar._DN = new Array +("Niedziela", + "PoniedziaÅ‚ek", + "Wtorek", + "Åšroda", + "Czwartek", + "PiÄ…tek", + "Sobota", + "Niedziela"); +Calendar._SDN = new Array +("Nie", + "Pn", + "Wt", + "Åšr", + "Cz", + "Pt", + "So", + "Nie"); +Calendar._MN = new Array +("StyczeÅ„", + "Luty", + "Marzec", + "KwiecieÅ„", + "Maj", + "Czerwiec", + "Lipiec", + "SierpieÅ„", + "WrzesieÅ„", + "Październik", + "Listopad", + "GrudzieÅ„"); +Calendar._SMN = new Array +("Sty", + "Lut", + "Mar", + "Kwi", + "Maj", + "Cze", + "Lip", + "Sie", + "Wrz", + "Paź", + "Lis", + "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O kalendarzu"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"Aby pobrać najnowszÄ… wersjÄ™, odwiedź: http://dynarch.com/mishoo/calendar.epl\n" + +"DostÄ™pny na licencji GNU LGPL. Zobacz szczegóły na http://gnu.org/licenses/lgpl.html." + +"\n\n" + +"Wybór daty:\n" + +"- Użyj przycisków \xab, \xbb by wybrać rok\n" + +"- Użyj przycisków " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " by wybrać miesiÄ…c\n" + +"- Przytrzymaj klawisz myszy nad jednym z powyższych przycisków dla szybszego wyboru."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Wybór czasu:\n" + +"- Kliknij na jednym z pól czasu by zwiÄ™kszyć jego wartość\n" + +"- lub kliknij trzymajÄ…c Shift by zmiejszyć jego wartość\n" + +"- lub kliknij i przeciÄ…gnij dla szybszego wyboru."; + +//Calendar._TT["TOGGLE"] = "ZmieÅ„ pierwszy dzieÅ„ tygodnia"; +Calendar._TT["PREV_YEAR"] = "Poprzedni rok (przytrzymaj dla menu)"; +Calendar._TT["PREV_MONTH"] = "Poprzedni miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["GO_TODAY"] = "Idź do dzisiaj"; +Calendar._TT["NEXT_MONTH"] = "NastÄ™pny miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["NEXT_YEAR"] = "NastÄ™pny rok (przytrzymaj dla menu)"; +Calendar._TT["SEL_DATE"] = "Wybierz datÄ™"; +Calendar._TT["DRAG_TO_MOVE"] = "PrzeciÄ…gnij by przesunąć"; +Calendar._TT["PART_TODAY"] = " (dzisiaj)"; +Calendar._TT["MON_FIRST"] = "WyÅ›wietl poniedziaÅ‚ek jako pierwszy"; +Calendar._TT["SUN_FIRST"] = "WyÅ›wietl niedzielÄ™ jako pierwszÄ…"; +Calendar._TT["CLOSE"] = "Zamknij"; +Calendar._TT["TODAY"] = "Dzisiaj"; +Calendar._TT["TIME_PART"] = "(Shift-)Kliknij lub przeciÄ…gnij by zmienić wartość"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%e %B, %A"; + +Calendar._TT["WK"] = "ty"; diff --git a/src/core/static/js/jscalendar/lang/calendar-pl.js b/src/core/static/js/jscalendar/lang/calendar-pl.js new file mode 100755 index 0000000..df99fb0 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-pl.js @@ -0,0 +1,56 @@ +// ** I18N +// Calendar PL language +// Author: Artur Filipiak, <imagen@poczta.fm> +// January, 2004 +// Encoding: UTF-8 +Calendar._DN = new Array +("Niedziela", "PoniedziaÅ‚ek", "Wtorek", "Åšroda", "Czwartek", "PiÄ…tek", "Sobota", "Niedziela"); + +Calendar._SDN = new Array +("N", "Pn", "Wt", "Åšr", "Cz", "Pt", "So", "N"); + +Calendar._MN = new Array +("StyczeÅ„", "Luty", "Marzec", "KwiecieÅ„", "Maj", "Czerwiec", "Lipiec", "SierpieÅ„", "WrzesieÅ„", "Październik", "Listopad", "GrudzieÅ„"); + +Calendar._SMN = new Array +("Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "Paź", "Lis", "Gru"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O kalendarzu"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"For latest version visit: http://dynarch.com/mishoo/calendar.epl\n" + +"Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"Wybór daty:\n" + +"- aby wybrać rok użyj przycisków \xab, \xbb\n" + +"- aby wybrać miesiÄ…c użyj przycisków " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" + +"- aby przyspieszyć wybór przytrzymaj wciÅ›niÄ™ty przycisk myszy nad ww. przyciskami."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Wybór czasu:\n" + +"- aby zwiÄ™kszyć wartość kliknij na dowolnym elemencie selekcji czasu\n" + +"- aby zmniejszyć wartość użyj dodatkowo klawisza Shift\n" + +"- możesz również poruszać myszkÄ™ w lewo i prawo wraz z wciÅ›niÄ™tym lewym klawiszem."; + +Calendar._TT["PREV_YEAR"] = "Poprz. rok (przytrzymaj dla menu)"; +Calendar._TT["PREV_MONTH"] = "Poprz. miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["GO_TODAY"] = "Pokaż dziÅ›"; +Calendar._TT["NEXT_MONTH"] = "Nast. miesiÄ…c (przytrzymaj dla menu)"; +Calendar._TT["NEXT_YEAR"] = "Nast. rok (przytrzymaj dla menu)"; +Calendar._TT["SEL_DATE"] = "Wybierz datÄ™"; +Calendar._TT["DRAG_TO_MOVE"] = "PrzesuÅ„ okienko"; +Calendar._TT["PART_TODAY"] = " (dziÅ›)"; +Calendar._TT["MON_FIRST"] = "Pokaż PoniedziaÅ‚ek jako pierwszy"; +Calendar._TT["SUN_FIRST"] = "Pokaż NiedzielÄ™ jako pierwszÄ…"; +Calendar._TT["CLOSE"] = "Zamknij"; +Calendar._TT["TODAY"] = "DziÅ›"; +Calendar._TT["TIME_PART"] = "(Shift-)klik | drag, aby zmienić wartość"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y.%m.%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "wk"; \ No newline at end of file diff --git a/src/core/static/js/jscalendar/lang/calendar-pt.js b/src/core/static/js/jscalendar/lang/calendar-pt.js new file mode 100755 index 0000000..0bbdc7c --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-pt.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("Domingo", + "Segunda", + "Terça", + "Quarta", + "Quinta", + "Sexta", + "Sábado", + "Domingo"); +Calendar._MN = new Array +("Janeiro", + "Fevereiro", + "Março", + "Abril", + "Maio", + "Junho", + "Julho", + "Agosto", + "Setembro", + "Outubro", + "Novembro", + "Dezembro"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Trocar o primeiro dia da semana"; +Calendar._TT["PREV_YEAR"] = "Ano Anterior (mantenha para menu)"; +Calendar._TT["PREV_MONTH"] = "Mês Anterior (mantenha para menu)"; +Calendar._TT["GO_TODAY"] = "Ir para hoje"; +Calendar._TT["NEXT_MONTH"] = "Próximo Mês (mantenha para menu)"; +Calendar._TT["NEXT_YEAR"] = "Próximo Ano (mantenha para menu)"; +Calendar._TT["SEL_DATE"] = "Escolha Data"; +Calendar._TT["DRAG_TO_MOVE"] = "Arraste para mover"; +Calendar._TT["PART_TODAY"] = " (hoje)"; +Calendar._TT["MON_FIRST"] = "Mostrar Segunda primeiro"; +Calendar._TT["SUN_FIRST"] = "Mostrar Domingo primeiro"; +Calendar._TT["CLOSE"] = "Fechar"; +Calendar._TT["TODAY"] = "Hoje"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "a-mm-dd"; +Calendar._TT["TT_DATE_FORMAT"] = "D, M d"; + +Calendar._TT["WK"] = "sm"; diff --git a/src/core/static/js/jscalendar/lang/calendar-ro.js b/src/core/static/js/jscalendar/lang/calendar-ro.js new file mode 100755 index 0000000..02a7885 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-ro.js @@ -0,0 +1,66 @@ +// ** I18N +Calendar._DN = new Array +("Duminică", + "Luni", + "MarÅ£i", + "Miercuri", + "Joi", + "Vineri", + "Sâmbătă", + "Duminică"); +Calendar._SDN_len = 2; +Calendar._MN = new Array +("Ianuarie", + "Februarie", + "Martie", + "Aprilie", + "Mai", + "Iunie", + "Iulie", + "August", + "Septembrie", + "Octombrie", + "Noiembrie", + "Decembrie"); + +// tooltips +Calendar._TT = {}; + +Calendar._TT["INFO"] = "Despre calendar"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"Pentru ultima versiune vizitaÅ£i: http://dynarch.com/mishoo/calendar.epl\n" + +"Distribuit sub GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + +"\n\n" + +"SelecÅ£ia datei:\n" + +"- FolosiÅ£i butoanele \xab, \xbb pentru a selecta anul\n" + +"- FolosiÅ£i butoanele " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " pentru a selecta luna\n" + +"- TineÅ£i butonul mouse-ului apăsat pentru selecÅ£ie mai rapidă."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"SelecÅ£ia orei:\n" + +"- Click pe ora sau minut pentru a mări valoarea cu 1\n" + +"- Sau Shift-Click pentru a micÅŸora valoarea cu 1\n" + +"- Sau Click ÅŸi drag pentru a selecta mai repede."; + +Calendar._TT["PREV_YEAR"] = "Anul precedent (lung pt menu)"; +Calendar._TT["PREV_MONTH"] = "Luna precedentă (lung pt menu)"; +Calendar._TT["GO_TODAY"] = "Data de azi"; +Calendar._TT["NEXT_MONTH"] = "Luna următoare (lung pt menu)"; +Calendar._TT["NEXT_YEAR"] = "Anul următor (lung pt menu)"; +Calendar._TT["SEL_DATE"] = "Selectează data"; +Calendar._TT["DRAG_TO_MOVE"] = "Trage pentru a miÅŸca"; +Calendar._TT["PART_TODAY"] = " (astăzi)"; +Calendar._TT["DAY_FIRST"] = "AfiÅŸează %s prima zi"; +Calendar._TT["WEEKEND"] = "0,6"; +Calendar._TT["CLOSE"] = "ÃŽnchide"; +Calendar._TT["TODAY"] = "Astăzi"; +Calendar._TT["TIME_PART"] = "(Shift-)Click sau drag pentru a selecta"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %d %B"; + +Calendar._TT["WK"] = "spt"; +Calendar._TT["TIME"] = "Ora:"; diff --git a/src/core/static/js/jscalendar/lang/calendar-ru.js b/src/core/static/js/jscalendar/lang/calendar-ru.js new file mode 100755 index 0000000..3bdae17 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-ru.js @@ -0,0 +1,45 @@ +// ** I18N +Calendar._DN = new Array +("Âîñêðåñåíüå", + "Ïîíåäåëüíèê", + "Âòîðíèê", + "Ñðåäà", + "×åòâåðã", + "Ïÿòíèöà", + "Ñóááîòà", + "Âîñêðåñåíüå"); +Calendar._MN = new Array +("ßíâàðü", + "Ôåâðàëü", + "Ìàðò", + "Àïðåëü", + "Ìàé", + "Èþíü", + "Èþëü", + "Àâãóñò", + "Ñåíòÿáðü", + "Îêòÿáðü", + "Íîÿáðü", + "Äåêàáðü"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Ñìåíèòü äåíü íà÷àëà íåäåëè (ÏÍ/ÂÑ)"; +Calendar._TT["PREV_YEAR"] = "Ïðåä. ãîä (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["PREV_MONTH"] = "Ïðåä. ìåñÿö (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["GO_TODAY"] = "Íà ñåãîäíÿ"; +Calendar._TT["NEXT_MONTH"] = "Ñëåä. ìåñÿö (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["NEXT_YEAR"] = "Ñëåä. ãîä (óäåðæèâàòü äëÿ ìåíþ)"; +Calendar._TT["SEL_DATE"] = "Âûáðàòü äàòó"; +Calendar._TT["DRAG_TO_MOVE"] = "Ïåðåòàùèòü"; +Calendar._TT["PART_TODAY"] = " (ñåãîäíÿ)"; +Calendar._TT["MON_FIRST"] = "Ïîêàçàòü ïîíåäåëüíèê ïåðâûì"; +Calendar._TT["SUN_FIRST"] = "Ïîêàçàòü âîñêðåñåíüå ïåðâûì"; +Calendar._TT["CLOSE"] = "Çàêðûòü"; +Calendar._TT["TODAY"] = "Ñåãîäíÿ"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "y-mm-dd"; +Calendar._TT["TT_DATE_FORMAT"] = "D, M d"; + +Calendar._TT["WK"] = "íåä"; diff --git a/src/core/static/js/jscalendar/lang/calendar-si.js b/src/core/static/js/jscalendar/lang/calendar-si.js new file mode 100755 index 0000000..77f4aa8 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-si.js @@ -0,0 +1,94 @@ +/* Slovenian language file for the DHTML Calendar version 0.9.2 +* Author David Milost <mercy@volja.net>, January 2004. +* Feel free to use this script under the terms of the GNU Lesser General +* Public License, as long as you do not remove or alter this notice. +*/ + // full day names +Calendar._DN = new Array +("Nedelja", + "Ponedeljek", + "Torek", + "Sreda", + "ÄŒetrtek", + "Petek", + "Sobota", + "Nedelja"); + // short day names + Calendar._SDN = new Array +("Ned", + "Pon", + "Tor", + "Sre", + "ÄŒet", + "Pet", + "Sob", + "Ned"); +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "Maj", + "Jun", + "Jul", + "Avg", + "Sep", + "Okt", + "Nov", + "Dec"); + // full month names +Calendar._MN = new Array +("Januar", + "Februar", + "Marec", + "April", + "Maj", + "Junij", + "Julij", + "Avgust", + "September", + "Oktober", + "November", + "December"); + +// tooltips +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O koledarju"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"Za zadnjo verzijo pojdine na naslov: http://dynarch.com/mishoo/calendar.epl\n" + +"Distribuirano pod GNU LGPL. Poglejte http://gnu.org/licenses/lgpl.html za podrobnosti." + +"\n\n" + +"Izbor datuma:\n" + +"- Uporabite \xab, \xbb gumbe za izbor leta\n" + +"- Uporabite " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " gumbe za izbor meseca\n" + +"- Zadržite klik na kateremkoli od zgornjih gumbov za hiter izbor."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Izbor ćasa:\n" + +"- Kliknite na katerikoli del ćasa za poveć. le-tega\n" + +"- ali Shift-click za zmanj. le-tega\n" + +"- ali kliknite in povlecite za hiter izbor."; + +Calendar._TT["TOGGLE"] = "Spremeni dan s katerim se prićne teden"; +Calendar._TT["PREV_YEAR"] = "Predhodnje leto (dolg klik za meni)"; +Calendar._TT["PREV_MONTH"] = "Predhodnji mesec (dolg klik za meni)"; +Calendar._TT["GO_TODAY"] = "Pojdi na tekoći dan"; +Calendar._TT["NEXT_MONTH"] = "Naslednji mesec (dolg klik za meni)"; +Calendar._TT["NEXT_YEAR"] = "Naslednje leto (dolg klik za meni)"; +Calendar._TT["SEL_DATE"] = "Izberite datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Pritisni in povleci za spremembo pozicije"; +Calendar._TT["PART_TODAY"] = " (danes)"; +Calendar._TT["MON_FIRST"] = "Prikaži ponedeljek kot prvi dan"; +Calendar._TT["SUN_FIRST"] = "Prikaži nedeljo kot prvi dan"; +Calendar._TT["CLOSE"] = "Zapri"; +Calendar._TT["TODAY"] = "Danes"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e"; + +Calendar._TT["WK"] = "Ted"; \ No newline at end of file diff --git a/src/core/static/js/jscalendar/lang/calendar-sk.js b/src/core/static/js/jscalendar/lang/calendar-sk.js new file mode 100755 index 0000000..9b8c205 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-sk.js @@ -0,0 +1,99 @@ +// ** I18N + +// Calendar SK language +// Author: Peter Valach (pvalach@gmx.net) +// Encoding: utf-8 +// Last update: 2003/10/29 +// Distributed under the same terms as the calendar itself. + +// full day names +Calendar._DN = new Array +("NedeÄľa", + "Pondelok", + "Utorok", + "Streda", + "Ĺ tvrtok", + "Piatok", + "Sobota", + "NedeÄľa"); + +// short day names +Calendar._SDN = new Array +("Ned", + "Pon", + "Uto", + "Str", + "Ĺ tv", + "Pia", + "Sob", + "Ned"); + +// full month names +Calendar._MN = new Array +("Január", + "Február", + "Marec", + "AprĂ­l", + "Máj", + "JÄ‚ÅŸn", + "JÄ‚ÅŸl", + "August", + "September", + "OktÄ‚Å‚ber", + "November", + "December"); + +// short month names +Calendar._SMN = new Array +("Jan", + "Feb", + "Mar", + "Apr", + "Máj", + "JÄ‚ÅŸn", + "JÄ‚ÅŸl", + "Aug", + "Sep", + "Okt", + "Nov", + "Dec"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "O kalendári"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + +"PoslednÄ‚ÅŸ verziu nájdete na: http://dynarch.com/mishoo/calendar.epl\n" + +"DistribuovanĂ© pod GNU LGPL. ViÄŹ http://gnu.org/licenses/lgpl.html pre detaily." + +"\n\n" + +"VÄ‚Ëber dátumu:\n" + +"- PouĹľite tlaÄŤidlá \xab, \xbb pre vÄ‚Ëber roku\n" + +"- PouĹľite tlaÄŤidlá " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " pre vÄ‚Ëber mesiaca\n" + +"- Ak ktorĂ©koÄľvek z tÄ‚Ëchto tlaÄŤidiel podržíte dlhšie, zobrazĂ­ sa rÄ‚Ëchly vÄ‚Ëber."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"VÄ‚Ëber ÄŤasu:\n" + +"- Kliknutie na niektorÄ‚ÅŸ poloĹľku ÄŤasu ju zvÄ‚Ëši\n" + +"- Shift-klik ju znĂ­Ĺľi\n" + +"- Ak podržíte tlaÄŤĂ­tko stlaÄŤenĂ©, posÄ‚ÅŸvanĂ­m menĂ­te hodnotu."; + +Calendar._TT["PREV_YEAR"] = "PredošlÄ‚Ë rok (podrĹľte pre menu)"; +Calendar._TT["PREV_MONTH"] = "PredošlÄ‚Ë mesiac (podrĹľte pre menu)"; +Calendar._TT["GO_TODAY"] = "PrejsĹĄ na dnešok"; +Calendar._TT["NEXT_MONTH"] = "Nasl. mesiac (podrĹľte pre menu)"; +Calendar._TT["NEXT_YEAR"] = "Nasl. rok (podrĹľte pre menu)"; +Calendar._TT["SEL_DATE"] = "ZvoÄľte dátum"; +Calendar._TT["DRAG_TO_MOVE"] = "PodrĹľanĂ­m tlaÄŤĂ­tka zmenĂ­te polohu"; +Calendar._TT["PART_TODAY"] = " (dnes)"; +Calendar._TT["MON_FIRST"] = "ZobraziĹĄ pondelok ako prvÄ‚Ë"; +Calendar._TT["SUN_FIRST"] = "ZobraziĹĄ nedeÄľu ako prvÄ‚ÅŸ"; +Calendar._TT["CLOSE"] = "ZavrieĹĄ"; +Calendar._TT["TODAY"] = "Dnes"; +Calendar._TT["TIME_PART"] = "(Shift-)klik/ĹĄahanie zmenĂ­ hodnotu"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "$d. %m. %Y"; +Calendar._TT["TT_DATE_FORMAT"] = "%a, %e. %b"; + +Calendar._TT["WK"] = "tÄ‚ËĹľ"; diff --git a/src/core/static/js/jscalendar/lang/calendar-sp.js b/src/core/static/js/jscalendar/lang/calendar-sp.js new file mode 100755 index 0000000..5aa94c6 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-sp.js @@ -0,0 +1,63 @@ +// ** I18N +Calendar._DN = new Array +("Domingo", + "Lunes", + "Martes", + "Miercoles", + "Jueves", + "Viernes", + "Sabado", + "Domingo"); +Calendar._MN = new Array +("Enero", + "Febrero", + "Marzo", + "Abril", + "Mayo", + "Junio", + "Julio", + "Agosto", + "Septiembre", + "Octubre", + "Noviembre", + "Diciembre"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Información del Calendario"; + +Calendar._TT["ABOUT"] = +"DHTML Date/Time Selector\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"Nuevas versiones en: http://dynarch.com/mishoo/calendar.epl\n" + +"Distribuida bajo licencia GNU LGPL. Para detalles vea http://gnu.org/licenses/lgpl.html ." + +"\n\n" + +"Selección de Fechas:\n" + +"- Use \xab, \xbb para seleccionar el año\n" + +"- Use " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " para seleccionar el mes\n" + +"- Mantenga presionado el botón del ratón en cualquiera de las opciones superiores para un acceso rapido ."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Selección del Reloj:\n" + +"- Seleccione la hora para cambiar el reloj\n" + +"- o presione Shift-click para disminuirlo\n" + +"- o presione click y arrastre del ratón para una selección rapida."; + +Calendar._TT["TOGGLE"] = "Primer dia de la semana"; +Calendar._TT["PREV_YEAR"] = "Año anterior (Presione para menu)"; +Calendar._TT["PREV_MONTH"] = "Mes Anterior (Presione para menu)"; +Calendar._TT["GO_TODAY"] = "Ir a Hoy"; +Calendar._TT["NEXT_MONTH"] = "Mes Siguiente (Presione para menu)"; +Calendar._TT["NEXT_YEAR"] = "Año Siguiente (Presione para menu)"; +Calendar._TT["SEL_DATE"] = "Seleccione fecha"; +Calendar._TT["DRAG_TO_MOVE"] = "Arrastre y mueva"; +Calendar._TT["PART_TODAY"] = " (Hoy)"; +Calendar._TT["MON_FIRST"] = "Lunes Primero"; +Calendar._TT["SUN_FIRST"] = "Domingo Primero"; +Calendar._TT["CLOSE"] = "Cerrar"; +Calendar._TT["TODAY"] = "Hoy"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-yy"; +Calendar._TT["TT_DATE_FORMAT"] = "%A, %e de %B de %Y"; + +Calendar._TT["WK"] = "Smn"; diff --git a/src/core/static/js/jscalendar/lang/calendar-sv.js b/src/core/static/js/jscalendar/lang/calendar-sv.js new file mode 100755 index 0000000..07adb4c --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-sv.js @@ -0,0 +1,93 @@ +// ** I18N + +// Calendar SV language (Swedish, svenska) +// Author: Mihai Bazon, <mishoo@infoiasi.ro> +// Translation team: <sv@li.org> +// Translator: Leonard Norrgård <leonard.norrgard@refactor.fi> +// Last translator: Leonard Norrgård <leonard.norrgard@refactor.fi> +// Encoding: iso-latin-1 +// Distributed under the same terms as the calendar itself. + +// For translators: please use UTF-8 if possible. We strongly believe that +// Unicode is the answer to a real internationalized world. Also please +// include your contact information in the header, as can be seen above. + +// full day names +Calendar._DN = new Array +("söndag", + "måndag", + "tisdag", + "onsdag", + "torsdag", + "fredag", + "lördag", + "söndag"); + +// Please note that the following array of short day names (and the same goes +// for short month names, _SMN) isn't absolutely necessary. We give it here +// for exemplification on how one can customize the short day names, but if +// they are simply the first N letters of the full name you can simply say: +// +// Calendar._SDN_len = N; // short day name length +// Calendar._SMN_len = N; // short month name length +// +// If N = 3 then this is not needed either since we assume a value of 3 if not +// present, to be compatible with translation files that were written before +// this feature. +Calendar._SDN_len = 2; +Calendar._SMN_len = 3; + +// full month names +Calendar._MN = new Array +("januari", + "februari", + "mars", + "april", + "maj", + "juni", + "juli", + "augusti", + "september", + "oktober", + "november", + "december"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["INFO"] = "Om kalendern"; + +Calendar._TT["ABOUT"] = +"DHTML Datum/tid-väljare\n" + +"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) +"För senaste version gå till: http://dynarch.com/mishoo/calendar.epl\n" + +"Distribueras under GNU LGPL. Se http://gnu.org/licenses/lgpl.html för detaljer." + +"\n\n" + +"Val av datum:\n" + +"- Använd knapparna \xab, \xbb för att välja år\n" + +"- Använd knapparna " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " för att välja månad\n" + +"- Håll musknappen nedtryckt på någon av ovanstående knappar för snabbare val."; +Calendar._TT["ABOUT_TIME"] = "\n\n" + +"Val av tid:\n" + +"- Klicka på en del av tiden för att öka den delen\n" + +"- eller skift-klicka för att minska den\n" + +"- eller klicka och drag för snabbare val."; + +Calendar._TT["PREV_YEAR"] = "Föregående år (håll för menu)"; +Calendar._TT["PREV_MONTH"] = "Föregående månad (håll för menu)"; +Calendar._TT["GO_TODAY"] = "Gå till dagens datum"; +Calendar._TT["NEXT_MONTH"] = "Följande månad (håll för menu)"; +Calendar._TT["NEXT_YEAR"] = "Följande år (håll för menu)"; +Calendar._TT["SEL_DATE"] = "Välj datum"; +Calendar._TT["DRAG_TO_MOVE"] = "Drag för att flytta"; +Calendar._TT["PART_TODAY"] = " (idag)"; +Calendar._TT["MON_FIRST"] = "Visa måndag först"; +Calendar._TT["SUN_FIRST"] = "Visa söndag först"; +Calendar._TT["CLOSE"] = "Stäng"; +Calendar._TT["TODAY"] = "Idag"; +Calendar._TT["TIME_PART"] = "(Skift-)klicka eller drag för att ändra tid"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d"; +Calendar._TT["TT_DATE_FORMAT"] = "%A %d %b %Y"; + +Calendar._TT["WK"] = "vecka"; diff --git a/src/core/static/js/jscalendar/lang/calendar-tr.js b/src/core/static/js/jscalendar/lang/calendar-tr.js new file mode 100755 index 0000000..2164687 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-tr.js @@ -0,0 +1,58 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// Turkish Translation by Nuri AKMAN +// Location: Ankara/TURKEY +// e-mail : nuriakman@hotmail.com +// Date : April, 9 2003 +// +// Note: if Turkish Characters does not shown on you screen +// please include falowing line your html code: +// +// <meta http-equiv="Content-Type" content="text/html; charset=windows-1254"> +// +////////////////////////////////////////////////////////////////////////////////////////////// + +// ** I18N +Calendar._DN = new Array +("Pazar", + "Pazartesi", + "Salý", + "Çarþamba", + "Perþembe", + "Cuma", + "Cumartesi", + "Pazar"); +Calendar._MN = new Array +("Ocak", + "Þubat", + "Mart", + "Nisan", + "Mayýs", + "Haziran", + "Temmuz", + "Aðustos", + "Eylül", + "Ekim", + "Kasým", + "Aralýk"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Haftanýn ilk gününü kaydýr"; +Calendar._TT["PREV_YEAR"] = "Önceki Yýl (Menü için basýlý tutunuz)"; +Calendar._TT["PREV_MONTH"] = "Önceki Ay (Menü için basýlý tutunuz)"; +Calendar._TT["GO_TODAY"] = "Bugün'e git"; +Calendar._TT["NEXT_MONTH"] = "Sonraki Ay (Menü için basýlý tutunuz)"; +Calendar._TT["NEXT_YEAR"] = "Sonraki Yýl (Menü için basýlý tutunuz)"; +Calendar._TT["SEL_DATE"] = "Tarih seçiniz"; +Calendar._TT["DRAG_TO_MOVE"] = "Taþýmak için sürükleyiniz"; +Calendar._TT["PART_TODAY"] = " (bugün)"; +Calendar._TT["MON_FIRST"] = "Takvim Pazartesi gününden baþlasýn"; +Calendar._TT["SUN_FIRST"] = "Takvim Pazar gününden baþlasýn"; +Calendar._TT["CLOSE"] = "Kapat"; +Calendar._TT["TODAY"] = "Bugün"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "dd-mm-y"; +Calendar._TT["TT_DATE_FORMAT"] = "d MM y, DD"; + +Calendar._TT["WK"] = "Hafta"; diff --git a/src/core/static/js/jscalendar/lang/calendar-zh.js b/src/core/static/js/jscalendar/lang/calendar-zh.js new file mode 100755 index 0000000..c0c5456 --- /dev/null +++ b/src/core/static/js/jscalendar/lang/calendar-zh.js @@ -0,0 +1,45 @@ +// ** Translated by ATang ** I18N +Calendar._DN = new Array +("ÐÇÆÚÈÕ", + "ÐÇÆÚÒ»", + "ÐÇÆÚ¶þ", + "ÐÇÆÚÈý", + "ÐÇÆÚËÄ", + "ÐÇÆÚÎå", + "ÐÇÆÚÁù", + "ÐÇÆÚÈÕ"); +Calendar._MN = new Array +("Ò»ÔÂ", + "¶þÔÂ", + "ÈýÔÂ", + "ËÄÔÂ", + "ÎåÔÂ", + "ÁùÔÂ", + "ÆßÔÂ", + "°ËÔÂ", + "¾ÅÔÂ", + "Ê®ÔÂ", + "ʮһÔÂ", + "Ê®¶þÔÂ"); + +// tooltips +Calendar._TT = {}; +Calendar._TT["TOGGLE"] = "Çл»ÖÜ¿ªÊ¼µÄÒ»Ìì"; +Calendar._TT["PREV_YEAR"] = "ÉÏÒ»Äê (°´×¡³ö²Ëµ¥)"; +Calendar._TT["PREV_MONTH"] = "ÉÏÒ»Ô (°´×¡³ö²Ëµ¥)"; +Calendar._TT["GO_TODAY"] = "µ½½ñÈÕ"; +Calendar._TT["NEXT_MONTH"] = "ÏÂÒ»Ô (°´×¡³ö²Ëµ¥)"; +Calendar._TT["NEXT_YEAR"] = "ÏÂÒ»Äê (°´×¡³ö²Ëµ¥)"; +Calendar._TT["SEL_DATE"] = "Ñ¡ÔñÈÕÆÚ"; +Calendar._TT["DRAG_TO_MOVE"] = "Í϶¯"; +Calendar._TT["PART_TODAY"] = " (½ñÈÕ)"; +Calendar._TT["MON_FIRST"] = "Ê×ÏÈÏÔʾÐÇÆÚÒ»"; +Calendar._TT["SUN_FIRST"] = "Ê×ÏÈÏÔʾÐÇÆÚÈÕ"; +Calendar._TT["CLOSE"] = "¹Ø±Õ"; +Calendar._TT["TODAY"] = "½ñÈÕ"; + +// date formats +Calendar._TT["DEF_DATE_FORMAT"] = "y-mm-dd"; +Calendar._TT["TT_DATE_FORMAT"] = "D, M d"; + +Calendar._TT["WK"] = "ÖÜ"; diff --git a/src/core/static/js/jscalendar/menuarrow.gif b/src/core/static/js/jscalendar/menuarrow.gif new file mode 100755 index 0000000000000000000000000000000000000000..ed2dee0e6368d201bf5d32833884c7c1da6c7424 GIT binary patch literal 68 zcmZ?wbhEHbWM^Py_{hZ2(9rPi-LwDy|1&T!DE?$&WME)o&;ha;K=KSsqAVN&i(DE6 VRJ~d>0vEY-3aNTcS;53$4FHxP5xxKb literal 0 HcmV?d00001 diff --git a/src/core/static/js/jscalendar/menuarrow2.gif b/src/core/static/js/jscalendar/menuarrow2.gif new file mode 100755 index 0000000000000000000000000000000000000000..40c0aadfc6e62e7cdf4a0dc4a3a3d735c6995b76 GIT binary patch literal 49 zcmZ?wbhEHbWM^PyXkcV;a&r3r|G(l-7DfgJMg|=QAOOiQFmbfVR-Qb-pUlW$4FDM} B3akJC literal 0 HcmV?d00001 diff --git a/src/core/static/js/jscalendar/release-notes.html b/src/core/static/js/jscalendar/release-notes.html new file mode 100755 index 0000000..8963781 --- /dev/null +++ b/src/core/static/js/jscalendar/release-notes.html @@ -0,0 +1,334 @@ +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN"> +<html> + <head> + <title>jscalendar release notes</title> + + <style type="text/css"> + h1 { border-bottom: 1px solid #000; } + h2 { border-bottom: 1px solid #444; } + ul li { margin-top: 0.5em; margin-bottom: 0.5em; } + </style> + </head> + + <body> + <h1>jscalendar release notes</h1> + + <p>This release compiled at Friday, 6 Feb 2004 (21:40).</p> + + <h2>0.9.6</h2> + + <ul> + + <li> + "Smart" (TM :-) positioning algorithm. The new algorithm will + try to keep the calendar in the browser view, which is helpful + in situations when the input field is near the bottom or the + right edge. This code is only tested with IE and Mozilla, but + it should work with other browsers too. Many thanks to <a + href="http://www.ex3.com">Sunny Chowdhury</a> for sponsoring + this feature! + </li> + + <li> + Support for IE5/Win is back. I also want to thank Janusz + Piwowarski for keeping his eye on the CVS ;-) He reviewed my + IE5-related changes and sent me a much cleaner patch. + </li> + + <li> + The calendar will now allow any day of week to be "the first + day of week". This was requested long time ago, by someone + whose name I forgot (sorry). The reason was that in certain + countries weeks start on Saturday. So I thought that instead + of having a "mondayFirst" and a "saturdayFirst" parameter, + :-), it's better to have a "firstDayOfWeek" parameter; now + it's present and its meaning is: "0 for Sunday", "1 for + Monday", "2 for Tuesday", etc. The equivalent parameter for + Calendar.setup is "firstDay". The end user can also change + it very easy: click on the day name in the calendar display. + </li> + + <li> + The above feature triggered one <b>important change</b>: the + notion of "weekend" is now defined in the language file. + Added parameters: + + <pre> + Calendar._TT["WEEKEND"] = "0,6"; + Calendar._TT["DAY_FIRST"] = "Display %s first";</pre> + + "WEEKEND" specifies a string with comma-separated numbers from + 0 to 7; they define what days are marked as "weekend". 5 and + 6 mean, of course, "Sunday" and "Saturday". Day first is the + tooltip displayed when a day name is hovered; "%s" will get + replaced with the day name. Updated languages are "en" and + "ro", which I maintain. Please note that languages wich are + not updated <b>will not work</b>. If yours is one of them, + please consider fixing it and sending me the fix so that I can + include it in the distro. + </li> + + <li> + The calendar can now display days from the months adjacent to + the currently displayed one. This is optional, of course, and + the parameter name is "showsOtherMonths" (or "showOthers" in + Calendar.setup). All theme files were updated. + </li> + + <li> + Displays "Time:" near the time selector, only if defined in + the language file. + </li> + + <li> + Some bugs fixed in the date parsing code (which has also been + rewritten a little bit cleaner). + </li> + + <li> + Calendar.setup will now configure the calendar to trigger the + input fields' "onchange" event, if specified, when a date is + selected. + </li> + + <li> + New parameter in Calendar.setup: "cache" (<b>defaults to + false</b>). If set to true then the popup calendar object + will be "cached", meaning, it will be created only once, no + matter how many input fields are there in the page. Sometimes + this is not desirable, which is why I've added this + parameter. Please note that it defaults to "false" (thus the + default behavior has changed). + </li> + + <li> + Added a simple PHP wrapper. It provides code which loads all + the required scripts and theme file, and one function which + creates and configures an input field for date input. It + takes care of creating and assigning unique ID-s for the + calendar fields and it also creates the "Calendar.setup" code. + Functions to create more specialized fields can be added very + easily. This feature was requested by the FreeMED.org project + (thanks for donating!). + </li> + + </ul> + + <p>Wow, there were quite some changes :-D Enjoy it!</p> + + <h2>0.9.5</h2> + + <p> + This release's primary goal is to fix a wrong license statement which + can be found in some files from 0.9.4. For instance in README or + calendar.js, the statement was that the code is distributed under the + GNU GPL; that's because I had plans to change the license, then + changed my mind but unfortunately I committed files so. I am sorry + for this inconvenience, please use the latest (0.9.5) release which is + fully covered by LGPL. + </p> + + <p>Other changes:</p> + + <ul> + + <li> + <b>Fixed</b> an annoying bug that prevented the calendar to display + correctly when it was configured for an input field inside a + <b>scrolling area</b>. <b>Many thanks</b> to Ian Barrack (<a + href="http://www.simban.com">Simban.com</a>) who pointed it up and + donated quite some money for the Calendar project! + </li> + + <li> + All examples use UTF-8 now; the translations may not be all + up-to-date, but I <strong>strongly</strong> suggest everyone to use + UTF-8; other encodings are a plain mess. So far I know for sure + that Romanian translation will work with UTF-8 and <em>not + anymore</em> with ISO-8859-2. Other translations are probably + usable under UTF-8, but if your preferred language isn't... ;-) + please make it and send it to me for inclusion. + </li> + + <li> + Fixed small bug in the documentation (one footnote didn't appear + where it should have). + </li> + + <li> + Updated translations: DE, ES, HU, IT, RO. Thanks to everyone who + sent translations! + </li> + + </ul> + + <h2>0.9.4</h2> + + <h3>New stuff</h3> + + <ul> + + <li>Supports time selection. Yes. ;-) This work has been largely + sponsored by <strong>Himanshukumar Shah</strong> (thank you!). See + the docs and example files for details on how to setup.</li> + + <li>Easy to link 2 or more fields by using the new + <code>onUpdate</code> parameter of <code>Calendar.setup</code>. This + is useful, say, to automatically set a value in a second field based + on the value selected in the first field. See the documentation and + first sample in <a href="simple-1.html">simple-1.html</a>.</li> + + <li>Other <code>Calendar.setup</code> low-level parameters, for those + wanting to have the complete control: <code>onSelect</code> and + <code>onClose</code>. The handlers are called when something is + selected in the calendar or when the calendar is closed.</li> + + <li>The translation files can optionally include the short day names + and the short month names. That's because in some languages, like + German, the short form is not the first 3 letters of the entire name + but only the first 2. Also in other languages short names can't be + as easily derived from the full name by just calling substr, so this + patch solves the problem.</li> + + <li>Implemented a nice way to make some dates "special" (look + different). Specifically, the <code>setDisabledHandler</code> method + was replaced with the more general <code>setDateStatusHandler</code> + method (the old one is still available for backwards compatibility but + <em>will</em> be removed). More details about this in the + documentation. Also see <a href="simple-3.html">simple-3.html</a> + for a live sample.</li> + + <li>Date parsing and formatting engine is now rewritten and supports a + subset of <code>strftime</code> format specifiers from ANSI C. This + makes it possible to use dates like "YYYYMMDD" (the corresponding + format for this would be "%Y%m%d"). Details in the documentation. + <b>Please note that the new engine is not compatibile with older + calendar releases!</b></li> + + <li>Along with the new date parser I workarounded an unpleasant crash + that occurred in IE when certain accented characters appeared in the + texts. I think German was one of the language with such problems, and + the workaround was to use the letter without an accent. Well, now you + can translate to whatever you want.</li> + + <li>"Fixes" (I mean, "horrible workarounds") for Konqueror (and + hopefully Safari). Unfortunately, this otherwise excellent browser + still has some bugs that keep the calendar from working + <em>exactly</em> as it should.. But they're going to be fixed, + right? ;-)</li> + + <li>CSS themes got pretty much modified too so if you wrote your theme + you need to update it. Aside for the time selector support, the CSS + themes contain a simple hack that makes the navigation buttons show + a little arrow in the lower-right corner which indicates that if one + holds the mouse a menu will appear.</li> + + </ul> + + <h3>Translation files</h3> + + <p>The translation files need to be updated in order for the calendar to + work properly. Currently the only updated files are calendar-en.js + (main file) and calendar-ro.js (well, yes, I am a Romanian ;-).</p> + + <p>Specifically, they need the following:</p> + + <ul> + + <li>Correct date format, according with the new format specifiers + introduced in 0.9.4. Details about the available format specifiers + in the documentation</li> + + <li>Short day or month names, <em>if required</em>. If they can be + derived by taking the first N letters of the full name then a simple + Calendar._SDN_len = N or Calendar._SMN_len = N will suffice. If N + is 3 then nothing needs to be done as we take it for granted if no + other option is offered ;-)</li> + + <li>We have some new texts that shows short usage information as well + as copyright information.</li> + + </ul> + + <p>If your favorite language is not there yet, or it is but not updated + according to the main calendar-en.js file, then please consider + translating calendar-en.js and send the translation back to me so that + I include it in the official distribution.</p> + + <h3>Bug status</h3> + + <p>Check <a + href="http://sourceforge.net/tracker/?atid=544285&group_id=75569&func=browse">SourceForge</a>, + I didn't keep track. However, there were a lot of bugfixes.</p> + + <h2>0.9.3</h2> + + <h3>New stuff</h3> + + <ul> + + <li>Opera&nbsp;7 compatibility &mdash; keyboard navigation is + still not available; text selection can't be disabled, leading to an + ugly effect when walking through the month/year menus.</li> + + <li>Ability to align the calendar relative to the input field (or any + other element). Vertical: top, center, bottom. Horizontal: left, + center, right. This is established as a new parameter for + <tt>showAtElement</tt>.</li> + + <li>Added <tt>dateClicked</tt> property (boolean). This can be + inspected in the "onSelect" handler to determine if a date was + really clicked or the user only changed month/year using the menus. + You <em>need</em> to check this for "single-click" calendars and + only close/hide the calendar if it's <tt>true</tt>.</li> + + <li>Full documentation in <a href="doc/html/reference.html">HTML</a> + and <a href="doc/reference.pdf">PDF</a> format is now available in the + distribution archive.</li> + + <li>New language definition files: HU, HR, PT, ZH. Thanks those who + submitted!</li> + + </ul> + + <h3>Bug status</h3> + + <p>This covers only those bugs that have been reported <a + href="http://sourceforge.net/projects/jscalendar" target="_blank" + title="Project page at SourceForge">at SourceForge</a>.</p> + + <ol> + + <li><a href="http://sourceforge.net/tracker/index.php?func=detail&aid=703238&group_id=75569&atid=544285" target="_blank" + title="Go to bug description at sourceforge"><tt>#703,238</tt></a> &mdash; fixed</li> + <li><a href="http://sourceforge.net/tracker/index.php?func=detail&aid=703814&group_id=75569&atid=544285" target="_blank" + title="Go to bug description at sourceforge"><tt>#703,814</tt></a> &mdash; fixed</li> + <li><a href="http://sourceforge.net/tracker/index.php?func=detail&aid=716777&group_id=75569&atid=544285" target="_blank" + title="Go to bug description at sourceforge"><tt>#716,777</tt></a> &mdash; closed (was fixed already in 0.9.2-1)</li> + <li><a href="http://sourceforge.net/tracker/index.php?func=detail&aid=723335&group_id=75569&atid=544285" target="_blank" + title="Go to bug description at sourceforge"><tt>#723,335</tt></a> &mdash; fixed</li> + <li><a href="http://sourceforge.net/tracker/index.php?func=detail&aid=715122&group_id=75569&atid=544285" target="_blank" + title="Go to bug description at sourceforge"><tt>#715,122</tt></a> &mdash; feature request; implemented.</li> + <li><a href="http://sourceforge.net/tracker/index.php?func=detail&aid=721206&group_id=75569&atid=544285" target="_blank" + title="Go to bug description at sourceforge"><tt>#721,206</tt></a> &mdash; fixed (added "refresh()" function)</li> + <li><a href="http://sourceforge.net/tracker/index.php?func=detail&aid=721833&group_id=75569&atid=544285" target="_blank" + title="Go to bug description at sourceforge"><tt>#721,833</tt></a> &mdash; fixed (bug concerning the "yy" format + parsing)</li> + <li><a href="http://sourceforge.net/tracker/index.php?func=detail&aid=721833&group_id=75569&atid=544285" target="_blank" + title="Go to bug description at sourceforge"><tt>#721,833</tt></a> &mdash; won't fix (we won't set the time to + midnight; time might actually be useful when we implement support + for time selection). + + </ol> + + <hr /> + <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address> +<!-- Created: Tue Jul 8 17:29:37 EEST 2003 --> +<!-- hhmts start --> +Last modified on Wed Oct 29 02:37:07 2003 +<!-- hhmts end --> +<!-- doc-lang: English --> + </body> +</html> + + diff --git a/src/core/static/js/jscalendar/simple-1.html b/src/core/static/js/jscalendar/simple-1.html new file mode 100755 index 0000000..48f710e --- /dev/null +++ b/src/core/static/js/jscalendar/simple-1.html @@ -0,0 +1,244 @@ +<html style="background-color: buttonface; color: buttontext;"> + +<head> +<meta http-equiv="content-type" content="text/xml; charset=utf-8" /> + +<title>Simple calendar setups [popup calendar]</title> + + <!-- calendar stylesheet --> + <link rel="stylesheet" type="text/css" media="all" href="calendar-win2k-cold-1.css" title="win2k-cold-1" /> + + <!-- main calendar program --> + <script type="text/javascript" src="calendar.js"></script> + + <!-- language for the calendar --> + <script type="text/javascript" src="lang/calendar-en.js"></script> + + <!-- the following script defines the Calendar.setup helper function, which makes + adding a calendar a matter of 1 or 2 lines of code. --> + <script type="text/javascript" src="calendar-setup.js"></script> + +</head> + +<body> + +<h2>DHTML Calendar &mdash; for the impatient</h2> + + <blockquote> + <p> + This page lists some common setups for the popup calendar. In + order to see how to do any of them please see the source of this + page. For each example it's structured like this: there's the + &lt;form&gt; that contains the input field, and following there is + the JavaScript snippet that setups that form. An example of + <em>flat</em> calendar is available in <a + href="simple-2.html">another page</a>. + </p> + <p> + The code in this page uses a helper function defined in + "calendar-setup.js". With it you can setup the calendar in + minutes. If you're not <em>that</em> impatient, ;-) <a + href="doc/html/reference.html">complete documenation</a> is + available. + </p> + </blockquote> + + + +<hr /> + +<p><b>Basic setup: one input per calendar.</b> Clicking in the input field +activates the calendar. The date format is "%m/%d/%Y %I:%M %p". The +calendar defaults to "single-click mode".</p> + +<p>The example below has been updated to show you how to create "linked" +fields. Basically, when some field is filled with a date, the other +is updated so that the difference between them remains one week. The +property useful here is "onUpdate".</p> + +<form action="#" method="get"> +<input type="text" name="date" id="f_date_a" /> +<input type="text" name="date" id="f_calcdate" /> +</form> + +<script type="text/javascript"> + function catcalc(cal) { + var date = cal.date; + var time = date.getTime() + // use the _other_ field + var field = document.getElementById("f_calcdate"); + if (field == cal.params.inputField) { + field = document.getElementById("f_date_a"); + time -= Date.WEEK; // substract one week + } else { + time += Date.WEEK; // add one week + } + var date2 = new Date(time); + field.value = date2.print("%Y-%m-%d %H:%M"); + } + Calendar.setup({ + inputField : "f_date_a", // id of the input field + ifFormat : "%Y-%m-%d %H:%M", // format of the input field + showsTime : true, + timeFormat : "24", + onUpdate : catcalc + }); + Calendar.setup({ + inputField : "f_calcdate", + ifFormat : "%Y-%m-%d %H:%M", + showsTime : true, + timeFormat : "24", + onUpdate : catcalc + }); +</script> + + + +<hr /> + +<p><b>Input field with a trigger button.</b> Clicking the button activates +the calendar. Note that this one needs double-click (singleClick parameter +is explicitely set to false). Also demonstrates the "step" parameter +introduced in 0.9.6 (show all years in drop-down boxes, instead of every +other year as default).</p> + +<form action="#" method="get"> +<input type="text" name="date" id="f_date_b" /><button type="reset" id="f_trigger_b">...</button> +</form> + +<script type="text/javascript"> + Calendar.setup({ + inputField : "f_date_b", // id of the input field + ifFormat : "%m/%d/%Y %I:%M %p", // format of the input field + showsTime : true, // will display a time selector + button : "f_trigger_b", // trigger for the calendar (button ID) + singleClick : false, // double-click mode + step : 1 // show all years in drop-down boxes (instead of every other year as default) + }); +</script> + + + +<hr /> + +<p><b>Input field with a trigger image.</b> Note that the Calendar.setup +function doesn't care if the trigger is a button, image, or anything else. +Also in this example we setup a different alignment, just to show how it's +done. The input field is read-only (that is set from HTML).</p> + +<form action="#" method="get"> +<table cellspacing="0" cellpadding="0" style="border-collapse: collapse"><tr> + <td><input type="text" name="date" id="f_date_c" readonly="1" /></td> + <td><img src="img.gif" id="f_trigger_c" style="cursor: pointer; border: 1px solid red;" title="Date selector" + onmouseover="this.style.background='red';" onmouseout="this.style.background=''" /></td> +</table> +</form> + +<script type="text/javascript"> + Calendar.setup({ + inputField : "f_date_c", // id of the input field + ifFormat : "%B %e, %Y", // format of the input field + button : "f_trigger_c", // trigger for the calendar (button ID) + align : "Tl", // alignment (defaults to "Bl") + singleClick : true + }); +</script> + + + +<hr /> + +<p><b>Hidden field, display area.</b> The calendar now puts the date into 2 +elements: one is an input field of type "hidden"&mdash;so that the user +can't directly see or modify it&mdash; and one is a &lt;span&gt; element in +which the date is displayed. Note that if the trigger is not specified the +calendar will use the displayArea (or inputField as in the first example). +The display area can have it's own format. This is useful if, for instance, +we need to store one format in the database (thus pass it in the input +field) but we wanna show a friendlier format to the end-user.</p> + +<form action="#" method="get" style="visibility: hidden"> +<input type="hidden" name="date" id="f_date_d" /> +</form> + +<p>Your birthday: + <span style="background-color: #ff8; cursor: default;" + onmouseover="this.style.backgroundColor='#ff0';" + onmouseout="this.style.backgroundColor='#ff8';" + id="show_d" + >Click to open date selector</span>.</p> + +<script type="text/javascript"> + Calendar.setup({ + inputField : "f_date_d", // id of the input field + ifFormat : "%Y/%d/%m", // format of the input field (even if hidden, this format will be honored) + displayArea : "show_d", // ID of the span where the date is to be shown + daFormat : "%A, %B %d, %Y",// format of the displayed date + align : "Tl", // alignment (defaults to "Bl") + singleClick : true + }); +</script> + + + +<hr /> + +<p><b>Hidden field, display area, trigger image.</b> Very similar to the +previous example. The difference is that we also have a trigger image.</p> + +<form action="#" method="get" style="visibility: hidden"> +<input type="hidden" name="date" id="f_date_e" /> +</form> + +<p>Your birthday: <span id="show_e">-- not entered --</span> <img +src="img.gif" id="f_trigger_e" style="cursor: pointer; border: 1px solid +red;" title="Date selector" onmouseover="this.style.background='red';" +onmouseout="this.style.background=''" />.</p> + +<script type="text/javascript"> + Calendar.setup({ + inputField : "f_date_e", // id of the input field + ifFormat : "%Y/%d/%m", // format of the input field (even if hidden, this format will be honored) + displayArea : "show_e", // ID of the span where the date is to be shown + daFormat : "%A, %B %d, %Y",// format of the displayed date + button : "f_trigger_e", // trigger button (well, IMG in our case) + align : "Tl", // alignment (defaults to "Bl") + singleClick : true + }); +</script> + + + +<hr /> + +<p><b>Hidden field, display area.</b> Very much like the previous examples, +but we now disable some dates (all weekends, that is, Saturdays and +Sundays).</p> + +<form action="#" method="get" style="visibility: hidden"> +<input type="hidden" name="date" id="f_date_f" /> +</form> + +<p>Your birthday: + <span style="background-color: #ff8; cursor: default;" + onmouseover="this.style.backgroundColor='#ff0';" + onmouseout="this.style.backgroundColor='#ff8';" + id="show_f" + >Click to open date selector</span>.</p> + +<script type="text/javascript"> + Calendar.setup({ + inputField : "f_date_f", // id of the input field + ifFormat : "%Y/%d/%m", // format of the input field (even if hidden, this format will be honored) + displayArea : "show_f", // ID of the span where the date is to be shown + daFormat : "%A, %B %d, %Y",// format of the displayed date + align : "Tl", // alignment (defaults to "Bl") + dateStatusFunc : function (date) { // disable weekend days (Saturdays == 6 and Subdays == 0) + return (date.getDay() == 6 || date.getDay() == 0) ? true : false; + } + }); +</script> + + +</body> +</html> diff --git a/src/core/static/js/jscalendar/simple-2.html b/src/core/static/js/jscalendar/simple-2.html new file mode 100755 index 0000000..e430c12 --- /dev/null +++ b/src/core/static/js/jscalendar/simple-2.html @@ -0,0 +1,108 @@ +<html style="background-color: buttonface; color: buttontext;"> + +<head> +<meta http-equiv="content-type" content="text/xml; charset=utf-8" /> + +<title>Simple calendar setup [flat calendar]</title> + + <!-- calendar stylesheet --> + <link rel="stylesheet" type="text/css" media="all" href="calendar-win2k-cold-1.css" title="win2k-cold-1" /> + + <!-- main calendar program --> + <script type="text/javascript" src="calendar.js"></script> + + <!-- language for the calendar --> + <script type="text/javascript" src="lang/calendar-en.js"></script> + + <!-- the following script defines the Calendar.setup helper function, which makes + adding a calendar a matter of 1 or 2 lines of code. --> + <script type="text/javascript" src="calendar-setup.js"></script> + +</head> + +<body> + +<h2>DHTML Calendar &mdash; for the impatient</h2> + + <blockquote> + <p> + This page demonstrates how to setup a flat calendar. Examples of + <em>popup</em> calendars are available in <a + href="simple-1.html">another page</a>. + </p> + <p> + The code in this page uses a helper function defined in + "calendar-setup.js". With it you can setup the calendar in + minutes. If you're not <em>that</em> impatient, ;-) <a + href="doc/html/reference.html">complete documenation</a> is + available. + </p> + </blockquote> + + + +<hr /> + +<div style="float: right; margin-left: 1em; margin-bottom: 1em;" +id="calendar-container"></div> + +<script type="text/javascript"> + function dateChanged(calendar) { + // Beware that this function is called even if the end-user only + // changed the month/year. In order to determine if a date was + // clicked you can use the dateClicked property of the calendar: + if (calendar.dateClicked) { + // OK, a date was clicked, redirect to /yyyy/mm/dd/index.php + var y = calendar.date.getFullYear(); + var m = calendar.date.getMonth(); // integer, 0..11 + var d = calendar.date.getDate(); // integer, 1..31 + // redirect... + window.location = "/" + y + "/" + m + "/" + d + "/index.php"; + } + }; + + Calendar.setup( + { + flat : "calendar-container", // ID of the parent element + flatCallback : dateChanged // our callback function + } + ); +</script> + +<p>The positioning of the DIV that contains the calendar is entirely your +job. For instance, the "calendar-container" DIV from this page has the +following style: "float: right; margin-left: 1em; margin-bottom: 1em".</p> + +<p>Following there is the code that has been used to create this calendar. +You can find the full description of the <tt>Calendar.setup()</tt> function +in the <a href="doc/html/reference.html">calendar documenation</a>.</p> + +<pre +>&lt;div style="float: right; margin-left: 1em; margin-bottom: 1em;" +id="calendar-container"&gt;&lt;/div&gt; + +&lt;script type="text/javascript"&gt; + function dateChanged(calendar) { + // Beware that this function is called even if the end-user only + // changed the month/year. In order to determine if a date was + // clicked you can use the dateClicked property of the calendar: + if (calendar.dateClicked) { + // OK, a date was clicked, redirect to /yyyy/mm/dd/index.php + var y = calendar.date.getFullYear(); + var m = calendar.date.getMonth(); // integer, 0..11 + var d = calendar.date.getDate(); // integer, 1..31 + // redirect... + window.location = "/" + y + "/" + m + "/" + d + "/index.php"; + } + }; + + Calendar.setup( + { + flat : "calendar-container", // ID of the parent element + flatCallback : dateChanged // our callback function + } + ); +&lt;/script&gt;</pre> + +</body> +</html> diff --git a/src/core/static/js/jscalendar/simple-3.html b/src/core/static/js/jscalendar/simple-3.html new file mode 100755 index 0000000..753ca43 --- /dev/null +++ b/src/core/static/js/jscalendar/simple-3.html @@ -0,0 +1,130 @@ +<html style="background-color: buttonface; color: buttontext;"> + +<head> +<meta http-equiv="content-type" content="text/xml; charset=utf-8" /> + +<title>Simple calendar setup [flat calendar]</title> + + <!-- calendar stylesheet --> + <link rel="stylesheet" type="text/css" media="all" href="calendar-win2k-cold-1.css" title="win2k-cold-1" /> + + <!-- main calendar program --> + <script type="text/javascript" src="calendar.js"></script> + + <!-- language for the calendar --> + <script type="text/javascript" src="lang/calendar-en.js"></script> + + <!-- the following script defines the Calendar.setup helper function, which makes + adding a calendar a matter of 1 or 2 lines of code. --> + <script type="text/javascript" src="calendar-setup.js"></script> + + <style type="text/css"> + .special { background-color: #000; color: #fff; } + </style> + +</head> + +<body> + +<h2>DHTML Calendar &mdash; for the impatient</h2> + + <blockquote> + <p> + This page demonstrates how to setup a flat calendar. Examples of + <em>popup</em> calendars are available in <a + href="simple-1.html">another page</a>. + </p> + <p> + The code in this page uses a helper function defined in + "calendar-setup.js". With it you can setup the calendar in + minutes. If you're not <em>that</em> impatient, ;-) <a + href="doc/html/reference.html">complete documenation</a> is + available. + </p> + </blockquote> + + + +<hr /> + +<div style="float: right; margin-left: 1em; margin-bottom: 1em;" +id="calendar-container"></div> + +<script type="text/javascript"> + var SPECIAL_DAYS = { + 0 : [ 13, 24 ], // special days in January + 2 : [ 1, 6, 8, 12, 18 ], // special days in March + 8 : [ 21, 11 ] // special days in September + }; + + function dateIsSpecial(year, month, day) { + var m = SPECIAL_DAYS[month]; + if (!m) return false; + for (var i in m) if (m[i] == day) return true; + return false; + }; + + function dateChanged(calendar) { + // Beware that this function is called even if the end-user only + // changed the month/year. In order to determine if a date was + // clicked you can use the dateClicked property of the calendar: + if (calendar.dateClicked) { + // OK, a date was clicked, redirect to /yyyy/mm/dd/index.php + var y = calendar.date.getFullYear(); + var m = calendar.date.getMonth(); // integer, 0..11 + var d = calendar.date.getDate(); // integer, 1..31 + // redirect... + window.location = "/" + y + "/" + m + "/" + d + "/index.php"; + } + }; + + Calendar.setup( + { + flat : "calendar-container", // ID of the parent element + flatCallback : dateChanged, // our callback function + dateStatusFunc : function(date, y, m, d) { + if (dateIsSpecial(y, m, d)) return "special"; + else return false; // other dates are enabled + // return true if you want to disable other dates + } + } + ); +</script> + +<p>The positioning of the DIV that contains the calendar is entirely your +job. For instance, the "calendar-container" DIV from this page has the +following style: "float: right; margin-left: 1em; margin-bottom: 1em".</p> + +<p>Following there is the code that has been used to create this calendar. +You can find the full description of the <tt>Calendar.setup()</tt> function +in the <a href="doc/html/reference.html">calendar documenation</a>.</p> + +<pre +>&lt;div style="float: right; margin-left: 1em; margin-bottom: 1em;" +id="calendar-container"&gt;&lt;/div&gt; + +&lt;script type="text/javascript"&gt; + function dateChanged(calendar) { + // Beware that this function is called even if the end-user only + // changed the month/year. In order to determine if a date was + // clicked you can use the dateClicked property of the calendar: + if (calendar.dateClicked) { + // OK, a date was clicked, redirect to /yyyy/mm/dd/index.php + var y = calendar.date.getFullYear(); + var m = calendar.date.getMonth(); // integer, 0..11 + var d = calendar.date.getDate(); // integer, 1..31 + // redirect... + window.location = "/" + y + "/" + m + "/" + d + "/index.php"; + } + }; + + Calendar.setup( + { + flat : "calendar-container", // ID of the parent element + flatCallback : dateChanged // our callback function + } + ); +&lt;/script&gt;</pre> + +</body> +</html> diff --git a/src/core/static/js/jscalendar/test-position.html b/src/core/static/js/jscalendar/test-position.html new file mode 100755 index 0000000..48d794b --- /dev/null +++ b/src/core/static/js/jscalendar/test-position.html @@ -0,0 +1,40 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> + + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <title>JS Calendar (positioning test)</title> + <script type="text/javascript" src="calendar.js"></script> + <script type="text/javascript" src="calendar-setup.js"></script> + <script type="text/javascript" src="lang/calendar-en.js"></script> + <style type="text/css"> @import url("calendar-win2k-cold-1.css"); </style> + </head> + + <body style="height: 100%; margin: 0px; padding: 0px;"> + <table style="height: 100%; width: 100%;" cellspacing="0" cellpadding="0"> + <tr style="height: 100%;"> + <td style="vertical-align: top; text-align: left;"> + <input type="text" id="cal-field-1" /> + <button type="submit" id="cal-button-1">...</button> + <script type="text/javascript"> + Calendar.setup({ + inputField : "cal-field-1", + button : "cal-button-1", + align : "Tr" + }); + </script> + </td> + <td style="vertical-align: bottom; text-align: right;"> + <input type="text" id="cal-field-2" /> + <button type="submit" id="cal-button-2">...</button> + <script type="text/javascript"> + Calendar.setup({ + inputField : "cal-field-2", + button : "cal-button-2" + }); + </script> + </td> + </tr> + </table> + </body> + +</html> diff --git a/src/core/static/js/jscalendar/test.php b/src/core/static/js/jscalendar/test.php new file mode 100755 index 0000000..4ae18c9 --- /dev/null +++ b/src/core/static/js/jscalendar/test.php @@ -0,0 +1,116 @@ +<?php + +$lang = $_GET['lang']; +if (!$lang) { + $lang = $_REQUEST['lang']; +} +if (!$lang) { + $lang = 'en'; +} +setcookie('lang', $lang); + +?> +<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<html> +<head> +<title> +Test for calendar.php +</title> + +<?php + +// put here the correct path to "calendar.php"; don't move the file +// "calendar.php" -- I think it's best if you leave it inside the +// "/jscalendar/" directory. Just put here the correct path to it, such as +// "../jscalendar/calendar.php" or something. +require_once ('calendar.php'); + +// parameters to constructor: +// 1. the absolute URL path to the calendar files +// 2. the languate used for the calendar (see the lang/ dir) +// 3. the theme file used for the clanedar, without the ".css" extension +// 4. boolean that specifies if the "_stripped" files are to be loaded +// The stripped files are smaller as they have no whitespace and comments +$calendar = new DHTML_Calendar('/jscalendar/', $lang, 'calendar-win2k-2', false); + +// call this in the <head> section; it will "echo" code that loads the calendar +// scripts and theme file. +$calendar->load_files(); + +?> + +</head> + +<body> + +<?php if ($_REQUEST['submitted']) { ?> + +<h1>Form submitted</h1> + +<?php foreach ($_REQUEST as $key => $val) { + echo htmlspecialchars($key) . ' = ' . htmlspecialchars($val) . '<br />'; +} ?> + +<?php } else { ?> + +<h1>Calendar.php test</h1> + + <form action="test.php" method="get"> + Select language: <select name="lang" onchange="this.form.submit()"> + <?php +$cwd = getcwd(); +chdir('lang'); +foreach (glob('*.js') as $filename) { + $l = preg_replace('/(^calendar-|.js$)/', '', $filename); + $selected = ''; + if ($l == $lang) + $selected = 'selected="selected" '; + $display = $l; + if ($l == 'en') + $display = 'EN'; + echo '<option ' . $selected . 'value="' . $l . '">' . $display . '</option>'; +} + ?> + </select> + <blockquote style="font-size: 90%"> + <b>NOTE</b>: as of this release, 0.9.6, only "EN" and "RO", which I + maintain, function correctly. Other language files do not work + because they need to be updated. If you update some language file, + please consider sending it back to me so that I can include it in the + calendar distribution. + </blockquote> + </form> + + <form action="test.php" method="get"> + <input type="hidden" name="submitted" value="1" /> + + <table> + <tr> + <td> + Date 1: + </td> + <td> + <?php $calendar->make_input_field( + // calendar options go here; see the documentation and/or calendar-setup.js + array('firstDay' => 1, // show Monday first + 'showsTime' => true, + 'showOthers' => true, + 'ifFormat' => '%Y-%m-%d %I:%M %P', + 'timeFormat' => '12'), + // field attributes go here + array('style' => 'width: 15em; color: #840; background-color: #ff8; border: 1px solid #000; text-align: center', + 'name' => 'date1', + 'value' => strftime('%Y-%m-%d %I:%M %P', strtotime('now')))); ?> + </td> + </tr> + </table> + + <hr /> + <button>Submit</button> + + </form> + +<?php } ?> + +</body> +</html> diff --git a/src/core/static/js/locale/de.js b/src/core/static/js/locale/de.js new file mode 100644 index 0000000..0ef4855 --- /dev/null +++ b/src/core/static/js/locale/de.js @@ -0,0 +1,33 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +var GlizyLocale = new Object(); +GlizyLocale = { + LANGUAGE: 'en', + WARNING: 'Achtung', + REQUIREDFIELDS: 'Diese Felder sind notwendig:', + SUCCESS: '', + SUCCESSMSG: 'Gespeichert!', + DATE_FORMAT: '%Y-%m-%d', + DATETIME_FORMAT: '%Y-%m-%d %H:%M:00', + NOVALIDFIELD: 'Die Eingabe im Feld "%s" ist nicht gültig.', + FIRSTNAME: 'First Name', + LASTNAME: 'Last Name', + EMAIL: 'email', + PASSWORD: 'password', + PRIVACY: 'Permission to use personal data is required.' +}; + +var SeadragonConfig = {}; +SeadragonConfig.Loading = "Loading..."; +SeadragonConfig.Home = "Fit Image"; +SeadragonConfig.FullPage = "Exit"; +SeadragonConfig.ZoomIn = "Zoom In"; +SeadragonConfig.ZoomOut = "Zoom Out"; + +var pageTexts = {ins: 'Einfügen', add: 'Neuen Eintrag einfügen', addFirst: 'Neuen Eintrag am Anfang einfügen', addLast: 'Neuen Eintrag am Ende einfügen', addBefore: 'Neuen Eintrag vor diesem einfügen', moveUp: 'Nach oben verschieben', moveDn: 'Nach unten verschieben', edit: 'Bearbeiten', del: 'Löschen', confirmDel: 'Wollen Sie diesen Eintrag wirklich löschen?', newImg: 'Wählen Sie ein Bild aus', newMedia: 'Wählen Sie ein Medien-Datei aus ', color: 'Wählen Sie eine Farbe aus', cancel: 'Abbrechen', ok: 'OK', save: 'Speichern', confirmSave: 'Änderungen speichern?', noSave: 'keine Änderungen vorhanden', searchOn: 'Suche in', goSearch: 'Suche starten', selItems: 'Suchergebnis', noResult: 'Kein Suchergebnis', include: 'Hinzufügen', reset: 'Neue Suche', preview: 'Vorschau' }; \ No newline at end of file diff --git a/src/core/static/js/locale/en.js b/src/core/static/js/locale/en.js new file mode 100644 index 0000000..bbe7ad1 --- /dev/null +++ b/src/core/static/js/locale/en.js @@ -0,0 +1,34 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +var GlizyLocale = new Object(); +GlizyLocale = { + LANGUAGE: 'en', + WARNING: 'Warning', + REQUIREDFIELDS: 'These fields are required:', + SUCCESS: '', + SUCCESSMSG: 'Saved!', + DATE_FORMAT: '%Y-%m-%d', + DATETIME_FORMAT: '%Y-%m-%d %H:%M:00', + NOVALIDFIELD: 'The field "%s" is not valid.', + FIRSTNAME: 'First Name', + LASTNAME: 'Last Name', + EMAIL: 'email', + PASSWORD: 'password', + PRIVACY: 'Permission to use personal data is required.' +}; + +var SeadragonConfig = {}; +SeadragonConfig.Loading = "Loading..."; +SeadragonConfig.Home = "Fit Image"; +SeadragonConfig.FullPage = "Exit"; +SeadragonConfig.ZoomIn = "Zoom In"; +SeadragonConfig.ZoomOut = "Zoom Out"; + +var pageTexts = {ins: 'Insert', add: 'Add new record', addFirst: 'Add new record before the first one', addLast: 'Add new record after the last one', addBefore: 'Add new record before this one', moveUp: 'Move up', moveDn: 'Move down', edit: 'Modify', del: 'Delete', confirmDel: 'Are you sure to delete this record?', newImg: 'Pick up an image', newMedia: 'Pick up a media file ', color: 'Pick up a color', cancel: 'Cancel', ok: 'OK', save: 'Save', confirmSave: 'Save updates?', noSave: 'Nothing to save!', searchOn: 'Search in', goSearch: 'Start search', selItems: 'selected items', noResult: 'no search result', include: 'Add', reset: 'Restart', preview: 'Preview' }; + diff --git a/src/core/static/js/locale/fr.js b/src/core/static/js/locale/fr.js new file mode 100644 index 0000000..073d7e1 --- /dev/null +++ b/src/core/static/js/locale/fr.js @@ -0,0 +1,33 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +var GlizyLocale = new Object(); +GlizyLocale = { + LANGUAGE: 'en', + WARNING: 'Attention', + REQUIREDFIELDS: 'Ces champs sont indispensable:', + SUCCESS: '', + SUCCESSMSG: 'Sauvegardé!', + DATE_FORMAT: '%Y-%m-%d', + DATETIME_FORMAT: '%Y-%m-%d %H:%M:00', + NOVALIDFIELD: 'Le champs "%s" n\'est pas valide', + FIRSTNAME: 'First Name', + LASTNAME: 'Last Name', + EMAIL: 'email', + PASSWORD: 'password', + PRIVACY: 'Permission to use personal data is required.' +}; + +var SeadragonConfig = {}; +SeadragonConfig.Loading = "Loading..."; +SeadragonConfig.Home = "Fit Image"; +SeadragonConfig.FullPage = "Exit"; +SeadragonConfig.ZoomIn = "Zoom In"; +SeadragonConfig.ZoomOut = "Zoom Out"; + +var pageTexts = {ins: 'Insérer', add: 'Ajouter un nouvel enregistrement', addFirst: 'Ajouter un nouvel enregistrement avant le premier', addLast: 'Ajouter un nouvel enregistrement avant le dernier', addBefore: 'Ajouter un nouvel enregistrement avant celui-ci', moveUp: 'Déplacer vers le haut', moveDn: 'Déplacer vers le bas', edit: 'Modifier', del: 'Supprimer', confirmDel: 'Etes-vous sur de vouloir supprimer cet enregistrement?', newImg: 'Choisir une image', newMedia: 'Choisir un fichier média', color: 'Choisir une couleur', cancel: 'Annuler', ok: 'OK', save: 'Sauvegarder', confirmSave: 'Sauvergarder les mises à jour?', noSave: 'Rien à sauvegarder!', searchOn: 'Rechercher dans', goSearch: 'Commencer la recherche', selItems: 'articles sélectionnés', noResult: 'Aucun résultat', include: 'Ajouter', reset: 'Recommencer', preview: 'Aperçu' }; \ No newline at end of file diff --git a/src/core/static/js/locale/it.js b/src/core/static/js/locale/it.js new file mode 100644 index 0000000..97df6cc --- /dev/null +++ b/src/core/static/js/locale/it.js @@ -0,0 +1,34 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +var GlizyLocale = new Object(); +GlizyLocale = { + LANGUAGE: 'it', + WARNING: 'Attenzione', + REQUIREDFIELDS: 'I seguenti campi sono richiesti', + SUCCESS: '', + SUCCESSMSG: 'Salvataggio avvenuto', + DATE_FORMAT: '%d/%m/%Y', + DATETIME_FORMAT: '%d/%m/%Y %H:%M:00', + NOVALIDFIELD: 'Il campo "%s" non e\' valido.', + FIRSTNAME: 'Nome', + LASTNAME: 'Cognome', + EMAIL: 'email', + PASSWORD: 'password', + PRIVACY: 'E\' necessario acconsentire al trattamento dei dati personali.' +}; + +var SeadragonConfig = {}; +SeadragonConfig.Loading = "Caricamento..."; +SeadragonConfig.Home = "Visualizza tutta l'immagine"; +SeadragonConfig.FullPage = "Esci"; +SeadragonConfig.ZoomIn = "Ingrandisci"; +SeadragonConfig.ZoomOut = "Riduci"; + + +var pageTexts = {ins: 'Inserisci', add: 'Aggiungi nuovo record', addFirst: 'Aggiungi nuovo record all\'inizio', addLast: 'Aggiungi nuovo record alla fine', addBefore: 'Aggiungi un record prima di questo', moveUp: 'Sposta in alto', moveDn: 'Sposta in basso', edit: 'Modifica', del: 'Rimuovi', confirmDel: 'Siete sicuri di voler cancellare il record selezionato ?', newImg: 'scegli una nuova immagine', newMedia: 'scegli un nuovo media', color: 'scegli un colore', cancel: 'Annulla', ok: 'OK', save: 'Salva', confirmSave: 'vuoi salvare le modifiche?', noSave: 'niente da salvare!', searchOn: 'Cerca in', goSearch: 'Esegui ricerca', selItems: 'item selezionati', noResult: 'nessun risultato coerente con i criteri di ricerca', include: 'Inserisci', reset: 'ricomincia', preview: 'anteprima' }; diff --git a/src/core/static/js/progressBar/progressBar.css b/src/core/static/js/progressBar/progressBar.css new file mode 100644 index 0000000..afcdb8f --- /dev/null +++ b/src/core/static/js/progressBar/progressBar.css @@ -0,0 +1,83 @@ +/* Progress Bar */ + +#progress_bar +{ + margin-left: auto ; + margin-right: auto ; + width: 400px; + display: none; +} + +.ui-progress-bar { + margin-top: 3em; + margin-bottom: 3em; +} + +.ui-progress span.ui-label { + font-size: 1.2em; + position: absolute; + right: 0; + line-height: 33px; + padding-right: 12px; + color: rgba(0,0,0,0.6); + text-shadow: rgba(255,255,255, 0.45) 0 1px 0px; + white-space: nowrap; +} + +@-webkit-keyframes animate-stripes { + from { + background-position: 0 0; + } + + to { + background-position: 44px 0; + } +} + +.ui-progress-bar { + position: relative; + height: 35px; + padding-right: 2px; + background-color: #abb2bc; + border-radius: 35px; + -moz-border-radius: 35px; + -webkit-border-radius: 35px; + background: -webkit-gradient(linear, left bottom, left top, color-stop(0, #b6bcc6), color-stop(1, #9da5b0)); + background: -moz-linear-gradient(#9da5b0 0%, #b6bcc6 100%); + -webkit-box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.5), 0px 1px 0px 0px #FFF; + -moz-box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.5), 0px 1px 0px 0px #FFF; + box-shadow: inset 0px 1px 2px 0px rgba(0, 0, 0, 0.5), 0px 1px 0px 0px #FFF; +} + +.ui-progress { + position: relative; + display: block; + overflow: hidden; + height: 33px; + -moz-border-radius: 35px; + -webkit-border-radius: 35px; + border-radius: 35px; + -webkit-background-size: 44px 44px; + background-color: #74d04c; + background: -webkit-gradient(linear, 0 0, 44 44, + color-stop(0.00, rgba(255,255,255,0.17)), + color-stop(0.25, rgba(255,255,255,0.17)), + color-stop(0.26, rgba(255,255,255,0)), + color-stop(0.50, rgba(255,255,255,0)), + color-stop(0.51, rgba(255,255,255,0.17)), + color-stop(0.75, rgba(255,255,255,0.17)), + color-stop(0.76, rgba(255,255,255,0)), + color-stop(1.00, rgba(255,255,255,0)) + ), -webkit-gradient(linear, left bottom, left top, color-stop(0, #74d04c), color-stop(1, #9bdd62)); + background: -moz-repeating-linear-gradient(top left -30deg, + rgba(255,255,255,0.17), + rgba(255,255,255,0.17) 15px, + rgba(255,255,255,0) 15px, + rgba(255,255,255,0) 30px + ), -moz-linear-gradient(#9bdd62 0%, #74d04c 100%); + -webkit-box-shadow: inset 0px 1px 0px 0px #dbf383, inset 0px -1px 1px #58c43a; + -moz-box-shadow: inset 0px 1px 0px 0px #dbf383, inset 0px -1px 1px #58c43a; + box-shadow: inset 0px 1px 0px 0px #dbf383, inset 0px -1px 1px #58c43a; + border: 1px solid #4c8932; + -webkit-animation: animate-stripes 2s linear infinite; +} diff --git a/src/core/static/js/progressBar/progressBar.js b/src/core/static/js/progressBar/progressBar.js new file mode 100644 index 0000000..eb422b4 --- /dev/null +++ b/src/core/static/js/progressBar/progressBar.js @@ -0,0 +1,52 @@ +$(function() { + var state = 'progress'; + + (function ($) { + $.fn.animateProgress = function (progress, callback) { + jQuery.fx.off = false; + old_progress = progress; + return this.each(function () { + $(this).animate({ + width: String(progress) + '%' + }, { + easing: 'swing', + step: function (progress) { + if (state === 'progress') { + + jQuery.fx.off = false; + + var labelEl = $('.ui-label', this), + valueEl = $('.value', labelEl); + + if (Math.ceil(progress) < 20) { + labelEl.hide(); + } else { + if (labelEl.is(":hidden")) { + labelEl.fadeIn(); + } + } + + valueEl.text(Math.ceil(progress) + '%'); + } + }, + + complete: function (scope, i, elem) { + if (callback) { + scope = 0; + callback.call(this, i, elem); + } + } + }); + }); + }; + }(jQuery)); + + + var resetProgressBar = function () { + jQuery.fx.off = true; + $('#progress_bar .ui-progress').width("0%"); + $('#progress_bar .ui-label').hide(); + }; + + resetProgressBar(); +}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/langs/de.js b/src/core/static/js/tiny_mce/langs/de.js new file mode 100755 index 0000000..1494406 --- /dev/null +++ b/src/core/static/js/tiny_mce/langs/de.js @@ -0,0 +1 @@ +tinyMCE.addI18n({de:{common:{"more_colors":"Weitere Farben","invalid_data":"Fehler: Sie haben ung\u00fcltige Werte eingegeben (rot markiert).","popup_blocked":"Leider hat Ihr Popup-Blocker ein Fenster unterbunden, das f\u00fcr den Betrieb dieses Programms n\u00f6tig ist. Bitte deaktivieren Sie den Popup-Blocker f\u00fcr diese Seite.","clipboard_no_support":"Wird derzeit in Ihrem Browser nicht unterst\u00fctzt. Bitte benutzen Sie stattdessen die Tastenk\u00fcrzel.","clipboard_msg":"Kopieren, Ausschneiden und Einf\u00fcgen sind im Mozilla Firefox nicht m\u00f6glich.\nM\u00f6chten Sie mehr \u00fcber dieses Problem erfahren?","not_set":"- unbestimmt -","class_name":"CSS-Klasse",browse:"Durchsuchen",close:"Schlie\u00dfen",cancel:"Abbrechen",update:"Aktualisieren",insert:"Einf\u00fcgen",apply:"\u00dcbernehmen","edit_confirm":"M\u00f6chten Sie diesen Text jetzt bearbeiten?","invalid_data_number":"{#field} muss eine Zahl sein","invalid_data_min":"{#field} muss eine Zahl gr\u00f6\u00dfer als {#min} sein","invalid_data_size":"{#field} muss eine Zahl oder ein Prozentwert sein",value:"(Wert)"},contextmenu:{full:"Blocksatz",right:"Rechtsb\u00fcndig",center:"Zentriert",left:"Linksb\u00fcndig",align:"Ausrichtung"},insertdatetime:{"day_short":"So,Mo,Di,Mi,Do,Fr,Sa,So","day_long":"Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag,Sonntag","months_short":"Jan,Feb,M\u00e4r,Apr,Mai,Juni,Juli,Aug,Sept,Okt,Nov,Dez","months_long":"Januar,Februar,M\u00e4rz,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember","inserttime_desc":"Zeit einf\u00fcgen","insertdate_desc":"Datum einf\u00fcgen","time_fmt":"%H:%M:%S","date_fmt":"%d.%m.%Y"},print:{"print_desc":"Drucken"},preview:{"preview_desc":"Vorschau"},directionality:{"rtl_desc":"Schrift von rechts nach links","ltr_desc":"Schrift von links nach rechts"},layer:{content:"Neue Ebene...","absolute_desc":"Absolute Positionierung","backward_desc":"Nach hinten legen","forward_desc":"Nach vorne holen","insertlayer_desc":"Neue Ebene einf\u00fcgen"},save:{"save_desc":"Speichern","cancel_desc":"Alle \u00c4nderungen verwerfen"},nonbreaking:{"nonbreaking_desc":"Gesch\u00fctztes Leerzeichen einf\u00fcgen"},iespell:{download:"ieSpell konnte nicht gefunden werden. Wollen Sie es installieren?","iespell_desc":"Rechtschreibpr\u00fcfung"},advhr:{"advhr_desc":"Trennlinie","delta_height":"","delta_width":""},emotions:{"emotions_desc":"Smilies","delta_height":"","delta_width":""},searchreplace:{"replace_desc":"Suchen/Ersetzen","search_desc":"Suchen","delta_width":"","delta_height":""},advimage:{"image_desc":"Bild einf\u00fcgen/ver\u00e4ndern","delta_width":"","delta_height":""},advlink:{"link_desc":"Link einf\u00fcgen/ver\u00e4ndern","delta_height":"","delta_width":""},xhtmlxtras:{"attribs_desc":"Attribute einf\u00fcgen/bearbeiten","ins_desc":"Eingef\u00fcgter Text","del_desc":"Entfernter Text","acronym_desc":"Akronym","abbr_desc":"Abk\u00fcrzung","cite_desc":"Quellenangabe","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"CSS-Styles bearbeiten","delta_height":"","delta_width":""},paste:{"plaintext_mode":"Einf\u00fcgemodus ist nun \"Nur Text\". Erneut klicken stellt den Normalmodus wieder her.","plaintext_mode_sticky":"Einf\u00fcgemodus ist nun \"Nur Text\". Erneut klicken (oder das Einf\u00fcgen aus der Zwischenablage) stellt den Normalmodus wieder her.","selectall_desc":"Alles ausw\u00e4hlen","paste_word_desc":"Mit Formatierungen (aus Word) einf\u00fcgen","paste_text_desc":"Als einfachen Text einf\u00fcgen"},"paste_dlg":{"word_title":"Dr\u00fccken Sie auf Ihrer Tastatur Strg+V, um den Text einzuf\u00fcgen.","text_linebreaks":"Zeilenumbr\u00fcche beibehalten","text_title":"Dr\u00fccken Sie auf Ihrer Tastatur Strg+V, um den Text einzuf\u00fcgen."},table:{"cellprops_delta_width":"150",cell:"Zelle",col:"Spalte",row:"Zeile",del:"Tabelle l\u00f6schen","copy_row_desc":"Zeile kopieren","cut_row_desc":"Zeile ausschneiden","paste_row_after_desc":"Zeile unterhalb aus der Zwischenablage einf\u00fcgen","paste_row_before_desc":"Zeile oberhalb aus der Zwischenablage einf\u00fcgen","props_desc":"Eigenschaften der Tabelle","cell_desc":"Eigenschaften der Zelle","row_desc":"Eigenschaften der Zeile","merge_cells_desc":"Zellen verbinden","split_cells_desc":"Verbundene Zellen trennen","delete_col_desc":"Spalte l\u00f6schen","col_after_desc":"Spalte rechts einf\u00fcgen","col_before_desc":"Spalte links einf\u00fcgen","delete_row_desc":"Zeile l\u00f6schen","row_after_desc":"Zeile unterhalb einf\u00fcgen","row_before_desc":"Zeile oberhalb einf\u00fcgen",desc:"Tabelle erstellen/bearbeiten","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"Wenn Sie den Inhalt wiederherstellen, gehen die aktuellen Daten im Editor verloren.\n\nSind sie sicher, dass Sie den Inhalt wiederherstellen m\u00f6chten?","restore_content":"Automatisch gespeicherten Inhalt wiederherstellen.","unload_msg":"Ihre \u00c4nderungen werden verloren gehen, wenn Sie die Seite verlassen."},fullscreen:{desc:"Vollbildschirm"},media:{edit:"Multimediaeinbettung bearbeiten",desc:"Multimedia einbetten/bearbeiten","delta_height":"","delta_width":""},fullpage:{desc:"Dokument-Eigenschaften","delta_width":"","delta_height":""},template:{desc:"Inhalt aus Vorlage einf\u00fcgen"},visualchars:{desc:"Sichtbarkeit der Steuerzeichen an/aus"},spellchecker:{desc:"Rechtschreibpr\u00fcfung an/aus",menu:"Einstellungen der Rechtschreibpr\u00fcfung","ignore_word":"Wort ignorieren","ignore_words":"Alle ignorieren",langs:"Sprachen",wait:"Bitte warten...",sug:"Vorschl\u00e4ge","no_sug":"Keine Vorschl\u00e4ge","no_mpell":"Keine Rechtschreibfehler gefunden.","learn_word":"Zum W\u00f6rterbuch hinzuf\u00fcgen"},pagebreak:{desc:"Seitenumbruch einf\u00fcgen"},advlist:{types:"Typen",def:"Standard","lower_alpha":"a. b. c.","lower_greek":"1. 2. 3.","lower_roman":"i. ii. iii.","upper_alpha":"A. B. C.","upper_roman":"I. II. III.",circle:"Kreis",disc:"Punkt",square:"Quadrat"},colors:{"333300":"Dunkeloliv","993300":"Orange","000000":"Schwarz","003300":"Dunkelgr\u00fcn","003366":"Dunkles himmelblau","000080":"Marineblau","333399":"Indigoblau","333333":"Sehr dunkelgrau","800000":"Kastanienbraun",FF6600:"Orange","808000":"Oliv","008000":"Gr\u00fcn","008080":"Blaugr\u00fcn","0000FF":"Blau","666699":"Graublau","808080":"Grau",FF0000:"Rot",FF9900:"Bernsteinfarben","99CC00":"Gelbgr\u00fcn","339966":"Meergr\u00fcn","33CCCC":"T\u00fcrkis","3366FF":"K\u00f6nigsblau","800080":"Violett","999999":"Mittelgrau",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Gelb","00FF00":"Hellgr\u00fcn","00FFFF":"Aquamarinblau","00CCFF":"Himmelblau","993366":"Braun",C0C0C0:"Silber",FF99CC:"Rosa",FFCC99:"Pfirsichfarben",FFFF99:"Hellgelb",CCFFCC:"Blassgr\u00fcn",CCFFFF:"Blasst\u00fcrkis","99CCFF":"Helles himmelblau",CC99FF:"Pflaumenblau",FFFFFF:"Wei\u00df"},aria:{"rich_text_area":"Rich Text Bereich"},wordcount:{words:"W\u00f6rter: "}}}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/langs/en.js b/src/core/static/js/tiny_mce/langs/en.js new file mode 100755 index 0000000..16d7a93 --- /dev/null +++ b/src/core/static/js/tiny_mce/langs/en.js @@ -0,0 +1 @@ +tinyMCE.addI18n({en:{common:{"more_colors":"More Colors...","invalid_data":"Error: Invalid values entered, these are marked in red.","popup_blocked":"Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.","clipboard_no_support":"Currently not supported by your browser, use keyboard shortcuts instead.","clipboard_msg":"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?","not_set":"-- Not Set --","class_name":"Class",browse:"Browse",close:"Close",cancel:"Cancel",update:"Update",insert:"Insert",apply:"Apply","edit_confirm":"Do you want to use the WYSIWYG mode for this textarea?","invalid_data_number":"{#field} must be a number","invalid_data_min":"{#field} must be a number greater than {#min}","invalid_data_size":"{#field} must be a number or percentage",value:"(value)"},contextmenu:{full:"Full",right:"Right",center:"Center",left:"Left",align:"Alignment"},insertdatetime:{"day_short":"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun","day_long":"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday","months_short":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","months_long":"January,February,March,April,May,June,July,August,September,October,November,December","inserttime_desc":"Insert Time","insertdate_desc":"Insert Date","time_fmt":"%H:%M:%S","date_fmt":"%Y-%m-%d"},print:{"print_desc":"Print"},preview:{"preview_desc":"Preview"},directionality:{"rtl_desc":"Direction Right to Left","ltr_desc":"Direction Left to Right"},layer:{content:"New layer...","absolute_desc":"Toggle Absolute Positioning","backward_desc":"Move Backward","forward_desc":"Move Forward","insertlayer_desc":"Insert New Layer"},save:{"save_desc":"Save","cancel_desc":"Cancel All Changes"},nonbreaking:{"nonbreaking_desc":"Insert Non-Breaking Space Character"},iespell:{download:"ieSpell not detected. Do you want to install it now?","iespell_desc":"Check Spelling"},advhr:{"delta_height":"","delta_width":"","advhr_desc":"Insert Horizontal Line"},emotions:{"delta_height":"","delta_width":"","emotions_desc":"Emotions"},searchreplace:{"replace_desc":"Find/Replace","delta_width":"","delta_height":"","search_desc":"Find"},advimage:{"delta_width":"","image_desc":"Insert/Edit Image","delta_height":""},advlink:{"delta_height":"","delta_width":"","link_desc":"Insert/Edit Link"},xhtmlxtras:{"attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":"","attribs_desc":"Insert/Edit Attributes","ins_desc":"Insertion","del_desc":"Deletion","acronym_desc":"Acronym","abbr_desc":"Abbreviation","cite_desc":"Citation"},style:{"delta_height":"","delta_width":"",desc:"Edit CSS Style"},paste:{"plaintext_mode":"Paste is now in plain text mode. Click again to toggle back to regular paste mode.","plaintext_mode_sticky":"Paste is now in plain text mode. Click again to toggle back to regular paste mode. After you paste something you will be returned to regular paste mode.","selectall_desc":"Select All","paste_word_desc":"Paste from Word","paste_text_desc":"Paste as Plain Text"},"paste_dlg":{"word_title":"Use Ctrl+V on your keyboard to paste the text into the window.","text_linebreaks":"Keep Linebreaks","text_title":"Use Ctrl+V on your keyboard to paste the text into the window."},table:{"merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":"",cell:"Cell",col:"Column",row:"Row",del:"Delete Table","copy_row_desc":"Copy Table Row","cut_row_desc":"Cut Table Row","paste_row_after_desc":"Paste Table Row After","paste_row_before_desc":"Paste Table Row Before","props_desc":"Table Properties","cell_desc":"Table Cell Properties","row_desc":"Table Row Properties","merge_cells_desc":"Merge Table Cells","split_cells_desc":"Split Merged Table Cells","delete_col_desc":"Delete Column","col_after_desc":"Insert Column After","col_before_desc":"Insert Column Before","delete_row_desc":"Delete Row","row_after_desc":"Insert Row After","row_before_desc":"Insert Row Before",desc:"Insert/Edit Table"},autosave:{"warning_message":"If you restore the saved content, you will lose all the content that is currently in the editor.\n\nAre you sure you want to restore the saved content?","restore_content":"Restore auto-saved content.","unload_msg":"The changes you made will be lost if you navigate away from this page."},fullscreen:{desc:"Toggle Full Screen Mode"},media:{"delta_height":"","delta_width":"",edit:"Edit Embedded Media",desc:"Insert/Edit Embedded Media"},fullpage:{desc:"Document Properties","delta_width":"","delta_height":""},template:{desc:"Insert Predefined Template Content"},visualchars:{desc:"Show/Hide Visual Control Characters"},spellchecker:{desc:"Toggle Spell Checker",menu:"Spell Checker Settings","ignore_word":"Ignore Word","ignore_words":"Ignore All",langs:"Languages",wait:"Please wait...",sug:"Suggestions","no_sug":"No Suggestions","no_mpell":"No misspellings found.","learn_word":"Learn word"},pagebreak:{desc:"Insert Page Break for Printing"},advlist:{types:"Types",def:"Default","lower_alpha":"Lower Alpha","lower_greek":"Lower Greek","lower_roman":"Lower Roman","upper_alpha":"Upper Alpha","upper_roman":"Upper Roman",circle:"Circle",disc:"Disc",square:"Square"},colors:{"333300":"Dark olive","993300":"Burnt orange","000000":"Black","003300":"Dark green","003366":"Dark azure","000080":"Navy Blue","333399":"Indigo","333333":"Very dark gray","800000":"Maroon",FF6600:"Orange","808000":"Olive","008000":"Green","008080":"Teal","0000FF":"Blue","666699":"Grayish blue","808080":"Gray",FF0000:"Red",FF9900:"Amber","99CC00":"Yellow green","339966":"Sea green","33CCCC":"Turquoise","3366FF":"Royal blue","800080":"Purple","999999":"Medium gray",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Yellow","00FF00":"Lime","00FFFF":"Aqua","00CCFF":"Sky blue","993366":"Brown",C0C0C0:"Silver",FF99CC:"Pink",FFCC99:"Peach",FFFF99:"Light yellow",CCFFCC:"Pale green",CCFFFF:"Pale cyan","99CCFF":"Light sky blue",CC99FF:"Plum",FFFFFF:"White"},aria:{"rich_text_area":"Rich Text Area"},wordcount:{words:"Words:"}}}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/langs/fr.js b/src/core/static/js/tiny_mce/langs/fr.js new file mode 100755 index 0000000..7042832 --- /dev/null +++ b/src/core/static/js/tiny_mce/langs/fr.js @@ -0,0 +1 @@ +tinyMCE.addI18n({fr:{common:{"more_colors":"Plus de couleurs","invalid_data":"Erreur : saisie de valeurs incorrectes. Elles sont mises en \u00e9vidence en rouge.","popup_blocked":"D\u00e9sol\u00e9, nous avons d\u00e9tect\u00e9 que votre bloqueur de popup a bloqu\u00e9 une fen\u00eatre dont l\'application a besoin. Vous devez d\u00e9sactiver votre bloqueur de popup pour pouvoir utiliser cet outil.","clipboard_no_support":"Actuellement non support\u00e9 par votre navigateur.\n Veuillez utiliser les raccourcis clavier \u00e0 la place.","clipboard_msg":"Les fonctions Copier/Couper/Coller ne sont pas valables sur Mozilla et Firefox.\nSouhaitez-vous avoir plus d\'informations sur ce sujet ?","not_set":"-- non d\u00e9fini --","class_name":"Classe",browse:"parcourir",close:"Fermer",cancel:"Annuler",update:"Mettre \u00e0 jour",insert:"Ins\u00e9rer",apply:"Appliquer","edit_confirm":"Souhaitez-vous utiliser le mode WYSIWYG pour cette zone de texte ?","invalid_data_number":"{#field} doit \u00eatre un nombre","invalid_data_min":"{#field} doit \u00eatre un nombre plus grand que {#min}","invalid_data_size":"{#field} doit \u00eatre un nombre ou un pourcentage",value:"(value)"},contextmenu:{full:"Justifi\u00e9",right:"Droite",center:"Centr\u00e9",left:"Gauche",align:"Alignement"},insertdatetime:{"day_short":"Dim,Lun,Mar,Mer,Jeu,Ven,Sam,Dim","day_long":"Dimanche,Lundi,Mardi,Mercredi,Jeudi,Vendredi,Samedi,Dimanche","months_short":"Jan,F\u00e9v,Mar,Avr,Mai,Juin,Juil,Ao\u00fbt,Sep,Oct,Nov,D\u00e9c","months_long":"Janvier,F\u00e9vrier,Mars,Avril,Mai,Juin,Juillet,Ao\u00fbt,Septembre,Octobre,Novembre,D\u00e9cembre","inserttime_desc":"Ins\u00e9rer l\'heure","insertdate_desc":"Ins\u00e9rer la date","time_fmt":"%H:%M:%S","date_fmt":"%d-%m-%Y"},print:{"print_desc":"Imprimer"},preview:{"preview_desc":"Pr\u00e9visualiser"},directionality:{"rtl_desc":"\u00c9criture de droite \u00e0 gauche","ltr_desc":"\u00c9criture de gauche \u00e0 droite"},layer:{content:"Nouvelle couche\u2026","absolute_desc":"Activer le positionnement absolu","backward_desc":"D\u00e9placer vers l\'arri\u00e8re","forward_desc":"D\u00e9placer vers l\'avant","insertlayer_desc":"Ins\u00e9rer une nouvelle couche"},save:{"save_desc":"Enregistrer","cancel_desc":"Annuler toutes les modifications"},nonbreaking:{"nonbreaking_desc":"Ins\u00e9rer une espace ins\u00e9cable"},iespell:{download:"ieSpell n\'est pas install\u00e9. Souhaitez-vous l\'installer maintenant ?","iespell_desc":"Lancer le v\u00e9rificateur d\'orthographe"},advhr:{"delta_height":"Ecart de hauteur","delta_width":"Ecart de largeur","advhr_desc":"Ins\u00e9rer un trait horizontal"},emotions:{"emotions_desc":"\u00c9motic\u00f4nes","delta_height":"","delta_width":""},searchreplace:{"replace_desc":"Rechercher / remplacer","search_desc":"Rechercher","delta_width":"","delta_height":""},advimage:{"image_desc":"Ins\u00e9rer / \u00e9diter une image","delta_width":"","delta_height":""},advlink:{"link_desc":"Ins\u00e9rer / \u00e9diter un lien","delta_height":"","delta_width":""},xhtmlxtras:{"attribs_desc":"Ins\u00e9rer / \u00e9diter les attributs","ins_desc":"Ins\u00e9r\u00e9","del_desc":"Barr\u00e9","acronym_desc":"Acronyme","abbr_desc":"Abr\u00e9viation","cite_desc":"Citation","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"\u00c9diter la feuille de style (CSS)","delta_height":"","delta_width":""},paste:{"plaintext_mode":"Le collage est actuellement en mode texte non format\u00e9. Cliquez \u00e0 nouveau pour revenir en mode de collage ordinaire.","plaintext_mode_sticky":"Le collage est actuellement en mode texte non format\u00e9. Cliquez \u00e0 nouveau pour revenir en mode de collage ordinaire. Apr\u00e8s avoir coll\u00e9 quelque chose, vous retournerez en mode de collage ordinaire.","selectall_desc":"Tout s\u00e9lectionner","paste_word_desc":"Coller un texte cr\u00e9\u00e9 sous Word","paste_text_desc":"Coller comme texte brut"},"paste_dlg":{"word_title":"Utilisez CTRL+V sur votre clavier pour coller le texte dans la fen\u00eatre.","text_linebreaks":"Conserver les retours \u00e0 la ligne","text_title":"Utilisez CTRL+V sur votre clavier pour coller le texte dans la fen\u00eatre."},table:{cell:"Cellule",col:"Colonne",row:"Ligne",del:"Effacer le tableau","copy_row_desc":"Copier la ligne","cut_row_desc":"Couper la ligne","paste_row_after_desc":"Coller la ligne apr\u00e8s","paste_row_before_desc":"Coller la ligne avant","props_desc":"Propri\u00e9t\u00e9s du tableau","cell_desc":"Propri\u00e9t\u00e9s de la cellule","row_desc":"Propri\u00e9t\u00e9s de la ligne","merge_cells_desc":"Fusionner les cellules","split_cells_desc":"Scinder les cellules fusionn\u00e9es","delete_col_desc":"Effacer la colonne","col_after_desc":"Ins\u00e9rer une colonne apr\u00e8s","col_before_desc":"Ins\u00e9rer une colonne avant","delete_row_desc":"Effacer la ligne","row_after_desc":"Ins\u00e9rer une ligne apr\u00e8s","row_before_desc":"Ins\u00e9rer une ligne avant",desc:"Ins\u00e9rer un nouveau tableau","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"Si vous restaurez le contenu sauv\u00e9, vous perdrez le contenu qui est actuellement dans l\'\u00e9diteur.\n\n\u00cates-vous s\u00fbr de vouloir restaurer le contenu sauv\u00e9 ?","restore_content":"Restaurer le contenu auto-sauvegard\u00e9.","unload_msg":"Les modifications apport\u00e9es seront perdues si vous quittez cette page."},fullscreen:{desc:"Passer en mode plein \u00e9cran"},media:{edit:"\u00c9diter un m\u00e9dia incorpor\u00e9",desc:"Ins\u00e9rer / \u00e9diter un m\u00e9dia incorpor\u00e9","delta_height":"","delta_width":""},fullpage:{desc:"Propri\u00e9t\u00e9s du document","delta_width":"","delta_height":""},template:{desc:"Ins\u00e9rer un mod\u00e8le pr\u00e9d\u00e9fini."},visualchars:{desc:"Activer les caract\u00e8res de mise en page."},spellchecker:{desc:"Activer le v\u00e9rificateur d\'orthographe",menu:"Param\u00e8tres du v\u00e9rificateur d\'orthographe","ignore_word":"Ignorer le mot","ignore_words":"Tout ignorer",langs:"Langues",wait:"Veuillez patienter\u2026",sug:"Suggestions","no_sug":"Aucune suggestion","no_mpell":"Aucune erreur trouv\u00e9e.","learn_word":"Apprendre le mot"},pagebreak:{desc:"Ins\u00e9rer un saut de page."},advlist:{types:"Types",def:"D\u00e9faut","lower_alpha":"Alpha minuscule","lower_greek":"Grec minuscule","lower_roman":"Romain minuscule","upper_alpha":"Alpha majuscule","upper_roman":"Romain majuscule",circle:"Cercle",disc:"Disque",square:"Carr\u00e9"},colors:{"333300":"Dark olive","993300":"Burnt orange","000000":"Black","003300":"Dark green","003366":"Dark azure","000080":"Navy Blue","333399":"Indigo","333333":"Very dark gray","800000":"Maroon",FF6600:"Orange","808000":"Olive","008000":"Green","008080":"Teal","0000FF":"Blue","666699":"Grayish blue","808080":"Gray",FF0000:"Red",FF9900:"Amber","99CC00":"Yellow green","339966":"Sea green","33CCCC":"Turquoise","3366FF":"Royal blue","800080":"Purple","999999":"Medium gray",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Yellow","00FF00":"Lime","00FFFF":"Aqua","00CCFF":"Sky blue","993366":"Brown",C0C0C0:"Silver",FF99CC:"Pink",FFCC99:"Peach",FFFF99:"Light yellow",CCFFCC:"Pale green",CCFFFF:"Pale cyan","99CCFF":"Light sky blue",CC99FF:"Plum",FFFFFF:"White"},aria:{"rich_text_area":"Texte riche"},wordcount:{words:"Mots:"}}}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/langs/it.js b/src/core/static/js/tiny_mce/langs/it.js new file mode 100755 index 0000000..59acac9 --- /dev/null +++ b/src/core/static/js/tiny_mce/langs/it.js @@ -0,0 +1 @@ +tinyMCE.addI18n({it:{common:{"more_colors":"Colori aggiuntivi","invalid_data":"Errore: valori inseriti non validi, sono marcati in rosso.","popup_blocked":"Spiacente, ma il blocco popup ha disabilitato una finestra che fornisce funzionalit\u00e0 dell\'applicazione. Si deve disabilitare il blocco popup per questo sito per poter utlizzare appieno questo strumento.","clipboard_no_support":"Attualmente non supportato dal browser in uso, usare le scorciatoie da tastiera.","clipboard_msg":"Copia/Taglia/Incolla non \u00e8 disponibile in Mozilla e Firefox.\nSi desidera avere maggiori informazioni su questo problema?","not_set":"-- Non impostato --","class_name":"Classe",browse:"Sfoglia",close:"Chiudi",cancel:"Annulla",update:"Aggiorna",insert:"Inserisci",apply:"Applica","edit_confirm":"Usare la modalit\u00e0 WYSIWYG per questa textarea?","invalid_data_number":"{#field} deve essere un numero","invalid_data_min":"{#field} deve essere un numero maggiore di {#min}","invalid_data_size":"{#field} deve essere un numero o una percentuale",value:"(value)"},contextmenu:{full:"Giustifica",right:"Allinea a destra",center:"Centra",left:"Allinea a sinistra",align:"Allineamento"},insertdatetime:{"day_short":"Dom,Lun,Mar,Mer,Gio,Ven,Sab,Dom","day_long":"Domenica,Luned\u00ec,Marted\u00ec,Mercoled\u00ec,Gioved\u00ec,Venerd\u00ec,Sabato,Domenica","months_short":"Gen,Feb,Mar,Apr,Mag,Giu,Lug,Ago,Set,Ott,Nov,Dic","months_long":"Gennaio,Febbraio,Marzo,Aprile,Maggio,Giugno,Luglio,Agosto,Settembre,Ottobre,Novembre,Dicembre","inserttime_desc":"Inserisci ora","insertdate_desc":"Inserisci data","time_fmt":"%H:%M:%S","date_fmt":"%Y-%m-%d"},print:{"print_desc":"Stampa"},preview:{"preview_desc":"Anteprima"},directionality:{"rtl_desc":"Direzione da destra a sinistra","ltr_desc":"Direzione da sinistra a destra"},layer:{content:"Nuovo layer...","absolute_desc":"Attiva/Disattiva posizionamento assoluto","backward_desc":"Porta in sfondo","forward_desc":"Porta in rilievo","insertlayer_desc":"Inserisci nuovo layer"},save:{"save_desc":"Salva","cancel_desc":"Cancella tutte le modifiche"},nonbreaking:{"nonbreaking_desc":"Inserisci uno spazio"},iespell:{download:"ieSpell non rilevato. Installarlo ora?","iespell_desc":"Esegui controllo ortografico"},advhr:{"advhr_desc":"Riga orizzontale","delta_height":"","delta_width":""},emotions:{"emotions_desc":"Faccine","delta_height":"","delta_width":""},searchreplace:{"replace_desc":"Trova/Sostituisci","search_desc":"Trova","delta_width":"","delta_height":""},advimage:{"image_desc":"Inserisci/modifica immagine","delta_width":"","delta_height":""},advlink:{"link_desc":"Inserisci/modifica collegamento","delta_height":"","delta_width":""},xhtmlxtras:{"attribs_desc":"Inserisci/modifica attributi","ins_desc":"Inserimento","del_desc":"Cancellamento","acronym_desc":"Acronimo","abbr_desc":"Abbreviazione","cite_desc":"Citazione","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"Modifica stile CSS","delta_height":"","delta_width":""},paste:{"plaintext_mode":"Incolla adesso e in modalit\u00e0 testo. Clicca nuovamente per tornare alla modalit\u00e0 normale.","plaintext_mode_sticky":"Incolla adesso e in modalit\u00e0 testo. Clicca nuovamente per tornare alla modalit\u00e0 normale. Dopo che avrai incollato qualcosa tornerai alla modalit\u00e0 normale","selectall_desc":"Seleziona tutto","paste_word_desc":"Incolla da Word","paste_text_desc":"Incolla come testo semplice"},"paste_dlg":{"word_title":"Premere CTRL+V sulla tastiera per incollare il testo nella finestra.","text_linebreaks":"Mantieni interruzioni di riga","text_title":"Premere CTRL+V sulla tastiera per incollare il testo nella finestra."},table:{cell:"Cella",col:"Colonna",row:"Riga",del:"Elimina tabella","copy_row_desc":"Copia riga","cut_row_desc":"Taglia riga","paste_row_after_desc":"Incolla riga dopo","paste_row_before_desc":"Incolla riga prima","props_desc":"Propriet\u00e0 tabella","cell_desc":"Propriet\u00e0 cella","row_desc":"Propriet\u00e0 riga","merge_cells_desc":"Unisci celle","split_cells_desc":"Separa celle","delete_col_desc":"Elimina colonna","col_after_desc":"Inserisci colonna dopo","col_before_desc":"Inserisci colonna prima","delete_row_desc":"Elimina riga","row_after_desc":"Inserisci riga dopo","row_before_desc":"Inserisci riga prima",desc:"Inserisci una nuova tabella","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"Se ripristini i dati salvati automaticamente perderai i dati attuali dell\'editor\n\nSei sicuro di voler ripristinare i dati?.","restore_content":"Ripristina i dati salvati automaticamente","unload_msg":"I cambiamenti effettuati saranno persi se si abbandona la pagina corrente."},fullscreen:{desc:"Attiva/disattiva modalit\u00e0 a tutto schermo"},media:{edit:"Modifica file multimediale",desc:"Inserisci/modifica file multimediale","delta_height":"","delta_width":""},fullpage:{desc:"Propriet\u00e0 Documento","delta_width":"","delta_height":""},template:{desc:"Inserisci contenuto da modello predefinito"},visualchars:{desc:"Attiva/disattiva caratteri di controllo visuale."},spellchecker:{desc:"Attiva/disattiva controllo ortografico",menu:"Impostazioni controllo ortografico","ignore_word":"Ignora parola","ignore_words":"Ignora tutto",langs:"Lingue",wait:"Attendere prego...",sug:"Suggerimenti","no_sug":"Nessun suggerimento","no_mpell":"Nessun errore rilevato.","learn_word":"Learn word"},pagebreak:{desc:"Inserisci intterruzione di pagina."},advlist:{types:"Tipi",def:"Default","lower_alpha":"Minuscolo alfanumerico","lower_greek":"Minuscolo lettera greca","lower_roman":"Minuscolo lettere romane","upper_alpha":"Maiuscolo alfanumerico","upper_roman":"Maiuscolo lettere romane",circle:"Cerchio",disc:"Punto",square:"Quadrato"},colors:{"333300":"Dark olive","993300":"Burnt orange","000000":"Black","003300":"Dark green","003366":"Dark azure","000080":"Navy Blue","333399":"Indigo","333333":"Very dark gray","800000":"Maroon",FF6600:"Orange","808000":"Olive","008000":"Green","008080":"Teal","0000FF":"Blue","666699":"Grayish blue","808080":"Gray",FF0000:"Red",FF9900:"Amber","99CC00":"Yellow green","339966":"Sea green","33CCCC":"Turquoise","3366FF":"Royal blue","800080":"Purple","999999":"Medium gray",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Yellow","00FF00":"Lime","00FFFF":"Aqua","00CCFF":"Sky blue","993366":"Brown",C0C0C0:"Silver",FF99CC:"Pink",FFCC99:"Peach",FFFF99:"Light yellow",CCFFCC:"Pale green",CCFFFF:"Pale cyan","99CCFF":"Light sky blue",CC99FF:"Plum",FFFFFF:"White"},aria:{"rich_text_area":"Area testo formattato"},wordcount:{words:"Parole:"}}}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/license.txt b/src/core/static/js/tiny_mce/license.txt new file mode 100644 index 0000000..60d6d4c --- /dev/null +++ b/src/core/static/js/tiny_mce/license.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_image/css/GLZ_image.css b/src/core/static/js/tiny_mce/plugins/GLZ_image/css/GLZ_image.css new file mode 100755 index 0000000..ae54921 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_image/css/GLZ_image.css @@ -0,0 +1,72 @@ +/* CSS file for advimage plugin popup */ + +.mceImageList { + width: 280px; +} + +.mceActionPanel { + margin-top: 7px; +} + +.alignPreview { + border: 1px solid black; + width: 100px; + height: 100px; + overflow: hidden; + padding: 5px; +} + +.checkbox { + border: 0px; +} + +.panel_wrapper div.current { + height: 305px; +} + +#align, #classlist { + width: 120px; +} + +#width, #height { + vertical-align: middle; + width: 40px; + text-align: center; +} + +#vspace, #hspace, #border { + vertical-align: middle; + width: 30px; + text-align: center; +} + +#cssClass { + width: 140px; + margin-right: 5px; +} + +input { + width: 100%; +} + +#id, #dir, #lang, #usemap, #longdesc { + width: 200px; +} + +#general_panel { + width: 370px; +} + +#picker { + width: 100%; + height: 450px; +} + + +.multifieldset { + margin-bottom: 4px; +} + +body { + margin: 6px; +} diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_image/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/GLZ_image/editor_plugin.js new file mode 100755 index 0000000..eb6b754 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_image/editor_plugin.js @@ -0,0 +1,67 @@ +/** + * TinyMCE Image plugin, based on TinyMCE-advimage plugin by Moxiecode Systems AB. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + * + * @copyright Copyright (c) 2005, 2006 Daniele Ugoletti + * @link http://www.glizy.org Glizy Project + * @license http://www.gnu.org/copyleft/lesser.html GNU LESSER GENERAL PUBLIC LICENSE + * @package glizy + * @subpackage javascript + * @author Daniele Ugoletti <daniele.ugoletti@glizy.com>, Giorgio Braga <giorgio@justattributes.com> + * @category javascript + * @since Glizy v 0.01 + * @version $Rev: 81 $ + * @modifiedby $LastChangedBy: ugoletti $ + * @lastmodified $Date: 2007-01-14 08:59:55 +0100 (dom, 14 gen 2007) $ + */ + + +(function() { + tinymce.PluginManager.requireLangPack('GLZ_image'); + + tinymce.create('tinymce.plugins.GlizyImagePlugin', { + init : function(ed, url) { + this.editor = ed; + + // Register commands + ed.addCommand('mceGlzImage', function() { + // Internal image object like a flash placeholder + if (ed.dom.getAttrib(ed.selection.getNode(), 'class', '').indexOf('mceItem') != -1) + return; + + ed.windowManager.open({ + file : url + '/image.htm', + width : $(window).width() - 80 + parseInt(ed.getLang('GLZ_image.delta_width', 0)), + height : 530 + parseInt(ed.getLang('GLZ_image.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('image', { + title : 'advimage.image_desc', + cmd : 'mceGlzImage' + }); + }, + + getInfo : function() { + return { + longname : 'Glizy Image (based on TinyMCE-advimage plugin by Moxiecode Systems AB)', + author : 'Daniele Ugoletti', + authorurl : 'http://www.glizy.org', + infourl : 'http://www.glizy.org', + version : '1.2.0' + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('GLZ_image', tinymce.plugins.GlizyImagePlugin); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_image/image.htm b/src/core/static/js/tiny_mce/plugins/GLZ_image/image.htm new file mode 100755 index 0000000..7c0078a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_image/image.htm @@ -0,0 +1,115 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#GLZ_image.window_title}</title> + <script language="javascript" src="../../../../../../static/jquery/jquery-1.8.3.min.js"></script> + <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script> + <script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script> + <script language="javascript" type="text/javascript" src="jscripts/functions.js"></script> + <link href="css/GLZ_image.css" rel="stylesheet" type="text/css" /> +</head> +<body id="GLZ_image" style="display: none"> + <form onsubmit="insertAction();return false;" action="#"> + <input type="hidden" id="src" name="src" value = ""/> + <input type="hidden" id="imgid" value = ""/> + <input type="hidden" id="orw" value = ""/> + <input type="hidden" id="orh" value = ""/> + <table style="background-color:#FFFFFF;border:1px solid #919B9C;" width="100%"> + <tr> + <td style="padding-left:4px;" valign="top"> + <table border="0" cellpadding="0" cellspacing="0" width="100%" height="334"> + <tr><td valign="top"> + <fieldset> + <legend>{#GLZ_image.general}</legend> + <table border="0" cellpadding="2" cellspacing="0"> + <tr> + <td rowspan="5" width="100" align="center" valign="middle"><img src="images/sample.gif" alt="{#GLZ_image.sample_image}" id="thumbnail" width="100" height="100"/></td> + <td width="100%"><label id="altlabel" for="alt">{#GLZ_image.alt}</label></td> + <tr> + <tr><td><input id="alt" name="alt" type="text" value="" /></td></tr> + <tr><td><label id="titlelabel" for="title">{#GLZ_image.title}</label></td></tr> + <tr><td><input id="title" name="title" type="text" value="" /></td></tr> + </table> + </fieldset> + </td></tr> + <tr><td valign="bottom"> + <fieldset> + <legend>{#GLZ_image.tab_appearance}</legend> + <table border="0" cellpadding="2" cellspacing="0"> + <tr> + <td><label id="alignlabel" for="align">{#GLZ_image.align}</label></td> + <td><select id="align" name="align" onchange="changeAppearance();"> + <option value="">{#GLZ_image.align_default}</option> + <option value="left">{#GLZ_image.align_left}</option> + <option value="right">{#GLZ_image.align_right}</option> + </select> + </td> + <td rowspan="6" valign="top"> + <div class="alignPreview"> + <img id="alignSampleImg" src="images/sample.gif" alt="{#GLZ_image.example_img}" /> + Lorem ipsum, Dolor sit amet, consectetuer adipiscing loreum ipsum edipiscing elit, sed diam + nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.Loreum ipsum + edipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam + erat volutpat. + </div> + </td> + </tr> + <tr> + <td><label id="widthlabel" for="width">{#GLZ_image.dimensions}</label></td> + <td nowrap="nowrap"> + <input name="width" type="text" id="width" value="" size="5" maxlength="5" onchange="changeHeight();" /> x + <input name="height" type="text" id="height" value="" size="5" maxlength="5" onchange="changeWidth();" /> px + </td> + </tr> + <tr> + <td width="1%"><label id="vspacelabel" for="vspace">{#GLZ_image.vspace}</label></td> + <td><input name="vspace" type="text" id="vspace" value="" size="3" maxlength="3" onchange="changeAppearance();updateStyle();" /> + </td> + </tr> + <tr> + <td><label id="hspacelabel" for="hspace">{#GLZ_image.hspace}</label></td> + <td><input name="hspace" type="text" id="hspace" value="" size="3" maxlength="3" onchange="changeAppearance();updateStyle();" /></td> + </tr> + <tr> + <td><label id="borderlabel" for="border">{#GLZ_image.border}</label></td> + <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="changeAppearance();updateStyle();" /></td> + </tr> + <tr> + <td><label id="classlabel" for="classlist">{#class_name}</label></td> + <td colspan="2"><input name="cssclass" type="text" id="cssclass" value="" onchange="changeAppearance();updateStyle();"/><select id="cssClassList" onchange="changeCssClass(this);"> + <option value="">-</option> + <option value="left">{#GLZ_image.css_left}</option> + <option value="right">{#GLZ_image.css_right}</option> + <option value="center">{#GLZ_image.css_center}</option> + <option value="left noBorder">{#GLZ_image.css_left_noborder}</option> + <option value="right noBorder">{#GLZ_image.css_right_noborder}</option> + <option value="center noBorder">{#GLZ_image.css_center_noborder}</option> + </select></td> + </tr> + <tr> + <td><label id="stylelabel" for="style">{#GLZ_image.style}</label></td> + <td colspan="2"><input id="style" name="style" type="text" value="" onchange="styleUpdated();" /></td> + </tr> + </table> + </fieldset> + </td></tr> + </table> + </td> + <td style="padding:4px;width:100%;"> + <fieldset> + <iframe id="picker" frameborder="0"></iframe> + </fieldset> + </td> + </tr> + </table> + <div class="mceActionPanel"> + <div style="float: left"> + <input type="button" id="insert" name="insert" value="{#insert}" onclick="insertAction();" /> + </div> + <div style="float: right"> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="cancelAction();" /> + </div> + </div> + </form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_image/images/sample.gif b/src/core/static/js/tiny_mce/plugins/GLZ_image/images/sample.gif new file mode 100755 index 0000000000000000000000000000000000000000..53bf6890b507741c10910c9e2217ad8247b98e8d GIT binary patch literal 1624 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 WE}n@{k&&Vq!n33@nsG^i002Ao7W&ix literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_image/jscripts/functions.js b/src/core/static/js/tiny_mce/plugins/GLZ_image/jscripts/functions.js new file mode 100644 index 0000000..3d43719 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_image/jscripts/functions.js @@ -0,0 +1,318 @@ +/** + * TinyMCE Image plugin, based on TinyMCE-advimage plugin by Moxiecode Systems AB. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + * + * @copyright Copyright (c) 2005, 2006 Daniele Ugoletti + * @link http://www.glizy.org Glizy Project + * @license http://www.gnu.org/copyleft/lesser.html GNU LESSER GENERAL PUBLIC LICENSE + * @package glizy + * @subpackage javascript + * @author Daniele Ugoletti <daniele.ugoletti@glizy.com>, Giorgio Braga <giorgio@justattributes.com> + * @category javascript + * @since Glizy v 0.01 + * @version $Rev: 328 $ + * @modifiedby $LastChangedBy: ugoletti $ + * @lastmodified $Date: 2011-01-24 17:46:02 +0100 (lun, 24 gen 2011) $ + */ + + +function convertURL(url, node, on_save) { + return url; +} +function trimSize(size) { + return size.replace(/([0-9\.]+)px|(%|in|cm|mm|em|ex|pt|pc)/, '$1$2'); +} + +function init() { + var f = document.forms[0], formObj = f.elements, ed = tinyMCEPopup.editor, dom = ed.dom, elm = ed.selection.getNode(); + var $picker = $("#picker"); + $picker.attr("src", parent.Glizy.tinyMCE_options.urls.imagePickerTiny).load(function(){ + jQuery( "img.js-glizyMediaPicker", $picker.contents().get(0)).click( function(){ + $img = jQuery( this ); + update( $img.data( "id" ), $img.data( "fileName" ), $img.attr( "title" ), $img.attr( "src" ), $img.data( "width" ), $img.data( "height" ) ); + }); + }); + + tinyMCEPopup.resizeToInnerSize(); + if (elm.nodeName == 'IMG') { + var src = dom.getAttrib(elm, 'src'); + src = convertURL(src, elm, true); + // Setup form data + var style = dom.getAttrib(elm, 'style'); + var search = src.split("?")[1]; + var els = search.split("&"); + formObj.imgid.value = els[0].split("=")[1]; + var tn = formObj.src.value = src; + formObj.alt.value = dom.getAttrib(elm, 'alt'); + formObj.title.value = dom.getAttrib(elm, 'title'); + var border = dom.getStyle(elm, 'border' ); + if (border!='') + { + formObj.border.value = trimSize(border.split(' ')[0]); + } + else + { + formObj.border.value = ''; + } + + var margin = getStyle(elm, 'margin'); + if (margin!='') + { + margin = margin.split(' '); + formObj.vspace.value = trimSize(margin[0]); + formObj.hspace.value = trimSize(margin[margin.length > 1 ? 1 : 0]); + } + else + { + formObj.vspace.value = ''; + formObj.hspace.value = ''; + } + + formObj.cssclass.value = dom.getAttrib(elm, 'class'); + var w = formObj.orw.value = formObj.width.value = trimSize(dom.getStyle(elm, 'width')); + var h = formObj.orh.value = formObj.height.value = trimSize(dom.getStyle(elm, 'height')); + formObj.style.value = style; ///dom.serializeStyle(style); + with (f.thumbnail) { + if (w>h) { + width = 100; + height = h/w*100; + } + else { + height = 100; + width = w/h*100; + } + src = tn.indexOf('http://')>-1 ? tn : parent.Glizy.tinyMCE_options.urls.root+tn; + } + + selectByValue(f, 'align', dom.getStyle(elm, 'float')); + + updateStyle(); + changeAppearance(); + } + + // // Check action + // if (elm != null && elm.nodeName == "IMG") + // action = "update"; + // + // formObj.insert.value = tinyMCE.getLang('lang_' + action, 'Insert', true); + // + // if (action == "update") { + // + // } +} + +function update(imgid,url,t,tn,w,h) { + var formObj = document.forms[0]; + formObj.imgid.value = imgid; + with (formObj) { + title.value = t; + alt.value = t; + width.value = orw.value = w; + height.value = orh.value = h; + with (thumbnail) { + if (w/h > 1) { + width = 100; + height = h/w*100; + } + else { + height = 100; + width = w/h*100; + } + src = parent.Glizy.tinyMCE_options.urls.root+tn; + } + } + updateStyle(); +} + +function setAttrib(elm, attrib, value) { + var ed = tinyMCEPopup.editor, dom = ed.dom; + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib]; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + if (value != "") { + dom.setAttrib(elm, attrib, value); + } else + elm.removeAttribute(attrib); +} + +function makeAttrib(attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib]; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + if (value == "") + return ""; + return ' ' + attrib + '="' + value + '"'; +} + +function insertAction() { + var ed = tinyMCEPopup.editor, dom = ed.dom; + var formObj = document.forms[0]; + tinyMCEPopup.restoreSelection(); + + // Fixes crash in Safari + if (tinymce.isWebKit) + ed.getWin().focus(); + + if (formObj.imgid.value) { + var src = parent.Glizy.tinyMCE_options.urls.imageResizer + .replace('#id#', formObj.imgid.value) + .replace('#w#', formObj.width.value) + .replace('#h#', formObj.height.value); + formObj.alt.value = formObj.alt.value || formObj.title.value; + src = convertURL(src, tinyMCE.imgElement); + + var elm = ed.selection.getNode(); + if (elm && elm.nodeName == 'IMG') { + setAttrib(elm, 'src', src); + setAttrib(elm, 'alt'); + setAttrib(elm, 'title'); + setAttrib(elm, 'style'); + setAttrib(elm, 'class', formObj.cssclass.value); + } else { + var html = "<img"; + + html += makeAttrib('src', src); + html += makeAttrib('alt'); + html += makeAttrib('title'); + html += makeAttrib('style'); + html += makeAttrib('class', formObj.cssclass.value); + html += " />"; + + ed.execCommand("mceInsertContent", false, html, {skip_undo : 1}); + ed.undoManager.add(); + } + } + + tinyMCEPopup.editor.execCommand('mceRepaint'); + tinyMCEPopup.editor.focus(); + tinyMCEPopup.close(); +} + +function cancelAction() { + tinyMCEPopup.close(); +} + +function changeAppearance() { + var formObj = document.forms[0]; + var img = document.getElementById('alignSampleImg'); + + if (img) { + img.align = formObj.align.value; + img.border = formObj.border.value; + img.hspace = formObj.hspace.value; + img.vspace = formObj.vspace.value; + updateStyle(); + } +} + +function changeCssClass(elm) { + if (elm.selectedIndex !=0) + { + var formObj = document.forms[0]; + formObj.cssclass.value = elm.value; + elm.selectedIndex = 0; + } +} + +function updateStyle() { + var ed = tinyMCEPopup.editor, dom = ed.dom; + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + if (ed.settings.inline_styles) { + st['width'] = formObj.width.value == '' ? '' : formObj.width.value + "px"; + st['height'] = formObj.height.value == '' ? '' : formObj.height.value + "px"; + st['border'] = formObj.border.value == '' ? '' : formObj.border.value + "px solid"; + if (formObj.vspace.value != '' || formObj.hspace.value != '') + { + st['margin'] = formObj.vspace.value == '' ? '0' : formObj.vspace.value + "px" + st['margin'] += formObj.hspace.value == '' ? ' 0' : ' '+formObj.hspace.value + "px"; + st['margin'] += formObj.vspace.value == '' ? ' 0' : ' '+formObj.vspace.value + "px" + st['margin'] += formObj.hspace.value == '' ? ' 0' : ' '+formObj.hspace.value + "px"; + } + else + { + delete st['margin']; + } + + } else { + st['width'] = st['height'] = st['border'] = null; + + if (st['margin-top'] == st['margin-bottom']) + st['margin-top'] = st['margin-bottom'] = null; + + if (st['margin-left'] == st['margin-right']) + st['margin-left'] = st['margin-right'] = null; + } + + st['float'] = formObj.align.value == '' ? '' : formObj.align.value; + + formObj.style.value = dom.serializeStyle(st); +} + +function styleUpdated() { + var ed = tinyMCEPopup.editor, dom = ed.dom; + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + if (st['width']) + formObj.width.value = st['width'].replace('px', ''); + + if (st['height']) + formObj.height.value = st['height'].replace('px', ''); + + if (st['margin-top'] && st['margin-top'] == st['margin-bottom']) + formObj.vspace.value = st['margin-top'].replace('px', ''); + + if (st['margin-left'] && st['margin-left'] == st['margin-right']) + formObj.hspace.value = st['margin-left'].replace('px', ''); + + if (st['border-width']) + formObj.border.value = st['border-width'].replace('px', ''); +} + +function changeHeight() { + var formObj = document.forms[0]; + + var temp = (formObj.width.value / formObj.orw.value) * formObj.orh.value; + formObj.height.value = temp.toFixed(0); + updateStyle(); +} + +function changeWidth() { + var formObj = document.forms[0]; + + var temp = (formObj.height.value / formObj.orh.value) * formObj.orw.value; + formObj.width.value = temp.toFixed(0); + updateStyle(); +} + +function getSelectValue(form_obj, field_name) { + var elm = form_obj.elements[field_name]; + + if (elm == null || elm.options == null) + return ""; + + return elm.options[elm.selectedIndex].value; +} + +tinyMCEPopup.onInit.add(init, null); diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_image/langs/en.js b/src/core/static/js/tiny_mce/plugins/GLZ_image/langs/en.js new file mode 100755 index 0000000..814c03f --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_image/langs/en.js @@ -0,0 +1,56 @@ +// UK lang variables + +tinyMCE.addI18n('en.GLZ_image',{ + window_title:"Insert/Edit Image", + tab_appearance : 'Appearance', + general : 'General', + title : 'Title', + style : 'Style', + example_img : 'Appearance&nbsp;preview&nbsp;image', + sample_image : 'image placeholder', + css_left : 'Left aligned', + css_right : 'Right aligned', + css_center : 'Center aligned', + css_left_noborder : 'Left aligned, no border', + css_right_noborder : 'Right aligned, no border', + css_center_noborder : 'Center aligned, no border', + align_default:"-- Default --", + "image_list":"Image List", + "align_right":"Right", + "align_left":"Left", + "align_textbottom":"Text Bottom", + "align_texttop":"Text Top", + "align_bottom":"Bottom", + "align_middle":"Middle", + "align_top":"Top", + "align_baseline":"Baseline", + align:"Alignment", + hspace:"Horizontal Space", + vspace:"Vertical Space", + dimensions:"Dimensions", + border:"Border",list:"Image List", + alt:"Image Description", + src:"Image URL", + "missing_alt":"Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.", + misc:"Miscellaneous", + mouseout:"For Mouse Out", + mouseover:"For Mouse Over", + "alt_image":"Alternative Image", + "swap_image":"Swap Image", + map:"Image Map", + id:"ID", + rtl:"Right to Left", + ltr:"Left to Right", + classes:"Classes", + "long_desc":"Long Description Link", + langcode:"Language Code", + langdir:"Language Direction", + "constrain_proportions":"Constrain Proportions", + preview:"Preview", + "tab_advanced":"Advanced", + "tab_appearance":"Appearance", + "tab_general":"General", + width:"Width", + height:"Height" +}); + diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_image/langs/it.js b/src/core/static/js/tiny_mce/plugins/GLZ_image/langs/it.js new file mode 100755 index 0000000..d028846 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_image/langs/it.js @@ -0,0 +1,57 @@ +// IT lang variables + +tinyMCE.addI18n('it.GLZ_image',{ + window_title:"Inserisci/modifica immagine", + tab_appearance : 'Aspetto', + general : 'Propriet&agrave&nbsp;generali', + style : 'Stile', + title : 'Titolo', + example_img : 'Immagine&nbsp;esemplificativa', + sample_image : 'Immagine&nbsp;esemplificativa', + css_left : 'Allineato a sinistra', + css_right : 'Allineato a destra', + css_center : 'Allineato al centro', + css_left_noborder : 'Allineato a sinistra, senza bordo', + css_right_noborder : 'Allineato a destra, senza bordo', + css_center_noborder : 'Allineato al centro, senza bordo', + align_default:"-- Non impostato --", + "image_list":"Lista immagini", + "align_right":"A destra", + "align_left":"A sinistra", + "align_textbottom":"In basso al testo", + "align_texttop":"In alto al testo", + "align_bottom":"In basso", + "align_middle":"In mezzo", + "align_top":"In alto", + "align_baseline":"Alla base", + align:"Allineamento", + hspace:"Spaziatura orizzontale", + vspace:"Spaziatura verticale", + dimensions:"Dimensioni", + border:"Bordo", + list:"Lista immagini", + alt:"Descrizione immagine", + src:"URL immagine", + "missing_alt":"Sicuro di continuare senza includere una descrizione dell\'immagine? Senza di essa l\'immagine pu\u00f2 non essere accessibile ad alcuni utenti con disabilit\u00e0, o per coloro che usano un browser testuale oppure che hanno disabilitato la visualizzazione delle immagini nel loro browser.", + misc:"Impostazioni varie", + mouseout:"quando mouse fuori", + mouseover:"quando mouse sopra", + "alt_image":"Immagine alternativa", + "swap_image":"Sostituisci immagine", + map:"Immagine come mappa", + id:"Id", + rtl:"Destra verso sinistra", + ltr:"Sinistra verso destra", + classes:"Classe", + style:"Stile", + "long_desc":"Descrizione del collegamento", + langcode:"codice lingua", + langdir:"Direzione testo", + "constrain_proportions":"Mantieni proporzioni", + preview:"Anteprima", + "tab_advanced":"Avanzate", + "tab_appearance":"Aspetto", + "tab_general":"Generale", + width:"Larghezza", + height:"Altezza" +}); diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_link/css/GLZ_link.css b/src/core/static/js/tiny_mce/plugins/GLZ_link/css/GLZ_link.css new file mode 100644 index 0000000..eb6d90a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_link/css/GLZ_link.css @@ -0,0 +1,41 @@ +/* CSS file for advimage plugin popup */ + +.mceActionPanel { + margin-top: 7px; +} + +.panel_wrapper { + border-top: 1px solid #919B9C; + width: 380px; +} + +#linkType, #linkUrl, #internalLink, #title, #target, #id, #style, #classlist, #rel, #rev, #tabindex, #accesskey, #cssclass { + width: 100%; +} + +#preview { + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 10px; + cursor: pointer; +} + +.multifieldset { + margin-bottom: 4px; +} + +#picker { + width: 100%; + height: 100%; +} + +#pickerPanel { + background-color: #FFF; + position: absolute; + left: 414px; + top: 8px; + width: 470px; + height: 466px; + display: none; + padding: 4px; + border: 1px solid #919B9C; +} diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_link/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/GLZ_link/editor_plugin.js new file mode 100644 index 0000000..40bc166 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_link/editor_plugin.js @@ -0,0 +1,77 @@ +/* SVN FILE: $Id: editor_plugin.js 162 2007-03-30 22:57:05Z ugoletti $ */ +/** + * TinyMCE Image plugin, based on TinyMCE-advlink plugin by Moxiecode Systems AB. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2006 Daniele Ugoletti <daniele@ugoletti.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + * + * @copyright Copyright (c) 2005, 2006 Daniele Ugoletti + * @link http://www.glizy.org Glizy Project + * @license http://www.gnu.org/copyleft/lesser.html GNU LESSER GENERAL PUBLIC LICENSE + * @package glizy + * @subpackage javascript + * @author Daniele Ugoletti <daniele@ugoletti.com>, Giorgio Braga <giorgio@justattributes.com> + * @category javascript + * @since Glizy v 0.01 + * @version $Rev: 162 $ + * @modifiedby $LastChangedBy: ugoletti $ + * @lastmodified $Date: 2007-03-31 00:57:05 +0200 (sab, 31 mar 2007) $ + */ + + +(function() { + tinymce.PluginManager.requireLangPack('GLZ_link'); + + tinymce.create('tinymce.plugins.GlizyLinkPlugin', { + init : function(ed, url) { + this.editor = ed; + + // Register commands + ed.addCommand('mceGlzLink', function() { + var se = ed.selection; + + // No selection and not in link + if (se.isCollapsed() && !ed.dom.getParent(se.getNode(), 'A')) + return; + + ed.windowManager.open({ + file : url + '/link.htm', + width : 420 + parseInt(ed.getLang('GLZ_link.delta_width', 0)), + height : 530 + parseInt(ed.getLang('GLZ_link.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('link', { + title : 'advlink.link_desc', + cmd : 'mceGlzLink' + }); + + ed.addShortcut('ctrl+k', 'advlink.link_desc', 'mceGLZ_link'); + + ed.onNodeChange.add(function(ed, cm, n, co) { + cm.setDisabled('link', co && n.nodeName != 'A'); + cm.setActive('link', n.nodeName == 'A' && !n.name); + }); + }, + + getInfo : function() { + return { + longname : 'Glizy link (based on TinyMCE-advlink plugin by Moxiecode Systems AB)', + author : 'Daniele Ugoletti', + authorurl : 'http://www.glizy.org', + infourl : 'http://www.glizy.org', + version : '1.2.0' + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('GLZ_link', tinymce.plugins.GlizyLinkPlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_link/jscripts/functions.js b/src/core/static/js/tiny_mce/plugins/GLZ_link/jscripts/functions.js new file mode 100644 index 0000000..5d4c666 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_link/jscripts/functions.js @@ -0,0 +1,400 @@ +/* SVN FILE: $Id: functions.js 298 2008-10-21 23:21:58Z ugoletti $ */ + +/** + * TinyMCE Image plugin, based on TinyMCE-advlink plugin by Moxiecode Systems AB. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2006 Daniele Ugoletti <daniele@ugoletti.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + * + * @copyright Copyright (c) 2005, 2006 Daniele Ugoletti + * @link http://www.glizy.org Glizy Project + * @license http://www.gnu.org/copyleft/lesser.html GNU LESSER GENERAL PUBLIC LICENSE + * @package glizy + * @subpackage javascript + * @author Daniele Ugoletti <daniele@ugoletti.com> + * @category javascript + * @since Glizy v 0.01 + * @version $Rev: 298 $ + * @modifiedby $LastChangedBy: ugoletti $ + * @lastmodified $Date: 2008-10-22 01:21:58 +0200 (mer, 22 ott 2008) $ + */ + + +/* Functions for the advlink plugin popup */ + +var currentSize = {w: 420, h: 530 }; + +function renderRepeaterLinks() { + var aSel = []; + aSel.push('<select id="repeaterLink" style="width: 100%; display:none">'); + aSel.push('<option value="">---</option>'); + parent.$("fieldset[data-anchor]").each(function(index, el){ + var $el = $(el); + var id = $(el).attr("id"); + var title = $el.find('legend').text(); + $el.find('div.GFERowContainer').each(function(index, el){ + var $el = $(el); + var itemCode = index+1; + var $elTitle = $el.find("[data-anchor-title]"); + var itemTitle = title + ": " + ($elTitle.length ? $elTitle.val() : itemCode); + var $elCode = $el.find("[data-anchor-code]"); + itemCode = id+":"+($elCode.length ? $elCode.val() : itemCode); + aSel.push('<option value="repeater:'+itemCode+'">'+itemTitle+'</option>'); + }); + }); + aSel.push('</select>'); + $('#internalLinks').append(aSel.join("")); +} + +function renderInternalLinks(callback) { + if ( parent.Glizy.tinyMCE_options.glz_links) { + var intLinks = parent.Glizy.tinyMCE_options.glz_links; + var aSel = ['<select id="internalLink" style="width: 100%" disabled="disabled">']; + aSel.push('<option value="">---</option>'); + for (var i=0;i<intLinks.internal.length;i++) { + aSel.push('<option value="'+intLinks.internal[i].link+'">'+intLinks.internal[i].name+'</option>'); + } + aSel.push('</select>'); + + $('#internalLinks').append(aSel.join("")); + callback() + } else { + loadInternalLinks(callback); + } +} + +function loadInternalLinks(callback) { + $.ajax(parent.Glizy.tinyMCE_options.urls.ajaxUrl + "&controllerName=org.glizycms.contents.controllers.tinymce.ajax.GlzLinkList", { + dataType: 'json', + success: function (intLinks) { + parent.Glizy.tinyMCE_options.glz_links = intLinks; + renderInternalLinks(callback); + } + }); +} + +function setLinkType(type) { + var wSize = {w: 420, h: 530 } + if (type=="1") + { + document.getElementById("protocol").disabled = "disabled"; + document.getElementById("linkUrl").disabled = "disabled"; + document.getElementById("preview").disabled = "disabled"; + document.getElementById("internalLink").disabled = ""; + document.getElementById("repeaterLink").style.display = "none"; + document.getElementById("pickerPanel").style.display = "none"; + } + else if (type=="2") + { + document.getElementById("protocol").disabled = ""; + document.getElementById("linkUrl").disabled = ""; + document.getElementById("preview").disabled = ""; + //document.getElementById("internalLink").disabled = "disabled"; + document.getElementById("repeaterLink").style.display = "none"; + document.getElementById("pickerPanel").style.display = "none"; + } + else if (type=="3") + { + var $picker = $("#picker"); + $picker.attr("src", parent.Glizy.tinyMCE_options.urls.mediaPicker).load(function(){ + jQuery( "img.js-glizyMediaPicker", $picker.contents().get(0)).click( function(){ + $img = jQuery( this ); + update( $img.data( "id" ), $img.attr( "title" )); + }); + }); + + document.getElementById("pickerPanel").style.display = "block"; + document.getElementById("linkUrl").disabled = "disabled"; + document.getElementById("internalLink").disabled = "disabled"; + document.getElementById("repeaterLink").style.display = "none"; + document.getElementById("protocol").disabled = "disabled"; + wSize = {w: $(parent.window).width() - 80, h: 530 } + $('#pickerPanel').width(wSize.w-430); + } + else if (type=="4") + { + document.getElementById("protocol").disabled = "disabled"; + document.getElementById("linkUrl").disabled = ""; + document.getElementById("preview").disabled = "disabled"; + document.getElementById("internalLink").disabled = "disabled"; + document.getElementById("repeaterLink").style.display = "none"; + document.getElementById("pickerPanel").style.display = "none"; + } + else if (type=="5") + { + document.getElementById("protocol").disabled = "disabled"; + document.getElementById("linkUrl").disabled = "disabled"; + document.getElementById("preview").disabled = "disabled"; + document.getElementById("internalLink").style.display = "none"; + document.getElementById("glossaryLinks").style.display = "inline"; + document.getElementById("pickerPanel").style.display = "none"; + } + else if (type=="6") + { + document.getElementById("protocol").disabled = "disabled"; + document.getElementById("linkUrl").disabled = ""; + document.getElementById("preview").disabled = "disabled"; + document.getElementById("internalLink").disabled = "disabled"; + document.getElementById("repeaterLink").style.display = "none"; + document.getElementById("pickerPanel").style.display = "none"; + } + else if (type=="7") + { + document.getElementById("protocol").disabled = "disabled"; + document.getElementById("linkUrl").disabled = "disabled"; + document.getElementById("preview").disabled = "disabled"; + document.getElementById("internalLink").style.display = "none"; + document.getElementById("repeaterLink").style.display = "inline"; + document.getElementById("pickerPanel").style.display = "none"; + } + + + resizeMe( wSize ); +} + +function resizeMe( newSize ) { + var winID = tinyMCEPopup.id; + var wm = tinyMCEPopup.editor.windowManager; + + wm.resizeBy(newSize.w - currentSize.w, newSize.h - currentSize.h, winID); + var left = parseInt( tinymce.DOM.getStyle( winID, 'left' ).replace( 'px', '' ) ); + tinymce.DOM.setStyle( winID, 'left', ( left - (newSize.w - currentSize.w) / 2 ) + 'px' ); + currentSize = newSize; +} + +function previewLink() { + var url = document.getElementById("protocol").value+document.getElementById("linkUrl").value; + if (url) try {window.open(url,"urlTest","")} catch(err) {}; +} + +function init() { + tinyMCEPopup.resizeToInnerSize(); + renderRepeaterLinks(); + var formObj = document.forms[0]; + var inst = tinyMCEPopup.editor; + var elm = inst.selection.getNode(); + var action = "insert"; + var linkType = 0; + + elm = inst.dom.getParent(elm, "A"); + if (elm != null && elm.nodeName == "A") + action = "update"; + + formObj.insert.value = tinyMCEPopup.getLang(action, 'Insert', true); + + if (action == "update") { + var href = inst.dom.getAttrib(elm, 'href'); + href = convertURL(href, elm, true); + + // Setup form data + + var protocol = 'http://'; + if (href.indexOf("internal:")==0) + { + linkType = 1; + setFormValue('linkUrl', ''); + } + else if (href.indexOf("media:")==0) + { + linkType = 3; + var mediaInfo = href.split(':'); + setFormValue('linkUrl', mediaInfo[2]); + setFormValue('mediaId', mediaInfo[1]); + setFormValue('mediaTitle', mediaInfo[2]); + } + else if (href.indexOf("#")==0) + { + linkType = 4; + setFormValue('linkUrl', href); + } + else if (href.indexOf("repeater:")==0) + { + linkType = 7; + setFormValue('linkUrl', ''); + setFormValue('repeaterLink', href); + } + else + { + var regExp = new RegExp("(http://|https://|ftp://|mailto:)(.*)", "gi"); + linkType = href.match( regExp ) ? 2 : 6 ; + if ( linkType == 2 ) + { + protocol = href.replace(regExp, "$1"); + setFormValue('linkUrl', href.replace(protocol,"")); + } + else + { + setFormValue('linkUrl', href ); + } + } + + + + setFormValue('linkType', String(linkType)); + + setFormValue('protocol', protocol); + // setFormValue('internalLink', linkType==1 ? href:""); + // setLinkType(String(linkType)); + setFormValue('title', inst.dom.getAttrib(elm, 'title')); + setFormValue('id', inst.dom.getAttrib(elm, 'id')); + setFormValue('style', inst.dom.getAttrib(elm, 'style')); + setFormValue('cssclass', inst.dom.getAttrib(elm, 'class')); + setFormValue('dir', inst.dom.getAttrib(elm, 'dir')); + setFormValue('hreflang', inst.dom.getAttrib(elm, 'hreflang')); + setFormValue('lang', inst.dom.getAttrib(elm, 'lang')); + setFormValue('charset', inst.dom.getAttrib(elm, 'charset')); + document.forms[0].elements['relExternal'].checked = tinymce.DOM.getAttrib(elm, 'rel') == "external"; + setFormValue('tabindex', inst.dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : "")); + setFormValue('accesskey', inst.dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : "")); + } + + var href = linkType==1 ? href:"" + var callback = function() { + setFormValue('internalLink', linkType==1 ? href:""); + setLinkType(String(linkType)); + } + + renderInternalLinks(callback); + window.focus(); +} + +function setFormValue(name, value) { + document.forms[0].elements[name].value = value; +} + + + +function convertURL(url, node, on_save) { + return url; + //return eval("tinyMCEPopup.windowOpener." + tinyMCE.settings['urlconverter_callback'] + "(url, node, on_save);"); +} + +function setAttrib(elm, attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib.toLowerCase()]; + var dom = tinyMCEPopup.editor.dom; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + // Clean up the style + if (attrib == 'style') + value = dom.serializeStyle(dom.parseStyle(value), 'a'); + + dom.setAttrib(elm, attrib, value); +} + +function insertAction() { + var inst = tinyMCEPopup.editor; + var elm, elementArray, i; + + elm = inst.selection.getNode(); + elm = inst.dom.getParent(elm, "A"); + + tinyMCEPopup.execCommand("mceBeginUndoLevel"); + + // Create new anchor elements + if (elm == null) { + inst.getDoc().execCommand("unlink", false, null); + tinyMCEPopup.execCommand("CreateLink", false, "#mce_temp_url#", {skip_undo : 1}); + + elementArray = tinymce.grep(inst.dom.select("a"), function(n) {return inst.dom.getAttrib(n, 'href') == '#mce_temp_url#';}); + for (i=0; i<elementArray.length; i++) + setAllAttribs(elm = elementArray[i]); + } else + setAllAttribs(elm); + + // Don't move caret if selection was image + if (elm && (elm.childNodes.length != 1 || elm.firstChild.nodeName != 'IMG')) { + inst.focus(); + inst.selection.select(elm); + inst.selection.collapse(0); + tinyMCEPopup.storeSelection(); + } + + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); +} + + + +function setAllAttribs(elm) { + var formObj = document.forms[0]; + var linkUrlObj = document.getElementById("linkUrl"); + var href; + switch (formObj.linkType.value) { + case "1": + href = formObj.internalLink.value; + break; + case "2": + href = formObj.protocol.value+linkUrlObj.value; + break; + case "3": + href = 'media:'+formObj.mediaId.value+":"+formObj.mediaTitle.value; + break; + case "4": + href = (linkUrlObj.value.indexOf('#')!=0 ? '#' : '')+linkUrlObj.value; + break; + case "6": + href = linkUrlObj.value; + break; + case "7": + href = formObj.repeaterLink.value; + break; + } + + if (href) { + href = convertURL(href, elm); + setAttrib(elm, 'href', href); + setAttrib(elm, 'title'); + setAttrib(elm, 'id'); + setAttrib(elm, 'style'); + setAttrib(elm, 'class', formObj.cssclass.value); + setAttrib(elm, 'rel', formObj.elements['relExternal'].checked ? "external" : "" ); + setAttrib(elm, 'charset'); + setAttrib(elm, 'hreflang'); + setAttrib(elm, 'dir'); + setAttrib(elm, 'lang'); + setAttrib(elm, 'tabindex'); + setAttrib(elm, 'accesskey'); + + // Refresh in old MSIE + if (tinyMCE.isMSIE5) + elm.outerHTML = elm.outerHTML; + } + else { + setAttrib(elm, 'href', null); + } +} + + +function getSelectValue(form_obj, field_name) { + var elm = form_obj.elements[field_name]; + + if (elm == null || elm.options == null) + return ""; + + return elm.options[elm.selectedIndex].value; +} + + +function update(i,t) { + var linkUrlObj = document.getElementById("linkUrl"); + var formObj = document.forms[0]; + with (formObj) { + mediaId.value = i; + mediaTitle.value = t; + title.value = t; + } + linkUrlObj.value = t; +} + + +tinyMCEPopup.onInit.add(init); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_link/langs/en.js b/src/core/static/js/tiny_mce/plugins/GLZ_link/langs/en.js new file mode 100644 index 0000000..053af3b --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_link/langs/en.js @@ -0,0 +1,34 @@ +// UK lang variables + +tinyMCE.addI18n('en.GLZ_link',{ + window_title:"Insert/edit link", + general_legend: 'General properties', + link_type: 'Link type', + internal_link: 'Internal link', + relative_link: 'Relative link', + external_link: 'External link', + media_link: 'Media link', + glossary_link: 'Link to glossary', + link_url: 'Link URL', + title: 'Title', + advanced_legend: 'Advanced properties', + id: 'Id', + style: 'Style', + classes: 'Class', + target_name : 'Target name', + langdir : 'Language direction', + target_langcode : 'Target language', + langcode : 'Language code', + encoding : 'Target character encoding', + mime : 'Target MIME type', + rel : 'Relationship page to target', + rev : 'Relationship target to page', + tabindex : 'Tabindex', + accesskey : 'Accesskey', + ltr : 'Left to right', + rtl : 'Right to left', + not_set: '-- Not set --', + preview: 'Preview', + anchor: 'Anchor', + open_external : 'Open in a new page' +}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_link/langs/it.js b/src/core/static/js/tiny_mce/plugins/GLZ_link/langs/it.js new file mode 100644 index 0000000..4f7932b --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_link/langs/it.js @@ -0,0 +1,34 @@ +// IT lang variables + +tinyMCE.addI18n('it.GLZ_link',{ + window_title:"Inserisci/modifica link", + general_legend: 'Propriet&agrave generali', + link_type: 'Tipo di link', + internal_link: 'Link interno', + relative_link: 'Link relativo', + external_link: 'Link esterno', + media_link: 'Link media', + glossary_link: 'Link a glossario', + link_url: 'Link URL', + title: 'Titolo', + advanced_legend: 'Propriet&agrave avanzate', + id : 'Id', + style: 'Stile', + classes : 'Classe', + target_name : 'Nome della destinazione', + langdir : 'Direzione del testo', + target_langcode : 'Codifica lingua destinazione', + langcode : 'Codifica lingua', + encoding : 'Codifica caratteri destinazione', + mime : 'Tipo MIME destinazione', + rel : 'Relazione pagina-destinazione', + rev : 'Relazione destinazione-pagina', + tabindex : 'Indice TAB', + accesskey : 'Tasto di accesso', + ltr : 'Da sinistra a destra', + rtl : 'Da destra a sinistra', + not_set: '-- Non impostato --', + preview: 'Anteprima', + anchor: 'Ancora', + open_external : 'Apri in una nuova pagina' +}); diff --git a/src/core/static/js/tiny_mce/plugins/GLZ_link/link.htm b/src/core/static/js/tiny_mce/plugins/GLZ_link/link.htm new file mode 100644 index 0000000..a095aea --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/GLZ_link/link.htm @@ -0,0 +1,121 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#GLZ_link.window_title}</title> + <script language="javascript" src="../../../../../../static/jquery/jquery-1.8.3.min.js"></script> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script> + <script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script> + <script language="javascript" type="text/javascript" src="jscripts/functions.js"></script> + <link href="css/GLZ_link.css" rel="stylesheet" type="text/css" /> +</head> +<body id="GLZ_link" style="display: none"> + <form onsubmit="insertAction();return false;" action="#"> + <input type="hidden" name="mediaId" value="" /> + <input type="hidden" name="mediaTitle" value="" /> + <div class="panel_wrapper" style="width: 380px;"> + <fieldset class="multifieldset"> + <legend>{#GLZ_link.general_legend}</legend> + <table border="0" cellpadding="4" cellspacing="0" width="100%"> + <tr> + <td nowrap="nowrap"><label id="linkTypeLabel" for="linkType">{#GLZ_link.link_type}</label></td> + <td colspan="3" width="100%"><select id="linkType" style="width:100%" onchange="setLinkType(this.value)"> + <option>---</option> + <option value="7">Link elementi della pagina</option> + <option value="1">{#GLZ_link.internal_link}</option> + <option value="6">{#GLZ_link.relative_link}</option> + <option value="2">{#GLZ_link.external_link}</option> + <option value="3">{#GLZ_link.media_link}</option> + <!--<option value="4">{#GLZ_link.anchor}</option>--> + </select></td> + </tr> + <tr> + <td nowrap="nowrap"><label id="linkUrlLabel" for="linkUrl">{#GLZ_link.link_url}</label></td> + <td width="1%"><select id="protocol"><option selected="selected" value="http://">http://</option><option value="https://">https://</option><option value="ftp://">ftp://</option><option value="mailto:">mailto:</option></select></td> + <td><input id="linkUrl" name="linkUrl" style="width:100%" type="text" value="" disabled="disabled" class="ja={suggest:{src:'../../../../../../../admin/ajax.php?pageId=AjaxCatalog&ajaxTarget=glossary',key:'t'}}"/></td> + <td width="1%"><input type="button" id="preview" value="{#GLZ_link.preview}" disabled="disabled" onclick="previewLink()"/></td> + </tr> + <tr> + <td nowrap><label id="internalLinkLabel" for="internalLink">{#GLZ_link.internal_link}</label></td> + <td colspan="3" id="internalLinks"> + </td> + </tr> + <tr> + <td nowrap="nowrap"><label id="titleLabel" for="title">{#GLZ_link.title}</label></td> + <td colspan="3"><input id="title" type="text" value="" /></td> + </tr> + <tr> + <td nowrap><label id="relLabel" for="rel">{#GLZ_link.open_external}</label></td> + <td> + <input type="checkbox" id="relExternal" name="nameExternal" value="1" /> + </td> + </tr> + </table> + </fieldset> + <fieldset> + <legend>{#GLZ_link.advanced_legend}</legend> + <table border="0" cellpadding="4" cellspacing="0" width="100%"> + <tr> + <td class="column1"><label id="idlabel" for="id">{#GLZ_link.id}</label></td> + <td><input id="id" name="id" type="text" value="" /></td> + </tr> + <tr> + <td nowrap="nowrap"><label id="styleLabel" for="style">{#GLZ_link.style}</label></td> + <td width="100%"><input id="style" type="text" value="" /></td> + </tr> + <tr id="classRow"> + <td nowrap="nowrap"><label id="classesLabel" for="classlist">{#GLZ_link.classes}</label></td> + <td><input id="cssclass" name="cssclass" type="text" value="" /></td> + </tr> + <tr> + <td class="column1"><label id="dirlabel" for="dir">{#GLZ_link.langdir}</label></td> + <td> + <select id="dir" name="dir"> + <option value="">{#GLZ_link.not_set}</option> + <option value="ltr">{#GLZ_link.ltr}</option> + <option value="rtl">{#GLZ_link.rtl}</option> + </select> + </td> + </tr> + + <tr> + <td><label id="hreflanglabel" for="hreflang">{#GLZ_link.target_langcode}</label></td> + <td><input type="text" id="hreflang" name="hreflang" value="" /></td> + </tr> + + <tr> + <td class="column1"><label id="langlabel" for="lang">{#GLZ_link.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" /> + </td> + </tr> + + <tr> + <td><label id="charsetlabel" for="charset">{#GLZ_link.encoding}</label></td> + <td><input type="text" id="charset" name="charset" value="" /></td> + </tr> + + <tr> + <td nowrap="nowrap"><label id="tabindexLabel" for="tabindex">{#GLZ_link.tabindex}</label></td> + <td><input id="tabindex" type="text" value="" /></td> + </tr> + <tr> + <td nowrap="nowrap"><label id="accesskeyLabel" for="accesskey">{#GLZ_link.accesskey}</label></td> + <td><input id="accesskey" type="text" value="" /></td> + </tr> + </table> + </fieldset> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" onclick="insertAction();" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + + <div id="pickerPanel"> + <iframe id="picker" frameborder="0"></iframe> + </div> + </form> +</body> +</html> + + diff --git a/src/core/static/js/tiny_mce/plugins/advhr/css/advhr.css b/src/core/static/js/tiny_mce/plugins/advhr/css/advhr.css new file mode 100644 index 0000000..0e22834 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advhr/css/advhr.css @@ -0,0 +1,5 @@ +input.radio {border:1px none #000; background:transparent; vertical-align:middle;} +.panel_wrapper div.current {height:80px;} +#width {width:50px; vertical-align:middle;} +#width2 {width:50px; vertical-align:middle;} +#size {width:100px;} diff --git a/src/core/static/js/tiny_mce/plugins/advhr/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/advhr/editor_plugin.js new file mode 100644 index 0000000..4d3b062 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advhr/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.AdvancedHRPlugin",{init:function(a,b){a.addCommand("mceAdvancedHr",function(){a.windowManager.open({file:b+"/rule.htm",width:250+parseInt(a.getLang("advhr.delta_width",0)),height:160+parseInt(a.getLang("advhr.delta_height",0)),inline:1},{plugin_url:b})});a.addButton("advhr",{title:"advhr.advhr_desc",cmd:"mceAdvancedHr"});a.onNodeChange.add(function(d,c,e){c.setActive("advhr",e.nodeName=="HR")});a.onClick.add(function(c,d){d=d.target;if(d.nodeName==="HR"){c.selection.select(d)}})},getInfo:function(){return{longname:"Advanced HR",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("advhr",tinymce.plugins.AdvancedHRPlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advhr/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/advhr/editor_plugin_src.js new file mode 100644 index 0000000..0c652d3 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advhr/editor_plugin_src.js @@ -0,0 +1,57 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.AdvancedHRPlugin', { + init : function(ed, url) { + // Register commands + ed.addCommand('mceAdvancedHr', function() { + ed.windowManager.open({ + file : url + '/rule.htm', + width : 250 + parseInt(ed.getLang('advhr.delta_width', 0)), + height : 160 + parseInt(ed.getLang('advhr.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('advhr', { + title : 'advhr.advhr_desc', + cmd : 'mceAdvancedHr' + }); + + ed.onNodeChange.add(function(ed, cm, n) { + cm.setActive('advhr', n.nodeName == 'HR'); + }); + + ed.onClick.add(function(ed, e) { + e = e.target; + + if (e.nodeName === 'HR') + ed.selection.select(e); + }); + }, + + getInfo : function() { + return { + longname : 'Advanced HR', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('advhr', tinymce.plugins.AdvancedHRPlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advhr/js/rule.js b/src/core/static/js/tiny_mce/plugins/advhr/js/rule.js new file mode 100644 index 0000000..b6cbd66 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advhr/js/rule.js @@ -0,0 +1,43 @@ +var AdvHRDialog = { + init : function(ed) { + var dom = ed.dom, f = document.forms[0], n = ed.selection.getNode(), w; + + w = dom.getAttrib(n, 'width'); + f.width.value = w ? parseInt(w) : (dom.getStyle('width') || ''); + f.size.value = dom.getAttrib(n, 'size') || parseInt(dom.getStyle('height')) || ''; + f.noshade.checked = !!dom.getAttrib(n, 'noshade') || !!dom.getStyle('border-width'); + selectByValue(f, 'width2', w.indexOf('%') != -1 ? '%' : 'px'); + }, + + update : function() { + var ed = tinyMCEPopup.editor, h, f = document.forms[0], st = ''; + + h = '<hr'; + + if (f.size.value) { + h += ' size="' + f.size.value + '"'; + st += ' height:' + f.size.value + 'px;'; + } + + if (f.width.value) { + h += ' width="' + f.width.value + (f.width2.value == '%' ? '%' : '') + '"'; + st += ' width:' + f.width.value + (f.width2.value == '%' ? '%' : 'px') + ';'; + } + + if (f.noshade.checked) { + h += ' noshade="noshade"'; + st += ' border-width: 1px; border-style: solid; border-color: #CCCCCC; color: #ffffff;'; + } + + if (ed.settings.inline_styles) + h += ' style="' + tinymce.trim(st) + '"'; + + h += ' />'; + + ed.execCommand("mceInsertContent", false, h); + tinyMCEPopup.close(); + } +}; + +tinyMCEPopup.requireLangPack(); +tinyMCEPopup.onInit.add(AdvHRDialog.init, AdvHRDialog); diff --git a/src/core/static/js/tiny_mce/plugins/advhr/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/advhr/langs/de_dlg.js new file mode 100755 index 0000000..7c5143e --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advhr/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.advhr_dlg',{size:"H\u00f6he",noshade:"Kein Schatten",width:"Breite",normal:"Normal",widthunits:"Einheiten"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advhr/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/advhr/langs/en_dlg.js new file mode 100755 index 0000000..0c3bf15 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advhr/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.advhr_dlg',{size:"Height",noshade:"No Shadow",width:"Width",normal:"Normal",widthunits:"Units"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advhr/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/advhr/langs/fr_dlg.js new file mode 100755 index 0000000..b4fcd2a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advhr/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.advhr_dlg',{size:"Hauteur",noshade:"Pas d\'ombre",width:"Largeur",normal:"Normal",widthunits:"Units"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advhr/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/advhr/langs/it_dlg.js new file mode 100755 index 0000000..f013f11 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advhr/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.advhr_dlg',{size:"Altezza",noshade:"Senza ombreggiatura",width:"Larghezza",normal:"Normal",widthunits:"Units"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advhr/rule.htm b/src/core/static/js/tiny_mce/plugins/advhr/rule.htm new file mode 100644 index 0000000..843e1f8 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advhr/rule.htm @@ -0,0 +1,58 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advhr.advhr_desc}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/rule.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <link href="css/advhr.css" rel="stylesheet" type="text/css" /> +</head> +<body role="application"> +<form onsubmit="AdvHRDialog.update();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advhr.advhr_desc}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr role="group" aria-labelledby="width_label"> + <td><label id="width_label" for="width">{#advhr_dlg.width}</label></td> + <td class="nowrap"> + <input id="width" name="width" type="text" value="" class="mceFocus" /> + <span style="display:none;" id="width_unit_label">{#advhr_dlg.widthunits}</span> + <select name="width2" id="width2" aria-labelledby="width_unit_label"> + <option value="">px</option> + <option value="%">%</option> + </select> + </td> + </tr> + <tr> + <td><label for="size">{#advhr_dlg.size}</label></td> + <td><select id="size" name="size"> + <option value="">{#advhr_dlg.normal}</option> + <option value="1">1</option> + <option value="2">2</option> + <option value="3">3</option> + <option value="4">4</option> + <option value="5">5</option> + </select></td> + </tr> + <tr> + <td><label for="noshade">{#advhr_dlg.noshade}</label></td> + <td><input type="checkbox" name="noshade" id="noshade" class="radio" /></td> + </tr> + </table> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/advimage/css/advimage.css b/src/core/static/js/tiny_mce/plugins/advimage/css/advimage.css new file mode 100644 index 0000000..0a6251a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advimage/css/advimage.css @@ -0,0 +1,13 @@ +#src_list, #over_list, #out_list {width:280px;} +.mceActionPanel {margin-top:7px;} +.alignPreview {border:1px solid #000; width:140px; height:140px; overflow:hidden; padding:5px;} +.checkbox {border:0;} +.panel_wrapper div.current {height:305px;} +#prev {margin:0; border:1px solid #000; width:428px; height:150px; overflow:auto;} +#align, #classlist {width:150px;} +#width, #height {vertical-align:middle; width:50px; text-align:center;} +#vspace, #hspace, #border {vertical-align:middle; width:30px; text-align:center;} +#class_list {width:180px;} +input {width: 280px;} +#constrain, #onmousemovecheck {width:auto;} +#id, #dir, #lang, #usemap, #longdesc {width:200px;} diff --git a/src/core/static/js/tiny_mce/plugins/advimage/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/advimage/editor_plugin.js new file mode 100644 index 0000000..d613a61 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advimage/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.AdvancedImagePlugin",{init:function(a,b){a.addCommand("mceAdvImage",function(){if(a.dom.getAttrib(a.selection.getNode(),"class","").indexOf("mceItem")!=-1){return}a.windowManager.open({file:b+"/image.htm",width:480+parseInt(a.getLang("advimage.delta_width",0)),height:385+parseInt(a.getLang("advimage.delta_height",0)),inline:1},{plugin_url:b})});a.addButton("image",{title:"advimage.image_desc",cmd:"mceAdvImage"})},getInfo:function(){return{longname:"Advanced image",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("advimage",tinymce.plugins.AdvancedImagePlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advimage/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/advimage/editor_plugin_src.js new file mode 100644 index 0000000..d2678cb --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advimage/editor_plugin_src.js @@ -0,0 +1,50 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.AdvancedImagePlugin', { + init : function(ed, url) { + // Register commands + ed.addCommand('mceAdvImage', function() { + // Internal image object like a flash placeholder + if (ed.dom.getAttrib(ed.selection.getNode(), 'class', '').indexOf('mceItem') != -1) + return; + + ed.windowManager.open({ + file : url + '/image.htm', + width : 480 + parseInt(ed.getLang('advimage.delta_width', 0)), + height : 385 + parseInt(ed.getLang('advimage.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('image', { + title : 'advimage.image_desc', + cmd : 'mceAdvImage' + }); + }, + + getInfo : function() { + return { + longname : 'Advanced image', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('advimage', tinymce.plugins.AdvancedImagePlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advimage/image.htm b/src/core/static/js/tiny_mce/plugins/advimage/image.htm new file mode 100644 index 0000000..ed16b3d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advimage/image.htm @@ -0,0 +1,235 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advimage_dlg.dialog_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/image.js"></script> + <link href="css/advimage.css" rel="stylesheet" type="text/css" /> +</head> +<body id="advimage" style="display: none" role="application" aria-labelledby="app_title"> + <span id="app_title" style="display:none">{#advimage_dlg.dialog_title}</span> + <form onsubmit="ImageDialog.insert();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advimage_dlg.tab_general}</a></span></li> + <li id="appearance_tab" aria-controls="appearance_panel"><span><a href="javascript:mcTabs.displayTab('appearance_tab','appearance_panel');" onmousedown="return false;">{#advimage_dlg.tab_appearance}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#advimage_dlg.tab_advanced}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#advimage_dlg.general}</legend> + + <table role="presentation" class="properties"> + <tr> + <td class="column1"><label id="srclabel" for="src">{#advimage_dlg.src}</label></td> + <td colspan="2"><table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input name="src" type="text" id="src" value="" class="mceFocus" onchange="ImageDialog.showPreviewImage(this.value);" aria-required="true" /></td> + <td id="srcbrowsercontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td><label for="src_list">{#advimage_dlg.image_list}</label></td> + <td><select id="src_list" name="src_list" onchange="document.getElementById('src').value=this.options[this.selectedIndex].value;document.getElementById('alt').value=this.options[this.selectedIndex].text;document.getElementById('title').value=this.options[this.selectedIndex].text;ImageDialog.showPreviewImage(this.options[this.selectedIndex].value);"><option value=""></option></select></td> + </tr> + <tr> + <td class="column1"><label id="altlabel" for="alt">{#advimage_dlg.alt}</label></td> + <td colspan="2"><input id="alt" name="alt" type="text" value="" /></td> + </tr> + <tr> + <td class="column1"><label id="titlelabel" for="title">{#advimage_dlg.title}</label></td> + <td colspan="2"><input id="title" name="title" type="text" value="" /></td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#advimage_dlg.preview}</legend> + <div id="prev"></div> + </fieldset> + </div> + + <div id="appearance_panel" class="panel"> + <fieldset> + <legend>{#advimage_dlg.tab_appearance}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label id="alignlabel" for="align">{#advimage_dlg.align}</label></td> + <td><select id="align" name="align" onchange="ImageDialog.updateStyle('align');ImageDialog.changeAppearance();"> + <option value="">{#not_set}</option> + <option value="baseline">{#advimage_dlg.align_baseline}</option> + <option value="top">{#advimage_dlg.align_top}</option> + <option value="middle">{#advimage_dlg.align_middle}</option> + <option value="bottom">{#advimage_dlg.align_bottom}</option> + <option value="text-top">{#advimage_dlg.align_texttop}</option> + <option value="text-bottom">{#advimage_dlg.align_textbottom}</option> + <option value="left">{#advimage_dlg.align_left}</option> + <option value="right">{#advimage_dlg.align_right}</option> + </select> + </td> + <td rowspan="6" valign="top"> + <div class="alignPreview"> + <img id="alignSampleImg" src="img/sample.gif" alt="{#advimage_dlg.example_img}" /> + Lorem ipsum, Dolor sit amet, consectetuer adipiscing loreum ipsum edipiscing elit, sed diam + nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.Loreum ipsum + edipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam + erat volutpat. + </div> + </td> + </tr> + + <tr role="group" aria-labelledby="widthlabel"> + <td class="column1"><label id="widthlabel" for="width">{#advimage_dlg.dimensions}</label></td> + <td class="nowrap"> + <span style="display:none" id="width_voiceLabel">{#advimage_dlg.width}</span> + <input name="width" type="text" id="width" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeHeight();" aria-labelledby="width_voiceLabel" /> x + <span style="display:none" id="height_voiceLabel">{#advimage_dlg.height}</span> + <input name="height" type="text" id="height" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeWidth();" aria-labelledby="height_voiceLabel" /> px + </td> + </tr> + + <tr> + <td>&nbsp;</td> + <td><table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="constrain" type="checkbox" name="constrain" class="checkbox" /></td> + <td><label id="constrainlabel" for="constrain">{#advimage_dlg.constrain_proportions}</label></td> + </tr> + </table></td> + </tr> + + <tr> + <td class="column1"><label id="vspacelabel" for="vspace">{#advimage_dlg.vspace}</label></td> + <td><input name="vspace" type="text" id="vspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" /> + </td> + </tr> + + <tr> + <td class="column1"><label id="hspacelabel" for="hspace">{#advimage_dlg.hspace}</label></td> + <td><input name="hspace" type="text" id="hspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" /></td> + </tr> + + <tr> + <td class="column1"><label id="borderlabel" for="border">{#advimage_dlg.border}</label></td> + <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" /></td> + </tr> + + <tr> + <td><label for="class_list">{#class_name}</label></td> + <td colspan="2"><select id="class_list" name="class_list" class="mceEditableSelect"><option value=""></option></select></td> + </tr> + + <tr> + <td class="column1"><label id="stylelabel" for="style">{#advimage_dlg.style}</label></td> + <td colspan="2"><input id="style" name="style" type="text" value="" onchange="ImageDialog.changeAppearance();" /></td> + </tr> + + <!-- <tr> + <td class="column1"><label id="classeslabel" for="classes">{#advimage_dlg.classes}</label></td> + <td colspan="2"><input id="classes" name="classes" type="text" value="" onchange="selectByValue(this.form,'classlist',this.value,true);" /></td> + </tr> --> + </table> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#advimage_dlg.swap_image}</legend> + + <input type="checkbox" id="onmousemovecheck" name="onmousemovecheck" class="checkbox" onclick="ImageDialog.setSwapImage(this.checked);" aria-controls="onmouseoversrc onmouseoutsrc" /> + <label id="onmousemovechecklabel" for="onmousemovecheck">{#advimage_dlg.alt_image}</label> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0" width="100%"> + <tr> + <td class="column1"><label id="onmouseoversrclabel" for="onmouseoversrc">{#advimage_dlg.mouseover}</label></td> + <td><table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="onmouseoversrc" name="onmouseoversrc" type="text" value="" /></td> + <td id="onmouseoversrccontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td><label for="over_list">{#advimage_dlg.image_list}</label></td> + <td><select id="over_list" name="over_list" onchange="document.getElementById('onmouseoversrc').value=this.options[this.selectedIndex].value;"><option value=""></option></select></td> + </tr> + <tr> + <td class="column1"><label id="onmouseoutsrclabel" for="onmouseoutsrc">{#advimage_dlg.mouseout}</label></td> + <td class="column2"><table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="onmouseoutsrc" name="onmouseoutsrc" type="text" value="" /></td> + <td id="onmouseoutsrccontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td><label for="out_list">{#advimage_dlg.image_list}</label></td> + <td><select id="out_list" name="out_list" onchange="document.getElementById('onmouseoutsrc').value=this.options[this.selectedIndex].value;"><option value=""></option></select></td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#advimage_dlg.misc}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label id="idlabel" for="id">{#advimage_dlg.id}</label></td> + <td><input id="id" name="id" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label id="dirlabel" for="dir">{#advimage_dlg.langdir}</label></td> + <td> + <select id="dir" name="dir" onchange="ImageDialog.changeAppearance();"> + <option value="">{#not_set}</option> + <option value="ltr">{#advimage_dlg.ltr}</option> + <option value="rtl">{#advimage_dlg.rtl}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label id="langlabel" for="lang">{#advimage_dlg.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" /> + </td> + </tr> + + <tr> + <td class="column1"><label id="usemaplabel" for="usemap">{#advimage_dlg.map}</label></td> + <td> + <input id="usemap" name="usemap" type="text" value="" /> + </td> + </tr> + + <tr> + <td class="column1"><label id="longdesclabel" for="longdesc">{#advimage_dlg.long_desc}</label></td> + <td><table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="longdesc" name="longdesc" type="text" value="" /></td> + <td id="longdesccontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/advimage/img/sample.gif b/src/core/static/js/tiny_mce/plugins/advimage/img/sample.gif new file mode 100644 index 0000000000000000000000000000000000000000..53bf6890b507741c10910c9e2217ad8247b98e8d GIT binary patch literal 1624 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 WE}n@{k&&Vq!n33@nsG^i002Ao7W&ix literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/advimage/js/image.js b/src/core/static/js/tiny_mce/plugins/advimage/js/image.js new file mode 100644 index 0000000..546b69c --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advimage/js/image.js @@ -0,0 +1,462 @@ +var ImageDialog = { + preInit : function() { + var url; + + tinyMCEPopup.requireLangPack(); + + if (url = tinyMCEPopup.getParam("external_image_list_url")) + document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>'); + }, + + init : function(ed) { + var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, dom = ed.dom, n = ed.selection.getNode(), fl = tinyMCEPopup.getParam('external_image_list', 'tinyMCEImageList'); + + tinyMCEPopup.resizeToInnerSize(); + this.fillClassList('class_list'); + this.fillFileList('src_list', fl); + this.fillFileList('over_list', fl); + this.fillFileList('out_list', fl); + TinyMCE_EditableSelects.init(); + + if (n.nodeName == 'IMG') { + nl.src.value = dom.getAttrib(n, 'src'); + nl.width.value = dom.getAttrib(n, 'width'); + nl.height.value = dom.getAttrib(n, 'height'); + nl.alt.value = dom.getAttrib(n, 'alt'); + nl.title.value = dom.getAttrib(n, 'title'); + nl.vspace.value = this.getAttrib(n, 'vspace'); + nl.hspace.value = this.getAttrib(n, 'hspace'); + nl.border.value = this.getAttrib(n, 'border'); + selectByValue(f, 'align', this.getAttrib(n, 'align')); + selectByValue(f, 'class_list', dom.getAttrib(n, 'class'), true, true); + nl.style.value = dom.getAttrib(n, 'style'); + nl.id.value = dom.getAttrib(n, 'id'); + nl.dir.value = dom.getAttrib(n, 'dir'); + nl.lang.value = dom.getAttrib(n, 'lang'); + nl.usemap.value = dom.getAttrib(n, 'usemap'); + nl.longdesc.value = dom.getAttrib(n, 'longdesc'); + nl.insert.value = ed.getLang('update'); + + if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseover'))) + nl.onmouseoversrc.value = dom.getAttrib(n, 'onmouseover').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1'); + + if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseout'))) + nl.onmouseoutsrc.value = dom.getAttrib(n, 'onmouseout').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1'); + + if (ed.settings.inline_styles) { + // Move attribs to styles + if (dom.getAttrib(n, 'align')) + this.updateStyle('align'); + + if (dom.getAttrib(n, 'hspace')) + this.updateStyle('hspace'); + + if (dom.getAttrib(n, 'border')) + this.updateStyle('border'); + + if (dom.getAttrib(n, 'vspace')) + this.updateStyle('vspace'); + } + } + + // Setup browse button + document.getElementById('srcbrowsercontainer').innerHTML = getBrowserHTML('srcbrowser','src','image','theme_advanced_image'); + if (isVisible('srcbrowser')) + document.getElementById('src').style.width = '260px'; + + // Setup browse button + document.getElementById('onmouseoversrccontainer').innerHTML = getBrowserHTML('overbrowser','onmouseoversrc','image','theme_advanced_image'); + if (isVisible('overbrowser')) + document.getElementById('onmouseoversrc').style.width = '260px'; + + // Setup browse button + document.getElementById('onmouseoutsrccontainer').innerHTML = getBrowserHTML('outbrowser','onmouseoutsrc','image','theme_advanced_image'); + if (isVisible('outbrowser')) + document.getElementById('onmouseoutsrc').style.width = '260px'; + + // If option enabled default contrain proportions to checked + if (ed.getParam("advimage_constrain_proportions", true)) + f.constrain.checked = true; + + // Check swap image if valid data + if (nl.onmouseoversrc.value || nl.onmouseoutsrc.value) + this.setSwapImage(true); + else + this.setSwapImage(false); + + this.changeAppearance(); + this.showPreviewImage(nl.src.value, 1); + }, + + insert : function(file, title) { + var ed = tinyMCEPopup.editor, t = this, f = document.forms[0]; + + if (f.src.value === '') { + if (ed.selection.getNode().nodeName == 'IMG') { + ed.dom.remove(ed.selection.getNode()); + ed.execCommand('mceRepaint'); + } + + tinyMCEPopup.close(); + return; + } + + if (tinyMCEPopup.getParam("accessibility_warnings", 1)) { + if (!f.alt.value) { + tinyMCEPopup.confirm(tinyMCEPopup.getLang('advimage_dlg.missing_alt'), function(s) { + if (s) + t.insertAndClose(); + }); + + return; + } + } + + t.insertAndClose(); + }, + + insertAndClose : function() { + var ed = tinyMCEPopup.editor, f = document.forms[0], nl = f.elements, v, args = {}, el; + + tinyMCEPopup.restoreSelection(); + + // Fixes crash in Safari + if (tinymce.isWebKit) + ed.getWin().focus(); + + if (!ed.settings.inline_styles) { + args = { + vspace : nl.vspace.value, + hspace : nl.hspace.value, + border : nl.border.value, + align : getSelectValue(f, 'align') + }; + } else { + // Remove deprecated values + args = { + vspace : '', + hspace : '', + border : '', + align : '' + }; + } + + tinymce.extend(args, { + src : nl.src.value.replace(/ /g, '%20'), + width : nl.width.value, + height : nl.height.value, + alt : nl.alt.value, + title : nl.title.value, + 'class' : getSelectValue(f, 'class_list'), + style : nl.style.value, + id : nl.id.value, + dir : nl.dir.value, + lang : nl.lang.value, + usemap : nl.usemap.value, + longdesc : nl.longdesc.value + }); + + args.onmouseover = args.onmouseout = ''; + + if (f.onmousemovecheck.checked) { + if (nl.onmouseoversrc.value) + args.onmouseover = "this.src='" + nl.onmouseoversrc.value + "';"; + + if (nl.onmouseoutsrc.value) + args.onmouseout = "this.src='" + nl.onmouseoutsrc.value + "';"; + } + + el = ed.selection.getNode(); + + if (el && el.nodeName == 'IMG') { + ed.dom.setAttribs(el, args); + } else { + tinymce.each(args, function(value, name) { + if (value === "") { + delete args[name]; + } + }); + + ed.execCommand('mceInsertContent', false, tinyMCEPopup.editor.dom.createHTML('img', args), {skip_undo : 1}); + ed.undoManager.add(); + } + + tinyMCEPopup.editor.execCommand('mceRepaint'); + tinyMCEPopup.editor.focus(); + tinyMCEPopup.close(); + }, + + getAttrib : function(e, at) { + var ed = tinyMCEPopup.editor, dom = ed.dom, v, v2; + + if (ed.settings.inline_styles) { + switch (at) { + case 'align': + if (v = dom.getStyle(e, 'float')) + return v; + + if (v = dom.getStyle(e, 'vertical-align')) + return v; + + break; + + case 'hspace': + v = dom.getStyle(e, 'margin-left') + v2 = dom.getStyle(e, 'margin-right'); + + if (v && v == v2) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + + case 'vspace': + v = dom.getStyle(e, 'margin-top') + v2 = dom.getStyle(e, 'margin-bottom'); + if (v && v == v2) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + + case 'border': + v = 0; + + tinymce.each(['top', 'right', 'bottom', 'left'], function(sv) { + sv = dom.getStyle(e, 'border-' + sv + '-width'); + + // False or not the same as prev + if (!sv || (sv != v && v !== 0)) { + v = 0; + return false; + } + + if (sv) + v = sv; + }); + + if (v) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + } + } + + if (v = dom.getAttrib(e, at)) + return v; + + return ''; + }, + + setSwapImage : function(st) { + var f = document.forms[0]; + + f.onmousemovecheck.checked = st; + setBrowserDisabled('overbrowser', !st); + setBrowserDisabled('outbrowser', !st); + + if (f.over_list) + f.over_list.disabled = !st; + + if (f.out_list) + f.out_list.disabled = !st; + + f.onmouseoversrc.disabled = !st; + f.onmouseoutsrc.disabled = !st; + }, + + fillClassList : function(id) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl; + + if (v = tinyMCEPopup.getParam('theme_advanced_styles')) { + cl = []; + + tinymce.each(v.split(';'), function(v) { + var p = v.split('='); + + cl.push({'title' : p[0], 'class' : p[1]}); + }); + } else + cl = tinyMCEPopup.editor.dom.getClasses(); + + if (cl.length > 0) { + lst.options.length = 0; + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), ''); + + tinymce.each(cl, function(o) { + lst.options[lst.options.length] = new Option(o.title || o['class'], o['class']); + }); + } else + dom.remove(dom.getParent(id, 'tr')); + }, + + fillFileList : function(id, l) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl; + + l = typeof(l) === 'function' ? l() : window[l]; + lst.options.length = 0; + + if (l && l.length > 0) { + lst.options[lst.options.length] = new Option('', ''); + + tinymce.each(l, function(o) { + lst.options[lst.options.length] = new Option(o[0], o[1]); + }); + } else + dom.remove(dom.getParent(id, 'tr')); + }, + + resetImageData : function() { + var f = document.forms[0]; + + f.elements.width.value = f.elements.height.value = ''; + }, + + updateImageData : function(img, st) { + var f = document.forms[0]; + + if (!st) { + f.elements.width.value = img.width; + f.elements.height.value = img.height; + } + + this.preloadImg = img; + }, + + changeAppearance : function() { + var ed = tinyMCEPopup.editor, f = document.forms[0], img = document.getElementById('alignSampleImg'); + + if (img) { + if (ed.getParam('inline_styles')) { + ed.dom.setAttrib(img, 'style', f.style.value); + } else { + img.align = f.align.value; + img.border = f.border.value; + img.hspace = f.hspace.value; + img.vspace = f.vspace.value; + } + } + }, + + changeHeight : function() { + var f = document.forms[0], tp, t = this; + + if (!f.constrain.checked || !t.preloadImg) { + return; + } + + if (f.width.value == "" || f.height.value == "") + return; + + tp = (parseInt(f.width.value) / parseInt(t.preloadImg.width)) * t.preloadImg.height; + f.height.value = tp.toFixed(0); + }, + + changeWidth : function() { + var f = document.forms[0], tp, t = this; + + if (!f.constrain.checked || !t.preloadImg) { + return; + } + + if (f.width.value == "" || f.height.value == "") + return; + + tp = (parseInt(f.height.value) / parseInt(t.preloadImg.height)) * t.preloadImg.width; + f.width.value = tp.toFixed(0); + }, + + updateStyle : function(ty) { + var dom = tinyMCEPopup.dom, b, bStyle, bColor, v, isIE = tinymce.isIE, f = document.forms[0], img = dom.create('img', {style : dom.get('style').value}); + + if (tinyMCEPopup.editor.settings.inline_styles) { + // Handle align + if (ty == 'align') { + dom.setStyle(img, 'float', ''); + dom.setStyle(img, 'vertical-align', ''); + + v = getSelectValue(f, 'align'); + if (v) { + if (v == 'left' || v == 'right') + dom.setStyle(img, 'float', v); + else + img.style.verticalAlign = v; + } + } + + // Handle border + if (ty == 'border') { + b = img.style.border ? img.style.border.split(' ') : []; + bStyle = dom.getStyle(img, 'border-style'); + bColor = dom.getStyle(img, 'border-color'); + + dom.setStyle(img, 'border', ''); + + v = f.border.value; + if (v || v == '0') { + if (v == '0') + img.style.border = isIE ? '0' : '0 none none'; + else { + if (b.length == 3 && b[isIE ? 2 : 1]) + bStyle = b[isIE ? 2 : 1]; + else if (!bStyle || bStyle == 'none') + bStyle = 'solid'; + if (b.length == 3 && b[isIE ? 0 : 2]) + bColor = b[isIE ? 0 : 2]; + else if (!bColor || bColor == 'none') + bColor = 'black'; + img.style.border = v + 'px ' + bStyle + ' ' + bColor; + } + } + } + + // Handle hspace + if (ty == 'hspace') { + dom.setStyle(img, 'marginLeft', ''); + dom.setStyle(img, 'marginRight', ''); + + v = f.hspace.value; + if (v) { + img.style.marginLeft = v + 'px'; + img.style.marginRight = v + 'px'; + } + } + + // Handle vspace + if (ty == 'vspace') { + dom.setStyle(img, 'marginTop', ''); + dom.setStyle(img, 'marginBottom', ''); + + v = f.vspace.value; + if (v) { + img.style.marginTop = v + 'px'; + img.style.marginBottom = v + 'px'; + } + } + + // Merge + dom.get('style').value = dom.serializeStyle(dom.parseStyle(img.style.cssText), 'img'); + } + }, + + changeMouseMove : function() { + }, + + showPreviewImage : function(u, st) { + if (!u) { + tinyMCEPopup.dom.setHTML('prev', ''); + return; + } + + if (!st && tinyMCEPopup.getParam("advimage_update_dimensions_onchange", true)) + this.resetImageData(); + + u = tinyMCEPopup.editor.documentBaseURI.toAbsolute(u); + + if (!st) + tinyMCEPopup.dom.setHTML('prev', '<img id="previewImg" src="' + u + '" border="0" onload="ImageDialog.updateImageData(this);" onerror="ImageDialog.resetImageData();" />'); + else + tinyMCEPopup.dom.setHTML('prev', '<img id="previewImg" src="' + u + '" border="0" onload="ImageDialog.updateImageData(this, 1);" />'); + } +}; + +ImageDialog.preInit(); +tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog); diff --git a/src/core/static/js/tiny_mce/plugins/advimage/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/advimage/langs/de_dlg.js new file mode 100755 index 0000000..fc0f6d1 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advimage/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.advimage_dlg',{"image_list":"Bilderliste","align_right":"Rechts","align_left":"Links","align_textbottom":"Unten im Text","align_texttop":"Oben im Text","align_bottom":"Unten","align_middle":"Mittig","align_top":"Oben","align_baseline":"Zeile",align:"Ausrichtung",hspace:"Horizontaler Abstand",vspace:"Vertikaler Abstand",dimensions:"Ausma\u00dfe",border:"Rahmen",list:"Bilderliste",alt:"Beschreibung",src:"Adresse","dialog_title":"Bild einf\u00fcgen/ver\u00e4ndern","missing_alt":"Wollen Sie wirklich keine Beschreibung eingeben? Bestimmte Benutzer mit k\u00f6rperlichen Einschr\u00e4nkungen k\u00f6nnen so nicht darauf zugreifen, ebenso solche, die einen Textbrowser benutzen oder die Anzeige von Bildern deaktiviert haben.","example_img":"Vorschau auf das Aussehen",misc:"Verschiedenes",mouseout:"bei keinem Mauskontakt",mouseover:"bei Mauskontakt","alt_image":"Alternatives Bild","swap_image":"Bild austauschen",map:"Image-Map",id:"ID",rtl:"Rechts nach links",ltr:"Links nach rechts",classes:"Klassen",style:"Format","long_desc":"Ausf\u00fchrliche Beschreibung",langcode:"Sprachcode",langdir:"Schriftrichtung","constrain_proportions":"Seitenverh\u00e4ltnis beibehalten",preview:"Vorschau",title:"Titel",general:"Allgemein","tab_advanced":"Erweitert","tab_appearance":"Aussehen","tab_general":"Allgemein",width:"Breite",height:"H\u00f6he"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advimage/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/advimage/langs/en_dlg.js new file mode 100755 index 0000000..5f122e2 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advimage/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.advimage_dlg',{"image_list":"Image List","align_right":"Right","align_left":"Left","align_textbottom":"Text Bottom","align_texttop":"Text Top","align_bottom":"Bottom","align_middle":"Middle","align_top":"Top","align_baseline":"Baseline",align:"Alignment",hspace:"Horizontal Space",vspace:"Vertical Space",dimensions:"Dimensions",border:"Border",list:"Image List",alt:"Image Description",src:"Image URL","dialog_title":"Insert/Edit Image","missing_alt":"Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.","example_img":"Appearance Preview Image",misc:"Miscellaneous",mouseout:"For Mouse Out",mouseover:"For Mouse Over","alt_image":"Alternative Image","swap_image":"Swap Image",map:"Image Map",id:"ID",rtl:"Right to Left",ltr:"Left to Right",classes:"Classes",style:"Style","long_desc":"Long Description Link",langcode:"Language Code",langdir:"Language Direction","constrain_proportions":"Constrain Proportions",preview:"Preview",title:"Title",general:"General","tab_advanced":"Advanced","tab_appearance":"Appearance","tab_general":"General",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advimage/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/advimage/langs/fr_dlg.js new file mode 100755 index 0000000..ecf3d95 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advimage/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.advimage_dlg',{"image_list":"Liste d\'images","align_right":"Droite (flottant)","align_left":"Gauche (flottant)","align_textbottom":"Texte en bas","align_texttop":"Texte en haut","align_bottom":"En bas","align_middle":"Au milieu","align_top":"En haut","align_baseline":"Normal",align:"Alignement",hspace:"Espacement horizontal",vspace:"Espacement vertical",dimensions:"Dimensions",border:"Bordure",list:"Liste d\'images",alt:"Description de l\'image",src:"URL de l\'image","dialog_title":"Ins\u00e9rer / \u00e9diter une image","missing_alt":"\u00cates-vous s\u00fbr de vouloir continuer sans d\u00e9finir de description pour l\'image ? Sans elle, l\'image peut ne pas \u00eatre accessible \u00e0 certains utilisateurs handicap\u00e9s, ceux utilisant un navigateur texte ou ceux qui naviguent sans affichage des images.","example_img":"Apparence de l\'image",misc:"Divers",mouseout:"\u00e0 la sortie de la souris",mouseover:"au survol de la souris","alt_image":"Image alternative","swap_image":"Image de remplacement",map:"Image cliquable",id:"Id",rtl:"De droite \u00e0 gauche",ltr:"De gauche \u00e0 droite",classes:"Classes",style:"Style","long_desc":"Description longue du lien",langcode:"Code de la langue",langdir:"Sens de lecture","constrain_proportions":"Conserver les proportions",preview:"Pr\u00e9visualisation",title:"Titre",general:"G\u00e9n\u00e9ral","tab_advanced":"Avanc\u00e9","tab_appearance":"Apparence","tab_general":"G\u00e9n\u00e9ral",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advimage/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/advimage/langs/it_dlg.js new file mode 100755 index 0000000..684369d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advimage/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.advimage_dlg',{"image_list":"Lista immagini","align_right":"A destra","align_left":"A sinistra","align_textbottom":"In basso al testo","align_texttop":"In alto al testo","align_bottom":"In basso","align_middle":"In mezzo","align_top":"In alto","align_baseline":"Alla base",align:"Allineamento",hspace:"Spaziatura orizzontale",vspace:"Spaziatura verticale",dimensions:"Dimensioni",border:"Bordo",list:"Lista immagini",alt:"Descrizione immagine",src:"URL immagine","dialog_title":"Inserisci/modifica immagine","missing_alt":"Sicuro di continuare senza includere una descrizione dell\'immagine? Senza di essa l\'immagine pu\u00f2 non essere accessibile ad alcuni utenti con disabilit\u00e0, o per coloro che usano un browser testuale oppure che hanno disabilitato la visualizzazione delle immagini nel loro browser.","example_img":"Anteprima aspetto immagine",misc:"Impostazioni varie",mouseout:"quando mouse fuori",mouseover:"quando mouse sopra","alt_image":"Immagine alternativa","swap_image":"Sostituisci immagine",map:"Immagine come mappa",id:"Id",rtl:"Destra verso sinistraa",ltr:"Sinistra verso destra",classes:"Classe",style:"Stile","long_desc":"Descrizione del collegamento",langcode:"codice lingua",langdir:"Direzione testo","constrain_proportions":"Mantieni proporzioni",preview:"Anteprima",title:"Titolo",general:"Generale","tab_advanced":"Avanzate","tab_appearance":"Aspetto","tab_general":"Generale",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advlink/css/advlink.css b/src/core/static/js/tiny_mce/plugins/advlink/css/advlink.css new file mode 100644 index 0000000..1436431 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advlink/css/advlink.css @@ -0,0 +1,8 @@ +.mceLinkList, .mceAnchorList, #targetlist {width:280px;} +.mceActionPanel {margin-top:7px;} +.panel_wrapper div.current {height:320px;} +#classlist, #title, #href {width:280px;} +#popupurl, #popupname {width:200px;} +#popupwidth, #popupheight, #popupleft, #popuptop {width:30px;vertical-align:middle;text-align:center;} +#id, #style, #classes, #target, #dir, #hreflang, #lang, #charset, #type, #rel, #rev, #tabindex, #accesskey {width:200px;} +#events_panel input {width:200px;} diff --git a/src/core/static/js/tiny_mce/plugins/advlink/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/advlink/editor_plugin.js new file mode 100644 index 0000000..983fe5a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advlink/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.AdvancedLinkPlugin",{init:function(a,b){this.editor=a;a.addCommand("mceAdvLink",function(){var c=a.selection;if(c.isCollapsed()&&!a.dom.getParent(c.getNode(),"A")){return}a.windowManager.open({file:b+"/link.htm",width:480+parseInt(a.getLang("advlink.delta_width",0)),height:400+parseInt(a.getLang("advlink.delta_height",0)),inline:1},{plugin_url:b})});a.addButton("link",{title:"advlink.link_desc",cmd:"mceAdvLink"});a.addShortcut("ctrl+k","advlink.advlink_desc","mceAdvLink");a.onNodeChange.add(function(d,c,f,e){c.setDisabled("link",e&&f.nodeName!="A");c.setActive("link",f.nodeName=="A"&&!f.name)})},getInfo:function(){return{longname:"Advanced link",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("advlink",tinymce.plugins.AdvancedLinkPlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advlink/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/advlink/editor_plugin_src.js new file mode 100644 index 0000000..14e46a7 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advlink/editor_plugin_src.js @@ -0,0 +1,61 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.AdvancedLinkPlugin', { + init : function(ed, url) { + this.editor = ed; + + // Register commands + ed.addCommand('mceAdvLink', function() { + var se = ed.selection; + + // No selection and not in link + if (se.isCollapsed() && !ed.dom.getParent(se.getNode(), 'A')) + return; + + ed.windowManager.open({ + file : url + '/link.htm', + width : 480 + parseInt(ed.getLang('advlink.delta_width', 0)), + height : 400 + parseInt(ed.getLang('advlink.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('link', { + title : 'advlink.link_desc', + cmd : 'mceAdvLink' + }); + + ed.addShortcut('ctrl+k', 'advlink.advlink_desc', 'mceAdvLink'); + + ed.onNodeChange.add(function(ed, cm, n, co) { + cm.setDisabled('link', co && n.nodeName != 'A'); + cm.setActive('link', n.nodeName == 'A' && !n.name); + }); + }, + + getInfo : function() { + return { + longname : 'Advanced link', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('advlink', tinymce.plugins.AdvancedLinkPlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advlink/js/advlink.js b/src/core/static/js/tiny_mce/plugins/advlink/js/advlink.js new file mode 100644 index 0000000..837c937 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advlink/js/advlink.js @@ -0,0 +1,532 @@ +/* Functions for the advlink plugin popup */ + +tinyMCEPopup.requireLangPack(); + +var templates = { + "window.open" : "window.open('${url}','${target}','${options}')" +}; + +function preinit() { + var url; + + if (url = tinyMCEPopup.getParam("external_link_list_url")) + document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>'); +} + +function changeClass() { + var f = document.forms[0]; + + f.classes.value = getSelectValue(f, 'classlist'); +} + +function init() { + tinyMCEPopup.resizeToInnerSize(); + + var formObj = document.forms[0]; + var inst = tinyMCEPopup.editor; + var elm = inst.selection.getNode(); + var action = "insert"; + var html; + + document.getElementById('hrefbrowsercontainer').innerHTML = getBrowserHTML('hrefbrowser','href','file','advlink'); + document.getElementById('popupurlbrowsercontainer').innerHTML = getBrowserHTML('popupurlbrowser','popupurl','file','advlink'); + document.getElementById('targetlistcontainer').innerHTML = getTargetListHTML('targetlist','target'); + + // Link list + html = getLinkListHTML('linklisthref','href'); + if (html == "") + document.getElementById("linklisthrefrow").style.display = 'none'; + else + document.getElementById("linklisthrefcontainer").innerHTML = html; + + // Anchor list + html = getAnchorListHTML('anchorlist','href'); + if (html == "") + document.getElementById("anchorlistrow").style.display = 'none'; + else + document.getElementById("anchorlistcontainer").innerHTML = html; + + // Resize some elements + if (isVisible('hrefbrowser')) + document.getElementById('href').style.width = '260px'; + + if (isVisible('popupurlbrowser')) + document.getElementById('popupurl').style.width = '180px'; + + elm = inst.dom.getParent(elm, "A"); + if (elm != null && elm.nodeName == "A") + action = "update"; + + formObj.insert.value = tinyMCEPopup.getLang(action, 'Insert', true); + + setPopupControlsDisabled(true); + + if (action == "update") { + var href = inst.dom.getAttrib(elm, 'href'); + var onclick = inst.dom.getAttrib(elm, 'onclick'); + + // Setup form data + setFormValue('href', href); + setFormValue('title', inst.dom.getAttrib(elm, 'title')); + setFormValue('id', inst.dom.getAttrib(elm, 'id')); + setFormValue('style', inst.dom.getAttrib(elm, "style")); + setFormValue('rel', inst.dom.getAttrib(elm, 'rel')); + setFormValue('rev', inst.dom.getAttrib(elm, 'rev')); + setFormValue('charset', inst.dom.getAttrib(elm, 'charset')); + setFormValue('hreflang', inst.dom.getAttrib(elm, 'hreflang')); + setFormValue('dir', inst.dom.getAttrib(elm, 'dir')); + setFormValue('lang', inst.dom.getAttrib(elm, 'lang')); + setFormValue('tabindex', inst.dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : "")); + setFormValue('accesskey', inst.dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : "")); + setFormValue('type', inst.dom.getAttrib(elm, 'type')); + setFormValue('onfocus', inst.dom.getAttrib(elm, 'onfocus')); + setFormValue('onblur', inst.dom.getAttrib(elm, 'onblur')); + setFormValue('onclick', onclick); + setFormValue('ondblclick', inst.dom.getAttrib(elm, 'ondblclick')); + setFormValue('onmousedown', inst.dom.getAttrib(elm, 'onmousedown')); + setFormValue('onmouseup', inst.dom.getAttrib(elm, 'onmouseup')); + setFormValue('onmouseover', inst.dom.getAttrib(elm, 'onmouseover')); + setFormValue('onmousemove', inst.dom.getAttrib(elm, 'onmousemove')); + setFormValue('onmouseout', inst.dom.getAttrib(elm, 'onmouseout')); + setFormValue('onkeypress', inst.dom.getAttrib(elm, 'onkeypress')); + setFormValue('onkeydown', inst.dom.getAttrib(elm, 'onkeydown')); + setFormValue('onkeyup', inst.dom.getAttrib(elm, 'onkeyup')); + setFormValue('target', inst.dom.getAttrib(elm, 'target')); + setFormValue('classes', inst.dom.getAttrib(elm, 'class')); + + // Parse onclick data + if (onclick != null && onclick.indexOf('window.open') != -1) + parseWindowOpen(onclick); + else + parseFunction(onclick); + + // Select by the values + selectByValue(formObj, 'dir', inst.dom.getAttrib(elm, 'dir')); + selectByValue(formObj, 'rel', inst.dom.getAttrib(elm, 'rel')); + selectByValue(formObj, 'rev', inst.dom.getAttrib(elm, 'rev')); + selectByValue(formObj, 'linklisthref', href); + + if (href.charAt(0) == '#') + selectByValue(formObj, 'anchorlist', href); + + addClassesToList('classlist', 'advlink_styles'); + + selectByValue(formObj, 'classlist', inst.dom.getAttrib(elm, 'class'), true); + selectByValue(formObj, 'targetlist', inst.dom.getAttrib(elm, 'target'), true); + } else + addClassesToList('classlist', 'advlink_styles'); +} + +function checkPrefix(n) { + if (n.value && Validator.isEmail(n) && !/^\s*mailto:/i.test(n.value) && confirm(tinyMCEPopup.getLang('advlink_dlg.is_email'))) + n.value = 'mailto:' + n.value; + + if (/^\s*www\./i.test(n.value) && confirm(tinyMCEPopup.getLang('advlink_dlg.is_external'))) + n.value = 'http://' + n.value; +} + +function setFormValue(name, value) { + document.forms[0].elements[name].value = value; +} + +function parseWindowOpen(onclick) { + var formObj = document.forms[0]; + + // Preprocess center code + if (onclick.indexOf('return false;') != -1) { + formObj.popupreturn.checked = true; + onclick = onclick.replace('return false;', ''); + } else + formObj.popupreturn.checked = false; + + var onClickData = parseLink(onclick); + + if (onClickData != null) { + formObj.ispopup.checked = true; + setPopupControlsDisabled(false); + + var onClickWindowOptions = parseOptions(onClickData['options']); + var url = onClickData['url']; + + formObj.popupname.value = onClickData['target']; + formObj.popupurl.value = url; + formObj.popupwidth.value = getOption(onClickWindowOptions, 'width'); + formObj.popupheight.value = getOption(onClickWindowOptions, 'height'); + + formObj.popupleft.value = getOption(onClickWindowOptions, 'left'); + formObj.popuptop.value = getOption(onClickWindowOptions, 'top'); + + if (formObj.popupleft.value.indexOf('screen') != -1) + formObj.popupleft.value = "c"; + + if (formObj.popuptop.value.indexOf('screen') != -1) + formObj.popuptop.value = "c"; + + formObj.popuplocation.checked = getOption(onClickWindowOptions, 'location') == "yes"; + formObj.popupscrollbars.checked = getOption(onClickWindowOptions, 'scrollbars') == "yes"; + formObj.popupmenubar.checked = getOption(onClickWindowOptions, 'menubar') == "yes"; + formObj.popupresizable.checked = getOption(onClickWindowOptions, 'resizable') == "yes"; + formObj.popuptoolbar.checked = getOption(onClickWindowOptions, 'toolbar') == "yes"; + formObj.popupstatus.checked = getOption(onClickWindowOptions, 'status') == "yes"; + formObj.popupdependent.checked = getOption(onClickWindowOptions, 'dependent') == "yes"; + + buildOnClick(); + } +} + +function parseFunction(onclick) { + var formObj = document.forms[0]; + var onClickData = parseLink(onclick); + + // TODO: Add stuff here +} + +function getOption(opts, name) { + return typeof(opts[name]) == "undefined" ? "" : opts[name]; +} + +function setPopupControlsDisabled(state) { + var formObj = document.forms[0]; + + formObj.popupname.disabled = state; + formObj.popupurl.disabled = state; + formObj.popupwidth.disabled = state; + formObj.popupheight.disabled = state; + formObj.popupleft.disabled = state; + formObj.popuptop.disabled = state; + formObj.popuplocation.disabled = state; + formObj.popupscrollbars.disabled = state; + formObj.popupmenubar.disabled = state; + formObj.popupresizable.disabled = state; + formObj.popuptoolbar.disabled = state; + formObj.popupstatus.disabled = state; + formObj.popupreturn.disabled = state; + formObj.popupdependent.disabled = state; + + setBrowserDisabled('popupurlbrowser', state); +} + +function parseLink(link) { + link = link.replace(new RegExp('&#39;', 'g'), "'"); + + var fnName = link.replace(new RegExp("\\s*([A-Za-z0-9\.]*)\\s*\\(.*", "gi"), "$1"); + + // Is function name a template function + var template = templates[fnName]; + if (template) { + // Build regexp + var variableNames = template.match(new RegExp("'?\\$\\{[A-Za-z0-9\.]*\\}'?", "gi")); + var regExp = "\\s*[A-Za-z0-9\.]*\\s*\\("; + var replaceStr = ""; + for (var i=0; i<variableNames.length; i++) { + // Is string value + if (variableNames[i].indexOf("'${") != -1) + regExp += "'(.*)'"; + else // Number value + regExp += "([0-9]*)"; + + replaceStr += "$" + (i+1); + + // Cleanup variable name + variableNames[i] = variableNames[i].replace(new RegExp("[^A-Za-z0-9]", "gi"), ""); + + if (i != variableNames.length-1) { + regExp += "\\s*,\\s*"; + replaceStr += "<delim>"; + } else + regExp += ".*"; + } + + regExp += "\\);?"; + + // Build variable array + var variables = []; + variables["_function"] = fnName; + var variableValues = link.replace(new RegExp(regExp, "gi"), replaceStr).split('<delim>'); + for (var i=0; i<variableNames.length; i++) + variables[variableNames[i]] = variableValues[i]; + + return variables; + } + + return null; +} + +function parseOptions(opts) { + if (opts == null || opts == "") + return []; + + // Cleanup the options + opts = opts.toLowerCase(); + opts = opts.replace(/;/g, ","); + opts = opts.replace(/[^0-9a-z=,]/g, ""); + + var optionChunks = opts.split(','); + var options = []; + + for (var i=0; i<optionChunks.length; i++) { + var parts = optionChunks[i].split('='); + + if (parts.length == 2) + options[parts[0]] = parts[1]; + } + + return options; +} + +function buildOnClick() { + var formObj = document.forms[0]; + + if (!formObj.ispopup.checked) { + formObj.onclick.value = ""; + return; + } + + var onclick = "window.open('"; + var url = formObj.popupurl.value; + + onclick += url + "','"; + onclick += formObj.popupname.value + "','"; + + if (formObj.popuplocation.checked) + onclick += "location=yes,"; + + if (formObj.popupscrollbars.checked) + onclick += "scrollbars=yes,"; + + if (formObj.popupmenubar.checked) + onclick += "menubar=yes,"; + + if (formObj.popupresizable.checked) + onclick += "resizable=yes,"; + + if (formObj.popuptoolbar.checked) + onclick += "toolbar=yes,"; + + if (formObj.popupstatus.checked) + onclick += "status=yes,"; + + if (formObj.popupdependent.checked) + onclick += "dependent=yes,"; + + if (formObj.popupwidth.value != "") + onclick += "width=" + formObj.popupwidth.value + ","; + + if (formObj.popupheight.value != "") + onclick += "height=" + formObj.popupheight.value + ","; + + if (formObj.popupleft.value != "") { + if (formObj.popupleft.value != "c") + onclick += "left=" + formObj.popupleft.value + ","; + else + onclick += "left='+(screen.availWidth/2-" + (formObj.popupwidth.value/2) + ")+',"; + } + + if (formObj.popuptop.value != "") { + if (formObj.popuptop.value != "c") + onclick += "top=" + formObj.popuptop.value + ","; + else + onclick += "top='+(screen.availHeight/2-" + (formObj.popupheight.value/2) + ")+',"; + } + + if (onclick.charAt(onclick.length-1) == ',') + onclick = onclick.substring(0, onclick.length-1); + + onclick += "');"; + + if (formObj.popupreturn.checked) + onclick += "return false;"; + + // tinyMCE.debug(onclick); + + formObj.onclick.value = onclick; + + if (formObj.href.value == "") + formObj.href.value = url; +} + +function setAttrib(elm, attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib.toLowerCase()]; + var dom = tinyMCEPopup.editor.dom; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + // Clean up the style + if (attrib == 'style') + value = dom.serializeStyle(dom.parseStyle(value), 'a'); + + dom.setAttrib(elm, attrib, value); +} + +function getAnchorListHTML(id, target) { + var ed = tinyMCEPopup.editor, nodes = ed.dom.select('a'), name, i, len, html = ""; + + for (i=0, len=nodes.length; i<len; i++) { + if ((name = ed.dom.getAttrib(nodes[i], "name")) != "") + html += '<option value="#' + name + '">' + name + '</option>'; + } + + if (html == "") + return ""; + + html = '<select id="' + id + '" name="' + id + '" class="mceAnchorList"' + + ' onchange="this.form.' + target + '.value=this.options[this.selectedIndex].value"' + + '>' + + '<option value="">---</option>' + + html + + '</select>'; + + return html; +} + +function insertAction() { + var inst = tinyMCEPopup.editor; + var elm, elementArray, i; + + elm = inst.selection.getNode(); + checkPrefix(document.forms[0].href); + + elm = inst.dom.getParent(elm, "A"); + + // Remove element if there is no href + if (!document.forms[0].href.value) { + i = inst.selection.getBookmark(); + inst.dom.remove(elm, 1); + inst.selection.moveToBookmark(i); + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); + return; + } + + // Create new anchor elements + if (elm == null) { + inst.getDoc().execCommand("unlink", false, null); + tinyMCEPopup.execCommand("mceInsertLink", false, "#mce_temp_url#", {skip_undo : 1}); + + elementArray = tinymce.grep(inst.dom.select("a"), function(n) {return inst.dom.getAttrib(n, 'href') == '#mce_temp_url#';}); + for (i=0; i<elementArray.length; i++) + setAllAttribs(elm = elementArray[i]); + } else + setAllAttribs(elm); + + // Don't move caret if selection was image + if (elm.childNodes.length != 1 || elm.firstChild.nodeName != 'IMG') { + inst.focus(); + inst.selection.select(elm); + inst.selection.collapse(0); + tinyMCEPopup.storeSelection(); + } + + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); +} + +function setAllAttribs(elm) { + var formObj = document.forms[0]; + var href = formObj.href.value.replace(/ /g, '%20'); + var target = getSelectValue(formObj, 'targetlist'); + + setAttrib(elm, 'href', href); + setAttrib(elm, 'title'); + setAttrib(elm, 'target', target == '_self' ? '' : target); + setAttrib(elm, 'id'); + setAttrib(elm, 'style'); + setAttrib(elm, 'class', getSelectValue(formObj, 'classlist')); + setAttrib(elm, 'rel'); + setAttrib(elm, 'rev'); + setAttrib(elm, 'charset'); + setAttrib(elm, 'hreflang'); + setAttrib(elm, 'dir'); + setAttrib(elm, 'lang'); + setAttrib(elm, 'tabindex'); + setAttrib(elm, 'accesskey'); + setAttrib(elm, 'type'); + setAttrib(elm, 'onfocus'); + setAttrib(elm, 'onblur'); + setAttrib(elm, 'onclick'); + setAttrib(elm, 'ondblclick'); + setAttrib(elm, 'onmousedown'); + setAttrib(elm, 'onmouseup'); + setAttrib(elm, 'onmouseover'); + setAttrib(elm, 'onmousemove'); + setAttrib(elm, 'onmouseout'); + setAttrib(elm, 'onkeypress'); + setAttrib(elm, 'onkeydown'); + setAttrib(elm, 'onkeyup'); + + // Refresh in old MSIE + if (tinyMCE.isMSIE5) + elm.outerHTML = elm.outerHTML; +} + +function getSelectValue(form_obj, field_name) { + var elm = form_obj.elements[field_name]; + + if (!elm || elm.options == null || elm.selectedIndex == -1) + return ""; + + return elm.options[elm.selectedIndex].value; +} + +function getLinkListHTML(elm_id, target_form_element, onchange_func) { + if (typeof(tinyMCELinkList) == "undefined" || tinyMCELinkList.length == 0) + return ""; + + var html = ""; + + html += '<select id="' + elm_id + '" name="' + elm_id + '"'; + html += ' class="mceLinkList" onfoc2us="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value='; + html += 'this.options[this.selectedIndex].value;'; + + if (typeof(onchange_func) != "undefined") + html += onchange_func + '(\'' + target_form_element + '\',this.options[this.selectedIndex].text,this.options[this.selectedIndex].value);'; + + html += '"><option value="">---</option>'; + + for (var i=0; i<tinyMCELinkList.length; i++) + html += '<option value="' + tinyMCELinkList[i][1] + '">' + tinyMCELinkList[i][0] + '</option>'; + + html += '</select>'; + + return html; + + // tinyMCE.debug('-- image list start --', html, '-- image list end --'); +} + +function getTargetListHTML(elm_id, target_form_element) { + var targets = tinyMCEPopup.getParam('theme_advanced_link_targets', '').split(';'); + var html = ''; + + html += '<select id="' + elm_id + '" name="' + elm_id + '" onf2ocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value='; + html += 'this.options[this.selectedIndex].value;">'; + html += '<option value="_self">' + tinyMCEPopup.getLang('advlink_dlg.target_same') + '</option>'; + html += '<option value="_blank">' + tinyMCEPopup.getLang('advlink_dlg.target_blank') + ' (_blank)</option>'; + html += '<option value="_parent">' + tinyMCEPopup.getLang('advlink_dlg.target_parent') + ' (_parent)</option>'; + html += '<option value="_top">' + tinyMCEPopup.getLang('advlink_dlg.target_top') + ' (_top)</option>'; + + for (var i=0; i<targets.length; i++) { + var key, value; + + if (targets[i] == "") + continue; + + key = targets[i].split('=')[0]; + value = targets[i].split('=')[1]; + + html += '<option value="' + key + '">' + value + ' (' + key + ')</option>'; + } + + html += '</select>'; + + return html; +} + +// While loading +preinit(); +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/plugins/advlink/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/advlink/langs/de_dlg.js new file mode 100755 index 0000000..bb0d3e3 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advlink/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.advlink_dlg',{"target_name":"Name der Zielseite",classes:"Klassen",style:"Format",id:"ID","popup_position":"Position (X/Y)",langdir:"Schriftrichtung","popup_size":"Gr\u00f6\u00dfe","popup_dependent":"Vom Elternfenster abh\u00e4ngig <br /> (nur Mozilla/Firefox) ","popup_resizable":"Vergr\u00f6\u00dfern des Fenster zulassen","popup_location":"Adressleiste anzeigen","popup_menubar":"Browsermen\u00fc anzeigen","popup_toolbar":"Werkzeugleisten anzeigen","popup_statusbar":"Statusleiste anzeigen","popup_scrollbars":"Scrollbalken anzeigen","popup_return":"Link trotz Popup folgen","popup_name":"Name des Fensters","popup_url":"Popup-Adresse",popup:"JavaScript-Popup","target_blank":"In neuem Fenster \u00f6ffnen","target_top":"Im obersten Frame \u00f6ffnen (sprengt das Frameset)","target_parent":"Im \u00fcbergeordneten Fenster/Frame \u00f6ffnen","target_same":"Im selben Fenster/Frame \u00f6ffnen","anchor_names":"Anker","popup_opts":"Optionen","advanced_props":"Erweiterte Eigenschaften","event_props":"Ereignisse","popup_props":"Popup-Eigenschaften","general_props":"Allemeine Eigenschaften","advanced_tab":"Erweitert","events_tab":"Ereignisse","popup_tab":"Popup","general_tab":"Allgemein",list:"Linkliste","is_external":"Diese Adresse scheint ein externer Link zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"http://\" voranstellen?","is_email":"Diese Adresse scheint eine E-Mail-Adresse zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"mailto:\" voranstellen?",titlefield:"Titel",target:"Fenster",url:"Adresse",title:"Link einf\u00fcgen/bearbeiten","link_list":"Linkliste",rtl:"Rechts nach links",ltr:"Links nach rechts",accesskey:"Tastenk\u00fcrzel",tabindex:"Tabindex",rev:"Beziehung des Linkziels zur Seite",rel:"Beziehung der Seite zum Linkziel",mime:"MIME-Type der Zielseite",encoding:"Zeichenkodierung der Zielseite",langcode:"Sprachcode","target_langcode":"Sprache der Zielseite",width:"Breite",height:"H\u00f6he"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advlink/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/advlink/langs/en_dlg.js new file mode 100755 index 0000000..3169a56 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advlink/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.advlink_dlg',{"target_name":"Target Name",classes:"Classes",style:"Style",id:"ID","popup_position":"Position (X/Y)",langdir:"Language Direction","popup_size":"Size","popup_dependent":"Dependent (Mozilla/Firefox Only)","popup_resizable":"Make Window Resizable","popup_location":"Show Location Bar","popup_menubar":"Show Menu Bar","popup_toolbar":"Show Toolbars","popup_statusbar":"Show Status Bar","popup_scrollbars":"Show Scrollbars","popup_return":"Insert \'return false\'","popup_name":"Window Name","popup_url":"Popup URL",popup:"JavaScript Popup","target_blank":"Open in New Window","target_top":"Open in Top Frame (Replaces All Frames)","target_parent":"Open in Parent Window/Frame","target_same":"Open in This Window/Frame","anchor_names":"Anchors","popup_opts":"Options","advanced_props":"Advanced Properties","event_props":"Events","popup_props":"Popup Properties","general_props":"General Properties","advanced_tab":"Advanced","events_tab":"Events","popup_tab":"Popup","general_tab":"General",list:"Link List","is_external":"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?","is_email":"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",titlefield:"Title",target:"Target",url:"Link URL",title:"Insert/Edit Link","link_list":"Link List",rtl:"Right to Left",ltr:"Left to Right",accesskey:"AccessKey",tabindex:"TabIndex",rev:"Relationship Target to Page",rel:"Relationship Page to Target",mime:"Target MIME Type",encoding:"Target Character Encoding",langcode:"Language Code","target_langcode":"Target Language",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advlink/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/advlink/langs/fr_dlg.js new file mode 100755 index 0000000..f22e960 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advlink/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.advlink_dlg',{"target_name":"Nom de la cible",classes:"Classes",style:"Style",id:"Id","popup_position":"Position (X/Y)",langdir:"Sens de lecture","popup_size":"Taille","popup_dependent":"D\u00e9pendante (seulement sous Mozilla/Firefox)","popup_resizable":"Autoriser le redimensionnement de la fen\u00eatre","popup_location":"Afficher la barre d\'adresse","popup_menubar":"Afficher la barre de menu","popup_toolbar":"Afficher la barre d\'outils","popup_statusbar":"Afficher la barre d\'\u00e9tat","popup_scrollbars":"Afficher les ascenseurs","popup_return":"Ins\u00e9rer \'return false\'","popup_name":"Nom de la fen\u00eatre","popup_url":"URL de la popup",popup:"Popup Javascript","target_blank":"Ouvrir dans une nouvelle fen\u00eatre","target_top":"Ouvrir dans le cadre principal (remplace tous les cadres)","target_parent":"Ouvrir dans la fen\u00eatre / le cadre parent","target_same":"Ouvrir dans cette fen\u00eatre / dans ce cadre","anchor_names":"Ancres","popup_opts":"Options","advanced_props":"Propri\u00e9t\u00e9s avanc\u00e9es","event_props":"\u00c9v\u00e8nements","popup_props":"Propri\u00e9t\u00e9s de la popup","general_props":"Propri\u00e9t\u00e9s g\u00e9n\u00e9rales","advanced_tab":"Avanc\u00e9","events_tab":"\u00c9v\u00e8nements","popup_tab":"Popup","general_tab":"G\u00e9n\u00e9ral",list:"Liste de liens","is_external":"L\'URL que vous avez saisie semble \u00eatre une adresse web externe. Souhaitez-vous ajouter le pr\u00e9fixe \u00ab http:// \u00bb ?","is_email":"L\'URL que vous avez saisie semble \u00eatre une adresse e-mail, souhaitez-vous ajouter le pr\u00e9fixe \u00ab mailto: \u00bb ?",titlefield:"Titre",target:"Cible",url:"URL du lien",title:"Ins\u00e9rer / \u00e9diter un lien","link_list":"Liste des liens",rtl:"Droite \u00e0 gauche",ltr:"Gauche \u00e0 droite",accesskey:"Touche d\'acc\u00e8s rapide",tabindex:"Tabindex",rev:"Relation de la cible \u00e0 la page",rel:"Relation de la page \u00e0 la cible",mime:"Type MIME de la cible",encoding:"Encodage de la cible",langcode:"Code de la langue","target_langcode":"Langue de la cible",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advlink/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/advlink/langs/it_dlg.js new file mode 100755 index 0000000..1a59f88 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advlink/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.advlink_dlg',{"target_name":"Nome target",classes:"Classe",style:"Stile",id:"Id","popup_position":"Posizione (X/Y)",langdir:"Direzione del testo","popup_size":"Dimensioni","popup_dependent":"Dipendente (Solo in Mozilla/Firefox)","popup_resizable":"Rendi la finestra ridimensionabile","popup_location":"Mostra barra navigazione","popup_menubar":"Mostra barra menu","popup_toolbar":"Mostra barre strumenti","popup_statusbar":"Mostra barra di stato","popup_scrollbars":"Mostra barre di scorrimento","popup_return":"Inserisci \'return false\'","popup_name":"Nome finestra","popup_url":"URL Popup",popup:"Popup Javascript","target_blank":"Apri in una nuova finestra","target_top":"Apri nella cornice superiore (sostituisce tutte le cornici)","target_parent":"Apri nella finestra / cornice genitore","target_same":"Apri in questa finestra / cornice","anchor_names":"Ancore","popup_opts":"Opzioni","advanced_props":"Propriet\u00e0 avanzate","event_props":"Eventi","popup_props":"Propriet\u00e0 popup","general_props":"Propriet\u00e0 generali","advanced_tab":"Avanzate","events_tab":"Eventi","popup_tab":"Popup","general_tab":"Generale",list:"Lista collegamenti","is_external":"L\'URL inserito sembra essere un link esterno. Aggiungere il necessario prefisso http:// ?","is_email":"L\'URL inserito sembra essere un indirizzo email. Aggiungere il necessario prefisso mailto: ?",titlefield:"Titolo",target:"Target",url:"URL collegamento",title:"Inserisci/modifica link","link_list":"Lista collegamenti",rtl:"Destra verso sinistra",ltr:"Sinistra verso destra",accesskey:"Carattere di accesso",tabindex:"Indice tabulazione",rev:"Relazione da target a pagina",rel:"Relazione da pagina a target",mime:"Tipo MIME del target",encoding:"Codifica carattere del target",langcode:"Lingua","target_langcode":"Lingua del target",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advlink/link.htm b/src/core/static/js/tiny_mce/plugins/advlink/link.htm new file mode 100644 index 0000000..8ab7c2a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advlink/link.htm @@ -0,0 +1,338 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advlink_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="js/advlink.js"></script> + <link href="css/advlink.css" rel="stylesheet" type="text/css" /> +</head> +<body id="advlink" style="display: none" role="application" onload="javascript:mcTabs.displayTab('general_tab','general_panel', true);" aria-labelledby="app_label"> + <span class="mceVoiceLabel" id="app_label" style="display:none;">{#advlink_dlg.title}</span> + <form onsubmit="insertAction();return false;" action="#"> + <div class="tabs" role="presentation"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel" ><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advlink_dlg.general_tab}</a></span></li> + <li id="popup_tab" aria-controls="popup_panel" ><span><a href="javascript:mcTabs.displayTab('popup_tab','popup_panel');" onmousedown="return false;">{#advlink_dlg.popup_tab}</a></span></li> + <li id="events_tab" aria-controls="events_panel"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#advlink_dlg.events_tab}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#advlink_dlg.advanced_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper" role="presentation"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#advlink_dlg.general_props}</legend> + + <table border="0" cellpadding="4" cellspacing="0" role="presentation"> + <tr> + <td class="nowrap"><label id="hreflabel" for="href">{#advlink_dlg.url}</label></td> + <td><table border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="href" name="href" type="text" class="mceFocus" value="" onchange="selectByValue(this.form,'linklisthref',this.value);" aria-required="true" /></td> + <td id="hrefbrowsercontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr id="linklisthrefrow"> + <td class="column1"><label for="linklisthref">{#advlink_dlg.list}</label></td> + <td colspan="2" id="linklisthrefcontainer"><select id="linklisthref"><option value=""></option></select></td> + </tr> + <tr id="anchorlistrow"> + <td class="column1"><label for="anchorlist">{#advlink_dlg.anchor_names}</label></td> + <td colspan="2" id="anchorlistcontainer"><select id="anchorlist"><option value=""></option></select></td> + </tr> + <tr> + <td><label id="targetlistlabel" for="targetlist">{#advlink_dlg.target}</label></td> + <td id="targetlistcontainer"><select id="targetlist"><option value=""></option></select></td> + </tr> + <tr> + <td class="nowrap"><label id="titlelabel" for="title">{#advlink_dlg.titlefield}</label></td> + <td><input id="title" name="title" type="text" value="" /></td> + </tr> + <tr> + <td><label id="classlabel" for="classlist">{#class_name}</label></td> + <td> + <select id="classlist" name="classlist" onchange="changeClass();"> + <option value="" selected="selected">{#not_set}</option> + </select> + </td> + </tr> + </table> + </fieldset> + </div> + + <div id="popup_panel" class="panel"> + <fieldset> + <legend>{#advlink_dlg.popup_props}</legend> + + <input type="checkbox" id="ispopup" name="ispopup" class="radio" onclick="setPopupControlsDisabled(!this.checked);buildOnClick();" /> + <label id="ispopuplabel" for="ispopup">{#advlink_dlg.popup}</label> + + <table border="0" cellpadding="0" cellspacing="4" role="presentation" > + <tr> + <td class="nowrap"><label for="popupurl">{#advlink_dlg.popup_url}</label>&nbsp;</td> + <td> + <table border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" name="popupurl" id="popupurl" value="" onchange="buildOnClick();" /></td> + <td id="popupurlbrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + <tr> + <td class="nowrap"><label for="popupname">{#advlink_dlg.popup_name}</label>&nbsp;</td> + <td><input type="text" name="popupname" id="popupname" value="" onchange="buildOnClick();" /></td> + </tr> + <tr role="group" aria-labelledby="popup_size_label"> + <td class="nowrap"><label id="popup_size_label">{#advlink_dlg.popup_size}</label>&nbsp;</td> + <td class="nowrap"> + <span style="display:none" id="width_voiceLabel">{#advlink_dlg.width}</span> + <input type="text" id="popupwidth" name="popupwidth" value="" onchange="buildOnClick();" aria-labelledby="width_voiceLabel" /> x + <span style="display:none" id="height_voiceLabel">{#advlink_dlg.height}</span> + <input type="text" id="popupheight" name="popupheight" value="" onchange="buildOnClick();" aria-labelledby="height_voiceLabel" /> px + </td> + </tr> + <tr role="group" aria-labelledby="popup_position_label center_hint"> + <td class="nowrap" id="labelleft"><label id="popup_position_label">{#advlink_dlg.popup_position}</label>&nbsp;</td> + <td class="nowrap"> + <span style="display:none" id="x_voiceLabel">X</span> + <input type="text" id="popupleft" name="popupleft" value="" onchange="buildOnClick();" aria-labelledby="x_voiceLabel" /> / + <span style="display:none" id="y_voiceLabel">Y</span> + <input type="text" id="popuptop" name="popuptop" value="" onchange="buildOnClick();" aria-labelledby="y_voiceLabel" /> <span id="center_hint">(c /c = center)</span> + </td> + </tr> + </table> + + <fieldset> + <legend>{#advlink_dlg.popup_opts}</legend> + + <table border="0" cellpadding="0" cellspacing="4" role="presentation" > + <tr> + <td><input type="checkbox" id="popuplocation" name="popuplocation" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popuplocationlabel" for="popuplocation">{#advlink_dlg.popup_location}</label></td> + <td><input type="checkbox" id="popupscrollbars" name="popupscrollbars" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popupscrollbarslabel" for="popupscrollbars">{#advlink_dlg.popup_scrollbars}</label></td> + </tr> + <tr> + <td><input type="checkbox" id="popupmenubar" name="popupmenubar" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popupmenubarlabel" for="popupmenubar">{#advlink_dlg.popup_menubar}</label></td> + <td><input type="checkbox" id="popupresizable" name="popupresizable" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popupresizablelabel" for="popupresizable">{#advlink_dlg.popup_resizable}</label></td> + </tr> + <tr> + <td><input type="checkbox" id="popuptoolbar" name="popuptoolbar" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popuptoolbarlabel" for="popuptoolbar">{#advlink_dlg.popup_toolbar}</label></td> + <td><input type="checkbox" id="popupdependent" name="popupdependent" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popupdependentlabel" for="popupdependent">{#advlink_dlg.popup_dependent}</label></td> + </tr> + <tr> + <td><input type="checkbox" id="popupstatus" name="popupstatus" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popupstatuslabel" for="popupstatus">{#advlink_dlg.popup_statusbar}</label></td> + <td><input type="checkbox" id="popupreturn" name="popupreturn" class="checkbox" onchange="buildOnClick();" checked="checked" /></td> + <td class="nowrap"><label id="popupreturnlabel" for="popupreturn">{#advlink_dlg.popup_return}</label></td> + </tr> + </table> + </fieldset> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#advlink_dlg.advanced_props}</legend> + + <table border="0" cellpadding="0" cellspacing="4" role="presentation" > + <tr> + <td class="column1"><label id="idlabel" for="id">{#advlink_dlg.id}</label></td> + <td><input id="id" name="id" type="text" value="" /></td> + </tr> + + <tr> + <td><label id="stylelabel" for="style">{#advlink_dlg.style}</label></td> + <td><input type="text" id="style" name="style" value="" /></td> + </tr> + + <tr> + <td><label id="classeslabel" for="classes">{#advlink_dlg.classes}</label></td> + <td><input type="text" id="classes" name="classes" value="" onchange="selectByValue(this.form,'classlist',this.value,true);" /></td> + </tr> + + <tr> + <td><label id="targetlabel" for="target">{#advlink_dlg.target_name}</label></td> + <td><input type="text" id="target" name="target" value="" onchange="selectByValue(this.form,'targetlist',this.value,true);" /></td> + </tr> + + <tr> + <td class="column1"><label id="dirlabel" for="dir">{#advlink_dlg.langdir}</label></td> + <td> + <select id="dir" name="dir"> + <option value="">{#not_set}</option> + <option value="ltr">{#advlink_dlg.ltr}</option> + <option value="rtl">{#advlink_dlg.rtl}</option> + </select> + </td> + </tr> + + <tr> + <td><label id="hreflanglabel" for="hreflang">{#advlink_dlg.target_langcode}</label></td> + <td><input type="text" id="hreflang" name="hreflang" value="" /></td> + </tr> + + <tr> + <td class="column1"><label id="langlabel" for="lang">{#advlink_dlg.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" /> + </td> + </tr> + + <tr> + <td><label id="charsetlabel" for="charset">{#advlink_dlg.encoding}</label></td> + <td><input type="text" id="charset" name="charset" value="" /></td> + </tr> + + <tr> + <td><label id="typelabel" for="type">{#advlink_dlg.mime}</label></td> + <td><input type="text" id="type" name="type" value="" /></td> + </tr> + + <tr> + <td><label id="rellabel" for="rel">{#advlink_dlg.rel}</label></td> + <td><select id="rel" name="rel"> + <option value="">{#not_set}</option> + <option value="lightbox">Lightbox</option> + <option value="alternate">Alternate</option> + <option value="designates">Designates</option> + <option value="stylesheet">Stylesheet</option> + <option value="start">Start</option> + <option value="next">Next</option> + <option value="prev">Prev</option> + <option value="contents">Contents</option> + <option value="index">Index</option> + <option value="glossary">Glossary</option> + <option value="copyright">Copyright</option> + <option value="chapter">Chapter</option> + <option value="subsection">Subsection</option> + <option value="appendix">Appendix</option> + <option value="help">Help</option> + <option value="bookmark">Bookmark</option> + <option value="nofollow">No Follow</option> + <option value="tag">Tag</option> + </select> + </td> + </tr> + + <tr> + <td><label id="revlabel" for="rev">{#advlink_dlg.rev}</label></td> + <td><select id="rev" name="rev"> + <option value="">{#not_set}</option> + <option value="alternate">Alternate</option> + <option value="designates">Designates</option> + <option value="stylesheet">Stylesheet</option> + <option value="start">Start</option> + <option value="next">Next</option> + <option value="prev">Prev</option> + <option value="contents">Contents</option> + <option value="index">Index</option> + <option value="glossary">Glossary</option> + <option value="copyright">Copyright</option> + <option value="chapter">Chapter</option> + <option value="subsection">Subsection</option> + <option value="appendix">Appendix</option> + <option value="help">Help</option> + <option value="bookmark">Bookmark</option> + </select> + </td> + </tr> + + <tr> + <td><label id="tabindexlabel" for="tabindex">{#advlink_dlg.tabindex}</label></td> + <td><input type="text" id="tabindex" name="tabindex" value="" /></td> + </tr> + + <tr> + <td><label id="accesskeylabel" for="accesskey">{#advlink_dlg.accesskey}</label></td> + <td><input type="text" id="accesskey" name="accesskey" value="" /></td> + </tr> + </table> + </fieldset> + </div> + + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#advlink_dlg.event_props}</legend> + + <table border="0" cellpadding="0" cellspacing="4" role="presentation" > + <tr> + <td class="column1"><label for="onfocus">onfocus</label></td> + <td><input id="onfocus" name="onfocus" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onblur">onblur</label></td> + <td><input id="onblur" name="onblur" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onclick">onclick</label></td> + <td><input id="onclick" name="onclick" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="ondblclick">ondblclick</label></td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onmousedown">onmousedown</label></td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onmouseup">onmouseup</label></td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onmouseover">onmouseover</label></td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onmousemove">onmousemove</label></td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onmouseout">onmouseout</label></td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onkeypress">onkeypress</label></td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onkeydown">onkeydown</label></td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onkeyup">onkeyup</label></td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/advlist/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/advlist/editor_plugin.js new file mode 100644 index 0000000..57ecce6 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advlist/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.each;tinymce.create("tinymce.plugins.AdvListPlugin",{init:function(b,c){var d=this;d.editor=b;function e(g){var f=[];a(g.split(/,/),function(h){f.push({title:"advlist."+(h=="default"?"def":h.replace(/-/g,"_")),styles:{listStyleType:h=="default"?"":h}})});return f}d.numlist=b.getParam("advlist_number_styles")||e("default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman");d.bullist=b.getParam("advlist_bullet_styles")||e("default,circle,disc,square");if(tinymce.isIE&&/MSIE [2-7]/.test(navigator.userAgent)){d.isIE7=true}},createControl:function(d,b){var f=this,e,i,g=f.editor;if(d=="numlist"||d=="bullist"){if(f[d][0].title=="advlist.def"){i=f[d][0]}function c(j,l){var k=true;a(l.styles,function(n,m){if(g.dom.getStyle(j,m)!=n){k=false;return false}});return k}function h(){var k,l=g.dom,j=g.selection;k=l.getParent(j.getNode(),"ol,ul");if(!k||k.nodeName==(d=="bullist"?"OL":"UL")||c(k,i)){g.execCommand(d=="bullist"?"InsertUnorderedList":"InsertOrderedList")}if(i){k=l.getParent(j.getNode(),"ol,ul");if(k){l.setStyles(k,i.styles);k.removeAttribute("data-mce-style")}}g.focus()}e=b.createSplitButton(d,{title:"advanced."+d+"_desc","class":"mce_"+d,onclick:function(){h()}});e.onRenderMenu.add(function(j,k){k.onHideMenu.add(function(){if(f.bookmark){g.selection.moveToBookmark(f.bookmark);f.bookmark=0}});k.onShowMenu.add(function(){var n=g.dom,m=n.getParent(g.selection.getNode(),"ol,ul"),l;if(m||i){l=f[d];a(k.items,function(o){var p=true;o.setSelected(0);if(m&&!o.isDisabled()){a(l,function(q){if(q.id==o.id){if(!c(m,q)){p=false;return false}}});if(p){o.setSelected(1)}}});if(!m){k.items[i.id].setSelected(1)}}g.focus();if(tinymce.isIE){f.bookmark=g.selection.getBookmark(1)}});k.add({id:g.dom.uniqueId(),title:"advlist.types","class":"mceMenuItemTitle",titleItem:true}).setDisabled(1);a(f[d],function(l){if(f.isIE7&&l.styles.listStyleType=="lower-greek"){return}l.id=g.dom.uniqueId();k.add({id:l.id,title:l.title,onclick:function(){i=l;h()}})})});return e}},getInfo:function(){return{longname:"Advanced lists",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlist",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("advlist",tinymce.plugins.AdvListPlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/advlist/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/advlist/editor_plugin_src.js new file mode 100644 index 0000000..a8f046b --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/advlist/editor_plugin_src.js @@ -0,0 +1,176 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var each = tinymce.each; + + tinymce.create('tinymce.plugins.AdvListPlugin', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + function buildFormats(str) { + var formats = []; + + each(str.split(/,/), function(type) { + formats.push({ + title : 'advlist.' + (type == 'default' ? 'def' : type.replace(/-/g, '_')), + styles : { + listStyleType : type == 'default' ? '' : type + } + }); + }); + + return formats; + }; + + // Setup number formats from config or default + t.numlist = ed.getParam("advlist_number_styles") || buildFormats("default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman"); + t.bullist = ed.getParam("advlist_bullet_styles") || buildFormats("default,circle,disc,square"); + + if (tinymce.isIE && /MSIE [2-7]/.test(navigator.userAgent)) + t.isIE7 = true; + }, + + createControl: function(name, cm) { + var t = this, btn, format, editor = t.editor; + + if (name == 'numlist' || name == 'bullist') { + // Default to first item if it's a default item + if (t[name][0].title == 'advlist.def') + format = t[name][0]; + + function hasFormat(node, format) { + var state = true; + + each(format.styles, function(value, name) { + // Format doesn't match + if (editor.dom.getStyle(node, name) != value) { + state = false; + return false; + } + }); + + return state; + }; + + function applyListFormat() { + var list, dom = editor.dom, sel = editor.selection; + + // Check for existing list element + list = dom.getParent(sel.getNode(), 'ol,ul'); + + // Switch/add list type if needed + if (!list || list.nodeName == (name == 'bullist' ? 'OL' : 'UL') || hasFormat(list, format)) + editor.execCommand(name == 'bullist' ? 'InsertUnorderedList' : 'InsertOrderedList'); + + // Append styles to new list element + if (format) { + list = dom.getParent(sel.getNode(), 'ol,ul'); + if (list) { + dom.setStyles(list, format.styles); + list.removeAttribute('data-mce-style'); + } + } + + editor.focus(); + }; + + btn = cm.createSplitButton(name, { + title : 'advanced.' + name + '_desc', + 'class' : 'mce_' + name, + onclick : function() { + applyListFormat(); + } + }); + + btn.onRenderMenu.add(function(btn, menu) { + menu.onHideMenu.add(function() { + if (t.bookmark) { + editor.selection.moveToBookmark(t.bookmark); + t.bookmark = 0; + } + }); + + menu.onShowMenu.add(function() { + var dom = editor.dom, list = dom.getParent(editor.selection.getNode(), 'ol,ul'), fmtList; + + if (list || format) { + fmtList = t[name]; + + // Unselect existing items + each(menu.items, function(item) { + var state = true; + + item.setSelected(0); + + if (list && !item.isDisabled()) { + each(fmtList, function(fmt) { + if (fmt.id == item.id) { + if (!hasFormat(list, fmt)) { + state = false; + return false; + } + } + }); + + if (state) + item.setSelected(1); + } + }); + + // Select the current format + if (!list) + menu.items[format.id].setSelected(1); + } + + editor.focus(); + + // IE looses it's selection so store it away and restore it later + if (tinymce.isIE) { + t.bookmark = editor.selection.getBookmark(1); + } + }); + + menu.add({id : editor.dom.uniqueId(), title : 'advlist.types', 'class' : 'mceMenuItemTitle', titleItem: true}).setDisabled(1); + + each(t[name], function(item) { + // IE<8 doesn't support lower-greek, skip it + if (t.isIE7 && item.styles.listStyleType == 'lower-greek') + return; + + item.id = editor.dom.uniqueId(); + + menu.add({id : item.id, title : item.title, onclick : function() { + format = item; + applyListFormat(); + }}); + }); + }); + + return btn; + } + }, + + getInfo : function() { + return { + longname : 'Advanced lists', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlist', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('advlist', tinymce.plugins.AdvListPlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/autolink/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/autolink/editor_plugin.js new file mode 100644 index 0000000..fd293dc --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/autolink/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.AutolinkPlugin",{init:function(a,b){var c=this;if(tinyMCE.isIE){return}a.onKeyDown.add(function(d,f){if(f.keyCode==13){return c.handleEnter(d)}});a.onKeyPress.add(function(d,f){if(f.which==41){return c.handleEclipse(d)}});a.onKeyUp.add(function(d,f){if(f.keyCode==32){return c.handleSpacebar(d)}})},handleEclipse:function(a){this.parseCurrentLine(a,-1,"(",true)},handleSpacebar:function(a){this.parseCurrentLine(a,0,"",true)},handleEnter:function(a){this.parseCurrentLine(a,-1,"",false)},parseCurrentLine:function(i,d,b,g){var a,f,c,n,k,m,h,e,j;a=i.selection.getRng().cloneRange();if(a.startOffset<5){e=a.endContainer.previousSibling;if(e==null){if(a.endContainer.firstChild==null||a.endContainer.firstChild.nextSibling==null){return}e=a.endContainer.firstChild.nextSibling}j=e.length;a.setStart(e,j);a.setEnd(e,j);if(a.endOffset<5){return}f=a.endOffset;n=e}else{n=a.endContainer;if(n.nodeType!=3&&n.firstChild){while(n.nodeType!=3&&n.firstChild){n=n.firstChild}a.setStart(n,0);a.setEnd(n,n.nodeValue.length)}if(a.endOffset==1){f=2}else{f=a.endOffset-1-d}}c=f;do{a.setStart(n,f-2);a.setEnd(n,f-1);f-=1}while(a.toString()!=" "&&a.toString()!=""&&a.toString().charCodeAt(0)!=160&&(f-2)>=0&&a.toString()!=b);if(a.toString()==b||a.toString().charCodeAt(0)==160){a.setStart(n,f);a.setEnd(n,c);f+=1}else{if(a.startOffset==0){a.setStart(n,0);a.setEnd(n,c)}else{a.setStart(n,f);a.setEnd(n,c)}}m=a.toString();h=m.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)(.+)$/i);if(h){if(h[1]=="www."){h[1]="http://www."}k=i.selection.getBookmark();i.selection.setRng(a);tinyMCE.execCommand("createlink",false,h[1]+h[2]);i.selection.moveToBookmark(k);if(tinyMCE.isWebKit){i.selection.collapse(false);var l=Math.min(n.length,c+1);a.setStart(n,l);a.setEnd(n,l);i.selection.setRng(a)}}},getInfo:function(){return{longname:"Autolink",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autolink",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("autolink",tinymce.plugins.AutolinkPlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/autolink/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/autolink/editor_plugin_src.js new file mode 100644 index 0000000..604da8b --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/autolink/editor_plugin_src.js @@ -0,0 +1,172 @@ +/** + * editor_plugin_src.js + * + * Copyright 2011, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.AutolinkPlugin', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + + init : function(ed, url) { + var t = this; + + // Internet Explorer has built-in automatic linking + if (tinyMCE.isIE) + return; + + // Add a key down handler + ed.onKeyDown.add(function(ed, e) { + if (e.keyCode == 13) + return t.handleEnter(ed); + }); + + ed.onKeyPress.add(function(ed, e) { + if (e.which == 41) + return t.handleEclipse(ed); + }); + + // Add a key up handler + ed.onKeyUp.add(function(ed, e) { + if (e.keyCode == 32) + return t.handleSpacebar(ed); + }); + }, + + handleEclipse : function(ed) { + this.parseCurrentLine(ed, -1, '(', true); + }, + + handleSpacebar : function(ed) { + this.parseCurrentLine(ed, 0, '', true); + }, + + handleEnter : function(ed) { + this.parseCurrentLine(ed, -1, '', false); + }, + + parseCurrentLine : function(ed, end_offset, delimiter, goback) { + var r, end, start, endContainer, bookmark, text, matches, prev, len; + + // We need at least five characters to form a URL, + // hence, at minimum, five characters from the beginning of the line. + r = ed.selection.getRng().cloneRange(); + if (r.startOffset < 5) { + // During testing, the caret is placed inbetween two text nodes. + // The previous text node contains the URL. + prev = r.endContainer.previousSibling; + if (prev == null) { + if (r.endContainer.firstChild == null || r.endContainer.firstChild.nextSibling == null) + return; + + prev = r.endContainer.firstChild.nextSibling; + } + len = prev.length; + r.setStart(prev, len); + r.setEnd(prev, len); + + if (r.endOffset < 5) + return; + + end = r.endOffset; + endContainer = prev; + } else { + endContainer = r.endContainer; + + // Get a text node + if (endContainer.nodeType != 3 && endContainer.firstChild) { + while (endContainer.nodeType != 3 && endContainer.firstChild) + endContainer = endContainer.firstChild; + + r.setStart(endContainer, 0); + r.setEnd(endContainer, endContainer.nodeValue.length); + } + + if (r.endOffset == 1) + end = 2; + else + end = r.endOffset - 1 - end_offset; + } + + start = end; + + do + { + // Move the selection one character backwards. + r.setStart(endContainer, end - 2); + r.setEnd(endContainer, end - 1); + end -= 1; + + // Loop until one of the following is found: a blank space, &nbsp;, delimeter, (end-2) >= 0 + } while (r.toString() != ' ' && r.toString() != '' && r.toString().charCodeAt(0) != 160 && (end -2) >= 0 && r.toString() != delimiter); + + if (r.toString() == delimiter || r.toString().charCodeAt(0) == 160) { + r.setStart(endContainer, end); + r.setEnd(endContainer, start); + end += 1; + } else if (r.startOffset == 0) { + r.setStart(endContainer, 0); + r.setEnd(endContainer, start); + } + else { + r.setStart(endContainer, end); + r.setEnd(endContainer, start); + } + + text = r.toString(); + matches = text.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)(.+)$/i); + + if (matches) { + if (matches[1] == 'www.') { + matches[1] = 'http://www.'; + } + + bookmark = ed.selection.getBookmark(); + + ed.selection.setRng(r); + tinyMCE.execCommand('createlink',false, matches[1] + matches[2]); + ed.selection.moveToBookmark(bookmark); + + // TODO: Determine if this is still needed. + if (tinyMCE.isWebKit) { + // move the caret to its original position + ed.selection.collapse(false); + var max = Math.min(endContainer.length, start + 1); + r.setStart(endContainer, max); + r.setEnd(endContainer, max); + ed.selection.setRng(r); + } + } + }, + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Autolink', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autolink', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('autolink', tinymce.plugins.AutolinkPlugin); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/autoresize/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/autoresize/editor_plugin.js new file mode 100644 index 0000000..6c4ff0d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/autoresize/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.AutoResizePlugin",{init:function(a,c){var d=this,e=0;if(a.getParam("fullscreen_is_enabled")){return}function b(){var i=a.getDoc(),f=i.body,k=i.documentElement,h=tinymce.DOM,j=d.autoresize_min_height,g;g=tinymce.isIE?f.scrollHeight:i.body.offsetHeight;if(g>d.autoresize_min_height){j=g}if(d.autoresize_max_height&&g>d.autoresize_max_height){j=d.autoresize_max_height;a.getBody().style.overflowY="auto"}else{a.getBody().style.overflowY="hidden"}if(j!==e){h.setStyle(h.get(a.id+"_ifr"),"height",j+"px");e=j}if(d.throbbing){a.setProgressState(false);a.setProgressState(true)}}d.editor=a;d.autoresize_min_height=parseInt(a.getParam("autoresize_min_height",a.getElement().offsetHeight));d.autoresize_max_height=parseInt(a.getParam("autoresize_max_height",0));a.onInit.add(function(f){f.dom.setStyle(f.getBody(),"paddingBottom",f.getParam("autoresize_bottom_margin",50)+"px")});a.onChange.add(b);a.onSetContent.add(b);a.onPaste.add(b);a.onKeyUp.add(b);a.onPostRender.add(b);if(a.getParam("autoresize_on_init",true)){a.onInit.add(function(g,f){g.setProgressState(true);d.throbbing=true;g.getBody().style.overflowY="hidden"});a.onLoadContent.add(function(g,f){b();setTimeout(function(){b();g.setProgressState(false);d.throbbing=false},1250)})}a.addCommand("mceAutoResize",b)},getInfo:function(){return{longname:"Auto Resize",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autoresize",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("autoresize",tinymce.plugins.AutoResizePlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/autoresize/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/autoresize/editor_plugin_src.js new file mode 100644 index 0000000..7d11341 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/autoresize/editor_plugin_src.js @@ -0,0 +1,137 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + /** + * Auto Resize + * + * This plugin automatically resizes the content area to fit its content height. + * It will retain a minimum height, which is the height of the content area when + * it's initialized. + */ + tinymce.create('tinymce.plugins.AutoResizePlugin', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed, url) { + var t = this, oldSize = 0; + + if (ed.getParam('fullscreen_is_enabled')) + return; + + /** + * This method gets executed each time the editor needs to resize. + */ + function resize() { + var d = ed.getDoc(), b = d.body, de = d.documentElement, DOM = tinymce.DOM, resizeHeight = t.autoresize_min_height, myHeight; + + // Get height differently depending on the browser used + myHeight = tinymce.isIE ? b.scrollHeight : d.body.offsetHeight; + + // Don't make it smaller than the minimum height + if (myHeight > t.autoresize_min_height) + resizeHeight = myHeight; + + // If a maximum height has been defined don't exceed this height + if (t.autoresize_max_height && myHeight > t.autoresize_max_height) { + resizeHeight = t.autoresize_max_height; + ed.getBody().style.overflowY = "auto"; + } else + ed.getBody().style.overflowY = "hidden"; + + // Resize content element + if (resizeHeight !== oldSize) { + DOM.setStyle(DOM.get(ed.id + '_ifr'), 'height', resizeHeight + 'px'); + oldSize = resizeHeight; + } + + // if we're throbbing, we'll re-throb to match the new size + if (t.throbbing) { + ed.setProgressState(false); + ed.setProgressState(true); + } + }; + + t.editor = ed; + + // Define minimum height + t.autoresize_min_height = parseInt( ed.getParam('autoresize_min_height', ed.getElement().offsetHeight) ); + + // Define maximum height + t.autoresize_max_height = parseInt( ed.getParam('autoresize_max_height', 0) ); + + // Add padding at the bottom for better UX + ed.onInit.add(function(ed){ + ed.dom.setStyle(ed.getBody(), 'paddingBottom', ed.getParam('autoresize_bottom_margin', 50) + 'px'); + }); + + // Add appropriate listeners for resizing content area + ed.onChange.add(resize); + ed.onSetContent.add(resize); + ed.onPaste.add(resize); + ed.onKeyUp.add(resize); + ed.onPostRender.add(resize); + + if (ed.getParam('autoresize_on_init', true)) { + // Things to do when the editor is ready + ed.onInit.add(function(ed, l) { + // Show throbber until content area is resized properly + ed.setProgressState(true); + t.throbbing = true; + + // Hide scrollbars + ed.getBody().style.overflowY = "hidden"; + }); + + ed.onLoadContent.add(function(ed, l) { + resize(); + + // Because the content area resizes when its content CSS loads, + // and we can't easily add a listener to its onload event, + // we'll just trigger a resize after a short loading period + setTimeout(function() { + resize(); + + // Disable throbber + ed.setProgressState(false); + t.throbbing = false; + }, 1250); + }); + } + + // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample'); + ed.addCommand('mceAutoResize', resize); + }, + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Auto Resize', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autoresize', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('autoresize', tinymce.plugins.AutoResizePlugin); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/autosave/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/autosave/editor_plugin.js new file mode 100644 index 0000000..f7d0576 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/autosave/editor_plugin.js @@ -0,0 +1 @@ +(function(e){var c="autosave",g="restoredraft",b=true,f,d,a=e.util.Dispatcher;e.create("tinymce.plugins.AutoSave",{init:function(i,j){var h=this,l=i.settings;h.editor=i;function k(n){var m={s:1000,m:60000};n=/^(\d+)([ms]?)$/.exec(""+n);return(n[2]?m[n[2]]:1)*parseInt(n)}e.each({ask_before_unload:b,interval:"30s",retention:"20m",minlength:50},function(n,m){m=c+"_"+m;if(l[m]===f){l[m]=n}});l.autosave_interval=k(l.autosave_interval);l.autosave_retention=k(l.autosave_retention);i.addButton(g,{title:c+".restore_content",onclick:function(){if(i.getContent({draft:true}).replace(/\s|&nbsp;|<\/?p[^>]*>|<br[^>]*>/gi,"").length>0){i.windowManager.confirm(c+".warning_message",function(m){if(m){h.restoreDraft()}})}else{h.restoreDraft()}}});i.onNodeChange.add(function(){var m=i.controlManager;if(m.get(g)){m.setDisabled(g,!h.hasDraft())}});i.onInit.add(function(){if(i.controlManager.get(g)){h.setupStorage(i);setInterval(function(){h.storeDraft();i.nodeChanged()},l.autosave_interval)}});h.onStoreDraft=new a(h);h.onRestoreDraft=new a(h);h.onRemoveDraft=new a(h);if(!d){window.onbeforeunload=e.plugins.AutoSave._beforeUnloadHandler;d=b}},getInfo:function(){return{longname:"Auto save",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave",version:e.majorVersion+"."+e.minorVersion}},getExpDate:function(){return new Date(new Date().getTime()+this.editor.settings.autosave_retention).toUTCString()},setupStorage:function(i){var h=this,k=c+"_test",j="OK";h.key=c+i.id;e.each([function(){if(localStorage){localStorage.setItem(k,j);if(localStorage.getItem(k)===j){localStorage.removeItem(k);return localStorage}}},function(){if(sessionStorage){sessionStorage.setItem(k,j);if(sessionStorage.getItem(k)===j){sessionStorage.removeItem(k);return sessionStorage}}},function(){if(e.isIE){i.getElement().style.behavior="url('#default#userData')";return{autoExpires:b,setItem:function(l,n){var m=i.getElement();m.setAttribute(l,n);m.expires=h.getExpDate();try{m.save("TinyMCE")}catch(o){}},getItem:function(l){var m=i.getElement();try{m.load("TinyMCE");return m.getAttribute(l)}catch(n){return null}},removeItem:function(l){i.getElement().removeAttribute(l)}}}},],function(l){try{h.storage=l();if(h.storage){return false}}catch(m){}})},storeDraft:function(){var i=this,l=i.storage,j=i.editor,h,k;if(l){if(!l.getItem(i.key)&&!j.isDirty()){return}k=j.getContent({draft:true});if(k.length>j.settings.autosave_minlength){h=i.getExpDate();if(!i.storage.autoExpires){i.storage.setItem(i.key+"_expires",h)}i.storage.setItem(i.key,k);i.onStoreDraft.dispatch(i,{expires:h,content:k})}}},restoreDraft:function(){var h=this,j=h.storage,i;if(j){i=j.getItem(h.key);if(i){h.editor.setContent(i);h.onRestoreDraft.dispatch(h,{content:i})}}},hasDraft:function(){var h=this,k=h.storage,i,j;if(k){j=!!k.getItem(h.key);if(j){if(!h.storage.autoExpires){i=new Date(k.getItem(h.key+"_expires"));if(new Date().getTime()<i.getTime()){return b}h.removeDraft()}else{return b}}}return false},removeDraft:function(){var h=this,k=h.storage,i=h.key,j;if(k){j=k.getItem(i);k.removeItem(i);k.removeItem(i+"_expires");if(j){h.onRemoveDraft.dispatch(h,{content:j})}}},"static":{_beforeUnloadHandler:function(h){var i;e.each(tinyMCE.editors,function(j){if(j.plugins.autosave){j.plugins.autosave.storeDraft()}if(j.getParam("fullscreen_is_enabled")){return}if(!i&&j.isDirty()&&j.getParam("autosave_ask_before_unload")){i=j.getLang("autosave.unload_msg")}});return i}}});e.PluginManager.add("autosave",e.plugins.AutoSave)})(tinymce); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/autosave/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/autosave/editor_plugin_src.js new file mode 100644 index 0000000..8311483 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/autosave/editor_plugin_src.js @@ -0,0 +1,431 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + * + * Adds auto-save capability to the TinyMCE text editor to rescue content + * inadvertently lost. This plugin was originally developed by Speednet + * and that project can be found here: http://code.google.com/p/tinyautosave/ + * + * TECHNOLOGY DISCUSSION: + * + * The plugin attempts to use the most advanced features available in the current browser to save + * as much content as possible. There are a total of four different methods used to autosave the + * content. In order of preference, they are: + * + * 1. localStorage - A new feature of HTML 5, localStorage can store megabytes of data per domain + * on the client computer. Data stored in the localStorage area has no expiration date, so we must + * manage expiring the data ourselves. localStorage is fully supported by IE8, and it is supposed + * to be working in Firefox 3 and Safari 3.2, but in reality is is flaky in those browsers. As + * HTML 5 gets wider support, the AutoSave plugin will use it automatically. In Windows Vista/7, + * localStorage is stored in the following folder: + * C:\Users\[username]\AppData\Local\Microsoft\Internet Explorer\DOMStore\[tempFolder] + * + * 2. sessionStorage - A new feature of HTML 5, sessionStorage works similarly to localStorage, + * except it is designed to expire after a certain amount of time. Because the specification + * around expiration date/time is very loosely-described, it is preferrable to use locaStorage and + * manage the expiration ourselves. sessionStorage has similar storage characteristics to + * localStorage, although it seems to have better support by Firefox 3 at the moment. (That will + * certainly change as Firefox continues getting better at HTML 5 adoption.) + * + * 3. UserData - A very under-exploited feature of Microsoft Internet Explorer, UserData is a + * way to store up to 128K of data per "document", or up to 1MB of data per domain, on the client + * computer. The feature is available for IE 5+, which makes it available for every version of IE + * supported by TinyMCE. The content is persistent across browser restarts and expires on the + * date/time specified, just like a cookie. However, the data is not cleared when the user clears + * cookies on the browser, which makes it well-suited for rescuing autosaved content. UserData, + * like other Microsoft IE browser technologies, is implemented as a behavior attached to a + * specific DOM object, so in this case we attach the behavior to the same DOM element that the + * TinyMCE editor instance is attached to. + */ + +(function(tinymce) { + // Setup constants to help the compressor to reduce script size + var PLUGIN_NAME = 'autosave', + RESTORE_DRAFT = 'restoredraft', + TRUE = true, + undefined, + unloadHandlerAdded, + Dispatcher = tinymce.util.Dispatcher; + + /** + * This plugin adds auto-save capability to the TinyMCE text editor to rescue content + * inadvertently lost. By using localStorage. + * + * @class tinymce.plugins.AutoSave + */ + tinymce.create('tinymce.plugins.AutoSave', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @method init + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed, url) { + var self = this, settings = ed.settings; + + self.editor = ed; + + // Parses the specified time string into a milisecond number 10m, 10s etc. + function parseTime(time) { + var multipels = { + s : 1000, + m : 60000 + }; + + time = /^(\d+)([ms]?)$/.exec('' + time); + + return (time[2] ? multipels[time[2]] : 1) * parseInt(time); + }; + + // Default config + tinymce.each({ + ask_before_unload : TRUE, + interval : '30s', + retention : '20m', + minlength : 50 + }, function(value, key) { + key = PLUGIN_NAME + '_' + key; + + if (settings[key] === undefined) + settings[key] = value; + }); + + // Parse times + settings.autosave_interval = parseTime(settings.autosave_interval); + settings.autosave_retention = parseTime(settings.autosave_retention); + + // Register restore button + ed.addButton(RESTORE_DRAFT, { + title : PLUGIN_NAME + ".restore_content", + onclick : function() { + if (ed.getContent({draft: true}).replace(/\s|&nbsp;|<\/?p[^>]*>|<br[^>]*>/gi, "").length > 0) { + // Show confirm dialog if the editor isn't empty + ed.windowManager.confirm( + PLUGIN_NAME + ".warning_message", + function(ok) { + if (ok) + self.restoreDraft(); + } + ); + } else + self.restoreDraft(); + } + }); + + // Enable/disable restoredraft button depending on if there is a draft stored or not + ed.onNodeChange.add(function() { + var controlManager = ed.controlManager; + + if (controlManager.get(RESTORE_DRAFT)) + controlManager.setDisabled(RESTORE_DRAFT, !self.hasDraft()); + }); + + ed.onInit.add(function() { + // Check if the user added the restore button, then setup auto storage logic + if (ed.controlManager.get(RESTORE_DRAFT)) { + // Setup storage engine + self.setupStorage(ed); + + // Auto save contents each interval time + setInterval(function() { + self.storeDraft(); + ed.nodeChanged(); + }, settings.autosave_interval); + } + }); + + /** + * This event gets fired when a draft is stored to local storage. + * + * @event onStoreDraft + * @param {tinymce.plugins.AutoSave} sender Plugin instance sending the event. + * @param {Object} draft Draft object containing the HTML contents of the editor. + */ + self.onStoreDraft = new Dispatcher(self); + + /** + * This event gets fired when a draft is restored from local storage. + * + * @event onStoreDraft + * @param {tinymce.plugins.AutoSave} sender Plugin instance sending the event. + * @param {Object} draft Draft object containing the HTML contents of the editor. + */ + self.onRestoreDraft = new Dispatcher(self); + + /** + * This event gets fired when a draft removed/expired. + * + * @event onRemoveDraft + * @param {tinymce.plugins.AutoSave} sender Plugin instance sending the event. + * @param {Object} draft Draft object containing the HTML contents of the editor. + */ + self.onRemoveDraft = new Dispatcher(self); + + // Add ask before unload dialog only add one unload handler + if (!unloadHandlerAdded) { + window.onbeforeunload = tinymce.plugins.AutoSave._beforeUnloadHandler; + unloadHandlerAdded = TRUE; + } + }, + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @method getInfo + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Auto save', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + /** + * Returns an expiration date UTC string. + * + * @method getExpDate + * @return {String} Expiration date UTC string. + */ + getExpDate : function() { + return new Date( + new Date().getTime() + this.editor.settings.autosave_retention + ).toUTCString(); + }, + + /** + * This method will setup the storage engine. If the browser has support for it. + * + * @method setupStorage + */ + setupStorage : function(ed) { + var self = this, testKey = PLUGIN_NAME + '_test', testVal = "OK"; + + self.key = PLUGIN_NAME + ed.id; + + // Loop though each storage engine type until we find one that works + tinymce.each([ + function() { + // Try HTML5 Local Storage + if (localStorage) { + localStorage.setItem(testKey, testVal); + + if (localStorage.getItem(testKey) === testVal) { + localStorage.removeItem(testKey); + + return localStorage; + } + } + }, + + function() { + // Try HTML5 Session Storage + if (sessionStorage) { + sessionStorage.setItem(testKey, testVal); + + if (sessionStorage.getItem(testKey) === testVal) { + sessionStorage.removeItem(testKey); + + return sessionStorage; + } + } + }, + + function() { + // Try IE userData + if (tinymce.isIE) { + ed.getElement().style.behavior = "url('#default#userData')"; + + // Fake localStorage on old IE + return { + autoExpires : TRUE, + + setItem : function(key, value) { + var userDataElement = ed.getElement(); + + userDataElement.setAttribute(key, value); + userDataElement.expires = self.getExpDate(); + + try { + userDataElement.save("TinyMCE"); + } catch (e) { + // Ignore, saving might fail if "Userdata Persistence" is disabled in IE + } + }, + + getItem : function(key) { + var userDataElement = ed.getElement(); + + try { + userDataElement.load("TinyMCE"); + return userDataElement.getAttribute(key); + } catch (e) { + // Ignore, loading might fail if "Userdata Persistence" is disabled in IE + return null; + } + }, + + removeItem : function(key) { + ed.getElement().removeAttribute(key); + } + }; + } + }, + ], function(setup) { + // Try executing each function to find a suitable storage engine + try { + self.storage = setup(); + + if (self.storage) + return false; + } catch (e) { + // Ignore + } + }); + }, + + /** + * This method will store the current contents in the the storage engine. + * + * @method storeDraft + */ + storeDraft : function() { + var self = this, storage = self.storage, editor = self.editor, expires, content; + + // Is the contents dirty + if (storage) { + // If there is no existing key and the contents hasn't been changed since + // it's original value then there is no point in saving a draft + if (!storage.getItem(self.key) && !editor.isDirty()) + return; + + // Store contents if the contents if longer than the minlength of characters + content = editor.getContent({draft: true}); + if (content.length > editor.settings.autosave_minlength) { + expires = self.getExpDate(); + + // Store expiration date if needed IE userData has auto expire built in + if (!self.storage.autoExpires) + self.storage.setItem(self.key + "_expires", expires); + + self.storage.setItem(self.key, content); + self.onStoreDraft.dispatch(self, { + expires : expires, + content : content + }); + } + } + }, + + /** + * This method will restore the contents from the storage engine back to the editor. + * + * @method restoreDraft + */ + restoreDraft : function() { + var self = this, storage = self.storage, content; + + if (storage) { + content = storage.getItem(self.key); + + if (content) { + self.editor.setContent(content); + self.onRestoreDraft.dispatch(self, { + content : content + }); + } + } + }, + + /** + * This method will return true/false if there is a local storage draft available. + * + * @method hasDraft + * @return {boolean} true/false state if there is a local draft. + */ + hasDraft : function() { + var self = this, storage = self.storage, expDate, exists; + + if (storage) { + // Does the item exist at all + exists = !!storage.getItem(self.key); + if (exists) { + // Storage needs autoexpire + if (!self.storage.autoExpires) { + expDate = new Date(storage.getItem(self.key + "_expires")); + + // Contents hasn't expired + if (new Date().getTime() < expDate.getTime()) + return TRUE; + + // Remove it if it has + self.removeDraft(); + } else + return TRUE; + } + } + + return false; + }, + + /** + * Removes the currently stored draft. + * + * @method removeDraft + */ + removeDraft : function() { + var self = this, storage = self.storage, key = self.key, content; + + if (storage) { + // Get current contents and remove the existing draft + content = storage.getItem(key); + storage.removeItem(key); + storage.removeItem(key + "_expires"); + + // Dispatch remove event if we had any contents + if (content) { + self.onRemoveDraft.dispatch(self, { + content : content + }); + } + } + }, + + "static" : { + // Internal unload handler will be called before the page is unloaded + _beforeUnloadHandler : function(e) { + var msg; + + tinymce.each(tinyMCE.editors, function(ed) { + // Store a draft for each editor instance + if (ed.plugins.autosave) + ed.plugins.autosave.storeDraft(); + + // Never ask in fullscreen mode + if (ed.getParam("fullscreen_is_enabled")) + return; + + // Setup a return message if the editor is dirty + if (!msg && ed.isDirty() && ed.getParam("autosave_ask_before_unload")) + msg = ed.getLang("autosave.unload_msg"); + }); + + return msg; + } + } + }); + + tinymce.PluginManager.add('autosave', tinymce.plugins.AutoSave); +})(tinymce); diff --git a/src/core/static/js/tiny_mce/plugins/autosave/langs/en.js b/src/core/static/js/tiny_mce/plugins/autosave/langs/en.js new file mode 100644 index 0000000..fce6bd3 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/autosave/langs/en.js @@ -0,0 +1,4 @@ +tinyMCE.addI18n('en.autosave',{ +restore_content: "Restore auto-saved content", +warning_message: "If you restore the saved content, you will lose all the content that is currently in the editor.\n\nAre you sure you want to restore the saved content?" +}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/bbcode/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/bbcode/editor_plugin.js new file mode 100644 index 0000000..8f8821f --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/bbcode/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(a,b){var d=this,c=a.getParam("bbcode_dialect","punbb").toLowerCase();a.onBeforeSetContent.add(function(e,f){f.content=d["_"+c+"_bbcode2html"](f.content)});a.onPostProcess.add(function(e,f){if(f.set){f.content=d["_"+c+"_bbcode2html"](f.content)}if(f.get){f.content=d["_"+c+"_html2bbcode"](f.content)}})},getInfo:function(){return{longname:"BBCode Plugin",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_punbb_html2bbcode:function(a){a=tinymce.trim(a);function b(c,d){a=a.replace(c,d)}b(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");b(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");b(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");b(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");b(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");b(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]");b(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]");b(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]");b(/<font>(.*?)<\/font>/gi,"$1");b(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]");b(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]");b(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]");b(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]");b(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]");b(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]");b(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]");b(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]");b(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]");b(/<\/(strong|b)>/gi,"[/b]");b(/<(strong|b)>/gi,"[b]");b(/<\/(em|i)>/gi,"[/i]");b(/<(em|i)>/gi,"[i]");b(/<\/u>/gi,"[/u]");b(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]");b(/<u>/gi,"[u]");b(/<blockquote[^>]*>/gi,"[quote]");b(/<\/blockquote>/gi,"[/quote]");b(/<br \/>/gi,"\n");b(/<br\/>/gi,"\n");b(/<br>/gi,"\n");b(/<p>/gi,"");b(/<\/p>/gi,"\n");b(/&nbsp;|\u00a0/gi," ");b(/&quot;/gi,'"');b(/&lt;/gi,"<");b(/&gt;/gi,">");b(/&amp;/gi,"&");return a},_punbb_bbcode2html:function(a){a=tinymce.trim(a);function b(c,d){a=a.replace(c,d)}b(/\n/gi,"<br />");b(/\[b\]/gi,"<strong>");b(/\[\/b\]/gi,"</strong>");b(/\[i\]/gi,"<em>");b(/\[\/i\]/gi,"</em>");b(/\[u\]/gi,"<u>");b(/\[\/u\]/gi,"</u>");b(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'<a href="$1">$2</a>');b(/\[url\](.*?)\[\/url\]/gi,'<a href="$1">$1</a>');b(/\[img\](.*?)\[\/img\]/gi,'<img src="$1" />');b(/\[color=(.*?)\](.*?)\[\/color\]/gi,'<font color="$1">$2</font>');b(/\[code\](.*?)\[\/code\]/gi,'<span class="codeStyle">$1</span>&nbsp;');b(/\[quote.*?\](.*?)\[\/quote\]/gi,'<span class="quoteStyle">$1</span>&nbsp;');return a}});tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/bbcode/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/bbcode/editor_plugin_src.js new file mode 100644 index 0000000..4e7eb33 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/bbcode/editor_plugin_src.js @@ -0,0 +1,120 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.BBCodePlugin', { + init : function(ed, url) { + var t = this, dialect = ed.getParam('bbcode_dialect', 'punbb').toLowerCase(); + + ed.onBeforeSetContent.add(function(ed, o) { + o.content = t['_' + dialect + '_bbcode2html'](o.content); + }); + + ed.onPostProcess.add(function(ed, o) { + if (o.set) + o.content = t['_' + dialect + '_bbcode2html'](o.content); + + if (o.get) + o.content = t['_' + dialect + '_html2bbcode'](o.content); + }); + }, + + getInfo : function() { + return { + longname : 'BBCode Plugin', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + // HTML -> BBCode in PunBB dialect + _punbb_html2bbcode : function(s) { + s = tinymce.trim(s); + + function rep(re, str) { + s = s.replace(re, str); + }; + + // example: <strong> to [b] + rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]"); + rep(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"); + rep(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"); + rep(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"); + rep(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"); + rep(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]"); + rep(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]"); + rep(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]"); + rep(/<font>(.*?)<\/font>/gi,"$1"); + rep(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]"); + rep(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]"); + rep(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]"); + rep(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"); + rep(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"); + rep(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"); + rep(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"); + rep(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"); + rep(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"); + rep(/<\/(strong|b)>/gi,"[/b]"); + rep(/<(strong|b)>/gi,"[b]"); + rep(/<\/(em|i)>/gi,"[/i]"); + rep(/<(em|i)>/gi,"[i]"); + rep(/<\/u>/gi,"[/u]"); + rep(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]"); + rep(/<u>/gi,"[u]"); + rep(/<blockquote[^>]*>/gi,"[quote]"); + rep(/<\/blockquote>/gi,"[/quote]"); + rep(/<br \/>/gi,"\n"); + rep(/<br\/>/gi,"\n"); + rep(/<br>/gi,"\n"); + rep(/<p>/gi,""); + rep(/<\/p>/gi,"\n"); + rep(/&nbsp;|\u00a0/gi," "); + rep(/&quot;/gi,"\""); + rep(/&lt;/gi,"<"); + rep(/&gt;/gi,">"); + rep(/&amp;/gi,"&"); + + return s; + }, + + // BBCode -> HTML from PunBB dialect + _punbb_bbcode2html : function(s) { + s = tinymce.trim(s); + + function rep(re, str) { + s = s.replace(re, str); + }; + + // example: [b] to <strong> + rep(/\n/gi,"<br />"); + rep(/\[b\]/gi,"<strong>"); + rep(/\[\/b\]/gi,"</strong>"); + rep(/\[i\]/gi,"<em>"); + rep(/\[\/i\]/gi,"</em>"); + rep(/\[u\]/gi,"<u>"); + rep(/\[\/u\]/gi,"</u>"); + rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>"); + rep(/\[url\](.*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>"); + rep(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />"); + rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"<font color=\"$1\">$2</font>"); + rep(/\[code\](.*?)\[\/code\]/gi,"<span class=\"codeStyle\">$1</span>&nbsp;"); + rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"<span class=\"quoteStyle\">$1</span>&nbsp;"); + + return s; + } + }); + + // Register plugin + tinymce.PluginManager.add('bbcode', tinymce.plugins.BBCodePlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/contextmenu/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/contextmenu/editor_plugin.js new file mode 100644 index 0000000..af7ae54 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/contextmenu/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.dom.Event,c=tinymce.each,b=tinymce.DOM;tinymce.create("tinymce.plugins.ContextMenu",{init:function(e){var h=this,f,d,i;h.editor=e;d=e.settings.contextmenu_never_use_native;h.onContextMenu=new tinymce.util.Dispatcher(this);f=e.onContextMenu.add(function(j,k){if((i!==0?i:k.ctrlKey)&&!d){return}a.cancel(k);if(k.target.nodeName=="IMG"){j.selection.select(k.target)}h._getMenu(j).showMenu(k.clientX||k.pageX,k.clientY||k.pageY);a.add(j.getDoc(),"click",function(l){g(j,l)});j.nodeChanged()});e.onRemove.add(function(){if(h._menu){h._menu.removeAll()}});function g(j,k){i=0;if(k&&k.button==2){i=k.ctrlKey;return}if(h._menu){h._menu.removeAll();h._menu.destroy();a.remove(j.getDoc(),"click",g)}}e.onMouseDown.add(g);e.onKeyDown.add(g);e.onKeyDown.add(function(j,k){if(k.shiftKey&&!k.ctrlKey&&!k.altKey&&k.keyCode===121){a.cancel(k);f(j,k)}})},getInfo:function(){return{longname:"Contextmenu",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/contextmenu",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_getMenu:function(e){var g=this,d=g._menu,j=e.selection,f=j.isCollapsed(),h=j.getNode()||e.getBody(),i,k;if(d){d.removeAll();d.destroy()}k=b.getPos(e.getContentAreaContainer());d=e.controlManager.createDropMenu("contextmenu",{offset_x:k.x+e.getParam("contextmenu_offset_x",0),offset_y:k.y+e.getParam("contextmenu_offset_y",0),constrain:1,keyboard_focus:true});g._menu=d;d.add({title:"advanced.cut_desc",icon:"cut",cmd:"Cut"}).setDisabled(f);d.add({title:"advanced.copy_desc",icon:"copy",cmd:"Copy"}).setDisabled(f);d.add({title:"advanced.paste_desc",icon:"paste",cmd:"Paste"});if((h.nodeName=="A"&&!e.dom.getAttrib(h,"name"))||!f){d.addSeparator();d.add({title:"advanced.link_desc",icon:"link",cmd:e.plugins.advlink?"mceAdvLink":"mceLink",ui:true});d.add({title:"advanced.unlink_desc",icon:"unlink",cmd:"UnLink"})}d.addSeparator();d.add({title:"advanced.image_desc",icon:"image",cmd:e.plugins.advimage?"mceAdvImage":"mceImage",ui:true});d.addSeparator();i=d.addMenu({title:"contextmenu.align"});i.add({title:"contextmenu.left",icon:"justifyleft",cmd:"JustifyLeft"});i.add({title:"contextmenu.center",icon:"justifycenter",cmd:"JustifyCenter"});i.add({title:"contextmenu.right",icon:"justifyright",cmd:"JustifyRight"});i.add({title:"contextmenu.full",icon:"justifyfull",cmd:"JustifyFull"});g.onContextMenu.dispatch(g,d,h,f);return d}});tinymce.PluginManager.add("contextmenu",tinymce.plugins.ContextMenu)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/contextmenu/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/contextmenu/editor_plugin_src.js new file mode 100644 index 0000000..956fbea --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/contextmenu/editor_plugin_src.js @@ -0,0 +1,160 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var Event = tinymce.dom.Event, each = tinymce.each, DOM = tinymce.DOM; + + /** + * This plugin a context menu to TinyMCE editor instances. + * + * @class tinymce.plugins.ContextMenu + */ + tinymce.create('tinymce.plugins.ContextMenu', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @method init + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed) { + var t = this, showMenu, contextmenuNeverUseNative, realCtrlKey; + + t.editor = ed; + + contextmenuNeverUseNative = ed.settings.contextmenu_never_use_native; + + /** + * This event gets fired when the context menu is shown. + * + * @event onContextMenu + * @param {tinymce.plugins.ContextMenu} sender Plugin instance sending the event. + * @param {tinymce.ui.DropMenu} menu Drop down menu to fill with more items if needed. + */ + t.onContextMenu = new tinymce.util.Dispatcher(this); + + showMenu = ed.onContextMenu.add(function(ed, e) { + // Block TinyMCE menu on ctrlKey and work around Safari issue + if ((realCtrlKey !== 0 ? realCtrlKey : e.ctrlKey) && !contextmenuNeverUseNative) + return; + + Event.cancel(e); + + // Select the image if it's clicked. WebKit would other wise expand the selection + if (e.target.nodeName == 'IMG') + ed.selection.select(e.target); + + t._getMenu(ed).showMenu(e.clientX || e.pageX, e.clientY || e.pageY); + Event.add(ed.getDoc(), 'click', function(e) { + hide(ed, e); + }); + + ed.nodeChanged(); + }); + + ed.onRemove.add(function() { + if (t._menu) + t._menu.removeAll(); + }); + + function hide(ed, e) { + realCtrlKey = 0; + + // Since the contextmenu event moves + // the selection we need to store it away + if (e && e.button == 2) { + realCtrlKey = e.ctrlKey; + return; + } + + if (t._menu) { + t._menu.removeAll(); + t._menu.destroy(); + Event.remove(ed.getDoc(), 'click', hide); + } + }; + + ed.onMouseDown.add(hide); + ed.onKeyDown.add(hide); + ed.onKeyDown.add(function(ed, e) { + if (e.shiftKey && !e.ctrlKey && !e.altKey && e.keyCode === 121) { + Event.cancel(e); + showMenu(ed, e); + } + }); + }, + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @method getInfo + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Contextmenu', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/contextmenu', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + _getMenu : function(ed) { + var t = this, m = t._menu, se = ed.selection, col = se.isCollapsed(), el = se.getNode() || ed.getBody(), am, p; + + if (m) { + m.removeAll(); + m.destroy(); + } + + p = DOM.getPos(ed.getContentAreaContainer()); + + m = ed.controlManager.createDropMenu('contextmenu', { + offset_x : p.x + ed.getParam('contextmenu_offset_x', 0), + offset_y : p.y + ed.getParam('contextmenu_offset_y', 0), + constrain : 1, + keyboard_focus: true + }); + + t._menu = m; + + m.add({title : 'advanced.cut_desc', icon : 'cut', cmd : 'Cut'}).setDisabled(col); + m.add({title : 'advanced.copy_desc', icon : 'copy', cmd : 'Copy'}).setDisabled(col); + m.add({title : 'advanced.paste_desc', icon : 'paste', cmd : 'Paste'}); + + if ((el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) || !col) { + m.addSeparator(); + m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true}); + m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'}); + } + + m.addSeparator(); + m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true}); + + m.addSeparator(); + am = m.addMenu({title : 'contextmenu.align'}); + am.add({title : 'contextmenu.left', icon : 'justifyleft', cmd : 'JustifyLeft'}); + am.add({title : 'contextmenu.center', icon : 'justifycenter', cmd : 'JustifyCenter'}); + am.add({title : 'contextmenu.right', icon : 'justifyright', cmd : 'JustifyRight'}); + am.add({title : 'contextmenu.full', icon : 'justifyfull', cmd : 'JustifyFull'}); + + t.onContextMenu.dispatch(t, m, el, col); + + return m; + } + }); + + // Register plugin + tinymce.PluginManager.add('contextmenu', tinymce.plugins.ContextMenu); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/directionality/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/directionality/editor_plugin.js new file mode 100644 index 0000000..bce8e73 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/directionality/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.Directionality",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceDirectionLTR",function(){var d=a.dom.getParent(a.selection.getNode(),a.dom.isBlock);if(d){if(a.dom.getAttrib(d,"dir")!="ltr"){a.dom.setAttrib(d,"dir","ltr")}else{a.dom.setAttrib(d,"dir","")}}a.nodeChanged()});a.addCommand("mceDirectionRTL",function(){var d=a.dom.getParent(a.selection.getNode(),a.dom.isBlock);if(d){if(a.dom.getAttrib(d,"dir")!="rtl"){a.dom.setAttrib(d,"dir","rtl")}else{a.dom.setAttrib(d,"dir","")}}a.nodeChanged()});a.addButton("ltr",{title:"directionality.ltr_desc",cmd:"mceDirectionLTR"});a.addButton("rtl",{title:"directionality.rtl_desc",cmd:"mceDirectionRTL"});a.onNodeChange.add(c._nodeChange,c)},getInfo:function(){return{longname:"Directionality",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_nodeChange:function(b,a,e){var d=b.dom,c;e=d.getParent(e,d.isBlock);if(!e){a.setDisabled("ltr",1);a.setDisabled("rtl",1);return}c=d.getAttrib(e,"dir");a.setActive("ltr",c=="ltr");a.setDisabled("ltr",0);a.setActive("rtl",c=="rtl");a.setDisabled("rtl",0)}});tinymce.PluginManager.add("directionality",tinymce.plugins.Directionality)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/directionality/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/directionality/editor_plugin_src.js new file mode 100644 index 0000000..4444959 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/directionality/editor_plugin_src.js @@ -0,0 +1,82 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.Directionality', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + ed.addCommand('mceDirectionLTR', function() { + var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock); + + if (e) { + if (ed.dom.getAttrib(e, "dir") != "ltr") + ed.dom.setAttrib(e, "dir", "ltr"); + else + ed.dom.setAttrib(e, "dir", ""); + } + + ed.nodeChanged(); + }); + + ed.addCommand('mceDirectionRTL', function() { + var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock); + + if (e) { + if (ed.dom.getAttrib(e, "dir") != "rtl") + ed.dom.setAttrib(e, "dir", "rtl"); + else + ed.dom.setAttrib(e, "dir", ""); + } + + ed.nodeChanged(); + }); + + ed.addButton('ltr', {title : 'directionality.ltr_desc', cmd : 'mceDirectionLTR'}); + ed.addButton('rtl', {title : 'directionality.rtl_desc', cmd : 'mceDirectionRTL'}); + + ed.onNodeChange.add(t._nodeChange, t); + }, + + getInfo : function() { + return { + longname : 'Directionality', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + _nodeChange : function(ed, cm, n) { + var dom = ed.dom, dir; + + n = dom.getParent(n, dom.isBlock); + if (!n) { + cm.setDisabled('ltr', 1); + cm.setDisabled('rtl', 1); + return; + } + + dir = dom.getAttrib(n, 'dir'); + cm.setActive('ltr', dir == "ltr"); + cm.setDisabled('ltr', 0); + cm.setActive('rtl', dir == "rtl"); + cm.setDisabled('rtl', 0); + } + }); + + // Register plugin + tinymce.PluginManager.add('directionality', tinymce.plugins.Directionality); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/emotions/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/emotions/editor_plugin.js new file mode 100644 index 0000000..dbdd8ff --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/emotions/editor_plugin.js @@ -0,0 +1 @@ +(function(a){a.create("tinymce.plugins.EmotionsPlugin",{init:function(b,c){b.addCommand("mceEmotion",function(){b.windowManager.open({file:c+"/emotions.htm",width:250+parseInt(b.getLang("emotions.delta_width",0)),height:160+parseInt(b.getLang("emotions.delta_height",0)),inline:1},{plugin_url:c})});b.addButton("emotions",{title:"emotions.emotions_desc",cmd:"mceEmotion"})},getInfo:function(){return{longname:"Emotions",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/emotions",version:a.majorVersion+"."+a.minorVersion}}});a.PluginManager.add("emotions",a.plugins.EmotionsPlugin)})(tinymce); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/emotions/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/emotions/editor_plugin_src.js new file mode 100644 index 0000000..71d5416 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/emotions/editor_plugin_src.js @@ -0,0 +1,43 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function(tinymce) { + tinymce.create('tinymce.plugins.EmotionsPlugin', { + init : function(ed, url) { + // Register commands + ed.addCommand('mceEmotion', function() { + ed.windowManager.open({ + file : url + '/emotions.htm', + width : 250 + parseInt(ed.getLang('emotions.delta_width', 0)), + height : 160 + parseInt(ed.getLang('emotions.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('emotions', {title : 'emotions.emotions_desc', cmd : 'mceEmotion'}); + }, + + getInfo : function() { + return { + longname : 'Emotions', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/emotions', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('emotions', tinymce.plugins.EmotionsPlugin); +})(tinymce); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/emotions/emotions.htm b/src/core/static/js/tiny_mce/plugins/emotions/emotions.htm new file mode 100644 index 0000000..2c91002 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/emotions/emotions.htm @@ -0,0 +1,41 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#emotions_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/emotions.js"></script> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#emotions_dlg.title}</span> +<div align="center"> + <div class="title">{#emotions_dlg.title}:<br /><br /></div> + + <table role="presentation" border="0" cellspacing="0" cellpadding="4"> + <tr> + <td><a href="javascript:EmotionsDialog.insert('smiley-cool.gif','emotions_dlg.cool');"><img src="img/smiley-cool.gif" width="18" height="18" border="0" alt="{#emotions_dlg.cool}" title="{#emotions_dlg.cool}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-cry.gif','emotions_dlg.cry');"><img src="img/smiley-cry.gif" width="18" height="18" border="0" alt="{#emotions_dlg.cry}" title="{#emotions_dlg.cry}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-embarassed.gif','emotions_dlg.embarassed');"><img src="img/smiley-embarassed.gif" width="18" height="18" border="0" alt="{#emotions_dlg.embarassed}" title="{#emotions_dlg.embarassed}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-foot-in-mouth.gif','emotions_dlg.foot_in_mouth');"><img src="img/smiley-foot-in-mouth.gif" width="18" height="18" border="0" alt="{#emotions_dlg.foot_in_mouth}" title="{#emotions_dlg.foot_in_mouth}" /></a></td> + </tr> + <tr> + <td><a href="javascript:EmotionsDialog.insert('smiley-frown.gif','emotions_dlg.frown');"><img src="img/smiley-frown.gif" width="18" height="18" border="0" alt="{#emotions_dlg.frown}" title="{#emotions_dlg.frown}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-innocent.gif','emotions_dlg.innocent');"><img src="img/smiley-innocent.gif" width="18" height="18" border="0" alt="{#emotions_dlg.innocent}" title="{#emotions_dlg.innocent}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-kiss.gif','emotions_dlg.kiss');"><img src="img/smiley-kiss.gif" width="18" height="18" border="0" alt="{#emotions_dlg.kiss}" title="{#emotions_dlg.kiss}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-laughing.gif','emotions_dlg.laughing');"><img src="img/smiley-laughing.gif" width="18" height="18" border="0" alt="{#emotions_dlg.laughing}" title="{#emotions_dlg.laughing}" /></a></td> + </tr> + <tr> + <td><a href="javascript:EmotionsDialog.insert('smiley-money-mouth.gif','emotions_dlg.money_mouth');"><img src="img/smiley-money-mouth.gif" width="18" height="18" border="0" alt="{#emotions_dlg.money_mouth}" title="{#emotions_dlg.money_mouth}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-sealed.gif','emotions_dlg.sealed');"><img src="img/smiley-sealed.gif" width="18" height="18" border="0" alt="{#emotions_dlg.sealed}" title="{#emotions_dlg.sealed}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-smile.gif','emotions_dlg.smile');"><img src="img/smiley-smile.gif" width="18" height="18" border="0" alt="{#emotions_dlg.smile}" title="{#emotions_dlg.smile}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-surprised.gif','emotions_dlg.surprised');"><img src="img/smiley-surprised.gif" width="18" height="18" border="0" alt="{#emotions_dlg.surprised}" title="{#emotions_dlg.surprised}" /></a></td> + </tr> + <tr> + <td><a href="javascript:EmotionsDialog.insert('smiley-tongue-out.gif','emotions_dlg.tongue_out');"><img src="img/smiley-tongue-out.gif" width="18" height="18" border="0" alt="{#emotions_dlg.tongue-out}" title="{#emotions_dlg.tongue_out}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-undecided.gif','emotions_dlg.undecided');"><img src="img/smiley-undecided.gif" width="18" height="18" border="0" alt="{#emotions_dlg.undecided}" title="{#emotions_dlg.undecided}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-wink.gif','emotions_dlg.wink');"><img src="img/smiley-wink.gif" width="18" height="18" border="0" alt="{#emotions_dlg.wink}" title="{#emotions_dlg.wink}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-yell.gif','emotions_dlg.yell');"><img src="img/smiley-yell.gif" width="18" height="18" border="0" alt="{#emotions_dlg.yell}" title="{#emotions_dlg.yell}" /></a></td> + </tr> + </table> +</div> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-cool.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-cool.gif new file mode 100644 index 0000000000000000000000000000000000000000..ba90cc36fb0415d0273d1cd206bff63fd9c91fde GIT binary patch literal 354 zcmV-o0iFIwNk%w1VG;lm0Mr!#3ke00dJfFY%i+lrhK7V(RutUQJhPY;?(XfrsZKgL z7WLQ^zPO&zzav{)SL^9nBOw~z(=orMEH5uC-P_gr`uhCnASMa|$-iRw?m_(dUwU8) zq>Kx}s1_F$4FCWDA^8LW0018VEC2ui01^Na000Hw;3tYzX_jM3Qpv$_M?zI9i5=0S zX-{-uv=l<p*=3HIT}Of#RazKBq;Z@YZV4Iz0#Fnb06?MO>3%&P0s%m9Ox_a(m_c|u z01g3U0`Wll5)poVdma=N8y<3f0Sf~hXmTC}2oxMW4FdxUj+z4<0}lrX2nP=qkDRIt z9Ge*(qzMrj3jrIOjvI{`5eWzt3`G_T8yChG8w(a19SkK12@M(+799Zr9n=~PzBCmA z5)BU-)YKUd4H5!D9|!^o9kWIe9SH(WDHRk92}DZ?3})2$P@$55g90f0N)ZA8JID5J Aw*UYD literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-cry.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-cry.gif new file mode 100644 index 0000000000000000000000000000000000000000..74d897a4f6d22e814e2b054e98b8a75fb464b4be GIT binary patch literal 329 zcmV-P0k-}}Nk%w1VG;lm0Mr-&E)xPSit@9T3%;vR+|V+?t0A(pllJjXrMl7n=_A_a za^B+Su$LjvyC3@TIQZNZa##w=!k(SO^P#bO*w(eU#;{U83XFCU_V)J5wrb+;g2vkN z#>U24qVoOvY5)KLA^8LW0018VEC2ui01^Na000HX;3tY$X_jM3QUfCh%s^o(nF++< zc?Th6v=oL>*by8K!mhvwelUXuuW&&U9iGO3hM@>Njw{l^#0q9mWpcefdI;O$;efnY zkd~@r-o$*74FCWI1%d((4+jDz0va0>69^fI6%`W{8w!gU1pyL>prH>E0R<%k6Aq%H z4ij+^9TEwM5P}eh2@)L<B?|!!2MHGf4Gk9;2?q@U3tR{Vzzzx13409%2tlM00|hxd bJp}{XBh3p2-Gt%><~6+>@EpxfA0YrcPNsSu literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-embarassed.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-embarassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..963a96b8a7593b1d8bcbab073abe5ee4e539dbf6 GIT binary patch literal 331 zcmV-R0kr-{Nk%w1VG;lm0MrryDh>j~yq&6%75dW~z^P39(NxsGDE{UkxtkIEq(S-a zRKlwv+S=Lr?>hbYY~sQ?c3T&ZcN_Nh_E<O%#>U3s(>Io6B&>WW`@bsw**)Ocy1bht z{*G6|uwwqUQ2+n{A^8LW0018VEC2ui01^Na000HZ;3tYwX_jM3YQ!c88=*-m*&&bO zILd=`w3KAC;8hxpif*w9ek6oqV-Z0L77fROK$B<?js^^gTnMs=8C02!K#=aEqQaFR z6pBm+GC@uzdU#EC4h0?_7ZwKt5f%vv7zzj_2!<RSkOKo436}{4lS7u67@C}(1%m_+ z1&^hgn~wz#bpZ=`7y=Uj023D&843#lB@6@x3J1!|$_fSq3|$Nh$PLU5&I{2a5)2&+ dN;`849os?-0Z|L<1OetM#T4=s(M}&B06V4ic~SrX literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif new file mode 100644 index 0000000000000000000000000000000000000000..c7cf1011dad0e7500e29a278b0d395b253871109 GIT binary patch literal 342 zcmV-c0jd5+Nk%w1VG;lm0Q4UKxtkou#>SR@5BAv-%C>6y>>#+D4e#&nz^qMDItlpp zTG728+|V&?R13PIEBW(C`uh6d*t-1sZ^XQv;oDD}iYLOV7uVO;{`xl4#4tJ{0;h@! z>)kdc3IhA?Hvj+tA^8La0018VEC2ui01^Na06+!P;3tYuX_ljS7!u|-O)<bjtr*7$ zT@&J176)Q-futaag{0!(c%F`mWPvb3CKkn_!{urOiG{*4F_H*|3`HWLWDErJ2gy*p z5_gw^Q9S?@9yNjn4F(zs0}lW>I}TzP1q%xT4HOFwMJaO;2ml)!00<FsBL_bU2o)S0 z6$oPvIh!mG92pr;wj2)<2BUro4=xFK7{e|P3X3Z(kb=%N4>$)141pU08x3594IX?4 o5YuAA8yXz~76K1c;3^jg77WP185Rf^u}23N0sR5^q(T4yJ1sVN5dZ)H literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-frown.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-frown.gif new file mode 100644 index 0000000000000000000000000000000000000000..716f55e161bfebb1c3d34f0b0f40c177fc82c30b GIT binary patch literal 340 zcmV-a0jvH;Nk%w1VG;lm0MroxK_>;q#>Sw62=mns-On=0wransPVevT^YK{Dy(0YY zH)vE6x0?;Wqb>gZas1^OT0si>`ugD5y87}*#H$s=yq(wA*8cf7{`y+(+9J7|9QfT7 z`ROHiU=Y&6FaQ7mA^8LW0018VEC2ui01^Na000Hi;3tYvX_jM3N`@u~nju9hSuh^r zIEcp-wA7(NL0~2d#RP+(G!CPPA>o*KJjv_CkucCA5=K?AfF#RG2V*8BU@jL304|4P z2;PGRF@bj$et;Jf2pR_mVsIA<85|n}kQ*Bq42Ovqj*yy>6P0=h3X&9Z01y<C4-<w5 z1_YrDr5zn|3>yk~2N4w%7#RW^55W%`0vQ+-6(y_*2pqz~90*;x9}yM}%$UI(7t#$D mK_3Se1{4HKM+6iG7EmeH6$V631{L5n)#CyC0qx-*Apkoyg?w!Q literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-innocent.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-innocent.gif new file mode 100644 index 0000000000000000000000000000000000000000..334d49e0e60f2997c9ba24071764f95d9e08a5cc GIT binary patch literal 336 zcmV-W0k8f?Nk%w1VG;lm0MrryI4TI-%dP0m5~*<p%dw5l&RW5fRqyTWvyTq>+Y`T~ z7Rth){q{I_X%*S48uRZ|(b3V&wIKTX`u+WJzo<^$#wuY;3W|Cf{O29IkTAcaE&lpe z+P*^H)-tknA^-pYA^8LW0018VEC2ui01^Na000He;3tYwX_n)75QgVvNQ`6#5gcMm zEEG~blgXokptKAJgCU?%JT?yo<M~i%4gt?6Fz6~Am9UtD7-RyH0HP3SJKk^yXMmPa zIvd6X(CBm;d>s!R6cPtcQWh2siHlNI2L}ifQhgX02^InZ2?-ktkqVRyZJY^Trk|lv zovp437?1~d46O)?2(1i+2NDYk8<+_Kil!K!3njA^!I#dL8x<729}*B65mC=m5gHH@ iDi9P3f*VjB3KS4HDb_qqRul{0DI<mu`1#Z$Apkp|ihYg% literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-kiss.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-kiss.gif new file mode 100644 index 0000000000000000000000000000000000000000..4efd549ed31c44b1faac17ed34bb67abeb42baf8 GIT binary patch literal 338 zcmV-Y0j>T=Nk%w1VG;lm0Mrx!QauaC#>Vb6G=_5=^YB^9wrc376Sb5I-qJGf@9vZ# z5WlKU(!eVB+7tfnDXp0zyB`?BZ5IChalob*`uh6d*t+@dKGHcU+L|83yq*5~IoH?L zy`?Gp<{bX|SpWb4A^8LW0018VEC2ui01^Na000Hg;3tYyX_jM3R?Bl7&r(q;SsVx< zNd$5fv{ZsKA$SlL3&KN~a1tZRf*~1Ltk<iAv7k{Z2Z`pvc_hgXjpQ(sE;$1LK%<cl zILB_HNUzT|aeYk*31NL24jm1Pj2;JshKLOYi<FIzdjt-Z3NH$l9TpRW3rGzS3J|Ig z3K0!T3keh%6CNEM5fB0b7ZJA}6B#85Qy!Zb7Z(@}4jx>x9~2uL3<QX`4jKdu92-F& k2^$L&NFE+a6AK$qDbg7WL{1AC-ZjzT0r>&z-yb0WJDRY082|tP literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-laughing.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-laughing.gif new file mode 100644 index 0000000000000000000000000000000000000000..82c5b182e61d32bd394acae551eff180f1eebd26 GIT binary patch literal 343 zcmV-d0jT~*Nk%w1VG;lm0Q4UK!lp8=s;1-69HWK?p_PpF=Pd8<?!T%|a$ZRD@LAHn zAH%B}$j8NMQxe3yo%Yxe`tnEM*t)ly6Z-o4{{3<N_BV)iTG-Xox}Pq}wrbweGI?VY z)x$ATJq`Z*S^xk5A^8La0018VEC2ui01^Na06+!Q;3tYxX_ljCNL1w(@FNIM?McQs zUCse43&6o~nWQEM1qH(4xS9}(;$WOO79K(4!YDB=4TWdnFp@G7PJ%*7a3mS?2dVM6 zI-PsI;?Yo72@41ogoT6%7!Wvf7XS(g6$={!3l#|p07WTt5eE_j0}=-jaw7&93ke<& ztPmc77&)9Q5ETu3w-r$mq=2;*8x1bOE)WSgD-;DBG&Rl-3j&G;1_v6p1PlQe7Xb_e p!hQx5)nWo01l-^P9#i8g7Y7R(uB#dg2N$wO23!pP`bvcW06U9bekA|^ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif new file mode 100644 index 0000000000000000000000000000000000000000..ca2451e102722e12e131ae53ea76989acbf191e2 GIT binary patch literal 321 zcmV-H0lxl6Nk%w1VG;lm0Mrx!DHsO6wwjoX9Kxs~!mLsE+7oVAHu>~Ygtcnp*fHAL z**;z>w3iC}`fmL6IkKB1N;3zEa}&zKpsu1;_V)HocR5-{J~BcYvE`YXhBnc@CfU=! za(E<?eig#P!T<mOA^8LW0018VEC2ui01^Na000HP;3tYyX_jM3Zp6bd53x}yNif>c zG>66zv=rqr;2j)}gKqE$ekcSD?}0=<bQ<7u!)Q1n00<H+ZZKxh#32EQBphsaG65Va zkpjTmkyjs@6kSLVZ3P8{5rzj0C4zW{h8>WLB?AWp85)qAL<a*U1aAfwq@|<=aCH)v z4*(Si6|WTl0-h2j3Q-&j3$U*X6&G0wG!zO07rYn<2p9_&0t3V&#uK|3*v<n4(?SXX Tyx|K0-72^q=pMvQA0YrcF~)Li literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-sealed.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-sealed.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe66220c24b4da4526818a5d68f75a06d9985a29 GIT binary patch literal 323 zcmV-J0lfZ4Nk%w1VG;lm0Q4UKz^WI%xS#gj6sL~~h=_>d+P=4)6X4oXy{bw2>K^d$ z@6ERvva+(4ib~41YUkTEn1&#?rzrOHT>1I=Y*h`+%*@WtPUPg|!@EEI_d5LgZ>^Og z-qyBKJqy*wF8}}lA^8La0018VEC2ui01^Na06+!6;3tYxX_lj?7+U61R3gAaEg8x< zT>%mSfCwURnWQF&g=Q0ZxH1ulW`QtH0>O!5%iT_X0VBy_@EkOngU8?ye~=H!t21{= z9@Uj3a_UbE88~kh5Eq7rh!7QSBn1c?0|Off1&k^`5*QE<4-gm<K{;<6EEx|T9xkX( z8U`F%268SPbQ!cyH(M+Z5eAXJzYDnv2)q*nU0VcScnUiRg#;DT)C3n02t_Ik4G<9+ V78V#$4Gf}33K!HB7tSdm06S^%c-8;_ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-smile.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd27edfaaa29a70a8c4563c0eab9f18c74d374fd GIT binary patch literal 344 zcmV-e0jK^)Nk%w1VG;lm0Q4UKd0-C4#>SR<4C>Dj%C>6W(lWoQPVevT^YB^Fy&h6M z4YZgH{O~qtR1(Ci8T;lQ`uh6d*t-7xar*K{#Jrulo-Wtd*44u?{`oh#n;gQXGXDEo z_}UUC3IeK%0ssI2A^8La0018VEC2ui01^Na06+!R;3tYuX_ljSEE482&%+G^XK%|f zLKbCc4u{4-u|QG~LqamSTo?@JM3OKZAr!|Z2IzP@fY`=CIg$vA3qm46TowfLCt29I z6pDKuvnf~)83+sm9yW#?9s>^(89F=~2?!W44-6Ox2^vNza}fp^9v&G65pp936%Gg+ z6HpTy2o4oGoh+>l3Q)KVQwybl2oo*<4a3D469|nfEii|MH4`}p1_cZp0ssj%2>=2d q41Na?)CpS;4gvxWVpZcR76uLludD?Q1{SnP2NnVU0rZ&)0RTIit8@_n literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-surprised.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..0cc9bb71cca4cdeafbb248ce7e07c3708c1cbd64 GIT binary patch literal 338 zcmV-Y0j>T=Nk%w1VG;lm0Q4UK`{WwN#>SnDDC*4*{OcpiwransPVevTQacIr@mkQp zCf(06s)_=>r7UYx48o@u`uh6d*t-7rH~ji<`P&oj;5Wp)o!8ga`SV6TA_BIW5#ZWV z{`*)c3<AWsL;wH)A^8La0018VEC2ui01^Na06+!L;3tYuX_ljSXp`hR4gtVa&1uI7 zU6#>2kA}f=futY?#YE7kxGD|7L}4&OEDw$hkm+~<00QS>F_H?J#bz?uEHnl42f5(9 z5O)`6Q9V2o5;YVLUK)Y`7!Nr+4GMq?85s%^2?`BGDRU798Vn2?1`%>22R{iO0u>bk z9tlA?nk*O<3zHJH6&Mp5qALj)E(mxM!Y&vII4dm@1Ov{`f*8pL3xPEVUI>D>1_uxa kNm?`6VH{N6Di;P13m6<67z+;u7qCYM7XkVK^`jvGJD~P?KL7v# literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif new file mode 100644 index 0000000000000000000000000000000000000000..2075dc16058f1f17912167675ce5cfb9986fc71d GIT binary patch literal 328 zcmV-O0k{4~Nk%w1VG;lm0Mrx!CJF+^#>SU@3-{U*rx+Q^wrc$ABfqLn@9*x?z8(4X zSW-O=@){bmmI~g|GQXoP);c<FSP}d3M*jVA`uh6d*t))=8CnMdwl62dyq*2^H`mwJ z)x$CM;3E1`Q~&?~A^8LW0018VEC2ui01^Na000HW;3tYyX_jM3R)^Iz)=^O^Su~t7 zO$yf(v=riDQ79xxiP7>vj3|f1M8e@{G*!tYaiCEujj1NGxRN#6#tiCETo+{x{Hkzt z5k-kPvcD=V2nb<UR~-feh=~dffrA={iID>mjCgL6k{uF&2nP-t0s;w<385Nx2oxDb z9T5Pp7qJl?3Kkh9oe2sCr5F$p7zPSlsUH*@54w*83=9Or4;w)r2pcU95(FL|1Th;< aDaRQH4;Tal7#Y$v#?=Au0pHUfApkpvZg^t= literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-undecided.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-undecided.gif new file mode 100644 index 0000000000000000000000000000000000000000..bef7e257303f8243c89787e7a7f9955dd1f112e2 GIT binary patch literal 337 zcmV-X0j~Z>Nk%w1VG;lm0MroxDi#99#>R?y8~4}{%C>6#>?OadPVevTr-=vi@LATn z4rERY-qJF+n+?CCE&B3D{{3<K`ugD5x<W4p!>Shh?>WT0o%`b%*Voqm`dL;(4F35y zc485^n;g!+Bme*aA^8LW0018VEC2ui01^Na000Hf;3tYvX_jM3N=AnuogqakNi<9X zK?&0kwA8^tNn{?C$|IAYI1ZzT!2>}iuMddFK#NEkRl!7%6brJAnUs;)XcnA}TNBSP zxQ9;SvEfwYeSaGd2^|LqU~(QF1qBxr3Ii7x84ZVt8wCTKoSYAqc?p`G2onnpk`IOl z1`HLGj}riN2p1K12N4z&8IBDc6tEWs859;JtRB6>lf+xO9}yT19toMv8wnl`7(pKg j7zPv!OGgY81{hE&(iR3pP6ig;HPPS!_yOwPA0Yrc)=Yf3 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-wink.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-wink.gif new file mode 100644 index 0000000000000000000000000000000000000000..0631c7616ec8624ddeee02b633326f697ee72f80 GIT binary patch literal 350 zcmV-k0ipg!Nk%w1VG;lm0Q4UK(ZVUl#>Sn03F^-g-qAA3wransPV?|t@9*x%vmQ`7 z4E*pcw3rOOq%3t@4*K#({N^40{c-yG`rz2Q!KfI-yq*61HrBop*VoqW<}&{JS@_x# zwwfF$4Fdh~IsgCwA^8La0018VEC2ui01^Na06+!X;3tYwX_ljiFp=e23$zWxW@`*G zN?2ty6iUNT!AMdPLn89<I6VNsBa$#2B^8PW0&#S{9S2uKsT@fK2H_Bi90-iU`I97Q z0E%zIqENUr1Xc(f2MYrXHi;Vy0}u}!Iy?;k2OcpH3myjm4Mr(+69yat0vrYtb0Y{q z2O3Qt4;lwTI-o2K1Rfax9u5ky5e%q<2M-n*2^lU94lWM|kSi@QiitH3IS2;18v+g& wHWv;88y<lO650S7F$tszn0E%~Di{V71hK9J6b2ZzNDyEMKrq0+R3QKWI|*@ij{pDw literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-yell.gif b/src/core/static/js/tiny_mce/plugins/emotions/img/smiley-yell.gif new file mode 100644 index 0000000000000000000000000000000000000000..648e6e879123fe49beebbc1f3635141864a79a9c GIT binary patch literal 336 zcmV-W0k8f?Nk%w1VG;lm0MrryG8O{K#>IbS7WCB_mWF$+hzY-{PWkp(?(Xf;zbH~P z3jOdj?W+^YwrakfE8fyG&5jTBz!3WS`fgM_;MltQ+c}4GO8)(E`S3`@yq&d~5!ct& z)v79NObo)O7XSbNA^8LW0018VEC2ui01^Na000He;3tYwX_jM3QifI(nn6h_*=Wyk zUB{y}v=qYOIUF#R3dZPhAVv~H;(|<CF_(maCZTAu39B_R)y$%~g`mSpayo)VZ;Q|z z7ZnA-;Q%Nq3riXZbr%Z>a2yN_5FH&J0|$eJ3kw4gj1Y?v5d#>LMV12^6BYy$1)ZKA zga!|m2?POz0R)f>4+aPl8KD{gz`+G_9vLMFQU?RU!8uyH9}*i52|cC+7S0YEK_3Vk i1|APfM-Ltb8&4_H83sg61{vHn(cc000qNZzApkp<uzFPh literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/emotions/js/emotions.js b/src/core/static/js/tiny_mce/plugins/emotions/js/emotions.js new file mode 100644 index 0000000..c549367 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/emotions/js/emotions.js @@ -0,0 +1,22 @@ +tinyMCEPopup.requireLangPack(); + +var EmotionsDialog = { + init : function(ed) { + tinyMCEPopup.resizeToInnerSize(); + }, + + insert : function(file, title) { + var ed = tinyMCEPopup.editor, dom = ed.dom; + + tinyMCEPopup.execCommand('mceInsertContent', false, dom.createHTML('img', { + src : tinyMCEPopup.getWindowArg('plugin_url') + '/img/' + file, + alt : ed.getLang(title), + title : ed.getLang(title), + border : 0 + })); + + tinyMCEPopup.close(); + } +}; + +tinyMCEPopup.onInit.add(EmotionsDialog.init, EmotionsDialog); diff --git a/src/core/static/js/tiny_mce/plugins/emotions/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/emotions/langs/de_dlg.js new file mode 100755 index 0000000..9ef427c --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/emotions/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.emotions_dlg',{cry:"Weinend",cool:"Cool",desc:"Smilies",title:"Smiley einf\u00fcgen",yell:"Br\u00fcllend",wink:"Zwinkernd",undecided:"Unentschlossen","tongue_out":"Zunge raus",surprised:"\u00dcberrascht",smile:"L\u00e4chelnd",sealed:"Verschlossen","money_mouth":"Geld",laughing:"Lachend",kiss:"K\u00fcssend",innocent:"Unschuldig",frown:"Stirnrunzelnd","foot_in_mouth":"Reingefallen",embarassed:"Verlegen",usage:"Navigation mit linken und rechten Pfeilen."}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/emotions/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/emotions/langs/en_dlg.js new file mode 100755 index 0000000..f5aafc3 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/emotions/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.emotions_dlg',{cry:"Cry",cool:"Cool",desc:"Emotions",title:"Insert Emotion",yell:"Yell",wink:"Wink",undecided:"Undecided","tongue_out":"Tongue Out",surprised:"Surprised",smile:"Smile",sealed:"Sealed","money_mouth":"Money Mouth",laughing:"Laughing",kiss:"Kiss",innocent:"Innocent",frown:"Frown","foot_in_mouth":"Foot in Mouth",embarassed:"Embarassed",usage:"Use left and right arrows to navigate."}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/emotions/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/emotions/langs/fr_dlg.js new file mode 100755 index 0000000..b312b0d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/emotions/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.emotions_dlg',{cry:"En pleurs",cool:"Cool",desc:"\u00c9motic\u00f4nes",title:"Ins\u00e9rer une \u00e9motic\u00f4ne",yell:"Criant",wink:"Clin d\'\u0153il",undecided:"Incertain","tongue_out":"Langue tir\u00e9e",surprised:"Surpris",smile:"Sourire",sealed:"Bouche cousue","money_mouth":"Avare",laughing:"Rigolant",kiss:"Bisou",innocent:"Innocent",frown:"D\u00e9\u00e7u","foot_in_mouth":"Pied de nez",embarassed:"Embarrass\u00e9"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/emotions/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/emotions/langs/it_dlg.js new file mode 100755 index 0000000..64c8e5a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/emotions/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.emotions_dlg',{cry:"Piango",cool:"Fico",desc:"Faccina",title:"Inserisci faccina",yell:"Arrabbiato",wink:"Occhiolino",undecided:"Indeciso","tongue_out":"Linguaccia",surprised:"Sorpreso",smile:"Sorridente",sealed:"Bocca sigillata","money_mouth":"Bocca danarosa",laughing:"Risatona",kiss:"Bacio",innocent:"Santarellino",frown:"Triste","foot_in_mouth":"Piede in bocca",embarassed:"Imbarazzato"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/example/dialog.htm b/src/core/static/js/tiny_mce/plugins/example/dialog.htm new file mode 100644 index 0000000..50b2b34 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/example/dialog.htm @@ -0,0 +1,22 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#example_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/dialog.js"></script> +</head> +<body> + +<form onsubmit="ExampleDialog.insert();return false;" action="#"> + <p>Here is a example dialog.</p> + <p>Selected text: <input id="someval" name="someval" type="text" class="text" /></p> + <p>Custom arg: <input id="somearg" name="somearg" type="text" class="text" /></p> + + <div class="mceActionPanel"> + <input type="button" id="insert" name="insert" value="{#insert}" onclick="ExampleDialog.insert();" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> + +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/example/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/example/editor_plugin.js new file mode 100644 index 0000000..ec1f81e --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/example/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.PluginManager.requireLangPack("example");tinymce.create("tinymce.plugins.ExamplePlugin",{init:function(a,b){a.addCommand("mceExample",function(){a.windowManager.open({file:b+"/dialog.htm",width:320+parseInt(a.getLang("example.delta_width",0)),height:120+parseInt(a.getLang("example.delta_height",0)),inline:1},{plugin_url:b,some_custom_arg:"custom arg"})});a.addButton("example",{title:"example.desc",cmd:"mceExample",image:b+"/img/example.gif"});a.onNodeChange.add(function(d,c,e){c.setActive("example",e.nodeName=="IMG")})},createControl:function(b,a){return null},getInfo:function(){return{longname:"Example plugin",author:"Some author",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example",version:"1.0"}}});tinymce.PluginManager.add("example",tinymce.plugins.ExamplePlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/example/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/example/editor_plugin_src.js new file mode 100644 index 0000000..9a0e7da --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/example/editor_plugin_src.js @@ -0,0 +1,84 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + // Load plugin specific language pack + tinymce.PluginManager.requireLangPack('example'); + + tinymce.create('tinymce.plugins.ExamplePlugin', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed, url) { + // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample'); + ed.addCommand('mceExample', function() { + ed.windowManager.open({ + file : url + '/dialog.htm', + width : 320 + parseInt(ed.getLang('example.delta_width', 0)), + height : 120 + parseInt(ed.getLang('example.delta_height', 0)), + inline : 1 + }, { + plugin_url : url, // Plugin absolute URL + some_custom_arg : 'custom arg' // Custom argument + }); + }); + + // Register example button + ed.addButton('example', { + title : 'example.desc', + cmd : 'mceExample', + image : url + '/img/example.gif' + }); + + // Add a node change handler, selects the button in the UI when a image is selected + ed.onNodeChange.add(function(ed, cm, n) { + cm.setActive('example', n.nodeName == 'IMG'); + }); + }, + + /** + * Creates control instances based in the incomming name. This method is normally not + * needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons + * but you sometimes need to create more complex controls like listboxes, split buttons etc then this + * method can be used to create those. + * + * @param {String} n Name of the control to create. + * @param {tinymce.ControlManager} cm Control manager to use inorder to create new control. + * @return {tinymce.ui.Control} New control instance or null if no control was created. + */ + createControl : function(n, cm) { + return null; + }, + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Example plugin', + author : 'Some author', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example', + version : "1.0" + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('example', tinymce.plugins.ExamplePlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/example/img/example.gif b/src/core/static/js/tiny_mce/plugins/example/img/example.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ab5da4461113d2af579898528246fdbe52ecd00 GIT binary patch literal 87 zcmZ?wbhEHb6k!lyn83&Y1dNP~ia%L^OhyJB5FaGNz@*pGzw+SQ`#f{}FJ-?!v#V)e mtsGNfpJeCKSAiOz**>0`XR2{OVa>-G_df0vaY<rium%9X5FI1{ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/example/js/dialog.js b/src/core/static/js/tiny_mce/plugins/example/js/dialog.js new file mode 100644 index 0000000..fa83411 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/example/js/dialog.js @@ -0,0 +1,19 @@ +tinyMCEPopup.requireLangPack(); + +var ExampleDialog = { + init : function() { + var f = document.forms[0]; + + // Get the selected contents as text and place it in the input + f.someval.value = tinyMCEPopup.editor.selection.getContent({format : 'text'}); + f.somearg.value = tinyMCEPopup.getWindowArg('some_custom_arg'); + }, + + insert : function() { + // Insert the contents from the input into the document + tinyMCEPopup.editor.execCommand('mceInsertContent', false, document.forms[0].someval.value); + tinyMCEPopup.close(); + } +}; + +tinyMCEPopup.onInit.add(ExampleDialog.init, ExampleDialog); diff --git a/src/core/static/js/tiny_mce/plugins/example/langs/en.js b/src/core/static/js/tiny_mce/plugins/example/langs/en.js new file mode 100644 index 0000000..e0784f8 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/example/langs/en.js @@ -0,0 +1,3 @@ +tinyMCE.addI18n('en.example',{ + desc : 'This is just a template button' +}); diff --git a/src/core/static/js/tiny_mce/plugins/example/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/example/langs/en_dlg.js new file mode 100644 index 0000000..ebcf948 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/example/langs/en_dlg.js @@ -0,0 +1,3 @@ +tinyMCE.addI18n('en.example_dlg',{ + title : 'This is just a example title' +}); diff --git a/src/core/static/js/tiny_mce/plugins/example_dependency/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/example_dependency/editor_plugin.js new file mode 100644 index 0000000..0a4551d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/example_dependency/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.ExampleDependencyPlugin",{init:function(a,b){},getInfo:function(){return{longname:"Example Dependency plugin",author:"Some author",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example_dependency",version:"1.0"}}});tinymce.PluginManager.add("example_dependency",tinymce.plugins.ExampleDependencyPlugin,["example"])})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/example_dependency/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/example_dependency/editor_plugin_src.js new file mode 100644 index 0000000..e1c55e4 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/example_dependency/editor_plugin_src.js @@ -0,0 +1,50 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + + tinymce.create('tinymce.plugins.ExampleDependencyPlugin', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed, url) { + }, + + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Example Dependency plugin', + author : 'Some author', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example_dependency', + version : "1.0" + }; + } + }); + + /** + * Register the plugin, specifying the list of the plugins that this plugin depends on. They are specified in a list, with the list loaded in order. + * plugins in this list will be initialised when this plugin is initialized. (before the init method is called). + * plugins in a depends list should typically be specified using the short name). If neccesary this can be done + * with an object which has the url to the plugin and the shortname. + */ + tinymce.PluginManager.add('example_dependency', tinymce.plugins.ExampleDependencyPlugin, ['example']); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/fullpage/css/fullpage.css b/src/core/static/js/tiny_mce/plugins/fullpage/css/fullpage.css new file mode 100644 index 0000000..2675cec --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullpage/css/fullpage.css @@ -0,0 +1,143 @@ +/* Hide the advanced tab */ +#advanced_tab { + display: none; +} + +#metatitle, #metakeywords, #metadescription, #metaauthor, #metacopyright { + width: 280px; +} + +#doctype, #docencoding { + width: 200px; +} + +#langcode { + width: 30px; +} + +#bgimage { + width: 220px; +} + +#fontface { + width: 240px; +} + +#leftmargin, #rightmargin, #topmargin, #bottommargin { + width: 50px; +} + +.panel_wrapper div.current { + height: 400px; +} + +#stylesheet, #style { + width: 240px; +} + +#doctypes { + width: 200px; +} + +/* Head list classes */ + +.headlistwrapper { + width: 100%; +} + +.selected { + border: 1px solid #0A246A; + background-color: #B6BDD2; +} + +.toolbar { + width: 100%; +} + +#headlist { + width: 100%; + margin-top: 3px; + font-size: 11px; +} + +#info, #title_element, #meta_element, #script_element, #style_element, #base_element, #link_element, #comment_element, #unknown_element { + display: none; +} + +#addmenu { + position: absolute; + border: 1px solid gray; + display: none; + z-index: 100; + background-color: white; +} + +#addmenu a { + display: block; + width: 100%; + line-height: 20px; + text-decoration: none; + background-color: white; +} + +#addmenu a:hover { + background-color: #B6BDD2; + color: black; +} + +#addmenu span { + padding-left: 10px; + padding-right: 10px; +} + +#updateElementPanel { + display: none; +} + +#script_element .panel_wrapper div.current { + height: 108px; +} + +#style_element .panel_wrapper div.current { + height: 108px; +} + +#link_element .panel_wrapper div.current { + height: 140px; +} + +#element_script_value { + width: 100%; + height: 100px; +} + +#element_comment_value { + width: 100%; + height: 120px; +} + +#element_style_value { + width: 100%; + height: 100px; +} + +#element_title, #element_script_src, #element_meta_name, #element_meta_content, #element_base_href, #element_link_href, #element_link_title { + width: 250px; +} + +.updateElementButton { + margin-top: 3px; +} + +/* MSIE specific styles */ + +* html .addbutton, * html .removebutton, * html .moveupbutton, * html .movedownbutton { + width: 22px; + height: 22px; +} + +textarea { + height: 55px; +} + +.panel_wrapper div.current {height:420px;} \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fullpage/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/fullpage/editor_plugin.js new file mode 100644 index 0000000..dcf7602 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullpage/editor_plugin.js @@ -0,0 +1 @@ +(function(){var b=tinymce.each,a=tinymce.html.Node;tinymce.create("tinymce.plugins.FullPagePlugin",{init:function(c,d){var e=this;e.editor=c;c.addCommand("mceFullPageProperties",function(){c.windowManager.open({file:d+"/fullpage.htm",width:430+parseInt(c.getLang("fullpage.delta_width",0)),height:495+parseInt(c.getLang("fullpage.delta_height",0)),inline:1},{plugin_url:d,data:e._htmlToData()})});c.addButton("fullpage",{title:"fullpage.desc",cmd:"mceFullPageProperties"});c.onBeforeSetContent.add(e._setContent,e);c.onGetContent.add(e._getContent,e)},getInfo:function(){return{longname:"Fullpage",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_htmlToData:function(){var f=this._parseHeader(),h={},c,i,g,e=this.editor;function d(l,j){var k=l.attr(j);return k||""}h.fontface=e.getParam("fullpage_default_fontface","");h.fontsize=e.getParam("fullpage_default_fontsize","");i=f.firstChild;if(i.type==7){h.xml_pi=true;g=/encoding="([^"]+)"/.exec(i.value);if(g){h.docencoding=g[1]}}i=f.getAll("#doctype")[0];if(i){h.doctype="<!DOCTYPE"+i.value+">"}i=f.getAll("title")[0];if(i&&i.firstChild){h.metatitle=i.firstChild.value}b(f.getAll("meta"),function(m){var k=m.attr("name"),j=m.attr("http-equiv"),l;if(k){h["meta"+k.toLowerCase()]=m.attr("content")}else{if(j=="Content-Type"){l=/charset\s*=\s*(.*)\s*/gi.exec(m.attr("content"));if(l){h.docencoding=l[1]}}}});i=f.getAll("html")[0];if(i){h.langcode=d(i,"lang")||d(i,"xml:lang")}i=f.getAll("link")[0];if(i&&i.attr("rel")=="stylesheet"){h.stylesheet=i.attr("href")}i=f.getAll("body")[0];if(i){h.langdir=d(i,"dir");h.style=d(i,"style");h.visited_color=d(i,"vlink");h.link_color=d(i,"link");h.active_color=d(i,"alink")}return h},_dataToHtml:function(g){var f,d,h,j,k,e=this.editor.dom;function c(n,l,m){n.attr(l,m?m:undefined)}function i(l){if(d.firstChild){d.insert(l,d.firstChild)}else{d.append(l)}}f=this._parseHeader();d=f.getAll("head")[0];if(!d){j=f.getAll("html")[0];d=new a("head",1);if(j.firstChild){j.insert(d,j.firstChild,true)}else{j.append(d)}}j=f.firstChild;if(g.xml_pi){k='version="1.0"';if(g.docencoding){k+=' encoding="'+g.docencoding+'"'}if(j.type!=7){j=new a("xml",7);f.insert(j,f.firstChild,true)}j.value=k}else{if(j&&j.type==7){j.remove()}}j=f.getAll("#doctype")[0];if(g.doctype){if(!j){j=new a("#doctype",10);if(g.xml_pi){f.insert(j,f.firstChild)}else{i(j)}}j.value=g.doctype.substring(9,g.doctype.length-1)}else{if(j){j.remove()}}j=f.getAll("title")[0];if(g.metatitle){if(!j){j=new a("title",1);j.append(new a("#text",3)).value=g.metatitle;i(j)}}if(g.docencoding){j=null;b(f.getAll("meta"),function(l){if(l.attr("http-equiv")=="Content-Type"){j=l}});if(!j){j=new a("meta",1);j.attr("http-equiv","Content-Type");j.shortEnded=true;i(j)}j.attr("content","text/html; charset="+g.docencoding)}b("keywords,description,author,copyright,robots".split(","),function(m){var l=f.getAll("meta"),n,p,o=g["meta"+m];for(n=0;n<l.length;n++){p=l[n];if(p.attr("name")==m){if(o){p.attr("content",o)}else{p.remove()}return}}if(o){j=new a("meta",1);j.attr("name",m);j.attr("content",o);j.shortEnded=true;i(j)}});j=f.getAll("link")[0];if(j&&j.attr("rel")=="stylesheet"){if(g.stylesheet){j.attr("href",g.stylesheet)}else{j.remove()}}else{if(g.stylesheet){j=new a("link",1);j.attr({rel:"stylesheet",text:"text/css",href:g.stylesheet});j.shortEnded=true;i(j)}}j=f.getAll("body")[0];if(j){c(j,"dir",g.langdir);c(j,"style",g.style);c(j,"vlink",g.visited_color);c(j,"link",g.link_color);c(j,"alink",g.active_color);e.setAttribs(this.editor.getBody(),{style:g.style,dir:g.dir,vLink:g.visited_color,link:g.link_color,aLink:g.active_color})}j=f.getAll("html")[0];if(j){c(j,"lang",g.langcode);c(j,"xml:lang",g.langcode)}h=new tinymce.html.Serializer({validate:false,indent:true,apply_source_formatting:true,indent_before:"head,html,body,meta,title,script,link,style",indent_after:"head,html,body,meta,title,script,link,style"}).serialize(f);this.head=h.substring(0,h.indexOf("</body>"))},_parseHeader:function(){return new tinymce.html.DomParser({validate:false,root_name:"#document"}).parse(this.head)},_setContent:function(g,d){var m=this,i,c,h=d.content,f,l="",e=m.editor.dom,j;function k(n){return n.replace(/<\/?[A-Z]+/g,function(o){return o.toLowerCase()})}if(d.format=="raw"&&m.head){return}if(d.source_view&&g.getParam("fullpage_hide_in_source_view")){return}h=h.replace(/<(\/?)BODY/gi,"<$1body");i=h.indexOf("<body");if(i!=-1){i=h.indexOf(">",i);m.head=k(h.substring(0,i+1));c=h.indexOf("</body",i);if(c==-1){c=h.length}d.content=h.substring(i+1,c);m.foot=k(h.substring(c))}else{m.head=this._getDefaultHeader();m.foot="\n</body>\n</html>"}f=m._parseHeader();b(f.getAll("style"),function(n){if(n.firstChild){l+=n.firstChild.value}});j=f.getAll("body")[0];if(j){e.setAttribs(m.editor.getBody(),{style:j.attr("style")||"",dir:j.attr("dir")||"",vLink:j.attr("vlink")||"",link:j.attr("link")||"",aLink:j.attr("alink")||""})}e.remove("fullpage_styles");if(l){e.add(m.editor.getDoc().getElementsByTagName("head")[0],"style",{id:"fullpage_styles"},l);j=e.get("fullpage_styles");if(j.styleSheet){j.styleSheet.cssText=l}}},_getDefaultHeader:function(){var f="",c=this.editor,e,d="";if(c.getParam("fullpage_default_xml_pi")){f+='<?xml version="1.0" encoding="'+c.getParam("fullpage_default_encoding","ISO-8859-1")+'" ?>\n'}f+=c.getParam("fullpage_default_doctype",'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">');f+="\n<html>\n<head>\n";if(e=c.getParam("fullpage_default_title")){f+="<title>"+e+"</title>\n"}if(e=c.getParam("fullpage_default_encoding")){f+='<meta http-equiv="Content-Type" content="text/html; charset='+e+'" />\n'}if(e=c.getParam("fullpage_default_font_family")){d+="font-family: "+e+";"}if(e=c.getParam("fullpage_default_font_size")){d+="font-size: "+e+";"}if(e=c.getParam("fullpage_default_text_color")){d+="color: "+e+";"}f+="</head>\n<body"+(d?' style="'+d+'"':"")+">\n";return f},_getContent:function(d,e){var c=this;if(!e.source_view||!d.getParam("fullpage_hide_in_source_view")){e.content=tinymce.trim(c.head)+"\n"+tinymce.trim(e.content)+"\n"+tinymce.trim(c.foot)}}});tinymce.PluginManager.add("fullpage",tinymce.plugins.FullPagePlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fullpage/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/fullpage/editor_plugin_src.js new file mode 100644 index 0000000..23de7c5 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullpage/editor_plugin_src.js @@ -0,0 +1,405 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var each = tinymce.each, Node = tinymce.html.Node; + + tinymce.create('tinymce.plugins.FullPagePlugin', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceFullPageProperties', function() { + ed.windowManager.open({ + file : url + '/fullpage.htm', + width : 430 + parseInt(ed.getLang('fullpage.delta_width', 0)), + height : 495 + parseInt(ed.getLang('fullpage.delta_height', 0)), + inline : 1 + }, { + plugin_url : url, + data : t._htmlToData() + }); + }); + + // Register buttons + ed.addButton('fullpage', {title : 'fullpage.desc', cmd : 'mceFullPageProperties'}); + + ed.onBeforeSetContent.add(t._setContent, t); + ed.onGetContent.add(t._getContent, t); + }, + + getInfo : function() { + return { + longname : 'Fullpage', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private plugin internal methods + + _htmlToData : function() { + var headerFragment = this._parseHeader(), data = {}, nodes, elm, matches, editor = this.editor; + + function getAttr(elm, name) { + var value = elm.attr(name); + + return value || ''; + }; + + // Default some values + data.fontface = editor.getParam("fullpage_default_fontface", ""); + data.fontsize = editor.getParam("fullpage_default_fontsize", ""); + + // Parse XML PI + elm = headerFragment.firstChild; + if (elm.type == 7) { + data.xml_pi = true; + matches = /encoding="([^"]+)"/.exec(elm.value); + if (matches) + data.docencoding = matches[1]; + } + + // Parse doctype + elm = headerFragment.getAll('#doctype')[0]; + if (elm) + data.doctype = '<!DOCTYPE' + elm.value + ">"; + + // Parse title element + elm = headerFragment.getAll('title')[0]; + if (elm && elm.firstChild) { + data.metatitle = elm.firstChild.value; + } + + // Parse meta elements + each(headerFragment.getAll('meta'), function(meta) { + var name = meta.attr('name'), httpEquiv = meta.attr('http-equiv'), matches; + + if (name) + data['meta' + name.toLowerCase()] = meta.attr('content'); + else if (httpEquiv == "Content-Type") { + matches = /charset\s*=\s*(.*)\s*/gi.exec(meta.attr('content')); + + if (matches) + data.docencoding = matches[1]; + } + }); + + // Parse html attribs + elm = headerFragment.getAll('html')[0]; + if (elm) + data.langcode = getAttr(elm, 'lang') || getAttr(elm, 'xml:lang'); + + // Parse stylesheet + elm = headerFragment.getAll('link')[0]; + if (elm && elm.attr('rel') == 'stylesheet') + data.stylesheet = elm.attr('href'); + + // Parse body parts + elm = headerFragment.getAll('body')[0]; + if (elm) { + data.langdir = getAttr(elm, 'dir'); + data.style = getAttr(elm, 'style'); + data.visited_color = getAttr(elm, 'vlink'); + data.link_color = getAttr(elm, 'link'); + data.active_color = getAttr(elm, 'alink'); + } + + return data; + }, + + _dataToHtml : function(data) { + var headerFragment, headElement, html, elm, value, dom = this.editor.dom; + + function setAttr(elm, name, value) { + elm.attr(name, value ? value : undefined); + }; + + function addHeadNode(node) { + if (headElement.firstChild) + headElement.insert(node, headElement.firstChild); + else + headElement.append(node); + }; + + headerFragment = this._parseHeader(); + headElement = headerFragment.getAll('head')[0]; + if (!headElement) { + elm = headerFragment.getAll('html')[0]; + headElement = new Node('head', 1); + + if (elm.firstChild) + elm.insert(headElement, elm.firstChild, true); + else + elm.append(headElement); + } + + // Add/update/remove XML-PI + elm = headerFragment.firstChild; + if (data.xml_pi) { + value = 'version="1.0"'; + + if (data.docencoding) + value += ' encoding="' + data.docencoding + '"'; + + if (elm.type != 7) { + elm = new Node('xml', 7); + headerFragment.insert(elm, headerFragment.firstChild, true); + } + + elm.value = value; + } else if (elm && elm.type == 7) + elm.remove(); + + // Add/update/remove doctype + elm = headerFragment.getAll('#doctype')[0]; + if (data.doctype) { + if (!elm) { + elm = new Node('#doctype', 10); + + if (data.xml_pi) + headerFragment.insert(elm, headerFragment.firstChild); + else + addHeadNode(elm); + } + + elm.value = data.doctype.substring(9, data.doctype.length - 1); + } else if (elm) + elm.remove(); + + // Add/update/remove title + elm = headerFragment.getAll('title')[0]; + if (data.metatitle) { + if (!elm) { + elm = new Node('title', 1); + elm.append(new Node('#text', 3)).value = data.metatitle; + addHeadNode(elm); + } + } + + // Add meta encoding + if (data.docencoding) { + elm = null; + each(headerFragment.getAll('meta'), function(meta) { + if (meta.attr('http-equiv') == 'Content-Type') + elm = meta; + }); + + if (!elm) { + elm = new Node('meta', 1); + elm.attr('http-equiv', 'Content-Type'); + elm.shortEnded = true; + addHeadNode(elm); + } + + elm.attr('content', 'text/html; charset=' + data.docencoding); + } + + // Add/update/remove meta + each('keywords,description,author,copyright,robots'.split(','), function(name) { + var nodes = headerFragment.getAll('meta'), i, meta, value = data['meta' + name]; + + for (i = 0; i < nodes.length; i++) { + meta = nodes[i]; + + if (meta.attr('name') == name) { + if (value) + meta.attr('content', value); + else + meta.remove(); + + return; + } + } + + if (value) { + elm = new Node('meta', 1); + elm.attr('name', name); + elm.attr('content', value); + elm.shortEnded = true; + + addHeadNode(elm); + } + }); + + // Add/update/delete link + elm = headerFragment.getAll('link')[0]; + if (elm && elm.attr('rel') == 'stylesheet') { + if (data.stylesheet) + elm.attr('href', data.stylesheet); + else + elm.remove(); + } else if (data.stylesheet) { + elm = new Node('link', 1); + elm.attr({ + rel : 'stylesheet', + text : 'text/css', + href : data.stylesheet + }); + elm.shortEnded = true; + + addHeadNode(elm); + } + + // Update body attributes + elm = headerFragment.getAll('body')[0]; + if (elm) { + setAttr(elm, 'dir', data.langdir); + setAttr(elm, 'style', data.style); + setAttr(elm, 'vlink', data.visited_color); + setAttr(elm, 'link', data.link_color); + setAttr(elm, 'alink', data.active_color); + + // Update iframe body as well + dom.setAttribs(this.editor.getBody(), { + style : data.style, + dir : data.dir, + vLink : data.visited_color, + link : data.link_color, + aLink : data.active_color + }); + } + + // Set html attributes + elm = headerFragment.getAll('html')[0]; + if (elm) { + setAttr(elm, 'lang', data.langcode); + setAttr(elm, 'xml:lang', data.langcode); + } + + // Serialize header fragment and crop away body part + html = new tinymce.html.Serializer({ + validate: false, + indent: true, + apply_source_formatting : true, + indent_before: 'head,html,body,meta,title,script,link,style', + indent_after: 'head,html,body,meta,title,script,link,style' + }).serialize(headerFragment); + + this.head = html.substring(0, html.indexOf('</body>')); + }, + + _parseHeader : function() { + // Parse the contents with a DOM parser + return new tinymce.html.DomParser({ + validate: false, + root_name: '#document' + }).parse(this.head); + }, + + _setContent : function(ed, o) { + var self = this, startPos, endPos, content = o.content, headerFragment, styles = '', dom = self.editor.dom, elm; + + function low(s) { + return s.replace(/<\/?[A-Z]+/g, function(a) { + return a.toLowerCase(); + }) + }; + + // Ignore raw updated if we already have a head, this will fix issues with undo/redo keeping the head/foot separate + if (o.format == 'raw' && self.head) + return; + + if (o.source_view && ed.getParam('fullpage_hide_in_source_view')) + return; + + // Parse out head, body and footer + content = content.replace(/<(\/?)BODY/gi, '<$1body'); + startPos = content.indexOf('<body'); + + if (startPos != -1) { + startPos = content.indexOf('>', startPos); + self.head = low(content.substring(0, startPos + 1)); + + endPos = content.indexOf('</body', startPos); + if (endPos == -1) + endPos = content.length; + + o.content = content.substring(startPos + 1, endPos); + self.foot = low(content.substring(endPos)); + } else { + self.head = this._getDefaultHeader(); + self.foot = '\n</body>\n</html>'; + } + + // Parse header and update iframe + headerFragment = self._parseHeader(); + each(headerFragment.getAll('style'), function(node) { + if (node.firstChild) + styles += node.firstChild.value; + }); + + elm = headerFragment.getAll('body')[0]; + if (elm) { + dom.setAttribs(self.editor.getBody(), { + style : elm.attr('style') || '', + dir : elm.attr('dir') || '', + vLink : elm.attr('vlink') || '', + link : elm.attr('link') || '', + aLink : elm.attr('alink') || '' + }); + } + + dom.remove('fullpage_styles'); + + if (styles) { + dom.add(self.editor.getDoc().getElementsByTagName('head')[0], 'style', {id : 'fullpage_styles'}, styles); + + // Needed for IE 6/7 + elm = dom.get('fullpage_styles'); + if (elm.styleSheet) + elm.styleSheet.cssText = styles; + } + }, + + _getDefaultHeader : function() { + var header = '', editor = this.editor, value, styles = ''; + + if (editor.getParam('fullpage_default_xml_pi')) + header += '<?xml version="1.0" encoding="' + editor.getParam('fullpage_default_encoding', 'ISO-8859-1') + '" ?>\n'; + + header += editor.getParam('fullpage_default_doctype', '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'); + header += '\n<html>\n<head>\n'; + + if (value = editor.getParam('fullpage_default_title')) + header += '<title>' + value + '</title>\n'; + + if (value = editor.getParam('fullpage_default_encoding')) + header += '<meta http-equiv="Content-Type" content="text/html; charset=' + value + '" />\n'; + + if (value = editor.getParam('fullpage_default_font_family')) + styles += 'font-family: ' + value + ';'; + + if (value = editor.getParam('fullpage_default_font_size')) + styles += 'font-size: ' + value + ';'; + + if (value = editor.getParam('fullpage_default_text_color')) + styles += 'color: ' + value + ';'; + + header += '</head>\n<body' + (styles ? ' style="' + styles + '"' : '') + '>\n'; + + return header; + }, + + _getContent : function(ed, o) { + var self = this; + + if (!o.source_view || !ed.getParam('fullpage_hide_in_source_view')) + o.content = tinymce.trim(self.head) + '\n' + tinymce.trim(o.content) + '\n' + tinymce.trim(self.foot); + } + }); + + // Register plugin + tinymce.PluginManager.add('fullpage', tinymce.plugins.FullPagePlugin); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/fullpage/fullpage.htm b/src/core/static/js/tiny_mce/plugins/fullpage/fullpage.htm new file mode 100644 index 0000000..14ab865 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullpage/fullpage.htm @@ -0,0 +1,259 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#fullpage_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="js/fullpage.js"></script> + <link href="css/fullpage.css" rel="stylesheet" type="text/css" /> +</head> +<body id="fullpage" style="display: none"> +<form onsubmit="FullPageDialog.update();return false;" name="fullpage" action="#"> + <div class="tabs"> + <ul> + <li id="meta_tab" class="current"><span><a href="javascript:mcTabs.displayTab('meta_tab','meta_panel');" onmousedown="return false;">{#fullpage_dlg.meta_tab}</a></span></li> + <li id="appearance_tab"><span><a href="javascript:mcTabs.displayTab('appearance_tab','appearance_panel');" onmousedown="return false;">{#fullpage_dlg.appearance_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="meta_panel" class="panel current"> + <fieldset> + <legend>{#fullpage_dlg.meta_props}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="nowrap"><label for="metatitle">{#fullpage_dlg.meta_title}</label>&nbsp;</td> + <td><input type="text" id="metatitle" name="metatitle" value="" class="mceFocus" /></td> + </tr> + <tr> + <td class="nowrap"><label for="metakeywords">{#fullpage_dlg.meta_keywords}</label>&nbsp;</td> + <td><textarea id="metakeywords" name="metakeywords" rows="4"></textarea></td> + </tr> + <tr> + <td class="nowrap"><label for="metadescription">{#fullpage_dlg.meta_description}</label>&nbsp;</td> + <td><textarea id="metadescription" name="metadescription" rows="4"></textarea></td> + </tr> + <tr> + <td class="nowrap"><label for="metaauthor">{#fullpage_dlg.author}</label>&nbsp;</td> + <td><input type="text" id="metaauthor" name="metaauthor" value="" /></td> + </tr> + <tr> + <td class="nowrap"><label for="metacopyright">{#fullpage_dlg.copyright}</label>&nbsp;</td> + <td><input type="text" id="metacopyright" name="metacopyright" value="" /></td> + </tr> + <tr> + <td class="nowrap"><label for="metarobots">{#fullpage_dlg.meta_robots}</label>&nbsp;</td> + <td> + <select id="metarobots" name="metarobots"> + <option value="">{#not_set}</option> + <option value="index,follow">{#fullpage_dlg.meta_index_follow}</option> + <option value="index,nofollow">{#fullpage_dlg.meta_index_nofollow}</option> + <option value="noindex,follow">{#fullpage_dlg.meta_noindex_follow}</option> + <option value="noindex,nofollow">{#fullpage_dlg.meta_noindex_nofollow}</option> + </select> + </td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#fullpage_dlg.langprops}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="docencoding">{#fullpage_dlg.encoding}</label></td> + <td> + <select id="docencoding" name="docencoding"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="nowrap"><label for="doctype">{#fullpage_dlg.doctypes}</label>&nbsp;</td> + <td> + <select id="doctype" name="doctype"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="nowrap"><label for="langcode">{#fullpage_dlg.langcode}</label>&nbsp;</td> + <td><input type="text" id="langcode" name="langcode" value="" /></td> + </tr> + <tr> + <td class="column1"><label for="langdir">{#fullpage_dlg.langdir}</label></td> + <td> + <select id="langdir" name="langdir"> + <option value="">{#not_set}</option> + <option value="ltr">{#fullpage_dlg.ltr}</option> + <option value="rtl">{#fullpage_dlg.rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="nowrap"><label for="xml_pi">{#fullpage_dlg.xml_pi}</label>&nbsp;</td> + <td><input type="checkbox" id="xml_pi" name="xml_pi" class="checkbox" /></td> + </tr> + </table> + </fieldset> + </div> + + <div id="appearance_panel" class="panel"> + <fieldset> + <legend>{#fullpage_dlg.appearance_textprops}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="fontface">{#fullpage_dlg.fontface}</label></td> + <td> + <select id="fontface" name="fontface" onchange="FullPageDialog.changedStyleProp();"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="fontsize">{#fullpage_dlg.fontsize}</label></td> + <td> + <select id="fontsize" name="fontsize" onchange="FullPageDialog.changedStyleProp();"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="textcolor">{#fullpage_dlg.textcolor}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="textcolor" name="textcolor" type="text" value="" size="9" onchange="updateColor('textcolor_pick','textcolor');FullPageDialog.changedStyleProp();" /></td> + <td id="textcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#fullpage_dlg.appearance_bgprops}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="bgimage">{#fullpage_dlg.bgimage}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgimage" name="bgimage" type="text" value="" onchange="FullPageDialog.changedStyleProp();" /></td> + <td id="bgimage_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + <tr> + <td class="column1"><label for="bgcolor">{#fullpage_dlg.bgcolor}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');FullPageDialog.changedStyleProp();" /></td> + <td id="bgcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#fullpage_dlg.appearance_marginprops}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="leftmargin">{#fullpage_dlg.left_margin}</label></td> + <td><input id="leftmargin" name="leftmargin" type="text" value="" onchange="FullPageDialog.changedStyleProp();" /></td> + <td class="column1"><label for="rightmargin">{#fullpage_dlg.right_margin}</label></td> + <td><input id="rightmargin" name="rightmargin" type="text" value="" onchange="FullPageDialog.changedStyleProp();" /></td> + </tr> + <tr> + <td class="column1"><label for="topmargin">{#fullpage_dlg.top_margin}</label></td> + <td><input id="topmargin" name="topmargin" type="text" value="" onchange="FullPageDialog.changedStyleProp();" /></td> + <td class="column1"><label for="bottommargin">{#fullpage_dlg.bottom_margin}</label></td> + <td><input id="bottommargin" name="bottommargin" type="text" value="" onchange="FullPageDialog.changedStyleProp();" /></td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#fullpage_dlg.appearance_linkprops}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="link_color">{#fullpage_dlg.link_color}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="link_color" name="link_color" type="text" value="" size="9" onchange="updateColor('link_color_pick','link_color');FullPageDialog.changedStyleProp();" /></td> + <td id="link_color_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + + <td class="column1"><label for="visited_color">{#fullpage_dlg.visited_color}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="visited_color" name="visited_color" type="text" value="" size="9" onchange="updateColor('visited_color_pick','visited_color');FullPageDialog.changedStyleProp();" /></td> + <td id="visited_color_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td class="column1"><label for="active_color">{#fullpage_dlg.active_color}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="active_color" name="active_color" type="text" value="" size="9" onchange="updateColor('active_color_pick','active_color');FullPageDialog.changedStyleProp();" /></td> + <td id="active_color_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + + <td>&nbsp;</td> + <td>&nbsp;</td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#fullpage_dlg.appearance_style}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="stylesheet">{#fullpage_dlg.stylesheet}</label></td> + <td><table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="stylesheet" name="stylesheet" type="text" value="" /></td> + <td id="stylesheet_browsercontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td class="column1"><label for="style">{#fullpage_dlg.style}</label></td> + <td><input id="style" name="style" type="text" value="" onchange="FullPageDialog.changedStyle();" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="update" value="{#update}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/fullpage/js/fullpage.js b/src/core/static/js/tiny_mce/plugins/fullpage/js/fullpage.js new file mode 100644 index 0000000..3f672ad --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullpage/js/fullpage.js @@ -0,0 +1,232 @@ +/** + * fullpage.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinyMCEPopup.requireLangPack(); + + var defaultDocTypes = + 'XHTML 1.0 Transitional=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">,' + + 'XHTML 1.0 Frameset=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">,' + + 'XHTML 1.0 Strict=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">,' + + 'XHTML 1.1=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">,' + + 'HTML 4.01 Transitional=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">,' + + 'HTML 4.01 Strict=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">,' + + 'HTML 4.01 Frameset=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'; + + var defaultEncodings = + 'Western european (iso-8859-1)=iso-8859-1,' + + 'Central European (iso-8859-2)=iso-8859-2,' + + 'Unicode (UTF-8)=utf-8,' + + 'Chinese traditional (Big5)=big5,' + + 'Cyrillic (iso-8859-5)=iso-8859-5,' + + 'Japanese (iso-2022-jp)=iso-2022-jp,' + + 'Greek (iso-8859-7)=iso-8859-7,' + + 'Korean (iso-2022-kr)=iso-2022-kr,' + + 'ASCII (us-ascii)=us-ascii'; + + var defaultFontNames = 'Arial=arial,helvetica,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,times new roman,times,serif;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times,serif;Verdana=verdana,arial,helvetica,sans-serif;Impact=impact;WingDings=wingdings'; + var defaultFontSizes = '10px,11px,12px,13px,14px,15px,16px'; + + function setVal(id, value) { + var elm = document.getElementById(id); + + if (elm) { + value = value || ''; + + if (elm.nodeName == "SELECT") + selectByValue(document.forms[0], id, value); + else if (elm.type == "checkbox") + elm.checked = !!value; + else + elm.value = value; + } + }; + + function getVal(id) { + var elm = document.getElementById(id); + + if (elm.nodeName == "SELECT") + return elm.options[elm.selectedIndex].value; + + if (elm.type == "checkbox") + return elm.checked; + + return elm.value; + }; + + window.FullPageDialog = { + changedStyle : function() { + var val, styles = tinyMCEPopup.editor.dom.parseStyle(getVal('style')); + + setVal('fontface', styles['font-face']); + setVal('fontsize', styles['font-size']); + setVal('textcolor', styles['color']); + + if (val = styles['background-image']) + setVal('bgimage', val.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1")); + else + setVal('bgimage', ''); + + setVal('bgcolor', styles['background-color']); + + // Reset margin form elements + setVal('topmargin', ''); + setVal('rightmargin', ''); + setVal('bottommargin', ''); + setVal('leftmargin', ''); + + // Expand margin + if (val = styles['margin']) { + val = val.split(' '); + styles['margin-top'] = val[0] || ''; + styles['margin-right'] = val[1] || val[0] || ''; + styles['margin-bottom'] = val[2] || val[0] || ''; + styles['margin-left'] = val[3] || val[0] || ''; + } + + if (val = styles['margin-top']) + setVal('topmargin', val.replace(/px/, '')); + + if (val = styles['margin-right']) + setVal('rightmargin', val.replace(/px/, '')); + + if (val = styles['margin-bottom']) + setVal('bottommargin', val.replace(/px/, '')); + + if (val = styles['margin-left']) + setVal('leftmargin', val.replace(/px/, '')); + + updateColor('bgcolor_pick', 'bgcolor'); + updateColor('textcolor_pick', 'textcolor'); + }, + + changedStyleProp : function() { + var val, dom = tinyMCEPopup.editor.dom, styles = dom.parseStyle(getVal('style')); + + styles['font-face'] = getVal('fontface'); + styles['font-size'] = getVal('fontsize'); + styles['color'] = getVal('textcolor'); + styles['background-color'] = getVal('bgcolor'); + + if (val = getVal('bgimage')) + styles['background-image'] = "url('" + val + "')"; + else + styles['background-image'] = ''; + + delete styles['margin']; + + if (val = getVal('topmargin')) + styles['margin-top'] = val + "px"; + else + styles['margin-top'] = ''; + + if (val = getVal('rightmargin')) + styles['margin-right'] = val + "px"; + else + styles['margin-right'] = ''; + + if (val = getVal('bottommargin')) + styles['margin-bottom'] = val + "px"; + else + styles['margin-bottom'] = ''; + + if (val = getVal('leftmargin')) + styles['margin-left'] = val + "px"; + else + styles['margin-left'] = ''; + + // Serialize, parse and reserialize this will compress redundant styles + setVal('style', dom.serializeStyle(dom.parseStyle(dom.serializeStyle(styles)))); + this.changedStyle(); + }, + + update : function() { + var data = {}; + + tinymce.each(tinyMCEPopup.dom.select('select,input,textarea'), function(node) { + data[node.id] = getVal(node.id); + }); + + tinyMCEPopup.editor.plugins.fullpage._dataToHtml(data); + tinyMCEPopup.close(); + } + }; + + function init() { + var form = document.forms[0], i, item, list, editor = tinyMCEPopup.editor; + + // Setup doctype select box + list = editor.getParam("fullpage_doctypes", defaultDocTypes).split(','); + for (i = 0; i < list.length; i++) { + item = list[i].split('='); + + if (item.length > 1) + addSelectValue(form, 'doctype', item[0], item[1]); + } + + // Setup fonts select box + list = editor.getParam("fullpage_fonts", defaultFontNames).split(';'); + for (i = 0; i < list.length; i++) { + item = list[i].split('='); + + if (item.length > 1) + addSelectValue(form, 'fontface', item[0], item[1]); + } + + // Setup fontsize select box + list = editor.getParam("fullpage_fontsizes", defaultFontSizes).split(','); + for (i = 0; i < list.length; i++) + addSelectValue(form, 'fontsize', list[i], list[i]); + + // Setup encodings select box + list = editor.getParam("fullpage_encodings", defaultEncodings).split(','); + for (i = 0; i < list.length; i++) { + item = list[i].split('='); + + if (item.length > 1) + addSelectValue(form, 'docencoding', item[0], item[1]); + } + + // Setup color pickers + document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor'); + document.getElementById('link_color_pickcontainer').innerHTML = getColorPickerHTML('link_color_pick','link_color'); + document.getElementById('visited_color_pickcontainer').innerHTML = getColorPickerHTML('visited_color_pick','visited_color'); + document.getElementById('active_color_pickcontainer').innerHTML = getColorPickerHTML('active_color_pick','active_color'); + document.getElementById('textcolor_pickcontainer').innerHTML = getColorPickerHTML('textcolor_pick','textcolor'); + document.getElementById('stylesheet_browsercontainer').innerHTML = getBrowserHTML('stylesheetbrowser','stylesheet','file','fullpage'); + document.getElementById('bgimage_pickcontainer').innerHTML = getBrowserHTML('bgimage_browser','bgimage','image','fullpage'); + + // Resize some elements + if (isVisible('stylesheetbrowser')) + document.getElementById('stylesheet').style.width = '220px'; + + if (isVisible('link_href_browser')) + document.getElementById('element_link_href').style.width = '230px'; + + if (isVisible('bgimage_browser')) + document.getElementById('bgimage').style.width = '210px'; + + // Update form + tinymce.each(tinyMCEPopup.getWindowArg('data'), function(value, key) { + setVal(key, value); + }); + + FullPageDialog.changedStyle(); + + // Update colors + updateColor('textcolor_pick', 'textcolor'); + updateColor('bgcolor_pick', 'bgcolor'); + updateColor('visited_color_pick', 'visited_color'); + updateColor('active_color_pick', 'active_color'); + updateColor('link_color_pick', 'link_color'); + }; + + tinyMCEPopup.onInit.add(init); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/fullpage/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/fullpage/langs/de_dlg.js new file mode 100755 index 0000000..ecdff9e --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullpage/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.fullpage_dlg',{title:"Dokument-Eigenschaften","meta_tab":"Allgemein","appearance_tab":"Aussehen","advanced_tab":"Erweitert","meta_props":"Meta-Information",langprops:"Sprache und Codierung","meta_title":"Titel","meta_keywords":"Keywords","meta_description":"Beschreibung","meta_robots":"Robots",doctypes:"DocType",langcode:"Sprachcode",langdir:"Sprachrichtung",ltr:"Links nach Rechts",rtl:"Rechts nach Links","xml_pi":"XML Deklaration",encoding:"Zeichencodierung","appearance_bgprops":"Hintergrund-Eigenschaften","appearance_marginprops":"Abst\u00e4nde des Body","appearance_linkprops":"Linkfarben","appearance_textprops":"Text-Eigenschaften",bgcolor:"Hintergrundfarbe",bgimage:"Hintergrundbild","left_margin":"Linker Abstand","right_margin":"Rechter Abstand","top_margin":"Oberer Abstand","bottom_margin":"Unterer Abstand","text_color":"Textfarbe","font_size":"Schriftgr\u00f6\u00dfe","font_face":"Schriftart","link_color":"Linkfarbe","hover_color":"Hover-Farbe","visited_color":"Visited-Farbe","active_color":"Active-Farbe",textcolor:"Farbe",fontsize:"Schriftgr\u00f6\u00dfe",fontface:"Schriftart","meta_index_follow":"Indizieren und den Links folgen","meta_index_nofollow":"Indizieren, aber den Links nicht folgen","meta_noindex_follow":"Nicht indizieren, aber den Links folgen","meta_noindex_nofollow":"Nicht indizieren und auch nicht den Links folgen","appearance_style":"CSS-Stylesheet und Stileigenschaften",stylesheet:"CSS-Stylesheet",style:"CSS-Stil",author:"Autor",copyright:"Copyright",add:"Neues Element hinzuf\u00fcgen",remove:"Ausgew\u00e4hltes Element entfernen",moveup:"Ausgew\u00e4hltes Element nach oben bewegen",movedown:"Ausgew\u00e4hltes Element nach unten bewegen","head_elements":"\u00dcberschriftenelemente",info:"Information","add_title":"Titel-Element","add_meta":"Meta-Element","add_script":"Script-Element","add_style":"Style-Element","add_link":"Link-Element","add_base":"Base-Element","add_comment":"HTML-Kommentar","title_element":"Titel-Element","script_element":"Script-Element","style_element":"Style-Element","base_element":"Base-Element","link_element":"Link-Element","meta_element":"Meta_Element","comment_element":"Kommentar",src:"Src",language:"Sprache",href:"Href",target:"Ziel",type:"Typ",charset:"Zeichensatz",defer:"Defer",media:"Media",properties:"Eigenschaften",name:"Name",value:"Wert",content:"Inhalt",rel:"Rel",rev:"Rev",hreflang:"Href lang","general_props":"Allgemein","advanced_props":"Erweitert"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fullpage/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/fullpage/langs/en_dlg.js new file mode 100755 index 0000000..516edc7 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullpage/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.fullpage_dlg',{title:"Document Properties","meta_tab":"General","appearance_tab":"Appearance","advanced_tab":"Advanced","meta_props":"Meta Information",langprops:"Language and Encoding","meta_title":"Title","meta_keywords":"Keywords","meta_description":"Description","meta_robots":"Robots",doctypes:"Doctype",langcode:"Language Code",langdir:"Language Direction",ltr:"Left to Right",rtl:"Right to Left","xml_pi":"XML Declaration",encoding:"Character Encoding","appearance_bgprops":"Background Properties","appearance_marginprops":"Body Margins","appearance_linkprops":"Link Colors","appearance_textprops":"Text Properties",bgcolor:"Background Color",bgimage:"Background Image","left_margin":"Left Margin","right_margin":"Right Margin","top_margin":"Top Margin","bottom_margin":"Bottom Margin","text_color":"Text Color","font_size":"Font Size","font_face":"Font Face","link_color":"Link Color","hover_color":"Hover Color","visited_color":"Visited Color","active_color":"Active Color",textcolor:"Color",fontsize:"Font Size",fontface:"Font Family","meta_index_follow":"Index and Follow the Links","meta_index_nofollow":"Index and Don\'t Follow the Links","meta_noindex_follow":"Do Not Index but Follow the Links","meta_noindex_nofollow":"Do Not Index and Don\'t Follow the Links","appearance_style":"Stylesheet and Style Properties",stylesheet:"Stylesheet",style:"Style",author:"Author",copyright:"Copyright",add:"Add New Element",remove:"Remove Selected Element",moveup:"Move Selected Element Up",movedown:"Move Selected Element Down","head_elements":"Head Elements",info:"Information","add_title":"Title Element","add_meta":"Meta Element","add_script":"Script Element","add_style":"Style Element","add_link":"Link Element","add_base":"Base Element","add_comment":"Comment Node","title_element":"Title Element","script_element":"Script Element","style_element":"Style Element","base_element":"Base Element","link_element":"Link Element","meta_element":"Meta Element","comment_element":"Comment",src:"Source",language:"Language",href:"HREF",target:"Target",type:"Type",charset:"Charset",defer:"Defer",media:"Media",properties:"Properties",name:"Name",value:"Value",content:"Content",rel:"Rel",rev:"Rev",hreflang:"HREF Lang","general_props":"General","advanced_props":"Advanced"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fullpage/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/fullpage/langs/fr_dlg.js new file mode 100755 index 0000000..c2ddc65 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullpage/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.fullpage_dlg',{title:"Propri\u00e9t\u00e9s du document","meta_tab":"G\u00e9n\u00e9ral","appearance_tab":"Apparence","advanced_tab":"Avanc\u00e9","meta_props":"Metadonn\u00e9es",langprops:"Langue et encodage","meta_title":"Titre","meta_keywords":"Mots-cl\u00e9s","meta_description":"Description","meta_robots":"Robots",doctypes:"Doctype",langcode:"Code de la langue",langdir:"Sens de lecture",ltr:"De gauche \u00e0 droite",rtl:"De droite \u00e0 gauche","xml_pi":"D\u00e9claration XML",encoding:"Encodage des caract\u00e8res","appearance_bgprops":"Propri\u00e9t\u00e9s du fond","appearance_marginprops":"Marge du corps de la page","appearance_linkprops":"Couleurs des liens","appearance_textprops":"Propri\u00e9t\u00e9s du texte",bgcolor:"Couleur de fond",bgimage:"Image de fond","left_margin":"Marge de gauche","right_margin":"Marge de droite","top_margin":"Marge du haut","bottom_margin":"Marge du bas","text_color":"Couleur du texte","font_size":"Taille de la police","font_face":"Nom de la police","link_color":"Couleur des liens","hover_color":"Couleur au survol","visited_color":"Couleur des liens visit\u00e9s","active_color":"Couleur du lien actif",textcolor:"Couleur",fontsize:"Taille de police",fontface:"Nom de la police","meta_index_follow":"Indexer et suivre les liens","meta_index_nofollow":"Indexer et ne pas suivre les liens","meta_noindex_follow":"Ne pas indexer et suivre les liens","meta_noindex_nofollow":"Ne pas indexer et ne pas suivre les liens","appearance_style":"Propri\u00e9t\u00e9s de la feuille de style et du style",stylesheet:"Feuille de style",style:"Style",author:"Auteur",copyright:"Copyright",add:"Ajouter un nouvel \u00e9l\u00e9ment",remove:"Retirer l\'\u00e9l\u00e9ment s\u00e9lectionn\u00e9",moveup:"D\u00e9placer l\'\u00e9l\u00e9ment s\u00e9lectionn\u00e9 vers le haut",movedown:"D\u00e9placer l\'\u00e9l\u00e9ment s\u00e9lectionn\u00e9 vers le bas","head_elements":"\u00c9l\u00e9ments d\'en-t\u00eate",info:"Information","add_title":"\u00c9l\u00e9ment de titre","add_meta":"\u00c9l\u00e9ment Meta","add_script":"\u00c9l\u00e9ment de script","add_style":"\u00c9l\u00e9ment de style","add_link":"\u00c9l\u00e9ment de lien","add_base":"\u00c9l\u00e9ment de base","add_comment":"Commentaire","title_element":"\u00c9l\u00e9ment de titre","script_element":"\u00c9l\u00e9ment de script","style_element":"\u00c9l\u00e9ment de style","base_element":"\u00c9l\u00e9ment de base","link_element":"\u00c9l\u00e9ment de lien","meta_element":"\u00c9l\u00e9ment Meta","comment_element":"Commentaire",src:"Source",language:"Langue",href:"Href",target:"Cible",type:"Type",charset:"Charset",defer:"D\u00e9f\u00e9rer",media:"M\u00e9dia",properties:"Propri\u00e9t\u00e9s",name:"Nom",value:"Valeur",content:"Contenu",rel:"Rel",rev:"Rev",hreflang:"langue Href","general_props":"G\u00e9n\u00e9ral","advanced_props":"Avanc\u00e9"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fullpage/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/fullpage/langs/it_dlg.js new file mode 100755 index 0000000..d5445e8 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullpage/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.fullpage_dlg',{title:"Propriet\u00e0 Documento","meta_tab":"Generale","appearance_tab":"Aspetto","advanced_tab":"Avanzate","meta_props":"Informazioni Metatag",langprops:"Lingua e codifica","meta_title":"Titolo","meta_keywords":"Parole chiave","meta_description":"Descrizione","meta_robots":"Robots",doctypes:"Doctype",langcode:"Codice lingua",langdir:"Direzione testo",ltr:"Sinistra verso destra",rtl:"Destra verso sinistra","xml_pi":"Dichiarazione XML",encoding:"Codifica carattere","appearance_bgprops":"Propriet\u00e0 sfondo","appearance_marginprops":"Margini body","appearance_linkprops":"Colori collegamenti","appearance_textprops":"Propriet\u00e0 testo",bgcolor:"Colore sfondo",bgimage:"Immagine sfondo","left_margin":"Margine sinistro","right_margin":"Margine destro","top_margin":"Margine superiore","bottom_margin":"Margine inferiore","text_color":"Colore testo","font_size":"Dimensione carattere","font_face":"Tipo carattere","link_color":"Colore collegamento","hover_color":"Colore \\\'Hover\\\'","visited_color":"Colore \\\'Visited\\\'","active_color":"Colore \\\'Active\\\'",textcolor:"Colore",fontsize:"Dimensione carattere",fontface:"Famiglia carattere","meta_index_follow":"Indicizzare e seguire collegamenti","meta_index_nofollow":"Indicizzare e non segure collegamenti","meta_noindex_follow":"Non indicizzare ma seguire collegamenti","meta_noindex_nofollow":"Non indicizzare e non seguire collegamenti","appearance_style":"Propriet\u00e0 stili e fogli di stile",stylesheet:"Fogli di stile",style:"Stile",author:"Autore",copyright:"Copyright",add:"Aggiungi nuovo elemento",remove:"Rimuovi elemento selezionato",moveup:"Sposta elemento selezionato in alto",movedown:"Sposta elemento selezionato in basso","head_elements":"Elementi Head",info:"Informazioni","add_title":"Elemento Titolo","add_meta":"Elemento Meta","add_script":"Elemento Script","add_style":"Elemento Style","add_link":"Elemento Link","add_base":"Elemento Base","add_comment":"Nodo Commento","title_element":"Elemento Titolo","script_element":"Elemento Script","style_element":"Elemento Style","base_element":"Elemento Base","link_element":"Elemento Link","meta_element":"Elemento Meta","comment_element":"Commento",src:"Sorgente",language:"Linguaggio",href:"Href",target:"Target",type:"Tipo",charset:"Set caratteri",defer:"Defer",media:"Media",properties:"Propriet\u00e0",name:"Nome",value:"Valore",content:"Contenuto",rel:"Rel",rev:"Rev",hreflang:"Href lang","general_props":"Generale","advanced_props":"Avanzate"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fullscreen/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/fullscreen/editor_plugin.js new file mode 100644 index 0000000..a6456f8 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullscreen/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.DOM;tinymce.create("tinymce.plugins.FullScreenPlugin",{init:function(d,e){var f=this,g={},c,b;f.editor=d;d.addCommand("mceFullScreen",function(){var i,j=a.doc.documentElement;if(d.getParam("fullscreen_is_enabled")){if(d.getParam("fullscreen_new_window")){closeFullscreen()}else{a.win.setTimeout(function(){tinymce.dom.Event.remove(a.win,"resize",f.resizeFunc);tinyMCE.get(d.getParam("fullscreen_editor_id")).setContent(d.getContent());tinyMCE.remove(d);a.remove("mce_fullscreen_container");j.style.overflow=d.getParam("fullscreen_html_overflow");a.setStyle(a.doc.body,"overflow",d.getParam("fullscreen_overflow"));a.win.scrollTo(d.getParam("fullscreen_scrollx"),d.getParam("fullscreen_scrolly"));tinyMCE.settings=tinyMCE.oldSettings},10)}return}if(d.getParam("fullscreen_new_window")){i=a.win.open(e+"/fullscreen.htm","mceFullScreenPopup","fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=yes,left=0,top=0,width="+screen.availWidth+",height="+screen.availHeight);try{i.resizeTo(screen.availWidth,screen.availHeight)}catch(h){}}else{tinyMCE.oldSettings=tinyMCE.settings;g.fullscreen_overflow=a.getStyle(a.doc.body,"overflow",1)||"auto";g.fullscreen_html_overflow=a.getStyle(j,"overflow",1);c=a.getViewPort();g.fullscreen_scrollx=c.x;g.fullscreen_scrolly=c.y;if(tinymce.isOpera&&g.fullscreen_overflow=="visible"){g.fullscreen_overflow="auto"}if(tinymce.isIE&&g.fullscreen_overflow=="scroll"){g.fullscreen_overflow="auto"}if(tinymce.isIE&&(g.fullscreen_html_overflow=="visible"||g.fullscreen_html_overflow=="scroll")){g.fullscreen_html_overflow="auto"}if(g.fullscreen_overflow=="0px"){g.fullscreen_overflow=""}a.setStyle(a.doc.body,"overflow","hidden");j.style.overflow="hidden";c=a.getViewPort();a.win.scrollTo(0,0);if(tinymce.isIE){c.h-=1}if(tinymce.isIE6){b="absolute;top:"+c.y}else{b="fixed;top:0"}n=a.add(a.doc.body,"div",{id:"mce_fullscreen_container",style:"position:"+b+";left:0;width:"+c.w+"px;height:"+c.h+"px;z-index:200000;"});a.add(n,"div",{id:"mce_fullscreen"});tinymce.each(d.settings,function(k,l){g[l]=k});g.id="mce_fullscreen";g.width=n.clientWidth;g.height=n.clientHeight-15;g.fullscreen_is_enabled=true;g.fullscreen_editor_id=d.id;g.theme_advanced_resizing=false;g.save_onsavecallback=function(){d.setContent(tinyMCE.get(g.id).getContent());d.execCommand("mceSave")};tinymce.each(d.getParam("fullscreen_settings"),function(m,l){g[l]=m});if(g.theme_advanced_toolbar_location==="external"){g.theme_advanced_toolbar_location="top"}f.fullscreenEditor=new tinymce.Editor("mce_fullscreen",g);f.fullscreenEditor.onInit.add(function(){f.fullscreenEditor.setContent(d.getContent());f.fullscreenEditor.focus()});f.fullscreenEditor.render();f.fullscreenElement=new tinymce.dom.Element("mce_fullscreen_container");f.fullscreenElement.update();f.resizeFunc=tinymce.dom.Event.add(a.win,"resize",function(){var o=tinymce.DOM.getViewPort(),l=f.fullscreenEditor,k,m;k=l.dom.getSize(l.getContainer().firstChild);m=l.dom.getSize(l.getContainer().getElementsByTagName("iframe")[0]);l.theme.resizeTo(o.w-k.w+m.w,o.h-k.h+m.h)})}});d.addButton("fullscreen",{title:"fullscreen.desc",cmd:"mceFullScreen"});d.onNodeChange.add(function(i,h){h.setActive("fullscreen",i.getParam("fullscreen_is_enabled"))})},getInfo:function(){return{longname:"Fullscreen",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("fullscreen",tinymce.plugins.FullScreenPlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fullscreen/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/fullscreen/editor_plugin_src.js new file mode 100644 index 0000000..afa4f9b --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullscreen/editor_plugin_src.js @@ -0,0 +1,159 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var DOM = tinymce.DOM; + + tinymce.create('tinymce.plugins.FullScreenPlugin', { + init : function(ed, url) { + var t = this, s = {}, vp, posCss; + + t.editor = ed; + + // Register commands + ed.addCommand('mceFullScreen', function() { + var win, de = DOM.doc.documentElement; + + if (ed.getParam('fullscreen_is_enabled')) { + if (ed.getParam('fullscreen_new_window')) + closeFullscreen(); // Call to close in new window + else { + DOM.win.setTimeout(function() { + tinymce.dom.Event.remove(DOM.win, 'resize', t.resizeFunc); + tinyMCE.get(ed.getParam('fullscreen_editor_id')).setContent(ed.getContent()); + tinyMCE.remove(ed); + DOM.remove('mce_fullscreen_container'); + de.style.overflow = ed.getParam('fullscreen_html_overflow'); + DOM.setStyle(DOM.doc.body, 'overflow', ed.getParam('fullscreen_overflow')); + DOM.win.scrollTo(ed.getParam('fullscreen_scrollx'), ed.getParam('fullscreen_scrolly')); + tinyMCE.settings = tinyMCE.oldSettings; // Restore old settings + }, 10); + } + + return; + } + + if (ed.getParam('fullscreen_new_window')) { + win = DOM.win.open(url + "/fullscreen.htm", "mceFullScreenPopup", "fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=yes,left=0,top=0,width=" + screen.availWidth + ",height=" + screen.availHeight); + try { + win.resizeTo(screen.availWidth, screen.availHeight); + } catch (e) { + // Ignore + } + } else { + tinyMCE.oldSettings = tinyMCE.settings; // Store old settings + s.fullscreen_overflow = DOM.getStyle(DOM.doc.body, 'overflow', 1) || 'auto'; + s.fullscreen_html_overflow = DOM.getStyle(de, 'overflow', 1); + vp = DOM.getViewPort(); + s.fullscreen_scrollx = vp.x; + s.fullscreen_scrolly = vp.y; + + // Fixes an Opera bug where the scrollbars doesn't reappear + if (tinymce.isOpera && s.fullscreen_overflow == 'visible') + s.fullscreen_overflow = 'auto'; + + // Fixes an IE bug where horizontal scrollbars would appear + if (tinymce.isIE && s.fullscreen_overflow == 'scroll') + s.fullscreen_overflow = 'auto'; + + // Fixes an IE bug where the scrollbars doesn't reappear + if (tinymce.isIE && (s.fullscreen_html_overflow == 'visible' || s.fullscreen_html_overflow == 'scroll')) + s.fullscreen_html_overflow = 'auto'; + + if (s.fullscreen_overflow == '0px') + s.fullscreen_overflow = ''; + + DOM.setStyle(DOM.doc.body, 'overflow', 'hidden'); + de.style.overflow = 'hidden'; //Fix for IE6/7 + vp = DOM.getViewPort(); + DOM.win.scrollTo(0, 0); + + if (tinymce.isIE) + vp.h -= 1; + + // Use fixed position if it exists + if (tinymce.isIE6) + posCss = 'absolute;top:' + vp.y; + else + posCss = 'fixed;top:0'; + + n = DOM.add(DOM.doc.body, 'div', { + id : 'mce_fullscreen_container', + style : 'position:' + posCss + ';left:0;width:' + vp.w + 'px;height:' + vp.h + 'px;z-index:200000;'}); + DOM.add(n, 'div', {id : 'mce_fullscreen'}); + + tinymce.each(ed.settings, function(v, n) { + s[n] = v; + }); + + s.id = 'mce_fullscreen'; + s.width = n.clientWidth; + s.height = n.clientHeight - 15; + s.fullscreen_is_enabled = true; + s.fullscreen_editor_id = ed.id; + s.theme_advanced_resizing = false; + s.save_onsavecallback = function() { + ed.setContent(tinyMCE.get(s.id).getContent()); + ed.execCommand('mceSave'); + }; + + tinymce.each(ed.getParam('fullscreen_settings'), function(v, k) { + s[k] = v; + }); + + if (s.theme_advanced_toolbar_location === 'external') + s.theme_advanced_toolbar_location = 'top'; + + t.fullscreenEditor = new tinymce.Editor('mce_fullscreen', s); + t.fullscreenEditor.onInit.add(function() { + t.fullscreenEditor.setContent(ed.getContent()); + t.fullscreenEditor.focus(); + }); + + t.fullscreenEditor.render(); + + t.fullscreenElement = new tinymce.dom.Element('mce_fullscreen_container'); + t.fullscreenElement.update(); + //document.body.overflow = 'hidden'; + + t.resizeFunc = tinymce.dom.Event.add(DOM.win, 'resize', function() { + var vp = tinymce.DOM.getViewPort(), fed = t.fullscreenEditor, outerSize, innerSize; + + // Get outer/inner size to get a delta size that can be used to calc the new iframe size + outerSize = fed.dom.getSize(fed.getContainer().firstChild); + innerSize = fed.dom.getSize(fed.getContainer().getElementsByTagName('iframe')[0]); + + fed.theme.resizeTo(vp.w - outerSize.w + innerSize.w, vp.h - outerSize.h + innerSize.h); + }); + } + }); + + // Register buttons + ed.addButton('fullscreen', {title : 'fullscreen.desc', cmd : 'mceFullScreen'}); + + ed.onNodeChange.add(function(ed, cm) { + cm.setActive('fullscreen', ed.getParam('fullscreen_is_enabled')); + }); + }, + + getInfo : function() { + return { + longname : 'Fullscreen', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('fullscreen', tinymce.plugins.FullScreenPlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fullscreen/fullscreen.htm b/src/core/static/js/tiny_mce/plugins/fullscreen/fullscreen.htm new file mode 100644 index 0000000..ffe528e --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fullscreen/fullscreen.htm @@ -0,0 +1,110 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title></title> + <meta http-equiv="X-UA-Compatible" content="IE=edge" /> + <script type="text/javascript" src="../../tiny_mce.js"></script> + <script type="text/javascript"> + function patchCallback(settings, key) { + if (settings[key]) + settings[key] = "window.opener." + settings[key]; + } + + var settings = {}, paSe = window.opener.tinyMCE.activeEditor.settings, oeID = window.opener.tinyMCE.activeEditor.id; + + // Clone array + for (var n in paSe) + settings[n] = paSe[n]; + + // Override options for fullscreen + for (var n in paSe.fullscreen_settings) + settings[n] = paSe.fullscreen_settings[n]; + + // Patch callbacks, make them point to window.opener + patchCallback(settings, 'urlconverter_callback'); + patchCallback(settings, 'insertlink_callback'); + patchCallback(settings, 'insertimage_callback'); + patchCallback(settings, 'setupcontent_callback'); + patchCallback(settings, 'save_callback'); + patchCallback(settings, 'onchange_callback'); + patchCallback(settings, 'init_instance_callback'); + patchCallback(settings, 'file_browser_callback'); + patchCallback(settings, 'cleanup_callback'); + patchCallback(settings, 'execcommand_callback'); + patchCallback(settings, 'oninit'); + + // Set options + delete settings.id; + settings['mode'] = 'exact'; + settings['elements'] = 'fullscreenarea'; + settings['add_unload_trigger'] = false; + settings['ask'] = false; + settings['document_base_url'] = window.opener.tinyMCE.activeEditor.documentBaseURI.getURI(); + settings['fullscreen_is_enabled'] = true; + settings['fullscreen_editor_id'] = oeID; + settings['theme_advanced_resizing'] = false; + settings['strict_loading_mode'] = true; + + settings.save_onsavecallback = function() { + window.opener.tinyMCE.get(oeID).setContent(tinyMCE.get('fullscreenarea').getContent({format : 'raw'}), {format : 'raw'}); + window.opener.tinyMCE.get(oeID).execCommand('mceSave'); + window.close(); + }; + + function unloadHandler(e) { + moveContent(); + } + + function moveContent() { + window.opener.tinyMCE.get(oeID).setContent(tinyMCE.activeEditor.getContent()); + } + + function closeFullscreen() { + moveContent(); + window.close(); + } + + function doParentSubmit() { + moveContent(); + + if (window.opener.tinyMCE.selectedInstance.formElement.form) + window.opener.tinyMCE.selectedInstance.formElement.form.submit(); + + window.close(); + + return false; + } + + function render() { + var e = document.getElementById('fullscreenarea'), vp, ed, ow, oh, dom = tinymce.DOM; + + e.value = window.opener.tinyMCE.get(oeID).getContent(); + + vp = dom.getViewPort(); + settings.width = vp.w; + settings.height = vp.h - 15; + + tinymce.dom.Event.add(window, 'resize', function() { + var vp = dom.getViewPort(); + + tinyMCE.activeEditor.theme.resizeTo(vp.w, vp.h); + }); + + tinyMCE.init(settings); + } + + // Add onunload + tinymce.dom.Event.add(window, "beforeunload", unloadHandler); + </script> +</head> +<body style="margin:0;overflow:hidden;width:100%;height:100%" scrolling="no" scroll="no"> +<form onsubmit="doParentSubmit();"> +<textarea id="fullscreenarea" style="width:100%; height:100%"></textarea> +</form> + +<script type="text/javascript"> + render(); +</script> + +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/css/styles.css b/src/core/static/js/tiny_mce/plugins/fxeditor/css/styles.css new file mode 100644 index 0000000..44bf0d0 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/css/styles.css @@ -0,0 +1,88 @@ +article,aside,details,figcaption,figure,footer,header,hgroup,nav,section,summary{display:block;} +audio,canvas,video{display:inline-block;*display:inline;*zoom:1;} +audio:not([controls]){display:none;height:0;} +[hidden]{display:none;} +html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;} +html,button,input,select,textarea{font-family:sans-serif;} +body{margin:0;} +a:focus{outline:thin dotted;} +a:active,a:hover{outline:0;} +h1{font-size:2em;margin:0.67em 0;} +h2{font-size:1.5em;margin:0.83em 0;} +h3{font-size:1.17em;margin:1em 0;} +h4{font-size:1em;margin:1.33em 0;} +h5{font-size:0.83em;margin:1.67em 0;} +h6{font-size:0.75em;margin:2.33em 0;} +abbr[title]{border-bottom:1px dotted;} +b,strong{font-weight:bold;} +blockquote{margin:1em 40px;} +dfn{font-style:italic;} +mark{background:#ff0;color:#000;} +p,pre{margin:1em 0;} +code,kbd,pre,samp{font-family:monospace, serif;_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:80%;} +sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;} +sup{top:-0.5em;} +sub{bottom:-0.25em;} +dl,menu,ol,ul{margin:1em 0;} +dd{margin:0 0 0 40px;} +menu,ol,ul{padding:0 0 0 40px;} +nav ul,nav ol{list-style:none;list-style-image:none;} +img{border:0;-ms-interpolation-mode:bicubic;} +svg:not(:root){overflow:hidden;} +figure{margin:0;} +form{margin:0;} +fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;} +legend{border:0;padding:0;white-space:normal;*margin-left:-7px;} +button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;} +button,input{line-height:normal;} +button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;*overflow:visible;} +button[disabled],input[disabled]{cursor:default;} +input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*height:13px;*width:13px;} +input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;} +input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;} +button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;} +textarea{overflow:auto;vertical-align:top;} +table{border-collapse:collapse;border-spacing:0;} +html,button,input,select,textarea{color:#222;} +body{font-size:1em;line-height:1.4;} +::-moz-selection{background:#b3d4fc;text-shadow:none;} +::selection{background:#b3d4fc;text-shadow:none;} +hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:1em 0;padding:0;} +img{vertical-align:middle;} +fieldset{border:0;margin:0;padding:0;} +textarea{resize:vertical;} +.chromeframe{margin:0.2em 0;background:#ccc;color:#000;padding:0.2em 0;} +.ir{background-color:transparent;border:0;overflow:hidden;*text-indent:-9999px;} +.ir:before{content:"";display:block;width:0;height:100%;} +.hidden{display:none !important;visibility:hidden;} +.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;} +.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto;} +.invisible{visibility:hidden;} +.clearfix:before,.clearfix:after{content:" ";display:table;} +.clearfix:after{clear:both;} +.clearfix{*zoom:1;} +@media only screen and (min-width:35em){}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-resolution:144dpi){}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-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{font-family:Arial,Helvetica,sans-serif;color:#333;font-size:12px;} +a{color:#333;text-decoration:none;}a:hover{text-decoration:underline;} +input[type="button"],input[type="submit"],input[type="reset"],button{width:auto;border:0;font-size:14px;background:;color:#333;padding:7px 15px 5px 15px;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;border:1px solid #ccc;background:#f4f4f4;background:-moz-linear-gradient(top, #f4f4f4 0%, #e9e9e9 100%);background:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #f4f4f4), color-stop(100%, #e9e9e9));background:-webkit-linear-gradient(top, #f4f4f4 0%, #e9e9e9 100%);background:-o-linear-gradient(top, #f4f4f4 0%, #e9e9e9 100%);background:-ms-linear-gradient(top, #f4f4f4 0%, #e9e9e9 100%);background:linear-gradient(to bottom, #f4f4f4 0%, #e9e9e9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f4f4f4', endColorstr='#e9e9e9', GradientType=0);}input[type="button"]:active,input[type="submit"]:active,input[type="reset"]:active,button:active{-moz-box-shadow:inset 0 0 10px #999999;-webkit-box-shadow:inset 0 0 10px #999999;box-shadow:inset 0 0 10px #999999;} +input[type="button"],input[type="submit"]{font-weight:bold;} +#outer{padding:10px;} +.content{width:880px;margin:0 auto;position:relative;background:url(../images/bg/content.png) repeat-y center;}.content #tab-menu{height:27px;float:left;width:880px;padding:0px 0 0 0;border-bottom:1px solid #ccc;background-color:#fff;}.content #tab-menu ul.tab{padding:0;margin:0;margin-top:4px;margin-left:8px;}.content #tab-menu ul.tab li{display:inline;float:left;}.content #tab-menu ul.tab li a{display:inline-block;background-color:#E0E0E0;font-size:13px;padding:2px 6px 2px 6px;margin-right:1px;border:1px solid #ccc;height:18px;}.content #tab-menu ul.tab li a:hover,.content #tab-menu ul.tab li a.active{background-color:#fff;text-decoration:none;border-bottom:1px solid #fff;} +.content #tab-menu ul.tab li a.active{font-weight:bold;} +.content .side-sx{width:440px;display:none;min-height:276px;float:left;padding:10px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-left:1px solid #ccc;}.content .side-sx .formula{padding:0;margin:0;}.content .side-sx .formula li{display:inline;list-style:none;}.content .side-sx .formula li a{display:inline-block;margin:0 5px 5px 0;} +.content .side-dx{float:right;width:440px;padding:10px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-right:1px solid #ccc;min-height:276px;}.content .side-dx .editor-box textarea{border:1px solid #ccc;width:368px;height:166px;} +.content .side-dx .editor-box .results{text-align:center;margin-top:20px;} +.content .row-button{height:43px;display:block;width:880px;float:left;border-top:1px solid #ccc;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:8px;text-align:right;background-color:#fff;} +.content .editor-toolbar ul li{display:inline;list-style:none;} +.content ul.toolbar{background-color:#E0E0E0;border:1px solid #ccc;padding:0 0 0 0;margin:0px;margin-top:2px;margin-left:440px;margin-right:0;height:22px;}.content ul.toolbar li{display:inline;float:left;}.content ul.toolbar li a{display:inline-block;background-color:#E0E0E0;font-size:13px;padding:2px 6px 2px 20px;margin-right:1px;}.content ul.toolbar li a#undo-command{background:url(../images/ico/ico.png) -4px 4px no-repeat;} +.content ul.toolbar li a#redo-command{background:url(../images/ico/ico.png) -4px -39px no-repeat;} +.content ul.toolbar li a#cut-command{background:url(../images/ico/ico.png) -2px -215px no-repeat;} +.content ul.toolbar li a#copy-command{background:url(../images/ico/ico.png) -4px -130px no-repeat;} +.content ul.toolbar li a#paste-command{background:url(../images/ico/ico.png) -4px -83px no-repeat;} +.content ul.toolbar li a#delete-command{background:url(../images/ico/ico.png) -4px -170px no-repeat;} +.content ul.toolbar li a:hover{background-color:#ccc!important;text-decoration:none;} +.content ul.toolbar li a.active{font-weight:bold;} +.content ul.toolbar li select{position:absolute;margin-top:2px;} diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/dialog.html b/src/core/static/js/tiny_mce/plugins/fxeditor/dialog.html new file mode 100755 index 0000000..36c3508 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/dialog.html @@ -0,0 +1,511 @@ +<!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>{#fxeditor_dlg.title}</title> + <meta name="description" content=""> + <meta name="viewport" content="width=device-width"> + + <!-- Map of math commands and symbols --> + <script type="text/javascript" src="js/mathmap.js?v=4"></script> + + <!-- TinyMCE --> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/dialog.js"></script> + + <!-- JQUERY LIB --> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> + <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.8.2.min.js"><\/script>')</script> + <!-- JQUERY LIB --> + + <script src="js/vendor/modernizr-2.6.2.min.js"></script> + + <!-- jQuery textrange plugin: to manage textarea text selection--> + <script type="text/javascript" src="js/jquery-textrange.js"></script> + + <!-- MathJAX --> + <script type="text/x-mathjax-config"> + MathJax.Hub.Config({ + config: ["MMLorHTML.js"], + jax: ["input/TeX","input/MathML","input/AsciiMath","output/HTML-CSS","output/NativeMML"], + extensions: ["tex2jax.js","mml2jax.js","asciimath2jax.js","MathMenu.js","MathZoom.js","toMathML.js"], + TeX: { + extensions: ["AMSmath.js","AMSsymbols.js","noErrors.js","noUndefined.js"] + }, + showProcessingMessages: true, + messageStyle: "simple", + showMathMenu: false, + showMathMenuMSIE: false, + "HTML-CSS": { + linebreaks: { + automatic: true, + width: "container" + } + }, + MMLorHTML: { + prefer: { + MSIE: "MML", + Firefox: "HTML", + Opera: "HTML", + Safari: "HTML", + Chrome: "HTML", + other: "HTML" + } + } + }); + </script> + + <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js"></script> + <!-- MathJAX --> + + <!-- Buffered UndoManager --> + <script type="text/javascript" src="js/underscore-min.js"></script> + <script type="text/javascript" src="js/undo-manager.js"></script> + + + <link rel="stylesheet" href="css/styles.css?v=18"> + + </head> + <body> + <script> + </script> + <!--[if lt IE 8]> + <p class="chromeframe">Stai usando un browser <strong>non supportato</strong>. Per favore <a href="http://browsehappy.com/">aggiorna il tuo browser</a> o <a href="http://www.google.com/chromeframe/?redirect=true">attiva Google Chrome Frame</a> per far diventare pi&ugrave; potente il tuo browser.</p> + <![endif]--> + + <!-- outer --> + <div id="outer"> + + <!-- content --> + <div class="content clearfix"> + + <!-- nav --> + <nav id="tab-menu"> + <ul class="tab"> + <li><a href="javascript:FormulaEditorDialog.selectTab('math-tab');" class="active">Math</a></li> + <li><a href="javascript:FormulaEditorDialog.selectTab('fun-tab');">Fun</a></li> + <li><a href="javascript:FormulaEditorDialog.selectTab('logic-tab');">Logic</a></li> + <li><a href="javascript:FormulaEditorDialog.selectTab('arrow-tab');">Arrow</a></li> + <li><a href="javascript:FormulaEditorDialog.selectTab('symbol-tab');">Symbol</a></li> + <li><a href="javascript:FormulaEditorDialog.selectTab('format-tab');">Format</a></li> + </ul> + <ul class="toolbar"> + <li><a href="javascript:FormulaEditorDialog.undo();" id="undo-command">Undo</a></li> + <li><a href="javascript:FormulaEditorDialog.redo();" id="redo-command">Redo</a></li> + <li><a href="javascript:FormulaEditorDialog.cut();" id="cut-command">Cut</a></li> + <li><a href="javascript:FormulaEditorDialog.copy();" id="copy-command">Copy</a></li> + <li><a href="javascript:FormulaEditorDialog.paste();" id="paste-command">Paste</a></li> + <li><a href="javascript:FormulaEditorDialog.clear();" id="delete-command">Delete</a></li> + <li> + <select id="mathjax-mode-select"> + <option value="tex">TeX</option> + <option value="am">AsciiMath</option> + <option value="mml">MathML</option> + </select> + </li> + </ul> + </nav> + <!-- nav --> + + <!-- sx --> + <div id="math-tab" class="side-sx" style="display: block"> + + <ul class="formula"> + <li><a href="javascript:void(0);" data-tex-command="times"><script type="math/tex; mode=display">\times</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="div"><script type="math/tex; mode=display">\div</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="pm"><script type="math/tex; mode=display">\pm</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="mp"><script type="math/tex; mode=display">\mp</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="cdot"><script type="math/tex; mode=display">\cdot</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="star"><script type="math/tex; mode=display">\star</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sqrt"><script type="math/tex; mode=display">\sqrt{ab}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rootn"><script type="math/tex; mode=display">\sqrt[n]{ab}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="logax"><script type="math/tex; mode=display">\log_{a}{x}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="lnx"><script type="math/tex; mode=display">\ln{x}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="pow"><script type="math/tex; mode=display">a^{b}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="subscr"><script type="math/tex; mode=display">a_{b}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="subsup"><script type="math/tex; mode=display">c_a^b</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="tilde"><script type="math/tex; mode=display">\widetilde{ab}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="hat"><script type="math/tex; mode=display">\widehat{ab}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="vecl"><script type="math/tex; mode=display">\overleftarrow{ab}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="vec"><script type="math/tex; mode=display">\overrightarrow{ab}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="overbr"><script type="math/tex; mode=display">\overbrace{ab}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="underbr"><script type="math/tex; mode=display">\underbrace{ab}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="underl"><script type="math/tex; mode=display">\underline{ab}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="overl"><script type="math/tex; mode=display">\overline{ab}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="bmatrix"><script type="math/tex; mode=display">\begin{bmatrix}a & b \\c & d \end{bmatrix}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="cases"><script type="math/tex; mode=display">\begin{cases}a & x = 0\\b & x > 0\end{cases}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="frac"><script type="math/tex; mode=display">\frac{ab}{cd}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="delab"><script type="math/tex; mode=display">\frac{\partial a}{\partial b}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="dxdy"><script type="math/tex; mode=display">\frac{\text{d}x}{\text{d}y}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="limx0"><script type="math/tex; mode=display">\lim_{x \rightarrow 0}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="integr"><script type="math/tex; mode=display">\int_{a}^{b}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="ointegr"><script type="math/tex; mode=display">\oint_a^b</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="prod"><script type="math/tex; mode=display">\prod_a^b</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="coprod"><script type="math/tex; mode=display">\coprod_a^b</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="bigcap"><script type="math/tex; mode=display">\bigcap_a^b </script></a></li> + <li><a href="javascript:void(0);" data-tex-command="bigcup"><script type="math/tex; mode=display">\bigcup_a^b</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="bigvee"><script type="math/tex; mode=display">\bigvee_a^b</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="bigwed"><script type="math/tex; mode=display">\bigwedge_a^b</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="bigsqc"><script type="math/tex; mode=display">\bigsqcup_a^b</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sum"><script type="math/tex; mode=display">\sum_{n=0}^\infty</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="arrayab"><script type="math/tex; mode=display">\left(\begin{array}{c}a\\ b\end{array}\right)</script></a></li> + </ul> + + </div> + + <div id="fun-tab" class="side-sx"> + <ul class="formula"> + <li><a href="javascript:void(0);" data-tex-command="alpha"><script type="math/tex; mode=display">\alpha</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="beta"><script type="math/tex; mode=display">\beta</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="gamma"><script type="math/tex; mode=display">\gamma</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="delta"><script type="math/tex; mode=display">\delta</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="epsilon"><script type="math/tex; mode=display">\epsilon</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="zeta"><script type="math/tex; mode=display">\zeta</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="eta"><script type="math/tex; mode=display">\eta</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="theta"><script type="math/tex; mode=display">\theta</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="iota"><script type="math/tex; mode=display">\iota</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="kappa"><script type="math/tex; mode=display">\kappa</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="lambda"><script type="math/tex; mode=display">\lambda</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="mu"><script type="math/tex; mode=display">\mu</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="nu"><script type="math/tex; mode=display">\nu</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="xi"><script type="math/tex; mode=display">\xi</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="pi"><script type="math/tex; mode=display">\pi</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rho"><script type="math/tex; mode=display">\rho</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sigma"><script type="math/tex; mode=display">\sigma</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="tau"><script type="math/tex; mode=display">\tau</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="upsilon"><script type="math/tex; mode=display">\upsilon</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="phi"><script type="math/tex; mode=display">\phi</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="chi"><script type="math/tex; mode=display">\chi</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="psi"><script type="math/tex; mode=display">\psi</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="omega"><script type="math/tex; mode=display">\omega</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Gamma"><script type="math/tex; mode=display">\Gamma</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Delta"><script type="math/tex; mode=display">\Delta</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Theta"><script type="math/tex; mode=display">\Theta</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Lambda"><script type="math/tex; mode=display">\Lambda</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Xi"><script type="math/tex; mode=display">\Xi</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Pi"><script type="math/tex; mode=display">\Pi</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Sigma"><script type="math/tex; mode=display">\Sigma</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Upsilon"><script type="math/tex; mode=display">\Upsilon</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Phi"><script type="math/tex; mode=display">\Phi</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Psi"><script type="math/tex; mode=display">\Psi</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Omega"><script type="math/tex; mode=display">\Omega</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="varepsilon"><script type="math/tex; mode=display">\varepsilon</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="vartheta"><script type="math/tex; mode=display">\vartheta</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="varrho"><script type="math/tex; mode=display">\varrho</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="varsigma"><script type="math/tex; mode=display">\varsigma</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="varphi"><script type="math/tex; mode=display">\varphi</script></a></li> + </ul> + <ul class="formula"> + <li><a href="javascript:void(0);" data-tex-command="arccos"><script type="math/tex; mode=display">\arccos</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="arcsin"><script type="math/tex; mode=display">\arcsin</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="arctan"><script type="math/tex; mode=display">\arctan</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="cos"><script type="math/tex; mode=display">\cos</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="cosh"><script type="math/tex; mode=display">\cosh</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="cot"><script type="math/tex; mode=display">\cot</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="coth"><script type="math/tex; mode=display">\coth</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="csc"><script type="math/tex; mode=display">\csc</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sec"><script type="math/tex; mode=display">\sec</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sin"><script type="math/tex; mode=display">\sin</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sinh"><script type="math/tex; mode=display">\sinh</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="tan"><script type="math/tex; mode=display">\tan</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="tanh"><script type="math/tex; mode=display">\tanh</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="exp"><script type="math/tex; mode=display">\exp</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="log"><script type="math/tex; mode=display">\log</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="ln"><script type="math/tex; mode=display">\ln</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="max"><script type="math/tex; mode=display">\max</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="min"><script type="math/tex; mode=display">\min</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sup"><script type="math/tex; mode=display">\sup</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="inf"><script type="math/tex; mode=display">\inf</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="lim"><script type="math/tex; mode=display">\lim</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="gcd"><script type="math/tex; mode=display">\gcd</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="hom"><script type="math/tex; mode=display">\hom</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="ker"><script type="math/tex; mode=display">\ker</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="det"><script type="math/tex; mode=display">\det</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="bmod"><script type="math/tex; mode=display">\bmod</script></a></li> + </ul> + </div> + <div id="logic-tab" class="side-sx"> + <ul class="formula"> + <li><a href="javascript:void(0);" data-tex-command="neq"><script type="math/tex; mode=display">\neq</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leq"><script type="math/tex; mode=display">\leq</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="geq"><script type="math/tex; mode=display">\geq</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sim"><script type="math/tex; mode=display">\sim</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="approx"><script type="math/tex; mode=display">\approx</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="cong"><script type="math/tex; mode=display">\cong</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="equiv"><script type="math/tex; mode=display">\equiv</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="propto"><script type="math/tex; mode=display">\propto</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="ll"><script type="math/tex; mode=display">\ll</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="gg"><script type="math/tex; mode=display">\gg</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="in_"><script type="math/tex; mode=display">\in</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="notin"><script type="math/tex; mode=display">\notin</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="ni"><script type="math/tex; mode=display">\ni</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="subset"><script type="math/tex; mode=display">\subset</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="subseteq"><script type="math/tex; mode=display">\subseteq</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="prec"><script type="math/tex; mode=display">\prec</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="preceq"><script type="math/tex; mode=display">\preceq</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="simeq"><script type="math/tex; mode=display">\simeq</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="asymp"><script type="math/tex; mode=display">\asymp</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="doteq"><script type="math/tex; mode=display">\doteq</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="succ"><script type="math/tex; mode=display">\succ</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="succeq"><script type="math/tex; mode=display">\succeq</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sqsubseteq"><script type="math/tex; mode=display">\sqsubseteq</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sqsupseteq"><script type="math/tex; mode=display">\sqsupseteq</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="models"><script type="math/tex; mode=display">\models</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="vdash"><script type="math/tex; mode=display">\vdash</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="dashv"><script type="math/tex; mode=display">\dashv</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="perp"><script type="math/tex; mode=display">\perp</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="mid"><script type="math/tex; mode=display">\mid</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="parallel"><script type="math/tex; mode=display">\parallel</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="smile"><script type="math/tex; mode=display">\smile</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="frown"><script type="math/tex; mode=display">\frown</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="bowtie"><script type="math/tex; mode=display">\bowtie</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="unlhd"><script type="math/tex; mode=display">\unlhd</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="unrhd"><script type="math/tex; mode=display">\unrhd</script></a></li> + </ul> + <ul class="formula"> + <li><a href="javascript:void(0);" data-tex-command="hata"><script type="math/tex; mode=display">\hat{a}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="checka"><script type="math/tex; mode=display">\check{a}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="brevea"><script type="math/tex; mode=display">\breve{a}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="acutea"><script type="math/tex; mode=display">\acute{a}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="gravea"><script type="math/tex; mode=display">\grave{a}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="tildea"><script type="math/tex; mode=display">\tilde{a}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="bara"><script type="math/tex; mode=display">\bar{a}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="veca"><script type="math/tex; mode=display">\vec{a}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="dota"><script type="math/tex; mode=display">\dot{a}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="ddota"><script type="math/tex; mode=display">\ddot{a}</script></a></li> + </ul> + </div> + <div id="arrow-tab" class="side-sx"> + <ul class="formula"> + <li><a href="javascript:void(0);" data-tex-command="leftp"><script type="math/tex; mode=display">(</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rightp"><script type="math/tex; mode=display">)</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftsp"><script type="math/tex; mode=display">[</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rightsp"><script type="math/tex; mode=display">]</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftgp"><script type="math/tex; mode=display">\{</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rightgp"><script type="math/tex; mode=display">\}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="lfloor"><script type="math/tex; mode=display">\lfloor</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="lceil"><script type="math/tex; mode=display">\lceil</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rfloor"><script type="math/tex; mode=display">\rfloor</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rceil"><script type="math/tex; mode=display">\rceil</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="langle"><script type="math/tex; mode=display">\langle</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rangle"><script type="math/tex; mode=display">\rangle</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="backslash"><script type="math/tex; mode=display">\backslash</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="cap"><script type="math/tex; mode=display">\cap</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="cup"><script type="math/tex; mode=display">\cup</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="uplus"><script type="math/tex; mode=display">\uplus</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sqcap"><script type="math/tex; mode=display">\sqcap</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sqcup"><script type="math/tex; mode=display">\sqcup</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="vee"><script type="math/tex; mode=display">\vee</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="wedge"><script type="math/tex; mode=display">\wedge</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="wr"><script type="math/tex; mode=display">\wr</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftarrow"><script type="math/tex; mode=display">\leftarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Leftarrow"><script type="math/tex; mode=display">\Leftarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rightarrow"><script type="math/tex; mode=display">\rightarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Rightarrow"><script type="math/tex; mode=display">\Rightarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftrightarrow"><script type="math/tex; mode=display">\leftrightarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Leftrightarrow"><script type="math/tex; mode=display">\Leftrightarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="mapsto"><script type="math/tex; mode=display">\mapsto</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftharpoonup"><script type="math/tex; mode=display">\leftharpoonup</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftharpoondown"><script type="math/tex; mode=display">\leftharpoondown</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rightleftharpoons"><script type="math/tex; mode=display">\rightleftharpoons</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftrightharpoons"><script type="math/tex; mode=display">\leftrightharpoons</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="hookrightarrow"><script type="math/tex; mode=display">\hookrightarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rightharpoonup"><script type="math/tex; mode=display">\rightharpoonup</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="uparrow"><script type="math/tex; mode=display">\uparrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Uparrow"><script type="math/tex; mode=display">\Uparrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="downarrow"><script type="math/tex; mode=display">\downarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Downarrow"><script type="math/tex; mode=display">\Downarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="updownarrow"><script type="math/tex; mode=display">\updownarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Updownarrow"><script type="math/tex; mode=display">\Updownarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftleftarrows"><script type="math/tex; mode=display">\leftleftarrows</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rightrightarrows"><script type="math/tex; mode=display">\rightrightarrows</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftrightarrows"><script type="math/tex; mode=display">\leftrightarrows</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rightleftarrows"><script type="math/tex; mode=display">\rightleftarrows</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Lleftarrow"><script type="math/tex; mode=display">\Lleftarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Rrightarrow"><script type="math/tex; mode=display">\Rrightarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="twoheadleftarrow"><script type="math/tex; mode=display">\twoheadleftarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="twoheadrightarrow"><script type="math/tex; mode=display">\twoheadrightarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftarrowtail"><script type="math/tex; mode=display">\leftarrowtail</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rightarrowtail"><script type="math/tex; mode=display">\rightarrowtail</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="looparrowleft"><script type="math/tex; mode=display">\looparrowleft</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="looparrowright"><script type="math/tex; mode=display">\looparrowright</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="curvearrowleft"><script type="math/tex; mode=display">\curvearrowleft</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="curvearrowright"><script type="math/tex; mode=display">\curvearrowright</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="circlearrowleft"><script type="math/tex; mode=display">\circlearrowleft</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="circlearrowright"><script type="math/tex; mode=display">\circlearrowright</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="dashleftarrow"><script type="math/tex; mode=display">\dashleftarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="dashrightarrow"><script type="math/tex; mode=display">\dashrightarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Lsh"><script type="math/tex; mode=display">\Lsh</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Rsh"><script type="math/tex; mode=display">\Rsh</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="upuparrows"><script type="math/tex; mode=display">\upuparrows</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="downdownarrows"><script type="math/tex; mode=display">\downdownarrows</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="upharpoonleft"><script type="math/tex; mode=display">\upharpoonleft</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="upharpoonright"><script type="math/tex; mode=display">\upharpoonright</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="downharpoonleft"><script type="math/tex; mode=display">\downharpoonleft</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="downharpoonright"><script type="math/tex; mode=display">\downharpoonright</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rightsquigarrow"><script type="math/tex; mode=display">\rightsquigarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftrightsquigarrow"><script type="math/tex; mode=display">\leftrightsquigarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="multimap"><script type="math/tex; mode=display">\multimap</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="nleftarrow"><script type="math/tex; mode=display">\nleftarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="nrightarrow"><script type="math/tex; mode=display">\nrightarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="nLeftarrow"><script type="math/tex; mode=display">\nLeftarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="nRightarrow"><script type="math/tex; mode=display">\nRightarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="nleftrightarrow"><script type="math/tex; mode=display">\nleftrightarrow</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="nLeftrightarrow"><script type="math/tex; mode=display">\nLeftrightarrow</script></a></li> + </ul> + </div> + <div id="symbol-tab" class="side-sx"> + <ul class="formula"> + <li><a href="javascript:void(0);" data-tex-command="infty"><script type="math/tex; mode=display">\infty</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="partial"><script type="math/tex; mode=display">\partial</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="varnothing"><script type="math/tex; mode=display">\varnothing</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="forall"><script type="math/tex; mode=display">\forall</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="exists"><script type="math/tex; mode=display">\exists</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="nexists"><script type="math/tex; mode=display">\nexists</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="mathbbR"><script type="math/tex; mode=display">\mathbb{R}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="mathbbC"><script type="math/tex; mode=display">\mathbb{C}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="mathbbN"><script type="math/tex; mode=display">\mathbb{N}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="mathbbZ"><script type="math/tex; mode=display">\mathbb{Z}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="mathbbQ"><script type="math/tex; mode=display">\mathbb{Q}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="imath"><script type="math/tex; mode=display">\imath</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="jmath"><script type="math/tex; mode=display">\jmath</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="ell"><script type="math/tex; mode=display">\ell</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="wp"><script type="math/tex; mode=display">\wp</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Im"><script type="math/tex; mode=display">\Im</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="prime"><script type="math/tex; mode=display">\prime</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="backprime"><script type="math/tex; mode=display">\backprime</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="angle"><script type="math/tex; mode=display">\angle</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="flat"><script type="math/tex; mode=display">\flat</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="natural"><script type="math/tex; mode=display">\natural</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sharp"><script type="math/tex; mode=display">\sharp</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="S"><script type="math/tex; mode=display">\S</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="checkmark"><script type="math/tex; mode=display">\checkmark</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="ulcorner"><script type="math/tex; mode=display">\ulcorner</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="urcorner"><script type="math/tex; mode=display">\urcorner</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="llcorner"><script type="math/tex; mode=display">\llcorner</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="lrcorner"><script type="math/tex; mode=display">\lrcorner</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="triangle"><script type="math/tex; mode=display">\triangle</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="triangledown"><script type="math/tex; mode=display">\triangledown</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="triangleleft"><script type="math/tex; mode=display">\triangleleft</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="triangleright"><script type="math/tex; mode=display">\triangleright</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="surd"><script type="math/tex; mode=display">\surd</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="top"><script type="math/tex; mode=display">\top</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="bot"><script type="math/tex; mode=display">\bot</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="heartsuit"><script type="math/tex; mode=display">\heartsuit</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="sphericalangle"><script type="math/tex; mode=display">\sphericalangle</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Game"><script type="math/tex; mode=display">\Game</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="dotplus"><script type="math/tex; mode=display">\dotplus</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="ltimes"><script type="math/tex; mode=display">\ltimes</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rtimes"><script type="math/tex; mode=display">\rtimes</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Cap"><script type="math/tex; mode=display">\Cap</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Cup"><script type="math/tex; mode=display">\Cup</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="leftthreetimes"><script type="math/tex; mode=display">\leftthreetimes</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="rightthreetimes"><script type="math/tex; mode=display">\rightthreetimes</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="curlywedge"><script type="math/tex; mode=display">\curlywedge</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="curlyvee"><script type="math/tex; mode=display">\curlyvee</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Finv"><script type="math/tex; mode=display">\Finv</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="diagup"><script type="math/tex; mode=display">\diagup</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="diagdown"><script type="math/tex; mode=display">\diagdown</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="barwedge"><script type="math/tex; mode=display">\barwedge</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="veebar"><script type="math/tex; mode=display">\veebar</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="doublebarwedge"><script type="math/tex; mode=display">\doublebarwedge</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="Box"><script type="math/tex; mode=display">\Box</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="boxplus"><script type="math/tex; mode=display">\boxplus</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="boxminus"><script type="math/tex; mode=display">\boxminus</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="boxtimes"><script type="math/tex; mode=display">\boxtimes</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="boxdot"><script type="math/tex; mode=display">\boxdot</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="circledast"><script type="math/tex; mode=display">\circledast</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="circledcirc"><script type="math/tex; mode=display">\circledcirc</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="divideontimes"><script type="math/tex; mode=display">\divideontimes</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="therefore"><script type="math/tex; mode=display">\therefore</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="because"><script type="math/tex; mode=display">\because</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="oplus"><script type="math/tex; mode=display">\oplus</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="ominus"><script type="math/tex; mode=display">\ominus</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="otimes"><script type="math/tex; mode=display">\otimes</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="oslash"><script type="math/tex; mode=display">\oslash</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="diamondsuit"><script type="math/tex; mode=display">\diamondsuit</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="diamond"><script type="math/tex; mode=display">\diamond</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="circ"><script type="math/tex; mode=display">\circ</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="hslash"><script type="math/tex; mode=display">\hslash</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="hbar"><script type="math/tex; mode=display">\hbar</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="mho"><script type="math/tex; mode=display">\mho</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="eth"><script type="math/tex; mode=display">\eth</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="blacktriangleleft"><script type="math/tex; mode=display">\blacktriangleleft</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="blacktriangleright"><script type="math/tex; mode=display">\blacktriangleright</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="blacklozenge"><script type="math/tex; mode=display">\blacklozenge</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="blacktriangle"><script type="math/tex; mode=display">\blacktriangle</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="blacktriangledown"><script type="math/tex; mode=display">\blacktriangledown</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="blacksquare"><script type="math/tex; mode=display">\blacksquare</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="clubsuit"><script type="math/tex; mode=display">\clubsuit</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="spadesuit"><script type="math/tex; mode=display">\spadesuit</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="bigstar"><script type="math/tex; mode=display">\bigstar</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="maltese"><script type="math/tex; mode=display">\maltese</script></a></li> + </ul> + </div> + <div id="format-tab" class="side-sx"> + <ul class="formula"> + <li><a href="javascript:void(0);" data-tex-command="bold"><script type="math/tex; mode=display">\bf Bold</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="italic"><script type="math/tex; mode=display">\it italic</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="typewriter"><script type="math/tex; mode=display">\tt Typewriter</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="tiny"><script type="math/tex; mode=display">\scriptsize tiny</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="scriptsize"><script type="math/tex; mode=display">\scriptsize script</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="small"><script type="math/tex; mode=display">\small small</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="normalsize"><script type="math/tex; mode=display">\normalsize normal</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="large"><script type="math/tex; mode=display">\large large</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="huge"><script type="math/tex; mode=display">\large huge</script></a></li> + </ul> + <ul class="formula"> + <li><a href="javascript:void(0);" data-tex-command="aqua"><script type="math/tex; mode=display">\color{aqua} {acqua}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="black"><script type="math/tex; mode=display">\color{black} {nero}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="blue"><script type="math/tex; mode=display">\color{blue} {blu}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="fuchsia"><script type="math/tex; mode=display">\color{fuchsia} {fucsia}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="gray"><script type="math/tex; mode=display">\color{gray} {grigio}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="green"><script type="math/tex; mode=display">\color{green} {verde}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="lime"><script type="math/tex; mode=display">\color{lime} {lime}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="maroon"><script type="math/tex; mode=display">\color{maroon} {marrone}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="navy"><script type="math/tex; mode=display">\color{navy} {navy}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="olive"><script type="math/tex; mode=display">\color{olive} {oliva}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="orange"><script type="math/tex; mode=display">\color{orange} {arancio}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="purple"><script type="math/tex; mode=display">\color{purple} {porpora}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="red"><script type="math/tex; mode=display">\color{red} {rosso}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="silver"><script type="math/tex; mode=display">\color{silver} {argento}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="teal"><script type="math/tex; mode=display">\color{teal} {teal}</script></a></li> + <li><a href="javascript:void(0);" data-tex-command="yellow"><script type="math/tex; mode=display">\color{yellow} {giallo}</script></a></li> + </ul> + </div> + <!-- sx --> + + <!-- dx --> + <div class="side-dx"> + + <div class="editor-box"> + + <textarea id="texformula"></textarea> + + <div id="previewcell" class="results"> + </div> + + </div> + + </div> + <!-- dx --> + + <!-- row-button --> + <div class="row-button"> + <input type="submit" name="insert" value="{#insert}" onclick="FormulaEditorDialog.insert();" /> + <input type="reset" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();"/> + </div> + <!-- row-button --> + + </div> + <!-- content--> + + + </div> + <!-- outer --> + </body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/fxeditor/editor_plugin.js new file mode 100644 index 0000000..754990c --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/editor_plugin.js @@ -0,0 +1,85 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + // Load plugin specific language pack + tinymce.PluginManager.requireLangPack('fxeditor'); + + tinymce.create('tinymce.plugins.FxEditorPlugin', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed, url) { + // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample'); + ed.addCommand('fxEdit', function() { + ed.windowManager.open({ + file : url + '/dialog.html', + width : 920 + parseInt(ed.getLang('fxeditor.delta_width', 0)), + height : 360 + parseInt(ed.getLang('fxeditor.delta_height', 0)), + popup_css : false, + inline : 0 + }, { + plugin_url : url, // Plugin absolute URL + some_custom_arg : 'custom arg' // Custom argument + }); + }); + + // Register button + ed.addButton('fxedit', { + title : 'fxeditor.desc', + cmd : 'fxEdit', + image : url + '/images/plugin.gif' + }); + + // Add a node change handler, selects the button in the UI when a image is selected + /*ed.onNodeChange.add(function(ed, cm, n) { + cm.setActive('fxedit', n.nodeName == 'IMG'); + });*/ + }, + + /** + * Creates control instances based in the incomming name. This method is normally not + * needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons + * but you sometimes need to create more complex controls like listboxes, split buttons etc then this + * method can be used to create those. + * + * @param {String} n Name of the control to create. + * @param {tinymce.ControlManager} cm Control manager to use inorder to create new control. + * @return {tinymce.ui.Control} New control instance or null if no control was created. + */ + createControl : function(n, cm) { + return null; + }, + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Formula Editor plugin', + author : 'Some author', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fx', + version : "1.0" + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('fxeditor', tinymce.plugins.FxEditorPlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/images/bg/content.png b/src/core/static/js/tiny_mce/plugins/fxeditor/images/bg/content.png new file mode 100755 index 0000000000000000000000000000000000000000..b2df24af9238008c17dc54ccdb3dc3765de50047 GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blmSQK*5Dp-y;YjHK@;M7UB8wRq zxP?HN@zUM8KR`jb64!{5;QX|b^2DN42FH~Aq*MjB%%art{G#k)1?ON>J;T-V9<PBa mc|BbmLpWw8TNFP#Q_sL*z?`z|=~jNA1cRrmpUXO@geCw2XeA*4 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/images/formula.png b/src/core/static/js/tiny_mce/plugins/fxeditor/images/formula.png new file mode 100755 index 0000000000000000000000000000000000000000..2c83bfddd1268d45c72fbdb8f2baa81ed238b4cb GIT binary patch literal 466 zcmeAS@N?(olHy`uVBq!ia0vp^3P7yM!3-pmSKsCXQq09po*^6@9Je3(KLCja_=LFX z#>8y>|Nme^JXiD1Rzs8GeZRF$>;CU<t6Q+3A$G3U!fUa{Q3o0t|NlFv7&q70*m!BQ zMRSAo|NsBvjf@w^G=#^_y+1!WsA=c_8%qsLqGs&<-E2}96BBc&!FEY>>{Xz;|95s7 znRNoK<1FxqEM{Qf76M_$OLy!300rerTq8<?^V3So6N^$A98>a>QWe}Xi&D$;i?WLq zoP$mE3|Gs0yauYg<LTlUV$nPIN-lqsf=FB9X>l)aj#pDefp$!7tbHL<+p)BG*UPPi z%7+i7^(9Fb)UpN4X4}^}-HNlud+FBWhbJ)2HBJ2U`)kp$hGSM&j|npw+b#d~)r04u zU8&o3i518E_&IClGcG&BaQz?KtJ`gj@@el?4L*B%1e{e@Y`FB<lfz*_Aj1_6hAa^V zQ?3UN%Iq5^GT%7CnDb<T6Q@kWRxyWzENmQV1`iUMm_>aO7IYte;VX2+SNz*;DQ2ld z+xTWzZQY-^psJc{``gK<WaSR^$TyZeT*kfagZelA3g!fksDtyh5AFo|lfl!~&t;uc GLK6Tos=pHe literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/images/ico/ico.png b/src/core/static/js/tiny_mce/plugins/fxeditor/images/ico/ico.png new file mode 100644 index 0000000000000000000000000000000000000000..5f863c65823257758302759763f7b8c710facfb0 GIT binary patch literal 1345 zcmY*Zdo<Gv9RJOj*B!TMGK_`R)LKKSJSMftD({WNG-Vvc>~5CHMCleuC8ZZPN@89^ zUgh!I?L;S<dt<23uBq;w*G|MPa_^k(AGhy0-{<+9^Euzg`DXe1?t>ec8vp<Rr+SkE zHQq|2pY>oGd$^Gwrg7T5Jye>WMud7%nVMXm;~mNa07Jy8LSB!YUe*+?5-EoggA$?> zlOnk+z%wf0C=25i%Vi}ca8K|sdxN$U94f56Cp1X2RpeeSD>5-QfsLWX#<KuN=Pg9% zEsjJ7C;!5tP7UJ?D%q1JD3~hr$+V=b?Mg$pUd$@XG^i*O_}`KYVlIx2k5M_$(Ij5B z?s|a}jx9ZPD-VIR^pk|mW7U$$=RqDL`g#UqU6eV@<SD%}2Sstkj<&+TrU$KE?{1$l zel|BpYdg{*nl@MZ@%^^l>n#to>@uM<dS^^>`Eoq*#ng(K*+yy|14YC+rhi)h=Ns_^ zLM5c!=%ZdcxTpo~`E{wNGS1g{1NAeHe&*PD%x#z#4)kK2!OAI%Iy-d=w4HfN`}oL& z2|ct(>8o}_<{khKfcqIA2&ftS(2mC7X)UX((aEhoAF5N`fYSI)1M{^aFZfv1`GruH z{gaq*SoPGzC>UwRfHdN5L$)&4BwyXujT)>c35Y~}dB8QhY(l*S%{AEi`XZ^ta+0a* zIwUbVDb7HzhH8NB>Tu;gc9tuaKJTf%lKBI5q^)6i8bu72QQPAzyYlR)0~KR3sp$jU zOYDd>eeJuW9TwtzJ1Q$k7Hx?gq5FHcy^0-jZb{289TjWWX*q>Tl>zLOynd1!MLF4! zzd_MsHB6Jar|l(|g3hodPVSxXu57$r-uvH?t&f<tzOh3!g%U<Fb3zfCUJ1j9T=1LY z&@FgWOzH_oX{AW#!XF&NL;AKuT+p-P+)ukMMRh}Tm(s{@C-X=k+ur4W&3p?JXjRDE zFnqJW$UN)CC}RKYB#(42q@7%{EpWatv&X5ah!8RF*wRE-6?EFv`5b>Dd#OzbI~csP z$Tgj6*;V?pS1L>R8u7@Xd6QzyQ}%a%4%kUzm-wRA$;JV9g%pyalhVm@L7<*yDZd}) zD!*#|+s;&0>p)^|=sh2IBg2fFM$))redr+uo83FXj8oiqTq@6w7tTibCL?nig&%z+ z`)n2Xdcy5!7jsmM^4YuAFQ*HQ;FFED-!}ALf5LN;k10Krs0;l}`@U+C)y!9`S-`zU zWbu3}ISMMM@T^?qUvH7$D35v{Hpp^Lj(Zr2{nT}>mTyC_;hpHr=~XV*4Ptfa{Z&b5 z%>n%5p(@S^A2{-eVJjRo>xDaicNH4W_S=$&^^|U?3uT;zfl14i4a-UVJjnnm`vppF z^CPm@w1F`(Yom%#?~FHj5Z_sIZownH=BAcuu1R>><uMlhYpOj{9w1*4f2CO9Xmhoh zZd$EyH=}T!h!C02{69^7pKQ3soOPV7Dl?+p)LC8?2!?>H!0t3XA>z(1=w^<q3eGuF zJz4`A(*4WW%BN@i=wED9B$ct)Xc-<38HJ4Ec6&g*M2qq0=Ke2P3bhcRfQ69@7eEv6 zX33S3RHS;18lv{0cXTTUNq$Y0y9K{ZL%|@h1N4hr(ozvrcSI|6(`J)q+?p1k0Q>6m zCe<a;${X159QRcI+`%-2;MUxwgbhxI$d@4-0lI86xV@-h%h2O;4@}$RcHLiKb_>=K vOZ`bf9n|C3NxB908HdNQq73x#-4*ERhcWFyK+{Rh69cFeUvl*x=GlJ%hqr0C literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/images/plugin.gif b/src/core/static/js/tiny_mce/plugins/fxeditor/images/plugin.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0c76dc9d9801427262ba716359977ec2edc9b42 GIT binary patch literal 388 zcmZ?wbhEHb6k!lyxN5=h;>C-<fB(LE_3G)<r_Y`}+r4}DlP6F1?%n(R`SZt*AHRS9 ze$SpghYufq^XAQwBS#J%Jh*1fn$4RxzkdCC-@bhd7A!b=^r*MD=Z6m;X3w5|_wHR; zS=sdT^eI!OtX;eI(4j-w+1ZyaU2<@6*uQ`OfddB~J$m%^?c1`lGBGi+2M->^#>VpS z@ML6U{Qmu0SXg+)iWSqRPj_{7ZEbDU*48dAE`Im!-M@eTK7Rbjz`*eT|9>Ef2^4>_ zFfuS$FzA4!Kz?FiTj(&Sz(Yr>|Ag|BV>xEZC!=${co)c-a|C6*u9DQb&YSh5YPW2# zR*Chjz2ZS<in69>o3(y+TO9hvHHeE#yT(M<gqN?u#hkI$MA|^1R*0v^xlfgssav0E zK|~&-5Cem}mgF)9<rz+W3yjT|NpWx}t+VK3V5w$d7T(#njpZmaGaDQGA;$g3PjX&l eJtW6|jhmbG7ORMnyG->%3C|}_pE)@)SOWl#xUD<@ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/images/risultato.png b/src/core/static/js/tiny_mce/plugins/fxeditor/images/risultato.png new file mode 100755 index 0000000000000000000000000000000000000000..491523762898ac19d2dc77c7088e66f259f13aba GIT binary patch literal 4683 zcmV-R6144!P)<h;3K|Lk000e1NJLTq006lF002P<1^@s6jcf%d00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gH7+r$A4ux}01?AUL_t(|ob8=?TvXNj$KMwQ8MZ_d*H~O|K}};2NOLK* za$mE4nM#Y6S$^9z+cZn_Ya3}AnPR4qS!w#sv~tUELs2ngKw}G(Rau%Dm|+I)?~g$Q z1)9-;xr6h5z4(K3?>+O}dp`HfInQ~XGlD3JB6jRFVH~V&fE_yxja}q+nml%q+iCLH zMQ*3bV;8xdCXZd@Hi?$sKbc3^2Rl(&+Y}o>u)7d#5PdT9Lm%OQ0QSba%CL8T;J+jM zt}B-{zA1KYn!+671h^~gEy4o5t~)H0Ye-H?M{RJ#r&o7cIMzH~lAVGwPfzDsjv22_ zM%UbjfIC`TSGTpV?b53|o{rZY2J|?#a;@!vy(hOtv}ZSRPuNOkZ{E+7{<m4%9LZxJ zliMKKaj}#O-RaZL!`i0U1a^_z90oE{QYdX1h_}07ZDVW#yU1-04asqrDC+HteV}3* zc9Gi}rCA)xC?}++A1)TDu$Ti8OPD@=I&(kRL}HQNBDG2hyU1;gtQ6t}2<_d`BGnyT zJcb3Ad<h%fkEAUt82!|SCg*#%yAW**&E*ULdbD-F`N~S;`8MY%evg=j3lQSx$iQcJ z5wCuV{!M7SZyO>vXvoRVr6A`5N%?X{j10EWSGDbNG5!<=A&`!(oJ=}jlb=mqVF8)S zzi<kAfV=Og_T*f8@KHqXDiJt0_dxH^mG(_Y;9w&n*JmAP)qAV?B{rQxzo!{KGT7QC zSqUx5<4QEXQ}L0TB1A25KddHv-7lmI@c732xVuL8AgdvOxb0i$IQu>PENisYv57Ic zlh3^@Sr`UD@FVwd>w1TaNjss(HKYgEuL;(MoB^|!@XR1*%7g*j*QxF&r#l_V<isgN zJ$|R9jFk*FA##AU{l5V)O5tl|ORR`0k3R*GfR61<zos;iAOFyiH+T?!b@l!kJDIdp zOU#DpcmM{2!6N2L1sf5$h7-S@K<hAydpo+K$xh?^`BVzEw^l@gAxlZT0KxtpOuj~& za)KBE9vTsX3&o_So+l-{@ahS92MC(@HZvBFp)56(l;6MN`N-G?u>R)J<X_<Y`SWDt zo9F+ri7`2<bL>{?@gDEZzQv<h`BN?c<wAEp*!?BLOq_(-I+rq1slb~+Khp<nDbasW zfj4~%_Apton)J%f+-G_?+n)92y$9!m11z60vFe&Pw;!>z={JR#b&_Rsp5^-s{!AKH z!1g_Pbw(W4UV#muidicv6bezHP>93c|4Ga(Rf&hg=ZFf0LY%wnFKe6EXe500h}f&& zeDS>A)GLa_b&rLJ3WY+vOEF&Dem++$`TGwsEKp%)JyzuJU&P@Gh1l+;&0>Kliem1s zqC%k%16Ce2xeA-;$&-&91>hgYSsa@;8X4f$KLEZy#-+j%>l)W+XgGT$9ZkS}v^BNW z3X?dbG=Kn)ZH{7`zboKOzZMRhE-s|RAc9Q7?m|O4?~Q+xJjXzGFMZfJ*=`*|_?xdH z3+ZEWH8vpfT#oFFr(EdH+TUhY8GJE55rCkcepa)rQPF2}R%yUzMsJh7OGRgn5HEno z^l)DCuZ*=W&EP~~1*(qy=wy-`(s~rd{LD57k)AI;N1rNNn=^3yLuS<@{fTFulI=wm zq&+Z=0nICKv^0@*pB+W#Fq8+o-69Uf!pj^JL_&I+?paYD+>3}ObEkw>m8JdkHSq!r zoi<SNuGouzo(7<QU%#8GNAe=SbmkZZz=BbIt9tPxD;Kk0fT=59qKCwLBTJ#pJ4XS~ z)yFgsIb7uT9eJp3A5Z_bl@s&4L(E&g50&4eygROYLz!wZoSN0Lu5HL6KDF@r@_LZC z$hE}m+DQf8gx=X2Fc25{JafNKX5fM^S#Wn7Ya7^TWGjt{5<N^zlrW?mXPbja`%yu( z!RVowGvWo#IS%E!4KHE~PtM81IK+yHK1nH1mi;FSL&mV;T(Md8NPJ8#r$es+I7IK~ z`Pt9VE#V~RZoh}68+S1_ptZG)YeWoWC#F!^awwfmj4P3~^yNMg_HBHV*-B4N#HJH6 z>uvTvJ=!J&4$yJpT%Oq%&F5?9F>tN1Y+CqM-Wg=xf}m~Wcxu(;t4a}_+-dE3D~4tj zvuVNu%<DXlv=1kl6`ZCi%BMsR@)llrNW4p{i!1lw-ogu)8@PuCxow@gh!W(qaF<)A zLb*F$atnl(+A5`49Lq2eGS>V=2{%tK+#1BF#^Yx1p#jF^8onEMKOvLWVczthsbJtj zLL4y(8CWa=BtL@~3noh3YSbxmP5uSWrDjz%RC!Sj=Th@bs?@o?Bjp~>QXlX)5ITOH zJB#U0{Lf+;HkzCiz(R=<w;<Q+ur!&4V;*H!Q3U|6>^#osjP(q8_H#r$S@ZiIf|^87 zy@8z6R4yB!{>T?SqO1j-JGD3YrS)j<h@sT<mpnJ_4^9-f<iWwcYQ4tXL<u`Jx&E2D z__1*Bao#u`$$*&=d^>+O%M&%c6|oYJVi&sotH7OU<|-hTHj{Wyu3_8csjPSS_jz}T z!z2zLf6c@gZqTVksCAd8Yfz`Lap|k9+>?s>_D2~oxK}Noq2;f$iD-NuH8D}b&b8E{ zLu0mxta~saVgxbDlRUL?KNACL-vB|Mb&~H6B+;x{GXR>A!;+I_xcZ*vo9|t#woNE2 zE2GnW6S=#cRJ<e2nY!Z}`d==?sooA!kIt!eovVXacC)%dOP~PoZ1Dy62Cb=a?h}!} z@ob-#fPvIKpEKpP4OPcn3Qm!t7Hj#IEavZcJsCqxO_Z=Ah8%Wp*@wDP3w5C@b7kP9 zk@z;!OIvqm>*7P8rvv+Bk1)9ofddGtWWvM4uPc}TeTazVhia6K>NcWYkp~3@nP9T% z#KzVi7v0?3pT6EV_Zc#mHrzkxevkvmk;}ED{;`L%g(89XkKqmkv;bNy9b79Px9U&k zFWA5n3tl8`%?b__Rp2Nlk(6CZkpDIN`Kj_aQCPvGPIWKmTl%@xN4?KfU&wbKhZFxV z+7<Dn)3}k;=j}G<p8l<!>-Ljp>?CO7+f?Aq@?W+wyj9(nYt`zi395@s&4!ud`6zE3 zyLZf^jX_&=%u()sLw?SNLBr0)^VpJI@h|SFQgj{0vGT2nCdPUg_-@)j<~z<Nal`aF zU490PJ&fjXID`Ka1;FT!ckuS0nh6nxb6W_V`T<iT_w!;O>2D`gu2oa|uWlt7?v`>d zn?N0s%O!mLVgiDDqKr)-I$gzZw>+X#Z)0H3>sK1(?$u}g0v-tHJX+CGE<=t~Jpzt6 zbD6U#WpwnY`vn$MDzXH%8TIOnwX1b#p-z!sdGKxl{qYl{NEhIAVh&s*@*7E%uqKXj zcgeMQ4Uy*`{+3m-2E5ZFh<x-@&dzDZ<a=hZZ*wH_Gn*-U_a_Eg%TkLYXZWHmoNj=c zby?*&$VAg7-X3iTKp-8FGe;9pJ*}wmjZu*Nr*WGIH~XaXMyb&bg-Lt)c~cw(y`JW1 zcqpJ@N`MpZAB;jdXANJQ7!ajXi#Rxz-Na&ufr|-oBwx}Xb8SwS-hF5zRnLM!i&|U# zPPGKQ{5q@J2O_A|RR0c;ySra6e3=)$0%Yt;)Z?y9A;&<q<#%JEM2U|Xi4qnd>+ojY zU9+2iT6N~(88aE%r+wpncmq)5(RH1%g56{FwD9t*JmAKZwZAY#+surZ5l6fS5959Z z{~L25YSW3F`3Mn-SA|o7Hw!j@#S{td#jT59&ybnxO**&sakU#g`}c&zIGn^3vNR(8 zSK{Uk`J7c6@HQh+qB{Si#&X8s!@#bl2eau;NAlncfAZfCClR-98Sgy#6XiRPGNG;Q z`si!wQ09i$wLe@SZ%%8o<_L0zys(5JH)znAPo8I0QWswRXf6Rx*=$<4lmkVXyfgJ9 zf{!f5Pcjo%BhLOKc=uH=boKio(d(g8>)Ow0(<K0i!%<A)RJw}6S6&2FE=tTxl&C@# z&ub4o!)IZu5X}(z!S9rOy7v<XHy0S$zZ-vrK1R|76|`+>z6}yVT9VNx^TqesEd6;0 zBikAy4nFv)EA#J}#vU<+EUk#2)K**FJ2K*-n~N#&^tn3OO#JI2REk`C@f_&_jA&=B zhg{3{*|UfdV63}&J@BAK%aLCh8VYi}0B2We$;4cwl{8_1L9cyLC2#;-IuaC6PeU0r zTsWV=xzs$=>Pw_#=2<Q<s*#ZS1kk(Ek(-=$sj56%nLq{J^zbonu#)-XGL|IW*cQxk z`Bgz1Qli=3DvZbLStn^UZlax~^@_T5;o-^G7V6LeI-w`N*Yx74Kd)lSq7AqO4JSBv zKL;|)DfD}qxF2RpK7X+WF6{{NaU?#ooWEm|P+`o!%uY+7)bU=E6D0u1`i=2R53}r> z&)NHb&v2})?o&1S7f8=5!OOQj4uyGCwD6|&m7ZUp%xjNsWA(4wtiIBEv+XRcp1d}) zPO&0U&+s=UQ{97{5cxb)7Hwe6@~s^Fd>Kn#nE=30o7^kW9X~(gnAhX)6QpWIKtsy0 zOB5^o%=kr#T*61cL6^7IalgMi`E{M9N@Vr4PzH?%BWmj!Mh+RmgA=9@l~P)H!X;Ku zd4~Zzwip)yt1aj?HkN2-iHlsrra7;X6Z{HG#`#y3>P|;8BjPB{AAX-jLye2Wde>F} z46@0+66N^!>H>hHm`ds;5%ifH%P`QTpXrGbXFhp~Pdh!wx^aG>tz)=Sc#1hgrm;G2 z99xg=<-LUqnOY%GCJd<D`JkA{z!7{ub`~LGE@`Q;eDK_I(yX9zOSQAKhAY<)7x5I! zE{@~S_m5P2YjcU5w}uM5Svc$7$}$57H-3rEVJLy#wf~l*)M+2s2RMpA5s8=8OlX!( zi~y5NOq9@`-N=lncKmpBhVfasxZ(<UHmg3LDQ45$IUE(dSrN6M%2U<K*O9!=#tlK^ zB3>fGL4?&WFlM#!c(<3<Gq2H=V!3vftjN!QJ(ub0TeCHKK~1+|#tGIJRZubhc?Mtc zCui+vMYN8~!NGKu>>bsQTbs^R5sXI?E~0hJ1fWM-6Z&yOI`7T+lyb-WIR9f5v1Q<v zf0`HpT#s)fs#z?~orW^3VkavS_1rf7)vK{cDbcLRG%zOYPF#S#vm=R}-B5RF1{Q2* zNlGH~$3;wDA+Ra>ldJox7}9xj#4<)L=?_4BmFbsQIOYus1eh_VCzliAFm&rn2T9&p z-3Tq(;x9ss0NE+YB+3#f7rN7-l?jU!r7AKJajw|M^5y$#94a}nlkgLuo!*V+*_)}r zoB2}|l}8O6To(brpgW~C%+p>j04&qal9NLA@2i=x^k-yv6Y)YAB_&4RT8>i5!SV0& zrrQMo6s1{YW-IyMvyZb&FrKq}?d$B&^kdJjeXVBy4ddcNXn+$jiF!(sPqM!t8ny3K zx|kBq;L)44F~_PE$Z$}d;>lsNNSn2ay-$aNLCxmJ%W)tRr^--J&EbW-yeF5E+b0q1 zp3A8OX98;pz_SXKqby6bv$Q6jrSZJ}@|OTOkV$N80!pP4rBX=&5czN@^6rC}=;=Vk zuOBjD%yj+=`-($R^8nBZ{n)x=0jBTXEhXIOUOAa^OW4Wg=rVjv{zVCp$z;|3z(H<Q zNpqZxNidZgdy06HpPotT&mS}RKgJ(6aJ{^hHy)h8mYjP0jg5>&+qpru+ih@4#k{;c z@t@MG{}&djtZ9%%$k?{9YKv-xLLttIQr>uF`ZV#az#wt#=doAo-?_A^?q2=oi)U1Y z;*V29MTJ5kE|%mL*p_K$+t^&_7Qt|KBcat&=^7$YLRXYeF)p<BG)8^v)J2rZJn?9} z9EL_mTEmrF9GP#gs^$F(yb0`J`DHC<Pp>M0130@kZGnSb<kG^U4gM{RO`><`ikGLv zg3)XgyT~PlCjp%+Js$yG@RpqK%Qmr#TvE8<9~=OHPvDIuO4zv`yT~O*hwgU)+*qQ7 zom#PrTw=JlHRe-xH9JwlPF>hth<2Jh_MY5MlgBP{J53(D$n7+F{vT~`&ijsgV?qD` N002ovPDHLkV1ksj1)Tr@ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/img/example.gif b/src/core/static/js/tiny_mce/plugins/fxeditor/img/example.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ab5da4461113d2af579898528246fdbe52ecd00 GIT binary patch literal 87 zcmZ?wbhEHb6k!lyn83&Y1dNP~ia%L^OhyJB5FaGNz@*pGzw+SQ`#f{}FJ-?!v#V)e mtsGNfpJeCKSAiOz**>0`XR2{OVa>-G_df0vaY<rium%9X5FI1{ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/js/dialog.js b/src/core/static/js/tiny_mce/plugins/fxeditor/js/dialog.js new file mode 100755 index 0000000..44b38a6 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/js/dialog.js @@ -0,0 +1,301 @@ +tinyMCEPopup.requireLangPack(); + +var FormulaEditorDialog = { + + isMathmlSupported : false, + mathmlFormula : null, + mathjaxMode : null, + undoMngr : null, + + init : function() { + var selectedTxt = tinyMCEPopup.editor.selection.getContent({format : 'text'}); + var arg = tinyMCEPopup.getWindowArg('some_custom_arg'); + + // Replace mathjax delimitators + selectedTxt = selectedTxt.replace(/^ *\\\[|\\\] *$|^ *`|` *$/g, ''); + + // Only FF supports MathML + //FormulaEditorDialog.isMathmlSupported = MathJax.Hub.Browser.isFirefox; + + // mathjax mode get + FormulaEditorDialog.mathjaxMode = tinyMCEPopup.editor.selection.getNode().getAttribute("data-fx-type"); + if (FormulaEditorDialog.mathjaxMode == null) { + FormulaEditorDialog.mathjaxMode = "tex"; + } + + // sets mathjax mode in select + $('#mathjax-mode-select').val(FormulaEditorDialog.mathjaxMode); + + // decodes xml + if (FormulaEditorDialog.mathjaxMode == "mml") { + if (tinyMCEPopup.editor.selection.getNode().getAttribute("data-encoded") == "true") { + selectedTxt = tinyMCEPopup.dom.decode(selectedTxt); + } + } + + // sets in textarea the selected formula in tinymce + $("#texformula").textrange("replace", selectedTxt); + //$("#texformula").val(selectedTxt); + FormulaEditorDialog.preview(); + + + // undo manager startup + FormulaEditorDialog.undoMngr = new BufferedUndoManager(); + FormulaEditorDialog.undoMngr.reset(selectedTxt); + + + // updates formula for each key click + $("#texformula").keyup(function() { + FormulaEditorDialog.undoMngr.update($("#texformula").val()); + FormulaEditorDialog.preview(); + }); + + + // math palette buttons management + $("ul.formula li a").click(function() { + var command = ""; + switch (FormulaEditorDialog.mathjaxMode) { + case "tex": + command = mathmap[$(this).data("tex-command")][0]; + break; + case "am": + command = mathmap[$(this).data("tex-command")][1]; + break; + case "mml": + command = mathmap[$(this).data("tex-command")][2]; + break; + } + + // block commands management: replaces ### with textarea selection + if (command.indexOf("###") >= 0) { + var sel = $("#texformula").textrange(); + if (sel.start != sel.end) { + command = command.replace("###", sel.text); + } else { + command = command.replace("###", ""); + } + } + + // inserts formula symbol into textarea + $("#texformula").textrange("replace", command); + var sel = $("#texformula").textrange(); + $("#texformula").textrange('set', sel.end); + + + // new undo and update formula preview + FormulaEditorDialog.undoMngr.update($("#texformula").val()); + FormulaEditorDialog.preview(); + }); + + + // tab menu activation/disactivation + $("#tab-menu ul.tab li a").click(function() { + $("#tab-menu ul li a.active").removeClass('active'); + $(this).addClass('active'); + }); + + + // select tex|ascii|mathml change event + $('#mathjax-mode-select').change(function() { + FormulaEditorDialog.mathjaxMode = $(this).attr('value'); + FormulaEditorDialog.preview(); + }); + }, + + // + // Inserts formula in TinyMCE doc + // + insert : function() { + var newformula = ""; + var encoded = false; + var formulaSpanStyle = ""; + var mathmlSpan = ""; + + // Adds delimiters + newformula = FormulaEditorDialog.addMathJaxDelimiters($("#texformula").val()); + + // If MathML output is selected, and not supported, encode xml + if (FormulaEditorDialog.mathjaxMode == "mml") { + if (!FormulaEditorDialog.isMathmlSupported) { + newformula = tinyMCEPopup.dom.encode(newformula); + encoded = true; + } + } + + // If MathML is supported, shows formula converted in mathml, and hides editable formula + if (FormulaEditorDialog.isMathmlSupported) { + formulaSpanStyle = ' style="display:none"'; + FormulaEditorDialog.getMathML(); + FormulaEditorDialog.mathmlFormula = FormulaEditorDialog.mathmlFormula.replace(' display="block"',''); + mathmlSpan = '<span>' + FormulaEditorDialog.mathmlFormula + '</span>'; + } else { + formulaSpanStyle = ''; + mathmlSpan = ''; + } + + /* mathml formula insert management + var toInsert = '<span class="mceNonEditable"' + + '><span class="formula"' + formulaSpanStyle + + ' data-fx-type="' + FormulaEditorDialog.mathjaxMode + '"' + + ' data-encoded="' + encoded + '"' + + '>' + + newformula + '</span>' + + mathmlSpan + + '</span>'; + */ + var toInsert = '<span class="mceNonEditable formula"' + + ' data-fx-type="' + FormulaEditorDialog.mathjaxMode + '"' + + '>' + + newformula + '</span>'; + + // Insert the contents from the input into the document + tinyMCEPopup.editor.execCommand('mceInsertContent', false, toInsert); + tinyMCEPopup.close(); + }, + + // + // Updates formula preview + // + preview : function () { + var formula = FormulaEditorDialog.addMathJaxDelimiters($("#texformula").val()); + $("#previewcell").html(formula); + MathJax.Hub.Queue(["Typeset",MathJax.Hub,"previewcell"]); + }, + + // + // To MathML formula conversion + // https://groups.google.com/forum/?fromgroups#!topic/mathjax-users/unL8IjcrTto + toMathML : function(jax,callback) { + var mml; + try { + mml = jax.root.toMathML(""); + } catch(err) { + if (!err.restart) {throw err;} // an actual error + return MathJax.Callback.After([FormulaEditorDialog.toMathML,jax,callback],err.restart); + } + MathJax.Callback(callback)(mml); + }, + + // + // Get MathML definition of formula in previewcell, + // and store it in FormulaEditorDialog.mathmlFormula var + // + getMathML : function() { + MathJax.Hub.Queue(function() { + var jax = MathJax.Hub.getAllJax("previewcell"); + for (var i = 0; i < jax.length; i++) { + FormulaEditorDialog.toMathML(jax[i],function(mml) { + FormulaEditorDialog.mathmlFormula = mml; + }); + } + }); + }, + + // + // Returns formula with MathJax delimites, depending on set mode (tex|ascii|mathml) + // + addMathJaxDelimiters : function(formula) { + var rformula = ""; + switch (FormulaEditorDialog.mathjaxMode) { + case "tex": + //tex mode: + rformula = "\\[" + formula + "\\]"; + break; + case "am": + //ascii mode: + rformula = "`" + formula + "`" + "\r"; + break; + case "mml": + //mathml mode: + rformula = FormulaEditorDialog.mathDecoration(formula); + break; + } + return rformula; + }, + + // + // Math tags mathml decoration + // + mathDecoration : function(txtbox) { + var rformu = ""; + + if (txtbox.indexOf("<math") >= 0) { + // starting math tag already exists + rformu = txtbox; + if (txtbox.indexOf("</math>") < 0) { + // end math tag does not exist + rformu = rformu + "</math>"; + } + + } else { + rformu = '<math xmlns="http://www.w3.org/1998/Math/MathML">' + + txtbox + '</math>'; + } + return rformu; + }, + + selectTab : function(tabId) { + $('.side-sx').css('display', 'none'); + $('#'+tabId).css('display', 'block'); + $("#texformula").focus(); + }, + + undo : function () { + if (FormulaEditorDialog.undoMngr.canUndo()) { + FormulaEditorDialog.undoMngr.undo(); + $("#texformula").val(FormulaEditorDialog.undoMngr.state); + FormulaEditorDialog.preview(); + $("#texformula").focus(); + } + }, + + redo : function () { + if (FormulaEditorDialog.undoMngr.canRedo()) { + FormulaEditorDialog.undoMngr.redo(); + $("#texformula").val(FormulaEditorDialog.undoMngr.state); + FormulaEditorDialog.preview(); + $("#texformula").focus(); + } + }, + + copyBuffer : "", + + copy : function () { + var sel = $("#texformula").textrange(); + if (sel.start != sel.end) { + FormulaEditorDialog.copyBuffer = sel.text; + } + }, + + cut : function () { + var sel = $("#texformula").textrange(); + if (sel.start != sel.end) { + FormulaEditorDialog.copyBuffer = sel.text; + } + $("#texformula").textrange("replace", ""); + FormulaEditorDialog.undoMngr.update($("#texformula").val()); + FormulaEditorDialog.preview(); + $("#texformula").focus(); + }, + + paste : function () { + if (FormulaEditorDialog.copyBuffer != "") { + $("#texformula").textrange("replace", FormulaEditorDialog.copyBuffer); + var sel = $("#texformula").textrange(); + $("#texformula").textrange('set', sel.end); + FormulaEditorDialog.undoMngr.update($("#texformula").val()); + FormulaEditorDialog.preview(); + $("#texformula").focus(); + } + }, + + clear : function () { + $("#texformula").val(""); + FormulaEditorDialog.undoMngr.update(""); + FormulaEditorDialog.preview(); + $("#texformula").focus(); + } + +}; + +tinyMCEPopup.onInit.add(FormulaEditorDialog.init, FormulaEditorDialog); diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/js/jquery-textrange.js b/src/core/static/js/tiny_mce/plugins/fxeditor/js/jquery-textrange.js new file mode 100644 index 0000000..08b3682 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/js/jquery-textrange.js @@ -0,0 +1,178 @@ +/** + * jquery-textrange + * A jQuery plugin for getting, setting and replacing the selected text in input fields and textareas. + * + * (c) 2012 Daniel Imhoff <dwieeb@gmail.com> - danielimhoff.com + */ +(function($) { + var browserType; + + var textrange = { + /** + * $().textrange() or $().textrange('get') + * Retrieves an object containing the start and end location of the text range, the length of the range and the + * substring of the range. + * + * @param (optional) property + * @return An object of properties including position, start, end, length, and text or a specific property. + */ + get: function(property) { + return _textrange[browserType].get.apply(this, [property]); + }, + + /** + * $().textrange('set') + * Sets the selected text of an object by specifying the start and end of the selection. + * + * @param start The starting position of the selection, or the position of the cursor, if end is not given. + * @param (optional) end The ending position of the selection. + */ + set: function(start, end) { + if(typeof start === 'undefined') { + start = 0; + end = -1; + } + + if(typeof end === 'undefined') { + end = start; + } + else if(end === -1) { + end = this.val().length; + } + + _textrange[browserType].set.apply(this, [start, end]); + + return this; + }, + + /** + * $().textrange('replace') + * Replaces the selected text in the input field or textarea with text. + * + * @param text The text to replace the selection with. + */ + replace: function(text) { + _textrange[browserType].replace.apply(this, [text]); + + return this; + }, + + /** + * Alias for $().textrange('replace') + */ + insert: function(text) { + return this.textrange('replace', text); + } + }; + + var _textrange = { + xul: { + get: function(property) { + this[0].focus(); + var props = { + position: this[0].selectionStart, + start: this[0].selectionStart, + end: this[0].selectionEnd, + length: this[0].selectionEnd - this[0].selectionStart, + text: this.val().substring(this[0].selectionStart, this[0].selectionEnd) + }; + + return typeof property === 'undefined' ? props : props[property]; + }, + + set: function(start, end) { + this[0].focus(); + this[0].selectionStart = start; + this[0].selectionEnd = end; + }, + + replace: function(text) { + this[0].focus(); + var start = this[0].selectionStart; + this.val(this.val().substring(0, this[0].selectionStart) + text + this.val().substring(this[0].selectionEnd, this.val().length)); + this[0].selectionStart = start; + this[0].selectionEnd = start + text.length; + } + }, + + msie: { + get: function(property) { + this[0].focus(); + + var range = document.selection.createRange(); + + if(typeof range === 'undefined') { + return { + position: 0, + start: 0, + end: this[0].val().length, + length: this[0].val().length, + text: this.val() + }; + } + + var rangetext = this[0].createTextRange(); + var rangetextcopy = rangetext.duplicate(); + + rangetext.moveToBookmark(range.getBookmark()); + rangetextcopy.setEndPoint('EndToStart', rangetext); + + return { + position: rangetextcopy.text.length, + start: rangetextcopy.text.length, + end: rangetextcopy.text.length + range.text.length, + length: range.text.length, + text: range.text + }; + }, + + set: function(start, end) { + this[0].focus(); + + var range = this[0].createTextRange(); + + if(typeof range === 'undefined') { + return this; + } + + if(typeof start !== 'undefined') { + range.moveStart('character', start); + range.collapse(); + } + + if(typeof end !== 'undefined') { + range.moveEnd('character', end - start); + } + + range.select(); + }, + + replace: function(text) { + this[0].focus(); + + document.selection.createRange().text = text; + } + } + }; + + $.fn.textrange = function(method) { + if(typeof browserType === 'undefined') { + browserType = 'selectionStart' in this[0] ? 'xul' : document.selection ? 'msie' : 'unknown'; + } + + // I don't know how to support this browser. :c + if(browserType === 'unknown') { + return this; + } + + if(typeof method === 'undefined' || typeof method !== 'string') { + return textrange.get.apply(this); + } + else if(typeof textrange[method] === 'function') { + return textrange[method].apply(this, Array.prototype.slice.call(arguments, 1)); + } + else { + $.error("Method " + method + " does not exist in jQuery.textrange"); + } + }; +})(jQuery); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/js/mathmap.js b/src/core/static/js/tiny_mce/plugins/fxeditor/js/mathmap.js new file mode 100644 index 0000000..e1e1336 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/js/mathmap.js @@ -0,0 +1,353 @@ +mathmap = { + times: ["\\times", "xx", "<mo>&#x00D7;</mo>"], //0 + div: ["\\div", "-:", "<mo>&#x00F7;</mo>"], //1 + pm: ["\\pm", "+-", "<mo>&#x00B1;</mo>"], //2 + mp: ["\\mp", "", "<mo>&#x2213;</mo>"], //3 + cdot: ["\\cdot", "*", "<mo>&#x22C5;</mo>"], //4 + star: ["\\star", "**", "<mo>&#x22C6;</mo>"], + sqrt: ["\\sqrt{ab}", "sqrt(ab)", "<msqrt>\n <mi>a</mi>\n <mi>b</mi>\n</msqrt>"], + rootn: ["\\sqrt[n]{ab}", "root(n)(ab)", "<mroot>\n <mrow>\n <mi>a</mi>\n <mi>b</mi>\n </mrow>\n <mi>n</mi>\n</mroot>"], + logax: ["\\log_{a}{x}", "log_(a)(x)", ""], + lnx: ["\\ln{x}", "ln(x)", ""], + pow: ["a^{b}", "a^(b)", ""], + subscr: ["a_{b}", "a_(b)", ""], + subsup: ["c_a^b", "c_a^b", ""], + tilde: ["\\widetilde{ab}", "tilde(ab)", ""], + hat: ["\\widehat{ab}", "hat(ab)", ""], + vecl: ["\\overleftarrow{ab}", "", ""], + vec: ["\\overrightarrow{ab}", "vec(ab)", ""], + overbr: ["\\overbrace{ab}", "", ""], + underbr: ["\\underbrace{ab}", "", ""], + underl: ["\\underline{ab}", "ul(ab)", ""], + overl: ["\\overline{ab}", "bar(ab)", ""], + bmatrix: ["\\begin{bmatrix}a & b \\\\c & d \\end{bmatrix}", "[(a,b),(c,d)]", ""], + cases: ["\\begin{cases}a & x = 0\\\\b & x > 0\\end{cases}", "{(a, x=0),(b, x>0):}", ""], + frac: ["\\frac{ab}{cd}", "(ab)/(cd)", ""], + delab: ["\\frac{\\partial a}{\\partial b}", "(del a)/(del b)", ""], + dxdy: ["\\frac{\\text{d}x}{\\text{d}y}", "(text(d)x)/(text(d)y)", ""], + limx0: ["\\lim_{x \rightarrow 0}", "lim_(x->0)", ""], + integr: ["\\int_{a}^{b}", "int_a^b", ""], + ointegr: ["\\oint_a^b", "oint_a^b", ""], + prod: ["\\prod_{a}^b", "prod_(a)^b", ""], + coprod: ["\\coprod_{a}^b", "coprod_(a)^b", ""], + bigcap: ["\\bigcap_a^b ", "nnn_(a)^b", ""], + bigcup: ["\\bigcup_a^b", "uuu_(a)^b", ""], + bigvee: ["\\bigvee_a^b", "vvv_(a)^b", ""], + bigwed: ["\\bigwedge_a^b", "^^^_(a)^b", ""], + bigsqc: ["\\bigsqcup_a^b", "", ""], + sum: ["\\sum_{n=0}^\\infty", "sum_(n=0)^oo", ""], + arrayab: ["\\left(\\begin{array}{c}a\\\\ b\\end{array}\\right)", "((a),(b))", ""], // 37 + //Greek + alpha: ["\\alpha", "alpha", "<mi>&#x03B1;</mi>"], // 38 + beta: ["\\beta", "beta", "<mi>&#x03B2;</mi>"], + gamma: ["\\gamma", "gamma", "<mi>&#x03B3;</mi>"], + delta: ["\\delta", "delta", "<mi>&#x03B4;</mi>"], + epsilon: ["\\epsilon", "epsilon", "<mi>&#x03F5;</mi>"], + zeta: ["\\zeta", "zeta", "<mi>&#x03B6;</mi>"], + eta: ["\\eta", "eta", "<mi>&#x03B7;</mi>"], + theta: ["\\theta", "theta", "<mi>&#x03B8;</mi>"], + iota: ["\\iota", "iota", "<mi>&#x03B9;</mi>"], + kappa: ["\\kappa", "kappa", "<mi>&#x03BA;</mi>"], + lambda: ["\\lambda", "lambda", "<mi>&#x03BB;</mi>"], + mu: ["\\mu", "mu", "<mi>&#x03BC;</mi>"], + nu: ["\\nu", "nu", "<mi>&#x03BD;</mi>"], + xi: ["\\xi", "xi", "<mi>&#x03BE;</mi>"], + pi: ["\\pi", "pi", "<mi>&#x03C0;</mi>"], + rho: ["\\rho", "rho", "<mi>&#x03C1;</mi>"], + sigma: ["\\sigma", "sigma", "<mi>&#x03C3;</mi>"], + tau: ["\\tau", "tau", "<mi>&#x03C4;</mi>"], + upsilon: ["\\upsilon", "upsilon", "<mi>&#x03C5;</mi>"], + phi: ["\\phi", "phi", "<mi>&#x03D5;</mi>"], + chi: ["\\chi", "chi", "<mi>&#x03C7;</mi>"], + psi: ["\\psi", "psi", "<mi>&#x03C8;</mi>"], + omega: ["\\omega", "omega", "<mi>&#x03C9;</mi>"], // 60 + Gamma: ["\\Gamma", "Gamma", ""], + Delta: ["\\Delta", "Delta", ""], + Theta: ["\\Theta", "Theta", ""], + Lambda: ["\\Lambda", "Lambda", ""], + Xi: ["\\Xi", "Xi", ""], + Pi: ["\\Pi", "Pi", ""], + Sigma: ["\\Sigma", "Sigma", ""], + Upsilon: ["\\Upsilon", "", ""], + Phi: ["\\Phi", "Phi", ""], + Psi: ["\\Psi", "Psi", ""], + Omega: ["\\Omega", "Omega", ""], + //var greek + varepsilon: ["\\varepsilon", "Omega", ""], + vartheta: ["\\vartheta", "Omega", ""], + varrho: ["\\varrho", "Omega", ""], + varsigma: ["\\varsigma", "Omega", ""], + varphi: ["\\varphi", "Omega", ""], + //Func + arccos: ["\\arccos", "arccos", "<mi>arccos</mi>"], // 61 + arcsin: ["\\arcsin", "arcsin", "<mi>arcsin</mi>"], + arctan: ["\\arctan", "arctan", "<mi>arctan</mi>"], + cos: ["\\cos", "cos", "<mi>cos</mi>"], + cosh: ["\\cosh", "cosh", "<mi>cosh</mi>"], + cot: ["\\cot", "cot", "<mi>cot</mi>"], + coth: ["\\coth", "coth", "<mi>coth</mi>"], + csc: ["\\csc", "csc", "<mi>csc</mi>"], + sec: ["\\sec", "sec", "<mi>sec</mi>"], + sin: ["\\sin", "sin", "<mi>sin</mi>"], + sinh: ["\\sinh", "sinh", "<mi>sinh</mi>"], + tan: ["\\tan", "tan", "<mi>tan</mi>"], + tanh: ["\\tanh", "tanh", "<mi>tanh</mi>"], // 73 + exp: ["\\exp", "", ""], + log: ["\\log", "log", ""], + ln: ["\\ln", "ln", ""], + max: ["\\max", "max", ""], + min: ["\\min", "min", ""], + sup: ["\\sup", "", ""], + inf: ["\\inf", "", ""], + lim: ["\\lim", "", ""], + gcd: ["\\gcd", "", ""], + hom: ["\\hom", "", ""], + ker: ["\\ker", "", ""], + det: ["\\det", "", ""], + bmod: ["\\bmod", "", ""], // 86 + //Logic + neq: ["\\neq", "!=", ""], // 87 + leq: ["\\leq", "<=", ""], + geq: ["\\geq", ">=", ""], + sim: ["\\sim", "", ""], + approx: ["\\approx", "", ""], + cong: ["\\cong", "", ""], + equiv: ["\\equiv", "", ""], + propto: ["\\propto", "", ""], + ll: ["\\ll", "", ""], + gg: ["\\gg", "", ""], + in_: ["\\in", "", ""], + notin: ["\\notin", "", ""], + subset: ["\\subset", "", ""], + subseteq: ["\\subseteq", "", ""], + prec: ["\\prec", "", ""], + preceq: ["\\preceq", "", ""], + simeq: ["\\simeq", "", ""], + asymp: ["\\asymp", "", ""], + doteq: ["\\doteq", "", ""], + succ: ["\\succ", "", ""], + succeq: ["\\succeq", "", ""], + sqsubseteq:["\\sqsubseteq", "", ""], + sqsupseteq:["\\sqsupseteq", "", ""], + ni: ["\\ni", "", ""], + models: ["\\models", "", ""], + vdash: ["\\vdash", "", ""], + dashv: ["\\dashv", "", ""], + perp: ["\\perp", "", ""], + mid: ["\\mid", "", ""], + parallel: ["\\parallel", "", ""], + smile: ["\\smile", "", ""], + frown: ["\\frown", "", ""], + bowtie: ["\\bowtie", "", ""], + unlhd: ["\\unlhd", "", ""], + unrhd: ["\\unrhd", "", ""], // 120 + + hata: ["\\hat{a}", "", ""], // 121 + checka: ["\\check{a}", "", ""], + brevea: ["\\breve{a}", "", ""], + acutea: ["\\acute{a}", "", ""], + gravea: ["\\grave{a}", "", ""], + tildea: ["\\tilde{a}", "", ""], + bara: ["\\bar{a}", "", ""], + veca: ["\\vec{a}", "", ""], + dota: ["\\dot{a}", "", ""], + ddota: ["\\ddot{a}", "", ""], // 130 + //Arrow + leftp: ["(", "(", ""], // 131 + rightp: [")", ")", ""], + leftsp: ["[", "[", ""], + rightsp: ["]", "]", ""], + leftgp: ["\\{", "{", ""], + rightgp: ["\\}", "}", ""], + lfloor: ["\\lfloor", "", ""], + lceil: ["\\lceil", "", ""], + rfloor: ["\\rfloor", "", ""], + rceil: ["\\rceil", "", ""], + langle: ["\\langle", "<<", ""], + rangle: ["\\rangle", ">>", ""], + backslash: ["\\backslash", "", ""], + cap: ["\\cap", "", ""], + cup: ["\\cup", "", ""], + uplus: ["\\uplus", "", ""], + sqcap: ["\\sqcap", "", ""], + sqcup: ["\\sqcup", "", ""], + vee: ["\\vee", "", ""], + wedge: ["\\wedge", "", ""], + wr: ["\\wr", "", ""], // 151 + + leftarrow: ["\\leftarrow", "", ""], // 152 + Leftarrow: ["\\Leftarrow", "", ""], + rightarrow: ["\\rightarrow", "", ""], + Rightarrow: ["\\Rightarrow", "", ""], + leftrightarrow: ["\\leftrightarrow", "", ""], + Leftrightarrow: ["\\Leftrightarrow", "", ""], + mapsto: ["\\mapsto", "", ""], + leftharpoonup: ["\\leftharpoonup", "", ""], + leftharpoondown: ["\\leftharpoondown", "", ""], + rightleftharpoons: ["\\rightleftharpoons", "", ""], + leftrightharpoons: ["\\leftrightharpoons", "", ""], + hookrightarrow: ["\\hookrightarrow", "", ""], + rightharpoonup: ["\\rightharpoonup", "", ""], + uparrow: ["\\uparrow", "", ""], + Uparrow: ["\\Uparrow", "", ""], + downarrow: ["\\downarrow", "", ""], + Downarrow: ["\\Downarrow", "", ""], + updownarrow: ["\\updownarrow", "", ""], + Updownarrow: ["\\Updownarrow", "", ""], + leftleftarrows: ["\\leftleftarrows", "", ""], + rightrightarrows: ["\\rightrightarrows", "", ""], + leftrightarrows: ["\\leftrightarrows", "", ""], + rightleftarrows: ["\\rightleftarrows", "", ""], + Lleftarrow: ["\\Lleftarrow", "", ""], + Rrightarrow: ["\\Rrightarrow", "", ""], + twoheadleftarrow: ["\\twoheadleftarrow", "", ""], + twoheadrightarrow: ["\\twoheadrightarrow", "", ""], + leftarrowtail: ["\\leftarrowtail", "", ""], + rightarrowtail: ["\\rightarrowtail", "", ""], + looparrowleft: ["\\looparrowleft", "", ""], + looparrowright: ["\\looparrowright", "", ""], + curvearrowleft: ["\\curvearrowleft", "", ""], + curvearrowright: ["\\curvearrowright", "", ""], + circlearrowleft: ["\\circlearrowleft", "", ""], + circlearrowright: ["\\circlearrowright", "", ""], + dashleftarrow: ["\\dashleftarrow", "", ""], + dashrightarrow: ["\\dashrightarrow", "", ""], + Lsh: ["\\Lsh", "", ""], + Rsh: ["\\Rsh", "", ""], + upuparrows: ["\\upuparrows", "", ""], + downdownarrows: ["\\downdownarrows", "", ""], + upharpoonleft: ["\\upharpoonleft", "", ""], + upharpoonright: ["\\upharpoonright", "", ""], + downharpoonleft: ["\\downharpoonleft", "", ""], + downharpoonright: ["\\downharpoonright", "", ""], + rightsquigarrow: ["\\rightsquigarrow", "", ""], + leftrightsquigarrow:["\\leftrightsquigarrow", "", ""], + multimap: ["\\multimap", "", ""], + nleftarrow: ["\\nleftarrow", "", ""], + nrightarrow: ["\\nrightarrow", "", ""], + nLeftarrow: ["\\nLeftarrow", "", ""], + nRightarrow: ["\\nRightarrow", "", ""], + nleftrightarrow: ["\\nleftrightarrow", "", ""], + nLeftrightarrow: ["\\nLeftrightarrow", "", ""], + //Symbol + mathbbC: ["\\mathbb{C}", "CC", ""], + mathbbR: ["\\mathbb{R}", "RR", ""], + mathbbN: ["\\mathbb{N}", "NN", ""], + mathbbZ: ["\\mathbb{Z}", "ZZ", ""], + mathbbQ: ["\\mathbb{Q}", "QQ", ""], + imath: ["\\imath", "", ""], + jmath: ["\\jmath", "", ""], + ell: ["\\ell", "", ""], + wp: ["\\wp", "", ""], + Im: ["\\Im", "", ""], + prime: ["\\prime", "", ""], + angle: ["\\angle", "", ""], + flat: ["\\flat", "", ""], + natural: ["\\natural", "", ""], + sharp: ["\\sharp", "", ""], + S: ["\\S", "", ""], + checkmark: ["\\checkmark", "", ""], + ulcorner: ["\\ulcorner", "", ""], + urcorner: ["\\urcorner", "", ""], + llcorner: ["\\llcorner", "", ""], + lrcorner: ["\\lrcorner", "", ""], + triangle: ["\\triangle", "", ""], + triangledown: ["\\triangledown", "", ""], + triangleleft: ["\\triangleleft", "", ""], + triangleright: ["\\triangleright", "", ""], + forall: ["\\forall", "", ""], + exists: ["\\exists", "", ""], + surd: ["\\surd", "", ""], + top: ["\\top", "", ""], + bot: ["\\bot", "", ""], + heartsuit: ["\\heartsuit", "", ""], + backprime: ["\\backprime", "", ""], + varnothing: ["\\varnothing", "", ""], + sphericalangle: ["\\sphericalangle", "", ""], + nexists: ["\\nexists", "", ""], + Game: ["\\Game", "", ""], + dotplus: ["\\dotplus", "", ""], + ltimes: ["\\ltimes", "", ""], + rtimes: ["\\rtimes", "", ""], + Cap: ["\\Cap", "", ""], + Cup: ["\\Cup", "", ""], + leftthreetimes: ["\\leftthreetimes", "", ""], + rightthreetimes: ["\\rightthreetimes", "", ""], + curlywedge: ["\\curlywedge", "", ""], + curlyvee: ["\\curlyvee", "", ""], + Finv: ["\\Finv", "", ""], + diagup: ["\\diagup", "", ""], + diagdown: ["\\diagdown", "", ""], + barwedge: ["\\barwedge", "", ""], + veebar: ["\\veebar", "", ""], + doublebarwedge: ["\\doublebarwedge", "", ""], + Box: ["\\Box", "", ""], + boxplus: ["\\boxplus", "", ""], + boxminus: ["\\boxminus", "", ""], + boxtimes: ["\\boxtimes", "", ""], + boxdot: ["\\boxdot", "", ""], + circledast: ["\\circledast", "", ""], + circledcirc: ["\\circledcirc", "", ""], + divideontimes: ["\\divideontimes", "", ""], + therefore: ["\\therefore", "", ""], + because: ["\\because", "", ""], + oplus: ["\\oplus", "", ""], + ominus: ["\\ominus", "", ""], + otimes: ["\\otimes", "", ""], + oslash: ["\\oslash", "", ""], + diamondsuit: ["\\diamondsuit", "", ""], + diamond: ["\\diamond", "", ""], + circ: ["\\circ", "", ""], + hslash: ["\\hslash", "", ""], + hbar: ["\\hbar", "", ""], + mho: ["\\mho", "", ""], + infty: ["\\infty", "oo", ""], + partial: ["\\partial", "", ""], + eth: ["\\eth", "", ""], + blacktriangleleft: ["\\blacktriangleleft", "", ""], + blacktriangleright: ["\\blacktriangleright", "", ""], + blacklozenge: ["\\blacklozenge", "", ""], + blacktriangle: ["\\blacktriangle", "", ""], + blacktriangledown: ["\\blacktriangledown", "", ""], + blacksquare: ["\\blacksquare", "", ""], + clubsuit: ["\\clubsuit", "", ""], + spadesuit: ["\\spadesuit", "", ""], + bigstar: ["\\bigstar", "", ""], + maltese: ["\\maltese", "", ""], + //Format + bold: ["\\bf", "", ""], + italic: ["\\it", "", ""], + typewriter: ["\\tt", "", ""], + tiny: ["\\tiny", "", ""], + scriptsize: ["\\scriptsize", "", ""], + small: ["\\small", "", ""], + normalsize: ["\\normalsize", "", ""], + large: ["\\large", "", ""], + huge: ["\\huge", "", ""], + + aqua: ["\\color{aqua} {###}", "", "<mstyle mathcolor=\"aqua\">\n ###\n</mstyle>"], + black: ["\\color{black} {###}", "", "<mstyle mathcolor=\"black\">\n ###\n</mstyle>"], + blue: ["\\color{blue} {###}", "", "<mstyle mathcolor=\"blue\">\n ###\n</mstyle>"], + fuchsia: ["\\color{fuchsia} {###}", "", "<mstyle mathcolor=\"fuchsia\">\n ###\n</mstyle>"], + gray: ["\\color{gray} {###}", "", "<mstyle mathcolor=\"gray\">\n ###\n</mstyle>"], + green: ["\\color{green} {###}", "", "<mstyle mathcolor=\"green\">\n ###\n</mstyle>"], + lime: ["\\color{lime} {###}", "", "<mstyle mathcolor=\"lime\">\n ###\n</mstyle>"], + maroon: ["\\color{maroon} {###}", "", "<mstyle mathcolor=\"maroon\">\n ###\n</mstyle>"], + navy: ["\\color{navy} {###}", "", "<mstyle mathcolor=\"navy\">\n ###\n</mstyle>"], + olive: ["\\color{olive} {###}", "", "<mstyle mathcolor=\"olive\">\n ###\n</mstyle>"], + orange: ["\\color{orange} {###}", "", "<mstyle mathcolor=\"orange\">\n ###\n</mstyle>"], + purple: ["\\color{purple} {###}", "", "<mstyle mathcolor=\"purple\">\n ###\n</mstyle>"], + red: ["\\color{red} {###}", "", "<mstyle mathcolor=\"red\">\n ###\n</mstyle>"], + silver: ["\\color{silver} {###}", "", "<mstyle mathcolor=\"silver\">\n ###\n</mstyle>"], + teal: ["\\color{teal} {###}", "", "<mstyle mathcolor=\"teal\">\n ###\n</mstyle>"], + yellow: ["\\color{yellow} {###}", "", "<mstyle mathcolor=\"yellow\">\n ###\n</mstyle>"] +}; + + + + + + + + + diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/js/underscore-min.js b/src/core/static/js/tiny_mce/plugins/fxeditor/js/underscore-min.js new file mode 100644 index 0000000..c1d9d3a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/js/underscore-min.js @@ -0,0 +1 @@ +(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.4";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2),e=w.isFunction(t);return w.map(n,function(n){return(e?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t,r){return w.isEmpty(t)?r?null:[]:w[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.findWhere=function(n,t){return w.where(n,t,!0)},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var k=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=k(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index<t.index?-1:1}),"value")};var F=function(n,t,r,e){var u={},i=k(t||w.identity);return A(n,function(t,a){var o=i.call(r,t,a,n);e(u,o,t)}),u};w.groupBy=function(n,t,r){return F(n,t,r,function(n,t,r){(w.has(n,t)?n[t]:n[t]=[]).push(r)})},w.countBy=function(n,t,r){return F(n,t,r,function(n,t){w.has(n,t)||(n[t]=0),n[t]++})},w.sortedIndex=function(n,t,r,e){r=null==r?w.identity:k(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i},w.bind=function(n,t){if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));var r=o.call(arguments,2);return function(){return n.apply(t,r.concat(o.call(arguments)))}},w.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},w.bindAll=function(n){var t=o.call(arguments,1);return 0===t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var I=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=I(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&I(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return I(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),"function"!=typeof/./&&(w.isFunction=function(n){return"function"==typeof n}),w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return n===void 0},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var M={escape:{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;"}};M.unescape=w.invert(M.escape);var S={escape:RegExp("["+w.keys(M.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(M.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(S[n],function(t){return M[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),D.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=++N+"";return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){var e;r=w.defaults({},r,w.templateSettings);var u=RegExp([(r.escape||T).source,(r.interpolate||T).source,(r.evaluate||T).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(B,function(n){return"\\"+q[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,w);var c=function(n){return e.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},w.chain=function(n){return w(n).chain()};var D=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],D.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return D.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/js/undo-manager.js b/src/core/static/js/tiny_mce/plugins/fxeditor/js/undo-manager.js new file mode 100644 index 0000000..905c8f8 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/js/undo-manager.js @@ -0,0 +1,121 @@ + +// http://blog.divshot.com/post/22843867366/undo-manager-for-javascript + +var BufferedUndoManager, + __slice = [].slice; + +BufferedUndoManager = (function() { + + function BufferedUndoManager(options) { + this.bindings = {}; + this.options = _.extend({ + buffer: 1000, + synchronizeOnUpdate: false, + comparator: function(a, b) { + return a === b; + } + }, options); + this.reset(this.options.state); + } + + BufferedUndoManager.prototype.reset = function(state, options) { + if (options == null) { + options = {}; + } + this.clearTimeout(); + delete this.undos; + delete this.redos; + delete this.bufferTimeout; + this.undos = []; + this.redos = []; + this.bufferReady = true; + return this.state = state; + }; + + BufferedUndoManager.prototype.undo = function() { + if (!this.canUndo()) { + return false; + } + this.redos.push(this.state); + this.state = this.undos.pop(); + this.trigger('undo', this.state); + this.synchronize(); + return this.undos.length; + }; + + BufferedUndoManager.prototype.redo = function() { + if (!this.canRedo()) { + return false; + } + this.undos.push(this.state); + this.state = this.redos.pop(); + this.trigger('redo', this.state); + this.synchronize(); + return this.redos.length; + }; + + BufferedUndoManager.prototype.canUndo = function() { + return this.undos.length > 0; + }; + + BufferedUndoManager.prototype.canRedo = function() { + return this.redos.length > 0; + }; + + BufferedUndoManager.prototype.on = function() { + var args, _ref; + args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + return (_ref = $(this)).on.apply(_ref, args); + }; + + BufferedUndoManager.prototype.off = function() { + var args, _ref; + args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + return (_ref = $(this)).off.apply(_ref, args); + }; + + BufferedUndoManager.prototype.update = function(state, options) { + var _this = this; + if (options == null) { + options = {}; + } + if (this.options.comparator(this.state, state) && !options.force) { + return false; + } + this.redos = []; + if (options.force || this.bufferReady) { + this.undos.push(this.state); + this.trigger('push', this.state); + this.bufferReady = false; + } + this.clearTimeout(); + this.bufferTimeout = setTimeout(function() { + _this.trigger('buffered', _this.state); + return _this.bufferReady = true; + }, this.options.buffer); + this.state = state; + return this.synchronize(this.options.synchronizeOnUpdate != null); + }; + + BufferedUndoManager.prototype.clearTimeout = function() { + if (this.bufferTimeout != null) { + return clearTimeout(this.bufferTimeout); + } + }; + + BufferedUndoManager.prototype.trigger = function() { + var args, _ref; + args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + return (_ref = $(this)).triggerHandler.apply(_ref, args); + }; + + BufferedUndoManager.prototype.synchronize = function(options) { + this.trigger('change', this.state); + if ((this.options.synchronize != null) && callThrough) { + return this.options.synchronize(this.state); + } + }; + + return BufferedUndoManager; + +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/js/vendor/jquery-1.8.2.min.js b/src/core/static/js/tiny_mce/plugins/fxeditor/js/vendor/jquery-1.8.2.min.js new file mode 100644 index 0000000..bc3fbc8 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/js/vendor/jquery-1.8.2.min.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call(" ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/js/vendor/modernizr-2.6.2.min.js b/src/core/static/js/tiny_mce/plugins/fxeditor/js/vendor/modernizr-2.6.2.min.js new file mode 100644 index 0000000..f65d479 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/js/vendor/modernizr-2.6.2.min.js @@ -0,0 +1,4 @@ +/* Modernizr 2.6.2 (Custom Build) | MIT & BSD + * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load + */ +;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="<svg/>",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function p(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return r.shivMethods?n(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+l().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(r,b.frag)}function q(a){a||(a=b);var c=m(a);return r.shivCSS&&!f&&!c.hasCSS&&(c.hasCSS=!!k(a,"article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}")),j||p(a,c),a}var c=a.html5||{},d=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,e=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,f,g="_html5shiv",h=0,i={},j;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))}; diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/langs/en.js b/src/core/static/js/tiny_mce/plugins/fxeditor/langs/en.js new file mode 100644 index 0000000..7e3c5bb --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/langs/en.js @@ -0,0 +1,3 @@ +tinyMCE.addI18n('en.fxeditor',{ + desc : 'Edit Formula' +}); diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/fxeditor/langs/en_dlg.js new file mode 100644 index 0000000..3f0f8d3 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/langs/en_dlg.js @@ -0,0 +1,3 @@ +tinyMCE.addI18n('en.fxeditor_dlg',{ + title : 'Formula Editor' +}); diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/langs/it.js b/src/core/static/js/tiny_mce/plugins/fxeditor/langs/it.js new file mode 100644 index 0000000..153908d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/langs/it.js @@ -0,0 +1,3 @@ +tinyMCE.addI18n('it.fxeditor',{ + desc : 'Modifica Formula' +}); diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/fxeditor/langs/it_dlg.js new file mode 100644 index 0000000..c831318 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/langs/it_dlg.js @@ -0,0 +1,3 @@ +tinyMCE.addI18n('it.fxeditor_dlg',{ + title : 'Modifica Formula' +}); diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/less/global.less b/src/core/static/js/tiny_mce/plugins/fxeditor/less/global.less new file mode 100755 index 0000000..d5fbba0 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/less/global.less @@ -0,0 +1,27 @@ +body { + font-family:Arial, Helvetica, sans-serif; + color:#333; + font-size:12px; + } + +a { + color:#333; + text-decoration:none; + + &:hover { + text-decoration:underline; + } + + } + +input[type="button"], +input[type="submit"], +input[type="reset"], +button { + .button-style(auto); + } + +input[type="button"], +input[type="submit"] { + font-weight:bold; + } \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/h5bp.less b/src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/h5bp.less new file mode 100755 index 0000000..408752b --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/h5bp.less @@ -0,0 +1,298 @@ +/* + * HTML5 Boilerplate + * + * What follows is the result of much research on cross-browser styling. + * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal, + * Kroc Camen, and the H5BP dev community and team. + */ + +/* ========================================================================== + Base styles: opinionated defaults + ========================================================================== */ + +html, +button, +input, +select, +textarea { + color: #222; +} + +body { + font-size: 1em; + line-height: 1.4; +} + +/* + * Remove text-shadow in selection highlight: h5bp.com/i + * These selection declarations have to be separate. + * Customize the background color to match your design. + */ + +::-moz-selection { + background: #b3d4fc; + text-shadow: none; +} + +::selection { + background: #b3d4fc; + text-shadow: none; +} + +/* + * A better looking default horizontal rule + */ + +hr { + display: block; + height: 1px; + border: 0; + border-top: 1px solid #ccc; + margin: 1em 0; + padding: 0; +} + +/* + * Remove the gap between images and the bottom of their containers: h5bp.com/i/440 + */ + +img { + vertical-align: middle; +} + +/* + * Remove default fieldset styles. + */ + +fieldset { + border: 0; + margin: 0; + padding: 0; +} + +/* + * Allow only vertical resizing of textareas. + */ + +textarea { + resize: vertical; +} + +/* ========================================================================== + Chrome Frame prompt + ========================================================================== */ + +.chromeframe { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; +} + +/* ========================================================================== + Author's custom styles + ========================================================================== */ + + + + + + + + + + + + + + + + + +/* ========================================================================== + Helper classes + ========================================================================== */ + +/* + * Image replacement + */ + +.ir { + background-color: transparent; + border: 0; + overflow: hidden; + /* IE 6/7 fallback */ + *text-indent: -9999px; +} + +.ir:before { + content: ""; + display: block; + width: 0; + height: 100%; +} + +/* + * Hide from both screenreaders and browsers: h5bp.com/u + */ + +.hidden { + display: none !important; + visibility: hidden; +} + +/* + * Hide only visually, but have it available for screenreaders: h5bp.com/v + */ + +.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: h5bp.com/p + */ + +.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; +} + +/* + * Clearfix: contain floats + * + * For modern browsers + * 1. The space content is one way to avoid an Opera bug when the + * `contenteditable` attribute is included anywhere else in the document. + * Otherwise it causes space to appear at the top and bottom of elements + * that receive the `clearfix` class. + * 2. The use of `table` rather than `block` is only necessary if using + * `:before` to contain the top-margins of child elements. + */ + +.clearfix:before, +.clearfix:after { + content: " "; /* 1 */ + display: table; /* 2 */ +} + +.clearfix:after { + clear: both; +} + +/* + * For IE 6/7 only + * Include this rule to trigger hasLayout and contain floats. + */ + +.clearfix { + *zoom: 1; +} + +/* ========================================================================== + EXAMPLE Media Queries for Responsive Design. + Theses examples override the primary ('mobile first') styles. + Modify as content requires. + ========================================================================== */ + +@media only screen and (min-width: 35em) { + /* Style adjustments for viewports that meet the condition */ +} + +@media only screen and (-webkit-min-device-pixel-ratio: 1.5), + only screen and (min-resolution: 144dpi) { + /* Style adjustments for high resolution devices */ +} + +/* ========================================================================== + Print styles. + Inlined to avoid required HTTP connection: h5bp.com/r + ========================================================================== */ + +@media print { + * { + background: transparent !important; + color: #000 !important; /* Black prints faster: h5bp.com/s */ + box-shadow: none !important; + text-shadow: none !important; + } + + a, + a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + /* + * Don't show links for images, or javascript/internal links + */ + + .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; /* h5bp.com/t */ + } + + 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/core/static/js/tiny_mce/plugins/fxeditor/less/libs/mixins.less b/src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/mixins.less new file mode 100755 index 0000000..25c0365 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/mixins.less @@ -0,0 +1,136 @@ +/* less define */ + +.margin-reset() { +margin:0; +} + +.padding-reset() { +padding:0; +} + +.padding-margin-reset() { + .padding-reset(); + .margin-reset(); + } + +/* define border radius */ + +.border-radius (@radius) { + border-radius: @radius; + -moz-border-radius: @radius; + -webkit-border-radius: @radius; +} + +.border-radius-top (@radius-top) { + border-top-left-radius: @radius-top; + border-top-right-radius: @radius-top; + -moz-border-radius-topright: @radius-top; + -moz-border-radius-topleft: @radius-top; + -webkit-border-top-right-radius: @radius-top; + -webkit-border-top-left-radius: @radius-top; +} + +.border-radius-bottom (@radius-bottom) { + border-bottom-left-radius: @radius-bottom; + border-bottom-right-radius: @radius-bottom; + -moz-border-radius-topright: @radius-bottom; + -moz-border-radius-topleft: @radius-bottom; + -webkit-border-bottom-right-radius: @radius-bottom; + -webkit-border-bottom-left-radius: @radius-bottom; +} +.border-radius-left (@radius-left) { + -webkit-border-bottom-left-radius:@radius-left; + border-bottom-left-radius:@radius-left; + -webkit-border-top-left-radius:@radius-left; + border-top-left-radius:@radius-left; + -moz-border-radius-bottomleft:@radius-left; + -moz-border-radius-topleft:@radius-left; +} + +.border-radius-right (@radius-right) { + -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; +} +/* define shadow */ + +.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #999) { + box-shadow: @arguments; + -moz-box-shadow: @arguments; + -webkit-box-shadow: @arguments; +} + +.box-shadow-inset (@where:inset, @x: 0, @y: 0, @blur: 1px, @color: #999) { + -moz-box-shadow:@arguments; + -webkit-box-shadow:@arguments; + box-shadow:@arguments; +} + +/* text-shaodow */ +.text-shadow (@x: 0, @y: 0, @blur: 1px, @color: #000) { + text-shadow:@arguments; +} + +/* define transition */ + +.transition (@time:.4s){ + -moz-transition:all @time ease-in-out; + -webkit-transition:all @time ease-in-out; + -o-transition:all @time ease-in-out; + transition:all @time ease-in-out; + } + +/* define rotation */ + +.rotation (@angle:-90deg){ + -moz-transform:rotate(@angle); + -webkit-transform:rotate(@angle); + -o-transform:rotate(@angle); + -ms-transform:rotate(@angle); + } + +.input-style (@width) { + background:#ccc; + border:0; + box-shadow:0; + color:#fff; + width:@width; + padding:2px; + font-size:20px; +} + +.button-style (@with) { + width: @with; + border:0; + font-size:14px; + background:; + color:#333; + padding:7px 15px 5px 15px; + .border-radius(5px); + border:1px solid #ccc; + background: #f4f4f4; /* Old browsers */ + +background: -moz-linear-gradient(top, #f4f4f4 0%, #e9e9e9 100%); /* FF3.6+ */ + +background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f4f4f4), color-stop(100%,#e9e9e9)); /* Chrome,Safari4+ */ + +background: -webkit-linear-gradient(top, #f4f4f4 0%,#e9e9e9 100%); /* Chrome10+,Safari5.1+ */ + +background: -o-linear-gradient(top, #f4f4f4 0%,#e9e9e9 100%); /* Opera 11.10+ */ + +background: -ms-linear-gradient(top, #f4f4f4 0%,#e9e9e9 100%); /* IE10+ */ + +background: linear-gradient(to bottom, #f4f4f4 0%,#e9e9e9 100%); /* W3C */ + +filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#e9e9e9',GradientType=0 ); /* IE6-9 */ + + + + &:active { + .box-shadow-inset(inset,0, 0, 10px, #999); + } + +} diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/normalize.less b/src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/normalize.less new file mode 100755 index 0000000..d4210aa --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/normalize.less @@ -0,0 +1,504 @@ +/*! normalize.css v1.0.1 | MIT License | git.io/normalize */ + +/* ========================================================================== + HTML5 display definitions + ========================================================================== */ + +/* + * Corrects `block` display not defined in IE 6/7/8/9 and Firefox 3. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +nav, +section, +summary { + display: block; +} + +/* + * Corrects `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. + */ + +audio, +canvas, +video { + display: inline-block; + *display: inline; + *zoom: 1; +} + +/* + * Prevents modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/* + * Addresses styling for `hidden` attribute not present in IE 7/8/9, Firefox 3, + * and Safari 4. + * Known issue: no IE 6 support. + */ + +[hidden] { + display: none; +} + +/* ========================================================================== + Base + ========================================================================== */ + +/* + * 1. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using + * `em` units. + * 2. Prevents iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-size: 100%; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -ms-text-size-adjust: 100%; /* 2 */ +} + +/* + * Addresses `font-family` inconsistency between `textarea` and other form + * elements. + */ + +html, +button, +input, +select, +textarea { + font-family: sans-serif; +} + +/* + * Addresses margins handled incorrectly in IE 6/7. + */ + +body { + margin: 0; +} + +/* ========================================================================== + Links + ========================================================================== */ + +/* + * Addresses `outline` inconsistency between Chrome and other browsers. + */ + +a:focus { + outline: thin dotted; +} + +/* + * Improves readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* ========================================================================== + Typography + ========================================================================== */ + +/* + * Addresses font sizes and margins set differently in IE 6/7. + * Addresses font sizes within `section` and `article` in Firefox 4+, Safari 5, + * and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +h2 { + font-size: 1.5em; + margin: 0.83em 0; +} + +h3 { + font-size: 1.17em; + margin: 1em 0; +} + +h4 { + font-size: 1em; + margin: 1.33em 0; +} + +h5 { + font-size: 0.83em; + margin: 1.67em 0; +} + +h6 { + font-size: 0.75em; + margin: 2.33em 0; +} + +/* + * Addresses styling not present in IE 7/8/9, Safari 5, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/* + * Addresses style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +blockquote { + margin: 1em 40px; +} + +/* + * Addresses styling not present in Safari 5 and Chrome. + */ + +dfn { + font-style: italic; +} + +/* + * Addresses styling not present in IE 6/7/8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/* + * Addresses margins set differently in IE 6/7. + */ + +p, +pre { + margin: 1em 0; +} + +/* + * Corrects font family set oddly in IE 6, Safari 4/5, and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + _font-family: 'courier new', monospace; + font-size: 1em; +} + +/* + * Improves readability of pre-formatted text in all browsers. + */ + +pre { + white-space: pre; + white-space: pre-wrap; + word-wrap: break-word; +} + +/* + * Addresses CSS quotes not supported in IE 6/7. + */ + +q { + quotes: none; +} + +/* + * Addresses `quotes` property not supported in Safari 4. + */ + +q:before, +q:after { + content: ''; + content: none; +} + +/* + * Addresses inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/* + * Prevents `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ========================================================================== + Lists + ========================================================================== */ + +/* + * Addresses margins set differently in IE 6/7. + */ + +dl, +menu, +ol, +ul { + margin: 1em 0; +} + +dd { + margin: 0 0 0 40px; +} + +/* + * Addresses paddings set differently in IE 6/7. + */ + +menu, +ol, +ul { + padding: 0 0 0 40px; +} + +/* + * Corrects list images handled incorrectly in IE 7. + */ + +nav ul, +nav ol { + list-style: none; + list-style-image: none; +} + +/* ========================================================================== + Embedded content + ========================================================================== */ + +/* + * 1. Removes border when inside `a` element in IE 6/7/8/9 and Firefox 3. + * 2. Improves image quality when scaled in IE 7. + */ + +img { + border: 0; /* 1 */ + -ms-interpolation-mode: bicubic; /* 2 */ +} + +/* + * Corrects overflow displayed oddly in IE 9. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* ========================================================================== + Figures + ========================================================================== */ + +/* + * Addresses margin not present in IE 6/7/8/9, Safari 5, and Opera 11. + */ + +figure { + margin: 0; +} + +/* ========================================================================== + Forms + ========================================================================== */ + +/* + * Corrects margin displayed oddly in IE 6/7. + */ + +form { + margin: 0; +} + +/* + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/* + * 1. Corrects color not being inherited in IE 6/7/8/9. + * 2. Corrects text not wrapping in Firefox 3. + * 3. Corrects alignment displayed oddly in IE 6/7. + */ + +legend { + border: 0; /* 1 */ + padding: 0; + white-space: normal; /* 2 */ + *margin-left: -7px; /* 3 */ +} + +/* + * 1. Corrects font size not being inherited in all browsers. + * 2. Addresses margins set differently in IE 6/7, Firefox 3+, Safari 5, + * and Chrome. + * 3. Improves appearance and consistency in all browsers. + */ + +button, +input, +select, +textarea { + font-size: 100%; /* 1 */ + margin: 0; /* 2 */ + vertical-align: baseline; /* 3 */ + *vertical-align: middle; /* 3 */ +} + +/* + * Addresses Firefox 3+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +button, +input { + line-height: normal; +} + +/* + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Corrects inability to style clickable `input` types in iOS. + * 3. Improves usability and consistency of cursor style between image-type + * `input` and others. + * 4. Removes inner spacing in IE 7 without affecting normal text inputs. + * Known issue: inner spacing remains in IE 6. + */ + +button, +html input[type="button"], /* 1 */ +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ + *overflow: visible; /* 4 */ +} + +/* + * Re-set default cursor for disabled elements. + */ + +button[disabled], +input[disabled] { + cursor: default; +} + +/* + * 1. Addresses box sizing set to content-box in IE 8/9. + * 2. Removes excess padding in IE 8/9. + * 3. Removes excess padding in IE 7. + * Known issue: excess padding remains in IE 6. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ + *height: 13px; /* 3 */ + *width: 13px; /* 3 */ +} + +/* + * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome. + * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/* + * Removes inner padding and search cancel button in Safari 5 and Chrome + * on OS X. + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* + * Removes inner padding and border in Firefox 3+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/* + * 1. Removes default vertical scrollbar in IE 6/7/8/9. + * 2. Improves readability and alignment in all browsers. + */ + +textarea { + overflow: auto; /* 1 */ + vertical-align: top; /* 2 */ +} + +/* ========================================================================== + Tables + ========================================================================== */ + +/* + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/wp-default.less b/src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/wp-default.less new file mode 100755 index 0000000..b87e409 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/less/libs/wp-default.less @@ -0,0 +1,69 @@ +/* ALO Newsletter */ + +.alo_easymail_form_table input[type='radio'], .input-radio { + margin-right:10px; + } + +.alo_easymail_form_table td { + padding-bottom:10px; + } + +.alo_easymail_form_table input[type='text'], +.alo_easymail_form_table input#opt_name, +.alo_easymail_form_table input#opt_email { + width:185px; + border:1px solid #ccc; + -webkit-border-radius: 60px; + -moz-border-radius: 60px; + border-radius: 60px; + padding:6px; + font-style:italic; + color:#999; + font-size:14px; + margin-left:10px; + } + +#alo_easymail_widget_form input.input-submit { + width:125px; + text-transform:lowercase; + border:1px solid #C2326D; + background-color:#C2326D; + -webkit-border-radius: 60px; + -moz-border-radius: 60px; + border-radius: 60px; + padding:6px; + font-weight:bold; + color:#fff; + letter-spacing:-1px; + font-size:16px; + } + +.gallery.default { + display:none; + } + +img.alignnone { + float:none; + margin-bottom:15px; + clear: both; + } + +img.alignleft { + float:left; + margin-right:15px; + margin-bottom:9px; + } + +img.alignright { + float:right; + margin-right:15px; + margin-bottom:9px; + } + +img.aligncenter { + clear: both; + display: block; + margin-left: auto; + margin-right: auto; + margin-bottom:15px; + } \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/less/structure.less b/src/core/static/js/tiny_mce/plugins/fxeditor/less/structure.less new file mode 100755 index 0000000..013642a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/less/structure.less @@ -0,0 +1,202 @@ +#outer { + padding:10px; + } + +.content { + width:@content-width; + margin:0 auto; + position:relative; + background:url(../images/bg/content.png) repeat-y center; + + #tab-menu { + height:27px; + float:left; + width:@content-width; + padding:0px 0 0 0; + border-bottom:1px solid #ccc; + background-color:#fff; + + + ul.tab { + .padding-margin-reset(); + margin-top:4px; + margin-left:8px; + + li { + display:inline; + float:left; + + a { + display:inline-block; + background-color:#E0E0E0; + font-size:13px; + padding:2px 6px 2px 6px; + margin-right:1px; + border:1px solid #ccc; + height:18px; + + &:hover, &.active { + background-color:#fff; + text-decoration:none; + border-bottom:1px solid #fff; + } + + &.active { + font-weight:bold; + } + + } + + } + + } + + } + + .side-sx { + width:@side-width; + display: none; + min-height:276px; + float:left; + padding:10px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-left:1px solid #ccc; + + .formula { + .padding-margin-reset(); + + li { + display: inline; + list-style:none; + + a { + display:inline-block; + margin:0 5px 5px 0; + } + + } + + } + + } + + .side-dx { + float:right; + width:@side-width; + padding:10px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + border-right:1px solid #ccc; + min-height:276px; + + .editor-box { + + textarea { + border:1px solid #ccc; + width:368px; + height:166px; + } + + .results { + text-align:center; + margin-top:20px; + } + + } + + } + + .row-button { + height:43px; + display:block; + width:@content-width; + float:left; + border-top:1px solid #ccc; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding:8px; + text-align:right; + background-color:#fff; + } + + /* START add by other developer no MaMa */ + + .editor-toolbar ul li { + display: inline; + list-style: none; + } + + ul.toolbar { + background-color: #E0E0E0; + border: 1px solid #ccc; + padding: 0 0 0 0; + margin: 0px; + margin-top: 2px; + margin-left: 440px; + margin-right:0; + height: 22px; + + li { + display: inline; + float: left; + + a { + display: inline-block; + background-color: #E0E0E0; + font-size: 13px; + padding: 2px 6px 2px 20px; + margin-right: 1px; + + &#undo-command { + background:url(../images/ico/ico.png) -4px 4px no-repeat; + } + + &#redo-command { + background:url(../images/ico/ico.png) -4px -39px no-repeat; + } + + &#cut-command { + background:url(../images/ico/ico.png) -2px -215px no-repeat; + } + + &#copy-command { + background:url(../images/ico/ico.png) -4px -130px no-repeat; + } + + &#paste-command { + background:url(../images/ico/ico.png) -4px -83px no-repeat; + } + + &#delete-command { + background:url(../images/ico/ico.png) -4px -170px no-repeat; + } + + &:hover { + background-color:#ccc!important; + text-decoration:none; + } + + } + + + } + + + } + + ul.toolbar li a.active { + font-weight: bold; + } + + ul.toolbar li select { + position:absolute; + margin-top:2px; + } + + /* END add by other developer no MaMa */ + +} \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/fxeditor/less/styles.less b/src/core/static/js/tiny_mce/plugins/fxeditor/less/styles.less new file mode 100755 index 0000000..7a50328 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/fxeditor/less/styles.less @@ -0,0 +1,12 @@ +/** + * Import libraries + */ +@import "libs/normalize.less"; +@import "libs/h5bp.less"; +@import "libs/mixins.less"; + +@import "global.less"; +@import "structure.less"; + +@content-width:880px; +@side-width:440px; diff --git a/src/core/static/js/tiny_mce/plugins/iespell/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/iespell/editor_plugin.js new file mode 100644 index 0000000..e9cba10 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/iespell/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.IESpell",{init:function(a,b){var c=this,d;if(!tinymce.isIE){return}c.editor=a;a.addCommand("mceIESpell",function(){try{d=new ActiveXObject("ieSpell.ieSpellExtension");d.CheckDocumentNode(a.getDoc().documentElement)}catch(f){if(f.number==-2146827859){a.windowManager.confirm(a.getLang("iespell.download"),function(e){if(e){window.open("http://www.iespell.com/download.php","ieSpellDownload","")}})}else{a.windowManager.alert("Error Loading ieSpell: Exception "+f.number)}}});a.addButton("iespell",{title:"iespell.iespell_desc",cmd:"mceIESpell"})},getInfo:function(){return{longname:"IESpell (IE Only)",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/iespell",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("iespell",tinymce.plugins.IESpell)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/iespell/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/iespell/editor_plugin_src.js new file mode 100644 index 0000000..1b2bb98 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/iespell/editor_plugin_src.js @@ -0,0 +1,54 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.IESpell', { + init : function(ed, url) { + var t = this, sp; + + if (!tinymce.isIE) + return; + + t.editor = ed; + + // Register commands + ed.addCommand('mceIESpell', function() { + try { + sp = new ActiveXObject("ieSpell.ieSpellExtension"); + sp.CheckDocumentNode(ed.getDoc().documentElement); + } catch (e) { + if (e.number == -2146827859) { + ed.windowManager.confirm(ed.getLang("iespell.download"), function(s) { + if (s) + window.open('http://www.iespell.com/download.php', 'ieSpellDownload', ''); + }); + } else + ed.windowManager.alert("Error Loading ieSpell: Exception " + e.number); + } + }); + + // Register buttons + ed.addButton('iespell', {title : 'iespell.iespell_desc', cmd : 'mceIESpell'}); + }, + + getInfo : function() { + return { + longname : 'IESpell (IE Only)', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/iespell', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('iespell', tinymce.plugins.IESpell); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/inlinepopups/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/inlinepopups/editor_plugin.js new file mode 100644 index 0000000..8bb96f9 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/inlinepopups/editor_plugin.js @@ -0,0 +1 @@ +(function(){var d=tinymce.DOM,b=tinymce.dom.Element,a=tinymce.dom.Event,e=tinymce.each,c=tinymce.is;tinymce.create("tinymce.plugins.InlinePopups",{init:function(f,g){f.onBeforeRenderUI.add(function(){f.windowManager=new tinymce.InlineWindowManager(f);d.loadCSS(g+"/skins/"+(f.settings.inlinepopups_skin||"clearlooks2")+"/window.css")})},getInfo:function(){return{longname:"InlinePopups",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.create("tinymce.InlineWindowManager:tinymce.WindowManager",{InlineWindowManager:function(f){var g=this;g.parent(f);g.zIndex=300000;g.count=0;g.windows={}},open:function(s,j){var z=this,i,k="",r=z.editor,g=0,v=0,h,m,o,q,l,x,y,n;s=s||{};j=j||{};if(!s.inline){return z.parent(s,j)}n=z._frontWindow();if(n&&d.get(n.id+"_ifr")){n.focussedElement=d.get(n.id+"_ifr").contentWindow.document.activeElement}if(!s.type){z.bookmark=r.selection.getBookmark(1)}i=d.uniqueId();h=d.getViewPort();s.width=parseInt(s.width||320);s.height=parseInt(s.height||240)+(tinymce.isIE?8:0);s.min_width=parseInt(s.min_width||150);s.min_height=parseInt(s.min_height||100);s.max_width=parseInt(s.max_width||2000);s.max_height=parseInt(s.max_height||2000);s.left=s.left||Math.round(Math.max(h.x,h.x+(h.w/2)-(s.width/2)));s.top=s.top||Math.round(Math.max(h.y,h.y+(h.h/2)-(s.height/2)));s.movable=s.resizable=true;j.mce_width=s.width;j.mce_height=s.height;j.mce_inline=true;j.mce_window_id=i;j.mce_auto_focus=s.auto_focus;z.features=s;z.params=j;z.onOpen.dispatch(z,s,j);if(s.type){k+=" mceModal";if(s.type){k+=" mce"+s.type.substring(0,1).toUpperCase()+s.type.substring(1)}s.resizable=false}if(s.statusbar){k+=" mceStatusbar"}if(s.resizable){k+=" mceResizable"}if(s.minimizable){k+=" mceMinimizable"}if(s.maximizable){k+=" mceMaximizable"}if(s.movable){k+=" mceMovable"}z._addAll(d.doc.body,["div",{id:i,role:"dialog","aria-labelledby":s.type?i+"_content":i+"_title","class":(r.settings.inlinepopups_skin||"clearlooks2")+(tinymce.isIE&&window.getSelection?" ie9":""),style:"width:100px;height:100px"},["div",{id:i+"_wrapper","class":"mceWrapper"+k},["div",{id:i+"_top","class":"mceTop"},["div",{"class":"mceLeft"}],["div",{"class":"mceCenter"}],["div",{"class":"mceRight"}],["span",{id:i+"_title"},s.title||""]],["div",{id:i+"_middle","class":"mceMiddle"},["div",{id:i+"_left","class":"mceLeft",tabindex:"0"}],["span",{id:i+"_content"}],["div",{id:i+"_right","class":"mceRight",tabindex:"0"}]],["div",{id:i+"_bottom","class":"mceBottom"},["div",{"class":"mceLeft"}],["div",{"class":"mceCenter"}],["div",{"class":"mceRight"}],["span",{id:i+"_status"},"Content"]],["a",{"class":"mceMove",tabindex:"-1",href:"javascript:;"}],["a",{"class":"mceMin",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{"class":"mceMax",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{"class":"mceMed",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{"class":"mceClose",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{id:i+"_resize_n","class":"mceResize mceResizeN",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_s","class":"mceResize mceResizeS",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_w","class":"mceResize mceResizeW",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_e","class":"mceResize mceResizeE",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_nw","class":"mceResize mceResizeNW",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_ne","class":"mceResize mceResizeNE",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_sw","class":"mceResize mceResizeSW",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_se","class":"mceResize mceResizeSE",tabindex:"-1",href:"javascript:;"}]]]);d.setStyles(i,{top:-10000,left:-10000});if(tinymce.isGecko){d.setStyle(i,"overflow","auto")}if(!s.type){g+=d.get(i+"_left").clientWidth;g+=d.get(i+"_right").clientWidth;v+=d.get(i+"_top").clientHeight;v+=d.get(i+"_bottom").clientHeight}d.setStyles(i,{top:s.top,left:s.left,width:s.width+g,height:s.height+v});y=s.url||s.file;if(y){if(tinymce.relaxedDomain){y+=(y.indexOf("?")==-1?"?":"&")+"mce_rdomain="+tinymce.relaxedDomain}y=tinymce._addVer(y)}if(!s.type){d.add(i+"_content","iframe",{id:i+"_ifr",src:'javascript:""',frameBorder:0,style:"border:0;width:10px;height:10px"});d.setStyles(i+"_ifr",{width:s.width,height:s.height});d.setAttrib(i+"_ifr","src",y)}else{d.add(i+"_wrapper","a",{id:i+"_ok","class":"mceButton mceOk",href:"javascript:;",onmousedown:"return false;"},"Ok");if(s.type=="confirm"){d.add(i+"_wrapper","a",{"class":"mceButton mceCancel",href:"javascript:;",onmousedown:"return false;"},"Cancel")}d.add(i+"_middle","div",{"class":"mceIcon"});d.setHTML(i+"_content",s.content.replace("\n","<br />"));a.add(i,"keyup",function(f){var p=27;if(f.keyCode===p){s.button_func(false);return a.cancel(f)}});a.add(i,"keydown",function(f){var t,p=9;if(f.keyCode===p){t=d.select("a.mceCancel",i+"_wrapper")[0];if(t&&t!==f.target){t.focus()}else{d.get(i+"_ok").focus()}return a.cancel(f)}})}o=a.add(i,"mousedown",function(t){var u=t.target,f,p;f=z.windows[i];z.focus(i);if(u.nodeName=="A"||u.nodeName=="a"){if(u.className=="mceClose"){z.close(null,i);return a.cancel(t)}else{if(u.className=="mceMax"){f.oldPos=f.element.getXY();f.oldSize=f.element.getSize();p=d.getViewPort();p.w-=2;p.h-=2;f.element.moveTo(p.x,p.y);f.element.resizeTo(p.w,p.h);d.setStyles(i+"_ifr",{width:p.w-f.deltaWidth,height:p.h-f.deltaHeight});d.addClass(i+"_wrapper","mceMaximized")}else{if(u.className=="mceMed"){f.element.moveTo(f.oldPos.x,f.oldPos.y);f.element.resizeTo(f.oldSize.w,f.oldSize.h);f.iframeElement.resizeTo(f.oldSize.w-f.deltaWidth,f.oldSize.h-f.deltaHeight);d.removeClass(i+"_wrapper","mceMaximized")}else{if(u.className=="mceMove"){return z._startDrag(i,t,u.className)}else{if(d.hasClass(u,"mceResize")){return z._startDrag(i,t,u.className.substring(13))}}}}}}});q=a.add(i,"click",function(f){var p=f.target;z.focus(i);if(p.nodeName=="A"||p.nodeName=="a"){switch(p.className){case"mceClose":z.close(null,i);return a.cancel(f);case"mceButton mceOk":case"mceButton mceCancel":s.button_func(p.className=="mceButton mceOk");return a.cancel(f)}}});a.add([i+"_left",i+"_right"],"focus",function(p){var t=d.get(i+"_ifr");if(t){var f=t.contentWindow.document.body;var u=d.select(":input:enabled,*[tabindex=0]",f);if(p.target.id===(i+"_left")){u[u.length-1].focus()}else{u[0].focus()}}else{d.get(i+"_ok").focus()}});x=z.windows[i]={id:i,mousedown_func:o,click_func:q,element:new b(i,{blocker:1,container:r.getContainer()}),iframeElement:new b(i+"_ifr"),features:s,deltaWidth:g,deltaHeight:v};x.iframeElement.on("focus",function(){z.focus(i)});if(z.count==0&&z.editor.getParam("dialog_type","modal")=="modal"){d.add(d.doc.body,"div",{id:"mceModalBlocker","class":(z.editor.settings.inlinepopups_skin||"clearlooks2")+"_modalBlocker",style:{zIndex:z.zIndex-1}});d.show("mceModalBlocker");d.setAttrib(d.doc.body,"aria-hidden","true")}else{d.setStyle("mceModalBlocker","z-index",z.zIndex-1)}if(tinymce.isIE6||/Firefox\/2\./.test(navigator.userAgent)||(tinymce.isIE&&!d.boxModel)){d.setStyles("mceModalBlocker",{position:"absolute",left:h.x,top:h.y,width:h.w-2,height:h.h-2})}d.setAttrib(i,"aria-hidden","false");z.focus(i);z._fixIELayout(i,1);if(d.get(i+"_ok")){d.get(i+"_ok").focus()}z.count++;return x},focus:function(h){var g=this,f;if(f=g.windows[h]){f.zIndex=this.zIndex++;f.element.setStyle("zIndex",f.zIndex);f.element.update();h=h+"_wrapper";d.removeClass(g.lastId,"mceFocus");d.addClass(h,"mceFocus");g.lastId=h;if(f.focussedElement){f.focussedElement.focus()}else{if(d.get(h+"_ok")){d.get(f.id+"_ok").focus()}else{if(d.get(f.id+"_ifr")){d.get(f.id+"_ifr").focus()}}}}},_addAll:function(k,h){var g,l,f=this,j=tinymce.DOM;if(c(h,"string")){k.appendChild(j.doc.createTextNode(h))}else{if(h.length){k=k.appendChild(j.create(h[0],h[1]));for(g=2;g<h.length;g++){f._addAll(k,h[g])}}}},_startDrag:function(v,G,E){var o=this,u,z,C=d.doc,f,l=o.windows[v],h=l.element,y=h.getXY(),x,q,F,g,A,s,r,j,i,m,k,n,B;g={x:0,y:0};A=d.getViewPort();A.w-=2;A.h-=2;j=G.screenX;i=G.screenY;m=k=n=B=0;u=a.add(C,"mouseup",function(p){a.remove(C,"mouseup",u);a.remove(C,"mousemove",z);if(f){f.remove()}h.moveBy(m,k);h.resizeBy(n,B);q=h.getSize();d.setStyles(v+"_ifr",{width:q.w-l.deltaWidth,height:q.h-l.deltaHeight});o._fixIELayout(v,1);return a.cancel(p)});if(E!="Move"){D()}function D(){if(f){return}o._fixIELayout(v,0);d.add(C.body,"div",{id:"mceEventBlocker","class":"mceEventBlocker "+(o.editor.settings.inlinepopups_skin||"clearlooks2"),style:{zIndex:o.zIndex+1}});if(tinymce.isIE6||(tinymce.isIE&&!d.boxModel)){d.setStyles("mceEventBlocker",{position:"absolute",left:A.x,top:A.y,width:A.w-2,height:A.h-2})}f=new b("mceEventBlocker");f.update();x=h.getXY();q=h.getSize();s=g.x+x.x-A.x;r=g.y+x.y-A.y;d.add(f.get(),"div",{id:"mcePlaceHolder","class":"mcePlaceHolder",style:{left:s,top:r,width:q.w,height:q.h}});F=new b("mcePlaceHolder")}z=a.add(C,"mousemove",function(w){var p,H,t;D();p=w.screenX-j;H=w.screenY-i;switch(E){case"ResizeW":m=p;n=0-p;break;case"ResizeE":n=p;break;case"ResizeN":case"ResizeNW":case"ResizeNE":if(E=="ResizeNW"){m=p;n=0-p}else{if(E=="ResizeNE"){n=p}}k=H;B=0-H;break;case"ResizeS":case"ResizeSW":case"ResizeSE":if(E=="ResizeSW"){m=p;n=0-p}else{if(E=="ResizeSE"){n=p}}B=H;break;case"mceMove":m=p;k=H;break}if(n<(t=l.features.min_width-q.w)){if(m!==0){m+=n-t}n=t}if(B<(t=l.features.min_height-q.h)){if(k!==0){k+=B-t}B=t}n=Math.min(n,l.features.max_width-q.w);B=Math.min(B,l.features.max_height-q.h);m=Math.max(m,A.x-(s+A.x));k=Math.max(k,A.y-(r+A.y));m=Math.min(m,(A.w+A.x)-(s+q.w+A.x));k=Math.min(k,(A.h+A.y)-(r+q.h+A.y));if(m+k!==0){if(s+m<0){m=0}if(r+k<0){k=0}F.moveTo(s+m,r+k)}if(n+B!==0){F.resizeTo(q.w+n,q.h+B)}return a.cancel(w)});return a.cancel(G)},resizeBy:function(g,h,i){var f=this.windows[i];if(f){f.element.resizeBy(g,h);f.iframeElement.resizeBy(g,h)}},close:function(i,k){var g=this,f,j=d.doc,h,k;k=g._findId(k||i);if(!g.windows[k]){g.parent(i);return}g.count--;if(g.count==0){d.remove("mceModalBlocker");d.setAttrib(d.doc.body,"aria-hidden","false");g.editor.focus()}if(f=g.windows[k]){g.onClose.dispatch(g);a.remove(j,"mousedown",f.mousedownFunc);a.remove(j,"click",f.clickFunc);a.clear(k);a.clear(k+"_ifr");d.setAttrib(k+"_ifr","src",'javascript:""');f.element.remove();delete g.windows[k];h=g._frontWindow();if(h){g.focus(h.id)}}},_frontWindow:function(){var g,f=0;e(this.windows,function(h){if(h.zIndex>f){g=h;f=h.zIndex}});return g},setTitle:function(f,g){var h;f=this._findId(f);if(h=d.get(f+"_title")){h.innerHTML=d.encode(g)}},alert:function(g,f,j){var i=this,h;h=i.open({title:i,type:"alert",button_func:function(k){if(f){f.call(k||i,k)}i.close(null,h.id)},content:d.encode(i.editor.getLang(g,g)),inline:1,width:400,height:130})},confirm:function(g,f,j){var i=this,h;h=i.open({title:i,type:"confirm",button_func:function(k){if(f){f.call(k||i,k)}i.close(null,h.id)},content:d.encode(i.editor.getLang(g,g)),inline:1,width:400,height:130})},_findId:function(f){var g=this;if(typeof(f)=="string"){return f}e(g.windows,function(h){var i=d.get(h.id+"_ifr");if(i&&f==i.contentWindow){f=h.id;return false}});return f},_fixIELayout:function(i,h){var f,g;if(!tinymce.isIE6){return}e(["n","s","w","e","nw","ne","sw","se"],function(j){var k=d.get(i+"_resize_"+j);d.setStyles(k,{width:h?k.clientWidth:"",height:h?k.clientHeight:"",cursor:d.getStyle(k,"cursor",1)});d.setStyle(i+"_bottom","bottom","-1px");k=0});if(f=this.windows[i]){f.element.hide();f.element.show();e(d.select("div,a",i),function(k,j){if(k.currentStyle.backgroundImage!="none"){g=new Image();g.src=k.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/,"$1")}});d.get(i).style.filter=""}}});tinymce.PluginManager.add("inlinepopups",tinymce.plugins.InlinePopups)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/inlinepopups/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/inlinepopups/editor_plugin_src.js new file mode 100644 index 0000000..67123ca --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/inlinepopups/editor_plugin_src.js @@ -0,0 +1,699 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var DOM = tinymce.DOM, Element = tinymce.dom.Element, Event = tinymce.dom.Event, each = tinymce.each, is = tinymce.is; + + tinymce.create('tinymce.plugins.InlinePopups', { + init : function(ed, url) { + // Replace window manager + ed.onBeforeRenderUI.add(function() { + ed.windowManager = new tinymce.InlineWindowManager(ed); + DOM.loadCSS(url + '/skins/' + (ed.settings.inlinepopups_skin || 'clearlooks2') + "/window.css"); + }); + }, + + getInfo : function() { + return { + longname : 'InlinePopups', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + tinymce.create('tinymce.InlineWindowManager:tinymce.WindowManager', { + InlineWindowManager : function(ed) { + var t = this; + + t.parent(ed); + t.zIndex = 300000; + t.count = 0; + t.windows = {}; + }, + + open : function(f, p) { + var t = this, id, opt = '', ed = t.editor, dw = 0, dh = 0, vp, po, mdf, clf, we, w, u, parentWindow; + + f = f || {}; + p = p || {}; + + // Run native windows + if (!f.inline) + return t.parent(f, p); + + parentWindow = t._frontWindow(); + if (parentWindow && DOM.get(parentWindow.id + '_ifr')) { + parentWindow.focussedElement = DOM.get(parentWindow.id + '_ifr').contentWindow.document.activeElement; + } + + // Only store selection if the type is a normal window + if (!f.type) + t.bookmark = ed.selection.getBookmark(1); + + id = DOM.uniqueId(); + vp = DOM.getViewPort(); + f.width = parseInt(f.width || 320); + f.height = parseInt(f.height || 240) + (tinymce.isIE ? 8 : 0); + f.min_width = parseInt(f.min_width || 150); + f.min_height = parseInt(f.min_height || 100); + f.max_width = parseInt(f.max_width || 2000); + f.max_height = parseInt(f.max_height || 2000); + f.left = f.left || Math.round(Math.max(vp.x, vp.x + (vp.w / 2.0) - (f.width / 2.0))); + f.top = f.top || Math.round(Math.max(vp.y, vp.y + (vp.h / 2.0) - (f.height / 2.0))); + f.movable = f.resizable = true; + p.mce_width = f.width; + p.mce_height = f.height; + p.mce_inline = true; + p.mce_window_id = id; + p.mce_auto_focus = f.auto_focus; + + // Transpose +// po = DOM.getPos(ed.getContainer()); +// f.left -= po.x; +// f.top -= po.y; + + t.features = f; + t.params = p; + t.onOpen.dispatch(t, f, p); + + if (f.type) { + opt += ' mceModal'; + + if (f.type) + opt += ' mce' + f.type.substring(0, 1).toUpperCase() + f.type.substring(1); + + f.resizable = false; + } + + if (f.statusbar) + opt += ' mceStatusbar'; + + if (f.resizable) + opt += ' mceResizable'; + + if (f.minimizable) + opt += ' mceMinimizable'; + + if (f.maximizable) + opt += ' mceMaximizable'; + + if (f.movable) + opt += ' mceMovable'; + + // Create DOM objects + t._addAll(DOM.doc.body, + ['div', {id : id, role : 'dialog', 'aria-labelledby': f.type ? id + '_content' : id + '_title', 'class' : (ed.settings.inlinepopups_skin || 'clearlooks2') + (tinymce.isIE && window.getSelection ? ' ie9' : ''), style : 'width:100px;height:100px'}, + ['div', {id : id + '_wrapper', 'class' : 'mceWrapper' + opt}, + ['div', {id : id + '_top', 'class' : 'mceTop'}, + ['div', {'class' : 'mceLeft'}], + ['div', {'class' : 'mceCenter'}], + ['div', {'class' : 'mceRight'}], + ['span', {id : id + '_title'}, f.title || ''] + ], + + ['div', {id : id + '_middle', 'class' : 'mceMiddle'}, + ['div', {id : id + '_left', 'class' : 'mceLeft', tabindex : '0'}], + ['span', {id : id + '_content'}], + ['div', {id : id + '_right', 'class' : 'mceRight', tabindex : '0'}] + ], + + ['div', {id : id + '_bottom', 'class' : 'mceBottom'}, + ['div', {'class' : 'mceLeft'}], + ['div', {'class' : 'mceCenter'}], + ['div', {'class' : 'mceRight'}], + ['span', {id : id + '_status'}, 'Content'] + ], + + ['a', {'class' : 'mceMove', tabindex : '-1', href : 'javascript:;'}], + ['a', {'class' : 'mceMin', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], + ['a', {'class' : 'mceMax', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], + ['a', {'class' : 'mceMed', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], + ['a', {'class' : 'mceClose', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], + ['a', {id : id + '_resize_n', 'class' : 'mceResize mceResizeN', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_s', 'class' : 'mceResize mceResizeS', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_w', 'class' : 'mceResize mceResizeW', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_e', 'class' : 'mceResize mceResizeE', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_nw', 'class' : 'mceResize mceResizeNW', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_ne', 'class' : 'mceResize mceResizeNE', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_sw', 'class' : 'mceResize mceResizeSW', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_se', 'class' : 'mceResize mceResizeSE', tabindex : '-1', href : 'javascript:;'}] + ] + ] + ); + + DOM.setStyles(id, {top : -10000, left : -10000}); + + // Fix gecko rendering bug, where the editors iframe messed with window contents + if (tinymce.isGecko) + DOM.setStyle(id, 'overflow', 'auto'); + + // Measure borders + if (!f.type) { + dw += DOM.get(id + '_left').clientWidth; + dw += DOM.get(id + '_right').clientWidth; + dh += DOM.get(id + '_top').clientHeight; + dh += DOM.get(id + '_bottom').clientHeight; + } + + // Resize window + DOM.setStyles(id, {top : f.top, left : f.left, width : f.width + dw, height : f.height + dh}); + + u = f.url || f.file; + if (u) { + if (tinymce.relaxedDomain) + u += (u.indexOf('?') == -1 ? '?' : '&') + 'mce_rdomain=' + tinymce.relaxedDomain; + + u = tinymce._addVer(u); + } + + if (!f.type) { + DOM.add(id + '_content', 'iframe', {id : id + '_ifr', src : 'javascript:""', frameBorder : 0, style : 'border:0;width:10px;height:10px'}); + DOM.setStyles(id + '_ifr', {width : f.width, height : f.height}); + DOM.setAttrib(id + '_ifr', 'src', u); + } else { + DOM.add(id + '_wrapper', 'a', {id : id + '_ok', 'class' : 'mceButton mceOk', href : 'javascript:;', onmousedown : 'return false;'}, 'Ok'); + + if (f.type == 'confirm') + DOM.add(id + '_wrapper', 'a', {'class' : 'mceButton mceCancel', href : 'javascript:;', onmousedown : 'return false;'}, 'Cancel'); + + DOM.add(id + '_middle', 'div', {'class' : 'mceIcon'}); + DOM.setHTML(id + '_content', f.content.replace('\n', '<br />')); + + Event.add(id, 'keyup', function(evt) { + var VK_ESCAPE = 27; + if (evt.keyCode === VK_ESCAPE) { + f.button_func(false); + return Event.cancel(evt); + } + }); + + Event.add(id, 'keydown', function(evt) { + var cancelButton, VK_TAB = 9; + if (evt.keyCode === VK_TAB) { + cancelButton = DOM.select('a.mceCancel', id + '_wrapper')[0]; + if (cancelButton && cancelButton !== evt.target) { + cancelButton.focus(); + } else { + DOM.get(id + '_ok').focus(); + } + return Event.cancel(evt); + } + }); + } + + // Register events + mdf = Event.add(id, 'mousedown', function(e) { + var n = e.target, w, vp; + + w = t.windows[id]; + t.focus(id); + + if (n.nodeName == 'A' || n.nodeName == 'a') { + if (n.className == 'mceClose') { + t.close(null, id); + return Event.cancel(e); + } else if (n.className == 'mceMax') { + w.oldPos = w.element.getXY(); + w.oldSize = w.element.getSize(); + + vp = DOM.getViewPort(); + + // Reduce viewport size to avoid scrollbars + vp.w -= 2; + vp.h -= 2; + + w.element.moveTo(vp.x, vp.y); + w.element.resizeTo(vp.w, vp.h); + DOM.setStyles(id + '_ifr', {width : vp.w - w.deltaWidth, height : vp.h - w.deltaHeight}); + DOM.addClass(id + '_wrapper', 'mceMaximized'); + } else if (n.className == 'mceMed') { + // Reset to old size + w.element.moveTo(w.oldPos.x, w.oldPos.y); + w.element.resizeTo(w.oldSize.w, w.oldSize.h); + w.iframeElement.resizeTo(w.oldSize.w - w.deltaWidth, w.oldSize.h - w.deltaHeight); + + DOM.removeClass(id + '_wrapper', 'mceMaximized'); + } else if (n.className == 'mceMove') + return t._startDrag(id, e, n.className); + else if (DOM.hasClass(n, 'mceResize')) + return t._startDrag(id, e, n.className.substring(13)); + } + }); + + clf = Event.add(id, 'click', function(e) { + var n = e.target; + + t.focus(id); + + if (n.nodeName == 'A' || n.nodeName == 'a') { + switch (n.className) { + case 'mceClose': + t.close(null, id); + return Event.cancel(e); + + case 'mceButton mceOk': + case 'mceButton mceCancel': + f.button_func(n.className == 'mceButton mceOk'); + return Event.cancel(e); + } + } + }); + + // Make sure the tab order loops within the dialog. + Event.add([id + '_left', id + '_right'], 'focus', function(evt) { + var iframe = DOM.get(id + '_ifr'); + if (iframe) { + var body = iframe.contentWindow.document.body; + var focusable = DOM.select(':input:enabled,*[tabindex=0]', body); + if (evt.target.id === (id + '_left')) { + focusable[focusable.length - 1].focus(); + } else { + focusable[0].focus(); + } + } else { + DOM.get(id + '_ok').focus(); + } + }); + + // Add window + w = t.windows[id] = { + id : id, + mousedown_func : mdf, + click_func : clf, + element : new Element(id, {blocker : 1, container : ed.getContainer()}), + iframeElement : new Element(id + '_ifr'), + features : f, + deltaWidth : dw, + deltaHeight : dh + }; + + w.iframeElement.on('focus', function() { + t.focus(id); + }); + + // Setup blocker + if (t.count == 0 && t.editor.getParam('dialog_type', 'modal') == 'modal') { + DOM.add(DOM.doc.body, 'div', { + id : 'mceModalBlocker', + 'class' : (t.editor.settings.inlinepopups_skin || 'clearlooks2') + '_modalBlocker', + style : {zIndex : t.zIndex - 1} + }); + + DOM.show('mceModalBlocker'); // Reduces flicker in IE + DOM.setAttrib(DOM.doc.body, 'aria-hidden', 'true'); + } else + DOM.setStyle('mceModalBlocker', 'z-index', t.zIndex - 1); + + if (tinymce.isIE6 || /Firefox\/2\./.test(navigator.userAgent) || (tinymce.isIE && !DOM.boxModel)) + DOM.setStyles('mceModalBlocker', {position : 'absolute', left : vp.x, top : vp.y, width : vp.w - 2, height : vp.h - 2}); + + DOM.setAttrib(id, 'aria-hidden', 'false'); + t.focus(id); + t._fixIELayout(id, 1); + + // Focus ok button + if (DOM.get(id + '_ok')) + DOM.get(id + '_ok').focus(); + t.count++; + + return w; + }, + + focus : function(id) { + var t = this, w; + + if (w = t.windows[id]) { + w.zIndex = this.zIndex++; + w.element.setStyle('zIndex', w.zIndex); + w.element.update(); + + id = id + '_wrapper'; + DOM.removeClass(t.lastId, 'mceFocus'); + DOM.addClass(id, 'mceFocus'); + t.lastId = id; + + if (w.focussedElement) { + w.focussedElement.focus(); + } else if (DOM.get(id + '_ok')) { + DOM.get(w.id + '_ok').focus(); + } else if (DOM.get(w.id + '_ifr')) { + DOM.get(w.id + '_ifr').focus(); + } + } + }, + + _addAll : function(te, ne) { + var i, n, t = this, dom = tinymce.DOM; + + if (is(ne, 'string')) + te.appendChild(dom.doc.createTextNode(ne)); + else if (ne.length) { + te = te.appendChild(dom.create(ne[0], ne[1])); + + for (i=2; i<ne.length; i++) + t._addAll(te, ne[i]); + } + }, + + _startDrag : function(id, se, ac) { + var t = this, mu, mm, d = DOM.doc, eb, w = t.windows[id], we = w.element, sp = we.getXY(), p, sz, ph, cp, vp, sx, sy, sex, sey, dx, dy, dw, dh; + + // Get positons and sizes +// cp = DOM.getPos(t.editor.getContainer()); + cp = {x : 0, y : 0}; + vp = DOM.getViewPort(); + + // Reduce viewport size to avoid scrollbars while dragging + vp.w -= 2; + vp.h -= 2; + + sex = se.screenX; + sey = se.screenY; + dx = dy = dw = dh = 0; + + // Handle mouse up + mu = Event.add(d, 'mouseup', function(e) { + Event.remove(d, 'mouseup', mu); + Event.remove(d, 'mousemove', mm); + + if (eb) + eb.remove(); + + we.moveBy(dx, dy); + we.resizeBy(dw, dh); + sz = we.getSize(); + DOM.setStyles(id + '_ifr', {width : sz.w - w.deltaWidth, height : sz.h - w.deltaHeight}); + t._fixIELayout(id, 1); + + return Event.cancel(e); + }); + + if (ac != 'Move') + startMove(); + + function startMove() { + if (eb) + return; + + t._fixIELayout(id, 0); + + // Setup event blocker + DOM.add(d.body, 'div', { + id : 'mceEventBlocker', + 'class' : 'mceEventBlocker ' + (t.editor.settings.inlinepopups_skin || 'clearlooks2'), + style : {zIndex : t.zIndex + 1} + }); + + if (tinymce.isIE6 || (tinymce.isIE && !DOM.boxModel)) + DOM.setStyles('mceEventBlocker', {position : 'absolute', left : vp.x, top : vp.y, width : vp.w - 2, height : vp.h - 2}); + + eb = new Element('mceEventBlocker'); + eb.update(); + + // Setup placeholder + p = we.getXY(); + sz = we.getSize(); + sx = cp.x + p.x - vp.x; + sy = cp.y + p.y - vp.y; + DOM.add(eb.get(), 'div', {id : 'mcePlaceHolder', 'class' : 'mcePlaceHolder', style : {left : sx, top : sy, width : sz.w, height : sz.h}}); + ph = new Element('mcePlaceHolder'); + }; + + // Handle mouse move/drag + mm = Event.add(d, 'mousemove', function(e) { + var x, y, v; + + startMove(); + + x = e.screenX - sex; + y = e.screenY - sey; + + switch (ac) { + case 'ResizeW': + dx = x; + dw = 0 - x; + break; + + case 'ResizeE': + dw = x; + break; + + case 'ResizeN': + case 'ResizeNW': + case 'ResizeNE': + if (ac == "ResizeNW") { + dx = x; + dw = 0 - x; + } else if (ac == "ResizeNE") + dw = x; + + dy = y; + dh = 0 - y; + break; + + case 'ResizeS': + case 'ResizeSW': + case 'ResizeSE': + if (ac == "ResizeSW") { + dx = x; + dw = 0 - x; + } else if (ac == "ResizeSE") + dw = x; + + dh = y; + break; + + case 'mceMove': + dx = x; + dy = y; + break; + } + + // Boundary check + if (dw < (v = w.features.min_width - sz.w)) { + if (dx !== 0) + dx += dw - v; + + dw = v; + } + + if (dh < (v = w.features.min_height - sz.h)) { + if (dy !== 0) + dy += dh - v; + + dh = v; + } + + dw = Math.min(dw, w.features.max_width - sz.w); + dh = Math.min(dh, w.features.max_height - sz.h); + dx = Math.max(dx, vp.x - (sx + vp.x)); + dy = Math.max(dy, vp.y - (sy + vp.y)); + dx = Math.min(dx, (vp.w + vp.x) - (sx + sz.w + vp.x)); + dy = Math.min(dy, (vp.h + vp.y) - (sy + sz.h + vp.y)); + + // Move if needed + if (dx + dy !== 0) { + if (sx + dx < 0) + dx = 0; + + if (sy + dy < 0) + dy = 0; + + ph.moveTo(sx + dx, sy + dy); + } + + // Resize if needed + if (dw + dh !== 0) + ph.resizeTo(sz.w + dw, sz.h + dh); + + return Event.cancel(e); + }); + + return Event.cancel(se); + }, + + resizeBy : function(dw, dh, id) { + var w = this.windows[id]; + + if (w) { + w.element.resizeBy(dw, dh); + w.iframeElement.resizeBy(dw, dh); + } + }, + + close : function(win, id) { + var t = this, w, d = DOM.doc, fw, id; + + id = t._findId(id || win); + + // Probably not inline + if (!t.windows[id]) { + t.parent(win); + return; + } + + t.count--; + + if (t.count == 0) { + DOM.remove('mceModalBlocker'); + DOM.setAttrib(DOM.doc.body, 'aria-hidden', 'false'); + t.editor.focus(); + } + + if (w = t.windows[id]) { + t.onClose.dispatch(t); + Event.remove(d, 'mousedown', w.mousedownFunc); + Event.remove(d, 'click', w.clickFunc); + Event.clear(id); + Event.clear(id + '_ifr'); + + DOM.setAttrib(id + '_ifr', 'src', 'javascript:""'); // Prevent leak + w.element.remove(); + delete t.windows[id]; + + fw = t._frontWindow(); + + if (fw) + t.focus(fw.id); + } + }, + + // Find front most window + _frontWindow : function() { + var fw, ix = 0; + // Find front most window and focus that + each (this.windows, function(w) { + if (w.zIndex > ix) { + fw = w; + ix = w.zIndex; + } + }); + return fw; + }, + + setTitle : function(w, ti) { + var e; + + w = this._findId(w); + + if (e = DOM.get(w + '_title')) + e.innerHTML = DOM.encode(ti); + }, + + alert : function(txt, cb, s) { + var t = this, w; + + w = t.open({ + title : t, + type : 'alert', + button_func : function(s) { + if (cb) + cb.call(s || t, s); + + t.close(null, w.id); + }, + content : DOM.encode(t.editor.getLang(txt, txt)), + inline : 1, + width : 400, + height : 130 + }); + }, + + confirm : function(txt, cb, s) { + var t = this, w; + + w = t.open({ + title : t, + type : 'confirm', + button_func : function(s) { + if (cb) + cb.call(s || t, s); + + t.close(null, w.id); + }, + content : DOM.encode(t.editor.getLang(txt, txt)), + inline : 1, + width : 400, + height : 130 + }); + }, + + // Internal functions + + _findId : function(w) { + var t = this; + + if (typeof(w) == 'string') + return w; + + each(t.windows, function(wo) { + var ifr = DOM.get(wo.id + '_ifr'); + + if (ifr && w == ifr.contentWindow) { + w = wo.id; + return false; + } + }); + + return w; + }, + + _fixIELayout : function(id, s) { + var w, img; + + if (!tinymce.isIE6) + return; + + // Fixes the bug where hover flickers and does odd things in IE6 + each(['n','s','w','e','nw','ne','sw','se'], function(v) { + var e = DOM.get(id + '_resize_' + v); + + DOM.setStyles(e, { + width : s ? e.clientWidth : '', + height : s ? e.clientHeight : '', + cursor : DOM.getStyle(e, 'cursor', 1) + }); + + DOM.setStyle(id + "_bottom", 'bottom', '-1px'); + + e = 0; + }); + + // Fixes graphics glitch + if (w = this.windows[id]) { + // Fixes rendering bug after resize + w.element.hide(); + w.element.show(); + + // Forced a repaint of the window + //DOM.get(id).style.filter = ''; + + // IE has a bug where images used in CSS won't get loaded + // sometimes when the cache in the browser is disabled + // This fix tries to solve it by loading the images using the image object + each(DOM.select('div,a', id), function(e, i) { + if (e.currentStyle.backgroundImage != 'none') { + img = new Image(); + img.src = e.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/, '$1'); + } + }); + + DOM.get(id).style.filter = ''; + } + } + }); + + // Register plugin + tinymce.PluginManager.add('inlinepopups', tinymce.plugins.InlinePopups); +})(); + diff --git a/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif b/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif new file mode 100644 index 0000000000000000000000000000000000000000..219139857ead162c6c83fa92e4a36eb978359b70 GIT binary patch literal 810 zcmV+_1J(RTNk%v~VITk?0QP$T|NsBgZf>Is3*B5?sT&&Hqoc$;Jkrt6&k+&QHa5gV zL)l77I5;@fLqpYMWV<abwUm?7QBkxrGu*<$+j)7$S6A9;Y1?*oyK8FB&&|;q8Uq6Z z%mM<tJUq<=1mJ9J-(q5{BqZT=b=gHl*N%?Q4i4J1w6jf2;c#%QD=X6^B;RFa%}Yzp z2ng9yQp1dkrxq5d6co*~vAevw&lVQfJw4b#LAqpQ*4EV8&dt-y$<jJH(kUsW5)!XE zI<Kdt&l(!iN=n~qYTH*=+fY!kC@7*564*OC#m2;^otw#{p&J_;(7(MUB_+qm#;Ty7 z)i5y3V`IHZN!8NO&$_wHv9Hj;zSfwSz<++opPsm0UDu+bp8^8hRaMU{EZU5W)p>c- z$;Z;u(cpZ1*{!X#QBc56PRYv1%goBm&CA4*kj9vnyFx<e!NJmBU(r85yc`_bZEdF@ zAmh5a-++MIVq($7!@-4wp8x>N007q4)xCFi000000000000000EC2ui03ZM$000O7 zfO>+1goTEOh>41ejE#<kdjbL&kBn<EaTYNzm5Oo!HY08@Q=Nx*5-1!VC`Egwg$FPc zDl{}a76Ll3gL`Zsc_ddHAQCscdSN|u8eRYZ2^zUfyjo^md0Wq997G)_uuL&@C2!Bq zK?u23rY98(946-g6CO4SKAlwrV=WQ$&)l@A(<4hIA5o69nDA`FhI1vLC<uYWk&+N1 zJUBS#@Z1FtLkMtclp+8W1oJwc1EPWjDMo4}2;l%G<->Ddx`lYP=u<6#D$nuIz(SWI zEFA^}1Gr=fzyf({6gh@S$E;fb0W@inbw`OH0<0jyAcaV_tY`tu;Q-}9nL~DuW|c$B zfB{+;EgA@rVMxoncy#S%&Cx=|gM5Uj%<`AEF#ro5b_h^H$lZ~%j?uQsqv1gcLINnz z$V0lc>C>q5v`E0^fS@#T44@D}8^s49D{>FmJ;a6Y1;88FsF47UkqoaP7{SB5x%21H on;U^3X3&`#Kb|Dn&b_<$?>}ZBkL3i3`Sa-0r$^%&nWI1eJN~S2!T<mO literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif b/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif new file mode 100644 index 0000000000000000000000000000000000000000..f957e49a3dda34867982d54bdbbf46e5b6c11298 GIT binary patch literal 272 zcmZ?wbh9u|3}BFB_{_m@?Z&m_<m7ADuRePG@c#XKPoF(yU|{(F|Np7eCx8r0paT*D z>1AL!8o=VbdauRnv)25R3VTvA=Vh!~_a@6HSLb|**VT%3)4#v_zecXW!-k{V<F4V! zIl8k0rmt{V8@2w%nzGYx%kuASsPH-0bo#}XSygen@8347vD?r1?#G_G^Y4HEZ>Z-e zYiw<6@2F~4>g?_7FYjibFlA~}%e0v@C(W8Wb<Vtny^~m$E?d50<*L<d)~;K-Wc{Yi zTehy)xNYaI-8**g+rPp5z~Ljy_cEV2dFu3;v**rVxOnFHrK{Jj-(YSQzIpfF{S*3% Pa!;N<doHdZ$Y2csQd^57 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif b/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif new file mode 100644 index 0000000000000000000000000000000000000000..6baf64ad321ab3d35330f2aaae7504aa519644bd GIT binary patch literal 1195 zcmV;c1XTM+Nk%w1VRQg60K^&qo}rxY@9u7Ug;85$H#j%{|NpDH#%p|xwZqR~a)67K zo_>*_&)DBrWN@OfznH1FT4{BUps!wTd|YdJ0002^_xJYp^u)%)d3$)z&B_1&{{R30 z000000000000000A^8LW000^QEC2ui0CWH_000I5phk>jX`ZJhqHH^=Zk(=iEn-2g z?|i>wBOI?nEE<hGAVKJBHkC}LRHw8|uQ|)eIy`!bJS~BXm5Ryb<~eQN_P*b+o2{PH zd+R&iu7i8!V@(u;go93bJ%&1pK8SicjyXhygMT}bi<FFefj)#epLLy&kbIIAnwF)b zJer$;XswiOtfZKeMii=9ri+P(y*q_dViy3%$j7b}$;}rd#?8tZ8I;n<&jiuZ%+1}` z+1uBJ*U91K%jE#)<J1(@)#~ir^yTy1*7DHkuKL>ih2q)UH?AHyg7~@-@+VH6!(;c_ zxnl@0-@$+5z5y6S@uA0c2rFuI7V_gjj3zt(raakjrMZ$WvB8W9atTdoP;NHMsS_E` zo&bQ*s1XAOQ5i;$x=5;&g^B@Cqe`7hmFm-~ShGUCs<o?Bu3o)rfXbk(*|TWVo|US$ zty>0c-^w)`cdp#12=eOP%eQY|sD1+r)(d#BVZMbAD~4*IvE#>(BS&T|xw7TPlrL+3 zoO$zRs18Dl9!<J*Y0#!qs}7CYbb;5fU$1UmTDEB0si8jD&AYen-@kPOe-Qii@ZQ3K z7l(cPLGs_si5ou-HG=i)*t2WbUVVFn<=(M(-@g2H_z2_47e9}Fz=HSi<IA5vA1eL# z1>)zw58wX%{rd5@fPehOCg6KeHK5@Cf($n3po0lM*gyda7AK*C5k5#^gBwbip@gwr zxFA#zlxU)f<rQ$^iV%><Vu>n3pyG@#n&{$-F`k&?i#Os}T#YskFu{;S5}9I=NKOD% zl13IcK><t>xnz`3B3WgWQ!)wLkXuHn<Ny+cDW;eyj%lU@P@Q>Z0c5HvW}0r6=_Z<B z#>pm`ce)8x0(|!A=bwNAx@Vw%7Dp(bgC44=paU%GsGm?BAnBx(R%)rGkzT6lrjlmL z>8F%>3M!~kDPZcUsHUnas#2}$>Z=O03hS(=%1Z03TZN@7Sh{A#Yp+%P3hY!W2w?27 z$R?|-vc)dz?6bx;3+=SXN=q&OwHg>}*IdYMD_6JPx&>~yY8|WCxyGKWSi0&O#%{ZU z8SB}+^3J<iz4l&)Z@!foyV}2{`3vyC4hZa8d8-**TLGitW}30hMf@AY!!0K<#mbe} z9LCU17u|5ivL`ZjA$tcNdnK!PvUe$~3>(S<94K>q#ugahfi?d(AAt1bTp(;R8!O__ z4hjuog&|&Ow1y6L_~6nY!bY^QK&A*J1XR};BaJ(<m^F?pcD>@)KE`%6)&h8Wq?g93 z?c|kAwoPS{a3?9ZmalP{H`@ZtDW{vp&e>*|d8!$>oy!S+xSFqx+4!8sJ}P<SiyC?; z<&rOodFGc3FzV;Vem-g_=%Rm0dg+@Udn>KTu0Ct)uD=R<?5jq5?d{gy{%r2LFUx!H J$!ZV+06W;kU)}%! literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif b/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif new file mode 100644 index 0000000000000000000000000000000000000000..20acbbf7aec8a3fccbffbbb894f973241a045732 GIT binary patch literal 907 zcmV;619bdHNk%v~VITk?0QPwR_mwyIk1Co}49|EKqh~0+ri!6j6Z*7U`lU1e^XU7^ zod5p+om&^t%*Cs9J)E4I)z#6vZX5cfOQfZw_J9bzzPy@aE7*uE$H2Mzs7<(K4$*}x z?4CLJokRMqQrd$ZlS~7knw0jXHTSe!o0*mDqeS+82K9OY`oWCJ%E<SVGxdH6#m2<> znI-zTdit_%`kX1XwzT=HMfsK@_J<qznmqP{6RobS&d<&GkQ=;e5vr@I!NS1#uvD?K zu=a@`xw*Li`}gaYEc&1=_lObsp+(MuEv0u!+?7DFgH-pHIK#xkyS%!zjA6^n%AsE! z($2`PeM!&I&ehh`{`c{}z`oGY&-j-*v$V3Xv9Gtdw(F`?#KptR!nLccs?dfq`Kw{c z!@HGxUzUAg-HIdp*R%V$UiqnAsh^Usu&>>ZF~`Wpm{14%#gX`?RrPxW_?tKTt2vcW z2>QE!xVg8it*iEY1oe3U*4Nd~$-n>r00000000000000000000EC2ui03ZM$000O7 zfOvv~gm?`F4o?Cg0#6PF4TX}EcwG(x5lCAjW+Pij5dscfl$1#VUuGE{0IjYW2VVk7 z5T%0+1Q8<=O0K@HMI#Xek);g`Mh92F%&$fa#ghcdz0KAc8w9nIO}f?A*AY#Uc?QbO z3RLO});$J!g;5v0=nMAj%^ep}gir!z-+rO6w*Un=4+5YJDiFZ~I2Q!xfRmu3z#s=| zihz4T@CCRUY8(uDQlbX9GX%kWEb(N}zkt6a5bW@S#*YBZWC(Bx@FPJRcY+3`q2d)A zmpx#*`mrL2J)uzF{Ai_fBnOke0ssw~U_pYYQE6~!DagSGIIXnWiQ2(U2e47_$%qtG zKtl_-P`Bc}lcVA-0SHd)Rj{DU-aA7Q5{fb)$6lukR^TP_fghoAf$`3v(q`|FciePj zJ`5Lzj&afk40%I3YKsBdC>>Kxp>@z91EARoLqLOw8Eg0E5TStp1}jr0SxLdA!VxyA zTM#iJc<2lS0|XplvLpqLZT(nO0fGgM1vVN!2oVuSgpdy!*jPa0LraD3QY1MMPyWV) z5M!Jt2O|PlAVvri?2tta_j#uua~06xgMa@$K*EI<Cg{b2+^zAQa{KWRVGI-2vBQZQ hrh$chRdC^;Ef7e-+!7*2$i$8J@xX!;$Vn0i06V<1vibl3 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif b/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif new file mode 100644 index 0000000000000000000000000000000000000000..d5de1cc236c9e44b2bcce92b4444f9cc7c43c551 GIT binary patch literal 909 zcmd6k{WFts0KlK`HhVEz-VP%)t%%6w2P$qT_Vhz_x6{iH74Ayc4<%REb(eY?v$8WW z4khQU($$h#iW<+#%Or2nwaUu~d&TU9y;A)beg1;a=RRq0YFvEgF31;JgQ3skzaR)o z*dHe!>EGPkB#}sYrS(hdInBZpyW+|1vW7c?#%0ZK)9R8@uU$7A%*K`47Ku)&&@N8% zYK4`}Z?(#q)nzsJ;d4P#TS@)v!Eck-?^kOUr>&MXooZI6QXu6`cgvfGK6NyRP`l0I zbUL24e{$GuZ=Tk)b;~w3oNZk)lVQ14(q~xFwmqvbt?JB%Wl>kZ(_t4$`g=#dTP<eG zn(;&5sLi_G*)#n1;}>!FfZc90uIhs65nZyc!gn8KV?V^`fOK%epx0W~O)FaE->(0k z?N*!%1i?_`Kh=Lv7=%p(X0u)L3pj<K5DsTDu^52khZi$LF^n|#8g~#+t*1VAPh&Jt z;{m^<RKPEL31U3oc!EfBC%N4-2H@XEzTiJ-<?~>dSo+ZClpSM3^jOZ=j+CO8eJz!t zq0G`~;ye*V;nnyBVl=9W>Jj!cd0-F0N&tsQ8zkEnF;O24JZ?^&qO;nwIHcqN+QW<Y z!shUY;r5QKURM^_MoCT#JKn?|aHR#S!g55(9t8oJk|Q1pDd&+dMvtOi*kLjSW9mV% zI}>1R89rxky}AI}=gmx4Tw`N1SlNC{7h0s;mS9Zt)}#|SIi=REJiRqNljiTH@k0@h zx>r*jSI^6*BI>TpNc;poVS4>2-YcJQ#?7&Nd)eix@@huXX@A74D!h?VgENw#pGCd% zsxdBiJjhjk58aQsL`ifN^D`QSq1}1pNdyf@Mne4A*(&$hR50t$mZ#==bMuuaZyc{W z3OccYpqV9ab*SFuDkp>y%A>aq7N>y#HQJSeP+30Wl?>dA3F_dI^EEnyd3A<t%9c`4 zqTn1Y2B`}nW^oi5L^4~?0~8S_=;VDx<1r|~+k2GZV$M;70My493y4x_QDBV>IUAW9 QatMOy3rC81I1F^)55?|uDF6Tf literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif b/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif new file mode 100644 index 0000000000000000000000000000000000000000..c2a2ad454db194e428a7b9da40f62d5376a17428 GIT binary patch literal 769 zcmb7?=`WiB0LI^D)(HC`v6*aD4AW#LGRb0Oi$t<fW)_L~Kx~mM4a>H~CP=nb%N%8n zy02ceuewTUUDeW|RaMp*TlLV6R$o=rQOY{@AME+?`}QQiCwU%4Jq)?`{5B8=ECT1T z+wH!7{<!M4+^W_x3X9mvt_8U*Jv?fkfX)#zho;^a)qkj<V5?d`5osSQsRa$~gqAMJ z;>zji$)-UA>D9({)xO1SJGLHK54Mat(}s4_unMiKjB85EHng*~!Ddt+?(c5uHG4ZI zsc>jP#5Y6w6Wj5!Y<hs+bU!o%27{ex{L}eAcpo{y03Z+uIIo>=0^oK*&D+R;Yh@ze z7vfi;q<Qcix+@`mxieE@%Hh|uvSI=oWth?&>FW{owiOfGqcB@XkwUZ0j?Km4{qjE- z6c!Z|O1!?5l~+^}tE#<g>*^aCo0?lZ$rLKBwT;dI+nLO(UEMvb-ad9elEWPw8Xg(t zx$y<#6T+{PQ@$ecjAT|iC%dxnP5yoH$I`OLFU5*drPiz>bidcu^@a^2v}rP3-`?4^ z?Cl>M-Z(n8ot*x$0~Z|;ku35!-qAHSQN*GM3tW8AN#VWJNrHQD+6qXfO_zB^6eFVU z<cf)?cxIBg&kt7{lseNC#imOygk%_3#B7GlPJ-i{Jkb5%0xi-Rl|0kmE@#Bi&~@km z=3+-8JFQeO(6Q9>OjzupAb0*`W8}<a38zcJed8@^j^=hNN3twNrKHx3=VLE8BVz_x ztHMH8|4hMPuWq{BC%Pqu+_xsF3r<(fW@Gg-as&bSc({K<4n7S|lnxI-ORQ80JbZ*> zQVeE5Djt<<RtxaXp0SAh9i51HD`jqU$fBR8MUx&V^Y)=-cDj0w7e+8^gapqgW1~l| z26;z{Y>a0+Owme6r2OGio7DoTWqkhGKj0`0*1-*<$#uL5YH*kC8Z>wpCvYO~asp;G r-~A;>$wp)vkltB=c_?k6Zw*FUgrbAm;sB08O9+}m=}H3OFd*zN8L+JA literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif b/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif new file mode 100644 index 0000000000000000000000000000000000000000..0b4cc3682a1c62b3583d83ad83b84fce14461ec3 GIT binary patch literal 84 zcmZ?wbh9u|<YM4s_{6~Q{`GSP28ON6=G?h*=KufyKsE&EfGCg}2WCYL24P2Ujb{oI gR`0dgdh|+Jsp#~nk2Ra-N!C4)I;{2Ajg!F|0C)f#UH||9 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css b/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css new file mode 100644 index 0000000..a50d4fc --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css @@ -0,0 +1,90 @@ +/* Clearlooks 2 */ + +/* Reset */ +.clearlooks2, .clearlooks2 div, .clearlooks2 span, .clearlooks2 a {vertical-align:baseline; text-align:left; position:absolute; border:0; padding:0; margin:0; background:transparent; font-family:Arial,Verdana; font-size:11px; color:#000; text-decoration:none; font-weight:normal; width:auto; height:auto; overflow:hidden; display:block} + +/* General */ +.clearlooks2 {position:absolute; direction:ltr} +.clearlooks2 .mceWrapper {position:static} +.mceEventBlocker {position:fixed; left:0; top:0; background:url(img/horizontal.gif) no-repeat 0 -75px; width:100%; height:100%} +.clearlooks2 .mcePlaceHolder {border:1px solid #000; background:#888; top:0; left:0; opacity:0.5; -ms-filter:'alpha(opacity=50)'; filter:alpha(opacity=50)} +.clearlooks2_modalBlocker {position:fixed; left:0; top:0; width:100%; height:100%; background:#FFF; opacity:0.6; -ms-filter:'alpha(opacity=60)'; filter:alpha(opacity=60); display:none} + +/* Top */ +.clearlooks2 .mceTop, .clearlooks2 .mceTop div {top:0; width:100%; height:23px} +.clearlooks2 .mceTop .mceLeft {width:6px; background:url(img/corners.gif)} +.clearlooks2 .mceTop .mceCenter {right:6px; width:100%; height:23px; background:url(img/horizontal.gif) 12px 0; clip:rect(auto auto auto 12px)} +.clearlooks2 .mceTop .mceRight {right:0; width:6px; height:23px; background:url(img/corners.gif) -12px 0} +.clearlooks2 .mceTop span {width:100%; text-align:center; vertical-align:middle; line-height:23px; font-weight:bold} +.clearlooks2 .mceFocus .mceTop .mceLeft {background:url(img/corners.gif) -6px 0} +.clearlooks2 .mceFocus .mceTop .mceCenter {background:url(img/horizontal.gif) 0 -23px} +.clearlooks2 .mceFocus .mceTop .mceRight {background:url(img/corners.gif) -18px 0} +.clearlooks2 .mceFocus .mceTop span {color:#FFF} + +/* Middle */ +.clearlooks2 .mceMiddle, .clearlooks2 .mceMiddle div {top:0} +.clearlooks2 .mceMiddle {width:100%; height:100%; clip:rect(23px auto auto auto)} +.clearlooks2 .mceMiddle .mceLeft {left:0; width:5px; height:100%; background:url(img/vertical.gif) -5px 0} +.clearlooks2 .mceMiddle span {top:23px; left:5px; width:100%; height:100%; background:#FFF} +.clearlooks2 .mceMiddle .mceRight {right:0; width:5px; height:100%; background:url(img/vertical.gif)} + +/* Bottom */ +.clearlooks2 .mceBottom, .clearlooks2 .mceBottom div {height:6px} +.clearlooks2 .mceBottom {left:0; bottom:0; width:100%} +.clearlooks2 .mceBottom div {top:0} +.clearlooks2 .mceBottom .mceLeft {left:0; width:5px; background:url(img/corners.gif) -34px -6px} +.clearlooks2 .mceBottom .mceCenter {left:5px; width:100%; background:url(img/horizontal.gif) 0 -46px} +.clearlooks2 .mceBottom .mceRight {right:0; width:5px; background: url(img/corners.gif) -34px 0} +.clearlooks2 .mceBottom span {display:none} +.clearlooks2 .mceStatusbar .mceBottom, .clearlooks2 .mceStatusbar .mceBottom div {height:23px} +.clearlooks2 .mceStatusbar .mceBottom .mceLeft {background:url(img/corners.gif) -29px 0} +.clearlooks2 .mceStatusbar .mceBottom .mceCenter {background:url(img/horizontal.gif) 0 -52px} +.clearlooks2 .mceStatusbar .mceBottom .mceRight {background:url(img/corners.gif) -24px 0} +.clearlooks2 .mceStatusbar .mceBottom span {display:block; left:7px; font-family:Arial, Verdana; font-size:11px; line-height:23px} + +/* Actions */ +.clearlooks2 a {width:29px; height:16px; top:3px;} +.clearlooks2 .mceClose {right:6px; background:url(img/buttons.gif) -87px 0} +.clearlooks2 .mceMin {display:none; right:68px; background:url(img/buttons.gif) 0 0} +.clearlooks2 .mceMed {display:none; right:37px; background:url(img/buttons.gif) -29px 0} +.clearlooks2 .mceMax {display:none; right:37px; background:url(img/buttons.gif) -58px 0} +.clearlooks2 .mceMove {display:none;width:100%;cursor:move;background:url(img/corners.gif) no-repeat -100px -100px} +.clearlooks2 .mceMovable .mceMove {display:block} +.clearlooks2 .mceFocus .mceClose {right:6px; background:url(img/buttons.gif) -87px -16px} +.clearlooks2 .mceFocus .mceMin {right:68px; background:url(img/buttons.gif) 0 -16px} +.clearlooks2 .mceFocus .mceMed {right:37px; background:url(img/buttons.gif) -29px -16px} +.clearlooks2 .mceFocus .mceMax {right:37px; background:url(img/buttons.gif) -58px -16px} +.clearlooks2 .mceFocus .mceClose:hover {right:6px; background:url(img/buttons.gif) -87px -32px} +.clearlooks2 .mceFocus .mceClose:hover {right:6px; background:url(img/buttons.gif) -87px -32px} +.clearlooks2 .mceFocus .mceMin:hover {right:68px; background:url(img/buttons.gif) 0 -32px} +.clearlooks2 .mceFocus .mceMed:hover {right:37px; background:url(img/buttons.gif) -29px -32px} +.clearlooks2 .mceFocus .mceMax:hover {right:37px; background:url(img/buttons.gif) -58px -32px} + +/* Resize */ +.clearlooks2 .mceResize {top:auto; left:auto; display:none; width:5px; height:5px; background:url(img/horizontal.gif) no-repeat 0 -75px} +.clearlooks2 .mceResizable .mceResize {display:block} +.clearlooks2 .mceResizable .mceMin, .clearlooks2 .mceMax {display:none} +.clearlooks2 .mceMinimizable .mceMin {display:block} +.clearlooks2 .mceMaximizable .mceMax {display:block} +.clearlooks2 .mceMaximized .mceMed {display:block} +.clearlooks2 .mceMaximized .mceMax {display:none} +.clearlooks2 a.mceResizeN {top:0; left:0; width:100%; cursor:n-resize} +.clearlooks2 a.mceResizeNW {top:0; left:0; cursor:nw-resize} +.clearlooks2 a.mceResizeNE {top:0; right:0; cursor:ne-resize} +.clearlooks2 a.mceResizeW {top:0; left:0; height:100%; cursor:w-resize;} +.clearlooks2 a.mceResizeE {top:0; right:0; height:100%; cursor:e-resize} +.clearlooks2 a.mceResizeS {bottom:0; left:0; width:100%; cursor:s-resize} +.clearlooks2 a.mceResizeSW {bottom:0; left:0; cursor:sw-resize} +.clearlooks2 a.mceResizeSE {bottom:0; right:0; cursor:se-resize} + +/* Alert/Confirm */ +.clearlooks2 .mceButton {font-weight:bold; bottom:10px; width:80px; height:30px; background:url(img/button.gif); line-height:30px; vertical-align:middle; text-align:center; outline:0} +.clearlooks2 .mceMiddle .mceIcon {left:15px; top:35px; width:32px; height:32px} +.clearlooks2 .mceAlert .mceMiddle span, .clearlooks2 .mceConfirm .mceMiddle span {background:transparent;left:60px; top:35px; width:320px; height:50px; font-weight:bold; overflow:auto; white-space:normal} +.clearlooks2 a:hover {font-weight:bold;} +.clearlooks2 .mceAlert .mceMiddle, .clearlooks2 .mceConfirm .mceMiddle {background:#D6D7D5} +.clearlooks2 .mceAlert .mceOk {left:50%; top:auto; margin-left: -40px} +.clearlooks2 .mceAlert .mceIcon {background:url(img/alert.gif)} +.clearlooks2 .mceConfirm .mceOk {left:50%; top:auto; margin-left: -90px} +.clearlooks2 .mceConfirm .mceCancel {left:50%; top:auto} +.clearlooks2 .mceConfirm .mceIcon {background:url(img/confirm.gif)} diff --git a/src/core/static/js/tiny_mce/plugins/inlinepopups/template.htm b/src/core/static/js/tiny_mce/plugins/inlinepopups/template.htm new file mode 100644 index 0000000..f9ec642 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/inlinepopups/template.htm @@ -0,0 +1,387 @@ +<!-- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> --> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Template for dialogs</title> +<link rel="stylesheet" type="text/css" href="skins/clearlooks2/window.css" /> +</head> +<body> + +<div class="mceEditor"> + <div class="clearlooks2" style="width:400px; height:100px; left:10px;"> + <div class="mceWrapper"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Blured</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:420px;"> + <div class="mceWrapper mceMovable mceFocus"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Focused</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:120px;"> + <div class="mceWrapper mceMovable mceFocus mceStatusbar"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:120px;"> + <div class="mceWrapper mceMovable mceFocus mceStatusbar mceResizable"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar, Resizable</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:230px;"> + <div class="mceWrapper mceMovable mceFocus mceResizable mceMaximizable"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Resizable, Maximizable</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:230px;"> + <div class="mceWrapper mceMovable mceStatusbar mceResizable mceMaximizable"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Blurred, Maximizable, Statusbar, Resizable</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:340px;"> + <div class="mceWrapper mceMovable mceFocus mceResizable mceMaximized mceMinimizable mceMaximizable"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Maximized, Maximizable, Minimizable</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:340px;"> + <div class="mceWrapper mceMovable mceStatusbar mceResizable mceMaximized mceMinimizable mceMaximizable"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Blured</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:130px; left:10px; top:450px;"> + <div class="mceWrapper mceMovable mceFocus mceModal mceAlert"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Alert</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span> + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + </span> + <div class="mceRight"></div> + <div class="mceIcon"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceButton mceOk" href="#">Ok</a> + <a class="mceClose" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:130px; left:420px; top:450px;"> + <div class="mceWrapper mceMovable mceFocus mceModal mceConfirm"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Confirm</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span> + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + </span> + <div class="mceRight"></div> + <div class="mceIcon"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceButton mceOk" href="#">Ok</a> + <a class="mceButton mceCancel" href="#">Cancel</a> + <a class="mceClose" href="#"></a> + </div> + </div> +</div> + +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/insertdatetime/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/insertdatetime/editor_plugin.js new file mode 100644 index 0000000..938ce6b --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/insertdatetime/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.InsertDateTime",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceInsertDate",function(){var d=c._getDateTime(new Date(),a.getParam("plugin_insertdate_dateFormat",a.getLang("insertdatetime.date_fmt")));a.execCommand("mceInsertContent",false,d)});a.addCommand("mceInsertTime",function(){var d=c._getDateTime(new Date(),a.getParam("plugin_insertdate_timeFormat",a.getLang("insertdatetime.time_fmt")));a.execCommand("mceInsertContent",false,d)});a.addButton("insertdate",{title:"insertdatetime.insertdate_desc",cmd:"mceInsertDate"});a.addButton("inserttime",{title:"insertdatetime.inserttime_desc",cmd:"mceInsertTime"})},getInfo:function(){return{longname:"Insert date/time",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/insertdatetime",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_getDateTime:function(e,a){var c=this.editor;function b(g,d){g=""+g;if(g.length<d){for(var f=0;f<(d-g.length);f++){g="0"+g}}return g}a=a.replace("%D","%m/%d/%y");a=a.replace("%r","%I:%M:%S %p");a=a.replace("%Y",""+e.getFullYear());a=a.replace("%y",""+e.getYear());a=a.replace("%m",b(e.getMonth()+1,2));a=a.replace("%d",b(e.getDate(),2));a=a.replace("%H",""+b(e.getHours(),2));a=a.replace("%M",""+b(e.getMinutes(),2));a=a.replace("%S",""+b(e.getSeconds(),2));a=a.replace("%I",""+((e.getHours()+11)%12+1));a=a.replace("%p",""+(e.getHours()<12?"AM":"PM"));a=a.replace("%B",""+c.getLang("insertdatetime.months_long").split(",")[e.getMonth()]);a=a.replace("%b",""+c.getLang("insertdatetime.months_short").split(",")[e.getMonth()]);a=a.replace("%A",""+c.getLang("insertdatetime.day_long").split(",")[e.getDay()]);a=a.replace("%a",""+c.getLang("insertdatetime.day_short").split(",")[e.getDay()]);a=a.replace("%%","%");return a}});tinymce.PluginManager.add("insertdatetime",tinymce.plugins.InsertDateTime)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/insertdatetime/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/insertdatetime/editor_plugin_src.js new file mode 100644 index 0000000..181c791 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/insertdatetime/editor_plugin_src.js @@ -0,0 +1,83 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.InsertDateTime', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + ed.addCommand('mceInsertDate', function() { + var str = t._getDateTime(new Date(), ed.getParam("plugin_insertdate_dateFormat", ed.getLang('insertdatetime.date_fmt'))); + + ed.execCommand('mceInsertContent', false, str); + }); + + ed.addCommand('mceInsertTime', function() { + var str = t._getDateTime(new Date(), ed.getParam("plugin_insertdate_timeFormat", ed.getLang('insertdatetime.time_fmt'))); + + ed.execCommand('mceInsertContent', false, str); + }); + + ed.addButton('insertdate', {title : 'insertdatetime.insertdate_desc', cmd : 'mceInsertDate'}); + ed.addButton('inserttime', {title : 'insertdatetime.inserttime_desc', cmd : 'mceInsertTime'}); + }, + + getInfo : function() { + return { + longname : 'Insert date/time', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/insertdatetime', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + _getDateTime : function(d, fmt) { + var ed = this.editor; + + function addZeros(value, len) { + value = "" + value; + + if (value.length < len) { + for (var i=0; i<(len-value.length); i++) + value = "0" + value; + } + + return value; + }; + + fmt = fmt.replace("%D", "%m/%d/%y"); + fmt = fmt.replace("%r", "%I:%M:%S %p"); + fmt = fmt.replace("%Y", "" + d.getFullYear()); + fmt = fmt.replace("%y", "" + d.getYear()); + fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2)); + fmt = fmt.replace("%d", addZeros(d.getDate(), 2)); + fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2)); + fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2)); + fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2)); + fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1)); + fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM")); + fmt = fmt.replace("%B", "" + ed.getLang("insertdatetime.months_long").split(',')[d.getMonth()]); + fmt = fmt.replace("%b", "" + ed.getLang("insertdatetime.months_short").split(',')[d.getMonth()]); + fmt = fmt.replace("%A", "" + ed.getLang("insertdatetime.day_long").split(',')[d.getDay()]); + fmt = fmt.replace("%a", "" + ed.getLang("insertdatetime.day_short").split(',')[d.getDay()]); + fmt = fmt.replace("%%", "%"); + + return fmt; + } + }); + + // Register plugin + tinymce.PluginManager.add('insertdatetime', tinymce.plugins.InsertDateTime); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/layer/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/layer/editor_plugin.js new file mode 100644 index 0000000..ca3857a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/layer/editor_plugin.js @@ -0,0 +1 @@ +(function(){function a(b){do{if(b.className&&b.className.indexOf("mceItemLayer")!=-1){return b}}while(b=b.parentNode)}tinymce.create("tinymce.plugins.Layer",{init:function(b,c){var d=this;d.editor=b;b.addCommand("mceInsertLayer",d._insertLayer,d);b.addCommand("mceMoveForward",function(){d._move(1)});b.addCommand("mceMoveBackward",function(){d._move(-1)});b.addCommand("mceMakeAbsolute",function(){d._toggleAbsolute()});b.addButton("moveforward",{title:"layer.forward_desc",cmd:"mceMoveForward"});b.addButton("movebackward",{title:"layer.backward_desc",cmd:"mceMoveBackward"});b.addButton("absolute",{title:"layer.absolute_desc",cmd:"mceMakeAbsolute"});b.addButton("insertlayer",{title:"layer.insertlayer_desc",cmd:"mceInsertLayer"});b.onInit.add(function(){var e=b.dom;if(tinymce.isIE){b.getDoc().execCommand("2D-Position",false,true)}});b.onMouseUp.add(function(f,h){var g=a(h.target);if(g){f.dom.setAttrib(g,"data-mce-style","")}});b.onMouseDown.add(function(f,j){var h=j.target,i=f.getDoc(),g;if(tinymce.isGecko){if(a(h)){if(i.designMode!=="on"){i.designMode="on";h=i.body;g=h.parentNode;g.removeChild(h);g.appendChild(h)}}else{if(i.designMode=="on"){i.designMode="off"}}}});b.onNodeChange.add(d._nodeChange,d);b.onVisualAid.add(d._visualAid,d)},getInfo:function(){return{longname:"Layer",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_nodeChange:function(c,b,f){var d,e;d=this._getParentLayer(f);e=c.dom.getParent(f,"DIV,P,IMG");if(!e){b.setDisabled("absolute",1);b.setDisabled("moveforward",1);b.setDisabled("movebackward",1)}else{b.setDisabled("absolute",0);b.setDisabled("moveforward",!d);b.setDisabled("movebackward",!d);b.setActive("absolute",d&&d.style.position.toLowerCase()=="absolute")}},_visualAid:function(b,d,c){var f=b.dom;tinymce.each(f.select("div,p",d),function(g){if(/^(absolute|relative|fixed)$/i.test(g.style.position)){if(c){f.addClass(g,"mceItemVisualAid")}else{f.removeClass(g,"mceItemVisualAid")}f.addClass(g,"mceItemLayer")}})},_move:function(j){var c=this.editor,g,h=[],f=this._getParentLayer(c.selection.getNode()),e=-1,k=-1,b;b=[];tinymce.walk(c.getBody(),function(d){if(d.nodeType==1&&/^(absolute|relative|static)$/i.test(d.style.position)){b.push(d)}},"childNodes");for(g=0;g<b.length;g++){h[g]=b[g].style.zIndex?parseInt(b[g].style.zIndex):0;if(e<0&&b[g]==f){e=g}}if(j<0){for(g=0;g<h.length;g++){if(h[g]<h[e]){k=g;break}}if(k>-1){b[e].style.zIndex=h[k];b[k].style.zIndex=h[e]}else{if(h[e]>0){b[e].style.zIndex=h[e]-1}}}else{for(g=0;g<h.length;g++){if(h[g]>h[e]){k=g;break}}if(k>-1){b[e].style.zIndex=h[k];b[k].style.zIndex=h[e]}else{b[e].style.zIndex=h[e]+1}}c.execCommand("mceRepaint")},_getParentLayer:function(b){return this.editor.dom.getParent(b,function(c){return c.nodeType==1&&/^(absolute|relative|static)$/i.test(c.style.position)})},_insertLayer:function(){var c=this.editor,e=c.dom,d=e.getPos(e.getParent(c.selection.getNode(),"*")),b=c.getBody();c.dom.add(b,"div",{style:{position:"absolute",left:d.x,top:(d.y>20?d.y:20),width:100,height:100},"class":"mceItemVisualAid mceItemLayer"},c.selection.getContent()||c.getLang("layer.content"));if(tinymce.isIE){e.setHTML(b,b.innerHTML)}},_toggleAbsolute:function(){var b=this.editor,c=this._getParentLayer(b.selection.getNode());if(!c){c=b.dom.getParent(b.selection.getNode(),"DIV,P,IMG")}if(c){if(c.style.position.toLowerCase()=="absolute"){b.dom.setStyles(c,{position:"",left:"",top:"",width:"",height:""});b.dom.removeClass(c,"mceItemVisualAid");b.dom.removeClass(c,"mceItemLayer")}else{if(c.style.left==""){c.style.left=20+"px"}if(c.style.top==""){c.style.top=20+"px"}if(c.style.width==""){c.style.width=c.width?(c.width+"px"):"100px"}if(c.style.height==""){c.style.height=c.height?(c.height+"px"):"100px"}c.style.position="absolute";b.dom.setAttrib(c,"data-mce-style","");b.addVisual(b.getBody())}b.execCommand("mceRepaint");b.nodeChanged()}}});tinymce.PluginManager.add("layer",tinymce.plugins.Layer)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/layer/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/layer/editor_plugin_src.js new file mode 100644 index 0000000..daed280 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/layer/editor_plugin_src.js @@ -0,0 +1,262 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + function findParentLayer(node) { + do { + if (node.className && node.className.indexOf('mceItemLayer') != -1) { + return node; + } + } while (node = node.parentNode); + }; + + tinymce.create('tinymce.plugins.Layer', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceInsertLayer', t._insertLayer, t); + + ed.addCommand('mceMoveForward', function() { + t._move(1); + }); + + ed.addCommand('mceMoveBackward', function() { + t._move(-1); + }); + + ed.addCommand('mceMakeAbsolute', function() { + t._toggleAbsolute(); + }); + + // Register buttons + ed.addButton('moveforward', {title : 'layer.forward_desc', cmd : 'mceMoveForward'}); + ed.addButton('movebackward', {title : 'layer.backward_desc', cmd : 'mceMoveBackward'}); + ed.addButton('absolute', {title : 'layer.absolute_desc', cmd : 'mceMakeAbsolute'}); + ed.addButton('insertlayer', {title : 'layer.insertlayer_desc', cmd : 'mceInsertLayer'}); + + ed.onInit.add(function() { + var dom = ed.dom; + + if (tinymce.isIE) + ed.getDoc().execCommand('2D-Position', false, true); + }); + + // Remove serialized styles when selecting a layer since it might be changed by a drag operation + ed.onMouseUp.add(function(ed, e) { + var layer = findParentLayer(e.target); + + if (layer) { + ed.dom.setAttrib(layer, 'data-mce-style', ''); + } + }); + + // Fixes edit focus issues with layers on Gecko + // This will enable designMode while inside a layer and disable it when outside + ed.onMouseDown.add(function(ed, e) { + var node = e.target, doc = ed.getDoc(), parent; + + if (tinymce.isGecko) { + if (findParentLayer(node)) { + if (doc.designMode !== 'on') { + doc.designMode = 'on'; + + // Repaint caret + node = doc.body; + parent = node.parentNode; + parent.removeChild(node); + parent.appendChild(node); + } + } else if (doc.designMode == 'on') { + doc.designMode = 'off'; + } + } + }); + + ed.onNodeChange.add(t._nodeChange, t); + ed.onVisualAid.add(t._visualAid, t); + }, + + getInfo : function() { + return { + longname : 'Layer', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + _nodeChange : function(ed, cm, n) { + var le, p; + + le = this._getParentLayer(n); + p = ed.dom.getParent(n, 'DIV,P,IMG'); + + if (!p) { + cm.setDisabled('absolute', 1); + cm.setDisabled('moveforward', 1); + cm.setDisabled('movebackward', 1); + } else { + cm.setDisabled('absolute', 0); + cm.setDisabled('moveforward', !le); + cm.setDisabled('movebackward', !le); + cm.setActive('absolute', le && le.style.position.toLowerCase() == "absolute"); + } + }, + + // Private methods + + _visualAid : function(ed, e, s) { + var dom = ed.dom; + + tinymce.each(dom.select('div,p', e), function(e) { + if (/^(absolute|relative|fixed)$/i.test(e.style.position)) { + if (s) + dom.addClass(e, 'mceItemVisualAid'); + else + dom.removeClass(e, 'mceItemVisualAid'); + + dom.addClass(e, 'mceItemLayer'); + } + }); + }, + + _move : function(d) { + var ed = this.editor, i, z = [], le = this._getParentLayer(ed.selection.getNode()), ci = -1, fi = -1, nl; + + nl = []; + tinymce.walk(ed.getBody(), function(n) { + if (n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position)) + nl.push(n); + }, 'childNodes'); + + // Find z-indexes + for (i=0; i<nl.length; i++) { + z[i] = nl[i].style.zIndex ? parseInt(nl[i].style.zIndex) : 0; + + if (ci < 0 && nl[i] == le) + ci = i; + } + + if (d < 0) { + // Move back + + // Try find a lower one + for (i=0; i<z.length; i++) { + if (z[i] < z[ci]) { + fi = i; + break; + } + } + + if (fi > -1) { + nl[ci].style.zIndex = z[fi]; + nl[fi].style.zIndex = z[ci]; + } else { + if (z[ci] > 0) + nl[ci].style.zIndex = z[ci] - 1; + } + } else { + // Move forward + + // Try find a higher one + for (i=0; i<z.length; i++) { + if (z[i] > z[ci]) { + fi = i; + break; + } + } + + if (fi > -1) { + nl[ci].style.zIndex = z[fi]; + nl[fi].style.zIndex = z[ci]; + } else + nl[ci].style.zIndex = z[ci] + 1; + } + + ed.execCommand('mceRepaint'); + }, + + _getParentLayer : function(n) { + return this.editor.dom.getParent(n, function(n) { + return n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position); + }); + }, + + _insertLayer : function() { + var ed = this.editor, dom = ed.dom, p = dom.getPos(dom.getParent(ed.selection.getNode(), '*')), body = ed.getBody(); + + ed.dom.add(body, 'div', { + style : { + position : 'absolute', + left : p.x, + top : (p.y > 20 ? p.y : 20), + width : 100, + height : 100 + }, + 'class' : 'mceItemVisualAid mceItemLayer' + }, ed.selection.getContent() || ed.getLang('layer.content')); + + // Workaround for IE where it messes up the JS engine if you insert a layer on IE 6,7 + if (tinymce.isIE) + dom.setHTML(body, body.innerHTML); + }, + + _toggleAbsolute : function() { + var ed = this.editor, le = this._getParentLayer(ed.selection.getNode()); + + if (!le) + le = ed.dom.getParent(ed.selection.getNode(), 'DIV,P,IMG'); + + if (le) { + if (le.style.position.toLowerCase() == "absolute") { + ed.dom.setStyles(le, { + position : '', + left : '', + top : '', + width : '', + height : '' + }); + + ed.dom.removeClass(le, 'mceItemVisualAid'); + ed.dom.removeClass(le, 'mceItemLayer'); + } else { + if (le.style.left == "") + le.style.left = 20 + 'px'; + + if (le.style.top == "") + le.style.top = 20 + 'px'; + + if (le.style.width == "") + le.style.width = le.width ? (le.width + 'px') : '100px'; + + if (le.style.height == "") + le.style.height = le.height ? (le.height + 'px') : '100px'; + + le.style.position = "absolute"; + + ed.dom.setAttrib(le, 'data-mce-style', ''); + ed.addVisual(ed.getBody()); + } + + ed.execCommand('mceRepaint'); + ed.nodeChanged(); + } + } + }); + + // Register plugin + tinymce.PluginManager.add('layer', tinymce.plugins.Layer); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/legacyoutput/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/legacyoutput/editor_plugin.js new file mode 100644 index 0000000..b3a4ce3 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/legacyoutput/editor_plugin.js @@ -0,0 +1 @@ +(function(a){a.onAddEditor.addToTop(function(c,b){b.settings.inline_styles=false});a.create("tinymce.plugins.LegacyOutput",{init:function(b){b.onInit.add(function(){var c="p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img",e=a.explode(b.settings.font_size_style_values),d=b.schema;b.formatter.register({alignleft:{selector:c,attributes:{align:"left"}},aligncenter:{selector:c,attributes:{align:"center"}},alignright:{selector:c,attributes:{align:"right"}},alignfull:{selector:c,attributes:{align:"justify"}},bold:[{inline:"b",remove:"all"},{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}}],italic:[{inline:"i",remove:"all"},{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}}],underline:[{inline:"u",remove:"all"},{inline:"span",styles:{textDecoration:"underline"},exact:true}],strikethrough:[{inline:"strike",remove:"all"},{inline:"span",styles:{textDecoration:"line-through"},exact:true}],fontname:{inline:"font",attributes:{face:"%value"}},fontsize:{inline:"font",attributes:{size:function(f){return a.inArray(e,f.value)+1}}},forecolor:{inline:"font",styles:{color:"%value"}},hilitecolor:{inline:"font",styles:{backgroundColor:"%value"}}});a.each("b,i,u,strike".split(","),function(f){d.addValidElements(f+"[*]")});if(!d.getElementRule("font")){d.addValidElements("font[face|size|color|style]")}a.each(c.split(","),function(f){var h=d.getElementRule(f),g;if(h){if(!h.attributes.align){h.attributes.align={};h.attributesOrder.push("align")}}});b.onNodeChange.add(function(g,k){var j,f,h,i;f=g.dom.getParent(g.selection.getNode(),"font");if(f){h=f.face;i=f.size}if(j=k.get("fontselect")){j.select(function(l){return l==h})}if(j=k.get("fontsizeselect")){j.select(function(m){var l=a.inArray(e,m.fontSize);return l+1==i})}})})},getInfo:function(){return{longname:"LegacyOutput",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/legacyoutput",version:a.majorVersion+"."+a.minorVersion}}});a.PluginManager.add("legacyoutput",a.plugins.LegacyOutput)})(tinymce); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/legacyoutput/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/legacyoutput/editor_plugin_src.js new file mode 100644 index 0000000..e627ec7 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/legacyoutput/editor_plugin_src.js @@ -0,0 +1,139 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + * + * This plugin will force TinyMCE to produce deprecated legacy output such as font elements, u elements, align + * attributes and so forth. There are a few cases where these old items might be needed for example in email applications or with Flash + * + * However you should NOT use this plugin if you are building some system that produces web contents such as a CMS. All these elements are + * not apart of the newer specifications for HTML and XHTML. + */ + +(function(tinymce) { + // Override inline_styles setting to force TinyMCE to produce deprecated contents + tinymce.onAddEditor.addToTop(function(tinymce, editor) { + editor.settings.inline_styles = false; + }); + + // Create the legacy ouput plugin + tinymce.create('tinymce.plugins.LegacyOutput', { + init : function(editor) { + editor.onInit.add(function() { + var alignElements = 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', + fontSizes = tinymce.explode(editor.settings.font_size_style_values), + schema = editor.schema; + + // Override some internal formats to produce legacy elements and attributes + editor.formatter.register({ + // Change alignment formats to use the deprecated align attribute + alignleft : {selector : alignElements, attributes : {align : 'left'}}, + aligncenter : {selector : alignElements, attributes : {align : 'center'}}, + alignright : {selector : alignElements, attributes : {align : 'right'}}, + alignfull : {selector : alignElements, attributes : {align : 'justify'}}, + + // Change the basic formatting elements to use deprecated element types + bold : [ + {inline : 'b', remove : 'all'}, + {inline : 'strong', remove : 'all'}, + {inline : 'span', styles : {fontWeight : 'bold'}} + ], + italic : [ + {inline : 'i', remove : 'all'}, + {inline : 'em', remove : 'all'}, + {inline : 'span', styles : {fontStyle : 'italic'}} + ], + underline : [ + {inline : 'u', remove : 'all'}, + {inline : 'span', styles : {textDecoration : 'underline'}, exact : true} + ], + strikethrough : [ + {inline : 'strike', remove : 'all'}, + {inline : 'span', styles : {textDecoration: 'line-through'}, exact : true} + ], + + // Change font size and font family to use the deprecated font element + fontname : {inline : 'font', attributes : {face : '%value'}}, + fontsize : { + inline : 'font', + attributes : { + size : function(vars) { + return tinymce.inArray(fontSizes, vars.value) + 1; + } + } + }, + + // Setup font elements for colors as well + forecolor : {inline : 'font', styles : {color : '%value'}}, + hilitecolor : {inline : 'font', styles : {backgroundColor : '%value'}} + }); + + // Check that deprecated elements are allowed if not add them + tinymce.each('b,i,u,strike'.split(','), function(name) { + schema.addValidElements(name + '[*]'); + }); + + // Add font element if it's missing + if (!schema.getElementRule("font")) + schema.addValidElements("font[face|size|color|style]"); + + // Add the missing and depreacted align attribute for the serialization engine + tinymce.each(alignElements.split(','), function(name) { + var rule = schema.getElementRule(name), found; + + if (rule) { + if (!rule.attributes.align) { + rule.attributes.align = {}; + rule.attributesOrder.push('align'); + } + } + }); + + // Listen for the onNodeChange event so that we can do special logic for the font size and font name drop boxes + editor.onNodeChange.add(function(editor, control_manager) { + var control, fontElm, fontName, fontSize; + + // Find font element get it's name and size + fontElm = editor.dom.getParent(editor.selection.getNode(), 'font'); + if (fontElm) { + fontName = fontElm.face; + fontSize = fontElm.size; + } + + // Select/unselect the font name in droplist + if (control = control_manager.get('fontselect')) { + control.select(function(value) { + return value == fontName; + }); + } + + // Select/unselect the font size in droplist + if (control = control_manager.get('fontsizeselect')) { + control.select(function(value) { + var index = tinymce.inArray(fontSizes, value.fontSize); + + return index + 1 == fontSize; + }); + } + }); + }); + }, + + getInfo : function() { + return { + longname : 'LegacyOutput', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/legacyoutput', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('legacyoutput', tinymce.plugins.LegacyOutput); +})(tinymce); diff --git a/src/core/static/js/tiny_mce/plugins/lists/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/lists/editor_plugin.js new file mode 100644 index 0000000..67308f0 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/lists/editor_plugin.js @@ -0,0 +1 @@ +(function(){var e=tinymce.each,r=tinymce.dom.Event,g;function p(t,s){while(t&&(t.nodeType===8||(t.nodeType===3&&/^[ \t\n\r]*$/.test(t.nodeValue)))){t=s(t)}return t}function b(s){return p(s,function(t){return t.previousSibling})}function i(s){return p(s,function(t){return t.nextSibling})}function d(s,u,t){return s.dom.getParent(u,function(v){return tinymce.inArray(t,v)!==-1})}function n(s){return s&&(s.tagName==="OL"||s.tagName==="UL")}function c(u,v){var t,w,s;t=b(u.lastChild);while(n(t)){w=t;t=b(w.previousSibling)}if(w){s=v.create("li",{style:"list-style-type: none;"});v.split(u,w);v.insertAfter(s,w);s.appendChild(w);s.appendChild(w);u=s.previousSibling}return u}function m(t,s,u){t=a(t,s,u);return o(t,s,u)}function a(u,s,v){var t=b(u.previousSibling);if(t){return h(t,u,s?t:false,v)}else{return u}}function o(u,t,v){var s=i(u.nextSibling);if(s){return h(u,s,t?s:false,v)}else{return u}}function h(u,s,t,v){if(l(u,s,!!t,v)){return f(u,s,t)}else{if(u&&u.tagName==="LI"&&n(s)){u.appendChild(s)}}return s}function l(u,t,s,v){if(!u||!t){return false}else{if(u.tagName==="LI"&&t.tagName==="LI"){return t.style.listStyleType==="none"||j(t)}else{if(n(u)){return(u.tagName===t.tagName&&(s||u.style.listStyleType===t.style.listStyleType))||q(t)}else{if(v&&u.tagName==="P"&&t.tagName==="P"){return true}else{return false}}}}}function q(t){var s=i(t.firstChild),u=b(t.lastChild);return s&&u&&n(t)&&s===u&&(n(s)||s.style.listStyleType==="none"||j(s))}function j(u){var t=i(u.firstChild),s=b(u.lastChild);return t&&s&&t===s&&n(t)}function f(w,v,s){var u=b(w.lastChild),t=i(v.firstChild);if(w.tagName==="P"){w.appendChild(w.ownerDocument.createElement("br"))}while(v.firstChild){w.appendChild(v.firstChild)}if(s){w.style.listStyleType=s.style.listStyleType}v.parentNode.removeChild(v);h(u,t,false);return w}function k(t,u){var s;if(!u.is(t,"li,ol,ul")){s=u.getParent(t,"li");if(s){t=s}}return t}tinymce.create("tinymce.plugins.Lists",{init:function(A,y){var w=0;var t=1;var H=2;var J=3;var z=J;function C(M){return M.keyCode===9&&(A.queryCommandState("InsertUnorderedList")||A.queryCommandState("InsertOrderedList"))}function x(){var M=B();var O=M.parentNode.parentNode;var N=M.parentNode.lastChild===M;return N&&!u(O)&&K(M)}function u(M){if(n(M)){return M.parentNode&&M.parentNode.tagName==="LI"}else{return M.tagName==="LI"}}function D(){return A.selection.isCollapsed()&&K(B())}function B(){var M=A.selection.getStart();return((M.tagName=="BR"||M.tagName=="")&&M.parentNode.tagName=="LI")?M.parentNode:M}function K(M){var N=M.childNodes.length;if(M.tagName==="LI"){return N==0?true:N==1&&(M.firstChild.tagName==""||F(M)||G(M))}return false}function F(M){return tinymce.isWebKit&&M.firstChild.nodeName=="BR"}function G(M){var N=tinymce.grep(M.parentNode.childNodes,function(Q){return Q.nodeName=="LI"});var O=M==N[N.length-1];var P=M.firstChild;return tinymce.isIE9&&O&&(P.nodeValue==String.fromCharCode(160)||P.nodeValue==String.fromCharCode(32))}function L(M){return M.keyCode===13}function I(M){if(C(M)){return w}else{if(L(M)&&x()){return H}else{if(L(M)&&D()){return t}else{return J}}}}function s(M,N){if(z==w||z==t){return r.cancel(N)}}function v(P,R){var U;if(!tinymce.isGecko){return}var N=P.selection.getStart();if(R.keyCode!=8||N.tagName!=="IMG"){return}function O(Y){var Z=Y.firstChild;var X=null;do{if(!Z){break}if(Z.tagName==="LI"){X=Z}}while(Z=Z.nextSibling);return X}function W(Y,X){while(Y.childNodes.length>0){X.appendChild(Y.childNodes[0])}}U=N.parentNode.previousSibling;if(!U){return}var S;if(U.tagName==="UL"||U.tagName==="OL"){S=U}else{if(U.previousSibling&&(U.previousSibling.tagName==="UL"||U.previousSibling.tagName==="OL")){S=U.previousSibling}else{return}}var V=O(S);var M=P.dom.createRng();M.setStart(V,1);M.setEnd(V,1);P.selection.setRng(M);P.selection.collapse(true);var Q=P.selection.getBookmark();var T=N.parentNode.cloneNode(true);if(T.tagName==="P"||T.tagName==="DIV"){W(T,V)}else{V.appendChild(T)}N.parentNode.parentNode.removeChild(N.parentNode);P.selection.moveToBookmark(Q)}function E(M){var N=A.dom.getParent(M,"ol,ul");if(N!=null){var O=N.lastChild;O.appendChild(A.getDoc().createElement(""));A.selection.setCursorLocation(O,0)}}this.ed=A;A.addCommand("Indent",this.indent,this);A.addCommand("Outdent",this.outdent,this);A.addCommand("InsertUnorderedList",function(){this.applyList("UL","OL")},this);A.addCommand("InsertOrderedList",function(){this.applyList("OL","UL")},this);A.onInit.add(function(){A.editorCommands.addCommands({outdent:function(){var N=A.selection,O=A.dom;function M(P){P=O.getParent(P,O.isBlock);return P&&(parseInt(A.dom.getStyle(P,"margin-left")||0,10)+parseInt(A.dom.getStyle(P,"padding-left")||0,10))>0}return M(N.getStart())||M(N.getEnd())||A.queryCommandState("InsertOrderedList")||A.queryCommandState("InsertUnorderedList")}},"state")});A.onKeyUp.add(function(N,O){if(z==w){N.execCommand(O.shiftKey?"Outdent":"Indent",true,null);z=J;return r.cancel(O)}else{if(z==t){var M=B();var Q=N.settings.list_outdent_on_enter===true||O.shiftKey;N.execCommand(Q?"Outdent":"Indent",true,null);if(tinymce.isIE){E(M)}return r.cancel(O)}else{if(z==H){if(tinymce.isIE8){var P=N.getDoc().createTextNode("\uFEFF");N.selection.getNode().appendChild(P)}else{if(tinymce.isIE9){N.execCommand("Outdent");return r.cancel(O)}}}}}});A.onKeyDown.add(function(M,N){z=I(N)});A.onKeyDown.add(s);A.onKeyDown.add(v);A.onKeyPress.add(s)},applyList:function(y,v){var C=this,z=C.ed,I=z.dom,s=[],H=false,u=false,w=false,B,G=z.selection.getSelectedBlocks();function E(t){if(t&&t.tagName==="BR"){I.remove(t)}}function F(M){var N=I.create(y),t;function L(O){if(O.style.marginLeft||O.style.paddingLeft){C.adjustPaddingFunction(false)(O)}}if(M.tagName==="LI"){}else{if(M.tagName==="P"||M.tagName==="DIV"||M.tagName==="BODY"){K(M,function(P,O,Q){J(P,O,M.tagName==="BODY"?null:P.parentNode);t=P.parentNode;L(t);E(O)});if(M.tagName==="P"||G.length>1){I.split(t.parentNode.parentNode,t.parentNode)}m(t.parentNode,true);return}else{t=I.create("li");I.insertAfter(t,M);t.appendChild(M);L(M);M=t}}I.insertAfter(N,M);N.appendChild(M);m(N,true);s.push(M)}function J(Q,L,O){var t,P=Q,N,M;while(!I.isBlock(Q.parentNode)&&Q.parentNode!==I.getRoot()){Q=I.split(Q.parentNode,Q.previousSibling);Q=Q.nextSibling;P=Q}if(O){t=O.cloneNode(true);Q.parentNode.insertBefore(t,Q);while(t.firstChild){I.remove(t.firstChild)}t=I.rename(t,"li")}else{t=I.create("li");Q.parentNode.insertBefore(t,Q)}while(P&&P!=L){N=P.nextSibling;t.appendChild(P);P=N}if(t.childNodes.length===0){t.innerHTML='<br _mce_bogus="1" />'}F(t)}function K(Q,T){var N,R,O=3,L=1,t="br,ul,ol,p,div,h1,h2,h3,h4,h5,h6,table,blockquote,address,pre,form,center,dl";function P(X,U){var V=I.createRng(),W;g.keep=true;z.selection.moveToBookmark(g);g.keep=false;W=z.selection.getRng(true);if(!U){U=X.parentNode.lastChild}V.setStartBefore(X);V.setEndAfter(U);return !(V.compareBoundaryPoints(O,W)>0||V.compareBoundaryPoints(L,W)<=0)}function S(U){if(U.nextSibling){return U.nextSibling}if(!I.isBlock(U.parentNode)&&U.parentNode!==I.getRoot()){return S(U.parentNode)}}N=Q.firstChild;var M=false;e(I.select(t,Q),function(V){var U;if(V.hasAttribute&&V.hasAttribute("_mce_bogus")){return true}if(P(N,V)){I.addClass(V,"_mce_tagged_br");N=S(V)}});M=(N&&P(N,undefined));N=Q.firstChild;e(I.select(t,Q),function(V){var U=S(V);if(V.hasAttribute&&V.hasAttribute("_mce_bogus")){return true}if(I.hasClass(V,"_mce_tagged_br")){T(N,V,R);R=null}else{R=V}N=U});if(M){T(N,undefined,R)}}function D(t){K(t,function(M,L,N){J(M,L);E(L);E(N)})}function A(t){if(tinymce.inArray(s,t)!==-1){return}if(t.parentNode.tagName===v){I.split(t.parentNode,t);F(t);o(t.parentNode,false)}s.push(t)}function x(M){var O,N,L,t;if(tinymce.inArray(s,M)!==-1){return}M=c(M,I);while(I.is(M.parentNode,"ol,ul,li")){I.split(M.parentNode,M)}s.push(M);M=I.rename(M,"p");L=m(M,false,z.settings.force_br_newlines);if(L===M){O=M.firstChild;while(O){if(I.isBlock(O)){O=I.split(O.parentNode,O);t=true;N=O.nextSibling&&O.nextSibling.firstChild}else{N=O.nextSibling;if(t&&O.tagName==="BR"){I.remove(O)}t=false}O=N}}}e(G,function(t){t=k(t,I);if(t.tagName===v||(t.tagName==="LI"&&t.parentNode.tagName===v)){u=true}else{if(t.tagName===y||(t.tagName==="LI"&&t.parentNode.tagName===y)){H=true}else{w=true}}});if(w||u||G.length===0){B={LI:A,H1:F,H2:F,H3:F,H4:F,H5:F,H6:F,P:F,BODY:F,DIV:G.length>1?F:D,defaultAction:D}}else{B={defaultAction:x}}this.process(B)},indent:function(){var u=this.ed,w=u.dom,x=[];function s(z){var y=w.create("li",{style:"list-style-type: none;"});w.insertAfter(y,z);return y}function t(B){var y=s(B),D=w.getParent(B,"ol,ul"),C=D.tagName,E=w.getStyle(D,"list-style-type"),A={},z;if(E!==""){A.style="list-style-type: "+E+";"}z=w.create(C,A);y.appendChild(z);return z}function v(z){if(!d(u,z,x)){z=c(z,w);var y=t(z);y.appendChild(z);m(y.parentNode,false);m(y,false);x.push(z)}}this.process({LI:v,defaultAction:this.adjustPaddingFunction(true)})},outdent:function(){var v=this,u=v.ed,w=u.dom,s=[];function x(t){var z,y,A;if(!d(u,t,s)){if(w.getStyle(t,"margin-left")!==""||w.getStyle(t,"padding-left")!==""){return v.adjustPaddingFunction(false)(t)}A=w.getStyle(t,"text-align",true);if(A==="center"||A==="right"){w.setStyle(t,"text-align","left");return}t=c(t,w);z=t.parentNode;y=t.parentNode.parentNode;if(y.tagName==="P"){w.split(y,t.parentNode)}else{w.split(z,t);if(y.tagName==="LI"){w.split(y,t)}else{if(!w.is(y,"ol,ul")){w.rename(t,"p")}}}s.push(t)}}this.process({LI:x,defaultAction:this.adjustPaddingFunction(false)});e(s,m)},process:function(y){var D=this,w=D.ed.selection,z=D.ed.dom,C,u;function x(s){z.removeClass(s,"_mce_act_on");if(!s||s.nodeType!==1){return}s=k(s,z);var t=y[s.tagName];if(!t){t=y.defaultAction}t(s)}function v(s){D.splitSafeEach(s.childNodes,x)}function B(s,t){return t>=0&&s.hasChildNodes()&&t<s.childNodes.length&&s.childNodes[t].tagName==="BR"}C=w.getSelectedBlocks();if(C.length===0){C=[z.getRoot()]}u=w.getRng(true);if(!u.collapsed){if(B(u.endContainer,u.endOffset-1)){u.setEnd(u.endContainer,u.endOffset-1);w.setRng(u)}if(B(u.startContainer,u.startOffset)){u.setStart(u.startContainer,u.startOffset+1);w.setRng(u)}}if(tinymce.isIE8){var E=D.ed.selection.getNode();if(E.tagName==="LI"&&!(E.parentNode.lastChild===E)){var A=D.ed.getDoc().createTextNode("\uFEFF");E.appendChild(A)}}g=w.getBookmark();y.OL=y.UL=v;D.splitSafeEach(C,x);w.moveToBookmark(g);g=null;D.ed.execCommand("mceRepaint")},splitSafeEach:function(t,s){if(tinymce.isGecko&&(/Firefox\/[12]\.[0-9]/.test(navigator.userAgent)||/Firefox\/3\.[0-4]/.test(navigator.userAgent))){this.classBasedEach(t,s)}else{e(t,s)}},classBasedEach:function(v,u){var w=this.ed.dom,s,t;e(v,function(x){w.addClass(x,"_mce_act_on")});s=w.select("._mce_act_on");while(s.length>0){t=s.shift();w.removeClass(t,"_mce_act_on");u(t);s=w.select("._mce_act_on")}},adjustPaddingFunction:function(u){var s,v,t=this.ed;s=t.settings.indentation;v=/[a-z%]+/i.exec(s);s=parseInt(s,10);return function(w){var y,x;y=parseInt(t.dom.getStyle(w,"margin-left")||0,10)+parseInt(t.dom.getStyle(w,"padding-left")||0,10);if(u){x=y+s}else{x=y-s}t.dom.setStyle(w,"padding-left","");t.dom.setStyle(w,"margin-left",x>0?x+v:"")}},getInfo:function(){return{longname:"Lists",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/lists",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("lists",tinymce.plugins.Lists)}()); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/lists/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/lists/editor_plugin_src.js new file mode 100644 index 0000000..1db29f7 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/lists/editor_plugin_src.js @@ -0,0 +1,781 @@ +/** + * editor_plugin_src.js + * + * Copyright 2011, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var each = tinymce.each, Event = tinymce.dom.Event, bookmark; + + // Skips text nodes that only contain whitespace since they aren't semantically important. + function skipWhitespaceNodes(e, next) { + while (e && (e.nodeType === 8 || (e.nodeType === 3 && /^[ \t\n\r]*$/.test(e.nodeValue)))) { + e = next(e); + } + return e; + } + + function skipWhitespaceNodesBackwards(e) { + return skipWhitespaceNodes(e, function(e) { + return e.previousSibling; + }); + } + + function skipWhitespaceNodesForwards(e) { + return skipWhitespaceNodes(e, function(e) { + return e.nextSibling; + }); + } + + function hasParentInList(ed, e, list) { + return ed.dom.getParent(e, function(p) { + return tinymce.inArray(list, p) !== -1; + }); + } + + function isList(e) { + return e && (e.tagName === 'OL' || e.tagName === 'UL'); + } + + function splitNestedLists(element, dom) { + var tmp, nested, wrapItem; + tmp = skipWhitespaceNodesBackwards(element.lastChild); + while (isList(tmp)) { + nested = tmp; + tmp = skipWhitespaceNodesBackwards(nested.previousSibling); + } + if (nested) { + wrapItem = dom.create('li', { style: 'list-style-type: none;'}); + dom.split(element, nested); + dom.insertAfter(wrapItem, nested); + wrapItem.appendChild(nested); + wrapItem.appendChild(nested); + element = wrapItem.previousSibling; + } + return element; + } + + function attemptMergeWithAdjacent(e, allowDifferentListStyles, mergeParagraphs) { + e = attemptMergeWithPrevious(e, allowDifferentListStyles, mergeParagraphs); + return attemptMergeWithNext(e, allowDifferentListStyles, mergeParagraphs); + } + + function attemptMergeWithPrevious(e, allowDifferentListStyles, mergeParagraphs) { + var prev = skipWhitespaceNodesBackwards(e.previousSibling); + if (prev) { + return attemptMerge(prev, e, allowDifferentListStyles ? prev : false, mergeParagraphs); + } else { + return e; + } + } + + function attemptMergeWithNext(e, allowDifferentListStyles, mergeParagraphs) { + var next = skipWhitespaceNodesForwards(e.nextSibling); + if (next) { + return attemptMerge(e, next, allowDifferentListStyles ? next : false, mergeParagraphs); + } else { + return e; + } + } + + function attemptMerge(e1, e2, differentStylesMasterElement, mergeParagraphs) { + if (canMerge(e1, e2, !!differentStylesMasterElement, mergeParagraphs)) { + return merge(e1, e2, differentStylesMasterElement); + } else if (e1 && e1.tagName === 'LI' && isList(e2)) { + // Fix invalidly nested lists. + e1.appendChild(e2); + } + return e2; + } + + function canMerge(e1, e2, allowDifferentListStyles, mergeParagraphs) { + if (!e1 || !e2) { + return false; + } else if (e1.tagName === 'LI' && e2.tagName === 'LI') { + return e2.style.listStyleType === 'none' || containsOnlyAList(e2); + } else if (isList(e1)) { + return (e1.tagName === e2.tagName && (allowDifferentListStyles || e1.style.listStyleType === e2.style.listStyleType)) || isListForIndent(e2); + } else if (mergeParagraphs && e1.tagName === 'P' && e2.tagName === 'P') { + return true; + } else { + return false; + } + } + + function isListForIndent(e) { + var firstLI = skipWhitespaceNodesForwards(e.firstChild), lastLI = skipWhitespaceNodesBackwards(e.lastChild); + return firstLI && lastLI && isList(e) && firstLI === lastLI && (isList(firstLI) || firstLI.style.listStyleType === 'none' || containsOnlyAList(firstLI)); + } + + function containsOnlyAList(e) { + var firstChild = skipWhitespaceNodesForwards(e.firstChild), lastChild = skipWhitespaceNodesBackwards(e.lastChild); + return firstChild && lastChild && firstChild === lastChild && isList(firstChild); + } + + function merge(e1, e2, masterElement) { + var lastOriginal = skipWhitespaceNodesBackwards(e1.lastChild), firstNew = skipWhitespaceNodesForwards(e2.firstChild); + if (e1.tagName === 'P') { + e1.appendChild(e1.ownerDocument.createElement('br')); + } + while (e2.firstChild) { + e1.appendChild(e2.firstChild); + } + if (masterElement) { + e1.style.listStyleType = masterElement.style.listStyleType; + } + e2.parentNode.removeChild(e2); + attemptMerge(lastOriginal, firstNew, false); + return e1; + } + + function findItemToOperateOn(e, dom) { + var item; + if (!dom.is(e, 'li,ol,ul')) { + item = dom.getParent(e, 'li'); + if (item) { + e = item; + } + } + return e; + } + + tinymce.create('tinymce.plugins.Lists', { + init: function(ed, url) { + var LIST_TABBING = 0; + var LIST_EMPTY_ITEM = 1; + var LIST_ESCAPE = 2; + var LIST_UNKNOWN = 3; + var state = LIST_UNKNOWN; + + function isTabInList(e) { + return e.keyCode === 9 && (ed.queryCommandState('InsertUnorderedList') || ed.queryCommandState('InsertOrderedList')); + } + + function isOnLastListItem() { + var li = getLi(); + var grandParent = li.parentNode.parentNode; + var isLastItem = li.parentNode.lastChild === li; + return isLastItem && !isNestedList(grandParent) && isEmptyListItem(li); + } + + function isNestedList(grandParent) { + if (isList(grandParent)) { + return grandParent.parentNode && grandParent.parentNode.tagName === 'LI'; + } else { + return grandParent.tagName === 'LI'; + } + } + + function isInEmptyListItem() { + return ed.selection.isCollapsed() && isEmptyListItem(getLi()); + } + + function getLi() { + var n = ed.selection.getStart(); + // Get start will return BR if the LI only contains a BR or an empty element as we use these to fix caret position + return ((n.tagName == 'BR' || n.tagName == '') && n.parentNode.tagName == 'LI') ? n.parentNode : n; + } + + function isEmptyListItem(li) { + var numChildren = li.childNodes.length; + if (li.tagName === 'LI') { + return numChildren == 0 ? true : numChildren == 1 && (li.firstChild.tagName == '' || isEmptyWebKitLi(li) || isEmptyIE9Li(li)); + } + return false; + } + + function isEmptyWebKitLi(li) { + // Check for empty LI or a LI with just a child that is a BR since Gecko and WebKit uses BR elements to place the caret + return tinymce.isWebKit && li.firstChild.nodeName == 'BR'; + } + + function isEmptyIE9Li(li) { + // only consider this to be last item if there is no list item content or that content is nbsp or space since IE9 creates these + var lis = tinymce.grep(li.parentNode.childNodes, function(n) {return n.nodeName == 'LI'}); + var isLastLi = li == lis[lis.length - 1]; + var child = li.firstChild; + return tinymce.isIE9 && isLastLi && (child.nodeValue == String.fromCharCode(160) || child.nodeValue == String.fromCharCode(32)); + } + + function isEnter(e) { + return e.keyCode === 13; + } + + function getListKeyState(e) { + if (isTabInList(e)) { + return LIST_TABBING; + } else if (isEnter(e) && isOnLastListItem()) { + return LIST_ESCAPE; + } else if (isEnter(e) && isInEmptyListItem()) { + return LIST_EMPTY_ITEM; + } else { + return LIST_UNKNOWN; + } + } + + function cancelEnterAndTab(_, e) { + if (state == LIST_TABBING || state == LIST_EMPTY_ITEM) { + return Event.cancel(e); + } + } + + function imageJoiningListItem(ed, e) { + var prevSibling; + + if (!tinymce.isGecko) + return; + + var n = ed.selection.getStart(); + if (e.keyCode != 8 || n.tagName !== 'IMG') + return; + + function lastLI(node) { + var child = node.firstChild; + var li = null; + do { + if (!child) + break; + + if (child.tagName === 'LI') + li = child; + } while (child = child.nextSibling); + + return li; + } + + function addChildren(parentNode, destination) { + while (parentNode.childNodes.length > 0) + destination.appendChild(parentNode.childNodes[0]); + } + + // Check if there is a previous sibling + prevSibling = n.parentNode.previousSibling; + if (!prevSibling) + return; + + var ul; + if (prevSibling.tagName === 'UL' || prevSibling.tagName === 'OL') + ul = prevSibling; + else if (prevSibling.previousSibling && (prevSibling.previousSibling.tagName === 'UL' || prevSibling.previousSibling.tagName === 'OL')) + ul = prevSibling.previousSibling; + else + return; + + var li = lastLI(ul); + + // move the caret to the end of the list item + var rng = ed.dom.createRng(); + rng.setStart(li, 1); + rng.setEnd(li, 1); + ed.selection.setRng(rng); + ed.selection.collapse(true); + + // save a bookmark at the end of the list item + var bookmark = ed.selection.getBookmark(); + + // copy the image an its text to the list item + var clone = n.parentNode.cloneNode(true); + if (clone.tagName === 'P' || clone.tagName === 'DIV') + addChildren(clone, li); + else + li.appendChild(clone); + + // remove the old copy of the image + n.parentNode.parentNode.removeChild(n.parentNode); + + // move the caret where we saved the bookmark + ed.selection.moveToBookmark(bookmark); + } + + // fix the cursor position to ensure it is correct in IE + function setCursorPositionToOriginalLi(li) { + var list = ed.dom.getParent(li, 'ol,ul'); + if (list != null) { + var lastLi = list.lastChild; + lastLi.appendChild(ed.getDoc().createElement('')); + ed.selection.setCursorLocation(lastLi, 0); + } + } + + this.ed = ed; + ed.addCommand('Indent', this.indent, this); + ed.addCommand('Outdent', this.outdent, this); + ed.addCommand('InsertUnorderedList', function() { + this.applyList('UL', 'OL'); + }, this); + ed.addCommand('InsertOrderedList', function() { + this.applyList('OL', 'UL'); + }, this); + + ed.onInit.add(function() { + ed.editorCommands.addCommands({ + 'outdent': function() { + var sel = ed.selection, dom = ed.dom; + + function hasStyleIndent(n) { + n = dom.getParent(n, dom.isBlock); + return n && (parseInt(ed.dom.getStyle(n, 'margin-left') || 0, 10) + parseInt(ed.dom.getStyle(n, 'padding-left') || 0, 10)) > 0; + } + + return hasStyleIndent(sel.getStart()) || hasStyleIndent(sel.getEnd()) || ed.queryCommandState('InsertOrderedList') || ed.queryCommandState('InsertUnorderedList'); + } + }, 'state'); + }); + + ed.onKeyUp.add(function(ed, e) { + if (state == LIST_TABBING) { + ed.execCommand(e.shiftKey ? 'Outdent' : 'Indent', true, null); + state = LIST_UNKNOWN; + return Event.cancel(e); + } else if (state == LIST_EMPTY_ITEM) { + var li = getLi(); + var shouldOutdent = ed.settings.list_outdent_on_enter === true || e.shiftKey; + ed.execCommand(shouldOutdent ? 'Outdent' : 'Indent', true, null); + if (tinymce.isIE) { + setCursorPositionToOriginalLi(li); + } + return Event.cancel(e); + } else if (state == LIST_ESCAPE) { + if (tinymce.isIE8) { + // append a zero sized nbsp so that caret is positioned correctly in IE8 after escaping and applying formatting. + // if there is no text then applying formatting for e.g a H1 to the P tag immediately following list after + // escaping from it will cause the caret to be positioned on the last li instead of staying the in P tag. + var n = ed.getDoc().createTextNode('\uFEFF'); + ed.selection.getNode().appendChild(n); + } else if (tinymce.isIE9) { + // IE9 does not escape the list so we use outdent to do this and cancel the default behaviour + ed.execCommand('Outdent'); + return Event.cancel(e); + } + } + }); + ed.onKeyDown.add(function(_, e) { state = getListKeyState(e); }); + ed.onKeyDown.add(cancelEnterAndTab); + ed.onKeyDown.add(imageJoiningListItem); + ed.onKeyPress.add(cancelEnterAndTab); + }, + + applyList: function(targetListType, oppositeListType) { + var t = this, ed = t.ed, dom = ed.dom, applied = [], hasSameType = false, hasOppositeType = false, hasNonList = false, actions, + selectedBlocks = ed.selection.getSelectedBlocks(); + + function cleanupBr(e) { + if (e && e.tagName === 'BR') { + dom.remove(e); + } + } + + function makeList(element) { + var list = dom.create(targetListType), li; + + function adjustIndentForNewList(element) { + // If there's a margin-left, outdent one level to account for the extra list margin. + if (element.style.marginLeft || element.style.paddingLeft) { + t.adjustPaddingFunction(false)(element); + } + } + + if (element.tagName === 'LI') { + // No change required. + } else if (element.tagName === 'P' || element.tagName === 'DIV' || element.tagName === 'BODY') { + processBrs(element, function(startSection, br, previousBR) { + doWrapList(startSection, br, element.tagName === 'BODY' ? null : startSection.parentNode); + li = startSection.parentNode; + adjustIndentForNewList(li); + cleanupBr(br); + }); + if (element.tagName === 'P' || selectedBlocks.length > 1) { + dom.split(li.parentNode.parentNode, li.parentNode); + } + attemptMergeWithAdjacent(li.parentNode, true); + return; + } else { + // Put the list around the element. + li = dom.create('li'); + dom.insertAfter(li, element); + li.appendChild(element); + adjustIndentForNewList(element); + element = li; + } + dom.insertAfter(list, element); + list.appendChild(element); + attemptMergeWithAdjacent(list, true); + applied.push(element); + } + + function doWrapList(start, end, template) { + var li, n = start, tmp, i; + while (!dom.isBlock(start.parentNode) && start.parentNode !== dom.getRoot()) { + start = dom.split(start.parentNode, start.previousSibling); + start = start.nextSibling; + n = start; + } + if (template) { + li = template.cloneNode(true); + start.parentNode.insertBefore(li, start); + while (li.firstChild) dom.remove(li.firstChild); + li = dom.rename(li, 'li'); + } else { + li = dom.create('li'); + start.parentNode.insertBefore(li, start); + } + while (n && n != end) { + tmp = n.nextSibling; + li.appendChild(n); + n = tmp; + } + if (li.childNodes.length === 0) { + li.innerHTML = '<br _mce_bogus="1" />'; + } + makeList(li); + } + + function processBrs(element, callback) { + var startSection, previousBR, END_TO_START = 3, START_TO_END = 1, + breakElements = 'br,ul,ol,p,div,h1,h2,h3,h4,h5,h6,table,blockquote,address,pre,form,center,dl'; + + function isAnyPartSelected(start, end) { + var r = dom.createRng(), sel; + bookmark.keep = true; + ed.selection.moveToBookmark(bookmark); + bookmark.keep = false; + sel = ed.selection.getRng(true); + if (!end) { + end = start.parentNode.lastChild; + } + r.setStartBefore(start); + r.setEndAfter(end); + return !(r.compareBoundaryPoints(END_TO_START, sel) > 0 || r.compareBoundaryPoints(START_TO_END, sel) <= 0); + } + + function nextLeaf(br) { + if (br.nextSibling) + return br.nextSibling; + if (!dom.isBlock(br.parentNode) && br.parentNode !== dom.getRoot()) + return nextLeaf(br.parentNode); + } + + // Split on BRs within the range and process those. + startSection = element.firstChild; + // First mark the BRs that have any part of the previous section selected. + var trailingContentSelected = false; + each(dom.select(breakElements, element), function(br) { + var b; + if (br.hasAttribute && br.hasAttribute('_mce_bogus')) { + return true; // Skip the bogus Brs that are put in to appease Firefox and Safari. + } + if (isAnyPartSelected(startSection, br)) { + dom.addClass(br, '_mce_tagged_br'); + startSection = nextLeaf(br); + } + }); + trailingContentSelected = (startSection && isAnyPartSelected(startSection, undefined)); + startSection = element.firstChild; + each(dom.select(breakElements, element), function(br) { + // Got a section from start to br. + var tmp = nextLeaf(br); + if (br.hasAttribute && br.hasAttribute('_mce_bogus')) { + return true; // Skip the bogus Brs that are put in to appease Firefox and Safari. + } + if (dom.hasClass(br, '_mce_tagged_br')) { + callback(startSection, br, previousBR); + previousBR = null; + } else { + previousBR = br; + } + startSection = tmp; + }); + if (trailingContentSelected) { + callback(startSection, undefined, previousBR); + } + } + + function wrapList(element) { + processBrs(element, function(startSection, br, previousBR) { + // Need to indent this part + doWrapList(startSection, br); + cleanupBr(br); + cleanupBr(previousBR); + }); + } + + function changeList(element) { + if (tinymce.inArray(applied, element) !== -1) { + return; + } + if (element.parentNode.tagName === oppositeListType) { + dom.split(element.parentNode, element); + makeList(element); + attemptMergeWithNext(element.parentNode, false); + } + applied.push(element); + } + + function convertListItemToParagraph(element) { + var child, nextChild, mergedElement, splitLast; + if (tinymce.inArray(applied, element) !== -1) { + return; + } + element = splitNestedLists(element, dom); + while (dom.is(element.parentNode, 'ol,ul,li')) { + dom.split(element.parentNode, element); + } + // Push the original element we have from the selection, not the renamed one. + applied.push(element); + element = dom.rename(element, 'p'); + mergedElement = attemptMergeWithAdjacent(element, false, ed.settings.force_br_newlines); + if (mergedElement === element) { + // Now split out any block elements that can't be contained within a P. + // Manually iterate to ensure we handle modifications correctly (doesn't work with tinymce.each) + child = element.firstChild; + while (child) { + if (dom.isBlock(child)) { + child = dom.split(child.parentNode, child); + splitLast = true; + nextChild = child.nextSibling && child.nextSibling.firstChild; + } else { + nextChild = child.nextSibling; + if (splitLast && child.tagName === 'BR') { + dom.remove(child); + } + splitLast = false; + } + child = nextChild; + } + } + } + + each(selectedBlocks, function(e) { + e = findItemToOperateOn(e, dom); + if (e.tagName === oppositeListType || (e.tagName === 'LI' && e.parentNode.tagName === oppositeListType)) { + hasOppositeType = true; + } else if (e.tagName === targetListType || (e.tagName === 'LI' && e.parentNode.tagName === targetListType)) { + hasSameType = true; + } else { + hasNonList = true; + } + }); + + if (hasNonList || hasOppositeType || selectedBlocks.length === 0) { + actions = { + 'LI': changeList, + 'H1': makeList, + 'H2': makeList, + 'H3': makeList, + 'H4': makeList, + 'H5': makeList, + 'H6': makeList, + 'P': makeList, + 'BODY': makeList, + 'DIV': selectedBlocks.length > 1 ? makeList : wrapList, + defaultAction: wrapList + }; + } else { + actions = { + defaultAction: convertListItemToParagraph + }; + } + this.process(actions); + }, + + indent: function() { + var ed = this.ed, dom = ed.dom, indented = []; + + function createWrapItem(element) { + var wrapItem = dom.create('li', { style: 'list-style-type: none;'}); + dom.insertAfter(wrapItem, element); + return wrapItem; + } + + function createWrapList(element) { + var wrapItem = createWrapItem(element), + list = dom.getParent(element, 'ol,ul'), + listType = list.tagName, + listStyle = dom.getStyle(list, 'list-style-type'), + attrs = {}, + wrapList; + if (listStyle !== '') { + attrs.style = 'list-style-type: ' + listStyle + ';'; + } + wrapList = dom.create(listType, attrs); + wrapItem.appendChild(wrapList); + return wrapList; + } + + function indentLI(element) { + if (!hasParentInList(ed, element, indented)) { + element = splitNestedLists(element, dom); + var wrapList = createWrapList(element); + wrapList.appendChild(element); + attemptMergeWithAdjacent(wrapList.parentNode, false); + attemptMergeWithAdjacent(wrapList, false); + indented.push(element); + } + } + + this.process({ + 'LI': indentLI, + defaultAction: this.adjustPaddingFunction(true) + }); + + }, + + outdent: function() { + var t = this, ed = t.ed, dom = ed.dom, outdented = []; + + function outdentLI(element) { + var listElement, targetParent, align; + if (!hasParentInList(ed, element, outdented)) { + if (dom.getStyle(element, 'margin-left') !== '' || dom.getStyle(element, 'padding-left') !== '') { + return t.adjustPaddingFunction(false)(element); + } + align = dom.getStyle(element, 'text-align', true); + if (align === 'center' || align === 'right') { + dom.setStyle(element, 'text-align', 'left'); + return; + } + element = splitNestedLists(element, dom); + listElement = element.parentNode; + targetParent = element.parentNode.parentNode; + if (targetParent.tagName === 'P') { + dom.split(targetParent, element.parentNode); + } else { + dom.split(listElement, element); + if (targetParent.tagName === 'LI') { + // Nested list, need to split the LI and go back out to the OL/UL element. + dom.split(targetParent, element); + } else if (!dom.is(targetParent, 'ol,ul')) { + dom.rename(element, 'p'); + } + } + outdented.push(element); + } + } + + this.process({ + 'LI': outdentLI, + defaultAction: this.adjustPaddingFunction(false) + }); + + each(outdented, attemptMergeWithAdjacent); + }, + + process: function(actions) { + var t = this, sel = t.ed.selection, dom = t.ed.dom, selectedBlocks, r; + + function processElement(element) { + dom.removeClass(element, '_mce_act_on'); + if (!element || element.nodeType !== 1) { + return; + } + element = findItemToOperateOn(element, dom); + var action = actions[element.tagName]; + if (!action) { + action = actions.defaultAction; + } + action(element); + } + + function recurse(element) { + t.splitSafeEach(element.childNodes, processElement); + } + + function brAtEdgeOfSelection(container, offset) { + return offset >= 0 && container.hasChildNodes() && offset < container.childNodes.length && + container.childNodes[offset].tagName === 'BR'; + } + + selectedBlocks = sel.getSelectedBlocks(); + if (selectedBlocks.length === 0) { + selectedBlocks = [ dom.getRoot() ]; + } + + r = sel.getRng(true); + if (!r.collapsed) { + if (brAtEdgeOfSelection(r.endContainer, r.endOffset - 1)) { + r.setEnd(r.endContainer, r.endOffset - 1); + sel.setRng(r); + } + if (brAtEdgeOfSelection(r.startContainer, r.startOffset)) { + r.setStart(r.startContainer, r.startOffset + 1); + sel.setRng(r); + } + } + + + if (tinymce.isIE8) { + // append a zero sized nbsp so that caret is restored correctly using bookmark + var s = t.ed.selection.getNode(); + if (s.tagName === 'LI' && !(s.parentNode.lastChild === s)) { + var i = t.ed.getDoc().createTextNode('\uFEFF'); + s.appendChild(i); + } + } + + bookmark = sel.getBookmark(); + actions.OL = actions.UL = recurse; + t.splitSafeEach(selectedBlocks, processElement); + sel.moveToBookmark(bookmark); + bookmark = null; + // Avoids table or image handles being left behind in Firefox. + t.ed.execCommand('mceRepaint'); + }, + + splitSafeEach: function(elements, f) { + if (tinymce.isGecko && (/Firefox\/[12]\.[0-9]/.test(navigator.userAgent) || + /Firefox\/3\.[0-4]/.test(navigator.userAgent))) { + this.classBasedEach(elements, f); + } else { + each(elements, f); + } + }, + + classBasedEach: function(elements, f) { + var dom = this.ed.dom, nodes, element; + // Mark nodes + each(elements, function(element) { + dom.addClass(element, '_mce_act_on'); + }); + nodes = dom.select('._mce_act_on'); + while (nodes.length > 0) { + element = nodes.shift(); + dom.removeClass(element, '_mce_act_on'); + f(element); + nodes = dom.select('._mce_act_on'); + } + }, + + adjustPaddingFunction: function(isIndent) { + var indentAmount, indentUnits, ed = this.ed; + indentAmount = ed.settings.indentation; + indentUnits = /[a-z%]+/i.exec(indentAmount); + indentAmount = parseInt(indentAmount, 10); + return function(element) { + var currentIndent, newIndentAmount; + currentIndent = parseInt(ed.dom.getStyle(element, 'margin-left') || 0, 10) + parseInt(ed.dom.getStyle(element, 'padding-left') || 0, 10); + if (isIndent) { + newIndentAmount = currentIndent + indentAmount; + } else { + newIndentAmount = currentIndent - indentAmount; + } + ed.dom.setStyle(element, 'padding-left', ''); + ed.dom.setStyle(element, 'margin-left', newIndentAmount > 0 ? newIndentAmount + indentUnits : ''); + }; + }, + + getInfo: function() { + return { + longname : 'Lists', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/lists', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + tinymce.PluginManager.add("lists", tinymce.plugins.Lists); +}()); diff --git a/src/core/static/js/tiny_mce/plugins/media/css/media.css b/src/core/static/js/tiny_mce/plugins/media/css/media.css new file mode 100644 index 0000000..0c45c7f --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/media/css/media.css @@ -0,0 +1,17 @@ +#id, #name, #hspace, #vspace, #class_name, #align { width: 100px } +#hspace, #vspace { width: 50px } +#flash_quality, #flash_align, #flash_scale, #flash_salign, #flash_wmode { width: 100px } +#flash_base, #flash_flashvars, #html5_altsource1, #html5_altsource2, #html5_poster { width: 240px } +#width, #height { width: 40px } +#src, #media_type { width: 250px } +#class { width: 120px } +#prev { margin: 0; border: 1px solid black; width: 380px; height: 260px; overflow: auto } +.panel_wrapper div.current { height: 420px; overflow: auto } +#flash_options, #shockwave_options, #qt_options, #wmp_options, #rmp_options { display: none } +.mceAddSelectValue { background-color: #DDDDDD } +#qt_starttime, #qt_endtime, #qt_fov, #qt_href, #qt_moveid, #qt_moviename, #qt_node, #qt_pan, #qt_qtsrc, #qt_qtsrcchokespeed, #qt_target, #qt_tilt, #qt_urlsubstituten, #qt_volume { width: 70px } +#wmp_balance, #wmp_baseurl, #wmp_captioningid, #wmp_currentmarker, #wmp_currentposition, #wmp_defaultframe, #wmp_playcount, #wmp_rate, #wmp_uimode, #wmp_volume { width: 70px } +#rmp_console, #rmp_numloop, #rmp_controls, #rmp_scriptcallbacks { width: 70px } +#shockwave_swvolume, #shockwave_swframe, #shockwave_swurl, #shockwave_swstretchvalign, #shockwave_swstretchhalign, #shockwave_swstretchstyle { width: 90px } +#qt_qtsrc { width: 200px } +iframe {border: 1px solid gray} diff --git a/src/core/static/js/tiny_mce/plugins/media/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/media/editor_plugin.js new file mode 100644 index 0000000..37b4320 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/media/editor_plugin.js @@ -0,0 +1 @@ +(function(){var d=tinymce.explode("id,name,width,height,style,align,class,hspace,vspace,bgcolor,type"),h=tinymce.makeMap(d.join(",")),b=tinymce.html.Node,f,a,g=tinymce.util.JSON,e;f=[["Flash","d27cdb6e-ae6d-11cf-96b8-444553540000","application/x-shockwave-flash","http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"],["ShockWave","166b1bca-3f9c-11cf-8075-444553540000","application/x-director","http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0"],["WindowsMedia","6bf52a52-394a-11d3-b153-00c04f79faa6,22d6f312-b0f6-11d0-94ab-0080c74c7e95,05589fa1-c356-11ce-bf01-00aa0055595a","application/x-mplayer2","http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701"],["QuickTime","02bf25d5-8c17-4b23-bc80-d3488abddc6b","video/quicktime","http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0"],["RealMedia","cfcdaa03-8be4-11cf-b84b-0020afbbccfa","audio/x-pn-realaudio-plugin","http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"],["Java","8ad9c840-044e-11d1-b3e9-00805f499d93","application/x-java-applet","http://java.sun.com/products/plugin/autodl/jinstall-1_5_0-windows-i586.cab#Version=1,5,0,0"],["Silverlight","dfeaf541-f3e1-4c24-acac-99c30715084a","application/x-silverlight-2"],["Iframe"],["Video"],["EmbeddedAudio"],["Audio"]];function c(m){var l,j,k;if(m&&!m.splice){j=[];for(k=0;true;k++){if(m[k]){j[k]=m[k]}else{break}}return j}return m}tinymce.create("tinymce.plugins.MediaPlugin",{init:function(n,j){var r=this,l={},m,p,q,k;function o(i){return i&&i.nodeName==="IMG"&&n.dom.hasClass(i,"mceItemMedia")}r.editor=n;r.url=j;a="";for(m=0;m<f.length;m++){k=f[m][0];q={name:k,clsids:tinymce.explode(f[m][1]||""),mimes:tinymce.explode(f[m][2]||""),codebase:f[m][3]};for(p=0;p<q.clsids.length;p++){l["clsid:"+q.clsids[p]]=q}for(p=0;p<q.mimes.length;p++){l[q.mimes[p]]=q}l["mceItem"+k]=q;l[k.toLowerCase()]=q;a+=(a?"|":"")+k}tinymce.each(n.getParam("media_types","video=mp4,m4v,ogv,webm;silverlight=xap;flash=swf,flv;shockwave=dcr;quicktime=mov,qt,mpg,mpeg;shockwave=dcr;windowsmedia=avi,wmv,wm,asf,asx,wmx,wvx;realmedia=rm,ra,ram;java=jar;audio=mp3,ogg").split(";"),function(v){var s,u,t;v=v.split(/=/);u=tinymce.explode(v[1].toLowerCase());for(s=0;s<u.length;s++){t=l[v[0].toLowerCase()];if(t){l[u[s]]=t}}});a=new RegExp("write("+a+")\\(([^)]+)\\)");r.lookup=l;n.onPreInit.add(function(){n.schema.addValidElements("object[id|style|width|height|classid|codebase|*],param[name|value],embed[id|style|width|height|type|src|*],video[*],audio[*],source[*]");n.parser.addNodeFilter("object,embed,video,audio,script,iframe",function(s){var t=s.length;while(t--){r.objectToImg(s[t])}});n.serializer.addNodeFilter("img",function(s,u,t){var v=s.length,w;while(v--){w=s[v];if((w.attr("class")||"").indexOf("mceItemMedia")!==-1){r.imgToObject(w,t)}}})});n.onInit.add(function(){if(n.theme&&n.theme.onResolveName){n.theme.onResolveName.add(function(i,s){if(s.name==="img"&&n.dom.hasClass(s.node,"mceItemMedia")){s.name="media"}})}if(n&&n.plugins.contextmenu){n.plugins.contextmenu.onContextMenu.add(function(s,t,i){if(i.nodeName==="IMG"&&i.className.indexOf("mceItemMedia")!==-1){t.add({title:"media.edit",icon:"media",cmd:"mceMedia"})}})}});n.addCommand("mceMedia",function(){var s,i;i=n.selection.getNode();if(o(i)){s=n.dom.getAttrib(i,"data-mce-json");if(s){s=g.parse(s);tinymce.each(d,function(t){var u=n.dom.getAttrib(i,t);if(u){s[t]=u}});s.type=r.getType(i.className).name.toLowerCase()}}if(!s){s={type:"flash",video:{sources:[]},params:{}}}n.windowManager.open({file:j+"/media.htm",width:430+parseInt(n.getLang("media.delta_width",0)),height:500+parseInt(n.getLang("media.delta_height",0)),inline:1},{plugin_url:j,data:s})});n.addButton("media",{title:"media.desc",cmd:"mceMedia"});n.onNodeChange.add(function(s,i,t){i.setActive("media",o(t))})},convertUrl:function(k,n){var j=this,m=j.editor,l=m.settings,o=l.url_converter,i=l.url_converter_scope||j;if(!k){return k}if(n){return m.documentBaseURI.toAbsolute(k)}return o.call(i,k,"src","object")},getInfo:function(){return{longname:"Media",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media",version:tinymce.majorVersion+"."+tinymce.minorVersion}},dataToImg:function(m,k){var r=this,o=r.editor,p=o.documentBaseURI,j,q,n,l;m.params.src=r.convertUrl(m.params.src,k);q=m.video.attrs;if(q){q.src=r.convertUrl(q.src,k)}if(q){q.poster=r.convertUrl(q.poster,k)}j=c(m.video.sources);if(j){for(l=0;l<j.length;l++){j[l].src=r.convertUrl(j[l].src,k)}}n=r.editor.dom.create("img",{id:m.id,style:m.style,align:m.align,hspace:m.hspace,vspace:m.vspace,src:r.editor.theme.url+"/img/trans.gif","class":"mceItemMedia mceItem"+r.getType(m.type).name,"data-mce-json":g.serialize(m,"'")});n.width=m.width||(m.type=="audio"?"300":"320");n.height=m.height||(m.type=="audio"?"32":"240");return n},dataToHtml:function(i,j){return this.editor.serializer.serialize(this.dataToImg(i,j),{forced_root_block:"",force_absolute:j})},htmlToData:function(k){var j,i,l;l={type:"flash",video:{sources:[]},params:{}};j=this.editor.parser.parse(k);i=j.getAll("img")[0];if(i){l=g.parse(i.attr("data-mce-json"));l.type=this.getType(i.attr("class")).name.toLowerCase();tinymce.each(d,function(m){var n=i.attr(m);if(n){l[m]=n}})}return l},getType:function(m){var k,j,l;j=tinymce.explode(m," ");for(k=0;k<j.length;k++){l=this.lookup[j[k]];if(l){return l}}},imgToObject:function(z,o){var u=this,p=u.editor,C,H,j,t,I,y,G,w,k,E,s,q,A,D,m,x,l,B,F;function r(i,n){var M,L,N,K,J;J=p.getParam("flash_video_player_url",u.convertUrl(u.url+"/moxieplayer.swf"));if(J){M=p.documentBaseURI;G.params.src=J;if(p.getParam("flash_video_player_absvideourl",true)){i=M.toAbsolute(i||"",true);n=M.toAbsolute(n||"",true)}N="";L=p.getParam("flash_video_player_flashvars",{url:"$url",poster:"$poster"});tinymce.each(L,function(P,O){P=P.replace(/\$url/,i||"");P=P.replace(/\$poster/,n||"");if(P.length>0){N+=(N?"&":"")+O+"="+escape(P)}});if(N.length){G.params.flashvars=N}K=p.getParam("flash_video_player_params",{allowfullscreen:true,allowscriptaccess:true});tinymce.each(K,function(P,O){G.params[O]=""+P})}}G=z.attr("data-mce-json");if(!G){return}G=g.parse(G);q=this.getType(z.attr("class"));B=z.attr("data-mce-style");if(!B){B=z.attr("style");if(B){B=p.dom.serializeStyle(p.dom.parseStyle(B,"img"))}}if(q.name==="Iframe"){x=new b("iframe",1);tinymce.each(d,function(i){var n=z.attr(i);if(i=="class"&&n){n=n.replace(/mceItem.+ ?/g,"")}if(n&&n.length>0){x.attr(i,n)}});for(I in G.params){x.attr(I,G.params[I])}x.attr({style:B,src:G.params.src});z.replace(x);return}if(this.editor.settings.media_use_script){x=new b("script",1).attr("type","text/javascript");y=new b("#text",3);y.value="write"+q.name+"("+g.serialize(tinymce.extend(G.params,{width:z.attr("width"),height:z.attr("height")}))+");";x.append(y);z.replace(x);return}if(q.name==="Video"&&G.video.sources[0]){C=new b("video",1).attr(tinymce.extend({id:z.attr("id"),width:z.attr("width"),height:z.attr("height"),style:B},G.video.attrs));if(G.video.attrs){l=G.video.attrs.poster}k=G.video.sources=c(G.video.sources);for(A=0;A<k.length;A++){if(/\.mp4$/.test(k[A].src)){m=k[A].src}}if(!k[0].type){C.attr("src",k[0].src);k.splice(0,1)}for(A=0;A<k.length;A++){w=new b("source",1).attr(k[A]);w.shortEnded=true;C.append(w)}if(m){r(m,l);q=u.getType("flash")}else{G.params.src=""}}if(q.name==="Audio"&&G.video.sources[0]){F=new b("audio",1).attr(tinymce.extend({id:z.attr("id"),width:z.attr("width"),height:z.attr("height"),style:B},G.video.attrs));if(G.video.attrs){l=G.video.attrs.poster}k=G.video.sources=c(G.video.sources);if(!k[0].type){F.attr("src",k[0].src);k.splice(0,1)}for(A=0;A<k.length;A++){w=new b("source",1).attr(k[A]);w.shortEnded=true;F.append(w)}G.params.src=""}if(q.name==="EmbeddedAudio"){j=new b("embed",1);j.shortEnded=true;j.attr({id:z.attr("id"),width:z.attr("width"),height:z.attr("height"),style:B,type:z.attr("type")});for(I in G.params){j.attr(I,G.params[I])}tinymce.each(d,function(i){if(G[i]&&i!="type"){j.attr(i,G[i])}});G.params.src=""}if(G.params.src){if(/\.flv$/i.test(G.params.src)){r(G.params.src,"")}if(o&&o.force_absolute){G.params.src=p.documentBaseURI.toAbsolute(G.params.src)}H=new b("object",1).attr({id:z.attr("id"),width:z.attr("width"),height:z.attr("height"),style:B});tinymce.each(d,function(i){var n=G[i];if(i=="class"&&n){n=n.replace(/mceItem.+ ?/g,"")}if(n&&i!="type"){H.attr(i,n)}});for(I in G.params){s=new b("param",1);s.shortEnded=true;y=G.params[I];if(I==="src"&&q.name==="WindowsMedia"){I="url"}s.attr({name:I,value:y});H.append(s)}if(this.editor.getParam("media_strict",true)){H.attr({data:G.params.src,type:q.mimes[0]})}else{H.attr({classid:"clsid:"+q.clsids[0],codebase:q.codebase});j=new b("embed",1);j.shortEnded=true;j.attr({id:z.attr("id"),width:z.attr("width"),height:z.attr("height"),style:B,type:q.mimes[0]});for(I in G.params){j.attr(I,G.params[I])}tinymce.each(d,function(i){if(G[i]&&i!="type"){j.attr(i,G[i])}});H.append(j)}if(G.object_html){y=new b("#text",3);y.raw=true;y.value=G.object_html;H.append(y)}if(C){C.append(H)}}if(C){if(G.video_html){y=new b("#text",3);y.raw=true;y.value=G.video_html;C.append(y)}}if(F){if(G.video_html){y=new b("#text",3);y.raw=true;y.value=G.video_html;F.append(y)}}var v=C||F||H||j;if(v){z.replace(v)}else{z.remove()}},objectToImg:function(C){var L,k,F,s,M,N,y,A,x,G,E,t,q,I,B,l,K,o,H=this.lookup,m,z,v=this.editor.settings.url_converter,n=this.editor.settings.url_converter_scope,w,r,D,j;function u(i){return new tinymce.html.Serializer({inner:true,validate:false}).serialize(i)}function J(O,i){return H[(O.attr(i)||"").toLowerCase()]}function p(O){var i=O.replace(/^.*\.([^.]+)$/,"$1");return H[i.toLowerCase()||""]}if(!C.parent){return}if(C.name==="script"){if(C.firstChild){m=a.exec(C.firstChild.value)}if(!m){return}o=m[1];K={video:{},params:g.parse(m[2])};A=K.params.width;x=K.params.height}K=K||{video:{},params:{}};M=new b("img",1);M.attr({src:this.editor.theme.url+"/img/trans.gif"});N=C.name;if(N==="video"||N=="audio"){F=C;L=C.getAll("object")[0];k=C.getAll("embed")[0];A=F.attr("width");x=F.attr("height");y=F.attr("id");K.video={attrs:{},sources:[]};z=K.video.attrs;for(N in F.attributes.map){z[N]=F.attributes.map[N]}B=C.attr("src");if(B){K.video.sources.push({src:v.call(n,B,"src",C.name)})}l=F.getAll("source");for(E=0;E<l.length;E++){B=l[E].remove();K.video.sources.push({src:v.call(n,B.attr("src"),"src","source"),type:B.attr("type"),media:B.attr("media")})}if(z.poster){z.poster=v.call(n,z.poster,"poster",C.name)}}if(C.name==="object"){L=C;k=C.getAll("embed")[0]}if(C.name==="embed"){k=C}if(C.name==="iframe"){s=C;o="Iframe"}if(L){A=A||L.attr("width");x=x||L.attr("height");G=G||L.attr("style");y=y||L.attr("id");w=w||L.attr("hspace");r=r||L.attr("vspace");D=D||L.attr("align");j=j||L.attr("bgcolor");K.name=L.attr("name");I=L.getAll("param");for(E=0;E<I.length;E++){q=I[E];N=q.remove().attr("name");if(!h[N]){K.params[N]=q.attr("value")}}K.params.src=K.params.src||L.attr("data")}if(k){A=A||k.attr("width");x=x||k.attr("height");G=G||k.attr("style");y=y||k.attr("id");w=w||k.attr("hspace");r=r||k.attr("vspace");D=D||k.attr("align");j=j||k.attr("bgcolor");for(N in k.attributes.map){if(!h[N]&&!K.params[N]){K.params[N]=k.attributes.map[N]}}}if(s){A=s.attr("width");x=s.attr("height");G=G||s.attr("style");y=s.attr("id");w=s.attr("hspace");r=s.attr("vspace");D=s.attr("align");j=s.attr("bgcolor");tinymce.each(d,function(i){M.attr(i,s.attr(i))});for(N in s.attributes.map){if(!h[N]&&!K.params[N]){K.params[N]=s.attributes.map[N]}}}if(K.params.movie){K.params.src=K.params.src||K.params.movie;delete K.params.movie}if(K.params.src){K.params.src=v.call(n,K.params.src,"src","object")}if(F){if(C.name==="video"){o=H.video.name}else{if(C.name==="audio"){o=H.audio.name}}}if(L&&!o){o=(J(L,"clsid")||J(L,"classid")||J(L,"type")||{}).name}if(k&&!o){o=(J(k,"type")||p(K.params.src)||{}).name}if(k&&o=="EmbeddedAudio"){K.params.type=k.attr("type")}C.replace(M);if(k){k.remove()}if(L){t=u(L.remove());if(t){K.object_html=t}}if(F){t=u(F.remove());if(t){K.video_html=t}}K.hspace=w;K.vspace=r;K.align=D;K.bgcolor=j;M.attr({id:y,"class":"mceItemMedia mceItem"+(o||"Flash"),style:G,width:A||(C.name=="audio"?"300":"320"),height:x||(C.name=="audio"?"32":"240"),hspace:w,vspace:r,align:D,bgcolor:j,"data-mce-json":g.serialize(K,"'")})}});tinymce.PluginManager.add("media",tinymce.plugins.MediaPlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/media/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/media/editor_plugin_src.js new file mode 100644 index 0000000..ea79db1 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/media/editor_plugin_src.js @@ -0,0 +1,890 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var rootAttributes = tinymce.explode('id,name,width,height,style,align,class,hspace,vspace,bgcolor,type'), excludedAttrs = tinymce.makeMap(rootAttributes.join(',')), Node = tinymce.html.Node, + mediaTypes, scriptRegExp, JSON = tinymce.util.JSON, mimeTypes; + + // Media types supported by this plugin + mediaTypes = [ + // Type, clsid:s, mime types, codebase + ["Flash", "d27cdb6e-ae6d-11cf-96b8-444553540000", "application/x-shockwave-flash", "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"], + ["ShockWave", "166b1bca-3f9c-11cf-8075-444553540000", "application/x-director", "http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0"], + ["WindowsMedia", "6bf52a52-394a-11d3-b153-00c04f79faa6,22d6f312-b0f6-11d0-94ab-0080c74c7e95,05589fa1-c356-11ce-bf01-00aa0055595a", "application/x-mplayer2", "http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701"], + ["QuickTime", "02bf25d5-8c17-4b23-bc80-d3488abddc6b", "video/quicktime", "http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0"], + ["RealMedia", "cfcdaa03-8be4-11cf-b84b-0020afbbccfa", "audio/x-pn-realaudio-plugin", "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"], + ["Java", "8ad9c840-044e-11d1-b3e9-00805f499d93", "application/x-java-applet", "http://java.sun.com/products/plugin/autodl/jinstall-1_5_0-windows-i586.cab#Version=1,5,0,0"], + ["Silverlight", "dfeaf541-f3e1-4c24-acac-99c30715084a", "application/x-silverlight-2"], + ["Iframe"], + ["Video"], + ["EmbeddedAudio"], + ["Audio"] + ]; + + function toArray(obj) { + var undef, out, i; + + if (obj && !obj.splice) { + out = []; + + for (i = 0; true; i++) { + if (obj[i]) + out[i] = obj[i]; + else + break; + } + + return out; + } + + return obj; + }; + + tinymce.create('tinymce.plugins.MediaPlugin', { + init : function(ed, url) { + var self = this, lookup = {}, i, y, item, name; + + function isMediaImg(node) { + return node && node.nodeName === 'IMG' && ed.dom.hasClass(node, 'mceItemMedia'); + }; + + self.editor = ed; + self.url = url; + + // Parse media types into a lookup table + scriptRegExp = ''; + for (i = 0; i < mediaTypes.length; i++) { + name = mediaTypes[i][0]; + + item = { + name : name, + clsids : tinymce.explode(mediaTypes[i][1] || ''), + mimes : tinymce.explode(mediaTypes[i][2] || ''), + codebase : mediaTypes[i][3] + }; + + for (y = 0; y < item.clsids.length; y++) + lookup['clsid:' + item.clsids[y]] = item; + + for (y = 0; y < item.mimes.length; y++) + lookup[item.mimes[y]] = item; + + lookup['mceItem' + name] = item; + lookup[name.toLowerCase()] = item; + + scriptRegExp += (scriptRegExp ? '|' : '') + name; + } + + // Handle the media_types setting + tinymce.each(ed.getParam("media_types", + "video=mp4,m4v,ogv,webm;" + + "silverlight=xap;" + + "flash=swf,flv;" + + "shockwave=dcr;" + + "quicktime=mov,qt,mpg,mpeg;" + + "shockwave=dcr;" + + "windowsmedia=avi,wmv,wm,asf,asx,wmx,wvx;" + + "realmedia=rm,ra,ram;" + + "java=jar;" + + "audio=mp3,ogg" + ).split(';'), function(item) { + var i, extensions, type; + + item = item.split(/=/); + extensions = tinymce.explode(item[1].toLowerCase()); + for (i = 0; i < extensions.length; i++) { + type = lookup[item[0].toLowerCase()]; + + if (type) + lookup[extensions[i]] = type; + } + }); + + scriptRegExp = new RegExp('write(' + scriptRegExp + ')\\(([^)]+)\\)'); + self.lookup = lookup; + + ed.onPreInit.add(function() { + // Allow video elements + ed.schema.addValidElements('object[id|style|width|height|classid|codebase|*],param[name|value],embed[id|style|width|height|type|src|*],video[*],audio[*],source[*]'); + + // Convert video elements to image placeholder + ed.parser.addNodeFilter('object,embed,video,audio,script,iframe', function(nodes) { + var i = nodes.length; + + while (i--) + self.objectToImg(nodes[i]); + }); + + // Convert image placeholders to video elements + ed.serializer.addNodeFilter('img', function(nodes, name, args) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + if ((node.attr('class') || '').indexOf('mceItemMedia') !== -1) + self.imgToObject(node, args); + } + }); + }); + + ed.onInit.add(function() { + // Display "media" instead of "img" in element path + if (ed.theme && ed.theme.onResolveName) { + ed.theme.onResolveName.add(function(theme, path_object) { + if (path_object.name === 'img' && ed.dom.hasClass(path_object.node, 'mceItemMedia')) + path_object.name = 'media'; + }); + } + + // Add contect menu if it's loaded + if (ed && ed.plugins.contextmenu) { + ed.plugins.contextmenu.onContextMenu.add(function(plugin, menu, element) { + if (element.nodeName === 'IMG' && element.className.indexOf('mceItemMedia') !== -1) + menu.add({title : 'media.edit', icon : 'media', cmd : 'mceMedia'}); + }); + } + }); + + // Register commands + ed.addCommand('mceMedia', function() { + var data, img; + + img = ed.selection.getNode(); + if (isMediaImg(img)) { + data = ed.dom.getAttrib(img, 'data-mce-json'); + if (data) { + data = JSON.parse(data); + + // Add some extra properties to the data object + tinymce.each(rootAttributes, function(name) { + var value = ed.dom.getAttrib(img, name); + + if (value) + data[name] = value; + }); + + data.type = self.getType(img.className).name.toLowerCase(); + } + } + + if (!data) { + data = { + type : 'flash', + video: {sources:[]}, + params: {} + }; + } + + ed.windowManager.open({ + file : url + '/media.htm', + width : 430 + parseInt(ed.getLang('media.delta_width', 0)), + height : 500 + parseInt(ed.getLang('media.delta_height', 0)), + inline : 1 + }, { + plugin_url : url, + data : data + }); + }); + + // Register buttons + ed.addButton('media', {title : 'media.desc', cmd : 'mceMedia'}); + + // Update media selection status + ed.onNodeChange.add(function(ed, cm, node) { + cm.setActive('media', isMediaImg(node)); + }); + }, + + convertUrl : function(url, force_absolute) { + var self = this, editor = self.editor, settings = editor.settings, + urlConverter = settings.url_converter, + urlConverterScope = settings.url_converter_scope || self; + + if (!url) + return url; + + if (force_absolute) + return editor.documentBaseURI.toAbsolute(url); + + return urlConverter.call(urlConverterScope, url, 'src', 'object'); + }, + + getInfo : function() { + return { + longname : 'Media', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + /** + * Converts the JSON data object to an img node. + */ + dataToImg : function(data, force_absolute) { + var self = this, editor = self.editor, baseUri = editor.documentBaseURI, sources, attrs, img, i; + + data.params.src = self.convertUrl(data.params.src, force_absolute); + + attrs = data.video.attrs; + if (attrs) + attrs.src = self.convertUrl(attrs.src, force_absolute); + + if (attrs) + attrs.poster = self.convertUrl(attrs.poster, force_absolute); + + sources = toArray(data.video.sources); + if (sources) { + for (i = 0; i < sources.length; i++) + sources[i].src = self.convertUrl(sources[i].src, force_absolute); + } + + img = self.editor.dom.create('img', { + id : data.id, + style : data.style, + align : data.align, + hspace : data.hspace, + vspace : data.vspace, + src : self.editor.theme.url + '/img/trans.gif', + 'class' : 'mceItemMedia mceItem' + self.getType(data.type).name, + 'data-mce-json' : JSON.serialize(data, "'") + }); + + img.width = data.width || (data.type == 'audio' ? "300" : "320"); + img.height = data.height || (data.type == 'audio' ? "32" : "240"); + + return img; + }, + + /** + * Converts the JSON data object to a HTML string. + */ + dataToHtml : function(data, force_absolute) { + return this.editor.serializer.serialize(this.dataToImg(data, force_absolute), {forced_root_block : '', force_absolute : force_absolute}); + }, + + /** + * Converts the JSON data object to a HTML string. + */ + htmlToData : function(html) { + var fragment, img, data; + + data = { + type : 'flash', + video: {sources:[]}, + params: {} + }; + + fragment = this.editor.parser.parse(html); + img = fragment.getAll('img')[0]; + + if (img) { + data = JSON.parse(img.attr('data-mce-json')); + data.type = this.getType(img.attr('class')).name.toLowerCase(); + + // Add some extra properties to the data object + tinymce.each(rootAttributes, function(name) { + var value = img.attr(name); + + if (value) + data[name] = value; + }); + } + + return data; + }, + + /** + * Get type item by extension, class, clsid or mime type. + * + * @method getType + * @param {String} value Value to get type item by. + * @return {Object} Type item object or undefined. + */ + getType : function(value) { + var i, values, typeItem; + + // Find type by checking the classes + values = tinymce.explode(value, ' '); + for (i = 0; i < values.length; i++) { + typeItem = this.lookup[values[i]]; + + if (typeItem) + return typeItem; + } + }, + + /** + * Converts a tinymce.html.Node image element to video/object/embed. + */ + imgToObject : function(node, args) { + var self = this, editor = self.editor, video, object, embed, iframe, name, value, data, + source, sources, params, param, typeItem, i, item, mp4Source, replacement, + posterSrc, style, audio; + + // Adds the flash player + function addPlayer(video_src, poster_src) { + var baseUri, flashVars, flashVarsOutput, params, flashPlayer; + + flashPlayer = editor.getParam('flash_video_player_url', self.convertUrl(self.url + '/moxieplayer.swf')); + if (flashPlayer) { + baseUri = editor.documentBaseURI; + data.params.src = flashPlayer; + + // Convert the movie url to absolute urls + if (editor.getParam('flash_video_player_absvideourl', true)) { + video_src = baseUri.toAbsolute(video_src || '', true); + poster_src = baseUri.toAbsolute(poster_src || '', true); + } + + // Generate flash vars + flashVarsOutput = ''; + flashVars = editor.getParam('flash_video_player_flashvars', {url : '$url', poster : '$poster'}); + tinymce.each(flashVars, function(value, name) { + // Replace $url and $poster variables in flashvars value + value = value.replace(/\$url/, video_src || ''); + value = value.replace(/\$poster/, poster_src || ''); + + if (value.length > 0) + flashVarsOutput += (flashVarsOutput ? '&' : '') + name + '=' + escape(value); + }); + + if (flashVarsOutput.length) + data.params.flashvars = flashVarsOutput; + + params = editor.getParam('flash_video_player_params', { + allowfullscreen: true, + allowscriptaccess: true + }); + + tinymce.each(params, function(value, name) { + data.params[name] = "" + value; + }); + } + }; + + data = node.attr('data-mce-json'); + if (!data) + return; + + data = JSON.parse(data); + typeItem = this.getType(node.attr('class')); + + style = node.attr('data-mce-style') + if (!style) { + style = node.attr('style'); + + if (style) + style = editor.dom.serializeStyle(editor.dom.parseStyle(style, 'img')); + } + + // Handle iframe + if (typeItem.name === 'Iframe') { + replacement = new Node('iframe', 1); + + tinymce.each(rootAttributes, function(name) { + var value = node.attr(name); + + if (name == 'class' && value) + value = value.replace(/mceItem.+ ?/g, ''); + + if (value && value.length > 0) + replacement.attr(name, value); + }); + + for (name in data.params) + replacement.attr(name, data.params[name]); + + replacement.attr({ + style: style, + src: data.params.src + }); + + node.replace(replacement); + + return; + } + + // Handle scripts + if (this.editor.settings.media_use_script) { + replacement = new Node('script', 1).attr('type', 'text/javascript'); + + value = new Node('#text', 3); + value.value = 'write' + typeItem.name + '(' + JSON.serialize(tinymce.extend(data.params, { + width: node.attr('width'), + height: node.attr('height') + })) + ');'; + + replacement.append(value); + node.replace(replacement); + + return; + } + + // Add HTML5 video element + if (typeItem.name === 'Video' && data.video.sources[0]) { + // Create new object element + video = new Node('video', 1).attr(tinymce.extend({ + id : node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style + }, data.video.attrs)); + + // Get poster source and use that for flash fallback + if (data.video.attrs) + posterSrc = data.video.attrs.poster; + + sources = data.video.sources = toArray(data.video.sources); + for (i = 0; i < sources.length; i++) { + if (/\.mp4$/.test(sources[i].src)) + mp4Source = sources[i].src; + } + + if (!sources[0].type) { + video.attr('src', sources[0].src); + sources.splice(0, 1); + } + + for (i = 0; i < sources.length; i++) { + source = new Node('source', 1).attr(sources[i]); + source.shortEnded = true; + video.append(source); + } + + // Create flash fallback for video if we have a mp4 source + if (mp4Source) { + addPlayer(mp4Source, posterSrc); + typeItem = self.getType('flash'); + } else + data.params.src = ''; + } + + // Add HTML5 audio element + if (typeItem.name === 'Audio' && data.video.sources[0]) { + // Create new object element + audio = new Node('audio', 1).attr(tinymce.extend({ + id : node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style + }, data.video.attrs)); + + // Get poster source and use that for flash fallback + if (data.video.attrs) + posterSrc = data.video.attrs.poster; + + sources = data.video.sources = toArray(data.video.sources); + if (!sources[0].type) { + audio.attr('src', sources[0].src); + sources.splice(0, 1); + } + + for (i = 0; i < sources.length; i++) { + source = new Node('source', 1).attr(sources[i]); + source.shortEnded = true; + audio.append(source); + } + + data.params.src = ''; + } + + if (typeItem.name === 'EmbeddedAudio') { + embed = new Node('embed', 1); + embed.shortEnded = true; + embed.attr({ + id: node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style, + type: node.attr('type') + }); + + for (name in data.params) + embed.attr(name, data.params[name]); + + tinymce.each(rootAttributes, function(name) { + if (data[name] && name != 'type') + embed.attr(name, data[name]); + }); + + data.params.src = ''; + } + + // Do we have a params src then we can generate object + if (data.params.src) { + // Is flv movie add player for it + if (/\.flv$/i.test(data.params.src)) + addPlayer(data.params.src, ''); + + if (args && args.force_absolute) + data.params.src = editor.documentBaseURI.toAbsolute(data.params.src); + + // Create new object element + object = new Node('object', 1).attr({ + id : node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style + }); + + tinymce.each(rootAttributes, function(name) { + var value = data[name]; + + if (name == 'class' && value) + value = value.replace(/mceItem.+ ?/g, ''); + + if (value && name != 'type') + object.attr(name, value); + }); + + // Add params + for (name in data.params) { + param = new Node('param', 1); + param.shortEnded = true; + value = data.params[name]; + + // Windows media needs to use url instead of src for the media URL + if (name === 'src' && typeItem.name === 'WindowsMedia') + name = 'url'; + + param.attr({name: name, value: value}); + object.append(param); + } + + // Setup add type and classid if strict is disabled + if (this.editor.getParam('media_strict', true)) { + object.attr({ + data: data.params.src, + type: typeItem.mimes[0] + }); + } else { + object.attr({ + classid: "clsid:" + typeItem.clsids[0], + codebase: typeItem.codebase + }); + + embed = new Node('embed', 1); + embed.shortEnded = true; + embed.attr({ + id: node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style, + type: typeItem.mimes[0] + }); + + for (name in data.params) + embed.attr(name, data.params[name]); + + tinymce.each(rootAttributes, function(name) { + if (data[name] && name != 'type') + embed.attr(name, data[name]); + }); + + object.append(embed); + } + + // Insert raw HTML + if (data.object_html) { + value = new Node('#text', 3); + value.raw = true; + value.value = data.object_html; + object.append(value); + } + + // Append object to video element if it exists + if (video) + video.append(object); + } + + if (video) { + // Insert raw HTML + if (data.video_html) { + value = new Node('#text', 3); + value.raw = true; + value.value = data.video_html; + video.append(value); + } + } + + if (audio) { + // Insert raw HTML + if (data.video_html) { + value = new Node('#text', 3); + value.raw = true; + value.value = data.video_html; + audio.append(value); + } + } + + var n = video || audio || object || embed; + if (n) + node.replace(n); + else + node.remove(); + }, + + /** + * Converts a tinymce.html.Node video/object/embed to an img element. + * + * The video/object/embed will be converted into an image placeholder with a JSON data attribute like this: + * <img class="mceItemMedia mceItemFlash" width="100" height="100" data-mce-json="{..}" /> + * + * The JSON structure will be like this: + * {'params':{'flashvars':'something','quality':'high','src':'someurl'}, 'video':{'sources':[{src: 'someurl', type: 'video/mp4'}]}} + */ + objectToImg : function(node) { + var object, embed, video, iframe, img, name, id, width, height, style, i, html, + param, params, source, sources, data, type, lookup = this.lookup, + matches, attrs, urlConverter = this.editor.settings.url_converter, + urlConverterScope = this.editor.settings.url_converter_scope, + hspace, vspace, align, bgcolor; + + function getInnerHTML(node) { + return new tinymce.html.Serializer({ + inner: true, + validate: false + }).serialize(node); + }; + + function lookupAttribute(o, attr) { + return lookup[(o.attr(attr) || '').toLowerCase()]; + } + + function lookupExtension(src) { + var ext = src.replace(/^.*\.([^.]+)$/, '$1'); + return lookup[ext.toLowerCase() || '']; + } + + // If node isn't in document + if (!node.parent) + return; + + // Handle media scripts + if (node.name === 'script') { + if (node.firstChild) + matches = scriptRegExp.exec(node.firstChild.value); + + if (!matches) + return; + + type = matches[1]; + data = {video : {}, params : JSON.parse(matches[2])}; + width = data.params.width; + height = data.params.height; + } + + // Setup data objects + data = data || { + video : {}, + params : {} + }; + + // Setup new image object + img = new Node('img', 1); + img.attr({ + src : this.editor.theme.url + '/img/trans.gif' + }); + + // Video element + name = node.name; + if (name === 'video' || name == 'audio') { + video = node; + object = node.getAll('object')[0]; + embed = node.getAll('embed')[0]; + width = video.attr('width'); + height = video.attr('height'); + id = video.attr('id'); + data.video = {attrs : {}, sources : []}; + + // Get all video attributes + attrs = data.video.attrs; + for (name in video.attributes.map) + attrs[name] = video.attributes.map[name]; + + source = node.attr('src'); + if (source) + data.video.sources.push({src : urlConverter.call(urlConverterScope, source, 'src', node.name)}); + + // Get all sources + sources = video.getAll("source"); + for (i = 0; i < sources.length; i++) { + source = sources[i].remove(); + + data.video.sources.push({ + src: urlConverter.call(urlConverterScope, source.attr('src'), 'src', 'source'), + type: source.attr('type'), + media: source.attr('media') + }); + } + + // Convert the poster URL + if (attrs.poster) + attrs.poster = urlConverter.call(urlConverterScope, attrs.poster, 'poster', node.name); + } + + // Object element + if (node.name === 'object') { + object = node; + embed = node.getAll('embed')[0]; + } + + // Embed element + if (node.name === 'embed') + embed = node; + + // Iframe element + if (node.name === 'iframe') { + iframe = node; + type = 'Iframe'; + } + + if (object) { + // Get width/height + width = width || object.attr('width'); + height = height || object.attr('height'); + style = style || object.attr('style'); + id = id || object.attr('id'); + hspace = hspace || object.attr('hspace'); + vspace = vspace || object.attr('vspace'); + align = align || object.attr('align'); + bgcolor = bgcolor || object.attr('bgcolor'); + data.name = object.attr('name'); + + // Get all object params + params = object.getAll("param"); + for (i = 0; i < params.length; i++) { + param = params[i]; + name = param.remove().attr('name'); + + if (!excludedAttrs[name]) + data.params[name] = param.attr('value'); + } + + data.params.src = data.params.src || object.attr('data'); + } + + if (embed) { + // Get width/height + width = width || embed.attr('width'); + height = height || embed.attr('height'); + style = style || embed.attr('style'); + id = id || embed.attr('id'); + hspace = hspace || embed.attr('hspace'); + vspace = vspace || embed.attr('vspace'); + align = align || embed.attr('align'); + bgcolor = bgcolor || embed.attr('bgcolor'); + + // Get all embed attributes + for (name in embed.attributes.map) { + if (!excludedAttrs[name] && !data.params[name]) + data.params[name] = embed.attributes.map[name]; + } + } + + if (iframe) { + // Get width/height + width = iframe.attr('width'); + height = iframe.attr('height'); + style = style || iframe.attr('style'); + id = iframe.attr('id'); + hspace = iframe.attr('hspace'); + vspace = iframe.attr('vspace'); + align = iframe.attr('align'); + bgcolor = iframe.attr('bgcolor'); + + tinymce.each(rootAttributes, function(name) { + img.attr(name, iframe.attr(name)); + }); + + // Get all iframe attributes + for (name in iframe.attributes.map) { + if (!excludedAttrs[name] && !data.params[name]) + data.params[name] = iframe.attributes.map[name]; + } + } + + // Use src not movie + if (data.params.movie) { + data.params.src = data.params.src || data.params.movie; + delete data.params.movie; + } + + // Convert the URL to relative/absolute depending on configuration + if (data.params.src) + data.params.src = urlConverter.call(urlConverterScope, data.params.src, 'src', 'object'); + + if (video) { + if (node.name === 'video') + type = lookup.video.name; + else if (node.name === 'audio') + type = lookup.audio.name; + } + + if (object && !type) + type = (lookupAttribute(object, 'clsid') || lookupAttribute(object, 'classid') || lookupAttribute(object, 'type') || {}).name; + + if (embed && !type) + type = (lookupAttribute(embed, 'type') || lookupExtension(data.params.src) || {}).name; + + // for embedded audio we preserve the original specified type + if (embed && type == 'EmbeddedAudio') { + data.params.type = embed.attr('type'); + } + + // Replace the video/object/embed element with a placeholder image containing the data + node.replace(img); + + // Remove embed + if (embed) + embed.remove(); + + // Serialize the inner HTML of the object element + if (object) { + html = getInnerHTML(object.remove()); + + if (html) + data.object_html = html; + } + + // Serialize the inner HTML of the video element + if (video) { + html = getInnerHTML(video.remove()); + + if (html) + data.video_html = html; + } + + data.hspace = hspace; + data.vspace = vspace; + data.align = align; + data.bgcolor = bgcolor; + + // Set width/height of placeholder + img.attr({ + id : id, + 'class' : 'mceItemMedia mceItem' + (type || 'Flash'), + style : style, + width : width || (node.name == 'audio' ? "300" : "320"), + height : height || (node.name == 'audio' ? "32" : "240"), + hspace : hspace, + vspace : vspace, + align : align, + bgcolor : bgcolor, + "data-mce-json" : JSON.serialize(data, "'") + }); + } + }); + + // Register plugin + tinymce.PluginManager.add('media', tinymce.plugins.MediaPlugin); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/media/js/embed.js b/src/core/static/js/tiny_mce/plugins/media/js/embed.js new file mode 100644 index 0000000..f8dc810 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/media/js/embed.js @@ -0,0 +1,73 @@ +/** + * This script contains embed functions for common plugins. This scripts are complety free to use for any purpose. + */ + +function writeFlash(p) { + writeEmbed( + 'D27CDB6E-AE6D-11cf-96B8-444553540000', + 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0', + 'application/x-shockwave-flash', + p + ); +} + +function writeShockWave(p) { + writeEmbed( + '166B1BCA-3F9C-11CF-8075-444553540000', + 'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0', + 'application/x-director', + p + ); +} + +function writeQuickTime(p) { + writeEmbed( + '02BF25D5-8C17-4B23-BC80-D3488ABDDC6B', + 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0', + 'video/quicktime', + p + ); +} + +function writeRealMedia(p) { + writeEmbed( + 'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA', + 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0', + 'audio/x-pn-realaudio-plugin', + p + ); +} + +function writeWindowsMedia(p) { + p.url = p.src; + writeEmbed( + '6BF52A52-394A-11D3-B153-00C04F79FAA6', + 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701', + 'application/x-mplayer2', + p + ); +} + +function writeEmbed(cls, cb, mt, p) { + var h = '', n; + + h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"'; + h += typeof(p.id) != "undefined" ? 'id="' + p.id + '"' : ''; + h += typeof(p.name) != "undefined" ? 'name="' + p.name + '"' : ''; + h += typeof(p.width) != "undefined" ? 'width="' + p.width + '"' : ''; + h += typeof(p.height) != "undefined" ? 'height="' + p.height + '"' : ''; + h += typeof(p.align) != "undefined" ? 'align="' + p.align + '"' : ''; + h += '>'; + + for (n in p) + h += '<param name="' + n + '" value="' + p[n] + '">'; + + h += '<embed type="' + mt + '"'; + + for (n in p) + h += n + '="' + p[n] + '" '; + + h += '></embed></object>'; + + document.write(h); +} diff --git a/src/core/static/js/tiny_mce/plugins/media/js/media.js b/src/core/static/js/tiny_mce/plugins/media/js/media.js new file mode 100644 index 0000000..c4ec453 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/media/js/media.js @@ -0,0 +1,453 @@ +(function() { + var url; + + if (url = tinyMCEPopup.getParam("media_external_list_url")) + document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>'); + + function get(id) { + return document.getElementById(id); + } + + function clone(obj) { + var i, len, copy, attr; + + if (null == obj || "object" != typeof obj) + return obj; + + // Handle Array + if ('length' in obj) { + copy = []; + + for (i = 0, len = obj.length; i < len; ++i) { + copy[i] = clone(obj[i]); + } + + return copy; + } + + // Handle Object + copy = {}; + for (attr in obj) { + if (obj.hasOwnProperty(attr)) + copy[attr] = clone(obj[attr]); + } + + return copy; + } + + function getVal(id) { + var elm = get(id); + + if (elm.nodeName == "SELECT") + return elm.options[elm.selectedIndex].value; + + if (elm.type == "checkbox") + return elm.checked; + + return elm.value; + } + + function setVal(id, value, name) { + if (typeof(value) != 'undefined') { + var elm = get(id); + + if (elm.nodeName == "SELECT") + selectByValue(document.forms[0], id, value); + else if (elm.type == "checkbox") { + if (typeof(value) == 'string') { + value = value.toLowerCase(); + value = (!name && value === 'true') || (name && value === name.toLowerCase()); + } + elm.checked = !!value; + } else + elm.value = value; + } + } + + window.Media = { + init : function() { + var html, editor; + + this.editor = editor = tinyMCEPopup.editor; + + // Setup file browsers and color pickers + get('filebrowsercontainer').innerHTML = getBrowserHTML('filebrowser','src','media','media'); + get('qtsrcfilebrowsercontainer').innerHTML = getBrowserHTML('qtsrcfilebrowser','quicktime_qtsrc','media','media'); + get('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor'); + get('video_altsource1_filebrowser').innerHTML = getBrowserHTML('video_filebrowser_altsource1','video_altsource1','media','media'); + get('video_altsource2_filebrowser').innerHTML = getBrowserHTML('video_filebrowser_altsource2','video_altsource2','media','media'); + get('audio_altsource1_filebrowser').innerHTML = getBrowserHTML('audio_filebrowser_altsource1','audio_altsource1','media','media'); + get('audio_altsource2_filebrowser').innerHTML = getBrowserHTML('audio_filebrowser_altsource2','audio_altsource2','media','media'); + get('video_poster_filebrowser').innerHTML = getBrowserHTML('filebrowser_poster','video_poster','media','image'); + + html = this.getMediaListHTML('medialist', 'src', 'media', 'media'); + if (html == "") + get("linklistrow").style.display = 'none'; + else + get("linklistcontainer").innerHTML = html; + + if (isVisible('filebrowser')) + get('src').style.width = '230px'; + + if (isVisible('video_filebrowser_altsource1')) + get('video_altsource1').style.width = '220px'; + + if (isVisible('video_filebrowser_altsource2')) + get('video_altsource2').style.width = '220px'; + + if (isVisible('audio_filebrowser_altsource1')) + get('audio_altsource1').style.width = '220px'; + + if (isVisible('audio_filebrowser_altsource2')) + get('audio_altsource2').style.width = '220px'; + + if (isVisible('filebrowser_poster')) + get('video_poster').style.width = '220px'; + + editor.dom.setOuterHTML(get('media_type'), this.getMediaTypeHTML(editor)); + + this.data = clone(tinyMCEPopup.getWindowArg('data')); + this.dataToForm(); + this.preview(); + + updateColor('bgcolor_pick', 'bgcolor'); + }, + + insert : function() { + var editor = tinyMCEPopup.editor; + + this.formToData(); + editor.execCommand('mceRepaint'); + tinyMCEPopup.restoreSelection(); + editor.selection.setNode(editor.plugins.media.dataToImg(this.data)); + tinyMCEPopup.close(); + }, + + preview : function() { + get('prev').innerHTML = this.editor.plugins.media.dataToHtml(this.data, true); + }, + + moveStates : function(to_form, field) { + var data = this.data, editor = this.editor, + mediaPlugin = editor.plugins.media, ext, src, typeInfo, defaultStates, src; + + defaultStates = { + // QuickTime + quicktime_autoplay : true, + quicktime_controller : true, + + // Flash + flash_play : true, + flash_loop : true, + flash_menu : true, + + // WindowsMedia + windowsmedia_autostart : true, + windowsmedia_enablecontextmenu : true, + windowsmedia_invokeurls : true, + + // RealMedia + realmedia_autogotourl : true, + realmedia_imagestatus : true + }; + + function parseQueryParams(str) { + var out = {}; + + if (str) { + tinymce.each(str.split('&'), function(item) { + var parts = item.split('='); + + out[unescape(parts[0])] = unescape(parts[1]); + }); + } + + return out; + }; + + function setOptions(type, names) { + var i, name, formItemName, value, list; + + if (type == data.type || type == 'global') { + names = tinymce.explode(names); + for (i = 0; i < names.length; i++) { + name = names[i]; + formItemName = type == 'global' ? name : type + '_' + name; + + if (type == 'global') + list = data; + else if (type == 'video' || type == 'audio') { + list = data.video.attrs; + + if (!list && !to_form) + data.video.attrs = list = {}; + } else + list = data.params; + + if (list) { + if (to_form) { + setVal(formItemName, list[name], type == 'video' || type == 'audio' ? name : ''); + } else { + delete list[name]; + + value = getVal(formItemName); + if ((type == 'video' || type == 'audio') && value === true) + value = name; + + if (defaultStates[formItemName]) { + if (value !== defaultStates[formItemName]) { + value = "" + value; + list[name] = value; + } + } else if (value) { + value = "" + value; + list[name] = value; + } + } + } + } + } + } + + if (!to_form) { + data.type = get('media_type').options[get('media_type').selectedIndex].value; + data.width = getVal('width'); + data.height = getVal('height'); + + // Switch type based on extension + src = getVal('src'); + if (field == 'src') { + ext = src.replace(/^.*\.([^.]+)$/, '$1'); + if (typeInfo = mediaPlugin.getType(ext)) + data.type = typeInfo.name.toLowerCase(); + + setVal('media_type', data.type); + } + + if (data.type == "video" || data.type == "audio") { + if (!data.video.sources) + data.video.sources = []; + + data.video.sources[0] = {src: getVal('src')}; + } + } + + // Hide all fieldsets and show the one active + get('video_options').style.display = 'none'; + get('audio_options').style.display = 'none'; + get('flash_options').style.display = 'none'; + get('quicktime_options').style.display = 'none'; + get('shockwave_options').style.display = 'none'; + get('windowsmedia_options').style.display = 'none'; + get('realmedia_options').style.display = 'none'; + get('embeddedaudio_options').style.display = 'none'; + + if (get(data.type + '_options')) + get(data.type + '_options').style.display = 'block'; + + setVal('media_type', data.type); + + setOptions('flash', 'play,loop,menu,swliveconnect,quality,scale,salign,wmode,base,flashvars'); + setOptions('quicktime', 'loop,autoplay,cache,controller,correction,enablejavascript,kioskmode,autohref,playeveryframe,targetcache,scale,starttime,endtime,target,qtsrcchokespeed,volume,qtsrc'); + setOptions('shockwave', 'sound,progress,autostart,swliveconnect,swvolume,swstretchstyle,swstretchhalign,swstretchvalign'); + setOptions('windowsmedia', 'autostart,enabled,enablecontextmenu,fullscreen,invokeurls,mute,stretchtofit,windowlessvideo,balance,baseurl,captioningid,currentmarker,currentposition,defaultframe,playcount,rate,uimode,volume'); + setOptions('realmedia', 'autostart,loop,autogotourl,center,imagestatus,maintainaspect,nojava,prefetch,shuffle,console,controls,numloop,scriptcallbacks'); + setOptions('video', 'poster,autoplay,loop,muted,preload,controls'); + setOptions('audio', 'autoplay,loop,preload,controls'); + setOptions('embeddedaudio', 'autoplay,loop,controls'); + setOptions('global', 'id,name,vspace,hspace,bgcolor,align,width,height'); + + if (to_form) { + if (data.type == 'video') { + if (data.video.sources[0]) + setVal('src', data.video.sources[0].src); + + src = data.video.sources[1]; + if (src) + setVal('video_altsource1', src.src); + + src = data.video.sources[2]; + if (src) + setVal('video_altsource2', src.src); + } else if (data.type == 'audio') { + if (data.video.sources[0]) + setVal('src', data.video.sources[0].src); + + src = data.video.sources[1]; + if (src) + setVal('audio_altsource1', src.src); + + src = data.video.sources[2]; + if (src) + setVal('audio_altsource2', src.src); + } else { + // Check flash vars + if (data.type == 'flash') { + tinymce.each(editor.getParam('flash_video_player_flashvars', {url : '$url', poster : '$poster'}), function(value, name) { + if (value == '$url') + data.params.src = parseQueryParams(data.params.flashvars)[name] || data.params.src || ''; + }); + } + + setVal('src', data.params.src); + } + } else { + src = getVal("src"); + + // YouTube *NEW* + if (src.match(/youtu.be\/[a-z1-9.-_]+/)) { + data.width = 425; + data.height = 350; + data.params.frameborder = '0'; + data.type = 'iframe'; + src = 'http://www.youtube.com/embed/' + src.match(/youtu.be\/([a-z1-9.-_]+)/)[1]; + setVal('src', src); + setVal('media_type', data.type); + } + + // YouTube + if (src.match(/youtube.com(.+)v=([^&]+)/)) { + data.width = 425; + data.height = 350; + data.params.frameborder = '0'; + data.type = 'iframe'; + src = 'http://www.youtube.com/embed/' + src.match(/v=([^&]+)/)[1]; + setVal('src', src); + setVal('media_type', data.type); + } + + // Google video + if (src.match(/video.google.com(.+)docid=([^&]+)/)) { + data.width = 425; + data.height = 326; + data.type = 'flash'; + src = 'http://video.google.com/googleplayer.swf?docId=' + src.match(/docid=([^&]+)/)[1] + '&hl=en'; + setVal('src', src); + setVal('media_type', data.type); + } + + if (data.type == 'video') { + if (!data.video.sources) + data.video.sources = []; + + data.video.sources[0] = {src : src}; + + src = getVal("video_altsource1"); + if (src) + data.video.sources[1] = {src : src}; + + src = getVal("video_altsource2"); + if (src) + data.video.sources[2] = {src : src}; + } else if (data.type == 'audio') { + if (!data.video.sources) + data.video.sources = []; + + data.video.sources[0] = {src : src}; + + src = getVal("audio_altsource1"); + if (src) + data.video.sources[1] = {src : src}; + + src = getVal("audio_altsource2"); + if (src) + data.video.sources[2] = {src : src}; + } else + data.params.src = src; + + // Set default size + setVal('width', data.width || (data.type == 'audio' ? 300 : 320)); + setVal('height', data.height || (data.type == 'audio' ? 32 : 240)); + } + }, + + dataToForm : function() { + this.moveStates(true); + }, + + formToData : function(field) { + if (field == "width" || field == "height") + this.changeSize(field); + + if (field == 'source') { + this.moveStates(false, field); + setVal('source', this.editor.plugins.media.dataToHtml(this.data)); + this.panel = 'source'; + } else { + if (this.panel == 'source') { + this.data = clone(this.editor.plugins.media.htmlToData(getVal('source'))); + this.dataToForm(); + this.panel = ''; + } + + this.moveStates(false, field); + this.preview(); + } + }, + + beforeResize : function() { + this.width = parseInt(getVal('width') || (this.data.type == 'audio' ? "300" : "320"), 10); + this.height = parseInt(getVal('height') || (this.data.type == 'audio' ? "32" : "240"), 10); + }, + + changeSize : function(type) { + var width, height, scale, size; + + if (get('constrain').checked) { + width = parseInt(getVal('width') || (this.data.type == 'audio' ? "300" : "320"), 10); + height = parseInt(getVal('height') || (this.data.type == 'audio' ? "32" : "240"), 10); + + if (type == 'width') { + this.height = Math.round((width / this.width) * height); + setVal('height', this.height); + } else { + this.width = Math.round((height / this.height) * width); + setVal('width', this.width); + } + } + }, + + getMediaListHTML : function() { + if (typeof(tinyMCEMediaList) != "undefined" && tinyMCEMediaList.length > 0) { + var html = ""; + + html += '<select id="linklist" name="linklist" style="width: 250px" onchange="this.form.src.value=this.options[this.selectedIndex].value;Media.formToData(\'src\');">'; + html += '<option value="">---</option>'; + + for (var i=0; i<tinyMCEMediaList.length; i++) + html += '<option value="' + tinyMCEMediaList[i][1] + '">' + tinyMCEMediaList[i][0] + '</option>'; + + html += '</select>'; + + return html; + } + + return ""; + }, + + getMediaTypeHTML : function(editor) { + var html = ""; + html += '<select id="media_type" name="media_type" onchange="Media.formToData(\'type\');">'; + html += '<option value="video">HTML5 Video</option>'; + html += '<option value="audio">HTML5 Audio</option>'; + html += '<option value="flash">Flash</option>'; + html += '<option value="quicktime">QuickTime</option>'; + html += '<option value="shockwave">Shockwave</option>'; + html += '<option value="windowsmedia">Windows Media</option>'; + html += '<option value="realmedia">Real Media</option>'; + html += '<option value="iframe">Iframe</option>'; + + if (editor.getParam('media_embedded_audio', false)) { + html += '<option value="embeddedaudio">Embedded Audio</option>'; + } + + html += '</select>'; + return html; + } + }; + + tinyMCEPopup.requireLangPack(); + tinyMCEPopup.onInit.add(function() { + Media.init(); + }); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/media/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/media/langs/de_dlg.js new file mode 100755 index 0000000..614b11b --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/media/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.media_dlg',{list:"Liste",file:"Datei/URL",advanced:"Erweitert",general:"Allgemein",title:"Multimedia-Inhalte einf\u00fcgen/bearbeiten","align_top_left":"Oben Links","align_center":"Zentriert","align_left":"Links","align_bottom":"Unten","align_right":"Rechts","align_top":"Oben","qt_stream_warn":"In den Erweiterten Einstellungen sollten im Feld \'QT Src\' gestreamte RTSP Resourcen hinzugef\u00fcgt werden.\nZus\u00e4tzlich sollten Sie dort auch eine nicht-gestreamte Resource angeben.",qtsrc:"Angabe zu QT Src",progress:"Fortschritt",sound:"Ton",swstretchvalign:"Stretch V-Ausrichtung",swstretchhalign:"Stretch H-Ausrichtung",swstretchstyle:"Stretch-Art",scriptcallbacks:"Script callbacks","align_top_right":"Oben Rechts",uimode:"UI Modus",rate:"Rate",playcount:"Z\u00e4hler",defaultframe:"Frame-Voreinstellung",currentposition:"Aktuelle Position",currentmarker:"Aktueller Marker",captioningid:"Captioning id",baseurl:"Base URL",balance:"Balance",windowlessvideo:"Fensterloses Video",stretchtofit:"Anzeigefl\u00e4che an verf\u00fcgbaren Platz anpassen",mute:"Stumm",invokeurls:"Invoke URLs",fullscreen:"Vollbild",enabled:"Aktiviert",autostart:"Autostart",volume:"Lautst\u00e4rke",target:"Ziel",qtsrcchokespeed:"Choke speed",href:"Href",endtime:"Endzeitpunkt",starttime:"Startzeitpunkt",enablejavascript:"JavaScript aktivieren",correction:"Ohne Korrektur",targetcache:"Ziel zwischenspeichern",playeveryframe:"Jeden Frame abspielen",kioskmode:"Kioskmodus",controller:"Controller",menu:"Men\u00fc anzeigen",loop:"Wiederholung",play:"Automatisches Abspielen",hspace:"Horizontaler Abstand",vspace:"Vertikaler Abstand","class_name":"CSS-Klasse",name:"Name",id:"Id",type:"Typ",size:"Abmessungen",preview:"Vorschau","constrain_proportions":"Proportionen erhalten",controls:"Steuerung",numloop:"Anzahl Wiederholungen",console:"Konsole",cache:"Zwischenspeicher",autohref:"AutoHREF",liveconnect:"SWLiveConnect",flashvars:"Flashvariablen",base:"Base",bgcolor:"Hintergrund",wmode:"WMode",salign:"S-Ausrichtung",align:"Ausrichtung",scale:"Skalierung",quality:"Qualit\u00e4t",shuffle:"Zuf\u00e4llige Wiedergabe",prefetch:"Prefetch",nojava:"Kein Java",maintainaspect:"Bildverh\u00e4ltnis beibehalten",imagestatus:"Bildstatus",center:"Zentriert",autogotourl:"Auto goto URL","shockwave_options":"Shockwave-Optionen","rmp_options":"Optionen f\u00fcr Real Media Player","wmp_options":"Optionen f\u00fcr Windows Media Player","qt_options":"Quicktime-Optionen","flash_options":"Flash-Optionen",hidden:"Versteckt","align_bottom_left":"Unten Links","align_bottom_right":"Unten Rechts","embedded_audio_options":"Integrierte Audio Optionen","html5_video_options":"HTML5 Video Optionen",altsource1:"Alternative Quelle 1",altsource2:"Alternative Quelle 2",preload:"Preload",poster:"Poster",source:"Quelle","html5_audio_options":"Audio Optionen","preload_none":"Nicht vorladen","preload_metadata":"Video Metadaten vorladen","preload_auto":"Benutzer Browser entscheidet automatisch"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/media/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/media/langs/en_dlg.js new file mode 100755 index 0000000..11b24a1 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/media/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.media_dlg',{list:"List",file:"File/URL",advanced:"Advanced",general:"General",title:"Insert/Edit Embedded Media","align_top_left":"Top Left","align_center":"Center","align_left":"Left","align_bottom":"Bottom","align_right":"Right","align_top":"Top","qt_stream_warn":"Streamed RTSP resources should be added to the QT Source field under the Advanced tab.\nYou should also add a non-streamed version to the Source field.",qtsrc:"QT Source",progress:"Progress",sound:"Sound",swstretchvalign:"Stretch V-Align",swstretchhalign:"Stretch H-Align",swstretchstyle:"Stretch Style",scriptcallbacks:"Script Callbacks","align_top_right":"Top Right",uimode:"UI Mode",rate:"Rate",playcount:"Play Count",defaultframe:"Default Frame",currentposition:"Current Position",currentmarker:"Current Marker",captioningid:"Captioning ID",baseurl:"Base URL",balance:"Balance",windowlessvideo:"Windowless Video",stretchtofit:"Stretch to Fit",mute:"Mute",invokeurls:"Invoke URLs",fullscreen:"Full Screen",enabled:"Enabled",autostart:"Auto Start",volume:"Volume",target:"Target",qtsrcchokespeed:"Choke Speed",href:"HREF",endtime:"End Time",starttime:"Start Time",enablejavascript:"Enable JavaScript",correction:"No Correction",targetcache:"Target Cache",playeveryframe:"Play Every Frame",kioskmode:"Kiosk Mode",controller:"Controller",menu:"Show Menu",loop:"Loop",play:"Auto Play",hspace:"H-Space",vspace:"V-Space","class_name":"Class",name:"Name",id:"ID",type:"Type",size:"Dimensions",preview:"Preview","constrain_proportions":"Constrain Proportions",controls:"Controls",numloop:"Num Loops",console:"Console",cache:"Cache",autohref:"Auto HREF",liveconnect:"SWLiveConnect",flashvars:"Flash Vars",base:"Base",bgcolor:"Background",wmode:"WMode",salign:"SAlign",align:"Align",scale:"Scale",quality:"Quality",shuffle:"Shuffle",prefetch:"Prefetch",nojava:"No Java",maintainaspect:"Maintain Aspect",imagestatus:"Image Status",center:"Center",autogotourl:"Auto Goto URL","shockwave_options":"Shockwave Options","rmp_options":"Real Media Player Options","wmp_options":"Windows Media Player Options","qt_options":"QuickTime Options","flash_options":"Flash Options",hidden:"Hidden","align_bottom_left":"Bottom Left","align_bottom_right":"Bottom Right","embedded_audio_options":"Embedded Audio Options","html5_video_options":"HTML5 Video Options",altsource1:"Alternative source 1",altsource2:"Alternative source 2",preload:"Preload",poster:"Poster",source:"Source","html5_audio_options":"Audio Options","preload_none":"Don\'t Preload","preload_metadata":"Preload video metadata","preload_auto":"Let user\'s browser decide"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/media/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/media/langs/fr_dlg.js new file mode 100755 index 0000000..6273c59 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/media/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.media_dlg',{list:"Liste",file:"Fichier / URL",advanced:"Avanc\u00e9",general:"G\u00e9n\u00e9ral",title:"Ins\u00e9rer / \u00e9diter un fichier m\u00e9dia","align_top_left":"En haut \u00e0 gauche","align_center":"Centr\u00e9","align_left":"Gauche","align_bottom":"Bas","align_right":"Droite","align_top":"Haut","qt_stream_warn":"Les ressources rtsp en streaming doivent \u00eatre ajout\u00e9es au champ \u00ab Source QT \u00bb dans l\'onglet avanc\u00e9.\nVous devriez aussi ajouter une version n\'\u00e9tant pas en streaming au champ \u00ab source QT \u00bb.",qtsrc:"Source QT",progress:"Progression",sound:"Son",swstretchvalign:"Stretch vertical",swstretchhalign:"Stretch horizontal",swstretchstyle:"Stretch style",scriptcallbacks:"Callback de script","align_top_right":"En haut \u00e0 droite",uimode:"Mode UI",rate:"Taux",playcount:"Compteur",defaultframe:"Image par d\u00e9faut",currentposition:"Position actuelle",currentmarker:"Marqueur actuel",captioningid:"ID sous-titrage",baseurl:"Adresse de base",balance:"Balance",windowlessvideo:"Vid\u00e9o sans fen\u00eatre",stretchtofit:"\u00c9tendre pour adapter la taille",mute:"Muet",invokeurls:"Invoquer URLs",fullscreen:"Plein \u00e9cran",enabled:"Activ\u00e9",autostart:"Lire automatiquement",volume:"Volume",target:"Cible",qtsrcchokespeed:"D\u00e9bit maximum",href:"Href",endtime:"Fin",starttime:"D\u00e9but",enablejavascript:"Activer le JavaScript",correction:"Pas de correction",targetcache:"Cache cible",playeveryframe:"Jouer toutes les images",kioskmode:"Mode kiosque",controller:"Contr\u00f4leur",menu:"Afficher le menu",loop:"Lire en boucle",play:"Lecture automatique",hspace:"Espacement horizontal",vspace:"Espacement vertical","class_name":"Classe",name:"Nom",id:"Id",type:"Type",size:"Dimensions",preview:"Pr\u00e9visualisation","constrain_proportions":"Conserver les proportions",controls:"Contr\u00f4les",numloop:"Nombre de tours",console:"Console",cache:"Cache",autohref:"AutoHREF",liveconnect:"SWLiveConnect",flashvars:"Variables flash",base:"Base",bgcolor:"Fond",wmode:"WMode",salign:"SAlign",align:"Alignement",scale:"\u00c9chelle",quality:"Qualit\u00e9",shuffle:"Al\u00e9atoire",prefetch:"Pr\u00e9chargement",nojava:"Pas java",maintainaspect:"Maintenir l\'aspect",imagestatus:"Statut de l\'image",center:"Centrer",autogotourl:"Aller automatiquement \u00e0 l\'URL","shockwave_options":"Options Shockwave","rmp_options":"Options Real media player","wmp_options":"Windows media player options","qt_options":"Options Quicktime","flash_options":"Options Flash",hidden:"Cach\u00e9","align_bottom_left":"En bas \u00e0 gauche","align_bottom_right":"En bas \u00e0 droite","html5_video_options":"Options Vid\u00e9o HTML 5",altsource1:"Source alternative 1",altsource2:"Source alternative 2",preload:"Pr\u00e9chargement",poster:"Poster",source:"Source","html5_audio_options":"Audio Options","preload_none":"Don\'t Preload","preload_metadata":"Preload video metadata","preload_auto":"Let user\'s browser decide"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/media/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/media/langs/it_dlg.js new file mode 100755 index 0000000..23b5240 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/media/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.media_dlg',{list:"Lista",file:"File/URL",advanced:"Avanzate",general:"Generale",title:"Inserisci/modifica file multimediale","align_top_left":"Alto a sinistra","align_center":"Centro","align_left":"Sinistra","align_bottom":"Basso","align_right":"Destra","align_top":"Alto","qt_stream_warn":"Le risorse rstp \'streamed\' devono essere aggiunte al campo Sorgente QT nella tabella Avanzate.\nSi dovrebbe inserire anche una versione non \'streamed\' al campo Sorgente..",qtsrc:"Sorgente QT",progress:"Avanzamento",sound:"Suono",swstretchvalign:"Tratto V-Allineamento",swstretchhalign:"Tratto H-Allineamento",swstretchstyle:"Stile Tratto",scriptcallbacks:"Script richiamato","align_top_right":"Alto a destra",uimode:"Modalit\u00e0 Interfaccia Utente",rate:"Qualit\u00e0",playcount:"Conteggio esecuzione",defaultframe:"Frame predefinito",currentposition:"Posizione corrente",currentmarker:"Indicatore corrente",captioningid:"Didascalia dell\'Id",baseurl:"URL base",balance:"Bilanciamento",windowlessvideo:"Video senza finestra",stretchtofit:"Adatta dimensioni",mute:"Muto",invokeurls:"Invoca URLs",fullscreen:"Tutto schermo",enabled:"Abilitato",autostart:"Avvio automatico",volume:"Volume",target:"Target",qtsrcchokespeed:"Velocit\u00e0 cursore",href:"Href",endtime:"Ora fine",starttime:"Ora inizio",enablejavascript:"Abilita JavaScript",correction:"Nessuna correzione",targetcache:"Cache del target",playeveryframe:"Esegui ogni frame",kioskmode:"Modalit\u00e0 Kiosk",controller:"Controller",menu:"Mostra menu",loop:"Riproduzione ciclica",play:"Esecuzione automatica",hspace:"H-Spazio",vspace:"V-Spazio","class_name":"Classe",name:"Nome",id:"Id",type:"Tipo",size:"Dimensioni",preview:"Anteprima","constrain_proportions":"Mantieni proporzioni",controls:"Controlli",numloop:"Numero cicli",console:"Console",cache:"Cache",autohref:"AutoHREF",liveconnect:"SWLiveConnect",flashvars:"Flashvars",base:"Base",bgcolor:"Sfondo",wmode:"WMode",salign:"SAlign",align:"Allineamento",scale:"Scala",quality:"Qualit\u00e0",shuffle:"Shuffle",prefetch:"Precaricamento",nojava:"No java",maintainaspect:"Mantieni aspetto",imagestatus:"Stato immagine",center:"Centra",autogotourl:"Vai a URL automatico","shockwave_options":"Opzioni Shockwave","rmp_options":"Opzioni Real media player","wmp_options":"Opzioni Windows media player","qt_options":"Opzioni Quicktime","flash_options":"Opzioni Flash",hidden:"Nascosto","align_bottom_left":"Basso a sinistra","align_bottom_right":"Basso a destra","html5_video_options":"Opzioni Video HTML5",altsource1:"Sorgente alternativa 1",altsource2:"Sorgente alternativa 2",preload:"Precarica",poster:"Poster",source:"Sorgente","html5_audio_options":"Audio Options","preload_none":"Don\'t Preload","preload_metadata":"Preload video metadata","preload_auto":"Let user\'s browser decide"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/media/media.htm b/src/core/static/js/tiny_mce/plugins/media/media.htm new file mode 100644 index 0000000..957d83a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/media/media.htm @@ -0,0 +1,922 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#media_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/media.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <link href="css/media.css" rel="stylesheet" type="text/css" /> +</head> +<body style="display: none" role="application"> +<form onsubmit="Media.insert();return false;" action="#"> + <div class="tabs" role="presentation"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');Media.formToData();" onmousedown="return false;">{#media_dlg.general}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');Media.formToData();" onmousedown="return false;">{#media_dlg.advanced}</a></span></li> + <li id="source_tab" aria-controls="source_panel"><span><a href="javascript:mcTabs.displayTab('source_tab','source_panel');Media.formToData('source');" onmousedown="return false;">{#media_dlg.source}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#media_dlg.general}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td><label for="media_type">{#media_dlg.type}</label></td> + <td> + <select id="media_type"></select> + </td> + </tr> + <tr> + <td><label for="src">{#media_dlg.file}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="src" name="src" type="text" value="" class="mceFocus" onchange="Media.formToData();" /></td> + <td id="filebrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + <tr id="linklistrow"> + <td><label for="linklist">{#media_dlg.list}</label></td> + <td id="linklistcontainer"><select id="linklist"><option value=""></option></select></td> + </tr> + <tr> + <td><label for="width">{#media_dlg.size}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="text" id="width" name="width" value="" class="size" onchange="Media.formToData('width');" onfocus="Media.beforeResize();" /> x <input type="text" id="height" name="height" value="" class="size" onfocus="Media.beforeResize();" onchange="Media.formToData('height');" /></td> + <td>&nbsp;&nbsp;<input id="constrain" type="checkbox" name="constrain" class="checkbox" checked="checked" /></td> + <td><label id="constrainlabel" for="constrain">{#media_dlg.constrain_proportions}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#media_dlg.preview}</legend> + <div id="prev"></div> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#media_dlg.advanced}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0" width="100%"> + <tr> + <td><label for="id">{#media_dlg.id}</label></td> + <td><input type="text" id="id" name="id" onchange="Media.formToData();" /></td> + <td><label for="name">{#media_dlg.name}</label></td> + <td><input type="text" id="name" name="name" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="align">{#media_dlg.align}</label></td> + <td> + <select id="align" name="align" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="top">{#media_dlg.align_top}</option> + <option value="right">{#media_dlg.align_right}</option> + <option value="bottom">{#media_dlg.align_bottom}</option> + <option value="left">{#media_dlg.align_left}</option> + </select> + </td> + + <td><label for="bgcolor">{#media_dlg.bgcolor}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');Media.formToData();" /></td> + <td id="bgcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="vspace">{#media_dlg.vspace}</label></td> + <td><input type="text" id="vspace" name="vspace" class="number" onchange="Media.formToData();" /></td> + <td><label for="hspace">{#media_dlg.hspace}</label></td> + <td><input type="text" id="hspace" name="hspace" class="number" onchange="Media.formToData();" /></td> + </tr> + </table> + </fieldset> + + <fieldset id="video_options"> + <legend>{#media_dlg.html5_video_options}</legend> + + <table role="presentation"> + <tr> + <td><label for="video_altsource1">{#media_dlg.altsource1}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="video_altsource1" name="video_altsource1" onchange="Media.formToData();" style="width: 240px" /></td> + <td id="video_altsource1_filebrowser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="video_altsource2">{#media_dlg.altsource2}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="video_altsource2" name="video_altsource2" onchange="Media.formToData();" style="width: 240px" /></td> + <td id="video_altsource2_filebrowser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="video_poster">{#media_dlg.poster}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="video_poster" name="video_poster" onchange="Media.formToData();" style="width: 240px" /></td> + <td id="video_poster_filebrowser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="video_preload">{#media_dlg.preload}</label></td> + <td> + <select id="video_preload" name="video_preload" onchange="Media.formToData();"> + <option value="none">{#media_dlg.preload_none}</option> + <option value="metadata">{#media_dlg.preload_metadata}</option> + <option value="auto">{#media_dlg.preload_auto}</option> + </select> + </td> + </tr> + </table> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="video_autoplay" name="video_autoplay" onchange="Media.formToData();" /></td> + <td><label for="video_autoplay">{#media_dlg.play}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="video_muted" name="video_muted" onchange="Media.formToData();" /></td> + <td><label for="video_muted">{#media_dlg.mute}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="video_loop" name="video_loop" onchange="Media.formToData();" /></td> + <td><label for="video_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="video_controls" name="video_controls" onchange="Media.formToData();" /></td> + <td><label for="video_controls">{#media_dlg.controls}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset id="embeddedaudio_options"> + <legend>{#media_dlg.embedded_audio_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="embeddedaudio_autoplay" name="audio_autoplay" onchange="Media.formToData();" /></td> + <td><label for="audio_autoplay">{#media_dlg.play}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="embeddedaudio_loop" name="audio_loop" onchange="Media.formToData();" /></td> + <td><label for="audio_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="embeddedaudio_controls" name="audio_controls" onchange="Media.formToData();" /></td> + <td><label for="audio_controls">{#media_dlg.controls}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset id="audio_options"> + <legend>{#media_dlg.html5_audio_options}</legend> + + <table role="presentation"> + <tr> + <td><label for="audio_altsource1">{#media_dlg.altsource1}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="audio_altsource1" name="audio_altsource1" onchange="Media.formToData();" style="width: 240px" /></td> + <td id="audio_altsource1_filebrowser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="audio_altsource2">{#media_dlg.altsource2}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="audio_altsource2" name="audio_altsource2" onchange="Media.formToData();" style="width: 240px" /></td> + <td id="audio_altsource2_filebrowser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="audio_preload">{#media_dlg.preload}</label></td> + <td> + <select id="audio_preload" name="audio_preload" onchange="Media.formToData();"> + <option value="none">{#media_dlg.preload_none}</option> + <option value="metadata">{#media_dlg.preload_metadata}</option> + <option value="auto">{#media_dlg.preload_auto}</option> + </select> + </td> + </tr> + </table> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="audio_autoplay" name="audio_autoplay" onchange="Media.formToData();" /></td> + <td><label for="audio_autoplay">{#media_dlg.play}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="audio_loop" name="audio_loop" onchange="Media.formToData();" /></td> + <td><label for="audio_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="audio_controls" name="audio_controls" onchange="Media.formToData();" /></td> + <td><label for="audio_controls">{#media_dlg.controls}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset id="flash_options"> + <legend>{#media_dlg.flash_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td><label for="flash_quality">{#media_dlg.quality}</label></td> + <td> + <select id="flash_quality" name="flash_quality" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="high">high</option> + <option value="low">low</option> + <option value="autolow">autolow</option> + <option value="autohigh">autohigh</option> + <option value="best">best</option> + </select> + </td> + + <td><label for="flash_scale">{#media_dlg.scale}</label></td> + <td> + <select id="flash_scale" name="flash_scale" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="showall">showall</option> + <option value="noborder">noborder</option> + <option value="exactfit">exactfit</option> + <option value="noscale">noscale</option> + </select> + </td> + </tr> + + <tr> + <td><label for="flash_wmode">{#media_dlg.wmode}</label></td> + <td> + <select id="flash_wmode" name="flash_wmode" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="window">window</option> + <option value="opaque">opaque</option> + <option value="transparent">transparent</option> + </select> + </td> + + <td><label for="flash_salign">{#media_dlg.salign}</label></td> + <td> + <select id="flash_salign" name="flash_salign" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="l">{#media_dlg.align_left}</option> + <option value="t">{#media_dlg.align_top}</option> + <option value="r">{#media_dlg.align_right}</option> + <option value="b">{#media_dlg.align_bottom}</option> + <option value="tl">{#media_dlg.align_top_left}</option> + <option value="tr">{#media_dlg.align_top_right}</option> + <option value="bl">{#media_dlg.align_bottom_left}</option> + <option value="br">{#media_dlg.align_bottom_right}</option> + </select> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="flash_play" name="flash_play" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="flash_play">{#media_dlg.play}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="flash_loop" name="flash_loop" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="flash_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="flash_menu" name="flash_menu" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="flash_menu">{#media_dlg.menu}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="flash_swliveconnect" name="flash_swliveconnect" onchange="Media.formToData();" /></td> + <td><label for="flash_swliveconnect">{#media_dlg.liveconnect}</label></td> + </tr> + </table> + </td> + </tr> + </table> + + <table role="presentation"> + <tr> + <td><label for="flash_base">{#media_dlg.base}</label></td> + <td><input type="text" id="flash_base" name="flash_base" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="flash_flashvars">{#media_dlg.flashvars}</label></td> + <td><input type="text" id="flash_flashvars" name="flash_flashvars" onchange="Media.formToData();" /></td> + </tr> + </table> + </fieldset> + + <fieldset id="quicktime_options"> + <legend>{#media_dlg.qt_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_loop" name="quicktime_loop" onchange="Media.formToData();" /></td> + <td><label for="quicktime_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_autoplay" name="quicktime_autoplay" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="quicktime_autoplay">{#media_dlg.play}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_cache" name="quicktime_cache" onchange="Media.formToData();" /></td> + <td><label for="quicktime_cache">{#media_dlg.cache}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_controller" name="quicktime_controller" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="quicktime_controller">{#media_dlg.controller}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_correction" name="quicktime_correction" onchange="Media.formToData();" /></td> + <td><label for="quicktime_correction">{#media_dlg.correction}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_enablejavascript" name="quicktime_enablejavascript" onchange="Media.formToData();" /></td> + <td><label for="quicktime_enablejavascript">{#media_dlg.enablejavascript}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_kioskmode" name="quicktime_kioskmode" onchange="Media.formToData();" /></td> + <td><label for="quicktime_kioskmode">{#media_dlg.kioskmode}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_autohref" name="quicktime_autohref" onchange="Media.formToData();" /></td> + <td><label for="quicktime_autohref">{#media_dlg.autohref}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_playeveryframe" name="quicktime_playeveryframe" onchange="Media.formToData();" /></td> + <td><label for="quicktime_playeveryframe">{#media_dlg.playeveryframe}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_targetcache" name="quicktime_targetcache" onchange="Media.formToData();" /></td> + <td><label for="quicktime_targetcache">{#media_dlg.targetcache}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="quicktime_scale">{#media_dlg.scale}</label></td> + <td><select id="quicktime_scale" name="quicktime_scale" class="mceEditableSelect" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="tofit">tofit</option> + <option value="aspect">aspect</option> + </select> + </td> + + <td colspan="2">&nbsp;</td> + </tr> + + <tr> + <td><label for="quicktime_starttime">{#media_dlg.starttime}</label></td> + <td><input type="text" id="quicktime_starttime" name="quicktime_starttime" onchange="Media.formToData();" /></td> + + <td><label for="quicktime_endtime">{#media_dlg.endtime}</label></td> + <td><input type="text" id="quicktime_endtime" name="quicktime_endtime" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="quicktime_target">{#media_dlg.target}</label></td> + <td><input type="text" id="quicktime_target" name="quicktime_target" onchange="Media.formToData();" /></td> + + <td><label for="quicktime_href">{#media_dlg.href}</label></td> + <td><input type="text" id="quicktime_href" name="quicktime_href" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="quicktime_qtsrcchokespeed">{#media_dlg.qtsrcchokespeed}</label></td> + <td><input type="text" id="quicktime_qtsrcchokespeed" name="quicktime_qtsrcchokespeed" onchange="Media.formToData();" /></td> + + <td><label for="quicktime_volume">{#media_dlg.volume}</label></td> + <td><input type="text" id="quicktime_volume" name="quicktime_volume" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="quicktime_qtsrc">{#media_dlg.qtsrc}</label></td> + <td colspan="4"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="quicktime_qtsrc" name="quicktime_qtsrc" onchange="Media.formToData();" /></td> + <td id="qtsrcfilebrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset id="windowsmedia_options"> + <legend>{#media_dlg.wmp_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_autostart" name="windowsmedia_autostart" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_autostart">{#media_dlg.autostart}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_enabled" name="windowsmedia_enabled" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_enabled">{#media_dlg.enabled}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_enablecontextmenu" name="windowsmedia_enablecontextmenu" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_enablecontextmenu">{#media_dlg.menu}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_fullscreen" name="windowsmedia_fullscreen" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_fullscreen">{#media_dlg.fullscreen}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_invokeurls" name="windowsmedia_invokeurls" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_invokeurls">{#media_dlg.invokeurls}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_mute" name="windowsmedia_mute" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_mute">{#media_dlg.mute}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_stretchtofit" name="windowsmedia_stretchtofit" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_stretchtofit">{#media_dlg.stretchtofit}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_windowlessvideo" name="windowsmedia_windowlessvideo" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_windowlessvideo">{#media_dlg.windowlessvideo}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="windowsmedia_balance">{#media_dlg.balance}</label></td> + <td><input type="text" id="windowsmedia_balance" name="windowsmedia_balance" onchange="Media.formToData();" /></td> + + <td><label for="windowsmedia_baseurl">{#media_dlg.baseurl}</label></td> + <td><input type="text" id="windowsmedia_baseurl" name="windowsmedia_baseurl" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="windowsmedia_captioningid">{#media_dlg.captioningid}</label></td> + <td><input type="text" id="windowsmedia_captioningid" name="windowsmedia_captioningid" onchange="Media.formToData();" /></td> + + <td><label for="windowsmedia_currentmarker">{#media_dlg.currentmarker}</label></td> + <td><input type="text" id="windowsmedia_currentmarker" name="windowsmedia_currentmarker" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="windowsmedia_currentposition">{#media_dlg.currentposition}</label></td> + <td><input type="text" id="windowsmedia_currentposition" name="windowsmedia_currentposition" onchange="Media.formToData();" /></td> + + <td><label for="windowsmedia_defaultframe">{#media_dlg.defaultframe}</label></td> + <td><input type="text" id="windowsmedia_defaultframe" name="windowsmedia_defaultframe" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="windowsmedia_playcount">{#media_dlg.playcount}</label></td> + <td><input type="text" id="windowsmedia_playcount" name="windowsmedia_playcount" onchange="Media.formToData();" /></td> + + <td><label for="windowsmedia_rate">{#media_dlg.rate}</label></td> + <td><input type="text" id="windowsmedia_rate" name="windowsmedia_rate" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="windowsmedia_uimode">{#media_dlg.uimode}</label></td> + <td><input type="text" id="windowsmedia_uimode" name="windowsmedia_uimode" onchange="Media.formToData();" /></td> + + <td><label for="windowsmedia_volume">{#media_dlg.volume}</label></td> + <td><input type="text" id="windowsmedia_volume" name="windowsmedia_volume" onchange="Media.formToData();" /></td> + </tr> + + </table> + </fieldset> + + <fieldset id="realmedia_options"> + <legend>{#media_dlg.rmp_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_autostart" name="realmedia_autostart" onchange="Media.formToData();" /></td> + <td><label for="realmedia_autostart">{#media_dlg.autostart}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_loop" name="realmedia_loop" onchange="Media.formToData();" /></td> + <td><label for="realmedia_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_autogotourl" name="realmedia_autogotourl" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="realmedia_autogotourl">{#media_dlg.autogotourl}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_center" name="realmedia_center" onchange="Media.formToData();" /></td> + <td><label for="realmedia_center">{#media_dlg.center}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_imagestatus" name="realmedia_imagestatus" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="realmedia_imagestatus">{#media_dlg.imagestatus}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_maintainaspect" name="realmedia_maintainaspect" onchange="Media.formToData();" /></td> + <td><label for="realmedia_maintainaspect">{#media_dlg.maintainaspect}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_nojava" name="realmedia_nojava" onchange="Media.formToData();" /></td> + <td><label for="realmedia_nojava">{#media_dlg.nojava}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_prefetch" name="realmedia_prefetch" onchange="Media.formToData();" /></td> + <td><label for="realmedia_prefetch">{#media_dlg.prefetch}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_shuffle" name="realmedia_shuffle" onchange="Media.formToData();" /></td> + <td><label for="realmedia_shuffle">{#media_dlg.shuffle}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + &nbsp; + </td> + </tr> + + <tr> + <td><label for="realmedia_console">{#media_dlg.console}</label></td> + <td><input type="text" id="realmedia_console" name="realmedia_console" onchange="Media.formToData();" /></td> + + <td><label for="realmedia_controls">{#media_dlg.controls}</label></td> + <td><input type="text" id="realmedia_controls" name="realmedia_controls" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="realmedia_numloop">{#media_dlg.numloop}</label></td> + <td><input type="text" id="realmedia_numloop" name="realmedia_numloop" onchange="Media.formToData();" /></td> + + <td><label for="realmedia_scriptcallbacks">{#media_dlg.scriptcallbacks}</label></td> + <td><input type="text" id="realmedia_scriptcallbacks" name="realmedia_scriptcallbacks" onchange="Media.formToData();" /></td> + </tr> + </table> + </fieldset> + + <fieldset id="shockwave_options"> + <legend>{#media_dlg.shockwave_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td><label for="shockwave_swstretchstyle">{#media_dlg.swstretchstyle}</label></td> + <td> + <select id="shockwave_swstretchstyle" name="shockwave_swstretchstyle" onchange="Media.formToData();"> + <option value="none">{#not_set}</option> + <option value="meet">Meet</option> + <option value="fill">Fill</option> + <option value="stage">Stage</option> + </select> + </td> + + <td><label for="shockwave_swvolume">{#media_dlg.volume}</label></td> + <td><input type="text" id="shockwave_swvolume" name="shockwave_swvolume" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="shockwave_swstretchhalign">{#media_dlg.swstretchhalign}</label></td> + <td> + <select id="shockwave_swstretchhalign" name="shockwave_swstretchhalign" onchange="Media.formToData();"> + <option value="none">{#not_set}</option> + <option value="left">{#media_dlg.align_left}</option> + <option value="center">{#media_dlg.align_center}</option> + <option value="right">{#media_dlg.align_right}</option> + </select> + </td> + + <td><label for="shockwave_swstretchvalign">{#media_dlg.swstretchvalign}</label></td> + <td> + <select id="shockwave_swstretchvalign" name="shockwave_swstretchvalign" onchange="Media.formToData();"> + <option value="none">{#not_set}</option> + <option value="meet">Meet</option> + <option value="fill">Fill</option> + <option value="stage">Stage</option> + </select> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="shockwave_autostart" name="shockwave_autostart" onchange="Media.formToData();" checked="checked" /></td> + <td><label for="shockwave_autostart">{#media_dlg.autostart}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="shockwave_sound" name="shockwave_sound" onchange="Media.formToData();" checked="checked" /></td> + <td><label for="shockwave_sound">{#media_dlg.sound}</label></td> + </tr> + </table> + </td> + </tr> + + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="shockwave_swliveconnect" name="shockwave_swliveconnect" onchange="Media.formToData();" /></td> + <td><label for="shockwave_swliveconnect">{#media_dlg.liveconnect}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="shockwave_progress" name="shockwave_progress" onchange="Media.formToData();" checked="checked" /></td> + <td><label for="shockwave_progress">{#media_dlg.progress}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + </div> + + <div id="source_panel" class="panel"> + <fieldset> + <legend>{#media_dlg.source}</legend> + <textarea id="source" style="width: 99%; height: 390px"></textarea> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/media/moxieplayer.swf b/src/core/static/js/tiny_mce/plugins/media/moxieplayer.swf new file mode 100644 index 0000000000000000000000000000000000000000..2a040358df0d1f8eb784d2ec0919626198d6eb47 GIT binary patch literal 33931 zcmV(xK<K|iS5pd^6#)Qv0qngAcvHpqH-6{lCO1jby-hc|&=v|^lkP20nwF;QAT2wg zq-}0nXq%FxrR)_%P!=}?7eod5q9Xeuihzm&3QCG>0*ZhFf=CoW0g?C2+$1+GrGCZV z?|I($|NQejx%b?;XU^<rX3l(OZX?B<qbQI6P*fnIdU*#?6gAWL0HUbwrgAQONH1+f zV@-9fIUAmO#8g@=b=gTtlO|0{oRpGiG*u+2v$C?1RLM!n$qB%bV4hrS(Kja4nxkTJ zh=5)ObD62C&QfKpjlcr+rN(+okC+&{)bcW?(7Jk4H4#}}mSm_l)EH_l<|K8Z8U&S> zWphSTjoy-@udA!BD$`?eNsS5SN@LlCN%{su0#~g!S9VVl7_lEqm8IH{qbWC*8X~mS zhQ^502#w&MaPusfxm<{7j!QE2*mq)?u_md`WGt^QgE(;@ig<SQf<@HTmsVGqD-EWc z`q~M##!0n=OK`<JWhR5(Vr<FbaKrDb^|clC`U*o%!9e2M`Ap)dw-|Ez>T4s^De)1> zDz%!A26pY9gmc#=x9u)afH_pSSA9^lI(o7uy4MiRNR2+Zv2x^q>PZ6{HHOUI$%RRj z)pNjsAHLg;QesD5eE#f^C){4^<#kEaoyw>0-McqRE`mxSfj@%|=D-bp|Jm?LQvy_y z!}6l4n!0Mk0Apj7VQ{s6vcW{%^B?3*QScIe-FrgqiD)pG%ur%IBGrki$OuDinX$a8 zwxUPm&|+;uW@OJCcX{_3EC2{uce7=3wIQOayhmhdy~Sdzjf|L7Rc@*55t$5rD-Bf@ zl@_4WA|ouux*n0>mek5y9YmwVY=K;fj40KYO{g##>uW(=vMK_5yN_L8Z#J~W-!^-L zvAVv-P*PvlmKO*jt&JGj{ggwMXv<gIp1AtzYG^wK!vp-NRc(Y+i<?P1-XMZ)`m-1s zEs+tNu@>@nn88%8uhmCJn5(83pv=^f5oN||qp3$^l$QJ;TaDF_p%zm;WHBj*6ySzN zTV~OhR)Zf7;sCEmR^u|QF_!a1%EvD<M+UC4?zm*?BJ^drIroSxgV0UJYO}MzA*P*L z7P)J2sv;o$CPN*xCr4DO4II$mTxx`xQ$wl=t{e~)UzZ|C<q~R^BWPS@A|rV3YE>lf zN7fx8XZPS*r%0->Oe56mb{TMix64pjWw98{mUei$C-E`=?~;M5vP(K58mi1yE(Ov? zx?C%N+X-uvqeaTv<Y=9=HkewbjV~wAvK1zS*<7kOIV*;Xo3m~tB;$tWPzPBpTY8j= z{OolzQ^=7tXVJDLzm*V2Wp`$atDn+(jx(5A`N$_fd%cGWg8K|dYWTeWZz?0NE$Zu_ zcJs<EO^CKoBk$8g&S<(;%LjA0mf(ZAT9x917~3kz_FEh;2}i<SN}y#N$xV&?`-*Fi z2^Qc`sqJMzn|y6#L7RMSXF?mS|2!K6CGSjrN?ZCz;A=Ov?XbBfwjH)sX?-APTS>*8 zh_lgJs%i{|YJHvAP!4?q?$bd_lU{~bv#HR0?HzkMkoxMX3g`n!6%ZQGeG;+XR^sfn zMveP+hd@U+4^5EtF}U&Jrq|tES5;dJTHB%ctBra*6lvLxp^t<@;5)XOs`Bz`r%o+{ zK`Cza_Ha@`wK!BzD(E0{oxuS8qA&zV!X2MIaG?_vGWEag2vc!pIRZ*+rR*TKS@628 zp3o6pM|Y^ka!ioodUKCRXFdA|eWODl>GLz3%2d!w{}1+)jx@FEEBWGYGmUL@WvvDS zZF0D_z`8a$S~b45nA&Q0F1?JiV!OCGt7~#5v<pWyYE_F`cA2=I@XgeoJC2cqYZvGU zqGjW8juD;e*wxSfdbf!)*%5bWour~>woy_4Khl5j$-rX;zPK`z|31ya)Wumu|4$4V z@Z5o)5ZTiRwb`!xQ`#CKwKW%NGsW#Py0+SO8Cx~pc6i%r!{+L$a+iLIFIV2to?3Of zqmZGeYpXr-exS7pjT~Bly{p1~lI!fr+1?%90Ze=N`5K<tRO)M?*K;ZpUUIde!BFiK z=+gB8=_)!oD<Tu-gZ8ZMp2Vkuk1;>~y{}tuZ=ir9=IGaf<fog?4qn#%K4A|YBV>R# zhbSPOqS_jK{9iJ1=ng{&Y#He(TM0%Lni3~dzoABSRabTJm9Lb;7M48z<;u5$O+zpK zcqKRb6VIOWdW{O`x$fn-rTre;_IUUw{e9nvoaa;USYY1bW54A;*ZDtQ*9R9p^4OZ# z$H!kjtpDcjJIgPQIP=%d9cO-5l$^R&{z|#w>dxg`k9~V(@|oY4T|0I0n`_VPym_); zw&u&MiyeMsvTmLzTjl%xrIk-D8Tj<dMcI9`HH*6c+WW<Blh(aq`TW=dW8xr>xZpU$ zt39S}JNRNs;gD>@guNL{W9IrVe16lU`uaXG`@z|;cR|pzhr5nW+4WxctamEkSv>vo z#a$1}lB*6!|H!<k($BKY>d<gPe^_R+YS=!j_dm*py}9+1;2WQATQTFycSm9$q1y&N zefRe>CD{eqr^42@dO7{bn~$8^bf->b`o8y%enINe$By|-I1+H`$=g|HxQ#0|4!Nn{ z^Y{}7e%|wu_4WK!qH@ofS)wm<yNWhVJg@zFOI1<)#BmEI+<W)Tj4Nk<zjg7|18K*{ z_@0`&BWc3%b<eNgbvt%R<LSWTe=RMU@#1fHZX7Q$eDi+2>FChmpEeqA{IK~@&R1&n zx@Q`@&p&#qWZEwUp1TL--0Jm<arfO}g9p7iblnHPetu&8H+RRbnZ0bo^1++O%((T# z)#W{}-<T3QvB&lqi93HAvgl0W&aW=dyYf-}<X=7w`2Fkb5r-z7nZEkC=jHcoAG?iS zTd_La^O)v~DLHq4`)b(uXFPNM$hC#}_F0y)ck8|8!tfimxcy5PyjzxY<4DoOb=up% z-aKVIaOc|Y@P5mpfaB*K*KXRTURnF@v%8*9A2EKt$uMydcl*~byIs4aMo($ajd@a^ zXgj;?+o{)fhRyiy)9<@hp8;}Wb=>r|=l6K_T-^KIGWEK<g9mx`wE6sS`PlAjyY8HO zq2aeq%R+8UJoe7Wl~-Rof4X$T`!m1WIk!ZU^WMF`?v$NrxCyU))(!VR=zq01^tX-K zLkpK(gHo-$IBmY^$M^pFWnXx|=#9INvEfHFXNq@jZ)ocI$9J<QF8cPT`O{~fO<Q*E z>#^r;v)@>EJ-uZ2&XGGVHb|DCiVuV8@U2O)|B0C8U7qUs*Y*xG|NLdk)}niEXXbam z^V8<52VeZW)Ab8qe0AgCjVs3w1XV11=GUrYHxG5pe>}d&@2Aa%J&(J8aiPnTn@{hD zQchZ`YY3Xw=}%*#e&_35);)5kr^G#Yi{I~^=LT=s_I2g7FH4rsxLtK%Vf@HVy=MG% zt77D?X<6sKUzqXj(-&WznX`1IV(NFxr~dqC{LUN4Mvu(zcID~k<Ax`%|MJ%3A+>|2 zAMO+LnP<;GBjzg;p56Rqw%dd=2J;tZZ`4<;>w46Z_#ee{XJ+2pnYi_QzuND&9v^#t z<1?%JE&cpJ((VP*vY&EG-2PhpB=50XwiSP0^6A*U3)dM>n+_z5==c4-vR`jsS%2W% zr}Ni*Kj_wJ|6@0<y?^e>xQH8RuY5A9ckH(P!}c!x;P&M;vwrz_Yhu#Q-+X@EAGiL4 zk0<QzV)VbWWyamx-%LNK-gjwA?{hOx#b#als^%59d%nk+?H~McZvGAPkC3fT*VVk; z^Vs}>J#G|Vs4O^i>CEnX-<+8H^oab*^!3XoeLHzc$h6vsrDIS15q9?b=LRi#*|;m{ z;?T`yZ=4(K_U)OX5u4NRexN#CS@XxAZfE8kIo@H?x!>!)IQHoF7ecbmKIVI5(V;~r zrw)s|HEC#k&Yl~04sW=*Wz7Zax{0gi9Gc(o#YfjOMPD|he5bJAEQzA`U-g|D=h@@8 z!LkW;n-1mN*$=f;*XO(Wfj>>%Gxk8ljwic*^VJj66Gak*HS6rRchBybdwkCH%Ypf! z^9mMi=(%NlsOhs#OLO18z4X>+CpMPV|8?TI53@|+^qq~|fMZGT6hsdHy79vwR?JU) zc3;@k{++h0`DF2}OF5oLo_@CRub(z^dp{g|>dGV8-+nyD?T6RrhCO@AxLYT_IxcR0 z+@2eOPao&fF25PN@^s_-$Gm=C+Pu~Kou>wmn=nzA|CH#<iTl6%X!e!hnkPTKG$HN$ z$G?1bY~t-7S08}N^QP&m0U1ZrPOg5XVN~Ka#aBC@{$rPD+K|n!oD9!f@RHi9FERYs zxG!|lvN1F7-Y|VrfBb0uhUY(h{;bLN5qo9o!dFr*?4LYq(w5h+F8eWmx5y(i7gTFe zdRW~@FBwM6KU&{xUFTDDVdb5OJ%7A^NO?y#dELJ2-%qPauoWn7Hb)ko_<clr*u)(3 zW7Chj<}}Ihrz>)2{Q1kiuwM_R9QuCclaJgD|MBvg^@%qxh4$KY>%z;mhd*8(^xn;r z6Mg_a_{hkOrJX9`<A%L6ZpXWpX~uzZ=l9PNyIr|ew|mH&;xt>%s$r(3pB~%y!`<O$ zyT{G{?Ckq{_l|jURlv{d`z>5w|J|-`(tXB?gqrP132E0(bY3%T?TP_o8_$Z@il-jF zw*9=v$&jO_Q#J1%&HB1e{U_$dF|SVB^!%0N)A!ywzGvOKm4&(!Zs9*a_vF>-ZzXM? ztNQ8eQ1zXApKb|RTlld#bjtpyr@9}mT&}%)<FCS>2JM-V{qt4#tJ>?<-80Sv{=ReT z_H73~7`o->n7wyrH!c@NLy@nV_S1~PHFML>EG{vAZ8=zH47=F;Q|9~o{3my5e0<N! zr*ckK@6w)&{&VN5saap_I-)(dcKwBq?q2o!KEKDChO-|R99#cQ&E!AM&b{&1bz9cT zSCgz4QdT$r^6{BOx4_wV&R)JV2I_6kEjwIQ*oQ%vx=WPHCSQ1Q0;rJp5{$cUb!KW# z+#a&(g=^ZM)_?TU(eRmnzV35!!;Mv=KHPaMqB-se{m%LhzRL=yC{`qo6J4lJJ@nxR z8+K2x8Bucj$%-!G#MhhW?(A~q=Z3NRbuZf#QGcFUaPg_yGrM&4m-dV;?ziUntxX#O zrigB?eq8-pbJDqYo(%n9g8MI%7tMH6-1tb?ky+;tU%Hcc;RF9e9Y49={oR^Vl7%zk zwqAPgvGY$)5qGn#$bM<-m5I6TH~nvK$avZJ`0VBV(qm3#?wfLUXW^@#&N)A><kGtv z25l-@R2X->aP!4n<CyR-c9o=!7M&m5uiKgRPX}!MZu_OIVZU6TeSP9p+`4mj1YO#F zarxAB@<Y@&3odRs7qnVqecXM-j(t}aPJ7|v`$yLdKfh!6tshsv`u(Av_lh;$PBh(^ zGwQ?lj*YvweB;%@ZqugB-lH`Q4DC7N&&wO`U7C3|MKLSA`rzvqeYPh}5i4?jJ2N!+ z`mu@$wyz7%W`%5+m@}ovcVl9wAh+XgcPBl+S8c7xn7I7)uoIcD4t#56(U)rmzV~If zAEpN!myQ2uVzc?3r)GHkI%U#T#ZUbuOCGD3v)1#_%2UHe2h7oi-+U$OsbPCR-nu*V z_l48%-Ti&j<m;U7z$}mHCnn9^z2o!CqBEmJe=YB`b5`gdKhGFb_w%KRy^rRO&P=q$ zoqxl7+Qi26rWs59XG|3Z-_@QgE7=)V=kdc>G`FO~slFu>KKyp>+R^Wp-V@zk`~87+ zS2t~&mG<q(qSXU+GcLX|sWhQx^oXT%UULuGaQcJa#tuBv6ky3r%(|ESPV@PX?giZo zz4_a{fJ1Np3Ee~e)tLvDB+wrPPuYNG4{HA7YEIY}W5T~1HQ~dQ`uStA)5NOZZ!{mg z<Nswy508R0YuF;UY4aEL*>QE@j2V|sn*Iz`T&%61f961HQOqK@FV#E8ethp4>!sB> z8Ff9bY#n!T+4#9v#Jj#YSW)qbrElnt>ywY}pLklg{<?O2ld;>klR`o_zx(ItyB&U7 zJ2~ySfPLbNBT{BAO-)(8Pf+f;XDV_p%snHY_2=}zx|%-!;Fd{ldHUAL<t6*p++I~$ zv~ANbCNom*JM>DA!r}{zyMA}?;Wy%*T)i`XP;KIZv>bEZw^^Gju01_cbDX(Rxnt4r z-`sxbQCgI~;Kh)nxt%U_TQgzF!ONGQ{aO>1w8j725yOnPPDGBb{UG**8!x79?iUd_ z|KzqOibfyYR@69jbgXBo{*eCI>bO59&AG@<`r?JR>T@Se@LipFeRE@MXG6bF#w{u^ zchnB(dHKb!Dvp%tUk-Zgg`-3N9I|m^!qU}pZaUZh<wU;|Uw`@I+cVzl@S$n)+vAQ^ zOxe#qvG0wAne{J*+cLN9=gg~0=Uv?J{-GmP$?nO9xBIWJg4(pf8H1<xKA!c1>Pkx5 zA9>#y=cJ!Ia*VxtV!ijvUp)VLe)qY}6~Dgm8U14R<R?F0{Myi2?k|DZlGt=Z+yT*; z^RKOZPj&2e-3;5DZ*G3Q?foair&TLXZd{A=Df?dKuID-r^m$(9Ye+t+S@YP<UR$0h zT6*hf>HD85PngaR{irnj*dyyZrmcG`>dMk56E=M`@QKMQclNEey{MWo>+?@uTWbxQ zaAkIbeEs;%?+sCZVh)_XH(Wh7TeB!|(qp-MLtal<g$rx#+IY{2A$!u*<4^1h&8eOH z=heEPfbVTDeYmJ0bp54$f#YA^cTzR1;e*p-#&1jydoQi$hLfkO`c;MQo>dZi?BwUa zet%)bY3=nM<p(<+K3-m3`ejt%0>AxlKC|-jePy)q(0=czEs{m2ihNgp`^eOduYOvj z?mBv;;+GX8PRv(*;<K9DHDa~x?ev%9{PRBu3{iLgv!RbyUB8-BpS+d8o$C6*+X>IJ z8#i23UD>?n-Khzmymc>o><=>*ysnKub!6khhVhH$=F}WfmM#443e#iSh(89bc<HsU zZRYpiE=goJj9CtKNAvRZ@!cd7$It&7=SjaGH1R)W9lULQw=8w$g#F7ZK0EpL?X54c zyYD>Pq2&6{e=JPAvT}Dw$`+;Xh5aLLd#xVU{XE-!QNpIPzgIrF_kcbsuuvCLbaCG8 z*{{@mxnp$CKVB>OEUE6RsPs)g{963clt0GJIQ#pvj~`Dx`GRQXfz_v`eGWBFyzO-3 z&<!UFFOE#_d1S<@Z)auw{@tqb4;mLODJnhkUFi1P<NoYDZ)E756CKhALDk)S%hc$x z*?g(t=NHVM?_H_8P%*ip`k5~-l-7peYBhKFQ~ybGm+k&~Xt&P!6KZfXQ4ad_jq0}o z7rnaY{acSsj$`%TZa6M(_zl`h__-tL|9SF@3!64p`&NX%R8yKZV8&&0dc%o%P@~k3 z2T!an`ii^QYxMLEDQEHy-u^D*_N;M=xGkE|8*{SPkBXljyz%QXzcdb2-`+Um750yd zAAJ4zHhS3$HD9d`8Xem?L!!RyWt<tcacsX2Z@oP4leey<MHGI#-W!^1-@q&DzsSF+ z7(F2K;^O~!S|H=&4&--#{;9yNH$J+y%p)vy#A{naFZB6lUU=D?-Urg_zgZHpp5`vj zKfO4z+r-On&-g9r@O#~ds;<o5c9Z>UsOR2Qo)a%?I)OrXV{Km8vG79$7rj3H>fJ?X zwdd9>Zk4?{Y<Ydq>kG@8zYH9Idt~=5tVf48ha4KdM?aUe=(0C!mY?9vBYSRpVzcKL z>FUdmis)g{^Wr{!r^gS&j}BWhw=p(+qsL*<&5+l2Kesmc>SD#4U%yq9Q!sgmy6ekd zytv0aV*jJp*)&`C(r)Y496WSxLBi%$b&%zy;fs#TrtF^nyKmf^vb)>UujDT~xwjbd zEqzJNxu5bk4_GkejB2>__OZF3Aq+D<JnztHA6-k%hbi$l11h5i>MoE<_Vt*z0?%bF z$hmv-QcP&X^m~iy*4yV!|NqS~i~QF)abkMVA3gW<G#2jmn*$gsjDEQv8RJDIQuJVo z`W|`T|5B4Q)C@S8r1AQS3Vl*h6#xU0Y8tDO%miSA7gh`=jJ!%Ro65R%yU%~3-t10L zP>JPLX3Q<=4{KWnlZ<z)HCSXrhxF&&I^5^Gq-a7_ZBd;GLX`_-P}_VX2J~k!6Wk?u z0Sy8H>=rLt48WTTkb$onyrw5D9yGY5e}T4GOss55z-&$GW#IJn)s}n!e87s}07GrP z2k}r;rpHjCa)Wf>ppv3|P5%O!+2O>Pj7E!`53WxwXO!3JP5K%GEXSE8W)g9aO1*i| zq}stIW1YcdncUHi;t~*Cnxd4XWR)r%AQe^Bma1A2V3WKt>I7Ex_}F8?;(`WvR`A&d zCQpE&N%IE{7~H?0xWI=G2{Y##G49D?@Y0u;6CeGn%pk~MQuG;AU@{p^#8KL3P)Wg% zA%li^2|l&@s%k^I97<z|VPZYNKa}@nGZbdD%CALnX7i;J-O{laU)F<4#{>2T=cm33 zq7dGasSjSX#4DZ+2A(mb<@**wI`HrKglCgP;P-k<835ZPynhB4gRiqX_0n7PT7u7G ziVH>*%gde5o{+<?ndNSO=CdH`zH~#iZ-piklZZ$xdQ*kL!rBW<UR7IVse<}6#Snj= z4**?MH30Z4TgY)oSuqX9s`A+X#s?ok?^e-|R*9g_GdO*+;>mReQqIWG^}!Nb36Pae zwiq-flYX)rpUw4_s%o<=&*3VmHq=&FDir_{EC+BLb~nfTt#m%J?gI_D2Gl}D063Kh z8a&P}{3wGrMHY}*BQf(gesRK!)CtHcTyZe+O3p9O6~ofKco?il811pFF_c&7#SPfS zQ*W{8%PO4`y<1m*bM%AbD-@eM5!R=6Fi~qFP#+RN{Q$5|T4f%L*G9`_Rpufv(AOEt z#bh0n8KAdRN^u3iF_o6rn+OV2%vBqWCdO<qOpt@NOyu>XyCX%U{z~}u3y&g<11vV_ zYt0x<>S1p2C^H)@!w9y|6L6gn$Yh5MZ=##*jRa_m!A(1~e}7O=LkbE8D$4mLNM1+= z4jM8*)8B2tprJ(tp!GDv3KW%)Z4OcL0Y*q0iIkk@888S~uugQa__QvRXcdD|1X2fs z+>CYWaEys`BV=!aiIflSuNhgA-@i|OKexde96X^t1`iojIHaJch<|h+HmLv50r0N3 zW?*4~2mds5F#pnvf9y4A_&~b@PA8vCy8}+2tAmH8SFeIzCB>kwi!~q+rv#U29)WIp zl1E&e{Ie7)OMYclb-4tpBfu`&X^O3LfdN&oXR1IyGk_j7_&O_KA`UJQR~0eTAcMt& zywO|g&3ravutgDpQOX6}g_x9s)ZPZG7#vSet&@}YNxB}=3>XY%VeN}lZnzDbu~q{m zPUvEzMPJSLgyp{Xw+EHnSUUh>kJY54thx$%6#2k{Vw_{eLyO!B1{N0#DbWtm3@C_u zaMQU@teDh)IcZ0HWgsM98ALTzwPFH$6_fQY3BT$O3rCY#th*ua<&Lt@SlVf^E_qN3 zy)A>A*Ztj95|+t;iZ-(xWXqs>OXmlt#I-$0FngcccDP-ehOfy`11r^}bR4}cYj3P> z{5w*++R?|YnzlF}aN}liK~1TlTmt&QRA!KxVPun7S6dNKQc__ou^3Cr4IEKi#@dof zLv<a)LHC{e4+d-ZcWThRi|UMKQI<ND4-UEsX${md+^Gb*V%&{o7K0^$*V>F)rOuG# zRat8EbwH=7;gXrbsMX0TxTK}PB{PjtC##d$JfpGNps$68G;m2#0Ygek7E@nUYXK@V zSu(I5l5Aqssp?cFIW;wfNlwd9Gs)?h=}dAaP${Z(6_b*hk-?;8sMJh)W}1r0NXyJ* zGSaisnT(9gWF{jsJww6|N<2xC2*U(-yRzg*3*PsQKa?%rW5q^>Egc*=UIqyH`?6h~ znwBieOiA+>BPFAhC~0YkGF%)JKnJ2=6x=1aYjA9ETyT7Ff-+zEh*Gayh-i1jh*_yj z?xt|}@br2Sv9y>Ku`DBHk&I>JEOKKR50>_1884RcW*Hxr_GKAAmhop9CCdb`OdyMb zSaC3mI<QPAD+yzn2o`l@nMhU=#WK+>>comV%YqQgB(kC;mQk^cnnlShN|AK{$8?zj z$uba&GFc{@WqQbRz_BOG<g(H<*1H$W6tIkz74>FOAC~FMiu$prKZ^#k%plfhFpGw; zOc9HUSu{*G96XL-(MT4JVwuq_GlpeySfpc_u`E-<GUHg^QWll5KIJT9U>S}@6)auJ zGF2=yo@FMmOf`#YSV=9*7+F-u`kGnB!ZP(N)4(#5Sf-I>CbP^GmYK>j(^zIY%gkUA zNS?_uO%U*-h?SaHW)_l-g{K6TnS*4HBOvD?R`LYgpG2(R0=O@N=cgdKPXql7{GWyY zbMRjb|L5WV0{o#En3v%H3jCMD|5f<E2LIRLzXJX%;r|BwSHb^3@P7;b@4$Z@{5QaV zBm6hPe+v}nM{wT{|AX-V68_+H8lvzG+`onY8TfyPI^cD4ib|zWtTL-94aHL3<{^aw z2&HBgek>%9RP0cSiUm&iqu9PQ=4^d+yytnw&qhz80my`6tLdi45Q?oMo-A<X8DB;; z6}uXNxbbhJrZ*84yB0l0#jeMf&3KAPQ=wZC+J@dm+Y$X9+JW9jAE2#>-iCIeooKh< z`k_F6ERcHy@)LplR3P^X<UWD?OdvlO$O8iTg+Lw>NUK0L3*=#e{7N8?2;@<LJSLFG z1@eSIel3tE1@aU+>&TsRg6nyNo<oa~Oh%y~CYM@-AUBbOCuosRF7*@?GGhF4sW`Zc zQ*)^lc%P9=rBjIQmP=(*NUF`HM#4*3PA>H{lFN}?g9$e`<d$bA6#a6kXAlx0cSA1q zEEJ_jpoXH6X9o=>LS9iC*c0O&t)axor>lmNAm2<4<%RruXefW=U$3E*NExo70#LwE z4eYN99HF6tP|zR^1sV&C1R;=uUJ&n)4jm|jq%x6JRS3=^kxagl{zYU<v#KJR(9wt{ z`k1YwRVU&^m5eRgsuOeKN{KDq+K0M^6ja7F<c>0ISvr<uby7~s$@FqtHhzlHyV<%C zX9cI=-1Q!|9y(9Xlk?)dt(=e67d6B-_;^uNSHaZ}yZSswQMMc%>We4{-qy33^Vcak zB^O}j0<}SOS6eQ23Fd;i5G&V#xM-Snp$;irSl>{j4M$yV`8v8UP2uSGI;@M}BDjwF zNL#^Shp;H(ReRVWDw;eO9(EDc$u7#v1ESQ&s_j5^we_`Xqv19X@`|QunY<%p)gxBb zHIzm@Vk@#XbDg;uu1lqlt=OvV3XDU6QG^-8fN?m_INUbUYVFHVz%`2J8Vy{Gh>?31 z0hi9I8XkKLM0Q6y18S~8Sh&tM&Z>(uplSpm#P^Lum3}ro@43_~kfN-r!>UnK?D1Gt zTn)07>7sEoL!}~{p%4WnXC@?~Bnl}hF$3kB3V~GcQK`6w@=%qn%Gy^#HK~r-#zP>7 z4|8g5GUCISz=u%{5tN9KOg;(x8m%hZL@30Fcc2WtStvs*=LZiyuvg1wDzsUwx|F^t zRAs8I-pZv$Xw#rH8mzi>c<7ssDl=@8t?>i2nczCj%4I~$^;x#*RviF(sLF1(8CI?v zxN5t@>n3E?_JB-$6hZJT4XvaX1V10?a=4r&J^>Kg0;CIf7JW}#?p|)-{4~;KfQ(%5 z`z#u(iK*1so<n2vVk+}&i?J*zmK6lDUgR0`f$=3^><o-AV+I*R%jI!6<Ch~~dyTN^ zdU3s)xq|5Ol{zh_<qB75dn0Whi0A9ri`?nu4eaGVXly@VuIy)9&3o>z>&Nv2zkT~7 z{Q%pW*ozwtp#<Sj-o{?uL0E2dxppAPT#FeLPKNcEVI$8#5r$2e!5t?ASFLxEZjg2m zBx5^t%+MAGbA!1@^h0d#VJ;5`*DeRwZh@-^xIV;Oo+6N?0$F?cm$=mx>xObeNz2&B zI}YQ9al>^ZxDmv0KlbOvisXtNSZ6$j994HBdJNg?u8DdK*&at$-AG(}q1r%Y!BON! zk?ZKbBgK_k+Y|6ctLw}4<;LW)ST=}T>U7iPO6_jToo-`uWp=kWoNgt#a=Y8xPPcKn zZg#izPB(q7!tS=!=~kNSZg=~@=~kBOVRzd@+;EnZ=X%=R4q!JcXV4eg4)SC_QZiq{ zgT@CdjYHU3%TZmu<nYu?o+_Y_zCyZ6{H78L`UvD9s-n>N0mz#X$>ovPAn&MCxV%r3 z@*Znw<|f1*t27*z(h$@)IM01>#ps4>&RNWO9yN0{Ty6YZ<QD+}eGhfLGt~7TNX?6; zNF}{MglUZs{3R^H7mFBxMO?umu7Ze(K43n!{fu;(@$(UBpx2OYgmwhPUkNXM!7uoR z`zz9!IFr^4!fv3kIWd(vwwqX}AFf0BAns43tJl`U>w8F-$K@^Y=>h_pXk5W@)8rcT zlWdO)kB!7}^2+G)75XW**))jq7twMB2cnLXT6Gi@;u1t1N4ArYjT!MvaimY7T<@Vs zKh<^?yXoq<I&NC7kG*)V@HN)LS-3}XeeI67kS>UH0n>B+>`ss2(3A}5=x1;xo=aO* zU5;Ku%MkShZJSSnKH_FXQ|qv<6BAvR)8NBEY8KFiwx?*U6!_{)7+3O@8q+gZYMT&U zf7JFYmVx;QNAn8pqX_9|A=`7V?lbM~vyp8nEeM>2JUT*HFF06T-@G18uOzadfxX20 z8I6OO&HH(|g&+GHr=K~<_6jg)WAu+B+j3er7jm#0RF%01`q<ZKYiB6Z*Ky7S;NGhX zWXv0oG1m}`B;TNI|G{26W3Q`$%4pWkLr|69#QcGnKLYsI5dJlYT0`5`V*XC=(Ap<3 z-#W|}<lx)j;M+jkHaYm7#C)4EUoh@=#(})8z-N0GGer2NL7r?UNhXC^Yy~YfAIJPX z-jS#&D`+X=_&)ZeU4WoEen9IMl4iIN2e6a2Mu76!g~JJ<VHl*fVg(pxpmfz-wMzFq z;+{t;-4ettf!k8VErr_)h<gEUixIcjaT`H}l3(R>xK;*%wB3GVppM{iHeN^JErUr8 zGa8w)Qg}rMeyTvhc9`9QL!l`uDkv^08B(C>HIi}zYk|RH#^%|{E(SLlmJODjvI(xH zH&~$n%NKEOZH04eoggn;+T;|xv9b&x*cFCW20C~CU40$#cb~b=lYfm7>pVki^PQ() z0pl53oAW%eVVK9*6NbWnVCLv1WOBC_SqRn+#sY>7VmI&npp0%=Fm?lByEd4A5;?Mx z)>aL0m}0<oB2s5$h>}y1Mah|2q7*PTq^eUysTt{_wA2()x>_Yl&rm<m#@u4Ph+jgo zFP5}x)evQ<RCIcp1Z)~2Wfx^EoWbD9(lj<y&@4;KSlW%H-LZ*+_Qu8uI)J5vSW#D& ziDT(_80(2(*5gJ6&I6UNgu$4IQUuc>p&i1=HJn@{$h9N6Mv`k3xki&~Cvxpft}zMN zZz7?SkiuOihG~gB7a9nXQ8J`OZVZCyik5bhAea+rMQ&1rXhzGp$>C9~6}u@AVkBCL zn+HN-R?E71AtaG%rEWf8Es$wtZhp|d5segh)+2X=$b*H3!zzuY*s&;{sf2;H7)i&{ z@sdjV8cg41V@2`OO3^hW6UoOi@$yRM8pOhFtT<j#DTaxUSTR--?@=kahCC(iW7&AG zO7<G^W<ADA<9#Zn*O0H&bF3`huTlp305Kx5q~kCCHeVc~lJdQV0+6rG-+H)GZc|#D zV`BP<YyrSXgBoHwf*SI-i9ro{a2_h1JLgU=Sj|)_;0^9-cl-5*?#Q8G>?;9Dg?Q6G zZy6&B23sFe0&vB*b7Z@6X#Z&&vkU3wBE-?eq_A3AjrU^6LG$G6>n!yqgA~@ojIgjf znFY7u2K@wyfh=k=b@k@Tzh5N1Z+)}N0}_(d+C)uO+w2Wls;#dj>rxKWqzFurs7h3$ zZ?vy@wPoD(YMI376gQW!|L<KMjd6*kYf&fhHfl|EHR*iJQ4ivCNw%1*7PhMg|49WR zda#Xp>QIBJSt+3Il093+6fDiD$!;#uY6UfD+YH=7CqAT2Sd^NY;VnjiNb07f#R1B| zfIzUF1O*2NhXi*B4h;@d#wim;9*7n(Vu{1nizI<qcZ%dJqretk#>K)*Y`Y;y#vqv( zEQTFfrVA^HWj*6%u{6tsv0e$RXA<kFVm;N+v|+;yk;}TzgJ}VRKY65>aA?yJ@TVyz zl8)*W-I-it$h9lECL=Fz8BK{qD3|g89U;<#GDV))dISmqG03YI+(cN#IxRn9iA<gg zqZe<ipcu*<D?_+QXt=N<xJVgq&|Vy9N}FGEyx8V{cqpi27)1qJn-3R=VDJ@!^%u4< z3<WviR#h|w<7i*1<2B@mB5jf2my?-~*`lH;^HDEIh0GSMlY?tB=f)}QcXzEEBt<oU zXg=C}*#FeMd$!KjVN@lu#ei@T4P!xwAc*%Qu3(0;#li~)58krK3wNE5&X@C5>HIi9 zmCm2@SK%R|N*BNdsC3?(H@P?mY+fJ=>*w8mJK&U=*4k7{maAOV={qz<zw{#hz1K6H zjNBZ0wFU1#86S|ri$k%xO2L{HPB!6OH4h+J>MHf#t=OW|{$80rs1x|VSC<hbF2?Jh zu*eRJtWu7w*hQ;d0Ssb{7%(~4<XQVxYO-X{FGI=+2T^-1w1T*}&wzp<_w_Lz#JR)) zyTPC$lZ7l_g}drZ*AhtLBPPQ)Sb&UHN3_ccES(<6;40U?MA@ze{wFo9g$8yF$f1JO znJJD{R8e|zmco_CRRy=d=+;s}|JO@!_60qWIyuW%i~_`BR!J+xQYl$ulLgCz-GUXt z?!g|xo=QJuh*B-`Y^ixYk+=g(GcpONRxdneg*7!VSWP2KX-p979n3OhDGf9&6VB4G z$`-*go$zp0oWP0`WeK2!Jz4K0)<?zqB(pv#tWT;8t69)H<c~yN9bsZBQo1-q@eWip zQOKgsbWGPSvE&+0u4%~EPsW1v(i>atDIaX92Q>pjQD3ZsX;?x4o#wE<gZ*C#8p&6O zIE4QkorGS~(>6b>S!sBSC)P^*CK`crfR5o9tr+IDfn%8nJwv9RBC*KL{aHK_l{?IF zzDRCB9cR_h1{BdGsS(*tb4p5XQ(%jN55%a@=3ziq;IVlckWPZF`Pg6=EnlgX!L_f1 z#y)M{W7*D?tj!1BiF9&K&bj3xt%BI={GD#@xwPFa7`tgbAcoL6h&(Ce1?w3&OBqTe z0h_ly!JS<b{5qrzYkM(Ha15lQD@iZ~&aut}$MFe{AIru-bP|AFg44YKr#sA%?no5Y zcDloC5jfpT_=HE=6CTxG!aF%r=a$RZQ`g1m=AJ9IyCphPoYY2&S(wzgLAgN31rbe! zXoD>p$$FBmOR6Jl9rnH|kPB4lg18_RUZPOxLbwonp9US9qyGx6^aU~ebl~k!p#y6* z-6T^15%gUYbqD!k-NQ3D?G04kKb;Bi0-UpL&>*rB2QZ4Lzg8h6IbJ3Kn9hy?5I5+n z>kUrbEyb$7Kb*3H5~LPm@7{g-6csUKi**|@7UY3dg!B~B5<5zU=;_wM+uz~P-EcSs z{P{3$4s%GJ-XyIxOd@a=9=O6_GzQFI_+ympFcuG!q1>3~JlU<?pdeyw35KTtz=KD( z@x2m(jfJ(9CZ0J7Jht~5XCU-S05g&j@qnlyC?Y5F3<@J!<zg=Q`@z8jM>78pjv6q? zr_FM)qmOX*I;MgSV3i#~<${rGIaDBcHg{t!!3XkyvY@sKkifuN_J8eQq3t~$!PrU6 z1W1f=!Dtey^mUlA+D1ovwRqhgD4NCRYk-N+4Wp(9>rH_3PG-tY`bjQ8R={53(+)BE z*&Qb8z2O9g{CbnwXp&Z#^mUb0WoB8ap`xl*TUA{x#eRnXvXeE`mSYERV{NgqqN17{ z!ASDwz9E$h-pj4FzJ>s$OorMHZRMaNVfM+p9dm@Sul_X{z&Hq!W9J#HuQgO7gF7BO zV~j8v;yD`ud1__+gklCO#fX+xPhuM+t;Il$6K+N1JPhJr!lP9^c<biSI=<)~gG?{p zxfd8c`4{(@MOztBy;@sEy;@sA6#`B*TIIA{II*W9X#0vX9*9bkFB>ul;Gh8H93thZ zp~ViAojcTXlGS}`%MFbLJ}1Xok&mhZDzo!}hq<~DqcQ*5sTbi)54%~IKTE^@z~_;; zsDGbc1ri?7DRo$g<$^8P1^4JB7=Za8<buK1OCasRV-;;z*<zI{TcskM13q3ul0csQ z9i<MK`wDz&Up}^h`#D^P5jbr=v1GSp_jMw*h5Y8>-U)40N(Zd_zN+3DW$I#>C$_5A zy^tVC$oy8oRaY~9*Y+dhqK$|>r*&wpAh3~bNh3VYiXegJ3E({FetDEEQjwXD+|eCJ zt5{f8FxHlvX_X3Pqbg*U@EtW<r!OC6Fd3uU3dE6YhnUc|n4r4yrRJD|IOcmQGO;4F zI5H1xZ6UHxlUf05<-}w}e7R1bU1o!A&h&!YiW;8S^{EYc&?}hGIk2E@^4O7|4~_Wz zCxf%LRvR4CyNu-Ie}MTEWhSSIGSf0enXo32rG|f6nu5pH@{JTMbLw=sV4SBa3oZcf zl<<lH<3Rxwnyk)*OL~f&M?2%OoU9lw+A2eJIR=Nq>y*?qH%A+WK^Qn>w48Wiq$u#E zre!heG!=kO(=s5`bagUZQsFT@6JBKCOJ+JCN>#}jaLLL7L}^MUlbn?d*wU=5R34$t zq^JSAnv#{OW-<Vl%48&CNNFknSTkUi1;C{lsZ2&zN~VCwXEIaMG8n*{rZ6B%#bl*r zWjgWj?azb%>zS|X)Vkdz8zv=1l`2Y4O$&rY8(JKtj1GvFb|Mqx&cQJ)fT*d;Ol7vR zRJjHz*COR1M0>TGEqgr*U`d9hB`i%asQ^f&6)f$+B2N}pF%SS!{aD(cEc*ZyHJGJg zb{z@`R9PgFCBpKEilx;ooy>Ztuyh)W(pjG@*0&q$)177VSd`B)y;xMh(mhzF4@>uD zQ9qXM&(Z@}dLT;=V(Gyw{RoDc(nTy?%+f<ydN}Jdf~5(}lm?8cj-|)4bO}q3V`)9> zSH>a(OFPh|bQMdFXXyznUBl7@S4vN0X%kCZSk%CxNi3kvVTMnKuxJ`fPiJWWmCk|$ zKZaN_phm@j8l?d-N&{k)2DB&*Xi>>hxC25|{4)GCtQY{IVgQJW0U#=V9bUnj7+^yY z;6mxu@P8BjfDiS58}5;;5@4d<028Ix!yllcVkt`}vh-$n+6tZkFWZy#*^5}^0mKGa z!9wvB&`05|nWevn+f{J-748YF_jSbj{09FU@V^OMzoQ6ZgrLD(3kz~hEJb@^DyWHt zYZ!hGhiCt!rU;77pv06)olMiintJ5)%+-M50Yj(YeIVU58nM~r%G3Djcu%pgQVvWD zQPTogFAIFyet!<%DRwa!2-xQVf~XovH!VR(MXx}!UIxaID-lG11Tb<VKvI!N3XYo) z-~mKZiroVKV78yQ4H2B_dx*v;(;WaX-G=CQ0cE-ieTbZ{9|`2g0=Y*ZKM}}J1#+K2 z?ia|<1oCr%JSdP~2;`Rn*({KU1@eeM9uvsp0(n9pzZS@o0(nXxPYdKX0{N{#o)O6J z1oEsvo)gIP0{MeLUJ%HO0(nUwe-y~e0(nIse-g-_1@f9e+63|!^oOHhZwaoq5t`Bf zrY~7+crImxT7Wu|J1tV=Qc<u95t&P=C?u}SrPKg~l}yZ~lHtzw&ZSIXAL~nQGC<41 zle`DHxedsr%oI`#CQt5<kei1rm$FdE6M(pI^MW<wdJ1{>%B318<dc$1`BTUjAh}>1 z@q^_Mnie5{DSuab^7nw!T&fa+4ix2qH7-b$59=hs$~>^wg(&j@W!oVjA5gZT0eN7% z3!9Wru_(MzLrGCYCk^F;I>u`#UliF#L;0boV2r+vF2?BFPQx(zwzC-HZeu26+-(<w zp6Y<Q>h)A8imla9VJHq_6^^FhCF%Ht2nZY&rg<PPLT(BL*mm*&^a8*k)En9nL%S)u zfm<P7qG7>e*T>onD<l1^oM;J#)54+=KrxvHA2_bf)*q;NxfR}N#b85}*am>HN#qba z2*f^O<)k2%k%-(BE3n<H7?4lLu;gOfFpw;@jj(dE1|J1T8wr%P86<%qfD%C%zTi5> z8AkK#_E1W!oLq>DsKE!UoUjOl#@WU-!z<2h1;l7&{V|*VFnRO<3#+Y^kl<Ku<rMMC zct4xraD0G`!_Mxo%H#n{LRAobu>^9U7-Cw@=Rmcs7UJoN(Wos0g?zP{u&fY}W!8Cd zUd>u>1n5f=&<c=kag{v@WP@3j&+*BSHB+seCu9waAiQh{Zzc{ef|?0XR6sB`_(XvG zS*V$S{AOb(t*;&AH-|j=fx&YwHp@xD!l_6E2~Prw%?8k;XsS|aTSV>wfK#>V0(D^M z<AVAIB5g1%ragmw$;2`@#T{HEi@{q&Q%IR4qNzg}8_^V62Ec+I)M9iE<p2Wx8tO^o zYpw`iHL%&i7HZXnabcC=wg@YRJy&+LJ&y=lTPt1yJcSZ`?aeMhwigg&UL*itt-7eg zU-gZmD;0o#g<P{XmolYdZ8X!>_6k67J3(Rq0UO#kl)~Wy+_hBNS>M^V0`4*T7~4v? zb6ujr1g`B01@(sWkw}RJDXWN+HVy>+2S`4}RxVzf0Q`WDO$4_jE-4zlu1y3N0*;jf zR72qbS+D_(P3c^j0_a!B88?UPW^j!G*DcspA)ytD>}zN=wGU_7XGoW-OS65BbZJ}~ zmu@?NNDTmlATd~Dlp)lHzG<{J6>|IwEWw=t2~k+WQ7qv&kwCm>Hgj1H))Sc3Lj<e_ z%u2AA=a4Rvi;OS#%Y-^{9_hMq-D33J0fVXQ!S!hH!N5<zVFKM5TrUc8bNZ$s9KM$y zaQrB^_q4m)F5|#Foq^eKya0kJ1O^~X5Q_u5PJ-nF`;E{zup9RaC4v1exH}?Y`vV8& zC4wvuhF}1+2^mO|pX-QD69&n7J2>XhP7aNO<8jR40}=L^Ee0WLpz02f#kkFCY7L-) zBbxGR>^A@eBG62V_*!i~s_bQ32eqzOgHLD32@KNhMJh-EfO(;QfTT@MH!Xm9dAIGn z05cZg12AXOEZsrC`}l<q)Wt%mNdV==!PH}}-nN~<)tlE`yD;gfhkZyr{E+8u#JqiN z9|1#Op7&!+I(UN#?<YL(6wE8PeF_Zn2A?bleIKMSSAkOs@y0-4IoFT(3d;hB_{E@L zIoH3H>tSBvR4j1-0EDgFfCe87b3BSAx`RXvPQ}>Q0lI81n;Qu7Xd>^F(`}H`?OR^j zOf0RN?F?{qYw+;_X&5NmjSm{I&3sl~<(Zoh=I#ObUn{P-nA?U)JGZBu`%j+xQNlgg zb{AL%^W1-7($4K==blBA0+>y>9|2^qm3xHeehia#Zf`sHJf3?F;g;E+02b(fFrxoS zOvXQsyPpL-(_F&D*cQSY=#DVcB2325!%R;>U8ILlD32<l=sXN|c2nSe4~q%d6o#~m zY1<ND@6C1h!L?>7ZEeOdX)oLzy@(&MGJXlyXg?A7#VQ=|vQU}9?<=(JRobd8#(Gg` z2SXk0fWT$}zRdgLVYA?ihs|n-fv?qqui*|~1U##RB`-w^goVMg1T_nF5Jzbp#I-MO z)PR=7br`#C#3XM1n{YG(9A2F`S-aQm*ehnkFj%|S9hk)8KEPf9va3+U5PbC~xR!lN zH%H6X<1m^5{5=QfN&E{4)342eUNMLfDLj6|6?`|ulHaTH5<<ISb+HRxV(fw!7`xOk z(B$XTi0x~QFC%I<ZTkdX=LSM$mVod5@PJ!IboV#vYZ%*S@QC#^cIxzWhc}|TuLLb! z4{MH}w|v7p)3$@We@Qv`U^EEAvVFljiK40XcykfFAa6w)G|P*DR4hZY;$K0pfxGxM z%>O0uSJTmy2W-@{9deOJYfuZuX3Qw=O-V+<nk_XNhLO}5yb7!X=m|BJ604{ZN|Hwf z;~`oOr0poFD=c-CwjGDOhPI4r*$GTG>&JQd!^26T5@a?zdYIF=JVFrYVNa0qGp*BW z^-y81VdoAw-?!s@KjX~zRS2DdsF7VlQtAwCI}1TX#y^Vu%n-zRcqoks0;rAcdrWG} zK-Le0DhKKUhCi2j;f*wxXe%TT6&Rq_|48dNj??0e3O~_SU1cY$XEf?tNmrKIu42Es zDz1tfpBrLtv^FAd0*rsKpx*?~H(X@?0SSP90F6YVP}~-0Kq_vNJd#qkY1>_pL1Nt> zMBIai6aukt5*6BJiAZc}AU3l_*5(2|#Bh#?q$>oNAIBs~*IYv3bj=fybm2C#z~N<) zAm%9%WM&v1?%~emSr~BJ7K2|XBiva(k4bGUh<QPzE7xLqFJcejuudz7kvDh=24Ln? zZmLQ*jhm*@P3NYobThaaD&0(Orb-veg{pK-h-(6Hcmvl!F3#oJ(8?*`ANRGp{f5BY z7*CID8k5S5CPPvmEqvTdgF)U7Xt*1dSCBoX+|V#4HL-CFhtHguWHe1MkAX!=eCUc< za2tb9=Ba5MgC%tnB!T4*Y^{mdHCu3X35vD9l?!j%g`51N2#v8vXpA7-Zi)meUy6!` zO&4G$V38Q$aDXSqnE^Mr1L};GNdedk)(q?lrU``65*RoDTNH8rVVo@O1;s(zqI7h` z2n-QZkbL!nhVGiLI9vIh>yCVl^>O5h@Q#Hgl%hU^2FAAe0XA}U4+nz4yqW~?QG=;g zU+tEf2p<(oRHv&l(jT&<gzzC_6v7iM-<Fci_W0li_qwV^Lv>LtY|e+JUYWTDP9v(s zi@x|+1nEGy427dyq>v_Zq>C5%rki1CZ55pGgWrnnXT><my5;($oX;B^5TmcR80`yh zjuld8^${YMB#>kk238OF-S)-yRRb`B^Hok@OmeI!{4dllAryz9J1s5QxrD*MnFDEZ zfych0Xh+Dmw&1o{_HBt9ZQnARtV&4{WhE!e0YWZPik0pG-bx>(cOX)B0=pWRQE65L zTmBWS$b%JmvLY{RB9!>DV!(>}vtl_bQnI2zRus;%9a%}FtRsLfqgYuqE9ngNSqu$B zDpv$NDN-o>0B;Wm3s7>{tOYL^0-5JQ_YpA|MBjzDbVZ(CGAWo8JoI4BfHnmfdO60> z0|3Vp8WR{o7<eIJJ@BZ8ru=veJTxJI(M#RO|02P*hvBhh47_GVd8Csupu@O_|EdO1 z@lq-epz#PUayk#VwWJ5Z{VDuK0B7$zmd5*rty%_E(zgCyFru`oN*TOQwM<Mls)kC% zwvmNMGiaz-B4WYlqfp2IobQL+D3L-ghc?biy+O1ERCEI`%N<)n00)XB3DEc@ws4)d z&WH0+xnMqF457jU30~_~dIA@(83x*wj8o(G*H1RqTY6QQ_=AfI_)kAN)I<O^=;73F z+hU<|7C9P5pSD>*yV!Mg+wb8MjV&Tfur&Ni9gn5?9}fU}BLc1&`8P59+n86?0@$aj z98NH5m9&h%ll*|Z0*FVudF9zEui8~S|EQpaZmm^P?DYVDK!Cr;*~ew1!=e}*X%h6n z#KY25irS%<10Il4QD$m7qeN1<(vODj60h1ISd4)68XwRdGJnJ)m!S)Vep1pTrf4Z> z1{nQ7H^?YxcTW#5a`h%xUvgC<G1eU-V)3Mi#S<|Yp@@4}F%sk67NZ{Ry)8iT9KCIj zPJ(+|vCWP2wi99VxodAry82$ON5eUq(|hP)+fxg1<U|)vUuJ-8&T-ZOtlwL(2^I3b zSK0VDKiqU$c7!dpeb0vzO-{wavc*OCsH}&KAnw@jYuo=umZKTxK3uBcyhAuS3diUH z$LBm`+-mgZ30UgC@eWDTJY1^mP;ndq$7ttYN`kn+AlzlR{a;tfMpE4T(MS(1;^Bjz zjDvs3a3^Cx-9uI^a>myP9QeNz@GoO9^54c_<iE%R0&Dv>c|Zh^B;-9@<ukz{a^$nt zP!9iA1eC->s!p=A1sBA>^8fJRlhf+{Mfkk`hp&nJIeGu0CfWr+3<@8v9+bi9ng)%T zpAh1R{Ex_i`1F0a_!#T-FohM+);LP`dE5V#M2K9khl?C+RX0{wV<aq&mL1_#VKCOn zup8{4uQvR9$q>DV?2_Q5Kzu$ijvK#^^Iyt=nB+fPM!`p*Ys)dV7{}#b%Xs*BSRALX z;&{lMXR$tHj09=_rV7EC(^-Y4s&X795Au1~e_wf=G9hB(IwM%C9x{m))y7hNb+NHO z22G0x{|iY3c3o^NBm({U1C{gP>|8hu6efg4bugNLNTm<?mWR*MHTQV9$_f5)jz45e zCHpl@_~dR}fb#x$uLpS)8B51MWUj-v9E;%)VBVsJPfeAXEA@2-ZMDAQA^T>#L{fl{ zJX|*E%gO*^T~%6D4V(D^tyu@BoL9ji@sMg?9^2W1BS6zO|Nn64P{I2?oQ3ATIU!6Y zdp}&()EM+;IO?FhH#rI!=g33$nhrr^3lf%-{g4rY9UsoEOfuNh#K-I*t0UyGrp!{W zuP%ZU&jB3&z{$=16MxS>cGEKK7|}y7;MIrhslan0{z&&0##R7cKS(w?fB%2Oe$!%l z=4x0VN91N^q~qPc6$U^vtFwr;9o8+<QsI)BA>rr506$JiW$-)}EIs%{+^pmb$Mz5g z;LpiSax(Z$P6bm?aw>qNlQV!nIU_w)!q0u+xLZI$1FScNcNoc}0A?A0zR4L9erCX= z0N|OY;bmq@s?;%FXHr#JsSF$yqvp4TGpQ+=Y9=*Roo3&`mYSZP%%sAxx%S;_Olnpt zIAmpHxVISVF=@#FhE9WMd9@yMF==T4mQG8{OqUBI9wsd_H483TYSuo^VA9p8nQ+NW zkvaQ&COs9T0!CXcbM}@@dPZ_8T+-7(oTH~=GE~WMsIMwL)xAZZ!(>1<xVPv$;3VKI zwG0{uul3<1;M8;$9<dT<GS$f`E}v-t=(Z}wy@fsnAUA;6T@@me39#;f7TQbDZvgpD zPJ>HUx`(56@{Q>qsU5*y*p}LX3ZhcGJH(U557j}fhFxI|1}OWKEWD9NXoFC`>6s3b zq0jxT4k~N1S_;P$BV~fJpK^qBq;eaa_yC9EAT}M=+KBBC4);;82+kh{lsBwR#Ihm) zE2~*iIxFfyu-pA*!;ow^%}PeGl5wo0l$97*Nd+qz&q}ncq>z<NWF;0>GKrN;W+hWu z$qZKVC_tzIUM-mme}Gp@7Q!D6<CVZ6yns1lB>=64k7lwGz*S3LgZ~Qn1E5+0fNBYV zsU-lUmaK(8pr<8p$gTtq*=65FvUiaPfHh!Z#7l%Um^uMh45#V1HOVP4tf?c|Qw--> zz>~xquUz;7#rgroDlrv+sX$BxVJa9?A(-lbDcCW~hQS~3(+q&?z@;OmA~A&#s%$i- zI$^3aP?8v+Bwc`#b_Gfr2b3%xC|MFvasab3@?@YyaM~*)N(IU-4Jfw^%$JGzvYWDC zX}^0@H@N1&Rfck#dcsxH)RS@t@Tmk9H1!fmSXR;pAFHG->`i&}1&<yBKm<DoqB<C0 zpe*}H6Tq9`UfeXKh@yrPQ*Xv-ddyf|3AyUYwTxWL$(1A5N^-3t*9qiWO|CWMT1&1* za;+m*6S<nnwVqrX$hDDNr;zJ3a-B}DGs(3Hk=rc(Hk-fA;ct)gw|V^S3H~;pzb)Wz zi}>49{OuY3_AGx}%-^2pZ%g^x3;gXR{`N9|dxgKf%HLk+Z!7uRD*m>bzrDrZ*6_D? z$ZZ{3Z@+J}-#6RuTkZGl2&KXnbx*I1bZ-nBrhM}7I-74EHlq7t*s#bi4`9QLKZXs9 z{V{A<0-$2R#{;NXhNJ)|mLnNJi`|esFpp9ox4?YL9VvqHC=cWwluvmgkKjBw($_OM zpYldtA$b5c_U-^+Cgc;E2Vi60(0l+J`-SBJ*w{ZTAHc@S@H{x`Hy}J8Ajg3b07pSV z5%~Zo3GSE&z~hjP`2alb5Sa(yhtSA;DjbDH<xvqRJSv~+h$5o%s7TZ?I-iO{k)86W zXcW~cpX!97JLgfIQK!!NR1E4IlSg$yF)?snD(ccjL&c)5aP)8-ijCD!@hC1%LnWa2 z_&h2RB_wF5B$Sw_p;Ra-DUVVkRZ>2cjMS<;Dg`C0^QcsmlB}W9P-=>XN{3S@DU^v) z@v=iYUUpy@yvU#FSaui)i~MPL*&)@wlt%+#$936(A8E8ePwd4z-T5Jf%iDjs&hLd) z_%N7Q!*@>d@d5sx@NE!NRU=-3C(l&=LybsXVhBS~`@qON89wV%<E^QygT0N!Lf6Y! z1IN|>7uWz9fCYGF_p*8uw%+qkevT~3c1egke7y+1i)8=O0KZMm9XeIP&94kTIRr7_ zCjj>Jd$){qbgFYD>+d(5w}HTDbr20N{NH{q$juJxC`m0*@kise7<7usH$)V0d>9Pi z$%p4n_w8N|cVwAMa+6%>ma9lEa0)w;f}koK3k)9os-)Hc+xKDDDr#hThY_$D+CKax zm6%^ybg;o*^ZP1tlIxNIzxo^CSYmY=H~7l=0PirYAZxq$!yIH?d1RZ6WNqL9Z$Jc^ zV)s3&O`a)uCi8$d;M>J+##<Or9Y1z;cMcix#KVn`AQ>I8@F|R{ib{(xsFc)@Ht2+^ zxD-wjZ<U2Ov>ak7c!5QD3_7A6j}S%s*g34NGT>u^lh|s2=qi6?dtM;`nPWUZ!oFrb z#BPrt(Xp*Co!mIszu|C|KC+eck?r~=>j{6u;VOMpE9s-!^*ics<30+ns5oaj5$$CJ zmeoE3h_X+&+AIowCWgh313E<dQgeHJPHAlyERjaC@4-UIdJ!L`QLa^G)Puc{ENkyI zM9Zs$uhvdPOH5n&)`|zG`@sl>|4IS`4V&!mS5b~x4L@nZ0l~pn4`y>(KJ1h02P`%} z2qz(_slp$>vsXlC9ys;)1K<_GxZl&1H|T524CVcaB6R3or@g~fqdXAI0f(rxk+!z2 zF>SUE$VOqF#~()krwH6H)3Kf2wcGOR(?-AH%NMmHIb?w1%#Q4~(~L(51V@;iEevg> zoV~+JZ!bO%&Pb-poYKn+4<hO<hH_qRN-rs|w^Mp~w0hHCAP?x{+BFaTqcNFty6#fw zc1Vv1fQ4Xmfo<Tas<ccO%xqipaIldigN+0}Ym}a%&S28P=mDF~!F+_R8eq7<`^~f9 zvqqVz87gdrNN2LrQ&X9&jFfb-T9vHA*R1qRF&LjRRB%npNP%lcMw%G!t51b%N+$3m zXJlcQEPPFY{qb;xgMG#7)Z`5C3rAS0#jtHY8Qjyr(jcm~n1IU4$aL#dYp%m9Rba1y zvs*2O3ZrQ<TZlg+3D8yp90UObUKM7+OT5WaEmo%|<6vQ1JqS*RQvt;4jFe=ELPjQR zs>kLEu{tX~J+q~~0^G7vGsR%!fOG*$G7V_BWx2UzuM0f0H6XJkD#s4qY#)l5ngJP~ zlAfLlpKAgvrcB9-{gui9r8I!-ln-<q;i(K)MoZ(B-K1s_{#ujs2v1KWf&J-#*MzS$ ziOB(;<SaSHHw3X>E}voYhO^^3<1;)FoQWLE`o!TcF(LR2Q!>lov*TDMgZ0T|ePKg9 z?EjXqKDjK?;LY(2Y>qEreY7mo8-IGqryt7<V13}zOOLQVLs(`g>obgHMv@OL@t;`I zvrIYbV_*?{RtdhT1US-K*4xNR>R3M$i!7`USYxKKXgcdN3pS0<hP~uqi1C3hB`tyj z=AMFo9nCT(mU$Q6ya%S0UGU$HWV;YJcVN9fguUw@!T)2_2`mf%HHA-BMa=`KX$;sP z-~(2aZvut<ebr4#6r8*cR63@zFqMs|UYIJxR3A+B$J8K94aQUvriw8&98)7O1-mHx zeMe(ThpBOxD#cV8rZ`Mh0Oe5yl*a_@Rt;Y)sDZBn)Kj#-uWv(BYzn?lZkp7H{AE*{ zrcnNm!hF#GaXcwxDfkisJrA~{KY`{WC%Hf%7YgLl0{M(UJ}Z#V3FKmdd|n`z2;@?M zd_f>z6v&qZ@@0WsCXlZP<Z^+0RUlsz$kzpOg+Q(p$TtLXl|cSSAXf|In*#ZkK)x-I z@1V7aUWYb-Wn`n^x=A263*;7o+$xaU1aiATzAunF1o8uc+==!$O7j!J^;3j;_mRm& zdHKCiXV@Mt0Ry2|F4Y}u2i~P%i4l93fh9(wECovpt1JUcj5M$mEHSdcGO)zRLrTFC z;}%i|mKa4?F6B!h_oz}Z$aqARfkDQzb14{PygHYGLB_jFDHvpYx|D%I#y7SUe`6`O z3=A^<@ugspQO1{nK_(!f6bv$f31wiA2~w4UK_*yL1_qfBbtxERI;hLQAQK9E(LL6H zAvUZ4EHiX?L;*I<bOf_Y2NVegnoty#iuZ&^Yc*h+=~Soz(@bYK4VY$PvNd3u>EfpW z(@a-LlooklAh#$N%%KQ%$c2*>0r?q?dSh63Y+NTuJu405Vcp)s(dHHSG~Y@B@D@vD zucBY1cwaMo;i(KCY);LD4>}>ZxYIM?4eV-eKKvD+xaS}YypHfo#rwEDL~{{rY}U~n z%`w=cZ5}FR;=N$=H`x&W1R5*SNr(%Jv=XEj;ZO8{f4n6ec8qt$bi5xYCHGKHx`E%U z4jZF&GET<9X~1sy97Wh64e<p0w^Y^<BJ(ERJpB%AFZ7D=18l36@vip*OE5fhKJ^3- zPD^Elzz91<0j-`yZ9=dy*vfe~<INzpt*8(_kVAaqZGx~_v{~%!g*VCL9id*$dLJ9? z2i4+D+vH0)uq}lT_cI(W{>+ObT%|MI035EEwucL!b|K+5BeHc<$%hM{cCj53!aae* zRg!Q|^Wg@-*If8;&*1b*9N}KV;a+wLH_#bw5Dpi5CqBKfL6d}QL$+UmJ&+IgI)r;e z2={j!ZXgNw4j*n1e4m96_b(i-R4kIpDk1yuw@)IPg5lKW9@Ijb?7xJRvyf4+|B?ym z4LdA#9k>n=zER)=-#!64_E>yRP6~VZy|_>-7p4p6!np{INJ@hk+cR`?gAWu~GY16* zB>^&U^kpK5eg%XFyDmxem(qC8B^Sa+A9h{Zmcb(gjf-nJ?8X#_c&UM0fnA&Rq2&7` zURJJSG___4-n9is3v^sr?*%Ia(NsNr=L^0{LW=V(yl+nKNZuBg<n5rzw?yp8gFTW= zRB!xs5NGms{(bUxJCg_Xf+Q~rC(jKh&j88$)SkRgY1=-Cc@&?#{gAxRh2$N?$&2zz zg5+6&tPHaq!7r^`v`gZmg~WBjdkab8j^o5B9ChY92+VelmkU{LWjZ_SObm{dyQ9v) zRzH&ImuTB%VDHSw>I%dP@9wi_`ZXM@&ZN#<$F9x#7}(m!hkFx;3*VID+X&vpXZzD7 z+%C>=yW(&?9pTP`jdr+g&Vmm`!5+IVe7JL9iyz*(XAk!Y*smw<Lc(2$U7Piw3t$Tg zZktczZFpXeaABXG%C?mENzxnZ3^xvk>+J~l6??d^h-|L{dn_OBYY^@VA>21`xUnSM zH~DbmY;W1aU4z5*afG`8hr7uo-1wH^!d7FxZEm-RyIo{^AK2shaCbnsJB4s}<8b3i zxO*Joeqs-IFAf(V|9n0l!r?Z%gqz?DHxj28HXKW3qoLLvw}*RNWcwP}6ZmjXLb#`e zaKFXjCV0Vk&vuRvH_~<<6S_n$v00l0dZObBXlUQt<8lGV1$HO%ak+-$@(VAG<h{xn zmrgh?0XQxrAuhk$<MO-6cI*E%_a)$Q6nDN|ebw}gj*)B~mSkJ9#*!t**39U(F-Shf zw(x<m4K^?~BWc<a$dZv{V?z>z!H|WQKsMn>Hjmg4HV4^+4UkQ;n?T61Nywoi*vsbF z9B*@M4tF+r`@Sz9;P?AichB_5l0jJez4zIwuBooBs;;W8>;M1%euy5i%kmeL<u&_h z`oQ0yvP6P3rkqekn=iNSR>w0X2|a<Y;vUuR1^22bNvT_s2UV2hee{$wGepxRiBU<w zGGw>Lqlieo?@`tIAfiX@l6*+TP-8zWh8h(miHg>E!Y)b7deX`FDayBu0Q2+kVlPm> zUqPHkWKvF<G$8bAP9|Sdt#7CplN!bJ^UuiSTSysb72if;P3X!mQ(_gAST!Ddl@j}* zN_Y#l4eF1C-^7UY6E!3uhsAEx-&53co~V``6=U;%+EJG%7|ef6ll$G;c%&A1E^DQe znsri3w3sbpt*->1#Q<zQpiLy&%(iC>KTOm5t?a#;^<E7Hu6$Y`$-q>r&U%mn5^WP; z0yEnYe)Np>er=LwaxQ>of|XAn6}(;#Yvb|Nc;FE{5UgB46YFE-olLH=K8Snxc!Mhu z_+f3*gHsbcS_s<_>y#Vwv>nrWLWA{g(0WQEgE8yl+Jq>!^;g=&(Si-&1Nfwdx?3va zEtlgZpTkR@WA)N=U}R}z&uP}@wDE~#f%OmC_++x!`aDIhbR)kcBHt#xgviI(OPcjH zMD8oMzK+O!)z&vCauq{kE<(yLi^#W2FT<=HMWbf>9z|HDBJ1;1!9PF@ET2G<dHEUZ zEZ$>n<-!}pGD&(>vtHHQWzs9w54DN#yJ(R_b@L-_JfYKXu|xvm!oO)^+F3|;+CM|g zJ1Hi;{Li)h6%_SOJ8H7R`lZNa!5x&#7-PTItY2&6U27#O!GCC&hF4<t`z?7Q$>rAX z$P-P*tlyKT24nai$g={2>N)a+lb2Z*c?z%u`XhOYlO@)FlBYDe$odm`$}tN3SsTan zg^%!mQ$+=>|3mdqP2XS#s^JY(gEgj$wy#I2PmtHVLcHtU`nbB3eqNdE2$Bi>NjIP~ zS!vy;Bb^Y0e7q6Hd_L=@L>I9nMiN`it&zkwb6X^_-P|5YY%#Y8$FZaC+l;ujN#DPa zun=3m3pl?$xVf$YQdPx8W3^xG?uA6!o(x=V4DXS~-0e%V<w(v+hv#I(rV7tL0I|`~ zz|mCiF2NbzGzZ}B2A5x)ALt=`)IkQNqip8!oYb+yL&KxHjvwkC8qf|5^be-w#+Y^h zYCe}vJf5@hSkJ(b-jq0py!aUo<+t==4dR~2;UI3dqd%oF*2oDcu~>x}uCEw~Ld0qX zV^+;Tmjm*l21N^l>jAFhka7w75iYo@xq4o(aA8qNe!&7(T)GI`H6pfJN^T`A;S5!D zI&8YgEFC{&1;%&y95CIXM`Mp?_;msDj$dS{?u(8`5(<IWM~Fc;lF&^(LJ0H`!r70| zKp`9#D4>s)<u5F}!|C0w!Ror>qbWhklO^abDNdi4X5GI;QMVL-dy?#|GN73<NB&uN z8nR!;5th!@mMV3KITa{#jGL9M+i!4^>p8!5zu>&=LV1ZsjPxz%)4q5I2IqYQeD>|_ z=z+o@JfDog!8rzCNE|I<6@jxj7=afWL3GFk=y#epxuUCLfci3!yO7)>;V;JdB#13Q zoq*022k#lS|CAVdA3C+oW#-s%7iR3Zq4T8&Vg0;MSW4dj6fo;Xr$ee$B5V_g9z-t` zoe~apz&<r?G5z>OhgX1dyJPFpMKgb_6s2+2TeFO+cxaXeajHJk7Ty+`uK^Me?6VAz zxHIDb**s4Jr0)=5uXls5uoUVWuFglpP|s*;bmhn>s2>l_aR{Ad#zO_W-$7GTY_@Ms zX>5t;neh`H4Op>Rqi6P@X>fl|Ua(+6Q6M*;6)prPV5z(aR9TD31>VYR!zOJ1-C<Mb zS;M9V5~-|VGi#i52FXL%|I-ox=*$hhw&8JujY2FsCyna+p>C34z;kYP&SB<+X=FO_ zHTLtUKp`#Gfid1YkYdLaK&3l+w>_!;0sVkrw}4*9^qd>S4Iyqm0_zL~qLyq7doKdL z2bkW$S)V;c$Pa}=hZj%Si+w$V0!*GzfH|;x$AMkDJ2!3gkOEww2LmOJ3*N-83R_fZ z>!3Ig`(7r648(dUrY46EjyM_>8AB<L7Kq+0%sD)i1njsb=okFkcI?@;@xX>1*KN;* zTK4ehhT-Hvuo4{f**ErFokJ{9Zm6xg9kB0h-Pn2UMjzy*0ubLeh*HsBd&$|y?Izso zT=!+MGuf{=177@0tbx;^$pxCY(<xUwDLH81&g*Ogc7M9{MGOrsam{Wc{fYueep(u? z1UMZ@)Pwu_>aN{8u7=?Lg67IR=BX!v;eWAAC~s2O7p0qRun-gUTs|on=%+s^=X-U> zq*x=!P+M9R0=vdMsx-DWk>pirZ*6vQ)&cQNVBd|v9*;pc9W!mD#laq*W#yeMNX%Yr zzh$Iuhq2?LQ@_#{jVjUhCLqCJ=@~38g6J_+QiLVwb(pbNgQAKP#VW>9fH+_^U_ct- zKyL#W#^zd87jg~g)xh0e#AQHlF9y&v*FajejO*2$E$4C#mutDag3EQB)pPkW&ccKq zO`y{aT&^N`ZXV@4#(5*>O<Zo_ax0hHIYR-~aQSjBU%}-ox!g&3-0Ci47Z$|3xweNJ z*K%VoH}-MkdK`&h^z;RQxa%t%!|n~5(>V*}u?i`t`CcgpfR{OI?~!sk@VD+BikrJ$ z-VoooNw}MZyG6KN!o5nkTZOw#xI2V<wQzR|_nI3hg&T!G!D6{Uuu%ePhm?yUUKSTt z(jgUN@xwbHz)_e2wOcTz77}K!7VLzWM~@Q67Ow#IHS;YYoL&QpsRpBI!p~x~WD4Zq zoiemrDqwfpfXlTI``F@fBAXhAd;<qms;NCmV4*q$uU5&p$wR$)9GlqE@lY>9$`FFX z8Q}8z1KoIjF&#zZN{g+f6Co)F`B{}AY4nv~K73UZcos4XYgwpw^c5?Fa|doMM?RDt z?ma1TqpTn^sYw_KzYSJ8(dCyxz*Q$0u>gJL55$mDJxY2Rt>?nyiQKMSsZX_5IzHKI z7$@3TGauXTcmZT7v?WmiOcw~9V-*syvv1g6D6%yd(3T|gl7-er#MOXQlzU1+JnYJC zc)v>4m|}Pr0{@{40RHHr+850MpsSJ^tyX~eITff8Ke^8Ekktl;Eo4+g^;-0Ig=LcD zMnVw61uZ$E+9&v<$iQ0dWMQrGKKq%>vu<)1JgZr2#}maNLjS{Q30{wKMHvU=)2At{ zt61$Tv983enq;Zffh*lZwRhTH1xFw2;Uxx1v#dj<N<?LBLNfHgW?b=riU+pXUJVZb zgjp63l#iPgqS^t#Y=@9sM1*W3>4<2XN;hb`2%?PAv93n1I!aO#05ro3bkp6qs_`mx zf<5rb!guW^Nn0kdY6v_4_p+R<B5EYnC)G-tPtvKM>_C~Z@&{aVd<o9364{xrK*!jh zojC>FL^;(VdXh3CPxrXE^q^yK>gXGgte{P<l1!^FokIP%d6{_0o6~(a3>;Rs_uhi! zYRAnI!VI(qkd}|qBEHcf`e>@8Ap&uh<ExP4aCV|ptkHC$4W2}gARU9!2_c<hb~?wb z+tYC)p15})E)D=(sx^P2G0|i;Md-{mLMNk<M61~vp)=7)qTOs4e9OXdx8#fa=)<%3 z<zSCaFF9?}AZG>>25#wP=Q3=}`&Zc!oY`MQuxEJ5KSD%9VhXp3baF%htUV8>21lIL zo*mXBh-`Yr#BPVsTz@##yK%0ISi3aN8dj8s7P4uMbiomGVTrx3=j_xS4!4W02j)^b zu^zB<_U7iU38K*!C5klx=`h7wu`Y<&3}^Ne-W7AUg130Zx3Xgg?Rrz14!x|nf;Q_4 z2r;~b=r$XAkSpa}U2H%dNM3@TfbF*g7&W3ifUXRF@&dVV;esOJ77MpTxTV5fw3O~v z3V#*Oj0DrU)&Z>*rb1UC&UD({gIZSyBsnpi>ptwAz;vzy5D~T|%tuogHcgoERIP!! z{aa@+$5-G`kq0bsV2~r_Va{TCRuCt<8rXkrD)K@^q=PGQP7ts(Oh*AT5FsJGaKt%* z?~eiJgLpN4P}SdHvk*17L|)>Y)N@j>teifIX;ek&Na2gzydX)jH?mW@kPyu|6PtFT z^Z(faf~PK4O|LNb^fhW9F3bZ7(7YcnKplD3_I5v9XduouMktM~O>{u37VB6Y%i@3* z%VMlQI1oVvK%$X-#1P;(VZhNsX)aD?i%J%iLH1U$Wbx8Ua;yH^ju>9MuzPzbi`+A? z3NhR}J==SKF2kTWX|U5+<4FUx>FhnScP?puO3#MbA)8EZcg2`~VX+!K$<Nk8Vplhp z;)_w-&dZy=+ZmwIsze*xJs+-@`)QV)Th@S{y^VXz8@G$^*rKh?a!U(!MGf7MKs$>t zwqmqbIgBv@xu^KJVt`QCD5S$$u7eo~+p`kv(478>#XiXm0sz0y%@=NP5&6r6zZ{00 zG|bD`!r<Um!iEMHI?M%NAC2bI<Of7^z8R|x5XD*nTIT0qSJK5Kz-Z=Tl~jYJXTB4n zV&JBQtYQ@=XtfK`VIBB`Y0WFV4s)=}j;<xREpZS7Ip`1~_PCy7=0s>oE*y8s(?=-X z_KN3h6$*=Y^nCChLdo=s=MT*L4R~YBr4xC-0Z$tA4P;m{y}jBKslnsV{!|=^8c|6K zTYjGGA@$~wJXpW&xNQ($!(pIW9Dj4$wE|BTC{rjJ_4MZo8xF%+LW$MKhBV-T)4{zQ zbDp&5M9^Ja5zA&MLNFqN9n?NobkEJ!xrjR2*3Nw!ugO^4L!thdFrqNvv5hV`UUzH% z$f(@k%MSsBXYZi_U&_Wg9Z6&421Wt$avO*>lOrjdn;joW1*iZHo@II<ao8|*8>UX{ z>FXcpl~V(rNo=+EbtnmO9vRFg%?(A=<ml*d0BheKKm#QQM@I|_=<kMcfNr;nj#oT5 z+DDfDyQn-PI%wk%Ij7gdzAMh@oPo`oadvjTLA*BMAgdctpdgiMTWYj#sCVNr)XPY{ zXT{-7#62tXR7BzQXNhH3B;|!!MoB4M*W!;xM0dF}Tl(Je@LfQ8h7!K#Ow_iF<0JMB z9hC-XCk@*Bsa|me&5qej_w4way^NCtRfKkMc<9JsZRAMz#(`|2cPg-R-sta6Qyq&F z!Wk;tttXKjC5-8Z*krS)0_7uzeWEF0XTXmf-UYn5lnR4^VS^m|XD?_}4RXX!4v>aX zY>r&820PG!Z1nPC&Qzy%38*lFKUz13hGA;r>rI)-BLnDdX%0fCl8KnmF9JnG)da&T zhm|Y(W>SNwd}vr5ffb?(nRqXtHu?_^=4WDe(r<O^#`tdk2)-=aqN2dbD-$iZb8xgD zag!q?;PG{CxVCfq`i&cM(fu>Q1tLDNBX$Ccn=BvI?K`&P<l6Zq4s|cm2%~rrdTsBl zN^*(xGQn9Jta_79dDtOU#iOE0#nJDuF7~Ixj>O~58o`cCkJC~7C<Ye7G4cz)_@=d8 z6!2!R<aV1tdMLnGmmV%ga%~(I$0pP<9Lqu64G^Ubl9_gn6GK>n=G%n6s91YgQK-Y( zpd)YE!QG+A79ZH+4xStsz{uGP+p}IsfdpGBtCl0j_;3pC)RWS$NgdpH?6ADQ8eMT@ zlvU!p1&ES5I(#Ih5}&O$OvbGI<|8Ac{pNArPh`D2%mNyb$vAZncKKplR<PlRa0H*$ zA$>U6+ka$4M;0*4db75i_QopalqfkdkcbcW_lz27?875F1_zESx1^4zIfrK(T;1>8 z9*^_9HH`@i^NuEFAl;sR<mDlG|4KjJfkrK0>0I_EJ<pq-$Cf(HM6LA<q>{rKK5F^c zalKnW<@@am0oi*bOFct}k6%sr`6Ky)!`ikwii5a1w-;@H4N02_Jmvyk>o+T?cOv?4 zSw4FPHh1~l(%Py3CPx8nsRAGzrL{c*mev@tLX&Vr@Op!bwXJO$O+8SGT0xiE4m6-x zV|#nRGYx<yHQHjN2X8_miaC1;`g8$6(*!JiXIO#RTVrefw824bYKs9JNRVcWN1CH8 z00(MriV#dtL~Ut{HmYr{ZQxD?aFP}U-ciiUMxM32pKktj@pXF}>Yydo6vV=v7t6j} zEw4DgBwtv01<MMG*B4)1+*|w`rudoS+IKPiL*U~Cf;L1jVo?v?Q#A)iIat=qi?~uo z$2zQnv&BX+0+-}1#m`E>@f!f^0P|@zel9m^fK5}xc`@fDTv@?+Dd%;Z14buoG%zDV z1gS<0F&jB+;tJSQn>k;_c?dF@yePuk31>&Sg7eEczmh8*Twlj?HgILLu?3JI$hXV5 z3YIF&*aZI;u3W`)cNjb2huCK~XV-G&I<D;F$_-pe82b^vpXc@PycEwH;L0JxM2Knh z!R<5p;r1Ih!@b$K1@0|e88Qap8RU6~xpFI4hI!ryS4O#VgexV4>7yLy%I!S&9b7qP z97D`^8SlbT*WJtrF{7U4!Mzs;sW|WAFtFn60aV8Sz#jmAln3z#z#kQWKMMF%Re=7e ze}lhjt^)H%J&oW`F(Zc=AQ9#KGx#HzAHW33pChOrW&l>j_yYbwY{Qj*Vm#+dxPF-# zFCgrr_<Iq5U%}r?bpLz!8^_-yN^u5%|AN1N#ov$c_Y?g66n1XEW<38tnDJ{SgJ@00 zKSkBYRE<dxY5CQqlCQk{vip@<I$Bd8sw<V3`f6J42R_fL5H@P7$Ld+s*LmV{7E`yv zzgE2lZijjR?q(HcXzV8S4!Aw)on!S%pRWd%cVlBLRL^SE_p%eX)ch?`sH)gIMWcVm z-YvtTF7Pq-arO!JNhX)8zUL8Z6&PG=zRJdmLR7>>Ut{vu**~*yuy3-o_gfk7w=>?C zGv4oHyx+}uzn}3=WV}-u?+-HGS2EtS8SkqZ?+-KHA7{M(mht{9<NbNY`-_bCe`UP? zp7H)N<NX!;t^4x7%Y^=(u}9fsjOZ*%SO-p6g)k6$cdVd8sNaE66tYPrS6oyarq%$( z{=KXdN2L0LxF`&LtP`iJzG4y)8ldddng4wV;w<pjxcFGk`*AT??gwyz8Q8<Pzz*yY zTwn;+*-3_Ap-wUc8|oxOFi?NO5NxoM48dxN2DBI(<OL`uZRbl$fk1`BSx2u$Ry3VN z6wtXkhn`S%j%lpQT1FfDYRCZ@q=A#z+AkMpt~lAPLEIG-*DtMrsL#|UAVwpGGxD1J zL=eYOl_wy1RMdcOJV%sWs{~bthG!P4t5U4$1QBmlj;V+AX}ldN*lQhvy;qU6>KrR( za7tu2rOGM`BEA7;n_(pbRx{CgD4>LFA&=UZYqgE<A>9Af;~}Ys<9xx)J9eVSm&iBs z!}2=TqX$<&9MkRV=G8q$w^85YuOJo<l6O5#;;e3<h;<uDzSsx)l9-PdOq@UO^Z9tU z?$bjO1YHHz<wzOI!v*m|=|m3?Zb5n|FJe^Fn^<d65FJdLP$-WVN#W1}WN2Lh@t_DV zW_W4qO8B+fMR~Z>0WT4ZY4H-AiCiAzdcmiWCHLvp`c0BvN(UN?AU&&PWs*|PlnP0O zyO<R5mPk6z;-PY9e2e(D;#9k5QMoJSI8|#t2|&TQCFoGju~kz19L(?H)@G7f_TcQL zAYLh<a`bfNsKLvqa`bMkx`%i3`W|0JqADDPD31so?fOx>wQf%JgG!0%TEX{FSly>} zt3H)-w7T#vO1xS+S{T9GU4{1+O+<AU57CRt@#XSZ4aBWmAtpro4=|I9;97{#wr`S@ z6`)v=>Lj@)C#POg@+D2-8s<a1;ZA6>pFD#ObGGV4k6Jla(*qUxdTHl5*2;FBV^Mkc zIaa6a!E375T6-tV%P3dGw)Rb=8|35}$QmcZZKvX4R(K_fm>93`(J8=06Hat8pN_Px z15;!|08x0|lz18Nw2|0Ro3fj=TTODSyIb9C_112NO&o^n08zg7xw7artS`lCNfIqs z&n}nxET~^mRp52WegPG5C<xPn@yH}`&72ifGu9v;!mY(V#X3xtvY9PuXkNKWZlF4e zNODx-x~Az5Q*D56233ISh@Gt*Yb5i?dTErJ_~<#dQHB#&jzZuV-V}=MfpHybU)1~= z$R34Qanfv_G+QA4J{4~Tm8RJ=X|_$8?M^^fqfCifcO+un>ZG~4D<&f&>mB1$lW}UP zcTM4Wm`>b@Ya2NF#@G}p!l(E&{d-ipdtmfuw~}hN(mh~w-Nx>P8<OvXTc^Am?soM( z%(@pGp=2Jg_6*E6MM=kM&Vr0~%DlohHF<!IPfm$!-$Q*@pK!jtE2z8LUtSMvLm2pA zJs(~r+U!9#jzD~Mc$J4Rs?;tbjfeNK$!;}%B|f<KF#6&??|g9&v&kv(R*#T}Uh6S7 ziPthTtjr#w*ZQ!qWvrJzjI!@ykBhhY2(un%iH@!gX{_Un^^wdQoMw~b;XP9m@lGYV z4otN8wb%Z&9(=U;b-n#-1L$b+>qh(6M$peX#rT+8j8C90;<aTQW&b3btW9o$p(z#2 zpQCH~U#MWuI0btKMY@T77H$&6?&nyy@;nt%{St%SX<~ENW@&8m8S7b=*wVE{8ryO< zY=#ep`(Sw*lEVGg=UFHaz8S`+wc%SpQkv*8yUeS?gVsN?+C4hHH<gT0yJ05e_9j&O z3v8-eGq)zU!7i12+mky$OiI41lRK@KgzuW<F6*npw>!B9RHTzr$!o1|pcORpy5wFE zl1?V}nfuJ^lQ&r3g#SkKMl+Gz4{}_JLEY?S;iDG$uJE-a4_Mz9RS=+6^Dt@vbfnG) zano7)7N+RE*(-35$*(Z5<vKm<jP)u@+|+fGG<MTj3%sOGhlY`>sfCYEnMr)wpeDtS z+o#NK{P-zz`ufkvLuL4d=<GSvEAFAn|5ZBc9+CC0MApB7`%d{c%=&F6>)*3PPgjpL z)^pZ6m(CgnvQuX7_=K5qhDp)Y|45-GLJxXF|Kt|t&u(G<OB5zoK~Fe@viwDKgfS-l zMHGVEdYRn2nDQDfCz$#=gK2G|ud7cQ>qC>ij*Kv4JGs!P3U1wQ4TD3n#Tt{z*Pd** zz>+GslIiQeTgKQ2`%2BH8^0$d95TwawQx={b{~d43{5op(d>?Ch%QiI5o2M!bRSvm zrq~`y%meqsi;o&+YO>jn`ABo;qqD&<eczZ{s(bWqy}pOrbM?*U&E_o_ho2@BuPKyC zr}+poW=vBHzKc&;^Qlul&}-7*k16TB$Y4MicY|)Ij{IUs@1o&B4oPQ4$N(mDRV)r@ z@i9enIYtb6lK#~6xFUWml+Z06lw+zQ=06p~_4}QaSbWBmK5(&=-k+7yBO)rmA;fGE zKO}`q<AX9XeAK=Hl5P}&(Tx)O#)s@1B~)01VHpNxE)hw@I1$8{C+^*k$>#)8`WyR! zQW031^#J9SdEh?h0kFza-1rcP&D15N18^7<v~(*LchU;zZAtmMU(=uRp(mV1PpCY3 zw(=xq=#xEK<=AkKevSxfPs{W@J_*+^llu@;o|LU8W$FfJtfx?aJ$wRdwcz6lS{*C2 zB`43qMtWk(<VY(x#b8agQys^X?_=68WdroHu;Gs{gwV(Olsri@*hHA#5HlFe@!+1u z#FlIp7G0l4gz|1RUXB3kGjeb>@&G06r2T|*>oo2?D+i%2VOXD|#Q&O!)c?UvovK5m zPP3#)y-lS4g-q&gV6YATNJa`@qSWb$bn0!^m*wD#bnhj35*-&U@l`qa84CC&0^9;} zu*?QONTJ`M&=C~m11$V7i;v3j5r&7pD+h0<+v6xBs@R&46GzM=V82~QGvHB1>Sxv@ z$~4lgWj%UDkd~Z3kTI%;Kg8m<vE&sn)DEts#C|A>6hB7%vri+FAIZTY3jeuV)L+O! z6#-zJ4L{Dp@i3;nU&`02)V^S5#i~)o!|~%RbiNGV8KQxs6%A+omR<rA3GUyHPZCN0 zP7Z#NNk;H_2GdD-s)y3FJ}Gw_Wms@6mx9+Z30Z(T*a>05jR<*yS<ky6a<CC0Pcj(8 zJ8_g?6+)I;FS-G0Fo*!t`idK%1<#{cn_%$nJfa8xfPjAM8*Ts({ulutWiW(yqWFR@ zBc#uI*$ps)Uqrx8(C|7j{J~Ek;ARl$Ist*;V+eSPfk)Q~$qC+zkp0%HZa{AE2m%H{ zuIt3e3-%(Q#QKRFkRJqMZnzX2x=xH>a2*2fXVy>Mkb)o<*yvv%({<t$1_2X{dHdhp zfCbb!YiSj`d?9VemM`=f<@djFe&M%XJMVw}e9i0U`(8hPkNE%a>*wwNPrrWt+pnK5 zc_Z_`;f?d@{~d3f$Mg7DX=}9iHL*3aEO|1#1%t>VLLcyt@?=QDhx8|eUX>30vj}ao z{!6B1OHjo!@fn&q$uOUWiF52@n6dC}f1EM8e1gez`6N^5@-$OllVQJ4Yrjd_blv1E z{FYGne;uCzt=4ley3=}r6YuS_!T{KMLk<EH#2Qnk3dwNwE@c8=$UB(LbbNw-i6@d= ze8=~A0+1ao4IgoqhW9BGD0l(ww!Tjj-UHY++uN;AGx-5baT!AC%$}=WdO*R>i#?zK z7XSk&v!{`8@xo;&%=?t_@Mpx9C|n{oSK((I2I#+MC$JsaY`q^3(PLultzww-X!rO5 zN=h@UA1S;asXU5bs27r@i|Nz5om)xOl(n6sy>4dy^kKt0eM9%1%!V#I+sD$`E<m;) zRNPre#2S=0TmMrL!_a3j3{e4TAlibMAHj3e;u2r>DFjor^fO^O{!W=Vwx6)?D9|@X z1oa8Lb8s6H`ly}$v!3)@5d754>Hn>hN;(gEPULZ#D)Hk=qFj`+98;PmrnD8Lr1~!G zvZXt*$(FE$(g3NzvETYWonCwjEsog?o2|QWl17IUpF-n?*rych)5@fIMPkGpc~<nY zXOs!^1dHFzpeOqG!jIeWdl;D8KZ^oCD`F3u!_O9egiNHr$mHjd(myigbBgsm-9#?d z=aj@<Y|=c5zKUf|NF5>Y4y?&Wuo~;Si^-xC*5?(h#!Y5o3w0lxq9xB%2vd&dIRW~C z=Z?^G_c1lm7?MH~ws-M&Go{Y@f~Txs6#j0tvbHAvS4^#=9DxI|$$CMV#IQ)~1dK4& ziy|7Of@G2Eq<KG!KftuQAdZ);m!{o~<6N=M`kI~1d#FmjPB0A%NN=we_I-*~lK3D? z)R;Aq#AD2S4B8#yB9!+Yr7^-*?l^<OxXK-l;J0DZa4I#p8#1)vv~ovG=yo^}R(m4M zS+~PUV@)OvNI10K6yOR2woq$5<T9hWtwjN>#I!)#ldY$Sjz)q4Ybv423Ou`k0TNyN zkBp?&Cl3?WE<~XHL&Kmi;Rw4fmApkgd}O5W&9yx)u!G7ntjWAV1FVaLx(8`n5Q?5q zeQ@+S(o!{7D}ePY5S2Mv4l`L21v4oN9g~>XkgLE1^mLyC(<mD0t*D&<qI1T298M8- zU+2JpDE^2o-ke{N)`h*w6={)1SgfUSy5W@4+}`ZZR6&-Rr+DG%f}$)b(#54l(WZ7N z`sQhjln#ACt-QFRq@s+KEiPM9wzT-N;#EojHnkan5j4G^1ZHc1fw{SWL`BL%qHQM5 zW|A3|3+Ye*l87o22kG@ZCv4Qi%y%izU5Sy7#168;Au&O+0%%Y%3g4~xA(!$CguOgT z$B_zRY0Kp5<)Iqk)(W?-fkGm}A7urFhKz%59D?WLlhu+q;Ku1R&bP4!0S`jK1|)(! zaQd9Ks#Fx6SK(VX?9*q1PM-~nk6%la=>ed8ZIK0-0uG*aP8#__FW66d!2t#*M~0KD zz{yidP1s~%zf~|14p@bgd*ryv>R>oCF}YF0=CugJkD?;OJxFKKcqAkNOR7XF#{n~| zuqtRc^^csf7KfyfSAtkI7}k<R0HG6RjtR{+am|YdkkaCb7e`*1m@N7s5I-vIvQ{B+ zVvN`9u}w=XAcKoYqR1?Y*c{Lxf)=`KeFf>UZ4ngo+_BA8oXA!q-i2XdH07#rhDf8; z)z-;U$aUhyE`EQev^~mU3uZ`?JBrEy4<6>+6(MI-b^Ct`9^t9UY}IDFCLQhOSlhg5 zH_y>Dnr4+5b=B?ix#Lq)G&0*z2;0O~pI3dk7+_q4Fp;Ie%z1$GT+qHdnxeSiJ6H2{ zp~qY%)R@aFq{Z@*%B5Ay$gQ4Tk9pn^CccN#*q=v3&(LrR%4!ENiKd1JlLPKIq0b3D z7rL7_QcAd{Q$k%z>2B@`ukRZjJ-oW1;kMguTb1k`>Q1c!4sb&(5@~5LL9>9uG`NLP zigElc$&lQmv>5A9Xi&hz>mv`W0kPa+4kpYyc>0|LkZ}WP=Mh0edL^^I03V$Va_ru_ zM6e9rLkkuxmOAGOnjwm@#w`Y_N{4O^u^A1b)S6HS^1=LPcs;Zji=gPS6I@*VW`C+z zps3Ju-pNs3z1meFdh?}?4&^`S06D7=zne?vC_4b{+G!Qk&;$H|(bS&7esFS9wyvt` z4pH0^XNtFf?H<|%-J-#Rp-A??l&!sOuQY`9Ggf}~la2-#sf-;=L1{J5Q!}BqW}jQG z{4LiA?I$Ql4fI2`$n9VG{eyTEP~KYxd;39JSK<t>tEa^Wi%a4L^=6P7!d`Jz?yeMQ zGO#$@NC@IA1=Xq%XbQ3+HbT`&31Qhcy+&qyWvInXkB3&<GkEI-?M94e*_|-mQ)e4; zY%A-zbTNWK5t-cRsYpR@Mi$kyU<QJ8b8vd&LRqM(t!Ty<1UFezQ^_pv1QM~fR-c=d z(%#&jFYr%teZgYAc#&3FTvbvf6m&|8t9{EA15$GCGk`M8e3fKu1-%?tU8(t8EdV$Q zR~L{Wv<9`5GOm?#Z86uDKtV?{c<wTu7b5g!?J}-~xlzH5mE2gxjRtN+xCY#nHC$WE zwJW)=)957PD4?YJjG{3g^ZBDED&UWeVVB;B!9<tzCK)ViZNgnG+{=Y~g>XBByN)d} z48MfUk_Ia+pGsC*9da2~W2}599JyjAmM6;MotlDSN@Gi~7{f9QOEg8rT8PZFJZP-p z{Wx<;5|kpekrXJ({E@=|6|sC$=Q&V9L8R=Lw_pvXTy3qNc%%^7S{o`iTk(W45my+5 zty?C;d02jpoVB{9LgyFYjK;cZaw;UBg5p1JUp+Z#>LGR-*kL0$E8N+wh9b|n=xzAX z{%PCF^qR@=!c&O9dom%{_h_bE{~}}pTDP8*N&I{YXEU;<s>Y9HlrSxYEhQ;z<w;u* z;TM94lO%_z91D=@fe=SjKs0-+eate3C_#%Be7E6fKrwSpP)S^&ftf3Q;%HsS5X>AA zCl~N?Xg2Fu@Flo+q*!<<g+E76;@Dk84KFqG#EBE#p&uuM82!cL`6p2z>z(8$J%ncq z*C3TUVV)eMpm>m(1yojuSMggrS_noV>n`~5OAXghShzM`$WDdpPMxBZ?y>L5l}}T- zDb`6k*%Hy~PvIh;LXNUEB9g!>(mPwjxB>KB4a?a3SP-)AEU7d}qu)b0LLA-rW%=v! zf`wWU%+z7wjsuetN%2diWYxP!(gKo#m9=^^8sTx0iJb(ppHCt&sliUc^~)b))@e3D z<{i(Hlmb#w@#DUeXM)fjfgm*9b0GY5yUxdPv~hj`-oyF?M2G3l^Ry5EqKm6qKmb`G z+h^#sK*IuDDaUNft)+>jUVFg4B?z-o*=hk^=Ur9I#7*EXFOExF=Q5t9*B3LTiP_Uu z%iWkB^=Dv3z`6npjp5YlnUYv-Qzq;s`Vo5vZ(BReLy8zOFF6%K95N57%tu)SMaw0Z zMev$zxmc6DmG(+ghs;w-X#LG^zf5WFBGHZJCn2=hd?X|~(EKDcPbCuFXg*3LdeXMH z-)i=kpC(_T5nvuuLv77lYN8S6F}3+Dn`q8?E1PK3u1jsxU4rI|8g#yrLXFK&Qlcs6 zE2()am1xBIDb@V6piLP>E$Fd})9uhpE~k??YH#bM_B1=G#tl?bpZjC}QbiHhz5OB* z2@@Hax<ZIc7<BEia*LDThPPiPo3o2bb?J$q&f{;tBm}Ssl(W55mib6#UP>c)<SxB5 zVwAarZkWx_MK!ej?N@YmVs@8|UNpIx7V3aOoP8C~omKor&r#;I@1S!O+BDoaQ(2tD zVjQJ_)C*i(txo>?V0Z=g^k{3W%?Y_4z;!Uiih+X5%V`O2_!!_~!PDi>tQ}Pl!8a2> ze0wGk4DjHGR~wt6p1|wX#@0pzw#C|~u`upcn__K^;Dv8(n|5cP3Yx5T*lsm7O}leF z&Tyj5YI9>W;-x0stKxv92_{|5E#BaLY6~EFh~g~f4ZhyyI|Jugn-gpghH7gx(g>%$ z*<nI;$4C&n$J*3ZSaYc~Oo1P*4P5SmjgLkd;&yL$2>xJ97HKAnvPPf#&5~(ZJBZq& zZEny$wY|Bel_=F(^0GS|S)et=E+C^raAQ-NSbau1J*BOsNdvEXm9Me*C;%ds&}kKj zy@1LmFXwCpS77Y5hU~hOPOfa=$|e|cab+7<uI9=vuE1;yHd{Ax<p5W@xsu|_LD*(- z1vXnlWQGMBEcG_yHU?7xI@OldF<|@v76^#+<TJ?UCm*)+at{5<9iwxnJPLz6kjX*v zfd`$*h2#UP5zL;*heHJ>7n2W+=u9pp9~jY@Tt+_F&fxTle2dAqgnZycXG$e}3YgHD z8iG%)!T!G%e|7k)N2qog#RLO7lUI^&75N(I87NSxU~G|M;;6n3@EUF4sUvr_a4#3` zTH#(P+z#Qc6YhH9ZWL}@xSNH$MYvZ9cdKx>3wMWbcMA6!;qDgh9^qam+`YoRUbr_1 zHzC~p!o5kjN#XVgw^z8PaQlRNvv6+_?jhk03iq&ZZx!x{aE}Q07|`}Kscwb79@Qf0 z>qu71*ORQ4uaiIz?pu$8MAawg!HspWMAD7*Fht`1^+XTu7xdr(K@T1f^x!#y9y~|T zgXao*a8SmB9z0LbgXal)@ci{e51zk{=)r@69vs?jpa(Ay^xz;W2R%5j5<w3R+(giW zgQy(z;2<prJ@`UF4-V3D(1U}t9Q5FzD+fJz$vUZuRf4E|8LI+Oc{N)GqH@rKgQ$Et z3xTK{^xz;W2R%3_%0Ul~-doQq=<ss|Nu>c=h;yTQyu2L5xshy@Cl(WxcZC%|_zMf^ zjL$wSO3ULM2n2CNq)-=HF93XP`R!`=?p)ADactzKzQ%c;L@iz@1@3?gXhOfhD^$@& zNe?CqwZn#DXmFD9tVwOG24M$YD42RvoxoWb>|HNF8yu!$e@2R|0yDtOP#N1tP9uFo zK>zS+d}JXsIO|?t?-84!(Jx9Yv^TQUAhg|Ewr#xT0tFV5tqhOqX0jJT639o=0&nMS z8Yp{}0OmNw*>PlarbvCjuG5l(2Vr}2j2*Y%V1Qs9FrxR#S8vhnx5wel1?j_pcoY(@ zRPX8wYluV=7oD}|(&_>A0}A|<xhvz%w7QUf#2SGk*Ai9fU6rP$HkIB-K)1FxMO+My zS>*89QmkwV*IPy;(rr1j7pwW=YAcPAm=bMk4nX28gUuj-FPXq)%K$OE27p0zq@_ZD zMVvE06#=;}muq=k&xfWZmkYTJY}o~5vaFVHA5dk>xm@7@%j%_EhVZ3|%ORS`WEdH{ z*s=hYg|4RD#En*?6;`@!+}F<itGWMj?qAFOuwcHDV=^Mm72R*^w}6sLVmbQK`=LZr zD&;K0RF${5ek{M5;_<M&vSC$3xKZIY3b$FfEgf{XQ~1}h%3Q)s(&P?|q5?AsjFe!{ z6WT6I$(U2&WXuV{2;h|}G2TFfg=R~Cz_Ghjlt4}tnjjc<$nG*onlC{>+`;Y=DEYNe ze^~(YOW7(KPbi^Sm%;#}T8uGCR$%^1Dl?TfT2koeaSoM~D%&=a4%lHIxeO5%Majt{ z0~v^SY!i)zY!S&oa&5Uto?|Bn^%rT81*OPwx?@!c34v_-&A=F<KnDiMOOF(Wa0m~s z6qSrL%wUI1aGFTFnoykzq1+crEP#@0omB%%KG>J)vSLVbt^|bKJkpB^<kTZ}oj`^) z)yhRA0ssW33RB5Cpu<+;<r)&j@nZZUL|9El?R4P@fV`e#`BLLKR?Ql%X3!SNX30b3 zmOd0;g!gWlm`s$JWoG&E=h%}^#4Dii(`v^Okwly}qzL*t=HDpv4*iKLvTKYas?F+1 zB4maliRI?<h^>lPYt}{*E6f!$U~De#t3-)xt;AQTVKMf*<QLNfxUT%5M%wiD<OkXE zW6TEY(>sdnTbc9c?C{moM9s7<vPIgq5aN>4!wyo+2UpCwU?UrbdO+YiI7(%5xBGK0 z&#)t5cSPxw)+MKbcUn8w*Kx}+LM6C_r;)d#UXVHY$Zpb$G<E-IKNK%+Pq_~W9+r`` z+QGEmN!kLojLD5}t0^>0i#MBk!Ubv!2M!z@IxsqP0JuT|Pk(3-kT(N|g+jobK7h<d zHoIi$J#1S`qmcgl`_sJ$s3DQ|{Ne2G0BDfbD0r5eTMYNkh}slw!=^IU(pH*5{de=R zYfNndAGFejO)z#+K_8Tr<$wU>5c3w`&q=kioGXjDQpuHSqX5*TG!8IW{ll7n4D=|F z+CxN&Ujh7L*a*oicTB^6DSr$`IFLOezELC>mzFFNZkcc^gu6tzONCn{+-1TI33oZB z2~9G5+B#aYYwKyrj)i-A$&TfFddZIEJ1yA>JAhMx1RD$UWtO}IH|#8V%MyNC@~T2U vdgX$LP(+&3GHau36*+=Sl`qa|#b&u}KRR2&juzt#d|6Tl%JhE$aI&Xx7{a|1 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/nonbreaking/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/nonbreaking/editor_plugin.js new file mode 100644 index 0000000..687f548 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/nonbreaking/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.Nonbreaking",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceNonBreaking",function(){a.execCommand("mceInsertContent",false,(a.plugins.visualchars&&a.plugins.visualchars.state)?'<span data-mce-bogus="1" class="mceItemHidden mceItemNbsp">&nbsp;</span>':"&nbsp;")});a.addButton("nonbreaking",{title:"nonbreaking.nonbreaking_desc",cmd:"mceNonBreaking"});if(a.getParam("nonbreaking_force_tab")){a.onKeyDown.add(function(d,f){if(f.keyCode==9){f.preventDefault();d.execCommand("mceNonBreaking");d.execCommand("mceNonBreaking");d.execCommand("mceNonBreaking")}})}},getInfo:function(){return{longname:"Nonbreaking space",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("nonbreaking",tinymce.plugins.Nonbreaking)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js new file mode 100644 index 0000000..d492fbe --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js @@ -0,0 +1,54 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.Nonbreaking', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceNonBreaking', function() { + ed.execCommand('mceInsertContent', false, (ed.plugins.visualchars && ed.plugins.visualchars.state) ? '<span data-mce-bogus="1" class="mceItemHidden mceItemNbsp">&nbsp;</span>' : '&nbsp;'); + }); + + // Register buttons + ed.addButton('nonbreaking', {title : 'nonbreaking.nonbreaking_desc', cmd : 'mceNonBreaking'}); + + if (ed.getParam('nonbreaking_force_tab')) { + ed.onKeyDown.add(function(ed, e) { + if (e.keyCode == 9) { + e.preventDefault(); + + ed.execCommand('mceNonBreaking'); + ed.execCommand('mceNonBreaking'); + ed.execCommand('mceNonBreaking'); + } + }); + } + }, + + getInfo : function() { + return { + longname : 'Nonbreaking space', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + + // Private methods + }); + + // Register plugin + tinymce.PluginManager.add('nonbreaking', tinymce.plugins.Nonbreaking); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/noneditable/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/noneditable/editor_plugin.js new file mode 100644 index 0000000..2d60138 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/noneditable/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.dom.Event;tinymce.create("tinymce.plugins.NonEditablePlugin",{init:function(d,e){var f=this,c,b,g;f.editor=d;c=d.getParam("noneditable_editable_class","mceEditable");b=d.getParam("noneditable_noneditable_class","mceNonEditable");d.onNodeChange.addToTop(function(i,h,l){var k,j;k=i.dom.getParent(i.selection.getStart(),function(m){return i.dom.hasClass(m,b)});j=i.dom.getParent(i.selection.getEnd(),function(m){return i.dom.hasClass(m,b)});if(k||j){g=1;f._setDisabled(1);return false}else{if(g==1){f._setDisabled(0);g=0}}})},getInfo:function(){return{longname:"Non editable elements",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_block:function(c,d){var b=d.keyCode;if((b>32&&b<41)||(b>111&&b<124)){return}return a.cancel(d)},_setDisabled:function(d){var c=this,b=c.editor;tinymce.each(b.controlManager.controls,function(e){e.setDisabled(d)});if(d!==c.disabled){if(d){b.onKeyDown.addToTop(c._block);b.onKeyPress.addToTop(c._block);b.onKeyUp.addToTop(c._block);b.onPaste.addToTop(c._block);b.onContextMenu.addToTop(c._block)}else{b.onKeyDown.remove(c._block);b.onKeyPress.remove(c._block);b.onKeyUp.remove(c._block);b.onPaste.remove(c._block);b.onContextMenu.remove(c._block)}c.disabled=d}}});tinymce.PluginManager.add("noneditable",tinymce.plugins.NonEditablePlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/noneditable/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/noneditable/editor_plugin_src.js new file mode 100644 index 0000000..916dce2 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/noneditable/editor_plugin_src.js @@ -0,0 +1,95 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var Event = tinymce.dom.Event; + + tinymce.create('tinymce.plugins.NonEditablePlugin', { + init : function(ed, url) { + var t = this, editClass, nonEditClass, state; + + t.editor = ed; + editClass = ed.getParam("noneditable_editable_class", "mceEditable"); + nonEditClass = ed.getParam("noneditable_noneditable_class", "mceNonEditable"); + + ed.onNodeChange.addToTop(function(ed, cm, n) { + var sc, ec; + + // Block if start or end is inside a non editable element + sc = ed.dom.getParent(ed.selection.getStart(), function(n) { + return ed.dom.hasClass(n, nonEditClass); + }); + + ec = ed.dom.getParent(ed.selection.getEnd(), function(n) { + return ed.dom.hasClass(n, nonEditClass); + }); + + // Block or unblock + if (sc || ec) { + state = 1; + t._setDisabled(1); + return false; + } else if (state == 1) { + t._setDisabled(0); + state = 0; + } + }); + }, + + getInfo : function() { + return { + longname : 'Non editable elements', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + _block : function(ed, e) { + var k = e.keyCode; + + // Don't block arrow keys, pg up/down, and F1-F12 + if ((k > 32 && k < 41) || (k > 111 && k < 124)) + return; + + return Event.cancel(e); + }, + + _setDisabled : function(s) { + var t = this, ed = t.editor; + + tinymce.each(ed.controlManager.controls, function(c) { + c.setDisabled(s); + }); + + if (s !== t.disabled) { + if (s) { + ed.onKeyDown.addToTop(t._block); + ed.onKeyPress.addToTop(t._block); + ed.onKeyUp.addToTop(t._block); + ed.onPaste.addToTop(t._block); + ed.onContextMenu.addToTop(t._block); + } else { + ed.onKeyDown.remove(t._block); + ed.onKeyPress.remove(t._block); + ed.onKeyUp.remove(t._block); + ed.onPaste.remove(t._block); + ed.onContextMenu.remove(t._block); + } + + t.disabled = s; + } + } + }); + + // Register plugin + tinymce.PluginManager.add('noneditable', tinymce.plugins.NonEditablePlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/pagebreak/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/pagebreak/editor_plugin.js new file mode 100644 index 0000000..35085e8 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/pagebreak/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.PageBreakPlugin",{init:function(b,d){var f='<img src="'+b.theme.url+'/img/trans.gif" class="mcePageBreak mceItemNoResize" />',a="mcePageBreak",c=b.getParam("pagebreak_separator","<!-- pagebreak -->"),e;e=new RegExp(c.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(g){return"\\"+g}),"g");b.addCommand("mcePageBreak",function(){b.execCommand("mceInsertContent",0,f)});b.addButton("pagebreak",{title:"pagebreak.desc",cmd:a});b.onInit.add(function(){if(b.theme.onResolveName){b.theme.onResolveName.add(function(g,h){if(h.node.nodeName=="IMG"&&b.dom.hasClass(h.node,a)){h.name="pagebreak"}})}});b.onClick.add(function(g,h){h=h.target;if(h.nodeName==="IMG"&&g.dom.hasClass(h,a)){g.selection.select(h)}});b.onNodeChange.add(function(h,g,i){g.setActive("pagebreak",i.nodeName==="IMG"&&h.dom.hasClass(i,a))});b.onBeforeSetContent.add(function(g,h){h.content=h.content.replace(e,f)});b.onPostProcess.add(function(g,h){if(h.get){h.content=h.content.replace(/<img[^>]+>/g,function(i){if(i.indexOf('class="mcePageBreak')!==-1){i=c}return i})}})},getInfo:function(){return{longname:"PageBreak",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/pagebreak",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("pagebreak",tinymce.plugins.PageBreakPlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/pagebreak/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/pagebreak/editor_plugin_src.js new file mode 100644 index 0000000..a094c19 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/pagebreak/editor_plugin_src.js @@ -0,0 +1,74 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.PageBreakPlugin', { + init : function(ed, url) { + var pb = '<img src="' + ed.theme.url + '/img/trans.gif" class="mcePageBreak mceItemNoResize" />', cls = 'mcePageBreak', sep = ed.getParam('pagebreak_separator', '<!-- pagebreak -->'), pbRE; + + pbRE = new RegExp(sep.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g, function(a) {return '\\' + a;}), 'g'); + + // Register commands + ed.addCommand('mcePageBreak', function() { + ed.execCommand('mceInsertContent', 0, pb); + }); + + // Register buttons + ed.addButton('pagebreak', {title : 'pagebreak.desc', cmd : cls}); + + ed.onInit.add(function() { + if (ed.theme.onResolveName) { + ed.theme.onResolveName.add(function(th, o) { + if (o.node.nodeName == 'IMG' && ed.dom.hasClass(o.node, cls)) + o.name = 'pagebreak'; + }); + } + }); + + ed.onClick.add(function(ed, e) { + e = e.target; + + if (e.nodeName === 'IMG' && ed.dom.hasClass(e, cls)) + ed.selection.select(e); + }); + + ed.onNodeChange.add(function(ed, cm, n) { + cm.setActive('pagebreak', n.nodeName === 'IMG' && ed.dom.hasClass(n, cls)); + }); + + ed.onBeforeSetContent.add(function(ed, o) { + o.content = o.content.replace(pbRE, pb); + }); + + ed.onPostProcess.add(function(ed, o) { + if (o.get) + o.content = o.content.replace(/<img[^>]+>/g, function(im) { + if (im.indexOf('class="mcePageBreak') !== -1) + im = sep; + + return im; + }); + }); + }, + + getInfo : function() { + return { + longname : 'PageBreak', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/pagebreak', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('pagebreak', tinymce.plugins.PageBreakPlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/paste/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/paste/editor_plugin.js new file mode 100644 index 0000000..e47a5c6 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/paste/editor_plugin.js @@ -0,0 +1 @@ +(function(){var c=tinymce.each,a={paste_auto_cleanup_on_paste:true,paste_enable_default_filters:true,paste_block_drop:false,paste_retain_style_properties:"none",paste_strip_class_attributes:"mso",paste_remove_spans:false,paste_remove_styles:false,paste_remove_styles_if_webkit:true,paste_convert_middot_lists:true,paste_convert_headers_to_strong:false,paste_dialog_width:"450",paste_dialog_height:"400",paste_text_use_dialog:false,paste_text_sticky:false,paste_text_sticky_default:false,paste_text_notifyalways:false,paste_text_linebreaktype:"combined",paste_text_replacements:[[/\u2026/g,"..."],[/[\x93\x94\u201c\u201d]/g,'"'],[/[\x60\x91\x92\u2018\u2019]/g,"'"]]};function b(d,e){return d.getParam(e,a[e])}tinymce.create("tinymce.plugins.PastePlugin",{init:function(d,e){var f=this;f.editor=d;f.url=e;f.onPreProcess=new tinymce.util.Dispatcher(f);f.onPostProcess=new tinymce.util.Dispatcher(f);f.onPreProcess.add(f._preProcess);f.onPostProcess.add(f._postProcess);f.onPreProcess.add(function(i,j){d.execCallback("paste_preprocess",i,j)});f.onPostProcess.add(function(i,j){d.execCallback("paste_postprocess",i,j)});d.onKeyDown.addToTop(function(i,j){if(((tinymce.isMac?j.metaKey:j.ctrlKey)&&j.keyCode==86)||(j.shiftKey&&j.keyCode==45)){return false}});d.pasteAsPlainText=b(d,"paste_text_sticky_default");function h(l,j){var k=d.dom,i;f.onPreProcess.dispatch(f,l);l.node=k.create("div",0,l.content);if(tinymce.isGecko){i=d.selection.getRng(true);if(i.startContainer==i.endContainer&&i.startContainer.nodeType==3){if(l.node.childNodes.length===1&&/^(p|h[1-6]|pre)$/i.test(l.node.firstChild.nodeName)&&l.content.indexOf("__MCE_ITEM__")===-1){k.remove(l.node.firstChild,true)}}}f.onPostProcess.dispatch(f,l);l.content=d.serializer.serialize(l.node,{getInner:1,forced_root_block:""});if((!j)&&(d.pasteAsPlainText)){f._insertPlainText(l.content);if(!b(d,"paste_text_sticky")){d.pasteAsPlainText=false;d.controlManager.setActive("pastetext",false)}}else{f._insert(l.content)}}d.addCommand("mceInsertClipboardContent",function(i,j){h(j,true)});if(!b(d,"paste_text_use_dialog")){d.addCommand("mcePasteText",function(j,i){var k=tinymce.util.Cookie;d.pasteAsPlainText=!d.pasteAsPlainText;d.controlManager.setActive("pastetext",d.pasteAsPlainText);if((d.pasteAsPlainText)&&(!k.get("tinymcePasteText"))){if(b(d,"paste_text_sticky")){d.windowManager.alert(d.translate("paste.plaintext_mode_sticky"))}else{d.windowManager.alert(d.translate("paste.plaintext_mode"))}if(!b(d,"paste_text_notifyalways")){k.set("tinymcePasteText","1",new Date(new Date().getFullYear()+1,12,31))}}})}d.addButton("pastetext",{title:"paste.paste_text_desc",cmd:"mcePasteText"});d.addButton("selectall",{title:"paste.selectall_desc",cmd:"selectall"});function g(s){var l,p,j,t,k=d.selection,o=d.dom,q=d.getBody(),i,r;if(s.clipboardData||o.doc.dataTransfer){r=(s.clipboardData||o.doc.dataTransfer).getData("Text");if(d.pasteAsPlainText){s.preventDefault();h({content:o.encode(r).replace(/\r?\n/g,"<br />")});return}}if(o.get("_mcePaste")){return}l=o.add(q,"div",{id:"_mcePaste","class":"mcePaste","data-mce-bogus":"1"},"\uFEFF\uFEFF");if(q!=d.getDoc().body){i=o.getPos(d.selection.getStart(),q).y}else{i=q.scrollTop+o.getViewPort(d.getWin()).y}o.setStyles(l,{position:"absolute",left:tinymce.isGecko?-40:0,top:i-25,width:1,height:1,overflow:"hidden"});if(tinymce.isIE){t=k.getRng();j=o.doc.body.createTextRange();j.moveToElementText(l);j.execCommand("Paste");o.remove(l);if(l.innerHTML==="\uFEFF\uFEFF"){d.execCommand("mcePasteWord");s.preventDefault();return}k.setRng(t);k.setContent("");setTimeout(function(){h({content:l.innerHTML})},0);return tinymce.dom.Event.cancel(s)}else{function m(n){n.preventDefault()}o.bind(d.getDoc(),"mousedown",m);o.bind(d.getDoc(),"keydown",m);p=d.selection.getRng();l=l.firstChild;j=d.getDoc().createRange();j.setStart(l,0);j.setEnd(l,2);k.setRng(j);window.setTimeout(function(){var u="",n;if(!o.select("div.mcePaste > div.mcePaste").length){n=o.select("div.mcePaste");c(n,function(w){var v=w.firstChild;if(v&&v.nodeName=="DIV"&&v.style.marginTop&&v.style.backgroundColor){o.remove(v,1)}c(o.select("span.Apple-style-span",w),function(x){o.remove(x,1)});c(o.select("br[data-mce-bogus]",w),function(x){o.remove(x)});if(w.parentNode.className!="mcePaste"){u+=w.innerHTML}})}else{u="<p>"+o.encode(r).replace(/\r?\n\r?\n/g,"</p><p>").replace(/\r?\n/g,"<br />")+"</p>"}c(o.select("div.mcePaste"),function(v){o.remove(v)});if(p){k.setRng(p)}h({content:u});o.unbind(d.getDoc(),"mousedown",m);o.unbind(d.getDoc(),"keydown",m)},0)}}if(b(d,"paste_auto_cleanup_on_paste")){if(tinymce.isOpera||/Firefox\/2/.test(navigator.userAgent)){d.onKeyDown.addToTop(function(i,j){if(((tinymce.isMac?j.metaKey:j.ctrlKey)&&j.keyCode==86)||(j.shiftKey&&j.keyCode==45)){g(j)}})}else{d.onPaste.addToTop(function(i,j){return g(j)})}}d.onInit.add(function(){d.controlManager.setActive("pastetext",d.pasteAsPlainText);if(b(d,"paste_block_drop")){d.dom.bind(d.getBody(),["dragend","dragover","draggesture","dragdrop","drop","drag"],function(i){i.preventDefault();i.stopPropagation();return false})}});f._legacySupport()},getInfo:function(){return{longname:"Paste text/word",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_preProcess:function(g,e){var k=this.editor,j=e.content,p=tinymce.grep,n=tinymce.explode,f=tinymce.trim,l,i;function d(h){c(h,function(o){if(o.constructor==RegExp){j=j.replace(o,"")}else{j=j.replace(o[0],o[1])}})}if(k.settings.paste_enable_default_filters==false){return}if(tinymce.isIE&&document.documentMode>=9){d([[/(?:<br>&nbsp;[\s\r\n]+|<br>)*(<\/?(h[1-6r]|p|div|address|pre|form|table|tbody|thead|tfoot|th|tr|td|li|ol|ul|caption|blockquote|center|dl|dt|dd|dir|fieldset)[^>]*>)(?:<br>&nbsp;[\s\r\n]+|<br>)*/g,"$1"]]);d([[/<br><br>/g,"<BR><BR>"],[/<br>/g," "],[/<BR><BR>/g,"<br>"]])}if(/class="?Mso|style="[^"]*\bmso-|w:WordDocument/i.test(j)||e.wordContent){e.wordContent=true;d([/^\s*(&nbsp;)+/gi,/(&nbsp;|<br[^>]*>)+\s*$/gi]);if(b(k,"paste_convert_headers_to_strong")){j=j.replace(/<p [^>]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi,"<p><strong>$1</strong></p>")}if(b(k,"paste_convert_middot_lists")){d([[/<!--\[if !supportLists\]-->/gi,"$&__MCE_ITEM__"],[/(<span[^>]+(?:mso-list:|:\s*symbol)[^>]+>)/gi,"$1__MCE_ITEM__"],[/(<p[^>]+(?:MsoListParagraph)[^>]+>)/gi,"$1__MCE_ITEM__"]])}d([/<!--[\s\S]+?-->/gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/&nbsp;/gi,"\u00a0"]]);do{l=j.length;j=j.replace(/(<[a-z][^>]*\s)(?:id|name|language|type|on\w+|\w+:\w+)=(?:"[^"]*"|\w+)\s?/gi,"$1")}while(l!=j.length);if(b(k,"paste_retain_style_properties").replace(/^none$/i,"").length==0){j=j.replace(/<\/?span[^>]*>/gi,"")}else{d([[/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,function(o,h){return(h.length>0)?h.replace(/./," ").slice(Math.floor(h.length/2)).split("").join("\u00a0"):""}],[/(<[a-z][^>]*)\sstyle="([^"]*)"/gi,function(t,h,r){var u=[],o=0,q=n(f(r).replace(/&quot;/gi,"'"),";");c(q,function(s){var w,y,z=n(s,":");function x(A){return A+((A!=="0")&&(/\d$/.test(A)))?"px":""}if(z.length==2){w=z[0].toLowerCase();y=z[1].toLowerCase();switch(w){case"mso-padding-alt":case"mso-padding-top-alt":case"mso-padding-right-alt":case"mso-padding-bottom-alt":case"mso-padding-left-alt":case"mso-margin-alt":case"mso-margin-top-alt":case"mso-margin-right-alt":case"mso-margin-bottom-alt":case"mso-margin-left-alt":case"mso-table-layout-alt":case"mso-height":case"mso-width":case"mso-vertical-align-alt":u[o++]=w.replace(/^mso-|-alt$/g,"")+":"+x(y);return;case"horiz-align":u[o++]="text-align:"+y;return;case"vert-align":u[o++]="vertical-align:"+y;return;case"font-color":case"mso-foreground":u[o++]="color:"+y;return;case"mso-background":case"mso-highlight":u[o++]="background:"+y;return;case"mso-default-height":u[o++]="min-height:"+x(y);return;case"mso-default-width":u[o++]="min-width:"+x(y);return;case"mso-padding-between-alt":u[o++]="border-collapse:separate;border-spacing:"+x(y);return;case"text-line-through":if((y=="single")||(y=="double")){u[o++]="text-decoration:line-through"}return;case"mso-zero-height":if(y=="yes"){u[o++]="display:none"}return}if(/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?!align|decor|indent|trans)|top-bar|version|vnd|word-break)/.test(w)){return}u[o++]=w+":"+z[1]}});if(o>0){return h+' style="'+u.join(";")+'"'}else{return h}}]])}}if(b(k,"paste_convert_headers_to_strong")){d([[/<h[1-6][^>]*>/gi,"<p><strong>"],[/<\/h[1-6][^>]*>/gi,"</strong></p>"]])}d([[/Version:[\d.]+\nStartHTML:\d+\nEndHTML:\d+\nStartFragment:\d+\nEndFragment:\d+/gi,""]]);i=b(k,"paste_strip_class_attributes");if(i!=="none"){function m(q,o){if(i==="all"){return""}var h=p(n(o.replace(/^(["'])(.*)\1$/,"$2")," "),function(r){return(/^(?!mso)/i.test(r))});return h.length?' class="'+h.join(" ")+'"':""}j=j.replace(/ class="([^"]+)"/gi,m);j=j.replace(/ class=([\-\w]+)/gi,m)}if(b(k,"paste_remove_spans")){j=j.replace(/<\/?span[^>]*>/gi,"")}e.content=j},_postProcess:function(g,i){var f=this,e=f.editor,h=e.dom,d;if(e.settings.paste_enable_default_filters==false){return}if(i.wordContent){c(h.select("a",i.node),function(j){if(!j.href||j.href.indexOf("#_Toc")!=-1){h.remove(j,1)}});if(b(e,"paste_convert_middot_lists")){f._convertLists(g,i)}d=b(e,"paste_retain_style_properties");if((tinymce.is(d,"string"))&&(d!=="all")&&(d!=="*")){d=tinymce.explode(d.replace(/^none$/i,""));c(h.select("*",i.node),function(m){var n={},k=0,l,o,j;if(d){for(l=0;l<d.length;l++){o=d[l];j=h.getStyle(m,o);if(j){n[o]=j;k++}}}h.setAttrib(m,"style","");if(d&&k>0){h.setStyles(m,n)}else{if(m.nodeName=="SPAN"&&!m.className){h.remove(m,true)}}})}}if(b(e,"paste_remove_styles")||(b(e,"paste_remove_styles_if_webkit")&&tinymce.isWebKit)){c(h.select("*[style]",i.node),function(j){j.removeAttribute("style");j.removeAttribute("data-mce-style")})}else{if(tinymce.isWebKit){c(h.select("*",i.node),function(j){j.removeAttribute("data-mce-style")})}}},_convertLists:function(g,e){var i=g.editor.dom,h,l,d=-1,f,m=[],k,j;c(i.select("p",e.node),function(t){var q,u="",s,r,n,o;for(q=t.firstChild;q&&q.nodeType==3;q=q.nextSibling){u+=q.nodeValue}u=t.innerHTML.replace(/<\/?\w+[^>]*>/gi,"").replace(/&nbsp;/g,"\u00a0");if(/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*\u00a0*/.test(u)){s="ul"}if(/^__MCE_ITEM__\s*\w+\.\s*\u00a0+/.test(u)){s="ol"}if(s){f=parseFloat(t.style.marginLeft||0);if(f>d){m.push(f)}if(!h||s!=k){h=i.create(s);i.insertAfter(h,t)}else{if(f>d){h=l.appendChild(i.create(s))}else{if(f<d){n=tinymce.inArray(m,f);o=i.getParents(h.parentNode,s);h=o[o.length-1-n]||h}}}c(i.select("span",t),function(v){var p=v.innerHTML.replace(/<\/?\w+[^>]*>/gi,"");if(s=="ul"&&/^__MCE_ITEM__[\u2022\u00b7\u00a7\u00d8o\u25CF]/.test(p)){i.remove(v)}else{if(/^__MCE_ITEM__[\s\S]*\w+\.(&nbsp;|\u00a0)*\s*/.test(p)){i.remove(v)}}});r=t.innerHTML;if(s=="ul"){r=t.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*(&nbsp;|\u00a0)+\s*/,"")}else{r=t.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^\s*\w+\.(&nbsp;|\u00a0)+\s*/,"")}l=h.appendChild(i.create("li",0,r));i.remove(t);d=f;k=s}else{h=d=0}});j=e.node.innerHTML;if(j.indexOf("__MCE_ITEM__")!=-1){e.node.innerHTML=j.replace(/__MCE_ITEM__/g,"")}},_insert:function(f,d){var e=this.editor,g=e.selection.getRng();if(!e.selection.isCollapsed()&&g.startContainer!=g.endContainer){e.getDoc().execCommand("Delete",false,null)}e.execCommand("mceInsertContent",false,f,{skip_undo:d})},_insertPlainText:function(g){var d=this.editor,e=b(d,"paste_text_linebreaktype"),i=b(d,"paste_text_replacements"),f=tinymce.is;function h(j){c(j,function(k){if(k.constructor==RegExp){g=g.replace(k,"")}else{g=g.replace(k[0],k[1])}})}if((typeof(g)==="string")&&(g.length>0)){if(/<(?:p|br|h[1-6]|ul|ol|dl|table|t[rdh]|div|blockquote|fieldset|pre|address|center)[^>]*>/i.test(g)){h([/[\n\r]+/g])}else{h([/\r+/g])}h([[/<\/(?:p|h[1-6]|ul|ol|dl|table|div|blockquote|fieldset|pre|address|center)>/gi,"\n\n"],[/<br[^>]*>|<\/tr>/gi,"\n"],[/<\/t[dh]>\s*<t[dh][^>]*>/gi,"\t"],/<[a-z!\/?][^>]*>/gi,[/&nbsp;/gi," "],[/(?:(?!\n)\s)*(\n+)(?:(?!\n)\s)*/gi,"$1"],[/\n{3,}/g,"\n\n"]]);g=d.dom.decode(tinymce.html.Entities.encodeRaw(g));if(f(i,"array")){h(i)}else{if(f(i,"string")){h(new RegExp(i,"gi"))}}if(e=="none"){h([[/\n+/g," "]])}else{if(e=="br"){h([[/\n/g,"<br />"]])}else{if(e=="p"){h([[/\n+/g,"</p><p>"],[/^(.*<\/p>)(<p>)$/,"<p>$1"]])}else{h([[/\n\n/g,"</p><p>"],[/^(.*<\/p>)(<p>)$/,"<p>$1"],[/\n/g,"<br />"]])}}}d.execCommand("mceInsertContent",false,g)}},_legacySupport:function(){var e=this,d=e.editor;d.addCommand("mcePasteWord",function(){d.windowManager.open({file:e.url+"/pasteword.htm",width:parseInt(b(d,"paste_dialog_width")),height:parseInt(b(d,"paste_dialog_height")),inline:1})});if(b(d,"paste_text_use_dialog")){d.addCommand("mcePasteText",function(){d.windowManager.open({file:e.url+"/pastetext.htm",width:parseInt(b(d,"paste_dialog_width")),height:parseInt(b(d,"paste_dialog_height")),inline:1})})}d.addButton("pasteword",{title:"paste.paste_word_desc",cmd:"mcePasteWord"})}});tinymce.PluginManager.add("paste",tinymce.plugins.PastePlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/paste/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/paste/editor_plugin_src.js new file mode 100644 index 0000000..73fe7fe --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/paste/editor_plugin_src.js @@ -0,0 +1,871 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var each = tinymce.each, + defs = { + paste_auto_cleanup_on_paste : true, + paste_enable_default_filters : true, + paste_block_drop : false, + paste_retain_style_properties : "none", + paste_strip_class_attributes : "mso", + paste_remove_spans : false, + paste_remove_styles : false, + paste_remove_styles_if_webkit : true, + paste_convert_middot_lists : true, + paste_convert_headers_to_strong : false, + paste_dialog_width : "450", + paste_dialog_height : "400", + paste_text_use_dialog : false, + paste_text_sticky : false, + paste_text_sticky_default : false, + paste_text_notifyalways : false, + paste_text_linebreaktype : "combined", + paste_text_replacements : [ + [/\u2026/g, "..."], + [/[\x93\x94\u201c\u201d]/g, '"'], + [/[\x60\x91\x92\u2018\u2019]/g, "'"] + ] + }; + + function getParam(ed, name) { + return ed.getParam(name, defs[name]); + } + + tinymce.create('tinymce.plugins.PastePlugin', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + t.url = url; + + // Setup plugin events + t.onPreProcess = new tinymce.util.Dispatcher(t); + t.onPostProcess = new tinymce.util.Dispatcher(t); + + // Register default handlers + t.onPreProcess.add(t._preProcess); + t.onPostProcess.add(t._postProcess); + + // Register optional preprocess handler + t.onPreProcess.add(function(pl, o) { + ed.execCallback('paste_preprocess', pl, o); + }); + + // Register optional postprocess + t.onPostProcess.add(function(pl, o) { + ed.execCallback('paste_postprocess', pl, o); + }); + + ed.onKeyDown.addToTop(function(ed, e) { + // Block ctrl+v from adding an undo level since the default logic in tinymce.Editor will add that + if (((tinymce.isMac ? e.metaKey : e.ctrlKey) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45)) + return false; // Stop other listeners + }); + + // Initialize plain text flag + ed.pasteAsPlainText = getParam(ed, 'paste_text_sticky_default'); + + // This function executes the process handlers and inserts the contents + // force_rich overrides plain text mode set by user, important for pasting with execCommand + function process(o, force_rich) { + var dom = ed.dom, rng; + + // Execute pre process handlers + t.onPreProcess.dispatch(t, o); + + // Create DOM structure + o.node = dom.create('div', 0, o.content); + + // If pasting inside the same element and the contents is only one block + // remove the block and keep the text since Firefox will copy parts of pre and h1-h6 as a pre element + if (tinymce.isGecko) { + rng = ed.selection.getRng(true); + if (rng.startContainer == rng.endContainer && rng.startContainer.nodeType == 3) { + // Is only one block node and it doesn't contain word stuff + if (o.node.childNodes.length === 1 && /^(p|h[1-6]|pre)$/i.test(o.node.firstChild.nodeName) && o.content.indexOf('__MCE_ITEM__') === -1) + dom.remove(o.node.firstChild, true); + } + } + + // Execute post process handlers + t.onPostProcess.dispatch(t, o); + + // Serialize content + o.content = ed.serializer.serialize(o.node, {getInner : 1, forced_root_block : ''}); + + // Plain text option active? + if ((!force_rich) && (ed.pasteAsPlainText)) { + t._insertPlainText(o.content); + + if (!getParam(ed, "paste_text_sticky")) { + ed.pasteAsPlainText = false; + ed.controlManager.setActive("pastetext", false); + } + } else { + t._insert(o.content); + } + } + + // Add command for external usage + ed.addCommand('mceInsertClipboardContent', function(u, o) { + process(o, true); + }); + + if (!getParam(ed, "paste_text_use_dialog")) { + ed.addCommand('mcePasteText', function(u, v) { + var cookie = tinymce.util.Cookie; + + ed.pasteAsPlainText = !ed.pasteAsPlainText; + ed.controlManager.setActive('pastetext', ed.pasteAsPlainText); + + if ((ed.pasteAsPlainText) && (!cookie.get("tinymcePasteText"))) { + if (getParam(ed, "paste_text_sticky")) { + ed.windowManager.alert(ed.translate('paste.plaintext_mode_sticky')); + } else { + ed.windowManager.alert(ed.translate('paste.plaintext_mode')); + } + + if (!getParam(ed, "paste_text_notifyalways")) { + cookie.set("tinymcePasteText", "1", new Date(new Date().getFullYear() + 1, 12, 31)) + } + } + }); + } + + ed.addButton('pastetext', {title: 'paste.paste_text_desc', cmd: 'mcePasteText'}); + ed.addButton('selectall', {title: 'paste.selectall_desc', cmd: 'selectall'}); + + // This function grabs the contents from the clipboard by adding a + // hidden div and placing the caret inside it and after the browser paste + // is done it grabs that contents and processes that + function grabContent(e) { + var n, or, rng, oldRng, sel = ed.selection, dom = ed.dom, body = ed.getBody(), posY, textContent; + + // Check if browser supports direct plaintext access + if (e.clipboardData || dom.doc.dataTransfer) { + textContent = (e.clipboardData || dom.doc.dataTransfer).getData('Text'); + + if (ed.pasteAsPlainText) { + e.preventDefault(); + process({content : dom.encode(textContent).replace(/\r?\n/g, '<br />')}); + return; + } + } + + if (dom.get('_mcePaste')) + return; + + // Create container to paste into + n = dom.add(body, 'div', {id : '_mcePaste', 'class' : 'mcePaste', 'data-mce-bogus' : '1'}, '\uFEFF\uFEFF'); + + // If contentEditable mode we need to find out the position of the closest element + if (body != ed.getDoc().body) + posY = dom.getPos(ed.selection.getStart(), body).y; + else + posY = body.scrollTop + dom.getViewPort(ed.getWin()).y; + + // Styles needs to be applied after the element is added to the document since WebKit will otherwise remove all styles + // If also needs to be in view on IE or the paste would fail + dom.setStyles(n, { + position : 'absolute', + left : tinymce.isGecko ? -40 : 0, // Need to move it out of site on Gecko since it will othewise display a ghost resize rect for the div + top : posY - 25, + width : 1, + height : 1, + overflow : 'hidden' + }); + + if (tinymce.isIE) { + // Store away the old range + oldRng = sel.getRng(); + + // Select the container + rng = dom.doc.body.createTextRange(); + rng.moveToElementText(n); + rng.execCommand('Paste'); + + // Remove container + dom.remove(n); + + // Check if the contents was changed, if it wasn't then clipboard extraction failed probably due + // to IE security settings so we pass the junk though better than nothing right + if (n.innerHTML === '\uFEFF\uFEFF') { + ed.execCommand('mcePasteWord'); + e.preventDefault(); + return; + } + + // Restore the old range and clear the contents before pasting + sel.setRng(oldRng); + sel.setContent(''); + + // For some odd reason we need to detach the the mceInsertContent call from the paste event + // It's like IE has a reference to the parent element that you paste in and the selection gets messed up + // when it tries to restore the selection + setTimeout(function() { + // Process contents + process({content : n.innerHTML}); + }, 0); + + // Block the real paste event + return tinymce.dom.Event.cancel(e); + } else { + function block(e) { + e.preventDefault(); + }; + + // Block mousedown and click to prevent selection change + dom.bind(ed.getDoc(), 'mousedown', block); + dom.bind(ed.getDoc(), 'keydown', block); + + or = ed.selection.getRng(); + + // Move select contents inside DIV + n = n.firstChild; + rng = ed.getDoc().createRange(); + rng.setStart(n, 0); + rng.setEnd(n, 2); + sel.setRng(rng); + + // Wait a while and grab the pasted contents + window.setTimeout(function() { + var h = '', nl; + + // Paste divs duplicated in paste divs seems to happen when you paste plain text so lets first look for that broken behavior in WebKit + if (!dom.select('div.mcePaste > div.mcePaste').length) { + nl = dom.select('div.mcePaste'); + + // WebKit will split the div into multiple ones so this will loop through then all and join them to get the whole HTML string + each(nl, function(n) { + var child = n.firstChild; + + // WebKit inserts a DIV container with lots of odd styles + if (child && child.nodeName == 'DIV' && child.style.marginTop && child.style.backgroundColor) { + dom.remove(child, 1); + } + + // Remove apply style spans + each(dom.select('span.Apple-style-span', n), function(n) { + dom.remove(n, 1); + }); + + // Remove bogus br elements + each(dom.select('br[data-mce-bogus]', n), function(n) { + dom.remove(n); + }); + + // WebKit will make a copy of the DIV for each line of plain text pasted and insert them into the DIV + if (n.parentNode.className != 'mcePaste') + h += n.innerHTML; + }); + } else { + // Found WebKit weirdness so force the content into paragraphs this seems to happen when you paste plain text from Nodepad etc + // So this logic will replace double enter with paragraphs and single enter with br so it kind of looks the same + h = '<p>' + dom.encode(textContent).replace(/\r?\n\r?\n/g, '</p><p>').replace(/\r?\n/g, '<br />') + '</p>'; + } + + // Remove the nodes + each(dom.select('div.mcePaste'), function(n) { + dom.remove(n); + }); + + // Restore the old selection + if (or) + sel.setRng(or); + + process({content : h}); + + // Unblock events ones we got the contents + dom.unbind(ed.getDoc(), 'mousedown', block); + dom.unbind(ed.getDoc(), 'keydown', block); + }, 0); + } + } + + // Check if we should use the new auto process method + if (getParam(ed, "paste_auto_cleanup_on_paste")) { + // Is it's Opera or older FF use key handler + if (tinymce.isOpera || /Firefox\/2/.test(navigator.userAgent)) { + ed.onKeyDown.addToTop(function(ed, e) { + if (((tinymce.isMac ? e.metaKey : e.ctrlKey) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45)) + grabContent(e); + }); + } else { + // Grab contents on paste event on Gecko and WebKit + ed.onPaste.addToTop(function(ed, e) { + return grabContent(e); + }); + } + } + + ed.onInit.add(function() { + ed.controlManager.setActive("pastetext", ed.pasteAsPlainText); + + // Block all drag/drop events + if (getParam(ed, "paste_block_drop")) { + ed.dom.bind(ed.getBody(), ['dragend', 'dragover', 'draggesture', 'dragdrop', 'drop', 'drag'], function(e) { + e.preventDefault(); + e.stopPropagation(); + + return false; + }); + } + }); + + // Add legacy support + t._legacySupport(); + }, + + getInfo : function() { + return { + longname : 'Paste text/word', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + _preProcess : function(pl, o) { + var ed = this.editor, + h = o.content, + grep = tinymce.grep, + explode = tinymce.explode, + trim = tinymce.trim, + len, stripClass; + + //console.log('Before preprocess:' + o.content); + + function process(items) { + each(items, function(v) { + // Remove or replace + if (v.constructor == RegExp) + h = h.replace(v, ''); + else + h = h.replace(v[0], v[1]); + }); + } + + if (ed.settings.paste_enable_default_filters == false) { + return; + } + + // IE9 adds BRs before/after block elements when contents is pasted from word or for example another browser + if (tinymce.isIE && document.documentMode >= 9) { + // IE9 adds BRs before/after block elements when contents is pasted from word or for example another browser + process([[/(?:<br>&nbsp;[\s\r\n]+|<br>)*(<\/?(h[1-6r]|p|div|address|pre|form|table|tbody|thead|tfoot|th|tr|td|li|ol|ul|caption|blockquote|center|dl|dt|dd|dir|fieldset)[^>]*>)(?:<br>&nbsp;[\s\r\n]+|<br>)*/g, '$1']]); + + // IE9 also adds an extra BR element for each soft-linefeed and it also adds a BR for each word wrap break + process([ + [/<br><br>/g, '<BR><BR>'], // Replace multiple BR elements with uppercase BR to keep them intact + [/<br>/g, ' '], // Replace single br elements with space since they are word wrap BR:s + [/<BR><BR>/g, '<br>'] // Replace back the double brs but into a single BR + ]); + } + + // Detect Word content and process it more aggressive + if (/class="?Mso|style="[^"]*\bmso-|w:WordDocument/i.test(h) || o.wordContent) { + o.wordContent = true; // Mark the pasted contents as word specific content + //console.log('Word contents detected.'); + + // Process away some basic content + process([ + /^\s*(&nbsp;)+/gi, // &nbsp; entities at the start of contents + /(&nbsp;|<br[^>]*>)+\s*$/gi // &nbsp; entities at the end of contents + ]); + + if (getParam(ed, "paste_convert_headers_to_strong")) { + h = h.replace(/<p [^>]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "<p><strong>$1</strong></p>"); + } + + if (getParam(ed, "paste_convert_middot_lists")) { + process([ + [/<!--\[if !supportLists\]-->/gi, '$&__MCE_ITEM__'], // Convert supportLists to a list item marker + [/(<span[^>]+(?:mso-list:|:\s*symbol)[^>]+>)/gi, '$1__MCE_ITEM__'], // Convert mso-list and symbol spans to item markers + [/(<p[^>]+(?:MsoListParagraph)[^>]+>)/gi, '$1__MCE_ITEM__'] // Convert mso-list and symbol paragraphs to item markers (FF) + ]); + } + + process([ + // Word comments like conditional comments etc + /<!--[\s\S]+?-->/gi, + + // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, MS Office namespaced tags, and a few other tags + /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi, + + // Convert <s> into <strike> for line-though + [/<(\/?)s>/gi, "<$1strike>"], + + // Replace nsbp entites to char since it's easier to handle + [/&nbsp;/gi, "\u00a0"] + ]); + + // Remove bad attributes, with or without quotes, ensuring that attribute text is really inside a tag. + // If JavaScript had a RegExp look-behind, we could have integrated this with the last process() array and got rid of the loop. But alas, it does not, so we cannot. + do { + len = h.length; + h = h.replace(/(<[a-z][^>]*\s)(?:id|name|language|type|on\w+|\w+:\w+)=(?:"[^"]*"|\w+)\s?/gi, "$1"); + } while (len != h.length); + + // Remove all spans if no styles is to be retained + if (getParam(ed, "paste_retain_style_properties").replace(/^none$/i, "").length == 0) { + h = h.replace(/<\/?span[^>]*>/gi, ""); + } else { + // We're keeping styles, so at least clean them up. + // CSS Reference: http://msdn.microsoft.com/en-us/library/aa155477.aspx + + process([ + // Convert <span style="mso-spacerun:yes">___</span> to string of alternating breaking/non-breaking spaces of same length + [/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi, + function(str, spaces) { + return (spaces.length > 0)? spaces.replace(/./, " ").slice(Math.floor(spaces.length/2)).split("").join("\u00a0") : ""; + } + ], + + // Examine all styles: delete junk, transform some, and keep the rest + [/(<[a-z][^>]*)\sstyle="([^"]*)"/gi, + function(str, tag, style) { + var n = [], + i = 0, + s = explode(trim(style).replace(/&quot;/gi, "'"), ";"); + + // Examine each style definition within the tag's style attribute + each(s, function(v) { + var name, value, + parts = explode(v, ":"); + + function ensureUnits(v) { + return v + ((v !== "0") && (/\d$/.test(v)))? "px" : ""; + } + + if (parts.length == 2) { + name = parts[0].toLowerCase(); + value = parts[1].toLowerCase(); + + // Translate certain MS Office styles into their CSS equivalents + switch (name) { + case "mso-padding-alt": + case "mso-padding-top-alt": + case "mso-padding-right-alt": + case "mso-padding-bottom-alt": + case "mso-padding-left-alt": + case "mso-margin-alt": + case "mso-margin-top-alt": + case "mso-margin-right-alt": + case "mso-margin-bottom-alt": + case "mso-margin-left-alt": + case "mso-table-layout-alt": + case "mso-height": + case "mso-width": + case "mso-vertical-align-alt": + n[i++] = name.replace(/^mso-|-alt$/g, "") + ":" + ensureUnits(value); + return; + + case "horiz-align": + n[i++] = "text-align:" + value; + return; + + case "vert-align": + n[i++] = "vertical-align:" + value; + return; + + case "font-color": + case "mso-foreground": + n[i++] = "color:" + value; + return; + + case "mso-background": + case "mso-highlight": + n[i++] = "background:" + value; + return; + + case "mso-default-height": + n[i++] = "min-height:" + ensureUnits(value); + return; + + case "mso-default-width": + n[i++] = "min-width:" + ensureUnits(value); + return; + + case "mso-padding-between-alt": + n[i++] = "border-collapse:separate;border-spacing:" + ensureUnits(value); + return; + + case "text-line-through": + if ((value == "single") || (value == "double")) { + n[i++] = "text-decoration:line-through"; + } + return; + + case "mso-zero-height": + if (value == "yes") { + n[i++] = "display:none"; + } + return; + } + + // Eliminate all MS Office style definitions that have no CSS equivalent by examining the first characters in the name + if (/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?!align|decor|indent|trans)|top-bar|version|vnd|word-break)/.test(name)) { + return; + } + + // If it reached this point, it must be a valid CSS style + n[i++] = name + ":" + parts[1]; // Lower-case name, but keep value case + } + }); + + // If style attribute contained any valid styles the re-write it; otherwise delete style attribute. + if (i > 0) { + return tag + ' style="' + n.join(';') + '"'; + } else { + return tag; + } + } + ] + ]); + } + } + + // Replace headers with <strong> + if (getParam(ed, "paste_convert_headers_to_strong")) { + process([ + [/<h[1-6][^>]*>/gi, "<p><strong>"], + [/<\/h[1-6][^>]*>/gi, "</strong></p>"] + ]); + } + + process([ + // Copy paste from Java like Open Office will produce this junk on FF + [/Version:[\d.]+\nStartHTML:\d+\nEndHTML:\d+\nStartFragment:\d+\nEndFragment:\d+/gi, ''] + ]); + + // Class attribute options are: leave all as-is ("none"), remove all ("all"), or remove only those starting with mso ("mso"). + // Note:- paste_strip_class_attributes: "none", verify_css_classes: true is also a good variation. + stripClass = getParam(ed, "paste_strip_class_attributes"); + + if (stripClass !== "none") { + function removeClasses(match, g1) { + if (stripClass === "all") + return ''; + + var cls = grep(explode(g1.replace(/^(["'])(.*)\1$/, "$2"), " "), + function(v) { + return (/^(?!mso)/i.test(v)); + } + ); + + return cls.length ? ' class="' + cls.join(" ") + '"' : ''; + }; + + h = h.replace(/ class="([^"]+)"/gi, removeClasses); + h = h.replace(/ class=([\-\w]+)/gi, removeClasses); + } + + // Remove spans option + if (getParam(ed, "paste_remove_spans")) { + h = h.replace(/<\/?span[^>]*>/gi, ""); + } + + //console.log('After preprocess:' + h); + + o.content = h; + }, + + /** + * Various post process items. + */ + _postProcess : function(pl, o) { + var t = this, ed = t.editor, dom = ed.dom, styleProps; + + if (ed.settings.paste_enable_default_filters == false) { + return; + } + + if (o.wordContent) { + // Remove named anchors or TOC links + each(dom.select('a', o.node), function(a) { + if (!a.href || a.href.indexOf('#_Toc') != -1) + dom.remove(a, 1); + }); + + if (getParam(ed, "paste_convert_middot_lists")) { + t._convertLists(pl, o); + } + + // Process styles + styleProps = getParam(ed, "paste_retain_style_properties"); // retained properties + + // Process only if a string was specified and not equal to "all" or "*" + if ((tinymce.is(styleProps, "string")) && (styleProps !== "all") && (styleProps !== "*")) { + styleProps = tinymce.explode(styleProps.replace(/^none$/i, "")); + + // Retains some style properties + each(dom.select('*', o.node), function(el) { + var newStyle = {}, npc = 0, i, sp, sv; + + // Store a subset of the existing styles + if (styleProps) { + for (i = 0; i < styleProps.length; i++) { + sp = styleProps[i]; + sv = dom.getStyle(el, sp); + + if (sv) { + newStyle[sp] = sv; + npc++; + } + } + } + + // Remove all of the existing styles + dom.setAttrib(el, 'style', ''); + + if (styleProps && npc > 0) + dom.setStyles(el, newStyle); // Add back the stored subset of styles + else // Remove empty span tags that do not have class attributes + if (el.nodeName == 'SPAN' && !el.className) + dom.remove(el, true); + }); + } + } + + // Remove all style information or only specifically on WebKit to avoid the style bug on that browser + if (getParam(ed, "paste_remove_styles") || (getParam(ed, "paste_remove_styles_if_webkit") && tinymce.isWebKit)) { + each(dom.select('*[style]', o.node), function(el) { + el.removeAttribute('style'); + el.removeAttribute('data-mce-style'); + }); + } else { + if (tinymce.isWebKit) { + // We need to compress the styles on WebKit since if you paste <img border="0" /> it will become <img border="0" style="... lots of junk ..." /> + // Removing the mce_style that contains the real value will force the Serializer engine to compress the styles + each(dom.select('*', o.node), function(el) { + el.removeAttribute('data-mce-style'); + }); + } + } + }, + + /** + * Converts the most common bullet and number formats in Office into a real semantic UL/LI list. + */ + _convertLists : function(pl, o) { + var dom = pl.editor.dom, listElm, li, lastMargin = -1, margin, levels = [], lastType, html; + + // Convert middot lists into real semantic lists + each(dom.select('p', o.node), function(p) { + var sib, val = '', type, html, idx, parents; + + // Get text node value at beginning of paragraph + for (sib = p.firstChild; sib && sib.nodeType == 3; sib = sib.nextSibling) + val += sib.nodeValue; + + val = p.innerHTML.replace(/<\/?\w+[^>]*>/gi, '').replace(/&nbsp;/g, '\u00a0'); + + // Detect unordered lists look for bullets + if (/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*\u00a0*/.test(val)) + type = 'ul'; + + // Detect ordered lists 1., a. or ixv. + if (/^__MCE_ITEM__\s*\w+\.\s*\u00a0+/.test(val)) + type = 'ol'; + + // Check if node value matches the list pattern: o&nbsp;&nbsp; + if (type) { + margin = parseFloat(p.style.marginLeft || 0); + + if (margin > lastMargin) + levels.push(margin); + + if (!listElm || type != lastType) { + listElm = dom.create(type); + dom.insertAfter(listElm, p); + } else { + // Nested list element + if (margin > lastMargin) { + listElm = li.appendChild(dom.create(type)); + } else if (margin < lastMargin) { + // Find parent level based on margin value + idx = tinymce.inArray(levels, margin); + parents = dom.getParents(listElm.parentNode, type); + listElm = parents[parents.length - 1 - idx] || listElm; + } + } + + // Remove middot or number spans if they exists + each(dom.select('span', p), function(span) { + var html = span.innerHTML.replace(/<\/?\w+[^>]*>/gi, ''); + + // Remove span with the middot or the number + if (type == 'ul' && /^__MCE_ITEM__[\u2022\u00b7\u00a7\u00d8o\u25CF]/.test(html)) + dom.remove(span); + else if (/^__MCE_ITEM__[\s\S]*\w+\.(&nbsp;|\u00a0)*\s*/.test(html)) + dom.remove(span); + }); + + html = p.innerHTML; + + // Remove middot/list items + if (type == 'ul') + html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*(&nbsp;|\u00a0)+\s*/, ''); + else + html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^\s*\w+\.(&nbsp;|\u00a0)+\s*/, ''); + + // Create li and add paragraph data into the new li + li = listElm.appendChild(dom.create('li', 0, html)); + dom.remove(p); + + lastMargin = margin; + lastType = type; + } else + listElm = lastMargin = 0; // End list element + }); + + // Remove any left over makers + html = o.node.innerHTML; + if (html.indexOf('__MCE_ITEM__') != -1) + o.node.innerHTML = html.replace(/__MCE_ITEM__/g, ''); + }, + + /** + * Inserts the specified contents at the caret position. + */ + _insert : function(h, skip_undo) { + var ed = this.editor, r = ed.selection.getRng(); + + // First delete the contents seems to work better on WebKit when the selection spans multiple list items or multiple table cells. + if (!ed.selection.isCollapsed() && r.startContainer != r.endContainer) + ed.getDoc().execCommand('Delete', false, null); + + ed.execCommand('mceInsertContent', false, h, {skip_undo : skip_undo}); + }, + + /** + * Instead of the old plain text method which tried to re-create a paste operation, the + * new approach adds a plain text mode toggle switch that changes the behavior of paste. + * This function is passed the same input that the regular paste plugin produces. + * It performs additional scrubbing and produces (and inserts) the plain text. + * This approach leverages all of the great existing functionality in the paste + * plugin, and requires minimal changes to add the new functionality. + * Speednet - June 2009 + */ + _insertPlainText : function(content) { + var ed = this.editor, + linebr = getParam(ed, "paste_text_linebreaktype"), + rl = getParam(ed, "paste_text_replacements"), + is = tinymce.is; + + function process(items) { + each(items, function(v) { + if (v.constructor == RegExp) + content = content.replace(v, ""); + else + content = content.replace(v[0], v[1]); + }); + }; + + if ((typeof(content) === "string") && (content.length > 0)) { + // If HTML content with line-breaking tags, then remove all cr/lf chars because only tags will break a line + if (/<(?:p|br|h[1-6]|ul|ol|dl|table|t[rdh]|div|blockquote|fieldset|pre|address|center)[^>]*>/i.test(content)) { + process([ + /[\n\r]+/g + ]); + } else { + // Otherwise just get rid of carriage returns (only need linefeeds) + process([ + /\r+/g + ]); + } + + process([ + [/<\/(?:p|h[1-6]|ul|ol|dl|table|div|blockquote|fieldset|pre|address|center)>/gi, "\n\n"], // Block tags get a blank line after them + [/<br[^>]*>|<\/tr>/gi, "\n"], // Single linebreak for <br /> tags and table rows + [/<\/t[dh]>\s*<t[dh][^>]*>/gi, "\t"], // Table cells get tabs betweem them + /<[a-z!\/?][^>]*>/gi, // Delete all remaining tags + [/&nbsp;/gi, " "], // Convert non-break spaces to regular spaces (remember, *plain text*) + [/(?:(?!\n)\s)*(\n+)(?:(?!\n)\s)*/gi, "$1"],// Cool little RegExp deletes whitespace around linebreak chars. + [/\n{3,}/g, "\n\n"] // Max. 2 consecutive linebreaks + ]); + + content = ed.dom.decode(tinymce.html.Entities.encodeRaw(content)); + + // Perform default or custom replacements + if (is(rl, "array")) { + process(rl); + } else if (is(rl, "string")) { + process(new RegExp(rl, "gi")); + } + + // Treat paragraphs as specified in the config + if (linebr == "none") { + // Convert all line breaks to space + process([ + [/\n+/g, " "] + ]); + } else if (linebr == "br") { + // Convert all line breaks to <br /> + process([ + [/\n/g, "<br />"] + ]); + } else if (linebr == "p") { + // Convert all line breaks to <p>...</p> + process([ + [/\n+/g, "</p><p>"], + [/^(.*<\/p>)(<p>)$/, '<p>$1'] + ]); + } else { + // defaults to "combined" + // Convert single line breaks to <br /> and double line breaks to <p>...</p> + process([ + [/\n\n/g, "</p><p>"], + [/^(.*<\/p>)(<p>)$/, '<p>$1'], + [/\n/g, "<br />"] + ]); + } + + ed.execCommand('mceInsertContent', false, content); + } + }, + + /** + * This method will open the old style paste dialogs. Some users might want the old behavior but still use the new cleanup engine. + */ + _legacySupport : function() { + var t = this, ed = t.editor; + + // Register command(s) for backwards compatibility + ed.addCommand("mcePasteWord", function() { + ed.windowManager.open({ + file: t.url + "/pasteword.htm", + width: parseInt(getParam(ed, "paste_dialog_width")), + height: parseInt(getParam(ed, "paste_dialog_height")), + inline: 1 + }); + }); + + if (getParam(ed, "paste_text_use_dialog")) { + ed.addCommand("mcePasteText", function() { + ed.windowManager.open({ + file : t.url + "/pastetext.htm", + width: parseInt(getParam(ed, "paste_dialog_width")), + height: parseInt(getParam(ed, "paste_dialog_height")), + inline : 1 + }); + }); + } + + // Register button for backwards compatibility + ed.addButton("pasteword", {title : "paste.paste_word_desc", cmd : "mcePasteWord"}); + } + }); + + // Register plugin + tinymce.PluginManager.add("paste", tinymce.plugins.PastePlugin); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/paste/js/pastetext.js b/src/core/static/js/tiny_mce/plugins/paste/js/pastetext.js new file mode 100644 index 0000000..c524f9e --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/paste/js/pastetext.js @@ -0,0 +1,36 @@ +tinyMCEPopup.requireLangPack(); + +var PasteTextDialog = { + init : function() { + this.resize(); + }, + + insert : function() { + var h = tinyMCEPopup.dom.encode(document.getElementById('content').value), lines; + + // Convert linebreaks into paragraphs + if (document.getElementById('linebreaks').checked) { + lines = h.split(/\r?\n/); + if (lines.length > 1) { + h = ''; + tinymce.each(lines, function(row) { + h += '<p>' + row + '</p>'; + }); + } + } + + tinyMCEPopup.editor.execCommand('mceInsertClipboardContent', false, {content : h}); + tinyMCEPopup.close(); + }, + + resize : function() { + var vp = tinyMCEPopup.dom.getViewPort(window), el; + + el = document.getElementById('content'); + + el.style.width = (vp.w - 20) + 'px'; + el.style.height = (vp.h - 90) + 'px'; + } +}; + +tinyMCEPopup.onInit.add(PasteTextDialog.init, PasteTextDialog); diff --git a/src/core/static/js/tiny_mce/plugins/paste/js/pasteword.js b/src/core/static/js/tiny_mce/plugins/paste/js/pasteword.js new file mode 100644 index 0000000..a52731c --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/paste/js/pasteword.js @@ -0,0 +1,51 @@ +tinyMCEPopup.requireLangPack(); + +var PasteWordDialog = { + init : function() { + var ed = tinyMCEPopup.editor, el = document.getElementById('iframecontainer'), ifr, doc, css, cssHTML = ''; + + // Create iframe + el.innerHTML = '<iframe id="iframe" src="javascript:\'\';" frameBorder="0" style="border: 1px solid gray"></iframe>'; + ifr = document.getElementById('iframe'); + doc = ifr.contentWindow.document; + + // Force absolute CSS urls + css = [ed.baseURI.toAbsolute("themes/" + ed.settings.theme + "/skins/" + ed.settings.skin + "/content.css")]; + css = css.concat(tinymce.explode(ed.settings.content_css) || []); + tinymce.each(css, function(u) { + cssHTML += '<link href="' + ed.documentBaseURI.toAbsolute('' + u) + '" rel="stylesheet" type="text/css" />'; + }); + + // Write content into iframe + doc.open(); + doc.write('<html><head>' + cssHTML + '</head><body class="mceContentBody" spellcheck="false"></body></html>'); + doc.close(); + + doc.designMode = 'on'; + this.resize(); + + window.setTimeout(function() { + ifr.contentWindow.focus(); + }, 10); + }, + + insert : function() { + var h = document.getElementById('iframe').contentWindow.document.body.innerHTML; + + tinyMCEPopup.editor.execCommand('mceInsertClipboardContent', false, {content : h, wordContent : true}); + tinyMCEPopup.close(); + }, + + resize : function() { + var vp = tinyMCEPopup.dom.getViewPort(window), el; + + el = document.getElementById('iframe'); + + if (el) { + el.style.width = (vp.w - 20) + 'px'; + el.style.height = (vp.h - 90) + 'px'; + } + } +}; + +tinyMCEPopup.onInit.add(PasteWordDialog.init, PasteWordDialog); diff --git a/src/core/static/js/tiny_mce/plugins/paste/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/paste/langs/de_dlg.js new file mode 100755 index 0000000..84b9bc6 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/paste/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.paste_dlg',{"word_title":"Dr\u00fccken Sie auf Ihrer Tastatur Strg+V, um den Text einzuf\u00fcgen.","text_linebreaks":"Zeilenumbr\u00fcche beibehalten","text_title":"Dr\u00fccken Sie auf Ihrer Tastatur Strg+V, um den Text einzuf\u00fcgen."}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/paste/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/paste/langs/en_dlg.js new file mode 100755 index 0000000..bc74daf --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/paste/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.paste_dlg',{"word_title":"Use Ctrl+V on your keyboard to paste the text into the window.","text_linebreaks":"Keep Linebreaks","text_title":"Use Ctrl+V on your keyboard to paste the text into the window."}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/paste/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/paste/langs/fr_dlg.js new file mode 100755 index 0000000..acc5d63 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/paste/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.paste_dlg',{"word_title":"Utilisez CTRL+V sur votre clavier pour coller le texte dans la fen\u00eatre.","text_linebreaks":"Conserver les retours \u00e0 la ligne","text_title":"Utilisez CTRL+V sur votre clavier pour coller le texte dans la fen\u00eatre."}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/paste/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/paste/langs/it_dlg.js new file mode 100755 index 0000000..f1b8dc7 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/paste/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.paste_dlg',{"word_title":"Premere CTRL+V sulla tastiera per incollare il testo nella finestra.","text_linebreaks":"Mantieni interruzioni di riga","text_title":"Premere CTRL+V sulla tastiera per incollare il testo nella finestra."}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/paste/pastetext.htm b/src/core/static/js/tiny_mce/plugins/paste/pastetext.htm new file mode 100644 index 0000000..b655945 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/paste/pastetext.htm @@ -0,0 +1,27 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#paste.paste_text_desc}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/pastetext.js"></script> +</head> +<body onresize="PasteTextDialog.resize();" style="display:none; overflow:hidden;"> + <form name="source" onsubmit="return PasteTextDialog.insert();" action="#"> + <div style="float: left" class="title">{#paste.paste_text_desc}</div> + + <div style="float: right"> + <input type="checkbox" name="linebreaks" id="linebreaks" class="wordWrapCode" checked="checked" /><label for="linebreaks">{#paste_dlg.text_linebreaks}</label> + </div> + + <br style="clear: both" /> + + <div>{#paste_dlg.text_title}</div> + + <textarea id="content" name="content" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,mono; font-size: 12px;" dir="ltr" wrap="soft" class="mceFocus"></textarea> + + <div class="mceActionPanel"> + <input type="submit" name="insert" value="{#insert}" id="insert" /> + <input type="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" /> + </div> + </form> +</body> +</html> \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/paste/pasteword.htm b/src/core/static/js/tiny_mce/plugins/paste/pasteword.htm new file mode 100644 index 0000000..0f6bb41 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/paste/pasteword.htm @@ -0,0 +1,21 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#paste.paste_word_desc}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/pasteword.js"></script> +</head> +<body onresize="PasteWordDialog.resize();" style="display:none; overflow:hidden;"> + <form name="source" onsubmit="return PasteWordDialog.insert();" action="#"> + <div class="title">{#paste.paste_word_desc}</div> + + <div>{#paste_dlg.word_title}</div> + + <div id="iframecontainer"></div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/preview/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/preview/editor_plugin.js new file mode 100644 index 0000000..507909c --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/preview/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.Preview",{init:function(a,b){var d=this,c=tinymce.explode(a.settings.content_css);d.editor=a;tinymce.each(c,function(f,e){c[e]=a.documentBaseURI.toAbsolute(f)});a.addCommand("mcePreview",function(){a.windowManager.open({file:a.getParam("plugin_preview_pageurl",b+"/preview.html"),width:parseInt(a.getParam("plugin_preview_width","550")),height:parseInt(a.getParam("plugin_preview_height","600")),resizable:"yes",scrollbars:"yes",popup_css:c?c.join(","):a.baseURI.toAbsolute("themes/"+a.settings.theme+"/skins/"+a.settings.skin+"/content.css"),inline:a.getParam("plugin_preview_inline",1)},{base:a.documentBaseURI.getURI()})});a.addButton("preview",{title:"preview.preview_desc",cmd:"mcePreview"})},getInfo:function(){return{longname:"Preview",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/preview",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("preview",tinymce.plugins.Preview)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/preview/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/preview/editor_plugin_src.js new file mode 100644 index 0000000..80f00f0 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/preview/editor_plugin_src.js @@ -0,0 +1,53 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.Preview', { + init : function(ed, url) { + var t = this, css = tinymce.explode(ed.settings.content_css); + + t.editor = ed; + + // Force absolute CSS urls + tinymce.each(css, function(u, k) { + css[k] = ed.documentBaseURI.toAbsolute(u); + }); + + ed.addCommand('mcePreview', function() { + ed.windowManager.open({ + file : ed.getParam("plugin_preview_pageurl", url + "/preview.html"), + width : parseInt(ed.getParam("plugin_preview_width", "550")), + height : parseInt(ed.getParam("plugin_preview_height", "600")), + resizable : "yes", + scrollbars : "yes", + popup_css : css ? css.join(',') : ed.baseURI.toAbsolute("themes/" + ed.settings.theme + "/skins/" + ed.settings.skin + "/content.css"), + inline : ed.getParam("plugin_preview_inline", 1) + }, { + base : ed.documentBaseURI.getURI() + }); + }); + + ed.addButton('preview', {title : 'preview.preview_desc', cmd : 'mcePreview'}); + }, + + getInfo : function() { + return { + longname : 'Preview', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/preview', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('preview', tinymce.plugins.Preview); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/preview/example.html b/src/core/static/js/tiny_mce/plugins/preview/example.html new file mode 100644 index 0000000..b2c3d90 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/preview/example.html @@ -0,0 +1,28 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<script language="javascript" src="../../tiny_mce_popup.js"></script> +<script type="text/javascript" src="jscripts/embed.js"></script> +<script type="text/javascript"> +tinyMCEPopup.onInit.add(function(ed) { + var dom = tinyMCEPopup.dom; + + // Load editor content_css + tinymce.each(ed.settings.content_css.split(','), function(u) { + dom.loadCSS(ed.documentBaseURI.toAbsolute(u)); + }); + + // Place contents inside div container + dom.setHTML('content', ed.getContent()); +}); +</script> +<title>Example of a custom preview page</title> +</head> +<body> + +Editor contents: <br /> +<div id="content"> +<!-- Gets filled with editor contents --> +</div> + +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/preview/jscripts/embed.js b/src/core/static/js/tiny_mce/plugins/preview/jscripts/embed.js new file mode 100644 index 0000000..f8dc810 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/preview/jscripts/embed.js @@ -0,0 +1,73 @@ +/** + * This script contains embed functions for common plugins. This scripts are complety free to use for any purpose. + */ + +function writeFlash(p) { + writeEmbed( + 'D27CDB6E-AE6D-11cf-96B8-444553540000', + 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0', + 'application/x-shockwave-flash', + p + ); +} + +function writeShockWave(p) { + writeEmbed( + '166B1BCA-3F9C-11CF-8075-444553540000', + 'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0', + 'application/x-director', + p + ); +} + +function writeQuickTime(p) { + writeEmbed( + '02BF25D5-8C17-4B23-BC80-D3488ABDDC6B', + 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0', + 'video/quicktime', + p + ); +} + +function writeRealMedia(p) { + writeEmbed( + 'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA', + 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0', + 'audio/x-pn-realaudio-plugin', + p + ); +} + +function writeWindowsMedia(p) { + p.url = p.src; + writeEmbed( + '6BF52A52-394A-11D3-B153-00C04F79FAA6', + 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701', + 'application/x-mplayer2', + p + ); +} + +function writeEmbed(cls, cb, mt, p) { + var h = '', n; + + h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"'; + h += typeof(p.id) != "undefined" ? 'id="' + p.id + '"' : ''; + h += typeof(p.name) != "undefined" ? 'name="' + p.name + '"' : ''; + h += typeof(p.width) != "undefined" ? 'width="' + p.width + '"' : ''; + h += typeof(p.height) != "undefined" ? 'height="' + p.height + '"' : ''; + h += typeof(p.align) != "undefined" ? 'align="' + p.align + '"' : ''; + h += '>'; + + for (n in p) + h += '<param name="' + n + '" value="' + p[n] + '">'; + + h += '<embed type="' + mt + '"'; + + for (n in p) + h += n + '="' + p[n] + '" '; + + h += '></embed></object>'; + + document.write(h); +} diff --git a/src/core/static/js/tiny_mce/plugins/preview/preview.html b/src/core/static/js/tiny_mce/plugins/preview/preview.html new file mode 100644 index 0000000..67e7b14 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/preview/preview.html @@ -0,0 +1,17 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<script type="text/javascript" src="../../tiny_mce_popup.js"></script> +<script type="text/javascript" src="jscripts/embed.js"></script> +<script type="text/javascript"><!-- +document.write('<base href="' + tinyMCEPopup.getWindowArg("base") + '">'); +// --> +</script> +<title>{#preview.preview_desc}</title> +</head> +<body id="content"> +<script type="text/javascript"> + document.write(tinyMCEPopup.editor.getContent()); +</script> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/print/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/print/editor_plugin.js new file mode 100644 index 0000000..b5b3a55 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/print/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.Print",{init:function(a,b){a.addCommand("mcePrint",function(){a.getWin().print()});a.addButton("print",{title:"print.print_desc",cmd:"mcePrint"})},getInfo:function(){return{longname:"Print",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/print",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("print",tinymce.plugins.Print)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/print/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/print/editor_plugin_src.js new file mode 100644 index 0000000..3933fe6 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/print/editor_plugin_src.js @@ -0,0 +1,34 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.Print', { + init : function(ed, url) { + ed.addCommand('mcePrint', function() { + ed.getWin().print(); + }); + + ed.addButton('print', {title : 'print.print_desc', cmd : 'mcePrint'}); + }, + + getInfo : function() { + return { + longname : 'Print', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/print', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('print', tinymce.plugins.Print); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/save/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/save/editor_plugin.js new file mode 100644 index 0000000..8e93996 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/save/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.Save",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceSave",c._save,c);a.addCommand("mceCancel",c._cancel,c);a.addButton("save",{title:"save.save_desc",cmd:"mceSave"});a.addButton("cancel",{title:"save.cancel_desc",cmd:"mceCancel"});a.onNodeChange.add(c._nodeChange,c);a.addShortcut("ctrl+s",a.getLang("save.save_desc"),"mceSave")},getInfo:function(){return{longname:"Save",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/save",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_nodeChange:function(b,a,c){var b=this.editor;if(b.getParam("save_enablewhendirty")){a.setDisabled("save",!b.isDirty());a.setDisabled("cancel",!b.isDirty())}},_save:function(){var c=this.editor,a,e,d,b;a=tinymce.DOM.get(c.id).form||tinymce.DOM.getParent(c.id,"form");if(c.getParam("save_enablewhendirty")&&!c.isDirty()){return}tinyMCE.triggerSave();if(e=c.getParam("save_onsavecallback")){if(c.execCallback("save_onsavecallback",c)){c.startContent=tinymce.trim(c.getContent({format:"raw"}));c.nodeChanged()}return}if(a){c.isNotDirty=true;if(a.onsubmit==null||a.onsubmit()!=false){a.submit()}c.nodeChanged()}else{c.windowManager.alert("Error: No form element found.")}},_cancel:function(){var a=this.editor,c,b=tinymce.trim(a.startContent);if(c=a.getParam("save_oncancelcallback")){a.execCallback("save_oncancelcallback",a);return}a.setContent(b);a.undoManager.clear();a.nodeChanged()}});tinymce.PluginManager.add("save",tinymce.plugins.Save)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/save/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/save/editor_plugin_src.js new file mode 100644 index 0000000..f5a3de8 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/save/editor_plugin_src.js @@ -0,0 +1,101 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.Save', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceSave', t._save, t); + ed.addCommand('mceCancel', t._cancel, t); + + // Register buttons + ed.addButton('save', {title : 'save.save_desc', cmd : 'mceSave'}); + ed.addButton('cancel', {title : 'save.cancel_desc', cmd : 'mceCancel'}); + + ed.onNodeChange.add(t._nodeChange, t); + ed.addShortcut('ctrl+s', ed.getLang('save.save_desc'), 'mceSave'); + }, + + getInfo : function() { + return { + longname : 'Save', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/save', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + _nodeChange : function(ed, cm, n) { + var ed = this.editor; + + if (ed.getParam('save_enablewhendirty')) { + cm.setDisabled('save', !ed.isDirty()); + cm.setDisabled('cancel', !ed.isDirty()); + } + }, + + // Private methods + + _save : function() { + var ed = this.editor, formObj, os, i, elementId; + + formObj = tinymce.DOM.get(ed.id).form || tinymce.DOM.getParent(ed.id, 'form'); + + if (ed.getParam("save_enablewhendirty") && !ed.isDirty()) + return; + + tinyMCE.triggerSave(); + + // Use callback instead + if (os = ed.getParam("save_onsavecallback")) { + if (ed.execCallback('save_onsavecallback', ed)) { + ed.startContent = tinymce.trim(ed.getContent({format : 'raw'})); + ed.nodeChanged(); + } + + return; + } + + if (formObj) { + ed.isNotDirty = true; + + if (formObj.onsubmit == null || formObj.onsubmit() != false) + formObj.submit(); + + ed.nodeChanged(); + } else + ed.windowManager.alert("Error: No form element found."); + }, + + _cancel : function() { + var ed = this.editor, os, h = tinymce.trim(ed.startContent); + + // Use callback instead + if (os = ed.getParam("save_oncancelcallback")) { + ed.execCallback('save_oncancelcallback', ed); + return; + } + + ed.setContent(h); + ed.undoManager.clear(); + ed.nodeChanged(); + } + }); + + // Register plugin + tinymce.PluginManager.add('save', tinymce.plugins.Save); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/searchreplace/css/searchreplace.css b/src/core/static/js/tiny_mce/plugins/searchreplace/css/searchreplace.css new file mode 100644 index 0000000..ecdf58c --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/searchreplace/css/searchreplace.css @@ -0,0 +1,6 @@ +.panel_wrapper {height:85px;} +.panel_wrapper div.current {height:85px;} + +/* IE */ +* html .panel_wrapper {height:100px;} +* html .panel_wrapper div.current {height:100px;} diff --git a/src/core/static/js/tiny_mce/plugins/searchreplace/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/searchreplace/editor_plugin.js new file mode 100644 index 0000000..165bc12 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/searchreplace/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.SearchReplacePlugin",{init:function(a,c){function b(d){window.focus();a.windowManager.open({file:c+"/searchreplace.htm",width:420+parseInt(a.getLang("searchreplace.delta_width",0)),height:170+parseInt(a.getLang("searchreplace.delta_height",0)),inline:1,auto_focus:0},{mode:d,search_string:a.selection.getContent({format:"text"}),plugin_url:c})}a.addCommand("mceSearch",function(){b("search")});a.addCommand("mceReplace",function(){b("replace")});a.addButton("search",{title:"searchreplace.search_desc",cmd:"mceSearch"});a.addButton("replace",{title:"searchreplace.replace_desc",cmd:"mceReplace"});a.addShortcut("ctrl+f","searchreplace.search_desc","mceSearch")},getInfo:function(){return{longname:"Search/Replace",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("searchreplace",tinymce.plugins.SearchReplacePlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js new file mode 100644 index 0000000..4c87e8f --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js @@ -0,0 +1,61 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.SearchReplacePlugin', { + init : function(ed, url) { + function open(m) { + // Keep IE from writing out the f/r character to the editor + // instance while initializing a new dialog. See: #3131190 + window.focus(); + + ed.windowManager.open({ + file : url + '/searchreplace.htm', + width : 420 + parseInt(ed.getLang('searchreplace.delta_width', 0)), + height : 170 + parseInt(ed.getLang('searchreplace.delta_height', 0)), + inline : 1, + auto_focus : 0 + }, { + mode : m, + search_string : ed.selection.getContent({format : 'text'}), + plugin_url : url + }); + }; + + // Register commands + ed.addCommand('mceSearch', function() { + open('search'); + }); + + ed.addCommand('mceReplace', function() { + open('replace'); + }); + + // Register buttons + ed.addButton('search', {title : 'searchreplace.search_desc', cmd : 'mceSearch'}); + ed.addButton('replace', {title : 'searchreplace.replace_desc', cmd : 'mceReplace'}); + + ed.addShortcut('ctrl+f', 'searchreplace.search_desc', 'mceSearch'); + }, + + getInfo : function() { + return { + longname : 'Search/Replace', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('searchreplace', tinymce.plugins.SearchReplacePlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/searchreplace/js/searchreplace.js b/src/core/static/js/tiny_mce/plugins/searchreplace/js/searchreplace.js new file mode 100644 index 0000000..80284b9 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/searchreplace/js/searchreplace.js @@ -0,0 +1,142 @@ +tinyMCEPopup.requireLangPack(); + +var SearchReplaceDialog = { + init : function(ed) { + var t = this, f = document.forms[0], m = tinyMCEPopup.getWindowArg("mode"); + + t.switchMode(m); + + f[m + '_panel_searchstring'].value = tinyMCEPopup.getWindowArg("search_string"); + + // Focus input field + f[m + '_panel_searchstring'].focus(); + + mcTabs.onChange.add(function(tab_id, panel_id) { + t.switchMode(tab_id.substring(0, tab_id.indexOf('_'))); + }); + }, + + switchMode : function(m) { + var f, lm = this.lastMode; + + if (lm != m) { + f = document.forms[0]; + + if (lm) { + f[m + '_panel_searchstring'].value = f[lm + '_panel_searchstring'].value; + f[m + '_panel_backwardsu'].checked = f[lm + '_panel_backwardsu'].checked; + f[m + '_panel_backwardsd'].checked = f[lm + '_panel_backwardsd'].checked; + f[m + '_panel_casesensitivebox'].checked = f[lm + '_panel_casesensitivebox'].checked; + } + + mcTabs.displayTab(m + '_tab', m + '_panel'); + document.getElementById("replaceBtn").style.display = (m == "replace") ? "inline" : "none"; + document.getElementById("replaceAllBtn").style.display = (m == "replace") ? "inline" : "none"; + this.lastMode = m; + } + }, + + searchNext : function(a) { + var ed = tinyMCEPopup.editor, se = ed.selection, r = se.getRng(), f, m = this.lastMode, s, b, fl = 0, w = ed.getWin(), wm = ed.windowManager, fo = 0; + + // Get input + f = document.forms[0]; + s = f[m + '_panel_searchstring'].value; + b = f[m + '_panel_backwardsu'].checked; + ca = f[m + '_panel_casesensitivebox'].checked; + rs = f['replace_panel_replacestring'].value; + + if (tinymce.isIE) { + r = ed.getDoc().selection.createRange(); + } + + if (s == '') + return; + + function fix() { + // Correct Firefox graphics glitches + // TODO: Verify if this is actually needed any more, maybe it was for very old FF versions? + r = se.getRng().cloneRange(); + ed.getDoc().execCommand('SelectAll', false, null); + se.setRng(r); + }; + + function replace() { + ed.selection.setContent(rs); // Needs to be duplicated due to selection bug in IE + }; + + // IE flags + if (ca) + fl = fl | 4; + + switch (a) { + case 'all': + // Move caret to beginning of text + ed.execCommand('SelectAll'); + ed.selection.collapse(true); + + if (tinymce.isIE) { + ed.focus(); + r = ed.getDoc().selection.createRange(); + + while (r.findText(s, b ? -1 : 1, fl)) { + r.scrollIntoView(); + r.select(); + replace(); + fo = 1; + + if (b) { + r.moveEnd("character", -(rs.length)); // Otherwise will loop forever + } + } + + tinyMCEPopup.storeSelection(); + } else { + while (w.find(s, ca, b, false, false, false, false)) { + replace(); + fo = 1; + } + } + + if (fo) + tinyMCEPopup.alert(ed.getLang('searchreplace_dlg.allreplaced')); + else + tinyMCEPopup.alert(ed.getLang('searchreplace_dlg.notfound')); + + return; + + case 'current': + if (!ed.selection.isCollapsed()) + replace(); + + break; + } + + se.collapse(b); + r = se.getRng(); + + // Whats the point + if (!s) + return; + + if (tinymce.isIE) { + ed.focus(); + r = ed.getDoc().selection.createRange(); + + if (r.findText(s, b ? -1 : 1, fl)) { + r.scrollIntoView(); + r.select(); + } else + tinyMCEPopup.alert(ed.getLang('searchreplace_dlg.notfound')); + + tinyMCEPopup.storeSelection(); + } else { + if (!w.find(s, ca, b, false, false, false, false)) + tinyMCEPopup.alert(ed.getLang('searchreplace_dlg.notfound')); + else + fix(); + } + } +}; + +tinyMCEPopup.onInit.add(SearchReplaceDialog.init, SearchReplaceDialog); diff --git a/src/core/static/js/tiny_mce/plugins/searchreplace/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/searchreplace/langs/de_dlg.js new file mode 100755 index 0000000..7c40acd --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/searchreplace/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.searchreplace_dlg',{findwhat:"Zu suchender Text",replacewith:"Ersetzen durch",direction:"Suchrichtung",up:"Aufw\u00e4rts",down:"Abw\u00e4rts",mcase:"Gro\u00df-/Kleinschreibung beachten",findnext:"Weitersuchen",allreplaced:"Alle Vorkommen der Zeichenkette wurden ersetzt.","searchnext_desc":"Weitersuchen",notfound:"Die Suche ist am Ende angelangt. Die Zeichenkette konnte nicht gefunden werden.","search_title":"Suchen","replace_title":"Suchen/Ersetzen",replaceall:"Alle ersetzen",replace:"Ersetzen"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/searchreplace/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/searchreplace/langs/en_dlg.js new file mode 100755 index 0000000..8a65900 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/searchreplace/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.searchreplace_dlg',{findwhat:"Find What",replacewith:"Replace with",direction:"Direction",up:"Up",down:"Down",mcase:"Match Case",findnext:"Find Next",allreplaced:"All occurrences of the search string were replaced.","searchnext_desc":"Find Again",notfound:"The search has been completed. The search string could not be found.","search_title":"Find","replace_title":"Find/Replace",replaceall:"Replace All",replace:"Replace"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/searchreplace/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/searchreplace/langs/fr_dlg.js new file mode 100755 index 0000000..707b5c2 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/searchreplace/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.searchreplace_dlg',{findwhat:"Rechercher ceci",replacewith:"Remplacer par",direction:"Direction",up:"Vers le haut",down:"Vers le bas",mcase:"Sensible \u00e0 la casse",findnext:"Rechercher le suivant",allreplaced:"Toutes les occurrences de la cha\u00eene recherch\u00e9e ont \u00e9t\u00e9 remplac\u00e9es.","searchnext_desc":"Suivant",notfound:"La recherche est termin\u00e9e. La cha\u00eene recherch\u00e9e n\'a pas \u00e9t\u00e9 trouv\u00e9e.","search_title":"Rechercher","replace_title":"Rechercher / remplacer",replaceall:"Tout remplacer",replace:"Remplacer"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/searchreplace/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/searchreplace/langs/it_dlg.js new file mode 100755 index 0000000..da34e5d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/searchreplace/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.searchreplace_dlg',{findwhat:"Trova:",replacewith:"Sostituisci con:",direction:"Direzione",up:"Avanti",down:"Indietro",mcase:"Maiuscole/minuscole",findnext:"Trova succ.",allreplaced:"Tutte le occorrenze del criterio di ricerca sono state sostituite.","searchnext_desc":"Trova successivo",notfound:"Ricerca completata. Nessun risultato trovato.","search_title":"Trova","replace_title":"Trova/Sostituisci",replaceall:"Sost. tutto",replace:"Sostituisci"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/searchreplace/searchreplace.htm b/src/core/static/js/tiny_mce/plugins/searchreplace/searchreplace.htm new file mode 100644 index 0000000..5a22d8a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/searchreplace/searchreplace.htm @@ -0,0 +1,100 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#searchreplace_dlg.replace_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="js/searchreplace.js"></script> + <link rel="stylesheet" type="text/css" href="css/searchreplace.css" /> +</head> +<body style="display:none;" role="application" aria-labelledby="app_title"> +<span id="app_title" style="display:none">{#searchreplace_dlg.replace_title}</span> +<form onsubmit="SearchReplaceDialog.searchNext('none');return false;" action="#"> + <div class="tabs"> + <ul> + <li id="search_tab" aria-controls="search_panel"><span><a href="javascript:SearchReplaceDialog.switchMode('search');" onmousedown="return false;">{#searchreplace.search_desc}</a></span></li> + <li id="replace_tab" aria-controls="replace_panel"><span><a href="javascript:SearchReplaceDialog.switchMode('replace');" onmousedown="return false;">{#searchreplace_dlg.replace}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="search_panel" class="panel"> + <table role="presentation" border="0" cellspacing="0" cellpadding="2"> + <tr> + <td><label for="search_panel_searchstring">{#searchreplace_dlg.findwhat}</label></td> + <td><input type="text" id="search_panel_searchstring" name="search_panel_searchstring" style="width: 200px" aria-required="true" /></td> + </tr> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0" class="direction"> + <tr role="group" aria-labelledby="search_panel_backwards_label"> + <td><label id="search_panel_backwards_label">{#searchreplace_dlg.direction}</label></td> + <td><input id="search_panel_backwardsu" name="search_panel_backwards" class="radio" type="radio" /></td> + <td><label for="search_panel_backwardsu">{#searchreplace_dlg.up}</label></td> + <td><input id="search_panel_backwardsd" name="search_panel_backwards" class="radio" type="radio" checked="checked" /></td> + <td><label for="search_panel_backwardsd">{#searchreplace_dlg.down}</label></td> + </tr> + </table> + </td> + </tr> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="search_panel_casesensitivebox" name="search_panel_casesensitivebox" class="checkbox" type="checkbox" /></td> + <td><label for="search_panel_casesensitivebox">{#searchreplace_dlg.mcase}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </div> + + <div id="replace_panel" class="panel"> + <table role="presentation" border="0" cellspacing="0" cellpadding="2"> + <tr> + <td><label for="replace_panel_searchstring">{#searchreplace_dlg.findwhat}</label></td> + <td><input type="text" id="replace_panel_searchstring" name="replace_panel_searchstring" style="width: 200px" aria-required="true" /></td> + </tr> + <tr> + <td><label for="replace_panel_replacestring">{#searchreplace_dlg.replacewith}</label></td> + <td><input type="text" id="replace_panel_replacestring" name="replace_panel_replacestring" style="width: 200px" aria-required="true" /></td> + </tr> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0" class="direction"> + <tr role="group" aria-labelledby="replace_panel_dir_label"> + <td><label id="replace_panel_dir_label">{#searchreplace_dlg.direction}</label></td> + <td><input id="replace_panel_backwardsu" name="replace_panel_backwards" class="radio" type="radio" /></td> + <td><label for="replace_panel_backwardsu">{#searchreplace_dlg.up}</label></td> + <td><input id="replace_panel_backwardsd" name="replace_panel_backwards" class="radio" type="radio" checked="checked" /></td> + <td><label for="replace_panel_backwardsd">{#searchreplace_dlg.down}</label></td> + </tr> + </table> + </td> + </tr> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="replace_panel_casesensitivebox" name="replace_panel_casesensitivebox" class="checkbox" type="checkbox" /></td> + <td><label for="replace_panel_casesensitivebox">{#searchreplace_dlg.mcase}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </div> + + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#searchreplace_dlg.findnext}" /> + <input type="button" class="button" id="replaceBtn" name="replaceBtn" value="{#searchreplace_dlg.replace}" onclick="SearchReplaceDialog.searchNext('current');" /> + <input type="button" class="button" id="replaceAllBtn" name="replaceAllBtn" value="{#searchreplace_dlg.replaceall}" onclick="SearchReplaceDialog.searchNext('all');" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/spellchecker/css/content.css b/src/core/static/js/tiny_mce/plugins/spellchecker/css/content.css new file mode 100644 index 0000000..24efa02 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/spellchecker/css/content.css @@ -0,0 +1 @@ +.mceItemHiddenSpellWord {background:url(../img/wline.gif) repeat-x bottom left; cursor:default;} diff --git a/src/core/static/js/tiny_mce/plugins/spellchecker/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/spellchecker/editor_plugin.js new file mode 100644 index 0000000..71fbb68 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/spellchecker/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.util.JSONRequest,c=tinymce.each,b=tinymce.DOM;tinymce.create("tinymce.plugins.SpellcheckerPlugin",{getInfo:function(){return{longname:"Spellchecker",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker",version:tinymce.majorVersion+"."+tinymce.minorVersion}},init:function(e,f){var g=this,d;g.url=f;g.editor=e;g.rpcUrl=e.getParam("spellchecker_rpc_url","{backend}");if(g.rpcUrl=="{backend}"){if(tinymce.isIE){return}g.hasSupport=true;e.onContextMenu.addToTop(function(h,i){if(g.active){return false}})}e.addCommand("mceSpellCheck",function(){if(g.rpcUrl=="{backend}"){g.editor.getBody().spellcheck=g.active=!g.active;return}if(!g.active){e.setProgressState(1);g._sendRPC("checkWords",[g.selectedLang,g._getWords()],function(h){if(h.length>0){g.active=1;g._markWords(h);e.setProgressState(0);e.nodeChanged()}else{e.setProgressState(0);if(e.getParam("spellchecker_report_no_misspellings",true)){e.windowManager.alert("spellchecker.no_mpell")}}})}else{g._done()}});if(e.settings.content_css!==false){e.contentCSS.push(f+"/css/content.css")}e.onClick.add(g._showMenu,g);e.onContextMenu.add(g._showMenu,g);e.onBeforeGetContent.add(function(){if(g.active){g._removeWords()}});e.onNodeChange.add(function(i,h){h.setActive("spellchecker",g.active)});e.onSetContent.add(function(){g._done()});e.onBeforeGetContent.add(function(){g._done()});e.onBeforeExecCommand.add(function(h,i){if(i=="mceFullScreen"){g._done()}});g.languages={};c(e.getParam("spellchecker_languages","+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv","hash"),function(i,h){if(h.indexOf("+")===0){h=h.substring(1);g.selectedLang=i}g.languages[h]=i})},createControl:function(h,d){var f=this,g,e=f.editor;if(h=="spellchecker"){if(f.rpcUrl=="{backend}"){if(f.hasSupport){g=d.createButton(h,{title:"spellchecker.desc",cmd:"mceSpellCheck",scope:f})}return g}g=d.createSplitButton(h,{title:"spellchecker.desc",cmd:"mceSpellCheck",scope:f});g.onRenderMenu.add(function(j,i){i.add({title:"spellchecker.langs","class":"mceMenuItemTitle"}).setDisabled(1);c(f.languages,function(n,m){var p={icon:1},l;p.onclick=function(){if(n==f.selectedLang){return}l.setSelected(1);f.selectedItem.setSelected(0);f.selectedItem=l;f.selectedLang=n};p.title=m;l=i.add(p);l.setSelected(n==f.selectedLang);if(n==f.selectedLang){f.selectedItem=l}})});return g}},_walk:function(i,g){var h=this.editor.getDoc(),e;if(h.createTreeWalker){e=h.createTreeWalker(i,NodeFilter.SHOW_TEXT,null,false);while((i=e.nextNode())!=null){g.call(this,i)}}else{tinymce.walk(i,g,"childNodes")}},_getSeparators:function(){var e="",d,f=this.editor.getParam("spellchecker_word_separator_chars",'\\s!"#$%&()*+,-./:;<=>?@[]^_{|}§©«®±¶·¸»¼½¾¿×÷¤\u201d\u201c');for(d=0;d<f.length;d++){e+="\\"+f.charAt(d)}return e},_getWords:function(){var e=this.editor,g=[],d="",f={},h=[];this._walk(e.getBody(),function(i){if(i.nodeType==3){d+=i.nodeValue+" "}});if(e.getParam("spellchecker_word_pattern")){h=d.match("("+e.getParam("spellchecker_word_pattern")+")","gi")}else{d=d.replace(new RegExp("([0-9]|["+this._getSeparators()+"])","g")," ");d=tinymce.trim(d.replace(/(\s+)/g," "));h=d.split(" ")}c(h,function(i){if(!f[i]){g.push(i);f[i]=1}});return g},_removeWords:function(e){var f=this.editor,h=f.dom,g=f.selection,d=g.getBookmark();c(h.select("span").reverse(),function(i){if(i&&(h.hasClass(i,"mceItemHiddenSpellWord")||h.hasClass(i,"mceItemHidden"))){if(!e||h.decode(i.innerHTML)==e){h.remove(i,1)}}});g.moveToBookmark(d)},_markWords:function(l){var g=this.editor,f=g.dom,j=g.getDoc(),h=g.selection,i=h.getBookmark(),d=[],k=l.join("|"),m=this._getSeparators(),e=new RegExp("(^|["+m+"])("+k+")(?=["+m+"]|$)","g");this._walk(g.getBody(),function(o){if(o.nodeType==3){d.push(o)}});c(d,function(t){var r,q,o,s,p=t.nodeValue;if(e.test(p)){p=f.encode(p);q=f.create("span",{"class":"mceItemHidden"});if(tinymce.isIE){p=p.replace(e,"$1<mcespell>$2</mcespell>");while((s=p.indexOf("<mcespell>"))!=-1){o=p.substring(0,s);if(o.length){r=j.createTextNode(f.decode(o));q.appendChild(r)}p=p.substring(s+10);s=p.indexOf("</mcespell>");o=p.substring(0,s);p=p.substring(s+11);q.appendChild(f.create("span",{"class":"mceItemHiddenSpellWord"},o))}if(p.length){r=j.createTextNode(f.decode(p));q.appendChild(r)}}else{q.innerHTML=p.replace(e,'$1<span class="mceItemHiddenSpellWord">$2</span>')}f.replace(q,t)}});h.moveToBookmark(i)},_showMenu:function(h,j){var i=this,h=i.editor,d=i._menu,l,k=h.dom,g=k.getViewPort(h.getWin()),f=j.target;j=0;if(!d){d=h.controlManager.createDropMenu("spellcheckermenu",{"class":"mceNoIcons"});i._menu=d}if(k.hasClass(f,"mceItemHiddenSpellWord")){d.removeAll();d.add({title:"spellchecker.wait","class":"mceMenuItemTitle"}).setDisabled(1);i._sendRPC("getSuggestions",[i.selectedLang,k.decode(f.innerHTML)],function(m){var e;d.removeAll();if(m.length>0){d.add({title:"spellchecker.sug","class":"mceMenuItemTitle"}).setDisabled(1);c(m,function(n){d.add({title:n,onclick:function(){k.replace(h.getDoc().createTextNode(n),f);i._checkDone()}})});d.addSeparator()}else{d.add({title:"spellchecker.no_sug","class":"mceMenuItemTitle"}).setDisabled(1)}if(h.getParam("show_ignore_words",true)){e=i.editor.getParam("spellchecker_enable_ignore_rpc","");d.add({title:"spellchecker.ignore_word",onclick:function(){var n=f.innerHTML;k.remove(f,1);i._checkDone();if(e){h.setProgressState(1);i._sendRPC("ignoreWord",[i.selectedLang,n],function(o){h.setProgressState(0)})}}});d.add({title:"spellchecker.ignore_words",onclick:function(){var n=f.innerHTML;i._removeWords(k.decode(n));i._checkDone();if(e){h.setProgressState(1);i._sendRPC("ignoreWords",[i.selectedLang,n],function(o){h.setProgressState(0)})}}})}if(i.editor.getParam("spellchecker_enable_learn_rpc")){d.add({title:"spellchecker.learn_word",onclick:function(){var n=f.innerHTML;k.remove(f,1);i._checkDone();h.setProgressState(1);i._sendRPC("learnWord",[i.selectedLang,n],function(o){h.setProgressState(0)})}})}d.update()});l=b.getPos(h.getContentAreaContainer());d.settings.offset_x=l.x;d.settings.offset_y=l.y;h.selection.select(f);l=k.getPos(f);d.showMenu(l.x,l.y+f.offsetHeight-g.y);return tinymce.dom.Event.cancel(j)}else{d.hideMenu()}},_checkDone:function(){var e=this,d=e.editor,g=d.dom,f;c(g.select("span"),function(h){if(h&&g.hasClass(h,"mceItemHiddenSpellWord")){f=true;return false}});if(!f){e._done()}},_done:function(){var d=this,e=d.active;if(d.active){d.active=0;d._removeWords();if(d._menu){d._menu.hideMenu()}if(e){d.editor.nodeChanged()}}},_sendRPC:function(e,g,d){var f=this;a.sendRPC({url:f.rpcUrl,method:e,params:g,success:d,error:function(i,h){f.editor.setProgressState(0);f.editor.windowManager.alert(i.errstr||("Error response: "+h.responseText))}})}});tinymce.PluginManager.add("spellchecker",tinymce.plugins.SpellcheckerPlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/spellchecker/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/spellchecker/editor_plugin_src.js new file mode 100644 index 0000000..fb32af4 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/spellchecker/editor_plugin_src.js @@ -0,0 +1,436 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var JSONRequest = tinymce.util.JSONRequest, each = tinymce.each, DOM = tinymce.DOM; + + tinymce.create('tinymce.plugins.SpellcheckerPlugin', { + getInfo : function() { + return { + longname : 'Spellchecker', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + init : function(ed, url) { + var t = this, cm; + + t.url = url; + t.editor = ed; + t.rpcUrl = ed.getParam("spellchecker_rpc_url", "{backend}"); + + if (t.rpcUrl == '{backend}') { + // Sniff if the browser supports native spellchecking (Don't know of a better way) + if (tinymce.isIE) + return; + + t.hasSupport = true; + + // Disable the context menu when spellchecking is active + ed.onContextMenu.addToTop(function(ed, e) { + if (t.active) + return false; + }); + } + + // Register commands + ed.addCommand('mceSpellCheck', function() { + if (t.rpcUrl == '{backend}') { + // Enable/disable native spellchecker + t.editor.getBody().spellcheck = t.active = !t.active; + return; + } + + if (!t.active) { + ed.setProgressState(1); + t._sendRPC('checkWords', [t.selectedLang, t._getWords()], function(r) { + if (r.length > 0) { + t.active = 1; + t._markWords(r); + ed.setProgressState(0); + ed.nodeChanged(); + } else { + ed.setProgressState(0); + + if (ed.getParam('spellchecker_report_no_misspellings', true)) + ed.windowManager.alert('spellchecker.no_mpell'); + } + }); + } else + t._done(); + }); + + if (ed.settings.content_css !== false) + ed.contentCSS.push(url + '/css/content.css'); + + ed.onClick.add(t._showMenu, t); + ed.onContextMenu.add(t._showMenu, t); + ed.onBeforeGetContent.add(function() { + if (t.active) + t._removeWords(); + }); + + ed.onNodeChange.add(function(ed, cm) { + cm.setActive('spellchecker', t.active); + }); + + ed.onSetContent.add(function() { + t._done(); + }); + + ed.onBeforeGetContent.add(function() { + t._done(); + }); + + ed.onBeforeExecCommand.add(function(ed, cmd) { + if (cmd == 'mceFullScreen') + t._done(); + }); + + // Find selected language + t.languages = {}; + each(ed.getParam('spellchecker_languages', '+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv', 'hash'), function(v, k) { + if (k.indexOf('+') === 0) { + k = k.substring(1); + t.selectedLang = v; + } + + t.languages[k] = v; + }); + }, + + createControl : function(n, cm) { + var t = this, c, ed = t.editor; + + if (n == 'spellchecker') { + // Use basic button if we use the native spellchecker + if (t.rpcUrl == '{backend}') { + // Create simple toggle button if we have native support + if (t.hasSupport) + c = cm.createButton(n, {title : 'spellchecker.desc', cmd : 'mceSpellCheck', scope : t}); + + return c; + } + + c = cm.createSplitButton(n, {title : 'spellchecker.desc', cmd : 'mceSpellCheck', scope : t}); + + c.onRenderMenu.add(function(c, m) { + m.add({title : 'spellchecker.langs', 'class' : 'mceMenuItemTitle'}).setDisabled(1); + each(t.languages, function(v, k) { + var o = {icon : 1}, mi; + + o.onclick = function() { + if (v == t.selectedLang) { + return; + } + mi.setSelected(1); + t.selectedItem.setSelected(0); + t.selectedItem = mi; + t.selectedLang = v; + }; + + o.title = k; + mi = m.add(o); + mi.setSelected(v == t.selectedLang); + + if (v == t.selectedLang) + t.selectedItem = mi; + }) + }); + + return c; + } + }, + + // Internal functions + + _walk : function(n, f) { + var d = this.editor.getDoc(), w; + + if (d.createTreeWalker) { + w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false); + + while ((n = w.nextNode()) != null) + f.call(this, n); + } else + tinymce.walk(n, f, 'childNodes'); + }, + + _getSeparators : function() { + var re = '', i, str = this.editor.getParam('spellchecker_word_separator_chars', '\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}§©«®±¶·¸»¼½¾¿×÷¤\u201d\u201c'); + + // Build word separator regexp + for (i=0; i<str.length; i++) + re += '\\' + str.charAt(i); + + return re; + }, + + _getWords : function() { + var ed = this.editor, wl = [], tx = '', lo = {}, rawWords = []; + + // Get area text + this._walk(ed.getBody(), function(n) { + if (n.nodeType == 3) + tx += n.nodeValue + ' '; + }); + + // split the text up into individual words + if (ed.getParam('spellchecker_word_pattern')) { + // look for words that match the pattern + rawWords = tx.match('(' + ed.getParam('spellchecker_word_pattern') + ')', 'gi'); + } else { + // Split words by separator + tx = tx.replace(new RegExp('([0-9]|[' + this._getSeparators() + '])', 'g'), ' '); + tx = tinymce.trim(tx.replace(/(\s+)/g, ' ')); + rawWords = tx.split(' '); + } + + // Build word array and remove duplicates + each(rawWords, function(v) { + if (!lo[v]) { + wl.push(v); + lo[v] = 1; + } + }); + + return wl; + }, + + _removeWords : function(w) { + var ed = this.editor, dom = ed.dom, se = ed.selection, b = se.getBookmark(); + + each(dom.select('span').reverse(), function(n) { + if (n && (dom.hasClass(n, 'mceItemHiddenSpellWord') || dom.hasClass(n, 'mceItemHidden'))) { + if (!w || dom.decode(n.innerHTML) == w) + dom.remove(n, 1); + } + }); + + se.moveToBookmark(b); + }, + + _markWords : function(wl) { + var ed = this.editor, dom = ed.dom, doc = ed.getDoc(), se = ed.selection, b = se.getBookmark(), nl = [], + w = wl.join('|'), re = this._getSeparators(), rx = new RegExp('(^|[' + re + '])(' + w + ')(?=[' + re + ']|$)', 'g'); + + // Collect all text nodes + this._walk(ed.getBody(), function(n) { + if (n.nodeType == 3) { + nl.push(n); + } + }); + + // Wrap incorrect words in spans + each(nl, function(n) { + var node, elem, txt, pos, v = n.nodeValue; + + if (rx.test(v)) { + // Encode the content + v = dom.encode(v); + // Create container element + elem = dom.create('span', {'class' : 'mceItemHidden'}); + + // Following code fixes IE issues by creating text nodes + // using DOM methods instead of innerHTML. + // Bug #3124: <PRE> elements content is broken after spellchecking. + // Bug #1408: Preceding whitespace characters are removed + // @TODO: I'm not sure that both are still issues on IE9. + if (tinymce.isIE) { + // Enclose mispelled words with temporal tag + v = v.replace(rx, '$1<mcespell>$2</mcespell>'); + // Loop over the content finding mispelled words + while ((pos = v.indexOf('<mcespell>')) != -1) { + // Add text node for the content before the word + txt = v.substring(0, pos); + if (txt.length) { + node = doc.createTextNode(dom.decode(txt)); + elem.appendChild(node); + } + v = v.substring(pos+10); + pos = v.indexOf('</mcespell>'); + txt = v.substring(0, pos); + v = v.substring(pos+11); + // Add span element for the word + elem.appendChild(dom.create('span', {'class' : 'mceItemHiddenSpellWord'}, txt)); + } + // Add text node for the rest of the content + if (v.length) { + node = doc.createTextNode(dom.decode(v)); + elem.appendChild(node); + } + } else { + // Other browsers preserve whitespace characters on innerHTML usage + elem.innerHTML = v.replace(rx, '$1<span class="mceItemHiddenSpellWord">$2</span>'); + } + + // Finally, replace the node with the container + dom.replace(elem, n); + } + }); + + se.moveToBookmark(b); + }, + + _showMenu : function(ed, e) { + var t = this, ed = t.editor, m = t._menu, p1, dom = ed.dom, vp = dom.getViewPort(ed.getWin()), wordSpan = e.target; + + e = 0; // Fixes IE memory leak + + if (!m) { + m = ed.controlManager.createDropMenu('spellcheckermenu', {'class' : 'mceNoIcons'}); + t._menu = m; + } + + if (dom.hasClass(wordSpan, 'mceItemHiddenSpellWord')) { + m.removeAll(); + m.add({title : 'spellchecker.wait', 'class' : 'mceMenuItemTitle'}).setDisabled(1); + + t._sendRPC('getSuggestions', [t.selectedLang, dom.decode(wordSpan.innerHTML)], function(r) { + var ignoreRpc; + + m.removeAll(); + + if (r.length > 0) { + m.add({title : 'spellchecker.sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1); + each(r, function(v) { + m.add({title : v, onclick : function() { + dom.replace(ed.getDoc().createTextNode(v), wordSpan); + t._checkDone(); + }}); + }); + + m.addSeparator(); + } else + m.add({title : 'spellchecker.no_sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1); + + if (ed.getParam('show_ignore_words', true)) { + ignoreRpc = t.editor.getParam("spellchecker_enable_ignore_rpc", ''); + m.add({ + title : 'spellchecker.ignore_word', + onclick : function() { + var word = wordSpan.innerHTML; + + dom.remove(wordSpan, 1); + t._checkDone(); + + // tell the server if we need to + if (ignoreRpc) { + ed.setProgressState(1); + t._sendRPC('ignoreWord', [t.selectedLang, word], function(r) { + ed.setProgressState(0); + }); + } + } + }); + + m.add({ + title : 'spellchecker.ignore_words', + onclick : function() { + var word = wordSpan.innerHTML; + + t._removeWords(dom.decode(word)); + t._checkDone(); + + // tell the server if we need to + if (ignoreRpc) { + ed.setProgressState(1); + t._sendRPC('ignoreWords', [t.selectedLang, word], function(r) { + ed.setProgressState(0); + }); + } + } + }); + } + + if (t.editor.getParam("spellchecker_enable_learn_rpc")) { + m.add({ + title : 'spellchecker.learn_word', + onclick : function() { + var word = wordSpan.innerHTML; + + dom.remove(wordSpan, 1); + t._checkDone(); + + ed.setProgressState(1); + t._sendRPC('learnWord', [t.selectedLang, word], function(r) { + ed.setProgressState(0); + }); + } + }); + } + + m.update(); + }); + + p1 = DOM.getPos(ed.getContentAreaContainer()); + m.settings.offset_x = p1.x; + m.settings.offset_y = p1.y; + + ed.selection.select(wordSpan); + p1 = dom.getPos(wordSpan); + m.showMenu(p1.x, p1.y + wordSpan.offsetHeight - vp.y); + + return tinymce.dom.Event.cancel(e); + } else + m.hideMenu(); + }, + + _checkDone : function() { + var t = this, ed = t.editor, dom = ed.dom, o; + + each(dom.select('span'), function(n) { + if (n && dom.hasClass(n, 'mceItemHiddenSpellWord')) { + o = true; + return false; + } + }); + + if (!o) + t._done(); + }, + + _done : function() { + var t = this, la = t.active; + + if (t.active) { + t.active = 0; + t._removeWords(); + + if (t._menu) + t._menu.hideMenu(); + + if (la) + t.editor.nodeChanged(); + } + }, + + _sendRPC : function(m, p, cb) { + var t = this; + + JSONRequest.sendRPC({ + url : t.rpcUrl, + method : m, + params : p, + success : cb, + error : function(e, x) { + t.editor.setProgressState(0); + t.editor.windowManager.alert(e.errstr || ('Error response: ' + x.responseText)); + } + }); + } + }); + + // Register plugin + tinymce.PluginManager.add('spellchecker', tinymce.plugins.SpellcheckerPlugin); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/spellchecker/img/wline.gif b/src/core/static/js/tiny_mce/plugins/spellchecker/img/wline.gif new file mode 100644 index 0000000000000000000000000000000000000000..7d0a4dbca03cc13177a359a5f175dda819fdf464 GIT binary patch literal 46 ycmZ?wbhEHbWMN=tXkcXcqowu#|9{1wEQ|~cj0`#qKmd|qU}ANVOOs?}um%7FLkRf* literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/plugins/style/css/props.css b/src/core/static/js/tiny_mce/plugins/style/css/props.css new file mode 100644 index 0000000..eb1f264 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/style/css/props.css @@ -0,0 +1,13 @@ +#text_font {width:250px;} +#text_size {width:70px;} +.mceAddSelectValue {background:#DDD;} +select, #block_text_indent, #box_width, #box_height, #box_padding_top, #box_padding_right, #box_padding_bottom, #box_padding_left {width:70px;} +#box_margin_top, #box_margin_right, #box_margin_bottom, #box_margin_left, #positioning_width, #positioning_height, #positioning_zindex {width:70px;} +#positioning_placement_top, #positioning_placement_right, #positioning_placement_bottom, #positioning_placement_left {width:70px;} +#positioning_clip_top, #positioning_clip_right, #positioning_clip_bottom, #positioning_clip_left {width:70px;} +.panel_wrapper div.current {padding-top:10px;height:230px;} +.delim {border-left:1px solid gray;} +.tdelim {border-bottom:1px solid gray;} +#block_display {width:145px;} +#list_type {width:115px;} +.disabled {background:#EEE;} diff --git a/src/core/static/js/tiny_mce/plugins/style/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/style/editor_plugin.js new file mode 100644 index 0000000..cab2153 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/style/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.StylePlugin",{init:function(a,b){a.addCommand("mceStyleProps",function(){a.windowManager.open({file:b+"/props.htm",width:480+parseInt(a.getLang("style.delta_width",0)),height:320+parseInt(a.getLang("style.delta_height",0)),inline:1},{plugin_url:b,style_text:a.selection.getNode().style.cssText})});a.addCommand("mceSetElementStyle",function(d,c){if(e=a.selection.getNode()){a.dom.setAttrib(e,"style",c);a.execCommand("mceRepaint")}});a.onNodeChange.add(function(d,c,f){c.setDisabled("styleprops",f.nodeName==="BODY")});a.addButton("styleprops",{title:"style.desc",cmd:"mceStyleProps"})},getInfo:function(){return{longname:"Style",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/style",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("style",tinymce.plugins.StylePlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/style/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/style/editor_plugin_src.js new file mode 100644 index 0000000..5f7755f --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/style/editor_plugin_src.js @@ -0,0 +1,55 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.StylePlugin', { + init : function(ed, url) { + // Register commands + ed.addCommand('mceStyleProps', function() { + ed.windowManager.open({ + file : url + '/props.htm', + width : 480 + parseInt(ed.getLang('style.delta_width', 0)), + height : 320 + parseInt(ed.getLang('style.delta_height', 0)), + inline : 1 + }, { + plugin_url : url, + style_text : ed.selection.getNode().style.cssText + }); + }); + + ed.addCommand('mceSetElementStyle', function(ui, v) { + if (e = ed.selection.getNode()) { + ed.dom.setAttrib(e, 'style', v); + ed.execCommand('mceRepaint'); + } + }); + + ed.onNodeChange.add(function(ed, cm, n) { + cm.setDisabled('styleprops', n.nodeName === 'BODY'); + }); + + // Register buttons + ed.addButton('styleprops', {title : 'style.desc', cmd : 'mceStyleProps'}); + }, + + getInfo : function() { + return { + longname : 'Style', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/style', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('style', tinymce.plugins.StylePlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/style/js/props.js b/src/core/static/js/tiny_mce/plugins/style/js/props.js new file mode 100644 index 0000000..6800a9a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/style/js/props.js @@ -0,0 +1,635 @@ +tinyMCEPopup.requireLangPack(); + +var defaultFonts = "" + + "Arial, Helvetica, sans-serif=Arial, Helvetica, sans-serif;" + + "Times New Roman, Times, serif=Times New Roman, Times, serif;" + + "Courier New, Courier, mono=Courier New, Courier, mono;" + + "Times New Roman, Times, serif=Times New Roman, Times, serif;" + + "Georgia, Times New Roman, Times, serif=Georgia, Times New Roman, Times, serif;" + + "Verdana, Arial, Helvetica, sans-serif=Verdana, Arial, Helvetica, sans-serif;" + + "Geneva, Arial, Helvetica, sans-serif=Geneva, Arial, Helvetica, sans-serif"; + +var defaultSizes = "9;10;12;14;16;18;24;xx-small;x-small;small;medium;large;x-large;xx-large;smaller;larger"; +var defaultMeasurement = "+pixels=px;points=pt;inches=in;centimetres=cm;millimetres=mm;picas=pc;ems=em;exs=ex;%"; +var defaultSpacingMeasurement = "pixels=px;points=pt;inches=in;centimetres=cm;millimetres=mm;picas=pc;+ems=em;exs=ex;%"; +var defaultIndentMeasurement = "pixels=px;+points=pt;inches=in;centimetres=cm;millimetres=mm;picas=pc;ems=em;exs=ex;%"; +var defaultWeight = "normal;bold;bolder;lighter;100;200;300;400;500;600;700;800;900"; +var defaultTextStyle = "normal;italic;oblique"; +var defaultVariant = "normal;small-caps"; +var defaultLineHeight = "normal"; +var defaultAttachment = "fixed;scroll"; +var defaultRepeat = "no-repeat;repeat;repeat-x;repeat-y"; +var defaultPosH = "left;center;right"; +var defaultPosV = "top;center;bottom"; +var defaultVAlign = "baseline;sub;super;top;text-top;middle;bottom;text-bottom"; +var defaultDisplay = "inline;block;list-item;run-in;compact;marker;table;inline-table;table-row-group;table-header-group;table-footer-group;table-row;table-column-group;table-column;table-cell;table-caption;none"; +var defaultBorderStyle = "none;solid;dashed;dotted;double;groove;ridge;inset;outset"; +var defaultBorderWidth = "thin;medium;thick"; +var defaultListType = "disc;circle;square;decimal;lower-roman;upper-roman;lower-alpha;upper-alpha;none"; + +function init() { + var ce = document.getElementById('container'), h; + + ce.style.cssText = tinyMCEPopup.getWindowArg('style_text'); + + h = getBrowserHTML('background_image_browser','background_image','image','advimage'); + document.getElementById("background_image_browser").innerHTML = h; + + document.getElementById('text_color_pickcontainer').innerHTML = getColorPickerHTML('text_color_pick','text_color'); + document.getElementById('background_color_pickcontainer').innerHTML = getColorPickerHTML('background_color_pick','background_color'); + document.getElementById('border_color_top_pickcontainer').innerHTML = getColorPickerHTML('border_color_top_pick','border_color_top'); + document.getElementById('border_color_right_pickcontainer').innerHTML = getColorPickerHTML('border_color_right_pick','border_color_right'); + document.getElementById('border_color_bottom_pickcontainer').innerHTML = getColorPickerHTML('border_color_bottom_pick','border_color_bottom'); + document.getElementById('border_color_left_pickcontainer').innerHTML = getColorPickerHTML('border_color_left_pick','border_color_left'); + + fillSelect(0, 'text_font', 'style_font', defaultFonts, ';', true); + fillSelect(0, 'text_size', 'style_font_size', defaultSizes, ';', true); + fillSelect(0, 'text_size_measurement', 'style_font_size_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'text_case', 'style_text_case', "capitalize;uppercase;lowercase", ';', true); + fillSelect(0, 'text_weight', 'style_font_weight', defaultWeight, ';', true); + fillSelect(0, 'text_style', 'style_font_style', defaultTextStyle, ';', true); + fillSelect(0, 'text_variant', 'style_font_variant', defaultVariant, ';', true); + fillSelect(0, 'text_lineheight', 'style_font_line_height', defaultLineHeight, ';', true); + fillSelect(0, 'text_lineheight_measurement', 'style_font_line_height_measurement', defaultMeasurement, ';', true); + + fillSelect(0, 'background_attachment', 'style_background_attachment', defaultAttachment, ';', true); + fillSelect(0, 'background_repeat', 'style_background_repeat', defaultRepeat, ';', true); + + fillSelect(0, 'background_hpos_measurement', 'style_background_hpos_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'background_vpos_measurement', 'style_background_vpos_measurement', defaultMeasurement, ';', true); + + fillSelect(0, 'background_hpos', 'style_background_hpos', defaultPosH, ';', true); + fillSelect(0, 'background_vpos', 'style_background_vpos', defaultPosV, ';', true); + + fillSelect(0, 'block_wordspacing', 'style_wordspacing', 'normal', ';', true); + fillSelect(0, 'block_wordspacing_measurement', 'style_wordspacing_measurement', defaultSpacingMeasurement, ';', true); + fillSelect(0, 'block_letterspacing', 'style_letterspacing', 'normal', ';', true); + fillSelect(0, 'block_letterspacing_measurement', 'style_letterspacing_measurement', defaultSpacingMeasurement, ';', true); + fillSelect(0, 'block_vertical_alignment', 'style_vertical_alignment', defaultVAlign, ';', true); + fillSelect(0, 'block_text_align', 'style_text_align', "left;right;center;justify", ';', true); + fillSelect(0, 'block_whitespace', 'style_whitespace', "normal;pre;nowrap", ';', true); + fillSelect(0, 'block_display', 'style_display', defaultDisplay, ';', true); + fillSelect(0, 'block_text_indent_measurement', 'style_text_indent_measurement', defaultIndentMeasurement, ';', true); + + fillSelect(0, 'box_width_measurement', 'style_box_width_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_height_measurement', 'style_box_height_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_float', 'style_float', 'left;right;none', ';', true); + fillSelect(0, 'box_clear', 'style_clear', 'left;right;both;none', ';', true); + fillSelect(0, 'box_padding_left_measurement', 'style_padding_left_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_padding_top_measurement', 'style_padding_top_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_padding_bottom_measurement', 'style_padding_bottom_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_padding_right_measurement', 'style_padding_right_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_margin_left_measurement', 'style_margin_left_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_margin_top_measurement', 'style_margin_top_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_margin_bottom_measurement', 'style_margin_bottom_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_margin_right_measurement', 'style_margin_right_measurement', defaultMeasurement, ';', true); + + fillSelect(0, 'border_style_top', 'style_border_style_top', defaultBorderStyle, ';', true); + fillSelect(0, 'border_style_right', 'style_border_style_right', defaultBorderStyle, ';', true); + fillSelect(0, 'border_style_bottom', 'style_border_style_bottom', defaultBorderStyle, ';', true); + fillSelect(0, 'border_style_left', 'style_border_style_left', defaultBorderStyle, ';', true); + + fillSelect(0, 'border_width_top', 'style_border_width_top', defaultBorderWidth, ';', true); + fillSelect(0, 'border_width_right', 'style_border_width_right', defaultBorderWidth, ';', true); + fillSelect(0, 'border_width_bottom', 'style_border_width_bottom', defaultBorderWidth, ';', true); + fillSelect(0, 'border_width_left', 'style_border_width_left', defaultBorderWidth, ';', true); + + fillSelect(0, 'border_width_top_measurement', 'style_border_width_top_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'border_width_right_measurement', 'style_border_width_right_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'border_width_bottom_measurement', 'style_border_width_bottom_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'border_width_left_measurement', 'style_border_width_left_measurement', defaultMeasurement, ';', true); + + fillSelect(0, 'list_type', 'style_list_type', defaultListType, ';', true); + fillSelect(0, 'list_position', 'style_list_position', "inside;outside", ';', true); + + fillSelect(0, 'positioning_type', 'style_positioning_type', "absolute;relative;static", ';', true); + fillSelect(0, 'positioning_visibility', 'style_positioning_visibility', "inherit;visible;hidden", ';', true); + + fillSelect(0, 'positioning_width_measurement', 'style_positioning_width_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_height_measurement', 'style_positioning_height_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_overflow', 'style_positioning_overflow', "visible;hidden;scroll;auto", ';', true); + + fillSelect(0, 'positioning_placement_top_measurement', 'style_positioning_placement_top_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_placement_right_measurement', 'style_positioning_placement_right_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_placement_bottom_measurement', 'style_positioning_placement_bottom_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_placement_left_measurement', 'style_positioning_placement_left_measurement', defaultMeasurement, ';', true); + + fillSelect(0, 'positioning_clip_top_measurement', 'style_positioning_clip_top_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_clip_right_measurement', 'style_positioning_clip_right_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_clip_bottom_measurement', 'style_positioning_clip_bottom_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_clip_left_measurement', 'style_positioning_clip_left_measurement', defaultMeasurement, ';', true); + + TinyMCE_EditableSelects.init(); + setupFormData(); + showDisabledControls(); +} + +function setupFormData() { + var ce = document.getElementById('container'), f = document.forms[0], s, b, i; + + // Setup text fields + + selectByValue(f, 'text_font', ce.style.fontFamily, true, true); + selectByValue(f, 'text_size', getNum(ce.style.fontSize), true, true); + selectByValue(f, 'text_size_measurement', getMeasurement(ce.style.fontSize)); + selectByValue(f, 'text_weight', ce.style.fontWeight, true, true); + selectByValue(f, 'text_style', ce.style.fontStyle, true, true); + selectByValue(f, 'text_lineheight', getNum(ce.style.lineHeight), true, true); + selectByValue(f, 'text_lineheight_measurement', getMeasurement(ce.style.lineHeight)); + selectByValue(f, 'text_case', ce.style.textTransform, true, true); + selectByValue(f, 'text_variant', ce.style.fontVariant, true, true); + f.text_color.value = tinyMCEPopup.editor.dom.toHex(ce.style.color); + updateColor('text_color_pick', 'text_color'); + f.text_underline.checked = inStr(ce.style.textDecoration, 'underline'); + f.text_overline.checked = inStr(ce.style.textDecoration, 'overline'); + f.text_linethrough.checked = inStr(ce.style.textDecoration, 'line-through'); + f.text_blink.checked = inStr(ce.style.textDecoration, 'blink'); + + // Setup background fields + + f.background_color.value = tinyMCEPopup.editor.dom.toHex(ce.style.backgroundColor); + updateColor('background_color_pick', 'background_color'); + f.background_image.value = ce.style.backgroundImage.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1"); + selectByValue(f, 'background_repeat', ce.style.backgroundRepeat, true, true); + selectByValue(f, 'background_attachment', ce.style.backgroundAttachment, true, true); + selectByValue(f, 'background_hpos', getNum(getVal(ce.style.backgroundPosition, 0)), true, true); + selectByValue(f, 'background_hpos_measurement', getMeasurement(getVal(ce.style.backgroundPosition, 0))); + selectByValue(f, 'background_vpos', getNum(getVal(ce.style.backgroundPosition, 1)), true, true); + selectByValue(f, 'background_vpos_measurement', getMeasurement(getVal(ce.style.backgroundPosition, 1))); + + // Setup block fields + + selectByValue(f, 'block_wordspacing', getNum(ce.style.wordSpacing), true, true); + selectByValue(f, 'block_wordspacing_measurement', getMeasurement(ce.style.wordSpacing)); + selectByValue(f, 'block_letterspacing', getNum(ce.style.letterSpacing), true, true); + selectByValue(f, 'block_letterspacing_measurement', getMeasurement(ce.style.letterSpacing)); + selectByValue(f, 'block_vertical_alignment', ce.style.verticalAlign, true, true); + selectByValue(f, 'block_text_align', ce.style.textAlign, true, true); + f.block_text_indent.value = getNum(ce.style.textIndent); + selectByValue(f, 'block_text_indent_measurement', getMeasurement(ce.style.textIndent)); + selectByValue(f, 'block_whitespace', ce.style.whiteSpace, true, true); + selectByValue(f, 'block_display', ce.style.display, true, true); + + // Setup box fields + + f.box_width.value = getNum(ce.style.width); + selectByValue(f, 'box_width_measurement', getMeasurement(ce.style.width)); + + f.box_height.value = getNum(ce.style.height); + selectByValue(f, 'box_height_measurement', getMeasurement(ce.style.height)); + selectByValue(f, 'box_float', ce.style.cssFloat || ce.style.styleFloat, true, true); + + selectByValue(f, 'box_clear', ce.style.clear, true, true); + + setupBox(f, ce, 'box_padding', 'padding', ''); + setupBox(f, ce, 'box_margin', 'margin', ''); + + // Setup border fields + + setupBox(f, ce, 'border_style', 'border', 'Style'); + setupBox(f, ce, 'border_width', 'border', 'Width'); + setupBox(f, ce, 'border_color', 'border', 'Color'); + + updateColor('border_color_top_pick', 'border_color_top'); + updateColor('border_color_right_pick', 'border_color_right'); + updateColor('border_color_bottom_pick', 'border_color_bottom'); + updateColor('border_color_left_pick', 'border_color_left'); + + f.elements.border_color_top.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_top.value); + f.elements.border_color_right.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_right.value); + f.elements.border_color_bottom.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_bottom.value); + f.elements.border_color_left.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_left.value); + + // Setup list fields + + selectByValue(f, 'list_type', ce.style.listStyleType, true, true); + selectByValue(f, 'list_position', ce.style.listStylePosition, true, true); + f.list_bullet_image.value = ce.style.listStyleImage.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1"); + + // Setup box fields + + selectByValue(f, 'positioning_type', ce.style.position, true, true); + selectByValue(f, 'positioning_visibility', ce.style.visibility, true, true); + selectByValue(f, 'positioning_overflow', ce.style.overflow, true, true); + f.positioning_zindex.value = ce.style.zIndex ? ce.style.zIndex : ""; + + f.positioning_width.value = getNum(ce.style.width); + selectByValue(f, 'positioning_width_measurement', getMeasurement(ce.style.width)); + + f.positioning_height.value = getNum(ce.style.height); + selectByValue(f, 'positioning_height_measurement', getMeasurement(ce.style.height)); + + setupBox(f, ce, 'positioning_placement', '', '', ['top', 'right', 'bottom', 'left']); + + s = ce.style.clip.replace(new RegExp("rect\\('?([^']*)'?\\)", 'gi'), "$1"); + s = s.replace(/,/g, ' '); + + if (!hasEqualValues([getVal(s, 0), getVal(s, 1), getVal(s, 2), getVal(s, 3)])) { + f.positioning_clip_top.value = getNum(getVal(s, 0)); + selectByValue(f, 'positioning_clip_top_measurement', getMeasurement(getVal(s, 0))); + f.positioning_clip_right.value = getNum(getVal(s, 1)); + selectByValue(f, 'positioning_clip_right_measurement', getMeasurement(getVal(s, 1))); + f.positioning_clip_bottom.value = getNum(getVal(s, 2)); + selectByValue(f, 'positioning_clip_bottom_measurement', getMeasurement(getVal(s, 2))); + f.positioning_clip_left.value = getNum(getVal(s, 3)); + selectByValue(f, 'positioning_clip_left_measurement', getMeasurement(getVal(s, 3))); + } else { + f.positioning_clip_top.value = getNum(getVal(s, 0)); + selectByValue(f, 'positioning_clip_top_measurement', getMeasurement(getVal(s, 0))); + f.positioning_clip_right.value = f.positioning_clip_bottom.value = f.positioning_clip_left.value; + } + +// setupBox(f, ce, '', 'border', 'Color'); +} + +function getMeasurement(s) { + return s.replace(/^([0-9.]+)(.*)$/, "$2"); +} + +function getNum(s) { + if (new RegExp('^(?:[0-9.]+)(?:[a-z%]+)$', 'gi').test(s)) + return s.replace(/[^0-9.]/g, ''); + + return s; +} + +function inStr(s, n) { + return new RegExp(n, 'gi').test(s); +} + +function getVal(s, i) { + var a = s.split(' '); + + if (a.length > 1) + return a[i]; + + return ""; +} + +function setValue(f, n, v) { + if (f.elements[n].type == "text") + f.elements[n].value = v; + else + selectByValue(f, n, v, true, true); +} + +function setupBox(f, ce, fp, pr, sf, b) { + if (typeof(b) == "undefined") + b = ['Top', 'Right', 'Bottom', 'Left']; + + if (isSame(ce, pr, sf, b)) { + f.elements[fp + "_same"].checked = true; + + setValue(f, fp + "_top", getNum(ce.style[pr + b[0] + sf])); + f.elements[fp + "_top"].disabled = false; + + f.elements[fp + "_right"].value = ""; + f.elements[fp + "_right"].disabled = true; + f.elements[fp + "_bottom"].value = ""; + f.elements[fp + "_bottom"].disabled = true; + f.elements[fp + "_left"].value = ""; + f.elements[fp + "_left"].disabled = true; + + if (f.elements[fp + "_top_measurement"]) { + selectByValue(f, fp + '_top_measurement', getMeasurement(ce.style[pr + b[0] + sf])); + f.elements[fp + "_left_measurement"].disabled = true; + f.elements[fp + "_bottom_measurement"].disabled = true; + f.elements[fp + "_right_measurement"].disabled = true; + } + } else { + f.elements[fp + "_same"].checked = false; + + setValue(f, fp + "_top", getNum(ce.style[pr + b[0] + sf])); + f.elements[fp + "_top"].disabled = false; + + setValue(f, fp + "_right", getNum(ce.style[pr + b[1] + sf])); + f.elements[fp + "_right"].disabled = false; + + setValue(f, fp + "_bottom", getNum(ce.style[pr + b[2] + sf])); + f.elements[fp + "_bottom"].disabled = false; + + setValue(f, fp + "_left", getNum(ce.style[pr + b[3] + sf])); + f.elements[fp + "_left"].disabled = false; + + if (f.elements[fp + "_top_measurement"]) { + selectByValue(f, fp + '_top_measurement', getMeasurement(ce.style[pr + b[0] + sf])); + selectByValue(f, fp + '_right_measurement', getMeasurement(ce.style[pr + b[1] + sf])); + selectByValue(f, fp + '_bottom_measurement', getMeasurement(ce.style[pr + b[2] + sf])); + selectByValue(f, fp + '_left_measurement', getMeasurement(ce.style[pr + b[3] + sf])); + f.elements[fp + "_left_measurement"].disabled = false; + f.elements[fp + "_bottom_measurement"].disabled = false; + f.elements[fp + "_right_measurement"].disabled = false; + } + } +} + +function isSame(e, pr, sf, b) { + var a = [], i, x; + + if (typeof(b) == "undefined") + b = ['Top', 'Right', 'Bottom', 'Left']; + + if (typeof(sf) == "undefined" || sf == null) + sf = ""; + + a[0] = e.style[pr + b[0] + sf]; + a[1] = e.style[pr + b[1] + sf]; + a[2] = e.style[pr + b[2] + sf]; + a[3] = e.style[pr + b[3] + sf]; + + for (i=0; i<a.length; i++) { + if (a[i] == null) + return false; + + for (x=0; x<a.length; x++) { + if (a[x] != a[i]) + return false; + } + } + + return true; +}; + +function hasEqualValues(a) { + var i, x; + + for (i=0; i<a.length; i++) { + if (a[i] == null) + return false; + + for (x=0; x<a.length; x++) { + if (a[x] != a[i]) + return false; + } + } + + return true; +} + +function applyAction() { + var ce = document.getElementById('container'), ed = tinyMCEPopup.editor; + + generateCSS(); + + tinyMCEPopup.restoreSelection(); + ed.dom.setAttrib(ed.selection.getSelectedBlocks(), 'style', tinyMCEPopup.editor.dom.serializeStyle(tinyMCEPopup.editor.dom.parseStyle(ce.style.cssText))); +} + +function updateAction() { + applyAction(); + tinyMCEPopup.close(); +} + +function generateCSS() { + var ce = document.getElementById('container'), f = document.forms[0], num = new RegExp('[0-9]+', 'g'), s, t; + + ce.style.cssText = ""; + + // Build text styles + ce.style.fontFamily = f.text_font.value; + ce.style.fontSize = f.text_size.value + (isNum(f.text_size.value) ? (f.text_size_measurement.value || 'px') : ""); + ce.style.fontStyle = f.text_style.value; + ce.style.lineHeight = f.text_lineheight.value + (isNum(f.text_lineheight.value) ? f.text_lineheight_measurement.value : ""); + ce.style.textTransform = f.text_case.value; + ce.style.fontWeight = f.text_weight.value; + ce.style.fontVariant = f.text_variant.value; + ce.style.color = f.text_color.value; + + s = ""; + s += f.text_underline.checked ? " underline" : ""; + s += f.text_overline.checked ? " overline" : ""; + s += f.text_linethrough.checked ? " line-through" : ""; + s += f.text_blink.checked ? " blink" : ""; + s = s.length > 0 ? s.substring(1) : s; + + if (f.text_none.checked) + s = "none"; + + ce.style.textDecoration = s; + + // Build background styles + + ce.style.backgroundColor = f.background_color.value; + ce.style.backgroundImage = f.background_image.value != "" ? "url(" + f.background_image.value + ")" : ""; + ce.style.backgroundRepeat = f.background_repeat.value; + ce.style.backgroundAttachment = f.background_attachment.value; + + if (f.background_hpos.value != "") { + s = ""; + s += f.background_hpos.value + (isNum(f.background_hpos.value) ? f.background_hpos_measurement.value : "") + " "; + s += f.background_vpos.value + (isNum(f.background_vpos.value) ? f.background_vpos_measurement.value : ""); + ce.style.backgroundPosition = s; + } + + // Build block styles + + ce.style.wordSpacing = f.block_wordspacing.value + (isNum(f.block_wordspacing.value) ? f.block_wordspacing_measurement.value : ""); + ce.style.letterSpacing = f.block_letterspacing.value + (isNum(f.block_letterspacing.value) ? f.block_letterspacing_measurement.value : ""); + ce.style.verticalAlign = f.block_vertical_alignment.value; + ce.style.textAlign = f.block_text_align.value; + ce.style.textIndent = f.block_text_indent.value + (isNum(f.block_text_indent.value) ? f.block_text_indent_measurement.value : ""); + ce.style.whiteSpace = f.block_whitespace.value; + ce.style.display = f.block_display.value; + + // Build box styles + + ce.style.width = f.box_width.value + (isNum(f.box_width.value) ? f.box_width_measurement.value : ""); + ce.style.height = f.box_height.value + (isNum(f.box_height.value) ? f.box_height_measurement.value : ""); + ce.style.styleFloat = f.box_float.value; + ce.style.cssFloat = f.box_float.value; + + ce.style.clear = f.box_clear.value; + + if (!f.box_padding_same.checked) { + ce.style.paddingTop = f.box_padding_top.value + (isNum(f.box_padding_top.value) ? f.box_padding_top_measurement.value : ""); + ce.style.paddingRight = f.box_padding_right.value + (isNum(f.box_padding_right.value) ? f.box_padding_right_measurement.value : ""); + ce.style.paddingBottom = f.box_padding_bottom.value + (isNum(f.box_padding_bottom.value) ? f.box_padding_bottom_measurement.value : ""); + ce.style.paddingLeft = f.box_padding_left.value + (isNum(f.box_padding_left.value) ? f.box_padding_left_measurement.value : ""); + } else + ce.style.padding = f.box_padding_top.value + (isNum(f.box_padding_top.value) ? f.box_padding_top_measurement.value : ""); + + if (!f.box_margin_same.checked) { + ce.style.marginTop = f.box_margin_top.value + (isNum(f.box_margin_top.value) ? f.box_margin_top_measurement.value : ""); + ce.style.marginRight = f.box_margin_right.value + (isNum(f.box_margin_right.value) ? f.box_margin_right_measurement.value : ""); + ce.style.marginBottom = f.box_margin_bottom.value + (isNum(f.box_margin_bottom.value) ? f.box_margin_bottom_measurement.value : ""); + ce.style.marginLeft = f.box_margin_left.value + (isNum(f.box_margin_left.value) ? f.box_margin_left_measurement.value : ""); + } else + ce.style.margin = f.box_margin_top.value + (isNum(f.box_margin_top.value) ? f.box_margin_top_measurement.value : ""); + + // Build border styles + + if (!f.border_style_same.checked) { + ce.style.borderTopStyle = f.border_style_top.value; + ce.style.borderRightStyle = f.border_style_right.value; + ce.style.borderBottomStyle = f.border_style_bottom.value; + ce.style.borderLeftStyle = f.border_style_left.value; + } else + ce.style.borderStyle = f.border_style_top.value; + + if (!f.border_width_same.checked) { + ce.style.borderTopWidth = f.border_width_top.value + (isNum(f.border_width_top.value) ? f.border_width_top_measurement.value : ""); + ce.style.borderRightWidth = f.border_width_right.value + (isNum(f.border_width_right.value) ? f.border_width_right_measurement.value : ""); + ce.style.borderBottomWidth = f.border_width_bottom.value + (isNum(f.border_width_bottom.value) ? f.border_width_bottom_measurement.value : ""); + ce.style.borderLeftWidth = f.border_width_left.value + (isNum(f.border_width_left.value) ? f.border_width_left_measurement.value : ""); + } else + ce.style.borderWidth = f.border_width_top.value + (isNum(f.border_width_top.value) ? f.border_width_top_measurement.value : ""); + + if (!f.border_color_same.checked) { + ce.style.borderTopColor = f.border_color_top.value; + ce.style.borderRightColor = f.border_color_right.value; + ce.style.borderBottomColor = f.border_color_bottom.value; + ce.style.borderLeftColor = f.border_color_left.value; + } else + ce.style.borderColor = f.border_color_top.value; + + // Build list styles + + ce.style.listStyleType = f.list_type.value; + ce.style.listStylePosition = f.list_position.value; + ce.style.listStyleImage = f.list_bullet_image.value != "" ? "url(" + f.list_bullet_image.value + ")" : ""; + + // Build positioning styles + + ce.style.position = f.positioning_type.value; + ce.style.visibility = f.positioning_visibility.value; + + if (ce.style.width == "") + ce.style.width = f.positioning_width.value + (isNum(f.positioning_width.value) ? f.positioning_width_measurement.value : ""); + + if (ce.style.height == "") + ce.style.height = f.positioning_height.value + (isNum(f.positioning_height.value) ? f.positioning_height_measurement.value : ""); + + ce.style.zIndex = f.positioning_zindex.value; + ce.style.overflow = f.positioning_overflow.value; + + if (!f.positioning_placement_same.checked) { + ce.style.top = f.positioning_placement_top.value + (isNum(f.positioning_placement_top.value) ? f.positioning_placement_top_measurement.value : ""); + ce.style.right = f.positioning_placement_right.value + (isNum(f.positioning_placement_right.value) ? f.positioning_placement_right_measurement.value : ""); + ce.style.bottom = f.positioning_placement_bottom.value + (isNum(f.positioning_placement_bottom.value) ? f.positioning_placement_bottom_measurement.value : ""); + ce.style.left = f.positioning_placement_left.value + (isNum(f.positioning_placement_left.value) ? f.positioning_placement_left_measurement.value : ""); + } else { + s = f.positioning_placement_top.value + (isNum(f.positioning_placement_top.value) ? f.positioning_placement_top_measurement.value : ""); + ce.style.top = s; + ce.style.right = s; + ce.style.bottom = s; + ce.style.left = s; + } + + if (!f.positioning_clip_same.checked) { + s = "rect("; + s += (isNum(f.positioning_clip_top.value) ? f.positioning_clip_top.value + f.positioning_clip_top_measurement.value : "auto") + " "; + s += (isNum(f.positioning_clip_right.value) ? f.positioning_clip_right.value + f.positioning_clip_right_measurement.value : "auto") + " "; + s += (isNum(f.positioning_clip_bottom.value) ? f.positioning_clip_bottom.value + f.positioning_clip_bottom_measurement.value : "auto") + " "; + s += (isNum(f.positioning_clip_left.value) ? f.positioning_clip_left.value + f.positioning_clip_left_measurement.value : "auto"); + s += ")"; + + if (s != "rect(auto auto auto auto)") + ce.style.clip = s; + } else { + s = "rect("; + t = isNum(f.positioning_clip_top.value) ? f.positioning_clip_top.value + f.positioning_clip_top_measurement.value : "auto"; + s += t + " "; + s += t + " "; + s += t + " "; + s += t + ")"; + + if (s != "rect(auto auto auto auto)") + ce.style.clip = s; + } + + ce.style.cssText = ce.style.cssText; +} + +function isNum(s) { + return new RegExp('[0-9]+', 'g').test(s); +} + +function showDisabledControls() { + var f = document.forms, i, a; + + for (i=0; i<f.length; i++) { + for (a=0; a<f[i].elements.length; a++) { + if (f[i].elements[a].disabled) + tinyMCEPopup.editor.dom.addClass(f[i].elements[a], "disabled"); + else + tinyMCEPopup.editor.dom.removeClass(f[i].elements[a], "disabled"); + } + } +} + +function fillSelect(f, s, param, dval, sep, em) { + var i, ar, p, se; + + f = document.forms[f]; + sep = typeof(sep) == "undefined" ? ";" : sep; + + if (em) + addSelectValue(f, s, "", ""); + + ar = tinyMCEPopup.getParam(param, dval).split(sep); + for (i=0; i<ar.length; i++) { + se = false; + + if (ar[i].charAt(0) == '+') { + ar[i] = ar[i].substring(1); + se = true; + } + + p = ar[i].split('='); + + if (p.length > 1) { + addSelectValue(f, s, p[0], p[1]); + + if (se) + selectByValue(f, s, p[1]); + } else { + addSelectValue(f, s, p[0], p[0]); + + if (se) + selectByValue(f, s, p[0]); + } + } +} + +function toggleSame(ce, pre) { + var el = document.forms[0].elements, i; + + if (ce.checked) { + el[pre + "_top"].disabled = false; + el[pre + "_right"].disabled = true; + el[pre + "_bottom"].disabled = true; + el[pre + "_left"].disabled = true; + + if (el[pre + "_top_measurement"]) { + el[pre + "_top_measurement"].disabled = false; + el[pre + "_right_measurement"].disabled = true; + el[pre + "_bottom_measurement"].disabled = true; + el[pre + "_left_measurement"].disabled = true; + } + } else { + el[pre + "_top"].disabled = false; + el[pre + "_right"].disabled = false; + el[pre + "_bottom"].disabled = false; + el[pre + "_left"].disabled = false; + + if (el[pre + "_top_measurement"]) { + el[pre + "_top_measurement"].disabled = false; + el[pre + "_right_measurement"].disabled = false; + el[pre + "_bottom_measurement"].disabled = false; + el[pre + "_left_measurement"].disabled = false; + } + } + + showDisabledControls(); +} + +function synch(fr, to) { + var f = document.forms[0]; + + f.elements[to].value = f.elements[fr].value; + + if (f.elements[fr + "_measurement"]) + selectByValue(f, to + "_measurement", f.elements[fr + "_measurement"].value); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/plugins/style/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/style/langs/de_dlg.js new file mode 100755 index 0000000..ad04664 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/style/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.style_dlg',{"text_lineheight":"Zeilenh\u00f6he","text_variant":"Variante","text_style":"Stil","text_weight":"Dicke","text_size":"Gr\u00f6\u00dfe","text_font":"Schriftart","text_props":"Text","positioning_tab":"Positionierung","list_tab":"Liste","border_tab":"Rahmen","box_tab":"Box","block_tab":"Block","background_tab":"Hintergrund","text_tab":"Text",apply:"\u00dcbernehmen",title:"CSS-Styles bearbeiten",clip:"Ausschnitt",placement:"Platzierung",overflow:"Verhalten bei \u00dcbergr\u00f6\u00dfe",zindex:"Z-Wert",visibility:"Sichtbar","positioning_type":"Art der Positionierung",position:"Positionierung","bullet_image":"Listenpunkt-Grafik","list_type":"Listenpunkt-Art",color:"Textfarbe",height:"H\u00f6he",width:"Breite",style:"Format",margin:"\u00c4u\u00dferer Abstand",left:"Links",bottom:"Unten",right:"Rechts",top:"Oben",same:"Alle gleich",padding:"Innerer Abstand","box_clear":"Umflie\u00dfung verhindern","box_float":"Umflie\u00dfung","box_height":"H\u00f6he","box_width":"Breite","block_display":"Umbruchverhalten","block_whitespace":"Automatischer Umbruch","block_text_indent":"Einr\u00fcckung","block_text_align":"Ausrichtung","block_vertical_alignment":"Vertikale Ausrichtung","block_letterspacing":"Buchstabenabstand","block_wordspacing":"Wortabstand","background_vpos":"Position Y","background_hpos":"Position X","background_attachment":"Wasserzeicheneffekt","background_repeat":"Wiederholung","background_image":"Hintergrundbild","background_color":"Hintergrundfarbe","text_none":"keine","text_blink":"blinkend","text_case":"Schreibung","text_striketrough":"durchgestrichen","text_underline":"unterstrichen","text_overline":"\u00fcberstrichen","text_decoration":"Gestaltung","text_color":"Farbe",text:"Text",background:"Hintergrund",block:"Block",box:"Box",border:"Rahmen",list:"Liste"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/style/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/style/langs/en_dlg.js new file mode 100755 index 0000000..9a1d4a2 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/style/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.style_dlg',{"text_lineheight":"Line Height","text_variant":"Variant","text_style":"Style","text_weight":"Weight","text_size":"Size","text_font":"Font","text_props":"Text","positioning_tab":"Positioning","list_tab":"List","border_tab":"Border","box_tab":"Box","block_tab":"Block","background_tab":"Background","text_tab":"Text",apply:"Apply",title:"Edit CSS Style",clip:"Clip",placement:"Placement",overflow:"Overflow",zindex:"Z-index",visibility:"Visibility","positioning_type":"Type",position:"Position","bullet_image":"Bullet Image","list_type":"Type",color:"Color",height:"Height",width:"Width",style:"Style",margin:"Margin",left:"Left",bottom:"Bottom",right:"Right",top:"Top",same:"Same for All",padding:"Padding","box_clear":"Clear","box_float":"Float","box_height":"Height","box_width":"Width","block_display":"Display","block_whitespace":"Whitespace","block_text_indent":"Text Indent","block_text_align":"Text Align","block_vertical_alignment":"Vertical Alignment","block_letterspacing":"Letter Spacing","block_wordspacing":"Word Spacing","background_vpos":"Vertical Position","background_hpos":"Horizontal Position","background_attachment":"Attachment","background_repeat":"Repeat","background_image":"Background Image","background_color":"Background Color","text_none":"None","text_blink":"Blink","text_case":"Case","text_striketrough":"Strikethrough","text_underline":"Underline","text_overline":"Overline","text_decoration":"Decoration","text_color":"Color",text:"Text",background:"Background",block:"Block",box:"Box",border:"Border",list:"List"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/style/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/style/langs/fr_dlg.js new file mode 100755 index 0000000..8ab5e6c --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/style/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.style_dlg',{"text_lineheight":"Hauteur de ligne","text_variant":"Variante","text_style":"Style","text_weight":"Gras","text_size":"Taille","text_font":"Police","text_props":"Texte","positioning_tab":"Positionnement","list_tab":"Liste","border_tab":"Bordure","box_tab":"Bo\u00eete","block_tab":"Bloc","background_tab":"Fond","text_tab":"Texte",apply:"Appliquer",title:"\u00c9diter la feuille de style",clip:"Clip",placement:"Placement",overflow:"D\u00e9bordement",zindex:"Z-index",visibility:"Visibilit\u00e9","positioning_type":"Type",position:"Position","bullet_image":"Image de puce","list_type":"Type",color:"Couleur",height:"Hauteur",width:"Largeur",style:"Style",margin:"Marge",left:"Gauche",bottom:"Bas",right:"Droit",top:"Haut",same:"Identique pour tous",padding:"Espacement","box_clear":"Vider","box_float":"Flottant","box_height":"Hauteur","box_width":"Largeur","block_display":"Affichage","block_whitespace":"Fin de ligne","block_text_indent":"Indentation du texte","block_text_align":"Alignement du texte","block_vertical_alignment":"Alignement vertical","block_letterspacing":"Espacement des lettres","block_wordspacing":"Espacement des mots ","background_vpos":"Position verticale","background_hpos":"Position horizontale","background_attachment":"Attachement","background_repeat":"R\u00e9p\u00e9ter","background_image":"Image de fond","background_color":"Couleur de fond","text_none":"aucun","text_blink":"clignotant","text_case":"Casse","text_striketrough":"barr\u00e9","text_underline":"soulign\u00e9","text_overline":"ligne au-dessus","text_decoration":"D\u00e9coration","text_color":"Couleur",text:"Text",background:"Background",block:"Block",box:"Box",border:"Border",list:"List"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/style/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/style/langs/it_dlg.js new file mode 100755 index 0000000..3ffc088 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/style/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.style_dlg',{"text_lineheight":"Altezza linea","text_variant":"Variante","text_style":"Stile","text_weight":"Spessore","text_size":"Dimensione","text_font":"Carattere","text_props":"Testo","positioning_tab":"Posizionamento","list_tab":"Liste","border_tab":"Bordi","box_tab":"Contenitore","block_tab":"Blocco","background_tab":"Sfondo","text_tab":"Testo",apply:"Applica",title:"Modifica stile CSS",clip:"Clip",placement:"Piazzamento",overflow:"Overflow",zindex:"Z-index",visibility:"Visibilit\u00e0","positioning_type":"Tipo",position:"Posizione","bullet_image":"Immagine Punto","list_type":"Tipo",color:"Colore",height:"Altezza",width:"Larghezza",style:"Stile",margin:"Margine",left:"Sinistro",bottom:"Inferiore",right:"Destro",top:"Superiore",same:"Uguale per tutti",padding:"Spazio dal bordo","box_clear":"Pulito","box_float":"Fluttuante","box_height":"Altezza","box_width":"Larghezza","block_display":"Visualizzazione","block_whitespace":"Whitespace","block_text_indent":"Indentazione testo","block_text_align":"Allineamento testo","block_vertical_alignment":"Allineamento verticale","block_letterspacing":"Spaziatura caratteri","block_wordspacing":"Spaziatura parole","background_vpos":"Posizione verticale","background_hpos":"Posizione orizzontale","background_attachment":"Allegato","background_repeat":"Repetizione","background_image":"Immagine sfondo","background_color":"Colore sfondo","text_none":"nessuna","text_blink":"lampeggiante","text_case":"Tipo","text_striketrough":"barrato","text_underline":"sottolineato","text_overline":"sopralineato","text_decoration":"Decorazione","text_color":"Colore",text:"Text",background:"Background",block:"Block",box:"Box",border:"Border",list:"List"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/style/props.htm b/src/core/static/js/tiny_mce/plugins/style/props.htm new file mode 100644 index 0000000..76ab68d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/style/props.htm @@ -0,0 +1,840 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#style_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="js/props.js"></script> + <link href="css/props.css" rel="stylesheet" type="text/css" /> +</head> + +<body id="styleprops" style="display: none" role="application" aria-labelledby="app_title"> +<span id="app_title" style="display:none">{#style_dlg.title}</span> +<form onsubmit="updateAction();return false;" action="#"> +<div class="tabs"> + <ul> + <li id="text_tab" class="current" aria-controls="text_panel"><span><a href="javascript:mcTabs.displayTab('text_tab','text_panel');" onMouseDown="return false;">{#style_dlg.text_tab}</a></span></li> + <li id="background_tab" aria-controls="background_panel"><span><a href="javascript:mcTabs.displayTab('background_tab','background_panel');" onMouseDown="return false;">{#style_dlg.background_tab}</a></span></li> + <li id="block_tab" aria-controls="block_panel"><span><a href="javascript:mcTabs.displayTab('block_tab','block_panel');" onMouseDown="return false;">{#style_dlg.block_tab}</a></span></li> + <li id="box_tab" aria-controls="box_panel"><span><a href="javascript:mcTabs.displayTab('box_tab','box_panel');" onMouseDown="return false;">{#style_dlg.box_tab}</a></span></li> + <li id="border_tab" aria-controls="border_panel"><span><a href="javascript:mcTabs.displayTab('border_tab','border_panel');" onMouseDown="return false;">{#style_dlg.border_tab}</a></span></li> + <li id="list_tab" aria-controls="list_panel"><span><a href="javascript:mcTabs.displayTab('list_tab','list_panel');" onMouseDown="return false;">{#style_dlg.list_tab}</a></span></li> + <li id="positioning_tab" aria-controls="positioning_panel"><span><a href="javascript:mcTabs.displayTab('positioning_tab','positioning_panel');" onMouseDown="return false;">{#style_dlg.positioning_tab}</a></span></li> + </ul> +</div> + +<div class="panel_wrapper"> +<div id="text_panel" class="panel current"> + <fieldset> + <legend>{#style_dlg.text}</legend> + <table role="presentation" border="0" width="100%"> + <tr> + <td><label for="text_font">{#style_dlg.text_font}</label></td> + <td colspan="3"> + <select id="text_font" name="text_font" class="mceEditableSelect mceFocus"></select> + </td> + </tr> + <tr> + <td><label for="text_size">{#style_dlg.text_size}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="text_size" name="text_size" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + <label id="text_size_measurement_label" for="text_size_measurement" style="display: none; visibility: hidden;">Text Size Measurement Unit</label> + <select id="text_size_measurement" name="text_size_measurement" aria-labelledby="text_size_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td><label for="text_weight">{#style_dlg.text_weight}</label></td> + <td> + <select id="text_weight" name="text_weight"></select> + </td> + </tr> + <tr> + <td><label for="text_style">{#style_dlg.text_style}</label></td> + <td> + <select id="text_style" name="text_style" class="mceEditableSelect"></select> + </td> + <td><label for="text_variant">{#style_dlg.text_variant}</label></td> + <td> + <select id="text_variant" name="text_variant"></select> + </td> + </tr> + <tr> + <td><label for="text_lineheight">{#style_dlg.text_lineheight}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td> + <select id="text_lineheight" name="text_lineheight" class="mceEditableSelect"></select> + </td> + <td>&nbsp;</td> + <td> + <label id="text_lineheight_measurement_label" for="text_lineheight_measurement" style="display: none; visibility: hidden;">Line Height Measurement Unit</label> + <select id="text_lineheight_measurement" name="text_lineheight_measurement" aria-labelledby="text_lineheight_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td><label for="text_case">{#style_dlg.text_case}</label></td> + <td> + <select id="text_case" name="text_case"></select> + </td> + </tr> + <tr> + <td><label for="text_color">{#style_dlg.text_color}</label></td> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="text_color" name="text_color" type="text" value="" size="9" onChange="updateColor('text_color_pick','text_color');" /></td> + <td id="text_color_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + <tr> + <td valign="top" style="vertical-align: top; padding-top: 3px;">{#style_dlg.text_decoration}</td> + <td colspan="2"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="text_underline" name="text_underline" class="checkbox" type="checkbox" /></td> + <td><label for="text_underline">{#style_dlg.text_underline}</label></td> + </tr> + <tr> + <td><input id="text_overline" name="text_overline" class="checkbox" type="checkbox" /></td> + <td><label for="text_overline">{#style_dlg.text_overline}</label></td> + </tr> + <tr> + <td><input id="text_linethrough" name="text_linethrough" class="checkbox" type="checkbox" /></td> + <td><label for="text_linethrough">{#style_dlg.text_striketrough}</label></td> + </tr> + <tr> + <td><input id="text_blink" name="text_blink" class="checkbox" type="checkbox" /></td> + <td><label for="text_blink">{#style_dlg.text_blink}</label></td> + </tr> + <tr> + <td><input id="text_none" name="text_none" class="checkbox" type="checkbox" /></td> + <td><label for="text_none">{#style_dlg.text_none}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> + +<div id="background_panel" class="panel"> + <fieldset> + <legend>{#style_dlg.background}</legend> + <table role="presentation" border="0"> + <tr> + <td><label for="background_color">{#style_dlg.background_color}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="background_color" name="background_color" type="text" value="" size="9" onChange="updateColor('background_color_pick','background_color');" /></td> + <td id="background_color_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="background_image">{#style_dlg.background_image}</label></td> + <td><table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="background_image" name="background_image" type="text" /></td> + <td id="background_image_browser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="background_repeat">{#style_dlg.background_repeat}</label></td> + <td><select id="background_repeat" name="background_repeat" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="background_attachment">{#style_dlg.background_attachment}</label></td> + <td><select id="background_attachment" name="background_attachment" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="background_hpos">{#style_dlg.background_hpos}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="background_hpos" name="background_hpos" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + <label id="background_hpos_measurement_label" for="background_hpos_measurement" style="display: none; visibility: hidden;">Horizontal position measurement unit</label> + <select id="background_hpos_measurement" name="background_hpos_measurement" aria-labelledby="background_hpos_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="background_vpos">{#style_dlg.background_vpos}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="background_vpos" name="background_vpos" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + + <label id="background_vpos_measurement_label" for="background_vpos_measurement" style="display: none; visibility: hidden;">Vertical position measurement unit</label> + <select id="background_vpos_measurement" name="background_vpos_measurement" aria-labelledby="background_vpos_measurement_label">></select></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> + +<div id="block_panel" class="panel"> + <fieldset> + <legend>{#style_dlg.block}</legend> + <table role="presentation" border="0"> + <tr> + <td><label for="block_wordspacing">{#style_dlg.block_wordspacing}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="block_wordspacing" name="block_wordspacing" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + <label id="block_wordspacing_measurement_label" for="block_wordspacing_measurement" style="display: none; visibility: hidden;">Word spacing measurement unit</label> + <select id="block_wordspacing_measurement" name="block_wordspacing_measurement" aria-labelledby="block_wordspacing_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="block_letterspacing">{#style_dlg.block_letterspacing}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="block_letterspacing" name="block_letterspacing" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + <label id="block_letterspacing_measurement_label" for="block_letterspacing_measurement" style="display: none; visibility: hidden;">Letter spacing measurement unit</label> + <select id="block_letterspacing_measurement" name="block_letterspacing_measurement" aria-labelledby="block_letterspacing_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="block_vertical_alignment">{#style_dlg.block_vertical_alignment}</label></td> + <td><select id="block_vertical_alignment" name="block_vertical_alignment" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="block_text_align">{#style_dlg.block_text_align}</label></td> + <td><select id="block_text_align" name="block_text_align" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="block_text_indent">{#style_dlg.block_text_indent}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="block_text_indent" name="block_text_indent" /></td> + <td>&nbsp;</td> + <td> + <label id="block_text_indent_measurement_label" for="block_text_indent_measurement" style="display: none; visibility: hidden;">Text Indent Measurement Unit</label> + + <select id="block_text_indent_measurement" name="block_text_indent_measurement" aria-labelledby="block_text_indent_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="block_whitespace">{#style_dlg.block_whitespace}</label></td> + <td><select id="block_whitespace" name="block_whitespace" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="block_display">{#style_dlg.block_display}</label></td> + <td><select id="block_display" name="block_display" class="mceEditableSelect"></select></td> + </tr> + </table> + </fieldset> +</div> + +<div id="box_panel" class="panel"> + <fieldset> + <legend>{#style_dlg.box}</legend> + <table role="presentation" border="0"> + <tr> + <td><label for="box_width">{#style_dlg.box_width}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_width" name="box_width" class="mceEditableSelect" onChange="synch('box_width','positioning_width');" /></td> + <td>&nbsp;</td> + <td> + <label id="box_width_measurement_label" for="box_width_measurement" style="display: none; visibility: hidden;">Box Width Measurement Unit</label> + <select id="box_width_measurement" name="box_width_measurement" aria-labelledby="box_width_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td>&nbsp;&nbsp;&nbsp;<label for="box_float">{#style_dlg.box_float}</label></td> + <td><select id="box_float" name="box_float" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="box_height">{#style_dlg.box_height}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_height" name="box_height" class="mceEditableSelect" onChange="synch('box_height','positioning_height');" /></td> + <td>&nbsp;</td> + <td> + <label id="box_height_measurement_label" for="box_height_measurement" style="display: none; visibility: hidden;">Box Height Measurement Unit</label> + <select id="box_height_measurement" name="box_height_measurement" aria-labelledby="box_height_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td>&nbsp;&nbsp;&nbsp;<label for="box_clear">{#style_dlg.box_clear}</label></td> + <td><select id="box_clear" name="box_clear" class="mceEditableSelect"></select></td> + </tr> + </table> + </fieldset> + +<div style="float: left; width: 49%"> + <fieldset> + <legend>{#style_dlg.padding}</legend> + + <table role="presentation" border="0"> + <tr> + <td>&nbsp;</td> + <td><input type="checkbox" id="box_padding_same" name="box_padding_same" class="checkbox" checked="checked" onClick="toggleSame(this,'box_padding');" /> <label for="box_padding_same">{#style_dlg.same}</label></td> + </tr> + <tr> + <td><label for="box_padding_top">{#style_dlg.top}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_padding_top" name="box_padding_top" class="mceEditableSelect" /></td> + <td>&nbsp;</td> + <td> + <label id="box_padding_top_measurement_label" for="box_padding_top_measurement" style="display: none; visibility: hidden;">Padding Top Measurement Unit</label> + <select id="box_padding_top_measurement" name="box_padding_top_measurement" aria-labelledby="box_padding_top_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_padding_right">{#style_dlg.right}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_padding_right" name="box_padding_right" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_padding_right_measurement_label" for="box_padding_right_measurement" style="display: none; visibility: hidden;">Padding Right Measurement Unit</label> + <select id="box_padding_right_measurement" name="box_padding_right_measurement" disabled="disabled" aria-labelledby="box_padding_right_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_padding_bottom">{#style_dlg.bottom}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_padding_bottom" name="box_padding_bottom" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_padding_bottom_measurement_label" for="box_padding_bottom_measurement" style="display: none; visibility: hidden;">Padding Bottom Measurement Unit</label> + <select id="box_padding_bottom_measurement" name="box_padding_bottom_measurement" disabled="disabled" aria-labelledby="box_padding_bottom_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_padding_left">{#style_dlg.left}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_padding_left" name="box_padding_left" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_padding_left_measurement_label" for="box_padding_left_measurement" style="display: none; visibility: hidden;">Padding Left Measurement Unit</label> + <select id="box_padding_left_measurement" name="box_padding_left_measurement" disabled="disabled" aria-labelledby="box_padding_left_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> + +<div style="float: right; width: 49%"> + <fieldset> + <legend>{#style_dlg.margin}</legend> + + <table role="presentation" border="0"> + <tr> + <td>&nbsp;</td> + <td><input type="checkbox" id="box_margin_same" name="box_margin_same" class="checkbox" checked="checked" onClick="toggleSame(this,'box_margin');" /> <label for="box_margin_same">{#style_dlg.same}</label></td> + </tr> + <tr> + <td><label for="box_margin_top">{#style_dlg.top}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_margin_top" name="box_margin_top" class="mceEditableSelect" /></td> + <td>&nbsp;</td> + <td> + <label id="box_margin_top_measurement_label" for="box_margin_top_measurement" style="display: none; visibility: hidden;">Margin Top Measurement Unit</label> + <select id="box_margin_top_measurement" name="box_margin_top_measurement" aria-labelledby="box_margin_top_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_margin_right">{#style_dlg.right}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_margin_right" name="box_margin_right" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_margin_right_measurement_label" for="box_margin_right_measurement" style="display: none; visibility: hidden;">Margin Right Measurement Unit</label> + <select id="box_margin_right_measurement" name="box_margin_right_measurement" disabled="disabled" aria-labelledby="box_margin_right_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_margin_bottom">{#style_dlg.bottom}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_margin_bottom" name="box_margin_bottom" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_margin_bottom_measurement_label" for="box_margin_bottom_measurement" style="display: none; visibility: hidden;">Margin Bottom Measurement Unit</label> + <select id="box_margin_bottom_measurement" name="box_margin_bottom_measurement" disabled="disabled" aria-labelledby="box_margin_bottom_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_margin_left">{#style_dlg.left}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_margin_left" name="box_margin_left" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_margin_left_measurement_label" for="box_margin_left_measurement" style="display: none; visibility: hidden;">Margin Left Measurement Unit</label> + <select id="box_margin_left_measurement" name="box_margin_left_measurement" disabled="disabled" aria-labelledby="box_margin_left_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> +<br style="clear: both" /> +</div> + +<div id="border_panel" class="panel"> + <fieldset> + <legend>{#style_dlg.border}</legend> + <table role="presentation" border="0" cellspacing="0" cellpadding="0" width="100%"> + <tr> + <td class="tdelim">&nbsp;</td> + <td class="tdelim delim">&nbsp;</td> + <td class="tdelim">{#style_dlg.style}</td> + <td class="tdelim delim">&nbsp;</td> + <td class="tdelim">{#style_dlg.width}</td> + <td class="tdelim delim">&nbsp;</td> + <td class="tdelim">{#style_dlg.color}</td> + </tr> + + <tr> + <td>&nbsp;</td> + <td class="delim">&nbsp;</td> + <td><input type="checkbox" id="border_style_same" name="border_style_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_style');" /> <label for="border_style_same">{#style_dlg.same}</label></td> + <td class="delim">&nbsp;</td> + <td><input type="checkbox" id="border_width_same" name="border_width_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_width');" /> <label for="border_width_same">{#style_dlg.same}</label></td> + <td class="delim">&nbsp;</td> + <td><input type="checkbox" id="border_color_same" name="border_color_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_color');" /> <label for="border_color_same">{#style_dlg.same}</label></td> + </tr> + + <tr> + <td>{#style_dlg.top}</td> + <td class="delim">&nbsp;</td> + <td><select id="border_style_top" name="border_style_top" class="mceEditableSelect"></select></td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="border_width_top" name="border_width_top" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + <label id="border_width_top_measurement_label" for="border_width_top_measurement" style="display: none; visibility: hidden;">Width top Measurement Unit</label> + <select id="border_width_top_measurement" name="border_width_top_measurement" aria-labelledby="border_width_top_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="border_color_top" name="border_color_top" type="text" value="" size="9" onChange="updateColor('border_color_top_pick','border_color_top');" /></td> + <td id="border_color_top_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td>{#style_dlg.right}</td> + <td class="delim">&nbsp;</td> + <td><select id="border_style_right" name="border_style_right" class="mceEditableSelect" disabled="disabled"></select></td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="border_width_right" name="border_width_right" class="mceEditableSelect" disabled="disabled"></select></td> + <td>&nbsp;</td> + <td> + <label id="border_width_right_measurement_label" for="border_width_right_measurement" style="display: none; visibility: hidden;">Width Right Measurement Unit</label> + <select id="border_width_right_measurement" name="border_width_right_measurement" disabled="disabled" aria-labelledby="border_width_right_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="border_color_right" name="border_color_right" type="text" value="" size="9" onChange="updateColor('border_color_right_pick','border_color_right');" disabled="disabled" /></td> + <td id="border_color_right_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td>{#style_dlg.bottom}</td> + <td class="delim">&nbsp;</td> + <td><select id="border_style_bottom" name="border_style_bottom" class="mceEditableSelect" disabled="disabled"></select></td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="border_width_bottom" name="border_width_bottom" class="mceEditableSelect" disabled="disabled"></select></td> + <td>&nbsp;</td> + <td> + <label id="border_width_bottom_measurement_label" for="border_width_bottom_measurement" style="display: none; visibility: hidden;">Width Bottom Measurement Unit</label> + <select id="border_width_bottom_measurement" name="border_width_bottom_measurement" disabled="disabled" aria-labelledby="border_width_bottom_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="border_color_bottom" name="border_color_bottom" type="text" value="" size="9" onChange="updateColor('border_color_bottom_pick','border_color_bottom');" disabled="disabled" /></td> + <td id="border_color_bottom_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td>{#style_dlg.left}</td> + <td class="delim">&nbsp;</td> + <td><select id="border_style_left" name="border_style_left" class="mceEditableSelect" disabled="disabled"></select></td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="border_width_left" name="border_width_left" class="mceEditableSelect" disabled="disabled"></select></td> + <td>&nbsp;</td> + <td> + <label id="border_width_left_measurement_label" for="border_width_left_measurement" style="display: none; visibility: hidden;">Width Left Measurement Unit</label> + <select id="border_width_left_measurement" name="border_width_left_measurement" disabled="disabled" aria-labelledby="border_width_left_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="border_color_left" name="border_color_left" type="text" value="" size="9" onChange="updateColor('border_color_left_pick','border_color_left');" disabled="disabled" /></td> + <td id="border_color_left_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> + +<div id="list_panel" class="panel"> +<fieldset> + <legend>{#style_dlg.list}</legend> + <table role="presentation" border="0"> + <tr> + <td><label for="list_type">{#style_dlg.list_type}</label></td> + <td><select id="list_type" name="list_type" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="list_bullet_image">{#style_dlg.bullet_image}</label></td> + <td><input id="list_bullet_image" name="list_bullet_image" type="text" /></td> + </tr> + + <tr> + <td><label for="list_position">{#style_dlg.position}</label></td> + <td><select id="list_position" name="list_position" class="mceEditableSelect"></select></td> + </tr> + </table> +</fieldset> +</div> + +<div id="positioning_panel" class="panel"> +<fieldset> + <legend>{#style_dlg.position}</legend> +<table role="presentation" border="0"> + <tr> + <td><label for="positioning_type">{#style_dlg.positioning_type}</label></td> + <td><select id="positioning_type" name="positioning_type" class="mceEditableSelect"></select></td> + <td>&nbsp;&nbsp;&nbsp;<label for="positioning_visibility">{#style_dlg.visibility}</label></td> + <td><select id="positioning_visibility" name="positioning_visibility" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="positioning_width">{#style_dlg.width}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_width" name="positioning_width" onChange="synch('positioning_width','box_width');" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_width_measurement_label" for="positioning_width_measurement" style="display: none; visibility: hidden;">Positioning width Measurement Unit</label> + <select id="positioning_width_measurement" name="positioning_width_measurement" aria-labelledby="positioning_width_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td>&nbsp;&nbsp;&nbsp;<label for="positioning_zindex">{#style_dlg.zindex}</label></td> + <td><input type="text" id="positioning_zindex" name="positioning_zindex" /></td> + </tr> + + <tr> + <td><label for="positioning_height">{#style_dlg.height}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_height" name="positioning_height" onChange="synch('positioning_height','box_height');" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_height_measurement_label" for="positioning_height_measurement" style="display: none; visibility: hidden;">Positioning Height Measurement Unit</label> + <select id="positioning_height_measurement" name="positioning_height_measurement" aria-labelledby="positioning_height_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td>&nbsp;&nbsp;&nbsp;<label for="positioning_overflow">{#style_dlg.overflow}</label></td> + <td><select id="positioning_overflow" name="positioning_overflow" class="mceEditableSelect"></select></td> + </tr> +</table> +</fieldset> + +<div style="float: left; width: 49%"> + <fieldset> + <legend>{#style_dlg.placement}</legend> + + <table role="presentation" border="0"> + <tr> + <td>&nbsp;</td> + <td><input type="checkbox" id="positioning_placement_same" name="positioning_placement_same" class="checkbox" checked="checked" onClick="toggleSame(this,'positioning_placement');" /> <label for="positioning_placement_same">{#style_dlg.same}</label></td> + </tr> + <tr> + <td>{#style_dlg.top}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_placement_top" name="positioning_placement_top" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_placement_top_measurement_label" for="positioning_placement_top_measurement" style="display: none; visibility: hidden;">Placement Top Measurement Unit</label> + <select id="positioning_placement_top_measurement" name="positioning_placement_top_measurement" aria-labelledby="positioning_placement_top_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.right}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_placement_right" name="positioning_placement_right" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_placement_right_measurement_label" for="positioning_placement_right_measurement" style="display: none; visibility: hidden;">Placement Right Measurement Unit</label> + <select id="positioning_placement_right_measurement" name="positioning_placement_right_measurement" disabled="disabled" aria-labelledby="positioning_placement_right_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.bottom}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_placement_bottom" name="positioning_placement_bottom" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_placement_bottom_measurement_label" for="positioning_placement_bottom_measurement" style="display: none; visibility: hidden;">Placement Bottom Measurement Unit</label> + <select id="positioning_placement_bottom_measurement" name="positioning_placement_bottom_measurement" disabled="disabled" aria-labelledby="positioning_placement_bottom_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.left}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_placement_left" name="positioning_placement_left" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_placement_left_measurement_label" for="positioning_placement_left_measurement" style="display: none; visibility: hidden;">Placement Left Measurement Unit</label> + <select id="positioning_placement_left_measurement" name="positioning_placement_left_measurement" disabled="disabled" aria-labelledby="positioning_placement_left_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> + +<div style="float: right; width: 49%"> + <fieldset> + <legend>{#style_dlg.clip}</legend> + + <table role="presentation" border="0"> + <tr> + <td>&nbsp;</td> + <td><input type="checkbox" id="positioning_clip_same" name="positioning_clip_same" class="checkbox" checked="checked" onClick="toggleSame(this,'positioning_clip');" /> <label for="positioning_clip_same">{#style_dlg.same}</label></td> + </tr> + <tr> + <td>{#style_dlg.top}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_clip_top" name="positioning_clip_top" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_clip_top_measurement_label" for="positioning_clip_top_measurement" style="display: none; visibility: hidden;">Clip Top Measurement Unit</label> + <select id="positioning_clip_top_measurement" name="positioning_clip_top_measurement" aria-labelledby="positioning_clip_top_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.right}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_clip_right" name="positioning_clip_right" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_clip_right_measurement_label" for="positioning_clip_right_measurement" style="display: none; visibility: hidden;">Clip Right Measurement Unit</label> + <select id="positioning_clip_right_measurement" name="positioning_clip_right_measurement" disabled="disabled" aria-labelledby="positioning_clip_right_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.bottom}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_clip_bottom" name="positioning_clip_bottom" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_clip_bottom_measurement_label" for="positioning_clip_bottom_measurement" style="display: none; visibility: hidden;">Clip Bottom Measurement Unit</label> + <select id="positioning_clip_bottom_measurement" name="positioning_clip_bottom_measurement" disabled="disabled" aria-labelledby="positioning_clip_bottom_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.left}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_clip_left" name="positioning_clip_left" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_clip_left_measurement_label" for="positioning_clip_left_measurement" style="display: none; visibility: hidden;">Clip Left Measurement Unit</label> + <select id="positioning_clip_left_measurement" name="positioning_clip_left_measurement" disabled="disabled" aria-labelledby="positioning_clip_left_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> +<br style="clear: both" /> +</div> +</div> + +<div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" class="button" id="apply" name="apply" value="{#style_dlg.apply}" onClick="applyAction();" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onClick="tinyMCEPopup.close();" /> +</div> +</form> + +<div style="display: none"> + <div id="container"></div> +</div> + +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/tabfocus/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/tabfocus/editor_plugin.js new file mode 100644 index 0000000..42a82d1 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/tabfocus/editor_plugin.js @@ -0,0 +1 @@ +(function(){var c=tinymce.DOM,a=tinymce.dom.Event,d=tinymce.each,b=tinymce.explode;tinymce.create("tinymce.plugins.TabFocusPlugin",{init:function(f,g){function e(i,j){if(j.keyCode===9){return a.cancel(j)}}function h(l,p){var j,m,o,n,k;function q(t){n=c.select(":input:enabled,*[tabindex]");function s(v){return v.nodeName==="BODY"||(v.type!="hidden"&&!(v.style.display=="none")&&!(v.style.visibility=="hidden")&&s(v.parentNode))}function i(v){return v.attributes.tabIndex.specified||v.nodeName=="INPUT"||v.nodeName=="TEXTAREA"}function u(){return tinymce.isIE6||tinymce.isIE7}function r(v){return((!u()||i(v)))&&v.getAttribute("tabindex")!="-1"&&s(v)}d(n,function(w,v){if(w.id==l.id){j=v;return false}});if(t>0){for(m=j+1;m<n.length;m++){if(r(n[m])){return n[m]}}}else{for(m=j-1;m>=0;m--){if(r(n[m])){return n[m]}}}return null}if(p.keyCode===9){k=b(l.getParam("tab_focus",l.getParam("tabfocus_elements",":prev,:next")));if(k.length==1){k[1]=k[0];k[0]=":prev"}if(p.shiftKey){if(k[0]==":prev"){n=q(-1)}else{n=c.get(k[0])}}else{if(k[1]==":next"){n=q(1)}else{n=c.get(k[1])}}if(n){if(n.id&&(l=tinymce.get(n.id||n.name))){l.focus()}else{window.setTimeout(function(){if(!tinymce.isWebKit){window.focus()}n.focus()},10)}return a.cancel(p)}}}f.onKeyUp.add(e);if(tinymce.isGecko){f.onKeyPress.add(h);f.onKeyDown.add(e)}else{f.onKeyDown.add(h)}},getInfo:function(){return{longname:"Tabfocus",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/tabfocus",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("tabfocus",tinymce.plugins.TabFocusPlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/tabfocus/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/tabfocus/editor_plugin_src.js new file mode 100644 index 0000000..a1579c8 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/tabfocus/editor_plugin_src.js @@ -0,0 +1,122 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, explode = tinymce.explode; + + tinymce.create('tinymce.plugins.TabFocusPlugin', { + init : function(ed, url) { + function tabCancel(ed, e) { + if (e.keyCode === 9) + return Event.cancel(e); + } + + function tabHandler(ed, e) { + var x, i, f, el, v; + + function find(d) { + el = DOM.select(':input:enabled,*[tabindex]'); + + function canSelectRecursive(e) { + return e.nodeName==="BODY" || (e.type != 'hidden' && + !(e.style.display == "none") && + !(e.style.visibility == "hidden") && canSelectRecursive(e.parentNode)); + } + function canSelectInOldIe(el) { + return el.attributes["tabIndex"].specified || el.nodeName == "INPUT" || el.nodeName == "TEXTAREA"; + } + function isOldIe() { + return tinymce.isIE6 || tinymce.isIE7; + } + function canSelect(el) { + return ((!isOldIe() || canSelectInOldIe(el))) && el.getAttribute("tabindex") != '-1' && canSelectRecursive(el); + } + + each(el, function(e, i) { + if (e.id == ed.id) { + x = i; + return false; + } + }); + if (d > 0) { + for (i = x + 1; i < el.length; i++) { + if (canSelect(el[i])) + return el[i]; + } + } else { + for (i = x - 1; i >= 0; i--) { + if (canSelect(el[i])) + return el[i]; + } + } + + return null; + } + + if (e.keyCode === 9) { + v = explode(ed.getParam('tab_focus', ed.getParam('tabfocus_elements', ':prev,:next'))); + + if (v.length == 1) { + v[1] = v[0]; + v[0] = ':prev'; + } + + // Find element to focus + if (e.shiftKey) { + if (v[0] == ':prev') + el = find(-1); + else + el = DOM.get(v[0]); + } else { + if (v[1] == ':next') + el = find(1); + else + el = DOM.get(v[1]); + } + + if (el) { + if (el.id && (ed = tinymce.get(el.id || el.name))) + ed.focus(); + else + window.setTimeout(function() { + if (!tinymce.isWebKit) + window.focus(); + el.focus(); + }, 10); + + return Event.cancel(e); + } + } + } + + ed.onKeyUp.add(tabCancel); + + if (tinymce.isGecko) { + ed.onKeyPress.add(tabHandler); + ed.onKeyDown.add(tabCancel); + } else + ed.onKeyDown.add(tabHandler); + + }, + + getInfo : function() { + return { + longname : 'Tabfocus', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/tabfocus', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('tabfocus', tinymce.plugins.TabFocusPlugin); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/table/cell.htm b/src/core/static/js/tiny_mce/plugins/table/cell.htm new file mode 100644 index 0000000..a72a8d6 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/cell.htm @@ -0,0 +1,180 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#table_dlg.cell_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/cell.js"></script> + <link href="css/cell.css" rel="stylesheet" type="text/css" /> +</head> +<body id="tablecell" style="display: none" role="application"> + <form onsubmit="updateAction();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#table_dlg.general_props}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td><label for="align">{#table_dlg.align}</label></td> + <td> + <select id="align" name="align" class="mceFocus"> + <option value="">{#not_set}</option> + <option value="center">{#table_dlg.align_middle}</option> + <option value="left">{#table_dlg.align_left}</option> + <option value="right">{#table_dlg.align_right}</option> + </select> + </td> + + <td><label for="celltype">{#table_dlg.cell_type}</label></td> + <td> + <select id="celltype" name="celltype"> + <option value="td">{#table_dlg.td}</option> + <option value="th">{#table_dlg.th}</option> + </select> + </td> + </tr> + + <tr> + <td><label for="valign">{#table_dlg.valign}</label></td> + <td> + <select id="valign" name="valign"> + <option value="">{#not_set}</option> + <option value="top">{#table_dlg.align_top}</option> + <option value="middle">{#table_dlg.align_middle}</option> + <option value="bottom">{#table_dlg.align_bottom}</option> + </select> + </td> + + <td><label for="scope">{#table_dlg.scope}</label></td> + <td> + <select id="scope" name="scope"> + <option value="">{#not_set}</option> + <option value="col">{#table.col}</option> + <option value="row">{#table.row}</option> + <option value="rowgroup">{#table_dlg.rowgroup}</option> + <option value="colgroup">{#table_dlg.colgroup}</option> + </select> + </td> + + </tr> + + <tr> + <td><label for="width">{#table_dlg.width}</label></td> + <td><input id="width" name="width" type="text" value="" size="7" maxlength="7" onchange="changedSize();" class="size" /></td> + + <td><label for="height">{#table_dlg.height}</label></td> + <td><input id="height" name="height" type="text" value="" size="7" maxlength="7" onchange="changedSize();" class="size" /></td> + </tr> + + <tr id="styleSelectRow"> + <td><label for="class">{#class_name}</label></td> + <td colspan="3"> + <select id="class" name="class" class="mceEditableSelect"> + <option value="" selected="selected">{#not_set}</option> + </select> + </td> + </tr> + </table> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#table_dlg.advanced_props}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="column1"><label for="id">{#table_dlg.id}</label></td> + <td><input id="id" name="id" type="text" value="" style="width: 200px" /></td> + </tr> + + <tr> + <td><label for="style">{#table_dlg.style}</label></td> + <td><input type="text" id="style" name="style" value="" style="width: 200px;" onchange="changedStyle();" /></td> + </tr> + + <tr> + <td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> + <td> + <select id="dir" name="dir" style="width: 200px"> + <option value="">{#not_set}</option> + <option value="ltr">{#table_dlg.ltr}</option> + <option value="rtl">{#table_dlg.rtl}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="lang">{#table_dlg.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" style="width: 200px" /> + </td> + </tr> + + <tr> + <td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="backgroundimage" name="backgroundimage" type="text" value="" style="width: 200px" onchange="changedBackgroundImage();" /></td> + <td id="backgroundimagebrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr role="group" aria-labelledby="bordercolor_label"> + <td class="column1"><label id="bordercolor_label" for="bordercolor">{#table_dlg.bordercolor}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bordercolor" name="bordercolor" type="text" value="" size="9" onchange="updateColor('bordercolor_pick','bordercolor');changedColor();" /></td> + <td id="bordercolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr role="group" aria-labelledby="bgcolor_label"> + <td class="column1"><label id="bgcolor_label" for="bgcolor">{#table_dlg.bgcolor}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');changedColor();" /></td> + <td id="bgcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <div> + <select id="action" name="action"> + <option value="cell">{#table_dlg.cell_cell}</option> + <option value="row">{#table_dlg.cell_row}</option> + <option value="col">{#table_dlg.cell_col}</option> + <option value="all">{#table_dlg.cell_all}</option> + </select> + </div> + + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/table/css/cell.css b/src/core/static/js/tiny_mce/plugins/table/css/cell.css new file mode 100644 index 0000000..a067ecd --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/css/cell.css @@ -0,0 +1,17 @@ +/* CSS file for cell dialog in the table plugin */ + +.panel_wrapper div.current { + height: 200px; +} + +.advfield { + width: 200px; +} + +#action { + margin-bottom: 3px; +} + +#class { + width: 150px; +} \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/table/css/row.css b/src/core/static/js/tiny_mce/plugins/table/css/row.css new file mode 100644 index 0000000..1f7755d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/css/row.css @@ -0,0 +1,25 @@ +/* CSS file for row dialog in the table plugin */ + +.panel_wrapper div.current { + height: 200px; +} + +.advfield { + width: 200px; +} + +#action { + margin-bottom: 3px; +} + +#rowtype,#align,#valign,#class,#height { + width: 150px; +} + +#height { + width: 50px; +} + +.col2 { + padding-left: 20px; +} diff --git a/src/core/static/js/tiny_mce/plugins/table/css/table.css b/src/core/static/js/tiny_mce/plugins/table/css/table.css new file mode 100644 index 0000000..d11c3f6 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/css/table.css @@ -0,0 +1,13 @@ +/* CSS file for table dialog in the table plugin */ + +.panel_wrapper div.current { + height: 245px; +} + +.advfield { + width: 200px; +} + +#class { + width: 150px; +} diff --git a/src/core/static/js/tiny_mce/plugins/table/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/table/editor_plugin.js new file mode 100644 index 0000000..94e3c21 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/editor_plugin.js @@ -0,0 +1 @@ +(function(d){var e=d.each;function c(g,h){var j=h.ownerDocument,f=j.createRange(),k;f.setStartBefore(h);f.setEnd(g.endContainer,g.endOffset);k=j.createElement("body");k.appendChild(f.cloneContents());return k.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length==0}function a(g,f){return parseInt(g.getAttribute(f)||1)}function b(H,G,K){var g,L,D,o;t();o=G.getParent(K.getStart(),"th,td");if(o){L=F(o);D=I();o=z(L.x,L.y)}function A(N,M){N=N.cloneNode(M);N.removeAttribute("id");return N}function t(){var M=0;g=[];e(["thead","tbody","tfoot"],function(N){var O=G.select("> "+N+" tr",H);e(O,function(P,Q){Q+=M;e(G.select("> td, > th",P),function(W,R){var S,T,U,V;if(g[Q]){while(g[Q][R]){R++}}U=a(W,"rowspan");V=a(W,"colspan");for(T=Q;T<Q+U;T++){if(!g[T]){g[T]=[]}for(S=R;S<R+V;S++){g[T][S]={part:N,real:T==Q&&S==R,elm:W,rowspan:U,colspan:V}}}})});M+=O.length})}function z(M,O){var N;N=g[O];if(N){return N[M]}}function s(O,M,N){if(O){N=parseInt(N);if(N===1){O.removeAttribute(M,1)}else{O.setAttribute(M,N,1)}}}function j(M){return M&&(G.hasClass(M.elm,"mceSelected")||M==o)}function k(){var M=[];e(H.rows,function(N){e(N.cells,function(O){if(G.hasClass(O,"mceSelected")||O==o.elm){M.push(N);return false}})});return M}function r(){var M=G.createRng();M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H)}function f(M){var N;d.walk(M,function(P){var O;if(P.nodeType==3){e(G.getParents(P.parentNode,null,M).reverse(),function(Q){Q=A(Q,false);if(!N){N=O=Q}else{if(O){O.appendChild(Q)}}O=Q});if(O){O.innerHTML=d.isIE?"&nbsp;":'<br data-mce-bogus="1" />'}return false}},"childNodes");M=A(M,false);s(M,"rowSpan",1);s(M,"colSpan",1);if(N){M.appendChild(N)}else{if(!d.isIE){M.innerHTML='<br data-mce-bogus="1" />'}}return M}function q(){var M=G.createRng();e(G.select("tr",H),function(N){if(N.cells.length==0){G.remove(N)}});if(G.select("tr",H).length==0){M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H);return}e(G.select("thead,tbody,tfoot",H),function(N){if(N.rows.length==0){G.remove(N)}});t();row=g[Math.min(g.length-1,L.y)];if(row){K.select(row[Math.min(row.length-1,L.x)].elm,true);K.collapse(true)}}function u(S,Q,U,R){var P,N,M,O,T;P=g[Q][S].elm.parentNode;for(M=1;M<=U;M++){P=G.getNext(P,"tr");if(P){for(N=S;N>=0;N--){T=g[Q+M][N].elm;if(T.parentNode==P){for(O=1;O<=R;O++){G.insertAfter(f(T),T)}break}}if(N==-1){for(O=1;O<=R;O++){P.insertBefore(f(P.cells[0]),P.cells[0])}}}}}function C(){e(g,function(M,N){e(M,function(P,O){var S,R,T,Q;if(j(P)){P=P.elm;S=a(P,"colspan");R=a(P,"rowspan");if(S>1||R>1){s(P,"rowSpan",1);s(P,"colSpan",1);for(Q=0;Q<S-1;Q++){G.insertAfter(f(P),P)}u(O,N,R-1,S)}}})})}function p(V,S,Y){var P,O,X,W,U,R,T,M,V,N,Q;if(V){pos=F(V);P=pos.x;O=pos.y;X=P+(S-1);W=O+(Y-1)}else{P=L.x;O=L.y;X=D.x;W=D.y}T=z(P,O);M=z(X,W);if(T&&M&&T.part==M.part){C();t();T=z(P,O).elm;s(T,"colSpan",(X-P)+1);s(T,"rowSpan",(W-O)+1);for(R=O;R<=W;R++){for(U=P;U<=X;U++){if(!g[R]||!g[R][U]){continue}V=g[R][U].elm;if(V!=T){N=d.grep(V.childNodes);e(N,function(Z){T.appendChild(Z)});if(N.length){N=d.grep(T.childNodes);Q=0;e(N,function(Z){if(Z.nodeName=="BR"&&G.getAttrib(Z,"data-mce-bogus")&&Q++<N.length-1){T.removeChild(Z)}})}G.remove(V)}}}q()}}function l(Q){var M,S,P,R,T,U,N,V,O;e(g,function(W,X){e(W,function(Z,Y){if(j(Z)){Z=Z.elm;T=Z.parentNode;U=A(T,false);M=X;if(Q){return false}}});if(Q){return !M}});for(R=0;R<g[0].length;R++){if(!g[M][R]){continue}S=g[M][R].elm;if(S!=P){if(!Q){O=a(S,"rowspan");if(O>1){s(S,"rowSpan",O+1);continue}}else{if(M>0&&g[M-1][R]){V=g[M-1][R].elm;O=a(V,"rowSpan");if(O>1){s(V,"rowSpan",O+1);continue}}}N=f(S);s(N,"colSpan",S.colSpan);U.appendChild(N);P=S}}if(U.hasChildNodes()){if(!Q){G.insertAfter(U,T)}else{T.parentNode.insertBefore(U,T)}}}function h(N){var O,M;e(g,function(P,Q){e(P,function(S,R){if(j(S)){O=R;if(N){return false}}});if(N){return !O}});e(g,function(S,T){var P,Q,R;if(!S[O]){return}P=S[O].elm;if(P!=M){R=a(P,"colspan");Q=a(P,"rowspan");if(R==1){if(!N){G.insertAfter(f(P),P);u(O,T,Q-1,R)}else{P.parentNode.insertBefore(f(P),P);u(O,T,Q-1,R)}}else{s(P,"colSpan",P.colSpan+1)}M=P}})}function n(){var M=[];e(g,function(N,O){e(N,function(Q,P){if(j(Q)&&d.inArray(M,P)===-1){e(g,function(T){var R=T[P].elm,S;S=a(R,"colSpan");if(S>1){s(R,"colSpan",S-1)}else{G.remove(R)}});M.push(P)}})});q()}function m(){var N;function M(Q){var P,R,O;P=G.getNext(Q,"tr");e(Q.cells,function(S){var T=a(S,"rowSpan");if(T>1){s(S,"rowSpan",T-1);R=F(S);u(R.x,R.y,1,1)}});R=F(Q.cells[0]);e(g[R.y],function(S){var T;S=S.elm;if(S!=O){T=a(S,"rowSpan");if(T<=1){G.remove(S)}else{s(S,"rowSpan",T-1)}O=S}})}N=k();e(N.reverse(),function(O){M(O)});q()}function E(){var M=k();G.remove(M);q();return M}function J(){var M=k();e(M,function(O,N){M[N]=A(O,true)});return M}function B(O,N){var P=k(),M=P[N?0:P.length-1],Q=M.cells.length;e(g,function(S){var R;Q=0;e(S,function(U,T){if(U.real){Q+=U.colspan}if(U.elm.parentNode==M){R=1}});if(R){return false}});if(!N){O.reverse()}e(O,function(T){var S=T.cells.length,R;for(i=0;i<S;i++){R=T.cells[i];s(R,"colSpan",1);s(R,"rowSpan",1)}for(i=S;i<Q;i++){T.appendChild(f(T.cells[S-1]))}for(i=Q;i<S;i++){G.remove(T.cells[i])}if(N){M.parentNode.insertBefore(T,M)}else{G.insertAfter(T,M)}})}function F(M){var N;e(g,function(O,P){e(O,function(R,Q){if(R.elm==M){N={x:Q,y:P};return false}});return !N});return N}function w(M){L=F(M)}function I(){var O,N,M;N=M=0;e(g,function(P,Q){e(P,function(S,R){var U,T;if(j(S)){S=g[Q][R];if(R>N){N=R}if(Q>M){M=Q}if(S.real){U=S.colspan-1;T=S.rowspan-1;if(U){if(R+U>N){N=R+U}}if(T){if(Q+T>M){M=Q+T}}}}})});return{x:N,y:M}}function v(S){var P,O,U,T,N,M,Q,R;D=F(S);if(L&&D){P=Math.min(L.x,D.x);O=Math.min(L.y,D.y);U=Math.max(L.x,D.x);T=Math.max(L.y,D.y);N=U;M=T;for(y=O;y<=M;y++){S=g[y][P];if(!S.real){if(P-(S.colspan-1)<P){P-=S.colspan-1}}}for(x=P;x<=N;x++){S=g[O][x];if(!S.real){if(O-(S.rowspan-1)<O){O-=S.rowspan-1}}}for(y=O;y<=T;y++){for(x=P;x<=U;x++){S=g[y][x];if(S.real){Q=S.colspan-1;R=S.rowspan-1;if(Q){if(x+Q>N){N=x+Q}}if(R){if(y+R>M){M=y+R}}}}}G.removeClass(G.select("td.mceSelected,th.mceSelected"),"mceSelected");for(y=O;y<=M;y++){for(x=P;x<=N;x++){if(g[y][x]){G.addClass(g[y][x].elm,"mceSelected")}}}}}d.extend(this,{deleteTable:r,split:C,merge:p,insertRow:l,insertCol:h,deleteCols:n,deleteRows:m,cutRows:E,copyRows:J,pasteRows:B,getPos:F,setStartCell:w,setEndCell:v})}d.create("tinymce.plugins.TablePlugin",{init:function(g,h){var f,m,j=true;function l(p){var o=g.selection,n=g.dom.getParent(p||o.getNode(),"table");if(n){return new b(n,g.dom,o)}}function k(){g.getBody().style.webkitUserSelect="";if(j){g.dom.removeClass(g.dom.select("td.mceSelected,th.mceSelected"),"mceSelected");j=false}}e([["table","table.desc","mceInsertTable",true],["delete_table","table.del","mceTableDelete"],["delete_col","table.delete_col_desc","mceTableDeleteCol"],["delete_row","table.delete_row_desc","mceTableDeleteRow"],["col_after","table.col_after_desc","mceTableInsertColAfter"],["col_before","table.col_before_desc","mceTableInsertColBefore"],["row_after","table.row_after_desc","mceTableInsertRowAfter"],["row_before","table.row_before_desc","mceTableInsertRowBefore"],["row_props","table.row_desc","mceTableRowProps",true],["cell_props","table.cell_desc","mceTableCellProps",true],["split_cells","table.split_cells_desc","mceTableSplitCells",true],["merge_cells","table.merge_cells_desc","mceTableMergeCells",true]],function(n){g.addButton(n[0],{title:n[1],cmd:n[2],ui:n[3]})});if(!d.isIE){g.onClick.add(function(n,o){o=o.target;if(o.nodeName==="TABLE"){n.selection.select(o);n.nodeChanged()}})}g.onPreProcess.add(function(o,p){var n,q,r,t=o.dom,s;n=t.select("table",p.node);q=n.length;while(q--){r=n[q];t.setAttrib(r,"data-mce-style","");if((s=t.getAttrib(r,"width"))){t.setStyle(r,"width",s);t.setAttrib(r,"width","")}if((s=t.getAttrib(r,"height"))){t.setStyle(r,"height",s);t.setAttrib(r,"height","")}}});g.onNodeChange.add(function(q,o,s){var r;s=q.selection.getStart();r=q.dom.getParent(s,"td,th,caption");o.setActive("table",s.nodeName==="TABLE"||!!r);if(r&&r.nodeName==="CAPTION"){r=0}o.setDisabled("delete_table",!r);o.setDisabled("delete_col",!r);o.setDisabled("delete_table",!r);o.setDisabled("delete_row",!r);o.setDisabled("col_after",!r);o.setDisabled("col_before",!r);o.setDisabled("row_after",!r);o.setDisabled("row_before",!r);o.setDisabled("row_props",!r);o.setDisabled("cell_props",!r);o.setDisabled("split_cells",!r);o.setDisabled("merge_cells",!r)});g.onInit.add(function(r){var p,t,q=r.dom,u;f=r.windowManager;r.onMouseDown.add(function(w,z){if(z.button!=2){k();t=q.getParent(z.target,"td,th");p=q.getParent(t,"table")}});q.bind(r.getDoc(),"mouseover",function(C){var A,z,B=C.target;if(t&&(u||B!=t)&&(B.nodeName=="TD"||B.nodeName=="TH")){z=q.getParent(B,"table");if(z==p){if(!u){u=l(z);u.setStartCell(t);r.getBody().style.webkitUserSelect="none"}u.setEndCell(B);j=true}A=r.selection.getSel();try{if(A.removeAllRanges){A.removeAllRanges()}else{A.empty()}}catch(w){}C.preventDefault()}});r.onMouseUp.add(function(F,G){var z,B=F.selection,H,I=B.getSel(),w,C,A,E;if(t){if(u){F.getBody().style.webkitUserSelect=""}function D(J,L){var K=new d.dom.TreeWalker(J,J);do{if(J.nodeType==3&&d.trim(J.nodeValue).length!=0){if(L){z.setStart(J,0)}else{z.setEnd(J,J.nodeValue.length)}return}if(J.nodeName=="BR"){if(L){z.setStartBefore(J)}else{z.setEndBefore(J)}return}}while(J=(L?K.next():K.prev()))}H=q.select("td.mceSelected,th.mceSelected");if(H.length>0){z=q.createRng();C=H[0];E=H[H.length-1];z.setStartBefore(C);z.setEndAfter(C);D(C,1);w=new d.dom.TreeWalker(C,q.getParent(H[0],"table"));do{if(C.nodeName=="TD"||C.nodeName=="TH"){if(!q.hasClass(C,"mceSelected")){break}A=C}}while(C=w.next());D(A);B.setRng(z)}F.nodeChanged();t=u=p=null}});r.onKeyUp.add(function(w,z){k()});r.onKeyDown.add(function(w,z){n(w)});r.onMouseDown.add(function(w,z){if(z.button!=2){n(w)}});function o(D,z,A,F){var B=3,G=D.dom.getParent(z.startContainer,"TABLE"),C,w,E;if(G){C=G.parentNode}w=z.startContainer.nodeType==B&&z.startOffset==0&&z.endOffset==0&&F&&(A.nodeName=="TR"||A==C);E=(A.nodeName=="TD"||A.nodeName=="TH")&&!F;return w||E}function n(A){if(!d.isWebKit){return}var z=A.selection.getRng();var C=A.selection.getNode();var B=A.dom.getParent(z.startContainer,"TD");if(!o(A,z,C,B)){return}if(!B){B=C}var w=B.lastChild;while(w.lastChild){w=w.lastChild}z.setEnd(w,w.nodeValue.length);A.selection.setRng(z)}r.plugins.table.fixTableCellSelection=n;if(r&&r.plugins.contextmenu){r.plugins.contextmenu.onContextMenu.add(function(A,w,C){var D,B=r.selection,z=B.getNode()||r.getBody();if(r.dom.getParent(C,"td")||r.dom.getParent(C,"th")||r.dom.select("td.mceSelected,th.mceSelected").length){w.removeAll();if(z.nodeName=="A"&&!r.dom.getAttrib(z,"name")){w.add({title:"advanced.link_desc",icon:"link",cmd:r.plugins.advlink?"mceAdvLink":"mceLink",ui:true});w.add({title:"advanced.unlink_desc",icon:"unlink",cmd:"UnLink"});w.addSeparator()}if(z.nodeName=="IMG"&&z.className.indexOf("mceItem")==-1){w.add({title:"advanced.image_desc",icon:"image",cmd:r.plugins.advimage?"mceAdvImage":"mceImage",ui:true});w.addSeparator()}w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable",value:{action:"insert"}});w.add({title:"table.props_desc",icon:"table_props",cmd:"mceInsertTable"});w.add({title:"table.del",icon:"delete_table",cmd:"mceTableDelete"});w.addSeparator();D=w.addMenu({title:"table.cell"});D.add({title:"table.cell_desc",icon:"cell_props",cmd:"mceTableCellProps"});D.add({title:"table.split_cells_desc",icon:"split_cells",cmd:"mceTableSplitCells"});D.add({title:"table.merge_cells_desc",icon:"merge_cells",cmd:"mceTableMergeCells"});D=w.addMenu({title:"table.row"});D.add({title:"table.row_desc",icon:"row_props",cmd:"mceTableRowProps"});D.add({title:"table.row_before_desc",icon:"row_before",cmd:"mceTableInsertRowBefore"});D.add({title:"table.row_after_desc",icon:"row_after",cmd:"mceTableInsertRowAfter"});D.add({title:"table.delete_row_desc",icon:"delete_row",cmd:"mceTableDeleteRow"});D.addSeparator();D.add({title:"table.cut_row_desc",icon:"cut",cmd:"mceTableCutRow"});D.add({title:"table.copy_row_desc",icon:"copy",cmd:"mceTableCopyRow"});D.add({title:"table.paste_row_before_desc",icon:"paste",cmd:"mceTablePasteRowBefore"}).setDisabled(!m);D.add({title:"table.paste_row_after_desc",icon:"paste",cmd:"mceTablePasteRowAfter"}).setDisabled(!m);D=w.addMenu({title:"table.col"});D.add({title:"table.col_before_desc",icon:"col_before",cmd:"mceTableInsertColBefore"});D.add({title:"table.col_after_desc",icon:"col_after",cmd:"mceTableInsertColAfter"});D.add({title:"table.delete_col_desc",icon:"delete_col",cmd:"mceTableDeleteCol"})}else{w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable"})}})}if(d.isWebKit){function v(B,M){function F(Q){B.selection.setCursorLocation(Q,0)}function H(R,Q){return R.keyCode==z?Q.previousSibling:Q.nextSibling}function G(R,S){var Q=H(R,S);return Q!==null&&Q.tagName==="TR"?Q:null}function C(Q,R){return Q.dom.getParent(R,"table")}function O(Q){var R=C(B,Q);return H(M,R)}function A(Q){return Q.keyCode==z||Q.keyCode==I}function D(Q){var S=Q.selection.getNode();var R=Q.dom.getParent(S,"tr");return R!==null}function N(R){var Q=0;var S=R;while(S.previousSibling){S=S.previousSibling;Q=Q+a(S,"colspan")}return Q}function E(S,Q){var T=0;var R=0;e(S.children,function(U,V){T=T+a(U,"colspan");R=V;if(T>Q){return false}});return R}function w(S,T,V){var U=N(S.dom.getParent(T,"td,th"));var R=E(V,U);var Q=V.childNodes[R];F(Q)}function L(R,T){var Q=O(R);if(Q!==null){F(Q);return d.dom.Event.cancel(T)}else{var S=T.keyCode==z?R.firstChild:R.lastChild;F(S);return true}}var z=38;var I=40;if(A(M)&&D(B)){var J=B.selection.getNode();var P=B.dom.getParent(J,"tr");var K=G(M,P);if(K==null){return L(P,M)}else{w(B,J,K);d.dom.Event.cancel(M);return true}}}r.onKeyDown.add(v)}if(!d.isIE){function s(){var w;for(w=r.getBody().lastChild;w&&w.nodeType==3&&!w.nodeValue.length;w=w.previousSibling){}if(w&&w.nodeName=="TABLE"){r.dom.add(r.getBody(),"p",null,'<br mce_bogus="1" />')}}if(d.isGecko){r.onKeyDown.add(function(z,B){var w,A,C=z.dom;if(B.keyCode==37||B.keyCode==38){w=z.selection.getRng();A=C.getParent(w.startContainer,"table");if(A&&z.getBody().firstChild==A){if(c(w,A)){w=C.createRng();w.setStartBefore(A);w.setEndBefore(A);z.selection.setRng(w);B.preventDefault()}}}})}r.onKeyUp.add(s);r.onSetContent.add(s);r.onVisualAid.add(s);r.onPreProcess.add(function(w,A){var z=A.node.lastChild;if(z&&z.childNodes.length==1&&z.firstChild.nodeName=="BR"){w.dom.remove(z)}});s();r.startContent=r.getContent({format:"raw"})}});e({mceTableSplitCells:function(n){n.split()},mceTableMergeCells:function(o){var p,q,n;n=g.dom.getParent(g.selection.getNode(),"th,td");if(n){p=n.rowSpan;q=n.colSpan}if(!g.dom.select("td.mceSelected,th.mceSelected").length){f.open({url:h+"/merge_cells.htm",width:240+parseInt(g.getLang("table.merge_cells_delta_width",0)),height:110+parseInt(g.getLang("table.merge_cells_delta_height",0)),inline:1},{rows:p,cols:q,onaction:function(r){o.merge(n,r.cols,r.rows)},plugin_url:h})}else{o.merge()}},mceTableInsertRowBefore:function(n){n.insertRow(true)},mceTableInsertRowAfter:function(n){n.insertRow()},mceTableInsertColBefore:function(n){n.insertCol(true)},mceTableInsertColAfter:function(n){n.insertCol()},mceTableDeleteCol:function(n){n.deleteCols()},mceTableDeleteRow:function(n){n.deleteRows()},mceTableCutRow:function(n){m=n.cutRows()},mceTableCopyRow:function(n){m=n.copyRows()},mceTablePasteRowBefore:function(n){n.pasteRows(m,true)},mceTablePasteRowAfter:function(n){n.pasteRows(m)},mceTableDelete:function(n){n.deleteTable()}},function(o,n){g.addCommand(n,function(){var p=l();if(p){o(p);g.execCommand("mceRepaint");k()}})});e({mceInsertTable:function(n){f.open({url:h+"/table.htm",width:400+parseInt(g.getLang("table.table_delta_width",0)),height:320+parseInt(g.getLang("table.table_delta_height",0)),inline:1},{plugin_url:h,action:n?n.action:0})},mceTableRowProps:function(){f.open({url:h+"/row.htm",width:400+parseInt(g.getLang("table.rowprops_delta_width",0)),height:295+parseInt(g.getLang("table.rowprops_delta_height",0)),inline:1},{plugin_url:h})},mceTableCellProps:function(){f.open({url:h+"/cell.htm",width:400+parseInt(g.getLang("table.cellprops_delta_width",0)),height:295+parseInt(g.getLang("table.cellprops_delta_height",0)),inline:1},{plugin_url:h})}},function(o,n){g.addCommand(n,function(p,q){o(q)})})}});d.PluginManager.add("table",d.plugins.TablePlugin)})(tinymce); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/table/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/table/editor_plugin_src.js new file mode 100644 index 0000000..ccfe808 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/editor_plugin_src.js @@ -0,0 +1,1364 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function(tinymce) { + var each = tinymce.each; + + // Checks if the selection/caret is at the start of the specified block element + function isAtStart(rng, par) { + var doc = par.ownerDocument, rng2 = doc.createRange(), elm; + + rng2.setStartBefore(par); + rng2.setEnd(rng.endContainer, rng.endOffset); + + elm = doc.createElement('body'); + elm.appendChild(rng2.cloneContents()); + + // Check for text characters of other elements that should be treated as content + return elm.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi, '-').replace(/<[^>]+>/g, '').length == 0; + }; + + function getSpanVal(td, name) { + return parseInt(td.getAttribute(name) || 1); + } + + /** + * Table Grid class. + */ + function TableGrid(table, dom, selection) { + var grid, startPos, endPos, selectedCell; + + buildGrid(); + selectedCell = dom.getParent(selection.getStart(), 'th,td'); + if (selectedCell) { + startPos = getPos(selectedCell); + endPos = findEndPos(); + selectedCell = getCell(startPos.x, startPos.y); + } + + function cloneNode(node, children) { + node = node.cloneNode(children); + node.removeAttribute('id'); + + return node; + } + + function buildGrid() { + var startY = 0; + + grid = []; + + each(['thead', 'tbody', 'tfoot'], function(part) { + var rows = dom.select('> ' + part + ' tr', table); + + each(rows, function(tr, y) { + y += startY; + + each(dom.select('> td, > th', tr), function(td, x) { + var x2, y2, rowspan, colspan; + + // Skip over existing cells produced by rowspan + if (grid[y]) { + while (grid[y][x]) + x++; + } + + // Get col/rowspan from cell + rowspan = getSpanVal(td, 'rowspan'); + colspan = getSpanVal(td, 'colspan'); + + // Fill out rowspan/colspan right and down + for (y2 = y; y2 < y + rowspan; y2++) { + if (!grid[y2]) + grid[y2] = []; + + for (x2 = x; x2 < x + colspan; x2++) { + grid[y2][x2] = { + part : part, + real : y2 == y && x2 == x, + elm : td, + rowspan : rowspan, + colspan : colspan + }; + } + } + }); + }); + + startY += rows.length; + }); + }; + + function getCell(x, y) { + var row; + + row = grid[y]; + if (row) + return row[x]; + }; + + function setSpanVal(td, name, val) { + if (td) { + val = parseInt(val); + + if (val === 1) + td.removeAttribute(name, 1); + else + td.setAttribute(name, val, 1); + } + } + + function isCellSelected(cell) { + return cell && (dom.hasClass(cell.elm, 'mceSelected') || cell == selectedCell); + }; + + function getSelectedRows() { + var rows = []; + + each(table.rows, function(row) { + each(row.cells, function(cell) { + if (dom.hasClass(cell, 'mceSelected') || cell == selectedCell.elm) { + rows.push(row); + return false; + } + }); + }); + + return rows; + }; + + function deleteTable() { + var rng = dom.createRng(); + + rng.setStartAfter(table); + rng.setEndAfter(table); + + selection.setRng(rng); + + dom.remove(table); + }; + + function cloneCell(cell) { + var formatNode; + + // Clone formats + tinymce.walk(cell, function(node) { + var curNode; + + if (node.nodeType == 3) { + each(dom.getParents(node.parentNode, null, cell).reverse(), function(node) { + node = cloneNode(node, false); + + if (!formatNode) + formatNode = curNode = node; + else if (curNode) + curNode.appendChild(node); + + curNode = node; + }); + + // Add something to the inner node + if (curNode) + curNode.innerHTML = tinymce.isIE ? '&nbsp;' : '<br data-mce-bogus="1" />'; + + return false; + } + }, 'childNodes'); + + cell = cloneNode(cell, false); + setSpanVal(cell, 'rowSpan', 1); + setSpanVal(cell, 'colSpan', 1); + + if (formatNode) { + cell.appendChild(formatNode); + } else { + if (!tinymce.isIE) + cell.innerHTML = '<br data-mce-bogus="1" />'; + } + + return cell; + }; + + function cleanup() { + var rng = dom.createRng(); + + // Empty rows + each(dom.select('tr', table), function(tr) { + if (tr.cells.length == 0) + dom.remove(tr); + }); + + // Empty table + if (dom.select('tr', table).length == 0) { + rng.setStartAfter(table); + rng.setEndAfter(table); + selection.setRng(rng); + dom.remove(table); + return; + } + + // Empty header/body/footer + each(dom.select('thead,tbody,tfoot', table), function(part) { + if (part.rows.length == 0) + dom.remove(part); + }); + + // Restore selection to start position if it still exists + buildGrid(); + + // Restore the selection to the closest table position + row = grid[Math.min(grid.length - 1, startPos.y)]; + if (row) { + selection.select(row[Math.min(row.length - 1, startPos.x)].elm, true); + selection.collapse(true); + } + }; + + function fillLeftDown(x, y, rows, cols) { + var tr, x2, r, c, cell; + + tr = grid[y][x].elm.parentNode; + for (r = 1; r <= rows; r++) { + tr = dom.getNext(tr, 'tr'); + + if (tr) { + // Loop left to find real cell + for (x2 = x; x2 >= 0; x2--) { + cell = grid[y + r][x2].elm; + + if (cell.parentNode == tr) { + // Append clones after + for (c = 1; c <= cols; c++) + dom.insertAfter(cloneCell(cell), cell); + + break; + } + } + + if (x2 == -1) { + // Insert nodes before first cell + for (c = 1; c <= cols; c++) + tr.insertBefore(cloneCell(tr.cells[0]), tr.cells[0]); + } + } + } + }; + + function split() { + each(grid, function(row, y) { + each(row, function(cell, x) { + var colSpan, rowSpan, newCell, i; + + if (isCellSelected(cell)) { + cell = cell.elm; + colSpan = getSpanVal(cell, 'colspan'); + rowSpan = getSpanVal(cell, 'rowspan'); + + if (colSpan > 1 || rowSpan > 1) { + setSpanVal(cell, 'rowSpan', 1); + setSpanVal(cell, 'colSpan', 1); + + // Insert cells right + for (i = 0; i < colSpan - 1; i++) + dom.insertAfter(cloneCell(cell), cell); + + fillLeftDown(x, y, rowSpan - 1, colSpan); + } + } + }); + }); + }; + + function merge(cell, cols, rows) { + var startX, startY, endX, endY, x, y, startCell, endCell, cell, children, count; + + // Use specified cell and cols/rows + if (cell) { + pos = getPos(cell); + startX = pos.x; + startY = pos.y; + endX = startX + (cols - 1); + endY = startY + (rows - 1); + } else { + // Use selection + startX = startPos.x; + startY = startPos.y; + endX = endPos.x; + endY = endPos.y; + } + + // Find start/end cells + startCell = getCell(startX, startY); + endCell = getCell(endX, endY); + + // Check if the cells exists and if they are of the same part for example tbody = tbody + if (startCell && endCell && startCell.part == endCell.part) { + // Split and rebuild grid + split(); + buildGrid(); + + // Set row/col span to start cell + startCell = getCell(startX, startY).elm; + setSpanVal(startCell, 'colSpan', (endX - startX) + 1); + setSpanVal(startCell, 'rowSpan', (endY - startY) + 1); + + // Remove other cells and add it's contents to the start cell + for (y = startY; y <= endY; y++) { + for (x = startX; x <= endX; x++) { + if (!grid[y] || !grid[y][x]) + continue; + + cell = grid[y][x].elm; + + if (cell != startCell) { + // Move children to startCell + children = tinymce.grep(cell.childNodes); + each(children, function(node) { + startCell.appendChild(node); + }); + + // Remove bogus nodes if there is children in the target cell + if (children.length) { + children = tinymce.grep(startCell.childNodes); + count = 0; + each(children, function(node) { + if (node.nodeName == 'BR' && dom.getAttrib(node, 'data-mce-bogus') && count++ < children.length - 1) + startCell.removeChild(node); + }); + } + + // Remove cell + dom.remove(cell); + } + } + } + + // Remove empty rows etc and restore caret location + cleanup(); + } + }; + + function insertRow(before) { + var posY, cell, lastCell, x, rowElm, newRow, newCell, otherCell, rowSpan; + + // Find first/last row + each(grid, function(row, y) { + each(row, function(cell, x) { + if (isCellSelected(cell)) { + cell = cell.elm; + rowElm = cell.parentNode; + newRow = cloneNode(rowElm, false); + posY = y; + + if (before) + return false; + } + }); + + if (before) + return !posY; + }); + + for (x = 0; x < grid[0].length; x++) { + // Cell not found could be because of an invalid table structure + if (!grid[posY][x]) + continue; + + cell = grid[posY][x].elm; + + if (cell != lastCell) { + if (!before) { + rowSpan = getSpanVal(cell, 'rowspan'); + if (rowSpan > 1) { + setSpanVal(cell, 'rowSpan', rowSpan + 1); + continue; + } + } else { + // Check if cell above can be expanded + if (posY > 0 && grid[posY - 1][x]) { + otherCell = grid[posY - 1][x].elm; + rowSpan = getSpanVal(otherCell, 'rowSpan'); + if (rowSpan > 1) { + setSpanVal(otherCell, 'rowSpan', rowSpan + 1); + continue; + } + } + } + + // Insert new cell into new row + newCell = cloneCell(cell); + setSpanVal(newCell, 'colSpan', cell.colSpan); + + newRow.appendChild(newCell); + + lastCell = cell; + } + } + + if (newRow.hasChildNodes()) { + if (!before) + dom.insertAfter(newRow, rowElm); + else + rowElm.parentNode.insertBefore(newRow, rowElm); + } + }; + + function insertCol(before) { + var posX, lastCell; + + // Find first/last column + each(grid, function(row, y) { + each(row, function(cell, x) { + if (isCellSelected(cell)) { + posX = x; + + if (before) + return false; + } + }); + + if (before) + return !posX; + }); + + each(grid, function(row, y) { + var cell, rowSpan, colSpan; + + if (!row[posX]) + return; + + cell = row[posX].elm; + if (cell != lastCell) { + colSpan = getSpanVal(cell, 'colspan'); + rowSpan = getSpanVal(cell, 'rowspan'); + + if (colSpan == 1) { + if (!before) { + dom.insertAfter(cloneCell(cell), cell); + fillLeftDown(posX, y, rowSpan - 1, colSpan); + } else { + cell.parentNode.insertBefore(cloneCell(cell), cell); + fillLeftDown(posX, y, rowSpan - 1, colSpan); + } + } else + setSpanVal(cell, 'colSpan', cell.colSpan + 1); + + lastCell = cell; + } + }); + }; + + function deleteCols() { + var cols = []; + + // Get selected column indexes + each(grid, function(row, y) { + each(row, function(cell, x) { + if (isCellSelected(cell) && tinymce.inArray(cols, x) === -1) { + each(grid, function(row) { + var cell = row[x].elm, colSpan; + + colSpan = getSpanVal(cell, 'colSpan'); + + if (colSpan > 1) + setSpanVal(cell, 'colSpan', colSpan - 1); + else + dom.remove(cell); + }); + + cols.push(x); + } + }); + }); + + cleanup(); + }; + + function deleteRows() { + var rows; + + function deleteRow(tr) { + var nextTr, pos, lastCell; + + nextTr = dom.getNext(tr, 'tr'); + + // Move down row spanned cells + each(tr.cells, function(cell) { + var rowSpan = getSpanVal(cell, 'rowSpan'); + + if (rowSpan > 1) { + setSpanVal(cell, 'rowSpan', rowSpan - 1); + pos = getPos(cell); + fillLeftDown(pos.x, pos.y, 1, 1); + } + }); + + // Delete cells + pos = getPos(tr.cells[0]); + each(grid[pos.y], function(cell) { + var rowSpan; + + cell = cell.elm; + + if (cell != lastCell) { + rowSpan = getSpanVal(cell, 'rowSpan'); + + if (rowSpan <= 1) + dom.remove(cell); + else + setSpanVal(cell, 'rowSpan', rowSpan - 1); + + lastCell = cell; + } + }); + }; + + // Get selected rows and move selection out of scope + rows = getSelectedRows(); + + // Delete all selected rows + each(rows.reverse(), function(tr) { + deleteRow(tr); + }); + + cleanup(); + }; + + function cutRows() { + var rows = getSelectedRows(); + + dom.remove(rows); + cleanup(); + + return rows; + }; + + function copyRows() { + var rows = getSelectedRows(); + + each(rows, function(row, i) { + rows[i] = cloneNode(row, true); + }); + + return rows; + }; + + function pasteRows(rows, before) { + var selectedRows = getSelectedRows(), + targetRow = selectedRows[before ? 0 : selectedRows.length - 1], + targetCellCount = targetRow.cells.length; + + // Calc target cell count + each(grid, function(row) { + var match; + + targetCellCount = 0; + each(row, function(cell, x) { + if (cell.real) + targetCellCount += cell.colspan; + + if (cell.elm.parentNode == targetRow) + match = 1; + }); + + if (match) + return false; + }); + + if (!before) + rows.reverse(); + + each(rows, function(row) { + var cellCount = row.cells.length, cell; + + // Remove col/rowspans + for (i = 0; i < cellCount; i++) { + cell = row.cells[i]; + setSpanVal(cell, 'colSpan', 1); + setSpanVal(cell, 'rowSpan', 1); + } + + // Needs more cells + for (i = cellCount; i < targetCellCount; i++) + row.appendChild(cloneCell(row.cells[cellCount - 1])); + + // Needs less cells + for (i = targetCellCount; i < cellCount; i++) + dom.remove(row.cells[i]); + + // Add before/after + if (before) + targetRow.parentNode.insertBefore(row, targetRow); + else + dom.insertAfter(row, targetRow); + }); + }; + + function getPos(target) { + var pos; + + each(grid, function(row, y) { + each(row, function(cell, x) { + if (cell.elm == target) { + pos = {x : x, y : y}; + return false; + } + }); + + return !pos; + }); + + return pos; + }; + + function setStartCell(cell) { + startPos = getPos(cell); + }; + + function findEndPos() { + var pos, maxX, maxY; + + maxX = maxY = 0; + + each(grid, function(row, y) { + each(row, function(cell, x) { + var colSpan, rowSpan; + + if (isCellSelected(cell)) { + cell = grid[y][x]; + + if (x > maxX) + maxX = x; + + if (y > maxY) + maxY = y; + + if (cell.real) { + colSpan = cell.colspan - 1; + rowSpan = cell.rowspan - 1; + + if (colSpan) { + if (x + colSpan > maxX) + maxX = x + colSpan; + } + + if (rowSpan) { + if (y + rowSpan > maxY) + maxY = y + rowSpan; + } + } + } + }); + }); + + return {x : maxX, y : maxY}; + }; + + function setEndCell(cell) { + var startX, startY, endX, endY, maxX, maxY, colSpan, rowSpan; + + endPos = getPos(cell); + + if (startPos && endPos) { + // Get start/end positions + startX = Math.min(startPos.x, endPos.x); + startY = Math.min(startPos.y, endPos.y); + endX = Math.max(startPos.x, endPos.x); + endY = Math.max(startPos.y, endPos.y); + + // Expand end positon to include spans + maxX = endX; + maxY = endY; + + // Expand startX + for (y = startY; y <= maxY; y++) { + cell = grid[y][startX]; + + if (!cell.real) { + if (startX - (cell.colspan - 1) < startX) + startX -= cell.colspan - 1; + } + } + + // Expand startY + for (x = startX; x <= maxX; x++) { + cell = grid[startY][x]; + + if (!cell.real) { + if (startY - (cell.rowspan - 1) < startY) + startY -= cell.rowspan - 1; + } + } + + // Find max X, Y + for (y = startY; y <= endY; y++) { + for (x = startX; x <= endX; x++) { + cell = grid[y][x]; + + if (cell.real) { + colSpan = cell.colspan - 1; + rowSpan = cell.rowspan - 1; + + if (colSpan) { + if (x + colSpan > maxX) + maxX = x + colSpan; + } + + if (rowSpan) { + if (y + rowSpan > maxY) + maxY = y + rowSpan; + } + } + } + } + + // Remove current selection + dom.removeClass(dom.select('td.mceSelected,th.mceSelected'), 'mceSelected'); + + // Add new selection + for (y = startY; y <= maxY; y++) { + for (x = startX; x <= maxX; x++) { + if (grid[y][x]) + dom.addClass(grid[y][x].elm, 'mceSelected'); + } + } + } + }; + + // Expose to public + tinymce.extend(this, { + deleteTable : deleteTable, + split : split, + merge : merge, + insertRow : insertRow, + insertCol : insertCol, + deleteCols : deleteCols, + deleteRows : deleteRows, + cutRows : cutRows, + copyRows : copyRows, + pasteRows : pasteRows, + getPos : getPos, + setStartCell : setStartCell, + setEndCell : setEndCell + }); + }; + + tinymce.create('tinymce.plugins.TablePlugin', { + init : function(ed, url) { + var winMan, clipboardRows, hasCellSelection = true; // Might be selected cells on reload + + function createTableGrid(node) { + var selection = ed.selection, tblElm = ed.dom.getParent(node || selection.getNode(), 'table'); + + if (tblElm) + return new TableGrid(tblElm, ed.dom, selection); + }; + + function cleanup() { + // Restore selection possibilities + ed.getBody().style.webkitUserSelect = ''; + + if (hasCellSelection) { + ed.dom.removeClass(ed.dom.select('td.mceSelected,th.mceSelected'), 'mceSelected'); + hasCellSelection = false; + } + }; + + // Register buttons + each([ + ['table', 'table.desc', 'mceInsertTable', true], + ['delete_table', 'table.del', 'mceTableDelete'], + ['delete_col', 'table.delete_col_desc', 'mceTableDeleteCol'], + ['delete_row', 'table.delete_row_desc', 'mceTableDeleteRow'], + ['col_after', 'table.col_after_desc', 'mceTableInsertColAfter'], + ['col_before', 'table.col_before_desc', 'mceTableInsertColBefore'], + ['row_after', 'table.row_after_desc', 'mceTableInsertRowAfter'], + ['row_before', 'table.row_before_desc', 'mceTableInsertRowBefore'], + ['row_props', 'table.row_desc', 'mceTableRowProps', true], + ['cell_props', 'table.cell_desc', 'mceTableCellProps', true], + ['split_cells', 'table.split_cells_desc', 'mceTableSplitCells', true], + ['merge_cells', 'table.merge_cells_desc', 'mceTableMergeCells', true] + ], function(c) { + ed.addButton(c[0], {title : c[1], cmd : c[2], ui : c[3]}); + }); + + // Select whole table is a table border is clicked + if (!tinymce.isIE) { + ed.onClick.add(function(ed, e) { + e = e.target; + + if (e.nodeName === 'TABLE') { + ed.selection.select(e); + ed.nodeChanged(); + } + }); + } + + ed.onPreProcess.add(function(ed, args) { + var nodes, i, node, dom = ed.dom, value; + + nodes = dom.select('table', args.node); + i = nodes.length; + while (i--) { + node = nodes[i]; + dom.setAttrib(node, 'data-mce-style', ''); + + if ((value = dom.getAttrib(node, 'width'))) { + dom.setStyle(node, 'width', value); + dom.setAttrib(node, 'width', ''); + } + + if ((value = dom.getAttrib(node, 'height'))) { + dom.setStyle(node, 'height', value); + dom.setAttrib(node, 'height', ''); + } + } + }); + + // Handle node change updates + ed.onNodeChange.add(function(ed, cm, n) { + var p; + + n = ed.selection.getStart(); + p = ed.dom.getParent(n, 'td,th,caption'); + cm.setActive('table', n.nodeName === 'TABLE' || !!p); + + // Disable table tools if we are in caption + if (p && p.nodeName === 'CAPTION') + p = 0; + + cm.setDisabled('delete_table', !p); + cm.setDisabled('delete_col', !p); + cm.setDisabled('delete_table', !p); + cm.setDisabled('delete_row', !p); + cm.setDisabled('col_after', !p); + cm.setDisabled('col_before', !p); + cm.setDisabled('row_after', !p); + cm.setDisabled('row_before', !p); + cm.setDisabled('row_props', !p); + cm.setDisabled('cell_props', !p); + cm.setDisabled('split_cells', !p); + cm.setDisabled('merge_cells', !p); + }); + + ed.onInit.add(function(ed) { + var startTable, startCell, dom = ed.dom, tableGrid; + + winMan = ed.windowManager; + + // Add cell selection logic + ed.onMouseDown.add(function(ed, e) { + if (e.button != 2) { + cleanup(); + + startCell = dom.getParent(e.target, 'td,th'); + startTable = dom.getParent(startCell, 'table'); + } + }); + + dom.bind(ed.getDoc(), 'mouseover', function(e) { + var sel, table, target = e.target; + + if (startCell && (tableGrid || target != startCell) && (target.nodeName == 'TD' || target.nodeName == 'TH')) { + table = dom.getParent(target, 'table'); + if (table == startTable) { + if (!tableGrid) { + tableGrid = createTableGrid(table); + tableGrid.setStartCell(startCell); + + ed.getBody().style.webkitUserSelect = 'none'; + } + + tableGrid.setEndCell(target); + hasCellSelection = true; + } + + // Remove current selection + sel = ed.selection.getSel(); + + try { + if (sel.removeAllRanges) + sel.removeAllRanges(); + else + sel.empty(); + } catch (ex) { + // IE9 might throw errors here + } + + e.preventDefault(); + } + }); + + ed.onMouseUp.add(function(ed, e) { + var rng, sel = ed.selection, selectedCells, nativeSel = sel.getSel(), walker, node, lastNode, endNode; + + // Move selection to startCell + if (startCell) { + if (tableGrid) + ed.getBody().style.webkitUserSelect = ''; + + function setPoint(node, start) { + var walker = new tinymce.dom.TreeWalker(node, node); + + do { + // Text node + if (node.nodeType == 3 && tinymce.trim(node.nodeValue).length != 0) { + if (start) + rng.setStart(node, 0); + else + rng.setEnd(node, node.nodeValue.length); + + return; + } + + // BR element + if (node.nodeName == 'BR') { + if (start) + rng.setStartBefore(node); + else + rng.setEndBefore(node); + + return; + } + } while (node = (start ? walker.next() : walker.prev())); + } + + // Try to expand text selection as much as we can only Gecko supports cell selection + selectedCells = dom.select('td.mceSelected,th.mceSelected'); + if (selectedCells.length > 0) { + rng = dom.createRng(); + node = selectedCells[0]; + endNode = selectedCells[selectedCells.length - 1]; + rng.setStartBefore(node); + rng.setEndAfter(node); + + setPoint(node, 1); + walker = new tinymce.dom.TreeWalker(node, dom.getParent(selectedCells[0], 'table')); + + do { + if (node.nodeName == 'TD' || node.nodeName == 'TH') { + if (!dom.hasClass(node, 'mceSelected')) + break; + + lastNode = node; + } + } while (node = walker.next()); + + setPoint(lastNode); + + sel.setRng(rng); + } + + ed.nodeChanged(); + startCell = tableGrid = startTable = null; + } + }); + + ed.onKeyUp.add(function(ed, e) { + cleanup(); + }); + + ed.onKeyDown.add(function (ed, e) { + fixTableCellSelection(ed); + }); + + ed.onMouseDown.add(function (ed, e) { + if (e.button != 2) { + fixTableCellSelection(ed); + } + }); + function tableCellSelected(ed, rng, n, currentCell) { + // The decision of when a table cell is selected is somewhat involved. The fact that this code is + // required is actually a pointer to the root cause of this bug. A cell is selected when the start + // and end offsets are 0, the start container is a text, and the selection node is either a TR (most cases) + // or the parent of the table (in the case of the selection containing the last cell of a table). + var TEXT_NODE = 3, table = ed.dom.getParent(rng.startContainer, 'TABLE'), + tableParent, allOfCellSelected, tableCellSelection; + if (table) + tableParent = table.parentNode; + allOfCellSelected =rng.startContainer.nodeType == TEXT_NODE && + rng.startOffset == 0 && + rng.endOffset == 0 && + currentCell && + (n.nodeName=="TR" || n==tableParent); + tableCellSelection = (n.nodeName=="TD"||n.nodeName=="TH")&& !currentCell; + return allOfCellSelected || tableCellSelection; + // return false; + } + + // this nasty hack is here to work around some WebKit selection bugs. + function fixTableCellSelection(ed) { + if (!tinymce.isWebKit) + return; + + var rng = ed.selection.getRng(); + var n = ed.selection.getNode(); + var currentCell = ed.dom.getParent(rng.startContainer, 'TD'); + + if (!tableCellSelected(ed, rng, n, currentCell)) + return; + if (!currentCell) { + currentCell=n; + } + + // Get the very last node inside the table cell + var end = currentCell.lastChild; + while (end.lastChild) + end = end.lastChild; + + // Select the entire table cell. Nothing outside of the table cell should be selected. + rng.setEnd(end, end.nodeValue.length); + ed.selection.setRng(rng); + } + ed.plugins.table.fixTableCellSelection=fixTableCellSelection; + + // Add context menu + if (ed && ed.plugins.contextmenu) { + ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) { + var sm, se = ed.selection, el = se.getNode() || ed.getBody(); + + if (ed.dom.getParent(e, 'td') || ed.dom.getParent(e, 'th') || ed.dom.select('td.mceSelected,th.mceSelected').length) { + m.removeAll(); + + if (el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) { + m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true}); + m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'}); + m.addSeparator(); + } + + if (el.nodeName == 'IMG' && el.className.indexOf('mceItem') == -1) { + m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true}); + m.addSeparator(); + } + + m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', value : {action : 'insert'}}); + m.add({title : 'table.props_desc', icon : 'table_props', cmd : 'mceInsertTable'}); + m.add({title : 'table.del', icon : 'delete_table', cmd : 'mceTableDelete'}); + m.addSeparator(); + + // Cell menu + sm = m.addMenu({title : 'table.cell'}); + sm.add({title : 'table.cell_desc', icon : 'cell_props', cmd : 'mceTableCellProps'}); + sm.add({title : 'table.split_cells_desc', icon : 'split_cells', cmd : 'mceTableSplitCells'}); + sm.add({title : 'table.merge_cells_desc', icon : 'merge_cells', cmd : 'mceTableMergeCells'}); + + // Row menu + sm = m.addMenu({title : 'table.row'}); + sm.add({title : 'table.row_desc', icon : 'row_props', cmd : 'mceTableRowProps'}); + sm.add({title : 'table.row_before_desc', icon : 'row_before', cmd : 'mceTableInsertRowBefore'}); + sm.add({title : 'table.row_after_desc', icon : 'row_after', cmd : 'mceTableInsertRowAfter'}); + sm.add({title : 'table.delete_row_desc', icon : 'delete_row', cmd : 'mceTableDeleteRow'}); + sm.addSeparator(); + sm.add({title : 'table.cut_row_desc', icon : 'cut', cmd : 'mceTableCutRow'}); + sm.add({title : 'table.copy_row_desc', icon : 'copy', cmd : 'mceTableCopyRow'}); + sm.add({title : 'table.paste_row_before_desc', icon : 'paste', cmd : 'mceTablePasteRowBefore'}).setDisabled(!clipboardRows); + sm.add({title : 'table.paste_row_after_desc', icon : 'paste', cmd : 'mceTablePasteRowAfter'}).setDisabled(!clipboardRows); + + // Column menu + sm = m.addMenu({title : 'table.col'}); + sm.add({title : 'table.col_before_desc', icon : 'col_before', cmd : 'mceTableInsertColBefore'}); + sm.add({title : 'table.col_after_desc', icon : 'col_after', cmd : 'mceTableInsertColAfter'}); + sm.add({title : 'table.delete_col_desc', icon : 'delete_col', cmd : 'mceTableDeleteCol'}); + } else + m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable'}); + }); + } + + // Fix to allow navigating up and down in a table in WebKit browsers. + if (tinymce.isWebKit) { + function moveSelection(ed, e) { + + function moveCursorToStartOfElement(n) { + ed.selection.setCursorLocation(n, 0); + } + + function getSibling(event, element) { + return event.keyCode == UP_ARROW ? element.previousSibling : element.nextSibling; + } + + function getNextRow(e, row) { + var sibling = getSibling(e, row); + return sibling !== null && sibling.tagName === 'TR' ? sibling : null; + } + + function getTable(ed, currentRow) { + return ed.dom.getParent(currentRow, 'table'); + } + + function getTableSibling(currentRow) { + var table = getTable(ed, currentRow); + return getSibling(e, table); + } + + function isVerticalMovement(event) { + return event.keyCode == UP_ARROW || event.keyCode == DOWN_ARROW; + } + + function isInTable(ed) { + var node = ed.selection.getNode(); + var currentRow = ed.dom.getParent(node, 'tr'); + return currentRow !== null; + } + + function columnIndex(column) { + var colIndex = 0; + var c = column; + while (c.previousSibling) { + c = c.previousSibling; + colIndex = colIndex + getSpanVal(c, "colspan"); + } + return colIndex; + } + + function findColumn(rowElement, columnIndex) { + var c = 0; + var r = 0; + each(rowElement.children, function(cell, i) { + c = c + getSpanVal(cell, "colspan"); + r = i; + if (c > columnIndex) + return false; + }); + return r; + } + + function moveCursorToRow(ed, node, row) { + var srcColumnIndex = columnIndex(ed.dom.getParent(node, 'td,th')); + var tgtColumnIndex = findColumn(row, srcColumnIndex) + var tgtNode = row.childNodes[tgtColumnIndex]; + moveCursorToStartOfElement(tgtNode); + } + + function escapeTable(currentRow, e) { + var tableSiblingElement = getTableSibling(currentRow); + if (tableSiblingElement !== null) { + moveCursorToStartOfElement(tableSiblingElement); + return tinymce.dom.Event.cancel(e); + } else { + var element = e.keyCode == UP_ARROW ? currentRow.firstChild : currentRow.lastChild; + // rely on default behaviour to escape table after we are in the last cell of the last row + moveCursorToStartOfElement(element); + return true; + } + } + + var UP_ARROW = 38; + var DOWN_ARROW = 40; + + if (isVerticalMovement(e) && isInTable(ed)) { + var node = ed.selection.getNode(); + var currentRow = ed.dom.getParent(node, 'tr'); + var nextRow = getNextRow(e, currentRow); + + // If we're at the first or last row in the table, we should move the caret outside of the table + if (nextRow == null) { + return escapeTable(currentRow, e); + } else { + moveCursorToRow(ed, node, nextRow); + tinymce.dom.Event.cancel(e); + return true; + } + } + } + + ed.onKeyDown.add(moveSelection); + } + + // Fixes an issue on Gecko where it's impossible to place the caret behind a table + // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled + if (!tinymce.isIE) { + function fixTableCaretPos() { + var last; + + // Skip empty text nodes form the end + for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling) ; + + if (last && last.nodeName == 'TABLE') + ed.dom.add(ed.getBody(), 'p', null, '<br mce_bogus="1" />'); + }; + + // Fixes an bug where it's impossible to place the caret before a table in Gecko + // this fix solves it by detecting when the caret is at the beginning of such a table + // and then manually moves the caret infront of the table + if (tinymce.isGecko) { + ed.onKeyDown.add(function(ed, e) { + var rng, table, dom = ed.dom; + + // On gecko it's not possible to place the caret before a table + if (e.keyCode == 37 || e.keyCode == 38) { + rng = ed.selection.getRng(); + table = dom.getParent(rng.startContainer, 'table'); + + if (table && ed.getBody().firstChild == table) { + if (isAtStart(rng, table)) { + rng = dom.createRng(); + + rng.setStartBefore(table); + rng.setEndBefore(table); + + ed.selection.setRng(rng); + + e.preventDefault(); + } + } + } + }); + } + + ed.onKeyUp.add(fixTableCaretPos); + ed.onSetContent.add(fixTableCaretPos); + ed.onVisualAid.add(fixTableCaretPos); + + ed.onPreProcess.add(function(ed, o) { + var last = o.node.lastChild; + + if (last && last.childNodes.length == 1 && last.firstChild.nodeName == 'BR') + ed.dom.remove(last); + }); + + fixTableCaretPos(); + ed.startContent = ed.getContent({format : 'raw'}); + } + }); + + // Register action commands + each({ + mceTableSplitCells : function(grid) { + grid.split(); + }, + + mceTableMergeCells : function(grid) { + var rowSpan, colSpan, cell; + + cell = ed.dom.getParent(ed.selection.getNode(), 'th,td'); + if (cell) { + rowSpan = cell.rowSpan; + colSpan = cell.colSpan; + } + + if (!ed.dom.select('td.mceSelected,th.mceSelected').length) { + winMan.open({ + url : url + '/merge_cells.htm', + width : 240 + parseInt(ed.getLang('table.merge_cells_delta_width', 0)), + height : 110 + parseInt(ed.getLang('table.merge_cells_delta_height', 0)), + inline : 1 + }, { + rows : rowSpan, + cols : colSpan, + onaction : function(data) { + grid.merge(cell, data.cols, data.rows); + }, + plugin_url : url + }); + } else + grid.merge(); + }, + + mceTableInsertRowBefore : function(grid) { + grid.insertRow(true); + }, + + mceTableInsertRowAfter : function(grid) { + grid.insertRow(); + }, + + mceTableInsertColBefore : function(grid) { + grid.insertCol(true); + }, + + mceTableInsertColAfter : function(grid) { + grid.insertCol(); + }, + + mceTableDeleteCol : function(grid) { + grid.deleteCols(); + }, + + mceTableDeleteRow : function(grid) { + grid.deleteRows(); + }, + + mceTableCutRow : function(grid) { + clipboardRows = grid.cutRows(); + }, + + mceTableCopyRow : function(grid) { + clipboardRows = grid.copyRows(); + }, + + mceTablePasteRowBefore : function(grid) { + grid.pasteRows(clipboardRows, true); + }, + + mceTablePasteRowAfter : function(grid) { + grid.pasteRows(clipboardRows); + }, + + mceTableDelete : function(grid) { + grid.deleteTable(); + } + }, function(func, name) { + ed.addCommand(name, function() { + var grid = createTableGrid(); + + if (grid) { + func(grid); + ed.execCommand('mceRepaint'); + cleanup(); + } + }); + }); + + // Register dialog commands + each({ + mceInsertTable : function(val) { + winMan.open({ + url : url + '/table.htm', + width : 400 + parseInt(ed.getLang('table.table_delta_width', 0)), + height : 320 + parseInt(ed.getLang('table.table_delta_height', 0)), + inline : 1 + }, { + plugin_url : url, + action : val ? val.action : 0 + }); + }, + + mceTableRowProps : function() { + winMan.open({ + url : url + '/row.htm', + width : 400 + parseInt(ed.getLang('table.rowprops_delta_width', 0)), + height : 295 + parseInt(ed.getLang('table.rowprops_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }, + + mceTableCellProps : function() { + winMan.open({ + url : url + '/cell.htm', + width : 400 + parseInt(ed.getLang('table.cellprops_delta_width', 0)), + height : 295 + parseInt(ed.getLang('table.cellprops_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + } + }, function(func, name) { + ed.addCommand(name, function(ui, val) { + func(val); + }); + }); + } + }); + + // Register plugin + tinymce.PluginManager.add('table', tinymce.plugins.TablePlugin); +})(tinymce); diff --git a/src/core/static/js/tiny_mce/plugins/table/js/cell.js b/src/core/static/js/tiny_mce/plugins/table/js/cell.js new file mode 100644 index 0000000..d6f3290 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/js/cell.js @@ -0,0 +1,319 @@ +tinyMCEPopup.requireLangPack(); + +var ed; + +function init() { + ed = tinyMCEPopup.editor; + tinyMCEPopup.resizeToInnerSize(); + + document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table'); + document.getElementById('bordercolor_pickcontainer').innerHTML = getColorPickerHTML('bordercolor_pick','bordercolor'); + document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor') + + var inst = ed; + var tdElm = ed.dom.getParent(ed.selection.getStart(), "td,th"); + var formObj = document.forms[0]; + var st = ed.dom.parseStyle(ed.dom.getAttrib(tdElm, "style")); + + // Get table cell data + var celltype = tdElm.nodeName.toLowerCase(); + var align = ed.dom.getAttrib(tdElm, 'align'); + var valign = ed.dom.getAttrib(tdElm, 'valign'); + var width = trimSize(getStyle(tdElm, 'width', 'width')); + var height = trimSize(getStyle(tdElm, 'height', 'height')); + var bordercolor = convertRGBToHex(getStyle(tdElm, 'bordercolor', 'borderLeftColor')); + var bgcolor = convertRGBToHex(getStyle(tdElm, 'bgcolor', 'backgroundColor')); + var className = ed.dom.getAttrib(tdElm, 'class'); + var backgroundimage = getStyle(tdElm, 'background', 'backgroundImage').replace(new RegExp("url\\(['\"]?([^'\"]*)['\"]?\\)", 'gi'), "$1"); + var id = ed.dom.getAttrib(tdElm, 'id'); + var lang = ed.dom.getAttrib(tdElm, 'lang'); + var dir = ed.dom.getAttrib(tdElm, 'dir'); + var scope = ed.dom.getAttrib(tdElm, 'scope'); + + // Setup form + addClassesToList('class', 'table_cell_styles'); + TinyMCE_EditableSelects.init(); + + if (!ed.dom.hasClass(tdElm, 'mceSelected')) { + formObj.bordercolor.value = bordercolor; + formObj.bgcolor.value = bgcolor; + formObj.backgroundimage.value = backgroundimage; + formObj.width.value = width; + formObj.height.value = height; + formObj.id.value = id; + formObj.lang.value = lang; + formObj.style.value = ed.dom.serializeStyle(st); + selectByValue(formObj, 'align', align); + selectByValue(formObj, 'valign', valign); + selectByValue(formObj, 'class', className, true, true); + selectByValue(formObj, 'celltype', celltype); + selectByValue(formObj, 'dir', dir); + selectByValue(formObj, 'scope', scope); + + // Resize some elements + if (isVisible('backgroundimagebrowser')) + document.getElementById('backgroundimage').style.width = '180px'; + + updateColor('bordercolor_pick', 'bordercolor'); + updateColor('bgcolor_pick', 'bgcolor'); + } else + tinyMCEPopup.dom.hide('action'); +} + +function updateAction() { + var el, inst = ed, tdElm, trElm, tableElm, formObj = document.forms[0]; + + if (!AutoValidator.validate(formObj)) { + tinyMCEPopup.alert(AutoValidator.getErrorMessages(formObj).join('. ') + '.'); + return false; + } + + tinyMCEPopup.restoreSelection(); + el = ed.selection.getStart(); + tdElm = ed.dom.getParent(el, "td,th"); + trElm = ed.dom.getParent(el, "tr"); + tableElm = ed.dom.getParent(el, "table"); + + // Cell is selected + if (ed.dom.hasClass(tdElm, 'mceSelected')) { + // Update all selected sells + tinymce.each(ed.dom.select('td.mceSelected,th.mceSelected'), function(td) { + updateCell(td); + }); + + ed.addVisual(); + ed.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); + return; + } + + switch (getSelectValue(formObj, 'action')) { + case "cell": + var celltype = getSelectValue(formObj, 'celltype'); + var scope = getSelectValue(formObj, 'scope'); + + function doUpdate(s) { + if (s) { + updateCell(tdElm); + + ed.addVisual(); + ed.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); + } + }; + + if (ed.getParam("accessibility_warnings", 1)) { + if (celltype == "th" && scope == "") + tinyMCEPopup.confirm(ed.getLang('table_dlg.missing_scope', '', true), doUpdate); + else + doUpdate(1); + + return; + } + + updateCell(tdElm); + break; + + case "row": + var cell = trElm.firstChild; + + if (cell.nodeName != "TD" && cell.nodeName != "TH") + cell = nextCell(cell); + + do { + cell = updateCell(cell, true); + } while ((cell = nextCell(cell)) != null); + + break; + + case "col": + var curr, col = 0, cell = trElm.firstChild, rows = tableElm.getElementsByTagName("tr"); + + if (cell.nodeName != "TD" && cell.nodeName != "TH") + cell = nextCell(cell); + + do { + if (cell == tdElm) + break; + col += cell.getAttribute("colspan"); + } while ((cell = nextCell(cell)) != null); + + for (var i=0; i<rows.length; i++) { + cell = rows[i].firstChild; + + if (cell.nodeName != "TD" && cell.nodeName != "TH") + cell = nextCell(cell); + + curr = 0; + do { + if (curr == col) { + cell = updateCell(cell, true); + break; + } + curr += cell.getAttribute("colspan"); + } while ((cell = nextCell(cell)) != null); + } + + break; + + case "all": + var rows = tableElm.getElementsByTagName("tr"); + + for (var i=0; i<rows.length; i++) { + var cell = rows[i].firstChild; + + if (cell.nodeName != "TD" && cell.nodeName != "TH") + cell = nextCell(cell); + + do { + cell = updateCell(cell, true); + } while ((cell = nextCell(cell)) != null); + } + + break; + } + + ed.addVisual(); + ed.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); +} + +function nextCell(elm) { + while ((elm = elm.nextSibling) != null) { + if (elm.nodeName == "TD" || elm.nodeName == "TH") + return elm; + } + + return null; +} + +function updateCell(td, skip_id) { + var inst = ed; + var formObj = document.forms[0]; + var curCellType = td.nodeName.toLowerCase(); + var celltype = getSelectValue(formObj, 'celltype'); + var doc = inst.getDoc(); + var dom = ed.dom; + + if (!skip_id) + dom.setAttrib(td, 'id', formObj.id.value); + + dom.setAttrib(td, 'align', formObj.align.value); + dom.setAttrib(td, 'vAlign', formObj.valign.value); + dom.setAttrib(td, 'lang', formObj.lang.value); + dom.setAttrib(td, 'dir', getSelectValue(formObj, 'dir')); + dom.setAttrib(td, 'style', ed.dom.serializeStyle(ed.dom.parseStyle(formObj.style.value))); + dom.setAttrib(td, 'scope', formObj.scope.value); + dom.setAttrib(td, 'class', getSelectValue(formObj, 'class')); + + // Clear deprecated attributes + ed.dom.setAttrib(td, 'width', ''); + ed.dom.setAttrib(td, 'height', ''); + ed.dom.setAttrib(td, 'bgColor', ''); + ed.dom.setAttrib(td, 'borderColor', ''); + ed.dom.setAttrib(td, 'background', ''); + + // Set styles + td.style.width = getCSSSize(formObj.width.value); + td.style.height = getCSSSize(formObj.height.value); + if (formObj.bordercolor.value != "") { + td.style.borderColor = formObj.bordercolor.value; + td.style.borderStyle = td.style.borderStyle == "" ? "solid" : td.style.borderStyle; + td.style.borderWidth = td.style.borderWidth == "" ? "1px" : td.style.borderWidth; + } else + td.style.borderColor = ''; + + td.style.backgroundColor = formObj.bgcolor.value; + + if (formObj.backgroundimage.value != "") + td.style.backgroundImage = "url('" + formObj.backgroundimage.value + "')"; + else + td.style.backgroundImage = ''; + + if (curCellType != celltype) { + // changing to a different node type + var newCell = doc.createElement(celltype); + + for (var c=0; c<td.childNodes.length; c++) + newCell.appendChild(td.childNodes[c].cloneNode(1)); + + for (var a=0; a<td.attributes.length; a++) + ed.dom.setAttrib(newCell, td.attributes[a].name, ed.dom.getAttrib(td, td.attributes[a].name)); + + td.parentNode.replaceChild(newCell, td); + td = newCell; + } + + dom.setAttrib(td, 'style', dom.serializeStyle(dom.parseStyle(td.style.cssText))); + + return td; +} + +function changedBackgroundImage() { + var formObj = document.forms[0]; + var st = ed.dom.parseStyle(formObj.style.value); + + st['background-image'] = "url('" + formObj.backgroundimage.value + "')"; + + formObj.style.value = ed.dom.serializeStyle(st); +} + +function changedSize() { + var formObj = document.forms[0]; + var st = ed.dom.parseStyle(formObj.style.value); + + var width = formObj.width.value; + if (width != "") + st['width'] = getCSSSize(width); + else + st['width'] = ""; + + var height = formObj.height.value; + if (height != "") + st['height'] = getCSSSize(height); + else + st['height'] = ""; + + formObj.style.value = ed.dom.serializeStyle(st); +} + +function changedColor() { + var formObj = document.forms[0]; + var st = ed.dom.parseStyle(formObj.style.value); + + st['background-color'] = formObj.bgcolor.value; + st['border-color'] = formObj.bordercolor.value; + + formObj.style.value = ed.dom.serializeStyle(st); +} + +function changedStyle() { + var formObj = document.forms[0]; + var st = ed.dom.parseStyle(formObj.style.value); + + if (st['background-image']) + formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1"); + else + formObj.backgroundimage.value = ''; + + if (st['width']) + formObj.width.value = trimSize(st['width']); + + if (st['height']) + formObj.height.value = trimSize(st['height']); + + if (st['background-color']) { + formObj.bgcolor.value = st['background-color']; + updateColor('bgcolor_pick','bgcolor'); + } + + if (st['border-color']) { + formObj.bordercolor.value = st['border-color']; + updateColor('bordercolor_pick','bordercolor'); + } +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/plugins/table/js/merge_cells.js b/src/core/static/js/tiny_mce/plugins/table/js/merge_cells.js new file mode 100644 index 0000000..7ee4bf0 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/js/merge_cells.js @@ -0,0 +1,27 @@ +tinyMCEPopup.requireLangPack(); + +var MergeCellsDialog = { + init : function() { + var f = document.forms[0]; + + f.numcols.value = tinyMCEPopup.getWindowArg('cols', 1); + f.numrows.value = tinyMCEPopup.getWindowArg('rows', 1); + }, + + merge : function() { + var func, f = document.forms[0]; + + tinyMCEPopup.restoreSelection(); + + func = tinyMCEPopup.getWindowArg('onaction'); + + func({ + cols : f.numcols.value, + rows : f.numrows.value + }); + + tinyMCEPopup.close(); + } +}; + +tinyMCEPopup.onInit.add(MergeCellsDialog.init, MergeCellsDialog); diff --git a/src/core/static/js/tiny_mce/plugins/table/js/row.js b/src/core/static/js/tiny_mce/plugins/table/js/row.js new file mode 100644 index 0000000..a13d695 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/js/row.js @@ -0,0 +1,237 @@ +tinyMCEPopup.requireLangPack(); + +function init() { + tinyMCEPopup.resizeToInnerSize(); + + document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table'); + document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor'); + + var inst = tinyMCEPopup.editor; + var dom = inst.dom; + var trElm = dom.getParent(inst.selection.getStart(), "tr"); + var formObj = document.forms[0]; + var st = dom.parseStyle(dom.getAttrib(trElm, "style")); + + // Get table row data + var rowtype = trElm.parentNode.nodeName.toLowerCase(); + var align = dom.getAttrib(trElm, 'align'); + var valign = dom.getAttrib(trElm, 'valign'); + var height = trimSize(getStyle(trElm, 'height', 'height')); + var className = dom.getAttrib(trElm, 'class'); + var bgcolor = convertRGBToHex(getStyle(trElm, 'bgcolor', 'backgroundColor')); + var backgroundimage = getStyle(trElm, 'background', 'backgroundImage').replace(new RegExp("url\\(['\"]?([^'\"]*)['\"]?\\)", 'gi'), "$1"); + var id = dom.getAttrib(trElm, 'id'); + var lang = dom.getAttrib(trElm, 'lang'); + var dir = dom.getAttrib(trElm, 'dir'); + + selectByValue(formObj, 'rowtype', rowtype); + + // Any cells selected + if (dom.select('td.mceSelected,th.mceSelected', trElm).length == 0) { + // Setup form + addClassesToList('class', 'table_row_styles'); + TinyMCE_EditableSelects.init(); + + formObj.bgcolor.value = bgcolor; + formObj.backgroundimage.value = backgroundimage; + formObj.height.value = height; + formObj.id.value = id; + formObj.lang.value = lang; + formObj.style.value = dom.serializeStyle(st); + selectByValue(formObj, 'align', align); + selectByValue(formObj, 'valign', valign); + selectByValue(formObj, 'class', className, true, true); + selectByValue(formObj, 'dir', dir); + + // Resize some elements + if (isVisible('backgroundimagebrowser')) + document.getElementById('backgroundimage').style.width = '180px'; + + updateColor('bgcolor_pick', 'bgcolor'); + } else + tinyMCEPopup.dom.hide('action'); +} + +function updateAction() { + var inst = tinyMCEPopup.editor, dom = inst.dom, trElm, tableElm, formObj = document.forms[0]; + var action = getSelectValue(formObj, 'action'); + + if (!AutoValidator.validate(formObj)) { + tinyMCEPopup.alert(AutoValidator.getErrorMessages(formObj).join('. ') + '.'); + return false; + } + + tinyMCEPopup.restoreSelection(); + trElm = dom.getParent(inst.selection.getStart(), "tr"); + tableElm = dom.getParent(inst.selection.getStart(), "table"); + + // Update all selected rows + if (dom.select('td.mceSelected,th.mceSelected', trElm).length > 0) { + tinymce.each(tableElm.rows, function(tr) { + var i; + + for (i = 0; i < tr.cells.length; i++) { + if (dom.hasClass(tr.cells[i], 'mceSelected')) { + updateRow(tr, true); + return; + } + } + }); + + inst.addVisual(); + inst.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); + return; + } + + switch (action) { + case "row": + updateRow(trElm); + break; + + case "all": + var rows = tableElm.getElementsByTagName("tr"); + + for (var i=0; i<rows.length; i++) + updateRow(rows[i], true); + + break; + + case "odd": + case "even": + var rows = tableElm.getElementsByTagName("tr"); + + for (var i=0; i<rows.length; i++) { + if ((i % 2 == 0 && action == "odd") || (i % 2 != 0 && action == "even")) + updateRow(rows[i], true, true); + } + + break; + } + + inst.addVisual(); + inst.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); +} + +function updateRow(tr_elm, skip_id, skip_parent) { + var inst = tinyMCEPopup.editor; + var formObj = document.forms[0]; + var dom = inst.dom; + var curRowType = tr_elm.parentNode.nodeName.toLowerCase(); + var rowtype = getSelectValue(formObj, 'rowtype'); + var doc = inst.getDoc(); + + // Update row element + if (!skip_id) + dom.setAttrib(tr_elm, 'id', formObj.id.value); + + dom.setAttrib(tr_elm, 'align', getSelectValue(formObj, 'align')); + dom.setAttrib(tr_elm, 'vAlign', getSelectValue(formObj, 'valign')); + dom.setAttrib(tr_elm, 'lang', formObj.lang.value); + dom.setAttrib(tr_elm, 'dir', getSelectValue(formObj, 'dir')); + dom.setAttrib(tr_elm, 'style', dom.serializeStyle(dom.parseStyle(formObj.style.value))); + dom.setAttrib(tr_elm, 'class', getSelectValue(formObj, 'class')); + + // Clear deprecated attributes + dom.setAttrib(tr_elm, 'background', ''); + dom.setAttrib(tr_elm, 'bgColor', ''); + dom.setAttrib(tr_elm, 'height', ''); + + // Set styles + tr_elm.style.height = getCSSSize(formObj.height.value); + tr_elm.style.backgroundColor = formObj.bgcolor.value; + + if (formObj.backgroundimage.value != "") + tr_elm.style.backgroundImage = "url('" + formObj.backgroundimage.value + "')"; + else + tr_elm.style.backgroundImage = ''; + + // Setup new rowtype + if (curRowType != rowtype && !skip_parent) { + // first, clone the node we are working on + var newRow = tr_elm.cloneNode(1); + + // next, find the parent of its new destination (creating it if necessary) + var theTable = dom.getParent(tr_elm, "table"); + var dest = rowtype; + var newParent = null; + for (var i = 0; i < theTable.childNodes.length; i++) { + if (theTable.childNodes[i].nodeName.toLowerCase() == dest) + newParent = theTable.childNodes[i]; + } + + if (newParent == null) { + newParent = doc.createElement(dest); + + if (theTable.firstChild.nodeName == 'CAPTION') + inst.dom.insertAfter(newParent, theTable.firstChild); + else + theTable.insertBefore(newParent, theTable.firstChild); + } + + // append the row to the new parent + newParent.appendChild(newRow); + + // remove the original + tr_elm.parentNode.removeChild(tr_elm); + + // set tr_elm to the new node + tr_elm = newRow; + } + + dom.setAttrib(tr_elm, 'style', dom.serializeStyle(dom.parseStyle(tr_elm.style.cssText))); +} + +function changedBackgroundImage() { + var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom; + var st = dom.parseStyle(formObj.style.value); + + st['background-image'] = "url('" + formObj.backgroundimage.value + "')"; + + formObj.style.value = dom.serializeStyle(st); +} + +function changedStyle() { + var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom; + var st = dom.parseStyle(formObj.style.value); + + if (st['background-image']) + formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1"); + else + formObj.backgroundimage.value = ''; + + if (st['height']) + formObj.height.value = trimSize(st['height']); + + if (st['background-color']) { + formObj.bgcolor.value = st['background-color']; + updateColor('bgcolor_pick','bgcolor'); + } +} + +function changedSize() { + var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom; + var st = dom.parseStyle(formObj.style.value); + + var height = formObj.height.value; + if (height != "") + st['height'] = getCSSSize(height); + else + st['height'] = ""; + + formObj.style.value = dom.serializeStyle(st); +} + +function changedColor() { + var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom; + var st = dom.parseStyle(formObj.style.value); + + st['background-color'] = formObj.bgcolor.value; + + formObj.style.value = dom.serializeStyle(st); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/plugins/table/js/table.js b/src/core/static/js/tiny_mce/plugins/table/js/table.js new file mode 100644 index 0000000..520d857 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/js/table.js @@ -0,0 +1,450 @@ +tinyMCEPopup.requireLangPack(); + +var action, orgTableWidth, orgTableHeight, dom = tinyMCEPopup.editor.dom; + +function insertTable() { + var formObj = document.forms[0]; + var inst = tinyMCEPopup.editor, dom = inst.dom; + var cols = 2, rows = 2, border = 0, cellpadding = -1, cellspacing = -1, align, width, height, className, caption, frame, rules; + var html = '', capEl, elm; + var cellLimit, rowLimit, colLimit; + + tinyMCEPopup.restoreSelection(); + + if (!AutoValidator.validate(formObj)) { + tinyMCEPopup.alert(AutoValidator.getErrorMessages(formObj).join('. ') + '.'); + return false; + } + + elm = dom.getParent(inst.selection.getNode(), 'table'); + + // Get form data + cols = formObj.elements['cols'].value; + rows = formObj.elements['rows'].value; + border = formObj.elements['border'].value != "" ? formObj.elements['border'].value : 0; + cellpadding = formObj.elements['cellpadding'].value != "" ? formObj.elements['cellpadding'].value : ""; + cellspacing = formObj.elements['cellspacing'].value != "" ? formObj.elements['cellspacing'].value : ""; + align = getSelectValue(formObj, "align"); + frame = getSelectValue(formObj, "tframe"); + rules = getSelectValue(formObj, "rules"); + width = formObj.elements['width'].value; + height = formObj.elements['height'].value; + bordercolor = formObj.elements['bordercolor'].value; + bgcolor = formObj.elements['bgcolor'].value; + className = getSelectValue(formObj, "class"); + id = formObj.elements['id'].value; + summary = formObj.elements['summary'].value; + style = formObj.elements['style'].value; + dir = formObj.elements['dir'].value; + lang = formObj.elements['lang'].value; + background = formObj.elements['backgroundimage'].value; + caption = formObj.elements['caption'].checked; + + cellLimit = tinyMCEPopup.getParam('table_cell_limit', false); + rowLimit = tinyMCEPopup.getParam('table_row_limit', false); + colLimit = tinyMCEPopup.getParam('table_col_limit', false); + + // Validate table size + if (colLimit && cols > colLimit) { + tinyMCEPopup.alert(inst.getLang('table_dlg.col_limit').replace(/\{\$cols\}/g, colLimit)); + return false; + } else if (rowLimit && rows > rowLimit) { + tinyMCEPopup.alert(inst.getLang('table_dlg.row_limit').replace(/\{\$rows\}/g, rowLimit)); + return false; + } else if (cellLimit && cols * rows > cellLimit) { + tinyMCEPopup.alert(inst.getLang('table_dlg.cell_limit').replace(/\{\$cells\}/g, cellLimit)); + return false; + } + + // Update table + if (action == "update") { + dom.setAttrib(elm, 'cellPadding', cellpadding, true); + dom.setAttrib(elm, 'cellSpacing', cellspacing, true); + dom.setAttrib(elm, 'border', border); + dom.setAttrib(elm, 'align', align); + dom.setAttrib(elm, 'frame', frame); + dom.setAttrib(elm, 'rules', rules); + dom.setAttrib(elm, 'class', className); + dom.setAttrib(elm, 'style', style); + dom.setAttrib(elm, 'id', id); + dom.setAttrib(elm, 'summary', summary); + dom.setAttrib(elm, 'dir', dir); + dom.setAttrib(elm, 'lang', lang); + + capEl = inst.dom.select('caption', elm)[0]; + + if (capEl && !caption) + capEl.parentNode.removeChild(capEl); + + if (!capEl && caption) { + capEl = elm.ownerDocument.createElement('caption'); + + if (!tinymce.isIE) + capEl.innerHTML = '<br data-mce-bogus="1"/>'; + + elm.insertBefore(capEl, elm.firstChild); + } + + if (width && inst.settings.inline_styles) { + dom.setStyle(elm, 'width', width); + dom.setAttrib(elm, 'width', ''); + } else { + dom.setAttrib(elm, 'width', width, true); + dom.setStyle(elm, 'width', ''); + } + + // Remove these since they are not valid XHTML + dom.setAttrib(elm, 'borderColor', ''); + dom.setAttrib(elm, 'bgColor', ''); + dom.setAttrib(elm, 'background', ''); + + if (height && inst.settings.inline_styles) { + dom.setStyle(elm, 'height', height); + dom.setAttrib(elm, 'height', ''); + } else { + dom.setAttrib(elm, 'height', height, true); + dom.setStyle(elm, 'height', ''); + } + + if (background != '') + elm.style.backgroundImage = "url('" + background + "')"; + else + elm.style.backgroundImage = ''; + +/* if (tinyMCEPopup.getParam("inline_styles")) { + if (width != '') + elm.style.width = getCSSSize(width); + }*/ + + if (bordercolor != "") { + elm.style.borderColor = bordercolor; + elm.style.borderStyle = elm.style.borderStyle == "" ? "solid" : elm.style.borderStyle; + elm.style.borderWidth = border == "" ? "1px" : border; + } else + elm.style.borderColor = ''; + + elm.style.backgroundColor = bgcolor; + elm.style.height = getCSSSize(height); + + inst.addVisual(); + + // Fix for stange MSIE align bug + //elm.outerHTML = elm.outerHTML; + + inst.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + + // Repaint if dimensions changed + if (formObj.width.value != orgTableWidth || formObj.height.value != orgTableHeight) + inst.execCommand('mceRepaint'); + + tinyMCEPopup.close(); + return true; + } + + // Create new table + html += '<table'; + + html += makeAttrib('id', id); + html += makeAttrib('border', border); + html += makeAttrib('cellpadding', cellpadding); + html += makeAttrib('cellspacing', cellspacing); + html += makeAttrib('data-mce-new', '1'); + + if (width && inst.settings.inline_styles) { + if (style) + style += '; '; + + // Force px + if (/^[0-9\.]+$/.test(width)) + width += 'px'; + + style += 'width: ' + width; + } else + html += makeAttrib('width', width); + +/* if (height) { + if (style) + style += '; '; + + style += 'height: ' + height; + }*/ + + //html += makeAttrib('height', height); + //html += makeAttrib('bordercolor', bordercolor); + //html += makeAttrib('bgcolor', bgcolor); + html += makeAttrib('align', align); + html += makeAttrib('frame', frame); + html += makeAttrib('rules', rules); + html += makeAttrib('class', className); + html += makeAttrib('style', style); + html += makeAttrib('summary', summary); + html += makeAttrib('dir', dir); + html += makeAttrib('lang', lang); + html += '>'; + + if (caption) { + if (!tinymce.isIE) + html += '<caption><br data-mce-bogus="1"/></caption>'; + else + html += '<caption></caption>'; + } + + for (var y=0; y<rows; y++) { + html += "<tr>"; + + for (var x=0; x<cols; x++) { + if (!tinymce.isIE) + html += '<td><br data-mce-bogus="1"/></td>'; + else + html += '<td></td>'; + } + + html += "</tr>"; + } + + html += "</table>"; + + // Move table + if (inst.settings.fix_table_elements) { + var patt = ''; + + inst.focus(); + inst.selection.setContent('<br class="_mce_marker" />'); + + tinymce.each('h1,h2,h3,h4,h5,h6,p'.split(','), function(n) { + if (patt) + patt += ','; + + patt += n + ' ._mce_marker'; + }); + + tinymce.each(inst.dom.select(patt), function(n) { + inst.dom.split(inst.dom.getParent(n, 'h1,h2,h3,h4,h5,h6,p'), n); + }); + + dom.setOuterHTML(dom.select('br._mce_marker')[0], html); + } else + inst.execCommand('mceInsertContent', false, html); + + tinymce.each(dom.select('table[data-mce-new]'), function(node) { + var td = dom.select('td', node); + + try { + // IE9 might fail to do this selection + inst.selection.select(td[0], true); + inst.selection.collapse(); + } catch (ex) { + // Ignore + } + + dom.setAttrib(node, 'data-mce-new', ''); + }); + + inst.addVisual(); + inst.execCommand('mceEndUndoLevel'); + + tinyMCEPopup.close(); +} + +function makeAttrib(attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib]; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + if (value == "") + return ""; + + // XML encode it + value = value.replace(/&/g, '&amp;'); + value = value.replace(/\"/g, '&quot;'); + value = value.replace(/</g, '&lt;'); + value = value.replace(/>/g, '&gt;'); + + return ' ' + attrib + '="' + value + '"'; +} + +function init() { + tinyMCEPopup.resizeToInnerSize(); + + document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table'); + document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table'); + document.getElementById('bordercolor_pickcontainer').innerHTML = getColorPickerHTML('bordercolor_pick','bordercolor'); + document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor'); + + var cols = 2, rows = 2, border = tinyMCEPopup.getParam('table_default_border', '0'), cellpadding = tinyMCEPopup.getParam('table_default_cellpadding', ''), cellspacing = tinyMCEPopup.getParam('table_default_cellspacing', ''); + var align = "", width = "", height = "", bordercolor = "", bgcolor = "", className = ""; + var id = "", summary = "", style = "", dir = "", lang = "", background = "", bgcolor = "", bordercolor = "", rules = "", frame = ""; + var inst = tinyMCEPopup.editor, dom = inst.dom; + var formObj = document.forms[0]; + var elm = dom.getParent(inst.selection.getNode(), "table"); + + action = tinyMCEPopup.getWindowArg('action'); + + if (!action) + action = elm ? "update" : "insert"; + + if (elm && action != "insert") { + var rowsAr = elm.rows; + var cols = 0; + for (var i=0; i<rowsAr.length; i++) + if (rowsAr[i].cells.length > cols) + cols = rowsAr[i].cells.length; + + cols = cols; + rows = rowsAr.length; + + st = dom.parseStyle(dom.getAttrib(elm, "style")); + border = trimSize(getStyle(elm, 'border', 'borderWidth')); + cellpadding = dom.getAttrib(elm, 'cellpadding', ""); + cellspacing = dom.getAttrib(elm, 'cellspacing', ""); + width = trimSize(getStyle(elm, 'width', 'width')); + height = trimSize(getStyle(elm, 'height', 'height')); + bordercolor = convertRGBToHex(getStyle(elm, 'bordercolor', 'borderLeftColor')); + bgcolor = convertRGBToHex(getStyle(elm, 'bgcolor', 'backgroundColor')); + align = dom.getAttrib(elm, 'align', align); + frame = dom.getAttrib(elm, 'frame'); + rules = dom.getAttrib(elm, 'rules'); + className = tinymce.trim(dom.getAttrib(elm, 'class').replace(/mceItem.+/g, '')); + id = dom.getAttrib(elm, 'id'); + summary = dom.getAttrib(elm, 'summary'); + style = dom.serializeStyle(st); + dir = dom.getAttrib(elm, 'dir'); + lang = dom.getAttrib(elm, 'lang'); + background = getStyle(elm, 'background', 'backgroundImage').replace(new RegExp("url\\(['\"]?([^'\"]*)['\"]?\\)", 'gi'), "$1"); + formObj.caption.checked = elm.getElementsByTagName('caption').length > 0; + + orgTableWidth = width; + orgTableHeight = height; + + action = "update"; + formObj.insert.value = inst.getLang('update'); + } + + addClassesToList('class', "table_styles"); + TinyMCE_EditableSelects.init(); + + // Update form + selectByValue(formObj, 'align', align); + selectByValue(formObj, 'tframe', frame); + selectByValue(formObj, 'rules', rules); + selectByValue(formObj, 'class', className, true, true); + formObj.cols.value = cols; + formObj.rows.value = rows; + formObj.border.value = border; + formObj.cellpadding.value = cellpadding; + formObj.cellspacing.value = cellspacing; + formObj.width.value = width; + formObj.height.value = height; + formObj.bordercolor.value = bordercolor; + formObj.bgcolor.value = bgcolor; + formObj.id.value = id; + formObj.summary.value = summary; + formObj.style.value = style; + formObj.dir.value = dir; + formObj.lang.value = lang; + formObj.backgroundimage.value = background; + + updateColor('bordercolor_pick', 'bordercolor'); + updateColor('bgcolor_pick', 'bgcolor'); + + // Resize some elements + if (isVisible('backgroundimagebrowser')) + document.getElementById('backgroundimage').style.width = '180px'; + + // Disable some fields in update mode + if (action == "update") { + formObj.cols.disabled = true; + formObj.rows.disabled = true; + } +} + +function changedSize() { + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + +/* var width = formObj.width.value; + if (width != "") + st['width'] = tinyMCEPopup.getParam("inline_styles") ? getCSSSize(width) : ""; + else + st['width'] = "";*/ + + var height = formObj.height.value; + if (height != "") + st['height'] = getCSSSize(height); + else + st['height'] = ""; + + formObj.style.value = dom.serializeStyle(st); +} + +function changedBackgroundImage() { + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + st['background-image'] = "url('" + formObj.backgroundimage.value + "')"; + + formObj.style.value = dom.serializeStyle(st); +} + +function changedBorder() { + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + // Update border width if the element has a color + if (formObj.border.value != "" && formObj.bordercolor.value != "") + st['border-width'] = formObj.border.value + "px"; + + formObj.style.value = dom.serializeStyle(st); +} + +function changedColor() { + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + st['background-color'] = formObj.bgcolor.value; + + if (formObj.bordercolor.value != "") { + st['border-color'] = formObj.bordercolor.value; + + // Add border-width if it's missing + if (!st['border-width']) + st['border-width'] = formObj.border.value == "" ? "1px" : formObj.border.value + "px"; + } + + formObj.style.value = dom.serializeStyle(st); +} + +function changedStyle() { + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + if (st['background-image']) + formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\(['\"]?([^'\"]*)['\"]?\\)", 'gi'), "$1"); + else + formObj.backgroundimage.value = ''; + + if (st['width']) + formObj.width.value = trimSize(st['width']); + + if (st['height']) + formObj.height.value = trimSize(st['height']); + + if (st['background-color']) { + formObj.bgcolor.value = st['background-color']; + updateColor('bgcolor_pick','bgcolor'); + } + + if (st['border-color']) { + formObj.bordercolor.value = st['border-color']; + updateColor('bordercolor_pick','bordercolor'); + } +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/plugins/table/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/table/langs/de_dlg.js new file mode 100755 index 0000000..5a64ebd --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.table_dlg',{"rules_border":"alle 4 Seiten (Border)","rules_box":"alle 4 Seiten (Box)","rules_vsides":"links und rechts","rules_rhs":"nur rechts","rules_lhs":"nur links","rules_hsides":"oben und unten","rules_below":"nur unten","rules_above":"nur oben","rules_void":"keins",rules:"Gitter","frame_all":"zwischen allen Zellen","frame_cols":"zwischen Spalten","frame_rows":"zwischen Zeilen","frame_groups":"zwischen Gruppen","frame_none":"keine",frame:"Rahmen",caption:"Beschriftung der Tabelle","missing_scope":"Wollen Sie wirklich keine Beziehung f\u00fcr diese \u00dcberschrift angeben? Benutzer mit k\u00f6rperlichen Einschr\u00e4nkungen k\u00f6nnten Schwierigkeiten haben, den Inhalt der Tabelle zu verstehen.","cell_limit":"Sie haben die maximale Zellenzahl von {$cells} \u00fcberschritten.","row_limit":"Sie haben die maximale Zeilenzahl von {$rows} \u00fcberschritten.","col_limit":"Sie haben die maximale Spaltenzahl von {$cols} \u00fcberschritten.",colgroup:"Horizontal gruppieren",rowgroup:"Vertikal gruppieren",scope:"Bezug",tfoot:"Tabellenfu\u00df",tbody:"Tabelleninhalt",thead:"Tabellenkopf","row_all":"Alle Zeilen ver\u00e4ndern","row_even":"Gerade Zeilen ver\u00e4ndern","row_odd":"Ungerade Zeilen ver\u00e4ndern","row_row":"Diese Zeile ver\u00e4ndern","cell_all":"Alle Zellen der Tabelle ver\u00e4ndern","cell_row":"Alle Zellen in dieser Zeile ver\u00e4ndern","cell_cell":"Diese Zelle ver\u00e4ndern",th:"\u00dcberschrift",td:"Textzelle",summary:"Zusammenfassung",bgimage:"Hintergrundbild",rtl:"Rechts nach links",ltr:"Links nach rechts",mime:"MIME-Type des Inhalts",langcode:"Sprachcode",langdir:"Schriftrichtung",style:"Format",id:"ID","merge_cells_title":"Zellen vereinen",bgcolor:"Hintergrundfarbe",bordercolor:"Rahmenfarbe","align_bottom":"Unten","align_top":"Oben",valign:"Vertikale Ausrichtung","cell_type":"Zellentyp","cell_title":"Eigenschaften der Zelle","row_title":"Eigenschaften der Zeile","align_middle":"Mittig","align_right":"Rechts","align_left":"Links","align_default":"Standard",align:"Ausrichtung",border:"Rahmen",cellpadding:"Abstand innerhalb der Zellen",cellspacing:"Zellenabstand",rows:"Zeilen",cols:"Spalten",height:"H\u00f6he",width:"Breite",title:"Tabelle einf\u00fcgen/bearbeiten",rowtype:"Gruppierung","advanced_props":"Erweiterte Einstellungen","general_props":"Allgemeine Einstellungen","advanced_tab":"Erweitert","general_tab":"Allgemein","cell_col":"Alle Zellen in dieser Spalte aktualisieren"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/table/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/table/langs/en_dlg.js new file mode 100755 index 0000000..463e09e --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.table_dlg',{"rules_border":"border","rules_box":"box","rules_vsides":"vsides","rules_rhs":"rhs","rules_lhs":"lhs","rules_hsides":"hsides","rules_below":"below","rules_above":"above","rules_void":"void",rules:"Rules","frame_all":"all","frame_cols":"cols","frame_rows":"rows","frame_groups":"groups","frame_none":"none",frame:"Frame",caption:"Table Caption","missing_scope":"Are you sure you want to continue without specifying a scope for this table header cell. Without it, it may be difficult for some users with disabilities to understand the content or data displayed of the table.","cell_limit":"You\'ve exceeded the maximum number of cells of {$cells}.","row_limit":"You\'ve exceeded the maximum number of rows of {$rows}.","col_limit":"You\'ve exceeded the maximum number of columns of {$cols}.",colgroup:"Col Group",rowgroup:"Row Group",scope:"Scope",tfoot:"Footer",tbody:"Body",thead:"Header","row_all":"Update All Rows in Table","row_even":"Update Even Rows in Table","row_odd":"Update Odd Rows in Table","row_row":"Update Current Row","cell_all":"Update All Cells in Table","cell_row":"Update All Cells in Row","cell_cell":"Update Current Cell",th:"Header",td:"Data",summary:"Summary",bgimage:"Background Image",rtl:"Right to Left",ltr:"Left to Right",mime:"Target MIME Type",langcode:"Language Code",langdir:"Language Direction",style:"Style",id:"ID","merge_cells_title":"Merge Table Cells",bgcolor:"Background Color",bordercolor:"Border Color","align_bottom":"Bottom","align_top":"Top",valign:"Vertical Alignment","cell_type":"Cell Type","cell_title":"Table Cell Properties","row_title":"Table Row Properties","align_middle":"Center","align_right":"Right","align_left":"Left","align_default":"Default",align:"Alignment",border:"Border",cellpadding:"Cell Padding",cellspacing:"Cell Spacing",rows:"Rows",cols:"Columns",height:"Height",width:"Width",title:"Insert/Edit Table",rowtype:"Row Type","advanced_props":"Advanced Properties","general_props":"General Properties","advanced_tab":"Advanced","general_tab":"General","cell_col":"Update all cells in column"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/table/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/table/langs/fr_dlg.js new file mode 100755 index 0000000..9f9488a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.table_dlg',{"rules_border":"bordure","rules_box":"bo\u00eete","rules_vsides":"verticales","rules_rhs":"\u00e0 droite","rules_lhs":"\u00e0 gauche","rules_hsides":"horizontales","rules_below":"au-dessous","rules_above":"au-dessus","rules_void":"aucune",rules:"R\u00e8gles","frame_all":"tous","frame_cols":"colonnes","frame_rows":"lignes","frame_groups":"groupe","frame_none":"aucun",frame:"Cadre",caption:"Afficher la l\u00e9gende du tableau","missing_scope":"\u00cates-vous s\u00fbr de vouloir continuer sans sp\u00e9cifier de port\u00e9e pour cette cellule de titre ? Sans port\u00e9e, cela peut \u00eatre difficile pour certains utilisateurs de comprendre le contenu ou les donn\u00e9es affich\u00e9es dans le tableau.","cell_limit":"Vous avez d\u00e9pass\u00e9 le nombre maximum de cellules ({$cells}).","row_limit":"Vous avez d\u00e9pass\u00e9 le nombre maximum de lignes ({$rows}).","col_limit":"Vous avez d\u00e9pass\u00e9 le nombre maximum de colonnes ({$cols}).",colgroup:"Groupe de colonnes",rowgroup:"Groupe de lignes",scope:"Port\u00e9e",tfoot:"Pied de tableau",tbody:"Corps de tableau",thead:"En-t\u00eates de tableau","row_all":"Mettre \u00e0 jour toutes les lignes du tableau","row_even":"Mettre \u00e0 jour les lignes paires","row_odd":"Mettre \u00e0 jour les lignes impaires","row_row":"Mettre \u00e0 jour la ligne courante","cell_all":"Mettre \u00e0 jour toutes les cellules du tableau","cell_row":"Mettre \u00e0 jour toutes les cellules de la ligne","cell_cell":"Mettre \u00e0 jour la cellule courante",th:"Titre",td:"Donn\u00e9es",summary:"R\u00e9sum\u00e9",bgimage:"Image de fond",rtl:"de droite \u00e0 gauche",ltr:"De gauche \u00e0 droite",mime:"Type MIME de la cible",langcode:"Code de la langue",langdir:"Sens de lecture",style:"Style",id:"Id","merge_cells_title":"Fusionner les cellules",bgcolor:"Couleur du fond",bordercolor:"Couleur de la bordure","align_bottom":"Bas","align_top":"Haut",valign:"Alignement vertical","cell_type":"Type de cellule","cell_title":"Propri\u00e9t\u00e9s de la cellule","row_title":"Propri\u00e9t\u00e9s de la ligne","align_middle":"Centr\u00e9","align_right":"Droite","align_left":"Gauche","align_default":"Par d\u00e9faut",align:"Alignement",border:"Bordure",cellpadding:"Espacement dans les cellules",cellspacing:"Espacement entre les cellules",rows:"Lignes",cols:"Colonnes",height:"Hauteur",width:"Largeur",title:"Ins\u00e9rer / modifier un tableau",rowtype:"Type de ligne","advanced_props":"Propri\u00e9t\u00e9s avanc\u00e9es","general_props":"Propri\u00e9t\u00e9s g\u00e9n\u00e9rales","advanced_tab":"Avanc\u00e9","general_tab":"G\u00e9n\u00e9ral","cell_col":"Mettre \u00e0 jour toutes les cellules de la colonne"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/table/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/table/langs/it_dlg.js new file mode 100755 index 0000000..2a847ed --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.table_dlg',{"rules_border":"bordo","rules_box":"box","rules_vsides":"lato vert.","rules_rhs":"rhs","rules_lhs":"lhs","rules_hsides":"lato orizz.","rules_below":"sotto","rules_above":"sopra","rules_void":"vuoto",rules:"Regole","frame_all":"tutte","frame_cols":"colonne","frame_rows":"righe","frame_groups":"gruppi","frame_none":"nessuna",frame:"Cornice",caption:"Didascalia tabella","missing_scope":"Sicuro di proseguire senza aver specificato uno scope per l\'intestazione di questa tabella? Senza di esso, potrebbe essere difficoltoso per alcuni utenti con disabilit\u00e0 capire il contenuto o i dati mostrati nella tabella.","cell_limit":"Superato il numero massimo di celle di {$cells}.","row_limit":"Superato il numero massimo di righe di {$rows}.","col_limit":"Superato il numero massimo di colonne di {$cols}.",colgroup:"Gruppo colonna",rowgroup:"Gruppo riga",scope:"Scope",tfoot:"Pedice tabella",tbody:"Corpo tabella",thead:"Intestazione tabella","row_all":"Update tutte le righe della tabella","row_even":"Aggiorna righe pari della tabella","row_odd":"Aggiorna righe dispari della tabella","row_row":"Aggiorna riga corrente","cell_all":"Aggiorna tutte le celle della tabella","cell_row":"Aggiorna tutte le celle della riga","cell_cell":"Aggiorna cella corrente",th:"Intestazione",td:"Data",summary:"Sommario",bgimage:"Immagine sfondo",rtl:"Destra verso sinistra",ltr:"Sinistra verso destra",mime:"Tipo MIME del target",langcode:"Lingua",langdir:"Direzione testo",style:"Stile",id:"Id","merge_cells_title":"Unisci celle",bgcolor:"Colore sfondo",bordercolor:"Colore bordo","align_bottom":"In basso","align_top":"In alto",valign:"Allineamento verticale","cell_type":"Tipo cella","cell_title":"Propriet\u00e0 cella","row_title":"Propriet\u00e0 riga","align_middle":"Centra","align_right":"A destra","align_left":"A sinistra","align_default":"Predefinito",align:"Allineamento",border:"Bordo",cellpadding:"Padding celle",cellspacing:"Spaziatura celle",rows:"Righe",cols:"Colonne",height:"Altezza",width:"Larghezza",title:"Inserisci/Modifica tabella",rowtype:"Riga in una parte di tabella","advanced_props":"Propriet\u00e0 avanzate","general_props":"Propriet\u00e0 generali","advanced_tab":"Avanzate","general_tab":"Generale","cell_col":"Aggiorna tutte le celle della colonna"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/table/merge_cells.htm b/src/core/static/js/tiny_mce/plugins/table/merge_cells.htm new file mode 100644 index 0000000..d231090 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/merge_cells.htm @@ -0,0 +1,32 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#table_dlg.merge_cells_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="js/merge_cells.js"></script> +</head> +<body style="margin: 8px" role="application"> +<form onsubmit="MergeCellsDialog.merge();return false;" action="#"> + <fieldset> + <legend>{#table_dlg.merge_cells_title}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="3" width="100%"> + <tr> + <td><label for="numcols">{#table_dlg.cols}</label>:</td> + <td align="right"><input type="text" id="numcols" name="numcols" value="" class="number min1 mceFocus" style="width: 30px" aria-required="true" /></td> + </tr> + <tr> + <td><label for="numrows">{#table_dlg.rows}</label>:</td> + <td align="right"><input type="text" id="numrows" name="numrows" value="" class="number min1" style="width: 30px" aria-required="true" /></td> + </tr> + </table> + </fieldset> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/table/row.htm b/src/core/static/js/tiny_mce/plugins/table/row.htm new file mode 100644 index 0000000..1885401 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/row.htm @@ -0,0 +1,158 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#table_dlg.row_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/row.js"></script> + <link href="css/row.css" rel="stylesheet" type="text/css" /> +</head> +<body id="tablerow" style="display: none" role="application"> + <form onsubmit="updateAction();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#table_dlg.general_props}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td><label for="rowtype">{#table_dlg.rowtype}</label></td> + <td class="col2"> + <select id="rowtype" name="rowtype" class="mceFocus"> + <option value="thead">{#table_dlg.thead}</option> + <option value="tbody">{#table_dlg.tbody}</option> + <option value="tfoot">{#table_dlg.tfoot}</option> + </select> + </td> + </tr> + + <tr> + <td><label for="align">{#table_dlg.align}</label></td> + <td class="col2"> + <select id="align" name="align"> + <option value="">{#not_set}</option> + <option value="center">{#table_dlg.align_middle}</option> + <option value="left">{#table_dlg.align_left}</option> + <option value="right">{#table_dlg.align_right}</option> + </select> + </td> + </tr> + + <tr> + <td><label for="valign">{#table_dlg.valign}</label></td> + <td class="col2"> + <select id="valign" name="valign"> + <option value="">{#not_set}</option> + <option value="top">{#table_dlg.align_top}</option> + <option value="middle">{#table_dlg.align_middle}</option> + <option value="bottom">{#table_dlg.align_bottom}</option> + </select> + </td> + </tr> + + <tr id="styleSelectRow"> + <td><label for="class">{#class_name}</label></td> + <td class="col2"> + <select id="class" name="class" class="mceEditableSelect"> + <option value="" selected="selected">{#not_set}</option> + </select> + </td> + </tr> + + <tr> + <td><label for="height">{#table_dlg.height}</label></td> + <td class="col2"><input name="height" type="text" id="height" value="" size="7" maxlength="7" onchange="changedSize();" class="size" /></td> + </tr> + </table> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#table_dlg.advanced_props}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="column1"><label for="id">{#table_dlg.id}</label></td> + <td><input id="id" name="id" type="text" value="" style="width: 200px" /></td> + </tr> + + <tr> + <td><label for="style">{#table_dlg.style}</label></td> + <td><input type="text" id="style" name="style" value="" style="width: 200px;" onchange="changedStyle();" /></td> + </tr> + + <tr> + <td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> + <td> + <select id="dir" name="dir" style="width: 200px"> + <option value="">{#not_set}</option> + <option value="ltr">{#table_dlg.ltr}</option> + <option value="rtl">{#table_dlg.rtl}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="lang">{#table_dlg.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" style="width: 200px" /> + </td> + </tr> + + <tr> + <td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="backgroundimage" name="backgroundimage" type="text" value="" style="width: 200px" onchange="changedBackgroundImage();" /></td> + <td id="backgroundimagebrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td class="column1"><label for="bgcolor" id="bgcolor_label">{#table_dlg.bgcolor}</label></td> + <td> + <span role="group" aria-labelledby="bgcolor_label"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');changedColor();" /></td> + <td id="bgcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </span> + </td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <div> + <select id="action" name="action"> + <option value="row">{#table_dlg.row_row}</option> + <option value="odd">{#table_dlg.row_odd}</option> + <option value="even">{#table_dlg.row_even}</option> + <option value="all">{#table_dlg.row_all}</option> + </select> + </div> + + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/table/table.htm b/src/core/static/js/tiny_mce/plugins/table/table.htm new file mode 100644 index 0000000..09d3700 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/table/table.htm @@ -0,0 +1,188 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#table_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/table.js"></script> + <link href="css/table.css" rel="stylesheet" type="text/css" /> +</head> +<body id="table" style="display: none" role="application" aria-labelledby="app_title"> + <span style="display:none;" id="app_title">{#table_dlg.title}</span> + <form onsubmit="insertTable();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" aria-controls="general_panel" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#table_dlg.general_props}</legend> + <table role="presentation" border="0" cellpadding="4" cellspacing="0" width="100%"> + <tr> + <td><label id="colslabel" for="cols">{#table_dlg.cols}</label></td> + <td><input id="cols" name="cols" type="text" value="" size="3" maxlength="3" class="required number min1 mceFocus" aria-required="true" /></td> + <td><label id="rowslabel" for="rows">{#table_dlg.rows}</label></td> + <td><input id="rows" name="rows" type="text" value="" size="3" maxlength="3" class="required number min1" aria-required="true" /></td> + </tr> + <tr> + <td><label id="cellpaddinglabel" for="cellpadding">{#table_dlg.cellpadding}</label></td> + <td><input id="cellpadding" name="cellpadding" type="text" value="" size="3" maxlength="3" class="number" /></td> + <td><label id="cellspacinglabel" for="cellspacing">{#table_dlg.cellspacing}</label></td> + <td><input id="cellspacing" name="cellspacing" type="text" value="" size="3" maxlength="3" class="number" /></td> + </tr> + <tr> + <td><label id="alignlabel" for="align">{#table_dlg.align}</label></td> + <td><select id="align" name="align"> + <option value="">{#not_set}</option> + <option value="center">{#table_dlg.align_middle}</option> + <option value="left">{#table_dlg.align_left}</option> + <option value="right">{#table_dlg.align_right}</option> + </select></td> + <td><label id="borderlabel" for="border">{#table_dlg.border}</label></td> + <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="changedBorder();" class="number" /></td> + </tr> + <tr id="width_row"> + <td><label id="widthlabel" for="width">{#table_dlg.width}</label></td> + <td><input name="width" type="text" id="width" value="" size="7" maxlength="7" onchange="changedSize();" class="size" /></td> + <td><label id="heightlabel" for="height">{#table_dlg.height}</label></td> + <td><input name="height" type="text" id="height" value="" size="7" maxlength="7" onchange="changedSize();" class="size" /></td> + </tr> + <tr id="styleSelectRow" > + <td><label id="classlabel" for="class">{#class_name}</label></td> + <td colspan="3" > + <select id="class" name="class" class="mceEditableSelect"> + <option value="" selected="selected">{#not_set}</option> + </select></td> + </tr> + <tr> + <td class="column1" ><label for="caption">{#table_dlg.caption}</label></td> + <td><input id="caption" name="caption" type="checkbox" class="checkbox" value="true" /></td> + </tr> + </table> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#table_dlg.advanced_props}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="column1"><label for="id">{#table_dlg.id}</label></td> + <td><input id="id" name="id" type="text" value="" class="advfield" /></td> + </tr> + + <tr> + <td class="column1"><label for="summary">{#table_dlg.summary}</label></td> + <td><input id="summary" name="summary" type="text" value="" class="advfield" /></td> + </tr> + + <tr> + <td><label for="style">{#table_dlg.style}</label></td> + <td><input type="text" id="style" name="style" value="" class="advfield" onchange="changedStyle();" /></td> + </tr> + + <tr> + <td class="column1"><label id="langlabel" for="lang">{#table_dlg.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" class="advfield" /> + </td> + </tr> + + <tr> + <td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> + <td> + <table role="presentation" aria-labelledby="backgroundimage_label" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="backgroundimage" name="backgroundimage" type="text" value="" class="advfield" onchange="changedBackgroundImage();" /></td> + <td id="backgroundimagebrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td class="column1"><label for="tframe">{#table_dlg.frame}</label></td> + <td> + <select id="tframe" name="tframe" class="advfield"> + <option value="">{#not_set}</option> + <option value="void">{#table_dlg.rules_void}</option> + <option value="above">{#table_dlg.rules_above}</option> + <option value="below">{#table_dlg.rules_below}</option> + <option value="hsides">{#table_dlg.rules_hsides}</option> + <option value="lhs">{#table_dlg.rules_lhs}</option> + <option value="rhs">{#table_dlg.rules_rhs}</option> + <option value="vsides">{#table_dlg.rules_vsides}</option> + <option value="box">{#table_dlg.rules_box}</option> + <option value="border">{#table_dlg.rules_border}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="rules">{#table_dlg.rules}</label></td> + <td> + <select id="rules" name="rules" class="advfield"> + <option value="">{#not_set}</option> + <option value="none">{#table_dlg.frame_none}</option> + <option value="groups">{#table_dlg.frame_groups}</option> + <option value="rows">{#table_dlg.frame_rows}</option> + <option value="cols">{#table_dlg.frame_cols}</option> + <option value="all">{#table_dlg.frame_all}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> + <td> + <select id="dir" name="dir" class="advfield"> + <option value="">{#not_set}</option> + <option value="ltr">{#table_dlg.ltr}</option> + <option value="rtl">{#table_dlg.rtl}</option> + </select> + </td> + </tr> + + <tr role="group" aria-labelledby="bordercolor_label"> + <td class="column1"><label id="bordercolor_label" for="bordercolor">{#table_dlg.bordercolor}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bordercolor" name="bordercolor" type="text" value="" size="9" onchange="updateColor('bordercolor_pick','bordercolor');changedColor();" /></td> + <td id="bordercolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr role="group" aria-labelledby="bgcolor_label"> + <td class="column1"><label id="bgcolor_label" for="bgcolor">{#table_dlg.bgcolor}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');changedColor();" /></td> + <td id="bgcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/template/blank.htm b/src/core/static/js/tiny_mce/plugins/template/blank.htm new file mode 100644 index 0000000..ecde53f --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/template/blank.htm @@ -0,0 +1,12 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>blank_page</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <script type="text/javascript"> + parent.TemplateDialog.loadCSSFiles(document); + </script> +</head> +<body id="mceTemplatePreview" class="mceContentBody"> + +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/template/css/template.css b/src/core/static/js/tiny_mce/plugins/template/css/template.css new file mode 100644 index 0000000..2d23a49 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/template/css/template.css @@ -0,0 +1,23 @@ +#frmbody { + padding: 10px; + background-color: #FFF; + border: 1px solid #CCC; +} + +.frmRow { + margin-bottom: 10px; +} + +#templatesrc { + border: none; + width: 320px; + height: 240px; +} + +.title { + padding-bottom: 5px; +} + +.mceActionPanel { + padding-top: 5px; +} diff --git a/src/core/static/js/tiny_mce/plugins/template/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/template/editor_plugin.js new file mode 100644 index 0000000..ebe3c27 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/template/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.each;tinymce.create("tinymce.plugins.TemplatePlugin",{init:function(b,c){var d=this;d.editor=b;b.addCommand("mceTemplate",function(e){b.windowManager.open({file:c+"/template.htm",width:b.getParam("template_popup_width",750),height:b.getParam("template_popup_height",600),inline:1},{plugin_url:c})});b.addCommand("mceInsertTemplate",d._insertTemplate,d);b.addButton("template",{title:"template.desc",cmd:"mceTemplate"});b.onPreProcess.add(function(e,g){var f=e.dom;a(f.select("div",g.node),function(h){if(f.hasClass(h,"mceTmpl")){a(f.select("*",h),function(i){if(f.hasClass(i,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))){i.innerHTML=d._getDateTime(new Date(),e.getParam("template_mdate_format",e.getLang("template.mdate_format")))}});d._replaceVals(h)}})})},getInfo:function(){return{longname:"Template plugin",author:"Moxiecode Systems AB",authorurl:"http://www.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/template",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_insertTemplate:function(i,j){var k=this,g=k.editor,f,c,d=g.dom,b=g.selection.getContent();f=j.content;a(k.editor.getParam("template_replace_values"),function(l,h){if(typeof(l)!="function"){f=f.replace(new RegExp("\\{\\$"+h+"\\}","g"),l)}});c=d.create("div",null,f);n=d.select(".mceTmpl",c);if(n&&n.length>0){c=d.create("div",null);c.appendChild(n[0].cloneNode(true))}function e(l,h){return new RegExp("\\b"+h+"\\b","g").test(l.className)}a(d.select("*",c),function(h){if(e(h,g.getParam("template_cdate_classes","cdate").replace(/\s+/g,"|"))){h.innerHTML=k._getDateTime(new Date(),g.getParam("template_cdate_format",g.getLang("template.cdate_format")))}if(e(h,g.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))){h.innerHTML=k._getDateTime(new Date(),g.getParam("template_mdate_format",g.getLang("template.mdate_format")))}if(e(h,g.getParam("template_selected_content_classes","selcontent").replace(/\s+/g,"|"))){h.innerHTML=b}});k._replaceVals(c);g.execCommand("mceInsertContent",false,c.innerHTML);g.addVisual()},_replaceVals:function(c){var d=this.editor.dom,b=this.editor.getParam("template_replace_values");a(d.select("*",c),function(f){a(b,function(g,e){if(d.hasClass(f,e)){if(typeof(b[e])=="function"){b[e](f)}}})})},_getDateTime:function(e,b){if(!b){return""}function c(g,d){var f;g=""+g;if(g.length<d){for(f=0;f<(d-g.length);f++){g="0"+g}}return g}b=b.replace("%D","%m/%d/%y");b=b.replace("%r","%I:%M:%S %p");b=b.replace("%Y",""+e.getFullYear());b=b.replace("%y",""+e.getYear());b=b.replace("%m",c(e.getMonth()+1,2));b=b.replace("%d",c(e.getDate(),2));b=b.replace("%H",""+c(e.getHours(),2));b=b.replace("%M",""+c(e.getMinutes(),2));b=b.replace("%S",""+c(e.getSeconds(),2));b=b.replace("%I",""+((e.getHours()+11)%12+1));b=b.replace("%p",""+(e.getHours()<12?"AM":"PM"));b=b.replace("%B",""+this.editor.getLang("template_months_long").split(",")[e.getMonth()]);b=b.replace("%b",""+this.editor.getLang("template_months_short").split(",")[e.getMonth()]);b=b.replace("%A",""+this.editor.getLang("template_day_long").split(",")[e.getDay()]);b=b.replace("%a",""+this.editor.getLang("template_day_short").split(",")[e.getDay()]);b=b.replace("%%","%");return b}});tinymce.PluginManager.add("template",tinymce.plugins.TemplatePlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/template/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/template/editor_plugin_src.js new file mode 100644 index 0000000..9cac269 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/template/editor_plugin_src.js @@ -0,0 +1,159 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var each = tinymce.each; + + tinymce.create('tinymce.plugins.TemplatePlugin', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceTemplate', function(ui) { + ed.windowManager.open({ + file : url + '/template.htm', + width : ed.getParam('template_popup_width', 750), + height : ed.getParam('template_popup_height', 600), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceInsertTemplate', t._insertTemplate, t); + + // Register buttons + ed.addButton('template', {title : 'template.desc', cmd : 'mceTemplate'}); + + ed.onPreProcess.add(function(ed, o) { + var dom = ed.dom; + + each(dom.select('div', o.node), function(e) { + if (dom.hasClass(e, 'mceTmpl')) { + each(dom.select('*', e), function(e) { + if (dom.hasClass(e, ed.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|'))) + e.innerHTML = t._getDateTime(new Date(), ed.getParam("template_mdate_format", ed.getLang("template.mdate_format"))); + }); + + t._replaceVals(e); + } + }); + }); + }, + + getInfo : function() { + return { + longname : 'Template plugin', + author : 'Moxiecode Systems AB', + authorurl : 'http://www.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/template', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + _insertTemplate : function(ui, v) { + var t = this, ed = t.editor, h, el, dom = ed.dom, sel = ed.selection.getContent(); + + h = v.content; + + each(t.editor.getParam('template_replace_values'), function(v, k) { + if (typeof(v) != 'function') + h = h.replace(new RegExp('\\{\\$' + k + '\\}', 'g'), v); + }); + + el = dom.create('div', null, h); + + // Find template element within div + n = dom.select('.mceTmpl', el); + if (n && n.length > 0) { + el = dom.create('div', null); + el.appendChild(n[0].cloneNode(true)); + } + + function hasClass(n, c) { + return new RegExp('\\b' + c + '\\b', 'g').test(n.className); + }; + + each(dom.select('*', el), function(n) { + // Replace cdate + if (hasClass(n, ed.getParam('template_cdate_classes', 'cdate').replace(/\s+/g, '|'))) + n.innerHTML = t._getDateTime(new Date(), ed.getParam("template_cdate_format", ed.getLang("template.cdate_format"))); + + // Replace mdate + if (hasClass(n, ed.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|'))) + n.innerHTML = t._getDateTime(new Date(), ed.getParam("template_mdate_format", ed.getLang("template.mdate_format"))); + + // Replace selection + if (hasClass(n, ed.getParam('template_selected_content_classes', 'selcontent').replace(/\s+/g, '|'))) + n.innerHTML = sel; + }); + + t._replaceVals(el); + + ed.execCommand('mceInsertContent', false, el.innerHTML); + ed.addVisual(); + }, + + _replaceVals : function(e) { + var dom = this.editor.dom, vl = this.editor.getParam('template_replace_values'); + + each(dom.select('*', e), function(e) { + each(vl, function(v, k) { + if (dom.hasClass(e, k)) { + if (typeof(vl[k]) == 'function') + vl[k](e); + } + }); + }); + }, + + _getDateTime : function(d, fmt) { + if (!fmt) + return ""; + + function addZeros(value, len) { + var i; + + value = "" + value; + + if (value.length < len) { + for (i=0; i<(len-value.length); i++) + value = "0" + value; + } + + return value; + } + + fmt = fmt.replace("%D", "%m/%d/%y"); + fmt = fmt.replace("%r", "%I:%M:%S %p"); + fmt = fmt.replace("%Y", "" + d.getFullYear()); + fmt = fmt.replace("%y", "" + d.getYear()); + fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2)); + fmt = fmt.replace("%d", addZeros(d.getDate(), 2)); + fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2)); + fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2)); + fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2)); + fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1)); + fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM")); + fmt = fmt.replace("%B", "" + this.editor.getLang("template_months_long").split(',')[d.getMonth()]); + fmt = fmt.replace("%b", "" + this.editor.getLang("template_months_short").split(',')[d.getMonth()]); + fmt = fmt.replace("%A", "" + this.editor.getLang("template_day_long").split(',')[d.getDay()]); + fmt = fmt.replace("%a", "" + this.editor.getLang("template_day_short").split(',')[d.getDay()]); + fmt = fmt.replace("%%", "%"); + + return fmt; + } + }); + + // Register plugin + tinymce.PluginManager.add('template', tinymce.plugins.TemplatePlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/template/js/template.js b/src/core/static/js/tiny_mce/plugins/template/js/template.js new file mode 100644 index 0000000..bc3045d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/template/js/template.js @@ -0,0 +1,106 @@ +tinyMCEPopup.requireLangPack(); + +var TemplateDialog = { + preInit : function() { + var url = tinyMCEPopup.getParam("template_external_list_url"); + + if (url != null) + document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></sc'+'ript>'); + }, + + init : function() { + var ed = tinyMCEPopup.editor, tsrc, sel, x, u; + + tsrc = ed.getParam("template_templates", false); + sel = document.getElementById('tpath'); + + // Setup external template list + if (!tsrc && typeof(tinyMCETemplateList) != 'undefined') { + for (x=0, tsrc = []; x<tinyMCETemplateList.length; x++) + tsrc.push({title : tinyMCETemplateList[x][0], src : tinyMCETemplateList[x][1], description : tinyMCETemplateList[x][2]}); + } + + for (x=0; x<tsrc.length; x++) + sel.options[sel.options.length] = new Option(tsrc[x].title, tinyMCEPopup.editor.documentBaseURI.toAbsolute(tsrc[x].src)); + + this.resize(); + this.tsrc = tsrc; + }, + + resize : function() { + var w, h, e; + + if (!self.innerWidth) { + w = document.body.clientWidth - 50; + h = document.body.clientHeight - 160; + } else { + w = self.innerWidth - 50; + h = self.innerHeight - 170; + } + + e = document.getElementById('templatesrc'); + + if (e) { + e.style.height = Math.abs(h) + 'px'; + e.style.width = Math.abs(w - 5) + 'px'; + } + }, + + loadCSSFiles : function(d) { + var ed = tinyMCEPopup.editor; + + tinymce.each(ed.getParam("content_css", '').split(','), function(u) { + d.write('<link href="' + ed.documentBaseURI.toAbsolute(u) + '" rel="stylesheet" type="text/css" />'); + }); + }, + + selectTemplate : function(u, ti) { + var d = window.frames['templatesrc'].document, x, tsrc = this.tsrc; + + if (!u) + return; + + d.body.innerHTML = this.templateHTML = this.getFileContents(u); + + for (x=0; x<tsrc.length; x++) { + if (tsrc[x].title == ti) + document.getElementById('tmpldesc').innerHTML = tsrc[x].description || ''; + } + }, + + insert : function() { + tinyMCEPopup.execCommand('mceInsertTemplate', false, { + content : this.templateHTML, + selection : tinyMCEPopup.editor.selection.getContent() + }); + + tinyMCEPopup.close(); + }, + + getFileContents : function(u) { + var x, d, t = 'text/plain'; + + function g(s) { + x = 0; + + try { + x = new ActiveXObject(s); + } catch (s) { + } + + return x; + }; + + x = window.ActiveXObject ? g('Msxml2.XMLHTTP') || g('Microsoft.XMLHTTP') : new XMLHttpRequest(); + + // Synchronous AJAX load file + x.overrideMimeType && x.overrideMimeType(t); + x.open("GET", u, false); + x.send(null); + + return x.responseText; + } +}; + +TemplateDialog.preInit(); +tinyMCEPopup.onInit.add(TemplateDialog.init, TemplateDialog); diff --git a/src/core/static/js/tiny_mce/plugins/template/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/template/langs/de_dlg.js new file mode 100755 index 0000000..04c9fa1 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/template/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.template_dlg',{title:"Vorlagen",label:"Vorlage","desc_label":"Beschreibung",desc:"Inhalt aus Vorlage einf\u00fcgen",select:"Vorlage ausw\u00e4hlen",preview:"Vorschau",warning:"Warnung: Eine Vorlage mit einer anderen zu aktualisieren kann zu einem Datenverlust f\u00fchren!","mdate_format":"%Y-%m-%d %H:%M:%S","cdate_format":"%Y-%m-%d %H:%M:%S","months_long":"Januar,Februar,M\u00e4rz,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember","months_short":"Jan,Feb,M\u00e4r,Apr,Mai,Juni,Juli,Aug,Sept,Okt,Nov,Dez","day_long":"Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag,Sonntag","day_short":"So,Mo,Di,Mi,Do,Fr,Sa,So"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/template/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/template/langs/en_dlg.js new file mode 100755 index 0000000..83e599d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/template/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.template_dlg',{title:"Templates",label:"Template","desc_label":"Description",desc:"Insert Predefined Template Content",select:"Select a Template",preview:"Preview",warning:"Warning: Updating a template with a different one may cause data loss.","mdate_format":"%Y-%m-%d %H:%M:%S","cdate_format":"%Y-%m-%d %H:%M:%S","months_long":"January,February,March,April,May,June,July,August,September,October,November,December","months_short":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","day_long":"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday","day_short":"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/template/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/template/langs/fr_dlg.js new file mode 100755 index 0000000..a9ee124 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/template/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.template_dlg',{title:"Mod\u00e8les",label:"Mod\u00e8le","desc_label":"Description",desc:"Ins\u00e9rer un mod\u00e8le pr\u00e9d\u00e9fini",select:"Choisir un mod\u00e8le",preview:"Pr\u00e9visualisation",warning:"Attention : Mettre \u00e0 jour un mod\u00e8le pour un autre peut entra\u00eener une perte de donn\u00e9es !","mdate_format":"%d/%m/%Y %H:%M:%S","cdate_format":"%d/%m/%Y %H:%M:%S","months_long":"Janvier,F\u00e9vrier,Mars,Avril,Mai,Juin,Juillet,Ao\u00fbt,Septembre,Octobre,Novembre,D\u00e9cembre","months_short":"Jan,F\u00e9v,Mar,Avr,Mai,Juin,Juil,Ao\u00fbt,Sep,Oct,Nov,D\u00e9c","day_long":"Dimanche,Lundi,Mardi,Mercredi,Jeudi,Vendredi,Samedi,Dimanche","day_short":"Dim,Lun,Mar,Mer,Jeu,Ven,Sam,Dim"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/template/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/template/langs/it_dlg.js new file mode 100755 index 0000000..78abd1f --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/template/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.template_dlg',{title:"Modelli",label:"Modello","desc_label":"Descrizione",desc:"Inserisci contenuto da modello predefinito",select:"Seleziona un modello",preview:"Anteprima",warning:"Attenzione: Aggiornare un modello con un altro differente pu\u00f2 causare perdite di dati.","mdate_format":"%Y-%m-%d %H:%M:%S","cdate_format":"%Y-%m-%d %H:%M:%S","months_long":"Gennaio,Febbraio,Marzo,Aprile,Maggio,Giugno,Luglio,Agosto,Settembre,Ottobre,Novembre,Dicembre","months_short":"Gen,Feb,Mar,Apr,Mag,Giu,Lug,Ago,Set,Ott,Nov,Dic","day_long":"Domenica,Luned\u00ec,Marted\u00ec,Mercoled\u00ec,Gioved\u00ec,Venerd\u00ec,Sabato,Domenica","day_short":"Dom,Lun,Mar,Mer,Gio,Ven,Sab,Dom"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/template/template.htm b/src/core/static/js/tiny_mce/plugins/template/template.htm new file mode 100644 index 0000000..b2182e6 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/template/template.htm @@ -0,0 +1,31 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#template_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/template.js"></script> + <link href="css/template.css" rel="stylesheet" type="text/css" /> +</head> +<body onresize="TemplateDialog.resize();"> + <form onsubmit="TemplateDialog.insert();return false;"> + <div id="frmbody"> + <div class="title">{#template_dlg.desc}</div> + <div class="frmRow"><label for="tpath" title="{#template_dlg.select}">{#template_dlg.label}:</label> + <select id="tpath" name="tpath" onchange="TemplateDialog.selectTemplate(this.options[this.selectedIndex].value, this.options[this.selectedIndex].text);" class="mceFocus"> + <option value="">{#template_dlg.select}...</option> + </select> + <span id="warning"></span></div> + <div class="frmRow"><label for="tdesc">{#template_dlg.desc_label}:</label> + <span id="tmpldesc"></span></div> + <fieldset> + <legend>{#template_dlg.preview}</legend> + <iframe id="templatesrc" name="templatesrc" src="blank.htm" width="690" height="400" frameborder="0"></iframe> + </fieldset> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/visualchars/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/visualchars/editor_plugin.js new file mode 100644 index 0000000..1a148e8 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/visualchars/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.VisualChars",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceVisualChars",c._toggleVisualChars,c);a.addButton("visualchars",{title:"visualchars.desc",cmd:"mceVisualChars"});a.onBeforeGetContent.add(function(d,e){if(c.state&&e.format!="raw"&&!e.draft){c.state=true;c._toggleVisualChars(false)}})},getInfo:function(){return{longname:"Visual characters",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/visualchars",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_toggleVisualChars:function(m){var p=this,k=p.editor,a,g,j,n=k.getDoc(),o=k.getBody(),l,q=k.selection,e,c,f;p.state=!p.state;k.controlManager.setActive("visualchars",p.state);if(m){f=q.getBookmark()}if(p.state){a=[];tinymce.walk(o,function(b){if(b.nodeType==3&&b.nodeValue&&b.nodeValue.indexOf("\u00a0")!=-1){a.push(b)}},"childNodes");for(g=0;g<a.length;g++){l=a[g].nodeValue;l=l.replace(/(\u00a0)/g,'<span data-mce-bogus="1" class="mceItemHidden mceItemNbsp">$1</span>');c=k.dom.create("div",null,l);while(node=c.lastChild){k.dom.insertAfter(node,a[g])}k.dom.remove(a[g])}}else{a=k.dom.select("span.mceItemNbsp",o);for(g=a.length-1;g>=0;g--){k.dom.remove(a[g],1)}}q.moveToBookmark(f)}});tinymce.PluginManager.add("visualchars",tinymce.plugins.VisualChars)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/visualchars/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/visualchars/editor_plugin_src.js new file mode 100644 index 0000000..df98590 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/visualchars/editor_plugin_src.js @@ -0,0 +1,83 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.VisualChars', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceVisualChars', t._toggleVisualChars, t); + + // Register buttons + ed.addButton('visualchars', {title : 'visualchars.desc', cmd : 'mceVisualChars'}); + + ed.onBeforeGetContent.add(function(ed, o) { + if (t.state && o.format != 'raw' && !o.draft) { + t.state = true; + t._toggleVisualChars(false); + } + }); + }, + + getInfo : function() { + return { + longname : 'Visual characters', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/visualchars', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + _toggleVisualChars : function(bookmark) { + var t = this, ed = t.editor, nl, i, h, d = ed.getDoc(), b = ed.getBody(), nv, s = ed.selection, bo, div, bm; + + t.state = !t.state; + ed.controlManager.setActive('visualchars', t.state); + + if (bookmark) + bm = s.getBookmark(); + + if (t.state) { + nl = []; + tinymce.walk(b, function(n) { + if (n.nodeType == 3 && n.nodeValue && n.nodeValue.indexOf('\u00a0') != -1) + nl.push(n); + }, 'childNodes'); + + for (i = 0; i < nl.length; i++) { + nv = nl[i].nodeValue; + nv = nv.replace(/(\u00a0)/g, '<span data-mce-bogus="1" class="mceItemHidden mceItemNbsp">$1</span>'); + + div = ed.dom.create('div', null, nv); + while (node = div.lastChild) + ed.dom.insertAfter(node, nl[i]); + + ed.dom.remove(nl[i]); + } + } else { + nl = ed.dom.select('span.mceItemNbsp', b); + + for (i = nl.length - 1; i >= 0; i--) + ed.dom.remove(nl[i], 1); + } + + s.moveToBookmark(bm); + } + }); + + // Register plugin + tinymce.PluginManager.add('visualchars', tinymce.plugins.VisualChars); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/wordcount/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/wordcount/editor_plugin.js new file mode 100644 index 0000000..a752ad3 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/wordcount/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.WordCount",{block:0,id:null,countre:null,cleanre:null,init:function(a,b){var c=this,d=0;c.countre=a.getParam("wordcount_countregex",/[\w\u2019\'-]+/g);c.cleanre=a.getParam("wordcount_cleanregex",/[0-9.(),;:!?%#$?\'\"_+=\\\/-]*/g);c.id=a.id+"-word-count";a.onPostRender.add(function(f,e){var g,h;h=f.getParam("wordcount_target_id");if(!h){g=tinymce.DOM.get(f.id+"_path_row");if(g){tinymce.DOM.add(g.parentNode,"div",{style:"float: right"},f.getLang("wordcount.words","Words: ")+'<span id="'+c.id+'">0</span>')}}else{tinymce.DOM.add(h,"span",{},'<span id="'+c.id+'">0</span>')}});a.onInit.add(function(e){e.selection.onSetContent.add(function(){c._count(e)});c._count(e)});a.onSetContent.add(function(e){c._count(e)});a.onKeyUp.add(function(f,g){if(g.keyCode==d){return}if(13==g.keyCode||8==d||46==d){c._count(f)}d=g.keyCode})},_getCount:function(c){var a=0;var b=c.getContent({format:"raw"});if(b){b=b.replace(/\.\.\./g," ");b=b.replace(/<.[^<>]*?>/g," ").replace(/&nbsp;|&#160;/gi," ");b=b.replace(/(\w+)(&.+?;)+(\w+)/,"$1$3").replace(/&.+?;/g," ");b=b.replace(this.cleanre,"");var d=b.match(this.countre);if(d){a=d.length}}return a},_count:function(a){var b=this;if(b.block){return}b.block=1;setTimeout(function(){if(!a.destroyed){var c=b._getCount(a);tinymce.DOM.setHTML(b.id,c.toString());setTimeout(function(){b.block=0},2000)}},1)},getInfo:function(){return{longname:"Word Count plugin",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/wordcount",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("wordcount",tinymce.plugins.WordCount)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/wordcount/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/wordcount/editor_plugin_src.js new file mode 100644 index 0000000..e94743b --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/wordcount/editor_plugin_src.js @@ -0,0 +1,114 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.WordCount', { + block : 0, + id : null, + countre : null, + cleanre : null, + + init : function(ed, url) { + var t = this, last = 0; + + t.countre = ed.getParam('wordcount_countregex', /[\w\u2019\'-]+/g); // u2019 == &rsquo; + t.cleanre = ed.getParam('wordcount_cleanregex', /[0-9.(),;:!?%#$?\'\"_+=\\\/-]*/g); + t.id = ed.id + '-word-count'; + + ed.onPostRender.add(function(ed, cm) { + var row, id; + + // Add it to the specified id or the theme advanced path + id = ed.getParam('wordcount_target_id'); + if (!id) { + row = tinymce.DOM.get(ed.id + '_path_row'); + + if (row) + tinymce.DOM.add(row.parentNode, 'div', {'style': 'float: right'}, ed.getLang('wordcount.words', 'Words: ') + '<span id="' + t.id + '">0</span>'); + } else { + tinymce.DOM.add(id, 'span', {}, '<span id="' + t.id + '">0</span>'); + } + }); + + ed.onInit.add(function(ed) { + ed.selection.onSetContent.add(function() { + t._count(ed); + }); + + t._count(ed); + }); + + ed.onSetContent.add(function(ed) { + t._count(ed); + }); + + ed.onKeyUp.add(function(ed, e) { + if (e.keyCode == last) + return; + + if (13 == e.keyCode || 8 == last || 46 == last) + t._count(ed); + + last = e.keyCode; + }); + }, + + _getCount : function(ed) { + var tc = 0; + var tx = ed.getContent({ format: 'raw' }); + + if (tx) { + tx = tx.replace(/\.\.\./g, ' '); // convert ellipses to spaces + tx = tx.replace(/<.[^<>]*?>/g, ' ').replace(/&nbsp;|&#160;/gi, ' '); // remove html tags and space chars + + // deal with html entities + tx = tx.replace(/(\w+)(&.+?;)+(\w+)/, "$1$3").replace(/&.+?;/g, ' '); + tx = tx.replace(this.cleanre, ''); // remove numbers and punctuation + + var wordArray = tx.match(this.countre); + if (wordArray) { + tc = wordArray.length; + } + } + + return tc; + }, + + _count : function(ed) { + var t = this; + + // Keep multiple calls from happening at the same time + if (t.block) + return; + + t.block = 1; + + setTimeout(function() { + if (!ed.destroyed) { + var tc = t._getCount(ed); + tinymce.DOM.setHTML(t.id, tc.toString()); + setTimeout(function() {t.block = 0;}, 2000); + } + }, 1); + }, + + getInfo: function() { + return { + longname : 'Word Count plugin', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/wordcount', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + tinymce.PluginManager.add('wordcount', tinymce.plugins.WordCount); +})(); diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/abbr.htm b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/abbr.htm new file mode 100644 index 0000000..30a894f --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/abbr.htm @@ -0,0 +1,142 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.title_abbr_element}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/element_common.js"></script> + <script type="text/javascript" src="js/abbr.js"></script> + <link rel="stylesheet" type="text/css" href="css/popup.css" /> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_abbr_element}</span> +<form onsubmit="insertAbbr();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li> + <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> --> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> + <td> + <select id="class" name="class" class="field mceEditableSelect"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir" class="field"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" class="field" /> + </td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeAbbr();" style="display: none;" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/acronym.htm b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/acronym.htm new file mode 100644 index 0000000..c109345 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/acronym.htm @@ -0,0 +1,142 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.title_acronym_element}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/element_common.js"></script> + <script type="text/javascript" src="js/acronym.js"></script> + <link rel="stylesheet" type="text/css" href="css/popup.css" /> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_acronym_element}</span> +<form onsubmit="insertAcronym();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li> + <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> --> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> + <td> + <select id="class" name="class" class="field mceEditableSelect"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir" class="field"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" class="field" /> + </td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeAcronym();" style="display: none;" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/attributes.htm b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/attributes.htm new file mode 100644 index 0000000..e8d606a --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/attributes.htm @@ -0,0 +1,149 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.attribs_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="js/attributes.js"></script> + <link rel="stylesheet" type="text/css" href="css/attributes.css" /> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.attribs_title}</span> +<form onsubmit="insertAction();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.attribute_attrib_tab}</a></span></li> + <li id="events_tab" aria-controls="events_panel"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.attribute_events_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.attribute_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="mceFocus" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" /></td> + </tr> + <tr> + <td><label id="classlabel" for="classlist">{#class_name}</label></td> + <td> + <select id="classlist" name="classlist" class="mceEditableSelect"> + <option value="" selected="selected">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" /> + </td> + </tr> + <tr> + <td><label id="tabindexlabel" for="tabindex">{#xhtmlxtras_dlg.attribute_label_tabindex}</label></td> + <td><input type="text" id="tabindex" name="tabindex" value="" /></td> + </tr> + + <tr> + <td><label id="accesskeylabel" for="accesskey">{#xhtmlxtras_dlg.attribute_label_accesskey}</label></td> + <td><input type="text" id="accesskey" name="accesskey" value="" /></td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.attribute_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/cite.htm b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/cite.htm new file mode 100644 index 0000000..0ac6bdb --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/cite.htm @@ -0,0 +1,142 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.title_cite_element}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/element_common.js"></script> + <script type="text/javascript" src="js/cite.js"></script> + <link rel="stylesheet" type="text/css" href="css/popup.css" /> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_cite_element}</span> +<form onsubmit="insertCite();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li> + <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> --> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> + <td> + <select id="class" name="class" class="field mceEditableSelect"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir" class="field"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" class="field" /> + </td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeCite();" style="display: none;" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/css/attributes.css b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/css/attributes.css new file mode 100644 index 0000000..9a6a235 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/css/attributes.css @@ -0,0 +1,11 @@ +.panel_wrapper div.current { + height: 290px; +} + +#id, #style, #title, #dir, #hreflang, #lang, #classlist, #tabindex, #accesskey { + width: 200px; +} + +#events_panel input { + width: 200px; +} diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/css/popup.css b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/css/popup.css new file mode 100644 index 0000000..e67114d --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/css/popup.css @@ -0,0 +1,9 @@ +input.field, select.field {width:200px;} +input.picker {width:179px; margin-left: 5px;} +input.disabled {border-color:#F2F2F2;} +img.picker {vertical-align:text-bottom; cursor:pointer;} +h1 {padding: 0 0 5px 0;} +.panel_wrapper div.current {height:160px;} +#xhtmlxtrasdel .panel_wrapper div.current, #xhtmlxtrasins .panel_wrapper div.current {height: 230px;} +a.browse span {display:block; width:20px; height:20px; background:url('../../../themes/advanced/img/icons.gif') -140px -20px;} +#datetime {width:180px;} diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/del.htm b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/del.htm new file mode 100644 index 0000000..5f66751 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/del.htm @@ -0,0 +1,162 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.title_del_element}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/element_common.js"></script> + <script type="text/javascript" src="js/del.js"></script> + <link rel="stylesheet" type="text/css" href="css/popup.css" /> +</head> +<body id="xhtmlxtrasins" style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_del_element}</span> +<form onsubmit="insertDel();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li> + <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> --> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_general_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="datetimelabel" for="datetime">{#xhtmlxtras_dlg.attribute_label_datetime}</label>:</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="datetime" name="datetime" type="text" value="" maxlength="19" class="field mceFocus" /></td> + <td><a href="javascript:insertDateTime('datetime');" onmousedown="return false;" class="browse" role="button" aria-labelledby="datetimelabel"><span class="datetime" title="{#xhtmlxtras_dlg.insert_date}"></span></a></td> + </tr> + </table> + </td> + </tr> + <tr> + <td class="label"><label id="citelabel" for="cite">{#xhtmlxtras_dlg.attribute_label_cite}</label>:</td> + <td><input id="cite" name="cite" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> + <td> + <select id="class" name="class" class="field mceEditableSelect"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir" class="field"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" class="field" /> + </td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeDel();" style="display: none;" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/editor_plugin.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/editor_plugin.js new file mode 100644 index 0000000..9b98a51 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.XHTMLXtrasPlugin",{init:function(a,b){a.addCommand("mceCite",function(){a.windowManager.open({file:b+"/cite.htm",width:350+parseInt(a.getLang("xhtmlxtras.cite_delta_width",0)),height:250+parseInt(a.getLang("xhtmlxtras.cite_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceAcronym",function(){a.windowManager.open({file:b+"/acronym.htm",width:350+parseInt(a.getLang("xhtmlxtras.acronym_delta_width",0)),height:250+parseInt(a.getLang("xhtmlxtras.acronym_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceAbbr",function(){a.windowManager.open({file:b+"/abbr.htm",width:350+parseInt(a.getLang("xhtmlxtras.abbr_delta_width",0)),height:250+parseInt(a.getLang("xhtmlxtras.abbr_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceDel",function(){a.windowManager.open({file:b+"/del.htm",width:340+parseInt(a.getLang("xhtmlxtras.del_delta_width",0)),height:310+parseInt(a.getLang("xhtmlxtras.del_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceIns",function(){a.windowManager.open({file:b+"/ins.htm",width:340+parseInt(a.getLang("xhtmlxtras.ins_delta_width",0)),height:310+parseInt(a.getLang("xhtmlxtras.ins_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceAttributes",function(){a.windowManager.open({file:b+"/attributes.htm",width:380+parseInt(a.getLang("xhtmlxtras.attr_delta_width",0)),height:370+parseInt(a.getLang("xhtmlxtras.attr_delta_height",0)),inline:1},{plugin_url:b})});a.addButton("cite",{title:"xhtmlxtras.cite_desc",cmd:"mceCite"});a.addButton("acronym",{title:"xhtmlxtras.acronym_desc",cmd:"mceAcronym"});a.addButton("abbr",{title:"xhtmlxtras.abbr_desc",cmd:"mceAbbr"});a.addButton("del",{title:"xhtmlxtras.del_desc",cmd:"mceDel"});a.addButton("ins",{title:"xhtmlxtras.ins_desc",cmd:"mceIns"});a.addButton("attribs",{title:"xhtmlxtras.attribs_desc",cmd:"mceAttributes"});a.onNodeChange.add(function(d,c,f,e){f=d.dom.getParent(f,"CITE,ACRONYM,ABBR,DEL,INS");c.setDisabled("cite",e);c.setDisabled("acronym",e);c.setDisabled("abbr",e);c.setDisabled("del",e);c.setDisabled("ins",e);c.setDisabled("attribs",f&&f.nodeName=="BODY");c.setActive("cite",0);c.setActive("acronym",0);c.setActive("abbr",0);c.setActive("del",0);c.setActive("ins",0);if(f){do{c.setDisabled(f.nodeName.toLowerCase(),0);c.setActive(f.nodeName.toLowerCase(),1)}while(f=f.parentNode)}});a.onPreInit.add(function(){a.dom.create("abbr")})},getInfo:function(){return{longname:"XHTML Xtras Plugin",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("xhtmlxtras",tinymce.plugins.XHTMLXtrasPlugin)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js new file mode 100644 index 0000000..f240572 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js @@ -0,0 +1,132 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.XHTMLXtrasPlugin', { + init : function(ed, url) { + // Register commands + ed.addCommand('mceCite', function() { + ed.windowManager.open({ + file : url + '/cite.htm', + width : 350 + parseInt(ed.getLang('xhtmlxtras.cite_delta_width', 0)), + height : 250 + parseInt(ed.getLang('xhtmlxtras.cite_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceAcronym', function() { + ed.windowManager.open({ + file : url + '/acronym.htm', + width : 350 + parseInt(ed.getLang('xhtmlxtras.acronym_delta_width', 0)), + height : 250 + parseInt(ed.getLang('xhtmlxtras.acronym_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceAbbr', function() { + ed.windowManager.open({ + file : url + '/abbr.htm', + width : 350 + parseInt(ed.getLang('xhtmlxtras.abbr_delta_width', 0)), + height : 250 + parseInt(ed.getLang('xhtmlxtras.abbr_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceDel', function() { + ed.windowManager.open({ + file : url + '/del.htm', + width : 340 + parseInt(ed.getLang('xhtmlxtras.del_delta_width', 0)), + height : 310 + parseInt(ed.getLang('xhtmlxtras.del_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceIns', function() { + ed.windowManager.open({ + file : url + '/ins.htm', + width : 340 + parseInt(ed.getLang('xhtmlxtras.ins_delta_width', 0)), + height : 310 + parseInt(ed.getLang('xhtmlxtras.ins_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceAttributes', function() { + ed.windowManager.open({ + file : url + '/attributes.htm', + width : 380 + parseInt(ed.getLang('xhtmlxtras.attr_delta_width', 0)), + height : 370 + parseInt(ed.getLang('xhtmlxtras.attr_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('cite', {title : 'xhtmlxtras.cite_desc', cmd : 'mceCite'}); + ed.addButton('acronym', {title : 'xhtmlxtras.acronym_desc', cmd : 'mceAcronym'}); + ed.addButton('abbr', {title : 'xhtmlxtras.abbr_desc', cmd : 'mceAbbr'}); + ed.addButton('del', {title : 'xhtmlxtras.del_desc', cmd : 'mceDel'}); + ed.addButton('ins', {title : 'xhtmlxtras.ins_desc', cmd : 'mceIns'}); + ed.addButton('attribs', {title : 'xhtmlxtras.attribs_desc', cmd : 'mceAttributes'}); + + ed.onNodeChange.add(function(ed, cm, n, co) { + n = ed.dom.getParent(n, 'CITE,ACRONYM,ABBR,DEL,INS'); + + cm.setDisabled('cite', co); + cm.setDisabled('acronym', co); + cm.setDisabled('abbr', co); + cm.setDisabled('del', co); + cm.setDisabled('ins', co); + cm.setDisabled('attribs', n && n.nodeName == 'BODY'); + cm.setActive('cite', 0); + cm.setActive('acronym', 0); + cm.setActive('abbr', 0); + cm.setActive('del', 0); + cm.setActive('ins', 0); + + // Activate all + if (n) { + do { + cm.setDisabled(n.nodeName.toLowerCase(), 0); + cm.setActive(n.nodeName.toLowerCase(), 1); + } while (n = n.parentNode); + } + }); + + ed.onPreInit.add(function() { + // Fixed IE issue where it can't handle these elements correctly + ed.dom.create('abbr'); + }); + }, + + getInfo : function() { + return { + longname : 'XHTML Xtras Plugin', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('xhtmlxtras', tinymce.plugins.XHTMLXtrasPlugin); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/ins.htm b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/ins.htm new file mode 100644 index 0000000..d001ac7 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/ins.htm @@ -0,0 +1,162 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.title_ins_element}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/element_common.js"></script> + <script type="text/javascript" src="js/ins.js"></script> + <link rel="stylesheet" type="text/css" href="css/popup.css" /> +</head> +<body id="xhtmlxtrasins" style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_ins_element}</span> +<form onsubmit="insertIns();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li> + <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> --> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_general_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="datetimelabel" for="datetime">{#xhtmlxtras_dlg.attribute_label_datetime}</label>:</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="datetime" name="datetime" type="text" value="" maxlength="19" class="field mceFocus" /></td> + <td ><a href="javascript:insertDateTime('datetime');" onmousedown="return false;" class="browse" role="button" aria-labelledby="datetimelabel"><span class="datetime" title="{#xhtmlxtras_dlg.insert_date}"></span></a></td> + </tr> + </table> + </td> + </tr> + <tr > + <td class="label"><label id="citelabel" for="cite">{#xhtmlxtras_dlg.attribute_label_cite}</label>:</td> + <td><input id="cite" name="cite" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> + <td> + <select id="class" name="class" class="field mceEditableSelect"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir" class="field"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" class="field" /> + </td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeIns();" style="display: none;" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/abbr.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/abbr.js new file mode 100644 index 0000000..4b51a25 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/abbr.js @@ -0,0 +1,28 @@ +/** + * abbr.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + SXE.initElementDialog('abbr'); + if (SXE.currentAction == "update") { + SXE.showRemoveButton(); + } +} + +function insertAbbr() { + SXE.insertElement('abbr'); + tinyMCEPopup.close(); +} + +function removeAbbr() { + SXE.removeElement('abbr'); + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/acronym.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/acronym.js new file mode 100644 index 0000000..6ec2f88 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/acronym.js @@ -0,0 +1,28 @@ +/** + * acronym.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + SXE.initElementDialog('acronym'); + if (SXE.currentAction == "update") { + SXE.showRemoveButton(); + } +} + +function insertAcronym() { + SXE.insertElement('acronym'); + tinyMCEPopup.close(); +} + +function removeAcronym() { + SXE.removeElement('acronym'); + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/attributes.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/attributes.js new file mode 100644 index 0000000..9c99995 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/attributes.js @@ -0,0 +1,111 @@ +/** + * attributes.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + tinyMCEPopup.resizeToInnerSize(); + var inst = tinyMCEPopup.editor; + var dom = inst.dom; + var elm = inst.selection.getNode(); + var f = document.forms[0]; + var onclick = dom.getAttrib(elm, 'onclick'); + + setFormValue('title', dom.getAttrib(elm, 'title')); + setFormValue('id', dom.getAttrib(elm, 'id')); + setFormValue('style', dom.getAttrib(elm, "style")); + setFormValue('dir', dom.getAttrib(elm, 'dir')); + setFormValue('lang', dom.getAttrib(elm, 'lang')); + setFormValue('tabindex', dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : "")); + setFormValue('accesskey', dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : "")); + setFormValue('onfocus', dom.getAttrib(elm, 'onfocus')); + setFormValue('onblur', dom.getAttrib(elm, 'onblur')); + setFormValue('onclick', onclick); + setFormValue('ondblclick', dom.getAttrib(elm, 'ondblclick')); + setFormValue('onmousedown', dom.getAttrib(elm, 'onmousedown')); + setFormValue('onmouseup', dom.getAttrib(elm, 'onmouseup')); + setFormValue('onmouseover', dom.getAttrib(elm, 'onmouseover')); + setFormValue('onmousemove', dom.getAttrib(elm, 'onmousemove')); + setFormValue('onmouseout', dom.getAttrib(elm, 'onmouseout')); + setFormValue('onkeypress', dom.getAttrib(elm, 'onkeypress')); + setFormValue('onkeydown', dom.getAttrib(elm, 'onkeydown')); + setFormValue('onkeyup', dom.getAttrib(elm, 'onkeyup')); + className = dom.getAttrib(elm, 'class'); + + addClassesToList('classlist', 'advlink_styles'); + selectByValue(f, 'classlist', className, true); + + TinyMCE_EditableSelects.init(); +} + +function setFormValue(name, value) { + if(value && document.forms[0].elements[name]){ + document.forms[0].elements[name].value = value; + } +} + +function insertAction() { + var inst = tinyMCEPopup.editor; + var elm = inst.selection.getNode(); + + setAllAttribs(elm); + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); +} + +function setAttrib(elm, attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib.toLowerCase()]; + var inst = tinyMCEPopup.editor; + var dom = inst.dom; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + dom.setAttrib(elm, attrib.toLowerCase(), value); +} + +function setAllAttribs(elm) { + var f = document.forms[0]; + + setAttrib(elm, 'title'); + setAttrib(elm, 'id'); + setAttrib(elm, 'style'); + setAttrib(elm, 'class', getSelectValue(f, 'classlist')); + setAttrib(elm, 'dir'); + setAttrib(elm, 'lang'); + setAttrib(elm, 'tabindex'); + setAttrib(elm, 'accesskey'); + setAttrib(elm, 'onfocus'); + setAttrib(elm, 'onblur'); + setAttrib(elm, 'onclick'); + setAttrib(elm, 'ondblclick'); + setAttrib(elm, 'onmousedown'); + setAttrib(elm, 'onmouseup'); + setAttrib(elm, 'onmouseover'); + setAttrib(elm, 'onmousemove'); + setAttrib(elm, 'onmouseout'); + setAttrib(elm, 'onkeypress'); + setAttrib(elm, 'onkeydown'); + setAttrib(elm, 'onkeyup'); + + // Refresh in old MSIE +// if (tinyMCE.isMSIE5) +// elm.outerHTML = elm.outerHTML; +} + +function insertAttribute() { + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); +tinyMCEPopup.requireLangPack(); diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/cite.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/cite.js new file mode 100644 index 0000000..009b715 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/cite.js @@ -0,0 +1,28 @@ +/** + * cite.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + SXE.initElementDialog('cite'); + if (SXE.currentAction == "update") { + SXE.showRemoveButton(); + } +} + +function insertCite() { + SXE.insertElement('cite'); + tinyMCEPopup.close(); +} + +function removeCite() { + SXE.removeElement('cite'); + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/del.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/del.js new file mode 100644 index 0000000..1f957dc --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/del.js @@ -0,0 +1,53 @@ +/** + * del.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + SXE.initElementDialog('del'); + if (SXE.currentAction == "update") { + setFormValue('datetime', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'datetime')); + setFormValue('cite', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'cite')); + SXE.showRemoveButton(); + } +} + +function setElementAttribs(elm) { + setAllCommonAttribs(elm); + setAttrib(elm, 'datetime'); + setAttrib(elm, 'cite'); + elm.removeAttribute('data-mce-new'); +} + +function insertDel() { + var elm = tinyMCEPopup.editor.dom.getParent(SXE.focusElement, 'DEL'); + + if (elm == null) { + var s = SXE.inst.selection.getContent(); + if(s.length > 0) { + insertInlineElement('del'); + var elementArray = SXE.inst.dom.select('del[data-mce-new]'); + for (var i=0; i<elementArray.length; i++) { + var elm = elementArray[i]; + setElementAttribs(elm); + } + } + } else { + setElementAttribs(elm); + } + tinyMCEPopup.editor.nodeChanged(); + tinyMCEPopup.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); +} + +function removeDel() { + SXE.removeElement('del'); + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/element_common.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/element_common.js new file mode 100644 index 0000000..4e5d9c3 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/element_common.js @@ -0,0 +1,229 @@ +/** + * element_common.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +tinyMCEPopup.requireLangPack(); + +function initCommonAttributes(elm) { + var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom; + + // Setup form data for common element attributes + setFormValue('title', dom.getAttrib(elm, 'title')); + setFormValue('id', dom.getAttrib(elm, 'id')); + selectByValue(formObj, 'class', dom.getAttrib(elm, 'class'), true); + setFormValue('style', dom.getAttrib(elm, 'style')); + selectByValue(formObj, 'dir', dom.getAttrib(elm, 'dir')); + setFormValue('lang', dom.getAttrib(elm, 'lang')); + setFormValue('onfocus', dom.getAttrib(elm, 'onfocus')); + setFormValue('onblur', dom.getAttrib(elm, 'onblur')); + setFormValue('onclick', dom.getAttrib(elm, 'onclick')); + setFormValue('ondblclick', dom.getAttrib(elm, 'ondblclick')); + setFormValue('onmousedown', dom.getAttrib(elm, 'onmousedown')); + setFormValue('onmouseup', dom.getAttrib(elm, 'onmouseup')); + setFormValue('onmouseover', dom.getAttrib(elm, 'onmouseover')); + setFormValue('onmousemove', dom.getAttrib(elm, 'onmousemove')); + setFormValue('onmouseout', dom.getAttrib(elm, 'onmouseout')); + setFormValue('onkeypress', dom.getAttrib(elm, 'onkeypress')); + setFormValue('onkeydown', dom.getAttrib(elm, 'onkeydown')); + setFormValue('onkeyup', dom.getAttrib(elm, 'onkeyup')); +} + +function setFormValue(name, value) { + if(document.forms[0].elements[name]) document.forms[0].elements[name].value = value; +} + +function insertDateTime(id) { + document.getElementById(id).value = getDateTime(new Date(), "%Y-%m-%dT%H:%M:%S"); +} + +function getDateTime(d, fmt) { + fmt = fmt.replace("%D", "%m/%d/%y"); + fmt = fmt.replace("%r", "%I:%M:%S %p"); + fmt = fmt.replace("%Y", "" + d.getFullYear()); + fmt = fmt.replace("%y", "" + d.getYear()); + fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2)); + fmt = fmt.replace("%d", addZeros(d.getDate(), 2)); + fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2)); + fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2)); + fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2)); + fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1)); + fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM")); + fmt = fmt.replace("%%", "%"); + + return fmt; +} + +function addZeros(value, len) { + var i; + + value = "" + value; + + if (value.length < len) { + for (i=0; i<(len-value.length); i++) + value = "0" + value; + } + + return value; +} + +function selectByValue(form_obj, field_name, value, add_custom, ignore_case) { + if (!form_obj || !form_obj.elements[field_name]) + return; + + var sel = form_obj.elements[field_name]; + + var found = false; + for (var i=0; i<sel.options.length; i++) { + var option = sel.options[i]; + + if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) { + option.selected = true; + found = true; + } else + option.selected = false; + } + + if (!found && add_custom && value != '') { + var option = new Option('Value: ' + value, value); + option.selected = true; + sel.options[sel.options.length] = option; + } + + return found; +} + +function setAttrib(elm, attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib.toLowerCase()]; + tinyMCEPopup.editor.dom.setAttrib(elm, attrib, value || valueElm.value); +} + +function setAllCommonAttribs(elm) { + setAttrib(elm, 'title'); + setAttrib(elm, 'id'); + setAttrib(elm, 'class'); + setAttrib(elm, 'style'); + setAttrib(elm, 'dir'); + setAttrib(elm, 'lang'); + /*setAttrib(elm, 'onfocus'); + setAttrib(elm, 'onblur'); + setAttrib(elm, 'onclick'); + setAttrib(elm, 'ondblclick'); + setAttrib(elm, 'onmousedown'); + setAttrib(elm, 'onmouseup'); + setAttrib(elm, 'onmouseover'); + setAttrib(elm, 'onmousemove'); + setAttrib(elm, 'onmouseout'); + setAttrib(elm, 'onkeypress'); + setAttrib(elm, 'onkeydown'); + setAttrib(elm, 'onkeyup');*/ +} + +SXE = { + currentAction : "insert", + inst : tinyMCEPopup.editor, + updateElement : null +} + +SXE.focusElement = SXE.inst.selection.getNode(); + +SXE.initElementDialog = function(element_name) { + addClassesToList('class', 'xhtmlxtras_styles'); + TinyMCE_EditableSelects.init(); + + element_name = element_name.toLowerCase(); + var elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase()); + if (elm != null && elm.nodeName.toUpperCase() == element_name.toUpperCase()) { + SXE.currentAction = "update"; + } + + if (SXE.currentAction == "update") { + initCommonAttributes(elm); + SXE.updateElement = elm; + } + + document.forms[0].insert.value = tinyMCEPopup.getLang(SXE.currentAction, 'Insert', true); +} + +SXE.insertElement = function(element_name) { + var elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase()), h, tagName; + + if (elm == null) { + var s = SXE.inst.selection.getContent(); + if(s.length > 0) { + tagName = element_name; + + insertInlineElement(element_name); + var elementArray = tinymce.grep(SXE.inst.dom.select(element_name)); + for (var i=0; i<elementArray.length; i++) { + var elm = elementArray[i]; + + if (SXE.inst.dom.getAttrib(elm, 'data-mce-new')) { + elm.id = ''; + elm.setAttribute('id', ''); + elm.removeAttribute('id'); + elm.removeAttribute('data-mce-new'); + + setAllCommonAttribs(elm); + } + } + } + } else { + setAllCommonAttribs(elm); + } + SXE.inst.nodeChanged(); + tinyMCEPopup.execCommand('mceEndUndoLevel'); +} + +SXE.removeElement = function(element_name){ + element_name = element_name.toLowerCase(); + elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase()); + if(elm && elm.nodeName.toUpperCase() == element_name.toUpperCase()){ + tinyMCE.execCommand('mceRemoveNode', false, elm); + SXE.inst.nodeChanged(); + tinyMCEPopup.execCommand('mceEndUndoLevel'); + } +} + +SXE.showRemoveButton = function() { + document.getElementById("remove").style.display = ''; +} + +SXE.containsClass = function(elm,cl) { + return (elm.className.indexOf(cl) > -1) ? true : false; +} + +SXE.removeClass = function(elm,cl) { + if(elm.className == null || elm.className == "" || !SXE.containsClass(elm,cl)) { + return true; + } + var classNames = elm.className.split(" "); + var newClassNames = ""; + for (var x = 0, cnl = classNames.length; x < cnl; x++) { + if (classNames[x] != cl) { + newClassNames += (classNames[x] + " "); + } + } + elm.className = newClassNames.substring(0,newClassNames.length-1); //removes extra space at the end +} + +SXE.addClass = function(elm,cl) { + if(!SXE.containsClass(elm,cl)) elm.className ? elm.className += " " + cl : elm.className = cl; + return true; +} + +function insertInlineElement(en) { + var ed = tinyMCEPopup.editor, dom = ed.dom; + + ed.getDoc().execCommand('FontName', false, 'mceinline'); + tinymce.each(dom.select('span,font'), function(n) { + if (n.style.fontFamily == 'mceinline' || n.face == 'mceinline') + dom.replace(dom.create(en, {'data-mce-new' : 1}), n, 1); + }); +} diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/ins.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/ins.js new file mode 100644 index 0000000..c4addfb --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/js/ins.js @@ -0,0 +1,53 @@ +/** + * ins.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + SXE.initElementDialog('ins'); + if (SXE.currentAction == "update") { + setFormValue('datetime', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'datetime')); + setFormValue('cite', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'cite')); + SXE.showRemoveButton(); + } +} + +function setElementAttribs(elm) { + setAllCommonAttribs(elm); + setAttrib(elm, 'datetime'); + setAttrib(elm, 'cite'); + elm.removeAttribute('data-mce-new'); +} + +function insertIns() { + var elm = tinyMCEPopup.editor.dom.getParent(SXE.focusElement, 'INS'); + + if (elm == null) { + var s = SXE.inst.selection.getContent(); + if(s.length > 0) { + insertInlineElement('ins'); + var elementArray = SXE.inst.dom.select('ins[data-mce-new]'); + for (var i=0; i<elementArray.length; i++) { + var elm = elementArray[i]; + setElementAttribs(elm); + } + } + } else { + setElementAttribs(elm); + } + tinyMCEPopup.editor.nodeChanged(); + tinyMCEPopup.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); +} + +function removeIns() { + SXE.removeElement('ins'); + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/de_dlg.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/de_dlg.js new file mode 100755 index 0000000..4994355 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.xhtmlxtras_dlg',{"attribs_title":"Attribute einf\u00fcgen/bearbeiten","option_rtl":"Rechts nach links","option_ltr":"Links nach rechts","insert_date":"Aktuelle Zeit/Datum einf\u00fcgen",remove:"Entfernen","title_cite_element":"Quellenangabe","title_abbr_element":"Abk\u00fcrzung","title_acronym_element":"Akronym","title_del_element":"Entfernter Text","title_ins_element":"Eingef\u00fcgter Text","fieldset_events_tab":"Ereignisse","fieldset_attrib_tab":"Attribute","fieldset_general_tab":"Allgemeine Einstellungen","events_tab":"Ereignisse","attrib_tab":"Attribute","general_tab":"Allgemein","attribute_attrib_tab":"Attribute","attribute_events_tab":"Ereignisse","attribute_label_accesskey":"Tastenk\u00fcrzel","attribute_label_tabindex":"Tabindex","attribute_label_langcode":"Sprache","attribute_option_rtl":"Rechts nach links","attribute_option_ltr":"Links nach rechts","attribute_label_langdir":"Schriftrichtung","attribute_label_datetime":"Zeit/Datum","attribute_label_cite":"Quellenangabe","attribute_label_style":"Format","attribute_label_class":"Klasse","attribute_label_id":"ID","attribute_label_title":"Titel"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js new file mode 100755 index 0000000..c4569f8 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.xhtmlxtras_dlg',{"attribs_title":"Insert/Edit Attributes","option_rtl":"Right to Left","option_ltr":"Left to Right","insert_date":"Insert Current Date/Time",remove:"Remove","title_cite_element":"Citation Element","title_abbr_element":"Abbreviation Element","title_acronym_element":"Acronym Element","title_del_element":"Deletion Element","title_ins_element":"Insertion Element","fieldset_events_tab":"Element Events","fieldset_attrib_tab":"Element Attributes","fieldset_general_tab":"General Settings","events_tab":"Events","attrib_tab":"Attributes","general_tab":"General","attribute_attrib_tab":"Attributes","attribute_events_tab":"Events","attribute_label_accesskey":"AccessKey","attribute_label_tabindex":"TabIndex","attribute_label_langcode":"Language","attribute_option_rtl":"Right to Left","attribute_option_ltr":"Left to Right","attribute_label_langdir":"Text Direction","attribute_label_datetime":"Date/Time","attribute_label_cite":"Cite","attribute_label_style":"Style","attribute_label_class":"Class","attribute_label_id":"ID","attribute_label_title":"Title"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/fr_dlg.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/fr_dlg.js new file mode 100755 index 0000000..4ae5a3b --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.xhtmlxtras_dlg',{"attribs_title":"Ins\u00e9rer / \u00e9diter les attributs","option_rtl":"De droite \u00e0 gauche","option_ltr":"De gauche \u00e0 droite","insert_date":"Ins\u00e9rer la date et l\'heure actuelles",remove:"Enlever","title_cite_element":"Citation","title_abbr_element":"Abr\u00e9viation","title_acronym_element":"Acronyme","title_del_element":"Suppression","title_ins_element":"Insertion","fieldset_events_tab":"\u00c9v\u00e9nements","fieldset_attrib_tab":"Attributs","fieldset_general_tab":"Param\u00e8tres g\u00e9n\u00e9raux","events_tab":"\u00c9v\u00e9nements","attrib_tab":"Attributs","general_tab":"G\u00e9n\u00e9ral","attribute_attrib_tab":"Attributs","attribute_events_tab":"\u00c9v\u00e8nements","attribute_label_accesskey":"Accesskey","attribute_label_tabindex":"TabIndex","attribute_label_langcode":"Langue","attribute_option_rtl":"De droite \u00e0 gauche","attribute_option_ltr":"De gauche \u00e0 droite","attribute_label_langdir":"Sens de lecture","attribute_label_datetime":"Date / heure","attribute_label_cite":"Citation","attribute_label_style":"Style","attribute_label_class":"Classe","attribute_label_id":"ID","attribute_label_title":"Titre"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/it_dlg.js b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/it_dlg.js new file mode 100755 index 0000000..726be22 --- /dev/null +++ b/src/core/static/js/tiny_mce/plugins/xhtmlxtras/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.xhtmlxtras_dlg',{"attribs_title":"Inserisci/modifica attributi","option_rtl":"Destra verso sinistra","option_ltr":"Sinistra verso destra","insert_date":"Inserisci data/ora corrente",remove:"Rimuovi","title_cite_element":"Citazione elemento","title_abbr_element":"Abbreviazione elemento","title_acronym_element":"Acronimo elemento","title_del_element":"Cancellazione elemento","title_ins_element":"Inserimento elemento","fieldset_events_tab":"Eventi elemento","fieldset_attrib_tab":"Attributi elemento","fieldset_general_tab":"Impostazioni Generali","events_tab":"Eventi","attrib_tab":"Attributi","general_tab":"Generale","attribute_attrib_tab":"Attributi","attribute_events_tab":"Eventi","attribute_label_accesskey":"Tasto di accesso","attribute_label_tabindex":"Indice tabulazione","attribute_label_langcode":"Lingua","attribute_option_rtl":"Destra verso sinistra","attribute_option_ltr":"Sinistra verso destra","attribute_label_langdir":"Direzione del testo","attribute_label_datetime":"Date/Time","attribute_label_cite":"Citazione","attribute_label_style":"Style","attribute_label_class":"Classe","attribute_label_id":"ID","attribute_label_title":"Titolo"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/advanced/about.htm b/src/core/static/js/tiny_mce/themes/advanced/about.htm new file mode 100644 index 0000000..7a97cb7 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/about.htm @@ -0,0 +1,52 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.about_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="js/about.js"></script> +</head> +<body id="about" style="display: none"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.about_general}</a></span></li> + <li id="help_tab" style="display:none" aria-hidden="true" aria-controls="help_panel"><span><a href="javascript:mcTabs.displayTab('help_tab','help_panel');" onmousedown="return false;">{#advanced_dlg.about_help}</a></span></li> + <li id="plugins_tab" aria-controls="plugins_panel"><span><a href="javascript:mcTabs.displayTab('plugins_tab','plugins_panel');" onmousedown="return false;">{#advanced_dlg.about_plugins}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <h3>{#advanced_dlg.about_title}</h3> + <p>Version: <span id="version"></span> (<span id="date"></span>)</p> + <p>TinyMCE is a platform independent web based Javascript HTML WYSIWYG editor control released as Open Source under <a href="../../license.txt" target="_blank">LGPL</a> + by Moxiecode Systems AB. It has the ability to convert HTML TEXTAREA fields or other HTML elements to editor instances.</p> + <p>Copyright &copy; 2003-2008, <a href="http://www.moxiecode.com" target="_blank">Moxiecode Systems AB</a>, All rights reserved.</p> + <p>For more information about this software visit the <a href="http://tinymce.moxiecode.com" target="_blank">TinyMCE website</a>.</p> + + <div id="buttoncontainer"> + <a href="http://www.moxiecode.com" target="_blank"><img src="http://tinymce.moxiecode.com/images/gotmoxie.png" alt="Got Moxie?" border="0" /></a> + </div> + </div> + + <div id="plugins_panel" class="panel"> + <div id="pluginscontainer"> + <h3>{#advanced_dlg.about_loaded}</h3> + + <div id="plugintablecontainer"> + </div> + + <p>&nbsp;</p> + </div> + </div> + + <div id="help_panel" class="panel noscroll" style="overflow: visible;"> + <div id="iframecontainer"></div> + </div> + </div> + + <div class="mceActionPanel"> + <input type="button" id="cancel" name="cancel" value="{#close}" onclick="tinyMCEPopup.close();" /> + </div> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/themes/advanced/anchor.htm b/src/core/static/js/tiny_mce/themes/advanced/anchor.htm new file mode 100644 index 0000000..75c93b7 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/anchor.htm @@ -0,0 +1,26 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.anchor_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/anchor.js"></script> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<form onsubmit="AnchorDialog.update();return false;" action="#"> + <table border="0" cellpadding="4" cellspacing="0" role="presentation"> + <tr> + <td colspan="2" class="title" id="app_title">{#advanced_dlg.anchor_title}</td> + </tr> + <tr> + <td class="nowrap"><label for="anchorName">{#advanced_dlg.anchor_name}:</label></td> + <td><input name="anchorName" type="text" class="mceFocus" id="anchorName" value="" style="width: 200px" aria-required="true" /></td> + </tr> + </table> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/themes/advanced/charmap.htm b/src/core/static/js/tiny_mce/themes/advanced/charmap.htm new file mode 100644 index 0000000..2c3b3f2 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/charmap.htm @@ -0,0 +1,51 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.charmap_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/charmap.js"></script> +</head> +<body id="charmap" style="display:none"> +<table align="center" border="0" cellspacing="0" cellpadding="2" role="presentation"> + <tr> + <td colspan="2" class="title" ><label for="charmapView" id="charmap_label">{#advanced_dlg.charmap_title}</label></td> + </tr> + <tr> + <td id="charmapView" rowspan="2" align="left" valign="top"> + <!-- Chars will be rendered here --> + </td> + <td width="100" align="center" valign="top"> + <table border="0" cellpadding="0" cellspacing="0" width="100" style="height:100px" role="presentation"> + <tr> + <td id="codeV">&nbsp;</td> + </tr> + <tr> + <td id="codeN">&nbsp;</td> + </tr> + </table> + </td> + </tr> + <tr> + <td valign="bottom" style="padding-bottom: 3px;"> + <table width="100" align="center" border="0" cellpadding="2" cellspacing="0" role="presentation"> + <tr> + <td align="center" style="border-left: 1px solid #666699; border-top: 1px solid #666699; border-right: 1px solid #666699;"><label for="codeA">HTML-Code</label></td> + </tr> + <tr> + <td style="font-size: 16px; font-weight: bold; border-left: 1px solid #666699; border-bottom: 1px solid #666699; border-right: 1px solid #666699;" id="codeA" align="center">&nbsp;</td> + </tr> + <tr> + <td style="font-size: 1px;">&nbsp;</td> + </tr> + <tr> + <td align="center" style="border-left: 1px solid #666699; border-top: 1px solid #666699; border-right: 1px solid #666699;"><label for="codeB">NUM-Code</label></td> + </tr> + <tr> + <td style="font-size: 16px; font-weight: bold; border-left: 1px solid #666699; border-bottom: 1px solid #666699; border-right: 1px solid #666699;" id="codeB" align="center">&nbsp;</td> + </tr> + </table> + </td> + </tr> +</table> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/themes/advanced/color_picker.htm b/src/core/static/js/tiny_mce/themes/advanced/color_picker.htm new file mode 100644 index 0000000..ad1bb0f --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/color_picker.htm @@ -0,0 +1,74 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.colorpicker_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="js/color_picker.js"></script> +</head> +<body id="colorpicker" style="display: none" role="application" aria-labelledby="app_label"> + <span class="mceVoiceLabel" id="app_label" style="display:none;">{#advanced_dlg.colorpicker_title}</span> +<form onsubmit="insertAction();return false" action="#"> + <div class="tabs"> + <ul> + <li id="picker_tab" aria-controls="picker_panel" class="current"><span><a href="javascript:mcTabs.displayTab('picker_tab','picker_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_picker_tab}</a></span></li> + <li id="rgb_tab" aria-controls="rgb_panel"><span><a href="javascript:;" onclick="mcTabs.displayTab('rgb_tab','rgb_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_palette_tab}</a></span></li> + <li id="named_tab" aria-controls="named_panel"><span><a href="javascript:;" onclick="javascript:mcTabs.displayTab('named_tab','named_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_named_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="picker_panel" class="panel current"> + <fieldset> + <legend>{#advanced_dlg.colorpicker_picker_title}</legend> + <div id="picker"> + <img id="colors" src="img/colorpicker.jpg" onclick="computeColor(event)" onmousedown="isMouseDown = true;return false;" onmouseup="isMouseDown = false;" onmousemove="if (isMouseDown && isMouseOver) computeColor(event); return false;" onmouseover="isMouseOver=true;" onmouseout="isMouseOver=false;" alt="" /> + + <div id="light"> + <!-- Will be filled with divs --> + </div> + + <br style="clear: both" /> + </div> + </fieldset> + </div> + + <div id="rgb_panel" class="panel"> + <fieldset> + <legend id="webcolors_title">{#advanced_dlg.colorpicker_palette_title}</legend> + <div id="webcolors"> + <!-- Gets filled with web safe colors--> + </div> + + <br style="clear: both" /> + </fieldset> + </div> + + <div id="named_panel" class="panel"> + <fieldset id="named_picker_label"> + <legend id="named_title">{#advanced_dlg.colorpicker_named_title}</legend> + <div id="namedcolors" role="listbox" tabindex="0" aria-labelledby="named_picker_label"> + <!-- Gets filled with named colors--> + </div> + + <br style="clear: both" /> + + <div id="colornamecontainer"> + {#advanced_dlg.colorpicker_name} <span id="colorname"></span> + </div> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#apply}" /> + + <div id="preview"></div> + + <div id="previewblock"> + <label for="color">{#advanced_dlg.colorpicker_color}</label> <input id="color" type="text" size="8" class="text mceFocus" aria-required="true" /> + </div> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/themes/advanced/editor_template.js b/src/core/static/js/tiny_mce/themes/advanced/editor_template.js new file mode 100644 index 0000000..7f30c18 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/editor_template.js @@ -0,0 +1 @@ +(function(e){var d=e.DOM,b=e.dom.Event,h=e.extend,f=e.each,a=e.util.Cookie,g,c=e.explode;e.ThemeManager.requireLangPack("advanced");e.create("tinymce.themes.AdvancedTheme",{sizes:[8,10,12,14,18,24,36],controls:{bold:["bold_desc","Bold"],italic:["italic_desc","Italic"],underline:["underline_desc","Underline"],strikethrough:["striketrough_desc","Strikethrough"],justifyleft:["justifyleft_desc","JustifyLeft"],justifycenter:["justifycenter_desc","JustifyCenter"],justifyright:["justifyright_desc","JustifyRight"],justifyfull:["justifyfull_desc","JustifyFull"],bullist:["bullist_desc","InsertUnorderedList"],numlist:["numlist_desc","InsertOrderedList"],outdent:["outdent_desc","Outdent"],indent:["indent_desc","Indent"],cut:["cut_desc","Cut"],copy:["copy_desc","Copy"],paste:["paste_desc","Paste"],undo:["undo_desc","Undo"],redo:["redo_desc","Redo"],link:["link_desc","mceLink"],unlink:["unlink_desc","unlink"],image:["image_desc","mceImage"],cleanup:["cleanup_desc","mceCleanup"],help:["help_desc","mceHelp"],code:["code_desc","mceCodeEditor"],hr:["hr_desc","InsertHorizontalRule"],removeformat:["removeformat_desc","RemoveFormat"],sub:["sub_desc","subscript"],sup:["sup_desc","superscript"],forecolor:["forecolor_desc","ForeColor"],forecolorpicker:["forecolor_desc","mceForeColor"],backcolor:["backcolor_desc","HiliteColor"],backcolorpicker:["backcolor_desc","mceBackColor"],charmap:["charmap_desc","mceCharMap"],visualaid:["visualaid_desc","mceToggleVisualAid"],anchor:["anchor_desc","mceInsertAnchor"],newdocument:["newdocument_desc","mceNewDocument"],blockquote:["blockquote_desc","mceBlockQuote"]},stateControls:["bold","italic","underline","strikethrough","bullist","numlist","justifyleft","justifycenter","justifyright","justifyfull","sub","sup","blockquote"],init:function(j,k){var l=this,m,i,n;l.editor=j;l.url=k;l.onResolveName=new e.util.Dispatcher(this);j.forcedHighContrastMode=j.settings.detect_highcontrast&&l._isHighContrast();j.settings.skin=j.forcedHighContrastMode?"highcontrast":j.settings.skin;l.settings=m=h({theme_advanced_path:true,theme_advanced_toolbar_location:"bottom",theme_advanced_buttons1:"bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",theme_advanced_buttons2:"bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",theme_advanced_buttons3:"hr,removeformat,visualaid,|,sub,sup,|,charmap",theme_advanced_blockformats:"p,address,pre,h1,h2,h3,h4,h5,h6",theme_advanced_toolbar_align:"center",theme_advanced_fonts:"Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",theme_advanced_more_colors:1,theme_advanced_row_height:23,theme_advanced_resize_horizontal:1,theme_advanced_resizing_use_cookie:1,theme_advanced_font_sizes:"1,2,3,4,5,6,7",theme_advanced_font_selector:"span",theme_advanced_show_current_color:0,readonly:j.settings.readonly},j.settings);if(!m.font_size_style_values){m.font_size_style_values="8pt,10pt,12pt,14pt,18pt,24pt,36pt"}if(e.is(m.theme_advanced_font_sizes,"string")){m.font_size_style_values=e.explode(m.font_size_style_values);m.font_size_classes=e.explode(m.font_size_classes||"");n={};j.settings.theme_advanced_font_sizes=m.theme_advanced_font_sizes;f(j.getParam("theme_advanced_font_sizes","","hash"),function(q,p){var o;if(p==q&&q>=1&&q<=7){p=q+" ("+l.sizes[q-1]+"pt)";o=m.font_size_classes[q-1];q=m.font_size_style_values[q-1]||(l.sizes[q-1]+"pt")}if(/^\s*\./.test(q)){o=q.replace(/\./g,"")}n[p]=o?{"class":o}:{fontSize:q}});m.theme_advanced_font_sizes=n}if((i=m.theme_advanced_path_location)&&i!="none"){m.theme_advanced_statusbar_location=m.theme_advanced_path_location}if(m.theme_advanced_statusbar_location=="none"){m.theme_advanced_statusbar_location=0}if(j.settings.content_css!==false){j.contentCSS.push(j.baseURI.toAbsolute(k+"/skins/"+j.settings.skin+"/content.css"))}j.onInit.add(function(){if(!j.settings.readonly){j.onNodeChange.add(l._nodeChanged,l);j.onKeyUp.add(l._updateUndoStatus,l);j.onMouseUp.add(l._updateUndoStatus,l);j.dom.bind(j.dom.getRoot(),"dragend",function(){l._updateUndoStatus(j)})}});j.onSetProgressState.add(function(q,o,r){var s,t=q.id,p;if(o){l.progressTimer=setTimeout(function(){s=q.getContainer();s=s.insertBefore(d.create("DIV",{style:"position:relative"}),s.firstChild);p=d.get(q.id+"_tbl");d.add(s,"div",{id:t+"_blocker","class":"mceBlocker",style:{width:p.clientWidth+2,height:p.clientHeight+2}});d.add(s,"div",{id:t+"_progress","class":"mceProgress",style:{left:p.clientWidth/2,top:p.clientHeight/2}})},r||0)}else{d.remove(t+"_blocker");d.remove(t+"_progress");clearTimeout(l.progressTimer)}});d.loadCSS(m.editor_css?j.documentBaseURI.toAbsolute(m.editor_css):k+"/skins/"+j.settings.skin+"/ui.css");if(m.skin_variant){d.loadCSS(k+"/skins/"+j.settings.skin+"/ui_"+m.skin_variant+".css")}},_isHighContrast:function(){var i,j=d.add(d.getRoot(),"div",{style:"background-color: rgb(171,239,86);"});i=(d.getStyle(j,"background-color",true)+"").toLowerCase().replace(/ /g,"");d.remove(j);return i!="rgb(171,239,86)"&&i!="#abef56"},createControl:function(l,i){var j,k;if(k=i.createControl(l)){return k}switch(l){case"styleselect":return this._createStyleSelect();case"formatselect":return this._createBlockFormats();case"fontselect":return this._createFontSelect();case"fontsizeselect":return this._createFontSizeSelect();case"forecolor":return this._createForeColorMenu();case"backcolor":return this._createBackColorMenu()}if((j=this.controls[l])){return i.createButton(l,{title:"advanced."+j[0],cmd:j[1],ui:j[2],value:j[3]})}},execCommand:function(k,j,l){var i=this["_"+k];if(i){i.call(this,j,l);return true}return false},_importClasses:function(k){var i=this.editor,j=i.controlManager.get("styleselect");if(j.getLength()==0){f(i.dom.getClasses(),function(n,l){var m="style_"+l;i.formatter.register(m,{inline:"span",attributes:{"class":n["class"]},selector:"*"});j.add(n["class"],m)})}},_createStyleSelect:function(m){var k=this,i=k.editor,j=i.controlManager,l;l=j.createListBox("styleselect",{title:"advanced.style_select",onselect:function(o){var p,n=[];f(l.items,function(q){n.push(q.value)});i.focus();i.undoManager.add();p=i.formatter.matchAll(n);if(!o||p[0]==o){if(p[0]){i.formatter.remove(p[0])}}else{i.formatter.apply(o)}i.undoManager.add();i.nodeChanged();return false}});i.onInit.add(function(){var o=0,n=i.getParam("style_formats");if(n){f(n,function(p){var q,r=0;f(p,function(){r++});if(r>1){q=p.name=p.name||"style_"+(o++);i.formatter.register(q,p);l.add(p.title,q)}else{l.add(p.title)}})}else{f(i.getParam("theme_advanced_styles","","hash"),function(r,q){var p;if(r){p="style_"+(o++);i.formatter.register(p,{inline:"span",classes:r,selector:"*"});l.add(k.editor.translate(q),p)}})}});if(l.getLength()==0){l.onPostRender.add(function(o,p){if(!l.NativeListBox){b.add(p.id+"_text","focus",k._importClasses,k);b.add(p.id+"_text","mousedown",k._importClasses,k);b.add(p.id+"_open","focus",k._importClasses,k);b.add(p.id+"_open","mousedown",k._importClasses,k)}else{b.add(p.id,"focus",k._importClasses,k)}})}return l},_createFontSelect:function(){var k,j=this,i=j.editor;k=i.controlManager.createListBox("fontselect",{title:"advanced.fontdefault",onselect:function(l){var m=k.items[k.selectedIndex];if(!l&&m){i.execCommand("FontName",false,m.value);return}i.execCommand("FontName",false,l);k.select(function(n){return l==n});if(m&&m.value==l){k.select(null)}return false}});if(k){f(i.getParam("theme_advanced_fonts",j.settings.theme_advanced_fonts,"hash"),function(m,l){k.add(i.translate(l),m,{style:m.indexOf("dings")==-1?"font-family:"+m:""})})}return k},_createFontSizeSelect:function(){var m=this,k=m.editor,n,l=0,j=[];n=k.controlManager.createListBox("fontsizeselect",{title:"advanced.font_size",onselect:function(i){var o=n.items[n.selectedIndex];if(!i&&o){o=o.value;if(o["class"]){k.formatter.toggle("fontsize_class",{value:o["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,o.fontSize)}return}if(i["class"]){k.focus();k.undoManager.add();k.formatter.toggle("fontsize_class",{value:i["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,i.fontSize)}n.select(function(p){return i==p});if(o&&(o.value.fontSize==i.fontSize||o.value["class"]==i["class"])){n.select(null)}return false}});if(n){f(m.settings.theme_advanced_font_sizes,function(o,i){var p=o.fontSize;if(p>=1&&p<=7){p=m.sizes[parseInt(p)-1]+"pt"}n.add(i,o,{style:"font-size:"+p,"class":"mceFontSize"+(l++)+(" "+(o["class"]||""))})})}return n},_createBlockFormats:function(){var k,i={p:"advanced.paragraph",address:"advanced.address",pre:"advanced.pre",h1:"advanced.h1",h2:"advanced.h2",h3:"advanced.h3",h4:"advanced.h4",h5:"advanced.h5",h6:"advanced.h6",div:"advanced.div",blockquote:"advanced.blockquote",code:"advanced.code",dt:"advanced.dt",dd:"advanced.dd",samp:"advanced.samp"},j=this;k=j.editor.controlManager.createListBox("formatselect",{title:"advanced.block",onselect:function(l){j.editor.execCommand("FormatBlock",false,l);return false}});if(k){f(j.editor.getParam("theme_advanced_blockformats",j.settings.theme_advanced_blockformats,"hash"),function(m,l){k.add(j.editor.translate(l!=m?l:i[m]),m,{"class":"mce_formatPreview mce_"+m})})}return k},_createForeColorMenu:function(){var m,j=this,k=j.settings,l={},i;if(k.theme_advanced_more_colors){l.more_colors_func=function(){j._mceColorPicker(0,{color:m.value,func:function(n){m.setColor(n)}})}}if(i=k.theme_advanced_text_colors){l.colors=i}if(k.theme_advanced_default_foreground_color){l.default_color=k.theme_advanced_default_foreground_color}l.title="advanced.forecolor_desc";l.cmd="ForeColor";l.scope=this;m=j.editor.controlManager.createColorSplitButton("forecolor",l);return m},_createBackColorMenu:function(){var m,j=this,k=j.settings,l={},i;if(k.theme_advanced_more_colors){l.more_colors_func=function(){j._mceColorPicker(0,{color:m.value,func:function(n){m.setColor(n)}})}}if(i=k.theme_advanced_background_colors){l.colors=i}if(k.theme_advanced_default_background_color){l.default_color=k.theme_advanced_default_background_color}l.title="advanced.backcolor_desc";l.cmd="HiliteColor";l.scope=this;m=j.editor.controlManager.createColorSplitButton("backcolor",l);return m},renderUI:function(k){var m,l,q,v=this,r=v.editor,w=v.settings,u,j,i;if(r.settings){r.settings.aria_label=w.aria_label+r.getLang("advanced.help_shortcut")}m=j=d.create("span",{role:"application","aria-labelledby":r.id+"_voice",id:r.id+"_parent","class":"mceEditor "+r.settings.skin+"Skin"+(w.skin_variant?" "+r.settings.skin+"Skin"+v._ufirst(w.skin_variant):"")});d.add(m,"span",{"class":"mceVoiceLabel",style:"display:none;",id:r.id+"_voice"},w.aria_label);if(!d.boxModel){m=d.add(m,"div",{"class":"mceOldBoxModel"})}m=u=d.add(m,"table",{role:"presentation",id:r.id+"_tbl","class":"mceLayout",cellSpacing:0,cellPadding:0});m=q=d.add(m,"tbody");switch((w.theme_advanced_layout_manager||"").toLowerCase()){case"rowlayout":l=v._rowLayout(w,q,k);break;case"customlayout":l=r.execCallback("theme_advanced_custom_layout",w,q,k,j);break;default:l=v._simpleLayout(w,q,k,j)}m=k.targetNode;i=u.rows;d.addClass(i[0],"mceFirst");d.addClass(i[i.length-1],"mceLast");f(d.select("tr",q),function(o){d.addClass(o.firstChild,"mceFirst");d.addClass(o.childNodes[o.childNodes.length-1],"mceLast")});if(d.get(w.theme_advanced_toolbar_container)){d.get(w.theme_advanced_toolbar_container).appendChild(j)}else{d.insertAfter(j,m)}b.add(r.id+"_path_row","click",function(n){n=n.target;if(n.nodeName=="A"){v._sel(n.className.replace(/^.*mcePath_([0-9]+).*$/,"$1"));return b.cancel(n)}});if(!r.getParam("accessibility_focus")){b.add(d.add(j,"a",{href:"#"},"<!-- IE -->"),"focus",function(){tinyMCE.get(r.id).focus()})}if(w.theme_advanced_toolbar_location=="external"){k.deltaHeight=0}v.deltaHeight=k.deltaHeight;k.targetNode=null;r.onKeyDown.add(function(p,n){var s=121,o=122;if(n.altKey){if(n.keyCode===s){window.focus();v.toolbarGroup.focus();return b.cancel(n)}else{if(n.keyCode===o){d.get(p.id+"_path_row").focus();return b.cancel(n)}}}});r.addShortcut("alt+0","","mceShortcuts",v);return{iframeContainer:l,editorContainer:r.id+"_parent",sizeContainer:u,deltaHeight:k.deltaHeight}},getInfo:function(){return{longname:"Advanced theme",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",version:e.majorVersion+"."+e.minorVersion}},resizeBy:function(i,j){var k=d.get(this.editor.id+"_ifr");this.resizeTo(k.clientWidth+i,k.clientHeight+j)},resizeTo:function(i,m,k){var j=this.editor,l=this.settings,n=d.get(j.id+"_tbl"),o=d.get(j.id+"_ifr");i=Math.max(l.theme_advanced_resizing_min_width||100,i);m=Math.max(l.theme_advanced_resizing_min_height||100,m);i=Math.min(l.theme_advanced_resizing_max_width||65535,i);m=Math.min(l.theme_advanced_resizing_max_height||65535,m);d.setStyle(n,"height","");d.setStyle(o,"height",m);if(l.theme_advanced_resize_horizontal){d.setStyle(n,"width","");d.setStyle(o,"width",i);if(i<n.clientWidth){i=n.clientWidth;d.setStyle(o,"width",n.clientWidth)}}if(k&&l.theme_advanced_resizing_use_cookie){a.setHash("TinyMCE_"+j.id+"_size",{cw:i,ch:m})}},destroy:function(){var i=this.editor.id;b.clear(i+"_resize");b.clear(i+"_path_row");b.clear(i+"_external_close")},_simpleLayout:function(y,r,k,i){var x=this,u=x.editor,v=y.theme_advanced_toolbar_location,m=y.theme_advanced_statusbar_location,l,j,q,w;if(y.readonly){l=d.add(r,"tr");l=j=d.add(l,"td",{"class":"mceIframeContainer"});return j}if(v=="top"){x._addToolbars(r,k)}if(v=="external"){l=w=d.create("div",{style:"position:relative"});l=d.add(l,"div",{id:u.id+"_external","class":"mceExternalToolbar"});d.add(l,"a",{id:u.id+"_external_close",href:"javascript:;","class":"mceExternalClose"});l=d.add(l,"table",{id:u.id+"_tblext",cellSpacing:0,cellPadding:0});q=d.add(l,"tbody");if(i.firstChild.className=="mceOldBoxModel"){i.firstChild.appendChild(w)}else{i.insertBefore(w,i.firstChild)}x._addToolbars(q,k);u.onMouseUp.add(function(){var o=d.get(u.id+"_external");d.show(o);d.hide(g);var n=b.add(u.id+"_external_close","click",function(){d.hide(u.id+"_external");b.remove(u.id+"_external_close","click",n)});d.show(o);d.setStyle(o,"top",0-d.getRect(u.id+"_tblext").h-1);d.hide(o);d.show(o);o.style.filter="";g=u.id+"_external";o=null})}if(m=="top"){x._addStatusBar(r,k)}if(!y.theme_advanced_toolbar_container){l=d.add(r,"tr");l=j=d.add(l,"td",{"class":"mceIframeContainer"})}if(v=="bottom"){x._addToolbars(r,k)}if(m=="bottom"){x._addStatusBar(r,k)}return j},_rowLayout:function(w,m,k){var v=this,p=v.editor,u,x,i=p.controlManager,l,j,r,q;u=w.theme_advanced_containers_default_class||"";x=w.theme_advanced_containers_default_align||"center";f(c(w.theme_advanced_containers||""),function(s,o){var n=w["theme_advanced_container_"+s]||"";switch(s.toLowerCase()){case"mceeditor":l=d.add(m,"tr");l=j=d.add(l,"td",{"class":"mceIframeContainer"});break;case"mceelementpath":v._addStatusBar(m,k);break;default:q=(w["theme_advanced_container_"+s+"_align"]||x).toLowerCase();q="mce"+v._ufirst(q);l=d.add(d.add(m,"tr"),"td",{"class":"mceToolbar "+(w["theme_advanced_container_"+s+"_class"]||u)+" "+q||x});r=i.createToolbar("toolbar"+o);v._addControls(n,r);d.setHTML(l,r.renderHTML());k.deltaHeight-=w.theme_advanced_row_height}});return j},_addControls:function(j,i){var k=this,l=k.settings,m,n=k.editor.controlManager;if(l.theme_advanced_disable&&!k._disabled){m={};f(c(l.theme_advanced_disable),function(o){m[o]=1});k._disabled=m}else{m=k._disabled}f(c(j),function(p){var o;if(m&&m[p]){return}if(p=="tablecontrols"){f(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"],function(q){q=k.createControl(q,n);if(q){i.add(q)}});return}o=k.createControl(p,n);if(o){i.add(o)}})},_addToolbars:function(x,k){var A=this,p,m,r=A.editor,B=A.settings,z,j=r.controlManager,u,l,q=[],y,w;w=j.createToolbarGroup("toolbargroup",{name:r.getLang("advanced.toolbar"),tab_focus_toolbar:r.getParam("theme_advanced_tab_focus_toolbar")});A.toolbarGroup=w;y=B.theme_advanced_toolbar_align.toLowerCase();y="mce"+A._ufirst(y);l=d.add(d.add(x,"tr",{role:"presentation"}),"td",{"class":"mceToolbar "+y,role:"presentation"});for(p=1;(z=B["theme_advanced_buttons"+p]);p++){m=j.createToolbar("toolbar"+p,{"class":"mceToolbarRow"+p});if(B["theme_advanced_buttons"+p+"_add"]){z+=","+B["theme_advanced_buttons"+p+"_add"]}if(B["theme_advanced_buttons"+p+"_add_before"]){z=B["theme_advanced_buttons"+p+"_add_before"]+","+z}A._addControls(z,m);w.add(m);k.deltaHeight-=B.theme_advanced_row_height}q.push(w.renderHTML());q.push(d.createHTML("a",{href:"#",accesskey:"z",title:r.getLang("advanced.toolbar_focus"),onfocus:"tinyMCE.getInstanceById('"+r.id+"').focus();"},"<!-- IE -->"));d.setHTML(l,q.join(""))},_addStatusBar:function(m,j){var k,v=this,p=v.editor,w=v.settings,i,q,u,l;k=d.add(m,"tr");k=l=d.add(k,"td",{"class":"mceStatusbar"});k=d.add(k,"div",{id:p.id+"_path_row",role:"group","aria-labelledby":p.id+"_path_voice"});if(w.theme_advanced_path){d.add(k,"span",{id:p.id+"_path_voice"},p.translate("advanced.path"));d.add(k,"span",{},": ")}else{d.add(k,"span",{},"&#160;")}if(w.theme_advanced_resizing){d.add(l,"a",{id:p.id+"_resize",href:"javascript:;",onclick:"return false;","class":"mceResize",tabIndex:"-1"});if(w.theme_advanced_resizing_use_cookie){p.onPostRender.add(function(){var n=a.getHash("TinyMCE_"+p.id+"_size"),r=d.get(p.id+"_tbl");if(!n){return}v.resizeTo(n.cw,n.ch)})}p.onPostRender.add(function(){b.add(p.id+"_resize","click",function(n){n.preventDefault()});b.add(p.id+"_resize","mousedown",function(D){var t,r,s,o,C,z,A,F,n,E,x;function y(G){G.preventDefault();n=A+(G.screenX-C);E=F+(G.screenY-z);v.resizeTo(n,E)}function B(G){b.remove(d.doc,"mousemove",t);b.remove(p.getDoc(),"mousemove",r);b.remove(d.doc,"mouseup",s);b.remove(p.getDoc(),"mouseup",o);n=A+(G.screenX-C);E=F+(G.screenY-z);v.resizeTo(n,E,true)}D.preventDefault();C=D.screenX;z=D.screenY;x=d.get(v.editor.id+"_ifr");A=n=x.clientWidth;F=E=x.clientHeight;t=b.add(d.doc,"mousemove",y);r=b.add(p.getDoc(),"mousemove",y);s=b.add(d.doc,"mouseup",B);o=b.add(p.getDoc(),"mouseup",B)})})}j.deltaHeight-=21;k=m=null},_updateUndoStatus:function(j){var i=j.controlManager,k=j.undoManager;i.setDisabled("undo",!k.hasUndo()&&!k.typing);i.setDisabled("redo",!k.hasRedo())},_nodeChanged:function(m,r,D,q,E){var y=this,C,F=0,x,G,z=y.settings,w,k,u,B,l,j,i;e.each(y.stateControls,function(n){r.setActive(n,m.queryCommandState(y.controls[n][1]))});function o(p){var s,n=E.parents,t=p;if(typeof(p)=="string"){t=function(v){return v.nodeName==p}}for(s=0;s<n.length;s++){if(t(n[s])){return n[s]}}}r.setActive("visualaid",m.hasVisual);y._updateUndoStatus(m);r.setDisabled("outdent",!m.queryCommandState("Outdent"));C=o("A");if(G=r.get("link")){if(!C||!C.name){G.setDisabled(!C&&q);G.setActive(!!C)}}if(G=r.get("unlink")){G.setDisabled(!C&&q);G.setActive(!!C&&!C.name)}if(G=r.get("anchor")){G.setActive(!q&&!!C&&C.name)}C=o("IMG");if(G=r.get("image")){G.setActive(!q&&!!C&&D.className.indexOf("mceItem")==-1)}if(G=r.get("styleselect")){y._importClasses();j=[];f(G.items,function(n){j.push(n.value)});i=m.formatter.matchAll(j);G.select(i[0])}if(G=r.get("formatselect")){C=o(d.isBlock);if(C){G.select(C.nodeName.toLowerCase())}}o(function(p){if(p.nodeName==="SPAN"){if(!w&&p.className){w=p.className}}if(m.dom.is(p,z.theme_advanced_font_selector)){if(!k&&p.style.fontSize){k=p.style.fontSize}if(!u&&p.style.fontFamily){u=p.style.fontFamily.replace(/[\"\']+/g,"").replace(/^([^,]+).*/,"$1").toLowerCase()}if(!B&&p.style.color){B=p.style.color}if(!l&&p.style.backgroundColor){l=p.style.backgroundColor}}return false});if(G=r.get("fontselect")){G.select(function(n){return n.replace(/^([^,]+).*/,"$1").toLowerCase()==u})}if(G=r.get("fontsizeselect")){if(z.theme_advanced_runtime_fontsize&&!k&&!w){k=m.dom.getStyle(D,"fontSize",true)}G.select(function(n){if(n.fontSize&&n.fontSize===k){return true}if(n["class"]&&n["class"]===w){return true}})}if(z.theme_advanced_show_current_color){function A(p,n){if(G=r.get(p)){if(!n){n=G.settings.default_color}if(n!==G.value){G.displayColor(n)}}}A("forecolor",B);A("backcolor",l)}if(z.theme_advanced_show_current_color){function A(p,n){if(G=r.get(p)){if(!n){n=G.settings.default_color}if(n!==G.value){G.displayColor(n)}}}A("forecolor",B);A("backcolor",l)}if(z.theme_advanced_path&&z.theme_advanced_statusbar_location){C=d.get(m.id+"_path")||d.add(m.id+"_path_row","span",{id:m.id+"_path"});if(y.statusKeyboardNavigation){y.statusKeyboardNavigation.destroy();y.statusKeyboardNavigation=null}d.setHTML(C,"");o(function(H){var p=H.nodeName.toLowerCase(),s,v,t="";if(H.nodeType!=1||p==="br"||H.getAttribute("data-mce-bogus")||d.hasClass(H,"mceItemHidden")||d.hasClass(H,"mceItemRemoved")){return}if(e.isIE&&H.scopeName!=="HTML"){p=H.scopeName+":"+p}p=p.replace(/mce\:/g,"");switch(p){case"b":p="strong";break;case"i":p="em";break;case"img":if(x=d.getAttrib(H,"src")){t+="src: "+x+" "}break;case"a":if(x=d.getAttrib(H,"name")){t+="name: "+x+" ";p+="#"+x}if(x=d.getAttrib(H,"href")){t+="href: "+x+" "}break;case"font":if(x=d.getAttrib(H,"face")){t+="font: "+x+" "}if(x=d.getAttrib(H,"size")){t+="size: "+x+" "}if(x=d.getAttrib(H,"color")){t+="color: "+x+" "}break;case"span":if(x=d.getAttrib(H,"style")){t+="style: "+x+" "}break}if(x=d.getAttrib(H,"id")){t+="id: "+x+" "}if(x=H.className){x=x.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g,"");if(x){t+="class: "+x+" ";if(d.isBlock(H)||p=="img"||p=="span"){p+="."+x}}}p=p.replace(/(html:)/g,"");p={name:p,node:H,title:t};y.onResolveName.dispatch(y,p);t=p.title;p=p.name;v=d.create("a",{href:"javascript:;",role:"button",onmousedown:"return false;",title:t,"class":"mcePath_"+(F++)},p);if(C.hasChildNodes()){C.insertBefore(d.create("span",{"aria-hidden":"true"},"\u00a0\u00bb "),C.firstChild);C.insertBefore(v,C.firstChild)}else{C.appendChild(v)}},m.getBody());if(d.select("a",C).length>0){y.statusKeyboardNavigation=new e.ui.KeyboardNavigation({root:m.id+"_path_row",items:d.select("a",C),excludeFromTabOrder:true,onCancel:function(){m.focus()}},d)}}},_sel:function(i){this.editor.execCommand("mceSelectNodeDepth",false,i)},_mceInsertAnchor:function(k,j){var i=this.editor;i.windowManager.open({url:this.url+"/anchor.htm",width:320+parseInt(i.getLang("advanced.anchor_delta_width",0)),height:90+parseInt(i.getLang("advanced.anchor_delta_height",0)),inline:true},{theme_url:this.url})},_mceCharMap:function(){var i=this.editor;i.windowManager.open({url:this.url+"/charmap.htm",width:550+parseInt(i.getLang("advanced.charmap_delta_width",0)),height:250+parseInt(i.getLang("advanced.charmap_delta_height",0)),inline:true},{theme_url:this.url})},_mceHelp:function(){var i=this.editor;i.windowManager.open({url:this.url+"/about.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceShortcuts:function(){var i=this.editor;i.windowManager.open({url:this.url+"/shortcuts.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceColorPicker:function(k,j){var i=this.editor;j=j||{};i.windowManager.open({url:this.url+"/color_picker.htm",width:375+parseInt(i.getLang("advanced.colorpicker_delta_width",0)),height:250+parseInt(i.getLang("advanced.colorpicker_delta_height",0)),close_previous:false,inline:true},{input_color:j.color,func:j.func,theme_url:this.url})},_mceCodeEditor:function(j,k){var i=this.editor;i.windowManager.open({url:this.url+"/source_editor.htm",width:parseInt(i.getParam("theme_advanced_source_editor_width",720)),height:parseInt(i.getParam("theme_advanced_source_editor_height",580)),inline:true,resizable:true,maximizable:true},{theme_url:this.url})},_mceImage:function(j,k){var i=this.editor;if(i.dom.getAttrib(i.selection.getNode(),"class").indexOf("mceItem")!=-1){return}i.windowManager.open({url:this.url+"/image.htm",width:355+parseInt(i.getLang("advanced.image_delta_width",0)),height:275+parseInt(i.getLang("advanced.image_delta_height",0)),inline:true},{theme_url:this.url})},_mceLink:function(j,k){var i=this.editor;i.windowManager.open({url:this.url+"/link.htm",width:310+parseInt(i.getLang("advanced.link_delta_width",0)),height:200+parseInt(i.getLang("advanced.link_delta_height",0)),inline:true},{theme_url:this.url})},_mceNewDocument:function(){var i=this.editor;i.windowManager.confirm("advanced.newdocument",function(j){if(j){i.execCommand("mceSetContent",false,"")}})},_mceForeColor:function(){var i=this;this._mceColorPicker(0,{color:i.fgColor,func:function(j){i.fgColor=j;i.editor.execCommand("ForeColor",false,j)}})},_mceBackColor:function(){var i=this;this._mceColorPicker(0,{color:i.bgColor,func:function(j){i.bgColor=j;i.editor.execCommand("HiliteColor",false,j)}})},_ufirst:function(i){return i.substring(0,1).toUpperCase()+i.substring(1)}});e.ThemeManager.add("advanced",e.themes.AdvancedTheme)}(tinymce)); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/advanced/editor_template_src.js b/src/core/static/js/tiny_mce/themes/advanced/editor_template_src.js new file mode 100644 index 0000000..bee26e1 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/editor_template_src.js @@ -0,0 +1,1358 @@ +/** + * editor_template_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, each = tinymce.each, Cookie = tinymce.util.Cookie, lastExtID, explode = tinymce.explode; + + // Tell it to load theme specific language pack(s) + tinymce.ThemeManager.requireLangPack('advanced'); + + tinymce.create('tinymce.themes.AdvancedTheme', { + sizes : [8, 10, 12, 14, 18, 24, 36], + + // Control name lookup, format: title, command + controls : { + bold : ['bold_desc', 'Bold'], + italic : ['italic_desc', 'Italic'], + underline : ['underline_desc', 'Underline'], + strikethrough : ['striketrough_desc', 'Strikethrough'], + justifyleft : ['justifyleft_desc', 'JustifyLeft'], + justifycenter : ['justifycenter_desc', 'JustifyCenter'], + justifyright : ['justifyright_desc', 'JustifyRight'], + justifyfull : ['justifyfull_desc', 'JustifyFull'], + bullist : ['bullist_desc', 'InsertUnorderedList'], + numlist : ['numlist_desc', 'InsertOrderedList'], + outdent : ['outdent_desc', 'Outdent'], + indent : ['indent_desc', 'Indent'], + cut : ['cut_desc', 'Cut'], + copy : ['copy_desc', 'Copy'], + paste : ['paste_desc', 'Paste'], + undo : ['undo_desc', 'Undo'], + redo : ['redo_desc', 'Redo'], + link : ['link_desc', 'mceLink'], + unlink : ['unlink_desc', 'unlink'], + image : ['image_desc', 'mceImage'], + cleanup : ['cleanup_desc', 'mceCleanup'], + help : ['help_desc', 'mceHelp'], + code : ['code_desc', 'mceCodeEditor'], + hr : ['hr_desc', 'InsertHorizontalRule'], + removeformat : ['removeformat_desc', 'RemoveFormat'], + sub : ['sub_desc', 'subscript'], + sup : ['sup_desc', 'superscript'], + forecolor : ['forecolor_desc', 'ForeColor'], + forecolorpicker : ['forecolor_desc', 'mceForeColor'], + backcolor : ['backcolor_desc', 'HiliteColor'], + backcolorpicker : ['backcolor_desc', 'mceBackColor'], + charmap : ['charmap_desc', 'mceCharMap'], + visualaid : ['visualaid_desc', 'mceToggleVisualAid'], + anchor : ['anchor_desc', 'mceInsertAnchor'], + newdocument : ['newdocument_desc', 'mceNewDocument'], + blockquote : ['blockquote_desc', 'mceBlockQuote'] + }, + + stateControls : ['bold', 'italic', 'underline', 'strikethrough', 'bullist', 'numlist', 'justifyleft', 'justifycenter', 'justifyright', 'justifyfull', 'sub', 'sup', 'blockquote'], + + init : function(ed, url) { + var t = this, s, v, o; + + t.editor = ed; + t.url = url; + t.onResolveName = new tinymce.util.Dispatcher(this); + + ed.forcedHighContrastMode = ed.settings.detect_highcontrast && t._isHighContrast(); + ed.settings.skin = ed.forcedHighContrastMode ? 'highcontrast' : ed.settings.skin; + + // Default settings + t.settings = s = extend({ + theme_advanced_path : true, + theme_advanced_toolbar_location : 'bottom', + theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect", + theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code", + theme_advanced_buttons3 : "hr,removeformat,visualaid,|,sub,sup,|,charmap", + theme_advanced_blockformats : "p,address,pre,h1,h2,h3,h4,h5,h6", + theme_advanced_toolbar_align : "center", + theme_advanced_fonts : "Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats", + theme_advanced_more_colors : 1, + theme_advanced_row_height : 23, + theme_advanced_resize_horizontal : 1, + theme_advanced_resizing_use_cookie : 1, + theme_advanced_font_sizes : "1,2,3,4,5,6,7", + theme_advanced_font_selector : "span", + theme_advanced_show_current_color: 0, + readonly : ed.settings.readonly + }, ed.settings); + + // Setup default font_size_style_values + if (!s.font_size_style_values) + s.font_size_style_values = "8pt,10pt,12pt,14pt,18pt,24pt,36pt"; + + if (tinymce.is(s.theme_advanced_font_sizes, 'string')) { + s.font_size_style_values = tinymce.explode(s.font_size_style_values); + s.font_size_classes = tinymce.explode(s.font_size_classes || ''); + + // Parse string value + o = {}; + ed.settings.theme_advanced_font_sizes = s.theme_advanced_font_sizes; + each(ed.getParam('theme_advanced_font_sizes', '', 'hash'), function(v, k) { + var cl; + + if (k == v && v >= 1 && v <= 7) { + k = v + ' (' + t.sizes[v - 1] + 'pt)'; + cl = s.font_size_classes[v - 1]; + v = s.font_size_style_values[v - 1] || (t.sizes[v - 1] + 'pt'); + } + + if (/^\s*\./.test(v)) + cl = v.replace(/\./g, ''); + + o[k] = cl ? {'class' : cl} : {fontSize : v}; + }); + + s.theme_advanced_font_sizes = o; + } + + if ((v = s.theme_advanced_path_location) && v != 'none') + s.theme_advanced_statusbar_location = s.theme_advanced_path_location; + + if (s.theme_advanced_statusbar_location == 'none') + s.theme_advanced_statusbar_location = 0; + + if (ed.settings.content_css !== false) + ed.contentCSS.push(ed.baseURI.toAbsolute(url + "/skins/" + ed.settings.skin + "/content.css")); + + // Init editor + ed.onInit.add(function() { + if (!ed.settings.readonly) { + ed.onNodeChange.add(t._nodeChanged, t); + ed.onKeyUp.add(t._updateUndoStatus, t); + ed.onMouseUp.add(t._updateUndoStatus, t); + ed.dom.bind(ed.dom.getRoot(), 'dragend', function() { + t._updateUndoStatus(ed); + }); + } + }); + + ed.onSetProgressState.add(function(ed, b, ti) { + var co, id = ed.id, tb; + + if (b) { + t.progressTimer = setTimeout(function() { + co = ed.getContainer(); + co = co.insertBefore(DOM.create('DIV', {style : 'position:relative'}), co.firstChild); + tb = DOM.get(ed.id + '_tbl'); + + DOM.add(co, 'div', {id : id + '_blocker', 'class' : 'mceBlocker', style : {width : tb.clientWidth + 2, height : tb.clientHeight + 2}}); + DOM.add(co, 'div', {id : id + '_progress', 'class' : 'mceProgress', style : {left : tb.clientWidth / 2, top : tb.clientHeight / 2}}); + }, ti || 0); + } else { + DOM.remove(id + '_blocker'); + DOM.remove(id + '_progress'); + clearTimeout(t.progressTimer); + } + }); + + DOM.loadCSS(s.editor_css ? ed.documentBaseURI.toAbsolute(s.editor_css) : url + "/skins/" + ed.settings.skin + "/ui.css"); + + if (s.skin_variant) + DOM.loadCSS(url + "/skins/" + ed.settings.skin + "/ui_" + s.skin_variant + ".css"); + }, + + _isHighContrast : function() { + var actualColor, div = DOM.add(DOM.getRoot(), 'div', {'style': 'background-color: rgb(171,239,86);'}); + + actualColor = (DOM.getStyle(div, 'background-color', true) + '').toLowerCase().replace(/ /g, ''); + DOM.remove(div); + + return actualColor != 'rgb(171,239,86)' && actualColor != '#abef56'; + }, + + createControl : function(n, cf) { + var cd, c; + + if (c = cf.createControl(n)) + return c; + + switch (n) { + case "styleselect": + return this._createStyleSelect(); + + case "formatselect": + return this._createBlockFormats(); + + case "fontselect": + return this._createFontSelect(); + + case "fontsizeselect": + return this._createFontSizeSelect(); + + case "forecolor": + return this._createForeColorMenu(); + + case "backcolor": + return this._createBackColorMenu(); + } + + if ((cd = this.controls[n])) + return cf.createButton(n, {title : "advanced." + cd[0], cmd : cd[1], ui : cd[2], value : cd[3]}); + }, + + execCommand : function(cmd, ui, val) { + var f = this['_' + cmd]; + + if (f) { + f.call(this, ui, val); + return true; + } + + return false; + }, + + _importClasses : function(e) { + var ed = this.editor, ctrl = ed.controlManager.get('styleselect'); + + if (ctrl.getLength() == 0) { + each(ed.dom.getClasses(), function(o, idx) { + var name = 'style_' + idx; + + ed.formatter.register(name, { + inline : 'span', + attributes : {'class' : o['class']}, + selector : '*' + }); + + ctrl.add(o['class'], name); + }); + } + }, + + _createStyleSelect : function(n) { + var t = this, ed = t.editor, ctrlMan = ed.controlManager, ctrl; + + // Setup style select box + ctrl = ctrlMan.createListBox('styleselect', { + title : 'advanced.style_select', + onselect : function(name) { + var matches, formatNames = []; + + each(ctrl.items, function(item) { + formatNames.push(item.value); + }); + + ed.focus(); + ed.undoManager.add(); + + // Toggle off the current format + matches = ed.formatter.matchAll(formatNames); + if (!name || matches[0] == name) { + if (matches[0]) + ed.formatter.remove(matches[0]); + } else + ed.formatter.apply(name); + + ed.undoManager.add(); + ed.nodeChanged(); + + return false; // No auto select + } + }); + + // Handle specified format + ed.onInit.add(function() { + var counter = 0, formats = ed.getParam('style_formats'); + + if (formats) { + each(formats, function(fmt) { + var name, keys = 0; + + each(fmt, function() {keys++;}); + + if (keys > 1) { + name = fmt.name = fmt.name || 'style_' + (counter++); + ed.formatter.register(name, fmt); + ctrl.add(fmt.title, name); + } else + ctrl.add(fmt.title); + }); + } else { + each(ed.getParam('theme_advanced_styles', '', 'hash'), function(val, key) { + var name; + + if (val) { + name = 'style_' + (counter++); + + ed.formatter.register(name, { + inline : 'span', + classes : val, + selector : '*' + }); + + ctrl.add(t.editor.translate(key), name); + } + }); + } + }); + + // Auto import classes if the ctrl box is empty + if (ctrl.getLength() == 0) { + ctrl.onPostRender.add(function(ed, n) { + if (!ctrl.NativeListBox) { + Event.add(n.id + '_text', 'focus', t._importClasses, t); + Event.add(n.id + '_text', 'mousedown', t._importClasses, t); + Event.add(n.id + '_open', 'focus', t._importClasses, t); + Event.add(n.id + '_open', 'mousedown', t._importClasses, t); + } else + Event.add(n.id, 'focus', t._importClasses, t); + }); + } + + return ctrl; + }, + + _createFontSelect : function() { + var c, t = this, ed = t.editor; + + c = ed.controlManager.createListBox('fontselect', { + title : 'advanced.fontdefault', + onselect : function(v) { + var cur = c.items[c.selectedIndex]; + + if (!v && cur) { + ed.execCommand('FontName', false, cur.value); + return; + } + + ed.execCommand('FontName', false, v); + + // Fake selection, execCommand will fire a nodeChange and update the selection + c.select(function(sv) { + return v == sv; + }); + + if (cur && cur.value == v) { + c.select(null); + } + + return false; // No auto select + } + }); + + if (c) { + each(ed.getParam('theme_advanced_fonts', t.settings.theme_advanced_fonts, 'hash'), function(v, k) { + c.add(ed.translate(k), v, {style : v.indexOf('dings') == -1 ? 'font-family:' + v : ''}); + }); + } + + return c; + }, + + _createFontSizeSelect : function() { + var t = this, ed = t.editor, c, i = 0, cl = []; + + c = ed.controlManager.createListBox('fontsizeselect', {title : 'advanced.font_size', onselect : function(v) { + var cur = c.items[c.selectedIndex]; + + if (!v && cur) { + cur = cur.value; + + if (cur['class']) { + ed.formatter.toggle('fontsize_class', {value : cur['class']}); + ed.undoManager.add(); + ed.nodeChanged(); + } else { + ed.execCommand('FontSize', false, cur.fontSize); + } + + return; + } + + if (v['class']) { + ed.focus(); + ed.undoManager.add(); + ed.formatter.toggle('fontsize_class', {value : v['class']}); + ed.undoManager.add(); + ed.nodeChanged(); + } else + ed.execCommand('FontSize', false, v.fontSize); + + // Fake selection, execCommand will fire a nodeChange and update the selection + c.select(function(sv) { + return v == sv; + }); + + if (cur && (cur.value.fontSize == v.fontSize || cur.value['class'] == v['class'])) { + c.select(null); + } + + return false; // No auto select + }}); + + if (c) { + each(t.settings.theme_advanced_font_sizes, function(v, k) { + var fz = v.fontSize; + + if (fz >= 1 && fz <= 7) + fz = t.sizes[parseInt(fz) - 1] + 'pt'; + + c.add(k, v, {'style' : 'font-size:' + fz, 'class' : 'mceFontSize' + (i++) + (' ' + (v['class'] || ''))}); + }); + } + + return c; + }, + + _createBlockFormats : function() { + var c, fmts = { + p : 'advanced.paragraph', + address : 'advanced.address', + pre : 'advanced.pre', + h1 : 'advanced.h1', + h2 : 'advanced.h2', + h3 : 'advanced.h3', + h4 : 'advanced.h4', + h5 : 'advanced.h5', + h6 : 'advanced.h6', + div : 'advanced.div', + blockquote : 'advanced.blockquote', + code : 'advanced.code', + dt : 'advanced.dt', + dd : 'advanced.dd', + samp : 'advanced.samp' + }, t = this; + + c = t.editor.controlManager.createListBox('formatselect', {title : 'advanced.block', onselect : function(v) { + t.editor.execCommand('FormatBlock', false, v); + return false; + }}); + + if (c) { + each(t.editor.getParam('theme_advanced_blockformats', t.settings.theme_advanced_blockformats, 'hash'), function(v, k) { + c.add(t.editor.translate(k != v ? k : fmts[v]), v, {'class' : 'mce_formatPreview mce_' + v}); + }); + } + + return c; + }, + + _createForeColorMenu : function() { + var c, t = this, s = t.settings, o = {}, v; + + if (s.theme_advanced_more_colors) { + o.more_colors_func = function() { + t._mceColorPicker(0, { + color : c.value, + func : function(co) { + c.setColor(co); + } + }); + }; + } + + if (v = s.theme_advanced_text_colors) + o.colors = v; + + if (s.theme_advanced_default_foreground_color) + o.default_color = s.theme_advanced_default_foreground_color; + + o.title = 'advanced.forecolor_desc'; + o.cmd = 'ForeColor'; + o.scope = this; + + c = t.editor.controlManager.createColorSplitButton('forecolor', o); + + return c; + }, + + _createBackColorMenu : function() { + var c, t = this, s = t.settings, o = {}, v; + + if (s.theme_advanced_more_colors) { + o.more_colors_func = function() { + t._mceColorPicker(0, { + color : c.value, + func : function(co) { + c.setColor(co); + } + }); + }; + } + + if (v = s.theme_advanced_background_colors) + o.colors = v; + + if (s.theme_advanced_default_background_color) + o.default_color = s.theme_advanced_default_background_color; + + o.title = 'advanced.backcolor_desc'; + o.cmd = 'HiliteColor'; + o.scope = this; + + c = t.editor.controlManager.createColorSplitButton('backcolor', o); + + return c; + }, + + renderUI : function(o) { + var n, ic, tb, t = this, ed = t.editor, s = t.settings, sc, p, nl; + + if (ed.settings) { + ed.settings.aria_label = s.aria_label + ed.getLang('advanced.help_shortcut'); + } + + // TODO: ACC Should have an aria-describedby attribute which is user-configurable to describe what this field is actually for. + // Maybe actually inherit it from the original textara? + n = p = DOM.create('span', {role : 'application', 'aria-labelledby' : ed.id + '_voice', id : ed.id + '_parent', 'class' : 'mceEditor ' + ed.settings.skin + 'Skin' + (s.skin_variant ? ' ' + ed.settings.skin + 'Skin' + t._ufirst(s.skin_variant) : '')}); + DOM.add(n, 'span', {'class': 'mceVoiceLabel', 'style': 'display:none;', id: ed.id + '_voice'}, s.aria_label); + + if (!DOM.boxModel) + n = DOM.add(n, 'div', {'class' : 'mceOldBoxModel'}); + + n = sc = DOM.add(n, 'table', {role : "presentation", id : ed.id + '_tbl', 'class' : 'mceLayout', cellSpacing : 0, cellPadding : 0}); + n = tb = DOM.add(n, 'tbody'); + + switch ((s.theme_advanced_layout_manager || '').toLowerCase()) { + case "rowlayout": + ic = t._rowLayout(s, tb, o); + break; + + case "customlayout": + ic = ed.execCallback("theme_advanced_custom_layout", s, tb, o, p); + break; + + default: + ic = t._simpleLayout(s, tb, o, p); + } + + n = o.targetNode; + + // Add classes to first and last TRs + nl = sc.rows; + DOM.addClass(nl[0], 'mceFirst'); + DOM.addClass(nl[nl.length - 1], 'mceLast'); + + // Add classes to first and last TDs + each(DOM.select('tr', tb), function(n) { + DOM.addClass(n.firstChild, 'mceFirst'); + DOM.addClass(n.childNodes[n.childNodes.length - 1], 'mceLast'); + }); + + if (DOM.get(s.theme_advanced_toolbar_container)) + DOM.get(s.theme_advanced_toolbar_container).appendChild(p); + else + DOM.insertAfter(p, n); + + Event.add(ed.id + '_path_row', 'click', function(e) { + e = e.target; + + if (e.nodeName == 'A') { + t._sel(e.className.replace(/^.*mcePath_([0-9]+).*$/, '$1')); + + return Event.cancel(e); + } + }); +/* + if (DOM.get(ed.id + '_path_row')) { + Event.add(ed.id + '_tbl', 'mouseover', function(e) { + var re; + + e = e.target; + + if (e.nodeName == 'SPAN' && DOM.hasClass(e.parentNode, 'mceButton')) { + re = DOM.get(ed.id + '_path_row'); + t.lastPath = re.innerHTML; + DOM.setHTML(re, e.parentNode.title); + } + }); + + Event.add(ed.id + '_tbl', 'mouseout', function(e) { + if (t.lastPath) { + DOM.setHTML(ed.id + '_path_row', t.lastPath); + t.lastPath = 0; + } + }); + } +*/ + + if (!ed.getParam('accessibility_focus')) + Event.add(DOM.add(p, 'a', {href : '#'}, '<!-- IE -->'), 'focus', function() {tinyMCE.get(ed.id).focus();}); + + if (s.theme_advanced_toolbar_location == 'external') + o.deltaHeight = 0; + + t.deltaHeight = o.deltaHeight; + o.targetNode = null; + + ed.onKeyDown.add(function(ed, evt) { + var DOM_VK_F10 = 121, DOM_VK_F11 = 122; + + if (evt.altKey) { + if (evt.keyCode === DOM_VK_F10) { + window.focus(); + t.toolbarGroup.focus(); + return Event.cancel(evt); + } else if (evt.keyCode === DOM_VK_F11) { + DOM.get(ed.id + '_path_row').focus(); + return Event.cancel(evt); + } + } + }); + + // alt+0 is the UK recommended shortcut for accessing the list of access controls. + ed.addShortcut('alt+0', '', 'mceShortcuts', t); + + return { + iframeContainer : ic, + editorContainer : ed.id + '_parent', + sizeContainer : sc, + deltaHeight : o.deltaHeight + }; + }, + + getInfo : function() { + return { + longname : 'Advanced theme', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + version : tinymce.majorVersion + "." + tinymce.minorVersion + } + }, + + resizeBy : function(dw, dh) { + var e = DOM.get(this.editor.id + '_ifr'); + + this.resizeTo(e.clientWidth + dw, e.clientHeight + dh); + }, + + resizeTo : function(w, h, store) { + var ed = this.editor, s = this.settings, e = DOM.get(ed.id + '_tbl'), ifr = DOM.get(ed.id + '_ifr'); + + // Boundery fix box + w = Math.max(s.theme_advanced_resizing_min_width || 100, w); + h = Math.max(s.theme_advanced_resizing_min_height || 100, h); + w = Math.min(s.theme_advanced_resizing_max_width || 0xFFFF, w); + h = Math.min(s.theme_advanced_resizing_max_height || 0xFFFF, h); + + // Resize iframe and container + DOM.setStyle(e, 'height', ''); + DOM.setStyle(ifr, 'height', h); + + if (s.theme_advanced_resize_horizontal) { + DOM.setStyle(e, 'width', ''); + DOM.setStyle(ifr, 'width', w); + + // Make sure that the size is never smaller than the over all ui + if (w < e.clientWidth) { + w = e.clientWidth; + DOM.setStyle(ifr, 'width', e.clientWidth); + } + } + + // Store away the size + if (store && s.theme_advanced_resizing_use_cookie) { + Cookie.setHash("TinyMCE_" + ed.id + "_size", { + cw : w, + ch : h + }); + } + }, + + destroy : function() { + var id = this.editor.id; + + Event.clear(id + '_resize'); + Event.clear(id + '_path_row'); + Event.clear(id + '_external_close'); + }, + + // Internal functions + + _simpleLayout : function(s, tb, o, p) { + var t = this, ed = t.editor, lo = s.theme_advanced_toolbar_location, sl = s.theme_advanced_statusbar_location, n, ic, etb, c; + + if (s.readonly) { + n = DOM.add(tb, 'tr'); + n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'}); + return ic; + } + + // Create toolbar container at top + if (lo == 'top') + t._addToolbars(tb, o); + + // Create external toolbar + if (lo == 'external') { + n = c = DOM.create('div', {style : 'position:relative'}); + n = DOM.add(n, 'div', {id : ed.id + '_external', 'class' : 'mceExternalToolbar'}); + DOM.add(n, 'a', {id : ed.id + '_external_close', href : 'javascript:;', 'class' : 'mceExternalClose'}); + n = DOM.add(n, 'table', {id : ed.id + '_tblext', cellSpacing : 0, cellPadding : 0}); + etb = DOM.add(n, 'tbody'); + + if (p.firstChild.className == 'mceOldBoxModel') + p.firstChild.appendChild(c); + else + p.insertBefore(c, p.firstChild); + + t._addToolbars(etb, o); + + ed.onMouseUp.add(function() { + var e = DOM.get(ed.id + '_external'); + DOM.show(e); + + DOM.hide(lastExtID); + + var f = Event.add(ed.id + '_external_close', 'click', function() { + DOM.hide(ed.id + '_external'); + Event.remove(ed.id + '_external_close', 'click', f); + }); + + DOM.show(e); + DOM.setStyle(e, 'top', 0 - DOM.getRect(ed.id + '_tblext').h - 1); + + // Fixes IE rendering bug + DOM.hide(e); + DOM.show(e); + e.style.filter = ''; + + lastExtID = ed.id + '_external'; + + e = null; + }); + } + + if (sl == 'top') + t._addStatusBar(tb, o); + + // Create iframe container + if (!s.theme_advanced_toolbar_container) { + n = DOM.add(tb, 'tr'); + n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'}); + } + + // Create toolbar container at bottom + if (lo == 'bottom') + t._addToolbars(tb, o); + + if (sl == 'bottom') + t._addStatusBar(tb, o); + + return ic; + }, + + _rowLayout : function(s, tb, o) { + var t = this, ed = t.editor, dc, da, cf = ed.controlManager, n, ic, to, a; + + dc = s.theme_advanced_containers_default_class || ''; + da = s.theme_advanced_containers_default_align || 'center'; + + each(explode(s.theme_advanced_containers || ''), function(c, i) { + var v = s['theme_advanced_container_' + c] || ''; + + switch (c.toLowerCase()) { + case 'mceeditor': + n = DOM.add(tb, 'tr'); + n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'}); + break; + + case 'mceelementpath': + t._addStatusBar(tb, o); + break; + + default: + a = (s['theme_advanced_container_' + c + '_align'] || da).toLowerCase(); + a = 'mce' + t._ufirst(a); + + n = DOM.add(DOM.add(tb, 'tr'), 'td', { + 'class' : 'mceToolbar ' + (s['theme_advanced_container_' + c + '_class'] || dc) + ' ' + a || da + }); + + to = cf.createToolbar("toolbar" + i); + t._addControls(v, to); + DOM.setHTML(n, to.renderHTML()); + o.deltaHeight -= s.theme_advanced_row_height; + } + }); + + return ic; + }, + + _addControls : function(v, tb) { + var t = this, s = t.settings, di, cf = t.editor.controlManager; + + if (s.theme_advanced_disable && !t._disabled) { + di = {}; + + each(explode(s.theme_advanced_disable), function(v) { + di[v] = 1; + }); + + t._disabled = di; + } else + di = t._disabled; + + each(explode(v), function(n) { + var c; + + if (di && di[n]) + return; + + // Compatiblity with 2.x + if (n == 'tablecontrols') { + each(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"], function(n) { + n = t.createControl(n, cf); + + if (n) + tb.add(n); + }); + + return; + } + + c = t.createControl(n, cf); + + if (c) + tb.add(c); + }); + }, + + _addToolbars : function(c, o) { + var t = this, i, tb, ed = t.editor, s = t.settings, v, cf = ed.controlManager, di, n, h = [], a, toolbarGroup; + + toolbarGroup = cf.createToolbarGroup('toolbargroup', { + 'name': ed.getLang('advanced.toolbar'), + 'tab_focus_toolbar':ed.getParam('theme_advanced_tab_focus_toolbar') + }); + + t.toolbarGroup = toolbarGroup; + + a = s.theme_advanced_toolbar_align.toLowerCase(); + a = 'mce' + t._ufirst(a); + + n = DOM.add(DOM.add(c, 'tr', {role: 'presentation'}), 'td', {'class' : 'mceToolbar ' + a, "role":"presentation"}); + + // Create toolbar and add the controls + for (i=1; (v = s['theme_advanced_buttons' + i]); i++) { + tb = cf.createToolbar("toolbar" + i, {'class' : 'mceToolbarRow' + i}); + + if (s['theme_advanced_buttons' + i + '_add']) + v += ',' + s['theme_advanced_buttons' + i + '_add']; + + if (s['theme_advanced_buttons' + i + '_add_before']) + v = s['theme_advanced_buttons' + i + '_add_before'] + ',' + v; + + t._addControls(v, tb); + toolbarGroup.add(tb); + + o.deltaHeight -= s.theme_advanced_row_height; + } + h.push(toolbarGroup.renderHTML()); + h.push(DOM.createHTML('a', {href : '#', accesskey : 'z', title : ed.getLang("advanced.toolbar_focus"), onfocus : 'tinyMCE.getInstanceById(\'' + ed.id + '\').focus();'}, '<!-- IE -->')); + DOM.setHTML(n, h.join('')); + }, + + _addStatusBar : function(tb, o) { + var n, t = this, ed = t.editor, s = t.settings, r, mf, me, td; + + n = DOM.add(tb, 'tr'); + n = td = DOM.add(n, 'td', {'class' : 'mceStatusbar'}); + n = DOM.add(n, 'div', {id : ed.id + '_path_row', 'role': 'group', 'aria-labelledby': ed.id + '_path_voice'}); + if (s.theme_advanced_path) { + DOM.add(n, 'span', {id: ed.id + '_path_voice'}, ed.translate('advanced.path')); + DOM.add(n, 'span', {}, ': '); + } else { + DOM.add(n, 'span', {}, '&#160;'); + } + + + if (s.theme_advanced_resizing) { + DOM.add(td, 'a', {id : ed.id + '_resize', href : 'javascript:;', onclick : "return false;", 'class' : 'mceResize', tabIndex:"-1"}); + + if (s.theme_advanced_resizing_use_cookie) { + ed.onPostRender.add(function() { + var o = Cookie.getHash("TinyMCE_" + ed.id + "_size"), c = DOM.get(ed.id + '_tbl'); + + if (!o) + return; + + t.resizeTo(o.cw, o.ch); + }); + } + + ed.onPostRender.add(function() { + Event.add(ed.id + '_resize', 'click', function(e) { + e.preventDefault(); + }); + + Event.add(ed.id + '_resize', 'mousedown', function(e) { + var mouseMoveHandler1, mouseMoveHandler2, + mouseUpHandler1, mouseUpHandler2, + startX, startY, startWidth, startHeight, width, height, ifrElm; + + function resizeOnMove(e) { + e.preventDefault(); + + width = startWidth + (e.screenX - startX); + height = startHeight + (e.screenY - startY); + + t.resizeTo(width, height); + }; + + function endResize(e) { + // Stop listening + Event.remove(DOM.doc, 'mousemove', mouseMoveHandler1); + Event.remove(ed.getDoc(), 'mousemove', mouseMoveHandler2); + Event.remove(DOM.doc, 'mouseup', mouseUpHandler1); + Event.remove(ed.getDoc(), 'mouseup', mouseUpHandler2); + + width = startWidth + (e.screenX - startX); + height = startHeight + (e.screenY - startY); + t.resizeTo(width, height, true); + }; + + e.preventDefault(); + + // Get the current rect size + startX = e.screenX; + startY = e.screenY; + ifrElm = DOM.get(t.editor.id + '_ifr'); + startWidth = width = ifrElm.clientWidth; + startHeight = height = ifrElm.clientHeight; + + // Register envent handlers + mouseMoveHandler1 = Event.add(DOM.doc, 'mousemove', resizeOnMove); + mouseMoveHandler2 = Event.add(ed.getDoc(), 'mousemove', resizeOnMove); + mouseUpHandler1 = Event.add(DOM.doc, 'mouseup', endResize); + mouseUpHandler2 = Event.add(ed.getDoc(), 'mouseup', endResize); + }); + }); + } + + o.deltaHeight -= 21; + n = tb = null; + }, + + _updateUndoStatus : function(ed) { + var cm = ed.controlManager, um = ed.undoManager; + + cm.setDisabled('undo', !um.hasUndo() && !um.typing); + cm.setDisabled('redo', !um.hasRedo()); + }, + + _nodeChanged : function(ed, cm, n, co, ob) { + var t = this, p, de = 0, v, c, s = t.settings, cl, fz, fn, fc, bc, formatNames, matches; + + tinymce.each(t.stateControls, function(c) { + cm.setActive(c, ed.queryCommandState(t.controls[c][1])); + }); + + function getParent(name) { + var i, parents = ob.parents, func = name; + + if (typeof(name) == 'string') { + func = function(node) { + return node.nodeName == name; + }; + } + + for (i = 0; i < parents.length; i++) { + if (func(parents[i])) + return parents[i]; + } + }; + + cm.setActive('visualaid', ed.hasVisual); + t._updateUndoStatus(ed); + cm.setDisabled('outdent', !ed.queryCommandState('Outdent')); + + p = getParent('A'); + if (c = cm.get('link')) { + if (!p || !p.name) { + c.setDisabled(!p && co); + c.setActive(!!p); + } + } + + if (c = cm.get('unlink')) { + c.setDisabled(!p && co); + c.setActive(!!p && !p.name); + } + + if (c = cm.get('anchor')) { + c.setActive(!co && !!p && p.name); + } + + p = getParent('IMG'); + if (c = cm.get('image')) + c.setActive(!co && !!p && n.className.indexOf('mceItem') == -1); + + if (c = cm.get('styleselect')) { + t._importClasses(); + + formatNames = []; + each(c.items, function(item) { + formatNames.push(item.value); + }); + + matches = ed.formatter.matchAll(formatNames); + c.select(matches[0]); + } + + if (c = cm.get('formatselect')) { + p = getParent(DOM.isBlock); + + if (p) + c.select(p.nodeName.toLowerCase()); + } + + // Find out current fontSize, fontFamily and fontClass + getParent(function(n) { + if (n.nodeName === 'SPAN') { + if (!cl && n.className) + cl = n.className; + } + + if (ed.dom.is(n, s.theme_advanced_font_selector)) { + if (!fz && n.style.fontSize) + fz = n.style.fontSize; + + if (!fn && n.style.fontFamily) + fn = n.style.fontFamily.replace(/[\"\']+/g, '').replace(/^([^,]+).*/, '$1').toLowerCase(); + + if (!fc && n.style.color) + fc = n.style.color; + + if (!bc && n.style.backgroundColor) + bc = n.style.backgroundColor; + } + + return false; + }); + + if (c = cm.get('fontselect')) { + c.select(function(v) { + return v.replace(/^([^,]+).*/, '$1').toLowerCase() == fn; + }); + } + + // Select font size + if (c = cm.get('fontsizeselect')) { + // Use computed style + if (s.theme_advanced_runtime_fontsize && !fz && !cl) + fz = ed.dom.getStyle(n, 'fontSize', true); + + c.select(function(v) { + if (v.fontSize && v.fontSize === fz) + return true; + + if (v['class'] && v['class'] === cl) + return true; + }); + } + + if (s.theme_advanced_show_current_color) { + function updateColor(controlId, color) { + if (c = cm.get(controlId)) { + if (!color) + color = c.settings.default_color; + if (color !== c.value) { + c.displayColor(color); + } + } + } + updateColor('forecolor', fc); + updateColor('backcolor', bc); + } + + if (s.theme_advanced_show_current_color) { + function updateColor(controlId, color) { + if (c = cm.get(controlId)) { + if (!color) + color = c.settings.default_color; + if (color !== c.value) { + c.displayColor(color); + } + } + }; + + updateColor('forecolor', fc); + updateColor('backcolor', bc); + } + + if (s.theme_advanced_path && s.theme_advanced_statusbar_location) { + p = DOM.get(ed.id + '_path') || DOM.add(ed.id + '_path_row', 'span', {id : ed.id + '_path'}); + + if (t.statusKeyboardNavigation) { + t.statusKeyboardNavigation.destroy(); + t.statusKeyboardNavigation = null; + } + + DOM.setHTML(p, ''); + + getParent(function(n) { + var na = n.nodeName.toLowerCase(), u, pi, ti = ''; + + // Ignore non element and bogus/hidden elements + if (n.nodeType != 1 || na === 'br' || n.getAttribute('data-mce-bogus') || DOM.hasClass(n, 'mceItemHidden') || DOM.hasClass(n, 'mceItemRemoved')) + return; + + // Handle prefix + if (tinymce.isIE && n.scopeName !== 'HTML') + na = n.scopeName + ':' + na; + + // Remove internal prefix + na = na.replace(/mce\:/g, ''); + + // Handle node name + switch (na) { + case 'b': + na = 'strong'; + break; + + case 'i': + na = 'em'; + break; + + case 'img': + if (v = DOM.getAttrib(n, 'src')) + ti += 'src: ' + v + ' '; + + break; + + case 'a': + if (v = DOM.getAttrib(n, 'name')) { + ti += 'name: ' + v + ' '; + na += '#' + v; + } + + if (v = DOM.getAttrib(n, 'href')) + ti += 'href: ' + v + ' '; + + break; + + case 'font': + if (v = DOM.getAttrib(n, 'face')) + ti += 'font: ' + v + ' '; + + if (v = DOM.getAttrib(n, 'size')) + ti += 'size: ' + v + ' '; + + if (v = DOM.getAttrib(n, 'color')) + ti += 'color: ' + v + ' '; + + break; + + case 'span': + if (v = DOM.getAttrib(n, 'style')) + ti += 'style: ' + v + ' '; + + break; + } + + if (v = DOM.getAttrib(n, 'id')) + ti += 'id: ' + v + ' '; + + if (v = n.className) { + v = v.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g, '') + + if (v) { + ti += 'class: ' + v + ' '; + + if (DOM.isBlock(n) || na == 'img' || na == 'span') + na += '.' + v; + } + } + + na = na.replace(/(html:)/g, ''); + na = {name : na, node : n, title : ti}; + t.onResolveName.dispatch(t, na); + ti = na.title; + na = na.name; + + //u = "javascript:tinymce.EditorManager.get('" + ed.id + "').theme._sel('" + (de++) + "');"; + pi = DOM.create('a', {'href' : "javascript:;", role: 'button', onmousedown : "return false;", title : ti, 'class' : 'mcePath_' + (de++)}, na); + + if (p.hasChildNodes()) { + p.insertBefore(DOM.create('span', {'aria-hidden': 'true'}, '\u00a0\u00bb '), p.firstChild); + p.insertBefore(pi, p.firstChild); + } else + p.appendChild(pi); + }, ed.getBody()); + + if (DOM.select('a', p).length > 0) { + t.statusKeyboardNavigation = new tinymce.ui.KeyboardNavigation({ + root: ed.id + "_path_row", + items: DOM.select('a', p), + excludeFromTabOrder: true, + onCancel: function() { + ed.focus(); + } + }, DOM); + } + } + }, + + // Commands gets called by execCommand + + _sel : function(v) { + this.editor.execCommand('mceSelectNodeDepth', false, v); + }, + + _mceInsertAnchor : function(ui, v) { + var ed = this.editor; + + ed.windowManager.open({ + url : this.url + '/anchor.htm', + width : 320 + parseInt(ed.getLang('advanced.anchor_delta_width', 0)), + height : 90 + parseInt(ed.getLang('advanced.anchor_delta_height', 0)), + inline : true + }, { + theme_url : this.url + }); + }, + + _mceCharMap : function() { + var ed = this.editor; + + ed.windowManager.open({ + url : this.url + '/charmap.htm', + width : 550 + parseInt(ed.getLang('advanced.charmap_delta_width', 0)), + height : 250 + parseInt(ed.getLang('advanced.charmap_delta_height', 0)), + inline : true + }, { + theme_url : this.url + }); + }, + + _mceHelp : function() { + var ed = this.editor; + + ed.windowManager.open({ + url : this.url + '/about.htm', + width : 480, + height : 380, + inline : true + }, { + theme_url : this.url + }); + }, + + _mceShortcuts : function() { + var ed = this.editor; + ed.windowManager.open({ + url: this.url + '/shortcuts.htm', + width: 480, + height: 380, + inline: true + }, { + theme_url: this.url + }); + }, + + _mceColorPicker : function(u, v) { + var ed = this.editor; + + v = v || {}; + + ed.windowManager.open({ + url : this.url + '/color_picker.htm', + width : 375 + parseInt(ed.getLang('advanced.colorpicker_delta_width', 0)), + height : 250 + parseInt(ed.getLang('advanced.colorpicker_delta_height', 0)), + close_previous : false, + inline : true + }, { + input_color : v.color, + func : v.func, + theme_url : this.url + }); + }, + + _mceCodeEditor : function(ui, val) { + var ed = this.editor; + + ed.windowManager.open({ + url : this.url + '/source_editor.htm', + width : parseInt(ed.getParam("theme_advanced_source_editor_width", 720)), + height : parseInt(ed.getParam("theme_advanced_source_editor_height", 580)), + inline : true, + resizable : true, + maximizable : true + }, { + theme_url : this.url + }); + }, + + _mceImage : function(ui, val) { + var ed = this.editor; + + // Internal image object like a flash placeholder + if (ed.dom.getAttrib(ed.selection.getNode(), 'class').indexOf('mceItem') != -1) + return; + + ed.windowManager.open({ + url : this.url + '/image.htm', + width : 355 + parseInt(ed.getLang('advanced.image_delta_width', 0)), + height : 275 + parseInt(ed.getLang('advanced.image_delta_height', 0)), + inline : true + }, { + theme_url : this.url + }); + }, + + _mceLink : function(ui, val) { + var ed = this.editor; + + ed.windowManager.open({ + url : this.url + '/link.htm', + width : 310 + parseInt(ed.getLang('advanced.link_delta_width', 0)), + height : 200 + parseInt(ed.getLang('advanced.link_delta_height', 0)), + inline : true + }, { + theme_url : this.url + }); + }, + + _mceNewDocument : function() { + var ed = this.editor; + + ed.windowManager.confirm('advanced.newdocument', function(s) { + if (s) + ed.execCommand('mceSetContent', false, ''); + }); + }, + + _mceForeColor : function() { + var t = this; + + this._mceColorPicker(0, { + color: t.fgColor, + func : function(co) { + t.fgColor = co; + t.editor.execCommand('ForeColor', false, co); + } + }); + }, + + _mceBackColor : function() { + var t = this; + + this._mceColorPicker(0, { + color: t.bgColor, + func : function(co) { + t.bgColor = co; + t.editor.execCommand('HiliteColor', false, co); + } + }); + }, + + _ufirst : function(s) { + return s.substring(0, 1).toUpperCase() + s.substring(1); + } + }); + + tinymce.ThemeManager.add('advanced', tinymce.themes.AdvancedTheme); +}(tinymce)); diff --git a/src/core/static/js/tiny_mce/themes/advanced/image.htm b/src/core/static/js/tiny_mce/themes/advanced/image.htm new file mode 100644 index 0000000..b8ba729 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/image.htm @@ -0,0 +1,80 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.image_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="js/image.js"></script> +</head> +<body id="image" style="display: none"> +<form onsubmit="ImageDialog.update();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.image_title}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="nowrap"><label for="src">{#advanced_dlg.image_src}</label></td> + <td><table border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="src" name="src" type="text" class="mceFocus" value="" style="width: 200px" onchange="ImageDialog.getImageData();" /></td> + <td id="srcbrowsercontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td><label for="image_list">{#advanced_dlg.image_list}</label></td> + <td><select id="image_list" name="image_list" onchange="document.getElementById('src').value=this.options[this.selectedIndex].value;document.getElementById('alt').value=this.options[this.selectedIndex].text;"></select></td> + </tr> + <tr> + <td class="nowrap"><label for="alt">{#advanced_dlg.image_alt}</label></td> + <td><input id="alt" name="alt" type="text" value="" style="width: 200px" /></td> + </tr> + <tr> + <td class="nowrap"><label for="align">{#advanced_dlg.image_align}</label></td> + <td><select id="align" name="align" onchange="ImageDialog.updateStyle();"> + <option value="">{#not_set}</option> + <option value="baseline">{#advanced_dlg.image_align_baseline}</option> + <option value="top">{#advanced_dlg.image_align_top}</option> + <option value="middle">{#advanced_dlg.image_align_middle}</option> + <option value="bottom">{#advanced_dlg.image_align_bottom}</option> + <option value="text-top">{#advanced_dlg.image_align_texttop}</option> + <option value="text-bottom">{#advanced_dlg.image_align_textbottom}</option> + <option value="left">{#advanced_dlg.image_align_left}</option> + <option value="right">{#advanced_dlg.image_align_right}</option> + </select></td> + </tr> + <tr> + <td class="nowrap"><label for="width">{#advanced_dlg.image_dimensions}</label></td> + <td><input id="width" name="width" type="text" value="" size="3" maxlength="5" /> + x + <input id="height" name="height" type="text" value="" size="3" maxlength="5" /></td> + </tr> + <tr> + <td class="nowrap"><label for="border">{#advanced_dlg.image_border}</label></td> + <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td> + </tr> + <tr> + <td class="nowrap"><label for="vspace">{#advanced_dlg.image_vspace}</label></td> + <td><input id="vspace" name="vspace" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td> + </tr> + <tr> + <td class="nowrap"><label for="hspace">{#advanced_dlg.image_hspace}</label></td> + <td><input id="hspace" name="hspace" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td> + </tr> + </table> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/themes/advanced/img/colorpicker.jpg b/src/core/static/js/tiny_mce/themes/advanced/img/colorpicker.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b1a377aba7784d3a0a0fabb4d22b8114cde25ace GIT binary patch literal 2584 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 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/img/flash.gif b/src/core/static/js/tiny_mce/themes/advanced/img/flash.gif new file mode 100644 index 0000000000000000000000000000000000000000..dec3f7c7028df98657860529461af29b8793601c GIT binary patch literal 239 zcmV<L01*F2Nk%w1VH5xq0P_z3YJHAwilWKS*;Z<L?e6iex5E`&f8F2Yf{&g3{rv|x zTAiq{x5Lr`C`yW(uK)l5A^8La000jFEC2ui02BZe06+ws@X1N5eMlUVdNW3$9SmZT z&ejo!!yFgE0ODZ_#R4!yB?`cXLQ!DZ4u!(yLC_5bfJHCn&~OrjA?P4*OeFwKCm|dv zi~>M~p;I&fgwbZVtlRJPxC7uw?yFxEX;uVr4IeWCJ^(5m4hjYVM>G^+2V)FnXE$mS p86yHh03AmHCKD}bWutOkFce4&0zF5CG_Myp4hRT+ig>^g06S0cRV@Gj literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/img/icons.gif b/src/core/static/js/tiny_mce/themes/advanced/img/icons.gif new file mode 100644 index 0000000000000000000000000000000000000000..641a9e3d314f4ea051692a2274aeb281456f5df9 GIT binary patch literal 11790 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 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/img/iframe.gif b/src/core/static/js/tiny_mce/themes/advanced/img/iframe.gif new file mode 100644 index 0000000000000000000000000000000000000000..410c7ad084db698e9f35e3230233aa4040682566 GIT binary patch literal 600 zcmZ?wbhEHb6krfwcoxm@|NsB$<##6SeDUYszh8g<{{H*-%a7k_-3KZc-T3+YPwBiX zzyAIE^Y`z!U%$Wp{QdX;|FQ*Fw;jIy{pasbUw?o3{yVB>Q_sR<KmYuB{`zY~^~S1Y zciw#Z@#p{luRnhO{QLLE-@o7g{7Got_4nVux1YbidjG9*@y-0{XY!|=4lZ6<Jm+Fq z+1kX`-QR!z2`*lB@A;>gx-G9iegFLZcfrha#d9w;%sU=Zx~6K$tw~$%z4`#O^Y@3Z zKV#~)MpSKh@#b63l#}6=>yq2|{`&JLqwny)|NnC)o%r$l&-Y)yKYjo8?#quSuRaGB zt_&<%`RV)bl#YEr{`~p)?RU|v^Y1_Z`u*?Ux8J`*N>>+5JlMAOZr+qr@y$D{mfVhO z+zt#7208-8pDc_F4ABfaAUi>E!oa?@A-bu#r8Qd6oKeb*Lx9UTz)0QBL@+vxY38ii zvqGa87c5+~h&?)zVa3W-D;=U$88}^qMBJ^ERU|z17!;#97+4%Rd1XcXJq#>t8KR;E z7<gD&#C7=C421)w8LXqZ7?@cv%J~Uh^ATncjn;g?{P2>zr5i6BgH5y=gAD)sAQlGB zh8au?j!n~E(Pks?@!j1fR&j<cH=I(Yx`udfix4PUaFR<$Un}Lu!X_>*RWY8GF(-=x H6d0@lT&58X literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/img/pagebreak.gif b/src/core/static/js/tiny_mce/themes/advanced/img/pagebreak.gif new file mode 100644 index 0000000000000000000000000000000000000000..acdf4085f3068c4c0a1d6855f4b80dae8bac3068 GIT binary patch literal 325 zcmV-L0lNN2Nk%w1VPpUd0J9GO`>v<{=;ru;boX6P{`2zsmyZ3>&HK5t_;hIbi-G;z z+4`cI{KdfcXj}GCLjV8&A^8LW000jFEC2ui0Av6R000E?@X1N5y*TU5yZ>M)j$|1M z4Ouvb$pHu>IW8BZq|n;U0s@T!VM5~w1_+1X!EiVl!&PITYdjT!ffYfpt{jAfv%qvh zA63WUHSlr7LkeyaV4(pM0f50(II?RD4RtMg4-E+tFhdAy5{3c=0}3Bg9Y8`B2To20 zR%SO62L%9}0H+dzoKB$+2TOwzUrwi{XiBM^4V#>63q3!LsU3u93zH8CdwqY%62;1g z0g8ze$k93lWExp`CUe|K4qOWk17ZeJ0|5pDP6+}};{>bI@lOWj=kf}r2sHp7w9-Ie XK%9UG6W(*AX-vY05F<*&5CH%?Gwy&_ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/img/quicktime.gif b/src/core/static/js/tiny_mce/themes/advanced/img/quicktime.gif new file mode 100644 index 0000000000000000000000000000000000000000..8f10e7aa6b6ab40ee69a1a41a961c092168d6fda GIT binary patch literal 301 zcmV+|0n+|QNk%w1VGsZi0Q4UK+~)L6v+~s9^fsC5ZpZP=*zu3F=Jxpf8k_5u%JNv6 z=md-84VLU4w)kSE=yI&-yw>b=v+SqE?+kq47pC+YrR?bJ^yu>Zyvpn;hTp*6^mM!O zu+8!}sO$`q<p2NwA^8La0018VEC2ui01yBW06+z*;3tYl0b#{4ii5Xs;uR2=_;^fo zWDC-1qryV~Stvvritq6-7#;xx!V|!VI2kE}qGSvd0+C|D*aRJj0HEVCNTwOcN@Vch z03!gQ!RL1p348;2Pa6>%8%`=C5EEn#1d#z95FHtK5(^#(cp^e+Y!d=4FCrFbY9A3U z4-O0-4kHJPJ2(jk13n5879s!!3Q`V>8VwW`9my3H#|R8ZD+fdx0E-+693cQZ;!k;* literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/img/realmedia.gif b/src/core/static/js/tiny_mce/themes/advanced/img/realmedia.gif new file mode 100644 index 0000000000000000000000000000000000000000..fdfe0b9ac05869ae845fdd828eaad97cc0c69dbc GIT binary patch literal 439 zcmV;o0Z9HwNk%w1VI=?(0K^{vQcz8xz}f&njBB06v9GQ`Jv%NdDHCI&z`wqZw$(Lw zuFTBL!Pe#<92tv>h)9OE1Xh}vnVEHSaeb-GByg#tqM_B*)YRkdSdqTu<Kq($4eIgt z07{c)W@Z2Y0RR90A^8LW0018VEC2ui03`qt000I5;3tmX6%3D}JVU~ea4d`4L_vbU z?R!oQuNiDZ90d+Lh@ur}CQvxRV<Qx03Jr;9kQ`iu8)s06@OUDh#O^TuSUR0br;y1w z00jxcDls$+9Rwc|9vTZ9NC#ge4rUr200@t8W`Y171r7xs4H=gP8w@)SF#sAG4s`|| z1`!brkZu*Tn+6N39Ur0`7(=T7A`7Pl003~V4I0GBk&kGI90yb*k{%9LupJo$4h|NN zbOg?g8W|#L917Eeg?l0d$&Vfq8<!de2B!p<1q2IQYbH?1u;3qw4G1a_F!zptg$xJ| zEkIx)q7e!?4qyntfXKQ4DFjvllRyE792_7taG3BR07ec2){PXxV8R0m2M#27utPzc hnLsyCNWv1RQ6oJU9W}ZE0)zxhqYhA@G%AS@06S<cl~n)$ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/img/shockwave.gif b/src/core/static/js/tiny_mce/themes/advanced/img/shockwave.gif new file mode 100644 index 0000000000000000000000000000000000000000..9314d044709c9845876e08003cf94526fd69177f GIT binary patch literal 384 zcmZ?wbhEHb6lD-#_^Qe9?Af#b->&}n`s(k;lb>H+`#+Q6|3c{>OLTv23;utm>DSfy zuOD3adm!iUuGar)4FAhzel5=UwZ7*6(K(+k@BP_g{o}}@k7u_2k7W2iGwlom!+#Z( z|Hj5w_4MwTo8QaHxm#EFYX1DUOO|}vvgQBb!_ST${rmj+`+Fep|C$j4HGtwz7FGrZ zO$Hs1VIV&_u+2R%#bJV$RKJIcL*N7vss0Y-EsB{gGlSJaTr>sRLKbLj5HMTpyK;)l zJcfpaMYltBZdEK6Kht6+BPy*VtthFMtIoqFC=#Tu$e^eaDXCC7U0vOYOJjNk(;P<O z+?*WGIXu2>!V<jVVxdx#m$@=9ujFJ8P~>agC#fQ*?7otVO)-#9rK#nB%ry4`E_DHQ Wm01j~^6E13^D1O7+^=wCum%9s<%z=p literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/img/trans.gif b/src/core/static/js/tiny_mce/themes/advanced/img/trans.gif new file mode 100644 index 0000000000000000000000000000000000000000..388486517fa8da13ebd150e8f65d5096c3e10c3a GIT binary patch literal 43 ncmZ?wbhEHbWMp7un7{x9ia%KxMSyG_5FaGNz{KRj$Y2csb)f_x literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/img/video.gif b/src/core/static/js/tiny_mce/themes/advanced/img/video.gif new file mode 100644 index 0000000000000000000000000000000000000000..3570104077a3b3585f11403c8d4c3fc9351f35d2 GIT binary patch literal 597 zcmZ?wbhEHb6krfwc$UTx9v<%P?Ok48Ze?YanwpxCkzrwBk(ZYzB_&l;Q<IsQ8F##3 z&6+hjyS!_6-?m?OIypHx=Cr@-5&wj}H`bh97ZVd>w!gmM(Ep^QBwbzIoSdAh>*2n> zz9l6k0Xw#(?);y5^ls9w|LObxXI*si^YfcEYu3*P8J(S-PEJlaNB-yTd}C^Ax@_69 zzP`Ryt5)S5`=P3;TDk9SbaeFk_3NiTjGA~aFd-pf@}tlxQ>GLb7jM|Gp`oFHlaq7F zk|nvhxjsHV=g+oST3Rl6T(N1>rn0iK*Ed>3MMVn>3vF#}<Kp6$Jg%90KfnCM|DvP+ z<KyEe-;F<iW5)F9(>**q!otE>Sy|^jDoRUBoBANRc=wyaJ<nc0nc3Rf>ged$+}u3x zK}ld>puWET<a=QO0RcuvMvEU*R8>{||NozXdO-0f3nK$V8iNkVNKl+Guy1NeYie$3 zZB}=&Zex!RYq8YfVwgNdMpdFkN|rU!Fha}0m66q>CDxczOhH^pM9qvxw1p`;Rftzu zQJ&9}g>iErlc2ORw;aC_=l*6UJ=st%r*ISVV2jgDT<)w>rX<Tawy@hu>HGL<21Kdo z#<Z}gv#eUPE{L72Mbyr3`_A1O_6G!-4lo?pkaV1FiiAT30~@pViHb_0Wo%3wHXM={ aHZHoY!s6T`pfu63XCY5W0tXihgEasdRMD9L literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/img/windowsmedia.gif b/src/core/static/js/tiny_mce/themes/advanced/img/windowsmedia.gif new file mode 100644 index 0000000000000000000000000000000000000000..ab50f2d887a0843b116ef598e5a005e5601d18d0 GIT binary patch literal 415 zcmV;Q0bu?|Nk%w1VGjTg0M$PL`E^qkEu+z?1&N?x_*pRg{rx~kg!#|I<>uyug^O^t z0hZGrt*x!>$1C!zn`W5@`ts6_uMW)2%<0NUEKIo?SIPPE=}U0}7Z(?JcX!y=*;bF< zCWz-=h7+2ao9)(dOHM;+X=xs9)%!~xc&ICMZdRYdUQ2$^@9y(6X3NCIz{cM7f^Z=Q z1_tQ95kgl8b%R%OiYTIo7LSdE^<g{S%f{2(!x(nqRGjHZr0IW^!yX<Ufq!q~!#RbG zsQ>@}A^8LW002J#EC2ui01p5U000KOz@O0K01zUifeIyT9%!RzMDgehG|mwLz+Eh; z7Z~<O+d66*jm@O!TxJNz2;i`UR0tHx^tgZ+0CP1KAR!ql1qdV^FA0GF8iXJ_Eg=Xd zF)utP961Ptlsgg#A3Xw_HykS#I~WWS1r`&g89Eg=I4CoS1qB}yE;0!k6cr*HE4>iE zrX?OfJ^>XeDJK)xJuWOB3_l1N0Ra>g4Gk^=ED0V6LI?>4;Q|6OB{LplLMRLg8U5-E J?0y6R06W6!pgRBn literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/js/about.js b/src/core/static/js/tiny_mce/themes/advanced/js/about.js new file mode 100644 index 0000000..5b35845 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/js/about.js @@ -0,0 +1,73 @@ +tinyMCEPopup.requireLangPack(); + +function init() { + var ed, tcont; + + tinyMCEPopup.resizeToInnerSize(); + ed = tinyMCEPopup.editor; + + // Give FF some time + window.setTimeout(insertHelpIFrame, 10); + + tcont = document.getElementById('plugintablecontainer'); + document.getElementById('plugins_tab').style.display = 'none'; + + var html = ""; + html += '<table id="plugintable">'; + html += '<thead>'; + html += '<tr>'; + html += '<td>' + ed.getLang('advanced_dlg.about_plugin') + '</td>'; + html += '<td>' + ed.getLang('advanced_dlg.about_author') + '</td>'; + html += '<td>' + ed.getLang('advanced_dlg.about_version') + '</td>'; + html += '</tr>'; + html += '</thead>'; + html += '<tbody>'; + + tinymce.each(ed.plugins, function(p, n) { + var info; + + if (!p.getInfo) + return; + + html += '<tr>'; + + info = p.getInfo(); + + if (info.infourl != null && info.infourl != '') + html += '<td width="50%" title="' + n + '"><a href="' + info.infourl + '" target="_blank">' + info.longname + '</a></td>'; + else + html += '<td width="50%" title="' + n + '">' + info.longname + '</td>'; + + if (info.authorurl != null && info.authorurl != '') + html += '<td width="35%"><a href="' + info.authorurl + '" target="_blank">' + info.author + '</a></td>'; + else + html += '<td width="35%">' + info.author + '</td>'; + + html += '<td width="15%">' + info.version + '</td>'; + html += '</tr>'; + + document.getElementById('plugins_tab').style.display = ''; + + }); + + html += '</tbody>'; + html += '</table>'; + + tcont.innerHTML = html; + + tinyMCEPopup.dom.get('version').innerHTML = tinymce.majorVersion + "." + tinymce.minorVersion; + tinyMCEPopup.dom.get('date').innerHTML = tinymce.releaseDate; +} + +function insertHelpIFrame() { + var html; + + if (tinyMCEPopup.getParam('docs_url')) { + html = '<iframe width="100%" height="300" src="' + tinyMCEPopup.editor.baseURI.toAbsolute(tinyMCEPopup.getParam('docs_url')) + '"></iframe>'; + document.getElementById('iframecontainer').innerHTML = html; + document.getElementById('help_tab').style.display = 'block'; + document.getElementById('help_tab').setAttribute("aria-hidden", "false"); + } +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/themes/advanced/js/anchor.js b/src/core/static/js/tiny_mce/themes/advanced/js/anchor.js new file mode 100644 index 0000000..04f41e0 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/js/anchor.js @@ -0,0 +1,43 @@ +tinyMCEPopup.requireLangPack(); + +var AnchorDialog = { + init : function(ed) { + var action, elm, f = document.forms[0]; + + this.editor = ed; + elm = ed.dom.getParent(ed.selection.getNode(), 'A'); + v = ed.dom.getAttrib(elm, 'name'); + + if (v) { + this.action = 'update'; + f.anchorName.value = v; + } + + f.insert.value = ed.getLang(elm ? 'update' : 'insert'); + }, + + update : function() { + var ed = this.editor, elm, name = document.forms[0].anchorName.value; + + if (!name || !/^[a-z][a-z0-9\-\_:\.]*$/i.test(name)) { + tinyMCEPopup.alert('advanced_dlg.anchor_invalid'); + return; + } + + tinyMCEPopup.restoreSelection(); + + if (this.action != 'update') + ed.selection.collapse(1); + + elm = ed.dom.getParent(ed.selection.getNode(), 'A'); + if (elm) { + elm.setAttribute('name', name); + elm.name = name; + } else + ed.execCommand('mceInsertContent', 0, ed.dom.createHTML('a', {name : name, 'class' : 'mceItemAnchor'}, '')); + + tinyMCEPopup.close(); + } +}; + +tinyMCEPopup.onInit.add(AnchorDialog.init, AnchorDialog); diff --git a/src/core/static/js/tiny_mce/themes/advanced/js/charmap.js b/src/core/static/js/tiny_mce/themes/advanced/js/charmap.js new file mode 100644 index 0000000..1cead6d --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/js/charmap.js @@ -0,0 +1,355 @@ +/** + * charmap.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +tinyMCEPopup.requireLangPack(); + +var charmap = [ + ['&nbsp;', '&#160;', true, 'no-break space'], + ['&amp;', '&#38;', true, 'ampersand'], + ['&quot;', '&#34;', true, 'quotation mark'], +// finance + ['&cent;', '&#162;', true, 'cent sign'], + ['&euro;', '&#8364;', true, 'euro sign'], + ['&pound;', '&#163;', true, 'pound sign'], + ['&yen;', '&#165;', true, 'yen sign'], +// signs + ['&copy;', '&#169;', true, 'copyright sign'], + ['&reg;', '&#174;', true, 'registered sign'], + ['&trade;', '&#8482;', true, 'trade mark sign'], + ['&permil;', '&#8240;', true, 'per mille sign'], + ['&micro;', '&#181;', true, 'micro sign'], + ['&middot;', '&#183;', true, 'middle dot'], + ['&bull;', '&#8226;', true, 'bullet'], + ['&hellip;', '&#8230;', true, 'three dot leader'], + ['&prime;', '&#8242;', true, 'minutes / feet'], + ['&Prime;', '&#8243;', true, 'seconds / inches'], + ['&sect;', '&#167;', true, 'section sign'], + ['&para;', '&#182;', true, 'paragraph sign'], + ['&szlig;', '&#223;', true, 'sharp s / ess-zed'], +// quotations + ['&lsaquo;', '&#8249;', true, 'single left-pointing angle quotation mark'], + ['&rsaquo;', '&#8250;', true, 'single right-pointing angle quotation mark'], + ['&laquo;', '&#171;', true, 'left pointing guillemet'], + ['&raquo;', '&#187;', true, 'right pointing guillemet'], + ['&lsquo;', '&#8216;', true, 'left single quotation mark'], + ['&rsquo;', '&#8217;', true, 'right single quotation mark'], + ['&ldquo;', '&#8220;', true, 'left double quotation mark'], + ['&rdquo;', '&#8221;', true, 'right double quotation mark'], + ['&sbquo;', '&#8218;', true, 'single low-9 quotation mark'], + ['&bdquo;', '&#8222;', true, 'double low-9 quotation mark'], + ['&lt;', '&#60;', true, 'less-than sign'], + ['&gt;', '&#62;', true, 'greater-than sign'], + ['&le;', '&#8804;', true, 'less-than or equal to'], + ['&ge;', '&#8805;', true, 'greater-than or equal to'], + ['&ndash;', '&#8211;', true, 'en dash'], + ['&mdash;', '&#8212;', true, 'em dash'], + ['&macr;', '&#175;', true, 'macron'], + ['&oline;', '&#8254;', true, 'overline'], + ['&curren;', '&#164;', true, 'currency sign'], + ['&brvbar;', '&#166;', true, 'broken bar'], + ['&uml;', '&#168;', true, 'diaeresis'], + ['&iexcl;', '&#161;', true, 'inverted exclamation mark'], + ['&iquest;', '&#191;', true, 'turned question mark'], + ['&circ;', '&#710;', true, 'circumflex accent'], + ['&tilde;', '&#732;', true, 'small tilde'], + ['&deg;', '&#176;', true, 'degree sign'], + ['&minus;', '&#8722;', true, 'minus sign'], + ['&plusmn;', '&#177;', true, 'plus-minus sign'], + ['&divide;', '&#247;', true, 'division sign'], + ['&frasl;', '&#8260;', true, 'fraction slash'], + ['&times;', '&#215;', true, 'multiplication sign'], + ['&sup1;', '&#185;', true, 'superscript one'], + ['&sup2;', '&#178;', true, 'superscript two'], + ['&sup3;', '&#179;', true, 'superscript three'], + ['&frac14;', '&#188;', true, 'fraction one quarter'], + ['&frac12;', '&#189;', true, 'fraction one half'], + ['&frac34;', '&#190;', true, 'fraction three quarters'], +// math / logical + ['&fnof;', '&#402;', true, 'function / florin'], + ['&int;', '&#8747;', true, 'integral'], + ['&sum;', '&#8721;', true, 'n-ary sumation'], + ['&infin;', '&#8734;', true, 'infinity'], + ['&radic;', '&#8730;', true, 'square root'], + ['&sim;', '&#8764;', false,'similar to'], + ['&cong;', '&#8773;', false,'approximately equal to'], + ['&asymp;', '&#8776;', true, 'almost equal to'], + ['&ne;', '&#8800;', true, 'not equal to'], + ['&equiv;', '&#8801;', true, 'identical to'], + ['&isin;', '&#8712;', false,'element of'], + ['&notin;', '&#8713;', false,'not an element of'], + ['&ni;', '&#8715;', false,'contains as member'], + ['&prod;', '&#8719;', true, 'n-ary product'], + ['&and;', '&#8743;', false,'logical and'], + ['&or;', '&#8744;', false,'logical or'], + ['&not;', '&#172;', true, 'not sign'], + ['&cap;', '&#8745;', true, 'intersection'], + ['&cup;', '&#8746;', false,'union'], + ['&part;', '&#8706;', true, 'partial differential'], + ['&forall;', '&#8704;', false,'for all'], + ['&exist;', '&#8707;', false,'there exists'], + ['&empty;', '&#8709;', false,'diameter'], + ['&nabla;', '&#8711;', false,'backward difference'], + ['&lowast;', '&#8727;', false,'asterisk operator'], + ['&prop;', '&#8733;', false,'proportional to'], + ['&ang;', '&#8736;', false,'angle'], +// undefined + ['&acute;', '&#180;', true, 'acute accent'], + ['&cedil;', '&#184;', true, 'cedilla'], + ['&ordf;', '&#170;', true, 'feminine ordinal indicator'], + ['&ordm;', '&#186;', true, 'masculine ordinal indicator'], + ['&dagger;', '&#8224;', true, 'dagger'], + ['&Dagger;', '&#8225;', true, 'double dagger'], +// alphabetical special chars + ['&Agrave;', '&#192;', true, 'A - grave'], + ['&Aacute;', '&#193;', true, 'A - acute'], + ['&Acirc;', '&#194;', true, 'A - circumflex'], + ['&Atilde;', '&#195;', true, 'A - tilde'], + ['&Auml;', '&#196;', true, 'A - diaeresis'], + ['&Aring;', '&#197;', true, 'A - ring above'], + ['&AElig;', '&#198;', true, 'ligature AE'], + ['&Ccedil;', '&#199;', true, 'C - cedilla'], + ['&Egrave;', '&#200;', true, 'E - grave'], + ['&Eacute;', '&#201;', true, 'E - acute'], + ['&Ecirc;', '&#202;', true, 'E - circumflex'], + ['&Euml;', '&#203;', true, 'E - diaeresis'], + ['&Igrave;', '&#204;', true, 'I - grave'], + ['&Iacute;', '&#205;', true, 'I - acute'], + ['&Icirc;', '&#206;', true, 'I - circumflex'], + ['&Iuml;', '&#207;', true, 'I - diaeresis'], + ['&ETH;', '&#208;', true, 'ETH'], + ['&Ntilde;', '&#209;', true, 'N - tilde'], + ['&Ograve;', '&#210;', true, 'O - grave'], + ['&Oacute;', '&#211;', true, 'O - acute'], + ['&Ocirc;', '&#212;', true, 'O - circumflex'], + ['&Otilde;', '&#213;', true, 'O - tilde'], + ['&Ouml;', '&#214;', true, 'O - diaeresis'], + ['&Oslash;', '&#216;', true, 'O - slash'], + ['&OElig;', '&#338;', true, 'ligature OE'], + ['&Scaron;', '&#352;', true, 'S - caron'], + ['&Ugrave;', '&#217;', true, 'U - grave'], + ['&Uacute;', '&#218;', true, 'U - acute'], + ['&Ucirc;', '&#219;', true, 'U - circumflex'], + ['&Uuml;', '&#220;', true, 'U - diaeresis'], + ['&Yacute;', '&#221;', true, 'Y - acute'], + ['&Yuml;', '&#376;', true, 'Y - diaeresis'], + ['&THORN;', '&#222;', true, 'THORN'], + ['&agrave;', '&#224;', true, 'a - grave'], + ['&aacute;', '&#225;', true, 'a - acute'], + ['&acirc;', '&#226;', true, 'a - circumflex'], + ['&atilde;', '&#227;', true, 'a - tilde'], + ['&auml;', '&#228;', true, 'a - diaeresis'], + ['&aring;', '&#229;', true, 'a - ring above'], + ['&aelig;', '&#230;', true, 'ligature ae'], + ['&ccedil;', '&#231;', true, 'c - cedilla'], + ['&egrave;', '&#232;', true, 'e - grave'], + ['&eacute;', '&#233;', true, 'e - acute'], + ['&ecirc;', '&#234;', true, 'e - circumflex'], + ['&euml;', '&#235;', true, 'e - diaeresis'], + ['&igrave;', '&#236;', true, 'i - grave'], + ['&iacute;', '&#237;', true, 'i - acute'], + ['&icirc;', '&#238;', true, 'i - circumflex'], + ['&iuml;', '&#239;', true, 'i - diaeresis'], + ['&eth;', '&#240;', true, 'eth'], + ['&ntilde;', '&#241;', true, 'n - tilde'], + ['&ograve;', '&#242;', true, 'o - grave'], + ['&oacute;', '&#243;', true, 'o - acute'], + ['&ocirc;', '&#244;', true, 'o - circumflex'], + ['&otilde;', '&#245;', true, 'o - tilde'], + ['&ouml;', '&#246;', true, 'o - diaeresis'], + ['&oslash;', '&#248;', true, 'o slash'], + ['&oelig;', '&#339;', true, 'ligature oe'], + ['&scaron;', '&#353;', true, 's - caron'], + ['&ugrave;', '&#249;', true, 'u - grave'], + ['&uacute;', '&#250;', true, 'u - acute'], + ['&ucirc;', '&#251;', true, 'u - circumflex'], + ['&uuml;', '&#252;', true, 'u - diaeresis'], + ['&yacute;', '&#253;', true, 'y - acute'], + ['&thorn;', '&#254;', true, 'thorn'], + ['&yuml;', '&#255;', true, 'y - diaeresis'], + ['&Alpha;', '&#913;', true, 'Alpha'], + ['&Beta;', '&#914;', true, 'Beta'], + ['&Gamma;', '&#915;', true, 'Gamma'], + ['&Delta;', '&#916;', true, 'Delta'], + ['&Epsilon;', '&#917;', true, 'Epsilon'], + ['&Zeta;', '&#918;', true, 'Zeta'], + ['&Eta;', '&#919;', true, 'Eta'], + ['&Theta;', '&#920;', true, 'Theta'], + ['&Iota;', '&#921;', true, 'Iota'], + ['&Kappa;', '&#922;', true, 'Kappa'], + ['&Lambda;', '&#923;', true, 'Lambda'], + ['&Mu;', '&#924;', true, 'Mu'], + ['&Nu;', '&#925;', true, 'Nu'], + ['&Xi;', '&#926;', true, 'Xi'], + ['&Omicron;', '&#927;', true, 'Omicron'], + ['&Pi;', '&#928;', true, 'Pi'], + ['&Rho;', '&#929;', true, 'Rho'], + ['&Sigma;', '&#931;', true, 'Sigma'], + ['&Tau;', '&#932;', true, 'Tau'], + ['&Upsilon;', '&#933;', true, 'Upsilon'], + ['&Phi;', '&#934;', true, 'Phi'], + ['&Chi;', '&#935;', true, 'Chi'], + ['&Psi;', '&#936;', true, 'Psi'], + ['&Omega;', '&#937;', true, 'Omega'], + ['&alpha;', '&#945;', true, 'alpha'], + ['&beta;', '&#946;', true, 'beta'], + ['&gamma;', '&#947;', true, 'gamma'], + ['&delta;', '&#948;', true, 'delta'], + ['&epsilon;', '&#949;', true, 'epsilon'], + ['&zeta;', '&#950;', true, 'zeta'], + ['&eta;', '&#951;', true, 'eta'], + ['&theta;', '&#952;', true, 'theta'], + ['&iota;', '&#953;', true, 'iota'], + ['&kappa;', '&#954;', true, 'kappa'], + ['&lambda;', '&#955;', true, 'lambda'], + ['&mu;', '&#956;', true, 'mu'], + ['&nu;', '&#957;', true, 'nu'], + ['&xi;', '&#958;', true, 'xi'], + ['&omicron;', '&#959;', true, 'omicron'], + ['&pi;', '&#960;', true, 'pi'], + ['&rho;', '&#961;', true, 'rho'], + ['&sigmaf;', '&#962;', true, 'final sigma'], + ['&sigma;', '&#963;', true, 'sigma'], + ['&tau;', '&#964;', true, 'tau'], + ['&upsilon;', '&#965;', true, 'upsilon'], + ['&phi;', '&#966;', true, 'phi'], + ['&chi;', '&#967;', true, 'chi'], + ['&psi;', '&#968;', true, 'psi'], + ['&omega;', '&#969;', true, 'omega'], +// symbols + ['&alefsym;', '&#8501;', false,'alef symbol'], + ['&piv;', '&#982;', false,'pi symbol'], + ['&real;', '&#8476;', false,'real part symbol'], + ['&thetasym;','&#977;', false,'theta symbol'], + ['&upsih;', '&#978;', false,'upsilon - hook symbol'], + ['&weierp;', '&#8472;', false,'Weierstrass p'], + ['&image;', '&#8465;', false,'imaginary part'], +// arrows + ['&larr;', '&#8592;', true, 'leftwards arrow'], + ['&uarr;', '&#8593;', true, 'upwards arrow'], + ['&rarr;', '&#8594;', true, 'rightwards arrow'], + ['&darr;', '&#8595;', true, 'downwards arrow'], + ['&harr;', '&#8596;', true, 'left right arrow'], + ['&crarr;', '&#8629;', false,'carriage return'], + ['&lArr;', '&#8656;', false,'leftwards double arrow'], + ['&uArr;', '&#8657;', false,'upwards double arrow'], + ['&rArr;', '&#8658;', false,'rightwards double arrow'], + ['&dArr;', '&#8659;', false,'downwards double arrow'], + ['&hArr;', '&#8660;', false,'left right double arrow'], + ['&there4;', '&#8756;', false,'therefore'], + ['&sub;', '&#8834;', false,'subset of'], + ['&sup;', '&#8835;', false,'superset of'], + ['&nsub;', '&#8836;', false,'not a subset of'], + ['&sube;', '&#8838;', false,'subset of or equal to'], + ['&supe;', '&#8839;', false,'superset of or equal to'], + ['&oplus;', '&#8853;', false,'circled plus'], + ['&otimes;', '&#8855;', false,'circled times'], + ['&perp;', '&#8869;', false,'perpendicular'], + ['&sdot;', '&#8901;', false,'dot operator'], + ['&lceil;', '&#8968;', false,'left ceiling'], + ['&rceil;', '&#8969;', false,'right ceiling'], + ['&lfloor;', '&#8970;', false,'left floor'], + ['&rfloor;', '&#8971;', false,'right floor'], + ['&lang;', '&#9001;', false,'left-pointing angle bracket'], + ['&rang;', '&#9002;', false,'right-pointing angle bracket'], + ['&loz;', '&#9674;', true, 'lozenge'], + ['&spades;', '&#9824;', true, 'black spade suit'], + ['&clubs;', '&#9827;', true, 'black club suit'], + ['&hearts;', '&#9829;', true, 'black heart suit'], + ['&diams;', '&#9830;', true, 'black diamond suit'], + ['&ensp;', '&#8194;', false,'en space'], + ['&emsp;', '&#8195;', false,'em space'], + ['&thinsp;', '&#8201;', false,'thin space'], + ['&zwnj;', '&#8204;', false,'zero width non-joiner'], + ['&zwj;', '&#8205;', false,'zero width joiner'], + ['&lrm;', '&#8206;', false,'left-to-right mark'], + ['&rlm;', '&#8207;', false,'right-to-left mark'], + ['&shy;', '&#173;', false,'soft hyphen'] +]; + +tinyMCEPopup.onInit.add(function() { + tinyMCEPopup.dom.setHTML('charmapView', renderCharMapHTML()); + addKeyboardNavigation(); +}); + +function addKeyboardNavigation(){ + var tableElm, cells, settings; + + cells = tinyMCEPopup.dom.select(".charmaplink", "charmapgroup"); + + settings ={ + root: "charmapgroup", + items: cells + }; + + tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', settings, tinyMCEPopup.dom); +} + +function renderCharMapHTML() { + var charsPerRow = 20, tdWidth=20, tdHeight=20, i; + var html = '<div id="charmapgroup" aria-labelledby="charmap_label" tabindex="0" role="listbox">'+ + '<table role="presentation" border="0" cellspacing="1" cellpadding="0" width="' + (tdWidth*charsPerRow) + + '"><tr height="' + tdHeight + '">'; + var cols=-1; + + for (i=0; i<charmap.length; i++) { + var previewCharFn; + + if (charmap[i][2]==true) { + cols++; + previewCharFn = 'previewChar(\'' + charmap[i][1].substring(1,charmap[i][1].length) + '\',\'' + charmap[i][0].substring(1,charmap[i][0].length) + '\',\'' + charmap[i][3] + '\');'; + html += '' + + '<td class="charmap">' + + '<a class="charmaplink" role="button" onmouseover="'+previewCharFn+'" onfocus="'+previewCharFn+'" href="javascript:void(0)" onclick="insertChar(\'' + charmap[i][1].substring(2,charmap[i][1].length-1) + '\');" onclick="return false;" onmousedown="return false;" title="' + charmap[i][3] + '">' + + charmap[i][1] + + '</a></td>'; + if ((cols+1) % charsPerRow == 0) + html += '</tr><tr height="' + tdHeight + '">'; + } + } + + if (cols % charsPerRow > 0) { + var padd = charsPerRow - (cols % charsPerRow); + for (var i=0; i<padd-1; i++) + html += '<td width="' + tdWidth + '" height="' + tdHeight + '" class="charmap">&nbsp;</td>'; + } + + html += '</tr></table></div>'; + html = html.replace(/<tr height="20"><\/tr>/g, ''); + + return html; +} + +function insertChar(chr) { + tinyMCEPopup.execCommand('mceInsertContent', false, '&#' + chr + ';'); + + // Refocus in window + if (tinyMCEPopup.isWindow) + window.focus(); + + tinyMCEPopup.editor.focus(); + tinyMCEPopup.close(); +} + +function previewChar(codeA, codeB, codeN) { + var elmA = document.getElementById('codeA'); + var elmB = document.getElementById('codeB'); + var elmV = document.getElementById('codeV'); + var elmN = document.getElementById('codeN'); + + if (codeA=='#160;') { + elmV.innerHTML = '__'; + } else { + elmV.innerHTML = '&' + codeA; + } + + elmB.innerHTML = '&amp;' + codeA; + elmA.innerHTML = '&amp;' + codeB; + elmN.innerHTML = codeN; +} diff --git a/src/core/static/js/tiny_mce/themes/advanced/js/color_picker.js b/src/core/static/js/tiny_mce/themes/advanced/js/color_picker.js new file mode 100644 index 0000000..7decac5 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/js/color_picker.js @@ -0,0 +1,329 @@ +tinyMCEPopup.requireLangPack(); + +var detail = 50, strhex = "0123456789ABCDEF", i, isMouseDown = false, isMouseOver = false; + +var colors = [ + "#000000","#000033","#000066","#000099","#0000cc","#0000ff","#330000","#330033", + "#330066","#330099","#3300cc","#3300ff","#660000","#660033","#660066","#660099", + "#6600cc","#6600ff","#990000","#990033","#990066","#990099","#9900cc","#9900ff", + "#cc0000","#cc0033","#cc0066","#cc0099","#cc00cc","#cc00ff","#ff0000","#ff0033", + "#ff0066","#ff0099","#ff00cc","#ff00ff","#003300","#003333","#003366","#003399", + "#0033cc","#0033ff","#333300","#333333","#333366","#333399","#3333cc","#3333ff", + "#663300","#663333","#663366","#663399","#6633cc","#6633ff","#993300","#993333", + "#993366","#993399","#9933cc","#9933ff","#cc3300","#cc3333","#cc3366","#cc3399", + "#cc33cc","#cc33ff","#ff3300","#ff3333","#ff3366","#ff3399","#ff33cc","#ff33ff", + "#006600","#006633","#006666","#006699","#0066cc","#0066ff","#336600","#336633", + "#336666","#336699","#3366cc","#3366ff","#666600","#666633","#666666","#666699", + "#6666cc","#6666ff","#996600","#996633","#996666","#996699","#9966cc","#9966ff", + "#cc6600","#cc6633","#cc6666","#cc6699","#cc66cc","#cc66ff","#ff6600","#ff6633", + "#ff6666","#ff6699","#ff66cc","#ff66ff","#009900","#009933","#009966","#009999", + "#0099cc","#0099ff","#339900","#339933","#339966","#339999","#3399cc","#3399ff", + "#669900","#669933","#669966","#669999","#6699cc","#6699ff","#999900","#999933", + "#999966","#999999","#9999cc","#9999ff","#cc9900","#cc9933","#cc9966","#cc9999", + "#cc99cc","#cc99ff","#ff9900","#ff9933","#ff9966","#ff9999","#ff99cc","#ff99ff", + "#00cc00","#00cc33","#00cc66","#00cc99","#00cccc","#00ccff","#33cc00","#33cc33", + "#33cc66","#33cc99","#33cccc","#33ccff","#66cc00","#66cc33","#66cc66","#66cc99", + "#66cccc","#66ccff","#99cc00","#99cc33","#99cc66","#99cc99","#99cccc","#99ccff", + "#cccc00","#cccc33","#cccc66","#cccc99","#cccccc","#ccccff","#ffcc00","#ffcc33", + "#ffcc66","#ffcc99","#ffcccc","#ffccff","#00ff00","#00ff33","#00ff66","#00ff99", + "#00ffcc","#00ffff","#33ff00","#33ff33","#33ff66","#33ff99","#33ffcc","#33ffff", + "#66ff00","#66ff33","#66ff66","#66ff99","#66ffcc","#66ffff","#99ff00","#99ff33", + "#99ff66","#99ff99","#99ffcc","#99ffff","#ccff00","#ccff33","#ccff66","#ccff99", + "#ccffcc","#ccffff","#ffff00","#ffff33","#ffff66","#ffff99","#ffffcc","#ffffff" +]; + +var named = { + '#F0F8FF':'Alice Blue','#FAEBD7':'Antique White','#00FFFF':'Aqua','#7FFFD4':'Aquamarine','#F0FFFF':'Azure','#F5F5DC':'Beige', + '#FFE4C4':'Bisque','#000000':'Black','#FFEBCD':'Blanched Almond','#0000FF':'Blue','#8A2BE2':'Blue Violet','#A52A2A':'Brown', + '#DEB887':'Burly Wood','#5F9EA0':'Cadet Blue','#7FFF00':'Chartreuse','#D2691E':'Chocolate','#FF7F50':'Coral','#6495ED':'Cornflower Blue', + '#FFF8DC':'Cornsilk','#DC143C':'Crimson','#00FFFF':'Cyan','#00008B':'Dark Blue','#008B8B':'Dark Cyan','#B8860B':'Dark Golden Rod', + '#A9A9A9':'Dark Gray','#A9A9A9':'Dark Grey','#006400':'Dark Green','#BDB76B':'Dark Khaki','#8B008B':'Dark Magenta','#556B2F':'Dark Olive Green', + '#FF8C00':'Darkorange','#9932CC':'Dark Orchid','#8B0000':'Dark Red','#E9967A':'Dark Salmon','#8FBC8F':'Dark Sea Green','#483D8B':'Dark Slate Blue', + '#2F4F4F':'Dark Slate Gray','#2F4F4F':'Dark Slate Grey','#00CED1':'Dark Turquoise','#9400D3':'Dark Violet','#FF1493':'Deep Pink','#00BFFF':'Deep Sky Blue', + '#696969':'Dim Gray','#696969':'Dim Grey','#1E90FF':'Dodger Blue','#B22222':'Fire Brick','#FFFAF0':'Floral White','#228B22':'Forest Green', + '#FF00FF':'Fuchsia','#DCDCDC':'Gainsboro','#F8F8FF':'Ghost White','#FFD700':'Gold','#DAA520':'Golden Rod','#808080':'Gray','#808080':'Grey', + '#008000':'Green','#ADFF2F':'Green Yellow','#F0FFF0':'Honey Dew','#FF69B4':'Hot Pink','#CD5C5C':'Indian Red','#4B0082':'Indigo','#FFFFF0':'Ivory', + '#F0E68C':'Khaki','#E6E6FA':'Lavender','#FFF0F5':'Lavender Blush','#7CFC00':'Lawn Green','#FFFACD':'Lemon Chiffon','#ADD8E6':'Light Blue', + '#F08080':'Light Coral','#E0FFFF':'Light Cyan','#FAFAD2':'Light Golden Rod Yellow','#D3D3D3':'Light Gray','#D3D3D3':'Light Grey','#90EE90':'Light Green', + '#FFB6C1':'Light Pink','#FFA07A':'Light Salmon','#20B2AA':'Light Sea Green','#87CEFA':'Light Sky Blue','#778899':'Light Slate Gray','#778899':'Light Slate Grey', + '#B0C4DE':'Light Steel Blue','#FFFFE0':'Light Yellow','#00FF00':'Lime','#32CD32':'Lime Green','#FAF0E6':'Linen','#FF00FF':'Magenta','#800000':'Maroon', + '#66CDAA':'Medium Aqua Marine','#0000CD':'Medium Blue','#BA55D3':'Medium Orchid','#9370D8':'Medium Purple','#3CB371':'Medium Sea Green','#7B68EE':'Medium Slate Blue', + '#00FA9A':'Medium Spring Green','#48D1CC':'Medium Turquoise','#C71585':'Medium Violet Red','#191970':'Midnight Blue','#F5FFFA':'Mint Cream','#FFE4E1':'Misty Rose','#FFE4B5':'Moccasin', + '#FFDEAD':'Navajo White','#000080':'Navy','#FDF5E6':'Old Lace','#808000':'Olive','#6B8E23':'Olive Drab','#FFA500':'Orange','#FF4500':'Orange Red','#DA70D6':'Orchid', + '#EEE8AA':'Pale Golden Rod','#98FB98':'Pale Green','#AFEEEE':'Pale Turquoise','#D87093':'Pale Violet Red','#FFEFD5':'Papaya Whip','#FFDAB9':'Peach Puff', + '#CD853F':'Peru','#FFC0CB':'Pink','#DDA0DD':'Plum','#B0E0E6':'Powder Blue','#800080':'Purple','#FF0000':'Red','#BC8F8F':'Rosy Brown','#4169E1':'Royal Blue', + '#8B4513':'Saddle Brown','#FA8072':'Salmon','#F4A460':'Sandy Brown','#2E8B57':'Sea Green','#FFF5EE':'Sea Shell','#A0522D':'Sienna','#C0C0C0':'Silver', + '#87CEEB':'Sky Blue','#6A5ACD':'Slate Blue','#708090':'Slate Gray','#708090':'Slate Grey','#FFFAFA':'Snow','#00FF7F':'Spring Green', + '#4682B4':'Steel Blue','#D2B48C':'Tan','#008080':'Teal','#D8BFD8':'Thistle','#FF6347':'Tomato','#40E0D0':'Turquoise','#EE82EE':'Violet', + '#F5DEB3':'Wheat','#FFFFFF':'White','#F5F5F5':'White Smoke','#FFFF00':'Yellow','#9ACD32':'Yellow Green' +}; + +var namedLookup = {}; + +function init() { + var inputColor = convertRGBToHex(tinyMCEPopup.getWindowArg('input_color')), key, value; + + tinyMCEPopup.resizeToInnerSize(); + + generatePicker(); + generateWebColors(); + generateNamedColors(); + + if (inputColor) { + changeFinalColor(inputColor); + + col = convertHexToRGB(inputColor); + + if (col) + updateLight(col.r, col.g, col.b); + } + + for (key in named) { + value = named[key]; + namedLookup[value.replace(/\s+/, '').toLowerCase()] = key.replace(/#/, '').toLowerCase(); + } +} + +function toHexColor(color) { + var matches, red, green, blue, toInt = parseInt; + + function hex(value) { + value = parseInt(value).toString(16); + + return value.length > 1 ? value : '0' + value; // Padd with leading zero + }; + + color = color.replace(/[\s#]+/g, '').toLowerCase(); + color = namedLookup[color] || color; + matches = /^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)|([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})|([a-f0-9])([a-f0-9])([a-f0-9])$/.exec(color); + + if (matches) { + if (matches[1]) { + red = toInt(matches[1]); + green = toInt(matches[2]); + blue = toInt(matches[3]); + } else if (matches[4]) { + red = toInt(matches[4], 16); + green = toInt(matches[5], 16); + blue = toInt(matches[6], 16); + } else if (matches[7]) { + red = toInt(matches[7] + matches[7], 16); + green = toInt(matches[8] + matches[8], 16); + blue = toInt(matches[9] + matches[9], 16); + } + + return '#' + hex(red) + hex(green) + hex(blue); + } + + return ''; +} + +function insertAction() { + var color = document.getElementById("color").value, f = tinyMCEPopup.getWindowArg('func'); + + tinyMCEPopup.restoreSelection(); + + if (f) + f(toHexColor(color)); + + tinyMCEPopup.close(); +} + +function showColor(color, name) { + if (name) + document.getElementById("colorname").innerHTML = name; + + document.getElementById("preview").style.backgroundColor = color; + document.getElementById("color").value = color.toUpperCase(); +} + +function convertRGBToHex(col) { + var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi"); + + if (!col) + return col; + + var rgb = col.replace(re, "$1,$2,$3").split(','); + if (rgb.length == 3) { + r = parseInt(rgb[0]).toString(16); + g = parseInt(rgb[1]).toString(16); + b = parseInt(rgb[2]).toString(16); + + r = r.length == 1 ? '0' + r : r; + g = g.length == 1 ? '0' + g : g; + b = b.length == 1 ? '0' + b : b; + + return "#" + r + g + b; + } + + return col; +} + +function convertHexToRGB(col) { + if (col.indexOf('#') != -1) { + col = col.replace(new RegExp('[^0-9A-F]', 'gi'), ''); + + r = parseInt(col.substring(0, 2), 16); + g = parseInt(col.substring(2, 4), 16); + b = parseInt(col.substring(4, 6), 16); + + return {r : r, g : g, b : b}; + } + + return null; +} + +function generatePicker() { + var el = document.getElementById('light'), h = '', i; + + for (i = 0; i < detail; i++){ + h += '<div id="gs'+i+'" style="background-color:#000000; width:15px; height:3px; border-style:none; border-width:0px;"' + + ' onclick="changeFinalColor(this.style.backgroundColor)"' + + ' onmousedown="isMouseDown = true; return false;"' + + ' onmouseup="isMouseDown = false;"' + + ' onmousemove="if (isMouseDown && isMouseOver) changeFinalColor(this.style.backgroundColor); return false;"' + + ' onmouseover="isMouseOver = true;"' + + ' onmouseout="isMouseOver = false;"' + + '></div>'; + } + + el.innerHTML = h; +} + +function generateWebColors() { + var el = document.getElementById('webcolors'), h = '', i; + + if (el.className == 'generated') + return; + + // TODO: VoiceOver doesn't seem to support legend as a label referenced by labelledby. + h += '<div role="listbox" aria-labelledby="webcolors_title" tabindex="0"><table role="presentation" border="0" cellspacing="1" cellpadding="0">' + + '<tr>'; + + for (i=0; i<colors.length; i++) { + h += '<td bgcolor="' + colors[i] + '" width="10" height="10">' + + '<a href="javascript:insertAction();" role="option" tabindex="-1" aria-labelledby="web_colors_' + i + '" onfocus="showColor(\'' + colors[i] + '\');" onmouseover="showColor(\'' + colors[i] + '\');" style="display:block;width:10px;height:10px;overflow:hidden;">'; + if (tinyMCEPopup.editor.forcedHighContrastMode) { + h += '<canvas class="mceColorSwatch" height="10" width="10" data-color="' + colors[i] + '"></canvas>'; + } + h += '<span class="mceVoiceLabel" style="display:none;" id="web_colors_' + i + '">' + colors[i].toUpperCase() + '</span>'; + h += '</a></td>'; + if ((i+1) % 18 == 0) + h += '</tr><tr>'; + } + + h += '</table></div>'; + + el.innerHTML = h; + el.className = 'generated'; + + paintCanvas(el); + enableKeyboardNavigation(el.firstChild); +} + +function paintCanvas(el) { + tinyMCEPopup.getWin().tinymce.each(tinyMCEPopup.dom.select('canvas.mceColorSwatch', el), function(canvas) { + var context; + if (canvas.getContext && (context = canvas.getContext("2d"))) { + context.fillStyle = canvas.getAttribute('data-color'); + context.fillRect(0, 0, 10, 10); + } + }); +} +function generateNamedColors() { + var el = document.getElementById('namedcolors'), h = '', n, v, i = 0; + + if (el.className == 'generated') + return; + + for (n in named) { + v = named[n]; + h += '<a href="javascript:insertAction();" role="option" tabindex="-1" aria-labelledby="named_colors_' + i + '" onfocus="showColor(\'' + n + '\',\'' + v + '\');" onmouseover="showColor(\'' + n + '\',\'' + v + '\');" style="background-color: ' + n + '">'; + if (tinyMCEPopup.editor.forcedHighContrastMode) { + h += '<canvas class="mceColorSwatch" height="10" width="10" data-color="' + colors[i] + '"></canvas>'; + } + h += '<span class="mceVoiceLabel" style="display:none;" id="named_colors_' + i + '">' + v + '</span>'; + h += '</a>'; + i++; + } + + el.innerHTML = h; + el.className = 'generated'; + + paintCanvas(el); + enableKeyboardNavigation(el); +} + +function enableKeyboardNavigation(el) { + tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', { + root: el, + items: tinyMCEPopup.dom.select('a', el) + }, tinyMCEPopup.dom); +} + +function dechex(n) { + return strhex.charAt(Math.floor(n / 16)) + strhex.charAt(n % 16); +} + +function computeColor(e) { + var x, y, partWidth, partDetail, imHeight, r, g, b, coef, i, finalCoef, finalR, finalG, finalB; + + x = e.offsetX ? e.offsetX : (e.target ? e.clientX - e.target.x : 0); + y = e.offsetY ? e.offsetY : (e.target ? e.clientY - e.target.y : 0); + + partWidth = document.getElementById('colors').width / 6; + partDetail = detail / 2; + imHeight = document.getElementById('colors').height; + + r = (x >= 0)*(x < partWidth)*255 + (x >= partWidth)*(x < 2*partWidth)*(2*255 - x * 255 / partWidth) + (x >= 4*partWidth)*(x < 5*partWidth)*(-4*255 + x * 255 / partWidth) + (x >= 5*partWidth)*(x < 6*partWidth)*255; + g = (x >= 0)*(x < partWidth)*(x * 255 / partWidth) + (x >= partWidth)*(x < 3*partWidth)*255 + (x >= 3*partWidth)*(x < 4*partWidth)*(4*255 - x * 255 / partWidth); + b = (x >= 2*partWidth)*(x < 3*partWidth)*(-2*255 + x * 255 / partWidth) + (x >= 3*partWidth)*(x < 5*partWidth)*255 + (x >= 5*partWidth)*(x < 6*partWidth)*(6*255 - x * 255 / partWidth); + + coef = (imHeight - y) / imHeight; + r = 128 + (r - 128) * coef; + g = 128 + (g - 128) * coef; + b = 128 + (b - 128) * coef; + + changeFinalColor('#' + dechex(r) + dechex(g) + dechex(b)); + updateLight(r, g, b); +} + +function updateLight(r, g, b) { + var i, partDetail = detail / 2, finalCoef, finalR, finalG, finalB, color; + + for (i=0; i<detail; i++) { + if ((i>=0) && (i<partDetail)) { + finalCoef = i / partDetail; + finalR = dechex(255 - (255 - r) * finalCoef); + finalG = dechex(255 - (255 - g) * finalCoef); + finalB = dechex(255 - (255 - b) * finalCoef); + } else { + finalCoef = 2 - i / partDetail; + finalR = dechex(r * finalCoef); + finalG = dechex(g * finalCoef); + finalB = dechex(b * finalCoef); + } + + color = finalR + finalG + finalB; + + setCol('gs' + i, '#'+color); + } +} + +function changeFinalColor(color) { + if (color.indexOf('#') == -1) + color = convertRGBToHex(color); + + setCol('preview', color); + document.getElementById('color').value = color; +} + +function setCol(e, c) { + try { + document.getElementById(e).style.backgroundColor = c; + } catch (ex) { + // Ignore IE warning + } +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/core/static/js/tiny_mce/themes/advanced/js/image.js b/src/core/static/js/tiny_mce/themes/advanced/js/image.js new file mode 100644 index 0000000..6c2489a --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/js/image.js @@ -0,0 +1,251 @@ +var ImageDialog = { + preInit : function() { + var url; + + tinyMCEPopup.requireLangPack(); + + if (url = tinyMCEPopup.getParam("external_image_list_url")) + document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>'); + }, + + init : function() { + var f = document.forms[0], ed = tinyMCEPopup.editor; + + // Setup browse button + document.getElementById('srcbrowsercontainer').innerHTML = getBrowserHTML('srcbrowser','src','image','theme_advanced_image'); + if (isVisible('srcbrowser')) + document.getElementById('src').style.width = '180px'; + + e = ed.selection.getNode(); + + this.fillFileList('image_list', tinyMCEPopup.getParam('external_image_list', 'tinyMCEImageList')); + + if (e.nodeName == 'IMG') { + f.src.value = ed.dom.getAttrib(e, 'src'); + f.alt.value = ed.dom.getAttrib(e, 'alt'); + f.border.value = this.getAttrib(e, 'border'); + f.vspace.value = this.getAttrib(e, 'vspace'); + f.hspace.value = this.getAttrib(e, 'hspace'); + f.width.value = ed.dom.getAttrib(e, 'width'); + f.height.value = ed.dom.getAttrib(e, 'height'); + f.insert.value = ed.getLang('update'); + this.styleVal = ed.dom.getAttrib(e, 'style'); + selectByValue(f, 'image_list', f.src.value); + selectByValue(f, 'align', this.getAttrib(e, 'align')); + this.updateStyle(); + } + }, + + fillFileList : function(id, l) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl; + + l = typeof(l) === 'function' ? l() : window[l]; + + if (l && l.length > 0) { + lst.options[lst.options.length] = new Option('', ''); + + tinymce.each(l, function(o) { + lst.options[lst.options.length] = new Option(o[0], o[1]); + }); + } else + dom.remove(dom.getParent(id, 'tr')); + }, + + update : function() { + var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, args = {}, el; + + tinyMCEPopup.restoreSelection(); + + if (f.src.value === '') { + if (ed.selection.getNode().nodeName == 'IMG') { + ed.dom.remove(ed.selection.getNode()); + ed.execCommand('mceRepaint'); + } + + tinyMCEPopup.close(); + return; + } + + if (!ed.settings.inline_styles) { + args = tinymce.extend(args, { + vspace : nl.vspace.value, + hspace : nl.hspace.value, + border : nl.border.value, + align : getSelectValue(f, 'align') + }); + } else + args.style = this.styleVal; + + tinymce.extend(args, { + src : f.src.value.replace(/ /g, '%20'), + alt : f.alt.value, + width : f.width.value, + height : f.height.value + }); + + el = ed.selection.getNode(); + + if (el && el.nodeName == 'IMG') { + ed.dom.setAttribs(el, args); + tinyMCEPopup.editor.execCommand('mceRepaint'); + tinyMCEPopup.editor.focus(); + } else { + tinymce.each(args, function(value, name) { + if (value === "") { + delete args[name]; + } + }); + + ed.execCommand('mceInsertContent', false, tinyMCEPopup.editor.dom.createHTML('img', args), {skip_undo : 1}); + ed.undoManager.add(); + } + + tinyMCEPopup.close(); + }, + + updateStyle : function() { + var dom = tinyMCEPopup.dom, st, v, f = document.forms[0]; + + if (tinyMCEPopup.editor.settings.inline_styles) { + st = tinyMCEPopup.dom.parseStyle(this.styleVal); + + // Handle align + v = getSelectValue(f, 'align'); + if (v) { + if (v == 'left' || v == 'right') { + st['float'] = v; + delete st['vertical-align']; + } else { + st['vertical-align'] = v; + delete st['float']; + } + } else { + delete st['float']; + delete st['vertical-align']; + } + + // Handle border + v = f.border.value; + if (v || v == '0') { + if (v == '0') + st['border'] = '0'; + else + st['border'] = v + 'px solid black'; + } else + delete st['border']; + + // Handle hspace + v = f.hspace.value; + if (v) { + delete st['margin']; + st['margin-left'] = v + 'px'; + st['margin-right'] = v + 'px'; + } else { + delete st['margin-left']; + delete st['margin-right']; + } + + // Handle vspace + v = f.vspace.value; + if (v) { + delete st['margin']; + st['margin-top'] = v + 'px'; + st['margin-bottom'] = v + 'px'; + } else { + delete st['margin-top']; + delete st['margin-bottom']; + } + + // Merge + st = tinyMCEPopup.dom.parseStyle(dom.serializeStyle(st), 'img'); + this.styleVal = dom.serializeStyle(st, 'img'); + } + }, + + getAttrib : function(e, at) { + var ed = tinyMCEPopup.editor, dom = ed.dom, v, v2; + + if (ed.settings.inline_styles) { + switch (at) { + case 'align': + if (v = dom.getStyle(e, 'float')) + return v; + + if (v = dom.getStyle(e, 'vertical-align')) + return v; + + break; + + case 'hspace': + v = dom.getStyle(e, 'margin-left') + v2 = dom.getStyle(e, 'margin-right'); + if (v && v == v2) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + + case 'vspace': + v = dom.getStyle(e, 'margin-top') + v2 = dom.getStyle(e, 'margin-bottom'); + if (v && v == v2) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + + case 'border': + v = 0; + + tinymce.each(['top', 'right', 'bottom', 'left'], function(sv) { + sv = dom.getStyle(e, 'border-' + sv + '-width'); + + // False or not the same as prev + if (!sv || (sv != v && v !== 0)) { + v = 0; + return false; + } + + if (sv) + v = sv; + }); + + if (v) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + } + } + + if (v = dom.getAttrib(e, at)) + return v; + + return ''; + }, + + resetImageData : function() { + var f = document.forms[0]; + + f.width.value = f.height.value = ""; + }, + + updateImageData : function() { + var f = document.forms[0], t = ImageDialog; + + if (f.width.value == "") + f.width.value = t.preloadImg.width; + + if (f.height.value == "") + f.height.value = t.preloadImg.height; + }, + + getImageData : function() { + var f = document.forms[0]; + + this.preloadImg = new Image(); + this.preloadImg.onload = this.updateImageData; + this.preloadImg.onerror = this.resetImageData; + this.preloadImg.src = tinyMCEPopup.editor.documentBaseURI.toAbsolute(f.src.value); + } +}; + +ImageDialog.preInit(); +tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog); diff --git a/src/core/static/js/tiny_mce/themes/advanced/js/link.js b/src/core/static/js/tiny_mce/themes/advanced/js/link.js new file mode 100644 index 0000000..53ff409 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/js/link.js @@ -0,0 +1,153 @@ +tinyMCEPopup.requireLangPack(); + +var LinkDialog = { + preInit : function() { + var url; + + if (url = tinyMCEPopup.getParam("external_link_list_url")) + document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>'); + }, + + init : function() { + var f = document.forms[0], ed = tinyMCEPopup.editor; + + // Setup browse button + document.getElementById('hrefbrowsercontainer').innerHTML = getBrowserHTML('hrefbrowser', 'href', 'file', 'theme_advanced_link'); + if (isVisible('hrefbrowser')) + document.getElementById('href').style.width = '180px'; + + this.fillClassList('class_list'); + this.fillFileList('link_list', 'tinyMCELinkList'); + this.fillTargetList('target_list'); + + if (e = ed.dom.getParent(ed.selection.getNode(), 'A')) { + f.href.value = ed.dom.getAttrib(e, 'href'); + f.linktitle.value = ed.dom.getAttrib(e, 'title'); + f.insert.value = ed.getLang('update'); + selectByValue(f, 'link_list', f.href.value); + selectByValue(f, 'target_list', ed.dom.getAttrib(e, 'target')); + selectByValue(f, 'class_list', ed.dom.getAttrib(e, 'class')); + } + }, + + update : function() { + var f = document.forms[0], ed = tinyMCEPopup.editor, e, b, href = f.href.value.replace(/ /g, '%20'); + + tinyMCEPopup.restoreSelection(); + e = ed.dom.getParent(ed.selection.getNode(), 'A'); + + // Remove element if there is no href + if (!f.href.value) { + if (e) { + b = ed.selection.getBookmark(); + ed.dom.remove(e, 1); + ed.selection.moveToBookmark(b); + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); + return; + } + } + + // Create new anchor elements + if (e == null) { + ed.getDoc().execCommand("unlink", false, null); + tinyMCEPopup.execCommand("mceInsertLink", false, "#mce_temp_url#", {skip_undo : 1}); + + tinymce.each(ed.dom.select("a"), function(n) { + if (ed.dom.getAttrib(n, 'href') == '#mce_temp_url#') { + e = n; + + ed.dom.setAttribs(e, { + href : href, + title : f.linktitle.value, + target : f.target_list ? getSelectValue(f, "target_list") : null, + 'class' : f.class_list ? getSelectValue(f, "class_list") : null + }); + } + }); + } else { + ed.dom.setAttribs(e, { + href : href, + title : f.linktitle.value, + target : f.target_list ? getSelectValue(f, "target_list") : null, + 'class' : f.class_list ? getSelectValue(f, "class_list") : null + }); + } + + // Don't move caret if selection was image + if (e.childNodes.length != 1 || e.firstChild.nodeName != 'IMG') { + ed.focus(); + ed.selection.select(e); + ed.selection.collapse(0); + tinyMCEPopup.storeSelection(); + } + + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); + }, + + checkPrefix : function(n) { + if (n.value && Validator.isEmail(n) && !/^\s*mailto:/i.test(n.value) && confirm(tinyMCEPopup.getLang('advanced_dlg.link_is_email'))) + n.value = 'mailto:' + n.value; + + if (/^\s*www\./i.test(n.value) && confirm(tinyMCEPopup.getLang('advanced_dlg.link_is_external'))) + n.value = 'http://' + n.value; + }, + + fillFileList : function(id, l) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl; + + l = window[l]; + + if (l && l.length > 0) { + lst.options[lst.options.length] = new Option('', ''); + + tinymce.each(l, function(o) { + lst.options[lst.options.length] = new Option(o[0], o[1]); + }); + } else + dom.remove(dom.getParent(id, 'tr')); + }, + + fillClassList : function(id) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl; + + if (v = tinyMCEPopup.getParam('theme_advanced_styles')) { + cl = []; + + tinymce.each(v.split(';'), function(v) { + var p = v.split('='); + + cl.push({'title' : p[0], 'class' : p[1]}); + }); + } else + cl = tinyMCEPopup.editor.dom.getClasses(); + + if (cl.length > 0) { + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), ''); + + tinymce.each(cl, function(o) { + lst.options[lst.options.length] = new Option(o.title || o['class'], o['class']); + }); + } else + dom.remove(dom.getParent(id, 'tr')); + }, + + fillTargetList : function(id) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v; + + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), ''); + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('advanced_dlg.link_target_same'), '_self'); + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('advanced_dlg.link_target_blank'), '_blank'); + + if (v = tinyMCEPopup.getParam('theme_advanced_link_targets')) { + tinymce.each(v.split(','), function(v) { + v = v.split('='); + lst.options[lst.options.length] = new Option(v[0], v[1]); + }); + } + } +}; + +LinkDialog.preInit(); +tinyMCEPopup.onInit.add(LinkDialog.init, LinkDialog); diff --git a/src/core/static/js/tiny_mce/themes/advanced/js/source_editor.js b/src/core/static/js/tiny_mce/themes/advanced/js/source_editor.js new file mode 100644 index 0000000..84546ad --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/js/source_editor.js @@ -0,0 +1,56 @@ +tinyMCEPopup.requireLangPack(); +tinyMCEPopup.onInit.add(onLoadInit); + +function saveContent() { + tinyMCEPopup.editor.setContent(document.getElementById('htmlSource').value, {source_view : true}); + tinyMCEPopup.close(); +} + +function onLoadInit() { + tinyMCEPopup.resizeToInnerSize(); + + // Remove Gecko spellchecking + if (tinymce.isGecko) + document.body.spellcheck = tinyMCEPopup.editor.getParam("gecko_spellcheck"); + + document.getElementById('htmlSource').value = tinyMCEPopup.editor.getContent({source_view : true}); + + if (tinyMCEPopup.editor.getParam("theme_advanced_source_editor_wrap", true)) { + setWrap('soft'); + document.getElementById('wraped').checked = true; + } + + resizeInputs(); +} + +function setWrap(val) { + var v, n, s = document.getElementById('htmlSource'); + + s.wrap = val; + + if (!tinymce.isIE) { + v = s.value; + n = s.cloneNode(false); + n.setAttribute("wrap", val); + s.parentNode.replaceChild(n, s); + n.value = v; + } +} + +function toggleWordWrap(elm) { + if (elm.checked) + setWrap('soft'); + else + setWrap('off'); +} + +function resizeInputs() { + var vp = tinyMCEPopup.dom.getViewPort(window), el; + + el = document.getElementById('htmlSource'); + + if (el) { + el.style.width = (vp.w - 20) + 'px'; + el.style.height = (vp.h - 65) + 'px'; + } +} diff --git a/src/core/static/js/tiny_mce/themes/advanced/langs/de.js b/src/core/static/js/tiny_mce/themes/advanced/langs/de.js new file mode 100755 index 0000000..034195c --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/langs/de.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.advanced',{"underline_desc":"Unterstrichen (Strg+U)","italic_desc":"Kursiv (Strg+I)","bold_desc":"Fett (Strg+B)",dd:"Definitionsbeschreibung",dt:"Definitionsbegriff",samp:"Beispiel",code:"Code",blockquote:"Zitatblock",h6:"\u00dcberschrift 6",h5:"\u00dcberschrift 5",h4:"\u00dcberschrift 4",h3:"\u00dcberschrift 3",h2:"\u00dcberschrift 2",h1:"\u00dcberschrift 1",pre:"Rohdaten",address:"Adresse",div:"Zusammenh\u00e4ngender Bereich",paragraph:"Absatz",block:"Vorlage",fontdefault:"Schriftart","font_size":"Schriftgr\u00f6\u00dfe","style_select":"Format","anchor_delta_width":"13","more_colors":"Weitere Farben","toolbar_focus":"Zur Werkzeugleiste springen: Alt+Q; Zum Editor springen: Alt-Z; Zum Elementpfad springen: Alt-X",newdocument:"Wollen Sie wirklich den ganzen Inhalt l\u00f6schen?",path:"Pfad","clipboard_msg":"Kopieren, Ausschneiden und Einf\u00fcgen sind im Mozilla Firefox nicht m\u00f6glich.\nWollen Sie mehr \u00fcber dieses Problem erfahren?","blockquote_desc":"Zitatblock","help_desc":"Hilfe","newdocument_desc":"Neues Dokument","image_props_desc":"Bildeigenschaften","paste_desc":"Einf\u00fcgen","copy_desc":"Kopieren","cut_desc":"Ausschneiden","anchor_desc":"Anker einf\u00fcgen/ver\u00e4ndern","visualaid_desc":"Hilfslinien und unsichtbare Elemente ein-/ausblenden","charmap_desc":"Sonderzeichen einf\u00fcgen","backcolor_desc":"Hintergrundfarbe","forecolor_desc":"Textfarbe","custom1_desc":"Benutzerdefinierte Beschreibung","removeformat_desc":"Formatierungen zur\u00fccksetzen","hr_desc":"Trennlinie einf\u00fcgen","sup_desc":"Hochgestellt","sub_desc":"Tiefgestellt","code_desc":"HTML-Quellcode bearbeiten","cleanup_desc":"Quellcode aufr\u00e4umen","image_desc":"Bild einf\u00fcgen/ver\u00e4ndern","unlink_desc":"Link entfernen","link_desc":"Link einf\u00fcgen/ver\u00e4ndern","redo_desc":"Wiederholen (Strg+Y)","undo_desc":"R\u00fcckg\u00e4ngig (Strg+Z)","indent_desc":"Einr\u00fccken","outdent_desc":"Ausr\u00fccken","numlist_desc":"Sortierte Liste","bullist_desc":"Unsortierte Liste","justifyfull_desc":"Blocksatz","justifyright_desc":"Rechtsb\u00fcndig","justifycenter_desc":"Zentriert","justifyleft_desc":"Linksb\u00fcndig","striketrough_desc":"Durchgestrichen","help_shortcut":"Dr\u00fccken Sie ALT-F10 f\u00fcr die Toolbar. Dr\u00fccken Sie ALT-0 f\u00fcr Hilfe","rich_text_area":"Rich Text Feld","shortcuts_desc":"Eingabehilfe",toolbar:"Toolbar","anchor_delta_height":"","charmap_delta_height":"","charmap_delta_width":"","colorpicker_delta_height":"","colorpicker_delta_width":"","link_delta_height":"","link_delta_width":"","image_delta_height":"","image_delta_width":""}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/advanced/langs/de_dlg.js b/src/core/static/js/tiny_mce/themes/advanced/langs/de_dlg.js new file mode 100755 index 0000000..b823694 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.advanced_dlg',{"link_list":"Linkliste","link_is_external":"Diese Adresse scheint ein externer Link zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"http://\" voranstellen?","link_is_email":"Diese Adresse scheint eine E-Mail-Adresse zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"mailto:\" voranstellen?","link_titlefield":"Titel","link_target_blank":"Neues Fenster \u00f6ffnen","link_target_same":"Im selben Fenster \u00f6ffnen","link_target":"Fenster","link_url":"Adresse","link_title":"Link einf\u00fcgen/ver\u00e4ndern","image_align_right":"Rechts","image_align_left":"Links","image_align_textbottom":"Unten im Text","image_align_texttop":"Oben im Text","image_align_bottom":"Unten","image_align_middle":"Mittig","image_align_top":"Oben","image_align_baseline":"Zeile","image_align":"Ausrichtung","image_hspace":"Horizontaler Abstand","image_vspace":"Vertikaler Abstand","image_dimensions":"Abmessungen","image_alt":"Alternativtext","image_list":"Bilderliste","image_border":"Rahmen","image_src":"Adresse","image_title":"Bild einf\u00fcgen/ver\u00e4ndern","charmap_title":"Sonderzeichen","colorpicker_name":"Name:","colorpicker_color":"Farbe:","colorpicker_named_title":"Benannte Farben","colorpicker_named_tab":"Benannte Farben","colorpicker_palette_title":"Farbpalette","colorpicker_palette_tab":"Palette","colorpicker_picker_title":"Farbwahl","colorpicker_picker_tab":"Farbwahl","colorpicker_title":"Farbe","code_wordwrap":"Automatischer Zeilenumbruch","code_title":"HTML-Quellcode bearbeiten","anchor_name":"Name des Ankers","anchor_title":"Anker einf\u00fcgen/ver\u00e4ndern","about_loaded":"Geladene Plugins","about_version":"Version","about_author":"Urheber","about_plugin":"Plugin","about_plugins":"Plugins","about_license":"Lizenzbedingungen","about_help":"Hilfe","about_general":"\u00dcber","about_title":"\u00dcber TinyMCE","charmap_usage":"Navigation mit linken und rechten Pfeilen.","anchor_invalid":"Bitte geben Sie einen g\u00fcltigen Namen f\u00fcr den Anker ein!","accessibility_help":"Eingabehilfe","accessibility_usage_title":"Allgemeine Verwendung"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/advanced/langs/en.js b/src/core/static/js/tiny_mce/themes/advanced/langs/en.js new file mode 100755 index 0000000..6e58481 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/langs/en.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.advanced',{"underline_desc":"Underline (Ctrl+U)","italic_desc":"Italic (Ctrl+I)","bold_desc":"Bold (Ctrl+B)",dd:"Definition Description",dt:"Definition Term ",samp:"Code Sample",code:"Code",blockquote:"Block Quote",h6:"Heading 6",h5:"Heading 5",h4:"Heading 4",h3:"Heading 3",h2:"Heading 2",h1:"Heading 1",pre:"Preformatted",address:"Address",div:"DIV",paragraph:"Paragraph",block:"Format",fontdefault:"Font Family","font_size":"Font Size","style_select":"Styles","anchor_delta_height":"","anchor_delta_width":"","charmap_delta_height":"","charmap_delta_width":"","colorpicker_delta_height":"","colorpicker_delta_width":"","link_delta_height":"","link_delta_width":"","image_delta_height":"","image_delta_width":"","more_colors":"More Colors...","toolbar_focus":"Jump to tool buttons - Alt+Q, Jump to editor - Alt-Z, Jump to element path - Alt-X",newdocument:"Are you sure you want clear all contents?",path:"Path","clipboard_msg":"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?","blockquote_desc":"Block Quote","help_desc":"Help","newdocument_desc":"New Document","image_props_desc":"Image Properties","paste_desc":"Paste (Ctrl+V)","copy_desc":"Copy (Ctrl+C)","cut_desc":"Cut (Ctrl+X)","anchor_desc":"Insert/Edit Anchor","visualaid_desc":"show/Hide Guidelines/Invisible Elements","charmap_desc":"Insert Special Character","backcolor_desc":"Select Background Color","forecolor_desc":"Select Text Color","custom1_desc":"Your Custom Description Here","removeformat_desc":"Remove Formatting","hr_desc":"Insert Horizontal Line","sup_desc":"Superscript","sub_desc":"Subscript","code_desc":"Edit HTML Source","cleanup_desc":"Cleanup Messy Code","image_desc":"Insert/Edit Image","unlink_desc":"Unlink","link_desc":"Insert/Edit Link","redo_desc":"Redo (Ctrl+Y)","undo_desc":"Undo (Ctrl+Z)","indent_desc":"Increase Indent","outdent_desc":"Decrease Indent","numlist_desc":"Insert/Remove Numbered List","bullist_desc":"Insert/Remove Bulleted List","justifyfull_desc":"Align Full","justifyright_desc":"Align Right","justifycenter_desc":"Align Center","justifyleft_desc":"Align Left","striketrough_desc":"Strikethrough","help_shortcut":"Press ALT-F10 for toolbar. Press ALT-0 for help","rich_text_area":"Rich Text Area","shortcuts_desc":"Accessability Help",toolbar:"Toolbar"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/advanced/langs/en_dlg.js b/src/core/static/js/tiny_mce/themes/advanced/langs/en_dlg.js new file mode 100755 index 0000000..5e786e3 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.advanced_dlg',{"link_list":"Link List","link_is_external":"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?","link_is_email":"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?","link_titlefield":"Title","link_target_blank":"Open Link in a New Window","link_target_same":"Open Link in the Same Window","link_target":"Target","link_url":"Link URL","link_title":"Insert/Edit Link","image_align_right":"Right","image_align_left":"Left","image_align_textbottom":"Text Bottom","image_align_texttop":"Text Top","image_align_bottom":"Bottom","image_align_middle":"Middle","image_align_top":"Top","image_align_baseline":"Baseline","image_align":"Alignment","image_hspace":"Horizontal Space","image_vspace":"Vertical Space","image_dimensions":"Dimensions","image_alt":"Image Description","image_list":"Image List","image_border":"Border","image_src":"Image URL","image_title":"Insert/Edit Image","charmap_title":"Select Special Character","colorpicker_name":"Name:","colorpicker_color":"Color:","colorpicker_named_title":"Named Colors","colorpicker_named_tab":"Named","colorpicker_palette_title":"Palette Colors","colorpicker_palette_tab":"Palette","colorpicker_picker_title":"Color Picker","colorpicker_picker_tab":"Picker","colorpicker_title":"Select a Color","code_wordwrap":"Word Wrap","code_title":"HTML Source Editor","anchor_name":"Anchor Name","anchor_title":"Insert/Edit Anchor","about_loaded":"Loaded Plugins","about_version":"Version","about_author":"Author","about_plugin":"Plugin","about_plugins":"Plugins","about_license":"License","about_help":"Help","about_general":"About","about_title":"About TinyMCE","charmap_usage":"Use left and right arrows to navigate.","anchor_invalid":"Please specify a valid anchor name.","accessibility_help":"Accessibility Help","accessibility_usage_title":"General Usage"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/advanced/langs/fr.js b/src/core/static/js/tiny_mce/themes/advanced/langs/fr.js new file mode 100755 index 0000000..1e91abb --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/langs/fr.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.advanced',{"underline_desc":"Soulign\u00e9 (Ctrl+U)","italic_desc":"Italique (Ctrl+I)","bold_desc":"Gras (Ctrl+B)",dd:"D\u00e9finition du terme",dt:"Terme \u00e0 d\u00e9finir",samp:"Exemple de code",code:"Code",blockquote:"Bloc de citation",h6:"Titre 6",h5:"Titre 5",h4:"Titre 4",h3:"Titre 3",h2:"Titre 2",h1:"Titre 1",pre:"Pr\u00e9format\u00e9",address:"Adresse",div:"Div",paragraph:"Paragraphe",block:"Format",fontdefault:"Police","font_size":"Taille police","style_select":"Styles","more_colors":"Plus de couleurs","toolbar_focus":"Atteindre les boutons de l\'\u00e9diteur - Alt+Q, Aller \u00e0 l\'\u00e9diteur - Alt-Z, Aller au chemin de l\'\u00e9l\u00e9ment - Alt-X",newdocument:"\u00cates-vous s\u00fbr de vouloir effacer l\'int\u00e9gralit\u00e9 du document ?",path:"Chemin","clipboard_msg":"Les fonctions Copier/Couper/Coller ne sont pas valables sur Mozilla et Firefox.\nSouhaitez-vous avoir plus d\'informations sur ce sujet ?","blockquote_desc":"Citation","help_desc":"Aide","newdocument_desc":"Nouveau document","image_props_desc":"Propri\u00e9t\u00e9s de l\'image","paste_desc":"Coller","copy_desc":"Copier","cut_desc":"Couper","anchor_desc":"Ins\u00e9rer / \u00e9diter une ancre","visualaid_desc":"Activer / d\u00e9sactiver les guides et les \u00e9l\u00e9ments invisibles","charmap_desc":"Ins\u00e9rer des caract\u00e8res sp\u00e9ciaux","backcolor_desc":"Choisir la couleur de surlignage","forecolor_desc":"Choisir la couleur du texte","custom1_desc":"Votre description personnalis\u00e9e ici","removeformat_desc":"Supprimer le formatage","hr_desc":"Ins\u00e9rer un trait horizontal","sup_desc":"Exposant","sub_desc":"Indice","code_desc":"\u00c9diter le code source HTML","cleanup_desc":"Nettoyer le code","image_desc":"Ins\u00e9rer / \u00e9diter l\'image","unlink_desc":"Supprimer le lien","link_desc":"Ins\u00e9rer / \u00e9diter le lien","redo_desc":"R\u00e9tablir (Ctrl+Y)","undo_desc":"Annuler (Ctrl+Z)","indent_desc":"Indenter","outdent_desc":"Retirer l\'indentation","numlist_desc":"Liste num\u00e9rot\u00e9e","bullist_desc":"Liste \u00e0 puces","justifyfull_desc":"Justifi\u00e9","justifyright_desc":"Align\u00e9 \u00e0 droite","justifycenter_desc":"Centr\u00e9","justifyleft_desc":"Align\u00e9 \u00e0 gauche","striketrough_desc":"Barr\u00e9","help_shortcut":"Faites ALT-F10 pour acc\u00e9der \u00e0 la barre d\'outils. Faites ALT-0 pour acc\u00e9der \u00e0 l\'aide","rich_text_area":"Zone de texte enrichi","shortcuts_desc":"Aides \u00e0 l\'accessibilit\u00e9",toolbar:"Barre d\'outils","anchor_delta_height":"","anchor_delta_width":"","charmap_delta_height":"","charmap_delta_width":"","colorpicker_delta_height":"","colorpicker_delta_width":"","link_delta_height":"","link_delta_width":"","image_delta_height":"","image_delta_width":""}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/advanced/langs/fr_dlg.js b/src/core/static/js/tiny_mce/themes/advanced/langs/fr_dlg.js new file mode 100755 index 0000000..2976296 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.advanced_dlg',{"link_list":"Liste de liens","link_is_external":"L\'URL que vous avez saisie semble \u00eatre une adresse web externe. Souhaitez-vous ajouter le pr\u00e9fixe \u00ab http:// \u00bb ?","link_is_email":"L\'URL que vous avez saisie semble \u00eatre une adresse e-mail, souhaitez-vous ajouter le pr\u00e9fixe \u00ab mailto: \u00bb ?","link_titlefield":"Titre","link_target_blank":"Ouvrir dans une nouvelle fen\u00eatre","link_target_same":"Ouvrir dans la m\u00eame fen\u00eatre","link_target":"Cible","link_url":"URL du lien","link_title":"Ins\u00e9rer / \u00e9diter un lien","image_align_right":"Droite (flottant)","image_align_left":"Gauche (flottant)","image_align_textbottom":"Texte en bas","image_align_texttop":"Texte en haut","image_align_bottom":"En bas","image_align_middle":"Au milieu","image_align_top":"En haut","image_align_baseline":"Normal","image_align":"Alignement","image_hspace":"Espacement horizontal","image_vspace":"Espacement vertical","image_dimensions":"Dimensions","image_alt":"Description de l\'image","image_list":"Liste d\'images","image_border":"Bordure","image_src":"URL de l\'image","image_title":"Ins\u00e9rer / \u00e9diter une image","charmap_title":"Choisir le caract\u00e8re \u00e0 ins\u00e9rer","colorpicker_name":"Nom :","colorpicker_color":"Couleur :","colorpicker_named_title":"Couleurs nomm\u00e9es","colorpicker_named_tab":"Noms","colorpicker_palette_title":"Couleurs de la palette","colorpicker_palette_tab":"Palette","colorpicker_picker_title":"Nuancier","colorpicker_picker_tab":"Nuancier","colorpicker_title":"Choisir une couleur","code_wordwrap":"Retour \u00e0 la ligne","code_title":"\u00c9diteur de source HTML","anchor_name":"Nom de l\'ancre","anchor_title":"Ins\u00e9rer / \u00e9diter une ancre","about_loaded":"Plugins charg\u00e9s","about_version":"Version","about_author":"Auteur","about_plugin":"Plugin","about_plugins":"Plugins","about_license":"Licence","about_help":"Aide","about_general":"\u00c0 propos","about_title":"\u00c0 propos de TinyMCE","anchor_invalid":"Veuillez sp\u00e9cifier un nom d\'ancre valide.","accessibility_help":"Accessibility Help","accessibility_usage_title":"General Usage"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/advanced/langs/it.js b/src/core/static/js/tiny_mce/themes/advanced/langs/it.js new file mode 100755 index 0000000..af84c79 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/langs/it.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.advanced',{"underline_desc":"Sottolineato (Ctrl+U)","italic_desc":"Corsivo (Ctrl+I)","bold_desc":"Grassetto (Ctrl+B)",dd:"Descrizione definizione",dt:"Termine definizione",samp:"Esempio codice",code:"Codice",blockquote:"Testo quotato",h6:"Intestazione 6",h5:"Intestazione 5",h4:"Intestazione 4",h3:"Intestazione 3",h2:"Intestazione 2",h1:"Intestazione 1",pre:"Preformattato",address:"Indirizzo",div:"Div",paragraph:"Paragrafo",block:"Formato",fontdefault:"Famiglia carattere","font_size":"Grandezza carattere","style_select":"Stili","anchor_delta_height":"anchor_delta_height","anchor_delta_width":"anchor_delta_width","charmap_delta_height":"charmap_delta_height","charmap_delta_width":"charmap_delta_width","colorpicker_delta_height":"colorpicker_delta_height","colorpicker_delta_width":"colorpicker_delta_width","link_delta_height":"link_delta_height","link_delta_width":"link_delta_width","image_delta_height":"image_delta_height","image_delta_width":"image_delta_width","more_colors":"Colori aggiuntivi","toolbar_focus":"Vai ai pulsanti strumento - Alt+Q, Vai all\'editor - Alt-Z, Vai al percorso dell\'elemento - Alt-X",newdocument:"Sei sicuro di voler cancellare tutti i contenuti?",path:"Percorso","clipboard_msg":"Copia/Taglia/Incolla non \u00e8 disponibile in Mozilla e Firefox..\nSi desidera avere maggiori informazioni su questo problema?","blockquote_desc":"Testo quotato","help_desc":"Aiuto","newdocument_desc":"Nuovo documento","image_props_desc":"Propriet\u00e0 immagine","paste_desc":"Incolla","copy_desc":"Copia","cut_desc":"Taglia","anchor_desc":"Inserisci/modifica ancora","visualaid_desc":"Mostra/nascondi linee guida/elementi invisibili","charmap_desc":"Inserisci carattere speciale","backcolor_desc":"Seleziona colore sfondo","forecolor_desc":"Seleziona colore testo","custom1_desc":"La tua descrizione personalizzata qui","removeformat_desc":"Rimuovi formattazione","hr_desc":"Inserisci riga orizzontale","sup_desc":"Apice","sub_desc":"Pedice","code_desc":"Modifica sorgente HTML","cleanup_desc":"Pulisci codice disordinato","image_desc":"Inserisci/modifica immagine","unlink_desc":"Togli collegamento","link_desc":"Inserisci/modifica collegamento","redo_desc":"Ripristina (Ctrl+Y)","undo_desc":"Annulla (Ctrl+Z)","indent_desc":"Sposta verso interno","outdent_desc":"Sposta verso esterno","numlist_desc":"Lista ordinata","bullist_desc":"Lista non ordinata","justifyfull_desc":"Giustifica","justifyright_desc":"Allinea a destra","justifycenter_desc":"Centra","justifyleft_desc":"Allinea a sinistra","striketrough_desc":"Barrato","help_shortcut":"Premi ALT-F10 Per la barra degli strumenti. Premi ALT-0 per l\'aiuto","rich_text_area":"Rich Text Area","shortcuts_desc":"Aiuto accessibilit\u00e0",toolbar:"Barra degli strumenti"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/advanced/langs/it_dlg.js b/src/core/static/js/tiny_mce/themes/advanced/langs/it_dlg.js new file mode 100755 index 0000000..10918c2 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.advanced_dlg',{"link_list":"Lista link","link_is_external":"L\'URL inserito sembra essere un link esterno. Aggiungere il necessario prefisso http:// ?","link_is_email":"L\'URL inserito sembra essere un indirizzo email. Aggiungere il necessario prefisso mailto: ?","link_titlefield":"Titolo","link_target_blank":"Apri link in una nuova finestra","link_target_same":"Apri link nella stessa finestra","link_target":"Target","link_url":"URL link","link_title":"Inserisci/modifica collegamento","image_align_right":"A destra","image_align_left":"A sinistra","image_align_textbottom":"In basso al testo","image_align_texttop":"In alto al testo","image_align_bottom":"In basso","image_align_middle":"In mezzo","image_align_top":"In alto","image_align_baseline":"Alla base","image_align":"Allineamentot","image_hspace":"Spaziatura orizz.","image_vspace":"Spaziatura vert.","image_dimensions":"Dimensioni","image_alt":"Descrizione","image_list":"Lista immagini","image_border":"Bordo","image_src":"URL immagine","image_title":"Inserisci/modifica immagine","charmap_title":"Seleziona carattere speciale","colorpicker_name":"Nome:","colorpicker_color":"Colore:","colorpicker_named_title":"Colori per nome","colorpicker_named_tab":"Per nome","colorpicker_palette_title":"Tavolozza dei colori","colorpicker_palette_tab":"Tavolozza","colorpicker_picker_title":"Selettore colori","colorpicker_picker_tab":"Selettore","colorpicker_title":"Seleziona un colore","code_wordwrap":"A capo automatico","code_title":"Editor sorgente HTML","anchor_name":"Nome ancora","anchor_title":"Inserisci/modifica ancora","about_loaded":"Plugin caricati","about_version":"Versione","about_author":"Autore","about_plugin":"Plugin","about_plugins":"Plugins","about_license":"Licenza","about_help":"Aiuto","about_general":"Informazioni","about_title":"Informazioni su TinyMCE","anchor_invalid":"Specificare un nome di ancora valido.","accessibility_help":"Accessibility Help","accessibility_usage_title":"General Usage"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/advanced/link.htm b/src/core/static/js/tiny_mce/themes/advanced/link.htm new file mode 100644 index 0000000..5d9dea9 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/link.htm @@ -0,0 +1,57 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.link_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="js/link.js"></script> +</head> +<body id="link" style="display: none"> +<form onsubmit="LinkDialog.update();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.link_title}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="nowrap"><label for="href">{#advanced_dlg.link_url}</label></td> + <td><table border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="href" name="href" type="text" class="mceFocus" value="" style="width: 200px" onchange="LinkDialog.checkPrefix(this);" /></td> + <td id="hrefbrowsercontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td><label for="link_list">{#advanced_dlg.link_list}</label></td> + <td><select id="link_list" name="link_list" onchange="document.getElementById('href').value=this.options[this.selectedIndex].value;"></select></td> + </tr> + <tr> + <td><label id="targetlistlabel" for="targetlist">{#advanced_dlg.link_target}</label></td> + <td><select id="target_list" name="target_list"></select></td> + </tr> + <tr> + <td class="nowrap"><label for="linktitle">{#advanced_dlg.link_titlefield}</label></td> + <td><input id="linktitle" name="linktitle" type="text" value="" style="width: 200px" /></td> + </tr> + <tr> + <td><label for="class_list">{#class_name}</label></td> + <td><select id="class_list" name="class_list"></select></td> + </tr> + </table> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/themes/advanced/shortcuts.htm b/src/core/static/js/tiny_mce/themes/advanced/shortcuts.htm new file mode 100644 index 0000000..20ec2f5 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/shortcuts.htm @@ -0,0 +1,47 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>{#advanced_dlg.accessibility_help}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript">tinyMCEPopup.requireLangPack();</script> + </head> + <body id="content"> + <h1>{#advanced_dlg.accessibility_usage_title}</h1> + <h2>Toolbars</h2> + <p>Press ALT-F10 to move focus to the toolbars. Navigate through the buttons using the arrow keys. + Press enter to activate a button and return focus to the editor. + Press escape to return focus to the editor without performing any actions.</p> + + <h2>Status Bar</h2> + <p>To access the editor status bar, press ALT-F11. Use the left and right arrow keys to navigate between elements in the path. + Press enter or space to select an element. Press escape to return focus to the editor without changing the selection.</p> + + <h2>Context Menu</h2> + <p>Press shift-F10 to activate the context menu. Use the up and down arrow keys to move between menu items. To open sub-menus press the right arrow key. + To close submenus press the left arrow key. Press escape to close the context menu.</p> + + <h1>Keyboard Shortcuts</h1> + <table> + <thead> + <tr> + <th>Keystroke</th> + <th>Function</th> + </tr> + </thead> + <tbody> + <tr> + <td>Control-B</td><td>Bold</td> + </tr> + <tr> + <td>Control-I</td><td>Italic</td> + </tr> + <tr> + <td>Control-Z</td><td>Undo</td> + </tr> + <tr> + <td>Control-Y</td><td>Redo</td> + </tr> + </tbody> + </table> + </body> +</html> diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/default/content.css b/src/core/static/js/tiny_mce/themes/advanced/skins/default/content.css new file mode 100644 index 0000000..2fd94a1 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/skins/default/content.css @@ -0,0 +1,50 @@ +body, td, pre {color:#000; font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px; margin:8px;} +body {background:#FFF;} +body.mceForceColors {background:#FFF; color:#000;} +body.mceBrowserDefaults {background:transparent; color:inherit; font-size:inherit; font-family:inherit;} +h1 {font-size: 2em} +h2 {font-size: 1.5em} +h3 {font-size: 1.17em} +h4 {font-size: 1em} +h5 {font-size: .83em} +h6 {font-size: .75em} +.mceItemTable, .mceItemTable td, .mceItemTable th, .mceItemTable caption, .mceItemVisualAid {border: 1px dashed #BBB;} +a.mceItemAnchor {display:inline-block; -webkit-user-select:all; -webkit-user-modify:read-only; -moz-user-select:all; -moz-user-modify:read-only; width:11px !important; height:11px !important; background:url(img/items.gif) no-repeat center center} +span.mceItemNbsp {background: #DDD} +td.mceSelected, th.mceSelected {background-color:#3399ff !important} +img {border:0;} +table, img, hr, .mceItemAnchor {cursor:default} +table td, table th {cursor:text} +ins {border-bottom:1px solid green; text-decoration: none; color:green} +del {color:red; text-decoration:line-through} +cite {border-bottom:1px dashed blue} +acronym {border-bottom:1px dotted #CCC; cursor:help} +abbr {border-bottom:1px dashed #CCC; cursor:help} + +/* IE */ +* html body { +scrollbar-3dlight-color:#F0F0EE; +scrollbar-arrow-color:#676662; +scrollbar-base-color:#F0F0EE; +scrollbar-darkshadow-color:#DDD; +scrollbar-face-color:#E0E0DD; +scrollbar-highlight-color:#F0F0EE; +scrollbar-shadow-color:#F0F0EE; +scrollbar-track-color:#F5F5F5; +} + +img:-moz-broken {-moz-force-broken-image-icon:1; width:24px; height:24px} +font[face=mceinline] {font-family:inherit !important} +*[contentEditable]:focus {outline:0} + +.mceItemMedia {border:1px dotted #cc0000; background-position:center; background-repeat:no-repeat; background-color:#ffffcc} +.mceItemShockWave {background-image:url(../../img/shockwave.gif)} +.mceItemFlash {background-image:url(../../img/flash.gif)} +.mceItemQuickTime {background-image:url(../../img/quicktime.gif)} +.mceItemWindowsMedia {background-image:url(../../img/windowsmedia.gif)} +.mceItemRealMedia {background-image:url(../../img/realmedia.gif)} +.mceItemVideo {background-image:url(../../img/video.gif)} +.mceItemAudio {background-image:url(../../img/video.gif)} +.mceItemEmbeddedAudio {background-image:url(../../img/video.gif)} +.mceItemIframe {background-image:url(../../img/iframe.gif)} +.mcePageBreak {display:block;border:0;width:100%;height:12px;border-top:1px dotted #ccc;margin-top:15px;background:#fff url(../../img/pagebreak.gif) no-repeat center top;} diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/default/dialog.css b/src/core/static/js/tiny_mce/themes/advanced/skins/default/dialog.css new file mode 100644 index 0000000..f012226 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/skins/default/dialog.css @@ -0,0 +1,117 @@ +/* Generic */ +body { +font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px; +scrollbar-3dlight-color:#F0F0EE; +scrollbar-arrow-color:#676662; +scrollbar-base-color:#F0F0EE; +scrollbar-darkshadow-color:#DDDDDD; +scrollbar-face-color:#E0E0DD; +scrollbar-highlight-color:#F0F0EE; +scrollbar-shadow-color:#F0F0EE; +scrollbar-track-color:#F5F5F5; +background:#F0F0EE; +padding:0; +margin:8px 8px 0 8px; +} + +html {background:#F0F0EE;} +td {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +textarea {resize:none;outline:none;} +a:link, a:visited {color:black;} +a:hover {color:#2B6FB6;} +.nowrap {white-space: nowrap} + +/* Forms */ +fieldset {margin:0; padding:4px; border:1px solid #919B9C; font-family:Verdana, Arial; font-size:10px;} +legend {color:#2B6FB6; font-weight:bold;} +label.msg {display:none;} +label.invalid {color:#EE0000; display:inline;} +input.invalid {border:1px solid #EE0000;} +input {background:#FFF; border:1px solid #CCC;} +input, select, textarea {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +input, select, textarea {border:1px solid #808080;} +input.radio {border:1px none #000000; background:transparent; vertical-align:middle;} +input.checkbox {border:1px none #000000; background:transparent; vertical-align:middle;} +.input_noborder {border:0;} + +/* Buttons */ +#insert, #cancel, input.button, .updateButton { +border:0; margin:0; padding:0; +font-weight:bold; +width:94px; height:26px; +background:url(img/buttons.png) 0 -26px; +cursor:pointer; +padding-bottom:2px; +float:left; +} + +#insert {background:url(img/buttons.png) 0 -52px} +#cancel {background:url(img/buttons.png) 0 0; float:right} + +/* Browse */ +a.pickcolor, a.browse {text-decoration:none} +a.browse span {display:block; width:20px; height:18px; background:url(../../img/icons.gif) -860px 0; border:1px solid #FFF; margin-left:1px;} +.mceOldBoxModel a.browse span {width:22px; height:20px;} +a.browse:hover span {border:1px solid #0A246A; background-color:#B2BBD0;} +a.browse span.disabled {border:1px solid white; opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +a.browse:hover span.disabled {border:1px solid white; background-color:transparent;} +a.pickcolor span {display:block; width:20px; height:16px; background:url(../../img/icons.gif) -840px 0; margin-left:2px;} +.mceOldBoxModel a.pickcolor span {width:21px; height:17px;} +a.pickcolor:hover span {background-color:#B2BBD0;} +a.pickcolor:hover span.disabled {} + +/* Charmap */ +table.charmap {border:1px solid #AAA; text-align:center} +td.charmap, #charmap a {width:18px; height:18px; color:#000; border:1px solid #AAA; text-align:center; font-size:12px; vertical-align:middle; line-height: 18px;} +#charmap a {display:block; color:#000; text-decoration:none; border:0} +#charmap a:hover {background:#CCC;color:#2B6FB6} +#charmap #codeN {font-size:10px; font-family:Arial,Helvetica,sans-serif; text-align:center} +#charmap #codeV {font-size:40px; height:80px; border:1px solid #AAA; text-align:center} + +/* Source */ +.wordWrapCode {vertical-align:middle; border:1px none #000000; background:transparent;} +.mceActionPanel {margin-top:5px;} + +/* Tabs classes */ +.tabs {width:100%; height:18px; line-height:normal; background:url(img/tabs.gif) repeat-x 0 -72px;} +.tabs ul {margin:0; padding:0; list-style:none;} +.tabs li {float:left; background:url(img/tabs.gif) no-repeat 0 0; margin:0 2px 0 0; padding:0 0 0 10px; line-height:17px; height:18px; display:block;} +.tabs li.current {background:url(img/tabs.gif) no-repeat 0 -18px; margin-right:2px;} +.tabs span {float:left; display:block; background:url(img/tabs.gif) no-repeat right -36px; padding:0px 10px 0 0;} +.tabs .current span {background:url(img/tabs.gif) no-repeat right -54px;} +.tabs a {text-decoration:none; font-family:Verdana, Arial; font-size:10px;} +.tabs a:link, .tabs a:visited, .tabs a:hover {color:black;} + +/* Panels */ +.panel_wrapper div.panel {display:none;} +.panel_wrapper div.current {display:block; width:100%; height:300px; overflow:visible;} +.panel_wrapper {border:1px solid #919B9C; border-top:0px; padding:10px; padding-top:5px; clear:both; background:white;} + +/* Columns */ +.column {float:left;} +.properties {width:100%;} +.properties .column1 {} +.properties .column2 {text-align:left;} + +/* Titles */ +h1, h2, h3, h4 {color:#2B6FB6; margin:0; padding:0; padding-top:5px;} +h3 {font-size:14px;} +.title {font-size:12px; font-weight:bold; color:#2B6FB6;} + +/* Dialog specific */ +#link .panel_wrapper, #link div.current {height:125px;} +#image .panel_wrapper, #image div.current {height:200px;} +#plugintable thead {font-weight:bold; background:#DDD;} +#plugintable, #about #plugintable td {border:1px solid #919B9C;} +#plugintable {width:96%; margin-top:10px;} +#pluginscontainer {height:290px; overflow:auto;} +#colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;} +#colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;} +#colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;} +#colorpicker #light div {overflow:hidden;} +#colorpicker #previewblock {float:right; padding-left:10px; height:20px;} +#colorpicker .panel_wrapper div.current {height:175px;} +#colorpicker #namedcolors {width:150px;} +#colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;} +#colorpicker #colornamecontainer {margin-top:5px;} +#colorpicker #picker_panel fieldset {margin:auto;width:325px;} diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/buttons.png b/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/buttons.png new file mode 100644 index 0000000000000000000000000000000000000000..1e53560e0aa7bb1b9a0373fc2f330acab7d1d51f GIT binary patch literal 3133 zcmV-D48rq?P)<h;3K|Lk000e1NJLTq003S9002%10{{R3p4w5z0006{P)t-s@9yp7 z<mB+r#qjU$^z`%j`S|hh@AdWc?d<EFAq?^H@U*kC^3cZS#=u)!TlLe(`1tmwv|i=K zzVh<%*Vor|h#2(I$Mo~^q_bRz9SUJ^6_k^b?Ca_6&Bgio`RVB9>gng~>+0yq!tBh% zt0xP1czF2u_k)9j>dM0B$HDja_H1ly_V)Go`1nXjNaW+;^YZfD+t}*M#Nxuc=*Yq1 z;NB`KDhCG#@bK{R@$l@+!)t46+`F{;`ugO=z30fm^Yila^6}@#zv02U-oCc!%EL4? zH23%S=jP<#-rMNs<w{CQ0RaK+?CRIIujItL*}1WKd3kzzdP_@7_4W1c%);NlxLsXc zgqa=Q+}Z2u=+4c{+}hXa$iL?0<K*Jtc6N5-!@R1xUWS-3eUBp(6BFRx-1YSH_4M@i z_4PS9IaO6vLPA0@F){G)@0qDf^z`)G+1B*)^I2J0@b2y9<KdB_IrQ}M@$v8I=Hy^t zVE6X+Zf<UlokaHb^yA~>>FMdm#>K$Dy`ivK#l*utK0e&s+{nkq>gea}%)@eWa<{g% z>dL@PO-<wB-|6S&@9^&O^6=Bs)4#sFbaZs7sHgDo?wOgF?CR<3>FDO<;_vP3{r&yS z%gJYFXW`)8?90T9iiya`$o2O1+}hao_x2?vCGqg?<>cY)?CRy@;^N@n=jG#KaTS=D zm+I)|g@uFe?(C6}kHNve?(FOH^YiBA;_dD0_xJVh?(XR4=IY46=jG(~_V(`W?9I*1 z!^6SJF#_`P^4;Ct@9*!-P0sTG012r{L_t(|+O?MXUsG2ahi}Pp<ApGqTa7alxQQSW zX&^8V4ajDKBte!qBFd(N%GL@BEmi8c?{%+RtL-?}rTac@XG=;6f7pEAbMBT(KmCO~ zkmTf??|I&P5<c8lC@wBu$PrKr#S8bhgI5Y)*=`0C3{3y&x6#w4@b>NZ7ob12<L4Yv zc&b=fcqw=Kmljn0nl%LlYu2p!9X(VqQ-GHO0+UN)4p82}tj9`T9{gEoGkL_)6>ts4 zA_nFqLtjdnoh+!creNnz_KL?&0LP2uu@&_VjZFOf^A4upSXxT<`l7sS>g!pxJp2~b zgUf1h)S;pzug4E}@{1@iQEJjdaP@Ltb^$+T7zI?z4@yu#C-3srtNyDv6^9}$t5I62 z>xb$~{1JaiNl_6V8bd?=JbL9-OZ-DXKO)}#7Xi}+6<r<D-(eH<8~JBnTIzB|TuzrC zpTIvr2`AzlLNNn>#OZW7Begij5aQTVUu2>r61l7mL6M<f;p!%wevLnadS|zjKJgNr z`bf8#+LA20zq{MdV;qyd)>%W;u2b1cxN5qol8KVq;TnzZb$VIutgWfp%2Ix?b*q1c zp^rpdy`U!2+}vDCtV5;l-Wsivb|!ywlycE%FI3t1UC}6o*QwN+^e&e(+6tmh&IV$* zwKr1BS*PP_W%O>?$}xn9*J^BNZXP!2n_RA@)&|hp<igj-scC3%ZisAP)arGj4aD#| z6U~fhLod%pfHT^l=?hC&3^z43^)@h~E)D3L%%=gcxL67!6Kt(D*~-H%y0T=_q{mk^ z98D%$dmHeCT3nw@s<oUd5dcjxiR;ve5VY8kY(<jgdy~+Z^id+&)msy7=;})Lq5!Dr z>N1XEREc(VbqzbSVA5n4^h7iXM|9ZGb3fK`idO7ys2Lt+`qm~5qe2Y=O=dNx30Fri zO%RZ1g`tQ4_sh%*NOe8@%T1~FFYSIIXUE2k`Uvcx=T}~&aOr7E^L^Zb*nQ}WPrdxk zJ1^$|SWi(Sa_XfVacZGB*KO4MjfcaFIU#(w@qM8&{Po|#YujGmtnxR;Yuh-x-oA6^ zuPW=;|7B_P^k$a3bLVa1+i;_B_~hj6+w(c#_U(fw4-4VU<aehBE}mOn_qmG$r@uRx z2@8uCCQpAbP*Ks-Q=wB##Cm#C#l;n=9uQ+QjZ2{g8e!-uHW>Ke^uY^@!eVA}U?3JN zw_3}~%v4||MYYOBD+pBBK=CiB2=GM=ZK74QsnEWGf%6%rzj!7P2v}t?l}eTCl$E#0 zCt|T!SuA#<MV4i2fQn)x0|r8r!IAO`yelhfk*#GM>?$iibMaNC?>Kiw?CEKdz7J@m zh=3#=raCG7elLNAKrH)!qKsKt#0a)nOqN=3Ipr#WE9WM;em?(%Xq9ft;&=}b#V3I$ zVj$2nbyH3S@RR!2vy>>^v{<H4fVRgNqI`34>Son5CX1CHOG#5ljy)?^FYn1j{`_;M zADPb=<Q99{;+`2Bo0+kK@v*V7aUpG=5W$2v5tx{$vIyyPTCxT>ZhIQ<?PGys#{%>? zHi5i*0!a~!kBegd{0P&(I-l?JIeb2!v}MbdD$qi>-D#hIVvMoz@o}r2GQRY`r|cGi z4IOo&281m>pFB3k;xjWdZg>8ChpzV$j-yf?=hiJ*-qPv)1oe0=FyoffUNeFlHkBhs z+(*6MIyZ&4Fl3Y7(s`pD2p`>>vJ*#-;!E?jd#RF4@GUKZ(yrmPyBRG|GN;h~pQ9AL zRR<)g&ZJL&<J$w;1&d|TLfo_5o9f@wK7~rsQDhmiTxXeku;&4bN?SN2Bx~I#d*%?9 z?8Ma6J&Q@-+3A?u3+B?`;lqal;oUona*U5Yva9&^5?HCzQCBYQePB^}1G^QI{#~E1 z|9S|__B%kDaVhkfLtwn|hPKge|6hpk+D-7KxzMN35)ad9$LArF{=NSG{!d2}qobpb z=6s;j0hH0v{xnBWfu(a4gfKE85W&$|9{#7pap|+sgr+|~pa0cYm%MX*eb+xu;K|#M z!vLkP??z`QRZ5$yT<`1a+aqK{i;wzdA;t!u?_)$}b^W<3?d>;iwD%4EptL_49PIl6 zhXKmq;2s}=Ev71;4-O8#m(B)@zP`a(n8A(2;9z3Td*z&}zj)?uJLsF9RTO3K;Pmt( z#fu7;o=yjG4h|InKc>^l^z>7oVg8Y(vD*K1`T=t9_6H%ju3Wl%=Hdv~4-CxT{qm2? z%9nTN2L_n_!g<_I&Roe~R<4}E?c_ObC*jPu2RV}+Bik6)ULEP^7@2&Ir`I^IgI%1r zu3>uDTZ~;ASf0c*?dzDlcI_HjMmoOEgmEkX>BA3y$^o$AR^AvsnYoZzejq&=Zp?KX zWwTjxrMKE_f-U@bGbpSq+-wFD3{0>8ZS=G`y!mn1CRl@QXV0$60cX!v2CewRY+Ji( z-@a9AmlJNRq%JMfhVjakqPSAWMx;bBWwWis3mYtrDFB0LnuotKvq<`V`_MU{CtI0? zHj_e^M#Eo`>x<?tjrQ%^r|Q=pf}XlGGb>YW`2>4Sop9r3$7^9D0|tV3X(>MKmaTjd zTktrvwvFjGojrtexg~ch8%eTiL$?HEDrQFQ(o|zg&NduBtLhIOr!H+##_1SX!$S-& zLZ~82VT&b<_XeVjKkdaT)8&MZn3s<q()EJurY_BGwc??HE=^Ry*Qa%9DURBuSq&ZX zZb}kXs|fuj{@EWo?(sN09*<PTadXlh0mTgLl<}m6FuF80bV#BOF3jVR)ufxy^>6O? z@Gec#kU^Eh>o9787rQi=j4n;`dL<UCV#xd7)b$pJLI`$y*iJ}<NAdDXKs}bA=%7n8 zASc#%SmK!U>2Ex7py*wi-C_@W;tGmM2H0td2k}Eu?UR&MBu6|>VLK7V2WZmcZX6GS zxVhu-27`juJ?VIY96{1iSCn8dt4q`M`ww_PhzNR&E=>uAmgv&rzt*M2LqTW>>P+IH z1N(Ko7y4j=2*o|XK`4oY=fy6~L8&FXv_z1HX=^Bv(Dl0y&{q|&t_}qgctS0PQeCYe z`pYgYR9#&iU!qG3RR?(*S6W@22p-sN=n3pnlmu<&1!%&<&tk3;N5Y%VhNKDTS)3e+ zxYwj#O?s^3If&gM#p`AIphv@~pdjEet2rJm%>~M8L%)0X>M#DVtbDN=Qm(JW=)me_ z<^ZH^(1$aRD>-eOHt8eKM$d&WQn~arrTISYK<sfQj9d9nIU{IABNEKyh+x>3<2LI5 XtZb~ra4Vor00000NkvXXu0mjf(5kL( literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/items.gif b/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/items.gif new file mode 100644 index 0000000000000000000000000000000000000000..d2f93671ca3090b277e16a67b1aa6cfb6ac4915f GIT binary patch literal 64 zcmZ?wbhEHb<YwSz_`t*f1poh^QT)lm%D}+HpabHAWE_~pU3$vJPT#)OT-dba%GH`< P{}UIOOiKDG%3uuu9X}L~ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif b/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif new file mode 100644 index 0000000000000000000000000000000000000000..85e31dfb2d0454de352d87fe95f7003f22c87992 GIT binary patch literal 68 zcmZ?wbhEHb6k!lyXkcUjg8%>jEB<5wG8q|kKzxu41Cw-5|H{*E`4`XOxxoD9Y}F^Z SLTQbO*E^TJI;F+RU=09Vu@yA{ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/menu_check.gif b/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/menu_check.gif new file mode 100644 index 0000000000000000000000000000000000000000..adfdddccd7cac62a17d68873fa53c248bff8351a GIT binary patch literal 70 zcmZ?wbhEHb6k!lyXkcUjg8%>jEB<5wG8q|kKzxu41Cwk||H{*E`4`XG(j;}D)%x|1 U%)82UlRJ8EoZ9xTT7<zG0H3rM{r~^~ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/progress.gif b/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/progress.gif new file mode 100644 index 0000000000000000000000000000000000000000..5bb90fd6a49107a321c35b9cee4a7b810314b51f GIT binary patch literal 1787 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 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/tabs.gif b/src/core/static/js/tiny_mce/themes/advanced/skins/default/img/tabs.gif new file mode 100644 index 0000000000000000000000000000000000000000..06812cb4109b0b236b9659c570458842e39c6416 GIT binary patch literal 1322 zcmV+_1=adTNk%w1VJrb!0QEKi{QUg<{QfdZVv?e=w#3bmr?lkh?BnU|?eX)Wv%9Ie zzvJoa`uqFH(aq4-(D3l;^z`rZ^X~HU?eX#K@bK&Q_VV@h@$~fY^YicW^6v5R?e_Nb z_4V@m`}z3z_V)Jl{r&v>{QLU)`S|$v@$cX6?dI$1<L~b1?Ca(6@aypJ>gD3v=j7e% z=;7w$-Rb7w=;hz@@$UBY^8Wt*`uh6+|Nj60000000000000000000000000000000 z00000A^8La001@sEC2ui04xDo06+%+K$1gIC>oE*q;kn@I-k&}bV{vSuh^_MTj5x~ z;IMd1E}PHjw0g~MyWjA*d`_1aD382;&+q&HfPsR8goTEOh>41ejE#<s1p$(il$Dm3 zl{K21oSmMZprN9pq@|{(sHv)}tgWu4k(jcxnXk6DxVgH!yuGeAz`?@9#Kp$P$jQpf z%+1cv(9zP<)Ya26Dh1Zt+}+;a;Njxq$|x+_<mu|`?CtLB0|V&q^!4`l_~erF`ThR? z00RmfNU)&6g9sBUT)3?O4G|C{N}NcsqQ#3CGiuz(v7^V2AVZ2ANwOr#0udreSjn=b z%a<@?%A85Frp=o;bL!m5v!~DhpFn*Uh)1-j(W6L{DqYI7sne%Wqe`7hwW`&tShL2W z#TApUuVBN99ZR+q!?S49woA}}gxa@o<5pAgf}h;Gc=HBpvBIw2zktu~3rx6h!oh|U zD_+dFvEyV44$PQLxw7TUm@{kM%(=7Y&!9t#9!<Km>C>oB7x?gDgX`C@W6PdRySDAy zxO3~?&AYen-@t<lA0E8Gg$o#xD__pMx%21Hqf4Joy}I@5*t2Wj&b_;L?gds(7*D>u z`Sa-0t6$H)z5Dm@<IA5<zrOwZ`0X=rAfUhh{{RLk;D7`cXyAbeCaB<o3^wTCgAhh2 zVT4<CW#J@cWvJnX9Cn!hN`)6%=;4SYmS|!xAcn}*i7dA0;)|Z7sN#$?)@b96IOeG1 zjy(2=<6}Su3C;`)C?MpKNKTVN3w|Z(<dejd07H{dR_P=PE>LOZmO%>O00UfxnIvLj zmiZW&W~QkanrgNg7@Ka!Dd(JY)@kRRc;=aq0|XcV<DY;ADkv!hfB*sjAtb8kqKr1` z=%bKED(R$@R%+>`m}aW!rkr-_>81sY;K8V*mTKy$sHUpws;su^>Z`EED(kGY)@tjm zxZYZTYZdhB>#x8DE9|hu7HjOW$R?}ovdlK??6c5DD=oAId~w{h*k-Hkw%m5>?YH2D zEAF`DmTT_0=%%ax?z-w0009Ik#VhZ;^ww+dz4+#<@4o!@>+in+2Q2Ww1Q$$j0U2bV z!NLqT?C`@7M=bHg6jyBV#TaL-@x~l??D5ASdtAVH6qIc8$tb6+^2#i??DESn$1L;A zG}mnN%{b?*GtOJ|?DNk+2QBo_L>Daue_181^wLZ>?ex=7N9~l1I}U2~)mXDawT@YL z?e*83Y@H+6WS1?d*f^T4_Sz?+eIwg&$E~5;Hp*@H-M-LWBi?-X{fgc`1}^yEgcol3 z;X3N6_(2E|;K1UL57dDST1Ia9J29Y8`Q@Cev*hNThaS!eb%|~|J5qvv`s&nRsXFVh zKVw2)vDa=#`|SV?;3e+7Ljz~;z#H>>@Wcl*eDTB|k38_oFVB1P&fgAw^tDe<{q@*q gul@Gickli8;D;~%_~eUY^!ezgum1Y%w;u!mJFYAXt^fc4 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/default/ui.css b/src/core/static/js/tiny_mce/themes/advanced/skins/default/ui.css new file mode 100644 index 0000000..2b7c2a5 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/skins/default/ui.css @@ -0,0 +1,214 @@ +/* Reset */ +.defaultSkin table, .defaultSkin tbody, .defaultSkin a, .defaultSkin img, .defaultSkin tr, .defaultSkin div, .defaultSkin td, .defaultSkin iframe, .defaultSkin span, .defaultSkin *, .defaultSkin .mceText {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000; vertical-align:baseline; width:auto; border-collapse:separate; text-align:left} +.defaultSkin a:hover, .defaultSkin a:link, .defaultSkin a:visited, .defaultSkin a:active {text-decoration:none; font-weight:normal; cursor:default; color:#000} +.defaultSkin table td {vertical-align:middle} + +/* Containers */ +.defaultSkin table {direction:ltr;background:transparent} +.defaultSkin iframe {display:block;} +.defaultSkin .mceToolbar {height:26px} +.defaultSkin .mceLeft {text-align:left} +.defaultSkin .mceRight {text-align:right} + +/* External */ +.defaultSkin .mceExternalToolbar {position:absolute; border:1px solid #CCC; border-bottom:0; display:none;} +.defaultSkin .mceExternalToolbar td.mceToolbar {padding-right:13px;} +.defaultSkin .mceExternalClose {position:absolute; top:3px; right:3px; width:7px; height:7px; background:url(../../img/icons.gif) -820px 0} + +/* Layout */ +.defaultSkin table.mceLayout {border:0; border-left:1px solid #CCC; border-right:1px solid #CCC} +.defaultSkin table.mceLayout tr.mceFirst td {border-top:1px solid #CCC} +.defaultSkin table.mceLayout tr.mceLast td {border-bottom:1px solid #CCC} +.defaultSkin table.mceToolbar, .defaultSkin tr.mceFirst .mceToolbar tr td, .defaultSkin tr.mceLast .mceToolbar tr td {border:0; margin:0; padding:0;} +.defaultSkin td.mceToolbar {background:#F0F0EE; padding-top:1px; vertical-align:top} +.defaultSkin .mceIframeContainer {border-top:1px solid #CCC; border-bottom:1px solid #CCC} +.defaultSkin .mceStatusbar {background:#F0F0EE; font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:9pt; line-height:16px; overflow:visible; color:#000; display:block; height:20px} +.defaultSkin .mceStatusbar div {float:left; margin:2px} +.defaultSkin .mceStatusbar a.mceResize {display:block; float:right; background:url(../../img/icons.gif) -800px 0; width:20px; height:20px; cursor:se-resize; outline:0} +.defaultSkin .mceStatusbar a:hover {text-decoration:underline} +.defaultSkin table.mceToolbar {margin-left:3px} +.defaultSkin span.mceIcon, .defaultSkin img.mceIcon {display:block; width:20px; height:20px} +.defaultSkin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px} +.defaultSkin td.mceCenter {text-align:center;} +.defaultSkin td.mceCenter table {margin:0 auto; text-align:left;} +.defaultSkin td.mceRight table {margin:0 0 0 auto;} + +/* Button */ +.defaultSkin .mceButton {display:block; border:1px solid #F0F0EE; width:20px; height:20px; margin-right:1px} +.defaultSkin a.mceButtonEnabled:hover {border:1px solid #0A246A; background-color:#B2BBD0} +.defaultSkin a.mceButtonActive, .defaultSkin a.mceButtonSelected {border:1px solid #0A246A; background-color:#C2CBE0} +.defaultSkin .mceButtonDisabled .mceIcon {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +.defaultSkin .mceButtonLabeled {width:auto} +.defaultSkin .mceButtonLabeled span.mceIcon {float:left} +.defaultSkin span.mceButtonLabel {display:block; font-size:10px; padding:4px 6px 0 22px; font-family:Tahoma,Verdana,Arial,Helvetica} +.defaultSkin .mceButtonDisabled .mceButtonLabel {color:#888} + +/* Separator */ +.defaultSkin .mceSeparator {display:block; background:url(../../img/icons.gif) -180px 0; width:2px; height:20px; margin:2px 2px 0 4px} + +/* ListBox */ +.defaultSkin .mceListBox, .defaultSkin .mceListBox a {display:block} +.defaultSkin .mceListBox .mceText {padding-left:4px; width:70px; text-align:left; border:1px solid #CCC; border-right:0; background:#FFF; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; height:20px; line-height:20px; overflow:hidden} +.defaultSkin .mceListBox .mceOpen {width:9px; height:20px; background:url(../../img/icons.gif) -741px 0; margin-right:2px; border:1px solid #CCC;} +.defaultSkin table.mceListBoxEnabled:hover .mceText, .defaultSkin .mceListBoxHover .mceText, .defaultSkin .mceListBoxSelected .mceText {border:1px solid #A2ABC0; border-right:0; background:#FFF} +.defaultSkin table.mceListBoxEnabled:hover .mceOpen, .defaultSkin .mceListBoxHover .mceOpen, .defaultSkin .mceListBoxSelected .mceOpen {background-color:#FFF; border:1px solid #A2ABC0} +.defaultSkin .mceListBoxDisabled a.mceText {color:gray; background-color:transparent;} +.defaultSkin .mceListBoxMenu {overflow:auto; overflow-x:hidden} +.defaultSkin .mceOldBoxModel .mceListBox .mceText {height:22px} +.defaultSkin .mceOldBoxModel .mceListBox .mceOpen {width:11px; height:22px;} +.defaultSkin select.mceNativeListBox {font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:7pt; background:#F0F0EE; border:1px solid gray; margin-right:2px;} + +/* SplitButton */ +.defaultSkin .mceSplitButton {width:32px; height:20px; direction:ltr} +.defaultSkin .mceSplitButton a, .defaultSkin .mceSplitButton span {height:20px; display:block} +.defaultSkin .mceSplitButton a.mceAction {width:20px; border:1px solid #F0F0EE; border-right:0;} +.defaultSkin .mceSplitButton span.mceAction {width:20px; background-image:url(../../img/icons.gif);} +.defaultSkin .mceSplitButton a.mceOpen {width:9px; background:url(../../img/icons.gif) -741px 0; border:1px solid #F0F0EE;} +.defaultSkin .mceSplitButton span.mceOpen {display:none} +.defaultSkin table.mceSplitButtonEnabled:hover a.mceAction, .defaultSkin .mceSplitButtonHover a.mceAction, .defaultSkin .mceSplitButtonSelected a.mceAction {border:1px solid #0A246A; border-right:0; background-color:#B2BBD0} +.defaultSkin table.mceSplitButtonEnabled:hover a.mceOpen, .defaultSkin .mceSplitButtonHover a.mceOpen, .defaultSkin .mceSplitButtonSelected a.mceOpen {background-color:#B2BBD0; border:1px solid #0A246A;} +.defaultSkin .mceSplitButtonDisabled .mceAction, .defaultSkin .mceSplitButtonDisabled a.mceOpen {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +.defaultSkin .mceSplitButtonActive a.mceAction {border:1px solid #0A246A; background-color:#C2CBE0} +.defaultSkin .mceSplitButtonActive a.mceOpen {border-left:0;} + +/* ColorSplitButton */ +.defaultSkin div.mceColorSplitMenu table {background:#FFF; border:1px solid gray} +.defaultSkin .mceColorSplitMenu td {padding:2px} +.defaultSkin .mceColorSplitMenu a {display:block; width:9px; height:9px; overflow:hidden; border:1px solid #808080} +.defaultSkin .mceColorSplitMenu td.mceMoreColors {padding:1px 3px 1px 1px} +.defaultSkin .mceColorSplitMenu a.mceMoreColors {width:100%; height:auto; text-align:center; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; line-height:20px; border:1px solid #FFF} +.defaultSkin .mceColorSplitMenu a.mceMoreColors:hover {border:1px solid #0A246A; background-color:#B6BDD2} +.defaultSkin a.mceMoreColors:hover {border:1px solid #0A246A} +.defaultSkin .mceColorPreview {margin-left:2px; width:16px; height:4px; overflow:hidden; background:#9a9b9a} +.defaultSkin .mce_forecolor span.mceAction, .defaultSkin .mce_backcolor span.mceAction {overflow:hidden; height:16px} + +/* Menu */ +.defaultSkin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #D4D0C8} +.defaultSkin .mceNoIcons span.mceIcon {width:0;} +.defaultSkin .mceNoIcons a .mceText {padding-left:10px} +.defaultSkin .mceMenu table {background:#FFF} +.defaultSkin .mceMenu a, .defaultSkin .mceMenu span, .defaultSkin .mceMenu {display:block} +.defaultSkin .mceMenu td {height:20px} +.defaultSkin .mceMenu a {position:relative;padding:3px 0 4px 0} +.defaultSkin .mceMenu .mceText {position:relative; display:block; font-family:Tahoma,Verdana,Arial,Helvetica; color:#000; cursor:default; margin:0; padding:0 25px 0 25px; display:block} +.defaultSkin .mceMenu span.mceText, .defaultSkin .mceMenu .mcePreview {font-size:11px} +.defaultSkin .mceMenu pre.mceText {font-family:Monospace} +.defaultSkin .mceMenu .mceIcon {position:absolute; top:0; left:0; width:22px;} +.defaultSkin .mceMenu .mceMenuItemEnabled a:hover, .defaultSkin .mceMenu .mceMenuItemActive {background-color:#dbecf3} +.defaultSkin td.mceMenuItemSeparator {background:#DDD; height:1px} +.defaultSkin .mceMenuItemTitle a {border:0; background:#EEE; border-bottom:1px solid #DDD} +.defaultSkin .mceMenuItemTitle span.mceText {color:#000; font-weight:bold; padding-left:4px} +.defaultSkin .mceMenuItemDisabled .mceText {color:#888} +.defaultSkin .mceMenuItemSelected .mceIcon {background:url(img/menu_check.gif)} +.defaultSkin .mceNoIcons .mceMenuItemSelected a {background:url(img/menu_arrow.gif) no-repeat -6px center} +.defaultSkin .mceMenu span.mceMenuLine {display:none} +.defaultSkin .mceMenuItemSub a {background:url(img/menu_arrow.gif) no-repeat top right;} +.defaultSkin .mceMenuItem td, .defaultSkin .mceMenuItem th {line-height: normal} + +/* Progress,Resize */ +.defaultSkin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=50)'; filter:alpha(opacity=50); background:#FFF} +.defaultSkin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px} + +/* Formats */ +.defaultSkin .mce_formatPreview a {font-size:10px} +.defaultSkin .mce_p span.mceText {} +.defaultSkin .mce_address span.mceText {font-style:italic} +.defaultSkin .mce_pre span.mceText {font-family:monospace} +.defaultSkin .mce_h1 span.mceText {font-weight:bolder; font-size: 2em} +.defaultSkin .mce_h2 span.mceText {font-weight:bolder; font-size: 1.5em} +.defaultSkin .mce_h3 span.mceText {font-weight:bolder; font-size: 1.17em} +.defaultSkin .mce_h4 span.mceText {font-weight:bolder; font-size: 1em} +.defaultSkin .mce_h5 span.mceText {font-weight:bolder; font-size: .83em} +.defaultSkin .mce_h6 span.mceText {font-weight:bolder; font-size: .75em} + +/* Theme */ +.defaultSkin span.mce_bold {background-position:0 0} +.defaultSkin span.mce_italic {background-position:-60px 0} +.defaultSkin span.mce_underline {background-position:-140px 0} +.defaultSkin span.mce_strikethrough {background-position:-120px 0} +.defaultSkin span.mce_undo {background-position:-160px 0} +.defaultSkin span.mce_redo {background-position:-100px 0} +.defaultSkin span.mce_cleanup {background-position:-40px 0} +.defaultSkin span.mce_bullist {background-position:-20px 0} +.defaultSkin span.mce_numlist {background-position:-80px 0} +.defaultSkin span.mce_justifyleft {background-position:-460px 0} +.defaultSkin span.mce_justifyright {background-position:-480px 0} +.defaultSkin span.mce_justifycenter {background-position:-420px 0} +.defaultSkin span.mce_justifyfull {background-position:-440px 0} +.defaultSkin span.mce_anchor {background-position:-200px 0} +.defaultSkin span.mce_indent {background-position:-400px 0} +.defaultSkin span.mce_outdent {background-position:-540px 0} +.defaultSkin span.mce_link {background-position:-500px 0} +.defaultSkin span.mce_unlink {background-position:-640px 0} +.defaultSkin span.mce_sub {background-position:-600px 0} +.defaultSkin span.mce_sup {background-position:-620px 0} +.defaultSkin span.mce_removeformat {background-position:-580px 0} +.defaultSkin span.mce_newdocument {background-position:-520px 0} +.defaultSkin span.mce_image {background-position:-380px 0} +.defaultSkin span.mce_help {background-position:-340px 0} +.defaultSkin span.mce_code {background-position:-260px 0} +.defaultSkin span.mce_hr {background-position:-360px 0} +.defaultSkin span.mce_visualaid {background-position:-660px 0} +.defaultSkin span.mce_charmap {background-position:-240px 0} +.defaultSkin span.mce_paste {background-position:-560px 0} +.defaultSkin span.mce_copy {background-position:-700px 0} +.defaultSkin span.mce_cut {background-position:-680px 0} +.defaultSkin span.mce_blockquote {background-position:-220px 0} +.defaultSkin .mce_forecolor span.mceAction {background-position:-720px 0} +.defaultSkin .mce_backcolor span.mceAction {background-position:-760px 0} +.defaultSkin span.mce_forecolorpicker {background-position:-720px 0} +.defaultSkin span.mce_backcolorpicker {background-position:-760px 0} + +/* Plugins */ +.defaultSkin span.mce_advhr {background-position:-0px -20px} +.defaultSkin span.mce_ltr {background-position:-20px -20px} +.defaultSkin span.mce_rtl {background-position:-40px -20px} +.defaultSkin span.mce_emotions {background-position:-60px -20px} +.defaultSkin span.mce_fullpage {background-position:-80px -20px} +.defaultSkin span.mce_fullscreen {background-position:-100px -20px} +.defaultSkin span.mce_iespell {background-position:-120px -20px} +.defaultSkin span.mce_insertdate {background-position:-140px -20px} +.defaultSkin span.mce_inserttime {background-position:-160px -20px} +.defaultSkin span.mce_absolute {background-position:-180px -20px} +.defaultSkin span.mce_backward {background-position:-200px -20px} +.defaultSkin span.mce_forward {background-position:-220px -20px} +.defaultSkin span.mce_insert_layer {background-position:-240px -20px} +.defaultSkin span.mce_insertlayer {background-position:-260px -20px} +.defaultSkin span.mce_movebackward {background-position:-280px -20px} +.defaultSkin span.mce_moveforward {background-position:-300px -20px} +.defaultSkin span.mce_media {background-position:-320px -20px} +.defaultSkin span.mce_nonbreaking {background-position:-340px -20px} +.defaultSkin span.mce_pastetext {background-position:-360px -20px} +.defaultSkin span.mce_pasteword {background-position:-380px -20px} +.defaultSkin span.mce_selectall {background-position:-400px -20px} +.defaultSkin span.mce_preview {background-position:-420px -20px} +.defaultSkin span.mce_print {background-position:-440px -20px} +.defaultSkin span.mce_cancel {background-position:-460px -20px} +.defaultSkin span.mce_save {background-position:-480px -20px} +.defaultSkin span.mce_replace {background-position:-500px -20px} +.defaultSkin span.mce_search {background-position:-520px -20px} +.defaultSkin span.mce_styleprops {background-position:-560px -20px} +.defaultSkin span.mce_table {background-position:-580px -20px} +.defaultSkin span.mce_cell_props {background-position:-600px -20px} +.defaultSkin span.mce_delete_table {background-position:-620px -20px} +.defaultSkin span.mce_delete_col {background-position:-640px -20px} +.defaultSkin span.mce_delete_row {background-position:-660px -20px} +.defaultSkin span.mce_col_after {background-position:-680px -20px} +.defaultSkin span.mce_col_before {background-position:-700px -20px} +.defaultSkin span.mce_row_after {background-position:-720px -20px} +.defaultSkin span.mce_row_before {background-position:-740px -20px} +.defaultSkin span.mce_merge_cells {background-position:-760px -20px} +.defaultSkin span.mce_table_props {background-position:-980px -20px} +.defaultSkin span.mce_row_props {background-position:-780px -20px} +.defaultSkin span.mce_split_cells {background-position:-800px -20px} +.defaultSkin span.mce_template {background-position:-820px -20px} +.defaultSkin span.mce_visualchars {background-position:-840px -20px} +.defaultSkin span.mce_abbr {background-position:-860px -20px} +.defaultSkin span.mce_acronym {background-position:-880px -20px} +.defaultSkin span.mce_attribs {background-position:-900px -20px} +.defaultSkin span.mce_cite {background-position:-920px -20px} +.defaultSkin span.mce_del {background-position:-940px -20px} +.defaultSkin span.mce_ins {background-position:-960px -20px} +.defaultSkin span.mce_pagebreak {background-position:0 -40px} +.defaultSkin span.mce_restoredraft {background-position:-20px -40px} +.defaultSkin span.mce_spellchecker {background-position:-540px -20px} diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/content.css b/src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/content.css new file mode 100644 index 0000000..cbce6c6 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/content.css @@ -0,0 +1,24 @@ +body, td, pre { margin:8px;} +body.mceForceColors {background:#FFF; color:#000;} +h1 {font-size: 2em} +h2 {font-size: 1.5em} +h3 {font-size: 1.17em} +h4 {font-size: 1em} +h5 {font-size: .83em} +h6 {font-size: .75em} +.mceItemTable, .mceItemTable td, .mceItemTable th, .mceItemTable caption, .mceItemVisualAid {border: 1px dashed #BBB;} +a.mceItemAnchor {display:inline-block; width:11px !important; height:11px !important; background:url(../default/img/items.gif) no-repeat 0 0;} +span.mceItemNbsp {background: #DDD} +td.mceSelected, th.mceSelected {background-color:#3399ff !important} +img {border:0;} +table, img, hr, .mceItemAnchor {cursor:default} +table td, table th {cursor:text} +ins {border-bottom:1px solid green; text-decoration: none; color:green} +del {color:red; text-decoration:line-through} +cite {border-bottom:1px dashed blue} +acronym {border-bottom:1px dotted #CCC; cursor:help} +abbr {border-bottom:1px dashed #CCC; cursor:help} + +img:-moz-broken {-moz-force-broken-image-icon:1; width:24px; height:24px} +font[face=mceinline] {font-family:inherit !important} +*[contentEditable]:focus {outline:0} diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/dialog.css b/src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/dialog.css new file mode 100644 index 0000000..b2ed097 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/dialog.css @@ -0,0 +1,105 @@ +/* Generic */ +body { +font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px; +background:#F0F0EE; +color: black; +padding:0; +margin:8px 8px 0 8px; +} + +html {background:#F0F0EE; color:#000;} +td {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +textarea {resize:none;outline:none;} +a:link, a:visited {color:black;background-color:transparent;} +a:hover {color:#2B6FB6;background-color:transparent;} +.nowrap {white-space: nowrap} + +/* Forms */ +fieldset {margin:0; padding:4px; border:1px solid #919B9C; font-family:Verdana, Arial; font-size:10px;} +legend {color:#2B6FB6; font-weight:bold;} +label.msg {display:none;} +label.invalid {color:#EE0000; display:inline;background-color:transparent;} +input.invalid {border:1px solid #EE0000;background-color:transparent;} +input {background:#FFF; border:1px solid #CCC;color:black;} +input, select, textarea {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +input, select, textarea {border:1px solid #808080;} +input.radio {border:1px none #000000; background:transparent; vertical-align:middle;} +input.checkbox {border:1px none #000000; background:transparent; vertical-align:middle;} +.input_noborder {border:0;} + +/* Buttons */ +#insert, #cancel, input.button, .updateButton { +font-weight:bold; +width:94px; height:23px; +cursor:pointer; +padding-bottom:2px; +float:left; +} + +#cancel {float:right} + +/* Browse */ +a.pickcolor, a.browse {text-decoration:none} +a.browse span {display:block; width:20px; height:18px; background:url(../../img/icons.gif) -860px 0; border:1px solid #FFF; margin-left:1px;} +.mceOldBoxModel a.browse span {width:22px; height:20px;} +a.browse:hover span {border:1px solid #0A246A; background-color:#B2BBD0;} +a.browse span.disabled {border:1px solid white; opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +a.browse:hover span.disabled {border:1px solid white; background-color:transparent;} +a.pickcolor span {display:block; width:20px; height:16px; background:url(../../img/icons.gif) -840px 0; margin-left:2px;} +.mceOldBoxModel a.pickcolor span {width:21px; height:17px;} +a.pickcolor:hover span {background-color:#B2BBD0;} +a.pickcolor:hover span.disabled {} + +/* Charmap */ +table.charmap {border:1px solid #AAA; text-align:center} +td.charmap, #charmap a {width:18px; height:18px; color:#000; border:1px solid #AAA; text-align:center; font-size:12px; vertical-align:middle; line-height: 18px;} +#charmap a {display:block; color:#000; text-decoration:none; border:0} +#charmap a:hover {background:#CCC;color:#2B6FB6} +#charmap #codeN {font-size:10px; font-family:Arial,Helvetica,sans-serif; text-align:center} +#charmap #codeV {font-size:40px; height:80px; border:1px solid #AAA; text-align:center} + +/* Source */ +.wordWrapCode {vertical-align:middle; border:1px none #000000; background:transparent;} +.mceActionPanel {margin-top:5px;} + +/* Tabs classes */ +.tabs {width:100%; height:18px; line-height:normal;} +.tabs ul {margin:0; padding:0; list-style:none;} +.tabs li {float:left; border: 1px solid black; border-bottom:0; margin:0 2px 0 0; padding:0 0 0 10px; line-height:17px; height:18px; display:block; cursor:pointer;} +.tabs li.current {font-weight: bold; margin-right:2px;} +.tabs span {float:left; display:block; padding:0px 10px 0 0;} +.tabs a {text-decoration:none; font-family:Verdana, Arial; font-size:10px;} +.tabs a:link, .tabs a:visited, .tabs a:hover {color:black;} + +/* Panels */ +.panel_wrapper div.panel {display:none;} +.panel_wrapper div.current {display:block; width:100%; height:300px; overflow:visible;} +.panel_wrapper {border:1px solid #919B9C; padding:10px; padding-top:5px; clear:both; background:white;} + +/* Columns */ +.column {float:left;} +.properties {width:100%;} +.properties .column1 {} +.properties .column2 {text-align:left;} + +/* Titles */ +h1, h2, h3, h4 {color:#2B6FB6; margin:0; padding:0; padding-top:5px;} +h3 {font-size:14px;} +.title {font-size:12px; font-weight:bold; color:#2B6FB6;} + +/* Dialog specific */ +#link .panel_wrapper, #link div.current {height:125px;} +#image .panel_wrapper, #image div.current {height:200px;} +#plugintable thead {font-weight:bold; background:#DDD;} +#plugintable, #about #plugintable td {border:1px solid #919B9C;} +#plugintable {width:96%; margin-top:10px;} +#pluginscontainer {height:290px; overflow:auto;} +#colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;} +#colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;} +#colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;} +#colorpicker #light div {overflow:hidden;} +#colorpicker #previewblock {float:right; padding-left:10px; height:20px;} +#colorpicker .panel_wrapper div.current {height:175px;} +#colorpicker #namedcolors {width:150px;} +#colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;} +#colorpicker #colornamecontainer {margin-top:5px;} diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/ui.css b/src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/ui.css new file mode 100644 index 0000000..a2cfcc3 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/skins/highcontrast/ui.css @@ -0,0 +1,102 @@ +/* Reset */ +.highcontrastSkin table, .highcontrastSkin tbody, .highcontrastSkin a, .highcontrastSkin img, .highcontrastSkin tr, .highcontrastSkin div, .highcontrastSkin td, .highcontrastSkin iframe, .highcontrastSkin span, .highcontrastSkin *, .highcontrastSkin .mceText {border:0; margin:0; padding:0; vertical-align:baseline; border-collapse:separate;} +.highcontrastSkin a:hover, .highcontrastSkin a:link, .highcontrastSkin a:visited, .highcontrastSkin a:active {text-decoration:none; font-weight:normal; cursor:default;} +.highcontrastSkin table td {vertical-align:middle} + +.highcontrastSkin .mceIconOnly {display: block !important;} + +/* External */ +.highcontrastSkin .mceExternalToolbar {position:absolute; border:1px solid; border-bottom:0; display:none; background-color: white;} +.highcontrastSkin .mceExternalToolbar td.mceToolbar {padding-right:13px;} +.highcontrastSkin .mceExternalClose {position:absolute; top:3px; right:3px; width:7px; height:7px;} + +/* Layout */ +.highcontrastSkin table.mceLayout {border: 1px solid;} +.highcontrastSkin .mceIframeContainer {border-top:1px solid; border-bottom:1px solid} +.highcontrastSkin .mceStatusbar a:hover {text-decoration:underline} +.highcontrastSkin .mceStatusbar {display:block; line-height:1.5em; overflow:visible;} +.highcontrastSkin .mceStatusbar div {float:left} +.highcontrastSkin .mceStatusbar a.mceResize {display:block; float:right; width:20px; height:20px; cursor:se-resize; outline:0} + +.highcontrastSkin .mceToolbar td { display: inline-block; float: left;} +.highcontrastSkin .mceToolbar tr { display: block;} +.highcontrastSkin .mceToolbar table { display: block; } + +/* Button */ + +.highcontrastSkin .mceButton { display:block; margin: 2px; padding: 5px 10px;border: 1px solid; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; -ms-border-radius: 3px; height: 2em;} +.highcontrastSkin .mceButton .mceVoiceLabel { height: 100%; vertical-align: center; line-height: 2em} +.highcontrastSkin .mceButtonDisabled .mceVoiceLabel { opacity:0.6; -ms-filter:'alpha(opacity=60)'; filter:alpha(opacity=60);} +.highcontrastSkin .mceButtonActive, .highcontrastSkin .mceButton:focus, .highcontrastSkin .mceButton:active { border: 5px solid; padding: 1px 6px;-webkit-focus-ring-color:none;outline:none;} + +/* Separator */ +.highcontrastSkin .mceSeparator {display:block; width:16px; height:26px;} + +/* ListBox */ +.highcontrastSkin .mceListBox { display: block; margin:2px;-webkit-focus-ring-color:none;outline:none;} +.highcontrastSkin .mceListBox .mceText {padding: 5px 6px; line-height: 2em; width: 15ex; overflow: hidden;} +.highcontrastSkin .mceListBoxDisabled .mceText { opacity:0.6; -ms-filter:'alpha(opacity=60)'; filter:alpha(opacity=60);} +.highcontrastSkin .mceListBox a.mceText { padding: 5px 10px; display: block; height: 2em; line-height: 2em; border: 1px solid; border-right: 0; border-radius: 3px 0px 0px 3px; -moz-border-radius: 3px 0px 0px 3px; -webkit-border-radius: 3px 0px 0px 3px; -ms-border-radius: 3px 0px 0px 3px;} +.highcontrastSkin .mceListBox a.mceOpen { padding: 5px 4px; display: block; height: 2em; line-height: 2em; border: 1px solid; border-left: 0; border-radius: 0px 3px 3px 0px; -moz-border-radius: 0px 3px 3px 0px; -webkit-border-radius: 0px 3px 3px 0px; -ms-border-radius: 0px 3px 3px 0px;} +.highcontrastSkin .mceListBox:focus a.mceText, .highcontrastSkin .mceListBox:active a.mceText { border-width: 5px; padding: 1px 10px 1px 6px;} +.highcontrastSkin .mceListBox:focus a.mceOpen, .highcontrastSkin .mceListBox:active a.mceOpen { border-width: 5px; padding: 1px 0px 1px 4px;} + +.highcontrastSkin .mceListBoxMenu {overflow-y:auto} + +/* SplitButton */ +.highcontrastSkin .mceSplitButtonDisabled .mceAction {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} + +.highcontrastSkin .mceSplitButton { border-collapse: collapse; margin: 2px; height: 2em; line-height: 2em;-webkit-focus-ring-color:none;outline:none;} +.highcontrastSkin .mceSplitButton td { display: table-cell; float: none; margin: 0; padding: 0; height: 2em;} +.highcontrastSkin .mceSplitButton tr { display: table-row; } +.highcontrastSkin table.mceSplitButton { display: table; } +.highcontrastSkin .mceSplitButton a.mceAction { padding: 5px 10px; display: block; height: 2em; line-height: 2em; overflow: hidden; border: 1px solid; border-right: 0; border-radius: 3px 0px 0px 3px; -moz-border-radius: 3px 0px 0px 3px; -webkit-border-radius: 3px 0px 0px 3px; -ms-border-radius: 3px 0px 0px 3px;} +.highcontrastSkin .mceSplitButton a.mceOpen { padding: 5px 4px; display: block; height: 2em; line-height: 2em; border: 1px solid; border-radius: 0px 3px 3px 0px; -moz-border-radius: 0px 3px 3px 0px; -webkit-border-radius: 0px 3px 3px 0px; -ms-border-radius: 0px 3px 3px 0px;} +.highcontrastSkin .mceSplitButton .mceVoiceLabel { height: 2em; vertical-align: center; line-height: 2em; } +.highcontrastSkin .mceSplitButton:focus a.mceAction, .highcontrastSkin .mceSplitButton:active a.mceAction { border-width: 5px; border-right-width: 1px; padding: 1px 10px 1px 6px;-webkit-focus-ring-color:none;outline:none;} +.highcontrastSkin .mceSplitButton:focus a.mceOpen, .highcontrastSkin .mceSplitButton:active a.mceOpen { border-width: 5px; border-left-width: 1px; padding: 1px 0px 1px 4px;-webkit-focus-ring-color:none;outline:none;} + +/* Menu */ +.highcontrastSkin .mceNoIcons span.mceIcon {width:0;} +.highcontrastSkin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid; } +.highcontrastSkin .mceMenu table {background:white; color: black} +.highcontrastSkin .mceNoIcons a .mceText {padding-left:10px} +.highcontrastSkin .mceMenu a, .highcontrastSkin .mceMenu span, .highcontrastSkin .mceMenu {display:block;background:white; color: black} +.highcontrastSkin .mceMenu td {height:2em} +.highcontrastSkin .mceMenu a {position:relative;padding:3px 0 4px 0; display: block;} +.highcontrastSkin .mceMenu .mceText {position:relative; display:block; cursor:default; margin:0; padding:0 25px 0 25px;} +.highcontrastSkin .mceMenu pre.mceText {font-family:Monospace} +.highcontrastSkin .mceMenu .mceIcon {position:absolute; top:0; left:0; width:26px;} +.highcontrastSkin td.mceMenuItemSeparator {border-top:1px solid; height:1px} +.highcontrastSkin .mceMenuItemTitle a {border:0; border-bottom:1px solid} +.highcontrastSkin .mceMenuItemTitle span.mceText {font-weight:bold; padding-left:4px} +.highcontrastSkin .mceNoIcons .mceMenuItemSelected span.mceText:before {content: "\2713\A0";} +.highcontrastSkin .mceMenu span.mceMenuLine {display:none} +.highcontrastSkin .mceMenuItemSub a .mceText:after {content: "\A0\25B8"} +.highcontrastSkin .mceMenuItem td, .highcontrastSkin .mceMenuItem th {line-height: normal} + +/* ColorSplitButton */ +.highcontrastSkin div.mceColorSplitMenu table {background:#FFF; border:1px solid; color: #000} +.highcontrastSkin .mceColorSplitMenu td {padding:2px} +.highcontrastSkin .mceColorSplitMenu a {display:block; width:16px; height:16px; overflow:hidden; color:#000; margin: 0; padding: 0;} +.highcontrastSkin .mceColorSplitMenu td.mceMoreColors {padding:1px 3px 1px 1px} +.highcontrastSkin .mceColorSplitMenu a.mceMoreColors {width:100%; height:auto; text-align:center; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; line-height:20px; border:1px solid #FFF} +.highcontrastSkin .mceColorSplitMenu a.mceMoreColors:hover {border:1px solid; background-color:#B6BDD2} +.highcontrastSkin a.mceMoreColors:hover {border:1px solid #0A246A; color: #000;} +.highcontrastSkin .mceColorPreview {display:none;} +.highcontrastSkin .mce_forecolor span.mceAction, .highcontrastSkin .mce_backcolor span.mceAction {height:17px;overflow:hidden} + +/* Progress,Resize */ +.highcontrastSkin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=50); background:#FFF} +.highcontrastSkin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(../default/img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px} + +/* Formats */ +.highcontrastSkin .mce_p span.mceText {} +.highcontrastSkin .mce_address span.mceText {font-style:italic} +.highcontrastSkin .mce_pre span.mceText {font-family:monospace} +.highcontrastSkin .mce_h1 span.mceText {font-weight:bolder; font-size: 2em} +.highcontrastSkin .mce_h2 span.mceText {font-weight:bolder; font-size: 1.5em} +.highcontrastSkin .mce_h3 span.mceText {font-weight:bolder; font-size: 1.17em} +.highcontrastSkin .mce_h4 span.mceText {font-weight:bolder; font-size: 1em} +.highcontrastSkin .mce_h5 span.mceText {font-weight:bolder; font-size: .83em} +.highcontrastSkin .mce_h6 span.mceText {font-weight:bolder; font-size: .75em} diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/content.css b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/content.css new file mode 100644 index 0000000..a1a8f9b --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/content.css @@ -0,0 +1,48 @@ +body, td, pre {color:#000; font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px; margin:8px;} +body {background:#FFF;} +body.mceForceColors {background:#FFF; color:#000;} +h1 {font-size: 2em} +h2 {font-size: 1.5em} +h3 {font-size: 1.17em} +h4 {font-size: 1em} +h5 {font-size: .83em} +h6 {font-size: .75em} +.mceItemTable, .mceItemTable td, .mceItemTable th, .mceItemTable caption, .mceItemVisualAid {border: 1px dashed #BBB;} +a.mceItemAnchor {display:inline-block; width:11px !important; height:11px !important; background:url(../default/img/items.gif) no-repeat 0 0;} +span.mceItemNbsp {background: #DDD} +td.mceSelected, th.mceSelected {background-color:#3399ff !important} +img {border:0;} +table, img, hr, .mceItemAnchor {cursor:default} +table td, table th {cursor:text} +ins {border-bottom:1px solid green; text-decoration: none; color:green} +del {color:red; text-decoration:line-through} +cite {border-bottom:1px dashed blue} +acronym {border-bottom:1px dotted #CCC; cursor:help} +abbr {border-bottom:1px dashed #CCC; cursor:help} + +/* IE */ +* html body { +scrollbar-3dlight-color:#F0F0EE; +scrollbar-arrow-color:#676662; +scrollbar-base-color:#F0F0EE; +scrollbar-darkshadow-color:#DDD; +scrollbar-face-color:#E0E0DD; +scrollbar-highlight-color:#F0F0EE; +scrollbar-shadow-color:#F0F0EE; +scrollbar-track-color:#F5F5F5; +} + +img:-moz-broken {-moz-force-broken-image-icon:1; width:24px; height:24px} +font[face=mceinline] {font-family:inherit !important} +*[contentEditable]:focus {outline:0} + +.mceItemMedia {border:1px dotted #cc0000; background-position:center; background-repeat:no-repeat; background-color:#ffffcc} +.mceItemShockWave {background-image:url(../../img/shockwave.gif)} +.mceItemFlash {background-image:url(../../img/flash.gif)} +.mceItemQuickTime {background-image:url(../../img/quicktime.gif)} +.mceItemWindowsMedia {background-image:url(../../img/windowsmedia.gif)} +.mceItemRealMedia {background-image:url(../../img/realmedia.gif)} +.mceItemVideo {background-image:url(../../img/video.gif)} +.mceItemAudio {background-image:url(../../img/video.gif)} +.mceItemIframe {background-image:url(../../img/iframe.gif)} +.mcePageBreak {display:block;border:0;width:100%;height:12px;border-top:1px dotted #ccc;margin-top:15px;background:#fff url(../../img/pagebreak.gif) no-repeat center top;} diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/dialog.css b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/dialog.css new file mode 100644 index 0000000..ec08772 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/dialog.css @@ -0,0 +1,117 @@ +/* Generic */ +body { +font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px; +scrollbar-3dlight-color:#F0F0EE; +scrollbar-arrow-color:#676662; +scrollbar-base-color:#F0F0EE; +scrollbar-darkshadow-color:#DDDDDD; +scrollbar-face-color:#E0E0DD; +scrollbar-highlight-color:#F0F0EE; +scrollbar-shadow-color:#F0F0EE; +scrollbar-track-color:#F5F5F5; +background:#F0F0EE; +padding:0; +margin:8px 8px 0 8px; +} + +html {background:#F0F0EE;} +td {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +textarea {resize:none;outline:none;} +a:link, a:visited {color:black;} +a:hover {color:#2B6FB6;} +.nowrap {white-space: nowrap} + +/* Forms */ +fieldset {margin:0; padding:4px; border:1px solid #919B9C; font-family:Verdana, Arial; font-size:10px;} +legend {color:#2B6FB6; font-weight:bold;} +label.msg {display:none;} +label.invalid {color:#EE0000; display:inline;} +input.invalid {border:1px solid #EE0000;} +input {background:#FFF; border:1px solid #CCC;} +input, select, textarea {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +input, select, textarea {border:1px solid #808080;} +input.radio {border:1px none #000000; background:transparent; vertical-align:middle;} +input.checkbox {border:1px none #000000; background:transparent; vertical-align:middle;} +.input_noborder {border:0;} + +/* Buttons */ +#insert, #cancel, input.button, .updateButton { +border:0; margin:0; padding:0; +font-weight:bold; +width:94px; height:26px; +background:url(../default/img/buttons.png) 0 -26px; +cursor:pointer; +padding-bottom:2px; +float:left; +} + +#insert {background:url(../default/img/buttons.png) 0 -52px} +#cancel {background:url(../default/img/buttons.png) 0 0; float:right} + +/* Browse */ +a.pickcolor, a.browse {text-decoration:none} +a.browse span {display:block; width:20px; height:18px; background:url(../../img/icons.gif) -860px 0; border:1px solid #FFF; margin-left:1px;} +.mceOldBoxModel a.browse span {width:22px; height:20px;} +a.browse:hover span {border:1px solid #0A246A; background-color:#B2BBD0;} +a.browse span.disabled {border:1px solid white; opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +a.browse:hover span.disabled {border:1px solid white; background-color:transparent;} +a.pickcolor span {display:block; width:20px; height:16px; background:url(../../img/icons.gif) -840px 0; margin-left:2px;} +.mceOldBoxModel a.pickcolor span {width:21px; height:17px;} +a.pickcolor:hover span {background-color:#B2BBD0;} +a.pickcolor:hover span.disabled {} + +/* Charmap */ +table.charmap {border:1px solid #AAA; text-align:center} +td.charmap, #charmap a {width:18px; height:18px; color:#000; border:1px solid #AAA; text-align:center; font-size:12px; vertical-align:middle; line-height: 18px;} +#charmap a {display:block; color:#000; text-decoration:none; border:0} +#charmap a:hover {background:#CCC;color:#2B6FB6} +#charmap #codeN {font-size:10px; font-family:Arial,Helvetica,sans-serif; text-align:center} +#charmap #codeV {font-size:40px; height:80px; border:1px solid #AAA; text-align:center} + +/* Source */ +.wordWrapCode {vertical-align:middle; border:1px none #000000; background:transparent;} +.mceActionPanel {margin-top:5px;} + +/* Tabs classes */ +.tabs {width:100%; height:18px; line-height:normal; background:url(../default/img/tabs.gif) repeat-x 0 -72px;} +.tabs ul {margin:0; padding:0; list-style:none;} +.tabs li {float:left; background:url(../default/img/tabs.gif) no-repeat 0 0; margin:0 2px 0 0; padding:0 0 0 10px; line-height:17px; height:18px; display:block;} +.tabs li.current {background:url(../default/img/tabs.gif) no-repeat 0 -18px; margin-right:2px;} +.tabs span {float:left; display:block; background:url(../default/img/tabs.gif) no-repeat right -36px; padding:0px 10px 0 0;} +.tabs .current span {background:url(../default/img/tabs.gif) no-repeat right -54px;} +.tabs a {text-decoration:none; font-family:Verdana, Arial; font-size:10px;} +.tabs a:link, .tabs a:visited, .tabs a:hover {color:black;} + +/* Panels */ +.panel_wrapper div.panel {display:none;} +.panel_wrapper div.current {display:block; width:100%; height:300px; overflow:visible;} +.panel_wrapper {border:1px solid #919B9C; border-top:0px; padding:10px; padding-top:5px; clear:both; background:white;} + +/* Columns */ +.column {float:left;} +.properties {width:100%;} +.properties .column1 {} +.properties .column2 {text-align:left;} + +/* Titles */ +h1, h2, h3, h4 {color:#2B6FB6; margin:0; padding:0; padding-top:5px;} +h3 {font-size:14px;} +.title {font-size:12px; font-weight:bold; color:#2B6FB6;} + +/* Dialog specific */ +#link .panel_wrapper, #link div.current {height:125px;} +#image .panel_wrapper, #image div.current {height:200px;} +#plugintable thead {font-weight:bold; background:#DDD;} +#plugintable, #about #plugintable td {border:1px solid #919B9C;} +#plugintable {width:96%; margin-top:10px;} +#pluginscontainer {height:290px; overflow:auto;} +#colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;} +#colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;} +#colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;} +#colorpicker #light div {overflow:hidden;} +#colorpicker #previewblock {float:right; padding-left:10px; height:20px;} +#colorpicker .panel_wrapper div.current {height:175px;} +#colorpicker #namedcolors {width:150px;} +#colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;} +#colorpicker #colornamecontainer {margin-top:5px;} +#colorpicker #picker_panel fieldset {margin:auto;width:325px;} diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..13a5cb03097c004f7b37658654a9250748cf073c GIT binary patch literal 2766 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 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png new file mode 100644 index 0000000000000000000000000000000000000000..7fc57f2bc2d63a3ad6fbf98b663f336539f011ec GIT binary patch literal 651 zcmV;60(AX}P)<h;3K|Lk000e1NJLTq003A3002S=0{{R3<ObpU00009a7bBm000XU z000XU0RWnu7ytkO%uq~JMF0Q*ySuvp002`{Q*w5EkCBv-nWUJXshgs#pQf*(sj{Z5 zwW+VTt+TtZw!XBv!MD7`yTHb~z{kA7$iBnLzr@SI#>~UV&BV#i#>&vh%+bls)637) z|EoX$u}%N7Q2(@4|Fu{Dw_E?XUjMpc|GQ=Xy=niyZU4b?|HF3w#e4t9fd9#a|I3O0 z&5r-ub^qLY|J{H8--Q3*iT~k_|KpSY<e2~Eo&V>d|L3Cr=%)YbtN-h;|LwH@@45f* zzW?&W|MbWI_00eO|F&Wq@&Et;0(4SNQveU<EYPU{00CD?L_t(o!|j!^Y63wJhUf0E z38<tH3j+ZS_yTH?=eNik1Wc9ICSB6xJa_MOcK7_3U3YV-=7U6-aX#c{;V+*cqpGS# z)W_`cR3EBAdssG*xmwL{#Aa_#*EW3U5ueoR6e*^61M#6ptS_5bv3<seA{KGB_)7!C zJWmx*)&D6F^E^3<2~A)W*LixzV^79od2S+371wH2$BJJK#E17(Q-Q^M8&gd)2#lgJ zdwcwBv(!JJ6+b{~%}o>qL%#keZfRNo2=jQw7k!se7X^9V1j4iLUp68Z@t=r4G(h~O zNf#5nT>kpvo%+~iMX{n4jABdM%#4?wj5qS!L>wXh2IPsmmi~l5Z*gRt`Huw!S{nag zygxXo!EY-rAUF!s;uNGb)obDTa;U{!asI0iv51EeU)nfId<Wdd14Pla@emnr<W-3H lf5f2{cf>~s{&Jwj9nO>J@7?&+<Hi60002ovPDHLkV1hmPRc!zO literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png new file mode 100644 index 0000000000000000000000000000000000000000..c0dcc6cac2003f7405fff3ea5df7bcf276243596 GIT binary patch literal 2084 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 O0000<MNUMnLSTX~QySp_ literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui.css b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui.css new file mode 100644 index 0000000..0916c34 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui.css @@ -0,0 +1,217 @@ +/* Reset */ +.o2k7Skin table, .o2k7Skin tbody, .o2k7Skin a, .o2k7Skin img, .o2k7Skin tr, .o2k7Skin div, .o2k7Skin td, .o2k7Skin iframe, .o2k7Skin span, .o2k7Skin *, .o2k7Skin .mceText {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000; vertical-align:baseline; width:auto; border-collapse:separate; text-align:left} +.o2k7Skin a:hover, .o2k7Skin a:link, .o2k7Skin a:visited, .o2k7Skin a:active {text-decoration:none; font-weight:normal; cursor:default; color:#000} +.o2k7Skin table td {vertical-align:middle} + +/* Containers */ +.o2k7Skin table {background:transparent} +.o2k7Skin iframe {display:block;} +.o2k7Skin .mceToolbar {height:26px} + +/* External */ +.o2k7Skin .mceExternalToolbar {position:absolute; border:1px solid #ABC6DD; border-bottom:0; display:none} +.o2k7Skin .mceExternalToolbar td.mceToolbar {padding-right:13px;} +.o2k7Skin .mceExternalClose {position:absolute; top:3px; right:3px; width:7px; height:7px; background:url(../../img/icons.gif) -820px 0} + +/* Layout */ +.o2k7Skin table.mceLayout {border:0; border-left:1px solid #ABC6DD; border-right:1px solid #ABC6DD} +.o2k7Skin table.mceLayout tr.mceFirst td {border-top:1px solid #ABC6DD} +.o2k7Skin table.mceLayout tr.mceLast td {border-bottom:1px solid #ABC6DD} +.o2k7Skin table.mceToolbar, .o2k7Skin tr.mceFirst .mceToolbar tr td, .o2k7Skin tr.mceLast .mceToolbar tr td {border:0; margin:0; padding:0} +.o2k7Skin .mceIframeContainer {border-top:1px solid #ABC6DD; border-bottom:1px solid #ABC6DD} +.o2k7Skin td.mceToolbar{background:#E5EFFD} +.o2k7Skin .mceStatusbar {background:#E5EFFD; display:block; font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:9pt; line-height:16px; overflow:visible; color:#000; height:20px} +.o2k7Skin .mceStatusbar div {float:left; padding:2px} +.o2k7Skin .mceStatusbar a.mceResize {display:block; float:right; background:url(../../img/icons.gif) -800px 0; width:20px; height:20px; cursor:se-resize; outline:0} +.o2k7Skin .mceStatusbar a:hover {text-decoration:underline} +.o2k7Skin table.mceToolbar {margin-left:3px} +.o2k7Skin .mceToolbar .mceToolbarStart span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px; margin-left:3px;} +.o2k7Skin .mceToolbar td.mceFirst span {margin:0} +.o2k7Skin .mceToolbar .mceToolbarEnd span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px} +.o2k7Skin .mceToolbar .mceToolbarEndListBox span, .o2k7Skin .mceToolbar .mceToolbarStartListBox span {display:none} +.o2k7Skin span.mceIcon, .o2k7Skin img.mceIcon {display:block; width:20px; height:20px} +.o2k7Skin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px} +.o2k7Skin td.mceCenter {text-align:center;} +.o2k7Skin td.mceCenter table {margin:0 auto; text-align:left;} +.o2k7Skin td.mceRight table {margin:0 0 0 auto;} + +/* Button */ +.o2k7Skin .mceButton {display:block; background:url(img/button_bg.png); width:22px; height:22px} +.o2k7Skin a.mceButton span, .o2k7Skin a.mceButton img {margin-left:1px} +.o2k7Skin .mceOldBoxModel a.mceButton span, .o2k7Skin .mceOldBoxModel a.mceButton img {margin:0 0 0 1px} +.o2k7Skin a.mceButtonEnabled:hover {background-color:#B2BBD0; background-position:0 -22px} +.o2k7Skin a.mceButtonActive, .o2k7Skin a.mceButtonSelected {background-position:0 -44px} +.o2k7Skin .mceButtonDisabled .mceIcon {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +.o2k7Skin .mceButtonLabeled {width:auto} +.o2k7Skin .mceButtonLabeled span.mceIcon {float:left} +.o2k7Skin span.mceButtonLabel {display:block; font-size:10px; padding:4px 6px 0 22px; font-family:Tahoma,Verdana,Arial,Helvetica} +.o2k7Skin .mceButtonDisabled .mceButtonLabel {color:#888} + +/* Separator */ +.o2k7Skin .mceSeparator {display:block; background:url(img/button_bg.png) -22px 0; width:5px; height:22px} + +/* ListBox */ +.o2k7Skin .mceListBox {padding-left: 3px} +.o2k7Skin .mceListBox, .o2k7Skin .mceListBox a {display:block} +.o2k7Skin .mceListBox .mceText {padding-left:4px; text-align:left; width:70px; border:1px solid #b3c7e1; border-right:0; background:#eaf2fb; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; height:20px; line-height:20px; overflow:hidden} +.o2k7Skin .mceListBox .mceOpen {width:14px; height:22px; background:url(img/button_bg.png) -66px 0} +.o2k7Skin table.mceListBoxEnabled:hover .mceText, .o2k7Skin .mceListBoxHover .mceText, .o2k7Skin .mceListBoxSelected .mceText {background:#FFF} +.o2k7Skin table.mceListBoxEnabled:hover .mceOpen, .o2k7Skin .mceListBoxHover .mceOpen, .o2k7Skin .mceListBoxSelected .mceOpen {background-position:-66px -22px} +.o2k7Skin .mceListBoxDisabled .mceText {color:gray} +.o2k7Skin .mceListBoxMenu {overflow:auto; overflow-x:hidden; margin-left:3px} +.o2k7Skin .mceOldBoxModel .mceListBox .mceText {height:22px} +.o2k7Skin select.mceListBox {font-family:Tahoma,Verdana,Arial,Helvetica; font-size:12px; border:1px solid #b3c7e1; background:#FFF;} + +/* SplitButton */ +.o2k7Skin .mceSplitButton, .o2k7Skin .mceSplitButton a, .o2k7Skin .mceSplitButton span {display:block; height:22px; direction:ltr} +.o2k7Skin .mceSplitButton {background:url(img/button_bg.png)} +.o2k7Skin .mceSplitButton a.mceAction {width:22px} +.o2k7Skin .mceSplitButton span.mceAction {width:22px; background-image:url(../../img/icons.gif)} +.o2k7Skin .mceSplitButton a.mceOpen {width:10px; background:url(img/button_bg.png) -44px 0} +.o2k7Skin .mceSplitButton span.mceOpen {display:none} +.o2k7Skin table.mceSplitButtonEnabled:hover a.mceAction, .o2k7Skin .mceSplitButtonHover a.mceAction, .o2k7Skin .mceSplitButtonSelected {background:url(img/button_bg.png) 0 -22px} +.o2k7Skin table.mceSplitButtonEnabled:hover a.mceOpen, .o2k7Skin .mceSplitButtonHover a.mceOpen, .o2k7Skin .mceSplitButtonSelected a.mceOpen {background-position:-44px -44px} +.o2k7Skin .mceSplitButtonDisabled .mceAction {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +.o2k7Skin .mceSplitButtonActive {background-position:0 -44px} + +/* ColorSplitButton */ +.o2k7Skin div.mceColorSplitMenu table {background:#FFF; border:1px solid gray} +.o2k7Skin .mceColorSplitMenu td {padding:2px} +.o2k7Skin .mceColorSplitMenu a {display:block; width:9px; height:9px; overflow:hidden; border:1px solid #808080} +.o2k7Skin .mceColorSplitMenu td.mceMoreColors {padding:1px 3px 1px 1px} +.o2k7Skin .mceColorSplitMenu a.mceMoreColors {width:100%; height:auto; text-align:center; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; line-height:20px; border:1px solid #FFF} +.o2k7Skin .mceColorSplitMenu a.mceMoreColors:hover {border:1px solid #0A246A; background-color:#B6BDD2} +.o2k7Skin a.mceMoreColors:hover {border:1px solid #0A246A} +.o2k7Skin .mceColorPreview {margin-left:2px; width:16px; height:4px; overflow:hidden; background:#9a9b9a;overflow:hidden} +.o2k7Skin .mce_forecolor span.mceAction, .o2k7Skin .mce_backcolor span.mceAction {height:15px;overflow:hidden} + +/* Menu */ +.o2k7Skin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #ABC6DD} +.o2k7Skin .mceNoIcons span.mceIcon {width:0;} +.o2k7Skin .mceNoIcons a .mceText {padding-left:10px} +.o2k7Skin .mceMenu table {background:#FFF} +.o2k7Skin .mceMenu a, .o2k7Skin .mceMenu span, .o2k7Skin .mceMenu {display:block} +.o2k7Skin .mceMenu td {height:20px} +.o2k7Skin .mceMenu a {position:relative;padding:3px 0 4px 0} +.o2k7Skin .mceMenu .mceText {position:relative; display:block; font-family:Tahoma,Verdana,Arial,Helvetica; color:#000; cursor:default; margin:0; padding:0 25px 0 25px; display:block} +.o2k7Skin .mceMenu span.mceText, .o2k7Skin .mceMenu .mcePreview {font-size:11px} +.o2k7Skin .mceMenu pre.mceText {font-family:Monospace} +.o2k7Skin .mceMenu .mceIcon {position:absolute; top:0; left:0; width:22px;} +.o2k7Skin .mceMenu .mceMenuItemEnabled a:hover, .o2k7Skin .mceMenu .mceMenuItemActive {background-color:#dbecf3} +.o2k7Skin td.mceMenuItemSeparator {background:#DDD; height:1px} +.o2k7Skin .mceMenuItemTitle a {border:0; background:#E5EFFD; border-bottom:1px solid #ABC6DD} +.o2k7Skin .mceMenuItemTitle span.mceText {color:#000; font-weight:bold; padding-left:4px} +.o2k7Skin .mceMenuItemDisabled .mceText {color:#888} +.o2k7Skin .mceMenuItemSelected .mceIcon {background:url(../default/img/menu_check.gif)} +.o2k7Skin .mceNoIcons .mceMenuItemSelected a {background:url(../default/img/menu_arrow.gif) no-repeat -6px center} +.o2k7Skin .mceMenu span.mceMenuLine {display:none} +.o2k7Skin .mceMenuItemSub a {background:url(../default/img/menu_arrow.gif) no-repeat top right;} +.o2k7Skin .mceMenuItem td, .o2k7Skin .mceMenuItem th {line-height: normal} + +/* Progress,Resize */ +.o2k7Skin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=50); background:#FFF} +.o2k7Skin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(../default/img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px} + +/* Formats */ +.o2k7Skin .mce_formatPreview a {font-size:10px} +.o2k7Skin .mce_p span.mceText {} +.o2k7Skin .mce_address span.mceText {font-style:italic} +.o2k7Skin .mce_pre span.mceText {font-family:monospace} +.o2k7Skin .mce_h1 span.mceText {font-weight:bolder; font-size: 2em} +.o2k7Skin .mce_h2 span.mceText {font-weight:bolder; font-size: 1.5em} +.o2k7Skin .mce_h3 span.mceText {font-weight:bolder; font-size: 1.17em} +.o2k7Skin .mce_h4 span.mceText {font-weight:bolder; font-size: 1em} +.o2k7Skin .mce_h5 span.mceText {font-weight:bolder; font-size: .83em} +.o2k7Skin .mce_h6 span.mceText {font-weight:bolder; font-size: .75em} + +/* Theme */ +.o2k7Skin span.mce_bold {background-position:0 0} +.o2k7Skin span.mce_italic {background-position:-60px 0} +.o2k7Skin span.mce_underline {background-position:-140px 0} +.o2k7Skin span.mce_strikethrough {background-position:-120px 0} +.o2k7Skin span.mce_undo {background-position:-160px 0} +.o2k7Skin span.mce_redo {background-position:-100px 0} +.o2k7Skin span.mce_cleanup {background-position:-40px 0} +.o2k7Skin span.mce_bullist {background-position:-20px 0} +.o2k7Skin span.mce_numlist {background-position:-80px 0} +.o2k7Skin span.mce_justifyleft {background-position:-460px 0} +.o2k7Skin span.mce_justifyright {background-position:-480px 0} +.o2k7Skin span.mce_justifycenter {background-position:-420px 0} +.o2k7Skin span.mce_justifyfull {background-position:-440px 0} +.o2k7Skin span.mce_anchor {background-position:-200px 0} +.o2k7Skin span.mce_indent {background-position:-400px 0} +.o2k7Skin span.mce_outdent {background-position:-540px 0} +.o2k7Skin span.mce_link {background-position:-500px 0} +.o2k7Skin span.mce_unlink {background-position:-640px 0} +.o2k7Skin span.mce_sub {background-position:-600px 0} +.o2k7Skin span.mce_sup {background-position:-620px 0} +.o2k7Skin span.mce_removeformat {background-position:-580px 0} +.o2k7Skin span.mce_newdocument {background-position:-520px 0} +.o2k7Skin span.mce_image {background-position:-380px 0} +.o2k7Skin span.mce_help {background-position:-340px 0} +.o2k7Skin span.mce_code {background-position:-260px 0} +.o2k7Skin span.mce_hr {background-position:-360px 0} +.o2k7Skin span.mce_visualaid {background-position:-660px 0} +.o2k7Skin span.mce_charmap {background-position:-240px 0} +.o2k7Skin span.mce_paste {background-position:-560px 0} +.o2k7Skin span.mce_copy {background-position:-700px 0} +.o2k7Skin span.mce_cut {background-position:-680px 0} +.o2k7Skin span.mce_blockquote {background-position:-220px 0} +.o2k7Skin .mce_forecolor span.mceAction {background-position:-720px 0} +.o2k7Skin .mce_backcolor span.mceAction {background-position:-760px 0} +.o2k7Skin span.mce_forecolorpicker {background-position:-720px 0} +.o2k7Skin span.mce_backcolorpicker {background-position:-760px 0} + +/* Plugins */ +.o2k7Skin span.mce_advhr {background-position:-0px -20px} +.o2k7Skin span.mce_ltr {background-position:-20px -20px} +.o2k7Skin span.mce_rtl {background-position:-40px -20px} +.o2k7Skin span.mce_emotions {background-position:-60px -20px} +.o2k7Skin span.mce_fullpage {background-position:-80px -20px} +.o2k7Skin span.mce_fullscreen {background-position:-100px -20px} +.o2k7Skin span.mce_iespell {background-position:-120px -20px} +.o2k7Skin span.mce_insertdate {background-position:-140px -20px} +.o2k7Skin span.mce_inserttime {background-position:-160px -20px} +.o2k7Skin span.mce_absolute {background-position:-180px -20px} +.o2k7Skin span.mce_backward {background-position:-200px -20px} +.o2k7Skin span.mce_forward {background-position:-220px -20px} +.o2k7Skin span.mce_insert_layer {background-position:-240px -20px} +.o2k7Skin span.mce_insertlayer {background-position:-260px -20px} +.o2k7Skin span.mce_movebackward {background-position:-280px -20px} +.o2k7Skin span.mce_moveforward {background-position:-300px -20px} +.o2k7Skin span.mce_media {background-position:-320px -20px} +.o2k7Skin span.mce_nonbreaking {background-position:-340px -20px} +.o2k7Skin span.mce_pastetext {background-position:-360px -20px} +.o2k7Skin span.mce_pasteword {background-position:-380px -20px} +.o2k7Skin span.mce_selectall {background-position:-400px -20px} +.o2k7Skin span.mce_preview {background-position:-420px -20px} +.o2k7Skin span.mce_print {background-position:-440px -20px} +.o2k7Skin span.mce_cancel {background-position:-460px -20px} +.o2k7Skin span.mce_save {background-position:-480px -20px} +.o2k7Skin span.mce_replace {background-position:-500px -20px} +.o2k7Skin span.mce_search {background-position:-520px -20px} +.o2k7Skin span.mce_styleprops {background-position:-560px -20px} +.o2k7Skin span.mce_table {background-position:-580px -20px} +.o2k7Skin span.mce_cell_props {background-position:-600px -20px} +.o2k7Skin span.mce_delete_table {background-position:-620px -20px} +.o2k7Skin span.mce_delete_col {background-position:-640px -20px} +.o2k7Skin span.mce_delete_row {background-position:-660px -20px} +.o2k7Skin span.mce_col_after {background-position:-680px -20px} +.o2k7Skin span.mce_col_before {background-position:-700px -20px} +.o2k7Skin span.mce_row_after {background-position:-720px -20px} +.o2k7Skin span.mce_row_before {background-position:-740px -20px} +.o2k7Skin span.mce_merge_cells {background-position:-760px -20px} +.o2k7Skin span.mce_table_props {background-position:-980px -20px} +.o2k7Skin span.mce_row_props {background-position:-780px -20px} +.o2k7Skin span.mce_split_cells {background-position:-800px -20px} +.o2k7Skin span.mce_template {background-position:-820px -20px} +.o2k7Skin span.mce_visualchars {background-position:-840px -20px} +.o2k7Skin span.mce_abbr {background-position:-860px -20px} +.o2k7Skin span.mce_acronym {background-position:-880px -20px} +.o2k7Skin span.mce_attribs {background-position:-900px -20px} +.o2k7Skin span.mce_cite {background-position:-920px -20px} +.o2k7Skin span.mce_del {background-position:-940px -20px} +.o2k7Skin span.mce_ins {background-position:-960px -20px} +.o2k7Skin span.mce_pagebreak {background-position:0 -40px} +.o2k7Skin span.mce_restoredraft {background-position:-20px -40px} +.o2k7Skin span.mce_spellchecker {background-position:-540px -20px} diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui_black.css b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui_black.css new file mode 100644 index 0000000..50c9b76 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui_black.css @@ -0,0 +1,8 @@ +/* Black */ +.o2k7SkinBlack .mceToolbar .mceToolbarStart span, .o2k7SkinBlack .mceToolbar .mceToolbarEnd span, .o2k7SkinBlack .mceButton, .o2k7SkinBlack .mceSplitButton, .o2k7SkinBlack .mceSeparator, .o2k7SkinBlack .mceSplitButton a.mceOpen, .o2k7SkinBlack .mceListBox a.mceOpen {background-image:url(img/button_bg_black.png)} +.o2k7SkinBlack td.mceToolbar, .o2k7SkinBlack td.mceStatusbar, .o2k7SkinBlack .mceMenuItemTitle a, .o2k7SkinBlack .mceMenuItemTitle span.mceText, .o2k7SkinBlack .mceStatusbar div, .o2k7SkinBlack .mceStatusbar span, .o2k7SkinBlack .mceStatusbar a {background:#535353; color:#FFF} +.o2k7SkinBlack table.mceListBoxEnabled .mceText, o2k7SkinBlack .mceListBox .mceText {background:#FFF; border:1px solid #CBCFD4; border-bottom-color:#989FA9; border-right:0} +.o2k7SkinBlack table.mceListBoxEnabled:hover .mceText, .o2k7SkinBlack .mceListBoxHover .mceText, .o2k7SkinBlack .mceListBoxSelected .mceText {background:#FFF; border:1px solid #FFBD69; border-right:0} +.o2k7SkinBlack .mceExternalToolbar, .o2k7SkinBlack .mceListBox .mceText, .o2k7SkinBlack div.mceMenu, .o2k7SkinBlack table.mceLayout, .o2k7SkinBlack .mceMenuItemTitle a, .o2k7SkinBlack table.mceLayout tr.mceFirst td, .o2k7SkinBlack table.mceLayout, .o2k7SkinBlack .mceMenuItemTitle a, .o2k7SkinBlack table.mceLayout tr.mceLast td, .o2k7SkinBlack .mceIframeContainer {border-color: #535353;} +.o2k7SkinBlack table.mceSplitButtonEnabled:hover a.mceAction, .o2k7SkinBlack .mceSplitButtonHover a.mceAction, .o2k7SkinBlack .mceSplitButtonSelected {background-image:url(img/button_bg_black.png)} +.o2k7SkinBlack .mceMenu .mceMenuItemEnabled a:hover, .o2k7SkinBlack .mceMenu .mceMenuItemActive {background-color:#FFE7A1} \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css new file mode 100644 index 0000000..960a8e4 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css @@ -0,0 +1,5 @@ +/* Silver */ +.o2k7SkinSilver .mceToolbar .mceToolbarStart span, .o2k7SkinSilver .mceButton, .o2k7SkinSilver .mceSplitButton, .o2k7SkinSilver .mceSeparator, .o2k7SkinSilver .mceSplitButton a.mceOpen, .o2k7SkinSilver .mceListBox a.mceOpen {background-image:url(img/button_bg_silver.png)} +.o2k7SkinSilver td.mceToolbar, .o2k7SkinSilver td.mceStatusbar, .o2k7SkinSilver .mceMenuItemTitle a {background:#eee} +.o2k7SkinSilver .mceListBox .mceText {background:#FFF} +.o2k7SkinSilver .mceExternalToolbar, .o2k7SkinSilver .mceListBox .mceText, .o2k7SkinSilver div.mceMenu, .o2k7SkinSilver table.mceLayout, .o2k7SkinSilver .mceMenuItemTitle a, .o2k7SkinSilver table.mceLayout tr.mceFirst td, .o2k7SkinSilver table.mceLayout, .o2k7SkinSilver .mceMenuItemTitle a, .o2k7SkinSilver table.mceLayout tr.mceLast td, .o2k7SkinSilver .mceIframeContainer {border-color: #bbb} diff --git a/src/core/static/js/tiny_mce/themes/advanced/source_editor.htm b/src/core/static/js/tiny_mce/themes/advanced/source_editor.htm new file mode 100644 index 0000000..3c6d658 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/advanced/source_editor.htm @@ -0,0 +1,25 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.code_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/source_editor.js"></script> +</head> +<body onresize="resizeInputs();" style="display:none; overflow:hidden;"> + <form name="source" onsubmit="saveContent();return false;" action="#"> + <div style="float: left" class="title"><label for="htmlSource">{#advanced_dlg.code_title}</label></div> + + <div id="wrapline" style="float: right"> + <input type="checkbox" name="wraped" id="wraped" onclick="toggleWordWrap(this);" class="wordWrapCode" /><label for="wraped">{#advanced_dlg.code_wordwrap}</label> + </div> + + <br style="clear: both" /> + + <textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,monospace; font-size: 12px;" dir="ltr" wrap="off" class="mceFocus"></textarea> + + <div class="mceActionPanel"> + <input type="submit" role="button" name="insert" value="{#update}" id="insert" /> + <input type="button" role="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" /> + </div> + </form> +</body> +</html> diff --git a/src/core/static/js/tiny_mce/themes/simple/editor_template.js b/src/core/static/js/tiny_mce/themes/simple/editor_template.js new file mode 100644 index 0000000..4b3209c --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/simple/editor_template.js @@ -0,0 +1 @@ +(function(){var a=tinymce.DOM;tinymce.ThemeManager.requireLangPack("simple");tinymce.create("tinymce.themes.SimpleTheme",{init:function(c,d){var e=this,b=["Bold","Italic","Underline","Strikethrough","InsertUnorderedList","InsertOrderedList"],f=c.settings;e.editor=c;c.contentCSS.push(d+"/skins/"+f.skin+"/content.css");c.onInit.add(function(){c.onNodeChange.add(function(h,g){tinymce.each(b,function(i){g.get(i.toLowerCase()).setActive(h.queryCommandState(i))})})});a.loadCSS((f.editor_css?c.documentBaseURI.toAbsolute(f.editor_css):"")||d+"/skins/"+f.skin+"/ui.css")},renderUI:function(h){var e=this,i=h.targetNode,b,c,d=e.editor,f=d.controlManager,g;i=a.insertAfter(a.create("span",{id:d.id+"_container","class":"mceEditor "+d.settings.skin+"SimpleSkin"}),i);i=g=a.add(i,"table",{cellPadding:0,cellSpacing:0,"class":"mceLayout"});i=c=a.add(i,"tbody");i=a.add(c,"tr");i=b=a.add(a.add(i,"td"),"div",{"class":"mceIframeContainer"});i=a.add(a.add(c,"tr",{"class":"last"}),"td",{"class":"mceToolbar mceLast",align:"center"});c=e.toolbar=f.createToolbar("tools1");c.add(f.createButton("bold",{title:"simple.bold_desc",cmd:"Bold"}));c.add(f.createButton("italic",{title:"simple.italic_desc",cmd:"Italic"}));c.add(f.createButton("underline",{title:"simple.underline_desc",cmd:"Underline"}));c.add(f.createButton("strikethrough",{title:"simple.striketrough_desc",cmd:"Strikethrough"}));c.add(f.createSeparator());c.add(f.createButton("undo",{title:"simple.undo_desc",cmd:"Undo"}));c.add(f.createButton("redo",{title:"simple.redo_desc",cmd:"Redo"}));c.add(f.createSeparator());c.add(f.createButton("cleanup",{title:"simple.cleanup_desc",cmd:"mceCleanup"}));c.add(f.createSeparator());c.add(f.createButton("insertunorderedlist",{title:"simple.bullist_desc",cmd:"InsertUnorderedList"}));c.add(f.createButton("insertorderedlist",{title:"simple.numlist_desc",cmd:"InsertOrderedList"}));c.renderTo(i);return{iframeContainer:b,editorContainer:d.id+"_container",sizeContainer:g,deltaHeight:-20}},getInfo:function(){return{longname:"Simple theme",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.ThemeManager.add("simple",tinymce.themes.SimpleTheme)})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/simple/editor_template_src.js b/src/core/static/js/tiny_mce/themes/simple/editor_template_src.js new file mode 100644 index 0000000..01ce87c --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/simple/editor_template_src.js @@ -0,0 +1,84 @@ +/** + * editor_template_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var DOM = tinymce.DOM; + + // Tell it to load theme specific language pack(s) + tinymce.ThemeManager.requireLangPack('simple'); + + tinymce.create('tinymce.themes.SimpleTheme', { + init : function(ed, url) { + var t = this, states = ['Bold', 'Italic', 'Underline', 'Strikethrough', 'InsertUnorderedList', 'InsertOrderedList'], s = ed.settings; + + t.editor = ed; + ed.contentCSS.push(url + "/skins/" + s.skin + "/content.css"); + + ed.onInit.add(function() { + ed.onNodeChange.add(function(ed, cm) { + tinymce.each(states, function(c) { + cm.get(c.toLowerCase()).setActive(ed.queryCommandState(c)); + }); + }); + }); + + DOM.loadCSS((s.editor_css ? ed.documentBaseURI.toAbsolute(s.editor_css) : '') || url + "/skins/" + s.skin + "/ui.css"); + }, + + renderUI : function(o) { + var t = this, n = o.targetNode, ic, tb, ed = t.editor, cf = ed.controlManager, sc; + + n = DOM.insertAfter(DOM.create('span', {id : ed.id + '_container', 'class' : 'mceEditor ' + ed.settings.skin + 'SimpleSkin'}), n); + n = sc = DOM.add(n, 'table', {cellPadding : 0, cellSpacing : 0, 'class' : 'mceLayout'}); + n = tb = DOM.add(n, 'tbody'); + + // Create iframe container + n = DOM.add(tb, 'tr'); + n = ic = DOM.add(DOM.add(n, 'td'), 'div', {'class' : 'mceIframeContainer'}); + + // Create toolbar container + n = DOM.add(DOM.add(tb, 'tr', {'class' : 'last'}), 'td', {'class' : 'mceToolbar mceLast', align : 'center'}); + + // Create toolbar + tb = t.toolbar = cf.createToolbar("tools1"); + tb.add(cf.createButton('bold', {title : 'simple.bold_desc', cmd : 'Bold'})); + tb.add(cf.createButton('italic', {title : 'simple.italic_desc', cmd : 'Italic'})); + tb.add(cf.createButton('underline', {title : 'simple.underline_desc', cmd : 'Underline'})); + tb.add(cf.createButton('strikethrough', {title : 'simple.striketrough_desc', cmd : 'Strikethrough'})); + tb.add(cf.createSeparator()); + tb.add(cf.createButton('undo', {title : 'simple.undo_desc', cmd : 'Undo'})); + tb.add(cf.createButton('redo', {title : 'simple.redo_desc', cmd : 'Redo'})); + tb.add(cf.createSeparator()); + tb.add(cf.createButton('cleanup', {title : 'simple.cleanup_desc', cmd : 'mceCleanup'})); + tb.add(cf.createSeparator()); + tb.add(cf.createButton('insertunorderedlist', {title : 'simple.bullist_desc', cmd : 'InsertUnorderedList'})); + tb.add(cf.createButton('insertorderedlist', {title : 'simple.numlist_desc', cmd : 'InsertOrderedList'})); + tb.renderTo(n); + + return { + iframeContainer : ic, + editorContainer : ed.id + '_container', + sizeContainer : sc, + deltaHeight : -20 + }; + }, + + getInfo : function() { + return { + longname : 'Simple theme', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + version : tinymce.majorVersion + "." + tinymce.minorVersion + } + } + }); + + tinymce.ThemeManager.add('simple', tinymce.themes.SimpleTheme); +})(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/simple/img/icons.gif b/src/core/static/js/tiny_mce/themes/simple/img/icons.gif new file mode 100644 index 0000000000000000000000000000000000000000..6fcbcb5dedf16a5fa1d15c2aa127bceb612f1e71 GIT binary patch literal 806 zcmZ?wbhEHbJi#Es@KuxH{{08bHy>kQU|4+kcV*u?6Yu2z|Nk2X_I-c9E~4fBsnb_x z&7Ngzq1inB@Woqi-rnfiGF7y<BJ%goW0A3G&CP97J93+rew?^?=aC%~&u<9q>w9zM z^p;~=3MY4TT)2AY!iC=7fBwej_wPS(UDm1P!}|}9?`#au+qhx#R?Fl=KuakHia%Lc z85lGfbU;Rd{N%v)|G<<24;`ug6HAIt=2*?Yu%d)ZG@><(acbwmDSj%f4MMZ#%vkt3 z%+g~)i<pR3VyF7n8#Z$JA<O@`mzEZZI~9w$$|__BGb*!0O9%_{aQAqM=SM3kP4|vm z(BRE1&gaoJFMyGSaitRjFE7_TKF--n%yZZ6cH(2+zszk#Ph`ZR>8kP^LLB_(WJHBo z)4eilyozQ8a&qqSt%<6xpa0;xA7k;M?mchbzI*>+`RnL~M?L!{MDwZt;o_B2<MUBS zf8W6@vUbsfBIEWxz1)=!e>F2$0=pQSpQ!u@RcUGT{(44KaY91N#ws_nDH9G%Qf=ZF z5o_THWH`G~`GwyilS^z$ZvV~I`dh4Lx_8c>?R@8gr-07UIgFjp0y#A&c{B)cE>2kS zL5I1;i$zoEA)6qV`HGJvVWE!{8MZ6ST|PC}d%K<xbI{vYcTaC$e}8|&bH2siMjBT& z{xP(Dc#_6(b?bhX$PZ!_9Bz&>i<?4}%fuUm8II^=2wdP1))w7xa^j`QZxmxvJKt#D zxH;qT)&eDCABP7k(~{;)Toy6)>d7{KiD{l18xziSGKuWtj9AkWy-*`}#c~0`Lrjq> z-;O-o=3A#@&dst%_SasuJq0xZW;OwR3vM!diY%Es?;J~Pp}LYununP(i|XxU>#u=* zSvNC^0?cJ=S?=UK4&2DdcCO^BsHxjWc4vR-Z64x&8r#>V9!<LDaqw)tCXZP-hw94E x+X50U2O7f@HcobM>JMd4O!Z*d@mNrgX=jUy;0|T>ZntHjDU$=-I8y`|tN~Y<KXd>9 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/simple/langs/de.js b/src/core/static/js/tiny_mce/themes/simple/langs/de.js new file mode 100755 index 0000000..59bf788 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/simple/langs/de.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.simple',{"cleanup_desc":"Quellcode aufr\u00e4umen","redo_desc":"Wiederholen (Strg+Y)","undo_desc":"R\u00fcckg\u00e4ngig (Strg+Z)","numlist_desc":"Nummerierung","bullist_desc":"Aufz\u00e4hlung","striketrough_desc":"Durchgestrichen","underline_desc":"Unterstrichen (Strg+U)","italic_desc":"Kursiv (Strg+I)","bold_desc":"Fett (Strg+B)"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/simple/langs/en.js b/src/core/static/js/tiny_mce/themes/simple/langs/en.js new file mode 100755 index 0000000..088ed0f --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/simple/langs/en.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.simple',{"cleanup_desc":"Cleanup Messy Code","redo_desc":"Redo (Ctrl+Y)","undo_desc":"Undo (Ctrl+Z)","numlist_desc":"Insert/Remove Numbered List","bullist_desc":"Insert/Remove Bulleted List","striketrough_desc":"Strikethrough","underline_desc":"Underline (Ctrl+U)","italic_desc":"Italic (Ctrl+I)","bold_desc":"Bold (Ctrl+B)"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/simple/langs/fr.js b/src/core/static/js/tiny_mce/themes/simple/langs/fr.js new file mode 100755 index 0000000..ebe964e --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/simple/langs/fr.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.simple',{"cleanup_desc":"Nettoyer le code","redo_desc":"R\u00e9tablir (Ctrl+Y)","undo_desc":"Annuler (Ctrl+Z)","numlist_desc":"Liste num\u00e9rot\u00e9e","bullist_desc":"Liste \u00e0 puces","striketrough_desc":"Barr\u00e9","underline_desc":"Soulign\u00e9 (Ctrl+U)","italic_desc":"Italique (Ctrl+I)","bold_desc":"Gras (Ctrl+B)"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/simple/langs/it.js b/src/core/static/js/tiny_mce/themes/simple/langs/it.js new file mode 100755 index 0000000..e0c45ed --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/simple/langs/it.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.simple',{"cleanup_desc":"Pulisci codice disordinato","redo_desc":"Ripristina (Ctrl+Y)","undo_desc":"Annulla (Ctrl+Z)","numlist_desc":"Lista ordinata","bullist_desc":"Lista non ordinata","striketrough_desc":"Barrato","underline_desc":"Sottolineato (Ctrl+U)","italic_desc":"Corsivo (Ctrl+I)","bold_desc":"Grassetto (Ctrl+B)"}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/themes/simple/skins/default/content.css b/src/core/static/js/tiny_mce/themes/simple/skins/default/content.css new file mode 100644 index 0000000..2506c80 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/simple/skins/default/content.css @@ -0,0 +1,25 @@ +body, td, pre { + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 10px; +} + +body { + background-color: #FFFFFF; +} + +.mceVisualAid { + border: 1px dashed #BBBBBB; +} + +/* MSIE specific */ + +* html body { + scrollbar-3dlight-color: #F0F0EE; + scrollbar-arrow-color: #676662; + scrollbar-base-color: #F0F0EE; + scrollbar-darkshadow-color: #DDDDDD; + scrollbar-face-color: #E0E0DD; + scrollbar-highlight-color: #F0F0EE; + scrollbar-shadow-color: #F0F0EE; + scrollbar-track-color: #F5F5F5; +} diff --git a/src/core/static/js/tiny_mce/themes/simple/skins/default/ui.css b/src/core/static/js/tiny_mce/themes/simple/skins/default/ui.css new file mode 100644 index 0000000..076fe84 --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/simple/skins/default/ui.css @@ -0,0 +1,32 @@ +/* Reset */ +.defaultSimpleSkin table, .defaultSimpleSkin tbody, .defaultSimpleSkin a, .defaultSimpleSkin img, .defaultSimpleSkin tr, .defaultSimpleSkin div, .defaultSimpleSkin td, .defaultSimpleSkin iframe, .defaultSimpleSkin span, .defaultSimpleSkin * {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000} + +/* Containers */ +.defaultSimpleSkin {position:relative} +.defaultSimpleSkin table.mceLayout {background:#F0F0EE; border:1px solid #CCC;} +.defaultSimpleSkin iframe {display:block; background:#FFF; border-bottom:1px solid #CCC;} +.defaultSimpleSkin .mceToolbar {height:24px;} + +/* Layout */ +.defaultSimpleSkin span.mceIcon, .defaultSimpleSkin img.mceIcon {display:block; width:20px; height:20px} +.defaultSimpleSkin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px} + +/* Button */ +.defaultSimpleSkin .mceButton {display:block; border:1px solid #F0F0EE; width:20px; height:20px} +.defaultSimpleSkin a.mceButtonEnabled:hover {border:1px solid #0A246A; background-color:#B2BBD0} +.defaultSimpleSkin a.mceButtonActive {border:1px solid #0A246A; background-color:#C2CBE0} +.defaultSimpleSkin .mceButtonDisabled span {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} + +/* Separator */ +.defaultSimpleSkin .mceSeparator {display:block; background:url(../../img/icons.gif) -180px 0; width:2px; height:20px; margin:0 2px 0 4px} + +/* Theme */ +.defaultSimpleSkin span.mce_bold {background-position:0 0} +.defaultSimpleSkin span.mce_italic {background-position:-60px 0} +.defaultSimpleSkin span.mce_underline {background-position:-140px 0} +.defaultSimpleSkin span.mce_strikethrough {background-position:-120px 0} +.defaultSimpleSkin span.mce_undo {background-position:-160px 0} +.defaultSimpleSkin span.mce_redo {background-position:-100px 0} +.defaultSimpleSkin span.mce_cleanup {background-position:-40px 0} +.defaultSimpleSkin span.mce_insertunorderedlist {background-position:-20px 0} +.defaultSimpleSkin span.mce_insertorderedlist {background-position:-80px 0} diff --git a/src/core/static/js/tiny_mce/themes/simple/skins/o2k7/content.css b/src/core/static/js/tiny_mce/themes/simple/skins/o2k7/content.css new file mode 100644 index 0000000..595809f --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/simple/skins/o2k7/content.css @@ -0,0 +1,17 @@ +body, td, pre {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} + +body {background: #FFF;} +.mceVisualAid {border: 1px dashed #BBB;} + +/* IE */ + +* html body { +scrollbar-3dlight-color: #F0F0EE; +scrollbar-arrow-color: #676662; +scrollbar-base-color: #F0F0EE; +scrollbar-darkshadow-color: #DDDDDD; +scrollbar-face-color: #E0E0DD; +scrollbar-highlight-color: #F0F0EE; +scrollbar-shadow-color: #F0F0EE; +scrollbar-track-color: #F5F5F5; +} diff --git a/src/core/static/js/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png b/src/core/static/js/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..527e3495a653e57d76bf7e55316793d17dda497a GIT binary patch literal 5102 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 VmjT$ODWe$zObpERYjs_s{s;8{A&me4 literal 0 HcmV?d00001 diff --git a/src/core/static/js/tiny_mce/themes/simple/skins/o2k7/ui.css b/src/core/static/js/tiny_mce/themes/simple/skins/o2k7/ui.css new file mode 100644 index 0000000..cf6c35d --- /dev/null +++ b/src/core/static/js/tiny_mce/themes/simple/skins/o2k7/ui.css @@ -0,0 +1,35 @@ +/* Reset */ +.o2k7SimpleSkin table, .o2k7SimpleSkin tbody, .o2k7SimpleSkin a, .o2k7SimpleSkin img, .o2k7SimpleSkin tr, .o2k7SimpleSkin div, .o2k7SimpleSkin td, .o2k7SimpleSkin iframe, .o2k7SimpleSkin span, .o2k7SimpleSkin * {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000} + +/* Containers */ +.o2k7SimpleSkin {position:relative} +.o2k7SimpleSkin table.mceLayout {background:#E5EFFD; border:1px solid #ABC6DD;} +.o2k7SimpleSkin iframe {display:block; background:#FFF; border-bottom:1px solid #ABC6DD;} +.o2k7SimpleSkin .mceToolbar {height:26px;} + +/* Layout */ +.o2k7SimpleSkin .mceToolbar .mceToolbarStart span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px; } +.o2k7SimpleSkin .mceToolbar .mceToolbarEnd span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px} +.o2k7SimpleSkin span.mceIcon, .o2k7SimpleSkin img.mceIcon {display:block; width:20px; height:20px} +.o2k7SimpleSkin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px} + +/* Button */ +.o2k7SimpleSkin .mceButton {display:block; background:url(img/button_bg.png); width:22px; height:22px} +.o2k7SimpleSkin a.mceButton span, .o2k7SimpleSkin a.mceButton img {margin:1px 0 0 1px} +.o2k7SimpleSkin a.mceButtonEnabled:hover {background-color:#B2BBD0; background-position:0 -22px} +.o2k7SimpleSkin a.mceButtonActive {background-position:0 -44px} +.o2k7SimpleSkin .mceButtonDisabled span {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} + +/* Separator */ +.o2k7SimpleSkin .mceSeparator {display:block; background:url(img/button_bg.png) -22px 0; width:5px; height:22px} + +/* Theme */ +.o2k7SimpleSkin span.mce_bold {background-position:0 0} +.o2k7SimpleSkin span.mce_italic {background-position:-60px 0} +.o2k7SimpleSkin span.mce_underline {background-position:-140px 0} +.o2k7SimpleSkin span.mce_strikethrough {background-position:-120px 0} +.o2k7SimpleSkin span.mce_undo {background-position:-160px 0} +.o2k7SimpleSkin span.mce_redo {background-position:-100px 0} +.o2k7SimpleSkin span.mce_cleanup {background-position:-40px 0} +.o2k7SimpleSkin span.mce_insertunorderedlist {background-position:-20px 0} +.o2k7SimpleSkin span.mce_insertorderedlist {background-position:-80px 0} diff --git a/src/core/static/js/tiny_mce/tiny_mce.js b/src/core/static/js/tiny_mce/tiny_mce.js new file mode 100644 index 0000000..e1c0acf --- /dev/null +++ b/src/core/static/js/tiny_mce/tiny_mce.js @@ -0,0 +1 @@ +(function(d){var a=/^\s*|\s*$/g,e,c="B".replace(/A(.)|B/,"$1")==="$1";var b={majorVersion:"3",minorVersion:"4.6",releaseDate:"2011-09-29",_init:function(){var s=this,q=document,o=navigator,g=o.userAgent,m,f,l,k,j,r;s.isOpera=d.opera&&opera.buildNumber;s.isWebKit=/WebKit/.test(g);s.isIE=!s.isWebKit&&!s.isOpera&&(/MSIE/gi).test(g)&&(/Explorer/gi).test(o.appName);s.isIE6=s.isIE&&/MSIE [56]/.test(g);s.isIE7=s.isIE&&/MSIE [7]/.test(g);s.isIE8=s.isIE&&/MSIE [8]/.test(g);s.isIE9=s.isIE&&/MSIE [9]/.test(g);s.isGecko=!s.isWebKit&&/Gecko/.test(g);s.isMac=g.indexOf("Mac")!=-1;s.isAir=/adobeair/i.test(g);s.isIDevice=/(iPad|iPhone)/.test(g);s.isIOS5=s.isIDevice&&g.match(/AppleWebKit\/(\d*)/)[1]>=534;if(d.tinyMCEPreInit){s.suffix=tinyMCEPreInit.suffix;s.baseURL=tinyMCEPreInit.base;s.query=tinyMCEPreInit.query;return}s.suffix="";f=q.getElementsByTagName("base");for(m=0;m<f.length;m++){if(r=f[m].href){if(/^https?:\/\/[^\/]+$/.test(r)){r+="/"}k=r?r.match(/.*\//)[0]:""}}function h(i){if(i.src&&/tiny_mce(|_gzip|_jquery|_prototype|_full)(_dev|_src)?.js/.test(i.src)){if(/_(src|dev)\.js/g.test(i.src)){s.suffix="_src"}if((j=i.src.indexOf("?"))!=-1){s.query=i.src.substring(j+1)}s.baseURL=i.src.substring(0,i.src.lastIndexOf("/"));if(k&&s.baseURL.indexOf("://")==-1&&s.baseURL.indexOf("/")!==0){s.baseURL=k+s.baseURL}return s.baseURL}return null}f=q.getElementsByTagName("script");for(m=0;m<f.length;m++){if(h(f[m])){return}}l=q.getElementsByTagName("head")[0];if(l){f=l.getElementsByTagName("script");for(m=0;m<f.length;m++){if(h(f[m])){return}}}return},is:function(g,f){if(!f){return g!==e}if(f=="array"&&(g.hasOwnProperty&&g instanceof Array)){return true}return typeof(g)==f},makeMap:function(f,j,h){var g;f=f||[];j=j||",";if(typeof(f)=="string"){f=f.split(j)}h=h||{};g=f.length;while(g--){h[f[g]]={}}return h},each:function(i,f,h){var j,g;if(!i){return 0}h=h||i;if(i.length!==e){for(j=0,g=i.length;j<g;j++){if(f.call(h,i[j],j,i)===false){return 0}}}else{for(j in i){if(i.hasOwnProperty(j)){if(f.call(h,i[j],j,i)===false){return 0}}}}return 1},map:function(g,h){var i=[];b.each(g,function(f){i.push(h(f))});return i},grep:function(g,h){var i=[];b.each(g,function(f){if(!h||h(f)){i.push(f)}});return i},inArray:function(g,h){var j,f;if(g){for(j=0,f=g.length;j<f;j++){if(g[j]===h){return j}}}return -1},extend:function(k,j){var h,g,f=arguments;for(h=1,g=f.length;h<g;h++){j=f[h];b.each(j,function(i,l){if(i!==e){k[l]=i}})}return k},trim:function(f){return(f?""+f:"").replace(a,"")},create:function(o,f,j){var n=this,g,i,k,l,h,m=0;o=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(o);k=o[3].match(/(^|\.)(\w+)$/i)[2];i=n.createNS(o[3].replace(/\.\w+$/,""),j);if(i[k]){return}if(o[2]=="static"){i[k]=f;if(this.onCreate){this.onCreate(o[2],o[3],i[k])}return}if(!f[k]){f[k]=function(){};m=1}i[k]=f[k];n.extend(i[k].prototype,f);if(o[5]){g=n.resolve(o[5]).prototype;l=o[5].match(/\.(\w+)$/i)[1];h=i[k];if(m){i[k]=function(){return g[l].apply(this,arguments)}}else{i[k]=function(){this.parent=g[l];return h.apply(this,arguments)}}i[k].prototype[k]=i[k];n.each(g,function(p,q){i[k].prototype[q]=g[q]});n.each(f,function(p,q){if(g[q]){i[k].prototype[q]=function(){this.parent=g[q];return p.apply(this,arguments)}}else{if(q!=k){i[k].prototype[q]=p}}})}n.each(f["static"],function(p,q){i[k][q]=p});if(this.onCreate){this.onCreate(o[2],o[3],i[k].prototype)}},walk:function(i,h,j,g){g=g||this;if(i){if(j){i=i[j]}b.each(i,function(k,f){if(h.call(g,k,f,j)===false){return false}b.walk(k,h,j,g)})}},createNS:function(j,h){var g,f;h=h||d;j=j.split(".");for(g=0;g<j.length;g++){f=j[g];if(!h[f]){h[f]={}}h=h[f]}return h},resolve:function(j,h){var g,f;h=h||d;j=j.split(".");for(g=0,f=j.length;g<f;g++){h=h[j[g]];if(!h){break}}return h},addUnload:function(j,i){var h=this;j={func:j,scope:i||this};if(!h.unloads){function g(){var f=h.unloads,l,m;if(f){for(m in f){l=f[m];if(l&&l.func){l.func.call(l.scope,1)}}if(d.detachEvent){d.detachEvent("onbeforeunload",k);d.detachEvent("onunload",g)}else{if(d.removeEventListener){d.removeEventListener("unload",g,false)}}h.unloads=l=f=w=g=0;if(d.CollectGarbage){CollectGarbage()}}}function k(){var l=document;if(l.readyState=="interactive"){function f(){l.detachEvent("onstop",f);if(g){g()}l=0}if(l){l.attachEvent("onstop",f)}d.setTimeout(function(){if(l){l.detachEvent("onstop",f)}},0)}}if(d.attachEvent){d.attachEvent("onunload",g);d.attachEvent("onbeforeunload",k)}else{if(d.addEventListener){d.addEventListener("unload",g,false)}}h.unloads=[j]}else{h.unloads.push(j)}return j},removeUnload:function(i){var g=this.unloads,h=null;b.each(g,function(j,f){if(j&&j.func==i){g.splice(f,1);h=i;return false}});return h},explode:function(f,g){return f?b.map(f.split(g||","),b.trim):f},_addVer:function(g){var f;if(!this.query){return g}f=(g.indexOf("?")==-1?"?":"&")+this.query;if(g.indexOf("#")==-1){return g+f}return g.replace("#",f+"#")},_replace:function(h,f,g){if(c){return g.replace(h,function(){var l=f,j=arguments,k;for(k=0;k<j.length-2;k++){if(j[k]===e){l=l.replace(new RegExp("\\$"+k,"g"),"")}else{l=l.replace(new RegExp("\\$"+k,"g"),j[k])}}return l})}return g.replace(h,f)}};b._init();d.tinymce=d.tinyMCE=b})(window);tinymce.create("tinymce.util.Dispatcher",{scope:null,listeners:null,Dispatcher:function(a){this.scope=a||this;this.listeners=[]},add:function(a,b){this.listeners.push({cb:a,scope:b||this.scope});return a},addToTop:function(a,b){this.listeners.unshift({cb:a,scope:b||this.scope});return a},remove:function(a){var b=this.listeners,c=null;tinymce.each(b,function(e,d){if(a==e.cb){c=a;b.splice(d,1);return false}});return c},dispatch:function(){var f,d=arguments,e,b=this.listeners,g;for(e=0;e<b.length;e++){g=b[e];f=g.cb.apply(g.scope,d);if(f===false){break}}return f}});(function(){var a=tinymce.each;tinymce.create("tinymce.util.URI",{URI:function(e,g){var f=this,i,d,c,h;e=tinymce.trim(e);g=f.settings=g||{};if(/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)){f.source=e;return}if(e.indexOf("/")===0&&e.indexOf("//")!==0){e=(g.base_uri?g.base_uri.protocol||"http":"http")+"://mce_host"+e}if(!/^[\w-]*:?\/\//.test(e)){h=g.base_uri?g.base_uri.path:new tinymce.util.URI(location.href).directory;e=((g.base_uri&&g.base_uri.protocol)||"http")+"://mce_host"+f.toAbsPath(h,e)}e=e.replace(/@@/g,"(mce_at)");e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e);a(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(b,j){var k=e[j];if(k){k=k.replace(/\(mce_at\)/g,"@@")}f[b]=k});if(c=g.base_uri){if(!f.protocol){f.protocol=c.protocol}if(!f.userInfo){f.userInfo=c.userInfo}if(!f.port&&f.host=="mce_host"){f.port=c.port}if(!f.host||f.host=="mce_host"){f.host=c.host}f.source=""}},setPath:function(c){var b=this;c=/^(.*?)\/?(\w+)?$/.exec(c);b.path=c[0];b.directory=c[1];b.file=c[2];b.source="";b.getURI()},toRelative:function(b){var c=this,d;if(b==="./"){return b}b=new tinymce.util.URI(b,{base_uri:c});if((b.host!="mce_host"&&c.host!=b.host&&b.host)||c.port!=b.port||c.protocol!=b.protocol){return b.getURI()}d=c.toRelPath(c.path,b.path);if(b.query){d+="?"+b.query}if(b.anchor){d+="#"+b.anchor}return d},toAbsolute:function(b,c){var b=new tinymce.util.URI(b,{base_uri:this});return b.getURI(this.host==b.host&&this.protocol==b.protocol?c:0)},toRelPath:function(g,h){var c,f=0,d="",e,b;g=g.substring(0,g.lastIndexOf("/"));g=g.split("/");c=h.split("/");if(g.length>=c.length){for(e=0,b=g.length;e<b;e++){if(e>=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length<c.length){for(e=0,b=c.length;e<b;e++){if(e>=g.length||g[e]!=c[e]){f=e+1;break}}}if(f==1){return h}for(e=0,b=g.length-(f-1);e<b;e++){d+="../"}for(e=f-1,b=c.length;e<b;e++){if(e!=f-1){d+="/"+c[e]}else{d+=c[e]}}return d},toAbsPath:function(e,f){var c,b=0,h=[],d,g;d=/\/$/.test(f)?"/":"";e=e.split("/");f=f.split("/");a(e,function(i){if(i){h.push(i)}});e=h;for(c=f.length-1,h=[];c>=0;c--){if(f[c].length==0||f[c]=="."){continue}if(f[c]==".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!=0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(e,b){var c=new Date();c.setTime(c.getTime()-1000);this.set(e,"",c,b,c)}})})();(function(){function serialize(o,quote){var i,v,t;quote=quote||'"';if(o==null){return"null"}t=typeof o;if(t=="string"){v="\bb\tt\nn\ff\rr\"\"''\\\\";return quote+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){if(quote==='"'&&a==="'"){return a}i=v.indexOf(b);if(i+1){return"\\"+v.charAt(i+1)}a=b.charCodeAt().toString(16);return"\\u"+"0000".substring(a.length)+a})+quote}if(t=="object"){if(o.hasOwnProperty&&o instanceof Array){for(i=0,v="[";i<o.length;i++){v+=(i>0?",":"")+serialize(o[i],quote)}return v+"]"}v="{";for(i in o){v+=typeof o[i]!="function"?(v.length>1?","+quote:quote)+i+quote+":"+serialize(o[i],quote):""}return v+"}"}return""+o}tinymce.util.JSON={serialize:serialize,parse:function(s){try{return eval("("+s+")")}catch(ex){}}}})();tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){if(e){e.call(f.error_scope||f.scope,h,g)}};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(a){a.VK={DELETE:46,BACKSPACE:8}})(tinymce);(function(i){var g=i.VK,h=g.BACKSPACE,f=g.DELETE;function b(j){var l=j.dom,k=j.selection;j.onKeyDown.add(function(n,r){var m,s,p,q,o;o=r.keyCode==f;if(o||r.keyCode==h){r.preventDefault();m=k.getRng();s=l.getParent(m.startContainer,l.isBlock);if(o){s=l.getNext(s,l.isBlock)}if(s){p=s.firstChild;while(p.nodeType==3&&p.nodeValue.length==0){p=p.nextSibling}if(p&&p.nodeName==="SPAN"){q=p.cloneNode(false)}}n.getDoc().execCommand(o?"ForwardDelete":"Delete",false,null);s=l.getParent(m.startContainer,l.isBlock);i.each(l.select("span.Apple-style-span,font.Apple-style-span",s),function(t){var u=k.getBookmark();if(q){l.replace(q.cloneNode(false),t,true)}else{l.remove(t,true)}k.moveToBookmark(u)})}})}function c(j){j.onKeyUp.add(function(k,m){var l=m.keyCode;if(l==f||l==h){if(k.dom.isEmpty(k.getBody())){k.setContent("",{format:"raw"});k.nodeChanged();return}}})}function a(j){j.dom.bind(j.getDoc(),"focusin",function(){j.selection.setRng(j.selection.getRng())})}function e(j){if(!Range.prototype.getClientRects){j.onMouseDown.add(function(l,m){if(m.target.nodeName==="HTML"){var k=l.getBody();k.blur();setTimeout(function(){k.focus()},0)}})}}function d(j){j.onClick.add(function(k,l){l=l.target;if(/^(IMG|HR)$/.test(l.nodeName)){k.selection.getSel().setBaseAndExtent(l,0,l,1)}if(l.nodeName=="A"&&k.dom.hasClass(l,"mceItemAnchor")){k.selection.select(l)}k.nodeChanged()})}i.create("tinymce.util.Quirks",{Quirks:function(j){if(i.isWebKit){b(j);c(j);a(j);d(j)}if(i.isIE){c(j)}if(i.isGecko){e(j)}}})})(tinymce);(function(j){var a,g,d,k=/[&<>\"\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/[<>&\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,f=/[<>&\"\']/g,c=/&(#x|#)?([\w]+);/g,i={128:"\u20AC",130:"\u201A",131:"\u0192",132:"\u201E",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02C6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017D",145:"\u2018",146:"\u2019",147:"\u201C",148:"\u201D",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02DC",153:"\u2122",154:"\u0161",155:"\u203A",156:"\u0153",158:"\u017E",159:"\u0178"};g={'"':"&quot;","'":"&#39;","<":"&lt;",">":"&gt;","&":"&amp;"};d={"&lt;":"<","&gt;":">","&amp;":"&","&quot;":'"',"&apos;":"'"};function h(l){var m;m=document.createElement("div");m.innerHTML=l;return m.textContent||m.innerText||l}function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n<m.length;n+=2){o=String.fromCharCode(parseInt(m[n],p));if(!g[o]){l="&"+m[n+1]+";";q[o]=l;q[l]=o}}return q}}a=e("50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",32);j.html=j.html||{};j.html.Entities={encodeRaw:function(m,l){return m.replace(l?k:b,function(n){return g[n]||n})},encodeAllRaw:function(l){return(""+l).replace(f,function(m){return g[m]||m})},encodeNumeric:function(m,l){return m.replace(l?k:b,function(n){if(n.length>1){return"&#"+(((n.charCodeAt(0)-55296)*1024)+(n.charCodeAt(1)-56320)+65536)+";"}return g[n]||"&#"+n.charCodeAt(0)+";"})},encodeNamed:function(n,l,m){m=m||a;return n.replace(l?k:b,function(o){return g[o]||m[o]||o})},getEncodeFunc:function(l,o){var p=j.html.Entities;o=e(o)||a;function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&#"+s.charCodeAt(0)+";"||s})}function n(r,q){return p.encodeNamed(r,q,o)}l=j.makeMap(l.replace(/\+/g,","));if(l.named&&l.numeric){return m}if(l.named){if(o){return n}return p.encodeNamed}if(l.numeric){return p.encodeNumeric}return p.encodeRaw},decode:function(l){return l.replace(c,function(n,m,o){if(m){o=parseInt(o,m.length===2?16:10);if(o>65535){o-=65536;return String.fromCharCode(55296+(o>>10),56320+(o&1023))}else{return i[o]||String.fromCharCode(o)}}return d[n]||a[n]||h(n)})}}})(tinymce);tinymce.html.Styles=function(d,f){var k=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,h=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,b=/\s*([^:]+):\s*([^;]+);?/g,l=/\s+$/,m=/rgb/,e,g,a={},j;d=d||{};j="\\\" \\' \\; \\: ; : \uFEFF".split(" ");for(g=0;g<j.length;g++){a[j[g]]="\uFEFF"+g;a["\uFEFF"+g]=j[g]}function c(n,q,p,i){function o(r){r=parseInt(r).toString(16);return r.length>1?r:"0"+r}return"#"+o(q)+o(p)+o(i)}return{toHex:function(i){return i.replace(k,c)},parse:function(r){var y={},p,n,v,q,u=d.url_converter,x=d.url_converter_scope||this;function o(C,F){var E,B,A,D;E=y[C+"-top"+F];if(!E){return}B=y[C+"-right"+F];if(E!=B){return}A=y[C+"-bottom"+F];if(B!=A){return}D=y[C+"-left"+F];if(A!=D){return}y[C+F]=D;delete y[C+"-top"+F];delete y[C+"-right"+F];delete y[C+"-bottom"+F];delete y[C+"-left"+F]}function t(B){var C=y[B],A;if(!C||C.indexOf(" ")<0){return}C=C.split(" ");A=C.length;while(A--){if(C[A]!==C[0]){return false}}y[B]=C[0];return true}function z(C,B,A,D){if(!t(B)){return}if(!t(A)){return}if(!t(D)){return}y[C]=y[B]+" "+y[A]+" "+y[D];delete y[B];delete y[A];delete y[D]}function s(A){q=true;return a[A]}function i(B,A){if(q){B=B.replace(/\uFEFF[0-9]/g,function(C){return a[C]})}if(!A){B=B.replace(/\\([\'\";:])/g,"$1")}return B}if(r){r=r.replace(/\\[\"\';:\uFEFF]/g,s).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(A){return A.replace(/[;:]/g,s)});while(p=b.exec(r)){n=p[1].replace(l,"").toLowerCase();v=p[2].replace(l,"");if(n&&v.length>0){if(n==="font-weight"&&v==="700"){v="bold"}else{if(n==="color"||n==="background-color"){v=v.toLowerCase()}}v=v.replace(k,c);v=v.replace(h,function(B,A,E,D,F,C){F=F||C;if(F){F=i(F);return"'"+F.replace(/\'/g,"\\'")+"'"}A=i(A||E||D);if(u){A=u.call(x,A,"style")}return"url('"+A.replace(/\'/g,"\\'")+"')"});y[n]=q?i(v,true):v}b.lastIndex=p.index+p[0].length}o("border","");o("border","-width");o("border","-color");o("border","-style");o("padding","");o("margin","");z("border","border-width","border-style","border-color");if(y.border==="medium none"){delete y.border}}return y},serialize:function(p,r){var o="",n,q;function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u<s;u++){t=x[u];v=p[t];if(v!==e&&v.length>0){o+=(o.length>0?" ":"")+t+": "+v+";"}}}}if(r&&f&&f.styles){i("*");i(r)}else{for(n in p){q=p[n];if(q!==e&&q.length>0){o+=(o.length>0?" ":"")+n+": "+q+";"}}}return o}}};(function(m){var h={},j,l,g,f,c={},b,e,d=m.makeMap,k=m.each;function i(o,n){return o.split(n||",")}function a(r,q){var o,p={};function n(s){return s.replace(/[A-Z]+/g,function(t){return n(r[t])})}for(o in r){if(r.hasOwnProperty(o)){r[o]=n(r[o])}}n(q).replace(/#/g,"#text").replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g,function(v,t,s,u){s=i(s,"|");p[t]={attributes:d(s),attributesOrder:s,children:d(u,"|",{"#comment":{}})}});return p}l="h1,h2,h3,h4,h5,h6,hr,p,div,address,pre,form,table,tbody,thead,tfoot,th,tr,td,li,ol,ul,caption,blockquote,center,dl,dt,dd,dir,fieldset,noscript,menu,isindex,samp,header,footer,article,section,hgroup";l=d(l,",",d(l.toUpperCase()));h=a({Z:"H|K|N|O|P",Y:"X|form|R|Q",ZG:"E|span|width|align|char|charoff|valign",X:"p|T|div|U|W|isindex|fieldset|table",ZF:"E|align|char|charoff|valign",W:"pre|hr|blockquote|address|center|noframes",ZE:"abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height",ZD:"[E][S]",U:"ul|ol|dl|menu|dir",ZC:"p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q",T:"h1|h2|h3|h4|h5|h6",ZB:"X|S|Q",S:"R|P",ZA:"a|G|J|M|O|P",R:"a|H|K|N|O",Q:"noscript|P",P:"ins|del|script",O:"input|select|textarea|label|button",N:"M|L",M:"em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym",L:"sub|sup",K:"J|I",J:"tt|i|b|u|s|strike",I:"big|small|font|basefont",H:"G|F",G:"br|span|bdo",F:"object|applet|img|map|iframe",E:"A|B|C",D:"accesskey|tabindex|onfocus|onblur",C:"onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"lang|xml:lang|dir",A:"id|class|style|title"},"script[id|charset|type|language|src|defer|xml:space][]style[B|id|type|media|title|xml:space][]object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]param[id|name|value|valuetype|type][]p[E|align][#|S]a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]br[A|clear][]span[E][#|S]bdo[A|C|B][#|S]applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]h1[E|align][#|S]img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]map[B|C|A|name][X|form|Q|area]h2[E|align][#|S]iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]h3[E|align][#|S]tt[E][#|S]i[E][#|S]b[E][#|S]u[E][#|S]s[E][#|S]strike[E][#|S]big[E][#|S]small[E][#|S]font[A|B|size|color|face][#|S]basefont[id|size|color|face][]em[E][#|S]strong[E][#|S]dfn[E][#|S]code[E][#|S]q[E|cite][#|S]samp[E][#|S]kbd[E][#|S]var[E][#|S]cite[E][#|S]abbr[E][#|S]acronym[E][#|S]sub[E][#|S]sup[E][#|S]input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]optgroup[E|disabled|label][option]option[E|selected|disabled|label|value][]textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]label[E|for|accesskey|onfocus|onblur][#|S]button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]h4[E|align][#|S]ins[E|cite|datetime][#|Y]h5[E|align][#|S]del[E|cite|datetime][#|Y]h6[E|align][#|S]div[E|align][#|Y]ul[E|type|compact][li]li[E|type|value][#|Y]ol[E|type|compact|start][li]dl[E|compact][dt|dd]dt[E][#|S]dd[E][#|Y]menu[E|compact][li]dir[E|compact][li]pre[E|width|xml:space][#|ZA]hr[E|align|noshade|size|width][]blockquote[E|cite][#|Y]address[E][#|S|p]center[E][#|Y]noframes[E][#|Y]isindex[A|B|prompt][]fieldset[E][#|legend|Y]legend[E|accesskey|align][#|S]table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]caption[E|align][#|S]col[ZG][]colgroup[ZG][col]thead[ZF][tr]tr[ZF|bgcolor][th|td]th[E|ZE][#|Y]form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]noscript[E][#|Y]td[E|ZE][#|Y]tfoot[ZF][tr]tbody[ZF][tr]area[E|D|shape|coords|href|nohref|alt|target][]base[id|href|target][]body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]");j=d("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected,autoplay,loop,controls");g=d("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,source");f=m.extend(d("td,th,iframe,video,audio,object"),g);b=d("pre,script,style,textarea");e=d("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");m.html.Schema=function(r){var A=this,n={},o={},y=[],q,p;r=r||{};if(r.verify_html===false){r.valid_elements="*[*]"}if(r.valid_styles){q={};k(r.valid_styles,function(C,B){q[B]=m.explode(C)})}p=r.whitespace_elements?d(r.whitespace_elements):b;function z(B){return new RegExp("^"+B.replace(/([?+*])/g,".$1")+"$")}function t(I){var H,D,W,S,X,C,F,R,U,N,V,Z,L,G,T,B,P,E,Y,aa,M,Q,K=/^([#+-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,O=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,J=/[*?+]/;if(I){I=i(I);if(n["@"]){P=n["@"].attributes;E=n["@"].attributesOrder}for(H=0,D=I.length;H<D;H++){C=K.exec(I[H]);if(C){T=C[1];N=C[2];B=C[3];U=C[4];L={};G=[];F={attributes:L,attributesOrder:G};if(T==="#"){F.paddEmpty=true}if(T==="-"){F.removeEmpty=true}if(P){for(aa in P){L[aa]=P[aa]}G.push.apply(G,E)}if(U){U=i(U,"|");for(W=0,S=U.length;W<S;W++){C=O.exec(U[W]);if(C){R={};Z=C[1];V=C[2].replace(/::/g,":");T=C[3];Q=C[4];if(Z==="!"){F.attributesRequired=F.attributesRequired||[];F.attributesRequired.push(V);R.required=true}if(Z==="-"){delete L[V];G.splice(m.inArray(G,V),1);continue}if(T){if(T==="="){F.attributesDefault=F.attributesDefault||[];F.attributesDefault.push({name:V,value:Q});R.defaultValue=Q}if(T===":"){F.attributesForced=F.attributesForced||[];F.attributesForced.push({name:V,value:Q});R.forcedValue=Q}if(T==="<"){R.validValues=d(Q,"?")}}if(J.test(V)){F.attributePatterns=F.attributePatterns||[];R.pattern=z(V);F.attributePatterns.push(R)}else{if(!L[V]){G.push(V)}L[V]=R}}}}if(!P&&N=="@"){P=L;E=G}if(B){F.outputName=N;n[B]=F}if(J.test(N)){F.pattern=z(N);y.push(F)}else{n[N]=F}}}}}function v(B){n={};y=[];t(B);k(h,function(D,C){o[C]=D.children})}function s(C){var B=/^(~)?(.+)$/;if(C){k(i(C),function(G){var E=B.exec(G),F=E[1]==="~",H=F?"span":"div",D=E[2];o[D]=o[H];c[D]=H;if(!F){l[D]={}}k(o,function(I,J){if(I[H]){I[D]=I[H]}})})}}function u(C){var B=/^([+\-]?)(\w+)\[([^\]]+)\]$/;if(C){k(i(C),function(G){var F=B.exec(G),D,E;if(F){E=F[1];if(E){D=o[F[2]]}else{D=o[F[2]]={"#comment":{}}}D=o[F[2]];k(i(F[3],"|"),function(H){if(E==="-"){delete D[H]}else{D[H]={}}})}})}}function x(B){var D=n[B],C;if(D){return D}C=y.length;while(C--){D=y[C];if(D.pattern.test(B)){return D}}}if(!r.valid_elements){k(h,function(C,B){n[B]={attributes:C.attributes,attributesOrder:C.attributesOrder};o[B]=C.children});k(i("strong/b,em/i"),function(B){B=i(B,"/");n[B[1]].outputName=B[0]});n.img.attributesDefault=[{name:"alt",value:""}];k(i("ol,ul,sub,sup,blockquote,span,font,a,table,tbody,tr"),function(B){n[B].removeEmpty=true});k(i("p,h1,h2,h3,h4,h5,h6,th,td,pre,div,address,caption"),function(B){n[B].paddEmpty=true})}else{v(r.valid_elements)}s(r.custom_elements);u(r.valid_children);t(r.extended_valid_elements);u("+ol[ul|ol],+ul[ul|ol]");if(!x("span")){t("span[!data-mce-type|*]")}if(r.invalid_elements){m.each(m.explode(r.invalid_elements),function(B){if(n[B]){delete n[B]}})}A.children=o;A.styles=q;A.getBoolAttrs=function(){return j};A.getBlockElements=function(){return l};A.getShortEndedElements=function(){return g};A.getSelfClosingElements=function(){return e};A.getNonEmptyElements=function(){return f};A.getWhiteSpaceElements=function(){return p};A.isValidChild=function(B,D){var C=o[B];return !!(C&&C[D])};A.getElementRule=x;A.getCustomElements=function(){return c};A.addValidElements=t;A.setValidElements=v;A.addCustomElements=s;A.addValidChildren=u};m.html.Schema.boolAttrMap=j;m.html.Schema.blockElementsMap=l})(tinymce);(function(a){a.html.SaxParser=function(c,e){var b=this,d=function(){};c=c||{};b.schema=e=e||new a.html.Schema();if(c.fix_self_closing!==false){c.fix_self_closing=true}a.each("comment cdata text start end pi doctype".split(" "),function(f){if(f){b[f]=c[f]||d}});b.parse=function(D){var n=this,g,F=0,H,A,z=[],M,P,B,q,y,r,L,G,N,u,m,k,s,Q,o,O,E,R,K,f,I,l,C,J,h,v=0,j=a.html.Entities.decode,x,p;function t(S){var U,T;U=z.length;while(U--){if(z[U].name===S){break}}if(U>=0){for(T=z.length-1;T>=U;T--){S=z[T];if(S.valid){n.end(S.name)}}z.length=U}}l=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([^\\s\\/<>]+)\\s*((?:[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*)>))","g");C=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;J={script:/<\/script[^>]*>/gi,style:/<\/style[^>]*>/gi,noscript:/<\/noscript[^>]*>/gi};L=e.getShortEndedElements();I=e.getSelfClosingElements();G=e.getBoolAttrs();u=c.validate;r=c.remove_internals;x=c.fix_self_closing;p=a.isIE;o=/^:/;while(g=l.exec(D)){if(F<g.index){n.text(j(D.substr(F,g.index-F)))}if(H=g[6]){H=H.toLowerCase();if(p&&o.test(H)){H=H.substr(1)}t(H)}else{if(H=g[7]){H=H.toLowerCase();if(p&&o.test(H)){H=H.substr(1)}N=H in L;if(x&&I[H]&&z.length>0&&z[z.length-1].name===H){t(H)}if(!u||(m=e.getElementRule(H))){k=true;if(u){O=m.attributes;E=m.attributePatterns}if(Q=g[8]){y=Q.indexOf("data-mce-type")!==-1;if(y&&r){k=false}M=[];M.map={};Q.replace(C,function(T,S,X,W,V){var Y,U;S=S.toLowerCase();X=S in G?S:j(X||W||V||"");if(u&&!y&&S.indexOf("data-")!==0){Y=O[S];if(!Y&&E){U=E.length;while(U--){Y=E[U];if(Y.pattern.test(S)){break}}if(U===-1){Y=null}}if(!Y){return}if(Y.validValues&&!(X in Y.validValues)){return}}M.map[S]=X;M.push({name:S,value:X})})}else{M=[];M.map={}}if(u&&!y){R=m.attributesRequired;K=m.attributesDefault;f=m.attributesForced;if(f){P=f.length;while(P--){s=f[P];q=s.name;h=s.value;if(h==="{$uid}"){h="mce_"+v++}M.map[q]=h;M.push({name:q,value:h})}}if(K){P=K.length;while(P--){s=K[P];q=s.name;if(!(q in M.map)){h=s.value;if(h==="{$uid}"){h="mce_"+v++}M.map[q]=h;M.push({name:q,value:h})}}}if(R){P=R.length;while(P--){if(R[P] in M.map){break}}if(P===-1){k=false}}if(M.map["data-mce-bogus"]){k=false}}if(k){n.start(H,M,N)}}else{k=false}if(A=J[H]){A.lastIndex=F=g.index+g[0].length;if(g=A.exec(D)){if(k){B=D.substr(F,g.index-F)}F=g.index+g[0].length}else{B=D.substr(F);F=D.length}if(k&&B.length>0){n.text(B,true)}if(k){n.end(H)}l.lastIndex=F;continue}if(!N){if(!Q||Q.indexOf("/")!=Q.length-1){z.push({name:H,valid:k})}else{if(k){n.end(H)}}}}else{if(H=g[1]){n.comment(H)}else{if(H=g[2]){n.cdata(H)}else{if(H=g[3]){n.doctype(H)}else{if(H=g[4]){n.pi(H,g[5])}}}}}}F=g.index+g[0].length}if(F<D.length){n.text(j(D.substr(F)))}for(P=z.length-1;P>=0;P--){H=z[P];if(H.valid){n.end(H.name)}}}}})(tinymce);(function(d){var c=/^[ \t\r\n]*$/,e={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next";if(k[f]){return k[f]}if(k!==l){i=k[g];if(i){return i}for(h=k.parent;h&&h!==l;h=h.parent){i=h[g];if(i){return i}}}}function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];this.attributes.map={}}}d.extend(b.prototype,{replace:function(g){var f=this;if(g.parent){g.remove()}f.insert(g,f);f.remove();return f},attr:function(h,l){var f=this,g,j,k;if(typeof h!=="string"){for(j in h){f.attr(j,h[j])}return f}if(g=f.attributes){if(l!==k){if(l===null){if(h in g.map){delete g.map[h];j=g.length;while(j--){if(g[j].name===h){g=g.splice(j,1);return f}}}return f}if(h in g.map){j=g.length;while(j--){if(g[j].name===h){g[j].value=l;break}}}else{g.push({name:h,value:l})}g.map[h]=l;return f}else{return g.map[h]}}},clone:function(){var g=this,n=new b(g.name,g.type),h,f,m,j,k;if(m=g.attributes){k=[];k.map={};for(h=0,f=m.length;h<f;h++){j=m[h];if(j.name!=="id"){k[k.length]={name:j.name,value:j.value};k.map[j.name]=j.value}}n.attributes=k}n.value=g.value;n.shortEnded=g.shortEnded;return n},wrap:function(g){var f=this;f.parent.insert(g,f);g.append(f);return f},unwrap:function(){var f=this,h,g;for(h=f.firstChild;h;){g=h.next;f.insert(h,f,true);h=g}f.remove()},remove:function(){var f=this,h=f.parent,g=f.next,i=f.prev;if(h){if(h.firstChild===f){h.firstChild=g;if(g){g.prev=null}}else{i.next=g}if(h.lastChild===f){h.lastChild=i;if(i){i.next=null}}else{g.prev=i}f.parent=f.next=f.prev=null}return f},append:function(h){var f=this,g;if(h.parent){h.remove()}g=f.lastChild;if(g){g.next=h;h.prev=g;f.lastChild=h}else{f.lastChild=f.firstChild=h}h.parent=f;return h},insert:function(h,f,i){var g;if(h.parent){h.remove()}g=f.parent||this;if(i){if(f===g.firstChild){g.firstChild=h}else{f.prev.next=h}h.prev=f.prev;h.next=f;f.prev=h}else{if(f===g.lastChild){g.lastChild=h}else{f.next.prev=h}h.next=f.next;h.prev=f;f.next=h}h.parent=g;return h},getAll:function(g){var f=this,h,i=[];for(h=f.firstChild;h;h=a(h,f)){if(h.name===g){i.push(h)}}return i},empty:function(){var g=this,f,h,j;if(g.firstChild){f=[];for(j=g.firstChild;j;j=a(j,g)){f.push(j)}h=f.length;while(h--){j=f[h];j.parent=j.firstChild=j.lastChild=j.next=j.prev=null}}g.firstChild=g.lastChild=null;return g},isEmpty:function(k){var f=this,j=f.firstChild,h,g;if(j){do{if(j.type===1){if(j.attributes.map["data-mce-bogus"]){continue}if(k[j.name]){return false}h=j.attributes.length;while(h--){g=j.attributes[h].name;if(g==="name"||g.indexOf("data-")===0){return false}}}if((j.type===3&&!c.test(j.value))){return false}}while(j=a(j,f))}return true},walk:function(f){return a(this,null,f)}});d.extend(b,{create:function(g,f){var i,h;i=new b(g,e[g]||1);if(f){for(h in f){i.attr(h,f[h])}}return i}});d.html.Node=b})(tinymce);(function(b){var a=b.html.Node;b.html.DomParser=function(g,h){var f=this,e={},d=[],i={},c={};g=g||{};g.validate="validate" in g?g.validate:true;g.root_name=g.root_name||"body";f.schema=h=h||new b.html.Schema();function j(m){var o,p,x,v,z,n,q,l,t,u,k,s,y,r;s=b.makeMap("tr,td,th,tbody,thead,tfoot,table");k=h.getNonEmptyElements();for(o=0;o<m.length;o++){p=m[o];if(!p.parent){continue}v=[p];for(x=p.parent;x&&!h.isValidChild(x.name,p.name)&&!s[x.name];x=x.parent){v.push(x)}if(x&&v.length>1){v.reverse();z=n=f.filterNode(v[0].clone());for(t=0;t<v.length-1;t++){if(h.isValidChild(n.name,v[t].name)){q=f.filterNode(v[t].clone());n.append(q)}else{q=n}for(l=v[t].firstChild;l&&l!=v[t+1];){r=l.next;q.append(l);l=r}n=q}if(!z.isEmpty(k)){x.insert(z,v[0],true);x.insert(p,z)}else{x.insert(p,v[0],true)}x=v[0];if(x.isEmpty(k)||x.firstChild===x.lastChild&&x.firstChild.name==="br"){x.empty().remove()}}else{if(p.parent){if(p.name==="li"){y=p.prev;if(y&&(y.name==="ul"||y.name==="ul")){y.append(p);continue}y=p.next;if(y&&(y.name==="ul"||y.name==="ul")){y.insert(p,y.firstChild,true);continue}p.wrap(f.filterNode(new a("ul",1)));continue}if(h.isValidChild(p.parent.name,"div")&&h.isValidChild("div",p.name)){p.wrap(f.filterNode(new a("div",1)))}else{if(p.name==="style"||p.name==="script"){p.empty().remove()}else{p.unwrap()}}}}}}f.filterNode=function(m){var l,k,n;if(k in e){n=i[k];if(n){n.push(m)}else{i[k]=[m]}}l=d.length;while(l--){k=d[l].name;if(k in m.attributes.map){n=c[k];if(n){n.push(m)}else{c[k]=[m]}}}return m};f.addNodeFilter=function(k,l){b.each(b.explode(k),function(m){var n=e[m];if(!n){e[m]=n=[]}n.push(l)})};f.addAttributeFilter=function(k,l){b.each(b.explode(k),function(m){var n;for(n=0;n<d.length;n++){if(d[n].name===m){d[n].callbacks.push(l);return}}d.push({name:m,callbacks:[l]})})};f.parse=function(v,m){var n,H,A,z,C,B,x,r,E,K,y,o,D,J=[],t,k,s,p,u,q;m=m||{};i={};c={};o=b.extend(b.makeMap("script,style,head,html,body,title,meta,param"),h.getBlockElements());u=h.getNonEmptyElements();p=h.children;y=g.validate;q="forced_root_block" in m?m.forced_root_block:g.forced_root_block;s=h.getWhiteSpaceElements();D=/^[ \t\r\n]+/;t=/[ \t\r\n]+$/;k=/[ \t\r\n]+/g;function F(){var L=H.firstChild,l,M;while(L){l=L.next;if(L.type==3||(L.type==1&&L.name!=="p"&&!o[L.name]&&!L.attr("data-mce-type"))){if(!M){M=I(q,1);H.insert(M,L);M.append(L)}else{M.append(L)}}else{M=null}L=l}}function I(l,L){var M=new a(l,L),N;if(l in e){N=i[l];if(N){N.push(M)}else{i[l]=[M]}}return M}function G(M){var N,l,L;for(N=M.prev;N&&N.type===3;){l=N.value.replace(t,"");if(l.length>0){N.value=l;N=N.prev}else{L=N.prev;N.remove();N=L}}}n=new b.html.SaxParser({validate:y,fix_self_closing:!y,cdata:function(l){A.append(I("#cdata",4)).value=l},text:function(M,l){var L;if(!s[A.name]){M=M.replace(k," ");if(A.lastChild&&o[A.lastChild.name]){M=M.replace(D,"")}}if(M.length!==0){L=I("#text",3);L.raw=!!l;A.append(L).value=M}},comment:function(l){A.append(I("#comment",8)).value=l},pi:function(l,L){A.append(I(l,7)).value=L;G(A)},doctype:function(L){var l;l=A.append(I("#doctype",10));l.value=L;G(A)},start:function(l,T,M){var R,O,N,L,P,U,S,Q;N=y?h.getElementRule(l):{};if(N){R=I(N.outputName||l,1);R.attributes=T;R.shortEnded=M;A.append(R);Q=p[A.name];if(Q&&p[R.name]&&!Q[R.name]){J.push(R)}O=d.length;while(O--){P=d[O].name;if(P in T.map){E=c[P];if(E){E.push(R)}else{c[P]=[R]}}}if(o[l]){G(R)}if(!M){A=R}}},end:function(l){var P,M,O,L,N;M=y?h.getElementRule(l):{};if(M){if(o[l]){if(!s[A.name]){for(P=A.firstChild;P&&P.type===3;){O=P.value.replace(D,"");if(O.length>0){P.value=O;P=P.next}else{L=P.next;P.remove();P=L}}for(P=A.lastChild;P&&P.type===3;){O=P.value.replace(t,"");if(O.length>0){P.value=O;P=P.prev}else{L=P.prev;P.remove();P=L}}}P=A.prev;if(P&&P.type===3){O=P.value.replace(D,"");if(O.length>0){P.value=O}else{P.remove()}}}if(M.removeEmpty||M.paddEmpty){if(A.isEmpty(u)){if(M.paddEmpty){A.empty().append(new a("#text","3")).value="\u00a0"}else{if(!A.attributes.map.name){N=A.parent;A.empty().remove();A=N;return}}}}A=A.parent}}},h);H=A=new a(m.context||g.root_name,11);n.parse(v);if(y&&J.length){if(!m.context){j(J)}else{m.invalid=true}}if(q&&H.name=="body"){F()}if(!m.invalid){for(K in i){E=e[K];z=i[K];x=z.length;while(x--){if(!z[x].parent){z.splice(x,1)}}for(C=0,B=E.length;C<B;C++){E[C](z,K,m)}}for(C=0,B=d.length;C<B;C++){E=d[C];if(E.name in c){z=c[E.name];x=z.length;while(x--){if(!z[x].parent){z.splice(x,1)}}for(x=0,r=E.callbacks.length;x<r;x++){E.callbacks[x](z,E.name,m)}}}}return H};if(g.remove_trailing_brs){f.addNodeFilter("br",function(n,m){var r,q=n.length,o,u=h.getBlockElements(),k=h.getNonEmptyElements(),s,p,t;u.body=1;for(r=0;r<q;r++){o=n[r];s=o.parent;if(u[o.parent.name]&&o===s.lastChild){p=o.prev;while(p){t=p.name;if(t!=="span"||p.attr("data-mce-type")!=="bookmark"){if(t!=="br"){break}if(t==="br"){o=null;break}}p=p.prev}if(o){o.remove();if(s.isEmpty(k)){elementRule=h.getElementRule(s.name);if(elementRule){if(elementRule.removeEmpty){s.remove()}else{if(elementRule.paddEmpty){s.empty().append(new b.html.Node("#text",3)).value="\u00a0"}}}}}}}})}}})(tinymce);tinymce.html.Writer=function(e){var c=[],a,b,d,f,g;e=e||{};a=e.indent;b=tinymce.makeMap(e.indent_before||"");d=tinymce.makeMap(e.indent_after||"");f=tinymce.html.Entities.getEncodeFunc(e.entity_encoding||"raw",e.entities);g=e.element_format=="html";return{start:function(m,k,p){var n,j,h,o;if(a&&b[m]&&c.length>0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}c.push("<",m);if(k){for(n=0,j=k.length;n<j;n++){h=k[n];c.push(" ",h.name,'="',f(h.value,true),'"')}}if(!p||g){c[c.length]=">"}else{c[c.length]=" />"}if(p&&a&&d[m]&&c.length>0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}},end:function(h){var i;c.push("</",h,">");if(a&&d[h]&&c.length>0){i=c[c.length-1];if(i.length>0&&i!=="\n"){c.push("\n")}}},text:function(i,h){if(i.length>0){c[c.length]=h?i:f(i)}},cdata:function(h){c.push("<![CDATA[",h,"]]>")},comment:function(h){c.push("<!--",h,"-->")},pi:function(h,i){if(i){c.push("<?",h," ",i,"?>")}else{c.push("<?",h,"?>")}if(a){c.push("\n")}},doctype:function(h){c.push("<!DOCTYPE",h,">",a?"\n":"")},reset:function(){c.length=0},getContent:function(){return c.join("").replace(/\n$/,"")}}};(function(a){a.html.Serializer=function(c,d){var b=this,e=new a.html.Writer(c);c=c||{};c.validate="validate" in c?c.validate:true;b.schema=d=d||new a.html.Schema();b.writer=e;b.serialize=function(h){var g,i;i=c.validate;g={3:function(k,j){e.text(k.value,k.raw)},8:function(j){e.comment(j.value)},7:function(j){e.pi(j.name,j.value)},10:function(j){e.doctype(j.value)},4:function(j){e.cdata(j.value)},11:function(j){if((j=j.firstChild)){do{f(j)}while(j=j.next)}}};e.reset();function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shortEnded;s=k.attributes;if(i&&s&&s.length>1){u=[];u.map={};q=d.getElementRule(k.name);for(n=0,m=q.attributesOrder.length;n<m;n++){r=q.attributesOrder[n];if(r in s.map){p=s.map[r];u.map[r]=p;u.push({name:r,value:p})}}for(n=0,m=s.length;n<m;n++){r=s[n].name;if(!(r in u.map)){p=s.map[r];u.map[r]=p;u.push({name:r,value:p})}}s=u}e.start(k.name,s,o);if(!o){if((k=k.firstChild)){do{f(k)}while(k=k.next)}e.end(j)}}else{t(k)}}if(h.type==1&&!c.inner){f(h)}else{g[11](h)}return e.getContent()}}})(tinymce);(function(h){var f=h.each,e=h.is,d=h.isWebKit,b=h.isIE,c=h.html.Entities,a=/^([a-z0-9],?)+$/i,g=h.html.Schema.blockElementsMap,i=/^[ \t\r\n]*$/;h.create("tinymce.dom.DOMUtils",{doc:null,root:null,files:null,pixelStyles:/^(top|left|bottom|right|width|height|borderWidth)$/,props:{"for":"htmlFor","class":"className",className:"className",checked:"checked",disabled:"disabled",maxlength:"maxLength",readonly:"readOnly",selected:"selected",value:"value",id:"id",name:"name",type:"type"},DOMUtils:function(o,m){var l=this,j,k;l.doc=o;l.win=window;l.files={};l.cssFlicker=false;l.counter=0;l.stdMode=!h.isIE||o.documentMode>=8;l.boxModel=!h.isIE||o.compatMode=="CSS1Compat"||l.stdMode;l.hasOuterHTML="outerHTML" in o.createElement("a");l.settings=m=h.extend({keep_values:false,hex_colors:1},m);l.schema=m.schema;l.styles=new h.html.Styles({url_converter:m.url_converter,url_converter_scope:m.url_converter_scope},m.schema);if(h.isIE6){try{o.execCommand("BackgroundImageCache",false,true)}catch(n){l.cssFlicker=true}}if(b&&m.schema){("abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video").replace(/\w+/g,function(p){o.createElement(p)});for(k in m.schema.getCustomElements()){o.createElement(k)}}h.addUnload(l.destroy,l)},getRoot:function(){var j=this,k=j.settings;return(k&&j.get(k.root_element))||j.doc.body},getViewPort:function(k){var l,j;k=!k?this.win:k;l=k.document;j=this.boxModel?l.documentElement:l.body;return{x:k.pageXOffset||j.scrollLeft,y:k.pageYOffset||j.scrollTop,w:k.innerWidth||j.clientWidth,h:k.innerHeight||j.clientHeight}},getRect:function(m){var l,j=this,k;m=j.get(m);l=j.getPos(m);k=j.getSize(m);return{x:l.x,y:l.y,w:k.w,h:k.h}},getSize:function(m){var k=this,j,l;m=k.get(m);j=k.getStyle(m,"width");l=k.getStyle(m,"height");if(j.indexOf("px")===-1){j=0}if(l.indexOf("px")===-1){l=0}return{w:parseInt(j)||m.offsetWidth||m.clientWidth,h:parseInt(l)||m.offsetHeight||m.clientHeight}},getParent:function(l,k,j){return this.getParents(l,k,j,false)},getParents:function(u,p,l,s){var k=this,j,m=k.settings,q=[];u=k.get(u);s=s===undefined;if(m.strict_root){l=l||k.getRoot()}if(e(p,"string")){j=p;if(p==="*"){p=function(o){return o.nodeType==1}}else{p=function(o){return k.is(o,j)}}}while(u){if(u==l||!u.nodeType||u.nodeType===9){break}if(!p||p(u)){if(s){q.push(u)}else{return u}}u=u.parentNode}return s?q:null},get:function(j){var k;if(j&&this.doc&&typeof(j)=="string"){k=j;j=this.doc.getElementById(j);if(j&&j.id!==k){return this.doc.getElementsByName(k)[1]}}return j},getNext:function(k,j){return this._findSib(k,j,"nextSibling")},getPrev:function(k,j){return this._findSib(k,j,"previousSibling")},select:function(l,k){var j=this;return h.dom.Sizzle(l,j.get(k)||j.get(j.settings.root_element)||j.doc,[])},is:function(l,j){var k;if(l.length===undefined){if(j==="*"){return l.nodeType==1}if(a.test(j)){j=j.toLowerCase().split(/,/);l=l.nodeName.toLowerCase();for(k=j.length-1;k>=0;k--){if(j[k]==l){return true}}return false}}return h.dom.Sizzle.matches(j,l.nodeType?[l]:l).length>0},add:function(m,q,j,l,o){var k=this;return this.run(m,function(s){var r,n;r=e(q,"string")?k.doc.createElement(q):q;k.setAttribs(r,j);if(l){if(l.nodeType){r.appendChild(l)}else{k.setHTML(r,l)}}return !o?s.appendChild(r):r})},create:function(l,j,k){return this.add(this.doc.createElement(l),l,j,k,1)},createHTML:function(r,j,p){var q="",m=this,l;q+="<"+r;for(l in j){if(j.hasOwnProperty(l)){q+=" "+l+'="'+m.encode(j[l])+'"'}}if(typeof(p)!="undefined"){return q+">"+p+"</"+r+">"}return q+" />"},remove:function(j,k){return this.run(j,function(m){var n,l=m.parentNode;if(!l){return null}if(k){while(n=m.firstChild){if(!h.isIE||n.nodeType!==3||n.nodeValue){l.insertBefore(n,m)}else{m.removeChild(n)}}}return l.removeChild(m)})},setStyle:function(m,j,k){var l=this;return l.run(m,function(p){var o,n;o=p.style;j=j.replace(/-(\D)/g,function(r,q){return q.toUpperCase()});if(l.pixelStyles.test(j)&&(h.is(k,"number")||/^[\-0-9\.]+$/.test(k))){k+="px"}switch(j){case"opacity":if(b){o.filter=k===""?"":"alpha(opacity="+(k*100)+")";if(!m.currentStyle||!m.currentStyle.hasLayout){o.display="inline-block"}}o[j]=o["-moz-opacity"]=o["-khtml-opacity"]=k||"";break;case"float":b?o.styleFloat=k:o.cssFloat=k;break;default:o[j]=k||""}if(l.settings.update_styles){l.setAttrib(p,"data-mce-style")}})},getStyle:function(m,j,l){m=this.get(m);if(!m){return}if(this.doc.defaultView&&l){j=j.replace(/[A-Z]/g,function(n){return"-"+n});try{return this.doc.defaultView.getComputedStyle(m,null).getPropertyValue(j)}catch(k){return null}}j=j.replace(/-(\D)/g,function(o,n){return n.toUpperCase()});if(j=="float"){j=b?"styleFloat":"cssFloat"}if(m.currentStyle&&l){return m.currentStyle[j]}return m.style?m.style[j]:undefined},setStyles:function(m,n){var k=this,l=k.settings,j;j=l.update_styles;l.update_styles=0;f(n,function(o,p){k.setStyle(m,p,o)});l.update_styles=j;if(l.update_styles){k.setAttrib(m,l.cssText)}},removeAllAttribs:function(j){return this.run(j,function(m){var l,k=m.attributes;for(l=k.length-1;l>=0;l--){m.removeAttributeNode(k.item(l))}})},setAttrib:function(l,m,j){var k=this;if(!l||!m){return}if(k.settings.strict){m=m.toLowerCase()}return this.run(l,function(o){var n=k.settings;switch(m){case"style":if(!e(j,"string")){f(j,function(p,q){k.setStyle(o,q,p)});return}if(n.keep_values){if(j&&!k._isRes(j)){o.setAttribute("data-mce-style",j,2)}else{o.removeAttribute("data-mce-style",2)}}o.style.cssText=j;break;case"class":o.className=j||"";break;case"src":case"href":if(n.keep_values){if(n.url_converter){j=n.url_converter.call(n.url_converter_scope||k,j,m,o)}k.setAttrib(o,"data-mce-"+m,j,2)}break;case"shape":o.setAttribute("data-mce-style",j);break}if(e(j)&&j!==null&&j.length!==0){o.setAttribute(m,""+j,2)}else{o.removeAttribute(m,2)}})},setAttribs:function(k,l){var j=this;return this.run(k,function(m){f(l,function(o,p){j.setAttrib(m,p,o)})})},getAttrib:function(o,p,l){var j,k=this,m;o=k.get(o);if(!o||o.nodeType!==1){return l===m?false:l}if(!e(l)){l=""}if(/^(src|href|style|coords|shape)$/.test(p)){j=o.getAttribute("data-mce-"+p);if(j){return j}}if(b&&k.props[p]){j=o[k.props[p]];j=j&&j.nodeValue?j.nodeValue:j}if(!j){j=o.getAttribute(p,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(p)){if(o[k.props[p]]===true&&j===""){return p}return j?p:""}if(o.nodeName==="FORM"&&o.getAttributeNode(p)){return o.getAttributeNode(p).nodeValue}if(p==="style"){j=j||o.style.cssText;if(j){j=k.serializeStyle(k.parseStyle(j),o.nodeName);if(k.settings.keep_values&&!k._isRes(j)){o.setAttribute("data-mce-style",j)}}}if(d&&p==="class"&&j){j=j.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(b){switch(p){case"rowspan":case"colspan":if(j===1){j=""}break;case"size":if(j==="+0"||j===20||j===0){j=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(j===0){j=""}break;case"hspace":if(j===-1){j=""}break;case"maxlength":case"tabindex":if(j===32768||j===2147483647||j==="32768"){j=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(j===65535){return p}return l;case"shape":j=j.toLowerCase();break;default:if(p.indexOf("on")===0&&j){j=h._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1",""+j)}}}return(j!==m&&j!==null&&j!=="")?""+j:l},getPos:function(s,m){var k=this,j=0,q=0,o,p=k.doc,l;s=k.get(s);m=m||p.body;if(s){if(s.getBoundingClientRect){s=s.getBoundingClientRect();o=k.boxModel?p.documentElement:p.body;j=s.left+(p.documentElement.scrollLeft||p.body.scrollLeft)-o.clientTop;q=s.top+(p.documentElement.scrollTop||p.body.scrollTop)-o.clientLeft;return{x:j,y:q}}l=s;while(l&&l!=m&&l.nodeType){j+=l.offsetLeft||0;q+=l.offsetTop||0;l=l.offsetParent}l=s.parentNode;while(l&&l!=m&&l.nodeType){j-=l.scrollLeft||0;q-=l.scrollTop||0;l=l.parentNode}}return{x:j,y:q}},parseStyle:function(j){return this.styles.parse(j)},serializeStyle:function(k,j){return this.styles.serialize(k,j)},loadCSS:function(j){var l=this,m=l.doc,k;if(!j){j=""}k=l.select("head")[0];f(j.split(","),function(n){var o;if(l.files[n]){return}l.files[n]=true;o=l.create("link",{rel:"stylesheet",href:h._addVer(n)});if(b&&m.documentMode&&m.recalc){o.onload=function(){if(m.recalc){m.recalc()}o.onload=null}}k.appendChild(o)})},addClass:function(j,k){return this.run(j,function(l){var m;if(!k){return 0}if(this.hasClass(l,k)){return l.className}m=this.removeClass(l,k);return l.className=(m!=""?(m+" "):"")+k})},removeClass:function(l,m){var j=this,k;return j.run(l,function(o){var n;if(j.hasClass(o,m)){if(!k){k=new RegExp("(^|\\s+)"+m+"(\\s+|$)","g")}n=o.className.replace(k," ");n=h.trim(n!=" "?n:"");o.className=n;if(!n){o.removeAttribute("class");o.removeAttribute("className")}return n}return o.className})},hasClass:function(k,j){k=this.get(k);if(!k||!j){return false}return(" "+k.className+" ").indexOf(" "+j+" ")!==-1},show:function(j){return this.setStyle(j,"display","block")},hide:function(j){return this.setStyle(j,"display","none")},isHidden:function(j){j=this.get(j);return !j||j.style.display=="none"||this.getStyle(j,"display")=="none"},uniqueId:function(j){return(!j?"mce_":j)+(this.counter++)},setHTML:function(l,k){var j=this;return j.run(l,function(n){if(b){while(n.firstChild){n.removeChild(n.firstChild)}try{n.innerHTML="<br />"+k;n.removeChild(n.firstChild)}catch(m){n=j.create("div");n.innerHTML="<br />"+k;f(n.childNodes,function(p,o){if(o){n.appendChild(p)}})}}else{n.innerHTML=k}return k})},getOuterHTML:function(l){var k,j=this;l=j.get(l);if(!l){return null}if(l.nodeType===1&&j.hasOuterHTML){return l.outerHTML}k=(l.ownerDocument||j.doc).createElement("body");k.appendChild(l.cloneNode(true));return k.innerHTML},setOuterHTML:function(m,k,n){var j=this;function l(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.lastChild;while(s){j.insertAfter(s.cloneNode(true),p);s=s.previousSibling}j.remove(p)}return this.run(m,function(p){p=j.get(p);if(p.nodeType==1){n=n||p.ownerDocument||j.doc;if(b){try{if(b&&p.nodeType==1){p.outerHTML=k}else{l(p,k,n)}}catch(o){l(p,k,n)}}else{l(p,k,n)}}})},decode:c.decode,encode:c.encodeAllRaw,insertAfter:function(j,k){k=this.get(k);return this.run(j,function(m){var l,n;l=k.parentNode;n=k.nextSibling;if(n){l.insertBefore(m,n)}else{l.appendChild(m)}return m})},isBlock:function(k){var j=k.nodeType;if(j){return !!(j===1&&g[k.nodeName])}return !!g[k]},replace:function(p,m,j){var l=this;if(e(m,"array")){p=p.cloneNode(true)}return l.run(m,function(k){if(j){f(h.grep(k.childNodes),function(n){p.appendChild(n)})}return k.parentNode.replaceChild(p,k)})},rename:function(m,j){var l=this,k;if(m.nodeName!=j.toUpperCase()){k=l.create(j);f(l.getAttribs(m),function(n){l.setAttrib(k,n.nodeName,l.getAttrib(m,n.nodeName))});l.replace(k,m,1)}return k||m},findCommonAncestor:function(l,j){var m=l,k;while(m){k=j;while(k&&m!=k){k=k.parentNode}if(m==k){break}m=m.parentNode}if(!m&&l.ownerDocument){return l.ownerDocument.documentElement}return m},toHex:function(j){var l=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(j);function k(m){m=parseInt(m).toString(16);return m.length>1?m:"0"+m}if(l){j="#"+k(l[1])+k(l[2])+k(l[3]);return j}return j},getClasses:function(){var n=this,j=[],m,o={},p=n.settings.class_filter,l;if(n.classes){return n.classes}function q(r){f(r.imports,function(s){q(s)});f(r.cssRules||r.rules,function(s){switch(s.type||1){case 1:if(s.selectorText){f(s.selectorText.split(","),function(t){t=t.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(t)||!/\.[\w\-]+$/.test(t)){return}l=t;t=h._replace(/.*\.([a-z0-9_\-]+).*/i,"$1",t);if(p&&!(t=p(t,l))){return}if(!o[t]){j.push({"class":t});o[t]=1}})}break;case 3:q(s.styleSheet);break}})}try{f(n.doc.styleSheets,q)}catch(k){}if(j.length>0){n.classes=j}return j},run:function(m,l,k){var j=this,n;if(j.doc&&typeof(m)==="string"){m=j.get(m)}if(!m){return false}k=k||this;if(!m.nodeType&&(m.length||m.length===0)){n=[];f(m,function(p,o){if(p){if(typeof(p)=="string"){p=j.doc.getElementById(p)}n.push(l.call(k,p,o))}});return n}return l.call(k,m)},getAttribs:function(k){var j;k=this.get(k);if(!k){return[]}if(b){j=[];if(k.nodeName=="OBJECT"){return k.attributes}if(k.nodeName==="OPTION"&&this.getAttrib(k,"selected")){j.push({specified:1,nodeName:"selected"})}k.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi,"").replace(/[\w:\-]+/gi,function(l){j.push({specified:1,nodeName:l})});return j}return k.attributes},isEmpty:function(m,k){var r=this,o,n,q,j,l,p;m=m.firstChild;if(m){j=new h.dom.TreeWalker(m);k=k||r.schema?r.schema.getNonEmptyElements():null;do{q=m.nodeType;if(q===1){if(m.getAttribute("data-mce-bogus")){continue}l=m.nodeName.toLowerCase();if(k&&k[l]){p=m.parentNode;if(l==="br"&&r.isBlock(p)&&p.firstChild===m&&p.lastChild===m){continue}return false}n=r.getAttribs(m);o=m.attributes.length;while(o--){l=m.attributes[o].nodeName;if(l==="name"||l==="data-mce-bookmark"){return false}}}if((q===3&&!i.test(m.nodeValue))){return false}}while(m=j.next())}return true},destroy:function(k){var j=this;if(j.events){j.events.destroy()}j.win=j.doc=j.root=j.events=null;if(!k){h.removeUnload(j.destroy)}},createRng:function(){var j=this.doc;return j.createRange?j.createRange():new h.dom.Range(this)},nodeIndex:function(n,o){var j=0,l,m,k;if(n){for(l=n.nodeType,n=n.previousSibling,m=n;n;n=n.previousSibling){k=n.nodeType;if(o&&k==3){if(k==l||!n.nodeValue.length){continue}}j++;l=k}}return j},split:function(n,m,q){var s=this,j=s.createRng(),o,l,p;function k(v){var t,r=v.childNodes,u=v.nodeType;if(u==1&&v.getAttribute("data-mce-type")=="bookmark"){return}for(t=r.length-1;t>=0;t--){k(r[t])}if(u!=9){if(u==3&&v.nodeValue.length>0){if(!s.isBlock(v.parentNode)||h.trim(v.nodeValue).length>0){return}}else{if(u==1){r=v.childNodes;if(r.length==1&&r[0]&&r[0].nodeType==1&&r[0].getAttribute("data-mce-type")=="bookmark"){v.parentNode.insertBefore(r[0],v)}if(r.length||/^(br|hr|input|img)$/i.test(v.nodeName)){return}}}s.remove(v)}return v}if(n&&m){j.setStart(n.parentNode,s.nodeIndex(n));j.setEnd(m.parentNode,s.nodeIndex(m));o=j.extractContents();j=s.createRng();j.setStart(m.parentNode,s.nodeIndex(m)+1);j.setEnd(n.parentNode,s.nodeIndex(n)+1);l=j.extractContents();p=n.parentNode;p.insertBefore(k(o),n);if(q){p.replaceChild(q,m)}else{p.insertBefore(m,n)}p.insertBefore(k(l),n);s.remove(n);return q||m}},bind:function(n,j,m,l){var k=this;if(!k.events){k.events=new h.dom.EventUtils()}return k.events.add(n,j,m,l||this)},unbind:function(m,j,l){var k=this;if(!k.events){k.events=new h.dom.EventUtils()}return k.events.remove(m,j,l)},_findSib:function(m,j,k){var l=this,n=j;if(m){if(e(n,"string")){n=function(o){return l.is(o,j)}}for(m=m[k];m;m=m[k]){if(n(m)){return m}}}return null},_isRes:function(j){return/^(top|left|bottom|right|width|height)/i.test(j)||/;\s*(top|left|bottom|right|width|height)/i.test(j)}});h.DOM=new h.dom.DOMUtils(document,{process_html:0})})(tinymce);(function(a){function b(c){var N=this,e=c.doc,S=0,E=1,j=2,D=true,R=false,U="startOffset",h="startContainer",P="endContainer",z="endOffset",k=tinymce.extend,n=c.nodeIndex;k(N,{startContainer:e,startOffset:0,endContainer:e,endOffset:0,collapsed:D,commonAncestorContainer:e,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:q,setEnd:s,setStartBefore:g,setStartAfter:I,setEndBefore:J,setEndAfter:u,collapse:A,selectNode:x,selectNodeContents:F,compareBoundaryPoints:v,deleteContents:p,extractContents:H,cloneContents:d,insertNode:C,surroundContents:M,cloneRange:K});function q(V,t){B(D,V,t)}function s(V,t){B(R,V,t)}function g(t){q(t.parentNode,n(t))}function I(t){q(t.parentNode,n(t)+1)}function J(t){s(t.parentNode,n(t))}function u(t){s(t.parentNode,n(t)+1)}function A(t){if(t){N[P]=N[h];N[z]=N[U]}else{N[h]=N[P];N[U]=N[z]}N.collapsed=D}function x(t){g(t);u(t)}function F(t){q(t,0);s(t,t.nodeType===1?t.childNodes.length:t.nodeValue.length)}function v(Y,t){var ab=N[h],W=N[U],aa=N[P],V=N[z],Z=t.startContainer,ad=t.startOffset,X=t.endContainer,ac=t.endOffset;if(Y===0){return G(ab,W,Z,ad)}if(Y===1){return G(aa,V,Z,ad)}if(Y===2){return G(aa,V,X,ac)}if(Y===3){return G(ab,W,X,ac)}}function p(){m(j)}function H(){return m(S)}function d(){return m(E)}function C(Y){var V=this[h],t=this[U],X,W;if((V.nodeType===3||V.nodeType===4)&&V.nodeValue){if(!t){V.parentNode.insertBefore(Y,V)}else{if(t>=V.nodeValue.length){c.insertAfter(Y,V)}else{X=V.splitText(t);V.parentNode.insertBefore(Y,X)}}}else{if(V.childNodes.length>0){W=V.childNodes[t]}if(W){V.insertBefore(Y,W)}else{V.appendChild(Y)}}}function M(V){var t=N.extractContents();N.insertNode(V);V.appendChild(t);N.selectNode(V)}function K(){return k(new b(c),{startContainer:N[h],startOffset:N[U],endContainer:N[P],endOffset:N[z],collapsed:N.collapsed,commonAncestorContainer:N.commonAncestorContainer})}function O(t,V){var W;if(t.nodeType==3){return t}if(V<0){return t}W=t.firstChild;while(W&&V>0){--V;W=W.nextSibling}if(W){return W}return t}function l(){return(N[h]==N[P]&&N[U]==N[z])}function G(X,Z,V,Y){var aa,W,t,ab,ad,ac;if(X==V){if(Z==Y){return 0}if(Z<Y){return -1}return 1}aa=V;while(aa&&aa.parentNode!=X){aa=aa.parentNode}if(aa){W=0;t=X.firstChild;while(t!=aa&&W<Z){W++;t=t.nextSibling}if(Z<=W){return -1}return 1}aa=X;while(aa&&aa.parentNode!=V){aa=aa.parentNode}if(aa){W=0;t=V.firstChild;while(t!=aa&&W<Y){W++;t=t.nextSibling}if(W<Y){return -1}return 1}ab=c.findCommonAncestor(X,V);ad=X;while(ad&&ad.parentNode!=ab){ad=ad.parentNode}if(!ad){ad=ab}ac=V;while(ac&&ac.parentNode!=ab){ac=ac.parentNode}if(!ac){ac=ab}if(ad==ac){return 0}t=ab.firstChild;while(t){if(t==ad){return -1}if(t==ac){return 1}t=t.nextSibling}}function B(V,Y,X){var t,W;if(V){N[h]=Y;N[U]=X}else{N[P]=Y;N[z]=X}t=N[P];while(t.parentNode){t=t.parentNode}W=N[h];while(W.parentNode){W=W.parentNode}if(W==t){if(G(N[h],N[U],N[P],N[z])>0){N.collapse(V)}}else{N.collapse(V)}N.collapsed=l();N.commonAncestorContainer=c.findCommonAncestor(N[h],N[P])}function m(ab){var aa,X=0,ad=0,V,Z,W,Y,t,ac;if(N[h]==N[P]){return f(ab)}for(aa=N[P],V=aa.parentNode;V;aa=V,V=V.parentNode){if(V==N[h]){return r(aa,ab)}++X}for(aa=N[h],V=aa.parentNode;V;aa=V,V=V.parentNode){if(V==N[P]){return T(aa,ab)}++ad}Z=ad-X;W=N[h];while(Z>0){W=W.parentNode;Z--}Y=N[P];while(Z<0){Y=Y.parentNode;Z++}for(t=W.parentNode,ac=Y.parentNode;t!=ac;t=t.parentNode,ac=ac.parentNode){W=t;Y=ac}return o(W,Y,ab)}function f(Z){var ab,Y,X,aa,t,W,V;if(Z!=j){ab=e.createDocumentFragment()}if(N[U]==N[z]){return ab}if(N[h].nodeType==3){Y=N[h].nodeValue;X=Y.substring(N[U],N[z]);if(Z!=E){N[h].deleteData(N[U],N[z]-N[U]);N.collapse(D)}if(Z==j){return}ab.appendChild(e.createTextNode(X));return ab}aa=O(N[h],N[U]);t=N[z]-N[U];while(t>0){W=aa.nextSibling;V=y(aa,Z);if(ab){ab.appendChild(V)}--t;aa=W}if(Z!=E){N.collapse(D)}return ab}function r(ab,Y){var aa,Z,V,t,X,W;if(Y!=j){aa=e.createDocumentFragment()}Z=i(ab,Y);if(aa){aa.appendChild(Z)}V=n(ab);t=V-N[U];if(t<=0){if(Y!=E){N.setEndBefore(ab);N.collapse(R)}return aa}Z=ab.previousSibling;while(t>0){X=Z.previousSibling;W=y(Z,Y);if(aa){aa.insertBefore(W,aa.firstChild)}--t;Z=X}if(Y!=E){N.setEndBefore(ab);N.collapse(R)}return aa}function T(Z,Y){var ab,V,aa,t,X,W;if(Y!=j){ab=e.createDocumentFragment()}aa=Q(Z,Y);if(ab){ab.appendChild(aa)}V=n(Z);++V;t=N[z]-V;aa=Z.nextSibling;while(t>0){X=aa.nextSibling;W=y(aa,Y);if(ab){ab.appendChild(W)}--t;aa=X}if(Y!=E){N.setStartAfter(Z);N.collapse(D)}return ab}function o(Z,t,ac){var W,ae,Y,aa,ab,V,ad,X;if(ac!=j){ae=e.createDocumentFragment()}W=Q(Z,ac);if(ae){ae.appendChild(W)}Y=Z.parentNode;aa=n(Z);ab=n(t);++aa;V=ab-aa;ad=Z.nextSibling;while(V>0){X=ad.nextSibling;W=y(ad,ac);if(ae){ae.appendChild(W)}ad=X;--V}W=i(t,ac);if(ae){ae.appendChild(W)}if(ac!=E){N.setStartAfter(Z);N.collapse(D)}return ae}function i(aa,ab){var W=O(N[P],N[z]-1),ac,Z,Y,t,V,X=W!=N[P];if(W==aa){return L(W,X,R,ab)}ac=W.parentNode;Z=L(ac,R,R,ab);while(ac){while(W){Y=W.previousSibling;t=L(W,X,R,ab);if(ab!=j){Z.insertBefore(t,Z.firstChild)}X=D;W=Y}if(ac==aa){return Z}W=ac.previousSibling;ac=ac.parentNode;V=L(ac,R,R,ab);if(ab!=j){V.appendChild(Z)}Z=V}}function Q(aa,ab){var X=O(N[h],N[U]),Y=X!=N[h],ac,Z,W,t,V;if(X==aa){return L(X,Y,D,ab)}ac=X.parentNode;Z=L(ac,R,D,ab);while(ac){while(X){W=X.nextSibling;t=L(X,Y,D,ab);if(ab!=j){Z.appendChild(t)}Y=D;X=W}if(ac==aa){return Z}X=ac.nextSibling;ac=ac.parentNode;V=L(ac,R,D,ab);if(ab!=j){V.appendChild(Z)}Z=V}}function L(t,Y,ab,ac){var X,W,Z,V,aa;if(Y){return y(t,ac)}if(t.nodeType==3){X=t.nodeValue;if(ab){V=N[U];W=X.substring(V);Z=X.substring(0,V)}else{V=N[z];W=X.substring(0,V);Z=X.substring(V)}if(ac!=E){t.nodeValue=Z}if(ac==j){return}aa=t.cloneNode(R);aa.nodeValue=W;return aa}if(ac==j){return}return t.cloneNode(R)}function y(V,t){if(t!=j){return t==E?V.cloneNode(D):V}V.parentNode.removeChild(V)}}a.Range=b})(tinymce.dom);(function(){function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=0,q,n,m,l,o,r,p=-1,s;k=i.duplicate();k.collapse(j);s=k.parentElement();if(s.ownerDocument!==d.dom.doc){return}while(s.contentEditable==="false"){s=s.parentNode}if(!s.hasChildNodes()){return{node:s,inside:1}}m=s.children;q=m.length-1;while(t<=q){r=Math.floor((t+q)/2);l=m[r];k.moveToElementText(l);p=k.compareEndPoints(j?"StartToStart":"EndToEnd",i);if(p>0){q=r-1}else{if(p<0){t=r+1}else{return{node:l}}}}if(p<0){if(!l){k.moveToElementText(s);k.collapse(true);l=s;n=true}else{k.collapse(false)}k.setEndPoint(j?"EndToStart":"EndToEnd",i);if(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)>0){k=i.duplicate();k.collapse(j);o=-1;while(s==k.parentElement()){if(k.move("character",-1)==0){break}o++}}o=o||k.text.replace("\r\n"," ").length}else{k.collapse(true);k.setEndPoint(j?"StartToStart":"StartToEnd",i);o=k.text.replace("\r\n"," ").length}return{node:l,position:p,offset:o,inside:n}}function g(){var i=d.getRng(),r=h.createRng(),l,k,p,q,m,j;l=i.item?i.item(0):i.parentElement();if(l.ownerDocument!=h.doc){return r}k=d.isCollapsed();if(i.item){r.setStart(l.parentNode,h.nodeIndex(l));r.setEnd(r.startContainer,r.startOffset+1);return r}function o(A){var u=e(i,A),s,y,z=0,x,v,t;s=u.node;y=u.offset;if(u.inside&&!s.hasChildNodes()){r[A?"setStart":"setEnd"](s,0);return}if(y===v){r[A?"setStartBefore":"setEndAfter"](s);return}if(u.position<0){x=u.inside?s.firstChild:s.nextSibling;if(!x){r[A?"setStartAfter":"setEndAfter"](s);return}if(!y){if(x.nodeType==3){r[A?"setStart":"setEnd"](x,0)}else{r[A?"setStartBefore":"setEndBefore"](x)}return}while(x){t=x.nodeValue;z+=t.length;if(z>=y){s=x;z-=y;z=t.length-z;break}x=x.nextSibling}}else{x=s.previousSibling;if(!x){return r[A?"setStartBefore":"setEndBefore"](s)}if(!y){if(s.nodeType==3){r[A?"setStart":"setEnd"](x,s.nodeValue.length)}else{r[A?"setStartAfter":"setEndAfter"](x)}return}while(x){z+=x.nodeValue.length;if(z>=y){s=x;z-=y;break}x=x.previousSibling}}r[A?"setStart":"setEnd"](s,z)}try{o(true);if(!k){o()}}catch(n){if(n.number==-2147024809){m=b.getBookmark(2);p=i.duplicate();p.collapse(true);l=p.parentElement();if(!k){p=i.duplicate();p.collapse(false);q=p.parentElement();q.innerHTML=q.innerHTML}l.innerHTML=l.innerHTML;b.moveToBookmark(m);i=d.getRng();o(true);if(!k){o()}}else{throw n}}return r}this.getBookmark=function(m){var j=d.getRng(),o,i,l={};function n(u){var u,t,p,s,r,q=[];t=u.parentNode;p=h.getRoot().parentNode;while(t!=p){s=t.children;r=s.length;while(r--){if(u===s[r]){q.push(r);break}}u=t;t=t.parentNode}return q}function k(q){var p;p=e(j,q);if(p){return{position:p.position,offset:p.offset,indexes:n(p.node),inside:p.inside}}}if(m===2){if(!j.item){l.start=k(true);if(!d.isCollapsed()){l.end=k()}}else{l.start={ctrl:true,indexes:n(j.item(0))}}}return l};this.moveToBookmark=function(k){var j,i=h.doc.body;function m(o){var r,q,n,p;r=h.getRoot();for(q=o.length-1;q>=0;q--){p=r.children;n=o[q];if(n<=p.length-1){r=p[n]}}return r}function l(r){var n=k[r?"start":"end"],q,p,o;if(n){q=n.position>0;p=i.createTextRange();p.moveToElementText(m(n.indexes));offset=n.offset;if(offset!==o){p.collapse(n.inside||q);p.moveStart("character",q?-offset:offset)}else{p.collapse(r)}j.setEndPoint(r?"StartToStart":"EndToStart",p);if(r){j.collapse(true)}}}if(k.start){if(k.start.ctrl){j=i.createControlRange();j.addElement(m(k.start.indexes));j.select()}else{j=i.createTextRange();l(true);l();j.select()}}};this.addRange=function(i){var n,l,k,p,s,q,r=d.dom.doc,m=r.body;function j(z){var u,y,t,x,v;t=h.create("a");u=z?k:s;y=z?p:q;x=n.duplicate();if(u==r||u==r.documentElement){u=m;y=0}if(u.nodeType==3){u.parentNode.insertBefore(t,u);x.moveToElementText(t);x.moveStart("character",y);h.remove(t);n.setEndPoint(z?"StartToStart":"EndToEnd",x)}else{v=u.childNodes;if(v.length){if(y>=v.length){h.insertAfter(t,v[v.length-1])}else{u.insertBefore(t,v[y])}x.moveToElementText(t)}else{t=r.createTextNode("\uFEFF");u.appendChild(t);x.moveToElementText(t.parentNode);x.collapse(c)}n.setEndPoint(z?"StartToStart":"EndToEnd",x);h.remove(t)}}k=i.startContainer;p=i.startOffset;s=i.endContainer;q=i.endOffset;n=m.createTextRange();if(k==s&&k.nodeType==1&&p==q-1){if(p==q-1){try{l=m.createControlRange();l.addElement(k.childNodes[p]);l.select();return}catch(o){}}}j(true);j();n.select()};this.getRangeAt=g}tinymce.dom.TridentSelection=a})();(function(){var p=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,j=0,d=Object.prototype.toString,o=false,i=true;[0,0].sort(function(){i=false;return 0});var b=function(v,e,z,A){z=z||[];e=e||document;var C=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!v||typeof v!=="string"){return z}var x=[],s,E,H,r,u=true,t=b.isXML(e),B=v,D,G,F,y;do{p.exec("");s=p.exec(B);if(s){B=s[3];x.push(s[1]);if(s[2]){r=s[3];break}}}while(s);if(x.length>1&&k.exec(v)){if(x.length===2&&f.relative[x[0]]){E=h(x[0]+x[1],e)}else{E=f.relative[x[0]]?[e]:b(x.shift(),e);while(x.length){v=x.shift();if(f.relative[v]){v+=x.shift()}E=h(v,E)}}}else{if(!A&&x.length>1&&e.nodeType===9&&!t&&f.match.ID.test(x[0])&&!f.match.ID.test(x[x.length-1])){D=b.find(x.shift(),e,t);e=D.expr?b.filter(D.expr,D.set)[0]:D.set[0]}if(e){D=A?{expr:x.pop(),set:a(A)}:b.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&e.parentNode?e.parentNode:e,t);E=D.expr?b.filter(D.expr,D.set):D.set;if(x.length>0){H=a(E)}else{u=false}while(x.length){G=x.pop();F=G;if(!f.relative[G]){G=""}else{F=x.pop()}if(F==null){F=e}f.relative[G](H,F,t)}}else{H=x=[]}}if(!H){H=E}if(!H){b.error(G||v)}if(d.call(H)==="[object Array]"){if(!u){z.push.apply(z,H)}else{if(e&&e.nodeType===1){for(y=0;H[y]!=null;y++){if(H[y]&&(H[y]===true||H[y].nodeType===1&&b.contains(e,H[y]))){z.push(E[y])}}}else{for(y=0;H[y]!=null;y++){if(H[y]&&H[y].nodeType===1){z.push(E[y])}}}}}else{a(H,z)}if(r){b(r,C,z,A);b.uniqueSort(z)}return z};b.uniqueSort=function(r){if(c){o=i;r.sort(c);if(o){for(var e=1;e<r.length;e++){if(r[e]===r[e-1]){r.splice(e--,1)}}}}return r};b.matches=function(e,r){return b(e,null,null,r)};b.find=function(y,e,z){var x;if(!y){return[]}for(var t=0,s=f.order.length;t<s;t++){var v=f.order[t],u;if((u=f.leftMatch[v].exec(y))){var r=u[1];u.splice(1,1);if(r.substr(r.length-1)!=="\\"){u[1]=(u[1]||"").replace(/\\/g,"");x=f.find[v](u,e,z);if(x!=null){y=y.replace(f.match[v],"");break}}}}if(!x){x=e.getElementsByTagName("*")}return{set:x,expr:y}};b.filter=function(C,B,F,u){var s=C,H=[],z=B,x,e,y=B&&B[0]&&b.isXML(B[0]);while(C&&B.length){for(var A in f.filter){if((x=f.leftMatch[A].exec(C))!=null&&x[2]){var r=f.filter[A],G,E,t=x[1];e=false;x.splice(1,1);if(t.substr(t.length-1)==="\\"){continue}if(z===H){H=[]}if(f.preFilter[A]){x=f.preFilter[A](x,z,F,H,u,y);if(!x){e=G=true}else{if(x===true){continue}}}if(x){for(var v=0;(E=z[v])!=null;v++){if(E){G=r(E,x,v,z);var D=u^!!G;if(F&&G!=null){if(D){e=true}else{z[v]=false}}else{if(D){H.push(E);e=true}}}}}if(G!==undefined){if(!F){z=H}C=C.replace(f.match[A],"");if(!e){return[]}break}}}if(C===s){if(e==null){b.error(C)}else{break}}s=C}return z};b.error=function(e){throw"Syntax error, unrecognized expression: "+e};var f=b.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(e){return e.getAttribute("href")}},relative:{"+":function(x,r){var t=typeof r==="string",v=t&&!/\W/.test(r),y=t&&!v;if(v){r=r.toLowerCase()}for(var s=0,e=x.length,u;s<e;s++){if((u=x[s])){while((u=u.previousSibling)&&u.nodeType!==1){}x[s]=y||u&&u.nodeName.toLowerCase()===r?u||false:u===r}}if(y){b.filter(r,x,true)}},">":function(x,r){var u=typeof r==="string",v,s=0,e=x.length;if(u&&!/\W/.test(r)){r=r.toLowerCase();for(;s<e;s++){v=x[s];if(v){var t=v.parentNode;x[s]=t.nodeName.toLowerCase()===r?t:false}}}else{for(;s<e;s++){v=x[s];if(v){x[s]=u?v.parentNode:v.parentNode===r}}if(u){b.filter(r,x,true)}}},"":function(t,r,v){var s=j++,e=q,u;if(typeof r==="string"&&!/\W/.test(r)){r=r.toLowerCase();u=r;e=n}e("parentNode",r,s,t,u,v)},"~":function(t,r,v){var s=j++,e=q,u;if(typeof r==="string"&&!/\W/.test(r)){r=r.toLowerCase();u=r;e=n}e("previousSibling",r,s,t,u,v)}},find:{ID:function(r,s,t){if(typeof s.getElementById!=="undefined"&&!t){var e=s.getElementById(r[1]);return e?[e]:[]}},NAME:function(s,v){if(typeof v.getElementsByName!=="undefined"){var r=[],u=v.getElementsByName(s[1]);for(var t=0,e=u.length;t<e;t++){if(u[t].getAttribute("name")===s[1]){r.push(u[t])}}return r.length===0?null:r}},TAG:function(e,r){return r.getElementsByTagName(e[1])}},preFilter:{CLASS:function(t,r,s,e,x,y){t=" "+t[1].replace(/\\/g,"")+" ";if(y){return t}for(var u=0,v;(v=r[u])!=null;u++){if(v){if(x^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(t)>=0)){if(!s){e.push(v)}}else{if(s){r[u]=false}}}}return false},ID:function(e){return e[1].replace(/\\/g,"")},TAG:function(r,e){return r[1].toLowerCase()},CHILD:function(e){if(e[1]==="nth"){var r=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(r[1]+(r[2]||1))-0;e[3]=r[3]-0}e[0]=j++;return e},ATTR:function(u,r,s,e,v,x){var t=u[1].replace(/\\/g,"");if(!x&&f.attrMap[t]){u[1]=f.attrMap[t]}if(u[2]==="~="){u[4]=" "+u[4]+" "}return u},PSEUDO:function(u,r,s,e,v){if(u[1]==="not"){if((p.exec(u[3])||"").length>1||/^\w/.test(u[3])){u[3]=b(u[3],null,null,r)}else{var t=b.filter(u[3],r,s,true^v);if(!s){e.push.apply(e,t)}return false}}else{if(f.match.POS.test(u[0])||f.match.CHILD.test(u[0])){return true}}return u},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){e.parentNode.selectedIndex;return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(s,r,e){return !!b(e[3],s).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(e){return"text"===e.type},radio:function(e){return"radio"===e.type},checkbox:function(e){return"checkbox"===e.type},file:function(e){return"file"===e.type},password:function(e){return"password"===e.type},submit:function(e){return"submit"===e.type},image:function(e){return"image"===e.type},reset:function(e){return"reset"===e.type},button:function(e){return"button"===e.type||e.nodeName.toLowerCase()==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)}},setFilters:{first:function(r,e){return e===0},last:function(s,r,e,t){return r===t.length-1},even:function(r,e){return e%2===0},odd:function(r,e){return e%2===1},lt:function(s,r,e){return r<e[3]-0},gt:function(s,r,e){return r>e[3]-0},nth:function(s,r,e){return e[3]-0===r},eq:function(s,r,e){return e[3]-0===r}},filter:{PSEUDO:function(s,y,x,z){var e=y[1],r=f.filters[e];if(r){return r(s,x,y,z)}else{if(e==="contains"){return(s.textContent||s.innerText||b.getText([s])||"").indexOf(y[3])>=0}else{if(e==="not"){var t=y[3];for(var v=0,u=t.length;v<u;v++){if(t[v]===s){return false}}return true}else{b.error("Syntax error, unrecognized expression: "+e)}}}},CHILD:function(e,t){var x=t[1],r=e;switch(x){case"only":case"first":while((r=r.previousSibling)){if(r.nodeType===1){return false}}if(x==="first"){return true}r=e;case"last":while((r=r.nextSibling)){if(r.nodeType===1){return false}}return true;case"nth":var s=t[2],A=t[3];if(s===1&&A===0){return true}var v=t[0],z=e.parentNode;if(z&&(z.sizcache!==v||!e.nodeIndex)){var u=0;for(r=z.firstChild;r;r=r.nextSibling){if(r.nodeType===1){r.nodeIndex=++u}}z.sizcache=v}var y=e.nodeIndex-A;if(s===0){return y===0}else{return(y%s===0&&y/s>=0)}}},ID:function(r,e){return r.nodeType===1&&r.getAttribute("id")===e},TAG:function(r,e){return(e==="*"&&r.nodeType===1)||r.nodeName.toLowerCase()===e},CLASS:function(r,e){return(" "+(r.className||r.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(v,t){var s=t[1],e=f.attrHandle[s]?f.attrHandle[s](v):v[s]!=null?v[s]:v.getAttribute(s),x=e+"",u=t[2],r=t[4];return e==null?u==="!=":u==="="?x===r:u==="*="?x.indexOf(r)>=0:u==="~="?(" "+x+" ").indexOf(r)>=0:!r?x&&e!==false:u==="!="?x!==r:u==="^="?x.indexOf(r)===0:u==="$="?x.substr(x.length-r.length)===r:u==="|="?x===r||x.substr(0,r.length+1)===r+"-":false},POS:function(u,r,s,v){var e=r[2],t=f.setFilters[e];if(t){return t(u,s,r,v)}}}};var k=f.match.POS,g=function(r,e){return"\\"+(e-0+1)};for(var m in f.match){f.match[m]=new RegExp(f.match[m].source+(/(?![^\[]*\])(?![^\(]*\))/.source));f.leftMatch[m]=new RegExp(/(^(?:.|\r|\n)*?)/.source+f.match[m].source.replace(/\\(\d+)/g,g))}var a=function(r,e){r=Array.prototype.slice.call(r,0);if(e){e.push.apply(e,r);return e}return r};try{Array.prototype.slice.call(document.documentElement.childNodes,0)[0].nodeType}catch(l){a=function(u,t){var r=t||[],s=0;if(d.call(u)==="[object Array]"){Array.prototype.push.apply(r,u)}else{if(typeof u.length==="number"){for(var e=u.length;s<e;s++){r.push(u[s])}}else{for(;u[s];s++){r.push(u[s])}}}return r}}var c;if(document.documentElement.compareDocumentPosition){c=function(r,e){if(!r.compareDocumentPosition||!e.compareDocumentPosition){if(r==e){o=true}return r.compareDocumentPosition?-1:1}var s=r.compareDocumentPosition(e)&4?-1:r===e?0:1;if(s===0){o=true}return s}}else{if("sourceIndex" in document.documentElement){c=function(r,e){if(!r.sourceIndex||!e.sourceIndex){if(r==e){o=true}return r.sourceIndex?-1:1}var s=r.sourceIndex-e.sourceIndex;if(s===0){o=true}return s}}else{if(document.createRange){c=function(t,r){if(!t.ownerDocument||!r.ownerDocument){if(t==r){o=true}return t.ownerDocument?-1:1}var s=t.ownerDocument.createRange(),e=r.ownerDocument.createRange();s.setStart(t,0);s.setEnd(t,0);e.setStart(r,0);e.setEnd(r,0);var u=s.compareBoundaryPoints(Range.START_TO_END,e);if(u===0){o=true}return u}}}}b.getText=function(e){var r="",t;for(var s=0;e[s];s++){t=e[s];if(t.nodeType===3||t.nodeType===4){r+=t.nodeValue}else{if(t.nodeType!==8){r+=b.getText(t.childNodes)}}}return r};(function(){var r=document.createElement("div"),s="script"+(new Date()).getTime();r.innerHTML="<a name='"+s+"'/>";var e=document.documentElement;e.insertBefore(r,e.firstChild);if(document.getElementById(s)){f.find.ID=function(u,v,x){if(typeof v.getElementById!=="undefined"&&!x){var t=v.getElementById(u[1]);return t?t.id===u[1]||typeof t.getAttributeNode!=="undefined"&&t.getAttributeNode("id").nodeValue===u[1]?[t]:undefined:[]}};f.filter.ID=function(v,t){var u=typeof v.getAttributeNode!=="undefined"&&v.getAttributeNode("id");return v.nodeType===1&&u&&u.nodeValue===t}}e.removeChild(r);e=r=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){f.find.TAG=function(r,v){var u=v.getElementsByTagName(r[1]);if(r[1]==="*"){var t=[];for(var s=0;u[s];s++){if(u[s].nodeType===1){t.push(u[s])}}u=t}return u}}e.innerHTML="<a href='#'></a>";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){f.attrHandle.href=function(r){return r.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=b,s=document.createElement("div");s.innerHTML="<p class='TEST'></p>";if(s.querySelectorAll&&s.querySelectorAll(".TEST").length===0){return}b=function(x,v,t,u){v=v||document;if(!u&&v.nodeType===9&&!b.isXML(v)){try{return a(v.querySelectorAll(x),t)}catch(y){}}return e(x,v,t,u)};for(var r in e){b[r]=e[r]}s=null})()}(function(){var e=document.createElement("div");e.innerHTML="<div class='test e'></div><div class='test'></div>";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}f.order.splice(1,0,"CLASS");f.find.CLASS=function(r,s,t){if(typeof s.getElementsByClassName!=="undefined"&&!t){return s.getElementsByClassName(r[1])}};e=null})();function n(r,x,v,A,y,z){for(var t=0,s=A.length;t<s;t++){var e=A[t];if(e){e=e[r];var u=false;while(e){if(e.sizcache===v){u=A[e.sizset];break}if(e.nodeType===1&&!z){e.sizcache=v;e.sizset=t}if(e.nodeName.toLowerCase()===x){u=e;break}e=e[r]}A[t]=u}}}function q(r,x,v,A,y,z){for(var t=0,s=A.length;t<s;t++){var e=A[t];if(e){e=e[r];var u=false;while(e){if(e.sizcache===v){u=A[e.sizset];break}if(e.nodeType===1){if(!z){e.sizcache=v;e.sizset=t}if(typeof x!=="string"){if(e===x){u=true;break}}else{if(b.filter(x,[e]).length>0){u=e;break}}}e=e[r]}A[t]=u}}}b.contains=document.compareDocumentPosition?function(r,e){return !!(r.compareDocumentPosition(e)&16)}:function(r,e){return r!==e&&(r.contains?r.contains(e):true)};b.isXML=function(e){var r=(e?e.ownerDocument||e:0).documentElement;return r?r.nodeName!=="HTML":false};var h=function(e,y){var t=[],u="",v,s=y.nodeType?[y]:y;while((v=f.match.PSEUDO.exec(e))){u+=v[0];e=e.replace(f.match.PSEUDO,"")}e=f.relative[e]?e+"*":e;for(var x=0,r=s.length;x<r;x++){b(e,s[x],t)}return b.filter(u,t)};window.tinymce.dom.Sizzle=b})();(function(d){var f=d.each,c=d.DOM,b=d.isIE,e=d.isWebKit,a;d.create("tinymce.dom.EventUtils",{EventUtils:function(){this.inits=[];this.events=[]},add:function(m,p,l,j){var g,h=this,i=h.events,k;if(p instanceof Array){k=[];f(p,function(o){k.push(h.add(m,o,l,j))});return k}if(m&&m.hasOwnProperty&&m instanceof Array){k=[];f(m,function(n){n=c.get(n);k.push(h.add(n,p,l,j))});return k}m=c.get(m);if(!m){return}g=function(n){if(h.disabled){return}n=n||window.event;if(n&&b){if(!n.target){n.target=n.srcElement}d.extend(n,h._stoppers)}if(!j){return l(n)}return l.call(j,n)};if(p=="unload"){d.unloads.unshift({func:g});return g}if(p=="init"){if(h.domLoaded){g()}else{h.inits.push(g)}return g}i.push({obj:m,name:p,func:l,cfunc:g,scope:j});h._add(m,p,g);return l},remove:function(l,m,k){var h=this,g=h.events,i=false,j;if(l&&l.hasOwnProperty&&l instanceof Array){j=[];f(l,function(n){n=c.get(n);j.push(h.remove(n,m,k))});return j}l=c.get(l);f(g,function(o,n){if(o.obj==l&&o.name==m&&(!k||(o.func==k||o.cfunc==k))){g.splice(n,1);h._remove(l,m,o.cfunc);i=true;return false}});return i},clear:function(l){var j=this,g=j.events,h,k;if(l){l=c.get(l);for(h=g.length-1;h>=0;h--){k=g[h];if(k.obj===l){j._remove(k.obj,k.name,k.cfunc);k.obj=k.cfunc=null;g.splice(h,1)}}}},cancel:function(g){if(!g){return false}this.stop(g);return this.prevent(g)},stop:function(g){if(g.stopPropagation){g.stopPropagation()}else{g.cancelBubble=true}return false},prevent:function(g){if(g.preventDefault){g.preventDefault()}else{g.returnValue=false}return false},destroy:function(){var g=this;f(g.events,function(j,h){g._remove(j.obj,j.name,j.cfunc);j.obj=j.cfunc=null});g.events=[];g=null},_add:function(h,i,g){if(h.attachEvent){h.attachEvent("on"+i,g)}else{if(h.addEventListener){h.addEventListener(i,g,false)}else{h["on"+i]=g}}},_remove:function(i,j,h){if(i){try{if(i.detachEvent){i.detachEvent("on"+j,h)}else{if(i.removeEventListener){i.removeEventListener(j,h,false)}else{i["on"+j]=null}}}catch(g){}}},_pageInit:function(h){var g=this;if(g.domLoaded){return}g.domLoaded=true;f(g.inits,function(i){i()});g.inits=[]},_wait:function(i){var g=this,h=i.document;if(i.tinyMCE_GZ&&tinyMCE_GZ.loaded){g.domLoaded=1;return}if(h.attachEvent){h.attachEvent("onreadystatechange",function(){if(h.readyState==="complete"){h.detachEvent("onreadystatechange",arguments.callee);g._pageInit(i)}});if(h.documentElement.doScroll&&i==i.top){(function(){if(g.domLoaded){return}try{h.documentElement.doScroll("left")}catch(j){setTimeout(arguments.callee,0);return}g._pageInit(i)})()}}else{if(h.addEventListener){g._add(i,"DOMContentLoaded",function(){g._pageInit(i)})}}g._add(i,"load",function(){g._pageInit(i)})},_stoppers:{preventDefault:function(){this.returnValue=false},stopPropagation:function(){this.cancelBubble=true}}});a=d.dom.Event=new d.dom.EventUtils();a._wait(window);d.addUnload(function(){a.destroy()})})(tinymce);(function(a){a.dom.Element=function(f,d){var b=this,e,c;b.settings=d=d||{};b.id=f;b.dom=e=d.dom||a.DOM;if(!a.isIE){c=e.get(b.id)}a.each(("getPos,getRect,getParent,add,setStyle,getStyle,setStyles,setAttrib,setAttribs,getAttrib,addClass,removeClass,hasClass,getOuterHTML,setOuterHTML,remove,show,hide,isHidden,setHTML,get").split(/,/),function(g){b[g]=function(){var h=[f],j;for(j=0;j<arguments.length;j++){h.push(arguments[j])}h=e[g].apply(e,h);b.update(g);return h}});a.extend(b,{on:function(i,h,g){return a.dom.Event.add(b.id,i,h,g)},getXY:function(){return{x:parseInt(b.getStyle("left")),y:parseInt(b.getStyle("top"))}},getSize:function(){var g=e.get(b.id);return{w:parseInt(b.getStyle("width")||g.clientWidth),h:parseInt(b.getStyle("height")||g.clientHeight)}},moveTo:function(g,h){b.setStyles({left:g,top:h})},moveBy:function(g,i){var h=b.getXY();b.moveTo(h.x+g,h.y+i)},resizeTo:function(g,i){b.setStyles({width:g,height:i})},resizeBy:function(g,j){var i=b.getSize();b.resizeTo(i.w+g,i.h+j)},update:function(h){var g;if(a.isIE6&&d.blocker){h=h||"";if(h.indexOf("get")===0||h.indexOf("has")===0||h.indexOf("is")===0){return}if(h=="remove"){e.remove(b.blocker);return}if(!b.blocker){b.blocker=e.uniqueId();g=e.add(d.container||e.getRoot(),"iframe",{id:b.blocker,style:"position:absolute;",frameBorder:0,src:'javascript:""'});e.setStyle(g,"opacity",0)}else{g=e.get(b.blocker)}e.setStyles(g,{left:b.getStyle("left",1),top:b.getStyle("top",1),width:b.getStyle("width",1),height:b.getStyle("height",1),display:b.getStyle("display",1),zIndex:parseInt(b.getStyle("zIndex",1)||0)-1})}}})}})(tinymce);(function(c){function e(f){return f.replace(/[\n\r]+/g,"")}var b=c.is,a=c.isIE,d=c.each;c.create("tinymce.dom.Selection",{Selection:function(i,h,g){var f=this;f.dom=i;f.win=h;f.serializer=g;d(["onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent"],function(j){f[j]=new c.util.Dispatcher(f)});if(!f.win.getSelection){f.tridentSel=new c.dom.TridentSelection(f)}if(c.isIE&&i.boxModel){this._fixIESelection()}c.addUnload(f.destroy,f)},setCursorLocation:function(h,i){var f=this;var g=f.dom.createRng();g.setStart(h,i);g.setEnd(h,i);f.setRng(g);f.collapse(false)},getContent:function(g){var f=this,h=f.getRng(),l=f.dom.create("body"),j=f.getSel(),i,k,m;g=g||{};i=k="";g.get=true;g.format=g.format||"html";g.forced_root_block="";f.onBeforeGetContent.dispatch(f,g);if(g.format=="text"){return f.isCollapsed()?"":(h.text||(j.toString?j.toString():""))}if(h.cloneContents){m=h.cloneContents();if(m){l.appendChild(m)}}else{if(b(h.item)||b(h.htmlText)){l.innerHTML="<br>"+(h.item?h.item(0).outerHTML:h.htmlText);l.removeChild(l.firstChild)}else{l.innerHTML=h.toString()}}if(/^\s/.test(l.innerHTML)){i=" "}if(/\s+$/.test(l.innerHTML)){k=" "}g.getInner=true;g.content=f.isCollapsed()?"":i+f.serializer.serialize(l,g)+k;f.onGetContent.dispatch(f,g);return g.content},setContent:function(g,i){var n=this,f=n.getRng(),j,k=n.win.document,m,l;i=i||{format:"html"};i.set=true;g=i.content=g;if(!i.no_events){n.onBeforeSetContent.dispatch(n,i)}g=i.content;if(f.insertNode){g+='<span id="__caret">_</span>';if(f.startContainer==k&&f.endContainer==k){k.body.innerHTML=g}else{f.deleteContents();if(k.body.childNodes.length==0){k.body.innerHTML=g}else{if(f.createContextualFragment){f.insertNode(f.createContextualFragment(g))}else{m=k.createDocumentFragment();l=k.createElement("div");m.appendChild(l);l.outerHTML=g;f.insertNode(m)}}}j=n.dom.get("__caret");f=k.createRange();f.setStartBefore(j);f.setEndBefore(j);n.setRng(f);n.dom.remove("__caret");try{n.setRng(f)}catch(h){}}else{if(f.item){k.execCommand("Delete",false,null);f=n.getRng()}if(/^\s+/.test(g)){f.pasteHTML('<span id="__mce_tmp">_</span>'+g);n.dom.remove("__mce_tmp")}else{f.pasteHTML(g)}}if(!i.no_events){n.onSetContent.dispatch(n,i)}},getStart:function(){var g=this.getRng(),h,f,j,i;if(g.duplicate||g.item){if(g.item){return g.item(0)}j=g.duplicate();j.collapse(1);h=j.parentElement();f=i=g.parentElement();while(i=i.parentNode){if(i==h){h=f;break}}return h}else{h=g.startContainer;if(h.nodeType==1&&h.hasChildNodes()){h=h.childNodes[Math.min(h.childNodes.length-1,g.startOffset)]}if(h&&h.nodeType==3){return h.parentNode}return h}},getEnd:function(){var g=this,h=g.getRng(),i,f;if(h.duplicate||h.item){if(h.item){return h.item(0)}h=h.duplicate();h.collapse(0);i=h.parentElement();if(i&&i.nodeName=="BODY"){return i.lastChild||i}return i}else{i=h.endContainer;f=h.endOffset;if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[f>0?f-1:f]}if(i&&i.nodeType==3){return i.parentNode}return i}},getBookmark:function(r,s){var v=this,m=v.dom,g,j,i,n,h,o,p,l="\uFEFF",u;function f(x,y){var t=0;d(m.select(x),function(A,z){if(A==y){t=z}});return t}if(r==2){function k(){var x=v.getRng(true),t=m.getRoot(),y={};function z(C,H){var B=C[H?"startContainer":"endContainer"],G=C[H?"startOffset":"endOffset"],A=[],D,F,E=0;if(B.nodeType==3){if(s){for(D=B.previousSibling;D&&D.nodeType==3;D=D.previousSibling){G+=D.nodeValue.length}}A.push(G)}else{F=B.childNodes;if(G>=F.length&&F.length){E=1;G=Math.max(0,F.length-1)}A.push(v.dom.nodeIndex(F[G],s)+E)}for(;B&&B!=t;B=B.parentNode){A.push(v.dom.nodeIndex(B,s))}return A}y.start=z(x,true);if(!v.isCollapsed()){y.end=z(x)}return y}if(v.tridentSel){return v.tridentSel.getBookmark(r)}return k()}if(r){return{rng:v.getRng()}}g=v.getRng();i=m.uniqueId();n=tinyMCE.activeEditor.selection.isCollapsed();u="overflow:hidden;line-height:0px";if(g.duplicate||g.item){if(!g.item){j=g.duplicate();try{g.collapse();g.pasteHTML('<span data-mce-type="bookmark" id="'+i+'_start" style="'+u+'">'+l+"</span>");if(!n){j.collapse(false);g.moveToElementText(j.parentElement());if(g.compareEndPoints("StartToEnd",j)==0){j.move("character",-1)}j.pasteHTML('<span data-mce-type="bookmark" id="'+i+'_end" style="'+u+'">'+l+"</span>")}}catch(q){return null}}else{o=g.item(0);h=o.nodeName;return{name:h,index:f(h,o)}}}else{o=v.getNode();h=o.nodeName;if(h=="IMG"){return{name:h,index:f(h,o)}}j=g.cloneRange();if(!n){j.collapse(false);j.insertNode(m.create("span",{"data-mce-type":"bookmark",id:i+"_end",style:u},l))}g.collapse(true);g.insertNode(m.create("span",{"data-mce-type":"bookmark",id:i+"_start",style:u},l))}v.moveToBookmark({id:i,keep:1});return{id:i}},moveToBookmark:function(n){var r=this,l=r.dom,i,h,f,q,j,s,o,p;if(n){if(n.start){f=l.createRng();q=l.getRoot();function g(z){var t=n[z?"start":"end"],v,x,y,u;if(t){y=t[0];for(x=q,v=t.length-1;v>=1;v--){u=x.childNodes;if(t[v]>u.length-1){return}x=u[t[v]]}if(x.nodeType===3){y=Math.min(t[0],x.nodeValue.length)}if(x.nodeType===1){y=Math.min(t[0],x.childNodes.length)}if(z){f.setStart(x,y)}else{f.setEnd(x,y)}}return true}if(r.tridentSel){return r.tridentSel.moveToBookmark(n)}if(g(true)&&g()){r.setRng(f)}}else{if(n.id){function k(A){var u=l.get(n.id+"_"+A),z,t,x,y,v=n.keep;if(u){z=u.parentNode;if(A=="start"){if(!v){t=l.nodeIndex(u)}else{z=u.firstChild;t=1}j=s=z;o=p=t}else{if(!v){t=l.nodeIndex(u)}else{z=u.firstChild;t=1}s=z;p=t}if(!v){y=u.previousSibling;x=u.nextSibling;d(c.grep(u.childNodes),function(B){if(B.nodeType==3){B.nodeValue=B.nodeValue.replace(/\uFEFF/g,"")}});while(u=l.get(n.id+"_"+A)){l.remove(u,1)}if(y&&x&&y.nodeType==x.nodeType&&y.nodeType==3&&!c.isOpera){t=y.nodeValue.length;y.appendData(x.nodeValue);l.remove(x);if(A=="start"){j=s=y;o=p=t}else{s=y;p=t}}}}}function m(t){if(l.isBlock(t)&&!t.innerHTML){t.innerHTML=!a?'<br data-mce-bogus="1" />':" "}return t}k("start");k("end");if(j){f=l.createRng();f.setStart(m(j),o);f.setEnd(m(s),p);r.setRng(f)}}else{if(n.name){r.select(l.select(n.name)[n.index])}else{if(n.rng){r.setRng(n.rng)}}}}}},select:function(k,j){var i=this,l=i.dom,g=l.createRng(),f;if(k){f=l.nodeIndex(k);g.setStart(k.parentNode,f);g.setEnd(k.parentNode,f+1);if(j){function h(m,o){var n=new c.dom.TreeWalker(m,m);do{if(m.nodeType==3&&c.trim(m.nodeValue).length!=0){if(o){g.setStart(m,0)}else{g.setEnd(m,m.nodeValue.length)}return}if(m.nodeName=="BR"){if(o){g.setStartBefore(m)}else{g.setEndBefore(m)}return}}while(m=(o?n.next():n.prev()))}h(k,1);h(k)}i.setRng(g)}return k},isCollapsed:function(){var f=this,h=f.getRng(),g=f.getSel();if(!h||h.item){return false}if(h.compareEndPoints){return h.compareEndPoints("StartToEnd",h)===0}return !g||h.collapsed},collapse:function(f){var h=this,g=h.getRng(),i;if(g.item){i=g.item(0);g=h.win.document.body.createTextRange();g.moveToElementText(i)}g.collapse(!!f);h.setRng(g)},getSel:function(){var g=this,f=this.win;return f.getSelection?f.getSelection():f.document.selection},getRng:function(l){var g=this,h,i,k,j=g.win.document;if(l&&g.tridentSel){return g.tridentSel.getRangeAt(0)}try{if(h=g.getSel()){i=h.rangeCount>0?h.getRangeAt(0):(h.createRange?h.createRange():j.createRange())}}catch(f){}if(c.isIE&&i&&i.setStart&&j.selection.createRange().item){k=j.selection.createRange().item(0);i=j.createRange();i.setStartBefore(k);i.setEndAfter(k)}if(!i){i=j.createRange?j.createRange():j.body.createTextRange()}if(g.selectedRange&&g.explicitRange){if(i.compareBoundaryPoints(i.START_TO_START,g.selectedRange)===0&&i.compareBoundaryPoints(i.END_TO_END,g.selectedRange)===0){i=g.explicitRange}else{g.selectedRange=null;g.explicitRange=null}}return i},setRng:function(i){var h,g=this;if(!g.tridentSel){h=g.getSel();if(h){g.explicitRange=i;try{h.removeAllRanges()}catch(f){}h.addRange(i);g.selectedRange=h.getRangeAt(0)}}else{if(i.cloneRange){g.tridentSel.addRange(i);return}try{i.select()}catch(f){}}},setNode:function(g){var f=this;f.setContent(f.dom.getOuterHTML(g));return g},getNode:function(){var h=this,g=h.getRng(),i=h.getSel(),l,k=g.startContainer,f=g.endContainer;if(!g){return h.dom.getRoot()}if(g.setStart){l=g.commonAncestorContainer;if(!g.collapsed){if(g.startContainer==g.endContainer){if(g.endOffset-g.startOffset<2){if(g.startContainer.hasChildNodes()){l=g.startContainer.childNodes[g.startOffset]}}}if(k.nodeType===3&&f.nodeType===3){function j(p,m){var o=p;while(p&&p.nodeType===3&&p.length===0){p=m?p.nextSibling:p.previousSibling}return p||o}if(k.length===g.startOffset){k=j(k.nextSibling,true)}else{k=k.parentNode}if(g.endOffset===0){f=j(f.previousSibling,false)}else{f=f.parentNode}if(k&&k===f){return k}}}if(l&&l.nodeType==3){return l.parentNode}return l}return g.item?g.item(0):g.parentElement()},getSelectedBlocks:function(g,f){var i=this,j=i.dom,m,h,l,k=[];m=j.getParent(g||i.getStart(),j.isBlock);h=j.getParent(f||i.getEnd(),j.isBlock);if(m){k.push(m)}if(m&&h&&m!=h){l=m;while((l=l.nextSibling)&&l!=h){if(j.isBlock(l)){k.push(l)}}}if(h&&m!=h){k.push(h)}return k},normalize:function(){var g=this,f,i;if(c.isIE){return}function h(p){var k,o,n,m=g.dom,j=m.getRoot(),l;k=f[(p?"start":"end")+"Container"];o=f[(p?"start":"end")+"Offset"];if(k.nodeType===9){k=k.body;o=0}if(k===j){if(k.hasChildNodes()){k=k.childNodes[Math.min(!p&&o>0?o-1:o,k.childNodes.length-1)];o=0;if(k.hasChildNodes()){l=k;n=new c.dom.TreeWalker(k,j);do{if(l.nodeType===3){o=p?0:l.nodeValue.length-1;k=l;break}if(l.nodeName==="BR"){o=m.nodeIndex(l);k=l.parentNode;break}}while(l=(p?n.next():n.prev()));i=true}}}if(i){f["set"+(p?"Start":"End")](k,o)}}f=g.getRng();h(true);if(f.collapsed){h()}if(i){g.setRng(f)}},destroy:function(g){var f=this;f.win=null;if(!g){c.removeUnload(f.destroy)}},_fixIESelection:function(){var g=this.dom,m=g.doc,h=m.body,j,n,f;m.documentElement.unselectable=true;function i(o,r){var p=h.createTextRange();try{p.moveToPoint(o,r)}catch(q){p=null}return p}function l(p){var o;if(p.button){o=i(p.x,p.y);if(o){if(o.compareEndPoints("StartToStart",n)>0){o.setEndPoint("StartToStart",n)}else{o.setEndPoint("EndToEnd",n)}o.select()}}else{k()}}function k(){var o=m.selection.createRange();if(n&&!o.item&&o.compareEndPoints("StartToEnd",o)===0){n.select()}g.unbind(m,"mouseup",k);g.unbind(m,"mousemove",l);n=j=0}g.bind(m,["mousedown","contextmenu"],function(o){if(o.target.nodeName==="HTML"){if(j){k()}f=m.documentElement;if(f.scrollHeight>f.clientHeight){return}j=1;n=i(o.x,o.y);if(n){g.bind(m,"mouseup",k);g.bind(m,"mousemove",l);g.win.focus();n.select()}}})}})})(tinymce);(function(a){a.dom.Serializer=function(e,i,f){var h,b,d=a.isIE,g=a.each,c;if(!e.apply_source_formatting){e.indent=false}e.remove_trailing_brs=true;i=i||a.DOM;f=f||new a.html.Schema(e);e.entity_encoding=e.entity_encoding||"named";h=new a.util.Dispatcher(self);b=new a.util.Dispatcher(self);c=new a.html.DomParser(e,f);c.addAttributeFilter("src,href,style",function(k,j){var o=k.length,l,q,n="data-mce-"+j,p=e.url_converter,r=e.url_converter_scope,m;while(o--){l=k[o];q=l.attributes.map[n];if(q!==m){l.attr(j,q.length>0?q:null);l.attr(n,null)}else{q=l.attributes.map[j];if(j==="style"){q=i.serializeStyle(i.parseStyle(q),l.name)}else{if(p){q=p.call(r,q,j,l.name)}}l.attr(j,q.length>0?q:null)}}});c.addAttributeFilter("class",function(j,k){var l=j.length,m,n;while(l--){m=j[l];n=m.attr("class").replace(/\s*mce(Item\w+|Selected)\s*/g,"");m.attr("class",n.length>0?n:null)}});c.addAttributeFilter("data-mce-type",function(j,l,k){var m=j.length,n;while(m--){n=j[m];if(n.attributes.map["data-mce-type"]==="bookmark"&&!k.cleanup){n.remove()}}});c.addNodeFilter("script,style",function(k,l){var m=k.length,n,o;function j(p){return p.replace(/(<!--\[CDATA\[|\]\]-->)/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(\/\/\s*<!--|\/\/\s*<!\[CDATA\[|<!--|<!\[CDATA\[)[\r\n]*/g,"").replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->|\]\]-->)\s*$/g,"")}while(m--){n=k[m];o=n.firstChild?n.firstChild.value:"";if(l==="script"){n.attr("type",(n.attr("type")||"text/javascript").replace(/^mce\-/,""));if(o.length>0){n.firstChild.value="// <![CDATA[\n"+j(o)+"\n// ]]>"}}else{if(o.length>0){n.firstChild.value="<!--\n"+j(o)+"\n-->"}}}});c.addNodeFilter("#comment",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.value.indexOf("[CDATA[")===0){m.name="#cdata";m.type=4;m.value=m.value.replace(/^\[CDATA\[|\]\]$/g,"")}else{if(m.value.indexOf("mce:protected ")===0){m.name="#text";m.type=3;m.raw=true;m.value=unescape(m.value).substr(14)}}}});c.addNodeFilter("xml:namespace,input",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.type===7){m.remove()}else{if(m.type===1){if(k==="input"&&!("type" in m.attributes.map)){m.attr("type","text")}}}}});if(e.fix_list_elements){c.addNodeFilter("ul,ol",function(k,l){var m=k.length,n,j;while(m--){n=k[m];j=n.parent;if(j.name==="ul"||j.name==="ol"){if(n.prev&&n.prev.name==="li"){n.prev.append(n)}}}})}c.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style",function(j,k){var l=j.length;while(l--){j[l].attr(k,null)}});return{schema:f,addNodeFilter:c.addNodeFilter,addAttributeFilter:c.addAttributeFilter,onPreProcess:h,onPostProcess:b,serialize:function(o,m){var l,p,k,j,n;if(d&&i.select("script,style,select,map").length>0){n=o.innerHTML;o=o.cloneNode(false);i.setHTML(o,n)}else{o=o.cloneNode(true)}l=o.ownerDocument.implementation;if(l.createHTMLDocument){p=l.createHTMLDocument("");g(o.nodeName=="BODY"?o.childNodes:[o],function(q){p.body.appendChild(p.importNode(q,true))});if(o.nodeName!="BODY"){o=p.body.firstChild}else{o=p.body}k=i.doc;i.doc=p}m=m||{};m.format=m.format||"html";if(!m.no_events){m.node=o;h.dispatch(self,m)}j=new a.html.Serializer(e,f);m.content=j.serialize(c.parse(m.getInner?o.innerHTML:a.trim(i.getOuterHTML(o),m),m));if(!m.cleanup){m.content=m.content.replace(/\uFEFF/g,"")}if(!m.no_events){b.dispatch(self,m)}if(k){i.doc=k}m.node=null;return m.content},addRules:function(j){f.addValidElements(j)},setRules:function(j){f.setValidElements(j)}}}})(tinymce);(function(a){a.dom.ScriptLoader=function(h){var c=0,k=1,i=2,l={},j=[],f={},d=[],g=0,e;function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s){s.onreadystatechange=s.onload=s=null}v()}function u(){if(typeof(console)!=="undefined"&&console.log){console.log("Failed to load: "+m)}}n=q.uniqueId();if(a.isIE6){o=new a.util.URI(m);r=location;if(o.host==r.hostname&&o.port==r.port&&(o.protocol+":")==r.protocol&&o.protocol.toLowerCase()!="file"){a.util.XHR.send({url:a._addVer(o.getURI()),success:function(y){var t=q.create("script",{type:"text/javascript"});t.text=y;document.getElementsByTagName("head")[0].appendChild(t);q.remove(t);p()},error:u});return}}s=q.create("script",{id:n,type:"text/javascript",src:a._addVer(m)});if(!a.isIE){s.onload=p}s.onerror=u;if(!a.isOpera){s.onreadystatechange=function(){var t=s.readyState;if(t=="complete"||t=="loaded"){p()}}}(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}this.isDone=function(m){return l[m]==i};this.markDone=function(m){l[m]=i};this.add=this.load=function(m,q,n){var o,p=l[m];if(p==e){j.push(m);l[m]=c}if(q){if(!f[m]){f[m]=[]}f[m].push({func:q,scope:n||this})}};this.loadQueue=function(n,m){this.loadScripts(j,n,m)};this.loadScripts=function(m,q,p){var o;function n(r){a.each(f[r],function(s){s.func.call(s.scope)});f[r]=e}d.push({func:q,scope:p||this});o=function(){var r=a.grep(m);m.length=0;a.each(r,function(s){if(l[s]==i){n(s);return}if(l[s]!=k){l[s]=k;g++;b(s,function(){l[s]=i;g--;n(s);o()})}});if(!g){a.each(d,function(s){s.func.call(s.scope)});d.length=0}};o()}};a.ScriptLoader=new a.dom.ScriptLoader()})(tinymce);tinymce.dom.TreeWalker=function(a,c){var b=a;function d(i,f,e,j){var h,g;if(i){if(!j&&i[f]){return i[f]}if(i!=c){h=i[e];if(h){return h}for(g=i.parentNode;g&&g!=c;g=g.parentNode){h=g[e];if(h){return h}}}}}this.current=function(){return b};this.next=function(e){return(b=d(b,"firstChild","nextSibling",e))};this.prev=function(e){return(b=d(b,"lastChild","previousSibling",e))}};(function(a){a.dom.RangeUtils=function(c){var b="\uFEFF";this.walk=function(d,r){var h=d.startContainer,k=d.startOffset,s=d.endContainer,l=d.endOffset,i,f,n,g,q,p,e;e=c.select("td.mceSelected,th.mceSelected");if(e.length>0){a.each(e,function(t){r([t])});return}function o(v,u,t){var x=[];for(;v&&v!=t;v=v[u]){x.push(v)}return x}function m(u,t){do{if(u.parentNode==t){return u}u=u.parentNode}while(u)}function j(v,u,x){var t=x?"nextSibling":"previousSibling";for(g=v,q=g.parentNode;g&&g!=u;g=q){q=g.parentNode;p=o(g==v?g:g[t],t);if(p.length){if(!x){p.reverse()}r(p)}}}if(h.nodeType==1&&h.hasChildNodes()){h=h.childNodes[k]}if(s.nodeType==1&&s.hasChildNodes()){s=s.childNodes[Math.min(l-1,s.childNodes.length-1)]}i=c.findCommonAncestor(h,s);if(h==s){return r([h])}for(g=h;g;g=g.parentNode){if(g==s){return j(h,i,true)}if(g==i){break}}for(g=s;g;g=g.parentNode){if(g==h){return j(s,i)}if(g==i){break}}f=m(h,i)||h;n=m(s,i)||s;j(h,f,true);p=o(f==h?f:f.nextSibling,"nextSibling",n==s?n.nextSibling:n);if(p.length){r(p)}j(s,n)}};a.dom.RangeUtils.compareRanges=function(c,b){if(c&&b){if(c.item||c.duplicate){if(c.item&&b.item&&c.item(0)===b.item(0)){return true}if(c.isEqual&&b.isEqual&&b.isEqual(c)){return true}}else{return c.startContainer==b.startContainer&&c.startOffset==b.startOffset}}return false}})(tinymce);(function(b){var a=b.dom.Event,c=b.each;b.create("tinymce.ui.KeyboardNavigation",{KeyboardNavigation:function(e,f){var p=this,m=e.root,l=e.items,n=e.enableUpDown,i=e.enableLeftRight||!e.enableUpDown,k=e.excludeFromTabOrder,j,h,o,d,g;f=f||b.DOM;j=function(q){g=q.target.id};h=function(q){f.setAttrib(q.target.id,"tabindex","-1")};d=function(q){var r=f.get(g);f.setAttrib(r,"tabindex","0");r.focus()};p.focus=function(){f.get(g).focus()};p.destroy=function(){c(l,function(q){f.unbind(f.get(q.id),"focus",j);f.unbind(f.get(q.id),"blur",h)});f.unbind(f.get(m),"focus",d);f.unbind(f.get(m),"keydown",o);l=f=m=p.focus=j=h=o=d=null;p.destroy=function(){}};p.moveFocus=function(u,r){var q=-1,t=p.controls,s;if(!g){return}c(l,function(x,v){if(x.id===g){q=v;return false}});q+=u;if(q<0){q=l.length-1}else{if(q>=l.length){q=0}}s=l[q];f.setAttrib(g,"tabindex","-1");f.setAttrib(s.id,"tabindex","0");f.get(s.id).focus();if(e.actOnFocus){e.onAction(s.id)}if(r){a.cancel(r)}};o=function(y){var u=37,t=39,x=38,z=40,q=27,s=14,r=13,v=32;switch(y.keyCode){case u:if(i){p.moveFocus(-1)}break;case t:if(i){p.moveFocus(1)}break;case x:if(n){p.moveFocus(-1)}break;case z:if(n){p.moveFocus(1)}break;case q:if(e.onCancel){e.onCancel();a.cancel(y)}break;case s:case r:case v:if(e.onAction){e.onAction(g);a.cancel(y)}break}};c(l,function(s,q){var r;if(!s.id){s.id=f.uniqueId("_mce_item_")}if(k){f.bind(s.id,"blur",h);r="-1"}else{r=(q===0?"0":"-1")}f.setAttrib(s.id,"tabindex",r);f.bind(f.get(s.id),"focus",j)});if(l[0]){g=l[0].id}f.setAttrib(m,"tabindex","-1");f.bind(f.get(m),"focus",d);f.bind(f.get(m),"keydown",o)}})})(tinymce);(function(c){var b=c.DOM,a=c.is;c.create("tinymce.ui.Control",{Control:function(f,e,d){this.id=f;this.settings=e=e||{};this.rendered=false;this.onRender=new c.util.Dispatcher(this);this.classPrefix="";this.scope=e.scope||this;this.disabled=0;this.active=0;this.editor=d},setAriaProperty:function(f,e){var d=b.get(this.id+"_aria")||b.get(this.id);if(d){b.setAttrib(d,"aria-"+f,!!e)}},focus:function(){b.get(this.id).focus()},setDisabled:function(d){if(d!=this.disabled){this.setAriaProperty("disabled",d);this.setState("Disabled",d);this.setState("Enabled",!d);this.disabled=d}},isDisabled:function(){return this.disabled},setActive:function(d){if(d!=this.active){this.setState("Active",d);this.active=d;this.setAriaProperty("pressed",d)}},isActive:function(){return this.active},setState:function(f,d){var e=b.get(this.id);f=this.classPrefix+f;if(d){b.addClass(e,f)}else{b.removeClass(e,f)}},isRendered:function(){return this.rendered},renderHTML:function(){},renderTo:function(d){b.setHTML(d,this.renderHTML())},postRender:function(){var e=this,d;if(a(e.disabled)){d=e.disabled;e.disabled=-1;e.setDisabled(d)}if(a(e.active)){d=e.active;e.active=-1;e.setActive(d)}},remove:function(){b.remove(this.id);this.destroy()},destroy:function(){c.dom.Event.clear(this.id)}})})(tinymce);tinymce.create("tinymce.ui.Container:tinymce.ui.Control",{Container:function(c,b,a){this.parent(c,b,a);this.controls=[];this.lookup={}},add:function(a){this.lookup[a.id]=a;this.controls.push(a);return a},get:function(a){return this.lookup[a]}});tinymce.create("tinymce.ui.Separator:tinymce.ui.Control",{Separator:function(b,a){this.parent(b,a);this.classPrefix="mceSeparator";this.setDisabled(true)},renderHTML:function(){return tinymce.DOM.createHTML("span",{"class":this.classPrefix,role:"separator","aria-orientation":"vertical",tabindex:"-1"})}});(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.MenuItem:tinymce.ui.Control",{MenuItem:function(g,f){this.parent(g,f);this.classPrefix="mceMenuItem"},setSelected:function(f){this.setState("Selected",f);this.setAriaProperty("checked",!!f);this.selected=f},isSelected:function(){return this.selected},postRender:function(){var f=this;f.parent();if(c(f.selected)){f.setSelected(f.selected)}}})})(tinymce);(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.Menu:tinymce.ui.MenuItem",{Menu:function(h,g){var f=this;f.parent(h,g);f.items={};f.collapsed=false;f.menuCount=0;f.onAddItem=new d.util.Dispatcher(this)},expand:function(g){var f=this;if(g){a(f,function(h){if(h.expand){h.expand()}},"items",f)}f.collapsed=false},collapse:function(g){var f=this;if(g){a(f,function(h){if(h.collapse){h.collapse()}},"items",f)}f.collapsed=true},isCollapsed:function(){return this.collapsed},add:function(f){if(!f.settings){f=new d.ui.MenuItem(f.id||b.uniqueId(),f)}this.onAddItem.dispatch(this,f);return this.items[f.id]=f},addSeparator:function(){return this.add({separator:true})},addMenu:function(f){if(!f.collapse){f=this.createMenu(f)}this.menuCount++;return this.add(f)},hasMenus:function(){return this.menuCount!==0},remove:function(f){delete this.items[f.id]},removeAll:function(){var f=this;a(f,function(g){if(g.removeAll){g.removeAll()}else{g.remove()}g.destroy()},"items",f);f.items={}},createMenu:function(g){var f=new d.ui.Menu(g.id||b.uniqueId(),g);f.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return f}})})(tinymce);(function(e){var d=e.is,c=e.DOM,f=e.each,a=e.dom.Event,b=e.dom.Element;e.create("tinymce.ui.DropMenu:tinymce.ui.Menu",{DropMenu:function(h,g){g=g||{};g.container=g.container||c.doc.body;g.offset_x=g.offset_x||0;g.offset_y=g.offset_y||0;g.vp_offset_x=g.vp_offset_x||0;g.vp_offset_y=g.vp_offset_y||0;if(d(g.icons)&&!g.icons){g["class"]+=" mceNoIcons"}this.parent(h,g);this.onShowMenu=new e.util.Dispatcher(this);this.onHideMenu=new e.util.Dispatcher(this);this.classPrefix="mceMenu"},createMenu:function(j){var h=this,i=h.settings,g;j.container=j.container||i.container;j.parent=h;j.constrain=j.constrain||i.constrain;j["class"]=j["class"]||i["class"];j.vp_offset_x=j.vp_offset_x||i.vp_offset_x;j.vp_offset_y=j.vp_offset_y||i.vp_offset_y;j.keyboard_focus=i.keyboard_focus;g=new e.ui.DropMenu(j.id||c.uniqueId(),j);g.onAddItem.add(h.onAddItem.dispatch,h.onAddItem);return g},focus:function(){var g=this;if(g.keyboardNav){g.keyboardNav.focus()}},update:function(){var i=this,j=i.settings,g=c.get("menu_"+i.id+"_tbl"),l=c.get("menu_"+i.id+"_co"),h,k;h=j.max_width?Math.min(g.clientWidth,j.max_width):g.clientWidth;k=j.max_height?Math.min(g.clientHeight,j.max_height):g.clientHeight;if(!c.boxModel){i.element.setStyles({width:h+2,height:k+2})}else{i.element.setStyles({width:h,height:k})}if(j.max_width){c.setStyle(l,"width",h)}if(j.max_height){c.setStyle(l,"height",k);if(g.clientHeight<j.max_height){c.setStyle(l,"overflow","hidden")}}},showMenu:function(p,n,r){var z=this,A=z.settings,o,g=c.getViewPort(),u,l,v,q,i=2,k,j,m=z.classPrefix;z.collapse(1);if(z.isMenuVisible){return}if(!z.rendered){o=c.add(z.settings.container,z.renderNode());f(z.items,function(h){h.postRender()});z.element=new b("menu_"+z.id,{blocker:1,container:A.container})}else{o=c.get("menu_"+z.id)}if(!e.isOpera){c.setStyles(o,{left:-65535,top:-65535})}c.show(o);z.update();p+=A.offset_x||0;n+=A.offset_y||0;g.w-=4;g.h-=4;if(A.constrain){u=o.clientWidth-i;l=o.clientHeight-i;v=g.x+g.w;q=g.y+g.h;if((p+A.vp_offset_x+u)>v){p=r?r-u:Math.max(0,(v-A.vp_offset_x)-u)}if((n+A.vp_offset_y+l)>q){n=Math.max(0,(q-A.vp_offset_y)-l)}}c.setStyles(o,{left:p,top:n});z.element.update();z.isMenuVisible=1;z.mouseClickFunc=a.add(o,"click",function(s){var h;s=s.target;if(s&&(s=c.getParent(s,"tr"))&&!c.hasClass(s,m+"ItemSub")){h=z.items[s.id];if(h.isDisabled()){return}k=z;while(k){if(k.hideMenu){k.hideMenu()}k=k.settings.parent}if(h.settings.onclick){h.settings.onclick(s)}return a.cancel(s)}});if(z.hasMenus()){z.mouseOverFunc=a.add(o,"mouseover",function(x){var h,t,s;x=x.target;if(x&&(x=c.getParent(x,"tr"))){h=z.items[x.id];if(z.lastMenu){z.lastMenu.collapse(1)}if(h.isDisabled()){return}if(x&&c.hasClass(x,m+"ItemSub")){t=c.getRect(x);h.showMenu((t.x+t.w-i),t.y-i,t.x);z.lastMenu=h;c.addClass(c.get(h.id).firstChild,m+"ItemActive")}}})}a.add(o,"keydown",z._keyHandler,z);z.onShowMenu.dispatch(z);if(A.keyboard_focus){z._setupKeyboardNav()}},hideMenu:function(j){var g=this,i=c.get("menu_"+g.id),h;if(!g.isMenuVisible){return}if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(i,"mouseover",g.mouseOverFunc);a.remove(i,"click",g.mouseClickFunc);a.remove(i,"keydown",g._keyHandler);c.hide(i);g.isMenuVisible=0;if(!j){g.collapse(1)}if(g.element){g.element.hide()}if(h=c.get(g.id)){c.removeClass(h.firstChild,g.classPrefix+"ItemActive")}g.onHideMenu.dispatch(g)},add:function(i){var g=this,h;i=g.parent(i);if(g.isRendered&&(h=c.get("menu_"+g.id))){g._add(c.select("tbody",h)[0],i)}return i},collapse:function(g){this.parent(g);this.hideMenu(1)},remove:function(g){c.remove(g.id);this.destroy();return this.parent(g)},destroy:function(){var g=this,h=c.get("menu_"+g.id);if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(h,"mouseover",g.mouseOverFunc);a.remove(c.select("a",h),"focus",g.mouseOverFunc);a.remove(h,"click",g.mouseClickFunc);a.remove(h,"keydown",g._keyHandler);if(g.element){g.element.remove()}c.remove(h)},renderNode:function(){var i=this,j=i.settings,l,h,k,g;g=c.create("div",{role:"listbox",id:"menu_"+i.id,"class":j["class"],style:"position:absolute;left:0;top:0;z-index:200000;outline:0"});if(i.settings.parent){c.setAttrib(g,"aria-parent","menu_"+i.settings.parent.id)}k=c.add(g,"div",{role:"presentation",id:"menu_"+i.id+"_co","class":i.classPrefix+(j["class"]?" "+j["class"]:"")});i.element=new b("menu_"+i.id,{blocker:1,container:j.container});if(j.menu_line){c.add(k,"span",{"class":i.classPrefix+"Line"})}l=c.add(k,"table",{role:"presentation",id:"menu_"+i.id+"_tbl",border:0,cellPadding:0,cellSpacing:0});h=c.add(l,"tbody");f(i.items,function(m){i._add(h,m)});i.rendered=true;return g},_setupKeyboardNav:function(){var i,h,g=this;i=c.select("#menu_"+g.id)[0];h=c.select("a[role=option]","menu_"+g.id);h.splice(0,0,i);g.keyboardNav=new e.ui.KeyboardNavigation({root:"menu_"+g.id,items:h,onCancel:function(){g.hideMenu()},enableUpDown:true});i.focus()},_keyHandler:function(g){var h=this,i;switch(g.keyCode){case 37:if(h.settings.parent){h.hideMenu();h.settings.parent.focus();a.cancel(g)}break;case 39:if(h.mouseOverFunc){h.mouseOverFunc(g)}break}},_add:function(j,h){var i,q=h.settings,p,l,k,m=this.classPrefix,g;if(q.separator){l=c.add(j,"tr",{id:h.id,"class":m+"ItemSeparator"});c.add(l,"td",{"class":m+"ItemSeparator"});if(i=l.previousSibling){c.addClass(i,"mceLast")}return}i=l=c.add(j,"tr",{id:h.id,"class":m+"Item "+m+"ItemEnabled"});i=k=c.add(i,q.titleItem?"th":"td");i=p=c.add(i,"a",{id:h.id+"_aria",role:q.titleItem?"presentation":"option",href:"javascript:;",onclick:"return false;",onmousedown:"return false;"});if(q.parent){c.setAttrib(p,"aria-haspopup","true");c.setAttrib(p,"aria-owns","menu_"+h.id)}c.addClass(k,q["class"]);g=c.add(i,"span",{"class":"mceIcon"+(q.icon?" mce_"+q.icon:"")});if(q.icon_src){c.add(g,"img",{src:q.icon_src})}i=c.add(i,q.element||"span",{"class":"mceText",title:h.settings.title},h.settings.title);if(h.settings.style){c.setAttrib(i,"style",h.settings.style)}if(j.childNodes.length==1){c.addClass(l,"mceFirst")}if((i=l.previousSibling)&&c.hasClass(i,m+"ItemSeparator")){c.addClass(l,"mceFirst")}if(h.collapse){c.addClass(l,m+"ItemSub")}if(i=l.previousSibling){c.removeClass(i,"mceLast")}c.addClass(l,"mceLast")}})})(tinymce);(function(b){var a=b.DOM;b.create("tinymce.ui.Button:tinymce.ui.Control",{Button:function(e,d,c){this.parent(e,d,c);this.classPrefix="mceButton"},renderHTML:function(){var f=this.classPrefix,e=this.settings,d,c;c=a.encode(e.label||"");d='<a role="button" id="'+this.id+'" href="javascript:;" class="'+f+" "+f+"Enabled "+e["class"]+(c?" "+f+"Labeled":"")+'" onmousedown="return false;" onclick="return false;" aria-labelledby="'+this.id+'_voice" title="'+a.encode(e.title)+'">';if(e.image&&!(this.editor&&this.editor.forcedHighContrastMode)){d+='<img class="mceIcon" src="'+e.image+'" alt="'+a.encode(e.title)+'" />'+c}else{d+='<span class="mceIcon '+e["class"]+'"></span>'+(c?'<span class="'+f+'Label">'+c+"</span>":"")}d+='<span class="mceVoiceLabel mceIconOnly" style="display: none;" id="'+this.id+'_voice">'+e.title+"</span>";d+="</a>";return d},postRender:function(){var c=this,d=c.settings;b.dom.Event.add(c.id,"click",function(f){if(!c.isDisabled()){return d.onclick.call(d.scope,f)}})}})})(tinymce);(function(d){var c=d.DOM,b=d.dom.Event,e=d.each,a=d.util.Dispatcher;d.create("tinymce.ui.ListBox:tinymce.ui.Control",{ListBox:function(i,h,f){var g=this;g.parent(i,h,f);g.items=[];g.onChange=new a(g);g.onPostRender=new a(g);g.onAdd=new a(g);g.onRenderMenu=new d.util.Dispatcher(this);g.classPrefix="mceListBox"},select:function(h){var g=this,j,i;if(h==undefined){return g.selectByIndex(-1)}if(h&&h.call){i=h}else{i=function(f){return f==h}}if(h!=g.selectedValue){e(g.items,function(k,f){if(i(k.value)){j=1;g.selectByIndex(f);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(f){var h=this,i,j,g;if(f!=h.selectedIndex){i=c.get(h.id+"_text");g=c.get(h.id+"_voiceDesc");j=h.items[f];if(j){h.selectedValue=j.value;h.selectedIndex=f;c.setHTML(i,c.encode(j.title));c.setHTML(g,h.settings.title+" - "+j.title);c.removeClass(i,"mceTitle");c.setAttrib(h.id,"aria-valuenow",j.title)}else{c.setHTML(i,c.encode(h.settings.title));c.setHTML(g,c.encode(h.settings.title));c.addClass(i,"mceTitle");h.selectedValue=h.selectedIndex=null;c.setAttrib(h.id,"aria-valuenow",h.settings.title)}i=0}},add:function(i,f,h){var g=this;h=h||{};h=d.extend(h,{title:i,value:f});g.items.push(h);g.onAdd.dispatch(g,h)},getLength:function(){return this.items.length},renderHTML:function(){var i="",f=this,g=f.settings,j=f.classPrefix;i='<span role="listbox" aria-haspopup="true" aria-labelledby="'+f.id+'_voiceDesc" aria-describedby="'+f.id+'_voiceDesc"><table role="presentation" tabindex="0" id="'+f.id+'" cellpadding="0" cellspacing="0" class="'+j+" "+j+"Enabled"+(g["class"]?(" "+g["class"]):"")+'"><tbody><tr>';i+="<td>"+c.createHTML("span",{id:f.id+"_voiceDesc","class":"voiceLabel",style:"display:none;"},f.settings.title);i+=c.createHTML("a",{id:f.id+"_text",tabindex:-1,href:"javascript:;","class":"mceText",onclick:"return false;",onmousedown:"return false;"},c.encode(f.settings.title))+"</td>";i+="<td>"+c.createHTML("a",{id:f.id+"_open",tabindex:-1,href:"javascript:;","class":"mceOpen",onclick:"return false;",onmousedown:"return false;"},'<span><span style="display:none;" class="mceIconOnly" aria-hidden="true">\u25BC</span></span>')+"</td>";i+="</tr></tbody></table></span>";return i},showMenu:function(){var g=this,i,h=c.get(this.id),f;if(g.isDisabled()||g.items.length==0){return}if(g.menu&&g.menu.isMenuVisible){return g.hideMenu()}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}i=c.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.keyboard_focus=!d.isOpera;if(g.oldID){f.items[g.oldID].setSelected(0)}e(g.items,function(j){if(j.value===g.selectedValue){f.items[j.id].setSelected(1);g.oldID=j.id}});f.showMenu(0,h.clientHeight);b.add(c.doc,"mousedown",g.hideMenu,g);c.addClass(g.id,g.classPrefix+"Selected")},hideMenu:function(g){var f=this;if(f.menu&&f.menu.isMenuVisible){c.removeClass(f.id,f.classPrefix+"Selected");if(g&&g.type=="mousedown"&&(g.target.id==f.id+"_text"||g.target.id==f.id+"_open")){return}if(!g||!c.getParent(g.target,".mceMenu")){c.removeClass(f.id,f.classPrefix+"Selected");b.remove(c.doc,"mousedown",f.hideMenu,f);f.menu.hideMenu()}}},renderMenu:function(){var g=this,f;f=g.settings.control_manager.createDropMenu(g.id+"_menu",{menu_line:1,"class":g.classPrefix+"Menu mceNoIcons",max_width:150,max_height:150});f.onHideMenu.add(function(){g.hideMenu();g.focus()});f.add({title:g.settings.title,"class":"mceMenuItemTitle",onclick:function(){if(g.settings.onselect("")!==false){g.select("")}}});e(g.items,function(h){if(h.value===undefined){f.add({title:h.title,role:"option","class":"mceMenuItemTitle",onclick:function(){if(g.settings.onselect("")!==false){g.select("")}}})}else{h.id=c.uniqueId();h.role="option";h.onclick=function(){if(g.settings.onselect(h.value)!==false){g.select(h.value)}};f.add(h)}});g.onRenderMenu.dispatch(g,f);g.menu=f},postRender:function(){var f=this,g=f.classPrefix;b.add(f.id,"click",f.showMenu,f);b.add(f.id,"keydown",function(h){if(h.keyCode==32){f.showMenu(h);b.cancel(h)}});b.add(f.id,"focus",function(){if(!f._focused){f.keyDownHandler=b.add(f.id,"keydown",function(h){if(h.keyCode==40){f.showMenu();b.cancel(h)}});f.keyPressHandler=b.add(f.id,"keypress",function(i){var h;if(i.keyCode==13){h=f.selectedValue;f.selectedValue=null;b.cancel(i);f.settings.onselect(h)}})}f._focused=1});b.add(f.id,"blur",function(){b.remove(f.id,"keydown",f.keyDownHandler);b.remove(f.id,"keypress",f.keyPressHandler);f._focused=0});if(d.isIE6||!c.boxModel){b.add(f.id,"mouseover",function(){if(!c.hasClass(f.id,g+"Disabled")){c.addClass(f.id,g+"Hover")}});b.add(f.id,"mouseout",function(){if(!c.hasClass(f.id,g+"Disabled")){c.removeClass(f.id,g+"Hover")}})}f.onPostRender.dispatch(f,c.get(f.id))},destroy:function(){this.parent();b.clear(this.id+"_text");b.clear(this.id+"_open")}})})(tinymce);(function(d){var c=d.DOM,b=d.dom.Event,e=d.each,a=d.util.Dispatcher;d.create("tinymce.ui.NativeListBox:tinymce.ui.ListBox",{NativeListBox:function(g,f){this.parent(g,f);this.classPrefix="mceNativeListBox"},setDisabled:function(f){c.get(this.id).disabled=f;this.setAriaProperty("disabled",f)},isDisabled:function(){return c.get(this.id).disabled},select:function(h){var g=this,j,i;if(h==undefined){return g.selectByIndex(-1)}if(h&&h.call){i=h}else{i=function(f){return f==h}}if(h!=g.selectedValue){e(g.items,function(k,f){if(i(k.value)){j=1;g.selectByIndex(f);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(f){c.get(this.id).selectedIndex=f+1;this.selectedValue=this.items[f]?this.items[f].value:null},add:function(j,g,f){var i,h=this;f=f||{};f.value=g;if(h.isRendered()){c.add(c.get(this.id),"option",f,j)}i={title:j,value:g,attribs:f};h.items.push(i);h.onAdd.dispatch(h,i)},getLength:function(){return this.items.length},renderHTML:function(){var g,f=this;g=c.createHTML("option",{value:""},"-- "+f.settings.title+" --");e(f.items,function(h){g+=c.createHTML("option",{value:h.value},h.title)});g=c.createHTML("select",{id:f.id,"class":"mceNativeListBox","aria-labelledby":f.id+"_aria"},g);g+=c.createHTML("span",{id:f.id+"_aria",style:"display: none"},f.settings.title);return g},postRender:function(){var g=this,h,i=true;g.rendered=true;function f(k){var j=g.items[k.target.selectedIndex-1];if(j&&(j=j.value)){g.onChange.dispatch(g,j);if(g.settings.onselect){g.settings.onselect(j)}}}b.add(g.id,"change",f);b.add(g.id,"keydown",function(k){var j;b.remove(g.id,"change",h);i=false;j=b.add(g.id,"blur",function(){if(i){return}i=true;b.add(g.id,"change",f);b.remove(g.id,"blur",j)});if(d.isWebKit&&(k.keyCode==37||k.keyCode==39)){return b.prevent(k)}if(k.keyCode==13||k.keyCode==32){f(k);return b.cancel(k)}});g.onPostRender.dispatch(g,c.get(g.id))}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.MenuButton:tinymce.ui.Button",{MenuButton:function(g,f,e){this.parent(g,f,e);this.onRenderMenu=new c.util.Dispatcher(this);f.menu_container=f.menu_container||b.doc.body},showMenu:function(){var g=this,j,i,h=b.get(g.id),f;if(g.isDisabled()){return}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}if(g.isMenuVisible){return g.hideMenu()}j=b.getPos(g.settings.menu_container);i=b.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.vp_offset_x=i.x;f.settings.vp_offset_y=i.y;f.settings.keyboard_focus=g._focused;f.showMenu(0,h.clientHeight);a.add(b.doc,"mousedown",g.hideMenu,g);g.setState("Selected",1);g.isMenuVisible=1},renderMenu:function(){var f=this,e;e=f.settings.control_manager.createDropMenu(f.id+"_menu",{menu_line:1,"class":this.classPrefix+"Menu",icons:f.settings.icons});e.onHideMenu.add(function(){f.hideMenu();f.focus()});f.onRenderMenu.dispatch(f,e);f.menu=e},hideMenu:function(g){var f=this;if(g&&g.type=="mousedown"&&b.getParent(g.target,function(h){return h.id===f.id||h.id===f.id+"_open"})){return}if(!g||!b.getParent(g.target,".mceMenu")){f.setState("Selected",0);a.remove(b.doc,"mousedown",f.hideMenu,f);if(f.menu){f.menu.hideMenu()}}f.isMenuVisible=0},postRender:function(){var e=this,f=e.settings;a.add(e.id,"click",function(){if(!e.isDisabled()){if(f.onclick){f.onclick(e.value)}e.showMenu()}})}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.SplitButton:tinymce.ui.MenuButton",{SplitButton:function(g,f,e){this.parent(g,f,e);this.classPrefix="mceSplitButton"},renderHTML:function(){var i,f=this,g=f.settings,e;i="<tbody><tr>";if(g.image){e=b.createHTML("img ",{src:g.image,role:"presentation","class":"mceAction "+g["class"]})}else{e=b.createHTML("span",{"class":"mceAction "+g["class"]},"")}e+=b.createHTML("span",{"class":"mceVoiceLabel mceIconOnly",id:f.id+"_voice",style:"display:none;"},g.title);i+="<td >"+b.createHTML("a",{role:"button",id:f.id+"_action",tabindex:"-1",href:"javascript:;","class":"mceAction "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"</td>";e=b.createHTML("span",{"class":"mceOpen "+g["class"]},'<span style="display:none;" class="mceIconOnly" aria-hidden="true">\u25BC</span>');i+="<td >"+b.createHTML("a",{role:"button",id:f.id+"_open",tabindex:"-1",href:"javascript:;","class":"mceOpen "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"</td>";i+="</tr></tbody>";i=b.createHTML("table",{role:"presentation","class":"mceSplitButton mceSplitButtonEnabled "+g["class"],cellpadding:"0",cellspacing:"0",title:g.title},i);return b.createHTML("div",{id:f.id,role:"button",tabindex:"0","aria-labelledby":f.id+"_voice","aria-haspopup":"true"},i)},postRender:function(){var e=this,g=e.settings,f;if(g.onclick){f=function(h){if(!e.isDisabled()){g.onclick(e.value);a.cancel(h)}};a.add(e.id+"_action","click",f);a.add(e.id,["click","keydown"],function(h){var k=32,m=14,i=13,j=38,l=40;if((h.keyCode===32||h.keyCode===13||h.keyCode===14)&&!h.altKey&&!h.ctrlKey&&!h.metaKey){f();a.cancel(h)}else{if(h.type==="click"||h.keyCode===l){e.showMenu();a.cancel(h)}}})}a.add(e.id+"_open","click",function(h){e.showMenu();a.cancel(h)});a.add([e.id,e.id+"_open"],"focus",function(){e._focused=1});a.add([e.id,e.id+"_open"],"blur",function(){e._focused=0});if(c.isIE6||!b.boxModel){a.add(e.id,"mouseover",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.addClass(e.id,"mceSplitButtonHover")}});a.add(e.id,"mouseout",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.removeClass(e.id,"mceSplitButtonHover")}})}},destroy:function(){this.parent();a.clear(this.id+"_action");a.clear(this.id+"_open");a.clear(this.id)}})})(tinymce);(function(d){var c=d.DOM,a=d.dom.Event,b=d.is,e=d.each;d.create("tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton",{ColorSplitButton:function(i,h,f){var g=this;g.parent(i,h,f);g.settings=h=d.extend({colors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",grid_width:8,default_color:"#888888"},g.settings);g.onShowMenu=new d.util.Dispatcher(g);g.onHideMenu=new d.util.Dispatcher(g);g.value=h.default_color},showMenu:function(){var f=this,g,j,i,h;if(f.isDisabled()){return}if(!f.isMenuRendered){f.renderMenu();f.isMenuRendered=true}if(f.isMenuVisible){return f.hideMenu()}i=c.get(f.id);c.show(f.id+"_menu");c.addClass(i,"mceSplitButtonSelected");h=c.getPos(i);c.setStyles(f.id+"_menu",{left:h.x,top:h.y+i.clientHeight,zIndex:200000});i=0;a.add(c.doc,"mousedown",f.hideMenu,f);f.onShowMenu.dispatch(f);if(f._focused){f._keyHandler=a.add(f.id+"_menu","keydown",function(k){if(k.keyCode==27){f.hideMenu()}});c.select("a",f.id+"_menu")[0].focus()}f.isMenuVisible=1},hideMenu:function(g){var f=this;if(f.isMenuVisible){if(g&&g.type=="mousedown"&&c.getParent(g.target,function(h){return h.id===f.id+"_open"})){return}if(!g||!c.getParent(g.target,".mceSplitButtonMenu")){c.removeClass(f.id,"mceSplitButtonSelected");a.remove(c.doc,"mousedown",f.hideMenu,f);a.remove(f.id+"_menu","keydown",f._keyHandler);c.hide(f.id+"_menu")}f.isMenuVisible=0;f.onHideMenu.dispatch()}},renderMenu:function(){var p=this,h,k=0,q=p.settings,g,j,l,o,f;o=c.add(q.menu_container,"div",{role:"listbox",id:p.id+"_menu","class":q.menu_class+" "+q["class"],style:"position:absolute;left:0;top:-1000px;"});h=c.add(o,"div",{"class":q["class"]+" mceSplitButtonMenu"});c.add(h,"span",{"class":"mceMenuLine"});g=c.add(h,"table",{role:"presentation","class":"mceColorSplitMenu"});j=c.add(g,"tbody");k=0;e(b(q.colors,"array")?q.colors:q.colors.split(","),function(i){i=i.replace(/^#/,"");if(!k--){l=c.add(j,"tr");k=q.grid_width-1}g=c.add(l,"td");g=c.add(g,"a",{role:"option",href:"javascript:;",style:{backgroundColor:"#"+i},title:p.editor.getLang("colors."+i,i),"data-mce-color":"#"+i});if(p.editor.forcedHighContrastMode){g=c.add(g,"canvas",{width:16,height:16,"aria-hidden":"true"});if(g.getContext&&(f=g.getContext("2d"))){f.fillStyle="#"+i;f.fillRect(0,0,16,16)}else{c.remove(g)}}});if(q.more_colors_func){g=c.add(j,"tr");g=c.add(g,"td",{colspan:q.grid_width,"class":"mceMoreColors"});g=c.add(g,"a",{role:"option",id:p.id+"_more",href:"javascript:;",onclick:"return false;","class":"mceMoreColors"},q.more_colors_title);a.add(g,"click",function(i){q.more_colors_func.call(q.more_colors_scope||this);return a.cancel(i)})}c.addClass(h,"mceColorSplitMenu");new d.ui.KeyboardNavigation({root:p.id+"_menu",items:c.select("a",p.id+"_menu"),onCancel:function(){p.hideMenu();p.focus()}});a.add(p.id+"_menu","mousedown",function(i){return a.cancel(i)});a.add(p.id+"_menu","click",function(i){var m;i=c.getParent(i.target,"a",j);if(i&&i.nodeName.toLowerCase()=="a"&&(m=i.getAttribute("data-mce-color"))){p.setColor(m)}return a.cancel(i)});return o},setColor:function(f){this.displayColor(f);this.hideMenu();this.settings.onselect(f)},displayColor:function(g){var f=this;c.setStyle(f.id+"_preview","backgroundColor",g);f.value=g},postRender:function(){var f=this,g=f.id;f.parent();c.add(g+"_action","div",{id:g+"_preview","class":"mceColorPreview"});c.setStyle(f.id+"_preview","backgroundColor",f.value)},destroy:function(){this.parent();a.clear(this.id+"_menu");a.clear(this.id+"_more");c.remove(this.id+"_menu")}})})(tinymce);(function(b){var d=b.DOM,c=b.each,a=b.dom.Event;b.create("tinymce.ui.ToolbarGroup:tinymce.ui.Container",{renderHTML:function(){var f=this,i=[],e=f.controls,j=b.each,g=f.settings;i.push('<div id="'+f.id+'" role="group" aria-labelledby="'+f.id+'_voice">');i.push("<span role='application'>");i.push('<span id="'+f.id+'_voice" class="mceVoiceLabel" style="display:none;">'+d.encode(g.name)+"</span>");j(e,function(h){i.push(h.renderHTML())});i.push("</span>");i.push("</div>");return i.join("")},focus:function(){var e=this;d.get(e.id).focus()},postRender:function(){var f=this,e=[];c(f.controls,function(g){c(g.controls,function(h){if(h.id){e.push(h)}})});f.keyNav=new b.ui.KeyboardNavigation({root:f.id,items:e,onCancel:function(){if(b.isWebKit){d.get(f.editor.id+"_ifr").focus()}f.editor.focus()},excludeFromTabOrder:!f.settings.tab_focus_toolbar})},destroy:function(){var e=this;e.parent();e.keyNav.destroy();a.clear(e.id)}})})(tinymce);(function(a){var c=a.DOM,b=a.each;a.create("tinymce.ui.Toolbar:tinymce.ui.Container",{renderHTML:function(){var m=this,f="",j,k,n=m.settings,e,d,g,l;l=m.controls;for(e=0;e<l.length;e++){k=l[e];d=l[e-1];g=l[e+1];if(e===0){j="mceToolbarStart";if(k.Button){j+=" mceToolbarStartButton"}else{if(k.SplitButton){j+=" mceToolbarStartSplitButton"}else{if(k.ListBox){j+=" mceToolbarStartListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,"<!-- IE -->"))}if(d&&k.ListBox){if(d.Button||d.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarEnd"},c.createHTML("span",null,"<!-- IE -->"))}}if(c.stdMode){f+='<td style="position: relative">'+k.renderHTML()+"</td>"}else{f+="<td>"+k.renderHTML()+"</td>"}if(g&&k.ListBox){if(g.Button||g.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarStart"},c.createHTML("span",null,"<!-- IE -->"))}}}j="mceToolbarEnd";if(k.Button){j+=" mceToolbarEndButton"}else{if(k.SplitButton){j+=" mceToolbarEndSplitButton"}else{if(k.ListBox){j+=" mceToolbarEndListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,"<!-- IE -->"));return c.createHTML("table",{id:m.id,"class":"mceToolbar"+(n["class"]?" "+n["class"]:""),cellpadding:"0",cellspacing:"0",align:m.settings.align||"",role:"presentation",tabindex:"-1"},"<tbody><tr>"+f+"</tr></tbody>")}})})(tinymce);(function(b){var a=b.util.Dispatcher,c=b.each;b.create("tinymce.AddOnManager",{AddOnManager:function(){var d=this;d.items=[];d.urls={};d.lookup={};d.onAdd=new a(d)},get:function(d){if(this.lookup[d]){return this.lookup[d].instance}else{return undefined}},dependencies:function(e){var d;if(this.lookup[e]){d=this.lookup[e].dependencies}return d||[]},requireLangPack:function(e){var d=b.settings;if(d&&d.language&&d.language_load!==false){b.ScriptLoader.add(this.urls[e]+"/langs/"+d.language+".js")}},add:function(f,e,d){this.items.push(e);this.lookup[f]={instance:e,dependencies:d};this.onAdd.dispatch(this,f,e);return e},createUrl:function(d,e){if(typeof e==="object"){return e}else{return{prefix:d.prefix,resource:e,suffix:d.suffix}}},addComponents:function(f,d){var e=this.urls[f];b.each(d,function(g){b.ScriptLoader.add(e+"/"+g)})},load:function(j,f,d,h){var g=this,e=f;function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.createUrl(f,m);g.load(l.resource,l,undefined,undefined)});if(d){if(h){d.call(h)}else{d.call(b.ScriptLoader)}}}if(g.urls[j]){return}if(typeof f==="object"){e=f.prefix+f.resource+f.suffix}if(e.indexOf("/")!=0&&e.indexOf("://")==-1){e=b.baseURL+"/"+e}g.urls[j]=e.substring(0,e.lastIndexOf("/"));if(g.lookup[j]){i()}else{b.ScriptLoader.add(e,i,h)}}});b.PluginManager=new b.AddOnManager();b.ThemeManager=new b.AddOnManager()}(tinymce));(function(j){var g=j.each,d=j.extend,k=j.DOM,i=j.dom.Event,f=j.ThemeManager,b=j.PluginManager,e=j.explode,h=j.util.Dispatcher,a,c=0;j.documentBaseURL=window.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,"");if(!/[\/\\]$/.test(j.documentBaseURL)){j.documentBaseURL+="/"}j.baseURL=new j.util.URI(j.documentBaseURL).toAbsolute(j.baseURL);j.baseURI=new j.util.URI(j.baseURL);j.onBeforeUnload=new h(j);i.add(window,"beforeunload",function(l){j.onBeforeUnload.dispatch(j,l)});j.onAddEditor=new h(j);j.onRemoveEditor=new h(j);j.EditorManager=d(j,{editors:[],i18n:{},activeEditor:null,init:function(q){var n=this,p,l=j.ScriptLoader,u,o=[],m;function r(x,y,t){var v=x[y];if(!v){return}if(j.is(v,"string")){t=v.replace(/\.\w+$/,"");t=t?j.resolve(t):0;v=j.resolve(v)}return v.apply(t||this,Array.prototype.slice.call(arguments,2))}q=d({theme:"simple",language:"en"},q);n.settings=q;i.add(document,"init",function(){var s,v;r(q,"onpageload");switch(q.mode){case"exact":s=q.elements||"";if(s.length>0){g(e(s),function(x){if(k.get(x)){m=new j.Editor(x,q);o.push(m);m.render(1)}else{g(document.forms,function(y){g(y.elements,function(z){if(z.name===x){x="mce_editor_"+c++;k.setAttrib(z,"id",x);m=new j.Editor(x,q);o.push(m);m.render(1)}})})}})}break;case"textareas":case"specific_textareas":function t(y,x){return x.constructor===RegExp?x.test(y.className):k.hasClass(y,x)}g(k.select("textarea"),function(x){if(q.editor_deselector&&t(x,q.editor_deselector)){return}if(!q.editor_selector||t(x,q.editor_selector)){u=k.get(x.name);if(!x.id&&!u){x.id=x.name}if(!x.id||n.get(x.id)){x.id=k.uniqueId()}m=new j.Editor(x.id,q);o.push(m);m.render(1)}});break}if(q.oninit){s=v=0;g(o,function(x){v++;if(!x.initialized){x.onInit.add(function(){s++;if(s==v){r(q,"oninit")}})}else{s++}if(s==v){r(q,"oninit")}})}})},get:function(l){if(l===a){return this.editors}return this.editors[l]},getInstanceById:function(l){return this.get(l)},add:function(m){var l=this,n=l.editors;n[m.id]=m;n.push(m);l._setActive(m);l.onAddEditor.dispatch(l,m);return m},remove:function(n){var m=this,l,o=m.editors;if(!o[n.id]){return null}delete o[n.id];for(l=0;l<o.length;l++){if(o[l]==n){o.splice(l,1);break}}if(m.activeEditor==n){m._setActive(o[0])}n.destroy();m.onRemoveEditor.dispatch(m,n);return n},execCommand:function(r,p,o){var q=this,n=q.get(o),l;switch(r){case"mceFocus":n.focus();return true;case"mceAddEditor":case"mceAddControl":if(!q.get(o)){new j.Editor(o,q.settings).render()}return true;case"mceAddFrameControl":l=o.window;l.tinyMCE=tinyMCE;l.tinymce=j;j.DOM.doc=l.document;j.DOM.win=l;n=new j.Editor(o.element_id,o);n.render();if(j.isIE){function m(){n.destroy();l.detachEvent("onunload",m);l=l.tinyMCE=l.tinymce=null}l.attachEvent("onunload",m)}o.page_window=null;return true;case"mceRemoveEditor":case"mceRemoveControl":if(n){n.remove()}return true;case"mceToggleEditor":if(!n){q.execCommand("mceAddControl",0,o);return true}if(n.isHidden()){n.show()}else{n.hide()}return true}if(q.activeEditor){return q.activeEditor.execCommand(r,p,o)}return false},execInstanceCommand:function(p,o,n,m){var l=this.get(p);if(l){return l.execCommand(o,n,m)}return false},triggerSave:function(){g(this.editors,function(l){l.save()})},addI18n:function(n,q){var l,m=this.i18n;if(!j.is(n,"string")){g(n,function(r,p){g(r,function(t,s){g(t,function(v,u){if(s==="common"){m[p+"."+u]=v}else{m[p+"."+s+"."+u]=v}})})})}else{g(q,function(r,p){m[n+"."+p]=r})}},_setActive:function(l){this.selectedInstance=this.activeEditor=l}})})(tinymce);(function(m){var n=m.DOM,j=m.dom.Event,f=m.extend,k=m.util.Dispatcher,i=m.each,a=m.isGecko,b=m.isIE,e=m.isWebKit,d=m.is,h=m.ThemeManager,c=m.PluginManager,o=m.inArray,l=m.grep,g=m.explode;m.create("tinymce.Editor",{Editor:function(r,q){var p=this;p.id=p.editorId=r;p.execCommands={};p.queryStateCommands={};p.queryValueCommands={};p.isNotDirty=false;p.plugins={};i(["onPreInit","onBeforeRenderUI","onPostRender","onInit","onRemove","onActivate","onDeactivate","onClick","onEvent","onMouseUp","onMouseDown","onDblClick","onKeyDown","onKeyUp","onKeyPress","onContextMenu","onSubmit","onReset","onPaste","onPreProcess","onPostProcess","onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent","onLoadContent","onSaveContent","onNodeChange","onChange","onBeforeExecCommand","onExecCommand","onUndo","onRedo","onVisualAid","onSetProgressState"],function(s){p[s]=new k(p)});p.settings=q=f({id:r,language:"en",docs_language:"en",theme:"simple",skin:"default",delta_width:0,delta_height:0,popup_css:"",plugins:"",document_base_url:m.documentBaseURL,add_form_submit_trigger:1,submit_patch:1,add_unload_trigger:1,convert_urls:1,relative_urls:1,remove_script_host:1,table_inline_editing:0,object_resizing:1,cleanup:1,accessibility_focus:1,custom_shortcuts:1,custom_undo_redo_keyboard_shortcuts:1,custom_undo_redo_restore_selection:1,custom_undo_redo:1,doctype:m.isIE6?'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">':"<!DOCTYPE>",visual_table_class:"mceItemTable",visual:1,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",apply_source_formatting:1,directionality:"ltr",forced_root_block:"p",hidden_input:1,padd_empty_editor:1,render_ui:1,init_theme:1,force_p_newlines:1,indentation:"30px",keep_styles:1,fix_table_elements:1,inline_styles:1,convert_fonts_to_spans:true,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr",validate:true,entity_encoding:"named",url_converter:p.convertURL,url_converter_scope:p,ie7_compat:true},q);p.documentBaseURI=new m.util.URI(q.document_base_url||m.documentBaseURL,{base_uri:tinyMCE.baseURI});p.baseURI=m.baseURI;p.contentCSS=[];p.execCallback("setup",p)},render:function(r){var u=this,v=u.settings,x=u.id,p=m.ScriptLoader;if(!j.domLoaded){j.add(document,"init",function(){u.render()});return}tinyMCE.settings=v;if(!u.getElement()){return}if(m.isIDevice&&!m.isIOS5){return}if(!/TEXTAREA|INPUT/i.test(u.getElement().nodeName)&&v.hidden_input&&n.getParent(x,"form")){n.insertAfter(n.create("input",{type:"hidden",name:x}),x)}if(m.WindowManager){u.windowManager=new m.WindowManager(u)}if(v.encoding=="xml"){u.onGetContent.add(function(s,t){if(t.save){t.content=n.encode(t.content)}})}if(v.add_form_submit_trigger){u.onSubmit.addToTop(function(){if(u.initialized){u.save();u.isNotDirty=1}})}if(v.add_unload_trigger){u._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(u.initialized&&!u.destroyed&&!u.isHidden()){u.save({format:"raw",no_events:true})}})}m.addUnload(u.destroy,u);if(v.submit_patch){u.onBeforeRenderUI.add(function(){var s=u.getElement().form;if(!s){return}if(s._mceOldSubmit){return}if(!s.submit.nodeType&&!s.submit.length){u.formElement=s;s._mceOldSubmit=s.submit;s.submit=function(){m.triggerSave();u.isNotDirty=1;return u.formElement._mceOldSubmit(u.formElement)}}s=null})}function q(){if(v.language&&v.language_load!==false){p.add(m.baseURL+"/langs/"+v.language+".js")}if(v.theme&&v.theme.charAt(0)!="-"&&!h.urls[v.theme]){h.load(v.theme,"themes/"+v.theme+"/editor_template"+m.suffix+".js")}i(g(v.plugins),function(t){if(t&&!c.urls[t]){if(t.charAt(0)=="-"){t=t.substr(1,t.length);var s=c.dependencies(t);i(s,function(z){var y={prefix:"plugins/",resource:z,suffix:"/editor_plugin"+m.suffix+".js"};var z=c.createUrl(y,z);c.load(z.resource,z)})}else{if(t=="safari"){return}c.load(t,{prefix:"plugins/",resource:t,suffix:"/editor_plugin"+m.suffix+".js"})}}});p.loadQueue(function(){if(!u.removed){u.init()}})}q()},init:function(){var r,H=this,I=H.settings,E,A,D=H.getElement(),q,p,F,y,C,G,z,v=[];m.add(H);I.aria_label=I.aria_label||n.getAttrib(D,"aria-label",H.getLang("aria.rich_text_area"));if(I.theme){I.theme=I.theme.replace(/-/,"");q=h.get(I.theme);H.theme=new q();if(H.theme.init&&I.init_theme){H.theme.init(H,h.urls[I.theme]||m.documentBaseURL.replace(/\/$/,""))}}function B(J){var K=c.get(J),t=c.urls[J]||m.documentBaseURL.replace(/\/$/,""),s;if(K&&m.inArray(v,J)===-1){i(c.dependencies(J),function(u){B(u)});s=new K(H,t);H.plugins[J]=s;if(s.init){s.init(H,t);v.push(J)}}}i(g(I.plugins.replace(/\-/g,"")),B);if(I.popup_css!==false){if(I.popup_css){I.popup_css=H.documentBaseURI.toAbsolute(I.popup_css)}else{I.popup_css=H.baseURI.toAbsolute("themes/"+I.theme+"/skins/"+I.skin+"/dialog.css")}}if(I.popup_css_add){I.popup_css+=","+H.documentBaseURI.toAbsolute(I.popup_css_add)}H.controlManager=new m.ControlManager(H);if(I.custom_undo_redo){H.onBeforeExecCommand.add(function(t,J,u,K,s){if(J!="Undo"&&J!="Redo"&&J!="mceRepaint"&&(!s||!s.skip_undo)){H.undoManager.beforeChange()}});H.onExecCommand.add(function(t,J,u,K,s){if(J!="Undo"&&J!="Redo"&&J!="mceRepaint"&&(!s||!s.skip_undo)){H.undoManager.add()}})}H.onExecCommand.add(function(s,t){if(!/^(FontName|FontSize)$/.test(t)){H.nodeChanged()}});if(a){function x(s,t){if(!t||!t.initial){H.execCommand("mceRepaint")}}H.onUndo.add(x);H.onRedo.add(x);H.onSetContent.add(x)}H.onBeforeRenderUI.dispatch(H,H.controlManager);if(I.render_ui){E=I.width||D.style.width||D.offsetWidth;A=I.height||D.style.height||D.offsetHeight;H.orgDisplay=D.style.display;G=/^[0-9\.]+(|px)$/i;if(G.test(""+E)){E=Math.max(parseInt(E)+(q.deltaWidth||0),100)}if(G.test(""+A)){A=Math.max(parseInt(A)+(q.deltaHeight||0),100)}q=H.theme.renderUI({targetNode:D,width:E,height:A,deltaWidth:I.delta_width,deltaHeight:I.delta_height});H.editorContainer=q.editorContainer}if(document.domain&&location.hostname!=document.domain){m.relaxedDomain=document.domain}n.setStyles(q.sizeContainer||q.editorContainer,{width:E,height:A});if(I.content_css){m.each(g(I.content_css),function(s){H.contentCSS.push(H.documentBaseURI.toAbsolute(s))})}A=(q.iframeHeight||A)+(typeof(A)=="number"?(q.deltaHeight||0):"");if(A<100){A=100}H.iframeHTML=I.doctype+'<html><head xmlns="http://www.w3.org/1999/xhtml">';if(I.document_base_url!=m.documentBaseURL){H.iframeHTML+='<base href="'+H.documentBaseURI.getURI()+'" />'}if(I.ie7_compat){H.iframeHTML+='<meta http-equiv="X-UA-Compatible" content="IE=7" />'}else{H.iframeHTML+='<meta http-equiv="X-UA-Compatible" content="IE=edge" />'}H.iframeHTML+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';for(z=0;z<H.contentCSS.length;z++){H.iframeHTML+='<link type="text/css" rel="stylesheet" href="'+H.contentCSS[z]+'" />'}y=I.body_id||"tinymce";if(y.indexOf("=")!=-1){y=H.getParam("body_id","","hash");y=y[H.id]||y}C=I.body_class||"";if(C.indexOf("=")!=-1){C=H.getParam("body_class","","hash");C=C[H.id]||""}H.iframeHTML+='</head><body id="'+y+'" class="mceContentBody '+C+'"><br></body></html>';if(m.relaxedDomain&&(b||(m.isOpera&&parseFloat(opera.version())<11))){F='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+H.id+'");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()'}r=n.add(q.iframeContainer,"iframe",{id:H.id+"_ifr",src:F||'javascript:""',frameBorder:"0",allowTransparency:"true",title:I.aria_label,style:{width:"100%",height:A,display:"block"}});H.contentAreaContainer=q.iframeContainer;n.get(q.editorContainer).style.display=H.orgDisplay;n.get(H.id).style.display="none";n.setAttrib(H.id,"aria-hidden",true);if(!m.relaxedDomain||!F){H.setupIframe()}D=r=q=null},setupIframe:function(){var q=this,v=q.settings,x=n.get(q.id),y=q.getDoc(),u,p;if(!b||!m.relaxedDomain){y.open();y.write(q.iframeHTML);y.close();if(m.relaxedDomain){y.domain=m.relaxedDomain}}p=q.getBody();p.disabled=true;if(!v.readonly){p.contentEditable=true}p.disabled=false;q.schema=new m.html.Schema(v);q.dom=new m.dom.DOMUtils(q.getDoc(),{keep_values:true,url_converter:q.convertURL,url_converter_scope:q,hex_colors:v.force_hex_style_colors,class_filter:v.class_filter,update_styles:1,fix_ie_paragraphs:1,schema:q.schema});q.parser=new m.html.DomParser(v,q.schema);if(!q.settings.allow_html_in_named_anchor){q.parser.addAttributeFilter("name",function(s,t){var A=s.length,C,z,B,D;while(A--){D=s[A];if(D.name==="a"&&D.firstChild){B=D.parent;C=D.lastChild;do{z=C.prev;B.insert(C,D);C=z}while(C)}}})}q.parser.addAttributeFilter("src,href,style",function(s,t){var z=s.length,B,D=q.dom,C,A;while(z--){B=s[z];C=B.attr(t);A="data-mce-"+t;if(!B.attributes.map[A]){if(t==="style"){B.attr(A,D.serializeStyle(D.parseStyle(C),B.name))}else{B.attr(A,q.convertURL(C,t,B.name))}}}});q.parser.addNodeFilter("script",function(s,t){var z=s.length;while(z--){s[z].attr("type","mce-text/javascript")}});q.parser.addNodeFilter("#cdata",function(s,t){var z=s.length,A;while(z--){A=s[z];A.type=8;A.name="#comment";A.value="[CDATA["+A.value+"]]"}});q.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(t,z){var A=t.length,B,s=q.schema.getNonEmptyElements();while(A--){B=t[A];if(B.isEmpty(s)){B.empty().append(new m.html.Node("br",1)).shortEnded=true}}});q.serializer=new m.dom.Serializer(v,q.dom,q.schema);q.selection=new m.dom.Selection(q.dom,q.getWin(),q.serializer);q.formatter=new m.Formatter(this);q.formatter.register({alignleft:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"left"}},{selector:"img,table",collapsed:false,styles:{"float":"left"}}],aligncenter:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"center"}},{selector:"img",collapsed:false,styles:{display:"block",marginLeft:"auto",marginRight:"auto"}},{selector:"table",collapsed:false,styles:{marginLeft:"auto",marginRight:"auto"}}],alignright:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"right"}},{selector:"img,table",collapsed:false,styles:{"float":"right"}}],alignfull:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"justify"}}],bold:[{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all"}],italic:[{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all"}],underline:[{inline:"span",styles:{textDecoration:"underline"},exact:true},{inline:"u",remove:"all"}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:true},{inline:"strike",remove:"all"}],forecolor:{inline:"span",styles:{color:"%value"},wrap_links:false},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},wrap_links:false},fontname:{inline:"span",styles:{fontFamily:"%value"}},fontsize:{inline:"span",styles:{fontSize:"%value"}},fontsize_class:{inline:"span",attributes:{"class":"%value"}},blockquote:{block:"blockquote",wrapper:1,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},link:{inline:"a",selector:"a",remove:"all",split:true,deep:true,onmatch:function(s){return true},onformat:function(z,s,t){i(t,function(B,A){q.dom.setAttrib(z,A,B)})}},removeformat:[{selector:"b,strong,em,i,font,u,strike",remove:"all",split:true,expand:false,block_expand:true,deep:true},{selector:"span",attributes:["style","class"],remove:"empty",split:true,expand:false,deep:true},{selector:"*",attributes:["style","class"],split:false,expand:false,deep:true}]});i("p h1 h2 h3 h4 h5 h6 div address pre div code dt dd samp".split(/\s/),function(s){q.formatter.register(s,{block:s,remove:"all"})});q.formatter.register(q.settings.formats);q.undoManager=new m.UndoManager(q);q.undoManager.onAdd.add(function(t,s){if(t.hasUndo()){return q.onChange.dispatch(q,s,t)}});q.undoManager.onUndo.add(function(t,s){return q.onUndo.dispatch(q,s,t)});q.undoManager.onRedo.add(function(t,s){return q.onRedo.dispatch(q,s,t)});q.forceBlocks=new m.ForceBlocks(q,{forced_root_block:v.forced_root_block});q.editorCommands=new m.EditorCommands(q);q.serializer.onPreProcess.add(function(s,t){return q.onPreProcess.dispatch(q,t,s)});q.serializer.onPostProcess.add(function(s,t){return q.onPostProcess.dispatch(q,t,s)});q.onPreInit.dispatch(q);if(!v.gecko_spellcheck){q.getBody().spellcheck=0}if(!v.readonly){q._addEvents()}q.controlManager.onPostRender.dispatch(q,q.controlManager);q.onPostRender.dispatch(q);q.quirks=new m.util.Quirks(this);if(v.directionality){q.getBody().dir=v.directionality}if(v.nowrap){q.getBody().style.whiteSpace="nowrap"}if(v.handle_node_change_callback){q.onNodeChange.add(function(t,s,z){q.execCallback("handle_node_change_callback",q.id,z,-1,-1,true,q.selection.isCollapsed())})}if(v.save_callback){q.onSaveContent.add(function(s,z){var t=q.execCallback("save_callback",q.id,z.content,q.getBody());if(t){z.content=t}})}if(v.onchange_callback){q.onChange.add(function(t,s){q.execCallback("onchange_callback",q,s)})}if(v.protect){q.onBeforeSetContent.add(function(s,t){if(v.protect){i(v.protect,function(z){t.content=t.content.replace(z,function(A){return"<!--mce:protected "+escape(A)+"-->"})})}})}if(v.convert_newlines_to_brs){q.onBeforeSetContent.add(function(s,t){if(t.initial){t.content=t.content.replace(/\r?\n/g,"<br />")}})}if(v.preformatted){q.onPostProcess.add(function(s,t){t.content=t.content.replace(/^\s*<pre.*?>/,"");t.content=t.content.replace(/<\/pre>\s*$/,"");if(t.set){t.content='<pre class="mceItemHidden">'+t.content+"</pre>"}})}if(v.verify_css_classes){q.serializer.attribValueFilter=function(B,z){var A,t;if(B=="class"){if(!q.classesRE){t=q.dom.getClasses();if(t.length>0){A="";i(t,function(s){A+=(A?"|":"")+s["class"]});q.classesRE=new RegExp("("+A+")","gi")}}return !q.classesRE||/(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(z)||q.classesRE.test(z)?z:""}return z}}if(v.cleanup_callback){q.onBeforeSetContent.add(function(s,t){t.content=q.execCallback("cleanup_callback","insert_to_editor",t.content,t)});q.onPreProcess.add(function(s,t){if(t.set){q.execCallback("cleanup_callback","insert_to_editor_dom",t.node,t)}if(t.get){q.execCallback("cleanup_callback","get_from_editor_dom",t.node,t)}});q.onPostProcess.add(function(s,t){if(t.set){t.content=q.execCallback("cleanup_callback","insert_to_editor",t.content,t)}if(t.get){t.content=q.execCallback("cleanup_callback","get_from_editor",t.content,t)}})}if(v.save_callback){q.onGetContent.add(function(s,t){if(t.save){t.content=q.execCallback("save_callback",q.id,t.content,q.getBody())}})}if(v.handle_event_callback){q.onEvent.add(function(s,t,z){if(q.execCallback("handle_event_callback",t,s,z)===false){j.cancel(t)}})}q.onSetContent.add(function(){q.addVisual(q.getBody())});if(v.padd_empty_editor){q.onPostProcess.add(function(s,t){t.content=t.content.replace(/^(<p[^>]*>(&nbsp;|&#160;|\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/,"")})}if(a){function r(s,t){i(s.dom.select("a"),function(A){var z=A.parentNode;if(s.dom.isBlock(z)&&z.lastChild===A){s.dom.add(z,"br",{"data-mce-bogus":1})}})}q.onExecCommand.add(function(s,t){if(t==="CreateLink"){r(s)}});q.onSetContent.add(q.selection.onSetContent.add(r))}q.load({initial:true,format:"html"});q.startContent=q.getContent({format:"raw"});q.undoManager.add();q.initialized=true;q.onInit.dispatch(q);q.execCallback("setupcontent_callback",q.id,q.getBody(),q.getDoc());q.execCallback("init_instance_callback",q);q.focus(true);q.nodeChanged({initial:1});i(q.contentCSS,function(s){q.dom.loadCSS(s)});if(v.auto_focus){setTimeout(function(){var s=m.get(v.auto_focus);s.selection.select(s.getBody(),1);s.selection.collapse(1);s.getBody().focus();s.getWin().focus()},100)}x=null},focus:function(u){var y,q=this,s=q.selection,x=q.settings.content_editable,r,p,v=q.getDoc();if(!u){r=s.getRng();if(r.item){p=r.item(0)}q._refreshContentEditable();s.normalize();if(!x){q.getWin().focus()}if(m.isGecko){q.getBody().focus()}if(p&&p.ownerDocument==v){r=v.body.createControlRange();r.addElement(p);r.select()}}if(m.activeEditor!=q){if((y=m.activeEditor)!=null){y.onDeactivate.dispatch(y,q)}q.onActivate.dispatch(q,y)}m._setActive(q)},execCallback:function(u){var p=this,r=p.settings[u],q;if(!r){return}if(p.callbackLookup&&(q=p.callbackLookup[u])){r=q.func;q=q.scope}if(d(r,"string")){q=r.replace(/\.\w+$/,"");q=q?m.resolve(q):0;r=m.resolve(r);p.callbackLookup=p.callbackLookup||{};p.callbackLookup[u]={func:r,scope:q}}return r.apply(q||p,Array.prototype.slice.call(arguments,1))},translate:function(p){var r=this.settings.language||"en",q=m.i18n;if(!p){return""}return q[r+"."+p]||p.replace(/{\#([^}]+)\}/g,function(t,s){return q[r+"."+s]||"{#"+s+"}"})},getLang:function(q,p){return m.i18n[(this.settings.language||"en")+"."+q]||(d(p)?p:"{#"+q+"}")},getParam:function(u,r,p){var s=m.trim,q=d(this.settings[u])?this.settings[u]:r,t;if(p==="hash"){t={};if(d(q,"string")){i(q.indexOf("=")>0?q.split(/[;,](?![^=;,]*(?:[;,]|$))/):q.split(","),function(x){x=x.split("=");if(x.length>1){t[s(x[0])]=s(x[1])}else{t[s(x[0])]=s(x)}})}else{t=q}return t}return q},nodeChanged:function(r){var p=this,q=p.selection,u=q.getStart()||p.getBody();if(p.initialized){r=r||{};u=b&&u.ownerDocument!=p.getDoc()?p.getBody():u;r.parents=[];p.dom.getParent(u,function(s){if(s.nodeName=="BODY"){return true}r.parents.push(s)});p.onNodeChange.dispatch(p,r?r.controlManager||p.controlManager:p.controlManager,u,q.isCollapsed(),r)}},addButton:function(r,q){var p=this;p.buttons=p.buttons||{};p.buttons[r]=q},addCommand:function(p,r,q){this.execCommands[p]={func:r,scope:q||this}},addQueryStateHandler:function(p,r,q){this.queryStateCommands[p]={func:r,scope:q||this}},addQueryValueHandler:function(p,r,q){this.queryValueCommands[p]={func:r,scope:q||this}},addShortcut:function(r,u,p,s){var q=this,v;if(!q.settings.custom_shortcuts){return false}q.shortcuts=q.shortcuts||{};if(d(p,"string")){v=p;p=function(){q.execCommand(v,false,null)}}if(d(p,"object")){v=p;p=function(){q.execCommand(v[0],v[1],v[2])}}i(g(r),function(t){var x={func:p,scope:s||this,desc:u,alt:false,ctrl:false,shift:false};i(g(t,"+"),function(y){switch(y){case"alt":case"ctrl":case"shift":x[y]=true;break;default:x.charCode=y.charCodeAt(0);x.keyCode=y.toUpperCase().charCodeAt(0)}});q.shortcuts[(x.ctrl?"ctrl":"")+","+(x.alt?"alt":"")+","+(x.shift?"shift":"")+","+x.keyCode]=x});return true},execCommand:function(x,v,z,p){var r=this,u=0,y,q;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(x)&&(!p||!p.skip_focus)){r.focus()}y={};r.onBeforeExecCommand.dispatch(r,x,v,z,y);if(y.terminate){return false}if(r.execCallback("execcommand_callback",r.id,r.selection.getNode(),x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);return true}if(y=r.execCommands[x]){q=y.func.call(y.scope,v,z);if(q!==true){r.onExecCommand.dispatch(r,x,v,z,p);return q}}i(r.plugins,function(s){if(s.execCommand&&s.execCommand(x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);u=1;return false}});if(u){return true}if(r.theme&&r.theme.execCommand&&r.theme.execCommand(x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);return true}if(r.editorCommands.execCommand(x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);return true}r.getDoc().execCommand(x,v,z);r.onExecCommand.dispatch(r,x,v,z,p)},queryCommandState:function(u){var q=this,v,r;if(q._isHidden()){return}if(v=q.queryStateCommands[u]){r=v.func.call(v.scope);if(r!==true){return r}}v=q.editorCommands.queryCommandState(u);if(v!==-1){return v}try{return this.getDoc().queryCommandState(u)}catch(p){}},queryCommandValue:function(v){var q=this,u,r;if(q._isHidden()){return}if(u=q.queryValueCommands[v]){r=u.func.call(u.scope);if(r!==true){return r}}u=q.editorCommands.queryCommandValue(v);if(d(u)){return u}try{return this.getDoc().queryCommandValue(v)}catch(p){}},show:function(){var p=this;n.show(p.getContainer());n.hide(p.id);p.load()},hide:function(){var p=this,q=p.getDoc();if(b&&q){q.execCommand("SelectAll")}p.save();n.hide(p.getContainer());n.setStyle(p.id,"display",p.orgDisplay)},isHidden:function(){return !n.isHidden(this.id)},setProgressState:function(p,q,r){this.onSetProgressState.dispatch(this,p,q,r);return p},load:function(s){var p=this,r=p.getElement(),q;if(r){s=s||{};s.load=true;q=p.setContent(d(r.value)?r.value:r.innerHTML,s);s.element=r;if(!s.no_events){p.onLoadContent.dispatch(p,s)}s.element=r=null;return q}},save:function(u){var p=this,s=p.getElement(),q,r;if(!s||!p.initialized){return}u=u||{};u.save=true;if(!u.no_events){p.undoManager.typing=false;p.undoManager.add()}u.element=s;q=u.content=p.getContent(u);if(!u.no_events){p.onSaveContent.dispatch(p,u)}q=u.content;if(!/TEXTAREA|INPUT/i.test(s.nodeName)){s.innerHTML=q;if(r=n.getParent(p.id,"form")){i(r.elements,function(t){if(t.name==p.id){t.value=q;return false}})}}else{s.value=q}u.element=s=null;return q},setContent:function(u,s){var r=this,q,p=r.getBody(),t;s=s||{};s.format=s.format||"html";s.set=true;s.content=u;if(!s.no_events){r.onBeforeSetContent.dispatch(r,s)}u=s.content;if(!m.isIE&&(u.length===0||/^\s+$/.test(u))){t=r.settings.forced_root_block;if(t){u="<"+t+'><br data-mce-bogus="1"></'+t+">"}else{u='<br data-mce-bogus="1">'}p.innerHTML=u;r.selection.select(p,true);r.selection.collapse(true);return}if(s.format!=="raw"){u=new m.html.Serializer({},r.schema).serialize(r.parser.parse(u))}s.content=m.trim(u);r.dom.setHTML(p,s.content);if(!s.no_events){r.onSetContent.dispatch(r,s)}r.selection.normalize();return s.content},getContent:function(q){var p=this,r;q=q||{};q.format=q.format||"html";q.get=true;if(!q.no_events){p.onBeforeGetContent.dispatch(p,q)}if(q.format=="raw"){r=p.getBody().innerHTML}else{r=p.serializer.serialize(p.getBody(),q)}q.content=m.trim(r);if(!q.no_events){p.onGetContent.dispatch(p,q)}return q.content},isDirty:function(){var p=this;return m.trim(p.startContent)!=m.trim(p.getContent({format:"raw",no_events:1}))&&!p.isNotDirty},getContainer:function(){var p=this;if(!p.container){p.container=n.get(p.editorContainer||p.id+"_parent")}return p.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return n.get(this.settings.content_element||this.id)},getWin:function(){var p=this,q;if(!p.contentWindow){q=n.get(p.id+"_ifr");if(q){p.contentWindow=q.contentWindow}}return p.contentWindow},getDoc:function(){var q=this,p;if(!q.contentDocument){p=q.getWin();if(p){q.contentDocument=p.document}}return q.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(p,x,v){var q=this,r=q.settings;if(r.urlconverter_callback){return q.execCallback("urlconverter_callback",p,v,true,x)}if(!r.convert_urls||(v&&v.nodeName=="LINK")||p.indexOf("file:")===0){return p}if(r.relative_urls){return q.documentBaseURI.toRelative(p)}p=q.documentBaseURI.toAbsolute(p,r.remove_script_host);return p},addVisual:function(r){var p=this,q=p.settings;r=r||p.getBody();if(!d(p.hasVisual)){p.hasVisual=q.visual}i(p.dom.select("table,a",r),function(t){var s;switch(t.nodeName){case"TABLE":s=p.dom.getAttrib(t,"border");if(!s||s=="0"){if(p.hasVisual){p.dom.addClass(t,q.visual_table_class)}else{p.dom.removeClass(t,q.visual_table_class)}}return;case"A":s=p.dom.getAttrib(t,"name");if(s){if(p.hasVisual){p.dom.addClass(t,"mceItemAnchor")}else{p.dom.removeClass(t,"mceItemAnchor")}}return}});p.onVisualAid.dispatch(p,r,p.hasVisual)},remove:function(){var p=this,q=p.getContainer();p.removed=1;p.hide();p.execCallback("remove_instance_callback",p);p.onRemove.dispatch(p);p.onExecCommand.listeners=[];m.remove(p);n.remove(q)},destroy:function(q){var p=this;if(p.destroyed){return}if(!q){m.removeUnload(p.destroy);tinyMCE.onBeforeUnload.remove(p._beforeUnload);if(p.theme&&p.theme.destroy){p.theme.destroy()}p.controlManager.destroy();p.selection.destroy();p.dom.destroy();if(!p.settings.content_editable){j.clear(p.getWin());j.clear(p.getDoc())}j.clear(p.getBody());j.clear(p.formElement)}if(p.formElement){p.formElement.submit=p.formElement._mceOldSubmit;p.formElement._mceOldSubmit=null}p.contentAreaContainer=p.formElement=p.container=p.settings.content_element=p.bodyElement=p.contentDocument=p.contentWindow=null;if(p.selection){p.selection=p.selection.win=p.selection.dom=p.selection.dom.doc=null}p.destroyed=1},_addEvents:function(){var B=this,r,C=B.settings,q=B.dom,x={mouseup:"onMouseUp",mousedown:"onMouseDown",click:"onClick",keyup:"onKeyUp",keydown:"onKeyDown",keypress:"onKeyPress",submit:"onSubmit",reset:"onReset",contextmenu:"onContextMenu",dblclick:"onDblClick",paste:"onPaste"};function p(t,D){var s=t.type;if(B.removed){return}if(B.onEvent.dispatch(B,t,D)!==false){B[x[t.fakeType||t.type]].dispatch(B,t,D)}}i(x,function(t,s){switch(s){case"contextmenu":q.bind(B.getDoc(),s,p);break;case"paste":q.bind(B.getBody(),s,function(D){p(D)});break;case"submit":case"reset":q.bind(B.getElement().form||n.getParent(B.id,"form"),s,p);break;default:q.bind(C.content_editable?B.getBody():B.getDoc(),s,p)}});q.bind(C.content_editable?B.getBody():(a?B.getDoc():B.getWin()),"focus",function(s){B.focus(true)});if(m.isGecko){q.bind(B.getDoc(),"DOMNodeInserted",function(t){var s;t=t.target;if(t.nodeType===1&&t.nodeName==="IMG"&&(s=t.getAttribute("data-mce-src"))){t.src=B.documentBaseURI.toAbsolute(s)}})}if(a){function u(){var E=this,G=E.getDoc(),F=E.settings;if(a&&!F.readonly){E._refreshContentEditable();try{G.execCommand("styleWithCSS",0,false)}catch(D){if(!E._isHidden()){try{G.execCommand("useCSS",0,true)}catch(D){}}}if(!F.table_inline_editing){try{G.execCommand("enableInlineTableEditing",false,false)}catch(D){}}if(!F.object_resizing){try{G.execCommand("enableObjectResizing",false,false)}catch(D){}}}}B.onBeforeExecCommand.add(u);B.onMouseDown.add(u)}B.onMouseUp.add(B.nodeChanged);B.onKeyUp.add(function(s,t){var D=t.keyCode;if((D>=33&&D<=36)||(D>=37&&D<=40)||D==13||D==45||D==46||D==8||(m.isMac&&(D==91||D==93))||t.ctrlKey){B.nodeChanged()}});B.onKeyDown.add(function(t,D){if(D.keyCode!=8){return}var F=t.selection.getRng().startContainer;var E=t.selection.getRng().startOffset;while(F&&F.nodeType&&F.nodeType!=1&&F.parentNode){F=F.parentNode}if(F&&F.parentNode&&F.parentNode.tagName==="BLOCKQUOTE"&&F.parentNode.firstChild==F&&E==0){t.formatter.toggle("blockquote",null,F.parentNode);var s=t.selection.getRng();s.setStart(F,0);s.setEnd(F,0);t.selection.setRng(s);t.selection.collapse(false)}});B.onReset.add(function(){B.setContent(B.startContent,{format:"raw"})});if(C.custom_shortcuts){if(C.custom_undo_redo_keyboard_shortcuts){B.addShortcut("ctrl+z",B.getLang("undo_desc"),"Undo");B.addShortcut("ctrl+y",B.getLang("redo_desc"),"Redo")}B.addShortcut("ctrl+b",B.getLang("bold_desc"),"Bold");B.addShortcut("ctrl+i",B.getLang("italic_desc"),"Italic");B.addShortcut("ctrl+u",B.getLang("underline_desc"),"Underline");for(r=1;r<=6;r++){B.addShortcut("ctrl+"+r,"",["FormatBlock",false,"h"+r])}B.addShortcut("ctrl+7","",["FormatBlock",false,"p"]);B.addShortcut("ctrl+8","",["FormatBlock",false,"div"]);B.addShortcut("ctrl+9","",["FormatBlock",false,"address"]);function v(t){var s=null;if(!t.altKey&&!t.ctrlKey&&!t.metaKey){return s}i(B.shortcuts,function(D){if(m.isMac&&D.ctrl!=t.metaKey){return}else{if(!m.isMac&&D.ctrl!=t.ctrlKey){return}}if(D.alt!=t.altKey){return}if(D.shift!=t.shiftKey){return}if(t.keyCode==D.keyCode||(t.charCode&&t.charCode==D.charCode)){s=D;return false}});return s}B.onKeyUp.add(function(s,t){var D=v(t);if(D){return j.cancel(t)}});B.onKeyPress.add(function(s,t){var D=v(t);if(D){return j.cancel(t)}});B.onKeyDown.add(function(s,t){var D=v(t);if(D){D.func.call(D.scope);return j.cancel(t)}})}if(m.isIE){q.bind(B.getDoc(),"controlselect",function(D){var t=B.resizeInfo,s;D=D.target;if(D.nodeName!=="IMG"){return}if(t){q.unbind(t.node,t.ev,t.cb)}if(!q.hasClass(D,"mceItemNoResize")){ev="resizeend";s=q.bind(D,ev,function(F){var E;F=F.target;if(E=q.getStyle(F,"width")){q.setAttrib(F,"width",E.replace(/[^0-9%]+/g,""));q.setStyle(F,"width","")}if(E=q.getStyle(F,"height")){q.setAttrib(F,"height",E.replace(/[^0-9%]+/g,""));q.setStyle(F,"height","")}})}else{ev="resizestart";s=q.bind(D,"resizestart",j.cancel,j)}t=B.resizeInfo={node:D,ev:ev,cb:s}})}if(m.isOpera){B.onClick.add(function(s,t){j.prevent(t)})}if(C.custom_undo_redo){function y(){B.undoManager.typing=false;B.undoManager.add()}q.bind(B.getDoc(),"focusout",function(s){if(!B.removed&&B.undoManager.typing){y()}});B.dom.bind(B.dom.getRoot(),"dragend",function(s){y()});B.onKeyUp.add(function(s,D){var t=D.keyCode;if((t>=33&&t<=36)||(t>=37&&t<=40)||t==13||t==45||D.ctrlKey){y()}});B.onKeyDown.add(function(s,E){var D=E.keyCode,t;if(D==8){t=B.getDoc().selection;if(t&&t.createRange&&t.createRange().item){B.undoManager.beforeChange();s.dom.remove(t.createRange().item(0));y();return j.cancel(E)}}if((D>=33&&D<=36)||(D>=37&&D<=40)||D==13||D==45){if(m.isIE&&D==13){B.undoManager.beforeChange()}if(B.undoManager.typing){y()}return}if((D<16||D>20)&&D!=224&&D!=91&&!B.undoManager.typing){B.undoManager.beforeChange();B.undoManager.typing=true;B.undoManager.add()}});B.onMouseDown.add(function(){if(B.undoManager.typing){y()}})}if(m.isWebKit){q.bind(B.getDoc(),"selectionchange",function(){if(B.selectionTimer){clearTimeout(B.selectionTimer);B.selectionTimer=0}B.selectionTimer=window.setTimeout(function(){B.nodeChanged()},50)})}if(m.isGecko){function A(){var s=B.dom.getAttribs(B.selection.getStart().cloneNode(false));return function(){var t=B.selection.getStart();if(t!==B.getBody()){B.dom.removeAllAttribs(t);i(s,function(D){t.setAttributeNode(D.cloneNode(true))})}}}function z(){var t=B.selection;return !t.isCollapsed()&&t.getStart()!=t.getEnd()}B.onKeyPress.add(function(s,D){var t;if((D.keyCode==8||D.keyCode==46)&&z()){t=A();B.getDoc().execCommand("delete",false,null);t();return j.cancel(D)}});B.dom.bind(B.getDoc(),"cut",function(t){var s;if(z()){s=A();B.onKeyUp.addToTop(j.cancel,j);setTimeout(function(){s();B.onKeyUp.remove(j.cancel,j)},0)}})}},_refreshContentEditable:function(){var q=this,p,r;if(q._isHidden()){p=q.getBody();r=p.parentNode;r.removeChild(p);r.appendChild(p);p.focus()}},_isHidden:function(){var p;if(!a){return 0}p=this.selection.getSel();return(!p||!p.rangeCount||p.rangeCount==0)}})})(tinymce);(function(c){var d=c.each,e,a=true,b=false;c.EditorCommands=function(n){var m=n.dom,p=n.selection,j={state:{},exec:{},value:{}},k=n.settings,q=n.formatter,o;function r(z,y,x){var v;z=z.toLowerCase();if(v=j.exec[z]){v(z,y,x);return a}return b}function l(x){var v;x=x.toLowerCase();if(v=j.state[x]){return v(x)}return -1}function h(x){var v;x=x.toLowerCase();if(v=j.value[x]){return v(x)}return b}function u(v,x){x=x||"exec";d(v,function(z,y){d(y.toLowerCase().split(","),function(A){j[x][A]=z})})}c.extend(this,{execCommand:r,queryCommandState:l,queryCommandValue:h,addCommands:u});function f(y,x,v){if(x===e){x=b}if(v===e){v=null}return n.getDoc().execCommand(y,x,v)}function t(v){return q.match(v)}function s(v,x){q.toggle(v,x?{value:x}:e)}function i(v){o=p.getBookmark(v)}function g(){p.moveToBookmark(o)}u({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(z){var y=n.getDoc(),v;try{f(z)}catch(x){v=a}if(v||!y.queryCommandSupported(z)){if(c.isGecko){n.windowManager.confirm(n.getLang("clipboard_msg"),function(A){if(A){open("http://www.mozilla.org/editor/midasdemo/securityprefs.html","_blank")}})}else{n.windowManager.alert(n.getLang("clipboard_no_support"))}}},unlink:function(v){if(p.isCollapsed()){p.select(p.getNode())}f(v);p.collapse(b)},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){var x=v.substring(7);d("left,center,right,full".split(","),function(y){if(x!=y){q.remove("align"+y)}});s("align"+x);r("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(y){var v,x;f(y);v=m.getParent(p.getNode(),"ol,ul");if(v){x=v.parentNode;if(/^(H[1-6]|P|ADDRESS|PRE)$/.test(x.nodeName)){i();m.split(x,v);g()}}},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){s(v)},"ForeColor,HiliteColor,FontName":function(y,x,v){s(y,v)},FontSize:function(z,y,x){var v,A;if(x>=1&&x<=7){A=c.explode(k.font_size_style_values);v=c.explode(k.font_size_classes);if(v){x=v[x-1]||x}else{x=A[x-1]||x}}s(z,x)},RemoveFormat:function(v){q.remove(v)},mceBlockQuote:function(v){s("blockquote")},FormatBlock:function(y,x,v){return s(v||"p")},mceCleanup:function(){var v=p.getBookmark();n.setContent(n.getContent({cleanup:a}),{cleanup:a});p.moveToBookmark(v)},mceRemoveNode:function(z,y,x){var v=x||p.getNode();if(v!=n.getBody()){i();n.dom.remove(v,a);g()}},mceSelectNodeDepth:function(z,y,x){var v=0;m.getParent(p.getNode(),function(A){if(A.nodeType==1&&v++==x){p.select(A);return b}},n.getBody())},mceSelectNode:function(y,x,v){p.select(v)},mceInsertContent:function(B,I,K){var y,J,E,z,F,G,D,C,L,x,A,M,v,H;y=n.parser;J=new c.html.Serializer({},n.schema);v='<span id="mce_marker" data-mce-type="bookmark">\uFEFF</span>';G={content:K,format:"html"};p.onBeforeSetContent.dispatch(p,G);K=G.content;if(K.indexOf("{$caret}")==-1){K+="{$caret}"}K=K.replace(/\{\$caret\}/,v);if(!p.isCollapsed()){n.getDoc().execCommand("Delete",false,null)}E=p.getNode();G={context:E.nodeName.toLowerCase()};F=y.parse(K,G);A=F.lastChild;if(A.attr("id")=="mce_marker"){D=A;for(A=A.prev;A;A=A.walk(true)){if(A.type==3||!m.isBlock(A.name)){A.parent.insert(D,A,A.name==="br");break}}}if(!G.invalid){K=J.serialize(F);A=E.firstChild;M=E.lastChild;if(!A||(A===M&&A.nodeName==="BR")){m.setHTML(E,K)}else{p.setContent(K)}}else{p.setContent(v);E=n.selection.getNode();z=n.getBody();if(E.nodeType==9){E=A=z}else{A=E}while(A!==z){E=A;A=A.parentNode}K=E==z?z.innerHTML:m.getOuterHTML(E);K=J.serialize(y.parse(K.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i,function(){return J.serialize(F)})));if(E==z){m.setHTML(z,K)}else{m.setOuterHTML(E,K)}}D=m.get("mce_marker");C=m.getRect(D);L=m.getViewPort(n.getWin());if((C.y+C.h>L.y+L.h||C.y<L.y)||(C.x>L.x+L.w||C.x<L.x)){H=c.isIE?n.getDoc().documentElement:n.getBody();H.scrollLeft=C.x;H.scrollTop=C.y-L.h+25}x=m.createRng();A=D.previousSibling;if(A&&A.nodeType==3){x.setStart(A,A.nodeValue.length)}else{x.setStartBefore(D);x.setEndBefore(D)}m.remove(D);p.setRng(x);p.onSetContent.dispatch(p,G);n.addVisual()},mceInsertRawHTML:function(y,x,v){p.setContent("tiny_mce_marker");n.setContent(n.getContent().replace(/tiny_mce_marker/g,function(){return v}))},mceSetContent:function(y,x,v){n.setContent(v)},"Indent,Outdent":function(z){var x,v,y;x=k.indentation;v=/[a-z%]+$/i.exec(x);x=parseInt(x);if(!l("InsertUnorderedList")&&!l("InsertOrderedList")){d(p.getSelectedBlocks(),function(A){if(z=="outdent"){y=Math.max(0,parseInt(A.style.paddingLeft||0)-x);m.setStyle(A,"paddingLeft",y?y+v:"")}else{m.setStyle(A,"paddingLeft",(parseInt(A.style.paddingLeft||0)+x)+v)}})}else{f(z)}},mceRepaint:function(){var x;if(c.isGecko){try{i(a);if(p.getSel()){p.getSel().selectAllChildren(n.getBody())}p.collapse(a);g()}catch(v){}}},mceToggleFormat:function(y,x,v){q.toggle(v)},InsertHorizontalRule:function(){n.execCommand("mceInsertContent",false,"<hr />")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual;n.addVisual()},mceReplaceContent:function(y,x,v){n.execCommand("mceInsertContent",false,v.replace(/\{\$selection\}/g,p.getContent({format:"text"})))},mceInsertLink:function(z,y,x){var v;if(typeof(x)=="string"){x={href:x}}v=m.getParent(p.getNode(),"a");x.href=x.href.replace(" ","%20");if(!v||!x.href){q.remove("link")}if(x.href){q.apply("link",x,v)}},selectAll:function(){var x=m.getRoot(),v=m.createRng();v.setStart(x,0);v.setEnd(x,x.childNodes.length);n.selection.setRng(v)}});u({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){return t("align"+v.substring(7))},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){return t(v)},mceBlockQuote:function(){return t("blockquote")},Outdent:function(){var v;if(k.inline_styles){if((v=m.getParent(p.getStart(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}if((v=m.getParent(p.getEnd(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}}return l("InsertUnorderedList")||l("InsertOrderedList")||(!k.inline_styles&&!!m.getParent(p.getNode(),"BLOCKQUOTE"))},"InsertUnorderedList,InsertOrderedList":function(v){return m.getParent(p.getNode(),v=="insertunorderedlist"?"UL":"OL")}},"state");u({"FontSize,FontName":function(y){var x=0,v;if(v=m.getParent(p.getNode(),"span")){if(y=="fontsize"){x=v.style.fontSize}else{x=v.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()}}return x}},"value");if(k.custom_undo_redo){u({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}}})(tinymce);(function(b){var a=b.util.Dispatcher;b.UndoManager=function(f){var d,e=0,h=[],c;function g(){return b.trim(f.getContent({format:"raw",no_events:1}))}return d={typing:false,onAdd:new a(d),onUndo:new a(d),onRedo:new a(d),beforeChange:function(){c=f.selection.getBookmark(2,true)},add:function(m){var j,k=f.settings,l;m=m||{};m.content=g();l=h[e];if(l&&l.content==m.content){return null}if(h[e]){h[e].beforeBookmark=c}if(k.custom_undo_redo_levels){if(h.length>k.custom_undo_redo_levels){for(j=0;j<h.length-1;j++){h[j]=h[j+1]}h.length--;e=h.length}}m.bookmark=f.selection.getBookmark(2,true);if(e<h.length-1){h.length=e+1}h.push(m);e=h.length-1;d.onAdd.dispatch(d,m);f.isNotDirty=0;return m},undo:function(){var k,j;if(d.typing){d.add();d.typing=false}if(e>0){k=h[--e];f.setContent(k.content,{format:"raw"});f.selection.moveToBookmark(k.beforeBookmark);d.onUndo.dispatch(d,k)}return k},redo:function(){var i;if(e<h.length-1){i=h[++e];f.setContent(i.content,{format:"raw"});f.selection.moveToBookmark(i.bookmark);d.onRedo.dispatch(d,i)}return i},clear:function(){h=[];e=0;d.typing=false},hasUndo:function(){return e>0||this.typing},hasRedo:function(){return e<h.length-1&&!this.typing}}}})(tinymce);(function(l){var j=l.dom.Event,c=l.isIE,a=l.isGecko,b=l.isOpera,i=l.each,h=l.extend,d=true,g=false;function k(o){var p,n,m;do{if(/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(o.nodeName)){if(p){n=o.cloneNode(false);n.appendChild(p);p=n}else{p=m=o.cloneNode(false)}p.removeAttribute("id")}}while(o=o.parentNode);if(p){return{wrapper:p,inner:m}}}function f(n,o){var m=o.ownerDocument.createRange();m.setStart(n.endContainer,n.endOffset);m.setEndAfter(o);return m.cloneContents().textContent.length==0}function e(o,q,m){var n,p;if(q.isEmpty(m)){n=q.getParent(m,"ul,ol");if(!q.getParent(n.parentNode,"ul,ol")){q.split(n,m);p=q.create("p",0,'<br data-mce-bogus="1" />');q.replace(p,m);o.select(p,1)}return g}return d}l.create("tinymce.ForceBlocks",{ForceBlocks:function(m){var n=this,o=m.settings,p;n.editor=m;n.dom=m.dom;p=(o.forced_root_block||"p").toLowerCase();o.element=p.toUpperCase();m.onPreInit.add(n.setup,n)},setup:function(){var n=this,m=n.editor,p=m.settings,u=m.dom,o=m.selection,q=m.schema.getBlockElements();if(p.forced_root_block){function v(){var y=o.getStart(),t=m.getBody(),s,z,D,F,E,x,A,B=-16777215;if(!y||y.nodeType!==1){return}while(y!=t){if(q[y.nodeName]){return}y=y.parentNode}s=o.getRng();if(s.setStart){z=s.startContainer;D=s.startOffset;F=s.endContainer;E=s.endOffset}else{if(s.item){s=m.getDoc().body.createTextRange();s.moveToElementText(s.item(0))}tmpRng=s.duplicate();tmpRng.collapse(true);D=tmpRng.move("character",B)*-1;if(!tmpRng.collapsed){tmpRng=s.duplicate();tmpRng.collapse(false);E=(tmpRng.move("character",B)*-1)-D}}for(y=t.firstChild;y;y){if(y.nodeType===3||(y.nodeType==1&&!q[y.nodeName])){if(!x){x=u.create(p.forced_root_block);y.parentNode.insertBefore(x,y)}A=y;y=y.nextSibling;x.appendChild(A)}else{x=null;y=y.nextSibling}}if(s.setStart){s.setStart(z,D);s.setEnd(F,E);o.setRng(s)}else{try{s=m.getDoc().body.createTextRange();s.moveToElementText(t);s.collapse(true);s.moveStart("character",D);if(E>0){s.moveEnd("character",E)}s.select()}catch(C){}}m.nodeChanged()}m.onKeyUp.add(v);m.onClick.add(v)}if(p.force_br_newlines){if(c){m.onKeyPress.add(function(s,t){var x;if(t.keyCode==13&&o.getNode().nodeName!="LI"){o.setContent('<br id="__" /> ',{format:"raw"});x=u.get("__");x.removeAttribute("id");o.select(x);o.collapse();return j.cancel(t)}})}}if(p.force_p_newlines){if(!c){m.onKeyPress.add(function(s,t){if(t.keyCode==13&&!t.shiftKey&&!n.insertPara(t)){j.cancel(t)}})}else{l.addUnload(function(){n._previousFormats=0});m.onKeyPress.add(function(s,t){n._previousFormats=0;if(t.keyCode==13&&!t.shiftKey&&s.selection.isCollapsed()&&p.keep_styles){n._previousFormats=k(s.selection.getStart())}});m.onKeyUp.add(function(t,y){if(y.keyCode==13&&!y.shiftKey){var x=t.selection.getStart(),s=n._previousFormats;if(!x.hasChildNodes()&&s){x=u.getParent(x,u.isBlock);if(x&&x.nodeName!="LI"){x.innerHTML="";if(n._previousFormats){x.appendChild(s.wrapper);s.inner.innerHTML="\uFEFF"}else{x.innerHTML="\uFEFF"}o.select(x,1);o.collapse(true);t.getDoc().execCommand("Delete",false,null);n._previousFormats=0}}}})}if(a){m.onKeyDown.add(function(s,t){if((t.keyCode==8||t.keyCode==46)&&!t.shiftKey){n.backspaceDelete(t,t.keyCode==8)}})}}if(l.isWebKit){function r(t){var s=o.getRng(),x,A=u.create("div",null," "),z,y=u.getViewPort(t.getWin()).h;s.insertNode(x=u.create("br"));s.setStartAfter(x);s.setEndAfter(x);o.setRng(s);if(o.getSel().focusNode==x.previousSibling){o.select(u.insertAfter(u.doc.createTextNode("\u00a0"),x));o.collapse(d)}u.insertAfter(A,x);z=u.getPos(A).y;u.remove(A);if(z>y){t.getWin().scrollTo(0,z)}}m.onKeyPress.add(function(s,t){if(t.keyCode==13&&(t.shiftKey||(p.force_br_newlines&&!u.getParent(o.getNode(),"h1,h2,h3,h4,h5,h6,ol,ul")))){r(s);j.cancel(t)}})}if(c){if(p.element!="P"){m.onKeyPress.add(function(s,t){n.lastElm=o.getNode().nodeName});m.onKeyUp.add(function(t,x){var z,y=o.getNode(),s=t.getBody();if(s.childNodes.length===1&&y.nodeName=="P"){y=u.rename(y,p.element);o.select(y);o.collapse();t.nodeChanged()}else{if(x.keyCode==13&&!x.shiftKey&&n.lastElm!="P"){z=u.getParent(y,"p");if(z){u.rename(z,p.element);t.nodeChanged()}}}})}}},getParentBlock:function(o){var m=this.dom;return m.getParent(o,m.isBlock)},insertPara:function(Q){var E=this,v=E.editor,M=v.dom,R=v.getDoc(),V=v.settings,F=v.selection.getSel(),G=F.getRangeAt(0),U=R.body;var J,K,H,O,N,q,o,u,z,m,C,T,p,x,I,L=M.getViewPort(v.getWin()),B,D,A;v.undoManager.beforeChange();J=R.createRange();J.setStart(F.anchorNode,F.anchorOffset);J.collapse(d);K=R.createRange();K.setStart(F.focusNode,F.focusOffset);K.collapse(d);H=J.compareBoundaryPoints(J.START_TO_END,K)<0;O=H?F.anchorNode:F.focusNode;N=H?F.anchorOffset:F.focusOffset;q=H?F.focusNode:F.anchorNode;o=H?F.focusOffset:F.anchorOffset;if(O===q&&/^(TD|TH)$/.test(O.nodeName)){if(O.firstChild.nodeName=="BR"){M.remove(O.firstChild)}if(O.childNodes.length==0){v.dom.add(O,V.element,null,"<br />");T=v.dom.add(O,V.element,null,"<br />")}else{I=O.innerHTML;O.innerHTML="";v.dom.add(O,V.element,null,I);T=v.dom.add(O,V.element,null,"<br />")}G=R.createRange();G.selectNodeContents(T);G.collapse(1);v.selection.setRng(G);return g}if(O==U&&q==U&&U.firstChild&&v.dom.isBlock(U.firstChild)){O=q=O.firstChild;N=o=0;J=R.createRange();J.setStart(O,0);K=R.createRange();K.setStart(q,0)}if(!R.body.hasChildNodes()){R.body.appendChild(M.create("br"))}O=O.nodeName=="HTML"?R.body:O;O=O.nodeName=="BODY"?O.firstChild:O;q=q.nodeName=="HTML"?R.body:q;q=q.nodeName=="BODY"?q.firstChild:q;u=E.getParentBlock(O);z=E.getParentBlock(q);m=u?u.nodeName:V.element;if(I=E.dom.getParent(u,"li,pre")){if(I.nodeName=="LI"){return e(v.selection,E.dom,I)}return d}if(u&&(u.nodeName=="CAPTION"||/absolute|relative|fixed/gi.test(M.getStyle(u,"position",1)))){m=V.element;u=null}if(z&&(z.nodeName=="CAPTION"||/absolute|relative|fixed/gi.test(M.getStyle(u,"position",1)))){m=V.element;z=null}if(/(TD|TABLE|TH|CAPTION)/.test(m)||(u&&m=="DIV"&&/left|right/gi.test(M.getStyle(u,"float",1)))){m=V.element;u=z=null}C=(u&&u.nodeName==m)?u.cloneNode(0):v.dom.create(m);T=(z&&z.nodeName==m)?z.cloneNode(0):v.dom.create(m);T.removeAttribute("id");if(/^(H[1-6])$/.test(m)&&f(G,u)){T=v.dom.create(V.element)}I=p=O;do{if(I==U||I.nodeType==9||E.dom.isBlock(I)||/(TD|TABLE|TH|CAPTION)/.test(I.nodeName)){break}p=I}while((I=I.previousSibling?I.previousSibling:I.parentNode));I=x=q;do{if(I==U||I.nodeType==9||E.dom.isBlock(I)||/(TD|TABLE|TH|CAPTION)/.test(I.nodeName)){break}x=I}while((I=I.nextSibling?I.nextSibling:I.parentNode));if(p.nodeName==m){J.setStart(p,0)}else{J.setStartBefore(p)}J.setEnd(O,N);C.appendChild(J.cloneContents()||R.createTextNode(""));try{K.setEndAfter(x)}catch(P){}K.setStart(q,o);T.appendChild(K.cloneContents()||R.createTextNode(""));G=R.createRange();if(!p.previousSibling&&p.parentNode.nodeName==m){G.setStartBefore(p.parentNode)}else{if(J.startContainer.nodeName==m&&J.startOffset==0){G.setStartBefore(J.startContainer)}else{G.setStart(J.startContainer,J.startOffset)}}if(!x.nextSibling&&x.parentNode.nodeName==m){G.setEndAfter(x.parentNode)}else{G.setEnd(K.endContainer,K.endOffset)}G.deleteContents();if(b){v.getWin().scrollTo(0,L.y)}if(C.firstChild&&C.firstChild.nodeName==m){C.innerHTML=C.firstChild.innerHTML}if(T.firstChild&&T.firstChild.nodeName==m){T.innerHTML=T.firstChild.innerHTML}function S(y,s){var r=[],X,W,t;y.innerHTML="";if(V.keep_styles){W=s;do{if(/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(W.nodeName)){X=W.cloneNode(g);M.setAttrib(X,"id","");r.push(X)}}while(W=W.parentNode)}if(r.length>0){for(t=r.length-1,X=y;t>=0;t--){X=X.appendChild(r[t])}r[0].innerHTML=b?"\u00a0":"<br />";return r[0]}else{y.innerHTML=b?"\u00a0":"<br />"}}if(M.isEmpty(C)){S(C,O)}if(M.isEmpty(T)){A=S(T,q)}if(b&&parseFloat(opera.version())<9.5){G.insertNode(C);G.insertNode(T)}else{G.insertNode(T);G.insertNode(C)}T.normalize();C.normalize();v.selection.select(T,true);v.selection.collapse(true);B=v.dom.getPos(T).y;if(B<L.y||B+25>L.y+L.h){v.getWin().scrollTo(0,B<L.y?B:B-L.h+25)}v.undoManager.add();return g},backspaceDelete:function(u,B){var C=this,s=C.editor,y=s.getBody(),q=s.dom,p,v=s.selection,o=v.getRng(),x=o.startContainer,p,z,A,m;if(!B&&o.collapsed&&x.nodeType==1&&o.startOffset==x.childNodes.length){m=new l.dom.TreeWalker(x.lastChild,x);for(p=x.lastChild;p;p=m.prev()){if(p.nodeType==3){o.setStart(p,p.nodeValue.length);o.collapse(true);v.setRng(o);return}}}if(x&&s.dom.isBlock(x)&&!/^(TD|TH)$/.test(x.nodeName)&&B){if(x.childNodes.length==0||(x.childNodes.length==1&&x.firstChild.nodeName=="BR")){p=x;while((p=p.previousSibling)&&!s.dom.isBlock(p)){}if(p){if(x!=y.firstChild){z=s.dom.doc.createTreeWalker(p,NodeFilter.SHOW_TEXT,null,g);while(A=z.nextNode()){p=A}o=s.getDoc().createRange();o.setStart(p,p.nodeValue?p.nodeValue.length:0);o.setEnd(p,p.nodeValue?p.nodeValue.length:0);v.setRng(o);s.dom.remove(x)}return j.cancel(u)}}}}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each,e=c.extend;c.create("tinymce.ControlManager",{ControlManager:function(f,j){var h=this,g;j=j||{};h.editor=f;h.controls={};h.onAdd=new c.util.Dispatcher(h);h.onPostRender=new c.util.Dispatcher(h);h.prefix=j.prefix||f.id+"_";h._cls={};h.onPostRender.add(function(){d(h.controls,function(i){i.postRender()})})},get:function(f){return this.controls[this.prefix+f]||this.controls[f]},setActive:function(h,f){var g=null;if(g=this.get(h)){g.setActive(f)}return g},setDisabled:function(h,f){var g=null;if(g=this.get(h)){g.setDisabled(f)}return g},add:function(g){var f=this;if(g){f.controls[g.id]=g;f.onAdd.dispatch(g,f)}return g},createControl:function(i){var h,g=this,f=g.editor;d(f.plugins,function(j){if(j.createControl){h=j.createControl(i,g);if(h){return false}}});switch(i){case"|":case"separator":return g.createSeparator()}if(!h&&f.buttons&&(h=f.buttons[i])){return g.createButton(i,h)}return g.add(h)},createDropMenu:function(f,n,h){var m=this,i=m.editor,j,g,k,l;n=e({"class":"mceDropDown",constrain:i.settings.constrain_menus},n);n["class"]=n["class"]+" "+i.getParam("skin")+"Skin";if(k=i.getParam("skin_variant")){n["class"]+=" "+i.getParam("skin")+"Skin"+k.substring(0,1).toUpperCase()+k.substring(1)}f=m.prefix+f;l=h||m._cls.dropmenu||c.ui.DropMenu;j=m.controls[f]=new l(f,n);j.onAddItem.add(function(r,q){var p=q.settings;p.title=i.getLang(p.title,p.title);if(!p.onclick){p.onclick=function(o){if(p.cmd){i.execCommand(p.cmd,p.ui||false,p.value)}}}});i.onRemove.add(function(){j.destroy()});if(c.isIE){j.onShowMenu.add(function(){i.focus();g=i.selection.getBookmark(1)});j.onHideMenu.add(function(){if(g){i.selection.moveToBookmark(g);g=0}})}return m.add(j)},createListBox:function(f,n,h){var l=this,j=l.editor,i,k,m;if(l.get(f)){return null}n.title=j.translate(n.title);n.scope=n.scope||j;if(!n.onselect){n.onselect=function(o){j.execCommand(n.cmd,n.ui||false,o||n.value)}}n=e({title:n.title,"class":"mce_"+f,scope:n.scope,control_manager:l},n);f=l.prefix+f;function g(o){return o.settings.use_accessible_selects&&!c.isGecko}if(j.settings.use_native_selects||g(j)){k=new c.ui.NativeListBox(f,n)}else{m=h||l._cls.listbox||c.ui.ListBox;k=new m(f,n,j)}l.controls[f]=k;if(c.isWebKit){k.onPostRender.add(function(p,o){a.add(o,"mousedown",function(){j.bookmark=j.selection.getBookmark(1)});a.add(o,"focus",function(){j.selection.moveToBookmark(j.bookmark);j.bookmark=null})})}if(k.hideMenu){j.onMouseDown.add(k.hideMenu,k)}return l.add(k)},createButton:function(m,i,l){var h=this,g=h.editor,j,k,f;if(h.get(m)){return null}i.title=g.translate(i.title);i.label=g.translate(i.label);i.scope=i.scope||g;if(!i.onclick&&!i.menu_button){i.onclick=function(){g.execCommand(i.cmd,i.ui||false,i.value)}}i=e({title:i.title,"class":"mce_"+m,unavailable_prefix:g.getLang("unavailable",""),scope:i.scope,control_manager:h},i);m=h.prefix+m;if(i.menu_button){f=l||h._cls.menubutton||c.ui.MenuButton;k=new f(m,i,g);g.onMouseDown.add(k.hideMenu,k)}else{f=h._cls.button||c.ui.Button;k=new f(m,i,g)}return h.add(k)},createMenuButton:function(h,f,g){f=f||{};f.menu_button=1;return this.createButton(h,f,g)},createSplitButton:function(m,i,l){var h=this,g=h.editor,j,k,f;if(h.get(m)){return null}i.title=g.translate(i.title);i.scope=i.scope||g;if(!i.onclick){i.onclick=function(n){g.execCommand(i.cmd,i.ui||false,n||i.value)}}if(!i.onselect){i.onselect=function(n){g.execCommand(i.cmd,i.ui||false,n||i.value)}}i=e({title:i.title,"class":"mce_"+m,scope:i.scope,control_manager:h},i);m=h.prefix+m;f=l||h._cls.splitbutton||c.ui.SplitButton;k=h.add(new f(m,i,g));g.onMouseDown.add(k.hideMenu,k);return k},createColorSplitButton:function(f,n,h){var l=this,j=l.editor,i,k,m,g;if(l.get(f)){return null}n.title=j.translate(n.title);n.scope=n.scope||j;if(!n.onclick){n.onclick=function(o){if(c.isIE){g=j.selection.getBookmark(1)}j.execCommand(n.cmd,n.ui||false,o||n.value)}}if(!n.onselect){n.onselect=function(o){j.execCommand(n.cmd,n.ui||false,o||n.value)}}n=e({title:n.title,"class":"mce_"+f,menu_class:j.getParam("skin")+"Skin",scope:n.scope,more_colors_title:j.getLang("more_colors")},n);f=l.prefix+f;m=h||l._cls.colorsplitbutton||c.ui.ColorSplitButton;k=new m(f,n,j);j.onMouseDown.add(k.hideMenu,k);j.onRemove.add(function(){k.destroy()});if(c.isIE){k.onShowMenu.add(function(){j.focus();g=j.selection.getBookmark(1)});k.onHideMenu.add(function(){if(g){j.selection.moveToBookmark(g);g=0}})}return l.add(k)},createToolbar:function(k,h,j){var i,g=this,f;k=g.prefix+k;f=j||g._cls.toolbar||c.ui.Toolbar;i=new f(k,h,g.editor);if(g.get(k)){return null}return g.add(i)},createToolbarGroup:function(k,h,j){var i,g=this,f;k=g.prefix+k;f=j||this._cls.toolbarGroup||c.ui.ToolbarGroup;i=new f(k,h,g.editor);if(g.get(k)){return null}return g.add(i)},createSeparator:function(g){var f=g||this._cls.separator||c.ui.Separator;return new f()},setControlType:function(g,f){return this._cls[g.toLowerCase()]=f},destroy:function(){d(this.controls,function(f){f.destroy()});this.controls=null}})})(tinymce);(function(d){var a=d.util.Dispatcher,e=d.each,c=d.isIE,b=d.isOpera;d.create("tinymce.WindowManager",{WindowManager:function(f){var g=this;g.editor=f;g.onOpen=new a(g);g.onClose=new a(g);g.params={};g.features={}},open:function(z,h){var v=this,k="",n,m,i=v.editor.settings.dialog_type=="modal",q,o,j,g=d.DOM.getViewPort(),r;z=z||{};h=h||{};o=b?g.w:screen.width;j=b?g.h:screen.height;z.name=z.name||"mc_"+new Date().getTime();z.width=parseInt(z.width||320);z.height=parseInt(z.height||240);z.resizable=true;z.left=z.left||parseInt(o/2)-(z.width/2);z.top=z.top||parseInt(j/2)-(z.height/2);h.inline=false;h.mce_width=z.width;h.mce_height=z.height;h.mce_auto_focus=z.auto_focus;if(i){if(c){z.center=true;z.help=false;z.dialogWidth=z.width+"px";z.dialogHeight=z.height+"px";z.scroll=z.scrollbars||false}}e(z,function(p,f){if(d.is(p,"boolean")){p=p?"yes":"no"}if(!/^(name|url)$/.test(f)){if(c&&i){k+=(k?";":"")+f+":"+p}else{k+=(k?",":"")+f+"="+p}}});v.features=z;v.params=h;v.onOpen.dispatch(v,z,h);r=z.url||z.file;r=d._addVer(r);try{if(c&&i){q=1;window.showModalDialog(r,window,k)}else{q=window.open(r,z.name,k)}}catch(l){}if(!q){alert(v.editor.getLang("popup_blocked"))}},close:function(f){f.close();this.onClose.dispatch(this)},createInstance:function(i,h,g,m,l,k){var j=d.resolve(i);return new j(h,g,m,l,k)},confirm:function(h,f,i,g){g=g||window;f.call(i||this,g.confirm(this._decode(this.editor.getLang(h,h))))},alert:function(h,f,j,g){var i=this;g=g||window;g.alert(i._decode(i.editor.getLang(h,h)));if(f){f.call(j||i)}},resizeBy:function(f,g,h){h.resizeBy(f,g)},_decode:function(f){return d.DOM.decode(f).replace(/\\n/g,"\n")}})}(tinymce));(function(a){a.Formatter=function(V){var M={},O=a.each,c=V.dom,q=V.selection,t=a.dom.TreeWalker,K=new a.dom.RangeUtils(c),d=V.schema.isValidChild,F=c.isBlock,l=V.settings.forced_root_block,s=c.nodeIndex,E="\uFEFF",e=/^(src|href|style)$/,S=false,B=true,p,P={apply:[],remove:[]};function z(W){return W instanceof Array}function m(X,W){return c.getParents(X,W,c.getRoot())}function b(W){return W.nodeType===1&&(W.face==="mceinline"||W.style.fontFamily==="mceinline")}function R(W){return W?M[W]:M}function k(W,X){if(W){if(typeof(W)!=="string"){O(W,function(Z,Y){k(Y,Z)})}else{X=X.length?X:[X];O(X,function(Y){if(Y.deep===p){Y.deep=!Y.selector}if(Y.split===p){Y.split=!Y.selector||Y.inline}if(Y.remove===p&&Y.selector&&!Y.inline){Y.remove="none"}if(Y.selector&&Y.inline){Y.mixed=true;Y.block_expand=true}if(typeof(Y.classes)==="string"){Y.classes=Y.classes.split(/\s+/)}});M[W]=X}}}var i=function(X){var W;V.dom.getParent(X,function(Y){W=V.dom.getStyle(Y,"text-decoration");return W&&W!=="none"});return W};var I=function(W){var X;if(W.nodeType===1&&W.parentNode&&W.parentNode.nodeType===1){X=i(W.parentNode);if(V.dom.getStyle(W,"color")&&X){V.dom.setStyle(W,"text-decoration",X)}else{if(V.dom.getStyle(W,"textdecoration")===X){V.dom.setStyle(W,"text-decoration",null)}}}};function T(Z,ah,ac){var ad=R(Z),ai=ad[0],ag,X,af,ae=q.isCollapsed();function aa(am){var al=am.startContainer,ap=am.startOffset,ao,an;if(al.nodeType==1||al.nodeValue===""){al=al.nodeType==1?al.childNodes[ap]:al;if(al){ao=new t(al,al.parentNode);for(an=ao.current();an;an=ao.next()){if(an.nodeType==3&&!f(an)){am.setStart(an,0);break}}}}return am}function W(am,al){al=al||ai;if(am){if(al.onformat){al.onformat(am,al,ah,ac)}O(al.styles,function(ao,an){c.setStyle(am,an,r(ao,ah))});O(al.attributes,function(ao,an){c.setAttrib(am,an,r(ao,ah))});O(al.classes,function(an){an=r(an,ah);if(!c.hasClass(am,an)){c.addClass(am,an)}})}}function ab(){function an(au,ar){var at=new t(ar);for(ac=at.current();ac;ac=at.prev()){if(ac.childNodes.length>1||ac==au){return ac}}}var am=V.selection.getRng();var aq=am.startContainer;var al=am.endContainer;if(aq!=al&&am.endOffset==0){var ap=an(aq,al);var ao=ap.nodeType==3?ap.length:ap.childNodes.length;am.setEnd(ap,ao)}return am}function Y(ao,au,ar,aq,am){var al=[],an=-1,at,aw=-1,ap=-1,av;O(ao.childNodes,function(ay,ax){if(ay.nodeName==="UL"||ay.nodeName==="OL"){an=ax;at=ay;return false}});O(ao.childNodes,function(ay,ax){if(ay.nodeName==="SPAN"&&c.getAttrib(ay,"data-mce-type")=="bookmark"){if(ay.id==au.id+"_start"){aw=ax}else{if(ay.id==au.id+"_end"){ap=ax}}}});if(an<=0||(aw<an&&ap>an)){O(a.grep(ao.childNodes),am);return 0}else{av=ar.cloneNode(S);O(a.grep(ao.childNodes),function(ay,ax){if((aw<an&&ax<an)||(aw>an&&ax>an)){al.push(ay);ay.parentNode.removeChild(ay)}});if(aw<an){ao.insertBefore(av,at)}else{if(aw>an){ao.insertBefore(av,at.nextSibling)}}aq.push(av);O(al,function(ax){av.appendChild(ax)});return av}}function aj(am,ao){var al=[],ap,an;ap=ai.inline||ai.block;an=c.create(ap);W(an);K.walk(am,function(aq){var ar;function at(au){var ax=au.nodeName.toLowerCase(),aw=au.parentNode.nodeName.toLowerCase(),av;if(g(ax,"br")){ar=0;if(ai.block){c.remove(au)}return}if(ai.wrapper&&x(au,Z,ah)){ar=0;return}if(ai.block&&!ai.wrapper&&G(ax)){au=c.rename(au,ap);W(au);al.push(au);ar=0;return}if(ai.selector){O(ad,function(ay){if("collapsed" in ay&&ay.collapsed!==ae){return}if(c.is(au,ay.selector)&&!b(au)){W(au,ay);av=true}});if(!ai.inline||av){ar=0;return}}if(d(ap,ax)&&d(aw,ap)&&!(au.nodeType===3&&au.nodeValue.length===1&&au.nodeValue.charCodeAt(0)===65279)){if(!ar){ar=an.cloneNode(S);au.parentNode.insertBefore(ar,au);al.push(ar)}ar.appendChild(au)}else{if(ax=="li"&&ao){ar=Y(au,ao,an,al,at)}else{ar=0;O(a.grep(au.childNodes),at);ar=0}}}O(aq,at)});if(ai.wrap_links===false){O(al,function(aq){function ar(aw){var av,au,at;if(aw.nodeName==="A"){au=an.cloneNode(S);al.push(au);at=a.grep(aw.childNodes);for(av=0;av<at.length;av++){au.appendChild(at[av])}aw.appendChild(au)}O(a.grep(aw.childNodes),ar)}ar(aq)})}O(al,function(at){var aq;function au(aw){var av=0;O(aw.childNodes,function(ax){if(!f(ax)&&!H(ax)){av++}});return av}function ar(av){var ax,aw;O(av.childNodes,function(ay){if(ay.nodeType==1&&!H(ay)&&!b(ay)){ax=ay;return S}});if(ax&&h(ax,ai)){aw=ax.cloneNode(S);W(aw);c.replace(aw,av,B);c.remove(ax,1)}return aw||av}aq=au(at);if((al.length>1||!F(at))&&aq===0){c.remove(at,1);return}if(ai.inline||ai.wrapper){if(!ai.exact&&aq===1){at=ar(at)}O(ad,function(av){O(c.select(av.inline,at),function(ax){var aw;if(av.wrap_links===false){aw=ax.parentNode;do{if(aw.nodeName==="A"){return}}while(aw=aw.parentNode)}U(av,ah,ax,av.exact?ax:null)})});if(x(at.parentNode,Z,ah)){c.remove(at,1);at=0;return B}if(ai.merge_with_parents){c.getParent(at.parentNode,function(av){if(x(av,Z,ah)){c.remove(at,1);at=0;return B}})}if(at&&ai.merge_siblings!==false){at=u(C(at),at);at=u(at,C(at,B))}}})}if(ai){if(ac){X=c.createRng();X.setStartBefore(ac);X.setEndAfter(ac);aj(o(X,ad))}else{if(!ae||!ai.inline||c.select("td.mceSelected,th.mceSelected").length){var ak=V.selection.getNode();V.selection.setRng(ab());ag=q.getBookmark();aj(o(q.getRng(B),ad),ag);if(ai.styles&&(ai.styles.color||ai.styles.textDecoration)){a.walk(ak,I,"childNodes");I(ak)}q.moveToBookmark(ag);q.setRng(aa(q.getRng(B)));V.nodeChanged()}else{Q("apply",Z,ah)}}}}function A(Y,ah,ab){var ac=R(Y),aj=ac[0],ag,af,X;function aa(am){var al=am.startContainer,ar=am.startOffset,aq,ap,an,ao;if(al.nodeType==3&&ar>=al.nodeValue.length-1){al=al.parentNode;ar=s(al)+1}if(al.nodeType==1){an=al.childNodes;al=an[Math.min(ar,an.length-1)];aq=new t(al);if(ar>an.length-1){aq.next()}for(ap=aq.current();ap;ap=aq.next()){if(ap.nodeType==3&&!f(ap)){ao=c.create("a",null,E);ap.parentNode.insertBefore(ao,ap);am.setStart(ap,0);q.setRng(am);c.remove(ao);return}}}}function Z(ao){var an,am,al;an=a.grep(ao.childNodes);for(am=0,al=ac.length;am<al;am++){if(U(ac[am],ah,ao,ao)){break}}if(aj.deep){for(am=0,al=an.length;am<al;am++){Z(an[am])}}}function ad(al){var am;O(m(al.parentNode).reverse(),function(an){var ao;if(!am&&an.id!="_start"&&an.id!="_end"){ao=x(an,Y,ah);if(ao&&ao.split!==false){am=an}}});return am}function W(ao,al,aq,au){var av,at,ar,an,ap,am;if(ao){am=ao.parentNode;for(av=al.parentNode;av&&av!=am;av=av.parentNode){at=av.cloneNode(S);for(ap=0;ap<ac.length;ap++){if(U(ac[ap],ah,at,at)){at=0;break}}if(at){if(ar){at.appendChild(ar)}if(!an){an=at}ar=at}}if(au&&(!aj.mixed||!F(ao))){al=c.split(ao,al)}if(ar){aq.parentNode.insertBefore(ar,aq);an.appendChild(aq)}}return al}function ai(al){return W(ad(al),al,al,true)}function ae(an){var am=c.get(an?"_start":"_end"),al=am[an?"firstChild":"lastChild"];if(H(al)){al=al[an?"firstChild":"lastChild"]}c.remove(am,true);return al}function ak(al){var am,an;al=o(al,ac,B);if(aj.split){am=J(al,B);an=J(al);if(am!=an){am=N(am,"span",{id:"_start","data-mce-type":"bookmark"});an=N(an,"span",{id:"_end","data-mce-type":"bookmark"});ai(am);ai(an);am=ae(B);an=ae()}else{am=an=ai(am)}al.startContainer=am.parentNode;al.startOffset=s(am);al.endContainer=an.parentNode;al.endOffset=s(an)+1}K.walk(al,function(ao){O(ao,function(ap){Z(ap);if(ap.nodeType===1&&V.dom.getStyle(ap,"text-decoration")==="underline"&&ap.parentNode&&i(ap.parentNode)==="underline"){U({deep:false,exact:true,inline:"span",styles:{textDecoration:"underline"}},null,ap)}})})}if(ab){X=c.createRng();X.setStartBefore(ab);X.setEndAfter(ab);ak(X);return}if(!q.isCollapsed()||!aj.inline||c.select("td.mceSelected,th.mceSelected").length){ag=q.getBookmark();ak(q.getRng(B));q.moveToBookmark(ag);if(aj.inline&&j(Y,ah,q.getStart())){aa(q.getRng(true))}V.nodeChanged()}else{Q("remove",Y,ah)}}function D(X,Z,Y){var W=R(X);if(j(X,Z,Y)&&(!("toggle" in W[0])||W[0]["toggle"])){A(X,Z,Y)}else{T(X,Z,Y)}}function x(X,W,ac,aa){var Y=R(W),ad,ab,Z;function ae(ai,ak,al){var ah,aj,af=ak[al],ag;if(ak.onmatch){return ak.onmatch(ai,ak,al)}if(af){if(af.length===p){for(ah in af){if(af.hasOwnProperty(ah)){if(al==="attributes"){aj=c.getAttrib(ai,ah)}else{aj=L(ai,ah)}if(aa&&!aj&&!ak.exact){return}if((!aa||ak.exact)&&!g(aj,r(af[ah],ac))){return}}}}else{for(ag=0;ag<af.length;ag++){if(al==="attributes"?c.getAttrib(ai,af[ag]):L(ai,af[ag])){return ak}}}}return ak}if(Y&&X){for(ab=0;ab<Y.length;ab++){ad=Y[ab];if(h(X,ad)&&ae(X,ad,"attributes")&&ae(X,ad,"styles")){if(Z=ad.classes){for(ab=0;ab<Z.length;ab++){if(!c.hasClass(X,Z[ab])){return}}}return ad}}}}function j(Y,ab,aa){var X,Z;function W(ac){ac=c.getParent(ac,function(ad){return !!x(ad,Y,ab,true)});return x(ac,Y,ab)}if(aa){return W(aa)}if(q.isCollapsed()){for(Z=P.apply.length-1;Z>=0;Z--){if(P.apply[Z].name==Y){return true}}for(Z=P.remove.length-1;Z>=0;Z--){if(P.remove[Z].name==Y){return false}}return W(q.getNode())}aa=q.getNode();if(W(aa)){return B}X=q.getStart();if(X!=aa){if(W(X)){return B}}return S}function v(ad,ac){var aa,ab=[],Z={},Y,X,W;if(q.isCollapsed()){for(X=0;X<ad.length;X++){for(Y=P.remove.length-1;Y>=0;Y--){W=ad[X];if(P.remove[Y].name==W){Z[W]=true;break}}}for(Y=P.apply.length-1;Y>=0;Y--){for(X=0;X<ad.length;X++){W=ad[X];if(!Z[W]&&P.apply[Y].name==W){Z[W]=true;ab.push(W)}}}}aa=q.getStart();c.getParent(aa,function(ag){var af,ae;for(af=0;af<ad.length;af++){ae=ad[af];if(!Z[ae]&&x(ag,ae,ac)){Z[ae]=true;ab.push(ae)}}});return ab}function y(aa){var ac=R(aa),Z,Y,ab,X,W;if(ac){Z=q.getStart();Y=m(Z);for(X=ac.length-1;X>=0;X--){W=ac[X].selector;if(!W){return B}for(ab=Y.length-1;ab>=0;ab--){if(c.is(Y[ab],W)){return B}}}}return S}a.extend(this,{get:R,register:k,apply:T,remove:A,toggle:D,match:j,matchAll:v,matchNode:x,canApply:y});function h(W,X){if(g(W,X.inline)){return B}if(g(W,X.block)){return B}if(X.selector){return c.is(W,X.selector)}}function g(X,W){X=X||"";W=W||"";X=""+(X.nodeName||X);W=""+(W.nodeName||W);return X.toLowerCase()==W.toLowerCase()}function L(X,W){var Y=c.getStyle(X,W);if(W=="color"||W=="backgroundColor"){Y=c.toHex(Y)}if(W=="fontWeight"&&Y==700){Y="bold"}return""+Y}function r(W,X){if(typeof(W)!="string"){W=W(X)}else{if(X){W=W.replace(/%(\w+)/g,function(Z,Y){return X[Y]||Z})}}return W}function f(W){return W&&W.nodeType===3&&/^([\s\r\n]+|)$/.test(W.nodeValue)}function N(Y,X,W){var Z=c.create(X,W);Y.parentNode.insertBefore(Z,Y);Z.appendChild(Y);return Z}function o(W,ag,Z){var Y=W.startContainer,ad=W.startOffset,aj=W.endContainer,ae=W.endOffset,ai,af,ac;function ah(am,an,ak,al){var ao,ap;al=al||c.getRoot();for(;;){ao=am.parentNode;if(ao==al||(!ag[0].block_expand&&F(ao))){return am}for(ai=ao[an];ai&&ai!=am;ai=ai[ak]){if(ai.nodeType==1&&!H(ai)){return am}if(ai.nodeType==3&&!f(ai)){return am}}am=am.parentNode}return am}function ab(ak,al){if(al===p){al=ak.nodeType===3?ak.length:ak.childNodes.length}while(ak&&ak.hasChildNodes()){ak=ak.childNodes[al];if(ak){al=ak.nodeType===3?ak.length:ak.childNodes.length}}return{node:ak,offset:al}}if(Y.nodeType==1&&Y.hasChildNodes()){af=Y.childNodes.length-1;Y=Y.childNodes[ad>af?af:ad];if(Y.nodeType==3){ad=0}}if(aj.nodeType==1&&aj.hasChildNodes()){af=aj.childNodes.length-1;aj=aj.childNodes[ae>af?af:ae-1];if(aj.nodeType==3){ae=aj.nodeValue.length}}if(H(Y.parentNode)){Y=Y.parentNode}if(H(Y)){Y=Y.nextSibling||Y}if(H(aj.parentNode)){ae=c.nodeIndex(aj);aj=aj.parentNode}if(H(aj)&&aj.previousSibling){aj=aj.previousSibling;ae=aj.length}if(ag[0].inline){ac=ab(aj,ae);if(ac.node){while(ac.node&&ac.offset===0&&ac.node.previousSibling){ac=ab(ac.node.previousSibling)}if(ac.node&&ac.offset>0&&ac.node.nodeType===3&&ac.node.nodeValue.charAt(ac.offset-1)===" "){if(ac.offset>1){aj=ac.node;aj.splitText(ac.offset-1)}else{if(ac.node.previousSibling){aj=ac.node.previousSibling}}}}}if(ag[0].inline||ag[0].block_expand){Y=ah(Y,"firstChild","nextSibling");aj=ah(aj,"lastChild","previousSibling")}if(ag[0].selector&&ag[0].expand!==S&&!ag[0].inline){function aa(al,ak){var am,an,ap,ao;if(al.nodeType==3&&al.nodeValue.length==0&&al[ak]){al=al[ak]}am=m(al);for(an=0;an<am.length;an++){for(ap=0;ap<ag.length;ap++){ao=ag[ap];if("collapsed" in ao&&ao.collapsed!==W.collapsed){continue}if(c.is(am[an],ao.selector)){return am[an]}}}return al}Y=aa(Y,"previousSibling");aj=aa(aj,"nextSibling")}if(ag[0].block||ag[0].selector){function X(al,ak,an){var am;if(!ag[0].wrapper){am=c.getParent(al,ag[0].block)}if(!am){am=c.getParent(al.nodeType==3?al.parentNode:al,F)}if(am&&ag[0].wrapper){am=m(am,"ul,ol").reverse()[0]||am}if(!am){am=al;while(am[ak]&&!F(am[ak])){am=am[ak];if(g(am,"br")){break}}}return am||al}Y=X(Y,"previousSibling");aj=X(aj,"nextSibling");if(ag[0].block){if(!F(Y)){Y=ah(Y,"firstChild","nextSibling")}if(!F(aj)){aj=ah(aj,"lastChild","previousSibling")}}}if(Y.nodeType==1){ad=s(Y);Y=Y.parentNode}if(aj.nodeType==1){ae=s(aj)+1;aj=aj.parentNode}return{startContainer:Y,startOffset:ad,endContainer:aj,endOffset:ae}}function U(ac,ab,Z,W){var Y,X,aa;if(!h(Z,ac)){return S}if(ac.remove!="all"){O(ac.styles,function(ae,ad){ae=r(ae,ab);if(typeof(ad)==="number"){ad=ae;W=0}if(!W||g(L(W,ad),ae)){c.setStyle(Z,ad,"")}aa=1});if(aa&&c.getAttrib(Z,"style")==""){Z.removeAttribute("style");Z.removeAttribute("data-mce-style")}O(ac.attributes,function(af,ad){var ae;af=r(af,ab);if(typeof(ad)==="number"){ad=af;W=0}if(!W||g(c.getAttrib(W,ad),af)){if(ad=="class"){af=c.getAttrib(Z,ad);if(af){ae="";O(af.split(/\s+/),function(ag){if(/mce\w+/.test(ag)){ae+=(ae?" ":"")+ag}});if(ae){c.setAttrib(Z,ad,ae);return}}}if(ad=="class"){Z.removeAttribute("className")}if(e.test(ad)){Z.removeAttribute("data-mce-"+ad)}Z.removeAttribute(ad)}});O(ac.classes,function(ad){ad=r(ad,ab);if(!W||c.hasClass(W,ad)){c.removeClass(Z,ad)}});X=c.getAttribs(Z);for(Y=0;Y<X.length;Y++){if(X[Y].nodeName.indexOf("_")!==0){return S}}}if(ac.remove!="none"){n(Z,ac);return B}}function n(Y,Z){var W=Y.parentNode,X;if(Z.block){if(!l){function aa(ac,ab,ad){ac=C(ac,ab,ad);return !ac||(ac.nodeName=="BR"||F(ac))}if(F(Y)&&!F(W)){if(!aa(Y,S)&&!aa(Y.firstChild,B,1)){Y.insertBefore(c.create("br"),Y.firstChild)}if(!aa(Y,B)&&!aa(Y.lastChild,S,1)){Y.appendChild(c.create("br"))}}}else{if(W==c.getRoot()){if(!Z.list_block||!g(Y,Z.list_block)){O(a.grep(Y.childNodes),function(ab){if(d(l,ab.nodeName.toLowerCase())){if(!X){X=N(ab,l)}else{X.appendChild(ab)}}else{X=0}})}}}}if(Z.selector&&Z.inline&&!g(Z.inline,Y)){return}c.remove(Y,1)}function C(X,W,Y){if(X){W=W?"nextSibling":"previousSibling";for(X=Y?X:X[W];X;X=X[W]){if(X.nodeType==1||!f(X)){return X}}}}function H(W){return W&&W.nodeType==1&&W.getAttribute("data-mce-type")=="bookmark"}function u(aa,Z){var W,Y,X;function ac(af,ae){if(af.nodeName!=ae.nodeName){return S}function ad(ah){var ai={};O(c.getAttribs(ah),function(aj){var ak=aj.nodeName.toLowerCase();if(ak.indexOf("_")!==0&&ak!=="style"){ai[ak]=c.getAttrib(ah,ak)}});return ai}function ag(ak,aj){var ai,ah;for(ah in ak){if(ak.hasOwnProperty(ah)){ai=aj[ah];if(ai===p){return S}if(ak[ah]!=ai){return S}delete aj[ah]}}for(ah in aj){if(aj.hasOwnProperty(ah)){return S}}return B}if(!ag(ad(af),ad(ae))){return S}if(!ag(c.parseStyle(c.getAttrib(af,"style")),c.parseStyle(c.getAttrib(ae,"style")))){return S}return B}if(aa&&Z){function ab(ae,ad){for(Y=ae;Y;Y=Y[ad]){if(Y.nodeType==3&&Y.nodeValue.length!==0){return ae}if(Y.nodeType==1&&!H(Y)){return Y}}return ae}aa=ab(aa,"previousSibling");Z=ab(Z,"nextSibling");if(ac(aa,Z)){for(Y=aa.nextSibling;Y&&Y!=Z;){X=Y;Y=Y.nextSibling;aa.appendChild(X)}c.remove(Z);O(a.grep(Z.childNodes),function(ad){aa.appendChild(ad)});return aa}}return Z}function G(W){return/^(h[1-6]|p|div|pre|address|dl|dt|dd)$/.test(W)}function J(X,aa){var W,Z,Y;W=X[aa?"startContainer":"endContainer"];Z=X[aa?"startOffset":"endOffset"];if(W.nodeType==1){Y=W.childNodes.length-1;if(!aa&&Z){Z--}W=W.childNodes[Z>Y?Y:Z]}return W}function Q(ad,Y,ac){var aa,X=P[ad],ae=P[ad=="apply"?"remove":"apply"];function af(){return P.apply.length||P.remove.length}function ab(){P.apply=[];P.remove=[]}function ag(ah){O(P.apply.reverse(),function(ai){T(ai.name,ai.vars,ah);if(ai.name==="forecolor"&&ai.vars.value){I(ah.parentNode)}});O(P.remove.reverse(),function(ai){A(ai.name,ai.vars,ah)});c.remove(ah,1);ab()}for(aa=X.length-1;aa>=0;aa--){if(X[aa].name==Y){return}}X.push({name:Y,vars:ac});for(aa=ae.length-1;aa>=0;aa--){if(ae[aa].name==Y){ae.splice(aa,1)}}if(af()){V.getDoc().execCommand("FontName",false,"mceinline");P.lastRng=q.getRng();O(c.select("font,span"),function(ai){var ah;if(b(ai)){ah=q.getBookmark();ag(ai);q.moveToBookmark(ah);V.nodeChanged()}});if(!P.isListening&&af()){P.isListening=true;function W(ai,aj){var ah=c.createRng();ag(ai);ah.setStart(aj,aj.nodeValue.length);ah.setEnd(aj,aj.nodeValue.length);q.setRng(ah);V.nodeChanged()}var Z=false;O("onKeyDown,onKeyUp,onKeyPress,onMouseUp".split(","),function(ah){V[ah].addToTop(function(ai,al){if(al.keyCode==13&&!al.shiftKey){Z=true;return}if(af()&&!a.dom.RangeUtils.compareRanges(P.lastRng,q.getRng())){var aj=false;O(c.select("font,span"),function(ao){var ap,an;if(b(ao)){aj=true;ap=ao.firstChild;while(ap&&ap.nodeType!=3){ap=ap.firstChild}if(ap){W(ao,ap)}else{c.remove(ao)}}});if(Z&&!aj){var ak=q.getNode();var am=ak;while(am&&am.nodeType!=3){am=am.firstChild}if(am){ak=am.parentNode;while(!F(ak)){ak=ak.parentNode}W(ak,am)}}if(al.type=="keyup"||al.type=="mouseup"){ab();Z=false}}})})}}}}})(tinymce);tinymce.onAddEditor.add(function(e,a){var d,h,g,c=a.settings;if(c.inline_styles){h=e.explode(c.font_size_style_values);function b(j,i){e.each(i,function(l,k){if(l){g.setStyle(j,k,l)}});g.rename(j,"span")}d={font:function(j,i){b(i,{backgroundColor:i.style.backgroundColor,color:i.color,fontFamily:i.face,fontSize:h[parseInt(i.size)-1]})},u:function(j,i){b(i,{textDecoration:"underline"})},strike:function(j,i){b(i,{textDecoration:"line-through"})}};function f(i,j){g=i.dom;if(c.convert_fonts_to_spans){e.each(g.select("font,u,strike",j.node),function(k){d[k.nodeName.toLowerCase()](a.dom,k)})}}a.onPreProcess.add(f);a.onSetContent.add(f);a.onInit.add(function(){a.selection.onSetContent.add(f)})}}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/tiny_mce_popup.js b/src/core/static/js/tiny_mce/tiny_mce_popup.js new file mode 100644 index 0000000..f859d24 --- /dev/null +++ b/src/core/static/js/tiny_mce/tiny_mce_popup.js @@ -0,0 +1,5 @@ + +// Uncomment and change this document.domain value if you are loading the script cross subdomains +// document.domain = 'moxiecode.com'; + +var tinymce=null,tinyMCEPopup,tinyMCE;tinyMCEPopup={init:function(){var b=this,a,c;a=b.getWin();tinymce=a.tinymce;tinyMCE=a.tinyMCE;b.editor=tinymce.EditorManager.activeEditor;b.params=b.editor.windowManager.params;b.features=b.editor.windowManager.features;b.dom=b.editor.windowManager.createInstance("tinymce.dom.DOMUtils",document);if(b.features.popup_css!==false){b.dom.loadCSS(b.features.popup_css||b.editor.settings.popup_css)}b.listeners=[];b.onInit={add:function(e,d){b.listeners.push({func:e,scope:d})}};b.isWindow=!b.getWindowArg("mce_inline");b.id=b.getWindowArg("mce_window_id");b.editor.windowManager.onOpen.dispatch(b.editor.windowManager,window)},getWin:function(){return(!window.frameElement&&window.dialogArguments)||opener||parent||top},getWindowArg:function(c,b){var a=this.params[c];return tinymce.is(a)?a:b},getParam:function(b,a){return this.editor.getParam(b,a)},getLang:function(b,a){return this.editor.getLang(b,a)},execCommand:function(d,c,e,b){b=b||{};b.skip_focus=1;this.restoreSelection();return this.editor.execCommand(d,c,e,b)},resizeToInnerSize:function(){var a=this;setTimeout(function(){var b=a.dom.getViewPort(window);a.editor.windowManager.resizeBy(a.getWindowArg("mce_width")-b.w,a.getWindowArg("mce_height")-b.h,a.id||window)},10)},executeOnLoad:function(s){this.onInit.add(function(){eval(s)})},storeSelection:function(){this.editor.windowManager.bookmark=tinyMCEPopup.editor.selection.getBookmark(1)},restoreSelection:function(){var a=tinyMCEPopup;if(!a.isWindow&&tinymce.isIE){a.editor.selection.moveToBookmark(a.editor.windowManager.bookmark)}},requireLangPack:function(){var b=this,a=b.getWindowArg("plugin_url")||b.getWindowArg("theme_url");if(a&&b.editor.settings.language&&b.features.translate_i18n!==false&&b.editor.settings.language_load!==false){a+="/langs/"+b.editor.settings.language+"_dlg.js";if(!tinymce.ScriptLoader.isDone(a)){document.write('<script type="text/javascript" src="'+tinymce._addVer(a)+'"><\/script>');tinymce.ScriptLoader.markDone(a)}}},pickColor:function(b,a){this.execCommand("mceColorPicker",true,{color:document.getElementById(a).value,func:function(e){document.getElementById(a).value=e;try{document.getElementById(a).onchange()}catch(d){}}})},openBrowser:function(a,c,b){tinyMCEPopup.restoreSelection();this.editor.execCallback("file_browser_callback",a,document.getElementById(a).value,c,window)},confirm:function(b,a,c){this.editor.windowManager.confirm(b,a,c,window)},alert:function(b,a,c){this.editor.windowManager.alert(b,a,c,window)},close:function(){var a=this;function b(){a.editor.windowManager.close(window);tinymce=tinyMCE=a.editor=a.params=a.dom=a.dom.doc=null}if(tinymce.isOpera){a.getWin().setTimeout(b,0)}else{b()}},_restoreSelection:function(){var a=window.event.srcElement;if(a.nodeName=="INPUT"&&(a.type=="submit"||a.type=="button")){tinyMCEPopup.restoreSelection()}},_onDOMLoaded:function(){var b=tinyMCEPopup,d=document.title,e,c,a;if(b.domLoaded){return}b.domLoaded=1;if(b.features.translate_i18n!==false){c=document.body.innerHTML;if(tinymce.isIE){c=c.replace(/ (value|title|alt)=([^"][^\s>]+)/gi,' $1="$2"')}document.dir=b.editor.getParam("directionality","");if((a=b.editor.translate(c))&&a!=c){document.body.innerHTML=a}if((a=b.editor.translate(d))&&a!=d){document.title=d=a}}if(!b.editor.getParam("browser_preferred_colors",false)||!b.isWindow){b.dom.addClass(document.body,"forceColors")}document.body.style.display="";if(tinymce.isIE){document.attachEvent("onmouseup",tinyMCEPopup._restoreSelection);b.dom.add(b.dom.select("head")[0],"base",{target:"_self"})}b.restoreSelection();b.resizeToInnerSize();if(!b.isWindow){b.editor.windowManager.setTitle(window,d)}else{window.focus()}if(!tinymce.isIE&&!b.isWindow){tinymce.dom.Event._add(document,"focus",function(){b.editor.windowManager.focus(b.id)})}tinymce.each(b.dom.select("select"),function(f){f.onkeydown=tinyMCEPopup._accessHandler});tinymce.each(b.listeners,function(f){f.func.call(f.scope,b.editor)});if(b.getWindowArg("mce_auto_focus",true)){window.focus();tinymce.each(document.forms,function(g){tinymce.each(g.elements,function(f){if(b.dom.hasClass(f,"mceFocus")&&!f.disabled){f.focus();return false}})})}document.onkeyup=tinyMCEPopup._closeWinKeyHandler},_accessHandler:function(a){a=a||window.event;if(a.keyCode==13||a.keyCode==32){a=a.target||a.srcElement;if(a.onchange){a.onchange()}return tinymce.dom.Event.cancel(a)}},_closeWinKeyHandler:function(a){a=a||window.event;if(a.keyCode==27){tinyMCEPopup.close()}},_wait:function(){if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);tinyMCEPopup._onDOMLoaded()}});if(document.documentElement.doScroll&&window==window.top){(function(){if(tinyMCEPopup.domLoaded){return}try{document.documentElement.doScroll("left")}catch(a){setTimeout(arguments.callee,0);return}tinyMCEPopup._onDOMLoaded()})()}document.attachEvent("onload",tinyMCEPopup._onDOMLoaded)}else{if(document.addEventListener){window.addEventListener("DOMContentLoaded",tinyMCEPopup._onDOMLoaded,false);window.addEventListener("load",tinyMCEPopup._onDOMLoaded,false)}}}};tinyMCEPopup.init();tinyMCEPopup._wait(); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/tiny_mce_src.js b/src/core/static/js/tiny_mce/tiny_mce_src.js new file mode 100644 index 0000000..358de47 --- /dev/null +++ b/src/core/static/js/tiny_mce/tiny_mce_src.js @@ -0,0 +1,16479 @@ +(function(win) { + var whiteSpaceRe = /^\s*|\s*$/g, + undefined, isRegExpBroken = 'B'.replace(/A(.)|B/, '$1') === '$1'; + + var tinymce = { + majorVersion : '3', + + minorVersion : '4.6', + + releaseDate : '2011-09-29', + + _init : function() { + var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v; + + t.isOpera = win.opera && opera.buildNumber; + + t.isWebKit = /WebKit/.test(ua); + + t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName); + + t.isIE6 = t.isIE && /MSIE [56]/.test(ua); + + t.isIE7 = t.isIE && /MSIE [7]/.test(ua); + + t.isIE8 = t.isIE && /MSIE [8]/.test(ua); + + t.isIE9 = t.isIE && /MSIE [9]/.test(ua); + + t.isGecko = !t.isWebKit && /Gecko/.test(ua); + + t.isMac = ua.indexOf('Mac') != -1; + + t.isAir = /adobeair/i.test(ua); + + t.isIDevice = /(iPad|iPhone)/.test(ua); + + t.isIOS5 = t.isIDevice && ua.match(/AppleWebKit\/(\d*)/)[1]>=534; + + // TinyMCE .NET webcontrol might be setting the values for TinyMCE + if (win.tinyMCEPreInit) { + t.suffix = tinyMCEPreInit.suffix; + t.baseURL = tinyMCEPreInit.base; + t.query = tinyMCEPreInit.query; + return; + } + + // Get suffix and base + t.suffix = ''; + + // If base element found, add that infront of baseURL + nl = d.getElementsByTagName('base'); + for (i=0; i<nl.length; i++) { + if (v = nl[i].href) { + // Host only value like http://site.com or http://site.com:8008 + if (/^https?:\/\/[^\/]+$/.test(v)) + v += '/'; + + base = v ? v.match(/.*\//)[0] : ''; // Get only directory + } + } + + function getBase(n) { + if (n.src && /tiny_mce(|_gzip|_jquery|_prototype|_full)(_dev|_src)?.js/.test(n.src)) { + if (/_(src|dev)\.js/g.test(n.src)) + t.suffix = '_src'; + + if ((p = n.src.indexOf('?')) != -1) + t.query = n.src.substring(p + 1); + + t.baseURL = n.src.substring(0, n.src.lastIndexOf('/')); + + // If path to script is relative and a base href was found add that one infront + // the src property will always be an absolute one on non IE browsers and IE 8 + // so this logic will basically only be executed on older IE versions + if (base && t.baseURL.indexOf('://') == -1 && t.baseURL.indexOf('/') !== 0) + t.baseURL = base + t.baseURL; + + return t.baseURL; + } + + return null; + }; + + // Check document + nl = d.getElementsByTagName('script'); + for (i=0; i<nl.length; i++) { + if (getBase(nl[i])) + return; + } + + // Check head + n = d.getElementsByTagName('head')[0]; + if (n) { + nl = n.getElementsByTagName('script'); + for (i=0; i<nl.length; i++) { + if (getBase(nl[i])) + return; + } + } + + return; + }, + + is : function(o, t) { + if (!t) + return o !== undefined; + + if (t == 'array' && (o.hasOwnProperty && o instanceof Array)) + return true; + + return typeof(o) == t; + }, + + makeMap : function(items, delim, map) { + var i; + + items = items || []; + delim = delim || ','; + + if (typeof(items) == "string") + items = items.split(delim); + + map = map || {}; + + i = items.length; + while (i--) + map[items[i]] = {}; + + return map; + }, + + each : function(o, cb, s) { + var n, l; + + if (!o) + return 0; + + s = s || o; + + if (o.length !== undefined) { + // Indexed arrays, needed for Safari + for (n=0, l = o.length; n < l; n++) { + if (cb.call(s, o[n], n, o) === false) + return 0; + } + } else { + // Hashtables + for (n in o) { + if (o.hasOwnProperty(n)) { + if (cb.call(s, o[n], n, o) === false) + return 0; + } + } + } + + return 1; + }, + + + map : function(a, f) { + var o = []; + + tinymce.each(a, function(v) { + o.push(f(v)); + }); + + return o; + }, + + grep : function(a, f) { + var o = []; + + tinymce.each(a, function(v) { + if (!f || f(v)) + o.push(v); + }); + + return o; + }, + + inArray : function(a, v) { + var i, l; + + if (a) { + for (i = 0, l = a.length; i < l; i++) { + if (a[i] === v) + return i; + } + } + + return -1; + }, + + extend : function(o, e) { + var i, l, a = arguments; + + for (i = 1, l = a.length; i < l; i++) { + e = a[i]; + + tinymce.each(e, function(v, n) { + if (v !== undefined) + o[n] = v; + }); + } + + return o; + }, + + + trim : function(s) { + return (s ? '' + s : '').replace(whiteSpaceRe, ''); + }, + + create : function(s, p, root) { + var t = this, sp, ns, cn, scn, c, de = 0; + + // Parse : <prefix> <class>:<super class> + s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s); + cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name + + // Create namespace for new class + ns = t.createNS(s[3].replace(/\.\w+$/, ''), root); + + // Class already exists + if (ns[cn]) + return; + + // Make pure static class + if (s[2] == 'static') { + ns[cn] = p; + + if (this.onCreate) + this.onCreate(s[2], s[3], ns[cn]); + + return; + } + + // Create default constructor + if (!p[cn]) { + p[cn] = function() {}; + de = 1; + } + + // Add constructor and methods + ns[cn] = p[cn]; + t.extend(ns[cn].prototype, p); + + // Extend + if (s[5]) { + sp = t.resolve(s[5]).prototype; + scn = s[5].match(/\.(\w+)$/i)[1]; // Class name + + // Extend constructor + c = ns[cn]; + if (de) { + // Add passthrough constructor + ns[cn] = function() { + return sp[scn].apply(this, arguments); + }; + } else { + // Add inherit constructor + ns[cn] = function() { + this.parent = sp[scn]; + return c.apply(this, arguments); + }; + } + ns[cn].prototype[cn] = ns[cn]; + + // Add super methods + t.each(sp, function(f, n) { + ns[cn].prototype[n] = sp[n]; + }); + + // Add overridden methods + t.each(p, function(f, n) { + // Extend methods if needed + if (sp[n]) { + ns[cn].prototype[n] = function() { + this.parent = sp[n]; + return f.apply(this, arguments); + }; + } else { + if (n != cn) + ns[cn].prototype[n] = f; + } + }); + } + + // Add static methods + t.each(p['static'], function(f, n) { + ns[cn][n] = f; + }); + + if (this.onCreate) + this.onCreate(s[2], s[3], ns[cn].prototype); + }, + + walk : function(o, f, n, s) { + s = s || this; + + if (o) { + if (n) + o = o[n]; + + tinymce.each(o, function(o, i) { + if (f.call(s, o, i, n) === false) + return false; + + tinymce.walk(o, f, n, s); + }); + } + }, + + createNS : function(n, o) { + var i, v; + + o = o || win; + + n = n.split('.'); + for (i=0; i<n.length; i++) { + v = n[i]; + + if (!o[v]) + o[v] = {}; + + o = o[v]; + } + + return o; + }, + + resolve : function(n, o) { + var i, l; + + o = o || win; + + n = n.split('.'); + for (i = 0, l = n.length; i < l; i++) { + o = o[n[i]]; + + if (!o) + break; + } + + return o; + }, + + addUnload : function(f, s) { + var t = this; + + f = {func : f, scope : s || this}; + + if (!t.unloads) { + function unload() { + var li = t.unloads, o, n; + + if (li) { + // Call unload handlers + for (n in li) { + o = li[n]; + + if (o && o.func) + o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy + } + + // Detach unload function + if (win.detachEvent) { + win.detachEvent('onbeforeunload', fakeUnload); + win.detachEvent('onunload', unload); + } else if (win.removeEventListener) + win.removeEventListener('unload', unload, false); + + // Destroy references + t.unloads = o = li = w = unload = 0; + + // Run garbarge collector on IE + if (win.CollectGarbage) + CollectGarbage(); + } + }; + + function fakeUnload() { + var d = document; + + // Is there things still loading, then do some magic + if (d.readyState == 'interactive') { + function stop() { + // Prevent memory leak + d.detachEvent('onstop', stop); + + // Call unload handler + if (unload) + unload(); + + d = 0; + }; + + // Fire unload when the currently loading page is stopped + if (d) + d.attachEvent('onstop', stop); + + // Remove onstop listener after a while to prevent the unload function + // to execute if the user presses cancel in an onbeforeunload + // confirm dialog and then presses the browser stop button + win.setTimeout(function() { + if (d) + d.detachEvent('onstop', stop); + }, 0); + } + }; + + // Attach unload handler + if (win.attachEvent) { + win.attachEvent('onunload', unload); + win.attachEvent('onbeforeunload', fakeUnload); + } else if (win.addEventListener) + win.addEventListener('unload', unload, false); + + // Setup initial unload handler array + t.unloads = [f]; + } else + t.unloads.push(f); + + return f; + }, + + removeUnload : function(f) { + var u = this.unloads, r = null; + + tinymce.each(u, function(o, i) { + if (o && o.func == f) { + u.splice(i, 1); + r = f; + return false; + } + }); + + return r; + }, + + explode : function(s, d) { + return s ? tinymce.map(s.split(d || ','), tinymce.trim) : s; + }, + + _addVer : function(u) { + var v; + + if (!this.query) + return u; + + v = (u.indexOf('?') == -1 ? '?' : '&') + this.query; + + if (u.indexOf('#') == -1) + return u + v; + + return u.replace('#', v + '#'); + }, + + // Fix function for IE 9 where regexps isn't working correctly + // Todo: remove me once MS fixes the bug + _replace : function(find, replace, str) { + // On IE9 we have to fake $x replacement + if (isRegExpBroken) { + return str.replace(find, function() { + var val = replace, args = arguments, i; + + for (i = 0; i < args.length - 2; i++) { + if (args[i] === undefined) { + val = val.replace(new RegExp('\\$' + i, 'g'), ''); + } else { + val = val.replace(new RegExp('\\$' + i, 'g'), args[i]); + } + } + + return val; + }); + } + + return str.replace(find, replace); + } + + }; + + // Initialize the API + tinymce._init(); + + // Expose tinymce namespace to the global namespace (window) + win.tinymce = win.tinyMCE = tinymce; + + // Describe the different namespaces + + })(window); + + + +tinymce.create('tinymce.util.Dispatcher', { + scope : null, + listeners : null, + + Dispatcher : function(s) { + this.scope = s || this; + this.listeners = []; + }, + + add : function(cb, s) { + this.listeners.push({cb : cb, scope : s || this.scope}); + + return cb; + }, + + addToTop : function(cb, s) { + this.listeners.unshift({cb : cb, scope : s || this.scope}); + + return cb; + }, + + remove : function(cb) { + var l = this.listeners, o = null; + + tinymce.each(l, function(c, i) { + if (cb == c.cb) { + o = cb; + l.splice(i, 1); + return false; + } + }); + + return o; + }, + + dispatch : function() { + var s, a = arguments, i, li = this.listeners, c; + + // Needs to be a real loop since the listener count might change while looping + // And this is also more efficient + for (i = 0; i<li.length; i++) { + c = li[i]; + s = c.cb.apply(c.scope, a); + + if (s === false) + break; + } + + return s; + } + + }); + +(function() { + var each = tinymce.each; + + tinymce.create('tinymce.util.URI', { + URI : function(u, s) { + var t = this, o, a, b, base_url; + + // Trim whitespace + u = tinymce.trim(u); + + // Default settings + s = t.settings = s || {}; + + // Strange app protocol that isn't http/https or local anchor + // For example: mailto,skype,tel etc. + if (/^([\w\-]+):([^\/]{2})/i.test(u) || /^\s*#/.test(u)) { + t.source = u; + return; + } + + // Absolute path with no host, fake host and protocol + if (u.indexOf('/') === 0 && u.indexOf('//') !== 0) + u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u; + + // Relative path http:// or protocol relative //path + if (!/^[\w-]*:?\/\//.test(u)) { + base_url = s.base_uri ? s.base_uri.path : new tinymce.util.URI(location.href).directory; + u = ((s.base_uri && s.base_uri.protocol) || 'http') + '://mce_host' + t.toAbsPath(base_url, u); + } + + // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri) + u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something + u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u); + each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) { + var s = u[i]; + + // Zope 3 workaround, they use @@something + if (s) + s = s.replace(/\(mce_at\)/g, '@@'); + + t[v] = s; + }); + + if (b = s.base_uri) { + if (!t.protocol) + t.protocol = b.protocol; + + if (!t.userInfo) + t.userInfo = b.userInfo; + + if (!t.port && t.host == 'mce_host') + t.port = b.port; + + if (!t.host || t.host == 'mce_host') + t.host = b.host; + + t.source = ''; + } + + //t.path = t.path || '/'; + }, + + setPath : function(p) { + var t = this; + + p = /^(.*?)\/?(\w+)?$/.exec(p); + + // Update path parts + t.path = p[0]; + t.directory = p[1]; + t.file = p[2]; + + // Rebuild source + t.source = ''; + t.getURI(); + }, + + toRelative : function(u) { + var t = this, o; + + if (u === "./") + return u; + + u = new tinymce.util.URI(u, {base_uri : t}); + + // Not on same domain/port or protocol + if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol) + return u.getURI(); + + o = t.toRelPath(t.path, u.path); + + // Add query + if (u.query) + o += '?' + u.query; + + // Add anchor + if (u.anchor) + o += '#' + u.anchor; + + return o; + }, + + toAbsolute : function(u, nh) { + var u = new tinymce.util.URI(u, {base_uri : this}); + + return u.getURI(this.host == u.host && this.protocol == u.protocol ? nh : 0); + }, + + toRelPath : function(base, path) { + var items, bp = 0, out = '', i, l; + + // Split the paths + base = base.substring(0, base.lastIndexOf('/')); + base = base.split('/'); + items = path.split('/'); + + if (base.length >= items.length) { + for (i = 0, l = base.length; i < l; i++) { + if (i >= items.length || base[i] != items[i]) { + bp = i + 1; + break; + } + } + } + + if (base.length < items.length) { + for (i = 0, l = items.length; i < l; i++) { + if (i >= base.length || base[i] != items[i]) { + bp = i + 1; + break; + } + } + } + + if (bp == 1) + return path; + + for (i = 0, l = base.length - (bp - 1); i < l; i++) + out += "../"; + + for (i = bp - 1, l = items.length; i < l; i++) { + if (i != bp - 1) + out += "/" + items[i]; + else + out += items[i]; + } + + return out; + }, + + toAbsPath : function(base, path) { + var i, nb = 0, o = [], tr, outPath; + + // Split paths + tr = /\/$/.test(path) ? '/' : ''; + base = base.split('/'); + path = path.split('/'); + + // Remove empty chunks + each(base, function(k) { + if (k) + o.push(k); + }); + + base = o; + + // Merge relURLParts chunks + for (i = path.length - 1, o = []; i >= 0; i--) { + // Ignore empty or . + if (path[i].length == 0 || path[i] == ".") + continue; + + // Is parent + if (path[i] == '..') { + nb++; + continue; + } + + // Move up + if (nb > 0) { + nb--; + continue; + } + + o.push(path[i]); + } + + i = base.length - nb; + + // If /a/b/c or / + if (i <= 0) + outPath = o.reverse().join('/'); + else + outPath = base.slice(0, i).join('/') + '/' + o.reverse().join('/'); + + // Add front / if it's needed + if (outPath.indexOf('/') !== 0) + outPath = '/' + outPath; + + // Add traling / if it's needed + if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) + outPath += tr; + + return outPath; + }, + + getURI : function(nh) { + var s, t = this; + + // Rebuild source + if (!t.source || nh) { + s = ''; + + if (!nh) { + if (t.protocol) + s += t.protocol + '://'; + + if (t.userInfo) + s += t.userInfo + '@'; + + if (t.host) + s += t.host; + + if (t.port) + s += ':' + t.port; + } + + if (t.path) + s += t.path; + + if (t.query) + s += '?' + t.query; + + if (t.anchor) + s += '#' + t.anchor; + + t.source = s; + } + + return t.source; + } + }); +})(); + +(function() { + var each = tinymce.each; + + tinymce.create('static tinymce.util.Cookie', { + getHash : function(n) { + var v = this.get(n), h; + + if (v) { + each(v.split('&'), function(v) { + v = v.split('='); + h = h || {}; + h[unescape(v[0])] = unescape(v[1]); + }); + } + + return h; + }, + + setHash : function(n, v, e, p, d, s) { + var o = ''; + + each(v, function(v, k) { + o += (!o ? '' : '&') + escape(k) + '=' + escape(v); + }); + + this.set(n, o, e, p, d, s); + }, + + get : function(n) { + var c = document.cookie, e, p = n + "=", b; + + // Strict mode + if (!c) + return; + + b = c.indexOf("; " + p); + + if (b == -1) { + b = c.indexOf(p); + + if (b != 0) + return null; + } else + b += 2; + + e = c.indexOf(";", b); + + if (e == -1) + e = c.length; + + return unescape(c.substring(b + p.length, e)); + }, + + set : function(n, v, e, p, d, s) { + document.cookie = n + "=" + escape(v) + + ((e) ? "; expires=" + e.toGMTString() : "") + + ((p) ? "; path=" + escape(p) : "") + + ((d) ? "; domain=" + d : "") + + ((s) ? "; secure" : ""); + }, + + remove : function(n, p) { + var d = new Date(); + + d.setTime(d.getTime() - 1000); + + this.set(n, '', d, p, d); + } + }); +})(); + +(function() { + function serialize(o, quote) { + var i, v, t; + + quote = quote || '"'; + + if (o == null) + return 'null'; + + t = typeof o; + + if (t == 'string') { + v = '\bb\tt\nn\ff\rr\""\'\'\\\\'; + + return quote + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g, function(a, b) { + // Make sure single quotes never get encoded inside double quotes for JSON compatibility + if (quote === '"' && a === "'") + return a; + + i = v.indexOf(b); + + if (i + 1) + return '\\' + v.charAt(i + 1); + + a = b.charCodeAt().toString(16); + + return '\\u' + '0000'.substring(a.length) + a; + }) + quote; + } + + if (t == 'object') { + if (o.hasOwnProperty && o instanceof Array) { + for (i=0, v = '['; i<o.length; i++) + v += (i > 0 ? ',' : '') + serialize(o[i], quote); + + return v + ']'; + } + + v = '{'; + + for (i in o) + v += typeof o[i] != 'function' ? (v.length > 1 ? ',' + quote : quote) + i + quote +':' + serialize(o[i], quote) : ''; + + return v + '}'; + } + + return '' + o; + }; + + tinymce.util.JSON = { + serialize: serialize, + + parse: function(s) { + try { + return eval('(' + s + ')'); + } catch (ex) { + // Ignore + } + } + + }; +})(); +tinymce.create('static tinymce.util.XHR', { + send : function(o) { + var x, t, w = window, c = 0; + + // Default settings + o.scope = o.scope || this; + o.success_scope = o.success_scope || o.scope; + o.error_scope = o.error_scope || o.scope; + o.async = o.async === false ? false : true; + o.data = o.data || ''; + + function get(s) { + x = 0; + + try { + x = new ActiveXObject(s); + } catch (ex) { + } + + return x; + }; + + x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP'); + + if (x) { + if (x.overrideMimeType) + x.overrideMimeType(o.content_type); + + x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async); + + if (o.content_type) + x.setRequestHeader('Content-Type', o.content_type); + + x.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + + x.send(o.data); + + function ready() { + if (!o.async || x.readyState == 4 || c++ > 10000) { + if (o.success && c < 10000 && x.status == 200) + o.success.call(o.success_scope, '' + x.responseText, x, o); + else if (o.error) + o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o); + + x = null; + } else + w.setTimeout(ready, 10); + }; + + // Syncronous request + if (!o.async) + return ready(); + + // Wait for response, onReadyStateChange can not be used since it leaks memory in IE + t = w.setTimeout(ready, 10); + } + } +}); + +(function() { + var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR; + + tinymce.create('tinymce.util.JSONRequest', { + JSONRequest : function(s) { + this.settings = extend({ + }, s); + this.count = 0; + }, + + send : function(o) { + var ecb = o.error, scb = o.success; + + o = extend(this.settings, o); + + o.success = function(c, x) { + c = JSON.parse(c); + + if (typeof(c) == 'undefined') { + c = { + error : 'JSON Parse error.' + }; + } + + if (c.error) + ecb.call(o.error_scope || o.scope, c.error, x); + else + scb.call(o.success_scope || o.scope, c.result); + }; + + o.error = function(ty, x) { + if (ecb) + ecb.call(o.error_scope || o.scope, ty, x); + }; + + o.data = JSON.serialize({ + id : o.id || 'c' + (this.count++), + method : o.method, + params : o.params + }); + + // JSON content type for Ruby on rails. Bug: #1883287 + o.content_type = 'application/json'; + + XHR.send(o); + }, + + 'static' : { + sendRPC : function(o) { + return new tinymce.util.JSONRequest().send(o); + } + } + }); +}()); +(function(tinymce){ + tinymce.VK = { + DELETE:46, + BACKSPACE:8 + + } + +})(tinymce); + +(function(tinymce) { + var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE; + + function cleanupStylesWhenDeleting(ed) { + var dom = ed.dom, selection = ed.selection; + + ed.onKeyDown.add(function(ed, e) { + var rng, blockElm, node, clonedSpan, isDelete; + + isDelete = e.keyCode == DELETE; + if (isDelete || e.keyCode == BACKSPACE) { + e.preventDefault(); + rng = selection.getRng(); + + // Find root block + blockElm = dom.getParent(rng.startContainer, dom.isBlock); + + // On delete clone the root span of the next block element + if (isDelete) + blockElm = dom.getNext(blockElm, dom.isBlock); + + // Locate root span element and clone it since it would otherwise get merged by the "apple-style-span" on delete/backspace + if (blockElm) { + node = blockElm.firstChild; + + // Ignore empty text nodes + while (node.nodeType == 3 && node.nodeValue.length == 0) + node = node.nextSibling; + + if (node && node.nodeName === 'SPAN') { + clonedSpan = node.cloneNode(false); + } + } + + // Do the backspace/delete actiopn + ed.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null); + + // Find all odd apple-style-spans + blockElm = dom.getParent(rng.startContainer, dom.isBlock); + tinymce.each(dom.select('span.Apple-style-span,font.Apple-style-span', blockElm), function(span) { + var bm = selection.getBookmark(); + + if (clonedSpan) { + dom.replace(clonedSpan.cloneNode(false), span, true); + } else { + dom.remove(span, true); + } + + // Restore the selection + selection.moveToBookmark(bm); + }); + } + }); + }; + + function emptyEditorWhenDeleting(ed) { + ed.onKeyUp.add(function(ed, e) { + var keyCode = e.keyCode; + + if (keyCode == DELETE || keyCode == BACKSPACE) { + if (ed.dom.isEmpty(ed.getBody())) { + ed.setContent('', {format : 'raw'}); + ed.nodeChanged(); + return; + } + } + }); + }; + + function inputMethodFocus(ed) { + ed.dom.bind(ed.getDoc(), 'focusin', function() { + ed.selection.setRng(ed.selection.getRng()); + }); + }; + + function focusBody(ed) { + // Fix for a focus bug in FF 3.x where the body element + // wouldn't get proper focus if the user clicked on the HTML element + if (!Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4 + ed.onMouseDown.add(function(ed, e) { + if (e.target.nodeName === "HTML") { + var body = ed.getBody(); + + // Blur the body it's focused but not correctly focused + body.blur(); + + // Refocus the body after a little while + setTimeout(function() { + body.focus(); + }, 0); + } + }); + } + }; + + function selectControlElements(ed) { + ed.onClick.add(function(ed, e) { + e = e.target; + + // Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250 + // WebKit can't even do simple things like selecting an image + // Needs tobe the setBaseAndExtend or it will fail to select floated images + if (/^(IMG|HR)$/.test(e.nodeName)) + ed.selection.getSel().setBaseAndExtent(e, 0, e, 1); + + if (e.nodeName == 'A' && ed.dom.hasClass(e, 'mceItemAnchor')) + ed.selection.select(e); + + ed.nodeChanged(); + }); + }; + + tinymce.create('tinymce.util.Quirks', { + Quirks: function(ed) { + // WebKit + if (tinymce.isWebKit) { + cleanupStylesWhenDeleting(ed); + emptyEditorWhenDeleting(ed); + inputMethodFocus(ed); + selectControlElements(ed); + } + + // IE + if (tinymce.isIE) { + emptyEditorWhenDeleting(ed); + } + + // Gecko + if (tinymce.isGecko) { + focusBody(ed); + } + } + }); +})(tinymce); +(function(tinymce) { + var namedEntities, baseEntities, reverseEntities, + attrsCharsRegExp = /[&<>\"\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + textCharsRegExp = /[<>&\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + rawCharsRegExp = /[<>&\"\']/g, + entityRegExp = /&(#x|#)?([\w]+);/g, + asciiMap = { + 128 : "\u20AC", 130 : "\u201A", 131 : "\u0192", 132 : "\u201E", 133 : "\u2026", 134 : "\u2020", + 135 : "\u2021", 136 : "\u02C6", 137 : "\u2030", 138 : "\u0160", 139 : "\u2039", 140 : "\u0152", + 142 : "\u017D", 145 : "\u2018", 146 : "\u2019", 147 : "\u201C", 148 : "\u201D", 149 : "\u2022", + 150 : "\u2013", 151 : "\u2014", 152 : "\u02DC", 153 : "\u2122", 154 : "\u0161", 155 : "\u203A", + 156 : "\u0153", 158 : "\u017E", 159 : "\u0178" + }; + + // Raw entities + baseEntities = { + '\"' : '&quot;', // Needs to be escaped since the YUI compressor would otherwise break the code + "'" : '&#39;', + '<' : '&lt;', + '>' : '&gt;', + '&' : '&amp;' + }; + + // Reverse lookup table for raw entities + reverseEntities = { + '&lt;' : '<', + '&gt;' : '>', + '&amp;' : '&', + '&quot;' : '"', + '&apos;' : "'" + }; + + // Decodes text by using the browser + function nativeDecode(text) { + var elm; + + elm = document.createElement("div"); + elm.innerHTML = text; + + return elm.textContent || elm.innerText || text; + }; + + // Build a two way lookup table for the entities + function buildEntitiesLookup(items, radix) { + var i, chr, entity, lookup = {}; + + if (items) { + items = items.split(','); + radix = radix || 10; + + // Build entities lookup table + for (i = 0; i < items.length; i += 2) { + chr = String.fromCharCode(parseInt(items[i], radix)); + + // Only add non base entities + if (!baseEntities[chr]) { + entity = '&' + items[i + 1] + ';'; + lookup[chr] = entity; + lookup[entity] = chr; + } + } + + return lookup; + } + }; + + // Unpack entities lookup where the numbers are in radix 32 to reduce the size + namedEntities = buildEntitiesLookup( + '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' + + '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' + + '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' + + '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' + + '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' + + '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' + + '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' + + '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' + + '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' + + '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' + + 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' + + 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' + + 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' + + 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' + + 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' + + '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' + + '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' + + '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' + + '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' + + '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' + + 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' + + 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' + + 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' + + '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' + + '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro' + , 32); + + tinymce.html = tinymce.html || {}; + + tinymce.html.Entities = { + encodeRaw : function(text, attr) { + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + return baseEntities[chr] || chr; + }); + }, + + encodeAllRaw : function(text) { + return ('' + text).replace(rawCharsRegExp, function(chr) { + return baseEntities[chr] || chr; + }); + }, + + encodeNumeric : function(text, attr) { + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + // Multi byte sequence convert it to a single entity + if (chr.length > 1) + return '&#' + (((chr.charCodeAt(0) - 0xD800) * 0x400) + (chr.charCodeAt(1) - 0xDC00) + 0x10000) + ';'; + + return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';'; + }); + }, + + encodeNamed : function(text, attr, entities) { + entities = entities || namedEntities; + + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + return baseEntities[chr] || entities[chr] || chr; + }); + }, + + getEncodeFunc : function(name, entities) { + var Entities = tinymce.html.Entities; + + entities = buildEntitiesLookup(entities) || namedEntities; + + function encodeNamedAndNumeric(text, attr) { + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + return baseEntities[chr] || entities[chr] || '&#' + chr.charCodeAt(0) + ';' || chr; + }); + }; + + function encodeCustomNamed(text, attr) { + return Entities.encodeNamed(text, attr, entities); + }; + + // Replace + with , to be compatible with previous TinyMCE versions + name = tinymce.makeMap(name.replace(/\+/g, ',')); + + // Named and numeric encoder + if (name.named && name.numeric) + return encodeNamedAndNumeric; + + // Named encoder + if (name.named) { + // Custom names + if (entities) + return encodeCustomNamed; + + return Entities.encodeNamed; + } + + // Numeric + if (name.numeric) + return Entities.encodeNumeric; + + // Raw encoder + return Entities.encodeRaw; + }, + + decode : function(text) { + return text.replace(entityRegExp, function(all, numeric, value) { + if (numeric) { + value = parseInt(value, numeric.length === 2 ? 16 : 10); + + // Support upper UTF + if (value > 0xFFFF) { + value -= 0x10000; + + return String.fromCharCode(0xD800 + (value >> 10), 0xDC00 + (value & 0x3FF)); + } else + return asciiMap[value] || String.fromCharCode(value); + } + + return reverseEntities[all] || namedEntities[all] || nativeDecode(all); + }); + } + }; +})(tinymce); + +tinymce.html.Styles = function(settings, schema) { + var rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi, + urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi, + styleRegExp = /\s*([^:]+):\s*([^;]+);?/g, + trimRightRegExp = /\s+$/, + urlColorRegExp = /rgb/, + undef, i, encodingLookup = {}, encodingItems; + + settings = settings || {}; + + encodingItems = '\\" \\\' \\; \\: ; : \uFEFF'.split(' '); + for (i = 0; i < encodingItems.length; i++) { + encodingLookup[encodingItems[i]] = '\uFEFF' + i; + encodingLookup['\uFEFF' + i] = encodingItems[i]; + } + + function toHex(match, r, g, b) { + function hex(val) { + val = parseInt(val).toString(16); + + return val.length > 1 ? val : '0' + val; // 0 -> 00 + }; + + return '#' + hex(r) + hex(g) + hex(b); + }; + + return { + toHex : function(color) { + return color.replace(rgbRegExp, toHex); + }, + + parse : function(css) { + var styles = {}, matches, name, value, isEncoded, urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope || this; + + function compress(prefix, suffix) { + var top, right, bottom, left; + + // Get values and check it it needs compressing + top = styles[prefix + '-top' + suffix]; + if (!top) + return; + + right = styles[prefix + '-right' + suffix]; + if (top != right) + return; + + bottom = styles[prefix + '-bottom' + suffix]; + if (right != bottom) + return; + + left = styles[prefix + '-left' + suffix]; + if (bottom != left) + return; + + // Compress + styles[prefix + suffix] = left; + delete styles[prefix + '-top' + suffix]; + delete styles[prefix + '-right' + suffix]; + delete styles[prefix + '-bottom' + suffix]; + delete styles[prefix + '-left' + suffix]; + }; + + function canCompress(key) { + var value = styles[key], i; + + if (!value || value.indexOf(' ') < 0) + return; + + value = value.split(' '); + i = value.length; + while (i--) { + if (value[i] !== value[0]) + return false; + } + + styles[key] = value[0]; + + return true; + }; + + function compress2(target, a, b, c) { + if (!canCompress(a)) + return; + + if (!canCompress(b)) + return; + + if (!canCompress(c)) + return; + + // Compress + styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c]; + delete styles[a]; + delete styles[b]; + delete styles[c]; + }; + + // Encodes the specified string by replacing all \" \' ; : with _<num> + function encode(str) { + isEncoded = true; + + return encodingLookup[str]; + }; + + // Decodes the specified string by replacing all _<num> with it's original value \" \' etc + // It will also decode the \" \' if keep_slashes is set to fale or omitted + function decode(str, keep_slashes) { + if (isEncoded) { + str = str.replace(/\uFEFF[0-9]/g, function(str) { + return encodingLookup[str]; + }); + } + + if (!keep_slashes) + str = str.replace(/\\([\'\";:])/g, "$1"); + + return str; + } + + if (css) { + // Encode \" \' % and ; and : inside strings so they don't interfere with the style parsing + css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, function(str) { + return str.replace(/[;:]/g, encode); + }); + + // Parse styles + while (matches = styleRegExp.exec(css)) { + name = matches[1].replace(trimRightRegExp, '').toLowerCase(); + value = matches[2].replace(trimRightRegExp, ''); + + if (name && value.length > 0) { + // Opera will produce 700 instead of bold in their style values + if (name === 'font-weight' && value === '700') + value = 'bold'; + else if (name === 'color' || name === 'background-color') // Lowercase colors like RED + value = value.toLowerCase(); + + // Convert RGB colors to HEX + value = value.replace(rgbRegExp, toHex); + + // Convert URLs and force them into url('value') format + value = value.replace(urlOrStrRegExp, function(match, url, url2, url3, str, str2) { + str = str || str2; + + if (str) { + str = decode(str); + + // Force strings into single quote format + return "'" + str.replace(/\'/g, "\\'") + "'"; + } + + url = decode(url || url2 || url3); + + // Convert the URL to relative/absolute depending on config + if (urlConverter) + url = urlConverter.call(urlConverterScope, url, 'style'); + + // Output new URL format + return "url('" + url.replace(/\'/g, "\\'") + "')"; + }); + + styles[name] = isEncoded ? decode(value, true) : value; + } + + styleRegExp.lastIndex = matches.index + matches[0].length; + } + + // Compress the styles to reduce it's size for example IE will expand styles + compress("border", ""); + compress("border", "-width"); + compress("border", "-color"); + compress("border", "-style"); + compress("padding", ""); + compress("margin", ""); + compress2('border', 'border-width', 'border-style', 'border-color'); + + // Remove pointless border, IE produces these + if (styles.border === 'medium none') + delete styles.border; + } + + return styles; + }, + + serialize : function(styles, element_name) { + var css = '', name, value; + + function serializeStyles(name) { + var styleList, i, l, value; + + styleList = schema.styles[name]; + if (styleList) { + for (i = 0, l = styleList.length; i < l; i++) { + name = styleList[i]; + value = styles[name]; + + if (value !== undef && value.length > 0) + css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; + } + } + }; + + // Serialize styles according to schema + if (element_name && schema && schema.styles) { + // Serialize global styles and element specific styles + serializeStyles('*'); + serializeStyles(element_name); + } else { + // Output the styles in the order they are inside the object + for (name in styles) { + value = styles[name]; + + if (value !== undef && value.length > 0) + css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; + } + } + + return css; + } + }; +}; + +(function(tinymce) { + var transitional = {}, boolAttrMap, blockElementsMap, shortEndedElementsMap, nonEmptyElementsMap, customElementsMap = {}, + defaultWhiteSpaceElementsMap, selfClosingElementsMap, makeMap = tinymce.makeMap, each = tinymce.each; + + function split(str, delim) { + return str.split(delim || ','); + }; + + function unpack(lookup, data) { + var key, elements = {}; + + function replace(value) { + return value.replace(/[A-Z]+/g, function(key) { + return replace(lookup[key]); + }); + }; + + // Unpack lookup + for (key in lookup) { + if (lookup.hasOwnProperty(key)) + lookup[key] = replace(lookup[key]); + } + + // Unpack and parse data into object map + replace(data).replace(/#/g, '#text').replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g, function(str, name, attributes, children) { + attributes = split(attributes, '|'); + + elements[name] = { + attributes : makeMap(attributes), + attributesOrder : attributes, + children : makeMap(children, '|', {'#comment' : {}}) + } + }); + + return elements; + }; + + // Build a lookup table for block elements both lowercase and uppercase + blockElementsMap = 'h1,h2,h3,h4,h5,h6,hr,p,div,address,pre,form,table,tbody,thead,tfoot,' + + 'th,tr,td,li,ol,ul,caption,blockquote,center,dl,dt,dd,dir,fieldset,' + + 'noscript,menu,isindex,samp,header,footer,article,section,hgroup'; + blockElementsMap = makeMap(blockElementsMap, ',', makeMap(blockElementsMap.toUpperCase())); + + // This is the XHTML 1.0 transitional elements with it's attributes and children packed to reduce it's size + transitional = unpack({ + Z : 'H|K|N|O|P', + Y : 'X|form|R|Q', + ZG : 'E|span|width|align|char|charoff|valign', + X : 'p|T|div|U|W|isindex|fieldset|table', + ZF : 'E|align|char|charoff|valign', + W : 'pre|hr|blockquote|address|center|noframes', + ZE : 'abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height', + ZD : '[E][S]', + U : 'ul|ol|dl|menu|dir', + ZC : 'p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q', + T : 'h1|h2|h3|h4|h5|h6', + ZB : 'X|S|Q', + S : 'R|P', + ZA : 'a|G|J|M|O|P', + R : 'a|H|K|N|O', + Q : 'noscript|P', + P : 'ins|del|script', + O : 'input|select|textarea|label|button', + N : 'M|L', + M : 'em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym', + L : 'sub|sup', + K : 'J|I', + J : 'tt|i|b|u|s|strike', + I : 'big|small|font|basefont', + H : 'G|F', + G : 'br|span|bdo', + F : 'object|applet|img|map|iframe', + E : 'A|B|C', + D : 'accesskey|tabindex|onfocus|onblur', + C : 'onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup', + B : 'lang|xml:lang|dir', + A : 'id|class|style|title' + }, 'script[id|charset|type|language|src|defer|xml:space][]' + + 'style[B|id|type|media|title|xml:space][]' + + 'object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]' + + 'param[id|name|value|valuetype|type][]' + + 'p[E|align][#|S]' + + 'a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]' + + 'br[A|clear][]' + + 'span[E][#|S]' + + 'bdo[A|C|B][#|S]' + + 'applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]' + + 'h1[E|align][#|S]' + + 'img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]' + + 'map[B|C|A|name][X|form|Q|area]' + + 'h2[E|align][#|S]' + + 'iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]' + + 'h3[E|align][#|S]' + + 'tt[E][#|S]' + + 'i[E][#|S]' + + 'b[E][#|S]' + + 'u[E][#|S]' + + 's[E][#|S]' + + 'strike[E][#|S]' + + 'big[E][#|S]' + + 'small[E][#|S]' + + 'font[A|B|size|color|face][#|S]' + + 'basefont[id|size|color|face][]' + + 'em[E][#|S]' + + 'strong[E][#|S]' + + 'dfn[E][#|S]' + + 'code[E][#|S]' + + 'q[E|cite][#|S]' + + 'samp[E][#|S]' + + 'kbd[E][#|S]' + + 'var[E][#|S]' + + 'cite[E][#|S]' + + 'abbr[E][#|S]' + + 'acronym[E][#|S]' + + 'sub[E][#|S]' + + 'sup[E][#|S]' + + 'input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]' + + 'select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]' + + 'optgroup[E|disabled|label][option]' + + 'option[E|selected|disabled|label|value][]' + + 'textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]' + + 'label[E|for|accesskey|onfocus|onblur][#|S]' + + 'button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]' + + 'h4[E|align][#|S]' + + 'ins[E|cite|datetime][#|Y]' + + 'h5[E|align][#|S]' + + 'del[E|cite|datetime][#|Y]' + + 'h6[E|align][#|S]' + + 'div[E|align][#|Y]' + + 'ul[E|type|compact][li]' + + 'li[E|type|value][#|Y]' + + 'ol[E|type|compact|start][li]' + + 'dl[E|compact][dt|dd]' + + 'dt[E][#|S]' + + 'dd[E][#|Y]' + + 'menu[E|compact][li]' + + 'dir[E|compact][li]' + + 'pre[E|width|xml:space][#|ZA]' + + 'hr[E|align|noshade|size|width][]' + + 'blockquote[E|cite][#|Y]' + + 'address[E][#|S|p]' + + 'center[E][#|Y]' + + 'noframes[E][#|Y]' + + 'isindex[A|B|prompt][]' + + 'fieldset[E][#|legend|Y]' + + 'legend[E|accesskey|align][#|S]' + + 'table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]' + + 'caption[E|align][#|S]' + + 'col[ZG][]' + + 'colgroup[ZG][col]' + + 'thead[ZF][tr]' + + 'tr[ZF|bgcolor][th|td]' + + 'th[E|ZE][#|Y]' + + 'form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]' + + 'noscript[E][#|Y]' + + 'td[E|ZE][#|Y]' + + 'tfoot[ZF][tr]' + + 'tbody[ZF][tr]' + + 'area[E|D|shape|coords|href|nohref|alt|target][]' + + 'base[id|href|target][]' + + 'body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]' + ); + + boolAttrMap = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected,autoplay,loop,controls'); + shortEndedElementsMap = makeMap('area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,source'); + nonEmptyElementsMap = tinymce.extend(makeMap('td,th,iframe,video,audio,object'), shortEndedElementsMap); + defaultWhiteSpaceElementsMap = makeMap('pre,script,style,textarea'); + selfClosingElementsMap = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'); + + tinymce.html.Schema = function(settings) { + var self = this, elements = {}, children = {}, patternElements = [], validStyles, whiteSpaceElementsMap; + + settings = settings || {}; + + // Allow all elements and attributes if verify_html is set to false + if (settings.verify_html === false) + settings.valid_elements = '*[*]'; + + // Build styles list + if (settings.valid_styles) { + validStyles = {}; + + // Convert styles into a rule list + each(settings.valid_styles, function(value, key) { + validStyles[key] = tinymce.explode(value); + }); + } + + whiteSpaceElementsMap = settings.whitespace_elements ? makeMap(settings.whitespace_elements) : defaultWhiteSpaceElementsMap; + + // Converts a wildcard expression string to a regexp for example *a will become /.*a/. + function patternToRegExp(str) { + return new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$'); + }; + + // Parses the specified valid_elements string and adds to the current rules + // This function is a bit hard to read since it's heavily optimized for speed + function addValidElements(valid_elements) { + var ei, el, ai, al, yl, matches, element, attr, attrData, elementName, attrName, attrType, attributes, attributesOrder, + prefix, outputName, globalAttributes, globalAttributesOrder, transElement, key, childKey, value, + elementRuleRegExp = /^([#+-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/, + attrRuleRegExp = /^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/, + hasPatternsRegExp = /[*?+]/; + + if (valid_elements) { + // Split valid elements into an array with rules + valid_elements = split(valid_elements); + + if (elements['@']) { + globalAttributes = elements['@'].attributes; + globalAttributesOrder = elements['@'].attributesOrder; + } + + // Loop all rules + for (ei = 0, el = valid_elements.length; ei < el; ei++) { + // Parse element rule + matches = elementRuleRegExp.exec(valid_elements[ei]); + if (matches) { + // Setup local names for matches + prefix = matches[1]; + elementName = matches[2]; + outputName = matches[3]; + attrData = matches[4]; + + // Create new attributes and attributesOrder + attributes = {}; + attributesOrder = []; + + // Create the new element + element = { + attributes : attributes, + attributesOrder : attributesOrder + }; + + // Padd empty elements prefix + if (prefix === '#') + element.paddEmpty = true; + + // Remove empty elements prefix + if (prefix === '-') + element.removeEmpty = true; + + // Copy attributes from global rule into current rule + if (globalAttributes) { + for (key in globalAttributes) + attributes[key] = globalAttributes[key]; + + attributesOrder.push.apply(attributesOrder, globalAttributesOrder); + } + + // Attributes defined + if (attrData) { + attrData = split(attrData, '|'); + for (ai = 0, al = attrData.length; ai < al; ai++) { + matches = attrRuleRegExp.exec(attrData[ai]); + if (matches) { + attr = {}; + attrType = matches[1]; + attrName = matches[2].replace(/::/g, ':'); + prefix = matches[3]; + value = matches[4]; + + // Required + if (attrType === '!') { + element.attributesRequired = element.attributesRequired || []; + element.attributesRequired.push(attrName); + attr.required = true; + } + + // Denied from global + if (attrType === '-') { + delete attributes[attrName]; + attributesOrder.splice(tinymce.inArray(attributesOrder, attrName), 1); + continue; + } + + // Default value + if (prefix) { + // Default value + if (prefix === '=') { + element.attributesDefault = element.attributesDefault || []; + element.attributesDefault.push({name: attrName, value: value}); + attr.defaultValue = value; + } + + // Forced value + if (prefix === ':') { + element.attributesForced = element.attributesForced || []; + element.attributesForced.push({name: attrName, value: value}); + attr.forcedValue = value; + } + + // Required values + if (prefix === '<') + attr.validValues = makeMap(value, '?'); + } + + // Check for attribute patterns + if (hasPatternsRegExp.test(attrName)) { + element.attributePatterns = element.attributePatterns || []; + attr.pattern = patternToRegExp(attrName); + element.attributePatterns.push(attr); + } else { + // Add attribute to order list if it doesn't already exist + if (!attributes[attrName]) + attributesOrder.push(attrName); + + attributes[attrName] = attr; + } + } + } + } + + // Global rule, store away these for later usage + if (!globalAttributes && elementName == '@') { + globalAttributes = attributes; + globalAttributesOrder = attributesOrder; + } + + // Handle substitute elements such as b/strong + if (outputName) { + element.outputName = elementName; + elements[outputName] = element; + } + + // Add pattern or exact element + if (hasPatternsRegExp.test(elementName)) { + element.pattern = patternToRegExp(elementName); + patternElements.push(element); + } else + elements[elementName] = element; + } + } + } + }; + + function setValidElements(valid_elements) { + elements = {}; + patternElements = []; + + addValidElements(valid_elements); + + each(transitional, function(element, name) { + children[name] = element.children; + }); + }; + + // Adds custom non HTML elements to the schema + function addCustomElements(custom_elements) { + var customElementRegExp = /^(~)?(.+)$/; + + if (custom_elements) { + each(split(custom_elements), function(rule) { + var matches = customElementRegExp.exec(rule), + inline = matches[1] === '~', + cloneName = inline ? 'span' : 'div', + name = matches[2]; + + children[name] = children[cloneName]; + customElementsMap[name] = cloneName; + + // If it's not marked as inline then add it to valid block elements + if (!inline) + blockElementsMap[name] = {}; + + // Add custom elements at span/div positions + each(children, function(element, child) { + if (element[cloneName]) + element[name] = element[cloneName]; + }); + }); + } + }; + + // Adds valid children to the schema object + function addValidChildren(valid_children) { + var childRuleRegExp = /^([+\-]?)(\w+)\[([^\]]+)\]$/; + + if (valid_children) { + each(split(valid_children), function(rule) { + var matches = childRuleRegExp.exec(rule), parent, prefix; + + if (matches) { + prefix = matches[1]; + + // Add/remove items from default + if (prefix) + parent = children[matches[2]]; + else + parent = children[matches[2]] = {'#comment' : {}}; + + parent = children[matches[2]]; + + each(split(matches[3], '|'), function(child) { + if (prefix === '-') + delete parent[child]; + else + parent[child] = {}; + }); + } + }); + } + }; + + function getElementRule(name) { + var element = elements[name], i; + + // Exact match found + if (element) + return element; + + // No exact match then try the patterns + i = patternElements.length; + while (i--) { + element = patternElements[i]; + + if (element.pattern.test(name)) + return element; + } + }; + + if (!settings.valid_elements) { + // No valid elements defined then clone the elements from the transitional spec + each(transitional, function(element, name) { + elements[name] = { + attributes : element.attributes, + attributesOrder : element.attributesOrder + }; + + children[name] = element.children; + }); + + // Switch these + each(split('strong/b,em/i'), function(item) { + item = split(item, '/'); + elements[item[1]].outputName = item[0]; + }); + + // Add default alt attribute for images + elements.img.attributesDefault = [{name: 'alt', value: ''}]; + + // Remove these if they are empty by default + each(split('ol,ul,sub,sup,blockquote,span,font,a,table,tbody,tr'), function(name) { + elements[name].removeEmpty = true; + }); + + // Padd these by default + each(split('p,h1,h2,h3,h4,h5,h6,th,td,pre,div,address,caption'), function(name) { + elements[name].paddEmpty = true; + }); + } else + setValidElements(settings.valid_elements); + + addCustomElements(settings.custom_elements); + addValidChildren(settings.valid_children); + addValidElements(settings.extended_valid_elements); + + // Todo: Remove this when we fix list handling to be valid + addValidChildren('+ol[ul|ol],+ul[ul|ol]'); + + // If the user didn't allow span only allow internal spans + if (!getElementRule('span')) + addValidElements('span[!data-mce-type|*]'); + + // Delete invalid elements + if (settings.invalid_elements) { + tinymce.each(tinymce.explode(settings.invalid_elements), function(item) { + if (elements[item]) + delete elements[item]; + }); + } + + self.children = children; + + self.styles = validStyles; + + self.getBoolAttrs = function() { + return boolAttrMap; + }; + + self.getBlockElements = function() { + return blockElementsMap; + }; + + self.getShortEndedElements = function() { + return shortEndedElementsMap; + }; + + self.getSelfClosingElements = function() { + return selfClosingElementsMap; + }; + + self.getNonEmptyElements = function() { + return nonEmptyElementsMap; + }; + + self.getWhiteSpaceElements = function() { + return whiteSpaceElementsMap; + }; + + self.isValidChild = function(name, child) { + var parent = children[name]; + + return !!(parent && parent[child]); + }; + + self.getElementRule = getElementRule; + + self.getCustomElements = function() { + return customElementsMap; + }; + + self.addValidElements = addValidElements; + + self.setValidElements = setValidElements; + + self.addCustomElements = addCustomElements; + + self.addValidChildren = addValidChildren; + }; + + // Expose boolMap and blockElementMap as static properties for usage in DOMUtils + tinymce.html.Schema.boolAttrMap = boolAttrMap; + tinymce.html.Schema.blockElementsMap = blockElementsMap; +})(tinymce); + +(function(tinymce) { + tinymce.html.SaxParser = function(settings, schema) { + var self = this, noop = function() {}; + + settings = settings || {}; + self.schema = schema = schema || new tinymce.html.Schema(); + + if (settings.fix_self_closing !== false) + settings.fix_self_closing = true; + + // Add handler functions from settings and setup default handlers + tinymce.each('comment cdata text start end pi doctype'.split(' '), function(name) { + if (name) + self[name] = settings[name] || noop; + }); + + self.parse = function(html) { + var self = this, matches, index = 0, value, endRegExp, stack = [], attrList, i, text, name, isInternalElement, removeInternalElements, + shortEndedElements, fillAttrsMap, isShortEnded, validate, elementRule, isValidElement, attr, attribsValue, invalidPrefixRegExp, + validAttributesMap, validAttributePatterns, attributesRequired, attributesDefault, attributesForced, selfClosing, + tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0, decode = tinymce.html.Entities.decode, fixSelfClosing, isIE; + + function processEndTag(name) { + var pos, i; + + // Find position of parent of the same type + pos = stack.length; + while (pos--) { + if (stack[pos].name === name) + break; + } + + // Found parent + if (pos >= 0) { + // Close all the open elements + for (i = stack.length - 1; i >= pos; i--) { + name = stack[i]; + + if (name.valid) + self.end(name.name); + } + + // Remove the open elements from the stack + stack.length = pos; + } + }; + + // Precompile RegExps and map objects + tokenRegExp = new RegExp('<(?:' + + '(?:!--([\\w\\W]*?)-->)|' + // Comment + '(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|' + // CDATA + '(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE + '(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI + '(?:\\/([^>]+)>)|' + // End element + '(?:([^\\s\\/<>]+)\\s*((?:[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*)>)' + // Start element + ')', 'g'); + + attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g; + specialElements = { + 'script' : /<\/script[^>]*>/gi, + 'style' : /<\/style[^>]*>/gi, + 'noscript' : /<\/noscript[^>]*>/gi + }; + + // Setup lookup tables for empty elements and boolean attributes + shortEndedElements = schema.getShortEndedElements(); + selfClosing = schema.getSelfClosingElements(); + fillAttrsMap = schema.getBoolAttrs(); + validate = settings.validate; + removeInternalElements = settings.remove_internals; + fixSelfClosing = settings.fix_self_closing; + isIE = tinymce.isIE; + invalidPrefixRegExp = /^:/; + + while (matches = tokenRegExp.exec(html)) { + // Text + if (index < matches.index) + self.text(decode(html.substr(index, matches.index - index))); + + if (value = matches[6]) { // End element + value = value.toLowerCase(); + + // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements + if (isIE && invalidPrefixRegExp.test(value)) + value = value.substr(1); + + processEndTag(value); + } else if (value = matches[7]) { // Start element + value = value.toLowerCase(); + + // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements + if (isIE && invalidPrefixRegExp.test(value)) + value = value.substr(1); + + isShortEnded = value in shortEndedElements; + + // Is self closing tag for example an <li> after an open <li> + if (fixSelfClosing && selfClosing[value] && stack.length > 0 && stack[stack.length - 1].name === value) + processEndTag(value); + + // Validate element + if (!validate || (elementRule = schema.getElementRule(value))) { + isValidElement = true; + + // Grab attributes map and patters when validation is enabled + if (validate) { + validAttributesMap = elementRule.attributes; + validAttributePatterns = elementRule.attributePatterns; + } + + // Parse attributes + if (attribsValue = matches[8]) { + isInternalElement = attribsValue.indexOf('data-mce-type') !== -1; // Check if the element is an internal element + + // If the element has internal attributes then remove it if we are told to do so + if (isInternalElement && removeInternalElements) + isValidElement = false; + + attrList = []; + attrList.map = {}; + + attribsValue.replace(attrRegExp, function(match, name, value, val2, val3) { + var attrRule, i; + + name = name.toLowerCase(); + value = name in fillAttrsMap ? name : decode(value || val2 || val3 || ''); // Handle boolean attribute than value attribute + + // Validate name and value + if (validate && !isInternalElement && name.indexOf('data-') !== 0) { + attrRule = validAttributesMap[name]; + + // Find rule by pattern matching + if (!attrRule && validAttributePatterns) { + i = validAttributePatterns.length; + while (i--) { + attrRule = validAttributePatterns[i]; + if (attrRule.pattern.test(name)) + break; + } + + // No rule matched + if (i === -1) + attrRule = null; + } + + // No attribute rule found + if (!attrRule) + return; + + // Validate value + if (attrRule.validValues && !(value in attrRule.validValues)) + return; + } + + // Add attribute to list and map + attrList.map[name] = value; + attrList.push({ + name: name, + value: value + }); + }); + } else { + attrList = []; + attrList.map = {}; + } + + // Process attributes if validation is enabled + if (validate && !isInternalElement) { + attributesRequired = elementRule.attributesRequired; + attributesDefault = elementRule.attributesDefault; + attributesForced = elementRule.attributesForced; + + // Handle forced attributes + if (attributesForced) { + i = attributesForced.length; + while (i--) { + attr = attributesForced[i]; + name = attr.name; + attrValue = attr.value; + + if (attrValue === '{$uid}') + attrValue = 'mce_' + idCount++; + + attrList.map[name] = attrValue; + attrList.push({name: name, value: attrValue}); + } + } + + // Handle default attributes + if (attributesDefault) { + i = attributesDefault.length; + while (i--) { + attr = attributesDefault[i]; + name = attr.name; + + if (!(name in attrList.map)) { + attrValue = attr.value; + + if (attrValue === '{$uid}') + attrValue = 'mce_' + idCount++; + + attrList.map[name] = attrValue; + attrList.push({name: name, value: attrValue}); + } + } + } + + // Handle required attributes + if (attributesRequired) { + i = attributesRequired.length; + while (i--) { + if (attributesRequired[i] in attrList.map) + break; + } + + // None of the required attributes where found + if (i === -1) + isValidElement = false; + } + + // Invalidate element if it's marked as bogus + if (attrList.map['data-mce-bogus']) + isValidElement = false; + } + + if (isValidElement) + self.start(value, attrList, isShortEnded); + } else + isValidElement = false; + + // Treat script, noscript and style a bit different since they may include code that looks like elements + if (endRegExp = specialElements[value]) { + endRegExp.lastIndex = index = matches.index + matches[0].length; + + if (matches = endRegExp.exec(html)) { + if (isValidElement) + text = html.substr(index, matches.index - index); + + index = matches.index + matches[0].length; + } else { + text = html.substr(index); + index = html.length; + } + + if (isValidElement && text.length > 0) + self.text(text, true); + + if (isValidElement) + self.end(value); + + tokenRegExp.lastIndex = index; + continue; + } + + // Push value on to stack + if (!isShortEnded) { + if (!attribsValue || attribsValue.indexOf('/') != attribsValue.length - 1) + stack.push({name: value, valid: isValidElement}); + else if (isValidElement) + self.end(value); + } + } else if (value = matches[1]) { // Comment + self.comment(value); + } else if (value = matches[2]) { // CDATA + self.cdata(value); + } else if (value = matches[3]) { // DOCTYPE + self.doctype(value); + } else if (value = matches[4]) { // PI + self.pi(value, matches[5]); + } + + index = matches.index + matches[0].length; + } + + // Text + if (index < html.length) + self.text(decode(html.substr(index))); + + // Close any open elements + for (i = stack.length - 1; i >= 0; i--) { + value = stack[i]; + + if (value.valid) + self.end(value.name); + } + }; + } +})(tinymce); + +(function(tinymce) { + var whiteSpaceRegExp = /^[ \t\r\n]*$/, typeLookup = { + '#text' : 3, + '#comment' : 8, + '#cdata' : 4, + '#pi' : 7, + '#doctype' : 10, + '#document-fragment' : 11 + }; + + // Walks the tree left/right + function walk(node, root_node, prev) { + var sibling, parent, startName = prev ? 'lastChild' : 'firstChild', siblingName = prev ? 'prev' : 'next'; + + // Walk into nodes if it has a start + if (node[startName]) + return node[startName]; + + // Return the sibling if it has one + if (node !== root_node) { + sibling = node[siblingName]; + + if (sibling) + return sibling; + + // Walk up the parents to look for siblings + for (parent = node.parent; parent && parent !== root_node; parent = parent.parent) { + sibling = parent[siblingName]; + + if (sibling) + return sibling; + } + } + }; + + function Node(name, type) { + this.name = name; + this.type = type; + + if (type === 1) { + this.attributes = []; + this.attributes.map = {}; + } + } + + tinymce.extend(Node.prototype, { + replace : function(node) { + var self = this; + + if (node.parent) + node.remove(); + + self.insert(node, self); + self.remove(); + + return self; + }, + + attr : function(name, value) { + var self = this, attrs, i, undef; + + if (typeof name !== "string") { + for (i in name) + self.attr(i, name[i]); + + return self; + } + + if (attrs = self.attributes) { + if (value !== undef) { + // Remove attribute + if (value === null) { + if (name in attrs.map) { + delete attrs.map[name]; + + i = attrs.length; + while (i--) { + if (attrs[i].name === name) { + attrs = attrs.splice(i, 1); + return self; + } + } + } + + return self; + } + + // Set attribute + if (name in attrs.map) { + // Set attribute + i = attrs.length; + while (i--) { + if (attrs[i].name === name) { + attrs[i].value = value; + break; + } + } + } else + attrs.push({name: name, value: value}); + + attrs.map[name] = value; + + return self; + } else { + return attrs.map[name]; + } + } + }, + + clone : function() { + var self = this, clone = new Node(self.name, self.type), i, l, selfAttrs, selfAttr, cloneAttrs; + + // Clone element attributes + if (selfAttrs = self.attributes) { + cloneAttrs = []; + cloneAttrs.map = {}; + + for (i = 0, l = selfAttrs.length; i < l; i++) { + selfAttr = selfAttrs[i]; + + // Clone everything except id + if (selfAttr.name !== 'id') { + cloneAttrs[cloneAttrs.length] = {name: selfAttr.name, value: selfAttr.value}; + cloneAttrs.map[selfAttr.name] = selfAttr.value; + } + } + + clone.attributes = cloneAttrs; + } + + clone.value = self.value; + clone.shortEnded = self.shortEnded; + + return clone; + }, + + wrap : function(wrapper) { + var self = this; + + self.parent.insert(wrapper, self); + wrapper.append(self); + + return self; + }, + + unwrap : function() { + var self = this, node, next; + + for (node = self.firstChild; node; ) { + next = node.next; + self.insert(node, self, true); + node = next; + } + + self.remove(); + }, + + remove : function() { + var self = this, parent = self.parent, next = self.next, prev = self.prev; + + if (parent) { + if (parent.firstChild === self) { + parent.firstChild = next; + + if (next) + next.prev = null; + } else { + prev.next = next; + } + + if (parent.lastChild === self) { + parent.lastChild = prev; + + if (prev) + prev.next = null; + } else { + next.prev = prev; + } + + self.parent = self.next = self.prev = null; + } + + return self; + }, + + append : function(node) { + var self = this, last; + + if (node.parent) + node.remove(); + + last = self.lastChild; + if (last) { + last.next = node; + node.prev = last; + self.lastChild = node; + } else + self.lastChild = self.firstChild = node; + + node.parent = self; + + return node; + }, + + insert : function(node, ref_node, before) { + var parent; + + if (node.parent) + node.remove(); + + parent = ref_node.parent || this; + + if (before) { + if (ref_node === parent.firstChild) + parent.firstChild = node; + else + ref_node.prev.next = node; + + node.prev = ref_node.prev; + node.next = ref_node; + ref_node.prev = node; + } else { + if (ref_node === parent.lastChild) + parent.lastChild = node; + else + ref_node.next.prev = node; + + node.next = ref_node.next; + node.prev = ref_node; + ref_node.next = node; + } + + node.parent = parent; + + return node; + }, + + getAll : function(name) { + var self = this, node, collection = []; + + for (node = self.firstChild; node; node = walk(node, self)) { + if (node.name === name) + collection.push(node); + } + + return collection; + }, + + empty : function() { + var self = this, nodes, i, node; + + // Remove all children + if (self.firstChild) { + nodes = []; + + // Collect the children + for (node = self.firstChild; node; node = walk(node, self)) + nodes.push(node); + + // Remove the children + i = nodes.length; + while (i--) { + node = nodes[i]; + node.parent = node.firstChild = node.lastChild = node.next = node.prev = null; + } + } + + self.firstChild = self.lastChild = null; + + return self; + }, + + isEmpty : function(elements) { + var self = this, node = self.firstChild, i, name; + + if (node) { + do { + if (node.type === 1) { + // Ignore bogus elements + if (node.attributes.map['data-mce-bogus']) + continue; + + // Keep empty elements like <img /> + if (elements[node.name]) + return false; + + // Keep elements with data attributes or name attribute like <a name="1"></a> + i = node.attributes.length; + while (i--) { + name = node.attributes[i].name; + if (name === "name" || name.indexOf('data-') === 0) + return false; + } + } + + // Keep non whitespace text nodes + if ((node.type === 3 && !whiteSpaceRegExp.test(node.value))) + return false; + } while (node = walk(node, self)); + } + + return true; + }, + + walk : function(prev) { + return walk(this, null, prev); + } + }); + + tinymce.extend(Node, { + create : function(name, attrs) { + var node, attrName; + + // Create node + node = new Node(name, typeLookup[name] || 1); + + // Add attributes if needed + if (attrs) { + for (attrName in attrs) + node.attr(attrName, attrs[attrName]); + } + + return node; + } + }); + + tinymce.html.Node = Node; +})(tinymce); + +(function(tinymce) { + var Node = tinymce.html.Node; + + tinymce.html.DomParser = function(settings, schema) { + var self = this, nodeFilters = {}, attributeFilters = [], matchedNodes = {}, matchedAttributes = {}; + + settings = settings || {}; + settings.validate = "validate" in settings ? settings.validate : true; + settings.root_name = settings.root_name || 'body'; + self.schema = schema = schema || new tinymce.html.Schema(); + + function fixInvalidChildren(nodes) { + var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i, + childClone, nonEmptyElements, nonSplitableElements, sibling, nextNode; + + nonSplitableElements = tinymce.makeMap('tr,td,th,tbody,thead,tfoot,table'); + nonEmptyElements = schema.getNonEmptyElements(); + + for (ni = 0; ni < nodes.length; ni++) { + node = nodes[ni]; + + // Already removed + if (!node.parent) + continue; + + // Get list of all parent nodes until we find a valid parent to stick the child into + parents = [node]; + for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) && !nonSplitableElements[parent.name]; parent = parent.parent) + parents.push(parent); + + // Found a suitable parent + if (parent && parents.length > 1) { + // Reverse the array since it makes looping easier + parents.reverse(); + + // Clone the related parent and insert that after the moved node + newParent = currentNode = self.filterNode(parents[0].clone()); + + // Start cloning and moving children on the left side of the target node + for (i = 0; i < parents.length - 1; i++) { + if (schema.isValidChild(currentNode.name, parents[i].name)) { + tempNode = self.filterNode(parents[i].clone()); + currentNode.append(tempNode); + } else + tempNode = currentNode; + + for (childNode = parents[i].firstChild; childNode && childNode != parents[i + 1]; ) { + nextNode = childNode.next; + tempNode.append(childNode); + childNode = nextNode; + } + + currentNode = tempNode; + } + + if (!newParent.isEmpty(nonEmptyElements)) { + parent.insert(newParent, parents[0], true); + parent.insert(node, newParent); + } else { + parent.insert(node, parents[0], true); + } + + // Check if the element is empty by looking through it's contents and special treatment for <p><br /></p> + parent = parents[0]; + if (parent.isEmpty(nonEmptyElements) || parent.firstChild === parent.lastChild && parent.firstChild.name === 'br') { + parent.empty().remove(); + } + } else if (node.parent) { + // If it's an LI try to find a UL/OL for it or wrap it + if (node.name === 'li') { + sibling = node.prev; + if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) { + sibling.append(node); + continue; + } + + sibling = node.next; + if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) { + sibling.insert(node, sibling.firstChild, true); + continue; + } + + node.wrap(self.filterNode(new Node('ul', 1))); + continue; + } + + // Try wrapping the element in a DIV + if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) { + node.wrap(self.filterNode(new Node('div', 1))); + } else { + // We failed wrapping it, then remove or unwrap it + if (node.name === 'style' || node.name === 'script') + node.empty().remove(); + else + node.unwrap(); + } + } + } + }; + + self.filterNode = function(node) { + var i, name, list; + + // Run element filters + if (name in nodeFilters) { + list = matchedNodes[name]; + + if (list) + list.push(node); + else + matchedNodes[name] = [node]; + } + + // Run attribute filters + i = attributeFilters.length; + while (i--) { + name = attributeFilters[i].name; + + if (name in node.attributes.map) { + list = matchedAttributes[name]; + + if (list) + list.push(node); + else + matchedAttributes[name] = [node]; + } + } + + return node; + }; + + self.addNodeFilter = function(name, callback) { + tinymce.each(tinymce.explode(name), function(name) { + var list = nodeFilters[name]; + + if (!list) + nodeFilters[name] = list = []; + + list.push(callback); + }); + }; + + self.addAttributeFilter = function(name, callback) { + tinymce.each(tinymce.explode(name), function(name) { + var i; + + for (i = 0; i < attributeFilters.length; i++) { + if (attributeFilters[i].name === name) { + attributeFilters[i].callbacks.push(callback); + return; + } + } + + attributeFilters.push({name: name, callbacks: [callback]}); + }); + }; + + self.parse = function(html, args) { + var parser, rootNode, node, nodes, i, l, fi, fl, list, name, validate, + blockElements, startWhiteSpaceRegExp, invalidChildren = [], + endWhiteSpaceRegExp, allWhiteSpaceRegExp, whiteSpaceElements, children, nonEmptyElements, rootBlockName; + + args = args || {}; + matchedNodes = {}; + matchedAttributes = {}; + blockElements = tinymce.extend(tinymce.makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements()); + nonEmptyElements = schema.getNonEmptyElements(); + children = schema.children; + validate = settings.validate; + rootBlockName = "forced_root_block" in args ? args.forced_root_block : settings.forced_root_block; + + whiteSpaceElements = schema.getWhiteSpaceElements(); + startWhiteSpaceRegExp = /^[ \t\r\n]+/; + endWhiteSpaceRegExp = /[ \t\r\n]+$/; + allWhiteSpaceRegExp = /[ \t\r\n]+/g; + + function addRootBlocks() { + var node = rootNode.firstChild, next, rootBlockNode; + + while (node) { + next = node.next; + + if (node.type == 3 || (node.type == 1 && node.name !== 'p' && !blockElements[node.name] && !node.attr('data-mce-type'))) { + if (!rootBlockNode) { + // Create a new root block element + rootBlockNode = createNode(rootBlockName, 1); + rootNode.insert(rootBlockNode, node); + rootBlockNode.append(node); + } else + rootBlockNode.append(node); + } else { + rootBlockNode = null; + } + + node = next; + }; + }; + + function createNode(name, type) { + var node = new Node(name, type), list; + + if (name in nodeFilters) { + list = matchedNodes[name]; + + if (list) + list.push(node); + else + matchedNodes[name] = [node]; + } + + return node; + }; + + function removeWhitespaceBefore(node) { + var textNode, textVal, sibling; + + for (textNode = node.prev; textNode && textNode.type === 3; ) { + textVal = textNode.value.replace(endWhiteSpaceRegExp, ''); + + if (textVal.length > 0) { + textNode.value = textVal; + textNode = textNode.prev; + } else { + sibling = textNode.prev; + textNode.remove(); + textNode = sibling; + } + } + }; + + parser = new tinymce.html.SaxParser({ + validate : validate, + fix_self_closing : !validate, // Let the DOM parser handle <li> in <li> or <p> in <p> for better results + + cdata: function(text) { + node.append(createNode('#cdata', 4)).value = text; + }, + + text: function(text, raw) { + var textNode; + + // Trim all redundant whitespace on non white space elements + if (!whiteSpaceElements[node.name]) { + text = text.replace(allWhiteSpaceRegExp, ' '); + + if (node.lastChild && blockElements[node.lastChild.name]) + text = text.replace(startWhiteSpaceRegExp, ''); + } + + // Do we need to create the node + if (text.length !== 0) { + textNode = createNode('#text', 3); + textNode.raw = !!raw; + node.append(textNode).value = text; + } + }, + + comment: function(text) { + node.append(createNode('#comment', 8)).value = text; + }, + + pi: function(name, text) { + node.append(createNode(name, 7)).value = text; + removeWhitespaceBefore(node); + }, + + doctype: function(text) { + var newNode; + + newNode = node.append(createNode('#doctype', 10)); + newNode.value = text; + removeWhitespaceBefore(node); + }, + + start: function(name, attrs, empty) { + var newNode, attrFiltersLen, elementRule, textNode, attrName, text, sibling, parent; + + elementRule = validate ? schema.getElementRule(name) : {}; + if (elementRule) { + newNode = createNode(elementRule.outputName || name, 1); + newNode.attributes = attrs; + newNode.shortEnded = empty; + + node.append(newNode); + + // Check if node is valid child of the parent node is the child is + // unknown we don't collect it since it's probably a custom element + parent = children[node.name]; + if (parent && children[newNode.name] && !parent[newNode.name]) + invalidChildren.push(newNode); + + attrFiltersLen = attributeFilters.length; + while (attrFiltersLen--) { + attrName = attributeFilters[attrFiltersLen].name; + + if (attrName in attrs.map) { + list = matchedAttributes[attrName]; + + if (list) + list.push(newNode); + else + matchedAttributes[attrName] = [newNode]; + } + } + + // Trim whitespace before block + if (blockElements[name]) + removeWhitespaceBefore(newNode); + + // Change current node if the element wasn't empty i.e not <br /> or <img /> + if (!empty) + node = newNode; + } + }, + + end: function(name) { + var textNode, elementRule, text, sibling, tempNode; + + elementRule = validate ? schema.getElementRule(name) : {}; + if (elementRule) { + if (blockElements[name]) { + if (!whiteSpaceElements[node.name]) { + // Trim whitespace at beginning of block + for (textNode = node.firstChild; textNode && textNode.type === 3; ) { + text = textNode.value.replace(startWhiteSpaceRegExp, ''); + + if (text.length > 0) { + textNode.value = text; + textNode = textNode.next; + } else { + sibling = textNode.next; + textNode.remove(); + textNode = sibling; + } + } + + // Trim whitespace at end of block + for (textNode = node.lastChild; textNode && textNode.type === 3; ) { + text = textNode.value.replace(endWhiteSpaceRegExp, ''); + + if (text.length > 0) { + textNode.value = text; + textNode = textNode.prev; + } else { + sibling = textNode.prev; + textNode.remove(); + textNode = sibling; + } + } + } + + // Trim start white space + textNode = node.prev; + if (textNode && textNode.type === 3) { + text = textNode.value.replace(startWhiteSpaceRegExp, ''); + + if (text.length > 0) + textNode.value = text; + else + textNode.remove(); + } + } + + // Handle empty nodes + if (elementRule.removeEmpty || elementRule.paddEmpty) { + if (node.isEmpty(nonEmptyElements)) { + if (elementRule.paddEmpty) + node.empty().append(new Node('#text', '3')).value = '\u00a0'; + else { + // Leave nodes that have a name like <a name="name"> + if (!node.attributes.map.name) { + tempNode = node.parent; + node.empty().remove(); + node = tempNode; + return; + } + } + } + } + + node = node.parent; + } + } + }, schema); + + rootNode = node = new Node(args.context || settings.root_name, 11); + + parser.parse(html); + + // Fix invalid children or report invalid children in a contextual parsing + if (validate && invalidChildren.length) { + if (!args.context) + fixInvalidChildren(invalidChildren); + else + args.invalid = true; + } + + // Wrap nodes in the root into block elements if the root is body + if (rootBlockName && rootNode.name == 'body') + addRootBlocks(); + + // Run filters only when the contents is valid + if (!args.invalid) { + // Run node filters + for (name in matchedNodes) { + list = nodeFilters[name]; + nodes = matchedNodes[name]; + + // Remove already removed children + fi = nodes.length; + while (fi--) { + if (!nodes[fi].parent) + nodes.splice(fi, 1); + } + + for (i = 0, l = list.length; i < l; i++) + list[i](nodes, name, args); + } + + // Run attribute filters + for (i = 0, l = attributeFilters.length; i < l; i++) { + list = attributeFilters[i]; + + if (list.name in matchedAttributes) { + nodes = matchedAttributes[list.name]; + + // Remove already removed children + fi = nodes.length; + while (fi--) { + if (!nodes[fi].parent) + nodes.splice(fi, 1); + } + + for (fi = 0, fl = list.callbacks.length; fi < fl; fi++) + list.callbacks[fi](nodes, list.name, args); + } + } + } + + return rootNode; + }; + + // Remove <br> at end of block elements Gecko and WebKit injects BR elements to + // make it possible to place the caret inside empty blocks. This logic tries to remove + // these elements and keep br elements that where intended to be there intact + if (settings.remove_trailing_brs) { + self.addNodeFilter('br', function(nodes, name) { + var i, l = nodes.length, node, blockElements = schema.getBlockElements(), + nonEmptyElements = schema.getNonEmptyElements(), parent, prev, prevName; + + // Remove brs from body element as well + blockElements.body = 1; + + // Must loop forwards since it will otherwise remove all brs in <p>a<br><br><br></p> + for (i = 0; i < l; i++) { + node = nodes[i]; + parent = node.parent; + + if (blockElements[node.parent.name] && node === parent.lastChild) { + // Loop all nodes to the right of the current node and check for other BR elements + // excluding bookmarks since they are invisible + prev = node.prev; + while (prev) { + prevName = prev.name; + + // Ignore bookmarks + if (prevName !== "span" || prev.attr('data-mce-type') !== 'bookmark') { + // Found a non BR element + if (prevName !== "br") + break; + + // Found another br it's a <br><br> structure then don't remove anything + if (prevName === 'br') { + node = null; + break; + } + } + + prev = prev.prev; + } + + if (node) { + node.remove(); + + // Is the parent to be considered empty after we removed the BR + if (parent.isEmpty(nonEmptyElements)) { + elementRule = schema.getElementRule(parent.name); + + // Remove or padd the element depending on schema rule + if (elementRule) { + if (elementRule.removeEmpty) + parent.remove(); + else if (elementRule.paddEmpty) + parent.empty().append(new tinymce.html.Node('#text', 3)).value = '\u00a0'; + } + } + } + } + } + }); + } + } +})(tinymce); + +tinymce.html.Writer = function(settings) { + var html = [], indent, indentBefore, indentAfter, encode, htmlOutput; + + settings = settings || {}; + indent = settings.indent; + indentBefore = tinymce.makeMap(settings.indent_before || ''); + indentAfter = tinymce.makeMap(settings.indent_after || ''); + encode = tinymce.html.Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities); + htmlOutput = settings.element_format == "html"; + + return { + start: function(name, attrs, empty) { + var i, l, attr, value; + + if (indent && indentBefore[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + } + + html.push('<', name); + + if (attrs) { + for (i = 0, l = attrs.length; i < l; i++) { + attr = attrs[i]; + html.push(' ', attr.name, '="', encode(attr.value, true), '"'); + } + } + + if (!empty || htmlOutput) + html[html.length] = '>'; + else + html[html.length] = ' />'; + + if (empty && indent && indentAfter[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + } + }, + + end: function(name) { + var value; + + /*if (indent && indentBefore[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + }*/ + + html.push('</', name, '>'); + + if (indent && indentAfter[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + } + }, + + text: function(text, raw) { + if (text.length > 0) + html[html.length] = raw ? text : encode(text); + }, + + cdata: function(text) { + html.push('<![CDATA[', text, ']]>'); + }, + + comment: function(text) { + html.push('<!--', text, '-->'); + }, + + pi: function(name, text) { + if (text) + html.push('<?', name, ' ', text, '?>'); + else + html.push('<?', name, '?>'); + + if (indent) + html.push('\n'); + }, + + doctype: function(text) { + html.push('<!DOCTYPE', text, '>', indent ? '\n' : ''); + }, + + reset: function() { + html.length = 0; + }, + + getContent: function() { + return html.join('').replace(/\n$/, ''); + } + }; +}; + +(function(tinymce) { + tinymce.html.Serializer = function(settings, schema) { + var self = this, writer = new tinymce.html.Writer(settings); + + settings = settings || {}; + settings.validate = "validate" in settings ? settings.validate : true; + + self.schema = schema = schema || new tinymce.html.Schema(); + self.writer = writer; + + self.serialize = function(node) { + var handlers, validate; + + validate = settings.validate; + + handlers = { + // #text + 3: function(node, raw) { + writer.text(node.value, node.raw); + }, + + // #comment + 8: function(node) { + writer.comment(node.value); + }, + + // Processing instruction + 7: function(node) { + writer.pi(node.name, node.value); + }, + + // Doctype + 10: function(node) { + writer.doctype(node.value); + }, + + // CDATA + 4: function(node) { + writer.cdata(node.value); + }, + + // Document fragment + 11: function(node) { + if ((node = node.firstChild)) { + do { + walk(node); + } while (node = node.next); + } + } + }; + + writer.reset(); + + function walk(node) { + var handler = handlers[node.type], name, isEmpty, attrs, attrName, attrValue, sortedAttrs, i, l, elementRule; + + if (!handler) { + name = node.name; + isEmpty = node.shortEnded; + attrs = node.attributes; + + // Sort attributes + if (validate && attrs && attrs.length > 1) { + sortedAttrs = []; + sortedAttrs.map = {}; + + elementRule = schema.getElementRule(node.name); + for (i = 0, l = elementRule.attributesOrder.length; i < l; i++) { + attrName = elementRule.attributesOrder[i]; + + if (attrName in attrs.map) { + attrValue = attrs.map[attrName]; + sortedAttrs.map[attrName] = attrValue; + sortedAttrs.push({name: attrName, value: attrValue}); + } + } + + for (i = 0, l = attrs.length; i < l; i++) { + attrName = attrs[i].name; + + if (!(attrName in sortedAttrs.map)) { + attrValue = attrs.map[attrName]; + sortedAttrs.map[attrName] = attrValue; + sortedAttrs.push({name: attrName, value: attrValue}); + } + } + + attrs = sortedAttrs; + } + + writer.start(node.name, attrs, isEmpty); + + if (!isEmpty) { + if ((node = node.firstChild)) { + do { + walk(node); + } while (node = node.next); + } + + writer.end(name); + } + } else + handler(node); + } + + // Serialize element and treat all non elements as fragments + if (node.type == 1 && !settings.inner) + walk(node); + else + handlers[11](node); + + return writer.getContent(); + }; + } +})(tinymce); + +(function(tinymce) { + // Shorten names + var each = tinymce.each, + is = tinymce.is, + isWebKit = tinymce.isWebKit, + isIE = tinymce.isIE, + Entities = tinymce.html.Entities, + simpleSelectorRe = /^([a-z0-9],?)+$/i, + blockElementsMap = tinymce.html.Schema.blockElementsMap, + whiteSpaceRegExp = /^[ \t\r\n]*$/; + + tinymce.create('tinymce.dom.DOMUtils', { + doc : null, + root : null, + files : null, + pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/, + props : { + "for" : "htmlFor", + "class" : "className", + className : "className", + checked : "checked", + disabled : "disabled", + maxlength : "maxLength", + readonly : "readOnly", + selected : "selected", + value : "value", + id : "id", + name : "name", + type : "type" + }, + + DOMUtils : function(d, s) { + var t = this, globalStyle, name; + + t.doc = d; + t.win = window; + t.files = {}; + t.cssFlicker = false; + t.counter = 0; + t.stdMode = !tinymce.isIE || d.documentMode >= 8; + t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat" || t.stdMode; + t.hasOuterHTML = "outerHTML" in d.createElement("a"); + + t.settings = s = tinymce.extend({ + keep_values : false, + hex_colors : 1 + }, s); + + t.schema = s.schema; + t.styles = new tinymce.html.Styles({ + url_converter : s.url_converter, + url_converter_scope : s.url_converter_scope + }, s.schema); + + // Fix IE6SP2 flicker and check it failed for pre SP2 + if (tinymce.isIE6) { + try { + d.execCommand('BackgroundImageCache', false, true); + } catch (e) { + t.cssFlicker = true; + } + } + + if (isIE && s.schema) { + // Add missing HTML 4/5 elements to IE + ('abbr article aside audio canvas ' + + 'details figcaption figure footer ' + + 'header hgroup mark menu meter nav ' + + 'output progress section summary ' + + 'time video').replace(/\w+/g, function(name) { + d.createElement(name); + }); + + // Create all custom elements + for (name in s.schema.getCustomElements()) { + d.createElement(name); + } + } + + tinymce.addUnload(t.destroy, t); + }, + + getRoot : function() { + var t = this, s = t.settings; + + return (s && t.get(s.root_element)) || t.doc.body; + }, + + getViewPort : function(w) { + var d, b; + + w = !w ? this.win : w; + d = w.document; + b = this.boxModel ? d.documentElement : d.body; + + // Returns viewport size excluding scrollbars + return { + x : w.pageXOffset || b.scrollLeft, + y : w.pageYOffset || b.scrollTop, + w : w.innerWidth || b.clientWidth, + h : w.innerHeight || b.clientHeight + }; + }, + + getRect : function(e) { + var p, t = this, sr; + + e = t.get(e); + p = t.getPos(e); + sr = t.getSize(e); + + return { + x : p.x, + y : p.y, + w : sr.w, + h : sr.h + }; + }, + + getSize : function(e) { + var t = this, w, h; + + e = t.get(e); + w = t.getStyle(e, 'width'); + h = t.getStyle(e, 'height'); + + // Non pixel value, then force offset/clientWidth + if (w.indexOf('px') === -1) + w = 0; + + // Non pixel value, then force offset/clientWidth + if (h.indexOf('px') === -1) + h = 0; + + return { + w : parseInt(w) || e.offsetWidth || e.clientWidth, + h : parseInt(h) || e.offsetHeight || e.clientHeight + }; + }, + + getParent : function(n, f, r) { + return this.getParents(n, f, r, false); + }, + + getParents : function(n, f, r, c) { + var t = this, na, se = t.settings, o = []; + + n = t.get(n); + c = c === undefined; + + if (se.strict_root) + r = r || t.getRoot(); + + // Wrap node name as func + if (is(f, 'string')) { + na = f; + + if (f === '*') { + f = function(n) {return n.nodeType == 1;}; + } else { + f = function(n) { + return t.is(n, na); + }; + } + } + + while (n) { + if (n == r || !n.nodeType || n.nodeType === 9) + break; + + if (!f || f(n)) { + if (c) + o.push(n); + else + return n; + } + + n = n.parentNode; + } + + return c ? o : null; + }, + + get : function(e) { + var n; + + if (e && this.doc && typeof(e) == 'string') { + n = e; + e = this.doc.getElementById(e); + + // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick + if (e && e.id !== n) + return this.doc.getElementsByName(n)[1]; + } + + return e; + }, + + getNext : function(node, selector) { + return this._findSib(node, selector, 'nextSibling'); + }, + + getPrev : function(node, selector) { + return this._findSib(node, selector, 'previousSibling'); + }, + + + select : function(pa, s) { + var t = this; + + return tinymce.dom.Sizzle(pa, t.get(s) || t.get(t.settings.root_element) || t.doc, []); + }, + + is : function(n, selector) { + var i; + + // If it isn't an array then try to do some simple selectors instead of Sizzle for to boost performance + if (n.length === undefined) { + // Simple all selector + if (selector === '*') + return n.nodeType == 1; + + // Simple selector just elements + if (simpleSelectorRe.test(selector)) { + selector = selector.toLowerCase().split(/,/); + n = n.nodeName.toLowerCase(); + + for (i = selector.length - 1; i >= 0; i--) { + if (selector[i] == n) + return true; + } + + return false; + } + } + + return tinymce.dom.Sizzle.matches(selector, n.nodeType ? [n] : n).length > 0; + }, + + + add : function(p, n, a, h, c) { + var t = this; + + return this.run(p, function(p) { + var e, k; + + e = is(n, 'string') ? t.doc.createElement(n) : n; + t.setAttribs(e, a); + + if (h) { + if (h.nodeType) + e.appendChild(h); + else + t.setHTML(e, h); + } + + return !c ? p.appendChild(e) : e; + }); + }, + + create : function(n, a, h) { + return this.add(this.doc.createElement(n), n, a, h, 1); + }, + + createHTML : function(n, a, h) { + var o = '', t = this, k; + + o += '<' + n; + + for (k in a) { + if (a.hasOwnProperty(k)) + o += ' ' + k + '="' + t.encode(a[k]) + '"'; + } + + // A call to tinymce.is doesn't work for some odd reason on IE9 possible bug inside their JS runtime + if (typeof(h) != "undefined") + return o + '>' + h + '</' + n + '>'; + + return o + ' />'; + }, + + remove : function(node, keep_children) { + return this.run(node, function(node) { + var child, parent = node.parentNode; + + if (!parent) + return null; + + if (keep_children) { + while (child = node.firstChild) { + // IE 8 will crash if you don't remove completely empty text nodes + if (!tinymce.isIE || child.nodeType !== 3 || child.nodeValue) + parent.insertBefore(child, node); + else + node.removeChild(child); + } + } + + return parent.removeChild(node); + }); + }, + + setStyle : function(n, na, v) { + var t = this; + + return t.run(n, function(e) { + var s, i; + + s = e.style; + + // Camelcase it, if needed + na = na.replace(/-(\D)/g, function(a, b){ + return b.toUpperCase(); + }); + + // Default px suffix on these + if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v))) + v += 'px'; + + switch (na) { + case 'opacity': + // IE specific opacity + if (isIE) { + s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")"; + + if (!n.currentStyle || !n.currentStyle.hasLayout) + s.display = 'inline-block'; + } + + // Fix for older browsers + s[na] = s['-moz-opacity'] = s['-khtml-opacity'] = v || ''; + break; + + case 'float': + isIE ? s.styleFloat = v : s.cssFloat = v; + break; + + default: + s[na] = v || ''; + } + + // Force update of the style data + if (t.settings.update_styles) + t.setAttrib(e, 'data-mce-style'); + }); + }, + + getStyle : function(n, na, c) { + n = this.get(n); + + if (!n) + return; + + // Gecko + if (this.doc.defaultView && c) { + // Remove camelcase + na = na.replace(/[A-Z]/g, function(a){ + return '-' + a; + }); + + try { + return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na); + } catch (ex) { + // Old safari might fail + return null; + } + } + + // Camelcase it, if needed + na = na.replace(/-(\D)/g, function(a, b){ + return b.toUpperCase(); + }); + + if (na == 'float') + na = isIE ? 'styleFloat' : 'cssFloat'; + + // IE & Opera + if (n.currentStyle && c) + return n.currentStyle[na]; + + return n.style ? n.style[na] : undefined; + }, + + setStyles : function(e, o) { + var t = this, s = t.settings, ol; + + ol = s.update_styles; + s.update_styles = 0; + + each(o, function(v, n) { + t.setStyle(e, n, v); + }); + + // Update style info + s.update_styles = ol; + if (s.update_styles) + t.setAttrib(e, s.cssText); + }, + + removeAllAttribs: function(e) { + return this.run(e, function(e) { + var i, attrs = e.attributes; + for (i = attrs.length - 1; i >= 0; i--) { + e.removeAttributeNode(attrs.item(i)); + } + }); + }, + + setAttrib : function(e, n, v) { + var t = this; + + // Whats the point + if (!e || !n) + return; + + // Strict XML mode + if (t.settings.strict) + n = n.toLowerCase(); + + return this.run(e, function(e) { + var s = t.settings; + + switch (n) { + case "style": + if (!is(v, 'string')) { + each(v, function(v, n) { + t.setStyle(e, n, v); + }); + + return; + } + + // No mce_style for elements with these since they might get resized by the user + if (s.keep_values) { + if (v && !t._isRes(v)) + e.setAttribute('data-mce-style', v, 2); + else + e.removeAttribute('data-mce-style', 2); + } + + e.style.cssText = v; + break; + + case "class": + e.className = v || ''; // Fix IE null bug + break; + + case "src": + case "href": + if (s.keep_values) { + if (s.url_converter) + v = s.url_converter.call(s.url_converter_scope || t, v, n, e); + + t.setAttrib(e, 'data-mce-' + n, v, 2); + } + + break; + + case "shape": + e.setAttribute('data-mce-style', v); + break; + } + + if (is(v) && v !== null && v.length !== 0) + e.setAttribute(n, '' + v, 2); + else + e.removeAttribute(n, 2); + }); + }, + + setAttribs : function(e, o) { + var t = this; + + return this.run(e, function(e) { + each(o, function(v, n) { + t.setAttrib(e, n, v); + }); + }); + }, + + getAttrib : function(e, n, dv) { + var v, t = this, undef; + + e = t.get(e); + + if (!e || e.nodeType !== 1) + return dv === undef ? false : dv; + + if (!is(dv)) + dv = ''; + + // Try the mce variant for these + if (/^(src|href|style|coords|shape)$/.test(n)) { + v = e.getAttribute("data-mce-" + n); + + if (v) + return v; + } + + if (isIE && t.props[n]) { + v = e[t.props[n]]; + v = v && v.nodeValue ? v.nodeValue : v; + } + + if (!v) + v = e.getAttribute(n, 2); + + // Check boolean attribs + if (/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(n)) { + if (e[t.props[n]] === true && v === '') + return n; + + return v ? n : ''; + } + + // Inner input elements will override attributes on form elements + if (e.nodeName === "FORM" && e.getAttributeNode(n)) + return e.getAttributeNode(n).nodeValue; + + if (n === 'style') { + v = v || e.style.cssText; + + if (v) { + v = t.serializeStyle(t.parseStyle(v), e.nodeName); + + if (t.settings.keep_values && !t._isRes(v)) + e.setAttribute('data-mce-style', v); + } + } + + // Remove Apple and WebKit stuff + if (isWebKit && n === "class" && v) + v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, ''); + + // Handle IE issues + if (isIE) { + switch (n) { + case 'rowspan': + case 'colspan': + // IE returns 1 as default value + if (v === 1) + v = ''; + + break; + + case 'size': + // IE returns +0 as default value for size + if (v === '+0' || v === 20 || v === 0) + v = ''; + + break; + + case 'width': + case 'height': + case 'vspace': + case 'checked': + case 'disabled': + case 'readonly': + if (v === 0) + v = ''; + + break; + + case 'hspace': + // IE returns -1 as default value + if (v === -1) + v = ''; + + break; + + case 'maxlength': + case 'tabindex': + // IE returns default value + if (v === 32768 || v === 2147483647 || v === '32768') + v = ''; + + break; + + case 'multiple': + case 'compact': + case 'noshade': + case 'nowrap': + if (v === 65535) + return n; + + return dv; + + case 'shape': + v = v.toLowerCase(); + break; + + default: + // IE has odd anonymous function for event attributes + if (n.indexOf('on') === 0 && v) + v = tinymce._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/, '$1', '' + v); + } + } + + return (v !== undef && v !== null && v !== '') ? '' + v : dv; + }, + + getPos : function(n, ro) { + var t = this, x = 0, y = 0, e, d = t.doc, r; + + n = t.get(n); + ro = ro || d.body; + + if (n) { + // Use getBoundingClientRect if it exists since it's faster than looping offset nodes + if (n.getBoundingClientRect) { + n = n.getBoundingClientRect(); + e = t.boxModel ? d.documentElement : d.body; + + // Add scroll offsets from documentElement or body since IE with the wrong box model will use d.body and so do WebKit + // Also remove the body/documentelement clientTop/clientLeft on IE 6, 7 since they offset the position + x = n.left + (d.documentElement.scrollLeft || d.body.scrollLeft) - e.clientTop; + y = n.top + (d.documentElement.scrollTop || d.body.scrollTop) - e.clientLeft; + + return {x : x, y : y}; + } + + r = n; + while (r && r != ro && r.nodeType) { + x += r.offsetLeft || 0; + y += r.offsetTop || 0; + r = r.offsetParent; + } + + r = n.parentNode; + while (r && r != ro && r.nodeType) { + x -= r.scrollLeft || 0; + y -= r.scrollTop || 0; + r = r.parentNode; + } + } + + return {x : x, y : y}; + }, + + parseStyle : function(st) { + return this.styles.parse(st); + }, + + serializeStyle : function(o, name) { + return this.styles.serialize(o, name); + }, + + loadCSS : function(u) { + var t = this, d = t.doc, head; + + if (!u) + u = ''; + + head = t.select('head')[0]; + + each(u.split(','), function(u) { + var link; + + if (t.files[u]) + return; + + t.files[u] = true; + link = t.create('link', {rel : 'stylesheet', href : tinymce._addVer(u)}); + + // IE 8 has a bug where dynamically loading stylesheets would produce a 1 item remaining bug + // This fix seems to resolve that issue by realcing the document ones a stylesheet finishes loading + // It's ugly but it seems to work fine. + if (isIE && d.documentMode && d.recalc) { + link.onload = function() { + if (d.recalc) + d.recalc(); + + link.onload = null; + }; + } + + head.appendChild(link); + }); + }, + + addClass : function(e, c) { + return this.run(e, function(e) { + var o; + + if (!c) + return 0; + + if (this.hasClass(e, c)) + return e.className; + + o = this.removeClass(e, c); + + return e.className = (o != '' ? (o + ' ') : '') + c; + }); + }, + + removeClass : function(e, c) { + var t = this, re; + + return t.run(e, function(e) { + var v; + + if (t.hasClass(e, c)) { + if (!re) + re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g"); + + v = e.className.replace(re, ' '); + v = tinymce.trim(v != ' ' ? v : ''); + + e.className = v; + + // Empty class attr + if (!v) { + e.removeAttribute('class'); + e.removeAttribute('className'); + } + + return v; + } + + return e.className; + }); + }, + + hasClass : function(n, c) { + n = this.get(n); + + if (!n || !c) + return false; + + return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1; + }, + + show : function(e) { + return this.setStyle(e, 'display', 'block'); + }, + + hide : function(e) { + return this.setStyle(e, 'display', 'none'); + }, + + isHidden : function(e) { + e = this.get(e); + + return !e || e.style.display == 'none' || this.getStyle(e, 'display') == 'none'; + }, + + uniqueId : function(p) { + return (!p ? 'mce_' : p) + (this.counter++); + }, + + setHTML : function(element, html) { + var self = this; + + return self.run(element, function(element) { + if (isIE) { + // Remove all child nodes, IE keeps empty text nodes in DOM + while (element.firstChild) + element.removeChild(element.firstChild); + + try { + // IE will remove comments from the beginning + // unless you padd the contents with something + element.innerHTML = '<br />' + html; + element.removeChild(element.firstChild); + } catch (ex) { + // IE sometimes produces an unknown runtime error on innerHTML if it's an block element within a block element for example a div inside a p + // This seems to fix this problem + + // Create new div with HTML contents and a BR infront to keep comments + element = self.create('div'); + element.innerHTML = '<br />' + html; + + // Add all children from div to target + each (element.childNodes, function(node, i) { + // Skip br element + if (i) + element.appendChild(node); + }); + } + } else + element.innerHTML = html; + + return html; + }); + }, + + getOuterHTML : function(elm) { + var doc, self = this; + + elm = self.get(elm); + + if (!elm) + return null; + + if (elm.nodeType === 1 && self.hasOuterHTML) + return elm.outerHTML; + + doc = (elm.ownerDocument || self.doc).createElement("body"); + doc.appendChild(elm.cloneNode(true)); + + return doc.innerHTML; + }, + + setOuterHTML : function(e, h, d) { + var t = this; + + function setHTML(e, h, d) { + var n, tp; + + tp = d.createElement("body"); + tp.innerHTML = h; + + n = tp.lastChild; + while (n) { + t.insertAfter(n.cloneNode(true), e); + n = n.previousSibling; + } + + t.remove(e); + }; + + return this.run(e, function(e) { + e = t.get(e); + + // Only set HTML on elements + if (e.nodeType == 1) { + d = d || e.ownerDocument || t.doc; + + if (isIE) { + try { + // Try outerHTML for IE it sometimes produces an unknown runtime error + if (isIE && e.nodeType == 1) + e.outerHTML = h; + else + setHTML(e, h, d); + } catch (ex) { + // Fix for unknown runtime error + setHTML(e, h, d); + } + } else + setHTML(e, h, d); + } + }); + }, + + decode : Entities.decode, + + encode : Entities.encodeAllRaw, + + insertAfter : function(node, reference_node) { + reference_node = this.get(reference_node); + + return this.run(node, function(node) { + var parent, nextSibling; + + parent = reference_node.parentNode; + nextSibling = reference_node.nextSibling; + + if (nextSibling) + parent.insertBefore(node, nextSibling); + else + parent.appendChild(node); + + return node; + }); + }, + + isBlock : function(node) { + var type = node.nodeType; + + // If it's a node then check the type and use the nodeName + if (type) + return !!(type === 1 && blockElementsMap[node.nodeName]); + + return !!blockElementsMap[node]; + }, + + replace : function(n, o, k) { + var t = this; + + if (is(o, 'array')) + n = n.cloneNode(true); + + return t.run(o, function(o) { + if (k) { + each(tinymce.grep(o.childNodes), function(c) { + n.appendChild(c); + }); + } + + return o.parentNode.replaceChild(n, o); + }); + }, + + rename : function(elm, name) { + var t = this, newElm; + + if (elm.nodeName != name.toUpperCase()) { + // Rename block element + newElm = t.create(name); + + // Copy attribs to new block + each(t.getAttribs(elm), function(attr_node) { + t.setAttrib(newElm, attr_node.nodeName, t.getAttrib(elm, attr_node.nodeName)); + }); + + // Replace block + t.replace(newElm, elm, 1); + } + + return newElm || elm; + }, + + findCommonAncestor : function(a, b) { + var ps = a, pe; + + while (ps) { + pe = b; + + while (pe && ps != pe) + pe = pe.parentNode; + + if (ps == pe) + break; + + ps = ps.parentNode; + } + + if (!ps && a.ownerDocument) + return a.ownerDocument.documentElement; + + return ps; + }, + + toHex : function(s) { + var c = /^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s); + + function hex(s) { + s = parseInt(s).toString(16); + + return s.length > 1 ? s : '0' + s; // 0 -> 00 + }; + + if (c) { + s = '#' + hex(c[1]) + hex(c[2]) + hex(c[3]); + + return s; + } + + return s; + }, + + getClasses : function() { + var t = this, cl = [], i, lo = {}, f = t.settings.class_filter, ov; + + if (t.classes) + return t.classes; + + function addClasses(s) { + // IE style imports + each(s.imports, function(r) { + addClasses(r); + }); + + each(s.cssRules || s.rules, function(r) { + // Real type or fake it on IE + switch (r.type || 1) { + // Rule + case 1: + if (r.selectorText) { + each(r.selectorText.split(','), function(v) { + v = v.replace(/^\s*|\s*$|^\s\./g, ""); + + // Is internal or it doesn't contain a class + if (/\.mce/.test(v) || !/\.[\w\-]+$/.test(v)) + return; + + // Remove everything but class name + ov = v; + v = tinymce._replace(/.*\.([a-z0-9_\-]+).*/i, '$1', v); + + // Filter classes + if (f && !(v = f(v, ov))) + return; + + if (!lo[v]) { + cl.push({'class' : v}); + lo[v] = 1; + } + }); + } + break; + + // Import + case 3: + addClasses(r.styleSheet); + break; + } + }); + }; + + try { + each(t.doc.styleSheets, addClasses); + } catch (ex) { + // Ignore + } + + if (cl.length > 0) + t.classes = cl; + + return cl; + }, + + run : function(e, f, s) { + var t = this, o; + + if (t.doc && typeof(e) === 'string') + e = t.get(e); + + if (!e) + return false; + + s = s || this; + if (!e.nodeType && (e.length || e.length === 0)) { + o = []; + + each(e, function(e, i) { + if (e) { + if (typeof(e) == 'string') + e = t.doc.getElementById(e); + + o.push(f.call(s, e, i)); + } + }); + + return o; + } + + return f.call(s, e); + }, + + getAttribs : function(n) { + var o; + + n = this.get(n); + + if (!n) + return []; + + if (isIE) { + o = []; + + // Object will throw exception in IE + if (n.nodeName == 'OBJECT') + return n.attributes; + + // IE doesn't keep the selected attribute if you clone option elements + if (n.nodeName === 'OPTION' && this.getAttrib(n, 'selected')) + o.push({specified : 1, nodeName : 'selected'}); + + // It's crazy that this is faster in IE but it's because it returns all attributes all the time + n.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi, '').replace(/[\w:\-]+/gi, function(a) { + o.push({specified : 1, nodeName : a}); + }); + + return o; + } + + return n.attributes; + }, + + isEmpty : function(node, elements) { + var self = this, i, attributes, type, walker, name, parentNode; + + node = node.firstChild; + if (node) { + walker = new tinymce.dom.TreeWalker(node); + elements = elements || self.schema ? self.schema.getNonEmptyElements() : null; + + do { + type = node.nodeType; + + if (type === 1) { + // Ignore bogus elements + if (node.getAttribute('data-mce-bogus')) + continue; + + // Keep empty elements like <img /> + name = node.nodeName.toLowerCase(); + if (elements && elements[name]) { + // Ignore single BR elements in blocks like <p><br /></p> + parentNode = node.parentNode; + if (name === 'br' && self.isBlock(parentNode) && parentNode.firstChild === node && parentNode.lastChild === node) { + continue; + } + + return false; + } + + // Keep elements with data-bookmark attributes or name attribute like <a name="1"></a> + attributes = self.getAttribs(node); + i = node.attributes.length; + while (i--) { + name = node.attributes[i].nodeName; + if (name === "name" || name === 'data-mce-bookmark') + return false; + } + } + + // Keep non whitespace text nodes + if ((type === 3 && !whiteSpaceRegExp.test(node.nodeValue))) + return false; + } while (node = walker.next()); + } + + return true; + }, + + destroy : function(s) { + var t = this; + + if (t.events) + t.events.destroy(); + + t.win = t.doc = t.root = t.events = null; + + // Manual destroy then remove unload handler + if (!s) + tinymce.removeUnload(t.destroy); + }, + + createRng : function() { + var d = this.doc; + + return d.createRange ? d.createRange() : new tinymce.dom.Range(this); + }, + + nodeIndex : function(node, normalized) { + var idx = 0, lastNodeType, lastNode, nodeType; + + if (node) { + for (lastNodeType = node.nodeType, node = node.previousSibling, lastNode = node; node; node = node.previousSibling) { + nodeType = node.nodeType; + + // Normalize text nodes + if (normalized && nodeType == 3) { + if (nodeType == lastNodeType || !node.nodeValue.length) + continue; + } + idx++; + lastNodeType = nodeType; + } + } + + return idx; + }, + + split : function(pe, e, re) { + var t = this, r = t.createRng(), bef, aft, pa; + + // W3C valid browsers tend to leave empty nodes to the left/right side of the contents, this makes sense + // but we don't want that in our code since it serves no purpose for the end user + // For example if this is chopped: + // <p>text 1<span><b>CHOP</b></span>text 2</p> + // would produce: + // <p>text 1<span></span></p><b>CHOP</b><p><span></span>text 2</p> + // this function will then trim of empty edges and produce: + // <p>text 1</p><b>CHOP</b><p>text 2</p> + function trim(node) { + var i, children = node.childNodes, type = node.nodeType; + + if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark') + return; + + for (i = children.length - 1; i >= 0; i--) + trim(children[i]); + + if (type != 9) { + // Keep non whitespace text nodes + if (type == 3 && node.nodeValue.length > 0) { + // If parent element isn't a block or there isn't any useful contents for example "<p> </p>" + if (!t.isBlock(node.parentNode) || tinymce.trim(node.nodeValue).length > 0) + return; + } else if (type == 1) { + // If the only child is a bookmark then move it up + children = node.childNodes; + if (children.length == 1 && children[0] && children[0].nodeType == 1 && children[0].getAttribute('data-mce-type') == 'bookmark') + node.parentNode.insertBefore(children[0], node); + + // Keep non empty elements or img, hr etc + if (children.length || /^(br|hr|input|img)$/i.test(node.nodeName)) + return; + } + + t.remove(node); + } + + return node; + }; + + if (pe && e) { + // Get before chunk + r.setStart(pe.parentNode, t.nodeIndex(pe)); + r.setEnd(e.parentNode, t.nodeIndex(e)); + bef = r.extractContents(); + + // Get after chunk + r = t.createRng(); + r.setStart(e.parentNode, t.nodeIndex(e) + 1); + r.setEnd(pe.parentNode, t.nodeIndex(pe) + 1); + aft = r.extractContents(); + + // Insert before chunk + pa = pe.parentNode; + pa.insertBefore(trim(bef), pe); + + // Insert middle chunk + if (re) + pa.replaceChild(re, e); + else + pa.insertBefore(e, pe); + + // Insert after chunk + pa.insertBefore(trim(aft), pe); + t.remove(pe); + + return re || e; + } + }, + + bind : function(target, name, func, scope) { + var t = this; + + if (!t.events) + t.events = new tinymce.dom.EventUtils(); + + return t.events.add(target, name, func, scope || this); + }, + + unbind : function(target, name, func) { + var t = this; + + if (!t.events) + t.events = new tinymce.dom.EventUtils(); + + return t.events.remove(target, name, func); + }, + + + _findSib : function(node, selector, name) { + var t = this, f = selector; + + if (node) { + // If expression make a function of it using is + if (is(f, 'string')) { + f = function(node) { + return t.is(node, selector); + }; + } + + // Loop all siblings + for (node = node[name]; node; node = node[name]) { + if (f(node)) + return node; + } + } + + return null; + }, + + _isRes : function(c) { + // Is live resizble element + return /^(top|left|bottom|right|width|height)/i.test(c) || /;\s*(top|left|bottom|right|width|height)/i.test(c); + } + + /* + walk : function(n, f, s) { + var d = this.doc, w; + + if (d.createTreeWalker) { + w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false); + + while ((n = w.nextNode()) != null) + f.call(s || this, n); + } else + tinymce.walk(n, f, 'childNodes', s); + } + */ + + /* + toRGB : function(s) { + var c = /^\s*?#([0-9A-F]{2})([0-9A-F]{1,2})([0-9A-F]{2})?\s*?$/.exec(s); + + if (c) { + // #FFF -> #FFFFFF + if (!is(c[3])) + c[3] = c[2] = c[1]; + + return "rgb(" + parseInt(c[1], 16) + "," + parseInt(c[2], 16) + "," + parseInt(c[3], 16) + ")"; + } + + return s; + } + */ + }); + + tinymce.DOM = new tinymce.dom.DOMUtils(document, {process_html : 0}); +})(tinymce); + +(function(ns) { + // Range constructor + function Range(dom) { + var t = this, + doc = dom.doc, + EXTRACT = 0, + CLONE = 1, + DELETE = 2, + TRUE = true, + FALSE = false, + START_OFFSET = 'startOffset', + START_CONTAINER = 'startContainer', + END_CONTAINER = 'endContainer', + END_OFFSET = 'endOffset', + extend = tinymce.extend, + nodeIndex = dom.nodeIndex; + + extend(t, { + // Inital states + startContainer : doc, + startOffset : 0, + endContainer : doc, + endOffset : 0, + collapsed : TRUE, + commonAncestorContainer : doc, + + // Range constants + START_TO_START : 0, + START_TO_END : 1, + END_TO_END : 2, + END_TO_START : 3, + + // Public methods + setStart : setStart, + setEnd : setEnd, + setStartBefore : setStartBefore, + setStartAfter : setStartAfter, + setEndBefore : setEndBefore, + setEndAfter : setEndAfter, + collapse : collapse, + selectNode : selectNode, + selectNodeContents : selectNodeContents, + compareBoundaryPoints : compareBoundaryPoints, + deleteContents : deleteContents, + extractContents : extractContents, + cloneContents : cloneContents, + insertNode : insertNode, + surroundContents : surroundContents, + cloneRange : cloneRange + }); + + function setStart(n, o) { + _setEndPoint(TRUE, n, o); + }; + + function setEnd(n, o) { + _setEndPoint(FALSE, n, o); + }; + + function setStartBefore(n) { + setStart(n.parentNode, nodeIndex(n)); + }; + + function setStartAfter(n) { + setStart(n.parentNode, nodeIndex(n) + 1); + }; + + function setEndBefore(n) { + setEnd(n.parentNode, nodeIndex(n)); + }; + + function setEndAfter(n) { + setEnd(n.parentNode, nodeIndex(n) + 1); + }; + + function collapse(ts) { + if (ts) { + t[END_CONTAINER] = t[START_CONTAINER]; + t[END_OFFSET] = t[START_OFFSET]; + } else { + t[START_CONTAINER] = t[END_CONTAINER]; + t[START_OFFSET] = t[END_OFFSET]; + } + + t.collapsed = TRUE; + }; + + function selectNode(n) { + setStartBefore(n); + setEndAfter(n); + }; + + function selectNodeContents(n) { + setStart(n, 0); + setEnd(n, n.nodeType === 1 ? n.childNodes.length : n.nodeValue.length); + }; + + function compareBoundaryPoints(h, r) { + var sc = t[START_CONTAINER], so = t[START_OFFSET], ec = t[END_CONTAINER], eo = t[END_OFFSET], + rsc = r.startContainer, rso = r.startOffset, rec = r.endContainer, reo = r.endOffset; + + // Check START_TO_START + if (h === 0) + return _compareBoundaryPoints(sc, so, rsc, rso); + + // Check START_TO_END + if (h === 1) + return _compareBoundaryPoints(ec, eo, rsc, rso); + + // Check END_TO_END + if (h === 2) + return _compareBoundaryPoints(ec, eo, rec, reo); + + // Check END_TO_START + if (h === 3) + return _compareBoundaryPoints(sc, so, rec, reo); + }; + + function deleteContents() { + _traverse(DELETE); + }; + + function extractContents() { + return _traverse(EXTRACT); + }; + + function cloneContents() { + return _traverse(CLONE); + }; + + function insertNode(n) { + var startContainer = this[START_CONTAINER], + startOffset = this[START_OFFSET], nn, o; + + // Node is TEXT_NODE or CDATA + if ((startContainer.nodeType === 3 || startContainer.nodeType === 4) && startContainer.nodeValue) { + if (!startOffset) { + // At the start of text + startContainer.parentNode.insertBefore(n, startContainer); + } else if (startOffset >= startContainer.nodeValue.length) { + // At the end of text + dom.insertAfter(n, startContainer); + } else { + // Middle, need to split + nn = startContainer.splitText(startOffset); + startContainer.parentNode.insertBefore(n, nn); + } + } else { + // Insert element node + if (startContainer.childNodes.length > 0) + o = startContainer.childNodes[startOffset]; + + if (o) + startContainer.insertBefore(n, o); + else + startContainer.appendChild(n); + } + }; + + function surroundContents(n) { + var f = t.extractContents(); + + t.insertNode(n); + n.appendChild(f); + t.selectNode(n); + }; + + function cloneRange() { + return extend(new Range(dom), { + startContainer : t[START_CONTAINER], + startOffset : t[START_OFFSET], + endContainer : t[END_CONTAINER], + endOffset : t[END_OFFSET], + collapsed : t.collapsed, + commonAncestorContainer : t.commonAncestorContainer + }); + }; + + // Private methods + + function _getSelectedNode(container, offset) { + var child; + + if (container.nodeType == 3 /* TEXT_NODE */) + return container; + + if (offset < 0) + return container; + + child = container.firstChild; + while (child && offset > 0) { + --offset; + child = child.nextSibling; + } + + if (child) + return child; + + return container; + }; + + function _isCollapsed() { + return (t[START_CONTAINER] == t[END_CONTAINER] && t[START_OFFSET] == t[END_OFFSET]); + }; + + function _compareBoundaryPoints(containerA, offsetA, containerB, offsetB) { + var c, offsetC, n, cmnRoot, childA, childB; + + // In the first case the boundary-points have the same container. A is before B + // if its offset is less than the offset of B, A is equal to B if its offset is + // equal to the offset of B, and A is after B if its offset is greater than the + // offset of B. + if (containerA == containerB) { + if (offsetA == offsetB) + return 0; // equal + + if (offsetA < offsetB) + return -1; // before + + return 1; // after + } + + // In the second case a child node C of the container of A is an ancestor + // container of B. In this case, A is before B if the offset of A is less than or + // equal to the index of the child node C and A is after B otherwise. + c = containerB; + while (c && c.parentNode != containerA) + c = c.parentNode; + + if (c) { + offsetC = 0; + n = containerA.firstChild; + + while (n != c && offsetC < offsetA) { + offsetC++; + n = n.nextSibling; + } + + if (offsetA <= offsetC) + return -1; // before + + return 1; // after + } + + // In the third case a child node C of the container of B is an ancestor container + // of A. In this case, A is before B if the index of the child node C is less than + // the offset of B and A is after B otherwise. + c = containerA; + while (c && c.parentNode != containerB) { + c = c.parentNode; + } + + if (c) { + offsetC = 0; + n = containerB.firstChild; + + while (n != c && offsetC < offsetB) { + offsetC++; + n = n.nextSibling; + } + + if (offsetC < offsetB) + return -1; // before + + return 1; // after + } + + // In the fourth case, none of three other cases hold: the containers of A and B + // are siblings or descendants of sibling nodes. In this case, A is before B if + // the container of A is before the container of B in a pre-order traversal of the + // Ranges' context tree and A is after B otherwise. + cmnRoot = dom.findCommonAncestor(containerA, containerB); + childA = containerA; + + while (childA && childA.parentNode != cmnRoot) + childA = childA.parentNode; + + if (!childA) + childA = cmnRoot; + + childB = containerB; + while (childB && childB.parentNode != cmnRoot) + childB = childB.parentNode; + + if (!childB) + childB = cmnRoot; + + if (childA == childB) + return 0; // equal + + n = cmnRoot.firstChild; + while (n) { + if (n == childA) + return -1; // before + + if (n == childB) + return 1; // after + + n = n.nextSibling; + } + }; + + function _setEndPoint(st, n, o) { + var ec, sc; + + if (st) { + t[START_CONTAINER] = n; + t[START_OFFSET] = o; + } else { + t[END_CONTAINER] = n; + t[END_OFFSET] = o; + } + + // If one boundary-point of a Range is set to have a root container + // other than the current one for the Range, the Range is collapsed to + // the new position. This enforces the restriction that both boundary- + // points of a Range must have the same root container. + ec = t[END_CONTAINER]; + while (ec.parentNode) + ec = ec.parentNode; + + sc = t[START_CONTAINER]; + while (sc.parentNode) + sc = sc.parentNode; + + if (sc == ec) { + // The start position of a Range is guaranteed to never be after the + // end position. To enforce this restriction, if the start is set to + // be at a position after the end, the Range is collapsed to that + // position. + if (_compareBoundaryPoints(t[START_CONTAINER], t[START_OFFSET], t[END_CONTAINER], t[END_OFFSET]) > 0) + t.collapse(st); + } else + t.collapse(st); + + t.collapsed = _isCollapsed(); + t.commonAncestorContainer = dom.findCommonAncestor(t[START_CONTAINER], t[END_CONTAINER]); + }; + + function _traverse(how) { + var c, endContainerDepth = 0, startContainerDepth = 0, p, depthDiff, startNode, endNode, sp, ep; + + if (t[START_CONTAINER] == t[END_CONTAINER]) + return _traverseSameContainer(how); + + for (c = t[END_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) { + if (p == t[START_CONTAINER]) + return _traverseCommonStartContainer(c, how); + + ++endContainerDepth; + } + + for (c = t[START_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) { + if (p == t[END_CONTAINER]) + return _traverseCommonEndContainer(c, how); + + ++startContainerDepth; + } + + depthDiff = startContainerDepth - endContainerDepth; + + startNode = t[START_CONTAINER]; + while (depthDiff > 0) { + startNode = startNode.parentNode; + depthDiff--; + } + + endNode = t[END_CONTAINER]; + while (depthDiff < 0) { + endNode = endNode.parentNode; + depthDiff++; + } + + // ascend the ancestor hierarchy until we have a common parent. + for (sp = startNode.parentNode, ep = endNode.parentNode; sp != ep; sp = sp.parentNode, ep = ep.parentNode) { + startNode = sp; + endNode = ep; + } + + return _traverseCommonAncestors(startNode, endNode, how); + }; + + function _traverseSameContainer(how) { + var frag, s, sub, n, cnt, sibling, xferNode; + + if (how != DELETE) + frag = doc.createDocumentFragment(); + + // If selection is empty, just return the fragment + if (t[START_OFFSET] == t[END_OFFSET]) + return frag; + + // Text node needs special case handling + if (t[START_CONTAINER].nodeType == 3 /* TEXT_NODE */) { + // get the substring + s = t[START_CONTAINER].nodeValue; + sub = s.substring(t[START_OFFSET], t[END_OFFSET]); + + // set the original text node to its new value + if (how != CLONE) { + t[START_CONTAINER].deleteData(t[START_OFFSET], t[END_OFFSET] - t[START_OFFSET]); + + // Nothing is partially selected, so collapse to start point + t.collapse(TRUE); + } + + if (how == DELETE) + return; + + frag.appendChild(doc.createTextNode(sub)); + return frag; + } + + // Copy nodes between the start/end offsets. + n = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]); + cnt = t[END_OFFSET] - t[START_OFFSET]; + + while (cnt > 0) { + sibling = n.nextSibling; + xferNode = _traverseFullySelected(n, how); + + if (frag) + frag.appendChild( xferNode ); + + --cnt; + n = sibling; + } + + // Nothing is partially selected, so collapse to start point + if (how != CLONE) + t.collapse(TRUE); + + return frag; + }; + + function _traverseCommonStartContainer(endAncestor, how) { + var frag, n, endIdx, cnt, sibling, xferNode; + + if (how != DELETE) + frag = doc.createDocumentFragment(); + + n = _traverseRightBoundary(endAncestor, how); + + if (frag) + frag.appendChild(n); + + endIdx = nodeIndex(endAncestor); + cnt = endIdx - t[START_OFFSET]; + + if (cnt <= 0) { + // Collapse to just before the endAncestor, which + // is partially selected. + if (how != CLONE) { + t.setEndBefore(endAncestor); + t.collapse(FALSE); + } + + return frag; + } + + n = endAncestor.previousSibling; + while (cnt > 0) { + sibling = n.previousSibling; + xferNode = _traverseFullySelected(n, how); + + if (frag) + frag.insertBefore(xferNode, frag.firstChild); + + --cnt; + n = sibling; + } + + // Collapse to just before the endAncestor, which + // is partially selected. + if (how != CLONE) { + t.setEndBefore(endAncestor); + t.collapse(FALSE); + } + + return frag; + }; + + function _traverseCommonEndContainer(startAncestor, how) { + var frag, startIdx, n, cnt, sibling, xferNode; + + if (how != DELETE) + frag = doc.createDocumentFragment(); + + n = _traverseLeftBoundary(startAncestor, how); + if (frag) + frag.appendChild(n); + + startIdx = nodeIndex(startAncestor); + ++startIdx; // Because we already traversed it + + cnt = t[END_OFFSET] - startIdx; + n = startAncestor.nextSibling; + while (cnt > 0) { + sibling = n.nextSibling; + xferNode = _traverseFullySelected(n, how); + + if (frag) + frag.appendChild(xferNode); + + --cnt; + n = sibling; + } + + if (how != CLONE) { + t.setStartAfter(startAncestor); + t.collapse(TRUE); + } + + return frag; + }; + + function _traverseCommonAncestors(startAncestor, endAncestor, how) { + var n, frag, commonParent, startOffset, endOffset, cnt, sibling, nextSibling; + + if (how != DELETE) + frag = doc.createDocumentFragment(); + + n = _traverseLeftBoundary(startAncestor, how); + if (frag) + frag.appendChild(n); + + commonParent = startAncestor.parentNode; + startOffset = nodeIndex(startAncestor); + endOffset = nodeIndex(endAncestor); + ++startOffset; + + cnt = endOffset - startOffset; + sibling = startAncestor.nextSibling; + + while (cnt > 0) { + nextSibling = sibling.nextSibling; + n = _traverseFullySelected(sibling, how); + + if (frag) + frag.appendChild(n); + + sibling = nextSibling; + --cnt; + } + + n = _traverseRightBoundary(endAncestor, how); + + if (frag) + frag.appendChild(n); + + if (how != CLONE) { + t.setStartAfter(startAncestor); + t.collapse(TRUE); + } + + return frag; + }; + + function _traverseRightBoundary(root, how) { + var next = _getSelectedNode(t[END_CONTAINER], t[END_OFFSET] - 1), parent, clonedParent, prevSibling, clonedChild, clonedGrandParent, isFullySelected = next != t[END_CONTAINER]; + + if (next == root) + return _traverseNode(next, isFullySelected, FALSE, how); + + parent = next.parentNode; + clonedParent = _traverseNode(parent, FALSE, FALSE, how); + + while (parent) { + while (next) { + prevSibling = next.previousSibling; + clonedChild = _traverseNode(next, isFullySelected, FALSE, how); + + if (how != DELETE) + clonedParent.insertBefore(clonedChild, clonedParent.firstChild); + + isFullySelected = TRUE; + next = prevSibling; + } + + if (parent == root) + return clonedParent; + + next = parent.previousSibling; + parent = parent.parentNode; + + clonedGrandParent = _traverseNode(parent, FALSE, FALSE, how); + + if (how != DELETE) + clonedGrandParent.appendChild(clonedParent); + + clonedParent = clonedGrandParent; + } + }; + + function _traverseLeftBoundary(root, how) { + var next = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]), isFullySelected = next != t[START_CONTAINER], parent, clonedParent, nextSibling, clonedChild, clonedGrandParent; + + if (next == root) + return _traverseNode(next, isFullySelected, TRUE, how); + + parent = next.parentNode; + clonedParent = _traverseNode(parent, FALSE, TRUE, how); + + while (parent) { + while (next) { + nextSibling = next.nextSibling; + clonedChild = _traverseNode(next, isFullySelected, TRUE, how); + + if (how != DELETE) + clonedParent.appendChild(clonedChild); + + isFullySelected = TRUE; + next = nextSibling; + } + + if (parent == root) + return clonedParent; + + next = parent.nextSibling; + parent = parent.parentNode; + + clonedGrandParent = _traverseNode(parent, FALSE, TRUE, how); + + if (how != DELETE) + clonedGrandParent.appendChild(clonedParent); + + clonedParent = clonedGrandParent; + } + }; + + function _traverseNode(n, isFullySelected, isLeft, how) { + var txtValue, newNodeValue, oldNodeValue, offset, newNode; + + if (isFullySelected) + return _traverseFullySelected(n, how); + + if (n.nodeType == 3 /* TEXT_NODE */) { + txtValue = n.nodeValue; + + if (isLeft) { + offset = t[START_OFFSET]; + newNodeValue = txtValue.substring(offset); + oldNodeValue = txtValue.substring(0, offset); + } else { + offset = t[END_OFFSET]; + newNodeValue = txtValue.substring(0, offset); + oldNodeValue = txtValue.substring(offset); + } + + if (how != CLONE) + n.nodeValue = oldNodeValue; + + if (how == DELETE) + return; + + newNode = n.cloneNode(FALSE); + newNode.nodeValue = newNodeValue; + + return newNode; + } + + if (how == DELETE) + return; + + return n.cloneNode(FALSE); + }; + + function _traverseFullySelected(n, how) { + if (how != DELETE) + return how == CLONE ? n.cloneNode(TRUE) : n; + + n.parentNode.removeChild(n); + }; + }; + + ns.Range = Range; +})(tinymce.dom); + +(function() { + function Selection(selection) { + var self = this, dom = selection.dom, TRUE = true, FALSE = false; + + function getPosition(rng, start) { + var checkRng, startIndex = 0, endIndex, inside, + children, child, offset, index, position = -1, parent; + + // Setup test range, collapse it and get the parent + checkRng = rng.duplicate(); + checkRng.collapse(start); + parent = checkRng.parentElement(); + + // Check if the selection is within the right document + if (parent.ownerDocument !== selection.dom.doc) + return; + + // IE will report non editable elements as it's parent so look for an editable one + while (parent.contentEditable === "false") { + parent = parent.parentNode; + } + + // If parent doesn't have any children then return that we are inside the element + if (!parent.hasChildNodes()) { + return {node : parent, inside : 1}; + } + + // Setup node list and endIndex + children = parent.children; + endIndex = children.length - 1; + + // Perform a binary search for the position + while (startIndex <= endIndex) { + index = Math.floor((startIndex + endIndex) / 2); + + // Move selection to node and compare the ranges + child = children[index]; + checkRng.moveToElementText(child); + position = checkRng.compareEndPoints(start ? 'StartToStart' : 'EndToEnd', rng); + + // Before/after or an exact match + if (position > 0) { + endIndex = index - 1; + } else if (position < 0) { + startIndex = index + 1; + } else { + return {node : child}; + } + } + + // Check if child position is before or we didn't find a position + if (position < 0) { + // No element child was found use the parent element and the offset inside that + if (!child) { + checkRng.moveToElementText(parent); + checkRng.collapse(true); + child = parent; + inside = true; + } else + checkRng.collapse(false); + + checkRng.setEndPoint(start ? 'EndToStart' : 'EndToEnd', rng); + + // Fix for edge case: <div style="width: 100px; height:100px;"><table>..</table>ab|c</div> + if (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) > 0) { + checkRng = rng.duplicate(); + checkRng.collapse(start); + + offset = -1; + while (parent == checkRng.parentElement()) { + if (checkRng.move('character', -1) == 0) + break; + + offset++; + } + } + + offset = offset || checkRng.text.replace('\r\n', ' ').length; + } else { + // Child position is after the selection endpoint + checkRng.collapse(true); + checkRng.setEndPoint(start ? 'StartToStart' : 'StartToEnd', rng); + + // Get the length of the text to find where the endpoint is relative to it's container + offset = checkRng.text.replace('\r\n', ' ').length; + } + + return {node : child, position : position, offset : offset, inside : inside}; + }; + + // Returns a W3C DOM compatible range object by using the IE Range API + function getRange() { + var ieRange = selection.getRng(), domRange = dom.createRng(), element, collapsed, tmpRange, element2, bookmark, fail; + + // If selection is outside the current document just return an empty range + element = ieRange.item ? ieRange.item(0) : ieRange.parentElement(); + if (element.ownerDocument != dom.doc) + return domRange; + + collapsed = selection.isCollapsed(); + + // Handle control selection + if (ieRange.item) { + domRange.setStart(element.parentNode, dom.nodeIndex(element)); + domRange.setEnd(domRange.startContainer, domRange.startOffset + 1); + + return domRange; + } + + function findEndPoint(start) { + var endPoint = getPosition(ieRange, start), container, offset, textNodeOffset = 0, sibling, undef, nodeValue; + + container = endPoint.node; + offset = endPoint.offset; + + if (endPoint.inside && !container.hasChildNodes()) { + domRange[start ? 'setStart' : 'setEnd'](container, 0); + return; + } + + if (offset === undef) { + domRange[start ? 'setStartBefore' : 'setEndAfter'](container); + return; + } + + if (endPoint.position < 0) { + sibling = endPoint.inside ? container.firstChild : container.nextSibling; + + if (!sibling) { + domRange[start ? 'setStartAfter' : 'setEndAfter'](container); + return; + } + + if (!offset) { + if (sibling.nodeType == 3) + domRange[start ? 'setStart' : 'setEnd'](sibling, 0); + else + domRange[start ? 'setStartBefore' : 'setEndBefore'](sibling); + + return; + } + + // Find the text node and offset + while (sibling) { + nodeValue = sibling.nodeValue; + textNodeOffset += nodeValue.length; + + // We are at or passed the position we where looking for + if (textNodeOffset >= offset) { + container = sibling; + textNodeOffset -= offset; + textNodeOffset = nodeValue.length - textNodeOffset; + break; + } + + sibling = sibling.nextSibling; + } + } else { + // Find the text node and offset + sibling = container.previousSibling; + + if (!sibling) + return domRange[start ? 'setStartBefore' : 'setEndBefore'](container); + + // If there isn't any text to loop then use the first position + if (!offset) { + if (container.nodeType == 3) + domRange[start ? 'setStart' : 'setEnd'](sibling, container.nodeValue.length); + else + domRange[start ? 'setStartAfter' : 'setEndAfter'](sibling); + + return; + } + + while (sibling) { + textNodeOffset += sibling.nodeValue.length; + + // We are at or passed the position we where looking for + if (textNodeOffset >= offset) { + container = sibling; + textNodeOffset -= offset; + break; + } + + sibling = sibling.previousSibling; + } + } + + domRange[start ? 'setStart' : 'setEnd'](container, textNodeOffset); + }; + + try { + // Find start point + findEndPoint(true); + + // Find end point if needed + if (!collapsed) + findEndPoint(); + } catch (ex) { + // IE has a nasty bug where text nodes might throw "invalid argument" when you + // access the nodeValue or other properties of text nodes. This seems to happend when + // text nodes are split into two nodes by a delete/backspace call. So lets detect it and try to fix it. + if (ex.number == -2147024809) { + // Get the current selection + bookmark = self.getBookmark(2); + + // Get start element + tmpRange = ieRange.duplicate(); + tmpRange.collapse(true); + element = tmpRange.parentElement(); + + // Get end element + if (!collapsed) { + tmpRange = ieRange.duplicate(); + tmpRange.collapse(false); + element2 = tmpRange.parentElement(); + element2.innerHTML = element2.innerHTML; + } + + // Remove the broken elements + element.innerHTML = element.innerHTML; + + // Restore the selection + self.moveToBookmark(bookmark); + + // Since the range has moved we need to re-get it + ieRange = selection.getRng(); + + // Find start point + findEndPoint(true); + + // Find end point if needed + if (!collapsed) + findEndPoint(); + } else + throw ex; // Throw other errors + } + + return domRange; + }; + + this.getBookmark = function(type) { + var rng = selection.getRng(), start, end, bookmark = {}; + + function getIndexes(node) { + var node, parent, root, children, i, indexes = []; + + parent = node.parentNode; + root = dom.getRoot().parentNode; + + while (parent != root) { + children = parent.children; + + i = children.length; + while (i--) { + if (node === children[i]) { + indexes.push(i); + break; + } + } + + node = parent; + parent = parent.parentNode; + } + + return indexes; + }; + + function getBookmarkEndPoint(start) { + var position; + + position = getPosition(rng, start); + if (position) { + return { + position : position.position, + offset : position.offset, + indexes : getIndexes(position.node), + inside : position.inside + }; + } + }; + + // Non ubstructive bookmark + if (type === 2) { + // Handle text selection + if (!rng.item) { + bookmark.start = getBookmarkEndPoint(true); + + if (!selection.isCollapsed()) + bookmark.end = getBookmarkEndPoint(); + } else + bookmark.start = {ctrl : true, indexes : getIndexes(rng.item(0))}; + } + + return bookmark; + }; + + this.moveToBookmark = function(bookmark) { + var rng, body = dom.doc.body; + + function resolveIndexes(indexes) { + var node, i, idx, children; + + node = dom.getRoot(); + for (i = indexes.length - 1; i >= 0; i--) { + children = node.children; + idx = indexes[i]; + + if (idx <= children.length - 1) { + node = children[idx]; + } + } + + return node; + }; + + function setBookmarkEndPoint(start) { + var endPoint = bookmark[start ? 'start' : 'end'], moveLeft, moveRng, undef; + + if (endPoint) { + moveLeft = endPoint.position > 0; + + moveRng = body.createTextRange(); + moveRng.moveToElementText(resolveIndexes(endPoint.indexes)); + + offset = endPoint.offset; + if (offset !== undef) { + moveRng.collapse(endPoint.inside || moveLeft); + moveRng.moveStart('character', moveLeft ? -offset : offset); + } else + moveRng.collapse(start); + + rng.setEndPoint(start ? 'StartToStart' : 'EndToStart', moveRng); + + if (start) + rng.collapse(true); + } + }; + + if (bookmark.start) { + if (bookmark.start.ctrl) { + rng = body.createControlRange(); + rng.addElement(resolveIndexes(bookmark.start.indexes)); + rng.select(); + } else { + rng = body.createTextRange(); + setBookmarkEndPoint(true); + setBookmarkEndPoint(); + rng.select(); + } + } + }; + + this.addRange = function(rng) { + var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, doc = selection.dom.doc, body = doc.body; + + function setEndPoint(start) { + var container, offset, marker, tmpRng, nodes; + + marker = dom.create('a'); + container = start ? startContainer : endContainer; + offset = start ? startOffset : endOffset; + tmpRng = ieRng.duplicate(); + + if (container == doc || container == doc.documentElement) { + container = body; + offset = 0; + } + + if (container.nodeType == 3) { + container.parentNode.insertBefore(marker, container); + tmpRng.moveToElementText(marker); + tmpRng.moveStart('character', offset); + dom.remove(marker); + ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng); + } else { + nodes = container.childNodes; + + if (nodes.length) { + if (offset >= nodes.length) { + dom.insertAfter(marker, nodes[nodes.length - 1]); + } else { + container.insertBefore(marker, nodes[offset]); + } + + tmpRng.moveToElementText(marker); + } else { + // Empty node selection for example <div>|</div> + marker = doc.createTextNode('\uFEFF'); + container.appendChild(marker); + tmpRng.moveToElementText(marker.parentNode); + tmpRng.collapse(TRUE); + } + + ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng); + dom.remove(marker); + } + } + + // Setup some shorter versions + startContainer = rng.startContainer; + startOffset = rng.startOffset; + endContainer = rng.endContainer; + endOffset = rng.endOffset; + ieRng = body.createTextRange(); + + // If single element selection then try making a control selection out of it + if (startContainer == endContainer && startContainer.nodeType == 1 && startOffset == endOffset - 1) { + if (startOffset == endOffset - 1) { + try { + ctrlRng = body.createControlRange(); + ctrlRng.addElement(startContainer.childNodes[startOffset]); + ctrlRng.select(); + return; + } catch (ex) { + // Ignore + } + } + } + + // Set start/end point of selection + setEndPoint(true); + setEndPoint(); + + // Select the new range and scroll it into view + ieRng.select(); + }; + + // Expose range method + this.getRangeAt = getRange; + }; + + // Expose the selection object + tinymce.dom.TridentSelection = Selection; +})(); + + +/* + * Sizzle CSS Selector Engine - v1.0 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function(){ + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function(selector, context, results, seed) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var parts = [], m, set, checkSet, extra, prune = true, contextXML = Sizzle.isXML(context), + soFar = selector, ret, cur, pop, i; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec(""); + m = chunker.exec(soFar); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray(set); + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function(results){ + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort(sortOrder); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[i-1] ) { + results.splice(i--, 1); + } + } + } + } + + return results; +}; + +Sizzle.matches = function(expr, set){ + return Sizzle(expr, null, null, set); +}; + +Sizzle.find = function(expr, context, isXML){ + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var type = Expr.order[i], match; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice(1,1); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace(/\\/g, ""); + set = Expr.find[ type ]( match, context, isXML ); + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = context.getElementsByTagName("*"); + } + + return {set: set, expr: expr}; +}; + +Sizzle.filter = function(expr, set, inplace, not){ + var old = expr, result = [], curLoop = set, match, anyFound, + isXMLFilter = set && set[0] && Sizzle.isXML(set[0]); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var filter = Expr.filter[ type ], found, item, left = match[1]; + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + } else { + curLoop[i] = false; + } + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + leftMatch: {}, + attrMap: { + "class": "className", + "for": "htmlFor" + }, + attrHandle: { + href: function(elem){ + return elem.getAttribute("href"); + } + }, + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !/\W/.test(part), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + ">": function(checkSet, part){ + var isPartStr = typeof part === "string", + elem, i = 0, l = checkSet.length; + + if ( isPartStr && !/\W/.test(part) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + "": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck, nodeCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); + }, + "~": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck, nodeCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); + } + }, + find: { + ID: function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? [m] : []; + } + }, + NAME: function(match, context){ + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], results = context.getElementsByName(match[1]); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + TAG: function(match, context){ + return context.getElementsByTagName(match[1]); + } + }, + preFilter: { + CLASS: function(match, curLoop, inplace, result, not, isXML){ + match = " " + match[1].replace(/\\/g, "") + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + ID: function(match){ + return match[1].replace(/\\/g, ""); + }, + TAG: function(match, curLoop){ + return match[1].toLowerCase(); + }, + CHILD: function(match){ + if ( match[1] === "nth" ) { + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + ATTR: function(match, curLoop, inplace, result, not, isXML){ + var name = match[1].replace(/\\/g, ""); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + PSEUDO: function(match, curLoop, inplace, result, not){ + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + if ( !inplace ) { + result.push.apply( result, ret ); + } + return false; + } + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + POS: function(match){ + match.unshift( true ); + return match; + } + }, + filters: { + enabled: function(elem){ + return elem.disabled === false && elem.type !== "hidden"; + }, + disabled: function(elem){ + return elem.disabled === true; + }, + checked: function(elem){ + return elem.checked === true; + }, + selected: function(elem){ + // Accessing this property makes selected-by-default + // options in Safari work properly + elem.parentNode.selectedIndex; + return elem.selected === true; + }, + parent: function(elem){ + return !!elem.firstChild; + }, + empty: function(elem){ + return !elem.firstChild; + }, + has: function(elem, i, match){ + return !!Sizzle( match[3], elem ).length; + }, + header: function(elem){ + return (/h\d/i).test( elem.nodeName ); + }, + text: function(elem){ + return "text" === elem.type; + }, + radio: function(elem){ + return "radio" === elem.type; + }, + checkbox: function(elem){ + return "checkbox" === elem.type; + }, + file: function(elem){ + return "file" === elem.type; + }, + password: function(elem){ + return "password" === elem.type; + }, + submit: function(elem){ + return "submit" === elem.type; + }, + image: function(elem){ + return "image" === elem.type; + }, + reset: function(elem){ + return "reset" === elem.type; + }, + button: function(elem){ + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + input: function(elem){ + return (/input|select|textarea|button/i).test(elem.nodeName); + } + }, + setFilters: { + first: function(elem, i){ + return i === 0; + }, + last: function(elem, i, match, array){ + return i === array.length - 1; + }, + even: function(elem, i){ + return i % 2 === 0; + }, + odd: function(elem, i){ + return i % 2 === 1; + }, + lt: function(elem, i, match){ + return i < match[3] - 0; + }, + gt: function(elem, i, match){ + return i > match[3] - 0; + }, + nth: function(elem, i, match){ + return match[3] - 0 === i; + }, + eq: function(elem, i, match){ + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function(elem, match, i, array){ + var name = match[1], filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + } else { + Sizzle.error( "Syntax error, unrecognized expression: " + name ); + } + }, + CHILD: function(elem, match){ + var type = match[1], node = elem; + switch (type) { + case 'only': + case 'first': + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + if ( type === "first" ) { + return true; + } + node = elem; + case 'last': + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + return true; + case 'nth': + var first = match[2], last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + if ( first === 0 ) { + return diff === 0; + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + ID: function(elem, match){ + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + TAG: function(elem, match){ + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + CLASS: function(elem, match){ + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + ATTR: function(elem, match){ + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + POS: function(elem, match, i, array){ + var name = match[2], filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function(array, results) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch(e){ + makeArray = function(array, results) { + var ret = results || [], i = 0; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.compareDocumentPosition ? -1 : 1; + } + + var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( "sourceIndex" in document.documentElement ) { + sortOrder = function( a, b ) { + if ( !a.sourceIndex || !b.sourceIndex ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.sourceIndex ? -1 : 1; + } + + var ret = a.sourceIndex - b.sourceIndex; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( document.createRange ) { + sortOrder = function( a, b ) { + if ( !a.ownerDocument || !b.ownerDocument ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.ownerDocument ? -1 : 1; + } + + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(); + form.innerHTML = "<a name='" + id + "'/>"; + + // Inject it into the root element, check its status, and remove it quickly + var root = document.documentElement; + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; + } + }; + + Expr.filter.ID = function(elem, match){ + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + root = form = null; // release memory in IE +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function(match, context){ + var results = context.getElementsByTagName(match[1]); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = "<a href='#'></a>"; + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } + + div = null; // release memory in IE +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, div = document.createElement("div"); + div.innerHTML = "<p class='TEST'></p>"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function(query, context, extra, seed){ + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && context.nodeType === 9 && !Sizzle.isXML(context) ) { + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(e){} + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + div = null; // release memory in IE + })(); +} + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "<div class='test e'></div><div class='test'></div>"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function(match, context, isXML) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + div = null; // release memory in IE +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +Sizzle.contains = document.compareDocumentPosition ? function(a, b){ + return !!(a.compareDocumentPosition(b) & 16); +} : function(a, b){ + return a !== b && (a.contains ? a.contains(b) : true); +}; + +Sizzle.isXML = function(elem){ + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function(selector, context){ + var tmpSet = [], later = "", match, + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE + +window.tinymce.dom.Sizzle = Sizzle; + +})(); + + +(function(tinymce) { + // Shorten names + var each = tinymce.each, DOM = tinymce.DOM, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, Event; + + tinymce.create('tinymce.dom.EventUtils', { + EventUtils : function() { + this.inits = []; + this.events = []; + }, + + add : function(o, n, f, s) { + var cb, t = this, el = t.events, r; + + if (n instanceof Array) { + r = []; + + each(n, function(n) { + r.push(t.add(o, n, f, s)); + }); + + return r; + } + + // Handle array + if (o && o.hasOwnProperty && o instanceof Array) { + r = []; + + each(o, function(o) { + o = DOM.get(o); + r.push(t.add(o, n, f, s)); + }); + + return r; + } + + o = DOM.get(o); + + if (!o) + return; + + // Setup event callback + cb = function(e) { + // Is all events disabled + if (t.disabled) + return; + + e = e || window.event; + + // Patch in target, preventDefault and stopPropagation in IE it's W3C valid + if (e && isIE) { + if (!e.target) + e.target = e.srcElement; + + // Patch in preventDefault, stopPropagation methods for W3C compatibility + tinymce.extend(e, t._stoppers); + } + + if (!s) + return f(e); + + return f.call(s, e); + }; + + if (n == 'unload') { + tinymce.unloads.unshift({func : cb}); + return cb; + } + + if (n == 'init') { + if (t.domLoaded) + cb(); + else + t.inits.push(cb); + + return cb; + } + + // Store away listener reference + el.push({ + obj : o, + name : n, + func : f, + cfunc : cb, + scope : s + }); + + t._add(o, n, cb); + + return f; + }, + + remove : function(o, n, f) { + var t = this, a = t.events, s = false, r; + + // Handle array + if (o && o.hasOwnProperty && o instanceof Array) { + r = []; + + each(o, function(o) { + o = DOM.get(o); + r.push(t.remove(o, n, f)); + }); + + return r; + } + + o = DOM.get(o); + + each(a, function(e, i) { + if (e.obj == o && e.name == n && (!f || (e.func == f || e.cfunc == f))) { + a.splice(i, 1); + t._remove(o, n, e.cfunc); + s = true; + return false; + } + }); + + return s; + }, + + clear : function(o) { + var t = this, a = t.events, i, e; + + if (o) { + o = DOM.get(o); + + for (i = a.length - 1; i >= 0; i--) { + e = a[i]; + + if (e.obj === o) { + t._remove(e.obj, e.name, e.cfunc); + e.obj = e.cfunc = null; + a.splice(i, 1); + } + } + } + }, + + cancel : function(e) { + if (!e) + return false; + + this.stop(e); + + return this.prevent(e); + }, + + stop : function(e) { + if (e.stopPropagation) + e.stopPropagation(); + else + e.cancelBubble = true; + + return false; + }, + + prevent : function(e) { + if (e.preventDefault) + e.preventDefault(); + else + e.returnValue = false; + + return false; + }, + + destroy : function() { + var t = this; + + each(t.events, function(e, i) { + t._remove(e.obj, e.name, e.cfunc); + e.obj = e.cfunc = null; + }); + + t.events = []; + t = null; + }, + + _add : function(o, n, f) { + if (o.attachEvent) + o.attachEvent('on' + n, f); + else if (o.addEventListener) + o.addEventListener(n, f, false); + else + o['on' + n] = f; + }, + + _remove : function(o, n, f) { + if (o) { + try { + if (o.detachEvent) + o.detachEvent('on' + n, f); + else if (o.removeEventListener) + o.removeEventListener(n, f, false); + else + o['on' + n] = null; + } catch (ex) { + // Might fail with permission denined on IE so we just ignore that + } + } + }, + + _pageInit : function(win) { + var t = this; + + // Keep it from running more than once + if (t.domLoaded) + return; + + t.domLoaded = true; + + each(t.inits, function(c) { + c(); + }); + + t.inits = []; + }, + + _wait : function(win) { + var t = this, doc = win.document; + + // No need since the document is already loaded + if (win.tinyMCE_GZ && tinyMCE_GZ.loaded) { + t.domLoaded = 1; + return; + } + + // Use IE method + if (doc.attachEvent) { + doc.attachEvent("onreadystatechange", function() { + if (doc.readyState === "complete") { + doc.detachEvent("onreadystatechange", arguments.callee); + t._pageInit(win); + } + }); + + if (doc.documentElement.doScroll && win == win.top) { + (function() { + if (t.domLoaded) + return; + + try { + // If IE is used, use the trick by Diego Perini licensed under MIT by request to the author. + // http://javascript.nwbox.com/IEContentLoaded/ + doc.documentElement.doScroll("left"); + } catch (ex) { + setTimeout(arguments.callee, 0); + return; + } + + t._pageInit(win); + })(); + } + } else if (doc.addEventListener) { + t._add(win, 'DOMContentLoaded', function() { + t._pageInit(win); + }); + } + + t._add(win, 'load', function() { + t._pageInit(win); + }); + }, + + _stoppers : { + preventDefault : function() { + this.returnValue = false; + }, + + stopPropagation : function() { + this.cancelBubble = true; + } + } + }); + + Event = tinymce.dom.Event = new tinymce.dom.EventUtils(); + + // Dispatch DOM content loaded event for IE and Safari + Event._wait(window); + + tinymce.addUnload(function() { + Event.destroy(); + }); +})(tinymce); + +(function(tinymce) { + tinymce.dom.Element = function(id, settings) { + var t = this, dom, el; + + t.settings = settings = settings || {}; + t.id = id; + t.dom = dom = settings.dom || tinymce.DOM; + + // Only IE leaks DOM references, this is a lot faster + if (!tinymce.isIE) + el = dom.get(t.id); + + tinymce.each( + ('getPos,getRect,getParent,add,setStyle,getStyle,setStyles,' + + 'setAttrib,setAttribs,getAttrib,addClass,removeClass,' + + 'hasClass,getOuterHTML,setOuterHTML,remove,show,hide,' + + 'isHidden,setHTML,get').split(/,/) + , function(k) { + t[k] = function() { + var a = [id], i; + + for (i = 0; i < arguments.length; i++) + a.push(arguments[i]); + + a = dom[k].apply(dom, a); + t.update(k); + + return a; + }; + }); + + tinymce.extend(t, { + on : function(n, f, s) { + return tinymce.dom.Event.add(t.id, n, f, s); + }, + + getXY : function() { + return { + x : parseInt(t.getStyle('left')), + y : parseInt(t.getStyle('top')) + }; + }, + + getSize : function() { + var n = dom.get(t.id); + + return { + w : parseInt(t.getStyle('width') || n.clientWidth), + h : parseInt(t.getStyle('height') || n.clientHeight) + }; + }, + + moveTo : function(x, y) { + t.setStyles({left : x, top : y}); + }, + + moveBy : function(x, y) { + var p = t.getXY(); + + t.moveTo(p.x + x, p.y + y); + }, + + resizeTo : function(w, h) { + t.setStyles({width : w, height : h}); + }, + + resizeBy : function(w, h) { + var s = t.getSize(); + + t.resizeTo(s.w + w, s.h + h); + }, + + update : function(k) { + var b; + + if (tinymce.isIE6 && settings.blocker) { + k = k || ''; + + // Ignore getters + if (k.indexOf('get') === 0 || k.indexOf('has') === 0 || k.indexOf('is') === 0) + return; + + // Remove blocker on remove + if (k == 'remove') { + dom.remove(t.blocker); + return; + } + + if (!t.blocker) { + t.blocker = dom.uniqueId(); + b = dom.add(settings.container || dom.getRoot(), 'iframe', {id : t.blocker, style : 'position:absolute;', frameBorder : 0, src : 'javascript:""'}); + dom.setStyle(b, 'opacity', 0); + } else + b = dom.get(t.blocker); + + dom.setStyles(b, { + left : t.getStyle('left', 1), + top : t.getStyle('top', 1), + width : t.getStyle('width', 1), + height : t.getStyle('height', 1), + display : t.getStyle('display', 1), + zIndex : parseInt(t.getStyle('zIndex', 1) || 0) - 1 + }); + } + } + }); + }; +})(tinymce); + +(function(tinymce) { + function trimNl(s) { + return s.replace(/[\n\r]+/g, ''); + }; + + // Shorten names + var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each; + + tinymce.create('tinymce.dom.Selection', { + Selection : function(dom, win, serializer) { + var t = this; + + t.dom = dom; + t.win = win; + t.serializer = serializer; + + // Add events + each([ + 'onBeforeSetContent', + + 'onBeforeGetContent', + + 'onSetContent', + + 'onGetContent' + ], function(e) { + t[e] = new tinymce.util.Dispatcher(t); + }); + + // No W3C Range support + if (!t.win.getSelection) + t.tridentSel = new tinymce.dom.TridentSelection(t); + + if (tinymce.isIE && dom.boxModel) + this._fixIESelection(); + + // Prevent leaks + tinymce.addUnload(t.destroy, t); + }, + + setCursorLocation: function(node, offset) { + var t = this; var r = t.dom.createRng(); + r.setStart(node, offset); + r.setEnd(node, offset); + t.setRng(r); + t.collapse(false); + }, + getContent : function(s) { + var t = this, r = t.getRng(), e = t.dom.create("body"), se = t.getSel(), wb, wa, n; + + s = s || {}; + wb = wa = ''; + s.get = true; + s.format = s.format || 'html'; + s.forced_root_block = ''; + t.onBeforeGetContent.dispatch(t, s); + + if (s.format == 'text') + return t.isCollapsed() ? '' : (r.text || (se.toString ? se.toString() : '')); + + if (r.cloneContents) { + n = r.cloneContents(); + + if (n) + e.appendChild(n); + } else if (is(r.item) || is(r.htmlText)) { + // IE will produce invalid markup if elements are present that + // it doesn't understand like custom elements or HTML5 elements. + // Adding a BR in front of the contents and then remoiving it seems to fix it though. + e.innerHTML = '<br>' + (r.item ? r.item(0).outerHTML : r.htmlText); + e.removeChild(e.firstChild); + } else + e.innerHTML = r.toString(); + + // Keep whitespace before and after + if (/^\s/.test(e.innerHTML)) + wb = ' '; + + if (/\s+$/.test(e.innerHTML)) + wa = ' '; + + s.getInner = true; + + s.content = t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa; + t.onGetContent.dispatch(t, s); + + return s.content; + }, + + setContent : function(content, args) { + var self = this, rng = self.getRng(), caretNode, doc = self.win.document, frag, temp; + + args = args || {format : 'html'}; + args.set = true; + content = args.content = content; + + // Dispatch before set content event + if (!args.no_events) + self.onBeforeSetContent.dispatch(self, args); + + content = args.content; + + if (rng.insertNode) { + // Make caret marker since insertNode places the caret in the beginning of text after insert + content += '<span id="__caret">_</span>'; + + // Delete and insert new node + if (rng.startContainer == doc && rng.endContainer == doc) { + // WebKit will fail if the body is empty since the range is then invalid and it can't insert contents + doc.body.innerHTML = content; + } else { + rng.deleteContents(); + + if (doc.body.childNodes.length == 0) { + doc.body.innerHTML = content; + } else { + // createContextualFragment doesn't exists in IE 9 DOMRanges + if (rng.createContextualFragment) { + rng.insertNode(rng.createContextualFragment(content)); + } else { + // Fake createContextualFragment call in IE 9 + frag = doc.createDocumentFragment(); + temp = doc.createElement('div'); + + frag.appendChild(temp); + temp.outerHTML = content; + + rng.insertNode(frag); + } + } + } + + // Move to caret marker + caretNode = self.dom.get('__caret'); + + // Make sure we wrap it compleatly, Opera fails with a simple select call + rng = doc.createRange(); + rng.setStartBefore(caretNode); + rng.setEndBefore(caretNode); + self.setRng(rng); + + // Remove the caret position + self.dom.remove('__caret'); + + try { + self.setRng(rng); + } catch (ex) { + // Might fail on Opera for some odd reason + } + } else { + if (rng.item) { + // Delete content and get caret text selection + doc.execCommand('Delete', false, null); + rng = self.getRng(); + } + + // Explorer removes spaces from the beginning of pasted contents + if (/^\s+/.test(content)) { + rng.pasteHTML('<span id="__mce_tmp">_</span>' + content); + self.dom.remove('__mce_tmp'); + } else + rng.pasteHTML(content); + } + + // Dispatch set content event + if (!args.no_events) + self.onSetContent.dispatch(self, args); + }, + + getStart : function() { + var rng = this.getRng(), startElement, parentElement, checkRng, node; + + if (rng.duplicate || rng.item) { + // Control selection, return first item + if (rng.item) + return rng.item(0); + + // Get start element + checkRng = rng.duplicate(); + checkRng.collapse(1); + startElement = checkRng.parentElement(); + + // Check if range parent is inside the start element, then return the inner parent element + // This will fix issues when a single element is selected, IE would otherwise return the wrong start element + parentElement = node = rng.parentElement(); + while (node = node.parentNode) { + if (node == startElement) { + startElement = parentElement; + break; + } + } + + return startElement; + } else { + startElement = rng.startContainer; + + if (startElement.nodeType == 1 && startElement.hasChildNodes()) + startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)]; + + if (startElement && startElement.nodeType == 3) + return startElement.parentNode; + + return startElement; + } + }, + + getEnd : function() { + var t = this, r = t.getRng(), e, eo; + + if (r.duplicate || r.item) { + if (r.item) + return r.item(0); + + r = r.duplicate(); + r.collapse(0); + e = r.parentElement(); + + if (e && e.nodeName == 'BODY') + return e.lastChild || e; + + return e; + } else { + e = r.endContainer; + eo = r.endOffset; + + if (e.nodeType == 1 && e.hasChildNodes()) + e = e.childNodes[eo > 0 ? eo - 1 : eo]; + + if (e && e.nodeType == 3) + return e.parentNode; + + return e; + } + }, + + getBookmark : function(type, normalized) { + var t = this, dom = t.dom, rng, rng2, id, collapsed, name, element, index, chr = '\uFEFF', styles; + + function findIndex(name, element) { + var index = 0; + + each(dom.select(name), function(node, i) { + if (node == element) + index = i; + }); + + return index; + }; + + if (type == 2) { + function getLocation() { + var rng = t.getRng(true), root = dom.getRoot(), bookmark = {}; + + function getPoint(rng, start) { + var container = rng[start ? 'startContainer' : 'endContainer'], + offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0; + + if (container.nodeType == 3) { + if (normalized) { + for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) + offset += node.nodeValue.length; + } + + point.push(offset); + } else { + childNodes = container.childNodes; + + if (offset >= childNodes.length && childNodes.length) { + after = 1; + offset = Math.max(0, childNodes.length - 1); + } + + point.push(t.dom.nodeIndex(childNodes[offset], normalized) + after); + } + + for (; container && container != root; container = container.parentNode) + point.push(t.dom.nodeIndex(container, normalized)); + + return point; + }; + + bookmark.start = getPoint(rng, true); + + if (!t.isCollapsed()) + bookmark.end = getPoint(rng); + + return bookmark; + }; + + if (t.tridentSel) + return t.tridentSel.getBookmark(type); + + return getLocation(); + } + + // Handle simple range + if (type) + return {rng : t.getRng()}; + + rng = t.getRng(); + id = dom.uniqueId(); + collapsed = tinyMCE.activeEditor.selection.isCollapsed(); + styles = 'overflow:hidden;line-height:0px'; + + // Explorer method + if (rng.duplicate || rng.item) { + // Text selection + if (!rng.item) { + rng2 = rng.duplicate(); + + try { + // Insert start marker + rng.collapse(); + rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>'); + + // Insert end marker + if (!collapsed) { + rng2.collapse(false); + + // Detect the empty space after block elements in IE and move the end back one character <p></p>] becomes <p>]</p> + rng.moveToElementText(rng2.parentElement()); + if (rng.compareEndPoints('StartToEnd', rng2) == 0) + rng2.move('character', -1); + + rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>'); + } + } catch (ex) { + // IE might throw unspecified error so lets ignore it + return null; + } + } else { + // Control selection + element = rng.item(0); + name = element.nodeName; + + return {name : name, index : findIndex(name, element)}; + } + } else { + element = t.getNode(); + name = element.nodeName; + if (name == 'IMG') + return {name : name, index : findIndex(name, element)}; + + // W3C method + rng2 = rng.cloneRange(); + + // Insert end marker + if (!collapsed) { + rng2.collapse(false); + rng2.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_end', style : styles}, chr)); + } + + rng.collapse(true); + rng.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_start', style : styles}, chr)); + } + + t.moveToBookmark({id : id, keep : 1}); + + return {id : id}; + }, + + moveToBookmark : function(bookmark) { + var t = this, dom = t.dom, marker1, marker2, rng, root, startContainer, endContainer, startOffset, endOffset; + + if (bookmark) { + if (bookmark.start) { + rng = dom.createRng(); + root = dom.getRoot(); + + function setEndPoint(start) { + var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; + + if (point) { + offset = point[0]; + + // Find container node + for (node = root, i = point.length - 1; i >= 1; i--) { + children = node.childNodes; + + if (point[i] > children.length - 1) + return; + + node = children[point[i]]; + } + + // Move text offset to best suitable location + if (node.nodeType === 3) + offset = Math.min(point[0], node.nodeValue.length); + + // Move element offset to best suitable location + if (node.nodeType === 1) + offset = Math.min(point[0], node.childNodes.length); + + // Set offset within container node + if (start) + rng.setStart(node, offset); + else + rng.setEnd(node, offset); + } + + return true; + }; + + if (t.tridentSel) + return t.tridentSel.moveToBookmark(bookmark); + + if (setEndPoint(true) && setEndPoint()) { + t.setRng(rng); + } + } else if (bookmark.id) { + function restoreEndPoint(suffix) { + var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep; + + if (marker) { + node = marker.parentNode; + + if (suffix == 'start') { + if (!keep) { + idx = dom.nodeIndex(marker); + } else { + node = marker.firstChild; + idx = 1; + } + + startContainer = endContainer = node; + startOffset = endOffset = idx; + } else { + if (!keep) { + idx = dom.nodeIndex(marker); + } else { + node = marker.firstChild; + idx = 1; + } + + endContainer = node; + endOffset = idx; + } + + if (!keep) { + prev = marker.previousSibling; + next = marker.nextSibling; + + // Remove all marker text nodes + each(tinymce.grep(marker.childNodes), function(node) { + if (node.nodeType == 3) + node.nodeValue = node.nodeValue.replace(/\uFEFF/g, ''); + }); + + // Remove marker but keep children if for example contents where inserted into the marker + // Also remove duplicated instances of the marker for example by a split operation or by WebKit auto split on paste feature + while (marker = dom.get(bookmark.id + '_' + suffix)) + dom.remove(marker, 1); + + // If siblings are text nodes then merge them unless it's Opera since it some how removes the node + // and we are sniffing since adding a lot of detection code for a browser with 3% of the market isn't worth the effort. Sorry, Opera but it's just a fact + if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !tinymce.isOpera) { + idx = prev.nodeValue.length; + prev.appendData(next.nodeValue); + dom.remove(next); + + if (suffix == 'start') { + startContainer = endContainer = prev; + startOffset = endOffset = idx; + } else { + endContainer = prev; + endOffset = idx; + } + } + } + } + }; + + function addBogus(node) { + // Adds a bogus BR element for empty block elements or just a space on IE since it renders BR elements incorrectly + if (dom.isBlock(node) && !node.innerHTML) + node.innerHTML = !isIE ? '<br data-mce-bogus="1" />' : ' '; + + return node; + }; + + // Restore start/end points + restoreEndPoint('start'); + restoreEndPoint('end'); + + if (startContainer) { + rng = dom.createRng(); + rng.setStart(addBogus(startContainer), startOffset); + rng.setEnd(addBogus(endContainer), endOffset); + t.setRng(rng); + } + } else if (bookmark.name) { + t.select(dom.select(bookmark.name)[bookmark.index]); + } else if (bookmark.rng) + t.setRng(bookmark.rng); + } + }, + + select : function(node, content) { + var t = this, dom = t.dom, rng = dom.createRng(), idx; + + if (node) { + idx = dom.nodeIndex(node); + rng.setStart(node.parentNode, idx); + rng.setEnd(node.parentNode, idx + 1); + + // Find first/last text node or BR element + if (content) { + function setPoint(node, start) { + var walker = new tinymce.dom.TreeWalker(node, node); + + do { + // Text node + if (node.nodeType == 3 && tinymce.trim(node.nodeValue).length != 0) { + if (start) + rng.setStart(node, 0); + else + rng.setEnd(node, node.nodeValue.length); + + return; + } + + // BR element + if (node.nodeName == 'BR') { + if (start) + rng.setStartBefore(node); + else + rng.setEndBefore(node); + + return; + } + } while (node = (start ? walker.next() : walker.prev())); + }; + + setPoint(node, 1); + setPoint(node); + } + + t.setRng(rng); + } + + return node; + }, + + isCollapsed : function() { + var t = this, r = t.getRng(), s = t.getSel(); + + if (!r || r.item) + return false; + + if (r.compareEndPoints) + return r.compareEndPoints('StartToEnd', r) === 0; + + return !s || r.collapsed; + }, + + collapse : function(to_start) { + var self = this, rng = self.getRng(), node; + + // Control range on IE + if (rng.item) { + node = rng.item(0); + rng = self.win.document.body.createTextRange(); + rng.moveToElementText(node); + } + + rng.collapse(!!to_start); + self.setRng(rng); + }, + + getSel : function() { + var t = this, w = this.win; + + return w.getSelection ? w.getSelection() : w.document.selection; + }, + + getRng : function(w3c) { + var t = this, s, r, elm, doc = t.win.document; + + // Found tridentSel object then we need to use that one + if (w3c && t.tridentSel) + return t.tridentSel.getRangeAt(0); + + try { + if (s = t.getSel()) + r = s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : doc.createRange()); + } catch (ex) { + // IE throws unspecified error here if TinyMCE is placed in a frame/iframe + } + + // We have W3C ranges and it's IE then fake control selection since IE9 doesn't handle that correctly yet + if (tinymce.isIE && r && r.setStart && doc.selection.createRange().item) { + elm = doc.selection.createRange().item(0); + r = doc.createRange(); + r.setStartBefore(elm); + r.setEndAfter(elm); + } + + // No range found then create an empty one + // This can occur when the editor is placed in a hidden container element on Gecko + // Or on IE when there was an exception + if (!r) + r = doc.createRange ? doc.createRange() : doc.body.createTextRange(); + + if (t.selectedRange && t.explicitRange) { + if (r.compareBoundaryPoints(r.START_TO_START, t.selectedRange) === 0 && r.compareBoundaryPoints(r.END_TO_END, t.selectedRange) === 0) { + // Safari, Opera and Chrome only ever select text which causes the range to change. + // This lets us use the originally set range if the selection hasn't been changed by the user. + r = t.explicitRange; + } else { + t.selectedRange = null; + t.explicitRange = null; + } + } + + return r; + }, + + setRng : function(r) { + var s, t = this; + + if (!t.tridentSel) { + s = t.getSel(); + + if (s) { + t.explicitRange = r; + + try { + s.removeAllRanges(); + } catch (ex) { + // IE9 might throw errors here don't know why + } + + s.addRange(r); + t.selectedRange = s.getRangeAt(0); + } + } else { + // Is W3C Range + if (r.cloneRange) { + t.tridentSel.addRange(r); + return; + } + + // Is IE specific range + try { + r.select(); + } catch (ex) { + // Needed for some odd IE bug #1843306 + } + } + }, + + setNode : function(n) { + var t = this; + + t.setContent(t.dom.getOuterHTML(n)); + + return n; + }, + + getNode : function() { + var t = this, rng = t.getRng(), sel = t.getSel(), elm, start = rng.startContainer, end = rng.endContainer; + + // Range maybe lost after the editor is made visible again + if (!rng) + return t.dom.getRoot(); + + if (rng.setStart) { + elm = rng.commonAncestorContainer; + + // Handle selection a image or other control like element such as anchors + if (!rng.collapsed) { + if (rng.startContainer == rng.endContainer) { + if (rng.endOffset - rng.startOffset < 2) { + if (rng.startContainer.hasChildNodes()) + elm = rng.startContainer.childNodes[rng.startOffset]; + } + } + + // If the anchor node is a element instead of a text node then return this element + //if (tinymce.isWebKit && sel.anchorNode && sel.anchorNode.nodeType == 1) + // return sel.anchorNode.childNodes[sel.anchorOffset]; + + // Handle cases where the selection is immediately wrapped around a node and return that node instead of it's parent. + // This happens when you double click an underlined word in FireFox. + if (start.nodeType === 3 && end.nodeType === 3) { + function skipEmptyTextNodes(n, forwards) { + var orig = n; + while (n && n.nodeType === 3 && n.length === 0) { + n = forwards ? n.nextSibling : n.previousSibling; + } + return n || orig; + } + if (start.length === rng.startOffset) { + start = skipEmptyTextNodes(start.nextSibling, true); + } else { + start = start.parentNode; + } + if (rng.endOffset === 0) { + end = skipEmptyTextNodes(end.previousSibling, false); + } else { + end = end.parentNode; + } + + if (start && start === end) + return start; + } + } + + if (elm && elm.nodeType == 3) + return elm.parentNode; + + return elm; + } + + return rng.item ? rng.item(0) : rng.parentElement(); + }, + + getSelectedBlocks : function(st, en) { + var t = this, dom = t.dom, sb, eb, n, bl = []; + + sb = dom.getParent(st || t.getStart(), dom.isBlock); + eb = dom.getParent(en || t.getEnd(), dom.isBlock); + + if (sb) + bl.push(sb); + + if (sb && eb && sb != eb) { + n = sb; + + while ((n = n.nextSibling) && n != eb) { + if (dom.isBlock(n)) + bl.push(n); + } + } + + if (eb && sb != eb) + bl.push(eb); + + return bl; + }, + + normalize : function() { + var self = this, rng, normalized; + + // Normalize only on non IE browsers for now + if (tinymce.isIE) + return; + + function normalizeEndPoint(start) { + var container, offset, walker, dom = self.dom, body = dom.getRoot(), node; + + container = rng[(start ? 'start' : 'end') + 'Container']; + offset = rng[(start ? 'start' : 'end') + 'Offset']; + + // If the container is a document move it to the body element + if (container.nodeType === 9) { + container = container.body; + offset = 0; + } + + // If the container is body try move it into the closest text node or position + // TODO: Add more logic here to handle element selection cases + if (container === body) { + // Resolve the index + if (container.hasChildNodes()) { + container = container.childNodes[Math.min(!start && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1)]; + offset = 0; + + // Don't walk into elements that doesn't have any child nodes like a IMG + if (container.hasChildNodes()) { + // Walk the DOM to find a text node to place the caret at or a BR + node = container; + walker = new tinymce.dom.TreeWalker(container, body); + do { + // Found a text node use that position + if (node.nodeType === 3) { + offset = start ? 0 : node.nodeValue.length - 1; + container = node; + break; + } + + // Found a BR element that we can place the caret before + if (node.nodeName === 'BR') { + offset = dom.nodeIndex(node); + container = node.parentNode; + break; + } + } while (node = (start ? walker.next() : walker.prev())); + + normalized = true; + } + } + } + + // Set endpoint if it was normalized + if (normalized) + rng['set' + (start ? 'Start' : 'End')](container, offset); + }; + + rng = self.getRng(); + + // Normalize the end points + normalizeEndPoint(true); + + if (rng.collapsed) + normalizeEndPoint(); + + // Set the selection if it was normalized + if (normalized) { + //console.log(self.dom.dumpRng(rng)); + self.setRng(rng); + } + }, + + destroy : function(s) { + var t = this; + + t.win = null; + + // Manual destroy then remove unload handler + if (!s) + tinymce.removeUnload(t.destroy); + }, + + // IE has an issue where you can't select/move the caret by clicking outside the body if the document is in standards mode + _fixIESelection : function() { + var dom = this.dom, doc = dom.doc, body = doc.body, started, startRng, htmlElm; + + // Make HTML element unselectable since we are going to handle selection by hand + doc.documentElement.unselectable = true; + + // Return range from point or null if it failed + function rngFromPoint(x, y) { + var rng = body.createTextRange(); + + try { + rng.moveToPoint(x, y); + } catch (ex) { + // IE sometimes throws and exception, so lets just ignore it + rng = null; + } + + return rng; + }; + + // Fires while the selection is changing + function selectionChange(e) { + var pointRng; + + // Check if the button is down or not + if (e.button) { + // Create range from mouse position + pointRng = rngFromPoint(e.x, e.y); + + if (pointRng) { + // Check if pointRange is before/after selection then change the endPoint + if (pointRng.compareEndPoints('StartToStart', startRng) > 0) + pointRng.setEndPoint('StartToStart', startRng); + else + pointRng.setEndPoint('EndToEnd', startRng); + + pointRng.select(); + } + } else + endSelection(); + } + + // Removes listeners + function endSelection() { + var rng = doc.selection.createRange(); + + // If the range is collapsed then use the last start range + if (startRng && !rng.item && rng.compareEndPoints('StartToEnd', rng) === 0) + startRng.select(); + + dom.unbind(doc, 'mouseup', endSelection); + dom.unbind(doc, 'mousemove', selectionChange); + startRng = started = 0; + }; + + // Detect when user selects outside BODY + dom.bind(doc, ['mousedown', 'contextmenu'], function(e) { + if (e.target.nodeName === 'HTML') { + if (started) + endSelection(); + + // Detect vertical scrollbar, since IE will fire a mousedown on the scrollbar and have target set as HTML + htmlElm = doc.documentElement; + if (htmlElm.scrollHeight > htmlElm.clientHeight) + return; + + started = 1; + // Setup start position + startRng = rngFromPoint(e.x, e.y); + if (startRng) { + // Listen for selection change events + dom.bind(doc, 'mouseup', endSelection); + dom.bind(doc, 'mousemove', selectionChange); + + dom.win.focus(); + startRng.select(); + } + } + }); + } + }); +})(tinymce); + +(function(tinymce) { + tinymce.dom.Serializer = function(settings, dom, schema) { + var onPreProcess, onPostProcess, isIE = tinymce.isIE, each = tinymce.each, htmlParser; + + // Support the old apply_source_formatting option + if (!settings.apply_source_formatting) + settings.indent = false; + + settings.remove_trailing_brs = true; + + // Default DOM and Schema if they are undefined + dom = dom || tinymce.DOM; + schema = schema || new tinymce.html.Schema(settings); + settings.entity_encoding = settings.entity_encoding || 'named'; + + onPreProcess = new tinymce.util.Dispatcher(self); + + onPostProcess = new tinymce.util.Dispatcher(self); + + htmlParser = new tinymce.html.DomParser(settings, schema); + + // Convert move data-mce-src, data-mce-href and data-mce-style into nodes or process them if needed + htmlParser.addAttributeFilter('src,href,style', function(nodes, name) { + var i = nodes.length, node, value, internalName = 'data-mce-' + name, urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope, undef; + + while (i--) { + node = nodes[i]; + + value = node.attributes.map[internalName]; + if (value !== undef) { + // Set external name to internal value and remove internal + node.attr(name, value.length > 0 ? value : null); + node.attr(internalName, null); + } else { + // No internal attribute found then convert the value we have in the DOM + value = node.attributes.map[name]; + + if (name === "style") + value = dom.serializeStyle(dom.parseStyle(value), node.name); + else if (urlConverter) + value = urlConverter.call(urlConverterScope, value, name, node.name); + + node.attr(name, value.length > 0 ? value : null); + } + } + }); + + // Remove internal classes mceItem<..> + htmlParser.addAttributeFilter('class', function(nodes, name) { + var i = nodes.length, node, value; + + while (i--) { + node = nodes[i]; + value = node.attr('class').replace(/\s*mce(Item\w+|Selected)\s*/g, ''); + node.attr('class', value.length > 0 ? value : null); + } + }); + + // Remove bookmark elements + htmlParser.addAttributeFilter('data-mce-type', function(nodes, name, args) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + + if (node.attributes.map['data-mce-type'] === 'bookmark' && !args.cleanup) + node.remove(); + } + }); + + // Force script into CDATA sections and remove the mce- prefix also add comments around styles + htmlParser.addNodeFilter('script,style', function(nodes, name) { + var i = nodes.length, node, value; + + function trim(value) { + return value.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n') + .replace(/^[\r\n]*|[\r\n]*$/g, '') + .replace(/^\s*(\/\/\s*<!--|\/\/\s*<!\[CDATA\[|<!--|<!\[CDATA\[)[\r\n]*/g, '') + .replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->|\]\]-->)\s*$/g, ''); + }; + + while (i--) { + node = nodes[i]; + value = node.firstChild ? node.firstChild.value : ''; + + if (name === "script") { + // Remove mce- prefix from script elements + node.attr('type', (node.attr('type') || 'text/javascript').replace(/^mce\-/, '')); + + if (value.length > 0) + node.firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>'; + } else { + if (value.length > 0) + node.firstChild.value = '<!--\n' + trim(value) + '\n-->'; + } + } + }); + + // Convert comments to cdata and handle protected comments + htmlParser.addNodeFilter('#comment', function(nodes, name) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + + if (node.value.indexOf('[CDATA[') === 0) { + node.name = '#cdata'; + node.type = 4; + node.value = node.value.replace(/^\[CDATA\[|\]\]$/g, ''); + } else if (node.value.indexOf('mce:protected ') === 0) { + node.name = "#text"; + node.type = 3; + node.raw = true; + node.value = unescape(node.value).substr(14); + } + } + }); + + htmlParser.addNodeFilter('xml:namespace,input', function(nodes, name) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + if (node.type === 7) + node.remove(); + else if (node.type === 1) { + if (name === "input" && !("type" in node.attributes.map)) + node.attr('type', 'text'); + } + } + }); + + // Fix list elements, TODO: Replace this later + if (settings.fix_list_elements) { + htmlParser.addNodeFilter('ul,ol', function(nodes, name) { + var i = nodes.length, node, parentNode; + + while (i--) { + node = nodes[i]; + parentNode = node.parent; + + if (parentNode.name === 'ul' || parentNode.name === 'ol') { + if (node.prev && node.prev.name === 'li') { + node.prev.append(node); + } + } + } + }); + } + + // Remove internal data attributes + htmlParser.addAttributeFilter('data-mce-src,data-mce-href,data-mce-style', function(nodes, name) { + var i = nodes.length; + + while (i--) { + nodes[i].attr(name, null); + } + }); + + // Return public methods + return { + schema : schema, + + addNodeFilter : htmlParser.addNodeFilter, + + addAttributeFilter : htmlParser.addAttributeFilter, + + onPreProcess : onPreProcess, + + onPostProcess : onPostProcess, + + serialize : function(node, args) { + var impl, doc, oldDoc, htmlSerializer, content; + + // Explorer won't clone contents of script and style and the + // selected index of select elements are cleared on a clone operation. + if (isIE && dom.select('script,style,select,map').length > 0) { + content = node.innerHTML; + node = node.cloneNode(false); + dom.setHTML(node, content); + } else + node = node.cloneNode(true); + + // Nodes needs to be attached to something in WebKit/Opera + // Older builds of Opera crashes if you attach the node to an document created dynamically + // and since we can't feature detect a crash we need to sniff the acutal build number + // This fix will make DOM ranges and make Sizzle happy! + impl = node.ownerDocument.implementation; + if (impl.createHTMLDocument) { + // Create an empty HTML document + doc = impl.createHTMLDocument(""); + + // Add the element or it's children if it's a body element to the new document + each(node.nodeName == 'BODY' ? node.childNodes : [node], function(node) { + doc.body.appendChild(doc.importNode(node, true)); + }); + + // Grab first child or body element for serialization + if (node.nodeName != 'BODY') + node = doc.body.firstChild; + else + node = doc.body; + + // set the new document in DOMUtils so createElement etc works + oldDoc = dom.doc; + dom.doc = doc; + } + + args = args || {}; + args.format = args.format || 'html'; + + // Pre process + if (!args.no_events) { + args.node = node; + onPreProcess.dispatch(self, args); + } + + // Setup serializer + htmlSerializer = new tinymce.html.Serializer(settings, schema); + + // Parse and serialize HTML + args.content = htmlSerializer.serialize( + htmlParser.parse(args.getInner ? node.innerHTML : tinymce.trim(dom.getOuterHTML(node), args), args) + ); + + // Replace all BOM characters for now until we can find a better solution + if (!args.cleanup) + args.content = args.content.replace(/\uFEFF/g, ''); + + // Post process + if (!args.no_events) + onPostProcess.dispatch(self, args); + + // Restore the old document if it was changed + if (oldDoc) + dom.doc = oldDoc; + + args.node = null; + + return args.content; + }, + + addRules : function(rules) { + schema.addValidElements(rules); + }, + + setRules : function(rules) { + schema.setValidElements(rules); + } + }; + }; +})(tinymce); +(function(tinymce) { + tinymce.dom.ScriptLoader = function(settings) { + var QUEUED = 0, + LOADING = 1, + LOADED = 2, + states = {}, + queue = [], + scriptLoadedCallbacks = {}, + queueLoadedCallbacks = [], + loading = 0, + undefined; + + function loadScript(url, callback) { + var t = this, dom = tinymce.DOM, elm, uri, loc, id; + + // Execute callback when script is loaded + function done() { + dom.remove(id); + + if (elm) + elm.onreadystatechange = elm.onload = elm = null; + + callback(); + }; + + function error() { + // Report the error so it's easier for people to spot loading errors + if (typeof(console) !== "undefined" && console.log) + console.log("Failed to load: " + url); + + // We can't mark it as done if there is a load error since + // A) We don't want to produce 404 errors on the server and + // B) the onerror event won't fire on all browsers. + // done(); + }; + + id = dom.uniqueId(); + + if (tinymce.isIE6) { + uri = new tinymce.util.URI(url); + loc = location; + + // If script is from same domain and we + // use IE 6 then use XHR since it's more reliable + if (uri.host == loc.hostname && uri.port == loc.port && (uri.protocol + ':') == loc.protocol && uri.protocol.toLowerCase() != 'file') { + tinymce.util.XHR.send({ + url : tinymce._addVer(uri.getURI()), + success : function(content) { + // Create new temp script element + var script = dom.create('script', { + type : 'text/javascript' + }); + + // Evaluate script in global scope + script.text = content; + document.getElementsByTagName('head')[0].appendChild(script); + dom.remove(script); + + done(); + }, + + error : error + }); + + return; + } + } + + // Create new script element + elm = dom.create('script', { + id : id, + type : 'text/javascript', + src : tinymce._addVer(url) + }); + + // Add onload listener for non IE browsers since IE9 + // fires onload event before the script is parsed and executed + if (!tinymce.isIE) + elm.onload = done; + + // Add onerror event will get fired on some browsers but not all of them + elm.onerror = error; + + // Opera 9.60 doesn't seem to fire the onreadystate event at correctly + if (!tinymce.isOpera) { + elm.onreadystatechange = function() { + var state = elm.readyState; + + // Loaded state is passed on IE 6 however there + // are known issues with this method but we can't use + // XHR in a cross domain loading + if (state == 'complete' || state == 'loaded') + done(); + }; + } + + // Most browsers support this feature so we report errors + // for those at least to help users track their missing plugins etc + // todo: Removed since it produced error if the document is unloaded by navigating away, re-add it as an option + /*elm.onerror = function() { + alert('Failed to load: ' + url); + };*/ + + // Add script to document + (document.getElementsByTagName('head')[0] || document.body).appendChild(elm); + }; + + this.isDone = function(url) { + return states[url] == LOADED; + }; + + this.markDone = function(url) { + states[url] = LOADED; + }; + + this.add = this.load = function(url, callback, scope) { + var item, state = states[url]; + + // Add url to load queue + if (state == undefined) { + queue.push(url); + states[url] = QUEUED; + } + + if (callback) { + // Store away callback for later execution + if (!scriptLoadedCallbacks[url]) + scriptLoadedCallbacks[url] = []; + + scriptLoadedCallbacks[url].push({ + func : callback, + scope : scope || this + }); + } + }; + + this.loadQueue = function(callback, scope) { + this.loadScripts(queue, callback, scope); + }; + + this.loadScripts = function(scripts, callback, scope) { + var loadScripts; + + function execScriptLoadedCallbacks(url) { + // Execute URL callback functions + tinymce.each(scriptLoadedCallbacks[url], function(callback) { + callback.func.call(callback.scope); + }); + + scriptLoadedCallbacks[url] = undefined; + }; + + queueLoadedCallbacks.push({ + func : callback, + scope : scope || this + }); + + loadScripts = function() { + var loadingScripts = tinymce.grep(scripts); + + // Current scripts has been handled + scripts.length = 0; + + // Load scripts that needs to be loaded + tinymce.each(loadingScripts, function(url) { + // Script is already loaded then execute script callbacks directly + if (states[url] == LOADED) { + execScriptLoadedCallbacks(url); + return; + } + + // Is script not loading then start loading it + if (states[url] != LOADING) { + states[url] = LOADING; + loading++; + + loadScript(url, function() { + states[url] = LOADED; + loading--; + + execScriptLoadedCallbacks(url); + + // Load more scripts if they where added by the recently loaded script + loadScripts(); + }); + } + }); + + // No scripts are currently loading then execute all pending queue loaded callbacks + if (!loading) { + tinymce.each(queueLoadedCallbacks, function(callback) { + callback.func.call(callback.scope); + }); + + queueLoadedCallbacks.length = 0; + } + }; + + loadScripts(); + }; + }; + + // Global script loader + tinymce.ScriptLoader = new tinymce.dom.ScriptLoader(); +})(tinymce); + +tinymce.dom.TreeWalker = function(start_node, root_node) { + var node = start_node; + + function findSibling(node, start_name, sibling_name, shallow) { + var sibling, parent; + + if (node) { + // Walk into nodes if it has a start + if (!shallow && node[start_name]) + return node[start_name]; + + // Return the sibling if it has one + if (node != root_node) { + sibling = node[sibling_name]; + if (sibling) + return sibling; + + // Walk up the parents to look for siblings + for (parent = node.parentNode; parent && parent != root_node; parent = parent.parentNode) { + sibling = parent[sibling_name]; + if (sibling) + return sibling; + } + } + } + }; + + this.current = function() { + return node; + }; + + this.next = function(shallow) { + return (node = findSibling(node, 'firstChild', 'nextSibling', shallow)); + }; + + this.prev = function(shallow) { + return (node = findSibling(node, 'lastChild', 'previousSibling', shallow)); + }; +}; + +(function(tinymce) { + tinymce.dom.RangeUtils = function(dom) { + var INVISIBLE_CHAR = '\uFEFF'; + + this.walk = function(rng, callback) { + var startContainer = rng.startContainer, + startOffset = rng.startOffset, + endContainer = rng.endContainer, + endOffset = rng.endOffset, + ancestor, startPoint, + endPoint, node, parent, siblings, nodes; + + // Handle table cell selection the table plugin enables + // you to fake select table cells and perform formatting actions on them + nodes = dom.select('td.mceSelected,th.mceSelected'); + if (nodes.length > 0) { + tinymce.each(nodes, function(node) { + callback([node]); + }); + + return; + } + + function collectSiblings(node, name, end_node) { + var siblings = []; + + for (; node && node != end_node; node = node[name]) + siblings.push(node); + + return siblings; + }; + + function findEndPoint(node, root) { + do { + if (node.parentNode == root) + return node; + + node = node.parentNode; + } while(node); + }; + + function walkBoundary(start_node, end_node, next) { + var siblingName = next ? 'nextSibling' : 'previousSibling'; + + for (node = start_node, parent = node.parentNode; node && node != end_node; node = parent) { + parent = node.parentNode; + siblings = collectSiblings(node == start_node ? node : node[siblingName], siblingName); + + if (siblings.length) { + if (!next) + siblings.reverse(); + + callback(siblings); + } + } + }; + + // If index based start position then resolve it + if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) + startContainer = startContainer.childNodes[startOffset]; + + // If index based end position then resolve it + if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) + endContainer = endContainer.childNodes[Math.min(endOffset - 1, endContainer.childNodes.length - 1)]; + + // Find common ancestor and end points + ancestor = dom.findCommonAncestor(startContainer, endContainer); + + // Same container + if (startContainer == endContainer) + return callback([startContainer]); + + // Process left side + for (node = startContainer; node; node = node.parentNode) { + if (node == endContainer) + return walkBoundary(startContainer, ancestor, true); + + if (node == ancestor) + break; + } + + // Process right side + for (node = endContainer; node; node = node.parentNode) { + if (node == startContainer) + return walkBoundary(endContainer, ancestor); + + if (node == ancestor) + break; + } + + // Find start/end point + startPoint = findEndPoint(startContainer, ancestor) || startContainer; + endPoint = findEndPoint(endContainer, ancestor) || endContainer; + + // Walk left leaf + walkBoundary(startContainer, startPoint, true); + + // Walk the middle from start to end point + siblings = collectSiblings( + startPoint == startContainer ? startPoint : startPoint.nextSibling, + 'nextSibling', + endPoint == endContainer ? endPoint.nextSibling : endPoint + ); + + if (siblings.length) + callback(siblings); + + // Walk right leaf + walkBoundary(endContainer, endPoint); + }; + + /* this.split = function(rng) { + var startContainer = rng.startContainer, + startOffset = rng.startOffset, + endContainer = rng.endContainer, + endOffset = rng.endOffset; + + function splitText(node, offset) { + if (offset == node.nodeValue.length) + node.appendData(INVISIBLE_CHAR); + + node = node.splitText(offset); + + if (node.nodeValue === INVISIBLE_CHAR) + node.nodeValue = ''; + + return node; + }; + + // Handle single text node + if (startContainer == endContainer) { + if (startContainer.nodeType == 3) { + if (startOffset != 0) + startContainer = endContainer = splitText(startContainer, startOffset); + + if (endOffset - startOffset != startContainer.nodeValue.length) + splitText(startContainer, endOffset - startOffset); + } + } else { + // Split startContainer text node if needed + if (startContainer.nodeType == 3 && startOffset != 0) { + startContainer = splitText(startContainer, startOffset); + startOffset = 0; + } + + // Split endContainer text node if needed + if (endContainer.nodeType == 3 && endOffset != endContainer.nodeValue.length) { + endContainer = splitText(endContainer, endOffset).previousSibling; + endOffset = endContainer.nodeValue.length; + } + } + + return { + startContainer : startContainer, + startOffset : startOffset, + endContainer : endContainer, + endOffset : endOffset + }; + }; +*/ + }; + + tinymce.dom.RangeUtils.compareRanges = function(rng1, rng2) { + if (rng1 && rng2) { + // Compare native IE ranges + if (rng1.item || rng1.duplicate) { + // Both are control ranges and the selected element matches + if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0)) + return true; + + // Both are text ranges and the range matches + if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1)) + return true; + } else { + // Compare w3c ranges + return rng1.startContainer == rng2.startContainer && rng1.startOffset == rng2.startOffset; + } + } + + return false; + }; +})(tinymce); + +(function(tinymce) { + var Event = tinymce.dom.Event, each = tinymce.each; + + tinymce.create('tinymce.ui.KeyboardNavigation', { + KeyboardNavigation: function(settings, dom) { + var t = this, root = settings.root, items = settings.items, + enableUpDown = settings.enableUpDown, enableLeftRight = settings.enableLeftRight || !settings.enableUpDown, + excludeFromTabOrder = settings.excludeFromTabOrder, + itemFocussed, itemBlurred, rootKeydown, rootFocussed, focussedId; + + dom = dom || tinymce.DOM; + + itemFocussed = function(evt) { + focussedId = evt.target.id; + }; + + itemBlurred = function(evt) { + dom.setAttrib(evt.target.id, 'tabindex', '-1'); + }; + + rootFocussed = function(evt) { + var item = dom.get(focussedId); + dom.setAttrib(item, 'tabindex', '0'); + item.focus(); + }; + + t.focus = function() { + dom.get(focussedId).focus(); + }; + + t.destroy = function() { + each(items, function(item) { + dom.unbind(dom.get(item.id), 'focus', itemFocussed); + dom.unbind(dom.get(item.id), 'blur', itemBlurred); + }); + + dom.unbind(dom.get(root), 'focus', rootFocussed); + dom.unbind(dom.get(root), 'keydown', rootKeydown); + + items = dom = root = t.focus = itemFocussed = itemBlurred = rootKeydown = rootFocussed = null; + t.destroy = function() {}; + }; + + t.moveFocus = function(dir, evt) { + var idx = -1, controls = t.controls, newFocus; + + if (!focussedId) + return; + + each(items, function(item, index) { + if (item.id === focussedId) { + idx = index; + return false; + } + }); + + idx += dir; + if (idx < 0) { + idx = items.length - 1; + } else if (idx >= items.length) { + idx = 0; + } + + newFocus = items[idx]; + dom.setAttrib(focussedId, 'tabindex', '-1'); + dom.setAttrib(newFocus.id, 'tabindex', '0'); + dom.get(newFocus.id).focus(); + + if (settings.actOnFocus) { + settings.onAction(newFocus.id); + } + + if (evt) + Event.cancel(evt); + }; + + rootKeydown = function(evt) { + var DOM_VK_LEFT = 37, DOM_VK_RIGHT = 39, DOM_VK_UP = 38, DOM_VK_DOWN = 40, DOM_VK_ESCAPE = 27, DOM_VK_ENTER = 14, DOM_VK_RETURN = 13, DOM_VK_SPACE = 32; + + switch (evt.keyCode) { + case DOM_VK_LEFT: + if (enableLeftRight) t.moveFocus(-1); + break; + + case DOM_VK_RIGHT: + if (enableLeftRight) t.moveFocus(1); + break; + + case DOM_VK_UP: + if (enableUpDown) t.moveFocus(-1); + break; + + case DOM_VK_DOWN: + if (enableUpDown) t.moveFocus(1); + break; + + case DOM_VK_ESCAPE: + if (settings.onCancel) { + settings.onCancel(); + Event.cancel(evt); + } + break; + + case DOM_VK_ENTER: + case DOM_VK_RETURN: + case DOM_VK_SPACE: + if (settings.onAction) { + settings.onAction(focussedId); + Event.cancel(evt); + } + break; + } + }; + + // Set up state and listeners for each item. + each(items, function(item, idx) { + var tabindex; + + if (!item.id) { + item.id = dom.uniqueId('_mce_item_'); + } + + if (excludeFromTabOrder) { + dom.bind(item.id, 'blur', itemBlurred); + tabindex = '-1'; + } else { + tabindex = (idx === 0 ? '0' : '-1'); + } + + dom.setAttrib(item.id, 'tabindex', tabindex); + dom.bind(dom.get(item.id), 'focus', itemFocussed); + }); + + // Setup initial state for root element. + if (items[0]){ + focussedId = items[0].id; + } + + dom.setAttrib(root, 'tabindex', '-1'); + + // Setup listeners for root element. + dom.bind(dom.get(root), 'focus', rootFocussed); + dom.bind(dom.get(root), 'keydown', rootKeydown); + } + }); +})(tinymce); + +(function(tinymce) { + // Shorten class names + var DOM = tinymce.DOM, is = tinymce.is; + + tinymce.create('tinymce.ui.Control', { + Control : function(id, s, editor) { + this.id = id; + this.settings = s = s || {}; + this.rendered = false; + this.onRender = new tinymce.util.Dispatcher(this); + this.classPrefix = ''; + this.scope = s.scope || this; + this.disabled = 0; + this.active = 0; + this.editor = editor; + }, + + setAriaProperty : function(property, value) { + var element = DOM.get(this.id + '_aria') || DOM.get(this.id); + if (element) { + DOM.setAttrib(element, 'aria-' + property, !!value); + } + }, + + focus : function() { + DOM.get(this.id).focus(); + }, + + setDisabled : function(s) { + if (s != this.disabled) { + this.setAriaProperty('disabled', s); + + this.setState('Disabled', s); + this.setState('Enabled', !s); + this.disabled = s; + } + }, + + isDisabled : function() { + return this.disabled; + }, + + setActive : function(s) { + if (s != this.active) { + this.setState('Active', s); + this.active = s; + this.setAriaProperty('pressed', s); + } + }, + + isActive : function() { + return this.active; + }, + + setState : function(c, s) { + var n = DOM.get(this.id); + + c = this.classPrefix + c; + + if (s) + DOM.addClass(n, c); + else + DOM.removeClass(n, c); + }, + + isRendered : function() { + return this.rendered; + }, + + renderHTML : function() { + }, + + renderTo : function(n) { + DOM.setHTML(n, this.renderHTML()); + }, + + postRender : function() { + var t = this, b; + + // Set pending states + if (is(t.disabled)) { + b = t.disabled; + t.disabled = -1; + t.setDisabled(b); + } + + if (is(t.active)) { + b = t.active; + t.active = -1; + t.setActive(b); + } + }, + + remove : function() { + DOM.remove(this.id); + this.destroy(); + }, + + destroy : function() { + tinymce.dom.Event.clear(this.id); + } + }); +})(tinymce); +tinymce.create('tinymce.ui.Container:tinymce.ui.Control', { + Container : function(id, s, editor) { + this.parent(id, s, editor); + + this.controls = []; + + this.lookup = {}; + }, + + add : function(c) { + this.lookup[c.id] = c; + this.controls.push(c); + + return c; + }, + + get : function(n) { + return this.lookup[n]; + } +}); + + +tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { + Separator : function(id, s) { + this.parent(id, s); + this.classPrefix = 'mceSeparator'; + this.setDisabled(true); + }, + + renderHTML : function() { + return tinymce.DOM.createHTML('span', {'class' : this.classPrefix, role : 'separator', 'aria-orientation' : 'vertical', tabindex : '-1'}); + } +}); + +(function(tinymce) { + var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk; + + tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', { + MenuItem : function(id, s) { + this.parent(id, s); + this.classPrefix = 'mceMenuItem'; + }, + + setSelected : function(s) { + this.setState('Selected', s); + this.setAriaProperty('checked', !!s); + this.selected = s; + }, + + isSelected : function() { + return this.selected; + }, + + postRender : function() { + var t = this; + + t.parent(); + + // Set pending state + if (is(t.selected)) + t.setSelected(t.selected); + } + }); +})(tinymce); + +(function(tinymce) { + var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk; + + tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', { + Menu : function(id, s) { + var t = this; + + t.parent(id, s); + t.items = {}; + t.collapsed = false; + t.menuCount = 0; + t.onAddItem = new tinymce.util.Dispatcher(this); + }, + + expand : function(d) { + var t = this; + + if (d) { + walk(t, function(o) { + if (o.expand) + o.expand(); + }, 'items', t); + } + + t.collapsed = false; + }, + + collapse : function(d) { + var t = this; + + if (d) { + walk(t, function(o) { + if (o.collapse) + o.collapse(); + }, 'items', t); + } + + t.collapsed = true; + }, + + isCollapsed : function() { + return this.collapsed; + }, + + add : function(o) { + if (!o.settings) + o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o); + + this.onAddItem.dispatch(this, o); + + return this.items[o.id] = o; + }, + + addSeparator : function() { + return this.add({separator : true}); + }, + + addMenu : function(o) { + if (!o.collapse) + o = this.createMenu(o); + + this.menuCount++; + + return this.add(o); + }, + + hasMenus : function() { + return this.menuCount !== 0; + }, + + remove : function(o) { + delete this.items[o.id]; + }, + + removeAll : function() { + var t = this; + + walk(t, function(o) { + if (o.removeAll) + o.removeAll(); + else + o.remove(); + + o.destroy(); + }, 'items', t); + + t.items = {}; + }, + + createMenu : function(o) { + var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o); + + m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem); + + return m; + } + }); +})(tinymce); +(function(tinymce) { + var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element; + + tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', { + DropMenu : function(id, s) { + s = s || {}; + s.container = s.container || DOM.doc.body; + s.offset_x = s.offset_x || 0; + s.offset_y = s.offset_y || 0; + s.vp_offset_x = s.vp_offset_x || 0; + s.vp_offset_y = s.vp_offset_y || 0; + + if (is(s.icons) && !s.icons) + s['class'] += ' mceNoIcons'; + + this.parent(id, s); + this.onShowMenu = new tinymce.util.Dispatcher(this); + this.onHideMenu = new tinymce.util.Dispatcher(this); + this.classPrefix = 'mceMenu'; + }, + + createMenu : function(s) { + var t = this, cs = t.settings, m; + + s.container = s.container || cs.container; + s.parent = t; + s.constrain = s.constrain || cs.constrain; + s['class'] = s['class'] || cs['class']; + s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x; + s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y; + s.keyboard_focus = cs.keyboard_focus; + m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s); + + m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem); + + return m; + }, + + focus : function() { + var t = this; + if (t.keyboardNav) { + t.keyboardNav.focus(); + } + }, + + update : function() { + var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th; + + tw = s.max_width ? Math.min(tb.clientWidth, s.max_width) : tb.clientWidth; + th = s.max_height ? Math.min(tb.clientHeight, s.max_height) : tb.clientHeight; + + if (!DOM.boxModel) + t.element.setStyles({width : tw + 2, height : th + 2}); + else + t.element.setStyles({width : tw, height : th}); + + if (s.max_width) + DOM.setStyle(co, 'width', tw); + + if (s.max_height) { + DOM.setStyle(co, 'height', th); + + if (tb.clientHeight < s.max_height) + DOM.setStyle(co, 'overflow', 'hidden'); + } + }, + + showMenu : function(x, y, px) { + var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb, cp = t.classPrefix; + + t.collapse(1); + + if (t.isMenuVisible) + return; + + if (!t.rendered) { + co = DOM.add(t.settings.container, t.renderNode()); + + each(t.items, function(o) { + o.postRender(); + }); + + t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container}); + } else + co = DOM.get('menu_' + t.id); + + // Move layer out of sight unless it's Opera since it scrolls to top of page due to an bug + if (!tinymce.isOpera) + DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF}); + + DOM.show(co); + t.update(); + + x += s.offset_x || 0; + y += s.offset_y || 0; + vp.w -= 4; + vp.h -= 4; + + // Move inside viewport if not submenu + if (s.constrain) { + w = co.clientWidth - ot; + h = co.clientHeight - ot; + mx = vp.x + vp.w; + my = vp.y + vp.h; + + if ((x + s.vp_offset_x + w) > mx) + x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w); + + if ((y + s.vp_offset_y + h) > my) + y = Math.max(0, (my - s.vp_offset_y) - h); + } + + DOM.setStyles(co, {left : x , top : y}); + t.element.update(); + + t.isMenuVisible = 1; + t.mouseClickFunc = Event.add(co, 'click', function(e) { + var m; + + e = e.target; + + if (e && (e = DOM.getParent(e, 'tr')) && !DOM.hasClass(e, cp + 'ItemSub')) { + m = t.items[e.id]; + + if (m.isDisabled()) + return; + + dm = t; + + while (dm) { + if (dm.hideMenu) + dm.hideMenu(); + + dm = dm.settings.parent; + } + + if (m.settings.onclick) + m.settings.onclick(e); + + return Event.cancel(e); // Cancel to fix onbeforeunload problem + } + }); + + if (t.hasMenus()) { + t.mouseOverFunc = Event.add(co, 'mouseover', function(e) { + var m, r, mi; + + e = e.target; + if (e && (e = DOM.getParent(e, 'tr'))) { + m = t.items[e.id]; + + if (t.lastMenu) + t.lastMenu.collapse(1); + + if (m.isDisabled()) + return; + + if (e && DOM.hasClass(e, cp + 'ItemSub')) { + //p = DOM.getPos(s.container); + r = DOM.getRect(e); + m.showMenu((r.x + r.w - ot), r.y - ot, r.x); + t.lastMenu = m; + DOM.addClass(DOM.get(m.id).firstChild, cp + 'ItemActive'); + } + } + }); + } + + Event.add(co, 'keydown', t._keyHandler, t); + + t.onShowMenu.dispatch(t); + + if (s.keyboard_focus) { + t._setupKeyboardNav(); + } + }, + + hideMenu : function(c) { + var t = this, co = DOM.get('menu_' + t.id), e; + + if (!t.isMenuVisible) + return; + + if (t.keyboardNav) t.keyboardNav.destroy(); + Event.remove(co, 'mouseover', t.mouseOverFunc); + Event.remove(co, 'click', t.mouseClickFunc); + Event.remove(co, 'keydown', t._keyHandler); + DOM.hide(co); + t.isMenuVisible = 0; + + if (!c) + t.collapse(1); + + if (t.element) + t.element.hide(); + + if (e = DOM.get(t.id)) + DOM.removeClass(e.firstChild, t.classPrefix + 'ItemActive'); + + t.onHideMenu.dispatch(t); + }, + + add : function(o) { + var t = this, co; + + o = t.parent(o); + + if (t.isRendered && (co = DOM.get('menu_' + t.id))) + t._add(DOM.select('tbody', co)[0], o); + + return o; + }, + + collapse : function(d) { + this.parent(d); + this.hideMenu(1); + }, + + remove : function(o) { + DOM.remove(o.id); + this.destroy(); + + return this.parent(o); + }, + + destroy : function() { + var t = this, co = DOM.get('menu_' + t.id); + + if (t.keyboardNav) t.keyboardNav.destroy(); + Event.remove(co, 'mouseover', t.mouseOverFunc); + Event.remove(DOM.select('a', co), 'focus', t.mouseOverFunc); + Event.remove(co, 'click', t.mouseClickFunc); + Event.remove(co, 'keydown', t._keyHandler); + + if (t.element) + t.element.remove(); + + DOM.remove(co); + }, + + renderNode : function() { + var t = this, s = t.settings, n, tb, co, w; + + w = DOM.create('div', {role: 'listbox', id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:200000;outline:0'}); + if (t.settings.parent) { + DOM.setAttrib(w, 'aria-parent', 'menu_' + t.settings.parent.id); + } + co = DOM.add(w, 'div', {role: 'presentation', id : 'menu_' + t.id + '_co', 'class' : t.classPrefix + (s['class'] ? ' ' + s['class'] : '')}); + t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container}); + + if (s.menu_line) + DOM.add(co, 'span', {'class' : t.classPrefix + 'Line'}); + +// n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'}); + n = DOM.add(co, 'table', {role: 'presentation', id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0}); + tb = DOM.add(n, 'tbody'); + + each(t.items, function(o) { + t._add(tb, o); + }); + + t.rendered = true; + + return w; + }, + + // Internal functions + _setupKeyboardNav : function(){ + var contextMenu, menuItems, t=this; + contextMenu = DOM.select('#menu_' + t.id)[0]; + menuItems = DOM.select('a[role=option]', 'menu_' + t.id); + menuItems.splice(0,0,contextMenu); + t.keyboardNav = new tinymce.ui.KeyboardNavigation({ + root: 'menu_' + t.id, + items: menuItems, + onCancel: function() { + t.hideMenu(); + }, + enableUpDown: true + }); + contextMenu.focus(); + }, + + _keyHandler : function(evt) { + var t = this, e; + switch (evt.keyCode) { + case 37: // Left + if (t.settings.parent) { + t.hideMenu(); + t.settings.parent.focus(); + Event.cancel(evt); + } + break; + case 39: // Right + if (t.mouseOverFunc) + t.mouseOverFunc(evt); + break; + } + }, + + _add : function(tb, o) { + var n, s = o.settings, a, ro, it, cp = this.classPrefix, ic; + + if (s.separator) { + ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'ItemSeparator'}); + DOM.add(ro, 'td', {'class' : cp + 'ItemSeparator'}); + + if (n = ro.previousSibling) + DOM.addClass(n, 'mceLast'); + + return; + } + + n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'Item ' + cp + 'ItemEnabled'}); + n = it = DOM.add(n, s.titleItem ? 'th' : 'td'); + n = a = DOM.add(n, 'a', {id: o.id + '_aria', role: s.titleItem ? 'presentation' : 'option', href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'}); + + if (s.parent) { + DOM.setAttrib(a, 'aria-haspopup', 'true'); + DOM.setAttrib(a, 'aria-owns', 'menu_' + o.id); + } + + DOM.addClass(it, s['class']); +// n = DOM.add(n, 'span', {'class' : 'item'}); + + ic = DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')}); + + if (s.icon_src) + DOM.add(ic, 'img', {src : s.icon_src}); + + n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title); + + if (o.settings.style) + DOM.setAttrib(n, 'style', o.settings.style); + + if (tb.childNodes.length == 1) + DOM.addClass(ro, 'mceFirst'); + + if ((n = ro.previousSibling) && DOM.hasClass(n, cp + 'ItemSeparator')) + DOM.addClass(ro, 'mceFirst'); + + if (o.collapse) + DOM.addClass(ro, cp + 'ItemSub'); + + if (n = ro.previousSibling) + DOM.removeClass(n, 'mceLast'); + + DOM.addClass(ro, 'mceLast'); + } + }); +})(tinymce); +(function(tinymce) { + var DOM = tinymce.DOM; + + tinymce.create('tinymce.ui.Button:tinymce.ui.Control', { + Button : function(id, s, ed) { + this.parent(id, s, ed); + this.classPrefix = 'mceButton'; + }, + + renderHTML : function() { + var cp = this.classPrefix, s = this.settings, h, l; + + l = DOM.encode(s.label || ''); + h = '<a role="button" id="' + this.id + '" href="javascript:;" class="' + cp + ' ' + cp + 'Enabled ' + s['class'] + (l ? ' ' + cp + 'Labeled' : '') +'" onmousedown="return false;" onclick="return false;" aria-labelledby="' + this.id + '_voice" title="' + DOM.encode(s.title) + '">'; + if (s.image && !(this.editor &&this.editor.forcedHighContrastMode) ) + h += '<img class="mceIcon" src="' + s.image + '" alt="' + DOM.encode(s.title) + '" />' + l; + else + h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : ''); + + h += '<span class="mceVoiceLabel mceIconOnly" style="display: none;" id="' + this.id + '_voice">' + s.title + '</span>'; + h += '</a>'; + return h; + }, + + postRender : function() { + var t = this, s = t.settings; + + tinymce.dom.Event.add(t.id, 'click', function(e) { + if (!t.isDisabled()) + return s.onclick.call(s.scope, e); + }); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher; + + tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', { + ListBox : function(id, s, ed) { + var t = this; + + t.parent(id, s, ed); + + t.items = []; + + t.onChange = new Dispatcher(t); + + t.onPostRender = new Dispatcher(t); + + t.onAdd = new Dispatcher(t); + + t.onRenderMenu = new tinymce.util.Dispatcher(this); + + t.classPrefix = 'mceListBox'; + }, + + select : function(va) { + var t = this, fv, f; + + if (va == undefined) + return t.selectByIndex(-1); + + // Is string or number make function selector + if (va && va.call) + f = va; + else { + f = function(v) { + return v == va; + }; + } + + // Do we need to do something? + if (va != t.selectedValue) { + // Find item + each(t.items, function(o, i) { + if (f(o.value)) { + fv = 1; + t.selectByIndex(i); + return false; + } + }); + + if (!fv) + t.selectByIndex(-1); + } + }, + + selectByIndex : function(idx) { + var t = this, e, o, label; + + if (idx != t.selectedIndex) { + e = DOM.get(t.id + '_text'); + label = DOM.get(t.id + '_voiceDesc'); + o = t.items[idx]; + + if (o) { + t.selectedValue = o.value; + t.selectedIndex = idx; + DOM.setHTML(e, DOM.encode(o.title)); + DOM.setHTML(label, t.settings.title + " - " + o.title); + DOM.removeClass(e, 'mceTitle'); + DOM.setAttrib(t.id, 'aria-valuenow', o.title); + } else { + DOM.setHTML(e, DOM.encode(t.settings.title)); + DOM.setHTML(label, DOM.encode(t.settings.title)); + DOM.addClass(e, 'mceTitle'); + t.selectedValue = t.selectedIndex = null; + DOM.setAttrib(t.id, 'aria-valuenow', t.settings.title); + } + e = 0; + } + }, + + add : function(n, v, o) { + var t = this; + + o = o || {}; + o = tinymce.extend(o, { + title : n, + value : v + }); + + t.items.push(o); + t.onAdd.dispatch(t, o); + }, + + getLength : function() { + return this.items.length; + }, + + renderHTML : function() { + var h = '', t = this, s = t.settings, cp = t.classPrefix; + + h = '<span role="listbox" aria-haspopup="true" aria-labelledby="' + t.id +'_voiceDesc" aria-describedby="' + t.id + '_voiceDesc"><table role="presentation" tabindex="0" id="' + t.id + '" cellpadding="0" cellspacing="0" class="' + cp + ' ' + cp + 'Enabled' + (s['class'] ? (' ' + s['class']) : '') + '"><tbody><tr>'; + h += '<td>' + DOM.createHTML('span', {id: t.id + '_voiceDesc', 'class': 'voiceLabel', style:'display:none;'}, t.settings.title); + h += DOM.createHTML('a', {id : t.id + '_text', tabindex : -1, href : 'javascript:;', 'class' : 'mceText', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + '</td>'; + h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', tabindex : -1, href : 'javascript:;', 'class' : 'mceOpen', onclick : "return false;", onmousedown : 'return false;'}, '<span><span style="display:none;" class="mceIconOnly" aria-hidden="true">\u25BC</span></span>') + '</td>'; + h += '</tr></tbody></table></span>'; + + return h; + }, + + showMenu : function() { + var t = this, p2, e = DOM.get(this.id), m; + + if (t.isDisabled() || t.items.length == 0) + return; + + if (t.menu && t.menu.isMenuVisible) + return t.hideMenu(); + + if (!t.isMenuRendered) { + t.renderMenu(); + t.isMenuRendered = true; + } + + p2 = DOM.getPos(e); + + m = t.menu; + m.settings.offset_x = p2.x; + m.settings.offset_y = p2.y; + m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus + + // Select in menu + if (t.oldID) + m.items[t.oldID].setSelected(0); + + each(t.items, function(o) { + if (o.value === t.selectedValue) { + m.items[o.id].setSelected(1); + t.oldID = o.id; + } + }); + + m.showMenu(0, e.clientHeight); + + Event.add(DOM.doc, 'mousedown', t.hideMenu, t); + DOM.addClass(t.id, t.classPrefix + 'Selected'); + + //DOM.get(t.id + '_text').focus(); + }, + + hideMenu : function(e) { + var t = this; + + if (t.menu && t.menu.isMenuVisible) { + DOM.removeClass(t.id, t.classPrefix + 'Selected'); + + // Prevent double toogles by canceling the mouse click event to the button + if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open')) + return; + + if (!e || !DOM.getParent(e.target, '.mceMenu')) { + DOM.removeClass(t.id, t.classPrefix + 'Selected'); + Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); + t.menu.hideMenu(); + } + } + }, + + renderMenu : function() { + var t = this, m; + + m = t.settings.control_manager.createDropMenu(t.id + '_menu', { + menu_line : 1, + 'class' : t.classPrefix + 'Menu mceNoIcons', + max_width : 150, + max_height : 150 + }); + + m.onHideMenu.add(function() { + t.hideMenu(); + t.focus(); + }); + + m.add({ + title : t.settings.title, + 'class' : 'mceMenuItemTitle', + onclick : function() { + if (t.settings.onselect('') !== false) + t.select(''); // Must be runned after + } + }); + + each(t.items, function(o) { + // No value then treat it as a title + if (o.value === undefined) { + m.add({ + title : o.title, + role : "option", + 'class' : 'mceMenuItemTitle', + onclick : function() { + if (t.settings.onselect('') !== false) + t.select(''); // Must be runned after + } + }); + } else { + o.id = DOM.uniqueId(); + o.role= "option"; + o.onclick = function() { + if (t.settings.onselect(o.value) !== false) + t.select(o.value); // Must be runned after + }; + + m.add(o); + } + }); + + t.onRenderMenu.dispatch(t, m); + t.menu = m; + }, + + postRender : function() { + var t = this, cp = t.classPrefix; + + Event.add(t.id, 'click', t.showMenu, t); + Event.add(t.id, 'keydown', function(evt) { + if (evt.keyCode == 32) { // Space + t.showMenu(evt); + Event.cancel(evt); + } + }); + Event.add(t.id, 'focus', function() { + if (!t._focused) { + t.keyDownHandler = Event.add(t.id, 'keydown', function(e) { + if (e.keyCode == 40) { + t.showMenu(); + Event.cancel(e); + } + }); + t.keyPressHandler = Event.add(t.id, 'keypress', function(e) { + var v; + if (e.keyCode == 13) { + // Fake select on enter + v = t.selectedValue; + t.selectedValue = null; // Needs to be null to fake change + Event.cancel(e); + t.settings.onselect(v); + } + }); + } + + t._focused = 1; + }); + Event.add(t.id, 'blur', function() { + Event.remove(t.id, 'keydown', t.keyDownHandler); + Event.remove(t.id, 'keypress', t.keyPressHandler); + t._focused = 0; + }); + + // Old IE doesn't have hover on all elements + if (tinymce.isIE6 || !DOM.boxModel) { + Event.add(t.id, 'mouseover', function() { + if (!DOM.hasClass(t.id, cp + 'Disabled')) + DOM.addClass(t.id, cp + 'Hover'); + }); + + Event.add(t.id, 'mouseout', function() { + if (!DOM.hasClass(t.id, cp + 'Disabled')) + DOM.removeClass(t.id, cp + 'Hover'); + }); + } + + t.onPostRender.dispatch(t, DOM.get(t.id)); + }, + + destroy : function() { + this.parent(); + + Event.clear(this.id + '_text'); + Event.clear(this.id + '_open'); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher; + + tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', { + NativeListBox : function(id, s) { + this.parent(id, s); + this.classPrefix = 'mceNativeListBox'; + }, + + setDisabled : function(s) { + DOM.get(this.id).disabled = s; + this.setAriaProperty('disabled', s); + }, + + isDisabled : function() { + return DOM.get(this.id).disabled; + }, + + select : function(va) { + var t = this, fv, f; + + if (va == undefined) + return t.selectByIndex(-1); + + // Is string or number make function selector + if (va && va.call) + f = va; + else { + f = function(v) { + return v == va; + }; + } + + // Do we need to do something? + if (va != t.selectedValue) { + // Find item + each(t.items, function(o, i) { + if (f(o.value)) { + fv = 1; + t.selectByIndex(i); + return false; + } + }); + + if (!fv) + t.selectByIndex(-1); + } + }, + + selectByIndex : function(idx) { + DOM.get(this.id).selectedIndex = idx + 1; + this.selectedValue = this.items[idx] ? this.items[idx].value : null; + }, + + add : function(n, v, a) { + var o, t = this; + + a = a || {}; + a.value = v; + + if (t.isRendered()) + DOM.add(DOM.get(this.id), 'option', a, n); + + o = { + title : n, + value : v, + attribs : a + }; + + t.items.push(o); + t.onAdd.dispatch(t, o); + }, + + getLength : function() { + return this.items.length; + }, + + renderHTML : function() { + var h, t = this; + + h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --'); + + each(t.items, function(it) { + h += DOM.createHTML('option', {value : it.value}, it.title); + }); + + h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox', 'aria-labelledby': t.id + '_aria'}, h); + h += DOM.createHTML('span', {id : t.id + '_aria', 'style': 'display: none'}, t.settings.title); + return h; + }, + + postRender : function() { + var t = this, ch, changeListenerAdded = true; + + t.rendered = true; + + function onChange(e) { + var v = t.items[e.target.selectedIndex - 1]; + + if (v && (v = v.value)) { + t.onChange.dispatch(t, v); + + if (t.settings.onselect) + t.settings.onselect(v); + } + }; + + Event.add(t.id, 'change', onChange); + + // Accessibility keyhandler + Event.add(t.id, 'keydown', function(e) { + var bf; + + Event.remove(t.id, 'change', ch); + changeListenerAdded = false; + + bf = Event.add(t.id, 'blur', function() { + if (changeListenerAdded) return; + changeListenerAdded = true; + Event.add(t.id, 'change', onChange); + Event.remove(t.id, 'blur', bf); + }); + + //prevent default left and right keys on chrome - so that the keyboard navigation is used. + if (tinymce.isWebKit && (e.keyCode==37 ||e.keyCode==39)) { + return Event.prevent(e); + } + + if (e.keyCode == 13 || e.keyCode == 32) { + onChange(e); + return Event.cancel(e); + } + }); + + t.onPostRender.dispatch(t, DOM.get(t.id)); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each; + + tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', { + MenuButton : function(id, s, ed) { + this.parent(id, s, ed); + + this.onRenderMenu = new tinymce.util.Dispatcher(this); + + s.menu_container = s.menu_container || DOM.doc.body; + }, + + showMenu : function() { + var t = this, p1, p2, e = DOM.get(t.id), m; + + if (t.isDisabled()) + return; + + if (!t.isMenuRendered) { + t.renderMenu(); + t.isMenuRendered = true; + } + + if (t.isMenuVisible) + return t.hideMenu(); + + p1 = DOM.getPos(t.settings.menu_container); + p2 = DOM.getPos(e); + + m = t.menu; + m.settings.offset_x = p2.x; + m.settings.offset_y = p2.y; + m.settings.vp_offset_x = p2.x; + m.settings.vp_offset_y = p2.y; + m.settings.keyboard_focus = t._focused; + m.showMenu(0, e.clientHeight); + + Event.add(DOM.doc, 'mousedown', t.hideMenu, t); + t.setState('Selected', 1); + + t.isMenuVisible = 1; + }, + + renderMenu : function() { + var t = this, m; + + m = t.settings.control_manager.createDropMenu(t.id + '_menu', { + menu_line : 1, + 'class' : this.classPrefix + 'Menu', + icons : t.settings.icons + }); + + m.onHideMenu.add(function() { + t.hideMenu(); + t.focus(); + }); + + t.onRenderMenu.dispatch(t, m); + t.menu = m; + }, + + hideMenu : function(e) { + var t = this; + + // Prevent double toogles by canceling the mouse click event to the button + if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';})) + return; + + if (!e || !DOM.getParent(e.target, '.mceMenu')) { + t.setState('Selected', 0); + Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); + if (t.menu) + t.menu.hideMenu(); + } + + t.isMenuVisible = 0; + }, + + postRender : function() { + var t = this, s = t.settings; + + Event.add(t.id, 'click', function() { + if (!t.isDisabled()) { + if (s.onclick) + s.onclick(t.value); + + t.showMenu(); + } + }); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each; + + tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', { + SplitButton : function(id, s, ed) { + this.parent(id, s, ed); + this.classPrefix = 'mceSplitButton'; + }, + + renderHTML : function() { + var h, t = this, s = t.settings, h1; + + h = '<tbody><tr>'; + + if (s.image) + h1 = DOM.createHTML('img ', {src : s.image, role: 'presentation', 'class' : 'mceAction ' + s['class']}); + else + h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, ''); + + h1 += DOM.createHTML('span', {'class': 'mceVoiceLabel mceIconOnly', id: t.id + '_voice', style: 'display:none;'}, s.title); + h += '<td >' + DOM.createHTML('a', {role: 'button', id : t.id + '_action', tabindex: '-1', href : 'javascript:;', 'class' : 'mceAction ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>'; + + h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']}, '<span style="display:none;" class="mceIconOnly" aria-hidden="true">\u25BC</span>'); + h += '<td >' + DOM.createHTML('a', {role: 'button', id : t.id + '_open', tabindex: '-1', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>'; + + h += '</tr></tbody>'; + h = DOM.createHTML('table', { role: 'presentation', 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', title : s.title}, h); + return DOM.createHTML('div', {id : t.id, role: 'button', tabindex: '0', 'aria-labelledby': t.id + '_voice', 'aria-haspopup': 'true'}, h); + }, + + postRender : function() { + var t = this, s = t.settings, activate; + + if (s.onclick) { + activate = function(evt) { + if (!t.isDisabled()) { + s.onclick(t.value); + Event.cancel(evt); + } + }; + Event.add(t.id + '_action', 'click', activate); + Event.add(t.id, ['click', 'keydown'], function(evt) { + var DOM_VK_SPACE = 32, DOM_VK_ENTER = 14, DOM_VK_RETURN = 13, DOM_VK_UP = 38, DOM_VK_DOWN = 40; + if ((evt.keyCode === 32 || evt.keyCode === 13 || evt.keyCode === 14) && !evt.altKey && !evt.ctrlKey && !evt.metaKey) { + activate(); + Event.cancel(evt); + } else if (evt.type === 'click' || evt.keyCode === DOM_VK_DOWN) { + t.showMenu(); + Event.cancel(evt); + } + }); + } + + Event.add(t.id + '_open', 'click', function (evt) { + t.showMenu(); + Event.cancel(evt); + }); + Event.add([t.id, t.id + '_open'], 'focus', function() {t._focused = 1;}); + Event.add([t.id, t.id + '_open'], 'blur', function() {t._focused = 0;}); + + // Old IE doesn't have hover on all elements + if (tinymce.isIE6 || !DOM.boxModel) { + Event.add(t.id, 'mouseover', function() { + if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled')) + DOM.addClass(t.id, 'mceSplitButtonHover'); + }); + + Event.add(t.id, 'mouseout', function() { + if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled')) + DOM.removeClass(t.id, 'mceSplitButtonHover'); + }); + } + }, + + destroy : function() { + this.parent(); + + Event.clear(this.id + '_action'); + Event.clear(this.id + '_open'); + Event.clear(this.id); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each; + + tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', { + ColorSplitButton : function(id, s, ed) { + var t = this; + + t.parent(id, s, ed); + + t.settings = s = tinymce.extend({ + colors : '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF', + grid_width : 8, + default_color : '#888888' + }, t.settings); + + t.onShowMenu = new tinymce.util.Dispatcher(t); + + t.onHideMenu = new tinymce.util.Dispatcher(t); + + t.value = s.default_color; + }, + + showMenu : function() { + var t = this, r, p, e, p2; + + if (t.isDisabled()) + return; + + if (!t.isMenuRendered) { + t.renderMenu(); + t.isMenuRendered = true; + } + + if (t.isMenuVisible) + return t.hideMenu(); + + e = DOM.get(t.id); + DOM.show(t.id + '_menu'); + DOM.addClass(e, 'mceSplitButtonSelected'); + p2 = DOM.getPos(e); + DOM.setStyles(t.id + '_menu', { + left : p2.x, + top : p2.y + e.clientHeight, + zIndex : 200000 + }); + e = 0; + + Event.add(DOM.doc, 'mousedown', t.hideMenu, t); + t.onShowMenu.dispatch(t); + + if (t._focused) { + t._keyHandler = Event.add(t.id + '_menu', 'keydown', function(e) { + if (e.keyCode == 27) + t.hideMenu(); + }); + + DOM.select('a', t.id + '_menu')[0].focus(); // Select first link + } + + t.isMenuVisible = 1; + }, + + hideMenu : function(e) { + var t = this; + + if (t.isMenuVisible) { + // Prevent double toogles by canceling the mouse click event to the button + if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';})) + return; + + if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) { + DOM.removeClass(t.id, 'mceSplitButtonSelected'); + Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); + Event.remove(t.id + '_menu', 'keydown', t._keyHandler); + DOM.hide(t.id + '_menu'); + } + + t.isMenuVisible = 0; + t.onHideMenu.dispatch(); + } + }, + + renderMenu : function() { + var t = this, m, i = 0, s = t.settings, n, tb, tr, w, context; + + w = DOM.add(s.menu_container, 'div', {role: 'listbox', id : t.id + '_menu', 'class' : s['menu_class'] + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'}); + m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'}); + DOM.add(m, 'span', {'class' : 'mceMenuLine'}); + + n = DOM.add(m, 'table', {role: 'presentation', 'class' : 'mceColorSplitMenu'}); + tb = DOM.add(n, 'tbody'); + + // Generate color grid + i = 0; + each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) { + c = c.replace(/^#/, ''); + + if (!i--) { + tr = DOM.add(tb, 'tr'); + i = s.grid_width - 1; + } + + n = DOM.add(tr, 'td'); + n = DOM.add(n, 'a', { + role : 'option', + href : 'javascript:;', + style : { + backgroundColor : '#' + c + }, + 'title': t.editor.getLang('colors.' + c, c), + 'data-mce-color' : '#' + c + }); + + if (t.editor.forcedHighContrastMode) { + n = DOM.add(n, 'canvas', { width: 16, height: 16, 'aria-hidden': 'true' }); + if (n.getContext && (context = n.getContext("2d"))) { + context.fillStyle = '#' + c; + context.fillRect(0, 0, 16, 16); + } else { + // No point leaving a canvas element around if it's not supported for drawing on anyway. + DOM.remove(n); + } + } + }); + + if (s.more_colors_func) { + n = DOM.add(tb, 'tr'); + n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'}); + n = DOM.add(n, 'a', {role: 'option', id : t.id + '_more', href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title); + + Event.add(n, 'click', function(e) { + s.more_colors_func.call(s.more_colors_scope || this); + return Event.cancel(e); // Cancel to fix onbeforeunload problem + }); + } + + DOM.addClass(m, 'mceColorSplitMenu'); + + new tinymce.ui.KeyboardNavigation({ + root: t.id + '_menu', + items: DOM.select('a', t.id + '_menu'), + onCancel: function() { + t.hideMenu(); + t.focus(); + } + }); + + // Prevent IE from scrolling and hindering click to occur #4019 + Event.add(t.id + '_menu', 'mousedown', function(e) {return Event.cancel(e);}); + + Event.add(t.id + '_menu', 'click', function(e) { + var c; + + e = DOM.getParent(e.target, 'a', tb); + + if (e && e.nodeName.toLowerCase() == 'a' && (c = e.getAttribute('data-mce-color'))) + t.setColor(c); + + return Event.cancel(e); // Prevent IE auto save warning + }); + + return w; + }, + + setColor : function(c) { + this.displayColor(c); + this.hideMenu(); + this.settings.onselect(c); + }, + + displayColor : function(c) { + var t = this; + + DOM.setStyle(t.id + '_preview', 'backgroundColor', c); + + t.value = c; + }, + + postRender : function() { + var t = this, id = t.id; + + t.parent(); + DOM.add(id + '_action', 'div', {id : id + '_preview', 'class' : 'mceColorPreview'}); + DOM.setStyle(t.id + '_preview', 'backgroundColor', t.value); + }, + + destroy : function() { + this.parent(); + + Event.clear(this.id + '_menu'); + Event.clear(this.id + '_more'); + DOM.remove(this.id + '_menu'); + } + }); +})(tinymce); + +(function(tinymce) { +// Shorten class names +var dom = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event; +tinymce.create('tinymce.ui.ToolbarGroup:tinymce.ui.Container', { + renderHTML : function() { + var t = this, h = [], controls = t.controls, each = tinymce.each, settings = t.settings; + + h.push('<div id="' + t.id + '" role="group" aria-labelledby="' + t.id + '_voice">'); + //TODO: ACC test this out - adding a role = application for getting the landmarks working well. + h.push("<span role='application'>"); + h.push('<span id="' + t.id + '_voice" class="mceVoiceLabel" style="display:none;">' + dom.encode(settings.name) + '</span>'); + each(controls, function(toolbar) { + h.push(toolbar.renderHTML()); + }); + h.push("</span>"); + h.push('</div>'); + + return h.join(''); + }, + + focus : function() { + var t = this; + dom.get(t.id).focus(); + }, + + postRender : function() { + var t = this, items = []; + + each(t.controls, function(toolbar) { + each (toolbar.controls, function(control) { + if (control.id) { + items.push(control); + } + }); + }); + + t.keyNav = new tinymce.ui.KeyboardNavigation({ + root: t.id, + items: items, + onCancel: function() { + //Move focus if webkit so that navigation back will read the item. + if (tinymce.isWebKit) { + dom.get(t.editor.id+"_ifr").focus(); + } + t.editor.focus(); + }, + excludeFromTabOrder: !t.settings.tab_focus_toolbar + }); + }, + + destroy : function() { + var self = this; + + self.parent(); + self.keyNav.destroy(); + Event.clear(self.id); + } +}); +})(tinymce); + +(function(tinymce) { +// Shorten class names +var dom = tinymce.DOM, each = tinymce.each; +tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { + renderHTML : function() { + var t = this, h = '', c, co, s = t.settings, i, pr, nx, cl; + + cl = t.controls; + for (i=0; i<cl.length; i++) { + // Get current control, prev control, next control and if the control is a list box or not + co = cl[i]; + pr = cl[i - 1]; + nx = cl[i + 1]; + + // Add toolbar start + if (i === 0) { + c = 'mceToolbarStart'; + + if (co.Button) + c += ' mceToolbarStartButton'; + else if (co.SplitButton) + c += ' mceToolbarStartSplitButton'; + else if (co.ListBox) + c += ' mceToolbarStartListBox'; + + h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->')); + } + + // Add toolbar end before list box and after the previous button + // This is to fix the o2k7 editor skins + if (pr && co.ListBox) { + if (pr.Button || pr.SplitButton) + h += dom.createHTML('td', {'class' : 'mceToolbarEnd'}, dom.createHTML('span', null, '<!-- IE -->')); + } + + // Render control HTML + + // IE 8 quick fix, needed to propertly generate a hit area for anchors + if (dom.stdMode) + h += '<td style="position: relative">' + co.renderHTML() + '</td>'; + else + h += '<td>' + co.renderHTML() + '</td>'; + + // Add toolbar start after list box and before the next button + // This is to fix the o2k7 editor skins + if (nx && co.ListBox) { + if (nx.Button || nx.SplitButton) + h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '<!-- IE -->')); + } + } + + c = 'mceToolbarEnd'; + + if (co.Button) + c += ' mceToolbarEndButton'; + else if (co.SplitButton) + c += ' mceToolbarEndSplitButton'; + else if (co.ListBox) + c += ' mceToolbarEndListBox'; + + h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->')); + + return dom.createHTML('table', {id : t.id, 'class' : 'mceToolbar' + (s['class'] ? ' ' + s['class'] : ''), cellpadding : '0', cellspacing : '0', align : t.settings.align || '', role: 'presentation', tabindex: '-1'}, '<tbody><tr>' + h + '</tr></tbody>'); + } +}); +})(tinymce); + +(function(tinymce) { + var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each; + + tinymce.create('tinymce.AddOnManager', { + AddOnManager : function() { + var self = this; + + self.items = []; + self.urls = {}; + self.lookup = {}; + self.onAdd = new Dispatcher(self); + }, + + get : function(n) { + if (this.lookup[n]) { + return this.lookup[n].instance; + } else { + return undefined; + } + }, + + dependencies : function(n) { + var result; + if (this.lookup[n]) { + result = this.lookup[n].dependencies; + } + return result || []; + }, + + requireLangPack : function(n) { + var s = tinymce.settings; + + if (s && s.language && s.language_load !== false) + tinymce.ScriptLoader.add(this.urls[n] + '/langs/' + s.language + '.js'); + }, + + add : function(id, o, dependencies) { + this.items.push(o); + this.lookup[id] = {instance:o, dependencies:dependencies}; + this.onAdd.dispatch(this, id, o); + + return o; + }, + createUrl: function(baseUrl, dep) { + if (typeof dep === "object") { + return dep + } else { + return {prefix: baseUrl.prefix, resource: dep, suffix: baseUrl.suffix}; + } + }, + + addComponents: function(pluginName, scripts) { + var pluginUrl = this.urls[pluginName]; + tinymce.each(scripts, function(script){ + tinymce.ScriptLoader.add(pluginUrl+"/"+script); + }); + }, + + load : function(n, u, cb, s) { + var t = this, url = u; + + function loadDependencies() { + var dependencies = t.dependencies(n); + tinymce.each(dependencies, function(dep) { + var newUrl = t.createUrl(u, dep); + t.load(newUrl.resource, newUrl, undefined, undefined); + }); + if (cb) { + if (s) { + cb.call(s); + } else { + cb.call(tinymce.ScriptLoader); + } + } + } + + if (t.urls[n]) + return; + if (typeof u === "object") + url = u.prefix + u.resource + u.suffix; + + if (url.indexOf('/') != 0 && url.indexOf('://') == -1) + url = tinymce.baseURL + '/' + url; + + t.urls[n] = url.substring(0, url.lastIndexOf('/')); + + if (t.lookup[n]) { + loadDependencies(); + } else { + tinymce.ScriptLoader.add(url, loadDependencies, s); + } + } + }); + + // Create plugin and theme managers + tinymce.PluginManager = new tinymce.AddOnManager(); + tinymce.ThemeManager = new tinymce.AddOnManager(); +}(tinymce)); + +(function(tinymce) { + // Shorten names + var each = tinymce.each, extend = tinymce.extend, + DOM = tinymce.DOM, Event = tinymce.dom.Event, + ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, + explode = tinymce.explode, + Dispatcher = tinymce.util.Dispatcher, undefined, instanceCounter = 0; + + // Setup some URLs where the editor API is located and where the document is + tinymce.documentBaseURL = window.location.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, ''); + if (!/[\/\\]$/.test(tinymce.documentBaseURL)) + tinymce.documentBaseURL += '/'; + + tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL); + + tinymce.baseURI = new tinymce.util.URI(tinymce.baseURL); + + // Add before unload listener + // This was required since IE was leaking memory if you added and removed beforeunload listeners + // with attachEvent/detatchEvent so this only adds one listener and instances can the attach to the onBeforeUnload event + tinymce.onBeforeUnload = new Dispatcher(tinymce); + + // Must be on window or IE will leak if the editor is placed in frame or iframe + Event.add(window, 'beforeunload', function(e) { + tinymce.onBeforeUnload.dispatch(tinymce, e); + }); + + tinymce.onAddEditor = new Dispatcher(tinymce); + + tinymce.onRemoveEditor = new Dispatcher(tinymce); + + tinymce.EditorManager = extend(tinymce, { + editors : [], + + i18n : {}, + + activeEditor : null, + + init : function(s) { + var t = this, pl, sl = tinymce.ScriptLoader, e, el = [], ed; + + function execCallback(se, n, s) { + var f = se[n]; + + if (!f) + return; + + if (tinymce.is(f, 'string')) { + s = f.replace(/\.\w+$/, ''); + s = s ? tinymce.resolve(s) : 0; + f = tinymce.resolve(f); + } + + return f.apply(s || this, Array.prototype.slice.call(arguments, 2)); + }; + + s = extend({ + theme : "simple", + language : "en" + }, s); + + t.settings = s; + + // Legacy call + Event.add(document, 'init', function() { + var l, co; + + execCallback(s, 'onpageload'); + + switch (s.mode) { + case "exact": + l = s.elements || ''; + + if(l.length > 0) { + each(explode(l), function(v) { + if (DOM.get(v)) { + ed = new tinymce.Editor(v, s); + el.push(ed); + ed.render(1); + } else { + each(document.forms, function(f) { + each(f.elements, function(e) { + if (e.name === v) { + v = 'mce_editor_' + instanceCounter++; + DOM.setAttrib(e, 'id', v); + + ed = new tinymce.Editor(v, s); + el.push(ed); + ed.render(1); + } + }); + }); + } + }); + } + break; + + case "textareas": + case "specific_textareas": + function hasClass(n, c) { + return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c); + }; + + each(DOM.select('textarea'), function(v) { + if (s.editor_deselector && hasClass(v, s.editor_deselector)) + return; + + if (!s.editor_selector || hasClass(v, s.editor_selector)) { + // Can we use the name + e = DOM.get(v.name); + if (!v.id && !e) + v.id = v.name; + + // Generate unique name if missing or already exists + if (!v.id || t.get(v.id)) + v.id = DOM.uniqueId(); + + ed = new tinymce.Editor(v.id, s); + el.push(ed); + ed.render(1); + } + }); + break; + } + + // Call onInit when all editors are initialized + if (s.oninit) { + l = co = 0; + + each(el, function(ed) { + co++; + + if (!ed.initialized) { + // Wait for it + ed.onInit.add(function() { + l++; + + // All done + if (l == co) + execCallback(s, 'oninit'); + }); + } else + l++; + + // All done + if (l == co) + execCallback(s, 'oninit'); + }); + } + }); + }, + + get : function(id) { + if (id === undefined) + return this.editors; + + return this.editors[id]; + }, + + getInstanceById : function(id) { + return this.get(id); + }, + + add : function(editor) { + var self = this, editors = self.editors; + + // Add named and index editor instance + editors[editor.id] = editor; + editors.push(editor); + + self._setActive(editor); + self.onAddEditor.dispatch(self, editor); + + + return editor; + }, + + remove : function(editor) { + var t = this, i, editors = t.editors; + + // Not in the collection + if (!editors[editor.id]) + return null; + + delete editors[editor.id]; + + for (i = 0; i < editors.length; i++) { + if (editors[i] == editor) { + editors.splice(i, 1); + break; + } + } + + // Select another editor since the active one was removed + if (t.activeEditor == editor) + t._setActive(editors[0]); + + editor.destroy(); + t.onRemoveEditor.dispatch(t, editor); + + return editor; + }, + + execCommand : function(c, u, v) { + var t = this, ed = t.get(v), w; + + // Manager commands + switch (c) { + case "mceFocus": + ed.focus(); + return true; + + case "mceAddEditor": + case "mceAddControl": + if (!t.get(v)) + new tinymce.Editor(v, t.settings).render(); + + return true; + + case "mceAddFrameControl": + w = v.window; + + // Add tinyMCE global instance and tinymce namespace to specified window + w.tinyMCE = tinyMCE; + w.tinymce = tinymce; + + tinymce.DOM.doc = w.document; + tinymce.DOM.win = w; + + ed = new tinymce.Editor(v.element_id, v); + ed.render(); + + // Fix IE memory leaks + if (tinymce.isIE) { + function clr() { + ed.destroy(); + w.detachEvent('onunload', clr); + w = w.tinyMCE = w.tinymce = null; // IE leak + }; + + w.attachEvent('onunload', clr); + } + + v.page_window = null; + + return true; + + case "mceRemoveEditor": + case "mceRemoveControl": + if (ed) + ed.remove(); + + return true; + + case 'mceToggleEditor': + if (!ed) { + t.execCommand('mceAddControl', 0, v); + return true; + } + + if (ed.isHidden()) + ed.show(); + else + ed.hide(); + + return true; + } + + // Run command on active editor + if (t.activeEditor) + return t.activeEditor.execCommand(c, u, v); + + return false; + }, + + execInstanceCommand : function(id, c, u, v) { + var ed = this.get(id); + + if (ed) + return ed.execCommand(c, u, v); + + return false; + }, + + triggerSave : function() { + each(this.editors, function(e) { + e.save(); + }); + }, + + addI18n : function(p, o) { + var lo, i18n = this.i18n; + + if (!tinymce.is(p, 'string')) { + each(p, function(o, lc) { + each(o, function(o, g) { + each(o, function(o, k) { + if (g === 'common') + i18n[lc + '.' + k] = o; + else + i18n[lc + '.' + g + '.' + k] = o; + }); + }); + }); + } else { + each(o, function(o, k) { + i18n[p + '.' + k] = o; + }); + } + }, + + // Private methods + + _setActive : function(editor) { + this.selectedInstance = this.activeEditor = editor; + } + }); +})(tinymce); + +(function(tinymce) { + // Shorten these names + var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, + Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isGecko = tinymce.isGecko, + isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, is = tinymce.is, + ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, + inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode; + + tinymce.create('tinymce.Editor', { + Editor : function(id, s) { + var t = this; + + t.id = t.editorId = id; + + t.execCommands = {}; + t.queryStateCommands = {}; + t.queryValueCommands = {}; + + t.isNotDirty = false; + + t.plugins = {}; + + // Add events to the editor + each([ + 'onPreInit', + + 'onBeforeRenderUI', + + 'onPostRender', + + 'onInit', + + 'onRemove', + + 'onActivate', + + 'onDeactivate', + + 'onClick', + + 'onEvent', + + 'onMouseUp', + + 'onMouseDown', + + 'onDblClick', + + 'onKeyDown', + + 'onKeyUp', + + 'onKeyPress', + + 'onContextMenu', + + 'onSubmit', + + 'onReset', + + 'onPaste', + + 'onPreProcess', + + 'onPostProcess', + + 'onBeforeSetContent', + + 'onBeforeGetContent', + + 'onSetContent', + + 'onGetContent', + + 'onLoadContent', + + 'onSaveContent', + + 'onNodeChange', + + 'onChange', + + 'onBeforeExecCommand', + + 'onExecCommand', + + 'onUndo', + + 'onRedo', + + 'onVisualAid', + + 'onSetProgressState' + ], function(e) { + t[e] = new Dispatcher(t); + }); + + t.settings = s = extend({ + id : id, + language : 'en', + docs_language : 'en', + theme : 'simple', + skin : 'default', + delta_width : 0, + delta_height : 0, + popup_css : '', + plugins : '', + document_base_url : tinymce.documentBaseURL, + add_form_submit_trigger : 1, + submit_patch : 1, + add_unload_trigger : 1, + convert_urls : 1, + relative_urls : 1, + remove_script_host : 1, + table_inline_editing : 0, + object_resizing : 1, + cleanup : 1, + accessibility_focus : 1, + custom_shortcuts : 1, + custom_undo_redo_keyboard_shortcuts : 1, + custom_undo_redo_restore_selection : 1, + custom_undo_redo : 1, + doctype : tinymce.isIE6 ? '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">' : '<!DOCTYPE>', // Use old doctype on IE 6 to avoid horizontal scroll + visual_table_class : 'mceItemTable', + visual : 1, + font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large', + apply_source_formatting : 1, + directionality : 'ltr', + forced_root_block : 'p', + hidden_input : 1, + padd_empty_editor : 1, + render_ui : 1, + init_theme : 1, + force_p_newlines : 1, + indentation : '30px', + keep_styles : 1, + fix_table_elements : 1, + inline_styles : 1, + convert_fonts_to_spans : true, + indent : 'simple', + indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr', + indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr', + validate : true, + entity_encoding : 'named', + url_converter : t.convertURL, + url_converter_scope : t, + ie7_compat : true + }, s); + + t.documentBaseURI = new tinymce.util.URI(s.document_base_url || tinymce.documentBaseURL, { + base_uri : tinyMCE.baseURI + }); + + t.baseURI = tinymce.baseURI; + + t.contentCSS = []; + + // Call setup + t.execCallback('setup', t); + }, + + render : function(nst) { + var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader; + + // Page is not loaded yet, wait for it + if (!Event.domLoaded) { + Event.add(document, 'init', function() { + t.render(); + }); + return; + } + + tinyMCE.settings = s; + + // Element not found, then skip initialization + if (!t.getElement()) + return; + + // Is a iPad/iPhone and not on iOS5, then skip initialization. We need to sniff + // here since the browser says it has contentEditable support but there is no visible + // caret We will remove this check ones Apple implements full contentEditable support + if (tinymce.isIDevice && !tinymce.isIOS5) + return; + + // Add hidden input for non input elements inside form elements + if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form')) + DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id); + + if (tinymce.WindowManager) + t.windowManager = new tinymce.WindowManager(t); + + if (s.encoding == 'xml') { + t.onGetContent.add(function(ed, o) { + if (o.save) + o.content = DOM.encode(o.content); + }); + } + + if (s.add_form_submit_trigger) { + t.onSubmit.addToTop(function() { + if (t.initialized) { + t.save(); + t.isNotDirty = 1; + } + }); + } + + if (s.add_unload_trigger) { + t._beforeUnload = tinyMCE.onBeforeUnload.add(function() { + if (t.initialized && !t.destroyed && !t.isHidden()) + t.save({format : 'raw', no_events : true}); + }); + } + + tinymce.addUnload(t.destroy, t); + + if (s.submit_patch) { + t.onBeforeRenderUI.add(function() { + var n = t.getElement().form; + + if (!n) + return; + + // Already patched + if (n._mceOldSubmit) + return; + + // Check page uses id="submit" or name="submit" for it's submit button + if (!n.submit.nodeType && !n.submit.length) { + t.formElement = n; + n._mceOldSubmit = n.submit; + n.submit = function() { + // Save all instances + tinymce.triggerSave(); + t.isNotDirty = 1; + + return t.formElement._mceOldSubmit(t.formElement); + }; + } + + n = null; + }); + } + + // Load scripts + function loadScripts() { + if (s.language && s.language_load !== false) + sl.add(tinymce.baseURL + '/langs/' + s.language + '.js'); + + if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme]) + ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js'); + + each(explode(s.plugins), function(p) { + if (p &&!PluginManager.urls[p]) { + if (p.charAt(0) == '-') { + p = p.substr(1, p.length); + var dependencies = PluginManager.dependencies(p); + each(dependencies, function(dep) { + var defaultSettings = {prefix:'plugins/', resource: dep, suffix:'/editor_plugin' + tinymce.suffix + '.js'}; + var dep = PluginManager.createUrl(defaultSettings, dep); + PluginManager.load(dep.resource, dep); + + }); + } else { + // Skip safari plugin, since it is removed as of 3.3b1 + if (p == 'safari') { + return; + } + PluginManager.load(p, {prefix:'plugins/', resource: p, suffix:'/editor_plugin' + tinymce.suffix + '.js'}); + } + } + }); + + // Init when que is loaded + sl.loadQueue(function() { + if (!t.removed) + t.init(); + }); + }; + + loadScripts(); + }, + + init : function() { + var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti, u, bi, bc, re, i, initializedPlugins = []; + + tinymce.add(t); + + s.aria_label = s.aria_label || DOM.getAttrib(e, 'aria-label', t.getLang('aria.rich_text_area')); + + if (s.theme) { + s.theme = s.theme.replace(/-/, ''); + o = ThemeManager.get(s.theme); + t.theme = new o(); + + if (t.theme.init && s.init_theme) + t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, '')); + } + function initPlugin(p) { + var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po; + if (c && tinymce.inArray(initializedPlugins,p) === -1) { + each(PluginManager.dependencies(p), function(dep){ + initPlugin(dep); + }); + po = new c(t, u); + + t.plugins[p] = po; + + if (po.init) { + po.init(t, u); + initializedPlugins.push(p); + } + } + } + + // Create all plugins + each(explode(s.plugins.replace(/\-/g, '')), initPlugin); + + // Setup popup CSS path(s) + if (s.popup_css !== false) { + if (s.popup_css) + s.popup_css = t.documentBaseURI.toAbsolute(s.popup_css); + else + s.popup_css = t.baseURI.toAbsolute("themes/" + s.theme + "/skins/" + s.skin + "/dialog.css"); + } + + if (s.popup_css_add) + s.popup_css += ',' + t.documentBaseURI.toAbsolute(s.popup_css_add); + + t.controlManager = new tinymce.ControlManager(t); + + if (s.custom_undo_redo) { + t.onBeforeExecCommand.add(function(ed, cmd, ui, val, a) { + if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!a || !a.skip_undo)) + t.undoManager.beforeChange(); + }); + + t.onExecCommand.add(function(ed, cmd, ui, val, a) { + if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!a || !a.skip_undo)) + t.undoManager.add(); + }); + } + + t.onExecCommand.add(function(ed, c) { + // Don't refresh the select lists until caret move + if (!/^(FontName|FontSize)$/.test(c)) + t.nodeChanged(); + }); + + // Remove ghost selections on images and tables in Gecko + if (isGecko) { + function repaint(a, o) { + if (!o || !o.initial) + t.execCommand('mceRepaint'); + }; + + t.onUndo.add(repaint); + t.onRedo.add(repaint); + t.onSetContent.add(repaint); + } + + // Enables users to override the control factory + t.onBeforeRenderUI.dispatch(t, t.controlManager); + + // Measure box + if (s.render_ui) { + w = s.width || e.style.width || e.offsetWidth; + h = s.height || e.style.height || e.offsetHeight; + t.orgDisplay = e.style.display; + re = /^[0-9\.]+(|px)$/i; + + if (re.test('' + w)) + w = Math.max(parseInt(w) + (o.deltaWidth || 0), 100); + + if (re.test('' + h)) + h = Math.max(parseInt(h) + (o.deltaHeight || 0), 100); + + // Render UI + o = t.theme.renderUI({ + targetNode : e, + width : w, + height : h, + deltaWidth : s.delta_width, + deltaHeight : s.delta_height + }); + + t.editorContainer = o.editorContainer; + } + + + // User specified a document.domain value + if (document.domain && location.hostname != document.domain) + tinymce.relaxedDomain = document.domain; + + // Resize editor + DOM.setStyles(o.sizeContainer || o.editorContainer, { + width : w, + height : h + }); + + // Load specified content CSS last + if (s.content_css) { + tinymce.each(explode(s.content_css), function(u) { + t.contentCSS.push(t.documentBaseURI.toAbsolute(u)); + }); + } + + h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : ''); + if (h < 100) + h = 100; + + t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml">'; + + // We only need to override paths if we have to + // IE has a bug where it remove site absolute urls to relative ones if this is specified + if (s.document_base_url != tinymce.documentBaseURL) + t.iframeHTML += '<base href="' + t.documentBaseURI.getURI() + '" />'; + + // IE8 doesn't support carets behind images setting ie7_compat would force IE8+ to run in IE7 compat mode. + if (s.ie7_compat) + t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=7" />'; + else + t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=edge" />'; + + t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />'; + + // Load the CSS by injecting them into the HTML this will reduce "flicker" + for (i = 0; i < t.contentCSS.length; i++) { + t.iframeHTML += '<link type="text/css" rel="stylesheet" href="' + t.contentCSS[i] + '" />'; + } + + bi = s.body_id || 'tinymce'; + if (bi.indexOf('=') != -1) { + bi = t.getParam('body_id', '', 'hash'); + bi = bi[t.id] || bi; + } + + bc = s.body_class || ''; + if (bc.indexOf('=') != -1) { + bc = t.getParam('body_class', '', 'hash'); + bc = bc[t.id] || ''; + } + + t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '"><br></body></html>'; + + // Domain relaxing enabled, then set document domain + if (tinymce.relaxedDomain && (isIE || (tinymce.isOpera && parseFloat(opera.version()) < 11))) { + // We need to write the contents here in IE since multiple writes messes up refresh button and back button + u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";var ed = window.parent.tinyMCE.get("' + t.id + '");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()'; + } + + // Create iframe + // TODO: ACC add the appropriate description on this. + n = DOM.add(o.iframeContainer, 'iframe', { + id : t.id + "_ifr", + src : u || 'javascript:""', // Workaround for HTTPS warning in IE6/7 + frameBorder : '0', + allowTransparency : "true", + title : s.aria_label, + style : { + width : '100%', + height : h, + display : 'block' // Important for Gecko to render the iframe correctly + } + }); + + t.contentAreaContainer = o.iframeContainer; + DOM.get(o.editorContainer).style.display = t.orgDisplay; + DOM.get(t.id).style.display = 'none'; + DOM.setAttrib(t.id, 'aria-hidden', true); + + if (!tinymce.relaxedDomain || !u) + t.setupIframe(); + + e = n = o = null; // Cleanup + }, + + setupIframe : function() { + var t = this, s = t.settings, e = DOM.get(t.id), d = t.getDoc(), h, b; + + // Setup iframe body + if (!isIE || !tinymce.relaxedDomain) { + d.open(); + d.write(t.iframeHTML); + d.close(); + + if (tinymce.relaxedDomain) + d.domain = tinymce.relaxedDomain; + } + + // It will not steal focus while setting contentEditable + b = t.getBody(); + b.disabled = true; + + if (!s.readonly) + b.contentEditable = true; + + b.disabled = false; + + t.schema = new tinymce.html.Schema(s); + + t.dom = new tinymce.dom.DOMUtils(t.getDoc(), { + keep_values : true, + url_converter : t.convertURL, + url_converter_scope : t, + hex_colors : s.force_hex_style_colors, + class_filter : s.class_filter, + update_styles : 1, + fix_ie_paragraphs : 1, + schema : t.schema + }); + + t.parser = new tinymce.html.DomParser(s, t.schema); + + // Force anchor names closed, unless the setting "allow_html_in_named_anchor" is explicitly included. + if (!t.settings.allow_html_in_named_anchor) { + t.parser.addAttributeFilter('name', function(nodes, name) { + var i = nodes.length, sibling, prevSibling, parent, node; + + while (i--) { + node = nodes[i]; + if (node.name === 'a' && node.firstChild) { + parent = node.parent; + + // Move children after current node + sibling = node.lastChild; + do { + prevSibling = sibling.prev; + parent.insert(sibling, node); + sibling = prevSibling; + } while (sibling); + } + } + }); + } + + // Convert src and href into data-mce-src, data-mce-href and data-mce-style + t.parser.addAttributeFilter('src,href,style', function(nodes, name) { + var i = nodes.length, node, dom = t.dom, value, internalName; + + while (i--) { + node = nodes[i]; + value = node.attr(name); + internalName = 'data-mce-' + name; + + // Add internal attribute if we need to we don't on a refresh of the document + if (!node.attributes.map[internalName]) { + if (name === "style") + node.attr(internalName, dom.serializeStyle(dom.parseStyle(value), node.name)); + else + node.attr(internalName, t.convertURL(value, name, node.name)); + } + } + }); + + // Keep scripts from executing + t.parser.addNodeFilter('script', function(nodes, name) { + var i = nodes.length; + + while (i--) + nodes[i].attr('type', 'mce-text/javascript'); + }); + + t.parser.addNodeFilter('#cdata', function(nodes, name) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + node.type = 8; + node.name = '#comment'; + node.value = '[CDATA[' + node.value + ']]'; + } + }); + + t.parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', function(nodes, name) { + var i = nodes.length, node, nonEmptyElements = t.schema.getNonEmptyElements(); + + while (i--) { + node = nodes[i]; + + if (node.isEmpty(nonEmptyElements)) + node.empty().append(new tinymce.html.Node('br', 1)).shortEnded = true; + } + }); + + t.serializer = new tinymce.dom.Serializer(s, t.dom, t.schema); + + t.selection = new tinymce.dom.Selection(t.dom, t.getWin(), t.serializer); + + t.formatter = new tinymce.Formatter(this); + + // Register default formats + t.formatter.register({ + alignleft : [ + {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'left'}}, + {selector : 'img,table', collapsed : false, styles : {'float' : 'left'}} + ], + + aligncenter : [ + {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'center'}}, + {selector : 'img', collapsed : false, styles : {display : 'block', marginLeft : 'auto', marginRight : 'auto'}}, + {selector : 'table', collapsed : false, styles : {marginLeft : 'auto', marginRight : 'auto'}} + ], + + alignright : [ + {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'right'}}, + {selector : 'img,table', collapsed : false, styles : {'float' : 'right'}} + ], + + alignfull : [ + {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'justify'}} + ], + + bold : [ + {inline : 'strong', remove : 'all'}, + {inline : 'span', styles : {fontWeight : 'bold'}}, + {inline : 'b', remove : 'all'} + ], + + italic : [ + {inline : 'em', remove : 'all'}, + {inline : 'span', styles : {fontStyle : 'italic'}}, + {inline : 'i', remove : 'all'} + ], + + underline : [ + {inline : 'span', styles : {textDecoration : 'underline'}, exact : true}, + {inline : 'u', remove : 'all'} + ], + + strikethrough : [ + {inline : 'span', styles : {textDecoration : 'line-through'}, exact : true}, + {inline : 'strike', remove : 'all'} + ], + + forecolor : {inline : 'span', styles : {color : '%value'}, wrap_links : false}, + hilitecolor : {inline : 'span', styles : {backgroundColor : '%value'}, wrap_links : false}, + fontname : {inline : 'span', styles : {fontFamily : '%value'}}, + fontsize : {inline : 'span', styles : {fontSize : '%value'}}, + fontsize_class : {inline : 'span', attributes : {'class' : '%value'}}, + blockquote : {block : 'blockquote', wrapper : 1, remove : 'all'}, + subscript : {inline : 'sub'}, + superscript : {inline : 'sup'}, + + link : {inline : 'a', selector : 'a', remove : 'all', split : true, deep : true, + onmatch : function(node) { + return true; + }, + + onformat : function(elm, fmt, vars) { + each(vars, function(value, key) { + t.dom.setAttrib(elm, key, value); + }); + } + }, + + removeformat : [ + {selector : 'b,strong,em,i,font,u,strike', remove : 'all', split : true, expand : false, block_expand : true, deep : true}, + {selector : 'span', attributes : ['style', 'class'], remove : 'empty', split : true, expand : false, deep : true}, + {selector : '*', attributes : ['style', 'class'], split : false, expand : false, deep : true} + ] + }); + + // Register default block formats + each('p h1 h2 h3 h4 h5 h6 div address pre div code dt dd samp'.split(/\s/), function(name) { + t.formatter.register(name, {block : name, remove : 'all'}); + }); + + // Register user defined formats + t.formatter.register(t.settings.formats); + + t.undoManager = new tinymce.UndoManager(t); + + // Pass through + t.undoManager.onAdd.add(function(um, l) { + if (um.hasUndo()) + return t.onChange.dispatch(t, l, um); + }); + + t.undoManager.onUndo.add(function(um, l) { + return t.onUndo.dispatch(t, l, um); + }); + + t.undoManager.onRedo.add(function(um, l) { + return t.onRedo.dispatch(t, l, um); + }); + + t.forceBlocks = new tinymce.ForceBlocks(t, { + forced_root_block : s.forced_root_block + }); + + t.editorCommands = new tinymce.EditorCommands(t); + + // Pass through + t.serializer.onPreProcess.add(function(se, o) { + return t.onPreProcess.dispatch(t, o, se); + }); + + t.serializer.onPostProcess.add(function(se, o) { + return t.onPostProcess.dispatch(t, o, se); + }); + + t.onPreInit.dispatch(t); + + if (!s.gecko_spellcheck) + t.getBody().spellcheck = 0; + + if (!s.readonly) + t._addEvents(); + + t.controlManager.onPostRender.dispatch(t, t.controlManager); + t.onPostRender.dispatch(t); + + t.quirks = new tinymce.util.Quirks(this); + + if (s.directionality) + t.getBody().dir = s.directionality; + + if (s.nowrap) + t.getBody().style.whiteSpace = "nowrap"; + + if (s.handle_node_change_callback) { + t.onNodeChange.add(function(ed, cm, n) { + t.execCallback('handle_node_change_callback', t.id, n, -1, -1, true, t.selection.isCollapsed()); + }); + } + + if (s.save_callback) { + t.onSaveContent.add(function(ed, o) { + var h = t.execCallback('save_callback', t.id, o.content, t.getBody()); + + if (h) + o.content = h; + }); + } + + if (s.onchange_callback) { + t.onChange.add(function(ed, l) { + t.execCallback('onchange_callback', t, l); + }); + } + + if (s.protect) { + t.onBeforeSetContent.add(function(ed, o) { + if (s.protect) { + each(s.protect, function(pattern) { + o.content = o.content.replace(pattern, function(str) { + return '<!--mce:protected ' + escape(str) + '-->'; + }); + }); + } + }); + } + + if (s.convert_newlines_to_brs) { + t.onBeforeSetContent.add(function(ed, o) { + if (o.initial) + o.content = o.content.replace(/\r?\n/g, '<br />'); + }); + } + + if (s.preformatted) { + t.onPostProcess.add(function(ed, o) { + o.content = o.content.replace(/^\s*<pre.*?>/, ''); + o.content = o.content.replace(/<\/pre>\s*$/, ''); + + if (o.set) + o.content = '<pre class="mceItemHidden">' + o.content + '</pre>'; + }); + } + + if (s.verify_css_classes) { + t.serializer.attribValueFilter = function(n, v) { + var s, cl; + + if (n == 'class') { + // Build regexp for classes + if (!t.classesRE) { + cl = t.dom.getClasses(); + + if (cl.length > 0) { + s = ''; + + each (cl, function(o) { + s += (s ? '|' : '') + o['class']; + }); + + t.classesRE = new RegExp('(' + s + ')', 'gi'); + } + } + + return !t.classesRE || /(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(v) || t.classesRE.test(v) ? v : ''; + } + + return v; + }; + } + + if (s.cleanup_callback) { + t.onBeforeSetContent.add(function(ed, o) { + o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o); + }); + + t.onPreProcess.add(function(ed, o) { + if (o.set) + t.execCallback('cleanup_callback', 'insert_to_editor_dom', o.node, o); + + if (o.get) + t.execCallback('cleanup_callback', 'get_from_editor_dom', o.node, o); + }); + + t.onPostProcess.add(function(ed, o) { + if (o.set) + o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o); + + if (o.get) + o.content = t.execCallback('cleanup_callback', 'get_from_editor', o.content, o); + }); + } + + if (s.save_callback) { + t.onGetContent.add(function(ed, o) { + if (o.save) + o.content = t.execCallback('save_callback', t.id, o.content, t.getBody()); + }); + } + + if (s.handle_event_callback) { + t.onEvent.add(function(ed, e, o) { + if (t.execCallback('handle_event_callback', e, ed, o) === false) + Event.cancel(e); + }); + } + + // Add visual aids when new contents is added + t.onSetContent.add(function() { + t.addVisual(t.getBody()); + }); + + // Remove empty contents + if (s.padd_empty_editor) { + t.onPostProcess.add(function(ed, o) { + o.content = o.content.replace(/^(<p[^>]*>(&nbsp;|&#160;|\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, ''); + }); + } + + if (isGecko) { + // Fix gecko link bug, when a link is placed at the end of block elements there is + // no way to move the caret behind the link. This fix adds a bogus br element after the link + function fixLinks(ed, o) { + each(ed.dom.select('a'), function(n) { + var pn = n.parentNode; + + if (ed.dom.isBlock(pn) && pn.lastChild === n) + ed.dom.add(pn, 'br', {'data-mce-bogus' : 1}); + }); + }; + + t.onExecCommand.add(function(ed, cmd) { + if (cmd === 'CreateLink') + fixLinks(ed); + }); + + t.onSetContent.add(t.selection.onSetContent.add(fixLinks)); + } + + t.load({initial : true, format : 'html'}); + t.startContent = t.getContent({format : 'raw'}); + t.undoManager.add(); + t.initialized = true; + + t.onInit.dispatch(t); + t.execCallback('setupcontent_callback', t.id, t.getBody(), t.getDoc()); + t.execCallback('init_instance_callback', t); + t.focus(true); + t.nodeChanged({initial : 1}); + + // Load specified content CSS last + each(t.contentCSS, function(u) { + t.dom.loadCSS(u); + }); + + // Handle auto focus + if (s.auto_focus) { + setTimeout(function () { + var ed = tinymce.get(s.auto_focus); + + ed.selection.select(ed.getBody(), 1); + ed.selection.collapse(1); + ed.getBody().focus(); + ed.getWin().focus(); + }, 100); + } + + e = null; + }, + + + focus : function(sf) { + var oed, t = this, selection = t.selection, ce = t.settings.content_editable, ieRng, controlElm, doc = t.getDoc(); + + if (!sf) { + // Get selected control element + ieRng = selection.getRng(); + if (ieRng.item) { + controlElm = ieRng.item(0); + } + + t._refreshContentEditable(); + selection.normalize(); + + // Is not content editable + if (!ce) + t.getWin().focus(); + + // Focus the body as well since it's contentEditable + if (tinymce.isGecko) { + t.getBody().focus(); + } + + // Restore selected control element + // This is needed when for example an image is selected within a + // layer a call to focus will then remove the control selection + if (controlElm && controlElm.ownerDocument == doc) { + ieRng = doc.body.createControlRange(); + ieRng.addElement(controlElm); + ieRng.select(); + } + + } + + if (tinymce.activeEditor != t) { + if ((oed = tinymce.activeEditor) != null) + oed.onDeactivate.dispatch(oed, t); + + t.onActivate.dispatch(t, oed); + } + + tinymce._setActive(t); + }, + + execCallback : function(n) { + var t = this, f = t.settings[n], s; + + if (!f) + return; + + // Look through lookup + if (t.callbackLookup && (s = t.callbackLookup[n])) { + f = s.func; + s = s.scope; + } + + if (is(f, 'string')) { + s = f.replace(/\.\w+$/, ''); + s = s ? tinymce.resolve(s) : 0; + f = tinymce.resolve(f); + t.callbackLookup = t.callbackLookup || {}; + t.callbackLookup[n] = {func : f, scope : s}; + } + + return f.apply(s || t, Array.prototype.slice.call(arguments, 1)); + }, + + translate : function(s) { + var c = this.settings.language || 'en', i18n = tinymce.i18n; + + if (!s) + return ''; + + return i18n[c + '.' + s] || s.replace(/{\#([^}]+)\}/g, function(a, b) { + return i18n[c + '.' + b] || '{#' + b + '}'; + }); + }, + + getLang : function(n, dv) { + return tinymce.i18n[(this.settings.language || 'en') + '.' + n] || (is(dv) ? dv : '{#' + n + '}'); + }, + + getParam : function(n, dv, ty) { + var tr = tinymce.trim, v = is(this.settings[n]) ? this.settings[n] : dv, o; + + if (ty === 'hash') { + o = {}; + + if (is(v, 'string')) { + each(v.indexOf('=') > 0 ? v.split(/[;,](?![^=;,]*(?:[;,]|$))/) : v.split(','), function(v) { + v = v.split('='); + + if (v.length > 1) + o[tr(v[0])] = tr(v[1]); + else + o[tr(v[0])] = tr(v); + }); + } else + o = v; + + return o; + } + + return v; + }, + + nodeChanged : function(o) { + var t = this, s = t.selection, n = s.getStart() || t.getBody(); + + // Fix for bug #1896577 it seems that this can not be fired while the editor is loading + if (t.initialized) { + o = o || {}; + n = isIE && n.ownerDocument != t.getDoc() ? t.getBody() : n; // Fix for IE initial state + + // Get parents and add them to object + o.parents = []; + t.dom.getParent(n, function(node) { + if (node.nodeName == 'BODY') + return true; + + o.parents.push(node); + }); + + t.onNodeChange.dispatch( + t, + o ? o.controlManager || t.controlManager : t.controlManager, + n, + s.isCollapsed(), + o + ); + } + }, + + addButton : function(n, s) { + var t = this; + + t.buttons = t.buttons || {}; + t.buttons[n] = s; + }, + + addCommand : function(name, callback, scope) { + this.execCommands[name] = {func : callback, scope : scope || this}; + }, + + addQueryStateHandler : function(name, callback, scope) { + this.queryStateCommands[name] = {func : callback, scope : scope || this}; + }, + + addQueryValueHandler : function(name, callback, scope) { + this.queryValueCommands[name] = {func : callback, scope : scope || this}; + }, + + addShortcut : function(pa, desc, cmd_func, sc) { + var t = this, c; + + if (!t.settings.custom_shortcuts) + return false; + + t.shortcuts = t.shortcuts || {}; + + if (is(cmd_func, 'string')) { + c = cmd_func; + + cmd_func = function() { + t.execCommand(c, false, null); + }; + } + + if (is(cmd_func, 'object')) { + c = cmd_func; + + cmd_func = function() { + t.execCommand(c[0], c[1], c[2]); + }; + } + + each(explode(pa), function(pa) { + var o = { + func : cmd_func, + scope : sc || this, + desc : desc, + alt : false, + ctrl : false, + shift : false + }; + + each(explode(pa, '+'), function(v) { + switch (v) { + case 'alt': + case 'ctrl': + case 'shift': + o[v] = true; + break; + + default: + o.charCode = v.charCodeAt(0); + o.keyCode = v.toUpperCase().charCodeAt(0); + } + }); + + t.shortcuts[(o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode] = o; + }); + + return true; + }, + + execCommand : function(cmd, ui, val, a) { + var t = this, s = 0, o, st; + + if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus)) + t.focus(); + + o = {}; + t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o); + if (o.terminate) + return false; + + // Command callback + if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return true; + } + + // Registred commands + if (o = t.execCommands[cmd]) { + st = o.func.call(o.scope, ui, val); + + // Fall through on true + if (st !== true) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return st; + } + } + + // Plugin commands + each(t.plugins, function(p) { + if (p.execCommand && p.execCommand(cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + s = 1; + return false; + } + }); + + if (s) + return true; + + // Theme commands + if (t.theme && t.theme.execCommand && t.theme.execCommand(cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return true; + } + + // Editor commands + if (t.editorCommands.execCommand(cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return true; + } + + // Browser commands + t.getDoc().execCommand(cmd, ui, val); + t.onExecCommand.dispatch(t, cmd, ui, val, a); + }, + + queryCommandState : function(cmd) { + var t = this, o, s; + + // Is hidden then return undefined + if (t._isHidden()) + return; + + // Registred commands + if (o = t.queryStateCommands[cmd]) { + s = o.func.call(o.scope); + + // Fall though on true + if (s !== true) + return s; + } + + // Registred commands + o = t.editorCommands.queryCommandState(cmd); + if (o !== -1) + return o; + + // Browser commands + try { + return this.getDoc().queryCommandState(cmd); + } catch (ex) { + // Fails sometimes see bug: 1896577 + } + }, + + queryCommandValue : function(c) { + var t = this, o, s; + + // Is hidden then return undefined + if (t._isHidden()) + return; + + // Registred commands + if (o = t.queryValueCommands[c]) { + s = o.func.call(o.scope); + + // Fall though on true + if (s !== true) + return s; + } + + // Registred commands + o = t.editorCommands.queryCommandValue(c); + if (is(o)) + return o; + + // Browser commands + try { + return this.getDoc().queryCommandValue(c); + } catch (ex) { + // Fails sometimes see bug: 1896577 + } + }, + + show : function() { + var t = this; + + DOM.show(t.getContainer()); + DOM.hide(t.id); + t.load(); + }, + + hide : function() { + var t = this, d = t.getDoc(); + + // Fixed bug where IE has a blinking cursor left from the editor + if (isIE && d) + d.execCommand('SelectAll'); + + // We must save before we hide so Safari doesn't crash + t.save(); + DOM.hide(t.getContainer()); + DOM.setStyle(t.id, 'display', t.orgDisplay); + }, + + isHidden : function() { + return !DOM.isHidden(this.id); + }, + + setProgressState : function(b, ti, o) { + this.onSetProgressState.dispatch(this, b, ti, o); + + return b; + }, + + load : function(o) { + var t = this, e = t.getElement(), h; + + if (e) { + o = o || {}; + o.load = true; + + // Double encode existing entities in the value + h = t.setContent(is(e.value) ? e.value : e.innerHTML, o); + o.element = e; + + if (!o.no_events) + t.onLoadContent.dispatch(t, o); + + o.element = e = null; + + return h; + } + }, + + save : function(o) { + var t = this, e = t.getElement(), h, f; + + if (!e || !t.initialized) + return; + + o = o || {}; + o.save = true; + + // Add undo level will trigger onchange event + if (!o.no_events) { + t.undoManager.typing = false; + t.undoManager.add(); + } + + o.element = e; + h = o.content = t.getContent(o); + + if (!o.no_events) + t.onSaveContent.dispatch(t, o); + + h = o.content; + + if (!/TEXTAREA|INPUT/i.test(e.nodeName)) { + e.innerHTML = h; + + // Update hidden form element + if (f = DOM.getParent(t.id, 'form')) { + each(f.elements, function(e) { + if (e.name == t.id) { + e.value = h; + return false; + } + }); + } + } else + e.value = h; + + o.element = e = null; + + return h; + }, + + setContent : function(content, args) { + var self = this, rootNode, body = self.getBody(), forcedRootBlockName; + + // Setup args object + args = args || {}; + args.format = args.format || 'html'; + args.set = true; + args.content = content; + + // Do preprocessing + if (!args.no_events) + self.onBeforeSetContent.dispatch(self, args); + + content = args.content; + + // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content + // It will also be impossible to place the caret in the editor unless there is a BR element present + if (!tinymce.isIE && (content.length === 0 || /^\s+$/.test(content))) { + forcedRootBlockName = self.settings.forced_root_block; + if (forcedRootBlockName) + content = '<' + forcedRootBlockName + '><br data-mce-bogus="1"></' + forcedRootBlockName + '>'; + else + content = '<br data-mce-bogus="1">'; + + body.innerHTML = content; + self.selection.select(body, true); + self.selection.collapse(true); + return; + } + + // Parse and serialize the html + if (args.format !== 'raw') { + content = new tinymce.html.Serializer({}, self.schema).serialize( + self.parser.parse(content) + ); + } + + // Set the new cleaned contents to the editor + args.content = tinymce.trim(content); + self.dom.setHTML(body, args.content); + + // Do post processing + if (!args.no_events) + self.onSetContent.dispatch(self, args); + + self.selection.normalize(); + + return args.content; + }, + + getContent : function(args) { + var self = this, content; + + // Setup args object + args = args || {}; + args.format = args.format || 'html'; + args.get = true; + + // Do preprocessing + if (!args.no_events) + self.onBeforeGetContent.dispatch(self, args); + + // Get raw contents or by default the cleaned contents + if (args.format == 'raw') + content = self.getBody().innerHTML; + else + content = self.serializer.serialize(self.getBody(), args); + + args.content = tinymce.trim(content); + + // Do post processing + if (!args.no_events) + self.onGetContent.dispatch(self, args); + + return args.content; + }, + + isDirty : function() { + var self = this; + + return tinymce.trim(self.startContent) != tinymce.trim(self.getContent({format : 'raw', no_events : 1})) && !self.isNotDirty; + }, + + getContainer : function() { + var t = this; + + if (!t.container) + t.container = DOM.get(t.editorContainer || t.id + '_parent'); + + return t.container; + }, + + getContentAreaContainer : function() { + return this.contentAreaContainer; + }, + + getElement : function() { + return DOM.get(this.settings.content_element || this.id); + }, + + getWin : function() { + var t = this, e; + + if (!t.contentWindow) { + e = DOM.get(t.id + "_ifr"); + + if (e) + t.contentWindow = e.contentWindow; + } + + return t.contentWindow; + }, + + getDoc : function() { + var t = this, w; + + if (!t.contentDocument) { + w = t.getWin(); + + if (w) + t.contentDocument = w.document; + } + + return t.contentDocument; + }, + + getBody : function() { + return this.bodyElement || this.getDoc().body; + }, + + convertURL : function(u, n, e) { + var t = this, s = t.settings; + + // Use callback instead + if (s.urlconverter_callback) + return t.execCallback('urlconverter_callback', u, e, true, n); + + // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs + if (!s.convert_urls || (e && e.nodeName == 'LINK') || u.indexOf('file:') === 0) + return u; + + // Convert to relative + if (s.relative_urls) + return t.documentBaseURI.toRelative(u); + + // Convert to absolute + u = t.documentBaseURI.toAbsolute(u, s.remove_script_host); + + return u; + }, + + addVisual : function(e) { + var t = this, s = t.settings; + + e = e || t.getBody(); + + if (!is(t.hasVisual)) + t.hasVisual = s.visual; + + each(t.dom.select('table,a', e), function(e) { + var v; + + switch (e.nodeName) { + case 'TABLE': + v = t.dom.getAttrib(e, 'border'); + + if (!v || v == '0') { + if (t.hasVisual) + t.dom.addClass(e, s.visual_table_class); + else + t.dom.removeClass(e, s.visual_table_class); + } + + return; + + case 'A': + v = t.dom.getAttrib(e, 'name'); + + if (v) { + if (t.hasVisual) + t.dom.addClass(e, 'mceItemAnchor'); + else + t.dom.removeClass(e, 'mceItemAnchor'); + } + + return; + } + }); + + t.onVisualAid.dispatch(t, e, t.hasVisual); + }, + + remove : function() { + var t = this, e = t.getContainer(); + + t.removed = 1; // Cancels post remove event execution + t.hide(); + + t.execCallback('remove_instance_callback', t); + t.onRemove.dispatch(t); + + // Clear all execCommand listeners this is required to avoid errors if the editor was removed inside another command + t.onExecCommand.listeners = []; + + tinymce.remove(t); + DOM.remove(e); + }, + + destroy : function(s) { + var t = this; + + // One time is enough + if (t.destroyed) + return; + + if (!s) { + tinymce.removeUnload(t.destroy); + tinyMCE.onBeforeUnload.remove(t._beforeUnload); + + // Manual destroy + if (t.theme && t.theme.destroy) + t.theme.destroy(); + + // Destroy controls, selection and dom + t.controlManager.destroy(); + t.selection.destroy(); + t.dom.destroy(); + + // Remove all events + + // Don't clear the window or document if content editable + // is enabled since other instances might still be present + if (!t.settings.content_editable) { + Event.clear(t.getWin()); + Event.clear(t.getDoc()); + } + + Event.clear(t.getBody()); + Event.clear(t.formElement); + } + + if (t.formElement) { + t.formElement.submit = t.formElement._mceOldSubmit; + t.formElement._mceOldSubmit = null; + } + + t.contentAreaContainer = t.formElement = t.container = t.settings.content_element = t.bodyElement = t.contentDocument = t.contentWindow = null; + + if (t.selection) + t.selection = t.selection.win = t.selection.dom = t.selection.dom.doc = null; + + t.destroyed = 1; + }, + + // Internal functions + + _addEvents : function() { + // 'focus', 'blur', 'dblclick', 'beforedeactivate', submit, reset + var t = this, i, s = t.settings, dom = t.dom, lo = { + mouseup : 'onMouseUp', + mousedown : 'onMouseDown', + click : 'onClick', + keyup : 'onKeyUp', + keydown : 'onKeyDown', + keypress : 'onKeyPress', + submit : 'onSubmit', + reset : 'onReset', + contextmenu : 'onContextMenu', + dblclick : 'onDblClick', + paste : 'onPaste' // Doesn't work in all browsers yet + }; + + function eventHandler(e, o) { + var ty = e.type; + + // Don't fire events when it's removed + if (t.removed) + return; + + // Generic event handler + if (t.onEvent.dispatch(t, e, o) !== false) { + // Specific event handler + t[lo[e.fakeType || e.type]].dispatch(t, e, o); + } + }; + + // Add DOM events + each(lo, function(v, k) { + switch (k) { + case 'contextmenu': + dom.bind(t.getDoc(), k, eventHandler); + break; + + case 'paste': + dom.bind(t.getBody(), k, function(e) { + eventHandler(e); + }); + break; + + case 'submit': + case 'reset': + dom.bind(t.getElement().form || DOM.getParent(t.id, 'form'), k, eventHandler); + break; + + default: + dom.bind(s.content_editable ? t.getBody() : t.getDoc(), k, eventHandler); + } + }); + + dom.bind(s.content_editable ? t.getBody() : (isGecko ? t.getDoc() : t.getWin()), 'focus', function(e) { + t.focus(true); + }); + + + // Fixes bug where a specified document_base_uri could result in broken images + // This will also fix drag drop of images in Gecko + if (tinymce.isGecko) { + dom.bind(t.getDoc(), 'DOMNodeInserted', function(e) { + var v; + + e = e.target; + + if (e.nodeType === 1 && e.nodeName === 'IMG' && (v = e.getAttribute('data-mce-src'))) + e.src = t.documentBaseURI.toAbsolute(v); + }); + } + + // Set various midas options in Gecko + if (isGecko) { + function setOpts() { + var t = this, d = t.getDoc(), s = t.settings; + + if (isGecko && !s.readonly) { + t._refreshContentEditable(); + + try { + // Try new Gecko method + d.execCommand("styleWithCSS", 0, false); + } catch (ex) { + // Use old method + if (!t._isHidden()) + try {d.execCommand("useCSS", 0, true);} catch (ex) {} + } + + if (!s.table_inline_editing) + try {d.execCommand('enableInlineTableEditing', false, false);} catch (ex) {} + + if (!s.object_resizing) + try {d.execCommand('enableObjectResizing', false, false);} catch (ex) {} + } + }; + + t.onBeforeExecCommand.add(setOpts); + t.onMouseDown.add(setOpts); + } + + // Add node change handlers + t.onMouseUp.add(t.nodeChanged); + //t.onClick.add(t.nodeChanged); + t.onKeyUp.add(function(ed, e) { + var c = e.keyCode; + + if ((c >= 33 && c <= 36) || (c >= 37 && c <= 40) || c == 13 || c == 45 || c == 46 || c == 8 || (tinymce.isMac && (c == 91 || c == 93)) || e.ctrlKey) + t.nodeChanged(); + }); + + + // Add block quote deletion handler + t.onKeyDown.add(function(ed, e) { + // Was the BACKSPACE key pressed? + if (e.keyCode != 8) + return; + + var n = ed.selection.getRng().startContainer; + var offset = ed.selection.getRng().startOffset; + + while (n && n.nodeType && n.nodeType != 1 && n.parentNode) + n = n.parentNode; + + // Is the cursor at the beginning of a blockquote? + if (n && n.parentNode && n.parentNode.tagName === 'BLOCKQUOTE' && n.parentNode.firstChild == n && offset == 0) { + // Remove the blockquote + ed.formatter.toggle('blockquote', null, n.parentNode); + + // Move the caret to the beginning of n + var rng = ed.selection.getRng(); + rng.setStart(n, 0); + rng.setEnd(n, 0); + ed.selection.setRng(rng); + ed.selection.collapse(false); + } + }); + + + + // Add reset handler + t.onReset.add(function() { + t.setContent(t.startContent, {format : 'raw'}); + }); + + // Add shortcuts + if (s.custom_shortcuts) { + if (s.custom_undo_redo_keyboard_shortcuts) { + t.addShortcut('ctrl+z', t.getLang('undo_desc'), 'Undo'); + t.addShortcut('ctrl+y', t.getLang('redo_desc'), 'Redo'); + } + + // Add default shortcuts for gecko + t.addShortcut('ctrl+b', t.getLang('bold_desc'), 'Bold'); + t.addShortcut('ctrl+i', t.getLang('italic_desc'), 'Italic'); + t.addShortcut('ctrl+u', t.getLang('underline_desc'), 'Underline'); + + // BlockFormat shortcuts keys + for (i=1; i<=6; i++) + t.addShortcut('ctrl+' + i, '', ['FormatBlock', false, 'h' + i]); + + t.addShortcut('ctrl+7', '', ['FormatBlock', false, 'p']); + t.addShortcut('ctrl+8', '', ['FormatBlock', false, 'div']); + t.addShortcut('ctrl+9', '', ['FormatBlock', false, 'address']); + + function find(e) { + var v = null; + + if (!e.altKey && !e.ctrlKey && !e.metaKey) + return v; + + each(t.shortcuts, function(o) { + if (tinymce.isMac && o.ctrl != e.metaKey) + return; + else if (!tinymce.isMac && o.ctrl != e.ctrlKey) + return; + + if (o.alt != e.altKey) + return; + + if (o.shift != e.shiftKey) + return; + + if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) { + v = o; + return false; + } + }); + + return v; + }; + + t.onKeyUp.add(function(ed, e) { + var o = find(e); + + if (o) + return Event.cancel(e); + }); + + t.onKeyPress.add(function(ed, e) { + var o = find(e); + + if (o) + return Event.cancel(e); + }); + + t.onKeyDown.add(function(ed, e) { + var o = find(e); + + if (o) { + o.func.call(o.scope); + return Event.cancel(e); + } + }); + } + + if (tinymce.isIE) { + // Fix so resize will only update the width and height attributes not the styles of an image + // It will also block mceItemNoResize items + dom.bind(t.getDoc(), 'controlselect', function(e) { + var re = t.resizeInfo, cb; + + e = e.target; + + // Don't do this action for non image elements + if (e.nodeName !== 'IMG') + return; + + if (re) + dom.unbind(re.node, re.ev, re.cb); + + if (!dom.hasClass(e, 'mceItemNoResize')) { + ev = 'resizeend'; + cb = dom.bind(e, ev, function(e) { + var v; + + e = e.target; + + if (v = dom.getStyle(e, 'width')) { + dom.setAttrib(e, 'width', v.replace(/[^0-9%]+/g, '')); + dom.setStyle(e, 'width', ''); + } + + if (v = dom.getStyle(e, 'height')) { + dom.setAttrib(e, 'height', v.replace(/[^0-9%]+/g, '')); + dom.setStyle(e, 'height', ''); + } + }); + } else { + ev = 'resizestart'; + cb = dom.bind(e, 'resizestart', Event.cancel, Event); + } + + re = t.resizeInfo = { + node : e, + ev : ev, + cb : cb + }; + }); + } + + if (tinymce.isOpera) { + t.onClick.add(function(ed, e) { + Event.prevent(e); + }); + } + + // Add custom undo/redo handlers + if (s.custom_undo_redo) { + function addUndo() { + t.undoManager.typing = false; + t.undoManager.add(); + }; + + dom.bind(t.getDoc(), 'focusout', function(e) { + if (!t.removed && t.undoManager.typing) + addUndo(); + }); + + // Add undo level when contents is drag/dropped within the editor + t.dom.bind(t.dom.getRoot(), 'dragend', function(e) { + addUndo(); + }); + + t.onKeyUp.add(function(ed, e) { + var keyCode = e.keyCode; + + if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 13 || keyCode == 45 || e.ctrlKey) + addUndo(); + }); + + t.onKeyDown.add(function(ed, e) { + var keyCode = e.keyCode, sel; + + if (keyCode == 8) { + sel = t.getDoc().selection; + + // Fix IE control + backspace browser bug + if (sel && sel.createRange && sel.createRange().item) { + t.undoManager.beforeChange(); + ed.dom.remove(sel.createRange().item(0)); + addUndo(); + + return Event.cancel(e); + } + } + + // Is caracter positon keys left,right,up,down,home,end,pgdown,pgup,enter + if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 13 || keyCode == 45) { + // Add position before enter key is pressed, used by IE since it still uses the default browser behavior + // Todo: Remove this once we normalize enter behavior on IE + if (tinymce.isIE && keyCode == 13) + t.undoManager.beforeChange(); + + if (t.undoManager.typing) + addUndo(); + + return; + } + + // If key isn't shift,ctrl,alt,capslock,metakey + if ((keyCode < 16 || keyCode > 20) && keyCode != 224 && keyCode != 91 && !t.undoManager.typing) { + t.undoManager.beforeChange(); + t.undoManager.typing = true; + t.undoManager.add(); + } + }); + + t.onMouseDown.add(function() { + if (t.undoManager.typing) + addUndo(); + }); + } + + // Fire a nodeChanged when the selection is changed on WebKit this fixes selection issues on iOS5 + // It only fires the nodeChange event every 50ms since it would other wise update the UI when you type and it hogs the CPU + if (tinymce.isWebKit) { + dom.bind(t.getDoc(), 'selectionchange', function() { + if (t.selectionTimer) { + clearTimeout(t.selectionTimer); + t.selectionTimer = 0; + } + + t.selectionTimer = window.setTimeout(function() { + t.nodeChanged(); + }, 50); + }); + } + + // Bug fix for FireFox keeping styles from end of selection instead of start. + if (tinymce.isGecko) { + function getAttributeApplyFunction() { + var template = t.dom.getAttribs(t.selection.getStart().cloneNode(false)); + + return function() { + var target = t.selection.getStart(); + + if (target !== t.getBody()) { + t.dom.removeAllAttribs(target); + + each(template, function(attr) { + target.setAttributeNode(attr.cloneNode(true)); + }); + } + }; + } + + function isSelectionAcrossElements() { + var s = t.selection; + + return !s.isCollapsed() && s.getStart() != s.getEnd(); + } + + t.onKeyPress.add(function(ed, e) { + var applyAttributes; + + if ((e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) { + applyAttributes = getAttributeApplyFunction(); + t.getDoc().execCommand('delete', false, null); + applyAttributes(); + + return Event.cancel(e); + } + }); + + t.dom.bind(t.getDoc(), 'cut', function(e) { + var applyAttributes; + + if (isSelectionAcrossElements()) { + applyAttributes = getAttributeApplyFunction(); + t.onKeyUp.addToTop(Event.cancel, Event); + + setTimeout(function() { + applyAttributes(); + t.onKeyUp.remove(Event.cancel, Event); + }, 0); + } + }); + } + }, + + _refreshContentEditable : function() { + var self = this, body, parent; + + // Check if the editor was hidden and the re-initalize contentEditable mode by removing and adding the body again + if (self._isHidden()) { + body = self.getBody(); + parent = body.parentNode; + + parent.removeChild(body); + parent.appendChild(body); + + body.focus(); + } + }, + + _isHidden : function() { + var s; + + if (!isGecko) + return 0; + + // Weird, wheres that cursor selection? + s = this.selection.getSel(); + return (!s || !s.rangeCount || s.rangeCount == 0); + } + }); +})(tinymce); + +(function(tinymce) { + // Added for compression purposes + var each = tinymce.each, undefined, TRUE = true, FALSE = false; + + tinymce.EditorCommands = function(editor) { + var dom = editor.dom, + selection = editor.selection, + commands = {state: {}, exec : {}, value : {}}, + settings = editor.settings, + formatter = editor.formatter, + bookmark; + + function execCommand(command, ui, value) { + var func; + + command = command.toLowerCase(); + if (func = commands.exec[command]) { + func(command, ui, value); + return TRUE; + } + + return FALSE; + }; + + function queryCommandState(command) { + var func; + + command = command.toLowerCase(); + if (func = commands.state[command]) + return func(command); + + return -1; + }; + + function queryCommandValue(command) { + var func; + + command = command.toLowerCase(); + if (func = commands.value[command]) + return func(command); + + return FALSE; + }; + + function addCommands(command_list, type) { + type = type || 'exec'; + + each(command_list, function(callback, command) { + each(command.toLowerCase().split(','), function(command) { + commands[type][command] = callback; + }); + }); + }; + + // Expose public methods + tinymce.extend(this, { + execCommand : execCommand, + queryCommandState : queryCommandState, + queryCommandValue : queryCommandValue, + addCommands : addCommands + }); + + // Private methods + + function execNativeCommand(command, ui, value) { + if (ui === undefined) + ui = FALSE; + + if (value === undefined) + value = null; + + return editor.getDoc().execCommand(command, ui, value); + }; + + function isFormatMatch(name) { + return formatter.match(name); + }; + + function toggleFormat(name, value) { + formatter.toggle(name, value ? {value : value} : undefined); + }; + + function storeSelection(type) { + bookmark = selection.getBookmark(type); + }; + + function restoreSelection() { + selection.moveToBookmark(bookmark); + }; + + // Add execCommand overrides + addCommands({ + // Ignore these, added for compatibility + 'mceResetDesignMode,mceBeginUndoLevel' : function() {}, + + // Add undo manager logic + 'mceEndUndoLevel,mceAddUndoLevel' : function() { + editor.undoManager.add(); + }, + + 'Cut,Copy,Paste' : function(command) { + var doc = editor.getDoc(), failed; + + // Try executing the native command + try { + execNativeCommand(command); + } catch (ex) { + // Command failed + failed = TRUE; + } + + // Present alert message about clipboard access not being available + if (failed || !doc.queryCommandSupported(command)) { + if (tinymce.isGecko) { + editor.windowManager.confirm(editor.getLang('clipboard_msg'), function(state) { + if (state) + open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', '_blank'); + }); + } else + editor.windowManager.alert(editor.getLang('clipboard_no_support')); + } + }, + + // Override unlink command + unlink : function(command) { + if (selection.isCollapsed()) + selection.select(selection.getNode()); + + execNativeCommand(command); + selection.collapse(FALSE); + }, + + // Override justify commands to use the text formatter engine + 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) { + var align = command.substring(7); + + // Remove all other alignments first + each('left,center,right,full'.split(','), function(name) { + if (align != name) + formatter.remove('align' + name); + }); + + toggleFormat('align' + align); + execCommand('mceRepaint'); + }, + + // Override list commands to fix WebKit bug + 'InsertUnorderedList,InsertOrderedList' : function(command) { + var listElm, listParent; + + execNativeCommand(command); + + // WebKit produces lists within block elements so we need to split them + // we will replace the native list creation logic to custom logic later on + // TODO: Remove this when the list creation logic is removed + listElm = dom.getParent(selection.getNode(), 'ol,ul'); + if (listElm) { + listParent = listElm.parentNode; + + // If list is within a text block then split that block + if (/^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)) { + storeSelection(); + dom.split(listParent, listElm); + restoreSelection(); + } + } + }, + + // Override commands to use the text formatter engine + 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript' : function(command) { + toggleFormat(command); + }, + + // Override commands to use the text formatter engine + 'ForeColor,HiliteColor,FontName' : function(command, ui, value) { + toggleFormat(command, value); + }, + + FontSize : function(command, ui, value) { + var fontClasses, fontSizes; + + // Convert font size 1-7 to styles + if (value >= 1 && value <= 7) { + fontSizes = tinymce.explode(settings.font_size_style_values); + fontClasses = tinymce.explode(settings.font_size_classes); + + if (fontClasses) + value = fontClasses[value - 1] || value; + else + value = fontSizes[value - 1] || value; + } + + toggleFormat(command, value); + }, + + RemoveFormat : function(command) { + formatter.remove(command); + }, + + mceBlockQuote : function(command) { + toggleFormat('blockquote'); + }, + + FormatBlock : function(command, ui, value) { + return toggleFormat(value || 'p'); + }, + + mceCleanup : function() { + var bookmark = selection.getBookmark(); + + editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); + + selection.moveToBookmark(bookmark); + }, + + mceRemoveNode : function(command, ui, value) { + var node = value || selection.getNode(); + + // Make sure that the body node isn't removed + if (node != editor.getBody()) { + storeSelection(); + editor.dom.remove(node, TRUE); + restoreSelection(); + } + }, + + mceSelectNodeDepth : function(command, ui, value) { + var counter = 0; + + dom.getParent(selection.getNode(), function(node) { + if (node.nodeType == 1 && counter++ == value) { + selection.select(node); + return FALSE; + } + }, editor.getBody()); + }, + + mceSelectNode : function(command, ui, value) { + selection.select(value); + }, + + mceInsertContent : function(command, ui, value) { + var parser, serializer, parentNode, rootNode, fragment, args, + marker, nodeRect, viewPortRect, rng, node, node2, bookmarkHtml, viewportBodyElement; + + // Setup parser and serializer + parser = editor.parser; + serializer = new tinymce.html.Serializer({}, editor.schema); + bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">\uFEFF</span>'; + + // Run beforeSetContent handlers on the HTML to be inserted + args = {content: value, format: 'html'}; + selection.onBeforeSetContent.dispatch(selection, args); + value = args.content; + + // Add caret at end of contents if it's missing + if (value.indexOf('{$caret}') == -1) + value += '{$caret}'; + + // Replace the caret marker with a span bookmark element + value = value.replace(/\{\$caret\}/, bookmarkHtml); + + // Insert node maker where we will insert the new HTML and get it's parent + if (!selection.isCollapsed()) + editor.getDoc().execCommand('Delete', false, null); + + parentNode = selection.getNode(); + + // Parse the fragment within the context of the parent node + args = {context : parentNode.nodeName.toLowerCase()}; + fragment = parser.parse(value, args); + + // Move the caret to a more suitable location + node = fragment.lastChild; + if (node.attr('id') == 'mce_marker') { + marker = node; + + for (node = node.prev; node; node = node.walk(true)) { + if (node.type == 3 || !dom.isBlock(node.name)) { + node.parent.insert(marker, node, node.name === 'br'); + break; + } + } + } + + // If parser says valid we can insert the contents into that parent + if (!args.invalid) { + value = serializer.serialize(fragment); + + // Check if parent is empty or only has one BR element then set the innerHTML of that parent + node = parentNode.firstChild; + node2 = parentNode.lastChild; + if (!node || (node === node2 && node.nodeName === 'BR')) + dom.setHTML(parentNode, value); + else + selection.setContent(value); + } else { + // If the fragment was invalid within that context then we need + // to parse and process the parent it's inserted into + + // Insert bookmark node and get the parent + selection.setContent(bookmarkHtml); + parentNode = editor.selection.getNode(); + rootNode = editor.getBody(); + + // Opera will return the document node when selection is in root + if (parentNode.nodeType == 9) + parentNode = node = rootNode; + else + node = parentNode; + + // Find the ancestor just before the root element + while (node !== rootNode) { + parentNode = node; + node = node.parentNode; + } + + // Get the outer/inner HTML depending on if we are in the root and parser and serialize that + value = parentNode == rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode); + value = serializer.serialize( + parser.parse( + // Need to replace by using a function since $ in the contents would otherwise be a problem + value.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i, function() { + return serializer.serialize(fragment); + }) + ) + ); + + // Set the inner/outer HTML depending on if we are in the root or not + if (parentNode == rootNode) + dom.setHTML(rootNode, value); + else + dom.setOuterHTML(parentNode, value); + } + + marker = dom.get('mce_marker'); + + // Scroll range into view scrollIntoView on element can't be used since it will scroll the main view port as well + nodeRect = dom.getRect(marker); + viewPortRect = dom.getViewPort(editor.getWin()); + + // Check if node is out side the viewport if it is then scroll to it + if ((nodeRect.y + nodeRect.h > viewPortRect.y + viewPortRect.h || nodeRect.y < viewPortRect.y) || + (nodeRect.x > viewPortRect.x + viewPortRect.w || nodeRect.x < viewPortRect.x)) { + viewportBodyElement = tinymce.isIE ? editor.getDoc().documentElement : editor.getBody(); + viewportBodyElement.scrollLeft = nodeRect.x; + viewportBodyElement.scrollTop = nodeRect.y - viewPortRect.h + 25; + } + + // Move selection before marker and remove it + rng = dom.createRng(); + + // If previous sibling is a text node set the selection to the end of that node + node = marker.previousSibling; + if (node && node.nodeType == 3) { + rng.setStart(node, node.nodeValue.length); + } else { + // If the previous sibling isn't a text node or doesn't exist set the selection before the marker node + rng.setStartBefore(marker); + rng.setEndBefore(marker); + } + + // Remove the marker node and set the new range + dom.remove(marker); + selection.setRng(rng); + + // Dispatch after event and add any visual elements needed + selection.onSetContent.dispatch(selection, args); + editor.addVisual(); + }, + + mceInsertRawHTML : function(command, ui, value) { + selection.setContent('tiny_mce_marker'); + editor.setContent(editor.getContent().replace(/tiny_mce_marker/g, function() { return value })); + }, + + mceSetContent : function(command, ui, value) { + editor.setContent(value); + }, + + 'Indent,Outdent' : function(command) { + var intentValue, indentUnit, value; + + // Setup indent level + intentValue = settings.indentation; + indentUnit = /[a-z%]+$/i.exec(intentValue); + intentValue = parseInt(intentValue); + + if (!queryCommandState('InsertUnorderedList') && !queryCommandState('InsertOrderedList')) { + each(selection.getSelectedBlocks(), function(element) { + if (command == 'outdent') { + value = Math.max(0, parseInt(element.style.paddingLeft || 0) - intentValue); + dom.setStyle(element, 'paddingLeft', value ? value + indentUnit : ''); + } else + dom.setStyle(element, 'paddingLeft', (parseInt(element.style.paddingLeft || 0) + intentValue) + indentUnit); + }); + } else + execNativeCommand(command); + }, + + mceRepaint : function() { + var bookmark; + + if (tinymce.isGecko) { + try { + storeSelection(TRUE); + + if (selection.getSel()) + selection.getSel().selectAllChildren(editor.getBody()); + + selection.collapse(TRUE); + restoreSelection(); + } catch (ex) { + // Ignore + } + } + }, + + mceToggleFormat : function(command, ui, value) { + formatter.toggle(value); + }, + + InsertHorizontalRule : function() { + editor.execCommand('mceInsertContent', false, '<hr />'); + }, + + mceToggleVisualAid : function() { + editor.hasVisual = !editor.hasVisual; + editor.addVisual(); + }, + + mceReplaceContent : function(command, ui, value) { + editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, selection.getContent({format : 'text'}))); + }, + + mceInsertLink : function(command, ui, value) { + var anchor; + + if (typeof(value) == 'string') + value = {href : value}; + + anchor = dom.getParent(selection.getNode(), 'a'); + + // Spaces are never valid in URLs and it's a very common mistake for people to make so we fix it here. + value.href = value.href.replace(' ', '%20'); + + // Remove existing links if there could be child links or that the href isn't specified + if (!anchor || !value.href) { + formatter.remove('link'); + } + + // Apply new link to selection + if (value.href) { + formatter.apply('link', value, anchor); + } + }, + + selectAll : function() { + var root = dom.getRoot(), rng = dom.createRng(); + + rng.setStart(root, 0); + rng.setEnd(root, root.childNodes.length); + + editor.selection.setRng(rng); + } + }); + + // Add queryCommandState overrides + addCommands({ + // Override justify commands + 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) { + return isFormatMatch('align' + command.substring(7)); + }, + + 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript' : function(command) { + return isFormatMatch(command); + }, + + mceBlockQuote : function() { + return isFormatMatch('blockquote'); + }, + + Outdent : function() { + var node; + + if (settings.inline_styles) { + if ((node = dom.getParent(selection.getStart(), dom.isBlock)) && parseInt(node.style.paddingLeft) > 0) + return TRUE; + + if ((node = dom.getParent(selection.getEnd(), dom.isBlock)) && parseInt(node.style.paddingLeft) > 0) + return TRUE; + } + + return queryCommandState('InsertUnorderedList') || queryCommandState('InsertOrderedList') || (!settings.inline_styles && !!dom.getParent(selection.getNode(), 'BLOCKQUOTE')); + }, + + 'InsertUnorderedList,InsertOrderedList' : function(command) { + return dom.getParent(selection.getNode(), command == 'insertunorderedlist' ? 'UL' : 'OL'); + } + }, 'state'); + + // Add queryCommandValue overrides + addCommands({ + 'FontSize,FontName' : function(command) { + var value = 0, parent; + + if (parent = dom.getParent(selection.getNode(), 'span')) { + if (command == 'fontsize') + value = parent.style.fontSize; + else + value = parent.style.fontFamily.replace(/, /g, ',').replace(/[\'\"]/g, '').toLowerCase(); + } + + return value; + } + }, 'value'); + + // Add undo manager logic + if (settings.custom_undo_redo) { + addCommands({ + Undo : function() { + editor.undoManager.undo(); + }, + + Redo : function() { + editor.undoManager.redo(); + } + }); + } + }; +})(tinymce); + +(function(tinymce) { + var Dispatcher = tinymce.util.Dispatcher; + + tinymce.UndoManager = function(editor) { + var self, index = 0, data = [], beforeBookmark; + + function getContent() { + return tinymce.trim(editor.getContent({format : 'raw', no_events : 1})); + }; + + return self = { + typing : false, + + onAdd : new Dispatcher(self), + + onUndo : new Dispatcher(self), + + onRedo : new Dispatcher(self), + + beforeChange : function() { + beforeBookmark = editor.selection.getBookmark(2, true); + }, + + add : function(level) { + var i, settings = editor.settings, lastLevel; + + level = level || {}; + level.content = getContent(); + + // Add undo level if needed + lastLevel = data[index]; + if (lastLevel && lastLevel.content == level.content) + return null; + + // Set before bookmark on previous level + if (data[index]) + data[index].beforeBookmark = beforeBookmark; + + // Time to compress + if (settings.custom_undo_redo_levels) { + if (data.length > settings.custom_undo_redo_levels) { + for (i = 0; i < data.length - 1; i++) + data[i] = data[i + 1]; + + data.length--; + index = data.length; + } + } + + // Get a non intrusive normalized bookmark + level.bookmark = editor.selection.getBookmark(2, true); + + // Crop array if needed + if (index < data.length - 1) + data.length = index + 1; + + data.push(level); + index = data.length - 1; + + self.onAdd.dispatch(self, level); + editor.isNotDirty = 0; + + return level; + }, + + undo : function() { + var level, i; + + if (self.typing) { + self.add(); + self.typing = false; + } + + if (index > 0) { + level = data[--index]; + + editor.setContent(level.content, {format : 'raw'}); + editor.selection.moveToBookmark(level.beforeBookmark); + + self.onUndo.dispatch(self, level); + } + + return level; + }, + + redo : function() { + var level; + + if (index < data.length - 1) { + level = data[++index]; + + editor.setContent(level.content, {format : 'raw'}); + editor.selection.moveToBookmark(level.bookmark); + + self.onRedo.dispatch(self, level); + } + + return level; + }, + + clear : function() { + data = []; + index = 0; + self.typing = false; + }, + + hasUndo : function() { + return index > 0 || this.typing; + }, + + hasRedo : function() { + return index < data.length - 1 && !this.typing; + } + }; + }; +})(tinymce); + +(function(tinymce) { + // Shorten names + var Event = tinymce.dom.Event, + isIE = tinymce.isIE, + isGecko = tinymce.isGecko, + isOpera = tinymce.isOpera, + each = tinymce.each, + extend = tinymce.extend, + TRUE = true, + FALSE = false; + + function cloneFormats(node) { + var clone, temp, inner; + + do { + if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) { + if (clone) { + temp = node.cloneNode(false); + temp.appendChild(clone); + clone = temp; + } else { + clone = inner = node.cloneNode(false); + } + + clone.removeAttribute('id'); + } + } while (node = node.parentNode); + + if (clone) + return {wrapper : clone, inner : inner}; + }; + + // Checks if the selection/caret is at the end of the specified block element + function isAtEnd(rng, par) { + var rng2 = par.ownerDocument.createRange(); + + rng2.setStart(rng.endContainer, rng.endOffset); + rng2.setEndAfter(par); + + // Get number of characters to the right of the cursor if it's zero then we are at the end and need to merge the next block element + return rng2.cloneContents().textContent.length == 0; + }; + + function splitList(selection, dom, li) { + var listBlock, block; + + if (dom.isEmpty(li)) { + listBlock = dom.getParent(li, 'ul,ol'); + + if (!dom.getParent(listBlock.parentNode, 'ul,ol')) { + dom.split(listBlock, li); + block = dom.create('p', 0, '<br data-mce-bogus="1" />'); + dom.replace(block, li); + selection.select(block, 1); + } + + return FALSE; + } + + return TRUE; + }; + + tinymce.create('tinymce.ForceBlocks', { + ForceBlocks : function(ed) { + var t = this, s = ed.settings, elm; + + t.editor = ed; + t.dom = ed.dom; + elm = (s.forced_root_block || 'p').toLowerCase(); + s.element = elm.toUpperCase(); + + ed.onPreInit.add(t.setup, t); + }, + + setup : function() { + var t = this, ed = t.editor, s = ed.settings, dom = ed.dom, selection = ed.selection, blockElements = ed.schema.getBlockElements(); + + // Force root blocks + if (s.forced_root_block) { + function addRootBlocks() { + var node = selection.getStart(), rootNode = ed.getBody(), rng, startContainer, startOffset, endContainer, endOffset, rootBlockNode, tempNode, offset = -0xFFFFFF; + + if (!node || node.nodeType !== 1) + return; + + // Check if node is wrapped in block + while (node != rootNode) { + if (blockElements[node.nodeName]) + return; + + node = node.parentNode; + } + + // Get current selection + rng = selection.getRng(); + if (rng.setStart) { + startContainer = rng.startContainer; + startOffset = rng.startOffset; + endContainer = rng.endContainer; + endOffset = rng.endOffset; + } else { + // Force control range into text range + if (rng.item) { + rng = ed.getDoc().body.createTextRange(); + rng.moveToElementText(rng.item(0)); + } + + tmpRng = rng.duplicate(); + tmpRng.collapse(true); + startOffset = tmpRng.move('character', offset) * -1; + + if (!tmpRng.collapsed) { + tmpRng = rng.duplicate(); + tmpRng.collapse(false); + endOffset = (tmpRng.move('character', offset) * -1) - startOffset; + } + } + + // Wrap non block elements and text nodes + for (node = rootNode.firstChild; node; node) { + if (node.nodeType === 3 || (node.nodeType == 1 && !blockElements[node.nodeName])) { + if (!rootBlockNode) { + rootBlockNode = dom.create(s.forced_root_block); + node.parentNode.insertBefore(rootBlockNode, node); + } + + tempNode = node; + node = node.nextSibling; + rootBlockNode.appendChild(tempNode); + } else { + rootBlockNode = null; + node = node.nextSibling; + } + } + + if (rng.setStart) { + rng.setStart(startContainer, startOffset); + rng.setEnd(endContainer, endOffset); + selection.setRng(rng); + } else { + try { + rng = ed.getDoc().body.createTextRange(); + rng.moveToElementText(rootNode); + rng.collapse(true); + rng.moveStart('character', startOffset); + + if (endOffset > 0) + rng.moveEnd('character', endOffset); + + rng.select(); + } catch (ex) { + // Ignore + } + } + + ed.nodeChanged(); + }; + + ed.onKeyUp.add(addRootBlocks); + ed.onClick.add(addRootBlocks); + } + + if (s.force_br_newlines) { + // Force IE to produce BRs on enter + if (isIE) { + ed.onKeyPress.add(function(ed, e) { + var n; + + if (e.keyCode == 13 && selection.getNode().nodeName != 'LI') { + selection.setContent('<br id="__" /> ', {format : 'raw'}); + n = dom.get('__'); + n.removeAttribute('id'); + selection.select(n); + selection.collapse(); + return Event.cancel(e); + } + }); + } + } + + if (s.force_p_newlines) { + if (!isIE) { + ed.onKeyPress.add(function(ed, e) { + if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) + Event.cancel(e); + }); + } else { + // Ungly hack to for IE to preserve the formatting when you press + // enter at the end of a block element with formatted contents + // This logic overrides the browsers default logic with + // custom logic that enables us to control the output + tinymce.addUnload(function() { + t._previousFormats = 0; // Fix IE leak + }); + + ed.onKeyPress.add(function(ed, e) { + t._previousFormats = 0; + + // Clone the current formats, this will later be applied to the new block contents + if (e.keyCode == 13 && !e.shiftKey && ed.selection.isCollapsed() && s.keep_styles) + t._previousFormats = cloneFormats(ed.selection.getStart()); + }); + + ed.onKeyUp.add(function(ed, e) { + // Let IE break the element and the wrap the new caret location in the previous formats + if (e.keyCode == 13 && !e.shiftKey) { + var parent = ed.selection.getStart(), fmt = t._previousFormats; + + // Parent is an empty block + if (!parent.hasChildNodes() && fmt) { + parent = dom.getParent(parent, dom.isBlock); + + if (parent && parent.nodeName != 'LI') { + parent.innerHTML = ''; + + if (t._previousFormats) { + parent.appendChild(fmt.wrapper); + fmt.inner.innerHTML = '\uFEFF'; + } else + parent.innerHTML = '\uFEFF'; + + selection.select(parent, 1); + selection.collapse(true); + ed.getDoc().execCommand('Delete', false, null); + t._previousFormats = 0; + } + } + } + }); + } + + if (isGecko) { + ed.onKeyDown.add(function(ed, e) { + if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) + t.backspaceDelete(e, e.keyCode == 8); + }); + } + } + + // Workaround for missing shift+enter support, http://bugs.webkit.org/show_bug.cgi?id=16973 + if (tinymce.isWebKit) { + function insertBr(ed) { + var rng = selection.getRng(), br, div = dom.create('div', null, ' '), divYPos, vpHeight = dom.getViewPort(ed.getWin()).h; + + // Insert BR element + rng.insertNode(br = dom.create('br')); + + // Place caret after BR + rng.setStartAfter(br); + rng.setEndAfter(br); + selection.setRng(rng); + + // Could not place caret after BR then insert an nbsp entity and move the caret + if (selection.getSel().focusNode == br.previousSibling) { + selection.select(dom.insertAfter(dom.doc.createTextNode('\u00a0'), br)); + selection.collapse(TRUE); + } + + // Create a temporary DIV after the BR and get the position as it + // seems like getPos() returns 0 for text nodes and BR elements. + dom.insertAfter(div, br); + divYPos = dom.getPos(div).y; + dom.remove(div); + + // Scroll to new position, scrollIntoView can't be used due to bug: http://bugs.webkit.org/show_bug.cgi?id=16117 + if (divYPos > vpHeight) // It is not necessary to scroll if the DIV is inside the view port. + ed.getWin().scrollTo(0, divYPos); + }; + + ed.onKeyPress.add(function(ed, e) { + if (e.keyCode == 13 && (e.shiftKey || (s.force_br_newlines && !dom.getParent(selection.getNode(), 'h1,h2,h3,h4,h5,h6,ol,ul')))) { + insertBr(ed); + Event.cancel(e); + } + }); + } + + // IE specific fixes + if (isIE) { + // Replaces IE:s auto generated paragraphs with the specified element name + if (s.element != 'P') { + ed.onKeyPress.add(function(ed, e) { + t.lastElm = selection.getNode().nodeName; + }); + + ed.onKeyUp.add(function(ed, e) { + var bl, n = selection.getNode(), b = ed.getBody(); + + if (b.childNodes.length === 1 && n.nodeName == 'P') { + n = dom.rename(n, s.element); + selection.select(n); + selection.collapse(); + ed.nodeChanged(); + } else if (e.keyCode == 13 && !e.shiftKey && t.lastElm != 'P') { + bl = dom.getParent(n, 'p'); + + if (bl) { + dom.rename(bl, s.element); + ed.nodeChanged(); + } + } + }); + } + } + }, + + getParentBlock : function(n) { + var d = this.dom; + + return d.getParent(n, d.isBlock); + }, + + insertPara : function(e) { + var t = this, ed = t.editor, dom = ed.dom, d = ed.getDoc(), se = ed.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body; + var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n, vp = dom.getViewPort(ed.getWin()), y, ch, car; + + ed.undoManager.beforeChange(); + + // If root blocks are forced then use Operas default behavior since it's really good +// Removed due to bug: #1853816 +// if (se.forced_root_block && isOpera) +// return TRUE; + + // Setup before range + rb = d.createRange(); + + // If is before the first block element and in body, then move it into first block element + rb.setStart(s.anchorNode, s.anchorOffset); + rb.collapse(TRUE); + + // Setup after range + ra = d.createRange(); + + // If is before the first block element and in body, then move it into first block element + ra.setStart(s.focusNode, s.focusOffset); + ra.collapse(TRUE); + + // Setup start/end points + dir = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0; + sn = dir ? s.anchorNode : s.focusNode; + so = dir ? s.anchorOffset : s.focusOffset; + en = dir ? s.focusNode : s.anchorNode; + eo = dir ? s.focusOffset : s.anchorOffset; + + // If selection is in empty table cell + if (sn === en && /^(TD|TH)$/.test(sn.nodeName)) { + if (sn.firstChild.nodeName == 'BR') + dom.remove(sn.firstChild); // Remove BR + + // Create two new block elements + if (sn.childNodes.length == 0) { + ed.dom.add(sn, se.element, null, '<br />'); + aft = ed.dom.add(sn, se.element, null, '<br />'); + } else { + n = sn.innerHTML; + sn.innerHTML = ''; + ed.dom.add(sn, se.element, null, n); + aft = ed.dom.add(sn, se.element, null, '<br />'); + } + + // Move caret into the last one + r = d.createRange(); + r.selectNodeContents(aft); + r.collapse(1); + ed.selection.setRng(r); + + return FALSE; + } + + // If the caret is in an invalid location in FF we need to move it into the first block + if (sn == b && en == b && b.firstChild && ed.dom.isBlock(b.firstChild)) { + sn = en = sn.firstChild; + so = eo = 0; + rb = d.createRange(); + rb.setStart(sn, 0); + ra = d.createRange(); + ra.setStart(en, 0); + } + + // If the body is totally empty add a BR element this might happen on webkit + if (!d.body.hasChildNodes()) { + d.body.appendChild(dom.create('br')); + } + + // Never use body as start or end node + sn = sn.nodeName == "HTML" ? d.body : sn; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes + sn = sn.nodeName == "BODY" ? sn.firstChild : sn; + en = en.nodeName == "HTML" ? d.body : en; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes + en = en.nodeName == "BODY" ? en.firstChild : en; + + // Get start and end blocks + sb = t.getParentBlock(sn); + eb = t.getParentBlock(en); + bn = sb ? sb.nodeName : se.element; // Get block name to create + + // Return inside list use default browser behavior + if (n = t.dom.getParent(sb, 'li,pre')) { + if (n.nodeName == 'LI') + return splitList(ed.selection, t.dom, n); + + return TRUE; + } + + // If caption or absolute layers then always generate new blocks within + if (sb && (sb.nodeName == 'CAPTION' || /absolute|relative|fixed/gi.test(dom.getStyle(sb, 'position', 1)))) { + bn = se.element; + sb = null; + } + + // If caption or absolute layers then always generate new blocks within + if (eb && (eb.nodeName == 'CAPTION' || /absolute|relative|fixed/gi.test(dom.getStyle(sb, 'position', 1)))) { + bn = se.element; + eb = null; + } + + // Use P instead + if (/(TD|TABLE|TH|CAPTION)/.test(bn) || (sb && bn == "DIV" && /left|right/gi.test(dom.getStyle(sb, 'float', 1)))) { + bn = se.element; + sb = eb = null; + } + + // Setup new before and after blocks + bef = (sb && sb.nodeName == bn) ? sb.cloneNode(0) : ed.dom.create(bn); + aft = (eb && eb.nodeName == bn) ? eb.cloneNode(0) : ed.dom.create(bn); + + // Remove id from after clone + aft.removeAttribute('id'); + + // Is header and cursor is at the end, then force paragraph under + if (/^(H[1-6])$/.test(bn) && isAtEnd(r, sb)) + aft = ed.dom.create(se.element); + + // Find start chop node + n = sc = sn; + do { + if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName)) + break; + + sc = n; + } while ((n = n.previousSibling ? n.previousSibling : n.parentNode)); + + // Find end chop node + n = ec = en; + do { + if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName)) + break; + + ec = n; + } while ((n = n.nextSibling ? n.nextSibling : n.parentNode)); + + // Place first chop part into before block element + if (sc.nodeName == bn) + rb.setStart(sc, 0); + else + rb.setStartBefore(sc); + + rb.setEnd(sn, so); + bef.appendChild(rb.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari + + // Place secnd chop part within new block element + try { + ra.setEndAfter(ec); + } catch(ex) { + //console.debug(s.focusNode, s.focusOffset); + } + + ra.setStart(en, eo); + aft.appendChild(ra.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari + + // Create range around everything + r = d.createRange(); + if (!sc.previousSibling && sc.parentNode.nodeName == bn) { + r.setStartBefore(sc.parentNode); + } else { + if (rb.startContainer.nodeName == bn && rb.startOffset == 0) + r.setStartBefore(rb.startContainer); + else + r.setStart(rb.startContainer, rb.startOffset); + } + + if (!ec.nextSibling && ec.parentNode.nodeName == bn) + r.setEndAfter(ec.parentNode); + else + r.setEnd(ra.endContainer, ra.endOffset); + + // Delete and replace it with new block elements + r.deleteContents(); + + if (isOpera) + ed.getWin().scrollTo(0, vp.y); + + // Never wrap blocks in blocks + if (bef.firstChild && bef.firstChild.nodeName == bn) + bef.innerHTML = bef.firstChild.innerHTML; + + if (aft.firstChild && aft.firstChild.nodeName == bn) + aft.innerHTML = aft.firstChild.innerHTML; + + function appendStyles(e, en) { + var nl = [], nn, n, i; + + e.innerHTML = ''; + + // Make clones of style elements + if (se.keep_styles) { + n = en; + do { + // We only want style specific elements + if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(n.nodeName)) { + nn = n.cloneNode(FALSE); + dom.setAttrib(nn, 'id', ''); // Remove ID since it needs to be unique + nl.push(nn); + } + } while (n = n.parentNode); + } + + // Append style elements to aft + if (nl.length > 0) { + for (i = nl.length - 1, nn = e; i >= 0; i--) + nn = nn.appendChild(nl[i]); + + // Padd most inner style element + nl[0].innerHTML = isOpera ? '\u00a0' : '<br />'; // Extra space for Opera so that the caret can move there + return nl[0]; // Move caret to most inner element + } else + e.innerHTML = isOpera ? '\u00a0' : '<br />'; // Extra space for Opera so that the caret can move there + }; + + // Padd empty blocks + if (dom.isEmpty(bef)) + appendStyles(bef, sn); + + // Fill empty afterblook with current style + if (dom.isEmpty(aft)) + car = appendStyles(aft, en); + + // Opera needs this one backwards for older versions + if (isOpera && parseFloat(opera.version()) < 9.5) { + r.insertNode(bef); + r.insertNode(aft); + } else { + r.insertNode(aft); + r.insertNode(bef); + } + + // Normalize + aft.normalize(); + bef.normalize(); + + // Move cursor and scroll into view + ed.selection.select(aft, true); + ed.selection.collapse(true); + + // scrollIntoView seems to scroll the parent window in most browsers now including FF 3.0b4 so it's time to stop using it and do it our selfs + y = ed.dom.getPos(aft).y; + //ch = aft.clientHeight; + + // Is element within viewport + if (y < vp.y || y + 25 > vp.y + vp.h) { + ed.getWin().scrollTo(0, y < vp.y ? y : y - vp.h + 25); // Needs to be hardcoded to roughly one line of text if a huge text block is broken into two blocks + + /*console.debug( + 'Element: y=' + y + ', h=' + ch + ', ' + + 'Viewport: y=' + vp.y + ", h=" + vp.h + ', bottom=' + (vp.y + vp.h) + );*/ + } + + ed.undoManager.add(); + + return FALSE; + }, + + backspaceDelete : function(e, bs) { + var t = this, ed = t.editor, b = ed.getBody(), dom = ed.dom, n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn, walker; + + // Delete when caret is behind a element doesn't work correctly on Gecko see #3011651 + if (!bs && r.collapsed && sc.nodeType == 1 && r.startOffset == sc.childNodes.length) { + walker = new tinymce.dom.TreeWalker(sc.lastChild, sc); + + // Walk the dom backwards until we find a text node + for (n = sc.lastChild; n; n = walker.prev()) { + if (n.nodeType == 3) { + r.setStart(n, n.nodeValue.length); + r.collapse(true); + se.setRng(r); + return; + } + } + } + + // The caret sometimes gets stuck in Gecko if you delete empty paragraphs + // This workaround removes the element by hand and moves the caret to the previous element + if (sc && ed.dom.isBlock(sc) && !/^(TD|TH)$/.test(sc.nodeName) && bs) { + if (sc.childNodes.length == 0 || (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR')) { + // Find previous block element + n = sc; + while ((n = n.previousSibling) && !ed.dom.isBlock(n)) ; + + if (n) { + if (sc != b.firstChild) { + // Find last text node + w = ed.dom.doc.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, FALSE); + while (tn = w.nextNode()) + n = tn; + + // Place caret at the end of last text node + r = ed.getDoc().createRange(); + r.setStart(n, n.nodeValue ? n.nodeValue.length : 0); + r.setEnd(n, n.nodeValue ? n.nodeValue.length : 0); + se.setRng(r); + + // Remove the target container + ed.dom.remove(sc); + } + + return Event.cancel(e); + } + } + } + } + }); +})(tinymce); + +(function(tinymce) { + // Shorten names + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, extend = tinymce.extend; + + tinymce.create('tinymce.ControlManager', { + ControlManager : function(ed, s) { + var t = this, i; + + s = s || {}; + t.editor = ed; + t.controls = {}; + t.onAdd = new tinymce.util.Dispatcher(t); + t.onPostRender = new tinymce.util.Dispatcher(t); + t.prefix = s.prefix || ed.id + '_'; + t._cls = {}; + + t.onPostRender.add(function() { + each(t.controls, function(c) { + c.postRender(); + }); + }); + }, + + get : function(id) { + return this.controls[this.prefix + id] || this.controls[id]; + }, + + setActive : function(id, s) { + var c = null; + + if (c = this.get(id)) + c.setActive(s); + + return c; + }, + + setDisabled : function(id, s) { + var c = null; + + if (c = this.get(id)) + c.setDisabled(s); + + return c; + }, + + add : function(c) { + var t = this; + + if (c) { + t.controls[c.id] = c; + t.onAdd.dispatch(c, t); + } + + return c; + }, + + createControl : function(n) { + var c, t = this, ed = t.editor; + + each(ed.plugins, function(p) { + if (p.createControl) { + c = p.createControl(n, t); + + if (c) + return false; + } + }); + + switch (n) { + case "|": + case "separator": + return t.createSeparator(); + } + + if (!c && ed.buttons && (c = ed.buttons[n])) + return t.createButton(n, c); + + return t.add(c); + }, + + createDropMenu : function(id, s, cc) { + var t = this, ed = t.editor, c, bm, v, cls; + + s = extend({ + 'class' : 'mceDropDown', + constrain : ed.settings.constrain_menus + }, s); + + s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin'; + if (v = ed.getParam('skin_variant')) + s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1); + + id = t.prefix + id; + cls = cc || t._cls.dropmenu || tinymce.ui.DropMenu; + c = t.controls[id] = new cls(id, s); + c.onAddItem.add(function(c, o) { + var s = o.settings; + + s.title = ed.getLang(s.title, s.title); + + if (!s.onclick) { + s.onclick = function(v) { + if (s.cmd) + ed.execCommand(s.cmd, s.ui || false, s.value); + }; + } + }); + + ed.onRemove.add(function() { + c.destroy(); + }); + + // Fix for bug #1897785, #1898007 + if (tinymce.isIE) { + c.onShowMenu.add(function() { + // IE 8 needs focus in order to store away a range with the current collapsed caret location + ed.focus(); + + bm = ed.selection.getBookmark(1); + }); + + c.onHideMenu.add(function() { + if (bm) { + ed.selection.moveToBookmark(bm); + bm = 0; + } + }); + } + + return t.add(c); + }, + + createListBox : function(id, s, cc) { + var t = this, ed = t.editor, cmd, c, cls; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.scope = s.scope || ed; + + if (!s.onselect) { + s.onselect = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + scope : s.scope, + control_manager : t + }, s); + + id = t.prefix + id; + + + function useNativeListForAccessibility(ed) { + return ed.settings.use_accessible_selects && !tinymce.isGecko + } + + if (ed.settings.use_native_selects || useNativeListForAccessibility(ed)) + c = new tinymce.ui.NativeListBox(id, s); + else { + cls = cc || t._cls.listbox || tinymce.ui.ListBox; + c = new cls(id, s, ed); + } + + t.controls[id] = c; + + // Fix focus problem in Safari + if (tinymce.isWebKit) { + c.onPostRender.add(function(c, n) { + // Store bookmark on mousedown + Event.add(n, 'mousedown', function() { + ed.bookmark = ed.selection.getBookmark(1); + }); + + // Restore on focus, since it might be lost + Event.add(n, 'focus', function() { + ed.selection.moveToBookmark(ed.bookmark); + ed.bookmark = null; + }); + }); + } + + if (c.hideMenu) + ed.onMouseDown.add(c.hideMenu, c); + + return t.add(c); + }, + + createButton : function(id, s, cc) { + var t = this, ed = t.editor, o, c, cls; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.label = ed.translate(s.label); + s.scope = s.scope || ed; + + if (!s.onclick && !s.menu_button) { + s.onclick = function() { + ed.execCommand(s.cmd, s.ui || false, s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + unavailable_prefix : ed.getLang('unavailable', ''), + scope : s.scope, + control_manager : t + }, s); + + id = t.prefix + id; + + if (s.menu_button) { + cls = cc || t._cls.menubutton || tinymce.ui.MenuButton; + c = new cls(id, s, ed); + ed.onMouseDown.add(c.hideMenu, c); + } else { + cls = t._cls.button || tinymce.ui.Button; + c = new cls(id, s, ed); + } + + return t.add(c); + }, + + createMenuButton : function(id, s, cc) { + s = s || {}; + s.menu_button = 1; + + return this.createButton(id, s, cc); + }, + + createSplitButton : function(id, s, cc) { + var t = this, ed = t.editor, cmd, c, cls; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.scope = s.scope || ed; + + if (!s.onclick) { + s.onclick = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + if (!s.onselect) { + s.onselect = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + scope : s.scope, + control_manager : t + }, s); + + id = t.prefix + id; + cls = cc || t._cls.splitbutton || tinymce.ui.SplitButton; + c = t.add(new cls(id, s, ed)); + ed.onMouseDown.add(c.hideMenu, c); + + return c; + }, + + createColorSplitButton : function(id, s, cc) { + var t = this, ed = t.editor, cmd, c, cls, bm; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.scope = s.scope || ed; + + if (!s.onclick) { + s.onclick = function(v) { + if (tinymce.isIE) + bm = ed.selection.getBookmark(1); + + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + if (!s.onselect) { + s.onselect = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + 'menu_class' : ed.getParam('skin') + 'Skin', + scope : s.scope, + more_colors_title : ed.getLang('more_colors') + }, s); + + id = t.prefix + id; + cls = cc || t._cls.colorsplitbutton || tinymce.ui.ColorSplitButton; + c = new cls(id, s, ed); + ed.onMouseDown.add(c.hideMenu, c); + + // Remove the menu element when the editor is removed + ed.onRemove.add(function() { + c.destroy(); + }); + + // Fix for bug #1897785, #1898007 + if (tinymce.isIE) { + c.onShowMenu.add(function() { + // IE 8 needs focus in order to store away a range with the current collapsed caret location + ed.focus(); + bm = ed.selection.getBookmark(1); + }); + + c.onHideMenu.add(function() { + if (bm) { + ed.selection.moveToBookmark(bm); + bm = 0; + } + }); + } + + return t.add(c); + }, + + createToolbar : function(id, s, cc) { + var c, t = this, cls; + + id = t.prefix + id; + cls = cc || t._cls.toolbar || tinymce.ui.Toolbar; + c = new cls(id, s, t.editor); + + if (t.get(id)) + return null; + + return t.add(c); + }, + + createToolbarGroup : function(id, s, cc) { + var c, t = this, cls; + id = t.prefix + id; + cls = cc || this._cls.toolbarGroup || tinymce.ui.ToolbarGroup; + c = new cls(id, s, t.editor); + + if (t.get(id)) + return null; + + return t.add(c); + }, + + createSeparator : function(cc) { + var cls = cc || this._cls.separator || tinymce.ui.Separator; + + return new cls(); + }, + + setControlType : function(n, c) { + return this._cls[n.toLowerCase()] = c; + }, + + destroy : function() { + each(this.controls, function(c) { + c.destroy(); + }); + + this.controls = null; + } + }); +})(tinymce); + +(function(tinymce) { + var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isIE = tinymce.isIE, isOpera = tinymce.isOpera; + + tinymce.create('tinymce.WindowManager', { + WindowManager : function(ed) { + var t = this; + + t.editor = ed; + t.onOpen = new Dispatcher(t); + t.onClose = new Dispatcher(t); + t.params = {}; + t.features = {}; + }, + + open : function(s, p) { + var t = this, f = '', x, y, mo = t.editor.settings.dialog_type == 'modal', w, sw, sh, vp = tinymce.DOM.getViewPort(), u; + + // Default some options + s = s || {}; + p = p || {}; + sw = isOpera ? vp.w : screen.width; // Opera uses windows inside the Opera window + sh = isOpera ? vp.h : screen.height; + s.name = s.name || 'mc_' + new Date().getTime(); + s.width = parseInt(s.width || 320); + s.height = parseInt(s.height || 240); + s.resizable = true; + s.left = s.left || parseInt(sw / 2.0) - (s.width / 2.0); + s.top = s.top || parseInt(sh / 2.0) - (s.height / 2.0); + p.inline = false; + p.mce_width = s.width; + p.mce_height = s.height; + p.mce_auto_focus = s.auto_focus; + + if (mo) { + if (isIE) { + s.center = true; + s.help = false; + s.dialogWidth = s.width + 'px'; + s.dialogHeight = s.height + 'px'; + s.scroll = s.scrollbars || false; + } + } + + // Build features string + each(s, function(v, k) { + if (tinymce.is(v, 'boolean')) + v = v ? 'yes' : 'no'; + + if (!/^(name|url)$/.test(k)) { + if (isIE && mo) + f += (f ? ';' : '') + k + ':' + v; + else + f += (f ? ',' : '') + k + '=' + v; + } + }); + + t.features = s; + t.params = p; + t.onOpen.dispatch(t, s, p); + + u = s.url || s.file; + u = tinymce._addVer(u); + + try { + if (isIE && mo) { + w = 1; + window.showModalDialog(u, window, f); + } else + w = window.open(u, s.name, f); + } catch (ex) { + // Ignore + } + + if (!w) + alert(t.editor.getLang('popup_blocked')); + }, + + close : function(w) { + w.close(); + this.onClose.dispatch(this); + }, + + createInstance : function(cl, a, b, c, d, e) { + var f = tinymce.resolve(cl); + + return new f(a, b, c, d, e); + }, + + confirm : function(t, cb, s, w) { + w = w || window; + + cb.call(s || this, w.confirm(this._decode(this.editor.getLang(t, t)))); + }, + + alert : function(tx, cb, s, w) { + var t = this; + + w = w || window; + w.alert(t._decode(t.editor.getLang(tx, tx))); + + if (cb) + cb.call(s || t); + }, + + resizeBy : function(dw, dh, win) { + win.resizeBy(dw, dh); + }, + + // Internal functions + + _decode : function(s) { + return tinymce.DOM.decode(s).replace(/\\n/g, '\n'); + } + }); +}(tinymce)); +(function(tinymce) { + tinymce.Formatter = function(ed) { + var formats = {}, + each = tinymce.each, + dom = ed.dom, + selection = ed.selection, + TreeWalker = tinymce.dom.TreeWalker, + rangeUtils = new tinymce.dom.RangeUtils(dom), + isValid = ed.schema.isValidChild, + isBlock = dom.isBlock, + forcedRootBlock = ed.settings.forced_root_block, + nodeIndex = dom.nodeIndex, + INVISIBLE_CHAR = '\uFEFF', + MCE_ATTR_RE = /^(src|href|style)$/, + FALSE = false, + TRUE = true, + undefined, + pendingFormats = {apply : [], remove : []}; + + function isArray(obj) { + return obj instanceof Array; + }; + + function getParents(node, selector) { + return dom.getParents(node, selector, dom.getRoot()); + }; + + function isCaretNode(node) { + return node.nodeType === 1 && (node.face === 'mceinline' || node.style.fontFamily === 'mceinline'); + }; + + // Public functions + + function get(name) { + return name ? formats[name] : formats; + }; + + function register(name, format) { + if (name) { + if (typeof(name) !== 'string') { + each(name, function(format, name) { + register(name, format); + }); + } else { + // Force format into array and add it to internal collection + format = format.length ? format : [format]; + + each(format, function(format) { + // Set deep to false by default on selector formats this to avoid removing + // alignment on images inside paragraphs when alignment is changed on paragraphs + if (format.deep === undefined) + format.deep = !format.selector; + + // Default to true + if (format.split === undefined) + format.split = !format.selector || format.inline; + + // Default to true + if (format.remove === undefined && format.selector && !format.inline) + format.remove = 'none'; + + // Mark format as a mixed format inline + block level + if (format.selector && format.inline) { + format.mixed = true; + format.block_expand = true; + } + + // Split classes if needed + if (typeof(format.classes) === 'string') + format.classes = format.classes.split(/\s+/); + }); + + formats[name] = format; + } + } + }; + + var getTextDecoration = function(node) { + var decoration; + + ed.dom.getParent(node, function(n) { + decoration = ed.dom.getStyle(n, 'text-decoration'); + return decoration && decoration !== 'none'; + }); + + return decoration; + }; + + var processUnderlineAndColor = function(node) { + var textDecoration; + if (node.nodeType === 1 && node.parentNode && node.parentNode.nodeType === 1) { + textDecoration = getTextDecoration(node.parentNode); + if (ed.dom.getStyle(node, 'color') && textDecoration) { + ed.dom.setStyle(node, 'text-decoration', textDecoration); + } else if (ed.dom.getStyle(node, 'textdecoration') === textDecoration) { + ed.dom.setStyle(node, 'text-decoration', null); + } + } + }; + + function apply(name, vars, node) { + var formatList = get(name), format = formatList[0], bookmark, rng, i, isCollapsed = selection.isCollapsed(); + + function moveStart(rng) { + var container = rng.startContainer, + offset = rng.startOffset, + walker, node; + + // Move startContainer/startOffset in to a suitable node + if (container.nodeType == 1 || container.nodeValue === "") { + container = container.nodeType == 1 ? container.childNodes[offset] : container; + + // Might fail if the offset is behind the last element in it's container + if (container) { + walker = new TreeWalker(container, container.parentNode); + for (node = walker.current(); node; node = walker.next()) { + if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { + rng.setStart(node, 0); + break; + } + } + } + } + + return rng; + }; + + function setElementFormat(elm, fmt) { + fmt = fmt || format; + + if (elm) { + if (fmt.onformat) { + fmt.onformat(elm, fmt, vars, node); + } + + each(fmt.styles, function(value, name) { + dom.setStyle(elm, name, replaceVars(value, vars)); + }); + + each(fmt.attributes, function(value, name) { + dom.setAttrib(elm, name, replaceVars(value, vars)); + }); + + each(fmt.classes, function(value) { + value = replaceVars(value, vars); + + if (!dom.hasClass(elm, value)) + dom.addClass(elm, value); + }); + } + }; + function adjustSelectionToVisibleSelection() { + function findSelectionEnd(start, end) { + var walker = new TreeWalker(end); + for (node = walker.current(); node; node = walker.prev()) { + if (node.childNodes.length > 1 || node == start) { + return node; + } + } + }; + + // Adjust selection so that a end container with a end offset of zero is not included in the selection + // as this isn't visible to the user. + var rng = ed.selection.getRng(); + var start = rng.startContainer; + var end = rng.endContainer; + + if (start != end && rng.endOffset == 0) { + var newEnd = findSelectionEnd(start, end); + var endOffset = newEnd.nodeType == 3 ? newEnd.length : newEnd.childNodes.length; + + rng.setEnd(newEnd, endOffset); + } + + return rng; + } + + function applyStyleToList(node, bookmark, wrapElm, newWrappers, process){ + var nodes = [], listIndex = -1, list, startIndex = -1, endIndex = -1, currentWrapElm; + + // find the index of the first child list. + each(node.childNodes, function(n, index) { + if (n.nodeName === "UL" || n.nodeName === "OL") { + listIndex = index; + list = n; + return false; + } + }); + + // get the index of the bookmarks + each(node.childNodes, function(n, index) { + if (n.nodeName === "SPAN" && dom.getAttrib(n, "data-mce-type") == "bookmark") { + if (n.id == bookmark.id + "_start") { + startIndex = index; + } else if (n.id == bookmark.id + "_end") { + endIndex = index; + } + } + }); + + // if the selection spans across an embedded list, or there isn't an embedded list - handle processing normally + if (listIndex <= 0 || (startIndex < listIndex && endIndex > listIndex)) { + each(tinymce.grep(node.childNodes), process); + return 0; + } else { + currentWrapElm = wrapElm.cloneNode(FALSE); + + // create a list of the nodes on the same side of the list as the selection + each(tinymce.grep(node.childNodes), function(n, index) { + if ((startIndex < listIndex && index < listIndex) || (startIndex > listIndex && index > listIndex)) { + nodes.push(n); + n.parentNode.removeChild(n); + } + }); + + // insert the wrapping element either before or after the list. + if (startIndex < listIndex) { + node.insertBefore(currentWrapElm, list); + } else if (startIndex > listIndex) { + node.insertBefore(currentWrapElm, list.nextSibling); + } + + // add the new nodes to the list. + newWrappers.push(currentWrapElm); + + each(nodes, function(node) { + currentWrapElm.appendChild(node); + }); + + return currentWrapElm; + } + }; + + function applyRngStyle(rng, bookmark) { + var newWrappers = [], wrapName, wrapElm; + + // Setup wrapper element + wrapName = format.inline || format.block; + wrapElm = dom.create(wrapName); + setElementFormat(wrapElm); + + rangeUtils.walk(rng, function(nodes) { + var currentWrapElm; + + function process(node) { + var nodeName = node.nodeName.toLowerCase(), parentName = node.parentNode.nodeName.toLowerCase(), found; + + // Stop wrapping on br elements + if (isEq(nodeName, 'br')) { + currentWrapElm = 0; + + // Remove any br elements when we wrap things + if (format.block) + dom.remove(node); + + return; + } + + // If node is wrapper type + if (format.wrapper && matchNode(node, name, vars)) { + currentWrapElm = 0; + return; + } + + // Can we rename the block + if (format.block && !format.wrapper && isTextBlock(nodeName)) { + node = dom.rename(node, wrapName); + setElementFormat(node); + newWrappers.push(node); + currentWrapElm = 0; + return; + } + + // Handle selector patterns + if (format.selector) { + // Look for matching formats + each(formatList, function(format) { + // Check collapsed state if it exists + if ('collapsed' in format && format.collapsed !== isCollapsed) { + return; + } + + if (dom.is(node, format.selector) && !isCaretNode(node)) { + setElementFormat(node, format); + found = true; + } + }); + + // Continue processing if a selector match wasn't found and a inline element is defined + if (!format.inline || found) { + currentWrapElm = 0; + return; + } + } + + // Is it valid to wrap this item + if (isValid(wrapName, nodeName) && isValid(parentName, wrapName) && + !(node.nodeType === 3 && node.nodeValue.length === 1 && node.nodeValue.charCodeAt(0) === 65279)) { + // Start wrapping + if (!currentWrapElm) { + // Wrap the node + currentWrapElm = wrapElm.cloneNode(FALSE); + node.parentNode.insertBefore(currentWrapElm, node); + newWrappers.push(currentWrapElm); + } + + currentWrapElm.appendChild(node); + } else if (nodeName == 'li' && bookmark) { + // Start wrapping - if we are in a list node and have a bookmark, then we will always begin by wrapping in a new element. + currentWrapElm = applyStyleToList(node, bookmark, wrapElm, newWrappers, process); + } else { + // Start a new wrapper for possible children + currentWrapElm = 0; + + each(tinymce.grep(node.childNodes), process); + + // End the last wrapper + currentWrapElm = 0; + } + }; + + // Process siblings from range + each(nodes, process); + }); + + // Wrap links inside as well, for example color inside a link when the wrapper is around the link + if (format.wrap_links === false) { + each(newWrappers, function(node) { + function process(node) { + var i, currentWrapElm, children; + + if (node.nodeName === 'A') { + currentWrapElm = wrapElm.cloneNode(FALSE); + newWrappers.push(currentWrapElm); + + children = tinymce.grep(node.childNodes); + for (i = 0; i < children.length; i++) + currentWrapElm.appendChild(children[i]); + + node.appendChild(currentWrapElm); + } + + each(tinymce.grep(node.childNodes), process); + }; + + process(node); + }); + } + + // Cleanup + each(newWrappers, function(node) { + var childCount; + + function getChildCount(node) { + var count = 0; + + each(node.childNodes, function(node) { + if (!isWhiteSpaceNode(node) && !isBookmarkNode(node)) + count++; + }); + + return count; + }; + + function mergeStyles(node) { + var child, clone; + + each(node.childNodes, function(node) { + if (node.nodeType == 1 && !isBookmarkNode(node) && !isCaretNode(node)) { + child = node; + return FALSE; // break loop + } + }); + + // If child was found and of the same type as the current node + if (child && matchName(child, format)) { + clone = child.cloneNode(FALSE); + setElementFormat(clone); + + dom.replace(clone, node, TRUE); + dom.remove(child, 1); + } + + return clone || node; + }; + + childCount = getChildCount(node); + + // Remove empty nodes but only if there is multiple wrappers and they are not block + // elements so never remove single <h1></h1> since that would remove the currrent empty block element where the caret is at + if ((newWrappers.length > 1 || !isBlock(node)) && childCount === 0) { + dom.remove(node, 1); + return; + } + + if (format.inline || format.wrapper) { + // Merges the current node with it's children of similar type to reduce the number of elements + if (!format.exact && childCount === 1) + node = mergeStyles(node); + + // Remove/merge children + each(formatList, function(format) { + // Merge all children of similar type will move styles from child to parent + // this: <span style="color:red"><b><span style="color:red; font-size:10px">text</span></b></span> + // will become: <span style="color:red"><b><span style="font-size:10px">text</span></b></span> + each(dom.select(format.inline, node), function(child) { + var parent; + + // When wrap_links is set to false we don't want + // to remove the format on children within links + if (format.wrap_links === false) { + parent = child.parentNode; + + do { + if (parent.nodeName === 'A') + return; + } while (parent = parent.parentNode); + } + + removeFormat(format, vars, child, format.exact ? child : null); + }); + }); + + // Remove child if direct parent is of same type + if (matchNode(node.parentNode, name, vars)) { + dom.remove(node, 1); + node = 0; + return TRUE; + } + + // Look for parent with similar style format + if (format.merge_with_parents) { + dom.getParent(node.parentNode, function(parent) { + if (matchNode(parent, name, vars)) { + dom.remove(node, 1); + node = 0; + return TRUE; + } + }); + } + + // Merge next and previous siblings if they are similar <b>text</b><b>text</b> becomes <b>texttext</b> + if (node && format.merge_siblings !== false) { + node = mergeSiblings(getNonWhiteSpaceSibling(node), node); + node = mergeSiblings(node, getNonWhiteSpaceSibling(node, TRUE)); + } + } + }); + }; + + if (format) { + if (node) { + rng = dom.createRng(); + + rng.setStartBefore(node); + rng.setEndAfter(node); + + applyRngStyle(expandRng(rng, formatList)); + } else { + if (!isCollapsed || !format.inline || dom.select('td.mceSelected,th.mceSelected').length) { + // Obtain selection node before selection is unselected by applyRngStyle() + var curSelNode = ed.selection.getNode(); + + // Apply formatting to selection + ed.selection.setRng(adjustSelectionToVisibleSelection()); + bookmark = selection.getBookmark(); + applyRngStyle(expandRng(selection.getRng(TRUE), formatList), bookmark); + + // Colored nodes should be underlined so that the color of the underline matches the text color. + if (format.styles && (format.styles.color || format.styles.textDecoration)) { + tinymce.walk(curSelNode, processUnderlineAndColor, 'childNodes'); + processUnderlineAndColor(curSelNode); + } + + selection.moveToBookmark(bookmark); + selection.setRng(moveStart(selection.getRng(TRUE))); + ed.nodeChanged(); + } else + performCaretAction('apply', name, vars); + } + } + }; + + function remove(name, vars, node) { + var formatList = get(name), format = formatList[0], bookmark, i, rng; + function moveStart(rng) { + var container = rng.startContainer, + offset = rng.startOffset, + walker, node, nodes, tmpNode; + + // Convert text node into index if possible + if (container.nodeType == 3 && offset >= container.nodeValue.length - 1) { + container = container.parentNode; + offset = nodeIndex(container) + 1; + } + + // Move startContainer/startOffset in to a suitable node + if (container.nodeType == 1) { + nodes = container.childNodes; + container = nodes[Math.min(offset, nodes.length - 1)]; + walker = new TreeWalker(container); + + // If offset is at end of the parent node walk to the next one + if (offset > nodes.length - 1) + walker.next(); + + for (node = walker.current(); node; node = walker.next()) { + if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { + // IE has a "neat" feature where it moves the start node into the closest element + // we can avoid this by inserting an element before it and then remove it after we set the selection + tmpNode = dom.create('a', null, INVISIBLE_CHAR); + node.parentNode.insertBefore(tmpNode, node); + + // Set selection and remove tmpNode + rng.setStart(node, 0); + selection.setRng(rng); + dom.remove(tmpNode); + + return; + } + } + } + }; + + // Merges the styles for each node + function process(node) { + var children, i, l; + + // Grab the children first since the nodelist might be changed + children = tinymce.grep(node.childNodes); + + // Process current node + for (i = 0, l = formatList.length; i < l; i++) { + if (removeFormat(formatList[i], vars, node, node)) + break; + } + + // Process the children + if (format.deep) { + for (i = 0, l = children.length; i < l; i++) + process(children[i]); + } + }; + + function findFormatRoot(container) { + var formatRoot; + + // Find format root + each(getParents(container.parentNode).reverse(), function(parent) { + var format; + + // Find format root element + if (!formatRoot && parent.id != '_start' && parent.id != '_end') { + // Is the node matching the format we are looking for + format = matchNode(parent, name, vars); + if (format && format.split !== false) + formatRoot = parent; + } + }); + + return formatRoot; + }; + + function wrapAndSplit(format_root, container, target, split) { + var parent, clone, lastClone, firstClone, i, formatRootParent; + + // Format root found then clone formats and split it + if (format_root) { + formatRootParent = format_root.parentNode; + + for (parent = container.parentNode; parent && parent != formatRootParent; parent = parent.parentNode) { + clone = parent.cloneNode(FALSE); + + for (i = 0; i < formatList.length; i++) { + if (removeFormat(formatList[i], vars, clone, clone)) { + clone = 0; + break; + } + } + + // Build wrapper node + if (clone) { + if (lastClone) + clone.appendChild(lastClone); + + if (!firstClone) + firstClone = clone; + + lastClone = clone; + } + } + + // Never split block elements if the format is mixed + if (split && (!format.mixed || !isBlock(format_root))) + container = dom.split(format_root, container); + + // Wrap container in cloned formats + if (lastClone) { + target.parentNode.insertBefore(lastClone, target); + firstClone.appendChild(target); + } + } + + return container; + }; + + function splitToFormatRoot(container) { + return wrapAndSplit(findFormatRoot(container), container, container, true); + }; + + function unwrap(start) { + var node = dom.get(start ? '_start' : '_end'), + out = node[start ? 'firstChild' : 'lastChild']; + + // If the end is placed within the start the result will be removed + // So this checks if the out node is a bookmark node if it is it + // checks for another more suitable node + if (isBookmarkNode(out)) + out = out[start ? 'firstChild' : 'lastChild']; + + dom.remove(node, true); + + return out; + }; + + function removeRngStyle(rng) { + var startContainer, endContainer; + + rng = expandRng(rng, formatList, TRUE); + + if (format.split) { + startContainer = getContainer(rng, TRUE); + endContainer = getContainer(rng); + + if (startContainer != endContainer) { + // Wrap start/end nodes in span element since these might be cloned/moved + startContainer = wrap(startContainer, 'span', {id : '_start', 'data-mce-type' : 'bookmark'}); + endContainer = wrap(endContainer, 'span', {id : '_end', 'data-mce-type' : 'bookmark'}); + + // Split start/end + splitToFormatRoot(startContainer); + splitToFormatRoot(endContainer); + + // Unwrap start/end to get real elements again + startContainer = unwrap(TRUE); + endContainer = unwrap(); + } else + startContainer = endContainer = splitToFormatRoot(startContainer); + + // Update range positions since they might have changed after the split operations + rng.startContainer = startContainer.parentNode; + rng.startOffset = nodeIndex(startContainer); + rng.endContainer = endContainer.parentNode; + rng.endOffset = nodeIndex(endContainer) + 1; + } + + // Remove items between start/end + rangeUtils.walk(rng, function(nodes) { + each(nodes, function(node) { + process(node); + + // Remove parent span if it only contains text-decoration: underline, yet a parent node is also underlined. + if (node.nodeType === 1 && ed.dom.getStyle(node, 'text-decoration') === 'underline' && node.parentNode && getTextDecoration(node.parentNode) === 'underline') { + removeFormat({'deep': false, 'exact': true, 'inline': 'span', 'styles': {'textDecoration' : 'underline'}}, null, node); + } + }); + }); + }; + + // Handle node + if (node) { + rng = dom.createRng(); + rng.setStartBefore(node); + rng.setEndAfter(node); + removeRngStyle(rng); + return; + } + + if (!selection.isCollapsed() || !format.inline || dom.select('td.mceSelected,th.mceSelected').length) { + bookmark = selection.getBookmark(); + removeRngStyle(selection.getRng(TRUE)); + selection.moveToBookmark(bookmark); + + // Check if start element still has formatting then we are at: "<b>text|</b>text" and need to move the start into the next text node + if (format.inline && match(name, vars, selection.getStart())) { + moveStart(selection.getRng(true)); + } + + ed.nodeChanged(); + } else + performCaretAction('remove', name, vars); + }; + + function toggle(name, vars, node) { + var fmt = get(name); + + if (match(name, vars, node) && (!('toggle' in fmt[0]) || fmt[0]['toggle'])) + remove(name, vars, node); + else + apply(name, vars, node); + }; + + function matchNode(node, name, vars, similar) { + var formatList = get(name), format, i, classes; + + function matchItems(node, format, item_name) { + var key, value, items = format[item_name], i; + + // Custom match + if (format.onmatch) { + return format.onmatch(node, format, item_name); + } + + // Check all items + if (items) { + // Non indexed object + if (items.length === undefined) { + for (key in items) { + if (items.hasOwnProperty(key)) { + if (item_name === 'attributes') + value = dom.getAttrib(node, key); + else + value = getStyle(node, key); + + if (similar && !value && !format.exact) + return; + + if ((!similar || format.exact) && !isEq(value, replaceVars(items[key], vars))) + return; + } + } + } else { + // Only one match needed for indexed arrays + for (i = 0; i < items.length; i++) { + if (item_name === 'attributes' ? dom.getAttrib(node, items[i]) : getStyle(node, items[i])) + return format; + } + } + } + + return format; + }; + + if (formatList && node) { + // Check each format in list + for (i = 0; i < formatList.length; i++) { + format = formatList[i]; + + // Name name, attributes, styles and classes + if (matchName(node, format) && matchItems(node, format, 'attributes') && matchItems(node, format, 'styles')) { + // Match classes + if (classes = format.classes) { + for (i = 0; i < classes.length; i++) { + if (!dom.hasClass(node, classes[i])) + return; + } + } + + return format; + } + } + } + }; + + function match(name, vars, node) { + var startNode, i; + + function matchParents(node) { + // Find first node with similar format settings + node = dom.getParent(node, function(node) { + return !!matchNode(node, name, vars, true); + }); + + // Do an exact check on the similar format element + return matchNode(node, name, vars); + }; + + // Check specified node + if (node) + return matchParents(node); + + // Check pending formats + if (selection.isCollapsed()) { + for (i = pendingFormats.apply.length - 1; i >= 0; i--) { + if (pendingFormats.apply[i].name == name) + return true; + } + + for (i = pendingFormats.remove.length - 1; i >= 0; i--) { + if (pendingFormats.remove[i].name == name) + return false; + } + + return matchParents(selection.getNode()); + } + + // Check selected node + node = selection.getNode(); + if (matchParents(node)) + return TRUE; + + // Check start node if it's different + startNode = selection.getStart(); + if (startNode != node) { + if (matchParents(startNode)) + return TRUE; + } + + return FALSE; + }; + + function matchAll(names, vars) { + var startElement, matchedFormatNames = [], checkedMap = {}, i, ni, name; + + // If the selection is collapsed then check pending formats + if (selection.isCollapsed()) { + for (ni = 0; ni < names.length; ni++) { + // If the name is to be removed, then stop it from being added + for (i = pendingFormats.remove.length - 1; i >= 0; i--) { + name = names[ni]; + + if (pendingFormats.remove[i].name == name) { + checkedMap[name] = true; + break; + } + } + } + + // If the format is to be applied + for (i = pendingFormats.apply.length - 1; i >= 0; i--) { + for (ni = 0; ni < names.length; ni++) { + name = names[ni]; + + if (!checkedMap[name] && pendingFormats.apply[i].name == name) { + checkedMap[name] = true; + matchedFormatNames.push(name); + } + } + } + } + + // Check start of selection for formats + startElement = selection.getStart(); + dom.getParent(startElement, function(node) { + var i, name; + + for (i = 0; i < names.length; i++) { + name = names[i]; + + if (!checkedMap[name] && matchNode(node, name, vars)) { + checkedMap[name] = true; + matchedFormatNames.push(name); + } + } + }); + + return matchedFormatNames; + }; + + function canApply(name) { + var formatList = get(name), startNode, parents, i, x, selector; + + if (formatList) { + startNode = selection.getStart(); + parents = getParents(startNode); + + for (x = formatList.length - 1; x >= 0; x--) { + selector = formatList[x].selector; + + // Format is not selector based, then always return TRUE + if (!selector) + return TRUE; + + for (i = parents.length - 1; i >= 0; i--) { + if (dom.is(parents[i], selector)) + return TRUE; + } + } + } + + return FALSE; + }; + + // Expose to public + tinymce.extend(this, { + get : get, + register : register, + apply : apply, + remove : remove, + toggle : toggle, + match : match, + matchAll : matchAll, + matchNode : matchNode, + canApply : canApply + }); + + // Private functions + + function matchName(node, format) { + // Check for inline match + if (isEq(node, format.inline)) + return TRUE; + + // Check for block match + if (isEq(node, format.block)) + return TRUE; + + // Check for selector match + if (format.selector) + return dom.is(node, format.selector); + }; + + function isEq(str1, str2) { + str1 = str1 || ''; + str2 = str2 || ''; + + str1 = '' + (str1.nodeName || str1); + str2 = '' + (str2.nodeName || str2); + + return str1.toLowerCase() == str2.toLowerCase(); + }; + + function getStyle(node, name) { + var styleVal = dom.getStyle(node, name); + + // Force the format to hex + if (name == 'color' || name == 'backgroundColor') + styleVal = dom.toHex(styleVal); + + // Opera will return bold as 700 + if (name == 'fontWeight' && styleVal == 700) + styleVal = 'bold'; + + return '' + styleVal; + }; + + function replaceVars(value, vars) { + if (typeof(value) != "string") + value = value(vars); + else if (vars) { + value = value.replace(/%(\w+)/g, function(str, name) { + return vars[name] || str; + }); + } + + return value; + }; + + function isWhiteSpaceNode(node) { + return node && node.nodeType === 3 && /^([\s\r\n]+|)$/.test(node.nodeValue); + }; + + function wrap(node, name, attrs) { + var wrapper = dom.create(name, attrs); + + node.parentNode.insertBefore(wrapper, node); + wrapper.appendChild(node); + + return wrapper; + }; + + function expandRng(rng, format, remove) { + var startContainer = rng.startContainer, + startOffset = rng.startOffset, + endContainer = rng.endContainer, + endOffset = rng.endOffset, sibling, lastIdx, leaf; + + // This function walks up the tree if there is no siblings before/after the node + function findParentContainer(container, child_name, sibling_name, root) { + var parent, child; + + root = root || dom.getRoot(); + + for (;;) { + // Check if we can move up are we at root level or body level + parent = container.parentNode; + + // Stop expanding on block elements or root depending on format + if (parent == root || (!format[0].block_expand && isBlock(parent))) + return container; + + for (sibling = parent[child_name]; sibling && sibling != container; sibling = sibling[sibling_name]) { + if (sibling.nodeType == 1 && !isBookmarkNode(sibling)) + return container; + + if (sibling.nodeType == 3 && !isWhiteSpaceNode(sibling)) + return container; + } + + container = container.parentNode; + } + + return container; + }; + + // This function walks down the tree to find the leaf at the selection. + // The offset is also returned as if node initially a leaf, the offset may be in the middle of the text node. + function findLeaf(node, offset) { + if (offset === undefined) + offset = node.nodeType === 3 ? node.length : node.childNodes.length; + while (node && node.hasChildNodes()) { + node = node.childNodes[offset]; + if (node) + offset = node.nodeType === 3 ? node.length : node.childNodes.length; + } + return { node: node, offset: offset }; + } + + // If index based start position then resolve it + if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) { + lastIdx = startContainer.childNodes.length - 1; + startContainer = startContainer.childNodes[startOffset > lastIdx ? lastIdx : startOffset]; + + if (startContainer.nodeType == 3) + startOffset = 0; + } + + // If index based end position then resolve it + if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) { + lastIdx = endContainer.childNodes.length - 1; + endContainer = endContainer.childNodes[endOffset > lastIdx ? lastIdx : endOffset - 1]; + + if (endContainer.nodeType == 3) + endOffset = endContainer.nodeValue.length; + } + + // Exclude bookmark nodes if possible + if (isBookmarkNode(startContainer.parentNode)) + startContainer = startContainer.parentNode; + + if (isBookmarkNode(startContainer)) + startContainer = startContainer.nextSibling || startContainer; + + if (isBookmarkNode(endContainer.parentNode)) { + endOffset = dom.nodeIndex(endContainer); + endContainer = endContainer.parentNode; + } + + if (isBookmarkNode(endContainer) && endContainer.previousSibling) { + endContainer = endContainer.previousSibling; + endOffset = endContainer.length; + } + + if (format[0].inline) { + // Avoid applying formatting to a trailing space. + leaf = findLeaf(endContainer, endOffset); + if (leaf.node) { + while (leaf.node && leaf.offset === 0 && leaf.node.previousSibling) + leaf = findLeaf(leaf.node.previousSibling); + + if (leaf.node && leaf.offset > 0 && leaf.node.nodeType === 3 && + leaf.node.nodeValue.charAt(leaf.offset - 1) === ' ') { + + if (leaf.offset > 1) { + endContainer = leaf.node; + endContainer.splitText(leaf.offset - 1); + } else if (leaf.node.previousSibling) { + endContainer = leaf.node.previousSibling; + } + } + } + } + + // Move start/end point up the tree if the leaves are sharp and if we are in different containers + // Example * becomes !: !<p><b><i>*text</i><i>text*</i></b></p>! + // This will reduce the number of wrapper elements that needs to be created + // Move start point up the tree + if (format[0].inline || format[0].block_expand) { + startContainer = findParentContainer(startContainer, 'firstChild', 'nextSibling'); + endContainer = findParentContainer(endContainer, 'lastChild', 'previousSibling'); + } + + // Expand start/end container to matching selector + if (format[0].selector && format[0].expand !== FALSE && !format[0].inline) { + function findSelectorEndPoint(container, sibling_name) { + var parents, i, y, curFormat; + + if (container.nodeType == 3 && container.nodeValue.length == 0 && container[sibling_name]) + container = container[sibling_name]; + + parents = getParents(container); + for (i = 0; i < parents.length; i++) { + for (y = 0; y < format.length; y++) { + curFormat = format[y]; + + // If collapsed state is set then skip formats that doesn't match that + if ("collapsed" in curFormat && curFormat.collapsed !== rng.collapsed) + continue; + + if (dom.is(parents[i], curFormat.selector)) + return parents[i]; + } + } + + return container; + }; + + // Find new startContainer/endContainer if there is better one + startContainer = findSelectorEndPoint(startContainer, 'previousSibling'); + endContainer = findSelectorEndPoint(endContainer, 'nextSibling'); + } + + // Expand start/end container to matching block element or text node + if (format[0].block || format[0].selector) { + function findBlockEndPoint(container, sibling_name, sibling_name2) { + var node; + + // Expand to block of similar type + if (!format[0].wrapper) + node = dom.getParent(container, format[0].block); + + // Expand to first wrappable block element or any block element + if (!node) + node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, isBlock); + + // Exclude inner lists from wrapping + if (node && format[0].wrapper) + node = getParents(node, 'ul,ol').reverse()[0] || node; + + // Didn't find a block element look for first/last wrappable element + if (!node) { + node = container; + + while (node[sibling_name] && !isBlock(node[sibling_name])) { + node = node[sibling_name]; + + // Break on BR but include it will be removed later on + // we can't remove it now since we need to check if it can be wrapped + if (isEq(node, 'br')) + break; + } + } + + return node || container; + }; + + // Find new startContainer/endContainer if there is better one + startContainer = findBlockEndPoint(startContainer, 'previousSibling'); + endContainer = findBlockEndPoint(endContainer, 'nextSibling'); + + // Non block element then try to expand up the leaf + if (format[0].block) { + if (!isBlock(startContainer)) + startContainer = findParentContainer(startContainer, 'firstChild', 'nextSibling'); + + if (!isBlock(endContainer)) + endContainer = findParentContainer(endContainer, 'lastChild', 'previousSibling'); + } + } + + // Setup index for startContainer + if (startContainer.nodeType == 1) { + startOffset = nodeIndex(startContainer); + startContainer = startContainer.parentNode; + } + + // Setup index for endContainer + if (endContainer.nodeType == 1) { + endOffset = nodeIndex(endContainer) + 1; + endContainer = endContainer.parentNode; + } + + // Return new range like object + return { + startContainer : startContainer, + startOffset : startOffset, + endContainer : endContainer, + endOffset : endOffset + }; + } + + function removeFormat(format, vars, node, compare_node) { + var i, attrs, stylesModified; + + // Check if node matches format + if (!matchName(node, format)) + return FALSE; + + // Should we compare with format attribs and styles + if (format.remove != 'all') { + // Remove styles + each(format.styles, function(value, name) { + value = replaceVars(value, vars); + + // Indexed array + if (typeof(name) === 'number') { + name = value; + compare_node = 0; + } + + if (!compare_node || isEq(getStyle(compare_node, name), value)) + dom.setStyle(node, name, ''); + + stylesModified = 1; + }); + + // Remove style attribute if it's empty + if (stylesModified && dom.getAttrib(node, 'style') == '') { + node.removeAttribute('style'); + node.removeAttribute('data-mce-style'); + } + + // Remove attributes + each(format.attributes, function(value, name) { + var valueOut; + + value = replaceVars(value, vars); + + // Indexed array + if (typeof(name) === 'number') { + name = value; + compare_node = 0; + } + + if (!compare_node || isEq(dom.getAttrib(compare_node, name), value)) { + // Keep internal classes + if (name == 'class') { + value = dom.getAttrib(node, name); + if (value) { + // Build new class value where everything is removed except the internal prefixed classes + valueOut = ''; + each(value.split(/\s+/), function(cls) { + if (/mce\w+/.test(cls)) + valueOut += (valueOut ? ' ' : '') + cls; + }); + + // We got some internal classes left + if (valueOut) { + dom.setAttrib(node, name, valueOut); + return; + } + } + } + + // IE6 has a bug where the attribute doesn't get removed correctly + if (name == "class") + node.removeAttribute('className'); + + // Remove mce prefixed attributes + if (MCE_ATTR_RE.test(name)) + node.removeAttribute('data-mce-' + name); + + node.removeAttribute(name); + } + }); + + // Remove classes + each(format.classes, function(value) { + value = replaceVars(value, vars); + + if (!compare_node || dom.hasClass(compare_node, value)) + dom.removeClass(node, value); + }); + + // Check for non internal attributes + attrs = dom.getAttribs(node); + for (i = 0; i < attrs.length; i++) { + if (attrs[i].nodeName.indexOf('_') !== 0) + return FALSE; + } + } + + // Remove the inline child if it's empty for example <b> or <span> + if (format.remove != 'none') { + removeNode(node, format); + return TRUE; + } + }; + + function removeNode(node, format) { + var parentNode = node.parentNode, rootBlockElm; + + if (format.block) { + if (!forcedRootBlock) { + function find(node, next, inc) { + node = getNonWhiteSpaceSibling(node, next, inc); + + return !node || (node.nodeName == 'BR' || isBlock(node)); + }; + + // Append BR elements if needed before we remove the block + if (isBlock(node) && !isBlock(parentNode)) { + if (!find(node, FALSE) && !find(node.firstChild, TRUE, 1)) + node.insertBefore(dom.create('br'), node.firstChild); + + if (!find(node, TRUE) && !find(node.lastChild, FALSE, 1)) + node.appendChild(dom.create('br')); + } + } else { + // Wrap the block in a forcedRootBlock if we are at the root of document + if (parentNode == dom.getRoot()) { + if (!format.list_block || !isEq(node, format.list_block)) { + each(tinymce.grep(node.childNodes), function(node) { + if (isValid(forcedRootBlock, node.nodeName.toLowerCase())) { + if (!rootBlockElm) + rootBlockElm = wrap(node, forcedRootBlock); + else + rootBlockElm.appendChild(node); + } else + rootBlockElm = 0; + }); + } + } + } + } + + // Never remove nodes that isn't the specified inline element if a selector is specified too + if (format.selector && format.inline && !isEq(format.inline, node)) + return; + + dom.remove(node, 1); + }; + + function getNonWhiteSpaceSibling(node, next, inc) { + if (node) { + next = next ? 'nextSibling' : 'previousSibling'; + + for (node = inc ? node : node[next]; node; node = node[next]) { + if (node.nodeType == 1 || !isWhiteSpaceNode(node)) + return node; + } + } + }; + + function isBookmarkNode(node) { + return node && node.nodeType == 1 && node.getAttribute('data-mce-type') == 'bookmark'; + }; + + function mergeSiblings(prev, next) { + var marker, sibling, tmpSibling; + + function compareElements(node1, node2) { + // Not the same name + if (node1.nodeName != node2.nodeName) + return FALSE; + + function getAttribs(node) { + var attribs = {}; + + each(dom.getAttribs(node), function(attr) { + var name = attr.nodeName.toLowerCase(); + + // Don't compare internal attributes or style + if (name.indexOf('_') !== 0 && name !== 'style') + attribs[name] = dom.getAttrib(node, name); + }); + + return attribs; + }; + + function compareObjects(obj1, obj2) { + var value, name; + + for (name in obj1) { + // Obj1 has item obj2 doesn't have + if (obj1.hasOwnProperty(name)) { + value = obj2[name]; + + // Obj2 doesn't have obj1 item + if (value === undefined) + return FALSE; + + // Obj2 item has a different value + if (obj1[name] != value) + return FALSE; + + // Delete similar value + delete obj2[name]; + } + } + + // Check if obj 2 has something obj 1 doesn't have + for (name in obj2) { + // Obj2 has item obj1 doesn't have + if (obj2.hasOwnProperty(name)) + return FALSE; + } + + return TRUE; + }; + + // Attribs are not the same + if (!compareObjects(getAttribs(node1), getAttribs(node2))) + return FALSE; + + // Styles are not the same + if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) + return FALSE; + + return TRUE; + }; + + // Check if next/prev exists and that they are elements + if (prev && next) { + function findElementSibling(node, sibling_name) { + for (sibling = node; sibling; sibling = sibling[sibling_name]) { + if (sibling.nodeType == 3 && sibling.nodeValue.length !== 0) + return node; + + if (sibling.nodeType == 1 && !isBookmarkNode(sibling)) + return sibling; + } + + return node; + }; + + // If previous sibling is empty then jump over it + prev = findElementSibling(prev, 'previousSibling'); + next = findElementSibling(next, 'nextSibling'); + + // Compare next and previous nodes + if (compareElements(prev, next)) { + // Append nodes between + for (sibling = prev.nextSibling; sibling && sibling != next;) { + tmpSibling = sibling; + sibling = sibling.nextSibling; + prev.appendChild(tmpSibling); + } + + // Remove next node + dom.remove(next); + + // Move children into prev node + each(tinymce.grep(next.childNodes), function(node) { + prev.appendChild(node); + }); + + return prev; + } + } + + return next; + }; + + function isTextBlock(name) { + return /^(h[1-6]|p|div|pre|address|dl|dt|dd)$/.test(name); + }; + + function getContainer(rng, start) { + var container, offset, lastIdx; + + container = rng[start ? 'startContainer' : 'endContainer']; + offset = rng[start ? 'startOffset' : 'endOffset']; + + if (container.nodeType == 1) { + lastIdx = container.childNodes.length - 1; + + if (!start && offset) + offset--; + + container = container.childNodes[offset > lastIdx ? lastIdx : offset]; + } + + return container; + }; + + function performCaretAction(type, name, vars) { + var i, currentPendingFormats = pendingFormats[type], + otherPendingFormats = pendingFormats[type == 'apply' ? 'remove' : 'apply']; + + function hasPending() { + return pendingFormats.apply.length || pendingFormats.remove.length; + }; + + function resetPending() { + pendingFormats.apply = []; + pendingFormats.remove = []; + }; + + function perform(caret_node) { + // Apply pending formats + each(pendingFormats.apply.reverse(), function(item) { + apply(item.name, item.vars, caret_node); + + // Colored nodes should be underlined so that the color of the underline matches the text color. + if (item.name === 'forecolor' && item.vars.value) + processUnderlineAndColor(caret_node.parentNode); + }); + + // Remove pending formats + each(pendingFormats.remove.reverse(), function(item) { + remove(item.name, item.vars, caret_node); + }); + + dom.remove(caret_node, 1); + resetPending(); + }; + + // Check if it already exists then ignore it + for (i = currentPendingFormats.length - 1; i >= 0; i--) { + if (currentPendingFormats[i].name == name) + return; + } + + currentPendingFormats.push({name : name, vars : vars}); + + // Check if it's in the other type, then remove it + for (i = otherPendingFormats.length - 1; i >= 0; i--) { + if (otherPendingFormats[i].name == name) + otherPendingFormats.splice(i, 1); + } + + // Pending apply or remove formats + if (hasPending()) { + ed.getDoc().execCommand('FontName', false, 'mceinline'); + pendingFormats.lastRng = selection.getRng(); + + // IE will convert the current word + each(dom.select('font,span'), function(node) { + var bookmark; + + if (isCaretNode(node)) { + bookmark = selection.getBookmark(); + perform(node); + selection.moveToBookmark(bookmark); + ed.nodeChanged(); + } + }); + + // Only register listeners once if we need to + if (!pendingFormats.isListening && hasPending()) { + pendingFormats.isListening = true; + function performPendingFormat(node, textNode) { + var rng = dom.createRng(); + perform(node); + + rng.setStart(textNode, textNode.nodeValue.length); + rng.setEnd(textNode, textNode.nodeValue.length); + selection.setRng(rng); + ed.nodeChanged(); + } + var enterKeyPressed = false; + + each('onKeyDown,onKeyUp,onKeyPress,onMouseUp'.split(','), function(event) { + ed[event].addToTop(function(ed, e) { + if (e.keyCode==13 && !e.shiftKey) { + enterKeyPressed = true; + return; + } + // Do we have pending formats and is the selection moved has moved + if (hasPending() && !tinymce.dom.RangeUtils.compareRanges(pendingFormats.lastRng, selection.getRng())) { + var foundCaret = false; + each(dom.select('font,span'), function(node) { + var textNode, rng; + + // Look for marker + if (isCaretNode(node)) { + foundCaret = true; + textNode = node.firstChild; + + // Find the first text node within node + while (textNode && textNode.nodeType != 3) + textNode = textNode.firstChild; + + if (textNode) + performPendingFormat(node, textNode); + else + dom.remove(node); + } + }); + + // no caret - so we are + if (enterKeyPressed && !foundCaret) { + var node = selection.getNode(); + var textNode = node; + + // Find the first text node within node + while (textNode && textNode.nodeType != 3) + textNode = textNode.firstChild; + if (textNode) { + node=textNode.parentNode; + while (!isBlock(node)){ + node=node.parentNode; + } + performPendingFormat(node, textNode); + } + } + + // Always unbind and clear pending styles on keyup + if (e.type == 'keyup' || e.type == 'mouseup') { + resetPending(); + enterKeyPressed=false; + } + } + }); + }); + } + } + }; + }; +})(tinymce); + +tinymce.onAddEditor.add(function(tinymce, ed) { + var filters, fontSizes, dom, settings = ed.settings; + + if (settings.inline_styles) { + fontSizes = tinymce.explode(settings.font_size_style_values); + + function replaceWithSpan(node, styles) { + tinymce.each(styles, function(value, name) { + if (value) + dom.setStyle(node, name, value); + }); + + dom.rename(node, 'span'); + }; + + filters = { + font : function(dom, node) { + replaceWithSpan(node, { + backgroundColor : node.style.backgroundColor, + color : node.color, + fontFamily : node.face, + fontSize : fontSizes[parseInt(node.size) - 1] + }); + }, + + u : function(dom, node) { + replaceWithSpan(node, { + textDecoration : 'underline' + }); + }, + + strike : function(dom, node) { + replaceWithSpan(node, { + textDecoration : 'line-through' + }); + } + }; + + function convert(editor, params) { + dom = editor.dom; + + if (settings.convert_fonts_to_spans) { + tinymce.each(dom.select('font,u,strike', params.node), function(node) { + filters[node.nodeName.toLowerCase()](ed.dom, node); + }); + } + }; + + ed.onPreProcess.add(convert); + ed.onSetContent.add(convert); + + ed.onInit.add(function() { + ed.selection.onSetContent.add(convert); + }); + } +}); + diff --git a/src/core/static/js/tiny_mce/utils/editable_selects.js b/src/core/static/js/tiny_mce/utils/editable_selects.js new file mode 100644 index 0000000..4b920f3 --- /dev/null +++ b/src/core/static/js/tiny_mce/utils/editable_selects.js @@ -0,0 +1,70 @@ +/** + * editable_selects.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +var TinyMCE_EditableSelects = { + editSelectElm : null, + + init : function() { + var nl = document.getElementsByTagName("select"), i, d = document, o; + + for (i=0; i<nl.length; i++) { + if (nl[i].className.indexOf('mceEditableSelect') != -1) { + o = new Option(tinyMCEPopup.editor.translate('value'), '__mce_add_custom__'); + + o.className = 'mceAddSelectValue'; + + nl[i].options[nl[i].options.length] = o; + nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect; + } + } + }, + + onChangeEditableSelect : function(e) { + var d = document, ne, se = window.event ? window.event.srcElement : e.target; + + if (se.options[se.selectedIndex].value == '__mce_add_custom__') { + ne = d.createElement("input"); + ne.id = se.id + "_custom"; + ne.name = se.name + "_custom"; + ne.type = "text"; + + ne.style.width = se.offsetWidth + 'px'; + se.parentNode.insertBefore(ne, se); + se.style.display = 'none'; + ne.focus(); + ne.onblur = TinyMCE_EditableSelects.onBlurEditableSelectInput; + ne.onkeydown = TinyMCE_EditableSelects.onKeyDown; + TinyMCE_EditableSelects.editSelectElm = se; + } + }, + + onBlurEditableSelectInput : function() { + var se = TinyMCE_EditableSelects.editSelectElm; + + if (se) { + if (se.previousSibling.value != '') { + addSelectValue(document.forms[0], se.id, se.previousSibling.value, se.previousSibling.value); + selectByValue(document.forms[0], se.id, se.previousSibling.value); + } else + selectByValue(document.forms[0], se.id, ''); + + se.style.display = 'inline'; + se.parentNode.removeChild(se.previousSibling); + TinyMCE_EditableSelects.editSelectElm = null; + } + }, + + onKeyDown : function(e) { + e = e || window.event; + + if (e.keyCode == 13) + TinyMCE_EditableSelects.onBlurEditableSelectInput(); + } +}; diff --git a/src/core/static/js/tiny_mce/utils/form_utils.js b/src/core/static/js/tiny_mce/utils/form_utils.js new file mode 100644 index 0000000..59da013 --- /dev/null +++ b/src/core/static/js/tiny_mce/utils/form_utils.js @@ -0,0 +1,210 @@ +/** + * form_utils.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +var themeBaseURL = tinyMCEPopup.editor.baseURI.toAbsolute('themes/' + tinyMCEPopup.getParam("theme")); + +function getColorPickerHTML(id, target_form_element) { + var h = "", dom = tinyMCEPopup.dom; + + if (label = dom.select('label[for=' + target_form_element + ']')[0]) { + label.id = label.id || dom.uniqueId(); + } + + h += '<a role="button" aria-labelledby="' + id + '_label" id="' + id + '_link" href="javascript:;" onclick="tinyMCEPopup.pickColor(event,\'' + target_form_element +'\');" onmousedown="return false;" class="pickcolor">'; + h += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '">&nbsp;<span id="' + id + '_label" class="mceVoiceLabel mceIconOnly" style="display:none;">' + tinyMCEPopup.getLang('browse') + '</span></span></a>'; + + return h; +} + +function updateColor(img_id, form_element_id) { + document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value; +} + +function setBrowserDisabled(id, state) { + var img = document.getElementById(id); + var lnk = document.getElementById(id + "_link"); + + if (lnk) { + if (state) { + lnk.setAttribute("realhref", lnk.getAttribute("href")); + lnk.removeAttribute("href"); + tinyMCEPopup.dom.addClass(img, 'disabled'); + } else { + if (lnk.getAttribute("realhref")) + lnk.setAttribute("href", lnk.getAttribute("realhref")); + + tinyMCEPopup.dom.removeClass(img, 'disabled'); + } + } +} + +function getBrowserHTML(id, target_form_element, type, prefix) { + var option = prefix + "_" + type + "_browser_callback", cb, html; + + cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback")); + + if (!cb) + return ""; + + html = ""; + html += '<a id="' + id + '_link" href="javascript:openBrowser(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;" class="browse">'; + html += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '">&nbsp;</span></a>'; + + return html; +} + +function openBrowser(img_id, target_form_element, type, option) { + var img = document.getElementById(img_id); + + if (img.className != "mceButtonDisabled") + tinyMCEPopup.openBrowser(target_form_element, type, option); +} + +function selectByValue(form_obj, field_name, value, add_custom, ignore_case) { + if (!form_obj || !form_obj.elements[field_name]) + return; + + if (!value) + value = ""; + + var sel = form_obj.elements[field_name]; + + var found = false; + for (var i=0; i<sel.options.length; i++) { + var option = sel.options[i]; + + if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) { + option.selected = true; + found = true; + } else + option.selected = false; + } + + if (!found && add_custom && value != '') { + var option = new Option(value, value); + option.selected = true; + sel.options[sel.options.length] = option; + sel.selectedIndex = sel.options.length - 1; + } + + return found; +} + +function getSelectValue(form_obj, field_name) { + var elm = form_obj.elements[field_name]; + + if (elm == null || elm.options == null || elm.selectedIndex === -1) + return ""; + + return elm.options[elm.selectedIndex].value; +} + +function addSelectValue(form_obj, field_name, name, value) { + var s = form_obj.elements[field_name]; + var o = new Option(name, value); + s.options[s.options.length] = o; +} + +function addClassesToList(list_id, specific_option) { + // Setup class droplist + var styleSelectElm = document.getElementById(list_id); + var styles = tinyMCEPopup.getParam('theme_advanced_styles', false); + styles = tinyMCEPopup.getParam(specific_option, styles); + + if (styles) { + var stylesAr = styles.split(';'); + + for (var i=0; i<stylesAr.length; i++) { + if (stylesAr != "") { + var key, value; + + key = stylesAr[i].split('=')[0]; + value = stylesAr[i].split('=')[1]; + + styleSelectElm.options[styleSelectElm.length] = new Option(key, value); + } + } + } else { + tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) { + styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']); + }); + } +} + +function isVisible(element_id) { + var elm = document.getElementById(element_id); + + return elm && elm.style.display != "none"; +} + +function convertRGBToHex(col) { + var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi"); + + var rgb = col.replace(re, "$1,$2,$3").split(','); + if (rgb.length == 3) { + r = parseInt(rgb[0]).toString(16); + g = parseInt(rgb[1]).toString(16); + b = parseInt(rgb[2]).toString(16); + + r = r.length == 1 ? '0' + r : r; + g = g.length == 1 ? '0' + g : g; + b = b.length == 1 ? '0' + b : b; + + return "#" + r + g + b; + } + + return col; +} + +function convertHexToRGB(col) { + if (col.indexOf('#') != -1) { + col = col.replace(new RegExp('[^0-9A-F]', 'gi'), ''); + + r = parseInt(col.substring(0, 2), 16); + g = parseInt(col.substring(2, 4), 16); + b = parseInt(col.substring(4, 6), 16); + + return "rgb(" + r + "," + g + "," + b + ")"; + } + + return col; +} + +function trimSize(size) { + return size.replace(/([0-9\.]+)(px|%|in|cm|mm|em|ex|pt|pc)/i, '$1$2'); +} + +function getCSSSize(size) { + size = trimSize(size); + + if (size == "") + return ""; + + // Add px + if (/^[0-9]+$/.test(size)) + size += 'px'; + // Sanity check, IE doesn't like broken values + else if (!(/^[0-9\.]+(px|%|in|cm|mm|em|ex|pt|pc)$/i.test(size))) + return ""; + + return size; +} + +function getStyle(elm, attrib, style) { + var val = tinyMCEPopup.dom.getAttrib(elm, attrib); + + if (val != '') + return '' + val; + + if (typeof(style) == 'undefined') + style = attrib; + + return tinyMCEPopup.dom.getStyle(elm, style); +} diff --git a/src/core/static/js/tiny_mce/utils/mctabs.js b/src/core/static/js/tiny_mce/utils/mctabs.js new file mode 100644 index 0000000..458ec86 --- /dev/null +++ b/src/core/static/js/tiny_mce/utils/mctabs.js @@ -0,0 +1,162 @@ +/** + * mctabs.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function MCTabs() { + this.settings = []; + this.onChange = tinyMCEPopup.editor.windowManager.createInstance('tinymce.util.Dispatcher'); +}; + +MCTabs.prototype.init = function(settings) { + this.settings = settings; +}; + +MCTabs.prototype.getParam = function(name, default_value) { + var value = null; + + value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name]; + + // Fix bool values + if (value == "true" || value == "false") + return (value == "true"); + + return value; +}; + +MCTabs.prototype.showTab =function(tab){ + tab.className = 'current'; + tab.setAttribute("aria-selected", true); + tab.setAttribute("aria-expanded", true); + tab.tabIndex = 0; +}; + +MCTabs.prototype.hideTab =function(tab){ + var t=this; + + tab.className = ''; + tab.setAttribute("aria-selected", false); + tab.setAttribute("aria-expanded", false); + tab.tabIndex = -1; +}; + +MCTabs.prototype.showPanel = function(panel) { + panel.className = 'current'; + panel.setAttribute("aria-hidden", false); +}; + +MCTabs.prototype.hidePanel = function(panel) { + panel.className = 'panel'; + panel.setAttribute("aria-hidden", true); +}; + +MCTabs.prototype.getPanelForTab = function(tabElm) { + return tinyMCEPopup.dom.getAttrib(tabElm, "aria-controls"); +}; + +MCTabs.prototype.displayTab = function(tab_id, panel_id, avoid_focus) { + var panelElm, panelContainerElm, tabElm, tabContainerElm, selectionClass, nodes, i, t = this; + + tabElm = document.getElementById(tab_id); + + if (panel_id === undefined) { + panel_id = t.getPanelForTab(tabElm); + } + + panelElm= document.getElementById(panel_id); + panelContainerElm = panelElm ? panelElm.parentNode : null; + tabContainerElm = tabElm ? tabElm.parentNode : null; + selectionClass = t.getParam('selection_class', 'current'); + + if (tabElm && tabContainerElm) { + nodes = tabContainerElm.childNodes; + + // Hide all other tabs + for (i = 0; i < nodes.length; i++) { + if (nodes[i].nodeName == "LI") { + t.hideTab(nodes[i]); + } + } + + // Show selected tab + t.showTab(tabElm); + } + + if (panelElm && panelContainerElm) { + nodes = panelContainerElm.childNodes; + + // Hide all other panels + for (i = 0; i < nodes.length; i++) { + if (nodes[i].nodeName == "DIV") + t.hidePanel(nodes[i]); + } + + if (!avoid_focus) { + tabElm.focus(); + } + + // Show selected panel + t.showPanel(panelElm); + } +}; + +MCTabs.prototype.getAnchor = function() { + var pos, url = document.location.href; + + if ((pos = url.lastIndexOf('#')) != -1) + return url.substring(pos + 1); + + return ""; +}; + + +//Global instance +var mcTabs = new MCTabs(); + +tinyMCEPopup.onInit.add(function() { + var tinymce = tinyMCEPopup.getWin().tinymce, dom = tinyMCEPopup.dom, each = tinymce.each; + + each(dom.select('div.tabs'), function(tabContainerElm) { + var keyNav; + + dom.setAttrib(tabContainerElm, "role", "tablist"); + + var items = tinyMCEPopup.dom.select('li', tabContainerElm); + var action = function(id) { + mcTabs.displayTab(id, mcTabs.getPanelForTab(id)); + mcTabs.onChange.dispatch(id); + }; + + each(items, function(item) { + dom.setAttrib(item, 'role', 'tab'); + dom.bind(item, 'click', function(evt) { + action(item.id); + }); + }); + + dom.bind(dom.getRoot(), 'keydown', function(evt) { + if (evt.keyCode === 9 && evt.ctrlKey && !evt.altKey) { // Tab + keyNav.moveFocus(evt.shiftKey ? -1 : 1); + tinymce.dom.Event.cancel(evt); + } + }); + + each(dom.select('a', tabContainerElm), function(a) { + dom.setAttrib(a, 'tabindex', '-1'); + }); + + keyNav = tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', { + root: tabContainerElm, + items: items, + onAction: action, + actOnFocus: true, + enableLeftRight: true, + enableUpDown: true + }, tinyMCEPopup.dom); + }); +}); \ No newline at end of file diff --git a/src/core/static/js/tiny_mce/utils/validate.js b/src/core/static/js/tiny_mce/utils/validate.js new file mode 100644 index 0000000..27cbfab --- /dev/null +++ b/src/core/static/js/tiny_mce/utils/validate.js @@ -0,0 +1,252 @@ +/** + * validate.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +/** + // String validation: + + if (!Validator.isEmail('myemail')) + alert('Invalid email.'); + + // Form validation: + + var f = document.forms['myform']; + + if (!Validator.isEmail(f.myemail)) + alert('Invalid email.'); +*/ + +var Validator = { + isEmail : function(s) { + return this.test(s, '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$'); + }, + + isAbsUrl : function(s) { + return this.test(s, '^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$'); + }, + + isSize : function(s) { + return this.test(s, '^[0-9.]+(%|in|cm|mm|em|ex|pt|pc|px)?$'); + }, + + isId : function(s) { + return this.test(s, '^[A-Za-z_]([A-Za-z0-9_])*$'); + }, + + isEmpty : function(s) { + var nl, i; + + if (s.nodeName == 'SELECT' && s.selectedIndex < 1) + return true; + + if (s.type == 'checkbox' && !s.checked) + return true; + + if (s.type == 'radio') { + for (i=0, nl = s.form.elements; i<nl.length; i++) { + if (nl[i].type == "radio" && nl[i].name == s.name && nl[i].checked) + return false; + } + + return true; + } + + return new RegExp('^\\s*$').test(s.nodeType == 1 ? s.value : s); + }, + + isNumber : function(s, d) { + return !isNaN(s.nodeType == 1 ? s.value : s) && (!d || !this.test(s, '^-?[0-9]*\\.[0-9]*$')); + }, + + test : function(s, p) { + s = s.nodeType == 1 ? s.value : s; + + return s == '' || new RegExp(p).test(s); + } +}; + +var AutoValidator = { + settings : { + id_cls : 'id', + int_cls : 'int', + url_cls : 'url', + number_cls : 'number', + email_cls : 'email', + size_cls : 'size', + required_cls : 'required', + invalid_cls : 'invalid', + min_cls : 'min', + max_cls : 'max' + }, + + init : function(s) { + var n; + + for (n in s) + this.settings[n] = s[n]; + }, + + validate : function(f) { + var i, nl, s = this.settings, c = 0; + + nl = this.tags(f, 'label'); + for (i=0; i<nl.length; i++) { + this.removeClass(nl[i], s.invalid_cls); + nl[i].setAttribute('aria-invalid', false); + } + + c += this.validateElms(f, 'input'); + c += this.validateElms(f, 'select'); + c += this.validateElms(f, 'textarea'); + + return c == 3; + }, + + invalidate : function(n) { + this.mark(n.form, n); + }, + + getErrorMessages : function(f) { + var nl, i, s = this.settings, field, msg, values, messages = [], ed = tinyMCEPopup.editor; + nl = this.tags(f, "label"); + for (i=0; i<nl.length; i++) { + if (this.hasClass(nl[i], s.invalid_cls)) { + field = document.getElementById(nl[i].getAttribute("for")); + values = { field: nl[i].textContent }; + if (this.hasClass(field, s.min_cls, true)) { + message = ed.getLang('invalid_data_min'); + values.min = this.getNum(field, s.min_cls); + } else if (this.hasClass(field, s.number_cls)) { + message = ed.getLang('invalid_data_number'); + } else if (this.hasClass(field, s.size_cls)) { + message = ed.getLang('invalid_data_size'); + } else { + message = ed.getLang('invalid_data'); + } + + message = message.replace(/{\#([^}]+)\}/g, function(a, b) { + return values[b] || '{#' + b + '}'; + }); + messages.push(message); + } + } + return messages; + }, + + reset : function(e) { + var t = ['label', 'input', 'select', 'textarea']; + var i, j, nl, s = this.settings; + + if (e == null) + return; + + for (i=0; i<t.length; i++) { + nl = this.tags(e.form ? e.form : e, t[i]); + for (j=0; j<nl.length; j++) { + this.removeClass(nl[j], s.invalid_cls); + nl[j].setAttribute('aria-invalid', false); + } + } + }, + + validateElms : function(f, e) { + var nl, i, n, s = this.settings, st = true, va = Validator, v; + + nl = this.tags(f, e); + for (i=0; i<nl.length; i++) { + n = nl[i]; + + this.removeClass(n, s.invalid_cls); + + if (this.hasClass(n, s.required_cls) && va.isEmpty(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.number_cls) && !va.isNumber(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.int_cls) && !va.isNumber(n, true)) + st = this.mark(f, n); + + if (this.hasClass(n, s.url_cls) && !va.isAbsUrl(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.email_cls) && !va.isEmail(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.size_cls) && !va.isSize(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.id_cls) && !va.isId(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.min_cls, true)) { + v = this.getNum(n, s.min_cls); + + if (isNaN(v) || parseInt(n.value) < parseInt(v)) + st = this.mark(f, n); + } + + if (this.hasClass(n, s.max_cls, true)) { + v = this.getNum(n, s.max_cls); + + if (isNaN(v) || parseInt(n.value) > parseInt(v)) + st = this.mark(f, n); + } + } + + return st; + }, + + hasClass : function(n, c, d) { + return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className); + }, + + getNum : function(n, c) { + c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0]; + c = c.replace(/[^0-9]/g, ''); + + return c; + }, + + addClass : function(n, c, b) { + var o = this.removeClass(n, c); + n.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c; + }, + + removeClass : function(n, c) { + c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' '); + return n.className = c != ' ' ? c : ''; + }, + + tags : function(f, s) { + return f.getElementsByTagName(s); + }, + + mark : function(f, n) { + var s = this.settings; + + this.addClass(n, s.invalid_cls); + n.setAttribute('aria-invalid', 'true'); + this.markLabels(f, n, s.invalid_cls); + + return false; + }, + + markLabels : function(f, n, ic) { + var nl, i; + + nl = this.tags(f, "label"); + for (i=0; i<nl.length; i++) { + if (nl[i].getAttribute("for") == n.id || nl[i].htmlFor == n.id) + this.addClass(nl[i], ic); + } + + return null; + } +}; diff --git a/src/export/.gitkeep b/src/export/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/getFile.php b/src/getFile.php new file mode 100644 index 0000000..a3277c4 --- /dev/null +++ b/src/getFile.php @@ -0,0 +1,79 @@ +<?php +if (!defined('GLZ_LOADED')) +{ + require_once('core/core.inc.php'); + $application = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.Application', 'application'); + org_glizy_Paths::addClassSearchPath('admin/application/classes/'); + + if (file_exists(org_glizy_Paths::get('APPLICATION_STARTUP'))) + { + // if the startup folder is defined all files are included + glz_require_once_dir(org_glizy_Paths::get('APPLICATION_STARTUP')); + } +} + + +$id = isset($_REQUEST['id']) ? $_REQUEST['id'] : NULL; +if (is_null($id)) exit; + +glz_import('org.glizycms.mediaArchive.MediaManager'); +$media = org_glizycms_mediaArchive_MediaManager::getMediaById($id); +if (!$media || !$media->exists()) { + header('HTTP/1.0 404 Not Found'); + echo "<h1>404 Not Found ".$media->originalFileName."</h1>"; + exit(); +} + +$browser=id_browser(); +$extension = strtolower(substr(strrchr($media->originalFileName, '.'),1)); +switch( $extension ) +{ + case "pdf": + $ctype="application/pdf"; + $disposition = "inline"; + break; + case "vcf": $ctype="application/vcard"; break; + case "exe": + $ctype= ($browser=='IE' || $browser=='OPERA') ? "application/octetstream" : "application/octet-stream"; + break; + case "zip": $ctype="application/zip"; break; + case "doc": $ctype="application/msword"; break; + case "xls": $ctype="application/vnd.ms-excel"; break; + case "ppt": $ctype="application/vnd.ms-powerpoint"; break; + case "gif": $ctype="image/gif"; break; + case "png": $ctype="image/png"; break; + case "jpeg": + case "jpg": $ctype="image/jpg"; break; + default: $ctype="application/force-download"; +} + + +header("Pragma: public"); +header("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); +header("Cache-Control: private",false); +header("Content-Type: ".$ctype); +header("Content-Transfer-Encoding: binary"); +header("Content-Disposition: ". ($disposition ?: 'attachment')."; filename=\"".$media->originalFileName."\""); +@readfile($media->getFileName()) or die(); + +$media->addDownloadCount(); + +function id_browser() +{ + $browser=$GLOBALS['__SERVER']['HTTP_USER_AGENT']; + + if(ereg('Opera(/| )([0-9].[0-9]{1,2})', $browser)) { + return 'OPERA'; + } else if(ereg('MSIE ([0-9].[0-9]{1,2})', $browser)) { + return 'IE'; + } else if(ereg('OmniWeb/([0-9].[0-9]{1,2})', $browser)) { + return 'OMNIWEB'; + } else if(ereg('(Konqueror/)(.*)', $browser)) { + return 'KONQUEROR'; + } else if(ereg('Mozilla/([0-9].[0-9]{1,2})', $browser)) { + return 'MOZILLA'; + } else { + return 'OTHER'; + } +} \ No newline at end of file diff --git a/src/getImage.php b/src/getImage.php new file mode 100644 index 0000000..dba9475 --- /dev/null +++ b/src/getImage.php @@ -0,0 +1,84 @@ +<?php +if (!defined('GLZ_LOADED')) +{ + require_once('core/core.inc.php'); + $application = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.Application', 'application'); + org_glizy_Paths::addClassSearchPath('admin/application/classes/'); + + if (file_exists(org_glizy_Paths::get('APPLICATION_STARTUP'))) + { + // if the startup folder is defined all files are included + glz_require_once_dir(org_glizy_Paths::get('APPLICATION_STARTUP')); + } +} + + +$id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : NULL; +$w = isset($_REQUEST['w']) ? intval($_REQUEST['w']) : NULL; +$h = isset($_REQUEST['h']) ? intval($_REQUEST['h']) : NULL; +$force = isset($_REQUEST['f']) ? $_REQUEST['f']=='true' || $_REQUEST['f']=='1': false; +$crop = isset($_REQUEST['c']) ? $_REQUEST['c']=='true' || $_REQUEST['c']=='1' : false; +$useThumbnail = isset($_REQUEST['t']) ? $_REQUEST['t']=='true' || $_REQUEST['t']=='1' : false; +$cropOffset = isset($_REQUEST['co']) ? $_REQUEST['co'] : 0; + + +if (is_null($id)) exit; + +glz_import('org.glizycms.mediaArchive.MediaManager'); +$media = org_glizycms_mediaArchive_MediaManager::getMediaById($id); +if ( $useThumbnail && !empty( $media->ar->media_thumbFileName ) ) +{ + $media->ar->media_fileName = $media->ar->media_thumbFileName; + $media->ar->media_type = 'IMAGE'; + $media = org_glizycms_mediaArchive_MediaManager::getMediaByRecord( $media->ar ); +} + +if (!is_null($w) && !is_null($h)) +{ + //resize the image + if ($media->type!='IMAGE') + { + $iconFile = $media->getIconFileName(); + header( 'location: '.$iconFile ); + } + $mediaInfo = $media->getResizeImage($w, $h, $crop, $cropOffset, $force); +} +else +{ + // get the full image + $mediaInfo = $media->getImageInfo(); +} + +$gmdate_mod = gmdate("D, d M Y H:i:s", filemtime( $mediaInfo['fileName'] ) ); +if(! strstr($gmdate_mod, "GMT")) +{ + $gmdate_mod .= " GMT"; +} + +if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) +{ + // check for updates + $if_modified_since = preg_replace("/;.*$/", "", $_SERVER["HTTP_IF_MODIFIED_SINCE"]); + + if ($if_modified_since == $gmdate_mod) + { + header("HTTP/1.1 304 Not Modified"); + exit; + } + +} + +$fileSize = filesize( $mediaInfo['fileName'] ); + +// send headers then display image +$mimeType = !is_string($mediaInfo['imageType']) ? image_type_to_mime_type($mediaInfo['imageType']) : $mediaInfo['imageType']; +header("Content-Type: ".$mimeType); +header("Accept-Ranges: bytes"); +header("Last-Modified: " . $gmdate_mod); +header("Content-Length: " . $fileSize); +header("Etag: " . md5($mediaInfo['fileName'])); +header("Cache-Control: max-age=9999, must-revalidate"); +header("Expires: " . $gmdate_mod); +// header("Content-Disposition: inline; filename=\"".$mediaInfo['fileName']."\""); +@readfile($mediaInfo['fileName']); +exit; \ No newline at end of file diff --git a/src/index.php b/src/index.php new file mode 100644 index 0000000..47aa3c5 --- /dev/null +++ b/src/index.php @@ -0,0 +1,6 @@ +<?php +require_once("core/core.inc.php"); + +$application = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.Application', 'application'); +org_glizy_Paths::addClassSearchPath('admin/application/classes/'); +$application->run(); diff --git a/src/static/OpenSeadragon/OpenSeadragon.debug.js b/src/static/OpenSeadragon/OpenSeadragon.debug.js new file mode 100644 index 0000000..b2e17fb --- /dev/null +++ b/src/static/OpenSeadragon/OpenSeadragon.debug.js @@ -0,0 +1,4240 @@ +// (c) 2010 OpenSeadragon, (c) 2010 CodePlex Foundation +// modify by Daniele Ugoletti for Glizy Framework + +if ( !window.SeadragonConfig ) { + window.SeadragonConfig = {}; + SeadragonConfig.imgPath = ''; +} + +Array.prototype.add = function(array, item) { + array[array.length] = item; +}; + +Array.prototype.clear = function(array) { + array.length = 0; +}; + +Array.prototype.clone = function(array) { + return array.length === 1 ? [array[0]] : Array.apply(null, array); +}; +SArray = Array(); + +if (!window.Function) { + window.Function = {}; +} +Function.prototype.createDelegate = function(object, method) { + return function() { + if (arguments === undefined) + arguments = []; + return method.apply(object, arguments); + }; +} + +// function String() { +// } +String.format = function(format, args) { + return String._toFormattedString(false, arguments); +} +String._toFormattedString = function(useLocale, args) { + var result = ''; + var format = args[0]; + + for (var i = 0; ; ) { + var open = format.indexOf('{', i); + var close = format.indexOf('}', i); + if ((open < 0) && (close < 0)) { + result += format.slice(i); + break; + } + if ((close > 0) && ((close < open) || (open < 0))) { + if (format.charAt(close + 1) !== '}') { + throw Error.argument('format', Sys.Res.stringFormatBraceMismatch); + } + result += format.slice(i, close + 1); + i = close + 2; + continue; + } + + result += format.slice(i, open); + i = open + 1; + + if (format.charAt(i) === '{') { + result += '{'; + i++; + continue; + } + + if (close < 0) throw Error.argument('format', Sys.Res.stringFormatBraceMismatch); + + + var brace = format.substring(i, close); + var colonIndex = brace.indexOf(':'); + var argNumber = parseInt((colonIndex < 0) ? brace : brace.substring(0, colonIndex), 10) + 1; + if (isNaN(argNumber)) throw Error.argument('format', Sys.Res.stringFormatInvalid); + var argFormat = (colonIndex < 0) ? '' : brace.substring(colonIndex + 1); + + var arg = args[argNumber]; + if (typeof (arg) === "undefined" || arg === null) { + arg = ''; + } + + if (arg.toFormattedString) { + result += arg.toFormattedString(argFormat); + } + else if (useLocale && arg.localeFormat) { + result += arg.localeFormat(argFormat); + } + else if (arg.format) { + result += arg.format(argFormat); + } + else + result += arg.toString(); + + i = close + 1; + } + + return result; +} + +function Observer() { } +Observer.prototype = { + _getContext: function(obj, create) { + var ctx = obj._observerContext; + if (ctx) return ctx(); + if (create) { + return (obj._observerContext = this._createContext())(); + } + return null; + }, + _createContext: function() { + var ctx = { + events: new EventHandlerList() + }; + return function() { + return ctx; + } + } +} + +var EventHandlerList = function EventHandlerList() { + this._list = {}; +} +EventHandlerList.prototype = { + _addHandler: function(id, handler) { + SArray.add(this._getEvent(id, true), handler); + }, + addHandler: function(id, handler) { + this._addHandler(id, handler); + }, + _removeHandler: function(id, handler) { + var evt = this._getEvent(id); + if (!evt) return; + SArray.remove(evt, handler); + }, + _removeHandlers: function(id) { + if (!id) { + this._list = {}; + } + else { + var evt = this._getEvent(id); + if (!evt) return; + evt.length = 0; + } + }, + removeHandler: function(id, handler) { + this._removeHandler(id, handler); + }, + getHandler: function(id) { + var evt = this._getEvent(id); + if (!evt || !evt.length) return null; + evt = SArray.clone(evt); + return function(source, args) { + for (var i = 0, l = evt.length; i < l; i++) { + evt[i](source, args); + } + }; + }, + _getEvent: function(id, create) { + var e = this._list[id]; + if (!e) { + if (!create) return null; + this._list[id] = e = []; + } + return e; + } +} +var Seadragon = new function() { + +} + +Seadragon.Utils = function() { + + + var Browser = { + UNKNOWN: 0, + IE: 1, + FIREFOX: 2, + SAFARI: 3, + CHROME: 4, + OPERA: 5 + }; + + Seadragon.Browser = Browser; + + + var self = this; + + var arrActiveX = ["Msxml2.XMLHTTP", "Msxml3.XMLHTTP", "Microsoft.XMLHTTP"]; + var fileFormats = { + "bmp": false, + "jpeg": true, + "jpg": true, + "png": true, + "tif": false, + "wdp": false + }; + + var browser = Browser.UNKNOWN; + var browserVersion = 0; + var badAlphaBrowser = false; // updated in constructor + + var urlParams = {}; + + + (function() { + + + var app = navigator.appName; + var ver = navigator.appVersion; + var ua = navigator.userAgent; + + if (app == "Microsoft Internet Explorer" && + !!window.attachEvent && !!window.ActiveXObject) { + + var ieOffset = ua.indexOf("MSIE"); + browser = Browser.IE; + browserVersion = parseFloat( + ua.substring(ieOffset + 5, ua.indexOf(";", ieOffset))); + + } else if (app == "Netscape" && !!window.addEventListener) { + + var ffOffset = ua.indexOf("Firefox"); + var saOffset = ua.indexOf("Safari"); + var chOffset = ua.indexOf("Chrome"); + + if (ffOffset >= 0) { + browser = Browser.FIREFOX; + browserVersion = parseFloat(ua.substring(ffOffset + 8)); + } else if (saOffset >= 0) { + var slash = ua.substring(0, saOffset).lastIndexOf("/"); + browser = (chOffset >= 0) ? Browser.CHROME : Browser.SAFARI; + browserVersion = parseFloat(ua.substring(slash + 1, saOffset)); + } + + } else if (app == "Opera" && !!window.opera && !!window.attachEvent) { + + browser = Browser.OPERA; + browserVersion = parseFloat(ver); + + } + + + var query = window.location.search.substring(1); // ignore '?' + var parts = query.split('&'); + + for (var i = 0; i < parts.length; i++) { + var part = parts[i]; + var sep = part.indexOf('='); + + if (sep > 0) { + urlParams[part.substring(0, sep)] = + decodeURIComponent(part.substring(sep + 1)); + } + } + + + badAlphaBrowser = (browser == Browser.IE || + (browser == Browser.CHROME && browserVersion < 2)); + + })(); + + + function getOffsetParent(elmt, isFixed) { + if (isFixed && elmt != document.body) { + return document.body; + } else { + return elmt.offsetParent; + } + } + + + this.getBrowser = function() { + return browser; + }; + + this.getBrowserVersion = function() { + return browserVersion; + }; + + this.getElement = function(elmt) { + if (typeof (elmt) == "string") { + elmt = document.getElementById(elmt); + } + + return elmt; + }; + + this.getElementPosition = function(elmt) { + var elmt = self.getElement(elmt); + var result = new Seadragon.Point(); + + + var isFixed = self.getElementStyle(elmt).position == "fixed"; + var offsetParent = getOffsetParent(elmt, isFixed); + + while (offsetParent) { + result.x += elmt.offsetLeft; + result.y += elmt.offsetTop; + + if (isFixed) { + result = result.plus(self.getPageScroll()); + } + + elmt = offsetParent; + isFixed = self.getElementStyle(elmt).position == "fixed"; + offsetParent = getOffsetParent(elmt, isFixed); + } + + return result; + }; + + this.getElementSize = function(elmt) { + var elmt = self.getElement(elmt); + return new Seadragon.Point(elmt.clientWidth, elmt.clientHeight); + }; + + this.getElementStyle = function(elmt) { + var elmt = self.getElement(elmt); + + if (elmt.currentStyle) { + return elmt.currentStyle; + } else if (window.getComputedStyle) { + return window.getComputedStyle(elmt, ""); + } else { + Seadragon.Debug.fail("Unknown element style, no known technique."); + } + }; + + this.getEvent = function(event) { + return event ? event : window.event; + }; + + this.getMousePosition = function(event) { + var event = self.getEvent(event); + var result = new Seadragon.Point(); + + + if (typeof (event.pageX) == "number") { + result.x = event.pageX; + result.y = event.pageY; + } else if (typeof (event.clientX) == "number") { + result.x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; + result.y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop; + } else { + Seadragon.Debug.fail("Unknown event mouse position, no known technique."); + } + + return result; + }; + + this.getPageScroll = function() { + var result = new Seadragon.Point(); + var docElmt = document.documentElement || {}; + var body = document.body || {}; + + + if (typeof (window.pageXOffset) == "number") { + result.x = window.pageXOffset; + result.y = window.pageYOffset; + } else if (body.scrollLeft || body.scrollTop) { + result.x = body.scrollLeft; + result.y = body.scrollTop; + } else if (docElmt.scrollLeft || docElmt.scrollTop) { + result.x = docElmt.scrollLeft; + result.y = docElmt.scrollTop; + } + + + return result; + }; + + this.getWindowSize = function() { + var result = new Seadragon.Point(); + var docElmt = document.documentElement || {}; + var body = document.body || {}; + + + + if (typeof (window.innerWidth) == 'number') { + result.x = window.innerWidth; + result.y = window.innerHeight; + } else if (docElmt.clientWidth || docElmt.clientHeight) { + result.x = docElmt.clientWidth; + result.y = docElmt.clientHeight; + } else if (body.clientWidth || body.clientHeight) { + result.x = body.clientWidth; + result.y = body.clientHeight; + } else { + Seadragon.Debug.fail("Unknown window size, no known technique."); + } + + return result; + }; + + this.imageFormatSupported = function(ext) { + var ext = ext ? ext : ""; + return !!fileFormats[ext.toLowerCase()]; + }; + + this.makeCenteredNode = function(elmt) { + var elmt = Seadragon.Utils.getElement(elmt); + var div = self.makeNeutralElement("div"); + var html = []; + + html.push('<div style="display:table; height:100%; width:100%;'); + html.push('border:none; margin:0px; padding:0px;'); // neutralizing + html.push('#position:relative; overflow:hidden; text-align:left;">'); + html.push('<div style="#position:absolute; #top:50%; width:100%; '); + html.push('border:none; margin:0px; padding:0px;'); // neutralizing + html.push('display:table-cell; vertical-align:middle;">'); + html.push('<div style="#position:relative; #top:-50%; width:100%; '); + html.push('border:none; margin:0px; padding:0px;'); // neutralizing + html.push('text-align:center;"></div></div></div>'); + + div.innerHTML = html.join(''); + div = div.firstChild; + + var innerDiv = div; + var innerDivs = div.getElementsByTagName("div"); + while (innerDivs.length > 0) { + innerDiv = innerDivs[0]; + innerDivs = innerDiv.getElementsByTagName("div"); + } + + innerDiv.appendChild(elmt); + + return div; + }; + + this.makeNeutralElement = function(tagName) { + var elmt = document.createElement(tagName); + var style = elmt.style; + + style.background = "transparent none"; + style.border = "none"; + style.margin = "0px"; + style.padding = "0px"; + style.position = "static"; + + return elmt; + }; + + this.makeTransparentImage = function(src) { + var img = self.makeNeutralElement("img"); + var elmt = null; + + if (browser == Browser.IE && browserVersion < 7) { + elmt = self.makeNeutralElement("span"); + elmt.style.display = "inline-block"; + + img.onload = function() { + elmt.style.width = elmt.style.width || img.width + "px"; + elmt.style.height = elmt.style.height || img.height + "px"; + + img.onload = null; + img = null; // to prevent memory leaks in IE + }; + + img.src = src; + elmt.style.filter = + "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + + src + "', sizingMethod='scale')"; + } else { + elmt = img; + elmt.src = src; + } + + return elmt; + }; + + this.setElementOpacity = function(elmt, opacity, usesAlpha) { + var elmt = self.getElement(elmt); + + if (usesAlpha && badAlphaBrowser) { + opacity = Math.round(opacity); + } + + if (opacity < 1) { + elmt.style.opacity = opacity; + } else { + elmt.style.opacity = ""; + } + + if (opacity == 1) { + var prevFilter = elmt.style.filter || ""; + elmt.style.filter = prevFilter.replace(/alpha\(.*?\)/g, ""); + return; + } + + var ieOpacity = Math.round(100 * opacity); + var ieFilter = " alpha(opacity=" + ieOpacity + ") "; + + try { + if (elmt.filters && elmt.filters.alpha) { + elmt.filters.alpha.opacity = ieOpacity; + } else { + elmt.style.filter += ieFilter; + } + } catch (e) { + elmt.style.filter += ieFilter; + } + }; + + this.addEvent = function(elmt, eventName, handler, useCapture) { + var elmt = self.getElement(elmt); + + + if (elmt.addEventListener) { + elmt.addEventListener(eventName, handler, useCapture); + } else if (elmt.attachEvent) { + elmt.attachEvent("on" + eventName, handler); + if (useCapture && elmt.setCapture) { + elmt.setCapture(); + } + } else { + Seadragon.Debug.fail("Unable to attach event handler, no known technique."); + } + }; + + this.removeEvent = function(elmt, eventName, handler, useCapture) { + var elmt = self.getElement(elmt); + + + if (elmt.removeEventListener) { + elmt.removeEventListener(eventName, handler, useCapture); + } else if (elmt.detachEvent) { + elmt.detachEvent("on" + eventName, handler); + if (useCapture && elmt.releaseCapture) { + elmt.releaseCapture(); + } + } else { + Seadragon.Debug.fail("Unable to detach event handler, no known technique."); + } + }; + + this.cancelEvent = function(event) { + var event = self.getEvent(event); + + + if (event.preventDefault) { + event.preventDefault(); // W3C for preventing default + } + + event.cancel = true; // legacy for preventing default + event.returnValue = false; // IE for preventing default + }; + + this.stopEvent = function(event) { + var event = self.getEvent(event); + + + if (event.stopPropagation) { + event.stopPropagation(); // W3C for stopping propagation + } + + event.cancelBubble = true; // IE for stopping propagation + }; + + this.createCallback = function(object, method) { + var initialArgs = []; + for (var i = 2; i < arguments.length; i++) { + initialArgs.push(arguments[i]); + } + + return function() { + var args = initialArgs.concat([]); + for (var i = 0; i < arguments.length; i++) { + args.push(arguments[i]); + } + + return method.apply(object, args); + }; + }; + + this.getUrlParameter = function(key) { + var value = urlParams[key]; + return value ? value : null; + }; + + this.makeAjaxRequest = function(url, callback) { + var async = typeof (callback) == "function"; + var req = null; + + if (async) { + var actual = callback; + var callback = function() { + window.setTimeout(Seadragon.Utils.createCallback(null, actual, req), 1); + }; + } + + if (window.ActiveXObject) { + for (var i = 0; i < arrActiveX.length; i++) { + try { + req = new ActiveXObject(arrActiveX[i]); + break; + } catch (e) { + continue; + } + } + } else if (window.XMLHttpRequest) { + req = new XMLHttpRequest(); + } + + if (!req) { + Seadragon.Debug.fail("Browser doesn't support XMLHttpRequest."); + } + + + if (async) { + req.onreadystatechange = function() { + if (req.readyState == 4) { + req.onreadystatechange = new function() { }; + callback(); + } + }; + } + + try { + req.open("GET", url, async); + req.send(null); + } catch (e) { + Seadragon.Debug.log(e.name + " while making AJAX request: " + e.message); + + req.onreadystatechange = null; + req = null; + + if (async) { + callback(); + } + } + + return async ? null : req; + }; + + this.parseXml = function(string) { + var xmlDoc = null; + + if (window.ActiveXObject) { + try { + xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async = false; + xmlDoc.loadXML(string); + } catch (e) { + Seadragon.Debug.log(e.name + " while parsing XML (ActiveX): " + e.message); + } + } else if (window.DOMParser) { + try { + var parser = new DOMParser(); + xmlDoc = parser.parseFromString(string, "text/xml"); + } catch (e) { + Seadragon.Debug.log(e.name + " while parsing XML (DOMParser): " + e.message); + } + } else { + Seadragon.Debug.fail("Browser doesn't support XML DOM."); + } + + return xmlDoc; + }; + +}; +Seadragon.Utils = new Seadragon.Utils(); +(function () { + + if (Seadragon.MouseTracker) { + return; + } + + + var isIE = Seadragon.Utils.getBrowser() == Seadragon.Browser.IE; + + + var buttonDownAny = false; + + var ieCapturingAny = false; + var ieTrackersActive = {}; // dictionary from hash to MouseTracker + var ieTrackersCapturing = []; // list of trackers interested in capture + + + function getMouseAbsolute(event) { + return Seadragon.Utils.getMousePosition(event); + } + + function getMouseRelative(event, elmt) { + var mouse = Seadragon.Utils.getMousePosition(event); + var offset = Seadragon.Utils.getElementPosition(elmt); + + return mouse.minus(offset); + } + + /** + * Returns true if elmtB is a child node of elmtA, or if they're equal. + */ + function isChild(elmtA, elmtB) { + var body = document.body; + while (elmtB && elmtA != elmtB && body != elmtB) { + try { + elmtB = elmtB.parentNode; + } catch (e) { + return false; + } + } + return elmtA == elmtB; + } + + function onGlobalMouseDown() { + buttonDownAny = true; + } + + function onGlobalMouseUp() { + buttonDownAny = false; + } + + + (function () { + if (isIE) { + Seadragon.Utils.addEvent(document, "mousedown", onGlobalMouseDown, false); + Seadragon.Utils.addEvent(document, "mouseup", onGlobalMouseUp, false); + } else { + Seadragon.Utils.addEvent(window, "mousedown", onGlobalMouseDown, true); + Seadragon.Utils.addEvent(window, "mouseup", onGlobalMouseUp, true); + } + })(); + + + Seadragon.MouseTracker = function (elmt, clickTimeThreshold, clickDistThreshold) { + + + var self = this; + var ieSelf = null; + + var hash = Math.random(); // a unique hash for this tracker + var elmt = Seadragon.Utils.getElement(elmt); + + var tracking = false; + var capturing = false; + var buttonDownElmt = false; + var insideElmt = false; + + var lastPoint = null; // position of last mouse down/move + var lastMouseDownTime = null; // time of last mouse down + var lastMouseDownPoint = null; // position of last mouse down + var clickTimeThreshold = clickTimeThreshold; + var clickDistThreshold = clickDistThreshold; + + + this.target = elmt; + this.enterHandler = null; // function(tracker, position, buttonDownElmt, buttonDownAny) + this.exitHandler = null; // function(tracker, position, buttonDownElmt, buttonDownAny) + this.pressHandler = null; // function(tracker, position) + this.releaseHandler = null; // function(tracker, position, insideElmtPress, insideElmtRelease) + this.scrollHandler = null; // function(tracker, position, scroll, shift) + this.clickHandler = null; // function(tracker, position, quick, shift) + this.dragHandler = null; // function(tracker, position, delta, shift) + + + + function startTracking() { + if (!tracking) { + Seadragon.Utils.addEvent(elmt, "mouseover", onMouseOver, false); + Seadragon.Utils.addEvent(elmt, "mouseout", onMouseOut, false); + Seadragon.Utils.addEvent(elmt, "mousedown", onMouseDown, false); + Seadragon.Utils.addEvent(elmt, "mouseup", onMouseUp, false); + Seadragon.Utils.addEvent(elmt, "click", onMouseClick, false); + Seadragon.Utils.addEvent(elmt, "DOMMouseScroll", onMouseWheelSpin, false); + Seadragon.Utils.addEvent(elmt, "mousewheel", onMouseWheelSpin, false); // Firefox + + tracking = true; + ieTrackersActive[hash] = ieSelf; + } + } + + function stopTracking() { + if (tracking) { + Seadragon.Utils.removeEvent(elmt, "mouseover", onMouseOver, false); + Seadragon.Utils.removeEvent(elmt, "mouseout", onMouseOut, false); + Seadragon.Utils.removeEvent(elmt, "mousedown", onMouseDown, false); + Seadragon.Utils.removeEvent(elmt, "mouseup", onMouseUp, false); + Seadragon.Utils.removeEvent(elmt, "click", onMouseClick, false); + Seadragon.Utils.removeEvent(elmt, "DOMMouseScroll", onMouseWheelSpin, false); + Seadragon.Utils.removeEvent(elmt, "mousewheel", onMouseWheelSpin, false); + + releaseMouse(); + tracking = false; + delete ieTrackersActive[hash]; + } + } + + function captureMouse() { + if (!capturing) { + if (isIE) { + Seadragon.Utils.removeEvent(elmt, "mouseup", onMouseUp, false); + Seadragon.Utils.addEvent(elmt, "mouseup", onMouseUpIE, true); + Seadragon.Utils.addEvent(elmt, "mousemove", onMouseMoveIE, true); + } else { + Seadragon.Utils.addEvent(window, "mouseup", onMouseUpWindow, true); + Seadragon.Utils.addEvent(window, "mousemove", onMouseMove, true); + } + + capturing = true; + } + } + + function releaseMouse() { + if (capturing) { + if (isIE) { + Seadragon.Utils.removeEvent(elmt, "mousemove", onMouseMoveIE, true); + Seadragon.Utils.removeEvent(elmt, "mouseup", onMouseUpIE, true); + Seadragon.Utils.addEvent(elmt, "mouseup", onMouseUp, false); + } else { + Seadragon.Utils.removeEvent(window, "mousemove", onMouseMove, true); + Seadragon.Utils.removeEvent(window, "mouseup", onMouseUpWindow, true); + } + + capturing = false; + } + } + + + function triggerOthers(eventName, event) { + var trackers = ieTrackersActive; + for (var otherHash in trackers) { + if (trackers.hasOwnProperty(otherHash) && hash != otherHash) { + trackers[otherHash][eventName](event); + } + } + } + + function hasMouse() { + return insideElmt; + } + + + function onMouseOver(event) { + var event = Seadragon.Utils.getEvent(event); + + if (isIE && capturing && !isChild(event.srcElement, elmt)) { + triggerOthers("onMouseOver", event); + } + + var to = event.target ? event.target : event.srcElement; + var from = event.relatedTarget ? event.relatedTarget : event.fromElement; + if (!isChild(elmt, to) || isChild(elmt, from)) { + return; + } + + insideElmt = true; + + if (typeof (self.enterHandler) == "function") { + try { + self.enterHandler(self, getMouseRelative(event, elmt), + buttonDownElmt, buttonDownAny); + } catch (e) { + Seadragon.Debug.error(e.name + + " while executing enter handler: " + e.message, e); + } + } + } + + function onMouseOut(event) { + var event = Seadragon.Utils.getEvent(event); + + if (isIE && capturing && !isChild(event.srcElement, elmt)) { + triggerOthers("onMouseOut", event); + } + + var from = event.target ? event.target : event.srcElement; + var to = event.relatedTarget ? event.relatedTarget : event.toElement; + if (!isChild(elmt, from) || isChild(elmt, to)) { + return; + } + + insideElmt = false; + + if (typeof (self.exitHandler) == "function") { + try { + self.exitHandler(self, getMouseRelative(event, elmt), + buttonDownElmt, buttonDownAny); + } catch (e) { + Seadragon.Debug.error(e.name + + " while executing exit handler: " + e.message, e); + } + } + } + + function onMouseDown(event) { + var event = Seadragon.Utils.getEvent(event); + + if (event.button == 2) { + return; + } + + buttonDownElmt = true; + + lastPoint = getMouseAbsolute(event); + lastMouseDownPoint = lastPoint; + lastMouseDownTime = new Date().getTime(); + + if (typeof (self.pressHandler) == "function") { + try { + self.pressHandler(self, getMouseRelative(event, elmt)); + } catch (e) { + Seadragon.Debug.error(e.name + + " while executing press handler: " + e.message, e); + } + } + + if (self.pressHandler || self.dragHandler) { + Seadragon.Utils.cancelEvent(event); + } + + if (!isIE || !ieCapturingAny) { + captureMouse(); + ieCapturingAny = true; + ieTrackersCapturing = [ieSelf]; // reset to empty & add us + } else if (isIE) { + ieTrackersCapturing.push(ieSelf); // add us to the list + } + } + + function onMouseUp(event) { + var event = Seadragon.Utils.getEvent(event); + var insideElmtPress = buttonDownElmt; + var insideElmtRelease = insideElmt; + + if (event.button == 2) { + return; + } + + buttonDownElmt = false; + + if (typeof (self.releaseHandler) == "function") { + try { + self.releaseHandler(self, getMouseRelative(event, elmt), + insideElmtPress, insideElmtRelease); + } catch (e) { + Seadragon.Debug.error(e.name + + " while executing release handler: " + e.message, e); + } + } + + if (insideElmtPress && insideElmtRelease) { + handleMouseClick(event); + } + } + + /** + * Only triggered once by the deepest element that initially received + * the mouse down event. We want to make sure THIS event doesn't bubble. + * Instead, we want to trigger the elements that initially received the + * mouse down event (including this one) only if the mouse is no longer + * inside them. Then, we want to release capture, and emulate a regular + * mouseup on the event that this event was meant for. + */ + function onMouseUpIE(event) { + var event = Seadragon.Utils.getEvent(event); + + if (event.button == 2) { + return; + } + + for (var i = 0; i < ieTrackersCapturing.length; i++) { + var tracker = ieTrackersCapturing[i]; + if (!tracker.hasMouse()) { + tracker.onMouseUp(event); + } + } + + releaseMouse(); + ieCapturingAny = false; + event.srcElement.fireEvent("on" + event.type, + document.createEventObject(event)); + + Seadragon.Utils.stopEvent(event); + } + + /** + * Only triggered in W3C browsers by elements within which the mouse was + * initially pressed, since they are now listening to the window for + * mouseup during the capture phase. We shouldn't handle the mouseup + * here if the mouse is still inside this element, since the regular + * mouseup handler will still fire. + */ + function onMouseUpWindow(event) { + if (!insideElmt) { + onMouseUp(event); + } + + releaseMouse(); + } + + function onMouseClick(event) { + + if (self.clickHandler) { + Seadragon.Utils.cancelEvent(event); + } + } + + function onMouseWheelSpin(event) { + var nDelta = 0; + if (!event) { // For IE, access the global (window) event object + event = window.event; + } + if (event.wheelDelta) { // IE and Opera + nDelta = event.wheelDelta; + if (window.opera) { // Opera has the values reversed + nDelta = -nDelta; + } + } + else if (event.detail) { // Mozilla FireFox + nDelta = -event.detail; + } + + nDelta = nDelta > 0 ? 1 : -1; + + if (typeof (self.scrollHandler) == "function") { + try { + self.scrollHandler(self, getMouseRelative(event, elmt), nDelta, event.shiftKey); + } catch (e) { + Seadragon.Debug.error(e.name + + " while executing scroll handler: " + e.message, e); + } + + Seadragon.Utils.cancelEvent(event); + } + } + + function handleMouseClick(event) { + var event = Seadragon.Utils.getEvent(event); + + if (event.button == 2) { + return; + } + + var time = new Date().getTime() - lastMouseDownTime; + var point = getMouseAbsolute(event); + var distance = lastMouseDownPoint.distanceTo(point); + var quick = time <= clickTimeThreshold && + distance <= clickDistThreshold; + + if (typeof (self.clickHandler) == "function") { + try { + self.clickHandler(self, getMouseRelative(event, elmt), + quick, event.shiftKey); + } catch (e) { + Seadragon.Debug.error(e.name + + " while executing click handler: " + e.message, e); + } + } + } + + function onMouseMove(event) { + var event = Seadragon.Utils.getEvent(event); + var point = getMouseAbsolute(event); + var delta = point.minus(lastPoint); + + lastPoint = point; + + if (typeof (self.dragHandler) == "function") { + try { + self.dragHandler(self, getMouseRelative(event, elmt), + delta, event.shiftKey); + } catch (e) { + Seadragon.Debug.error(e.name + + " while executing drag handler: " + e.message, e); + } + + Seadragon.Utils.cancelEvent(event); + } + } + + /** + * Only triggered once by the deepest element that initially received + * the mouse down event. Since no other element has captured the mouse, + * we want to trigger the elements that initially received the mouse + * down event (including this one). + */ + function onMouseMoveIE(event) { + for (var i = 0; i < ieTrackersCapturing.length; i++) { + ieTrackersCapturing[i].onMouseMove(event); + } + + Seadragon.Utils.stopEvent(event); + } + + + (function () { + ieSelf = { + hasMouse: hasMouse, + onMouseOver: onMouseOver, + onMouseOut: onMouseOut, + onMouseUp: onMouseUp, + onMouseMove: onMouseMove + }; + })(); + + + this.isTracking = function () { + return tracking; + }; + + this.setTracking = function (track) { + if (track) { + startTracking(); + } else { + stopTracking(); + } + }; + + }; + +})(); +if (!window.SIGNAL) + window.SIGNAL = "----seadragon----"; + +Seadragon.ControlAnchor = function() { + throw Error.invalidOperation(); +} +Seadragon.ControlAnchor = { + NONE: 0, + TOP_LEFT: 1, + TOP_RIGHT: 2, + BOTTOM_RIGHT: 3, + BOTTOM_LEFT: 4 +} +Seadragon.ControlAnchor = Seadragon.ControlAnchor; + +Seadragon.OverlayPlacement = function() { + throw Error.invalidOperation(); +} +Seadragon.OverlayPlacement = { + CENTER: 0, + TOP_LEFT: 1, + TOP: 2, + TOP_RIGHT: 3, + RIGHT: 4, + BOTTOM_RIGHT: 5, + BOTTOM: 6, + BOTTOM_LEFT: 7, + LEFT: 8 +} +Seadragon.OverlayPlacement = Seadragon.OverlayPlacement; + +Seadragon.NavControl = function(viewer) { + this._group = null; + this._zooming = false; // whether we should be continuously zooming + this._zoomFactor = null; // how much we should be continuously zooming by + this._lastZoomTime = null; + this._viewer = viewer; + this.config = this._viewer.config; + + this.elmt = null; + this.initialize(); +} +Seadragon.NavControl.prototype = { + initialize: function() { + var beginZoomingInHandler = Function.createDelegate(this, this._beginZoomingIn); + var endZoomingHandler = Function.createDelegate(this, this._endZooming); + var doSingleZoomInHandler = Function.createDelegate(this, this._doSingleZoomIn); + var beginZoomingOutHandler = Function.createDelegate(this, this._beginZoomingOut); + var doSingleZoomOutHandler = Function.createDelegate(this, this._doSingleZoomOut); + var onHomeHandler = Function.createDelegate(this, this._onHome); + var onFullPageHandler = Function.createDelegate(this, this._onFullPage); + + var navImages = this._viewer.config.navImages; + var zoomIn = new Seadragon.Button( + { config: this._viewer.config, tooltip: Seadragon.Strings.getString("Tooltips.ZoomIn"), srcRest: this._resolveUrl(navImages.zoomIn.REST), srcGroup: this._resolveUrl(navImages.zoomIn.GROUP), srcHover: this._resolveUrl(navImages.zoomIn.HOVER), srcDown: this._resolveUrl(navImages.zoomIn.DOWN) }, + { onPress: beginZoomingInHandler, onRelease: endZoomingHandler, onClick: doSingleZoomInHandler, onEnter: beginZoomingInHandler, onExit: endZoomingHandler }); + var zoomOut = new Seadragon.Button( + { config: this._viewer.config, tooltip: Seadragon.Strings.getString("Tooltips.ZoomOut"), srcRest: this._resolveUrl(navImages.zoomOut.REST), srcGroup: this._resolveUrl(navImages.zoomOut.GROUP), srcHover: this._resolveUrl(navImages.zoomOut.HOVER), srcDown: this._resolveUrl(navImages.zoomOut.DOWN) }, + { onPress: beginZoomingOutHandler, onRelease: endZoomingHandler, onClick: doSingleZoomOutHandler, onEnter: beginZoomingOutHandler, onExit: endZoomingHandler }); + var goHome = new Seadragon.Button( + { config: this._viewer.config, tooltip: Seadragon.Strings.getString("Tooltips.Home"), srcRest: this._resolveUrl(navImages.home.REST), srcGroup: this._resolveUrl(navImages.home.GROUP), srcHover: this._resolveUrl(navImages.home.HOVER), srcDown: this._resolveUrl(navImages.home.DOWN) }, + { onRelease: onHomeHandler }); + var fullPage = new Seadragon.Button( + { config: this._viewer.config, tooltip: Seadragon.Strings.getString("Tooltips.FullPage"), srcRest: this._resolveUrl(navImages.fullpage.REST), srcGroup: this._resolveUrl(navImages.fullpage.GROUP), srcHover: this._resolveUrl(navImages.fullpage.HOVER), srcDown: this._resolveUrl(navImages.fullpage.DOWN) }, + { onRelease: onFullPageHandler }); + this._group = new Seadragon.ButtonGroup({ config: this._viewer.config, buttons: [zoomIn, zoomOut, goHome, fullPage] }); + + this.elmt = this._group.get_element(); + this.elmt[SIGNAL] = true; // hack to get our controls to fade + this._viewer.add_open(Function.createDelegate(this, this._lightUp)); + }, + dispose: function() { + }, + get_events: function() { + return this._events; + }, + set_events: function(value) { + this._events = value; + }, + _resolveUrl: function(url) { + return String.format("{1}", this._viewer.get_prefixUrl(), url); + }, + _beginZoomingIn: function() { + this._lastZoomTime = new Date().getTime(); + this._zoomFactor = this.config.zoomPerSecond; + this._zooming = true; + this._scheduleZoom(); + }, + _beginZoomingOut: function() { + this._lastZoomTime = new Date().getTime(); + this._zoomFactor = 1.0 / this.config.zoomPerSecond; + this._zooming = true; + this._scheduleZoom(); + }, + + _endZooming: function() { + this._zooming = false; + }, + _scheduleZoom: function() { + window.setTimeout(Function.createDelegate(this, this._doZoom), 10); + }, + _doZoom: function() { + if (this._zooming && this._viewer.viewport) { + var currentTime = new Date().getTime(); + var deltaTime = currentTime - this._lastZoomTime; + var adjustedFactor = Math.pow(this._zoomFactor, deltaTime / 1000); + + this._viewer.viewport.zoomBy(adjustedFactor); + this._viewer.viewport.applyConstraints(); + this._lastZoomTime = currentTime; + this._scheduleZoom(); + } + }, + _doSingleZoomIn: function() { + if (this._viewer.viewport) { + this._zooming = false; + this._viewer.viewport.zoomBy(this.config.zoomPerClick / 1.0); + this._viewer.viewport.applyConstraints(); + } + }, + _doSingleZoomOut: function() { + if (this._viewer.viewport) { + this._zooming = false; + this._viewer.viewport.zoomBy(1.0 / this.config.zoomPerClick); + this._viewer.viewport.applyConstraints(); + } + }, + _lightUp: function() { + this._group.emulateEnter(); + this._group.emulateExit(); + }, + _onHome: function() { + if (this._viewer.viewport) { + this._viewer.viewport.goHome(); + } + }, + _onFullPage: function() { + this._viewer.setFullPage(!this._viewer.isFullPage()); + this._group.emulateExit(); // correct for no mouseout event on change + + if (this._viewer.viewport) { + this._viewer.viewport.applyConstraints(); + } + if ( this._viewer.onFullPage ) + { + this._viewer.onFullPage.apply( this._viewer ); + } + } +} + +Seadragon.Control = function (elmt, anchor, container) { + this.elmt = elmt; + this.anchor = anchor; + this.container = container; + this.wrapper = Seadragon.Utils.makeNeutralElement("span"); + this.wrapper.style.display = "inline-block"; + this.wrapper.appendChild(this.elmt); + if (this.anchor == Seadragon.ControlAnchor.NONE) { + this.wrapper.style.width = this.wrapper.style.height = "100%"; // IE6 fix + } + + if (this.anchor == Seadragon.ControlAnchor.TOP_RIGHT || this.anchor == Seadragon.ControlAnchor.BOTTOM_RIGHT) { + this.container.insertBefore(this.wrapper, this.container.firstChild); + } else { + this.container.appendChild(this.wrapper); + } +} +Seadragon.Control.prototype = { + destroy: function() { + this.wrapper.removeChild(this.elmt); + this.container.removeChild(this.wrapper); + }, + isVisible: function() { + return this.wrapper.style.display != "none"; + }, + setVisible: function(visible) { + this.wrapper.style.display = visible ? "inline-block" : "none"; + }, + setOpacity: function(opacity) { + if (this.elmt[SIGNAL] && Seadragon.Utils.getBrowser() == Seadragon.Browser.IE) { + Seadragon.Utils.setElementOpacity(this.elmt, opacity, true); + } else { + Seadragon.Utils.setElementOpacity(this.wrapper, opacity, true); + } + } +} + +Seadragon.Viewer = function(element, xmlPath, prefixUrl, controls, overlays, overlayControls) { + + this.config = new Seadragon.Config(); + this._prefixUrl = prefixUrl ? prefixUrl : ""; + this._element = document.getElementById(element); + + this._controls = controls ? controls : []; + this._customControls = []; + this._overlays = overlays ? overlays : []; + this._overlayControls = overlayControls ? overlayControls : []; + this._container = null; + this._canvas = null; + this._controlsTL = null; + this._controlsTR = null; + this._controlsBR = null; + this._controlsBL = null; + this._bodyWidth = null; + this._bodyHeight = null; + this._bodyOverflow = null; + this._docOverflow = null; + this._fsBoundsDelta = null; + this._prevContainerSize = null; + this._lastOpenStartTime = 0; + this._lastOpenEndTime = 0; + this._animating = false; + this._forceRedraw = false; + this._mouseInside = false; + this._xmlPath = xmlPath ? xmlPath : undefined; + + this.source = null; + this.drawer = null; + this.viewport = null; + this.profiler = null; + + this.initialize(); +} +Seadragon.Viewer.prototype = { + initialize: function () { + + this._observer = new Observer(); + + this._container = Seadragon.Utils.makeNeutralElement("div"); + this._canvas = Seadragon.Utils.makeNeutralElement("div"); + + this._controlsTL = Seadragon.Utils.makeNeutralElement("div"); + this._controlsTR = Seadragon.Utils.makeNeutralElement("div"); + this._controlsBR = Seadragon.Utils.makeNeutralElement("div"); + this._controlsBL = Seadragon.Utils.makeNeutralElement("div"); + + var innerTracker = new Seadragon.MouseTracker(this._canvas, this.config.clickTimeThreshold, this.config.clickDistThreshold); + var outerTracker = new Seadragon.MouseTracker(this._container, this.config.clickTimeThreshold, this.config.clickDistThreshold); + + this._bodyWidth = document.body.style.width; + this._bodyHeight = document.body.style.height; + this._bodyOverflow = document.body.style.overflow; + this._docOverflow = document.documentElement.style.overflow; + + this._fsBoundsDelta = new Seadragon.Point(1, 1); + + var canvasStyle = this._canvas.style; + var containerStyle = this._container.style; + var controlsTLStyle = this._controlsTL.style; + var controlsTRStyle = this._controlsTR.style; + var controlsBRStyle = this._controlsBR.style; + var controlsBLStyle = this._controlsBL.style; + + containerStyle.width = "100%"; + containerStyle.height = "100%"; + containerStyle.position = "relative"; + containerStyle.left = "0px"; + containerStyle.top = "0px"; + containerStyle.textAlign = "left"; // needed to protect against + + canvasStyle.width = "100%"; + canvasStyle.height = "100%"; + canvasStyle.overflow = "hidden"; + canvasStyle.position = "absolute"; + canvasStyle.top = "0px"; + canvasStyle.left = "0px"; + + controlsTLStyle.position = controlsTRStyle.position = + controlsBRStyle.position = controlsBLStyle.position = + "absolute"; + + controlsTLStyle.top = controlsTRStyle.top = "0px"; + controlsTLStyle.left = controlsBLStyle.left = "0px"; + controlsTRStyle.right = controlsBRStyle.right = "0px"; + controlsBLStyle.bottom = controlsBRStyle.bottom = "0px"; + + innerTracker.clickHandler = Function.createDelegate(this, this._onCanvasClick); + innerTracker.dragHandler = Function.createDelegate(this, this._onCanvasDrag); + innerTracker.releaseHandler = Function.createDelegate(this, this._onCanvasRelease); + innerTracker.scrollHandler = Function.createDelegate(this, this._onCanvasScroll); + innerTracker.setTracking(true); // default state + + if (this.get_showNavigationControl()) { + navControl = (new Seadragon.NavControl(this)).elmt; + navControl.style.marginRight = "4px"; + navControl.style.marginBottom = "4px"; + this.addControl(navControl, Seadragon.ControlAnchor.BOTTOM_RIGHT); + } + for (var i = 0; i < this._customControls.length; i++) { + this.addControl(this._customControls[i].id, this._customControls[i].anchor); + } + + outerTracker.enterHandler = Function.createDelegate(this, this._onContainerEnter); + outerTracker.exitHandler = Function.createDelegate(this, this._onContainerExit); + outerTracker.releaseHandler = Function.createDelegate(this, this._onContainerRelease); + outerTracker.setTracking(true); // always tracking + window.setTimeout(Function.createDelegate(this, this._beginControlsAutoHide), 1); // initial fade out + + this._container.appendChild(this._canvas); + this._container.appendChild(this._controlsTL); + this._container.appendChild(this._controlsTR); + this._container.appendChild(this._controlsBR); + this._container.appendChild(this._controlsBL); + this.get_element().appendChild(this._container); + + if (this._xmlPath) + this.openDzi(this._xmlPath); + }, + get_events: function get_events() { + return this._observer._getContext(this, true).events; + }, + _raiseEvent: function (eventName, eventArgs) { + var handler = this.get_events().getHandler(eventName); + + if (handler) { + if (!eventArgs) { + eventArgs = new Object(); // Sys.EventArgs.Empty; + } + + handler(this, eventArgs); + } + }, + _beginControlsAutoHide: function () { + if (!this.config.autoHideControls) { + return; + } + + this._controlsShouldFade = true; + this._controlsFadeBeginTime = new Date().getTime() + this._controlsFadeDelay; + window.setTimeout(Function.createDelegate(this, this._scheduleControlsFade), this._controlsFadeDelay); + }, + _scheduleControlsFade: function () { + window.setTimeout(Function.createDelegate(this, this._updateControlsFade), 20); + }, + _updateControlsFade: function () { + if (this._controlsShouldFade) { + var currentTime = new Date().getTime(); + var deltaTime = currentTime - this._controlsFadeBeginTime; + var opacity = 1.0 - deltaTime / this._controlsFadeLength; + + opacity = Math.min(1.0, opacity); + opacity = Math.max(0.0, opacity); + + for (var i = this._controls.length - 1; i >= 0; i--) { + this._controls[i].setOpacity(opacity); + } + + if (opacity > 0) { + this._scheduleControlsFade(); // fade again + } + } + }, + _onCanvasClick: function (tracker, position, quick, shift) { + if (this.viewport && quick) { // ignore clicks where mouse moved + var zoomPerClick = this.config.zoomPerClick; + var factor = shift ? 1.0 / zoomPerClick : zoomPerClick; + this.viewport.zoomBy(factor, this.viewport.pointFromPixel(position, true)); + this.viewport.applyConstraints(); + } + }, + _onCanvasDrag: function (tracker, position, delta, shift) { + if (this.viewport) { + this.viewport.panBy(this.viewport.deltaPointsFromPixels(delta.negate())); + } + }, + _onCanvasRelease: function (tracker, position, insideElmtPress, insideElmtRelease) { + if (insideElmtPress && this.viewport) { + this.viewport.applyConstraints(); + } + }, + _onCanvasScroll: function (tracker, position, scroll, shift) { + if (this.viewport) { + var factor = Math.pow(this.config.zoomPerScroll,scroll); + this.viewport.zoomBy(factor, this.viewport.pointFromPixel(position, true)); + this.viewport.applyConstraints(); + } + }, + _onContainerExit: function (tracker, position, buttonDownElmt, buttonDownAny) { + if (!buttonDownElmt) { + this._mouseInside = false; + if (!this._animating) { + this._beginControlsAutoHide(); + } + } + }, + _onContainerRelease: function (tracker, position, insideElmtPress, insideElmtRelease) { + if (!insideElmtRelease) { + this._mouseInside = false; + if (!this._animating) { + this._beginControlsAutoHide(); + } + } + }, + _getControlIndex: function (elmt) { + for (var i = this._controls.length - 1; i >= 0; i--) { + if (this._controls[i].elmt == elmt) { + return i; + } + } + + return -1; + }, + _abortControlsAutoHide: function () { + this._controlsShouldFade = false; + for (var i = this._controls.length - 1; i >= 0; i--) { + this._controls[i].setOpacity(1.0); + } + }, + _onContainerEnter: function (tracker, position, buttonDownElmt, buttonDownAny) { + this._mouseInside = true; + this._abortControlsAutoHide(); + }, + _updateOnce: function () { + if (!this.source) { + return; + } + + this.profiler.beginUpdate(); + + var containerSize = Seadragon.Utils.getElementSize(this._container); + + if (!containerSize.equals(this._prevContainerSize)) { + this.viewport.resize(containerSize, true); // maintain image position + this._prevContainerSize = containerSize; + this._raiseEvent("resize", this); + } + + var animated = this.viewport.update(); + + if (!this._animating && animated) { + this._raiseEvent("animationstart", self); + this._abortControlsAutoHide(); + } + + if (animated) { + this.drawer.update(); + this._raiseEvent("animation", self); + } else if (this._forceRedraw || this.drawer.needsUpdate()) { + this.drawer.update(); + this._forceRedraw = false; + } else { + this.drawer.idle(); + } + + if (this._animating && !animated) { + this._raiseEvent("animationfinish", this); + + if (!this._mouseInside) { + this._beginControlsAutoHide(); + } + } + + this._animating = animated; + + this.profiler.endUpdate(); + }, + _onClose: function () { + + this.source = null; + this.viewport = null; + this.drawer = null; + this.profiler = null; + + this._canvas.innerHTML = ""; + }, + _beforeOpen: function () { + if (this.source) { + this._onClose(); + } + + this._lastOpenStartTime = new Date().getTime(); // to ignore earlier opens + + window.setTimeout(Function.createDelegate(this, function () { + if (this._lastOpenStartTime > this._lastOpenEndTime) { + this._setMessage(Seadragon.Strings.getString("Messages.Loading")); + } + }), 2000); + + return this._lastOpenStartTime; + }, + _setMessage: function (message) { + var textNode = document.createTextNode(message); + + this._canvas.innerHTML = ""; + this._canvas.appendChild(Seadragon.Utils.makeCenteredNode(textNode)); + + var textStyle = textNode.parentNode.style; + + textStyle.color = "white"; + textStyle.fontFamily = "verdana"; + textStyle.fontSize = "13px"; + textStyle.fontSizeAdjust = "none"; + textStyle.fontStyle = "normal"; + textStyle.fontStretch = "normal"; + textStyle.fontVariant = "normal"; + textStyle.fontWeight = "normal"; + textStyle.lineHeight = "1em"; + textStyle.textAlign = "center"; + textStyle.textDecoration = "none"; + }, + _onOpen: function (time, _source, error) { + this._lastOpenEndTime = new Date().getTime(); + + if (time < this._lastOpenStartTime) { + Seadragon.Debug.log("Ignoring out-of-date open."); + this._raiseEvent("ignore"); + return; + } else if (!_source) { + this._setMessage(error); + this._raiseEvent("error"); + return; + } + + this._canvas.innerHTML = ""; + this._prevContainerSize = Seadragon.Utils.getElementSize(this._container); + + this.source = _source; + this.viewport = new Seadragon.Viewport(this._prevContainerSize, this.source.dimensions, this.config); + this.drawer = new Seadragon.Drawer(this.source, this.viewport, this._canvas); + this.profiler = new Seadragon.Profiler(); + + this._animating = false; + this._forceRedraw = true; + this._scheduleUpdate(this._updateMulti); + + for (var i = 0; i < this._overlayControls.length; i++) { + var overlay = this._overlayControls[i]; + if (overlay.point != null) { + this.drawer.addOverlay(overlay.id, new Seadragon.Point(overlay.point.X, overlay.point.Y), Seadragon.OverlayPlacement.TOP_LEFT); + } + else { + this.drawer.addOverlay(overlay.id, new Seadragon.Rect(overlay.rect.Point.X, overlay.rect.Point.Y, overlay.rect.Width, overlay.rect.Height), overlay.placement); + } + } + this._raiseEvent("open"); + }, + _scheduleUpdate: function (updateFunc, prevUpdateTime) { + if (this._animating) { + return window.setTimeout(Function.createDelegate(this, updateFunc), 1); + } + + var currentTime = new Date().getTime(); + var prevUpdateTime = prevUpdateTime ? prevUpdateTime : currentTime; + var targetTime = prevUpdateTime + 1000 / 60; // 60 fps ideal + + var deltaTime = Math.max(1, targetTime - currentTime); + return window.setTimeout(Function.createDelegate(this, updateFunc), deltaTime); + }, + _updateMulti: function () { + if (!this.source) { + return; + } + + var beginTime = new Date().getTime(); + + this._updateOnce(); + this._scheduleUpdate(arguments.callee, beginTime); + }, + _updateOnce: function () { + if (!this.source) { + return; + } + + this.profiler.beginUpdate(); + + var containerSize = Seadragon.Utils.getElementSize(this._container); + + if (!containerSize.equals(this._prevContainerSize)) { + this.viewport.resize(containerSize, true); // maintain image position + this._prevContainerSize = containerSize; + this._raiseEvent("resize"); + } + + var animated = this.viewport.update(); + + if (!this._animating && animated) { + this._raiseEvent("animationstart"); + this._abortControlsAutoHide(); + } + + if (animated) { + this.drawer.update(); + this._raiseEvent("animation"); + } else if (this._forceRedraw || this.drawer.needsUpdate()) { + this.drawer.update(); + this._forceRedraw = false; + } else { + this.drawer.idle(); + } + + if (this._animating && !animated) { + this._raiseEvent("animationfinish"); + + if (!this._mouseInside) { + this._beginControlsAutoHide(); + } + } + + this._animating = animated; + + this.profiler.endUpdate(); + }, + + getNavControl: function () { + return this._navControl; + }, + get_element: function () { + return this._element; + }, + get_xmlPath: function () { + return this._xmlPath; + }, + set_xmlPath: function (value) { + this._xmlPath = value; + }, + get_debugMode: function () { + return this.config.debugMode; + }, + set_debugMode: function (value) { + this.config.debugMode = value; + }, + get_animationTime: function () { + return this.config.animationTime; + }, + set_animationTime: function (value) { + this.config.animationTime = value; + }, + get_blendTime: function () { + return this.config.blendTime; + }, + set_blendTime: function (value) { + this.config.blendTime = value; + }, + get_alwaysBlend: function () { + return this.config.alwaysBlend; + }, + set_alwaysBlend: function (value) { + this.config.alwaysBlend = value; + }, + get_autoHideControls: function () { + return this.config.autoHideControls; + }, + set_autoHideControls: function (value) { + this.config.autoHideControls = value; + }, + get_immediateRender: function () { + return this.config.immediateRender; + }, + set_immediateRender: function (value) { + this.config.immediateRender = value; + }, + get_wrapHorizontal: function () { + return this.config.wrapHorizontal; + }, + set_wrapHorizontal: function (value) { + this.config.wrapHorizontal = value; + }, + get_wrapVertical: function () { + return this.config.wrapVertical; + }, + set_wrapVertical: function (value) { + this.config.wrapVertical = value; + }, + get_minZoomImageRatio: function () { + return this.config.minZoomImageRatio; + }, + set_minZoomImageRatio: function (value) { + this.config.minZoomImageRatio = value; + }, + get_maxZoomPixelRatio: function () { + return this.config.maxZoomPixelRatio; + }, + set_maxZoomPixelRatio: function (value) { + this.config.maxZoomPixelRatio = value; + }, + get_visibilityRatio: function () { + return this.config.visibilityRatio; + }, + set_visibilityRatio: function (value) { + this.config.visibilityRatio = value; + }, + get_springStiffness: function () { + return this.config.springStiffness; + }, + set_springStiffness: function (value) { + this.config.springStiffness = value; + }, + get_imageLoaderLimit: function () { + return this.config.imageLoaderLimit; + }, + set_imageLoaderLimit: function (value) { + this.config.imageLoaderLimit = value; + }, + get_clickTimeThreshold: function () { + return this.config.clickTimeThreshold; + }, + set_clickTimeThreshold: function (value) { + this.config.clickTimeThreshold = value; + }, + get_clickDistThreshold: function () { + return this.config.clickDistThreshold; + }, + set_clickDistThreshold: function (value) { + this.config.clickDistThreshold = value; + }, + get_zoomPerClick: function () { + return this.config.zoomPerClick; + }, + set_zoomPerClick: function (value) { + this.config.zoomPerClick = value; + }, + get_zoomPerSecond: function () { + return this.config.zoomPerSecond; + }, + set_zoomPerSecond: function (value) { + this.config.zoomPerSecond = value; + }, + get_zoomPerScroll: function () { + return this.config.zoomPerScroll; + }, + set_zoomPerScroll: function (value) { + this.config.zoomPerScroll = value; + }, + get_maxImageCacheCount: function () { + return this.config.maxImageCacheCount; + }, + set_maxImageCacheCount: function (value) { + this.config.maxImageCacheCount = value; + }, + get_showNavigationControl: function () { + return this.config.showNavigationControl; + }, + set_showNavigationControl: function (value) { + this.config.showNavigationControl = value; + }, + get_minPixelRatio: function () { + return this.config.minPixelRatio; + }, + set_minPixelRatio: function (value) { + this.config.minPixelRatio = value; + }, + get_mouseNavEnabled: function () { + return this.config.mouseNavEnabled; + }, + set_mouseNavEnabled: function (value) { + this.config.mouseNavEnabled = value; + }, + get_controls: function () { + return this._customControls; + }, + set_controls: function (value) { + this._customControls = value; + }, + get_overlays: function () { + return this._overlayControls; + }, + set_overlays: function (value) { + this._overlayControls = value; + }, + get_prefixUrl: function () { + return this._prefixUrl; + }, + set_prefixUrl: function (value) { + this._prefixUrl = value; + }, + add_open: function (handler) { + this.get_events().addHandler("open", handler); + }, + remove_open: function (handler) { + this.get_events().removeHandler("open", handler); + }, + add_error: function (handler) { + this.get_events().addHandler("error", handler); + }, + remove_error: function (handler) { + this.get_events().removeHandler("error", handler); + }, + add_ignore: function (handler) { + this.get_events().addHandler("ignore", handler); + }, + remove_ignore: function (handler) { + this.get_events().removeHandler("ignore", handler); + }, + add_resize: function (handler) { + this.get_events().addHandler("resize", handler); + }, + remove_resize: function (handler) { + this.get_events().removeHandler("resize", handler); + }, + add_animationstart: function (handler) { + this.get_events().addHandler("animationstart", handler); + }, + remove_animationstart: function (handler) { + this.get_events().removeHandler("animationstart", handler); + }, + add_animation: function (handler) { + this.get_events().addHandler("animation", handler); + }, + remove_animation: function (handler) { + this.get_events().removeHandler("animation", handler); + }, + add_animationfinish: function (handler) { + this.get_events().addHandler("animationfinish", handler); + }, + remove_animationfinish: function (handler) { + this.get_events().removeHandler("animationfinish", handler); + }, + addControl: function (elmt, anchor) { + var elmt = Seadragon.Utils.getElement(elmt); + + if (this._getControlIndex(elmt) >= 0) { + return; // they're trying to add a duplicate control + } + + var div = null; + + switch (anchor) { + case Seadragon.ControlAnchor.TOP_RIGHT: + div = this._controlsTR; + elmt.style.position = "relative"; + break; + case Seadragon.ControlAnchor.BOTTOM_RIGHT: + div = this._controlsBR; + elmt.style.position = "relative"; + break; + case Seadragon.ControlAnchor.BOTTOM_LEFT: + div = this._controlsBL; + elmt.style.position = "relative"; + break; + case Seadragon.ControlAnchor.TOP_LEFT: + div = this._controlsTL; + elmt.style.position = "relative"; + break; + case Seadragon.ControlAnchor.NONE: + default: + div = this._container; + elmt.style.position = "absolute"; + break; + } + + this._controls.push(new Seadragon.Control(elmt, anchor, div)); + + elmt.style.display = "inline-block"; + }, + isOpen: function () { + return !!this.source; + }, + openDzi: function (xmlUrl, xmlString) { + var currentTime = this._beforeOpen(); + Seadragon.DziTileSourceHelper.createFromXml(xmlUrl, xmlString, + Seadragon.Utils.createCallback(null, Function.createDelegate(this, this._onOpen), currentTime)); + }, + openTileSource: function (tileSource) { + var currentTime = beforeOpen(); + window.setTimeout(Function.createDelegate(this, function () { + onOpen(currentTime, tileSource); + }), 1); + }, + close: function () { + if (!this.source) { + return; + } + + this._onClose(); + }, + removeControl: function (elmt) { + var elmt = Seadragon.Utils.getElement(elmt); + var i = this._getControlIndex(elmt); + + if (i >= 0) { + this._controls[i].destroy(); + this._controls.splice(i, 1); + } + }, + clearControls: function () { + while (this._controls.length > 0) { + this._controls.pop().destroy(); + } + }, + isDashboardEnabled: function () { + for (var i = this._controls.length - 1; i >= 0; i--) { + if (this._controls[i].isVisible()) { + return true; + } + } + + return false; + }, + + isFullPage: function () { + return this._container.parentNode == document.body; + }, + + isMouseNavEnabled: function () { + return this._innerTracker.isTracking(); + }, + + isVisible: function () { + return this._container.style.visibility != "hidden"; + }, + + setDashboardEnabled: function (enabled) { + for (var i = this._controls.length - 1; i >= 0; i--) { + this._controls[i].setVisible(enabled); + } + }, + + setFullPage: function (fullPage) { + if (fullPage == this.isFullPage()) { + return; + } + + var body = document.body; + var bodyStyle = body.style; + var docStyle = document.documentElement.style; + var containerStyle = this._container.style; + var canvasStyle = this._canvas.style; + + if (fullPage) { + bodyOverflow = bodyStyle.overflow; + docOverflow = docStyle.overflow; + bodyStyle.overflow = "hidden"; + docStyle.overflow = "hidden"; + + bodyWidth = bodyStyle.width; + bodyHeight = bodyStyle.height; + bodyStyle.width = "100%"; + bodyStyle.height = "100%"; + + canvasStyle.backgroundColor = "black"; + canvasStyle.color = "white"; + + containerStyle.position = "fixed"; + containerStyle.zIndex = "99999999"; + + body.appendChild(this._container); + this._prevContainerSize = Seadragon.Utils.getWindowSize(); + + this._onContainerEnter(); // mouse will be inside container now + } else { + bodyStyle.overflow = bodyOverflow; + docStyle.overflow = docOverflow; + + bodyStyle.width = bodyWidth; + bodyStyle.height = bodyHeight; + + canvasStyle.backgroundColor = ""; + canvasStyle.color = ""; + + containerStyle.position = "relative"; + containerStyle.zIndex = ""; + + this.get_element().appendChild(this._container); + this._prevContainerSize = Seadragon.Utils.getElementSize(this.get_element()); + + this._onContainerExit(); // mouse will likely be outside now + } + if (this.viewport) { + var oldBounds = this.viewport.getBounds(); + this.viewport.resize(this._prevContainerSize); + var newBounds = this.viewport.getBounds(); + + if (fullPage) { + this._fsBoundsDelta = new Seadragon.Point(newBounds.width / oldBounds.width, + newBounds.height / oldBounds.height); + } else { + this.viewport.update(); + this.viewport.zoomBy(Math.max(this._fsBoundsDelta.x, this._fsBoundsDelta.y), + null, true); + } + + this._forceRedraw = true; + this._raiseEvent("resize", this); + this._updateOnce(); + } + }, + + setMouseNavEnabled: function (enabled) { + this._innerTracker.setTracking(enabled); + }, + + setVisible: function (visible) { + this._container.style.visibility = visible ? "" : "hidden"; + } + +} +Seadragon.Strings = { + Errors: { + Failure: SeadragonConfig.Failure ? SeadragonConfig.Failure : "Sorry, but Seadragon Ajax can't run on your browser!\n" + "Please try using IE 7 or Firefox 3.\n", + Dzc: SeadragonConfig.Dzc ? SeadragonConfig.Dzc : "Sorry, we don't support Deep Zoom Collections!", + Dzi: SeadragonConfig.Dzi ? SeadragonConfig.Dzi : "Hmm, this doesn't appear to be a valid Deep Zoom Image.", + Xml: SeadragonConfig.Xml ? SeadragonConfig.Xml : "Hmm, this doesn't appear to be a valid Deep Zoom Image.", + Empty: SeadragonConfig.Empty ? SeadragonConfig.Empty : "You asked us to open nothing, so we did just that.", + ImageFormat: SeadragonConfig.ImageFormat ? SeadragonConfig.ImageFormat : "Sorry, we don't support {0}-based Deep Zoom Images.", + Security: SeadragonConfig.Security ? SeadragonConfig.Security : "It looks like a security restriction stopped us from " + "loading this Deep Zoom Image.", + Status: SeadragonConfig.Status ? SeadragonConfig.Status : "This space unintentionally left blank ({0} {1}).", + Unknown: SeadragonConfig.Unknown ? SeadragonConfig.Unknown : "Whoops, something inexplicably went wrong. Sorry!" + }, + + Messages: { + Loading: SeadragonConfig.Loading ? SeadragonConfig.Loading : "Loading..." + }, + + Tooltips: { + FullPage: SeadragonConfig.FullPage ? SeadragonConfig.FullPage : "Exit", + Home: SeadragonConfig.Home ? SeadragonConfig.Home : "Fit image", + ZoomIn: SeadragonConfig.ZoomIn ? SeadragonConfig.ZoomIn : "Zoom in", + ZoomOut: SeadragonConfig.ZoomOut ? SeadragonConfig.ZoomOut : "Zoom out" + }, + getString: function(prop) { + var props = prop.split('.'); + var string = Seadragon.Strings; + + for (var i = 0; i < props.length; i++) { + string = string[props[i]] || {}; // in case not a subproperty + } + + if (typeof (string) != "string") { + string = ""; + } + + var args = arguments; + return string.replace(/\{\d+\}/g, function(capture) { + var i = parseInt(capture.match(/\d+/)) + 1; + return i < args.length ? args[i] : ""; + }); + }, + + setString: function(prop, value) { + var props = prop.split('.'); + var container = Seadragon.Strings; + + for (var i = 0; i < props.length - 1; i++) { + if (!container[props[i]]) { + container[props[i]] = {}; + } + container = container[props[i]]; + } + + container[props[i]] = value; + } + +} +Seadragon.Strings = Seadragon.Strings; + + +Seadragon.Point=Seadragon.Point = function(x, y) { + this.x = typeof (x) == "number" ? x : 0; + this.y = typeof (y) == "number" ? y : 0; +} +Seadragon.Point.prototype = { + + plus: function(point) { + return new Seadragon.Point(this.x + point.x, this.y + point.y); + }, + + minus: function(point) { + return new Seadragon.Point(this.x - point.x, this.y - point.y); + }, + + times: function(factor) { + return new Seadragon.Point(this.x * factor, this.y * factor); + }, + + divide: function(factor) { + return new Seadragon.Point(this.x / factor, this.y / factor); + }, + + negate: function() { + return new Seadragon.Point(-this.x, -this.y); + }, + + distanceTo: function(point) { + return Math.sqrt(Math.pow(this.x - point.x, 2) + + Math.pow(this.y - point.y, 2)); + }, + + apply: function(func) { + return new Seadragon.Point(func(this.x), func(this.y)); + }, + + equals: function(point) { + return (point instanceof Seadragon.Point) && + (this.x === point.x) && (this.y === point.y); + }, + + toString: function() { + return "(" + this.x + "," + this.y + ")"; + } +} +Seadragon.Profiler = function() { + + this._midUpdate = false; + this._numUpdates = 0; + + this._lastBeginTime = null; + this._lastEndTime = null; + + this._minUpdateTime = Infinity; + this._avgUpdateTime = 0; + this._maxUpdateTime = 0; + + this._minIdleTime = Infinity; + this._avgIdleTime = 0; + this._maxIdleTime = 0; +} +Seadragon.Profiler.prototype = { + + getAvgUpdateTime: function() { + return this._avgUpdateTime; + }, + + getMinUpdateTime: function() { + return this._minUpdateTime; + }, + + getMaxUpdateTime: function() { + return this._maxUpdateTime; + }, + + + getAvgIdleTime: function() { + return this._avgIdleTime; + }, + + getMinIdleTime: function() { + return this._minIdleTime; + }, + + getMaxIdleTime: function() { + return this._maxIdleTime; + }, + + + isMidUpdate: function() { + return this._midUpdate; + }, + + getNumUpdates: function() { + return this._numUpdates; + }, + + + beginUpdate: function() { + if (this._midUpdate) { + this.endUpdate(); + } + + this._midUpdate = true; + this._lastBeginTime = new Date().getTime(); + + if (this._numUpdates < 1) { + return; // this is the first update + } + + var time = this._lastBeginTime - this._lastEndTime; + + this._avgIdleTime = (this._avgIdleTime * (this._numUpdates - 1) + time) / this._numUpdates; + + if (time < this._minIdleTime) { + this._minIdleTime = time; + } + if (time > this._maxIdleTime) { + this._maxIdleTime = time; + } + }, + + endUpdate: function() { + if (!this._midUpdate) { + return; + } + + this._lastEndTime = new Date().getTime(); + this._midUpdate = false; + + var time = this._lastEndTime - this._lastBeginTime; + + this._numUpdates++; + this._avgUpdateTime = (this._avgUpdateTime * (this._numUpdates - 1) + time) / this._numUpdates; + + if (time < this._minUpdateTime) { + this._minUpdateTime = time; + } + if (time > this._maxUpdateTime) { + this._maxUpdateTime = time; + } + }, + + clearProfile: function() { + this._midUpdate = false; + this._numUpdates = 0; + + this._lastBeginTime = null; + this._lastEndTime = null; + + this._minUpdateTime = Infinity; + this._avgUpdateTime = 0; + this._maxUpdateTime = 0; + + this._minIdleTime = Infinity; + this._avgIdleTime = 0; + this._maxIdleTime = 0; + } +} +Seadragon.Job = function(src, callback) { + this._image = null; + this._timeout = null; + this._src = src; + this._callback = callback; + this.TIMEOUT = 5000; +} +Seadragon.Job.prototype = { + _finish: function(success) { + this._image.onload = null; + this._image.onabort = null; + this._image.onerror = null; + + + if (this._timeout) { + window.clearTimeout(this._timeout); + } + + var image = this._image; + var callback = this._callback; + window.setTimeout(function() { + callback(this._src, success ? image : null); + }, 1); + }, + _onloadHandler: function() { + this._finish(true); + }, + _onerrorHandler: function() { + this._finish(false); + }, + start: function() { + this._image = new Image(); + this._image.onload = Function.createDelegate(this, this._onloadHandler); + this._image.onabort = Function.createDelegate(this, this._onerrorHandler); + this._image.onerror = Function.createDelegate(this, this._onerrorHandler); + + this._timeout = window.setTimeout(Function.createDelegate(this, this._onerrorHandler), this.TIMEOUT); + + this._image.src = this._src; + } +} + + +Seadragon.ImageLoader = function(imageLoaderLimit) { + this._downloading = 0; + this.imageLoaderLimit = imageLoaderLimit; +} +Seadragon.ImageLoader.prototype = { + _onComplete: function(callback, src, image) { + this._downloading--; + if (typeof (callback) == "function") { + try { + callback(image); + } catch (e) { + Seadragon.Debug.error(e.name + " while executing " + src + + " callback: " + e.message, e); + } + } + }, + loadImage: function(src, callback) { + if (this._downloading >= this.imageLoaderLimit) { + return false; + } + + var func = Seadragon.Utils.createCallback(null, Function.createDelegate(this, this._onComplete), callback); + var job = new Seadragon.Job(src, func); + + this._downloading++; + job.start(); + + return true; + } +} + + +Seadragon.TileSource = function(width, height, tileSize, tileOverlap, minLevel, maxLevel) { + this.aspectRatio = width / height; + this.dimensions = new Seadragon.Point(width, height); + this.minLevel = minLevel ? minLevel : 0; + this.maxLevel = maxLevel ? maxLevel : + Math.ceil(Math.log(Math.max(width, height)) / Math.log(2)); + this.tileSize = tileSize ? tileSize : 0; + this.tileOverlap = tileOverlap ? tileOverlap : 0; +} +Seadragon.TileSource.prototype = { + getLevelScale: function(level) { + return 1 / (1 << (this.maxLevel - level)); + }, + + getNumTiles: function(level) { + var scale = this.getLevelScale(level); + var x = Math.ceil(scale * this.dimensions.x / this.tileSize); + var y = Math.ceil(scale * this.dimensions.y / this.tileSize); + + return new Seadragon.Point(x, y); + }, + + getPixelRatio: function(level) { + var imageSizeScaled = this.dimensions.times(this.getLevelScale(level)); + var rx = 1.0 / imageSizeScaled.x; + var ry = 1.0 / imageSizeScaled.y; + + return new Seadragon.Point(rx, ry); + }, + + getTileAtPoint: function(level, point) { + var pixel = point.times(this.dimensions.x).times(this.getLevelScale(level)); + + var tx = Math.floor(pixel.x / this.tileSize); + var ty = Math.floor(pixel.y / this.tileSize); + + return new Seadragon.Point(tx, ty); + }, + + getTileBounds: function(level, x, y) { + var dimensionsScaled = this.dimensions.times(this.getLevelScale(level)); + + var px = (x === 0) ? 0 : this.tileSize * x - this.tileOverlap; + var py = (y === 0) ? 0 : this.tileSize * y - this.tileOverlap; + + var sx = this.tileSize + (x === 0 ? 1 : 2) * this.tileOverlap; + var sy = this.tileSize + (y === 0 ? 1 : 2) * this.tileOverlap; + + sx = Math.min(sx, dimensionsScaled.x - px); + sy = Math.min(sy, dimensionsScaled.y - py); + + var scale = 1.0 / dimensionsScaled.x; + return new Seadragon.Rect(px * scale, py * scale, sx * scale, sy * scale); + }, + + getTileUrl: function(level, x, y) { + throw new Error("Method not implemented."); + }, + + tileExists: function(level, x, y) { + var numTiles = this.getNumTiles(level); + return level >= this.minLevel && level <= this.maxLevel && + x >= 0 && y >= 0 && x < numTiles.x && y < numTiles.y; + } +} +Seadragon.DziError = function(message) { + Error.apply(this, arguments); + this.message = message; +} +Seadragon.DziError.prototype = new Error(); +Seadragon.DziError.constructor = Seadragon.DziError; + +Seadragon.DziTileSource = function(width, height, tileSize, tileOverlap, tilesUrl, fileFormat, displayRects) { + Seadragon.TileSource.call(this, width, height, tileSize, tileOverlap, null, null); + + this._levelRects = {}; + this.tilesUrl = tilesUrl; + + this.fileFormat = fileFormat; + this.displayRects = displayRects; + this.initialize(); +} +Seadragon.DziTileSource.prototype = new Seadragon.TileSource(); +Seadragon.DziTileSource.prototype.constructor = Seadragon.DziTileSource; +Seadragon.DziTileSource.prototype.initialize = function() { + if (!this.displayRects) { + return; + } + + for (var i = this.displayRects.length - 1; i >= 0; i--) { + var rect = this.displayRects[i]; + for (var level = rect.minLevel; level <= rect.maxLevel; level++) { + if (!this._levelRects[level]) { + this._levelRects[level] = []; + } + this._levelRects[level].push(rect); + } + } +} +Seadragon.DziTileSource.prototype.getTileUrl = function(level, x, y) { + return [this.tilesUrl, level, '/', x, '_', y, '.', this.fileFormat].join(''); +} +Seadragon.DziTileSource.prototype.tileExists = function(level, x, y) { + var rects = this._levelRects[level]; + + if (!rects || !rects.length) { + return true; + } + + for (var i = rects.length - 1; i >= 0; i--) { + var rect = rects[i]; + + if (level < rect.minLevel || level > rect.maxLevel) { + continue; + } + + var scale = this.getLevelScale(level); + var xMin = rect.x * scale; + var yMin = rect.y * scale; + var xMax = xMin + rect.width * scale; + var yMax = yMin + rect.height * scale; + + xMin = Math.floor(xMin / this.tileSize); + yMin = Math.floor(yMin / this.tileSize); + xMax = Math.ceil(xMax / this.tileSize); + yMax = Math.ceil(yMax / this.tileSize); + + if (xMin <= x && x < xMax && yMin <= y && y < yMax) { + return true; + } + } + + return false; +} + +Seadragon._DziTileSourceHelper = function() { + +} +Seadragon._DziTileSourceHelper.prototype = { + createFromXml: function(xmlUrl, xmlString, callback) { + var async = typeof (callback) == "function"; + var error = null; + + if (!xmlUrl) { + this.error = Seadragon.Strings.getString("Errors.Empty"); + if (async) { + window.setTimeout(function() { + callback(null, error); + }, 1); + return null; + } + throw new Seadragon.DziError(error); + } + + var urlParts = xmlUrl.split('/'); + var filename = urlParts[urlParts.length - 1]; + var lastDot = filename.lastIndexOf('.'); + + if (lastDot > -1) { + urlParts[urlParts.length - 1] = filename.slice(0, lastDot); + } + + var tilesUrl = urlParts.join('/') + "_files/"; + function finish(func, obj) { + try { + return func(obj, tilesUrl); + } catch (e) { + if (async) { + error = this.getError(e).message; + return null; + } else { + throw this.getError(e); + } + } + } + if (async) { + if (xmlString) { + var handler = Function.createDelegate(this, this.processXml); + window.setTimeout(function() { + var source = finish(handler, Seadragon.Utils.parseXml(xmlString)); + callback(source, error); // call after finish sets error + }, 1); + } else { + var handler = Function.createDelegate(this, this.processResponse); + Seadragon.Utils.makeAjaxRequest(xmlUrl, function(xhr) { + var source = finish(handler, xhr); + callback(source, error); // call after finish sets error + }); + } + + return null; + } + + if (xmlString) { + return finish(Function.createDelegate(this, this.processXml), Seadragon.Utils.parseXml(xmlString)); + } else { + return finish(Function.createDelegate(this, this.processResponse), Seadragon.Utils.makeAjaxRequest(xmlUrl)); + } + }, + processResponse: function(xhr, tilesUrl) { + if (!xhr) { + throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.Security")); + } else if (xhr.status !== 200 && xhr.status !== 0) { + var status = xhr.status; + var statusText = (status == 404) ? "Not Found" : xhr.statusText; + throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.Status", status, statusText)); + } + + var doc = null; + + if (xhr.responseXML && xhr.responseXML.documentElement) { + doc = xhr.responseXML; + } else if (xhr.responseText) { + doc = Seadragon.Utils.parseXml(xhr.responseText); + } + + return this.processXml(doc, tilesUrl); + }, + + processXml: function(xmlDoc, tilesUrl) { + if (!xmlDoc || !xmlDoc.documentElement) { + throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.Xml")); + } + + var root = xmlDoc.documentElement; + var rootName = root.tagName; + + if (rootName == "Image") { + try { + return this.processDzi(root, tilesUrl); + } catch (e) { + var defMsg = Seadragon.Strings.getString("Errors.Dzi"); + throw (e instanceof Seadragon.DziError) ? e : new Seadragon.DziError(defMsg); + } + } else if (rootName == "Collection") { + throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.Dzc")); + } else if (rootName == "Error") { + return this.processError(root); + } + + throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.Dzi")); + }, + + processDzi: function(imageNode, tilesUrl) { + var fileFormat = imageNode.getAttribute("Format"); + + if (!Seadragon.Utils.imageFormatSupported(fileFormat)) { + throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.ImageFormat", + fileFormat.toUpperCase())); + } + + var sizeNode = imageNode.getElementsByTagName("Size")[0]; + var dispRectNodes = imageNode.getElementsByTagName("DisplayRect"); + + var width = parseInt(sizeNode.getAttribute("Width"), 10); + var height = parseInt(sizeNode.getAttribute("Height"), 10); + var tileSize = parseInt(imageNode.getAttribute("TileSize")); + var tileOverlap = parseInt(imageNode.getAttribute("Overlap")); + var dispRects = []; + + for (var i = 0; i < dispRectNodes.length; i++) { + var dispRectNode = dispRectNodes[i]; + var rectNode = dispRectNode.getElementsByTagName("Rect")[0]; + + dispRects.push(new Seadragon.DisplayRect( + parseInt(rectNode.getAttribute("X"), 10), + parseInt(rectNode.getAttribute("Y"), 10), + parseInt(rectNode.getAttribute("Width"), 10), + parseInt(rectNode.getAttribute("Height"), 10), + 0, // ignore MinLevel attribute, bug in Deep Zoom Composer + parseInt(dispRectNode.getAttribute("MaxLevel"), 10) + )); + } + return new Seadragon.DziTileSource(width, height, tileSize, tileOverlap, + tilesUrl, fileFormat, dispRects); + }, + + processError: function(errorNode) { + var messageNode = errorNode.getElementsByTagName("Message")[0]; + var message = messageNode.firstChild.nodeValue; + + throw new Seadragon.DziError(message); + }, + getError: function(e) { + if (!(e instanceof DziError)) { + Seadragon.Debug.error(e.name + " while creating DZI from XML: " + e.message); + e = new Seadragon.DziError(Seadragon.Strings.getString("Errors.Unknown")); + } + + } +} +Seadragon.DziTileSourceHelper = new Seadragon._DziTileSourceHelper(); + +Seadragon.ButtonState = function() { + throw Error.invalidOperation(); +} +Seadragon.ButtonState = { + REST: 0, + GROUP: 1, + HOVER: 2, + DOWN: 3 +} + +Seadragon.Button = function(properties, events) { + + this._tooltip = properties.tooltip; + this._srcRest = properties.srcRest; + this._srcGroup = properties.srcGroup; + this._srcHover = properties.srcHover; + this._srcDown = properties.srcDown; + this._button = properties.button; + this.config = properties.config; + + this.initialize(events); +} +Seadragon.Button.prototype = { + initialize: function(events) { + + this._observer = new Observer(); + + if (events.onPress != undefined) + this.add_onPress(events.onPress); + if (events.onRelease != undefined) + this.add_onRelease(events.onRelease); + if (events.onClick != undefined) + this.add_onClick(events.onClick); + if (events.onEnter != undefined) + this.add_onEnter(events.onEnter); + if (events.onExit != undefined) + this.add_onExit(events.onExit); + + this._button = Seadragon.Utils.makeNeutralElement("span"); + this._currentState = Seadragon.ButtonState.GROUP; + this._tracker = new Seadragon.MouseTracker(this._button, this.config.clickTimeThreshold, this.config.clickDistThreshold); + this._imgRest = Seadragon.Utils.makeTransparentImage(this._srcRest); + this._imgGroup = Seadragon.Utils.makeTransparentImage(this._srcGroup); + this._imgHover = Seadragon.Utils.makeTransparentImage(this._srcHover); + this._imgDown = Seadragon.Utils.makeTransparentImage(this._srcDown); + + this._fadeDelay = 0; // begin fading immediately + this._fadeLength = 2000; // fade over a period of 2 seconds + this._fadeBeginTime = null; + this._shouldFade = false; + + this._button.style.display = "inline-block"; + this._button.style.position = "relative"; + this._button.title = this._tooltip; + + this._button.appendChild(this._imgRest); + this._button.appendChild(this._imgGroup); + this._button.appendChild(this._imgHover); + this._button.appendChild(this._imgDown); + + var styleRest = this._imgRest.style; + var styleGroup = this._imgGroup.style; + var styleHover = this._imgHover.style; + var styleDown = this._imgDown.style; + + styleGroup.position = styleHover.position = styleDown.position = "absolute"; + styleGroup.top = styleHover.top = styleDown.top = "0px"; + styleGroup.left = styleHover.left = styleDown.left = "0px"; + styleHover.visibility = styleDown.visibility = "hidden"; + + if (Seadragon.Utils.getBrowser() == Seadragon.Browser.FIREFOX && + Seadragon.Utils.getBrowserVersion() < 3) { + styleGroup.top = styleHover.top = styleDown.top = ""; + } + + this._tracker.enterHandler = Function.createDelegate(this, this._enterHandler); + this._tracker.exitHandler = Function.createDelegate(this, this._exitHandler); + this._tracker.pressHandler = Function.createDelegate(this, this._pressHandler); + this._tracker.releaseHandler = Function.createDelegate(this, this._releaseHandler); + this._tracker.clickHandler = Function.createDelegate(this, this._clickHandler); + + this._tracker.setTracking(true); + this._outTo(Seadragon.ButtonState.REST); + }, + dispose: function() { + }, + _scheduleFade: function() { + window.setTimeout(Function.createDelegate(this, this._updateFade), 20); + }, + _updateFade: function() { + if (this._shouldFade) { + var currentTime = new Date().getTime(); + var deltaTime = currentTime - this._fadeBeginTime; + var opacity = 1.0 - deltaTime / this._fadeLength; + + opacity = Math.min(1.0, opacity); + opacity = Math.max(0.0, opacity); + + Seadragon.Utils.setElementOpacity(this._imgGroup, opacity, true); + if (opacity > 0) { + this._scheduleFade(); // fade again + } + } + }, + _beginFading: function() { + this._shouldFade = true; + this._fadeBeginTime = new Date().getTime() + this._fadeDelay; + window.setTimeout(Function.createDelegate(this, this._scheduleFade), this._fadeDelay); + }, + _stopFading: function() { + this._shouldFade = false; + Seadragon.Utils.setElementOpacity(this._imgGroup, 1.0, true); + }, + _inTo: function(newState) { + if (newState >= Seadragon.ButtonState.GROUP && this._currentState == Seadragon.ButtonState.REST) { + this._stopFading(); + this._currentState = Seadragon.ButtonState.GROUP; + } + + if (newState >= Seadragon.ButtonState.HOVER && this._currentState == Seadragon.ButtonState.GROUP) { + this._imgHover.style.visibility = ""; + this._currentState = Seadragon.ButtonState.HOVER; + } + + if (newState >= Seadragon.ButtonState.DOWN && this._currentState == Seadragon.ButtonState.HOVER) { + this._imgDown.style.visibility = ""; + this._currentState = Seadragon.ButtonState.DOWN; + } + }, + _outTo: function(newState) { + if (newState <= Seadragon.ButtonState.HOVER && this._currentState == Seadragon.ButtonState.DOWN) { + this._imgDown.style.visibility = "hidden"; + this._currentState = Seadragon.ButtonState.HOVER; + } + + if (newState <= Seadragon.ButtonState.GROUP && this._currentState == Seadragon.ButtonState.HOVER) { + this._imgHover.style.visibility = "hidden"; + this._currentState = Seadragon.ButtonState.GROUP; + } + + if (this._newState <= Seadragon.ButtonState.REST && this._currentState == Seadragon.ButtonState.GROUP) { + this._beginFading(); + this._currentState = Seadragon.ButtonState.REST; + } + }, + _enterHandler: function(tracker, position, buttonDownElmt, buttonDownAny) { + if (buttonDownElmt) { + this._inTo(Seadragon.ButtonState.DOWN); + this._raiseEvent("onEnter", this); + } else if (!buttonDownAny) { + this._inTo(Seadragon.ButtonState.HOVER); + } + }, + _exitHandler: function(tracker, position, buttonDownElmt, buttonDownAny) { + this._outTo(Seadragon.ButtonState.GROUP); + if (buttonDownElmt) { + this._raiseEvent("onExit", this); + } + }, + _pressHandler: function(tracker, position) { + this._inTo(Seadragon.ButtonState.DOWN); + this._raiseEvent("onPress", this); + }, + _releaseHandler: function(tracker, position, insideElmtPress, insideElmtRelease) { + if (insideElmtPress && insideElmtRelease) { + this._outTo(Seadragon.ButtonState.HOVER); + this._raiseEvent("onRelease", this); + } else if (insideElmtPress) { + this._outTo(Seadragon.ButtonState.GROUP); + } else { + this._inTo(Seadragon.ButtonState.HOVER); + } + }, + _clickHandler: function(tracker, position, quick, shift) { + if (quick) { + this._raiseEvent("onClick", this); + } + }, + get_events: function get_events() { + return this._observer._getContext(this, true).events; + }, + _raiseEvent: function(eventName, eventArgs) { + var handler = this.get_events().getHandler(eventName); + + if (handler) { + if (!eventArgs) { + eventArgs = new Object(); // Sys.EventArgs.Empty; + } + + handler(this, eventArgs); + } + }, + get_element: function() { + return this._button; + }, + get_tooltip: function() { + return this._tooltip; + }, + set_tooltip: function(value) { + this._tooltip = value; + }, + get_config: function() { + return this.config; + }, + set_config: function(value) { + this.config = value; + }, + get_srcRest: function() { + return this._srcRest; + }, + set_srcRest: function(value) { + this._srcRest = value; + }, + get_srcGroup: function() { + return this._srcGroup; + }, + set_srcGroup: function(value) { + this._srcGroup = value; + }, + get_srcHover: function() { + return this._srcHover; + }, + set_srcHover: function(value) { + this._srcHover = value; + }, + get_srcDown: function() { + return this._srcDown; + }, + set_srcDown: function(value) { + this._srcDown = value; + }, + add_onPress: function(handler) { + this.get_events().addHandler("onPress", handler); + }, + remove_onPress: function(handler) { + this.get_events().removeHandler("onPress", handler); + }, + add_onClick: function(handler) { + this.get_events().addHandler("onClick", handler); + }, + remove_onClick: function(handler) { + this.get_events().removeHandler("onClick", handler); + }, + add_onEnter: function(handler) { + this.get_events().addHandler("onEnter", handler); + }, + remove_onEnter: function(handler) { + this.get_events().removeHandler("onEnter", handler); + }, + add_onRelease: function(handler) { + this.get_events().addHandler("onRelease", handler); + }, + remove_onRelease: function(handler) { + this.get_events().removeHandler("onRelease", handler); + }, + add_onExit: function(handler) { + this.get_events().addHandler("onExit", handler); + }, + remove_onExit: function(handler) { + this.get_events().removeHandler("onExit", handler); + }, + notifyGroupEnter: function() { + this._inTo(Seadragon.ButtonState.GROUP); + }, + notifyGroupExit: function() { + this._outTo(Seadragon.ButtonState.REST); + } +} + +Seadragon.ButtonGroup = function(properties) { + + this._buttons = properties.buttons; + this._group = properties.group; + this.config = properties.config; + + this.initialize(); +} +Seadragon.ButtonGroup.prototype = { + initialize: function() { + + this._group = Seadragon.Utils.makeNeutralElement("span"); + var buttons = this._buttons.concat([]); // copy + var tracker = new Seadragon.MouseTracker(this._group, this.config.clickTimeThreshold, this.config.clickDistThreshold); + this._group.style.display = "inline-block"; + + for (var i = 0; i < buttons.length; i++) { + this._group.appendChild(buttons[i].get_element()); + } + + tracker.enterHandler = Function.createDelegate(this, this._enterHandler); + tracker.exitHandler = Function.createDelegate(this, this._exitHandler); + tracker.releaseHandler = Function.createDelegate(this, this._releaseHandler); + + tracker.setTracking(true); + }, + dispose: function() { + }, + get_buttons: function() { + return this._buttons; + }, + set_buttons: function(value) { + this._buttons = value; + }, + get_element: function() { + return this._group; + }, + get_config: function() { + return this.config; + }, + set_config: function(value) { + this.config = value; + }, + _enterHandler: function(tracker, position, buttonDownElmt, buttonDownAny) { + for (var i = 0; i < this._buttons.length; i++) { + this._buttons[i].notifyGroupEnter(); + } + }, + _exitHandler: function(tracker, position, buttonDownElmt, buttonDownAny) { + if (!buttonDownElmt) { + for (var i = 0; i < this._buttons.length; i++) { + this._buttons[i].notifyGroupExit(); + } + } + }, + _releaseHandler: function(tracker, position, insideElmtPress, insideElmtRelease) { + + if (!insideElmtRelease) { + for (var i = 0; i < this._buttons.length; i++) { + this._buttons[i].notifyGroupExit(); + } + } + }, + emulateEnter: function() { + this._enterHandler(); + }, + + emulateExit: function() { + this._exitHandler(); + } +} +Seadragon.Config = function () { + + this.debugMode = false; + + this.animationTime = 1.5; + + this.blendTime = 0.5; + + this.alwaysBlend = false; + + this.autoHideControls = true; + + this.immediateRender = true; + + this.wrapHorizontal = false; + + this.wrapVertical = false; + + this.minZoomImageRatio = 0.8; + + this.maxZoomPixelRatio = 2; + + this.visibilityRatio = 0.5; + + this.springStiffness = 5.0; + + this.imageLoaderLimit = 2; + + this.clickTimeThreshold = 200; + + this.clickDistThreshold = 5; + + this.zoomPerClick = 2.0; + + this.zoomPerScroll = 1.2; + + this.zoomPerSecond = 2.0; + + this.showNavigationControl = true; + + this.maxImageCacheCount = 100; + + this.minPixelRatio = 0.5; + + this.mouseNavEnabled = true; + + this.navImages = { + zoomIn: { + REST: SeadragonConfig.imgPath + 'OpenSeadragon/images/zoomin_rest.png', + GROUP: SeadragonConfig.imgPath + 'OpenSeadragon/images/zoomin_grouphover.png', + HOVER: SeadragonConfig.imgPath + 'OpenSeadragon/images/zoomin_hover.png', + DOWN: SeadragonConfig.imgPath + 'OpenSeadragon/images/zoomin_pressed.png' + }, + zoomOut: { + REST: SeadragonConfig.imgPath + 'OpenSeadragon/images/zoomout_rest.png', + GROUP: SeadragonConfig.imgPath + 'OpenSeadragon/images/zoomout_grouphover.png', + HOVER: SeadragonConfig.imgPath + 'OpenSeadragon/images/zoomout_hover.png', + DOWN: SeadragonConfig.imgPath + 'OpenSeadragon/images/zoomout_pressed.png' + }, + home: { + REST: SeadragonConfig.imgPath + 'OpenSeadragon/images/home_rest.png', + GROUP: SeadragonConfig.imgPath + 'OpenSeadragon/images/home_grouphover.png', + HOVER: SeadragonConfig.imgPath + 'OpenSeadragon/images/home_hover.png', + DOWN: SeadragonConfig.imgPath + 'OpenSeadragon/images/home_pressed.png' + }, + fullpage: { + REST: SeadragonConfig.imgPath + 'OpenSeadragon/images/fullpage_rest.png', + GROUP: SeadragonConfig.imgPath + 'OpenSeadragon/images/fullpage_grouphover.png', + HOVER: SeadragonConfig.imgPath + 'OpenSeadragon/images/fullpage_hover.png', + DOWN: SeadragonConfig.imgPath + 'OpenSeadragon/images/fullpage_pressed.png' + } + } +} +Seadragon.Rect = function(x, y, width, height) { + + this.x = typeof (x) == "number" ? x : 0; + this.y = typeof (y) == "number" ? y : 0; + this.width = typeof (width) == "number" ? width : 0; + this.height = typeof (height) == "number" ? height : 0; +} +Seadragon.Rect.prototype = { + getAspectRatio: function() { + return this.width / this.height; + }, + + getTopLeft: function() { + return new Seadragon.Point(this.x, this.y); + }, + + getBottomRight: function() { + return new Seadragon.Point(this.x + this.width, this.y + this.height); + }, + + getCenter: function() { + return new Seadragon.Point(this.x + this.width / 2.0, + this.y + this.height / 2.0); + }, + + getSize: function() { + return new Seadragon.Point(this.width, this.height); + }, + + equals: function(other) { + return (other instanceof Seadragon.Rect) && + (this.x === other.x) && (this.y === other.y) && + (this.width === other.width) && (this.height === other.height); + }, + + toString: function() { + return "[" + this.x + "," + this.y + "," + this.width + "x" + + this.height + "]"; + } +} +Seadragon.DisplayRect = function(x, y, width, height, minLevel, maxLevel) { + Seadragon.Rect.apply(this, [x, y, width, height]); + + this.minLevel = minLevel; + this.maxLevel = maxLevel; +} +Seadragon.DisplayRect.prototype = new Seadragon.Rect(); +Seadragon.DisplayRect.prototype.constructor = Seadragon.DisplayRect; +Seadragon.Spring = Seadragon.Spring = function(initialValue, config) { + this._currentValue = typeof (initialValue) == "number" ? initialValue : 0; + this._startValue = this._currentValue; + this._targetValue = this._currentValue; + this.config = config; + + this._currentTime = new Date().getTime(); // always work in milliseconds + this._startTime = this._currentTime; + this._targetTime = this._currentTime; +} +Seadragon.Spring.prototype = { + _transform: function(x) { + var s = this.config.springStiffness; + return (1.0 - Math.exp(-x * s)) / (1.0 - Math.exp(-s)); + }, + getCurrent: function() { + return this._currentValue; + }, + + getTarget: function() { + return this._targetValue; + }, + + resetTo: function(target) { + this._targetValue = target; + this._targetTime = this._currentTime; + this._startValue = this._targetValue; + this._startTime = this._targetTime; + }, + + springTo: function(target) { + this._startValue = this._currentValue; + this._startTime = this._currentTime; + this._targetValue = target; + this._targetTime = this._startTime + 1000 * this.config.animationTime; + }, + + shiftBy: function(delta) { + this._startValue += delta; + this._targetValue += delta; + }, + + update: function() { + this._currentTime = new Date().getTime(); + this._currentValue = (this._currentTime >= this._targetTime) ? this._targetValue : + this._startValue + (this._targetValue - this._startValue) * + this._transform((this._currentTime - this._startTime) / (this._targetTime - this._startTime)); + } +} + +var QUOTA = 100; // the max number of images we should keep in memory +var MIN_PIXEL_RATIO = 0.5; // the most shrunk a tile should be + + +var browser = Seadragon.Utils.getBrowser(); +var browserVer = Seadragon.Utils.getBrowserVersion(); + +var subpixelRenders = browser == Seadragon.Browser.FIREFOX || + browser == Seadragon.Browser.OPERA || + (browser == Seadragon.Browser.SAFARI && browserVer >= 4) || + (browser == Seadragon.Browser.CHROME && browserVer >= 2); + +var useCanvas = + typeof (document.createElement("canvas").getContext) == "function" && + subpixelRenders; +Seadragon.Tile = function(level, x, y, bounds, exists, url) { + this.level = level; + this.x = x; + this.y = y; + this.bounds = bounds; // where this tile fits, in normalized coordinates + this.exists = exists; // part of sparse image? tile hasn't failed to load? + this.loaded = false; // is this tile loaded? + this.loading = false; // or is this tile loading? + + + + this.elmt = null; // the HTML element for this tile + this.image = null; // the Image object for this tile + this.url = url; // the URL of this tile's image + + + this.style = null; // alias of this.elmt.style + this.position = null; // this tile's position on screen, in pixels + this.size = null; // this tile's size on screen, in pixels + this.blendStart = null; // the start time of this tile's blending + this.opacity = null; // the current opacity this tile should be + this.distance = null; // the distance of this tile to the viewport center + this.visibility = null; // the visibility score of this tile + + this.beingDrawn = false; // whether this tile is currently being drawn + this.lastTouchTime = 0; // the time that tile was last touched +} +Seadragon.Tile.prototype = { + dispose: function() { + }, + toString: function() { + return this.level + "/" + this.x + "_" + this.y; + }, + drawHTML: function(container) { + if (!this.loaded) { + Seadragon.Debug.error("Attempting to draw tile " + this.toString() + + " when it's not yet loaded."); + return; + } + + if (!this.elmt) { + this.elmt = Seadragon.Utils.makeNeutralElement("img"); + this.elmt.src = this.url; + this.style = this.elmt.style; + this.style.position = "absolute"; + this.style.msInterpolationMode = "nearest-neighbor"; + } + + var elmt = this.elmt; + var style = this.style; + var position = this.position.apply(Math.floor); + var size = this.size.apply(Math.ceil); + + + if (elmt.parentNode != container) { + container.appendChild(elmt); + } + + style.left = position.x + "px"; + style.top = position.y + "px"; + style.width = size.x + "px"; + style.height = size.y + "px"; + + Seadragon.Utils.setElementOpacity(elmt, this.opacity); + }, + drawCanvas: function(context) { + if (!this.loaded) { + Seadragon.Debug.error("Attempting to draw tile " + this.toString() + + " when it's not yet loaded."); + return; + } + + var position = this.position; + var size = this.size; + + context.globalAlpha = this.opacity; + context.drawImage(this.image, position.x, position.y, size.x, size.y); + }, + unload: function() { + if (this.elmt && this.elmt.parentNode) { + this.elmt.parentNode.removeChild(this.elmt); + } + + this.elmt = null; + this.image = null; + this.loaded = false; + this.loading = false; + } +} + +Seadragon.Overlay = function(elmt, loc, placement) { + this.elmt = elmt; + this.scales = (loc instanceof Seadragon.Rect); + this.bounds = new Seadragon.Rect(loc.x, loc.y, loc.width, loc.height); + this.placement = loc instanceof Seadragon.Point ? placement : Seadragon.OverlayPlacement.TOP_LEFT; // rects are always top-left + this.position = new Seadragon.Point(loc.x, loc.y); + this.size = new Seadragon.Point(loc.width, loc.height); + this.style = elmt.style; +} +Seadragon.Overlay.prototype = { + + adjust: function(position, size) { + switch (this.placement) { + case Seadragon.OverlayPlacement.TOP_LEFT: + break; + case Seadragon.OverlayPlacement.TOP: + position.x -= size.x / 2; + break; + case Seadragon.OverlayPlacement.TOP_RIGHT: + position.x -= size.x; + break; + case Seadragon.OverlayPlacement.RIGHT: + position.x -= size.x; + position.y -= size.y / 2; + break; + case Seadragon.OverlayPlacement.BOTTOM_RIGHT: + position.x -= size.x; + position.y -= size.y; + break; + case Seadragon.OverlayPlacement.BOTTOM: + position.x -= size.x / 2; + position.y -= size.y; + break; + case Seadragon.OverlayPlacement.BOTTOM_LEFT: + position.y -= size.y; + break; + case Seadragon.OverlayPlacement.LEFT: + position.y -= size.y / 2; + break; + case Seadragon.OverlayPlacement.CENTER: + default: + position.x -= size.x / 2; + position.y -= size.y / 2; + break; + } + }, + destroy: function() { + var elmt = this.elmt; + var style = this.style; + + if (elmt.parentNode) { + elmt.parentNode.removeChild(elmt); + } + + style.top = ""; + style.left = ""; + style.position = ""; + + if (this.scales) { + style.width = ""; + style.height = ""; + } + }, + drawHTML: function(container) { + var elmt = this.elmt; + var style = this.style; + var scales = this.scales; + + if (elmt.parentNode != container) { + container.appendChild(elmt); + } + + if (!scales) { + this.size = Seadragon.Utils.getElementSize(elmt); + } + + var position = this.position; + var size = this.size; + + this.adjust(position, size); + + position = position.apply(Math.floor); + size = size.apply(Math.ceil); + + style.left = position.x + "px"; + style.top = position.y + "px"; + style.position = "absolute"; + + if (scales) { + style.width = size.x + "px"; + style.height = size.y + "px"; + } + }, + update: function(loc, placement) { + this.scales = (loc instanceof Seadragon.Rect); + this.bounds = new Seadragon.Rect(loc.x, loc.y, loc.width, loc.height); + this.placement = loc instanceof Seadragon.Point ? + placement : Seadragon.OverlayPlacement.TOP_LEFT; // rects are always top-left + } + +} + +Seadragon.Drawer = function(source, viewport, elmt) { + + this._container = Seadragon.Utils.getElement(elmt); + this._canvas = Seadragon.Utils.makeNeutralElement(useCanvas ? "canvas" : "div"); + this._context = useCanvas ? this._canvas.getContext("2d") : null; + this._viewport = viewport; + this._source = source; + this.config = this._viewport.config; + + this._imageLoader = new Seadragon.ImageLoader(this.config.imageLoaderLimit); + this._profiler = new Seadragon.Profiler(); + + this._minLevel = source.minLevel; + this._maxLevel = source.maxLevel; + this._tileSize = source.tileSize; + this._tileOverlap = source.tileOverlap; + this._normHeight = source.dimensions.y / source.dimensions.x; + + this._cacheNumTiles = {}; // 1d dictionary [level] --> Point + this._cachePixelRatios = {}; // 1d dictionary [level] --> Point + this._tilesMatrix = {}; // 3d dictionary [level][x][y] --> Tile + this._tilesLoaded = []; // unordered list of Tiles with loaded images + this._coverage = {}; // 3d dictionary [level][x][y] --> Boolean + + this._overlays = []; // unordered list of Overlays added + this._lastDrawn = []; // unordered list of Tiles drawn last frame + this._lastResetTime = 0; + this._midUpdate = false; + this._updateAgain = true; + + + this.elmt = this._container; + + + this._init(); +} +Seadragon.Drawer.prototype = { + dispose: function() { + }, + _init: function() { + this._canvas.style.width = "100%"; + this._canvas.style.height = "100%"; + this._canvas.style.position = "absolute"; + this._container.style.textAlign = "left"; // explicit left-align + this._container.appendChild(this._canvas); + }, + _compareTiles: function(prevBest, tile) { + if (!prevBest) { + return tile; + } + + if (tile.visibility > prevBest.visibility) { + return tile; + } else if (tile.visibility == prevBest.visibility) { + if (tile.distance < prevBest.distance) { + return tile; + } + } + + return prevBest; + }, + _getNumTiles: function(level) { + if (!this._cacheNumTiles[level]) { + this._cacheNumTiles[level] = this._source.getNumTiles(level); + } + + return this._cacheNumTiles[level]; + }, + + _getPixelRatio: function(level) { + if (!this._cachePixelRatios[level]) { + this._cachePixelRatios[level] = this._source.getPixelRatio(level); + } + + return this._cachePixelRatios[level]; + }, + + + _getTile: function(level, x, y, time, numTilesX, numTilesY) { + if (!this._tilesMatrix[level]) { + this._tilesMatrix[level] = {}; + } + if (!this._tilesMatrix[level][x]) { + this._tilesMatrix[level][x] = {}; + } + + if (!this._tilesMatrix[level][x][y]) { + var xMod = (numTilesX + (x % numTilesX)) % numTilesX; + var yMod = (numTilesY + (y % numTilesY)) % numTilesY; + var bounds = this._source.getTileBounds(level, xMod, yMod); + var exists = this._source.tileExists(level, xMod, yMod); + var url = this._source.getTileUrl(level, xMod, yMod); + + bounds.x += 1.0 * (x - xMod) / numTilesX; + bounds.y += this._normHeight * (y - yMod) / numTilesY; + + this._tilesMatrix[level][x][y] = new Seadragon.Tile(level, x, y, bounds, exists, url); + } + + var tile = this._tilesMatrix[level][x][y]; + + tile.lastTouchTime = time; + + return tile; + }, + + _loadTile: function(tile, time) { + tile.loading = this._imageLoader.loadImage(tile.url, + Seadragon.Utils.createCallback(null, Function.createDelegate(this, this._onTileLoad), tile, time)); + }, + + _onTileLoad: function(tile, time, image) { + tile.loading = false; + + if (this._midUpdate) { + Seadragon.Debug.error("Tile load callback in middle of drawing routine."); + return; + } else if (!image) { + Seadragon.Debug.log("Tile " + tile + " failed to load: " + tile.url); + tile.exists = false; + return; + } else if (time < this._lastResetTime) { + Seadragon.Debug.log("Ignoring tile " + tile + " loaded before reset: " + tile.url); + return; + } + + tile.loaded = true; + tile.image = image; + + var insertionIndex = this._tilesLoaded.length; + + if (this._tilesLoaded.length >= QUOTA) { + var cutoff = Math.ceil(Math.log(this._tileSize) / Math.log(2)); + + var worstTile = null; + var worstTileIndex = -1; + + for (var i = this._tilesLoaded.length - 1; i >= 0; i--) { + var prevTile = this._tilesLoaded[i]; + + if (prevTile.level <= this._cutoff || prevTile.beingDrawn) { + continue; + } else if (!worstTile) { + worstTile = prevTile; + worstTileIndex = i; + continue; + } + + var prevTime = prevTile.lastTouchTime; + var worstTime = worstTile.lastTouchTime; + var prevLevel = prevTile.level; + var worstLevel = worstTile.level; + + if (prevTime < worstTime || + (prevTime == worstTime && prevLevel > worstLevel)) { + worstTile = prevTile; + worstTileIndex = i; + } + } + + if (worstTile && worstTileIndex >= 0) { + worstTile.unload(); + insertionIndex = worstTileIndex; + } + } + + this._tilesLoaded[insertionIndex] = tile; + this._updateAgain = true; + }, + + _clearTiles: function() { + this._tilesMatrix = {}; + this._tilesLoaded = []; + }, + + + + /** + * Returns true if the given tile provides coverage to lower-level tiles of + * lower resolution representing the same content. If neither x nor y is + * given, returns true if the entire visible level provides coverage. + * + * Note that out-of-bounds tiles provide coverage in this sense, since + * there's no content that they would need to cover. Tiles at non-existent + * levels that are within the image bounds, however, do not. + */ + _providesCoverage: function(level, x, y) { + if (!this._coverage[level]) { + return false; + } + + if (x === undefined || y === undefined) { + var rows = this._coverage[level]; + for (var i in rows) { + if (rows.hasOwnProperty(i)) { + var cols = rows[i]; + for (var j in cols) { + if (cols.hasOwnProperty(j) && !cols[j]) { + return false; + } + } + } + } + + return true; + } + + return (this._coverage[level][x] === undefined || + this._coverage[level][x][y] === undefined || + this._coverage[level][x][y] === true); + }, + + /** + * Returns true if the given tile is completely covered by higher-level + * tiles of higher resolution representing the same content. If neither x + * nor y is given, returns true if the entire visible level is covered. + */ + _isCovered: function(level, x, y) { + if (x === undefined || y === undefined) { + return this._providesCoverage(level + 1); + } else { + return (this._providesCoverage(level + 1, 2 * x, 2 * y) && + this._providesCoverage(level + 1, 2 * x, 2 * y + 1) && + this._providesCoverage(level + 1, 2 * x + 1, 2 * y) && + this._providesCoverage(level + 1, 2 * x + 1, 2 * y + 1)); + } + }, + + /** + * Sets whether the given tile provides coverage or not. + */ + _setCoverage: function(level, x, y, covers) { + if (!this._coverage[level]) { + Seadragon.Debug.error("Setting coverage for a tile before its " + + "level's coverage has been reset: " + level); + return; + } + + if (!this._coverage[level][x]) { + this._coverage[level][x] = {}; + } + + this._coverage[level][x][y] = covers; + }, + + /** + * Resets coverage information for the given level. This should be called + * after every draw routine. Note that at the beginning of the next draw + * routine, coverage for every visible tile should be explicitly set. + */ + _resetCoverage: function(level) { + this._coverage[level] = {}; + }, + + + _compareTiles: function(prevBest, tile) { + if (!prevBest) { + return tile; + } + + if (tile.visibility > prevBest.visibility) { + return tile; + } else if (tile.visibility == prevBest.visibility) { + if (tile.distance < prevBest.distance) { + return tile; + } + } + + return prevBest; + }, + + + _getOverlayIndex: function(elmt) { + for (var i = this._overlays.length - 1; i >= 0; i--) { + if (this._overlays[i].elmt == elmt) { + return i; + } + } + + return -1; + }, + + + _updateActual: function() { + this._updateAgain = false; + + var _canvas = this._canvas; + var _context = this._context; + var _container = this._container; + var _useCanvas = useCanvas; + var _lastDrawn = this._lastDrawn; + + while (_lastDrawn.length > 0) { + var tile = _lastDrawn.pop(); + tile.beingDrawn = false; + } + + var viewportSize = this._viewport.getContainerSize(); + var viewportWidth = viewportSize.x; + var viewportHeight = viewportSize.y; + + _canvas.innerHTML = ""; + if (_useCanvas) { + _canvas.width = viewportWidth; + _canvas.height = viewportHeight; + _context.clearRect(0, 0, viewportWidth, viewportHeight); + } + + var viewportBounds = this._viewport.getBounds(true); + var viewportTL = viewportBounds.getTopLeft(); + var viewportBR = viewportBounds.getBottomRight(); + if (!this.config.wrapHorizontal && + (viewportBR.x < 0 || viewportTL.x > 1)) { + return; + } else if (!this.config.wrapVertical && + (viewportBR.y < 0 || viewportTL.y > this._normHeight)) { + return; + } + + + + + var _abs = Math.abs; + var _ceil = Math.ceil; + var _floor = Math.floor; + var _log = Math.log; + var _max = Math.max; + var _min = Math.min; + var alwaysBlend = this.config.alwaysBlend; + var blendTimeMillis = 1000 * this.config.blendTime; + var immediateRender = this.config.immediateRender; + var wrapHorizontal = this.config.wrapHorizontal; + var wrapVertical = this.config.wrapVertical; + + if (!wrapHorizontal) { + viewportTL.x = _max(viewportTL.x, 0); + viewportBR.x = _min(viewportBR.x, 1); + } + if (!wrapVertical) { + viewportTL.y = _max(viewportTL.y, 0); + viewportBR.y = _min(viewportBR.y, this._normHeight); + } + + var best = null; + var haveDrawn = false; + var currentTime = new Date().getTime(); + + var viewportCenter = this._viewport.pixelFromPoint(this._viewport.getCenter()); + var zeroRatioT = this._viewport.deltaPixelsFromPoints(this._source.getPixelRatio(0), false).x; + var optimalPixelRatio = immediateRender ? 1 : zeroRatioT; + + var lowestLevel = _max(this._minLevel, _floor(_log(this.config.minZoomImageRatio) / _log(2))); + var zeroRatioC = this._viewport.deltaPixelsFromPoints(this._source.getPixelRatio(0), true).x; + var highestLevel = _min(this._maxLevel, + _floor(_log(zeroRatioC / MIN_PIXEL_RATIO) / _log(2))); + + lowestLevel = _min(lowestLevel, highestLevel); + + for (var level = highestLevel; level >= lowestLevel; level--) { + var drawLevel = false; + var renderPixelRatioC = this._viewport.deltaPixelsFromPoints( + this._source.getPixelRatio(level), true).x; // note the .x! + + if ((!haveDrawn && renderPixelRatioC >= MIN_PIXEL_RATIO) || + level == lowestLevel) { + drawLevel = true; + haveDrawn = true; + } else if (!haveDrawn) { + continue; + } + + this._resetCoverage(level); + + var levelOpacity = _min(1, (renderPixelRatioC - 0.5) / 0.5); + var renderPixelRatioT = this._viewport.deltaPixelsFromPoints( + this._source.getPixelRatio(level), false).x; + var levelVisibility = optimalPixelRatio / + _abs(optimalPixelRatio - renderPixelRatioT); + + var tileTL = this._source.getTileAtPoint(level, viewportTL); + var tileBR = this._source.getTileAtPoint(level, viewportBR); + var numTiles = this._getNumTiles(level); + var numTilesX = numTiles.x; + var numTilesY = numTiles.y; + if (!wrapHorizontal) { + tileBR.x = _min(tileBR.x, numTilesX - 1); + } + if (!wrapVertical) { + tileBR.y = _min(tileBR.y, numTilesY - 1); + } + + for (var x = tileTL.x; x <= tileBR.x; x++) { + for (var y = tileTL.y; y <= tileBR.y; y++) { + var tile = this._getTile(level, x, y, currentTime, numTilesX, numTilesY); + var drawTile = drawLevel; + + this._setCoverage(level, x, y, false); + + if (!tile.exists) { + continue; + } + + if (haveDrawn && !drawTile) { + if (this._isCovered(level, x, y)) { + this._setCoverage(level, x, y, true); + } else { + drawTile = true; + } + } + + if (!drawTile) { + continue; + } + + var boundsTL = tile.bounds.getTopLeft(); + var boundsSize = tile.bounds.getSize(); + var positionC = this._viewport.pixelFromPoint(boundsTL, true); + var sizeC = this._viewport.deltaPixelsFromPoints(boundsSize, true); + + if (!this._tileOverlap) { + sizeC = sizeC.plus(new Seadragon.Point(1, 1)); + } + + var positionT = this._viewport.pixelFromPoint(boundsTL, false); + var sizeT = this._viewport.deltaPixelsFromPoints(boundsSize, false); + var tileCenter = positionT.plus(sizeT.divide(2)); + var tileDistance = viewportCenter.distanceTo(tileCenter); + + tile.position = positionC; + tile.size = sizeC; + tile.distance = tileDistance; + tile.visibility = levelVisibility; + + if (tile.loaded) { + if (!tile.blendStart) { + tile.blendStart = currentTime; + } + + var deltaTime = currentTime - tile.blendStart; + var opacity = _min(1, deltaTime / blendTimeMillis); + + if (alwaysBlend) { + opacity *= levelOpacity; + } + + tile.opacity = opacity; + + _lastDrawn.push(tile); + + if (opacity == 1) { + this._setCoverage(level, x, y, true); + } else if (deltaTime < blendTimeMillis) { + updateAgain = true; + } + } else if (tile.Loading) { + } else { + best = this._compareTiles(best, tile); + } + } + } + + if (this._providesCoverage(level)) { + break; + } + } + + for (var i = _lastDrawn.length - 1; i >= 0; i--) { + var tile = _lastDrawn[i]; + + if (_useCanvas) { + tile.drawCanvas(_context); + } else { + tile.drawHTML(_canvas); + } + + tile.beingDrawn = true; + } + + var numOverlays = this._overlays.length; + for (var i = 0; i < numOverlays; i++) { + var overlay = this._overlays[i]; + var bounds = overlay.bounds; + + overlay.position = this._viewport.pixelFromPoint(bounds.getTopLeft(), true); + overlay.size = this._viewport.deltaPixelsFromPoints(bounds.getSize(), true); + overlay.drawHTML(_container); + } + + if (best) { + this._loadTile(best, currentTime); + this._updateAgain = true; // because we haven't finished drawing, so + } + }, + + + addOverlay: function(elmt, loc, placement) { + var elmt = Seadragon.Utils.getElement(elmt); + + if (this._getOverlayIndex(elmt) >= 0) { + return; // they're trying to add a duplicate overlay + } + + this._overlays.push(new Seadragon.Overlay(elmt, loc, placement)); + this._updateAgain = true; + }, + + updateOverlay: function(elmt, loc, placement) { + var elmt = Seadragon.Utils.getElement(elmt); + var i = this._getOverlayIndex(elmt); + + if (i >= 0) { + this._overlays[i].update(loc, placement); + this._updateAgain = true; + } + }, + + removeOverlay: function(elmt) { + var elmt = Seadragon.Utils.getElement(elmt); + var i = this._getOverlayIndex(elmt); + + if (i >= 0) { + this._overlays[i].destroy(); + this._overlays.splice(i, 1); + this._updateAgain = true; + } + }, + + clearOverlays: function() { + while (this._overlays.length > 0) { + this._overlays.pop().destroy(); + this._updateAgain = true; + } + }, + + + needsUpdate: function() { + return this._updateAgain; + }, + + numTilesLoaded: function() { + return this._tilesLoaded.length; + }, + + reset: function() { + this._clearTiles(); + this._lastResetTime = new Date().getTime(); + this._updateAgain = true; + }, + + update: function() { + this._profiler.beginUpdate(); + this._midUpdate = true; + this._updateActual(); + this._midUpdate = false; + this._profiler.endUpdate(); + }, + + idle: function() { + } +} + +Seadragon.Viewport = function(containerSize, contentSize, config) { + this.zoomPoint = null; + this.config = config; + this._containerSize = containerSize; + this._contentSize = contentSize; + this._contentAspect = contentSize.x / contentSize.y; + this._contentHeight = contentSize.y / contentSize.x; + this._centerSpringX = new Seadragon.Spring(0, this.config); + this._centerSpringY = new Seadragon.Spring(0, this.config); + this._zoomSpring = new Seadragon.Spring(1, this.config); + this._homeBounds = new Seadragon.Rect(0, 0, 1, this._contentHeight); + this.goHome(true); + this.update(); +} +Seadragon.Viewport.prototype = { + _getHomeZoom: function() { + var aspectFactor = this._contentAspect / this.getAspectRatio(); + return (aspectFactor >= 1) ? 1 : aspectFactor; + }, + + _getMinZoom: function() { + var homeZoom = this._getHomeZoom(); + var zoom = this.config.minZoomImageRatio * homeZoom; + + return Math.min(zoom, homeZoom); + }, + + _getMaxZoom: function() { + var zoom = this._contentSize.x * this.config.maxZoomPixelRatio / this._containerSize.x; + return Math.max(zoom, this._getHomeZoom()); + }, + getAspectRatio: function() { + return this._containerSize.x / this._containerSize.y; + }, + getContainerSize: function() { + return new Seadragon.Point(this._containerSize.x, this._containerSize.y); + }, + + getBounds: function(current) { + var center = this.getCenter(current); + var width = 1.0 / this.getZoom(current); + var height = width / this.getAspectRatio(); + + return new Seadragon.Rect(center.x - width / 2.0, center.y - height / 2.0, + width, height); + }, + + getCenter: function(current) { + var centerCurrent = new Seadragon.Point(this._centerSpringX.getCurrent(), + this._centerSpringY.getCurrent()); + var centerTarget = new Seadragon.Point(this._centerSpringX.getTarget(), + this._centerSpringY.getTarget()); + + if (current) { + return centerCurrent; + } else if (!this.zoomPoint) { + return centerTarget; + } + + var oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true); + + var zoom = this.getZoom(); + var width = 1.0 / zoom; + var height = width / this.getAspectRatio(); + var bounds = new Seadragon.Rect(centerCurrent.x - width / 2.0, + centerCurrent.y - height / 2.0, width, height); + + var newZoomPixel = this.zoomPoint.minus(bounds.getTopLeft()).times(this._containerSize.x / bounds.width); + var deltaZoomPixels = newZoomPixel.minus(oldZoomPixel); + var deltaZoomPoints = deltaZoomPixels.divide(this._containerSize.x * zoom); + + return centerTarget.plus(deltaZoomPoints); + }, + + getZoom: function(current) { + if (current) { + return this._zoomSpring.getCurrent(); + } else { + return this._zoomSpring.getTarget(); + } + }, + + + applyConstraints: function(immediately) { + var actualZoom = this.getZoom(); + var constrainedZoom = Math.max(Math.min(actualZoom, this._getMaxZoom()), this._getMinZoom()); + if (actualZoom != constrainedZoom) { + this.zoomTo(constrainedZoom, this.zoomPoint, immediately); + } + + var bounds = this.getBounds(); + var visibilityRatio = this.config.visibilityRatio; + + var horThres = visibilityRatio * bounds.width; + var verThres = visibilityRatio * bounds.height; + + var left = bounds.x + bounds.width; + var right = 1 - bounds.x; + var top = bounds.y + bounds.height; + var bottom = this._contentHeight - bounds.y; + + var dx = 0; + if (this.config.wrapHorizontal) { + } else if (left < horThres) { + dx = horThres - left; + } else if (right < horThres) { + dx = right - horThres; + } + + var dy = 0; + if (this.config.wrapVertical) { + } else if (top < verThres) { + dy = verThres - top; + } else if (bottom < verThres) { + dy = bottom - verThres; + } + + if (dx || dy) { + bounds.x += dx; + bounds.y += dy; + this.fitBounds(bounds, immediately); + } + }, + + ensureVisible: function(immediately) { + this.applyConstraints(immediately); + }, + + fitBounds: function(bounds, immediately) { + var aspect = this.getAspectRatio(); + var center = bounds.getCenter(); + + var newBounds = new Seadragon.Rect(bounds.x, bounds.y, bounds.width, bounds.height); + if (newBounds.getAspectRatio() >= aspect) { + newBounds.height = bounds.width / aspect; + newBounds.y = center.y - newBounds.height / 2; + } else { + newBounds.width = bounds.height * aspect; + newBounds.x = center.x - newBounds.width / 2; + } + + this.panTo(this.getCenter(true), true); + this.zoomTo(this.getZoom(true), null, true); + + var oldBounds = this.getBounds(); + var oldZoom = this.getZoom(); + + var newZoom = 1.0 / newBounds.width; + if (newZoom == oldZoom || newBounds.width == oldBounds.width) { + this.panTo(center, immediately); + return; + } + + var refPoint = oldBounds.getTopLeft().times(this._containerSize.x / oldBounds.width).minus( + newBounds.getTopLeft().times(this._containerSize.x / newBounds.width)).divide( + this._containerSize.x / oldBounds.width - this._containerSize.x / newBounds.width); + + + this.zoomTo(newZoom, refPoint, immediately); + }, + + goHome: function(immediately) { + var center = this.getCenter(); + + if (this.config.wrapHorizontal) { + center.x = (1 + (center.x % 1)) % 1; + this._centerSpringX.resetTo(center.x); + this._centerSpringX.update(); + } + + if (this.config.wrapVertical) { + center.y = (this._contentHeight + (center.y % this._contentHeight)) % this._contentHeight; + this._centerSpringY.resetTo(center.y); + this._centerSpringY.update(); + } + + this.fitBounds(this._homeBounds, immediately); + }, + + panBy: function(delta, immediately) { + var center = new Seadragon.Point(this._centerSpringX.getTarget(), + this._centerSpringY.getTarget()); + this.panTo(center.plus(delta), immediately); + }, + + panTo: function(center, immediately) { + if (immediately) { + this._centerSpringX.resetTo(center.x); + this._centerSpringY.resetTo(center.y); + } else { + this._centerSpringX.springTo(center.x); + this._centerSpringY.springTo(center.y); + } + }, + + zoomBy: function(factor, refPoint, immediately) { + this.zoomTo(this._zoomSpring.getTarget() * factor, refPoint, immediately); + }, + + zoomTo: function(zoom, refPoint, immediately) { + + if (immediately) { + this._zoomSpring.resetTo(zoom); + } else { + this._zoomSpring.springTo(zoom); + } + + this.zoomPoint = refPoint instanceof Seadragon.Point ? refPoint : null; + }, + + resize: function(newContainerSize, maintain) { + var oldBounds = this.getBounds(); + var newBounds = oldBounds; + var widthDeltaFactor = newContainerSize.x / this._containerSize.x; + + this._containerSize = new Seadragon.Point(newContainerSize.x, newContainerSize.y); + + if (maintain) { + newBounds.width = oldBounds.width * widthDeltaFactor; + newBounds.height = newBounds.width / this.getAspectRatio(); + } + + this.fitBounds(newBounds, true); + }, + + update: function() { + var oldCenterX = this._centerSpringX.getCurrent(); + var oldCenterY = this._centerSpringY.getCurrent(); + var oldZoom = this._zoomSpring.getCurrent(); + + if (this.zoomPoint) { + var oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true); + } + + this._zoomSpring.update(); + + if (this.zoomPoint && this._zoomSpring.getCurrent() != oldZoom) { + var newZoomPixel = this.pixelFromPoint(this.zoomPoint, true); + var deltaZoomPixels = newZoomPixel.minus(oldZoomPixel); + var deltaZoomPoints = this.deltaPointsFromPixels(deltaZoomPixels, true); + + this._centerSpringX.shiftBy(deltaZoomPoints.x); + this._centerSpringY.shiftBy(deltaZoomPoints.y); + } else { + this.zoomPoint = null; + } + + this._centerSpringX.update(); + this._centerSpringY.update(); + + return this._centerSpringX.getCurrent() != oldCenterX || + this._centerSpringY.getCurrent() != oldCenterY || + this._zoomSpring.getCurrent() != oldZoom; + }, + + + deltaPixelsFromPoints: function(deltaPoints, current) { + return deltaPoints.times(this._containerSize.x * this.getZoom(current)); + }, + + deltaPointsFromPixels: function(deltaPixels, current) { + return deltaPixels.divide(this._containerSize.x * this.getZoom(current)); + }, + + pixelFromPoint: function(point, current) { + var bounds = this.getBounds(current); + return point.minus(bounds.getTopLeft()).times(this._containerSize.x / bounds.width); + }, + + pointFromPixel: function(pixel, current) { + var bounds = this.getBounds(current); + return pixel.divide(this._containerSize.x / bounds.width).plus(bounds.getTopLeft()); + } +} + +Seadragon.Debug = {} +Seadragon.Debug.fail = function(){}; +Seadragon.Debug.log = function(){}; +Seadragon.Debug.error = function(){}; \ No newline at end of file diff --git a/src/static/OpenSeadragon/OpenSeadragon.js b/src/static/OpenSeadragon/OpenSeadragon.js new file mode 100644 index 0000000..cbb6735 --- /dev/null +++ b/src/static/OpenSeadragon/OpenSeadragon.js @@ -0,0 +1 @@ +function Observer(){}if(!window.SeadragonConfig){window.SeadragonConfig={};SeadragonConfig.imgPath=""}Array.prototype.add=function(a,b){a[a.length]=b};Array.prototype.clear=function(a){a.length=0};Array.prototype.clone=function(a){return a.length===1?[a[0]]:Array.apply(null,a)};SArray=Array();if(!window.Function){window.Function={}}Function.prototype.createDelegate=function(a,b){return function(){if(arguments===undefined)arguments=[];return b.apply(a,arguments)}};String.format=function(a,b){return String._toFormattedString(false,arguments)};String._toFormattedString=function(a,b){var c="";var d=b[0];for(var e=0;;){var f=d.indexOf("{",e);var g=d.indexOf("}",e);if(f<0&&g<0){c+=d.slice(e);break}if(g>0&&(g<f||f<0)){if(d.charAt(g+1)!=="}"){throw Error.argument("format",Sys.Res.stringFormatBraceMismatch)}c+=d.slice(e,g+1);e=g+2;continue}c+=d.slice(e,f);e=f+1;if(d.charAt(e)==="{"){c+="{";e++;continue}if(g<0)throw Error.argument("format",Sys.Res.stringFormatBraceMismatch);var h=d.substring(e,g);var i=h.indexOf(":");var j=parseInt(i<0?h:h.substring(0,i),10)+1;if(isNaN(j))throw Error.argument("format",Sys.Res.stringFormatInvalid);var k=i<0?"":h.substring(i+1);var l=b[j];if(typeof l==="undefined"||l===null){l=""}if(l.toFormattedString){c+=l.toFormattedString(k)}else if(a&&l.localeFormat){c+=l.localeFormat(k)}else if(l.format){c+=l.format(k)}else c+=l.toString();e=g+1}return c};Observer.prototype={_getContext:function(a,b){var c=a._observerContext;if(c)return c();if(b){return(a._observerContext=this._createContext())()}return null},_createContext:function(){var a={events:new EventHandlerList};return function(){return a}}};var EventHandlerList=function a(){this._list={}};EventHandlerList.prototype={_addHandler:function(a,b){SArray.add(this._getEvent(a,true),b)},addHandler:function(a,b){this._addHandler(a,b)},_removeHandler:function(a,b){var c=this._getEvent(a);if(!c)return;SArray.remove(c,b)},_removeHandlers:function(a){if(!a){this._list={}}else{var b=this._getEvent(a);if(!b)return;b.length=0}},removeHandler:function(a,b){this._removeHandler(a,b)},getHandler:function(a){var b=this._getEvent(a);if(!b||!b.length)return null;b=SArray.clone(b);return function(a,c){for(var d=0,e=b.length;d<e;d++){b[d](a,c)}}},_getEvent:function(a,b){var c=this._list[a];if(!c){if(!b)return null;this._list[a]=c=[]}return c}};var Seadragon=new function(){};Seadragon.Utils=function(){function i(a,b){if(b&&a!=document.body){return document.body}else{return a.offsetParent}}var a={UNKNOWN:0,IE:1,FIREFOX:2,SAFARI:3,CHROME:4,OPERA:5};Seadragon.Browser=a;var b=this;var c=["Msxml2.XMLHTTP","Msxml3.XMLHTTP","Microsoft.XMLHTTP"];var d={bmp:false,jpeg:true,jpg:true,png:true,tif:false,wdp:false};var e=a.UNKNOWN;var f=0;var g=false;var h={};(function(){var b=navigator.appName;var c=navigator.appVersion;var d=navigator.userAgent;if(b=="Microsoft Internet Explorer"&&!!window.attachEvent&&!!window.ActiveXObject){var i=d.indexOf("MSIE");e=a.IE;f=parseFloat(d.substring(i+5,d.indexOf(";",i)))}else if(b=="Netscape"&&!!window.addEventListener){var j=d.indexOf("Firefox");var k=d.indexOf("Safari");var l=d.indexOf("Chrome");if(j>=0){e=a.FIREFOX;f=parseFloat(d.substring(j+8))}else if(k>=0){var m=d.substring(0,k).lastIndexOf("/");e=l>=0?a.CHROME:a.SAFARI;f=parseFloat(d.substring(m+1,k))}}else if(b=="Opera"&&!!window.opera&&!!window.attachEvent){e=a.OPERA;f=parseFloat(c)}var n=window.location.search.substring(1);var o=n.split("&");for(var p=0;p<o.length;p++){var q=o[p];var r=q.indexOf("=");if(r>0){h[q.substring(0,r)]=decodeURIComponent(q.substring(r+1))}}g=e==a.IE||e==a.CHROME&&f<2})();this.getBrowser=function(){return e};this.getBrowserVersion=function(){return f};this.getElement=function(a){if(typeof a=="string"){a=document.getElementById(a)}return a};this.getElementPosition=function(a){var a=b.getElement(a);var c=new Seadragon.Point;var d=b.getElementStyle(a).position=="fixed";var e=i(a,d);while(e){c.x+=a.offsetLeft;c.y+=a.offsetTop;if(d){c=c.plus(b.getPageScroll())}a=e;d=b.getElementStyle(a).position=="fixed";e=i(a,d)}return c};this.getElementSize=function(a){var a=b.getElement(a);return new Seadragon.Point(a.clientWidth,a.clientHeight)};this.getElementStyle=function(a){var a=b.getElement(a);if(a.currentStyle){return a.currentStyle}else if(window.getComputedStyle){return window.getComputedStyle(a,"")}else{Seadragon.Debug.fail("Unknown element style, no known technique.")}};this.getEvent=function(a){return a?a:window.event};this.getMousePosition=function(a){var a=b.getEvent(a);var c=new Seadragon.Point;if(typeof a.pageX=="number"){c.x=a.pageX;c.y=a.pageY}else if(typeof a.clientX=="number"){c.x=a.clientX+document.body.scrollLeft+document.documentElement.scrollLeft;c.y=a.clientY+document.body.scrollTop+document.documentElement.scrollTop}else{Seadragon.Debug.fail("Unknown event mouse position, no known technique.")}return c};this.getPageScroll=function(){var a=new Seadragon.Point;var b=document.documentElement||{};var c=document.body||{};if(typeof window.pageXOffset=="number"){a.x=window.pageXOffset;a.y=window.pageYOffset}else if(c.scrollLeft||c.scrollTop){a.x=c.scrollLeft;a.y=c.scrollTop}else if(b.scrollLeft||b.scrollTop){a.x=b.scrollLeft;a.y=b.scrollTop}return a};this.getWindowSize=function(){var a=new Seadragon.Point;var b=document.documentElement||{};var c=document.body||{};if(typeof window.innerWidth=="number"){a.x=window.innerWidth;a.y=window.innerHeight}else if(b.clientWidth||b.clientHeight){a.x=b.clientWidth;a.y=b.clientHeight}else if(c.clientWidth||c.clientHeight){a.x=c.clientWidth;a.y=c.clientHeight}else{Seadragon.Debug.fail("Unknown window size, no known technique.")}return a};this.imageFormatSupported=function(a){var a=a?a:"";return!!d[a.toLowerCase()]};this.makeCenteredNode=function(a){var a=Seadragon.Utils.getElement(a);var c=b.makeNeutralElement("div");var d=[];d.push('<div style="display:table; height:100%; width:100%;');d.push("border:none; margin:0px; padding:0px;");d.push('#position:relative; overflow:hidden; text-align:left;">');d.push('<div style="#position:absolute; #top:50%; width:100%; ');d.push("border:none; margin:0px; padding:0px;");d.push('display:table-cell; vertical-align:middle;">');d.push('<div style="#position:relative; #top:-50%; width:100%; ');d.push("border:none; margin:0px; padding:0px;");d.push('text-align:center;"></div></div></div>');c.innerHTML=d.join("");c=c.firstChild;var e=c;var f=c.getElementsByTagName("div");while(f.length>0){e=f[0];f=e.getElementsByTagName("div")}e.appendChild(a);return c};this.makeNeutralElement=function(a){var b=document.createElement(a);var c=b.style;c.background="transparent none";c.border="none";c.margin="0px";c.padding="0px";c.position="static";return b};this.makeTransparentImage=function(c){var d=b.makeNeutralElement("img");var g=null;if(e==a.IE&&f<7){g=b.makeNeutralElement("span");g.style.display="inline-block";d.onload=function(){g.style.width=g.style.width||d.width+"px";g.style.height=g.style.height||d.height+"px";d.onload=null;d=null};d.src=c;g.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+c+"', sizingMethod='scale')"}else{g=d;g.src=c}return g};this.setElementOpacity=function(a,c,d){var a=b.getElement(a);if(d&&g){c=Math.round(c)}if(c<1){a.style.opacity=c}else{a.style.opacity=""}if(c==1){var e=a.style.filter||"";a.style.filter=e.replace(/alpha\(.*?\)/g,"");return}var f=Math.round(100*c);var h=" alpha(opacity="+f+") ";try{if(a.filters&&a.filters.alpha){a.filters.alpha.opacity=f}else{a.style.filter+=h}}catch(i){a.style.filter+=h}};this.addEvent=function(a,c,d,e){var a=b.getElement(a);if(a.addEventListener){a.addEventListener(c,d,e)}else if(a.attachEvent){a.attachEvent("on"+c,d);if(e&&a.setCapture){a.setCapture()}}else{Seadragon.Debug.fail("Unable to attach event handler, no known technique.")}};this.removeEvent=function(a,c,d,e){var a=b.getElement(a);if(a.removeEventListener){a.removeEventListener(c,d,e)}else if(a.detachEvent){a.detachEvent("on"+c,d);if(e&&a.releaseCapture){a.releaseCapture()}}else{Seadragon.Debug.fail("Unable to detach event handler, no known technique.")}};this.cancelEvent=function(a){var a=b.getEvent(a);if(a.preventDefault){a.preventDefault()}a.cancel=true;a.returnValue=false};this.stopEvent=function(a){var a=b.getEvent(a);if(a.stopPropagation){a.stopPropagation()}a.cancelBubble=true};this.createCallback=function(a,b){var c=[];for(var d=2;d<arguments.length;d++){c.push(arguments[d])}return function(){var d=c.concat([]);for(var e=0;e<arguments.length;e++){d.push(arguments[e])}return b.apply(a,d)}};this.getUrlParameter=function(a){var b=h[a];return b?b:null};this.makeAjaxRequest=function(a,b){var d=typeof b=="function";var e=null;if(d){var f=b;var b=function(){window.setTimeout(Seadragon.Utils.createCallback(null,f,e),1)}}if(window.ActiveXObject){for(var g=0;g<c.length;g++){try{e=new ActiveXObject(c[g]);break}catch(h){continue}}}else if(window.XMLHttpRequest){e=new XMLHttpRequest}if(!e){Seadragon.Debug.fail("Browser doesn't support XMLHttpRequest.")}if(d){e.onreadystatechange=function(){if(e.readyState==4){e.onreadystatechange=new function(){};b()}}}try{e.open("GET",a,d);e.send(null)}catch(h){Seadragon.Debug.log(h.name+" while making AJAX request: "+h.message);e.onreadystatechange=null;e=null;if(d){b()}}return d?null:e};this.parseXml=function(a){var b=null;if(window.ActiveXObject){try{b=new ActiveXObject("Microsoft.XMLDOM");b.async=false;b.loadXML(a)}catch(c){Seadragon.Debug.log(c.name+" while parsing XML (ActiveX): "+c.message)}}else if(window.DOMParser){try{var d=new DOMParser;b=d.parseFromString(a,"text/xml")}catch(c){Seadragon.Debug.log(c.name+" while parsing XML (DOMParser): "+c.message)}}else{Seadragon.Debug.fail("Browser doesn't support XML DOM.")}return b}};Seadragon.Utils=new Seadragon.Utils;(function(){function j(){b=false}function i(){b=true}function h(a,b){var c=document.body;while(b&&a!=b&&c!=b){try{b=b.parentNode}catch(d){return false}}return a==b}function g(a,b){var c=Seadragon.Utils.getMousePosition(a);var d=Seadragon.Utils.getElementPosition(b);return c.minus(d)}function f(a){return Seadragon.Utils.getMousePosition(a)}if(Seadragon.MouseTracker){return}var a=Seadragon.Utils.getBrowser()==Seadragon.Browser.IE;var b=false;var c=false;var d={};var e=[];(function(){if(a){Seadragon.Utils.addEvent(document,"mousedown",i,false);Seadragon.Utils.addEvent(document,"mouseup",j,false)}else{Seadragon.Utils.addEvent(window,"mousedown",i,true);Seadragon.Utils.addEvent(window,"mouseup",j,true)}})();Seadragon.MouseTracker=function(i,j,k){function L(a){for(var b=0;b<e.length;b++){e[b].onMouseMove(a)}Seadragon.Utils.stopEvent(a)}function K(a){var a=Seadragon.Utils.getEvent(a);var b=f(a);var c=b.minus(s);s=b;if(typeof l.dragHandler=="function"){try{l.dragHandler(l,g(a,i),c,a.shiftKey)}catch(d){Seadragon.Debug.error(d.name+" while executing drag handler: "+d.message,d)}Seadragon.Utils.cancelEvent(a)}}function J(a){var a=Seadragon.Utils.getEvent(a);if(a.button==2){return}var b=(new Date).getTime()-t;var c=f(a);var d=u.distanceTo(c);var e=b<=j&&d<=k;if(typeof l.clickHandler=="function"){try{l.clickHandler(l,g(a,i),e,a.shiftKey)}catch(h){Seadragon.Debug.error(h.name+" while executing click handler: "+h.message,h)}}}function I(a){var b=0;if(!a){a=window.event}if(a.wheelDelta){b=a.wheelDelta;if(window.opera){b=-b}}else if(a.detail){b=-a.detail}b=b>0?1:-1;if(typeof l.scrollHandler=="function"){try{l.scrollHandler(l,g(a,i),b,a.shiftKey)}catch(c){Seadragon.Debug.error(c.name+" while executing scroll handler: "+c.message,c)}Seadragon.Utils.cancelEvent(a)}}function H(a){if(l.clickHandler){Seadragon.Utils.cancelEvent(a)}}function G(a){if(!r){E(a)}y()}function F(a){var a=Seadragon.Utils.getEvent(a);if(a.button==2){return}for(var b=0;b<e.length;b++){var d=e[b];if(!d.hasMouse()){d.onMouseUp(a)}}y();c=false;a.srcElement.fireEvent("on"+a.type,document.createEventObject(a));Seadragon.Utils.stopEvent(a)}function E(a){var a=Seadragon.Utils.getEvent(a);var b=q;var c=r;if(a.button==2){return}q=false;if(typeof l.releaseHandler=="function"){try{l.releaseHandler(l,g(a,i),b,c)}catch(d){Seadragon.Debug.error(d.name+" while executing release handler: "+d.message,d)}}if(b&&c){J(a)}}function D(b){var b=Seadragon.Utils.getEvent(b);if(b.button==2){return}q=true;s=f(b);u=s;t=(new Date).getTime();if(typeof l.pressHandler=="function"){try{l.pressHandler(l,g(b,i))}catch(d){Seadragon.Debug.error(d.name+" while executing press handler: "+d.message,d)}}if(l.pressHandler||l.dragHandler){Seadragon.Utils.cancelEvent(b)}if(!a||!c){x();c=true;e=[m]}else if(a){e.push(m)}}function C(c){var c=Seadragon.Utils.getEvent(c);if(a&&p&&!h(c.srcElement,i)){z("onMouseOut",c)}var d=c.target?c.target:c.srcElement;var e=c.relatedTarget?c.relatedTarget:c.toElement;if(!h(i,d)||h(i,e)){return}r=false;if(typeof l.exitHandler=="function"){try{l.exitHandler(l,g(c,i),q,b)}catch(f){Seadragon.Debug.error(f.name+" while executing exit handler: "+f.message,f)}}}function B(c){var c=Seadragon.Utils.getEvent(c);if(a&&p&&!h(c.srcElement,i)){z("onMouseOver",c)}var d=c.target?c.target:c.srcElement;var e=c.relatedTarget?c.relatedTarget:c.fromElement;if(!h(i,d)||h(i,e)){return}r=true;if(typeof l.enterHandler=="function"){try{l.enterHandler(l,g(c,i),q,b)}catch(f){Seadragon.Debug.error(f.name+" while executing enter handler: "+f.message,f)}}}function A(){return r}function z(a,b){var c=d;for(var e in c){if(c.hasOwnProperty(e)&&n!=e){c[e][a](b)}}}function y(){if(p){if(a){Seadragon.Utils.removeEvent(i,"mousemove",L,true);Seadragon.Utils.removeEvent(i,"mouseup",F,true);Seadragon.Utils.addEvent(i,"mouseup",E,false)}else{Seadragon.Utils.removeEvent(window,"mousemove",K,true);Seadragon.Utils.removeEvent(window,"mouseup",G,true)}p=false}}function x(){if(!p){if(a){Seadragon.Utils.removeEvent(i,"mouseup",E,false);Seadragon.Utils.addEvent(i,"mouseup",F,true);Seadragon.Utils.addEvent(i,"mousemove",L,true)}else{Seadragon.Utils.addEvent(window,"mouseup",G,true);Seadragon.Utils.addEvent(window,"mousemove",K,true)}p=true}}function w(){if(o){Seadragon.Utils.removeEvent(i,"mouseover",B,false);Seadragon.Utils.removeEvent(i,"mouseout",C,false);Seadragon.Utils.removeEvent(i,"mousedown",D,false);Seadragon.Utils.removeEvent(i,"mouseup",E,false);Seadragon.Utils.removeEvent(i,"click",H,false);Seadragon.Utils.removeEvent(i,"DOMMouseScroll",I,false);Seadragon.Utils.removeEvent(i,"mousewheel",I,false);y();o=false;delete d[n]}}function v(){if(!o){Seadragon.Utils.addEvent(i,"mouseover",B,false);Seadragon.Utils.addEvent(i,"mouseout",C,false);Seadragon.Utils.addEvent(i,"mousedown",D,false);Seadragon.Utils.addEvent(i,"mouseup",E,false);Seadragon.Utils.addEvent(i,"click",H,false);Seadragon.Utils.addEvent(i,"DOMMouseScroll",I,false);Seadragon.Utils.addEvent(i,"mousewheel",I,false);o=true;d[n]=m}}var l=this;var m=null;var n=Math.random();var i=Seadragon.Utils.getElement(i);var o=false;var p=false;var q=false;var r=false;var s=null;var t=null;var u=null;var j=j;var k=k;this.target=i;this.enterHandler=null;this.exitHandler=null;this.pressHandler=null;this.releaseHandler=null;this.scrollHandler=null;this.clickHandler=null;this.dragHandler=null;(function(){m={hasMouse:A,onMouseOver:B,onMouseOut:C,onMouseUp:E,onMouseMove:K}})();this.isTracking=function(){return o};this.setTracking=function(a){if(a){v()}else{w()}}}})();if(!window.SIGNAL)window.SIGNAL="----seadragon----";Seadragon.ControlAnchor=function(){throw Error.invalidOperation()};Seadragon.ControlAnchor={NONE:0,TOP_LEFT:1,TOP_RIGHT:2,BOTTOM_RIGHT:3,BOTTOM_LEFT:4};Seadragon.ControlAnchor=Seadragon.ControlAnchor;Seadragon.OverlayPlacement=function(){throw Error.invalidOperation()};Seadragon.OverlayPlacement={CENTER:0,TOP_LEFT:1,TOP:2,TOP_RIGHT:3,RIGHT:4,BOTTOM_RIGHT:5,BOTTOM:6,BOTTOM_LEFT:7,LEFT:8};Seadragon.OverlayPlacement=Seadragon.OverlayPlacement;Seadragon.NavControl=function(a){this._group=null;this._zooming=false;this._zoomFactor=null;this._lastZoomTime=null;this._viewer=a;this.config=this._viewer.config;this.elmt=null;this.initialize()};Seadragon.NavControl.prototype={initialize:function(){var a=Function.createDelegate(this,this._beginZoomingIn);var b=Function.createDelegate(this,this._endZooming);var c=Function.createDelegate(this,this._doSingleZoomIn);var d=Function.createDelegate(this,this._beginZoomingOut);var e=Function.createDelegate(this,this._doSingleZoomOut);var f=Function.createDelegate(this,this._onHome);var g=Function.createDelegate(this,this._onFullPage);var h=this._viewer.config.navImages;var i=new Seadragon.Button({config:this._viewer.config,tooltip:Seadragon.Strings.getString("Tooltips.ZoomIn"),srcRest:this._resolveUrl(h.zoomIn.REST),srcGroup:this._resolveUrl(h.zoomIn.GROUP),srcHover:this._resolveUrl(h.zoomIn.HOVER),srcDown:this._resolveUrl(h.zoomIn.DOWN)},{onPress:a,onRelease:b,onClick:c,onEnter:a,onExit:b});var j=new Seadragon.Button({config:this._viewer.config,tooltip:Seadragon.Strings.getString("Tooltips.ZoomOut"),srcRest:this._resolveUrl(h.zoomOut.REST),srcGroup:this._resolveUrl(h.zoomOut.GROUP),srcHover:this._resolveUrl(h.zoomOut.HOVER),srcDown:this._resolveUrl(h.zoomOut.DOWN)},{onPress:d,onRelease:b,onClick:e,onEnter:d,onExit:b});var k=new Seadragon.Button({config:this._viewer.config,tooltip:Seadragon.Strings.getString("Tooltips.Home"),srcRest:this._resolveUrl(h.home.REST),srcGroup:this._resolveUrl(h.home.GROUP),srcHover:this._resolveUrl(h.home.HOVER),srcDown:this._resolveUrl(h.home.DOWN)},{onRelease:f});var l=new Seadragon.Button({config:this._viewer.config,tooltip:Seadragon.Strings.getString("Tooltips.FullPage"),srcRest:this._resolveUrl(h.fullpage.REST),srcGroup:this._resolveUrl(h.fullpage.GROUP),srcHover:this._resolveUrl(h.fullpage.HOVER),srcDown:this._resolveUrl(h.fullpage.DOWN)},{onRelease:g});this._group=new Seadragon.ButtonGroup({config:this._viewer.config,buttons:[i,j,k,l]});this.elmt=this._group.get_element();this.elmt[SIGNAL]=true;this._viewer.add_open(Function.createDelegate(this,this._lightUp))},dispose:function(){},get_events:function(){return this._events},set_events:function(a){this._events=a},_resolveUrl:function(a){return String.format("{1}",this._viewer.get_prefixUrl(),a)},_beginZoomingIn:function(){this._lastZoomTime=(new Date).getTime();this._zoomFactor=this.config.zoomPerSecond;this._zooming=true;this._scheduleZoom()},_beginZoomingOut:function(){this._lastZoomTime=(new Date).getTime();this._zoomFactor=1/this.config.zoomPerSecond;this._zooming=true;this._scheduleZoom()},_endZooming:function(){this._zooming=false},_scheduleZoom:function(){window.setTimeout(Function.createDelegate(this,this._doZoom),10)},_doZoom:function(){if(this._zooming&&this._viewer.viewport){var a=(new Date).getTime();var b=a-this._lastZoomTime;var c=Math.pow(this._zoomFactor,b/1e3);this._viewer.viewport.zoomBy(c);this._viewer.viewport.applyConstraints();this._lastZoomTime=a;this._scheduleZoom()}},_doSingleZoomIn:function(){if(this._viewer.viewport){this._zooming=false;this._viewer.viewport.zoomBy(this.config.zoomPerClick/1);this._viewer.viewport.applyConstraints()}},_doSingleZoomOut:function(){if(this._viewer.viewport){this._zooming=false;this._viewer.viewport.zoomBy(1/this.config.zoomPerClick);this._viewer.viewport.applyConstraints()}},_lightUp:function(){this._group.emulateEnter();this._group.emulateExit()},_onHome:function(){if(this._viewer.viewport){this._viewer.viewport.goHome()}},_onFullPage:function(){this._viewer.setFullPage(!this._viewer.isFullPage());this._group.emulateExit();if(this._viewer.viewport){this._viewer.viewport.applyConstraints()}if(this._viewer.onFullPage){this._viewer.onFullPage.apply(this._viewer)}}};Seadragon.Control=function(a,b,c){this.elmt=a;this.anchor=b;this.container=c;this.wrapper=Seadragon.Utils.makeNeutralElement("span");this.wrapper.style.display="inline-block";this.wrapper.appendChild(this.elmt);if(this.anchor==Seadragon.ControlAnchor.NONE){this.wrapper.style.width=this.wrapper.style.height="100%"}if(this.anchor==Seadragon.ControlAnchor.TOP_RIGHT||this.anchor==Seadragon.ControlAnchor.BOTTOM_RIGHT){this.container.insertBefore(this.wrapper,this.container.firstChild)}else{this.container.appendChild(this.wrapper)}};Seadragon.Control.prototype={destroy:function(){this.wrapper.removeChild(this.elmt);this.container.removeChild(this.wrapper)},isVisible:function(){return this.wrapper.style.display!="none"},setVisible:function(a){this.wrapper.style.display=a?"inline-block":"none"},setOpacity:function(a){if(this.elmt[SIGNAL]&&Seadragon.Utils.getBrowser()==Seadragon.Browser.IE){Seadragon.Utils.setElementOpacity(this.elmt,a,true)}else{Seadragon.Utils.setElementOpacity(this.wrapper,a,true)}}};Seadragon.Viewer=function(a,b,c,d,e,f){this.config=new Seadragon.Config;this._prefixUrl=c?c:"";this._element=document.getElementById(a);this._controls=d?d:[];this._customControls=[];this._overlays=e?e:[];this._overlayControls=f?f:[];this._container=null;this._canvas=null;this._controlsTL=null;this._controlsTR=null;this._controlsBR=null;this._controlsBL=null;this._bodyWidth=null;this._bodyHeight=null;this._bodyOverflow=null;this._docOverflow=null;this._fsBoundsDelta=null;this._prevContainerSize=null;this._lastOpenStartTime=0;this._lastOpenEndTime=0;this._animating=false;this._forceRedraw=false;this._mouseInside=false;this._xmlPath=b?b:undefined;this.source=null;this.drawer=null;this.viewport=null;this.profiler=null;this.initialize()};Seadragon.Viewer.prototype={initialize:function(){this._observer=new Observer;this._container=Seadragon.Utils.makeNeutralElement("div");this._canvas=Seadragon.Utils.makeNeutralElement("div");this._controlsTL=Seadragon.Utils.makeNeutralElement("div");this._controlsTR=Seadragon.Utils.makeNeutralElement("div");this._controlsBR=Seadragon.Utils.makeNeutralElement("div");this._controlsBL=Seadragon.Utils.makeNeutralElement("div");var a=new Seadragon.MouseTracker(this._canvas,this.config.clickTimeThreshold,this.config.clickDistThreshold);var b=new Seadragon.MouseTracker(this._container,this.config.clickTimeThreshold,this.config.clickDistThreshold);this._bodyWidth=document.body.style.width;this._bodyHeight=document.body.style.height;this._bodyOverflow=document.body.style.overflow;this._docOverflow=document.documentElement.style.overflow;this._fsBoundsDelta=new Seadragon.Point(1,1);var c=this._canvas.style;var d=this._container.style;var e=this._controlsTL.style;var f=this._controlsTR.style;var g=this._controlsBR.style;var h=this._controlsBL.style;d.width="100%";d.height="100%";d.position="relative";d.left="0px";d.top="0px";d.textAlign="left";c.width="100%";c.height="100%";c.overflow="hidden";c.position="absolute";c.top="0px";c.left="0px";e.position=f.position=g.position=h.position="absolute";e.top=f.top="0px";e.left=h.left="0px";f.right=g.right="0px";h.bottom=g.bottom="0px";a.clickHandler=Function.createDelegate(this,this._onCanvasClick);a.dragHandler=Function.createDelegate(this,this._onCanvasDrag);a.releaseHandler=Function.createDelegate(this,this._onCanvasRelease);a.scrollHandler=Function.createDelegate(this,this._onCanvasScroll);a.setTracking(true);if(this.get_showNavigationControl()){navControl=(new Seadragon.NavControl(this)).elmt;navControl.style.marginRight="4px";navControl.style.marginBottom="4px";this.addControl(navControl,Seadragon.ControlAnchor.BOTTOM_RIGHT)}for(var i=0;i<this._customControls.length;i++){this.addControl(this._customControls[i].id,this._customControls[i].anchor)}b.enterHandler=Function.createDelegate(this,this._onContainerEnter);b.exitHandler=Function.createDelegate(this,this._onContainerExit);b.releaseHandler=Function.createDelegate(this,this._onContainerRelease);b.setTracking(true);window.setTimeout(Function.createDelegate(this,this._beginControlsAutoHide),1);this._container.appendChild(this._canvas);this._container.appendChild(this._controlsTL);this._container.appendChild(this._controlsTR);this._container.appendChild(this._controlsBR);this._container.appendChild(this._controlsBL);this.get_element().appendChild(this._container);if(this._xmlPath)this.openDzi(this._xmlPath)},get_events:function b(){return this._observer._getContext(this,true).events},_raiseEvent:function(a,b){var c=this.get_events().getHandler(a);if(c){if(!b){b=new Object}c(this,b)}},_beginControlsAutoHide:function(){if(!this.config.autoHideControls){return}this._controlsShouldFade=true;this._controlsFadeBeginTime=(new Date).getTime()+this._controlsFadeDelay;window.setTimeout(Function.createDelegate(this,this._scheduleControlsFade),this._controlsFadeDelay)},_scheduleControlsFade:function(){window.setTimeout(Function.createDelegate(this,this._updateControlsFade),20)},_updateControlsFade:function(){if(this._controlsShouldFade){var a=(new Date).getTime();var b=a-this._controlsFadeBeginTime;var c=1-b/this._controlsFadeLength;c=Math.min(1,c);c=Math.max(0,c);for(var d=this._controls.length-1;d>=0;d--){this._controls[d].setOpacity(c)}if(c>0){this._scheduleControlsFade()}}},_onCanvasClick:function(a,b,c,d){if(this.viewport&&c){var e=this.config.zoomPerClick;var f=d?1/e:e;this.viewport.zoomBy(f,this.viewport.pointFromPixel(b,true));this.viewport.applyConstraints()}},_onCanvasDrag:function(a,b,c,d){if(this.viewport){this.viewport.panBy(this.viewport.deltaPointsFromPixels(c.negate()))}},_onCanvasRelease:function(a,b,c,d){if(c&&this.viewport){this.viewport.applyConstraints()}},_onCanvasScroll:function(a,b,c,d){if(this.viewport){var e=Math.pow(this.config.zoomPerScroll,c);this.viewport.zoomBy(e,this.viewport.pointFromPixel(b,true));this.viewport.applyConstraints()}},_onContainerExit:function(a,b,c,d){if(!c){this._mouseInside=false;if(!this._animating){this._beginControlsAutoHide()}}},_onContainerRelease:function(a,b,c,d){if(!d){this._mouseInside=false;if(!this._animating){this._beginControlsAutoHide()}}},_getControlIndex:function(a){for(var b=this._controls.length-1;b>=0;b--){if(this._controls[b].elmt==a){return b}}return-1},_abortControlsAutoHide:function(){this._controlsShouldFade=false;for(var a=this._controls.length-1;a>=0;a--){this._controls[a].setOpacity(1)}},_onContainerEnter:function(a,b,c,d){this._mouseInside=true;this._abortControlsAutoHide()},_updateOnce:function(){if(!this.source){return}this.profiler.beginUpdate();var a=Seadragon.Utils.getElementSize(this._container);if(!a.equals(this._prevContainerSize)){this.viewport.resize(a,true);this._prevContainerSize=a;this._raiseEvent("resize",this)}var b=this.viewport.update();if(!this._animating&&b){this._raiseEvent("animationstart",self);this._abortControlsAutoHide()}if(b){this.drawer.update();this._raiseEvent("animation",self)}else if(this._forceRedraw||this.drawer.needsUpdate()){this.drawer.update();this._forceRedraw=false}else{this.drawer.idle()}if(this._animating&&!b){this._raiseEvent("animationfinish",this);if(!this._mouseInside){this._beginControlsAutoHide()}}this._animating=b;this.profiler.endUpdate()},_onClose:function(){this.source=null;this.viewport=null;this.drawer=null;this.profiler=null;this._canvas.innerHTML=""},_beforeOpen:function(){if(this.source){this._onClose()}this._lastOpenStartTime=(new Date).getTime();window.setTimeout(Function.createDelegate(this,function(){if(this._lastOpenStartTime>this._lastOpenEndTime){this._setMessage(Seadragon.Strings.getString("Messages.Loading"))}}),2e3);return this._lastOpenStartTime},_setMessage:function(a){var b=document.createTextNode(a);this._canvas.innerHTML="";this._canvas.appendChild(Seadragon.Utils.makeCenteredNode(b));var c=b.parentNode.style;c.color="white";c.fontFamily="verdana";c.fontSize="13px";c.fontSizeAdjust="none";c.fontStyle="normal";c.fontStretch="normal";c.fontVariant="normal";c.fontWeight="normal";c.lineHeight="1em";c.textAlign="center";c.textDecoration="none"},_onOpen:function(a,b,c){this._lastOpenEndTime=(new Date).getTime();if(a<this._lastOpenStartTime){Seadragon.Debug.log("Ignoring out-of-date open.");this._raiseEvent("ignore");return}else if(!b){this._setMessage(c);this._raiseEvent("error");return}this._canvas.innerHTML="";this._prevContainerSize=Seadragon.Utils.getElementSize(this._container);this.source=b;this.viewport=new Seadragon.Viewport(this._prevContainerSize,this.source.dimensions,this.config);this.drawer=new Seadragon.Drawer(this.source,this.viewport,this._canvas);this.profiler=new Seadragon.Profiler;this._animating=false;this._forceRedraw=true;this._scheduleUpdate(this._updateMulti);for(var d=0;d<this._overlayControls.length;d++){var e=this._overlayControls[d];if(e.point!=null){this.drawer.addOverlay(e.id,new Seadragon.Point(e.point.X,e.point.Y),Seadragon.OverlayPlacement.TOP_LEFT)}else{this.drawer.addOverlay(e.id,new Seadragon.Rect(e.rect.Point.X,e.rect.Point.Y,e.rect.Width,e.rect.Height),e.placement)}}this._raiseEvent("open")},_scheduleUpdate:function(a,b){if(this._animating){return window.setTimeout(Function.createDelegate(this,a),1)}var c=(new Date).getTime();var b=b?b:c;var d=b+1e3/60;var e=Math.max(1,d-c);return window.setTimeout(Function.createDelegate(this,a),e)},_updateMulti:function(){if(!this.source){return}var a=(new Date).getTime();this._updateOnce();this._scheduleUpdate(arguments.callee,a)},_updateOnce:function(){if(!this.source){return}this.profiler.beginUpdate();var a=Seadragon.Utils.getElementSize(this._container);if(!a.equals(this._prevContainerSize)){this.viewport.resize(a,true);this._prevContainerSize=a;this._raiseEvent("resize")}var b=this.viewport.update();if(!this._animating&&b){this._raiseEvent("animationstart");this._abortControlsAutoHide()}if(b){this.drawer.update();this._raiseEvent("animation")}else if(this._forceRedraw||this.drawer.needsUpdate()){this.drawer.update();this._forceRedraw=false}else{this.drawer.idle()}if(this._animating&&!b){this._raiseEvent("animationfinish");if(!this._mouseInside){this._beginControlsAutoHide()}}this._animating=b;this.profiler.endUpdate()},getNavControl:function(){return this._navControl},get_element:function(){return this._element},get_xmlPath:function(){return this._xmlPath},set_xmlPath:function(a){this._xmlPath=a},get_debugMode:function(){return this.config.debugMode},set_debugMode:function(a){this.config.debugMode=a},get_animationTime:function(){return this.config.animationTime},set_animationTime:function(a){this.config.animationTime=a},get_blendTime:function(){return this.config.blendTime},set_blendTime:function(a){this.config.blendTime=a},get_alwaysBlend:function(){return this.config.alwaysBlend},set_alwaysBlend:function(a){this.config.alwaysBlend=a},get_autoHideControls:function(){return this.config.autoHideControls},set_autoHideControls:function(a){this.config.autoHideControls=a},get_immediateRender:function(){return this.config.immediateRender},set_immediateRender:function(a){this.config.immediateRender=a},get_wrapHorizontal:function(){return this.config.wrapHorizontal},set_wrapHorizontal:function(a){this.config.wrapHorizontal=a},get_wrapVertical:function(){return this.config.wrapVertical},set_wrapVertical:function(a){this.config.wrapVertical=a},get_minZoomImageRatio:function(){return this.config.minZoomImageRatio},set_minZoomImageRatio:function(a){this.config.minZoomImageRatio=a},get_maxZoomPixelRatio:function(){return this.config.maxZoomPixelRatio},set_maxZoomPixelRatio:function(a){this.config.maxZoomPixelRatio=a},get_visibilityRatio:function(){return this.config.visibilityRatio},set_visibilityRatio:function(a){this.config.visibilityRatio=a},get_springStiffness:function(){return this.config.springStiffness},set_springStiffness:function(a){this.config.springStiffness=a},get_imageLoaderLimit:function(){return this.config.imageLoaderLimit},set_imageLoaderLimit:function(a){this.config.imageLoaderLimit=a},get_clickTimeThreshold:function(){return this.config.clickTimeThreshold},set_clickTimeThreshold:function(a){this.config.clickTimeThreshold=a},get_clickDistThreshold:function(){return this.config.clickDistThreshold},set_clickDistThreshold:function(a){this.config.clickDistThreshold=a},get_zoomPerClick:function(){return this.config.zoomPerClick},set_zoomPerClick:function(a){this.config.zoomPerClick=a},get_zoomPerSecond:function(){return this.config.zoomPerSecond},set_zoomPerSecond:function(a){this.config.zoomPerSecond=a},get_zoomPerScroll:function(){return this.config.zoomPerScroll},set_zoomPerScroll:function(a){this.config.zoomPerScroll=a},get_maxImageCacheCount:function(){return this.config.maxImageCacheCount},set_maxImageCacheCount:function(a){this.config.maxImageCacheCount=a},get_showNavigationControl:function(){return this.config.showNavigationControl},set_showNavigationControl:function(a){this.config.showNavigationControl=a},get_minPixelRatio:function(){return this.config.minPixelRatio},set_minPixelRatio:function(a){this.config.minPixelRatio=a},get_mouseNavEnabled:function(){return this.config.mouseNavEnabled},set_mouseNavEnabled:function(a){this.config.mouseNavEnabled=a},get_controls:function(){return this._customControls},set_controls:function(a){this._customControls=a},get_overlays:function(){return this._overlayControls},set_overlays:function(a){this._overlayControls=a},get_prefixUrl:function(){return this._prefixUrl},set_prefixUrl:function(a){this._prefixUrl=a},add_open:function(a){this.get_events().addHandler("open",a)},remove_open:function(a){this.get_events().removeHandler("open",a)},add_error:function(a){this.get_events().addHandler("error",a)},remove_error:function(a){this.get_events().removeHandler("error",a)},add_ignore:function(a){this.get_events().addHandler("ignore",a)},remove_ignore:function(a){this.get_events().removeHandler("ignore",a)},add_resize:function(a){this.get_events().addHandler("resize",a)},remove_resize:function(a){this.get_events().removeHandler("resize",a)},add_animationstart:function(a){this.get_events().addHandler("animationstart",a)},remove_animationstart:function(a){this.get_events().removeHandler("animationstart",a)},add_animation:function(a){this.get_events().addHandler("animation",a)},remove_animation:function(a){this.get_events().removeHandler("animation",a)},add_animationfinish:function(a){this.get_events().addHandler("animationfinish",a)},remove_animationfinish:function(a){this.get_events().removeHandler("animationfinish",a)},addControl:function(a,b){var a=Seadragon.Utils.getElement(a);if(this._getControlIndex(a)>=0){return}var c=null;switch(b){case Seadragon.ControlAnchor.TOP_RIGHT:c=this._controlsTR;a.style.position="relative";break;case Seadragon.ControlAnchor.BOTTOM_RIGHT:c=this._controlsBR;a.style.position="relative";break;case Seadragon.ControlAnchor.BOTTOM_LEFT:c=this._controlsBL;a.style.position="relative";break;case Seadragon.ControlAnchor.TOP_LEFT:c=this._controlsTL;a.style.position="relative";break;case Seadragon.ControlAnchor.NONE:default:c=this._container;a.style.position="absolute";break}this._controls.push(new Seadragon.Control(a,b,c));a.style.display="inline-block"},isOpen:function(){return!!this.source},openDzi:function(a,b){var c=this._beforeOpen();Seadragon.DziTileSourceHelper.createFromXml(a,b,Seadragon.Utils.createCallback(null,Function.createDelegate(this,this._onOpen),c))},openTileSource:function(a){var b=beforeOpen();window.setTimeout(Function.createDelegate(this,function(){onOpen(b,a)}),1)},close:function(){if(!this.source){return}this._onClose()},removeControl:function(a){var a=Seadragon.Utils.getElement(a);var b=this._getControlIndex(a);if(b>=0){this._controls[b].destroy();this._controls.splice(b,1)}},clearControls:function(){while(this._controls.length>0){this._controls.pop().destroy()}},isDashboardEnabled:function(){for(var a=this._controls.length-1;a>=0;a--){if(this._controls[a].isVisible()){return true}}return false},isFullPage:function(){return this._container.parentNode==document.body},isMouseNavEnabled:function(){return this._innerTracker.isTracking()},isVisible:function(){return this._container.style.visibility!="hidden"},setDashboardEnabled:function(a){for(var b=this._controls.length-1;b>=0;b--){this._controls[b].setVisible(a)}},setFullPage:function(a){if(a==this.isFullPage()){return}var b=document.body;var c=b.style;var d=document.documentElement.style;var e=this._container.style;var f=this._canvas.style;if(a){bodyOverflow=c.overflow;docOverflow=d.overflow;c.overflow="hidden";d.overflow="hidden";bodyWidth=c.width;bodyHeight=c.height;c.width="100%";c.height="100%";f.backgroundColor="black";f.color="white";e.position="fixed";e.zIndex="99999999";b.appendChild(this._container);this._prevContainerSize=Seadragon.Utils.getWindowSize();this._onContainerEnter()}else{c.overflow=bodyOverflow;d.overflow=docOverflow;c.width=bodyWidth;c.height=bodyHeight;f.backgroundColor="";f.color="";e.position="relative";e.zIndex="";this.get_element().appendChild(this._container);this._prevContainerSize=Seadragon.Utils.getElementSize(this.get_element());this._onContainerExit()}if(this.viewport){var g=this.viewport.getBounds();this.viewport.resize(this._prevContainerSize);var h=this.viewport.getBounds();if(a){this._fsBoundsDelta=new Seadragon.Point(h.width/g.width,h.height/g.height)}else{this.viewport.update();this.viewport.zoomBy(Math.max(this._fsBoundsDelta.x,this._fsBoundsDelta.y),null,true)}this._forceRedraw=true;this._raiseEvent("resize",this);this._updateOnce()}},setMouseNavEnabled:function(a){this._innerTracker.setTracking(a)},setVisible:function(a){this._container.style.visibility=a?"":"hidden"}};Seadragon.Strings={Errors:{Failure:SeadragonConfig.Failure?SeadragonConfig.Failure:"Sorry, but Seadragon Ajax can't run on your browser!\n"+"Please try using IE 7 or Firefox 3.\n",Dzc:SeadragonConfig.Dzc?SeadragonConfig.Dzc:"Sorry, we don't support Deep Zoom Collections!",Dzi:SeadragonConfig.Dzi?SeadragonConfig.Dzi:"Hmm, this doesn't appear to be a valid Deep Zoom Image.",Xml:SeadragonConfig.Xml?SeadragonConfig.Xml:"Hmm, this doesn't appear to be a valid Deep Zoom Image.",Empty:SeadragonConfig.Empty?SeadragonConfig.Empty:"You asked us to open nothing, so we did just that.",ImageFormat:SeadragonConfig.ImageFormat?SeadragonConfig.ImageFormat:"Sorry, we don't support {0}-based Deep Zoom Images.",Security:SeadragonConfig.Security?SeadragonConfig.Security:"It looks like a security restriction stopped us from "+"loading this Deep Zoom Image.",Status:SeadragonConfig.Status?SeadragonConfig.Status:"This space unintentionally left blank ({0} {1}).",Unknown:SeadragonConfig.Unknown?SeadragonConfig.Unknown:"Whoops, something inexplicably went wrong. Sorry!"},Messages:{Loading:SeadragonConfig.Loading?SeadragonConfig.Loading:"Loading..."},Tooltips:{FullPage:SeadragonConfig.FullPage?SeadragonConfig.FullPage:"Exit",Home:SeadragonConfig.Home?SeadragonConfig.Home:"Fit image",ZoomIn:SeadragonConfig.ZoomIn?SeadragonConfig.ZoomIn:"Zoom in",ZoomOut:SeadragonConfig.ZoomOut?SeadragonConfig.ZoomOut:"Zoom out"},getString:function(a){var b=a.split(".");var c=Seadragon.Strings;for(var d=0;d<b.length;d++){c=c[b[d]]||{}}if(typeof c!="string"){c=""}var e=arguments;return c.replace(/\{\d+\}/g,function(a){var b=parseInt(a.match(/\d+/))+1;return b<e.length?e[b]:""})},setString:function(a,b){var c=a.split(".");var d=Seadragon.Strings;for(var e=0;e<c.length-1;e++){if(!d[c[e]]){d[c[e]]={}}d=d[c[e]]}d[c[e]]=b}};Seadragon.Strings=Seadragon.Strings;Seadragon.Point=Seadragon.Point=function(a,b){this.x=typeof a=="number"?a:0;this.y=typeof b=="number"?b:0};Seadragon.Point.prototype={plus:function(a){return new Seadragon.Point(this.x+a.x,this.y+a.y)},minus:function(a){return new Seadragon.Point(this.x-a.x,this.y-a.y)},times:function(a){return new Seadragon.Point(this.x*a,this.y*a)},divide:function(a){return new Seadragon.Point(this.x/a,this.y/a)},negate:function(){return new Seadragon.Point(-this.x,-this.y)},distanceTo:function(a){return Math.sqrt(Math.pow(this.x-a.x,2)+Math.pow(this.y-a.y,2))},apply:function(a){return new Seadragon.Point(a(this.x),a(this.y))},equals:function(a){return a instanceof Seadragon.Point&&this.x===a.x&&this.y===a.y},toString:function(){return"("+this.x+","+this.y+")"}};Seadragon.Profiler=function(){this._midUpdate=false;this._numUpdates=0;this._lastBeginTime=null;this._lastEndTime=null;this._minUpdateTime=Infinity;this._avgUpdateTime=0;this._maxUpdateTime=0;this._minIdleTime=Infinity;this._avgIdleTime=0;this._maxIdleTime=0};Seadragon.Profiler.prototype={getAvgUpdateTime:function(){return this._avgUpdateTime},getMinUpdateTime:function(){return this._minUpdateTime},getMaxUpdateTime:function(){return this._maxUpdateTime},getAvgIdleTime:function(){return this._avgIdleTime},getMinIdleTime:function(){return this._minIdleTime},getMaxIdleTime:function(){return this._maxIdleTime},isMidUpdate:function(){return this._midUpdate},getNumUpdates:function(){return this._numUpdates},beginUpdate:function(){if(this._midUpdate){this.endUpdate()}this._midUpdate=true;this._lastBeginTime=(new Date).getTime();if(this._numUpdates<1){return}var a=this._lastBeginTime-this._lastEndTime;this._avgIdleTime=(this._avgIdleTime*(this._numUpdates-1)+a)/this._numUpdates;if(a<this._minIdleTime){this._minIdleTime=a}if(a>this._maxIdleTime){this._maxIdleTime=a}},endUpdate:function(){if(!this._midUpdate){return}this._lastEndTime=(new Date).getTime();this._midUpdate=false;var a=this._lastEndTime-this._lastBeginTime;this._numUpdates++;this._avgUpdateTime=(this._avgUpdateTime*(this._numUpdates-1)+a)/this._numUpdates;if(a<this._minUpdateTime){this._minUpdateTime=a}if(a>this._maxUpdateTime){this._maxUpdateTime=a}},clearProfile:function(){this._midUpdate=false;this._numUpdates=0;this._lastBeginTime=null;this._lastEndTime=null;this._minUpdateTime=Infinity;this._avgUpdateTime=0;this._maxUpdateTime=0;this._minIdleTime=Infinity;this._avgIdleTime=0;this._maxIdleTime=0}};Seadragon.Job=function(a,b){this._image=null;this._timeout=null;this._src=a;this._callback=b;this.TIMEOUT=5e3};Seadragon.Job.prototype={_finish:function(a){this._image.onload=null;this._image.onabort=null;this._image.onerror=null;if(this._timeout){window.clearTimeout(this._timeout)}var b=this._image;var c=this._callback;window.setTimeout(function(){c(this._src,a?b:null)},1)},_onloadHandler:function(){this._finish(true)},_onerrorHandler:function(){this._finish(false)},start:function(){this._image=new Image;this._image.onload=Function.createDelegate(this,this._onloadHandler);this._image.onabort=Function.createDelegate(this,this._onerrorHandler);this._image.onerror=Function.createDelegate(this,this._onerrorHandler);this._timeout=window.setTimeout(Function.createDelegate(this,this._onerrorHandler),this.TIMEOUT);this._image.src=this._src}};Seadragon.ImageLoader=function(a){this._downloading=0;this.imageLoaderLimit=a};Seadragon.ImageLoader.prototype={_onComplete:function(a,b,c){this._downloading--;if(typeof a=="function"){try{a(c)}catch(d){Seadragon.Debug.error(d.name+" while executing "+b+" callback: "+d.message,d)}}},loadImage:function(a,b){if(this._downloading>=this.imageLoaderLimit){return false}var c=Seadragon.Utils.createCallback(null,Function.createDelegate(this,this._onComplete),b);var d=new Seadragon.Job(a,c);this._downloading++;d.start();return true}};Seadragon.TileSource=function(a,b,c,d,e,f){this.aspectRatio=a/b;this.dimensions=new Seadragon.Point(a,b);this.minLevel=e?e:0;this.maxLevel=f?f:Math.ceil(Math.log(Math.max(a,b))/Math.log(2));this.tileSize=c?c:0;this.tileOverlap=d?d:0};Seadragon.TileSource.prototype={getLevelScale:function(a){return 1/(1<<this.maxLevel-a)},getNumTiles:function(a){var b=this.getLevelScale(a);var c=Math.ceil(b*this.dimensions.x/this.tileSize);var d=Math.ceil(b*this.dimensions.y/this.tileSize);return new Seadragon.Point(c,d)},getPixelRatio:function(a){var b=this.dimensions.times(this.getLevelScale(a));var c=1/b.x;var d=1/b.y;return new Seadragon.Point(c,d)},getTileAtPoint:function(a,b){var c=b.times(this.dimensions.x).times(this.getLevelScale(a));var d=Math.floor(c.x/this.tileSize);var e=Math.floor(c.y/this.tileSize);return new Seadragon.Point(d,e)},getTileBounds:function(a,b,c){var d=this.dimensions.times(this.getLevelScale(a));var e=b===0?0:this.tileSize*b-this.tileOverlap;var f=c===0?0:this.tileSize*c-this.tileOverlap;var g=this.tileSize+(b===0?1:2)*this.tileOverlap;var h=this.tileSize+(c===0?1:2)*this.tileOverlap;g=Math.min(g,d.x-e);h=Math.min(h,d.y-f);var i=1/d.x;return new Seadragon.Rect(e*i,f*i,g*i,h*i)},getTileUrl:function(a,b,c){throw new Error("Method not implemented.")},tileExists:function(a,b,c){var d=this.getNumTiles(a);return a>=this.minLevel&&a<=this.maxLevel&&b>=0&&c>=0&&b<d.x&&c<d.y}};Seadragon.DziError=function(a){Error.apply(this,arguments);this.message=a};Seadragon.DziError.prototype=new Error;Seadragon.DziError.constructor=Seadragon.DziError;Seadragon.DziTileSource=function(a,b,c,d,e,f,g){Seadragon.TileSource.call(this,a,b,c,d,null,null);this._levelRects={};this.tilesUrl=e;this.fileFormat=f;this.displayRects=g;this.initialize()};Seadragon.DziTileSource.prototype=new Seadragon.TileSource;Seadragon.DziTileSource.prototype.constructor=Seadragon.DziTileSource;Seadragon.DziTileSource.prototype.initialize=function(){if(!this.displayRects){return}for(var a=this.displayRects.length-1;a>=0;a--){var b=this.displayRects[a];for(var c=b.minLevel;c<=b.maxLevel;c++){if(!this._levelRects[c]){this._levelRects[c]=[]}this._levelRects[c].push(b)}}};Seadragon.DziTileSource.prototype.getTileUrl=function(a,b,c){return[this.tilesUrl,a,"/",b,"_",c,".",this.fileFormat].join("")};Seadragon.DziTileSource.prototype.tileExists=function(a,b,c){var d=this._levelRects[a];if(!d||!d.length){return true}for(var e=d.length-1;e>=0;e--){var f=d[e];if(a<f.minLevel||a>f.maxLevel){continue}var g=this.getLevelScale(a);var h=f.x*g;var i=f.y*g;var j=h+f.width*g;var k=i+f.height*g;h=Math.floor(h/this.tileSize);i=Math.floor(i/this.tileSize);j=Math.ceil(j/this.tileSize);k=Math.ceil(k/this.tileSize);if(h<=b&&b<j&&i<=c&&c<k){return true}}return false};Seadragon._DziTileSourceHelper=function(){};Seadragon._DziTileSourceHelper.prototype={createFromXml:function(a,b,c){function j(a,b){try{return a(b,i)}catch(c){if(d){e=this.getError(c).message;return null}else{throw this.getError(c)}}}var d=typeof c=="function";var e=null;if(!a){this.error=Seadragon.Strings.getString("Errors.Empty");if(d){window.setTimeout(function(){c(null,e)},1);return null}throw new Seadragon.DziError(e)}var f=a.split("/");var g=f[f.length-1];var h=g.lastIndexOf(".");if(h>-1){f[f.length-1]=g.slice(0,h)}var i=f.join("/")+"_files/";if(d){if(b){var k=Function.createDelegate(this,this.processXml);window.setTimeout(function(){var a=j(k,Seadragon.Utils.parseXml(b));c(a,e)},1)}else{var k=Function.createDelegate(this,this.processResponse);Seadragon.Utils.makeAjaxRequest(a,function(a){var b=j(k,a);c(b,e)})}return null}if(b){return j(Function.createDelegate(this,this.processXml),Seadragon.Utils.parseXml(b))}else{return j(Function.createDelegate(this,this.processResponse),Seadragon.Utils.makeAjaxRequest(a))}},processResponse:function(a,b){if(!a){throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.Security"))}else if(a.status!==200&&a.status!==0){var c=a.status;var d=c==404?"Not Found":a.statusText;throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.Status",c,d))}var e=null;if(a.responseXML&&a.responseXML.documentElement){e=a.responseXML}else if(a.responseText){e=Seadragon.Utils.parseXml(a.responseText)}return this.processXml(e,b)},processXml:function(a,b){if(!a||!a.documentElement){throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.Xml"))}var c=a.documentElement;var d=c.tagName;if(d=="Image"){try{return this.processDzi(c,b)}catch(e){var f=Seadragon.Strings.getString("Errors.Dzi");throw e instanceof Seadragon.DziError?e:new Seadragon.DziError(f)}}else if(d=="Collection"){throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.Dzc"))}else if(d=="Error"){return this.processError(c)}throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.Dzi"))},processDzi:function(a,b){var c=a.getAttribute("Format");if(!Seadragon.Utils.imageFormatSupported(c)){throw new Seadragon.DziError(Seadragon.Strings.getString("Errors.ImageFormat",c.toUpperCase()))}var d=a.getElementsByTagName("Size")[0];var e=a.getElementsByTagName("DisplayRect");var f=parseInt(d.getAttribute("Width"),10);var g=parseInt(d.getAttribute("Height"),10);var h=parseInt(a.getAttribute("TileSize"));var i=parseInt(a.getAttribute("Overlap"));var j=[];for(var k=0;k<e.length;k++){var l=e[k];var m=l.getElementsByTagName("Rect")[0];j.push(new Seadragon.DisplayRect(parseInt(m.getAttribute("X"),10),parseInt(m.getAttribute("Y"),10),parseInt(m.getAttribute("Width"),10),parseInt(m.getAttribute("Height"),10),0,parseInt(l.getAttribute("MaxLevel"),10)))}return new Seadragon.DziTileSource(f,g,h,i,b,c,j)},processError:function(a){var b=a.getElementsByTagName("Message")[0];var c=b.firstChild.nodeValue;throw new Seadragon.DziError(c)},getError:function(a){if(!(a instanceof DziError)){Seadragon.Debug.error(a.name+" while creating DZI from XML: "+a.message);a=new Seadragon.DziError(Seadragon.Strings.getString("Errors.Unknown"))}}};Seadragon.DziTileSourceHelper=new Seadragon._DziTileSourceHelper;Seadragon.ButtonState=function(){throw Error.invalidOperation()};Seadragon.ButtonState={REST:0,GROUP:1,HOVER:2,DOWN:3};Seadragon.Button=function(a,b){this._tooltip=a.tooltip;this._srcRest=a.srcRest;this._srcGroup=a.srcGroup;this._srcHover=a.srcHover;this._srcDown=a.srcDown;this._button=a.button;this.config=a.config;this.initialize(b)};Seadragon.Button.prototype={initialize:function(a){this._observer=new Observer;if(a.onPress!=undefined)this.add_onPress(a.onPress);if(a.onRelease!=undefined)this.add_onRelease(a.onRelease);if(a.onClick!=undefined)this.add_onClick(a.onClick);if(a.onEnter!=undefined)this.add_onEnter(a.onEnter);if(a.onExit!=undefined)this.add_onExit(a.onExit);this._button=Seadragon.Utils.makeNeutralElement("span");this._currentState=Seadragon.ButtonState.GROUP;this._tracker=new Seadragon.MouseTracker(this._button,this.config.clickTimeThreshold,this.config.clickDistThreshold);this._imgRest=Seadragon.Utils.makeTransparentImage(this._srcRest);this._imgGroup=Seadragon.Utils.makeTransparentImage(this._srcGroup);this._imgHover=Seadragon.Utils.makeTransparentImage(this._srcHover);this._imgDown=Seadragon.Utils.makeTransparentImage(this._srcDown);this._fadeDelay=0;this._fadeLength=2e3;this._fadeBeginTime=null;this._shouldFade=false;this._button.style.display="inline-block";this._button.style.position="relative";this._button.title=this._tooltip;this._button.appendChild(this._imgRest);this._button.appendChild(this._imgGroup);this._button.appendChild(this._imgHover);this._button.appendChild(this._imgDown);var b=this._imgRest.style;var c=this._imgGroup.style;var d=this._imgHover.style;var e=this._imgDown.style;c.position=d.position=e.position="absolute";c.top=d.top=e.top="0px";c.left=d.left=e.left="0px";d.visibility=e.visibility="hidden";if(Seadragon.Utils.getBrowser()==Seadragon.Browser.FIREFOX&&Seadragon.Utils.getBrowserVersion()<3){c.top=d.top=e.top=""}this._tracker.enterHandler=Function.createDelegate(this,this._enterHandler);this._tracker.exitHandler=Function.createDelegate(this,this._exitHandler);this._tracker.pressHandler=Function.createDelegate(this,this._pressHandler);this._tracker.releaseHandler=Function.createDelegate(this,this._releaseHandler);this._tracker.clickHandler=Function.createDelegate(this,this._clickHandler);this._tracker.setTracking(true);this._outTo(Seadragon.ButtonState.REST)},dispose:function(){},_scheduleFade:function(){window.setTimeout(Function.createDelegate(this,this._updateFade),20)},_updateFade:function(){if(this._shouldFade){var a=(new Date).getTime();var b=a-this._fadeBeginTime;var c=1-b/this._fadeLength;c=Math.min(1,c);c=Math.max(0,c);Seadragon.Utils.setElementOpacity(this._imgGroup,c,true);if(c>0){this._scheduleFade()}}},_beginFading:function(){this._shouldFade=true;this._fadeBeginTime=(new Date).getTime()+this._fadeDelay;window.setTimeout(Function.createDelegate(this,this._scheduleFade),this._fadeDelay)},_stopFading:function(){this._shouldFade=false;Seadragon.Utils.setElementOpacity(this._imgGroup,1,true)},_inTo:function(a){if(a>=Seadragon.ButtonState.GROUP&&this._currentState==Seadragon.ButtonState.REST){this._stopFading();this._currentState=Seadragon.ButtonState.GROUP}if(a>=Seadragon.ButtonState.HOVER&&this._currentState==Seadragon.ButtonState.GROUP){this._imgHover.style.visibility="";this._currentState=Seadragon.ButtonState.HOVER}if(a>=Seadragon.ButtonState.DOWN&&this._currentState==Seadragon.ButtonState.HOVER){this._imgDown.style.visibility="";this._currentState=Seadragon.ButtonState.DOWN}},_outTo:function(a){if(a<=Seadragon.ButtonState.HOVER&&this._currentState==Seadragon.ButtonState.DOWN){this._imgDown.style.visibility="hidden";this._currentState=Seadragon.ButtonState.HOVER}if(a<=Seadragon.ButtonState.GROUP&&this._currentState==Seadragon.ButtonState.HOVER){this._imgHover.style.visibility="hidden";this._currentState=Seadragon.ButtonState.GROUP}if(this._newState<=Seadragon.ButtonState.REST&&this._currentState==Seadragon.ButtonState.GROUP){this._beginFading();this._currentState=Seadragon.ButtonState.REST}},_enterHandler:function(a,b,c,d){if(c){this._inTo(Seadragon.ButtonState.DOWN);this._raiseEvent("onEnter",this)}else if(!d){this._inTo(Seadragon.ButtonState.HOVER)}},_exitHandler:function(a,b,c,d){this._outTo(Seadragon.ButtonState.GROUP);if(c){this._raiseEvent("onExit",this)}},_pressHandler:function(a,b){this._inTo(Seadragon.ButtonState.DOWN);this._raiseEvent("onPress",this)},_releaseHandler:function(a,b,c,d){if(c&&d){this._outTo(Seadragon.ButtonState.HOVER);this._raiseEvent("onRelease",this)}else if(c){this._outTo(Seadragon.ButtonState.GROUP)}else{this._inTo(Seadragon.ButtonState.HOVER)}},_clickHandler:function(a,b,c,d){if(c){this._raiseEvent("onClick",this)}},get_events:function c(){return this._observer._getContext(this,true).events},_raiseEvent:function(a,b){var c=this.get_events().getHandler(a);if(c){if(!b){b=new Object}c(this,b)}},get_element:function(){return this._button},get_tooltip:function(){return this._tooltip},set_tooltip:function(a){this._tooltip=a},get_config:function(){return this.config},set_config:function(a){this.config=a},get_srcRest:function(){return this._srcRest},set_srcRest:function(a){this._srcRest=a},get_srcGroup:function(){return this._srcGroup},set_srcGroup:function(a){this._srcGroup=a},get_srcHover:function(){return this._srcHover},set_srcHover:function(a){this._srcHover=a},get_srcDown:function(){return this._srcDown},set_srcDown:function(a){this._srcDown=a},add_onPress:function(a){this.get_events().addHandler("onPress",a)},remove_onPress:function(a){this.get_events().removeHandler("onPress",a)},add_onClick:function(a){this.get_events().addHandler("onClick",a)},remove_onClick:function(a){this.get_events().removeHandler("onClick",a)},add_onEnter:function(a){this.get_events().addHandler("onEnter",a)},remove_onEnter:function(a){this.get_events().removeHandler("onEnter",a)},add_onRelease:function(a){this.get_events().addHandler("onRelease",a)},remove_onRelease:function(a){this.get_events().removeHandler("onRelease",a)},add_onExit:function(a){this.get_events().addHandler("onExit",a)},remove_onExit:function(a){this.get_events().removeHandler("onExit",a)},notifyGroupEnter:function(){this._inTo(Seadragon.ButtonState.GROUP)},notifyGroupExit:function(){this._outTo(Seadragon.ButtonState.REST)}};Seadragon.ButtonGroup=function(a){this._buttons=a.buttons;this._group=a.group;this.config=a.config;this.initialize()};Seadragon.ButtonGroup.prototype={initialize:function(){this._group=Seadragon.Utils.makeNeutralElement("span");var a=this._buttons.concat([]);var b=new Seadragon.MouseTracker(this._group,this.config.clickTimeThreshold,this.config.clickDistThreshold);this._group.style.display="inline-block";for(var c=0;c<a.length;c++){this._group.appendChild(a[c].get_element())}b.enterHandler=Function.createDelegate(this,this._enterHandler);b.exitHandler=Function.createDelegate(this,this._exitHandler);b.releaseHandler=Function.createDelegate(this,this._releaseHandler);b.setTracking(true)},dispose:function(){},get_buttons:function(){return this._buttons},set_buttons:function(a){this._buttons=a},get_element:function(){return this._group},get_config:function(){return this.config},set_config:function(a){this.config=a},_enterHandler:function(a,b,c,d){for(var e=0;e<this._buttons.length;e++){this._buttons[e].notifyGroupEnter()}},_exitHandler:function(a,b,c,d){if(!c){for(var e=0;e<this._buttons.length;e++){this._buttons[e].notifyGroupExit()}}},_releaseHandler:function(a,b,c,d){if(!d){for(var e=0;e<this._buttons.length;e++){this._buttons[e].notifyGroupExit()}}},emulateEnter:function(){this._enterHandler()},emulateExit:function(){this._exitHandler()}};Seadragon.Config=function(){this.debugMode=false;this.animationTime=1.5;this.blendTime=.5;this.alwaysBlend=false;this.autoHideControls=true;this.immediateRender=true;this.wrapHorizontal=false;this.wrapVertical=false;this.minZoomImageRatio=.8;this.maxZoomPixelRatio=2;this.visibilityRatio=.5;this.springStiffness=5;this.imageLoaderLimit=2;this.clickTimeThreshold=200;this.clickDistThreshold=5;this.zoomPerClick=2;this.zoomPerScroll=1.2;this.zoomPerSecond=2;this.showNavigationControl=true;this.maxImageCacheCount=100;this.minPixelRatio=.5;this.mouseNavEnabled=true;this.navImages={zoomIn:{REST:SeadragonConfig.imgPath+"OpenSeadragon/images/zoomin_rest.png",GROUP:SeadragonConfig.imgPath+"OpenSeadragon/images/zoomin_grouphover.png",HOVER:SeadragonConfig.imgPath+"OpenSeadragon/images/zoomin_hover.png",DOWN:SeadragonConfig.imgPath+"OpenSeadragon/images/zoomin_pressed.png"},zoomOut:{REST:SeadragonConfig.imgPath+"OpenSeadragon/images/zoomout_rest.png",GROUP:SeadragonConfig.imgPath+"OpenSeadragon/images/zoomout_grouphover.png",HOVER:SeadragonConfig.imgPath+"OpenSeadragon/images/zoomout_hover.png",DOWN:SeadragonConfig.imgPath+"OpenSeadragon/images/zoomout_pressed.png"},home:{REST:SeadragonConfig.imgPath+"OpenSeadragon/images/home_rest.png",GROUP:SeadragonConfig.imgPath+"OpenSeadragon/images/home_grouphover.png",HOVER:SeadragonConfig.imgPath+"OpenSeadragon/images/home_hover.png",DOWN:SeadragonConfig.imgPath+"OpenSeadragon/images/home_pressed.png"},fullpage:{REST:SeadragonConfig.imgPath+"OpenSeadragon/images/fullpage_rest.png",GROUP:SeadragonConfig.imgPath+"OpenSeadragon/images/fullpage_grouphover.png",HOVER:SeadragonConfig.imgPath+"OpenSeadragon/images/fullpage_hover.png",DOWN:SeadragonConfig.imgPath+"OpenSeadragon/images/fullpage_pressed.png"}}};Seadragon.Rect=function(a,b,c,d){this.x=typeof a=="number"?a:0;this.y=typeof b=="number"?b:0;this.width=typeof c=="number"?c:0;this.height=typeof d=="number"?d:0};Seadragon.Rect.prototype={getAspectRatio:function(){return this.width/this.height},getTopLeft:function(){return new Seadragon.Point(this.x,this.y)},getBottomRight:function(){return new Seadragon.Point(this.x+this.width,this.y+this.height)},getCenter:function(){return new Seadragon.Point(this.x+this.width/2,this.y+this.height/2)},getSize:function(){return new Seadragon.Point(this.width,this.height)},equals:function(a){return a instanceof Seadragon.Rect&&this.x===a.x&&this.y===a.y&&this.width===a.width&&this.height===a.height},toString:function(){return"["+this.x+","+this.y+","+this.width+"x"+this.height+"]"}};Seadragon.DisplayRect=function(a,b,c,d,e,f){Seadragon.Rect.apply(this,[a,b,c,d]);this.minLevel=e;this.maxLevel=f};Seadragon.DisplayRect.prototype=new Seadragon.Rect;Seadragon.DisplayRect.prototype.constructor=Seadragon.DisplayRect;Seadragon.Spring=Seadragon.Spring=function(a,b){this._currentValue=typeof a=="number"?a:0;this._startValue=this._currentValue;this._targetValue=this._currentValue;this.config=b;this._currentTime=(new Date).getTime();this._startTime=this._currentTime;this._targetTime=this._currentTime};Seadragon.Spring.prototype={_transform:function(a){var b=this.config.springStiffness;return(1-Math.exp(-a*b))/(1-Math.exp(-b))},getCurrent:function(){return this._currentValue},getTarget:function(){return this._targetValue},resetTo:function(a){this._targetValue=a;this._targetTime=this._currentTime;this._startValue=this._targetValue;this._startTime=this._targetTime},springTo:function(a){this._startValue=this._currentValue;this._startTime=this._currentTime;this._targetValue=a;this._targetTime=this._startTime+1e3*this.config.animationTime},shiftBy:function(a){this._startValue+=a;this._targetValue+=a},update:function(){this._currentTime=(new Date).getTime();this._currentValue=this._currentTime>=this._targetTime?this._targetValue:this._startValue+(this._targetValue-this._startValue)*this._transform((this._currentTime-this._startTime)/(this._targetTime-this._startTime))}};var QUOTA=100;var MIN_PIXEL_RATIO=.5;var browser=Seadragon.Utils.getBrowser();var browserVer=Seadragon.Utils.getBrowserVersion();var subpixelRenders=browser==Seadragon.Browser.FIREFOX||browser==Seadragon.Browser.OPERA||browser==Seadragon.Browser.SAFARI&&browserVer>=4||browser==Seadragon.Browser.CHROME&&browserVer>=2;var useCanvas=typeof document.createElement("canvas").getContext=="function"&&subpixelRenders;Seadragon.Tile=function(a,b,c,d,e,f){this.level=a;this.x=b;this.y=c;this.bounds=d;this.exists=e;this.loaded=false;this.loading=false;this.elmt=null;this.image=null;this.url=f;this.style=null;this.position=null;this.size=null;this.blendStart=null;this.opacity=null;this.distance=null;this.visibility=null;this.beingDrawn=false;this.lastTouchTime=0};Seadragon.Tile.prototype={dispose:function(){},toString:function(){return this.level+"/"+this.x+"_"+this.y},drawHTML:function(a){if(!this.loaded){Seadragon.Debug.error("Attempting to draw tile "+this.toString()+" when it's not yet loaded.");return}if(!this.elmt){this.elmt=Seadragon.Utils.makeNeutralElement("img");this.elmt.src=this.url;this.style=this.elmt.style;this.style.position="absolute";this.style.msInterpolationMode="nearest-neighbor"}var b=this.elmt;var c=this.style;var d=this.position.apply(Math.floor);var e=this.size.apply(Math.ceil);if(b.parentNode!=a){a.appendChild(b)}c.left=d.x+"px";c.top=d.y+"px";c.width=e.x+"px";c.height=e.y+"px";Seadragon.Utils.setElementOpacity(b,this.opacity)},drawCanvas:function(a){if(!this.loaded){Seadragon.Debug.error("Attempting to draw tile "+this.toString()+" when it's not yet loaded.");return}var b=this.position;var c=this.size;a.globalAlpha=this.opacity;a.drawImage(this.image,b.x,b.y,c.x,c.y)},unload:function(){if(this.elmt&&this.elmt.parentNode){this.elmt.parentNode.removeChild(this.elmt)}this.elmt=null;this.image=null;this.loaded=false;this.loading=false}};Seadragon.Overlay=function(a,b,c){this.elmt=a;this.scales=b instanceof Seadragon.Rect;this.bounds=new Seadragon.Rect(b.x,b.y,b.width,b.height);this.placement=b instanceof Seadragon.Point?c:Seadragon.OverlayPlacement.TOP_LEFT;this.position=new Seadragon.Point(b.x,b.y);this.size=new Seadragon.Point(b.width,b.height);this.style=a.style};Seadragon.Overlay.prototype={adjust:function(a,b){switch(this.placement){case Seadragon.OverlayPlacement.TOP_LEFT:break;case Seadragon.OverlayPlacement.TOP:a.x-=b.x/2;break;case Seadragon.OverlayPlacement.TOP_RIGHT:a.x-=b.x;break;case Seadragon.OverlayPlacement.RIGHT:a.x-=b.x;a.y-=b.y/2;break;case Seadragon.OverlayPlacement.BOTTOM_RIGHT:a.x-=b.x;a.y-=b.y;break;case Seadragon.OverlayPlacement.BOTTOM:a.x-=b.x/2;a.y-=b.y;break;case Seadragon.OverlayPlacement.BOTTOM_LEFT:a.y-=b.y;break;case Seadragon.OverlayPlacement.LEFT:a.y-=b.y/2;break;case Seadragon.OverlayPlacement.CENTER:default:a.x-=b.x/2;a.y-=b.y/2;break}},destroy:function(){var a=this.elmt;var b=this.style;if(a.parentNode){a.parentNode.removeChild(a)}b.top="";b.left="";b.position="";if(this.scales){b.width="";b.height=""}},drawHTML:function(a){var b=this.elmt;var c=this.style;var d=this.scales;if(b.parentNode!=a){a.appendChild(b)}if(!d){this.size=Seadragon.Utils.getElementSize(b)}var e=this.position;var f=this.size;this.adjust(e,f);e=e.apply(Math.floor);f=f.apply(Math.ceil);c.left=e.x+"px";c.top=e.y+"px";c.position="absolute";if(d){c.width=f.x+"px";c.height=f.y+"px"}},update:function(a,b){this.scales=a instanceof Seadragon.Rect;this.bounds=new Seadragon.Rect(a.x,a.y,a.width,a.height);this.placement=a instanceof Seadragon.Point?b:Seadragon.OverlayPlacement.TOP_LEFT}};Seadragon.Drawer=function(a,b,c){this._container=Seadragon.Utils.getElement(c);this._canvas=Seadragon.Utils.makeNeutralElement(useCanvas?"canvas":"div");this._context=useCanvas?this._canvas.getContext("2d"):null;this._viewport=b;this._source=a;this.config=this._viewport.config;this._imageLoader=new Seadragon.ImageLoader(this.config.imageLoaderLimit);this._profiler=new Seadragon.Profiler;this._minLevel=a.minLevel;this._maxLevel=a.maxLevel;this._tileSize=a.tileSize;this._tileOverlap=a.tileOverlap;this._normHeight=a.dimensions.y/a.dimensions.x;this._cacheNumTiles={};this._cachePixelRatios={};this._tilesMatrix={};this._tilesLoaded=[];this._coverage={};this._overlays=[];this._lastDrawn=[];this._lastResetTime=0;this._midUpdate=false;this._updateAgain=true;this.elmt=this._container;this._init()};Seadragon.Drawer.prototype={dispose:function(){},_init:function(){this._canvas.style.width="100%";this._canvas.style.height="100%";this._canvas.style.position="absolute";this._container.style.textAlign="left";this._container.appendChild(this._canvas)},_compareTiles:function(a,b){if(!a){return b}if(b.visibility>a.visibility){return b}else if(b.visibility==a.visibility){if(b.distance<a.distance){return b}}return a},_getNumTiles:function(a){if(!this._cacheNumTiles[a]){this._cacheNumTiles[a]=this._source.getNumTiles(a)}return this._cacheNumTiles[a]},_getPixelRatio:function(a){if(!this._cachePixelRatios[a]){this._cachePixelRatios[a]=this._source.getPixelRatio(a)}return this._cachePixelRatios[a]},_getTile:function(a,b,c,d,e,f){if(!this._tilesMatrix[a]){this._tilesMatrix[a]={}}if(!this._tilesMatrix[a][b]){this._tilesMatrix[a][b]={}}if(!this._tilesMatrix[a][b][c]){var g=(e+b%e)%e;var h=(f+c%f)%f;var i=this._source.getTileBounds(a,g,h);var j=this._source.tileExists(a,g,h);var k=this._source.getTileUrl(a,g,h);i.x+=1*(b-g)/e;i.y+=this._normHeight*(c-h)/f;this._tilesMatrix[a][b][c]=new Seadragon.Tile(a,b,c,i,j,k)}var l=this._tilesMatrix[a][b][c];l.lastTouchTime=d;return l},_loadTile:function(a,b){a.loading=this._imageLoader.loadImage(a.url,Seadragon.Utils.createCallback(null,Function.createDelegate(this,this._onTileLoad),a,b))},_onTileLoad:function(a,b,c){a.loading=false;if(this._midUpdate){Seadragon.Debug.error("Tile load callback in middle of drawing routine.");return}else if(!c){Seadragon.Debug.log("Tile "+a+" failed to load: "+a.url);a.exists=false;return}else if(b<this._lastResetTime){Seadragon.Debug.log("Ignoring tile "+a+" loaded before reset: "+a.url);return}a.loaded=true;a.image=c;var d=this._tilesLoaded.length;if(this._tilesLoaded.length>=QUOTA){var e=Math.ceil(Math.log(this._tileSize)/Math.log(2));var f=null;var g=-1;for(var h=this._tilesLoaded.length-1;h>=0;h--){var i=this._tilesLoaded[h];if(i.level<=this._cutoff||i.beingDrawn){continue}else if(!f){f=i;g=h;continue}var j=i.lastTouchTime;var k=f.lastTouchTime;var l=i.level;var m=f.level;if(j<k||j==k&&l>m){f=i;g=h}}if(f&&g>=0){f.unload();d=g}}this._tilesLoaded[d]=a;this._updateAgain=true},_clearTiles:function(){this._tilesMatrix={};this._tilesLoaded=[]},_providesCoverage:function(a,b,c){if(!this._coverage[a]){return false}if(b===undefined||c===undefined){var d=this._coverage[a];for(var e in d){if(d.hasOwnProperty(e)){var f=d[e];for(var g in f){if(f.hasOwnProperty(g)&&!f[g]){return false}}}}return true}return this._coverage[a][b]===undefined||this._coverage[a][b][c]===undefined||this._coverage[a][b][c]===true},_isCovered:function(a,b,c){if(b===undefined||c===undefined){return this._providesCoverage(a+1)}else{return this._providesCoverage(a+1,2*b,2*c)&&this._providesCoverage(a+1,2*b,2*c+1)&&this._providesCoverage(a+1,2*b+1,2*c)&&this._providesCoverage(a+1,2*b+1,2*c+1)}},_setCoverage:function(a,b,c,d){if(!this._coverage[a]){Seadragon.Debug.error("Setting coverage for a tile before its "+"level's coverage has been reset: "+a);return}if(!this._coverage[a][b]){this._coverage[a][b]={}}this._coverage[a][b][c]=d},_resetCoverage:function(a){this._coverage[a]={}},_compareTiles:function(a,b){if(!a){return b}if(b.visibility>a.visibility){return b}else if(b.visibility==a.visibility){if(b.distance<a.distance){return b}}return a},_getOverlayIndex:function(a){for(var b=this._overlays.length-1;b>=0;b--){if(this._overlays[b].elmt==a){return b}}return-1},_updateActual:function(){this._updateAgain=false;var a=this._canvas;var b=this._context;var c=this._container;var d=useCanvas;var e=this._lastDrawn;while(e.length>0){var f=e.pop();f.beingDrawn=false}var g=this._viewport.getContainerSize();var h=g.x;var i=g.y;a.innerHTML="";if(d){a.width=h;a.height=i;b.clearRect(0,0,h,i)}var j=this._viewport.getBounds(true);var k=j.getTopLeft();var l=j.getBottomRight();if(!this.config.wrapHorizontal&&(l.x<0||k.x>1)){return}else if(!this.config.wrapVertical&&(l.y<0||k.y>this._normHeight)){return}var m=Math.abs;var n=Math.ceil;var o=Math.floor;var p=Math.log;var q=Math.max;var r=Math.min;var s=this.config.alwaysBlend;var t=1e3*this.config.blendTime;var u=this.config.immediateRender;var v=this.config.wrapHorizontal;var w=this.config.wrapVertical;if(!v){k.x=q(k.x,0);l.x=r(l.x,1)}if(!w){k.y=q(k.y,0);l.y=r(l.y,this._normHeight)}var x=null;var y=false;var z=(new Date).getTime();var A=this._viewport.pixelFromPoint(this._viewport.getCenter());var B=this._viewport.deltaPixelsFromPoints(this._source.getPixelRatio(0),false).x;var C=u?1:B;var D=q(this._minLevel,o(p(this.config.minZoomImageRatio)/p(2)));var E=this._viewport.deltaPixelsFromPoints(this._source.getPixelRatio(0),true).x;var F=r(this._maxLevel,o(p(E/MIN_PIXEL_RATIO)/p(2)));D=r(D,F);for(var G=F;G>=D;G--){var H=false;var I=this._viewport.deltaPixelsFromPoints(this._source.getPixelRatio(G),true).x;if(!y&&I>=MIN_PIXEL_RATIO||G==D){H=true;y=true}else if(!y){continue}this._resetCoverage(G);var J=r(1,(I-.5)/.5);var K=this._viewport.deltaPixelsFromPoints(this._source.getPixelRatio(G),false).x;var L=C/m(C-K);var M=this._source.getTileAtPoint(G,k);var N=this._source.getTileAtPoint(G,l);var O=this._getNumTiles(G);var P=O.x;var Q=O.y;if(!v){N.x=r(N.x,P-1)}if(!w){N.y=r(N.y,Q-1)}for(var R=M.x;R<=N.x;R++){for(var S=M.y;S<=N.y;S++){var f=this._getTile(G,R,S,z,P,Q);var T=H;this._setCoverage(G,R,S,false);if(!f.exists){continue}if(y&&!T){if(this._isCovered(G,R,S)){this._setCoverage(G,R,S,true)}else{T=true}}if(!T){continue}var U=f.bounds.getTopLeft();var V=f.bounds.getSize();var W=this._viewport.pixelFromPoint(U,true);var X=this._viewport.deltaPixelsFromPoints(V,true);if(!this._tileOverlap){X=X.plus(new Seadragon.Point(1,1))}var Y=this._viewport.pixelFromPoint(U,false);var Z=this._viewport.deltaPixelsFromPoints(V,false);var $=Y.plus(Z.divide(2));var _=A.distanceTo($);f.position=W;f.size=X;f.distance=_;f.visibility=L;if(f.loaded){if(!f.blendStart){f.blendStart=z}var ba=z-f.blendStart;var bb=r(1,ba/t);if(s){bb*=J}f.opacity=bb;e.push(f);if(bb==1){this._setCoverage(G,R,S,true)}else if(ba<t){updateAgain=true}}else if(f.Loading){}else{x=this._compareTiles(x,f)}}}if(this._providesCoverage(G)){break}}for(var bc=e.length-1;bc>=0;bc--){var f=e[bc];if(d){f.drawCanvas(b)}else{f.drawHTML(a)}f.beingDrawn=true}var bd=this._overlays.length;for(var bc=0;bc<bd;bc++){var be=this._overlays[bc];var bf=be.bounds;be.position=this._viewport.pixelFromPoint(bf.getTopLeft(),true);be.size=this._viewport.deltaPixelsFromPoints(bf.getSize(),true);be.drawHTML(c)}if(x){this._loadTile(x,z);this._updateAgain=true}},addOverlay:function(a,b,c){var a=Seadragon.Utils.getElement(a);if(this._getOverlayIndex(a)>=0){return}this._overlays.push(new Seadragon.Overlay(a,b,c));this._updateAgain=true},updateOverlay:function(a,b,c){var a=Seadragon.Utils.getElement(a);var d=this._getOverlayIndex(a);if(d>=0){this._overlays[d].update(b,c);this._updateAgain=true}},removeOverlay:function(a){var a=Seadragon.Utils.getElement(a);var b=this._getOverlayIndex(a);if(b>=0){this._overlays[b].destroy();this._overlays.splice(b,1);this._updateAgain=true}},clearOverlays:function(){while(this._overlays.length>0){this._overlays.pop().destroy();this._updateAgain=true}},needsUpdate:function(){return this._updateAgain},numTilesLoaded:function(){return this._tilesLoaded.length},reset:function(){this._clearTiles();this._lastResetTime=(new Date).getTime();this._updateAgain=true},update:function(){this._profiler.beginUpdate();this._midUpdate=true;this._updateActual();this._midUpdate=false;this._profiler.endUpdate()},idle:function(){}};Seadragon.Viewport=function(a,b,c){this.zoomPoint=null;this.config=c;this._containerSize=a;this._contentSize=b;this._contentAspect=b.x/b.y;this._contentHeight=b.y/b.x;this._centerSpringX=new Seadragon.Spring(0,this.config);this._centerSpringY=new Seadragon.Spring(0,this.config);this._zoomSpring=new Seadragon.Spring(1,this.config);this._homeBounds=new Seadragon.Rect(0,0,1,this._contentHeight);this.goHome(true);this.update()};Seadragon.Viewport.prototype={_getHomeZoom:function(){var a=this._contentAspect/this.getAspectRatio();return a>=1?1:a},_getMinZoom:function(){var a=this._getHomeZoom();var b=this.config.minZoomImageRatio*a;return Math.min(b,a)},_getMaxZoom:function(){var a=this._contentSize.x*this.config.maxZoomPixelRatio/this._containerSize.x;return Math.max(a,this._getHomeZoom())},getAspectRatio:function(){return this._containerSize.x/this._containerSize.y},getContainerSize:function(){return new Seadragon.Point(this._containerSize.x,this._containerSize.y)},getBounds:function(a){var b=this.getCenter(a);var c=1/this.getZoom(a);var d=c/this.getAspectRatio();return new Seadragon.Rect(b.x-c/2,b.y-d/2,c,d)},getCenter:function(a){var b=new Seadragon.Point(this._centerSpringX.getCurrent(),this._centerSpringY.getCurrent());var c=new Seadragon.Point(this._centerSpringX.getTarget(),this._centerSpringY.getTarget());if(a){return b}else if(!this.zoomPoint){return c}var d=this.pixelFromPoint(this.zoomPoint,true);var e=this.getZoom();var f=1/e;var g=f/this.getAspectRatio();var h=new Seadragon.Rect(b.x-f/2,b.y-g/2,f,g);var i=this.zoomPoint.minus(h.getTopLeft()).times(this._containerSize.x/h.width);var j=i.minus(d);var k=j.divide(this._containerSize.x*e);return c.plus(k)},getZoom:function(a){if(a){return this._zoomSpring.getCurrent()}else{return this._zoomSpring.getTarget()}},applyConstraints:function(a){var b=this.getZoom();var c=Math.max(Math.min(b,this._getMaxZoom()),this._getMinZoom());if(b!=c){this.zoomTo(c,this.zoomPoint,a)}var d=this.getBounds();var e=this.config.visibilityRatio;var f=e*d.width;var g=e*d.height;var h=d.x+d.width;var i=1-d.x;var j=d.y+d.height;var k=this._contentHeight-d.y;var l=0;if(this.config.wrapHorizontal){}else if(h<f){l=f-h}else if(i<f){l=i-f}var m=0;if(this.config.wrapVertical){}else if(j<g){m=g-j}else if(k<g){m=k-g}if(l||m){d.x+=l;d.y+=m;this.fitBounds(d,a)}},ensureVisible:function(a){this.applyConstraints(a)},fitBounds:function(a,b){var c=this.getAspectRatio();var d=a.getCenter();var e=new Seadragon.Rect(a.x,a.y,a.width,a.height);if(e.getAspectRatio()>=c){e.height=a.width/c;e.y=d.y-e.height/2}else{e.width=a.height*c;e.x=d.x-e.width/2}this.panTo(this.getCenter(true),true);this.zoomTo(this.getZoom(true),null,true);var f=this.getBounds();var g=this.getZoom();var h=1/e.width;if(h==g||e.width==f.width){this.panTo(d,b);return}var i=f.getTopLeft().times(this._containerSize.x/f.width).minus(e.getTopLeft().times(this._containerSize.x/e.width)).divide(this._containerSize.x/f.width-this._containerSize.x/e.width);this.zoomTo(h,i,b)},goHome:function(a){var b=this.getCenter();if(this.config.wrapHorizontal){b.x=(1+b.x%1)%1;this._centerSpringX.resetTo(b.x);this._centerSpringX.update()}if(this.config.wrapVertical){b.y=(this._contentHeight+b.y%this._contentHeight)%this._contentHeight;this._centerSpringY.resetTo(b.y);this._centerSpringY.update()}this.fitBounds(this._homeBounds,a)},panBy:function(a,b){var c=new Seadragon.Point(this._centerSpringX.getTarget(),this._centerSpringY.getTarget());this.panTo(c.plus(a),b)},panTo:function(a,b){if(b){this._centerSpringX.resetTo(a.x);this._centerSpringY.resetTo(a.y)}else{this._centerSpringX.springTo(a.x);this._centerSpringY.springTo(a.y)}},zoomBy:function(a,b,c){this.zoomTo(this._zoomSpring.getTarget()*a,b,c)},zoomTo:function(a,b,c){if(c){this._zoomSpring.resetTo(a)}else{this._zoomSpring.springTo(a)}this.zoomPoint=b instanceof Seadragon.Point?b:null},resize:function(a,b){var c=this.getBounds();var d=c;var e=a.x/this._containerSize.x;this._containerSize=new Seadragon.Point(a.x,a.y);if(b){d.width=c.width*e;d.height=d.width/this.getAspectRatio()}this.fitBounds(d,true)},update:function(){var a=this._centerSpringX.getCurrent();var b=this._centerSpringY.getCurrent();var c=this._zoomSpring.getCurrent();if(this.zoomPoint){var d=this.pixelFromPoint(this.zoomPoint,true)}this._zoomSpring.update();if(this.zoomPoint&&this._zoomSpring.getCurrent()!=c){var e=this.pixelFromPoint(this.zoomPoint,true);var f=e.minus(d);var g=this.deltaPointsFromPixels(f,true);this._centerSpringX.shiftBy(g.x);this._centerSpringY.shiftBy(g.y)}else{this.zoomPoint=null}this._centerSpringX.update();this._centerSpringY.update();return this._centerSpringX.getCurrent()!=a||this._centerSpringY.getCurrent()!=b||this._zoomSpring.getCurrent()!=c},deltaPixelsFromPoints:function(a,b){return a.times(this._containerSize.x*this.getZoom(b))},deltaPointsFromPixels:function(a,b){return a.divide(this._containerSize.x*this.getZoom(b))},pixelFromPoint:function(a,b){var c=this.getBounds(b);return a.minus(c.getTopLeft()).times(this._containerSize.x/c.width)},pointFromPixel:function(a,b){var c=this.getBounds(b);return a.divide(this._containerSize.x/c.width).plus(c.getTopLeft())}};Seadragon.Debug={};Seadragon.Debug.fail=function(){};Seadragon.Debug.log=function(){};Seadragon.Debug.error=function(){} \ No newline at end of file diff --git a/src/static/OpenSeadragon/images/fullpage_grouphover.png b/src/static/OpenSeadragon/images/fullpage_grouphover.png new file mode 100644 index 0000000000000000000000000000000000000000..3ca4e1e3c366d44e9dbbde415f6addaef941b129 GIT binary patch literal 4907 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 literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/fullpage_hover.png b/src/static/OpenSeadragon/images/fullpage_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..d08eb2d0b077754ea9ad8906bf3c376f3fb178d4 GIT binary patch literal 5214 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 Y03r6Layo57ga7~l07*qoM6N<$f{F*rYybcN literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/fullpage_pressed.png b/src/static/OpenSeadragon/images/fullpage_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..0ee45b5fc68aea79b511fa35b2a0be387aa35351 GIT binary patch literal 5213 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 XkSH*Bx~K^}00000NkvXXu0mjf%Gk;7 literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/fullpage_rest.png b/src/static/OpenSeadragon/images/fullpage_rest.png new file mode 100644 index 0000000000000000000000000000000000000000..3172005c6e1f43e5183c589197112aa135320cc8 GIT binary patch literal 5155 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 R`k?>-002ovPDHLkV1ijn#q9t9 literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/home_grouphover.png b/src/static/OpenSeadragon/images/home_grouphover.png new file mode 100644 index 0000000000000000000000000000000000000000..204e1cc94b5057e04a42f0d4483ba0c96c05e7cc GIT binary patch literal 4808 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 literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/home_hover.png b/src/static/OpenSeadragon/images/home_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..ec218a00a0b18b6997b37b5f3c1ddc4ec413ca6f GIT binary patch literal 5107 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 VNa*~d>WBaU002ovPDHLkV1k<ts!RX? literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/home_pressed.png b/src/static/OpenSeadragon/images/home_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..4439508bc6ebb6c3d9aee81ae8df4da592bd1cb6 GIT binary patch literal 5138 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 AvH$=8 literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/home_rest.png b/src/static/OpenSeadragon/images/home_rest.png new file mode 100644 index 0000000000000000000000000000000000000000..009d1bbf4c410ca89adb6bdb3e1fa8192db2ff41 GIT binary patch literal 5061 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 b3;cHgLwsQRRRSox00000NkvXXu0mjfcv_4p literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/zoomin_grouphover.png b/src/static/OpenSeadragon/images/zoomin_grouphover.png new file mode 100644 index 0000000000000000000000000000000000000000..c985d0f958d78c8233c4fc3c3a48a240392c8ea8 GIT binary patch literal 4794 zcmV;r5=HHaP)<h;3K|Lk000e1NJLTq001KZ001Hg1^@s6)rDaE00009a7bBm000XU z000XU0RWnu7ytkYPiaF#P*7-ZbZ>KLZ*U+<Lqi~Na&Km7Y-Iodc-oy)XH-+^7Crag z^g>IBfRsybQWXdwQbLP>6p<z>Aqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uh<iVD~V z<RPMtgQJLw%KPDaqifc@_vX$1wbwr9tn;0-&j-K=43<bUQ8j=JsX`tR;Dg7+#^K~H zK!FM*Z~zbpvt%K2{UZSY_<lS*D<Z%Lz5oGu(+dayz)hRLFdT>f59&ghTmgWD0l;*T zI7<kC6aYYajzXpYKt=(8otP$50H6c_V9R4-;{Z@C0AMG7=F<Rxo%or10RUT+Ar%3j zkpLhQWr#!oXgdI`&sK^>09Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-<?i z0%4j!F2Z@488U%158(66005wo6%pWr^Zj_v4zAA5HjcIqUoGmt2LB>rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_<lS*MWK+n+1cgf z<k(8YLR(?VSAG6x!e78w{cQPuJpA|d;J)G{fihizM+Erb!p!tcr5w+a34~(Y=8s4G zw+sLL9n&JjNn*KJDiq^U5^;`1nvC-@r6P$!k}1U{(*I=Q-z@tBKHoI}uxdU5dyy@u zU1J0GOD7Ombim^G008p4Z^6_k2m^p<gW=D2|L;HjN1!DDfM!XOaR2~bL?kX$%CkSm z2mk;?pn)o|K^yeJ7%adB9Ki+L!3+FgHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_v zKpix|QD}yfa1JiQRk#j4a1Z)n2%f<xynzV>LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_Ifq<Ex{*7`05XF7hP+2Hl!3BQJ=6@fL%FCo z8iYoo3(#bAF`ADSpqtQgv>H8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ<AYmRsNLWl*PS{AOARHt#5!wki2?K;t z!Y3k=s7tgax)J%r7-BLphge7~Bi0g+6E6^Zh(p9TBoc{3GAFr^0!gu?RMHaCM$&Fl zBk3%un>0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 z<uv66WtcKSRim0x-Ke2d5jBrmLam{;Qm;{ms1r1GnmNsb7D-E`t)i9F8fX`2_i3-_ zbh;7Ul^#x)&{xvS=|||7=mYe33=M`AgU5(xC>fg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vF<Q0r40Q)j6=sE4X&sBct1q<&fbi3VB2Ov6t@q*0);U*o*SAPZv|vv@2aYYnT0 zb%8a+Cb7-ge0D0knEf5Qi#@8Tp*ce{N;6lpQuCB%KL_KOarm5cP6_8Ir<e17iry6O zDdH&`rZh~sF=bq9s+O0QSgS~@QL9Jmy*94xr=6y~MY~!1fet~(N+(<=M`w@D1)b+p z*;C!83a1uLJv#NSE~;y#8=<>IcfW3@?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<fJbF^|4I#xQ~n$Dc= zKYhjYmgz5NSkDm8*fZm{6U!;YX`NG>(?@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_-k<Mujg;0Lz*3buG=3$G&ehepthlN*$KaOySSQ^nWmo<0M+(UEUMEXRQ zMBbZcF;6+KElM>iKB_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+@AhPrP6BK<z=<L*0kfKU@CX*zeqbYQT4(^U>T#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot<a{81DF0~rvGr5Xr~8u`lav1h z1DNytV>2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000N&Nkl<Zc-pL(OKcR$8OQ(C)z7g#V}k~aU*I(Yyb4ipfI}dHWhEkc2`etU2#JRj zB^+`B5hNl&xez%Kmn4EE9CC<wBq&G-2@#7NFoHvfakL;?UXX%?J=lQV<LMdqv$`vX z?P_{v42iO7=~F+Zrs~(<_tp1k!a2t`IS3)7_8EW2q@43AiJ~YuXEGVc|HHy!agq{o z&*O1Cz7|m2_kCUqAkI+~0l<F;lY$@sBmgu%i))gC;Q%54Vfw79DhI$zr4knaY59*Z zi$KV+C;*g0hYq#u+O@04_kAgfB69oo?a9lRFVDpQ3_uVIizUkCavT6J6bif+rp}H+ zY5;TqjR2OOK7IN-&!0d4jb&M1xvt9{$KkeZ^M!>4Zdn$eo}T{K!-o$q96We%D}ZhQ zZ2*?W|JURBBmm^;)2A38AII3(*t=m;APN8jK<?D3Qy)%DO#I%qZSJ}*w{1It5R!(P znVI2t@8136{{8zuilLSR$i?$10%&Ap1jEC_Ut2;rz5t<=3bWAoEwo3E9_?MTX3ZCp zBvm<Ideew&Ns>Sa0U-pg>tb$h4nspjKR<l<@LvEd0I&ggvDrcZd}wHhZ`-yFl9((A z0{FgPYaVT6WaKB^-Q8b^F`nlk2m&z15Qbr5a{<X1OUB8vjC?+i&6_v>^1_7+KaMri z06<HdYhhvG>lYC)p69_Z46#im0Lrafw?102V#Tj0rSN?pK@cPh#|~a~78(+OK@fm* zj*gBF^!E1t?C8;>AIH8UOho~pzrUZ<!KBQi0MI%+JAb6AYNCzW7y$sXEQ3-CN+}2- zRlkQ}2;cV+h9SDTy0CWb+P$%MGAZqd(C`+<bzP*jGB`MRD4WfG!Wc^?Oq)db$NBT; zapJ@Y3=9lFlB7gCVtg2e@H`K?uA`@?XUmZzNA?0}ig%WhW=JkNJ3G?>O>JpuIizVC zT-U7w5h6(v48uS}Ljw%MsDcq13d0bLG1#_^?(S~1wY7a3`;7rWO$AUQ)y6ph@|iPd zzOAb2hr$`t+DHXN5JI478VtjLuItH85{Gz!Fboj{0Vt)&=kp(I*|OzZDHyrVOzB;; zYSpTbHBGBBj{u;QLQxbbiULY0R8@tp>(F%_lv2pDocK{X6fnl%x-ME<ThZ0k^}X0k zYI;}IrUPN7UeEJTE|($8GP2n$2qEx&AC_e$3rdm%N+~o=gDlH<{rYvHg&+u$=TQ{F zah$}ol+q7s99UW`HxU4m@B4Yi7%a<z=XrSZ<_%g}S}-~~iaU4iAfL~py}ccVVSo?< zRaFs&A#U8b0mpIh;>8P?ris43KJ3`B1I1zyzVAcRG!Q}%1VKv;2zeI_DVNKU@B8q5 zAD-udF@|!vjERW}T)A?kE}^!!x1&%f)IHB;v)Ht06CB3@V+@24L{WrFrNS4<_={)l zQmIrFyU6$b#2h_6Jve^+I21*Js;U5hix)4VP$;0OsR_r99ZRBl5CmAgdNpj@hUa+* z!w`z1pi-%zTrQUvTelX51K_i>vtOB}`9l%#2q9pMp|P<M+qZ9rq9|x=Y{ar<%W(br zbrcE(7>0oZ2M*xXt5>L0Dv4Gt%Ss|~CX>PB<Rps4;)_(RlN4c#!9?TZ<3p{jt;aTO z*Z{^Dq9}sz`*2-1*}hFpO`w!k{kd2yVtRTSmSxpdbCM)MRaFcR4`X_I`k!%~BMPuZ zVIlx*aBy&}qod==`t|GAOOlk1&Q*tHS#|f7N(GflrEY8{lR>Fe!jmUYCT3@6p91jH zMOST{NtcV>)YR0U?%%(U=H})^Gih;M7nWs#F_uK#QmF*Taq7lKQH18^W?Z{=4RdpI ze~ZfqH!dX-?T}Ok7D-Z#Giz?=&Yi#8w{PDMq9}rCns3WPAn}{#=4NP`h9C$~EEW@g zNdlK7Vabvuuq+D$0|Wn<nVI=DfN21)0h9n#Vl9P<X7=palh%w6z@3_!x_s%<CFr`2 zhK7b@clo{#$8k_B7Eve^FflQK$;nBWrU~1&lQCf!qM@Mygb<uPdlr^u{WS&P3J9T@ z1V$7%@ee)#XKZZj!PL~$FV3Ai2Srhk&*woYg~;T#ZDW3Z9;RtxettdyVT_491jZOn zo;(TDH2+}R_TK@_$1qOp#EH5SGi}|v6%QUf5CKSz!*v6IY)41Or@F3xzI*rX?{3_< z5vFOPR4T!B-73>jN}=mIve_(JT3T@L-aTBsdKHf2{5A-JI{;<@m;kJ}1Qq2cukx9` zzCMIuh{ul~r|VxmE`*w7Szf+$>C&HOv)Rx3`}@(`+lyQ-my{TkQW%DTnVA`kj*jBy z&6_YybC5CiXU_Rd3^5O&oN{26iZyRFvu@owL{Wri&z_N*?m&yvePax@!Z3`_2qE9+ zoOidiwIP$qpj<9va&i)37(U~ie;Gy59nSf5ytoygg?YRhkZPEfD_17<$IF*5YdZwd zvKX<Zgy@natpt$eoI9NJm+>NAEOttql+)IMRKYA?zPzg4oS&bsZD*Bu+iNLNQ-!r? zZ^PIz{S=fJ-`7Uns){Xv$>nl&1-I+Ei?z1`Oi8u7wY@g0X>Y?+q~(i&RKe)FUe}=2 zbeL(V+U8%XNhwiH^Z#CmIv7f6)i!<C`1gDgsmuQ9Pa^MwsQZBPe>liDo#5XC0P96f U<@`%&ga7~l07*qoM6N<$f_Nk7;{X5v literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/zoomin_hover.png b/src/static/OpenSeadragon/images/zoomin_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..3cab721f1bd5b0360dd1eac094c36a409b517738 GIT binary patch literal 5126 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 literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/zoomin_pressed.png b/src/static/OpenSeadragon/images/zoomin_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..9c3a75169cefbc031e7b1f0d0baf7472580552c3 GIT binary patch literal 5172 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 literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/zoomin_rest.png b/src/static/OpenSeadragon/images/zoomin_rest.png new file mode 100644 index 0000000000000000000000000000000000000000..f4219a50aed7503f63e9b553cf6159e2cca36d11 GIT binary patch literal 5041 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 Hu0mjf@M4@K literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/zoomout_grouphover.png b/src/static/OpenSeadragon/images/zoomout_grouphover.png new file mode 100644 index 0000000000000000000000000000000000000000..46d21b3e507e7363b4e8afd0e77343814ad63748 GIT binary patch literal 4596 zcmV<Q5ex2#P)<h;3K|Lk000e1NJLTq001KZ001Hg1^@s6)rDaE00009a7bBm000XU z000XU0RWnu7ytkYPiaF#P*7-ZbZ>KLZ*U+<Lqi~Na&Km7Y-Iodc-oy)XH-+^7Crag z^g>IBfRsybQWXdwQbLP>6p<z>Aqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uh<iVD~V z<RPMtgQJLw%KPDaqifc@_vX$1wbwr9tn;0-&j-K=43<bUQ8j=JsX`tR;Dg7+#^K~H zK!FM*Z~zbpvt%K2{UZSY_<lS*D<Z%Lz5oGu(+dayz)hRLFdT>f59&ghTmgWD0l;*T zI7<kC6aYYajzXpYKt=(8otP$50H6c_V9R4-;{Z@C0AMG7=F<Rxo%or10RUT+Ar%3j zkpLhQWr#!oXgdI`&sK^>09Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-<?i z0%4j!F2Z@488U%158(66005wo6%pWr^Zj_v4zAA5HjcIqUoGmt2LB>rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_<lS*MWK+n+1cgf z<k(8YLR(?VSAG6x!e78w{cQPuJpA|d;J)G{fihizM+Erb!p!tcr5w+a34~(Y=8s4G zw+sLL9n&JjNn*KJDiq^U5^;`1nvC-@r6P$!k}1U{(*I=Q-z@tBKHoI}uxdU5dyy@u zU1J0GOD7Ombim^G008p4Z^6_k2m^p<gW=D2|L;HjN1!DDfM!XOaR2~bL?kX$%CkSm z2mk;?pn)o|K^yeJ7%adB9Ki+L!3+FgHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_v zKpix|QD}yfa1JiQRk#j4a1Z)n2%f<xynzV>LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_Ifq<Ex{*7`05XF7hP+2Hl!3BQJ=6@fL%FCo z8iYoo3(#bAF`ADSpqtQgv>H8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ<AYmRsNLWl*PS{AOARHt#5!wki2?K;t z!Y3k=s7tgax)J%r7-BLphge7~Bi0g+6E6^Zh(p9TBoc{3GAFr^0!gu?RMHaCM$&Fl zBk3%un>0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 z<uv66WtcKSRim0x-Ke2d5jBrmLam{;Qm;{ms1r1GnmNsb7D-E`t)i9F8fX`2_i3-_ zbh;7Ul^#x)&{xvS=|||7=mYe33=M`AgU5(xC>fg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vF<Q0r40Q)j6=sE4X&sBct1q<&fbi3VB2Ov6t@q*0);U*o*SAPZv|vv@2aYYnT0 zb%8a+Cb7-ge0D0knEf5Qi#@8Tp*ce{N;6lpQuCB%KL_KOarm5cP6_8Ir<e17iry6O zDdH&`rZh~sF=bq9s+O0QSgS~@QL9Jmy*94xr=6y~MY~!1fet~(N+(<=M`w@D1)b+p z*;C!83a1uLJv#NSE~;y#8=<>IcfW3@?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<fJbF^|4I#xQ~n$Dc= zKYhjYmgz5NSkDm8*fZm{6U!;YX`NG>(?@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_-k<Mujg;0Lz*3buG=3$G&ehepthlN*$KaOySSQ^nWmo<0M+(UEUMEXRQ zMBbZcF;6+KElM>iKB_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+@AhPrP6BK<z=<L*0kfKU@CX*zeqbYQT4(^U>T#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot<a{81DF0~rvGr5Xr~8u`lav1h z1DNytV>2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000LcNkl<Zc-pL(Pizy}9ml_K{@7zXJI0Evr1=NgAPB3bDk*=YLJMUNl_<-K%a#iw z(rU}0>H(?ZPyy<No)A(ip=B?7r~<TVRS6_St@J<;Ih2O178ENBQVAp>5hPAL<BaFe zn|VF-z1ion!&0^*{WQ;$@q3^A{{KuEWB4`~A%rBKu?;q5j5SCUMe#kG%|d&NgT>)Q z67iYw_ZVLbDCYY<O9F^{6h#2=W-t;20iXa-`CY7u1j7JC07ChmN~IV8R;^Z<0FdPy zVOl_FTyy~X$jC_H$dMxhzV9nh6p`DvZ_i!5dUb^ZPyhiJ$|cI@^9%r6SXf|5m?k?4 zNdOoC+5ohlKY#xFPoF;hy=7TnxvtCV^*VDLhpn%#Gt08r;^N}J@87?F<>bke`vLR= z=mOBrzi;sU6aeJ$<HwkpnL)W+-WWy#(E(%t<j<Wu_ulO6>}QVSFxPdN<2W&d5E*J| zX^GvrbLWpIPMr7&hw1>3=lkgbXliN-larJGwS;hd0ivp^FpJ9ni}ZsB4~}o!w(V0z zQ5u|24jQpm6a|D35JKR(E>>1nFg`y1n^UJw{T0AE00)4_%@zV+<KyG(z<~o$#AZPd z!1w*6dD2r;Q@`l%@BdW1<9Qx}AONKlVHn0X7m$?F_&rV2P%IX)XV0GBUAc1Q6Rw#Y zfV6C`_4V~e&DgdL(=>%vGyuk}TesdH9v=Q%Hk$>dG<GyOwaDwFmW8GmV<?x)xN+mg zuP$A>GzP%pTJpGqGXN}(CeQOAnMVhZ?(OaUIF(Al^E^aR6sw;x*0A0PL}*G;6!i7= zVf*&&#{t}zqDu~c7Msa+U9nUE=%rF=#5B#HQA*+aev?UB`Hma};{7lT;dvem!@$76 zz`oO`Pag;H4v#G1$nn7dfZpC-IiaNrg~CWWordeWEkRlVv`Y737=ls?$8pf#-;b`Y zt`E82WB{b31WJ@-o&%s=xNzZnsZ{Dc;fw-egTxs7jl33S5<o!^Kvh)~i^X^M?c4WV z2}TnoMM;1t0JJSzw!EKCryI;84pUVXx~|8fX&N+5YglWV231udrvgeTT-QZsXD9ml z`hLjGl#-(=Sq_Amc6go#+qR);8cfp!Aq2kf!?G-Bn%0m{lI9W`O{de)G!0P{p<b_p zF$P6ZpsMP-Qg{n9HPt2pK=FOQNGXM7S@1j$uU@@Ep-{l|^fboC#!xI4(cRsROeWI+ zBMyE3{5dL>3WkS=ap=$?tgf!Y_kE<(X%IpX1VJGILN<aSwrxkg@5A?fc%BDJDQw%u z?CdPAUAxxgH{IRcSXfwSdTyE~cJJPedc6)xDF`8mq6oEGjkT!wt*dsmT3r=U<omu* zEd~Y#aOTVz=(-M7RX42mQ4}Ev0&Ly76^`S;^E`xM2wm4vtJPrJw%zJ`Nf-uzEiW&B zRjE`y5DAYE0!k^`+S+jN;6doR4n<Kmgkg-uTD2?-K@fm3hHN&Axw$#4uC6|plbvY7 zTERp!Gc)6zot?klxpQY+27KR#>$**j`?~g0u33trAeBmCa&i)ji;G|IG9WT=OPB}% zEtN{;o}QjZLqkJDilWHb`K_;PHj8Stibszg%`Pu5KL+5-O;-{|ZWq1z`T0NHyLWGB z@7}$r)oP%WzBP!ZY1p)B6Glfzv9hxA58g(&yims4X=Nq~ASjhee_@RMcyMs=r@34X zl}hF7_V9nW6h%QkpU1Oj&oD7D@voOJUzPyWIFM*bSwjXscI=p}86SW<KR<tUbaWJk zVIY^w#nJVq5{4mixf}=~xOnj*EX(>kfGUS^`8ly>Vi?ij@IUwf>g95IVt#)9x0f$p zhOX-<7K>0-6_nC%6kdlwDaF~dXHltCK6f1Fp8(c4Or2{cR(IT7?ccv26B841bCu@R z)$Hl%`Oq+opC3JX^as0k?LwteLA6?i>$(l5Q&km)VZby^6bc30y?YneuU|*KUjIW7 z1Y-b}0aOyrl`s>FVTOl?5r!ciK71(mzXpITfOj-a>u7Ip|D|b~A00k?7&~_CKt7+3 zTMSiIk;!DRw6uij>1o`&c@vdNr9>(HGh=LtL#zR?B?qQbuK8LsgM)*Jq6kl(JRync zAkE8t8;AN%CX@My5b`6&SbtYn7qZzbY}>}%+#JF%e8L#}GK!)x#@Hf1+~Rj(9xnmX z2(x+f=D7cO@!~~tLJ%WMhHFZQp(x5`048Is&KP^a5AnD-lGG)qZ31b4>FDTa7&q6} z){^6_&ijwFBq{z}mB!nUJEku|dHi!S>o#<3F-$(6ZyL&7*KIZ43NT$7cayU=O^mmp zlxbNjkOmmTFq)d|#DpnBC5L|{QBtDB@c&wfCKy#!-z3An?kAC^>M#E!@;Zp73j2S! e$hY0#KLY>*6CH&u;pYAT0000<MNUMnLSTZ;RF}~J literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/zoomout_hover.png b/src/static/OpenSeadragon/images/zoomout_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..7b924c26d8f587e030293036a7230d3faba88918 GIT binary patch literal 4931 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 BHPZk9 literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/zoomout_pressed.png b/src/static/OpenSeadragon/images/zoomout_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..c028db72405a925425228819f7e348df331d9afd GIT binary patch literal 5007 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 ZcL1+4p0OE`yDI<y002ovPDHLkV1g<;cmx0d literal 0 HcmV?d00001 diff --git a/src/static/OpenSeadragon/images/zoomout_rest.png b/src/static/OpenSeadragon/images/zoomout_rest.png new file mode 100644 index 0000000000000000000000000000000000000000..a13e07de798ec32c5bcbec32001427df6bade43b GIT binary patch literal 4811 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 literal 0 HcmV?d00001 diff --git a/src/static/dagre-d3/d3.v3.js b/src/static/dagre-d3/d3.v3.js new file mode 100644 index 0000000..8228777 --- /dev/null +++ b/src/static/dagre-d3/d3.v3.js @@ -0,0 +1,9233 @@ +!function() { + var d3 = { + version: "3.4.11" + }; + if (!Date.now) Date.now = function() { + return +new Date(); + }; + var d3_arraySlice = [].slice, d3_array = function(list) { + return d3_arraySlice.call(list); + }; + var d3_document = document, d3_documentElement = d3_document.documentElement, d3_window = window; + try { + d3_array(d3_documentElement.childNodes)[0].nodeType; + } catch (e) { + d3_array = function(list) { + var i = list.length, array = new Array(i); + while (i--) array[i] = list[i]; + return array; + }; + } + try { + d3_document.createElement("div").style.setProperty("opacity", 0, ""); + } catch (error) { + var d3_element_prototype = d3_window.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty; + d3_element_prototype.setAttribute = function(name, value) { + d3_element_setAttribute.call(this, name, value + ""); + }; + d3_element_prototype.setAttributeNS = function(space, local, value) { + d3_element_setAttributeNS.call(this, space, local, value + ""); + }; + d3_style_prototype.setProperty = function(name, value, priority) { + d3_style_setProperty.call(this, name, value + "", priority); + }; + } + d3.ascending = d3_ascending; + function d3_ascending(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; + } + d3.descending = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; + }; + d3.min = function(array, f) { + var i = -1, n = array.length, a, b; + if (arguments.length === 1) { + while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined; + while (++i < n) if ((b = array[i]) != null && a > b) a = b; + } else { + while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined; + while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b; + } + return a; + }; + d3.max = function(array, f) { + var i = -1, n = array.length, a, b; + if (arguments.length === 1) { + while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined; + while (++i < n) if ((b = array[i]) != null && b > a) a = b; + } else { + while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined; + while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b; + } + return a; + }; + d3.extent = function(array, f) { + var i = -1, n = array.length, a, b, c; + if (arguments.length === 1) { + while (++i < n && !((a = c = array[i]) != null && a <= a)) a = c = undefined; + while (++i < n) if ((b = array[i]) != null) { + if (a > b) a = b; + if (c < b) c = b; + } + } else { + while (++i < n && !((a = c = f.call(array, array[i], i)) != null && a <= a)) a = undefined; + while (++i < n) if ((b = f.call(array, array[i], i)) != null) { + if (a > b) a = b; + if (c < b) c = b; + } + } + return [ a, c ]; + }; + d3.sum = function(array, f) { + var s = 0, n = array.length, a, i = -1; + if (arguments.length === 1) { + while (++i < n) if (!isNaN(a = +array[i])) s += a; + } else { + while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a; + } + return s; + }; + function d3_number(x) { + return x != null && !isNaN(x); + } + d3.mean = function(array, f) { + var s = 0, n = array.length, a, i = -1, j = n; + if (arguments.length === 1) { + while (++i < n) if (d3_number(a = array[i])) s += a; else --j; + } else { + while (++i < n) if (d3_number(a = f.call(array, array[i], i))) s += a; else --j; + } + return j ? s / j : undefined; + }; + d3.quantile = function(values, p) { + var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h; + return e ? v + e * (values[h] - v) : v; + }; + d3.median = function(array, f) { + if (arguments.length > 1) array = array.map(f); + array = array.filter(d3_number); + return array.length ? d3.quantile(array.sort(d3_ascending), .5) : undefined; + }; + function d3_bisector(compare) { + return { + left: function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid; + } + return lo; + }, + right: function(a, x, lo, hi) { + if (arguments.length < 3) lo = 0; + if (arguments.length < 4) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1; + } + return lo; + } + }; + } + var d3_bisect = d3_bisector(d3_ascending); + d3.bisectLeft = d3_bisect.left; + d3.bisect = d3.bisectRight = d3_bisect.right; + d3.bisector = function(f) { + return d3_bisector(f.length === 1 ? function(d, x) { + return d3_ascending(f(d), x); + } : f); + }; + d3.shuffle = function(array) { + var m = array.length, t, i; + while (m) { + i = Math.random() * m-- | 0; + t = array[m], array[m] = array[i], array[i] = t; + } + return array; + }; + d3.permute = function(array, indexes) { + var i = indexes.length, permutes = new Array(i); + while (i--) permutes[i] = array[indexes[i]]; + return permutes; + }; + d3.pairs = function(array) { + var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n); + while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ]; + return pairs; + }; + d3.zip = function() { + if (!(n = arguments.length)) return []; + for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) { + for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) { + zip[j] = arguments[j][i]; + } + } + return zips; + }; + function d3_zipLength(d) { + return d.length; + } + d3.transpose = function(matrix) { + return d3.zip.apply(d3, matrix); + }; + d3.keys = function(map) { + var keys = []; + for (var key in map) keys.push(key); + return keys; + }; + d3.values = function(map) { + var values = []; + for (var key in map) values.push(map[key]); + return values; + }; + d3.entries = function(map) { + var entries = []; + for (var key in map) entries.push({ + key: key, + value: map[key] + }); + return entries; + }; + d3.merge = function(arrays) { + var n = arrays.length, m, i = -1, j = 0, merged, array; + while (++i < n) j += arrays[i].length; + merged = new Array(j); + while (--n >= 0) { + array = arrays[n]; + m = array.length; + while (--m >= 0) { + merged[--j] = array[m]; + } + } + return merged; + }; + var abs = Math.abs; + d3.range = function(start, stop, step) { + if (arguments.length < 3) { + step = 1; + if (arguments.length < 2) { + stop = start; + start = 0; + } + } + if ((stop - start) / step === Infinity) throw new Error("infinite range"); + var range = [], k = d3_range_integerScale(abs(step)), i = -1, j; + start *= k, stop *= k, step *= k; + if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k); + return range; + }; + function d3_range_integerScale(x) { + var k = 1; + while (x * k % 1) k *= 10; + return k; + } + function d3_class(ctor, properties) { + try { + for (var key in properties) { + Object.defineProperty(ctor.prototype, key, { + value: properties[key], + enumerable: false + }); + } + } catch (e) { + ctor.prototype = properties; + } + } + d3.map = function(object) { + var map = new d3_Map(); + if (object instanceof d3_Map) object.forEach(function(key, value) { + map.set(key, value); + }); else for (var key in object) map.set(key, object[key]); + return map; + }; + function d3_Map() {} + d3_class(d3_Map, { + has: d3_map_has, + get: function(key) { + return this[d3_map_prefix + key]; + }, + set: function(key, value) { + return this[d3_map_prefix + key] = value; + }, + remove: d3_map_remove, + keys: d3_map_keys, + values: function() { + var values = []; + this.forEach(function(key, value) { + values.push(value); + }); + return values; + }, + entries: function() { + var entries = []; + this.forEach(function(key, value) { + entries.push({ + key: key, + value: value + }); + }); + return entries; + }, + size: d3_map_size, + empty: d3_map_empty, + forEach: function(f) { + for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) f.call(this, key.substring(1), this[key]); + } + }); + var d3_map_prefix = "\x00", d3_map_prefixCode = d3_map_prefix.charCodeAt(0); + function d3_map_has(key) { + return d3_map_prefix + key in this; + } + function d3_map_remove(key) { + key = d3_map_prefix + key; + return key in this && delete this[key]; + } + function d3_map_keys() { + var keys = []; + this.forEach(function(key) { + keys.push(key); + }); + return keys; + } + function d3_map_size() { + var size = 0; + for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) ++size; + return size; + } + function d3_map_empty() { + for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) return false; + return true; + } + d3.nest = function() { + var nest = {}, keys = [], sortKeys = [], sortValues, rollup; + function map(mapType, array, depth) { + if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array; + var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values; + while (++i < n) { + if (values = valuesByKey.get(keyValue = key(object = array[i]))) { + values.push(object); + } else { + valuesByKey.set(keyValue, [ object ]); + } + } + if (mapType) { + object = mapType(); + setter = function(keyValue, values) { + object.set(keyValue, map(mapType, values, depth)); + }; + } else { + object = {}; + setter = function(keyValue, values) { + object[keyValue] = map(mapType, values, depth); + }; + } + valuesByKey.forEach(setter); + return object; + } + function entries(map, depth) { + if (depth >= keys.length) return map; + var array = [], sortKey = sortKeys[depth++]; + map.forEach(function(key, keyMap) { + array.push({ + key: key, + values: entries(keyMap, depth) + }); + }); + return sortKey ? array.sort(function(a, b) { + return sortKey(a.key, b.key); + }) : array; + } + nest.map = function(array, mapType) { + return map(mapType, array, 0); + }; + nest.entries = function(array) { + return entries(map(d3.map, array, 0), 0); + }; + nest.key = function(d) { + keys.push(d); + return nest; + }; + nest.sortKeys = function(order) { + sortKeys[keys.length - 1] = order; + return nest; + }; + nest.sortValues = function(order) { + sortValues = order; + return nest; + }; + nest.rollup = function(f) { + rollup = f; + return nest; + }; + return nest; + }; + d3.set = function(array) { + var set = new d3_Set(); + if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]); + return set; + }; + function d3_Set() {} + d3_class(d3_Set, { + has: d3_map_has, + add: function(value) { + this[d3_map_prefix + value] = true; + return value; + }, + remove: function(value) { + value = d3_map_prefix + value; + return value in this && delete this[value]; + }, + values: d3_map_keys, + size: d3_map_size, + empty: d3_map_empty, + forEach: function(f) { + for (var value in this) if (value.charCodeAt(0) === d3_map_prefixCode) f.call(this, value.substring(1)); + } + }); + d3.behavior = {}; + d3.rebind = function(target, source) { + var i = 1, n = arguments.length, method; + while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]); + return target; + }; + function d3_rebind(target, source, method) { + return function() { + var value = method.apply(source, arguments); + return value === source ? target : value; + }; + } + function d3_vendorSymbol(object, name) { + if (name in object) return name; + name = name.charAt(0).toUpperCase() + name.substring(1); + for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) { + var prefixName = d3_vendorPrefixes[i] + name; + if (prefixName in object) return prefixName; + } + } + var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ]; + function d3_noop() {} + d3.dispatch = function() { + var dispatch = new d3_dispatch(), i = -1, n = arguments.length; + while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); + return dispatch; + }; + function d3_dispatch() {} + d3_dispatch.prototype.on = function(type, listener) { + var i = type.indexOf("."), name = ""; + if (i >= 0) { + name = type.substring(i + 1); + type = type.substring(0, i); + } + if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener); + if (arguments.length === 2) { + if (listener == null) for (type in this) { + if (this.hasOwnProperty(type)) this[type].on(name, null); + } + return this; + } + }; + function d3_dispatch_event(dispatch) { + var listeners = [], listenerByName = new d3_Map(); + function event() { + var z = listeners, i = -1, n = z.length, l; + while (++i < n) if (l = z[i].on) l.apply(this, arguments); + return dispatch; + } + event.on = function(name, listener) { + var l = listenerByName.get(name), i; + if (arguments.length < 2) return l && l.on; + if (l) { + l.on = null; + listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1)); + listenerByName.remove(name); + } + if (listener) listeners.push(listenerByName.set(name, { + on: listener + })); + return dispatch; + }; + return event; + } + d3.event = null; + function d3_eventPreventDefault() { + d3.event.preventDefault(); + } + function d3_eventSource() { + var e = d3.event, s; + while (s = e.sourceEvent) e = s; + return e; + } + function d3_eventDispatch(target) { + var dispatch = new d3_dispatch(), i = 0, n = arguments.length; + while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch); + dispatch.of = function(thiz, argumentz) { + return function(e1) { + try { + var e0 = e1.sourceEvent = d3.event; + e1.target = target; + d3.event = e1; + dispatch[e1.type].apply(thiz, argumentz); + } finally { + d3.event = e0; + } + }; + }; + return dispatch; + } + d3.requote = function(s) { + return s.replace(d3_requote_re, "\\$&"); + }; + var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; + var d3_subclass = {}.__proto__ ? function(object, prototype) { + object.__proto__ = prototype; + } : function(object, prototype) { + for (var property in prototype) object[property] = prototype[property]; + }; + function d3_selection(groups) { + d3_subclass(groups, d3_selectionPrototype); + return groups; + } + var d3_select = function(s, n) { + return n.querySelector(s); + }, d3_selectAll = function(s, n) { + return n.querySelectorAll(s); + }, d3_selectMatcher = d3_documentElement.matches || d3_documentElement[d3_vendorSymbol(d3_documentElement, "matchesSelector")], d3_selectMatches = function(n, s) { + return d3_selectMatcher.call(n, s); + }; + if (typeof Sizzle === "function") { + d3_select = function(s, n) { + return Sizzle(s, n)[0] || null; + }; + d3_selectAll = Sizzle; + d3_selectMatches = Sizzle.matchesSelector; + } + d3.selection = function() { + return d3_selectionRoot; + }; + var d3_selectionPrototype = d3.selection.prototype = []; + d3_selectionPrototype.select = function(selector) { + var subgroups = [], subgroup, subnode, group, node; + selector = d3_selection_selector(selector); + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + subgroup.parentNode = (group = this[j]).parentNode; + for (var i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroup.push(subnode = selector.call(node, node.__data__, i, j)); + if (subnode && "__data__" in node) subnode.__data__ = node.__data__; + } else { + subgroup.push(null); + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_selector(selector) { + return typeof selector === "function" ? selector : function() { + return d3_select(selector, this); + }; + } + d3_selectionPrototype.selectAll = function(selector) { + var subgroups = [], subgroup, node; + selector = d3_selection_selectorAll(selector); + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j))); + subgroup.parentNode = node; + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_selectorAll(selector) { + return typeof selector === "function" ? selector : function() { + return d3_selectAll(selector, this); + }; + } + var d3_nsPrefix = { + svg: "http://www.w3.org/2000/svg", + xhtml: "http://www.w3.org/1999/xhtml", + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" + }; + d3.ns = { + prefix: d3_nsPrefix, + qualify: function(name) { + var i = name.indexOf(":"), prefix = name; + if (i >= 0) { + prefix = name.substring(0, i); + name = name.substring(i + 1); + } + return d3_nsPrefix.hasOwnProperty(prefix) ? { + space: d3_nsPrefix[prefix], + local: name + } : name; + } + }; + d3_selectionPrototype.attr = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") { + var node = this.node(); + name = d3.ns.qualify(name); + return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name); + } + for (value in name) this.each(d3_selection_attr(value, name[value])); + return this; + } + return this.each(d3_selection_attr(name, value)); + }; + function d3_selection_attr(name, value) { + name = d3.ns.qualify(name); + function attrNull() { + this.removeAttribute(name); + } + function attrNullNS() { + this.removeAttributeNS(name.space, name.local); + } + function attrConstant() { + this.setAttribute(name, value); + } + function attrConstantNS() { + this.setAttributeNS(name.space, name.local, value); + } + function attrFunction() { + var x = value.apply(this, arguments); + if (x == null) this.removeAttribute(name); else this.setAttribute(name, x); + } + function attrFunctionNS() { + var x = value.apply(this, arguments); + if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x); + } + return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant; + } + function d3_collapse(s) { + return s.trim().replace(/\s+/g, " "); + } + d3_selectionPrototype.classed = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") { + var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1; + if (value = node.classList) { + while (++i < n) if (!value.contains(name[i])) return false; + } else { + value = node.getAttribute("class"); + while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false; + } + return true; + } + for (value in name) this.each(d3_selection_classed(value, name[value])); + return this; + } + return this.each(d3_selection_classed(name, value)); + }; + function d3_selection_classedRe(name) { + return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g"); + } + function d3_selection_classes(name) { + return (name + "").trim().split(/^|\s+/); + } + function d3_selection_classed(name, value) { + name = d3_selection_classes(name).map(d3_selection_classedName); + var n = name.length; + function classedConstant() { + var i = -1; + while (++i < n) name[i](this, value); + } + function classedFunction() { + var i = -1, x = value.apply(this, arguments); + while (++i < n) name[i](this, x); + } + return typeof value === "function" ? classedFunction : classedConstant; + } + function d3_selection_classedName(name) { + var re = d3_selection_classedRe(name); + return function(node, value) { + if (c = node.classList) return value ? c.add(name) : c.remove(name); + var c = node.getAttribute("class") || ""; + if (value) { + re.lastIndex = 0; + if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name)); + } else { + node.setAttribute("class", d3_collapse(c.replace(re, " "))); + } + }; + } + d3_selectionPrototype.style = function(name, value, priority) { + var n = arguments.length; + if (n < 3) { + if (typeof name !== "string") { + if (n < 2) value = ""; + for (priority in name) this.each(d3_selection_style(priority, name[priority], value)); + return this; + } + if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name); + priority = ""; + } + return this.each(d3_selection_style(name, value, priority)); + }; + function d3_selection_style(name, value, priority) { + function styleNull() { + this.style.removeProperty(name); + } + function styleConstant() { + this.style.setProperty(name, value, priority); + } + function styleFunction() { + var x = value.apply(this, arguments); + if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority); + } + return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant; + } + d3_selectionPrototype.property = function(name, value) { + if (arguments.length < 2) { + if (typeof name === "string") return this.node()[name]; + for (value in name) this.each(d3_selection_property(value, name[value])); + return this; + } + return this.each(d3_selection_property(name, value)); + }; + function d3_selection_property(name, value) { + function propertyNull() { + delete this[name]; + } + function propertyConstant() { + this[name] = value; + } + function propertyFunction() { + var x = value.apply(this, arguments); + if (x == null) delete this[name]; else this[name] = x; + } + return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant; + } + d3_selectionPrototype.text = function(value) { + return arguments.length ? this.each(typeof value === "function" ? function() { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + } : value == null ? function() { + this.textContent = ""; + } : function() { + this.textContent = value; + }) : this.node().textContent; + }; + d3_selectionPrototype.html = function(value) { + return arguments.length ? this.each(typeof value === "function" ? function() { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + } : value == null ? function() { + this.innerHTML = ""; + } : function() { + this.innerHTML = value; + }) : this.node().innerHTML; + }; + d3_selectionPrototype.append = function(name) { + name = d3_selection_creator(name); + return this.select(function() { + return this.appendChild(name.apply(this, arguments)); + }); + }; + function d3_selection_creator(name) { + return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? function() { + return this.ownerDocument.createElementNS(name.space, name.local); + } : function() { + return this.ownerDocument.createElementNS(this.namespaceURI, name); + }; + } + d3_selectionPrototype.insert = function(name, before) { + name = d3_selection_creator(name); + before = d3_selection_selector(before); + return this.select(function() { + return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null); + }); + }; + d3_selectionPrototype.remove = function() { + return this.each(function() { + var parent = this.parentNode; + if (parent) parent.removeChild(this); + }); + }; + d3_selectionPrototype.data = function(value, key) { + var i = -1, n = this.length, group, node; + if (!arguments.length) { + value = new Array(n = (group = this[0]).length); + while (++i < n) { + if (node = group[i]) { + value[i] = node.__data__; + } + } + return value; + } + function bind(group, groupData) { + var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData; + if (key) { + var nodeByKeyValue = new d3_Map(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue; + for (i = -1; ++i < n; ) { + keyValue = key.call(node = group[i], node.__data__, i); + if (nodeByKeyValue.has(keyValue)) { + exitNodes[i] = node; + } else { + nodeByKeyValue.set(keyValue, node); + } + keyValues.push(keyValue); + } + for (i = -1; ++i < m; ) { + keyValue = key.call(groupData, nodeData = groupData[i], i); + if (node = nodeByKeyValue.get(keyValue)) { + updateNodes[i] = node; + node.__data__ = nodeData; + } else if (!dataByKeyValue.has(keyValue)) { + enterNodes[i] = d3_selection_dataNode(nodeData); + } + dataByKeyValue.set(keyValue, nodeData); + nodeByKeyValue.remove(keyValue); + } + for (i = -1; ++i < n; ) { + if (nodeByKeyValue.has(keyValues[i])) { + exitNodes[i] = group[i]; + } + } + } else { + for (i = -1; ++i < n0; ) { + node = group[i]; + nodeData = groupData[i]; + if (node) { + node.__data__ = nodeData; + updateNodes[i] = node; + } else { + enterNodes[i] = d3_selection_dataNode(nodeData); + } + } + for (;i < m; ++i) { + enterNodes[i] = d3_selection_dataNode(groupData[i]); + } + for (;i < n; ++i) { + exitNodes[i] = group[i]; + } + } + enterNodes.update = updateNodes; + enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode; + enter.push(enterNodes); + update.push(updateNodes); + exit.push(exitNodes); + } + var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]); + if (typeof value === "function") { + while (++i < n) { + bind(group = this[i], value.call(group, group.parentNode.__data__, i)); + } + } else { + while (++i < n) { + bind(group = this[i], value); + } + } + update.enter = function() { + return enter; + }; + update.exit = function() { + return exit; + }; + return update; + }; + function d3_selection_dataNode(data) { + return { + __data__: data + }; + } + d3_selectionPrototype.datum = function(value) { + return arguments.length ? this.property("__data__", value) : this.property("__data__"); + }; + d3_selectionPrototype.filter = function(filter) { + var subgroups = [], subgroup, group, node; + if (typeof filter !== "function") filter = d3_selection_filter(filter); + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + subgroup.parentNode = (group = this[j]).parentNode; + for (var i = 0, n = group.length; i < n; i++) { + if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { + subgroup.push(node); + } + } + } + return d3_selection(subgroups); + }; + function d3_selection_filter(selector) { + return function() { + return d3_selectMatches(this, selector); + }; + } + d3_selectionPrototype.order = function() { + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) { + if (node = group[i]) { + if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); + next = node; + } + } + } + return this; + }; + d3_selectionPrototype.sort = function(comparator) { + comparator = d3_selection_sortComparator.apply(this, arguments); + for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator); + return this.order(); + }; + function d3_selection_sortComparator(comparator) { + if (!arguments.length) comparator = d3_ascending; + return function(a, b) { + return a && b ? comparator(a.__data__, b.__data__) : !a - !b; + }; + } + d3_selectionPrototype.each = function(callback) { + return d3_selection_each(this, function(node, i, j) { + callback.call(node, node.__data__, i, j); + }); + }; + function d3_selection_each(groups, callback) { + for (var j = 0, m = groups.length; j < m; j++) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) { + if (node = group[i]) callback(node, i, j); + } + } + return groups; + } + d3_selectionPrototype.call = function(callback) { + var args = d3_array(arguments); + callback.apply(args[0] = this, args); + return this; + }; + d3_selectionPrototype.empty = function() { + return !this.node(); + }; + d3_selectionPrototype.node = function() { + for (var j = 0, m = this.length; j < m; j++) { + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + var node = group[i]; + if (node) return node; + } + } + return null; + }; + d3_selectionPrototype.size = function() { + var n = 0; + this.each(function() { + ++n; + }); + return n; + }; + function d3_selection_enter(selection) { + d3_subclass(selection, d3_selection_enterPrototype); + return selection; + } + var d3_selection_enterPrototype = []; + d3.selection.enter = d3_selection_enter; + d3.selection.enter.prototype = d3_selection_enterPrototype; + d3_selection_enterPrototype.append = d3_selectionPrototype.append; + d3_selection_enterPrototype.empty = d3_selectionPrototype.empty; + d3_selection_enterPrototype.node = d3_selectionPrototype.node; + d3_selection_enterPrototype.call = d3_selectionPrototype.call; + d3_selection_enterPrototype.size = d3_selectionPrototype.size; + d3_selection_enterPrototype.select = function(selector) { + var subgroups = [], subgroup, subnode, upgroup, group, node; + for (var j = -1, m = this.length; ++j < m; ) { + upgroup = (group = this[j]).update; + subgroups.push(subgroup = []); + subgroup.parentNode = group.parentNode; + for (var i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j)); + subnode.__data__ = node.__data__; + } else { + subgroup.push(null); + } + } + } + return d3_selection(subgroups); + }; + d3_selection_enterPrototype.insert = function(name, before) { + if (arguments.length < 2) before = d3_selection_enterInsertBefore(this); + return d3_selectionPrototype.insert.call(this, name, before); + }; + function d3_selection_enterInsertBefore(enter) { + var i0, j0; + return function(d, i, j) { + var group = enter[j].update, n = group.length, node; + if (j != j0) j0 = j, i0 = 0; + if (i >= i0) i0 = i + 1; + while (!(node = group[i0]) && ++i0 < n) ; + return node; + }; + } + d3_selectionPrototype.transition = function() { + var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = d3_transitionInherit || { + time: Date.now(), + ease: d3_ease_cubicInOut, + delay: 0, + duration: 250 + }; + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) d3_transitionNode(node, i, id, transition); + subgroup.push(node); + } + } + return d3_transition(subgroups, id); + }; + d3_selectionPrototype.interrupt = function() { + return this.each(d3_selection_interrupt); + }; + function d3_selection_interrupt() { + var lock = this.__transition__; + if (lock) ++lock.active; + } + d3.select = function(node) { + var group = [ typeof node === "string" ? d3_select(node, d3_document) : node ]; + group.parentNode = d3_documentElement; + return d3_selection([ group ]); + }; + d3.selectAll = function(nodes) { + var group = d3_array(typeof nodes === "string" ? d3_selectAll(nodes, d3_document) : nodes); + group.parentNode = d3_documentElement; + return d3_selection([ group ]); + }; + var d3_selectionRoot = d3.select(d3_documentElement); + d3_selectionPrototype.on = function(type, listener, capture) { + var n = arguments.length; + if (n < 3) { + if (typeof type !== "string") { + if (n < 2) listener = false; + for (capture in type) this.each(d3_selection_on(capture, type[capture], listener)); + return this; + } + if (n < 2) return (n = this.node()["__on" + type]) && n._; + capture = false; + } + return this.each(d3_selection_on(type, listener, capture)); + }; + function d3_selection_on(type, listener, capture) { + var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener; + if (i > 0) type = type.substring(0, i); + var filter = d3_selection_onFilters.get(type); + if (filter) type = filter, wrap = d3_selection_onFilter; + function onRemove() { + var l = this[name]; + if (l) { + this.removeEventListener(type, l, l.$); + delete this[name]; + } + } + function onAdd() { + var l = wrap(listener, d3_array(arguments)); + onRemove.call(this); + this.addEventListener(type, this[name] = l, l.$ = capture); + l._ = listener; + } + function removeAll() { + var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match; + for (var name in this) { + if (match = name.match(re)) { + var l = this[name]; + this.removeEventListener(match[1], l, l.$); + delete this[name]; + } + } + } + return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll; + } + var d3_selection_onFilters = d3.map({ + mouseenter: "mouseover", + mouseleave: "mouseout" + }); + d3_selection_onFilters.forEach(function(k) { + if ("on" + k in d3_document) d3_selection_onFilters.remove(k); + }); + function d3_selection_onListener(listener, argumentz) { + return function(e) { + var o = d3.event; + d3.event = e; + argumentz[0] = this.__data__; + try { + listener.apply(this, argumentz); + } finally { + d3.event = o; + } + }; + } + function d3_selection_onFilter(listener, argumentz) { + var l = d3_selection_onListener(listener, argumentz); + return function(e) { + var target = this, related = e.relatedTarget; + if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) { + l.call(target, e); + } + }; + } + var d3_event_dragSelect = "onselectstart" in d3_document ? null : d3_vendorSymbol(d3_documentElement.style, "userSelect"), d3_event_dragId = 0; + function d3_event_dragSuppress() { + var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault); + if (d3_event_dragSelect) { + var style = d3_documentElement.style, select = style[d3_event_dragSelect]; + style[d3_event_dragSelect] = "none"; + } + return function(suppressClick) { + w.on(name, null); + if (d3_event_dragSelect) style[d3_event_dragSelect] = select; + if (suppressClick) { + function off() { + w.on(click, null); + } + w.on(click, function() { + d3_eventPreventDefault(); + off(); + }, true); + setTimeout(off, 0); + } + }; + } + d3.mouse = function(container) { + return d3_mousePoint(container, d3_eventSource()); + }; + var d3_mouse_bug44083 = /WebKit/.test(d3_window.navigator.userAgent) ? -1 : 0; + function d3_mousePoint(container, e) { + if (e.changedTouches) e = e.changedTouches[0]; + var svg = container.ownerSVGElement || container; + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + if (d3_mouse_bug44083 < 0 && (d3_window.scrollX || d3_window.scrollY)) { + svg = d3.select("body").append("svg").style({ + position: "absolute", + top: 0, + left: 0, + margin: 0, + padding: 0, + border: "none" + }, "important"); + var ctm = svg[0][0].getScreenCTM(); + d3_mouse_bug44083 = !(ctm.f || ctm.e); + svg.remove(); + } + if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, + point.y = e.clientY; + point = point.matrixTransform(container.getScreenCTM().inverse()); + return [ point.x, point.y ]; + } + var rect = container.getBoundingClientRect(); + return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ]; + } + d3.touches = function(container, touches) { + if (arguments.length < 2) touches = d3_eventSource().touches; + return touches ? d3_array(touches).map(function(touch) { + var point = d3_mousePoint(container, touch); + point.identifier = touch.identifier; + return point; + }) : []; + }; + d3.behavior.drag = function() { + var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_behavior_dragMouseSubject, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_behavior_dragTouchSubject, "touchmove", "touchend"); + function drag() { + this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart); + } + function dragstart(id, position, subject, move, end) { + return function() { + var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject()).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(), position0 = position(parent, dragId); + if (origin) { + dragOffset = origin.apply(that, arguments); + dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ]; + } else { + dragOffset = [ 0, 0 ]; + } + dispatch({ + type: "dragstart" + }); + function moved() { + var position1 = position(parent, dragId), dx, dy; + if (!position1) return; + dx = position1[0] - position0[0]; + dy = position1[1] - position0[1]; + dragged |= dx | dy; + position0 = position1; + dispatch({ + type: "drag", + x: position1[0] + dragOffset[0], + y: position1[1] + dragOffset[1], + dx: dx, + dy: dy + }); + } + function ended() { + if (!position(parent, dragId)) return; + dragSubject.on(move + dragName, null).on(end + dragName, null); + dragRestore(dragged && d3.event.target === target); + dispatch({ + type: "dragend" + }); + } + }; + } + drag.origin = function(x) { + if (!arguments.length) return origin; + origin = x; + return drag; + }; + return d3.rebind(drag, event, "on"); + }; + function d3_behavior_dragTouchId() { + return d3.event.changedTouches[0].identifier; + } + function d3_behavior_dragTouchSubject() { + return d3.event.target; + } + function d3_behavior_dragMouseSubject() { + return d3_window; + } + var Ï€ = Math.PI, Ï„ = 2 * Ï€, halfÏ€ = Ï€ / 2, ε = 1e-6, ε2 = ε * ε, d3_radians = Ï€ / 180, d3_degrees = 180 / Ï€; + function d3_sgn(x) { + return x > 0 ? 1 : x < 0 ? -1 : 0; + } + function d3_cross2d(a, b, c) { + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); + } + function d3_acos(x) { + return x > 1 ? 0 : x < -1 ? Ï€ : Math.acos(x); + } + function d3_asin(x) { + return x > 1 ? halfÏ€ : x < -1 ? -halfÏ€ : Math.asin(x); + } + function d3_sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; + } + function d3_cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; + } + function d3_tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); + } + function d3_haversin(x) { + return (x = Math.sin(x / 2)) * x; + } + var Ï = Math.SQRT2, Ï2 = 2, Ï4 = 4; + d3.interpolateZoom = function(p0, p1) { + var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2]; + var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + Ï4 * d2) / (2 * w0 * Ï2 * d1), b1 = (w1 * w1 - w0 * w0 - Ï4 * d2) / (2 * w1 * Ï2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / Ï; + function interpolate(t) { + var s = t * S; + if (dr) { + var coshr0 = d3_cosh(r0), u = w0 / (Ï2 * d1) * (coshr0 * d3_tanh(Ï * s + r0) - d3_sinh(r0)); + return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(Ï * s + r0) ]; + } + return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(Ï * s) ]; + } + interpolate.duration = S * 1e3; + return interpolate; + }; + d3.behavior.zoom = function() { + var view = { + x: 0, + y: 0, + k: 1 + }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1; + function zoom(g) { + g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted); + } + zoom.event = function(g) { + g.each(function() { + var dispatch = event.of(this, arguments), view1 = view; + if (d3_transitionInheritId) { + d3.select(this).transition().each("start.zoom", function() { + view = this.__chart__ || { + x: 0, + y: 0, + k: 1 + }; + zoomstarted(dispatch); + }).tween("zoom:zoom", function() { + var dx = size[0], dy = size[1], cx = dx / 2, cy = dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]); + return function(t) { + var l = i(t), k = dx / l[2]; + this.__chart__ = view = { + x: cx - l[0] * k, + y: cy - l[1] * k, + k: k + }; + zoomed(dispatch); + }; + }).each("end.zoom", function() { + zoomended(dispatch); + }); + } else { + this.__chart__ = view; + zoomstarted(dispatch); + zoomed(dispatch); + zoomended(dispatch); + } + }); + }; + zoom.translate = function(_) { + if (!arguments.length) return [ view.x, view.y ]; + view = { + x: +_[0], + y: +_[1], + k: view.k + }; + rescale(); + return zoom; + }; + zoom.scale = function(_) { + if (!arguments.length) return view.k; + view = { + x: view.x, + y: view.y, + k: +_ + }; + rescale(); + return zoom; + }; + zoom.scaleExtent = function(_) { + if (!arguments.length) return scaleExtent; + scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ]; + return zoom; + }; + zoom.center = function(_) { + if (!arguments.length) return center; + center = _ && [ +_[0], +_[1] ]; + return zoom; + }; + zoom.size = function(_) { + if (!arguments.length) return size; + size = _ && [ +_[0], +_[1] ]; + return zoom; + }; + zoom.x = function(z) { + if (!arguments.length) return x1; + x1 = z; + x0 = z.copy(); + view = { + x: 0, + y: 0, + k: 1 + }; + return zoom; + }; + zoom.y = function(z) { + if (!arguments.length) return y1; + y1 = z; + y0 = z.copy(); + view = { + x: 0, + y: 0, + k: 1 + }; + return zoom; + }; + function location(p) { + return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ]; + } + function point(l) { + return [ l[0] * view.k + view.x, l[1] * view.k + view.y ]; + } + function scaleTo(s) { + view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s)); + } + function translateTo(p, l) { + l = point(l); + view.x += p[0] - l[0]; + view.y += p[1] - l[1]; + } + function rescale() { + if (x1) x1.domain(x0.range().map(function(x) { + return (x - view.x) / view.k; + }).map(x0.invert)); + if (y1) y1.domain(y0.range().map(function(y) { + return (y - view.y) / view.k; + }).map(y0.invert)); + } + function zoomstarted(dispatch) { + dispatch({ + type: "zoomstart" + }); + } + function zoomed(dispatch) { + rescale(); + dispatch({ + type: "zoom", + scale: view.k, + translate: [ view.x, view.y ] + }); + } + function zoomended(dispatch) { + dispatch({ + type: "zoomend" + }); + } + function mousedowned() { + var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(); + d3_selection_interrupt.call(that); + zoomstarted(dispatch); + function moved() { + dragged = 1; + translateTo(d3.mouse(that), location0); + zoomed(dispatch); + } + function ended() { + subject.on(mousemove, null).on(mouseup, null); + dragRestore(dragged && d3.event.target === target); + zoomended(dispatch); + } + } + function touchstarted() { + var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that).on(mousedown, null).on(touchstart, started), dragRestore = d3_event_dragSuppress(); + d3_selection_interrupt.call(that); + started(); + zoomstarted(dispatch); + function relocate() { + var touches = d3.touches(that); + scale0 = view.k; + touches.forEach(function(t) { + if (t.identifier in locations0) locations0[t.identifier] = location(t); + }); + return touches; + } + function started() { + var target = d3.event.target; + d3.select(target).on(touchmove, moved).on(touchend, ended); + targets.push(target); + var changed = d3.event.changedTouches; + for (var i = 0, n = changed.length; i < n; ++i) { + locations0[changed[i].identifier] = null; + } + var touches = relocate(), now = Date.now(); + if (touches.length === 1) { + if (now - touchtime < 500) { + var p = touches[0], l = locations0[p.identifier]; + scaleTo(view.k * 2); + translateTo(p, l); + d3_eventPreventDefault(); + zoomed(dispatch); + } + touchtime = now; + } else if (touches.length > 1) { + var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1]; + distance0 = dx * dx + dy * dy; + } + } + function moved() { + var touches = d3.touches(that), p0, l0, p1, l1; + for (var i = 0, n = touches.length; i < n; ++i, l1 = null) { + p1 = touches[i]; + if (l1 = locations0[p1.identifier]) { + if (l0) break; + p0 = p1, l0 = l1; + } + } + if (l1) { + var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0); + p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ]; + l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ]; + scaleTo(scale1 * scale0); + } + touchtime = null; + translateTo(p0, l0); + zoomed(dispatch); + } + function ended() { + if (d3.event.touches.length) { + var changed = d3.event.changedTouches; + for (var i = 0, n = changed.length; i < n; ++i) { + delete locations0[changed[i].identifier]; + } + for (var identifier in locations0) { + return void relocate(); + } + } + d3.selectAll(targets).on(zoomName, null); + subject.on(mousedown, mousedowned).on(touchstart, touchstarted); + dragRestore(); + zoomended(dispatch); + } + } + function mousewheeled() { + var dispatch = event.of(this, arguments); + if (mousewheelTimer) clearTimeout(mousewheelTimer); else translate0 = location(center0 = center || d3.mouse(this)), + d3_selection_interrupt.call(this), zoomstarted(dispatch); + mousewheelTimer = setTimeout(function() { + mousewheelTimer = null; + zoomended(dispatch); + }, 50); + d3_eventPreventDefault(); + scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k); + translateTo(center0, translate0); + zoomed(dispatch); + } + function dblclicked() { + var dispatch = event.of(this, arguments), p = d3.mouse(this), l = location(p), k = Math.log(view.k) / Math.LN2; + zoomstarted(dispatch); + scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1)); + translateTo(p, l); + zoomed(dispatch); + zoomended(dispatch); + } + return d3.rebind(zoom, event, "on"); + }; + var d3_behavior_zoomInfinity = [ 0, Infinity ]; + var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() { + return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1); + }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() { + return d3.event.wheelDelta; + }, "mousewheel") : (d3_behavior_zoomDelta = function() { + return -d3.event.detail; + }, "MozMousePixelScroll"); + d3.color = d3_color; + function d3_color() {} + d3_color.prototype.toString = function() { + return this.rgb() + ""; + }; + d3.hsl = d3_hsl; + function d3_hsl(h, s, l) { + return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l); + } + var d3_hslPrototype = d3_hsl.prototype = new d3_color(); + d3_hslPrototype.brighter = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_hsl(this.h, this.s, this.l / k); + }; + d3_hslPrototype.darker = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_hsl(this.h, this.s, k * this.l); + }; + d3_hslPrototype.rgb = function() { + return d3_hsl_rgb(this.h, this.s, this.l); + }; + function d3_hsl_rgb(h, s, l) { + var m1, m2; + h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h; + s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s; + l = l < 0 ? 0 : l > 1 ? 1 : l; + m2 = l <= .5 ? l * (1 + s) : l + s - l * s; + m1 = 2 * l - m2; + function v(h) { + if (h > 360) h -= 360; else if (h < 0) h += 360; + if (h < 60) return m1 + (m2 - m1) * h / 60; + if (h < 180) return m2; + if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60; + return m1; + } + function vv(h) { + return Math.round(v(h) * 255); + } + return new d3_rgb(vv(h + 120), vv(h), vv(h - 120)); + } + d3.hcl = d3_hcl; + function d3_hcl(h, c, l) { + return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l); + } + var d3_hclPrototype = d3_hcl.prototype = new d3_color(); + d3_hclPrototype.brighter = function(k) { + return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1))); + }; + d3_hclPrototype.darker = function(k) { + return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1))); + }; + d3_hclPrototype.rgb = function() { + return d3_hcl_lab(this.h, this.c, this.l).rgb(); + }; + function d3_hcl_lab(h, c, l) { + if (isNaN(h)) h = 0; + if (isNaN(c)) c = 0; + return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c); + } + d3.lab = d3_lab; + function d3_lab(l, a, b) { + return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b); + } + var d3_lab_K = 18; + var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883; + var d3_labPrototype = d3_lab.prototype = new d3_color(); + d3_labPrototype.brighter = function(k) { + return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + }; + d3_labPrototype.darker = function(k) { + return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b); + }; + d3_labPrototype.rgb = function() { + return d3_lab_rgb(this.l, this.a, this.b); + }; + function d3_lab_rgb(l, a, b) { + var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200; + x = d3_lab_xyz(x) * d3_lab_X; + y = d3_lab_xyz(y) * d3_lab_Y; + z = d3_lab_xyz(z) * d3_lab_Z; + return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z)); + } + function d3_lab_hcl(l, a, b) { + return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l); + } + function d3_lab_xyz(x) { + return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037; + } + function d3_xyz_lab(x) { + return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29; + } + function d3_xyz_rgb(r) { + return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055)); + } + d3.rgb = d3_rgb; + function d3_rgb(r, g, b) { + return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b); + } + function d3_rgbNumber(value) { + return new d3_rgb(value >> 16, value >> 8 & 255, value & 255); + } + function d3_rgbString(value) { + return d3_rgbNumber(value) + ""; + } + var d3_rgbPrototype = d3_rgb.prototype = new d3_color(); + d3_rgbPrototype.brighter = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + var r = this.r, g = this.g, b = this.b, i = 30; + if (!r && !g && !b) return new d3_rgb(i, i, i); + if (r && r < i) r = i; + if (g && g < i) g = i; + if (b && b < i) b = i; + return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k)); + }; + d3_rgbPrototype.darker = function(k) { + k = Math.pow(.7, arguments.length ? k : 1); + return new d3_rgb(k * this.r, k * this.g, k * this.b); + }; + d3_rgbPrototype.hsl = function() { + return d3_rgb_hsl(this.r, this.g, this.b); + }; + d3_rgbPrototype.toString = function() { + return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b); + }; + function d3_rgb_hex(v) { + return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16); + } + function d3_rgb_parse(format, rgb, hsl) { + var r = 0, g = 0, b = 0, m1, m2, color; + m1 = /([a-z]+)\((.*)\)/i.exec(format); + if (m1) { + m2 = m1[2].split(","); + switch (m1[1]) { + case "hsl": + { + return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100); + } + + case "rgb": + { + return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2])); + } + } + } + if (color = d3_rgb_names.get(format)) return rgb(color.r, color.g, color.b); + if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.substring(1), 16))) { + if (format.length === 4) { + r = (color & 3840) >> 4; + r = r >> 4 | r; + g = color & 240; + g = g >> 4 | g; + b = color & 15; + b = b << 4 | b; + } else if (format.length === 7) { + r = (color & 16711680) >> 16; + g = (color & 65280) >> 8; + b = color & 255; + } + } + return rgb(r, g, b); + } + function d3_rgb_hsl(r, g, b) { + var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2; + if (d) { + s = l < .5 ? d / (max + min) : d / (2 - max - min); + if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4; + h *= 60; + } else { + h = NaN; + s = l > 0 && l < 1 ? 0 : h; + } + return new d3_hsl(h, s, l); + } + function d3_rgb_lab(r, g, b) { + r = d3_rgb_xyz(r); + g = d3_rgb_xyz(g); + b = d3_rgb_xyz(b); + var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z); + return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z)); + } + function d3_rgb_xyz(r) { + return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4); + } + function d3_rgb_parseNumber(c) { + var f = parseFloat(c); + return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f; + } + var d3_rgb_names = d3.map({ + aliceblue: 15792383, + antiquewhite: 16444375, + aqua: 65535, + aquamarine: 8388564, + azure: 15794175, + beige: 16119260, + bisque: 16770244, + black: 0, + blanchedalmond: 16772045, + blue: 255, + blueviolet: 9055202, + brown: 10824234, + burlywood: 14596231, + cadetblue: 6266528, + chartreuse: 8388352, + chocolate: 13789470, + coral: 16744272, + cornflowerblue: 6591981, + cornsilk: 16775388, + crimson: 14423100, + cyan: 65535, + darkblue: 139, + darkcyan: 35723, + darkgoldenrod: 12092939, + darkgray: 11119017, + darkgreen: 25600, + darkgrey: 11119017, + darkkhaki: 12433259, + darkmagenta: 9109643, + darkolivegreen: 5597999, + darkorange: 16747520, + darkorchid: 10040012, + darkred: 9109504, + darksalmon: 15308410, + darkseagreen: 9419919, + darkslateblue: 4734347, + darkslategray: 3100495, + darkslategrey: 3100495, + darkturquoise: 52945, + darkviolet: 9699539, + deeppink: 16716947, + deepskyblue: 49151, + dimgray: 6908265, + dimgrey: 6908265, + dodgerblue: 2003199, + firebrick: 11674146, + floralwhite: 16775920, + forestgreen: 2263842, + fuchsia: 16711935, + gainsboro: 14474460, + ghostwhite: 16316671, + gold: 16766720, + goldenrod: 14329120, + gray: 8421504, + green: 32768, + greenyellow: 11403055, + grey: 8421504, + honeydew: 15794160, + hotpink: 16738740, + indianred: 13458524, + indigo: 4915330, + ivory: 16777200, + khaki: 15787660, + lavender: 15132410, + lavenderblush: 16773365, + lawngreen: 8190976, + lemonchiffon: 16775885, + lightblue: 11393254, + lightcoral: 15761536, + lightcyan: 14745599, + lightgoldenrodyellow: 16448210, + lightgray: 13882323, + lightgreen: 9498256, + lightgrey: 13882323, + lightpink: 16758465, + lightsalmon: 16752762, + lightseagreen: 2142890, + lightskyblue: 8900346, + lightslategray: 7833753, + lightslategrey: 7833753, + lightsteelblue: 11584734, + lightyellow: 16777184, + lime: 65280, + limegreen: 3329330, + linen: 16445670, + magenta: 16711935, + maroon: 8388608, + mediumaquamarine: 6737322, + mediumblue: 205, + mediumorchid: 12211667, + mediumpurple: 9662683, + mediumseagreen: 3978097, + mediumslateblue: 8087790, + mediumspringgreen: 64154, + mediumturquoise: 4772300, + mediumvioletred: 13047173, + midnightblue: 1644912, + mintcream: 16121850, + mistyrose: 16770273, + moccasin: 16770229, + navajowhite: 16768685, + navy: 128, + oldlace: 16643558, + olive: 8421376, + olivedrab: 7048739, + orange: 16753920, + orangered: 16729344, + orchid: 14315734, + palegoldenrod: 15657130, + palegreen: 10025880, + paleturquoise: 11529966, + palevioletred: 14381203, + papayawhip: 16773077, + peachpuff: 16767673, + peru: 13468991, + pink: 16761035, + plum: 14524637, + powderblue: 11591910, + purple: 8388736, + red: 16711680, + rosybrown: 12357519, + royalblue: 4286945, + saddlebrown: 9127187, + salmon: 16416882, + sandybrown: 16032864, + seagreen: 3050327, + seashell: 16774638, + sienna: 10506797, + silver: 12632256, + skyblue: 8900331, + slateblue: 6970061, + slategray: 7372944, + slategrey: 7372944, + snow: 16775930, + springgreen: 65407, + steelblue: 4620980, + tan: 13808780, + teal: 32896, + thistle: 14204888, + tomato: 16737095, + turquoise: 4251856, + violet: 15631086, + wheat: 16113331, + white: 16777215, + whitesmoke: 16119285, + yellow: 16776960, + yellowgreen: 10145074 + }); + d3_rgb_names.forEach(function(key, value) { + d3_rgb_names.set(key, d3_rgbNumber(value)); + }); + function d3_functor(v) { + return typeof v === "function" ? v : function() { + return v; + }; + } + d3.functor = d3_functor; + function d3_identity(d) { + return d; + } + d3.xhr = d3_xhrType(d3_identity); + function d3_xhrType(response) { + return function(url, mimeType, callback) { + if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, + mimeType = null; + return d3_xhr(url, mimeType, response, callback); + }; + } + function d3_xhr(url, mimeType, response, callback) { + var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null; + if (d3_window.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); + "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() { + request.readyState > 3 && respond(); + }; + function respond() { + var status = request.status, result; + if (!status && request.responseText || status >= 200 && status < 300 || status === 304) { + try { + result = response.call(xhr, request); + } catch (e) { + dispatch.error.call(xhr, e); + return; + } + dispatch.load.call(xhr, result); + } else { + dispatch.error.call(xhr, request); + } + } + request.onprogress = function(event) { + var o = d3.event; + d3.event = event; + try { + dispatch.progress.call(xhr, request); + } finally { + d3.event = o; + } + }; + xhr.header = function(name, value) { + name = (name + "").toLowerCase(); + if (arguments.length < 2) return headers[name]; + if (value == null) delete headers[name]; else headers[name] = value + ""; + return xhr; + }; + xhr.mimeType = function(value) { + if (!arguments.length) return mimeType; + mimeType = value == null ? null : value + ""; + return xhr; + }; + xhr.responseType = function(value) { + if (!arguments.length) return responseType; + responseType = value; + return xhr; + }; + xhr.response = function(value) { + response = value; + return xhr; + }; + [ "get", "post" ].forEach(function(method) { + xhr[method] = function() { + return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments))); + }; + }); + xhr.send = function(method, data, callback) { + if (arguments.length === 2 && typeof data === "function") callback = data, data = null; + request.open(method, url, true); + if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*"; + if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]); + if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType); + if (responseType != null) request.responseType = responseType; + if (callback != null) xhr.on("error", callback).on("load", function(request) { + callback(null, request); + }); + dispatch.beforesend.call(xhr, request); + request.send(data == null ? null : data); + return xhr; + }; + xhr.abort = function() { + request.abort(); + return xhr; + }; + d3.rebind(xhr, dispatch, "on"); + return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback)); + } + function d3_xhr_fixCallback(callback) { + return callback.length === 1 ? function(error, request) { + callback(error == null ? request : null); + } : callback; + } + d3.dsv = function(delimiter, mimeType) { + var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0); + function dsv(url, row, callback) { + if (arguments.length < 3) callback = row, row = null; + var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback); + xhr.row = function(_) { + return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row; + }; + return xhr; + } + function response(request) { + return dsv.parse(request.responseText); + } + function typedResponse(f) { + return function(request) { + return dsv.parse(request.responseText, f); + }; + } + dsv.parse = function(text, f) { + var o; + return dsv.parseRows(text, function(row, i) { + if (o) return o(row, i - 1); + var a = new Function("d", "return {" + row.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + "]"; + }).join(",") + "}"); + o = f ? function(row, i) { + return f(a(row), i); + } : a; + }); + }; + dsv.parseRows = function(text, f) { + var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol; + function token() { + if (I >= N) return EOF; + if (eol) return eol = false, EOL; + var j = I; + if (text.charCodeAt(j) === 34) { + var i = j; + while (i++ < N) { + if (text.charCodeAt(i) === 34) { + if (text.charCodeAt(i + 1) !== 34) break; + ++i; + } + } + I = i + 2; + var c = text.charCodeAt(i + 1); + if (c === 13) { + eol = true; + if (text.charCodeAt(i + 2) === 10) ++I; + } else if (c === 10) { + eol = true; + } + return text.substring(j + 1, i).replace(/""/g, '"'); + } + while (I < N) { + var c = text.charCodeAt(I++), k = 1; + if (c === 10) eol = true; else if (c === 13) { + eol = true; + if (text.charCodeAt(I) === 10) ++I, ++k; + } else if (c !== delimiterCode) continue; + return text.substring(j, I - k); + } + return text.substring(j); + } + while ((t = token()) !== EOF) { + var a = []; + while (t !== EOL && t !== EOF) { + a.push(t); + t = token(); + } + if (f && !(a = f(a, n++))) continue; + rows.push(a); + } + return rows; + }; + dsv.format = function(rows) { + if (Array.isArray(rows[0])) return dsv.formatRows(rows); + var fieldSet = new d3_Set(), fields = []; + rows.forEach(function(row) { + for (var field in row) { + if (!fieldSet.has(field)) { + fields.push(fieldSet.add(field)); + } + } + }); + return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) { + return fields.map(function(field) { + return formatValue(row[field]); + }).join(delimiter); + })).join("\n"); + }; + dsv.formatRows = function(rows) { + return rows.map(formatRow).join("\n"); + }; + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } + function formatValue(text) { + return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text; + } + return dsv; + }; + d3.csv = d3.dsv(",", "text/csv"); + d3.tsv = d3.dsv(" ", "text/tab-separated-values"); + d3.touch = function(container, touches, identifier) { + if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches; + if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) { + if ((touch = touches[i]).identifier === identifier) { + return d3_mousePoint(container, touch); + } + } + }; + var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, "requestAnimationFrame")] || function(callback) { + setTimeout(callback, 17); + }; + d3.timer = function(callback, delay, then) { + var n = arguments.length; + if (n < 2) delay = 0; + if (n < 3) then = Date.now(); + var time = then + delay, timer = { + c: callback, + t: time, + f: false, + n: null + }; + if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer; + d3_timer_queueTail = timer; + if (!d3_timer_interval) { + d3_timer_timeout = clearTimeout(d3_timer_timeout); + d3_timer_interval = 1; + d3_timer_frame(d3_timer_step); + } + }; + function d3_timer_step() { + var now = d3_timer_mark(), delay = d3_timer_sweep() - now; + if (delay > 24) { + if (isFinite(delay)) { + clearTimeout(d3_timer_timeout); + d3_timer_timeout = setTimeout(d3_timer_step, delay); + } + d3_timer_interval = 0; + } else { + d3_timer_interval = 1; + d3_timer_frame(d3_timer_step); + } + } + d3.timer.flush = function() { + d3_timer_mark(); + d3_timer_sweep(); + }; + function d3_timer_mark() { + var now = Date.now(); + d3_timer_active = d3_timer_queueHead; + while (d3_timer_active) { + if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t); + d3_timer_active = d3_timer_active.n; + } + return now; + } + function d3_timer_sweep() { + var t0, t1 = d3_timer_queueHead, time = Infinity; + while (t1) { + if (t1.f) { + t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n; + } else { + if (t1.t < time) time = t1.t; + t1 = (t0 = t1).n; + } + } + d3_timer_queueTail = t0; + return time; + } + function d3_format_precision(x, p) { + return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1); + } + d3.round = function(x, n) { + return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x); + }; + var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix); + d3.formatPrefix = function(value, precision) { + var i = 0; + if (value) { + if (value < 0) value *= -1; + if (precision) value = d3.round(value, d3_format_precision(value, precision)); + i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10); + i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3)); + } + return d3_formatPrefixes[8 + i / 3]; + }; + function d3_formatPrefix(d, i) { + var k = Math.pow(10, abs(8 - i) * 3); + return { + scale: i > 8 ? function(d) { + return d / k; + } : function(d) { + return d * k; + }, + symbol: d + }; + } + function d3_locale_numberFormat(locale) { + var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping ? function(value) { + var i = value.length, t = [], j = 0, g = locale_grouping[0]; + while (i > 0 && g > 0) { + t.push(value.substring(i -= g, i + g)); + g = locale_grouping[j = (j + 1) % locale_grouping.length]; + } + return t.reverse().join(locale_thousands); + } : d3_identity; + return function(specifier) { + var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false; + if (precision) precision = +precision.substring(1); + if (zfill || fill === "0" && align === "=") { + zfill = fill = "0"; + align = "="; + if (comma) width -= Math.floor((width - 1) / 4); + } + switch (type) { + case "n": + comma = true; + type = "g"; + break; + + case "%": + scale = 100; + suffix = "%"; + type = "f"; + break; + + case "p": + scale = 100; + suffix = "%"; + type = "r"; + break; + + case "b": + case "o": + case "x": + case "X": + if (symbol === "#") prefix = "0" + type.toLowerCase(); + + case "c": + case "d": + integer = true; + precision = 0; + break; + + case "s": + scale = -1; + type = "r"; + break; + } + if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1]; + if (type == "r" && !precision) type = "g"; + if (precision != null) { + if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision)); + } + type = d3_format_types.get(type) || d3_format_typeDefault; + var zcomma = zfill && comma; + return function(value) { + var fullSuffix = suffix; + if (integer && value % 1) return ""; + var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign; + if (scale < 0) { + var unit = d3.formatPrefix(value, precision); + value = unit.scale(value); + fullSuffix = unit.symbol + suffix; + } else { + value *= scale; + } + value = type(value, precision); + var i = value.lastIndexOf("."), before = i < 0 ? value : value.substring(0, i), after = i < 0 ? "" : locale_decimal + value.substring(i + 1); + if (!zfill && comma) before = formatGroup(before); + var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : ""; + if (zcomma) before = formatGroup(padding + before); + negative += prefix; + value = before + after; + return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix; + }; + }; + } + var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i; + var d3_format_types = d3.map({ + b: function(x) { + return x.toString(2); + }, + c: function(x) { + return String.fromCharCode(x); + }, + o: function(x) { + return x.toString(8); + }, + x: function(x) { + return x.toString(16); + }, + X: function(x) { + return x.toString(16).toUpperCase(); + }, + g: function(x, p) { + return x.toPrecision(p); + }, + e: function(x, p) { + return x.toExponential(p); + }, + f: function(x, p) { + return x.toFixed(p); + }, + r: function(x, p) { + return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p)))); + } + }); + function d3_format_typeDefault(x) { + return x + ""; + } + var d3_time = d3.time = {}, d3_date = Date; + function d3_date_utc() { + this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]); + } + d3_date_utc.prototype = { + getDate: function() { + return this._.getUTCDate(); + }, + getDay: function() { + return this._.getUTCDay(); + }, + getFullYear: function() { + return this._.getUTCFullYear(); + }, + getHours: function() { + return this._.getUTCHours(); + }, + getMilliseconds: function() { + return this._.getUTCMilliseconds(); + }, + getMinutes: function() { + return this._.getUTCMinutes(); + }, + getMonth: function() { + return this._.getUTCMonth(); + }, + getSeconds: function() { + return this._.getUTCSeconds(); + }, + getTime: function() { + return this._.getTime(); + }, + getTimezoneOffset: function() { + return 0; + }, + valueOf: function() { + return this._.valueOf(); + }, + setDate: function() { + d3_time_prototype.setUTCDate.apply(this._, arguments); + }, + setDay: function() { + d3_time_prototype.setUTCDay.apply(this._, arguments); + }, + setFullYear: function() { + d3_time_prototype.setUTCFullYear.apply(this._, arguments); + }, + setHours: function() { + d3_time_prototype.setUTCHours.apply(this._, arguments); + }, + setMilliseconds: function() { + d3_time_prototype.setUTCMilliseconds.apply(this._, arguments); + }, + setMinutes: function() { + d3_time_prototype.setUTCMinutes.apply(this._, arguments); + }, + setMonth: function() { + d3_time_prototype.setUTCMonth.apply(this._, arguments); + }, + setSeconds: function() { + d3_time_prototype.setUTCSeconds.apply(this._, arguments); + }, + setTime: function() { + d3_time_prototype.setTime.apply(this._, arguments); + } + }; + var d3_time_prototype = Date.prototype; + function d3_time_interval(local, step, number) { + function round(date) { + var d0 = local(date), d1 = offset(d0, 1); + return date - d0 < d1 - date ? d0 : d1; + } + function ceil(date) { + step(date = local(new d3_date(date - 1)), 1); + return date; + } + function offset(date, k) { + step(date = new d3_date(+date), k); + return date; + } + function range(t0, t1, dt) { + var time = ceil(t0), times = []; + if (dt > 1) { + while (time < t1) { + if (!(number(time) % dt)) times.push(new Date(+time)); + step(time, 1); + } + } else { + while (time < t1) times.push(new Date(+time)), step(time, 1); + } + return times; + } + function range_utc(t0, t1, dt) { + try { + d3_date = d3_date_utc; + var utc = new d3_date_utc(); + utc._ = t0; + return range(utc, t1, dt); + } finally { + d3_date = Date; + } + } + local.floor = local; + local.round = round; + local.ceil = ceil; + local.offset = offset; + local.range = range; + var utc = local.utc = d3_time_interval_utc(local); + utc.floor = utc; + utc.round = d3_time_interval_utc(round); + utc.ceil = d3_time_interval_utc(ceil); + utc.offset = d3_time_interval_utc(offset); + utc.range = range_utc; + return local; + } + function d3_time_interval_utc(method) { + return function(date, k) { + try { + d3_date = d3_date_utc; + var utc = new d3_date_utc(); + utc._ = date; + return method(utc, k)._; + } finally { + d3_date = Date; + } + }; + } + d3_time.year = d3_time_interval(function(date) { + date = d3_time.day(date); + date.setMonth(0, 1); + return date; + }, function(date, offset) { + date.setFullYear(date.getFullYear() + offset); + }, function(date) { + return date.getFullYear(); + }); + d3_time.years = d3_time.year.range; + d3_time.years.utc = d3_time.year.utc.range; + d3_time.day = d3_time_interval(function(date) { + var day = new d3_date(2e3, 0); + day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate()); + return day; + }, function(date, offset) { + date.setDate(date.getDate() + offset); + }, function(date) { + return date.getDate() - 1; + }); + d3_time.days = d3_time.day.range; + d3_time.days.utc = d3_time.day.utc.range; + d3_time.dayOfYear = function(date) { + var year = d3_time.year(date); + return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5); + }; + [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) { + i = 7 - i; + var interval = d3_time[day] = d3_time_interval(function(date) { + (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7); + return date; + }, function(date, offset) { + date.setDate(date.getDate() + Math.floor(offset) * 7); + }, function(date) { + var day = d3_time.year(date).getDay(); + return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i); + }); + d3_time[day + "s"] = interval.range; + d3_time[day + "s"].utc = interval.utc.range; + d3_time[day + "OfYear"] = function(date) { + var day = d3_time.year(date).getDay(); + return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7); + }; + }); + d3_time.week = d3_time.sunday; + d3_time.weeks = d3_time.sunday.range; + d3_time.weeks.utc = d3_time.sunday.utc.range; + d3_time.weekOfYear = d3_time.sundayOfYear; + function d3_locale_timeFormat(locale) { + var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths; + function d3_time_format(template) { + var n = template.length; + function format(date) { + var string = [], i = -1, j = 0, c, p, f; + while (++i < n) { + if (template.charCodeAt(i) === 37) { + string.push(template.substring(j, i)); + if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i); + if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p); + string.push(c); + j = i + 1; + } + } + string.push(template.substring(j, i)); + return string.join(""); + } + format.parse = function(string) { + var d = { + y: 1900, + m: 0, + d: 1, + H: 0, + M: 0, + S: 0, + L: 0, + Z: null + }, i = d3_time_parse(d, template, string, 0); + if (i != string.length) return null; + if ("p" in d) d.H = d.H % 12 + d.p * 12; + var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)(); + if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("w" in d && ("W" in d || "U" in d)) { + date.setFullYear(d.y, 0, 1); + date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7); + } else date.setFullYear(d.y, d.m, d.d); + date.setHours(d.H + Math.floor(d.Z / 100), d.M + d.Z % 100, d.S, d.L); + return localZ ? date._ : date; + }; + format.toString = function() { + return template; + }; + return format; + } + function d3_time_parse(date, template, string, j) { + var c, p, t, i = 0, n = template.length, m = string.length; + while (i < n) { + if (j >= m) return -1; + c = template.charCodeAt(i++); + if (c === 37) { + t = template.charAt(i++); + p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t]; + if (!p || (j = p(date, string, j)) < 0) return -1; + } else if (c != string.charCodeAt(j++)) { + return -1; + } + } + return j; + } + d3_time_format.utc = function(template) { + var local = d3_time_format(template); + function format(date) { + try { + d3_date = d3_date_utc; + var utc = new d3_date(); + utc._ = date; + return local(utc); + } finally { + d3_date = Date; + } + } + format.parse = function(string) { + try { + d3_date = d3_date_utc; + var date = local.parse(string); + return date && date._; + } finally { + d3_date = Date; + } + }; + format.toString = local.toString; + return format; + }; + d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti; + var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths); + locale_periods.forEach(function(p, i) { + d3_time_periodLookup.set(p.toLowerCase(), i); + }); + var d3_time_formats = { + a: function(d) { + return locale_shortDays[d.getDay()]; + }, + A: function(d) { + return locale_days[d.getDay()]; + }, + b: function(d) { + return locale_shortMonths[d.getMonth()]; + }, + B: function(d) { + return locale_months[d.getMonth()]; + }, + c: d3_time_format(locale_dateTime), + d: function(d, p) { + return d3_time_formatPad(d.getDate(), p, 2); + }, + e: function(d, p) { + return d3_time_formatPad(d.getDate(), p, 2); + }, + H: function(d, p) { + return d3_time_formatPad(d.getHours(), p, 2); + }, + I: function(d, p) { + return d3_time_formatPad(d.getHours() % 12 || 12, p, 2); + }, + j: function(d, p) { + return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3); + }, + L: function(d, p) { + return d3_time_formatPad(d.getMilliseconds(), p, 3); + }, + m: function(d, p) { + return d3_time_formatPad(d.getMonth() + 1, p, 2); + }, + M: function(d, p) { + return d3_time_formatPad(d.getMinutes(), p, 2); + }, + p: function(d) { + return locale_periods[+(d.getHours() >= 12)]; + }, + S: function(d, p) { + return d3_time_formatPad(d.getSeconds(), p, 2); + }, + U: function(d, p) { + return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2); + }, + w: function(d) { + return d.getDay(); + }, + W: function(d, p) { + return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2); + }, + x: d3_time_format(locale_date), + X: d3_time_format(locale_time), + y: function(d, p) { + return d3_time_formatPad(d.getFullYear() % 100, p, 2); + }, + Y: function(d, p) { + return d3_time_formatPad(d.getFullYear() % 1e4, p, 4); + }, + Z: d3_time_zone, + "%": function() { + return "%"; + } + }; + var d3_time_parsers = { + a: d3_time_parseWeekdayAbbrev, + A: d3_time_parseWeekday, + b: d3_time_parseMonthAbbrev, + B: d3_time_parseMonth, + c: d3_time_parseLocaleFull, + d: d3_time_parseDay, + e: d3_time_parseDay, + H: d3_time_parseHour24, + I: d3_time_parseHour24, + j: d3_time_parseDayOfYear, + L: d3_time_parseMilliseconds, + m: d3_time_parseMonthNumber, + M: d3_time_parseMinutes, + p: d3_time_parseAmPm, + S: d3_time_parseSeconds, + U: d3_time_parseWeekNumberSunday, + w: d3_time_parseWeekdayNumber, + W: d3_time_parseWeekNumberMonday, + x: d3_time_parseLocaleDate, + X: d3_time_parseLocaleTime, + y: d3_time_parseYear, + Y: d3_time_parseFullYear, + Z: d3_time_parseZone, + "%": d3_time_parseLiteralPercent + }; + function d3_time_parseWeekdayAbbrev(date, string, i) { + d3_time_dayAbbrevRe.lastIndex = 0; + var n = d3_time_dayAbbrevRe.exec(string.substring(i)); + return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseWeekday(date, string, i) { + d3_time_dayRe.lastIndex = 0; + var n = d3_time_dayRe.exec(string.substring(i)); + return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseMonthAbbrev(date, string, i) { + d3_time_monthAbbrevRe.lastIndex = 0; + var n = d3_time_monthAbbrevRe.exec(string.substring(i)); + return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseMonth(date, string, i) { + d3_time_monthRe.lastIndex = 0; + var n = d3_time_monthRe.exec(string.substring(i)); + return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; + } + function d3_time_parseLocaleFull(date, string, i) { + return d3_time_parse(date, d3_time_formats.c.toString(), string, i); + } + function d3_time_parseLocaleDate(date, string, i) { + return d3_time_parse(date, d3_time_formats.x.toString(), string, i); + } + function d3_time_parseLocaleTime(date, string, i) { + return d3_time_parse(date, d3_time_formats.X.toString(), string, i); + } + function d3_time_parseAmPm(date, string, i) { + var n = d3_time_periodLookup.get(string.substring(i, i += 2).toLowerCase()); + return n == null ? -1 : (date.p = n, i); + } + return d3_time_format; + } + var d3_time_formatPads = { + "-": "", + _: " ", + "0": "0" + }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/; + function d3_time_formatPad(value, fill, width) { + var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length; + return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); + } + function d3_time_formatRe(names) { + return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i"); + } + function d3_time_formatLookup(names) { + var map = new d3_Map(), i = -1, n = names.length; + while (++i < n) map.set(names[i].toLowerCase(), i); + return map; + } + function d3_time_parseWeekdayNumber(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i, i + 1)); + return n ? (date.w = +n[0], i + n[0].length) : -1; + } + function d3_time_parseWeekNumberSunday(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i)); + return n ? (date.U = +n[0], i + n[0].length) : -1; + } + function d3_time_parseWeekNumberMonday(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i)); + return n ? (date.W = +n[0], i + n[0].length) : -1; + } + function d3_time_parseFullYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i, i + 4)); + return n ? (date.y = +n[0], i + n[0].length) : -1; + } + function d3_time_parseYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i, i + 2)); + return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1; + } + function d3_time_parseZone(date, string, i) { + return /^[+-]\d{4}$/.test(string = string.substring(i, i + 5)) ? (date.Z = -string, + i + 5) : -1; + } + function d3_time_expandYear(d) { + return d + (d > 68 ? 1900 : 2e3); + } + function d3_time_parseMonthNumber(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i, i + 2)); + return n ? (date.m = n[0] - 1, i + n[0].length) : -1; + } + function d3_time_parseDay(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i, i + 2)); + return n ? (date.d = +n[0], i + n[0].length) : -1; + } + function d3_time_parseDayOfYear(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i, i + 3)); + return n ? (date.j = +n[0], i + n[0].length) : -1; + } + function d3_time_parseHour24(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i, i + 2)); + return n ? (date.H = +n[0], i + n[0].length) : -1; + } + function d3_time_parseMinutes(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i, i + 2)); + return n ? (date.M = +n[0], i + n[0].length) : -1; + } + function d3_time_parseSeconds(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i, i + 2)); + return n ? (date.S = +n[0], i + n[0].length) : -1; + } + function d3_time_parseMilliseconds(date, string, i) { + d3_time_numberRe.lastIndex = 0; + var n = d3_time_numberRe.exec(string.substring(i, i + 3)); + return n ? (date.L = +n[0], i + n[0].length) : -1; + } + function d3_time_zone(d) { + var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = ~~(abs(z) / 60), zm = abs(z) % 60; + return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2); + } + function d3_time_parseLiteralPercent(date, string, i) { + d3_time_percentRe.lastIndex = 0; + var n = d3_time_percentRe.exec(string.substring(i, i + 1)); + return n ? i + n[0].length : -1; + } + function d3_time_formatMulti(formats) { + var n = formats.length, i = -1; + while (++i < n) formats[i][0] = this(formats[i][0]); + return function(date) { + var i = 0, f = formats[i]; + while (!f[1](date)) f = formats[++i]; + return f[0](date); + }; + } + d3.locale = function(locale) { + return { + numberFormat: d3_locale_numberFormat(locale), + timeFormat: d3_locale_timeFormat(locale) + }; + }; + var d3_locale_enUS = d3.locale({ + decimal: ".", + thousands: ",", + grouping: [ 3 ], + currency: [ "$", "" ], + dateTime: "%a %b %e %X %Y", + date: "%m/%d/%Y", + time: "%H:%M:%S", + periods: [ "AM", "PM" ], + days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], + shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], + 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" ] + }); + d3.format = d3_locale_enUS.numberFormat; + d3.geo = {}; + function d3_adder() {} + d3_adder.prototype = { + s: 0, + t: 0, + add: function(y) { + d3_adderSum(y, this.t, d3_adderTemp); + d3_adderSum(d3_adderTemp.s, this.s, this); + if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t; + }, + reset: function() { + this.s = this.t = 0; + }, + valueOf: function() { + return this.s; + } + }; + var d3_adderTemp = new d3_adder(); + function d3_adderSum(a, b, o) { + var x = o.s = a + b, bv = x - a, av = x - bv; + o.t = a - av + (b - bv); + } + d3.geo.stream = function(object, listener) { + if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) { + d3_geo_streamObjectType[object.type](object, listener); + } else { + d3_geo_streamGeometry(object, listener); + } + }; + function d3_geo_streamGeometry(geometry, listener) { + if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) { + d3_geo_streamGeometryType[geometry.type](geometry, listener); + } + } + var d3_geo_streamObjectType = { + Feature: function(feature, listener) { + d3_geo_streamGeometry(feature.geometry, listener); + }, + FeatureCollection: function(object, listener) { + var features = object.features, i = -1, n = features.length; + while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener); + } + }; + var d3_geo_streamGeometryType = { + Sphere: function(object, listener) { + listener.sphere(); + }, + Point: function(object, listener) { + object = object.coordinates; + listener.point(object[0], object[1], object[2]); + }, + MultiPoint: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]); + }, + LineString: function(object, listener) { + d3_geo_streamLine(object.coordinates, listener, 0); + }, + MultiLineString: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0); + }, + Polygon: function(object, listener) { + d3_geo_streamPolygon(object.coordinates, listener); + }, + MultiPolygon: function(object, listener) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) d3_geo_streamPolygon(coordinates[i], listener); + }, + GeometryCollection: function(object, listener) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) d3_geo_streamGeometry(geometries[i], listener); + } + }; + function d3_geo_streamLine(coordinates, listener, closed) { + var i = -1, n = coordinates.length - closed, coordinate; + listener.lineStart(); + while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]); + listener.lineEnd(); + } + function d3_geo_streamPolygon(coordinates, listener) { + var i = -1, n = coordinates.length; + listener.polygonStart(); + while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1); + listener.polygonEnd(); + } + d3.geo.area = function(object) { + d3_geo_areaSum = 0; + d3.geo.stream(object, d3_geo_area); + return d3_geo_areaSum; + }; + var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder(); + var d3_geo_area = { + sphere: function() { + d3_geo_areaSum += 4 * Ï€; + }, + point: d3_noop, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: function() { + d3_geo_areaRingSum.reset(); + d3_geo_area.lineStart = d3_geo_areaRingStart; + }, + polygonEnd: function() { + var area = 2 * d3_geo_areaRingSum; + d3_geo_areaSum += area < 0 ? 4 * Ï€ + area : area; + d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop; + } + }; + function d3_geo_areaRingStart() { + var λ00, φ00, λ0, cosφ0, sinφ0; + d3_geo_area.point = function(λ, φ) { + d3_geo_area.point = nextPoint; + λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + Ï€ / 4), + sinφ0 = Math.sin(φ); + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + φ = φ * d3_radians / 2 + Ï€ / 4; + var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ); + d3_geo_areaRingSum.add(Math.atan2(v, u)); + λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ; + } + d3_geo_area.lineEnd = function() { + nextPoint(λ00, φ00); + }; + } + function d3_geo_cartesian(spherical) { + var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ); + return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ]; + } + function d3_geo_cartesianDot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + } + function d3_geo_cartesianCross(a, b) { + return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ]; + } + function d3_geo_cartesianAdd(a, b) { + a[0] += b[0]; + a[1] += b[1]; + a[2] += b[2]; + } + function d3_geo_cartesianScale(vector, k) { + return [ vector[0] * k, vector[1] * k, vector[2] * k ]; + } + function d3_geo_cartesianNormalize(d) { + var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + d[0] /= l; + d[1] /= l; + d[2] /= l; + } + function d3_geo_spherical(cartesian) { + return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ]; + } + function d3_geo_sphericalEqual(a, b) { + return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε; + } + d3.geo.bounds = function() { + var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range; + var bound = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + bound.point = ringPoint; + bound.lineStart = ringStart; + bound.lineEnd = ringEnd; + dλSum = 0; + d3_geo_area.polygonStart(); + }, + polygonEnd: function() { + d3_geo_area.polygonEnd(); + bound.point = point; + bound.lineStart = lineStart; + bound.lineEnd = lineEnd; + if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90; + range[0] = λ0, range[1] = λ1; + } + }; + function point(λ, φ) { + ranges.push(range = [ λ0 = λ, λ1 = λ ]); + if (φ < φ0) φ0 = φ; + if (φ > φ1) φ1 = φ; + } + function linePoint(λ, φ) { + var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]); + if (p0) { + var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal); + d3_geo_cartesianNormalize(inflection); + inflection = d3_geo_spherical(inflection); + var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180; + if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) { + var φi = inflection[1] * d3_degrees; + if (φi > φ1) φ1 = φi; + } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) { + var φi = -inflection[1] * d3_degrees; + if (φi < φ0) φ0 = φi; + } else { + if (φ < φ0) φ0 = φ; + if (φ > φ1) φ1 = φ; + } + if (antimeridian) { + if (λ < λ_) { + if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; + } else { + if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; + } + } else { + if (λ1 >= λ0) { + if (λ < λ0) λ0 = λ; + if (λ > λ1) λ1 = λ; + } else { + if (λ > λ_) { + if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ; + } else { + if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ; + } + } + } + } else { + point(λ, φ); + } + p0 = p, λ_ = λ; + } + function lineStart() { + bound.point = linePoint; + } + function lineEnd() { + range[0] = λ0, range[1] = λ1; + bound.point = point; + p0 = null; + } + function ringPoint(λ, φ) { + if (p0) { + var dλ = λ - λ_; + dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ; + } else λ__ = λ, φ__ = φ; + d3_geo_area.point(λ, φ); + linePoint(λ, φ); + } + function ringStart() { + d3_geo_area.lineStart(); + } + function ringEnd() { + ringPoint(λ__, φ__); + d3_geo_area.lineEnd(); + if (abs(dλSum) > ε) λ0 = -(λ1 = 180); + range[0] = λ0, range[1] = λ1; + p0 = null; + } + function angle(λ0, λ1) { + return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; + } + function compareRanges(a, b) { + return a[0] - b[0]; + } + function withinRange(x, range) { + return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; + } + return function(feature) { + φ1 = λ1 = -(λ0 = φ0 = Infinity); + ranges = []; + d3.geo.stream(feature, bound); + var n = ranges.length; + if (n) { + ranges.sort(compareRanges); + for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) { + b = ranges[i]; + if (withinRange(b[0], a) || withinRange(b[1], a)) { + if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; + if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; + } else { + merged.push(a = b); + } + } + var best = -Infinity, dλ; + for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) { + b = merged[i]; + if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1]; + } + } + ranges = range = null; + return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ]; + }; + }(); + d3.geo.centroid = function(object) { + d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; + d3.geo.stream(object, d3_geo_centroid); + var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z; + if (m < ε2) { + x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1; + if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0; + m = x * x + y * y + z * z; + if (m < ε2) return [ NaN, NaN ]; + } + return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ]; + }; + var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2; + var d3_geo_centroid = { + sphere: d3_noop, + point: d3_geo_centroidPoint, + lineStart: d3_geo_centroidLineStart, + lineEnd: d3_geo_centroidLineEnd, + polygonStart: function() { + d3_geo_centroid.lineStart = d3_geo_centroidRingStart; + }, + polygonEnd: function() { + d3_geo_centroid.lineStart = d3_geo_centroidLineStart; + } + }; + function d3_geo_centroidPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ)); + } + function d3_geo_centroidPointXYZ(x, y, z) { + ++d3_geo_centroidW0; + d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0; + d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0; + d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0; + } + function d3_geo_centroidLineStart() { + var x0, y0, z0; + d3_geo_centroid.point = function(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + x0 = cosφ * Math.cos(λ); + y0 = cosφ * Math.sin(λ); + z0 = Math.sin(φ); + d3_geo_centroid.point = nextPoint; + d3_geo_centroidPointXYZ(x0, y0, z0); + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); + d3_geo_centroidW1 += w; + d3_geo_centroidX1 += w * (x0 + (x0 = x)); + d3_geo_centroidY1 += w * (y0 + (y0 = y)); + d3_geo_centroidZ1 += w * (z0 + (z0 = z)); + d3_geo_centroidPointXYZ(x0, y0, z0); + } + } + function d3_geo_centroidLineEnd() { + d3_geo_centroid.point = d3_geo_centroidPoint; + } + function d3_geo_centroidRingStart() { + var λ00, φ00, x0, y0, z0; + d3_geo_centroid.point = function(λ, φ) { + λ00 = λ, φ00 = φ; + d3_geo_centroid.point = nextPoint; + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians); + x0 = cosφ * Math.cos(λ); + y0 = cosφ * Math.sin(λ); + z0 = Math.sin(φ); + d3_geo_centroidPointXYZ(x0, y0, z0); + }; + d3_geo_centroid.lineEnd = function() { + nextPoint(λ00, φ00); + d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd; + d3_geo_centroid.point = d3_geo_centroidPoint; + }; + function nextPoint(λ, φ) { + λ *= d3_radians; + var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u); + d3_geo_centroidX2 += v * cx; + d3_geo_centroidY2 += v * cy; + d3_geo_centroidZ2 += v * cz; + d3_geo_centroidW1 += w; + d3_geo_centroidX1 += w * (x0 + (x0 = x)); + d3_geo_centroidY1 += w * (y0 + (y0 = y)); + d3_geo_centroidZ1 += w * (z0 + (z0 = z)); + d3_geo_centroidPointXYZ(x0, y0, z0); + } + } + function d3_true() { + return true; + } + function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) { + var subject = [], clip = []; + segments.forEach(function(segment) { + if ((n = segment.length - 1) <= 0) return; + var n, p0 = segment[0], p1 = segment[n]; + if (d3_geo_sphericalEqual(p0, p1)) { + listener.lineStart(); + for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]); + listener.lineEnd(); + return; + } + var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false); + a.o = b; + subject.push(a); + clip.push(b); + a = new d3_geo_clipPolygonIntersection(p1, segment, null, false); + b = new d3_geo_clipPolygonIntersection(p1, null, a, true); + a.o = b; + subject.push(a); + clip.push(b); + }); + clip.sort(compare); + d3_geo_clipPolygonLinkCircular(subject); + d3_geo_clipPolygonLinkCircular(clip); + if (!subject.length) return; + for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) { + clip[i].e = entry = !entry; + } + var start = subject[0], points, point; + while (1) { + var current = start, isSubject = true; + while (current.v) if ((current = current.n) === start) return; + points = current.z; + listener.lineStart(); + do { + current.v = current.o.v = true; + if (current.e) { + if (isSubject) { + for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.n.x, 1, listener); + } + current = current.n; + } else { + if (isSubject) { + points = current.p.z; + for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.p.x, -1, listener); + } + current = current.p; + } + current = current.o; + points = current.z; + isSubject = !isSubject; + } while (!current.v); + listener.lineEnd(); + } + } + function d3_geo_clipPolygonLinkCircular(array) { + if (!(n = array.length)) return; + var n, i = 0, a = array[0], b; + while (++i < n) { + a.n = b = array[i]; + b.p = a; + a = b; + } + a.n = b = array[0]; + b.p = a; + } + function d3_geo_clipPolygonIntersection(point, points, other, entry) { + this.x = point; + this.z = points; + this.o = other; + this.e = entry; + this.v = false; + this.n = this.p = null; + } + function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) { + return function(rotate, listener) { + var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]); + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + clip.point = pointRing; + clip.lineStart = ringStart; + clip.lineEnd = ringEnd; + segments = []; + polygon = []; + }, + polygonEnd: function() { + clip.point = point; + clip.lineStart = lineStart; + clip.lineEnd = lineEnd; + segments = d3.merge(segments); + var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon); + if (segments.length) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener); + } else if (clipStartInside) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + } + if (polygonStarted) listener.polygonEnd(), polygonStarted = false; + segments = polygon = null; + }, + sphere: function() { + listener.polygonStart(); + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + listener.polygonEnd(); + } + }; + function point(λ, φ) { + var point = rotate(λ, φ); + if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ); + } + function pointLine(λ, φ) { + var point = rotate(λ, φ); + line.point(point[0], point[1]); + } + function lineStart() { + clip.point = pointLine; + line.lineStart(); + } + function lineEnd() { + clip.point = point; + line.lineEnd(); + } + var segments; + var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring; + function pointRing(λ, φ) { + ring.push([ λ, φ ]); + var point = rotate(λ, φ); + ringListener.point(point[0], point[1]); + } + function ringStart() { + ringListener.lineStart(); + ring = []; + } + function ringEnd() { + pointRing(ring[0][0], ring[0][1]); + ringListener.lineEnd(); + var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length; + ring.pop(); + polygon.push(ring); + ring = null; + if (!n) return; + if (clean & 1) { + segment = ringSegments[0]; + var n = segment.length - 1, i = -1, point; + if (n > 0) { + if (!polygonStarted) listener.polygonStart(), polygonStarted = true; + listener.lineStart(); + while (++i < n) listener.point((point = segment[i])[0], point[1]); + listener.lineEnd(); + } + return; + } + if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + segments.push(ringSegments.filter(d3_geo_clipSegmentLength1)); + } + return clip; + }; + } + function d3_geo_clipSegmentLength1(segment) { + return segment.length > 1; + } + function d3_geo_clipBufferListener() { + var lines = [], line; + return { + lineStart: function() { + lines.push(line = []); + }, + point: function(λ, φ) { + line.push([ λ, φ ]); + }, + lineEnd: d3_noop, + buffer: function() { + var buffer = lines; + lines = []; + line = null; + return buffer; + }, + rejoin: function() { + if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); + } + }; + } + function d3_geo_clipSort(a, b) { + return ((a = a.x)[0] < 0 ? a[1] - halfÏ€ - ε : halfÏ€ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfÏ€ - ε : halfÏ€ - b[1]); + } + function d3_geo_pointInPolygon(point, polygon) { + var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0; + d3_geo_areaRingSum.reset(); + for (var i = 0, n = polygon.length; i < n; ++i) { + var ring = polygon[i], m = ring.length; + if (!m) continue; + var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + Ï€ / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1; + while (true) { + if (j === m) j = 0; + point = ring[j]; + var λ = point[0], φ = point[1] / 2 + Ï€ / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > Ï€, k = sinφ0 * sinφ; + d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ))); + polarAngle += antimeridian ? dλ + sdλ * Ï„ : dλ; + if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) { + var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point)); + d3_geo_cartesianNormalize(arc); + var intersection = d3_geo_cartesianCross(meridianNormal, arc); + d3_geo_cartesianNormalize(intersection); + var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]); + if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) { + winding += antimeridian ^ dλ >= 0 ? 1 : -1; + } + } + if (!j++) break; + λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point; + } + } + return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1; + } + var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -Ï€, -Ï€ / 2 ]); + function d3_geo_clipAntimeridianLine(listener) { + var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean; + return { + lineStart: function() { + listener.lineStart(); + clean = 1; + }, + point: function(λ1, φ1) { + var sλ1 = λ1 > 0 ? Ï€ : -Ï€, dλ = abs(λ1 - λ0); + if (abs(dλ - Ï€) < ε) { + listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfÏ€ : -halfÏ€); + listener.point(sλ0, φ0); + listener.lineEnd(); + listener.lineStart(); + listener.point(sλ1, φ0); + listener.point(λ1, φ0); + clean = 0; + } else if (sλ0 !== sλ1 && dλ >= Ï€) { + if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε; + if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε; + φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1); + listener.point(sλ0, φ0); + listener.lineEnd(); + listener.lineStart(); + listener.point(sλ1, φ0); + clean = 0; + } + listener.point(λ0 = λ1, φ0 = φ1); + sλ0 = sλ1; + }, + lineEnd: function() { + listener.lineEnd(); + λ0 = φ0 = NaN; + }, + clean: function() { + return 2 - clean; + } + }; + } + function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) { + var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1); + return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2; + } + function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) { + var φ; + if (from == null) { + φ = direction * halfÏ€; + listener.point(-Ï€, φ); + listener.point(0, φ); + listener.point(Ï€, φ); + listener.point(Ï€, 0); + listener.point(Ï€, -φ); + listener.point(0, -φ); + listener.point(-Ï€, -φ); + listener.point(-Ï€, 0); + listener.point(-Ï€, φ); + } else if (abs(from[0] - to[0]) > ε) { + var s = from[0] < to[0] ? Ï€ : -Ï€; + φ = direction * s / 2; + listener.point(-s, φ); + listener.point(0, φ); + listener.point(s, φ); + } else { + listener.point(to[0], to[1]); + } + } + function d3_geo_clipCircle(radius) { + var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians); + return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -Ï€, radius - Ï€ ]); + function visible(λ, φ) { + return Math.cos(λ) * Math.cos(φ) > cr; + } + function clipLine(listener) { + var point0, c0, v0, v00, clean; + return { + lineStart: function() { + v00 = v0 = false; + clean = 1; + }, + point: function(λ, φ) { + var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? Ï€ : -Ï€), φ) : 0; + if (!point0 && (v00 = v0 = v)) listener.lineStart(); + if (v !== v0) { + point2 = intersect(point0, point1); + if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) { + point1[0] += ε; + point1[1] += ε; + v = visible(point1[0], point1[1]); + } + } + if (v !== v0) { + clean = 0; + if (v) { + listener.lineStart(); + point2 = intersect(point1, point0); + listener.point(point2[0], point2[1]); + } else { + point2 = intersect(point0, point1); + listener.point(point2[0], point2[1]); + listener.lineEnd(); + } + point0 = point2; + } else if (notHemisphere && point0 && smallRadius ^ v) { + var t; + if (!(c & c0) && (t = intersect(point1, point0, true))) { + clean = 0; + if (smallRadius) { + listener.lineStart(); + listener.point(t[0][0], t[0][1]); + listener.point(t[1][0], t[1][1]); + listener.lineEnd(); + } else { + listener.point(t[1][0], t[1][1]); + listener.lineEnd(); + listener.lineStart(); + listener.point(t[0][0], t[0][1]); + } + } + } + if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) { + listener.point(point1[0], point1[1]); + } + point0 = point1, v0 = v, c0 = c; + }, + lineEnd: function() { + if (v0) listener.lineEnd(); + point0 = null; + }, + clean: function() { + return clean | (v00 && v0) << 1; + } + }; + } + function intersect(a, b, two) { + var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b); + var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2; + if (!determinant) return !two && a; + var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2); + d3_geo_cartesianAdd(A, B); + var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1); + if (t2 < 0) return; + var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu); + d3_geo_cartesianAdd(q, A); + q = d3_geo_spherical(q); + if (!two) return q; + var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z; + if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z; + var δλ = λ1 - λ0, polar = abs(δλ - Ï€) < ε, meridian = polar || δλ < ε; + if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z; + if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > Ï€ ^ (λ0 <= q[0] && q[0] <= λ1)) { + var q1 = d3_geo_cartesianScale(u, (-w + t) / uu); + d3_geo_cartesianAdd(q1, A); + return [ q, d3_geo_spherical(q1) ]; + } + } + function code(λ, φ) { + var r = smallRadius ? radius : Ï€ - radius, code = 0; + if (λ < -r) code |= 1; else if (λ > r) code |= 2; + if (φ < -r) code |= 4; else if (φ > r) code |= 8; + return code; + } + } + function d3_geom_clipLine(x0, y0, x1, y1) { + return function(line) { + var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r; + r = x0 - ax; + if (!dx && r > 0) return; + r /= dx; + if (dx < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dx > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + r = x1 - ax; + if (!dx && r < 0) return; + r /= dx; + if (dx < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dx > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + r = y0 - ay; + if (!dy && r > 0) return; + r /= dy; + if (dy < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dy > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + r = y1 - ay; + if (!dy && r < 0) return; + r /= dy; + if (dy < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dy > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + if (t0 > 0) line.a = { + x: ax + t0 * dx, + y: ay + t0 * dy + }; + if (t1 < 1) line.b = { + x: ax + t1 * dx, + y: ay + t1 * dy + }; + return line; + }; + } + var d3_geo_clipExtentMAX = 1e9; + d3.geo.clipExtent = function() { + var x0, y0, x1, y1, stream, clip, clipExtent = { + stream: function(output) { + if (stream) stream.valid = false; + stream = clip(output); + stream.valid = true; + return stream; + }, + extent: function(_) { + if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; + clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]); + if (stream) stream.valid = false, stream = null; + return clipExtent; + } + }; + return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]); + }; + function d3_geo_clipExtent(x0, y0, x1, y1) { + return function(listener) { + var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring; + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + listener = bufferListener; + segments = []; + polygon = []; + clean = true; + }, + polygonEnd: function() { + listener = listener_; + segments = d3.merge(segments); + var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length; + if (inside || visible) { + listener.polygonStart(); + if (inside) { + listener.lineStart(); + interpolate(null, null, 1, listener); + listener.lineEnd(); + } + if (visible) { + d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener); + } + listener.polygonEnd(); + } + segments = polygon = ring = null; + } + }; + function insidePolygon(p) { + var wn = 0, n = polygon.length, y = p[1]; + for (var i = 0; i < n; ++i) { + for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) { + b = v[j]; + if (a[1] <= y) { + if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn; + } else { + if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn; + } + a = b; + } + } + return wn !== 0; + } + function interpolate(from, to, direction, listener) { + var a = 0, a1 = 0; + if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) { + do { + listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); + } while ((a = (a + direction + 4) % 4) !== a1); + } else { + listener.point(to[0], to[1]); + } + } + function pointVisible(x, y) { + return x0 <= x && x <= x1 && y0 <= y && y <= y1; + } + function point(x, y) { + if (pointVisible(x, y)) listener.point(x, y); + } + var x__, y__, v__, x_, y_, v_, first, clean; + function lineStart() { + clip.point = linePoint; + if (polygon) polygon.push(ring = []); + first = true; + v_ = false; + x_ = y_ = NaN; + } + function lineEnd() { + if (segments) { + linePoint(x__, y__); + if (v__ && v_) bufferListener.rejoin(); + segments.push(bufferListener.buffer()); + } + clip.point = point; + if (v_) listener.lineEnd(); + } + function linePoint(x, y) { + x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x)); + y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y)); + var v = pointVisible(x, y); + if (polygon) ring.push([ x, y ]); + if (first) { + x__ = x, y__ = y, v__ = v; + first = false; + if (v) { + listener.lineStart(); + listener.point(x, y); + } + } else { + if (v && v_) listener.point(x, y); else { + var l = { + a: { + x: x_, + y: y_ + }, + b: { + x: x, + y: y + } + }; + if (clipLine(l)) { + if (!v_) { + listener.lineStart(); + listener.point(l.a.x, l.a.y); + } + listener.point(l.b.x, l.b.y); + if (!v) listener.lineEnd(); + clean = false; + } else if (v) { + listener.lineStart(); + listener.point(x, y); + clean = false; + } + } + } + x_ = x, y_ = y, v_ = v; + } + return clip; + }; + function corner(p, direction) { + return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; + } + function compare(a, b) { + return comparePoints(a.x, b.x); + } + function comparePoints(a, b) { + var ca = corner(a, 1), cb = corner(b, 1); + return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0]; + } + } + function d3_geo_compose(a, b) { + function compose(x, y) { + return x = a(x, y), b(x[0], x[1]); + } + if (a.invert && b.invert) compose.invert = function(x, y) { + return x = b.invert(x, y), x && a.invert(x[0], x[1]); + }; + return compose; + } + function d3_geo_conic(projectAt) { + var φ0 = 0, φ1 = Ï€ / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1); + p.parallels = function(_) { + if (!arguments.length) return [ φ0 / Ï€ * 180, φ1 / Ï€ * 180 ]; + return m(φ0 = _[0] * Ï€ / 180, φ1 = _[1] * Ï€ / 180); + }; + return p; + } + function d3_geo_conicEqualArea(φ0, φ1) { + var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), Ï0 = Math.sqrt(C) / n; + function forward(λ, φ) { + var Ï = Math.sqrt(C - 2 * n * Math.sin(φ)) / n; + return [ Ï * Math.sin(λ *= n), Ï0 - Ï * Math.cos(λ) ]; + } + forward.invert = function(x, y) { + var Ï0_y = Ï0 - y; + return [ Math.atan2(x, Ï0_y) / n, d3_asin((C - (x * x + Ï0_y * Ï0_y) * n * n) / (2 * n)) ]; + }; + return forward; + } + (d3.geo.conicEqualArea = function() { + return d3_geo_conic(d3_geo_conicEqualArea); + }).raw = d3_geo_conicEqualArea; + d3.geo.albers = function() { + return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070); + }; + d3.geo.albersUsa = function() { + var lower48 = d3.geo.albers(); + var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]); + var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]); + var point, pointStream = { + point: function(x, y) { + point = [ x, y ]; + } + }, lower48Point, alaskaPoint, hawaiiPoint; + function albersUsa(coordinates) { + var x = coordinates[0], y = coordinates[1]; + point = null; + (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y); + return point; + } + albersUsa.invert = function(coordinates) { + var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k; + return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates); + }; + albersUsa.stream = function(stream) { + var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream); + return { + point: function(x, y) { + lower48Stream.point(x, y); + alaskaStream.point(x, y); + hawaiiStream.point(x, y); + }, + sphere: function() { + lower48Stream.sphere(); + alaskaStream.sphere(); + hawaiiStream.sphere(); + }, + lineStart: function() { + lower48Stream.lineStart(); + alaskaStream.lineStart(); + hawaiiStream.lineStart(); + }, + lineEnd: function() { + lower48Stream.lineEnd(); + alaskaStream.lineEnd(); + hawaiiStream.lineEnd(); + }, + polygonStart: function() { + lower48Stream.polygonStart(); + alaskaStream.polygonStart(); + hawaiiStream.polygonStart(); + }, + polygonEnd: function() { + lower48Stream.polygonEnd(); + alaskaStream.polygonEnd(); + hawaiiStream.polygonEnd(); + } + }; + }; + albersUsa.precision = function(_) { + if (!arguments.length) return lower48.precision(); + lower48.precision(_); + alaska.precision(_); + hawaii.precision(_); + return albersUsa; + }; + albersUsa.scale = function(_) { + if (!arguments.length) return lower48.scale(); + lower48.scale(_); + alaska.scale(_ * .35); + hawaii.scale(_); + return albersUsa.translate(lower48.translate()); + }; + albersUsa.translate = function(_) { + if (!arguments.length) return lower48.translate(); + var k = lower48.scale(), x = +_[0], y = +_[1]; + lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point; + alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; + hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point; + return albersUsa; + }; + return albersUsa.scale(1070); + }; + var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = { + point: d3_noop, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: function() { + d3_geo_pathAreaPolygon = 0; + d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart; + }, + polygonEnd: function() { + d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop; + d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2); + } + }; + function d3_geo_pathAreaRingStart() { + var x00, y00, x0, y0; + d3_geo_pathArea.point = function(x, y) { + d3_geo_pathArea.point = nextPoint; + x00 = x0 = x, y00 = y0 = y; + }; + function nextPoint(x, y) { + d3_geo_pathAreaPolygon += y0 * x - x0 * y; + x0 = x, y0 = y; + } + d3_geo_pathArea.lineEnd = function() { + nextPoint(x00, y00); + }; + } + var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1; + var d3_geo_pathBounds = { + point: d3_geo_pathBoundsPoint, + lineStart: d3_noop, + lineEnd: d3_noop, + polygonStart: d3_noop, + polygonEnd: d3_noop + }; + function d3_geo_pathBoundsPoint(x, y) { + if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x; + if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x; + if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y; + if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y; + } + function d3_geo_pathBuffer() { + var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = []; + var stream = { + point: point, + lineStart: function() { + stream.point = pointLineStart; + }, + lineEnd: lineEnd, + polygonStart: function() { + stream.lineEnd = lineEndPolygon; + }, + polygonEnd: function() { + stream.lineEnd = lineEnd; + stream.point = point; + }, + pointRadius: function(_) { + pointCircle = d3_geo_pathBufferCircle(_); + return stream; + }, + result: function() { + if (buffer.length) { + var result = buffer.join(""); + buffer = []; + return result; + } + } + }; + function point(x, y) { + buffer.push("M", x, ",", y, pointCircle); + } + function pointLineStart(x, y) { + buffer.push("M", x, ",", y); + stream.point = pointLine; + } + function pointLine(x, y) { + buffer.push("L", x, ",", y); + } + function lineEnd() { + stream.point = point; + } + function lineEndPolygon() { + buffer.push("Z"); + } + return stream; + } + function d3_geo_pathBufferCircle(radius) { + return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z"; + } + var d3_geo_pathCentroid = { + point: d3_geo_pathCentroidPoint, + lineStart: d3_geo_pathCentroidLineStart, + lineEnd: d3_geo_pathCentroidLineEnd, + polygonStart: function() { + d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart; + }, + polygonEnd: function() { + d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; + d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart; + d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd; + } + }; + function d3_geo_pathCentroidPoint(x, y) { + d3_geo_centroidX0 += x; + d3_geo_centroidY0 += y; + ++d3_geo_centroidZ0; + } + function d3_geo_pathCentroidLineStart() { + var x0, y0; + d3_geo_pathCentroid.point = function(x, y) { + d3_geo_pathCentroid.point = nextPoint; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + }; + function nextPoint(x, y) { + var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); + d3_geo_centroidX1 += z * (x0 + x) / 2; + d3_geo_centroidY1 += z * (y0 + y) / 2; + d3_geo_centroidZ1 += z; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + } + } + function d3_geo_pathCentroidLineEnd() { + d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint; + } + function d3_geo_pathCentroidRingStart() { + var x00, y00, x0, y0; + d3_geo_pathCentroid.point = function(x, y) { + d3_geo_pathCentroid.point = nextPoint; + d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y); + }; + function nextPoint(x, y) { + var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy); + d3_geo_centroidX1 += z * (x0 + x) / 2; + d3_geo_centroidY1 += z * (y0 + y) / 2; + d3_geo_centroidZ1 += z; + z = y0 * x - x0 * y; + d3_geo_centroidX2 += z * (x0 + x); + d3_geo_centroidY2 += z * (y0 + y); + d3_geo_centroidZ2 += z * 3; + d3_geo_pathCentroidPoint(x0 = x, y0 = y); + } + d3_geo_pathCentroid.lineEnd = function() { + nextPoint(x00, y00); + }; + } + function d3_geo_pathContext(context) { + var pointRadius = 4.5; + var stream = { + point: point, + lineStart: function() { + stream.point = pointLineStart; + }, + lineEnd: lineEnd, + polygonStart: function() { + stream.lineEnd = lineEndPolygon; + }, + polygonEnd: function() { + stream.lineEnd = lineEnd; + stream.point = point; + }, + pointRadius: function(_) { + pointRadius = _; + return stream; + }, + result: d3_noop + }; + function point(x, y) { + context.moveTo(x, y); + context.arc(x, y, pointRadius, 0, Ï„); + } + function pointLineStart(x, y) { + context.moveTo(x, y); + stream.point = pointLine; + } + function pointLine(x, y) { + context.lineTo(x, y); + } + function lineEnd() { + stream.point = point; + } + function lineEndPolygon() { + context.closePath(); + } + return stream; + } + function d3_geo_resample(project) { + var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16; + function resample(stream) { + return (maxDepth ? resampleRecursive : resampleNone)(stream); + } + function resampleNone(stream) { + return d3_geo_transformPoint(stream, function(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + }); + } + function resampleRecursive(stream) { + var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0; + var resample = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + stream.polygonStart(); + resample.lineStart = ringStart; + }, + polygonEnd: function() { + stream.polygonEnd(); + resample.lineStart = lineStart; + } + }; + function point(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + } + function lineStart() { + x0 = NaN; + resample.point = linePoint; + stream.lineStart(); + } + function linePoint(λ, φ) { + var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ); + resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); + stream.point(x0, y0); + } + function lineEnd() { + resample.point = point; + stream.lineEnd(); + } + function ringStart() { + lineStart(); + resample.point = ringPoint; + resample.lineEnd = ringEnd; + } + function ringPoint(λ, φ) { + linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; + resample.point = linePoint; + } + function ringEnd() { + resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream); + resample.lineEnd = lineEnd; + lineEnd(); + } + return resample; + } + function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) { + var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy; + if (d2 > 4 * δ2 && depth--) { + var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2; + if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { + resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream); + stream.point(x2, y2); + resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream); + } + } + } + resample.precision = function(_) { + if (!arguments.length) return Math.sqrt(δ2); + maxDepth = (δ2 = _ * _) > 0 && 16; + return resample; + }; + return resample; + } + d3.geo.path = function() { + var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream; + function path(object) { + if (object) { + if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); + if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream); + d3.geo.stream(object, cacheStream); + } + return contextStream.result(); + } + path.area = function(object) { + d3_geo_pathAreaSum = 0; + d3.geo.stream(object, projectStream(d3_geo_pathArea)); + return d3_geo_pathAreaSum; + }; + path.centroid = function(object) { + d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0; + d3.geo.stream(object, projectStream(d3_geo_pathCentroid)); + return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ]; + }; + path.bounds = function(object) { + d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity); + d3.geo.stream(object, projectStream(d3_geo_pathBounds)); + return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ]; + }; + path.projection = function(_) { + if (!arguments.length) return projection; + projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity; + return reset(); + }; + path.context = function(_) { + if (!arguments.length) return context; + contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_); + if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); + return reset(); + }; + path.pointRadius = function(_) { + if (!arguments.length) return pointRadius; + pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); + return path; + }; + function reset() { + cacheStream = null; + return path; + } + return path.projection(d3.geo.albersUsa()).context(null); + }; + function d3_geo_pathProjectStream(project) { + var resample = d3_geo_resample(function(x, y) { + return project([ x * d3_degrees, y * d3_degrees ]); + }); + return function(stream) { + return d3_geo_projectionRadians(resample(stream)); + }; + } + d3.geo.transform = function(methods) { + return { + stream: function(stream) { + var transform = new d3_geo_transform(stream); + for (var k in methods) transform[k] = methods[k]; + return transform; + } + }; + }; + function d3_geo_transform(stream) { + this.stream = stream; + } + d3_geo_transform.prototype = { + point: function(x, y) { + this.stream.point(x, y); + }, + sphere: function() { + this.stream.sphere(); + }, + lineStart: function() { + this.stream.lineStart(); + }, + lineEnd: function() { + this.stream.lineEnd(); + }, + polygonStart: function() { + this.stream.polygonStart(); + }, + polygonEnd: function() { + this.stream.polygonEnd(); + } + }; + function d3_geo_transformPoint(stream, point) { + return { + point: point, + sphere: function() { + stream.sphere(); + }, + lineStart: function() { + stream.lineStart(); + }, + lineEnd: function() { + stream.lineEnd(); + }, + polygonStart: function() { + stream.polygonStart(); + }, + polygonEnd: function() { + stream.polygonEnd(); + } + }; + } + d3.geo.projection = d3_geo_projection; + d3.geo.projectionMutator = d3_geo_projectionMutator; + function d3_geo_projection(project) { + return d3_geo_projectionMutator(function() { + return project; + })(); + } + function d3_geo_projectionMutator(projectAt) { + var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) { + x = project(x, y); + return [ x[0] * k + δx, δy - x[1] * k ]; + }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream; + function projection(point) { + point = projectRotate(point[0] * d3_radians, point[1] * d3_radians); + return [ point[0] * k + δx, δy - point[1] * k ]; + } + function invert(point) { + point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k); + return point && [ point[0] * d3_degrees, point[1] * d3_degrees ]; + } + projection.stream = function(output) { + if (stream) stream.valid = false; + stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output)))); + stream.valid = true; + return stream; + }; + projection.clipAngle = function(_) { + if (!arguments.length) return clipAngle; + preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians); + return invalidate(); + }; + projection.clipExtent = function(_) { + if (!arguments.length) return clipExtent; + clipExtent = _; + postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity; + return invalidate(); + }; + projection.scale = function(_) { + if (!arguments.length) return k; + k = +_; + return reset(); + }; + projection.translate = function(_) { + if (!arguments.length) return [ x, y ]; + x = +_[0]; + y = +_[1]; + return reset(); + }; + projection.center = function(_) { + if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ]; + λ = _[0] % 360 * d3_radians; + φ = _[1] % 360 * d3_radians; + return reset(); + }; + projection.rotate = function(_) { + if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ]; + δλ = _[0] % 360 * d3_radians; + δφ = _[1] % 360 * d3_radians; + δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0; + return reset(); + }; + d3.rebind(projection, projectResample, "precision"); + function reset() { + projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project); + var center = project(λ, φ); + δx = x - center[0] * k; + δy = y + center[1] * k; + return invalidate(); + } + function invalidate() { + if (stream) stream.valid = false, stream = null; + return projection; + } + return function() { + project = projectAt.apply(this, arguments); + projection.invert = project.invert && invert; + return reset(); + }; + } + function d3_geo_projectionRadians(stream) { + return d3_geo_transformPoint(stream, function(x, y) { + stream.point(x * d3_radians, y * d3_radians); + }); + } + function d3_geo_equirectangular(λ, φ) { + return [ λ, φ ]; + } + (d3.geo.equirectangular = function() { + return d3_geo_projection(d3_geo_equirectangular); + }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular; + d3.geo.rotation = function(rotate) { + rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0); + function forward(coordinates) { + coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians); + return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; + } + forward.invert = function(coordinates) { + coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians); + return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates; + }; + return forward; + }; + function d3_geo_identityRotation(λ, φ) { + return [ λ > Ï€ ? λ - Ï„ : λ < -Ï€ ? λ + Ï„ : λ, φ ]; + } + d3_geo_identityRotation.invert = d3_geo_equirectangular; + function d3_geo_rotation(δλ, δφ, δγ) { + return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation; + } + function d3_geo_forwardRotationλ(δλ) { + return function(λ, φ) { + return λ += δλ, [ λ > Ï€ ? λ - Ï„ : λ < -Ï€ ? λ + Ï„ : λ, φ ]; + }; + } + function d3_geo_rotationλ(δλ) { + var rotation = d3_geo_forwardRotationλ(δλ); + rotation.invert = d3_geo_forwardRotationλ(-δλ); + return rotation; + } + function d3_geo_rotationφγ(δφ, δγ) { + var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ); + function rotation(λ, φ) { + var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ; + return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ]; + } + rotation.invert = function(λ, φ) { + var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ; + return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ]; + }; + return rotation; + } + d3.geo.circle = function() { + var origin = [ 0, 0 ], angle, precision = 6, interpolate; + function circle() { + var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = []; + interpolate(null, null, 1, { + point: function(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= d3_degrees, x[1] *= d3_degrees; + } + }); + return { + type: "Polygon", + coordinates: [ ring ] + }; + } + circle.origin = function(x) { + if (!arguments.length) return origin; + origin = x; + return circle; + }; + circle.angle = function(x) { + if (!arguments.length) return angle; + interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians); + return circle; + }; + circle.precision = function(_) { + if (!arguments.length) return precision; + interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians); + return circle; + }; + return circle.angle(90); + }; + function d3_geo_circleInterpolate(radius, precision) { + var cr = Math.cos(radius), sr = Math.sin(radius); + return function(from, to, direction, listener) { + var step = direction * precision; + if (from != null) { + from = d3_geo_circleAngle(cr, from); + to = d3_geo_circleAngle(cr, to); + if (direction > 0 ? from < to : from > to) from += direction * Ï„; + } else { + from = radius + direction * Ï„; + to = radius - .5 * step; + } + for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) { + listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]); + } + }; + } + function d3_geo_circleAngle(cr, point) { + var a = d3_geo_cartesian(point); + a[0] -= cr; + d3_geo_cartesianNormalize(a); + var angle = d3_acos(-a[1]); + return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI); + } + d3.geo.distance = function(a, b) { + var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t; + return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ); + }; + d3.geo.graticule = function() { + var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5; + function graticule() { + return { + type: "MultiLineString", + coordinates: lines() + }; + } + function lines() { + return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) { + return abs(x % DX) > ε; + }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) { + return abs(y % DY) > ε; + }).map(y)); + } + graticule.lines = function() { + return lines().map(function(coordinates) { + return { + type: "LineString", + coordinates: coordinates + }; + }); + }; + graticule.outline = function() { + return { + type: "Polygon", + coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ] + }; + }; + graticule.extent = function(_) { + if (!arguments.length) return graticule.minorExtent(); + return graticule.majorExtent(_).minorExtent(_); + }; + graticule.majorExtent = function(_) { + if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ]; + X0 = +_[0][0], X1 = +_[1][0]; + Y0 = +_[0][1], Y1 = +_[1][1]; + if (X0 > X1) _ = X0, X0 = X1, X1 = _; + if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; + return graticule.precision(precision); + }; + graticule.minorExtent = function(_) { + if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ]; + x0 = +_[0][0], x1 = +_[1][0]; + y0 = +_[0][1], y1 = +_[1][1]; + if (x0 > x1) _ = x0, x0 = x1, x1 = _; + if (y0 > y1) _ = y0, y0 = y1, y1 = _; + return graticule.precision(precision); + }; + graticule.step = function(_) { + if (!arguments.length) return graticule.minorStep(); + return graticule.majorStep(_).minorStep(_); + }; + graticule.majorStep = function(_) { + if (!arguments.length) return [ DX, DY ]; + DX = +_[0], DY = +_[1]; + return graticule; + }; + graticule.minorStep = function(_) { + if (!arguments.length) return [ dx, dy ]; + dx = +_[0], dy = +_[1]; + return graticule; + }; + graticule.precision = function(_) { + if (!arguments.length) return precision; + precision = +_; + x = d3_geo_graticuleX(y0, y1, 90); + y = d3_geo_graticuleY(x0, x1, precision); + X = d3_geo_graticuleX(Y0, Y1, 90); + Y = d3_geo_graticuleY(X0, X1, precision); + return graticule; + }; + return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]); + }; + function d3_geo_graticuleX(y0, y1, dy) { + var y = d3.range(y0, y1 - ε, dy).concat(y1); + return function(x) { + return y.map(function(y) { + return [ x, y ]; + }); + }; + } + function d3_geo_graticuleY(x0, x1, dx) { + var x = d3.range(x0, x1 - ε, dx).concat(x1); + return function(y) { + return x.map(function(x) { + return [ x, y ]; + }); + }; + } + function d3_source(d) { + return d.source; + } + function d3_target(d) { + return d.target; + } + d3.geo.greatArc = function() { + var source = d3_source, source_, target = d3_target, target_; + function greatArc() { + return { + type: "LineString", + coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ] + }; + } + greatArc.distance = function() { + return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments)); + }; + greatArc.source = function(_) { + if (!arguments.length) return source; + source = _, source_ = typeof _ === "function" ? null : _; + return greatArc; + }; + greatArc.target = function(_) { + if (!arguments.length) return target; + target = _, target_ = typeof _ === "function" ? null : _; + return greatArc; + }; + greatArc.precision = function() { + return arguments.length ? greatArc : 0; + }; + return greatArc; + }; + d3.geo.interpolate = function(source, target) { + return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians); + }; + function d3_geo_interpolate(x0, y0, x1, y1) { + var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d); + var interpolate = d ? function(t) { + var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1; + return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ]; + } : function() { + return [ x0 * d3_degrees, y0 * d3_degrees ]; + }; + interpolate.distance = d; + return interpolate; + } + d3.geo.length = function(object) { + d3_geo_lengthSum = 0; + d3.geo.stream(object, d3_geo_length); + return d3_geo_lengthSum; + }; + var d3_geo_lengthSum; + var d3_geo_length = { + sphere: d3_noop, + point: d3_noop, + lineStart: d3_geo_lengthLineStart, + lineEnd: d3_noop, + polygonStart: d3_noop, + polygonEnd: d3_noop + }; + function d3_geo_lengthLineStart() { + var λ0, sinφ0, cosφ0; + d3_geo_length.point = function(λ, φ) { + λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ); + d3_geo_length.point = nextPoint; + }; + d3_geo_length.lineEnd = function() { + d3_geo_length.point = d3_geo_length.lineEnd = d3_noop; + }; + function nextPoint(λ, φ) { + var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t); + d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ); + λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ; + } + } + function d3_geo_azimuthal(scale, angle) { + function azimuthal(λ, φ) { + var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ); + return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ]; + } + azimuthal.invert = function(x, y) { + var Ï = Math.sqrt(x * x + y * y), c = angle(Ï), sinc = Math.sin(c), cosc = Math.cos(c); + return [ Math.atan2(x * sinc, Ï * cosc), Math.asin(Ï && y * sinc / Ï) ]; + }; + return azimuthal; + } + var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) { + return Math.sqrt(2 / (1 + cosλcosφ)); + }, function(Ï) { + return 2 * Math.asin(Ï / 2); + }); + (d3.geo.azimuthalEqualArea = function() { + return d3_geo_projection(d3_geo_azimuthalEqualArea); + }).raw = d3_geo_azimuthalEqualArea; + var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) { + var c = Math.acos(cosλcosφ); + return c && c / Math.sin(c); + }, d3_identity); + (d3.geo.azimuthalEquidistant = function() { + return d3_geo_projection(d3_geo_azimuthalEquidistant); + }).raw = d3_geo_azimuthalEquidistant; + function d3_geo_conicConformal(φ0, φ1) { + var cosφ0 = Math.cos(φ0), t = function(φ) { + return Math.tan(Ï€ / 4 + φ / 2); + }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n; + if (!n) return d3_geo_mercator; + function forward(λ, φ) { + if (F > 0) { + if (φ < -halfÏ€ + ε) φ = -halfÏ€ + ε; + } else { + if (φ > halfÏ€ - ε) φ = halfÏ€ - ε; + } + var Ï = F / Math.pow(t(φ), n); + return [ Ï * Math.sin(n * λ), F - Ï * Math.cos(n * λ) ]; + } + forward.invert = function(x, y) { + var Ï0_y = F - y, Ï = d3_sgn(n) * Math.sqrt(x * x + Ï0_y * Ï0_y); + return [ Math.atan2(x, Ï0_y) / n, 2 * Math.atan(Math.pow(F / Ï, 1 / n)) - halfÏ€ ]; + }; + return forward; + } + (d3.geo.conicConformal = function() { + return d3_geo_conic(d3_geo_conicConformal); + }).raw = d3_geo_conicConformal; + function d3_geo_conicEquidistant(φ0, φ1) { + var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0; + if (abs(n) < ε) return d3_geo_equirectangular; + function forward(λ, φ) { + var Ï = G - φ; + return [ Ï * Math.sin(n * λ), G - Ï * Math.cos(n * λ) ]; + } + forward.invert = function(x, y) { + var Ï0_y = G - y; + return [ Math.atan2(x, Ï0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + Ï0_y * Ï0_y) ]; + }; + return forward; + } + (d3.geo.conicEquidistant = function() { + return d3_geo_conic(d3_geo_conicEquidistant); + }).raw = d3_geo_conicEquidistant; + var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) { + return 1 / cosλcosφ; + }, Math.atan); + (d3.geo.gnomonic = function() { + return d3_geo_projection(d3_geo_gnomonic); + }).raw = d3_geo_gnomonic; + function d3_geo_mercator(λ, φ) { + return [ λ, Math.log(Math.tan(Ï€ / 4 + φ / 2)) ]; + } + d3_geo_mercator.invert = function(x, y) { + return [ x, 2 * Math.atan(Math.exp(y)) - halfÏ€ ]; + }; + function d3_geo_mercatorProjection(project) { + var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto; + m.scale = function() { + var v = scale.apply(m, arguments); + return v === m ? clipAuto ? m.clipExtent(null) : m : v; + }; + m.translate = function() { + var v = translate.apply(m, arguments); + return v === m ? clipAuto ? m.clipExtent(null) : m : v; + }; + m.clipExtent = function(_) { + var v = clipExtent.apply(m, arguments); + if (v === m) { + if (clipAuto = _ == null) { + var k = Ï€ * scale(), t = translate(); + clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]); + } + } else if (clipAuto) { + v = null; + } + return v; + }; + return m.clipExtent(null); + } + (d3.geo.mercator = function() { + return d3_geo_mercatorProjection(d3_geo_mercator); + }).raw = d3_geo_mercator; + var d3_geo_orthographic = d3_geo_azimuthal(function() { + return 1; + }, Math.asin); + (d3.geo.orthographic = function() { + return d3_geo_projection(d3_geo_orthographic); + }).raw = d3_geo_orthographic; + var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) { + return 1 / (1 + cosλcosφ); + }, function(Ï) { + return 2 * Math.atan(Ï); + }); + (d3.geo.stereographic = function() { + return d3_geo_projection(d3_geo_stereographic); + }).raw = d3_geo_stereographic; + function d3_geo_transverseMercator(λ, φ) { + return [ Math.log(Math.tan(Ï€ / 4 + φ / 2)), -λ ]; + } + d3_geo_transverseMercator.invert = function(x, y) { + return [ -y, 2 * Math.atan(Math.exp(x)) - halfÏ€ ]; + }; + (d3.geo.transverseMercator = function() { + var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate; + projection.center = function(_) { + return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]); + }; + projection.rotate = function(_) { + return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), + [ _[0], _[1], _[2] - 90 ]); + }; + return rotate([ 0, 0, 90 ]); + }).raw = d3_geo_transverseMercator; + d3.geom = {}; + function d3_geom_pointX(d) { + return d[0]; + } + function d3_geom_pointY(d) { + return d[1]; + } + d3.geom.hull = function(vertices) { + var x = d3_geom_pointX, y = d3_geom_pointY; + if (arguments.length) return hull(vertices); + function hull(data) { + if (data.length < 3) return []; + var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = []; + for (i = 0; i < n; i++) { + points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]); + } + points.sort(d3_geom_hullOrder); + for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]); + var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints); + var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = []; + for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]); + for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]); + return polygon; + } + hull.x = function(_) { + return arguments.length ? (x = _, hull) : x; + }; + hull.y = function(_) { + return arguments.length ? (y = _, hull) : y; + }; + return hull; + }; + function d3_geom_hullUpper(points) { + var n = points.length, hull = [ 0, 1 ], hs = 2; + for (var i = 2; i < n; i++) { + while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs; + hull[hs++] = i; + } + return hull.slice(0, hs); + } + function d3_geom_hullOrder(a, b) { + return a[0] - b[0] || a[1] - b[1]; + } + d3.geom.polygon = function(coordinates) { + d3_subclass(coordinates, d3_geom_polygonPrototype); + return coordinates; + }; + var d3_geom_polygonPrototype = d3.geom.polygon.prototype = []; + d3_geom_polygonPrototype.area = function() { + var i = -1, n = this.length, a, b = this[n - 1], area = 0; + while (++i < n) { + a = b; + b = this[i]; + area += a[1] * b[0] - a[0] * b[1]; + } + return area * .5; + }; + d3_geom_polygonPrototype.centroid = function(k) { + var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c; + if (!arguments.length) k = -1 / (6 * this.area()); + while (++i < n) { + a = b; + b = this[i]; + c = a[0] * b[1] - b[0] * a[1]; + x += (a[0] + b[0]) * c; + y += (a[1] + b[1]) * c; + } + return [ x * k, y * k ]; + }; + d3_geom_polygonPrototype.clip = function(subject) { + var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d; + while (++i < n) { + input = subject.slice(); + subject.length = 0; + b = this[i]; + c = input[(m = input.length - closed) - 1]; + j = -1; + while (++j < m) { + d = input[j]; + if (d3_geom_polygonInside(d, a, b)) { + if (!d3_geom_polygonInside(c, a, b)) { + subject.push(d3_geom_polygonIntersect(c, d, a, b)); + } + subject.push(d); + } else if (d3_geom_polygonInside(c, a, b)) { + subject.push(d3_geom_polygonIntersect(c, d, a, b)); + } + c = d; + } + if (closed) subject.push(subject[0]); + a = b; + } + return subject; + }; + function d3_geom_polygonInside(p, a, b) { + return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]); + } + function d3_geom_polygonIntersect(c, d, a, b) { + var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21); + return [ x1 + ua * x21, y1 + ua * y21 ]; + } + function d3_geom_polygonClosed(coordinates) { + var a = coordinates[0], b = coordinates[coordinates.length - 1]; + return !(a[0] - b[0] || a[1] - b[1]); + } + var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = []; + function d3_geom_voronoiBeach() { + d3_geom_voronoiRedBlackNode(this); + this.edge = this.site = this.circle = null; + } + function d3_geom_voronoiCreateBeach(site) { + var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach(); + beach.site = site; + return beach; + } + function d3_geom_voronoiDetachBeach(beach) { + d3_geom_voronoiDetachCircle(beach); + d3_geom_voronoiBeaches.remove(beach); + d3_geom_voronoiBeachPool.push(beach); + d3_geom_voronoiRedBlackNode(beach); + } + function d3_geom_voronoiRemoveBeach(beach) { + var circle = beach.circle, x = circle.x, y = circle.cy, vertex = { + x: x, + y: y + }, previous = beach.P, next = beach.N, disappearing = [ beach ]; + d3_geom_voronoiDetachBeach(beach); + var lArc = previous; + while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) { + previous = lArc.P; + disappearing.unshift(lArc); + d3_geom_voronoiDetachBeach(lArc); + lArc = previous; + } + disappearing.unshift(lArc); + d3_geom_voronoiDetachCircle(lArc); + var rArc = next; + while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) { + next = rArc.N; + disappearing.push(rArc); + d3_geom_voronoiDetachBeach(rArc); + rArc = next; + } + disappearing.push(rArc); + d3_geom_voronoiDetachCircle(rArc); + var nArcs = disappearing.length, iArc; + for (iArc = 1; iArc < nArcs; ++iArc) { + rArc = disappearing[iArc]; + lArc = disappearing[iArc - 1]; + d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); + } + lArc = disappearing[0]; + rArc = disappearing[nArcs - 1]; + rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + } + function d3_geom_voronoiAddBeach(site) { + var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._; + while (node) { + dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x; + if (dxl > ε) node = node.L; else { + dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix); + if (dxr > ε) { + if (!node.R) { + lArc = node; + break; + } + node = node.R; + } else { + if (dxl > -ε) { + lArc = node.P; + rArc = node; + } else if (dxr > -ε) { + lArc = node; + rArc = node.N; + } else { + lArc = rArc = node; + } + break; + } + } + } + var newArc = d3_geom_voronoiCreateBeach(site); + d3_geom_voronoiBeaches.insert(lArc, newArc); + if (!lArc && !rArc) return; + if (lArc === rArc) { + d3_geom_voronoiDetachCircle(lArc); + rArc = d3_geom_voronoiCreateBeach(lArc.site); + d3_geom_voronoiBeaches.insert(newArc, rArc); + newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + return; + } + if (!rArc) { + newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site); + return; + } + d3_geom_voronoiDetachCircle(lArc); + d3_geom_voronoiDetachCircle(rArc); + var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = { + x: (cy * hb - by * hc) / d + ax, + y: (bx * hc - cx * hb) / d + ay + }; + d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex); + newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex); + rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex); + d3_geom_voronoiAttachCircle(lArc); + d3_geom_voronoiAttachCircle(rArc); + } + function d3_geom_voronoiLeftBreakPoint(arc, directrix) { + var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix; + if (!pby2) return rfocx; + var lArc = arc.P; + if (!lArc) return -Infinity; + site = lArc.site; + var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix; + if (!plby2) return lfocx; + var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2; + if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; + return (rfocx + lfocx) / 2; + } + function d3_geom_voronoiRightBreakPoint(arc, directrix) { + var rArc = arc.N; + if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix); + var site = arc.site; + return site.y === directrix ? site.x : Infinity; + } + function d3_geom_voronoiCell(site) { + this.site = site; + this.edges = []; + } + d3_geom_voronoiCell.prototype.prepare = function() { + var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge; + while (iHalfEdge--) { + edge = halfEdges[iHalfEdge].edge; + if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1); + } + halfEdges.sort(d3_geom_voronoiHalfEdgeOrder); + return halfEdges.length; + }; + function d3_geom_voronoiCloseCells(extent) { + var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end; + while (iCell--) { + cell = cells[iCell]; + if (!cell || !cell.prepare()) continue; + halfEdges = cell.edges; + nHalfEdges = halfEdges.length; + iHalfEdge = 0; + while (iHalfEdge < nHalfEdges) { + end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y; + start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y; + if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) { + halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? { + x: x0, + y: abs(x2 - x0) < ε ? y2 : y1 + } : abs(y3 - y1) < ε && x1 - x3 > ε ? { + x: abs(y2 - y1) < ε ? x2 : x1, + y: y1 + } : abs(x3 - x1) < ε && y3 - y0 > ε ? { + x: x1, + y: abs(x2 - x1) < ε ? y2 : y0 + } : abs(y3 - y0) < ε && x3 - x0 > ε ? { + x: abs(y2 - y0) < ε ? x2 : x0, + y: y0 + } : null), cell.site, null)); + ++nHalfEdges; + } + } + } + } + function d3_geom_voronoiHalfEdgeOrder(a, b) { + return b.angle - a.angle; + } + function d3_geom_voronoiCircle() { + d3_geom_voronoiRedBlackNode(this); + this.x = this.y = this.arc = this.site = this.cy = null; + } + function d3_geom_voronoiAttachCircle(arc) { + var lArc = arc.P, rArc = arc.N; + if (!lArc || !rArc) return; + var lSite = lArc.site, cSite = arc.site, rSite = rArc.site; + if (lSite === rSite) return; + var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by; + var d = 2 * (ax * cy - ay * cx); + if (d >= -ε2) return; + var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by; + var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle(); + circle.arc = arc; + circle.site = cSite; + circle.x = x + bx; + circle.y = cy + Math.sqrt(x * x + y * y); + circle.cy = cy; + arc.circle = circle; + var before = null, node = d3_geom_voronoiCircles._; + while (node) { + if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) { + if (node.L) node = node.L; else { + before = node.P; + break; + } + } else { + if (node.R) node = node.R; else { + before = node; + break; + } + } + } + d3_geom_voronoiCircles.insert(before, circle); + if (!before) d3_geom_voronoiFirstCircle = circle; + } + function d3_geom_voronoiDetachCircle(arc) { + var circle = arc.circle; + if (circle) { + if (!circle.P) d3_geom_voronoiFirstCircle = circle.N; + d3_geom_voronoiCircles.remove(circle); + d3_geom_voronoiCirclePool.push(circle); + d3_geom_voronoiRedBlackNode(circle); + arc.circle = null; + } + } + function d3_geom_voronoiClipEdges(extent) { + var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e; + while (i--) { + e = edges[i]; + if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) { + e.a = e.b = null; + edges.splice(i, 1); + } + } + } + function d3_geom_voronoiConnectEdge(edge, extent) { + var vb = edge.b; + if (vb) return true; + var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb; + if (ry === ly) { + if (fx < x0 || fx >= x1) return; + if (lx > rx) { + if (!va) va = { + x: fx, + y: y0 + }; else if (va.y >= y1) return; + vb = { + x: fx, + y: y1 + }; + } else { + if (!va) va = { + x: fx, + y: y1 + }; else if (va.y < y0) return; + vb = { + x: fx, + y: y0 + }; + } + } else { + fm = (lx - rx) / (ry - ly); + fb = fy - fm * fx; + if (fm < -1 || fm > 1) { + if (lx > rx) { + if (!va) va = { + x: (y0 - fb) / fm, + y: y0 + }; else if (va.y >= y1) return; + vb = { + x: (y1 - fb) / fm, + y: y1 + }; + } else { + if (!va) va = { + x: (y1 - fb) / fm, + y: y1 + }; else if (va.y < y0) return; + vb = { + x: (y0 - fb) / fm, + y: y0 + }; + } + } else { + if (ly < ry) { + if (!va) va = { + x: x0, + y: fm * x0 + fb + }; else if (va.x >= x1) return; + vb = { + x: x1, + y: fm * x1 + fb + }; + } else { + if (!va) va = { + x: x1, + y: fm * x1 + fb + }; else if (va.x < x0) return; + vb = { + x: x0, + y: fm * x0 + fb + }; + } + } + } + edge.a = va; + edge.b = vb; + return true; + } + function d3_geom_voronoiEdge(lSite, rSite) { + this.l = lSite; + this.r = rSite; + this.a = this.b = null; + } + function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) { + var edge = new d3_geom_voronoiEdge(lSite, rSite); + d3_geom_voronoiEdges.push(edge); + if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va); + if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb); + d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite)); + d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite)); + return edge; + } + function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) { + var edge = new d3_geom_voronoiEdge(lSite, null); + edge.a = va; + edge.b = vb; + d3_geom_voronoiEdges.push(edge); + return edge; + } + function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) { + if (!edge.a && !edge.b) { + edge.a = vertex; + edge.l = lSite; + edge.r = rSite; + } else if (edge.l === rSite) { + edge.b = vertex; + } else { + edge.a = vertex; + } + } + function d3_geom_voronoiHalfEdge(edge, lSite, rSite) { + var va = edge.a, vb = edge.b; + this.edge = edge; + this.site = lSite; + this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y); + } + d3_geom_voronoiHalfEdge.prototype = { + start: function() { + return this.edge.l === this.site ? this.edge.a : this.edge.b; + }, + end: function() { + return this.edge.l === this.site ? this.edge.b : this.edge.a; + } + }; + function d3_geom_voronoiRedBlackTree() { + this._ = null; + } + function d3_geom_voronoiRedBlackNode(node) { + node.U = node.C = node.L = node.R = node.P = node.N = null; + } + d3_geom_voronoiRedBlackTree.prototype = { + insert: function(after, node) { + var parent, grandpa, uncle; + if (after) { + node.P = after; + node.N = after.N; + if (after.N) after.N.P = node; + after.N = node; + if (after.R) { + after = after.R; + while (after.L) after = after.L; + after.L = node; + } else { + after.R = node; + } + parent = after; + } else if (this._) { + after = d3_geom_voronoiRedBlackFirst(this._); + node.P = null; + node.N = after; + after.P = after.L = node; + parent = after; + } else { + node.P = node.N = null; + this._ = node; + parent = null; + } + node.L = node.R = null; + node.U = parent; + node.C = true; + after = node; + while (parent && parent.C) { + grandpa = parent.U; + if (parent === grandpa.L) { + uncle = grandpa.R; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.R) { + d3_geom_voronoiRedBlackRotateLeft(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + d3_geom_voronoiRedBlackRotateRight(this, grandpa); + } + } else { + uncle = grandpa.L; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.L) { + d3_geom_voronoiRedBlackRotateRight(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, grandpa); + } + } + parent = after.U; + } + this._.C = false; + }, + remove: function(node) { + if (node.N) node.N.P = node.P; + if (node.P) node.P.N = node.N; + node.N = node.P = null; + var parent = node.U, sibling, left = node.L, right = node.R, next, red; + if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right); + if (parent) { + if (parent.L === node) parent.L = next; else parent.R = next; + } else { + this._ = next; + } + if (left && right) { + red = next.C; + next.C = node.C; + next.L = left; + left.U = next; + if (next !== right) { + parent = next.U; + next.U = node.U; + node = next.R; + parent.L = node; + next.R = right; + right.U = next; + } else { + next.U = parent; + parent = next; + node = next.R; + } + } else { + red = node.C; + node = next; + } + if (node) node.U = parent; + if (red) return; + if (node && node.C) { + node.C = false; + return; + } + do { + if (node === this._) break; + if (node === parent.L) { + sibling = parent.R; + if (sibling.C) { + sibling.C = false; + parent.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, parent); + sibling = parent.R; + } + if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { + if (!sibling.R || !sibling.R.C) { + sibling.L.C = false; + sibling.C = true; + d3_geom_voronoiRedBlackRotateRight(this, sibling); + sibling = parent.R; + } + sibling.C = parent.C; + parent.C = sibling.R.C = false; + d3_geom_voronoiRedBlackRotateLeft(this, parent); + node = this._; + break; + } + } else { + sibling = parent.L; + if (sibling.C) { + sibling.C = false; + parent.C = true; + d3_geom_voronoiRedBlackRotateRight(this, parent); + sibling = parent.L; + } + if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) { + if (!sibling.L || !sibling.L.C) { + sibling.R.C = false; + sibling.C = true; + d3_geom_voronoiRedBlackRotateLeft(this, sibling); + sibling = parent.L; + } + sibling.C = parent.C; + parent.C = sibling.L.C = false; + d3_geom_voronoiRedBlackRotateRight(this, parent); + node = this._; + break; + } + } + sibling.C = true; + node = parent; + parent = parent.U; + } while (!node.C); + if (node) node.C = false; + } + }; + function d3_geom_voronoiRedBlackRotateLeft(tree, node) { + var p = node, q = node.R, parent = p.U; + if (parent) { + if (parent.L === p) parent.L = q; else parent.R = q; + } else { + tree._ = q; + } + q.U = parent; + p.U = q; + p.R = q.L; + if (p.R) p.R.U = p; + q.L = p; + } + function d3_geom_voronoiRedBlackRotateRight(tree, node) { + var p = node, q = node.L, parent = p.U; + if (parent) { + if (parent.L === p) parent.L = q; else parent.R = q; + } else { + tree._ = q; + } + q.U = parent; + p.U = q; + p.L = q.R; + if (p.L) p.L.U = p; + q.R = p; + } + function d3_geom_voronoiRedBlackFirst(node) { + while (node.L) node = node.L; + return node; + } + function d3_geom_voronoi(sites, bbox) { + var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle; + d3_geom_voronoiEdges = []; + d3_geom_voronoiCells = new Array(sites.length); + d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree(); + d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree(); + while (true) { + circle = d3_geom_voronoiFirstCircle; + if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) { + if (site.x !== x0 || site.y !== y0) { + d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site); + d3_geom_voronoiAddBeach(site); + x0 = site.x, y0 = site.y; + } + site = sites.pop(); + } else if (circle) { + d3_geom_voronoiRemoveBeach(circle.arc); + } else { + break; + } + } + if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox); + var diagram = { + cells: d3_geom_voronoiCells, + edges: d3_geom_voronoiEdges + }; + d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null; + return diagram; + } + function d3_geom_voronoiVertexOrder(a, b) { + return b.y - a.y || b.x - a.x; + } + d3.geom.voronoi = function(points) { + var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent; + if (points) return voronoi(points); + function voronoi(data) { + var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1]; + d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) { + var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) { + var s = e.start(); + return [ s.x, s.y ]; + }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : []; + polygon.point = data[i]; + }); + return polygons; + } + function sites(data) { + return data.map(function(d, i) { + return { + x: Math.round(fx(d, i) / ε) * ε, + y: Math.round(fy(d, i) / ε) * ε, + i: i + }; + }); + } + voronoi.links = function(data) { + return d3_geom_voronoi(sites(data)).edges.filter(function(edge) { + return edge.l && edge.r; + }).map(function(edge) { + return { + source: data[edge.l.i], + target: data[edge.r.i] + }; + }); + }; + voronoi.triangles = function(data) { + var triangles = []; + d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) { + var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l; + while (++j < m) { + e0 = e1; + s0 = s1; + e1 = edges[j].edge; + s1 = e1.l === site ? e1.r : e1.l; + if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) { + triangles.push([ data[i], data[s0.i], data[s1.i] ]); + } + } + }); + return triangles; + }; + voronoi.x = function(_) { + return arguments.length ? (fx = d3_functor(x = _), voronoi) : x; + }; + voronoi.y = function(_) { + return arguments.length ? (fy = d3_functor(y = _), voronoi) : y; + }; + voronoi.clipExtent = function(_) { + if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent; + clipExtent = _ == null ? d3_geom_voronoiClipExtent : _; + return voronoi; + }; + voronoi.size = function(_) { + if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1]; + return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]); + }; + return voronoi; + }; + var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ]; + function d3_geom_voronoiTriangleArea(a, b, c) { + return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y); + } + d3.geom.delaunay = function(vertices) { + return d3.geom.voronoi().triangles(vertices); + }; + d3.geom.quadtree = function(points, x1, y1, x2, y2) { + var x = d3_geom_pointX, y = d3_geom_pointY, compat; + if (compat = arguments.length) { + x = d3_geom_quadtreeCompatX; + y = d3_geom_quadtreeCompatY; + if (compat === 3) { + y2 = y1; + x2 = x1; + y1 = x1 = 0; + } + return quadtree(points); + } + function quadtree(data) { + var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_; + if (x1 != null) { + x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2; + } else { + x2_ = y2_ = -(x1_ = y1_ = Infinity); + xs = [], ys = []; + n = data.length; + if (compat) for (i = 0; i < n; ++i) { + d = data[i]; + if (d.x < x1_) x1_ = d.x; + if (d.y < y1_) y1_ = d.y; + if (d.x > x2_) x2_ = d.x; + if (d.y > y2_) y2_ = d.y; + xs.push(d.x); + ys.push(d.y); + } else for (i = 0; i < n; ++i) { + var x_ = +fx(d = data[i], i), y_ = +fy(d, i); + if (x_ < x1_) x1_ = x_; + if (y_ < y1_) y1_ = y_; + if (x_ > x2_) x2_ = x_; + if (y_ > y2_) y2_ = y_; + xs.push(x_); + ys.push(y_); + } + } + var dx = x2_ - x1_, dy = y2_ - y1_; + if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy; + function insert(n, d, x, y, x1, y1, x2, y2) { + if (isNaN(x) || isNaN(y)) return; + if (n.leaf) { + var nx = n.x, ny = n.y; + if (nx != null) { + if (abs(nx - x) + abs(ny - y) < .01) { + insertChild(n, d, x, y, x1, y1, x2, y2); + } else { + var nPoint = n.point; + n.x = n.y = n.point = null; + insertChild(n, nPoint, nx, ny, x1, y1, x2, y2); + insertChild(n, d, x, y, x1, y1, x2, y2); + } + } else { + n.x = x, n.y = y, n.point = d; + } + } else { + insertChild(n, d, x, y, x1, y1, x2, y2); + } + } + function insertChild(n, d, x, y, x1, y1, x2, y2) { + var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = x >= sx, bottom = y >= sy, i = (bottom << 1) + right; + n.leaf = false; + n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode()); + if (right) x1 = sx; else x2 = sx; + if (bottom) y1 = sy; else y2 = sy; + insert(n, d, x, y, x1, y1, x2, y2); + } + var root = d3_geom_quadtreeNode(); + root.add = function(d) { + insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_); + }; + root.visit = function(f) { + d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_); + }; + i = -1; + if (x1 == null) { + while (++i < n) { + insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_); + } + --i; + } else data.forEach(root.add); + xs = ys = data = d = null; + return root; + } + quadtree.x = function(_) { + return arguments.length ? (x = _, quadtree) : x; + }; + quadtree.y = function(_) { + return arguments.length ? (y = _, quadtree) : y; + }; + quadtree.extent = function(_) { + if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ]; + if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], + y2 = +_[1][1]; + return quadtree; + }; + quadtree.size = function(_) { + if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ]; + if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1]; + return quadtree; + }; + return quadtree; + }; + function d3_geom_quadtreeCompatX(d) { + return d.x; + } + function d3_geom_quadtreeCompatY(d) { + return d.y; + } + function d3_geom_quadtreeNode() { + return { + leaf: true, + nodes: [], + point: null, + x: null, + y: null + }; + } + function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) { + if (!f(node, x1, y1, x2, y2)) { + var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes; + if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy); + if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy); + if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2); + if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2); + } + } + d3.interpolateRgb = d3_interpolateRgb; + function d3_interpolateRgb(a, b) { + a = d3.rgb(a); + b = d3.rgb(b); + var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab; + return function(t) { + return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t)); + }; + } + d3.interpolateObject = d3_interpolateObject; + function d3_interpolateObject(a, b) { + var i = {}, c = {}, k; + for (k in a) { + if (k in b) { + i[k] = d3_interpolate(a[k], b[k]); + } else { + c[k] = a[k]; + } + } + for (k in b) { + if (!(k in a)) { + c[k] = b[k]; + } + } + return function(t) { + for (k in i) c[k] = i[k](t); + return c; + }; + } + d3.interpolateNumber = d3_interpolateNumber; + function d3_interpolateNumber(a, b) { + b -= a = +a; + return function(t) { + return a + b * t; + }; + } + d3.interpolateString = d3_interpolateString; + function d3_interpolateString(a, b) { + var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = []; + a = a + "", b = b + ""; + while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) { + if ((bs = bm.index) > bi) { + bs = b.substring(bi, bs); + if (s[i]) s[i] += bs; else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { + if (s[i]) s[i] += bm; else s[++i] = bm; + } else { + s[++i] = null; + q.push({ + i: i, + x: d3_interpolateNumber(am, bm) + }); + } + bi = d3_interpolate_numberB.lastIndex; + } + if (bi < b.length) { + bs = b.substring(bi); + if (s[i]) s[i] += bs; else s[++i] = bs; + } + return s.length < 2 ? q[0] ? (b = q[0].x, function(t) { + return b(t) + ""; + }) : function() { + return b; + } : (b = q.length, function(t) { + for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }); + } + var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g"); + d3.interpolate = d3_interpolate; + function d3_interpolate(a, b) { + var i = d3.interpolators.length, f; + while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ; + return f; + } + d3.interpolators = [ function(a, b) { + var t = typeof b; + return (t === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b); + } ]; + d3.interpolateArray = d3_interpolateArray; + function d3_interpolateArray(a, b) { + var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i; + for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i])); + for (;i < na; ++i) c[i] = a[i]; + for (;i < nb; ++i) c[i] = b[i]; + return function(t) { + for (i = 0; i < n0; ++i) c[i] = x[i](t); + return c; + }; + } + var d3_ease_default = function() { + return d3_identity; + }; + var d3_ease = d3.map({ + linear: d3_ease_default, + poly: d3_ease_poly, + quad: function() { + return d3_ease_quad; + }, + cubic: function() { + return d3_ease_cubic; + }, + sin: function() { + return d3_ease_sin; + }, + exp: function() { + return d3_ease_exp; + }, + circle: function() { + return d3_ease_circle; + }, + elastic: d3_ease_elastic, + back: d3_ease_back, + bounce: function() { + return d3_ease_bounce; + } + }); + var d3_ease_mode = d3.map({ + "in": d3_identity, + out: d3_ease_reverse, + "in-out": d3_ease_reflect, + "out-in": function(f) { + return d3_ease_reflect(d3_ease_reverse(f)); + } + }); + d3.ease = function(name) { + var i = name.indexOf("-"), t = i >= 0 ? name.substring(0, i) : name, m = i >= 0 ? name.substring(i + 1) : "in"; + t = d3_ease.get(t) || d3_ease_default; + m = d3_ease_mode.get(m) || d3_identity; + return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1)))); + }; + function d3_ease_clamp(f) { + return function(t) { + return t <= 0 ? 0 : t >= 1 ? 1 : f(t); + }; + } + function d3_ease_reverse(f) { + return function(t) { + return 1 - f(1 - t); + }; + } + function d3_ease_reflect(f) { + return function(t) { + return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t)); + }; + } + function d3_ease_quad(t) { + return t * t; + } + function d3_ease_cubic(t) { + return t * t * t; + } + function d3_ease_cubicInOut(t) { + if (t <= 0) return 0; + if (t >= 1) return 1; + var t2 = t * t, t3 = t2 * t; + return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75); + } + function d3_ease_poly(e) { + return function(t) { + return Math.pow(t, e); + }; + } + function d3_ease_sin(t) { + return 1 - Math.cos(t * halfÏ€); + } + function d3_ease_exp(t) { + return Math.pow(2, 10 * (t - 1)); + } + function d3_ease_circle(t) { + return 1 - Math.sqrt(1 - t * t); + } + function d3_ease_elastic(a, p) { + var s; + if (arguments.length < 2) p = .45; + if (arguments.length) s = p / Ï„ * Math.asin(1 / a); else a = 1, s = p / 4; + return function(t) { + return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * Ï„ / p); + }; + } + function d3_ease_back(s) { + if (!s) s = 1.70158; + return function(t) { + return t * t * ((s + 1) * t - s); + }; + } + function d3_ease_bounce(t) { + return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375; + } + d3.interpolateHcl = d3_interpolateHcl; + function d3_interpolateHcl(a, b) { + a = d3.hcl(a); + b = d3.hcl(b); + var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al; + if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac; + if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; + return function(t) { + return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + ""; + }; + } + d3.interpolateHsl = d3_interpolateHsl; + function d3_interpolateHsl(a, b) { + a = d3.hsl(a); + b = d3.hsl(b); + var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al; + if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as; + if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360; + return function(t) { + return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + ""; + }; + } + d3.interpolateLab = d3_interpolateLab; + function d3_interpolateLab(a, b) { + a = d3.lab(a); + b = d3.lab(b); + var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab; + return function(t) { + return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + ""; + }; + } + d3.interpolateRound = d3_interpolateRound; + function d3_interpolateRound(a, b) { + b -= a; + return function(t) { + return Math.round(a + b * t); + }; + } + d3.transform = function(string) { + var g = d3_document.createElementNS(d3.ns.prefix.svg, "g"); + return (d3.transform = function(string) { + if (string != null) { + g.setAttribute("transform", string); + var t = g.transform.baseVal.consolidate(); + } + return new d3_transform(t ? t.matrix : d3_transformIdentity); + })(string); + }; + function d3_transform(m) { + var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0; + if (r0[0] * r1[1] < r1[0] * r0[1]) { + r0[0] *= -1; + r0[1] *= -1; + kx *= -1; + kz *= -1; + } + this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees; + this.translate = [ m.e, m.f ]; + this.scale = [ kx, ky ]; + this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0; + } + d3_transform.prototype.toString = function() { + return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")"; + }; + function d3_transformDot(a, b) { + return a[0] * b[0] + a[1] * b[1]; + } + function d3_transformNormalize(a) { + var k = Math.sqrt(d3_transformDot(a, a)); + if (k) { + a[0] /= k; + a[1] /= k; + } + return k; + } + function d3_transformCombine(a, b, k) { + a[0] += k * b[0]; + a[1] += k * b[1]; + return a; + } + var d3_transformIdentity = { + a: 1, + b: 0, + c: 0, + d: 1, + e: 0, + f: 0 + }; + d3.interpolateTransform = d3_interpolateTransform; + function d3_interpolateTransform(a, b) { + var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale; + if (ta[0] != tb[0] || ta[1] != tb[1]) { + s.push("translate(", null, ",", null, ")"); + q.push({ + i: 1, + x: d3_interpolateNumber(ta[0], tb[0]) + }, { + i: 3, + x: d3_interpolateNumber(ta[1], tb[1]) + }); + } else if (tb[0] || tb[1]) { + s.push("translate(" + tb + ")"); + } else { + s.push(""); + } + if (ra != rb) { + if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; + q.push({ + i: s.push(s.pop() + "rotate(", null, ")") - 2, + x: d3_interpolateNumber(ra, rb) + }); + } else if (rb) { + s.push(s.pop() + "rotate(" + rb + ")"); + } + if (wa != wb) { + q.push({ + i: s.push(s.pop() + "skewX(", null, ")") - 2, + x: d3_interpolateNumber(wa, wb) + }); + } else if (wb) { + s.push(s.pop() + "skewX(" + wb + ")"); + } + if (ka[0] != kb[0] || ka[1] != kb[1]) { + n = s.push(s.pop() + "scale(", null, ",", null, ")"); + q.push({ + i: n - 4, + x: d3_interpolateNumber(ka[0], kb[0]) + }, { + i: n - 2, + x: d3_interpolateNumber(ka[1], kb[1]) + }); + } else if (kb[0] != 1 || kb[1] != 1) { + s.push(s.pop() + "scale(" + kb + ")"); + } + n = q.length; + return function(t) { + var i = -1, o; + while (++i < n) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + } + function d3_uninterpolateNumber(a, b) { + b = b - (a = +a) ? 1 / (b - a) : 0; + return function(x) { + return (x - a) * b; + }; + } + function d3_uninterpolateClamp(a, b) { + b = b - (a = +a) ? 1 / (b - a) : 0; + return function(x) { + return Math.max(0, Math.min(1, (x - a) * b)); + }; + } + d3.layout = {}; + d3.layout.bundle = function() { + return function(links) { + var paths = [], i = -1, n = links.length; + while (++i < n) paths.push(d3_layout_bundlePath(links[i])); + return paths; + }; + }; + function d3_layout_bundlePath(link) { + var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ]; + while (start !== lca) { + start = start.parent; + points.push(start); + } + var k = points.length; + while (end !== lca) { + points.splice(k, 0, end); + end = end.parent; + } + return points; + } + function d3_layout_bundleAncestors(node) { + var ancestors = [], parent = node.parent; + while (parent != null) { + ancestors.push(node); + node = parent; + parent = parent.parent; + } + ancestors.push(node); + return ancestors; + } + function d3_layout_bundleLeastCommonAncestor(a, b) { + if (a === b) return a; + var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null; + while (aNode === bNode) { + sharedNode = aNode; + aNode = aNodes.pop(); + bNode = bNodes.pop(); + } + return sharedNode; + } + d3.layout.chord = function() { + var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords; + function relayout() { + var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j; + chords = []; + groups = []; + k = 0, i = -1; + while (++i < n) { + x = 0, j = -1; + while (++j < n) { + x += matrix[i][j]; + } + groupSums.push(x); + subgroupIndex.push(d3.range(n)); + k += x; + } + if (sortGroups) { + groupIndex.sort(function(a, b) { + return sortGroups(groupSums[a], groupSums[b]); + }); + } + if (sortSubgroups) { + subgroupIndex.forEach(function(d, i) { + d.sort(function(a, b) { + return sortSubgroups(matrix[i][a], matrix[i][b]); + }); + }); + } + k = (Ï„ - padding * n) / k; + x = 0, i = -1; + while (++i < n) { + x0 = x, j = -1; + while (++j < n) { + var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k; + subgroups[di + "-" + dj] = { + index: di, + subindex: dj, + startAngle: a0, + endAngle: a1, + value: v + }; + } + groups[di] = { + index: di, + startAngle: x0, + endAngle: x, + value: (x - x0) / k + }; + x += padding; + } + i = -1; + while (++i < n) { + j = i - 1; + while (++j < n) { + var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i]; + if (source.value || target.value) { + chords.push(source.value < target.value ? { + source: target, + target: source + } : { + source: source, + target: target + }); + } + } + } + if (sortChords) resort(); + } + function resort() { + chords.sort(function(a, b) { + return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2); + }); + } + chord.matrix = function(x) { + if (!arguments.length) return matrix; + n = (matrix = x) && matrix.length; + chords = groups = null; + return chord; + }; + chord.padding = function(x) { + if (!arguments.length) return padding; + padding = x; + chords = groups = null; + return chord; + }; + chord.sortGroups = function(x) { + if (!arguments.length) return sortGroups; + sortGroups = x; + chords = groups = null; + return chord; + }; + chord.sortSubgroups = function(x) { + if (!arguments.length) return sortSubgroups; + sortSubgroups = x; + chords = null; + return chord; + }; + chord.sortChords = function(x) { + if (!arguments.length) return sortChords; + sortChords = x; + if (chords) resort(); + return chord; + }; + chord.chords = function() { + if (!chords) relayout(); + return chords; + }; + chord.groups = function() { + if (!groups) relayout(); + return groups; + }; + return chord; + }; + d3.layout.force = function() { + var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges; + function repulse(node) { + return function(quad, x1, _, x2) { + if (quad.point !== node) { + var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy; + if (dw * dw / theta2 < dn) { + if (dn < chargeDistance2) { + var k = quad.charge / dn; + node.px -= dx * k; + node.py -= dy * k; + } + return true; + } + if (quad.point && dn && dn < chargeDistance2) { + var k = quad.pointCharge / dn; + node.px -= dx * k; + node.py -= dy * k; + } + } + return !quad.charge; + }; + } + force.tick = function() { + if ((alpha *= .99) < .005) { + event.end({ + type: "end", + alpha: alpha = 0 + }); + return true; + } + var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y; + for (i = 0; i < m; ++i) { + o = links[i]; + s = o.source; + t = o.target; + x = t.x - s.x; + y = t.y - s.y; + if (l = x * x + y * y) { + l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; + x *= l; + y *= l; + t.x -= x * (k = s.weight / (t.weight + s.weight)); + t.y -= y * k; + s.x += x * (k = 1 - k); + s.y += y * k; + } + } + if (k = alpha * gravity) { + x = size[0] / 2; + y = size[1] / 2; + i = -1; + if (k) while (++i < n) { + o = nodes[i]; + o.x += (x - o.x) * k; + o.y += (y - o.y) * k; + } + } + if (charge) { + d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges); + i = -1; + while (++i < n) { + if (!(o = nodes[i]).fixed) { + q.visit(repulse(o)); + } + } + } + i = -1; + while (++i < n) { + o = nodes[i]; + if (o.fixed) { + o.x = o.px; + o.y = o.py; + } else { + o.x -= (o.px - (o.px = o.x)) * friction; + o.y -= (o.py - (o.py = o.y)) * friction; + } + } + event.tick({ + type: "tick", + alpha: alpha + }); + }; + force.nodes = function(x) { + if (!arguments.length) return nodes; + nodes = x; + return force; + }; + force.links = function(x) { + if (!arguments.length) return links; + links = x; + return force; + }; + force.size = function(x) { + if (!arguments.length) return size; + size = x; + return force; + }; + force.linkDistance = function(x) { + if (!arguments.length) return linkDistance; + linkDistance = typeof x === "function" ? x : +x; + return force; + }; + force.distance = force.linkDistance; + force.linkStrength = function(x) { + if (!arguments.length) return linkStrength; + linkStrength = typeof x === "function" ? x : +x; + return force; + }; + force.friction = function(x) { + if (!arguments.length) return friction; + friction = +x; + return force; + }; + force.charge = function(x) { + if (!arguments.length) return charge; + charge = typeof x === "function" ? x : +x; + return force; + }; + force.chargeDistance = function(x) { + if (!arguments.length) return Math.sqrt(chargeDistance2); + chargeDistance2 = x * x; + return force; + }; + force.gravity = function(x) { + if (!arguments.length) return gravity; + gravity = +x; + return force; + }; + force.theta = function(x) { + if (!arguments.length) return Math.sqrt(theta2); + theta2 = x * x; + return force; + }; + force.alpha = function(x) { + if (!arguments.length) return alpha; + x = +x; + if (alpha) { + if (x > 0) alpha = x; else alpha = 0; + } else if (x > 0) { + event.start({ + type: "start", + alpha: alpha = x + }); + d3.timer(force.tick); + } + return force; + }; + force.start = function() { + var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o; + for (i = 0; i < n; ++i) { + (o = nodes[i]).index = i; + o.weight = 0; + } + for (i = 0; i < m; ++i) { + o = links[i]; + if (typeof o.source == "number") o.source = nodes[o.source]; + if (typeof o.target == "number") o.target = nodes[o.target]; + ++o.source.weight; + ++o.target.weight; + } + for (i = 0; i < n; ++i) { + o = nodes[i]; + if (isNaN(o.x)) o.x = position("x", w); + if (isNaN(o.y)) o.y = position("y", h); + if (isNaN(o.px)) o.px = o.x; + if (isNaN(o.py)) o.py = o.y; + } + distances = []; + if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance; + strengths = []; + if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength; + charges = []; + if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge; + function position(dimension, size) { + if (!neighbors) { + neighbors = new Array(n); + for (j = 0; j < n; ++j) { + neighbors[j] = []; + } + for (j = 0; j < m; ++j) { + var o = links[j]; + neighbors[o.source.index].push(o.target); + neighbors[o.target.index].push(o.source); + } + } + var candidates = neighbors[i], j = -1, m = candidates.length, x; + while (++j < m) if (!isNaN(x = candidates[j][dimension])) return x; + return Math.random() * size; + } + return force.resume(); + }; + force.resume = function() { + return force.alpha(.1); + }; + force.stop = function() { + return force.alpha(0); + }; + force.drag = function() { + if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend); + if (!arguments.length) return drag; + this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag); + }; + function dragmove(d) { + d.px = d3.event.x, d.py = d3.event.y; + force.resume(); + } + return d3.rebind(force, event, "on"); + }; + function d3_layout_forceDragstart(d) { + d.fixed |= 2; + } + function d3_layout_forceDragend(d) { + d.fixed &= ~6; + } + function d3_layout_forceMouseover(d) { + d.fixed |= 4; + d.px = d.x, d.py = d.y; + } + function d3_layout_forceMouseout(d) { + d.fixed &= ~4; + } + function d3_layout_forceAccumulate(quad, alpha, charges) { + var cx = 0, cy = 0; + quad.charge = 0; + if (!quad.leaf) { + var nodes = quad.nodes, n = nodes.length, i = -1, c; + while (++i < n) { + c = nodes[i]; + if (c == null) continue; + d3_layout_forceAccumulate(c, alpha, charges); + quad.charge += c.charge; + cx += c.charge * c.cx; + cy += c.charge * c.cy; + } + } + if (quad.point) { + if (!quad.leaf) { + quad.point.x += Math.random() - .5; + quad.point.y += Math.random() - .5; + } + var k = alpha * charges[quad.point.index]; + quad.charge += quad.pointCharge = k; + cx += k * quad.point.x; + cy += k * quad.point.y; + } + quad.cx = cx / quad.charge; + quad.cy = cy / quad.charge; + } + var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity; + d3.layout.hierarchy = function() { + var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue; + function hierarchy(root) { + var stack = [ root ], nodes = [], node; + root.depth = 0; + while ((node = stack.pop()) != null) { + nodes.push(node); + if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) { + var n, childs, child; + while (--n >= 0) { + stack.push(child = childs[n]); + child.parent = node; + child.depth = node.depth + 1; + } + if (value) node.value = 0; + node.children = childs; + } else { + if (value) node.value = +value.call(hierarchy, node, node.depth) || 0; + delete node.children; + } + } + d3_layout_hierarchyVisitAfter(root, function(node) { + var childs, parent; + if (sort && (childs = node.children)) childs.sort(sort); + if (value && (parent = node.parent)) parent.value += node.value; + }); + return nodes; + } + hierarchy.sort = function(x) { + if (!arguments.length) return sort; + sort = x; + return hierarchy; + }; + hierarchy.children = function(x) { + if (!arguments.length) return children; + children = x; + return hierarchy; + }; + hierarchy.value = function(x) { + if (!arguments.length) return value; + value = x; + return hierarchy; + }; + hierarchy.revalue = function(root) { + if (value) { + d3_layout_hierarchyVisitBefore(root, function(node) { + if (node.children) node.value = 0; + }); + d3_layout_hierarchyVisitAfter(root, function(node) { + var parent; + if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0; + if (parent = node.parent) parent.value += node.value; + }); + } + return root; + }; + return hierarchy; + }; + function d3_layout_hierarchyRebind(object, hierarchy) { + d3.rebind(object, hierarchy, "sort", "children", "value"); + object.nodes = object; + object.links = d3_layout_hierarchyLinks; + return object; + } + function d3_layout_hierarchyVisitBefore(node, callback) { + var nodes = [ node ]; + while ((node = nodes.pop()) != null) { + callback(node); + if ((children = node.children) && (n = children.length)) { + var n, children; + while (--n >= 0) nodes.push(children[n]); + } + } + } + function d3_layout_hierarchyVisitAfter(node, callback) { + var nodes = [ node ], nodes2 = []; + while ((node = nodes.pop()) != null) { + nodes2.push(node); + if ((children = node.children) && (n = children.length)) { + var i = -1, n, children; + while (++i < n) nodes.push(children[i]); + } + } + while ((node = nodes2.pop()) != null) { + callback(node); + } + } + function d3_layout_hierarchyChildren(d) { + return d.children; + } + function d3_layout_hierarchyValue(d) { + return d.value; + } + function d3_layout_hierarchySort(a, b) { + return b.value - a.value; + } + function d3_layout_hierarchyLinks(nodes) { + return d3.merge(nodes.map(function(parent) { + return (parent.children || []).map(function(child) { + return { + source: parent, + target: child + }; + }); + })); + } + d3.layout.partition = function() { + var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ]; + function position(node, x, dx, dy) { + var children = node.children; + node.x = x; + node.y = node.depth * dy; + node.dx = dx; + node.dy = dy; + if (children && (n = children.length)) { + var i = -1, n, c, d; + dx = node.value ? dx / node.value : 0; + while (++i < n) { + position(c = children[i], x, d = c.value * dx, dy); + x += d; + } + } + } + function depth(node) { + var children = node.children, d = 0; + if (children && (n = children.length)) { + var i = -1, n; + while (++i < n) d = Math.max(d, depth(children[i])); + } + return 1 + d; + } + function partition(d, i) { + var nodes = hierarchy.call(this, d, i); + position(nodes[0], 0, size[0], size[1] / depth(nodes[0])); + return nodes; + } + partition.size = function(x) { + if (!arguments.length) return size; + size = x; + return partition; + }; + return d3_layout_hierarchyRebind(partition, hierarchy); + }; + d3.layout.pie = function() { + var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = Ï„; + function pie(data) { + var values = data.map(function(d, i) { + return +value.call(pie, d, i); + }); + var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle); + var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a) / d3.sum(values); + var index = d3.range(data.length); + if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) { + return values[j] - values[i]; + } : function(i, j) { + return sort(data[i], data[j]); + }); + var arcs = []; + index.forEach(function(i) { + var d; + arcs[i] = { + data: data[i], + value: d = values[i], + startAngle: a, + endAngle: a += d * k + }; + }); + return arcs; + } + pie.value = function(x) { + if (!arguments.length) return value; + value = x; + return pie; + }; + pie.sort = function(x) { + if (!arguments.length) return sort; + sort = x; + return pie; + }; + pie.startAngle = function(x) { + if (!arguments.length) return startAngle; + startAngle = x; + return pie; + }; + pie.endAngle = function(x) { + if (!arguments.length) return endAngle; + endAngle = x; + return pie; + }; + return pie; + }; + var d3_layout_pieSortByValue = {}; + d3.layout.stack = function() { + var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY; + function stack(data, index) { + var series = data.map(function(d, i) { + return values.call(stack, d, i); + }); + var points = series.map(function(d) { + return d.map(function(v, i) { + return [ x.call(stack, v, i), y.call(stack, v, i) ]; + }); + }); + var orders = order.call(stack, points, index); + series = d3.permute(series, orders); + points = d3.permute(points, orders); + var offsets = offset.call(stack, points, index); + var n = series.length, m = series[0].length, i, j, o; + for (j = 0; j < m; ++j) { + out.call(stack, series[0][j], o = offsets[j], points[0][j][1]); + for (i = 1; i < n; ++i) { + out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]); + } + } + return data; + } + stack.values = function(x) { + if (!arguments.length) return values; + values = x; + return stack; + }; + stack.order = function(x) { + if (!arguments.length) return order; + order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault; + return stack; + }; + stack.offset = function(x) { + if (!arguments.length) return offset; + offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero; + return stack; + }; + stack.x = function(z) { + if (!arguments.length) return x; + x = z; + return stack; + }; + stack.y = function(z) { + if (!arguments.length) return y; + y = z; + return stack; + }; + stack.out = function(z) { + if (!arguments.length) return out; + out = z; + return stack; + }; + return stack; + }; + function d3_layout_stackX(d) { + return d.x; + } + function d3_layout_stackY(d) { + return d.y; + } + function d3_layout_stackOut(d, y0, y) { + d.y0 = y0; + d.y = y; + } + var d3_layout_stackOrders = d3.map({ + "inside-out": function(data) { + var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) { + return max[a] - max[b]; + }), top = 0, bottom = 0, tops = [], bottoms = []; + for (i = 0; i < n; ++i) { + j = index[i]; + if (top < bottom) { + top += sums[j]; + tops.push(j); + } else { + bottom += sums[j]; + bottoms.push(j); + } + } + return bottoms.reverse().concat(tops); + }, + reverse: function(data) { + return d3.range(data.length).reverse(); + }, + "default": d3_layout_stackOrderDefault + }); + var d3_layout_stackOffsets = d3.map({ + silhouette: function(data) { + var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = []; + for (j = 0; j < m; ++j) { + for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; + if (o > max) max = o; + sums.push(o); + } + for (j = 0; j < m; ++j) { + y0[j] = (max - sums[j]) / 2; + } + return y0; + }, + wiggle: function(data) { + var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = []; + y0[0] = o = o0 = 0; + for (j = 1; j < m; ++j) { + for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1]; + for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) { + for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) { + s3 += (data[k][j][1] - data[k][j - 1][1]) / dx; + } + s2 += s3 * data[i][j][1]; + } + y0[j] = o -= s1 ? s2 / s1 * dx : 0; + if (o < o0) o0 = o; + } + for (j = 0; j < m; ++j) y0[j] -= o0; + return y0; + }, + expand: function(data) { + var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = []; + for (j = 0; j < m; ++j) { + for (i = 0, o = 0; i < n; i++) o += data[i][j][1]; + if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k; + } + for (j = 0; j < m; ++j) y0[j] = 0; + return y0; + }, + zero: d3_layout_stackOffsetZero + }); + function d3_layout_stackOrderDefault(data) { + return d3.range(data.length); + } + function d3_layout_stackOffsetZero(data) { + var j = -1, m = data[0].length, y0 = []; + while (++j < m) y0[j] = 0; + return y0; + } + function d3_layout_stackMaxIndex(array) { + var i = 1, j = 0, v = array[0][1], k, n = array.length; + for (;i < n; ++i) { + if ((k = array[i][1]) > v) { + j = i; + v = k; + } + } + return j; + } + function d3_layout_stackReduceSum(d) { + return d.reduce(d3_layout_stackSum, 0); + } + function d3_layout_stackSum(p, d) { + return p + d[1]; + } + d3.layout.histogram = function() { + var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges; + function histogram(data, i) { + var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x; + while (++i < m) { + bin = bins[i] = []; + bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]); + bin.y = 0; + } + if (m > 0) { + i = -1; + while (++i < n) { + x = values[i]; + if (x >= range[0] && x <= range[1]) { + bin = bins[d3.bisect(thresholds, x, 1, m) - 1]; + bin.y += k; + bin.push(data[i]); + } + } + } + return bins; + } + histogram.value = function(x) { + if (!arguments.length) return valuer; + valuer = x; + return histogram; + }; + histogram.range = function(x) { + if (!arguments.length) return ranger; + ranger = d3_functor(x); + return histogram; + }; + histogram.bins = function(x) { + if (!arguments.length) return binner; + binner = typeof x === "number" ? function(range) { + return d3_layout_histogramBinFixed(range, x); + } : d3_functor(x); + return histogram; + }; + histogram.frequency = function(x) { + if (!arguments.length) return frequency; + frequency = !!x; + return histogram; + }; + return histogram; + }; + function d3_layout_histogramBinSturges(range, values) { + return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1)); + } + function d3_layout_histogramBinFixed(range, n) { + var x = -1, b = +range[0], m = (range[1] - b) / n, f = []; + while (++x <= n) f[x] = m * x + b; + return f; + } + function d3_layout_histogramRange(values) { + return [ d3.min(values), d3.max(values) ]; + } + d3.layout.pack = function() { + var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius; + function pack(d, i) { + var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() { + return radius; + }; + root.x = root.y = 0; + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r = +r(d.value); + }); + d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); + if (padding) { + var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2; + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r += dr; + }); + d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings); + d3_layout_hierarchyVisitAfter(root, function(d) { + d.r -= dr; + }); + } + d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h)); + return nodes; + } + pack.size = function(_) { + if (!arguments.length) return size; + size = _; + return pack; + }; + pack.radius = function(_) { + if (!arguments.length) return radius; + radius = _ == null || typeof _ === "function" ? _ : +_; + return pack; + }; + pack.padding = function(_) { + if (!arguments.length) return padding; + padding = +_; + return pack; + }; + return d3_layout_hierarchyRebind(pack, hierarchy); + }; + function d3_layout_packSort(a, b) { + return a.value - b.value; + } + function d3_layout_packInsert(a, b) { + var c = a._pack_next; + a._pack_next = b; + b._pack_prev = a; + b._pack_next = c; + c._pack_prev = b; + } + function d3_layout_packSplice(a, b) { + a._pack_next = b; + b._pack_prev = a; + } + function d3_layout_packIntersects(a, b) { + var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r; + return .999 * dr * dr > dx * dx + dy * dy; + } + function d3_layout_packSiblings(node) { + if (!(nodes = node.children) || !(n = nodes.length)) return; + var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n; + function bound(node) { + xMin = Math.min(node.x - node.r, xMin); + xMax = Math.max(node.x + node.r, xMax); + yMin = Math.min(node.y - node.r, yMin); + yMax = Math.max(node.y + node.r, yMax); + } + nodes.forEach(d3_layout_packLink); + a = nodes[0]; + a.x = -a.r; + a.y = 0; + bound(a); + if (n > 1) { + b = nodes[1]; + b.x = b.r; + b.y = 0; + bound(b); + if (n > 2) { + c = nodes[2]; + d3_layout_packPlace(a, b, c); + bound(c); + d3_layout_packInsert(a, c); + a._pack_prev = c; + d3_layout_packInsert(c, b); + b = a._pack_next; + for (i = 3; i < n; i++) { + d3_layout_packPlace(a, b, c = nodes[i]); + var isect = 0, s1 = 1, s2 = 1; + for (j = b._pack_next; j !== b; j = j._pack_next, s1++) { + if (d3_layout_packIntersects(j, c)) { + isect = 1; + break; + } + } + if (isect == 1) { + for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) { + if (d3_layout_packIntersects(k, c)) { + break; + } + } + } + if (isect) { + if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b); + i--; + } else { + d3_layout_packInsert(a, c); + b = c; + bound(c); + } + } + } + } + var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0; + for (i = 0; i < n; i++) { + c = nodes[i]; + c.x -= cx; + c.y -= cy; + cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y)); + } + node.r = cr; + nodes.forEach(d3_layout_packUnlink); + } + function d3_layout_packLink(node) { + node._pack_next = node._pack_prev = node; + } + function d3_layout_packUnlink(node) { + delete node._pack_next; + delete node._pack_prev; + } + function d3_layout_packTransform(node, x, y, k) { + var children = node.children; + node.x = x += k * node.x; + node.y = y += k * node.y; + node.r *= k; + if (children) { + var i = -1, n = children.length; + while (++i < n) d3_layout_packTransform(children[i], x, y, k); + } + } + function d3_layout_packPlace(a, b, c) { + var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y; + if (db && (dx || dy)) { + var da = b.r + c.r, dc = dx * dx + dy * dy; + da *= da; + db *= db; + var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); + c.x = a.x + x * dx + y * dy; + c.y = a.y + x * dy - y * dx; + } else { + c.x = a.x + db; + c.y = a.y; + } + } + d3.layout.tree = function() { + var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null; + function tree(d, i) { + var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0); + d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z; + d3_layout_hierarchyVisitBefore(root1, secondWalk); + if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else { + var left = root0, right = root0, bottom = root0; + d3_layout_hierarchyVisitBefore(root0, function(node) { + if (node.x < left.x) left = node; + if (node.x > right.x) right = node; + if (node.depth > bottom.depth) bottom = node; + }); + var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1); + d3_layout_hierarchyVisitBefore(root0, function(node) { + node.x = (node.x + tx) * kx; + node.y = node.depth * ky; + }); + } + return nodes; + } + function wrapTree(root0) { + var root1 = { + A: null, + children: [ root0 ] + }, queue = [ root1 ], node1; + while ((node1 = queue.pop()) != null) { + for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) { + queue.push((children[i] = child = { + _: children[i], + parent: node1, + children: (child = children[i].children) && child.slice() || [], + A: null, + a: null, + z: 0, + m: 0, + c: 0, + s: 0, + t: null, + i: i + }).a = child); + } + } + return root1.children[0]; + } + function firstWalk(v) { + var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null; + if (children.length) { + d3_layout_treeShift(v); + var midpoint = (children[0].z + children[children.length - 1].z) / 2; + if (w) { + v.z = w.z + separation(v._, w._); + v.m = v.z - midpoint; + } else { + v.z = midpoint; + } + } else if (w) { + v.z = w.z + separation(v._, w._); + } + v.parent.A = apportion(v, w, v.parent.A || siblings[0]); + } + function secondWalk(v) { + v._.x = v.z + v.parent.m; + v.m += v.parent.m; + } + function apportion(v, w, ancestor) { + if (w) { + var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift; + while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) { + vom = d3_layout_treeLeft(vom); + vop = d3_layout_treeRight(vop); + vop.a = v; + shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); + if (shift > 0) { + d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift); + sip += shift; + sop += shift; + } + sim += vim.m; + sip += vip.m; + som += vom.m; + sop += vop.m; + } + if (vim && !d3_layout_treeRight(vop)) { + vop.t = vim; + vop.m += sim - sop; + } + if (vip && !d3_layout_treeLeft(vom)) { + vom.t = vip; + vom.m += sip - som; + ancestor = v; + } + } + return ancestor; + } + function sizeNode(node) { + node.x *= size[0]; + node.y = node.depth * size[1]; + } + tree.separation = function(x) { + if (!arguments.length) return separation; + separation = x; + return tree; + }; + tree.size = function(x) { + if (!arguments.length) return nodeSize ? null : size; + nodeSize = (size = x) == null ? sizeNode : null; + return tree; + }; + tree.nodeSize = function(x) { + if (!arguments.length) return nodeSize ? size : null; + nodeSize = (size = x) == null ? null : sizeNode; + return tree; + }; + return d3_layout_hierarchyRebind(tree, hierarchy); + }; + function d3_layout_treeSeparation(a, b) { + return a.parent == b.parent ? 1 : 2; + } + function d3_layout_treeLeft(v) { + var children = v.children; + return children.length ? children[0] : v.t; + } + function d3_layout_treeRight(v) { + var children = v.children, n; + return (n = children.length) ? children[n - 1] : v.t; + } + function d3_layout_treeMove(wm, wp, shift) { + var change = shift / (wp.i - wm.i); + wp.c -= change; + wp.s += shift; + wm.c += change; + wp.z += shift; + wp.m += shift; + } + function d3_layout_treeShift(v) { + var shift = 0, change = 0, children = v.children, i = children.length, w; + while (--i >= 0) { + w = children[i]; + w.z += shift; + w.m += shift; + shift += w.s + (change += w.c); + } + } + function d3_layout_treeAncestor(vim, v, ancestor) { + return vim.a.parent === v.parent ? vim.a : ancestor; + } + d3.layout.cluster = function() { + var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false; + function cluster(d, i) { + var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0; + d3_layout_hierarchyVisitAfter(root, function(node) { + var children = node.children; + if (children && children.length) { + node.x = d3_layout_clusterX(children); + node.y = d3_layout_clusterY(children); + } else { + node.x = previousNode ? x += separation(node, previousNode) : 0; + node.y = 0; + previousNode = node; + } + }); + var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2; + d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) { + node.x = (node.x - root.x) * size[0]; + node.y = (root.y - node.y) * size[1]; + } : function(node) { + node.x = (node.x - x0) / (x1 - x0) * size[0]; + node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1]; + }); + return nodes; + } + cluster.separation = function(x) { + if (!arguments.length) return separation; + separation = x; + return cluster; + }; + cluster.size = function(x) { + if (!arguments.length) return nodeSize ? null : size; + nodeSize = (size = x) == null; + return cluster; + }; + cluster.nodeSize = function(x) { + if (!arguments.length) return nodeSize ? size : null; + nodeSize = (size = x) != null; + return cluster; + }; + return d3_layout_hierarchyRebind(cluster, hierarchy); + }; + function d3_layout_clusterY(children) { + return 1 + d3.max(children, function(child) { + return child.y; + }); + } + function d3_layout_clusterX(children) { + return children.reduce(function(x, child) { + return x + child.x; + }, 0) / children.length; + } + function d3_layout_clusterLeft(node) { + var children = node.children; + return children && children.length ? d3_layout_clusterLeft(children[0]) : node; + } + function d3_layout_clusterRight(node) { + var children = node.children, n; + return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node; + } + d3.layout.treemap = function() { + var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5)); + function scale(children, k) { + var i = -1, n = children.length, child, area; + while (++i < n) { + area = (child = children[i]).value * (k < 0 ? 0 : k); + child.area = isNaN(area) || area <= 0 ? 0 : area; + } + } + function squarify(node) { + var children = node.children; + if (children && children.length) { + var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n; + scale(remaining, rect.dx * rect.dy / node.value); + row.area = 0; + while ((n = remaining.length) > 0) { + row.push(child = remaining[n - 1]); + row.area += child.area; + if (mode !== "squarify" || (score = worst(row, u)) <= best) { + remaining.pop(); + best = score; + } else { + row.area -= row.pop().area; + position(row, u, rect, false); + u = Math.min(rect.dx, rect.dy); + row.length = row.area = 0; + best = Infinity; + } + } + if (row.length) { + position(row, u, rect, true); + row.length = row.area = 0; + } + children.forEach(squarify); + } + } + function stickify(node) { + var children = node.children; + if (children && children.length) { + var rect = pad(node), remaining = children.slice(), child, row = []; + scale(remaining, rect.dx * rect.dy / node.value); + row.area = 0; + while (child = remaining.pop()) { + row.push(child); + row.area += child.area; + if (child.z != null) { + position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length); + row.length = row.area = 0; + } + } + children.forEach(stickify); + } + } + function worst(row, u) { + var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length; + while (++i < n) { + if (!(r = row[i].area)) continue; + if (r < rmin) rmin = r; + if (r > rmax) rmax = r; + } + s *= s; + u *= u; + return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity; + } + function position(row, u, rect, flush) { + var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o; + if (u == rect.dx) { + if (flush || v > rect.dy) v = rect.dy; + while (++i < n) { + o = row[i]; + o.x = x; + o.y = y; + o.dy = v; + x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0); + } + o.z = true; + o.dx += rect.x + rect.dx - x; + rect.y += v; + rect.dy -= v; + } else { + if (flush || v > rect.dx) v = rect.dx; + while (++i < n) { + o = row[i]; + o.x = x; + o.y = y; + o.dx = v; + y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0); + } + o.z = false; + o.dy += rect.y + rect.dy - y; + rect.x += v; + rect.dx -= v; + } + } + function treemap(d) { + var nodes = stickies || hierarchy(d), root = nodes[0]; + root.x = 0; + root.y = 0; + root.dx = size[0]; + root.dy = size[1]; + if (stickies) hierarchy.revalue(root); + scale([ root ], root.dx * root.dy / root.value); + (stickies ? stickify : squarify)(root); + if (sticky) stickies = nodes; + return nodes; + } + treemap.size = function(x) { + if (!arguments.length) return size; + size = x; + return treemap; + }; + treemap.padding = function(x) { + if (!arguments.length) return padding; + function padFunction(node) { + var p = x.call(treemap, node, node.depth); + return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p); + } + function padConstant(node) { + return d3_layout_treemapPad(node, x); + } + var type; + pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], + padConstant) : padConstant; + return treemap; + }; + treemap.round = function(x) { + if (!arguments.length) return round != Number; + round = x ? Math.round : Number; + return treemap; + }; + treemap.sticky = function(x) { + if (!arguments.length) return sticky; + sticky = x; + stickies = null; + return treemap; + }; + treemap.ratio = function(x) { + if (!arguments.length) return ratio; + ratio = x; + return treemap; + }; + treemap.mode = function(x) { + if (!arguments.length) return mode; + mode = x + ""; + return treemap; + }; + return d3_layout_hierarchyRebind(treemap, hierarchy); + }; + function d3_layout_treemapPadNull(node) { + return { + x: node.x, + y: node.y, + dx: node.dx, + dy: node.dy + }; + } + function d3_layout_treemapPad(node, padding) { + var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2]; + if (dx < 0) { + x += dx / 2; + dx = 0; + } + if (dy < 0) { + y += dy / 2; + dy = 0; + } + return { + x: x, + y: y, + dx: dx, + dy: dy + }; + } + d3.random = { + normal: function(µ, σ) { + var n = arguments.length; + if (n < 2) σ = 1; + if (n < 1) µ = 0; + return function() { + var x, y, r; + do { + x = Math.random() * 2 - 1; + y = Math.random() * 2 - 1; + r = x * x + y * y; + } while (!r || r > 1); + return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r); + }; + }, + logNormal: function() { + var random = d3.random.normal.apply(d3, arguments); + return function() { + return Math.exp(random()); + }; + }, + bates: function(m) { + var random = d3.random.irwinHall(m); + return function() { + return random() / m; + }; + }, + irwinHall: function(m) { + return function() { + for (var s = 0, j = 0; j < m; j++) s += Math.random(); + return s; + }; + } + }; + d3.scale = {}; + function d3_scaleExtent(domain) { + var start = domain[0], stop = domain[domain.length - 1]; + return start < stop ? [ start, stop ] : [ stop, start ]; + } + function d3_scaleRange(scale) { + return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range()); + } + function d3_scale_bilinear(domain, range, uninterpolate, interpolate) { + var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]); + return function(x) { + return i(u(x)); + }; + } + function d3_scale_nice(domain, nice) { + var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx; + if (x1 < x0) { + dx = i0, i0 = i1, i1 = dx; + dx = x0, x0 = x1, x1 = dx; + } + domain[i0] = nice.floor(x0); + domain[i1] = nice.ceil(x1); + return domain; + } + function d3_scale_niceStep(step) { + return step ? { + floor: function(x) { + return Math.floor(x / step) * step; + }, + ceil: function(x) { + return Math.ceil(x / step) * step; + } + } : d3_scale_niceIdentity; + } + var d3_scale_niceIdentity = { + floor: d3_identity, + ceil: d3_identity + }; + function d3_scale_polylinear(domain, range, uninterpolate, interpolate) { + var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1; + if (domain[k] < domain[0]) { + domain = domain.slice().reverse(); + range = range.slice().reverse(); + } + while (++j <= k) { + u.push(uninterpolate(domain[j - 1], domain[j])); + i.push(interpolate(range[j - 1], range[j])); + } + return function(x) { + var j = d3.bisect(domain, x, 1, k) - 1; + return i[j](u[j](x)); + }; + } + d3.scale.linear = function() { + return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false); + }; + function d3_scale_linear(domain, range, interpolate, clamp) { + var output, input; + function rescale() { + var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber; + output = linear(domain, range, uninterpolate, interpolate); + input = linear(range, domain, uninterpolate, d3_interpolate); + return scale; + } + function scale(x) { + return output(x); + } + scale.invert = function(y) { + return input(y); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = x.map(Number); + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.rangeRound = function(x) { + return scale.range(x).interpolate(d3_interpolateRound); + }; + scale.clamp = function(x) { + if (!arguments.length) return clamp; + clamp = x; + return rescale(); + }; + scale.interpolate = function(x) { + if (!arguments.length) return interpolate; + interpolate = x; + return rescale(); + }; + scale.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + scale.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + scale.nice = function(m) { + d3_scale_linearNice(domain, m); + return rescale(); + }; + scale.copy = function() { + return d3_scale_linear(domain, range, interpolate, clamp); + }; + return rescale(); + } + function d3_scale_linearRebind(scale, linear) { + return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp"); + } + function d3_scale_linearNice(domain, m) { + return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2])); + } + function d3_scale_linearTickRange(domain, m) { + if (m == null) m = 10; + var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step; + if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2; + extent[0] = Math.ceil(extent[0] / step) * step; + extent[1] = Math.floor(extent[1] / step) * step + step * .5; + extent[2] = step; + return extent; + } + function d3_scale_linearTicks(domain, m) { + return d3.range.apply(d3, d3_scale_linearTickRange(domain, m)); + } + function d3_scale_linearTickFormat(domain, m, format) { + var range = d3_scale_linearTickRange(domain, m); + if (format) { + var match = d3_format_re.exec(format); + match.shift(); + if (match[8] === "s") { + var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1]))); + if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2])); + match[8] = "f"; + format = d3.format(match.join("")); + return function(d) { + return format(prefix.scale(d)) + prefix.symbol; + }; + } + if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range); + format = match.join(""); + } else { + format = ",." + d3_scale_linearPrecision(range[2]) + "f"; + } + return d3.format(format); + } + var d3_scale_linearFormatSignificant = { + s: 1, + g: 1, + p: 1, + r: 1, + e: 1 + }; + function d3_scale_linearPrecision(value) { + return -Math.floor(Math.log(value) / Math.LN10 + .01); + } + function d3_scale_linearFormatPrecision(type, range) { + var p = d3_scale_linearPrecision(range[2]); + return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2; + } + d3.scale.log = function() { + return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]); + }; + function d3_scale_log(linear, base, positive, domain) { + function log(x) { + return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base); + } + function pow(x) { + return positive ? Math.pow(base, x) : -Math.pow(base, -x); + } + function scale(x) { + return linear(log(x)); + } + scale.invert = function(x) { + return pow(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + positive = x[0] >= 0; + linear.domain((domain = x.map(Number)).map(log)); + return scale; + }; + scale.base = function(_) { + if (!arguments.length) return base; + base = +_; + linear.domain(domain.map(log)); + return scale; + }; + scale.nice = function() { + var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative); + linear.domain(niced); + domain = niced.map(pow); + return scale; + }; + scale.ticks = function() { + var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base; + if (isFinite(j - i)) { + if (positive) { + for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k); + ticks.push(pow(i)); + } else { + ticks.push(pow(i)); + for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k); + } + for (i = 0; ticks[i] < u; i++) {} + for (j = ticks.length; ticks[j - 1] > v; j--) {} + ticks = ticks.slice(i, j); + } + return ticks; + }; + scale.tickFormat = function(n, format) { + if (!arguments.length) return d3_scale_logFormat; + if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format); + var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, Math.ceil) : (e = -1e-12, + Math.floor), e; + return function(d) { + return d / pow(f(log(d) + e)) <= k ? format(d) : ""; + }; + }; + scale.copy = function() { + return d3_scale_log(linear.copy(), base, positive, domain); + }; + return d3_scale_linearRebind(scale, linear); + } + var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = { + floor: function(x) { + return -Math.ceil(-x); + }, + ceil: function(x) { + return -Math.floor(-x); + } + }; + d3.scale.pow = function() { + return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]); + }; + function d3_scale_pow(linear, exponent, domain) { + var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent); + function scale(x) { + return linear(powp(x)); + } + scale.invert = function(x) { + return powb(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return domain; + linear.domain((domain = x.map(Number)).map(powp)); + return scale; + }; + scale.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + scale.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + scale.nice = function(m) { + return scale.domain(d3_scale_linearNice(domain, m)); + }; + scale.exponent = function(x) { + if (!arguments.length) return exponent; + powp = d3_scale_powPow(exponent = x); + powb = d3_scale_powPow(1 / exponent); + linear.domain(domain.map(powp)); + return scale; + }; + scale.copy = function() { + return d3_scale_pow(linear.copy(), exponent, domain); + }; + return d3_scale_linearRebind(scale, linear); + } + function d3_scale_powPow(e) { + return function(x) { + return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e); + }; + } + d3.scale.sqrt = function() { + return d3.scale.pow().exponent(.5); + }; + d3.scale.ordinal = function() { + return d3_scale_ordinal([], { + t: "range", + a: [ [] ] + }); + }; + function d3_scale_ordinal(domain, ranger) { + var index, range, rangeBand; + function scale(x) { + return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length]; + } + function steps(start, step) { + return d3.range(domain.length).map(function(i) { + return start + step * i; + }); + } + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = []; + index = new d3_Map(); + var i = -1, n = x.length, xi; + while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi)); + return scale[ranger.t].apply(scale, ranger.a); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + rangeBand = 0; + ranger = { + t: "range", + a: arguments + }; + return scale; + }; + scale.rangePoints = function(x, padding) { + if (arguments.length < 2) padding = 0; + var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding); + range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step); + rangeBand = 0; + ranger = { + t: "rangePoints", + a: arguments + }; + return scale; + }; + scale.rangeBands = function(x, padding, outerPadding) { + if (arguments.length < 2) padding = 0; + if (arguments.length < 3) outerPadding = padding; + var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding); + range = steps(start + step * outerPadding, step); + if (reverse) range.reverse(); + rangeBand = step * (1 - padding); + ranger = { + t: "rangeBands", + a: arguments + }; + return scale; + }; + scale.rangeRoundBands = function(x, padding, outerPadding) { + if (arguments.length < 2) padding = 0; + if (arguments.length < 3) outerPadding = padding; + var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step; + range = steps(start + Math.round(error / 2), step); + if (reverse) range.reverse(); + rangeBand = Math.round(step * (1 - padding)); + ranger = { + t: "rangeRoundBands", + a: arguments + }; + return scale; + }; + scale.rangeBand = function() { + return rangeBand; + }; + scale.rangeExtent = function() { + return d3_scaleExtent(ranger.a[0]); + }; + scale.copy = function() { + return d3_scale_ordinal(domain, ranger); + }; + return scale.domain(domain); + } + d3.scale.category10 = function() { + return d3.scale.ordinal().range(d3_category10); + }; + d3.scale.category20 = function() { + return d3.scale.ordinal().range(d3_category20); + }; + d3.scale.category20b = function() { + return d3.scale.ordinal().range(d3_category20b); + }; + d3.scale.category20c = function() { + return d3.scale.ordinal().range(d3_category20c); + }; + var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString); + var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString); + var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString); + var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString); + d3.scale.quantile = function() { + return d3_scale_quantile([], []); + }; + function d3_scale_quantile(domain, range) { + var thresholds; + function rescale() { + var k = 0, q = range.length; + thresholds = []; + while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q); + return scale; + } + function scale(x) { + if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)]; + } + scale.domain = function(x) { + if (!arguments.length) return domain; + domain = x.filter(d3_number).sort(d3_ascending); + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.quantiles = function() { + return thresholds; + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ]; + }; + scale.copy = function() { + return d3_scale_quantile(domain, range); + }; + return rescale(); + } + d3.scale.quantize = function() { + return d3_scale_quantize(0, 1, [ 0, 1 ]); + }; + function d3_scale_quantize(x0, x1, range) { + var kx, i; + function scale(x) { + return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))]; + } + function rescale() { + kx = range.length / (x1 - x0); + i = range.length - 1; + return scale; + } + scale.domain = function(x) { + if (!arguments.length) return [ x0, x1 ]; + x0 = +x[0]; + x1 = +x[x.length - 1]; + return rescale(); + }; + scale.range = function(x) { + if (!arguments.length) return range; + range = x; + return rescale(); + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + y = y < 0 ? NaN : y / kx + x0; + return [ y, y + 1 / kx ]; + }; + scale.copy = function() { + return d3_scale_quantize(x0, x1, range); + }; + return rescale(); + } + d3.scale.threshold = function() { + return d3_scale_threshold([ .5 ], [ 0, 1 ]); + }; + function d3_scale_threshold(domain, range) { + function scale(x) { + if (x <= x) return range[d3.bisect(domain, x)]; + } + scale.domain = function(_) { + if (!arguments.length) return domain; + domain = _; + return scale; + }; + scale.range = function(_) { + if (!arguments.length) return range; + range = _; + return scale; + }; + scale.invertExtent = function(y) { + y = range.indexOf(y); + return [ domain[y - 1], domain[y] ]; + }; + scale.copy = function() { + return d3_scale_threshold(domain, range); + }; + return scale; + } + d3.scale.identity = function() { + return d3_scale_identity([ 0, 1 ]); + }; + function d3_scale_identity(domain) { + function identity(x) { + return +x; + } + identity.invert = identity; + identity.domain = identity.range = function(x) { + if (!arguments.length) return domain; + domain = x.map(identity); + return identity; + }; + identity.ticks = function(m) { + return d3_scale_linearTicks(domain, m); + }; + identity.tickFormat = function(m, format) { + return d3_scale_linearTickFormat(domain, m, format); + }; + identity.copy = function() { + return d3_scale_identity(domain); + }; + return identity; + } + d3.svg = {}; + d3.svg.arc = function() { + var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; + function arc() { + var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0, + a0 = a1, a1 = da), a1 - a0), df = da < Ï€ ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1); + return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z"; + } + arc.innerRadius = function(v) { + if (!arguments.length) return innerRadius; + innerRadius = d3_functor(v); + return arc; + }; + arc.outerRadius = function(v) { + if (!arguments.length) return outerRadius; + outerRadius = d3_functor(v); + return arc; + }; + arc.startAngle = function(v) { + if (!arguments.length) return startAngle; + startAngle = d3_functor(v); + return arc; + }; + arc.endAngle = function(v) { + if (!arguments.length) return endAngle; + endAngle = d3_functor(v); + return arc; + }; + arc.centroid = function() { + var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset; + return [ Math.cos(a) * r, Math.sin(a) * r ]; + }; + return arc; + }; + var d3_svg_arcOffset = -halfÏ€, d3_svg_arcMax = Ï„ - ε; + function d3_svg_arcInnerRadius(d) { + return d.innerRadius; + } + function d3_svg_arcOuterRadius(d) { + return d.outerRadius; + } + function d3_svg_arcStartAngle(d) { + return d.startAngle; + } + function d3_svg_arcEndAngle(d) { + return d.endAngle; + } + function d3_svg_line(projection) { + var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7; + function line(data) { + var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y); + function segment() { + segments.push("M", interpolate(projection(points), tension)); + } + while (++i < n) { + if (defined.call(this, d = data[i], i)) { + points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]); + } else if (points.length) { + segment(); + points = []; + } + } + if (points.length) segment(); + return segments.length ? segments.join("") : null; + } + line.x = function(_) { + if (!arguments.length) return x; + x = _; + return line; + }; + line.y = function(_) { + if (!arguments.length) return y; + y = _; + return line; + }; + line.defined = function(_) { + if (!arguments.length) return defined; + defined = _; + return line; + }; + line.interpolate = function(_) { + if (!arguments.length) return interpolateKey; + if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; + return line; + }; + line.tension = function(_) { + if (!arguments.length) return tension; + tension = _; + return line; + }; + return line; + } + d3.svg.line = function() { + return d3_svg_line(d3_identity); + }; + var d3_svg_lineInterpolators = d3.map({ + linear: d3_svg_lineLinear, + "linear-closed": d3_svg_lineLinearClosed, + step: d3_svg_lineStep, + "step-before": d3_svg_lineStepBefore, + "step-after": d3_svg_lineStepAfter, + basis: d3_svg_lineBasis, + "basis-open": d3_svg_lineBasisOpen, + "basis-closed": d3_svg_lineBasisClosed, + bundle: d3_svg_lineBundle, + cardinal: d3_svg_lineCardinal, + "cardinal-open": d3_svg_lineCardinalOpen, + "cardinal-closed": d3_svg_lineCardinalClosed, + monotone: d3_svg_lineMonotone + }); + d3_svg_lineInterpolators.forEach(function(key, value) { + value.key = key; + value.closed = /-closed$/.test(key); + }); + function d3_svg_lineLinear(points) { + return points.join("L"); + } + function d3_svg_lineLinearClosed(points) { + return d3_svg_lineLinear(points) + "Z"; + } + function d3_svg_lineStep(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]); + if (n > 1) path.push("H", p[0]); + return path.join(""); + } + function d3_svg_lineStepBefore(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]); + return path.join(""); + } + function d3_svg_lineStepAfter(points) { + var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ]; + while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]); + return path.join(""); + } + function d3_svg_lineCardinalOpen(points, tension) { + return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension)); + } + function d3_svg_lineCardinalClosed(points, tension) { + return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), + points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension)); + } + function d3_svg_lineCardinal(points, tension) { + return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension)); + } + function d3_svg_lineHermite(points, tangents) { + if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) { + return d3_svg_lineLinear(points); + } + var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1; + if (quad) { + path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1]; + p0 = points[1]; + pi = 2; + } + if (tangents.length > 1) { + t = tangents[1]; + p = points[pi]; + pi++; + path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; + for (var i = 2; i < tangents.length; i++, pi++) { + p = points[pi]; + t = tangents[i]; + path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1]; + } + } + if (quad) { + var lp = points[pi]; + path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1]; + } + return path; + } + function d3_svg_lineCardinalTangents(points, tension) { + var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length; + while (++i < n) { + p0 = p1; + p1 = p2; + p2 = points[i]; + tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]); + } + return tangents; + } + function d3_svg_lineBasis(points) { + if (points.length < 3) return d3_svg_lineLinear(points); + var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; + points.push(points[n - 1]); + while (++i <= n) { + pi = points[i]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + points.pop(); + path.push("L", pi); + return path.join(""); + } + function d3_svg_lineBasisOpen(points) { + if (points.length < 4) return d3_svg_lineLinear(points); + var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ]; + while (++i < 3) { + pi = points[i]; + px.push(pi[0]); + py.push(pi[1]); + } + path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py)); + --i; + while (++i < n) { + pi = points[i]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + return path.join(""); + } + function d3_svg_lineBasisClosed(points) { + var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = []; + while (++i < 4) { + pi = points[i % n]; + px.push(pi[0]); + py.push(pi[1]); + } + path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ]; + --i; + while (++i < m) { + pi = points[i % n]; + px.shift(); + px.push(pi[0]); + py.shift(); + py.push(pi[1]); + d3_svg_lineBasisBezier(path, px, py); + } + return path.join(""); + } + function d3_svg_lineBundle(points, tension) { + var n = points.length - 1; + if (n) { + var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t; + while (++i <= n) { + p = points[i]; + t = i / n; + p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx); + p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy); + } + } + return d3_svg_lineBasis(points); + } + function d3_svg_lineDot4(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; + } + var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ]; + function d3_svg_lineBasisBezier(path, x, y) { + path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y)); + } + function d3_svg_lineSlope(p0, p1) { + return (p1[1] - p0[1]) / (p1[0] - p0[0]); + } + function d3_svg_lineFiniteDifferences(points) { + var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1); + while (++i < j) { + m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2; + } + m[i] = d; + return m; + } + function d3_svg_lineMonotoneTangents(points) { + var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1; + while (++i < j) { + d = d3_svg_lineSlope(points[i], points[i + 1]); + if (abs(d) < ε) { + m[i] = m[i + 1] = 0; + } else { + a = m[i] / d; + b = m[i + 1] / d; + s = a * a + b * b; + if (s > 9) { + s = d * 3 / Math.sqrt(s); + m[i] = s * a; + m[i + 1] = s * b; + } + } + } + i = -1; + while (++i <= j) { + s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i])); + tangents.push([ s || 0, m[i] * s || 0 ]); + } + return tangents; + } + function d3_svg_lineMonotone(points) { + return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points)); + } + d3.svg.line.radial = function() { + var line = d3_svg_line(d3_svg_lineRadial); + line.radius = line.x, delete line.x; + line.angle = line.y, delete line.y; + return line; + }; + function d3_svg_lineRadial(points) { + var point, i = -1, n = points.length, r, a; + while (++i < n) { + point = points[i]; + r = point[0]; + a = point[1] + d3_svg_arcOffset; + point[0] = r * Math.cos(a); + point[1] = r * Math.sin(a); + } + return points; + } + function d3_svg_area(projection) { + var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7; + function area(data) { + var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() { + return x; + } : d3_functor(x1), fy1 = y0 === y1 ? function() { + return y; + } : d3_functor(y1), x, y; + function segment() { + segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z"); + } + while (++i < n) { + if (defined.call(this, d = data[i], i)) { + points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]); + points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]); + } else if (points0.length) { + segment(); + points0 = []; + points1 = []; + } + } + if (points0.length) segment(); + return segments.length ? segments.join("") : null; + } + area.x = function(_) { + if (!arguments.length) return x1; + x0 = x1 = _; + return area; + }; + area.x0 = function(_) { + if (!arguments.length) return x0; + x0 = _; + return area; + }; + area.x1 = function(_) { + if (!arguments.length) return x1; + x1 = _; + return area; + }; + area.y = function(_) { + if (!arguments.length) return y1; + y0 = y1 = _; + return area; + }; + area.y0 = function(_) { + if (!arguments.length) return y0; + y0 = _; + return area; + }; + area.y1 = function(_) { + if (!arguments.length) return y1; + y1 = _; + return area; + }; + area.defined = function(_) { + if (!arguments.length) return defined; + defined = _; + return area; + }; + area.interpolate = function(_) { + if (!arguments.length) return interpolateKey; + if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key; + interpolateReverse = interpolate.reverse || interpolate; + L = interpolate.closed ? "M" : "L"; + return area; + }; + area.tension = function(_) { + if (!arguments.length) return tension; + tension = _; + return area; + }; + return area; + } + d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter; + d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore; + d3.svg.area = function() { + return d3_svg_area(d3_identity); + }; + d3.svg.area.radial = function() { + var area = d3_svg_area(d3_svg_lineRadial); + area.radius = area.x, delete area.x; + area.innerRadius = area.x0, delete area.x0; + area.outerRadius = area.x1, delete area.x1; + area.angle = area.y, delete area.y; + area.startAngle = area.y0, delete area.y0; + area.endAngle = area.y1, delete area.y1; + return area; + }; + d3.svg.chord = function() { + var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle; + function chord(d, i) { + var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i); + return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z"; + } + function subgroup(self, f, d, i) { + var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset; + return { + r: r, + a0: a0, + a1: a1, + p0: [ r * Math.cos(a0), r * Math.sin(a0) ], + p1: [ r * Math.cos(a1), r * Math.sin(a1) ] + }; + } + function equals(a, b) { + return a.a0 == b.a0 && a.a1 == b.a1; + } + function arc(r, p, a) { + return "A" + r + "," + r + " 0 " + +(a > Ï€) + ",1 " + p; + } + function curve(r0, p0, r1, p1) { + return "Q 0,0 " + p1; + } + chord.radius = function(v) { + if (!arguments.length) return radius; + radius = d3_functor(v); + return chord; + }; + chord.source = function(v) { + if (!arguments.length) return source; + source = d3_functor(v); + return chord; + }; + chord.target = function(v) { + if (!arguments.length) return target; + target = d3_functor(v); + return chord; + }; + chord.startAngle = function(v) { + if (!arguments.length) return startAngle; + startAngle = d3_functor(v); + return chord; + }; + chord.endAngle = function(v) { + if (!arguments.length) return endAngle; + endAngle = d3_functor(v); + return chord; + }; + return chord; + }; + function d3_svg_chordRadius(d) { + return d.radius; + } + d3.svg.diagonal = function() { + var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection; + function diagonal(d, i) { + var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, { + x: p0.x, + y: m + }, { + x: p3.x, + y: m + }, p3 ]; + p = p.map(projection); + return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3]; + } + diagonal.source = function(x) { + if (!arguments.length) return source; + source = d3_functor(x); + return diagonal; + }; + diagonal.target = function(x) { + if (!arguments.length) return target; + target = d3_functor(x); + return diagonal; + }; + diagonal.projection = function(x) { + if (!arguments.length) return projection; + projection = x; + return diagonal; + }; + return diagonal; + }; + function d3_svg_diagonalProjection(d) { + return [ d.x, d.y ]; + } + d3.svg.diagonal.radial = function() { + var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection; + diagonal.projection = function(x) { + return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection; + }; + return diagonal; + }; + function d3_svg_diagonalRadialProjection(projection) { + return function() { + var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset; + return [ r * Math.cos(a), r * Math.sin(a) ]; + }; + } + d3.svg.symbol = function() { + var type = d3_svg_symbolType, size = d3_svg_symbolSize; + function symbol(d, i) { + return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i)); + } + symbol.type = function(x) { + if (!arguments.length) return type; + type = d3_functor(x); + return symbol; + }; + symbol.size = function(x) { + if (!arguments.length) return size; + size = d3_functor(x); + return symbol; + }; + return symbol; + }; + function d3_svg_symbolSize() { + return 64; + } + function d3_svg_symbolType() { + return "circle"; + } + function d3_svg_symbolCircle(size) { + var r = Math.sqrt(size / Ï€); + return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z"; + } + var d3_svg_symbols = d3.map({ + circle: d3_svg_symbolCircle, + cross: function(size) { + var r = Math.sqrt(size / 5) / 2; + return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z"; + }, + diamond: function(size) { + var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30; + return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z"; + }, + square: function(size) { + var r = Math.sqrt(size) / 2; + return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z"; + }, + "triangle-down": function(size) { + var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; + return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z"; + }, + "triangle-up": function(size) { + var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2; + return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z"; + } + }); + d3.svg.symbolTypes = d3_svg_symbols.keys(); + var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians); + function d3_transition(groups, id) { + d3_subclass(groups, d3_transitionPrototype); + groups.id = id; + return groups; + } + var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit; + d3_transitionPrototype.call = d3_selectionPrototype.call; + d3_transitionPrototype.empty = d3_selectionPrototype.empty; + d3_transitionPrototype.node = d3_selectionPrototype.node; + d3_transitionPrototype.size = d3_selectionPrototype.size; + d3.transition = function(selection) { + return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition(); + }; + d3.transition.prototype = d3_transitionPrototype; + d3_transitionPrototype.select = function(selector) { + var id = this.id, subgroups = [], subgroup, subnode, node; + selector = d3_selection_selector(selector); + for (var j = -1, m = this.length; ++j < m; ) { + subgroups.push(subgroup = []); + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + d3_transitionNode(subnode, i, id, node.__transition__[id]); + subgroup.push(subnode); + } else { + subgroup.push(null); + } + } + } + return d3_transition(subgroups, id); + }; + d3_transitionPrototype.selectAll = function(selector) { + var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition; + selector = d3_selection_selectorAll(selector); + for (var j = -1, m = this.length; ++j < m; ) { + for (var group = this[j], i = -1, n = group.length; ++i < n; ) { + if (node = group[i]) { + transition = node.__transition__[id]; + subnodes = selector.call(node, node.__data__, i, j); + subgroups.push(subgroup = []); + for (var k = -1, o = subnodes.length; ++k < o; ) { + if (subnode = subnodes[k]) d3_transitionNode(subnode, k, id, transition); + subgroup.push(subnode); + } + } + } + } + return d3_transition(subgroups, id); + }; + d3_transitionPrototype.filter = function(filter) { + var subgroups = [], subgroup, group, node; + if (typeof filter !== "function") filter = d3_selection_filter(filter); + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + if ((node = group[i]) && filter.call(node, node.__data__, i, j)) { + subgroup.push(node); + } + } + } + return d3_transition(subgroups, this.id); + }; + d3_transitionPrototype.tween = function(name, tween) { + var id = this.id; + if (arguments.length < 2) return this.node().__transition__[id].tween.get(name); + return d3_selection_each(this, tween == null ? function(node) { + node.__transition__[id].tween.remove(name); + } : function(node) { + node.__transition__[id].tween.set(name, tween); + }); + }; + function d3_transition_tween(groups, name, value, tween) { + var id = groups.id; + return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) { + node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j))); + } : (value = tween(value), function(node) { + node.__transition__[id].tween.set(name, value); + })); + } + d3_transitionPrototype.attr = function(nameNS, value) { + if (arguments.length < 2) { + for (value in nameNS) this.attr(value, nameNS[value]); + return this; + } + var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS); + function attrNull() { + this.removeAttribute(name); + } + function attrNullNS() { + this.removeAttributeNS(name.space, name.local); + } + function attrTween(b) { + return b == null ? attrNull : (b += "", function() { + var a = this.getAttribute(name), i; + return a !== b && (i = interpolate(a, b), function(t) { + this.setAttribute(name, i(t)); + }); + }); + } + function attrTweenNS(b) { + return b == null ? attrNullNS : (b += "", function() { + var a = this.getAttributeNS(name.space, name.local), i; + return a !== b && (i = interpolate(a, b), function(t) { + this.setAttributeNS(name.space, name.local, i(t)); + }); + }); + } + return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween); + }; + d3_transitionPrototype.attrTween = function(nameNS, tween) { + var name = d3.ns.qualify(nameNS); + function attrTween(d, i) { + var f = tween.call(this, d, i, this.getAttribute(name)); + return f && function(t) { + this.setAttribute(name, f(t)); + }; + } + function attrTweenNS(d, i) { + var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local)); + return f && function(t) { + this.setAttributeNS(name.space, name.local, f(t)); + }; + } + return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween); + }; + d3_transitionPrototype.style = function(name, value, priority) { + var n = arguments.length; + if (n < 3) { + if (typeof name !== "string") { + if (n < 2) value = ""; + for (priority in name) this.style(priority, name[priority], value); + return this; + } + priority = ""; + } + function styleNull() { + this.style.removeProperty(name); + } + function styleString(b) { + return b == null ? styleNull : (b += "", function() { + var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i; + return a !== b && (i = d3_interpolate(a, b), function(t) { + this.style.setProperty(name, i(t), priority); + }); + }); + } + return d3_transition_tween(this, "style." + name, value, styleString); + }; + d3_transitionPrototype.styleTween = function(name, tween, priority) { + if (arguments.length < 3) priority = ""; + function styleTween(d, i) { + var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name)); + return f && function(t) { + this.style.setProperty(name, f(t), priority); + }; + } + return this.tween("style." + name, styleTween); + }; + d3_transitionPrototype.text = function(value) { + return d3_transition_tween(this, "text", value, d3_transition_text); + }; + function d3_transition_text(b) { + if (b == null) b = ""; + return function() { + this.textContent = b; + }; + } + d3_transitionPrototype.remove = function() { + return this.each("end.transition", function() { + var p; + if (this.__transition__.count < 2 && (p = this.parentNode)) p.removeChild(this); + }); + }; + d3_transitionPrototype.ease = function(value) { + var id = this.id; + if (arguments.length < 1) return this.node().__transition__[id].ease; + if (typeof value !== "function") value = d3.ease.apply(d3, arguments); + return d3_selection_each(this, function(node) { + node.__transition__[id].ease = value; + }); + }; + d3_transitionPrototype.delay = function(value) { + var id = this.id; + if (arguments.length < 1) return this.node().__transition__[id].delay; + return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { + node.__transition__[id].delay = +value.call(node, node.__data__, i, j); + } : (value = +value, function(node) { + node.__transition__[id].delay = value; + })); + }; + d3_transitionPrototype.duration = function(value) { + var id = this.id; + if (arguments.length < 1) return this.node().__transition__[id].duration; + return d3_selection_each(this, typeof value === "function" ? function(node, i, j) { + node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j)); + } : (value = Math.max(1, value), function(node) { + node.__transition__[id].duration = value; + })); + }; + d3_transitionPrototype.each = function(type, listener) { + var id = this.id; + if (arguments.length < 2) { + var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId; + d3_transitionInheritId = id; + d3_selection_each(this, function(node, i, j) { + d3_transitionInherit = node.__transition__[id]; + type.call(node, node.__data__, i, j); + }); + d3_transitionInherit = inherit; + d3_transitionInheritId = inheritId; + } else { + d3_selection_each(this, function(node) { + var transition = node.__transition__[id]; + (transition.event || (transition.event = d3.dispatch("start", "end"))).on(type, listener); + }); + } + return this; + }; + d3_transitionPrototype.transition = function() { + var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition; + for (var j = 0, m = this.length; j < m; j++) { + subgroups.push(subgroup = []); + for (var group = this[j], i = 0, n = group.length; i < n; i++) { + if (node = group[i]) { + transition = Object.create(node.__transition__[id0]); + transition.delay += transition.duration; + d3_transitionNode(node, i, id1, transition); + } + subgroup.push(node); + } + } + return d3_transition(subgroups, id1); + }; + function d3_transitionNode(node, i, id, inherit) { + var lock = node.__transition__ || (node.__transition__ = { + active: 0, + count: 0 + }), transition = lock[id]; + if (!transition) { + var time = inherit.time; + transition = lock[id] = { + tween: new d3_Map(), + time: time, + ease: inherit.ease, + delay: inherit.delay, + duration: inherit.duration + }; + ++lock.count; + d3.timer(function(elapsed) { + var d = node.__data__, ease = transition.ease, delay = transition.delay, duration = transition.duration, timer = d3_timer_active, tweened = []; + timer.t = delay + time; + if (delay <= elapsed) return start(elapsed - delay); + timer.c = start; + function start(elapsed) { + if (lock.active > id) return stop(); + lock.active = id; + transition.event && transition.event.start.call(node, d, i); + transition.tween.forEach(function(key, value) { + if (value = value.call(node, d, i)) { + tweened.push(value); + } + }); + d3.timer(function() { + timer.c = tick(elapsed || 1) ? d3_true : tick; + return 1; + }, 0, time); + } + function tick(elapsed) { + if (lock.active !== id) return stop(); + var t = elapsed / duration, e = ease(t), n = tweened.length; + while (n > 0) { + tweened[--n].call(node, e); + } + if (t >= 1) { + transition.event && transition.event.end.call(node, d, i); + return stop(); + } + } + function stop() { + if (--lock.count) delete lock[id]; else delete node.__transition__; + return 1; + } + }, 0, time); + } + } + d3.svg.axis = function() { + var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_; + function axis(g) { + g.each(function() { + var g = d3.select(this); + var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy(); + var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickTransform; + var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), + d3.transition(path)); + tickEnter.append("line"); + tickEnter.append("text"); + var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"); + switch (orient) { + case "bottom": + { + tickTransform = d3_svg_axisX; + lineEnter.attr("y2", innerTickSize); + textEnter.attr("y", Math.max(innerTickSize, 0) + tickPadding); + lineUpdate.attr("x2", 0).attr("y2", innerTickSize); + textUpdate.attr("x", 0).attr("y", Math.max(innerTickSize, 0) + tickPadding); + text.attr("dy", ".71em").style("text-anchor", "middle"); + pathUpdate.attr("d", "M" + range[0] + "," + outerTickSize + "V0H" + range[1] + "V" + outerTickSize); + break; + } + + case "top": + { + tickTransform = d3_svg_axisX; + lineEnter.attr("y2", -innerTickSize); + textEnter.attr("y", -(Math.max(innerTickSize, 0) + tickPadding)); + lineUpdate.attr("x2", 0).attr("y2", -innerTickSize); + textUpdate.attr("x", 0).attr("y", -(Math.max(innerTickSize, 0) + tickPadding)); + text.attr("dy", "0em").style("text-anchor", "middle"); + pathUpdate.attr("d", "M" + range[0] + "," + -outerTickSize + "V0H" + range[1] + "V" + -outerTickSize); + break; + } + + case "left": + { + tickTransform = d3_svg_axisY; + lineEnter.attr("x2", -innerTickSize); + textEnter.attr("x", -(Math.max(innerTickSize, 0) + tickPadding)); + lineUpdate.attr("x2", -innerTickSize).attr("y2", 0); + textUpdate.attr("x", -(Math.max(innerTickSize, 0) + tickPadding)).attr("y", 0); + text.attr("dy", ".32em").style("text-anchor", "end"); + pathUpdate.attr("d", "M" + -outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + -outerTickSize); + break; + } + + case "right": + { + tickTransform = d3_svg_axisY; + lineEnter.attr("x2", innerTickSize); + textEnter.attr("x", Math.max(innerTickSize, 0) + tickPadding); + lineUpdate.attr("x2", innerTickSize).attr("y2", 0); + textUpdate.attr("x", Math.max(innerTickSize, 0) + tickPadding).attr("y", 0); + text.attr("dy", ".32em").style("text-anchor", "start"); + pathUpdate.attr("d", "M" + outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + outerTickSize); + break; + } + } + if (scale1.rangeBand) { + var x = scale1, dx = x.rangeBand() / 2; + scale0 = scale1 = function(d) { + return x(d) + dx; + }; + } else if (scale0.rangeBand) { + scale0 = scale1; + } else { + tickExit.call(tickTransform, scale1); + } + tickEnter.call(tickTransform, scale0); + tickUpdate.call(tickTransform, scale1); + }); + } + axis.scale = function(x) { + if (!arguments.length) return scale; + scale = x; + return axis; + }; + axis.orient = function(x) { + if (!arguments.length) return orient; + orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient; + return axis; + }; + axis.ticks = function() { + if (!arguments.length) return tickArguments_; + tickArguments_ = arguments; + return axis; + }; + axis.tickValues = function(x) { + if (!arguments.length) return tickValues; + tickValues = x; + return axis; + }; + axis.tickFormat = function(x) { + if (!arguments.length) return tickFormat_; + tickFormat_ = x; + return axis; + }; + axis.tickSize = function(x) { + var n = arguments.length; + if (!n) return innerTickSize; + innerTickSize = +x; + outerTickSize = +arguments[n - 1]; + return axis; + }; + axis.innerTickSize = function(x) { + if (!arguments.length) return innerTickSize; + innerTickSize = +x; + return axis; + }; + axis.outerTickSize = function(x) { + if (!arguments.length) return outerTickSize; + outerTickSize = +x; + return axis; + }; + axis.tickPadding = function(x) { + if (!arguments.length) return tickPadding; + tickPadding = +x; + return axis; + }; + axis.tickSubdivide = function() { + return arguments.length && axis; + }; + return axis; + }; + var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = { + top: 1, + right: 1, + bottom: 1, + left: 1 + }; + function d3_svg_axisX(selection, x) { + selection.attr("transform", function(d) { + return "translate(" + x(d) + ",0)"; + }); + } + function d3_svg_axisY(selection, y) { + selection.attr("transform", function(d) { + return "translate(0," + y(d) + ")"; + }); + } + d3.svg.brush = function() { + var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0]; + function brush(g) { + g.each(function() { + var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart); + var background = g.selectAll(".background").data([ 0 ]); + background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair"); + g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move"); + var resize = g.selectAll(".resize").data(resizes, d3_identity); + resize.exit().remove(); + resize.enter().append("g").attr("class", function(d) { + return "resize " + d; + }).style("cursor", function(d) { + return d3_svg_brushCursor[d]; + }).append("rect").attr("x", function(d) { + return /[ew]$/.test(d) ? -3 : null; + }).attr("y", function(d) { + return /^[ns]/.test(d) ? -3 : null; + }).attr("width", 6).attr("height", 6).style("visibility", "hidden"); + resize.style("display", brush.empty() ? "none" : null); + var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range; + if (x) { + range = d3_scaleRange(x); + backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]); + redrawX(gUpdate); + } + if (y) { + range = d3_scaleRange(y); + backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]); + redrawY(gUpdate); + } + redraw(gUpdate); + }); + } + brush.event = function(g) { + g.each(function() { + var event_ = event.of(this, arguments), extent1 = { + x: xExtent, + y: yExtent, + i: xExtentDomain, + j: yExtentDomain + }, extent0 = this.__chart__ || extent1; + this.__chart__ = extent1; + if (d3_transitionInheritId) { + d3.select(this).transition().each("start.brush", function() { + xExtentDomain = extent0.i; + yExtentDomain = extent0.j; + xExtent = extent0.x; + yExtent = extent0.y; + event_({ + type: "brushstart" + }); + }).tween("brush:brush", function() { + var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y); + xExtentDomain = yExtentDomain = null; + return function(t) { + xExtent = extent1.x = xi(t); + yExtent = extent1.y = yi(t); + event_({ + type: "brush", + mode: "resize" + }); + }; + }).each("end.brush", function() { + xExtentDomain = extent1.i; + yExtentDomain = extent1.j; + event_({ + type: "brush", + mode: "resize" + }); + event_({ + type: "brushend" + }); + }); + } else { + event_({ + type: "brushstart" + }); + event_({ + type: "brush", + mode: "resize" + }); + event_({ + type: "brushend" + }); + } + }); + }; + function redraw(g) { + g.selectAll(".resize").attr("transform", function(d) { + return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")"; + }); + } + function redrawX(g) { + g.select(".extent").attr("x", xExtent[0]); + g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]); + } + function redrawY(g) { + g.select(".extent").attr("y", yExtent[0]); + g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]); + } + function brushstart() { + var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(), center, origin = d3.mouse(target), offset; + var w = d3.select(d3_window).on("keydown.brush", keydown).on("keyup.brush", keyup); + if (d3.event.changedTouches) { + w.on("touchmove.brush", brushmove).on("touchend.brush", brushend); + } else { + w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend); + } + g.interrupt().selectAll("*").interrupt(); + if (dragging) { + origin[0] = xExtent[0] - origin[0]; + origin[1] = yExtent[0] - origin[1]; + } else if (resizing) { + var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing); + offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ]; + origin[0] = xExtent[ex]; + origin[1] = yExtent[ey]; + } else if (d3.event.altKey) center = origin.slice(); + g.style("pointer-events", "none").selectAll(".resize").style("display", null); + d3.select("body").style("cursor", eventTarget.style("cursor")); + event_({ + type: "brushstart" + }); + brushmove(); + function keydown() { + if (d3.event.keyCode == 32) { + if (!dragging) { + center = null; + origin[0] -= xExtent[1]; + origin[1] -= yExtent[1]; + dragging = 2; + } + d3_eventPreventDefault(); + } + } + function keyup() { + if (d3.event.keyCode == 32 && dragging == 2) { + origin[0] += xExtent[1]; + origin[1] += yExtent[1]; + dragging = 0; + d3_eventPreventDefault(); + } + } + function brushmove() { + var point = d3.mouse(target), moved = false; + if (offset) { + point[0] += offset[0]; + point[1] += offset[1]; + } + if (!dragging) { + if (d3.event.altKey) { + if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ]; + origin[0] = xExtent[+(point[0] < center[0])]; + origin[1] = yExtent[+(point[1] < center[1])]; + } else center = null; + } + if (resizingX && move1(point, x, 0)) { + redrawX(g); + moved = true; + } + if (resizingY && move1(point, y, 1)) { + redrawY(g); + moved = true; + } + if (moved) { + redraw(g); + event_({ + type: "brush", + mode: dragging ? "move" : "resize" + }); + } + } + function move1(point, scale, i) { + var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max; + if (dragging) { + r0 -= position; + r1 -= size + position; + } + min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i]; + if (dragging) { + max = (min += position) + size; + } else { + if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min)); + if (position < min) { + max = min; + min = position; + } else { + max = position; + } + } + if (extent[0] != min || extent[1] != max) { + if (i) yExtentDomain = null; else xExtentDomain = null; + extent[0] = min; + extent[1] = max; + return true; + } + } + function brushend() { + brushmove(); + g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null); + d3.select("body").style("cursor", null); + w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null); + dragRestore(); + event_({ + type: "brushend" + }); + } + } + brush.x = function(z) { + if (!arguments.length) return x; + x = z; + resizes = d3_svg_brushResizes[!x << 1 | !y]; + return brush; + }; + brush.y = function(z) { + if (!arguments.length) return y; + y = z; + resizes = d3_svg_brushResizes[!x << 1 | !y]; + return brush; + }; + brush.clamp = function(z) { + if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null; + if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z; + return brush; + }; + brush.extent = function(z) { + var x0, x1, y0, y1, t; + if (!arguments.length) { + if (x) { + if (xExtentDomain) { + x0 = xExtentDomain[0], x1 = xExtentDomain[1]; + } else { + x0 = xExtent[0], x1 = xExtent[1]; + if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1); + if (x1 < x0) t = x0, x0 = x1, x1 = t; + } + } + if (y) { + if (yExtentDomain) { + y0 = yExtentDomain[0], y1 = yExtentDomain[1]; + } else { + y0 = yExtent[0], y1 = yExtent[1]; + if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1); + if (y1 < y0) t = y0, y0 = y1, y1 = t; + } + } + return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ]; + } + if (x) { + x0 = z[0], x1 = z[1]; + if (y) x0 = x0[0], x1 = x1[0]; + xExtentDomain = [ x0, x1 ]; + if (x.invert) x0 = x(x0), x1 = x(x1); + if (x1 < x0) t = x0, x0 = x1, x1 = t; + if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ]; + } + if (y) { + y0 = z[0], y1 = z[1]; + if (x) y0 = y0[1], y1 = y1[1]; + yExtentDomain = [ y0, y1 ]; + if (y.invert) y0 = y(y0), y1 = y(y1); + if (y1 < y0) t = y0, y0 = y1, y1 = t; + if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ]; + } + return brush; + }; + brush.clear = function() { + if (!brush.empty()) { + xExtent = [ 0, 0 ], yExtent = [ 0, 0 ]; + xExtentDomain = yExtentDomain = null; + } + return brush; + }; + brush.empty = function() { + return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1]; + }; + return d3.rebind(brush, event, "on"); + }; + var d3_svg_brushCursor = { + n: "ns-resize", + e: "ew-resize", + s: "ns-resize", + w: "ew-resize", + nw: "nwse-resize", + ne: "nesw-resize", + se: "nwse-resize", + sw: "nesw-resize" + }; + var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ]; + var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat; + var d3_time_formatUtc = d3_time_format.utc; + var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ"); + d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso; + function d3_time_formatIsoNative(date) { + return date.toISOString(); + } + d3_time_formatIsoNative.parse = function(string) { + var date = new Date(string); + return isNaN(date) ? null : date; + }; + d3_time_formatIsoNative.toString = d3_time_formatIso.toString; + d3_time.second = d3_time_interval(function(date) { + return new d3_date(Math.floor(date / 1e3) * 1e3); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 1e3); + }, function(date) { + return date.getSeconds(); + }); + d3_time.seconds = d3_time.second.range; + d3_time.seconds.utc = d3_time.second.utc.range; + d3_time.minute = d3_time_interval(function(date) { + return new d3_date(Math.floor(date / 6e4) * 6e4); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 6e4); + }, function(date) { + return date.getMinutes(); + }); + d3_time.minutes = d3_time.minute.range; + d3_time.minutes.utc = d3_time.minute.utc.range; + d3_time.hour = d3_time_interval(function(date) { + var timezone = date.getTimezoneOffset() / 60; + return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5); + }, function(date, offset) { + date.setTime(date.getTime() + Math.floor(offset) * 36e5); + }, function(date) { + return date.getHours(); + }); + d3_time.hours = d3_time.hour.range; + d3_time.hours.utc = d3_time.hour.utc.range; + d3_time.month = d3_time_interval(function(date) { + date = d3_time.day(date); + date.setDate(1); + return date; + }, function(date, offset) { + date.setMonth(date.getMonth() + offset); + }, function(date) { + return date.getMonth(); + }); + d3_time.months = d3_time.month.range; + d3_time.months.utc = d3_time.month.utc.range; + function d3_time_scale(linear, methods, format) { + function scale(x) { + return linear(x); + } + scale.invert = function(x) { + return d3_time_scaleDate(linear.invert(x)); + }; + scale.domain = function(x) { + if (!arguments.length) return linear.domain().map(d3_time_scaleDate); + linear.domain(x); + return scale; + }; + function tickMethod(extent, count) { + var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target); + return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) { + return d / 31536e6; + }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i]; + } + scale.nice = function(interval, skip) { + var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval); + if (method) interval = method[0], skip = method[1]; + function skipped(date) { + return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length; + } + return scale.domain(d3_scale_nice(domain, skip > 1 ? { + floor: function(date) { + while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1); + return date; + }, + ceil: function(date) { + while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1); + return date; + } + } : interval)); + }; + scale.ticks = function(interval, skip) { + var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ { + range: interval + }, skip ]; + if (method) interval = method[0], skip = method[1]; + return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip); + }; + scale.tickFormat = function() { + return format; + }; + scale.copy = function() { + return d3_time_scale(linear.copy(), methods, format); + }; + return d3_scale_linearRebind(scale, linear); + } + function d3_time_scaleDate(t) { + return new Date(t); + } + var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ]; + var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ]; + var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) { + return d.getMilliseconds(); + } ], [ ":%S", function(d) { + return d.getSeconds(); + } ], [ "%I:%M", function(d) { + return d.getMinutes(); + } ], [ "%I %p", function(d) { + return d.getHours(); + } ], [ "%a %d", function(d) { + return d.getDay() && d.getDate() != 1; + } ], [ "%b %d", function(d) { + return d.getDate() != 1; + } ], [ "%B", function(d) { + return d.getMonth(); + } ], [ "%Y", d3_true ] ]); + var d3_time_scaleMilliseconds = { + range: function(start, stop, step) { + return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate); + }, + floor: d3_identity, + ceil: d3_identity + }; + d3_time_scaleLocalMethods.year = d3_time.year; + d3_time.scale = function() { + return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat); + }; + var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) { + return [ m[0].utc, m[1] ]; + }); + var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) { + return d.getUTCMilliseconds(); + } ], [ ":%S", function(d) { + return d.getUTCSeconds(); + } ], [ "%I:%M", function(d) { + return d.getUTCMinutes(); + } ], [ "%I %p", function(d) { + return d.getUTCHours(); + } ], [ "%a %d", function(d) { + return d.getUTCDay() && d.getUTCDate() != 1; + } ], [ "%b %d", function(d) { + return d.getUTCDate() != 1; + } ], [ "%B", function(d) { + return d.getUTCMonth(); + } ], [ "%Y", d3_true ] ]); + d3_time_scaleUtcMethods.year = d3_time.year.utc; + d3_time.scale.utc = function() { + return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat); + }; + d3.text = d3_xhrType(function(request) { + return request.responseText; + }); + d3.json = function(url, callback) { + return d3_xhr(url, "application/json", d3_json, callback); + }; + function d3_json(request) { + return JSON.parse(request.responseText); + } + d3.html = function(url, callback) { + return d3_xhr(url, "text/html", d3_html, callback); + }; + function d3_html(request) { + var range = d3_document.createRange(); + range.selectNode(d3_document.body); + return range.createContextualFragment(request.responseText); + } + d3.xml = d3_xhrType(function(request) { + return request.responseXML; + }); + if (typeof define === "function" && define.amd) define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; + this.d3 = d3; +}(); \ No newline at end of file diff --git a/src/static/dagre-d3/d3.v3.min.js b/src/static/dagre-d3/d3.v3.min.js new file mode 100644 index 0000000..88550ae --- /dev/null +++ b/src/static/dagre-d3/d3.v3.min.js @@ -0,0 +1,5 @@ +!function(){function n(n,t){return t>n?-1:n>t?1:n>=t?0:0/0}function t(n){return null!=n&&!isNaN(n)}function e(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function r(n){return n.length}function u(n){for(var t=1;n*t%1;)t*=10;return t}function i(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function o(){}function a(n){return ia+n in this}function c(n){return n=ia+n,n in this&&delete this[n]}function s(){var n=[];return this.forEach(function(t){n.push(t)}),n}function l(){var n=0;for(var t in this)t.charCodeAt(0)===oa&&++n;return n}function f(){for(var n in this)if(n.charCodeAt(0)===oa)return!1;return!0}function h(){}function g(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function p(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=aa.length;r>e;++e){var u=aa[e]+t;if(u in n)return u}}function v(){}function d(){}function m(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new o;return t.on=function(t,u){var i,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function y(){Zo.event.preventDefault()}function x(){for(var n,t=Zo.event;n=t.sourceEvent;)t=n;return t}function M(n){for(var t=new d,e=0,r=arguments.length;++e<r;)t[arguments[e]]=m(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=Zo.event;u.target=n,Zo.event=u,t[u.type].apply(e,r)}finally{Zo.event=i}}},t}function _(n){return sa(n,pa),n}function b(n){return"function"==typeof n?n:function(){return la(n,this)}}function w(n){return"function"==typeof n?n:function(){return fa(n,this)}}function S(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=Zo.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?i:u}function k(n){return n.trim().replace(/\s+/g," ")}function E(n){return new RegExp("(?:^|\\s+)"+Zo.requote(n)+"(?:\\s+|$)","g")}function A(n){return(n+"").trim().split(/^|\s+/)}function C(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=A(n).map(N);var u=n.length;return"function"==typeof t?r:e}function N(n){var t=E(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",k(u+" "+n))):e.setAttribute("class",k(u.replace(t," ")))}}function z(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function L(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function T(n){return"function"==typeof n?n:(n=Zo.ns.qualify(n)).local?function(){return this.ownerDocument.createElementNS(n.space,n.local)}:function(){return this.ownerDocument.createElementNS(this.namespaceURI,n)}}function q(n){return{__data__:n}}function R(n){return function(){return ga(this,n)}}function D(t){return arguments.length||(t=n),function(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}}function P(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function U(n){return sa(n,da),n}function j(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t<c;);return o}}function H(){var n=this.__transition__;n&&++n.active}function F(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=c(t,Xo(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp("^__on([^.]+)"+Zo.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),c=O;a>0&&(n=n.substring(0,a));var s=ya.get(n);return s&&(n=s,c=Y),a?t?u:r:t?v:i}function O(n,t){return function(e){var r=Zo.event;Zo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Zo.event=r}}}function Y(n,t){var e=O(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function I(){var n=".dragsuppress-"+ ++Ma,t="click"+n,e=Zo.select(Wo).on("touchmove"+n,y).on("dragstart"+n,y).on("selectstart"+n,y);if(xa){var r=Bo.style,u=r[xa];r[xa]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),xa&&(r[xa]=u),i&&(e.on(t,function(){y(),o()},!0),setTimeout(o,0))}}function Z(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>_a&&(Wo.scrollX||Wo.scrollY)){e=Zo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();_a=!(u.f||u.e),e.remove()}return _a?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function V(){return Zo.event.changedTouches[0].identifier}function X(){return Zo.event.target}function $(){return Wo}function B(n){return n>0?1:0>n?-1:0}function W(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function J(n){return n>1?0:-1>n?ba:Math.acos(n)}function G(n){return n>1?Sa:-1>n?-Sa:Math.asin(n)}function K(n){return((n=Math.exp(n))-1/n)/2}function Q(n){return((n=Math.exp(n))+1/n)/2}function nt(n){return((n=Math.exp(2*n))-1)/(n+1)}function tt(n){return(n=Math.sin(n/2))*n}function et(){}function rt(n,t,e){return this instanceof rt?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof rt?new rt(n.h,n.s,n.l):mt(""+n,yt,rt):new rt(n,t,e)}function ut(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,new gt(u(n+120),u(n),u(n-120))}function it(n,t,e){return this instanceof it?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof it?new it(n.h,n.c,n.l):n instanceof at?st(n.l,n.a,n.b):st((n=xt((n=Zo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new it(n,t,e)}function ot(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new at(e,Math.cos(n*=Aa)*t,Math.sin(n)*t)}function at(n,t,e){return this instanceof at?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof at?new at(n.l,n.a,n.b):n instanceof it?ot(n.l,n.c,n.h):xt((n=gt(n)).r,n.g,n.b):new at(n,t,e)}function ct(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=lt(u)*ja,r=lt(r)*Ha,i=lt(i)*Fa,new gt(ht(3.2404542*u-1.5371385*r-.4985314*i),ht(-.969266*u+1.8760108*r+.041556*i),ht(.0556434*u-.2040259*r+1.0572252*i))}function st(n,t,e){return n>0?new it(Math.atan2(e,t)*Ca,Math.sqrt(t*t+e*e),n):new it(0/0,0/0,n)}function lt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function ft(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function ht(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function gt(n,t,e){return this instanceof gt?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof gt?new gt(n.r,n.g,n.b):mt(""+n,gt,ut):new gt(n,t,e)}function pt(n){return new gt(n>>16,255&n>>8,255&n)}function vt(n){return pt(n)+""}function dt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function mt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(_t(u[0]),_t(u[1]),_t(u[2]))}return(i=Ia.get(n))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.substring(1),16))||(4===n.length?(o=(3840&i)>>4,o=o>>4|o,a=240&i,a=a>>4|a,c=15&i,c=c<<4|c):7===n.length&&(o=(16711680&i)>>16,a=(65280&i)>>8,c=255&i)),t(o,a,c))}function yt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),new rt(r,u,c)}function xt(n,t,e){n=Mt(n),t=Mt(t),e=Mt(e);var r=ft((.4124564*n+.3575761*t+.1804375*e)/ja),u=ft((.2126729*n+.7151522*t+.072175*e)/Ha),i=ft((.0193339*n+.119192*t+.9503041*e)/Fa);return at(116*u-16,500*(r-u),200*(u-i))}function Mt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function _t(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function bt(n){return"function"==typeof n?n:function(){return n}}function wt(n){return n}function St(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),kt(t,e,n,r)}}function kt(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Zo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Wo.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Zo.event;Zo.event=n;try{o.progress.call(i,c)}finally{Zo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Xo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Zo.rebind(i,o,"on"),null==r?i:i.get(Et(r))}function Et(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function At(){var n=Ct(),t=Nt()-n;t>24?(isFinite(t)&&(clearTimeout($a),$a=setTimeout(At,t)),Xa=0):(Xa=1,Wa(At))}function Ct(){var n=Date.now();for(Ba=Za;Ba;)n>=Ba.t&&(Ba.f=Ba.c(n-Ba.t)),Ba=Ba.n;return n}function Nt(){for(var n,t=Za,e=1/0;t;)t.f?t=n?n.n=t.n:Za=t.n:(t.t<e&&(e=t.t),t=(n=t).n);return Va=n,e}function zt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Lt(n,t){var e=Math.pow(10,3*ua(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Tt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:wt;return function(n){var e=Ga.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=Ka.get(g)||qt;var y=s&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var c=Zo.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x=n.lastIndexOf("."),M=0>x?n:n.substring(0,x),_=0>x?"":t+n.substring(x+1);!s&&f&&(M=i(M));var b=v.length+M.length+_.length+(y?0:u.length),w=l>b?new Array(b=l-b+1).join(r):"";return y&&(M=i(w+M)),u+=v,n=M+_,("<"===o?u+n+w:">"===o?w+u+n:"^"===o?w.substring(0,b>>=1)+u+n+w.substring(b):u+(y?n:w+n))+e}}}function qt(n){return n+""}function Rt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Dt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new nc(e-1)),1),e}function i(n,e){return t(n=new nc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{nc=Rt;var r=new Rt;return r._=n,o(r,t,e)}finally{nc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Pt(n);return c.floor=c,c.round=Pt(r),c.ceil=Pt(u),c.offset=Pt(i),c.range=a,n}function Pt(n){return function(t,e){try{nc=Rt;var r=new Rt;return r._=t,n(r,e)._}finally{nc=Date}}}function Ut(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.substring(c,a)),null!=(u=ec[e=n.charAt(++a)])&&(e=n.charAt(++a)),(i=C[e])&&(e=i(t,null==u?"e"===e?" ":"0":u)),o.push(e),c=a+1);return o.push(n.substring(c,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var i=null!=r.Z&&nc!==Rt,o=new(i?Rt:nc);return"j"in r?o.setFullYear(r.y,0,r.j):"w"in r&&("W"in r||"U"in r)?(o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+Math.floor(r.Z/100),r.M+r.Z%100,r.S,r.L),i?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,o,a=0,c=t.length,s=e.length;c>a;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in ec?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{nc=Rt;var t=new nc;return t._=n,r(t)}finally{nc=Date}}var r=t(n);return e.parse=function(n){try{nc=Rt;var t=r.parse(n);return t&&t._}finally{nc=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=re;var x=Zo.map(),M=Ht(v),_=Ft(v),b=Ht(d),w=Ft(d),S=Ht(m),k=Ft(m),E=Ht(y),A=Ft(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return jt(n.getDate(),t,2)},e:function(n,t){return jt(n.getDate(),t,2)},H:function(n,t){return jt(n.getHours(),t,2)},I:function(n,t){return jt(n.getHours()%12||12,t,2)},j:function(n,t){return jt(1+Qa.dayOfYear(n),t,3)},L:function(n,t){return jt(n.getMilliseconds(),t,3)},m:function(n,t){return jt(n.getMonth()+1,t,2)},M:function(n,t){return jt(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return jt(n.getSeconds(),t,2)},U:function(n,t){return jt(Qa.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return jt(Qa.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return jt(n.getFullYear()%100,t,2)},Y:function(n,t){return jt(n.getFullYear()%1e4,t,4)},Z:te,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Wt,e:Wt,H:Gt,I:Gt,j:Jt,L:ne,m:Bt,M:Kt,p:l,S:Qt,U:Yt,w:Ot,W:It,x:c,X:s,y:Vt,Y:Zt,Z:Xt,"%":ee};return t}function jt(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Ht(n){return new RegExp("^(?:"+n.map(Zo.requote).join("|")+")","i")}function Ft(n){for(var t=new o,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Ot(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Yt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e));return r?(n.U=+r[0],e+r[0].length):-1}function It(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e));return r?(n.W=+r[0],e+r[0].length):-1}function Zt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Vt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.y=$t(+r[0]),e+r[0].length):-1}function Xt(n,t,e){return/^[+-]\d{4}$/.test(t=t.substring(e,e+5))?(n.Z=-t,e+5):-1}function $t(n){return n+(n>68?1900:2e3)}function Bt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Wt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Jt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Gt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Kt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Qt(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ne(n,t,e){rc.lastIndex=0;var r=rc.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function te(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(ua(t)/60),u=ua(t)%60;return e+jt(r,"0",2)+jt(u,"0",2)}function ee(n,t,e){uc.lastIndex=0;var r=uc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function re(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function ue(){}function ie(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function oe(n,t){n&&cc.hasOwnProperty(n.type)&&cc[n.type](n,t)}function ae(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function ce(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)ae(n[e],t,1);t.polygonEnd()}function se(){function n(n,t){n*=Aa,t=t*Aa/2+ba/4;var e=n-r,o=e>=0?1:-1,a=o*e,c=Math.cos(t),s=Math.sin(t),l=i*s,f=u*c+l*Math.cos(a),h=l*o*Math.sin(a);lc.add(Math.atan2(h,f)),r=n,u=c,i=s}var t,e,r,u,i;fc.point=function(o,a){fc.point=n,r=(t=o)*Aa,u=Math.cos(a=(e=a)*Aa/2+ba/4),i=Math.sin(a)},fc.lineEnd=function(){n(t,e)}}function le(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function fe(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function he(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function ge(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function pe(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function ve(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function de(n){return[Math.atan2(n[1],n[0]),G(n[2])]}function me(n,t){return ua(n[0]-t[0])<ka&&ua(n[1]-t[1])<ka}function ye(n,t){n*=Aa;var e=Math.cos(t*=Aa);xe(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function xe(n,t,e){++hc,pc+=(n-pc)/hc,vc+=(t-vc)/hc,dc+=(e-dc)/hc}function Me(){function n(n,u){n*=Aa;var i=Math.cos(u*=Aa),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),s=Math.atan2(Math.sqrt((s=e*c-r*a)*s+(s=r*o-t*c)*s+(s=t*a-e*o)*s),t*o+e*a+r*c);gc+=s,mc+=s*(t+(t=o)),yc+=s*(e+(e=a)),xc+=s*(r+(r=c)),xe(t,e,r)}var t,e,r;wc.point=function(u,i){u*=Aa;var o=Math.cos(i*=Aa);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),wc.point=n,xe(t,e,r)}}function _e(){wc.point=ye}function be(){function n(n,t){n*=Aa;var e=Math.cos(t*=Aa),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),s=u*c-i*a,l=i*o-r*c,f=r*a-u*o,h=Math.sqrt(s*s+l*l+f*f),g=r*o+u*a+i*c,p=h&&-J(g)/h,v=Math.atan2(h,g);Mc+=p*s,_c+=p*l,bc+=p*f,gc+=v,mc+=v*(r+(r=o)),yc+=v*(u+(u=a)),xc+=v*(i+(i=c)),xe(r,u,i)}var t,e,r,u,i;wc.point=function(o,a){t=o,e=a,wc.point=n,o*=Aa;var c=Math.cos(a*=Aa);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),xe(r,u,i)},wc.lineEnd=function(){n(t,e),wc.lineEnd=_e,wc.point=ye}}function we(){return!0}function Se(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(me(e,r)){u.lineStart();for(var a=0;t>a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new Ee(e,n,null,!0),s=new Ee(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new Ee(r,n,null,!1),s=new Ee(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),ke(i),ke(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function ke(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function Ee(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Ae(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function a(n,t){var e=u(n,t);d.point(e[0],e[1])}function c(){y.point=a,d.lineStart()}function s(){y.point=o,d.lineEnd()}function l(n,t){v.push([n,t]);var e=u(n,t);M.point(e[0],e[1])}function f(){M.lineStart(),v=[]}function h(){l(v[0][0],v[0][1]),M.lineEnd();var n,t=M.clean(),e=x.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r)if(1&t){n=e[0];var u,r=n.length-1,o=-1;if(r>0){for(_||(i.polygonStart(),_=!0),i.lineStart();++o<r;)i.point((u=n[o])[0],u[1]);i.lineEnd()}}else r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ce))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Zo.merge(g);var n=Le(m,p);g.length?(_||(i.polygonStart(),_=!0),Se(g,ze,n,e,i)):n&&(_||(i.polygonStart(),_=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),_&&(i.polygonEnd(),_=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ne(),M=t(x),_=!1;return y}}function Ce(n){return n.length>1}function Ne(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:v,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function ze(n,t){return((n=n.x)[0]<0?n[1]-Sa-ka:Sa-n[1])-((t=t.x)[0]<0?t[1]-Sa-ka:Sa-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;lc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+ba/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+ba/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=_>=0?1:-1,w=b*_,S=w>ba,k=p*x;if(lc.add(Math.atan2(k*b*Math.sin(w),v*M+k*Math.cos(w))),i+=S?_+b*wa:_,S^h>=e^m>=e){var E=he(le(f),le(n));ve(E);var A=he(u,E);ve(A);var C=(S^_>=0?-1:1)*G(A[2]);(r>C||r===C&&(E[0]||E[1]))&&(o+=S^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-ka>i||ka>i&&0>lc)^1&o}function Te(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?ba:-ba,c=ua(i-e);ua(c-ba)<ka?(n.point(e,r=(r+o)/2>0?Sa:-Sa),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=ba&&(ua(e-u)<ka&&(e-=u*ka),ua(i-a)<ka&&(i-=a*ka),r=qe(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function qe(n,t,e,r){var u,i,o=Math.sin(n-e);return ua(o)>ka?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function Re(n,t,e,r){var u;if(null==n)u=e*Sa,r.point(-ba,u),r.point(0,u),r.point(ba,u),r.point(ba,0),r.point(ba,-u),r.point(0,-u),r.point(-ba,-u),r.point(-ba,0),r.point(-ba,u);else if(ua(n[0]-t[0])>ka){var i=n[0]<t[0]?ba:-ba;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function De(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?ba:-ba),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(me(e,g)||me(p,g))&&(p[0]+=ka,p[1]+=ka,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&me(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=le(n),u=le(t),o=[1,0,0],a=he(r,u),c=fe(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=he(o,a),p=pe(o,f),v=pe(a,h);ge(p,v);var d=g,m=fe(p,d),y=fe(d,d),x=m*m-y*(fe(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=pe(d,(-m-M)/y);if(ge(_,p),_=de(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=ua(A-ba)<ka,N=C||ka>A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(ua(_[0]-w)<ka?k:E):k<=_[1]&&_[1]<=E:A>ba^(w<=_[0]&&_[0]<=S)){var z=pe(d,(-m+M)/y);return ge(z,p),[_,de(z)]}}}function u(t,e){var r=o?n:ba-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=ua(i)>ka,c=sr(n,6*Aa);return Ae(t,e,c,o?[0,-n]:[-ba,n-ba])}function Pe(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Ue(n,t,e,r){function u(r,u){return ua(r[0]-n)<ka?u>0?0:3:ua(r[0]-e)<ka?u>0?2:1:ua(r[1]-t)<ka?u>0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&W(s,i,n)>0&&++t:i[1]<=r&&W(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-kc,Math.min(kc,n)),t=Math.max(-kc,Math.min(kc,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ne(),C=Pe(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Zo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&Se(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function je(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function He(n){var t=0,e=ba/3,r=tr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*ba/180,e=n[1]*ba/180):[180*(t/ba),180*(e/ba)]},u}function Fe(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,G((i-(n*n+e*e)*u*u)/(2*u))]},e}function Oe(){function n(n,t){Ac+=u*n-r*t,r=n,u=t}var t,e,r,u;Tc.point=function(i,o){Tc.point=n,t=r=i,e=u=o},Tc.lineEnd=function(){n(t,e)}}function Ye(n,t){Cc>n&&(Cc=n),n>zc&&(zc=n),Nc>t&&(Nc=t),t>Lc&&(Lc=t)}function Ie(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ze(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ze(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ze(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ve(n,t){pc+=n,vc+=t,++dc}function Xe(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);mc+=o*(t+n)/2,yc+=o*(e+r)/2,xc+=o,Ve(t=n,e=r)}var t,e;Rc.point=function(r,u){Rc.point=n,Ve(t=r,e=u)}}function $e(){Rc.point=Ve}function Be(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);mc+=o*(r+n)/2,yc+=o*(u+t)/2,xc+=o,o=u*n-r*t,Mc+=o*(r+n),_c+=o*(u+t),bc+=3*o,Ve(r=n,u=t)}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,Ve(t=r=i,e=u=o)},Rc.lineEnd=function(){n(t,e)}}function We(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,wa)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:v};return a}function Je(n){function t(n){return(a?r:e)(n)}function e(t){return Qe(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=le([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=ua(ua(w)-1)<ka||ua(r-h)<ka?(r+h)/2:Math.atan2(b,_),A=n(E,k),C=A[0],N=A[1],z=C-t,L=N-e,T=x*z-y*L;(T*T/M>i||ua((y*z+x*L)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Aa),a=16; +return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Ge(n){var t=Je(function(t,e){return n([t*Ca,e*Ca])});return function(n){return er(t(n))}}function Ke(n){this.stream=n}function Qe(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function nr(n){return tr(function(){return n})()}function tr(n){function t(n){return n=a(n[0]*Aa,n[1]*Aa),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*Ca,n[1]*Ca]}function r(){a=je(o=ir(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=Je(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Sc,_=wt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=er(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Sc):De((b=+n)*Aa),u()):b},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Ue(n[0][0],n[0][1],n[1][0],n[1][1]):wt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Aa,d=n[1]%360*Aa,r()):[v*Ca,d*Ca]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Aa,y=n[1]%360*Aa,x=n.length>2?n[2]%360*Aa:0,r()):[m*Ca,y*Ca,x*Ca]},Zo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function er(n){return Qe(n,function(t,e){n.point(t*Aa,e*Aa)})}function rr(n,t){return[n,t]}function ur(n,t){return[n>ba?n-wa:-ba>n?n+wa:n,t]}function ir(n,t,e){return n?t||e?je(ar(n),cr(t,e)):ar(n):t||e?cr(t,e):ur}function or(n){return function(t,e){return t+=n,[t>ba?t-wa:-ba>t?t+wa:t,e]}}function ar(n){var t=or(n);return t.invert=or(-n),t}function cr(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),G(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),G(l*r-a*u)]},e}function sr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=lr(e,u),i=lr(e,i),(o>0?i>u:u>i)&&(u+=o*wa)):(u=n+o*wa,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=de([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function lr(n,t){var e=le(t);e[0]-=n,ve(e);var r=J(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-ka)%(2*Math.PI)}function fr(n,t,e){var r=Zo.range(n,t-ka,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function hr(n,t,e){var r=Zo.range(n,t-ka,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function gr(n){return n.source}function pr(n){return n.target}function vr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(tt(r-t)+u*o*tt(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*Ca,Math.atan2(o,Math.sqrt(r*r+u*u))*Ca]}:function(){return[n*Ca,t*Ca]};return p.distance=h,p}function dr(){function n(n,u){var i=Math.sin(u*=Aa),o=Math.cos(u),a=ua((n*=Aa)-t),c=Math.cos(a);Dc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;Pc.point=function(u,i){t=u*Aa,e=Math.sin(i*=Aa),r=Math.cos(i),Pc.point=n},Pc.lineEnd=function(){Pc.point=Pc.lineEnd=v}}function mr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function yr(n,t){function e(n,t){o>0?-Sa+ka>t&&(t=-Sa+ka):t>Sa-ka&&(t=Sa-ka);var e=o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(ba/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=B(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Sa]},e):Mr}function xr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return ua(u)<ka?rr:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-B(u)*Math.sqrt(n*n+e*e)]},e)}function Mr(n,t){return[n,Math.log(Math.tan(ba/4+t/2))]}function _r(n){var t,e=nr(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=ba*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function br(n,t){return[Math.log(Math.tan(ba/4+t/2)),-n]}function wr(n){return n[0]}function Sr(n){return n[1]}function kr(n){for(var t=n.length,e=[0,1],r=2,u=2;t>u;u++){for(;r>1&&W(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function Er(n,t){return n[0]-t[0]||n[1]-t[1]}function Ar(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Cr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Nr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function zr(){Gr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Bc.pop()||new zr;return t.site=n,t}function Tr(n){Yr(n),Vc.remove(n),Bc.push(n),Gr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Tr(n);for(var c=i;c.circle&&ua(e-c.circle.x)<ka&&ua(r-c.circle.cy)<ka;)i=c.P,a.unshift(c),Tr(c),c=i;a.unshift(c),Yr(c);for(var s=o;s.circle&&ua(e-s.circle.x)<ka&&ua(r-s.circle.cy)<ka;)o=s.N,a.push(s),Tr(s),s=o;a.push(s),Yr(s);var l,f=a.length;for(l=1;f>l;++l)s=a[l],c=a[l-1],Br(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Xr(c.site,s.site,null,u),Or(c),Or(s)}function Rr(n){for(var t,e,r,u,i=n.x,o=n.y,a=Vc._;a;)if(r=Dr(a,o)-i,r>ka)a=a.L;else{if(u=i-Pr(a,o),!(u>ka)){r>-ka?(t=a.P,e=a):u>-ka?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if(Vc.insert(t,c),t||e){if(t===e)return Yr(t),e=Lr(t.site),Vc.insert(c,e),c.edge=e.edge=Xr(t.site,c.site),Or(t),Or(e),void 0;if(!e)return c.edge=Xr(t.site,c.site),void 0;Yr(t),Yr(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};Br(e.edge,s,p,M),c.edge=Xr(s,n,null,M),e.edge=Xr(n,p,null,M),Or(t),Or(e)}}function Dr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Pr(n,t){var e=n.N;if(e)return Dr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ur(n){this.site=n,this.edges=[]}function jr(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Zc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(ua(r-t)>ka||ua(u-e)>ka)&&(a.splice(o,0,new Wr($r(i.site,l,ua(r-f)<ka&&p-u>ka?{x:f,y:ua(t-f)<ka?e:p}:ua(u-p)<ka&&h-r>ka?{x:ua(e-p)<ka?t:h,y:p}:ua(r-h)<ka&&u-g>ka?{x:h,y:ua(t-h)<ka?e:g}:ua(u-g)<ka&&r-f>ka?{x:ua(e-g)<ka?t:f,y:g}:null),i.site,null)),++c)}function Hr(n,t){return t.angle-n.angle}function Fr(){Gr(this),this.x=this.y=this.arc=this.site=this.cy=null}function Or(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,u=n.site,i=e.site;if(r!==i){var o=u.x,a=u.y,c=r.x-o,s=r.y-a,l=i.x-o,f=i.y-a,h=2*(c*f-s*l);if(!(h>=-Ea)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Wc.pop()||new Fr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=$c._;x;)if(m.y<x.y||m.y===x.y&&m.x<=x.x){if(!x.L){y=x.P;break}x=x.L}else{if(!x.R){y=x;break}x=x.R}$c.insert(y,m),y||(Xc=m)}}}}function Yr(n){var t=n.circle;t&&(t.P||(Xc=t.N),$c.remove(t),Wc.push(t),Gr(t),n.circle=null)}function Ir(n){for(var t,e=Ic,r=Pe(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Zr(t,n)||!r(t)||ua(t.a.x-t.b.x)<ka&&ua(t.a.y-t.b.y)<ka)&&(t.a=t.b=null,e.splice(u,1))}function Zr(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,o=t[0][0],a=t[1][0],c=t[0][1],s=t[1][1],l=n.l,f=n.r,h=l.x,g=l.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(o>d||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.y<c)return}else i={x:d,y:s};e={x:d,y:c}}}else if(r=(h-p)/(v-g),u=m-r*d,-1>r||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.y<c)return}else i={x:(s-u)/r,y:s};e={x:(c-u)/r,y:c}}else if(v>g){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.x<o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}return n.a=i,n.b=e,!0}function Vr(n,t){this.l=n,this.r=t,this.a=this.b=null}function Xr(n,t,e,r){var u=new Vr(n,t);return Ic.push(u),e&&Br(u,n,t,e),r&&Br(u,t,n,r),Zc[n.i].edges.push(new Wr(u,n,t)),Zc[t.i].edges.push(new Wr(u,t,n)),u}function $r(n,t,e){var r=new Vr(n,null);return r.a=t,r.b=e,Ic.push(r),r}function Br(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function Wr(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function Jr(){this._=null}function Gr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function Kr(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function Qr(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function nu(n){for(;n.L;)n=n.L;return n}function tu(n,t){var e,r,u,i=n.sort(eu).pop();for(Ic=[],Zc=new Array(n.length),Vc=new Jr,$c=new Jr;;)if(u=Xc,i&&(!u||i.y<u.y||i.y===u.y&&i.x<u.x))(i.x!==e||i.y!==r)&&(Zc[i.i]=new Ur(i),Rr(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;qr(u.arc)}t&&(Ir(t),jr(t));var o={cells:Zc,edges:Ic};return Vc=$c=Ic=Zc=null,o}function eu(n,t){return t.y-n.y||t.x-n.x}function ru(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function uu(n){return n.x}function iu(n){return n.y}function ou(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function au(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&au(n,c[0],e,r,o,a),c[1]&&au(n,c[1],o,r,u,a),c[2]&&au(n,c[2],e,a,o,i),c[3]&&au(n,c[3],o,a,u,i)}}function cu(n,t){n=Zo.rgb(n),t=Zo.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+dt(Math.round(e+i*n))+dt(Math.round(r+o*n))+dt(Math.round(u+a*n))}}function su(n,t){var e,r={},u={};for(e in n)e in t?r[e]=hu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function lu(n,t){return t-=n=+n,function(e){return n+t*e}}function fu(n,t){var e,r,u,i=Gc.lastIndex=Kc.lastIndex=0,o=-1,a=[],c=[];for(n+="",t+="";(e=Gc.exec(n))&&(r=Kc.exec(t));)(u=r.index)>i&&(u=t.substring(i,u),a[o]?a[o]+=u:a[++o]=u),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,c.push({i:o,x:lu(e,r)})),i=Kc.lastIndex;return i<t.length&&(u=t.substring(i),a[o]?a[o]+=u:a[++o]=u),a.length<2?c[0]?(t=c[0].x,function(n){return t(n)+""}):function(){return t}:(t=c.length,function(n){for(var e,r=0;t>r;++r)a[(e=c[r]).i]=e.x(n);return a.join("")})}function hu(n,t){for(var e,r=Zo.interpolators.length;--r>=0&&!(e=Zo.interpolators[r](n,t)););return e}function gu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(hu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function pu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function vu(n){return function(t){return 1-n(1-t)}}function du(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function mu(n){return n*n}function yu(n){return n*n*n}function xu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Mu(n){return function(t){return Math.pow(t,n)}}function _u(n){return 1-Math.cos(n*Sa)}function bu(n){return Math.pow(2,10*(n-1))}function wu(n){return 1-Math.sqrt(1-n*n)}function Su(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/wa*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*wa/t)}}function ku(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Eu(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Au(n,t){n=Zo.hcl(n),t=Zo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Zo.hsl(n),t=Zo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ut(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){n=Zo.lab(n),t=Zo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ct(e+i*n,r+o*n,u+a*n)+""}}function zu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=Tu(t,e),i=qu(Ru(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*Ca,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*Ca:0}function Tu(n,t){return n[0]*t[0]+n[1]*t[1]}function qu(n){var t=Math.sqrt(Tu(n,n));return t&&(n[0]/=t,n[1]/=t),t}function Ru(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Du(n,t){var e,r=[],u=[],i=Zo.transform(n),o=Zo.transform(t),a=i.translate,c=o.translate,s=i.rotate,l=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:lu(a[0],c[0])},{i:3,x:lu(a[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),s!=l?(s-l>180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:lu(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:lu(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:lu(g[0],p[0])},{i:e-2,x:lu(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i<e;)r[(t=u[i]).i]=t.x(n);return r.join("")}}function Pu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Uu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function ju(n){for(var t=n.source,e=n.target,r=Fu(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function Hu(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Fu(n,t){if(n===t)return n;for(var e=Hu(n),r=Hu(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function Ou(n){n.fixed|=2}function Yu(n){n.fixed&=-7}function Iu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Zu(n){n.fixed&=-5}function Vu(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c<a;)i=o[c],null!=i&&(Vu(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var s=t*e[n.point.index];n.charge+=n.pointCharge=s,r+=s*n.point.x,u+=s*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function Xu(n,t){return Zo.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=Ku,n}function $u(n,t){for(var e=[n];null!=(n=e.pop());)if(t(n),(u=n.children)&&(r=u.length))for(var r,u;--r>=0;)e.push(u[r])}function Bu(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,o=-1;++o<u;)e.push(i[o]);for(;null!=(n=r.pop());)t(n)}function Wu(n){return n.children}function Ju(n){return n.value}function Gu(n,t){return t.value-n.value}function Ku(n){return Zo.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function Qu(n){return n.x}function ni(n){return n.y}function ti(n,t,e){n.y0=t,n.y=e}function ei(n){return Zo.range(n.length)}function ri(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function ui(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ii(n){return n.reduce(oi,0)}function oi(n,t){return n+t[1]}function ai(n,t){return ci(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ci(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function si(n){return[Zo.min(n),Zo.max(n)]}function li(n,t){return n.value-t.value}function fi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function hi(n,t){n._pack_next=t,t._pack_prev=n}function gi(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function pi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(vi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],yi(r,u,i),t(i),fi(r,i),r._pack_prev=i,fi(i,u),u=r._pack_next,o=3;s>o;o++){yi(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(gi(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!gi(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.r<r.r?hi(r,u=a):hi(r=c,u),o--):(fi(r,i),u=i,t(i))}var m=(l+f)/2,y=(h+g)/2,x=0;for(o=0;s>o;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(di)}}function vi(n){n._pack_next=n._pack_prev=n}function di(n){delete n._pack_next,delete n._pack_prev}function mi(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i<o;)mi(u[i],t,e,r)}function yi(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),s=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+s*i,e.y=n.y+c*i-s*u}else e.x=n.x+r,e.y=n.y}function xi(n,t){return n.parent==t.parent?1:2}function Mi(n){var t=n.children;return t.length?t[0]:n.t}function _i(n){var t,e=n.children;return(t=e.length)?e[t-1]:n.t}function bi(n,t,e){var r=e/(t.i-n.i);t.c-=r,t.s+=e,n.c+=r,t.z+=e,t.m+=e}function wi(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Si(n,t,e){return n.a.parent===t.parent?n.a:e}function ki(n){return 1+Zo.max(n,function(n){return n.y})}function Ei(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Ai(n){var t=n.children;return t&&t.length?Ai(t[0]):n}function Ci(n){var t,e=n.children;return e&&(t=e.length)?Ci(e[t-1]):n}function Ni(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function zi(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Li(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ti(n){return n.rangeExtent?n.rangeExtent():Li(n.range())}function qi(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Ri(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Di(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ss}function Pi(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=Zo.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Ui(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?Pi:qi,c=r?Uu:Pu;return o=u(n,t,c,e),a=u(t,n,c,hu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(zu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Oi(n,t)},i.tickFormat=function(t,e){return Yi(n,t,e)},i.nice=function(t){return Hi(n,t),u()},i.copy=function(){return Ui(n,t,e,r)},u()}function ji(n,t){return Zo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Hi(n,t){return Ri(n,Di(Fi(n,t)[2]))}function Fi(n,t){null==t&&(t=10);var e=Li(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Oi(n,t){return Zo.range.apply(Zo,Fi(n,t))}function Yi(n,t,e){var r=Fi(n,t);if(e){var u=Ga.exec(e);if(u.shift(),"s"===u[8]){var i=Zo.formatPrefix(Math.max(ua(r[0]),ua(r[1])));return u[7]||(u[7]="."+Ii(i.scale(r[2]))),u[8]="f",e=Zo.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+Zi(u[8],r)),e=u.join("")}else e=",."+Ii(r[2])+"f";return Zo.format(e)}function Ii(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Zi(n,t){var e=Ii(t[2]);return n in ls?Math.abs(e-Ii(Math.max(ua(t[0]),ua(t[1]))))+ +("e"!==n):e-2*("%"===n)}function Vi(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Ri(r.map(u),e?Math:hs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Li(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++<l;)for(var h=f-1;h>0;h--)o.push(i(s)*h);for(s=0;o[s]<a;s++);for(l=o.length;o[l-1]>c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return fs;arguments.length<2?t=fs:"function"!=typeof t&&(t=Zo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return Vi(n.copy(),t,e,r)},ji(o,n)}function Xi(n,t,e){function r(t){return n(u(t))}var u=$i(t),i=$i(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Oi(e,n)},r.tickFormat=function(n,t){return Yi(e,n,t)},r.nice=function(n){return r.domain(Hi(e,n))},r.exponent=function(o){return arguments.length?(u=$i(t=o),i=$i(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Xi(n.copy(),t,e)},ji(r,n)}function $i(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Bi(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):0/0))-1)%i.length]}function r(t,e){return Zo.range(n.length).map(function(n){return t+e*n})}var u,i,a;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new o;for(var i,a=-1,c=r.length;++a<c;)u.has(i=r[a])||u.set(i,n.push(i));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(i=n,a=0,t={t:"range",a:arguments},e):i},e.rangePoints=function(u,o){arguments.length<2&&(o=0);var c=u[0],s=u[1],l=(s-c)/(Math.max(1,n.length-1)+o);return i=r(n.length<2?(c+s)/2:c+l*o/2,l),a=0,t={t:"rangePoints",a:arguments},e},e.rangeBands=function(u,o,c){arguments.length<2&&(o=0),arguments.length<3&&(c=o);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=(f-l)/(n.length-o+2*c);return i=r(l+h*c,h),s&&i.reverse(),a=h*(1-o),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,o,c){arguments.length<2&&(o=0),arguments.length<3&&(c=o);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=Math.floor((f-l)/(n.length-o+2*c)),g=f-l-(n.length-o)*h;return i=r(l+Math.round(g/2),h),s&&i.reverse(),a=Math.round(h*(1-o)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return a},e.rangeExtent=function(){return Li(t.a[0])},e.copy=function(){return Bi(n,t)},e.domain(n)}function Wi(e,r){function u(){var n=0,t=r.length;for(o=[];++n<t;)o[n-1]=Zo.quantile(e,n/t);return i}function i(n){return isNaN(n=+n)?void 0:r[Zo.bisect(o,n)]}var o;return i.domain=function(r){return arguments.length?(e=r.filter(t).sort(n),u()):e},i.range=function(n){return arguments.length?(r=n,u()):r},i.quantiles=function(){return o},i.invertExtent=function(n){return n=r.indexOf(n),0>n?[0/0,0/0]:[n>0?o[n-1]:e[0],n<o.length?o[n]:e[e.length-1]]},i.copy=function(){return Wi(e,r)},u()}function Ji(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ji(n,t,e)},u()}function Gi(n,t){function e(e){return e>=e?t[Zo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Gi(n,t)},e}function Ki(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Oi(n,t)},t.tickFormat=function(t,e){return Yi(n,t,e)},t.copy=function(){return Ki(n)},t}function Qi(n){return n.innerRadius}function no(n){return n.outerRadius}function to(n){return n.startAngle}function eo(n){return n.endAngle}function ro(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=bt(e),p=bt(r);++f<h;)u.call(this,c=t[f],f)?l.push([+g.call(this,c,f),+p.call(this,c,f)]):l.length&&(o(),l=[]);return l.length&&o(),s.length?s.join(""):null}var e=wr,r=Sr,u=we,i=uo,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?i=n:(i=xs.get(n)||uo).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function uo(n){return n.join("L")}function io(n){return uo(n)+"Z"}function oo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&u.push("H",r[0]),u.join("")}function ao(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("V",(r=n[t])[1],"H",r[0]);return u.join("")}function co(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r=n[t])[0],"V",r[1]);return u.join("")}function so(n,t){return n.length<4?uo(n):n[1]+ho(n.slice(1,n.length-1),go(n,t))}function lo(n,t){return n.length<3?uo(n):n[0]+ho((n.push(n[0]),n),go([n[n.length-2]].concat(n,[n[1]]),t))}function fo(n,t){return n.length<3?uo(n):n[0]+ho(n,go(n,t))}function ho(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return uo(n);var e=n.length!=t.length,r="",u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&&(r+="Q"+(i[0]-2*o[0]/3)+","+(i[1]-2*o[1]/3)+","+i[0]+","+i[1],u=n[1],c=2),t.length>1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s<t.length;s++,c++)i=n[c],a=t[s],r+="S"+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1]}if(e){var l=n[c];r+="Q"+(i[0]+2*a[0]/3)+","+(i[1]+2*a[1]/3)+","+l[0]+","+l[1]}return r}function go(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a<c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function po(n){if(n.length<3)return uo(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,",",i,"L",xo(bs,o),",",xo(bs,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),Mo(c,o,a);return n.pop(),c.push("L",r),c.join("")}function vo(n){if(n.length<4)return uo(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r<3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(xo(bs,i)+","+xo(bs,o)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),Mo(e,i,o);return e.join("")}function mo(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r<4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[xo(bs,o),",",xo(bs,a)],--r;++r<i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),Mo(t,o,a);return t.join("")}function yo(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,s=-1;++s<=e;)r=n[s],u=s/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return po(n)}function xo(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function Mo(n,t,e){n.push("C",xo(Ms,t),",",xo(Ms,e),",",xo(_s,t),",",xo(_s,e),",",xo(bs,t),",",xo(bs,e))}function _o(n,t){return(t[1]-n[1])/(t[0]-n[0])}function bo(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=_o(u,i);++t<e;)r[t]=(o+(o=_o(u=i,i=n[t+1])))/2;return r[t]=o,r}function wo(n){for(var t,e,r,u,i=[],o=bo(n),a=-1,c=n.length-1;++a<c;)t=_o(n[a],n[a+1]),ua(t)<ka?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function So(n){return n.length<3?uo(n):n[0]+ho(n,wo(n))}function ko(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]+ms,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Eo(n){function t(t){function c(){v.push("M",a(n(m),f),l,s(n(d.reverse()),f),"Z")}for(var h,g,p,v=[],d=[],m=[],y=-1,x=t.length,M=bt(e),_=bt(u),b=e===r?function(){return g}:bt(r),w=u===i?function(){return p}:bt(i);++y<x;)o.call(this,h=t[y],y)?(d.push([g=+M.call(this,h,y),p=+_.call(this,h,y)]),m.push([+b.call(this,h,y),+w.call(this,h,y)])):d.length&&(c(),d=[],m=[]);return d.length&&c(),v.length?v.join(""):null}var e=wr,r=wr,u=0,i=Sr,o=we,a=uo,c=a.key,s=a,l="L",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?a=n:(a=xs.get(n)||uo).key,s=a.reverse||a,l=a.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function Ao(n){return n.radius}function Co(n){return[n.x,n.y]}function No(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+ms;return[e*Math.cos(r),e*Math.sin(r)]}}function zo(){return 64}function Lo(){return"circle"}function To(n){var t=Math.sqrt(n/ba);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function qo(n,t){return sa(n,Cs),n.id=t,n}function Ro(n,t,e,r){var u=n.id;return P(n,"function"==typeof e?function(n,i,o){n.__transition__[u].tween.set(t,r(e.call(n,n.__data__,i,o)))}:(e=r(e),function(n){n.__transition__[u].tween.set(t,e)}))}function Do(n){return null==n&&(n=""),function(){this.textContent=n}}function Po(n,t,e,r){var u=n.__transition__||(n.__transition__={active:0,count:0}),i=u[e];if(!i){var a=r.time;i=u[e]={tween:new o,time:a,ease:r.ease,delay:r.delay,duration:r.duration},++u.count,Zo.timer(function(r){function o(r){return u.active>e?s():(u.active=e,i.event&&i.event.start.call(n,l,t),i.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Zo.timer(function(){return p.c=c(r||1)?we:c,1},0,a),void 0)}function c(r){if(u.active!==e)return s();for(var o=r/g,a=f(o),c=v.length;c>0;)v[--c].call(n,a); +return o>=1?(i.event&&i.event.end.call(n,l,t),s()):void 0}function s(){return--u.count?delete u[e]:delete n.__transition__,1}var l=n.__data__,f=i.ease,h=i.delay,g=i.duration,p=Ba,v=[];return p.t=h+a,r>=h?o(r-h):(p.c=o,void 0)},0,a)}}function Uo(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function jo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Ho(n){return n.toISOString()}function Fo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Zo.bisect(Us,u);return i==Us.length?[t.year,Fi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Us[i-1]<Us[i]/u?i-1:i]:[Fs,Fi(n,e)[2]]}return r.invert=function(t){return Oo(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Oo)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,Oo(+e+1),t).length}var i=r.domain(),o=Li(i),a=null==n?u(o,10):"number"==typeof n&&u(o,n);return a&&(n=a[0],t=a[1]),r.domain(Ri(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=Oo(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Oo(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Li(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Oo(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Fo(n.copy(),t,e)},ji(r,n)}function Oo(n){return new Date(n)}function Yo(n){return JSON.parse(n.responseText)}function Io(n){var t=$o.createRange();return t.selectNode($o.body),t.createContextualFragment(n.responseText)}var Zo={version:"3.4.11"};Date.now||(Date.now=function(){return+new Date});var Vo=[].slice,Xo=function(n){return Vo.call(n)},$o=document,Bo=$o.documentElement,Wo=window;try{Xo(Bo.childNodes)[0].nodeType}catch(Jo){Xo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{$o.createElement("div").style.setProperty("opacity",0,"")}catch(Go){var Ko=Wo.Element.prototype,Qo=Ko.setAttribute,na=Ko.setAttributeNS,ta=Wo.CSSStyleDeclaration.prototype,ea=ta.setProperty;Ko.setAttribute=function(n,t){Qo.call(this,n,t+"")},Ko.setAttributeNS=function(n,t,e){na.call(this,n,t,e+"")},ta.setProperty=function(n,t,e){ea.call(this,n,t+"",e)}}Zo.ascending=n,Zo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Zo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},Zo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},Zo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i<o&&!(null!=(e=u=n[i])&&e>=e);)e=u=void 0;for(;++i<o;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<o&&!(null!=(e=u=t.call(n,n[i],i))&&e>=e);)e=void 0;for(;++i<o;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},Zo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i<u;)isNaN(e=+n[i])||(r+=e);else for(;++i<u;)isNaN(e=+t.call(n,n[i],i))||(r+=e);return r},Zo.mean=function(n,e){var r,u=0,i=n.length,o=-1,a=i;if(1===arguments.length)for(;++o<i;)t(r=n[o])?u+=r:--a;else for(;++o<i;)t(r=e.call(n,n[o],o))?u+=r:--a;return a?u/a:void 0},Zo.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},Zo.median=function(e,r){return arguments.length>1&&(e=e.map(r)),e=e.filter(t),e.length?Zo.quantile(e.sort(n),.5):void 0};var ra=e(n);Zo.bisectLeft=ra.left,Zo.bisect=Zo.bisectRight=ra.right,Zo.bisector=function(t){return e(1===t.length?function(e,r){return n(t(e),r)}:t)},Zo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},Zo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},Zo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Zo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,t=Zo.min(arguments,r),e=new Array(t);++n<t;)for(var u,i=-1,o=e[n]=new Array(u);++i<u;)o[i]=arguments[i][n];return e},Zo.transpose=function(n){return Zo.zip.apply(Zo,n)},Zo.keys=function(n){var t=[];for(var e in n)t.push(e);return t},Zo.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},Zo.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},Zo.merge=function(n){for(var t,e,r,u=n.length,i=-1,o=0;++i<u;)o+=n[i].length;for(e=new Array(o);--u>=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var ua=Math.abs;Zo.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/e)throw new Error("infinite range");var r,i=[],o=u(ua(e)),a=-1;if(n*=o,t*=o,e*=o,0>e)for(;(r=n+e*++a)>t;)i.push(r/o);else for(;(r=n+e*++a)<t;)i.push(r/o);return i},Zo.map=function(n){var t=new o;if(n instanceof o)n.forEach(function(n,e){t.set(n,e)});else for(var e in n)t.set(e,n[e]);return t},i(o,{has:a,get:function(n){return this[ia+n]},set:function(n,t){return this[ia+n]=t},remove:c,keys:s,values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},size:l,empty:f,forEach:function(n){for(var t in this)t.charCodeAt(0)===oa&&n.call(this,t.substring(1),this[t])}});var ia="\x00",oa=ia.charCodeAt(0);Zo.nest=function(){function n(t,a,c){if(c>=i.length)return r?r.call(u,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=i[c++],d=new o;++g<p;)(h=d.get(s=v(l=a[g])))?h.push(l):d.set(s,[l]);return t?(l=t(),f=function(e,r){l.set(e,n(t,r,c))}):(l={},f=function(e,r){l[e]=n(t,r,c)}),d.forEach(f),l}function t(n,e){if(e>=i.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],a=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(Zo.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return a[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},Zo.set=function(n){var t=new h;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},i(h,{has:a,add:function(n){return this[ia+n]=!0,n},remove:function(n){return n=ia+n,n in this&&delete this[n]},values:s,size:l,empty:f,forEach:function(n){for(var t in this)t.charCodeAt(0)===oa&&n.call(this,t.substring(1))}}),Zo.behavior={},Zo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=g(n,t,t[e]);return n};var aa=["webkit","ms","moz","Moz","o","O"];Zo.dispatch=function(){for(var n=new d,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=m(n);return n},d.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Zo.event=null,Zo.requote=function(n){return n.replace(ca,"\\$&")};var ca=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,sa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},la=function(n,t){return t.querySelector(n)},fa=function(n,t){return t.querySelectorAll(n)},ha=Bo.matches||Bo[p(Bo,"matchesSelector")],ga=function(n,t){return ha.call(n,t)};"function"==typeof Sizzle&&(la=function(n,t){return Sizzle(n,t)[0]||null},fa=Sizzle,ga=Sizzle.matchesSelector),Zo.selection=function(){return ma};var pa=Zo.selection.prototype=[];pa.select=function(n){var t,e,r,u,i=[];n=b(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,s=r.length;++c<s;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return _(i)},pa.selectAll=function(n){var t,e,r=[];n=w(n);for(var u=-1,i=this.length;++u<i;)for(var o=this[u],a=-1,c=o.length;++a<c;)(e=o[a])&&(r.push(t=Xo(n.call(e,e.__data__,a,u))),t.parentNode=e);return _(r)};var va={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};Zo.ns={prefix:va,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),va.hasOwnProperty(e)?{space:va[e],local:n}:n}},pa.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Zo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(S(t,n[t]));return this}return this.each(S(n,t))},pa.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=A(n)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!E(n[u]).test(t))return!1;return!0}for(t in n)this.each(C(t,n[t]));return this}return this.each(C(n,t))},pa.style=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(z(e,n[e],t));return this}if(2>r)return Wo.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(z(n,t,e))},pa.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(L(t,n[t]));return this}return this.each(L(n,t))},pa.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},pa.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},pa.append=function(n){return n=T(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},pa.insert=function(n,t){return n=T(n),t=b(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},pa.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},pa.data=function(n,t){function e(n,e){var r,u,i,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new o,y=new o,x=[];for(r=-1;++r<a;)d=t.call(u=n[r],u.__data__,r),m.has(d)?v[r]=u:m.set(d,u),x.push(d);for(r=-1;++r<f;)d=t.call(e,i=e[r],r),(u=m.get(d))?(g[r]=u,u.__data__=i):y.has(d)||(p[r]=q(i)),y.set(d,i),m.remove(d);for(r=-1;++r<a;)m.has(x[r])&&(v[r]=n[r])}else{for(r=-1;++r<h;)u=n[r],i=e[r],u?(u.__data__=i,g[r]=u):p[r]=q(i);for(;f>r;++r)p[r]=q(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,u,i=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++i<a;)(u=r[i])&&(n[i]=u.__data__);return n}var c=U([]),s=_([]),l=_([]);if("function"==typeof n)for(;++i<a;)e(r=this[i],n.call(r,r.parentNode.__data__,i));else for(;++i<a;)e(r=this[i],n);return s.enter=function(){return c},s.exit=function(){return l},s},pa.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},pa.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=R(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return _(u)},pa.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},pa.sort=function(n){n=D.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},pa.each=function(n){return P(this,function(t,e,r){n.call(t,t.__data__,e,r)})},pa.call=function(n){var t=Xo(arguments);return n.apply(t[0]=this,t),this},pa.empty=function(){return!this.node()},pa.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},pa.size=function(){var n=0;return this.each(function(){++n}),n};var da=[];Zo.selection.enter=U,Zo.selection.enter.prototype=da,da.append=pa.append,da.empty=pa.empty,da.node=pa.node,da.call=pa.call,da.size=pa.size,da.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a<c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var s=-1,l=u.length;++s<l;)(i=u[s])?(t.push(r[s]=e=n.call(u.parentNode,i.__data__,s,a)),e.__data__=i.__data__):t.push(null)}return _(o)},da.insert=function(n,t){return arguments.length<2&&(t=j(this)),pa.insert.call(this,n,t)},pa.transition=function(){for(var n,t,e=Ss||++Ns,r=[],u=ks||{time:Date.now(),ease:xu,delay:0,duration:250},i=-1,o=this.length;++i<o;){r.push(n=[]);for(var a=this[i],c=-1,s=a.length;++c<s;)(t=a[c])&&Po(t,c,e,u),n.push(t)}return qo(r,e)},pa.interrupt=function(){return this.each(H)},Zo.select=function(n){var t=["string"==typeof n?la(n,$o):n];return t.parentNode=Bo,_([t])},Zo.selectAll=function(n){var t=Xo("string"==typeof n?fa(n,$o):n);return t.parentNode=Bo,_([t])};var ma=Zo.select(Bo);pa.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(F(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(F(n,t,e))};var ya=Zo.map({mouseenter:"mouseover",mouseleave:"mouseout"});ya.forEach(function(n){"on"+n in $o&&ya.remove(n)});var xa="onselectstart"in $o?null:p(Bo.style,"userSelect"),Ma=0;Zo.mouse=function(n){return Z(n,x())};var _a=/WebKit/.test(Wo.navigator.userAgent)?-1:0;Zo.touches=function(n,t){return arguments.length<2&&(t=x().touches),t?Xo(t).map(function(t){var e=Z(n,t);return e.identifier=t.identifier,e}):[]},Zo.behavior.drag=function(){function n(){this.on("mousedown.drag",u).on("touchstart.drag",i)}function t(n,t,u,i,o){return function(){function a(){var n,e,r=t(h,v);r&&(n=r[0]-x[0],e=r[1]-x[1],p|=n|e,x=r,g({type:"drag",x:r[0]+s[0],y:r[1]+s[1],dx:n,dy:e}))}function c(){t(h,v)&&(m.on(i+d,null).on(o+d,null),y(p&&Zo.event.target===f),g({type:"dragend"}))}var s,l=this,f=Zo.event.target,h=l.parentNode,g=e.of(l,arguments),p=0,v=n(),d=".drag"+(null==v?"":"-"+v),m=Zo.select(u()).on(i+d,a).on(o+d,c),y=I(),x=t(h,v);r?(s=r.apply(l,arguments),s=[s.x-x[0],s.y-x[1]]):s=[0,0],g({type:"dragstart"})}}var e=M(n,"drag","dragstart","dragend"),r=null,u=t(v,Zo.mouse,$,"mousemove","mouseup"),i=t(V,Zo.touch,X,"touchmove","touchend");return n.origin=function(t){return arguments.length?(r=t,n):r},Zo.rebind(n,e,"on")};var ba=Math.PI,wa=2*ba,Sa=ba/2,ka=1e-6,Ea=ka*ka,Aa=ba/180,Ca=180/ba,Na=Math.SQRT2,za=2,La=4;Zo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=Q(v),o=i/(za*h)*(e*nt(Na*t+v)-K(v));return[r+o*s,u+o*l,i*e/Q(Na*t+v)]}return[r+n*s,u+n*l,i*Math.exp(Na*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+La*f)/(2*i*za*h),p=(c*c-i*i-La*f)/(2*c*za*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Na;return e.duration=1e3*y,e},Zo.behavior.zoom=function(){function n(n){n.on(A,s).on(Ra+".zoom",f).on("dblclick.zoom",h).on(z,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(x.range().map(function(n){return(n-S.x)/S.k}).map(x.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Zo.mouse(r),h),a(s)}function e(){f.on(C,null).on(N,null),g(l&&Zo.event.target===i),c(s)}var r=this,i=Zo.event.target,s=L.of(r,arguments),l=0,f=Zo.select(Wo).on(C,n).on(N,e),h=t(Zo.mouse(r)),g=I();H.call(r),o(s)}function l(){function n(){var n=Zo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){var t=Zo.event.target;Zo.select(t).on(M,i).on(_,f),b.push(t);for(var e=Zo.event.changedTouches,o=0,c=e.length;c>o;++o)v[e[o].identifier]=null;var s=n(),l=Date.now();if(1===s.length){if(500>l-m){var h=s[0],g=v[h.identifier];r(2*S.k),u(h,g),y(),a(p)}m=l}else if(s.length>1){var h=s[0],x=s[1],w=h[0]-x[0],k=h[1]-x[1];d=w*w+k*k}}function i(){for(var n,t,e,i,o=Zo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=d&&Math.sqrt(l/d);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}m=null,u(n,t),a(p)}function f(){if(Zo.event.touches.length){for(var t=Zo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}Zo.selectAll(b).on(x,null),w.on(A,s).on(z,l),k(),c(p)}var h,g=this,p=L.of(g,arguments),v={},d=0,x=".zoom-"+Zo.event.changedTouches[0].identifier,M="touchmove"+x,_="touchend"+x,b=[],w=Zo.select(g).on(A,null).on(z,e),k=I();H.call(g),e(),o(p)}function f(){var n=L.of(this,arguments);d?clearTimeout(d):(g=t(p=v||Zo.mouse(this)),H.call(this),o(n)),d=setTimeout(function(){d=null,c(n)},50),y(),r(Math.pow(2,.002*Ta())*S.k),u(p,g),a(n)}function h(){var n=L.of(this,arguments),e=Zo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Zo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var g,p,v,d,m,x,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=qa,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",z="touchstart.zoom",L=M(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=L.of(this,arguments),t=S;Ss?Zo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Zo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?qa:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,x=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Zo.rebind(n,L,"on")};var Ta,qa=[0,1/0],Ra="onwheel"in $o?(Ta=function(){return-Zo.event.deltaY*(Zo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in $o?(Ta=function(){return Zo.event.wheelDelta},"mousewheel"):(Ta=function(){return-Zo.event.detail},"MozMousePixelScroll");Zo.color=et,et.prototype.toString=function(){return this.rgb()+""},Zo.hsl=rt;var Da=rt.prototype=new et;Da.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new rt(this.h,this.s,this.l/n)},Da.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new rt(this.h,this.s,n*this.l)},Da.rgb=function(){return ut(this.h,this.s,this.l)},Zo.hcl=it;var Pa=it.prototype=new et;Pa.brighter=function(n){return new it(this.h,this.c,Math.min(100,this.l+Ua*(arguments.length?n:1)))},Pa.darker=function(n){return new it(this.h,this.c,Math.max(0,this.l-Ua*(arguments.length?n:1)))},Pa.rgb=function(){return ot(this.h,this.c,this.l).rgb()},Zo.lab=at;var Ua=18,ja=.95047,Ha=1,Fa=1.08883,Oa=at.prototype=new et;Oa.brighter=function(n){return new at(Math.min(100,this.l+Ua*(arguments.length?n:1)),this.a,this.b)},Oa.darker=function(n){return new at(Math.max(0,this.l-Ua*(arguments.length?n:1)),this.a,this.b)},Oa.rgb=function(){return ct(this.l,this.a,this.b)},Zo.rgb=gt;var Ya=gt.prototype=new et;Ya.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),new gt(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new gt(u,u,u)},Ya.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new gt(n*this.r,n*this.g,n*this.b)},Ya.hsl=function(){return yt(this.r,this.g,this.b)},Ya.toString=function(){return"#"+dt(this.r)+dt(this.g)+dt(this.b)};var Ia=Zo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Ia.forEach(function(n,t){Ia.set(n,pt(t))}),Zo.functor=bt,Zo.xhr=St(wt),Zo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=kt(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++<s;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}l=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++l):10===r&&(u=!0),n.substring(t+1,e).replace(/""/g,'"')}for(;s>l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new h,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Zo.csv=Zo.dsv(",","text/csv"),Zo.tsv=Zo.dsv(" ","text/tab-separated-values"),Zo.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=x().changedTouches),t)for(var r,u=0,i=t.length;i>u;++u)if((r=t[u]).identifier===e)return Z(n,r)};var Za,Va,Xa,$a,Ba,Wa=Wo[p(Wo,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Zo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};Va?Va.n=i:Za=i,Va=i,Xa||($a=clearTimeout($a),Xa=1,Wa(At))},Zo.timer.flush=function(){Ct(),Nt()},Zo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ja=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Zo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Zo.round(n,zt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),Ja[8+e/3]};var Ga=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,Ka=Zo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Zo.round(n,zt(n,t))).toFixed(Math.max(0,Math.min(20,zt(n*(1+1e-15),t))))}}),Qa=Zo.time={},nc=Date;Rt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){tc.setUTCDate.apply(this._,arguments)},setDay:function(){tc.setUTCDay.apply(this._,arguments)},setFullYear:function(){tc.setUTCFullYear.apply(this._,arguments)},setHours:function(){tc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){tc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){tc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){tc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){tc.setUTCSeconds.apply(this._,arguments)},setTime:function(){tc.setTime.apply(this._,arguments)}};var tc=Date.prototype;Qa.year=Dt(function(n){return n=Qa.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),Qa.years=Qa.year.range,Qa.years.utc=Qa.year.utc.range,Qa.day=Dt(function(n){var t=new nc(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),Qa.days=Qa.day.range,Qa.days.utc=Qa.day.utc.range,Qa.dayOfYear=function(n){var t=Qa.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=Qa[n]=Dt(function(n){return(n=Qa.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=Qa.year(n).getDay();return Math.floor((Qa.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});Qa[n+"s"]=e.range,Qa[n+"s"].utc=e.utc.range,Qa[n+"OfYear"]=function(n){var e=Qa.year(n).getDay();return Math.floor((Qa.dayOfYear(n)+(e+t)%7)/7)}}),Qa.week=Qa.sunday,Qa.weeks=Qa.sunday.range,Qa.weeks.utc=Qa.sunday.utc.range,Qa.weekOfYear=Qa.sundayOfYear;var ec={"-":"",_:" ",0:"0"},rc=/^\s*\d+/,uc=/^%/;Zo.locale=function(n){return{numberFormat:Tt(n),timeFormat:Ut(n)}};var ic=Zo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],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"]});Zo.format=ic.numberFormat,Zo.geo={},ue.prototype={s:0,t:0,add:function(n){ie(n,this.t,oc),ie(oc.s,this.s,this),this.s?this.t+=oc.t:this.s=oc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var oc=new ue;Zo.geo.stream=function(n,t){n&&ac.hasOwnProperty(n.type)?ac[n.type](n,t):oe(n,t)};var ac={Feature:function(n,t){oe(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)oe(e[r].geometry,t)}},cc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){ae(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)ae(e[r],t,0)},Polygon:function(n,t){ce(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)ce(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)oe(e[r],t)}};Zo.geo.area=function(n){return sc=0,Zo.geo.stream(n,fc),sc};var sc,lc=new ue,fc={sphere:function(){sc+=4*ba},point:v,lineStart:v,lineEnd:v,polygonStart:function(){lc.reset(),fc.lineStart=se},polygonEnd:function(){var n=2*lc;sc+=0>n?4*ba+n:n,fc.lineStart=fc.lineEnd=fc.point=v}};Zo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=le([t*Aa,e*Aa]);if(m){var u=he(m,r),i=[u[1],-u[0],0],o=he(i,u);ve(o),o=de(o);var c=t-p,s=c>0?1:-1,v=o[0]*Ca*s,d=ua(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*Ca;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*Ca;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=ua(r)>180?r+(r>0?360:-360):r}else v=n,d=e;fc.point(n,e),t(n,e)}function i(){fc.lineStart()}function o(){u(v,d),fc.lineEnd(),ua(y)>ka&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var l,f,h,g,p,v,d,m,y,x,M,_={point:n,lineStart:e,lineEnd:r,polygonStart:function(){_.point=u,_.lineStart=i,_.lineEnd=o,y=0,fc.polygonStart()},polygonEnd:function(){fc.polygonEnd(),_.point=n,_.lineStart=e,_.lineEnd=r,0>lc?(l=-(h=180),f=-(g=90)):y>ka?g=90:-ka>y&&(f=-90),M[0]=l,M[1]=h}};return function(n){g=h=-(l=f=1/0),x=[],Zo.geo.stream(n,_);var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e); +for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Zo.geo.centroid=function(n){hc=gc=pc=vc=dc=mc=yc=xc=Mc=_c=bc=0,Zo.geo.stream(n,wc);var t=Mc,e=_c,r=bc,u=t*t+e*e+r*r;return Ea>u&&(t=mc,e=yc,r=xc,ka>gc&&(t=pc,e=vc,r=dc),u=t*t+e*e+r*r,Ea>u)?[0/0,0/0]:[Math.atan2(e,t)*Ca,G(r/Math.sqrt(u))*Ca]};var hc,gc,pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc={sphere:v,point:ye,lineStart:Me,lineEnd:_e,polygonStart:function(){wc.lineStart=be},polygonEnd:function(){wc.lineStart=Me}},Sc=Ae(we,Te,Re,[-ba,-ba/2]),kc=1e9;Zo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Ue(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Zo.geo.conicEqualArea=function(){return He(Fe)}).raw=Fe,Zo.geo.albers=function(){return Zo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Zo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Zo.geo.albers(),o=Zo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Zo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+ka,f+.12*s+ka],[l-.214*s-ka,f+.234*s-ka]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+ka,f+.166*s+ka],[l-.115*s-ka,f+.234*s-ka]]).stream(c).point,n},n.scale(1070)};var Ec,Ac,Cc,Nc,zc,Lc,Tc={point:v,lineStart:v,lineEnd:v,polygonStart:function(){Ac=0,Tc.lineStart=Oe},polygonEnd:function(){Tc.lineStart=Tc.lineEnd=Tc.point=v,Ec+=ua(Ac/2)}},qc={point:Ye,lineStart:v,lineEnd:v,polygonStart:v,polygonEnd:v},Rc={point:Ve,lineStart:Xe,lineEnd:$e,polygonStart:function(){Rc.lineStart=Be},polygonEnd:function(){Rc.point=Ve,Rc.lineStart=Xe,Rc.lineEnd=$e}};Zo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Zo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Ec=0,Zo.geo.stream(n,u(Tc)),Ec},n.centroid=function(n){return pc=vc=dc=mc=yc=xc=Mc=_c=bc=0,Zo.geo.stream(n,u(Rc)),bc?[Mc/bc,_c/bc]:xc?[mc/xc,yc/xc]:dc?[pc/dc,vc/dc]:[0/0,0/0]},n.bounds=function(n){return zc=Lc=-(Cc=Nc=1/0),Zo.geo.stream(n,u(qc)),[[Cc,Nc],[zc,Lc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Ge(n):wt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ie:new We(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Zo.geo.albersUsa()).context(null)},Zo.geo.transform=function(n){return{stream:function(t){var e=new Ke(t);for(var r in n)e[r]=n[r];return e}}},Ke.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Zo.geo.projection=nr,Zo.geo.projectionMutator=tr,(Zo.geo.equirectangular=function(){return nr(rr)}).raw=rr.invert=rr,Zo.geo.rotation=function(n){function t(t){return t=n(t[0]*Aa,t[1]*Aa),t[0]*=Ca,t[1]*=Ca,t}return n=ir(n[0]%360*Aa,n[1]*Aa,n.length>2?n[2]*Aa:0),t.invert=function(t){return t=n.invert(t[0]*Aa,t[1]*Aa),t[0]*=Ca,t[1]*=Ca,t},t},ur.invert=rr,Zo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ir(-n[0]*Aa,-n[1]*Aa,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Ca,n[1]*=Ca}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=sr((t=+r)*Aa,u*Aa),n):t},n.precision=function(r){return arguments.length?(e=sr(t*Aa,(u=+r)*Aa),n):u},n.angle(90)},Zo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Aa,u=n[1]*Aa,i=t[1]*Aa,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Zo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Zo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Zo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Zo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return ua(n%d)>ka}).map(l)).concat(Zo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return ua(n%m)>ka}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=fr(a,o,90),f=hr(r,e,y),h=fr(s,c,90),g=hr(i,u,y),n):y},n.majorExtent([[-180,-90+ka],[180,90-ka]]).minorExtent([[-180,-80-ka],[180,80+ka]])},Zo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=gr,u=pr;return n.distance=function(){return Zo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Zo.geo.interpolate=function(n,t){return vr(n[0]*Aa,n[1]*Aa,t[0]*Aa,t[1]*Aa)},Zo.geo.length=function(n){return Dc=0,Zo.geo.stream(n,Pc),Dc};var Dc,Pc={sphere:v,point:v,lineStart:dr,lineEnd:v,polygonStart:v,polygonEnd:v},Uc=mr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Zo.geo.azimuthalEqualArea=function(){return nr(Uc)}).raw=Uc;var jc=mr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},wt);(Zo.geo.azimuthalEquidistant=function(){return nr(jc)}).raw=jc,(Zo.geo.conicConformal=function(){return He(yr)}).raw=yr,(Zo.geo.conicEquidistant=function(){return He(xr)}).raw=xr;var Hc=mr(function(n){return 1/n},Math.atan);(Zo.geo.gnomonic=function(){return nr(Hc)}).raw=Hc,Mr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Sa]},(Zo.geo.mercator=function(){return _r(Mr)}).raw=Mr;var Fc=mr(function(){return 1},Math.asin);(Zo.geo.orthographic=function(){return nr(Fc)}).raw=Fc;var Oc=mr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Zo.geo.stereographic=function(){return nr(Oc)}).raw=Oc,br.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Sa]},(Zo.geo.transverseMercator=function(){var n=_r(br),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=br,Zo.geom={},Zo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=bt(e),i=bt(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(Er),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=kr(a),l=kr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t<l.length-h;++t)g.push(n[a[l[t]][2]]);return g}var e=wr,r=Sr;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},Zo.geom.polygon=function(n){return sa(n,Yc),n};var Yc=Zo.geom.polygon.prototype=[];Yc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},Yc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},Yc.clip=function(n){for(var t,e,r,u,i,o,a=Nr(n),c=-1,s=this.length-Nr(this),l=this[s-1];++c<s;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],Ar(o,l,u)?(Ar(i,l,u)||n.push(Cr(i,o,l,u)),n.push(o)):Ar(i,l,u)&&n.push(Cr(i,o,l,u)),i=o;a&&n.push(n[0]),l=u}return n};var Ic,Zc,Vc,Xc,$c,Bc=[],Wc=[];Ur.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(Hr),t.length},Wr.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},Jr.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=nu(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(u=r.R,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&&(Kr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Qr(this,r))):(u=r.L,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&&(Qr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Kr(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,o=n.R;if(e=i?o?nu(o):i:o,u?u.L===n?u.L=e:u.R=e:this._=e,i&&o?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==o?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=o,o.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&&(n.U=u),!r){if(n&&n.C)return n.C=!1,void 0;do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&&(t.C=!1,u.C=!0,Kr(this,u),t=u.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,Qr(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,Kr(this,u),n=this._;break}}else if(t=u.L,t.C&&(t.C=!1,u.C=!0,Qr(this,u),t=u.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,Kr(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,Qr(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&&(n.C=!1)}}},Zo.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],u=a[0][1],i=a[1][0],o=a[1][1];return tu(e(n),a).cells.forEach(function(e,a){var c=e.edges,s=e.site,l=t[a]=c.length?c.map(function(n){var t=n.start();return[t.x,t.y]}):s.x>=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/ka)*ka,y:Math.round(o(n,t)/ka)*ka,i:t}})}var r=wr,u=Sr,i=r,o=u,a=Jc;return n?t(n):(t.links=function(n){return tu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return tu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(Hr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c<s;)u=l,i=f,l=a[c].edge,f=l.l===o?l.r:l.l,r<i.i&&r<f.i&&ru(o,i,f)<0&&t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=bt(r=n),t):r},t.y=function(n){return arguments.length?(o=bt(u=n),t):u},t.clipExtent=function(n){return arguments.length?(a=null==n?Jc:n,t):a===Jc?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===Jc?null:a&&a[1]},t)};var Jc=[[-1e6,-1e6],[1e6,1e6]];Zo.geom.delaunay=function(n){return Zo.geom.voronoi().triangles(n)},Zo.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,l=n.y;if(null!=c)if(ua(c-e)+ua(l-r)<.01)s(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,s(n,f,c,l,u,i,o,a),s(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else s(n,t,e,r,u,i,o,a)}function s(n,t,e,r,u,o,a,c){var s=.5*(u+a),l=.5*(o+c),f=e>=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=ou()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=bt(a),M=bt(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.x<v&&(v=l.x),l.y<d&&(d=l.y),l.x>m&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=ou();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){au(n,k,v,d,m,y)},g=-1,null==t){for(;++g<p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=l=null,k}var o,a=wr,c=Sr;return(o=arguments.length)?(a=uu,c=iu,3===o&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},Zo.interpolateRgb=cu,Zo.interpolateObject=su,Zo.interpolateNumber=lu,Zo.interpolateString=fu;var Gc=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Kc=new RegExp(Gc.source,"g");Zo.interpolate=hu,Zo.interpolators=[function(n,t){var e=typeof t;return("string"===e?Ia.has(t)||/^(#|rgb\(|hsl\()/.test(t)?cu:fu:t instanceof et?cu:Array.isArray(t)?gu:"object"===e&&isNaN(t)?su:lu)(n,t)}],Zo.interpolateArray=gu;var Qc=function(){return wt},ns=Zo.map({linear:Qc,poly:Mu,quad:function(){return mu},cubic:function(){return yu},sin:function(){return _u},exp:function(){return bu},circle:function(){return wu},elastic:Su,back:ku,bounce:function(){return Eu}}),ts=Zo.map({"in":wt,out:vu,"in-out":du,"out-in":function(n){return du(vu(n))}});Zo.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ns.get(e)||Qc,r=ts.get(r)||wt,pu(r(e.apply(null,Vo.call(arguments,1))))},Zo.interpolateHcl=Au,Zo.interpolateHsl=Cu,Zo.interpolateLab=Nu,Zo.interpolateRound=zu,Zo.transform=function(n){var t=$o.createElementNS(Zo.ns.prefix.svg,"g");return(Zo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:es)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var es={a:1,b:0,c:0,d:1,e:0,f:0};Zo.interpolateTransform=Du,Zo.layout={},Zo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(ju(n[e]));return t}},Zo.layout.chord=function(){function n(){var n,s,f,h,g,p={},v=[],d=Zo.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(s=0,g=-1;++g<i;)s+=u[h][g];v.push(s),m.push(Zo.range(i)),n+=s}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(wa-l*i)/n,s=0,h=-1;++h<i;){for(f=s,g=-1;++g<i;){var y=d[h],x=m[y][g],M=u[y][x],_=s,b=s+=M*n;p[y+"-"+x]={index:y,subindex:x,startAngle:_,endAngle:b,value:M}}r[y]={index:y,startAngle:f,endAngle:s,value:(s-f)/n},s+=l}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,s={},l=0;return s.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,s):u},s.padding=function(n){return arguments.length?(l=n,e=r=null,s):l},s.sortGroups=function(n){return arguments.length?(o=n,e=r=null,s):o},s.sortSubgroups=function(n){return arguments.length?(a=n,e=null,s):a},s.sortChords=function(n){return arguments.length?(c=n,e&&t(),s):c},s.chords=function(){return e||n(),e},s.groups=function(){return r||n(),r},s},Zo.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=u-e,c=i*i+o*o;if(c>a*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Zo.event.x,n.py=Zo.event.y,a.resume()}var e,r,u,i,o,a={},c=Zo.dispatch("start","tick","end"),s=[1,1],l=.9,f=rs,h=us,g=-30,p=is,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Vu(t=Zo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Zo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++a<s;)if(!isNaN(i=o[a][n]))return i;return Math.random()*r}var t,e,r,c=m.length,l=y.length,p=s[0],v=s[1];for(t=0;c>t;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Zo.behavior.drag().origin(wt).on("dragstart.force",Ou).on("drag.force",t).on("dragend.force",Yu)),arguments.length?(this.on("mouseover.force",Iu).on("mouseout.force",Zu).call(e),void 0):e},Zo.rebind(a,c,"on")};var rs=20,us=1,is=1/0;Zo.layout.hierarchy=function(){function n(u){var i,o=[u],a=[];for(u.depth=0;null!=(i=o.pop());)if(a.push(i),(s=e.call(n,i,i.depth))&&(c=s.length)){for(var c,s,l;--c>=0;)o.push(l=s[c]),l.parent=i,l.depth=i.depth+1;r&&(i.value=0),i.children=s}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return Bu(u,function(n){var e,u;t&&(e=n.children)&&e.sort(t),r&&(u=n.parent)&&(u.value+=n.value)}),a}var t=Gu,e=Wu,r=Ju;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&($u(t,function(n){n.children&&(n.value=0)}),Bu(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},Zo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,s=-1;for(r=t.value?r/t.value:0;++s<o;)n(a=i[s],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=Zo.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},Xu(e,r)},Zo.layout.pie=function(){function n(i){var o=i.map(function(e,r){return+t.call(n,e,r)}),a=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof u?u.apply(this,arguments):u)-a)/Zo.sum(o),s=Zo.range(i.length);null!=e&&s.sort(e===os?function(n,t){return o[t]-o[n]}:function(n,t){return e(i[n],i[t])});var l=[];return s.forEach(function(n){var t;l[n]={data:i[n],value:t=o[n],startAngle:a,endAngle:a+=t*c}}),l}var t=Number,e=os,r=0,u=wa;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n};var os={};Zo.layout.stack=function(){function n(a,c){var s=a.map(function(e,r){return t.call(n,e,r)}),l=s.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,l,c);s=Zo.permute(s,f),l=Zo.permute(l,f);var h,g,p,v=r.call(n,l,c),d=s.length,m=s[0].length;for(g=0;m>g;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=wt,e=ei,r=ri,u=ti,i=Qu,o=ni;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:as.get(t)||ei,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:cs.get(t)||ri,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var as=Zo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ui),i=n.map(ii),o=Zo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Zo.range(n.length).reverse()},"default":ei}),cs=Zo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ri});Zo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i<g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g>0)for(i=-1;++i<h;)a=s[i],a>=l[0]&&a<=l[1]&&(o=c[Zo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=si,u=ai;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=bt(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ci(n,t)}:bt(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Zo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,Bu(a,function(n){n.r=+l(n.value)}),Bu(a,pi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;Bu(a,function(n){n.r+=f}),Bu(a,pi),Bu(a,function(n){n.r-=f})}return mi(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Zo.layout.hierarchy().sort(li),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Xu(n,e)},Zo.layout.tree=function(){function n(n,u){var l=o.call(this,n,u),f=l[0],h=t(f);if(Bu(h,e),h.parent.m=-h.z,$u(h,r),s)$u(f,i);else{var g=f,p=f,v=f;$u(f,function(n){n.x<g.x&&(g=n),n.x>p.x&&(p=n),n.depth>v.depth&&(v=n)});var d=a(g,p)/2-g.x,m=c[0]/(p.x+a(p,g)/2+d),y=c[1]/(v.depth||1);$u(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return l}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,o=0,a=i.length;a>o;++o)r.push((i[o]=u={_:i[o],parent:t,children:(u=i[o].children)&&u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:o}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){wi(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+a(n._,r._),n.m=n.z-i):n.z=i}else r&&(n.z=r.z+a(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,o=t,c=u.parent.children[0],s=u.m,l=i.m,f=o.m,h=c.m;o=_i(o),u=Mi(u),o&&u;)c=Mi(c),i=_i(i),i.a=n,r=o.z+f-u.z-s+a(o._,u._),r>0&&(bi(Si(o,n,e),n,r),s+=r,l+=r),f+=o.m,s+=u.m,h+=c.m,l+=i.m;o&&!_i(i)&&(i.t=o,i.m+=f-l),u&&!Mi(c)&&(c.t=u,c.m+=s-h,e=n)}return e}function i(n){n.x*=c[0],n.y=n.depth*c[1]}var o=Zo.layout.hierarchy().sort(null).value(null),a=xi,c=[1,1],s=null;return n.separation=function(t){return arguments.length?(a=t,n):a},n.size=function(t){return arguments.length?(s=null==(c=t)?i:null,n):s?null:c},n.nodeSize=function(t){return arguments.length?(s=null==(c=t)?null:i,n):s?c:null},Xu(n,o)},Zo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;Bu(c,function(n){var t=n.children;t&&t.length?(n.x=Ei(t),n.y=ki(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ai(c),f=Ci(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return Bu(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Zo.layout.hierarchy().sort(null).value(null),e=xi,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Xu(n,t)},Zo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++i<o;)u=n[i],u.x=a,u.y=s,u.dy=l,a+=u.dx=Math.min(e.x+e.dx-a,l?c(u.area/l):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=l,e.dy-=l}else{for((r||l>e.dx)&&(l=e.dx);++i<o;)u=n[i],u.x=a,u.y=s,u.dx=l,s+=u.dy=Math.min(e.y+e.dy-s,l?c(u.area/l):0);u.z=!1,u.dy+=e.y+e.dy-s,e.x+=l,e.dx-=l}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=s[0],i.dy=s[1],o&&a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&&(o=u),u}var o,a=Zo.layout.hierarchy(),c=Math.round,s=[1,1],l=null,f=Ni,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return i.size=function(n){return arguments.length?(s=n,i):s},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ni(t):zi(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return zi(t,n)}if(!arguments.length)return l;var r;return f=null==(l=n)?Ni:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+"",i):g},Xu(i,a)},Zo.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Zo.random.normal.apply(Zo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Zo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Zo.scale={};var ss={floor:wt,ceil:wt};Zo.scale.linear=function(){return Ui([0,1],[0,1],hu,!1)};var ls={s:1,g:1,p:1,r:1,e:1};Zo.scale.log=function(){return Vi(Zo.scale.linear().domain([0,1]),10,!0,[1,10])};var fs=Zo.format(".0e"),hs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Zo.scale.pow=function(){return Xi(Zo.scale.linear(),1,[0,1])},Zo.scale.sqrt=function(){return Zo.scale.pow().exponent(.5)},Zo.scale.ordinal=function(){return Bi([],{t:"range",a:[[]]})},Zo.scale.category10=function(){return Zo.scale.ordinal().range(gs)},Zo.scale.category20=function(){return Zo.scale.ordinal().range(ps)},Zo.scale.category20b=function(){return Zo.scale.ordinal().range(vs)},Zo.scale.category20c=function(){return Zo.scale.ordinal().range(ds)};var gs=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(vt),ps=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(vt),vs=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(vt),ds=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(vt);Zo.scale.quantile=function(){return Wi([],[])},Zo.scale.quantize=function(){return Ji(0,1,[0,1])},Zo.scale.threshold=function(){return Gi([.5],[0,1])},Zo.scale.identity=function(){return Ki([0,1])},Zo.svg={},Zo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ms,a=u.apply(this,arguments)+ms,c=(o>a&&(c=o,o=a,a=c),a-o),s=ba>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a); +return c>=ys?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=Qi,e=no,r=to,u=eo;return n.innerRadius=function(e){return arguments.length?(t=bt(e),n):t},n.outerRadius=function(t){return arguments.length?(e=bt(t),n):e},n.startAngle=function(t){return arguments.length?(r=bt(t),n):r},n.endAngle=function(t){return arguments.length?(u=bt(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ms;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ms=-Sa,ys=wa-ka;Zo.svg.line=function(){return ro(wt)};var xs=Zo.map({linear:uo,"linear-closed":io,step:oo,"step-before":ao,"step-after":co,basis:po,"basis-open":vo,"basis-closed":mo,bundle:yo,cardinal:fo,"cardinal-open":so,"cardinal-closed":lo,monotone:So});xs.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Ms=[0,2/3,1/3,0],_s=[0,1/3,2/3,0],bs=[0,1/6,2/3,1/6];Zo.svg.line.radial=function(){var n=ro(ko);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},ao.reverse=co,co.reverse=ao,Zo.svg.area=function(){return Eo(wt)},Zo.svg.area.radial=function(){var n=Eo(ko);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Zo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ms,l=s.call(n,u,r)+ms;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>ba)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=gr,o=pr,a=Ao,c=to,s=eo;return n.radius=function(t){return arguments.length?(a=bt(t),n):a},n.source=function(t){return arguments.length?(i=bt(t),n):i},n.target=function(t){return arguments.length?(o=bt(t),n):o},n.startAngle=function(t){return arguments.length?(c=bt(t),n):c},n.endAngle=function(t){return arguments.length?(s=bt(t),n):s},n},Zo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=gr,e=pr,r=Co;return n.source=function(e){return arguments.length?(t=bt(e),n):t},n.target=function(t){return arguments.length?(e=bt(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Zo.svg.diagonal.radial=function(){var n=Zo.svg.diagonal(),t=Co,e=n.projection;return n.projection=function(n){return arguments.length?e(No(t=n)):t},n},Zo.svg.symbol=function(){function n(n,r){return(ws.get(t.call(this,n,r))||To)(e.call(this,n,r))}var t=Lo,e=zo;return n.type=function(e){return arguments.length?(t=bt(e),n):t},n.size=function(t){return arguments.length?(e=bt(t),n):e},n};var ws=Zo.map({circle:To,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*As)),e=t*As;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/Es),e=t*Es/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/Es),e=t*Es/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Zo.svg.symbolTypes=ws.keys();var Ss,ks,Es=Math.sqrt(3),As=Math.tan(30*Aa),Cs=[],Ns=0;Cs.call=pa.call,Cs.empty=pa.empty,Cs.node=pa.node,Cs.size=pa.size,Zo.transition=function(n){return arguments.length?Ss?n.transition():n:ma.transition()},Zo.transition.prototype=Cs,Cs.select=function(n){var t,e,r,u=this.id,i=[];n=b(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]);for(var c=this[o],s=-1,l=c.length;++s<l;)(r=c[s])&&(e=n.call(r,r.__data__,s,o))?("__data__"in r&&(e.__data__=r.__data__),Po(e,s,u,r.__transition__[u]),t.push(e)):t.push(null)}return qo(i,u)},Cs.selectAll=function(n){var t,e,r,u,i,o=this.id,a=[];n=w(n);for(var c=-1,s=this.length;++c<s;)for(var l=this[c],f=-1,h=l.length;++f<h;)if(r=l[f]){i=r.__transition__[o],e=n.call(r,r.__data__,f,c),a.push(t=[]);for(var g=-1,p=e.length;++g<p;)(u=e[g])&&Po(u,g,o,i),t.push(u)}return qo(a,o)},Cs.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=R(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return qo(u,this.id)},Cs.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):P(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Cs.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Du:hu,a=Zo.ns.qualify(n);return Ro(this,"attr."+n,t,a.local?i:u)},Cs.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Zo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Cs.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Wo.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=hu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Ro(this,"style."+n,t,u)},Cs.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Wo.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Cs.text=function(n){return Ro(this,"text",n,Do)},Cs.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Cs.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Zo.ease.apply(Zo,arguments)),P(this,function(e){e.__transition__[t].ease=n}))},Cs.delay=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].delay:P(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Cs.duration=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].duration:P(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Cs.each=function(n,t){var e=this.id;if(arguments.length<2){var r=ks,u=Ss;Ss=e,P(this,function(t,r,u){ks=t.__transition__[e],n.call(t,t.__data__,r,u)}),ks=r,Ss=u}else P(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Zo.dispatch("start","end"))).on(n,t)});return this},Cs.transition=function(){for(var n,t,e,r,u=this.id,i=++Ns,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,Po(e,s,i,r)),n.push(e)}return qo(o,i)},Zo.svg.axis=function(){function n(n){n.each(function(){var n,s=Zo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):wt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",ka),d=Zo.transition(p.exit()).style("opacity",ka).remove(),m=Zo.transition(p.order()).style("opacity",1),y=Ti(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Zo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Uo,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Uo,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=jo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=jo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Zo.scale.linear(),r=zs,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Ls?t+"":zs,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var zs="bottom",Ls={top:1,right:1,bottom:1,left:1};Zo.svg.brush=function(){function n(i){i.each(function(){var i=Zo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,wt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Ts[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Zo.transition(i),h=Zo.transition(o);c&&(l=Ti(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ti(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Zo.event.keyCode&&(C||(x=null,z[0]-=l[1],z[1]-=f[1],C=2),y())}function p(){32==Zo.event.keyCode&&2==C&&(z[0]+=l[1],z[1]+=f[1],C=0,y())}function v(){var n=Zo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Zo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),z[0]=l[+(n[0]<x[0])],z[1]=f[+(n[1]<x[1])]):x=null),E&&d(n,c,0)&&(e(S),u=!0),A&&d(n,s,1)&&(r(S),u=!0),u&&(t(S),w({type:"brush",mode:C?"move":"resize"}))}function d(n,t,e){var r,u,a=Ti(t),c=a[0],s=a[1],p=z[e],v=e?f:l,d=v[1]-v[0];return C&&(c-=p,s-=d+p),r=(e?g:h)?Math.max(c,Math.min(s,n[e])):n[e],C?u=(r+=p)+d:(x&&(p=Math.max(c,Math.min(s,2*x[e]-r))),r>p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function m(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Zo.select("body").style("cursor",null),L.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Zo.select(Zo.event.target),w=a.of(_,arguments),S=Zo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=I(),z=Zo.mouse(_),L=Zo.select(Wo).on("keydown.brush",u).on("keyup.brush",p);if(Zo.event.changedTouches?L.on("touchmove.brush",v).on("touchend.brush",m):L.on("mousemove.brush",v).on("mouseup.brush",m),S.interrupt().selectAll("*").interrupt(),C)z[0]=l[0]-z[0],z[1]=f[0]-z[1];else if(k){var T=+/w$/.test(k),q=+/^n/.test(k);M=[l[1-T]-z[0],f[1-q]-z[1]],z[0]=l[T],z[1]=f[q]}else Zo.event.altKey&&(x=z.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Zo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=M(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=qs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,Ss?Zo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=gu(l,t.x),r=gu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=qs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=qs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Zo.rebind(n,a,"on")};var Ts={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},qs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Rs=Qa.format=ic.timeFormat,Ds=Rs.utc,Ps=Ds("%Y-%m-%dT%H:%M:%S.%LZ");Rs.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Ho:Ps,Ho.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Ho.toString=Ps.toString,Qa.second=Dt(function(n){return new nc(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),Qa.seconds=Qa.second.range,Qa.seconds.utc=Qa.second.utc.range,Qa.minute=Dt(function(n){return new nc(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),Qa.minutes=Qa.minute.range,Qa.minutes.utc=Qa.minute.utc.range,Qa.hour=Dt(function(n){var t=n.getTimezoneOffset()/60;return new nc(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),Qa.hours=Qa.hour.range,Qa.hours.utc=Qa.hour.utc.range,Qa.month=Dt(function(n){return n=Qa.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),Qa.months=Qa.month.range,Qa.months.utc=Qa.month.utc.range;var Us=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],js=[[Qa.second,1],[Qa.second,5],[Qa.second,15],[Qa.second,30],[Qa.minute,1],[Qa.minute,5],[Qa.minute,15],[Qa.minute,30],[Qa.hour,1],[Qa.hour,3],[Qa.hour,6],[Qa.hour,12],[Qa.day,1],[Qa.day,2],[Qa.week,1],[Qa.month,1],[Qa.month,3],[Qa.year,1]],Hs=Rs.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",we]]),Fs={range:function(n,t,e){return Zo.range(Math.ceil(n/e)*e,+t,e).map(Oo)},floor:wt,ceil:wt};js.year=Qa.year,Qa.scale=function(){return Fo(Zo.scale.linear(),js,Hs)};var Os=js.map(function(n){return[n[0].utc,n[1]]}),Ys=Ds.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",we]]);Os.year=Qa.year.utc,Qa.scale.utc=function(){return Fo(Zo.scale.linear(),Os,Ys)},Zo.text=St(function(n){return n.responseText}),Zo.json=function(n,t){return kt(n,"application/json",Yo,t)},Zo.html=function(n,t){return kt(n,"text/html",Io,t)},Zo.xml=St(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Zo):"object"==typeof module&&module.exports&&(module.exports=Zo),this.d3=Zo}(); \ No newline at end of file diff --git a/src/static/dagre-d3/dagre-d3.js b/src/static/dagre-d3/dagre-d3.js new file mode 100644 index 0000000..8728227 --- /dev/null +++ b/src/static/dagre-d3/dagre-d3.js @@ -0,0 +1,5003 @@ +;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ +var global=self;/** + * @license + * Copyright (c) 2012-2013 Chris Pettitt + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +global.dagreD3 = require('./index'); + +},{"./index":2}],2:[function(require,module,exports){ +/** + * @license + * Copyright (c) 2012-2013 Chris Pettitt + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +module.exports = { + Digraph: require('graphlib').Digraph, + Graph: require('graphlib').Graph, + Renderer: require('./lib/Renderer'), + json: require('graphlib').converter.json, + layout: require('dagre').layout, + version: require('./lib/version'), + debug: require('dagre').debug +}; + +},{"./lib/Renderer":3,"./lib/version":4,"dagre":11,"graphlib":29}],3:[function(require,module,exports){ +var layout = require('dagre').layout; + +var d3; +try { d3 = require('d3'); } catch (_) { d3 = window.d3; } + +module.exports = Renderer; + +function Renderer() { + // Set up defaults... + this._layout = layout(); + + this.drawNodes(defaultDrawNodes); + this.drawEdgeLabels(defaultDrawEdgeLabels); + this.drawEdgePaths(defaultDrawEdgePaths); + this.positionNodes(defaultPositionNodes); + this.positionEdgeLabels(defaultPositionEdgeLabels); + this.positionEdgePaths(defaultPositionEdgePaths); + this.zoomSetup(defaultZoomSetup); + this.zoom(defaultZoom); + this.transition(defaultTransition); + this.postLayout(defaultPostLayout); + this.postRender(defaultPostRender); + + this.edgeInterpolate('bundle'); + this.edgeTension(0.95); +} + +Renderer.prototype.layout = function(layout) { + if (!arguments.length) { return this._layout; } + this._layout = layout; + return this; +}; + +Renderer.prototype.drawNodes = function(drawNodes) { + if (!arguments.length) { return this._drawNodes; } + this._drawNodes = bind(drawNodes, this); + return this; +}; + +Renderer.prototype.drawEdgeLabels = function(drawEdgeLabels) { + if (!arguments.length) { return this._drawEdgeLabels; } + this._drawEdgeLabels = bind(drawEdgeLabels, this); + return this; +}; + +Renderer.prototype.drawEdgePaths = function(drawEdgePaths) { + if (!arguments.length) { return this._drawEdgePaths; } + this._drawEdgePaths = bind(drawEdgePaths, this); + return this; +}; + +Renderer.prototype.positionNodes = function(positionNodes) { + if (!arguments.length) { return this._positionNodes; } + this._positionNodes = bind(positionNodes, this); + return this; +}; + +Renderer.prototype.positionEdgeLabels = function(positionEdgeLabels) { + if (!arguments.length) { return this._positionEdgeLabels; } + this._positionEdgeLabels = bind(positionEdgeLabels, this); + return this; +}; + +Renderer.prototype.positionEdgePaths = function(positionEdgePaths) { + if (!arguments.length) { return this._positionEdgePaths; } + this._positionEdgePaths = bind(positionEdgePaths, this); + return this; +}; + +Renderer.prototype.transition = function(transition) { + if (!arguments.length) { return this._transition; } + this._transition = bind(transition, this); + return this; +}; + +Renderer.prototype.zoomSetup = function(zoomSetup) { + if (!arguments.length) { return this._zoomSetup; } + this._zoomSetup = bind(zoomSetup, this); + return this; +}; + +Renderer.prototype.zoom = function(zoom) { + if (!arguments.length) { return this._zoom; } + if (zoom) { + this._zoom = bind(zoom, this); + } else { + delete this._zoom; + } + return this; +}; + +Renderer.prototype.postLayout = function(postLayout) { + if (!arguments.length) { return this._postLayout; } + this._postLayout = bind(postLayout, this); + return this; +}; + +Renderer.prototype.postRender = function(postRender) { + if (!arguments.length) { return this._postRender; } + this._postRender = bind(postRender, this); + return this; +}; + +Renderer.prototype.edgeInterpolate = function(edgeInterpolate) { + if (!arguments.length) { return this._edgeInterpolate; } + this._edgeInterpolate = edgeInterpolate; + return this; +}; + +Renderer.prototype.edgeTension = function(edgeTension) { + if (!arguments.length) { return this._edgeTension; } + this._edgeTension = edgeTension; + return this; +}; + +Renderer.prototype.run = function(graph, orgSvg) { + // First copy the input graph so that it is not changed by the rendering + // process. + graph = copyAndInitGraph(graph); + + // Create zoom elements + var svg = this._zoomSetup(graph, orgSvg); + + // Create layers + svg + .selectAll('g.edgePaths, g.edgeLabels, g.nodes') + .data(['edgePaths', 'edgeLabels', 'nodes']) + .enter() + .append('g') + .attr('class', function(d) { return d; }); + + // Create node and edge roots, attach labels, and capture dimension + // information for use with layout. + var svgNodes = this._drawNodes(graph, svg.select('g.nodes')); + var svgEdgeLabels = this._drawEdgeLabels(graph, svg.select('g.edgeLabels')); + + svgNodes.each(function(u) { calculateDimensions(this, graph.node(u)); }); + svgEdgeLabels.each(function(e) { calculateDimensions(this, graph.edge(e)); }); + + // Now apply the layout function + var result = runLayout(graph, this._layout); + + // Copy useDef attribute from input graph to output graph + graph.eachNode(function(u, a) { + if (a.useDef) { + result.node(u).useDef = a.useDef; + } + }); + + // Run any user-specified post layout processing + this._postLayout(result, svg); + + var svgEdgePaths = this._drawEdgePaths(graph, svg.select('g.edgePaths')); + + // Apply the layout information to the graph + this._positionNodes(result, svgNodes); + this._positionEdgeLabels(result, svgEdgeLabels); + this._positionEdgePaths(result, svgEdgePaths, orgSvg); + + this._postRender(result, svg); + + return result; +}; + +function copyAndInitGraph(graph) { + var copy = graph.copy(); + + if (copy.graph() === undefined) { + copy.graph({}); + } + + if (!('arrowheadFix' in copy.graph())) { + copy.graph().arrowheadFix = true; + } + + // Init labels if they were not present in the source graph + copy.nodes().forEach(function(u) { + var value = copyObject(copy.node(u)); + copy.node(u, value); + if (!('label' in value)) { value.label = ''; } + }); + + copy.edges().forEach(function(e) { + var value = copyObject(copy.edge(e)); + copy.edge(e, value); + if (!('label' in value)) { value.label = ''; } + }); + + return copy; +} + +function copyObject(obj) { + var copy = {}; + for (var k in obj) { + copy[k] = obj[k]; + } + return copy; +} + +function calculateDimensions(group, value) { + var bbox = group.getBBox(); + value.width = bbox.width; + value.height = bbox.height; +} + +function runLayout(graph, layout) { + var result = layout.run(graph); + + // Copy labels to the result graph + graph.eachNode(function(u, value) { result.node(u).label = value.label; }); + graph.eachEdge(function(e, u, v, value) { result.edge(e).label = value.label; }); + + return result; +} + +function defaultDrawNodes(g, root) { + var nodes = g.nodes().filter(function(u) { return !isComposite(g, u); }); + + var svgNodes = root + .selectAll('g.node') + .classed('enter', false) + .data(nodes, function(u) { return u; }); + + svgNodes.selectAll('*').remove(); + + svgNodes + .enter() + .append('g') + .style('opacity', 0) + .attr('class', 'node enter'); + + svgNodes.each(function(u) { + var attrs = g.node(u), + domNode = d3.select(this); + addLabel(attrs, domNode, true, 10, 10); + }); + + this._transition(svgNodes.exit()) + .style('opacity', 0) + .remove(); + + return svgNodes; +} + +function defaultDrawEdgeLabels(g, root) { + var svgEdgeLabels = root + .selectAll('g.edgeLabel') + .classed('enter', false) + .data(g.edges(), function (e) { return e; }); + + svgEdgeLabels.selectAll('*').remove(); + + svgEdgeLabels + .enter() + .append('g') + .style('opacity', 0) + .attr('class', 'edgeLabel enter'); + + svgEdgeLabels.each(function(e) { addLabel(g.edge(e), d3.select(this), false, 0, 0); }); + + this._transition(svgEdgeLabels.exit()) + .style('opacity', 0) + .remove(); + + return svgEdgeLabels; +} + +var defaultDrawEdgePaths = function(g, root) { + var svgEdgePaths = root + .selectAll('g.edgePath') + .classed('enter', false) + .data(g.edges(), function(e) { return e; }); + + var DEFAULT_ARROWHEAD = 'url(#arrowhead)', + createArrowhead = DEFAULT_ARROWHEAD; + if (!g.isDirected()) { + createArrowhead = null; + } else if (g.graph().arrowheadFix !== 'false' && g.graph().arrowheadFix !== false) { + createArrowhead = function() { + var strokeColor = d3.select(this).style('stroke'); + if (strokeColor) { + var id = 'arrowhead-' + strokeColor.replace(/[^a-zA-Z0-9]/g, '_'); + getOrMakeArrowhead(root, id).style('fill', strokeColor); + return 'url(#' + id + ')'; + } + return DEFAULT_ARROWHEAD; + }; + } + + svgEdgePaths + .enter() + .append('g') + .attr('class', 'edgePath enter') + .append('path') + .style('opacity', 0); + + svgEdgePaths + .selectAll('path') + .each(function(e) { applyStyle(g.edge(e).style, d3.select(this)); }) + .attr('marker-end', createArrowhead); + + this._transition(svgEdgePaths.exit()) + .style('opacity', 0) + .remove(); + + return svgEdgePaths; +}; + +function defaultPositionNodes(g, svgNodes) { + function transform(u) { + var value = g.node(u); + return 'translate(' + value.x + ',' + value.y + ')'; + } + + // For entering nodes, position immediately without transition + svgNodes.filter('.enter').attr('transform', transform); + + this._transition(svgNodes) + .style('opacity', 1) + .attr('transform', transform); +} + +function defaultPositionEdgeLabels(g, svgEdgeLabels) { + function transform(e) { + var value = g.edge(e); + var point = findMidPoint(value.points); + return 'translate(' + point.x + ',' + point.y + ')'; + } + + // For entering edge labels, position immediately without transition + svgEdgeLabels.filter('.enter').attr('transform', transform); + + this._transition(svgEdgeLabels) + .style('opacity', 1) + .attr('transform', transform); +} + +function isEllipse(obj) { + return Object.prototype.toString.call(obj) === '[object SVGEllipseElement]'; +} + +function isCircle(obj) { + return Object.prototype.toString.call(obj) === '[object SVGCircleElement]'; +} + +function isPolygon(obj) { + return Object.prototype.toString.call(obj) === '[object SVGPolygonElement]'; +} + +function intersectNode(nd, p1, root) { + if (nd.useDef) { + var definedFig = root.select('defs #' + nd.useDef).node(); + if (definedFig) { + var outerFig = definedFig.childNodes[0]; + if (isCircle(outerFig) || isEllipse(outerFig)) { + return intersectEllipse(nd, outerFig, p1); + } else if (isPolygon(outerFig)) { + return intersectPolygon(nd, outerFig, p1); + } + } + } + // TODO: use bpodgursky's shortening algorithm here + return intersectRect(nd, p1); +} + +function defaultPositionEdgePaths(g, svgEdgePaths, root) { + var interpolate = this._edgeInterpolate, + tension = this._edgeTension; + + function calcPoints(e) { + var value = g.edge(e); + var source = g.node(g.incidentNodes(e)[0]); + var target = g.node(g.incidentNodes(e)[1]); + var points = value.points.slice(); + + var p0 = points.length === 0 ? target : points[0]; + var p1 = points.length === 0 ? source : points[points.length - 1]; + + points.unshift(intersectNode(source, p0, root)); + points.push(intersectNode(target, p1, root)); + + return d3.svg.line() + .x(function(d) { return d.x; }) + .y(function(d) { return d.y; }) + .interpolate(interpolate) + .tension(tension) + (points); + } + + svgEdgePaths.filter('.enter').selectAll('path') + .attr('d', calcPoints); + + this._transition(svgEdgePaths.selectAll('path')) + .attr('d', calcPoints) + .style('opacity', 1); +} + +// By default we do not use transitions +function defaultTransition(selection) { + return selection; +} + +// Setup dom for zooming +function defaultZoomSetup(graph, svg) { + var root = svg.property('ownerSVGElement'); + // If the svg node is the root, we get null, so set to svg. + if (!root) { + root = svg; + } else { + root = d3.select(root); + } + + if (root.select('rect.overlay').empty()) { + // Create an overlay for capturing mouse events that don't touch foreground + root.insert('rect', ':first-child') + .attr('class', 'overlay') + .attr('width', '100%') + .attr('height', '100%') + .style('fill', 'none') + .style('pointer-events', 'all'); + + // Capture the zoom behaviour from the svg + svg = svg.append('g') + .attr('class', 'zoom'); + + if (this._zoom) { + root.call(this._zoom(graph, svg)); + } + } + + return svg; +} + +// By default allow pan and zoom +function defaultZoom(graph, svg) { + return d3.behavior.zoom().on('zoom', function() { + svg.attr('transform', 'translate(' + d3.event.translate + ')scale(' + d3.event.scale + ')'); + }); +} + +function defaultPostLayout() { + // Do nothing +} + +function defaultPostRender(graph, root) { + if (graph.isDirected()) { + // Fill = #333 is for backwards compatibility + getOrMakeArrowhead(root, 'arrowhead') + .attr('fill', '#333'); + } +} + +function getOrMakeArrowhead(root, id) { + var search = root.select('#' + id); + if (!search.empty()) { return search; } + + var defs = root.select('defs'); + if (defs.empty()) { + defs = root.append('svg:defs'); + } + + var marker = + defs + .append('svg:marker') + .attr('id', id) + .attr('viewBox', '0 0 10 10') + .attr('refX', 8) + .attr('refY', 5) + .attr('markerUnits', 'strokeWidth') + .attr('markerWidth', 8) + .attr('markerHeight', 5) + .attr('orient', 'auto'); + + marker + .append('svg:path') + .attr('d', 'M 0 0 L 10 5 L 0 10 z'); + + return marker; +} + +function addLabel(node, root, addingNode, marginX, marginY) { + // If the node has 'useDef' meta data, we rely on that + if (node.useDef) { + root.append('use').attr('xlink:href', '#' + node.useDef); + return; + } + // Add the rect first so that it appears behind the label + var label = node.label; + var rect = root.append('rect'); + if (node.width) { + rect.attr('width', node.width); + } + if (node.height) { + rect.attr('height', node.height); + } + + var labelSvg = root.append('g'), + innerLabelSvg; + + if (label[0] === '<') { + addForeignObjectLabel(label, labelSvg); + // No margin for HTML elements + marginX = marginY = 0; + } else { + innerLabelSvg = addTextLabel(label, + labelSvg, + Math.floor(node.labelCols), + node.labelCut); + applyStyle(node.labelStyle, innerLabelSvg); + } + + var labelBBox = labelSvg.node().getBBox(); + labelSvg.attr('transform', + 'translate(' + (-labelBBox.width / 2) + ',' + (-labelBBox.height / 2) + ')'); + + var bbox = root.node().getBBox(); + + rect + .attr('rx', node.rx ? node.rx : 5) + .attr('ry', node.ry ? node.ry : 5) + .attr('x', -(bbox.width / 2 + marginX)) + .attr('y', -(bbox.height / 2 + marginY)) + .attr('width', bbox.width + 2 * marginX) + .attr('height', bbox.height + 2 * marginY) + .attr('fill', '#fff'); + + if (addingNode) { + applyStyle(node.style, rect); + + if (node.fill) { + rect.style('fill', node.fill); + } + + if (node.stroke) { + rect.style('stroke', node.stroke); + } + + if (node['stroke-width']) { + rect.style('stroke-width', node['stroke-width'] + 'px'); + } + + if (node['stroke-dasharray']) { + rect.style('stroke-dasharray', node['stroke-dasharray']); + } + + if (node.href) { + root + .attr('class', root.attr('class') + ' clickable') + .on('click', function() { + window.open(node.href); + }); + } + } +} + +function addForeignObjectLabel(label, root) { + var fo = root + .append('foreignObject') + .attr('width', '100000'); + + var w, h; + fo + .append('xhtml:div') + .style('float', 'left') + // TODO find a better way to get dimensions for foreignObjects... + .html(function() { return label; }) + .each(function() { + w = this.clientWidth; + h = this.clientHeight; + }); + + fo + .attr('width', w) + .attr('height', h); +} + +function addTextLabel(label, root, labelCols, labelCut) { + if (labelCut === undefined) { labelCut = 'false'; } + labelCut = (labelCut.toString().toLowerCase() === 'true'); + + var node = root + .append('text') + .attr('text-anchor', 'left'); + + label = label.replace(/\\n/g, '\n'); + + var arr = labelCols ? wordwrap(label, labelCols, labelCut) : label; + arr = arr.split('\n'); + for (var i = 0; i < arr.length; i++) { + node + .append('tspan') + .attr('dy', '1em') + .attr('x', '1') + .text(arr[i]); + } + + return node; +} + +// Thanks to +// http://james.padolsey.com/javascript/wordwrap-for-javascript/ +function wordwrap (str, width, cut, brk) { + brk = brk || '\n'; + width = width || 75; + cut = cut || false; + + if (!str) { return str; } + + var regex = '.{1,' + width + '}(\\s|$)' + (cut ? '|.{' + width + '}|.+$' : '|\\S+?(\\s|$)'); + + return str.match(new RegExp(regex, 'g')).join(brk); +} + +function findMidPoint(points) { + var midIdx = points.length / 2; + if (points.length % 2) { + return points[Math.floor(midIdx)]; + } else { + var p0 = points[midIdx - 1]; + var p1 = points[midIdx]; + return {x: (p0.x + p1.x) / 2, y: (p0.y + p1.y) / 2}; + } +} + +function intersectRect(rect, point) { + var x = rect.x; + var y = rect.y; + + // Rectangle intersection algorithm from: + // http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes + var dx = point.x - x; + var dy = point.y - y; + var w = rect.width / 2; + var h = rect.height / 2; + + var sx, sy; + if (Math.abs(dy) * w > Math.abs(dx) * h) { + // Intersection is top or bottom of rect. + if (dy < 0) { + h = -h; + } + sx = dy === 0 ? 0 : h * dx / dy; + sy = h; + } else { + // Intersection is left or right of rect. + if (dx < 0) { + w = -w; + } + sx = w; + sy = dx === 0 ? 0 : w * dy / dx; + } + + return {x: x + sx, y: y + sy}; +} + +function intersectEllipse(node, ellipseOrCircle, point) { + // Formulae from: http://mathworld.wolfram.com/Ellipse-LineIntersection.html + + var cx = node.x; + var cy = node.y; + var rx, ry; + + if (isCircle(ellipseOrCircle)) { + rx = ry = ellipseOrCircle.r.baseVal.value; + } else { + rx = ellipseOrCircle.rx.baseVal.value; + ry = ellipseOrCircle.ry.baseVal.value; + } + + var px = cx - point.x; + var py = cy - point.y; + + var det = Math.sqrt(rx * rx * py * py + ry * ry * px * px); + + var dx = Math.abs(rx * ry * px / det); + if (point.x < cx) { + dx = -dx; + } + var dy = Math.abs(rx * ry * py / det); + if (point.y < cy) { + dy = -dy; + } + + return {x: cx + dx, y: cy + dy}; +} + +function sameSign(r1, r2) { + return r1 * r2 > 0; +} + +// Add point to the found intersections, but check first that it is unique. +function addPoint(x, y, intersections) { + if (!intersections.some(function (elm) { return elm[0] === x && elm[1] === y; })) { + intersections.push([x, y]); + } +} + +function intersectLine(x1, y1, x2, y2, x3, y3, x4, y4, intersections) { + // Algorithm from J. Avro, (ed.) Graphics Gems, No 2, Morgan Kaufmann, 1994, p7 and p473. + + var a1, a2, b1, b2, c1, c2; + var r1, r2 , r3, r4; + var denom, offset, num; + var x, y; + + // Compute a1, b1, c1, where line joining points 1 and 2 is F(x,y) = a1 x + b1 y + c1 = 0. + a1 = y2 - y1; + b1 = x1 - x2; + c1 = (x2 * y1) - (x1 * y2); + + // Compute r3 and r4. + r3 = ((a1 * x3) + (b1 * y3) + c1); + r4 = ((a1 * x4) + (b1 * y4) + c1); + + // Check signs of r3 and r4. If both point 3 and point 4 lie on + // same side of line 1, the line segments do not intersect. + if ((r3 !== 0) && (r4 !== 0) && sameSign(r3, r4)) { + return /*DONT_INTERSECT*/; + } + + // Compute a2, b2, c2 where line joining points 3 and 4 is G(x,y) = a2 x + b2 y + c2 = 0 + a2 = y4 - y3; + b2 = x3 - x4; + c2 = (x4 * y3) - (x3 * y4); + + // Compute r1 and r2 + r1 = (a2 * x1) + (b2 * y1) + c2; + r2 = (a2 * x2) + (b2 * y2) + c2; + + // Check signs of r1 and r2. If both point 1 and point 2 lie + // on same side of second line segment, the line segments do + // not intersect. + if ((r1 !== 0) && (r2 !== 0) && (sameSign(r1, r2))) { + return /*DONT_INTERSECT*/; + } + + // Line segments intersect: compute intersection point. + denom = (a1 * b2) - (a2 * b1); + if (denom === 0) { + return /*COLLINEAR*/; + } + + offset = Math.abs(denom / 2); + + // The denom/2 is to get rounding instead of truncating. It + // is added or subtracted to the numerator, depending upon the + // sign of the numerator. + num = (b1 * c2) - (b2 * c1); + x = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom); + + num = (a2 * c1) - (a1 * c2); + y = (num < 0) ? ((num - offset) / denom) : ((num + offset) / denom); + + // lines_intersect + addPoint(x, y, intersections); +} + +function intersectPolygon(node, polygon, point) { + var x1 = node.x; + var y1 = node.y; + var x2 = point.x; + var y2 = point.y; + + var intersections = []; + var points = polygon.points; + + var minx = 100000, miny = 100000; + for (var j = 0; j < points.numberOfItems; j++) { + var p = points.getItem(j); + minx = Math.min(minx, p.x); + miny = Math.min(miny, p.y); + } + + var left = x1 - node.width / 2 - minx; + var top = y1 - node.height / 2 - miny; + + for (var i = 0; i < points.numberOfItems; i++) { + var p1 = points.getItem(i); + var p2 = points.getItem(i < points.numberOfItems - 1 ? i + 1 : 0); + intersectLine(x1, y1, x2, y2, left + p1.x, top + p1.y, left + p2.x, top + p2.y, intersections); + } + + if (intersections.length === 1) { + return {x: intersections[0][0], y: intersections[0][1]}; + } + + if (intersections.length > 1) { + // More intersections, find the one nearest to edge end point + intersections.sort(function(p, q) { + var pdx = p[0] - point.x, + pdy = p[1] - point.y, + distp = Math.sqrt(pdx * pdx + pdy * pdy), + + qdx = q[0] - point.x, + qdy = q[1] - point.y, + distq = Math.sqrt(qdx * qdx + qdy * qdy); + + return (distp < distq) ? -1 : (distp === distq ? 0 : 1); + }); + return {x: intersections[0][0], y: intersections[0][1]}; + } else { + console.log('NO INTERSECTION FOUND, RETURN NODE CENTER', node); + return node; + } +} + +function isComposite(g, u) { + return 'children' in g && g.children(u).length; +} + +function bind(func, thisArg) { + // For some reason PhantomJS occassionally fails when using the builtin bind, + // so we check if it is available and if not, use a degenerate polyfill. + if (func.bind) { + return func.bind(thisArg); + } + + return function() { + return func.apply(thisArg, arguments); + }; +} + +function applyStyle(style, domNode) { + if (style) { + var currStyle = domNode.attr('style') || ''; + domNode.attr('style', currStyle + '; ' + style); + } +} + +},{"d3":10,"dagre":11}],4:[function(require,module,exports){ +module.exports = '0.2.9'; + +},{}],5:[function(require,module,exports){ +exports.Set = require('./lib/Set'); +exports.PriorityQueue = require('./lib/PriorityQueue'); +exports.version = require('./lib/version'); + +},{"./lib/PriorityQueue":6,"./lib/Set":7,"./lib/version":9}],6:[function(require,module,exports){ +module.exports = PriorityQueue; + +/** + * A min-priority queue data structure. This algorithm is derived from Cormen, + * et al., "Introduction to Algorithms". The basic idea of a min-priority + * queue is that you can efficiently (in O(1) time) get the smallest key in + * the queue. Adding and removing elements takes O(log n) time. A key can + * have its priority decreased in O(log n) time. + */ +function PriorityQueue() { + this._arr = []; + this._keyIndices = {}; +} + +/** + * Returns the number of elements in the queue. Takes `O(1)` time. + */ +PriorityQueue.prototype.size = function() { + return this._arr.length; +}; + +/** + * Returns the keys that are in the queue. Takes `O(n)` time. + */ +PriorityQueue.prototype.keys = function() { + return this._arr.map(function(x) { return x.key; }); +}; + +/** + * Returns `true` if **key** is in the queue and `false` if not. + */ +PriorityQueue.prototype.has = function(key) { + return key in this._keyIndices; +}; + +/** + * Returns the priority for **key**. If **key** is not present in the queue + * then this function returns `undefined`. Takes `O(1)` time. + * + * @param {Object} key + */ +PriorityQueue.prototype.priority = function(key) { + var index = this._keyIndices[key]; + if (index !== undefined) { + return this._arr[index].priority; + } +}; + +/** + * Returns the key for the minimum element in this queue. If the queue is + * empty this function throws an Error. Takes `O(1)` time. + */ +PriorityQueue.prototype.min = function() { + if (this.size() === 0) { + throw new Error("Queue underflow"); + } + return this._arr[0].key; +}; + +/** + * Inserts a new key into the priority queue. If the key already exists in + * the queue this function returns `false`; otherwise it will return `true`. + * Takes `O(n)` time. + * + * @param {Object} key the key to add + * @param {Number} priority the initial priority for the key + */ +PriorityQueue.prototype.add = function(key, priority) { + var keyIndices = this._keyIndices; + if (!(key in keyIndices)) { + var arr = this._arr; + var index = arr.length; + keyIndices[key] = index; + arr.push({key: key, priority: priority}); + this._decrease(index); + return true; + } + return false; +}; + +/** + * Removes and returns the smallest key in the queue. Takes `O(log n)` time. + */ +PriorityQueue.prototype.removeMin = function() { + this._swap(0, this._arr.length - 1); + var min = this._arr.pop(); + delete this._keyIndices[min.key]; + this._heapify(0); + return min.key; +}; + +/** + * Decreases the priority for **key** to **priority**. If the new priority is + * greater than the previous priority, this function will throw an Error. + * + * @param {Object} key the key for which to raise priority + * @param {Number} priority the new priority for the key + */ +PriorityQueue.prototype.decrease = function(key, priority) { + var index = this._keyIndices[key]; + if (priority > this._arr[index].priority) { + throw new Error("New priority is greater than current priority. " + + "Key: " + key + " Old: " + this._arr[index].priority + " New: " + priority); + } + this._arr[index].priority = priority; + this._decrease(index); +}; + +PriorityQueue.prototype._heapify = function(i) { + var arr = this._arr; + var l = 2 * i, + r = l + 1, + largest = i; + if (l < arr.length) { + largest = arr[l].priority < arr[largest].priority ? l : largest; + if (r < arr.length) { + largest = arr[r].priority < arr[largest].priority ? r : largest; + } + if (largest !== i) { + this._swap(i, largest); + this._heapify(largest); + } + } +}; + +PriorityQueue.prototype._decrease = function(index) { + var arr = this._arr; + var priority = arr[index].priority; + var parent; + while (index !== 0) { + parent = index >> 1; + if (arr[parent].priority < priority) { + break; + } + this._swap(index, parent); + index = parent; + } +}; + +PriorityQueue.prototype._swap = function(i, j) { + var arr = this._arr; + var keyIndices = this._keyIndices; + var origArrI = arr[i]; + var origArrJ = arr[j]; + arr[i] = origArrJ; + arr[j] = origArrI; + keyIndices[origArrJ.key] = i; + keyIndices[origArrI.key] = j; +}; + +},{}],7:[function(require,module,exports){ +var util = require('./util'); + +module.exports = Set; + +/** + * Constructs a new Set with an optional set of `initialKeys`. + * + * It is important to note that keys are coerced to String for most purposes + * with this object, similar to the behavior of JavaScript's Object. For + * example, the following will add only one key: + * + * var s = new Set(); + * s.add(1); + * s.add("1"); + * + * However, the type of the key is preserved internally so that `keys` returns + * the original key set uncoerced. For the above example, `keys` would return + * `[1]`. + */ +function Set(initialKeys) { + this._size = 0; + this._keys = {}; + + if (initialKeys) { + for (var i = 0, il = initialKeys.length; i < il; ++i) { + this.add(initialKeys[i]); + } + } +} + +/** + * Returns a new Set that represents the set intersection of the array of given + * sets. + */ +Set.intersect = function(sets) { + if (sets.length === 0) { + return new Set(); + } + + var result = new Set(!util.isArray(sets[0]) ? sets[0].keys() : sets[0]); + for (var i = 1, il = sets.length; i < il; ++i) { + var resultKeys = result.keys(), + other = !util.isArray(sets[i]) ? sets[i] : new Set(sets[i]); + for (var j = 0, jl = resultKeys.length; j < jl; ++j) { + var key = resultKeys[j]; + if (!other.has(key)) { + result.remove(key); + } + } + } + + return result; +}; + +/** + * Returns a new Set that represents the set union of the array of given sets. + */ +Set.union = function(sets) { + var totalElems = util.reduce(sets, function(lhs, rhs) { + return lhs + (rhs.size ? rhs.size() : rhs.length); + }, 0); + var arr = new Array(totalElems); + + var k = 0; + for (var i = 0, il = sets.length; i < il; ++i) { + var cur = sets[i], + keys = !util.isArray(cur) ? cur.keys() : cur; + for (var j = 0, jl = keys.length; j < jl; ++j) { + arr[k++] = keys[j]; + } + } + + return new Set(arr); +}; + +/** + * Returns the size of this set in `O(1)` time. + */ +Set.prototype.size = function() { + return this._size; +}; + +/** + * Returns the keys in this set. Takes `O(n)` time. + */ +Set.prototype.keys = function() { + return values(this._keys); +}; + +/** + * Tests if a key is present in this Set. Returns `true` if it is and `false` + * if not. Takes `O(1)` time. + */ +Set.prototype.has = function(key) { + return key in this._keys; +}; + +/** + * Adds a new key to this Set if it is not already present. Returns `true` if + * the key was added and `false` if it was already present. Takes `O(1)` time. + */ +Set.prototype.add = function(key) { + if (!(key in this._keys)) { + this._keys[key] = key; + ++this._size; + return true; + } + return false; +}; + +/** + * Removes a key from this Set. If the key was removed this function returns + * `true`. If not, it returns `false`. Takes `O(1)` time. + */ +Set.prototype.remove = function(key) { + if (key in this._keys) { + delete this._keys[key]; + --this._size; + return true; + } + return false; +}; + +/* + * Returns an array of all values for properties of **o**. + */ +function values(o) { + var ks = Object.keys(o), + len = ks.length, + result = new Array(len), + i; + for (i = 0; i < len; ++i) { + result[i] = o[ks[i]]; + } + return result; +} + +},{"./util":8}],8:[function(require,module,exports){ +/* + * This polyfill comes from + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray + */ +if(!Array.isArray) { + exports.isArray = function (vArg) { + return Object.prototype.toString.call(vArg) === '[object Array]'; + }; +} else { + exports.isArray = Array.isArray; +} + +/* + * Slightly adapted polyfill from + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce + */ +if ('function' !== typeof Array.prototype.reduce) { + exports.reduce = function(array, callback, opt_initialValue) { + 'use strict'; + if (null === array || 'undefined' === typeof array) { + // At the moment all modern browsers, that support strict mode, have + // native implementation of Array.prototype.reduce. For instance, IE8 + // does not support strict mode, so this check is actually useless. + throw new TypeError( + 'Array.prototype.reduce called on null or undefined'); + } + if ('function' !== typeof callback) { + throw new TypeError(callback + ' is not a function'); + } + var index, value, + length = array.length >>> 0, + isValueSet = false; + if (1 < arguments.length) { + value = opt_initialValue; + isValueSet = true; + } + for (index = 0; length > index; ++index) { + if (array.hasOwnProperty(index)) { + if (isValueSet) { + value = callback(value, array[index], index, array); + } + else { + value = array[index]; + isValueSet = true; + } + } + } + if (!isValueSet) { + throw new TypeError('Reduce of empty array with no initial value'); + } + return value; + }; +} else { + exports.reduce = function(array, callback, opt_initialValue) { + return array.reduce(callback, opt_initialValue); + }; +} + +},{}],9:[function(require,module,exports){ +module.exports = '1.1.3'; + +},{}],10:[function(require,module,exports){ +require("./d3"); +module.exports = d3; +(function () { delete this.d3; })(); // unset global + +},{}],11:[function(require,module,exports){ +/* +Copyright (c) 2012-2013 Chris Pettitt + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +exports.Digraph = require("graphlib").Digraph; +exports.Graph = require("graphlib").Graph; +exports.layout = require("./lib/layout"); +exports.version = require("./lib/version"); +exports.debug = require("./lib/debug"); + +},{"./lib/debug":12,"./lib/layout":13,"./lib/version":28,"graphlib":29}],12:[function(require,module,exports){ +'use strict'; + +var util = require('./util'); + +/** + * Renders a graph in a stringified DOT format that indicates the ordering of + * nodes by layer. Circles represent normal nodes. Diamons represent dummy + * nodes. While we try to put nodes in clusters, it appears that graphviz + * does not respect this because we're later using subgraphs for ordering nodes + * in each layer. + */ +exports.dotOrdering = function(g) { + var ordering = util.ordering(g.filterNodes(util.filterNonSubgraphs(g))); + var result = 'digraph {'; + + function dfs(u) { + var children = g.children(u); + if (children.length) { + result += 'subgraph cluster_' + u + ' {'; + result += 'label="' + u + '";'; + children.forEach(function(v) { + dfs(v); + }); + result += '}'; + } else { + result += u; + if (g.node(u).dummy) { + result += ' [shape=diamond]'; + } + result += ';'; + } + } + + g.children(null).forEach(dfs); + + ordering.forEach(function(layer) { + result += 'subgraph { rank=same; edge [style="invis"];'; + result += layer.join('->'); + result += '}'; + }); + + g.eachEdge(function(e, u, v) { + result += u + '->' + v + ';'; + }); + + result += '}'; + + return result; +}; + +},{"./util":27}],13:[function(require,module,exports){ +'use strict'; + +var util = require('./util'), + rank = require('./rank'), + order = require('./order'), + CGraph = require('graphlib').CGraph, + CDigraph = require('graphlib').CDigraph; + +module.exports = function() { + // External configuration + var config = { + // How much debug information to include? + debugLevel: 0, + // Max number of sweeps to perform in order phase + orderMaxSweeps: order.DEFAULT_MAX_SWEEPS, + // Use network simplex algorithm in ranking + rankSimplex: false, + // Rank direction. Valid values are (TB, LR) + rankDir: 'TB' + }; + + // Phase functions + var position = require('./position')(); + + // This layout object + var self = {}; + + self.orderIters = util.propertyAccessor(self, config, 'orderMaxSweeps'); + + self.rankSimplex = util.propertyAccessor(self, config, 'rankSimplex'); + + self.nodeSep = delegateProperty(position.nodeSep); + self.edgeSep = delegateProperty(position.edgeSep); + self.universalSep = delegateProperty(position.universalSep); + self.rankSep = delegateProperty(position.rankSep); + self.rankDir = util.propertyAccessor(self, config, 'rankDir'); + self.debugAlignment = delegateProperty(position.debugAlignment); + + self.debugLevel = util.propertyAccessor(self, config, 'debugLevel', function(x) { + util.log.level = x; + position.debugLevel(x); + }); + + self.run = util.time('Total layout', run); + + self._normalize = normalize; + + return self; + + /* + * Constructs an adjacency graph using the nodes and edges specified through + * config. For each node and edge we add a property `dagre` that contains an + * object that will hold intermediate and final layout information. Some of + * the contents include: + * + * 1) A generated ID that uniquely identifies the object. + * 2) Dimension information for nodes (copied from the source node). + * 3) Optional dimension information for edges. + * + * After the adjacency graph is constructed the code no longer needs to use + * the original nodes and edges passed in via config. + */ + function initLayoutGraph(inputGraph) { + var g = new CDigraph(); + + inputGraph.eachNode(function(u, value) { + if (value === undefined) value = {}; + g.addNode(u, { + width: value.width, + height: value.height + }); + if (value.hasOwnProperty('rank')) { + g.node(u).prefRank = value.rank; + } + }); + + // Set up subgraphs + if (inputGraph.parent) { + inputGraph.nodes().forEach(function(u) { + g.parent(u, inputGraph.parent(u)); + }); + } + + inputGraph.eachEdge(function(e, u, v, value) { + if (value === undefined) value = {}; + var newValue = { + e: e, + minLen: value.minLen || 1, + width: value.width || 0, + height: value.height || 0, + points: [] + }; + + g.addEdge(null, u, v, newValue); + }); + + // Initial graph attributes + var graphValue = inputGraph.graph() || {}; + g.graph({ + rankDir: graphValue.rankDir || config.rankDir, + orderRestarts: graphValue.orderRestarts + }); + + return g; + } + + function run(inputGraph) { + var rankSep = self.rankSep(); + var g; + try { + // Build internal graph + g = util.time('initLayoutGraph', initLayoutGraph)(inputGraph); + + if (g.order() === 0) { + return g; + } + + // Make space for edge labels + g.eachEdge(function(e, s, t, a) { + a.minLen *= 2; + }); + self.rankSep(rankSep / 2); + + // Determine the rank for each node. Nodes with a lower rank will appear + // above nodes of higher rank. + util.time('rank.run', rank.run)(g, config.rankSimplex); + + // Normalize the graph by ensuring that every edge is proper (each edge has + // a length of 1). We achieve this by adding dummy nodes to long edges, + // thus shortening them. + util.time('normalize', normalize)(g); + + // Order the nodes so that edge crossings are minimized. + util.time('order', order)(g, config.orderMaxSweeps); + + // Find the x and y coordinates for every node in the graph. + util.time('position', position.run)(g); + + // De-normalize the graph by removing dummy nodes and augmenting the + // original long edges with coordinate information. + util.time('undoNormalize', undoNormalize)(g); + + // Reverses points for edges that are in a reversed state. + util.time('fixupEdgePoints', fixupEdgePoints)(g); + + // Restore delete edges and reverse edges that were reversed in the rank + // phase. + util.time('rank.restoreEdges', rank.restoreEdges)(g); + + // Construct final result graph and return it + return util.time('createFinalGraph', createFinalGraph)(g, inputGraph.isDirected()); + } finally { + self.rankSep(rankSep); + } + } + + /* + * This function is responsible for 'normalizing' the graph. The process of + * normalization ensures that no edge in the graph has spans more than one + * rank. To do this it inserts dummy nodes as needed and links them by adding + * dummy edges. This function keeps enough information in the dummy nodes and + * edges to ensure that the original graph can be reconstructed later. + * + * This method assumes that the input graph is cycle free. + */ + function normalize(g) { + var dummyCount = 0; + g.eachEdge(function(e, s, t, a) { + var sourceRank = g.node(s).rank; + var targetRank = g.node(t).rank; + if (sourceRank + 1 < targetRank) { + for (var u = s, rank = sourceRank + 1, i = 0; rank < targetRank; ++rank, ++i) { + var v = '_D' + (++dummyCount); + var node = { + width: a.width, + height: a.height, + edge: { id: e, source: s, target: t, attrs: a }, + rank: rank, + dummy: true + }; + + // If this node represents a bend then we will use it as a control + // point. For edges with 2 segments this will be the center dummy + // node. For edges with more than two segments, this will be the + // first and last dummy node. + if (i === 0) node.index = 0; + else if (rank + 1 === targetRank) node.index = 1; + + g.addNode(v, node); + g.addEdge(null, u, v, {}); + u = v; + } + g.addEdge(null, u, t, {}); + g.delEdge(e); + } + }); + } + + /* + * Reconstructs the graph as it was before normalization. The positions of + * dummy nodes are used to build an array of points for the original 'long' + * edge. Dummy nodes and edges are removed. + */ + function undoNormalize(g) { + g.eachNode(function(u, a) { + if (a.dummy) { + if ('index' in a) { + var edge = a.edge; + if (!g.hasEdge(edge.id)) { + g.addEdge(edge.id, edge.source, edge.target, edge.attrs); + } + var points = g.edge(edge.id).points; + points[a.index] = { x: a.x, y: a.y, ul: a.ul, ur: a.ur, dl: a.dl, dr: a.dr }; + } + g.delNode(u); + } + }); + } + + /* + * For each edge that was reversed during the `acyclic` step, reverse its + * array of points. + */ + function fixupEdgePoints(g) { + g.eachEdge(function(e, s, t, a) { if (a.reversed) a.points.reverse(); }); + } + + function createFinalGraph(g, isDirected) { + var out = isDirected ? new CDigraph() : new CGraph(); + out.graph(g.graph()); + g.eachNode(function(u, value) { out.addNode(u, value); }); + g.eachNode(function(u) { out.parent(u, g.parent(u)); }); + g.eachEdge(function(e, u, v, value) { + out.addEdge(value.e, u, v, value); + }); + + // Attach bounding box information + var maxX = 0, maxY = 0; + g.eachNode(function(u, value) { + if (!g.children(u).length) { + maxX = Math.max(maxX, value.x + value.width / 2); + maxY = Math.max(maxY, value.y + value.height / 2); + } + }); + g.eachEdge(function(e, u, v, value) { + var maxXPoints = Math.max.apply(Math, value.points.map(function(p) { return p.x; })); + var maxYPoints = Math.max.apply(Math, value.points.map(function(p) { return p.y; })); + maxX = Math.max(maxX, maxXPoints + value.width / 2); + maxY = Math.max(maxY, maxYPoints + value.height / 2); + }); + out.graph().width = maxX; + out.graph().height = maxY; + + return out; + } + + /* + * Given a function, a new function is returned that invokes the given + * function. The return value from the function is always the `self` object. + */ + function delegateProperty(f) { + return function() { + if (!arguments.length) return f(); + f.apply(null, arguments); + return self; + }; + } +}; + + +},{"./order":14,"./position":19,"./rank":20,"./util":27,"graphlib":29}],14:[function(require,module,exports){ +'use strict'; + +var util = require('./util'), + crossCount = require('./order/crossCount'), + initLayerGraphs = require('./order/initLayerGraphs'), + initOrder = require('./order/initOrder'), + sortLayer = require('./order/sortLayer'); + +module.exports = order; + +// The maximum number of sweeps to perform before finishing the order phase. +var DEFAULT_MAX_SWEEPS = 24; +order.DEFAULT_MAX_SWEEPS = DEFAULT_MAX_SWEEPS; + +/* + * Runs the order phase with the specified `graph, `maxSweeps`, and + * `debugLevel`. If `maxSweeps` is not specified we use `DEFAULT_MAX_SWEEPS`. + * If `debugLevel` is not set we assume 0. + */ +function order(g, maxSweeps) { + if (arguments.length < 2) { + maxSweeps = DEFAULT_MAX_SWEEPS; + } + + var restarts = g.graph().orderRestarts || 0; + + var layerGraphs = initLayerGraphs(g); + // TODO: remove this when we add back support for ordering clusters + layerGraphs.forEach(function(lg) { + lg = lg.filterNodes(function(u) { return !g.children(u).length; }); + }); + + var iters = 0, + currentBestCC, + allTimeBestCC = Number.MAX_VALUE, + allTimeBest = {}; + + function saveAllTimeBest() { + g.eachNode(function(u, value) { allTimeBest[u] = value.order; }); + } + + for (var j = 0; j < Number(restarts) + 1 && allTimeBestCC !== 0; ++j) { + currentBestCC = Number.MAX_VALUE; + initOrder(g, restarts > 0); + + util.log(2, 'Order phase start cross count: ' + g.graph().orderInitCC); + + var i, lastBest, cc; + for (i = 0, lastBest = 0; lastBest < 4 && i < maxSweeps && currentBestCC > 0; ++i, ++lastBest, ++iters) { + sweep(g, layerGraphs, i); + cc = crossCount(g); + if (cc < currentBestCC) { + lastBest = 0; + currentBestCC = cc; + if (cc < allTimeBestCC) { + saveAllTimeBest(); + allTimeBestCC = cc; + } + } + util.log(3, 'Order phase start ' + j + ' iter ' + i + ' cross count: ' + cc); + } + } + + Object.keys(allTimeBest).forEach(function(u) { + if (!g.children || !g.children(u).length) { + g.node(u).order = allTimeBest[u]; + } + }); + g.graph().orderCC = allTimeBestCC; + + util.log(2, 'Order iterations: ' + iters); + util.log(2, 'Order phase best cross count: ' + g.graph().orderCC); +} + +function predecessorWeights(g, nodes) { + var weights = {}; + nodes.forEach(function(u) { + weights[u] = g.inEdges(u).map(function(e) { + return g.node(g.source(e)).order; + }); + }); + return weights; +} + +function successorWeights(g, nodes) { + var weights = {}; + nodes.forEach(function(u) { + weights[u] = g.outEdges(u).map(function(e) { + return g.node(g.target(e)).order; + }); + }); + return weights; +} + +function sweep(g, layerGraphs, iter) { + if (iter % 2 === 0) { + sweepDown(g, layerGraphs, iter); + } else { + sweepUp(g, layerGraphs, iter); + } +} + +function sweepDown(g, layerGraphs) { + var cg; + for (var i = 1; i < layerGraphs.length; ++i) { + cg = sortLayer(layerGraphs[i], cg, predecessorWeights(g, layerGraphs[i].nodes())); + } +} + +function sweepUp(g, layerGraphs) { + var cg; + for (var i = layerGraphs.length - 2; i >= 0; --i) { + sortLayer(layerGraphs[i], cg, successorWeights(g, layerGraphs[i].nodes())); + } +} + +},{"./order/crossCount":15,"./order/initLayerGraphs":16,"./order/initOrder":17,"./order/sortLayer":18,"./util":27}],15:[function(require,module,exports){ +'use strict'; + +var util = require('../util'); + +module.exports = crossCount; + +/* + * Returns the cross count for the given graph. + */ +function crossCount(g) { + var cc = 0; + var ordering = util.ordering(g); + for (var i = 1; i < ordering.length; ++i) { + cc += twoLayerCrossCount(g, ordering[i-1], ordering[i]); + } + return cc; +} + +/* + * This function searches through a ranked and ordered graph and counts the + * number of edges that cross. This algorithm is derived from: + * + * W. Barth et al., Bilayer Cross Counting, JGAA, 8(2) 179–194 (2004) + */ +function twoLayerCrossCount(g, layer1, layer2) { + var indices = []; + layer1.forEach(function(u) { + var nodeIndices = []; + g.outEdges(u).forEach(function(e) { nodeIndices.push(g.node(g.target(e)).order); }); + nodeIndices.sort(function(x, y) { return x - y; }); + indices = indices.concat(nodeIndices); + }); + + var firstIndex = 1; + while (firstIndex < layer2.length) firstIndex <<= 1; + + var treeSize = 2 * firstIndex - 1; + firstIndex -= 1; + + var tree = []; + for (var i = 0; i < treeSize; ++i) { tree[i] = 0; } + + var cc = 0; + indices.forEach(function(i) { + var treeIndex = i + firstIndex; + ++tree[treeIndex]; + while (treeIndex > 0) { + if (treeIndex % 2) { + cc += tree[treeIndex + 1]; + } + treeIndex = (treeIndex - 1) >> 1; + ++tree[treeIndex]; + } + }); + + return cc; +} + +},{"../util":27}],16:[function(require,module,exports){ +'use strict'; + +var nodesFromList = require('graphlib').filter.nodesFromList, + /* jshint -W079 */ + Set = require('cp-data').Set; + +module.exports = initLayerGraphs; + +/* + * This function takes a compound layered graph, g, and produces an array of + * layer graphs. Each entry in the array represents a subgraph of nodes + * relevant for performing crossing reduction on that layer. + */ +function initLayerGraphs(g) { + var ranks = []; + + function dfs(u) { + if (u === null) { + g.children(u).forEach(function(v) { dfs(v); }); + return; + } + + var value = g.node(u); + value.minRank = ('rank' in value) ? value.rank : Number.MAX_VALUE; + value.maxRank = ('rank' in value) ? value.rank : Number.MIN_VALUE; + var uRanks = new Set(); + g.children(u).forEach(function(v) { + var rs = dfs(v); + uRanks = Set.union([uRanks, rs]); + value.minRank = Math.min(value.minRank, g.node(v).minRank); + value.maxRank = Math.max(value.maxRank, g.node(v).maxRank); + }); + + if ('rank' in value) uRanks.add(value.rank); + + uRanks.keys().forEach(function(r) { + if (!(r in ranks)) ranks[r] = []; + ranks[r].push(u); + }); + + return uRanks; + } + dfs(null); + + var layerGraphs = []; + ranks.forEach(function(us, rank) { + layerGraphs[rank] = g.filterNodes(nodesFromList(us)); + }); + + return layerGraphs; +} + +},{"cp-data":5,"graphlib":29}],17:[function(require,module,exports){ +'use strict'; + +var crossCount = require('./crossCount'), + util = require('../util'); + +module.exports = initOrder; + +/* + * Given a graph with a set of layered nodes (i.e. nodes that have a `rank` + * attribute) this function attaches an `order` attribute that uniquely + * arranges each node of each rank. If no constraint graph is provided the + * order of the nodes in each rank is entirely arbitrary. + */ +function initOrder(g, random) { + var layers = []; + + g.eachNode(function(u, value) { + var layer = layers[value.rank]; + if (g.children && g.children(u).length > 0) return; + if (!layer) { + layer = layers[value.rank] = []; + } + layer.push(u); + }); + + layers.forEach(function(layer) { + if (random) { + util.shuffle(layer); + } + layer.forEach(function(u, i) { + g.node(u).order = i; + }); + }); + + var cc = crossCount(g); + g.graph().orderInitCC = cc; + g.graph().orderCC = Number.MAX_VALUE; +} + +},{"../util":27,"./crossCount":15}],18:[function(require,module,exports){ +'use strict'; + +var util = require('../util'), + Digraph = require('graphlib').Digraph, + topsort = require('graphlib').alg.topsort, + nodesFromList = require('graphlib').filter.nodesFromList; + +module.exports = sortLayer; + +function sortLayer(g, cg, weights) { + weights = adjustWeights(g, weights); + var result = sortLayerSubgraph(g, null, cg, weights); + + result.list.forEach(function(u, i) { + g.node(u).order = i; + }); + return result.constraintGraph; +} + +function sortLayerSubgraph(g, sg, cg, weights) { + cg = cg ? cg.filterNodes(nodesFromList(g.children(sg))) : new Digraph(); + + var nodeData = {}; + g.children(sg).forEach(function(u) { + if (g.children(u).length) { + nodeData[u] = sortLayerSubgraph(g, u, cg, weights); + nodeData[u].firstSG = u; + nodeData[u].lastSG = u; + } else { + var ws = weights[u]; + nodeData[u] = { + degree: ws.length, + barycenter: util.sum(ws) / ws.length, + order: g.node(u).order, + orderCount: 1, + list: [u] + }; + } + }); + + resolveViolatedConstraints(g, cg, nodeData); + + var keys = Object.keys(nodeData); + keys.sort(function(x, y) { + return nodeData[x].barycenter - nodeData[y].barycenter || + nodeData[x].order - nodeData[y].order; + }); + + var result = keys.map(function(u) { return nodeData[u]; }) + .reduce(function(lhs, rhs) { return mergeNodeData(g, lhs, rhs); }); + return result; +} + +function mergeNodeData(g, lhs, rhs) { + var cg = mergeDigraphs(lhs.constraintGraph, rhs.constraintGraph); + + if (lhs.lastSG !== undefined && rhs.firstSG !== undefined) { + if (cg === undefined) { + cg = new Digraph(); + } + if (!cg.hasNode(lhs.lastSG)) { cg.addNode(lhs.lastSG); } + cg.addNode(rhs.firstSG); + cg.addEdge(null, lhs.lastSG, rhs.firstSG); + } + + return { + degree: lhs.degree + rhs.degree, + barycenter: (lhs.barycenter * lhs.degree + rhs.barycenter * rhs.degree) / + (lhs.degree + rhs.degree), + order: (lhs.order * lhs.orderCount + rhs.order * rhs.orderCount) / + (lhs.orderCount + rhs.orderCount), + orderCount: lhs.orderCount + rhs.orderCount, + list: lhs.list.concat(rhs.list), + firstSG: lhs.firstSG !== undefined ? lhs.firstSG : rhs.firstSG, + lastSG: rhs.lastSG !== undefined ? rhs.lastSG : lhs.lastSG, + constraintGraph: cg + }; +} + +function mergeDigraphs(lhs, rhs) { + if (lhs === undefined) return rhs; + if (rhs === undefined) return lhs; + + lhs = lhs.copy(); + rhs.nodes().forEach(function(u) { lhs.addNode(u); }); + rhs.edges().forEach(function(e, u, v) { lhs.addEdge(null, u, v); }); + return lhs; +} + +function resolveViolatedConstraints(g, cg, nodeData) { + // Removes nodes `u` and `v` from `cg` and makes any edges incident on them + // incident on `w` instead. + function collapseNodes(u, v, w) { + // TODO original paper removes self loops, but it is not obvious when this would happen + cg.inEdges(u).forEach(function(e) { + cg.delEdge(e); + cg.addEdge(null, cg.source(e), w); + }); + + cg.outEdges(v).forEach(function(e) { + cg.delEdge(e); + cg.addEdge(null, w, cg.target(e)); + }); + + cg.delNode(u); + cg.delNode(v); + } + + var violated; + while ((violated = findViolatedConstraint(cg, nodeData)) !== undefined) { + var source = cg.source(violated), + target = cg.target(violated); + + var v; + while ((v = cg.addNode(null)) && g.hasNode(v)) { + cg.delNode(v); + } + + // Collapse barycenter and list + nodeData[v] = mergeNodeData(g, nodeData[source], nodeData[target]); + delete nodeData[source]; + delete nodeData[target]; + + collapseNodes(source, target, v); + if (cg.incidentEdges(v).length === 0) { cg.delNode(v); } + } +} + +function findViolatedConstraint(cg, nodeData) { + var us = topsort(cg); + for (var i = 0; i < us.length; ++i) { + var u = us[i]; + var inEdges = cg.inEdges(u); + for (var j = 0; j < inEdges.length; ++j) { + var e = inEdges[j]; + if (nodeData[cg.source(e)].barycenter >= nodeData[u].barycenter) { + return e; + } + } + } +} + +// Adjust weights so that they fall in the range of 0..|N|-1. If a node has no +// weight assigned then set its adjusted weight to its current position. This +// allows us to better retain the origiinal position of nodes without neighbors. +function adjustWeights(g, weights) { + var minW = Number.MAX_VALUE, + maxW = 0, + adjusted = {}; + g.eachNode(function(u) { + if (g.children(u).length) return; + + var ws = weights[u]; + if (ws.length) { + minW = Math.min(minW, util.min(ws)); + maxW = Math.max(maxW, util.max(ws)); + } + }); + + var rangeW = (maxW - minW); + g.eachNode(function(u) { + if (g.children(u).length) return; + + var ws = weights[u]; + if (!ws.length) { + adjusted[u] = [g.node(u).order]; + } else { + adjusted[u] = ws.map(function(w) { + if (rangeW) { + return (w - minW) * (g.order() - 1) / rangeW; + } else { + return g.order() - 1 / 2; + } + }); + } + }); + + return adjusted; +} + +},{"../util":27,"graphlib":29}],19:[function(require,module,exports){ +'use strict'; + +var util = require('./util'); + +/* + * The algorithms here are based on Brandes and Köpf, "Fast and Simple + * Horizontal Coordinate Assignment". + */ +module.exports = function() { + // External configuration + var config = { + nodeSep: 50, + edgeSep: 10, + universalSep: null, + rankSep: 30 + }; + + var self = {}; + + self.nodeSep = util.propertyAccessor(self, config, 'nodeSep'); + self.edgeSep = util.propertyAccessor(self, config, 'edgeSep'); + // If not null this separation value is used for all nodes and edges + // regardless of their widths. `nodeSep` and `edgeSep` are ignored with this + // option. + self.universalSep = util.propertyAccessor(self, config, 'universalSep'); + self.rankSep = util.propertyAccessor(self, config, 'rankSep'); + self.debugLevel = util.propertyAccessor(self, config, 'debugLevel'); + + self.run = run; + + return self; + + function run(g) { + g = g.filterNodes(util.filterNonSubgraphs(g)); + + var layering = util.ordering(g); + + var conflicts = findConflicts(g, layering); + + var xss = {}; + ['u', 'd'].forEach(function(vertDir) { + if (vertDir === 'd') layering.reverse(); + + ['l', 'r'].forEach(function(horizDir) { + if (horizDir === 'r') reverseInnerOrder(layering); + + var dir = vertDir + horizDir; + var align = verticalAlignment(g, layering, conflicts, vertDir === 'u' ? 'predecessors' : 'successors'); + xss[dir]= horizontalCompaction(g, layering, align.pos, align.root, align.align); + + if (config.debugLevel >= 3) + debugPositioning(vertDir + horizDir, g, layering, xss[dir]); + + if (horizDir === 'r') flipHorizontally(xss[dir]); + + if (horizDir === 'r') reverseInnerOrder(layering); + }); + + if (vertDir === 'd') layering.reverse(); + }); + + balance(g, layering, xss); + + g.eachNode(function(v) { + var xs = []; + for (var alignment in xss) { + var alignmentX = xss[alignment][v]; + posXDebug(alignment, g, v, alignmentX); + xs.push(alignmentX); + } + xs.sort(function(x, y) { return x - y; }); + posX(g, v, (xs[1] + xs[2]) / 2); + }); + + // Align y coordinates with ranks + var y = 0, reverseY = g.graph().rankDir === 'BT' || g.graph().rankDir === 'RL'; + layering.forEach(function(layer) { + var maxHeight = util.max(layer.map(function(u) { return height(g, u); })); + y += maxHeight / 2; + layer.forEach(function(u) { + posY(g, u, reverseY ? -y : y); + }); + y += maxHeight / 2 + config.rankSep; + }); + + // Translate layout so that top left corner of bounding rectangle has + // coordinate (0, 0). + var minX = util.min(g.nodes().map(function(u) { return posX(g, u) - width(g, u) / 2; })); + var minY = util.min(g.nodes().map(function(u) { return posY(g, u) - height(g, u) / 2; })); + g.eachNode(function(u) { + posX(g, u, posX(g, u) - minX); + posY(g, u, posY(g, u) - minY); + }); + } + + /* + * Generate an ID that can be used to represent any undirected edge that is + * incident on `u` and `v`. + */ + function undirEdgeId(u, v) { + return u < v + ? u.toString().length + ':' + u + '-' + v + : v.toString().length + ':' + v + '-' + u; + } + + function findConflicts(g, layering) { + var conflicts = {}, // Set of conflicting edge ids + pos = {}, // Position of node in its layer + prevLayer, + currLayer, + k0, // Position of the last inner segment in the previous layer + l, // Current position in the current layer (for iteration up to `l1`) + k1; // Position of the next inner segment in the previous layer or + // the position of the last element in the previous layer + + if (layering.length <= 2) return conflicts; + + function updateConflicts(v) { + var k = pos[v]; + if (k < k0 || k > k1) { + conflicts[undirEdgeId(currLayer[l], v)] = true; + } + } + + layering[1].forEach(function(u, i) { pos[u] = i; }); + for (var i = 1; i < layering.length - 1; ++i) { + prevLayer = layering[i]; + currLayer = layering[i+1]; + k0 = 0; + l = 0; + + // Scan current layer for next node that is incident to an inner segement + // between layering[i+1] and layering[i]. + for (var l1 = 0; l1 < currLayer.length; ++l1) { + var u = currLayer[l1]; // Next inner segment in the current layer or + // last node in the current layer + pos[u] = l1; + k1 = undefined; + + if (g.node(u).dummy) { + var uPred = g.predecessors(u)[0]; + // Note: In the case of self loops and sideways edges it is possible + // for a dummy not to have a predecessor. + if (uPred !== undefined && g.node(uPred).dummy) + k1 = pos[uPred]; + } + if (k1 === undefined && l1 === currLayer.length - 1) + k1 = prevLayer.length - 1; + + if (k1 !== undefined) { + for (; l <= l1; ++l) { + g.predecessors(currLayer[l]).forEach(updateConflicts); + } + k0 = k1; + } + } + } + + return conflicts; + } + + function verticalAlignment(g, layering, conflicts, relationship) { + var pos = {}, // Position for a node in its layer + root = {}, // Root of the block that the node participates in + align = {}; // Points to the next node in the block or, if the last + // element in the block, points to the first block's root + + layering.forEach(function(layer) { + layer.forEach(function(u, i) { + root[u] = u; + align[u] = u; + pos[u] = i; + }); + }); + + layering.forEach(function(layer) { + var prevIdx = -1; + layer.forEach(function(v) { + var related = g[relationship](v), // Adjacent nodes from the previous layer + mid; // The mid point in the related array + + if (related.length > 0) { + related.sort(function(x, y) { return pos[x] - pos[y]; }); + mid = (related.length - 1) / 2; + related.slice(Math.floor(mid), Math.ceil(mid) + 1).forEach(function(u) { + if (align[v] === v) { + if (!conflicts[undirEdgeId(u, v)] && prevIdx < pos[u]) { + align[u] = v; + align[v] = root[v] = root[u]; + prevIdx = pos[u]; + } + } + }); + } + }); + }); + + return { pos: pos, root: root, align: align }; + } + + // This function deviates from the standard BK algorithm in two ways. First + // it takes into account the size of the nodes. Second it includes a fix to + // the original algorithm that is described in Carstens, "Node and Label + // Placement in a Layered Layout Algorithm". + function horizontalCompaction(g, layering, pos, root, align) { + var sink = {}, // Mapping of node id -> sink node id for class + maybeShift = {}, // Mapping of sink node id -> { class node id, min shift } + shift = {}, // Mapping of sink node id -> shift + pred = {}, // Mapping of node id -> predecessor node (or null) + xs = {}; // Calculated X positions + + layering.forEach(function(layer) { + layer.forEach(function(u, i) { + sink[u] = u; + maybeShift[u] = {}; + if (i > 0) + pred[u] = layer[i - 1]; + }); + }); + + function updateShift(toShift, neighbor, delta) { + if (!(neighbor in maybeShift[toShift])) { + maybeShift[toShift][neighbor] = delta; + } else { + maybeShift[toShift][neighbor] = Math.min(maybeShift[toShift][neighbor], delta); + } + } + + function placeBlock(v) { + if (!(v in xs)) { + xs[v] = 0; + var w = v; + do { + if (pos[w] > 0) { + var u = root[pred[w]]; + placeBlock(u); + if (sink[v] === v) { + sink[v] = sink[u]; + } + var delta = sep(g, pred[w]) + sep(g, w); + if (sink[v] !== sink[u]) { + updateShift(sink[u], sink[v], xs[v] - xs[u] - delta); + } else { + xs[v] = Math.max(xs[v], xs[u] + delta); + } + } + w = align[w]; + } while (w !== v); + } + } + + // Root coordinates relative to sink + util.values(root).forEach(function(v) { + placeBlock(v); + }); + + // Absolute coordinates + // There is an assumption here that we've resolved shifts for any classes + // that begin at an earlier layer. We guarantee this by visiting layers in + // order. + layering.forEach(function(layer) { + layer.forEach(function(v) { + xs[v] = xs[root[v]]; + if (v === root[v] && v === sink[v]) { + var minShift = 0; + if (v in maybeShift && Object.keys(maybeShift[v]).length > 0) { + minShift = util.min(Object.keys(maybeShift[v]) + .map(function(u) { + return maybeShift[v][u] + (u in shift ? shift[u] : 0); + } + )); + } + shift[v] = minShift; + } + }); + }); + + layering.forEach(function(layer) { + layer.forEach(function(v) { + xs[v] += shift[sink[root[v]]] || 0; + }); + }); + + return xs; + } + + function findMinCoord(g, layering, xs) { + return util.min(layering.map(function(layer) { + var u = layer[0]; + return xs[u]; + })); + } + + function findMaxCoord(g, layering, xs) { + return util.max(layering.map(function(layer) { + var u = layer[layer.length - 1]; + return xs[u]; + })); + } + + function balance(g, layering, xss) { + var min = {}, // Min coordinate for the alignment + max = {}, // Max coordinate for the alginment + smallestAlignment, + shift = {}; // Amount to shift a given alignment + + function updateAlignment(v) { + xss[alignment][v] += shift[alignment]; + } + + var smallest = Number.POSITIVE_INFINITY; + for (var alignment in xss) { + var xs = xss[alignment]; + min[alignment] = findMinCoord(g, layering, xs); + max[alignment] = findMaxCoord(g, layering, xs); + var w = max[alignment] - min[alignment]; + if (w < smallest) { + smallest = w; + smallestAlignment = alignment; + } + } + + // Determine how much to adjust positioning for each alignment + ['u', 'd'].forEach(function(vertDir) { + ['l', 'r'].forEach(function(horizDir) { + var alignment = vertDir + horizDir; + shift[alignment] = horizDir === 'l' + ? min[smallestAlignment] - min[alignment] + : max[smallestAlignment] - max[alignment]; + }); + }); + + // Find average of medians for xss array + for (alignment in xss) { + g.eachNode(updateAlignment); + } + } + + function flipHorizontally(xs) { + for (var u in xs) { + xs[u] = -xs[u]; + } + } + + function reverseInnerOrder(layering) { + layering.forEach(function(layer) { + layer.reverse(); + }); + } + + function width(g, u) { + switch (g.graph().rankDir) { + case 'LR': return g.node(u).height; + case 'RL': return g.node(u).height; + default: return g.node(u).width; + } + } + + function height(g, u) { + switch(g.graph().rankDir) { + case 'LR': return g.node(u).width; + case 'RL': return g.node(u).width; + default: return g.node(u).height; + } + } + + function sep(g, u) { + if (config.universalSep !== null) { + return config.universalSep; + } + var w = width(g, u); + var s = g.node(u).dummy ? config.edgeSep : config.nodeSep; + return (w + s) / 2; + } + + function posX(g, u, x) { + if (g.graph().rankDir === 'LR' || g.graph().rankDir === 'RL') { + if (arguments.length < 3) { + return g.node(u).y; + } else { + g.node(u).y = x; + } + } else { + if (arguments.length < 3) { + return g.node(u).x; + } else { + g.node(u).x = x; + } + } + } + + function posXDebug(name, g, u, x) { + if (g.graph().rankDir === 'LR' || g.graph().rankDir === 'RL') { + if (arguments.length < 3) { + return g.node(u)[name]; + } else { + g.node(u)[name] = x; + } + } else { + if (arguments.length < 3) { + return g.node(u)[name]; + } else { + g.node(u)[name] = x; + } + } + } + + function posY(g, u, y) { + if (g.graph().rankDir === 'LR' || g.graph().rankDir === 'RL') { + if (arguments.length < 3) { + return g.node(u).x; + } else { + g.node(u).x = y; + } + } else { + if (arguments.length < 3) { + return g.node(u).y; + } else { + g.node(u).y = y; + } + } + } + + function debugPositioning(align, g, layering, xs) { + layering.forEach(function(l, li) { + var u, xU; + l.forEach(function(v) { + var xV = xs[v]; + if (u) { + var s = sep(g, u) + sep(g, v); + if (xV - xU < s) + console.log('Position phase: sep violation. Align: ' + align + '. Layer: ' + li + '. ' + + 'U: ' + u + ' V: ' + v + '. Actual sep: ' + (xV - xU) + ' Expected sep: ' + s); + } + u = v; + xU = xV; + }); + }); + } +}; + +},{"./util":27}],20:[function(require,module,exports){ +'use strict'; + +var util = require('./util'), + acyclic = require('./rank/acyclic'), + initRank = require('./rank/initRank'), + feasibleTree = require('./rank/feasibleTree'), + constraints = require('./rank/constraints'), + simplex = require('./rank/simplex'), + components = require('graphlib').alg.components, + filter = require('graphlib').filter; + +exports.run = run; +exports.restoreEdges = restoreEdges; + +/* + * Heuristic function that assigns a rank to each node of the input graph with + * the intent of minimizing edge lengths, while respecting the `minLen` + * attribute of incident edges. + * + * Prerequisites: + * + * * Each edge in the input graph must have an assigned 'minLen' attribute + */ +function run(g, useSimplex) { + expandSelfLoops(g); + + // If there are rank constraints on nodes, then build a new graph that + // encodes the constraints. + util.time('constraints.apply', constraints.apply)(g); + + expandSidewaysEdges(g); + + // Reverse edges to get an acyclic graph, we keep the graph in an acyclic + // state until the very end. + util.time('acyclic', acyclic)(g); + + // Convert the graph into a flat graph for ranking + var flatGraph = g.filterNodes(util.filterNonSubgraphs(g)); + + // Assign an initial ranking using DFS. + initRank(flatGraph); + + // For each component improve the assigned ranks. + components(flatGraph).forEach(function(cmpt) { + var subgraph = flatGraph.filterNodes(filter.nodesFromList(cmpt)); + rankComponent(subgraph, useSimplex); + }); + + // Relax original constraints + util.time('constraints.relax', constraints.relax(g)); + + // When handling nodes with constrained ranks it is possible to end up with + // edges that point to previous ranks. Most of the subsequent algorithms assume + // that edges are pointing to successive ranks only. Here we reverse any "back + // edges" and mark them as such. The acyclic algorithm will reverse them as a + // post processing step. + util.time('reorientEdges', reorientEdges)(g); +} + +function restoreEdges(g) { + acyclic.undo(g); +} + +/* + * Expand self loops into three dummy nodes. One will sit above the incident + * node, one will be at the same level, and one below. The result looks like: + * + * /--<--x--->--\ + * node y + * \--<--z--->--/ + * + * Dummy nodes x, y, z give us the shape of a loop and node y is where we place + * the label. + * + * TODO: consolidate knowledge of dummy node construction. + * TODO: support minLen = 2 + */ +function expandSelfLoops(g) { + g.eachEdge(function(e, u, v, a) { + if (u === v) { + var x = addDummyNode(g, e, u, v, a, 0, false), + y = addDummyNode(g, e, u, v, a, 1, true), + z = addDummyNode(g, e, u, v, a, 2, false); + g.addEdge(null, x, u, {minLen: 1, selfLoop: true}); + g.addEdge(null, x, y, {minLen: 1, selfLoop: true}); + g.addEdge(null, u, z, {minLen: 1, selfLoop: true}); + g.addEdge(null, y, z, {minLen: 1, selfLoop: true}); + g.delEdge(e); + } + }); +} + +function expandSidewaysEdges(g) { + g.eachEdge(function(e, u, v, a) { + if (u === v) { + var origEdge = a.originalEdge, + dummy = addDummyNode(g, origEdge.e, origEdge.u, origEdge.v, origEdge.value, 0, true); + g.addEdge(null, u, dummy, {minLen: 1}); + g.addEdge(null, dummy, v, {minLen: 1}); + g.delEdge(e); + } + }); +} + +function addDummyNode(g, e, u, v, a, index, isLabel) { + return g.addNode(null, { + width: isLabel ? a.width : 0, + height: isLabel ? a.height : 0, + edge: { id: e, source: u, target: v, attrs: a }, + dummy: true, + index: index + }); +} + +function reorientEdges(g) { + g.eachEdge(function(e, u, v, value) { + if (g.node(u).rank > g.node(v).rank) { + g.delEdge(e); + value.reversed = true; + g.addEdge(e, v, u, value); + } + }); +} + +function rankComponent(subgraph, useSimplex) { + var spanningTree = feasibleTree(subgraph); + + if (useSimplex) { + util.log(1, 'Using network simplex for ranking'); + simplex(subgraph, spanningTree); + } + normalize(subgraph); +} + +function normalize(g) { + var m = util.min(g.nodes().map(function(u) { return g.node(u).rank; })); + g.eachNode(function(u, node) { node.rank -= m; }); +} + +},{"./rank/acyclic":21,"./rank/constraints":22,"./rank/feasibleTree":23,"./rank/initRank":24,"./rank/simplex":26,"./util":27,"graphlib":29}],21:[function(require,module,exports){ +'use strict'; + +var util = require('../util'); + +module.exports = acyclic; +module.exports.undo = undo; + +/* + * This function takes a directed graph that may have cycles and reverses edges + * as appropriate to break these cycles. Each reversed edge is assigned a + * `reversed` attribute with the value `true`. + * + * There should be no self loops in the graph. + */ +function acyclic(g) { + var onStack = {}, + visited = {}, + reverseCount = 0; + + function dfs(u) { + if (u in visited) return; + visited[u] = onStack[u] = true; + g.outEdges(u).forEach(function(e) { + var t = g.target(e), + value; + + if (u === t) { + console.error('Warning: found self loop "' + e + '" for node "' + u + '"'); + } else if (t in onStack) { + value = g.edge(e); + g.delEdge(e); + value.reversed = true; + ++reverseCount; + g.addEdge(e, t, u, value); + } else { + dfs(t); + } + }); + + delete onStack[u]; + } + + g.eachNode(function(u) { dfs(u); }); + + util.log(2, 'Acyclic Phase: reversed ' + reverseCount + ' edge(s)'); + + return reverseCount; +} + +/* + * Given a graph that has had the acyclic operation applied, this function + * undoes that operation. More specifically, any edge with the `reversed` + * attribute is again reversed to restore the original direction of the edge. + */ +function undo(g) { + g.eachEdge(function(e, s, t, a) { + if (a.reversed) { + delete a.reversed; + g.delEdge(e); + g.addEdge(e, t, s, a); + } + }); +} + +},{"../util":27}],22:[function(require,module,exports){ +'use strict'; + +exports.apply = function(g) { + function dfs(sg) { + var rankSets = {}; + g.children(sg).forEach(function(u) { + if (g.children(u).length) { + dfs(u); + return; + } + + var value = g.node(u), + prefRank = value.prefRank; + if (prefRank !== undefined) { + if (!checkSupportedPrefRank(prefRank)) { return; } + + if (!(prefRank in rankSets)) { + rankSets.prefRank = [u]; + } else { + rankSets.prefRank.push(u); + } + + var newU = rankSets[prefRank]; + if (newU === undefined) { + newU = rankSets[prefRank] = g.addNode(null, { originalNodes: [] }); + g.parent(newU, sg); + } + + redirectInEdges(g, u, newU, prefRank === 'min'); + redirectOutEdges(g, u, newU, prefRank === 'max'); + + // Save original node and remove it from reduced graph + g.node(newU).originalNodes.push({ u: u, value: value, parent: sg }); + g.delNode(u); + } + }); + + addLightEdgesFromMinNode(g, sg, rankSets.min); + addLightEdgesToMaxNode(g, sg, rankSets.max); + } + + dfs(null); +}; + +function checkSupportedPrefRank(prefRank) { + if (prefRank !== 'min' && prefRank !== 'max' && prefRank.indexOf('same_') !== 0) { + console.error('Unsupported rank type: ' + prefRank); + return false; + } + return true; +} + +function redirectInEdges(g, u, newU, reverse) { + g.inEdges(u).forEach(function(e) { + var origValue = g.edge(e), + value; + if (origValue.originalEdge) { + value = origValue; + } else { + value = { + originalEdge: { e: e, u: g.source(e), v: g.target(e), value: origValue }, + minLen: g.edge(e).minLen + }; + } + + // Do not reverse edges for self-loops. + if (origValue.selfLoop) { + reverse = false; + } + + if (reverse) { + // Ensure that all edges to min are reversed + g.addEdge(null, newU, g.source(e), value); + value.reversed = true; + } else { + g.addEdge(null, g.source(e), newU, value); + } + }); +} + +function redirectOutEdges(g, u, newU, reverse) { + g.outEdges(u).forEach(function(e) { + var origValue = g.edge(e), + value; + if (origValue.originalEdge) { + value = origValue; + } else { + value = { + originalEdge: { e: e, u: g.source(e), v: g.target(e), value: origValue }, + minLen: g.edge(e).minLen + }; + } + + // Do not reverse edges for self-loops. + if (origValue.selfLoop) { + reverse = false; + } + + if (reverse) { + // Ensure that all edges from max are reversed + g.addEdge(null, g.target(e), newU, value); + value.reversed = true; + } else { + g.addEdge(null, newU, g.target(e), value); + } + }); +} + +function addLightEdgesFromMinNode(g, sg, minNode) { + if (minNode !== undefined) { + g.children(sg).forEach(function(u) { + // The dummy check ensures we don't add an edge if the node is involved + // in a self loop or sideways edge. + if (u !== minNode && !g.outEdges(minNode, u).length && !g.node(u).dummy) { + g.addEdge(null, minNode, u, { minLen: 0 }); + } + }); + } +} + +function addLightEdgesToMaxNode(g, sg, maxNode) { + if (maxNode !== undefined) { + g.children(sg).forEach(function(u) { + // The dummy check ensures we don't add an edge if the node is involved + // in a self loop or sideways edge. + if (u !== maxNode && !g.outEdges(u, maxNode).length && !g.node(u).dummy) { + g.addEdge(null, u, maxNode, { minLen: 0 }); + } + }); + } +} + +/* + * This function "relaxes" the constraints applied previously by the "apply" + * function. It expands any nodes that were collapsed and assigns the rank of + * the collapsed node to each of the expanded nodes. It also restores the + * original edges and removes any dummy edges pointing at the collapsed nodes. + * + * Note that the process of removing collapsed nodes also removes dummy edges + * automatically. + */ +exports.relax = function(g) { + // Save original edges + var originalEdges = []; + g.eachEdge(function(e, u, v, value) { + var originalEdge = value.originalEdge; + if (originalEdge) { + originalEdges.push(originalEdge); + } + }); + + // Expand collapsed nodes + g.eachNode(function(u, value) { + var originalNodes = value.originalNodes; + if (originalNodes) { + originalNodes.forEach(function(originalNode) { + originalNode.value.rank = value.rank; + g.addNode(originalNode.u, originalNode.value); + g.parent(originalNode.u, originalNode.parent); + }); + g.delNode(u); + } + }); + + // Restore original edges + originalEdges.forEach(function(edge) { + g.addEdge(edge.e, edge.u, edge.v, edge.value); + }); +}; + +},{}],23:[function(require,module,exports){ +'use strict'; + +/* jshint -W079 */ +var Set = require('cp-data').Set, +/* jshint +W079 */ + Digraph = require('graphlib').Digraph, + util = require('../util'); + +module.exports = feasibleTree; + +/* + * Given an acyclic graph with each node assigned a `rank` attribute, this + * function constructs and returns a spanning tree. This function may reduce + * the length of some edges from the initial rank assignment while maintaining + * the `minLen` specified by each edge. + * + * Prerequisites: + * + * * The input graph is acyclic + * * Each node in the input graph has an assigned `rank` attribute + * * Each edge in the input graph has an assigned `minLen` attribute + * + * Outputs: + * + * A feasible spanning tree for the input graph (i.e. a spanning tree that + * respects each graph edge's `minLen` attribute) represented as a Digraph with + * a `root` attribute on graph. + * + * Nodes have the same id and value as that in the input graph. + * + * Edges in the tree have arbitrarily assigned ids. The attributes for edges + * include `reversed`. `reversed` indicates that the edge is a + * back edge in the input graph. + */ +function feasibleTree(g) { + var remaining = new Set(g.nodes()), + tree = new Digraph(); + + if (remaining.size() === 1) { + var root = g.nodes()[0]; + tree.addNode(root, {}); + tree.graph({ root: root }); + return tree; + } + + function addTightEdges(v) { + var continueToScan = true; + g.predecessors(v).forEach(function(u) { + if (remaining.has(u) && !slack(g, u, v)) { + if (remaining.has(v)) { + tree.addNode(v, {}); + remaining.remove(v); + tree.graph({ root: v }); + } + + tree.addNode(u, {}); + tree.addEdge(null, u, v, { reversed: true }); + remaining.remove(u); + addTightEdges(u); + continueToScan = false; + } + }); + + g.successors(v).forEach(function(w) { + if (remaining.has(w) && !slack(g, v, w)) { + if (remaining.has(v)) { + tree.addNode(v, {}); + remaining.remove(v); + tree.graph({ root: v }); + } + + tree.addNode(w, {}); + tree.addEdge(null, v, w, {}); + remaining.remove(w); + addTightEdges(w); + continueToScan = false; + } + }); + return continueToScan; + } + + function createTightEdge() { + var minSlack = Number.MAX_VALUE; + remaining.keys().forEach(function(v) { + g.predecessors(v).forEach(function(u) { + if (!remaining.has(u)) { + var edgeSlack = slack(g, u, v); + if (Math.abs(edgeSlack) < Math.abs(minSlack)) { + minSlack = -edgeSlack; + } + } + }); + + g.successors(v).forEach(function(w) { + if (!remaining.has(w)) { + var edgeSlack = slack(g, v, w); + if (Math.abs(edgeSlack) < Math.abs(minSlack)) { + minSlack = edgeSlack; + } + } + }); + }); + + tree.eachNode(function(u) { g.node(u).rank -= minSlack; }); + } + + while (remaining.size()) { + var nodesToSearch = !tree.order() ? remaining.keys() : tree.nodes(); + for (var i = 0, il = nodesToSearch.length; + i < il && addTightEdges(nodesToSearch[i]); + ++i); + if (remaining.size()) { + createTightEdge(); + } + } + + return tree; +} + +function slack(g, u, v) { + var rankDiff = g.node(v).rank - g.node(u).rank; + var maxMinLen = util.max(g.outEdges(u, v) + .map(function(e) { return g.edge(e).minLen; })); + return rankDiff - maxMinLen; +} + +},{"../util":27,"cp-data":5,"graphlib":29}],24:[function(require,module,exports){ +'use strict'; + +var util = require('../util'), + topsort = require('graphlib').alg.topsort; + +module.exports = initRank; + +/* + * Assigns a `rank` attribute to each node in the input graph and ensures that + * this rank respects the `minLen` attribute of incident edges. + * + * Prerequisites: + * + * * The input graph must be acyclic + * * Each edge in the input graph must have an assigned 'minLen' attribute + */ +function initRank(g) { + var sorted = topsort(g); + + sorted.forEach(function(u) { + var inEdges = g.inEdges(u); + if (inEdges.length === 0) { + g.node(u).rank = 0; + return; + } + + var minLens = inEdges.map(function(e) { + return g.node(g.source(e)).rank + g.edge(e).minLen; + }); + g.node(u).rank = util.max(minLens); + }); +} + +},{"../util":27,"graphlib":29}],25:[function(require,module,exports){ +'use strict'; + +module.exports = { + slack: slack +}; + +/* + * A helper to calculate the slack between two nodes (`u` and `v`) given a + * `minLen` constraint. The slack represents how much the distance between `u` + * and `v` could shrink while maintaining the `minLen` constraint. If the value + * is negative then the constraint is currently violated. + * + This function requires that `u` and `v` are in `graph` and they both have a + `rank` attribute. + */ +function slack(graph, u, v, minLen) { + return Math.abs(graph.node(u).rank - graph.node(v).rank) - minLen; +} + +},{}],26:[function(require,module,exports){ +'use strict'; + +var util = require('../util'), + rankUtil = require('./rankUtil'); + +module.exports = simplex; + +function simplex(graph, spanningTree) { + // The network simplex algorithm repeatedly replaces edges of + // the spanning tree with negative cut values until no such + // edge exists. + initCutValues(graph, spanningTree); + while (true) { + var e = leaveEdge(spanningTree); + if (e === null) break; + var f = enterEdge(graph, spanningTree, e); + exchange(graph, spanningTree, e, f); + } +} + +/* + * Set the cut values of edges in the spanning tree by a depth-first + * postorder traversal. The cut value corresponds to the cost, in + * terms of a ranking's edge length sum, of lengthening an edge. + * Negative cut values typically indicate edges that would yield a + * smaller edge length sum if they were lengthened. + */ +function initCutValues(graph, spanningTree) { + computeLowLim(spanningTree); + + spanningTree.eachEdge(function(id, u, v, treeValue) { + treeValue.cutValue = 0; + }); + + // Propagate cut values up the tree. + function dfs(n) { + var children = spanningTree.successors(n); + for (var c in children) { + var child = children[c]; + dfs(child); + } + if (n !== spanningTree.graph().root) { + setCutValue(graph, spanningTree, n); + } + } + dfs(spanningTree.graph().root); +} + +/* + * Perform a DFS postorder traversal, labeling each node v with + * its traversal order 'lim(v)' and the minimum traversal number + * of any of its descendants 'low(v)'. This provides an efficient + * way to test whether u is an ancestor of v since + * low(u) <= lim(v) <= lim(u) if and only if u is an ancestor. + */ +function computeLowLim(tree) { + var postOrderNum = 0; + + function dfs(n) { + var children = tree.successors(n); + var low = postOrderNum; + for (var c in children) { + var child = children[c]; + dfs(child); + low = Math.min(low, tree.node(child).low); + } + tree.node(n).low = low; + tree.node(n).lim = postOrderNum++; + } + + dfs(tree.graph().root); +} + +/* + * To compute the cut value of the edge parent -> child, we consider + * it and any other graph edges to or from the child. + * parent + * | + * child + * / \ + * u v + */ +function setCutValue(graph, tree, child) { + var parentEdge = tree.inEdges(child)[0]; + + // List of child's children in the spanning tree. + var grandchildren = []; + var grandchildEdges = tree.outEdges(child); + for (var gce in grandchildEdges) { + grandchildren.push(tree.target(grandchildEdges[gce])); + } + + var cutValue = 0; + + // TODO: Replace unit increment/decrement with edge weights. + var E = 0; // Edges from child to grandchild's subtree. + var F = 0; // Edges to child from grandchild's subtree. + var G = 0; // Edges from child to nodes outside of child's subtree. + var H = 0; // Edges from nodes outside of child's subtree to child. + + // Consider all graph edges from child. + var outEdges = graph.outEdges(child); + var gc; + for (var oe in outEdges) { + var succ = graph.target(outEdges[oe]); + for (gc in grandchildren) { + if (inSubtree(tree, succ, grandchildren[gc])) { + E++; + } + } + if (!inSubtree(tree, succ, child)) { + G++; + } + } + + // Consider all graph edges to child. + var inEdges = graph.inEdges(child); + for (var ie in inEdges) { + var pred = graph.source(inEdges[ie]); + for (gc in grandchildren) { + if (inSubtree(tree, pred, grandchildren[gc])) { + F++; + } + } + if (!inSubtree(tree, pred, child)) { + H++; + } + } + + // Contributions depend on the alignment of the parent -> child edge + // and the child -> u or v edges. + var grandchildCutSum = 0; + for (gc in grandchildren) { + var cv = tree.edge(grandchildEdges[gc]).cutValue; + if (!tree.edge(grandchildEdges[gc]).reversed) { + grandchildCutSum += cv; + } else { + grandchildCutSum -= cv; + } + } + + if (!tree.edge(parentEdge).reversed) { + cutValue += grandchildCutSum - E + F - G + H; + } else { + cutValue -= grandchildCutSum - E + F - G + H; + } + + tree.edge(parentEdge).cutValue = cutValue; +} + +/* + * Return whether n is a node in the subtree with the given + * root. + */ +function inSubtree(tree, n, root) { + return (tree.node(root).low <= tree.node(n).lim && + tree.node(n).lim <= tree.node(root).lim); +} + +/* + * Return an edge from the tree with a negative cut value, or null if there + * is none. + */ +function leaveEdge(tree) { + var edges = tree.edges(); + for (var n in edges) { + var e = edges[n]; + var treeValue = tree.edge(e); + if (treeValue.cutValue < 0) { + return e; + } + } + return null; +} + +/* + * The edge e should be an edge in the tree, with an underlying edge + * in the graph, with a negative cut value. Of the two nodes incident + * on the edge, take the lower one. enterEdge returns an edge with + * minimum slack going from outside of that node's subtree to inside + * of that node's subtree. + */ +function enterEdge(graph, tree, e) { + var source = tree.source(e); + var target = tree.target(e); + var lower = tree.node(target).lim < tree.node(source).lim ? target : source; + + // Is the tree edge aligned with the graph edge? + var aligned = !tree.edge(e).reversed; + + var minSlack = Number.POSITIVE_INFINITY; + var minSlackEdge; + if (aligned) { + graph.eachEdge(function(id, u, v, value) { + if (id !== e && inSubtree(tree, u, lower) && !inSubtree(tree, v, lower)) { + var slack = rankUtil.slack(graph, u, v, value.minLen); + if (slack < minSlack) { + minSlack = slack; + minSlackEdge = id; + } + } + }); + } else { + graph.eachEdge(function(id, u, v, value) { + if (id !== e && !inSubtree(tree, u, lower) && inSubtree(tree, v, lower)) { + var slack = rankUtil.slack(graph, u, v, value.minLen); + if (slack < minSlack) { + minSlack = slack; + minSlackEdge = id; + } + } + }); + } + + if (minSlackEdge === undefined) { + var outside = []; + var inside = []; + graph.eachNode(function(id) { + if (!inSubtree(tree, id, lower)) { + outside.push(id); + } else { + inside.push(id); + } + }); + throw new Error('No edge found from outside of tree to inside'); + } + + return minSlackEdge; +} + +/* + * Replace edge e with edge f in the tree, recalculating the tree root, + * the nodes' low and lim properties and the edges' cut values. + */ +function exchange(graph, tree, e, f) { + tree.delEdge(e); + var source = graph.source(f); + var target = graph.target(f); + + // Redirect edges so that target is the root of its subtree. + function redirect(v) { + var edges = tree.inEdges(v); + for (var i in edges) { + var e = edges[i]; + var u = tree.source(e); + var value = tree.edge(e); + redirect(u); + tree.delEdge(e); + value.reversed = !value.reversed; + tree.addEdge(e, v, u, value); + } + } + + redirect(target); + + var root = source; + var edges = tree.inEdges(root); + while (edges.length > 0) { + root = tree.source(edges[0]); + edges = tree.inEdges(root); + } + + tree.graph().root = root; + + tree.addEdge(null, source, target, {cutValue: 0}); + + initCutValues(graph, tree); + + adjustRanks(graph, tree); +} + +/* + * Reset the ranks of all nodes based on the current spanning tree. + * The rank of the tree's root remains unchanged, while all other + * nodes are set to the sum of minimum length constraints along + * the path from the root. + */ +function adjustRanks(graph, tree) { + function dfs(p) { + var children = tree.successors(p); + children.forEach(function(c) { + var minLen = minimumLength(graph, p, c); + graph.node(c).rank = graph.node(p).rank + minLen; + dfs(c); + }); + } + + dfs(tree.graph().root); +} + +/* + * If u and v are connected by some edges in the graph, return the + * minimum length of those edges, as a positive number if v succeeds + * u and as a negative number if v precedes u. + */ +function minimumLength(graph, u, v) { + var outEdges = graph.outEdges(u, v); + if (outEdges.length > 0) { + return util.max(outEdges.map(function(e) { + return graph.edge(e).minLen; + })); + } + + var inEdges = graph.inEdges(u, v); + if (inEdges.length > 0) { + return -util.max(inEdges.map(function(e) { + return graph.edge(e).minLen; + })); + } +} + +},{"../util":27,"./rankUtil":25}],27:[function(require,module,exports){ +'use strict'; + +/* + * Returns the smallest value in the array. + */ +exports.min = function(values) { + return Math.min.apply(Math, values); +}; + +/* + * Returns the largest value in the array. + */ +exports.max = function(values) { + return Math.max.apply(Math, values); +}; + +/* + * Returns `true` only if `f(x)` is `true` for all `x` in `xs`. Otherwise + * returns `false`. This function will return immediately if it finds a + * case where `f(x)` does not hold. + */ +exports.all = function(xs, f) { + for (var i = 0; i < xs.length; ++i) { + if (!f(xs[i])) { + return false; + } + } + return true; +}; + +/* + * Accumulates the sum of elements in the given array using the `+` operator. + */ +exports.sum = function(values) { + return values.reduce(function(acc, x) { return acc + x; }, 0); +}; + +/* + * Returns an array of all values in the given object. + */ +exports.values = function(obj) { + return Object.keys(obj).map(function(k) { return obj[k]; }); +}; + +exports.shuffle = function(array) { + for (var i = array.length - 1; i > 0; --i) { + var j = Math.floor(Math.random() * (i + 1)); + var aj = array[j]; + array[j] = array[i]; + array[i] = aj; + } +}; + +exports.propertyAccessor = function(self, config, field, setHook) { + return function(x) { + if (!arguments.length) return config[field]; + config[field] = x; + if (setHook) setHook(x); + return self; + }; +}; + +/* + * Given a layered, directed graph with `rank` and `order` node attributes, + * this function returns an array of ordered ranks. Each rank contains an array + * of the ids of the nodes in that rank in the order specified by the `order` + * attribute. + */ +exports.ordering = function(g) { + var ordering = []; + g.eachNode(function(u, value) { + var rank = ordering[value.rank] || (ordering[value.rank] = []); + rank[value.order] = u; + }); + return ordering; +}; + +/* + * A filter that can be used with `filterNodes` to get a graph that only + * includes nodes that do not contain others nodes. + */ +exports.filterNonSubgraphs = function(g) { + return function(u) { + return g.children(u).length === 0; + }; +}; + +/* + * Returns a new function that wraps `func` with a timer. The wrapper logs the + * time it takes to execute the function. + * + * The timer will be enabled provided `log.level >= 1`. + */ +function time(name, func) { + return function() { + var start = new Date().getTime(); + try { + return func.apply(null, arguments); + } finally { + log(1, name + ' time: ' + (new Date().getTime() - start) + 'ms'); + } + }; +} +time.enabled = false; + +exports.time = time; + +/* + * A global logger with the specification `log(level, message, ...)` that + * will log a message to the console if `log.level >= level`. + */ +function log(level) { + if (log.level >= level) { + console.log.apply(console, Array.prototype.slice.call(arguments, 1)); + } +} +log.level = 0; + +exports.log = log; + +},{}],28:[function(require,module,exports){ +module.exports = '0.4.6'; + +},{}],29:[function(require,module,exports){ +exports.Graph = require("./lib/Graph"); +exports.Digraph = require("./lib/Digraph"); +exports.CGraph = require("./lib/CGraph"); +exports.CDigraph = require("./lib/CDigraph"); +require("./lib/graph-converters"); + +exports.alg = { + isAcyclic: require("./lib/alg/isAcyclic"), + components: require("./lib/alg/components"), + dijkstra: require("./lib/alg/dijkstra"), + dijkstraAll: require("./lib/alg/dijkstraAll"), + findCycles: require("./lib/alg/findCycles"), + floydWarshall: require("./lib/alg/floydWarshall"), + postorder: require("./lib/alg/postorder"), + preorder: require("./lib/alg/preorder"), + prim: require("./lib/alg/prim"), + tarjan: require("./lib/alg/tarjan"), + topsort: require("./lib/alg/topsort") +}; + +exports.converter = { + json: require("./lib/converter/json.js") +}; + +var filter = require("./lib/filter"); +exports.filter = { + all: filter.all, + nodesFromList: filter.nodesFromList +}; + +exports.version = require("./lib/version"); + +},{"./lib/CDigraph":31,"./lib/CGraph":32,"./lib/Digraph":33,"./lib/Graph":34,"./lib/alg/components":35,"./lib/alg/dijkstra":36,"./lib/alg/dijkstraAll":37,"./lib/alg/findCycles":38,"./lib/alg/floydWarshall":39,"./lib/alg/isAcyclic":40,"./lib/alg/postorder":41,"./lib/alg/preorder":42,"./lib/alg/prim":43,"./lib/alg/tarjan":44,"./lib/alg/topsort":45,"./lib/converter/json.js":47,"./lib/filter":48,"./lib/graph-converters":49,"./lib/version":51}],30:[function(require,module,exports){ +/* jshint -W079 */ +var Set = require("cp-data").Set; +/* jshint +W079 */ + +module.exports = BaseGraph; + +function BaseGraph() { + // The value assigned to the graph itself. + this._value = undefined; + + // Map of node id -> { id, value } + this._nodes = {}; + + // Map of edge id -> { id, u, v, value } + this._edges = {}; + + // Used to generate a unique id in the graph + this._nextId = 0; +} + +// Number of nodes +BaseGraph.prototype.order = function() { + return Object.keys(this._nodes).length; +}; + +// Number of edges +BaseGraph.prototype.size = function() { + return Object.keys(this._edges).length; +}; + +// Accessor for graph level value +BaseGraph.prototype.graph = function(value) { + if (arguments.length === 0) { + return this._value; + } + this._value = value; +}; + +BaseGraph.prototype.hasNode = function(u) { + return u in this._nodes; +}; + +BaseGraph.prototype.node = function(u, value) { + var node = this._strictGetNode(u); + if (arguments.length === 1) { + return node.value; + } + node.value = value; +}; + +BaseGraph.prototype.nodes = function() { + var nodes = []; + this.eachNode(function(id) { nodes.push(id); }); + return nodes; +}; + +BaseGraph.prototype.eachNode = function(func) { + for (var k in this._nodes) { + var node = this._nodes[k]; + func(node.id, node.value); + } +}; + +BaseGraph.prototype.hasEdge = function(e) { + return e in this._edges; +}; + +BaseGraph.prototype.edge = function(e, value) { + var edge = this._strictGetEdge(e); + if (arguments.length === 1) { + return edge.value; + } + edge.value = value; +}; + +BaseGraph.prototype.edges = function() { + var es = []; + this.eachEdge(function(id) { es.push(id); }); + return es; +}; + +BaseGraph.prototype.eachEdge = function(func) { + for (var k in this._edges) { + var edge = this._edges[k]; + func(edge.id, edge.u, edge.v, edge.value); + } +}; + +BaseGraph.prototype.incidentNodes = function(e) { + var edge = this._strictGetEdge(e); + return [edge.u, edge.v]; +}; + +BaseGraph.prototype.addNode = function(u, value) { + if (u === undefined || u === null) { + do { + u = "_" + (++this._nextId); + } while (this.hasNode(u)); + } else if (this.hasNode(u)) { + throw new Error("Graph already has node '" + u + "'"); + } + this._nodes[u] = { id: u, value: value }; + return u; +}; + +BaseGraph.prototype.delNode = function(u) { + this._strictGetNode(u); + this.incidentEdges(u).forEach(function(e) { this.delEdge(e); }, this); + delete this._nodes[u]; +}; + +// inMap and outMap are opposite sides of an incidence map. For example, for +// Graph these would both come from the _incidentEdges map, while for Digraph +// they would come from _inEdges and _outEdges. +BaseGraph.prototype._addEdge = function(e, u, v, value, inMap, outMap) { + this._strictGetNode(u); + this._strictGetNode(v); + + if (e === undefined || e === null) { + do { + e = "_" + (++this._nextId); + } while (this.hasEdge(e)); + } + else if (this.hasEdge(e)) { + throw new Error("Graph already has edge '" + e + "'"); + } + + this._edges[e] = { id: e, u: u, v: v, value: value }; + addEdgeToMap(inMap[v], u, e); + addEdgeToMap(outMap[u], v, e); + + return e; +}; + +// See note for _addEdge regarding inMap and outMap. +BaseGraph.prototype._delEdge = function(e, inMap, outMap) { + var edge = this._strictGetEdge(e); + delEdgeFromMap(inMap[edge.v], edge.u, e); + delEdgeFromMap(outMap[edge.u], edge.v, e); + delete this._edges[e]; +}; + +BaseGraph.prototype.copy = function() { + var copy = new this.constructor(); + copy.graph(this.graph()); + this.eachNode(function(u, value) { copy.addNode(u, value); }); + this.eachEdge(function(e, u, v, value) { copy.addEdge(e, u, v, value); }); + copy._nextId = this._nextId; + return copy; +}; + +BaseGraph.prototype.filterNodes = function(filter) { + var copy = new this.constructor(); + copy.graph(this.graph()); + this.eachNode(function(u, value) { + if (filter(u)) { + copy.addNode(u, value); + } + }); + this.eachEdge(function(e, u, v, value) { + if (copy.hasNode(u) && copy.hasNode(v)) { + copy.addEdge(e, u, v, value); + } + }); + return copy; +}; + +BaseGraph.prototype._strictGetNode = function(u) { + var node = this._nodes[u]; + if (node === undefined) { + throw new Error("Node '" + u + "' is not in graph"); + } + return node; +}; + +BaseGraph.prototype._strictGetEdge = function(e) { + var edge = this._edges[e]; + if (edge === undefined) { + throw new Error("Edge '" + e + "' is not in graph"); + } + return edge; +}; + +function addEdgeToMap(map, v, e) { + (map[v] || (map[v] = new Set())).add(e); +} + +function delEdgeFromMap(map, v, e) { + var vEntry = map[v]; + vEntry.remove(e); + if (vEntry.size() === 0) { + delete map[v]; + } +} + + +},{"cp-data":5}],31:[function(require,module,exports){ +var Digraph = require("./Digraph"), + compoundify = require("./compoundify"); + +var CDigraph = compoundify(Digraph); + +module.exports = CDigraph; + +CDigraph.fromDigraph = function(src) { + var g = new CDigraph(), + graphValue = src.graph(); + + if (graphValue !== undefined) { + g.graph(graphValue); + } + + src.eachNode(function(u, value) { + if (value === undefined) { + g.addNode(u); + } else { + g.addNode(u, value); + } + }); + src.eachEdge(function(e, u, v, value) { + if (value === undefined) { + g.addEdge(null, u, v); + } else { + g.addEdge(null, u, v, value); + } + }); + return g; +}; + +CDigraph.prototype.toString = function() { + return "CDigraph " + JSON.stringify(this, null, 2); +}; + +},{"./Digraph":33,"./compoundify":46}],32:[function(require,module,exports){ +var Graph = require("./Graph"), + compoundify = require("./compoundify"); + +var CGraph = compoundify(Graph); + +module.exports = CGraph; + +CGraph.fromGraph = function(src) { + var g = new CGraph(), + graphValue = src.graph(); + + if (graphValue !== undefined) { + g.graph(graphValue); + } + + src.eachNode(function(u, value) { + if (value === undefined) { + g.addNode(u); + } else { + g.addNode(u, value); + } + }); + src.eachEdge(function(e, u, v, value) { + if (value === undefined) { + g.addEdge(null, u, v); + } else { + g.addEdge(null, u, v, value); + } + }); + return g; +}; + +CGraph.prototype.toString = function() { + return "CGraph " + JSON.stringify(this, null, 2); +}; + +},{"./Graph":34,"./compoundify":46}],33:[function(require,module,exports){ +/* + * This file is organized with in the following order: + * + * Exports + * Graph constructors + * Graph queries (e.g. nodes(), edges() + * Graph mutators + * Helper functions + */ + +var util = require("./util"), + BaseGraph = require("./BaseGraph"), +/* jshint -W079 */ + Set = require("cp-data").Set; +/* jshint +W079 */ + +module.exports = Digraph; + +/* + * Constructor to create a new directed multi-graph. + */ +function Digraph() { + BaseGraph.call(this); + + /*! Map of sourceId -> {targetId -> Set of edge ids} */ + this._inEdges = {}; + + /*! Map of targetId -> {sourceId -> Set of edge ids} */ + this._outEdges = {}; +} + +Digraph.prototype = new BaseGraph(); +Digraph.prototype.constructor = Digraph; + +/* + * Always returns `true`. + */ +Digraph.prototype.isDirected = function() { + return true; +}; + +/* + * Returns all successors of the node with the id `u`. That is, all nodes + * that have the node `u` as their source are returned. + * + * If no node `u` exists in the graph this function throws an Error. + * + * @param {String} u a node id + */ +Digraph.prototype.successors = function(u) { + this._strictGetNode(u); + return Object.keys(this._outEdges[u]) + .map(function(v) { return this._nodes[v].id; }, this); +}; + +/* + * Returns all predecessors of the node with the id `u`. That is, all nodes + * that have the node `u` as their target are returned. + * + * If no node `u` exists in the graph this function throws an Error. + * + * @param {String} u a node id + */ +Digraph.prototype.predecessors = function(u) { + this._strictGetNode(u); + return Object.keys(this._inEdges[u]) + .map(function(v) { return this._nodes[v].id; }, this); +}; + +/* + * Returns all nodes that are adjacent to the node with the id `u`. In other + * words, this function returns the set of all successors and predecessors of + * node `u`. + * + * @param {String} u a node id + */ +Digraph.prototype.neighbors = function(u) { + return Set.union([this.successors(u), this.predecessors(u)]).keys(); +}; + +/* + * Returns all nodes in the graph that have no in-edges. + */ +Digraph.prototype.sources = function() { + var self = this; + return this._filterNodes(function(u) { + // This could have better space characteristics if we had an inDegree function. + return self.inEdges(u).length === 0; + }); +}; + +/* + * Returns all nodes in the graph that have no out-edges. + */ +Digraph.prototype.sinks = function() { + var self = this; + return this._filterNodes(function(u) { + // This could have better space characteristics if we have an outDegree function. + return self.outEdges(u).length === 0; + }); +}; + +/* + * Returns the source node incident on the edge identified by the id `e`. If no + * such edge exists in the graph this function throws an Error. + * + * @param {String} e an edge id + */ +Digraph.prototype.source = function(e) { + return this._strictGetEdge(e).u; +}; + +/* + * Returns the target node incident on the edge identified by the id `e`. If no + * such edge exists in the graph this function throws an Error. + * + * @param {String} e an edge id + */ +Digraph.prototype.target = function(e) { + return this._strictGetEdge(e).v; +}; + +/* + * Returns an array of ids for all edges in the graph that have the node + * `target` as their target. If the node `target` is not in the graph this + * function raises an Error. + * + * Optionally a `source` node can also be specified. This causes the results + * to be filtered such that only edges from `source` to `target` are included. + * If the node `source` is specified but is not in the graph then this function + * raises an Error. + * + * @param {String} target the target node id + * @param {String} [source] an optional source node id + */ +Digraph.prototype.inEdges = function(target, source) { + this._strictGetNode(target); + var results = Set.union(util.values(this._inEdges[target])).keys(); + if (arguments.length > 1) { + this._strictGetNode(source); + results = results.filter(function(e) { return this.source(e) === source; }, this); + } + return results; +}; + +/* + * Returns an array of ids for all edges in the graph that have the node + * `source` as their source. If the node `source` is not in the graph this + * function raises an Error. + * + * Optionally a `target` node may also be specified. This causes the results + * to be filtered such that only edges from `source` to `target` are included. + * If the node `target` is specified but is not in the graph then this function + * raises an Error. + * + * @param {String} source the source node id + * @param {String} [target] an optional target node id + */ +Digraph.prototype.outEdges = function(source, target) { + this._strictGetNode(source); + var results = Set.union(util.values(this._outEdges[source])).keys(); + if (arguments.length > 1) { + this._strictGetNode(target); + results = results.filter(function(e) { return this.target(e) === target; }, this); + } + return results; +}; + +/* + * Returns an array of ids for all edges in the graph that have the `u` as + * their source or their target. If the node `u` is not in the graph this + * function raises an Error. + * + * Optionally a `v` node may also be specified. This causes the results to be + * filtered such that only edges between `u` and `v` - in either direction - + * are included. IF the node `v` is specified but not in the graph then this + * function raises an Error. + * + * @param {String} u the node for which to find incident edges + * @param {String} [v] option node that must be adjacent to `u` + */ +Digraph.prototype.incidentEdges = function(u, v) { + if (arguments.length > 1) { + return Set.union([this.outEdges(u, v), this.outEdges(v, u)]).keys(); + } else { + return Set.union([this.inEdges(u), this.outEdges(u)]).keys(); + } +}; + +/* + * Returns a string representation of this graph. + */ +Digraph.prototype.toString = function() { + return "Digraph " + JSON.stringify(this, null, 2); +}; + +/* + * Adds a new node with the id `u` to the graph and assigns it the value + * `value`. If a node with the id is already a part of the graph this function + * throws an Error. + * + * @param {String} u a node id + * @param {Object} [value] an optional value to attach to the node + */ +Digraph.prototype.addNode = function(u, value) { + u = BaseGraph.prototype.addNode.call(this, u, value); + this._inEdges[u] = {}; + this._outEdges[u] = {}; + return u; +}; + +/* + * Removes a node from the graph that has the id `u`. Any edges incident on the + * node are also removed. If the graph does not contain a node with the id this + * function will throw an Error. + * + * @param {String} u a node id + */ +Digraph.prototype.delNode = function(u) { + BaseGraph.prototype.delNode.call(this, u); + delete this._inEdges[u]; + delete this._outEdges[u]; +}; + +/* + * Adds a new edge to the graph with the id `e` from a node with the id `source` + * to a node with an id `target` and assigns it the value `value`. This graph + * allows more than one edge from `source` to `target` as long as the id `e` + * is unique in the set of edges. If `e` is `null` the graph will assign a + * unique identifier to the edge. + * + * If `source` or `target` are not present in the graph this function will + * throw an Error. + * + * @param {String} [e] an edge id + * @param {String} source the source node id + * @param {String} target the target node id + * @param {Object} [value] an optional value to attach to the edge + */ +Digraph.prototype.addEdge = function(e, source, target, value) { + return BaseGraph.prototype._addEdge.call(this, e, source, target, value, + this._inEdges, this._outEdges); +}; + +/* + * Removes an edge in the graph with the id `e`. If no edge in the graph has + * the id `e` this function will throw an Error. + * + * @param {String} e an edge id + */ +Digraph.prototype.delEdge = function(e) { + BaseGraph.prototype._delEdge.call(this, e, this._inEdges, this._outEdges); +}; + +// Unlike BaseGraph.filterNodes, this helper just returns nodes that +// satisfy a predicate. +Digraph.prototype._filterNodes = function(pred) { + var filtered = []; + this.eachNode(function(u) { + if (pred(u)) { + filtered.push(u); + } + }); + return filtered; +}; + + +},{"./BaseGraph":30,"./util":50,"cp-data":5}],34:[function(require,module,exports){ +/* + * This file is organized with in the following order: + * + * Exports + * Graph constructors + * Graph queries (e.g. nodes(), edges() + * Graph mutators + * Helper functions + */ + +var util = require("./util"), + BaseGraph = require("./BaseGraph"), +/* jshint -W079 */ + Set = require("cp-data").Set; +/* jshint +W079 */ + +module.exports = Graph; + +/* + * Constructor to create a new undirected multi-graph. + */ +function Graph() { + BaseGraph.call(this); + + /*! Map of nodeId -> { otherNodeId -> Set of edge ids } */ + this._incidentEdges = {}; +} + +Graph.prototype = new BaseGraph(); +Graph.prototype.constructor = Graph; + +/* + * Always returns `false`. + */ +Graph.prototype.isDirected = function() { + return false; +}; + +/* + * Returns all nodes that are adjacent to the node with the id `u`. + * + * @param {String} u a node id + */ +Graph.prototype.neighbors = function(u) { + this._strictGetNode(u); + return Object.keys(this._incidentEdges[u]) + .map(function(v) { return this._nodes[v].id; }, this); +}; + +/* + * Returns an array of ids for all edges in the graph that are incident on `u`. + * If the node `u` is not in the graph this function raises an Error. + * + * Optionally a `v` node may also be specified. This causes the results to be + * filtered such that only edges between `u` and `v` are included. If the node + * `v` is specified but not in the graph then this function raises an Error. + * + * @param {String} u the node for which to find incident edges + * @param {String} [v] option node that must be adjacent to `u` + */ +Graph.prototype.incidentEdges = function(u, v) { + this._strictGetNode(u); + if (arguments.length > 1) { + this._strictGetNode(v); + return v in this._incidentEdges[u] ? this._incidentEdges[u][v].keys() : []; + } else { + return Set.union(util.values(this._incidentEdges[u])).keys(); + } +}; + +/* + * Returns a string representation of this graph. + */ +Graph.prototype.toString = function() { + return "Graph " + JSON.stringify(this, null, 2); +}; + +/* + * Adds a new node with the id `u` to the graph and assigns it the value + * `value`. If a node with the id is already a part of the graph this function + * throws an Error. + * + * @param {String} u a node id + * @param {Object} [value] an optional value to attach to the node + */ +Graph.prototype.addNode = function(u, value) { + u = BaseGraph.prototype.addNode.call(this, u, value); + this._incidentEdges[u] = {}; + return u; +}; + +/* + * Removes a node from the graph that has the id `u`. Any edges incident on the + * node are also removed. If the graph does not contain a node with the id this + * function will throw an Error. + * + * @param {String} u a node id + */ +Graph.prototype.delNode = function(u) { + BaseGraph.prototype.delNode.call(this, u); + delete this._incidentEdges[u]; +}; + +/* + * Adds a new edge to the graph with the id `e` between a node with the id `u` + * and a node with an id `v` and assigns it the value `value`. This graph + * allows more than one edge between `u` and `v` as long as the id `e` + * is unique in the set of edges. If `e` is `null` the graph will assign a + * unique identifier to the edge. + * + * If `u` or `v` are not present in the graph this function will throw an + * Error. + * + * @param {String} [e] an edge id + * @param {String} u the node id of one of the adjacent nodes + * @param {String} v the node id of the other adjacent node + * @param {Object} [value] an optional value to attach to the edge + */ +Graph.prototype.addEdge = function(e, u, v, value) { + return BaseGraph.prototype._addEdge.call(this, e, u, v, value, + this._incidentEdges, this._incidentEdges); +}; + +/* + * Removes an edge in the graph with the id `e`. If no edge in the graph has + * the id `e` this function will throw an Error. + * + * @param {String} e an edge id + */ +Graph.prototype.delEdge = function(e) { + BaseGraph.prototype._delEdge.call(this, e, this._incidentEdges, this._incidentEdges); +}; + + +},{"./BaseGraph":30,"./util":50,"cp-data":5}],35:[function(require,module,exports){ +/* jshint -W079 */ +var Set = require("cp-data").Set; +/* jshint +W079 */ + +module.exports = components; + +/** + * Finds all [connected components][] in a graph and returns an array of these + * components. Each component is itself an array that contains the ids of nodes + * in the component. + * + * This function only works with undirected Graphs. + * + * [connected components]: http://en.wikipedia.org/wiki/Connected_component_(graph_theory) + * + * @param {Graph} g the graph to search for components + */ +function components(g) { + var results = []; + var visited = new Set(); + + function dfs(v, component) { + if (!visited.has(v)) { + visited.add(v); + component.push(v); + g.neighbors(v).forEach(function(w) { + dfs(w, component); + }); + } + } + + g.nodes().forEach(function(v) { + var component = []; + dfs(v, component); + if (component.length > 0) { + results.push(component); + } + }); + + return results; +} + +},{"cp-data":5}],36:[function(require,module,exports){ +var PriorityQueue = require("cp-data").PriorityQueue; + +module.exports = dijkstra; + +/** + * This function is an implementation of [Dijkstra's algorithm][] which finds + * the shortest path from **source** to all other nodes in **g**. This + * function returns a map of `u -> { distance, predecessor }`. The distance + * property holds the sum of the weights from **source** to `u` along the + * shortest path or `Number.POSITIVE_INFINITY` if there is no path from + * **source**. The predecessor property can be used to walk the individual + * elements of the path from **source** to **u** in reverse order. + * + * This function takes an optional `weightFunc(e)` which returns the + * weight of the edge `e`. If no weightFunc is supplied then each edge is + * assumed to have a weight of 1. This function throws an Error if any of + * the traversed edges have a negative edge weight. + * + * This function takes an optional `incidentFunc(u)` which returns the ids of + * all edges incident to the node `u` for the purposes of shortest path + * traversal. By default this function uses the `g.outEdges` for Digraphs and + * `g.incidentEdges` for Graphs. + * + * This function takes `O((|E| + |V|) * log |V|)` time. + * + * [Dijkstra's algorithm]: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm + * + * @param {Graph} g the graph to search for shortest paths from **source** + * @param {Object} source the source from which to start the search + * @param {Function} [weightFunc] optional weight function + * @param {Function} [incidentFunc] optional incident function + */ +function dijkstra(g, source, weightFunc, incidentFunc) { + var results = {}, + pq = new PriorityQueue(); + + function updateNeighbors(e) { + var incidentNodes = g.incidentNodes(e), + v = incidentNodes[0] !== u ? incidentNodes[0] : incidentNodes[1], + vEntry = results[v], + weight = weightFunc(e), + distance = uEntry.distance + weight; + + if (weight < 0) { + throw new Error("dijkstra does not allow negative edge weights. Bad edge: " + e + " Weight: " + weight); + } + + if (distance < vEntry.distance) { + vEntry.distance = distance; + vEntry.predecessor = u; + pq.decrease(v, distance); + } + } + + weightFunc = weightFunc || function() { return 1; }; + incidentFunc = incidentFunc || (g.isDirected() + ? function(u) { return g.outEdges(u); } + : function(u) { return g.incidentEdges(u); }); + + g.eachNode(function(u) { + var distance = u === source ? 0 : Number.POSITIVE_INFINITY; + results[u] = { distance: distance }; + pq.add(u, distance); + }); + + var u, uEntry; + while (pq.size() > 0) { + u = pq.removeMin(); + uEntry = results[u]; + if (uEntry.distance === Number.POSITIVE_INFINITY) { + break; + } + + incidentFunc(u).forEach(updateNeighbors); + } + + return results; +} + +},{"cp-data":5}],37:[function(require,module,exports){ +var dijkstra = require("./dijkstra"); + +module.exports = dijkstraAll; + +/** + * This function finds the shortest path from each node to every other + * reachable node in the graph. It is similar to [alg.dijkstra][], but + * instead of returning a single-source array, it returns a mapping of + * of `source -> alg.dijksta(g, source, weightFunc, incidentFunc)`. + * + * This function takes an optional `weightFunc(e)` which returns the + * weight of the edge `e`. If no weightFunc is supplied then each edge is + * assumed to have a weight of 1. This function throws an Error if any of + * the traversed edges have a negative edge weight. + * + * This function takes an optional `incidentFunc(u)` which returns the ids of + * all edges incident to the node `u` for the purposes of shortest path + * traversal. By default this function uses the `outEdges` function on the + * supplied graph. + * + * This function takes `O(|V| * (|E| + |V|) * log |V|)` time. + * + * [alg.dijkstra]: dijkstra.js.html#dijkstra + * + * @param {Graph} g the graph to search for shortest paths from **source** + * @param {Function} [weightFunc] optional weight function + * @param {Function} [incidentFunc] optional incident function + */ +function dijkstraAll(g, weightFunc, incidentFunc) { + var results = {}; + g.eachNode(function(u) { + results[u] = dijkstra(g, u, weightFunc, incidentFunc); + }); + return results; +} + +},{"./dijkstra":36}],38:[function(require,module,exports){ +var tarjan = require("./tarjan"); + +module.exports = findCycles; + +/* + * Given a Digraph **g** this function returns all nodes that are part of a + * cycle. Since there may be more than one cycle in a graph this function + * returns an array of these cycles, where each cycle is itself represented + * by an array of ids for each node involved in that cycle. + * + * [alg.isAcyclic][] is more efficient if you only need to determine whether + * a graph has a cycle or not. + * + * [alg.isAcyclic]: isAcyclic.js.html#isAcyclic + * + * @param {Digraph} g the graph to search for cycles. + */ +function findCycles(g) { + return tarjan(g).filter(function(cmpt) { return cmpt.length > 1; }); +} + +},{"./tarjan":44}],39:[function(require,module,exports){ +module.exports = floydWarshall; + +/** + * This function is an implementation of the [Floyd-Warshall algorithm][], + * which finds the shortest path from each node to every other reachable node + * in the graph. It is similar to [alg.dijkstraAll][], but it handles negative + * edge weights and is more efficient for some types of graphs. This function + * returns a map of `source -> { target -> { distance, predecessor }`. The + * distance property holds the sum of the weights from `source` to `target` + * along the shortest path of `Number.POSITIVE_INFINITY` if there is no path + * from `source`. The predecessor property can be used to walk the individual + * elements of the path from `source` to `target` in reverse order. + * + * This function takes an optional `weightFunc(e)` which returns the + * weight of the edge `e`. If no weightFunc is supplied then each edge is + * assumed to have a weight of 1. + * + * This function takes an optional `incidentFunc(u)` which returns the ids of + * all edges incident to the node `u` for the purposes of shortest path + * traversal. By default this function uses the `outEdges` function on the + * supplied graph. + * + * This algorithm takes O(|V|^3) time. + * + * [Floyd-Warshall algorithm]: https://en.wikipedia.org/wiki/Floyd-Warshall_algorithm + * [alg.dijkstraAll]: dijkstraAll.js.html#dijkstraAll + * + * @param {Graph} g the graph to search for shortest paths from **source** + * @param {Function} [weightFunc] optional weight function + * @param {Function} [incidentFunc] optional incident function + */ +function floydWarshall(g, weightFunc, incidentFunc) { + var results = {}, + nodes = g.nodes(); + + weightFunc = weightFunc || function() { return 1; }; + incidentFunc = incidentFunc || (g.isDirected() + ? function(u) { return g.outEdges(u); } + : function(u) { return g.incidentEdges(u); }); + + nodes.forEach(function(u) { + results[u] = {}; + results[u][u] = { distance: 0 }; + nodes.forEach(function(v) { + if (u !== v) { + results[u][v] = { distance: Number.POSITIVE_INFINITY }; + } + }); + incidentFunc(u).forEach(function(e) { + var incidentNodes = g.incidentNodes(e), + v = incidentNodes[0] !== u ? incidentNodes[0] : incidentNodes[1], + d = weightFunc(e); + if (d < results[u][v].distance) { + results[u][v] = { distance: d, predecessor: u }; + } + }); + }); + + nodes.forEach(function(k) { + var rowK = results[k]; + nodes.forEach(function(i) { + var rowI = results[i]; + nodes.forEach(function(j) { + var ik = rowI[k]; + var kj = rowK[j]; + var ij = rowI[j]; + var altDistance = ik.distance + kj.distance; + if (altDistance < ij.distance) { + ij.distance = altDistance; + ij.predecessor = kj.predecessor; + } + }); + }); + }); + + return results; +} + +},{}],40:[function(require,module,exports){ +var topsort = require("./topsort"); + +module.exports = isAcyclic; + +/* + * Given a Digraph **g** this function returns `true` if the graph has no + * cycles and returns `false` if it does. This algorithm returns as soon as it + * detects the first cycle. + * + * Use [alg.findCycles][] if you need the actual list of cycles in a graph. + * + * [alg.findCycles]: findCycles.js.html#findCycles + * + * @param {Digraph} g the graph to test for cycles + */ +function isAcyclic(g) { + try { + topsort(g); + } catch (e) { + if (e instanceof topsort.CycleException) return false; + throw e; + } + return true; +} + +},{"./topsort":45}],41:[function(require,module,exports){ +/* jshint -W079 */ +var Set = require("cp-data").Set; +/* jshint +W079 */ + +module.exports = postorder; + +// Postorder traversal of g, calling f for each visited node. Assumes the graph +// is a tree. +function postorder(g, root, f) { + var visited = new Set(); + if (g.isDirected()) { + throw new Error("This function only works for undirected graphs"); + } + function dfs(u, prev) { + if (visited.has(u)) { + throw new Error("The input graph is not a tree: " + g); + } + visited.add(u); + g.neighbors(u).forEach(function(v) { + if (v !== prev) dfs(v, u); + }); + f(u); + } + dfs(root); +} + +},{"cp-data":5}],42:[function(require,module,exports){ +/* jshint -W079 */ +var Set = require("cp-data").Set; +/* jshint +W079 */ + +module.exports = preorder; + +// Preorder traversal of g, calling f for each visited node. Assumes the graph +// is a tree. +function preorder(g, root, f) { + var visited = new Set(); + if (g.isDirected()) { + throw new Error("This function only works for undirected graphs"); + } + function dfs(u, prev) { + if (visited.has(u)) { + throw new Error("The input graph is not a tree: " + g); + } + visited.add(u); + f(u); + g.neighbors(u).forEach(function(v) { + if (v !== prev) dfs(v, u); + }); + } + dfs(root); +} + +},{"cp-data":5}],43:[function(require,module,exports){ +var Graph = require("../Graph"), + PriorityQueue = require("cp-data").PriorityQueue; + +module.exports = prim; + +/** + * [Prim's algorithm][] takes a connected undirected graph and generates a + * [minimum spanning tree][]. This function returns the minimum spanning + * tree as an undirected graph. This algorithm is derived from the description + * in "Introduction to Algorithms", Third Edition, Cormen, et al., Pg 634. + * + * This function takes a `weightFunc(e)` which returns the weight of the edge + * `e`. It throws an Error if the graph is not connected. + * + * This function takes `O(|E| log |V|)` time. + * + * [Prim's algorithm]: https://en.wikipedia.org/wiki/Prim's_algorithm + * [minimum spanning tree]: https://en.wikipedia.org/wiki/Minimum_spanning_tree + * + * @param {Graph} g the graph used to generate the minimum spanning tree + * @param {Function} weightFunc the weight function to use + */ +function prim(g, weightFunc) { + var result = new Graph(), + parents = {}, + pq = new PriorityQueue(), + u; + + function updateNeighbors(e) { + var incidentNodes = g.incidentNodes(e), + v = incidentNodes[0] !== u ? incidentNodes[0] : incidentNodes[1], + pri = pq.priority(v); + if (pri !== undefined) { + var edgeWeight = weightFunc(e); + if (edgeWeight < pri) { + parents[v] = u; + pq.decrease(v, edgeWeight); + } + } + } + + if (g.order() === 0) { + return result; + } + + g.eachNode(function(u) { + pq.add(u, Number.POSITIVE_INFINITY); + result.addNode(u); + }); + + // Start from an arbitrary node + pq.decrease(g.nodes()[0], 0); + + var init = false; + while (pq.size() > 0) { + u = pq.removeMin(); + if (u in parents) { + result.addEdge(null, u, parents[u]); + } else if (init) { + throw new Error("Input graph is not connected: " + g); + } else { + init = true; + } + + g.incidentEdges(u).forEach(updateNeighbors); + } + + return result; +} + +},{"../Graph":34,"cp-data":5}],44:[function(require,module,exports){ +module.exports = tarjan; + +/** + * This function is an implementation of [Tarjan's algorithm][] which finds + * all [strongly connected components][] in the directed graph **g**. Each + * strongly connected component is composed of nodes that can reach all other + * nodes in the component via directed edges. A strongly connected component + * can consist of a single node if that node cannot both reach and be reached + * by any other specific node in the graph. Components of more than one node + * are guaranteed to have at least one cycle. + * + * This function returns an array of components. Each component is itself an + * array that contains the ids of all nodes in the component. + * + * [Tarjan's algorithm]: http://en.wikipedia.org/wiki/Tarjan's_strongly_connected_components_algorithm + * [strongly connected components]: http://en.wikipedia.org/wiki/Strongly_connected_component + * + * @param {Digraph} g the graph to search for strongly connected components + */ +function tarjan(g) { + if (!g.isDirected()) { + throw new Error("tarjan can only be applied to a directed graph. Bad input: " + g); + } + + var index = 0, + stack = [], + visited = {}, // node id -> { onStack, lowlink, index } + results = []; + + function dfs(u) { + var entry = visited[u] = { + onStack: true, + lowlink: index, + index: index++ + }; + stack.push(u); + + g.successors(u).forEach(function(v) { + if (!(v in visited)) { + dfs(v); + entry.lowlink = Math.min(entry.lowlink, visited[v].lowlink); + } else if (visited[v].onStack) { + entry.lowlink = Math.min(entry.lowlink, visited[v].index); + } + }); + + if (entry.lowlink === entry.index) { + var cmpt = [], + v; + do { + v = stack.pop(); + visited[v].onStack = false; + cmpt.push(v); + } while (u !== v); + results.push(cmpt); + } + } + + g.nodes().forEach(function(u) { + if (!(u in visited)) { + dfs(u); + } + }); + + return results; +} + +},{}],45:[function(require,module,exports){ +module.exports = topsort; +topsort.CycleException = CycleException; + +/* + * Given a graph **g**, this function returns an ordered list of nodes such + * that for each edge `u -> v`, `u` appears before `v` in the list. If the + * graph has a cycle it is impossible to generate such a list and + * **CycleException** is thrown. + * + * See [topological sorting](https://en.wikipedia.org/wiki/Topological_sorting) + * for more details about how this algorithm works. + * + * @param {Digraph} g the graph to sort + */ +function topsort(g) { + if (!g.isDirected()) { + throw new Error("topsort can only be applied to a directed graph. Bad input: " + g); + } + + var visited = {}; + var stack = {}; + var results = []; + + function visit(node) { + if (node in stack) { + throw new CycleException(); + } + + if (!(node in visited)) { + stack[node] = true; + visited[node] = true; + g.predecessors(node).forEach(function(pred) { + visit(pred); + }); + delete stack[node]; + results.push(node); + } + } + + var sinks = g.sinks(); + if (g.order() !== 0 && sinks.length === 0) { + throw new CycleException(); + } + + g.sinks().forEach(function(sink) { + visit(sink); + }); + + return results; +} + +function CycleException() {} + +CycleException.prototype.toString = function() { + return "Graph has at least one cycle"; +}; + +},{}],46:[function(require,module,exports){ +// This file provides a helper function that mixes-in Dot behavior to an +// existing graph prototype. + +/* jshint -W079 */ +var Set = require("cp-data").Set; +/* jshint +W079 */ + +module.exports = compoundify; + +// Extends the given SuperConstructor with the ability for nodes to contain +// other nodes. A special node id `null` is used to indicate the root graph. +function compoundify(SuperConstructor) { + function Constructor() { + SuperConstructor.call(this); + + // Map of object id -> parent id (or null for root graph) + this._parents = {}; + + // Map of id (or null) -> children set + this._children = {}; + this._children[null] = new Set(); + } + + Constructor.prototype = new SuperConstructor(); + Constructor.prototype.constructor = Constructor; + + Constructor.prototype.parent = function(u, parent) { + this._strictGetNode(u); + + if (arguments.length < 2) { + return this._parents[u]; + } + + if (u === parent) { + throw new Error("Cannot make " + u + " a parent of itself"); + } + if (parent !== null) { + this._strictGetNode(parent); + } + + this._children[this._parents[u]].remove(u); + this._parents[u] = parent; + this._children[parent].add(u); + }; + + Constructor.prototype.children = function(u) { + if (u !== null) { + this._strictGetNode(u); + } + return this._children[u].keys(); + }; + + Constructor.prototype.addNode = function(u, value) { + u = SuperConstructor.prototype.addNode.call(this, u, value); + this._parents[u] = null; + this._children[u] = new Set(); + this._children[null].add(u); + return u; + }; + + Constructor.prototype.delNode = function(u) { + // Promote all children to the parent of the subgraph + var parent = this.parent(u); + this._children[u].keys().forEach(function(child) { + this.parent(child, parent); + }, this); + + this._children[parent].remove(u); + delete this._parents[u]; + delete this._children[u]; + + return SuperConstructor.prototype.delNode.call(this, u); + }; + + Constructor.prototype.copy = function() { + var copy = SuperConstructor.prototype.copy.call(this); + this.nodes().forEach(function(u) { + copy.parent(u, this.parent(u)); + }, this); + return copy; + }; + + Constructor.prototype.filterNodes = function(filter) { + var self = this, + copy = SuperConstructor.prototype.filterNodes.call(this, filter); + + var parents = {}; + function findParent(u) { + var parent = self.parent(u); + if (parent === null || copy.hasNode(parent)) { + parents[u] = parent; + return parent; + } else if (parent in parents) { + return parents[parent]; + } else { + return findParent(parent); + } + } + + copy.eachNode(function(u) { copy.parent(u, findParent(u)); }); + + return copy; + }; + + return Constructor; +} + +},{"cp-data":5}],47:[function(require,module,exports){ +var Graph = require("../Graph"), + Digraph = require("../Digraph"), + CGraph = require("../CGraph"), + CDigraph = require("../CDigraph"); + +exports.decode = function(nodes, edges, Ctor) { + Ctor = Ctor || Digraph; + + if (typeOf(nodes) !== "Array") { + throw new Error("nodes is not an Array"); + } + + if (typeOf(edges) !== "Array") { + throw new Error("edges is not an Array"); + } + + if (typeof Ctor === "string") { + switch(Ctor) { + case "graph": Ctor = Graph; break; + case "digraph": Ctor = Digraph; break; + case "cgraph": Ctor = CGraph; break; + case "cdigraph": Ctor = CDigraph; break; + default: throw new Error("Unrecognized graph type: " + Ctor); + } + } + + var graph = new Ctor(); + + nodes.forEach(function(u) { + graph.addNode(u.id, u.value); + }); + + // If the graph is compound, set up children... + if (graph.parent) { + nodes.forEach(function(u) { + if (u.children) { + u.children.forEach(function(v) { + graph.parent(v, u.id); + }); + } + }); + } + + edges.forEach(function(e) { + graph.addEdge(e.id, e.u, e.v, e.value); + }); + + return graph; +}; + +exports.encode = function(graph) { + var nodes = []; + var edges = []; + + graph.eachNode(function(u, value) { + var node = {id: u, value: value}; + if (graph.children) { + var children = graph.children(u); + if (children.length) { + node.children = children; + } + } + nodes.push(node); + }); + + graph.eachEdge(function(e, u, v, value) { + edges.push({id: e, u: u, v: v, value: value}); + }); + + var type; + if (graph instanceof CDigraph) { + type = "cdigraph"; + } else if (graph instanceof CGraph) { + type = "cgraph"; + } else if (graph instanceof Digraph) { + type = "digraph"; + } else if (graph instanceof Graph) { + type = "graph"; + } else { + throw new Error("Couldn't determine type of graph: " + graph); + } + + return { nodes: nodes, edges: edges, type: type }; +}; + +function typeOf(obj) { + return Object.prototype.toString.call(obj).slice(8, -1); +} + +},{"../CDigraph":31,"../CGraph":32,"../Digraph":33,"../Graph":34}],48:[function(require,module,exports){ +/* jshint -W079 */ +var Set = require("cp-data").Set; +/* jshint +W079 */ + +exports.all = function() { + return function() { return true; }; +}; + +exports.nodesFromList = function(nodes) { + var set = new Set(nodes); + return function(u) { + return set.has(u); + }; +}; + +},{"cp-data":5}],49:[function(require,module,exports){ +var Graph = require("./Graph"), + Digraph = require("./Digraph"); + +// Side-effect based changes are lousy, but node doesn't seem to resolve the +// requires cycle. + +/** + * Returns a new directed graph using the nodes and edges from this graph. The + * new graph will have the same nodes, but will have twice the number of edges: + * each edge is split into two edges with opposite directions. Edge ids, + * consequently, are not preserved by this transformation. + */ +Graph.prototype.toDigraph = +Graph.prototype.asDirected = function() { + var g = new Digraph(); + this.eachNode(function(u, value) { g.addNode(u, value); }); + this.eachEdge(function(e, u, v, value) { + g.addEdge(null, u, v, value); + g.addEdge(null, v, u, value); + }); + return g; +}; + +/** + * Returns a new undirected graph using the nodes and edges from this graph. + * The new graph will have the same nodes, but the edges will be made + * undirected. Edge ids are preserved in this transformation. + */ +Digraph.prototype.toGraph = +Digraph.prototype.asUndirected = function() { + var g = new Graph(); + this.eachNode(function(u, value) { g.addNode(u, value); }); + this.eachEdge(function(e, u, v, value) { + g.addEdge(e, u, v, value); + }); + return g; +}; + +},{"./Digraph":33,"./Graph":34}],50:[function(require,module,exports){ +// Returns an array of all values for properties of **o**. +exports.values = function(o) { + var ks = Object.keys(o), + len = ks.length, + result = new Array(len), + i; + for (i = 0; i < len; ++i) { + result[i] = o[ks[i]]; + } + return result; +}; + +},{}],51:[function(require,module,exports){ +module.exports = '0.7.4'; + +},{}]},{},[1]) +; \ No newline at end of file diff --git a/src/static/dagre-d3/dagre-d3.min.js b/src/static/dagre-d3/dagre-d3.min.js new file mode 100644 index 0000000..1f3e917 --- /dev/null +++ b/src/static/dagre-d3/dagre-d3.min.js @@ -0,0 +1,2 @@ +(function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var j=typeof require=="function"&&require;if(!h&&j)return j(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}var f=typeof require=="function"&&require;for(var g=0;g<d.length;g++)e(d[g]);return e})({1:[function(a,b,c){var d=self;d.dagreD3=a("./index")},{"./index":2}],2:[function(a,b,c){b.exports={Digraph:a("graphlib").Digraph,Renderer:a("./lib/Renderer"),json:a("graphlib").converter.json,layout:a("dagre").layout,version:a("./lib/version"),debug:a("dagre").debug}},{"./lib/Renderer":3,"./lib/version":4,dagre:11,graphlib:29}],3:[function(a,b,c){function g(){this._layout=d(),this.drawNodes(l),this.drawEdgeLabels(m),this.drawEdgePaths(n),this.positionNodes(o),this.positionEdgeLabels(p),this.positionEdgePaths(u),this.zoomSetup(w),this.zoom(x),this.transition(v),this.postLayout(y),this.postRender(z),this.edgeInterpolate("bundle"),this.edgeTension(.95)}function h(a){var b=a.copy();return b.nodes().forEach(function(a){var c=i(b.node(a));b.node(a,c),"label"in c||(c.label="")}),b.edges().forEach(function(a){var c=i(b.edge(a));b.edge(a,c),"label"in c||(c.label="")}),b}function i(a){var b={};for(var c in a)b[c]=a[c];return b}function j(a,b){var c=a.getBBox();b.width=c.width,b.height=c.height}function k(a,b){var c=b.run(a);return a.eachNode(function(a,b){c.node(a).label=b.label}),a.eachEdge(function(a,b,d,e){c.edge(a).label=e.label}),c}function l(a,b){var c=a.nodes().filter(function(b){return!L(a,b)}),d=b.selectAll("g.node").classed("enter",!1).data(c,function(a){return a});return d.selectAll("*").remove(),d.enter().append("g").style("opacity",0).attr("class","node enter"),d.each(function(b){A(a.node(b),e.select(this),!0,10,10)}),this._transition(d.exit()).style("opacity",0).remove(),d}function m(a,b){var c=b.selectAll("g.edgeLabel").classed("enter",!1).data(a.edges(),function(a){return a});return c.selectAll("*").remove(),c.enter().append("g").style("opacity",0).attr("class","edgeLabel enter"),c.each(function(b){A(a.edge(b),e.select(this),!1,0,0)}),this._transition(c.exit()).style("opacity",0).remove(),c}function o(a,b){function c(b){var c=a.node(b);return"translate("+c.x+","+c.y+")"}b.filter(".enter").attr("transform",c),this._transition(b).style("opacity",1).attr("transform",c)}function p(a,b){function c(b){var c=a.edge(b),d=E(c.points);return"translate("+d.x+","+d.y+")"}b.filter(".enter").attr("transform",c),this._transition(b).style("opacity",1).attr("transform",c)}function q(a){return Object.prototype.toString.call(a)==="[object SVGEllipseElement]"}function r(a){return Object.prototype.toString.call(a)==="[object SVGCircleElement]"}function s(a){return Object.prototype.toString.call(a)==="[object SVGPolygonElement]"}function t(a,b,c){if(a.useDef){var d=c.select("defs #"+a.useDef).node();if(d){var e=d.childNodes[0];if(r(e)||q(e))return G(a,e,b);if(s(e))return K(a,e,b)}}return F(a,b)}function u(a,b,c){function g(b){var g=a.edge(b),h=a.node(a.incidentNodes(b)[0]),i=a.node(a.incidentNodes(b)[1]),j=g.points.slice(),k=j.length===0?i:j[0],l=j.length===0?h:j[j.length-1];return j.unshift(t(h,k,c)),j.push(t(i,l,c)),e.svg.line().x(function(a){return a.x}).y(function(a){return a.y}).interpolate(d).tension(f)(j)}var d=this._edgeInterpolate,f=this._edgeTension;b.filter(".enter").selectAll("path").attr("d",g),this._transition(b.selectAll("path")).attr("d",g).style("opacity",1)}function v(a){return a}function w(a,b){var c=b.property("ownerSVGElement");return c?c=e.select(c):c=b,c.select("rect.overlay").empty()&&(c.append("rect").attr("class","overlay").attr("width","100%").attr("height","100%").style("fill","none"),b=b.append("g").attr("class","zoom"),this._zoom&&c.call(this._zoom(a,b))),b}function x(a,b){return e.behavior.zoom().on("zoom",function(){b.attr("transform","translate("+e.event.translate+")scale("+e.event.scale+")")})}function y(){}function z(a,b){a.isDirected()&&b.select("#arrowhead").empty()&&b.append("svg:defs").append("svg:marker").attr("id","arrowhead").attr("viewBox","0 0 10 10").attr("refX",8).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",8).attr("markerHeight",5).attr("orient","auto").attr("style","fill: #333").append("svg:path").attr("d","M 0 0 L 10 5 L 0 10 z")}function A(a,b,c,d,e){if(a.useDef){b.append("use").attr("xlink:href","#"+a.useDef);return}var f=a.label,g=b.append("rect");a.width&&g.attr("width",a.width),a.height&&g.attr("height",a.height);var h=b.append("g").style("stroke","#00");f[0]==="<"?(B(f,h),d=e=0):C(f,h,Math.floor(a.labelCols),a.labelCut);var i=h.node().getBBox();h.attr("transform","translate("+ -i.width/2+","+ -i.height/2+")");var j=b.node().getBBox();g.attr("rx",a.rx?a.rx:5).attr("ry",a.ry?a.ry:5).attr("x",-(j.width/2+d)).attr("y",-(j.height/2+e)).attr("width",j.width+2*d).attr("height",j.height+2*e).attr("fill","#fff"),c&&(a.fill&&g.style("fill",a.fill),a.stroke&&g.style("stroke",a.stroke),a["stroke-width"]&&g.style("stroke-width",a["stroke-width"]+"px"),a["stroke-dasharray"]&&g.style("stroke-dasharray",a["stroke-dasharray"]),a.href&&b.attr("class",b.attr("class")+" clickable").on("click",function(){window.open(a.href)}))}function B(a,b){var c=b.append("foreignObject").attr("width","100000"),d,e;c.append("xhtml:div").style("float","left").html(function(){return a}).each(function(){d=this.clientWidth,e=this.clientHeight}),c.attr("width",d).attr("height",e)}function C(a,b,c,d){d===undefined&&(d="false"),d=d.toString().toLowerCase()==="true";var e=b.append("text").attr("text-anchor","left");a=a.replace(/\\n/g,"\n");var f=c?D(a,c,d):a;f=f.split("\n");for(var g=0;g<f.length;g++)e.append("tspan").attr("dy","1em").attr("x","1").text(f[g])}function D(a,b,c,d){d=d||"\n",b=b||75,c=c||!1;if(!a)return a;var e=".{1,"+b+"}(\\s|$)"+(c?"|.{"+b+"}|.+$":"|\\S+?(\\s|$)");return a.match(new RegExp(e,"g")).join(d)}function E(a){var b=a.length/2;if(a.length%2)return a[Math.floor(b)];var c=a[b-1],d=a[b];return{x:(c.x+d.x)/2,y:(c.y+d.y)/2}}function F(a,b){var c=a.x,d=a.y,e=b.x-c,f=b.y-d,g=a.width/2,h=a.height/2,i,j;return Math.abs(f)*g>Math.abs(e)*h?(f<0&&(h=-h),i=f===0?0:h*e/f,j=h):(e<0&&(g=-g),i=g,j=e===0?0:g*f/e),{x:c+i,y:d+j}}function G(a,b,c){var d=a.x,e=a.y,f,g;r(b)?f=g=b.r.baseVal.value:(f=b.rx.baseVal.value,g=b.ry.baseVal.value);var h=d-c.x,i=e-c.y,j=Math.sqrt(f*f*i*i+g*g*h*h),k=Math.abs(f*g*h/j);c.x<d&&(k=-k);var l=Math.abs(f*g*i/j);return c.y<e&&(l=-l),{x:d+k,y:e+l}}function H(a,b){return a*b>0}function I(a,b,c){c.some(function(c){return c[0]===a&&c[1]===b})||c.push([a,b])}function J(a,b,c,d,e,f,g,h,i){var j,k,l,m,n,o,p,q,r,s,t,u,v,w,x;j=d-b,l=a-c,n=c*b-a*d,r=j*e+l*f+n,s=j*g+l*h+n;if(r!==0&&s!==0&&H(r,s))return;k=h-f,m=e-g,o=g*f-e*h,p=k*a+m*b+o,q=k*c+m*d+o;if(p!==0&&q!==0&&H(p,q))return;t=j*m-k*l;if(t===0)return;u=Math.abs(t/2),v=l*o-m*n,w=v<0?(v-u)/t:(v+u)/t,v=k*n-j*o,x=v<0?(v-u)/t:(v+u)/t,I(w,x,i)}function K(a,b,c){var d=a.x,e=a.y,f=c.x,g=c.y,h=[],i=b.points,j=1e5,k=1e5;for(var l=0;l<i.numberOfItems;l++){var m=i.getItem(l);j=Math.min(j,m.x),k=Math.min(k,m.y)}var n=d-a.width/2-j,o=e-a.height/2-k;for(var p=0;p<i.numberOfItems;p++){var q=i.getItem(p),r=i.getItem(p<i.numberOfItems-1?p+1:0);J(d,e,f,g,n+q.x,o+q.y,n+r.x,o+r.y,h)}return h.length===1?{x:h[0][0],y:h[0][1]}:h.length>1?(h.sort(function(a,b){var d=a[0]-c.x,e=a[1]-c.y,f=Math.sqrt(d*d+e*e),g=b[0]-c.x,h=b[1]-c.y,i=Math.sqrt(g*g+h*h);return f<i?-1:f===i?0:1}),{x:h[0][0],y:h[0][1]}):(console.log("NO INTERSECTION FOUND, RETURN NODE CENTER",a),a)}function L(a,b){return"children"in a&&a.children(b).length}function M(a,b){return a.bind?a.bind(b):function(){return a.apply(b,arguments)}}var d=a("dagre").layout,e;try{e=a("d3")}catch(f){e=window.d3}b.exports=g,g.prototype.layout=function(a){return arguments.length?(this._layout=a,this):this._layout},g.prototype.drawNodes=function(a){return arguments.length?(this._drawNodes=M(a,this),this):this._drawNodes},g.prototype.drawEdgeLabels=function(a){return arguments.length?(this._drawEdgeLabels=M(a,this),this):this._drawEdgeLabels},g.prototype.drawEdgePaths=function(a){return arguments.length?(this._drawEdgePaths=M(a,this),this):this._drawEdgePaths},g.prototype.positionNodes=function(a){return arguments.length?(this._positionNodes=M(a,this),this):this._positionNodes},g.prototype.positionEdgeLabels=function(a){return arguments.length?(this._positionEdgeLabels=M(a,this),this):this._positionEdgeLabels},g.prototype.positionEdgePaths=function(a){return arguments.length?(this._positionEdgePaths=M(a,this),this):this._positionEdgePaths},g.prototype.transition=function(a){return arguments.length?(this._transition=M(a,this),this):this._transition},g.prototype.zoomSetup=function(a){return arguments.length?(this._zoomSetup=M(a,this),this):this._zoomSetup},g.prototype.zoom=function(a){return arguments.length?(a?this._zoom=M(a,this):delete this._zoom,this):this._zoom},g.prototype.postLayout=function(a){return arguments.length?(this._postLayout=M(a,this),this):this._postLayout},g.prototype.postRender=function(a){return arguments.length?(this._postRender=M(a,this),this):this._postRender},g.prototype.edgeInterpolate=function(a){return arguments.length?(this._edgeInterpolate=a,this):this._edgeInterpolate},g.prototype.edgeTension=function(a){return arguments.length?(this._edgeTension=a,this):this._edgeTension},g.prototype.run=function(a,b){a=h(a);var c=this._zoomSetup(a,b);c.selectAll("g.edgePaths, g.edgeLabels, g.nodes").data(["edgePaths","edgeLabels","nodes"]).enter().append("g").attr("class",function(a){return a});var d=this._drawNodes(a,c.select("g.nodes")),e=this._drawEdgeLabels(a,c.select("g.edgeLabels"));d.each(function(b){j(this,a.node(b))}),e.each(function(b){j(this,a.edge(b))});var f=k(a,this._layout);a.eachNode(function(a,b){b.useDef&&(f.node(a).useDef=b.useDef)}),this._postLayout(f,c);var g=this._drawEdgePaths(a,c.select("g.edgePaths"));return this._positionNodes(f,d),this._positionEdgeLabels(f,e),this._positionEdgePaths(f,g,b),this._postRender(f,c),f};var n=function(a,b){var c=b.selectAll("g.edgePath").classed("enter",!1).data(a.edges(),function(a){return a});return c.enter().append("g").attr("class","edgePath enter").append("path").style("opacity",0).attr("marker-end","url(#arrowhead)"),this._transition(c.exit()).style("opacity",0).remove(),c}},{d3:10,dagre:11}],4:[function(a,b,c){b.exports="0.2.6"},{}],5:[function(a,b,c){c.Set=a("./lib/Set"),c.PriorityQueue=a("./lib/PriorityQueue"),c.version=a("./lib/version")},{"./lib/PriorityQueue":6,"./lib/Set":7,"./lib/version":9}],6:[function(a,b,c){function d(){this._arr=[],this._keyIndices={}}b.exports=d,d.prototype.size=function(){return this._arr.length},d.prototype.keys=function(){return this._arr.map(function(a){return a.key})},d.prototype.has=function(a){return a in this._keyIndices},d.prototype.priority=function(a){var b=this._keyIndices[a];if(b!==undefined)return this._arr[b].priority},d.prototype.min=function(){if(this.size()===0)throw new Error("Queue underflow");return this._arr[0].key},d.prototype.add=function(a,b){var c=this._keyIndices;if(a in c)return!1;var d=this._arr,e=d.length;return c[a]=e,d.push({key:a,priority:b}),this._decrease(e),!0},d.prototype.removeMin=function(){this._swap(0,this._arr.length-1);var a=this._arr.pop();return delete this._keyIndices[a.key],this._heapify(0),a.key},d.prototype.decrease=function(a,b){var c=this._keyIndices[a];if(b>this._arr[c].priority)throw new Error("New priority is greater than current priority. Key: "+a+" Old: "+this._arr[c].priority+" New: "+b);this._arr[c].priority=b,this._decrease(c)},d.prototype._heapify=function(a){var b=this._arr,c=2*a,d=c+1,e=a;c<b.length&&(e=b[c].priority<b[e].priority?c:e,d<b.length&&(e=b[d].priority<b[e].priority?d:e),e!==a&&(this._swap(a,e),this._heapify(e)))},d.prototype._decrease=function(a){var b=this._arr,c=b[a].priority,d;while(a!==0){d=a>>1;if(b[d].priority<c)break;this._swap(a,d),a=d}},d.prototype._swap=function(a,b){var c=this._arr,d=this._keyIndices,e=c[a],f=c[b];c[a]=f,c[b]=e,d[f.key]=a,d[e.key]=b}},{}],7:[function(a,b,c){function e(a){this._size=0,this._keys={};if(a)for(var b=0,c=a.length;b<c;++b)this.add(a[b])}function f(a){var b=Object.keys(a),c=b.length,d=new Array(c),e;for(e=0;e<c;++e)d[e]=a[b[e]];return d}var d=a("./util");b.exports=e,e.intersect=function(a){if(a.length===0)return new e;var b=new e(d.isArray(a[0])?a[0]:a[0].keys());for(var c=1,f=a.length;c<f;++c){var g=b.keys(),h=d.isArray(a[c])?new e(a[c]):a[c];for(var i=0,j=g.length;i<j;++i){var k=g[i];h.has(k)||b.remove(k)}}return b},e.union=function(a){var b=d.reduce(a,function(a,b){return a+(b.size?b.size():b.length)},0),c=new Array(b),f=0;for(var g=0,h=a.length;g<h;++g){var i=a[g],j=d.isArray(i)?i:i.keys();for(var k=0,l=j.length;k<l;++k)c[f++]=j[k]}return new e(c)},e.prototype.size=function(){return this._size},e.prototype.keys=function(){return f(this._keys)},e.prototype.has=function(a){return a in this._keys},e.prototype.add=function(a){return a in this._keys?!1:(this._keys[a]=a,++this._size,!0)},e.prototype.remove=function(a){return a in this._keys?(delete this._keys[a],--this._size,!0):!1}},{"./util":8}],8:[function(a,b,c){Array.isArray?c.isArray=Array.isArray:c.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"},"function"!=typeof Array.prototype.reduce?c.reduce=function(a,b,c){"use strict";if(null===a||"undefined"==typeof a)throw new TypeError("Array.prototype.reduce called on null or undefined");if("function"!=typeof b)throw new TypeError(b+" is not a function");var d,e,f=a.length>>>0,g=!1;1<arguments.length&&(e=c,g=!0);for(d=0;f>d;++d)a.hasOwnProperty(d)&&(g?e=b(e,a[d],d,a):(e=a[d],g=!0));if(!g)throw new TypeError("Reduce of empty array with no initial value");return e}:c.reduce=function(a,b,c){return a.reduce(b,c)}},{}],9:[function(a,b,c){b.exports="1.1.3"},{}],10:[function(a,b,c){a("./d3"),b.exports=d3,function(){delete this.d3}()},{}],11:[function(a,b,c){c.Digraph=a("graphlib").Digraph,c.Graph=a("graphlib").Graph,c.layout=a("./lib/layout"),c.version=a("./lib/version"),c.debug=a("./lib/debug")},{"./lib/debug":12,"./lib/layout":13,"./lib/version":28,graphlib:29}],12:[function(a,b,c){"use strict";var d=a("./util");c.dotOrdering=function(a){function e(b){var d=a.children(b);d.length?(c+="subgraph cluster_"+b+" {",c+='label="'+b+'";',d.forEach(function(a){e(a)}),c+="}"):(c+=b,a.node(b).dummy&&(c+=" [shape=diamond]"),c+=";")}var b=d.ordering(a.filterNodes(d.filterNonSubgraphs(a))),c="digraph {";return a.children(null).forEach(e),b.forEach(function(a){c+='subgraph { rank=same; edge [style="invis"];',c+=a.join("->"),c+="}"}),a.eachEdge(function(a,b,d){c+=b+"->"+d+";"}),c+="}",c}},{"./util":27}],13:[function(a,b,c){"use strict";var d=a("./util"),e=a("./rank"),f=a("./order"),g=a("graphlib").CGraph,h=a("graphlib").CDigraph;b.exports=function(){function j(a){var c=new h;a.eachNode(function(a,b){b===undefined&&(b={}),c.addNode(a,{width:b.width,height:b.height}),b.hasOwnProperty("rank")&&(c.node(a).prefRank=b.rank)}),a.parent&&a.nodes().forEach(function(b){c.parent(b,a.parent(b))}),a.eachEdge(function(a,b,d,e){e===undefined&&(e={});var f={e:a,minLen:e.minLen||1,width:e.width||0,height:e.height||0,points:[]};c.addEdge(null,b,d,f)});var d=a.graph()||{};return c.graph({rankDir:d.rankDir||b.rankDir,orderRestarts:d.orderRestarts}),c}function k(a){var g=i.rankSep(),h;try{return h=d.time("initLayoutGraph",j)(a),h.order()===0?h:(h.eachEdge(function(a,b,c,d){d.minLen*=2}),i.rankSep(g/2),d.time("rank.run",e.run)(h,b.rankSimplex),d.time("normalize",l)(h),d.time("order",f)(h,b.orderMaxSweeps),d.time("position",c.run)(h),d.time("undoNormalize",m)(h),d.time("fixupEdgePoints",n)(h),d.time("rank.restoreEdges",e.restoreEdges)(h),d.time("createFinalGraph",o)(h,a.isDirected()))}finally{i.rankSep(g)}}function l(a){var b=0;a.eachEdge(function(c,d,e,f){var g=a.node(d).rank,h=a.node(e).rank;if(g+1<h){for(var i=d,j=g+1,k=0;j<h;++j,++k){var l="_D"+ ++b,m={width:f.width,height:f.height,edge:{id:c,source:d,target:e,attrs:f},rank:j,dummy:!0};k===0?m.index=0:j+1===h&&(m.index=1),a.addNode(l,m),a.addEdge(null,i,l,{}),i=l}a.addEdge(null,i,e,{}),a.delEdge(c)}})}function m(a){a.eachNode(function(b,c){if(c.dummy){if("index"in c){var d=c.edge;a.hasEdge(d.id)||a.addEdge(d.id,d.source,d.target,d.attrs);var e=a.edge(d.id).points;e[c.index]={x:c.x,y:c.y,ul:c.ul,ur:c.ur,dl:c.dl,dr:c.dr}}a.delNode(b)}})}function n(a){a.eachEdge(function(a,b,c,d){d.reversed&&d.points.reverse()})}function o(a,b){var c=b?new h:new g;c.graph(a.graph()),a.eachNode(function(a,b){c.addNode(a,b)}),a.eachNode(function(b){c.parent(b,a.parent(b))}),a.eachEdge(function(a,b,d,e){c.addEdge(e.e,b,d,e)});var d=0,e=0;return a.eachNode(function(b,c){a.children(b).length||(d=Math.max(d,c.x+c.width/2),e=Math.max(e,c.y+c.height/2))}),a.eachEdge(function(a,b,c,f){var g=Math.max.apply(Math,f.points.map(function(a){return a.x})),h=Math.max.apply(Math,f.points.map(function(a){return a.y}));d=Math.max(d,g+f.width/2),e=Math.max(e,h+f.height/2)}),c.graph().width=d,c.graph().height=e,c}function p(a){return function(){return arguments.length?(a.apply(null,arguments),i):a()}}var b={debugLevel:0,orderMaxSweeps:f.DEFAULT_MAX_SWEEPS,rankSimplex:!1,rankDir:"TB"},c=a("./position")(),i={};return i.orderIters=d.propertyAccessor(i,b,"orderMaxSweeps"),i.rankSimplex=d.propertyAccessor(i,b,"rankSimplex"),i.nodeSep=p(c.nodeSep),i.edgeSep=p(c.edgeSep),i.universalSep=p(c.universalSep),i.rankSep=p(c.rankSep),i.rankDir=d.propertyAccessor(i,b,"rankDir"),i.debugAlignment=p(c.debugAlignment),i.debugLevel=d.propertyAccessor(i,b,"debugLevel",function(a){d.log.level=a,c.debugLevel(a)}),i.run=d.time("Total layout",k),i._normalize=l,i}},{"./order":14,"./position":19,"./rank":20,"./util":27,graphlib:29}],14:[function(a,b,c){function j(a,b){function o(){a.eachNode(function(a,b){n[a]=b.order})}arguments.length<2&&(b=i);var c=a.graph().orderRestarts||0,h=f(a);h.forEach(function(b){b=b.filterNodes(function(b){return!a.children(b).length})});var j=0,k,l=Number.MAX_VALUE,n={};for(var p=0;p<Number(c)+1&&l!==0;++p){k=Number.MAX_VALUE,g(a,c>0),d.log(2,"Order phase start cross count: "+a.graph().orderInitCC);var q,r,s;for(q=0,r=0;r<4&&q<b&&k>0;++q,++r,++j)m(a,h,q),s=e(a),s<k&&(r=0,k=s,s<l&&(o(),l=s)),d.log(3,"Order phase start "+p+" iter "+q+" cross count: "+s)}Object.keys(n).forEach(function(b){if(!a.children||!a.children(b).length)a.node(b).order=n[b]}),a.graph().orderCC=l,d.log(2,"Order iterations: "+j),d.log(2,"Order phase best cross count: "+a.graph().orderCC)}function k(a,b){var c={};return b.forEach(function(b){c[b]=a.inEdges(b).map(function(b){return a.node(a.source(b)).order})}),c}function l(a,b){var c={};return b.forEach(function(b){c[b]=a.outEdges(b).map(function(b){return a.node(a.target(b)).order})}),c}function m(a,b,c){c%2===0?n(a,b,c):o(a,b,c)}function n(a,b){var c;for(var d=1;d<b.length;++d)c=h(b[d],c,k(a,b[d].nodes()))}function o(a,b){var c;for(var d=b.length-2;d>=0;--d)h(b[d],c,l(a,b[d].nodes()))}"use strict";var d=a("./util"),e=a("./order/crossCount"),f=a("./order/initLayerGraphs"),g=a("./order/initOrder"),h=a("./order/sortLayer");b.exports=j;var i=24;j.DEFAULT_MAX_SWEEPS=i},{"./order/crossCount":15,"./order/initLayerGraphs":16,"./order/initOrder":17,"./order/sortLayer":18,"./util":27}],15:[function(a,b,c){function e(a){var b=0,c=d.ordering(a);for(var e=1;e<c.length;++e)b+=f(a,c[e-1],c[e]);return b}function f(a,b,c){var d=[];b.forEach(function(b){var c=[];a.outEdges(b).forEach(function(b){c.push(a.node(a.target(b)).order)}),c.sort(function(a,b){return a-b}),d=d.concat(c)});var e=1;while(e<c.length)e<<=1;var f=2*e-1;e-=1;var g=[];for(var h=0;h<f;++h)g[h]=0;var i=0;return d.forEach(function(a){var b=a+e;++g[b];while(b>0)b%2&&(i+=g[b+1]),b=b-1>>1,++g[b]}),i}"use strict";var d=a("../util");b.exports=e},{"../util":27}],16:[function(a,b,c){function f(a){function c(d){if(d===null){a.children(d).forEach(function(a){c(a)});return}var f=a.node(d);f.minRank="rank"in f?f.rank:Number.MAX_VALUE,f.maxRank="rank"in f?f.rank:Number.MIN_VALUE;var h=new e;return a.children(d).forEach(function(b){var d=c(b);h=e.union([h,d]),f.minRank=Math.min(f.minRank,a.node(b).minRank),f.maxRank=Math.max(f.maxRank,a.node(b).maxRank)}),"rank"in f&&h.add(f.rank),h.keys().forEach(function(a){a in b||(b[a]=[]),b[a].push(d)}),h}var b=[];c(null);var f=[];return b.forEach(function(b,c){f[c]=a.filterNodes(d(b))}),f}"use strict";var d=a("graphlib").filter.nodesFromList,e=a("cp-data").Set;b.exports=f},{"cp-data":5,graphlib:29}],17:[function(a,b,c){function f(a,b){var c=[];a.eachNode(function(b,d){var e=c[d.rank];if(a.children&&a.children(b).length>0)return;e||(e=c[d.rank]=[]),e.push(b)}),c.forEach(function(c){b&&e.shuffle(c),c.forEach(function(b,c){a.node(b).order=c})});var f=d(a);a.graph().orderInitCC=f,a.graph().orderCC=Number.MAX_VALUE}"use strict";var d=a("./crossCount"),e=a("../util");b.exports=f},{"../util":27,"./crossCount":15}],18:[function(a,b,c){function h(a,b,c){c=n(a,c);var d=i(a,null,b,c);return d.list.forEach(function(b,c){a.node(b).order=c}),d.constraintGraph}function i(a,b,c,f){c=c?c.filterNodes(g(a.children(b))):new e;var h={};a.children(b).forEach(function(b){if(a.children(b).length)h[b]=i(a,b,c,f),h[b].firstSG=b,h[b].lastSG=b;else{var e=f[b];h[b]={degree:e.length,barycenter:d.sum(e)/e.length,order:a.node(b).order,orderCount:1,list:[b]}}}),l(a,c,h);var k=Object.keys(h);k.sort(function(a,b){return h[a].barycenter-h[b].barycenter||h[a].order-h[b].order});var m=k.map(function(a){return h[a]}).reduce(function(b,c){return j(a,b,c)});return m}function j(a,b,c){var d=k(b.constraintGraph,c.constraintGraph);return b.lastSG!==undefined&&c.firstSG!==undefined&&(d===undefined&&(d=new e),d.hasNode(b.lastSG)||d.addNode(b.lastSG),d.addNode(c.firstSG),d.addEdge(null,b.lastSG,c.firstSG)),{degree:b.degree+c.degree,barycenter:(b.barycenter*b.degree+c.barycenter*c.degree)/(b.degree+c.degree),order:(b.order*b.orderCount+c.order*c.orderCount)/(b.orderCount+c.orderCount),orderCount:b.orderCount+c.orderCount,list:b.list.concat(c.list),firstSG:b.firstSG!==undefined?b.firstSG:c.firstSG,lastSG:c.lastSG!==undefined?c.lastSG:b.lastSG,constraintGraph:d}}function k(a,b){return a===undefined?b:b===undefined?a:(a=a.copy(),b.nodes().forEach(function(b){a.addNode(b)}),b.edges().forEach(function(b,c,d){a.addEdge(null,c,d)}),a)}function l(a,b,c){function d(a,c,d){b.inEdges(a).forEach(function(a){b.delEdge(a),b.addEdge(null,b.source(a),d)}),b.outEdges(c).forEach(function(a){b.delEdge(a),b.addEdge(null,d,b.target(a))}),b.delNode(a),b.delNode(c)}var e;while((e=m(b,c))!==undefined){var f=b.source(e),g=b.target(e),h;while((h=b.addNode(null))&&a.hasNode(h))b.delNode(h);c[h]=j(a,c[f],c[g]),delete c[f],delete c[g],d(f,g,h),b.incidentEdges(h).length===0&&b.delNode(h)}}function m(a,b){var c=f(a);for(var d=0;d<c.length;++d){var e=c[d],g=a.inEdges(e);for(var h=0;h<g.length;++h){var i=g[h];if(b[a.source(i)].barycenter>=b[e].barycenter)return i}}}function n(a,b){var c=Number.MAX_VALUE,e=0,f={};a.eachNode(function(f){if(a.children(f).length)return;var g=b[f];g.length&&(c=Math.min(c,d.min(g)),e=Math.max(e,d.max(g)))});var g=e-c;return a.eachNode(function(d){if(a.children(d).length)return;var e=b[d];e.length?f[d]=e.map(function(b){return g?(b-c)*(a.order()-1)/g:a.order()-.5}):f[d]=[a.node(d).order]}),f}"use strict";var d=a("../util"),e=a("graphlib").Digraph,f=a("graphlib").alg.topsort,g=a("graphlib").filter.nodesFromList;b.exports=h},{"../util":27,graphlib:29}],19:[function(a,b,c){"use strict";var d=a("./util");b.exports=function(){function c(b){b=b.filterNodes(d.filterNonSubgraphs(b));var c=d.ordering(b),e=f(b,c),i={};["u","d"].forEach(function(d){d==="d"&&c.reverse(),["l","r"].forEach(function(f){f==="r"&&m(c);var j=d+f,k=g(b,c,e,d==="u"?"predecessors":"successors");i[j]=h(b,c,k.pos,k.root,k.align),a.debugLevel>=3&&t(d+f,b,c,i[j]),f==="r"&&l(i[j]),f==="r"&&m(c)}),d==="d"&&c.reverse()}),k(b,c,i),b.eachNode(function(a){var c=[];for(var d in i){var e=i[d][a];r(d,b,a,e),c.push(e)}c.sort(function(a,b){return a-b}),q(b,a,(c[1]+c[2])/2)});var j=0,p=b.graph().rankDir==="BT"||b.graph().rankDir==="RL";c.forEach(function(c){var e=d.max(c.map(function(a){return o(b,a)}));j+=e/2,c.forEach(function(a){s(b,a,p?-j:j)}),j+=e/2+a.rankSep});var u=d.min(b.nodes().map(function(a){return q(b,a)-n(b,a)/2})),v=d.min(b.nodes().map(function(a){return s(b,a)-o(b,a)/2}));b.eachNode(function(a){q(b,a,q(b,a)-u),s(b,a,s(b,a)-v)})}function e(a,b){return a<b?a.toString().length+":"+a+"-"+b:b.toString().length+":"+b+"-"+a}function f(a,b){function k(a){var b=d[a];if(b<h||b>j)c[e(g[i],a)]=!0}var c={},d={},f,g,h,i,j;if(b.length<=2)return c;b[1].forEach(function(a,b){d[a]=b});for(var l=1;l<b.length-1;++l){f=b[l],g=b[l+1],h=0,i=0;for(var m=0;m<g.length;++m){var n=g[m];d[n]=m,j=undefined;if(a.node(n).dummy){var o=a.predecessors(n)[0];o!==undefined&&a.node(o).dummy&&(j=d[o])}j===undefined&&m===g.length-1&&(j=f.length-1);if(j!==undefined){for(;i<=m;++i)a.predecessors(g[i]).forEach(k);h=j}}}return c}function g(a,b,c,d){var f={},g={},h={};return b.forEach(function(a){a.forEach(function(a,b){g[a]=a,h[a]=a,f[a]=b})}),b.forEach(function(b){var i=-1;b.forEach(function(b){var j=a[d](b),k;j.length>0&&(j.sort(function(a,b){return f[a]-f[b]}),k=(j.length-1)/2,j.slice(Math.floor(k),Math.ceil(k)+1).forEach(function(a){h[b]===b&&!c[e(a,b)]&&i<f[a]&&(h[a]=b,h[b]=g[b]=g[a],i=f[a])}))})}),{pos:f,root:g,align:h}}function h(a,b,c,e,f){function l(a,b,c){b in h[a]?h[a][b]=Math.min(h[a][b],c):h[a][b]=c}function m(b){if(!(b in k)){k[b]=0;var d=b;do{if(c[d]>0){var h=e[j[d]];m(h),g[b]===b&&(g[b]=g[h]);var i=p(a,j[d])+p(a,d);g[b]!==g[h]?l(g[h],g[b],k[b]-k[h]-i):k[b]=Math.max(k[b],k[h]+i)}d=f[d]}while(d!==b)}}var g={},h={},i={},j={},k={};return b.forEach(function(a){a.forEach(function(b,c){g[b]=b,h[b]={},c>0&&(j[b]=a[c-1])})}),d.values(e).forEach(function(a){m(a)}),b.forEach(function(a){a.forEach(function(a){k[a]=k[e[a]];if(a===e[a]&&a===g[a]){var b=0;a in h&&Object.keys(h[a]).length>0&&(b=d.min(Object.keys(h[a]).map(function(b){return h[a][b]+(b in i?i[b]:0)}))),i[a]=b}})}),b.forEach(function(a){a.forEach(function(a){k[a]+=i[g[e[a]]]||0})}),k}function i(a,b,c){return d.min(b.map(function(a){var b=a[0];return c[b]}))}function j(a,b,c){return d.max(b.map(function(a){var b=a[a.length-1];return c[b]}))}function k(a,b,c){function h(a){c[l][a]+=g[l]}var d={},e={},f,g={},k=Number.POSITIVE_INFINITY;for(var l in c){var m=c[l];d[l]=i(a,b,m),e[l]=j(a,b,m);var n=e[l]-d[l];n<k&&(k=n,f=l)}["u","d"].forEach(function(a){["l","r"].forEach(function(b){var c=a+b;g[c]=b==="l"?d[f]-d[c]:e[f]-e[c]})});for(l in c)a.eachNode(h)}function l(a){for(var b in a)a[b]=-a[b]}function m(a){a.forEach(function(a){a.reverse()})}function n(a,b){switch(a.graph().rankDir){case"LR":return a.node(b).height;case"RL":return a.node(b).height;default:return a.node(b).width}}function o(a,b){switch(a.graph().rankDir){case"LR":return a.node(b).width;case"RL":return a.node(b).width;default:return a.node(b).height}}function p(b,c){if(a.universalSep!==null)return a.universalSep;var d=n(b,c),e=b.node(c).dummy?a.edgeSep:a.nodeSep;return(d+e)/2}function q(a,b,c){if(a.graph().rankDir==="LR"||a.graph().rankDir==="RL"){if(arguments.length<3)return a.node(b).y;a.node(b).y=c}else{if(arguments.length<3)return a.node(b).x;a.node(b).x=c}}function r(a,b,c,d){if(b.graph().rankDir==="LR"||b.graph().rankDir==="RL"){if(arguments.length<3)return b.node(c)[a];b.node(c)[a]=d}else{if(arguments.length<3)return b.node(c)[a];b.node(c)[a]=d}}function s(a,b,c){if(a.graph().rankDir==="LR"||a.graph().rankDir==="RL"){if(arguments.length<3)return a.node(b).x;a.node(b).x=c}else{if(arguments.length<3)return a.node(b).y;a.node(b).y=c}}function t(a,b,c,d){c.forEach(function(c,e){var f,g;c.forEach(function(c){var h=d[c];if(f){var i=p(b,f)+p(b,c);h-g<i&&console.log("Position phase: sep violation. Align: "+a+". Layer: "+e+". "+"U: "+f+" V: "+c+". Actual sep: "+(h-g)+" Expected sep: "+i)}f=c,g=h})})}var a={nodeSep:50,edgeSep:10,universalSep:null,rankSep:30},b={};return b.nodeSep=d.propertyAccessor(b,a,"nodeSep"),b.edgeSep=d.propertyAccessor(b,a,"edgeSep"),b.universalSep=d.propertyAccessor(b,a,"universalSep"),b.rankSep=d.propertyAccessor(b,a,"rankSep"),b.debugLevel=d.propertyAccessor(b,a,"debugLevel"),b.run=c,b}},{"./util":27}],20:[function(a,b,c){function l(a,b){n(a),d.time("constraints.apply",h.apply)(a),o(a),d.time("acyclic",e)(a);var c=a.filterNodes(d.filterNonSubgraphs(a));f(c),j(c).forEach(function(a){var d=c.filterNodes(k.nodesFromList(a));r(d,b)}),d.time("constraints.relax",h.relax(a)),d.time("reorientEdges",q)(a)}function m(a){e.undo(a)}function n(a){a.eachEdge(function(b,c,d,e){if(c===d){var f=p(a,b,c,d,e,0,!1),g=p(a,b,c,d,e,1,!0),h=p(a,b,c,d,e,2,!1);a.addEdge(null,f,c,{minLen:1,selfLoop:!0}),a.addEdge(null,f,g,{minLen:1,selfLoop:!0}),a.addEdge(null,c,h,{minLen:1,selfLoop:!0}),a.addEdge(null,g,h,{minLen:1,selfLoop:!0}),a.delEdge(b)}})}function o(a){a.eachEdge(function(b,c,d,e){if(c===d){var f=e.originalEdge,g=p(a,f.e,f.u,f.v,f.value,0,!0);a.addEdge(null,c,g,{minLen:1}),a.addEdge(null,g,d,{minLen:1}),a.delEdge(b)}})}function p(a,b,c,d,e,f,g){return a.addNode(null,{width:g?e.width:0,height:g?e.height:0,edge:{id:b,source:c,target:d,attrs:e},dummy:!0,index:f})}function q(a){a.eachEdge(function(b,c,d,e){a.node(c).rank>a.node(d).rank&&(a.delEdge(b),e.reversed=!0,a.addEdge(b,d,c,e))})}function r(a,b){var c=g(a);b&&(d.log(1,"Using network simplex for ranking"),i(a,c)),s(a)}function s(a){var b=d.min(a.nodes().map(function(b){return a.node(b).rank}));a.eachNode(function(a,c){c.rank-=b})}"use strict";var d=a("./util"),e=a("./rank/acyclic"),f=a("./rank/initRank"),g=a("./rank/feasibleTree"),h=a("./rank/constraints"),i=a("./rank/simplex"),j=a("graphlib").alg.components,k=a("graphlib").filter;c.run=l,c.restoreEdges=m},{"./rank/acyclic":21,"./rank/constraints":22,"./rank/feasibleTree":23,"./rank/initRank":24,"./rank/simplex":26,"./util":27,graphlib:29}],21:[function(a,b,c){function e(a){function f(d){if(d in c)return;c[d]=b[d]=!0,a.outEdges(d).forEach(function(c){var h=a.target(c),i;d===h?console.error('Warning: found self loop "'+c+'" for node "'+d+'"'):h in b?(i=a.edge(c),a.delEdge(c),i.reversed=!0,++e,a.addEdge(c,h,d,i)):f(h)}),delete b[d]}var b={},c={},e=0;return a.eachNode(function(a){f(a)}),d.log(2,"Acyclic Phase: reversed "+e+" edge(s)"),e}function f(a){a.eachEdge(function(b,c,d,e){e.reversed&&(delete e.reversed,a.delEdge(b),a.addEdge(b,d,c,e))})}"use strict";var d=a("../util");b.exports=e,b.exports.undo=f},{"../util":27}],22:[function(a,b,c){function d(a){return a!=="min"&&a!=="max"&&a.indexOf("same_")!==0?(console.error("Unsupported rank type: "+a),!1):!0}function e(a,b,c,d){a.inEdges(b).forEach(function(b){var e=a.edge(b),f;e.originalEdge?f=e:f={originalEdge:{e:b,u:a.source(b),v:a.target(b),value:e},minLen:a.edge(b).minLen},e.selfLoop&&(d=!1),d?(a.addEdge(null,c,a.source(b),f),f.reversed=!0):a.addEdge(null,a.source(b),c,f)})}function f(a,b,c,d){a.outEdges(b).forEach(function(b){var e=a.edge(b),f;e.originalEdge?f=e:f={originalEdge:{e:b,u:a.source(b),v:a.target(b),value:e},minLen:a.edge(b).minLen},e.selfLoop&&(d=!1),d?(a.addEdge(null,a.target(b),c,f),f.reversed=!0):a.addEdge(null,c,a.target(b),f)})}function g(a,b,c){c!==undefined&&a.children(b).forEach(function(b){b!==c&&!a.outEdges(c,b).length&&!a.node(b).dummy&&a.addEdge(null,c,b,{minLen:0})})}function h(a,b,c){c!==undefined&&a.children(b).forEach(function(b){b!==c&&!a.outEdges(b,c).length&&!a.node(b).dummy&&a.addEdge(null,b,c,{minLen:0})})}"use strict",c.apply=function(a){function b(c){var i={};a.children(c).forEach(function(g){if(a.children(g).length){b(g);return}var h=a.node(g),j=h.prefRank;if(j!==undefined){if(!d(j))return;j in i?i.prefRank.push(g):i.prefRank=[g];var k=i[j];k===undefined&&(k=i[j]=a.addNode(null,{originalNodes:[]}),a.parent(k,c)),e(a,g,k,j==="min"),f(a,g,k,j==="max"),a.node(k).originalNodes.push({u:g,value:h,parent:c}),a.delNode(g)}}),g(a,c,i.min),h(a,c,i.max)}b(null)},c.relax=function(a){var b=[];a.eachEdge(function(a,c,d,e){var f=e.originalEdge;f&&b.push(f)}),a.eachNode(function(b,c){var d=c.originalNodes;d&&(d.forEach(function(b){b.value.rank=c.rank,a.addNode(b.u,b.value),a.parent(b.u,b.parent)}),a.delNode(b))}),b.forEach(function(b){a.addEdge(b.e,b.u,b.v,b.value)})}},{}],23:[function(a,b,c){function g(a){function g(d){var e=!0;return a.predecessors(d).forEach(function(f){b.has(f)&&!h(a,f,d)&&(b.has(d)&&(c.addNode(d,{}),b.remove(d),c.graph({root:d})),c.addNode(f,{}),c.addEdge(null,f,d,{reversed:!0}),b.remove(f),g(f),e=!1)}),a.successors(d).forEach(function(f){b.has(f)&&!h(a,d,f)&&(b.has(d)&&(c.addNode(d,{}),b.remove(d),c.graph({root:d})),c.addNode(f,{}),c.addEdge(null,d,f,{}),b.remove(f),g(f),e=!1)}),e}function i(){var d=Number.MAX_VALUE;b.keys().forEach +(function(c){a.predecessors(c).forEach(function(e){if(!b.has(e)){var f=h(a,e,c);Math.abs(f)<Math.abs(d)&&(d=-f)}}),a.successors(c).forEach(function(e){if(!b.has(e)){var f=h(a,c,e);Math.abs(f)<Math.abs(d)&&(d=f)}})}),c.eachNode(function(b){a.node(b).rank-=d})}var b=new d(a.nodes()),c=new e;if(b.size()===1){var f=a.nodes()[0];return c.addNode(f,{}),c.graph({root:f}),c}while(b.size()){var j=c.order()?c.nodes():b.keys();for(var k=0,l=j.length;k<l&&g(j[k]);++k);b.size()&&i()}return c}function h(a,b,c){var d=a.node(c).rank-a.node(b).rank,e=f.max(a.outEdges(b,c).map(function(b){return a.edge(b).minLen}));return d-e}"use strict";var d=a("cp-data").Set,e=a("graphlib").Digraph,f=a("../util");b.exports=g},{"../util":27,"cp-data":5,graphlib:29}],24:[function(a,b,c){function f(a){var b=e(a);b.forEach(function(b){var c=a.inEdges(b);if(c.length===0){a.node(b).rank=0;return}var e=c.map(function(b){return a.node(a.source(b)).rank+a.edge(b).minLen});a.node(b).rank=d.max(e)})}"use strict";var d=a("../util"),e=a("graphlib").alg.topsort;b.exports=f},{"../util":27,graphlib:29}],25:[function(a,b,c){function d(a,b,c,d){return Math.abs(a.node(b).rank-a.node(c).rank)-d}"use strict",b.exports={slack:d}},{}],26:[function(a,b,c){function f(a,b){g(a,b);for(;;){var c=k(b);if(c===null)break;var d=l(a,b,c);m(a,b,c,d)}}function g(a,b){function c(d){var e=b.successors(d);for(var f in e){var g=e[f];c(g)}d!==b.graph().root&&i(a,b,d)}h(b),b.eachEdge(function(a,b,c,d){d.cutValue=0}),c(b.graph().root)}function h(a){function c(d){var e=a.successors(d),f=b;for(var g in e){var h=e[g];c(h),f=Math.min(f,a.node(h).low)}a.node(d).low=f,a.node(d).lim=b++}var b=0;c(a.graph().root)}function i(a,b,c){var d=b.inEdges(c)[0],e=[],f=b.outEdges(c);for(var g in f)e.push(b.target(f[g]));var h=0,i=0,k=0,l=0,m=0,n=a.outEdges(c),o;for(var p in n){var q=a.target(n[p]);for(o in e)j(b,q,e[o])&&i++;j(b,q,c)||l++}var r=a.inEdges(c);for(var s in r){var t=a.source(r[s]);for(o in e)j(b,t,e[o])&&k++;j(b,t,c)||m++}var u=0;for(o in e){var v=b.edge(f[o]).cutValue;b.edge(f[o]).reversed?u-=v:u+=v}b.edge(d).reversed?h-=u-i+k-l+m:h+=u-i+k-l+m,b.edge(d).cutValue=h}function j(a,b,c){return a.node(c).low<=a.node(b).lim&&a.node(b).lim<=a.node(c).lim}function k(a){var b=a.edges();for(var c in b){var d=b[c],e=a.edge(d);if(e.cutValue<0)return d}return null}function l(a,b,c){var d=b.source(c),f=b.target(c),g=b.node(f).lim<b.node(d).lim?f:d,h=!b.edge(c).reversed,i=Number.POSITIVE_INFINITY,k;h?a.eachEdge(function(d,f,h,l){if(d!==c&&j(b,f,g)&&!j(b,h,g)){var m=e.slack(a,f,h,l.minLen);m<i&&(i=m,k=d)}}):a.eachEdge(function(d,f,h,l){if(d!==c&&!j(b,f,g)&&j(b,h,g)){var m=e.slack(a,f,h,l.minLen);m<i&&(i=m,k=d)}});if(k===undefined){var l=[],m=[];throw a.eachNode(function(a){j(b,a,g)?m.push(a):l.push(a)}),new Error("No edge found from outside of tree to inside")}return k}function m(a,b,c,d){function h(a){var c=b.inEdges(a);for(var d in c){var e=c[d],f=b.source(e),g=b.edge(e);h(f),b.delEdge(e),g.reversed=!g.reversed,b.addEdge(e,a,f,g)}}b.delEdge(c);var e=a.source(d),f=a.target(d);h(f);var i=e,j=b.inEdges(i);while(j.length>0)i=b.source(j[0]),j=b.inEdges(i);b.graph().root=i,b.addEdge(null,e,f,{cutValue:0}),g(a,b),n(a,b)}function n(a,b){function c(d){var e=b.successors(d);e.forEach(function(b){var e=o(a,d,b);a.node(b).rank=a.node(d).rank+e,c(b)})}c(b.graph().root)}function o(a,b,c){var e=a.outEdges(b,c);if(e.length>0)return d.max(e.map(function(b){return a.edge(b).minLen}));var f=a.inEdges(b,c);if(f.length>0)return-d.max(f.map(function(b){return a.edge(b).minLen}))}"use strict";var d=a("../util"),e=a("./rankUtil");b.exports=f},{"../util":27,"./rankUtil":25}],27:[function(a,b,c){function d(a,b){return function(){var c=(new Date).getTime();try{return b.apply(null,arguments)}finally{e(1,a+" time: "+((new Date).getTime()-c)+"ms")}}}function e(a){e.level>=a&&console.log.apply(console,Array.prototype.slice.call(arguments,1))}"use strict",c.min=function(a){return Math.min.apply(Math,a)},c.max=function(a){return Math.max.apply(Math,a)},c.all=function(a,b){for(var c=0;c<a.length;++c)if(!b(a[c]))return!1;return!0},c.sum=function(a){return a.reduce(function(a,b){return a+b},0)},c.values=function(a){return Object.keys(a).map(function(b){return a[b]})},c.shuffle=function(a){for(var b=a.length-1;b>0;--b){var c=Math.floor(Math.random()*(b+1)),d=a[c];a[c]=a[b],a[b]=d}},c.propertyAccessor=function(a,b,c,d){return function(e){return arguments.length?(b[c]=e,d&&d(e),a):b[c]}},c.ordering=function(a){var b=[];return a.eachNode(function(a,c){var d=b[c.rank]||(b[c.rank]=[]);d[c.order]=a}),b},c.filterNonSubgraphs=function(a){return function(b){return a.children(b).length===0}},d.enabled=!1,c.time=d,e.level=0,c.log=e},{}],28:[function(a,b,c){b.exports="0.4.6"},{}],29:[function(a,b,c){c.Graph=a("./lib/Graph"),c.Digraph=a("./lib/Digraph"),c.CGraph=a("./lib/CGraph"),c.CDigraph=a("./lib/CDigraph"),a("./lib/graph-converters"),c.alg={isAcyclic:a("./lib/alg/isAcyclic"),components:a("./lib/alg/components"),dijkstra:a("./lib/alg/dijkstra"),dijkstraAll:a("./lib/alg/dijkstraAll"),findCycles:a("./lib/alg/findCycles"),floydWarshall:a("./lib/alg/floydWarshall"),postorder:a("./lib/alg/postorder"),preorder:a("./lib/alg/preorder"),prim:a("./lib/alg/prim"),tarjan:a("./lib/alg/tarjan"),topsort:a("./lib/alg/topsort")},c.converter={json:a("./lib/converter/json.js")};var d=a("./lib/filter");c.filter={all:d.all,nodesFromList:d.nodesFromList},c.version=a("./lib/version")},{"./lib/CDigraph":31,"./lib/CGraph":32,"./lib/Digraph":33,"./lib/Graph":34,"./lib/alg/components":35,"./lib/alg/dijkstra":36,"./lib/alg/dijkstraAll":37,"./lib/alg/findCycles":38,"./lib/alg/floydWarshall":39,"./lib/alg/isAcyclic":40,"./lib/alg/postorder":41,"./lib/alg/preorder":42,"./lib/alg/prim":43,"./lib/alg/tarjan":44,"./lib/alg/topsort":45,"./lib/converter/json.js":47,"./lib/filter":48,"./lib/graph-converters":49,"./lib/version":51}],30:[function(a,b,c){function e(){this._value=undefined,this._nodes={},this._edges={},this._nextId=0}function f(a,b,c){(a[b]||(a[b]=new d)).add(c)}function g(a,b,c){var d=a[b];d.remove(c),d.size()===0&&delete a[b]}var d=a("cp-data").Set;b.exports=e,e.prototype.order=function(){return Object.keys(this._nodes).length},e.prototype.size=function(){return Object.keys(this._edges).length},e.prototype.graph=function(a){if(arguments.length===0)return this._value;this._value=a},e.prototype.hasNode=function(a){return a in this._nodes},e.prototype.node=function(a,b){var c=this._strictGetNode(a);if(arguments.length===1)return c.value;c.value=b},e.prototype.nodes=function(){var a=[];return this.eachNode(function(b){a.push(b)}),a},e.prototype.eachNode=function(a){for(var b in this._nodes){var c=this._nodes[b];a(c.id,c.value)}},e.prototype.hasEdge=function(a){return a in this._edges},e.prototype.edge=function(a,b){var c=this._strictGetEdge(a);if(arguments.length===1)return c.value;c.value=b},e.prototype.edges=function(){var a=[];return this.eachEdge(function(b){a.push(b)}),a},e.prototype.eachEdge=function(a){for(var b in this._edges){var c=this._edges[b];a(c.id,c.u,c.v,c.value)}},e.prototype.incidentNodes=function(a){var b=this._strictGetEdge(a);return[b.u,b.v]},e.prototype.addNode=function(a,b){if(a===undefined||a===null){do a="_"+ ++this._nextId;while(this.hasNode(a))}else if(this.hasNode(a))throw new Error("Graph already has node '"+a+"'");return this._nodes[a]={id:a,value:b},a},e.prototype.delNode=function(a){this._strictGetNode(a),this.incidentEdges(a).forEach(function(a){this.delEdge(a)},this),delete this._nodes[a]},e.prototype._addEdge=function(a,b,c,d,e,g){this._strictGetNode(b),this._strictGetNode(c);if(a===undefined||a===null){do a="_"+ ++this._nextId;while(this.hasEdge(a))}else if(this.hasEdge(a))throw new Error("Graph already has edge '"+a+"'");return this._edges[a]={id:a,u:b,v:c,value:d},f(e[c],b,a),f(g[b],c,a),a},e.prototype._delEdge=function(a,b,c){var d=this._strictGetEdge(a);g(b[d.v],d.u,a),g(c[d.u],d.v,a),delete this._edges[a]},e.prototype.copy=function(){var a=new this.constructor;return a.graph(this.graph()),this.eachNode(function(b,c){a.addNode(b,c)}),this.eachEdge(function(b,c,d,e){a.addEdge(b,c,d,e)}),a._nextId=this._nextId,a},e.prototype.filterNodes=function(a){var b=new this.constructor;return b.graph(this.graph()),this.eachNode(function(c,d){a(c)&&b.addNode(c,d)}),this.eachEdge(function(a,c,d,e){b.hasNode(c)&&b.hasNode(d)&&b.addEdge(a,c,d,e)}),b},e.prototype._strictGetNode=function(a){var b=this._nodes[a];if(b===undefined)throw new Error("Node '"+a+"' is not in graph");return b},e.prototype._strictGetEdge=function(a){var b=this._edges[a];if(b===undefined)throw new Error("Edge '"+a+"' is not in graph");return b}},{"cp-data":5}],31:[function(a,b,c){var d=a("./Digraph"),e=a("./compoundify"),f=e(d);b.exports=f,f.fromDigraph=function(a){var b=new f,c=a.graph();return c!==undefined&&b.graph(c),a.eachNode(function(a,c){c===undefined?b.addNode(a):b.addNode(a,c)}),a.eachEdge(function(a,c,d,e){e===undefined?b.addEdge(null,c,d):b.addEdge(null,c,d,e)}),b},f.prototype.toString=function(){return"CDigraph "+JSON.stringify(this,null,2)}},{"./Digraph":33,"./compoundify":46}],32:[function(a,b,c){var d=a("./Graph"),e=a("./compoundify"),f=e(d);b.exports=f,f.fromGraph=function(a){var b=new f,c=a.graph();return c!==undefined&&b.graph(c),a.eachNode(function(a,c){c===undefined?b.addNode(a):b.addNode(a,c)}),a.eachEdge(function(a,c,d,e){e===undefined?b.addEdge(null,c,d):b.addEdge(null,c,d,e)}),b},f.prototype.toString=function(){return"CGraph "+JSON.stringify(this,null,2)}},{"./Graph":34,"./compoundify":46}],33:[function(a,b,c){function g(){e.call(this),this._inEdges={},this._outEdges={}}var d=a("./util"),e=a("./BaseGraph"),f=a("cp-data").Set;b.exports=g,g.prototype=new e,g.prototype.constructor=g,g.prototype.isDirected=function(){return!0},g.prototype.successors=function(a){return this._strictGetNode(a),Object.keys(this._outEdges[a]).map(function(a){return this._nodes[a].id},this)},g.prototype.predecessors=function(a){return this._strictGetNode(a),Object.keys(this._inEdges[a]).map(function(a){return this._nodes[a].id},this)},g.prototype.neighbors=function(a){return f.union([this.successors(a),this.predecessors(a)]).keys()},g.prototype.sources=function(){var a=this;return this._filterNodes(function(b){return a.inEdges(b).length===0})},g.prototype.sinks=function(){var a=this;return this._filterNodes(function(b){return a.outEdges(b).length===0})},g.prototype.source=function(a){return this._strictGetEdge(a).u},g.prototype.target=function(a){return this._strictGetEdge(a).v},g.prototype.inEdges=function(a,b){this._strictGetNode(a);var c=f.union(d.values(this._inEdges[a])).keys();return arguments.length>1&&(this._strictGetNode(b),c=c.filter(function(a){return this.source(a)===b},this)),c},g.prototype.outEdges=function(a,b){this._strictGetNode(a);var c=f.union(d.values(this._outEdges[a])).keys();return arguments.length>1&&(this._strictGetNode(b),c=c.filter(function(a){return this.target(a)===b},this)),c},g.prototype.incidentEdges=function(a,b){return arguments.length>1?f.union([this.outEdges(a,b),this.outEdges(b,a)]).keys():f.union([this.inEdges(a),this.outEdges(a)]).keys()},g.prototype.toString=function(){return"Digraph "+JSON.stringify(this,null,2)},g.prototype.addNode=function(a,b){return a=e.prototype.addNode.call(this,a,b),this._inEdges[a]={},this._outEdges[a]={},a},g.prototype.delNode=function(a){e.prototype.delNode.call(this,a),delete this._inEdges[a],delete this._outEdges[a]},g.prototype.addEdge=function(a,b,c,d){return e.prototype._addEdge.call(this,a,b,c,d,this._inEdges,this._outEdges)},g.prototype.delEdge=function(a){e.prototype._delEdge.call(this,a,this._inEdges,this._outEdges)},g.prototype._filterNodes=function(a){var b=[];return this.eachNode(function(c){a(c)&&b.push(c)}),b}},{"./BaseGraph":30,"./util":50,"cp-data":5}],34:[function(a,b,c){function g(){e.call(this),this._incidentEdges={}}var d=a("./util"),e=a("./BaseGraph"),f=a("cp-data").Set;b.exports=g,g.prototype=new e,g.prototype.constructor=g,g.prototype.isDirected=function(){return!1},g.prototype.neighbors=function(a){return this._strictGetNode(a),Object.keys(this._incidentEdges[a]).map(function(a){return this._nodes[a].id},this)},g.prototype.incidentEdges=function(a,b){return this._strictGetNode(a),arguments.length>1?(this._strictGetNode(b),b in this._incidentEdges[a]?this._incidentEdges[a][b].keys():[]):f.union(d.values(this._incidentEdges[a])).keys()},g.prototype.toString=function(){return"Graph "+JSON.stringify(this,null,2)},g.prototype.addNode=function(a,b){return a=e.prototype.addNode.call(this,a,b),this._incidentEdges[a]={},a},g.prototype.delNode=function(a){e.prototype.delNode.call(this,a),delete this._incidentEdges[a]},g.prototype.addEdge=function(a,b,c,d){return e.prototype._addEdge.call(this,a,b,c,d,this._incidentEdges,this._incidentEdges)},g.prototype.delEdge=function(a){e.prototype._delEdge.call(this,a,this._incidentEdges,this._incidentEdges)}},{"./BaseGraph":30,"./util":50,"cp-data":5}],35:[function(a,b,c){function e(a){function e(b,d){c.has(b)||(c.add(b),d.push(b),a.neighbors(b).forEach(function(a){e(a,d)}))}var b=[],c=new d;return a.nodes().forEach(function(a){var c=[];e(a,c),c.length>0&&b.push(c)}),b}var d=a("cp-data").Set;b.exports=e},{"cp-data":5}],36:[function(a,b,c){function e(a,b,c,e){function h(b){var d=a.incidentNodes(b),e=d[0]!==i?d[0]:d[1],h=f[e],k=c(b),l=j.distance+k;if(k<0)throw new Error("dijkstra does not allow negative edge weights. Bad edge: "+b+" Weight: "+k);l<h.distance&&(h.distance=l,h.predecessor=i,g.decrease(e,l))}var f={},g=new d;c=c||function(){return 1},e=e||(a.isDirected()?function(b){return a.outEdges(b)}:function(b){return a.incidentEdges(b)}),a.eachNode(function(a){var c=a===b?0:Number.POSITIVE_INFINITY;f[a]={distance:c},g.add(a,c)});var i,j;while(g.size()>0){i=g.removeMin(),j=f[i];if(j.distance===Number.POSITIVE_INFINITY)break;e(i).forEach(h)}return f}var d=a("cp-data").PriorityQueue;b.exports=e},{"cp-data":5}],37:[function(a,b,c){function e(a,b,c){var e={};return a.eachNode(function(f){e[f]=d(a,f,b,c)}),e}var d=a("./dijkstra");b.exports=e},{"./dijkstra":36}],38:[function(a,b,c){function e(a){return d(a).filter(function(a){return a.length>1})}var d=a("./tarjan");b.exports=e},{"./tarjan":44}],39:[function(a,b,c){function d(a,b,c){var d={},e=a.nodes();return b=b||function(){return 1},c=c||(a.isDirected()?function(b){return a.outEdges(b)}:function(b){return a.incidentEdges(b)}),e.forEach(function(f){d[f]={},d[f][f]={distance:0},e.forEach(function(a){f!==a&&(d[f][a]={distance:Number.POSITIVE_INFINITY})}),c(f).forEach(function(c){var e=a.incidentNodes(c),h=e[0]!==f?e[0]:e[1],i=b(c);i<d[f][h].distance&&(d[f][h]={distance:i,predecessor:f})})}),e.forEach(function(a){var b=d[a];e.forEach(function(c){var f=d[c];e.forEach(function(c){var d=f[a],e=b[c],g=f[c],h=d.distance+e.distance;h<g.distance&&(g.distance=h,g.predecessor=e.predecessor)})})}),d}b.exports=d},{}],40:[function(a,b,c){function e(a){try{d(a)}catch(b){if(b instanceof d.CycleException)return!1;throw b}return!0}var d=a("./topsort");b.exports=e},{"./topsort":45}],41:[function(a,b,c){function e(a,b,c){function f(b,d){if(e.has(b))throw new Error("The input graph is not a tree: "+a);e.add(b),a.neighbors(b).forEach(function(a){a!==d&&f(a,b)}),c(b)}var e=new d;if(a.isDirected())throw new Error("This function only works for undirected graphs");f(b)}var d=a("cp-data").Set;b.exports=e},{"cp-data":5}],42:[function(a,b,c){function e(a,b,c){function f(b,d){if(e.has(b))throw new Error("The input graph is not a tree: "+a);e.add(b),c(b),a.neighbors(b).forEach(function(a){a!==d&&f(a,b)})}var e=new d;if(a.isDirected())throw new Error("This function only works for undirected graphs");f(b)}var d=a("cp-data").Set;b.exports=e},{"cp-data":5}],43:[function(a,b,c){function f(a,b){function i(c){var d=a.incidentNodes(c),e=d[0]!==h?d[0]:d[1],i=g.priority(e);if(i!==undefined){var j=b(c);j<i&&(f[e]=h,g.decrease(e,j))}}var c=new d,f={},g=new e,h;if(a.order()===0)return c;a.eachNode(function(a){g.add(a,Number.POSITIVE_INFINITY),c.addNode(a)}),g.decrease(a.nodes()[0],0);var j=!1;while(g.size()>0){h=g.removeMin();if(h in f)c.addEdge(null,h,f[h]);else{if(j)throw new Error("Input graph is not connected: "+a);j=!0}a.incidentEdges(h).forEach(i)}return c}var d=a("../Graph"),e=a("cp-data").PriorityQueue;b.exports=f},{"../Graph":34,"cp-data":5}],44:[function(a,b,c){function d(a){function f(h){var i=d[h]={onStack:!0,lowlink:b,index:b++};c.push(h),a.successors(h).forEach(function(a){a in d?d[a].onStack&&(i.lowlink=Math.min(i.lowlink,d[a].index)):(f(a),i.lowlink=Math.min(i.lowlink,d[a].lowlink))});if(i.lowlink===i.index){var j=[],k;do k=c.pop(),d[k].onStack=!1,j.push(k);while(h!==k);e.push(j)}}if(!a.isDirected())throw new Error("tarjan can only be applied to a directed graph. Bad input: "+a);var b=0,c=[],d={},e=[];return a.nodes().forEach(function(a){a in d||f(a)}),e}b.exports=d},{}],45:[function(a,b,c){function d(a){function f(g){if(g in c)throw new e;g in b||(c[g]=!0,b[g]=!0,a.predecessors(g).forEach(function(a){f(a)}),delete c[g],d.push(g))}if(!a.isDirected())throw new Error("topsort can only be applied to a directed graph. Bad input: "+a);var b={},c={},d=[],g=a.sinks();if(a.order()!==0&&g.length===0)throw new e;return a.sinks().forEach(function(a){f(a)}),d}function e(){}b.exports=d,d.CycleException=e,e.prototype.toString=function(){return"Graph has at least one cycle"}},{}],46:[function(a,b,c){function e(a){function b(){a.call(this),this._parents={},this._children={},this._children[null]=new d}return b.prototype=new a,b.prototype.constructor=b,b.prototype.parent=function(a,b){this._strictGetNode(a);if(arguments.length<2)return this._parents[a];if(a===b)throw new Error("Cannot make "+a+" a parent of itself");b!==null&&this._strictGetNode(b),this._children[this._parents[a]].remove(a),this._parents[a]=b,this._children[b].add(a)},b.prototype.children=function(a){return a!==null&&this._strictGetNode(a),this._children[a].keys()},b.prototype.addNode=function(b,c){return b=a.prototype.addNode.call(this,b,c),this._parents[b]=null,this._children[b]=new d,this._children[null].add(b),b},b.prototype.delNode=function(b){var c=this.parent(b);return this._children[b].keys().forEach(function(a){this.parent(a,c)},this),this._children[c].remove(b),delete this._parents[b],delete this._children[b],a.prototype.delNode.call(this,b)},b.prototype.copy=function(){var b=a.prototype.copy.call(this);return this.nodes().forEach(function(a){b.parent(a,this.parent(a))},this),b},b.prototype.filterNodes=function(b){function f(a){var b=c.parent(a);return b===null||d.hasNode(b)?(e[a]=b,b):b in e?e[b]:f(b)}var c=this,d=a.prototype.filterNodes.call(this,b),e={};return d.eachNode(function(a){d.parent(a,f(a))}),d},b}var d=a("cp-data").Set;b.exports=e},{"cp-data":5}],47:[function(a,b,c){function h(a){return Object.prototype.toString.call(a).slice(8,-1)}var d=a("../Graph"),e=a("../Digraph"),f=a("../CGraph"),g=a("../CDigraph");c.decode=function(a,b,c){c=c||e;if(h(a)!=="Array")throw new Error("nodes is not an Array");if(h(b)!=="Array")throw new Error("edges is not an Array");if(typeof c=="string")switch(c){case"graph":c=d;break;case"digraph":c=e;break;case"cgraph":c=f;break;case"cdigraph":c=g;break;default:throw new Error("Unrecognized graph type: "+c)}var i=new c;return a.forEach(function(a){i.addNode(a.id,a.value)}),i.parent&&a.forEach(function(a){a.children&&a.children.forEach(function(b){i.parent(b,a.id)})}),b.forEach(function(a){i.addEdge(a.id,a.u,a.v,a.value)}),i},c.encode=function(a){var b=[],c=[];a.eachNode(function(c,d){var e={id:c,value:d};if(a.children){var f=a.children(c);f.length&&(e.children=f)}b.push(e)}),a.eachEdge(function(a,b,d,e){c.push({id:a,u:b,v:d,value:e})});var h;if(a instanceof g)h="cdigraph";else if(a instanceof f)h="cgraph";else if(a instanceof e)h="digraph";else if(a instanceof d)h="graph";else throw new Error("Couldn't determine type of graph: "+a);return{nodes:b,edges:c,type:h}}},{"../CDigraph":31,"../CGraph":32,"../Digraph":33,"../Graph":34}],48:[function(a,b,c){var d=a("cp-data").Set;c.all=function(){return function(){return!0}},c.nodesFromList=function(a){var b=new d(a);return function(a){return b.has(a)}}},{"cp-data":5}],49:[function(a,b,c){var d=a("./Graph"),e=a("./Digraph");d.prototype.toDigraph=d.prototype.asDirected=function(){var a=new e;return this.eachNode(function(b,c){a.addNode(b,c)}),this.eachEdge(function(b,c,d,e){a.addEdge(null,c,d,e),a.addEdge(null,d,c,e)}),a},e.prototype.toGraph=e.prototype.asUndirected=function(){var a=new d;return this.eachNode(function(b,c){a.addNode(b,c)}),this.eachEdge(function(b,c,d,e){a.addEdge(b,c,d,e)}),a}},{"./Digraph":33,"./Graph":34}],50:[function(a,b,c){c.values=function(a){var b=Object.keys(a),c=b.length,d=new Array(c),e;for(e=0;e<c;++e)d[e]=a[b[e]];return d}},{}],51:[function(a,b,c){b.exports="0.7.4"},{}]},{},[1]); \ No newline at end of file diff --git a/src/static/dagre-d3/graphlib-dot.min.js b/src/static/dagre-d3/graphlib-dot.min.js new file mode 100644 index 0000000..90051da --- /dev/null +++ b/src/static/dagre-d3/graphlib-dot.min.js @@ -0,0 +1,2 @@ +(function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var j=typeof require=="function"&&require;if(!h&&j)return j(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}var f=typeof require=="function"&&require;for(var g=0;g<d.length;g++)e(d[g]);return e})({1:[function(a,b,c){var d=typeof self!="undefined"?self:typeof window!="undefined"?window:{};d.graphlibDot=a("./index")},{"./index":2}],2:[function(a,b,c){var d=a("./lib/parse"),e=a("./lib/write"),f=a("./lib/version");b.exports={DotGraph:a("./lib/DotGraph"),DotDigraph:a("./lib/DotDigraph"),parse:d,decode:d,parseMany:d.parseMany,write:e,encode:e,version:f,type:"dot",buffer:!1}},{"./lib/DotDigraph":3,"./lib/DotGraph":4,"./lib/parse":8,"./lib/version":9,"./lib/write":10}],3:[function(a,b,c){var d=a("graphlib").CDigraph,e=a("./dotify"),f=e(d);b.exports=f,f.fromDigraph=function(a){var b=new f,c=a.graph();return c!==undefined&&b.graph(c),a.eachNode(function(a,c){c===undefined?b.addNode(a):b.addNode(a,c)}),a.eachEdge(function(a,c,d,e){e===undefined?b.addEdge(null,c,d):b.addEdge(null,c,d,e)}),b}},{"./dotify":7,graphlib:11}],4:[function(a,b,c){var d=a("graphlib").CGraph,e=a("./dotify"),f=e(d);b.exports=f,f.fromGraph=function(a){var b=new f,c=a.graph();return c!==undefined&&b.graph(c),a.eachNode(function(a,c){c===undefined?b.addNode(a):b.addNode(a,c)}),a.eachEdge(function(a,c,d,e){e===undefined?b.addEdge(null,c,d):b.addEdge(null,c,d,e)}),b}},{"./dotify":7,graphlib:11}],5:[function(a,b,c){function e(){this._indent="",this._content="",this._shouldIndent=!0}b.exports=e;var d=" ";e.prototype.indent=function(){this._indent+=d},e.prototype.unindent=function(){this._indent=this._indent.slice(d.length)},e.prototype.writeLine=function(a){this.write((a||"")+"\n"),this._shouldIndent=!0},e.prototype.write=function(a){this._shouldIndent&&(this._shouldIndent=!1,this._content+=this._indent),this._content+=a},e.prototype.toString=function(){return this._content}},{}],6:[function(a,b,c){b.exports=function(){function a(a){return'"'+a.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\x08/g,"\\b").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\f/g,"\\f").replace(/\r/g,"\\r").replace(/[\x00-\x07\x0B\x0E-\x1F\x80-\uFFFF]/g,escape)+'"'}var b={parse:function(b,c){function i(a,b,c){var d=a,e=c-a.length;for(var f=0;f<e;f++)d=b+d;return d}function j(a){var b=a.charCodeAt(0),c,d;return b<=255?(c="x",d=2):(c="u",d=4),"\\"+c+i(b.toString(16).toUpperCase(),"0",d)}function k(a){if(e<g)return;e>g&&(g=e,h=[]),h.push(a)}function l(){var a,b;b=m();if(b!==null){a=[];while(b!==null)a.push(b),b=m()}else a=null;return a}function m(){var a,c,d,g,h,i,j,l,m,o,p,q,r,s,t,u;s=e,t=e,a=[],c=N();while(c!==null)a.push(c),c=N();if(a!==null){u=e,c=J(),c!==null?(d=N(),d!==null?c=[c,d]:(c=null,e=u)):(c=null,e=u),c=c!==null?c:"";if(c!==null){d=K();if(d!==null){g=[],h=N();while(h!==null)g.push(h),h=N();if(g!==null){h=D(),h=h!==null?h:"";if(h!==null){i=[],j=N();while(j!==null)i.push(j),j=N();if(i!==null){b.charCodeAt(e)===123?(j="{",e++):(j=null,f===0&&k('"{"'));if(j!==null){l=[],m=N();while(m!==null)l.push(m),m=N();if(l!==null){m=n(),m=m!==null?m:"";if(m!==null){o=[],p=N();while(p!==null)o.push(p),p=N();if(o!==null){b.charCodeAt(e)===125?(p="}",e++):(p=null,f===0&&k('"}"'));if(p!==null){q=[],r=N();while(r!==null)q.push(r),r=N();q!==null?a=[a,c,d,g,h,i,j,l,m,o,p,q]:(a=null,e=t)}else a=null,e=t}else a=null,e=t}else a=null,e=t}else a=null,e=t}else a=null,e=t}else a=null,e=t}else a=null,e=t}else a=null,e=t}else a=null,e=t}else a=null,e=t}else a=null,e=t;return a!==null&&(a=function(a,b,c,d){return{type:b,id:c,stmts:d}}(s,a[2],a[4],a[8])),a===null&&(e=s),a}function n(){var a,c,d,g,h,i,j,l,m,n,p;m=e,n=e,a=o();if(a!==null){c=[],d=N();while(d!==null)c.push(d),d=N();if(c!==null){b.charCodeAt(e)===59?(d=";",e++):(d=null,f===0&&k('";"')),d=d!==null?d:"";if(d!==null){g=[],p=e,h=[],i=N();while(i!==null)h.push(i),i=N();if(h!==null){i=o();if(i!==null){j=[],l=N();while(l!==null)j.push(l),l=N();j!==null?(b.charCodeAt(e)===59?(l=";",e++):(l=null,f===0&&k('";"')),l=l!==null?l:"",l!==null?h=[h,i,j,l]:(h=null,e=p)):(h=null,e=p)}else h=null,e=p}else h=null,e=p;while(h!==null){g.push(h),p=e,h=[],i=N();while(i!==null)h.push(i),i=N();if(h!==null){i=o();if(i!==null){j=[],l=N();while(l!==null)j.push(l),l=N();j!==null?(b.charCodeAt(e)===59?(l=";",e++):(l=null,f===0&&k('";"')),l=l!==null?l:"",l!==null?h=[h,i,j,l]:(h=null,e=p)):(h=null,e=p)}else h=null,e=p}else h=null,e=p}g!==null?a=[a,c,d,g]:(a=null,e=n)}else a=null,e=n}else a=null,e=n}else a=null,e=n;return a!==null&&(a=function(a,b,c){var d=[b];for(var e=0;e<c.length;++e)d.push(c[e][1]);return d}(m,a[0],a[3])),a===null&&(e=m),a}function o(){var a;return a=p(),a===null&&(a=s(),a===null&&(a=t(),a===null&&(a=q(),a===null&&(a=r())))),a}function p(){var a,b,c,d,f;d=e,f=e,a=G(),a===null&&(a=E(),a===null&&(a=F()));if(a!==null){b=[],c=N();while(c!==null)b.push(c),c=N();b!==null?(c=u(),c!==null?a=[a,b,c]:(a=null,e=f)):(a=null,e=f)}else a=null,e=f;return a!==null&&(a=function(a,b,c){return{type:"attr",attrType:b,attrs:c||{}}}(d,a[0],a[2])),a===null&&(e=d),a}function q(){var a,c,d,g,h,i,j;i=e,j=e,a=D();if(a!==null){c=[],d=N();while(d!==null)c.push(d),d=N();if(c!==null){b.charCodeAt(e)===61?(d="=",e++):(d=null,f===0&&k('"="'));if(d!==null){g=[],h=N();while(h!==null)g.push(h),h=N();g!==null?(h=D(),h!==null?a=[a,c,d,g,h]:(a=null,e=j)):(a=null,e=j)}else a=null,e=j}else a=null,e=j}else a=null,e=j;return a!==null&&(a=function(a,b,c){var d={};return d[b]=c,{type:"inlineAttr",attrs:d}}(i,a[0],a[4])),a===null&&(e=i),a}function r(){var a,b,c,d,f;d=e,f=e,a=A();if(a!==null){b=[],c=N();while(c!==null)b.push(c),c=N();b!==null?(c=u(),c=c!==null?c:"",c!==null?a=[a,b,c]:(a=null,e=f)):(a=null,e=f)}else a=null,e=f;return a!==null&&(a=function(a,b,c){return{type:"node",id:b,attrs:c||{}}}(d,a[0],a[2])),a===null&&(e=d),a}function s(){var a,b,c,d,f,g,h;g=e,h=e,a=z();if(a!==null){b=[],c=N();while(c!==null)b.push(c),c=N();if(b!==null){c=x();if(c!==null){d=[],f=N();while(f!==null)d.push(f),f=N();d!==null?(f=u(),f=f!==null?f:"",f!==null?a=[a,b,c,d,f]:(a=null,e=h)):(a=null,e=h)}else a=null,e=h}else a=null,e=h}else a=null,e=h;return a!==null&&(a=function(a,b,c,d){var e=[b];for(var f=0;f<c.length;++f)e.push(c[f]);return{type:"edge",elems:e,attrs:d||{}}}(g,a[0],a[2],a[4])),a===null&&(e=g),a}function t(){var a,c,d,g,h,i,j,l,m,o;j=e,l=e,m=e,a=I();if(a!==null){c=[],d=N();while(d!==null)c.push(d),d=N();if(c!==null){o=e,d=D();if(d!==null){g=[],h=N();while(h!==null)g.push(h),h=N();g!==null?d=[d,g]:(d=null,e=o)}else d=null,e=o;d=d!==null?d:"",d!==null?a=[a,c,d]:(a=null,e=m)}else a=null,e=m}else a=null,e=m;a=a!==null?a:"";if(a!==null){b.charCodeAt(e)===123?(c="{",e++):(c=null,f===0&&k('"{"'));if(c!==null){d=[],g=N();while(g!==null)d.push(g),g=N();if(d!==null){g=n(),g=g!==null?g:"";if(g!==null){h=[],i=N();while(i!==null)h.push(i),i=N();h!==null?(b.charCodeAt(e)===125?(i="}",e++):(i=null,f===0&&k('"}"')),i!==null?a=[a,c,d,g,h,i]:(a=null,e=l)):(a=null,e=l)}else a=null,e=l}else a=null,e=l}else a=null,e=l}else a=null,e=l;return a!==null&&(a=function(a,b,c){return b=b[2]||[],{type:"subgraph",id:b[0],stmts:c}}(j,a[0],a[3])),a===null&&(e=j),a}function u(){var a,b,c,d,f,g,h;f=e,g=e,a=v();if(a!==null){b=[],h=e,c=[],d=N();while(d!==null)c.push(d),d=N();c!==null?(d=v(),d!==null?c=[c,d]:(c=null,e=h)):(c=null,e=h);while(c!==null){b.push(c),h=e,c=[],d=N();while(d!==null)c.push(d),d=N();c!==null?(d=v(),d!==null?c=[c,d]:(c=null,e=h)):(c=null,e=h)}b!==null?a=[a,b]:(a=null,e=g)}else a=null,e=g;return a!==null&&(a=function(a,b,c){var d=b;for(var e=0;e<c.length;++e)d=R(d,c[e][1]);return d}(f,a[0],a[1])),a===null&&(e=f),a}function v(){var a,c,d,g,h,i,j;i=e,j=e,b.charCodeAt(e)===91?(a="[",e++):(a=null,f===0&&k('"["'));if(a!==null){c=[],d=N();while(d!==null)c.push(d),d=N();if(c!==null){d=w(),d=d!==null?d:"";if(d!==null){g=[],h=N();while(h!==null)g.push(h),h=N();g!==null?(b.charCodeAt(e)===93?(h="]",e++):(h=null,f===0&&k('"]"')),h!==null?a=[a,c,d,g,h]:(a=null,e=j)):(a=null,e=j)}else a=null,e=j}else a=null,e=j}else a=null,e=j;return a!==null&&(a=function(a,b){return b}(i,a[2])),a===null&&(e=i),a}function w(){var a,c,d,g,h,i,j,l,m;j=e,l=e,a=y();if(a!==null){c=[],m=e,d=[],g=N();while(g!==null)d.push(g),g=N();if(d!==null){b.charCodeAt(e)===44?(g=",",e++):(g=null,f===0&&k('","')),g=g!==null?g:"";if(g!==null){h=[],i=N();while(i!==null)h.push(i),i=N();h!==null?(i=y(),i!==null?d=[d,g,h,i]:(d=null,e=m)):(d=null,e=m)}else d=null,e=m}else d=null,e=m;while(d!==null){c.push(d),m=e,d=[],g=N();while(g!==null)d.push(g),g=N();if(d!==null){b.charCodeAt(e)===44?(g=",",e++):(g=null,f===0&&k('","')),g=g!==null?g:"";if(g!==null){h=[],i=N();while(i!==null)h.push(i),i=N();h!==null?(i=y(),i!==null?d=[d,g,h,i]:(d=null,e=m)):(d=null,e=m)}else d=null,e=m}else d=null,e=m}c!==null?a=[a,c]:(a=null,e=l)}else a=null,e=l;return a!==null&&(a=function(a,b,c){var d=b;for(var e=0;e<c.length;++e)d=R(d,c[e][3]);return d}(j,a[0],a[1])),a===null&&(e=j),a}function x(){var a,c,d,g,h,i,j,l;i=e,j=e,l=e,b.substr(e,2)==="--"?(a="--",e+=2):(a=null,f===0&&k('"--"')),a!==null?(c=function(a){return Q}(e)?null:"",c!==null?a=[a,c]:(a=null,e=l)):(a=null,e=l),a===null&&(l=e,b.substr(e,2)==="->"?(a="->",e+=2):(a=null,f===0&&k('"->"')),a!==null?(c=function(a){return Q}(e)?"":null,c!==null?a=[a,c]:(a=null,e=l)):(a=null,e=l));if(a!==null){c=[],d=N();while(d!==null)c.push(d),d=N();if(c!==null){d=z();if(d!==null){g=[],h=N();while(h!==null)g.push(h),h=N();g!==null?(h=x(),h=h!==null?h:"",h!==null?a=[a,c,d,g,h]:(a=null,e=j)):(a=null,e=j)}else a=null,e=j}else a=null,e=j}else a=null,e=j;return a!==null&&(a=function(a,b,c){var d=[b];for(var e=0;e<c.length;++e)d.push(c[e]);return d}(i,a[2],a[4])),a===null&&(e=i),a}function y(){var a,c,d,g,h,i,j,l;i=e,j=e,a=D();if(a!==null){l=e,c=[],d=N();while(d!==null)c.push(d),d=N();if(c!==null){b.charCodeAt(e)===61?(d="=",e++):(d=null,f===0&&k('"="'));if(d!==null){g=[],h=N();while(h!==null)g.push(h),h=N();g!==null?(h=D(),h!==null?c=[c,d,g,h]:(c=null,e=l)):(c=null,e=l)}else c=null,e=l}else c=null,e=l;c=c!==null?c:"",c!==null?a=[a,c]:(a=null,e=j)}else a=null,e=j;return a!==null&&(a=function(a,b,c){var d={};return d[b]=c[3],d}(i,a[0],a[1])),a===null&&(e=i),a}function z(){var a,b;return a=t(),a===null&&(b=e,a=A(),a!==null&&(a=function(a,b){return{type:"node",id:b,attrs:{}}}(b,a)),a===null&&(e=b)),a}function A(){var a,b,c,d,f;d=e,f=e,a=D();if(a!==null){b=[],c=N();while(c!==null)b.push(c),c=N();b!==null?(c=B(),c=c!==null?c:"",c!==null?a=[a,b,c]:(a=null,e=f)):(a=null,e=f)}else a=null,e=f;return a!==null&&(a=function(a,b){return b}(d,a[0])),a===null&&(e=d),a}function B(){var a,c,d,g,h,i,j,l,m;l=e,b.charCodeAt(e)===58?(a=":",e++):(a=null,f===0&&k('":"'));if(a!==null){c=[],d=N();while(d!==null)c.push(d),d=N();if(c!==null){d=D();if(d!==null){g=[],h=N();while(h!==null)g.push(h),h=N();if(g!==null){m=e,b.charCodeAt(e)===58?(h=":",e++):(h=null,f===0&&k('":"'));if(h!==null){i=[],j=N();while(j!==null)i.push(j),j=N();i!==null?(j=C(),j!==null?h=[h,i,j]:(h=null,e=m)):(h=null,e=m)}else h=null,e=m;h=h!==null?h:"",h!==null?a=[a,c,d,g,h]:(a=null,e=l)}else a=null,e=l}else a=null,e=l}else a=null,e=l}else a=null,e=l;return a}function C(){var a;return b.substr(e,2)==="ne"?(a="ne",e+=2):(a=null,f===0&&k('"ne"')),a===null&&(b.substr(e,2)==="se"?(a="se",e+=2):(a=null,f===0&&k('"se"')),a===null&&(b.substr(e,2)==="sw"?(a="sw",e+=2):(a=null,f===0&&k('"sw"')),a===null&&(b.substr(e,2)==="nw"?(a="nw",e+=2):(a=null,f===0&&k('"nw"')),a===null&&(b.charCodeAt(e)===110?(a="n",e++):(a=null,f===0&&k('"n"')),a===null&&(b.charCodeAt(e)===101?(a="e",e++):(a=null,f===0&&k('"e"')),a===null&&(b.charCodeAt(e)===115?(a="s",e++):(a=null,f===0&&k('"s"')),a===null&&(b.charCodeAt(e)===119?(a="w",e++):(a=null,f===0&&k('"w"')),a===null&&(b.charCodeAt(e)===99?(a="c",e++):(a=null,f===0&&k('"c"')),a===null&&(b.charCodeAt(e)===95?(a="_",e++):(a=null,f===0&&k('"_"'))))))))))),a}function D(){var a,c,d,g,h,i,j,l,m;f++,i=e,j=e,/^[a-zA-Z\u0200-\u0377_]/.test(b.charAt(e))?(a=b.charAt(e),e++):(a=null,f===0&&k("[a-zA-Z\\u0200-\\u0377_]"));if(a!==null){c=[],/^[a-zA-Z\u0200-\u0377_0-9]/.test(b.charAt(e))?(d=b.charAt(e),e++):(d=null,f===0&&k("[a-zA-Z\\u0200-\\u0377_0-9]"));while(d!==null)c.push(d),/^[a-zA-Z\u0200-\u0377_0-9]/.test(b.charAt(e))?(d=b.charAt(e),e++):(d=null,f===0&&k("[a-zA-Z\\u0200-\\u0377_0-9]"));c!==null?a=[a,c]:(a=null,e=j)}else a=null,e=j;a!==null&&(a=function(a,b,c){return b+c.join("")}(i,a[0],a[1])),a===null&&(e=i);if(a===null){i=e,j=e,b.charCodeAt(e)===45?(a="-",e++):(a=null,f===0&&k('"-"')),a=a!==null?a:"";if(a!==null){b.charCodeAt(e)===46?(c=".",e++):(c=null,f===0&&k('"."'));if(c!==null){/^[0-9]/.test(b.charAt(e))?(g=b.charAt(e),e++):(g=null,f===0&&k("[0-9]"));if(g!==null){d=[];while(g!==null)d.push(g),/^[0-9]/.test(b.charAt(e))?(g=b.charAt(e),e++):(g=null,f===0&&k("[0-9]"))}else d=null;d!==null?a=[a,c,d]:(a=null,e=j)}else a=null,e=j}else a=null,e=j;a!==null&&(a=function(a,b,c,d){return b+c+d.join("")}(i,a[0],a[1],a[2])),a===null&&(e=i);if(a===null){i=e,j=e,b.charCodeAt(e)===45?(a="-",e++):(a=null,f===0&&k('"-"')),a=a!==null?a:"";if(a!==null){/^[0-9]/.test(b.charAt(e))?(d=b.charAt(e),e++):(d=null,f===0&&k("[0-9]"));if(d!==null){c=[];while(d!==null)c.push(d),/^[0-9]/.test(b.charAt(e))?(d=b.charAt(e),e++):(d=null,f===0&&k("[0-9]"))}else c=null;if(c!==null){l=e,b.charCodeAt(e)===46?(d=".",e++):(d=null,f===0&&k('"."'));if(d!==null){g=[],/^[0-9]/.test(b.charAt(e))?(h=b.charAt(e),e++):(h=null,f===0&&k("[0-9]"));while(h!==null)g.push(h),/^[0-9]/.test(b.charAt(e))?(h=b.charAt(e),e++):(h=null,f===0&&k("[0-9]"));g!==null?d=[d,g]:(d=null,e=l)}else d=null,e=l;d=d!==null?d:"",d!==null?a=[a,c,d]:(a=null,e=j)}else a=null,e=j}else a=null,e=j;a!==null&&(a=function(a,b,c,d){return b+c.join("")+(d[0]||"")+(d[1]||[]).join("")}(i,a[0],a[1],a[2])),a===null&&(e=i);if(a===null){i=e,j=e,b.charCodeAt(e)===34?(a='"',e++):(a=null,f===0&&k('"\\""'));if(a!==null){c=[],l=e,b.substr(e,2)==='\\"'?(d='\\"',e+=2):(d=null,f===0&&k('"\\\\\\""')),d!==null&&(d=function(a){return'"'}(l)),d===null&&(e=l),d===null&&(l=e,m=e,b.charCodeAt(e)===92?(d="\\",e++):(d=null,f===0&&k('"\\\\"')),d!==null?(/^[^"]/.test(b.charAt(e))?(g=b.charAt(e),e++):(g=null,f===0&&k('[^"]')),g!==null?d=[d,g]:(d=null,e=m)):(d=null,e=m),d!==null&&(d=function(a,b){return"\\"+b}(l,d[1])),d===null&&(e=l),d===null&&(/^[^"]/.test(b.charAt(e))?(d=b.charAt(e),e++):(d=null,f===0&&k('[^"]'))));while(d!==null)c.push(d),l=e,b.substr(e,2)==='\\"'?(d='\\"',e+=2):(d=null,f===0&&k('"\\\\\\""')),d!==null&&(d=function(a){return'"'}(l)),d===null&&(e=l),d===null&&(l=e,m=e,b.charCodeAt(e)===92?(d="\\",e++):(d=null,f===0&&k('"\\\\"')),d!==null?(/^[^"]/.test(b.charAt(e))?(g=b.charAt(e),e++):(g=null,f===0&&k('[^"]')),g!==null?d=[d,g]:(d=null,e=m)):(d=null,e=m),d!==null&&(d=function(a,b){return"\\"+b}(l,d[1])),d===null&&(e=l),d===null&&(/^[^"]/.test(b.charAt(e))?(d=b.charAt(e),e++):(d=null,f===0&&k('[^"]'))));c!==null?(b.charCodeAt(e)===34?(d='"',e++):(d=null,f===0&&k('"\\""')),d!==null?a=[a,c,d]:(a=null,e=j)):(a=null,e=j)}else a=null,e=j;a!==null&&(a=function(a,b){return b.join("")}(i,a[1])),a===null&&(e=i)}}}return f--,f===0&&a===null&&k("identifier"),a}function E(){var a,c;return c=e,b.substr(e,4).toLowerCase()==="node"?(a=b.substr(e,4),e+=4):(a=null,f===0&&k('"node"')),a!==null&&(a=function(a,b){return b.toLowerCase()}(c,a)),a===null&&(e=c),a}function F(){var a,c;return c=e,b.substr(e,4).toLowerCase()==="edge"?(a=b.substr(e,4),e+=4):(a=null,f===0&&k('"edge"')),a!==null&&(a=function(a,b){return b.toLowerCase()}(c,a)),a===null&&(e=c),a}function G(){var a,c;return c=e,b.substr(e,5).toLowerCase()==="graph"?(a=b.substr(e,5),e+=5):(a=null,f===0&&k('"graph"')),a!==null&&(a=function(a,b){return b.toLowerCase()}(c,a)),a===null&&(e=c),a}function H(){var a,c;return c=e,b.substr(e,7).toLowerCase()==="digraph"?(a=b.substr(e,7),e+=7):(a=null,f===0&&k('"digraph"')),a!==null&&(a=function(a,b){return b.toLowerCase()}(c,a)),a===null&&(e=c),a}function I(){var a,c;return c=e,b.substr(e,8).toLowerCase()==="subgraph"?(a=b.substr(e,8),e+=8):(a=null,f===0&&k('"subgraph"')),a!==null&&(a=function(a,b){return b.toLowerCase()}(c,a)),a===null&&(e=c),a}function J(){var a,c;return c=e,b.substr(e,6).toLowerCase()==="strict"?(a=b.substr(e,6),e+=6):(a=null,f===0&&k('"strict"')),a!==null&&(a=function(a,b){return b.toLowerCase()}(c,a)),a===null&&(e=c),a}function K(){var a,b;return a=G(),a===null&&(b=e,a=H(),a!==null&&(a=function(a,b){return Q=b==="digraph",b}(b,a)),a===null&&(e=b)),a}function L(){var a,c;f++,/^[ \t\r\n]/.test(b.charAt(e))?(c=b.charAt(e),e++):(c=null,f===0&&k("[ \\t\\r\\n]"));if(c!==null){a=[];while(c!==null)a.push(c),/^[ \t\r\n]/.test(b.charAt(e))?(c=b.charAt(e),e++):(c=null,f===0&&k("[ \\t\\r\\n]"))}else a=null;return f--,f===0&&a===null&&k("whitespace"),a}function M(){var a,c,d,g,h,i,j;f++,h=e,b.substr(e,2)==="//"?(a="//",e+=2):(a=null,f===0&&k('"//"'));if(a!==null){c=[],/^[^\n]/.test(b.charAt(e))?(d=b.charAt(e),e++):(d=null,f===0&&k("[^\\n]"));while(d!==null)c.push(d),/^[^\n]/.test(b.charAt(e))?(d=b.charAt(e),e++):(d=null,f===0&&k("[^\\n]"));c!==null?a=[a,c]:(a=null,e=h)}else a=null,e=h;if(a===null){h=e,b.substr(e,2)==="/*"?(a="/*",e+=2):(a=null,f===0&&k('"/*"'));if(a!==null){c=[],i=e,j=e,f++,b.substr(e,2)==="*/"?(d="*/",e+=2):(d=null,f===0&&k('"*/"')),f--,d===null?d="":(d=null,e=j),d!==null?(b.length>e?(g=b.charAt(e),e++):(g=null,f===0&&k("any character")),g!==null?d=[d,g]:(d=null,e=i)):(d=null,e=i);while(d!==null)c.push(d),i=e,j=e,f++,b.substr(e,2)==="*/"?(d="*/",e+=2):(d=null,f===0&&k('"*/"')),f--,d===null?d="":(d=null,e=j),d!==null?(b.length>e?(g=b.charAt(e),e++):(g=null,f===0&&k("any character")),g!==null?d=[d,g]:(d=null,e=i)):(d=null,e=i);c!==null?(b.substr(e,2)==="*/"?(d="*/",e+=2):(d=null,f===0&&k('"*/"')),d!==null?a=[a,c,d]:(a=null,e=h)):(a=null,e=h)}else a=null,e=h}return f--,f===0&&a===null&&k("comment"),a}function N(){var a;return a=L(),a===null&&(a=M()),a}function O(a){a.sort();var b=null,c=[];for(var d=0;d<a.length;d++)a[d]!==b&&(c.push(a[d]),b=a[d]);return c}function P(){var a=1,c=1,d=!1;for(var f=0;f<Math.max(e,g);f++){var h=b.charAt(f);h==="\n"?(d||a++,c=1,d=!1):h==="\r"||h==="\u2028"||h==="\u2029"?(a++,c=1,d=!0):(c++,d=!1)}return{line:a,column:c}}function R(a,b){var c={};for(var d in a)c[d]=a[d];for(var d in b)c[d]=b[d];return c}var d={start:l,graphStmt:m,stmtList:n,stmt:o,attrStmt:p,inlineAttrStmt:q,nodeStmt:r,edgeStmt:s,subgraphStmt:t,attrList:u,attrListBlock:v,aList:w,edgeRHS:x,idDef:y,nodeIdOrSubgraph:z,nodeId:A,port:B,compassPt:C,id:D,node:E,edge:F,graph:G,digraph:H,subgraph:I,strict:J,graphType:K,whitespace:L,comment:M,_:N};if(c!==undefined){if(d[c]===undefined)throw new Error("Invalid rule name: "+a(c)+".")}else c="start";var e=0,f=0,g=0,h=[],Q,S=d[c]();if(S===null||e!==b.length){var T=Math.max(e,g),U=T<b.length?b.charAt(T):null,V=P();throw new this.SyntaxError(O(h),U,T,V.line,V.column)}return S},toSource:function(){return this._source}};return b.SyntaxError=function(b,c,d,e,f){function g(b,c){var d,e;switch(b.length){case 0:d="end of input";break;case 1:d=b[0];break;default:d=b.slice(0,b.length-1).join(", ")+" or "+b[b.length-1]}return e=c?a(c):"end of input","Expected "+d+" but "+e+" found."}this.name="SyntaxError",this.expected=b,this.found=c,this.message=g(b,c),this.offset=d,this.line=e,this.column=f},b.SyntaxError.prototype=Error.prototype,b}()},{}],7:[function(a,b,c){function d(a){function b(){a.call(this),this.graph({})}return b.prototype=new a,b.prototype.constructor=b,b.prototype.graph=function(b){return arguments.length<1?a.prototype.graph.call(this):(this._checkValueType(b),a.prototype.graph.call(this,b))},b.prototype.node=function(b,c){return arguments.length<2?a.prototype.node.call(this,b):(this._checkValueType(c),a.prototype.node.call(this,b,c))},b.prototype.addNode=function(b,c){return arguments.length<2&&(c={}),this._checkValueType(c),a.prototype.addNode.call(this,b,c)},b.prototype.edge=function(b,c){return arguments.length<2?a.prototype.edge.call(this,b):(this._checkValueType(c),a.prototype.edge.call(this,b,c))},b.prototype.addEdge=function(b,c,d,e){return arguments.length<4&&(e={}),this._checkValueType(e),a.prototype.addEdge.call(this,b,c,d,e)},b.prototype._checkValueType=function(a){if(a===null||typeof a!="object")throw new Error("Value must be non-null and of type 'object'")},b}b.exports=d},{}],8:[function(a,b,c){function g(a){var b=f.parse(a,"graphStmt");return i(b)}function h(a){var b=f.parse(a);return b.map(function(a){return i(a)})}function i(a){function c(a,c,d){b.hasNode(a)||(b.addNode(a,h.get("node",{})),b.node(a).label===undefined&&(b.node(a).label=a),d!==null&&b.parent(a,d)),c&&j(c,b.node(a))}function f(a,c,d){var e={};j(h.get("edge",d),e);var f=d.id?d.id:null;b.addEdge(f,a,c,e)}function g(a){function e(a){c.push(a)}var b={},c=[],d;e(a);while(c.length!==0){d=c.pop();switch(d.type){case"node":b[d.id]=!0;break;case"edge":d.elems.forEach(e);break;case"subgraph":d.stmts.forEach(e)}}return Object.keys(b)}function i(a,d){var e=a.attrs;switch(a.type){case"node":c(a.id,e,d);break;case"edge":var k,l;a.elems.forEach(function(a){i(a,d);switch(a.type){case"node":l=[a.id];break;case"subgraph":l=g(a);break;default:throw new Error("Unsupported type incident on edge: "+a.type)}k&&k.forEach(function(a){l.forEach(function(b){f(a,b,e)})}),k=l});break;case"subgraph":h.enterSubDigraph(),a.id=b.addNode(a.id),d!==null&&b.parent(a.id,d),a.stmts&&a.stmts.forEach(function(b){i(b,a.id)}),b.children(a.id).length===0&&b.delNode(a.id),h.exitSubDigraph();break;case"attr":h.set(a.attrType,e);break;case"inlineAttr":a.attrs&&j(e,d===null?b.graph():b.node(d));break;default:throw new Error("Unsupported statement type: "+a.type)}}var b=a.type==="graph"?new e:new d,h={_default:{},get:function(b,c){if(typeof this._default[b]!="undefined"){var d={};return j(this._default[b],d),j(c,d),d}return c},set:function(b,c){this._default[b]=this.get(b,c)},enterSubDigraph:function(){function a(){}a.prototype=this._default;var b=new a;this._default=b},exitSubDigraph:function(){this._default=Object.getPrototypeOf(this._default)}};return a.stmts&&a.stmts.forEach(function(a){i(a,null)}),b}function j(a,b){Object.keys(a).forEach(function(c){b[c]=a[c]})}var d=a("./DotDigraph"),e=a("./DotGraph"),f=a("./dot-grammar");b.exports=g,b.exports.parseMany=h},{"./DotDigraph":3,"./DotGraph":4,"./dot-grammar":6}],9:[function(a,b,c){b.exports="0.4.10"},{}],10:[function(a,b,c){function f(a){var b=a.isDirected()?"->":"--",c=new d;c.writeLine((a.isDirected()?"digraph":"graph")+" {"),c.indent();var e=a.graph();return e&&Object.keys(e).map(function(a){c.writeLine(h(a)+"="+h(e[a])+";")}),g(a,null,c),a.edges().forEach(function(d){j(a,d,b,c)}),c.unindent(),c.writeLine("}"),c.toString()}function g(a,b,c){var d=a.children?a.children(b):b===null?a.nodes():[];d.forEach(function(b){if(!a.children||a.children(b).length===0)i(a,b,c);else{c.writeLine("subgraph "+h(b)+" {"),c.indent();var d=a.node(b);Object.keys(d).map(function(a){c.writeLine(h(a)+"="+h(d[a])+";")}),g(a,b,c),c.unindent(),c.writeLine("}")}})}function h(a){return typeof a=="number"||a.toString().match(e)?a:'"'+a.toString().replace(/"/g,'\\"')+'"'}function i(a,b,c){var d=a.node(b);c.write(h(b));if(d){var e=Object.keys(d).map(function(a){return h(a)+"="+h(d[a])});e.length&&c.write(" ["+e.join(",")+"]")}c.writeLine()}function j(a,b,c,d){var e=a.edge(b),f=a.incidentNodes(b),g=f[0],i=f[1];d.write(h(g)+" "+c+" "+h(i));if(e){var j=Object.keys(e).map(function(a){return h(a)+"="+h(e[a])});j.length&&d.write(" ["+j.join(",")+"]")}d.writeLine()}var d=a("./Writer");b.exports=f;var e=/^[a-zA-Z\200-\377_][a-zA-Z\200-\377_0-9]*$/},{"./Writer":5}],11:[function(a,b,c){c.Graph=a("./lib/Graph"),c.Digraph=a("./lib/Digraph"),c.CGraph=a("./lib/CGraph"),c.CDigraph=a("./lib/CDigraph"),a("./lib/graph-converters"),c.alg={isAcyclic:a("./lib/alg/isAcyclic"),components:a("./lib/alg/components"),dijkstra:a("./lib/alg/dijkstra"),dijkstraAll:a("./lib/alg/dijkstraAll"),findCycles:a("./lib/alg/findCycles"),floydWarshall:a("./lib/alg/floydWarshall"),postorder:a("./lib/alg/postorder"),preorder:a("./lib/alg/preorder"),prim:a("./lib/alg/prim"),tarjan:a("./lib/alg/tarjan"),topsort:a("./lib/alg/topsort")},c.converter={json:a("./lib/converter/json.js")};var d=a("./lib/filter");c.filter={all:d.all,nodesFromList:d.nodesFromList},c.version=a("./lib/version")},{"./lib/CDigraph":13,"./lib/CGraph":14,"./lib/Digraph":15,"./lib/Graph":16,"./lib/alg/components":17,"./lib/alg/dijkstra":18,"./lib/alg/dijkstraAll":19,"./lib/alg/findCycles":20,"./lib/alg/floydWarshall":21,"./lib/alg/isAcyclic":22,"./lib/alg/postorder":23,"./lib/alg/preorder":24,"./lib/alg/prim":25,"./lib/alg/tarjan":26,"./lib/alg/topsort":27,"./lib/converter/json.js":29,"./lib/filter":30,"./lib/graph-converters":31,"./lib/version":33}],12:[function(a,b,c){function e(){this._value=undefined,this._nodes={},this._edges={},this._nextId=0}function f(a,b,c){(a[b]||(a[b]=new d)).add(c)}function g(a,b,c){var d=a[b];d.remove(c),d.size()===0&&delete a[b]}var d=a("cp-data").Set;b.exports=e,e.prototype.order=function(){return Object.keys(this._nodes).length},e.prototype.size=function(){return Object.keys(this._edges).length},e.prototype.graph=function(a){if(arguments.length===0)return this._value;this._value=a},e.prototype.hasNode=function(a){return a in this._nodes},e.prototype.node=function(a,b){var c=this._strictGetNode(a);if(arguments.length===1)return c.value;c.value=b},e.prototype.nodes=function(){var a=[];return this.eachNode(function(b){a.push(b)}),a},e.prototype.eachNode=function(a){for(var b in this._nodes){var c=this._nodes[b];a(c.id,c.value)}},e.prototype.hasEdge=function(a){return a in this._edges},e.prototype.edge=function(a,b){var c=this._strictGetEdge(a);if(arguments.length===1)return c.value;c.value=b},e.prototype.edges=function(){var a=[];return this.eachEdge(function(b){a.push(b)}),a},e.prototype.eachEdge=function(a){for(var b in this._edges){var c=this._edges[b];a(c.id,c.u,c.v,c.value)}},e.prototype.incidentNodes=function(a){var b=this._strictGetEdge(a);return[b.u,b.v]},e.prototype.addNode=function(a,b){if(a===undefined||a===null){do a="_"+ ++this._nextId;while(this.hasNode(a))}else if(this.hasNode(a))throw new Error("Graph already has node '"+a+"'");return this._nodes[a]={id:a,value:b},a},e.prototype.delNode=function(a){this._strictGetNode(a),this.incidentEdges(a).forEach(function(a){this.delEdge(a)},this),delete this._nodes[a]},e.prototype._addEdge=function(a,b,c,d,e,g){this._strictGetNode(b),this._strictGetNode(c);if(a===undefined||a===null){do a="_"+ ++this._nextId;while(this.hasEdge(a))}else if(this.hasEdge(a))throw new Error("Graph already has edge '"+a+"'");return this._edges[a]={id:a,u:b,v:c,value:d},f(e[c],b,a),f(g[b],c,a),a},e.prototype._delEdge=function(a,b,c){var d=this._strictGetEdge(a);g(b[d.v],d.u,a),g(c[d.u],d.v,a),delete this._edges[a]},e.prototype.copy=function(){var a=new this.constructor;return a.graph(this.graph()),this.eachNode(function(b,c){a.addNode(b,c)}),this.eachEdge(function(b,c,d,e){a.addEdge(b,c,d,e)}),a._nextId=this._nextId,a},e.prototype.filterNodes=function(a){var b=new this.constructor;return b.graph(this.graph()),this.eachNode(function(c,d){a(c)&&b.addNode(c,d)}),this.eachEdge(function(a,c,d,e){b.hasNode(c)&&b.hasNode(d)&&b.addEdge(a,c,d,e)}),b},e.prototype._strictGetNode=function(a){var b=this._nodes[a];if(b===undefined)throw new Error("Node '"+a+"' is not in graph");return b},e.prototype._strictGetEdge=function(a){var b=this._edges[a];if(b===undefined)throw new Error("Edge '"+a+"' is not in graph");return b}},{"cp-data":34}],13:[function(a,b,c){var d=a("./Digraph"),e=a("./compoundify"),f=e(d);b.exports=f,f.fromDigraph=function(a){var b=new f,c=a.graph();return c!==undefined&&b.graph(c),a.eachNode(function(a,c){c===undefined?b.addNode(a):b.addNode(a,c)}),a.eachEdge(function(a,c,d,e){e===undefined?b.addEdge(null,c,d):b.addEdge(null,c,d,e)}),b},f.prototype.toString=function(){return"CDigraph "+JSON.stringify(this,null,2)}},{"./Digraph":15,"./compoundify":28}],14:[function(a,b,c){var d=a("./Graph"),e=a("./compoundify"),f=e(d);b.exports=f,f.fromGraph=function(a){var b=new f,c=a.graph();return c!==undefined&&b.graph(c),a.eachNode(function(a,c){c===undefined?b.addNode(a):b.addNode(a,c)}),a.eachEdge(function(a,c,d,e){e===undefined?b.addEdge(null,c,d):b.addEdge(null,c,d,e)}),b},f.prototype.toString=function(){return"CGraph "+JSON.stringify(this,null,2)}},{"./Graph":16,"./compoundify":28}],15:[function(a,b,c){function g(){e.call(this),this._inEdges={},this._outEdges={}}var d=a("./util"),e=a("./BaseGraph"),f=a("cp-data").Set;b.exports=g,g.prototype=new e,g.prototype.constructor=g,g.prototype.isDirected=function(){return!0},g.prototype.successors=function(a){return this._strictGetNode(a),Object.keys(this._outEdges[a]).map(function(a){return this._nodes[a].id},this)},g.prototype.predecessors=function(a){return this._strictGetNode(a),Object.keys(this._inEdges[a]).map(function(a){return this._nodes[a].id},this)},g.prototype.neighbors=function(a){return f.union([this.successors(a),this.predecessors(a)]).keys()},g.prototype.sources=function(){var a=this;return this._filterNodes(function(b){return a.inEdges(b).length===0})},g.prototype.sinks=function(){var a=this;return this._filterNodes(function(b){return a.outEdges(b).length===0})},g.prototype.source=function(a){return this._strictGetEdge(a).u},g.prototype.target=function(a){return this._strictGetEdge(a).v},g.prototype.inEdges=function(a,b){this._strictGetNode(a);var c=f.union(d.values(this._inEdges[a])).keys();return arguments.length>1&&(this._strictGetNode(b),c=c.filter(function(a){return this.source(a)===b},this)),c},g.prototype.outEdges=function(a,b){this._strictGetNode(a);var c=f.union(d.values(this._outEdges[a])).keys();return arguments.length>1&&(this._strictGetNode(b),c=c.filter(function(a){return this.target(a)===b},this)),c},g.prototype.incidentEdges=function(a,b){return arguments.length>1?f.union([this.outEdges(a,b),this.outEdges(b,a)]).keys():f.union([this.inEdges(a),this.outEdges(a)]).keys()},g.prototype.toString=function(){return"Digraph "+JSON.stringify(this,null,2)},g.prototype.addNode=function(a,b){return a=e.prototype.addNode.call(this,a,b),this._inEdges[a]={},this._outEdges[a]={},a},g.prototype.delNode=function(a){e.prototype.delNode.call(this,a),delete this._inEdges[a],delete this._outEdges[a]},g.prototype.addEdge=function(a,b,c,d){return e.prototype._addEdge.call(this,a,b,c,d,this._inEdges,this._outEdges)},g.prototype.delEdge=function(a){e.prototype._delEdge.call(this,a,this._inEdges,this._outEdges)},g.prototype._filterNodes=function(a){var b=[];return this.eachNode(function(c){a(c)&&b.push(c)}),b}},{"./BaseGraph":12,"./util":32,"cp-data":34}],16:[function(a,b,c){function g(){e.call(this),this._incidentEdges={}}var d=a("./util"),e=a("./BaseGraph"),f=a("cp-data").Set;b.exports=g,g.prototype=new e,g.prototype.constructor=g,g.prototype.isDirected=function(){return!1},g.prototype.neighbors=function(a){return this._strictGetNode(a),Object.keys(this._incidentEdges[a]).map(function(a){return this._nodes[a].id},this)},g.prototype.incidentEdges=function(a,b){return this._strictGetNode(a),arguments.length>1?(this._strictGetNode(b),b in this._incidentEdges[a]?this._incidentEdges[a][b].keys():[]):f.union(d.values(this._incidentEdges[a])).keys()},g.prototype.toString=function(){return"Graph "+JSON.stringify(this,null,2)},g.prototype.addNode=function(a,b){return a=e.prototype.addNode.call(this,a,b),this._incidentEdges[a]={},a},g.prototype.delNode=function(a){e.prototype.delNode.call(this,a),delete this._incidentEdges[a]},g.prototype.addEdge=function(a,b,c,d){return e.prototype._addEdge.call(this,a,b,c,d,this._incidentEdges,this._incidentEdges)},g.prototype.delEdge=function(a){e.prototype._delEdge.call(this,a,this._incidentEdges,this._incidentEdges)}},{"./BaseGraph":12,"./util":32,"cp-data":34}],17:[function(a,b,c){function e(a){function e(b,d){c.has(b)||(c.add(b),d.push(b),a.neighbors(b).forEach(function(a){e(a,d)}))}var b=[],c=new d;return a.nodes().forEach(function(a){var c=[];e(a,c),c.length>0&&b.push(c)}),b}var d=a("cp-data").Set;b.exports=e},{"cp-data":34}],18:[function(a,b,c){function e(a,b,c,e){function h(b){var d=a.incidentNodes(b),e=d[0]!==i?d[0]:d[1],h=f[e],k=c(b),l=j.distance+k;if(k<0)throw new Error("dijkstra does not allow negative edge weights. Bad edge: "+b+" Weight: "+k);l<h.distance&&(h.distance=l,h.predecessor=i,g.decrease(e,l))}var f={},g=new d;c=c||function(){return 1},e=e||(a.isDirected()?function(b){return a.outEdges(b)}:function(b){return a.incidentEdges(b)}),a.eachNode(function(a){var c=a===b?0:Number.POSITIVE_INFINITY;f[a]={distance:c},g.add(a,c)});var i,j;while(g.size +()>0){i=g.removeMin(),j=f[i];if(j.distance===Number.POSITIVE_INFINITY)break;e(i).forEach(h)}return f}var d=a("cp-data").PriorityQueue;b.exports=e},{"cp-data":34}],19:[function(a,b,c){function e(a,b,c){var e={};return a.eachNode(function(f){e[f]=d(a,f,b,c)}),e}var d=a("./dijkstra");b.exports=e},{"./dijkstra":18}],20:[function(a,b,c){function e(a){return d(a).filter(function(a){return a.length>1})}var d=a("./tarjan");b.exports=e},{"./tarjan":26}],21:[function(a,b,c){function d(a,b,c){var d={},e=a.nodes();return b=b||function(){return 1},c=c||(a.isDirected()?function(b){return a.outEdges(b)}:function(b){return a.incidentEdges(b)}),e.forEach(function(f){d[f]={},d[f][f]={distance:0},e.forEach(function(a){f!==a&&(d[f][a]={distance:Number.POSITIVE_INFINITY})}),c(f).forEach(function(c){var e=a.incidentNodes(c),h=e[0]!==f?e[0]:e[1],i=b(c);i<d[f][h].distance&&(d[f][h]={distance:i,predecessor:f})})}),e.forEach(function(a){var b=d[a];e.forEach(function(c){var f=d[c];e.forEach(function(c){var d=f[a],e=b[c],g=f[c],h=d.distance+e.distance;h<g.distance&&(g.distance=h,g.predecessor=e.predecessor)})})}),d}b.exports=d},{}],22:[function(a,b,c){function e(a){try{d(a)}catch(b){if(b instanceof d.CycleException)return!1;throw b}return!0}var d=a("./topsort");b.exports=e},{"./topsort":27}],23:[function(a,b,c){function e(a,b,c){function f(b,d){if(e.has(b))throw new Error("The input graph is not a tree: "+a);e.add(b),a.neighbors(b).forEach(function(a){a!==d&&f(a,b)}),c(b)}var e=new d;if(a.isDirected())throw new Error("This function only works for undirected graphs");f(b)}var d=a("cp-data").Set;b.exports=e},{"cp-data":34}],24:[function(a,b,c){function e(a,b,c){function f(b,d){if(e.has(b))throw new Error("The input graph is not a tree: "+a);e.add(b),c(b),a.neighbors(b).forEach(function(a){a!==d&&f(a,b)})}var e=new d;if(a.isDirected())throw new Error("This function only works for undirected graphs");f(b)}var d=a("cp-data").Set;b.exports=e},{"cp-data":34}],25:[function(a,b,c){function f(a,b){function i(c){var d=a.incidentNodes(c),e=d[0]!==h?d[0]:d[1],i=g.priority(e);if(i!==undefined){var j=b(c);j<i&&(f[e]=h,g.decrease(e,j))}}var c=new d,f={},g=new e,h;if(a.order()===0)return c;a.eachNode(function(a){g.add(a,Number.POSITIVE_INFINITY),c.addNode(a)}),g.decrease(a.nodes()[0],0);var j=!1;while(g.size()>0){h=g.removeMin();if(h in f)c.addEdge(null,h,f[h]);else{if(j)throw new Error("Input graph is not connected: "+a);j=!0}a.incidentEdges(h).forEach(i)}return c}var d=a("../Graph"),e=a("cp-data").PriorityQueue;b.exports=f},{"../Graph":16,"cp-data":34}],26:[function(a,b,c){function d(a){function f(h){var i=d[h]={onStack:!0,lowlink:b,index:b++};c.push(h),a.successors(h).forEach(function(a){a in d?d[a].onStack&&(i.lowlink=Math.min(i.lowlink,d[a].index)):(f(a),i.lowlink=Math.min(i.lowlink,d[a].lowlink))});if(i.lowlink===i.index){var j=[],k;do k=c.pop(),d[k].onStack=!1,j.push(k);while(h!==k);e.push(j)}}if(!a.isDirected())throw new Error("tarjan can only be applied to a directed graph. Bad input: "+a);var b=0,c=[],d={},e=[];return a.nodes().forEach(function(a){a in d||f(a)}),e}b.exports=d},{}],27:[function(a,b,c){function d(a){function f(g){if(g in c)throw new e;g in b||(c[g]=!0,b[g]=!0,a.predecessors(g).forEach(function(a){f(a)}),delete c[g],d.push(g))}if(!a.isDirected())throw new Error("topsort can only be applied to a directed graph. Bad input: "+a);var b={},c={},d=[],g=a.sinks();if(a.order()!==0&&g.length===0)throw new e;return a.sinks().forEach(function(a){f(a)}),d}function e(){}b.exports=d,d.CycleException=e,e.prototype.toString=function(){return"Graph has at least one cycle"}},{}],28:[function(a,b,c){function e(a){function b(){a.call(this),this._parents={},this._children={},this._children[null]=new d}return b.prototype=new a,b.prototype.constructor=b,b.prototype.parent=function(a,b){this._strictGetNode(a);if(arguments.length<2)return this._parents[a];if(a===b)throw new Error("Cannot make "+a+" a parent of itself");b!==null&&this._strictGetNode(b),this._children[this._parents[a]].remove(a),this._parents[a]=b,this._children[b].add(a)},b.prototype.children=function(a){return a!==null&&this._strictGetNode(a),this._children[a].keys()},b.prototype.addNode=function(b,c){return b=a.prototype.addNode.call(this,b,c),this._parents[b]=null,this._children[b]=new d,this._children[null].add(b),b},b.prototype.delNode=function(b){var c=this.parent(b);return this._children[b].keys().forEach(function(a){this.parent(a,c)},this),this._children[c].remove(b),delete this._parents[b],delete this._children[b],a.prototype.delNode.call(this,b)},b.prototype.copy=function(){var b=a.prototype.copy.call(this);return this.nodes().forEach(function(a){b.parent(a,this.parent(a))},this),b},b.prototype.filterNodes=function(b){function f(a){var b=c.parent(a);return b===null||d.hasNode(b)?(e[a]=b,b):b in e?e[b]:f(b)}var c=this,d=a.prototype.filterNodes.call(this,b),e={};return d.eachNode(function(a){d.parent(a,f(a))}),d},b}var d=a("cp-data").Set;b.exports=e},{"cp-data":34}],29:[function(a,b,c){function h(a){return Object.prototype.toString.call(a).slice(8,-1)}var d=a("../Graph"),e=a("../Digraph"),f=a("../CGraph"),g=a("../CDigraph");c.decode=function(a,b,c){c=c||e;if(h(a)!=="Array")throw new Error("nodes is not an Array");if(h(b)!=="Array")throw new Error("edges is not an Array");if(typeof c=="string")switch(c){case"graph":c=d;break;case"digraph":c=e;break;case"cgraph":c=f;break;case"cdigraph":c=g;break;default:throw new Error("Unrecognized graph type: "+c)}var i=new c;return a.forEach(function(a){i.addNode(a.id,a.value)}),i.parent&&a.forEach(function(a){a.children&&a.children.forEach(function(b){i.parent(b,a.id)})}),b.forEach(function(a){i.addEdge(a.id,a.u,a.v,a.value)}),i},c.encode=function(a){var b=[],c=[];a.eachNode(function(c,d){var e={id:c,value:d};if(a.children){var f=a.children(c);f.length&&(e.children=f)}b.push(e)}),a.eachEdge(function(a,b,d,e){c.push({id:a,u:b,v:d,value:e})});var h;if(a instanceof g)h="cdigraph";else if(a instanceof f)h="cgraph";else if(a instanceof e)h="digraph";else if(a instanceof d)h="graph";else throw new Error("Couldn't determine type of graph: "+a);return{nodes:b,edges:c,type:h}}},{"../CDigraph":13,"../CGraph":14,"../Digraph":15,"../Graph":16}],30:[function(a,b,c){var d=a("cp-data").Set;c.all=function(){return function(){return!0}},c.nodesFromList=function(a){var b=new d(a);return function(a){return b.has(a)}}},{"cp-data":34}],31:[function(a,b,c){var d=a("./Graph"),e=a("./Digraph");d.prototype.toDigraph=d.prototype.asDirected=function(){var a=new e;return this.eachNode(function(b,c){a.addNode(b,c)}),this.eachEdge(function(b,c,d,e){a.addEdge(null,c,d,e),a.addEdge(null,d,c,e)}),a},e.prototype.toGraph=e.prototype.asUndirected=function(){var a=new d;return this.eachNode(function(b,c){a.addNode(b,c)}),this.eachEdge(function(b,c,d,e){a.addEdge(b,c,d,e)}),a}},{"./Digraph":15,"./Graph":16}],32:[function(a,b,c){c.values=function(a){var b=Object.keys(a),c=b.length,d=new Array(c),e;for(e=0;e<c;++e)d[e]=a[b[e]];return d}},{}],33:[function(a,b,c){b.exports="0.7.4"},{}],34:[function(a,b,c){c.Set=a("./lib/Set"),c.PriorityQueue=a("./lib/PriorityQueue"),c.version=a("./lib/version")},{"./lib/PriorityQueue":35,"./lib/Set":36,"./lib/version":38}],35:[function(a,b,c){function d(){this._arr=[],this._keyIndices={}}b.exports=d,d.prototype.size=function(){return this._arr.length},d.prototype.keys=function(){return this._arr.map(function(a){return a.key})},d.prototype.has=function(a){return a in this._keyIndices},d.prototype.priority=function(a){var b=this._keyIndices[a];if(b!==undefined)return this._arr[b].priority},d.prototype.min=function(){if(this.size()===0)throw new Error("Queue underflow");return this._arr[0].key},d.prototype.add=function(a,b){var c=this._keyIndices;if(a in c)return!1;var d=this._arr,e=d.length;return c[a]=e,d.push({key:a,priority:b}),this._decrease(e),!0},d.prototype.removeMin=function(){this._swap(0,this._arr.length-1);var a=this._arr.pop();return delete this._keyIndices[a.key],this._heapify(0),a.key},d.prototype.decrease=function(a,b){var c=this._keyIndices[a];if(b>this._arr[c].priority)throw new Error("New priority is greater than current priority. Key: "+a+" Old: "+this._arr[c].priority+" New: "+b);this._arr[c].priority=b,this._decrease(c)},d.prototype._heapify=function(a){var b=this._arr,c=2*a,d=c+1,e=a;c<b.length&&(e=b[c].priority<b[e].priority?c:e,d<b.length&&(e=b[d].priority<b[e].priority?d:e),e!==a&&(this._swap(a,e),this._heapify(e)))},d.prototype._decrease=function(a){var b=this._arr,c=b[a].priority,d;while(a!==0){d=a>>1;if(b[d].priority<c)break;this._swap(a,d),a=d}},d.prototype._swap=function(a,b){var c=this._arr,d=this._keyIndices,e=c[a],f=c[b];c[a]=f,c[b]=e,d[f.key]=a,d[e.key]=b}},{}],36:[function(a,b,c){function e(a){this._size=0,this._keys={};if(a)for(var b=0,c=a.length;b<c;++b)this.add(a[b])}function f(a){var b=Object.keys(a),c=b.length,d=new Array(c),e;for(e=0;e<c;++e)d[e]=a[b[e]];return d}var d=a("./util");b.exports=e,e.intersect=function(a){if(a.length===0)return new e;var b=new e(d.isArray(a[0])?a[0]:a[0].keys());for(var c=1,f=a.length;c<f;++c){var g=b.keys(),h=d.isArray(a[c])?new e(a[c]):a[c];for(var i=0,j=g.length;i<j;++i){var k=g[i];h.has(k)||b.remove(k)}}return b},e.union=function(a){var b=d.reduce(a,function(a,b){return a+(b.size?b.size():b.length)},0),c=new Array(b),f=0;for(var g=0,h=a.length;g<h;++g){var i=a[g],j=d.isArray(i)?i:i.keys();for(var k=0,l=j.length;k<l;++k)c[f++]=j[k]}return new e(c)},e.prototype.size=function(){return this._size},e.prototype.keys=function(){return f(this._keys)},e.prototype.has=function(a){return a in this._keys},e.prototype.add=function(a){return a in this._keys?!1:(this._keys[a]=a,++this._size,!0)},e.prototype.remove=function(a){return a in this._keys?(delete this._keys[a],--this._size,!0):!1}},{"./util":37}],37:[function(a,b,c){Array.isArray?c.isArray=Array.isArray:c.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"},"function"!=typeof Array.prototype.reduce?c.reduce=function(a,b,c){"use strict";if(null===a||"undefined"==typeof a)throw new TypeError("Array.prototype.reduce called on null or undefined");if("function"!=typeof b)throw new TypeError(b+" is not a function");var d,e,f=a.length>>>0,g=!1;1<arguments.length&&(e=c,g=!0);for(d=0;f>d;++d)a.hasOwnProperty(d)&&(g?e=b(e,a[d],d,a):(e=a[d],g=!0));if(!g)throw new TypeError("Reduce of empty array with no initial value");return e}:c.reduce=function(a,b,c){return a.reduce(b,c)}},{}],38:[function(a,b,c){b.exports="1.1.3"},{}]},{},[1]); \ No newline at end of file diff --git a/src/static/galleria/LICENSE b/src/static/galleria/LICENSE new file mode 100644 index 0000000..4531e29 --- /dev/null +++ b/src/static/galleria/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2013 Aino http://aino.se + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/static/galleria/galleria-1.4.2.js b/src/static/galleria/galleria-1.4.2.js new file mode 100644 index 0000000..a29a51c --- /dev/null +++ b/src/static/galleria/galleria-1.4.2.js @@ -0,0 +1,6919 @@ +/** + * Galleria v 1.4.2 2014-08-07 + * http://galleria.io + * + * Licensed under the MIT license + * https://raw.github.com/aino/galleria/master/LICENSE + * + */ + +(function( $, window, Galleria, undef ) { + +/*global jQuery, navigator, Image, module, define */ + +// some references +var doc = window.document, + $doc = $( doc ), + $win = $( window ), + +// native prototypes + protoArray = Array.prototype, + +// internal constants + VERSION = 1.41, + DEBUG = true, + TIMEOUT = 30000, + DUMMY = false, + NAV = navigator.userAgent.toLowerCase(), + HASH = window.location.hash.replace(/#\//, ''), + PROT = window.location.protocol, + M = Math, + F = function(){}, + FALSE = function() { return false; }, + IE = (function() { + + var v = 3, + div = doc.createElement( 'div' ), + all = div.getElementsByTagName( 'i' ); + + do { + div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->'; + } while ( all[0] ); + + return v > 4 ? v : doc.documentMode || undef; + + }() ), + DOM = function() { + return { + html: doc.documentElement, + body: doc.body, + head: doc.getElementsByTagName('head')[0], + title: doc.title + }; + }, + IFRAME = window.parent !== window.self, + + // list of Galleria events + _eventlist = 'data ready thumbnail loadstart loadfinish image play pause progress ' + + 'fullscreen_enter fullscreen_exit idle_enter idle_exit rescale ' + + 'lightbox_open lightbox_close lightbox_image', + + _events = (function() { + + var evs = []; + + $.each( _eventlist.split(' '), function( i, ev ) { + evs.push( ev ); + + // legacy events + if ( /_/.test( ev ) ) { + evs.push( ev.replace( /_/g, '' ) ); + } + }); + + return evs; + + }()), + + // legacy options + // allows the old my_setting syntax and converts it to camel case + + _legacyOptions = function( options ) { + + var n; + + if ( typeof options !== 'object' ) { + + // return whatever it was... + return options; + } + + $.each( options, function( key, value ) { + if ( /^[a-z]+_/.test( key ) ) { + n = ''; + $.each( key.split('_'), function( i, k ) { + n += i > 0 ? k.substr( 0, 1 ).toUpperCase() + k.substr( 1 ) : k; + }); + options[ n ] = value; + delete options[ key ]; + } + }); + + return options; + }, + + _patchEvent = function( type ) { + + // allow 'image' instead of Galleria.IMAGE + if ( $.inArray( type, _events ) > -1 ) { + return Galleria[ type.toUpperCase() ]; + } + + return type; + }, + + // video providers + _video = { + youtube: { + reg: /https?:\/\/(?:[a-zA_Z]{2,3}.)?(?:youtube\.com\/watch\?)((?:[\w\d\-\_\=]+&amp;(?:amp;)?)*v(?:&lt;[A-Z]+&gt;)?=([0-9a-zA-Z\-\_]+))/i, + embed: function() { + return 'http://www.youtube.com/embed/' + this.id; + }, + getUrl: function() { + return PROT + '//gdata.youtube.com/feeds/api/videos/' + this.id + '?v=2&alt=json-in-script&callback=?'; + }, + get_thumb: function(data) { + return data.entry.media$group.media$thumbnail[2].url; + }, + get_image: function(data) { + if ( data.entry.yt$hd ) { + return PROT + '//img.youtube.com/vi/'+this.id+'/maxresdefault.jpg'; + } + return data.entry.media$group.media$thumbnail[3].url; + } + }, + vimeo: { + reg: /https?:\/\/(?:www\.)?(vimeo\.com)\/(?:hd#)?([0-9]+)/i, + embed: function() { + return 'http://player.vimeo.com/video/' + this.id; + }, + getUrl: function() { + return PROT + '//vimeo.com/api/v2/video/' + this.id + '.json?callback=?'; + }, + get_thumb: function( data ) { + return data[0].thumbnail_medium; + }, + get_image: function( data ) { + return data[0].thumbnail_large; + } + }, + dailymotion: { + reg: /https?:\/\/(?:www\.)?(dailymotion\.com)\/video\/([^_]+)/, + embed: function() { + return PROT + '//www.dailymotion.com/embed/video/' + this.id; + }, + getUrl: function() { + return 'https://api.dailymotion.com/video/' + this.id + '?fields=thumbnail_240_url,thumbnail_720_url&callback=?'; + }, + get_thumb: function( data ) { + return data.thumbnail_240_url; + }, + get_image: function( data ) { + return data.thumbnail_720_url; + } + }, + _inst: [] + }, + Video = function( type, id ) { + + for( var i=0; i<_video._inst.length; i++ ) { + if ( _video._inst[i].id === id && _video._inst[i].type == type ) { + return _video._inst[i]; + } + } + + this.type = type; + this.id = id; + this.readys = []; + + _video._inst.push(this); + + var self = this; + + $.extend( this, _video[type] ); + + $.getJSON( this.getUrl(), function(data) { + self.data = data; + $.each( self.readys, function( i, fn ) { + fn( self.data ); + }); + self.readys = []; + }); + + this.getMedia = function( type, callback, fail ) { + fail = fail || F; + var self = this; + var success = function( data ) { + callback( self['get_'+type]( data ) ); + }; + try { + if ( self.data ) { + success( self.data ); + } else { + self.readys.push( success ); + } + } catch(e) { + fail(); + } + }; + }, + + // utility for testing the video URL and getting the video ID + _videoTest = function( url ) { + var match; + for ( var v in _video ) { + match = url && _video[v].reg && url.match( _video[v].reg ); + if( match && match.length ) { + return { + id: match[2], + provider: v + }; + } + } + return false; + }, + + // native fullscreen handler + _nativeFullscreen = { + + support: (function() { + var html = DOM().html; + return !IFRAME && ( html.requestFullscreen || html.msRequestFullscreen || html.mozRequestFullScreen || html.webkitRequestFullScreen ); + }()), + + callback: F, + + enter: function( instance, callback, elem ) { + + this.instance = instance; + + this.callback = callback || F; + + elem = elem || DOM().html; + if ( elem.requestFullscreen ) { + elem.requestFullscreen(); + } + else if ( elem.msRequestFullscreen ) { + elem.msRequestFullscreen(); + } + else if ( elem.mozRequestFullScreen ) { + elem.mozRequestFullScreen(); + } + else if ( elem.webkitRequestFullScreen ) { + elem.webkitRequestFullScreen(); + } + }, + + exit: function( callback ) { + + this.callback = callback || F; + + if ( doc.exitFullscreen ) { + doc.exitFullscreen(); + } + else if ( doc.msExitFullscreen ) { + doc.msExitFullscreen(); + } + else if ( doc.mozCancelFullScreen ) { + doc.mozCancelFullScreen(); + } + else if ( doc.webkitCancelFullScreen ) { + doc.webkitCancelFullScreen(); + } + }, + + instance: null, + + listen: function() { + + if ( !this.support ) { + return; + } + + var handler = function() { + + if ( !_nativeFullscreen.instance ) { + return; + } + var fs = _nativeFullscreen.instance._fullscreen; + + if ( doc.fullscreen || doc.mozFullScreen || doc.webkitIsFullScreen || ( doc.msFullscreenElement && doc.msFullscreenElement !== null ) ) { + fs._enter( _nativeFullscreen.callback ); + } else { + fs._exit( _nativeFullscreen.callback ); + } + }; + doc.addEventListener( 'fullscreenchange', handler, false ); + doc.addEventListener( 'MSFullscreenChange', handler, false ); + doc.addEventListener( 'mozfullscreenchange', handler, false ); + doc.addEventListener( 'webkitfullscreenchange', handler, false ); + } + }, + + // the internal gallery holder + _galleries = [], + + // the internal instance holder + _instances = [], + + // flag for errors + _hasError = false, + + // canvas holder + _canvas = false, + + // instance pool, holds the galleries until themeLoad is triggered + _pool = [], + + // Run galleries from theme trigger + _loadedThemes = [], + _themeLoad = function( theme ) { + + _loadedThemes.push(theme); + + // run the instances we have in the pool + // and apply the last theme if not specified + $.each( _pool, function( i, instance ) { + if ( instance._options.theme == theme.name || (!instance._initialized && !instance._options.theme) ) { + instance.theme = theme; + instance._init.call( instance ); + } + }); + }, + + // the Utils singleton + Utils = (function() { + + return { + + // legacy support for clearTimer + clearTimer: function( id ) { + $.each( Galleria.get(), function() { + this.clearTimer( id ); + }); + }, + + // legacy support for addTimer + addTimer: function( id ) { + $.each( Galleria.get(), function() { + this.addTimer( id ); + }); + }, + + array : function( obj ) { + return protoArray.slice.call(obj, 0); + }, + + create : function( className, nodeName ) { + nodeName = nodeName || 'div'; + var elem = doc.createElement( nodeName ); + elem.className = className; + return elem; + }, + + removeFromArray : function( arr, elem ) { + $.each(arr, function(i, el) { + if ( el == elem ) { + arr.splice(i, 1); + return false; + } + }); + return arr; + }, + + getScriptPath : function( src ) { + + // the currently executing script is always the last + src = src || $('script:last').attr('src'); + var slices = src.split('/'); + + if (slices.length == 1) { + return ''; + } + + slices.pop(); + + return slices.join('/') + '/'; + }, + + // CSS3 transitions, added in 1.2.4 + animate : (function() { + + // detect transition + var transition = (function( style ) { + var props = 'transition WebkitTransition MozTransition OTransition'.split(' '), + i; + + // disable css3 animations in opera until stable + if ( window.opera ) { + return false; + } + + for ( i = 0; props[i]; i++ ) { + if ( typeof style[ props[ i ] ] !== 'undefined' ) { + return props[ i ]; + } + } + return false; + }(( doc.body || doc.documentElement).style )); + + // map transitionend event + var endEvent = { + MozTransition: 'transitionend', + OTransition: 'oTransitionEnd', + WebkitTransition: 'webkitTransitionEnd', + transition: 'transitionend' + }[ transition ]; + + // map bezier easing conversions + var easings = { + _default: [0.25, 0.1, 0.25, 1], + galleria: [0.645, 0.045, 0.355, 1], + galleriaIn: [0.55, 0.085, 0.68, 0.53], + galleriaOut: [0.25, 0.46, 0.45, 0.94], + ease: [0.25, 0, 0.25, 1], + linear: [0.25, 0.25, 0.75, 0.75], + 'ease-in': [0.42, 0, 1, 1], + 'ease-out': [0, 0, 0.58, 1], + 'ease-in-out': [0.42, 0, 0.58, 1] + }; + + // function for setting transition css for all browsers + var setStyle = function( elem, value, suffix ) { + var css = {}; + suffix = suffix || 'transition'; + $.each( 'webkit moz ms o'.split(' '), function() { + css[ '-' + this + '-' + suffix ] = value; + }); + elem.css( css ); + }; + + // clear styles + var clearStyle = function( elem ) { + setStyle( elem, 'none', 'transition' ); + if ( Galleria.WEBKIT && Galleria.TOUCH ) { + setStyle( elem, 'translate3d(0,0,0)', 'transform' ); + if ( elem.data('revert') ) { + elem.css( elem.data('revert') ); + elem.data('revert', null); + } + } + }; + + // various variables + var change, strings, easing, syntax, revert, form, css; + + // the actual animation method + return function( elem, to, options ) { + + // extend defaults + options = $.extend({ + duration: 400, + complete: F, + stop: false + }, options); + + // cache jQuery instance + elem = $( elem ); + + if ( !options.duration ) { + elem.css( to ); + options.complete.call( elem[0] ); + return; + } + + // fallback to jQuery's animate if transition is not supported + if ( !transition ) { + elem.animate(to, options); + return; + } + + // stop + if ( options.stop ) { + // clear the animation + elem.off( endEvent ); + clearStyle( elem ); + } + + // see if there is a change + change = false; + $.each( to, function( key, val ) { + css = elem.css( key ); + if ( Utils.parseValue( css ) != Utils.parseValue( val ) ) { + change = true; + } + // also add computed styles for FF + elem.css( key, css ); + }); + if ( !change ) { + window.setTimeout( function() { + options.complete.call( elem[0] ); + }, options.duration ); + return; + } + + // the css strings to be applied + strings = []; + + // the easing bezier + easing = options.easing in easings ? easings[ options.easing ] : easings._default; + + // the syntax + syntax = ' ' + options.duration + 'ms' + ' cubic-bezier(' + easing.join(',') + ')'; + + // add a tiny timeout so that the browsers catches any css changes before animating + window.setTimeout( (function(elem, endEvent, to, syntax) { + return function() { + + // attach the end event + elem.one(endEvent, (function( elem ) { + return function() { + + // clear the animation + clearStyle(elem); + + // run the complete method + options.complete.call(elem[0]); + }; + }( elem ))); + + // do the webkit translate3d for better performance on iOS + if( Galleria.WEBKIT && Galleria.TOUCH ) { + + revert = {}; + form = [0,0,0]; + + $.each( ['left', 'top'], function(i, m) { + if ( m in to ) { + form[ i ] = ( Utils.parseValue( to[ m ] ) - Utils.parseValue(elem.css( m )) ) + 'px'; + revert[ m ] = to[ m ]; + delete to[ m ]; + } + }); + + if ( form[0] || form[1]) { + + elem.data('revert', revert); + + strings.push('-webkit-transform' + syntax); + + // 3d animate + setStyle( elem, 'translate3d(' + form.join(',') + ')', 'transform'); + } + } + + // push the animation props + $.each(to, function( p, val ) { + strings.push(p + syntax); + }); + + // set the animation styles + setStyle( elem, strings.join(',') ); + + // animate + elem.css( to ); + + }; + }(elem, endEvent, to, syntax)), 2); + }; + }()), + + removeAlpha : function( elem ) { + if ( elem instanceof jQuery ) { + elem = elem[0]; + } + if ( IE < 9 && elem ) { + + var style = elem.style, + currentStyle = elem.currentStyle, + filter = currentStyle && currentStyle.filter || style.filter || ""; + + if ( /alpha/.test( filter ) ) { + style.filter = filter.replace( /alpha\([^)]*\)/i, '' ); + } + } + }, + + forceStyles : function( elem, styles ) { + elem = $(elem); + if ( elem.attr( 'style' ) ) { + elem.data( 'styles', elem.attr( 'style' ) ).removeAttr( 'style' ); + } + elem.css( styles ); + }, + + revertStyles : function() { + $.each( Utils.array( arguments ), function( i, elem ) { + + elem = $( elem ); + elem.removeAttr( 'style' ); + + elem.attr('style',''); // "fixes" webkit bug + + if ( elem.data( 'styles' ) ) { + elem.attr( 'style', elem.data('styles') ).data( 'styles', null ); + } + }); + }, + + moveOut : function( elem ) { + Utils.forceStyles( elem, { + position: 'absolute', + left: -10000 + }); + }, + + moveIn : function() { + Utils.revertStyles.apply( Utils, Utils.array( arguments ) ); + }, + + hide : function( elem, speed, callback ) { + + callback = callback || F; + + var $elem = $(elem); + elem = $elem[0]; + + // save the value if not exist + if (! $elem.data('opacity') ) { + $elem.data('opacity', $elem.css('opacity') ); + } + + // always hide + var style = { opacity: 0 }; + + if (speed) { + + var complete = IE < 9 && elem ? function() { + Utils.removeAlpha( elem ); + elem.style.visibility = 'hidden'; + callback.call( elem ); + } : callback; + + Utils.animate( elem, style, { + duration: speed, + complete: complete, + stop: true + }); + } else { + if ( IE < 9 && elem ) { + Utils.removeAlpha( elem ); + elem.style.visibility = 'hidden'; + } else { + $elem.css( style ); + } + } + }, + + show : function( elem, speed, callback ) { + + callback = callback || F; + + var $elem = $(elem); + elem = $elem[0]; + + // bring back saved opacity + var saved = parseFloat( $elem.data('opacity') ) || 1, + style = { opacity: saved }; + + // animate or toggle + if (speed) { + + if ( IE < 9 ) { + $elem.css('opacity', 0); + elem.style.visibility = 'visible'; + } + + var complete = IE < 9 && elem ? function() { + if ( style.opacity == 1 ) { + Utils.removeAlpha( elem ); + } + callback.call( elem ); + } : callback; + + Utils.animate( elem, style, { + duration: speed, + complete: complete, + stop: true + }); + } else { + if ( IE < 9 && style.opacity == 1 && elem ) { + Utils.removeAlpha( elem ); + elem.style.visibility = 'visible'; + } else { + $elem.css( style ); + } + } + }, + + wait : function(options) { + + Galleria._waiters = Galleria._waiters || []; + + options = $.extend({ + until : FALSE, + success : F, + error : function() { Galleria.raise('Could not complete wait function.'); }, + timeout: 3000 + }, options); + + var start = Utils.timestamp(), + elapsed, + now, + tid, + fn = function() { + now = Utils.timestamp(); + elapsed = now - start; + Utils.removeFromArray( Galleria._waiters, tid ); + if ( options.until( elapsed ) ) { + options.success(); + return false; + } + if (typeof options.timeout == 'number' && now >= start + options.timeout) { + options.error(); + return false; + } + Galleria._waiters.push( tid = window.setTimeout(fn, 10) ); + }; + Galleria._waiters.push( tid = window.setTimeout(fn, 10) ); + }, + + toggleQuality : function( img, force ) { + + if ( ( IE !== 7 && IE !== 8 ) || !img || img.nodeName.toUpperCase() != 'IMG' ) { + return; + } + + if ( typeof force === 'undefined' ) { + force = img.style.msInterpolationMode === 'nearest-neighbor'; + } + + img.style.msInterpolationMode = force ? 'bicubic' : 'nearest-neighbor'; + }, + + insertStyleTag : function( styles, id ) { + + if ( id && $( '#'+id ).length ) { + return; + } + + var style = doc.createElement( 'style' ); + if ( id ) { + style.id = id; + } + + DOM().head.appendChild( style ); + + if ( style.styleSheet ) { // IE + style.styleSheet.cssText = styles; + } else { + var cssText = doc.createTextNode( styles ); + style.appendChild( cssText ); + } + }, + + // a loadscript method that works for local scripts + loadScript: function( url, callback ) { + + var done = false, + script = $('<scr'+'ipt>').attr({ + src: url, + async: true + }).get(0); + + // Attach handlers for all browsers + script.onload = script.onreadystatechange = function() { + if ( !done && (!this.readyState || + this.readyState === 'loaded' || this.readyState === 'complete') ) { + + done = true; + + // Handle memory leak in IE + script.onload = script.onreadystatechange = null; + + if (typeof callback === 'function') { + callback.call( this, this ); + } + } + }; + + DOM().head.appendChild( script ); + }, + + // parse anything into a number + parseValue: function( val ) { + if (typeof val === 'number') { + return val; + } else if (typeof val === 'string') { + var arr = val.match(/\-?\d|\./g); + return arr && arr.constructor === Array ? arr.join('')*1 : 0; + } else { + return 0; + } + }, + + // timestamp abstraction + timestamp: function() { + return new Date().getTime(); + }, + + loadCSS : function( href, id, callback ) { + + var link, + length; + + // look for manual css + $('link[rel=stylesheet]').each(function() { + if ( new RegExp( href ).test( this.href ) ) { + link = this; + return false; + } + }); + + if ( typeof id === 'function' ) { + callback = id; + id = undef; + } + + callback = callback || F; // dirty + + // if already present, return + if ( link ) { + callback.call( link, link ); + return link; + } + + // save the length of stylesheets to check against + length = doc.styleSheets.length; + + // check for existing id + if( $( '#' + id ).length ) { + + $( '#' + id ).attr( 'href', href ); + length--; + + } else { + link = $( '<link>' ).attr({ + rel: 'stylesheet', + href: href, + id: id + }).get(0); + + var styles = $('link[rel="stylesheet"], style'); + if ( styles.length ) { + styles.get(0).parentNode.insertBefore( link, styles[0] ); + } else { + DOM().head.appendChild( link ); + } + + if ( IE && length >= 31 ) { + Galleria.raise( 'You have reached the browser stylesheet limit (31)', true ); + return; + } + } + + if ( typeof callback === 'function' ) { + + // First check for dummy element (new in 1.2.8) + var $loader = $('<s>').attr( 'id', 'galleria-loader' ).hide().appendTo( DOM().body ); + + Utils.wait({ + until: function() { + return $loader.height() == 1; + }, + success: function() { + $loader.remove(); + callback.call( link, link ); + }, + error: function() { + $loader.remove(); + + // If failed, tell the dev to download the latest theme + Galleria.raise( 'Theme CSS could not load after 20 sec. ' + ( Galleria.QUIRK ? + 'Your browser is in Quirks Mode, please add a correct doctype.' : + 'Please download the latest theme at http://galleria.io/customer/.' ), true ); + }, + timeout: 5000 + }); + } + return link; + } + }; + }()), + + // play icon + _playIcon = function( container ) { + + var css = '.galleria-videoicon{width:60px;height:60px;position:absolute;top:50%;left:50%;z-index:1;' + + 'margin:-30px 0 0 -30px;cursor:pointer;background:#000;background:rgba(0,0,0,.8);border-radius:3px;-webkit-transition:all 150ms}' + + '.galleria-videoicon i{width:0px;height:0px;border-style:solid;border-width:10px 0 10px 16px;display:block;' + + 'border-color:transparent transparent transparent #ffffff;margin:20px 0 0 22px}.galleria-image:hover .galleria-videoicon{background:#000}'; + + Utils.insertStyleTag( css, 'galleria-videoicon' ); + + return $( Utils.create( 'galleria-videoicon' ) ).html( '<i></i>' ).appendTo( container ) + .click( function() { $( this ).siblings( 'img' ).mouseup(); }); + }, + + // the transitions holder + _transitions = (function() { + + var _slide = function(params, complete, fade, door) { + + var easing = this.getOptions('easing'), + distance = this.getStageWidth(), + from = { left: distance * ( params.rewind ? -1 : 1 ) }, + to = { left: 0 }; + + if ( fade ) { + from.opacity = 0; + to.opacity = 1; + } else { + from.opacity = 1; + } + + $(params.next).css(from); + + Utils.animate(params.next, to, { + duration: params.speed, + complete: (function( elems ) { + return function() { + complete(); + elems.css({ + left: 0 + }); + }; + }( $( params.next ).add( params.prev ) )), + queue: false, + easing: easing + }); + + if (door) { + params.rewind = !params.rewind; + } + + if (params.prev) { + + from = { left: 0 }; + to = { left: distance * ( params.rewind ? 1 : -1 ) }; + + if ( fade ) { + from.opacity = 1; + to.opacity = 0; + } + + $(params.prev).css(from); + Utils.animate(params.prev, to, { + duration: params.speed, + queue: false, + easing: easing, + complete: function() { + $(this).css('opacity', 0); + } + }); + } + }; + + return { + + active: false, + + init: function( effect, params, complete ) { + if ( _transitions.effects.hasOwnProperty( effect ) ) { + _transitions.effects[ effect ].call( this, params, complete ); + } + }, + + effects: { + + fade: function(params, complete) { + $(params.next).css({ + opacity: 0, + left: 0 + }); + Utils.animate(params.next, { + opacity: 1 + },{ + duration: params.speed, + complete: complete + }); + if (params.prev) { + $(params.prev).css('opacity',1).show(); + Utils.animate(params.prev, { + opacity: 0 + },{ + duration: params.speed + }); + } + }, + + flash: function(params, complete) { + $(params.next).css({ + opacity: 0, + left: 0 + }); + if (params.prev) { + Utils.animate( params.prev, { + opacity: 0 + },{ + duration: params.speed/2, + complete: function() { + Utils.animate( params.next, { + opacity:1 + },{ + duration: params.speed, + complete: complete + }); + } + }); + } else { + Utils.animate( params.next, { + opacity: 1 + },{ + duration: params.speed, + complete: complete + }); + } + }, + + pulse: function(params, complete) { + if (params.prev) { + $(params.prev).hide(); + } + $(params.next).css({ + opacity: 0, + left: 0 + }).show(); + Utils.animate(params.next, { + opacity:1 + },{ + duration: params.speed, + complete: complete + }); + }, + + slide: function(params, complete) { + _slide.apply( this, Utils.array( arguments ) ); + }, + + fadeslide: function(params, complete) { + _slide.apply( this, Utils.array( arguments ).concat( [true] ) ); + }, + + doorslide: function(params, complete) { + _slide.apply( this, Utils.array( arguments ).concat( [false, true] ) ); + } + } + }; + }()); + +// listen to fullscreen +_nativeFullscreen.listen(); + +// create special click:fast event for fast touch interaction +$.event.special['click:fast'] = { + propagate: true, + add: function(handleObj) { + + var getCoords = function(e) { + if ( e.touches && e.touches.length ) { + var touch = e.touches[0]; + return { + x: touch.pageX, + y: touch.pageY + }; + } + }; + + var def = { + touched: false, + touchdown: false, + coords: { x:0, y:0 }, + evObj: {} + }; + + $(this).data({ + clickstate: def, + timer: 0 + }).on('touchstart.fast', function(e) { + window.clearTimeout($(this).data('timer')); + $(this).data('clickstate', { + touched: true, + touchdown: true, + coords: getCoords(e.originalEvent), + evObj: e + }); + }).on('touchmove.fast', function(e) { + var coords = getCoords(e.originalEvent), + state = $(this).data('clickstate'), + distance = Math.max( + Math.abs(state.coords.x - coords.x), + Math.abs(state.coords.y - coords.y) + ); + if ( distance > 6 ) { + $(this).data('clickstate', $.extend(state, { + touchdown: false + })); + } + }).on('touchend.fast', function(e) { + var $this = $(this), + state = $this.data('clickstate'); + if(state.touchdown) { + handleObj.handler.call(this, e); + } + $this.data('timer', window.setTimeout(function() { + $this.data('clickstate', def); + }, 400)); + }).on('click.fast', function(e) { + var state = $(this).data('clickstate'); + if ( state.touched ) { + return false; + } + $(this).data('clickstate', def); + handleObj.handler.call(this, e); + }); + }, + remove: function() { + $(this).off('touchstart.fast touchmove.fast touchend.fast click.fast'); + } +}; + +// trigger resize on orientationchange (IOS7) +$win.on( 'orientationchange', function() { + $(this).resize(); +}); + +/** + The main Galleria class + + @class + @constructor + + @example var gallery = new Galleria(); + + @author http://aino.se + + @requires jQuery + +*/ + +Galleria = function() { + + var self = this; + + // internal options + this._options = {}; + + // flag for controlling play/pause + this._playing = false; + + // internal interval for slideshow + this._playtime = 5000; + + // internal variable for the currently active image + this._active = null; + + // the internal queue, arrayified + this._queue = { length: 0 }; + + // the internal data array + this._data = []; + + // the internal dom collection + this._dom = {}; + + // the internal thumbnails array + this._thumbnails = []; + + // the internal layers array + this._layers = []; + + // internal init flag + this._initialized = false; + + // internal firstrun flag + this._firstrun = false; + + // global stagewidth/height + this._stageWidth = 0; + this._stageHeight = 0; + + // target holder + this._target = undef; + + // bind hashes + this._binds = []; + + // instance id + this._id = parseInt(M.random()*10000, 10); + + // add some elements + var divs = 'container stage images image-nav image-nav-left image-nav-right ' + + 'info info-text info-title info-description ' + + 'thumbnails thumbnails-list thumbnails-container thumb-nav-left thumb-nav-right ' + + 'loader counter tooltip', + spans = 'current total'; + + $.each( divs.split(' '), function( i, elemId ) { + self._dom[ elemId ] = Utils.create( 'galleria-' + elemId ); + }); + + $.each( spans.split(' '), function( i, elemId ) { + self._dom[ elemId ] = Utils.create( 'galleria-' + elemId, 'span' ); + }); + + // the internal keyboard object + // keeps reference of the keybinds and provides helper methods for binding keys + var keyboard = this._keyboard = { + + keys : { + 'UP': 38, + 'DOWN': 40, + 'LEFT': 37, + 'RIGHT': 39, + 'RETURN': 13, + 'ESCAPE': 27, + 'BACKSPACE': 8, + 'SPACE': 32 + }, + + map : {}, + + bound: false, + + press: function(e) { + var key = e.keyCode || e.which; + if ( key in keyboard.map && typeof keyboard.map[key] === 'function' ) { + keyboard.map[key].call(self, e); + } + }, + + attach: function(map) { + + var key, up; + + for( key in map ) { + if ( map.hasOwnProperty( key ) ) { + up = key.toUpperCase(); + if ( up in keyboard.keys ) { + keyboard.map[ keyboard.keys[up] ] = map[key]; + } else { + keyboard.map[ up ] = map[key]; + } + } + } + if ( !keyboard.bound ) { + keyboard.bound = true; + $doc.on('keydown', keyboard.press); + } + }, + + detach: function() { + keyboard.bound = false; + keyboard.map = {}; + $doc.off('keydown', keyboard.press); + } + }; + + // internal controls for keeping track of active / inactive images + var controls = this._controls = { + + 0: undef, + + 1: undef, + + active : 0, + + swap : function() { + controls.active = controls.active ? 0 : 1; + }, + + getActive : function() { + return self._options.swipe ? controls.slides[ self._active ] : controls[ controls.active ]; + }, + + getNext : function() { + return self._options.swipe ? controls.slides[ self.getNext( self._active ) ] : controls[ 1 - controls.active ]; + }, + + slides : [], + + frames: [], + + layers: [] + }; + + // internal carousel object + var carousel = this._carousel = { + + // shortcuts + next: self.$('thumb-nav-right'), + prev: self.$('thumb-nav-left'), + + // cache the width + width: 0, + + // track the current position + current: 0, + + // cache max value + max: 0, + + // save all hooks for each width in an array + hooks: [], + + // update the carousel + // you can run this method anytime, f.ex on window.resize + update: function() { + var w = 0, + h = 0, + hooks = [0]; + + $.each( self._thumbnails, function( i, thumb ) { + if ( thumb.ready ) { + w += thumb.outerWidth || $( thumb.container ).outerWidth( true ); + // Due to a bug in jquery, outerwidth() returns the floor of the actual outerwidth, + // if the browser is zoom to a value other than 100%. height() returns the floating point value. + var containerWidth = $( thumb.container).width(); + w += containerWidth - M.floor(containerWidth); + + hooks[ i+1 ] = w; + h = M.max( h, thumb.outerHeight || $( thumb.container).outerHeight( true ) ); + } + }); + + self.$( 'thumbnails' ).css({ + width: w, + height: h + }); + + carousel.max = w; + carousel.hooks = hooks; + carousel.width = self.$( 'thumbnails-list' ).width(); + carousel.setClasses(); + + self.$( 'thumbnails-container' ).toggleClass( 'galleria-carousel', w > carousel.width ); + + // one extra calculation + carousel.width = self.$( 'thumbnails-list' ).width(); + + // todo: fix so the carousel moves to the left + }, + + bindControls: function() { + + var i; + + carousel.next.on( 'click:fast', function(e) { + e.preventDefault(); + + if ( self._options.carouselSteps === 'auto' ) { + + for ( i = carousel.current; i < carousel.hooks.length; i++ ) { + if ( carousel.hooks[i] - carousel.hooks[ carousel.current ] > carousel.width ) { + carousel.set(i - 2); + break; + } + } + + } else { + carousel.set( carousel.current + self._options.carouselSteps); + } + }); + + carousel.prev.on( 'click:fast', function(e) { + e.preventDefault(); + + if ( self._options.carouselSteps === 'auto' ) { + + for ( i = carousel.current; i >= 0; i-- ) { + if ( carousel.hooks[ carousel.current ] - carousel.hooks[i] > carousel.width ) { + carousel.set( i + 2 ); + break; + } else if ( i === 0 ) { + carousel.set( 0 ); + break; + } + } + } else { + carousel.set( carousel.current - self._options.carouselSteps ); + } + }); + }, + + // calculate and set positions + set: function( i ) { + i = M.max( i, 0 ); + while ( carousel.hooks[i - 1] + carousel.width >= carousel.max && i >= 0 ) { + i--; + } + carousel.current = i; + carousel.animate(); + }, + + // get the last position + getLast: function(i) { + return ( i || carousel.current ) - 1; + }, + + // follow the active image + follow: function(i) { + + //don't follow if position fits + if ( i === 0 || i === carousel.hooks.length - 2 ) { + carousel.set( i ); + return; + } + + // calculate last position + var last = carousel.current; + while( carousel.hooks[last] - carousel.hooks[ carousel.current ] < + carousel.width && last <= carousel.hooks.length ) { + last ++; + } + + // set position + if ( i - 1 < carousel.current ) { + carousel.set( i - 1 ); + } else if ( i + 2 > last) { + carousel.set( i - last + carousel.current + 2 ); + } + }, + + // helper for setting disabled classes + setClasses: function() { + carousel.prev.toggleClass( 'disabled', !carousel.current ); + carousel.next.toggleClass( 'disabled', carousel.hooks[ carousel.current ] + carousel.width >= carousel.max ); + }, + + // the animation method + animate: function(to) { + carousel.setClasses(); + var num = carousel.hooks[ carousel.current ] * -1; + + if ( isNaN( num ) ) { + return; + } + + // FF 24 bug + self.$( 'thumbnails' ).css('left', function() { + return $(this).css('left'); + }); + + Utils.animate(self.get( 'thumbnails' ), { + left: num + },{ + duration: self._options.carouselSpeed, + easing: self._options.easing, + queue: false + }); + } + }; + + // tooltip control + // added in 1.2 + var tooltip = this._tooltip = { + + initialized : false, + + open: false, + + timer: 'tooltip' + self._id, + + swapTimer: 'swap' + self._id, + + init: function() { + + tooltip.initialized = true; + + var css = '.galleria-tooltip{padding:3px 8px;max-width:50%;background:#ffe;color:#000;z-index:3;position:absolute;font-size:11px;line-height:1.3;' + + 'opacity:0;box-shadow:0 0 2px rgba(0,0,0,.4);-moz-box-shadow:0 0 2px rgba(0,0,0,.4);-webkit-box-shadow:0 0 2px rgba(0,0,0,.4);}'; + + Utils.insertStyleTag( css, 'galleria-tooltip' ); + + self.$( 'tooltip' ).css({ + opacity: 0.8, + visibility: 'visible', + display: 'none' + }); + + }, + + // move handler + move: function( e ) { + var mouseX = self.getMousePosition(e).x, + mouseY = self.getMousePosition(e).y, + $elem = self.$( 'tooltip' ), + x = mouseX, + y = mouseY, + height = $elem.outerHeight( true ) + 1, + width = $elem.outerWidth( true ), + limitY = height + 15; + + var maxX = self.$( 'container' ).width() - width - 2, + maxY = self.$( 'container' ).height() - height - 2; + + if ( !isNaN(x) && !isNaN(y) ) { + + x += 10; + y -= ( height+8 ); + + x = M.max( 0, M.min( maxX, x ) ); + y = M.max( 0, M.min( maxY, y ) ); + + if( mouseY < limitY ) { + y = limitY; + } + + $elem.css({ left: x, top: y }); + } + }, + + // bind elements to the tooltip + // you can bind multiple elementIDs using { elemID : function } or { elemID : string } + // you can also bind single DOM elements using bind(elem, string) + bind: function( elem, value ) { + + // todo: revise if alternative tooltip is needed for mobile devices + if (Galleria.TOUCH) { + return; + } + + if (! tooltip.initialized ) { + tooltip.init(); + } + + var mouseout = function() { + self.$( 'container' ).off( 'mousemove', tooltip.move ); + self.clearTimer( tooltip.timer ); + + self.$( 'tooltip' ).stop().animate({ + opacity: 0 + }, 200, function() { + + self.$( 'tooltip' ).hide(); + + self.addTimer( tooltip.swapTimer, function() { + tooltip.open = false; + }, 1000); + }); + }; + + var hover = function( elem, value) { + + tooltip.define( elem, value ); + + $( elem ).hover(function() { + + self.clearTimer( tooltip.swapTimer ); + self.$('container').off( 'mousemove', tooltip.move ).on( 'mousemove', tooltip.move ).trigger( 'mousemove' ); + tooltip.show( elem ); + + self.addTimer( tooltip.timer, function() { + self.$( 'tooltip' ).stop().show().animate({ + opacity: 1 + }); + tooltip.open = true; + + }, tooltip.open ? 0 : 500); + + }, mouseout).click(mouseout); + }; + + if ( typeof value === 'string' ) { + hover( ( elem in self._dom ? self.get( elem ) : elem ), value ); + } else { + // asume elemID here + $.each( elem, function( elemID, val ) { + hover( self.get(elemID), val ); + }); + } + }, + + show: function( elem ) { + + elem = $( elem in self._dom ? self.get(elem) : elem ); + + var text = elem.data( 'tt' ), + mouseup = function( e ) { + + // attach a tiny settimeout to make sure the new tooltip is filled + window.setTimeout( (function( ev ) { + return function() { + tooltip.move( ev ); + }; + }( e )), 10); + + elem.off( 'mouseup', mouseup ); + + }; + + text = typeof text === 'function' ? text() : text; + + if ( ! text ) { + return; + } + + self.$( 'tooltip' ).html( text.replace(/\s/, '&#160;') ); + + // trigger mousemove on mouseup in case of click + elem.on( 'mouseup', mouseup ); + }, + + define: function( elem, value ) { + + // we store functions, not strings + if (typeof value !== 'function') { + var s = value; + value = function() { + return s; + }; + } + + elem = $( elem in self._dom ? self.get(elem) : elem ).data('tt', value); + + tooltip.show( elem ); + + } + }; + + // internal fullscreen control + var fullscreen = this._fullscreen = { + + scrolled: 0, + + crop: undef, + + active: false, + + prev: $(), + + beforeEnter: function(fn){ fn(); }, + beforeExit: function(fn){ fn(); }, + + keymap: self._keyboard.map, + + parseCallback: function( callback, enter ) { + + return _transitions.active ? function() { + if ( typeof callback == 'function' ) { + callback.call(self); + } + var active = self._controls.getActive(), + next = self._controls.getNext(); + + self._scaleImage( next ); + self._scaleImage( active ); + + if ( enter && self._options.trueFullscreen ) { + // Firefox bug, revise later + $( active.container ).add( next.container ).trigger( 'transitionend' ); + } + + } : callback; + + }, + + enter: function( callback ) { + + fullscreen.beforeEnter(function() { + + callback = fullscreen.parseCallback( callback, true ); + + if ( self._options.trueFullscreen && _nativeFullscreen.support ) { + + // do some stuff prior animation for wmoother transitions + + fullscreen.active = true; + + Utils.forceStyles( self.get('container'), { + width: '100%', + height: '100%' + }); + + self.rescale(); + + if ( Galleria.MAC ) { + if ( !( Galleria.SAFARI && /version\/[1-5]/.test(NAV)) ) { + self.$('container').css('opacity', 0).addClass('fullscreen'); + window.setTimeout(function() { + fullscreen.scale(); + self.$('container').css('opacity', 1); + }, 50); + } else { + self.$('stage').css('opacity', 0); + window.setTimeout(function() { + fullscreen.scale(); + self.$('stage').css('opacity', 1); + },4); + } + } else { + self.$('container').addClass('fullscreen'); + } + + $win.resize( fullscreen.scale ); + + _nativeFullscreen.enter( self, callback, self.get('container') ); + + } else { + + fullscreen.scrolled = $win.scrollTop(); + if( !Galleria.TOUCH ) { + window.scrollTo(0, 0); + } + + fullscreen._enter( callback ); + } + }); + + }, + + _enter: function( callback ) { + + fullscreen.active = true; + + if ( IFRAME ) { + + fullscreen.iframe = (function() { + + var elem, + refer = doc.referrer, + test = doc.createElement('a'), + loc = window.location; + + test.href = refer; + + if( test.protocol != loc.protocol || + test.hostname != loc.hostname || + test.port != loc.port ) { + Galleria.raise('Parent fullscreen not available. Iframe protocol, domains and ports must match.'); + return false; + } + + fullscreen.pd = window.parent.document; + + $( fullscreen.pd ).find('iframe').each(function() { + var idoc = this.contentDocument || this.contentWindow.document; + if ( idoc === doc ) { + elem = this; + return false; + } + }); + + return elem; + }()); + + } + + // hide the image until rescale is complete + Utils.hide( self.getActiveImage() ); + + if ( IFRAME && fullscreen.iframe ) { + fullscreen.iframe.scrolled = $( window.parent ).scrollTop(); + window.parent.scrollTo(0, 0); + } + + var data = self.getData(), + options = self._options, + inBrowser = !self._options.trueFullscreen || !_nativeFullscreen.support, + htmlbody = { + height: '100%', + overflow: 'hidden', + margin:0, + padding:0 + }; + + if (inBrowser) { + + self.$('container').addClass('fullscreen'); + fullscreen.prev = self.$('container').prev(); + + if ( !fullscreen.prev.length ) { + fullscreen.parent = self.$( 'container' ).parent(); + } + + // move + self.$( 'container' ).appendTo( 'body' ); + + // begin styleforce + + Utils.forceStyles(self.get('container'), { + position: Galleria.TOUCH ? 'absolute' : 'fixed', + top: 0, + left: 0, + width: '100%', + height: '100%', + zIndex: 10000 + }); + Utils.forceStyles( DOM().html, htmlbody ); + Utils.forceStyles( DOM().body, htmlbody ); + } + + if ( IFRAME && fullscreen.iframe ) { + Utils.forceStyles( fullscreen.pd.documentElement, htmlbody ); + Utils.forceStyles( fullscreen.pd.body, htmlbody ); + Utils.forceStyles( fullscreen.iframe, $.extend( htmlbody, { + width: '100%', + height: '100%', + top: 0, + left: 0, + position: 'fixed', + zIndex: 10000, + border: 'none' + })); + } + + // temporarily attach some keys + // save the old ones first in a cloned object + fullscreen.keymap = $.extend({}, self._keyboard.map); + + self.attachKeyboard({ + escape: self.exitFullscreen, + right: self.next, + left: self.prev + }); + + // temporarily save the crop + fullscreen.crop = options.imageCrop; + + // set fullscreen options + if ( options.fullscreenCrop != undef ) { + options.imageCrop = options.fullscreenCrop; + } + + // swap to big image if it's different from the display image + if ( data && data.big && data.image !== data.big ) { + var big = new Galleria.Picture(), + cached = big.isCached( data.big ), + index = self.getIndex(), + thumb = self._thumbnails[ index ]; + + self.trigger( { + type: Galleria.LOADSTART, + cached: cached, + rewind: false, + index: index, + imageTarget: self.getActiveImage(), + thumbTarget: thumb, + galleriaData: data + }); + + big.load( data.big, function( big ) { + self._scaleImage( big, { + complete: function( big ) { + self.trigger({ + type: Galleria.LOADFINISH, + cached: cached, + index: index, + rewind: false, + imageTarget: big.image, + thumbTarget: thumb + }); + var image = self._controls.getActive().image; + if ( image ) { + $( image ).width( big.image.width ).height( big.image.height ) + .attr( 'style', $( big.image ).attr('style') ) + .attr( 'src', big.image.src ); + } + } + }); + }); + + var n = self.getNext(index), + p = new Galleria.Picture(), + ndata = self.getData( n ); + p.preload( self.isFullscreen() && ndata.big ? ndata.big : ndata.image ); + } + + // init the first rescale and attach callbacks + + self.rescale(function() { + + self.addTimer(false, function() { + // show the image after 50 ms + if ( inBrowser ) { + Utils.show( self.getActiveImage() ); + } + + if (typeof callback === 'function') { + callback.call( self ); + } + self.rescale(); + + }, 100); + + self.trigger( Galleria.FULLSCREEN_ENTER ); + }); + + if ( !inBrowser ) { + Utils.show( self.getActiveImage() ); + } else { + $win.resize( fullscreen.scale ); + } + + }, + + scale : function() { + self.rescale(); + }, + + exit: function( callback ) { + + fullscreen.beforeExit(function() { + + callback = fullscreen.parseCallback( callback ); + + if ( self._options.trueFullscreen && _nativeFullscreen.support ) { + _nativeFullscreen.exit( callback ); + } else { + fullscreen._exit( callback ); + } + }); + }, + + _exit: function( callback ) { + + fullscreen.active = false; + + var inBrowser = !self._options.trueFullscreen || !_nativeFullscreen.support, + $container = self.$( 'container' ).removeClass( 'fullscreen' ); + + // move back + if ( fullscreen.parent ) { + fullscreen.parent.prepend( $container ); + } else { + $container.insertAfter( fullscreen.prev ); + } + + if ( inBrowser ) { + Utils.hide( self.getActiveImage() ); + + // revert all styles + Utils.revertStyles( self.get('container'), DOM().html, DOM().body ); + + // scroll back + if( !Galleria.TOUCH ) { + window.scrollTo(0, fullscreen.scrolled); + } + + // reload iframe src manually + var frame = self._controls.frames[ self._controls.active ]; + if ( frame && frame.image ) { + frame.image.src = frame.image.src; + } + } + + if ( IFRAME && fullscreen.iframe ) { + Utils.revertStyles( fullscreen.pd.documentElement, fullscreen.pd.body, fullscreen.iframe ); + if ( fullscreen.iframe.scrolled ) { + window.parent.scrollTo(0, fullscreen.iframe.scrolled ); + } + } + + // detach all keyboard events and apply the old keymap + self.detachKeyboard(); + self.attachKeyboard( fullscreen.keymap ); + + // bring back cached options + self._options.imageCrop = fullscreen.crop; + + // return to original image + var big = self.getData().big, + image = self._controls.getActive().image; + + if ( !self.getData().iframe && image && big && big == image.src ) { + + window.setTimeout(function(src) { + return function() { + image.src = src; + }; + }( self.getData().image ), 1 ); + + } + + self.rescale(function() { + self.addTimer(false, function() { + + // show the image after 50 ms + if ( inBrowser ) { + Utils.show( self.getActiveImage() ); + } + + if ( typeof callback === 'function' ) { + callback.call( self ); + } + + $win.trigger( 'resize' ); + + }, 50); + self.trigger( Galleria.FULLSCREEN_EXIT ); + }); + + $win.off('resize', fullscreen.scale); + } + }; + + // the internal idle object for controlling idle states + var idle = this._idle = { + + trunk: [], + + bound: false, + + active: false, + + add: function(elem, to, from, hide) { + if ( !elem || Galleria.TOUCH ) { + return; + } + if (!idle.bound) { + idle.addEvent(); + } + elem = $(elem); + + if ( typeof from == 'boolean' ) { + hide = from; + from = {}; + } + + from = from || {}; + + var extract = {}, + style; + + for ( style in to ) { + if ( to.hasOwnProperty( style ) ) { + extract[ style ] = elem.css( style ); + } + } + + elem.data('idle', { + from: $.extend( extract, from ), + to: to, + complete: true, + busy: false + }); + + if ( !hide ) { + idle.addTimer(); + } else { + elem.css( to ); + } + idle.trunk.push(elem); + }, + + remove: function(elem) { + + elem = $(elem); + + $.each(idle.trunk, function(i, el) { + if ( el && el.length && !el.not(elem).length ) { + elem.css( elem.data( 'idle' ).from ); + idle.trunk.splice(i, 1); + } + }); + + if (!idle.trunk.length) { + idle.removeEvent(); + self.clearTimer( idle.timer ); + } + }, + + addEvent : function() { + idle.bound = true; + self.$('container').on( 'mousemove click', idle.showAll ); + if ( self._options.idleMode == 'hover' ) { + self.$('container').on( 'mouseleave', idle.hide ); + } + }, + + removeEvent : function() { + idle.bound = false; + self.$('container').on( 'mousemove click', idle.showAll ); + if ( self._options.idleMode == 'hover' ) { + self.$('container').off( 'mouseleave', idle.hide ); + } + }, + + addTimer : function() { + if( self._options.idleMode == 'hover' ) { + return; + } + self.addTimer( 'idle', function() { + idle.hide(); + }, self._options.idleTime ); + }, + + hide : function() { + + if ( !self._options.idleMode || self.getIndex() === false ) { + return; + } + + self.trigger( Galleria.IDLE_ENTER ); + + var len = idle.trunk.length; + + $.each( idle.trunk, function(i, elem) { + + var data = elem.data('idle'); + + if (! data) { + return; + } + + elem.data('idle').complete = false; + + Utils.animate( elem, data.to, { + duration: self._options.idleSpeed, + complete: function() { + if ( i == len-1 ) { + idle.active = false; + } + } + }); + }); + }, + + showAll : function() { + + self.clearTimer( 'idle' ); + + $.each( idle.trunk, function( i, elem ) { + idle.show( elem ); + }); + }, + + show: function(elem) { + + var data = elem.data('idle'); + + if ( !idle.active || ( !data.busy && !data.complete ) ) { + + data.busy = true; + + self.trigger( Galleria.IDLE_EXIT ); + + self.clearTimer( 'idle' ); + + Utils.animate( elem, data.from, { + duration: self._options.idleSpeed/2, + complete: function() { + idle.active = true; + $(elem).data('idle').busy = false; + $(elem).data('idle').complete = true; + } + }); + + } + idle.addTimer(); + } + }; + + // internal lightbox object + // creates a predesigned lightbox for simple popups of images in galleria + var lightbox = this._lightbox = { + + width : 0, + + height : 0, + + initialized : false, + + active : null, + + image : null, + + elems : {}, + + keymap: false, + + init : function() { + + if ( lightbox.initialized ) { + return; + } + lightbox.initialized = true; + + // create some elements to work with + var elems = 'overlay box content shadow title info close prevholder prev nextholder next counter image', + el = {}, + op = self._options, + css = '', + abs = 'position:absolute;', + prefix = 'lightbox-', + cssMap = { + overlay: 'position:fixed;display:none;opacity:'+op.overlayOpacity+';filter:alpha(opacity='+(op.overlayOpacity*100)+ + ');top:0;left:0;width:100%;height:100%;background:'+op.overlayBackground+';z-index:99990', + box: 'position:fixed;display:none;width:400px;height:400px;top:50%;left:50%;margin-top:-200px;margin-left:-200px;z-index:99991', + shadow: abs+'background:#000;width:100%;height:100%;', + content: abs+'background-color:#fff;top:10px;left:10px;right:10px;bottom:10px;overflow:hidden', + info: abs+'bottom:10px;left:10px;right:10px;color:#444;font:11px/13px arial,sans-serif;height:13px', + close: abs+'top:10px;right:10px;height:20px;width:20px;background:#fff;text-align:center;cursor:pointer;color:#444;font:16px/22px arial,sans-serif;z-index:99999', + image: abs+'top:10px;left:10px;right:10px;bottom:30px;overflow:hidden;display:block;', + prevholder: abs+'width:50%;top:0;bottom:40px;cursor:pointer;', + nextholder: abs+'width:50%;top:0;bottom:40px;right:-1px;cursor:pointer;', + prev: abs+'top:50%;margin-top:-20px;height:40px;width:30px;background:#fff;left:20px;display:none;text-align:center;color:#000;font:bold 16px/36px arial,sans-serif', + next: abs+'top:50%;margin-top:-20px;height:40px;width:30px;background:#fff;right:20px;left:auto;display:none;font:bold 16px/36px arial,sans-serif;text-align:center;color:#000', + title: 'float:left', + counter: 'float:right;margin-left:8px;' + }, + hover = function(elem) { + return elem.hover( + function() { $(this).css( 'color', '#bbb' ); }, + function() { $(this).css( 'color', '#444' ); } + ); + }, + appends = {}; + + // fix for navigation hovers transparent background event "feature" + var exs = ''; + if ( IE > 7 ) { + exs = IE < 9 ? 'background:#000;filter:alpha(opacity=0);' : 'background:rgba(0,0,0,0);'; + } else { + exs = 'z-index:99999'; + } + + cssMap.nextholder += exs; + cssMap.prevholder += exs; + + // create and insert CSS + $.each(cssMap, function( key, value ) { + css += '.galleria-'+prefix+key+'{'+value+'}'; + }); + + css += '.galleria-'+prefix+'box.iframe .galleria-'+prefix+'prevholder,'+ + '.galleria-'+prefix+'box.iframe .galleria-'+prefix+'nextholder{'+ + 'width:100px;height:100px;top:50%;margin-top:-70px}'; + + Utils.insertStyleTag( css, 'galleria-lightbox' ); + + // create the elements + $.each(elems.split(' '), function( i, elemId ) { + self.addElement( 'lightbox-' + elemId ); + el[ elemId ] = lightbox.elems[ elemId ] = self.get( 'lightbox-' + elemId ); + }); + + // initiate the image + lightbox.image = new Galleria.Picture(); + + // append the elements + $.each({ + box: 'shadow content close prevholder nextholder', + info: 'title counter', + content: 'info image', + prevholder: 'prev', + nextholder: 'next' + }, function( key, val ) { + var arr = []; + $.each( val.split(' '), function( i, prop ) { + arr.push( prefix + prop ); + }); + appends[ prefix+key ] = arr; + }); + + self.append( appends ); + + $( el.image ).append( lightbox.image.container ); + + $( DOM().body ).append( el.overlay, el.box ); + + // add the prev/next nav and bind some controls + + hover( $( el.close ).on( 'click:fast', lightbox.hide ).html('&#215;') ); + + $.each( ['Prev','Next'], function(i, dir) { + + var $d = $( el[ dir.toLowerCase() ] ).html( /v/.test( dir ) ? '&#8249;&#160;' : '&#160;&#8250;' ), + $e = $( el[ dir.toLowerCase()+'holder'] ); + + $e.on( 'click:fast', function() { + lightbox[ 'show' + dir ](); + }); + + // IE7 and touch devices will simply show the nav + if ( IE < 8 || Galleria.TOUCH ) { + $d.show(); + return; + } + + $e.hover( function() { + $d.show(); + }, function(e) { + $d.stop().fadeOut( 200 ); + }); + + }); + $( el.overlay ).on( 'click:fast', lightbox.hide ); + + // the lightbox animation is slow on ipad + if ( Galleria.IPAD ) { + self._options.lightboxTransitionSpeed = 0; + } + + }, + + rescale: function(event) { + + // calculate + var width = M.min( $win.width()-40, lightbox.width ), + height = M.min( $win.height()-60, lightbox.height ), + ratio = M.min( width / lightbox.width, height / lightbox.height ), + destWidth = M.round( lightbox.width * ratio ) + 40, + destHeight = M.round( lightbox.height * ratio ) + 60, + to = { + width: destWidth, + height: destHeight, + 'margin-top': M.ceil( destHeight / 2 ) *- 1, + 'margin-left': M.ceil( destWidth / 2 ) *- 1 + }; + + // if rescale event, don't animate + if ( event ) { + $( lightbox.elems.box ).css( to ); + } else { + $( lightbox.elems.box ).animate( to, { + duration: self._options.lightboxTransitionSpeed, + easing: self._options.easing, + complete: function() { + var image = lightbox.image, + speed = self._options.lightboxFadeSpeed; + + self.trigger({ + type: Galleria.LIGHTBOX_IMAGE, + imageTarget: image.image + }); + + $( image.container ).show(); + + $( image.image ).animate({ opacity: 1 }, speed); + Utils.show( lightbox.elems.info, speed ); + } + }); + } + }, + + hide: function() { + + // remove the image + lightbox.image.image = null; + + $win.off('resize', lightbox.rescale); + + $( lightbox.elems.box ).hide().find( 'iframe' ).remove(); + + Utils.hide( lightbox.elems.info ); + + self.detachKeyboard(); + self.attachKeyboard( lightbox.keymap ); + + lightbox.keymap = false; + + Utils.hide( lightbox.elems.overlay, 200, function() { + $( this ).hide().css( 'opacity', self._options.overlayOpacity ); + self.trigger( Galleria.LIGHTBOX_CLOSE ); + }); + }, + + showNext: function() { + lightbox.show( self.getNext( lightbox.active ) ); + }, + + showPrev: function() { + lightbox.show( self.getPrev( lightbox.active ) ); + }, + + show: function(index) { + + lightbox.active = index = typeof index === 'number' ? index : self.getIndex() || 0; + + if ( !lightbox.initialized ) { + lightbox.init(); + } + + // trigger the event + self.trigger( Galleria.LIGHTBOX_OPEN ); + + // temporarily attach some keys + // save the old ones first in a cloned object + if ( !lightbox.keymap ) { + + lightbox.keymap = $.extend({}, self._keyboard.map); + + self.attachKeyboard({ + escape: lightbox.hide, + right: lightbox.showNext, + left: lightbox.showPrev + }); + } + + $win.off('resize', lightbox.rescale ); + + var data = self.getData(index), + total = self.getDataLength(), + n = self.getNext( index ), + ndata, p, i; + + Utils.hide( lightbox.elems.info ); + + try { + for ( i = self._options.preload; i > 0; i-- ) { + p = new Galleria.Picture(); + ndata = self.getData( n ); + p.preload( ndata.big ? ndata.big : ndata.image ); + n = self.getNext( n ); + } + } catch(e) {} + + lightbox.image.isIframe = ( data.iframe && !data.image ); + + $( lightbox.elems.box ).toggleClass( 'iframe', lightbox.image.isIframe ); + + $( lightbox.image.container ).find( '.galleria-videoicon' ).remove(); + + lightbox.image.load( data.big || data.image || data.iframe, function( image ) { + + if ( image.isIframe ) { + + var cw = $(window).width(), + ch = $(window).height(); + + if ( image.video && self._options.maxVideoSize ) { + var r = M.min( self._options.maxVideoSize/cw, self._options.maxVideoSize/ch ); + if ( r < 1 ) { + cw *= r; + ch *= r; + } + } + lightbox.width = cw; + lightbox.height = ch; + + } else { + lightbox.width = image.original.width; + lightbox.height = image.original.height; + } + + $( image.image ).css({ + width: image.isIframe ? '100%' : '100.1%', + height: image.isIframe ? '100%' : '100.1%', + top: 0, + bottom: 0, + zIndex: 99998, + opacity: 0, + visibility: 'visible' + }).parent().height('100%'); + + lightbox.elems.title.innerHTML = data.title || ''; + lightbox.elems.counter.innerHTML = (index + 1) + ' / ' + total; + $win.resize( lightbox.rescale ); + lightbox.rescale(); + + if( data.image && data.iframe ) { + + $( lightbox.elems.box ).addClass('iframe'); + + if ( data.video ) { + var $icon = _playIcon( image.container ).hide(); + window.setTimeout(function() { + $icon.fadeIn(200); + }, 200); + } + + $( image.image ).css( 'cursor', 'pointer' ).mouseup((function(data, image) { + return function(e) { + $( lightbox.image.container ).find( '.galleria-videoicon' ).remove(); + e.preventDefault(); + image.isIframe = true; + image.load( data.iframe + ( data.video ? '&autoplay=1' : '' ), { + width: '100%', + height: IE < 8 ? $( lightbox.image.container ).height() : '100%' + }); + }; + }(data, image))); + } + }); + + $( lightbox.elems.overlay ).show().css( 'visibility', 'visible' ); + $( lightbox.elems.box ).show(); + } + }; + + // the internal timeouts object + // provides helper methods for controlling timeouts + + var _timer = this._timer = { + + trunk: {}, + + add: function( id, fn, delay, loop ) { + id = id || new Date().getTime(); + loop = loop || false; + this.clear( id ); + if ( loop ) { + var old = fn; + fn = function() { + old(); + _timer.add( id, fn, delay ); + }; + } + this.trunk[ id ] = window.setTimeout( fn, delay ); + }, + + clear: function( id ) { + + var del = function( i ) { + window.clearTimeout( this.trunk[ i ] ); + delete this.trunk[ i ]; + }, i; + + if ( !!id && id in this.trunk ) { + del.call( this, id ); + + } else if ( typeof id === 'undefined' ) { + for ( i in this.trunk ) { + if ( this.trunk.hasOwnProperty( i ) ) { + del.call( this, i ); + } + } + } + } + }; + + return this; +}; + +// end Galleria constructor + +Galleria.prototype = { + + // bring back the constructor reference + + constructor: Galleria, + + /** + Use this function to initialize the gallery and start loading. + Should only be called once per instance. + + @param {HTMLElement} target The target element + @param {Object} options The gallery options + + @returns Instance + */ + + init: function( target, options ) { + + options = _legacyOptions( options ); + + // save the original ingredients + this._original = { + target: target, + options: options, + data: null + }; + + // save the target here + this._target = this._dom.target = target.nodeName ? target : $( target ).get(0); + + // save the original content for destruction + this._original.html = this._target.innerHTML; + + // push the instance + _instances.push( this ); + + // raise error if no target is detected + if ( !this._target ) { + Galleria.raise('Target not found', true); + return; + } + + // apply options + this._options = { + autoplay: false, + carousel: true, + carouselFollow: true, // legacy, deprecate at 1.3 + carouselSpeed: 400, + carouselSteps: 'auto', + clicknext: false, + dailymotion: { + foreground: '%23EEEEEE', + highlight: '%235BCEC5', + background: '%23222222', + logo: 0, + hideInfos: 1 + }, + dataConfig : function( elem ) { return {}; }, + dataSelector: 'img', + dataSort: false, + dataSource: this._target, + debug: undef, + dummy: undef, // 1.2.5 + easing: 'galleria', + extend: function(options) {}, + fullscreenCrop: undef, // 1.2.5 + fullscreenDoubleTap: true, // 1.2.4 toggles fullscreen on double-tap for touch devices + fullscreenTransition: undef, // 1.2.6 + height: 0, + idleMode: true, // 1.2.4 toggles idleMode + idleTime: 3000, + idleSpeed: 200, + imageCrop: false, + imageMargin: 0, + imagePan: false, + imagePanSmoothness: 12, + imagePosition: '50%', + imageTimeout: undef, // 1.2.5 + initialTransition: undef, // 1.2.4, replaces transitionInitial + keepSource: false, + layerFollow: true, // 1.2.5 + lightbox: false, // 1.2.3 + lightboxFadeSpeed: 200, + lightboxTransitionSpeed: 200, + linkSourceImages: true, + maxScaleRatio: undef, + maxVideoSize: undef, // 1.2.9 + minScaleRatio: undef, // deprecated in 1.2.9 + overlayOpacity: 0.85, + overlayBackground: '#0b0b0b', + pauseOnInteraction: true, + popupLinks: false, + preload: 2, + queue: true, + responsive: true, + show: 0, + showInfo: true, + showCounter: true, + showImagenav: true, + swipe: 'auto', // 1.2.4 -> revised in 1.3 -> changed type in 1.3.5 + theme: null, + thumbCrop: true, + thumbEventType: 'click:fast', + thumbMargin: 0, + thumbQuality: 'auto', + thumbDisplayOrder: true, // 1.2.8 + thumbPosition: '50%', // 1.3 + thumbnails: true, + touchTransition: undef, // 1.2.6 + transition: 'fade', + transitionInitial: undef, // legacy, deprecate in 1.3. Use initialTransition instead. + transitionSpeed: 400, + trueFullscreen: true, // 1.2.7 + useCanvas: false, // 1.2.4 + variation: '', // 1.3.2 + videoPoster: true, // 1.3 + vimeo: { + title: 0, + byline: 0, + portrait: 0, + color: 'aaaaaa' + }, + wait: 5000, // 1.2.7 + width: 'auto', + youtube: { + modestbranding: 1, + autohide: 1, + color: 'white', + hd: 1, + rel: 0, + showinfo: 0 + } + }; + + // legacy support for transitionInitial + this._options.initialTransition = this._options.initialTransition || this._options.transitionInitial; + + if ( options ) { + + // turn off debug + if ( options.debug === false ) { + DEBUG = false; + } + + // set timeout + if ( typeof options.imageTimeout === 'number' ) { + TIMEOUT = options.imageTimeout; + } + + // set dummy + if ( typeof options.dummy === 'string' ) { + DUMMY = options.dummy; + } + + // set theme + if ( typeof options.theme == 'string' ) { + this._options.theme = options.theme; + } + } + + // hide all content + $( this._target ).children().hide(); + + // Warn for quirks mode + if ( Galleria.QUIRK ) { + Galleria.raise('Your page is in Quirks mode, Galleria may not render correctly. Please validate your HTML and add a correct doctype.'); + } + + // now we just have to wait for the theme... + // first check if it has already loaded + if ( _loadedThemes.length ) { + if ( this._options.theme ) { + for ( var i=0; i<_loadedThemes.length; i++ ) { + if( this._options.theme === _loadedThemes[i].name ) { + this.theme = _loadedThemes[i]; + break; + } + } + } else { + // if no theme sepcified, apply the first loaded theme + this.theme = _loadedThemes[0]; + } + } + + if ( typeof this.theme == 'object' ) { + this._init(); + } else { + // if no theme is loaded yet, push the instance into a pool and run it when the theme is ready + _pool.push( this ); + } + + return this; + }, + + // this method should only be called once per instance + // for manipulation of data, use the .load method + + _init: function() { + + var self = this, + options = this._options; + + if ( this._initialized ) { + Galleria.raise( 'Init failed: Gallery instance already initialized.' ); + return this; + } + + this._initialized = true; + + if ( !this.theme ) { + Galleria.raise( 'Init failed: No theme found.', true ); + return this; + } + + // merge the theme & caller options + $.extend( true, options, this.theme.defaults, this._original.options, Galleria.configure.options ); + + // internally we use boolean for swipe + options.swipe = (function(s) { + + if ( s == 'enforced' ) { return true; } + + // legacy patch + if( s === false || s == 'disabled' ) { return false; } + + return !!Galleria.TOUCH; + + }( options.swipe )); + + // disable options that arent compatible with swipe + if ( options.swipe ) { + options.clicknext = false; + options.imagePan = false; + } + + // check for canvas support + (function( can ) { + if ( !( 'getContext' in can ) ) { + can = null; + return; + } + _canvas = _canvas || { + elem: can, + context: can.getContext( '2d' ), + cache: {}, + length: 0 + }; + }( doc.createElement( 'canvas' ) ) ); + + // bind the gallery to run when data is ready + this.bind( Galleria.DATA, function() { + + // remove big if total pixels are less than 1024 (most phones) + if ( window.screen && window.screen.width && Array.prototype.forEach ) { + + this._data.forEach(function(data) { + + var density = 'devicePixelRatio' in window ? window.devicePixelRatio : 1, + m = M.max( window.screen.width, window.screen.height ); + + if ( m*density < 1024 ) { + data.big = data.image; + } + }); + } + + // save the new data + this._original.data = this._data; + + // lets show the counter here + this.get('total').innerHTML = this.getDataLength(); + + // cache the container + var $container = this.$( 'container' ); + + // set ratio if height is < 2 + if ( self._options.height < 2 ) { + self._userRatio = self._ratio = self._options.height; + } + + // the gallery is ready, let's just wait for the css + var num = { width: 0, height: 0 }; + var testHeight = function() { + return self.$( 'stage' ).height(); + }; + + // check container and thumbnail height + Utils.wait({ + until: function() { + + // keep trying to get the value + num = self._getWH(); + $container.width( num.width ).height( num.height ); + return testHeight() && num.width && num.height > 50; + + }, + success: function() { + + self._width = num.width; + self._height = num.height; + self._ratio = self._ratio || num.height/num.width; + + // for some strange reason, webkit needs a single setTimeout to play ball + if ( Galleria.WEBKIT ) { + window.setTimeout( function() { + self._run(); + }, 1); + } else { + self._run(); + } + }, + error: function() { + + // Height was probably not set, raise hard errors + + if ( testHeight() ) { + Galleria.raise('Could not extract sufficient width/height of the gallery container. Traced measures: width:' + num.width + 'px, height: ' + num.height + 'px.', true); + } else { + Galleria.raise('Could not extract a stage height from the CSS. Traced height: ' + testHeight() + 'px.', true); + } + }, + timeout: typeof this._options.wait == 'number' ? this._options.wait : false + }); + }); + + // build the gallery frame + this.append({ + 'info-text' : + ['info-title', 'info-description'], + 'info' : + ['info-text'], + 'image-nav' : + ['image-nav-right', 'image-nav-left'], + 'stage' : + ['images', 'loader', 'counter', 'image-nav'], + 'thumbnails-list' : + ['thumbnails'], + 'thumbnails-container' : + ['thumb-nav-left', 'thumbnails-list', 'thumb-nav-right'], + 'container' : + ['stage', 'thumbnails-container', 'info', 'tooltip'] + }); + + Utils.hide( this.$( 'counter' ).append( + this.get( 'current' ), + doc.createTextNode(' / '), + this.get( 'total' ) + ) ); + + this.setCounter('&#8211;'); + + Utils.hide( self.get('tooltip') ); + + // add a notouch class on the container to prevent unwanted :hovers on touch devices + this.$( 'container' ).addClass([ + ( Galleria.TOUCH ? 'touch' : 'notouch' ), + this._options.variation, + 'galleria-theme-'+this.theme.name + ].join(' ')); + + // add images to the controls + if ( !this._options.swipe ) { + $.each( new Array(2), function( i ) { + + // create a new Picture instance + var image = new Galleria.Picture(); + + // apply some styles, create & prepend overlay + $( image.container ).css({ + position: 'absolute', + top: 0, + left: 0 + }).prepend( self._layers[i] = $( Utils.create('galleria-layer') ).css({ + position: 'absolute', + top:0, left:0, right:0, bottom:0, + zIndex:2 + })[0] ); + + // append the image + self.$( 'images' ).append( image.container ); + + // reload the controls + self._controls[i] = image; + + // build a frame + var frame = new Galleria.Picture(); + frame.isIframe = true; + + $( frame.container ).attr('class', 'galleria-frame').css({ + position: 'absolute', + top: 0, + left: 0, + zIndex: 4, + background: '#000', + display: 'none' + }).appendTo( image.container ); + + self._controls.frames[i] = frame; + + }); + } + + // some forced generic styling + this.$( 'images' ).css({ + position: 'relative', + top: 0, + left: 0, + width: '100%', + height: '100%' + }); + + if ( options.swipe ) { + this.$( 'images' ).css({ + position: 'absolute', + top: 0, + left: 0, + width: 0, + height: '100%' + }); + this.finger = new Galleria.Finger(this.get('stage'), { + onchange: function(page) { + self.pause().show(page); + }, + oncomplete: function(page) { + + var index = M.max( 0, M.min( parseInt( page, 10 ), self.getDataLength() - 1 ) ), + data = self.getData(index); + + $( self._thumbnails[ index ].container ) + .addClass( 'active' ) + .siblings( '.active' ) + .removeClass( 'active' ); + + if ( !data ) { + return; + } + + // remove video iframes + self.$( 'images' ).find( '.galleria-frame' ).css('opacity', 0).hide().find( 'iframe' ).remove(); + + if ( self._options.carousel && self._options.carouselFollow ) { + self._carousel.follow( index ); + } + } + }); + this.bind( Galleria.RESCALE, function() { + this.finger.setup(); + }); + this.$('stage').on('click', function(e) { + var data = self.getData(); + if ( !data ) { + return; + } + if ( data.iframe ) { + + if ( self.isPlaying() ) { + self.pause(); + } + var frame = self._controls.frames[ self._active ], + w = self._stageWidth, + h = self._stageHeight; + + if ( $( frame.container ).find( 'iframe' ).length ) { + return; + } + + $( frame.container ).css({ + width: w, + height: h, + opacity: 0 + }).show().animate({ + opacity: 1 + }, 200); + + window.setTimeout(function() { + frame.load( data.iframe + ( data.video ? '&autoplay=1' : '' ), { + width: w, + height: h + }, function( frame ) { + self.$( 'container' ).addClass( 'videoplay' ); + frame.scale({ + width: self._stageWidth, + height: self._stageHeight, + iframelimit: data.video ? self._options.maxVideoSize : undef + }); + }); + }, 100); + + return; + } + + if ( data.link ) { + if ( self._options.popupLinks ) { + var win = window.open( data.link, '_blank' ); + } else { + window.location.href = data.link; + } + return; + } + }); + this.bind( Galleria.IMAGE, function(e) { + + self.setCounter( e.index ); + self.setInfo( e.index ); + + var next = this.getNext(), + prev = this.getPrev(); + + var preloads = [prev,next]; + preloads.push(this.getNext(next), this.getPrev(prev), self._controls.slides.length-1); + + var filtered = []; + + $.each(preloads, function(i, val) { + if ( $.inArray(val, filtered) == -1 ) { + filtered.push(val); + } + }); + + $.each(filtered, function(i, loadme) { + var d = self.getData(loadme), + img = self._controls.slides[loadme], + src = self.isFullscreen() && d.big ? d.big : ( d.image || d.iframe ); + + if ( d.iframe && !d.image ) { + img.isIframe = true; + } + + if ( !img.ready ) { + self._controls.slides[loadme].load(src, function(img) { + if ( !img.isIframe ) { + $(img.image).css('visibility', 'hidden'); + } + self._scaleImage(img, { + complete: function(img) { + if ( !img.isIframe ) { + $(img.image).css({ + opacity: 0, + visibility: 'visible' + }).animate({ + opacity: 1 + }, 200); + } + } + }); + }); + } + }); + }); + } + + this.$( 'thumbnails, thumbnails-list' ).css({ + overflow: 'hidden', + position: 'relative' + }); + + // bind image navigation arrows + this.$( 'image-nav-right, image-nav-left' ).on( 'click:fast', function(e) { + + // pause if options is set + if ( options.pauseOnInteraction ) { + self.pause(); + } + + // navigate + var fn = /right/.test( this.className ) ? 'next' : 'prev'; + self[ fn ](); + + }).on('click', function(e) { + + e.preventDefault(); + + // tune the clicknext option + if ( options.clicknext || options.swipe ) { + e.stopPropagation(); + } + }); + + // hide controls if chosen to + $.each( ['info','counter','image-nav'], function( i, el ) { + if ( options[ 'show' + el.substr(0,1).toUpperCase() + el.substr(1).replace(/-/,'') ] === false ) { + Utils.moveOut( self.get( el.toLowerCase() ) ); + } + }); + + // load up target content + this.load(); + + // now it's usually safe to remove the content + // IE will never stop loading if we remove it, so let's keep it hidden for IE (it's usually fast enough anyway) + if ( !options.keepSource && !IE ) { + this._target.innerHTML = ''; + } + + // re-append the errors, if they happened before clearing + if ( this.get( 'errors' ) ) { + this.appendChild( 'target', 'errors' ); + } + + // append the gallery frame + this.appendChild( 'target', 'container' ); + + // parse the carousel on each thumb load + if ( options.carousel ) { + var count = 0, + show = options.show; + this.bind( Galleria.THUMBNAIL, function() { + this.updateCarousel(); + if ( ++count == this.getDataLength() && typeof show == 'number' && show > 0 ) { + this._carousel.follow( show ); + } + }); + } + + // bind window resize for responsiveness + if ( options.responsive ) { + $win.on( 'resize', function() { + if ( !self.isFullscreen() ) { + self.resize(); + } + }); + } + + // double-tap/click fullscreen toggle + + if ( options.fullscreenDoubleTap ) { + + this.$( 'stage' ).on( 'touchstart', (function() { + var last, cx, cy, lx, ly, now, + getData = function(e) { + return e.originalEvent.touches ? e.originalEvent.touches[0] : e; + }; + self.$( 'stage' ).on('touchmove', function() { + last = 0; + }); + return function(e) { + if( /(-left|-right)/.test(e.target.className) ) { + return; + } + now = Utils.timestamp(); + cx = getData(e).pageX; + cy = getData(e).pageY; + if ( e.originalEvent.touches.length < 2 && ( now - last < 300 ) && ( cx - lx < 20) && ( cy - ly < 20) ) { + self.toggleFullscreen(); + e.preventDefault(); + return; + } + last = now; + lx = cx; + ly = cy; + }; + }())); + } + + // bind the ons + $.each( Galleria.on.binds, function(i, bind) { + // check if already bound + if ( $.inArray( bind.hash, self._binds ) == -1 ) { + self.bind( bind.type, bind.callback ); + } + }); + + return this; + }, + + addTimer : function() { + this._timer.add.apply( this._timer, Utils.array( arguments ) ); + return this; + }, + + clearTimer : function() { + this._timer.clear.apply( this._timer, Utils.array( arguments ) ); + return this; + }, + + // parse width & height from CSS or options + + _getWH : function() { + + var $container = this.$( 'container' ), + $target = this.$( 'target' ), + self = this, + num = {}, + arr; + + $.each(['width', 'height'], function( i, m ) { + + // first check if options is set + if ( self._options[ m ] && typeof self._options[ m ] === 'number') { + num[ m ] = self._options[ m ]; + } else { + + arr = [ + Utils.parseValue( $container.css( m ) ), // the container css height + Utils.parseValue( $target.css( m ) ), // the target css height + $container[ m ](), // the container jQuery method + $target[ m ]() // the target jQuery method + ]; + + // if first time, include the min-width & min-height + if ( !self[ '_'+m ] ) { + arr.splice(arr.length, + Utils.parseValue( $container.css( 'min-'+m ) ), + Utils.parseValue( $target.css( 'min-'+m ) ) + ); + } + + // else extract the measures from different sources and grab the highest value + num[ m ] = M.max.apply( M, arr ); + } + }); + + // allow setting a height ratio instead of exact value + // useful when doing responsive galleries + + if ( self._userRatio ) { + num.height = num.width * self._userRatio; + } + + return num; + }, + + // Creates the thumbnails and carousel + // can be used at any time, f.ex when the data object is manipulated + // push is an optional argument with pushed images + + _createThumbnails : function( push ) { + + this.get( 'total' ).innerHTML = this.getDataLength(); + + var src, + thumb, + data, + + $container, + + self = this, + o = this._options, + + i = push ? this._data.length - push.length : 0, + chunk = i, + + thumbchunk = [], + loadindex = 0, + + gif = IE < 8 ? 'http://upload.wikimedia.org/wikipedia/commons/c/c0/Blank.gif' : + 'data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D', + + // get previously active thumbnail, if exists + active = (function() { + var a = self.$('thumbnails').find('.active'); + if ( !a.length ) { + return false; + } + return a.find('img').attr('src'); + }()), + + // cache the thumbnail option + optval = typeof o.thumbnails === 'string' ? o.thumbnails.toLowerCase() : null, + + // move some data into the instance + // for some reason, jQuery cant handle css(property) when zooming in FF, breaking the gallery + // so we resort to getComputedStyle for browsers who support it + getStyle = function( prop ) { + return doc.defaultView && doc.defaultView.getComputedStyle ? + doc.defaultView.getComputedStyle( thumb.container, null )[ prop ] : + $container.css( prop ); + }, + + fake = function(image, index, container) { + return function() { + $( container ).append( image ); + self.trigger({ + type: Galleria.THUMBNAIL, + thumbTarget: image, + index: index, + galleriaData: self.getData( index ) + }); + }; + }, + + onThumbEvent = function( e ) { + + // pause if option is set + if ( o.pauseOnInteraction ) { + self.pause(); + } + + // extract the index from the data + var index = $( e.currentTarget ).data( 'index' ); + if ( self.getIndex() !== index ) { + self.show( index ); + } + + e.preventDefault(); + }, + + thumbComplete = function( thumb, callback ) { + + $( thumb.container ).css( 'visibility', 'visible' ); + self.trigger({ + type: Galleria.THUMBNAIL, + thumbTarget: thumb.image, + index: thumb.data.order, + galleriaData: self.getData( thumb.data.order ) + }); + + if ( typeof callback == 'function' ) { + callback.call( self, thumb ); + } + }, + + onThumbLoad = function( thumb, callback ) { + + // scale when ready + thumb.scale({ + width: thumb.data.width, + height: thumb.data.height, + crop: o.thumbCrop, + margin: o.thumbMargin, + canvas: o.useCanvas, + position: o.thumbPosition, + complete: function( thumb ) { + + // shrink thumbnails to fit + var top = ['left', 'top'], + arr = ['Width', 'Height'], + m, + css, + data = self.getData( thumb.index ); + + // calculate shrinked positions + $.each(arr, function( i, measure ) { + m = measure.toLowerCase(); + if ( (o.thumbCrop !== true || o.thumbCrop === m ) ) { + css = {}; + css[ m ] = thumb[ m ]; + $( thumb.container ).css( css ); + css = {}; + css[ top[ i ] ] = 0; + $( thumb.image ).css( css ); + } + + // cache outer measures + thumb[ 'outer' + measure ] = $( thumb.container )[ 'outer' + measure ]( true ); + }); + + // set high quality if downscale is moderate + Utils.toggleQuality( thumb.image, + o.thumbQuality === true || + ( o.thumbQuality === 'auto' && thumb.original.width < thumb.width * 3 ) + ); + + if ( o.thumbDisplayOrder && !thumb.lazy ) { + + $.each( thumbchunk, function( i, th ) { + if ( i === loadindex && th.ready && !th.displayed ) { + + loadindex++; + th.displayed = true; + + thumbComplete( th, callback ); + + return; + } + }); + } else { + thumbComplete( thumb, callback ); + } + } + }); + }; + + if ( !push ) { + this._thumbnails = []; + this.$( 'thumbnails' ).empty(); + } + + // loop through data and create thumbnails + for( ; this._data[ i ]; i++ ) { + + data = this._data[ i ]; + + // get source from thumb or image + src = data.thumb || data.image; + + if ( ( o.thumbnails === true || optval == 'lazy' ) && ( data.thumb || data.image ) ) { + + // add a new Picture instance + thumb = new Galleria.Picture(i); + + // save the index + thumb.index = i; + + // flag displayed + thumb.displayed = false; + + // flag lazy + thumb.lazy = false; + + // flag video + thumb.video = false; + + // append the thumbnail + this.$( 'thumbnails' ).append( thumb.container ); + + // cache the container + $container = $( thumb.container ); + + // hide it + $container.css( 'visibility', 'hidden' ); + + thumb.data = { + width : Utils.parseValue( getStyle( 'width' ) ), + height : Utils.parseValue( getStyle( 'height' ) ), + order : i, + src : src + }; + + // grab & reset size for smoother thumbnail loads + if ( o.thumbCrop !== true ) { + $container.css( { width: 'auto', height: 'auto' } ); + } else { + $container.css( { width: thumb.data.width, height: thumb.data.height } ); + } + + // load the thumbnail + if ( optval == 'lazy' ) { + + $container.addClass( 'lazy' ); + + thumb.lazy = true; + + thumb.load( gif, { + height: thumb.data.height, + width: thumb.data.width + }); + + } else { + thumb.load( src, onThumbLoad ); + } + + // preload all images here + if ( o.preload === 'all' ) { + thumb.preload( data.image ); + } + + // create empty spans if thumbnails is set to 'empty' + } else if ( ( data.iframe && optval !== null ) || optval === 'empty' || optval === 'numbers' ) { + thumb = { + container: Utils.create( 'galleria-image' ), + image: Utils.create( 'img', 'span' ), + ready: true, + data: { + order: i + } + }; + + // create numbered thumbnails + if ( optval === 'numbers' ) { + $( thumb.image ).text( i + 1 ); + } + + if ( data.iframe ) { + $( thumb.image ).addClass( 'iframe' ); + } + + this.$( 'thumbnails' ).append( thumb.container ); + + // we need to "fake" a loading delay before we append and trigger + // 50+ should be enough + + window.setTimeout( ( fake )( thumb.image, i, thumb.container ), 50 + ( i*20 ) ); + + // create null object to silent errors + } else { + thumb = { + container: null, + image: null + }; + } + + // add events for thumbnails + // you can control the event type using thumb_event_type + // we'll add the same event to the source if it's kept + + $( thumb.container ).add( o.keepSource && o.linkSourceImages ? data.original : null ) + .data('index', i).on( o.thumbEventType, onThumbEvent ) + .data('thumbload', onThumbLoad); + + if (active === src) { + $( thumb.container ).addClass( 'active' ); + } + + this._thumbnails.push( thumb ); + } + + thumbchunk = this._thumbnails.slice( chunk ); + + return this; + }, + + /** + Lazy-loads thumbnails. + You can call this method to load lazy thumbnails at run time + + @param {Array|Number} index Index or array of indexes of thumbnails to be loaded + @param {Function} complete Callback that is called when all lazy thumbnails have been loaded + + @returns Instance + */ + + lazyLoad: function( index, complete ) { + + var arr = index.constructor == Array ? index : [ index ], + self = this, + loaded = 0; + + $.each( arr, function(i, ind) { + + if ( ind > self._thumbnails.length - 1 ) { + return; + } + + var thumb = self._thumbnails[ ind ], + data = thumb.data, + callback = function() { + if ( ++loaded == arr.length && typeof complete == 'function' ) { + complete.call( self ); + } + }, + thumbload = $( thumb.container ).data( 'thumbload' ); + if ( thumb.video ) { + thumbload.call( self, thumb, callback ); + } else { + thumb.load( data.src , function( thumb ) { + thumbload.call( self, thumb, callback ); + }); + } + }); + + return this; + + }, + + /** + Lazy-loads thumbnails in chunks. + This method automatcally chops up the loading process of many thumbnails into chunks + + @param {Number} size Size of each chunk to be loaded + @param {Number} [delay] Delay between each loads + + @returns Instance + */ + + lazyLoadChunks: function( size, delay ) { + + var len = this.getDataLength(), + i = 0, + n = 0, + arr = [], + temp = [], + self = this; + + delay = delay || 0; + + for( ; i<len; i++ ) { + temp.push(i); + if ( ++n == size || i == len-1 ) { + arr.push( temp ); + n = 0; + temp = []; + } + } + + var init = function( wait ) { + var a = arr.shift(); + if ( a ) { + window.setTimeout(function() { + self.lazyLoad(a, function() { + init( true ); + }); + }, ( delay && wait ) ? delay : 0 ); + } + }; + + init( false ); + + return this; + + }, + + // the internal _run method should be called after loading data into galleria + // makes sure the gallery has proper measurements before postrun & ready + _run : function() { + + var self = this; + + self._createThumbnails(); + + // make sure we have a stageHeight && stageWidth + + Utils.wait({ + + timeout: 10000, + + until: function() { + + // Opera crap + if ( Galleria.OPERA ) { + self.$( 'stage' ).css( 'display', 'inline-block' ); + } + + self._stageWidth = self.$( 'stage' ).width(); + self._stageHeight = self.$( 'stage' ).height(); + + return( self._stageWidth && + self._stageHeight > 50 ); // what is an acceptable height? + }, + + success: function() { + + // save the instance + _galleries.push( self ); + + // postrun some stuff after the gallery is ready + + // create the touch slider + if ( self._options.swipe ) { + + var $images = self.$( 'images' ).width( self.getDataLength() * self._stageWidth ); + $.each( new Array( self.getDataLength() ), function(i) { + + var image = new Galleria.Picture(), + data = self.getData(i); + + $( image.container ).css({ + position: 'absolute', + top: 0, + left: self._stageWidth*i + }).prepend( self._layers[i] = $( Utils.create('galleria-layer') ).css({ + position: 'absolute', + top:0, left:0, right:0, bottom:0, + zIndex:2 + })[0] ).appendTo( $images ); + + if( data.video ) { + _playIcon( image.container ); + } + + self._controls.slides.push(image); + + var frame = new Galleria.Picture(); + frame.isIframe = true; + + $( frame.container ).attr('class', 'galleria-frame').css({ + position: 'absolute', + top: 0, + left: 0, + zIndex: 4, + background: '#000', + display: 'none' + }).appendTo( image.container ); + + self._controls.frames.push(frame); + }); + + self.finger.setup(); + } + + // show counter + Utils.show( self.get('counter') ); + + // bind carousel nav + if ( self._options.carousel ) { + self._carousel.bindControls(); + } + + // start autoplay + if ( self._options.autoplay ) { + + self.pause(); + + if ( typeof self._options.autoplay === 'number' ) { + self._playtime = self._options.autoplay; + } + + self._playing = true; + } + // if second load, just do the show and return + if ( self._firstrun ) { + + if ( self._options.autoplay ) { + self.trigger( Galleria.PLAY ); + } + + if ( typeof self._options.show === 'number' ) { + self.show( self._options.show ); + } + return; + } + + self._firstrun = true; + + // initialize the History plugin + if ( Galleria.History ) { + + // bind the show method + Galleria.History.change(function( value ) { + + // if ID is NaN, the user pressed back from the first image + // return to previous address + if ( isNaN( value ) ) { + window.history.go(-1); + + // else show the image + } else { + self.show( value, undef, true ); + } + }); + } + + self.trigger( Galleria.READY ); + + // call the theme init method + self.theme.init.call( self, self._options ); + + // Trigger Galleria.ready + $.each( Galleria.ready.callbacks, function(i ,fn) { + if ( typeof fn == 'function' ) { + fn.call( self, self._options ); + } + }); + + // call the extend option + self._options.extend.call( self, self._options ); + + // show the initial image + // first test for permalinks in history + if ( /^[0-9]{1,4}$/.test( HASH ) && Galleria.History ) { + self.show( HASH, undef, true ); + + } else if( self._data[ self._options.show ] ) { + self.show( self._options.show ); + } + + // play trigger + if ( self._options.autoplay ) { + self.trigger( Galleria.PLAY ); + } + }, + + error: function() { + Galleria.raise('Stage width or height is too small to show the gallery. Traced measures: width:' + self._stageWidth + 'px, height: ' + self._stageHeight + 'px.', true); + } + + }); + }, + + /** + Loads data into the gallery. + You can call this method on an existing gallery to reload the gallery with new data. + + @param {Array|string} [source] Optional JSON array of data or selector of where to find data in the document. + Defaults to the Galleria target or dataSource option. + + @param {string} [selector] Optional element selector of what elements to parse. + Defaults to 'img'. + + @param {Function} [config] Optional function to modify the data extraction proceedure from the selector. + See the dataConfig option for more information. + + @returns Instance + */ + + load : function( source, selector, config ) { + + var self = this, + o = this._options; + + // empty the data array + this._data = []; + + // empty the thumbnails + this._thumbnails = []; + this.$('thumbnails').empty(); + + // shorten the arguments + if ( typeof selector === 'function' ) { + config = selector; + selector = null; + } + + // use the source set by target + source = source || o.dataSource; + + // use selector set by option + selector = selector || o.dataSelector; + + // use the dataConfig set by option + config = config || o.dataConfig; + + // if source is a true object, make it into an array + if( $.isPlainObject( source ) ) { + source = [source]; + } + + // check if the data is an array already + if ( $.isArray( source ) ) { + if ( this.validate( source ) ) { + this._data = source; + } else { + Galleria.raise( 'Load failed: JSON Array not valid.' ); + } + } else { + + // add .video and .iframe to the selector (1.2.7) + selector += ',.video,.iframe'; + + // loop through images and set data + $( source ).find( selector ).each( function( i, elem ) { + + elem = $( elem ); + var data = {}, + parent = elem.parent(), + href = parent.attr( 'href' ), + rel = parent.attr( 'rel' ); + + if( href && ( elem[0].nodeName == 'IMG' || elem.hasClass('video') ) && _videoTest( href ) ) { + data.video = href; + } else if( href && elem.hasClass('iframe') ) { + data.iframe = href; + } else { + data.image = data.big = href; + } + + if ( rel ) { + data.big = rel; + } + + // alternative extraction from HTML5 data attribute, added in 1.2.7 + $.each( 'big title description link layer image'.split(' '), function( i, val ) { + if ( elem.data(val) ) { + data[ val ] = elem.data(val).toString(); + } + }); + + if ( !data.big ) { + data.big = data.image; + } + + // mix default extractions with the hrefs and config + // and push it into the data array + self._data.push( $.extend({ + + title: elem.attr('title') || '', + thumb: elem.attr('src'), + image: elem.attr('src'), + big: elem.attr('src'), + description: elem.attr('alt') || '', + link: elem.attr('longdesc'), + original: elem.get(0) // saved as a reference + + }, data, config( elem ) ) ); + + }); + } + + if ( typeof o.dataSort == 'function' ) { + protoArray.sort.call( this._data, o.dataSort ); + } else if ( o.dataSort == 'random' ) { + this._data.sort( function() { + return M.round(M.random())-0.5; + }); + } + + // trigger the DATA event and return + if ( this.getDataLength() ) { + this._parseData( function() { + this.trigger( Galleria.DATA ); + } ); + } + return this; + + }, + + // make sure the data works properly + _parseData : function( callback ) { + + var self = this, + current, + ready = false, + onload = function() { + var complete = true; + $.each( self._data, function( i, data ) { + if ( data.loading ) { + complete = false; + return false; + } + }); + if ( complete && !ready ) { + ready = true; + callback.call( self ); + } + }; + + $.each( this._data, function( i, data ) { + + current = self._data[ i ]; + + // copy image as thumb if no thumb exists + if ( 'thumb' in data === false ) { + current.thumb = data.image; + } + // copy image as big image if no biggie exists + if ( !data.big ) { + current.big = data.image; + } + // parse video + if ( 'video' in data ) { + var result = _videoTest( data.video ); + + if ( result ) { + current.iframe = new Video(result.provider, result.id ).embed() + (function() { + + // add options + if ( typeof self._options[ result.provider ] == 'object' ) { + var str = '?', arr = []; + $.each( self._options[ result.provider ], function( key, val ) { + arr.push( key + '=' + val ); + }); + + // small youtube specifics, perhaps move to _video later + if ( result.provider == 'youtube' ) { + arr = ['wmode=opaque'].concat(arr); + } + return str + arr.join('&'); + } + return ''; + }()); + + // pre-fetch video providers media + + if( !current.thumb || !current.image ) { + $.each( ['thumb', 'image'], function( i, type ) { + if ( type == 'image' && !self._options.videoPoster ) { + current.image = undef; + return; + } + var video = new Video( result.provider, result.id ); + if ( !current[ type ] ) { + current.loading = true; + video.getMedia( type, (function(current, type) { + return function(src) { + current[ type ] = src; + if ( type == 'image' && !current.big ) { + current.big = current.image; + } + delete current.loading; + onload(); + }; + }( current, type ))); + } + }); + } + } + } + }); + + onload(); + + return this; + }, + + /** + Destroy the Galleria instance and recover the original content + + @example this.destroy(); + + @returns Instance + */ + + destroy : function() { + this.$( 'target' ).data( 'galleria', null ); + this.$( 'container' ).off( 'galleria' ); + this.get( 'target' ).innerHTML = this._original.html; + this.clearTimer(); + Utils.removeFromArray( _instances, this ); + Utils.removeFromArray( _galleries, this ); + if ( Galleria._waiters.length ) { + $.each( Galleria._waiters, function( i, w ) { + if ( w ) window.clearTimeout( w ); + }); + } + return this; + }, + + /** + Adds and/or removes images from the gallery + Works just like Array.splice + https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice + + @example this.splice( 2, 4 ); // removes 4 images after the second image + + @returns Instance + */ + + splice : function() { + var self = this, + args = Utils.array( arguments ); + window.setTimeout(function() { + protoArray.splice.apply( self._data, args ); + self._parseData( function() { + self._createThumbnails(); + }); + },2); + return self; + }, + + /** + Append images to the gallery + Works just like Array.push + https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push + + @example this.push({ image: 'image1.jpg' }); // appends the image to the gallery + + @returns Instance + */ + + push : function() { + var self = this, + args = Utils.array( arguments ); + + if ( args.length == 1 && args[0].constructor == Array ) { + args = args[0]; + } + + window.setTimeout(function() { + protoArray.push.apply( self._data, args ); + self._parseData( function() { + self._createThumbnails( args ); + }); + }, 2); + return self; + }, + + _getActive : function() { + return this._controls.getActive(); + }, + + validate : function( data ) { + // todo: validate a custom data array + return true; + }, + + /** + Bind any event to Galleria + + @param {string} type The Event type to listen for + @param {Function} fn The function to execute when the event is triggered + + @example this.bind( 'image', function() { Galleria.log('image shown') }); + + @returns Instance + */ + + bind : function(type, fn) { + + // allow 'image' instead of Galleria.IMAGE + type = _patchEvent( type ); + + this.$( 'container' ).on( type, this.proxy(fn) ); + return this; + }, + + /** + Unbind any event to Galleria + + @param {string} type The Event type to forget + + @returns Instance + */ + + unbind : function(type) { + + type = _patchEvent( type ); + + this.$( 'container' ).off( type ); + return this; + }, + + /** + Manually trigger a Galleria event + + @param {string} type The Event to trigger + + @returns Instance + */ + + trigger : function( type ) { + + type = typeof type === 'object' ? + $.extend( type, { scope: this } ) : + { type: _patchEvent( type ), scope: this }; + + this.$( 'container' ).trigger( type ); + + return this; + }, + + /** + Assign an "idle state" to any element. + The idle state will be applied after a certain amount of idle time + Useful to hide f.ex navigation when the gallery is inactive + + @param {HTMLElement|string} elem The Dom node or selector to apply the idle state to + @param {Object} styles the CSS styles to apply when in idle mode + @param {Object} [from] the CSS styles to apply when in normal + @param {Boolean} [hide] set to true if you want to hide it first + + @example addIdleState( this.get('image-nav'), { opacity: 0 }); + @example addIdleState( '.galleria-image-nav', { top: -200 }, true); + + @returns Instance + */ + + addIdleState: function( elem, styles, from, hide ) { + this._idle.add.apply( this._idle, Utils.array( arguments ) ); + return this; + }, + + /** + Removes any idle state previously set using addIdleState() + + @param {HTMLElement|string} elem The Dom node or selector to remove the idle state from. + + @returns Instance + */ + + removeIdleState: function( elem ) { + this._idle.remove.apply( this._idle, Utils.array( arguments ) ); + return this; + }, + + /** + Force Galleria to enter idle mode. + + @returns Instance + */ + + enterIdleMode: function() { + this._idle.hide(); + return this; + }, + + /** + Force Galleria to exit idle mode. + + @returns Instance + */ + + exitIdleMode: function() { + this._idle.showAll(); + return this; + }, + + /** + Enter FullScreen mode + + @param {Function} callback the function to be executed when the fullscreen mode is fully applied. + + @returns Instance + */ + + enterFullscreen: function( callback ) { + this._fullscreen.enter.apply( this, Utils.array( arguments ) ); + return this; + }, + + /** + Exits FullScreen mode + + @param {Function} callback the function to be executed when the fullscreen mode is fully applied. + + @returns Instance + */ + + exitFullscreen: function( callback ) { + this._fullscreen.exit.apply( this, Utils.array( arguments ) ); + return this; + }, + + /** + Toggle FullScreen mode + + @param {Function} callback the function to be executed when the fullscreen mode is fully applied or removed. + + @returns Instance + */ + + toggleFullscreen: function( callback ) { + this._fullscreen[ this.isFullscreen() ? 'exit' : 'enter'].apply( this, Utils.array( arguments ) ); + return this; + }, + + /** + Adds a tooltip to any element. + You can also call this method with an object as argument with elemID:value pairs to apply tooltips to (see examples) + + @param {HTMLElement} elem The DOM Node to attach the event to + @param {string|Function} value The tooltip message. Can also be a function that returns a string. + + @example this.bindTooltip( this.get('thumbnails'), 'My thumbnails'); + @example this.bindTooltip( this.get('thumbnails'), function() { return 'My thumbs' }); + @example this.bindTooltip( { image_nav: 'Navigation' }); + + @returns Instance + */ + + bindTooltip: function( elem, value ) { + this._tooltip.bind.apply( this._tooltip, Utils.array(arguments) ); + return this; + }, + + /** + Note: this method is deprecated. Use refreshTooltip() instead. + + Redefine a tooltip. + Use this if you want to re-apply a tooltip value to an already bound tooltip element. + + @param {HTMLElement} elem The DOM Node to attach the event to + @param {string|Function} value The tooltip message. Can also be a function that returns a string. + + @returns Instance + */ + + defineTooltip: function( elem, value ) { + this._tooltip.define.apply( this._tooltip, Utils.array(arguments) ); + return this; + }, + + /** + Refresh a tooltip value. + Use this if you want to change the tooltip value at runtime, f.ex if you have a play/pause toggle. + + @param {HTMLElement} elem The DOM Node that has a tooltip that should be refreshed + + @returns Instance + */ + + refreshTooltip: function( elem ) { + this._tooltip.show.apply( this._tooltip, Utils.array(arguments) ); + return this; + }, + + /** + Open a pre-designed lightbox with the currently active image. + You can control some visuals using gallery options. + + @returns Instance + */ + + openLightbox: function() { + this._lightbox.show.apply( this._lightbox, Utils.array( arguments ) ); + return this; + }, + + /** + Close the lightbox. + + @returns Instance + */ + + closeLightbox: function() { + this._lightbox.hide.apply( this._lightbox, Utils.array( arguments ) ); + return this; + }, + + /** + Check if a variation exists + + @returns {Boolean} If the variation has been applied + */ + + hasVariation: function( variation ) { + return $.inArray( variation, this._options.variation.split(/\s+/) ) > -1; + }, + + /** + Get the currently active image element. + + @returns {HTMLElement} The image element + */ + + getActiveImage: function() { + var active = this._getActive(); + return active ? active.image : undef; + }, + + /** + Get the currently active thumbnail element. + + @returns {HTMLElement} The thumbnail element + */ + + getActiveThumb: function() { + return this._thumbnails[ this._active ].image || undef; + }, + + /** + Get the mouse position relative to the gallery container + + @param e The mouse event + + @example + +var gallery = this; +$(document).mousemove(function(e) { + console.log( gallery.getMousePosition(e).x ); +}); + + @returns {Object} Object with x & y of the relative mouse postion + */ + + getMousePosition : function(e) { + return { + x: e.pageX - this.$( 'container' ).offset().left, + y: e.pageY - this.$( 'container' ).offset().top + }; + }, + + /** + Adds a panning effect to the image + + @param [img] The optional image element. If not specified it takes the currently active image + + @returns Instance + */ + + addPan : function( img ) { + + if ( this._options.imageCrop === false ) { + return; + } + + img = $( img || this.getActiveImage() ); + + // define some variables and methods + var self = this, + x = img.width() / 2, + y = img.height() / 2, + destX = parseInt( img.css( 'left' ), 10 ), + destY = parseInt( img.css( 'top' ), 10 ), + curX = destX || 0, + curY = destY || 0, + distX = 0, + distY = 0, + active = false, + ts = Utils.timestamp(), + cache = 0, + move = 0, + + // positions the image + position = function( dist, cur, pos ) { + if ( dist > 0 ) { + move = M.round( M.max( dist * -1, M.min( 0, cur ) ) ); + if ( cache !== move ) { + + cache = move; + + if ( IE === 8 ) { // scroll is faster for IE + img.parent()[ 'scroll' + pos ]( move * -1 ); + } else { + var css = {}; + css[ pos.toLowerCase() ] = move; + img.css(css); + } + } + } + }, + + // calculates mouse position after 50ms + calculate = function(e) { + if (Utils.timestamp() - ts < 50) { + return; + } + active = true; + x = self.getMousePosition(e).x; + y = self.getMousePosition(e).y; + }, + + // the main loop to check + loop = function(e) { + + if (!active) { + return; + } + + distX = img.width() - self._stageWidth; + distY = img.height() - self._stageHeight; + destX = x / self._stageWidth * distX * -1; + destY = y / self._stageHeight * distY * -1; + curX += ( destX - curX ) / self._options.imagePanSmoothness; + curY += ( destY - curY ) / self._options.imagePanSmoothness; + + position( distY, curY, 'Top' ); + position( distX, curX, 'Left' ); + + }; + + // we need to use scroll in IE8 to speed things up + if ( IE === 8 ) { + + img.parent().scrollTop( curY * -1 ).scrollLeft( curX * -1 ); + img.css({ + top: 0, + left: 0 + }); + + } + + // unbind and bind event + this.$( 'stage' ).off( 'mousemove', calculate ).on( 'mousemove', calculate ); + + // loop the loop + this.addTimer( 'pan' + self._id, loop, 50, true); + + return this; + }, + + /** + Brings the scope into any callback + + @param fn The callback to bring the scope into + @param [scope] Optional scope to bring + + @example $('#fullscreen').click( this.proxy(function() { this.enterFullscreen(); }) ) + + @returns {Function} Return the callback with the gallery scope + */ + + proxy : function( fn, scope ) { + if ( typeof fn !== 'function' ) { + return F; + } + scope = scope || this; + return function() { + return fn.apply( scope, Utils.array( arguments ) ); + }; + }, + + /** + Tells you the theme name of the gallery + + @returns {String} theme name + */ + + getThemeName : function() { + return this.theme.name; + }, + + /** + Removes the panning effect set by addPan() + + @returns Instance + */ + + removePan: function() { + + // todo: doublecheck IE8 + + this.$( 'stage' ).off( 'mousemove' ); + + this.clearTimer( 'pan' + this._id ); + + return this; + }, + + /** + Adds an element to the Galleria DOM array. + When you add an element here, you can access it using element ID in many API calls + + @param {string} id The element ID you wish to use. You can add many elements by adding more arguments. + + @example addElement('mybutton'); + @example addElement('mybutton','mylink'); + + @returns Instance + */ + + addElement : function( id ) { + + var dom = this._dom; + + $.each( Utils.array(arguments), function( i, blueprint ) { + dom[ blueprint ] = Utils.create( 'galleria-' + blueprint ); + }); + + return this; + }, + + /** + Attach keyboard events to Galleria + + @param {Object} map The map object of events. + Possible keys are 'UP', 'DOWN', 'LEFT', 'RIGHT', 'RETURN', 'ESCAPE', 'BACKSPACE', and 'SPACE'. + + @example + +this.attachKeyboard({ + right: this.next, + left: this.prev, + up: function() { + console.log( 'up key pressed' ) + } +}); + + @returns Instance + */ + + attachKeyboard : function( map ) { + this._keyboard.attach.apply( this._keyboard, Utils.array( arguments ) ); + return this; + }, + + /** + Detach all keyboard events to Galleria + + @returns Instance + */ + + detachKeyboard : function() { + this._keyboard.detach.apply( this._keyboard, Utils.array( arguments ) ); + return this; + }, + + /** + Fast helper for appending galleria elements that you added using addElement() + + @param {string} parentID The parent element ID where the element will be appended + @param {string} childID the element ID that should be appended + + @example this.addElement('myElement'); + this.appendChild( 'info', 'myElement' ); + + @returns Instance + */ + + appendChild : function( parentID, childID ) { + this.$( parentID ).append( this.get( childID ) || childID ); + return this; + }, + + /** + Fast helper for prepending galleria elements that you added using addElement() + + @param {string} parentID The parent element ID where the element will be prepended + @param {string} childID the element ID that should be prepended + + @example + +this.addElement('myElement'); +this.prependChild( 'info', 'myElement' ); + + @returns Instance + */ + + prependChild : function( parentID, childID ) { + this.$( parentID ).prepend( this.get( childID ) || childID ); + return this; + }, + + /** + Remove an element by blueprint + + @param {string} elemID The element to be removed. + You can remove multiple elements by adding arguments. + + @returns Instance + */ + + remove : function( elemID ) { + this.$( Utils.array( arguments ).join(',') ).remove(); + return this; + }, + + // a fast helper for building dom structures + // leave this out of the API for now + + append : function( data ) { + var i, j; + for( i in data ) { + if ( data.hasOwnProperty( i ) ) { + if ( data[i].constructor === Array ) { + for( j = 0; data[i][j]; j++ ) { + this.appendChild( i, data[i][j] ); + } + } else { + this.appendChild( i, data[i] ); + } + } + } + return this; + }, + + // an internal helper for scaling according to options + _scaleImage : function( image, options ) { + + image = image || this._controls.getActive(); + + // janpub (JH) fix: + // image might be unselected yet + // e.g. when external logics rescales the gallery on window resize events + if( !image ) { + return; + } + + var complete, + + scaleLayer = function( img ) { + $( img.container ).children(':first').css({ + top: M.max(0, Utils.parseValue( img.image.style.top )), + left: M.max(0, Utils.parseValue( img.image.style.left )), + width: Utils.parseValue( img.image.width ), + height: Utils.parseValue( img.image.height ) + }); + }; + + options = $.extend({ + width: this._stageWidth, + height: this._stageHeight, + crop: this._options.imageCrop, + max: this._options.maxScaleRatio, + min: this._options.minScaleRatio, + margin: this._options.imageMargin, + position: this._options.imagePosition, + iframelimit: this._options.maxVideoSize + }, options ); + + if ( this._options.layerFollow && this._options.imageCrop !== true ) { + + if ( typeof options.complete == 'function' ) { + complete = options.complete; + options.complete = function() { + complete.call( image, image ); + scaleLayer( image ); + }; + } else { + options.complete = scaleLayer; + } + + } else { + $( image.container ).children(':first').css({ top: 0, left: 0 }); + } + + image.scale( options ); + return this; + }, + + /** + Updates the carousel, + useful if you resize the gallery and want to re-check if the carousel nav is needed. + + @returns Instance + */ + + updateCarousel : function() { + this._carousel.update(); + return this; + }, + + /** + Resize the entire gallery container + + @param {Object} [measures] Optional object with width/height specified + @param {Function} [complete] The callback to be called when the scaling is complete + + @returns Instance + */ + + resize : function( measures, complete ) { + + if ( typeof measures == 'function' ) { + complete = measures; + measures = undef; + } + + measures = $.extend( { width:0, height:0 }, measures ); + + var self = this, + $container = this.$( 'container' ); + + $.each( measures, function( m, val ) { + if ( !val ) { + $container[ m ]( 'auto' ); + measures[ m ] = self._getWH()[ m ]; + } + }); + + $.each( measures, function( m, val ) { + $container[ m ]( val ); + }); + + return this.rescale( complete ); + + }, + + /** + Rescales the gallery + + @param {number} width The target width + @param {number} height The target height + @param {Function} complete The callback to be called when the scaling is complete + + @returns Instance + */ + + rescale : function( width, height, complete ) { + + var self = this; + + // allow rescale(fn) + if ( typeof width === 'function' ) { + complete = width; + width = undef; + } + + var scale = function() { + + // set stagewidth + self._stageWidth = width || self.$( 'stage' ).width(); + self._stageHeight = height || self.$( 'stage' ).height(); + + if ( self._options.swipe ) { + $.each( self._controls.slides, function(i, img) { + self._scaleImage( img ); + $( img.container ).css('left', self._stageWidth * i); + }); + self.$('images').css('width', self._stageWidth * self.getDataLength()); + } else { + // scale the active image + self._scaleImage(); + } + + if ( self._options.carousel ) { + self.updateCarousel(); + } + + var frame = self._controls.frames[ self._controls.active ]; + + if (frame) { + self._controls.frames[ self._controls.active ].scale({ + width: self._stageWidth, + height: self._stageHeight, + iframelimit: self._options.maxVideoSize + }); + } + + self.trigger( Galleria.RESCALE ); + + if ( typeof complete === 'function' ) { + complete.call( self ); + } + }; + + scale.call( self ); + + return this; + }, + + /** + Refreshes the gallery. + Useful if you change image options at runtime and want to apply the changes to the active image. + + @returns Instance + */ + + refreshImage : function() { + this._scaleImage(); + if ( this._options.imagePan ) { + this.addPan(); + } + return this; + }, + + _preload: function() { + if ( this._options.preload ) { + var p, i, + n = this.getNext(), + ndata; + try { + for ( i = this._options.preload; i > 0; i-- ) { + p = new Galleria.Picture(); + ndata = this.getData( n ); + p.preload( this.isFullscreen() && ndata.big ? ndata.big : ndata.image ); + n = this.getNext( n ); + } + } catch(e) {} + } + }, + + /** + Shows an image by index + + @param {number|boolean} index The index to show + @param {Boolean} rewind A boolean that should be true if you want the transition to go back + + @returns Instance + */ + + show : function( index, rewind, _history ) { + + var swipe = this._options.swipe; + + // do nothing queue is long || index is false || queue is false and transition is in progress + if ( !swipe && + ( this._queue.length > 3 || index === false || ( !this._options.queue && this._queue.stalled ) ) ) { + return; + } + + index = M.max( 0, M.min( parseInt( index, 10 ), this.getDataLength() - 1 ) ); + + rewind = typeof rewind !== 'undefined' ? !!rewind : index < this.getIndex(); + + _history = _history || false; + + // do the history thing and return + if ( !_history && Galleria.History ) { + Galleria.History.set( index.toString() ); + return; + } + + if ( this.finger && index !== this._active ) { + this.finger.to = -( index*this.finger.width ); + this.finger.index = index; + } + this._active = index; + + // we do things a bit simpler in swipe: + if ( swipe ) { + + var data = this.getData(index), + self = this; + if ( !data ) { + return; + } + + var src = this.isFullscreen() && data.big ? data.big : ( data.image || data.iframe ), + image = this._controls.slides[index], + cached = image.isCached( src ), + thumb = this._thumbnails[ index ]; + + var evObj = { + cached: cached, + index: index, + rewind: rewind, + imageTarget: image.image, + thumbTarget: thumb.image, + galleriaData: data + }; + + this.trigger($.extend(evObj, { + type: Galleria.LOADSTART + })); + + self.$('container').removeClass( 'videoplay' ); + + var complete = function() { + + self._layers[index].innerHTML = self.getData().layer || ''; + + self.trigger($.extend(evObj, { + type: Galleria.LOADFINISH + })); + self._playCheck(); + }; + + self._preload(); + + window.setTimeout(function() { + + // load if not ready + if ( !image.ready || $(image.image).attr('src') != src ) { + if ( data.iframe && !data.image ) { + image.isIframe = true; + } + image.load(src, function(image) { + evObj.imageTarget = image.image; + self._scaleImage(image, complete).trigger($.extend(evObj, { + type: Galleria.IMAGE + })); + complete(); + }); + } else { + self.trigger($.extend(evObj, { + type: Galleria.IMAGE + })); + complete(); + } + }, 100); + + } else { + protoArray.push.call( this._queue, { + index : index, + rewind : rewind + }); + if ( !this._queue.stalled ) { + this._show(); + } + } + + return this; + }, + + // the internal _show method does the actual showing + _show : function() { + + // shortcuts + var self = this, + queue = this._queue[ 0 ], + data = this.getData( queue.index ); + + if ( !data ) { + return; + } + + var src = this.isFullscreen() && data.big ? data.big : ( data.image || data.iframe ), + active = this._controls.getActive(), + next = this._controls.getNext(), + cached = next.isCached( src ), + thumb = this._thumbnails[ queue.index ], + mousetrigger = function() { + $( next.image ).trigger( 'mouseup' ); + }; + + self.$('container').toggleClass('iframe', !!data.isIframe).removeClass( 'videoplay' ); + + // to be fired when loading & transition is complete: + var complete = (function( data, next, active, queue, thumb ) { + + return function() { + + var win; + + _transitions.active = false; + + // optimize quality + Utils.toggleQuality( next.image, self._options.imageQuality ); + + // remove old layer + self._layers[ self._controls.active ].innerHTML = ''; + + // swap + $( active.container ).css({ + zIndex: 0, + opacity: 0 + }).show(); + + $( active.container ).find( 'iframe, .galleria-videoicon' ).remove(); + $( self._controls.frames[ self._controls.active ].container ).hide(); + + $( next.container ).css({ + zIndex: 1, + left: 0, + top: 0 + }).show(); + + self._controls.swap(); + + // add pan according to option + if ( self._options.imagePan ) { + self.addPan( next.image ); + } + + // make the image clickable + // order of precedence: iframe, link, lightbox, clicknext + if ( ( data.iframe && data.image ) || data.link || self._options.lightbox || self._options.clicknext ) { + + $( next.image ).css({ + cursor: 'pointer' + }).on( 'mouseup', function( e ) { + + // non-left click + if ( typeof e.which == 'number' && e.which > 1 ) { + return; + } + + // iframe / video + if ( data.iframe ) { + + if ( self.isPlaying() ) { + self.pause(); + } + var frame = self._controls.frames[ self._controls.active ], + w = self._stageWidth, + h = self._stageHeight; + + $( frame.container ).css({ + width: w, + height: h, + opacity: 0 + }).show().animate({ + opacity: 1 + }, 200); + + window.setTimeout(function() { + frame.load( data.iframe + ( data.video ? '&autoplay=1' : '' ), { + width: w, + height: h + }, function( frame ) { + self.$( 'container' ).addClass( 'videoplay' ); + frame.scale({ + width: self._stageWidth, + height: self._stageHeight, + iframelimit: data.video ? self._options.maxVideoSize : undef + }); + }); + }, 100); + + return; + } + + // clicknext + if ( self._options.clicknext && !Galleria.TOUCH ) { + if ( self._options.pauseOnInteraction ) { + self.pause(); + } + self.next(); + return; + } + + // popup link + if ( data.link ) { + if ( self._options.popupLinks ) { + win = window.open( data.link, '_blank' ); + } else { + window.location.href = data.link; + } + return; + } + + if ( self._options.lightbox ) { + self.openLightbox(); + } + + }); + } + + // check if we are playing + self._playCheck(); + + // trigger IMAGE event + self.trigger({ + type: Galleria.IMAGE, + index: queue.index, + imageTarget: next.image, + thumbTarget: thumb.image, + galleriaData: data + }); + + // remove the queued image + protoArray.shift.call( self._queue ); + + // remove stalled + self._queue.stalled = false; + + // if we still have images in the queue, show it + if ( self._queue.length ) { + self._show(); + } + + }; + }( data, next, active, queue, thumb )); + + // let the carousel follow + if ( this._options.carousel && this._options.carouselFollow ) { + this._carousel.follow( queue.index ); + } + + // preload images + self._preload(); + + // show the next image, just in case + Utils.show( next.container ); + + next.isIframe = data.iframe && !data.image; + + // add active classes + $( self._thumbnails[ queue.index ].container ) + .addClass( 'active' ) + .siblings( '.active' ) + .removeClass( 'active' ); + + // trigger the LOADSTART event + self.trigger( { + type: Galleria.LOADSTART, + cached: cached, + index: queue.index, + rewind: queue.rewind, + imageTarget: next.image, + thumbTarget: thumb.image, + galleriaData: data + }); + + // stall the queue + self._queue.stalled = true; + + // begin loading the next image + next.load( src, function( next ) { + + // add layer HTML + var layer = $( self._layers[ 1-self._controls.active ] ).html( data.layer || '' ).hide(); + + self._scaleImage( next, { + + complete: function( next ) { + + // toggle low quality for IE + if ( 'image' in active ) { + Utils.toggleQuality( active.image, false ); + } + Utils.toggleQuality( next.image, false ); + + // remove the image panning, if applied + // TODO: rethink if this is necessary + self.removePan(); + + // set the captions and counter + self.setInfo( queue.index ); + self.setCounter( queue.index ); + + // show the layer now + if ( data.layer ) { + layer.show(); + // inherit click events set on image + if ( ( data.iframe && data.image ) || data.link || self._options.lightbox || self._options.clicknext ) { + layer.css( 'cursor', 'pointer' ).off( 'mouseup' ).mouseup( mousetrigger ); + } + } + + // add play icon + if( data.video && data.image ) { + _playIcon( next.container ); + } + + var transition = self._options.transition; + + // can JavaScript loop through objects in order? yes. + $.each({ + initial: active.image === null, + touch: Galleria.TOUCH, + fullscreen: self.isFullscreen() + }, function( type, arg ) { + if ( arg && self._options[ type + 'Transition' ] !== undef ) { + transition = self._options[ type + 'Transition' ]; + return false; + } + }); + + // validate the transition + if ( transition in _transitions.effects === false ) { + complete(); + } else { + var params = { + prev: active.container, + next: next.container, + rewind: queue.rewind, + speed: self._options.transitionSpeed || 400 + }; + + _transitions.active = true; + + // call the transition function and send some stuff + _transitions.init.call( self, transition, params, complete ); + + } + + // trigger the LOADFINISH event + self.trigger({ + type: Galleria.LOADFINISH, + cached: cached, + index: queue.index, + rewind: queue.rewind, + imageTarget: next.image, + thumbTarget: self._thumbnails[ queue.index ].image, + galleriaData: self.getData( queue.index ) + }); + } + }); + }); + }, + + /** + Gets the next index + + @param {number} [base] Optional starting point + + @returns {number} the next index, or the first if you are at the first (looping) + */ + + getNext : function( base ) { + base = typeof base === 'number' ? base : this.getIndex(); + return base === this.getDataLength() - 1 ? 0 : base + 1; + }, + + /** + Gets the previous index + + @param {number} [base] Optional starting point + + @returns {number} the previous index, or the last if you are at the first (looping) + */ + + getPrev : function( base ) { + base = typeof base === 'number' ? base : this.getIndex(); + return base === 0 ? this.getDataLength() - 1 : base - 1; + }, + + /** + Shows the next image in line + + @returns Instance + */ + + next : function() { + if ( this.getDataLength() > 1 ) { + this.show( this.getNext(), false ); + } + return this; + }, + + /** + Shows the previous image in line + + @returns Instance + */ + + prev : function() { + if ( this.getDataLength() > 1 ) { + this.show( this.getPrev(), true ); + } + return this; + }, + + /** + Retrieve a DOM element by element ID + + @param {string} elemId The delement ID to fetch + + @returns {HTMLElement} The elements DOM node or null if not found. + */ + + get : function( elemId ) { + return elemId in this._dom ? this._dom[ elemId ] : null; + }, + + /** + Retrieve a data object + + @param {number} index The data index to retrieve. + If no index specified it will take the currently active image + + @returns {Object} The data object + */ + + getData : function( index ) { + return index in this._data ? + this._data[ index ] : this._data[ this._active ]; + }, + + /** + Retrieve the number of data items + + @returns {number} The data length + */ + getDataLength : function() { + return this._data.length; + }, + + /** + Retrieve the currently active index + + @returns {number|boolean} The active index or false if none found + */ + + getIndex : function() { + return typeof this._active === 'number' ? this._active : false; + }, + + /** + Retrieve the stage height + + @returns {number} The stage height + */ + + getStageHeight : function() { + return this._stageHeight; + }, + + /** + Retrieve the stage width + + @returns {number} The stage width + */ + + getStageWidth : function() { + return this._stageWidth; + }, + + /** + Retrieve the option + + @param {string} key The option key to retrieve. If no key specified it will return all options in an object. + + @returns option or options + */ + + getOptions : function( key ) { + return typeof key === 'undefined' ? this._options : this._options[ key ]; + }, + + /** + Set options to the instance. + You can set options using a key & value argument or a single object argument (see examples) + + @param {string} key The option key + @param {string} value the the options value + + @example setOptions( 'autoplay', true ) + @example setOptions({ autoplay: true }); + + @returns Instance + */ + + setOptions : function( key, value ) { + if ( typeof key === 'object' ) { + $.extend( this._options, key ); + } else { + this._options[ key ] = value; + } + return this; + }, + + /** + Starts playing the slideshow + + @param {number} delay Sets the slideshow interval in milliseconds. + If you set it once, you can just call play() and get the same interval the next time. + + @returns Instance + */ + + play : function( delay ) { + + this._playing = true; + + this._playtime = delay || this._playtime; + + this._playCheck(); + + this.trigger( Galleria.PLAY ); + + return this; + }, + + /** + Stops the slideshow if currently playing + + @returns Instance + */ + + pause : function() { + + this._playing = false; + + this.trigger( Galleria.PAUSE ); + + return this; + }, + + /** + Toggle between play and pause events. + + @param {number} delay Sets the slideshow interval in milliseconds. + + @returns Instance + */ + + playToggle : function( delay ) { + return ( this._playing ) ? this.pause() : this.play( delay ); + }, + + /** + Checks if the gallery is currently playing + + @returns {Boolean} + */ + + isPlaying : function() { + return this._playing; + }, + + /** + Checks if the gallery is currently in fullscreen mode + + @returns {Boolean} + */ + + isFullscreen : function() { + return this._fullscreen.active; + }, + + _playCheck : function() { + var self = this, + played = 0, + interval = 20, + now = Utils.timestamp(), + timer_id = 'play' + this._id; + + if ( this._playing ) { + + this.clearTimer( timer_id ); + + var fn = function() { + + played = Utils.timestamp() - now; + if ( played >= self._playtime && self._playing ) { + self.clearTimer( timer_id ); + self.next(); + return; + } + if ( self._playing ) { + + // trigger the PROGRESS event + self.trigger({ + type: Galleria.PROGRESS, + percent: M.ceil( played / self._playtime * 100 ), + seconds: M.floor( played / 1000 ), + milliseconds: played + }); + + self.addTimer( timer_id, fn, interval ); + } + }; + self.addTimer( timer_id, fn, interval ); + } + }, + + /** + Modify the slideshow delay + + @param {number} delay the number of milliseconds between slides, + + @returns Instance + */ + + setPlaytime: function( delay ) { + this._playtime = delay; + return this; + }, + + setIndex: function( val ) { + this._active = val; + return this; + }, + + /** + Manually modify the counter + + @param {number} [index] Optional data index to fectch, + if no index found it assumes the currently active index + + @returns Instance + */ + + setCounter: function( index ) { + + if ( typeof index === 'number' ) { + index++; + } else if ( typeof index === 'undefined' ) { + index = this.getIndex()+1; + } + + this.get( 'current' ).innerHTML = index; + + if ( IE ) { // weird IE bug + + var count = this.$( 'counter' ), + opacity = count.css( 'opacity' ); + + if ( parseInt( opacity, 10 ) === 1) { + Utils.removeAlpha( count[0] ); + } else { + this.$( 'counter' ).css( 'opacity', opacity ); + } + + } + + return this; + }, + + /** + Manually set captions + + @param {number} [index] Optional data index to fectch and apply as caption, + if no index found it assumes the currently active index + + @returns Instance + */ + + setInfo : function( index ) { + + var self = this, + data = this.getData( index ); + + $.each( ['title','description'], function( i, type ) { + + var elem = self.$( 'info-' + type ); + + if ( !!data[type] ) { + elem[ data[ type ].length ? 'show' : 'hide' ]().html( data[ type ] ); + } else { + elem.empty().hide(); + } + }); + + return this; + }, + + /** + Checks if the data contains any captions + + @param {number} [index] Optional data index to fectch, + if no index found it assumes the currently active index. + + @returns {boolean} + */ + + hasInfo : function( index ) { + + var check = 'title description'.split(' '), + i; + + for ( i = 0; check[i]; i++ ) { + if ( !!this.getData( index )[ check[i] ] ) { + return true; + } + } + return false; + + }, + + jQuery : function( str ) { + + var self = this, + ret = []; + + $.each( str.split(','), function( i, elemId ) { + elemId = $.trim( elemId ); + + if ( self.get( elemId ) ) { + ret.push( elemId ); + } + }); + + var jQ = $( self.get( ret.shift() ) ); + + $.each( ret, function( i, elemId ) { + jQ = jQ.add( self.get( elemId ) ); + }); + + return jQ; + + }, + + /** + Converts element IDs into a jQuery collection + You can call for multiple IDs separated with commas. + + @param {string} str One or more element IDs (comma-separated) + + @returns jQuery + + @example this.$('info,container').hide(); + */ + + $ : function( str ) { + return this.jQuery.apply( this, Utils.array( arguments ) ); + } + +}; + +// End of Galleria prototype + +// Add events as static variables +$.each( _events, function( i, ev ) { + + // legacy events + var type = /_/.test( ev ) ? ev.replace( /_/g, '' ) : ev; + + Galleria[ ev.toUpperCase() ] = 'galleria.'+type; + +} ); + +$.extend( Galleria, { + + // Browser helpers + IE9: IE === 9, + IE8: IE === 8, + IE7: IE === 7, + IE6: IE === 6, + IE: IE, + WEBKIT: /webkit/.test( NAV ), + CHROME: /chrome/.test( NAV ), + SAFARI: /safari/.test( NAV ) && !(/chrome/.test( NAV )), + QUIRK: ( IE && doc.compatMode && doc.compatMode === "BackCompat" ), + MAC: /mac/.test( navigator.platform.toLowerCase() ), + OPERA: !!window.opera, + IPHONE: /iphone/.test( NAV ), + IPAD: /ipad/.test( NAV ), + ANDROID: /android/.test( NAV ), + TOUCH: ('ontouchstart' in doc) + +}); + +// Galleria static methods + +/** + Adds a theme that you can use for your Gallery + + @param {Object} theme Object that should contain all your theme settings. + <ul> + <li>name - name of the theme</li> + <li>author - name of the author</li> + <li>css - css file name (not path)</li> + <li>defaults - default options to apply, including theme-specific options</li> + <li>init - the init function</li> + </ul> + + @returns {Object} theme +*/ + +Galleria.addTheme = function( theme ) { + + // make sure we have a name + if ( !theme.name ) { + Galleria.raise('No theme name specified'); + } + + if ( typeof theme.defaults !== 'object' ) { + theme.defaults = {}; + } else { + theme.defaults = _legacyOptions( theme.defaults ); + } + + var css = false, + reg; + + if ( typeof theme.css === 'string' ) { + + // look for manually added CSS + $('link').each(function( i, link ) { + reg = new RegExp( theme.css ); + if ( reg.test( link.href ) ) { + + // we found the css + css = true; + + // the themeload trigger + _themeLoad( theme ); + + return false; + } + }); + + // else look for the absolute path and load the CSS dynamic + if ( !css ) { + + + $(function() { + // Try to determine the css-path from the theme script. + // In IE8/9, the script-dom-element seems to be not present + // at once, if galleria itself is inserted into the dom + // dynamically. We therefore try multiple times before raising + // an error. + var retryCount = 0; + var tryLoadCss = function() { + $('script').each(function (i, script) { + // look for the theme script + reg = new RegExp('galleria\\.' + theme.name.toLowerCase() + '\\.'); + if (reg.test(script.src)) { + + // we have a match + css = script.src.replace(/[^\/]*$/, '') + theme.css; + + window.setTimeout(function () { + Utils.loadCSS(css, 'galleria-theme-'+theme.name, function () { + + // run galleries with this theme + _themeLoad(theme); + + }); + }, 1); + } + }); + if (!css) { + if (retryCount++ > 5) { + Galleria.raise('No theme CSS loaded'); + } else { + window.setTimeout(tryLoadCss, 500); + } + } + }; + tryLoadCss(); + }); + } + + } else { + + // pass + _themeLoad( theme ); + } + return theme; +}; + +/** + loadTheme loads a theme js file and attaches a load event to Galleria + + @param {string} src The relative path to the theme source file + + @param {Object} [options] Optional options you want to apply + + @returns Galleria +*/ + +Galleria.loadTheme = function( src, options ) { + + // Don't load if theme is already loaded + if( $('script').filter(function() { return $(this).attr('src') == src; }).length ) { + return; + } + + var loaded = false, + err; + + // start listening for the timeout onload + $( window ).load( function() { + if ( !loaded ) { + // give it another 20 seconds + err = window.setTimeout(function() { + if ( !loaded ) { + Galleria.raise( "Galleria had problems loading theme at " + src + ". Please check theme path or load manually.", true ); + } + }, 20000); + } + }); + + // load the theme + Utils.loadScript( src, function() { + loaded = true; + window.clearTimeout( err ); + }); + + return Galleria; +}; + +/** + Retrieves a Galleria instance. + + @param {number} [index] Optional index to retrieve. + If no index is supplied, the method will return all instances in an array. + + @returns Instance or Array of instances +*/ + +Galleria.get = function( index ) { + if ( !!_instances[ index ] ) { + return _instances[ index ]; + } else if ( typeof index !== 'number' ) { + return _instances; + } else { + Galleria.raise('Gallery index ' + index + ' not found'); + } +}; + +/** + + Configure Galleria options via a static function. + The options will be applied to all instances + + @param {string|object} key The options to apply or a key + + @param [value] If key is a string, this is the value + + @returns Galleria + +*/ + +Galleria.configure = function( key, value ) { + + var opts = {}; + + if( typeof key == 'string' && value ) { + opts[key] = value; + key = opts; + } else { + $.extend( opts, key ); + } + + Galleria.configure.options = opts; + + $.each( Galleria.get(), function(i, instance) { + instance.setOptions( opts ); + }); + + return Galleria; +}; + +Galleria.configure.options = {}; + +/** + + Bind a Galleria event to the gallery + + @param {string} type A string representing the galleria event + + @param {function} callback The function that should run when the event is triggered + + @returns Galleria + +*/ + +Galleria.on = function( type, callback ) { + if ( !type ) { + return; + } + + callback = callback || F; + + // hash the bind + var hash = type + callback.toString().replace(/\s/g,'') + Utils.timestamp(); + + // for existing instances + $.each( Galleria.get(), function(i, instance) { + instance._binds.push( hash ); + instance.bind( type, callback ); + }); + + // for future instances + Galleria.on.binds.push({ + type: type, + callback: callback, + hash: hash + }); + + return Galleria; +}; + +Galleria.on.binds = []; + +/** + + Run Galleria + Alias for $(selector).galleria(options) + + @param {string} selector A selector of element(s) to intialize galleria to + + @param {object} options The options to apply + + @returns Galleria + +*/ + +Galleria.run = function( selector, options ) { + if ( $.isFunction( options ) ) { + options = { extend: options }; + } + $( selector || '#galleria' ).galleria( options ); + return Galleria; +}; + +/** + Creates a transition to be used in your gallery + + @param {string} name The name of the transition that you will use as an option + + @param {Function} fn The function to be executed in the transition. + The function contains two arguments, params and complete. + Use the params Object to integrate the transition, and then call complete when you are done. + + @returns Galleria + +*/ + +Galleria.addTransition = function( name, fn ) { + _transitions.effects[name] = fn; + return Galleria; +}; + +/** + The Galleria utilites +*/ + +Galleria.utils = Utils; + +/** + A helper metod for cross-browser logging. + It uses the console log if available otherwise it falls back to alert + + @example Galleria.log("hello", document.body, [1,2,3]); +*/ + +Galleria.log = function() { + var args = Utils.array( arguments ); + if( 'console' in window && 'log' in window.console ) { + try { + return window.console.log.apply( window.console, args ); + } catch( e ) { + $.each( args, function() { + window.console.log(this); + }); + } + } else { + return window.alert( args.join('<br>') ); + } +}; + +/** + A ready method for adding callbacks when a gallery is ready + Each method is call before the extend option for every instance + + @param {function} callback The function to call + + @returns Galleria +*/ + +Galleria.ready = function( fn ) { + if ( typeof fn != 'function' ) { + return Galleria; + } + $.each( _galleries, function( i, gallery ) { + fn.call( gallery, gallery._options ); + }); + Galleria.ready.callbacks.push( fn ); + return Galleria; +}; + +Galleria.ready.callbacks = []; + +/** + Method for raising errors + + @param {string} msg The message to throw + + @param {boolean} [fatal] Set this to true to override debug settings and display a fatal error +*/ + +Galleria.raise = function( msg, fatal ) { + + var type = fatal ? 'Fatal error' : 'Error', + + css = { + color: '#fff', + position: 'absolute', + top: 0, + left: 0, + zIndex: 100000 + }, + + echo = function( msg ) { + + var html = '<div style="padding:4px;margin:0 0 2px;background:#' + + ( fatal ? '811' : '222' ) + ';">' + + ( fatal ? '<strong>' + type + ': </strong>' : '' ) + + msg + '</div>'; + + $.each( _instances, function() { + + var cont = this.$( 'errors' ), + target = this.$( 'target' ); + + if ( !cont.length ) { + + target.css( 'position', 'relative' ); + + cont = this.addElement( 'errors' ).appendChild( 'target', 'errors' ).$( 'errors' ).css(css); + } + cont.append( html ); + + }); + + if ( !_instances.length ) { + $('<div>').css( $.extend( css, { position: 'fixed' } ) ).append( html ).appendTo( DOM().body ); + } + }; + + // if debug is on, display errors and throw exception if fatal + if ( DEBUG ) { + echo( msg ); + if ( fatal ) { + throw new Error(type + ': ' + msg); + } + + // else just echo a silent generic error if fatal + } else if ( fatal ) { + if ( _hasError ) { + return; + } + _hasError = true; + fatal = false; + echo( 'Gallery could not load.' ); + } +}; + +// Add the version +Galleria.version = VERSION; + +Galleria.getLoadedThemes = function() { + return $.map(_loadedThemes, function(theme) { + return theme.name; + }); +}; + +/** + A method for checking what version of Galleria the user has installed and throws a readable error if the user needs to upgrade. + Useful when building plugins that requires a certain version to function. + + @param {number} version The minimum version required + + @param {string} [msg] Optional message to display. If not specified, Galleria will throw a generic error. + + @returns Galleria +*/ + +Galleria.requires = function( version, msg ) { + msg = msg || 'You need to upgrade Galleria to version ' + version + ' to use one or more components.'; + if ( Galleria.version < version ) { + Galleria.raise(msg, true); + } + return Galleria; +}; + +/** + Adds preload, cache, scale and crop functionality + + @constructor + + @requires jQuery + + @param {number} [id] Optional id to keep track of instances +*/ + +Galleria.Picture = function( id ) { + + // save the id + this.id = id || null; + + // the image should be null until loaded + this.image = null; + + // Create a new container + this.container = Utils.create('galleria-image'); + + // add container styles + $( this.container ).css({ + overflow: 'hidden', + position: 'relative' // for IE Standards mode + }); + + // saves the original measurements + this.original = { + width: 0, + height: 0 + }; + + // flag when the image is ready + this.ready = false; + + // flag for iframe Picture + this.isIframe = false; + +}; + +Galleria.Picture.prototype = { + + // the inherited cache object + cache: {}, + + // show the image on stage + show: function() { + Utils.show( this.image ); + }, + + // hide the image + hide: function() { + Utils.moveOut( this.image ); + }, + + clear: function() { + this.image = null; + }, + + /** + Checks if an image is in cache + + @param {string} src The image source path, ex '/path/to/img.jpg' + + @returns {boolean} + */ + + isCached: function( src ) { + return !!this.cache[src]; + }, + + /** + Preloads an image into the cache + + @param {string} src The image source path, ex '/path/to/img.jpg' + + @returns Galleria.Picture + */ + + preload: function( src ) { + $( new Image() ).load((function(src, cache) { + return function() { + cache[ src ] = src; + }; + }( src, this.cache ))).attr( 'src', src ); + }, + + /** + Loads an image and call the callback when ready. + Will also add the image to cache. + + @param {string} src The image source path, ex '/path/to/img.jpg' + @param {Object} [size] The forced size of the image, defined as an object { width: xx, height:xx } + @param {Function} callback The function to be executed when the image is loaded & scaled + + @returns The image container (jQuery object) + */ + + load: function(src, size, callback) { + + if ( typeof size == 'function' ) { + callback = size; + size = null; + } + + if( this.isIframe ) { + var id = 'if'+new Date().getTime(); + + var iframe = this.image = $('<iframe>', { + src: src, + frameborder: 0, + id: id, + allowfullscreen: true, + css: { visibility: 'hidden' } + })[0]; + + if ( size ) { + $( iframe ).css( size ); + } + + $( this.container ).find( 'iframe,img' ).remove(); + + this.container.appendChild( this.image ); + + $('#'+id).load( (function( self, callback ) { + return function() { + window.setTimeout(function() { + $( self.image ).css( 'visibility', 'visible' ); + if( typeof callback == 'function' ) { + callback.call( self, self ); + } + }, 10); + }; + }( this, callback ))); + + return this.container; + } + + this.image = new Image(); + + // IE8 opacity inherit bug + if ( Galleria.IE8 ) { + $( this.image ).css( 'filter', 'inherit' ); + } + + // FF shaking images bug: + // http://support.galleria.io/discussions/problems/12245-shaking-photos + if ( !Galleria.IE && !Galleria.CHROME && !Galleria.SAFARI ) { + $( this.image ).css( 'image-rendering', 'optimizequality' ); + } + + var reload = false, + resort = false, + + // some jquery cache + $container = $( this.container ), + $image = $( this.image ), + + onerror = function() { + if ( !reload ) { + reload = true; + // reload the image with a timestamp + window.setTimeout((function(image, src) { + return function() { + image.attr('src', src + (src.indexOf('?') > -1 ? '&' : '?') + Utils.timestamp() ); + }; + }( $(this), src )), 50); + } else { + // apply the dummy image if it exists + if ( DUMMY ) { + $( this ).attr( 'src', DUMMY ); + } else { + Galleria.raise('Image not found: ' + src); + } + } + }, + + // the onload method + onload = (function( self, callback, src ) { + + return function() { + + var complete = function() { + + $( this ).off( 'load' ); + + // save the original size + self.original = size || { + height: this.height, + width: this.width + }; + + // translate3d if needed + if ( Galleria.HAS3D ) { + this.style.MozTransform = this.style.webkitTransform = 'translate3d(0,0,0)'; + } + + $container.append( this ); + + self.cache[ src ] = src; // will override old cache + + if (typeof callback == 'function' ) { + window.setTimeout(function() { + callback.call( self, self ); + },1); + } + }; + + // Delay the callback to "fix" the Adblock Bug + // http://code.google.com/p/adblockforchrome/issues/detail?id=3701 + if ( ( !this.width || !this.height ) ) { + (function( img ) { + Utils.wait({ + until: function() { + return img.width && img.height; + }, + success: function() { + complete.call( img ); + }, + error: function() { + if ( !resort ) { + $(new Image()).load( onload ).attr( 'src', img.src ); + resort = true; + } else { + Galleria.raise('Could not extract width/height from image: ' + img.src + + '. Traced measures: width:' + img.width + 'px, height: ' + img.height + 'px.'); + } + }, + timeout: 100 + }); + }( this )); + } else { + complete.call( this ); + } + }; + }( this, callback, src )); + + // remove any previous images + $container.find( 'iframe,img' ).remove(); + + // append the image + $image.css( 'display', 'block'); + + // hide it for now + Utils.hide( this.image ); + + // remove any max/min scaling + $.each('minWidth minHeight maxWidth maxHeight'.split(' '), function(i, prop) { + $image.css(prop, (/min/.test(prop) ? '0' : 'none')); + }); + + // begin load and insert in cache when done + $image.load( onload ).on( 'error', onerror ).attr( 'src', src ); + + // return the container + return this.container; + }, + + /** + Scales and crops the image + + @param {Object} options The method takes an object with a number of options: + + <ul> + <li>width - width of the container</li> + <li>height - height of the container</li> + <li>min - minimum scale ratio</li> + <li>max - maximum scale ratio</li> + <li>margin - distance in pixels from the image border to the container</li> + <li>complete - a callback that fires when scaling is complete</li> + <li>position - positions the image, works like the css background-image property.</li> + <li>crop - defines how to crop. Can be true, false, 'width' or 'height'</li> + <li>canvas - set to true to try a canvas-based rescale</li> + </ul> + + @returns The image container object (jQuery) + */ + + scale: function( options ) { + + var self = this; + + // extend some defaults + options = $.extend({ + width: 0, + height: 0, + min: undef, + max: undef, + margin: 0, + complete: F, + position: 'center', + crop: false, + canvas: false, + iframelimit: undef + }, options); + + if( this.isIframe ) { + + var cw = options.width, + ch = options.height, + nw, nh; + if ( options.iframelimit ) { + var r = M.min( options.iframelimit/cw, options.iframelimit/ch ); + if ( r < 1 ) { + nw = cw * r; + nh = ch * r; + + $( this.image ).css({ + top: ch/2-nh/2, + left: cw/2-nw/2, + position: 'absolute' + }); + } else { + $( this.image ).css({ + top: 0, + left: 0 + }); + } + } + $( this.image ).width( nw || cw ).height( nh || ch ).removeAttr( 'width' ).removeAttr( 'height' ); + $( this.container ).width( cw ).height( ch ); + options.complete.call(self, self); + try { + if( this.image.contentWindow ) { + $( this.image.contentWindow ).trigger('resize'); + } + } catch(e) {} + return this.container; + + } + + // return the element if no image found + if (!this.image) { + return this.container; + } + + // store locale variables + var width, + height, + $container = $( self.container ), + data; + + // wait for the width/height + Utils.wait({ + until: function() { + width = options.width || + $container.width() || + Utils.parseValue( $container.css('width') ); + + height = options.height || + $container.height() || + Utils.parseValue( $container.css('height') ); + + return width && height; + }, + success: function() { + + // calculate some cropping + var newWidth = ( width - options.margin * 2 ) / self.original.width, + newHeight = ( height - options.margin * 2 ) / self.original.height, + min = M.min( newWidth, newHeight ), + max = M.max( newWidth, newHeight ), + cropMap = { + 'true' : max, + 'width' : newWidth, + 'height': newHeight, + 'false' : min, + 'landscape': self.original.width > self.original.height ? max : min, + 'portrait': self.original.width < self.original.height ? max : min + }, + ratio = cropMap[ options.crop.toString() ], + canvasKey = ''; + + // allow maxScaleRatio + if ( options.max ) { + ratio = M.min( options.max, ratio ); + } + + // allow minScaleRatio + if ( options.min ) { + ratio = M.max( options.min, ratio ); + } + + $.each( ['width','height'], function( i, m ) { + $( self.image )[ m ]( self[ m ] = self.image[ m ] = M.round( self.original[ m ] * ratio ) ); + }); + + $( self.container ).width( width ).height( height ); + + if ( options.canvas && _canvas ) { + + _canvas.elem.width = self.width; + _canvas.elem.height = self.height; + + canvasKey = self.image.src + ':' + self.width + 'x' + self.height; + + self.image.src = _canvas.cache[ canvasKey ] || (function( key ) { + + _canvas.context.drawImage(self.image, 0, 0, self.original.width*ratio, self.original.height*ratio); + + try { + + data = _canvas.elem.toDataURL(); + _canvas.length += data.length; + _canvas.cache[ key ] = data; + return data; + + } catch( e ) { + return self.image.src; + } + + }( canvasKey ) ); + + } + + // calculate image_position + var pos = {}, + mix = {}, + getPosition = function(value, measure, margin) { + var result = 0; + if (/\%/.test(value)) { + var flt = parseInt( value, 10 ) / 100, + m = self.image[ measure ] || $( self.image )[ measure ](); + + result = M.ceil( m * -1 * flt + margin * flt ); + } else { + result = Utils.parseValue( value ); + } + return result; + }, + positionMap = { + 'top': { top: 0 }, + 'left': { left: 0 }, + 'right': { left: '100%' }, + 'bottom': { top: '100%' } + }; + + $.each( options.position.toLowerCase().split(' '), function( i, value ) { + if ( value === 'center' ) { + value = '50%'; + } + pos[i ? 'top' : 'left'] = value; + }); + + $.each( pos, function( i, value ) { + if ( positionMap.hasOwnProperty( value ) ) { + $.extend( mix, positionMap[ value ] ); + } + }); + + pos = pos.top ? $.extend( pos, mix ) : mix; + + pos = $.extend({ + top: '50%', + left: '50%' + }, pos); + + // apply position + $( self.image ).css({ + position : 'absolute', + top : getPosition(pos.top, 'height', height), + left : getPosition(pos.left, 'width', width) + }); + + // show the image + self.show(); + + // flag ready and call the callback + self.ready = true; + options.complete.call( self, self ); + + }, + error: function() { + Galleria.raise('Could not scale image: '+self.image.src); + }, + timeout: 1000 + }); + return this; + } +}; + +// our own easings +$.extend( $.easing, { + + galleria: function (_, t, b, c, d) { + if ((t/=d/2) < 1) { + return c/2*t*t*t + b; + } + return c/2*((t-=2)*t*t + 2) + b; + }, + + galleriaIn: function (_, t, b, c, d) { + return c*(t/=d)*t + b; + }, + + galleriaOut: function (_, t, b, c, d) { + return -c *(t/=d)*(t-2) + b; + } + +}); + + +// Forked version of Ainos Finger.js for native-style touch + +Galleria.Finger = (function() { + + var abs = M.abs; + + // test for translate3d support + var has3d = Galleria.HAS3D = (function() { + + var el = doc.createElement('p'), + has3d, + t = ['webkit','O','ms','Moz',''], + s, + i=0, + a = 'transform'; + + DOM().html.insertBefore(el, null); + + for (; t[i]; i++) { + s = t[i] ? t[i]+'Transform' : a; + if (el.style[s] !== undefined) { + el.style[s] = "translate3d(1px,1px,1px)"; + has3d = $(el).css(t[i] ? '-'+t[i].toLowerCase()+'-'+a : a); + } + } + + DOM().html.removeChild(el); + return (has3d !== undefined && has3d.length > 0 && has3d !== "none"); + }()); + + // request animation shim + var requestFrame = (function(){ + var r = 'RequestAnimationFrame'; + return window.requestAnimationFrame || + window['webkit'+r] || + window['moz'+r] || + window['o'+r] || + window['ms'+r] || + function( callback ) { + window.setTimeout(callback, 1000 / 60); + }; + }()); + + var Finger = function(elem, options) { + + // default options + this.config = { + start: 0, + duration: 500, + onchange: function() {}, + oncomplete: function() {}, + easing: function(x,t,b,c,d) { + return -c * ((t=t/d-1)*t*t*t - 1) + b; // easeOutQuart + } + }; + + this.easeout = function (x, t, b, c, d) { + return c*((t=t/d-1)*t*t*t*t + 1) + b; + }; + + if ( !elem.children.length ) { + return; + } + + var self = this; + + // extend options + $.extend(this.config, options); + + this.elem = elem; + this.child = elem.children[0]; + this.to = this.pos = 0; + this.touching = false; + this.start = {}; + this.index = this.config.start; + this.anim = 0; + this.easing = this.config.easing; + + if ( !has3d ) { + this.child.style.position = 'absolute'; + this.elem.style.position = 'relative'; + } + + // Bind event handlers to context + $.each(['ontouchstart','ontouchmove','ontouchend','setup'], function(i, fn) { + self[fn] = (function(caller) { + return function() { + caller.apply( self, arguments ); + }; + }(self[fn])); + }); + + // the physical animator + this.setX = function() { + + var style = self.child.style; + + if (!has3d) { + // this is actually faster than CSS3 translate + style.left = self.pos+'px'; + return; + } + style.MozTransform = style.webkitTransform = style.transform = 'translate3d(' + self.pos + 'px,0,0)'; + return; + }; + + // bind events + $(elem).on('touchstart', this.ontouchstart); + $(window).on('resize', this.setup); + $(window).on('orientationchange', this.setup); + + // set up width + this.setup(); + + // start the animations + (function animloop(){ + requestFrame(animloop); + self.loop.call( self ); + }()); + + }; + + Finger.prototype = { + + constructor: Finger, + + setup: function() { + this.width = $( this.elem ).width(); + this.length = M.ceil( $(this.child).width() / this.width ); + if ( this.index !== 0 ) { + this.index = M.max(0, M.min( this.index, this.length-1 ) ); + this.pos = this.to = -this.width*this.index; + } + }, + + setPosition: function(pos) { + this.pos = pos; + this.to = pos; + }, + + ontouchstart: function(e) { + + var touch = e.originalEvent.touches; + + this.start = { + pageX: touch[0].pageX, + pageY: touch[0].pageY, + time: +new Date() + }; + + this.isScrolling = null; + this.touching = true; + this.deltaX = 0; + + $doc.on('touchmove', this.ontouchmove); + $doc.on('touchend', this.ontouchend); + }, + + ontouchmove: function(e) { + + var touch = e.originalEvent.touches; + + // ensure swiping with one touch and not pinching + if( touch && touch.length > 1 || e.scale && e.scale !== 1 ) { + return; + } + + this.deltaX = touch[0].pageX - this.start.pageX; + + // determine if scrolling test has run - one time test + if ( this.isScrolling === null ) { + this.isScrolling = !!( + this.isScrolling || + M.abs(this.deltaX) < M.abs(touch[0].pageY - this.start.pageY) + ); + } + + // if user is not trying to scroll vertically + if (!this.isScrolling) { + + // prevent native scrolling + e.preventDefault(); + + // increase resistance if first or last slide + this.deltaX /= ( (!this.index && this.deltaX > 0 || this.index == this.length - 1 && this.deltaX < 0 ) ? + ( M.abs(this.deltaX) / this.width + 1.8 ) : 1 ); + this.to = this.deltaX - this.index * this.width; + } + e.stopPropagation(); + }, + + ontouchend: function(e) { + + this.touching = false; + + // determine if slide attempt triggers next/prev slide + var isValidSlide = +new Date() - this.start.time < 250 && + M.abs(this.deltaX) > 40 || + M.abs(this.deltaX) > this.width/2, + + isPastBounds = !this.index && this.deltaX > 0 || + this.index == this.length - 1 && this.deltaX < 0; + + // if not scrolling vertically + if ( !this.isScrolling ) { + this.show( this.index + ( isValidSlide && !isPastBounds ? (this.deltaX < 0 ? 1 : -1) : 0 ) ); + } + + $doc.off('touchmove', this.ontouchmove); + $doc.off('touchend', this.ontouchend); + }, + + show: function( index ) { + if ( index != this.index ) { + this.config.onchange.call(this, index); + } else { + this.to = -( index*this.width ); + } + }, + + moveTo: function( index ) { + if ( index != this.index ) { + this.pos = this.to = -( index*this.width ); + this.index = index; + } + }, + + loop: function() { + + var distance = this.to - this.pos, + factor = 1; + + if ( this.width && distance ) { + factor = M.max(0.5, M.min(1.5, M.abs(distance / this.width) ) ); + } + + // if distance is short or the user is touching, do a 1-1 animation + if ( this.touching || M.abs(distance) <= 1 ) { + this.pos = this.to; + distance = 0; + if ( this.anim && !this.touching ) { + this.config.oncomplete( this.index ); + } + this.anim = 0; + this.easing = this.config.easing; + } else { + if ( !this.anim ) { + // save animation parameters + this.anim = { start: this.pos, time: +new Date(), distance: distance, factor: factor, destination: this.to }; + } + // check if to has changed or time has run out + var elapsed = +new Date() - this.anim.time; + var duration = this.config.duration*this.anim.factor; + + if ( elapsed > duration || this.anim.destination != this.to ) { + this.anim = 0; + this.easing = this.easeout; + return; + } + // apply easing + this.pos = this.easing( + null, + elapsed, + this.anim.start, + this.anim.distance, + duration + ); + } + this.setX(); + } + }; + + return Finger; + +}()); + +// the plugin initializer +$.fn.galleria = function( options ) { + + var selector = this.selector; + + // try domReady if element not found + if ( !$(this).length ) { + + $(function() { + if ( $( selector ).length ) { + + // if found on domReady, go ahead + $( selector ).galleria( options ); + + } else { + + // if not, try fetching the element for 5 secs, then raise a warning. + Galleria.utils.wait({ + until: function() { + return $( selector ).length; + }, + success: function() { + $( selector ).galleria( options ); + }, + error: function() { + Galleria.raise('Init failed: Galleria could not find the element "'+selector+'".'); + }, + timeout: 5000 + }); + + } + }); + return this; + } + + return this.each(function() { + + // destroy previous instance and prepare for new load + if ( $.data(this, 'galleria') ) { + $.data( this, 'galleria' ).destroy(); + $( this ).find( '*' ).hide(); + } + + // load the new gallery + $.data( this, 'galleria', new Galleria().init( this, options ) ); + }); + +}; + +// export as AMD or CommonJS +if ( typeof module === "object" && module && typeof module.exports === "object" ) { + module.exports = Galleria; +} else { + window.Galleria = Galleria; + if ( typeof define === "function" && define.amd ) { + define( "galleria", ['jquery'], function() { return Galleria; } ); + } +} + +// phew + +}( jQuery, this ) ); \ No newline at end of file diff --git a/src/static/galleria/galleria-1.4.2.min.js b/src/static/galleria/galleria-1.4.2.min.js new file mode 100644 index 0000000..838763c --- /dev/null +++ b/src/static/galleria/galleria-1.4.2.min.js @@ -0,0 +1,3 @@ +!function(t,e,i,n){var a=e.document,o=t(a),r=t(e),s=Array.prototype,l=1.41,c=true,u=3e4,h=false,f=navigator.userAgent.toLowerCase(),d=e.location.hash.replace(/#\//,""),p=e.location.protocol,g=Math,m=function(){},v=function(){return false},y=function(){var t=3,e=a.createElement("div"),i=e.getElementsByTagName("i");do{e.innerHTML="<!--[if gt IE "+ ++t+"]><i></i><![endif]-->"}while(i[0]);return t>4?t:a.documentMode||n}(),_=function(){return{html:a.documentElement,body:a.body,head:a.getElementsByTagName("head")[0],title:a.title}},b=e.parent!==e.self,w="data ready thumbnail loadstart loadfinish image play pause progress "+"fullscreen_enter fullscreen_exit idle_enter idle_exit rescale "+"lightbox_open lightbox_close lightbox_image",x=function(){var e=[];t.each(w.split(" "),function(t,i){e.push(i);if(/_/.test(i)){e.push(i.replace(/_/g,""))}});return e}(),T=function(e){var i;if(typeof e!=="object"){return e}t.each(e,function(n,a){if(/^[a-z]+_/.test(n)){i="";t.each(n.split("_"),function(t,e){i+=t>0?e.substr(0,1).toUpperCase()+e.substr(1):e});e[i]=a;delete e[n]}});return e},k=function(e){if(t.inArray(e,x)>-1){return i[e.toUpperCase()]}return e},C={youtube:{reg:/https?:\/\/(?:[a-zA_Z]{2,3}.)?(?:youtube\.com\/watch\?)((?:[\w\d\-\_\=]+&amp;(?:amp;)?)*v(?:&lt;[A-Z]+&gt;)?=([0-9a-zA-Z\-\_]+))/i,embed:function(){return"http://www.youtube.com/embed/"+this.id},getUrl:function(){return p+"//gdata.youtube.com/feeds/api/videos/"+this.id+"?v=2&alt=json-in-script&callback=?"},get_thumb:function(t){return t.entry.media$group.media$thumbnail[2].url},get_image:function(t){if(t.entry.yt$hd){return p+"//img.youtube.com/vi/"+this.id+"/maxresdefault.jpg"}return t.entry.media$group.media$thumbnail[3].url}},vimeo:{reg:/https?:\/\/(?:www\.)?(vimeo\.com)\/(?:hd#)?([0-9]+)/i,embed:function(){return"http://player.vimeo.com/video/"+this.id},getUrl:function(){return p+"//vimeo.com/api/v2/video/"+this.id+".json?callback=?"},get_thumb:function(t){return t[0].thumbnail_medium},get_image:function(t){return t[0].thumbnail_large}},dailymotion:{reg:/https?:\/\/(?:www\.)?(dailymotion\.com)\/video\/([^_]+)/,embed:function(){return p+"//www.dailymotion.com/embed/video/"+this.id},getUrl:function(){return"https://api.dailymotion.com/video/"+this.id+"?fields=thumbnail_240_url,thumbnail_720_url&callback=?"},get_thumb:function(t){return t.thumbnail_240_url},get_image:function(t){return t.thumbnail_720_url}},_inst:[]},I=function(e,i){for(var n=0;n<C._inst.length;n++){if(C._inst[n].id===i&&C._inst[n].type==e){return C._inst[n]}}this.type=e;this.id=i;this.readys=[];C._inst.push(this);var a=this;t.extend(this,C[e]);t.getJSON(this.getUrl(),function(e){a.data=e;t.each(a.readys,function(t,e){e(a.data)});a.readys=[]});this.getMedia=function(t,e,i){i=i||m;var n=this;var a=function(i){e(n["get_"+t](i))};try{if(n.data){a(n.data)}else{n.readys.push(a)}}catch(o){i()}}},S=function(t){var e;for(var i in C){e=t&&C[i].reg&&t.match(C[i].reg);if(e&&e.length){return{id:e[2],provider:i}}}return false},A={support:function(){var t=_().html;return!b&&(t.requestFullscreen||t.msRequestFullscreen||t.mozRequestFullScreen||t.webkitRequestFullScreen)}(),callback:m,enter:function(t,e,i){this.instance=t;this.callback=e||m;i=i||_().html;if(i.requestFullscreen){i.requestFullscreen()}else if(i.msRequestFullscreen){i.msRequestFullscreen()}else if(i.mozRequestFullScreen){i.mozRequestFullScreen()}else if(i.webkitRequestFullScreen){i.webkitRequestFullScreen()}},exit:function(t){this.callback=t||m;if(a.exitFullscreen){a.exitFullscreen()}else if(a.msExitFullscreen){a.msExitFullscreen()}else if(a.mozCancelFullScreen){a.mozCancelFullScreen()}else if(a.webkitCancelFullScreen){a.webkitCancelFullScreen()}},instance:null,listen:function(){if(!this.support){return}var t=function(){if(!A.instance){return}var t=A.instance._fullscreen;if(a.fullscreen||a.mozFullScreen||a.webkitIsFullScreen||a.msFullscreenElement&&a.msFullscreenElement!==null){t._enter(A.callback)}else{t._exit(A.callback)}};a.addEventListener("fullscreenchange",t,false);a.addEventListener("MSFullscreenChange",t,false);a.addEventListener("mozfullscreenchange",t,false);a.addEventListener("webkitfullscreenchange",t,false)}},E=[],D=[],$=false,L=false,P=[],z=[],F=function(e){z.push(e);t.each(P,function(t,i){if(i._options.theme==e.name||!i._initialized&&!i._options.theme){i.theme=e;i._init.call(i)}})},H=function(){return{clearTimer:function(e){t.each(i.get(),function(){this.clearTimer(e)})},addTimer:function(e){t.each(i.get(),function(){this.addTimer(e)})},array:function(t){return s.slice.call(t,0)},create:function(t,e){e=e||"div";var i=a.createElement(e);i.className=t;return i},removeFromArray:function(e,i){t.each(e,function(t,n){if(n==i){e.splice(t,1);return false}});return e},getScriptPath:function(e){e=e||t("script:last").attr("src");var i=e.split("/");if(i.length==1){return""}i.pop();return i.join("/")+"/"},animate:function(){var n=function(t){var i="transition WebkitTransition MozTransition OTransition".split(" "),n;if(e.opera){return false}for(n=0;i[n];n++){if(typeof t[i[n]]!=="undefined"){return i[n]}}return false}((a.body||a.documentElement).style);var o={MozTransition:"transitionend",OTransition:"oTransitionEnd",WebkitTransition:"webkitTransitionEnd",transition:"transitionend"}[n];var r={_default:[.25,.1,.25,1],galleria:[.645,.045,.355,1],galleriaIn:[.55,.085,.68,.53],galleriaOut:[.25,.46,.45,.94],ease:[.25,0,.25,1],linear:[.25,.25,.75,.75],"ease-in":[.42,0,1,1],"ease-out":[0,0,.58,1],"ease-in-out":[.42,0,.58,1]};var s=function(e,i,n){var a={};n=n||"transition";t.each("webkit moz ms o".split(" "),function(){a["-"+this+"-"+n]=i});e.css(a)};var l=function(t){s(t,"none","transition");if(i.WEBKIT&&i.TOUCH){s(t,"translate3d(0,0,0)","transform");if(t.data("revert")){t.css(t.data("revert"));t.data("revert",null)}}};var c,u,h,f,d,p,g;return function(a,v,y){y=t.extend({duration:400,complete:m,stop:false},y);a=t(a);if(!y.duration){a.css(v);y.complete.call(a[0]);return}if(!n){a.animate(v,y);return}if(y.stop){a.off(o);l(a)}c=false;t.each(v,function(t,e){g=a.css(t);if(H.parseValue(g)!=H.parseValue(e)){c=true}a.css(t,g)});if(!c){e.setTimeout(function(){y.complete.call(a[0])},y.duration);return}u=[];h=y.easing in r?r[y.easing]:r._default;f=" "+y.duration+"ms"+" cubic-bezier("+h.join(",")+")";e.setTimeout(function(e,n,a,o){return function(){e.one(n,function(t){return function(){l(t);y.complete.call(t[0])}}(e));if(i.WEBKIT&&i.TOUCH){d={};p=[0,0,0];t.each(["left","top"],function(t,i){if(i in a){p[t]=H.parseValue(a[i])-H.parseValue(e.css(i))+"px";d[i]=a[i];delete a[i]}});if(p[0]||p[1]){e.data("revert",d);u.push("-webkit-transform"+o);s(e,"translate3d("+p.join(",")+")","transform")}}t.each(a,function(t,e){u.push(t+o)});s(e,u.join(","));e.css(a)}}(a,o,v,f),2)}}(),removeAlpha:function(t){if(t instanceof jQuery){t=t[0]}if(y<9&&t){var e=t.style,i=t.currentStyle,n=i&&i.filter||e.filter||"";if(/alpha/.test(n)){e.filter=n.replace(/alpha\([^)]*\)/i,"")}}},forceStyles:function(e,i){e=t(e);if(e.attr("style")){e.data("styles",e.attr("style")).removeAttr("style")}e.css(i)},revertStyles:function(){t.each(H.array(arguments),function(e,i){i=t(i);i.removeAttr("style");i.attr("style","");if(i.data("styles")){i.attr("style",i.data("styles")).data("styles",null)}})},moveOut:function(t){H.forceStyles(t,{position:"absolute",left:-1e4})},moveIn:function(){H.revertStyles.apply(H,H.array(arguments))},hide:function(e,i,n){n=n||m;var a=t(e);e=a[0];if(!a.data("opacity")){a.data("opacity",a.css("opacity"))}var o={opacity:0};if(i){var r=y<9&&e?function(){H.removeAlpha(e);e.style.visibility="hidden";n.call(e)}:n;H.animate(e,o,{duration:i,complete:r,stop:true})}else{if(y<9&&e){H.removeAlpha(e);e.style.visibility="hidden"}else{a.css(o)}}},show:function(e,i,n){n=n||m;var a=t(e);e=a[0];var o=parseFloat(a.data("opacity"))||1,r={opacity:o};if(i){if(y<9){a.css("opacity",0);e.style.visibility="visible"}var s=y<9&&e?function(){if(r.opacity==1){H.removeAlpha(e)}n.call(e)}:n;H.animate(e,r,{duration:i,complete:s,stop:true})}else{if(y<9&&r.opacity==1&&e){H.removeAlpha(e);e.style.visibility="visible"}else{a.css(r)}}},wait:function(n){i._waiters=i._waiters||[];n=t.extend({until:v,success:m,error:function(){i.raise("Could not complete wait function.")},timeout:3e3},n);var a=H.timestamp(),o,r,s,l=function(){r=H.timestamp();o=r-a;H.removeFromArray(i._waiters,s);if(n.until(o)){n.success();return false}if(typeof n.timeout=="number"&&r>=a+n.timeout){n.error();return false}i._waiters.push(s=e.setTimeout(l,10))};i._waiters.push(s=e.setTimeout(l,10))},toggleQuality:function(t,e){if(y!==7&&y!==8||!t||t.nodeName.toUpperCase()!="IMG"){return}if(typeof e==="undefined"){e=t.style.msInterpolationMode==="nearest-neighbor"}t.style.msInterpolationMode=e?"bicubic":"nearest-neighbor"},insertStyleTag:function(e,i){if(i&&t("#"+i).length){return}var n=a.createElement("style");if(i){n.id=i}_().head.appendChild(n);if(n.styleSheet){n.styleSheet.cssText=e}else{var o=a.createTextNode(e);n.appendChild(o)}},loadScript:function(e,i){var n=false,a=t("<scr"+"ipt>").attr({src:e,async:true}).get(0);a.onload=a.onreadystatechange=function(){if(!n&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){n=true;a.onload=a.onreadystatechange=null;if(typeof i==="function"){i.call(this,this)}}};_().head.appendChild(a)},parseValue:function(t){if(typeof t==="number"){return t}else if(typeof t==="string"){var e=t.match(/\-?\d|\./g);return e&&e.constructor===Array?e.join("")*1:0}else{return 0}},timestamp:function(){return(new Date).getTime()},loadCSS:function(e,o,r){var s,l;t("link[rel=stylesheet]").each(function(){if(new RegExp(e).test(this.href)){s=this;return false}});if(typeof o==="function"){r=o;o=n}r=r||m;if(s){r.call(s,s);return s}l=a.styleSheets.length;if(t("#"+o).length){t("#"+o).attr("href",e);l--}else{s=t("<link>").attr({rel:"stylesheet",href:e,id:o}).get(0);var c=t('link[rel="stylesheet"], style');if(c.length){c.get(0).parentNode.insertBefore(s,c[0])}else{_().head.appendChild(s)}if(y&&l>=31){i.raise("You have reached the browser stylesheet limit (31)",true);return}}if(typeof r==="function"){var u=t("<s>").attr("id","galleria-loader").hide().appendTo(_().body);H.wait({until:function(){return u.height()==1},success:function(){u.remove();r.call(s,s)},error:function(){u.remove();i.raise("Theme CSS could not load after 20 sec. "+(i.QUIRK?"Your browser is in Quirks Mode, please add a correct doctype.":"Please download the latest theme at http://galleria.io/customer/."),true)},timeout:5e3})}return s}}}(),O=function(e){var i=".galleria-videoicon{width:60px;height:60px;position:absolute;top:50%;left:50%;z-index:1;"+"margin:-30px 0 0 -30px;cursor:pointer;background:#000;background:rgba(0,0,0,.8);border-radius:3px;-webkit-transition:all 150ms}"+".galleria-videoicon i{width:0px;height:0px;border-style:solid;border-width:10px 0 10px 16px;display:block;"+"border-color:transparent transparent transparent #ffffff;margin:20px 0 0 22px}.galleria-image:hover .galleria-videoicon{background:#000}";H.insertStyleTag(i,"galleria-videoicon");return t(H.create("galleria-videoicon")).html("<i></i>").appendTo(e).click(function(){t(this).siblings("img").mouseup()})},M=function(){var e=function(e,i,n,a){var o=this.getOptions("easing"),r=this.getStageWidth(),s={left:r*(e.rewind?-1:1)},l={left:0};if(n){s.opacity=0;l.opacity=1}else{s.opacity=1}t(e.next).css(s);H.animate(e.next,l,{duration:e.speed,complete:function(t){return function(){i();t.css({left:0})}}(t(e.next).add(e.prev)),queue:false,easing:o});if(a){e.rewind=!e.rewind}if(e.prev){s={left:0};l={left:r*(e.rewind?1:-1)};if(n){s.opacity=1;l.opacity=0}t(e.prev).css(s);H.animate(e.prev,l,{duration:e.speed,queue:false,easing:o,complete:function(){t(this).css("opacity",0)}})}};return{active:false,init:function(t,e,i){if(M.effects.hasOwnProperty(t)){M.effects[t].call(this,e,i)}},effects:{fade:function(e,i){t(e.next).css({opacity:0,left:0});H.animate(e.next,{opacity:1},{duration:e.speed,complete:i});if(e.prev){t(e.prev).css("opacity",1).show();H.animate(e.prev,{opacity:0},{duration:e.speed})}},flash:function(e,i){t(e.next).css({opacity:0,left:0});if(e.prev){H.animate(e.prev,{opacity:0},{duration:e.speed/2,complete:function(){H.animate(e.next,{opacity:1},{duration:e.speed,complete:i})}})}else{H.animate(e.next,{opacity:1},{duration:e.speed,complete:i})}},pulse:function(e,i){if(e.prev){t(e.prev).hide()}t(e.next).css({opacity:0,left:0}).show();H.animate(e.next,{opacity:1},{duration:e.speed,complete:i})},slide:function(t,i){e.apply(this,H.array(arguments))},fadeslide:function(t,i){e.apply(this,H.array(arguments).concat([true]))},doorslide:function(t,i){e.apply(this,H.array(arguments).concat([false,true]))}}}}();A.listen();t.event.special["click:fast"]={propagate:true,add:function(i){var n=function(t){if(t.touches&&t.touches.length){var e=t.touches[0];return{x:e.pageX,y:e.pageY}}};var a={touched:false,touchdown:false,coords:{x:0,y:0},evObj:{}};t(this).data({clickstate:a,timer:0}).on("touchstart.fast",function(i){e.clearTimeout(t(this).data("timer"));t(this).data("clickstate",{touched:true,touchdown:true,coords:n(i.originalEvent),evObj:i})}).on("touchmove.fast",function(e){var i=n(e.originalEvent),a=t(this).data("clickstate"),o=Math.max(Math.abs(a.coords.x-i.x),Math.abs(a.coords.y-i.y));if(o>6){t(this).data("clickstate",t.extend(a,{touchdown:false}))}}).on("touchend.fast",function(n){var o=t(this),r=o.data("clickstate");if(r.touchdown){i.handler.call(this,n)}o.data("timer",e.setTimeout(function(){o.data("clickstate",a)},400))}).on("click.fast",function(e){var n=t(this).data("clickstate");if(n.touched){return false}t(this).data("clickstate",a);i.handler.call(this,e)})},remove:function(){t(this).off("touchstart.fast touchmove.fast touchend.fast click.fast")}};r.on("orientationchange",function(){t(this).resize()});i=function(){var s=this;this._options={};this._playing=false;this._playtime=5e3;this._active=null;this._queue={length:0};this._data=[];this._dom={};this._thumbnails=[];this._layers=[];this._initialized=false;this._firstrun=false;this._stageWidth=0;this._stageHeight=0;this._target=n;this._binds=[];this._id=parseInt(g.random()*1e4,10);var l="container stage images image-nav image-nav-left image-nav-right "+"info info-text info-title info-description "+"thumbnails thumbnails-list thumbnails-container thumb-nav-left thumb-nav-right "+"loader counter tooltip",c="current total";t.each(l.split(" "),function(t,e){s._dom[e]=H.create("galleria-"+e)});t.each(c.split(" "),function(t,e){s._dom[e]=H.create("galleria-"+e,"span")});var u=this._keyboard={keys:{UP:38,DOWN:40,LEFT:37,RIGHT:39,RETURN:13,ESCAPE:27,BACKSPACE:8,SPACE:32},map:{},bound:false,press:function(t){var e=t.keyCode||t.which;if(e in u.map&&typeof u.map[e]==="function"){u.map[e].call(s,t)}},attach:function(t){var e,i;for(e in t){if(t.hasOwnProperty(e)){i=e.toUpperCase();if(i in u.keys){u.map[u.keys[i]]=t[e]}else{u.map[i]=t[e]}}}if(!u.bound){u.bound=true;o.on("keydown",u.press)}},detach:function(){u.bound=false;u.map={};o.off("keydown",u.press)}};var h=this._controls={0:n,1:n,active:0,swap:function(){h.active=h.active?0:1},getActive:function(){return s._options.swipe?h.slides[s._active]:h[h.active]},getNext:function(){return s._options.swipe?h.slides[s.getNext(s._active)]:h[1-h.active]},slides:[],frames:[],layers:[]};var d=this._carousel={next:s.$("thumb-nav-right"),prev:s.$("thumb-nav-left"),width:0,current:0,max:0,hooks:[],update:function(){var e=0,i=0,n=[0];t.each(s._thumbnails,function(a,o){if(o.ready){e+=o.outerWidth||t(o.container).outerWidth(true);var r=t(o.container).width();e+=r-g.floor(r);n[a+1]=e;i=g.max(i,o.outerHeight||t(o.container).outerHeight(true))}});s.$("thumbnails").css({width:e,height:i});d.max=e;d.hooks=n;d.width=s.$("thumbnails-list").width();d.setClasses();s.$("thumbnails-container").toggleClass("galleria-carousel",e>d.width);d.width=s.$("thumbnails-list").width()},bindControls:function(){var t;d.next.on("click:fast",function(e){e.preventDefault();if(s._options.carouselSteps==="auto"){for(t=d.current;t<d.hooks.length;t++){if(d.hooks[t]-d.hooks[d.current]>d.width){d.set(t-2);break}}}else{d.set(d.current+s._options.carouselSteps)}});d.prev.on("click:fast",function(e){e.preventDefault();if(s._options.carouselSteps==="auto"){for(t=d.current;t>=0;t--){if(d.hooks[d.current]-d.hooks[t]>d.width){d.set(t+2);break}else if(t===0){d.set(0);break}}}else{d.set(d.current-s._options.carouselSteps)}})},set:function(t){t=g.max(t,0);while(d.hooks[t-1]+d.width>=d.max&&t>=0){t--}d.current=t;d.animate()},getLast:function(t){return(t||d.current)-1},follow:function(t){if(t===0||t===d.hooks.length-2){d.set(t);return}var e=d.current;while(d.hooks[e]-d.hooks[d.current]<d.width&&e<=d.hooks.length){e++}if(t-1<d.current){d.set(t-1)}else if(t+2>e){d.set(t-e+d.current+2)}},setClasses:function(){d.prev.toggleClass("disabled",!d.current);d.next.toggleClass("disabled",d.hooks[d.current]+d.width>=d.max)},animate:function(e){d.setClasses();var i=d.hooks[d.current]*-1;if(isNaN(i)){return}s.$("thumbnails").css("left",function(){return t(this).css("left")});H.animate(s.get("thumbnails"),{left:i},{duration:s._options.carouselSpeed,easing:s._options.easing,queue:false})}};var p=this._tooltip={initialized:false,open:false,timer:"tooltip"+s._id,swapTimer:"swap"+s._id,init:function(){p.initialized=true;var t=".galleria-tooltip{padding:3px 8px;max-width:50%;background:#ffe;color:#000;z-index:3;position:absolute;font-size:11px;line-height:1.3;"+"opacity:0;box-shadow:0 0 2px rgba(0,0,0,.4);-moz-box-shadow:0 0 2px rgba(0,0,0,.4);-webkit-box-shadow:0 0 2px rgba(0,0,0,.4);}";H.insertStyleTag(t,"galleria-tooltip");s.$("tooltip").css({opacity:.8,visibility:"visible",display:"none"})},move:function(t){var e=s.getMousePosition(t).x,i=s.getMousePosition(t).y,n=s.$("tooltip"),a=e,o=i,r=n.outerHeight(true)+1,l=n.outerWidth(true),c=r+15;var u=s.$("container").width()-l-2,h=s.$("container").height()-r-2;if(!isNaN(a)&&!isNaN(o)){a+=10;o-=r+8;a=g.max(0,g.min(u,a));o=g.max(0,g.min(h,o));if(i<c){o=c}n.css({left:a,top:o})}},bind:function(e,n){if(i.TOUCH){return}if(!p.initialized){p.init()}var a=function(){s.$("container").off("mousemove",p.move);s.clearTimer(p.timer);s.$("tooltip").stop().animate({opacity:0},200,function(){s.$("tooltip").hide();s.addTimer(p.swapTimer,function(){p.open=false},1e3)})};var o=function(e,i){p.define(e,i);t(e).hover(function(){s.clearTimer(p.swapTimer);s.$("container").off("mousemove",p.move).on("mousemove",p.move).trigger("mousemove");p.show(e);s.addTimer(p.timer,function(){s.$("tooltip").stop().show().animate({opacity:1});p.open=true},p.open?0:500)},a).click(a)};if(typeof n==="string"){o(e in s._dom?s.get(e):e,n)}else{t.each(e,function(t,e){o(s.get(t),e)})}},show:function(i){i=t(i in s._dom?s.get(i):i);var n=i.data("tt"),a=function(t){e.setTimeout(function(t){return function(){p.move(t)}}(t),10);i.off("mouseup",a)};n=typeof n==="function"?n():n;if(!n){return}s.$("tooltip").html(n.replace(/\s/,"&#160;"));i.on("mouseup",a)},define:function(e,i){if(typeof i!=="function"){var n=i;i=function(){return n}}e=t(e in s._dom?s.get(e):e).data("tt",i);p.show(e)}};var m=this._fullscreen={scrolled:0,crop:n,active:false,prev:t(),beforeEnter:function(t){t()},beforeExit:function(t){t()},keymap:s._keyboard.map,parseCallback:function(e,i){return M.active?function(){if(typeof e=="function"){e.call(s)}var n=s._controls.getActive(),a=s._controls.getNext();s._scaleImage(a);s._scaleImage(n);if(i&&s._options.trueFullscreen){t(n.container).add(a.container).trigger("transitionend")}}:e},enter:function(t){m.beforeEnter(function(){t=m.parseCallback(t,true);if(s._options.trueFullscreen&&A.support){m.active=true;H.forceStyles(s.get("container"),{width:"100%",height:"100%"});s.rescale();if(i.MAC){if(!(i.SAFARI&&/version\/[1-5]/.test(f))){s.$("container").css("opacity",0).addClass("fullscreen");e.setTimeout(function(){m.scale();s.$("container").css("opacity",1)},50)}else{s.$("stage").css("opacity",0);e.setTimeout(function(){m.scale();s.$("stage").css("opacity",1)},4)}}else{s.$("container").addClass("fullscreen")}r.resize(m.scale);A.enter(s,t,s.get("container"))}else{m.scrolled=r.scrollTop();if(!i.TOUCH){e.scrollTo(0,0)}m._enter(t)}})},_enter:function(o){m.active=true;if(b){m.iframe=function(){var n,o=a.referrer,r=a.createElement("a"),s=e.location;r.href=o;if(r.protocol!=s.protocol||r.hostname!=s.hostname||r.port!=s.port){i.raise("Parent fullscreen not available. Iframe protocol, domains and ports must match.");return false}m.pd=e.parent.document;t(m.pd).find("iframe").each(function(){var t=this.contentDocument||this.contentWindow.document;if(t===a){n=this;return false}});return n}()}H.hide(s.getActiveImage());if(b&&m.iframe){m.iframe.scrolled=t(e.parent).scrollTop();e.parent.scrollTo(0,0)}var l=s.getData(),c=s._options,u=!s._options.trueFullscreen||!A.support,h={height:"100%",overflow:"hidden",margin:0,padding:0};if(u){s.$("container").addClass("fullscreen");m.prev=s.$("container").prev();if(!m.prev.length){m.parent=s.$("container").parent()}s.$("container").appendTo("body");H.forceStyles(s.get("container"),{position:i.TOUCH?"absolute":"fixed",top:0,left:0,width:"100%",height:"100%",zIndex:1e4});H.forceStyles(_().html,h);H.forceStyles(_().body,h)}if(b&&m.iframe){H.forceStyles(m.pd.documentElement,h);H.forceStyles(m.pd.body,h);H.forceStyles(m.iframe,t.extend(h,{width:"100%",height:"100%",top:0,left:0,position:"fixed",zIndex:1e4,border:"none"}))}m.keymap=t.extend({},s._keyboard.map);s.attachKeyboard({escape:s.exitFullscreen,right:s.next,left:s.prev});m.crop=c.imageCrop;if(c.fullscreenCrop!=n){c.imageCrop=c.fullscreenCrop}if(l&&l.big&&l.image!==l.big){var f=new i.Picture,d=f.isCached(l.big),p=s.getIndex(),g=s._thumbnails[p];s.trigger({type:i.LOADSTART,cached:d,rewind:false,index:p,imageTarget:s.getActiveImage(),thumbTarget:g,galleriaData:l});f.load(l.big,function(e){s._scaleImage(e,{complete:function(e){s.trigger({type:i.LOADFINISH,cached:d,index:p,rewind:false,imageTarget:e.image,thumbTarget:g});var n=s._controls.getActive().image;if(n){t(n).width(e.image.width).height(e.image.height).attr("style",t(e.image).attr("style")).attr("src",e.image.src)}}})});var v=s.getNext(p),y=new i.Picture,w=s.getData(v);y.preload(s.isFullscreen()&&w.big?w.big:w.image)}s.rescale(function(){s.addTimer(false,function(){if(u){H.show(s.getActiveImage())}if(typeof o==="function"){o.call(s)}s.rescale()},100);s.trigger(i.FULLSCREEN_ENTER)});if(!u){H.show(s.getActiveImage())}else{r.resize(m.scale)}},scale:function(){s.rescale()},exit:function(t){m.beforeExit(function(){t=m.parseCallback(t);if(s._options.trueFullscreen&&A.support){A.exit(t)}else{m._exit(t)}})},_exit:function(t){m.active=false;var n=!s._options.trueFullscreen||!A.support,a=s.$("container").removeClass("fullscreen");if(m.parent){m.parent.prepend(a)}else{a.insertAfter(m.prev)}if(n){H.hide(s.getActiveImage());H.revertStyles(s.get("container"),_().html,_().body);if(!i.TOUCH){e.scrollTo(0,m.scrolled)}var o=s._controls.frames[s._controls.active];if(o&&o.image){o.image.src=o.image.src}}if(b&&m.iframe){H.revertStyles(m.pd.documentElement,m.pd.body,m.iframe);if(m.iframe.scrolled){e.parent.scrollTo(0,m.iframe.scrolled)}}s.detachKeyboard();s.attachKeyboard(m.keymap);s._options.imageCrop=m.crop;var l=s.getData().big,c=s._controls.getActive().image;if(!s.getData().iframe&&c&&l&&l==c.src){e.setTimeout(function(t){return function(){c.src=t}}(s.getData().image),1)}s.rescale(function(){s.addTimer(false,function(){if(n){H.show(s.getActiveImage())}if(typeof t==="function"){t.call(s)}r.trigger("resize")},50);s.trigger(i.FULLSCREEN_EXIT)});r.off("resize",m.scale)}};var v=this._idle={trunk:[],bound:false,active:false,add:function(e,n,a,o){if(!e||i.TOUCH){return}if(!v.bound){v.addEvent()}e=t(e);if(typeof a=="boolean"){o=a;a={}}a=a||{};var r={},s;for(s in n){if(n.hasOwnProperty(s)){r[s]=e.css(s)}}e.data("idle",{from:t.extend(r,a),to:n,complete:true,busy:false});if(!o){v.addTimer()}else{e.css(n)}v.trunk.push(e)},remove:function(e){e=t(e);t.each(v.trunk,function(t,i){if(i&&i.length&&!i.not(e).length){e.css(e.data("idle").from);v.trunk.splice(t,1)}});if(!v.trunk.length){v.removeEvent();s.clearTimer(v.timer)}},addEvent:function(){v.bound=true;s.$("container").on("mousemove click",v.showAll);if(s._options.idleMode=="hover"){s.$("container").on("mouseleave",v.hide)}},removeEvent:function(){v.bound=false;s.$("container").on("mousemove click",v.showAll);if(s._options.idleMode=="hover"){s.$("container").off("mouseleave",v.hide)}},addTimer:function(){if(s._options.idleMode=="hover"){return}s.addTimer("idle",function(){v.hide()},s._options.idleTime)},hide:function(){if(!s._options.idleMode||s.getIndex()===false){return}s.trigger(i.IDLE_ENTER);var e=v.trunk.length;t.each(v.trunk,function(t,i){var n=i.data("idle");if(!n){return}i.data("idle").complete=false;H.animate(i,n.to,{duration:s._options.idleSpeed,complete:function(){if(t==e-1){v.active=false}}})})},showAll:function(){s.clearTimer("idle");t.each(v.trunk,function(t,e){v.show(e)})},show:function(e){var n=e.data("idle");if(!v.active||!n.busy&&!n.complete){n.busy=true;s.trigger(i.IDLE_EXIT);s.clearTimer("idle");H.animate(e,n.from,{duration:s._options.idleSpeed/2,complete:function(){v.active=true;t(e).data("idle").busy=false;t(e).data("idle").complete=true}})}v.addTimer()}};var w=this._lightbox={width:0,height:0,initialized:false,active:null,image:null,elems:{},keymap:false,init:function(){if(w.initialized){return}w.initialized=true;var e="overlay box content shadow title info close prevholder prev nextholder next counter image",n={},a=s._options,o="",r="position:absolute;",l="lightbox-",c={overlay:"position:fixed;display:none;opacity:"+a.overlayOpacity+";filter:alpha(opacity="+a.overlayOpacity*100+");top:0;left:0;width:100%;height:100%;background:"+a.overlayBackground+";z-index:99990",box:"position:fixed;display:none;width:400px;height:400px;top:50%;left:50%;margin-top:-200px;margin-left:-200px;z-index:99991",shadow:r+"background:#000;width:100%;height:100%;",content:r+"background-color:#fff;top:10px;left:10px;right:10px;bottom:10px;overflow:hidden",info:r+"bottom:10px;left:10px;right:10px;color:#444;font:11px/13px arial,sans-serif;height:13px",close:r+"top:10px;right:10px;height:20px;width:20px;background:#fff;text-align:center;cursor:pointer;color:#444;font:16px/22px arial,sans-serif;z-index:99999",image:r+"top:10px;left:10px;right:10px;bottom:30px;overflow:hidden;display:block;",prevholder:r+"width:50%;top:0;bottom:40px;cursor:pointer;",nextholder:r+"width:50%;top:0;bottom:40px;right:-1px;cursor:pointer;",prev:r+"top:50%;margin-top:-20px;height:40px;width:30px;background:#fff;left:20px;display:none;text-align:center;color:#000;font:bold 16px/36px arial,sans-serif",next:r+"top:50%;margin-top:-20px;height:40px;width:30px;background:#fff;right:20px;left:auto;display:none;font:bold 16px/36px arial,sans-serif;text-align:center;color:#000",title:"float:left",counter:"float:right;margin-left:8px;"},u=function(e){return e.hover(function(){t(this).css("color","#bbb")},function(){t(this).css("color","#444")})},h={};var f="";if(y>7){f=y<9?"background:#000;filter:alpha(opacity=0);":"background:rgba(0,0,0,0);"}else{f="z-index:99999"}c.nextholder+=f;c.prevholder+=f;t.each(c,function(t,e){o+=".galleria-"+l+t+"{"+e+"}"});o+=".galleria-"+l+"box.iframe .galleria-"+l+"prevholder,"+".galleria-"+l+"box.iframe .galleria-"+l+"nextholder{"+"width:100px;height:100px;top:50%;margin-top:-70px}";H.insertStyleTag(o,"galleria-lightbox");t.each(e.split(" "),function(t,e){s.addElement("lightbox-"+e);n[e]=w.elems[e]=s.get("lightbox-"+e)});w.image=new i.Picture;t.each({box:"shadow content close prevholder nextholder",info:"title counter",content:"info image",prevholder:"prev",nextholder:"next"},function(e,i){var n=[];t.each(i.split(" "),function(t,e){n.push(l+e)});h[l+e]=n});s.append(h);t(n.image).append(w.image.container);t(_().body).append(n.overlay,n.box);u(t(n.close).on("click:fast",w.hide).html("&#215;"));t.each(["Prev","Next"],function(e,a){var o=t(n[a.toLowerCase()]).html(/v/.test(a)?"&#8249;&#160;":"&#160;&#8250;"),r=t(n[a.toLowerCase()+"holder"]);r.on("click:fast",function(){w["show"+a]()});if(y<8||i.TOUCH){o.show();return}r.hover(function(){o.show()},function(t){o.stop().fadeOut(200)})});t(n.overlay).on("click:fast",w.hide);if(i.IPAD){s._options.lightboxTransitionSpeed=0}},rescale:function(e){var n=g.min(r.width()-40,w.width),a=g.min(r.height()-60,w.height),o=g.min(n/w.width,a/w.height),l=g.round(w.width*o)+40,c=g.round(w.height*o)+60,u={width:l,height:c,"margin-top":g.ceil(c/2)*-1,"margin-left":g.ceil(l/2)*-1};if(e){t(w.elems.box).css(u)}else{t(w.elems.box).animate(u,{duration:s._options.lightboxTransitionSpeed,easing:s._options.easing,complete:function(){var e=w.image,n=s._options.lightboxFadeSpeed;s.trigger({type:i.LIGHTBOX_IMAGE,imageTarget:e.image});t(e.container).show();t(e.image).animate({opacity:1},n);H.show(w.elems.info,n)}})}},hide:function(){w.image.image=null;r.off("resize",w.rescale);t(w.elems.box).hide().find("iframe").remove();H.hide(w.elems.info);s.detachKeyboard();s.attachKeyboard(w.keymap);w.keymap=false;H.hide(w.elems.overlay,200,function(){t(this).hide().css("opacity",s._options.overlayOpacity);s.trigger(i.LIGHTBOX_CLOSE)})},showNext:function(){w.show(s.getNext(w.active))},showPrev:function(){w.show(s.getPrev(w.active))},show:function(n){w.active=n=typeof n==="number"?n:s.getIndex()||0;if(!w.initialized){w.init()}s.trigger(i.LIGHTBOX_OPEN);if(!w.keymap){w.keymap=t.extend({},s._keyboard.map);s.attachKeyboard({escape:w.hide,right:w.showNext,left:w.showPrev})}r.off("resize",w.rescale);var a=s.getData(n),o=s.getDataLength(),l=s.getNext(n),c,u,h;H.hide(w.elems.info);try{for(h=s._options.preload;h>0;h--){u=new i.Picture;c=s.getData(l);u.preload(c.big?c.big:c.image);l=s.getNext(l)}}catch(f){}w.image.isIframe=a.iframe&&!a.image;t(w.elems.box).toggleClass("iframe",w.image.isIframe);t(w.image.container).find(".galleria-videoicon").remove();w.image.load(a.big||a.image||a.iframe,function(i){if(i.isIframe){var l=t(e).width(),c=t(e).height();if(i.video&&s._options.maxVideoSize){var u=g.min(s._options.maxVideoSize/l,s._options.maxVideoSize/c);if(u<1){l*=u;c*=u}}w.width=l;w.height=c}else{w.width=i.original.width;w.height=i.original.height}t(i.image).css({width:i.isIframe?"100%":"100.1%",height:i.isIframe?"100%":"100.1%",top:0,bottom:0,zIndex:99998,opacity:0,visibility:"visible"}).parent().height("100%");w.elems.title.innerHTML=a.title||"";w.elems.counter.innerHTML=n+1+" / "+o;r.resize(w.rescale);w.rescale();if(a.image&&a.iframe){t(w.elems.box).addClass("iframe");if(a.video){var h=O(i.container).hide();e.setTimeout(function(){h.fadeIn(200)},200)}t(i.image).css("cursor","pointer").mouseup(function(e,i){return function(n){t(w.image.container).find(".galleria-videoicon").remove();n.preventDefault();i.isIframe=true;i.load(e.iframe+(e.video?"&autoplay=1":""),{width:"100%",height:y<8?t(w.image.container).height():"100%"})}}(a,i))}});t(w.elems.overlay).show().css("visibility","visible");t(w.elems.box).show()}};var x=this._timer={trunk:{},add:function(t,i,n,a){t=t||(new Date).getTime();a=a||false;this.clear(t);if(a){var o=i;i=function(){o();x.add(t,i,n)}}this.trunk[t]=e.setTimeout(i,n)},clear:function(t){var i=function(t){e.clearTimeout(this.trunk[t]);delete this.trunk[t]},n;if(!!t&&t in this.trunk){i.call(this,t)}else if(typeof t==="undefined"){for(n in this.trunk){if(this.trunk.hasOwnProperty(n)){i.call(this,n)}}}}};return this};i.prototype={constructor:i,init:function(e,a){a=T(a);this._original={target:e,options:a,data:null};this._target=this._dom.target=e.nodeName?e:t(e).get(0);this._original.html=this._target.innerHTML;D.push(this);if(!this._target){i.raise("Target not found",true);return}this._options={autoplay:false,carousel:true,carouselFollow:true,carouselSpeed:400,carouselSteps:"auto",clicknext:false,dailymotion:{foreground:"%23EEEEEE",highlight:"%235BCEC5",background:"%23222222",logo:0,hideInfos:1},dataConfig:function(t){return{}},dataSelector:"img",dataSort:false,dataSource:this._target,debug:n,dummy:n,easing:"galleria",extend:function(t){},fullscreenCrop:n,fullscreenDoubleTap:true,fullscreenTransition:n,height:0,idleMode:true,idleTime:3e3,idleSpeed:200,imageCrop:false,imageMargin:0,imagePan:false,imagePanSmoothness:12,imagePosition:"50%",imageTimeout:n,initialTransition:n,keepSource:false,layerFollow:true,lightbox:false,lightboxFadeSpeed:200,lightboxTransitionSpeed:200,linkSourceImages:true,maxScaleRatio:n,maxVideoSize:n,minScaleRatio:n,overlayOpacity:.85,overlayBackground:"#0b0b0b",pauseOnInteraction:true,popupLinks:false,preload:2,queue:true,responsive:true,show:0,showInfo:true,showCounter:true,showImagenav:true,swipe:"auto",theme:null,thumbCrop:true,thumbEventType:"click:fast",thumbMargin:0,thumbQuality:"auto",thumbDisplayOrder:true,thumbPosition:"50%",thumbnails:true,touchTransition:n,transition:"fade",transitionInitial:n,transitionSpeed:400,trueFullscreen:true,useCanvas:false,variation:"",videoPoster:true,vimeo:{title:0,byline:0,portrait:0,color:"aaaaaa"},wait:5e3,width:"auto",youtube:{modestbranding:1,autohide:1,color:"white",hd:1,rel:0,showinfo:0}}; +this._options.initialTransition=this._options.initialTransition||this._options.transitionInitial;if(a){if(a.debug===false){c=false}if(typeof a.imageTimeout==="number"){u=a.imageTimeout}if(typeof a.dummy==="string"){h=a.dummy}if(typeof a.theme=="string"){this._options.theme=a.theme}}t(this._target).children().hide();if(i.QUIRK){i.raise("Your page is in Quirks mode, Galleria may not render correctly. Please validate your HTML and add a correct doctype.")}if(z.length){if(this._options.theme){for(var o=0;o<z.length;o++){if(this._options.theme===z[o].name){this.theme=z[o];break}}}else{this.theme=z[0]}}if(typeof this.theme=="object"){this._init()}else{P.push(this)}return this},_init:function(){var o=this,s=this._options;if(this._initialized){i.raise("Init failed: Gallery instance already initialized.");return this}this._initialized=true;if(!this.theme){i.raise("Init failed: No theme found.",true);return this}t.extend(true,s,this.theme.defaults,this._original.options,i.configure.options);s.swipe=function(t){if(t=="enforced"){return true}if(t===false||t=="disabled"){return false}return!!i.TOUCH}(s.swipe);if(s.swipe){s.clicknext=false;s.imagePan=false}!function(t){if(!("getContext"in t)){t=null;return}L=L||{elem:t,context:t.getContext("2d"),cache:{},length:0}}(a.createElement("canvas"));this.bind(i.DATA,function(){if(e.screen&&e.screen.width&&Array.prototype.forEach){this._data.forEach(function(t){var i="devicePixelRatio"in e?e.devicePixelRatio:1,n=g.max(e.screen.width,e.screen.height);if(n*i<1024){t.big=t.image}})}this._original.data=this._data;this.get("total").innerHTML=this.getDataLength();var t=this.$("container");if(o._options.height<2){o._userRatio=o._ratio=o._options.height}var n={width:0,height:0};var a=function(){return o.$("stage").height()};H.wait({until:function(){n=o._getWH();t.width(n.width).height(n.height);return a()&&n.width&&n.height>50},success:function(){o._width=n.width;o._height=n.height;o._ratio=o._ratio||n.height/n.width;if(i.WEBKIT){e.setTimeout(function(){o._run()},1)}else{o._run()}},error:function(){if(a()){i.raise("Could not extract sufficient width/height of the gallery container. Traced measures: width:"+n.width+"px, height: "+n.height+"px.",true)}else{i.raise("Could not extract a stage height from the CSS. Traced height: "+a()+"px.",true)}},timeout:typeof this._options.wait=="number"?this._options.wait:false})});this.append({"info-text":["info-title","info-description"],info:["info-text"],"image-nav":["image-nav-right","image-nav-left"],stage:["images","loader","counter","image-nav"],"thumbnails-list":["thumbnails"],"thumbnails-container":["thumb-nav-left","thumbnails-list","thumb-nav-right"],container:["stage","thumbnails-container","info","tooltip"]});H.hide(this.$("counter").append(this.get("current"),a.createTextNode(" / "),this.get("total")));this.setCounter("&#8211;");H.hide(o.get("tooltip"));this.$("container").addClass([i.TOUCH?"touch":"notouch",this._options.variation,"galleria-theme-"+this.theme.name].join(" "));if(!this._options.swipe){t.each(new Array(2),function(e){var n=new i.Picture;t(n.container).css({position:"absolute",top:0,left:0}).prepend(o._layers[e]=t(H.create("galleria-layer")).css({position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:2})[0]);o.$("images").append(n.container);o._controls[e]=n;var a=new i.Picture;a.isIframe=true;t(a.container).attr("class","galleria-frame").css({position:"absolute",top:0,left:0,zIndex:4,background:"#000",display:"none"}).appendTo(n.container);o._controls.frames[e]=a})}this.$("images").css({position:"relative",top:0,left:0,width:"100%",height:"100%"});if(s.swipe){this.$("images").css({position:"absolute",top:0,left:0,width:0,height:"100%"});this.finger=new i.Finger(this.get("stage"),{onchange:function(t){o.pause().show(t)},oncomplete:function(e){var i=g.max(0,g.min(parseInt(e,10),o.getDataLength()-1)),n=o.getData(i);t(o._thumbnails[i].container).addClass("active").siblings(".active").removeClass("active");if(!n){return}o.$("images").find(".galleria-frame").css("opacity",0).hide().find("iframe").remove();if(o._options.carousel&&o._options.carouselFollow){o._carousel.follow(i)}}});this.bind(i.RESCALE,function(){this.finger.setup()});this.$("stage").on("click",function(i){var a=o.getData();if(!a){return}if(a.iframe){if(o.isPlaying()){o.pause()}var r=o._controls.frames[o._active],s=o._stageWidth,l=o._stageHeight;if(t(r.container).find("iframe").length){return}t(r.container).css({width:s,height:l,opacity:0}).show().animate({opacity:1},200);e.setTimeout(function(){r.load(a.iframe+(a.video?"&autoplay=1":""),{width:s,height:l},function(t){o.$("container").addClass("videoplay");t.scale({width:o._stageWidth,height:o._stageHeight,iframelimit:a.video?o._options.maxVideoSize:n})})},100);return}if(a.link){if(o._options.popupLinks){var c=e.open(a.link,"_blank")}else{e.location.href=a.link}return}});this.bind(i.IMAGE,function(e){o.setCounter(e.index);o.setInfo(e.index);var i=this.getNext(),n=this.getPrev();var a=[n,i];a.push(this.getNext(i),this.getPrev(n),o._controls.slides.length-1);var r=[];t.each(a,function(e,i){if(t.inArray(i,r)==-1){r.push(i)}});t.each(r,function(e,i){var n=o.getData(i),a=o._controls.slides[i],r=o.isFullscreen()&&n.big?n.big:n.image||n.iframe;if(n.iframe&&!n.image){a.isIframe=true}if(!a.ready){o._controls.slides[i].load(r,function(e){if(!e.isIframe){t(e.image).css("visibility","hidden")}o._scaleImage(e,{complete:function(e){if(!e.isIframe){t(e.image).css({opacity:0,visibility:"visible"}).animate({opacity:1},200)}}})})}})})}this.$("thumbnails, thumbnails-list").css({overflow:"hidden",position:"relative"});this.$("image-nav-right, image-nav-left").on("click:fast",function(t){if(s.pauseOnInteraction){o.pause()}var e=/right/.test(this.className)?"next":"prev";o[e]()}).on("click",function(t){t.preventDefault();if(s.clicknext||s.swipe){t.stopPropagation()}});t.each(["info","counter","image-nav"],function(t,e){if(s["show"+e.substr(0,1).toUpperCase()+e.substr(1).replace(/-/,"")]===false){H.moveOut(o.get(e.toLowerCase()))}});this.load();if(!s.keepSource&&!y){this._target.innerHTML=""}if(this.get("errors")){this.appendChild("target","errors")}this.appendChild("target","container");if(s.carousel){var l=0,c=s.show;this.bind(i.THUMBNAIL,function(){this.updateCarousel();if(++l==this.getDataLength()&&typeof c=="number"&&c>0){this._carousel.follow(c)}})}if(s.responsive){r.on("resize",function(){if(!o.isFullscreen()){o.resize()}})}if(s.fullscreenDoubleTap){this.$("stage").on("touchstart",function(){var t,e,i,n,a,r,s=function(t){return t.originalEvent.touches?t.originalEvent.touches[0]:t};o.$("stage").on("touchmove",function(){t=0});return function(l){if(/(-left|-right)/.test(l.target.className)){return}r=H.timestamp();e=s(l).pageX;i=s(l).pageY;if(l.originalEvent.touches.length<2&&r-t<300&&e-n<20&&i-a<20){o.toggleFullscreen();l.preventDefault();return}t=r;n=e;a=i}}())}t.each(i.on.binds,function(e,i){if(t.inArray(i.hash,o._binds)==-1){o.bind(i.type,i.callback)}});return this},addTimer:function(){this._timer.add.apply(this._timer,H.array(arguments));return this},clearTimer:function(){this._timer.clear.apply(this._timer,H.array(arguments));return this},_getWH:function(){var e=this.$("container"),i=this.$("target"),n=this,a={},o;t.each(["width","height"],function(t,r){if(n._options[r]&&typeof n._options[r]==="number"){a[r]=n._options[r]}else{o=[H.parseValue(e.css(r)),H.parseValue(i.css(r)),e[r](),i[r]()];if(!n["_"+r]){o.splice(o.length,H.parseValue(e.css("min-"+r)),H.parseValue(i.css("min-"+r)))}a[r]=g.max.apply(g,o)}});if(n._userRatio){a.height=a.width*n._userRatio}return a},_createThumbnails:function(n){this.get("total").innerHTML=this.getDataLength();var o,r,s,l,c=this,u=this._options,h=n?this._data.length-n.length:0,f=h,d=[],p=0,g=y<8?"http://upload.wikimedia.org/wikipedia/commons/c/c0/Blank.gif":"data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D",m=function(){var t=c.$("thumbnails").find(".active");if(!t.length){return false}return t.find("img").attr("src")}(),v=typeof u.thumbnails==="string"?u.thumbnails.toLowerCase():null,_=function(t){return a.defaultView&&a.defaultView.getComputedStyle?a.defaultView.getComputedStyle(r.container,null)[t]:l.css(t)},b=function(e,n,a){return function(){t(a).append(e);c.trigger({type:i.THUMBNAIL,thumbTarget:e,index:n,galleriaData:c.getData(n)})}},w=function(e){if(u.pauseOnInteraction){c.pause()}var i=t(e.currentTarget).data("index");if(c.getIndex()!==i){c.show(i)}e.preventDefault()},x=function(e,n){t(e.container).css("visibility","visible");c.trigger({type:i.THUMBNAIL,thumbTarget:e.image,index:e.data.order,galleriaData:c.getData(e.data.order)});if(typeof n=="function"){n.call(c,e)}},T=function(e,i){e.scale({width:e.data.width,height:e.data.height,crop:u.thumbCrop,margin:u.thumbMargin,canvas:u.useCanvas,position:u.thumbPosition,complete:function(e){var n=["left","top"],a=["Width","Height"],o,r,s=c.getData(e.index);t.each(a,function(i,a){o=a.toLowerCase();if(u.thumbCrop!==true||u.thumbCrop===o){r={};r[o]=e[o];t(e.container).css(r);r={};r[n[i]]=0;t(e.image).css(r)}e["outer"+a]=t(e.container)["outer"+a](true)});H.toggleQuality(e.image,u.thumbQuality===true||u.thumbQuality==="auto"&&e.original.width<e.width*3);if(u.thumbDisplayOrder&&!e.lazy){t.each(d,function(t,e){if(t===p&&e.ready&&!e.displayed){p++;e.displayed=true;x(e,i);return}})}else{x(e,i)}}})};if(!n){this._thumbnails=[];this.$("thumbnails").empty()}for(;this._data[h];h++){s=this._data[h];o=s.thumb||s.image;if((u.thumbnails===true||v=="lazy")&&(s.thumb||s.image)){r=new i.Picture(h);r.index=h;r.displayed=false;r.lazy=false;r.video=false;this.$("thumbnails").append(r.container);l=t(r.container);l.css("visibility","hidden");r.data={width:H.parseValue(_("width")),height:H.parseValue(_("height")),order:h,src:o};if(u.thumbCrop!==true){l.css({width:"auto",height:"auto"})}else{l.css({width:r.data.width,height:r.data.height})}if(v=="lazy"){l.addClass("lazy");r.lazy=true;r.load(g,{height:r.data.height,width:r.data.width})}else{r.load(o,T)}if(u.preload==="all"){r.preload(s.image)}}else if(s.iframe&&v!==null||v==="empty"||v==="numbers"){r={container:H.create("galleria-image"),image:H.create("img","span"),ready:true,data:{order:h}};if(v==="numbers"){t(r.image).text(h+1)}if(s.iframe){t(r.image).addClass("iframe")}this.$("thumbnails").append(r.container);e.setTimeout(b(r.image,h,r.container),50+h*20)}else{r={container:null,image:null}}t(r.container).add(u.keepSource&&u.linkSourceImages?s.original:null).data("index",h).on(u.thumbEventType,w).data("thumbload",T);if(m===o){t(r.container).addClass("active")}this._thumbnails.push(r)}d=this._thumbnails.slice(f);return this},lazyLoad:function(e,i){var n=e.constructor==Array?e:[e],a=this,o=0;t.each(n,function(e,r){if(r>a._thumbnails.length-1){return}var s=a._thumbnails[r],l=s.data,c=function(){if(++o==n.length&&typeof i=="function"){i.call(a)}},u=t(s.container).data("thumbload");if(s.video){u.call(a,s,c)}else{s.load(l.src,function(t){u.call(a,t,c)})}});return this},lazyLoadChunks:function(t,i){var n=this.getDataLength(),a=0,o=0,r=[],s=[],l=this;i=i||0;for(;a<n;a++){s.push(a);if(++o==t||a==n-1){r.push(s);o=0;s=[]}}var c=function(t){var n=r.shift();if(n){e.setTimeout(function(){l.lazyLoad(n,function(){c(true)})},i&&t?i:0)}};c(false);return this},_run:function(){var a=this;a._createThumbnails();H.wait({timeout:1e4,until:function(){if(i.OPERA){a.$("stage").css("display","inline-block")}a._stageWidth=a.$("stage").width();a._stageHeight=a.$("stage").height();return a._stageWidth&&a._stageHeight>50},success:function(){E.push(a);if(a._options.swipe){var o=a.$("images").width(a.getDataLength()*a._stageWidth);t.each(new Array(a.getDataLength()),function(e){var n=new i.Picture,r=a.getData(e);t(n.container).css({position:"absolute",top:0,left:a._stageWidth*e}).prepend(a._layers[e]=t(H.create("galleria-layer")).css({position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:2})[0]).appendTo(o);if(r.video){O(n.container)}a._controls.slides.push(n);var s=new i.Picture;s.isIframe=true;t(s.container).attr("class","galleria-frame").css({position:"absolute",top:0,left:0,zIndex:4,background:"#000",display:"none"}).appendTo(n.container);a._controls.frames.push(s)});a.finger.setup()}H.show(a.get("counter"));if(a._options.carousel){a._carousel.bindControls()}if(a._options.autoplay){a.pause();if(typeof a._options.autoplay==="number"){a._playtime=a._options.autoplay}a._playing=true}if(a._firstrun){if(a._options.autoplay){a.trigger(i.PLAY)}if(typeof a._options.show==="number"){a.show(a._options.show)}return}a._firstrun=true;if(i.History){i.History.change(function(t){if(isNaN(t)){e.history.go(-1)}else{a.show(t,n,true)}})}a.trigger(i.READY);a.theme.init.call(a,a._options);t.each(i.ready.callbacks,function(t,e){if(typeof e=="function"){e.call(a,a._options)}});a._options.extend.call(a,a._options);if(/^[0-9]{1,4}$/.test(d)&&i.History){a.show(d,n,true)}else if(a._data[a._options.show]){a.show(a._options.show)}if(a._options.autoplay){a.trigger(i.PLAY)}},error:function(){i.raise("Stage width or height is too small to show the gallery. Traced measures: width:"+a._stageWidth+"px, height: "+a._stageHeight+"px.",true)}})},load:function(e,n,a){var o=this,r=this._options;this._data=[];this._thumbnails=[];this.$("thumbnails").empty();if(typeof n==="function"){a=n;n=null}e=e||r.dataSource;n=n||r.dataSelector;a=a||r.dataConfig;if(t.isPlainObject(e)){e=[e]}if(t.isArray(e)){if(this.validate(e)){this._data=e}else{i.raise("Load failed: JSON Array not valid.")}}else{n+=",.video,.iframe";t(e).find(n).each(function(e,i){i=t(i);var n={},r=i.parent(),s=r.attr("href"),l=r.attr("rel");if(s&&(i[0].nodeName=="IMG"||i.hasClass("video"))&&S(s)){n.video=s}else if(s&&i.hasClass("iframe")){n.iframe=s}else{n.image=n.big=s}if(l){n.big=l}t.each("big title description link layer image".split(" "),function(t,e){if(i.data(e)){n[e]=i.data(e).toString()}});if(!n.big){n.big=n.image}o._data.push(t.extend({title:i.attr("title")||"",thumb:i.attr("src"),image:i.attr("src"),big:i.attr("src"),description:i.attr("alt")||"",link:i.attr("longdesc"),original:i.get(0)},n,a(i)))})}if(typeof r.dataSort=="function"){s.sort.call(this._data,r.dataSort)}else if(r.dataSort=="random"){this._data.sort(function(){return g.round(g.random())-.5})}if(this.getDataLength()){this._parseData(function(){this.trigger(i.DATA)})}return this},_parseData:function(e){var i=this,a,o=false,r=function(){var n=true;t.each(i._data,function(t,e){if(e.loading){n=false;return false}});if(n&&!o){o=true;e.call(i)}};t.each(this._data,function(e,o){a=i._data[e];if("thumb"in o===false){a.thumb=o.image}if(!o.big){a.big=o.image}if("video"in o){var s=S(o.video);if(s){a.iframe=new I(s.provider,s.id).embed()+function(){if(typeof i._options[s.provider]=="object"){var e="?",n=[];t.each(i._options[s.provider],function(t,e){n.push(t+"="+e)});if(s.provider=="youtube"){n=["wmode=opaque"].concat(n)}return e+n.join("&")}return""}();if(!a.thumb||!a.image){t.each(["thumb","image"],function(t,e){if(e=="image"&&!i._options.videoPoster){a.image=n;return}var o=new I(s.provider,s.id);if(!a[e]){a.loading=true;o.getMedia(e,function(t,e){return function(i){t[e]=i;if(e=="image"&&!t.big){t.big=t.image}delete t.loading;r()}}(a,e))}})}}}});r();return this},destroy:function(){this.$("target").data("galleria",null);this.$("container").off("galleria");this.get("target").innerHTML=this._original.html;this.clearTimer();H.removeFromArray(D,this);H.removeFromArray(E,this);if(i._waiters.length){t.each(i._waiters,function(t,i){if(i)e.clearTimeout(i)})}return this},splice:function(){var t=this,i=H.array(arguments);e.setTimeout(function(){s.splice.apply(t._data,i);t._parseData(function(){t._createThumbnails()})},2);return t},push:function(){var t=this,i=H.array(arguments);if(i.length==1&&i[0].constructor==Array){i=i[0]}e.setTimeout(function(){s.push.apply(t._data,i);t._parseData(function(){t._createThumbnails(i)})},2);return t},_getActive:function(){return this._controls.getActive()},validate:function(t){return true},bind:function(t,e){t=k(t);this.$("container").on(t,this.proxy(e));return this},unbind:function(t){t=k(t);this.$("container").off(t);return this},trigger:function(e){e=typeof e==="object"?t.extend(e,{scope:this}):{type:k(e),scope:this};this.$("container").trigger(e);return this},addIdleState:function(t,e,i,n){this._idle.add.apply(this._idle,H.array(arguments));return this},removeIdleState:function(t){this._idle.remove.apply(this._idle,H.array(arguments));return this},enterIdleMode:function(){this._idle.hide();return this},exitIdleMode:function(){this._idle.showAll();return this},enterFullscreen:function(t){this._fullscreen.enter.apply(this,H.array(arguments));return this},exitFullscreen:function(t){this._fullscreen.exit.apply(this,H.array(arguments));return this},toggleFullscreen:function(t){this._fullscreen[this.isFullscreen()?"exit":"enter"].apply(this,H.array(arguments));return this},bindTooltip:function(t,e){this._tooltip.bind.apply(this._tooltip,H.array(arguments));return this},defineTooltip:function(t,e){this._tooltip.define.apply(this._tooltip,H.array(arguments));return this},refreshTooltip:function(t){this._tooltip.show.apply(this._tooltip,H.array(arguments));return this},openLightbox:function(){this._lightbox.show.apply(this._lightbox,H.array(arguments));return this},closeLightbox:function(){this._lightbox.hide.apply(this._lightbox,H.array(arguments));return this},hasVariation:function(e){return t.inArray(e,this._options.variation.split(/\s+/))>-1},getActiveImage:function(){var t=this._getActive();return t?t.image:n},getActiveThumb:function(){return this._thumbnails[this._active].image||n},getMousePosition:function(t){return{x:t.pageX-this.$("container").offset().left,y:t.pageY-this.$("container").offset().top}},addPan:function(e){if(this._options.imageCrop===false){return}e=t(e||this.getActiveImage());var i=this,n=e.width()/2,a=e.height()/2,o=parseInt(e.css("left"),10),r=parseInt(e.css("top"),10),s=o||0,l=r||0,c=0,u=0,h=false,f=H.timestamp(),d=0,p=0,m=function(t,i,n){if(t>0){p=g.round(g.max(t*-1,g.min(0,i)));if(d!==p){d=p;if(y===8){e.parent()["scroll"+n](p*-1)}else{var a={};a[n.toLowerCase()]=p;e.css(a)}}}},v=function(t){if(H.timestamp()-f<50){return}h=true;n=i.getMousePosition(t).x;a=i.getMousePosition(t).y},_=function(t){if(!h){return}c=e.width()-i._stageWidth;u=e.height()-i._stageHeight;o=n/i._stageWidth*c*-1;r=a/i._stageHeight*u*-1;s+=(o-s)/i._options.imagePanSmoothness;l+=(r-l)/i._options.imagePanSmoothness;m(u,l,"Top");m(c,s,"Left")};if(y===8){e.parent().scrollTop(l*-1).scrollLeft(s*-1);e.css({top:0,left:0})}this.$("stage").off("mousemove",v).on("mousemove",v);this.addTimer("pan"+i._id,_,50,true);return this},proxy:function(t,e){if(typeof t!=="function"){return m}e=e||this;return function(){return t.apply(e,H.array(arguments))}},getThemeName:function(){return this.theme.name},removePan:function(){this.$("stage").off("mousemove");this.clearTimer("pan"+this._id);return this},addElement:function(e){var i=this._dom;t.each(H.array(arguments),function(t,e){i[e]=H.create("galleria-"+e)});return this},attachKeyboard:function(t){this._keyboard.attach.apply(this._keyboard,H.array(arguments));return this},detachKeyboard:function(){this._keyboard.detach.apply(this._keyboard,H.array(arguments));return this},appendChild:function(t,e){this.$(t).append(this.get(e)||e);return this},prependChild:function(t,e){this.$(t).prepend(this.get(e)||e);return this},remove:function(t){this.$(H.array(arguments).join(",")).remove();return this},append:function(t){var e,i;for(e in t){if(t.hasOwnProperty(e)){if(t[e].constructor===Array){for(i=0;t[e][i];i++){this.appendChild(e,t[e][i])}}else{this.appendChild(e,t[e])}}}return this},_scaleImage:function(e,i){e=e||this._controls.getActive();if(!e){return}var n,a=function(e){t(e.container).children(":first").css({top:g.max(0,H.parseValue(e.image.style.top)),left:g.max(0,H.parseValue(e.image.style.left)),width:H.parseValue(e.image.width),height:H.parseValue(e.image.height)})};i=t.extend({width:this._stageWidth,height:this._stageHeight,crop:this._options.imageCrop,max:this._options.maxScaleRatio,min:this._options.minScaleRatio,margin:this._options.imageMargin,position:this._options.imagePosition,iframelimit:this._options.maxVideoSize},i);if(this._options.layerFollow&&this._options.imageCrop!==true){if(typeof i.complete=="function"){n=i.complete;i.complete=function(){n.call(e,e);a(e)}}else{i.complete=a}}else{t(e.container).children(":first").css({top:0,left:0})}e.scale(i);return this},updateCarousel:function(){this._carousel.update();return this},resize:function(e,i){if(typeof e=="function"){i=e;e=n}e=t.extend({width:0,height:0},e);var a=this,o=this.$("container");t.each(e,function(t,i){if(!i){o[t]("auto");e[t]=a._getWH()[t]}});t.each(e,function(t,e){o[t](e)});return this.rescale(i)},rescale:function(e,a,o){var r=this;if(typeof e==="function"){o=e;e=n}var s=function(){r._stageWidth=e||r.$("stage").width();r._stageHeight=a||r.$("stage").height();if(r._options.swipe){t.each(r._controls.slides,function(e,i){r._scaleImage(i);t(i.container).css("left",r._stageWidth*e)});r.$("images").css("width",r._stageWidth*r.getDataLength())}else{r._scaleImage()}if(r._options.carousel){r.updateCarousel()}var n=r._controls.frames[r._controls.active];if(n){r._controls.frames[r._controls.active].scale({width:r._stageWidth,height:r._stageHeight,iframelimit:r._options.maxVideoSize})}r.trigger(i.RESCALE);if(typeof o==="function"){o.call(r)}};s.call(r);return this},refreshImage:function(){this._scaleImage();if(this._options.imagePan){this.addPan()}return this},_preload:function(){if(this._options.preload){var t,e,n=this.getNext(),a;try{for(e=this._options.preload;e>0;e--){t=new i.Picture;a=this.getData(n);t.preload(this.isFullscreen()&&a.big?a.big:a.image);n=this.getNext(n)}}catch(o){}}},show:function(n,a,o){var r=this._options.swipe;if(!r&&(this._queue.length>3||n===false||!this._options.queue&&this._queue.stalled)){return}n=g.max(0,g.min(parseInt(n,10),this.getDataLength()-1));a=typeof a!=="undefined"?!!a:n<this.getIndex();o=o||false;if(!o&&i.History){i.History.set(n.toString());return}if(this.finger&&n!==this._active){this.finger.to=-(n*this.finger.width);this.finger.index=n}this._active=n;if(r){var l=this.getData(n),c=this;if(!l){return}var u=this.isFullscreen()&&l.big?l.big:l.image||l.iframe,h=this._controls.slides[n],f=h.isCached(u),d=this._thumbnails[n];var p={cached:f,index:n,rewind:a,imageTarget:h.image,thumbTarget:d.image,galleriaData:l};this.trigger(t.extend(p,{type:i.LOADSTART}));c.$("container").removeClass("videoplay");var m=function(){c._layers[n].innerHTML=c.getData().layer||"";c.trigger(t.extend(p,{type:i.LOADFINISH}));c._playCheck()};c._preload();e.setTimeout(function(){if(!h.ready||t(h.image).attr("src")!=u){if(l.iframe&&!l.image){h.isIframe=true}h.load(u,function(e){p.imageTarget=e.image;c._scaleImage(e,m).trigger(t.extend(p,{type:i.IMAGE}));m()})}else{c.trigger(t.extend(p,{type:i.IMAGE}));m()}},100)}else{s.push.call(this._queue,{index:n,rewind:a});if(!this._queue.stalled){this._show()}}return this},_show:function(){var a=this,o=this._queue[0],r=this.getData(o.index);if(!r){return}var l=this.isFullscreen()&&r.big?r.big:r.image||r.iframe,c=this._controls.getActive(),u=this._controls.getNext(),h=u.isCached(l),f=this._thumbnails[o.index],d=function(){t(u.image).trigger("mouseup")};a.$("container").toggleClass("iframe",!!r.isIframe).removeClass("videoplay");var p=function(o,r,l,c,u){return function(){var h;M.active=false;H.toggleQuality(r.image,a._options.imageQuality);a._layers[a._controls.active].innerHTML="";t(l.container).css({zIndex:0,opacity:0}).show();t(l.container).find("iframe, .galleria-videoicon").remove();t(a._controls.frames[a._controls.active].container).hide();t(r.container).css({zIndex:1,left:0,top:0}).show();a._controls.swap();if(a._options.imagePan){a.addPan(r.image)}if(o.iframe&&o.image||o.link||a._options.lightbox||a._options.clicknext){t(r.image).css({cursor:"pointer"}).on("mouseup",function(r){if(typeof r.which=="number"&&r.which>1){return}if(o.iframe){if(a.isPlaying()){a.pause()}var s=a._controls.frames[a._controls.active],l=a._stageWidth,c=a._stageHeight;t(s.container).css({width:l,height:c,opacity:0}).show().animate({opacity:1},200);e.setTimeout(function(){s.load(o.iframe+(o.video?"&autoplay=1":""),{width:l,height:c},function(t){a.$("container").addClass("videoplay");t.scale({width:a._stageWidth,height:a._stageHeight,iframelimit:o.video?a._options.maxVideoSize:n})})},100);return}if(a._options.clicknext&&!i.TOUCH){if(a._options.pauseOnInteraction){a.pause()}a.next();return}if(o.link){if(a._options.popupLinks){h=e.open(o.link,"_blank")}else{e.location.href=o.link}return}if(a._options.lightbox){a.openLightbox()}})}a._playCheck();a.trigger({type:i.IMAGE,index:c.index,imageTarget:r.image,thumbTarget:u.image,galleriaData:o});s.shift.call(a._queue);a._queue.stalled=false;if(a._queue.length){a._show()}}}(r,u,c,o,f);if(this._options.carousel&&this._options.carouselFollow){this._carousel.follow(o.index)}a._preload();H.show(u.container);u.isIframe=r.iframe&&!r.image;t(a._thumbnails[o.index].container).addClass("active").siblings(".active").removeClass("active");a.trigger({type:i.LOADSTART,cached:h,index:o.index,rewind:o.rewind,imageTarget:u.image,thumbTarget:f.image,galleriaData:r});a._queue.stalled=true;u.load(l,function(e){var s=t(a._layers[1-a._controls.active]).html(r.layer||"").hide();a._scaleImage(e,{complete:function(e){if("image"in c){H.toggleQuality(c.image,false)}H.toggleQuality(e.image,false);a.removePan();a.setInfo(o.index);a.setCounter(o.index);if(r.layer){s.show();if(r.iframe&&r.image||r.link||a._options.lightbox||a._options.clicknext){s.css("cursor","pointer").off("mouseup").mouseup(d)}}if(r.video&&r.image){O(e.container)}var l=a._options.transition;t.each({initial:c.image===null,touch:i.TOUCH,fullscreen:a.isFullscreen()},function(t,e){if(e&&a._options[t+"Transition"]!==n){l=a._options[t+"Transition"];return false}});if(l in M.effects===false){p()}else{var u={prev:c.container,next:e.container,rewind:o.rewind,speed:a._options.transitionSpeed||400};M.active=true;M.init.call(a,l,u,p)}a.trigger({type:i.LOADFINISH,cached:h,index:o.index,rewind:o.rewind,imageTarget:e.image,thumbTarget:a._thumbnails[o.index].image,galleriaData:a.getData(o.index)})}})})},getNext:function(t){t=typeof t==="number"?t:this.getIndex();return t===this.getDataLength()-1?0:t+1},getPrev:function(t){t=typeof t==="number"?t:this.getIndex();return t===0?this.getDataLength()-1:t-1},next:function(){if(this.getDataLength()>1){this.show(this.getNext(),false)}return this},prev:function(){if(this.getDataLength()>1){this.show(this.getPrev(),true)}return this},get:function(t){return t in this._dom?this._dom[t]:null},getData:function(t){return t in this._data?this._data[t]:this._data[this._active]},getDataLength:function(){return this._data.length},getIndex:function(){return typeof this._active==="number"?this._active:false},getStageHeight:function(){return this._stageHeight},getStageWidth:function(){return this._stageWidth},getOptions:function(t){return typeof t==="undefined"?this._options:this._options[t]},setOptions:function(e,i){if(typeof e==="object"){t.extend(this._options,e)}else{this._options[e]=i}return this},play:function(t){this._playing=true;this._playtime=t||this._playtime;this._playCheck();this.trigger(i.PLAY);return this},pause:function(){this._playing=false;this.trigger(i.PAUSE);return this},playToggle:function(t){return this._playing?this.pause():this.play(t)},isPlaying:function(){return this._playing},isFullscreen:function(){return this._fullscreen.active},_playCheck:function(){var t=this,e=0,n=20,a=H.timestamp(),o="play"+this._id;if(this._playing){this.clearTimer(o);var r=function(){e=H.timestamp()-a;if(e>=t._playtime&&t._playing){t.clearTimer(o);t.next();return}if(t._playing){t.trigger({type:i.PROGRESS,percent:g.ceil(e/t._playtime*100),seconds:g.floor(e/1e3),milliseconds:e});t.addTimer(o,r,n)}};t.addTimer(o,r,n)}},setPlaytime:function(t){this._playtime=t;return this},setIndex:function(t){this._active=t;return this},setCounter:function(t){if(typeof t==="number"){t++}else if(typeof t==="undefined"){t=this.getIndex()+1}this.get("current").innerHTML=t;if(y){var e=this.$("counter"),i=e.css("opacity");if(parseInt(i,10)===1){H.removeAlpha(e[0])}else{this.$("counter").css("opacity",i)}}return this},setInfo:function(e){var i=this,n=this.getData(e);t.each(["title","description"],function(t,e){var a=i.$("info-"+e);if(!!n[e]){a[n[e].length?"show":"hide"]().html(n[e])}else{a.empty().hide()}});return this},hasInfo:function(t){var e="title description".split(" "),i;for(i=0;e[i];i++){if(!!this.getData(t)[e[i]]){return true}}return false},jQuery:function(e){var i=this,n=[];t.each(e.split(","),function(e,a){a=t.trim(a);if(i.get(a)){n.push(a)}});var a=t(i.get(n.shift()));t.each(n,function(t,e){a=a.add(i.get(e))});return a},$:function(t){return this.jQuery.apply(this,H.array(arguments))}};t.each(x,function(t,e){var n=/_/.test(e)?e.replace(/_/g,""):e;i[e.toUpperCase()]="galleria."+n});t.extend(i,{IE9:y===9,IE8:y===8,IE7:y===7,IE6:y===6,IE:y,WEBKIT:/webkit/.test(f),CHROME:/chrome/.test(f),SAFARI:/safari/.test(f)&&!/chrome/.test(f),QUIRK:y&&a.compatMode&&a.compatMode==="BackCompat",MAC:/mac/.test(navigator.platform.toLowerCase()),OPERA:!!e.opera,IPHONE:/iphone/.test(f),IPAD:/ipad/.test(f),ANDROID:/android/.test(f),TOUCH:"ontouchstart"in a});i.addTheme=function(n){if(!n.name){i.raise("No theme name specified")}if(typeof n.defaults!=="object"){n.defaults={}}else{n.defaults=T(n.defaults)}var a=false,o;if(typeof n.css==="string"){t("link").each(function(t,e){o=new RegExp(n.css);if(o.test(e.href)){a=true;F(n);return false}});if(!a){t(function(){var r=0;var s=function(){t("script").each(function(t,i){o=new RegExp("galleria\\."+n.name.toLowerCase()+"\\.");if(o.test(i.src)){a=i.src.replace(/[^\/]*$/,"")+n.css;e.setTimeout(function(){H.loadCSS(a,"galleria-theme-"+n.name,function(){F(n)})},1)}});if(!a){if(r++>5){i.raise("No theme CSS loaded")}else{e.setTimeout(s,500)}}};s()})}}else{F(n)}return n};i.loadTheme=function(n,a){if(t("script").filter(function(){return t(this).attr("src")==n}).length){return}var o=false,r;t(e).load(function(){if(!o){r=e.setTimeout(function(){if(!o){i.raise("Galleria had problems loading theme at "+n+". Please check theme path or load manually.",true)}},2e4)}});H.loadScript(n,function(){o=true;e.clearTimeout(r)});return i};i.get=function(t){if(!!D[t]){return D[t]}else if(typeof t!=="number"){return D}else{i.raise("Gallery index "+t+" not found")}};i.configure=function(e,n){var a={};if(typeof e=="string"&&n){a[e]=n;e=a}else{t.extend(a,e)}i.configure.options=a;t.each(i.get(),function(t,e){e.setOptions(a)});return i};i.configure.options={};i.on=function(e,n){if(!e){return}n=n||m;var a=e+n.toString().replace(/\s/g,"")+H.timestamp();t.each(i.get(),function(t,i){i._binds.push(a);i.bind(e,n)});i.on.binds.push({type:e,callback:n,hash:a});return i};i.on.binds=[];i.run=function(e,n){if(t.isFunction(n)){n={extend:n}}t(e||"#galleria").galleria(n);return i};i.addTransition=function(t,e){M.effects[t]=e;return i};i.utils=H;i.log=function(){var i=H.array(arguments);if("console"in e&&"log"in e.console){try{return e.console.log.apply(e.console,i)}catch(n){t.each(i,function(){e.console.log(this)})}}else{return e.alert(i.join("<br>"))}};i.ready=function(e){if(typeof e!="function"){return i}t.each(E,function(t,i){e.call(i,i._options)});i.ready.callbacks.push(e);return i};i.ready.callbacks=[];i.raise=function(e,i){var n=i?"Fatal error":"Error",a={color:"#fff",position:"absolute",top:0,left:0,zIndex:1e5},o=function(e){var o='<div style="padding:4px;margin:0 0 2px;background:#'+(i?"811":"222")+';">'+(i?"<strong>"+n+": </strong>":"")+e+"</div>";t.each(D,function(){var t=this.$("errors"),e=this.$("target");if(!t.length){e.css("position","relative");t=this.addElement("errors").appendChild("target","errors").$("errors").css(a)}t.append(o)});if(!D.length){t("<div>").css(t.extend(a,{position:"fixed"})).append(o).appendTo(_().body) +}};if(c){o(e);if(i){throw new Error(n+": "+e)}}else if(i){if($){return}$=true;i=false;o("Gallery could not load.")}};i.version=l;i.getLoadedThemes=function(){return t.map(z,function(t){return t.name})};i.requires=function(t,e){e=e||"You need to upgrade Galleria to version "+t+" to use one or more components.";if(i.version<t){i.raise(e,true)}return i};i.Picture=function(e){this.id=e||null;this.image=null;this.container=H.create("galleria-image");t(this.container).css({overflow:"hidden",position:"relative"});this.original={width:0,height:0};this.ready=false;this.isIframe=false};i.Picture.prototype={cache:{},show:function(){H.show(this.image)},hide:function(){H.moveOut(this.image)},clear:function(){this.image=null},isCached:function(t){return!!this.cache[t]},preload:function(e){t(new Image).load(function(t,e){return function(){e[t]=t}}(e,this.cache)).attr("src",e)},load:function(n,a,o){if(typeof a=="function"){o=a;a=null}if(this.isIframe){var r="if"+(new Date).getTime();var s=this.image=t("<iframe>",{src:n,frameborder:0,id:r,allowfullscreen:true,css:{visibility:"hidden"}})[0];if(a){t(s).css(a)}t(this.container).find("iframe,img").remove();this.container.appendChild(this.image);t("#"+r).load(function(i,n){return function(){e.setTimeout(function(){t(i.image).css("visibility","visible");if(typeof n=="function"){n.call(i,i)}},10)}}(this,o));return this.container}this.image=new Image;if(i.IE8){t(this.image).css("filter","inherit")}if(!i.IE&&!i.CHROME&&!i.SAFARI){t(this.image).css("image-rendering","optimizequality")}var l=false,c=false,u=t(this.container),f=t(this.image),d=function(){if(!l){l=true;e.setTimeout(function(t,e){return function(){t.attr("src",e+(e.indexOf("?")>-1?"&":"?")+H.timestamp())}}(t(this),n),50)}else{if(h){t(this).attr("src",h)}else{i.raise("Image not found: "+n)}}},p=function(n,o,r){return function(){var s=function(){t(this).off("load");n.original=a||{height:this.height,width:this.width};if(i.HAS3D){this.style.MozTransform=this.style.webkitTransform="translate3d(0,0,0)"}u.append(this);n.cache[r]=r;if(typeof o=="function"){e.setTimeout(function(){o.call(n,n)},1)}};if(!this.width||!this.height){!function(e){H.wait({until:function(){return e.width&&e.height},success:function(){s.call(e)},error:function(){if(!c){t(new Image).load(p).attr("src",e.src);c=true}else{i.raise("Could not extract width/height from image: "+e.src+". Traced measures: width:"+e.width+"px, height: "+e.height+"px.")}},timeout:100})}(this)}else{s.call(this)}}}(this,o,n);u.find("iframe,img").remove();f.css("display","block");H.hide(this.image);t.each("minWidth minHeight maxWidth maxHeight".split(" "),function(t,e){f.css(e,/min/.test(e)?"0":"none")});f.load(p).on("error",d).attr("src",n);return this.container},scale:function(e){var a=this;e=t.extend({width:0,height:0,min:n,max:n,margin:0,complete:m,position:"center",crop:false,canvas:false,iframelimit:n},e);if(this.isIframe){var o=e.width,r=e.height,s,l;if(e.iframelimit){var c=g.min(e.iframelimit/o,e.iframelimit/r);if(c<1){s=o*c;l=r*c;t(this.image).css({top:r/2-l/2,left:o/2-s/2,position:"absolute"})}else{t(this.image).css({top:0,left:0})}}t(this.image).width(s||o).height(l||r).removeAttr("width").removeAttr("height");t(this.container).width(o).height(r);e.complete.call(a,a);try{if(this.image.contentWindow){t(this.image.contentWindow).trigger("resize")}}catch(u){}return this.container}if(!this.image){return this.container}var h,f,d=t(a.container),p;H.wait({until:function(){h=e.width||d.width()||H.parseValue(d.css("width"));f=e.height||d.height()||H.parseValue(d.css("height"));return h&&f},success:function(){var i=(h-e.margin*2)/a.original.width,n=(f-e.margin*2)/a.original.height,o=g.min(i,n),r=g.max(i,n),s={"true":r,width:i,height:n,"false":o,landscape:a.original.width>a.original.height?r:o,portrait:a.original.width<a.original.height?r:o},l=s[e.crop.toString()],c="";if(e.max){l=g.min(e.max,l)}if(e.min){l=g.max(e.min,l)}t.each(["width","height"],function(e,i){t(a.image)[i](a[i]=a.image[i]=g.round(a.original[i]*l))});t(a.container).width(h).height(f);if(e.canvas&&L){L.elem.width=a.width;L.elem.height=a.height;c=a.image.src+":"+a.width+"x"+a.height;a.image.src=L.cache[c]||function(t){L.context.drawImage(a.image,0,0,a.original.width*l,a.original.height*l);try{p=L.elem.toDataURL();L.length+=p.length;L.cache[t]=p;return p}catch(e){return a.image.src}}(c)}var u={},d={},m=function(e,i,n){var o=0;if(/\%/.test(e)){var r=parseInt(e,10)/100,s=a.image[i]||t(a.image)[i]();o=g.ceil(s*-1*r+n*r)}else{o=H.parseValue(e)}return o},v={top:{top:0},left:{left:0},right:{left:"100%"},bottom:{top:"100%"}};t.each(e.position.toLowerCase().split(" "),function(t,e){if(e==="center"){e="50%"}u[t?"top":"left"]=e});t.each(u,function(e,i){if(v.hasOwnProperty(i)){t.extend(d,v[i])}});u=u.top?t.extend(u,d):d;u=t.extend({top:"50%",left:"50%"},u);t(a.image).css({position:"absolute",top:m(u.top,"height",f),left:m(u.left,"width",h)});a.show();a.ready=true;e.complete.call(a,a)},error:function(){i.raise("Could not scale image: "+a.image.src)},timeout:1e3});return this}};t.extend(t.easing,{galleria:function(t,e,i,n,a){if((e/=a/2)<1){return n/2*e*e*e+i}return n/2*((e-=2)*e*e+2)+i},galleriaIn:function(t,e,i,n,a){return n*(e/=a)*e+i},galleriaOut:function(t,e,i,n,a){return-n*(e/=a)*(e-2)+i}});i.Finger=function(){var n=g.abs;var r=i.HAS3D=function(){var e=a.createElement("p"),i,n=["webkit","O","ms","Moz",""],o,r=0,s="transform";_().html.insertBefore(e,null);for(;n[r];r++){o=n[r]?n[r]+"Transform":s;if(e.style[o]!==undefined){e.style[o]="translate3d(1px,1px,1px)";i=t(e).css(n[r]?"-"+n[r].toLowerCase()+"-"+s:s)}}_().html.removeChild(e);return i!==undefined&&i.length>0&&i!=="none"}();var s=function(){var t="RequestAnimationFrame";return e.requestAnimationFrame||e["webkit"+t]||e["moz"+t]||e["o"+t]||e["ms"+t]||function(t){e.setTimeout(t,1e3/60)}}();var l=function(i,n){this.config={start:0,duration:500,onchange:function(){},oncomplete:function(){},easing:function(t,e,i,n,a){return-n*((e=e/a-1)*e*e*e-1)+i}};this.easeout=function(t,e,i,n,a){return n*((e=e/a-1)*e*e*e*e+1)+i};if(!i.children.length){return}var a=this;t.extend(this.config,n);this.elem=i;this.child=i.children[0];this.to=this.pos=0;this.touching=false;this.start={};this.index=this.config.start;this.anim=0;this.easing=this.config.easing;if(!r){this.child.style.position="absolute";this.elem.style.position="relative"}t.each(["ontouchstart","ontouchmove","ontouchend","setup"],function(t,e){a[e]=function(t){return function(){t.apply(a,arguments)}}(a[e])});this.setX=function(){var t=a.child.style;if(!r){t.left=a.pos+"px";return}t.MozTransform=t.webkitTransform=t.transform="translate3d("+a.pos+"px,0,0)";return};t(i).on("touchstart",this.ontouchstart);t(e).on("resize",this.setup);t(e).on("orientationchange",this.setup);this.setup();!function o(){s(o);a.loop.call(a)}()};l.prototype={constructor:l,setup:function(){this.width=t(this.elem).width();this.length=g.ceil(t(this.child).width()/this.width);if(this.index!==0){this.index=g.max(0,g.min(this.index,this.length-1));this.pos=this.to=-this.width*this.index}},setPosition:function(t){this.pos=t;this.to=t},ontouchstart:function(t){var e=t.originalEvent.touches;this.start={pageX:e[0].pageX,pageY:e[0].pageY,time:+new Date};this.isScrolling=null;this.touching=true;this.deltaX=0;o.on("touchmove",this.ontouchmove);o.on("touchend",this.ontouchend)},ontouchmove:function(t){var e=t.originalEvent.touches;if(e&&e.length>1||t.scale&&t.scale!==1){return}this.deltaX=e[0].pageX-this.start.pageX;if(this.isScrolling===null){this.isScrolling=!!(this.isScrolling||g.abs(this.deltaX)<g.abs(e[0].pageY-this.start.pageY))}if(!this.isScrolling){t.preventDefault();this.deltaX/=!this.index&&this.deltaX>0||this.index==this.length-1&&this.deltaX<0?g.abs(this.deltaX)/this.width+1.8:1;this.to=this.deltaX-this.index*this.width}t.stopPropagation()},ontouchend:function(t){this.touching=false;var e=+new Date-this.start.time<250&&g.abs(this.deltaX)>40||g.abs(this.deltaX)>this.width/2,i=!this.index&&this.deltaX>0||this.index==this.length-1&&this.deltaX<0;if(!this.isScrolling){this.show(this.index+(e&&!i?this.deltaX<0?1:-1:0))}o.off("touchmove",this.ontouchmove);o.off("touchend",this.ontouchend)},show:function(t){if(t!=this.index){this.config.onchange.call(this,t)}else{this.to=-(t*this.width)}},moveTo:function(t){if(t!=this.index){this.pos=this.to=-(t*this.width);this.index=t}},loop:function(){var t=this.to-this.pos,e=1;if(this.width&&t){e=g.max(.5,g.min(1.5,g.abs(t/this.width)))}if(this.touching||g.abs(t)<=1){this.pos=this.to;t=0;if(this.anim&&!this.touching){this.config.oncomplete(this.index)}this.anim=0;this.easing=this.config.easing}else{if(!this.anim){this.anim={start:this.pos,time:+new Date,distance:t,factor:e,destination:this.to}}var i=+new Date-this.anim.time;var n=this.config.duration*this.anim.factor;if(i>n||this.anim.destination!=this.to){this.anim=0;this.easing=this.easeout;return}this.pos=this.easing(null,i,this.anim.start,this.anim.distance,n)}this.setX()}};return l}();t.fn.galleria=function(e){var n=this.selector;if(!t(this).length){t(function(){if(t(n).length){t(n).galleria(e)}else{i.utils.wait({until:function(){return t(n).length},success:function(){t(n).galleria(e)},error:function(){i.raise('Init failed: Galleria could not find the element "'+n+'".')},timeout:5e3})}});return this}return this.each(function(){if(t.data(this,"galleria")){t.data(this,"galleria").destroy();t(this).find("*").hide()}t.data(this,"galleria",(new i).init(this,e))})};if(typeof module==="object"&&module&&typeof module.exports==="object"){module.exports=i}else{e.Galleria=i;if(typeof define==="function"&&define.amd){define("galleria",["jquery"],function(){return i})}}}(jQuery,this); \ No newline at end of file diff --git a/src/static/galleria/plugins/flickr/flickr-demo.html b/src/static/galleria/plugins/flickr/flickr-demo.html new file mode 100644 index 0000000..d427405 --- /dev/null +++ b/src/static/galleria/plugins/flickr/flickr-demo.html @@ -0,0 +1,62 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Galleria Flickr Plugin</title> + <style> + + /* Demo styles */ + html,body{background:#222;margin:0;} + body{border-top:4px solid #000;} + .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;} + h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;} + p{margin:0 0 20px} + a {color:#22BCB9;text-decoration:none;} + .cred{margin-top:20px;font-size:11px;} + + /* This rule is read by Galleria to define the gallery height: */ + #galleria{height:320px;} + + </style> + + <!-- load jQuery --> + <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script> + + <!-- load Galleria --> + <script src="../../galleria-1.4.2.min.js"></script> + + <!-- load flickr plugin --> + <script src="galleria.flickr.min.js"></script> + + </head> +<body> + <div class="content"> + <h1>Galleria Flickr Plugin Demo</h1> + <p>Demonstrating a basic gallery example with a Flickr search.</p> + + <!-- Adding gallery images. This is just a container for the dynamic flickr images --> + + <div id="galleria"></div> + + <p class="cred">Made by <a href="http://galleria.aino.se">Galleria</a>.</p> + <a href="#" id="close">cloase</a> + </div> + <script> + + // Load the classic theme + Galleria.loadTheme('../../themes/classic/galleria.classic.min.js'); + + // Initialize Galleria + Galleria.run('#galleria', { + + // search flickr for "galleria" + flickr: 'search:galleria', + + flickrOptions: { + // sort by interestingness + sort: 'interestingness-desc' + } + }); + </script> + </body> +</html> \ No newline at end of file diff --git a/src/static/galleria/plugins/flickr/flickr-loader.gif b/src/static/galleria/plugins/flickr/flickr-loader.gif new file mode 100755 index 0000000000000000000000000000000000000000..beaacacc93292a68ac6f21016d8affad0f9cca16 GIT binary patch literal 2129 zcmbW1ZA=q)9LN8Cq}L*JD2R+=!KbdY=Z3IZH?vZZA|jSqx^e|P3i4184#d)y0)2); zz-{S(OhxBrVzjtAaK(rT55^durUVzvIzx=hnl4LROcwTL?5;((DVc$LaqsT;@cn&0 zC*7U3T~rzi!oh>BzzYswU<U_8dVmTfmj-|yu-1Xh0U#X&s+%C@9T7<ItUtLgbHW>c z0^5EmTRL?#`FynML4eWynALkdW<a#}21hv^pqe99)2CU7yp#%da<xP{4ynG!=-CYE zX>8kh52cK=`Cx$VIL^{=K0H>&%C#nc&H11Y$~^9k8(07~Q04;wEG#VG?`1uS3#`0d z^8Fd<vRx_g+Y}Q1apIp;2!O3XKola@1oYkFevG$<3hZPqm%HO+H>oCvBN$YgT{k(Y z7q5Zl+f0)aq^!jfVrFI}s(HuolV>9*cCP*L&S3;AIV{O9SJ*SMvU76L^rfmJcy)gY zJNL_IXc%I2%1%E<OFb86Cz6<H@vy?Jd-{Y44Rz@5FbC|NeO4iTtl0U3tyk!K)?yU2 z)i)frXzQyqmb&^9)L7mO?=PrDToR&NUeS{6%EkS%DlRt)y5^_w)&SB3#+Sz<vwil7 zfFX><|NV=r*j2yTm2*SA-oHJWn>DJ65XEuxd|M19wAOZWu~n|E(>si{&6uM}PA^wh zm^ErxQKxD|k7Wki%4#x}Y<x)Ee@`sl7{#!p^B90h6N|ZSe#DUbk5kHU<=j&=KMlR) zckymltU3#m4S!X6DUxgPzj=m95~u}P-BwC7TMO+DK__hJYV9#KbP132=-`SjjiX*s zSyfb`Ei1^_CEdLT-n%b<e?e#h=6~<lAnw2Qe1gSuqM-@cFx~CZd1BR<{MK|3b0v&S zHatqA`g97AF5Lk1bpUEbAevcCv)P3m&QhAOr~MNFXzbDUk?568np!6Ye|)MKKA<np z4W<C+$v%=xR-8js!CQ+tJn9;GNJ_NyI($<=0vVC0c9dqZ6*@Yca7%Yvhq<BqNQXcV zSJ*Tip&Xi*$l)cPUm!sJh59c9YQLHcd`l+~5WdHI^o=WrcSZGSDvrR|Ew)H}e6(^? zBhA>RG*w&VTARMQrPhWu5(v~+R#R%^ivFS!R2@74egXNCt1qH19?T6p6GHvoIpodH z3DjjnbM%7*>T^xWlQ`;(wAe}VSTS_DV3O~9W)K>2)Xhye>gHM;b%UBfU8DSe)Pvrp zve{0m1;xGX%BacN$s1H!T{m~8Ud$vn`;tsfM#|cTgv~QEnYg#!<$D`NO+A};ostyW zDSNDzRgYYlwI(s6!+8q#JiZLY-KqO2X}}I*Y{IOuVp^ZAcQ4_saE0Cmy%~2}vp2G- zQy9M}T&Yx?xgRh@GV!CG!M(M*;%=xn_;uY}`e-3r6qgA5HW^BwSG*-J&s!NAtYMl= z;^2RSI>B}0y12C-Sv)fLG(A5W_x3aX?K;lc3&4<2?S&-c@vANlzagQuAW?0lP|#c9 z3vUH0@pjMR1iZy_qM-@cxW1nGQ-rtXaopQT2Qb`avVHS0B(apj*4Hs;tq2V=t09|R zfO`uO-U=Cnw^Z`-y?t#CRr$|zxN8`BNKG{LYJF1-3C)PCZbzY)y%ny&+Ykbkwto<q z6--SBzKb9b5N?BUZ{v7Z3XeA72#no|5J`$gE4MU4uX;-+ybW81w^7u0W2gD$A=Jmu oA?x}G)MZ2H^`8mU=Td*YPoSPQdtZX1e)-6B4(_eswcft}H=AX&%>V!Z literal 0 HcmV?d00001 diff --git a/src/static/galleria/plugins/flickr/galleria.flickr.js b/src/static/galleria/plugins/flickr/galleria.flickr.js new file mode 100644 index 0000000..fe1c4b9 --- /dev/null +++ b/src/static/galleria/plugins/flickr/galleria.flickr.js @@ -0,0 +1,383 @@ +/** + * Galleria Flickr Plugin 2012-09-04 + * http://galleria.io + * + * Licensed under the MIT license + * https://raw.github.com/aino/galleria/master/LICENSE + * + */ + +(function($) { + +/*global jQuery, Galleria, window */ + +Galleria.requires(1.25, 'The Flickr Plugin requires Galleria version 1.2.5 or later.'); + +// The script path +var PATH = Galleria.utils.getScriptPath(); + +/** + + @class + @constructor + + @example var flickr = new Galleria.Flickr(); + + @author http://galleria.io + + @requires jQuery + @requires Galleria + + @param {String} [api_key] Flickr API key to be used, defaults to the Galleria key + + @returns Instance +*/ + +Galleria.Flickr = function( api_key ) { + + this.api_key = api_key || '2a2ce06c15780ebeb0b706650fc890b2'; + + this.options = { + max: 30, // photos to return + imageSize: 'medium', // photo size ( thumb,small,medium,big,original ) + thumbSize: 'thumb', // thumbnail size ( thumb,small,medium,big,original ) + sort: 'interestingness-desc', // sort option ( date-posted-asc, date-posted-desc, date-taken-asc, date-taken-desc, interestingness-desc, interestingness-asc, relevance ) + description: false, // set this to true to get description as caption + complete: function(){}, // callback to be called inside the Galleria.prototype.load + backlink: false // set this to true if you want to pass a link back to the original image + }; +}; + +Galleria.Flickr.prototype = { + + // bring back the constructor reference + + constructor: Galleria.Flickr, + + /** + Search for anything at Flickr + + @param {String} phrase The string to search for + @param {Function} [callback] The callback to be called when the data is ready + + @returns Instance + */ + + search: function( phrase, callback ) { + return this._find({ + text: phrase + }, callback ); + }, + + /** + Search for anything at Flickr by tag + + @param {String} tag The tag(s) to search for + @param {Function} [callback] The callback to be called when the data is ready + + @returns Instance + */ + + tags: function( tag, callback ) { + return this._find({ + tags: tag + }, callback); + }, + + /** + Get a user's public photos + + @param {String} username The username as shown in the URL to fetch + @param {Function} [callback] The callback to be called when the data is ready + + @returns Instance + */ + + user: function( username, callback ) { + return this._call({ + method: 'flickr.urls.lookupUser', + url: 'flickr.com/photos/' + username + }, function( data ) { + this._find({ + user_id: data.user.id, + method: 'flickr.people.getPublicPhotos' + }, callback); + }); + }, + + /** + Get photos from a photoset by ID + + @param {String|Number} photoset_id The photoset id to fetch + @param {Function} [callback] The callback to be called when the data is ready + + @returns Instance + */ + + set: function( photoset_id, callback ) { + return this._find({ + photoset_id: photoset_id, + method: 'flickr.photosets.getPhotos' + }, callback); + }, + + /** + Get photos from a gallery by ID + + @param {String|Number} gallery_id The gallery id to fetch + @param {Function} [callback] The callback to be called when the data is ready + + @returns Instance + */ + + gallery: function( gallery_id, callback ) { + return this._find({ + gallery_id: gallery_id, + method: 'flickr.galleries.getPhotos' + }, callback); + }, + + /** + Search groups and fetch photos from the first group found + Useful if you know the exact name of a group and want to show the groups photos. + + @param {String} group The group name to search for + @param {Function} [callback] The callback to be called when the data is ready + + @returns Instance + */ + + groupsearch: function( group, callback ) { + return this._call({ + text: group, + method: 'flickr.groups.search' + }, function( data ) { + this.group( data.groups.group[0].nsid, callback ); + }); + }, + + /** + Get photos from a group by ID + + @param {String} group_id The group id to fetch + @param {Function} [callback] The callback to be called when the data is ready + + @returns Instance + */ + + group: function ( group_id, callback ) { + return this._find({ + group_id: group_id, + method: 'flickr.groups.pools.getPhotos' + }, callback ); + }, + + /** + Set flickr options + + @param {Object} options The options object to blend + + @returns Instance + */ + + setOptions: function( options ) { + $.extend(this.options, options); + return this; + }, + + + // call Flickr and raise errors + + _call: function( params, callback ) { + + var url = 'https://api.flickr.com/services/rest/?'; + + var scope = this; + + params = $.extend({ + format : 'json', + jsoncallback : '?', + api_key: this.api_key + }, params ); + + $.each(params, function( key, value ) { + url += '&' + key + '=' + value; + }); + + $.getJSON(url, function(data) { + if ( data.stat === 'ok' ) { + callback.call(scope, data); + } else { + Galleria.raise( data.code.toString() + ' ' + data.stat + ': ' + data.message, true ); + } + }); + return scope; + }, + + + // "hidden" way of getting a big image (~1024) from flickr + + _getBig: function( photo ) { + + if ( photo.url_l ) { + return photo.url_l; + } else if ( parseInt( photo.width_o, 10 ) > 1280 ) { + + return 'https://farm'+photo.farm + '.static.flickr.com/'+photo.server + + '/' + photo.id + '_' + photo.secret + '_b.jpg'; + } + + return photo.url_o || photo.url_z || photo.url_m; + + }, + + + // get image size by option name + + _getSize: function( photo, size ) { + + var img; + + switch(size) { + + case 'thumb': + img = photo.url_t; + break; + + case 'small': + img = photo.url_s; + break; + + case 'big': + img = this._getBig( photo ); + break; + + case 'original': + img = photo.url_o ? photo.url_o : this._getBig( photo ); + break; + + default: + img = photo.url_z || photo.url_m; + break; + } + return img; + }, + + + // ask flickr for photos, parse the result and call the callback with the galleria-ready data array + + _find: function( params, callback ) { + + params = $.extend({ + method: 'flickr.photos.search', + extras: 'url_t,url_m,url_o,url_s,url_l,url_z,description', + sort: this.options.sort, + per_page: Math.min( this.options.max, 500 ) + }, params ); + + return this._call( params, function(data) { + + var gallery = [], + photos = data.photos ? data.photos.photo : data.photoset.photo, + len = photos.length, + photo, + i; + + for ( i=0; i<len; i++ ) { + + photo = photos[i]; + + gallery.push({ + thumb: this._getSize( photo, this.options.thumbSize ), + image: this._getSize( photo, this.options.imageSize ), + big: this._getBig( photo ), + title: photos[i].title, + description: this.options.description && photos[i].description ? photos[i].description._content : '', + link: this.options.backlink ? 'https://flickr.com/photos/' + photo.owner + '/' + photo.id : '' + }); + } + callback.call( this, gallery ); + }); + } +}; + + +/** + Galleria modifications + We fake-extend the load prototype to make Flickr integration as simple as possible +*/ + + +// save the old prototype in a local variable + +var load = Galleria.prototype.load; + + +// fake-extend the load prototype using the flickr data + +Galleria.prototype.load = function() { + + // pass if no data is provided or flickr option not found + if ( arguments.length || typeof this._options.flickr !== 'string' ) { + load.apply( this, Galleria.utils.array( arguments ) ); + return; + } + + // define some local vars + var self = this, + args = Galleria.utils.array( arguments ), + flickr = this._options.flickr.split(':'), + f, + opts = $.extend({}, self._options.flickrOptions), + loader = typeof opts.loader !== 'undefined' ? + opts.loader : $('<div>').css({ + width: 48, + height: 48, + opacity: 0.7, + background:'#000 url('+PATH+'loader.gif) no-repeat 50% 50%' + }); + + if ( flickr.length ) { + + // validate the method + if ( typeof Galleria.Flickr.prototype[ flickr[0] ] !== 'function' ) { + Galleria.raise( flickr[0] + ' method not found in Flickr plugin' ); + return load.apply( this, args ); + } + + // validate the argument + if ( !flickr[1] ) { + Galleria.raise( 'No flickr argument found' ); + return load.apply( this, args ); + } + + // apply the preloader + window.setTimeout(function() { + self.$( 'target' ).append( loader ); + },100); + + // create the instance + f = new Galleria.Flickr(); + + // apply Flickr options + if ( typeof self._options.flickrOptions === 'object' ) { + f.setOptions( self._options.flickrOptions ); + } + + // call the flickr method and trigger the DATA event + f[ flickr[0] ]( flickr[1], function( data ) { + + self._data = data; + loader.remove(); + self.trigger( Galleria.DATA ); + f.options.complete.call(f, data); + + }); + } else { + + // if flickr array not found, pass + load.apply( this, args ); + } +}; + +}( jQuery ) ); \ No newline at end of file diff --git a/src/static/galleria/plugins/flickr/galleria.flickr.min.js b/src/static/galleria/plugins/flickr/galleria.flickr.min.js new file mode 100644 index 0000000..1779afe --- /dev/null +++ b/src/static/galleria/plugins/flickr/galleria.flickr.min.js @@ -0,0 +1 @@ +!function(t){Galleria.requires(1.25,"The Flickr Plugin requires Galleria version 1.2.5 or later.");var i=Galleria.utils.getScriptPath();Galleria.Flickr=function(t){this.api_key=t||"2a2ce06c15780ebeb0b706650fc890b2";this.options={max:30,imageSize:"medium",thumbSize:"thumb",sort:"interestingness-desc",description:false,complete:function(){},backlink:false}};Galleria.Flickr.prototype={constructor:Galleria.Flickr,search:function(t,i){return this._find({text:t},i)},tags:function(t,i){return this._find({tags:t},i)},user:function(t,i){return this._call({method:"flickr.urls.lookupUser",url:"flickr.com/photos/"+t},function(t){this._find({user_id:t.user.id,method:"flickr.people.getPublicPhotos"},i)})},set:function(t,i){return this._find({photoset_id:t,method:"flickr.photosets.getPhotos"},i)},gallery:function(t,i){return this._find({gallery_id:t,method:"flickr.galleries.getPhotos"},i)},groupsearch:function(t,i){return this._call({text:t,method:"flickr.groups.search"},function(t){this.group(t.groups.group[0].nsid,i)})},group:function(t,i){return this._find({group_id:t,method:"flickr.groups.pools.getPhotos"},i)},setOptions:function(i){t.extend(this.options,i);return this},_call:function(i,e){var r="https://api.flickr.com/services/rest/?";var o=this;i=t.extend({format:"json",jsoncallback:"?",api_key:this.api_key},i);t.each(i,function(t,i){r+="&"+t+"="+i});t.getJSON(r,function(t){if(t.stat==="ok"){e.call(o,t)}else{Galleria.raise(t.code.toString()+" "+t.stat+": "+t.message,true)}});return o},_getBig:function(t){if(t.url_l){return t.url_l}else if(parseInt(t.width_o,10)>1280){return"https://farm"+t.farm+".static.flickr.com/"+t.server+"/"+t.id+"_"+t.secret+"_b.jpg"}return t.url_o||t.url_z||t.url_m},_getSize:function(t,i){var e;switch(i){case"thumb":e=t.url_t;break;case"small":e=t.url_s;break;case"big":e=this._getBig(t);break;case"original":e=t.url_o?t.url_o:this._getBig(t);break;default:e=t.url_z||t.url_m;break}return e},_find:function(i,e){i=t.extend({method:"flickr.photos.search",extras:"url_t,url_m,url_o,url_s,url_l,url_z,description",sort:this.options.sort,per_page:Math.min(this.options.max,500)},i);return this._call(i,function(t){var i=[],r=t.photos?t.photos.photo:t.photoset.photo,o=r.length,s,l;for(l=0;l<o;l++){s=r[l];i.push({thumb:this._getSize(s,this.options.thumbSize),image:this._getSize(s,this.options.imageSize),big:this._getBig(s),title:r[l].title,description:this.options.description&&r[l].description?r[l].description._content:"",link:this.options.backlink?"https://flickr.com/photos/"+s.owner+"/"+s.id:""})}e.call(this,i)})}};var e=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||typeof this._options.flickr!=="string"){e.apply(this,Galleria.utils.array(arguments));return}var r=this,o=Galleria.utils.array(arguments),s=this._options.flickr.split(":"),l,n=t.extend({},r._options.flickrOptions),a=typeof n.loader!=="undefined"?n.loader:t("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+i+"loader.gif) no-repeat 50% 50%"});if(s.length){if(typeof Galleria.Flickr.prototype[s[0]]!=="function"){Galleria.raise(s[0]+" method not found in Flickr plugin");return e.apply(this,o)}if(!s[1]){Galleria.raise("No flickr argument found");return e.apply(this,o)}window.setTimeout(function(){r.$("target").append(a)},100);l=new Galleria.Flickr;if(typeof r._options.flickrOptions==="object"){l.setOptions(r._options.flickrOptions)}l[s[0]](s[1],function(t){r._data=t;a.remove();r.trigger(Galleria.DATA);l.options.complete.call(l,t)})}else{e.apply(this,o)}}}(jQuery); \ No newline at end of file diff --git a/src/static/galleria/plugins/flickr/loader.gif b/src/static/galleria/plugins/flickr/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..27df81f46d9fe7398b9daf3d0f5fc97337d93750 GIT binary patch literal 1849 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 literal 0 HcmV?d00001 diff --git a/src/static/galleria/plugins/history/galleria.history.js b/src/static/galleria/plugins/history/galleria.history.js new file mode 100644 index 0000000..6b13c36 --- /dev/null +++ b/src/static/galleria/plugins/history/galleria.history.js @@ -0,0 +1,146 @@ +/** + * Galleria History Plugin 2012-04-04 + * http://galleria.io + * + * Licensed under the MIT license + * https://raw.github.com/aino/galleria/master/LICENSE + * + */ + +(function( $, window ) { + +/*global jQuery, Galleria, window */ + +Galleria.requires(1.25, 'The History Plugin requires Galleria version 1.2.5 or later.'); + +Galleria.History = (function() { + + var onloads = [], + + init = false, + + loc = window.location, + + doc = window.document, + + ie = Galleria.IE, + + support = 'onhashchange' in window && ( doc.mode === undefined || doc.mode > 7 ), + + iframe, + + get = function( winloc ) { + if( iframe && !support && Galleria.IE ) { + winloc = winloc || iframe.location; + } else { + winloc = loc; + } + return parseInt( winloc.hash.substr(2), 10 ); + }, + + saved = get( loc ), + + callbacks = [], + + onchange = function() { + $.each( callbacks, function( i, fn ) { + fn.call( window, get() ); + }); + }, + + ready = function() { + $.each( onloads, function(i, fn) { + fn(); + }); + + init = true; + }, + + setHash = function( val ) { + return '/' + val; + }; + + // always remove support if IE < 8 + if ( support && ie < 8 ) { + support = false; + } + + if ( !support ) { + + $(function() { + + var interval = window.setInterval(function() { + + var hash = get(); + + if ( !isNaN( hash ) && hash != saved ) { + saved = hash; + loc.hash = setHash( hash ); + onchange(); + } + + }, 50); + + if ( ie ) { + + $('<iframe tabindex="-1" title="empty">').hide().attr( 'src', 'about:blank' ).one('load', function() { + + iframe = this.contentWindow; + + ready(); + + }).insertAfter(doc.body); + + } else { + ready(); + } + }); + } else { + ready(); + } + + return { + + change: function( fn ) { + + callbacks.push( fn ); + + if( support ) { + window.onhashchange = onchange; + } + }, + + set: function( val ) { + + if ( isNaN( val ) ) { + return; + } + + if ( !support && ie ) { + + this.ready(function() { + + var idoc = iframe.document; + idoc.open(); + idoc.close(); + + iframe.location.hash = setHash( val ); + + }); + } + + loc.hash = setHash( val ); + }, + + ready: function(fn) { + if (!init) { + onloads.push(fn); + } else { + fn(); + } + } + }; +}()); + +}( jQuery, this )); + diff --git a/src/static/galleria/plugins/history/galleria.history.min.js b/src/static/galleria/plugins/history/galleria.history.min.js new file mode 100644 index 0000000..59f9c82 --- /dev/null +++ b/src/static/galleria/plugins/history/galleria.history.min.js @@ -0,0 +1 @@ +!function(n,e){Galleria.requires(1.25,"The History Plugin requires Galleria version 1.2.5 or later.");Galleria.History=function(){var i=[],t=false,a=e.location,o=e.document,r=Galleria.IE,s="onhashchange"in e&&(o.mode===undefined||o.mode>7),u,c=function(n){if(u&&!s&&Galleria.IE){n=n||u.location}else{n=a}return parseInt(n.hash.substr(2),10)},f=c(a),l=[],h=function(){n.each(l,function(n,i){i.call(e,c())})},d=function(){n.each(i,function(n,e){e()});t=true},y=function(n){return"/"+n};if(s&&r<8){s=false}if(!s){n(function(){var i=e.setInterval(function(){var n=c();if(!isNaN(n)&&n!=f){f=n;a.hash=y(n);h()}},50);if(r){n('<iframe tabindex="-1" title="empty">').hide().attr("src","about:blank").one("load",function(){u=this.contentWindow;d()}).insertAfter(o.body)}else{d()}})}else{d()}return{change:function(n){l.push(n);if(s){e.onhashchange=h}},set:function(n){if(isNaN(n)){return}if(!s&&r){this.ready(function(){var e=u.document;e.open();e.close();u.location.hash=y(n)})}a.hash=y(n)},ready:function(n){if(!t){i.push(n)}else{n()}}}}()}(jQuery,this); \ No newline at end of file diff --git a/src/static/galleria/plugins/history/history-demo.html b/src/static/galleria/plugins/history/history-demo.html new file mode 100644 index 0000000..4cca075 --- /dev/null +++ b/src/static/galleria/plugins/history/history-demo.html @@ -0,0 +1,100 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Galleria History Plugin</title> + <style> + + /* Demo styles */ + html,body{background:#222;margin:0;} + body{border-top:4px solid #000;} + .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;} + h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;} + p{margin:0 0 20px} + a {color:#22BCB9;text-decoration:none;} + .cred{margin-top:20px;font-size:11px;} + + /* This rule is read by Galleria to define the gallery height: */ + #galleria{height:320px} + + </style> + + <!-- load jQuery --> + <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script> + + <!-- load Galleria --> + <script src="../../galleria-1.4.2.min.js"></script> + + <!-- load the History plugin, no need for further scripting --> + <script src="galleria.history.min.js"></script> + + </head> +<body> + <div class="content"> + <h1>Galleria History Plugin</h1> + <p>Demonstrating a basic history example. Supports most browsers, including FF 3.0+ and IE 7+</p> + + <!-- Adding gallery images. We use resized thumbnails here for better performance, but it’s not necessary --> + + <div id="galleria"> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Locomotives-Roundhouse2.jpg/800px-Locomotives-Roundhouse2.jpg"> + <img title="Locomotives Roundhouse" + alt="Steam locomotives of the Chicago &amp; North Western Railway." + src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Locomotives-Roundhouse2.jpg/100px-Locomotives-Roundhouse2.jpg"> + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Icebergs_in_the_High_Arctic_-_20050907.jpg/1000px-Icebergs_in_the_High_Arctic_-_20050907.jpg"> + <img title="Icebergs in the High Arctic" + alt="â€The debris loading isn't particularly extensive, but the color is usual.â€" + src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Icebergs_in_the_High_Arctic_-_20050907.jpg/100px-Icebergs_in_the_High_Arctic_-_20050907.jpg"> + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg/1000px-Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg"> + <img title="Araña" + alt="Xysticus cristatus, A Estrada, Galicia, Spain" + src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/fe/Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg/100px-Ara%C3%B1a._A_Estrada%2C_Galiza._02.jpg"> + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg/1000px-9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg"> + <img title="Museo storia naturale" + src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg/100px-9104_-_Milano_-_Museo_storia_naturale_-_Fluorite_-_Foto_Giovanni_Dall%27Orto_22-Apr-2007.jpg"> + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg/1000px-Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg"> + <img title="Grjótagjá caves in summer 2009" + src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg/100px-Grj%C3%B3tagj%C3%A1_caves_in_summer_2009_%282%29.jpg"> + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/9/90/20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg/1000px-20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg"> + <img title="Thermes" + alt="Xanthi hot-spa springs, Xanthi Prefecture, Greece" + src="http://upload.wikimedia.org/wikipedia/commons/thumb/9/90/20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg/100px-20091128_Loutra_Thermes_Xanthi_Thrace_Greece_2.jpg"> + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Polish_Army_Ko%C5%82obrzeg_077.JPG/1024px-Polish_Army_Ko%C5%82obrzeg_077.JPG"> + <img title="Polish Army KoÅ‚obrzeg" + alt="A display of the Polish Army. Both the soldier, and the vehicle belong to the 7th Pomeranian Coastal Defence Brigade, a part of the Szczecin-based 12th Mechanized Division â€BolesÅ‚aw Krzywoustyâ€" + src="http://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Polish_Army_Ko%C5%82obrzeg_077.JPG/100px-Polish_Army_Ko%C5%82obrzeg_077.JPG"> + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/20100213_Zlatograd_Bulgaria_3.jpg/1024px-20100213_Zlatograd_Bulgaria_3.jpg"> + <img title="Zlatograd Bulgaria" + src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/2d/20100213_Zlatograd_Bulgaria_3.jpg/100px-20100213_Zlatograd_Bulgaria_3.jpg"> + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg/1024px-FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg"> + <img title="09-28-2001 in New York City" + alt="New York, NY, September 28, 2001 -- Debris on surrounding roofs at the site of the World Trade Center. Photo by Andrea Booher/ FEMA News Photo" + src="http://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg/100px-FEMA_-_5399_-_Photograph_by_Andrea_Booher_taken_on_09-28-2001_in_New_York.jpg"> + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Antennae%2C_Hubble_images.jpg/1024px-Antennae%2C_Hubble_images.jpg"> + <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/Antennae%2C_Hubble_images.jpg/100px-Antennae%2C_Hubble_images.jpg"> + </a> + </div> + + <p class="cred">Made by <a href="http://galleria.aino.se">Galleria</a>.</p> + </div> + + <script> + + // Load the classic theme + Galleria.loadTheme('../../themes/classic/galleria.classic.min.js'); + + // Initialize Galleria + Galleria.run('#galleria'); + + </script> + </body> +</html> \ No newline at end of file diff --git a/src/static/galleria/plugins/picasa/galleria.picasa.js b/src/static/galleria/plugins/picasa/galleria.picasa.js new file mode 100644 index 0000000..27cfd7a --- /dev/null +++ b/src/static/galleria/plugins/picasa/galleria.picasa.js @@ -0,0 +1,320 @@ +/** + * Galleria Picasa Plugin 2012-04-04 + * http://galleria.io + * + * Licensed under the MIT license + * https://raw.github.com/aino/galleria/master/LICENSE + * + */ + +(function($) { + +/*global jQuery, Galleria, window */ + +Galleria.requires(1.25, 'The Picasa Plugin requires Galleria version 1.2.5 or later.'); + +// The script path +var PATH = Galleria.utils.getScriptPath(); + +/** + + @class + @constructor + + @example var picasa = new Galleria.Picasa(); + + @author http://aino.se + + @requires jQuery + @requires Galleria + + @returns Instance +*/ + +Galleria.Picasa = function() { + + this.options = { + max: 30, // photos to return + imageSize: 'medium', // photo size ( thumb,small,medium,big,original ) or a number + thumbSize: 'thumb', // thumbnail size ( thumb,small,medium,big,original ) or a number + complete: function(){} // callback to be called inside the Galleria.prototype.load + }; + +}; + +Galleria.Picasa.prototype = { + + // bring back the constructor reference + + constructor: Galleria.Picasa, + + /** + Search for anything at Picasa + + @param {String} phrase The string to search for + @param {Function} [callback] The callback to be called when the data is ready + + @returns Instance + */ + + search: function( phrase, callback ) { + return this._call( 'search', 'all', { + q: phrase + }, callback ); + }, + + /** + Get a user's public photos + + @param {String} username The username to fetch photos from + @param {Function} [callback] The callback to be called when the data is ready + + @returns Instance + */ + + user: function( username, callback ) { + return this._call( 'user', 'user/' + username, callback ); + }, + + /** + Get photos from an album + + @param {String} username The username that owns the album + @param {String} album The album ID + @param {Function} [callback] The callback to be called when the data is ready + + @returns Instance + */ + + useralbum: function( username, album, callback ) { + return this._call( 'useralbum', 'user/' + username + '/album/' + album, callback ); + }, + + /** + Set picasa options + + @param {Object} options The options object to blend + + @returns Instance + */ + + setOptions: function( options ) { + $.extend(this.options, options); + return this; + }, + + + // call Picasa + + _call: function( type, url, params, callback ) { + + url = 'https://picasaweb.google.com/data/feed/api/' + url + '?'; + + if (typeof params == 'function') { + callback = params; + params = {}; + } + + var self = this; + + params = $.extend({ + 'kind': 'photo', + 'access': 'public', + 'max-results': this.options.max, + 'thumbsize': this._getSizes().join(','), + 'alt': 'json-in-script', + 'callback': '?' + }, params ); + + $.each(params, function( key, value ) { + url += '&' + key + '=' + value; + }); + + // since Picasa throws 404 when the call is malformed, we must set a timeout here: + + var data = false; + + Galleria.utils.wait({ + until: function() { + return data; + }, + success: function() { + self._parse.call( self, data.feed.entry, callback ); + }, + error: function() { + var msg = ''; + if ( type == 'user' ) { + msg = 'user not found.'; + } else if ( type == 'useralbum' ) { + msg = 'album or user not found.'; + } + Galleria.raise('Picasa request failed' + (msg ? ': ' + msg : '.')); + }, + timeout: 5000 + }); + + $.getJSON( url, function( result ) { + data = result; + }); + + return self; + }, + + + // parse image sizes and return an array of three + + _getSizes: function() { + + var self = this, + norm = { + small: '72c', + thumb: '104u', + medium: '640u', + big: '1024u', + original: '1600u' + }, + op = self.options, + t = {}, + n, + sz = [32,48,64,72,94,104,110,128,144,150,160,200,220,288,320,400,512,576,640,720,800,912,1024,1152,1280,1440,1600]; + + $(['thumbSize', 'imageSize']).each(function() { + if( op[this] in norm ) { + t[this] = norm[ op[this] ]; + } else { + n = Galleria.utils.parseValue( op[this] ); + if (n > 1600) { + n = 1600; + } else { + $.each( sz, function(i) { + if ( n < this ) { + n = sz[i-1]; + return false; + } + }); + } + t[this] = n; + } + }); + + return [ t.thumbSize, t.imageSize, '1280u']; + + }, + + + // parse the result and call the callback with the galleria-ready data array + + _parse: function( data, callback ) { + + var self = this, + gallery = [], + img; + + $.each( data, function() { + + img = this.media$group.media$thumbnail; + + gallery.push({ + thumb: img[0].url, + image: img[1].url, + big: img[2].url, + title: this.summary.$t + }); + }); + + callback.call( this, gallery ); + } +}; + + +/** + Galleria modifications + We fake-extend the load prototype to make Picasa integration as simple as possible +*/ + + +// save the old prototype in a local variable + +var load = Galleria.prototype.load; + + +// fake-extend the load prototype using the picasa data + +Galleria.prototype.load = function() { + + // pass if no data is provided or picasa option not found + if ( arguments.length || typeof this._options.picasa !== 'string' ) { + load.apply( this, Galleria.utils.array( arguments ) ); + return; + } + + // define some local vars + var self = this, + args = Galleria.utils.array( arguments ), + picasa = this._options.picasa.split(':'), + p, + opts = $.extend({}, self._options.picasaOptions), + loader = typeof opts.loader !== 'undefined' ? + opts.loader : $('<div>').css({ + width: 48, + height: 48, + opacity: 0.7, + background:'#000 url('+PATH+'loader.gif) no-repeat 50% 50%' + }); + + if ( picasa.length ) { + + // validate the method + if ( typeof Galleria.Picasa.prototype[ picasa[0] ] !== 'function' ) { + Galleria.raise( picasa[0] + ' method not found in Picasa plugin' ); + return load.apply( this, args ); + } + + // validate the argument + if ( !picasa[1] ) { + Galleria.raise( 'No picasa argument found' ); + return load.apply( this, args ); + } + + // apply the preloader + window.setTimeout(function() { + self.$( 'target' ).append( loader ); + },100); + + // create the instance + p = new Galleria.Picasa(); + + // apply Flickr options + if ( typeof self._options.picasaOptions === 'object' ) { + p.setOptions( self._options.picasaOptions ); + } + + // call the picasa method and trigger the DATA event + var arg = []; + if ( picasa[0] == 'useralbum' ) { + arg = picasa[1].split('/'); + if (arg.length != 2) { + Galleria.raise( 'Picasa useralbum not correctly formatted (should be [user]/[album])'); + return; + } + } else { + arg.push( picasa[1] ); + } + + arg.push(function(data) { + self._data = data; + loader.remove(); + self.trigger( Galleria.DATA ); + p.options.complete.call(p, data); + }); + + p[ picasa[0] ].apply( p, arg ); + + } else { + + // if flickr array not found, pass + load.apply( this, args ); + } +}; + +}( jQuery ) ); \ No newline at end of file diff --git a/src/static/galleria/plugins/picasa/galleria.picasa.min.js b/src/static/galleria/plugins/picasa/galleria.picasa.min.js new file mode 100644 index 0000000..9e80017 --- /dev/null +++ b/src/static/galleria/plugins/picasa/galleria.picasa.min.js @@ -0,0 +1 @@ +!function(i){Galleria.requires(1.25,"The Picasa Plugin requires Galleria version 1.2.5 or later.");var e=Galleria.utils.getScriptPath();Galleria.Picasa=function(){this.options={max:30,imageSize:"medium",thumbSize:"thumb",complete:function(){}}};Galleria.Picasa.prototype={constructor:Galleria.Picasa,search:function(i,e){return this._call("search","all",{q:i},e)},user:function(i,e){return this._call("user","user/"+i,e)},useralbum:function(i,e,t){return this._call("useralbum","user/"+i+"/album/"+e,t)},setOptions:function(e){i.extend(this.options,e);return this},_call:function(e,t,a,s){t="https://picasaweb.google.com/data/feed/api/"+t+"?";if(typeof a=="function"){s=a;a={}}var r=this;a=i.extend({kind:"photo",access:"public","max-results":this.options.max,thumbsize:this._getSizes().join(","),alt:"json-in-script",callback:"?"},a);i.each(a,function(i,e){t+="&"+i+"="+e});var l=false;Galleria.utils.wait({until:function(){return l},success:function(){r._parse.call(r,l.feed.entry,s)},error:function(){var i="";if(e=="user"){i="user not found."}else if(e=="useralbum"){i="album or user not found."}Galleria.raise("Picasa request failed"+(i?": "+i:"."))},timeout:5e3});i.getJSON(t,function(i){l=i});return r},_getSizes:function(){var e=this,t={small:"72c",thumb:"104u",medium:"640u",big:"1024u",original:"1600u"},a=e.options,s={},r,l=[32,48,64,72,94,104,110,128,144,150,160,200,220,288,320,400,512,576,640,720,800,912,1024,1152,1280,1440,1600];i(["thumbSize","imageSize"]).each(function(){if(a[this]in t){s[this]=t[a[this]]}else{r=Galleria.utils.parseValue(a[this]);if(r>1600){r=1600}else{i.each(l,function(i){if(r<this){r=l[i-1];return false}})}s[this]=r}});return[s.thumbSize,s.imageSize,"1280u"]},_parse:function(e,t){var a=this,s=[],r;i.each(e,function(){r=this.media$group.media$thumbnail;s.push({thumb:r[0].url,image:r[1].url,big:r[2].url,title:this.summary.$t})});t.call(this,s)}};var t=Galleria.prototype.load;Galleria.prototype.load=function(){if(arguments.length||typeof this._options.picasa!=="string"){t.apply(this,Galleria.utils.array(arguments));return}var a=this,s=Galleria.utils.array(arguments),r=this._options.picasa.split(":"),l,n=i.extend({},a._options.picasaOptions),u=typeof n.loader!=="undefined"?n.loader:i("<div>").css({width:48,height:48,opacity:.7,background:"#000 url("+e+"loader.gif) no-repeat 50% 50%"});if(r.length){if(typeof Galleria.Picasa.prototype[r[0]]!=="function"){Galleria.raise(r[0]+" method not found in Picasa plugin");return t.apply(this,s)}if(!r[1]){Galleria.raise("No picasa argument found");return t.apply(this,s)}window.setTimeout(function(){a.$("target").append(u)},100);l=new Galleria.Picasa;if(typeof a._options.picasaOptions==="object"){l.setOptions(a._options.picasaOptions)}var o=[];if(r[0]=="useralbum"){o=r[1].split("/");if(o.length!=2){Galleria.raise("Picasa useralbum not correctly formatted (should be [user]/[album])");return}}else{o.push(r[1])}o.push(function(i){a._data=i;u.remove();a.trigger(Galleria.DATA);l.options.complete.call(l,i)});l[r[0]].apply(l,o)}else{t.apply(this,s)}}}(jQuery); \ No newline at end of file diff --git a/src/static/galleria/plugins/picasa/loader.gif b/src/static/galleria/plugins/picasa/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..27df81f46d9fe7398b9daf3d0f5fc97337d93750 GIT binary patch literal 1849 zcma*odr(tX9tZHtz31lM+(&YVNJFGd2tkvOnD7cwta}qc5LgzdLd#=Gz_5lw4HSfJ z5y=A~$WvKdT&=pxQWR|gA7dXNMrNejaaU%Y-KlM7v_m^eZ42#oR-Nv;2~(K-(LeV5 zasD_n=bX=cf9E$Redi9t77Iim@-M_co;`ae5D4n)>mwo}u3o+BcDsEmBO@bs@7~SN z&*wO9adEM{y!`3Yr*m_2gM))BoBrP^^1qUlI;*ALx<}e*tKTcNR9Tv;_gVIAw!K=p z4~cvN5XyH{<TE-aZP$w_#@w{H%{nZ|x1{#p;71~Oqg0Bb{Kzjx(Nq(8)7Uqb5$?G+ z=RGgFc-=CNjifrg@Jmkm>nkC~hc7+u%N^#HugZ42oEP(=_<y}`a+D;Wx<%iJJttzs z_`bhwjgw3EV;rF5&FXj{q$w6S%c4+{hp>A<Ya-yqACu9qCDODt@+V$Upk=?`V&kk^ zdQy$#hep^n**UvBBM8=xg_-Sp<>KxXOEf3NyKX+TXPhO;lW@FgY6t4@HoWKwfv%vY zs5YDhz`Oa{XYNBUhg9|igKV@+hT)W*iZ{6m9RLElqqI4j$Cl`iywUvnal^@^;-pmy z8c1pKQ$A*V6p%`$$;jTxPPc0&u1-Dn-09lf*^qX$6$uenUGkcj43I~BCGv8RG?a&C zh}2Tm{O3BcW`td;*-<F|W?{=zcJ6Rmd<;rKg%dT&SRP&3{YHn%R9L3<97I{JOzv^E zWYsy6jCE@mED*Dj%f|^mj60IdSeAXH67_DNZ|C)DIoCvoMgT>QgjNXf8)xk>LC}>S z^Y0HdBI4A8%k~T8+*{`PT*aWCblpFFQnIvL`=gXk(keA@D*>j6(U!`pf7PZvq%ywJ zfADB0oi)(aS!!(2>rd-fa{+;r>Xj0S{kh1<o68YCO8W+ynVLp0%|8sf3?On&w7!s& ze1^IGm*8FQv`4q$ROs95zo}ghB@c$bp0K{jEbiWy6<1bR^xbD&1)fW>Rlg|&R<6Dw zL#u5x|Dw%P*%EccGpHXp8np_*0|705z`JT6z$qhL%aU0Ybtsv!=U<FQ-Q!U@-tckr z8R?8<(~XKD#c(J#kjZi35!ar(epwVE(Z*i4VF|FqYo02&An^dq^!aoF5V8#i+_DOS zz%4m8Ekl$Nj8fUHAxI?KT78gD&^5LL2q4%RYjMmfi5E!vt)H|L`bb_G`OEM1vnubX zEGg~QpxeQvD-_uq@7QarxT3bVJWt*WmNM>dqqz$J;*IBvlv3!nS7QpQx7~5)LJvvS z{?MRW7fKNM8!LE_PnZdzQmJ4FjCk!}S!N&T*j`p5AT|loYm&$=`I?3Z)T}i0iUw7w z4@(uZs%gcKro>`VtT<>=`sbp_zwfl{jpU^tJ7;YYzdrdWQ`cd=rl0Y01<kw1aIl>4 z-j&pv$+l>@;MO0$vWpptUqayN2-d{svj-3^1~dbPL50K%F%%JdRKriRB%;;IH47PN zSxH8DVqx^nO~w;hXOFyd?{2sHk5~R907pG(C5md-iL)D%6Q$kvV4^71GaJ^bdk}Fk z-f20n(})hQ@4KuC7tB9@W=1>!dTzMv83`c}FW|#y)`k(7P)ON}^JUF^v<oE#{ZZ5q z$`|T!TTx?0qiVHI{GZpTvj$X8uFRr`M|G!Y%kkuY9=<&u^s>QGZccdk>Tm?@9W|9B z&hq!0!l!Zd#PvJDVblGmCq4?DzO`;)Ucna;b5rBbO94&tqN(i|!IC)5P;n|i2+>ZI zC$y<(z81%~!l4*BhV5U|P=T5T|EpQarn>l?{600A32Tf0<gI1mhs=4!j|GYA9FMn# z2|9nb1a`g@shg=YrW(Xd%Kovw4@2-zGjc0!!P5&iByRxpx{SG;eFIG4vC*jro6Cbh zn3teua36-XRoGBS=2Yn#S+{bnrRYG(T9r04wbP@NIvu6o&V)#v;+^o!J_AFxrz|a~ zf;-y}nJ%e^Bt3158^znGHb>W`Pr^idCz!$(4g8?rJg??6?SnrIi`9>|V<_Y$Q>-CB lXPcVF+Tga>T|!vOL#f|afc|5f*xFa*6zA6@`#++U@joVy6(Rrt literal 0 HcmV?d00001 diff --git a/src/static/galleria/plugins/picasa/picasa-demo.html b/src/static/galleria/plugins/picasa/picasa-demo.html new file mode 100644 index 0000000..0641c0c --- /dev/null +++ b/src/static/galleria/plugins/picasa/picasa-demo.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Galleria Flickr Plugin</title> + <style> + + /* Demo styles */ + html,body{background:#222;margin:0;} + body{border-top:4px solid #000;} + .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;} + h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;} + p{margin:0 0 20px} + a {color:#22BCB9;text-decoration:none;} + .cred{margin-top:20px;font-size:11px;} + + /* This rule is read by Galleria to define the gallery height: */ + #galleria{height:320px;} + + </style> + + <!-- load jQuery --> + <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script> + + <!-- load Galleria --> + <script src="../../galleria-1.4.2.min.js"></script> + + <!-- load picasa plugin --> + <script src="galleria.picasa.min.js"></script> + + </head> +<body> + <div class="content"> + <h1>Galleria Picasa Plugin Demo</h1> + <p>Demonstrating a basic gallery example with photos from a Picasa album.</p> + + <!-- Adding gallery images. This is just a container for the dynamic picasa images --> + + <div id="galleria"></div> + + <p class="cred">Made by <a href="http://galleria.aino.se">Galleria</a>.</p> + </div> + <script> + + // Load the classic theme + Galleria.loadTheme('../../themes/classic/galleria.classic.min.js'); + + Galleria.run('#galleria', { + // The user & album. This example fetches the album "Demo" from the user "galleriajs" + picasa: 'useralbum:galleriajs/Demo' + }); + + </script> + </body> +</html> \ No newline at end of file diff --git a/src/static/galleria/themes/classic/classic-demo.html b/src/static/galleria/themes/classic/classic-demo.html new file mode 100644 index 0000000..df2c481 --- /dev/null +++ b/src/static/galleria/themes/classic/classic-demo.html @@ -0,0 +1,124 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Galleria Classic Theme</title> + <style> + + /* Demo styles */ + html,body{background:#222;margin:0;} + body{border-top:4px solid #000;} + .content{color:#777;font:12px/1.4 "helvetica neue",arial,sans-serif;width:620px;margin:20px auto;} + h1{font-size:12px;font-weight:normal;color:#ddd;margin:0;} + p{margin:0 0 20px} + a {color:#22BCB9;text-decoration:none;} + .cred{margin-top:20px;font-size:11px;} + + /* This rule is read by Galleria to define the gallery height: */ + #galleria{height:320px} + + </style> + + <!-- load jQuery --> + <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js"></script> + + <!-- load Galleria --> + <script src="../../galleria-1.4.2.min.js"></script> + + </head> +<body> + <div class="content"> + <h1>Galleria Classic Theme</h1> + <p>Demonstrating a basic gallery example.</p> + + <!-- Adding gallery images. We use resized thumbnails here for better performance, but it’s not necessary --> + + <div id="galleria"> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/800px-Biandintz_eta_zaldiak_-_modified2.jpg"> + <img + src="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/100px-Biandintz_eta_zaldiak_-_modified2.jpg", + data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Biandintz_eta_zaldiak_-_modified2.jpg/1280px-Biandintz_eta_zaldiak_-_modified2.jpg" + data-title="Biandintz eta zaldiak" + data-description="Horses on Bianditz mountain, in Navarre, Spain." + > + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/800px-Athabasca_Rail_at_Brule_Lake.jpg"> + <img + src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/100px-Athabasca_Rail_at_Brule_Lake.jpg", + data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/Athabasca_Rail_at_Brule_Lake.jpg/1280px-Athabasca_Rail_at_Brule_Lake.jpg" + data-title="Athabasca Rail" + data-description="The Athabasca River railroad track at the mouth of Brulé Lake in Alberta, Canada." + > + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1280px-Back-scattering_crepuscular_rays_panorama_1.jpg"> + <img + src="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/100px-Back-scattering_crepuscular_rays_panorama_1.jpg", + data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/1/1f/Back-scattering_crepuscular_rays_panorama_1.jpg/1400px-Back-scattering_crepuscular_rays_panorama_1.jpg" + data-title="Back-scattering crepuscular rays" + data-description="Picture of the day on Wikimedia Commons 26 September 2010." + > + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/800px-Interior_convento_3.jpg"> + <img + src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/120px-Interior_convento_3.jpg", + data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Interior_convento_3.jpg/1400px-Interior_convento_3.jpg" + data-title="Interior convento" + data-description="Interior view of Yuriria Convent, founded in 1550." + > + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/800px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg"> + <img + src="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/100px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg", + data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/6/6b/Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg/1280px-Oxbow_Bend_outlook_in_the_Grand_Teton_National_Park.jpg" + data-title="Oxbow Bend outlook" + data-description="View over the Snake River to the Mount Moran with the Skillet Glacier." + > + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/800px-Hazy_blue_hour_in_Grand_Canyon.JPG"> + <img + src="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/100px-Hazy_blue_hour_in_Grand_Canyon.JPG", + data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Hazy_blue_hour_in_Grand_Canyon.JPG/1280px-Hazy_blue_hour_in_Grand_Canyon.JPG" + data-title="Hazy blue hour" + data-description="Hazy blue hour in Grand Canyon. View from the South Rim." + > + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/800px-2909_vallon_moy_res.jpg"> + <img + src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/100px-2909_vallon_moy_res.jpg", + data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/f/f4/2909_vallon_moy_res.jpg/1280px-2909_vallon_moy_res.jpg" + data-title="Haute Severaisse valley" + data-description="View of Haute Severaisse valley and surrounding summits from the slopes of Les Vernets." + > + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/800px-Bohinjsko_jezero_2.jpg"> + <img + src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/100px-Bohinjsko_jezero_2.jpg", + data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Bohinjsko_jezero_2.jpg/1280px-Bohinjsko_jezero_2.jpg" + data-title="Bohinj lake" + data-description="Bohinj lake (Triglav National Park, Slovenia) in the morning." + > + </a> + <a href="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/800px-Bowling_Balls_Beach_2_edit.jpg"> + <img + src="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/100px-Bowling_Balls_Beach_2_edit.jpg", + data-big="http://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Bowling_Balls_Beach_2_edit.jpg/1280px-Bowling_Balls_Beach_2_edit.jpg" + data-title="Bowling Balls" + data-description="Mendocino county, California, USA." + > + </a> + </div> + + <p class="cred">Made by <a href="http://galleria.aino.se">Galleria</a>.</p> + </div> + + <script> + + // Load the classic theme + Galleria.loadTheme('galleria.classic.min.js'); + + // Initialize Galleria + Galleria.run('#galleria'); + + </script> + </body> +</html> \ No newline at end of file diff --git a/src/static/galleria/themes/classic/classic-loader.gif b/src/static/galleria/themes/classic/classic-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..27df81f46d9fe7398b9daf3d0f5fc97337d93750 GIT binary patch literal 1849 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 literal 0 HcmV?d00001 diff --git a/src/static/galleria/themes/classic/classic-map.png b/src/static/galleria/themes/classic/classic-map.png new file mode 100644 index 0000000000000000000000000000000000000000..8d3c8c45cf3ccffe1df58634063d61bd6c009125 GIT binary patch literal 1840 zcmaJ?Yfuwc7`+w{jb#|MDuT++rc41LF9{(_V!(tblpvF!pg2NE7Rbb8!|nnJDu}Pa z3O+!s&(=}!i3DG@hz6{~2qI!_6-5-QJjTcHQi~}Nx&hJt(C&}j``ta?`ObImxpTKf zM=f-rxzhjuF5!zLasV9OQ)ABw<Egg-Pi9e{nPgZTslbxSOeKzjP&Jl>Lg6}P3MxmH zYExPrDxk7pO-vjaCyPW>n2w>eV;DxAfyxFzATk=1DlJMvNoa~jFNC`*t6)f@7Q(Sy z8B1mmqp6xjSvac5ii%NXX;pkRESe7qj0i=bLrEoM)UDDJh*1cS@FLXMKFx%o5eTUj z!lR<%WYLfq!%>LKVEL<9fh;JH&0x<9;PH5V5QoKPF<BfYo8!;sA@ev0iv@jnV5%Cf zPDbPs>4#cWB!p8*(tt3TnVFf4%y|q9Phqn8e7>E7!||sO{)9<SDvkbnf<DF|K?xPE zF_0Qe57`-&Nmx25gej$?E$9p%Y4ya1Wug|0X;d1RYzE8T(il)C`+ulT_YqBya`cnl z&k_?cCIiZpqXd?YtEi1jrrS#y5HXG_Neqv{uvKHL7@dld7?Fw@AhCiA$&@OM-X4$O zWiljOPmoHz3JsSCVTysF(WntNix(8IAdoBJN_lLyL>d&t6-)U6Vcbw|0Gq=L8q1Yn zs&pNyC&zNtpK=4gm}|F!&OlX`ptvRjRZDS92aU9hXg;HbKabC62XTWaKKAFejOMDp ztR>)!T9}j=rhQ}ov(aNylzZ&MkG7?PkH$y!l-qI2)+Z*u-9w$0;&4f5jIsIk<A$v= z<t*o(l&;@?xU%b<x*ZkE&R#7kp5QTgIM-#sr?9kl#sj!-%Fe>G2ai0+a|w*_@i~8P z@2mcx&W>M`JGSjhJH+pNa}wKp&g%cuYRelzXNBtON~Ztam$l?qZvI+V0B#*QUpsus zr%!<2pO8Bl@!aRz1Obq^#YrTJ6Kz>laBxwL-o3hNPt$(Y&e`qm#cd9tdI~MOs-@HU zb<<8g9y8so;04}bI&J@Pmu5?>X!WqFH&#zr>-)V;>*Wc+^w^%=s}Dzc<(LbpdN~PH z6jJ95*6sK3=;N9^=tVb$(TekrC-psy10eP2Hr%x|aYL}RsJ+<<0Gb7N^|pe+g(>jD z{Bcja8!{w0<t>>-baTiMzs&V|yXz2J#WK6sYy1DO5vS6=zKAr~cHbk0g6|k+x6et< zyJo&~ATpy*Szel?Pw(g8-{B9vH&bm!<gDaW2KO=W+PuSSPX)ifDZJx&pR>2BxOp0v zx72b)JS;fJ9kL-hM*nuYmd>LuETA=)C`?esg=wkl8|$Lx-&!JP-$3fSpL9OA{+OS1 z;ze%b<-u81W_ee4Sd{zJ3yYszYjm|(jg8YO9Xnn|*#>IoXgwk{y$><Jj#zOl{ncG_ z{kuNmg|lkrsjT5!k-mZ5ctvAye`|qr^Rk{dl~KX;1o)8vIJnHUVz38nhAZ<OotA`h ztD5U-Eb+E|TWw9XS*m5_SBT+qzy4PE5#6)Eso96=I78m+Q8fqz%5Ot9MDEf)imbRF z`pEleN5z!31wS+I2d}UVZQJShz}O}&X)%Y_u-BT8g>Ic>J5!q*GwV73P|I>!!1Z=q zHn6fR?NYvD$u~slMO*J+iuCMLyfvrOmf@Sx^;qOUvn}2(?~PY@d8RI}5UnUnJA5!H z``x`Wg9qzh@ag+vEny<h`o`mb_UWuQ6ls1{@jlk3{E5x+J-gS0R5*K0BL)&IOS5lx z|JBMZG_}XST^v?+{Mj#qwoO?>SYh39=(gL`3q9h~O#{zudxzSOT=vClo&oQEkYC-w zDUyyWU*nWe=e%n*0C7r$7_5B$&pMnkn2Y!Oi1~+G96*SeW+`-~@Zipl_2xE*n?e8r zil5H4j>3G#U<D2DxTZHJvo}4tR_ma0l(vPmQKkc+UePn)l_S7^r_RNJyerXN<3OT` hHlMn&qUj<>H(+6n58mkT_c8k&79JKQDO-@Z{$Cn;<9`4E literal 0 HcmV?d00001 diff --git a/src/static/galleria/themes/classic/galleria.classic.css b/src/static/galleria/themes/classic/galleria.classic.css new file mode 100644 index 0000000..bbb4e2f --- /dev/null +++ b/src/static/galleria/themes/classic/galleria.classic.css @@ -0,0 +1,219 @@ +/* Galleria Classic Theme 2012-08-07 | https://raw.github.com/aino/galleria/master/LICENSE | (c) Aino */ + +#galleria-loader{height:1px!important} + +.galleria-theme-classic { + position: relative; + overflow: hidden; + background: #000; +} +.galleria-theme-classic img { + -moz-user-select: none; + -webkit-user-select: none; + -o-user-select: none; +} +.galleria-theme-classic .galleria-stage { + position: absolute; + top: 10px; + bottom: 60px; + left: 10px; + right: 10px; + overflow:hidden; +} +.galleria-theme-classic .galleria-thumbnails-container { + height: 50px; + bottom: 0; + position: absolute; + left: 10px; + right: 10px; + z-index: 2; +} +.galleria-theme-classic .galleria-carousel .galleria-thumbnails-list { + margin-left: 30px; + margin-right: 30px; +} +.galleria-theme-classic .galleria-thumbnails .galleria-image { + height: 40px; + width: 60px; + background: #000; + margin: 0 5px 0 0; + border: 1px solid #000; + float: left; + cursor: pointer; +} +.galleria-theme-classic .galleria-counter { + position: absolute; + bottom: 10px; + left: 10px; + text-align: right; + color: #fff; + font: normal 11px/1 arial,sans-serif; + z-index: 1; +} +.galleria-theme-classic .galleria-loader { + background: #000; + width: 20px; + height: 20px; + position: absolute; + top: 10px; + right: 10px; + z-index: 2; + display: none; + background: url(classic-loader.gif) no-repeat 2px 2px; +} +.galleria-theme-classic .galleria-info { + width: 50%; + top: 15px; + left: 15px; + z-index: 2; + position: absolute; +} +.galleria-theme-classic .galleria-info-text { + background-color: #000; + padding: 12px; + display: none; + /* IE7 */ zoom:1; +} +.galleria-theme-classic .galleria-info-title { + font: bold 12px/1.1 arial,sans-serif; + margin: 0; + color: #fff; + margin-bottom: 7px; +} +.galleria-theme-classic .galleria-info-description { + font: italic 12px/1.4 georgia,serif; + margin: 0; + color: #bbb; +} +.galleria-theme-classic .galleria-info-close { + width: 9px; + height: 9px; + position: absolute; + top: 5px; + right: 5px; + background-position: -753px -11px; + opacity: .5; + filter: alpha(opacity=50); + cursor: pointer; + display: none; +} +.galleria-theme-classic .notouch .galleria-info-close:hover{ + opacity:1; + filter: alpha(opacity=100); +} +.galleria-theme-classic .touch .galleria-info-close:active{ + opacity:1; + filter: alpha(opacity=100); +} +.galleria-theme-classic .galleria-info-link { + background-position: -669px -5px; + opacity: .7; + filter: alpha(opacity=70); + position: absolute; + width: 20px; + height: 20px; + cursor: pointer; + background-color: #000; +} +.galleria-theme-classic.notouch .galleria-info-link:hover { + opacity: 1; + filter: alpha(opacity=100); +} +.galleria-theme-classic.touch .galleria-info-link:active { + opacity: 1; + filter: alpha(opacity=100); +} +.galleria-theme-classic .galleria-image-nav { + position: absolute; + top: 50%; + margin-top: -62px; + width: 100%; + height: 62px; + left: 0; +} +.galleria-theme-classic .galleria-image-nav-left, +.galleria-theme-classic .galleria-image-nav-right { + opacity: .3; + filter: alpha(opacity=30); + cursor: pointer; + width: 62px; + height: 124px; + position: absolute; + left: 10px; + z-index: 2; + background-position: 0 46px; +} +.galleria-theme-classic .galleria-image-nav-right { + left: auto; + right: 10px; + background-position: -254px 46px; + z-index: 2; +} +.galleria-theme-classic.notouch .galleria-image-nav-left:hover, +.galleria-theme-classic.notouch .galleria-image-nav-right:hover { + opacity: 1; + filter: alpha(opacity=100); +} +.galleria-theme-classic.touch .galleria-image-nav-left:active, +.galleria-theme-classic.touch .galleria-image-nav-right:active { + opacity: 1; + filter: alpha(opacity=100); +} +.galleria-theme-classic .galleria-thumb-nav-left, +.galleria-theme-classic .galleria-thumb-nav-right { + cursor: pointer; + display: none; + background-position: -495px 5px; + position: absolute; + left: 0; + top: 0; + height: 40px; + width: 23px; + z-index: 3; + opacity: .8; + filter: alpha(opacity=80); +} +.galleria-theme-classic .galleria-thumb-nav-right { + background-position: -578px 5px; + border-right: none; + right: 0; + left: auto; +} +.galleria-theme-classic .galleria-thumbnails-container .disabled { + opacity: .2; + filter: alpha(opacity=20); + cursor: default; +} +.galleria-theme-classic.notouch .galleria-thumb-nav-left:hover, +.galleria-theme-classic.notouch .galleria-thumb-nav-right:hover { + opacity: 1; + filter: alpha(opacity=100); + background-color: #111; +} +.galleria-theme-classic.touch .galleria-thumb-nav-left:active, +.galleria-theme-classic.touch .galleria-thumb-nav-right:active { + opacity: 1; + filter: alpha(opacity=100); + background-color: #111; +} +.galleria-theme-classic.notouch .galleria-thumbnails-container .disabled:hover { + opacity: .2; + filter: alpha(opacity=20); + background-color: transparent; +} + +.galleria-theme-classic .galleria-carousel .galleria-thumb-nav-left, +.galleria-theme-classic .galleria-carousel .galleria-thumb-nav-right { + display: block; +} +.galleria-theme-classic .galleria-thumb-nav-left, +.galleria-theme-classic .galleria-thumb-nav-right, +.galleria-theme-classic .galleria-info-link, +.galleria-theme-classic .galleria-info-close, +.galleria-theme-classic .galleria-image-nav-left, +.galleria-theme-classic .galleria-image-nav-right { + background-image: url(classic-map.png); + background-repeat: no-repeat; +} +.galleria-theme-classic.galleria-container.videoplay .galleria-info, +.galleria-theme-classic.galleria-container.videoplay .galleria-counter{ display:none!important; } diff --git a/src/static/galleria/themes/classic/galleria.classic.js b/src/static/galleria/themes/classic/galleria.classic.js new file mode 100644 index 0000000..377df3f --- /dev/null +++ b/src/static/galleria/themes/classic/galleria.classic.js @@ -0,0 +1,100 @@ +/** + * Galleria Classic Theme 2012-08-08 + * http://galleria.io + * + * Licensed under the MIT license + * https://raw.github.com/aino/galleria/master/LICENSE + * + */ + +(function($) { + +/*global window, jQuery, Galleria */ + +Galleria.addTheme({ + name: 'classic', + author: 'Galleria', + css: 'galleria.classic.css', + defaults: { + transition: 'slide', + thumbCrop: 'height', + + // set this to false if you want to show the caption all the time: + _toggleInfo: true + }, + init: function(options) { + + Galleria.requires(1.4, 'This version of Classic theme requires Galleria 1.4 or later'); + + // add some elements + this.addElement('info-link','info-close'); + this.append({ + 'info' : ['info-link','info-close'] + }); + + // cache some stuff + var info = this.$('info-link,info-close,info-text'), + touch = Galleria.TOUCH; + + // show loader & counter with opacity + this.$('loader,counter').show().css('opacity', 0.4); + + // some stuff for non-touch browsers + if (! touch ) { + this.addIdleState( this.get('image-nav-left'), { left:-50 }); + this.addIdleState( this.get('image-nav-right'), { right:-50 }); + this.addIdleState( this.get('counter'), { opacity:0 }); + } + + // toggle info + if ( options._toggleInfo === true ) { + info.bind( 'click:fast', function() { + info.toggle(); + }); + } else { + info.show(); + this.$('info-link, info-close').hide(); + } + + // bind some stuff + this.bind('thumbnail', function(e) { + + if (! touch ) { + // fade thumbnails + $(e.thumbTarget).css('opacity', 0.6).parent().hover(function() { + $(this).not('.active').children().stop().fadeTo(100, 1); + }, function() { + $(this).not('.active').children().stop().fadeTo(400, 0.6); + }); + + if ( e.index === this.getIndex() ) { + $(e.thumbTarget).css('opacity',1); + } + } else { + $(e.thumbTarget).css('opacity', this.getIndex() ? 1 : 0.6).bind('click:fast', function() { + $(this).css( 'opacity', 1 ).parent().siblings().children().css('opacity', 0.6); + }); + } + }); + + var activate = function(e) { + $(e.thumbTarget).css('opacity',1).parent().siblings().children().css('opacity', 0.6); + }; + + this.bind('loadstart', function(e) { + if (!e.cached) { + this.$('loader').show().fadeTo(200, 0.4); + } + window.setTimeout(function() { + activate(e); + }, touch ? 300 : 0); + this.$('info').toggle( this.hasInfo() ); + }); + + this.bind('loadfinish', function(e) { + this.$('loader').fadeOut(200); + }); + } +}); + +}(jQuery)); diff --git a/src/static/galleria/themes/classic/galleria.classic.min.js b/src/static/galleria/themes/classic/galleria.classic.min.js new file mode 100644 index 0000000..5c00c62 --- /dev/null +++ b/src/static/galleria/themes/classic/galleria.classic.min.js @@ -0,0 +1 @@ +!function(i){Galleria.addTheme({name:"classic",author:"Galleria",css:"galleria.classic.css",defaults:{transition:"slide",thumbCrop:"height",_toggleInfo:true},init:function(t){Galleria.requires(1.4,"This version of Classic theme requires Galleria 1.4 or later");this.addElement("info-link","info-close");this.append({info:["info-link","info-close"]});var e=this.$("info-link,info-close,info-text"),s=Galleria.TOUCH;this.$("loader,counter").show().css("opacity",.4);if(!s){this.addIdleState(this.get("image-nav-left"),{left:-50});this.addIdleState(this.get("image-nav-right"),{right:-50});this.addIdleState(this.get("counter"),{opacity:0})}if(t._toggleInfo===true){e.bind("click:fast",function(){e.toggle()})}else{e.show();this.$("info-link, info-close").hide()}this.bind("thumbnail",function(t){if(!s){i(t.thumbTarget).css("opacity",.6).parent().hover(function(){i(this).not(".active").children().stop().fadeTo(100,1)},function(){i(this).not(".active").children().stop().fadeTo(400,.6)});if(t.index===this.getIndex()){i(t.thumbTarget).css("opacity",1)}}else{i(t.thumbTarget).css("opacity",this.getIndex()?1:.6).bind("click:fast",function(){i(this).css("opacity",1).parent().siblings().children().css("opacity",.6)})}});var n=function(t){i(t.thumbTarget).css("opacity",1).parent().siblings().children().css("opacity",.6)};this.bind("loadstart",function(i){if(!i.cached){this.$("loader").show().fadeTo(200,.4)}window.setTimeout(function(){n(i)},s?300:0);this.$("info").toggle(this.hasInfo())});this.bind("loadfinish",function(i){this.$("loader").fadeOut(200)})}})}(jQuery); \ No newline at end of file diff --git a/src/static/galleria/themes/movio/css/bg-thumb.png b/src/static/galleria/themes/movio/css/bg-thumb.png new file mode 100644 index 0000000000000000000000000000000000000000..fae27607a8a20104f6d3d5c489ff54bc755a5f05 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blmSQK*5Dp-y;YjHK@;M7UB8wRq zxP?HN@zUM8KR`jb64!{5;QX|b^2DN42FH~Aq*MjB%%art{G#k)1?ON>J;T-V9<PBa z#X%~ai&7IyGV}8kLNaqx87y=S%yo?n42>^OZp{QL;q`QJ4B?oWY+z<)$IQSqhcWH+ SnG|iH1cRrmpUXO@geCx@8!hqx literal 0 HcmV?d00001 diff --git a/src/static/galleria/themes/movio/css/controller-left-hover.png b/src/static/galleria/themes/movio/css/controller-left-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..eedc813688d3c6110fe21fddd5df72959d6cbed8 GIT binary patch literal 580 zcmV-K0=xZ*P)<h;3K|Lk000e1NJLTq000yK001Ni1^@s6iSrtu00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gH7+r$A4ux}000+sMObu0a%Ew3X>V>IRB3Hx068r%H!U(SF*C&IktzTH z0hvieK~zYI?bab^+)y0H@o(}j>?oHk<J3DSr4<#0iowL}%*@P0)zn;T3WZkHR+XBX znNd-wXw}Tj%*5QpU}CVq)OF$_9+#y_X|KE_Z>BwQBA1Y3V%$$Y{(N}v!TZ0z#eKps zG-;ZWWf^tSYPE1(7b&GRUJQc3D5Z?n+SHBK+9;(=5CjIm3d7JijzhQGt+lhs42MIs z*4Rms;QM|f48Zq&k|e>-^Bf^WV^9b|p6A$&rHRbJIXIEgub=!mKb;LY`thCq=3BC% zDy?f(!EU~NrN6U9adSJhcIpnVzkH^@y;%vH3MQXEa=E)raW|@jm4a6vF8IB_hbi*P zSSe_Vq82n2^f%tHcyNei*K2L1clh|#YnG0Vu^eYMAVBBEOP1fAU_WZl1_W4m_MDaX zr-)8xHXuNI{VB^QXNV`|pIN1sGDcU|Xs@o7*8FGfYYzS+@L?utnui(5_B@X`jvIq< z9OHQ&wv^IRN)bg-?dcUD%QB)ULMerm(i)GkgTcV0X<GaELI_;frPu3O0Dl3FNyBit SS%P8!0000<MNUMnLSTXtb^oaV literal 0 HcmV?d00001 diff --git a/src/static/galleria/themes/movio/css/controller-left.png b/src/static/galleria/themes/movio/css/controller-left.png new file mode 100644 index 0000000000000000000000000000000000000000..2724f58babfbb281156d09a1e4e3cc6c66c7bdab GIT binary patch literal 547 zcmV+;0^I$HP)<h;3K|Lk000e1NJLTq000yK001Ni1^@s6iSrtu00004b3#c}2nYxW zd<bNS00009a7bBm000W>000W>0fLJSS^xk59&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gH7+r$A4ux}000+sMObu0a%Ew3X>V>IRB3Hx068r%H!U(SF*C&IktzTH z0eDG7K~zYI?bbnS!Y~*H;5SL7r$jRlRB+&M2Y-RXfoyJnd&rPEnLohGTqjIL&{h(J z9vZuYcoA09RdyJ@=a;8}gs&d~fZ1$D2q9aoHKHg&nmCRF&Usuemni@c02qx%@r9HS zoWpUPRA3ZEP+G$ef^DPGU}Qd@$Ba_QLLn7&m|(qz*=}R1l!D+q69xc+b10<<HO7E3 zmKkJ>!59OYSvtrWJc9=bf&d?$cN%cHT;i$QMHq&OJ*!EuSS;||>sd{rqu|$cikE&L z#u%G#Cxf4p30?;S#BpqeC4%qcG2VtlYiOSzFD1>XtibDf9XHJ;2qC8d0pO}u!)>bt zO6{NP(dK2fio15(8ntSbN+mqp-y@gHodyJeVzG$FP6w{*CiYVOGo_S}QYLo(+4wqx ze+2G#lC0V9NK^;`rFCXdX$>I+Xc&fU<@>w+?iVLD#voX)vGRT7^ZDHd>v<k^UDs%> lQ=^PAaL!SwRLEwtA>RqvkR?9yV@d!3002ovPDHLkV1iJz*#-ar literal 0 HcmV?d00001 diff --git a/src/static/galleria/themes/movio/css/controller-right-hover.png b/src/static/galleria/themes/movio/css/controller-right-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..e325e477b6dad23679b17637b2070af55c04523d GIT binary patch literal 583 zcmV-N0=WH&P)<h;3K|Lk000e1NJLTq000yK001Ni1^@s6iSrtu00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gH7+r$A4ux}000+sMObu0a%Ew3X>V>IRB3Hx068r%H!U(SF*C&IktzTH z0h~!hK~zYI?bb1C6hRz@@n>dkxg*@JYp%LOFlj6V3&FzH#>OTez#<^T6sfebw2@Rc zVj-juEX2yn#>T?VLa>l60=Z~$2N`d(+10o(GdC7;7J|83c0t6v<;=@(W}4wI07j#c z5JF6gqQF{9m9$zd!Z7sxeqa7tOp?TFt-UeESB){oYps2fBo07~$73G^0li+Y(#?L) zWHP}R<7J-b#Bp2;1Bm08JkN!6&Y_g54JxH@&LQVltK}5@@4>_8Pbqhk=0N-9fc@L+ zlpjAd0|MAAV{dbv<M;2H0Rg7pj@jSZ;OpBr&42*Y@;jgIY>~fy)eH#Wo#peryBxiI z(G2)g^>{b^<94fxC8Xlq{Rf=6u~r`xLBRR#hjg!9Ke4wEDBB%Y9z9{{%GJ5uxuEKH zS$(`i=hEdx&ORAbXM3#fJfm~r;zHP5aQWt~g`rvg@$c&t{7c|$CaIg*j3lEdBFnPc zV3uV>QG_hZQfaM8)3oyR3Sg}zO;fbic<-eE7!HTB-EO<0C@Mc+DMc8D3<d)M@B?&C V%u3bOj)4FG002ovPDHLkV1iz(0>l6S literal 0 HcmV?d00001 diff --git a/src/static/galleria/themes/movio/css/controller-right.png b/src/static/galleria/themes/movio/css/controller-right.png new file mode 100644 index 0000000000000000000000000000000000000000..40c06e4c6f1ad68081620a5c2229b74b1d427b25 GIT binary patch literal 532 zcmV+v0_**WP)<h;3K|Lk000e1NJLTq000yK001Ni1^@s6iSrtu00004b3#c}2nYxW zd<bNS00009a7bBm000W>000W>0fLJSS^xk59&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gH7+r$A4ux}000+sMObu0a%Ew3X>V>IRB3Hx068r%H!U(SF*C&IktzTH z0clA@K~zYI?bgdm12GhU;Xlcgu97-ZC{q-?toj6sf;W6^wW#PLbmJAYL!r);WK+t- zaiIkfv>j(aME`BVm#hv)@KzkhxpR&z%P3M11Zb^^qDTM;fL^bcFNPsTYl0vs1ZG)= zb&e!W>2x|m#BrP}DG3)A3PB%BM<e|6Gtyd%(Yh1{V6?_si}c>3lqwA>rSRS(OG_X6 z2md^Hb9+mgrqzMt@tC8N6NbZKH6XxbGU2$}WiS|21H$V>>7JhQ@c38_2;jZv?EIX& z`}=A@fIQE+xV+@*`nnqMJ^WdP#<LKD&5aFKS60e{QcAYBwpd<T`tsgfpi+vxogG@O z*37#z!CI}x{_ZZ#W^<mmzXt2|I)?`bgkd-rHWOT5Tbmo2_RGiDKlnr7bSEj>bVriL z7_4)pLF*jG7-XZ-;3-L7_q%WW)O$}l8u64QL{TKf^q}AG=gzsps8R~8HSKm=0K5SH WgNh)z34`_k0000<MNUMnLSTY{)Zrlj literal 0 HcmV?d00001 diff --git a/src/static/galleria/themes/movio/css/loader.gif b/src/static/galleria/themes/movio/css/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..27df81f46d9fe7398b9daf3d0f5fc97337d93750 GIT binary patch literal 1849 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 literal 0 HcmV?d00001 diff --git a/src/static/galleria/themes/movio/css/loader_black.gif b/src/static/galleria/themes/movio/css/loader_black.gif new file mode 100644 index 0000000000000000000000000000000000000000..13f0f64eab152fa4949476ed83ea24d6fd45a9bc GIT binary patch literal 3208 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 A6951J literal 0 HcmV?d00001 diff --git a/src/static/galleria/themes/movio/css/loader_white.gif b/src/static/galleria/themes/movio/css/loader_white.gif new file mode 100644 index 0000000000000000000000000000000000000000..3288d1035d70bb86517e2c233f1a904e41f06b29 GIT binary patch literal 3208 zcmc(iX;4#H9>pJdFE7h`I{IF)0|5<6L}(j=N}5%L009EB2nYfyF)E0PvIqo$u!IC; z4PgyY5|S9AEh38G)(9eq4TbH7_UHg@yWrlIJ$6smIADL7s^P;_O;ykRc<bJ}b<Y2s zU)AOL`#QVCGXW;>9soXl`UC*LwQJXkii*0rx|*7rI2=x7WaRkx_~XZqFJ8R3c=2Kg zf@aSAv8+BJ8+^hyay>(QR@t*blbKzsf0}bscEqRc5Hd3o(-N5RyW=zWB*zQw6Zh>* z2CROCDAbu#D`)S|J_<lj7Yz9)#_Og>o(lL9Yn3l*+8RdiRD_>iNz$#_IAzCna&Wl5 zSF_(rRCDD!wi#i8oAm&jYtn2_@VB%2-H*G%bN#|(6R6N?wM)3u`PiGzwuX7qmTgyF zpE)h0kuoxQ9?=kW7Y!=R@DmhU9)vwT<ZMc0Y;&y4jY1%TT3z!|H=R-GXDHPiKcVWh zY+!etO=DI2rIs8{iFWtPv(Lu|O3u|$F3Sbq;+xF{gTX$#T%m?MUUZy&ug3$=zXgXj zrxrf}reg*D3HB~8JyLgl$UCyV?EQ`@OKjW@tGrvh6ZqPD#+m=rK0T{FT01>*EZWzJ zrt+=2tqFts72yIp?|gvdLhs8Hfku^Z(){gmN%Y=K#<L1VKWYjwV^JDyeS;Y$p1xw* z#3VzfAV>P|%fkvg<hUP3U1Q=Hdgg~ik+2zyAc79kpuA<f*-~l+ZBH3*S2jBrEOF0w zrxe9#Vx$SxnL0JE4WeeXY1)ppOIy3@Vvexu&oeIa&QvoD`jBE#Gd7rT{j&OMLz1Wu zOEj;)PR^=mxjCG0NOUJb&U;ui6*-`3&wmcQ>Uj~HfIp3CuXqCtYGtJ#me+n+-LmP( z*XNuk%!aH8bIE@_Bj46>M*dSro|7<6vZ7WUHh5YQzN$>IJFqCb|CT!wj~R2C2%=q{ zpt8rzY$aw?W?=Ustv{jo?Ow@<k6~~d?F>ZRkLe<)NItY>Cyhle*wR59dTdF6(@{5^ zAQBOB*hNtc3bkY-8{Cm$nFS@elbTtSqrt7MB{h_4y+~`!mVa}?c&N>&?P}GqdMuhQ z&@TD5Czd((DcG_Su~dKKV)Pj$-qi1WHM8_vc^O4?^!oY|tmK~i!{fjd&@_1E(T~r7 z_REZy&hMT^ySJB3W7l<L=l9ZMvC<Gz>$4YhR`M(J7S5S~+4Q&3HPa)z%zPpisOp$^ zTEe99ig2$5_qFr!$;<oK+H}=wcaT3=%Nm!;Kw7MHnU5paWS{tI1+DOU?!7xefZ57L ze_iPrUrRQct0FSCtTFLtg*<#jo}Z3{E?T{skj>7A6CJ}PJmRhli>w?LC}Y`#HLGy6 zMU4<C6_PR!wGq`HQyoWJb;nj8>EhL~dKCN5Ut;U2jd*83ShB<kA1Y@1U)Ar;N|HhS znIkwkT(&i5XhkI;xwmC%DvPhGNIi?aY<|8rajSt<ap(2E-#qSPQxAp@jIY@-@>Niu zcJB0l9>1Modc?-oM<<M{t-|U0{*W+=Ct2ZY_02y-De{7vW<f^HJQhd1l&4)Gw2oOS zm46KASlsKI@J$sA#$$|7D5QMbewIaFv4fXyNbL5Ac~kS&g^#5XHaYBvNxbF3Y2L*6 ztrn?JmgOFAo1lh99BEb^pp>R<Z&2wFwWd*z2wF6&nmW9}nyMfWMO`hc&zkr2AeBP3 zj75NZQ8-VthLviI^j@e=FN6wxR@1uCRv<b;Y<3t(dr<e}N%b}FQtKxHi9xU2C!#0Z zO2<#(;s&964KtWfkQVi``vIFT7kbT~d;ITb0T9+U1AwIgET*ciil)~4gl;xgoy5M! z-UJHerGNh_`lO!vA)%ly=~<}ykhlnQnoP$oqido+`qK(cOpmt^pbhf`n-FQaIK5ix zq@=#Sl2Y&s<pe8B!1!YA78W7dA?2Xu9v7QHc?}NN)sx(o6iZ#|kHX64nijZG(yB1J zfMQm;1rb5O!-+1Pov;csFu7z>4?<d6>}3g}UJ%@K);kriq>)e*rh%hdqM)5Q)*+O8 zXm;SEbs@koiYS!9YXIclSg+5m_s~yrW#kKMdiRszg(gCP5HPmP7L)vCf8@fxUh6qY z@Z#TmkjzAZX{rwE+q|K~F2v5{_@vt%>yT_a#fF03SFt{0RX<yi^Bg0BS3UHmG;U4d z`2QlHs<l7ezUo)s<V^9ZccYv>vDAiaY~K9CgS1O>frXgAjBCS}mEd4mIWZ$=ovd5| zR?GRdU}d6+Q`+JRW)|=v7$)X<at#L3(d9WVd8CstDNPh>Nkn3yE`!nAiSCvOB1jKT zG<1aK3s<0b0m==egTD#8i(<nFTpHvxfx|aIng5yR81z6E<naz8-Ow^p@sCs8mz=%h zO$v$X0NS?ofjnp~62AE}^z%gY8Nsqj=NwUqyj+o6s$@kK@d+U4Vp-^_G32vzv@8nI z01{`FL$DXQL%WB*9R<xn7$ya31flsbiVh+-0m=YeB_ocaW;YRxI51d(jP?N!ane91 z9~^yzJ;S;OWRKC8PrrXYkZCaruNYE>Of=1pGDTOCho0XpIOMQ&P87cVKY1W=C6kIg z9cH=@a&zbm2+`|{(_?YC9fdm?1TY~-pwlBn?>=(~1pDKbco6jloP;0-cqRiwV1A_S zEyV0Dj8Pwy!nekzaN>{)7rgZ&_QLxK{~1yRe865^<m)Ax^m58MY|zev&92(G7#vQU zn~8r)5oUrwM9`}05|I<Nx*n}jlvg&C9_310Dd4OT2txd91Z*_U8bRtrNaq+nGd{E# zVGckZFpr^;mv}%%T{jHtz<a=^%;mPXVY7SR`@6_Uw@(0*>yx>}+a!ECd>#MMwddow z@CU{l+Rt$xuXuf}?ga{3IAr?Raql^c@a%sI0U5m}HvJ5O1#I%_MMPt#BH>OqUZ{-k zt>4Xzz=%jT*FVW(uYkWyx}9Gw$HdN*qU?Bit#ji(Wi7p-u|_8?h^%szIS^s^fNM}b zgGy>|=cbEufpguY5_6w~&ZLv=Bo06UF9EYIY;Er-1VK)SyF&!|J{axiE1z^(hXwVq zsFS=K-#zC}CcOs^8W{KAt+kK)jYDgDYbCXv{{<mZ_TMxh0{w%6lzzG*pm+Dj4XaZ5 zoJwkk5)~fyUmzYbwMERR3j)XePHj^2P!5GK`~^RXuEz>rwsgqtIU3<910$CJi)s?? z_t8k{>7*0~4l~LLF7$WXT5OSq5QCTbP_l!SN|{R}3D&eWA8~0ltWh1IL+ZBX4rRSt zWF6Om3WDMu4xK^1(BF`2cL}rUCzhHAB`@j5&R-yk_l*t;mPGY|u2^o|myvcOdrg0W z%=lX;f^Vkqfp?u7*4qQq%A3Mpf!xspWBSKS@O%r*TSM}?dl(@*%{0Jm_8;(h{R__M Bt<?Yk literal 0 HcmV?d00001 diff --git a/src/static/galleria/themes/movio/css/sprite.png b/src/static/galleria/themes/movio/css/sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..215271a9efdc145e0036c8b5350330070858d6fc GIT binary patch literal 2601 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 literal 0 HcmV?d00001 diff --git a/src/static/galleria/themes/movio/css/style.css b/src/static/galleria/themes/movio/css/style.css new file mode 100644 index 0000000..24aaef6 --- /dev/null +++ b/src/static/galleria/themes/movio/css/style.css @@ -0,0 +1,149 @@ +.wrapper-galleria-io.gallery{}.wrapper-galleria-io.gallery #galleria{height:500px} +.wrapper-galleria-io.gallery .content-galleria-io{color:#777;font-family:Arial,Helvetica,sans-serif;font-size:11px;position:relative} +.wrapper-galleria-io.gallery .galleria-container{position:relative;overflow:hidden}.wrapper-galleria-io.gallery .galleria-container img{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;-moz-transition:none;-webkit-transition:none;-o-transition:none;transition:none} +.wrapper-galleria-io.gallery .galleria-stage{position:absolute;top:0;bottom:60px;left:0;background:#202020;right:0;min-height:459px;overflow:hidden} +.wrapper-galleria-io.gallery .galleria-thumbnails-list{width:275px;position:absolute !important;right:0 !important;margin-right:100px}@media (max-width:765px){.wrapper-galleria-io.gallery .galleria-thumbnails-list{display:none !important}} +.wrapper-galleria-io.gallery .galleria-thumbnails-container{height:40px;bottom:0;margin-bottom:0;position:absolute;left:0;right:0;z-index:0;background:#202020;border-top:1px solid #000} +.wrapper-galleria-io.gallery .delimiter,.wrapper-galleria-io.gallery .galleria-container-delimeter{width:1px;background:#000;height:40px;display:block;position:absolute;right:0;margin-bottom:0;margin-right:90px;bottom:0} +.wrapper-galleria-io.gallery .galleria-thumbnails{margin-top:5px}.wrapper-galleria-io.gallery .galleria-thumbnails .galleria-image{height:27px;width:40px;background:#202020;margin:0 8px 0 0;float:left;cursor:pointer}.wrapper-galleria-io.gallery .galleria-thumbnails .galleria-image.active{border:1px solid #bababa} +.wrapper-galleria-io.gallery .galleria-counter{position:absolute;bottom:0;right:0;margin-bottom:9px;text-align:center;color:#fff;z-index:2;margin-right:40px;font-size:90%;width:40px} +.wrapper-galleria-io.gallery .galleria-loader{background:#000;width:32px;height:32px;position:absolute;top:16px;right:16px;z-index:2;display:none;background:url(loader_black.gif) no-repeat 2px 2px} +.wrapper-galleria-io.gallery .galleria-info{width:50%;bottom:0;left:15px;z-index:2;margin-bottom:5px;position:absolute} +.wrapper-galleria-io.gallery .galleria-info-text{display:none;zoom:1} +.wrapper-galleria-io.gallery .galleria-info-title{margin:0;color:#fff;line-height:1.1em;margin-bottom:6px;height:28px;overflow:hidden;font-size:12px;margin-bottom:-5px}@media (max-width:765px){.wrapper-galleria-io.gallery .galleria-info-title{margin-bottom:-5px}} +.wrapper-galleria-io.gallery .galleria-info-description{margin:0;color:#bbb;line-height:1.4em}@media (max-width:765px){.wrapper-galleria-io.gallery .galleria-info-description{display:none !important}} +.wrapper-galleria-io.gallery .galleria-info-close{width:9px;height:9px;position:absolute;top:5px;right:5px;background-position:-753px -11px;opacity:.5;filter:alpha(opacity=50);cursor:pointer;z-index:9} +.wrapper-galleria-io.gallery .galleria-fscr{width:10px;height:10px;position:absolute;bottom:0;margin-bottom:14px;right:10px;z-index:4;cursor:pointer;opacity:.7;filter:alpha(opacity=70);background-position:-840px -11px}.wrapper-galleria-io.gallery .galleria-fscr.active-fscr{background-position:-927px -11px} +.wrapper-galleria-io.gallery .galleria-fscr:hover{opacity:1 !important;filter:alpha(opacity=100) !important} +.wrapper-galleria-io.gallery .notouch .galleria-info-close:hover{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.gallery .touch .galleria-info-close:active{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.gallery .galleria-info-link{background-position:-669px -5px;opacity:.7;filter:alpha(opacity=70);position:absolute;width:20px;height:20px;cursor:pointer;background-color:#000} +.wrapper-galleria-io.gallery .notouch .galleria-info-link:hover{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.gallery .touch .galleria-info-link:active{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.gallery .galleria-image-nav{position:absolute;top:50%;margin-top:-62px;width:100%;height:62px;left:0;display:none}@media (max-width:765px){.wrapper-galleria-io.gallery .galleria-image-nav{display:block !important}} +.wrapper-galleria-io.gallery .galleria-image-nav-left,.wrapper-galleria-io.gallery .galleria-image-nav-right{opacity:.3;filter:alpha(opacity=30);cursor:pointer;width:62px;height:124px;position:absolute;left:10px;z-index:2;background-position:0 46px} +.wrapper-galleria-io.gallery .galleria-image-nav-right{left:auto;right:10px;background-position:-260px 46px;z-index:2} +.wrapper-galleria-io.gallery .notouch .galleria-image-nav-left:hover,.wrapper-galleria-io.gallery .notouch .galleria-image-nav-right:hover{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.gallery .touch .galleria-image-nav-left:active,.wrapper-galleria-io.gallery .touch .galleria-image-nav-right:active{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.gallery .galleria-thumb-nav-left,.wrapper-galleria-io.gallery .galleria-thumb-nav-right{cursor:pointer;display:none;background-position:-495px 5px;position:absolute;right:0;top:0;height:40px;width:23px;z-index:3;opacity:.7;filter:alpha(opacity=70);margin-right:70px}@media (max-width:765px){.wrapper-galleria-io.gallery .galleria-thumb-nav-left,.wrapper-galleria-io.gallery .galleria-thumb-nav-right{display:none !important}} +.wrapper-galleria-io.gallery .galleria-thumb-nav-right{background-position:-578px 5px;border-right:none;right:0;margin-right:26px} +.wrapper-galleria-io.gallery .galleria-thumbnails-container .disabled{opacity:.3;filter:alpha(opacity=30);cursor:default} +.wrapper-galleria-io.gallery .notouch .galleria-thumb-nav-left:hover,.wrapper-galleria-io.gallery .notouch .galleria-thumb-nav-right:hover{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.gallery .touch .galleria-thumb-nav-left:active,.wrapper-galleria-io.gallery .touch .galleria-thumb-nav-right:active{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.gallery .notouch .galleria-thumbnails-container .disabled:hover{opacity:.3;filter:alpha(opacity=30);background-color:transparent} +.wrapper-galleria-io.gallery .galleria-carousel .galleria-thumb-nav-left,.wrapper-galleria-io.gallery .galleria-carousel .galleria-thumb-nav-right{display:block} +.wrapper-galleria-io.gallery .galleria-thumb-nav-left,.wrapper-galleria-io.gallery .galleria-thumb-nav-right,.wrapper-galleria-io.gallery .galleria-info-link,.wrapper-galleria-io.gallery .galleria-info-close,.wrapper-galleria-io.gallery .galleria-image-nav-left,.wrapper-galleria-io.gallery .galleria-image-nav-right,.wrapper-galleria-io.gallery .galleria-fscr{background-image:url(sprite.png);background-repeat:no-repeat} +.wrapper-galleria-io.pageflip{}.wrapper-galleria-io.pageflip .content-galleria-io{color:#777;font-family:Arial,Helvetica,sans-serif;font-size:11px;position:relative} +.wrapper-galleria-io.pageflip .galleria-container{position:relative;overflow:hidden}.wrapper-galleria-io.pageflip .galleria-container img{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;-moz-transition:none;-webkit-transition:none;-o-transition:none;transition:none} +.wrapper-galleria-io.pageflip .galleria-stage{overflow:hidden;background:#202020;position:absolute;top:0;left:0;right:0;bottom:20px;min-height:459px} +.wrapper-galleria-io.pageflip .galleria-container.fullscreen .galleria-stage{bottom:0} +.wrapper-galleria-io.pageflip .galleria-bar{height:20px;width:100%;position:absolute;bottom:0;left:0;background:#202020;border-top:1px solid #000;z-index:3} +.wrapper-galleria-io.pageflip .galleria-delimiter1,.wrapper-galleria-io.pageflip .galleria-delimiter2,.wrapper-galleria-io.pageflip .galleria-delimiter3,.wrapper-galleria-io.pageflip .galleria-delimiter4{width:1px;background:#000;height:20px;position:absolute;left:20px;bottom:1px;display:none} +.wrapper-galleria-io.pageflip .galleria-delimiter2{left:80px} +.wrapper-galleria-io.pageflip .galleria-delimiter3{right:41px;left:auto} +.wrapper-galleria-io.pageflip .galleria-delimiter4{right:58px;left:auto;display:none} +.wrapper-galleria-io.pageflip .galleria-progress{height:2px;position:absolute;top:0;left:0;width:0;background:#fff;opacity:.5;z-index:3;filter:alpha(opacity=50)} +.wrapper-galleria-io.pageflip .galleria-thumblink,.wrapper-galleria-io.pageflip .galleria-fullscreen,.wrapper-galleria-io.pageflip .galleria-play,.wrapper-galleria-io.pageflip .galleria-popout{width:19px;height:19px;position:absolute;left:0;bottom:0;cursor:pointer;background:url(sprite.png) no-repeat} +.wrapper-galleria-io.pageflip .galleria-play{background-position:-1088px 3px;opacity:.7;filter:alpha(opacity=70);display:none} +.wrapper-galleria-io.pageflip .galleria-fullscreen{background-position:-835px -6px;opacity:.7;filter:alpha(opacity=70);right:0;margin-right:31px;left:auto}.wrapper-galleria-io.pageflip .galleria-fullscreen.open{background-position:-922px -6px} +.wrapper-galleria-io.pageflip .galleria-thumblink{background-position:-1011px -7px;opacity:.7;filter:alpha(opacity=70);right:0;left:auto;margin-right:6px} +.wrapper-galleria-io.pageflip .galleria-container.notouch .galleria-play:hover,.wrapper-galleria-io.pageflip .galleria-container.touch .galleria-play:active,.wrapper-galleria-io.pageflip .galleria-container.notouch .galleria-thumblink:hover,.wrapper-galleria-io.pageflip .galleria-container.touch .galleria-thumblink:active,.wrapper-galleria-io.pageflip .galleria-thumblink.open,.wrapper-galleria-io.pageflip .galleria-container.notouch .galleria-fullscreen:hover,.wrapper-galleria-io.pageflip .galleria-container.touch .galleria-fullscreen:active,.wrapper-galleria-io.pageflip .galleria-container.notouch .galleria-popout:hover,.wrapper-galleria-io.pageflip .galleria-container.touch .galleria-popout:active{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.pageflip .galleria-play.playing{background-position:-1165px 3px;opacity:.7;filter:alpha(opacity=70)}.wrapper-galleria-io.pageflip .galleria-play.playing:hover{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.pageflip .galleria-popout{display:none} +.wrapper-galleria-io.pageflip .galleria-thumbnails-container{position:absolute;top:0;left:auto;right:0;width:0;height:0;margin-right:-10px;background:#202020;width:215px !important;z-index:2;overflow:auto} +.wrapper-galleria-io.pageflip .galleria-thumbnails-list{position:absolute !important;top:10px;right:10px;left:10px;bottom:0;overflow:auto !important} +.wrapper-galleria-io.pageflip .galleria-thumbnails .galleria-image{width:80px;height:45px;float:left;margin:0 7px 7px 0;border:1px solid #bababa;cursor:pointer} +.wrapper-galleria-io.pageflip .galleria-container.notouch .galleria-thumbnails .galleria-image:hover,.wrapper-galleria-io.pageflip .galleria-container.touch .galleria-thumbnails .galleria-image:active{opacity:.9;box-shadow:0 0 3px rgba(0,0,0,0.4);-moz-box-shadow:0 0 3px rgba(0,0,0,0.4);-webkit-box-shadow:0 0 3px rgba(0,0,0,0.4)} +.wrapper-galleria-io.pageflip .galleria-info{position:absolute;height:15px;left:0;bottom:0;margin-bottom:2px !important;color:#bbb;margin-right:40px} +.wrapper-galleria-io.pageflip .galleria-info>*,.wrapper-galleria-io.pageflip .galleria-info-text>*{display:inline} +.wrapper-galleria-io.pageflip .galleria-info-title{color:#fff;padding:0 0;margin-bottom:0;margin-top:0;margin-right:10px} +.wrapper-galleria-io.pageflip .galleria-info-text{padding-left:10px} +.wrapper-galleria-io.pageflip .galleria-counter{background:url(separator.png) no-repeat 100% 0;display:inline-block;*display:inline;padding-right:10px;_height:29px;zoom:1;display:none} +.wrapper-galleria-io.pageflip .galleria-loader{background:#000;width:32px;height:32px;position:absolute;top:16px;right:16px;z-index:2;display:none;background:url(loader_black.gif) no-repeat 2px 2px} +.wrapper-galleria-io.pageflip .galleria-image-nav{position:absolute;top:50%;margin-top:-62px;width:100%;height:62px;left:0} +.wrapper-galleria-io.pageflip .galleria-image-nav-left,.wrapper-galleria-io.pageflip .galleria-image-nav-right{opacity:.3;filter:alpha(opacity=30);cursor:pointer;width:62px;height:124px;position:absolute;left:10px;z-index:2;background-position:0 46px} +.wrapper-galleria-io.pageflip .galleria-image-nav-right{left:auto;right:10px;background-position:-260px 46px;z-index:2} +.wrapper-galleria-io.pageflip .notouch .galleria-image-nav-left:hover,.wrapper-galleria-io.pageflip .notouch .galleria-image-nav-right:hover{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.pageflip .touch .galleria-image-nav-left:active,.wrapper-galleria-io.pageflip .touch .galleria-image-nav-right:active{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.pageflip .galleria-thumb-nav-right{background-position:-578px 5px;border-right:none;right:0;left:auto} +.wrapper-galleria-io.pageflip .galleria-thumbnails-container .disabled,.wrapper-galleria-io.pageflip .galleria-thumbnails-container .disabled:hover,.wrapper-galleria-io.pageflip .galleria-thumbnails-container .disabled:active{opacity:.2;cursor:default} +.wrapper-galleria-io.pageflip .galleria-container.notouch .galleria-thumb-nav-left:hover,.wrapper-galleria-io.pageflip .galleria-container.touch .galleria-thumb-nav-left:active,.wrapper-galleria-io.pageflip .galleria-container.notouch .galleria-thumb-nav-right:hover,.wrapper-galleria-io.pageflip .galleria-container.touch .galleria-thumb-nav-right:active{opacity:1;background-color:#111} +.wrapper-galleria-io.pageflip .galleria-carousel .galleria-thumb-nav-left,.wrapper-galleria-io.pageflip .galleria-carousel .galleria-thumb-nav-right{display:block} +.wrapper-galleria-io.pageflip .galleria-lightbox-content{background:url(loader_pos.gif) no-repeat 50% 50%} +.wrapper-galleria-io.pageflip .galleria-thumb-nav-left,.wrapper-galleria-io.pageflip .galleria-thumb-nav-right,.wrapper-galleria-io.pageflip .galleria-image-nav-left,.wrapper-galleria-io.pageflip .galleria-image-nav-right{background-image:url(sprite.png);background-repeat:no-repeat} +.wrapper-galleria-io.slider{}.wrapper-galleria-io.slider #galleria{height:490px} +.wrapper-galleria-io.slider .content-galleria-io{color:#777;font-family:Arial,Helvetica,sans-serif;font-size:11px;position:relative;margin-left:30px} +.wrapper-galleria-io.slider .galleria-container{position:relative}.wrapper-galleria-io.slider .galleria-container img{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;-moz-transition:none;-webkit-transition:none;-o-transition:none;transition:none} +.wrapper-galleria-io.slider .galleria-stage{background:#fff;position:relative;padding:5px;top:0;left:0;right:0;min-height:459px;border:1px solid #c6c6c6;border-radius:2px;-moz-border-radius:2px;-webkit-border-radius:2px;-moz-box-shadow:inset -1px 1px 1px #f3f3f3;-webkit-box-shadow:inset -1px 1px 1px #f3f3f3;box-shadow:inset -1px 1px 1px #f3f3f3;margin-right:40px} +.wrapper-galleria-io.slider .galleria-dots{position:absolute;height:10px;bottom:0;right:0;margin-right:35px}@media (max-width:765px){.wrapper-galleria-io.slider .galleria-dots{display:none !important}} +.wrapper-galleria-io.slider .galleria-dots div{width:10px;height:10px;margin-right:5px;background:#ddd;float:left;cursor:pointer;border-radius:100%;-moz-border-radius:100%;-webkit-border-radius:100%} +.wrapper-galleria-io.slider .galleria-dots div:hover{background-color:#333} +.wrapper-galleria-io.slider .galleria-dots div.active{background-color:#333} +.wrapper-galleria-io.slider .galleria-fs,.wrapper-galleria-io.slider .galleria-thumbs,.wrapper-galleria-io.slider .galleria-more{width:10px;height:10px;cursor:pointer;background:#222;position:absolute;bottom:0;right:0} +.wrapper-galleria-io.slider .galleria-fs{display:none} +.wrapper-galleria-io.slider .galleria-thumbs{right:15px;display:none} +.wrapper-galleria-io.slider .galleria-more{right:30px;display:none !important} +.wrapper-galleria-io.slider .galleria-counter{display:none} +.wrapper-galleria-io.slider .galleria-loader{width:32px;height:32px;background:#fff url(loader_white.gif) no-repeat 50% 50%;position:absolute;top:50%;left:50%;margin-top:-16px;margin-left:-16px;z-index:3;display:none} +.wrapper-galleria-io.slider .galleria-info{position:absolute;bottom:0;left:0 !important} +.wrapper-galleria-io.slider .galleria-info-title{display:inline;color:#000;font-size:12px;line-height:1.1em;height:28px;position:absolute;overflow:hidden} +.wrapper-galleria-io.slider .galleria-info-description{display:none !important} +.wrapper-galleria-io.slider .galleria-desc{position:absolute;width:auto;top:50%;left:50%;margin-left:-15%;background:#fff;border:5px solid #fff;padding:5px;z-index:2;font:11px/14px arial,sans-serif;display:none;color:#777;cursor:pointer} +.wrapper-galleria-io.slider .galleria-desc.hover{background:#fff} +.wrapper-galleria-io.slider .galleria-desc strong{color:#222;font-weight:normal;margin-bottom:5px;display:block} +.wrapper-galleria-io.slider .galleria-desc p{margin-bottom:0} +.wrapper-galleria-io.slider .galleria-image-nav{position:absolute;top:50%;margin-top:-62px;width:100%;height:62px;left:0} +.wrapper-galleria-io.slider .galleria-image-nav-left,.wrapper-galleria-io.slider .galleria-image-nav-right{opacity:1;filter:alpha(opacity=100);cursor:pointer;width:20px;height:124px;position:absolute;left:0;z-index:2}.wrapper-galleria-io.slider .galleria-image-nav-left.disabled,.wrapper-galleria-io.slider .galleria-image-nav-right.disabled{opacity:.5;filter:alpha(opacity=50)} +.wrapper-galleria-io.slider .galleria-image-nav-left{background:url(../css/controller-left.png) 0 50% no-repeat;margin-left:-30px;left:0}.wrapper-galleria-io.slider .galleria-image-nav-left:hover{background:url(../css/controller-left-hover.png) 0 50% no-repeat} +.wrapper-galleria-io.slider .galleria-image-nav-right{left:auto;right:0;background-position:-260px 46px;z-index:2;margin-right:-30px} +.wrapper-galleria-io.slider .galleria-image-nav-right{background:url(../css/controller-right.png) 0 50% no-repeat}.wrapper-galleria-io.slider .galleria-image-nav-right:hover{background:url(../css/controller-right-hover.png) 0 50% no-repeat} +.wrapper-galleria-io.slider .notouch .galleria-image-nav-left:hover,.wrapper-galleria-io.slider .notouch .galleria-image-nav-right:hover{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.slider .touch .galleria-image-nav-left:active,.wrapper-galleria-io.slider .touch .galleria-image-nav-right:active{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.slider .galleria-thumbnails-container{position:absolute;top:0;bottom:20px;left:0;right:0;z-index:2;overflow:hidden;visibility:hidden} +.wrapper-galleria-io.slider .galleria-thumbnails{margin:10px} +.wrapper-galleria-io.slider .galleria-thumbnails .galleria-image{height:50px;width:80px;background:#d77;margin:2px 8px 8px 2px;float:left;cursor:pointer;-moz-box-shadow:0 0 2px #000;-webkit-box-shadow:0 0 2px #000;box-shadow:0 0 2px #000} +.wrapper-galleria-io.slider .galleria-thumbnails .galleria-image img:hover{opacity:.1 !important;filter:alpha(opacity=10) !important} +.wrapper-galleria-io.slideshow{}.wrapper-galleria-io.slideshow #galleria{height:500px} +.wrapper-galleria-io.slideshow .content-galleria-io{color:#777;font-family:Arial,Helvetica,sans-serif;font-size:11px;position:relative} +.wrapper-galleria-io.slideshow .galleria-container{position:relative;overflow:hidden}.wrapper-galleria-io.slideshow .galleria-container img{-moz-user-select:none;-webkit-user-select:none;-o-user-select:none;-moz-transition:none;-webkit-transition:none;-o-transition:none;transition:none} +.wrapper-galleria-io.slideshow .galleria-stage{overflow:hidden;background:#202020;position:absolute;top:0;left:0;right:0;bottom:60px;min-height:459px} +.wrapper-galleria-io.slideshow .galleria-container.fullscreen .galleria-stage{bottom:0} +.wrapper-galleria-io.slideshow .galleria-bar{height:40px;width:100%;position:absolute;bottom:0;left:0;background:#202020;border-top:1px solid #000;z-index:3} +.wrapper-galleria-io.slideshow .galleria-delimiter1,.wrapper-galleria-io.slideshow .galleria-delimiter2,.wrapper-galleria-io.slideshow .galleria-delimiter3,.wrapper-galleria-io.slideshow .galleria-delimiter4{width:1px;background:#000;height:40px;position:absolute;left:40px;bottom:1px} +.wrapper-galleria-io.slideshow .galleria-delimiter2{left:80px} +.wrapper-galleria-io.slideshow .galleria-delimiter3{right:41px;left:auto} +.wrapper-galleria-io.slideshow .galleria-delimiter4{right:58px;left:auto;display:none} +.wrapper-galleria-io.slideshow .galleria-progress{height:2px;position:absolute;top:0;left:0;width:0;background:#fff;opacity:.5;z-index:3;filter:alpha(opacity=50)} +.wrapper-galleria-io.slideshow .galleria-thumblink,.wrapper-galleria-io.slideshow .galleria-fullscreen,.wrapper-galleria-io.slideshow .galleria-play,.wrapper-galleria-io.slideshow .galleria-popout{width:39px;height:39px;position:absolute;left:0;bottom:0;z-index:9;cursor:pointer;background:url(sprite.png) no-repeat} +.wrapper-galleria-io.slideshow .galleria-play{background-position:-1088px 3px;opacity:.7;filter:alpha(opacity=70)} +.wrapper-galleria-io.slideshow .galleria-fullscreen{background-position:-825px 3px;opacity:.7;filter:alpha(opacity=70);left:41px}.wrapper-galleria-io.slideshow .galleria-fullscreen.open{background-position:-912px 3px} +.wrapper-galleria-io.slideshow .galleria-thumblink{background-position:-1003px 3px;opacity:.7;filter:alpha(opacity=70);right:0;left:auto} +.wrapper-galleria-io.slideshow .galleria-container.notouch .galleria-play:hover,.wrapper-galleria-io.slideshow .galleria-container.touch .galleria-play:active,.wrapper-galleria-io.slideshow .galleria-container.notouch .galleria-thumblink:hover,.wrapper-galleria-io.slideshow .galleria-container.touch .galleria-thumblink:active,.wrapper-galleria-io.slideshow .galleria-thumblink.open,.wrapper-galleria-io.slideshow .galleria-container.notouch .galleria-fullscreen:hover,.wrapper-galleria-io.slideshow .galleria-container.touch .galleria-fullscreen:active,.wrapper-galleria-io.slideshow .galleria-container.notouch .galleria-popout:hover,.wrapper-galleria-io.slideshow .galleria-container.touch .galleria-popout:active{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.slideshow .galleria-play.playing{background-position:-1165px 3px;opacity:.7;filter:alpha(opacity=70)}.wrapper-galleria-io.slideshow .galleria-play.playing:hover{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.slideshow .galleria-popout{display:none} +.wrapper-galleria-io.slideshow .galleria-thumbnails-container{position:absolute;top:0;left:0;width:0;height:0;background:url(bg-thumb.png);z-index:2} +.wrapper-galleria-io.slideshow .galleria-thumbnails-list{position:absolute !important;top:10px;right:10px;left:10px;bottom:41px;overflow:auto !important} +.wrapper-galleria-io.slideshow .galleria-thumbnails .galleria-image{width:80px;height:45px;float:left;margin:0 7px 7px 0;border:3px solid #fff;cursor:pointer} +.wrapper-galleria-io.slideshow .galleria-container.notouch .galleria-thumbnails .galleria-image:hover,.wrapper-galleria-io.slideshow .galleria-container.touch .galleria-thumbnails .galleria-image:active{opacity:.9;box-shadow:0 0 3px rgba(0,0,0,0.4);-moz-box-shadow:0 0 3px rgba(0,0,0,0.4);-webkit-box-shadow:0 0 3px rgba(0,0,0,0.4)} +.wrapper-galleria-io.slideshow .galleria-info{width:90%;bottom:0;z-index:2;margin-bottom:0;position:absolute;color:#bbb;left:0;margin-right:40px} +.wrapper-galleria-io.slideshow .galleria-info>*,.wrapper-galleria-io.slideshow .galleria-info-text>*{display:block} +.wrapper-galleria-io.slideshow .galleria-info-title{color:#fff;padding:0 0;margin-bottom:3px;margin-top:8px} +.wrapper-galleria-io.slideshow .galleria-info-description{margin-left:90px;line-height:1.4em} +.wrapper-galleria-io.slideshow .galleria-info-title{left:0;margin-left:90px;margin-bottom:0;font-size:12px;line-height:1.1em;height:28px;overflow:hidden} +.wrapper-galleria-io.slideshow .galleria-info-text{padding-left:10px;line-height:1em;margin-bottom:-5px} +.wrapper-galleria-io.slideshow .galleria-counter{display:inline-block;*display:inline;padding-right:10px;_height:29px;zoom:1;display:none} +.wrapper-galleria-io.slideshow .galleria-loader{background:#000;width:32px;height:32px;position:absolute;top:16px;right:16px;z-index:2;display:none;background:url(loader_black.gif) no-repeat 2px 2px} +.wrapper-galleria-io.slideshow .galleria-image-nav{position:absolute;top:50%;margin-top:-62px;width:100%;height:62px;left:0} +.wrapper-galleria-io.slideshow .galleria-image-nav-left,.wrapper-galleria-io.slideshow .galleria-image-nav-right{opacity:.3;filter:alpha(opacity=30);cursor:pointer;width:62px;height:124px;position:absolute;left:10px;z-index:2;background-position:0 46px} +.wrapper-galleria-io.slideshow .galleria-image-nav-right{left:auto;right:10px;background-position:-260px 46px;z-index:2} +.wrapper-galleria-io.slideshow .notouch .galleria-image-nav-left:hover,.wrapper-galleria-io.slideshow .notouch .galleria-image-nav-right:hover{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.slideshow .touch .galleria-image-nav-left:active,.wrapper-galleria-io.slideshow .touch .galleria-image-nav-right:active{opacity:1;filter:alpha(opacity=100)} +.wrapper-galleria-io.slideshow .galleria-thumb-nav-right{background-position:-578px 5px;border-right:none;right:0;left:auto} +.wrapper-galleria-io.slideshow .galleria-thumbnails-container .disabled,.wrapper-galleria-io.slideshow .galleria-thumbnails-container .disabled:hover,.wrapper-galleria-io.slideshow .galleria-thumbnails-container .disabled:active{opacity:.2;cursor:default} +.wrapper-galleria-io.slideshow .galleria-container.notouch .galleria-thumb-nav-left:hover,.wrapper-galleria-io.slideshow .galleria-container.touch .galleria-thumb-nav-left:active,.wrapper-galleria-io.slideshow .galleria-container.notouch .galleria-thumb-nav-right:hover,.wrapper-galleria-io.slideshow .galleria-container.touch .galleria-thumb-nav-right:active{opacity:1;background-color:#111} +.wrapper-galleria-io.slideshow .galleria-carousel .galleria-thumb-nav-left,.wrapper-galleria-io.slideshow .galleria-carousel .galleria-thumb-nav-right{display:block} +.wrapper-galleria-io.slideshow .galleria-lightbox-content{background:url(loader_pos.gif) no-repeat 50% 50%} +.wrapper-galleria-io.slideshow .galleria-thumb-nav-left,.wrapper-galleria-io.slideshow .galleria-thumb-nav-right,.wrapper-galleria-io.slideshow .galleria-image-nav-left,.wrapper-galleria-io.slideshow .galleria-image-nav-right{background-image:url(sprite.png);background-repeat:no-repeat} +.wrapper-galleria-io.slideshow .galleria-tooltip{display:none} +#galleria-loader{height:1px !important} +#galleria{height:500px} diff --git a/src/static/galleria/themes/movio/galleria.gallery.js b/src/static/galleria/themes/movio/galleria.gallery.js new file mode 100644 index 0000000..1e15c6d --- /dev/null +++ b/src/static/galleria/themes/movio/galleria.gallery.js @@ -0,0 +1,111 @@ +(function($) { + +Galleria.addTheme({ + name: 'gallery', + author: 'GruppoMeta', + css: 'css/style.css', + defaults: { + transition: 'fade', + imageCrop: false, + thumbnails: 'lazy', + + // set this to false if you want to show the caption all the time: + _toggleInfo: false + + }, + init: function(options) { + + Galleria.requires(1.28, 'This version of Classic theme requires Galleria 1.2.8 or later'); + + // add some elements + this.addElement('info-link','info-close'); + + this.append({ + 'info' : ['info-link','info-close'] + }); + + // add some elements + this.addElement('container-delimeter'); + + this.append({ + 'container' : ['container-delimeter'] + }); + + // cache some stuff + var info = this.$('info-link,info-close,info-text'), + touch = Galleria.TOUCH, + click = touch ? 'touchstart' : 'click'; + + // show loader & counter with opacity + this.$('loader,counter').show().css('opacity', 1); + this.appendChild('container','counter'); + + // some stuff for non-touch browsers + if (! touch ) { + this.addIdleState( this.get('image-nav-left'), { left:-50 }); + this.addIdleState( this.get('image-nav-right'), { right:-50 }); + this.addIdleState( this.get('counter'), { opacity:1 }); + } + + // toggle info + if ( options._toggleInfo === true ) { + info.bind( click, function() { + info.toggle(); + }); + } else { + info.show(); + this.$('info-link, info-close').hide(); + } + + // bind some stuff + this.bind('thumbnail', function(e) { + + if (! touch ) { + // fade thumbnails + $(e.thumbTarget).css('opacity', 0.6).parent().hover(function() { + $(this).not('.active').children().stop().fadeTo(100, 1); + }, function() { + $(this).not('.active').children().stop().fadeTo(400, 0.6); + }); + + if ( e.index === this.getIndex() ) { + $(e.thumbTarget).css('opacity',1); + } + } else { + $(e.thumbTarget).css('opacity', this.getIndex() ? 1 : 0.6); + } + }); + + this.bind('loadstart', function(e) { + if (!e.cached) { + this.$('loader').show().fadeTo(200, 0.4); + } + + this.$('info').toggle( this.hasInfo() ); + + $(e.thumbTarget).css('opacity',1).parent().siblings().children().css('opacity', 0.6); + }); + + this.bind('loadfinish', function(e) { + this.$('loader').fadeOut(200); + this.lazyLoadChunks( 10 ); + }); + } +}); + +Galleria.ready(function() { + var gallery = this; + this.addElement('fscr'); + this.appendChild('container','fscr'); + var fscr = this.$('fscr') + .click(function() { + gallery.toggleFullscreen(); + }); + this.addIdleState(this.get('fscr'), { opacity:0.7 }); + + $(".galleria-fscr").click(function () { + $(".galleria-fscr").toggleClass('active-fscr'); + }); + +}); +}(jQuery)); diff --git a/src/static/galleria/themes/movio/galleria.pageflip.js b/src/static/galleria/themes/movio/galleria.pageflip.js new file mode 100644 index 0000000..a9c9d33 --- /dev/null +++ b/src/static/galleria/themes/movio/galleria.pageflip.js @@ -0,0 +1,115 @@ +(function (a) { + Galleria.addTheme({ + name: 'pageflip', + author: 'GruppoMeta', + css: 'css/style.css', + defaults: { + thumbnails: 'lazy', + transition: "fade", + transitionSpeed: 1500, + imageCrop: false, + thumbCrop: !0, + carousel: !1, + _locale: { + show_thumbnails: "Mostra le miniature", + hide_thumbnails: "Nascondi le miniature", + play: "Play slideshow", + pause: "Pause slideshow", + enter_fullscreen: "Entra fullscreen", + exit_fullscreen: "Esci fullscreen", + popout_image: "Pop image", + showing_image: "immagini %s di %s" + }, + _showFullscreen: !0, + _showPopout: !1, + _showProgress: !0, + _showTooltip: !0 + }, + init: function (b) { + this.addElement("bar", "fullscreen", "play", "popout", "thumblink", "delimiter1", "delimiter2", "delimiter3", "delimiter4", "progress"), this.append({ + stage: "progress", + container: ["bar", "tooltip"], + bar: ["fullscreen", "play", "popout", "thumblink", "info", "delimiter1", "delimiter2", "delimiter3", "delimiter4"] + }), this.prependChild("info", "counter"); + var c = this, + d = this.$("thumbnails-container"), + e = this.$("thumblink"), + f = this.$("fullscreen"), + g = this.$("play"), + h = this.$("popout"), + i = this.$("bar"), + j = this.$("progress"), + k = b.transition, + l = b._locale, + m = !1, + n = !1, + o = !! b.autoplay, + p = !1, + q = function () { + d.height(c.getStageHeight()).width(c.getStageWidth()).css("top", m ? 0 : c.getStageHeight() + 30) + }, r = function (a) { + m && p ? c.play() : (p = o, c.pause()), Galleria.utils.animate(d, { + top: m ? c.getStageHeight() + 30 : 0 + }, { + easing: "galleria", + duration: 400, + complete: function () { + c.defineTooltip("thumblink", m ? l.show_thumbnails : l.hide_thumbnails), e[m ? "removeClass" : "addClass"]("open"), m = !m + } + }) + }; + q(), b._showTooltip && c.bindTooltip({ + thumblink: l.show_thumbnails, + fullscreen: l.enter_fullscreen, + play: l.play, + popout: l.popout_image, + caption: function () { + var a = c.getData(), + b = ""; + return a && (a.title && a.title.length && (b += "<strong>" + a.title + "</strong>"), a.description && a.description.length && (b += "<br>" + a.description)), b + }, + counter: function () { + return l.showing_image.replace(/\%s/, c.getIndex() + 1).replace(/\%s/, c.getDataLength()) + } + }), b.showInfo || this.$("info").hide(), this.bind("play", function () { + o = !0, g.addClass("playing") + }), this.bind("pause", function () { + o = !1, g.removeClass("playing"), j.width(0) + }), b._showProgress && this.bind("progress", function (a) { + j.width(a.percent / 100 * this.getStageWidth()) + }), this.bind("loadstart", function (a) { + a.cached || this.$("loader").show() + }), this.bind("loadfinish", function (a) { + j.width(0), this.$("loader").hide(), this.refreshTooltip("counter", "caption"); + this.lazyLoadChunks( 10 ); + }), this.bind("thumbnail", function (b) { + a(b.thumbTarget).hover(function () { + c.setInfo(b.thumbOrder), c.setCounter(b.thumbOrder) + }, function () { + c.setInfo(), c.setCounter() + }).click(function () { + r() + }) + }), this.bind("fullscreen_enter", function (a) { + n = !0, c.setOptions("transition", !1), f.addClass("open"), i.css("bottom", 0), this.defineTooltip("fullscreen", l.exit_fullscreen), Galleria.TOUCH || this.addIdleState(i, { + bottom: 0 + }) + }), this.bind("fullscreen_exit", function (a) { + n = !1, Galleria.utils.clearTimer("bar"), c.setOptions("transition", k), f.removeClass("open"), i.css("bottom", 0), this.defineTooltip("fullscreen", l.enter_fullscreen), Galleria.TOUCH || this.removeIdleState(i, { + bottom: -31 + }) + }), this.bind("rescale", q), Galleria.TOUCH || (this.addIdleState(this.get("image-nav-left"), { + left: -36 + }), this.addIdleState(this.get("image-nav-right"), { + right: -36 + })), e.click(r), b._showPopout ? h.click(function (a) { + c.openLightbox(), a.preventDefault() + }) : (h.remove(), b._showFullscreen && (this.$("s4").remove(), this.$("info").css("right", 40), f.css("right", 0))), g.click(function () { + c.defineTooltip("play", o ? l.play : l.pause), o ? c.pause() : (m && e.click(), c.play()) + }), b._showFullscreen ? f.click(function () { + n ? c.exitFullscreen() : c.enterFullscreen() + }) : (f.remove(), b._show_popout && (this.$("s4").remove(), this.$("info").css("right", 40), h.css("right", 0))), !b._showFullscreen && !b._showPopout && (this.$("s3,s4").remove(), this.$("info").css("right", 10)), b.autoplay && this.trigger("play") + } + }) +})(jQuery) +$("#galleria").addClass("sfogliatore"); \ No newline at end of file diff --git a/src/static/galleria/themes/movio/galleria.slider.js b/src/static/galleria/themes/movio/galleria.slider.js new file mode 100644 index 0000000..ec23253 --- /dev/null +++ b/src/static/galleria/themes/movio/galleria.slider.js @@ -0,0 +1,105 @@ +(function (d) { + Galleria.addTheme({ + name: 'slider', + author: 'GruppoMeta', + css: 'css/style.css', + defaults: { + thumbnails: 'lazy', + transition: "pulse", + thumbCrop: true, + imageCrop: false, + carousel: false, + imagePan: true, + clicknext: true, + _locale: { + enter_fullscreen: "Enter fullscreen", + exit_fullscreen: "Exit fullscreen", + click_to_close: "Click to close", + show_thumbnails: "Show thumbnails", + show_info: "Show info" + } + }, + init: function (e) { + var c = this, + h = false, + b; + b = 0; + var f, j, i; + this.addElement("desc", "dots", "thumbs", "fs", "more"); + this.append({ + container: ["desc", "dots", + "thumbs", "fs", "info-description", "more" + ] + }); + i = this.$("thumbnails-container").hide().css("visibility", "visible"); + for (b = 0; b < this.getDataLength(); b++) this.$("dots").append(d("<div>").click(function (a) { + return function (g) { + g.preventDefault(); + c.show(a) + } + }(b))); + b = this.$("dots").outerWidth(); + f = this.$("desc").hide().hover(function () { + d(this).addClass("hover") + }, function () { + d(this).removeClass("hover") + }).click(function () { + d(this).hide() + }); + j = this.$("loader"); + this.bindTooltip({ + fs: function () { + return h ? e._locale.exit_fullscreen : + e._locale.enter_fullscreen + }, + desc: e._locale.click_to_close, + more: e._locale.show_info, + thumbs: e._locale.show_thumbnails + }); + this.bind("loadstart", function (a) { + a.cached || this.$("loader").show().fadeTo(200, 0.4) + }); + this.bind("loadfinish", function (a) { + var g = c.getData().title, + k = c.getData().description; + f.hide(); + j.fadeOut(200); + this.$("dots").children("div").eq(a.index).addClass("active").siblings(".active").removeClass("active"); + if (g && k) { + f.empty().append("<strong>" + g + "</strong>", "<p>" + k + "</p>").css({ + marginTop: this.$("desc").outerHeight() / -2 + }); + this.$("more").show() + } else this.$("more").hide(); + i.fadeOut(e.fadeSpeed); + c.$("thumbs").removeClass("active"); + this.lazyLoadChunks( 10 ); + }); + this.bind("thumbnail", function (a) { + d(a.thumbTarget).hover(function () { + c.setInfo(a.index) + }, function () { + c.setInfo() + }) + }); + this.$("fs").click(function () { + c.toggleFullscreen(); + h = !h + }); + this.$("thumbs").click(function (a) { + a.preventDefault(); + i.toggle(); + d(this).toggleClass("active"); + f.hide() + }); + this.$("more").click(function () { + f.toggle() + }); + this.$("info").css({ + width: this.getStageWidth() - b - 30, + left: b + 10 + }) + } + }) +})(jQuery); +// $("#galleria").addClass("slider"); \ No newline at end of file diff --git a/src/static/galleria/themes/movio/galleria.slideshow.js b/src/static/galleria/themes/movio/galleria.slideshow.js new file mode 100644 index 0000000..bec20e8 --- /dev/null +++ b/src/static/galleria/themes/movio/galleria.slideshow.js @@ -0,0 +1,116 @@ +// JavaScript Document + +(function (a) { + Galleria.addTheme({ + name: 'slideshow', + author: 'GruppoMeta', + css: 'css/style.css', + defaults: { + thumbnails: 'lazy', + transition: "fade", + transitionSpeed: 1500, + imageCrop: !1, + thumbCrop: !0, + carousel: !1, + _locale: { + show_thumbnails: "Mostra le miniature", + hide_thumbnails: "Nascondi le miniature", + play: "Play slideshow", + pause: "Pause slideshow", + enter_fullscreen: "Entra fullscreen", + exit_fullscreen: "Esci fullscreen", + popout_image: "Pop image", + showing_image: "immagini %s di %s" + }, + _showFullscreen: !0, + _showPopout: !1, + _showProgress: !0, + _showTooltip: !0 + }, + init: function (b) { + this.addElement("bar", "fullscreen", "play", "popout", "thumblink", "delimiter1", "delimiter2", "delimiter3", "delimiter4", "progress"), this.append({ + stage: "progress", + container: ["bar", "tooltip"], + bar: ["fullscreen", "play", "popout", "thumblink", "info", "delimiter1", "delimiter2", "delimiter3", "delimiter4"] + }), this.prependChild("info", "counter"); + var c = this, + d = this.$("thumbnails-container"), + e = this.$("thumblink"), + f = this.$("fullscreen"), + g = this.$("play"), + h = this.$("popout"), + i = this.$("bar"), + j = this.$("progress"), + k = b.transition, + l = b._locale, + m = !1, + n = !1, + o = !! b.autoplay, + p = !1, + q = function () { + d.height(c.getStageHeight()).width(c.getStageWidth()).css("top", m ? 0 : c.getStageHeight() + 30) + }, r = function (a) { + m && p ? c.play() : (p = o, c.pause()), Galleria.utils.animate(d, { + top: m ? c.getStageHeight() + 30 : 0 + }, { + easing: "galleria", + duration: 400, + complete: function () { + c.defineTooltip("thumblink", m ? l.show_thumbnails : l.hide_thumbnails), e[m ? "removeClass" : "addClass"]("open"), m = !m + } + }) + }; + q(), b._showTooltip && c.bindTooltip({ + thumblink: l.show_thumbnails, + fullscreen: l.enter_fullscreen, + play: l.play, + popout: l.popout_image, + caption: function () { + var a = c.getData(), + b = ""; + return a && (a.title && a.title.length && (b += "<strong>" + a.title + "</strong>"), a.description && a.description.length && (b += "<br>" + a.description)), b + }, + counter: function () { + return l.showing_image.replace(/\%s/, c.getIndex() + 1).replace(/\%s/, c.getDataLength()) + } + }), b.showInfo || this.$("info").hide(), this.bind("play", function () { + o = !0, g.addClass("playing") + }), this.bind("pause", function () { + o = !1, g.removeClass("playing"), j.width(0) + }), b._showProgress && this.bind("progress", function (a) { + j.width(a.percent / 100 * this.getStageWidth()) + }), this.bind("loadstart", function (a) { + a.cached || this.$("loader").show() + }), this.bind("loadfinish", function (a) { + j.width(0), this.$("loader").hide(), this.refreshTooltip("counter", "caption") + this.lazyLoadChunks( 10 ); + }), this.bind("thumbnail", function (b) { + a(b.thumbTarget).hover(function () { + c.setInfo(b.thumbOrder), c.setCounter(b.thumbOrder) + }, function () { + c.setInfo(), c.setCounter() + }).click(function () { + r() + }) + }), this.bind("fullscreen_enter", function (a) { + n = !0, c.setOptions("transition", !1), f.addClass("open"), i.css("bottom", 0), this.defineTooltip("fullscreen", l.exit_fullscreen), Galleria.TOUCH || this.addIdleState(i, { + bottom: 0 + }) + }), this.bind("fullscreen_exit", function (a) { + n = !1, Galleria.utils.clearTimer("bar"), c.setOptions("transition", k), f.removeClass("open"), i.css("bottom", 0), this.defineTooltip("fullscreen", l.enter_fullscreen), Galleria.TOUCH || this.removeIdleState(i, { + bottom: -31 + }) + }), this.bind("rescale", q), Galleria.TOUCH || (this.addIdleState(this.get("image-nav-left"), { + left: -36 + }), this.addIdleState(this.get("image-nav-right"), { + right: -36 + })), e.click(r), b._showPopout ? h.click(function (a) { + c.openLightbox(), a.preventDefault() + }) : (h.remove(), b._showFullscreen && (this.$("s4").remove(), this.$("info").css("right", 40), f.css("right", 0))), g.click(function () { + c.defineTooltip("play", o ? l.play : l.pause), o ? c.pause() : (m && e.click(), c.play()) + }), b._showFullscreen ? f.click(function () { + n ? c.exitFullscreen() : c.enterFullscreen() + }) : (f.remove(), b._show_popout && (this.$("s4").remove(), this.$("info").css("right", 40), h.css("right", 0))), !b._showFullscreen && !b._showPopout && (this.$("s3,s4").remove(), this.$("info").css("right", 10)), b.autoplay && this.trigger("play") + } + }) +})(jQuery) diff --git a/src/static/galleria/themes/movio/less/gallery.less b/src/static/galleria/themes/movio/less/gallery.less new file mode 100755 index 0000000..846b7ec --- /dev/null +++ b/src/static/galleria/themes/movio/less/gallery.less @@ -0,0 +1,343 @@ +.wrapper-galleria-io.gallery { + #galleria{height:500px} + + .content-galleria-io { + color:#777; + font-family:@font; + font-size:11px; + position:relative; + } + + .galleria-container { + position: relative; + overflow: hidden; + + img { + -moz-user-select: none; + -webkit-user-select: none; + -o-user-select: none; + -moz-transition:none; + -webkit-transition:none; + -o-transition:none; + transition:none; + } + + } + + /* main img */ + + .galleria-stage { + position: absolute; + top:0px; + bottom: 60px; + left:0px; + background: #202020; + right:0px; + min-height:459px; + overflow: hidden; + } + + /* thumb container */ + + .galleria-thumbnails-list { + width:275px; + position:absolute!important; + right:0!important; + margin-right:100px; + + @media (max-width: 765px) { + display:none!important; + } + + } + + .galleria-thumbnails-container { + height:40px; + bottom:0; + margin-bottom:0; + position: absolute; + left:0px; + right:0px; + z-index: 0; + background:#202020; + border-top:1px solid #000000; + + + } + + .delimiter, .galleria-container-delimeter { + width:1px; + background:#000; + height:40px; + display:block; + position:absolute; + right:0; + margin-bottom:0; + margin-right:90px; + bottom:0; + } + + .galleria-thumbnails { + margin-top:5px; + + .galleria-image { + height: 27px; + width: 40px; + background: #202020; + margin: 0 8px 0 0; + float: left; + cursor: pointer; + + &.active { + border:1px solid #BABABA; + } + + } + + } + + /* counter img */ + + .galleria-counter { + position: absolute; + bottom:0px; + right:0; + margin-bottom:9px; + text-align: center; + color: #fff; + z-index:2; + margin-right:40px; + font-size: 90%; + width: 40px; + } + + .galleria-loader { + background: #000; + width: 32px; + height: 32px; + position: absolute; + top: 16px; + right: 16px; + z-index: 2; + display: none; + background: url(loader_black.gif) no-repeat 2px 2px; + } + + /* title e description */ + + .galleria-info { + width: 50%; + bottom:0px; + left: 15px; + z-index: 2; + margin-bottom:5px; + position: absolute; + + + } + .galleria-info-text { + display: none; + /* IE7 */ zoom:1; + } + .galleria-info-title { + margin: 0; + color: #fff; + line-height:1.1em; + margin-bottom:6px; + height:28px; + overflow:hidden; + font-size:12px; + margin-bottom:-5px; + + @media (max-width: 765px) { + margin-bottom:-5px; + } + + } + .galleria-info-description { + margin: 0; + color: #bbb; + line-height:1.4em; + + @media (max-width: 765px) { + display:none!important; + } + } + + /* buttons */ + + .galleria-info-close { + width: 9px; + height: 9px; + position: absolute; + top: 5px; + right: 5px; + background-position: -753px -11px; + opacity: .5; + filter: alpha(opacity=50); + cursor: pointer; + z-index:9; + } + + .galleria-fscr { + width:10px; + height:10px; + position:absolute; + bottom:0px; + margin-bottom:14px; + right:10px; + z-index:4; + cursor: pointer; + opacity:0.7; + filter: alpha(opacity=70); + background-position: -840px -11px; + + &.active-fscr { + background-position: -927px -11px; + } + } + + .galleria-fscr:hover{ + opacity:1!important; + filter: alpha(opacity=100)!important; + } + + + .notouch .galleria-info-close:hover{ + opacity:1; + filter: alpha(opacity=100); + } + .touch .galleria-info-close:active{ + opacity:1; + filter: alpha(opacity=100); + } + .galleria-info-link { + background-position: -669px -5px; + opacity: .7; + filter: alpha(opacity=70); + position: absolute; + width: 20px; + height: 20px; + cursor: pointer; + background-color: #000; + } + .notouch .galleria-info-link:hover { + opacity: 1; + filter: alpha(opacity=100); + } + .touch .galleria-info-link:active { + opacity: 1; + filter: alpha(opacity=100); + } + + + /* controller main img */ + + .galleria-image-nav { + position: absolute; + top: 50%; + margin-top: -62px; + width: 100%; + height: 62px; + left: 0; + display:none; + + @media (max-width: 765px) { + display:block!important; + } + + } + .galleria-image-nav-left, + .galleria-image-nav-right { + opacity: .3; + filter: alpha(opacity=30); + cursor: pointer; + width: 62px; + height: 124px; + position: absolute; + left: 10px; + z-index: 2; + background-position: 0 46px; + } + .galleria-image-nav-right { + left: auto; + right:10px; + background-position: -260px 46px; + z-index: 2; + } + .notouch .galleria-image-nav-left:hover, + .notouch .galleria-image-nav-right:hover { + opacity: 1; + filter: alpha(opacity=100); + } + .touch .galleria-image-nav-left:active, + .touch .galleria-image-nav-right:active { + opacity: 1; + filter: alpha(opacity=100); + } + + /* controller thumb */ + + .galleria-thumb-nav-left, + .galleria-thumb-nav-right { + cursor: pointer; + display: none; + background-position: -495px 5px; + position: absolute; + right: 0; + top: 0; + height: 40px; + width: 23px; + z-index: 3; + opacity:0.7; + filter: alpha(opacity=70); + margin-right:70px; + + @media (max-width: 765px) { + display:none!important; + } + + } + .galleria-thumb-nav-right { + background-position: -578px 5px; + border-right: none; + right: 0; + margin-right:26px; + } + .galleria-thumbnails-container .disabled { + opacity: .3; + filter: alpha(opacity=30); + cursor: default; + } + .notouch .galleria-thumb-nav-left:hover, + .notouch .galleria-thumb-nav-right:hover { + opacity: 1; + filter: alpha(opacity=100); + } + .touch .galleria-thumb-nav-left:active, + .touch .galleria-thumb-nav-right:active { + opacity: 1; + filter: alpha(opacity=100); + } + .notouch .galleria-thumbnails-container .disabled:hover { + opacity: .3; + filter: alpha(opacity=30); + background-color: transparent; + } + + .galleria-carousel .galleria-thumb-nav-left, + .galleria-carousel .galleria-thumb-nav-right { + display: block; + } + .galleria-thumb-nav-left, + .galleria-thumb-nav-right, + .galleria-info-link, + .galleria-info-close, + .galleria-image-nav-left, + .galleria-image-nav-right, + .galleria-fscr { + background-image: url(sprite.png); + background-repeat: no-repeat; + } + +} \ No newline at end of file diff --git a/src/static/galleria/themes/movio/less/pageflip.less b/src/static/galleria/themes/movio/less/pageflip.less new file mode 100755 index 0000000..e86aa8d --- /dev/null +++ b/src/static/galleria/themes/movio/less/pageflip.less @@ -0,0 +1,315 @@ +.wrapper-galleria-io.pageflip { + .content-galleria-io { + color:#777; + font-family:@font; + font-size:11px; + position:relative; + } + + .galleria-container { + position: relative; + overflow: hidden; + + img { + -moz-user-select: none; + -webkit-user-select: none; + -o-user-select: none; + -moz-transition:none; + -webkit-transition:none; + -o-transition:none; + transition:none; + } + + } + + /* main img */ + + .galleria-stage { + overflow: hidden; + background: #202020; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom:20px; + min-height:459px; + } + + /* bottom element */ + + .galleria-container.fullscreen .galleria-stage { bottom: 0 } + .galleria-bar { + height:20px; + width: 100%; + position: absolute; + bottom: 0; + left: 0; + background:#202020; + border-top:1px solid #000000; + z-index: 3; + } + + /* delimiter */ + + .galleria-delimiter1, + .galleria-delimiter2, + .galleria-delimiter3, + .galleria-delimiter4 { + width:1px; + background:#000; + height:20px; + position: absolute; + left: 20px; + bottom: 1px; + display:none; + } + .galleria-delimiter2 { left: 80px } + + .galleria-delimiter3 { + right: 41px; + left: auto; + } + .galleria-delimiter4 { + right: 58px; + left: auto; + display:none; + } + + /* progress bar load image in play mode */ + + .galleria-progress { + height: 2px; + position: absolute; + top: 0; + left: 0; + width: 0; + background: #fff; + opacity:0.5; + z-index: 3; + filter: alpha(opacity=50); + } + + /* button */ + + .galleria-thumblink, + .galleria-fullscreen, + .galleria-play, + .galleria-popout { + width: 19px; + height: 19px; + position: absolute; + left: 0; + bottom:0; + cursor: pointer; + background:url(sprite.png) no-repeat; + } + + .galleria-play { + background-position: -1088px 3px; + opacity: .7; + filter: alpha(opacity=70); + display:none; + } + + .galleria-fullscreen { + background-position: -835px -6px; + opacity: .7; + filter: alpha(opacity=70); + right:0; + margin-right:31px; + left:auto; + + &.open { + background-position: -922px -6px; + } + + } + + .galleria-thumblink { + background-position: -1011px -7px; + opacity: .7; + filter: alpha(opacity=70); + right:0; + left:auto; + margin-right:6px; + } + + .galleria-container.notouch .galleria-play:hover, + .galleria-container.touch .galleria-play:active, + .galleria-container.notouch .galleria-thumblink:hover, + .galleria-container.touch .galleria-thumblink:active, + .galleria-thumblink.open, + .galleria-container.notouch .galleria-fullscreen:hover, + .galleria-container.touch .galleria-fullscreen:active, + .galleria-container.notouch .galleria-popout:hover, + .galleria-container.touch .galleria-popout:active { + opacity:1; + filter: alpha(opacity=100); + } + + .galleria-play.playing { + background-position: -1165px 3px; + opacity:.7; + filter: alpha(opacity=70); + + &:hover { + opacity:1; + filter: alpha(opacity=100); + } + + } + + .galleria-popout { + display:none; + } + + + .galleria-thumbnails-container { + position: absolute; + top: 0; + left: auto; + right:0; + width: 0; + height: 0; + margin-right:-10px; + background:#202020; + width:215px!important; + z-index: 2; + overflow:auto; + } + .galleria-thumbnails-list { + position: absolute!important; + top: 10px; + right: 10px; + left: 10px; + bottom: 0; + overflow: auto!important; + } + .galleria-thumbnails .galleria-image { + width: 80px; + height: 45px; + float: left; + margin: 0 7px 7px 0; + border: 1px solid #BABABA; + cursor: pointer; + } + .galleria-container.notouch .galleria-thumbnails .galleria-image:hover, + .galleria-container.touch .galleria-thumbnails .galleria-image:active { + opacity: .9; + box-shadow: 0 0 3px rgba(0,0,0,.4); + -moz-box-shadow: 0 0 3px rgba(0,0,0,.4); + -webkit-box-shadow: 0 0 3px rgba(0,0,0,.4); + } + .galleria-info { + position: absolute; + height:15px; + left:0px; + bottom:0; + margin-bottom:2px!important; + color: #bbb; + margin-right:40px; + } + .galleria-info > *, + .galleria-info-text > * { display: inline; } + .galleria-info-title { + color: #fff; + padding:0 0; + margin-bottom:0px; + margin-top:0; + margin-right:10px; + } + .galleria-info-text { padding-left: 10px;} + .galleria-counter { + background: url(separator.png) no-repeat 100% 0; + display: inline-block; + *display: inline; + padding-right: 10px; + _height: 29px; + zoom: 1; + display:none + } + + .galleria-loader { + background: #000; + width: 32px; + height: 32px; + position: absolute; + top: 16px; + right: 16px; + z-index: 2; + display: none; + background: url(loader_black.gif) no-repeat 2px 2px; + } + + /* controller main img */ + + .galleria-image-nav { + position: absolute; + top: 50%; + margin-top: -62px; + width: 100%; + height: 62px; + left: 0; + } + + .galleria-image-nav-left, + .galleria-image-nav-right { + opacity: .3; + filter: alpha(opacity=30); + cursor: pointer; + width: 62px; + height: 124px; + position: absolute; + left: 10px; + z-index: 2; + background-position: 0 46px; + } + .galleria-image-nav-right { + left: auto; + right:10px; + background-position: -260px 46px; + z-index: 2; + } + .notouch .galleria-image-nav-left:hover, + .notouch .galleria-image-nav-right:hover { + opacity: 1; + filter: alpha(opacity=100); + } + .touch .galleria-image-nav-left:active, + .touch .galleria-image-nav-right:active { + opacity: 1; + filter: alpha(opacity=100); + } + + + .galleria-thumb-nav-right { + background-position: -578px 5px; + border-right: none; + right: 0; + left: auto; + } + .galleria-thumbnails-container .disabled, + .galleria-thumbnails-container .disabled:hover, + .galleria-thumbnails-container .disabled:active { + opacity: .2; + cursor: default; + } + .galleria-container.notouch .galleria-thumb-nav-left:hover, + .galleria-container.touch .galleria-thumb-nav-left:active, + .galleria-container.notouch .galleria-thumb-nav-right:hover, + .galleria-container.touch .galleria-thumb-nav-right:active { + opacity: 1; + background-color: #111; + } + .galleria-carousel .galleria-thumb-nav-left, + .galleria-carousel .galleria-thumb-nav-right { display: block } + .galleria-lightbox-content { background: url(loader_pos.gif) no-repeat 50% 50% } + + .galleria-thumb-nav-left, + .galleria-thumb-nav-right, + .galleria-image-nav-left, + .galleria-image-nav-right { + background-image: url(sprite.png); + background-repeat: no-repeat; + } +} \ No newline at end of file diff --git a/src/static/galleria/themes/movio/less/slider.less b/src/static/galleria/themes/movio/less/slider.less new file mode 100755 index 0000000..44e81e1 --- /dev/null +++ b/src/static/galleria/themes/movio/less/slider.less @@ -0,0 +1,252 @@ +.wrapper-galleria-io.slider { + + #galleria{height:490px} + + .content-galleria-io { + color:#777; + font-family:@font; + font-size:11px; + position:relative; + margin-left:30px; + + } + + .galleria-container { + position: relative; + + img { + -moz-user-select: none; + -webkit-user-select: none; + -o-user-select: none; + -moz-transition:none; + -webkit-transition:none; + -o-transition:none; + transition:none; + } + + } + + /* main img */ + + .galleria-stage { + background: #fff; + position: relative; + padding:5px; + top: 0; + left: 0; + right: 0; + min-height:459px; + border:1px solid #C6C6C6; + .border-radius (2px); + .glow(#F3F3F3); + margin-right:40px; + } + + .galleria-dots { + position:absolute; + height:10px; + bottom:0; + right:0; + margin-right:35px; + + @media (max-width: 765px) { + display:none!important; + } + + } + .galleria-dots div { + width:10px; + height:10px; + margin-right:5px; + background:#ddd; + float:left; + cursor:pointer; + .border-radius(100%); + } + .galleria-dots div:hover { + background-color:#333; + } + .galleria-dots div.active { + background-color:#333; + } + .galleria-fs, + .galleria-thumbs, + .galleria-more { + width:10px; + height:10px; + cursor:pointer; + background:#222; + position:absolute; + bottom:0; + right:0; + } + .galleria-fs{ + display:none; + } + .galleria-thumbs{ + right:15px; + display:none; + } + .galleria-more{ + right:30px; + display:none!important; + } + + .galleria-counter { + display:none; + } + .galleria-loader { + width: 32px; + height: 32px; + background: #fff url(loader_white.gif) no-repeat 50% 50%; + position: absolute; + top: 50%; + left: 50%; + margin-top: -16px; + margin-left: -16px; + z-index: 3; + display:none; + } + + .galleria-info { + position: absolute; + bottom:0px; + left:0!important; + } + .galleria-info-title { + display:inline; + color:#000; + font-size:12px; + line-height:1.1em; + height:28px; + position:absolute; + overflow:hidden; + } + .galleria-info-description { + display:none!important; + } + .galleria-desc { + position:absolute; + width:auto; + top:50%; + left:50%; + margin-left:-15%; + background:#fff; + border:5px solid #fff; + padding:5px; + z-index:2; + font:11px/14px arial,sans-serif; + display:none; + color:#777; + cursor:pointer; + } + .galleria-desc.hover{ + background:#fff; + } + .galleria-desc strong{ + color:#222; + font-weight:normal; + margin-bottom:5px; + display:block; + } + .galleria-desc p{ + margin-bottom:0; + } + + /* controller main img */ + + .galleria-image-nav { + position: absolute; + top: 50%; + margin-top: -62px; + width: 100%; + height: 62px; + left: 0; + } + + .galleria-image-nav-left, + .galleria-image-nav-right { + opacity:1; + filter: alpha(opacity=100); + cursor: pointer; + width:20px; + height: 124px; + position: absolute; + left:0px; + z-index: 2; + + &.disabled { + opacity: .5; + filter: alpha(opacity=50); + } + + } + + .galleria-image-nav-left { + background: url(../css/controller-left.png) 0 50% no-repeat; + margin-left:-30px; + left:0; + + &:hover { + background: url(../css/controller-left-hover.png) 0 50% no-repeat; + } + + } + .galleria-image-nav-right { + left: auto; + right:0px; + background-position: -260px 46px; + z-index: 2; + margin-right:-30px; + } + + .galleria-image-nav-right { + background: url(../css/controller-right.png) 0 50% no-repeat; + + &:hover { + background: url(../css/controller-right-hover.png) 0 50% no-repeat; + } + + } + + .notouch .galleria-image-nav-left:hover, + .notouch .galleria-image-nav-right:hover { + opacity: 1; + filter: alpha(opacity=100); + } + .touch .galleria-image-nav-left:active, + .touch .galleria-image-nav-right:active { + opacity: 1; + filter: alpha(opacity=100); + } + + .galleria-thumbnails-container { + position:absolute; + top:0; + bottom:20px; + left:0; + right:0; + z-index:2; + overflow:hidden; + visibility: hidden; + } + .galleria-thumbnails { + margin:10px; + } + .galleria-thumbnails .galleria-image { + height: 50px; + width:80px; + background: #d77; + margin: 2px 8px 8px 2px; + float: left; + cursor: pointer; + -moz-box-shadow: 0 0 2px rgb(0,0,0); + -webkit-box-shadow: 0 0 2px rgb(0,0,0); + box-shadow: 0 0 2px rgb(0,0,0); + } + .galleria-thumbnails .galleria-image img:hover { + opacity:.1!important; + filter: alpha(opacity=10)!important; + } + +} diff --git a/src/static/galleria/themes/movio/less/slideshow.less b/src/static/galleria/themes/movio/less/slideshow.less new file mode 100755 index 0000000..91d291b --- /dev/null +++ b/src/static/galleria/themes/movio/less/slideshow.less @@ -0,0 +1,331 @@ +.wrapper-galleria-io.slideshow { + + #galleria{height:500px} + + .content-galleria-io { + color:#777; + font-family:@font; + font-size:11px; + position:relative; + } + + .galleria-container { + position: relative; + overflow: hidden; + + img { + -moz-user-select: none; + -webkit-user-select: none; + -o-user-select: none; + -moz-transition:none; + -webkit-transition:none; + -o-transition:none; + transition:none; + } + + } + + /* main img */ + + .galleria-stage { + overflow: hidden; + background: #202020; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom:60px; + min-height:459px; + } + + /* bottom element */ + + .galleria-container.fullscreen .galleria-stage { bottom: 0 } + .galleria-bar { + height:40px; + width: 100%; + position: absolute; + bottom: 0; + left: 0; + background:#202020; + border-top:1px solid #000000; + z-index: 3; + } + + /* delimiter */ + + .galleria-delimiter1, + .galleria-delimiter2, + .galleria-delimiter3, + .galleria-delimiter4 { + width:1px; + background:#000; + height:40px; + position: absolute; + left: 40px; + bottom: 1px; + } + .galleria-delimiter2 { left: 80px } + + .galleria-delimiter3 { + right: 41px; + left: auto; + } + .galleria-delimiter4 { + right: 58px; + left: auto; + display:none; + } + + /* progress bar load image in play mode */ + + .galleria-progress { + height: 2px; + position: absolute; + top: 0; + left: 0; + width: 0; + background: #fff; + opacity:0.5; + z-index: 3; + filter: alpha(opacity=50); + } + + /* button */ + + .galleria-thumblink, + .galleria-fullscreen, + .galleria-play, + .galleria-popout { + width: 39px; + height: 39px; + position: absolute; + left: 0; + bottom:0; + z-index:9; + cursor: pointer; + background:url(sprite.png) no-repeat; + } + + .galleria-play { + background-position: -1088px 3px; + opacity: .7; + filter: alpha(opacity=70); + } + + .galleria-fullscreen { + background-position: -825px 3px; + opacity: .7; + filter: alpha(opacity=70); + left:41px; + + &.open { + background-position: -912px 3px; + } + + } + + .galleria-thumblink { + background-position: -1003px 3px; + opacity: .7; + filter: alpha(opacity=70); + right:0; + left:auto; + } + + .galleria-container.notouch .galleria-play:hover, + .galleria-container.touch .galleria-play:active, + .galleria-container.notouch .galleria-thumblink:hover, + .galleria-container.touch .galleria-thumblink:active, + .galleria-thumblink.open, + .galleria-container.notouch .galleria-fullscreen:hover, + .galleria-container.touch .galleria-fullscreen:active, + .galleria-container.notouch .galleria-popout:hover, + .galleria-container.touch .galleria-popout:active { + opacity:1; + filter: alpha(opacity=100); + } + + .galleria-play.playing { + background-position: -1165px 3px; + opacity:.7; + filter: alpha(opacity=70); + + &:hover { + opacity:1; + filter: alpha(opacity=100); + } + + } + + .galleria-popout { + display:none; + } + + + .galleria-thumbnails-container { + position: absolute; + top: 0; + left: 0; + width: 0; + height: 0; + background: url(bg-thumb.png); + z-index: 2; + } + .galleria-thumbnails-list { + position: absolute!important; + top: 10px; + right: 10px; + left: 10px; + bottom: 41px; + overflow: auto!important; + } + .galleria-thumbnails .galleria-image { + width: 80px; + height: 45px; + float: left; + margin: 0 7px 7px 0; + border:3px solid #fff; + cursor: pointer; + } + .galleria-container.notouch .galleria-thumbnails .galleria-image:hover, + .galleria-container.touch .galleria-thumbnails .galleria-image:active { + opacity: .9; + box-shadow: 0 0 3px rgba(0,0,0,.4); + -moz-box-shadow: 0 0 3px rgba(0,0,0,.4); + -webkit-box-shadow: 0 0 3px rgba(0,0,0,.4); + } + + .galleria-info { + width:90%; + bottom:0px; + z-index: 2; + margin-bottom:0; + position: absolute; + color: #bbb; + left:0; + margin-right:40px; + } + + .galleria-info > *, + .galleria-info-text > * { display: block } + .galleria-info-title { + color: #fff; + padding:0 0; + margin-bottom:3px; + margin-top:8px; + } + + .galleria-info-description { + margin-left:90px; + line-height:1.4em; + } + + .galleria-info-title { + left:0; + margin-left:90px; + margin-bottom:0; + font-size: 12px; + font-size:12px; + line-height:1.1em; + height:28px; + overflow:hidden; + } + + .galleria-info-text { padding-left: 10px;line-height:1em;margin-bottom:-5px;} + .galleria-counter { + display: inline-block; + *display: inline; + padding-right: 10px; + _height: 29px; + zoom: 1; + display:none + } + + .galleria-loader { + background: #000; + width: 32px; + height: 32px; + position: absolute; + top: 16px; + right: 16px; + z-index: 2; + display: none; + background: url(loader_black.gif) no-repeat 2px 2px; + } + + /* controller main img */ + + .galleria-image-nav { + position: absolute; + top: 50%; + margin-top: -62px; + width: 100%; + height: 62px; + left: 0; + } + + .galleria-image-nav-left, + .galleria-image-nav-right { + opacity: .3; + filter: alpha(opacity=30); + cursor: pointer; + width: 62px; + height: 124px; + position: absolute; + left: 10px; + z-index: 2; + background-position: 0 46px; + } + .galleria-image-nav-right { + left: auto; + right:10px; + background-position: -260px 46px; + z-index: 2; + } + .notouch .galleria-image-nav-left:hover, + .notouch .galleria-image-nav-right:hover { + opacity: 1; + filter: alpha(opacity=100); + } + .touch .galleria-image-nav-left:active, + .touch .galleria-image-nav-right:active { + opacity: 1; + filter: alpha(opacity=100); + } + + + .galleria-thumb-nav-right { + background-position: -578px 5px; + border-right: none; + right: 0; + left: auto; + } + .galleria-thumbnails-container .disabled, + .galleria-thumbnails-container .disabled:hover, + .galleria-thumbnails-container .disabled:active { + opacity: .2; + cursor: default; + } + .galleria-container.notouch .galleria-thumb-nav-left:hover, + .galleria-container.touch .galleria-thumb-nav-left:active, + .galleria-container.notouch .galleria-thumb-nav-right:hover, + .galleria-container.touch .galleria-thumb-nav-right:active { + opacity: 1; + background-color: #111; + } + .galleria-carousel .galleria-thumb-nav-left, + .galleria-carousel .galleria-thumb-nav-right { display: block } + .galleria-lightbox-content { background: url(loader_pos.gif) no-repeat 50% 50% } + + .galleria-thumb-nav-left, + .galleria-thumb-nav-right, + .galleria-image-nav-left, + .galleria-image-nav-right { + background-image: url(sprite.png); + background-repeat: no-repeat; + } + + .galleria-tooltip{display: none;} + +} \ No newline at end of file diff --git a/src/static/galleria/themes/movio/less/style.less b/src/static/galleria/themes/movio/less/style.less new file mode 100755 index 0000000..1ae4c4e --- /dev/null +++ b/src/static/galleria/themes/movio/less/style.less @@ -0,0 +1,23 @@ +@import "gallery.less"; +@import "pageflip.less"; +@import "slider.less"; +@import "slideshow.less"; + +@font:Arial, Helvetica, sans-serif; + +#galleria-loader{height:1px!important} + +#galleria{height:500px} + + +.border-radius (@radius) { + border-radius: @radius; + -moz-border-radius: @radius; + -webkit-border-radius: @radius; +} + +.glow (@color) { +-moz-box-shadow: inset -1px 1px 1px @color; +-webkit-box-shadow: inset -1px 1px 1px @color; +box-shadow: inset -1px 1px 1px @color; +} diff --git a/src/static/handlebars/handlebars-1.0.rc.1.js b/src/static/handlebars/handlebars-1.0.rc.1.js new file mode 100644 index 0000000..0534637 --- /dev/null +++ b/src/static/handlebars/handlebars-1.0.rc.1.js @@ -0,0 +1,1920 @@ +// lib/handlebars/base.js + +/*jshint eqnull:true*/ +this.Handlebars = {}; + +(function(Handlebars) { + +Handlebars.VERSION = "1.0.rc.1"; + +Handlebars.helpers = {}; +Handlebars.partials = {}; + +Handlebars.registerHelper = function(name, fn, inverse) { + if(inverse) { fn.not = inverse; } + this.helpers[name] = fn; +}; + +Handlebars.registerPartial = function(name, str) { + this.partials[name] = str; +}; + +Handlebars.registerHelper('helperMissing', function(arg) { + if(arguments.length === 2) { + return undefined; + } else { + throw new Error("Could not find property '" + arg + "'"); + } +}); + +var toString = Object.prototype.toString, functionType = "[object Function]"; + +Handlebars.registerHelper('blockHelperMissing', function(context, options) { + var inverse = options.inverse || function() {}, fn = options.fn; + + + var ret = ""; + var type = toString.call(context); + + if(type === functionType) { context = context.call(this); } + + if(context === true) { + return fn(this); + } else if(context === false || context == null) { + return inverse(this); + } else if(type === "[object Array]") { + if(context.length > 0) { + return Handlebars.helpers.each(context, options); + } else { + return inverse(this); + } + } else { + return fn(context); + } +}); + +Handlebars.K = function() {}; + +Handlebars.createFrame = Object.create || function(object) { + Handlebars.K.prototype = object; + var obj = new Handlebars.K(); + Handlebars.K.prototype = null; + return obj; +}; + +Handlebars.registerHelper('each', function(context, options) { + var fn = options.fn, inverse = options.inverse; + var ret = "", data; + + if (options.data) { + data = Handlebars.createFrame(options.data); + } + + if(context && context.length > 0) { + for(var i=0, j=context.length; i<j; i++) { + if (data) { data.index = i; } + ret = ret + fn(context[i], { data: data }); + } + } else { + ret = inverse(this); + } + return ret; +}); + +Handlebars.registerHelper('if', function(context, options) { + var type = toString.call(context); + if(type === functionType) { context = context.call(this); } + + if(!context || Handlebars.Utils.isEmpty(context)) { + return options.inverse(this); + } else { + return options.fn(this); + } +}); + +Handlebars.registerHelper('unless', function(context, options) { + var fn = options.fn, inverse = options.inverse; + options.fn = inverse; + options.inverse = fn; + + return Handlebars.helpers['if'].call(this, context, options); +}); + +Handlebars.registerHelper('with', function(context, options) { + return options.fn(context); +}); + +Handlebars.registerHelper('log', function(context) { + Handlebars.log(context); +}); + +}(this.Handlebars)); +; +// lib/handlebars/compiler/parser.js +/* Jison generated parser */ +var handlebars = (function(){ +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"root":3,"program":4,"EOF":5,"statements":6,"simpleInverse":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"inMustache":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"OPEN_PARTIAL":24,"params":25,"hash":26,"DATA":27,"param":28,"STRING":29,"INTEGER":30,"BOOLEAN":31,"hashSegments":32,"hashSegment":33,"ID":34,"EQUALS":35,"pathSegments":36,"SEP":37,"$accept":0,"$end":1}, +terminals_: {2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"OPEN_PARTIAL",27:"DATA",29:"STRING",30:"INTEGER",31:"BOOLEAN",34:"ID",35:"EQUALS",37:"SEP"}, +productions_: [0,[3,2],[4,3],[4,1],[4,0],[6,1],[6,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,3],[13,4],[7,2],[17,3],[17,2],[17,2],[17,1],[17,1],[25,2],[25,1],[28,1],[28,1],[28,1],[28,1],[28,1],[26,1],[32,2],[32,1],[33,3],[33,3],[33,3],[33,3],[33,3],[21,1],[36,3],[36,1]], +performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + +var $0 = $$.length - 1; +switch (yystate) { +case 1: return $$[$0-1]; +break; +case 2: this.$ = new yy.ProgramNode($$[$0-2], $$[$0]); +break; +case 3: this.$ = new yy.ProgramNode($$[$0]); +break; +case 4: this.$ = new yy.ProgramNode([]); +break; +case 5: this.$ = [$$[$0]]; +break; +case 6: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; +break; +case 7: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1].inverse, $$[$0-1], $$[$0]); +break; +case 8: this.$ = new yy.BlockNode($$[$0-2], $$[$0-1], $$[$0-1].inverse, $$[$0]); +break; +case 9: this.$ = $$[$0]; +break; +case 10: this.$ = $$[$0]; +break; +case 11: this.$ = new yy.ContentNode($$[$0]); +break; +case 12: this.$ = new yy.CommentNode($$[$0]); +break; +case 13: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]); +break; +case 14: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]); +break; +case 15: this.$ = $$[$0-1]; +break; +case 16: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1]); +break; +case 17: this.$ = new yy.MustacheNode($$[$0-1][0], $$[$0-1][1], true); +break; +case 18: this.$ = new yy.PartialNode($$[$0-1]); +break; +case 19: this.$ = new yy.PartialNode($$[$0-2], $$[$0-1]); +break; +case 20: +break; +case 21: this.$ = [[$$[$0-2]].concat($$[$0-1]), $$[$0]]; +break; +case 22: this.$ = [[$$[$0-1]].concat($$[$0]), null]; +break; +case 23: this.$ = [[$$[$0-1]], $$[$0]]; +break; +case 24: this.$ = [[$$[$0]], null]; +break; +case 25: this.$ = [[new yy.DataNode($$[$0])], null]; +break; +case 26: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; +break; +case 27: this.$ = [$$[$0]]; +break; +case 28: this.$ = $$[$0]; +break; +case 29: this.$ = new yy.StringNode($$[$0]); +break; +case 30: this.$ = new yy.IntegerNode($$[$0]); +break; +case 31: this.$ = new yy.BooleanNode($$[$0]); +break; +case 32: this.$ = new yy.DataNode($$[$0]); +break; +case 33: this.$ = new yy.HashNode($$[$0]); +break; +case 34: $$[$0-1].push($$[$0]); this.$ = $$[$0-1]; +break; +case 35: this.$ = [$$[$0]]; +break; +case 36: this.$ = [$$[$0-2], $$[$0]]; +break; +case 37: this.$ = [$$[$0-2], new yy.StringNode($$[$0])]; +break; +case 38: this.$ = [$$[$0-2], new yy.IntegerNode($$[$0])]; +break; +case 39: this.$ = [$$[$0-2], new yy.BooleanNode($$[$0])]; +break; +case 40: this.$ = [$$[$0-2], new yy.DataNode($$[$0])]; +break; +case 41: this.$ = new yy.IdNode($$[$0]); +break; +case 42: $$[$0-2].push($$[$0]); this.$ = $$[$0-2]; +break; +case 43: this.$ = [$$[$0]]; +break; +} +}, +table: [{3:1,4:2,5:[2,4],6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{1:[3]},{5:[1,16]},{5:[2,3],7:17,8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,19],20:[2,3],22:[1,13],23:[1,14],24:[1,15]},{5:[2,5],14:[2,5],15:[2,5],16:[2,5],19:[2,5],20:[2,5],22:[2,5],23:[2,5],24:[2,5]},{4:20,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{4:21,6:3,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,4],22:[1,13],23:[1,14],24:[1,15]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{17:22,21:23,27:[1,24],34:[1,26],36:25},{17:27,21:23,27:[1,24],34:[1,26],36:25},{17:28,21:23,27:[1,24],34:[1,26],36:25},{17:29,21:23,27:[1,24],34:[1,26],36:25},{21:30,34:[1,26],36:25},{1:[2,1]},{6:31,8:4,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],22:[1,13],23:[1,14],24:[1,15]},{5:[2,6],14:[2,6],15:[2,6],16:[2,6],19:[2,6],20:[2,6],22:[2,6],23:[2,6],24:[2,6]},{17:22,18:[1,32],21:23,27:[1,24],34:[1,26],36:25},{10:33,20:[1,34]},{10:35,20:[1,34]},{18:[1,36]},{18:[2,24],21:41,25:37,26:38,27:[1,45],28:39,29:[1,42],30:[1,43],31:[1,44],32:40,33:46,34:[1,47],36:25},{18:[2,25]},{18:[2,41],27:[2,41],29:[2,41],30:[2,41],31:[2,41],34:[2,41],37:[1,48]},{18:[2,43],27:[2,43],29:[2,43],30:[2,43],31:[2,43],34:[2,43],37:[2,43]},{18:[1,49]},{18:[1,50]},{18:[1,51]},{18:[1,52],21:53,34:[1,26],36:25},{5:[2,2],8:18,9:5,11:6,12:7,13:8,14:[1,9],15:[1,10],16:[1,12],19:[1,11],20:[2,2],22:[1,13],23:[1,14],24:[1,15]},{14:[2,20],15:[2,20],16:[2,20],19:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,7],14:[2,7],15:[2,7],16:[2,7],19:[2,7],20:[2,7],22:[2,7],23:[2,7],24:[2,7]},{21:54,34:[1,26],36:25},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{18:[2,22],21:41,26:55,27:[1,45],28:56,29:[1,42],30:[1,43],31:[1,44],32:40,33:46,34:[1,47],36:25},{18:[2,23]},{18:[2,27],27:[2,27],29:[2,27],30:[2,27],31:[2,27],34:[2,27]},{18:[2,33],33:57,34:[1,58]},{18:[2,28],27:[2,28],29:[2,28],30:[2,28],31:[2,28],34:[2,28]},{18:[2,29],27:[2,29],29:[2,29],30:[2,29],31:[2,29],34:[2,29]},{18:[2,30],27:[2,30],29:[2,30],30:[2,30],31:[2,30],34:[2,30]},{18:[2,31],27:[2,31],29:[2,31],30:[2,31],31:[2,31],34:[2,31]},{18:[2,32],27:[2,32],29:[2,32],30:[2,32],31:[2,32],34:[2,32]},{18:[2,35],34:[2,35]},{18:[2,43],27:[2,43],29:[2,43],30:[2,43],31:[2,43],34:[2,43],35:[1,59],37:[2,43]},{34:[1,60]},{14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,16],14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,17],14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]},{18:[1,61]},{18:[1,62]},{18:[2,21]},{18:[2,26],27:[2,26],29:[2,26],30:[2,26],31:[2,26],34:[2,26]},{18:[2,34],34:[2,34]},{35:[1,59]},{21:63,27:[1,67],29:[1,64],30:[1,65],31:[1,66],34:[1,26],36:25},{18:[2,42],27:[2,42],29:[2,42],30:[2,42],31:[2,42],34:[2,42],37:[2,42]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]},{18:[2,36],34:[2,36]},{18:[2,37],34:[2,37]},{18:[2,38],34:[2,38]},{18:[2,39],34:[2,39]},{18:[2,40],34:[2,40]}], +defaultActions: {16:[2,1],24:[2,25],38:[2,23],55:[2,21]}, +parseError: function parseError(str, hash) { + throw new Error(str); +}, +parse: function parse(input) { + var self = this, stack = [0], vstack = [null], lstack = [], table = this.table, yytext = "", yylineno = 0, yyleng = 0, recovering = 0, TERROR = 2, EOF = 1; + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + this.yy.parser = this; + if (typeof this.lexer.yylloc == "undefined") + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + var ranges = this.lexer.options && this.lexer.options.ranges; + if (typeof this.yy.parseError === "function") + this.parseError = this.yy.parseError; + function popStack(n) { + stack.length = stack.length - 2 * n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + function lex() { + var token; + token = self.lexer.lex() || 1; + if (typeof token !== "number") { + token = self.symbols_[token] || token; + } + return token; + } + var symbol, preErrorSymbol, state, action, a, r, yyval = {}, p, len, newState, expected; + while (true) { + state = stack[stack.length - 1]; + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol === null || typeof symbol == "undefined") { + symbol = lex(); + } + action = table[state] && table[state][symbol]; + } + if (typeof action === "undefined" || !action.length || !action[0]) { + var errStr = ""; + if (!recovering) { + expected = []; + for (p in table[state]) + if (this.terminals_[p] && p > 2) { + expected.push("'" + this.terminals_[p] + "'"); + } + if (this.lexer.showPosition) { + errStr = "Parse error on line " + (yylineno + 1) + ":\n" + this.lexer.showPosition() + "\nExpecting " + expected.join(", ") + ", got '" + (this.terminals_[symbol] || symbol) + "'"; + } else { + errStr = "Parse error on line " + (yylineno + 1) + ": Unexpected " + (symbol == 1?"end of input":"'" + (this.terminals_[symbol] || symbol) + "'"); + } + this.parseError(errStr, {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + } + if (action[0] instanceof Array && action.length > 1) { + throw new Error("Parse Error: multiple actions possible at state: " + state + ", token: " + symbol); + } + switch (action[0]) { + case 1: + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); + symbol = null; + if (!preErrorSymbol) { + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + case 2: + len = this.productions_[action[1]][1]; + yyval.$ = vstack[vstack.length - len]; + yyval._$ = {first_line: lstack[lstack.length - (len || 1)].first_line, last_line: lstack[lstack.length - 1].last_line, first_column: lstack[lstack.length - (len || 1)].first_column, last_column: lstack[lstack.length - 1].last_column}; + if (ranges) { + yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]]; + } + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + if (typeof r !== "undefined") { + return r; + } + if (len) { + stack = stack.slice(0, -1 * len * 2); + vstack = vstack.slice(0, -1 * len); + lstack = lstack.slice(0, -1 * len); + } + stack.push(this.productions_[action[1]][0]); + vstack.push(yyval.$); + lstack.push(yyval._$); + newState = table[stack[stack.length - 2]][stack[stack.length - 1]]; + stack.push(newState); + break; + case 3: + return true; + } + } + return true; +} +}; +/* Jison generated lexer */ +var lexer = (function(){ +var lexer = ({EOF:1, +parseError:function parseError(str, hash) { + if (this.yy.parser) { + this.yy.parser.parseError(str, hash); + } else { + throw new Error(str); + } + }, +setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + if (this.options.ranges) this.yylloc.range = [0,0]; + this.offset = 0; + return this; + }, +input:function () { + var ch = this._input[0]; + this.yytext += ch; + this.yyleng++; + this.offset++; + this.match += ch; + this.matched += ch; + var lines = ch.match(/(?:\r\n?|\n).*/g); + if (lines) { + this.yylineno++; + this.yylloc.last_line++; + } else { + this.yylloc.last_column++; + } + if (this.options.ranges) this.yylloc.range[1]++; + + this._input = this._input.slice(1); + return ch; + }, +unput:function (ch) { + var len = ch.length; + var lines = ch.split(/(?:\r\n?|\n)/g); + + this._input = ch + this._input; + this.yytext = this.yytext.substr(0, this.yytext.length-len-1); + //this.yyleng -= len; + this.offset -= len; + var oldLines = this.match.split(/(?:\r\n?|\n)/g); + this.match = this.match.substr(0, this.match.length-1); + this.matched = this.matched.substr(0, this.matched.length-1); + + if (lines.length-1) this.yylineno -= lines.length-1; + var r = this.yylloc.range; + + this.yylloc = {first_line: this.yylloc.first_line, + last_line: this.yylineno+1, + first_column: this.yylloc.first_column, + last_column: lines ? + (lines.length === oldLines.length ? this.yylloc.first_column : 0) + oldLines[oldLines.length - lines.length].length - lines[0].length: + this.yylloc.first_column - len + }; + + if (this.options.ranges) { + this.yylloc.range = [r[0], r[0] + this.yyleng - len]; + } + return this; + }, +more:function () { + this._more = true; + return this; + }, +less:function (n) { + this.unput(this.match.slice(n)); + }, +pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, +upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, +showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, +next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + tempMatch, + index, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + tempMatch = this._input.match(this.rules[rules[i]]); + if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { + match = tempMatch; + index = i; + if (!this.options.flex) break; + } + } + if (match) { + lines = match[0].match(/(?:\r\n?|\n).*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length : this.yylloc.last_column + match[0].length}; + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + if (this.options.ranges) { + this.yylloc.range = [this.offset, this.offset += this.yyleng]; + } + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); + if (this.done && this._input) this.done = false; + if (token) return token; + else return; + } + if (this._input === "") { + return this.EOF; + } else { + return this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, +lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, +begin:function begin(condition) { + this.conditionStack.push(condition); + }, +popState:function popState() { + return this.conditionStack.pop(); + }, +_currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, +topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, +pushState:function begin(condition) { + this.begin(condition); + }}); +lexer.options = {}; +lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + +var YYSTATE=YY_START +switch($avoiding_name_collisions) { +case 0: + if(yy_.yytext.slice(-1) !== "\\") this.begin("mu"); + if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1), this.begin("emu"); + if(yy_.yytext) return 14; + +break; +case 1: return 14; +break; +case 2: + if(yy_.yytext.slice(-1) !== "\\") this.popState(); + if(yy_.yytext.slice(-1) === "\\") yy_.yytext = yy_.yytext.substr(0,yy_.yyleng-1); + return 14; + +break; +case 3: return 24; +break; +case 4: return 16; +break; +case 5: return 20; +break; +case 6: return 19; +break; +case 7: return 19; +break; +case 8: return 23; +break; +case 9: return 23; +break; +case 10: yy_.yytext = yy_.yytext.substr(3,yy_.yyleng-5); this.popState(); return 15; +break; +case 11: return 22; +break; +case 12: return 35; +break; +case 13: return 34; +break; +case 14: return 34; +break; +case 15: return 37; +break; +case 16: /*ignore whitespace*/ +break; +case 17: this.popState(); return 18; +break; +case 18: this.popState(); return 18; +break; +case 19: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 29; +break; +case 20: yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"'); return 29; +break; +case 21: yy_.yytext = yy_.yytext.substr(1); return 27; +break; +case 22: return 31; +break; +case 23: return 31; +break; +case 24: return 30; +break; +case 25: return 34; +break; +case 26: yy_.yytext = yy_.yytext.substr(1, yy_.yyleng-2); return 34; +break; +case 27: return 'INVALID'; +break; +case 28: return 5; +break; +} +}; +lexer.rules = [/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:\{\{>)/,/^(?:\{\{#)/,/^(?:\{\{\/)/,/^(?:\{\{\^)/,/^(?:\{\{\s*else\b)/,/^(?:\{\{\{)/,/^(?:\{\{&)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{)/,/^(?:=)/,/^(?:\.(?=[} ]))/,/^(?:\.\.)/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}\}\})/,/^(?:\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@[a-zA-Z]+)/,/^(?:true(?=[}\s]))/,/^(?:false(?=[}\s]))/,/^(?:[0-9]+(?=[}\s]))/,/^(?:[a-zA-Z0-9_$-]+(?=[=}\s\/.]))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:$)/]; +lexer.conditions = {"mu":{"rules":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"INITIAL":{"rules":[0,1,28],"inclusive":true}}; +return lexer;})() +parser.lexer = lexer; +function Parser () { this.yy = {}; }Parser.prototype = parser;parser.Parser = Parser; +return new Parser; +})(); +if (typeof require !== 'undefined' && typeof exports !== 'undefined') { +exports.parser = handlebars; +exports.Parser = handlebars.Parser; +exports.parse = function () { return handlebars.parse.apply(handlebars, arguments); } +exports.main = function commonjsMain(args) { + if (!args[1]) + throw new Error('Usage: '+args[0]+' FILE'); + var source, cwd; + if (typeof process !== 'undefined') { + source = require('fs').readFileSync(require('path').resolve(args[1]), "utf8"); + } else { + source = require("file").path(require("file").cwd()).join(args[1]).read({charset: "utf-8"}); + } + return exports.parser.parse(source); +} +if (typeof module !== 'undefined' && require.main === module) { + exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args); +} +}; +; +// lib/handlebars/compiler/base.js +Handlebars.Parser = handlebars; + +Handlebars.parse = function(string) { + Handlebars.Parser.yy = Handlebars.AST; + return Handlebars.Parser.parse(string); +}; + +Handlebars.print = function(ast) { + return new Handlebars.PrintVisitor().accept(ast); +}; + +Handlebars.logger = { + DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3, + + // override in the host environment + log: function(level, str) {} +}; + +Handlebars.log = function(level, str) { Handlebars.logger.log(level, str); }; +; +// lib/handlebars/compiler/ast.js +(function() { + + Handlebars.AST = {}; + + Handlebars.AST.ProgramNode = function(statements, inverse) { + this.type = "program"; + this.statements = statements; + if(inverse) { this.inverse = new Handlebars.AST.ProgramNode(inverse); } + }; + + Handlebars.AST.MustacheNode = function(rawParams, hash, unescaped) { + this.type = "mustache"; + this.escaped = !unescaped; + this.hash = hash; + + var id = this.id = rawParams[0]; + var params = this.params = rawParams.slice(1); + + // a mustache is an eligible helper if: + // * its id is simple (a single part, not `this` or `..`) + var eligibleHelper = this.eligibleHelper = id.isSimple; + + // a mustache is definitely a helper if: + // * it is an eligible helper, and + // * it has at least one parameter or hash segment + this.isHelper = eligibleHelper && (params.length || hash); + + // if a mustache is an eligible helper but not a definite + // helper, it is ambiguous, and will be resolved in a later + // pass or at runtime. + }; + + Handlebars.AST.PartialNode = function(id, context) { + this.type = "partial"; + + // TODO: disallow complex IDs + + this.id = id; + this.context = context; + }; + + var verifyMatch = function(open, close) { + if(open.original !== close.original) { + throw new Handlebars.Exception(open.original + " doesn't match " + close.original); + } + }; + + Handlebars.AST.BlockNode = function(mustache, program, inverse, close) { + verifyMatch(mustache.id, close); + this.type = "block"; + this.mustache = mustache; + this.program = program; + this.inverse = inverse; + + if (this.inverse && !this.program) { + this.isInverse = true; + } + }; + + Handlebars.AST.ContentNode = function(string) { + this.type = "content"; + this.string = string; + }; + + Handlebars.AST.HashNode = function(pairs) { + this.type = "hash"; + this.pairs = pairs; + }; + + Handlebars.AST.IdNode = function(parts) { + this.type = "ID"; + this.original = parts.join("."); + + var dig = [], depth = 0; + + for(var i=0,l=parts.length; i<l; i++) { + var part = parts[i]; + + if(part === "..") { depth++; } + else if(part === "." || part === "this") { this.isScoped = true; } + else { dig.push(part); } + } + + this.parts = dig; + this.string = dig.join('.'); + this.depth = depth; + + // an ID is simple if it only has one part, and that part is not + // `..` or `this`. + this.isSimple = parts.length === 1 && !this.isScoped && depth === 0; + }; + + Handlebars.AST.DataNode = function(id) { + this.type = "DATA"; + this.id = id; + }; + + Handlebars.AST.StringNode = function(string) { + this.type = "STRING"; + this.string = string; + }; + + Handlebars.AST.IntegerNode = function(integer) { + this.type = "INTEGER"; + this.integer = integer; + }; + + Handlebars.AST.BooleanNode = function(bool) { + this.type = "BOOLEAN"; + this.bool = bool; + }; + + Handlebars.AST.CommentNode = function(comment) { + this.type = "comment"; + this.comment = comment; + }; + +})();; +// lib/handlebars/utils.js +Handlebars.Exception = function(message) { + var tmp = Error.prototype.constructor.apply(this, arguments); + + for (var p in tmp) { + if (tmp.hasOwnProperty(p)) { this[p] = tmp[p]; } + } + + this.message = tmp.message; +}; +Handlebars.Exception.prototype = new Error(); + +// Build out our basic SafeString type +Handlebars.SafeString = function(string) { + this.string = string; +}; +Handlebars.SafeString.prototype.toString = function() { + return this.string.toString(); +}; + +(function() { + var escape = { + "&": "&amp;", + "<": "&lt;", + ">": "&gt;", + '"': "&quot;", + "'": "&#x27;", + "`": "&#x60;" + }; + + var badChars = /[&<>"'`]/g; + var possible = /[&<>"'`]/; + + var escapeChar = function(chr) { + return escape[chr] || "&amp;"; + }; + + Handlebars.Utils = { + escapeExpression: function(string) { + // don't escape SafeStrings, since they're already safe + if (string instanceof Handlebars.SafeString) { + return string.toString(); + } else if (string == null || string === false) { + return ""; + } + + if(!possible.test(string)) { return string; } + return string.replace(badChars, escapeChar); + }, + + isEmpty: function(value) { + if (typeof value === "undefined") { + return true; + } else if (value === null) { + return true; + } else if (value === false) { + return true; + } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) { + return true; + } else { + return false; + } + } + }; +})();; +// lib/handlebars/compiler/compiler.js + +/*jshint eqnull:true*/ +Handlebars.Compiler = function() {}; +Handlebars.JavaScriptCompiler = function() {}; + +(function(Compiler, JavaScriptCompiler) { + // the foundHelper register will disambiguate helper lookup from finding a + // function in a context. This is necessary for mustache compatibility, which + // requires that context functions in blocks are evaluated by blockHelperMissing, + // and then proceed as if the resulting value was provided to blockHelperMissing. + + Compiler.prototype = { + compiler: Compiler, + + disassemble: function() { + var opcodes = this.opcodes, opcode, out = [], params, param; + + for (var i=0, l=opcodes.length; i<l; i++) { + opcode = opcodes[i]; + + if (opcode.opcode === 'DECLARE') { + out.push("DECLARE " + opcode.name + "=" + opcode.value); + } else { + params = []; + for (var j=0; j<opcode.args.length; j++) { + param = opcode.args[j]; + if (typeof param === "string") { + param = "\"" + param.replace("\n", "\\n") + "\""; + } + params.push(param); + } + out.push(opcode.opcode + " " + params.join(" ")); + } + } + + return out.join("\n"); + }, + + guid: 0, + + compile: function(program, options) { + this.children = []; + this.depths = {list: []}; + this.options = options; + + // These changes will propagate to the other compiler components + var knownHelpers = this.options.knownHelpers; + this.options.knownHelpers = { + 'helperMissing': true, + 'blockHelperMissing': true, + 'each': true, + 'if': true, + 'unless': true, + 'with': true, + 'log': true + }; + if (knownHelpers) { + for (var name in knownHelpers) { + this.options.knownHelpers[name] = knownHelpers[name]; + } + } + + return this.program(program); + }, + + accept: function(node) { + return this[node.type](node); + }, + + program: function(program) { + var statements = program.statements, statement; + this.opcodes = []; + + for(var i=0, l=statements.length; i<l; i++) { + statement = statements[i]; + this[statement.type](statement); + } + this.isSimple = l === 1; + + this.depths.list = this.depths.list.sort(function(a, b) { + return a - b; + }); + + return this; + }, + + compileProgram: function(program) { + var result = new this.compiler().compile(program, this.options); + var guid = this.guid++, depth; + + this.usePartial = this.usePartial || result.usePartial; + + this.children[guid] = result; + + for(var i=0, l=result.depths.list.length; i<l; i++) { + depth = result.depths.list[i]; + + if(depth < 2) { continue; } + else { this.addDepth(depth - 1); } + } + + return guid; + }, + + block: function(block) { + var mustache = block.mustache, + program = block.program, + inverse = block.inverse; + + if (program) { + program = this.compileProgram(program); + } + + if (inverse) { + inverse = this.compileProgram(inverse); + } + + var type = this.classifyMustache(mustache); + + if (type === "helper") { + this.helperMustache(mustache, program, inverse); + } else if (type === "simple") { + this.simpleMustache(mustache); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('pushLiteral', '{}'); + this.opcode('blockValue'); + } else { + this.ambiguousMustache(mustache, program, inverse); + + // now that the simple mustache is resolved, we need to + // evaluate it by executing `blockHelperMissing` + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + this.opcode('pushLiteral', '{}'); + this.opcode('ambiguousBlockValue'); + } + + this.opcode('append'); + }, + + hash: function(hash) { + var pairs = hash.pairs, pair, val; + + this.opcode('push', '{}'); + + for(var i=0, l=pairs.length; i<l; i++) { + pair = pairs[i]; + val = pair[1]; + + this.accept(val); + this.opcode('assignToHash', pair[0]); + } + }, + + partial: function(partial) { + var id = partial.id; + this.usePartial = true; + + if(partial.context) { + this.ID(partial.context); + } else { + this.opcode('push', 'depth0'); + } + + this.opcode('invokePartial', id.original); + this.opcode('append'); + }, + + content: function(content) { + this.opcode('appendContent', content.string); + }, + + mustache: function(mustache) { + var options = this.options; + var type = this.classifyMustache(mustache); + + if (type === "simple") { + this.simpleMustache(mustache); + } else if (type === "helper") { + this.helperMustache(mustache); + } else { + this.ambiguousMustache(mustache); + } + + if(mustache.escaped && !options.noEscape) { + this.opcode('appendEscaped'); + } else { + this.opcode('append'); + } + }, + + ambiguousMustache: function(mustache, program, inverse) { + var id = mustache.id, name = id.parts[0]; + + this.opcode('getContext', id.depth); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + this.opcode('invokeAmbiguous', name); + }, + + simpleMustache: function(mustache, program, inverse) { + var id = mustache.id; + + if (id.type === 'DATA') { + this.DATA(id); + } else if (id.parts.length) { + this.ID(id); + } else { + // Simplified ID for `this` + this.addDepth(id.depth); + this.opcode('getContext', id.depth); + this.opcode('pushContext'); + } + + this.opcode('resolvePossibleLambda'); + }, + + helperMustache: function(mustache, program, inverse) { + var params = this.setupFullMustacheParams(mustache, program, inverse), + name = mustache.id.parts[0]; + + if (this.options.knownHelpers[name]) { + this.opcode('invokeKnownHelper', params.length, name); + } else if (this.knownHelpersOnly) { + throw new Error("You specified knownHelpersOnly, but used the unknown helper " + name); + } else { + this.opcode('invokeHelper', params.length, name); + } + }, + + ID: function(id) { + this.addDepth(id.depth); + this.opcode('getContext', id.depth); + + var name = id.parts[0]; + if (!name) { + this.opcode('pushContext'); + } else { + this.opcode('lookupOnContext', id.parts[0]); + } + + for(var i=1, l=id.parts.length; i<l; i++) { + this.opcode('lookup', id.parts[i]); + } + }, + + DATA: function(data) { + this.options.data = true; + this.opcode('lookupData', data.id); + }, + + STRING: function(string) { + this.opcode('pushString', string.string); + }, + + INTEGER: function(integer) { + this.opcode('pushLiteral', integer.integer); + }, + + BOOLEAN: function(bool) { + this.opcode('pushLiteral', bool.bool); + }, + + comment: function() {}, + + // HELPERS + opcode: function(name) { + this.opcodes.push({ opcode: name, args: [].slice.call(arguments, 1) }); + }, + + declare: function(name, value) { + this.opcodes.push({ opcode: 'DECLARE', name: name, value: value }); + }, + + addDepth: function(depth) { + if(isNaN(depth)) { throw new Error("EWOT"); } + if(depth === 0) { return; } + + if(!this.depths[depth]) { + this.depths[depth] = true; + this.depths.list.push(depth); + } + }, + + classifyMustache: function(mustache) { + var isHelper = mustache.isHelper; + var isEligible = mustache.eligibleHelper; + var options = this.options; + + // if ambiguous, we can possibly resolve the ambiguity now + if (isEligible && !isHelper) { + var name = mustache.id.parts[0]; + + if (options.knownHelpers[name]) { + isHelper = true; + } else if (options.knownHelpersOnly) { + isEligible = false; + } + } + + if (isHelper) { return "helper"; } + else if (isEligible) { return "ambiguous"; } + else { return "simple"; } + }, + + pushParams: function(params) { + var i = params.length, param; + + while(i--) { + param = params[i]; + + if(this.options.stringParams) { + if(param.depth) { + this.addDepth(param.depth); + } + + this.opcode('getContext', param.depth || 0); + this.opcode('pushStringParam', param.string); + } else { + this[param.type](param); + } + } + }, + + setupMustacheParams: function(mustache) { + var params = mustache.params; + this.pushParams(params); + + if(mustache.hash) { + this.hash(mustache.hash); + } else { + this.opcode('pushLiteral', '{}'); + } + + return params; + }, + + // this will replace setupMustacheParams when we're done + setupFullMustacheParams: function(mustache, program, inverse) { + var params = mustache.params; + this.pushParams(params); + + this.opcode('pushProgram', program); + this.opcode('pushProgram', inverse); + + if(mustache.hash) { + this.hash(mustache.hash); + } else { + this.opcode('pushLiteral', '{}'); + } + + return params; + } + }; + + var Literal = function(value) { + this.value = value; + }; + + JavaScriptCompiler.prototype = { + // PUBLIC API: You can override these methods in a subclass to provide + // alternative compiled forms for name lookup and buffering semantics + nameLookup: function(parent, name, type) { + if (/^[0-9]+$/.test(name)) { + return parent + "[" + name + "]"; + } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) { + return parent + "." + name; + } + else { + return parent + "['" + name + "']"; + } + }, + + appendToBuffer: function(string) { + if (this.environment.isSimple) { + return "return " + string + ";"; + } else { + return "buffer += " + string + ";"; + } + }, + + initializeBuffer: function() { + return this.quotedString(""); + }, + + namespace: "Handlebars", + // END PUBLIC API + + compile: function(environment, options, context, asObject) { + this.environment = environment; + this.options = options || {}; + + Handlebars.log(Handlebars.logger.DEBUG, this.environment.disassemble() + "\n\n"); + + this.name = this.environment.name; + this.isChild = !!context; + this.context = context || { + programs: [], + aliases: { } + }; + + this.preamble(); + + this.stackSlot = 0; + this.stackVars = []; + this.registers = { list: [] }; + this.compileStack = []; + + this.compileChildren(environment, options); + + var opcodes = environment.opcodes, opcode; + + this.i = 0; + + for(l=opcodes.length; this.i<l; this.i++) { + opcode = opcodes[this.i]; + + if(opcode.opcode === 'DECLARE') { + this[opcode.name] = opcode.value; + } else { + this[opcode.opcode].apply(this, opcode.args); + } + } + + return this.createFunctionContext(asObject); + }, + + nextOpcode: function() { + var opcodes = this.environment.opcodes, opcode = opcodes[this.i + 1]; + return opcodes[this.i + 1]; + }, + + eat: function(opcode) { + this.i = this.i + 1; + }, + + preamble: function() { + var out = []; + + if (!this.isChild) { + var namespace = this.namespace; + var copies = "helpers = helpers || " + namespace + ".helpers;"; + if (this.environment.usePartial) { copies = copies + " partials = partials || " + namespace + ".partials;"; } + if (this.options.data) { copies = copies + " data = data || {};"; } + out.push(copies); + } else { + out.push(''); + } + + if (!this.environment.isSimple) { + out.push(", buffer = " + this.initializeBuffer()); + } else { + out.push(""); + } + + // track the last context pushed into place to allow skipping the + // getContext opcode when it would be a noop + this.lastContext = 0; + this.source = out; + }, + + createFunctionContext: function(asObject) { + var locals = this.stackVars.concat(this.registers.list); + + if(locals.length > 0) { + this.source[1] = this.source[1] + ", " + locals.join(", "); + } + + // Generate minimizer alias mappings + if (!this.isChild) { + var aliases = []; + for (var alias in this.context.aliases) { + this.source[1] = this.source[1] + ', ' + alias + '=' + this.context.aliases[alias]; + } + } + + if (this.source[1]) { + this.source[1] = "var " + this.source[1].substring(2) + ";"; + } + + // Merge children + if (!this.isChild) { + this.source[1] += '\n' + this.context.programs.join('\n') + '\n'; + } + + if (!this.environment.isSimple) { + this.source.push("return buffer;"); + } + + var params = this.isChild ? ["depth0", "data"] : ["Handlebars", "depth0", "helpers", "partials", "data"]; + + for(var i=0, l=this.environment.depths.list.length; i<l; i++) { + params.push("depth" + this.environment.depths.list[i]); + } + + if (asObject) { + params.push(this.source.join("\n ")); + + return Function.apply(this, params); + } else { + var functionSource = 'function ' + (this.name || '') + '(' + params.join(',') + ') {\n ' + this.source.join("\n ") + '}'; + Handlebars.log(Handlebars.logger.DEBUG, functionSource + "\n\n"); + return functionSource; + } + }, + + // [blockValue] + // + // On stack, before: hash, inverse, program, value + // On stack, after: return value of blockHelperMissing + // + // The purpose of this opcode is to take a block of the form + // `{{#foo}}...{{/foo}}`, resolve the value of `foo`, and + // replace it on the stack with the result of properly + // invoking blockHelperMissing. + blockValue: function() { + this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; + + var params = ["depth0"]; + this.setupParams(0, params); + + this.replaceStack(function(current) { + params.splice(1, 0, current); + return current + " = blockHelperMissing.call(" + params.join(", ") + ")"; + }); + }, + + // [ambiguousBlockValue] + // + // On stack, before: hash, inverse, program, value + // Compiler value, before: lastHelper=value of last found helper, if any + // On stack, after, if no lastHelper: same as [blockValue] + // On stack, after, if lastHelper: value + ambiguousBlockValue: function() { + this.context.aliases.blockHelperMissing = 'helpers.blockHelperMissing'; + + var params = ["depth0"]; + this.setupParams(0, params); + + var current = this.topStack(); + params.splice(1, 0, current); + + this.source.push("if (!" + this.lastHelper + ") { " + current + " = blockHelperMissing.call(" + params.join(", ") + "); }"); + }, + + // [appendContent] + // + // On stack, before: ... + // On stack, after: ... + // + // Appends the string value of `content` to the current buffer + appendContent: function(content) { + this.source.push(this.appendToBuffer(this.quotedString(content))); + }, + + // [append] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Coerces `value` to a String and appends it to the current buffer. + // + // If `value` is truthy, or 0, it is coerced into a string and appended + // Otherwise, the empty string is appended + append: function() { + var local = this.popStack(); + this.source.push("if(" + local + " || " + local + " === 0) { " + this.appendToBuffer(local) + " }"); + if (this.environment.isSimple) { + this.source.push("else { " + this.appendToBuffer("''") + " }"); + } + }, + + // [appendEscaped] + // + // On stack, before: value, ... + // On stack, after: ... + // + // Escape `value` and append it to the buffer + appendEscaped: function() { + var opcode = this.nextOpcode(), extra = ""; + this.context.aliases.escapeExpression = 'this.escapeExpression'; + + if(opcode && opcode.opcode === 'appendContent') { + extra = " + " + this.quotedString(opcode.args[0]); + this.eat(opcode); + } + + this.source.push(this.appendToBuffer("escapeExpression(" + this.popStack() + ")" + extra)); + }, + + // [getContext] + // + // On stack, before: ... + // On stack, after: ... + // Compiler value, after: lastContext=depth + // + // Set the value of the `lastContext` compiler value to the depth + getContext: function(depth) { + if(this.lastContext !== depth) { + this.lastContext = depth; + } + }, + + // [lookupOnContext] + // + // On stack, before: ... + // On stack, after: currentContext[name], ... + // + // Looks up the value of `name` on the current context and pushes + // it onto the stack. + lookupOnContext: function(name) { + this.pushStack(this.nameLookup('depth' + this.lastContext, name, 'context')); + }, + + // [pushContext] + // + // On stack, before: ... + // On stack, after: currentContext, ... + // + // Pushes the value of the current context onto the stack. + pushContext: function() { + this.pushStackLiteral('depth' + this.lastContext); + }, + + // [resolvePossibleLambda] + // + // On stack, before: value, ... + // On stack, after: resolved value, ... + // + // If the `value` is a lambda, replace it on the stack by + // the return value of the lambda + resolvePossibleLambda: function() { + this.context.aliases.functionType = '"function"'; + + this.replaceStack(function(current) { + return "typeof " + current + " === functionType ? " + current + "() : " + current; + }); + }, + + // [lookup] + // + // On stack, before: value, ... + // On stack, after: value[name], ... + // + // Replace the value on the stack with the result of looking + // up `name` on `value` + lookup: function(name) { + this.replaceStack(function(current) { + return current + " == null || " + current + " === false ? " + current + " : " + this.nameLookup(current, name, 'context'); + }); + }, + + // [lookupData] + // + // On stack, before: ... + // On stack, after: data[id], ... + // + // Push the result of looking up `id` on the current data + lookupData: function(id) { + this.pushStack(this.nameLookup('data', id, 'data')); + }, + + // [pushStringParam] + // + // On stack, before: ... + // On stack, after: string, currentContext, ... + // + // This opcode is designed for use in string mode, which + // provides the string value of a parameter along with its + // depth rather than resolving it immediately. + pushStringParam: function(string) { + this.pushStackLiteral('depth' + this.lastContext); + this.pushString(string); + }, + + // [pushString] + // + // On stack, before: ... + // On stack, after: quotedString(string), ... + // + // Push a quoted version of `string` onto the stack + pushString: function(string) { + this.pushStackLiteral(this.quotedString(string)); + }, + + // [push] + // + // On stack, before: ... + // On stack, after: expr, ... + // + // Push an expression onto the stack + push: function(expr) { + this.pushStack(expr); + }, + + // [pushLiteral] + // + // On stack, before: ... + // On stack, after: value, ... + // + // Pushes a value onto the stack. This operation prevents + // the compiler from creating a temporary variable to hold + // it. + pushLiteral: function(value) { + this.pushStackLiteral(value); + }, + + // [pushProgram] + // + // On stack, before: ... + // On stack, after: program(guid), ... + // + // Push a program expression onto the stack. This takes + // a compile-time guid and converts it into a runtime-accessible + // expression. + pushProgram: function(guid) { + if (guid != null) { + this.pushStackLiteral(this.programExpression(guid)); + } else { + this.pushStackLiteral(null); + } + }, + + // [invokeHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // Pops off the helper's parameters, invokes the helper, + // and pushes the helper's return value onto the stack. + // + // If the helper is not found, `helperMissing` is called. + invokeHelper: function(paramSize, name) { + this.context.aliases.helperMissing = 'helpers.helperMissing'; + + var helper = this.lastHelper = this.setupHelper(paramSize, name); + this.register('foundHelper', helper.name); + + this.pushStack("foundHelper ? foundHelper.call(" + + helper.callParams + ") " + ": helperMissing.call(" + + helper.helperMissingParams + ")"); + }, + + // [invokeKnownHelper] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of helper invocation + // + // This operation is used when the helper is known to exist, + // so a `helperMissing` fallback is not required. + invokeKnownHelper: function(paramSize, name) { + var helper = this.setupHelper(paramSize, name); + this.pushStack(helper.name + ".call(" + helper.callParams + ")"); + }, + + // [invokeAmbiguous] + // + // On stack, before: hash, inverse, program, params..., ... + // On stack, after: result of disambiguation + // + // This operation is used when an expression like `{{foo}}` + // is provided, but we don't know at compile-time whether it + // is a helper or a path. + // + // This operation emits more code than the other options, + // and can be avoided by passing the `knownHelpers` and + // `knownHelpersOnly` flags at compile-time. + invokeAmbiguous: function(name) { + this.context.aliases.functionType = '"function"'; + + this.pushStackLiteral('{}'); + var helper = this.setupHelper(0, name); + + var helperName = this.lastHelper = this.nameLookup('helpers', name, 'helper'); + this.register('foundHelper', helperName); + + var nonHelper = this.nameLookup('depth' + this.lastContext, name, 'context'); + var nextStack = this.nextStack(); + + this.source.push('if (foundHelper) { ' + nextStack + ' = foundHelper.call(' + helper.callParams + '); }'); + this.source.push('else { ' + nextStack + ' = ' + nonHelper + '; ' + nextStack + ' = typeof ' + nextStack + ' === functionType ? ' + nextStack + '() : ' + nextStack + '; }'); + }, + + // [invokePartial] + // + // On stack, before: context, ... + // On stack after: result of partial invocation + // + // This operation pops off a context, invokes a partial with that context, + // and pushes the result of the invocation back. + invokePartial: function(name) { + var params = [this.nameLookup('partials', name, 'partial'), "'" + name + "'", this.popStack(), "helpers", "partials"]; + + if (this.options.data) { + params.push("data"); + } + + this.context.aliases.self = "this"; + this.pushStack("self.invokePartial(" + params.join(", ") + ");"); + }, + + // [assignToHash] + // + // On stack, before: value, hash, ... + // On stack, after: hash, ... + // + // Pops a value and hash off the stack, assigns `hash[key] = value` + // and pushes the hash back onto the stack. + assignToHash: function(key) { + var value = this.popStack(); + var hash = this.topStack(); + + this.source.push(hash + "['" + key + "'] = " + value + ";"); + }, + + // HELPERS + + compiler: JavaScriptCompiler, + + compileChildren: function(environment, options) { + var children = environment.children, child, compiler; + + for(var i=0, l=children.length; i<l; i++) { + child = children[i]; + compiler = new this.compiler(); + + this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children + var index = this.context.programs.length; + child.index = index; + child.name = 'program' + index; + this.context.programs[index] = compiler.compile(child, options, this.context); + } + }, + + programExpression: function(guid) { + this.context.aliases.self = "this"; + + if(guid == null) { + return "self.noop"; + } + + var child = this.environment.children[guid], + depths = child.depths.list, depth; + + var programParams = [child.index, child.name, "data"]; + + for(var i=0, l = depths.length; i<l; i++) { + depth = depths[i]; + + if(depth === 1) { programParams.push("depth0"); } + else { programParams.push("depth" + (depth - 1)); } + } + + if(depths.length === 0) { + return "self.program(" + programParams.join(", ") + ")"; + } else { + programParams.shift(); + return "self.programWithDepth(" + programParams.join(", ") + ")"; + } + }, + + register: function(name, val) { + this.useRegister(name); + this.source.push(name + " = " + val + ";"); + }, + + useRegister: function(name) { + if(!this.registers[name]) { + this.registers[name] = true; + this.registers.list.push(name); + } + }, + + pushStackLiteral: function(item) { + this.compileStack.push(new Literal(item)); + return item; + }, + + pushStack: function(item) { + this.source.push(this.incrStack() + " = " + item + ";"); + this.compileStack.push("stack" + this.stackSlot); + return "stack" + this.stackSlot; + }, + + replaceStack: function(callback) { + var item = callback.call(this, this.topStack()); + + this.source.push(this.topStack() + " = " + item + ";"); + return "stack" + this.stackSlot; + }, + + nextStack: function(skipCompileStack) { + var name = this.incrStack(); + this.compileStack.push("stack" + this.stackSlot); + return name; + }, + + incrStack: function() { + this.stackSlot++; + if(this.stackSlot > this.stackVars.length) { this.stackVars.push("stack" + this.stackSlot); } + return "stack" + this.stackSlot; + }, + + popStack: function() { + var item = this.compileStack.pop(); + + if (item instanceof Literal) { + return item.value; + } else { + this.stackSlot--; + return item; + } + }, + + topStack: function() { + var item = this.compileStack[this.compileStack.length - 1]; + + if (item instanceof Literal) { + return item.value; + } else { + return item; + } + }, + + quotedString: function(str) { + return '"' + str + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + '"'; + }, + + setupHelper: function(paramSize, name) { + var params = []; + this.setupParams(paramSize, params); + var foundHelper = this.nameLookup('helpers', name, 'helper'); + + return { + params: params, + name: foundHelper, + callParams: ["depth0"].concat(params).join(", "), + helperMissingParams: ["depth0", this.quotedString(name)].concat(params).join(", ") + }; + }, + + // the params and contexts arguments are passed in arrays + // to fill in + setupParams: function(paramSize, params) { + var options = [], contexts = [], param, inverse, program; + + options.push("hash:" + this.popStack()); + + inverse = this.popStack(); + program = this.popStack(); + + // Avoid setting fn and inverse if neither are set. This allows + // helpers to do a check for `if (options.fn)` + if (program || inverse) { + if (!program) { + this.context.aliases.self = "this"; + program = "self.noop"; + } + + if (!inverse) { + this.context.aliases.self = "this"; + inverse = "self.noop"; + } + + options.push("inverse:" + inverse); + options.push("fn:" + program); + } + + for(var i=0; i<paramSize; i++) { + param = this.popStack(); + params.push(param); + + if(this.options.stringParams) { + contexts.push(this.popStack()); + } + } + + if (this.options.stringParams) { + options.push("contexts:[" + contexts.join(",") + "]"); + } + + if(this.options.data) { + options.push("data:data"); + } + + params.push("{" + options.join(",") + "}"); + return params.join(", "); + } + }; + + var reservedWords = ( + "break else new var" + + " case finally return void" + + " catch for switch while" + + " continue function this with" + + " default if throw" + + " delete in try" + + " do instanceof typeof" + + " abstract enum int short" + + " boolean export interface static" + + " byte extends long super" + + " char final native synchronized" + + " class float package throws" + + " const goto private transient" + + " debugger implements protected volatile" + + " double import public let yield" + ).split(" "); + + var compilerWords = JavaScriptCompiler.RESERVED_WORDS = {}; + + for(var i=0, l=reservedWords.length; i<l; i++) { + compilerWords[reservedWords[i]] = true; + } + + JavaScriptCompiler.isValidJavaScriptVariableName = function(name) { + if(!JavaScriptCompiler.RESERVED_WORDS[name] && /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)) { + return true; + } + return false; + }; + +})(Handlebars.Compiler, Handlebars.JavaScriptCompiler); + +Handlebars.precompile = function(string, options) { + options = options || {}; + + var ast = Handlebars.parse(string); + var environment = new Handlebars.Compiler().compile(ast, options); + return new Handlebars.JavaScriptCompiler().compile(environment, options); +}; + +Handlebars.compile = function(string, options) { + options = options || {}; + + var compiled; + function compile() { + var ast = Handlebars.parse(string); + var environment = new Handlebars.Compiler().compile(ast, options); + var templateSpec = new Handlebars.JavaScriptCompiler().compile(environment, options, undefined, true); + return Handlebars.template(templateSpec); + } + + // Template is only compiled on first use and cached after that point. + return function(context, options) { + if (!compiled) { + compiled = compile(); + } + return compiled.call(this, context, options); + }; +}; +; +// lib/handlebars/runtime.js +Handlebars.VM = { + template: function(templateSpec) { + // Just add water + var container = { + escapeExpression: Handlebars.Utils.escapeExpression, + invokePartial: Handlebars.VM.invokePartial, + programs: [], + program: function(i, fn, data) { + var programWrapper = this.programs[i]; + if(data) { + return Handlebars.VM.program(fn, data); + } else if(programWrapper) { + return programWrapper; + } else { + programWrapper = this.programs[i] = Handlebars.VM.program(fn); + return programWrapper; + } + }, + programWithDepth: Handlebars.VM.programWithDepth, + noop: Handlebars.VM.noop + }; + + return function(context, options) { + options = options || {}; + return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data); + }; + }, + + programWithDepth: function(fn, data, $depth) { + var args = Array.prototype.slice.call(arguments, 2); + + return function(context, options) { + options = options || {}; + + return fn.apply(this, [context, options.data || data].concat(args)); + }; + }, + program: function(fn, data) { + return function(context, options) { + options = options || {}; + + return fn(context, options.data || data); + }; + }, + noop: function() { return ""; }, + invokePartial: function(partial, name, context, helpers, partials, data) { + var options = { helpers: helpers, partials: partials, data: data }; + + if(partial === undefined) { + throw new Handlebars.Exception("The partial " + name + " could not be found"); + } else if(partial instanceof Function) { + return partial(context, options); + } else if (!Handlebars.compile) { + throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode"); + } else { + partials[name] = Handlebars.compile(partial, {data: data !== undefined}); + return partials[name](context, options); + } + } +}; + +Handlebars.template = Handlebars.VM.template; +; diff --git a/src/static/jquery/bootstrap-editable-1.3.0/CHANGELOG.txt b/src/static/jquery/bootstrap-editable-1.3.0/CHANGELOG.txt new file mode 100755 index 0000000..5c410ec --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.3.0/CHANGELOG.txt @@ -0,0 +1,103 @@ +X-editable changelog +============================= + + +Version 1.3.0 Dec 10, 2012 +---------------------------- +[enh] added html5 inputs support: password, email, url, tel, number, range (vitalets) +[bug #43] fix for bootstrap 2.2.2 (vitalets) +[enh #41] 'abstract' class renamed to 'abstractinput' as abstract is reserved word (vitalets) +[enh #40] 'params' option defined as function overwrites original ajax data instead of appending (vitalets) +[bug] datepicker: error when click on arrows after clear date (vitalets) +[enh] 'hidden' event: added possible value of reason param - 'nochange'. Occurs when form is submitted but value was not changed (vitalets) +[enh] 'submit' method changed: error-callback's parameter simplified (vitalets) +[enh] 'submit' method changed: now when response 200 OK it does not set pk automatically (vitalets) +[enh] 'submit' method changed: removed dataType='json'. Use 'ajaxOptions' to specify dataType if needed (vitalets) +[enh] removed default ajax dataType='json'. Use 'ajaxOptions' to specify dataType if needed (vitalets) +[enh] select: do not show 'sourceError' in element during autotext execution (vitalets) + + +Version 1.2.0 Dec 6, 2012 +---------------------------- +[enh #36] 'submit' method: added 'ajaxOptions' property to modify ajax request (vitalets) +[enh] inputs now internally use 'value2submit' method instead of previous 'value2str' (vitalets) +[enh] editableContainer removed from docs (vitalets) +[enh] editableContainer: removed 'autohide' option and 'cancel' event. Use 'hidden' event instead (vitalets) +[enh] 'hidden' event: added param 'reason' that points to reason caused hiding (vitalets) +[enh] 'select' submit by enter (vitalets) +[bug #37] fix incorrectly shown datepicker in jquery 1.7.1 + webkit (vitalets) +[enh] added url param 'jquery' to run tests in different versions of jquery, e.g. '&jquery=1.7.2' (vitalets) +[enh] 'enablefocus' option removed. More efficient to use 'save/hide' events to set focus to any element (vitalets) +[enh] 'init' event was added due to removal of render event (vitalets) +[enh] 'render' event was removed, use 'display' callback instead (vitalets) +[enh] 'checklist' submit value as array, not comma separated string (vitalets) +[enh] 'checklist' was refactored: options 'viewseparator', 'limit', 'limitText' are supressed by 'display' callback (vitalets) +[enh] new option: 'display' callback. Makes far more flexible rendering value into element's text. (vitalets) +[bug] fix typos (atrophic) +[enh] all callbacks scope changed to element (vitalets) +[enh] new option: 'savenochange' to save or cancel value when it was not changed in form (vitalets) +[enh] composite pk can be defined as JSON in data-pk attribute (vitalets) +[enh #30] new option 'sourceCache' true|false to disable cache for select (vitalets) +[bug #34] inputclass span* broken with fluid bootstrap layout. Classes changed to 'input-*'. (vitalets) +[enh] utils now added to $.fn.editableutils instead of $.fn.editableform.utils (vitalets) +[enh] input types now added to $.fn.editabletypes instead of $.fn.editableform.types (vitalets) +[enh] playground and tests now use requirejs (vitalets) +[bug #27] 'today' button toggle bug in bootstrap-datepicker (vitalets) + + +Version 1.1.1 Nov 30, 2012 +---------------------------- +[enh] 'showbuttons' option to hide buttons in form (vitalets) +[enh] object can be passed in 'option' method to set several options at once (vitalets) +[enh #20] toggle editable by 'dblclick' and 'mouseenter' (vitalets) +[enh] added 'inputs-ext' directory with sample input 'address'. They will not be concatenated to main files (vitalets) +[enh #13] 'onblur' option: to cancel, submit or ignore when user clicks outside the form (vitalets) +[enh] 'ajaxOptions' parameter for advanced ajax configuration (vitalets) +[enh] 'success' callback can return object to overwrite submitted value (vitalets) + + +Version 1.1.0 Nov 27, 2012 +---------------------------- +[enh #11] icon cancel changed to 'cross' (tarciozemel) +[enh] added support for IE7+ (vitalets) +[enh #9] 'name' or 'id' is not required anymore (vitalets) +[enh] 'clear' button added in date and dateui (vitalets) +[enh] form template changed: added DIV.editable-input, DIV.editable.buttons and $.fn.editableform.buttons (vitalets) +[enh] new input type: checklist (vitalets) +[enh] updated docs: inputs dropdown menu, global templates section (vitalets) + + +Version 1.0.1 Nov 22, 2012 +---------------------------- +[enh] contribution guide in README.md (vitalets) +[enh #7] 'shown', 'hidden' events added (vitalets) +[enh #1] params can be a function to calculate it dynamically (vitalets) +[enh #6] do not preventDefault() in click when toggle='manual'. This allows to have clickable links (vitalets) +[bug #3] should not mark element with unsave css if url is user's function (vitalets) + + +Version 1.0.0 Nov 19, 2012 +---------------------------- +Initial release. This library is new life of bootstrap-editable (1.1.4) that was strongly refactored and improved. +Main features: +- support not only bootstrap but any core library: bootstrap, jquery-ui or pure jquery +- different container classes to show form: popover, tooltip, poshytip, etc +- inline and popup versions +- new directory structure and logic in separate js files allowing easy contribution + +It is not fully compatible with bootstrap-editable but has mainly the same interface and api. +Here list of differences to help you to upgrade your application: + +[change] 'toggle' option value can be only click|manual (not toggling element id). In case of 'manual' you should write handler calling 'show' method. +[change] 'validate' option cannot be defined as object anymore. +[change] events 'init', 'update', 'shown', 'hidden' removed. Events 'save', 'cancel' added. Event 'render' remains. +[change] input's option 'template' renamed to 'tpl' (to exclude conflict with container's template). +[change] value can be stored internally as object (previously was always string). Useful for date input. +[change] 'error' callback option is removed. 'success' callback remained. +[enh] 'source' option in select can be array of structure [{value: 1, text: 'abc'}, {...}]. This allows to keep ordering of items in dropdown list. Previous format is supported for compatibility. +[enh] api method 'setValue' to set manually value of editable. +[change] locales directory is excluded from bootstrap-datepicker input. If you need localization you should jus download corresponding file from github. +[change] date and dateui specific options can be set only via 'datepicker' option in first level of config (previously it was possible to set some options directly in config, e.g. weekStart). +[change] if 'url' option defined as function - it is used as submit method instead of ajax (previously it was dynamically return url string and ajax occurred anyway) + +Also all known bugs of bootstrap-editable were closed. diff --git a/src/static/jquery/bootstrap-editable-1.3.0/LICENSE-MIT b/src/static/jquery/bootstrap-editable-1.3.0/LICENSE-MIT new file mode 100755 index 0000000..bc67d5b --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.3.0/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 Vitaliy Potapov + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/static/jquery/bootstrap-editable-1.3.0/README.md b/src/static/jquery/bootstrap-editable-1.3.0/README.md new file mode 100755 index 0000000..38aacf7 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.3.0/README.md @@ -0,0 +1,71 @@ +# X-editable + +In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery. +It is a new life of [bootstrap-editable plugin](http://github.com/vitalets/bootstrap-editable) that was strongly refactored and improved. + +## Demo + Docs + Download +See **http://vitalets.github.com/x-editable** + +## Reporting issues +When creating issues please provide [jsFiddle](http://jsfiddle.net) example. You can easily fork one of **jsFiddle templates**: +1. [bootstrap](http://jsfiddle.net/xBB5x/25/) +2. [jqueryui](http://jsfiddle.net/xBB5x/24/) +3. [plain](http://jsfiddle.net/xBB5x/23/) +Your feedback is very appreciated! + +## Contribution +A few steps how to start contributing: + +1.[Fork X-editable](https://github.com/vitalets/x-editable/fork) and pull the latest changes from <code>dev</code> branch + +2.Arrange local directory structure. It should be: +**x-editable** + | -- **lib** (repo related to <code>dev</code> and <code>master</code> branches) + | -- **gh-pages** (repo related to <code>gh-pages</code> branch for docs & demo) + | -- **playground** (simple node-server and html page for testing, [playground_1.2.zip](https://github.com/downloads/vitalets/x-editable/playground_1.2.zip), **updated in 1.2.0!**) + +To make it easy follow this script ( _assuming you have [nodejs](http://nodejs.org) installed_ ). +Please replace <code>&lt;your-github-name&gt;</code> with your name: +```` +mkdir x-editable +cd x-editable + +#lib +git clone https://github.com/<your-github-name>/x-editable.git -b dev lib +cd lib +#install gruntjs globally - building tool +npm install -g grunt +#install other dependencies - grunt-contrib +npm install +cd .. + +#gh-pages +git clone https://github.com/<your-github-name>/x-editable.git -b gh-pages gh-pages +cd gh-pages +npm install +cd .. + +#playground +#download playground.zip from https://github.com/downloads/vitalets/x-editable/playground_1.2.zip +unzip playground.zip +cd playground +npm install +```` +3.That's it! You can start editing files in **lib/src** directory or create new editable input/container/whatever. +To test the result go to **playground**, start server <code>node server.js</code> and open in your browser [http://localhost:3000/playground](http://localhost:3000/playground). + +4.To run unit tests you can open it directly in browser **lib/test/index.html**. +Or use grunt's _qunit_ task <code>grunt test</code>. For that you also need to [install PhantomJS](https://github.com/gruntjs/grunt/blob/master/docs/faq.md#why-does-grunt-complain-that-phantomjs-isnt-installed) + +5.To build distributive run <code>grunt build</code> in **lib** directory. Result will appear in **lib/dist**. + +6.To build docs run <code>build data-docs-dist</code> in **gh-pages** directory. Result will appear in **gh-pages/*.html**. +Do not edit **index.html** and **docs.html** directly! Instead look at [Handlebars](https://github.com/wycats/handlebars.js) templates in **generator/templates**. + +7.Commit changes on <code>dev</code> / <code>gh-pages-dev</code> branch and make pull request as usual. + +Thanks for your support! + +## License +Copyright (c) 2012 Vitaliy Potapov +Licensed under the MIT licenses. \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/css/bootstrap-editable.css b/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/css/bootstrap-editable.css new file mode 100755 index 0000000..7c0b1c2 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/css/bootstrap-editable.css @@ -0,0 +1,434 @@ +/*! X-editable - v1.3.0 +* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery +* http://github.com/vitalets/x-editable +* Copyright (c) 2012 Vitaliy Potapov; Licensed MIT */ + +.editableform { + margin-bottom: 0; /* overwrites bootstrap margin */ +} + +.editableform .control-group { + margin-bottom: 0; /* overwrites bootstrap margin */ + white-space: nowrap; /* prevent wrapping buttons on new line */ +} + +.editable-buttons { + display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ + vertical-align: top; + margin-left: 7px; + /* display-inline emulation for IE7*/ + zoom: 1; + *display: inline; +} + + + +.editable-input { + vertical-align: top; + display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ + width: auto; /* bootstrap-responsive has width: 100% that breakes layout */ + white-space: normal; /* reset white-space decalred in parent*/ + /* display-inline emulation for IE7*/ + zoom: 1; + *display: inline; +} + +.editable-buttons .editable-cancel { + margin-left: 7px; +} + +/*for jquery-ui buttons need set height to look more pretty*/ +.editable-buttons button.ui-button-icon-only { + height: 24px; + width: 30px; +} + +.editableform-loading { + background: url('img/loading.gif') center center no-repeat; + height: 25px; + width: auto; + min-width: 25px; +} + +.editable-inline .editableform-loading { + background-position: left 5px; +} + + .editable-error-block { + max-width: 300px; + margin: 5px 0 0 0; + width: auto; + white-space: normal; +} + +/*add padding for jquery ui*/ +.editable-error-block.ui-state-error { + padding: 3px; +} + +.editable-error { + color: red; +} + +.editableform textarea { + height: 150px; /*default height for textarea*/ +} + +.editableform .editable-date { + padding: 0; + margin: 0; + float: left; +} + + +/* checklist vertical alignment */ +.editable-checklist label input[type="checkbox"], +.editable-checklist label span { + vertical-align: middle; + margin: 0; +} + +.editable-checklist label { + white-space: nowrap; +} + +.editable-clear { + clear: both; + font-size: 0.9em; + text-decoration: none; + text-align: right; +} +.editable-container { + max-width: none !important; /* without this rule poshytip/tooltip does not stretch */ +} + +.editable-container.popover { +/* width: 300px;*/ /* debug */ + width: auto; /* without this rule popover does not stretch */ +} + +.editable-container.editable-inline { +/* display: inline; */ /* display: inline does not correctly work with show()/hide() in jquery <= 1.7.2 */ + display: inline-block; + vertical-align: middle; +} + +.editable-container.ui-widget { + font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */ +} +.editable-click, +a.editable-click, +a.editable-click:hover { + text-decoration: none; + border-bottom: dashed 1px #0088cc; +} + +.editable-click.editable-disabled, +a.editable-click.editable-disabled, +a.editable-click.editable-disabled:hover { + color: #585858; + cursor: default; + border-bottom: none; +} + +.editable-empty, .editable-empty:hover{ + font-style: italic; + color: #DD1144; + border-bottom: none; + text-decoration: none; +} + +.editable-unsaved { + font-weight: bold; +} + +.editable-unsaved:after { +/* content: '*'*/ +} + + +/*! + * Datepicker for Bootstrap + * + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +.datepicker { + padding: 4px; + margin-top: 1px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + /*.dow { + border-top: 1px solid #ddd !important; + }*/ +} + +.datepicker-inline { + width: 220px; +/* height: 220px; */ +} + +.datepicker-float { + top: 0; + left: 0; +} + +.datepicker-float:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; + top: -7px; + left: 6px; +} +.datepicker-float:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + position: absolute; + top: -6px; + left: 7px; +} +.datepicker > div { + display: none; +} +.datepicker.days div.datepicker-days { + display: block; +} +.datepicker.months div.datepicker-months { + display: block; +} +.datepicker.years div.datepicker-years { + display: block; +} +.datepicker table { + margin: 0; +} +.datepicker td, +.datepicker th { + text-align: center; + width: 20px; + height: 20px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + /* vitalets: required to disable css inheritance when display inline inside table */ + border: none !important; + background-color: transparent !important; +} +.datepicker td.day:hover { + background: #eeeeee !important; /* disable inheritance for inline */ + cursor: pointer; +} +.datepicker td.old, +.datepicker td.new { + color: #999999; +} +.datepicker td.disabled, +.datepicker td.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datepicker td.today, +.datepicker td.today:hover, +.datepicker td.today.disabled, +.datepicker td.today.disabled:hover { + background-color: #fde19a !important; /* disable inheritance for inline */ + background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a)); + background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -o-linear-gradient(top, #fdd49a, #fdf59a); + background-image: linear-gradient(top, #fdd49a, #fdf59a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0); + border-color: #fdf59a #fdf59a #fbed50; + 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(enabled=false); +} +.datepicker td.today:hover, +.datepicker td.today:hover:hover, +.datepicker td.today.disabled:hover, +.datepicker td.today.disabled:hover:hover, +.datepicker td.today:active, +.datepicker td.today:hover:active, +.datepicker td.today.disabled:active, +.datepicker td.today.disabled:hover:active, +.datepicker td.today.active, +.datepicker td.today:hover.active, +.datepicker td.today.disabled.active, +.datepicker td.today.disabled:hover.active, +.datepicker td.today.disabled, +.datepicker td.today:hover.disabled, +.datepicker td.today.disabled.disabled, +.datepicker td.today.disabled:hover.disabled, +.datepicker td.today[disabled], +.datepicker td.today:hover[disabled], +.datepicker td.today.disabled[disabled], +.datepicker td.today.disabled:hover[disabled] { + background-color: #fdf59a !important; /* disable inheritance for inline */ +} +.datepicker td.today:active, +.datepicker td.today:hover:active, +.datepicker td.today.disabled:active, +.datepicker td.today.disabled:hover:active, +.datepicker td.today.active, +.datepicker td.today:hover.active, +.datepicker td.today.disabled.active, +.datepicker td.today.disabled:hover.active { + background-color: #fbf069 \9; +} +.datepicker td.active, +.datepicker td.active:hover, +.datepicker td.active.disabled, +.datepicker td.active.disabled:hover { + background-color: #006dcc !important; /* disable inheritance for inline */ + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-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(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + 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(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datepicker td.active:hover, +.datepicker td.active:hover:hover, +.datepicker td.active.disabled:hover, +.datepicker td.active.disabled:hover:hover, +.datepicker td.active:active, +.datepicker td.active:hover:active, +.datepicker td.active.disabled:active, +.datepicker td.active.disabled:hover:active, +.datepicker td.active.active, +.datepicker td.active:hover.active, +.datepicker td.active.disabled.active, +.datepicker td.active.disabled:hover.active, +.datepicker td.active.disabled, +.datepicker td.active:hover.disabled, +.datepicker td.active.disabled.disabled, +.datepicker td.active.disabled:hover.disabled, +.datepicker td.active[disabled], +.datepicker td.active:hover[disabled], +.datepicker td.active.disabled[disabled], +.datepicker td.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datepicker td.active:active, +.datepicker td.active:hover:active, +.datepicker td.active.disabled:active, +.datepicker td.active.disabled:hover:active, +.datepicker td.active.active, +.datepicker td.active:hover.active, +.datepicker td.active.disabled.active, +.datepicker td.active.disabled:hover.active { + background-color: #003399 \9; +} +.datepicker td span { + display: block; + width: 23%; + height: 54px; + line-height: 54px; + float: left; + margin: 1%; + cursor: pointer; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.datepicker td span:hover { + background: #eeeeee; +} +.datepicker td span.disabled, +.datepicker td span.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datepicker td span.active, +.datepicker td span.active:hover, +.datepicker td span.active.disabled, +.datepicker td span.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-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(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + 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(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datepicker td span.active:hover, +.datepicker td span.active:hover:hover, +.datepicker td span.active.disabled:hover, +.datepicker td span.active.disabled:hover:hover, +.datepicker td span.active:active, +.datepicker td span.active:hover:active, +.datepicker td span.active.disabled:active, +.datepicker td span.active.disabled:hover:active, +.datepicker td span.active.active, +.datepicker td span.active:hover.active, +.datepicker td span.active.disabled.active, +.datepicker td span.active.disabled:hover.active, +.datepicker td span.active.disabled, +.datepicker td span.active:hover.disabled, +.datepicker td span.active.disabled.disabled, +.datepicker td span.active.disabled:hover.disabled, +.datepicker td span.active[disabled], +.datepicker td span.active:hover[disabled], +.datepicker td span.active.disabled[disabled], +.datepicker td span.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datepicker td span.active:active, +.datepicker td span.active:hover:active, +.datepicker td span.active.disabled:active, +.datepicker td span.active.disabled:hover:active, +.datepicker td span.active.active, +.datepicker td span.active:hover.active, +.datepicker td span.active.disabled.active, +.datepicker td span.active.disabled:hover.active { + background-color: #003399 \9; +} +.datepicker td span.old { + color: #999999; +} +.datepicker th.switch { + width: 145px; +} +.datepicker thead tr:first-child th, +.datepicker tfoot tr:first-child th { + cursor: pointer; +} +.datepicker thead tr:first-child th:hover, +.datepicker tfoot tr:first-child th:hover { + background: #eeeeee; +} +.input-append.date .add-on i, +.input-prepend.date .add-on i { + display: block; + cursor: pointer; + width: 16px; + height: 16px; +} diff --git a/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/css/img/loading.gif b/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/css/img/loading.gif new file mode 100755 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 GIT binary patch literal 1849 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 EAHN$8j{pDw literal 0 HcmV?d00001 diff --git a/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable-inline.js b/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable-inline.js new file mode 100755 index 0000000..1b39c79 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable-inline.js @@ -0,0 +1,3769 @@ +/*! X-editable - v1.3.0 +* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery +* http://github.com/vitalets/x-editable +* Copyright (c) 2012 Vitaliy Potapov; Licensed MIT */ + +/** +Form with single input element, two buttons and two states: normal/loading. +Applied as jQuery method to DIV tag (not to form tag!). This is because form can be in loading state when spinner shown. +Editableform is linked with one of input types, e.g. 'text', 'select' etc. + +@class editableform +@uses text +@uses textarea +**/ +(function ($) { + + var EditableForm = function (div, options) { + this.options = $.extend({}, $.fn.editableform.defaults, options); + this.$div = $(div); //div, containing form. Not form tag! Not editable-element. + if(!this.options.scope) { + this.options.scope = this; + } + this.initInput(); + }; + + EditableForm.prototype = { + constructor: EditableForm, + initInput: function() { //called once + var TypeConstructor, typeOptions; + + //create input of specified type + if(typeof $.fn.editabletypes[this.options.type] === 'function') { + TypeConstructor = $.fn.editabletypes[this.options.type]; + typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults)); + this.input = new TypeConstructor(typeOptions); + } else { + $.error('Unknown type: '+ this.options.type); + return; + } + + this.value = this.input.str2value(this.options.value); + }, + initTemplate: function() { + this.$form = $($.fn.editableform.template); + }, + initButtons: function() { + this.$form.find('.editable-buttons').append($.fn.editableform.buttons); + }, + /** + Renders editableform + + @method render + **/ + render: function() { + this.$loading = $($.fn.editableform.loading); + this.$div.empty().append(this.$loading); + this.showLoading(); + + //init form template and buttons + this.initTemplate(); + if(this.options.showbuttons) { + this.initButtons(); + } else { + this.$form.find('.editable-buttons').remove(); + } + + /** + Fired when rendering starts + @event rendering + @param {Object} event event object + **/ + this.$div.triggerHandler('rendering'); + + //render input + $.when(this.input.render()) + .then($.proxy(function () { + //input + this.$form.find('div.editable-input').append(this.input.$input); + + //automatically submit inputs when no buttons shown + if(!this.options.showbuttons) { + this.input.autosubmit(); + } + + //"clear" link + if(this.input.$clear) { + this.$form.find('div.editable-input').append($('<div class="editable-clear">').append(this.input.$clear)); + } + + //append form to container + this.$div.append(this.$form); + + //attach 'cancel' handler + this.$form.find('.editable-cancel').click($.proxy(this.cancel, this)); + + if(this.input.error) { + this.error(this.input.error); + this.$form.find('.editable-submit').attr('disabled', true); + this.input.$input.attr('disabled', true); + //prevent form from submitting + this.$form.submit(function(e){ e.preventDefault(); }); + } else { + this.error(false); + this.input.$input.removeAttr('disabled'); + this.$form.find('.editable-submit').removeAttr('disabled'); + this.input.value2input(this.value); + //attach submit handler + this.$form.submit($.proxy(this.submit, this)); + } + + /** + Fired when form is rendered + @event rendered + @param {Object} event event object + **/ + this.$div.triggerHandler('rendered'); + + this.showForm(); + }, this)); + }, + cancel: function() { + /** + Fired when form was cancelled by user + @event cancel + @param {Object} event event object + **/ + this.$div.triggerHandler('cancel'); + }, + showLoading: function() { + var w; + if(this.$form) { + //set loading size equal to form + this.$loading.width(this.$form.outerWidth()); + this.$loading.height(this.$form.outerHeight()); + this.$form.hide(); + } else { + //stretch loading to fill container width + w = this.$loading.parent().width(); + if(w) { + this.$loading.width(w); + } + } + this.$loading.show(); + }, + + showForm: function(activate) { + this.$loading.hide(); + this.$form.show(); + if(activate !== false) { + this.input.activate(); + } + /** + Fired when form is shown + @event show + @param {Object} event event object + **/ + this.$div.triggerHandler('show'); + }, + + error: function(msg) { + var $group = this.$form.find('.control-group'), + $block = this.$form.find('.editable-error-block'); + + if(msg === false) { + $group.removeClass($.fn.editableform.errorGroupClass); + $block.removeClass($.fn.editableform.errorBlockClass).empty().hide(); + } else { + $group.addClass($.fn.editableform.errorGroupClass); + $block.addClass($.fn.editableform.errorBlockClass).text(msg).show(); + } + }, + + submit: function(e) { + e.stopPropagation(); + e.preventDefault(); + + var error, + newValue = this.input.input2value(); //get new value from input + + //validation + if (error = this.validate(newValue)) { + this.error(error); + this.showForm(); + return; + } + + //if value not changed --> trigger 'nochange' event and return + /*jslint eqeq: true*/ + if (!this.options.savenochange && this.input.value2str(newValue) == this.input.value2str(this.value)) { + /*jslint eqeq: false*/ + /** + Fired when value not changed but form is submitted. Requires savenochange = false. + @event nochange + @param {Object} event event object + **/ + this.$div.triggerHandler('nochange'); + return; + } + + //sending data to server + $.when(this.save(newValue)) + .done($.proxy(function(response) { + //run success callback + var res = typeof this.options.success === 'function' ? this.options.success.call(this.options.scope, response, newValue) : null; + + //if success callback returns false --> keep form open and do not activate input + if(res === false) { + this.error(false); + this.showForm(false); + return; + } + + //if success callback returns string --> keep form open, show error and activate input + if(typeof res === 'string') { + this.error(res); + this.showForm(); + return; + } + + //if success callback returns object like {newValue: <something>} --> use that value instead of submitted + if(res && typeof res === 'object' && res.hasOwnProperty('newValue')) { + newValue = res.newValue; + } + + //clear error message + this.error(false); + this.value = newValue; + /** + Fired when form is submitted + @event save + @param {Object} event event object + @param {Object} params additional params + @param {mixed} params.newValue submitted value + @param {Object} params.response ajax response + + @example + $('#form-div').on('save'), function(e, params){ + if(params.newValue === 'username') {...} + }); + **/ + this.$div.triggerHandler('save', {newValue: newValue, response: response}); + }, this)) + .fail($.proxy(function(xhr) { + this.error(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!'); + this.showForm(); + }, this)); + }, + + save: function(newValue) { + //convert value for submitting to server + var submitValue = this.input.value2submit(newValue); + + //try parse composite pk defined as json string in data-pk + this.options.pk = $.fn.editableutils.tryParseJson(this.options.pk, true); + + var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this.options.scope) : this.options.pk, + send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk)))), + params; + + if (send) { //send to server + this.showLoading(); + + //standard params + params = { + name: this.options.name || '', + value: submitValue, + pk: pk + }; + + //additional params + if(typeof this.options.params === 'function') { + params = this.options.params.call(this.options.scope, params); + } else { + //try parse json in single quotes (from data-params attribute) + this.options.params = $.fn.editableutils.tryParseJson(this.options.params, true); + $.extend(params, this.options.params); + } + + if(typeof this.options.url === 'function') { //user's function + return this.options.url.call(this.options.scope, params); + } else { + //send ajax to server and return deferred object + return $.ajax($.extend({ + url : this.options.url, + data : params, + type : 'POST' + }, this.options.ajaxOptions)); + } + } + }, + + validate: function (value) { + if (value === undefined) { + value = this.value; + } + if (typeof this.options.validate === 'function') { + return this.options.validate.call(this.options.scope, value); + } + }, + + option: function(key, value) { + this.options[key] = value; + if(key === 'value') { + this.setValue(value); + } + }, + + setValue: function(value, convertStr) { + if(convertStr) { + this.value = this.input.str2value(value); + } else { + this.value = value; + } + } + }; + + /* + Initialize editableform. Applied to jQuery object. + + @method $().editableform(options) + @params {Object} options + @example + var $form = $('&lt;div&gt;').editableform({ + type: 'text', + name: 'username', + url: '/post', + value: 'vitaliy' + }); + + //to display form you should call 'render' method + $form.editableform('render'); + */ + $.fn.editableform = function (option) { + var args = arguments; + return this.each(function () { + var $this = $(this), + data = $this.data('editableform'), + options = typeof option === 'object' && option; + if (!data) { + $this.data('editableform', (data = new EditableForm(this, options))); + } + + if (typeof option === 'string') { //call method + data[option].apply(data, Array.prototype.slice.call(args, 1)); + } + }); + }; + + //keep link to constructor to allow inheritance + $.fn.editableform.Constructor = EditableForm; + + //defaults + $.fn.editableform.defaults = { + /* see also defaults for input */ + + /** + Type of input. Can be <code>text|textarea|select|date|checklist</code> + + @property type + @type string + @default 'text' + **/ + type: 'text', + /** + Url for submit, e.g. <code>'/post'</code> + If function - it will be called instead of ajax. Function can return deferred object to run fail/done callbacks. + + @property url + @type string|function + @default null + @example + url: function(params) { + if(params.value === 'abc') { + var d = new $.Deferred; + return d.reject('field cannot be "abc"'); //returning error via deferred object + } else { + someModel.set(params.name, params.value); //save data in some js model + } + } + **/ + url:null, + /** + Additional params for submit. If defined as <code>object</code> - it is **appended** to original ajax data (pk, name and value). + If defined as <code>function</code> - returned object **overwrites** original ajax data. + @example + params: function(params) { + //originally params contain pk, name and value + params.a = 1; + return params; + } + + @property params + @type object|function + @default null + **/ + params:null, + /** + Name of field. Will be submitted on server. Can be taken from <code>id</code> attribute + + @property name + @type string + @default null + **/ + name: null, + /** + Primary key of editable object (e.g. record id in database). For composite keys use object, e.g. <code>{id: 1, lang: 'en'}</code>. + Can be calculated dynamically via function. + + @property pk + @type string|object|function + @default null + **/ + pk: null, + /** + Initial value. If not defined - will be taken from element's content. + For __select__ type should be defined (as it is ID of shown text). + + @property value + @type string|object + @default null + **/ + value: null, + /** + Strategy for sending data on server. Can be <code>auto|always|never</code>. + When 'auto' data will be sent on server only if pk defined, otherwise new value will be stored in element. + + @property send + @type string + @default 'auto' + **/ + send: 'auto', + /** + Function for client-side validation. If returns string - means validation not passed and string showed as error. + + @property validate + @type function + @default null + @example + validate: function(value) { + if($.trim(value) == '') { + return 'This field is required'; + } + } + **/ + validate: null, + /** + Success callback. Called when value successfully sent on server and **response status = 200**. + Useful to work with json response. For example, if your backend response can be <code>{success: true}</code> + or <code>{success: false, msg: "server error"}</code> you can check it inside this callback. + If it returns **string** - means error occured and string is shown as error message. + If it returns **object like** <code>{newValue: &lt;something&gt;}</code> - it overwrites value, submitted by user. + Otherwise newValue simply rendered into element. + + @property success + @type function + @default null + @example + success: function(response, newValue) { + if(!response.success) return response.msg; + } + **/ + success: null, + /** + Additional options for ajax request. + List of values: http://api.jquery.com/jQuery.ajax + + @property ajaxOptions + @type object + @default null + @since 1.1.1 + **/ + ajaxOptions: null, + /** + Whether to show buttons or not. + Form without buttons can be auto-submitted by input or by onblur = 'submit'. + @example + ajaxOptions: { + method: 'PUT', + dataType: 'xml' + } + + @property showbuttons + @type boolean + @default true + @since 1.1.1 + **/ + showbuttons: true, + /** + Scope for callback methods (success, validate). + If <code>null</code> means editableform instance itself. + + @property scope + @type DOMElement|object + @default null + @since 1.2.0 + @private + **/ + scope: null, + /** + Whether to save or cancel value when it was not changed but form was submitted + + @property savenochange + @type boolean + @default false + @since 1.2.0 + **/ + savenochange: false + }; + + /* + Note: following params could redefined in engine: bootstrap or jqueryui: + Classes 'control-group' and 'editable-error-block' must always present! + */ + $.fn.editableform.template = '<form class="form-inline editableform">'+ + '<div class="control-group">' + + '<div><div class="editable-input"></div><div class="editable-buttons"></div></div>'+ + '<div class="editable-error-block"></div>' + + '</div>' + + '</form>'; + + //loading div + $.fn.editableform.loading = '<div class="editableform-loading"></div>'; + + //buttons + $.fn.editableform.buttons = '<button type="submit" class="editable-submit">ok</button>'+ + '<button type="button" class="editable-cancel">cancel</button>'; + + //error class attached to control-group + $.fn.editableform.errorGroupClass = null; + + //error class attached to editable-error-block + $.fn.editableform.errorBlockClass = 'editable-error'; +}(window.jQuery)); +/** +* EditableForm utilites +*/ +(function ($) { + //utils + $.fn.editableutils = { + /** + * classic JS inheritance function + */ + inherit: function (Child, Parent) { + var F = function() { }; + F.prototype = Parent.prototype; + Child.prototype = new F(); + Child.prototype.constructor = Child; + Child.superclass = Parent.prototype; + }, + + /** + * set caret position in input + * see http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area + */ + setCursorPosition: function(elem, pos) { + if (elem.setSelectionRange) { + elem.setSelectionRange(pos, pos); + } else if (elem.createTextRange) { + var range = elem.createTextRange(); + range.collapse(true); + range.moveEnd('character', pos); + range.moveStart('character', pos); + range.select(); + } + }, + + /** + * function to parse JSON in *single* quotes. (jquery automatically parse only double quotes) + * That allows such code as: <a data-source="{'a': 'b', 'c': 'd'}"> + * safe = true --> means no exception will be thrown + * for details see http://stackoverflow.com/questions/7410348/how-to-set-json-format-to-html5-data-attributes-in-the-jquery + */ + tryParseJson: function(s, safe) { + if (typeof s === 'string' && s.length && s.match(/^[\{\[].*[\}\]]$/)) { + if (safe) { + try { + /*jslint evil: true*/ + s = (new Function('return ' + s))(); + /*jslint evil: false*/ + } catch (e) {} finally { + return s; + } + } else { + /*jslint evil: true*/ + s = (new Function('return ' + s))(); + /*jslint evil: false*/ + } + } + return s; + }, + + /** + * slice object by specified keys + */ + sliceObj: function(obj, keys, caseSensitive /* default: false */) { + var key, keyLower, newObj = {}; + + if (!$.isArray(keys) || !keys.length) { + return newObj; + } + + for (var i = 0; i < keys.length; i++) { + key = keys[i]; + if (obj.hasOwnProperty(key)) { + newObj[key] = obj[key]; + } + + if(caseSensitive === true) { + continue; + } + + //when getting data-* attributes via $.data() it's converted to lowercase. + //details: http://stackoverflow.com/questions/7602565/using-data-attributes-with-jquery + //workaround is code below. + keyLower = key.toLowerCase(); + if (obj.hasOwnProperty(keyLower)) { + newObj[key] = obj[keyLower]; + } + } + + return newObj; + }, + + /** + * exclude complex objects from $.data() before pass to config + */ + getConfigData: function($element) { + var data = {}; + $.each($element.data(), function(k, v) { + if(typeof v !== 'object' || (v && typeof v === 'object' && v.constructor === Object)) { + data[k] = v; + } + }); + return data; + }, + + objectKeys: function(o) { + if (Object.keys) { + return Object.keys(o); + } else { + if (o !== Object(o)) { + throw new TypeError('Object.keys called on a non-object'); + } + var k=[], p; + for (p in o) { + if (Object.prototype.hasOwnProperty.call(o,p)) { + k.push(p); + } + } + return k; + } + + }, + + /** + method to escape html. + **/ + escape: function(str) { + return $('<div>').text(str).html(); + } + }; +}(window.jQuery)); +/** +Attaches stand-alone container with editable-form to HTML element. Element is used only for positioning, value is not stored anywhere.<br> +This method applied internally in <code>$().editable()</code>. You should subscribe on it's events (save / cancel) to get profit of it.<br> +Final realization can be different: bootstrap-popover, jqueryui-tooltip, poshytip, inline-div. It depends on which js file you include.<br> +Applied as jQuery method. + +@class editableContainer +@uses editableform +**/ +(function ($) { + + var EditableContainer = function (element, options) { + this.init(element, options); + }; + + //methods + EditableContainer.prototype = { + containerName: null, //tbd in child class + innerCss: null, //tbd in child class + init: function(element, options) { + this.$element = $(element); + //todo: what is in priority: data or js? + this.options = $.extend({}, $.fn.editableContainer.defaults, $.fn.editableutils.getConfigData(this.$element), options); + this.splitOptions(); + this.initContainer(); + + //bind 'destroyed' listener to destroy container when element is removed from dom + this.$element.on('destroyed', $.proxy(function(){ + this.destroy(); + }, this)); + + //attach document handlers (once) + if(!$(document).data('editable-handlers-attached')) { + //close all on escape + $(document).on('keyup.editable', function (e) { + if (e.which === 27) { + $('.editable-open').editableContainer('hide'); + //todo: return focus on element + } + }); + + //close containers when click outside + $(document).on('click.editable', function(e) { + var $target = $(e.target); + + //if click inside some editableContainer --> no nothing + if($target.is('.editable-container') || $target.parents('.editable-container').length || $target.parents('.ui-datepicker-header').length) { + return; + } else { + //close all open containers (except one) + EditableContainer.prototype.closeOthers(e.target); + } + }); + + $(document).data('editable-handlers-attached', true); + } + }, + + //split options on containerOptions and formOptions + splitOptions: function() { + this.containerOptions = {}; + this.formOptions = {}; + var cDef = $.fn[this.containerName].defaults; + for(var k in this.options) { + if(k in cDef) { + this.containerOptions[k] = this.options[k]; + } else { + this.formOptions[k] = this.options[k]; + } + } + }, + + initContainer: function(){ + this.call(this.containerOptions); + }, + + initForm: function() { + this.formOptions.scope = this.$element[0]; //set scope of form callbacks to element + this.$form = $('<div>') + .editableform(this.formOptions) + .on({ + save: $.proxy(this.save, this), + cancel: $.proxy(function(){ this.hide('cancel'); }, this), + nochange: $.proxy(function(){ this.hide('nochange'); }, this), + show: $.proxy(this.setPosition, this), //re-position container every time form is shown (occurs each time after loading state) + rendering: $.proxy(this.setPosition, this), //this allows to place container correctly when loading shown + rendered: $.proxy(function(){ + /** + Fired when container is shown and form is rendered (for select will wait for loading dropdown options) + + @event shown + @param {Object} event event object + @example + $('#username').on('shown', function() { + var $tip = $(this).data('editableContainer').tip(); + $tip.find('input').val('overwriting value of input..'); + }); + **/ + this.$element.triggerHandler('shown'); + }, this) + }); + return this.$form; + }, + + /* + Returns jquery object of container + @method tip() + */ + tip: function() { + return this.container().$tip; + }, + + container: function() { + return this.$element.data(this.containerName); + }, + + call: function() { + this.$element[this.containerName].apply(this.$element, arguments); + }, + + /** + Shows container with form + @method show() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + show: function (closeAll) { + this.$element.addClass('editable-open'); + if(closeAll !== false) { + //close all open containers (except this) + this.closeOthers(this.$element[0]); + } + + this.innerShow(); + }, + + /* internal show method. To be overwritten in child classes */ + innerShow: function () { + this.call('show'); + this.tip().addClass('editable-container'); + this.initForm(); + this.tip().find(this.innerCss).empty().append(this.$form); + this.$form.editableform('render'); + }, + + /** + Hides container with form + @method hide() + @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|undefined (=manual)</code> + **/ + hide: function(reason) { + if(!this.tip() || !this.tip().is(':visible') || !this.$element.hasClass('editable-open')) { + return; + } + this.$element.removeClass('editable-open'); + this.innerHide(); + /** + Fired when container was hidden. It occurs on both save or cancel. + + @event hidden + @param {object} event event object + @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|undefined (=manual)</code> + @example + $('#username').on('hidden', function(e, reason) { + if(reason === 'save' || reason === 'cancel') { + //auto-open next editable + $(this).closest('tr').next().find('.editable').editable('show'); + } + }); + **/ + this.$element.triggerHandler('hidden', reason); + }, + + /* internal hide method. To be overwritten in child classes */ + innerHide: function () { + this.call('hide'); + }, + + /** + Toggles container visibility (show / hide) + @method toggle() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + toggle: function(closeAll) { + if(this.tip && this.tip().is(':visible')) { + this.hide(); + } else { + this.show(closeAll); + } + }, + + /* + Updates the position of container when content changed. + @method setPosition() + */ + setPosition: function() { + //tbd in child class + }, + + save: function(e, params) { + this.hide('save'); + /** + Fired when new value was submitted. You can use <code>$(this).data('editableContainer')</code> inside handler to access to editableContainer instance + + @event save + @param {Object} event event object + @param {Object} params additional params + @param {mixed} params.newValue submitted value + @param {Object} params.response ajax response + @example + $('#username').on('save', function(e, params) { + //assuming server response: '{success: true}' + var pk = $(this).data('editableContainer').options.pk; + if(params.response && params.response.success) { + alert('value: ' + params.newValue + ' with pk: ' + pk + ' saved!'); + } else { + alert('error!'); + } + }); + **/ + this.$element.triggerHandler('save', params); + }, + + /** + Sets new option + + @method option(key, value) + @param {string} key + @param {mixed} value + **/ + option: function(key, value) { + this.options[key] = value; + if(key in this.containerOptions) { + this.containerOptions[key] = value; + this.setContainerOption(key, value); + } else { + this.formOptions[key] = value; + if(this.$form) { + this.$form.editableform('option', key, value); + } + } + }, + + setContainerOption: function(key, value) { + this.call('option', key, value); + }, + + /** + Destroys the container instance + @method destroy() + **/ + destroy: function() { + this.call('destroy'); + }, + + /* + Closes other containers except one related to passed element. + Other containers can be cancelled or submitted (depends on onblur option) + */ + closeOthers: function(element) { + $('.editable-open').each(function(i, el){ + //do nothing with passed element and it's children + if(el === element || $(el).find(element).length) { + return; + } + + //otherwise cancel or submit all open containers + var $el = $(el), + ec = $el.data('editableContainer'); + + if(!ec) { + return; + } + + if(ec.options.onblur === 'cancel') { + $el.data('editableContainer').hide('onblur'); + } else if(ec.options.onblur === 'submit') { + $el.data('editableContainer').tip().find('form').submit(); + } + }); + + }, + + /** + Activates input of visible container (e.g. set focus) + @method activate() + **/ + activate: function() { + if(this.tip && this.tip().is(':visible') && this.$form) { + this.$form.data('editableform').input.activate(); + } + } + + }; + + /** + jQuery method to initialize editableContainer. + + @method $().editableContainer(options) + @params {Object} options + @example + $('#edit').editableContainer({ + type: 'text', + url: '/post', + pk: 1, + value: 'hello' + }); + **/ + $.fn.editableContainer = function (option) { + var args = arguments; + return this.each(function () { + var $this = $(this), + dataKey = 'editableContainer', + data = $this.data(dataKey), + options = typeof option === 'object' && option; + + if (!data) { + $this.data(dataKey, (data = new EditableContainer(this, options))); + } + + if (typeof option === 'string') { //call method + data[option].apply(data, Array.prototype.slice.call(args, 1)); + } + }); + }; + + //store constructor + $.fn.editableContainer.Constructor = EditableContainer; + + //defaults + $.fn.editableContainer.defaults = { + /** + Initial value of form input + + @property value + @type mixed + @default null + @private + **/ + value: null, + /** + Placement of container relative to element. Can be <code>top|right|bottom|left</code>. Not used for inline container. + + @property placement + @type string + @default 'top' + **/ + placement: 'top', + /** + Whether to hide container on save/cancel. + + @property autohide + @type boolean + @default true + @private + **/ + autohide: true, + /** + Action when user clicks outside the container. Can be <code>cancel|submit|ignore</code>. + Setting <code>ignore</code> allows to have several containers open. + + @property onblur + @type string + @default 'cancel' + @since 1.1.1 + **/ + onblur: 'cancel' + }; + + /* + * workaround to have 'destroyed' event to destroy popover when element is destroyed + * see http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom + */ + jQuery.event.special.destroyed = { + remove: function(o) { + if (o.handler) { + o.handler(); + } + } + }; + +}(window.jQuery)); + +/** +Makes editable any HTML element on the page. Applied as jQuery method. + +@class editable +@uses editableContainer +**/ +(function ($) { + + var Editable = function (element, options) { + this.$element = $(element); + this.options = $.extend({}, $.fn.editable.defaults, $.fn.editableutils.getConfigData(this.$element), options); + this.init(); + }; + + Editable.prototype = { + constructor: Editable, + init: function () { + var TypeConstructor, + isValueByText = false, + doAutotext, + finalize; + + //editableContainer must be defined + if(!$.fn.editableContainer) { + $.error('You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)'); + return; + } + + //name + this.options.name = this.options.name || this.$element.attr('id'); + + //create input of specified type. Input will be used for converting value, not in form + if(typeof $.fn.editabletypes[this.options.type] === 'function') { + TypeConstructor = $.fn.editabletypes[this.options.type]; + this.typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults)); + this.input = new TypeConstructor(this.typeOptions); + } else { + $.error('Unknown type: '+ this.options.type); + return; + } + + //set value from settings or by element's text + if (this.options.value === undefined || this.options.value === null) { + this.value = this.input.html2value($.trim(this.$element.html())); + isValueByText = true; + } else { + /* + value can be string when received from 'data-value' attribute + for complext objects value can be set as json string in data-value attribute, + e.g. data-value="{city: 'Moscow', street: 'Lenina'}" + */ + this.options.value = $.fn.editableutils.tryParseJson(this.options.value, true); + if(typeof this.options.value === 'string') { + this.value = this.input.str2value(this.options.value); + } else { + this.value = this.options.value; + } + } + + //add 'editable' class to every editable element + this.$element.addClass('editable'); + + //attach handler activating editable. In disabled mode it just prevent default action (useful for links) + if(this.options.toggle !== 'manual') { + this.$element.addClass('editable-click'); + this.$element.on(this.options.toggle + '.editable', $.proxy(function(e){ + e.preventDefault(); + //stop propagation not required anymore because in document click handler it checks event target + //e.stopPropagation(); + + if(this.options.toggle === 'mouseenter') { + //for hover only show container + this.show(); + } else { + //when toggle='click' we should not close all other containers as they will be closed automatically in document click listener + var closeAll = (this.options.toggle !== 'click'); + this.toggle(closeAll); + } + }, this)); + } else { + this.$element.attr('tabindex', -1); //do not stop focus on element when toggled manually + } + + //check conditions for autotext: + //if value was generated by text or value is empty, no sense to run autotext + doAutotext = !isValueByText && this.value !== null && this.value !== undefined; + doAutotext &= (this.options.autotext === 'always') || (this.options.autotext === 'auto' && !this.$element.text().length); + $.when(doAutotext ? this.render() : true).then($.proxy(function() { + if(this.options.disabled) { + this.disable(); + } else { + this.enable(); + } + /** + Fired when element was initialized by editable method. + + @event init + @param {Object} event event object + @param {Object} editable editable instance + @since 1.2.0 + **/ + this.$element.triggerHandler('init', this); + }, this)); + }, + + /* + Renders value into element's text. + Can call custom display method from options. + Can return deferred object. + @method render() + */ + render: function() { + //do not display anything + if(this.options.display === false) { + return; + } + //if it is input with source, we pass callback in third param to be called when source is loaded + if(this.input.options.hasOwnProperty('source')) { + return this.input.value2html(this.value, this.$element[0], this.options.display); + //if display method defined --> use it + } else if(typeof this.options.display === 'function') { + return this.options.display.call(this.$element[0], this.value); + //else use input's original value2html() method + } else { + return this.input.value2html(this.value, this.$element[0]); + } + }, + + /** + Enables editable + @method enable() + **/ + enable: function() { + this.options.disabled = false; + this.$element.removeClass('editable-disabled'); + this.handleEmpty(); + if(this.options.toggle !== 'manual') { + if(this.$element.attr('tabindex') === '-1') { + this.$element.removeAttr('tabindex'); + } + } + }, + + /** + Disables editable + @method disable() + **/ + disable: function() { + this.options.disabled = true; + this.hide(); + this.$element.addClass('editable-disabled'); + this.handleEmpty(); + //do not stop focus on this element + this.$element.attr('tabindex', -1); + }, + + /** + Toggles enabled / disabled state of editable element + @method toggleDisabled() + **/ + toggleDisabled: function() { + if(this.options.disabled) { + this.enable(); + } else { + this.disable(); + } + }, + + /** + Sets new option + + @method option(key, value) + @param {string|object} key option name or object with several options + @param {mixed} value option new value + @example + $('.editable').editable('option', 'pk', 2); + **/ + option: function(key, value) { + //set option(s) by object + if(key && typeof key === 'object') { + $.each(key, $.proxy(function(k, v){ + this.option($.trim(k), v); + }, this)); + return; + } + + //set option by string + this.options[key] = value; + + //disabled + if(key === 'disabled') { + if(value) { + this.disable(); + } else { + this.enable(); + } + return; + } + + //value + if(key === 'value') { + this.setValue(value); + } + + //transfer new option to container! + if(this.container) { + this.container.option(key, value); + } + }, + + /* + * set emptytext if element is empty (reverse: remove emptytext if needed) + */ + handleEmpty: function () { + //do not handle empty if we do not display anything + if(this.options.display === false) { + return; + } + + var emptyClass = 'editable-empty'; + //emptytext shown only for enabled + if(!this.options.disabled) { + if ($.trim(this.$element.text()) === '') { + this.$element.addClass(emptyClass).text(this.options.emptytext); + } else { + this.$element.removeClass(emptyClass); + } + } else { + //below required if element disable property was changed + if(this.$element.hasClass(emptyClass)) { + this.$element.empty(); + this.$element.removeClass(emptyClass); + } + } + }, + + /** + Shows container with form + @method show() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + show: function (closeAll) { + if(this.options.disabled) { + return; + } + + //init editableContainer: popover, tooltip, inline, etc.. + if(!this.container) { + var containerOptions = $.extend({}, this.options, { + value: this.value + }); + this.$element.editableContainer(containerOptions); + this.$element.on("save.internal", $.proxy(this.save, this)); + this.container = this.$element.data('editableContainer'); + } else if(this.container.tip().is(':visible')) { + return; + } + + //show container + this.container.show(closeAll); + }, + + /** + Hides container with form + @method hide() + **/ + hide: function () { + if(this.container) { + this.container.hide(); + } + }, + + /** + Toggles container visibility (show / hide) + @method toggle() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + toggle: function(closeAll) { + if(this.container && this.container.tip().is(':visible')) { + this.hide(); + } else { + this.show(closeAll); + } + }, + + /* + * called when form was submitted + */ + save: function(e, params) { + //if url is not user's function and value was not sent to server and value changed --> mark element with unsaved css. + if(typeof this.options.url !== 'function' && this.options.display !== false && params.response === undefined && this.input.value2str(this.value) !== this.input.value2str(params.newValue)) { + this.$element.addClass('editable-unsaved'); + } else { + this.$element.removeClass('editable-unsaved'); + } + + // this.hide(); + this.setValue(params.newValue); + + /** + Fired when new value was submitted. You can use <code>$(this).data('editable')</code> to access to editable instance + + @event save + @param {Object} event event object + @param {Object} params additional params + @param {mixed} params.newValue submitted value + @param {Object} params.response ajax response + @example + $('#username').on('save', function(e, params) { + //assuming server response: '{success: true}' + var pk = $(this).data('editable').options.pk; + if(params.response && params.response.success) { + alert('value: ' + params.newValue + ' with pk: ' + pk + ' saved!'); + } else { + alert('error!'); + } + }); + **/ + //event itself is triggered by editableContainer. Description here is only for documentation + }, + + validate: function () { + if (typeof this.options.validate === 'function') { + return this.options.validate.call(this, this.value); + } + }, + + /** + Sets new value of editable + @method setValue(value, convertStr) + @param {mixed} value new value + @param {boolean} convertStr whether to convert value from string to internal format + **/ + setValue: function(value, convertStr) { + if(convertStr) { + this.value = this.input.str2value(value); + } else { + this.value = value; + } + if(this.container) { + this.container.option('value', this.value); + } + $.when(this.render()) + .then($.proxy(function() { + this.handleEmpty(); + }, this)); + }, + + /** + Activates input of visible container (e.g. set focus) + @method activate() + **/ + activate: function() { + if(this.container) { + this.container.activate(); + } + } + }; + + /* EDITABLE PLUGIN DEFINITION + * ======================= */ + + /** + jQuery method to initialize editable element. + + @method $().editable(options) + @params {Object} options + @example + $('#username').editable({ + type: 'text', + url: '/post', + pk: 1 + }); + **/ + $.fn.editable = function (option) { + //special API methods returning non-jquery object + var result = {}, args = arguments, datakey = 'editable'; + switch (option) { + /** + Runs client-side validation for all matched editables + + @method validate() + @returns {Object} validation errors map + @example + $('#username, #fullname').editable('validate'); + // possible result: + { + username: "username is required", + fullname: "fullname should be minimum 3 letters length" + } + **/ + case 'validate': + this.each(function () { + var $this = $(this), data = $this.data(datakey), error; + if (data && (error = data.validate())) { + result[data.options.name] = error; + } + }); + return result; + + /** + Returns current values of editable elements. If value is <code>null</code> or <code>undefined</code> it will not be returned + @method getValue() + @returns {Object} object of element names and values + @example + $('#username, #fullname').editable('validate'); + // possible result: + { + username: "superuser", + fullname: "John" + } + **/ + case 'getValue': + this.each(function () { + var $this = $(this), data = $this.data(datakey); + if (data && data.value !== undefined && data.value !== null) { + result[data.options.name] = data.input.value2submit(data.value); + } + }); + return result; + + /** + This method collects values from several editable elements and submit them all to server. + Internally it runs client-side validation for all fields and submits only in case of success. + See <a href="#newrecord">creating new records</a> for details. + + @method submit(options) + @param {object} options + @param {object} options.url url to submit data + @param {object} options.data additional data to submit + @param {object} options.ajaxOptions additional ajax options + @param {function} options.error(obj) error handler + @param {function} options.success(obj,config) success handler + @returns {Object} jQuery object + **/ + case 'submit': //collects value, validate and submit to server for creating new record + var config = arguments[1] || {}, + $elems = this, + errors = this.editable('validate'), + values; + + if($.isEmptyObject(errors)) { + values = this.editable('getValue'); + if(config.data) { + $.extend(values, config.data); + } + + $.ajax($.extend({ + url: config.url, + data: values, + type: 'POST' + }, config.ajaxOptions)) + .success(function(response) { + //successful response 200 OK + if(typeof config.success === 'function') { + config.success.call($elems, response, config); + } + }) + .error(function(){ //ajax error + if(typeof config.error === 'function') { + config.error.apply($elems, arguments); + } + }); + } else { //client-side validation error + if(typeof config.error === 'function') { + config.error.call($elems, errors); + } + } + return this; + } + + //return jquery object + return this.each(function () { + var $this = $(this), + data = $this.data(datakey), + options = typeof option === 'object' && option; + + if (!data) { + $this.data(datakey, (data = new Editable(this, options))); + } + + if (typeof option === 'string') { //call method + data[option].apply(data, Array.prototype.slice.call(args, 1)); + } + }); + }; + + + $.fn.editable.defaults = { + /** + Type of input. Can be <code>text|textarea|select|date|checklist</code> and more + + @property type + @type string + @default 'text' + **/ + type: 'text', + /** + Sets disabled state of editable + + @property disabled + @type boolean + @default false + **/ + disabled: false, + /** + How to toggle editable. Can be <code>click|dblclick|mouseenter|manual</code>. + When set to <code>manual</code> you should manually call <code>show/hide</code> methods of editable. + **Note**: if you call <code>show</code> or <code>toggle</code> inside **click** handler of some DOM element, + you need to apply <code>e.stopPropagation()</code> because containers are being closed on any click on document. + + @example + $('#edit-button').click(function(e) { + e.stopPropagation(); + $('#username').editable('toggle'); + }); + + @property toggle + @type string + @default 'click' + **/ + toggle: 'click', + /** + Text shown when element is empty. + + @property emptytext + @type string + @default 'Empty' + **/ + emptytext: 'Empty', + /** + Allows to automatically set element's text based on it's value. Can be <code>auto|always|never</code>. Useful for select and date. + For example, if dropdown list is <code>{1: 'a', 2: 'b'}</code> and element's value set to <code>1</code>, it's html will be automatically set to <code>'a'</code>. + <code>auto</code> - text will be automatically set only if element is empty. + <code>always|never</code> - always(never) try to set element's text. + + @property autotext + @type string + @default 'auto' + **/ + autotext: 'auto', + /** + Initial value of input. Taken from <code>data-value</code> or element's text. + + @property value + @type mixed + @default element's text + **/ + value: null, + /** + Callback to perform custom displaying of value in element's text. + If <code>null</code>, default input's value2html() will be called. + If <code>false</code>, no displaying methods will be called, element's text will no change. + Runs under element's scope. + Second parameter __sourceData__ is passed for inputs with source (select, checklist). + + @property display + @type function|boolean + @default null + @since 1.2.0 + @example + display: function(value, sourceData) { + var escapedValue = $('<div>').text(value).html(); + $(this).html('<b>'+escapedValue+'</b>'); + } + **/ + display: null + }; + +}(window.jQuery)); + +/** +AbstractInput - base class for all editable inputs. +It defines interface to be implemented by any input type. +To create your own input you can inherit from this class. + +@class abstractinput +**/ +(function ($) { + + //types + $.fn.editabletypes = {}; + + var AbstractInput = function () { }; + + AbstractInput.prototype = { + /** + Initializes input + + @method init() + **/ + init: function(type, options, defaults) { + this.type = type; + this.options = $.extend({}, defaults, options); + this.$input = null; + this.$clear = null; + this.error = null; + }, + + /** + Renders input from tpl. Can return jQuery deferred object. + + @method render() + **/ + render: function() { + this.$input = $(this.options.tpl); + if(this.options.inputclass) { + this.$input.addClass(this.options.inputclass); + } + + if (this.options.placeholder) { + this.$input.attr('placeholder', this.options.placeholder); + } + }, + + /** + Sets element's html by value. + + @method value2html(value, element) + @param {mixed} value + @param {DOMElement} element + **/ + value2html: function(value, element) { + $(element).text(value); + }, + + /** + Converts element's html to value + + @method html2value(html) + @param {string} html + @returns {mixed} + **/ + html2value: function(html) { + return $('<div>').html(html).text(); + }, + + /** + Converts value to string (for internal compare). For submitting to server used value2submit(). + + @method value2str(value) + @param {mixed} value + @returns {string} + **/ + value2str: function(value) { + return value; + }, + + /** + Converts string received from server into value. + + @method str2value(str) + @param {string} str + @returns {mixed} + **/ + str2value: function(str) { + return str; + }, + + /** + Converts value for submitting to server + + @method value2submit(value) + @param {mixed} value + @returns {mixed} + **/ + value2submit: function(value) { + return value; + }, + + /** + Sets value of input. + + @method value2input(value) + @param {mixed} value + **/ + value2input: function(value) { + this.$input.val(value); + }, + + /** + Returns value of input. Value can be object (e.g. datepicker) + + @method input2value() + **/ + input2value: function() { + return this.$input.val(); + }, + + /** + Activates input. For text it sets focus. + + @method activate() + **/ + activate: function() { + if(this.$input.is(':visible')) { + this.$input.focus(); + } + }, + + /** + Creates input. + + @method clear() + **/ + clear: function() { + this.$input.val(null); + }, + + /** + method to escape html. + **/ + escape: function(str) { + return $('<div>').text(str).html(); + }, + + /** + attach handler to automatically submit form when value changed (useful when buttons not shown) + **/ + autosubmit: function() { + + } + }; + + AbstractInput.defaults = { + /** + HTML template of input. Normally you should not change it. + + @property tpl + @type string + @default '' + **/ + tpl: '', + /** + CSS class automatically applied to input + + @property inputclass + @type string + @default input-medium + **/ + inputclass: 'input-medium', + /** + Name attribute of input + + @property name + @type string + @default null + **/ + name: null + }; + + $.extend($.fn.editabletypes, {abstractinput: AbstractInput}); + +}(window.jQuery)); + +/** +List - abstract class for inputs that have source option loaded from js array or via ajax + +@class list +@extends abstractinput +**/ +(function ($) { + + var List = function (options) { + + }; + + $.fn.editableutils.inherit(List, $.fn.editabletypes.abstractinput); + + $.extend(List.prototype, { + render: function () { + List.superclass.render.call(this); + var deferred = $.Deferred(); + this.error = null; + this.sourceData = null; + this.prependData = null; + this.onSourceReady(function () { + this.renderList(); + deferred.resolve(); + }, function () { + this.error = this.options.sourceError; + deferred.resolve(); + }); + + return deferred.promise(); + }, + + html2value: function (html) { + return null; //can't set value by text + }, + + value2html: function (value, element, display) { + var deferred = $.Deferred(); + this.onSourceReady(function () { + if(typeof display === 'function') { + //custom display method + display.call(element, value, this.sourceData); + } else { + this.value2htmlFinal(value, element); + } + deferred.resolve(); + }, function () { + //do nothing with element + deferred.resolve(); + }); + + return deferred.promise(); + }, + + // ------------- additional functions ------------ + + onSourceReady: function (success, error) { + //if allready loaded just call success + if($.isArray(this.sourceData)) { + success.call(this); + return; + } + + // try parse json in single quotes (for double quotes jquery does automatically) + try { + this.options.source = $.fn.editableutils.tryParseJson(this.options.source, false); + } catch (e) { + error.call(this); + return; + } + + //loading from url + if (typeof this.options.source === 'string') { + //try to get from cache + if(this.options.sourceCache) { + var cacheID = this.options.source + (this.options.name ? '-' + this.options.name : ''), + cache; + + if (!$(document).data(cacheID)) { + $(document).data(cacheID, {}); + } + cache = $(document).data(cacheID); + + //check for cached data + if (cache.loading === false && cache.sourceData) { //take source from cache + this.sourceData = cache.sourceData; + success.call(this); + return; + } else if (cache.loading === true) { //cache is loading, put callback in stack to be called later + cache.callbacks.push($.proxy(function () { + this.sourceData = cache.sourceData; + success.call(this); + }, this)); + + //also collecting error callbacks + cache.err_callbacks.push($.proxy(error, this)); + return; + } else { //no cache yet, activate it + cache.loading = true; + cache.callbacks = []; + cache.err_callbacks = []; + } + } + + //loading sourceData from server + $.ajax({ + url: this.options.source, + type: 'get', + cache: false, + data: this.options.name ? {name: this.options.name} : {}, + dataType: 'json', + success: $.proxy(function (data) { + if(cache) { + cache.loading = false; + } + this.sourceData = this.makeArray(data); + if($.isArray(this.sourceData)) { + this.doPrepend(); + success.call(this); + if(cache) { + //store result in cache + cache.sourceData = this.sourceData; + $.each(cache.callbacks, function () { this.call(); }); //run success callbacks for other fields + } + } else { + error.call(this); + if(cache) { + $.each(cache.err_callbacks, function () { this.call(); }); //run error callbacks for other fields + } + } + }, this), + error: $.proxy(function () { + error.call(this); + if(cache) { + cache.loading = false; + //run error callbacks for other fields + $.each(cache.err_callbacks, function () { this.call(); }); + } + }, this) + }); + } else { //options as json/array + this.sourceData = this.makeArray(this.options.source); + if($.isArray(this.sourceData)) { + this.doPrepend(); + success.call(this); + } else { + error.call(this); + } + } + }, + + doPrepend: function () { + if(this.options.prepend === null || this.options.prepend === undefined) { + return; + } + + if(!$.isArray(this.prependData)) { + //try parse json in single quotes + this.options.prepend = $.fn.editableutils.tryParseJson(this.options.prepend, true); + if (typeof this.options.prepend === 'string') { + this.options.prepend = {'': this.options.prepend}; + } + this.prependData = this.makeArray(this.options.prepend); + } + + if($.isArray(this.prependData) && $.isArray(this.sourceData)) { + this.sourceData = this.prependData.concat(this.sourceData); + } + }, + + /* + renders input list + */ + renderList: function() { + // this method should be overwritten in child class + }, + + /* + set element's html by value + */ + value2htmlFinal: function(value, element) { + // this method should be overwritten in child class + }, + + /** + * convert data to array suitable for sourceData, e.g. [{value: 1, text: 'abc'}, {...}] + */ + makeArray: function(data) { + var count, obj, result = [], iterateEl; + if(!data || typeof data === 'string') { + return null; + } + + if($.isArray(data)) { //array + iterateEl = function (k, v) { + obj = {value: k, text: v}; + if(count++ >= 2) { + return false;// exit each if object has more than one value + } + }; + + for(var i = 0; i < data.length; i++) { + if(typeof data[i] === 'object') { + count = 0; + $.each(data[i], iterateEl); + if(count === 1) { + result.push(obj); + } else if(count > 1 && data[i].hasOwnProperty('value') && data[i].hasOwnProperty('text')) { + result.push(data[i]); + } else { + //data contains incorrect objects + } + } else { + result.push({value: data[i], text: data[i]}); + } + } + } else { //object + $.each(data, function (k, v) { + result.push({value: k, text: v}); + }); + } + return result; + }, + + //search for item by particular value + itemByVal: function(val) { + if($.isArray(this.sourceData)) { + for(var i=0; i<this.sourceData.length; i++){ + /*jshint eqeqeq: false*/ + if(this.sourceData[i].value == val) { + /*jshint eqeqeq: true*/ + return this.sourceData[i]; + } + } + } + } + + }); + + List.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + Source data for list. If string - considered ajax url to load items. Otherwise should be an array. + Array format is: <code>[{value: 1, text: "text"}, {...}]</code><br> + For compability it also supports format <code>{value1: "text1", value2: "text2" ...}</code> but it does not guarantee elements order. + If source is **string**, results will be cached for fields with the same source and name. See also <code>sourceCache</code> option. + + @property source + @type string|array|object + @default null + **/ + source:null, + /** + Data automatically prepended to the beginning of dropdown list. + + @property prepend + @type string|array|object + @default false + **/ + prepend:false, + /** + Error message when list cannot be loaded (e.g. ajax error) + + @property sourceError + @type string + @default Error when loading list + **/ + sourceError: 'Error when loading list', + /** + if <code>true</code> and source is **string url** - results will be cached for fields with the same source and name. + Usefull for editable grids. + + @property sourceCache + @type boolean + @default true + @since 1.2.0 + **/ + sourceCache: true + }); + + $.fn.editabletypes.list = List; + +}(window.jQuery)); +/** +Text input + +@class text +@extends abstractinput +@final +@example +<a href="#" id="username" data-type="text" data-pk="1">awesome</a> +<script> +$(function(){ + $('#username').editable({ + url: '/post', + title: 'Enter username' + }); +}); +</script> +**/ +(function ($) { + var Text = function (options) { + this.init('text', options, Text.defaults); + }; + + $.fn.editableutils.inherit(Text, $.fn.editabletypes.abstractinput); + + $.extend(Text.prototype, { + activate: function() { + if(this.$input.is(':visible')) { + this.$input.focus(); + $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length); + } + } + }); + + Text.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <input type="text"> + **/ + tpl: '<input type="text">', + /** + Placeholder attribute of input. Shown when input is empty. + + @property placeholder + @type string + @default null + **/ + placeholder: null + }); + + $.fn.editabletypes.text = Text; + +}(window.jQuery)); + +/** +Textarea input + +@class textarea +@extends abstractinput +@final +@example +<a href="#" id="comments" data-type="textarea" data-pk="1">awesome comment!</a> +<script> +$(function(){ + $('#comments').editable({ + url: '/post', + title: 'Enter comments' + }); +}); +</script> +**/ +(function ($) { + + var Textarea = function (options) { + this.init('textarea', options, Textarea.defaults); + }; + + $.fn.editableutils.inherit(Textarea, $.fn.editabletypes.abstractinput); + + $.extend(Textarea.prototype, { + render: function () { + Textarea.superclass.render.call(this); + + //ctrl + enter + this.$input.keydown(function (e) { + if (e.ctrlKey && e.which === 13) { + $(this).closest('form').submit(); + } + }); + }, + + value2html: function(value, element) { + var html = '', lines; + if(value) { + lines = value.split("\n"); + for (var i = 0; i < lines.length; i++) { + lines[i] = $('<div>').text(lines[i]).html(); + } + html = lines.join('<br>'); + } + $(element).html(html); + }, + + html2value: function(html) { + if(!html) { + return ''; + } + var lines = html.split(/<br\s*\/?>/i); + for (var i = 0; i < lines.length; i++) { + lines[i] = $('<div>').html(lines[i]).text(); + } + return lines.join("\n"); + }, + + activate: function() { + if(this.$input.is(':visible')) { + $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length); + this.$input.focus(); + } + } + }); + + Textarea.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <textarea></textarea> + **/ + tpl:'<textarea></textarea>', + /** + @property inputclass + @default input-large + **/ + inputclass: 'input-large', + /** + Placeholder attribute of input. Shown when input is empty. + + @property placeholder + @type string + @default null + **/ + placeholder: null + }); + + $.fn.editabletypes.textarea = Textarea; + +}(window.jQuery)); + +/** +Select (dropdown) + +@class select +@extends list +@final +@example +<a href="#" id="status" data-type="select" data-pk="1" data-url="/post" data-original-title="Select status"></a> +<script> +$(function(){ + $('#status').editable({ + value: 2, + source: [ + {value: 1, text: 'Active'}, + {value: 2, text: 'Blocked'}, + {value: 3, text: 'Deleted'} + ] + } + }); +}); +</script> +**/ +(function ($) { + + var Select = function (options) { + this.init('select', options, Select.defaults); + }; + + $.fn.editableutils.inherit(Select, $.fn.editabletypes.list); + + $.extend(Select.prototype, { + renderList: function() { + if(!$.isArray(this.sourceData)) { + return; + } + + for(var i=0; i<this.sourceData.length; i++) { + this.$input.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text)); + } + + //enter submit + this.$input.on('keydown.editable', function (e) { + if (e.which === 13) { + $(this).closest('form').submit(); + } + }); + }, + + value2htmlFinal: function(value, element) { + var text = '', item = this.itemByVal(value); + if(item) { + text = item.text; + } + Select.superclass.constructor.superclass.value2html(text, element); + }, + + autosubmit: function() { + this.$input.off('keydown.editable').on('change.editable', function(){ + $(this).closest('form').submit(); + }); + } + }); + + Select.defaults = $.extend({}, $.fn.editabletypes.list.defaults, { + /** + @property tpl + @default <select></select> + **/ + tpl:'<select></select>' + }); + + $.fn.editabletypes.select = Select; + +}(window.jQuery)); +/** +List of checkboxes. +Internally value stored as javascript array of values. + +@class checklist +@extends list +@final +@example +<a href="#" id="options" data-type="checklist" data-pk="1" data-url="/post" data-original-title="Select options"></a> +<script> +$(function(){ + $('#options').editable({ + value: [2, 3], + source: [ + {value: 1, text: 'option1'}, + {value: 2, text: 'option2'}, + {value: 3, text: 'option3'} + ] + } + }); +}); +</script> +**/ +(function ($) { + + var Checklist = function (options) { + this.init('checklist', options, Checklist.defaults); + }; + + $.fn.editableutils.inherit(Checklist, $.fn.editabletypes.list); + + $.extend(Checklist.prototype, { + renderList: function() { + var $label, $div; + if(!$.isArray(this.sourceData)) { + return; + } + + for(var i=0; i<this.sourceData.length; i++) { + $label = $('<label>').append($('<input>', { + type: 'checkbox', + value: this.sourceData[i].value, + name: this.options.name + })) + .append($('<span>').text(' '+this.sourceData[i].text)); + + $('<div>').append($label).appendTo(this.$input); + } + }, + + value2str: function(value) { + return $.isArray(value) ? value.sort().join($.trim(this.options.separator)) : ''; + }, + + //parse separated string + str2value: function(str) { + var reg, value = null; + if(typeof str === 'string' && str.length) { + reg = new RegExp('\\s*'+$.trim(this.options.separator)+'\\s*'); + value = str.split(reg); + } else if($.isArray(str)) { + value = str; + } + return value; + }, + + //set checked on required checkboxes + value2input: function(value) { + var $checks = this.$input.find('input[type="checkbox"]'); + $checks.removeAttr('checked'); + if($.isArray(value) && value.length) { + $checks.each(function(i, el) { + var $el = $(el); + // cannot use $.inArray as it performs strict comparison + $.each(value, function(j, val){ + /*jslint eqeq: true*/ + if($el.val() == val) { + /*jslint eqeq: false*/ + $el.attr('checked', 'checked'); + } + }); + }); + } + }, + + input2value: function() { + var checked = []; + this.$input.find('input:checked').each(function(i, el) { + checked.push($(el).val()); + }); + return checked; + }, + + //collect text of checked boxes + value2htmlFinal: function(value, element) { + var html = [], + /*jslint eqeq: true*/ + checked = $.grep(this.sourceData, function(o){ + return $.grep(value, function(v){ return v == o.value; }).length; + }); + /*jslint eqeq: false*/ + if(checked.length) { + $.each(checked, function(i, v) { html.push($.fn.editableutils.escape(v.text)); }); + $(element).html(html.join('<br>')); + } else { + $(element).empty(); + } + }, + + activate: function() { + this.$input.find('input[type="checkbox"]').first().focus(); + }, + + autosubmit: function() { + this.$input.find('input[type="checkbox"]').on('keydown', function(e){ + if (e.which === 13) { + $(this).closest('form').submit(); + } + }); + } + }); + + Checklist.defaults = $.extend({}, $.fn.editabletypes.list.defaults, { + /** + @property tpl + @default <div></div> + **/ + tpl:'<div></div>', + + /** + @property inputclass + @type string + @default editable-checklist + **/ + inputclass: 'editable-checklist', + + /** + Separator of values when reading from 'data-value' string + + @property separator + @type string + @default ', ' + **/ + separator: ',' + }); + + $.fn.editabletypes.checklist = Checklist; + +}(window.jQuery)); + +/** +HTML5 input types. +Following types are supported: + +* password +* email +* url +* tel +* number +* range + +Learn more about html5 inputs: +http://www.w3.org/wiki/HTML5_form_additions +To check browser compatibility please see: +https://developer.mozilla.org/en-US/docs/HTML/Element/Input + +@class html5types +@extends text +@final +@since 1.3.0 +@example +<a href="#" id="email" data-type="email" data-pk="1">admin@example.com</a> +<script> +$(function(){ + $('#email').editable({ + url: '/post', + title: 'Enter email' + }); +}); +</script> +**/ + +/** +@property tpl +@default depends on type +**/ + +/* +Password +*/ +(function ($) { + var Password = function (options) { + this.init('password', options, Password.defaults); + }; + $.fn.editableutils.inherit(Password, $.fn.editabletypes.text); + $.extend(Password.prototype, { + //do not display password, show '[hidden]' instead + value2html: function(value, element) { + if(value) { + $(element).text('[hidden]'); + } else { + $(element).empty(); + } + }, + //as password not displayed, should not set value by html + html2value: function(html) { + return null; + } + }); + Password.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="password">' + }); + $.fn.editabletypes.password = Password; +}(window.jQuery)); + + +/* +Email +*/ +(function ($) { + var Email = function (options) { + this.init('email', options, Email.defaults); + }; + $.fn.editableutils.inherit(Email, $.fn.editabletypes.text); + Email.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="email">' + }); + $.fn.editabletypes.email = Email; +}(window.jQuery)); + + +/* +Url +*/ +(function ($) { + var Url = function (options) { + this.init('url', options, Url.defaults); + }; + $.fn.editableutils.inherit(Url, $.fn.editabletypes.text); + Url.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="url">' + }); + $.fn.editabletypes.url = Url; +}(window.jQuery)); + + +/* +Tel +*/ +(function ($) { + var Tel = function (options) { + this.init('tel', options, Tel.defaults); + }; + $.fn.editableutils.inherit(Tel, $.fn.editabletypes.text); + Tel.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="tel">' + }); + $.fn.editabletypes.tel = Tel; +}(window.jQuery)); + + +/* +Number +*/ +(function ($) { + var NumberInput = function (options) { + this.init('number', options, NumberInput.defaults); + }; + $.fn.editableutils.inherit(NumberInput, $.fn.editabletypes.text); + $.extend(NumberInput.prototype, { + render: function () { + NumberInput.superclass.render.call(this); + + if (this.options.min !== null) { + this.$input.attr('min', this.options.min); + } + + if (this.options.max !== null) { + this.$input.attr('max', this.options.max); + } + + if (this.options.step !== null) { + this.$input.attr('step', this.options.step); + } + } + }); + NumberInput.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="number">', + inputclass: 'input-mini', + min: null, + max: null, + step: null + }); + $.fn.editabletypes.number = NumberInput; +}(window.jQuery)); + + +/* +Range (inherit from number) +*/ +(function ($) { + var Range = function (options) { + this.init('range', options, Range.defaults); + }; + $.fn.editableutils.inherit(Range, $.fn.editabletypes.number); + $.extend(Range.prototype, { + render: function () { + this.$input = $(this.options.tpl); + var $slider = this.$input.filter('input'); + if(this.options.inputclass) { + $slider.addClass(this.options.inputclass); + } + if (this.options.min !== null) { + $slider.attr('min', this.options.min); + } + + if (this.options.max !== null) { + $slider.attr('max', this.options.max); + } + + if (this.options.step !== null) { + $slider.attr('step', this.options.step); + } + + $slider.on('input', function(){ + $(this).siblings('output').text($(this).val()); + }); + }, + activate: function() { + this.$input.filter('input').focus(); + } + }); + Range.defaults = $.extend({}, $.fn.editabletypes.number.defaults, { + tpl: '<input type="range"><output style="width: 30px; display: inline-block"></output>', + inputclass: 'input-medium' + }); + $.fn.editabletypes.range = Range; +}(window.jQuery)); +/* +Editableform based on Twitter Bootstrap +*/ +(function ($) { + + $.extend($.fn.editableform.Constructor.prototype, { + initTemplate: function() { + this.$form = $($.fn.editableform.template); + this.$form.find('.editable-error-block').addClass('help-block'); + } + }); + + //buttons + $.fn.editableform.buttons = '<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button>'+ + '<button type="button" class="btn editable-cancel"><i class="icon-remove"></i></button>'; + + //error classes + $.fn.editableform.errorGroupClass = 'error'; + $.fn.editableform.errorBlockClass = null; + +}(window.jQuery)); +/** +* Editable Inline +* --------------------- +*/ +(function ($) { + + //extend methods + $.extend($.fn.editableContainer.Constructor.prototype, { + containerName: 'editableform', + innerCss: null, + + initContainer: function(){ + //no init for container + //only convert anim to miliseconds (int) + if(!this.options.anim) { + this.options.anim = 0; + } + }, + + splitOptions: function() { + this.containerOptions = {}; + this.formOptions = this.options; + }, + + tip: function() { + return this.$form; + }, + + innerShow: function () { + this.$element.hide(); + + if(this.$form) { + this.$form.remove(); + } + + this.initForm(); + this.tip().addClass('editable-container').addClass('editable-inline'); + this.$form.insertAfter(this.$element); + this.$form.show(this.options.anim); + this.$form.editableform('render'); + }, + + innerHide: function () { + this.$form.hide(this.options.anim, $.proxy(function() { + this.$element.show(); + }, this)); + }, + + destroy: function() { + this.tip().remove(); + } + }); + + //defaults + $.fn.editableContainer.defaults = $.extend({}, $.fn.editableContainer.defaults, { + anim: 'fast' + }); + + +}(window.jQuery)); +/** +Bootstrap-datepicker. +Description and examples: http://vitalets.github.com/bootstrap-datepicker. +For localization you can include js file from here: https://github.com/eternicode/bootstrap-datepicker/tree/master/js/locales + +@class date +@extends abstractinput +@final +@example +<a href="#" id="dob" data-type="date" data-pk="1" data-url="/post" data-original-title="Select date">15/05/1984</a> +<script> +$(function(){ + $('#dob').editable({ + format: 'yyyy-mm-dd', + viewformat: 'dd/mm/yyyy', + datepicker: { + weekStart: 1 + } + } + }); +}); +</script> +**/ +(function ($) { + + var Date = function (options) { + this.init('date', options, Date.defaults); + + //set popular options directly from settings or data-* attributes + var directOptions = $.fn.editableutils.sliceObj(this.options, ['format']); + + //overriding datepicker config (as by default jQuery extend() is not recursive) + this.options.datepicker = $.extend({}, Date.defaults.datepicker, directOptions, options.datepicker); + + //by default viewformat equals to format + if(!this.options.viewformat) { + this.options.viewformat = this.options.datepicker.format; + } + + //language + this.options.datepicker.language = this.options.datepicker.language || 'en'; + + //store DPglobal + this.dpg = $.fn.datepicker.DPGlobal; + + //store parsed formats + this.parsedFormat = this.dpg.parseFormat(this.options.datepicker.format); + this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat); + }; + + $.fn.editableutils.inherit(Date, $.fn.editabletypes.abstractinput); + + $.extend(Date.prototype, { + render: function () { + Date.superclass.render.call(this); + this.$input.datepicker(this.options.datepicker); + + if(this.options.clear) { + this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){ + e.preventDefault(); + e.stopPropagation(); + this.clear(); + }, this)); + } + }, + + value2html: function(value, element) { + var text = value ? this.dpg.formatDate(value, this.parsedViewFormat, this.options.datepicker.language) : ''; + Date.superclass.value2html(text, element); + }, + + html2value: function(html) { + return html ? this.dpg.parseDate(html, this.parsedViewFormat, this.options.datepicker.language) : null; + }, + + value2str: function(value) { + return value ? this.dpg.formatDate(value, this.parsedFormat, this.options.datepicker.language) : ''; + }, + + str2value: function(str) { + return str ? this.dpg.parseDate(str, this.parsedFormat, this.options.datepicker.language) : null; + }, + + value2submit: function(value) { + return this.value2str(value); + }, + + value2input: function(value) { + this.$input.datepicker('update', value); + }, + + input2value: function() { + return this.$input.data('datepicker').date; + }, + + activate: function() { + }, + + clear: function() { + this.$input.data('datepicker').date = null; + this.$input.find('.active').removeClass('active'); + }, + + autosubmit: function() { + this.$input.on('changeDate', function(e){ + var $form = $(this).closest('form'); + setTimeout(function() { + $form.submit(); + }, 200); + }); + } + + }); + + Date.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <div></div> + **/ + tpl:'<div></div>', + /** + @property inputclass + @default editable-date well + **/ + inputclass: 'editable-date well', + /** + Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br> + Possible tokens are: <code>d, dd, m, mm, yy, yyyy</code> + + @property format + @type string + @default yyyy-mm-dd + **/ + format:'yyyy-mm-dd', + /** + Format used for displaying date. Also applied when converting date from element's text on init. + If not specified equals to <code>format</code> + + @property viewformat + @type string + @default null + **/ + viewformat: null, + /** + Configuration of datepicker. + Full list of options: http://vitalets.github.com/bootstrap-datepicker + + @property datepicker + @type object + @default { + weekStart: 0, + startView: 0, + autoclose: false + } + **/ + datepicker:{ + weekStart: 0, + startView: 0, + autoclose: false + }, + /** + Text shown as clear date button. + If <code>false</code> clear button will not be rendered. + + @property clear + @type boolean|string + @default 'x clear' + **/ + clear: '&times; clear' + }); + + $.fn.editabletypes.date = Date; + +}(window.jQuery)); + +/* ========================================================= + * bootstrap-datepicker.js + * http://www.eyecon.ro/bootstrap-datepicker + * ========================================================= + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * + * 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( $ ) { + + function UTCDate(){ + return new Date(Date.UTC.apply(Date, arguments)); + } + function UTCToday(){ + var today = new Date(); + return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate()); + } + + // Picker object + + var Datepicker = function(element, options) { + var that = this; + + this.element = $(element); + this.language = options.language||this.element.data('date-language')||"en"; + this.language = this.language in dates ? this.language : "en"; + this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy'); + this.isInline = false; + this.isInput = this.element.is('input'); + this.component = this.element.is('.date') ? this.element.find('.add-on') : false; + this.hasInput = this.component && this.element.find('input').length; + if(this.component && this.component.length === 0) + this.component = false; + + if (this.isInput) { //single input + this.element.on({ + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }); + } else if(this.component && this.hasInput) { //component: input + button + // For components that are not readonly, allow keyboard nav + this.element.find('input').on({ + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }); + + this.component.on('click', $.proxy(this.show, this)); + } else if(this.element.is('div')) { //inline datepicker + this.isInline = true; + } else { + this.element.on('click', $.proxy(this.show, this)); + } + + this.picker = $(DPGlobal.template) + .appendTo(this.isInline ? this.element : 'body') + .on({ + click: $.proxy(this.click, this), + mousedown: $.proxy(this.mousedown, this) + }); + + if(this.isInline) { + this.picker.addClass('datepicker-inline'); + } else { + this.picker.addClass('dropdown-menu'); + } + + $(document).on('mousedown', function (e) { + // Clicked outside the datepicker, hide it + if ($(e.target).closest('.datepicker').length == 0) { + that.hide(); + } + }); + + this.autoclose = false; + if ('autoclose' in options) { + this.autoclose = options.autoclose; + } else if ('dateAutoclose' in this.element.data()) { + this.autoclose = this.element.data('date-autoclose'); + } + + this.keyboardNavigation = true; + if ('keyboardNavigation' in options) { + this.keyboardNavigation = options.keyboardNavigation; + } else if ('dateKeyboardNavigation' in this.element.data()) { + this.keyboardNavigation = this.element.data('date-keyboard-navigation'); + } + + switch(options.startView || this.element.data('date-start-view')){ + case 2: + case 'decade': + this.viewMode = this.startViewMode = 2; + break; + case 1: + case 'year': + this.viewMode = this.startViewMode = 1; + break; + case 0: + case 'month': + default: + this.viewMode = this.startViewMode = 0; + break; + } + + this.todayBtn = (options.todayBtn||this.element.data('date-today-btn')||false); + this.todayHighlight = (options.todayHighlight||this.element.data('date-today-highlight')||false); + + this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7); + this.weekEnd = ((this.weekStart + 6) % 7); + this.startDate = -Infinity; + this.endDate = Infinity; + this.setStartDate(options.startDate||this.element.data('date-startdate')); + this.setEndDate(options.endDate||this.element.data('date-enddate')); + this.fillDow(); + this.fillMonths(); + this.update(); + this.showMode(); + + if(this.isInline) { + this.show(); + } + }; + + Datepicker.prototype = { + constructor: Datepicker, + + show: function(e) { + this.picker.show(); + this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); + this.update(); + this.place(); + $(window).on('resize', $.proxy(this.place, this)); + if (e ) { + e.stopPropagation(); + e.preventDefault(); + } + this.element.trigger({ + type: 'show', + date: this.date + }); + }, + + hide: function(e){ + if(this.isInline) return; + this.picker.hide(); + $(window).off('resize', this.place); + this.viewMode = this.startViewMode; + this.showMode(); + if (!this.isInput) { + $(document).off('mousedown', this.hide); + } + if (e && e.currentTarget.value) + this.setValue(); + this.element.trigger({ + type: 'hide', + date: this.date + }); + }, + + getDate: function() { + var d = this.getUTCDate(); + return new Date(d.getTime() + (d.getTimezoneOffset()*60000)) + }, + + getUTCDate: function() { + return this.date; + }, + + setDate: function(d) { + this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000))); + }, + + setUTCDate: function(d) { + this.date = d; + this.setValue(); + }, + + setValue: function() { + var formatted = this.getFormattedDate(); + if (!this.isInput) { + if (this.component){ + this.element.find('input').prop('value', formatted); + } + this.element.data('date', formatted); + } else { + this.element.prop('value', formatted); + } + }, + + getFormattedDate: function(format) { + if(format == undefined) format = this.format; + return DPGlobal.formatDate(this.date, format, this.language); + }, + + setStartDate: function(startDate){ + this.startDate = startDate||-Infinity; + if (this.startDate !== -Infinity) { + this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language); + } + this.update(); + this.updateNavArrows(); + }, + + setEndDate: function(endDate){ + this.endDate = endDate||Infinity; + if (this.endDate !== Infinity) { + this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language); + } + this.update(); + this.updateNavArrows(); + }, + + place: function(){ + if(this.isInline) return; + var zIndex = parseInt(this.element.parents().filter(function() { + return $(this).css('z-index') != 'auto'; + }).first().css('z-index'))+10; + var offset = this.component ? this.component.offset() : this.element.offset(); + this.picker.css({ + top: offset.top + this.height, + left: offset.left, + zIndex: zIndex + }); + }, + + update: function(){ + var date, fromArgs = false; + if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) { + date = arguments[0]; + fromArgs = true; + } else { + date = this.isInput ? this.element.prop('value') : this.element.data('date') || this.element.find('input').prop('value'); + } + + this.date = DPGlobal.parseDate(date, this.format, this.language); + + if(fromArgs) this.setValue(); + + if (this.date < this.startDate) { + this.viewDate = new Date(this.startDate); + } else if (this.date > this.endDate) { + this.viewDate = new Date(this.endDate); + } else { + this.viewDate = new Date(this.date); + } + this.fill(); + }, + + fillDow: function(){ + var dowCnt = this.weekStart; + var html = '<tr>'; + while (dowCnt < this.weekStart + 7) { + html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>'; + } + html += '</tr>'; + this.picker.find('.datepicker-days thead').append(html); + }, + + fillMonths: function(){ + var html = ''; + var i = 0 + while (i < 12) { + html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>'; + } + this.picker.find('.datepicker-months td').html(html); + }, + + fill: function() { + var d = new Date(this.viewDate), + year = d.getUTCFullYear(), + month = d.getUTCMonth(), + startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity, + startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity, + endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity, + endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity, + currentDate = this.date && this.date.valueOf(), + today = new Date(); + this.picker.find('.datepicker-days thead th:eq(1)') + .text(dates[this.language].months[month]+' '+year); + this.picker.find('tfoot th.today') + .text(dates[this.language].today) + .toggle(this.todayBtn !== false); + this.updateNavArrows(); + this.fillMonths(); + var prevMonth = UTCDate(year, month-1, 28,0,0,0,0), + day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); + prevMonth.setUTCDate(day); + prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7); + var nextMonth = new Date(prevMonth); + nextMonth.setUTCDate(nextMonth.getUTCDate() + 42); + nextMonth = nextMonth.valueOf(); + var html = []; + var clsName; + while(prevMonth.valueOf() < nextMonth) { + if (prevMonth.getUTCDay() == this.weekStart) { + html.push('<tr>'); + } + clsName = ''; + if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) { + clsName += ' old'; + } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) { + clsName += ' new'; + } + // Compare internal UTC date with local today, not UTC today + if (this.todayHighlight && + prevMonth.getUTCFullYear() == today.getFullYear() && + prevMonth.getUTCMonth() == today.getMonth() && + prevMonth.getUTCDate() == today.getDate()) { + clsName += ' today'; + } + if (currentDate && prevMonth.valueOf() == currentDate) { + clsName += ' active'; + } + if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate) { + clsName += ' disabled'; + } + html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>'); + if (prevMonth.getUTCDay() == this.weekEnd) { + html.push('</tr>'); + } + prevMonth.setUTCDate(prevMonth.getUTCDate()+1); + } + this.picker.find('.datepicker-days tbody').empty().append(html.join('')); + var currentYear = this.date && this.date.getUTCFullYear(); + + var months = this.picker.find('.datepicker-months') + .find('th:eq(1)') + .text(year) + .end() + .find('span').removeClass('active'); + if (currentYear && currentYear == year) { + months.eq(this.date.getUTCMonth()).addClass('active'); + } + if (year < startYear || year > endYear) { + months.addClass('disabled'); + } + if (year == startYear) { + months.slice(0, startMonth).addClass('disabled'); + } + if (year == endYear) { + months.slice(endMonth+1).addClass('disabled'); + } + + html = ''; + year = parseInt(year/10, 10) * 10; + var yearCont = this.picker.find('.datepicker-years') + .find('th:eq(1)') + .text(year + '-' + (year + 9)) + .end() + .find('td'); + year -= 1; + for (var i = -1; i < 11; i++) { + html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>'; + year += 1; + } + yearCont.html(html); + }, + + updateNavArrows: function() { + var d = new Date(this.viewDate), + year = d.getUTCFullYear(), + month = d.getUTCMonth(); + switch (this.viewMode) { + case 0: + if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + case 1: + case 2: + if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + } + }, + + click: function(e) { + e.stopPropagation(); + e.preventDefault(); + var target = $(e.target).closest('span, td, th'); + if (target.length == 1) { + switch(target[0].nodeName.toLowerCase()) { + case 'th': + switch(target[0].className) { + case 'switch': + this.showMode(1); + break; + case 'prev': + case 'next': + var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1); + switch(this.viewMode){ + case 0: + this.viewDate = this.moveMonth(this.viewDate, dir); + break; + case 1: + case 2: + this.viewDate = this.moveYear(this.viewDate, dir); + break; + } + this.fill(); + break; + case 'today': + var date = new Date(); + date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); + + this.showMode(-2); + var which = this.todayBtn == 'linked' ? null : 'view'; + this._setDate(date, which); + break; + } + break; + case 'span': + if (!target.is('.disabled')) { + this.viewDate.setUTCDate(1); + if (target.is('.month')) { + var month = target.parent().find('span').index(target); + this.viewDate.setUTCMonth(month); + this.element.trigger({ + type: 'changeMonth', + date: this.viewDate + }); + } else { + var year = parseInt(target.text(), 10)||0; + this.viewDate.setUTCFullYear(year); + this.element.trigger({ + type: 'changeYear', + date: this.viewDate + }); + } + this.showMode(-1); + this.fill(); + } + break; + case 'td': + if (target.is('.day') && !target.is('.disabled')){ + var day = parseInt(target.text(), 10)||1; + var year = this.viewDate.getUTCFullYear(), + month = this.viewDate.getUTCMonth(); + if (target.is('.old')) { + if (month == 0) { + month = 11; + year -= 1; + } else { + month -= 1; + } + } else if (target.is('.new')) { + if (month == 11) { + month = 0; + year += 1; + } else { + month += 1; + } + } + this._setDate(UTCDate(year, month, day,0,0,0,0)); + } + break; + } + } + }, + + _setDate: function(date, which){ + if (!which || which == 'date') + this.date = date; + if (!which || which == 'view') + this.viewDate = date; + this.fill(); + this.setValue(); + this.element.trigger({ + type: 'changeDate', + date: this.date + }); + var element; + if (this.isInput) { + element = this.element; + } else if (this.component){ + element = this.element.find('input'); + } + if (element) { + element.change(); + if (this.autoclose) { + this.hide(); + } + } + }, + + moveMonth: function(date, dir){ + if (!dir) return date; + var new_date = new Date(date.valueOf()), + day = new_date.getUTCDate(), + month = new_date.getUTCMonth(), + mag = Math.abs(dir), + new_month, test; + dir = dir > 0 ? 1 : -1; + if (mag == 1){ + test = dir == -1 + // If going back one month, make sure month is not current month + // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02) + ? function(){ return new_date.getUTCMonth() == month; } + // If going forward one month, make sure month is as expected + // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02) + : function(){ return new_date.getUTCMonth() != new_month; }; + new_month = month + dir; + new_date.setUTCMonth(new_month); + // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11 + if (new_month < 0 || new_month > 11) + new_month = (new_month + 12) % 12; + } else { + // For magnitudes >1, move one month at a time... + for (var i=0; i<mag; i++) + // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)... + new_date = this.moveMonth(new_date, dir); + // ...then reset the day, keeping it in the new month + new_month = new_date.getUTCMonth(); + new_date.setUTCDate(day); + test = function(){ return new_month != new_date.getUTCMonth(); }; + } + // Common date-resetting loop -- if date is beyond end of month, make it + // end of month + while (test()){ + new_date.setUTCDate(--day); + new_date.setUTCMonth(new_month); + } + return new_date; + }, + + moveYear: function(date, dir){ + return this.moveMonth(date, dir*12); + }, + + dateWithinRange: function(date){ + return date >= this.startDate && date <= this.endDate; + }, + + keydown: function(e){ + if (this.picker.is(':not(:visible)')){ + if (e.keyCode == 27) // allow escape to hide and re-show picker + this.show(); + return; + } + var dateChanged = false, + dir, day, month, + newDate, newViewDate; + switch(e.keyCode){ + case 27: // escape + this.hide(); + e.preventDefault(); + break; + case 37: // left + case 39: // right + if (!this.keyboardNavigation) break; + dir = e.keyCode == 37 ? -1 : 1; + if (e.ctrlKey){ + newDate = this.moveYear(this.date, dir); + newViewDate = this.moveYear(this.viewDate, dir); + } else if (e.shiftKey){ + newDate = this.moveMonth(this.date, dir); + newViewDate = this.moveMonth(this.viewDate, dir); + } else { + newDate = new Date(this.date); + newDate.setUTCDate(this.date.getUTCDate() + dir); + newViewDate = new Date(this.viewDate); + newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir); + } + if (this.dateWithinRange(newDate)){ + this.date = newDate; + this.viewDate = newViewDate; + this.setValue(); + this.update(); + e.preventDefault(); + dateChanged = true; + } + break; + case 38: // up + case 40: // down + if (!this.keyboardNavigation) break; + dir = e.keyCode == 38 ? -1 : 1; + if (e.ctrlKey){ + newDate = this.moveYear(this.date, dir); + newViewDate = this.moveYear(this.viewDate, dir); + } else if (e.shiftKey){ + newDate = this.moveMonth(this.date, dir); + newViewDate = this.moveMonth(this.viewDate, dir); + } else { + newDate = new Date(this.date); + newDate.setUTCDate(this.date.getUTCDate() + dir * 7); + newViewDate = new Date(this.viewDate); + newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7); + } + if (this.dateWithinRange(newDate)){ + this.date = newDate; + this.viewDate = newViewDate; + this.setValue(); + this.update(); + e.preventDefault(); + dateChanged = true; + } + break; + case 13: // enter + this.hide(); + e.preventDefault(); + break; + case 9: // tab + this.hide(); + break; + } + if (dateChanged){ + this.element.trigger({ + type: 'changeDate', + date: this.date + }); + var element; + if (this.isInput) { + element = this.element; + } else if (this.component){ + element = this.element.find('input'); + } + if (element) { + element.change(); + } + } + }, + + showMode: function(dir) { + if (dir) { + this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir)); + } + /* + vitalets: fixing bug of very special conditions: + jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover. + Method show() does not set display css correctly and datepicker is not shown. + Changed to .css('display', 'block') solve the problem. + See https://github.com/vitalets/x-editable/issues/37 + + In jquery 1.7.2+ everything works fine. + */ + //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); + this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block'); + this.updateNavArrows(); + } + }; + + $.fn.datepicker = function ( option ) { + var args = Array.apply(null, arguments); + args.shift(); + return this.each(function () { + var $this = $(this), + data = $this.data('datepicker'), + options = typeof option == 'object' && option; + if (!data) { + $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options)))); + } + if (typeof option == 'string' && typeof data[option] == 'function') { + data[option].apply(data, args); + } + }); + }; + + $.fn.datepicker.defaults = { + }; + $.fn.datepicker.Constructor = Datepicker; + var dates = $.fn.datepicker.dates = { + en: { + days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], + daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], + months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], + today: "Today" + } + } + + var DPGlobal = { + modes: [ + { + clsName: 'days', + navFnc: 'Month', + navStep: 1 + }, + { + clsName: 'months', + navFnc: 'FullYear', + navStep: 1 + }, + { + clsName: 'years', + navFnc: 'FullYear', + navStep: 10 + }], + isLeapYear: function (year) { + return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)) + }, + getDaysInMonth: function (year, month) { + return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month] + }, + validParts: /dd?|mm?|MM?|yy(?:yy)?/g, + nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\r]+/g, + parseFormat: function(format){ + // IE treats \0 as a string end in inputs (truncating the value), + // so it's a bad format delimiter, anyway + var separators = format.replace(this.validParts, '\0').split('\0'), + parts = format.match(this.validParts); + if (!separators || !separators.length || !parts || parts.length == 0){ + throw new Error("Invalid date format."); + } + return {separators: separators, parts: parts}; + }, + parseDate: function(date, format, language) { + if (date instanceof Date) return date; + if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) { + var part_re = /([-+]\d+)([dmwy])/, + parts = date.match(/([-+]\d+)([dmwy])/g), + part, dir; + date = new Date(); + for (var i=0; i<parts.length; i++) { + part = part_re.exec(parts[i]); + dir = parseInt(part[1]); + switch(part[2]){ + case 'd': + date.setUTCDate(date.getUTCDate() + dir); + break; + case 'm': + date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir); + break; + case 'w': + date.setUTCDate(date.getUTCDate() + dir * 7); + break; + case 'y': + date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir); + break; + } + } + return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0); + } + var parts = date && date.match(this.nonpunctuation) || [], + date = new Date(), + parsed = {}, + setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'], + setters_map = { + yyyy: function(d,v){ return d.setUTCFullYear(v); }, + yy: function(d,v){ return d.setUTCFullYear(2000+v); }, + m: function(d,v){ + v -= 1; + while (v<0) v += 12; + v %= 12; + d.setUTCMonth(v); + while (d.getUTCMonth() != v) + d.setUTCDate(d.getUTCDate()-1); + return d; + }, + d: function(d,v){ return d.setUTCDate(v); } + }, + val, filtered, part; + setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m']; + setters_map['dd'] = setters_map['d']; + date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); + if (parts.length == format.parts.length) { + for (var i=0, cnt = format.parts.length; i < cnt; i++) { + val = parseInt(parts[i], 10); + part = format.parts[i]; + if (isNaN(val)) { + switch(part) { + case 'MM': + filtered = $(dates[language].months).filter(function(){ + var m = this.slice(0, parts[i].length), + p = parts[i].slice(0, m.length); + return m == p; + }); + val = $.inArray(filtered[0], dates[language].months) + 1; + break; + case 'M': + filtered = $(dates[language].monthsShort).filter(function(){ + var m = this.slice(0, parts[i].length), + p = parts[i].slice(0, m.length); + return m == p; + }); + val = $.inArray(filtered[0], dates[language].monthsShort) + 1; + break; + } + } + parsed[part] = val; + } + for (var i=0, s; i<setters_order.length; i++){ + s = setters_order[i]; + if (s in parsed) + setters_map[s](date, parsed[s]) + } + } + return date; + }, + formatDate: function(date, format, language){ + var val = { + d: date.getUTCDate(), + m: date.getUTCMonth() + 1, + M: dates[language].monthsShort[date.getUTCMonth()], + MM: dates[language].months[date.getUTCMonth()], + yy: date.getUTCFullYear().toString().substring(2), + yyyy: date.getUTCFullYear() + }; + val.dd = (val.d < 10 ? '0' : '') + val.d; + val.mm = (val.m < 10 ? '0' : '') + val.m; + var date = [], + seps = $.extend([], format.separators); + for (var i=0, cnt = format.parts.length; i < cnt; i++) { + if (seps.length) + date.push(seps.shift()) + date.push(val[format.parts[i]]); + } + return date.join(''); + }, + headTemplate: '<thead>'+ + '<tr>'+ + '<th class="prev"><i class="icon-arrow-left"/></th>'+ + '<th colspan="5" class="switch"></th>'+ + '<th class="next"><i class="icon-arrow-right"/></th>'+ + '</tr>'+ + '</thead>', + contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>', + footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>' + }; + DPGlobal.template = '<div class="datepicker">'+ + '<div class="datepicker-days">'+ + '<table class=" table-condensed">'+ + DPGlobal.headTemplate+ + '<tbody></tbody>'+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '<div class="datepicker-months">'+ + '<table class="table-condensed">'+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '<div class="datepicker-years">'+ + '<table class="table-condensed">'+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '</div>'; + + $.fn.datepicker.DPGlobal = DPGlobal; + +}( window.jQuery ); diff --git a/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable-inline.min.js b/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable-inline.min.js new file mode 100755 index 0000000..ed749a3 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable-inline.min.js @@ -0,0 +1,5 @@ +/*! X-editable - v1.3.0 +* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery +* http://github.com/vitalets/x-editable +* Copyright (c) 2012 Vitaliy Potapov; Licensed MIT */ +(function(e){var t=function(t,n){this.options=e.extend({},e.fn.editableform.defaults,n),this.$div=e(t),this.options.scope||(this.options.scope=this),this.initInput()};t.prototype={constructor:t,initInput:function(){var t,n;if(typeof e.fn.editabletypes[this.options.type]!="function"){e.error("Unknown type: "+this.options.type);return}t=e.fn.editabletypes[this.options.type],n=e.fn.editableutils.sliceObj(this.options,e.fn.editableutils.objectKeys(t.defaults)),this.input=new t(n),this.value=this.input.str2value(this.options.value)},initTemplate:function(){this.$form=e(e.fn.editableform.template)},initButtons:function(){this.$form.find(".editable-buttons").append(e.fn.editableform.buttons)},render:function(){this.$loading=e(e.fn.editableform.loading),this.$div.empty().append(this.$loading),this.showLoading(),this.initTemplate(),this.options.showbuttons?this.initButtons():this.$form.find(".editable-buttons").remove(),this.$div.triggerHandler("rendering"),e.when(this.input.render()).then(e.proxy(function(){this.$form.find("div.editable-input").append(this.input.$input),this.options.showbuttons||this.input.autosubmit(),this.input.$clear&&this.$form.find("div.editable-input").append(e('<div class="editable-clear">').append(this.input.$clear)),this.$div.append(this.$form),this.$form.find(".editable-cancel").click(e.proxy(this.cancel,this)),this.input.error?(this.error(this.input.error),this.$form.find(".editable-submit").attr("disabled",!0),this.input.$input.attr("disabled",!0),this.$form.submit(function(e){e.preventDefault()})):(this.error(!1),this.input.$input.removeAttr("disabled"),this.$form.find(".editable-submit").removeAttr("disabled"),this.input.value2input(this.value),this.$form.submit(e.proxy(this.submit,this))),this.$div.triggerHandler("rendered"),this.showForm()},this))},cancel:function(){this.$div.triggerHandler("cancel")},showLoading:function(){var e;this.$form?(this.$loading.width(this.$form.outerWidth()),this.$loading.height(this.$form.outerHeight()),this.$form.hide()):(e=this.$loading.parent().width(),e&&this.$loading.width(e)),this.$loading.show()},showForm:function(e){this.$loading.hide(),this.$form.show(),e!==!1&&this.input.activate(),this.$div.triggerHandler("show")},error:function(t){var n=this.$form.find(".control-group"),r=this.$form.find(".editable-error-block");t===!1?(n.removeClass(e.fn.editableform.errorGroupClass),r.removeClass(e.fn.editableform.errorBlockClass).empty().hide()):(n.addClass(e.fn.editableform.errorGroupClass),r.addClass(e.fn.editableform.errorBlockClass).text(t).show())},submit:function(t){t.stopPropagation(),t.preventDefault();var n,r=this.input.input2value();if(n=this.validate(r)){this.error(n),this.showForm();return}if(!this.options.savenochange&&this.input.value2str(r)==this.input.value2str(this.value)){this.$div.triggerHandler("nochange");return}e.when(this.save(r)).done(e.proxy(function(e){var t=typeof this.options.success=="function"?this.options.success.call(this.options.scope,e,r):null;if(t===!1){this.error(!1),this.showForm(!1);return}if(typeof t=="string"){this.error(t),this.showForm();return}t&&typeof t=="object"&&t.hasOwnProperty("newValue")&&(r=t.newValue),this.error(!1),this.value=r,this.$div.triggerHandler("save",{newValue:r,response:e})},this)).fail(e.proxy(function(e){this.error(typeof e=="string"?e:e.responseText||e.statusText||"Unknown error!"),this.showForm()},this))},save:function(t){var n=this.input.value2submit(t);this.options.pk=e.fn.editableutils.tryParseJson(this.options.pk,!0);var r=typeof this.options.pk=="function"?this.options.pk.call(this.options.scope):this.options.pk,i=!!(typeof this.options.url=="function"||this.options.url&&(this.options.send==="always"||this.options.send==="auto"&&r)),s;if(i)return this.showLoading(),s={name:this.options.name||"",value:n,pk:r},typeof this.options.params=="function"?s=this.options.params.call(this.options.scope,s):(this.options.params=e.fn.editableutils.tryParseJson(this.options.params,!0),e.extend(s,this.options.params)),typeof this.options.url=="function"?this.options.url.call(this.options.scope,s):e.ajax(e.extend({url:this.options.url,data:s,type:"POST"},this.options.ajaxOptions))},validate:function(e){e===undefined&&(e=this.value);if(typeof this.options.validate=="function")return this.options.validate.call(this.options.scope,e)},option:function(e,t){this.options[e]=t,e==="value"&&this.setValue(t)},setValue:function(e,t){t?this.value=this.input.str2value(e):this.value=e}},e.fn.editableform=function(n){var r=arguments;return this.each(function(){var i=e(this),s=i.data("editableform"),o=typeof n=="object"&&n;s||i.data("editableform",s=new t(this,o)),typeof n=="string"&&s[n].apply(s,Array.prototype.slice.call(r,1))})},e.fn.editableform.Constructor=t,e.fn.editableform.defaults={type:"text",url:null,params:null,name:null,pk:null,value:null,send:"auto",validate:null,success:null,ajaxOptions:null,showbuttons:!0,scope:null,savenochange:!1},e.fn.editableform.template='<form class="form-inline editableform"><div class="control-group"><div><div class="editable-input"></div><div class="editable-buttons"></div></div><div class="editable-error-block"></div></div></form>',e.fn.editableform.loading='<div class="editableform-loading"></div>',e.fn.editableform.buttons='<button type="submit" class="editable-submit">ok</button><button type="button" class="editable-cancel">cancel</button>',e.fn.editableform.errorGroupClass=null,e.fn.editableform.errorBlockClass="editable-error"})(window.jQuery),function(e){e.fn.editableutils={inherit:function(e,t){var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e,e.superclass=t.prototype},setCursorPosition:function(e,t){if(e.setSelectionRange)e.setSelectionRange(t,t);else if(e.createTextRange){var n=e.createTextRange();n.collapse(!0),n.moveEnd("character",t),n.moveStart("character",t),n.select()}},tryParseJson:function(e,t){if(typeof e=="string"&&e.length&&e.match(/^[\{\[].*[\}\]]$/))if(t)try{e=(new Function("return "+e))()}catch(n){}finally{return e}else e=(new Function("return "+e))();return e},sliceObj:function(t,n,r){var i,s,o={};if(!e.isArray(n)||!n.length)return o;for(var u=0;u<n.length;u++){i=n[u],t.hasOwnProperty(i)&&(o[i]=t[i]);if(r===!0)continue;s=i.toLowerCase(),t.hasOwnProperty(s)&&(o[i]=t[s])}return o},getConfigData:function(t){var n={};return e.each(t.data(),function(e,t){if(typeof t!="object"||t&&typeof t=="object"&&t.constructor===Object)n[e]=t}),n},objectKeys:function(e){if(Object.keys)return Object.keys(e);if(e!==Object(e))throw new TypeError("Object.keys called on a non-object");var t=[],n;for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.push(n);return t},escape:function(t){return e("<div>").text(t).html()}}}(window.jQuery),function(e){var t=function(e,t){this.init(e,t)};t.prototype={containerName:null,innerCss:null,init:function(n,r){this.$element=e(n),this.options=e.extend({},e.fn.editableContainer.defaults,e.fn.editableutils.getConfigData(this.$element),r),this.splitOptions(),this.initContainer(),this.$element.on("destroyed",e.proxy(function(){this.destroy()},this)),e(document).data("editable-handlers-attached")||(e(document).on("keyup.editable",function(t){t.which===27&&e(".editable-open").editableContainer("hide")}),e(document).on("click.editable",function(n){var r=e(n.target);if(r.is(".editable-container")||r.parents(".editable-container").length||r.parents(".ui-datepicker-header").length)return;t.prototype.closeOthers(n.target)}),e(document).data("editable-handlers-attached",!0))},splitOptions:function(){this.containerOptions={},this.formOptions={};var t=e.fn[this.containerName].defaults;for(var n in this.options)n in t?this.containerOptions[n]=this.options[n]:this.formOptions[n]=this.options[n]},initContainer:function(){this.call(this.containerOptions)},initForm:function(){return this.formOptions.scope=this.$element[0],this.$form=e("<div>").editableform(this.formOptions).on({save:e.proxy(this.save,this),cancel:e.proxy(function(){this.hide("cancel")},this),nochange:e.proxy(function(){this.hide("nochange")},this),show:e.proxy(this.setPosition,this),rendering:e.proxy(this.setPosition,this),rendered:e.proxy(function(){this.$element.triggerHandler("shown")},this)}),this.$form},tip:function(){return this.container().$tip},container:function(){return this.$element.data(this.containerName)},call:function(){this.$element[this.containerName].apply(this.$element,arguments)},show:function(e){this.$element.addClass("editable-open"),e!==!1&&this.closeOthers(this.$element[0]),this.innerShow()},innerShow:function(){this.call("show"),this.tip().addClass("editable-container"),this.initForm(),this.tip().find(this.innerCss).empty().append(this.$form),this.$form.editableform("render")},hide:function(e){if(!this.tip()||!this.tip().is(":visible")||!this.$element.hasClass("editable-open"))return;this.$element.removeClass("editable-open"),this.innerHide(),this.$element.triggerHandler("hidden",e)},innerHide:function(){this.call("hide")},toggle:function(e){this.tip&&this.tip().is(":visible")?this.hide():this.show(e)},setPosition:function(){},save:function(e,t){this.hide("save"),this.$element.triggerHandler("save",t)},option:function(e,t){this.options[e]=t,e in this.containerOptions?(this.containerOptions[e]=t,this.setContainerOption(e,t)):(this.formOptions[e]=t,this.$form&&this.$form.editableform("option",e,t))},setContainerOption:function(e,t){this.call("option",e,t)},destroy:function(){this.call("destroy")},closeOthers:function(t){e(".editable-open").each(function(n,r){if(r===t||e(r).find(t).length)return;var i=e(r),s=i.data("editableContainer");if(!s)return;s.options.onblur==="cancel"?i.data("editableContainer").hide("onblur"):s.options.onblur==="submit"&&i.data("editableContainer").tip().find("form").submit()})},activate:function(){this.tip&&this.tip().is(":visible")&&this.$form&&this.$form.data("editableform").input.activate()}},e.fn.editableContainer=function(n){var r=arguments;return this.each(function(){var i=e(this),s="editableContainer",o=i.data(s),u=typeof n=="object"&&n;o||i.data(s,o=new t(this,u)),typeof n=="string"&&o[n].apply(o,Array.prototype.slice.call(r,1))})},e.fn.editableContainer.Constructor=t,e.fn.editableContainer.defaults={value:null,placement:"top",autohide:!0,onblur:"cancel"},jQuery.event.special.destroyed={remove:function(e){e.handler&&e.handler()}}}(window.jQuery),function(e){var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.editable.defaults,e.fn.editableutils.getConfigData(this.$element),n),this.init()};t.prototype={constructor:t,init:function(){var t,n=!1,r,i;if(!e.fn.editableContainer){e.error("You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)");return}this.options.name=this.options.name||this.$element.attr("id");if(typeof e.fn.editabletypes[this.options.type]!="function"){e.error("Unknown type: "+this.options.type);return}t=e.fn.editabletypes[this.options.type],this.typeOptions=e.fn.editableutils.sliceObj(this.options,e.fn.editableutils.objectKeys(t.defaults)),this.input=new t(this.typeOptions),this.options.value===undefined||this.options.value===null?(this.value=this.input.html2value(e.trim(this.$element.html())),n=!0):(this.options.value=e.fn.editableutils.tryParseJson(this.options.value,!0),typeof this.options.value=="string"?this.value=this.input.str2value(this.options.value):this.value=this.options.value),this.$element.addClass("editable"),this.options.toggle!=="manual"?(this.$element.addClass("editable-click"),this.$element.on(this.options.toggle+".editable",e.proxy(function(e){e.preventDefault();if(this.options.toggle==="mouseenter")this.show();else{var t=this.options.toggle!=="click";this.toggle(t)}},this))):this.$element.attr("tabindex",-1),r=!n&&this.value!==null&&this.value!==undefined,r&=this.options.autotext==="always"||this.options.autotext==="auto"&&!this.$element.text().length,e.when(r?this.render():!0).then(e.proxy(function(){this.options.disabled?this.disable():this.enable(),this.$element.triggerHandler("init",this)},this))},render:function(){if(this.options.display===!1)return;return this.input.options.hasOwnProperty("source")?this.input.value2html(this.value,this.$element[0],this.options.display):typeof this.options.display=="function"?this.options.display.call(this.$element[0],this.value):this.input.value2html(this.value,this.$element[0])},enable:function(){this.options.disabled=!1,this.$element.removeClass("editable-disabled"),this.handleEmpty(),this.options.toggle!=="manual"&&this.$element.attr("tabindex")==="-1"&&this.$element.removeAttr("tabindex")},disable:function(){this.options.disabled=!0,this.hide(),this.$element.addClass("editable-disabled"),this.handleEmpty(),this.$element.attr("tabindex",-1)},toggleDisabled:function(){this.options.disabled?this.enable():this.disable()},option:function(t,n){if(t&&typeof t=="object"){e.each(t,e.proxy(function(t,n){this.option(e.trim(t),n)},this));return}this.options[t]=n;if(t==="disabled"){n?this.disable():this.enable();return}t==="value"&&this.setValue(n),this.container&&this.container.option(t,n)},handleEmpty:function(){if(this.options.display===!1)return;var t="editable-empty";this.options.disabled?this.$element.hasClass(t)&&(this.$element.empty(),this.$element.removeClass(t)):e.trim(this.$element.text())===""?this.$element.addClass(t).text(this.options.emptytext):this.$element.removeClass(t)},show:function(t){if(this.options.disabled)return;if(!this.container){var n=e.extend({},this.options,{value:this.value});this.$element.editableContainer(n),this.$element.on("save.internal",e.proxy(this.save,this)),this.container=this.$element.data("editableContainer")}else if(this.container.tip().is(":visible"))return;this.container.show(t)},hide:function(){this.container&&this.container.hide()},toggle:function(e){this.container&&this.container.tip().is(":visible")?this.hide():this.show(e)},save:function(e,t){typeof this.options.url!="function"&&this.options.display!==!1&&t.response===undefined&&this.input.value2str(this.value)!==this.input.value2str(t.newValue)?this.$element.addClass("editable-unsaved"):this.$element.removeClass("editable-unsaved"),this.setValue(t.newValue)},validate:function(){if(typeof this.options.validate=="function")return this.options.validate.call(this,this.value)},setValue:function(t,n){n?this.value=this.input.str2value(t):this.value=t,this.container&&this.container.option("value",this.value),e.when(this.render()).then(e.proxy(function(){this.handleEmpty()},this))},activate:function(){this.container&&this.container.activate()}},e.fn.editable=function(n){var r={},i=arguments,s="editable";switch(n){case"validate":return this.each(function(){var t=e(this),n=t.data(s),i;n&&(i=n.validate())&&(r[n.options.name]=i)}),r;case"getValue":return this.each(function(){var t=e(this),n=t.data(s);n&&n.value!==undefined&&n.value!==null&&(r[n.options.name]=n.input.value2submit(n.value))}),r;case"submit":var o=arguments[1]||{},u=this,a=this.editable("validate"),f;return e.isEmptyObject(a)?(f=this.editable("getValue"),o.data&&e.extend(f,o.data),e.ajax(e.extend({url:o.url,data:f,type:"POST"},o.ajaxOptions)).success(function(e){typeof o.success=="function"&&o.success.call(u,e,o)}).error(function(){typeof o.error=="function"&&o.error.apply(u,arguments)})):typeof o.error=="function"&&o.error.call(u,a),this}return this.each(function(){var r=e(this),o=r.data(s),u=typeof n=="object"&&n;o||r.data(s,o=new t(this,u)),typeof n=="string"&&o[n].apply(o,Array.prototype.slice.call(i,1))})},e.fn.editable.defaults={type:"text",disabled:!1,toggle:"click",emptytext:"Empty",autotext:"auto",value:null,display:null}}(window.jQuery),function(e){e.fn.editabletypes={};var t=function(){};t.prototype={init:function(t,n,r){this.type=t,this.options=e.extend({},r,n),this.$input=null,this.$clear=null,this.error=null},render:function(){this.$input=e(this.options.tpl),this.options.inputclass&&this.$input.addClass(this.options.inputclass),this.options.placeholder&&this.$input.attr("placeholder",this.options.placeholder)},value2html:function(t,n){e(n).text(t)},html2value:function(t){return e("<div>").html(t).text()},value2str:function(e){return e},str2value:function(e){return e},value2submit:function(e){return e},value2input:function(e){this.$input.val(e)},input2value:function(){return this.$input.val()},activate:function(){this.$input.is(":visible")&&this.$input.focus()},clear:function(){this.$input.val(null)},escape:function(t){return e("<div>").text(t).html()},autosubmit:function(){}},t.defaults={tpl:"",inputclass:"input-medium",name:null},e.extend(e.fn.editabletypes,{abstractinput:t})}(window.jQuery),function(e){var t=function(e){};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{render:function(){t.superclass.render.call(this);var n=e.Deferred();return this.error=null,this.sourceData=null,this.prependData=null,this.onSourceReady(function(){this.renderList(),n.resolve()},function(){this.error=this.options.sourceError,n.resolve()}),n.promise()},html2value:function(e){return null},value2html:function(t,n,r){var i=e.Deferred();return this.onSourceReady(function(){typeof r=="function"?r.call(n,t,this.sourceData):this.value2htmlFinal(t,n),i.resolve()},function(){i.resolve()}),i.promise()},onSourceReady:function(t,n){if(e.isArray(this.sourceData)){t.call(this);return}try{this.options.source=e.fn.editableutils.tryParseJson(this.options.source,!1)}catch(r){n.call(this);return}if(typeof this.options.source=="string"){if(this.options.sourceCache){var i=this.options.source+(this.options.name?"-"+this.options.name:""),s;e(document).data(i)||e(document).data(i,{}),s=e(document).data(i);if(s.loading===!1&&s.sourceData){this.sourceData=s.sourceData,t.call(this);return}if(s.loading===!0){s.callbacks.push(e.proxy(function(){this.sourceData=s.sourceData,t.call(this)},this)),s.err_callbacks.push(e.proxy(n,this));return}s.loading=!0,s.callbacks=[],s.err_callbacks=[]}e.ajax({url:this.options.source,type:"get",cache:!1,data:this.options.name?{name:this.options.name}:{},dataType:"json",success:e.proxy(function(r){s&&(s.loading=!1),this.sourceData=this.makeArray(r),e.isArray(this.sourceData)?(this.doPrepend(),t.call(this),s&&(s.sourceData=this.sourceData,e.each(s.callbacks,function(){this.call()}))):(n.call(this),s&&e.each(s.err_callbacks,function(){this.call()}))},this),error:e.proxy(function(){n.call(this),s&&(s.loading=!1,e.each(s.err_callbacks,function(){this.call()}))},this)})}else this.sourceData=this.makeArray(this.options.source),e.isArray(this.sourceData)?(this.doPrepend(),t.call(this)):n.call(this)},doPrepend:function(){if(this.options.prepend===null||this.options.prepend===undefined)return;e.isArray(this.prependData)||(this.options.prepend=e.fn.editableutils.tryParseJson(this.options.prepend,!0),typeof this.options.prepend=="string"&&(this.options.prepend={"":this.options.prepend}),this.prependData=this.makeArray(this.options.prepend)),e.isArray(this.prependData)&&e.isArray(this.sourceData)&&(this.sourceData=this.prependData.concat(this.sourceData))},renderList:function(){},value2htmlFinal:function(e,t){},makeArray:function(t){var n,r,i=[],s;if(!t||typeof t=="string")return null;if(e.isArray(t)){s=function(e,t){r={value:e,text:t};if(n++>=2)return!1};for(var o=0;o<t.length;o++)typeof t[o]=="object"?(n=0,e.each(t[o],s),n===1?i.push(r):n>1&&t[o].hasOwnProperty("value")&&t[o].hasOwnProperty("text")&&i.push(t[o])):i.push({value:t[o],text:t[o]})}else e.each(t,function(e,t){i.push({value:e,text:t})});return i},itemByVal:function(t){if(e.isArray(this.sourceData))for(var n=0;n<this.sourceData.length;n++)if(this.sourceData[n].value==t)return this.sourceData[n]}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{source:null,prepend:!1,sourceError:"Error when loading list",sourceCache:!0}),e.fn.editabletypes.list=t}(window.jQuery),function(e){var t=function(e){this.init("text",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{activate:function(){this.$input.is(":visible")&&(this.$input.focus(),e.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length))}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',placeholder:null}),e.fn.editabletypes.text=t}(window.jQuery),function(e){var t=function(e){this.init("textarea",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{render:function(){t.superclass.render.call(this),this.$input.keydown(function(t){t.ctrlKey&&t.which===13&&e(this).closest("form").submit()})},value2html:function(t,n){var r="",i;if(t){i=t.split("\n");for(var s=0;s<i.length;s++)i[s]=e("<div>").text(i[s]).html();r=i.join("<br>")}e(n).html(r)},html2value:function(t){if(!t)return"";var n=t.split(/<br\s*\/?>/i);for(var r=0;r<n.length;r++)n[r]=e("<div>").html(n[r]).text();return n.join("\n")},activate:function(){this.$input.is(":visible")&&(e.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length),this.$input.focus())}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{tpl:"<textarea></textarea>",inputclass:"input-large",placeholder:null}),e.fn.editabletypes.textarea=t}(window.jQuery),function(e){var t=function(e){this.init("select",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.list),e.extend(t.prototype,{renderList:function(){if(!e.isArray(this.sourceData))return;for(var t=0;t<this.sourceData.length;t++)this.$input.append(e("<option>",{value:this.sourceData[t].value}).text(this.sourceData[t].text));this.$input.on("keydown.editable",function(t){t.which===13&&e(this).closest("form").submit()})},value2htmlFinal:function(e,n){var r="",i=this.itemByVal(e);i&&(r=i.text),t.superclass.constructor.superclass.value2html(r,n)},autosubmit:function(){this.$input.off("keydown.editable").on("change.editable",function(){e(this).closest("form").submit()})}}),t.defaults=e.extend({},e.fn.editabletypes.list.defaults,{tpl:"<select></select>"}),e.fn.editabletypes.select=t}(window.jQuery),function(e){var t=function(e){this.init("checklist",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.list),e.extend(t.prototype,{renderList:function(){var t,n;if(!e.isArray(this.sourceData))return;for(var r=0;r<this.sourceData.length;r++)t=e("<label>").append(e("<input>",{type:"checkbox",value:this.sourceData[r].value,name:this.options.name})).append(e("<span>").text(" "+this.sourceData[r].text)),e("<div>").append(t).appendTo(this.$input)},value2str:function(t){return e.isArray(t)?t.sort().join(e.trim(this.options.separator)):""},str2value:function(t){var n,r=null;return typeof t=="string"&&t.length?(n=new RegExp("\\s*"+e.trim(this.options.separator)+"\\s*"),r=t.split(n)):e.isArray(t)&&(r=t),r},value2input:function(t){var n=this.$input.find('input[type="checkbox"]');n.removeAttr("checked"),e.isArray(t)&&t.length&&n.each(function(n,r){var i=e(r);e.each(t,function(e,t){i.val()==t&&i.attr("checked","checked")})})},input2value:function(){var t=[];return this.$input.find("input:checked").each(function(n,r){t.push(e(r).val())}),t},value2htmlFinal:function(t,n){var r=[],i=e.grep(this.sourceData,function(n){return e.grep(t,function(e){return e==n.value}).length});i.length?(e.each(i,function(t,n){r.push(e.fn.editableutils.escape(n.text))}),e(n).html(r.join("<br>"))):e(n).empty()},activate:function(){this.$input.find('input[type="checkbox"]').first().focus()},autosubmit:function(){this.$input.find('input[type="checkbox"]').on("keydown",function(t){t.which===13&&e(this).closest("form").submit()})}}),t.defaults=e.extend({},e.fn.editabletypes.list.defaults,{tpl:"<div></div>",inputclass:"editable-checklist",separator:","}),e.fn.editabletypes.checklist=t}(window.jQuery),function(e){var t=function(e){this.init("password",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),e.extend(t.prototype,{value2html:function(t,n){t?e(n).text("[hidden]"):e(n).empty()},html2value:function(e){return null}}),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="password">'}),e.fn.editabletypes.password=t}(window.jQuery),function(e){var t=function(e){this.init("email",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="email">'}),e.fn.editabletypes.email=t}(window.jQuery),function(e){var t=function(e){this.init("url",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="url">'}),e.fn.editabletypes.url=t}(window.jQuery),function(e){var t=function(e){this.init("tel",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="tel">'}),e.fn.editabletypes.tel=t}(window.jQuery),function(e){var t=function(e){this.init("number",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),e.extend(t.prototype,{render:function(){t.superclass.render.call(this),this.options.min!==null&&this.$input.attr("min",this.options.min),this.options.max!==null&&this.$input.attr("max",this.options.max),this.options.step!==null&&this.$input.attr("step",this.options.step)}}),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="number">',inputclass:"input-mini",min:null,max:null,step:null}),e.fn.editabletypes.number=t}(window.jQuery),function(e){var t=function(e){this.init("range",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.number),e.extend(t.prototype,{render:function(){this.$input=e(this.options.tpl);var t=this.$input.filter("input");this.options.inputclass&&t.addClass(this.options.inputclass),this.options.min!==null&&t.attr("min",this.options.min),this.options.max!==null&&t.attr("max",this.options.max),this.options.step!==null&&t.attr("step",this.options.step),t.on("input",function(){e(this).siblings("output").text(e(this).val())})},activate:function(){this.$input.filter("input").focus()}}),t.defaults=e.extend({},e.fn.editabletypes.number.defaults,{tpl:'<input type="range"><output style="width: 30px; display: inline-block"></output>',inputclass:"input-medium"}),e.fn.editabletypes.range=t}(window.jQuery),function(e){e.extend(e.fn.editableform.Constructor.prototype,{initTemplate:function(){this.$form=e(e.fn.editableform.template),this.$form.find(".editable-error-block").addClass("help-block")}}),e.fn.editableform.buttons='<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button><button type="button" class="btn editable-cancel"><i class="icon-remove"></i></button>',e.fn.editableform.errorGroupClass="error",e.fn.editableform.errorBlockClass=null}(window.jQuery),function(e){e.extend(e.fn.editableContainer.Constructor.prototype,{containerName:"editableform",innerCss:null,initContainer:function(){this.options.anim||(this.options.anim=0)},splitOptions:function(){this.containerOptions={},this.formOptions=this.options},tip:function(){return this.$form},innerShow:function(){this.$element.hide(),this.$form&&this.$form.remove(),this.initForm(),this.tip().addClass("editable-container").addClass("editable-inline"),this.$form.insertAfter(this.$element),this.$form.show(this.options.anim),this.$form.editableform("render")},innerHide:function(){this.$form.hide(this.options.anim,e.proxy(function(){this.$element.show()},this))},destroy:function(){this.tip().remove()}}),e.fn.editableContainer.defaults=e.extend({},e.fn.editableContainer.defaults,{anim:"fast"})}(window.jQuery),function(e){var t=function(n){this.init("date",n,t.defaults);var r=e.fn.editableutils.sliceObj(this.options,["format"]);this.options.datepicker=e.extend({},t.defaults.datepicker,r,n.datepicker),this.options.viewformat||(this.options.viewformat=this.options.datepicker.format),this.options.datepicker.language=this.options.datepicker.language||"en",this.dpg=e.fn.datepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.datepicker.format),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat)};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{render:function(){t.superclass.render.call(this),this.$input.datepicker(this.options.datepicker),this.options.clear&&(this.$clear=e('<a href="#"></a>').html(this.options.clear).click(e.proxy(function(e){e.preventDefault(),e.stopPropagation(),this.clear()},this)))},value2html:function(e,n){var r=e?this.dpg.formatDate(e,this.parsedViewFormat,this.options.datepicker.language):"";t.superclass.value2html(r,n)},html2value:function(e){return e?this.dpg.parseDate(e,this.parsedViewFormat,this.options.datepicker.language):null},value2str:function(e){return e?this.dpg.formatDate(e,this.parsedFormat,this.options.datepicker.language):""},str2value:function(e){return e?this.dpg.parseDate(e,this.parsedFormat,this.options.datepicker.language):null},value2submit:function(e){return this.value2str(e)},value2input:function(e){this.$input.datepicker("update",e)},input2value:function(){return this.$input.data("datepicker").date},activate:function(){},clear:function(){this.$input.data("datepicker").date=null,this.$input.find(".active").removeClass("active")},autosubmit:function(){this.$input.on("changeDate",function(t){var n=e(this).closest("form");setTimeout(function(){n.submit()},200)})}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{tpl:"<div></div>",inputclass:"editable-date well",format:"yyyy-mm-dd",viewformat:null,datepicker:{weekStart:0,startView:0,autoclose:!1},clear:"&times; clear"}),e.fn.editabletypes.date=t}(window.jQuery),!function(e){function t(){return new Date(Date.UTC.apply(Date,arguments))}function n(){var e=new Date;return t(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate())}var r=function(t,n){var r=this;this.element=e(t),this.language=n.language||this.element.data("date-language")||"en",this.language=this.language in i?this.language:"en",this.format=s.parseFormat(n.format||this.element.data("date-format")||"mm/dd/yyyy"),this.isInline=!1,this.isInput=this.element.is("input"),this.component=this.element.is(".date")?this.element.find(".add-on"):!1,this.hasInput=this.component&&this.element.find("input").length,this.component&&this.component.length===0&&(this.component=!1),this.isInput?this.element.on({focus:e.proxy(this.show,this),keyup:e.proxy(this.update,this),keydown:e.proxy(this.keydown,this)}):this.component&&this.hasInput?(this.element.find("input").on({focus:e.proxy(this.show,this),keyup:e.proxy(this.update,this),keydown:e.proxy(this.keydown,this)}),this.component.on("click",e.proxy(this.show,this))):this.element.is("div")?this.isInline=!0:this.element.on("click",e.proxy(this.show,this)),this.picker=e(s.template).appendTo(this.isInline?this.element:"body").on({click:e.proxy(this.click,this),mousedown:e.proxy(this.mousedown,this)}),this.isInline?this.picker.addClass("datepicker-inline"):this.picker.addClass("dropdown-menu"),e(document).on("mousedown",function(t){e(t.target).closest(".datepicker").length==0&&r.hide()}),this.autoclose=!1,"autoclose"in n?this.autoclose=n.autoclose:"dateAutoclose"in this.element.data()&&(this.autoclose=this.element.data("date-autoclose")),this.keyboardNavigation=!0,"keyboardNavigation"in n?this.keyboardNavigation=n.keyboardNavigation:"dateKeyboardNavigation"in this.element.data()&&(this.keyboardNavigation=this.element.data("date-keyboard-navigation"));switch(n.startView||this.element.data("date-start-view")){case 2:case"decade":this.viewMode=this.startViewMode=2;break;case 1:case"year":this.viewMode=this.startViewMode=1;break;case 0:case"month":default:this.viewMode=this.startViewMode=0}this.todayBtn=n.todayBtn||this.element.data("date-today-btn")||!1,this.todayHighlight=n.todayHighlight||this.element.data("date-today-highlight")||!1,this.weekStart=(n.weekStart||this.element.data("date-weekstart")||i[this.language].weekStart||0)%7,this.weekEnd=(this.weekStart+6)%7,this.startDate=-Infinity,this.endDate=Infinity,this.setStartDate(n.startDate||this.element.data("date-startdate")),this.setEndDate(n.endDate||this.element.data("date-enddate")),this.fillDow(),this.fillMonths(),this.update(),this.showMode(),this.isInline&&this.show()};r.prototype={constructor:r,show:function(t){this.picker.show(),this.height=this.component?this.component.outerHeight():this.element.outerHeight(),this.update(),this.place(),e(window).on("resize",e.proxy(this.place,this)),t&&(t.stopPropagation(),t.preventDefault()),this.element.trigger({type:"show",date:this.date})},hide:function(t){if(this.isInline)return;this.picker.hide(),e(window).off("resize",this.place),this.viewMode=this.startViewMode,this.showMode(),this.isInput||e(document).off("mousedown",this.hide),t&&t.currentTarget.value&&this.setValue(),this.element.trigger({type:"hide",date:this.date})},getDate:function(){var e=this.getUTCDate();return new Date(e.getTime()+e.getTimezoneOffset()*6e4)},getUTCDate:function(){return this.date},setDate:function(e){this.setUTCDate(new Date(e.getTime()-e.getTimezoneOffset()*6e4))},setUTCDate:function(e){this.date=e,this.setValue()},setValue:function(){var e=this.getFormattedDate();this.isInput?this.element.prop("value",e):(this.component&&this.element.find("input").prop("value",e),this.element.data("date",e))},getFormattedDate:function(e){return e==undefined&&(e=this.format),s.formatDate(this.date,e,this.language)},setStartDate:function(e){this.startDate=e||-Infinity,this.startDate!==-Infinity&&(this.startDate=s.parseDate(this.startDate,this.format,this.language)),this.update(),this.updateNavArrows()},setEndDate:function(e){this.endDate=e||Infinity,this.endDate!==Infinity&&(this.endDate=s.parseDate(this.endDate,this.format,this.language)),this.update(),this.updateNavArrows()},place:function(){if(this.isInline)return;var t=parseInt(this.element.parents().filter(function(){return e(this).css("z-index")!="auto"}).first().css("z-index"))+10,n=this.component?this.component.offset():this.element.offset();this.picker.css({top:n.top+this.height,left:n.left,zIndex:t})},update:function(){var e,t=!1;arguments&&arguments.length&&(typeof arguments[0]=="string"||arguments[0]instanceof Date)?(e=arguments[0],t=!0):e=this.isInput?this.element.prop("value"):this.element.data("date")||this.element.find("input").prop("value"),this.date=s.parseDate(e,this.format,this.language),t&&this.setValue(),this.date<this.startDate?this.viewDate=new Date(this.startDate):this.date>this.endDate?this.viewDate=new Date(this.endDate):this.viewDate=new Date(this.date),this.fill()},fillDow:function(){var e=this.weekStart,t="<tr>";while(e<this.weekStart+7)t+='<th class="dow">'+i[this.language].daysMin[e++%7]+"</th>";t+="</tr>",this.picker.find(".datepicker-days thead").append(t)},fillMonths:function(){var e="",t=0;while(t<12)e+='<span class="month">'+i[this.language].monthsShort[t++]+"</span>";this.picker.find(".datepicker-months td").html(e)},fill:function(){var e=new Date(this.viewDate),n=e.getUTCFullYear(),r=e.getUTCMonth(),o=this.startDate!==-Infinity?this.startDate.getUTCFullYear():-Infinity,u=this.startDate!==-Infinity?this.startDate.getUTCMonth():-Infinity,a=this.endDate!==Infinity?this.endDate.getUTCFullYear():Infinity,f=this.endDate!==Infinity?this.endDate.getUTCMonth():Infinity,l=this.date&&this.date.valueOf(),c=new Date;this.picker.find(".datepicker-days thead th:eq(1)").text(i[this.language].months[r]+" "+n),this.picker.find("tfoot th.today").text(i[this.language].today).toggle(this.todayBtn!==!1),this.updateNavArrows(),this.fillMonths();var h=t(n,r-1,28,0,0,0,0),p=s.getDaysInMonth(h.getUTCFullYear(),h.getUTCMonth());h.setUTCDate(p),h.setUTCDate(p-(h.getUTCDay()-this.weekStart+7)%7);var d=new Date(h);d.setUTCDate(d.getUTCDate()+42),d=d.valueOf();var v=[],m;while(h.valueOf()<d){h.getUTCDay()==this.weekStart&&v.push("<tr>"),m="";if(h.getUTCFullYear()<n||h.getUTCFullYear()==n&&h.getUTCMonth()<r)m+=" old";else if(h.getUTCFullYear()>n||h.getUTCFullYear()==n&&h.getUTCMonth()>r)m+=" new";this.todayHighlight&&h.getUTCFullYear()==c.getFullYear()&&h.getUTCMonth()==c.getMonth()&&h.getUTCDate()==c.getDate()&&(m+=" today"),l&&h.valueOf()==l&&(m+=" active");if(h.valueOf()<this.startDate||h.valueOf()>this.endDate)m+=" disabled";v.push('<td class="day'+m+'">'+h.getUTCDate()+"</td>"),h.getUTCDay()==this.weekEnd&&v.push("</tr>"),h.setUTCDate(h.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(v.join(""));var g=this.date&&this.date.getUTCFullYear(),y=this.picker.find(".datepicker-months").find("th:eq(1)").text(n).end().find("span").removeClass("active");g&&g==n&&y.eq(this.date.getUTCMonth()).addClass("active"),(n<o||n>a)&&y.addClass("disabled"),n==o&&y.slice(0,u).addClass("disabled"),n==a&&y.slice(f+1).addClass("disabled"),v="",n=parseInt(n/10,10)*10;var b=this.picker.find(".datepicker-years").find("th:eq(1)").text(n+"-"+(n+9)).end().find("td");n-=1;for(var w=-1;w<11;w++)v+='<span class="year'+(w==-1||w==10?" old":"")+(g==n?" active":"")+(n<o||n>a?" disabled":"")+'">'+n+"</span>",n+=1;b.html(v)},updateNavArrows:function(){var e=new Date(this.viewDate),t=e.getUTCFullYear(),n=e.getUTCMonth();switch(this.viewMode){case 0:this.startDate!==-Infinity&&t<=this.startDate.getUTCFullYear()&&n<=this.startDate.getUTCMonth()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==Infinity&&t>=this.endDate.getUTCFullYear()&&n>=this.endDate.getUTCMonth()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 1:case 2:this.startDate!==-Infinity&&t<=this.startDate.getUTCFullYear()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==Infinity&&t>=this.endDate.getUTCFullYear()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"})}},click:function(n){n.stopPropagation(),n.preventDefault();var r=e(n.target).closest("span, td, th");if(r.length==1)switch(r[0].nodeName.toLowerCase()){case"th":switch(r[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var i=s.modes[this.viewMode].navStep*(r[0].className=="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,i);break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,i)}this.fill();break;case"today":var o=new Date;o=t(o.getFullYear(),o.getMonth(),o.getDate(),0,0,0),this.showMode(-2);var u=this.todayBtn=="linked"?null:"view";this._setDate(o,u)}break;case"span":if(!r.is(".disabled")){this.viewDate.setUTCDate(1);if(r.is(".month")){var a=r.parent().find("span").index(r);this.viewDate.setUTCMonth(a),this.element.trigger({type:"changeMonth",date:this.viewDate})}else{var f=parseInt(r.text(),10)||0;this.viewDate.setUTCFullYear(f),this.element.trigger({type:"changeYear",date:this.viewDate})}this.showMode(-1),this.fill()}break;case"td":if(r.is(".day")&&!r.is(".disabled")){var l=parseInt(r.text(),10)||1,f=this.viewDate.getUTCFullYear(),a=this.viewDate.getUTCMonth();r.is(".old")?a==0?(a=11,f-=1):a-=1:r.is(".new")&&(a==11?(a=0,f+=1):a+=1),this._setDate(t(f,a,l,0,0,0,0))}}},_setDate:function(e,t){if(!t||t=="date")this.date=e;if(!t||t=="view")this.viewDate=e;this.fill(),this.setValue(),this.element.trigger({type:"changeDate",date:this.date});var n;this.isInput?n=this.element:this.component&&(n=this.element.find("input")),n&&(n.change(),this.autoclose&&this.hide())},moveMonth:function(e,t){if(!t)return e;var n=new Date(e.valueOf()),r=n.getUTCDate(),i=n.getUTCMonth(),s=Math.abs(t),o,u;t=t>0?1:-1;if(s==1){u=t==-1?function(){return n.getUTCMonth()==i}:function(){return n.getUTCMonth()!=o},o=i+t,n.setUTCMonth(o);if(o<0||o>11)o=(o+12)%12}else{for(var a=0;a<s;a++)n=this.moveMonth(n,t);o=n.getUTCMonth(),n.setUTCDate(r),u=function(){return o!=n.getUTCMonth()}}while(u())n.setUTCDate(--r),n.setUTCMonth(o);return n},moveYear:function(e,t){return this.moveMonth(e,t*12)},dateWithinRange:function(e){return e>=this.startDate&&e<=this.endDate},keydown:function(e){if(this.picker.is(":not(:visible)")){e.keyCode==27&&this.show();return}var t=!1,n,r,i,s,o;switch(e.keyCode){case 27:this.hide(),e.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation)break;n=e.keyCode==37?-1:1,e.ctrlKey?(s=this.moveYear(this.date,n),o=this.moveYear(this.viewDate,n)):e.shiftKey?(s=this.moveMonth(this.date,n),o=this.moveMonth(this.viewDate,n)):(s=new Date(this.date),s.setUTCDate(this.date.getUTCDate()+n),o=new Date(this.viewDate),o.setUTCDate(this.viewDate.getUTCDate()+n)),this.dateWithinRange(s)&&(this.date=s,this.viewDate=o,this.setValue(),this.update(),e.preventDefault(),t=!0);break;case 38:case 40:if(!this.keyboardNavigation)break;n=e.keyCode==38?-1:1,e.ctrlKey?(s=this.moveYear(this.date,n),o=this.moveYear(this.viewDate,n)):e.shiftKey?(s=this.moveMonth(this.date,n),o=this.moveMonth(this.viewDate,n)):(s=new Date(this.date),s.setUTCDate(this.date.getUTCDate()+n*7),o=new Date(this.viewDate),o.setUTCDate(this.viewDate.getUTCDate()+n*7)),this.dateWithinRange(s)&&(this.date=s,this.viewDate=o,this.setValue(),this.update(),e.preventDefault(),t=!0);break;case 13:this.hide(),e.preventDefault();break;case 9:this.hide()}if(t){this.element.trigger({type:"changeDate",date:this.date});var u;this.isInput?u=this.element:this.component&&(u=this.element.find("input")),u&&u.change()}},showMode:function(e){e&&(this.viewMode=Math.max(0,Math.min(2,this.viewMode+e))),this.picker.find(">div").hide().filter(".datepicker-"+s.modes[this.viewMode].clsName).css("display","block"),this.updateNavArrows()}},e.fn.datepicker=function(t){var n=Array.apply(null,arguments);return n.shift(),this.each(function(){var i=e(this),s=i.data("datepicker"),o=typeof t=="object"&&t;s||i.data("datepicker",s=new r(this,e.extend({},e.fn.datepicker.defaults,o))),typeof t=="string"&&typeof s[t]=="function"&&s[t].apply(s,n)})},e.fn.datepicker.defaults={},e.fn.datepicker.Constructor=r;var i=e.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today"}},s={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(e){return e%4===0&&e%100!==0||e%400===0},getDaysInMonth:function(e,t){return[31,s.isLeapYear(e)?29:28,31,30,31,30,31,31,30,31,30,31][t]},validParts:/dd?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\r]+/g,parseFormat:function(e){var t=e.replace(this.validParts,"\0").split("\0"),n=e.match(this.validParts);if(!t||!t.length||!n||n.length==0)throw new Error("Invalid date format.");return{separators:t,parts:n}},parseDate:function(n,s,o){if(n instanceof Date)return n;if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(n)){var u=/([-+]\d+)([dmwy])/,a=n.match(/([-+]\d+)([dmwy])/g),f,l;n=new Date;for(var c=0;c<a.length;c++){f=u.exec(a[c]),l=parseInt(f[1]);switch(f[2]){case"d":n.setUTCDate(n.getUTCDate()+l);break;case"m":n=r.prototype.moveMonth.call(r.prototype,n,l);break;case"w":n.setUTCDate(n.getUTCDate()+l*7);break;case"y":n=r.prototype.moveYear.call(r.prototype,n,l)}}return t(n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate(),0,0,0)}var a=n&&n.match(this.nonpunctuation)||[],n=new Date,h={},p=["yyyy","yy","M","MM","m","mm","d","dd"],d={yyyy:function(e,t){return e.setUTCFullYear(t)},yy:function(e,t){return e.setUTCFullYear(2e3+t)},m:function(e,t){t-=1;while(t<0)t+=12;t%=12,e.setUTCMonth(t);while(e.getUTCMonth()!=t)e.setUTCDate(e.getUTCDate()-1);return e},d:function(e,t){return e.setUTCDate(t)}},v,m,f;d.M=d.MM=d.mm=d.m,d.dd=d.d,n=t(n.getFullYear(),n.getMonth(),n.getDate(),0,0,0);if(a.length==s.parts.length){for(var c=0,g=s.parts.length;c<g;c++){v=parseInt(a[c],10),f=s.parts[c];if(isNaN(v))switch(f){case"MM":m=e(i[o].months).filter(function(){var e=this.slice(0,a[c].length),t=a[c].slice(0,e.length);return e==t}),v=e.inArray(m[0],i[o].months)+1;break;case"M":m=e(i[o].monthsShort).filter(function(){var e=this.slice(0,a[c].length),t=a[c].slice(0,e.length);return e==t}),v=e.inArray(m[0],i[o].monthsShort)+1}h[f]=v}for(var c=0,y;c<p.length;c++)y=p[c],y in h&&d[y](n,h[y])}return n},formatDate:function(t,n,r){var s={d:t.getUTCDate(),m:t.getUTCMonth()+1,M:i[r].monthsShort[t.getUTCMonth()],MM:i[r].months[t.getUTCMonth()],yy:t.getUTCFullYear().toString().substring(2),yyyy:t.getUTCFullYear()};s.dd=(s.d<10?"0":"")+s.d,s.mm=(s.m<10?"0":"")+s.m;var t=[],o=e.extend([],n.separators);for(var u=0,a=n.parts.length;u<a;u++)o.length&&t.push(o.shift()),t.push(s[n.parts[u]]);return t.join("")},headTemplate:'<thead><tr><th class="prev"><i class="icon-arrow-left"/></th><th colspan="5" class="switch"></th><th class="next"><i class="icon-arrow-right"/></th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'};s.template='<div class="datepicker"><div class="datepicker-days"><table class=" table-condensed">'+s.headTemplate+"<tbody></tbody>"+s.footTemplate+"</table>"+"</div>"+'<div class="datepicker-months">'+'<table class="table-condensed">'+s.headTemplate+s.contTemplate+s.footTemplate+"</table>"+"</div>"+'<div class="datepicker-years">'+'<table class="table-condensed">'+s.headTemplate+s.contTemplate+s.footTemplate+"</table>"+"</div>"+"</div>",e.fn.datepicker.DPGlobal=s}(window.jQuery); \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable.js b/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable.js new file mode 100755 index 0000000..42a79f5 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable.js @@ -0,0 +1,3801 @@ +/*! X-editable - v1.3.0 +* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery +* http://github.com/vitalets/x-editable +* Copyright (c) 2012 Vitaliy Potapov; Licensed MIT */ + +/** +Form with single input element, two buttons and two states: normal/loading. +Applied as jQuery method to DIV tag (not to form tag!). This is because form can be in loading state when spinner shown. +Editableform is linked with one of input types, e.g. 'text', 'select' etc. + +@class editableform +@uses text +@uses textarea +**/ +(function ($) { + + var EditableForm = function (div, options) { + this.options = $.extend({}, $.fn.editableform.defaults, options); + this.$div = $(div); //div, containing form. Not form tag! Not editable-element. + if(!this.options.scope) { + this.options.scope = this; + } + this.initInput(); + }; + + EditableForm.prototype = { + constructor: EditableForm, + initInput: function() { //called once + var TypeConstructor, typeOptions; + + //create input of specified type + if(typeof $.fn.editabletypes[this.options.type] === 'function') { + TypeConstructor = $.fn.editabletypes[this.options.type]; + typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults)); + this.input = new TypeConstructor(typeOptions); + } else { + $.error('Unknown type: '+ this.options.type); + return; + } + + this.value = this.input.str2value(this.options.value); + }, + initTemplate: function() { + this.$form = $($.fn.editableform.template); + }, + initButtons: function() { + this.$form.find('.editable-buttons').append($.fn.editableform.buttons); + }, + /** + Renders editableform + + @method render + **/ + render: function() { + this.$loading = $($.fn.editableform.loading); + this.$div.empty().append(this.$loading); + this.showLoading(); + + //init form template and buttons + this.initTemplate(); + if(this.options.showbuttons) { + this.initButtons(); + } else { + this.$form.find('.editable-buttons').remove(); + } + + /** + Fired when rendering starts + @event rendering + @param {Object} event event object + **/ + this.$div.triggerHandler('rendering'); + + //render input + $.when(this.input.render()) + .then($.proxy(function () { + //input + this.$form.find('div.editable-input').append(this.input.$input); + + //automatically submit inputs when no buttons shown + if(!this.options.showbuttons) { + this.input.autosubmit(); + } + + //"clear" link + if(this.input.$clear) { + this.$form.find('div.editable-input').append($('<div class="editable-clear">').append(this.input.$clear)); + } + + //append form to container + this.$div.append(this.$form); + + //attach 'cancel' handler + this.$form.find('.editable-cancel').click($.proxy(this.cancel, this)); + + if(this.input.error) { + this.error(this.input.error); + this.$form.find('.editable-submit').attr('disabled', true); + this.input.$input.attr('disabled', true); + //prevent form from submitting + this.$form.submit(function(e){ e.preventDefault(); }); + } else { + this.error(false); + this.input.$input.removeAttr('disabled'); + this.$form.find('.editable-submit').removeAttr('disabled'); + this.input.value2input(this.value); + //attach submit handler + this.$form.submit($.proxy(this.submit, this)); + } + + /** + Fired when form is rendered + @event rendered + @param {Object} event event object + **/ + this.$div.triggerHandler('rendered'); + + this.showForm(); + }, this)); + }, + cancel: function() { + /** + Fired when form was cancelled by user + @event cancel + @param {Object} event event object + **/ + this.$div.triggerHandler('cancel'); + }, + showLoading: function() { + var w; + if(this.$form) { + //set loading size equal to form + this.$loading.width(this.$form.outerWidth()); + this.$loading.height(this.$form.outerHeight()); + this.$form.hide(); + } else { + //stretch loading to fill container width + w = this.$loading.parent().width(); + if(w) { + this.$loading.width(w); + } + } + this.$loading.show(); + }, + + showForm: function(activate) { + this.$loading.hide(); + this.$form.show(); + if(activate !== false) { + this.input.activate(); + } + /** + Fired when form is shown + @event show + @param {Object} event event object + **/ + this.$div.triggerHandler('show'); + }, + + error: function(msg) { + var $group = this.$form.find('.control-group'), + $block = this.$form.find('.editable-error-block'); + + if(msg === false) { + $group.removeClass($.fn.editableform.errorGroupClass); + $block.removeClass($.fn.editableform.errorBlockClass).empty().hide(); + } else { + $group.addClass($.fn.editableform.errorGroupClass); + $block.addClass($.fn.editableform.errorBlockClass).text(msg).show(); + } + }, + + submit: function(e) { + e.stopPropagation(); + e.preventDefault(); + + var error, + newValue = this.input.input2value(); //get new value from input + + //validation + if (error = this.validate(newValue)) { + this.error(error); + this.showForm(); + return; + } + + //if value not changed --> trigger 'nochange' event and return + /*jslint eqeq: true*/ + if (!this.options.savenochange && this.input.value2str(newValue) == this.input.value2str(this.value)) { + /*jslint eqeq: false*/ + /** + Fired when value not changed but form is submitted. Requires savenochange = false. + @event nochange + @param {Object} event event object + **/ + this.$div.triggerHandler('nochange'); + return; + } + + //sending data to server + $.when(this.save(newValue)) + .done($.proxy(function(response) { + //run success callback + var res = typeof this.options.success === 'function' ? this.options.success.call(this.options.scope, response, newValue) : null; + + //if success callback returns false --> keep form open and do not activate input + if(res === false) { + this.error(false); + this.showForm(false); + return; + } + + //if success callback returns string --> keep form open, show error and activate input + if(typeof res === 'string') { + this.error(res); + this.showForm(); + return; + } + + //if success callback returns object like {newValue: <something>} --> use that value instead of submitted + if(res && typeof res === 'object' && res.hasOwnProperty('newValue')) { + newValue = res.newValue; + } + + //clear error message + this.error(false); + this.value = newValue; + /** + Fired when form is submitted + @event save + @param {Object} event event object + @param {Object} params additional params + @param {mixed} params.newValue submitted value + @param {Object} params.response ajax response + + @example + $('#form-div').on('save'), function(e, params){ + if(params.newValue === 'username') {...} + }); + **/ + this.$div.triggerHandler('save', {newValue: newValue, response: response}); + }, this)) + .fail($.proxy(function(xhr) { + this.error(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!'); + this.showForm(); + }, this)); + }, + + save: function(newValue) { + //convert value for submitting to server + var submitValue = this.input.value2submit(newValue); + + //try parse composite pk defined as json string in data-pk + this.options.pk = $.fn.editableutils.tryParseJson(this.options.pk, true); + + var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this.options.scope) : this.options.pk, + send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk)))), + params; + + if (send) { //send to server + this.showLoading(); + + //standard params + params = { + name: this.options.name || '', + value: submitValue, + pk: pk + }; + + //additional params + if(typeof this.options.params === 'function') { + params = this.options.params.call(this.options.scope, params); + } else { + //try parse json in single quotes (from data-params attribute) + this.options.params = $.fn.editableutils.tryParseJson(this.options.params, true); + $.extend(params, this.options.params); + } + + if(typeof this.options.url === 'function') { //user's function + return this.options.url.call(this.options.scope, params); + } else { + //send ajax to server and return deferred object + return $.ajax($.extend({ + url : this.options.url, + data : params, + type : 'POST' + }, this.options.ajaxOptions)); + } + } + }, + + validate: function (value) { + if (value === undefined) { + value = this.value; + } + if (typeof this.options.validate === 'function') { + return this.options.validate.call(this.options.scope, value); + } + }, + + option: function(key, value) { + this.options[key] = value; + if(key === 'value') { + this.setValue(value); + } + }, + + setValue: function(value, convertStr) { + if(convertStr) { + this.value = this.input.str2value(value); + } else { + this.value = value; + } + } + }; + + /* + Initialize editableform. Applied to jQuery object. + + @method $().editableform(options) + @params {Object} options + @example + var $form = $('&lt;div&gt;').editableform({ + type: 'text', + name: 'username', + url: '/post', + value: 'vitaliy' + }); + + //to display form you should call 'render' method + $form.editableform('render'); + */ + $.fn.editableform = function (option) { + var args = arguments; + return this.each(function () { + var $this = $(this), + data = $this.data('editableform'), + options = typeof option === 'object' && option; + if (!data) { + $this.data('editableform', (data = new EditableForm(this, options))); + } + + if (typeof option === 'string') { //call method + data[option].apply(data, Array.prototype.slice.call(args, 1)); + } + }); + }; + + //keep link to constructor to allow inheritance + $.fn.editableform.Constructor = EditableForm; + + //defaults + $.fn.editableform.defaults = { + /* see also defaults for input */ + + /** + Type of input. Can be <code>text|textarea|select|date|checklist</code> + + @property type + @type string + @default 'text' + **/ + type: 'text', + /** + Url for submit, e.g. <code>'/post'</code> + If function - it will be called instead of ajax. Function can return deferred object to run fail/done callbacks. + + @property url + @type string|function + @default null + @example + url: function(params) { + if(params.value === 'abc') { + var d = new $.Deferred; + return d.reject('field cannot be "abc"'); //returning error via deferred object + } else { + someModel.set(params.name, params.value); //save data in some js model + } + } + **/ + url:null, + /** + Additional params for submit. If defined as <code>object</code> - it is **appended** to original ajax data (pk, name and value). + If defined as <code>function</code> - returned object **overwrites** original ajax data. + @example + params: function(params) { + //originally params contain pk, name and value + params.a = 1; + return params; + } + + @property params + @type object|function + @default null + **/ + params:null, + /** + Name of field. Will be submitted on server. Can be taken from <code>id</code> attribute + + @property name + @type string + @default null + **/ + name: null, + /** + Primary key of editable object (e.g. record id in database). For composite keys use object, e.g. <code>{id: 1, lang: 'en'}</code>. + Can be calculated dynamically via function. + + @property pk + @type string|object|function + @default null + **/ + pk: null, + /** + Initial value. If not defined - will be taken from element's content. + For __select__ type should be defined (as it is ID of shown text). + + @property value + @type string|object + @default null + **/ + value: null, + /** + Strategy for sending data on server. Can be <code>auto|always|never</code>. + When 'auto' data will be sent on server only if pk defined, otherwise new value will be stored in element. + + @property send + @type string + @default 'auto' + **/ + send: 'auto', + /** + Function for client-side validation. If returns string - means validation not passed and string showed as error. + + @property validate + @type function + @default null + @example + validate: function(value) { + if($.trim(value) == '') { + return 'This field is required'; + } + } + **/ + validate: null, + /** + Success callback. Called when value successfully sent on server and **response status = 200**. + Useful to work with json response. For example, if your backend response can be <code>{success: true}</code> + or <code>{success: false, msg: "server error"}</code> you can check it inside this callback. + If it returns **string** - means error occured and string is shown as error message. + If it returns **object like** <code>{newValue: &lt;something&gt;}</code> - it overwrites value, submitted by user. + Otherwise newValue simply rendered into element. + + @property success + @type function + @default null + @example + success: function(response, newValue) { + if(!response.success) return response.msg; + } + **/ + success: null, + /** + Additional options for ajax request. + List of values: http://api.jquery.com/jQuery.ajax + + @property ajaxOptions + @type object + @default null + @since 1.1.1 + **/ + ajaxOptions: null, + /** + Whether to show buttons or not. + Form without buttons can be auto-submitted by input or by onblur = 'submit'. + @example + ajaxOptions: { + method: 'PUT', + dataType: 'xml' + } + + @property showbuttons + @type boolean + @default true + @since 1.1.1 + **/ + showbuttons: true, + /** + Scope for callback methods (success, validate). + If <code>null</code> means editableform instance itself. + + @property scope + @type DOMElement|object + @default null + @since 1.2.0 + @private + **/ + scope: null, + /** + Whether to save or cancel value when it was not changed but form was submitted + + @property savenochange + @type boolean + @default false + @since 1.2.0 + **/ + savenochange: false + }; + + /* + Note: following params could redefined in engine: bootstrap or jqueryui: + Classes 'control-group' and 'editable-error-block' must always present! + */ + $.fn.editableform.template = '<form class="form-inline editableform">'+ + '<div class="control-group">' + + '<div><div class="editable-input"></div><div class="editable-buttons"></div></div>'+ + '<div class="editable-error-block"></div>' + + '</div>' + + '</form>'; + + //loading div + $.fn.editableform.loading = '<div class="editableform-loading"></div>'; + + //buttons + $.fn.editableform.buttons = '<button type="submit" class="editable-submit">ok</button>'+ + '<button type="button" class="editable-cancel">cancel</button>'; + + //error class attached to control-group + $.fn.editableform.errorGroupClass = null; + + //error class attached to editable-error-block + $.fn.editableform.errorBlockClass = 'editable-error'; +}(window.jQuery)); +/** +* EditableForm utilites +*/ +(function ($) { + //utils + $.fn.editableutils = { + /** + * classic JS inheritance function + */ + inherit: function (Child, Parent) { + var F = function() { }; + F.prototype = Parent.prototype; + Child.prototype = new F(); + Child.prototype.constructor = Child; + Child.superclass = Parent.prototype; + }, + + /** + * set caret position in input + * see http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area + */ + setCursorPosition: function(elem, pos) { + if (elem.setSelectionRange) { + elem.setSelectionRange(pos, pos); + } else if (elem.createTextRange) { + var range = elem.createTextRange(); + range.collapse(true); + range.moveEnd('character', pos); + range.moveStart('character', pos); + range.select(); + } + }, + + /** + * function to parse JSON in *single* quotes. (jquery automatically parse only double quotes) + * That allows such code as: <a data-source="{'a': 'b', 'c': 'd'}"> + * safe = true --> means no exception will be thrown + * for details see http://stackoverflow.com/questions/7410348/how-to-set-json-format-to-html5-data-attributes-in-the-jquery + */ + tryParseJson: function(s, safe) { + if (typeof s === 'string' && s.length && s.match(/^[\{\[].*[\}\]]$/)) { + if (safe) { + try { + /*jslint evil: true*/ + s = (new Function('return ' + s))(); + /*jslint evil: false*/ + } catch (e) {} finally { + return s; + } + } else { + /*jslint evil: true*/ + s = (new Function('return ' + s))(); + /*jslint evil: false*/ + } + } + return s; + }, + + /** + * slice object by specified keys + */ + sliceObj: function(obj, keys, caseSensitive /* default: false */) { + var key, keyLower, newObj = {}; + + if (!$.isArray(keys) || !keys.length) { + return newObj; + } + + for (var i = 0; i < keys.length; i++) { + key = keys[i]; + if (obj.hasOwnProperty(key)) { + newObj[key] = obj[key]; + } + + if(caseSensitive === true) { + continue; + } + + //when getting data-* attributes via $.data() it's converted to lowercase. + //details: http://stackoverflow.com/questions/7602565/using-data-attributes-with-jquery + //workaround is code below. + keyLower = key.toLowerCase(); + if (obj.hasOwnProperty(keyLower)) { + newObj[key] = obj[keyLower]; + } + } + + return newObj; + }, + + /** + * exclude complex objects from $.data() before pass to config + */ + getConfigData: function($element) { + var data = {}; + $.each($element.data(), function(k, v) { + if(typeof v !== 'object' || (v && typeof v === 'object' && v.constructor === Object)) { + data[k] = v; + } + }); + return data; + }, + + objectKeys: function(o) { + if (Object.keys) { + return Object.keys(o); + } else { + if (o !== Object(o)) { + throw new TypeError('Object.keys called on a non-object'); + } + var k=[], p; + for (p in o) { + if (Object.prototype.hasOwnProperty.call(o,p)) { + k.push(p); + } + } + return k; + } + + }, + + /** + method to escape html. + **/ + escape: function(str) { + return $('<div>').text(str).html(); + } + }; +}(window.jQuery)); +/** +Attaches stand-alone container with editable-form to HTML element. Element is used only for positioning, value is not stored anywhere.<br> +This method applied internally in <code>$().editable()</code>. You should subscribe on it's events (save / cancel) to get profit of it.<br> +Final realization can be different: bootstrap-popover, jqueryui-tooltip, poshytip, inline-div. It depends on which js file you include.<br> +Applied as jQuery method. + +@class editableContainer +@uses editableform +**/ +(function ($) { + + var EditableContainer = function (element, options) { + this.init(element, options); + }; + + //methods + EditableContainer.prototype = { + containerName: null, //tbd in child class + innerCss: null, //tbd in child class + init: function(element, options) { + this.$element = $(element); + //todo: what is in priority: data or js? + this.options = $.extend({}, $.fn.editableContainer.defaults, $.fn.editableutils.getConfigData(this.$element), options); + this.splitOptions(); + this.initContainer(); + + //bind 'destroyed' listener to destroy container when element is removed from dom + this.$element.on('destroyed', $.proxy(function(){ + this.destroy(); + }, this)); + + //attach document handlers (once) + if(!$(document).data('editable-handlers-attached')) { + //close all on escape + $(document).on('keyup.editable', function (e) { + if (e.which === 27) { + $('.editable-open').editableContainer('hide'); + //todo: return focus on element + } + }); + + //close containers when click outside + $(document).on('click.editable', function(e) { + var $target = $(e.target); + + //if click inside some editableContainer --> no nothing + if($target.is('.editable-container') || $target.parents('.editable-container').length || $target.parents('.ui-datepicker-header').length) { + return; + } else { + //close all open containers (except one) + EditableContainer.prototype.closeOthers(e.target); + } + }); + + $(document).data('editable-handlers-attached', true); + } + }, + + //split options on containerOptions and formOptions + splitOptions: function() { + this.containerOptions = {}; + this.formOptions = {}; + var cDef = $.fn[this.containerName].defaults; + for(var k in this.options) { + if(k in cDef) { + this.containerOptions[k] = this.options[k]; + } else { + this.formOptions[k] = this.options[k]; + } + } + }, + + initContainer: function(){ + this.call(this.containerOptions); + }, + + initForm: function() { + this.formOptions.scope = this.$element[0]; //set scope of form callbacks to element + this.$form = $('<div>') + .editableform(this.formOptions) + .on({ + save: $.proxy(this.save, this), + cancel: $.proxy(function(){ this.hide('cancel'); }, this), + nochange: $.proxy(function(){ this.hide('nochange'); }, this), + show: $.proxy(this.setPosition, this), //re-position container every time form is shown (occurs each time after loading state) + rendering: $.proxy(this.setPosition, this), //this allows to place container correctly when loading shown + rendered: $.proxy(function(){ + /** + Fired when container is shown and form is rendered (for select will wait for loading dropdown options) + + @event shown + @param {Object} event event object + @example + $('#username').on('shown', function() { + var $tip = $(this).data('editableContainer').tip(); + $tip.find('input').val('overwriting value of input..'); + }); + **/ + this.$element.triggerHandler('shown'); + }, this) + }); + return this.$form; + }, + + /* + Returns jquery object of container + @method tip() + */ + tip: function() { + return this.container().$tip; + }, + + container: function() { + return this.$element.data(this.containerName); + }, + + call: function() { + this.$element[this.containerName].apply(this.$element, arguments); + }, + + /** + Shows container with form + @method show() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + show: function (closeAll) { + this.$element.addClass('editable-open'); + if(closeAll !== false) { + //close all open containers (except this) + this.closeOthers(this.$element[0]); + } + + this.innerShow(); + }, + + /* internal show method. To be overwritten in child classes */ + innerShow: function () { + this.call('show'); + this.tip().addClass('editable-container'); + this.initForm(); + this.tip().find(this.innerCss).empty().append(this.$form); + this.$form.editableform('render'); + }, + + /** + Hides container with form + @method hide() + @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|undefined (=manual)</code> + **/ + hide: function(reason) { + if(!this.tip() || !this.tip().is(':visible') || !this.$element.hasClass('editable-open')) { + return; + } + this.$element.removeClass('editable-open'); + this.innerHide(); + /** + Fired when container was hidden. It occurs on both save or cancel. + + @event hidden + @param {object} event event object + @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|undefined (=manual)</code> + @example + $('#username').on('hidden', function(e, reason) { + if(reason === 'save' || reason === 'cancel') { + //auto-open next editable + $(this).closest('tr').next().find('.editable').editable('show'); + } + }); + **/ + this.$element.triggerHandler('hidden', reason); + }, + + /* internal hide method. To be overwritten in child classes */ + innerHide: function () { + this.call('hide'); + }, + + /** + Toggles container visibility (show / hide) + @method toggle() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + toggle: function(closeAll) { + if(this.tip && this.tip().is(':visible')) { + this.hide(); + } else { + this.show(closeAll); + } + }, + + /* + Updates the position of container when content changed. + @method setPosition() + */ + setPosition: function() { + //tbd in child class + }, + + save: function(e, params) { + this.hide('save'); + /** + Fired when new value was submitted. You can use <code>$(this).data('editableContainer')</code> inside handler to access to editableContainer instance + + @event save + @param {Object} event event object + @param {Object} params additional params + @param {mixed} params.newValue submitted value + @param {Object} params.response ajax response + @example + $('#username').on('save', function(e, params) { + //assuming server response: '{success: true}' + var pk = $(this).data('editableContainer').options.pk; + if(params.response && params.response.success) { + alert('value: ' + params.newValue + ' with pk: ' + pk + ' saved!'); + } else { + alert('error!'); + } + }); + **/ + this.$element.triggerHandler('save', params); + }, + + /** + Sets new option + + @method option(key, value) + @param {string} key + @param {mixed} value + **/ + option: function(key, value) { + this.options[key] = value; + if(key in this.containerOptions) { + this.containerOptions[key] = value; + this.setContainerOption(key, value); + } else { + this.formOptions[key] = value; + if(this.$form) { + this.$form.editableform('option', key, value); + } + } + }, + + setContainerOption: function(key, value) { + this.call('option', key, value); + }, + + /** + Destroys the container instance + @method destroy() + **/ + destroy: function() { + this.call('destroy'); + }, + + /* + Closes other containers except one related to passed element. + Other containers can be cancelled or submitted (depends on onblur option) + */ + closeOthers: function(element) { + $('.editable-open').each(function(i, el){ + //do nothing with passed element and it's children + if(el === element || $(el).find(element).length) { + return; + } + + //otherwise cancel or submit all open containers + var $el = $(el), + ec = $el.data('editableContainer'); + + if(!ec) { + return; + } + + if(ec.options.onblur === 'cancel') { + $el.data('editableContainer').hide('onblur'); + } else if(ec.options.onblur === 'submit') { + $el.data('editableContainer').tip().find('form').submit(); + } + }); + + }, + + /** + Activates input of visible container (e.g. set focus) + @method activate() + **/ + activate: function() { + if(this.tip && this.tip().is(':visible') && this.$form) { + this.$form.data('editableform').input.activate(); + } + } + + }; + + /** + jQuery method to initialize editableContainer. + + @method $().editableContainer(options) + @params {Object} options + @example + $('#edit').editableContainer({ + type: 'text', + url: '/post', + pk: 1, + value: 'hello' + }); + **/ + $.fn.editableContainer = function (option) { + var args = arguments; + return this.each(function () { + var $this = $(this), + dataKey = 'editableContainer', + data = $this.data(dataKey), + options = typeof option === 'object' && option; + + if (!data) { + $this.data(dataKey, (data = new EditableContainer(this, options))); + } + + if (typeof option === 'string') { //call method + data[option].apply(data, Array.prototype.slice.call(args, 1)); + } + }); + }; + + //store constructor + $.fn.editableContainer.Constructor = EditableContainer; + + //defaults + $.fn.editableContainer.defaults = { + /** + Initial value of form input + + @property value + @type mixed + @default null + @private + **/ + value: null, + /** + Placement of container relative to element. Can be <code>top|right|bottom|left</code>. Not used for inline container. + + @property placement + @type string + @default 'top' + **/ + placement: 'top', + /** + Whether to hide container on save/cancel. + + @property autohide + @type boolean + @default true + @private + **/ + autohide: true, + /** + Action when user clicks outside the container. Can be <code>cancel|submit|ignore</code>. + Setting <code>ignore</code> allows to have several containers open. + + @property onblur + @type string + @default 'cancel' + @since 1.1.1 + **/ + onblur: 'cancel' + }; + + /* + * workaround to have 'destroyed' event to destroy popover when element is destroyed + * see http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom + */ + jQuery.event.special.destroyed = { + remove: function(o) { + if (o.handler) { + o.handler(); + } + } + }; + +}(window.jQuery)); + +/** +Makes editable any HTML element on the page. Applied as jQuery method. + +@class editable +@uses editableContainer +**/ +(function ($) { + + var Editable = function (element, options) { + this.$element = $(element); + this.options = $.extend({}, $.fn.editable.defaults, $.fn.editableutils.getConfigData(this.$element), options); + this.init(); + }; + + Editable.prototype = { + constructor: Editable, + init: function () { + var TypeConstructor, + isValueByText = false, + doAutotext, + finalize; + + //editableContainer must be defined + if(!$.fn.editableContainer) { + $.error('You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)'); + return; + } + + //name + this.options.name = this.options.name || this.$element.attr('id'); + + //create input of specified type. Input will be used for converting value, not in form + if(typeof $.fn.editabletypes[this.options.type] === 'function') { + TypeConstructor = $.fn.editabletypes[this.options.type]; + this.typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults)); + this.input = new TypeConstructor(this.typeOptions); + } else { + $.error('Unknown type: '+ this.options.type); + return; + } + + //set value from settings or by element's text + if (this.options.value === undefined || this.options.value === null) { + this.value = this.input.html2value($.trim(this.$element.html())); + isValueByText = true; + } else { + /* + value can be string when received from 'data-value' attribute + for complext objects value can be set as json string in data-value attribute, + e.g. data-value="{city: 'Moscow', street: 'Lenina'}" + */ + this.options.value = $.fn.editableutils.tryParseJson(this.options.value, true); + if(typeof this.options.value === 'string') { + this.value = this.input.str2value(this.options.value); + } else { + this.value = this.options.value; + } + } + + //add 'editable' class to every editable element + this.$element.addClass('editable'); + + //attach handler activating editable. In disabled mode it just prevent default action (useful for links) + if(this.options.toggle !== 'manual') { + this.$element.addClass('editable-click'); + this.$element.on(this.options.toggle + '.editable', $.proxy(function(e){ + e.preventDefault(); + //stop propagation not required anymore because in document click handler it checks event target + //e.stopPropagation(); + + if(this.options.toggle === 'mouseenter') { + //for hover only show container + this.show(); + } else { + //when toggle='click' we should not close all other containers as they will be closed automatically in document click listener + var closeAll = (this.options.toggle !== 'click'); + this.toggle(closeAll); + } + }, this)); + } else { + this.$element.attr('tabindex', -1); //do not stop focus on element when toggled manually + } + + //check conditions for autotext: + //if value was generated by text or value is empty, no sense to run autotext + doAutotext = !isValueByText && this.value !== null && this.value !== undefined; + doAutotext &= (this.options.autotext === 'always') || (this.options.autotext === 'auto' && !this.$element.text().length); + $.when(doAutotext ? this.render() : true).then($.proxy(function() { + if(this.options.disabled) { + this.disable(); + } else { + this.enable(); + } + /** + Fired when element was initialized by editable method. + + @event init + @param {Object} event event object + @param {Object} editable editable instance + @since 1.2.0 + **/ + this.$element.triggerHandler('init', this); + }, this)); + }, + + /* + Renders value into element's text. + Can call custom display method from options. + Can return deferred object. + @method render() + */ + render: function() { + //do not display anything + if(this.options.display === false) { + return; + } + //if it is input with source, we pass callback in third param to be called when source is loaded + if(this.input.options.hasOwnProperty('source')) { + return this.input.value2html(this.value, this.$element[0], this.options.display); + //if display method defined --> use it + } else if(typeof this.options.display === 'function') { + return this.options.display.call(this.$element[0], this.value); + //else use input's original value2html() method + } else { + return this.input.value2html(this.value, this.$element[0]); + } + }, + + /** + Enables editable + @method enable() + **/ + enable: function() { + this.options.disabled = false; + this.$element.removeClass('editable-disabled'); + this.handleEmpty(); + if(this.options.toggle !== 'manual') { + if(this.$element.attr('tabindex') === '-1') { + this.$element.removeAttr('tabindex'); + } + } + }, + + /** + Disables editable + @method disable() + **/ + disable: function() { + this.options.disabled = true; + this.hide(); + this.$element.addClass('editable-disabled'); + this.handleEmpty(); + //do not stop focus on this element + this.$element.attr('tabindex', -1); + }, + + /** + Toggles enabled / disabled state of editable element + @method toggleDisabled() + **/ + toggleDisabled: function() { + if(this.options.disabled) { + this.enable(); + } else { + this.disable(); + } + }, + + /** + Sets new option + + @method option(key, value) + @param {string|object} key option name or object with several options + @param {mixed} value option new value + @example + $('.editable').editable('option', 'pk', 2); + **/ + option: function(key, value) { + //set option(s) by object + if(key && typeof key === 'object') { + $.each(key, $.proxy(function(k, v){ + this.option($.trim(k), v); + }, this)); + return; + } + + //set option by string + this.options[key] = value; + + //disabled + if(key === 'disabled') { + if(value) { + this.disable(); + } else { + this.enable(); + } + return; + } + + //value + if(key === 'value') { + this.setValue(value); + } + + //transfer new option to container! + if(this.container) { + this.container.option(key, value); + } + }, + + /* + * set emptytext if element is empty (reverse: remove emptytext if needed) + */ + handleEmpty: function () { + //do not handle empty if we do not display anything + if(this.options.display === false) { + return; + } + + var emptyClass = 'editable-empty'; + //emptytext shown only for enabled + if(!this.options.disabled) { + if ($.trim(this.$element.text()) === '') { + this.$element.addClass(emptyClass).text(this.options.emptytext); + } else { + this.$element.removeClass(emptyClass); + } + } else { + //below required if element disable property was changed + if(this.$element.hasClass(emptyClass)) { + this.$element.empty(); + this.$element.removeClass(emptyClass); + } + } + }, + + /** + Shows container with form + @method show() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + show: function (closeAll) { + if(this.options.disabled) { + return; + } + + //init editableContainer: popover, tooltip, inline, etc.. + if(!this.container) { + var containerOptions = $.extend({}, this.options, { + value: this.value + }); + this.$element.editableContainer(containerOptions); + this.$element.on("save.internal", $.proxy(this.save, this)); + this.container = this.$element.data('editableContainer'); + } else if(this.container.tip().is(':visible')) { + return; + } + + //show container + this.container.show(closeAll); + }, + + /** + Hides container with form + @method hide() + **/ + hide: function () { + if(this.container) { + this.container.hide(); + } + }, + + /** + Toggles container visibility (show / hide) + @method toggle() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + toggle: function(closeAll) { + if(this.container && this.container.tip().is(':visible')) { + this.hide(); + } else { + this.show(closeAll); + } + }, + + /* + * called when form was submitted + */ + save: function(e, params) { + //if url is not user's function and value was not sent to server and value changed --> mark element with unsaved css. + if(typeof this.options.url !== 'function' && this.options.display !== false && params.response === undefined && this.input.value2str(this.value) !== this.input.value2str(params.newValue)) { + this.$element.addClass('editable-unsaved'); + } else { + this.$element.removeClass('editable-unsaved'); + } + + // this.hide(); + this.setValue(params.newValue); + + /** + Fired when new value was submitted. You can use <code>$(this).data('editable')</code> to access to editable instance + + @event save + @param {Object} event event object + @param {Object} params additional params + @param {mixed} params.newValue submitted value + @param {Object} params.response ajax response + @example + $('#username').on('save', function(e, params) { + //assuming server response: '{success: true}' + var pk = $(this).data('editable').options.pk; + if(params.response && params.response.success) { + alert('value: ' + params.newValue + ' with pk: ' + pk + ' saved!'); + } else { + alert('error!'); + } + }); + **/ + //event itself is triggered by editableContainer. Description here is only for documentation + }, + + validate: function () { + if (typeof this.options.validate === 'function') { + return this.options.validate.call(this, this.value); + } + }, + + /** + Sets new value of editable + @method setValue(value, convertStr) + @param {mixed} value new value + @param {boolean} convertStr whether to convert value from string to internal format + **/ + setValue: function(value, convertStr) { + if(convertStr) { + this.value = this.input.str2value(value); + } else { + this.value = value; + } + if(this.container) { + this.container.option('value', this.value); + } + $.when(this.render()) + .then($.proxy(function() { + this.handleEmpty(); + }, this)); + }, + + /** + Activates input of visible container (e.g. set focus) + @method activate() + **/ + activate: function() { + if(this.container) { + this.container.activate(); + } + } + }; + + /* EDITABLE PLUGIN DEFINITION + * ======================= */ + + /** + jQuery method to initialize editable element. + + @method $().editable(options) + @params {Object} options + @example + $('#username').editable({ + type: 'text', + url: '/post', + pk: 1 + }); + **/ + $.fn.editable = function (option) { + //special API methods returning non-jquery object + var result = {}, args = arguments, datakey = 'editable'; + switch (option) { + /** + Runs client-side validation for all matched editables + + @method validate() + @returns {Object} validation errors map + @example + $('#username, #fullname').editable('validate'); + // possible result: + { + username: "username is required", + fullname: "fullname should be minimum 3 letters length" + } + **/ + case 'validate': + this.each(function () { + var $this = $(this), data = $this.data(datakey), error; + if (data && (error = data.validate())) { + result[data.options.name] = error; + } + }); + return result; + + /** + Returns current values of editable elements. If value is <code>null</code> or <code>undefined</code> it will not be returned + @method getValue() + @returns {Object} object of element names and values + @example + $('#username, #fullname').editable('validate'); + // possible result: + { + username: "superuser", + fullname: "John" + } + **/ + case 'getValue': + this.each(function () { + var $this = $(this), data = $this.data(datakey); + if (data && data.value !== undefined && data.value !== null) { + result[data.options.name] = data.input.value2submit(data.value); + } + }); + return result; + + /** + This method collects values from several editable elements and submit them all to server. + Internally it runs client-side validation for all fields and submits only in case of success. + See <a href="#newrecord">creating new records</a> for details. + + @method submit(options) + @param {object} options + @param {object} options.url url to submit data + @param {object} options.data additional data to submit + @param {object} options.ajaxOptions additional ajax options + @param {function} options.error(obj) error handler + @param {function} options.success(obj,config) success handler + @returns {Object} jQuery object + **/ + case 'submit': //collects value, validate and submit to server for creating new record + var config = arguments[1] || {}, + $elems = this, + errors = this.editable('validate'), + values; + + if($.isEmptyObject(errors)) { + values = this.editable('getValue'); + if(config.data) { + $.extend(values, config.data); + } + + $.ajax($.extend({ + url: config.url, + data: values, + type: 'POST' + }, config.ajaxOptions)) + .success(function(response) { + //successful response 200 OK + if(typeof config.success === 'function') { + config.success.call($elems, response, config); + } + }) + .error(function(){ //ajax error + if(typeof config.error === 'function') { + config.error.apply($elems, arguments); + } + }); + } else { //client-side validation error + if(typeof config.error === 'function') { + config.error.call($elems, errors); + } + } + return this; + } + + //return jquery object + return this.each(function () { + var $this = $(this), + data = $this.data(datakey), + options = typeof option === 'object' && option; + + if (!data) { + $this.data(datakey, (data = new Editable(this, options))); + } + + if (typeof option === 'string') { //call method + data[option].apply(data, Array.prototype.slice.call(args, 1)); + } + }); + }; + + + $.fn.editable.defaults = { + /** + Type of input. Can be <code>text|textarea|select|date|checklist</code> and more + + @property type + @type string + @default 'text' + **/ + type: 'text', + /** + Sets disabled state of editable + + @property disabled + @type boolean + @default false + **/ + disabled: false, + /** + How to toggle editable. Can be <code>click|dblclick|mouseenter|manual</code>. + When set to <code>manual</code> you should manually call <code>show/hide</code> methods of editable. + **Note**: if you call <code>show</code> or <code>toggle</code> inside **click** handler of some DOM element, + you need to apply <code>e.stopPropagation()</code> because containers are being closed on any click on document. + + @example + $('#edit-button').click(function(e) { + e.stopPropagation(); + $('#username').editable('toggle'); + }); + + @property toggle + @type string + @default 'click' + **/ + toggle: 'click', + /** + Text shown when element is empty. + + @property emptytext + @type string + @default 'Empty' + **/ + emptytext: 'Empty', + /** + Allows to automatically set element's text based on it's value. Can be <code>auto|always|never</code>. Useful for select and date. + For example, if dropdown list is <code>{1: 'a', 2: 'b'}</code> and element's value set to <code>1</code>, it's html will be automatically set to <code>'a'</code>. + <code>auto</code> - text will be automatically set only if element is empty. + <code>always|never</code> - always(never) try to set element's text. + + @property autotext + @type string + @default 'auto' + **/ + autotext: 'auto', + /** + Initial value of input. Taken from <code>data-value</code> or element's text. + + @property value + @type mixed + @default element's text + **/ + value: null, + /** + Callback to perform custom displaying of value in element's text. + If <code>null</code>, default input's value2html() will be called. + If <code>false</code>, no displaying methods will be called, element's text will no change. + Runs under element's scope. + Second parameter __sourceData__ is passed for inputs with source (select, checklist). + + @property display + @type function|boolean + @default null + @since 1.2.0 + @example + display: function(value, sourceData) { + var escapedValue = $('<div>').text(value).html(); + $(this).html('<b>'+escapedValue+'</b>'); + } + **/ + display: null + }; + +}(window.jQuery)); + +/** +AbstractInput - base class for all editable inputs. +It defines interface to be implemented by any input type. +To create your own input you can inherit from this class. + +@class abstractinput +**/ +(function ($) { + + //types + $.fn.editabletypes = {}; + + var AbstractInput = function () { }; + + AbstractInput.prototype = { + /** + Initializes input + + @method init() + **/ + init: function(type, options, defaults) { + this.type = type; + this.options = $.extend({}, defaults, options); + this.$input = null; + this.$clear = null; + this.error = null; + }, + + /** + Renders input from tpl. Can return jQuery deferred object. + + @method render() + **/ + render: function() { + this.$input = $(this.options.tpl); + if(this.options.inputclass) { + this.$input.addClass(this.options.inputclass); + } + + if (this.options.placeholder) { + this.$input.attr('placeholder', this.options.placeholder); + } + }, + + /** + Sets element's html by value. + + @method value2html(value, element) + @param {mixed} value + @param {DOMElement} element + **/ + value2html: function(value, element) { + $(element).text(value); + }, + + /** + Converts element's html to value + + @method html2value(html) + @param {string} html + @returns {mixed} + **/ + html2value: function(html) { + return $('<div>').html(html).text(); + }, + + /** + Converts value to string (for internal compare). For submitting to server used value2submit(). + + @method value2str(value) + @param {mixed} value + @returns {string} + **/ + value2str: function(value) { + return value; + }, + + /** + Converts string received from server into value. + + @method str2value(str) + @param {string} str + @returns {mixed} + **/ + str2value: function(str) { + return str; + }, + + /** + Converts value for submitting to server + + @method value2submit(value) + @param {mixed} value + @returns {mixed} + **/ + value2submit: function(value) { + return value; + }, + + /** + Sets value of input. + + @method value2input(value) + @param {mixed} value + **/ + value2input: function(value) { + this.$input.val(value); + }, + + /** + Returns value of input. Value can be object (e.g. datepicker) + + @method input2value() + **/ + input2value: function() { + return this.$input.val(); + }, + + /** + Activates input. For text it sets focus. + + @method activate() + **/ + activate: function() { + if(this.$input.is(':visible')) { + this.$input.focus(); + } + }, + + /** + Creates input. + + @method clear() + **/ + clear: function() { + this.$input.val(null); + }, + + /** + method to escape html. + **/ + escape: function(str) { + return $('<div>').text(str).html(); + }, + + /** + attach handler to automatically submit form when value changed (useful when buttons not shown) + **/ + autosubmit: function() { + + } + }; + + AbstractInput.defaults = { + /** + HTML template of input. Normally you should not change it. + + @property tpl + @type string + @default '' + **/ + tpl: '', + /** + CSS class automatically applied to input + + @property inputclass + @type string + @default input-medium + **/ + inputclass: 'input-medium', + /** + Name attribute of input + + @property name + @type string + @default null + **/ + name: null + }; + + $.extend($.fn.editabletypes, {abstractinput: AbstractInput}); + +}(window.jQuery)); + +/** +List - abstract class for inputs that have source option loaded from js array or via ajax + +@class list +@extends abstractinput +**/ +(function ($) { + + var List = function (options) { + + }; + + $.fn.editableutils.inherit(List, $.fn.editabletypes.abstractinput); + + $.extend(List.prototype, { + render: function () { + List.superclass.render.call(this); + var deferred = $.Deferred(); + this.error = null; + this.sourceData = null; + this.prependData = null; + this.onSourceReady(function () { + this.renderList(); + deferred.resolve(); + }, function () { + this.error = this.options.sourceError; + deferred.resolve(); + }); + + return deferred.promise(); + }, + + html2value: function (html) { + return null; //can't set value by text + }, + + value2html: function (value, element, display) { + var deferred = $.Deferred(); + this.onSourceReady(function () { + if(typeof display === 'function') { + //custom display method + display.call(element, value, this.sourceData); + } else { + this.value2htmlFinal(value, element); + } + deferred.resolve(); + }, function () { + //do nothing with element + deferred.resolve(); + }); + + return deferred.promise(); + }, + + // ------------- additional functions ------------ + + onSourceReady: function (success, error) { + //if allready loaded just call success + if($.isArray(this.sourceData)) { + success.call(this); + return; + } + + // try parse json in single quotes (for double quotes jquery does automatically) + try { + this.options.source = $.fn.editableutils.tryParseJson(this.options.source, false); + } catch (e) { + error.call(this); + return; + } + + //loading from url + if (typeof this.options.source === 'string') { + //try to get from cache + if(this.options.sourceCache) { + var cacheID = this.options.source + (this.options.name ? '-' + this.options.name : ''), + cache; + + if (!$(document).data(cacheID)) { + $(document).data(cacheID, {}); + } + cache = $(document).data(cacheID); + + //check for cached data + if (cache.loading === false && cache.sourceData) { //take source from cache + this.sourceData = cache.sourceData; + success.call(this); + return; + } else if (cache.loading === true) { //cache is loading, put callback in stack to be called later + cache.callbacks.push($.proxy(function () { + this.sourceData = cache.sourceData; + success.call(this); + }, this)); + + //also collecting error callbacks + cache.err_callbacks.push($.proxy(error, this)); + return; + } else { //no cache yet, activate it + cache.loading = true; + cache.callbacks = []; + cache.err_callbacks = []; + } + } + + //loading sourceData from server + $.ajax({ + url: this.options.source, + type: 'get', + cache: false, + data: this.options.name ? {name: this.options.name} : {}, + dataType: 'json', + success: $.proxy(function (data) { + if(cache) { + cache.loading = false; + } + this.sourceData = this.makeArray(data); + if($.isArray(this.sourceData)) { + this.doPrepend(); + success.call(this); + if(cache) { + //store result in cache + cache.sourceData = this.sourceData; + $.each(cache.callbacks, function () { this.call(); }); //run success callbacks for other fields + } + } else { + error.call(this); + if(cache) { + $.each(cache.err_callbacks, function () { this.call(); }); //run error callbacks for other fields + } + } + }, this), + error: $.proxy(function () { + error.call(this); + if(cache) { + cache.loading = false; + //run error callbacks for other fields + $.each(cache.err_callbacks, function () { this.call(); }); + } + }, this) + }); + } else { //options as json/array + this.sourceData = this.makeArray(this.options.source); + if($.isArray(this.sourceData)) { + this.doPrepend(); + success.call(this); + } else { + error.call(this); + } + } + }, + + doPrepend: function () { + if(this.options.prepend === null || this.options.prepend === undefined) { + return; + } + + if(!$.isArray(this.prependData)) { + //try parse json in single quotes + this.options.prepend = $.fn.editableutils.tryParseJson(this.options.prepend, true); + if (typeof this.options.prepend === 'string') { + this.options.prepend = {'': this.options.prepend}; + } + this.prependData = this.makeArray(this.options.prepend); + } + + if($.isArray(this.prependData) && $.isArray(this.sourceData)) { + this.sourceData = this.prependData.concat(this.sourceData); + } + }, + + /* + renders input list + */ + renderList: function() { + // this method should be overwritten in child class + }, + + /* + set element's html by value + */ + value2htmlFinal: function(value, element) { + // this method should be overwritten in child class + }, + + /** + * convert data to array suitable for sourceData, e.g. [{value: 1, text: 'abc'}, {...}] + */ + makeArray: function(data) { + var count, obj, result = [], iterateEl; + if(!data || typeof data === 'string') { + return null; + } + + if($.isArray(data)) { //array + iterateEl = function (k, v) { + obj = {value: k, text: v}; + if(count++ >= 2) { + return false;// exit each if object has more than one value + } + }; + + for(var i = 0; i < data.length; i++) { + if(typeof data[i] === 'object') { + count = 0; + $.each(data[i], iterateEl); + if(count === 1) { + result.push(obj); + } else if(count > 1 && data[i].hasOwnProperty('value') && data[i].hasOwnProperty('text')) { + result.push(data[i]); + } else { + //data contains incorrect objects + } + } else { + result.push({value: data[i], text: data[i]}); + } + } + } else { //object + $.each(data, function (k, v) { + result.push({value: k, text: v}); + }); + } + return result; + }, + + //search for item by particular value + itemByVal: function(val) { + if($.isArray(this.sourceData)) { + for(var i=0; i<this.sourceData.length; i++){ + /*jshint eqeqeq: false*/ + if(this.sourceData[i].value == val) { + /*jshint eqeqeq: true*/ + return this.sourceData[i]; + } + } + } + } + + }); + + List.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + Source data for list. If string - considered ajax url to load items. Otherwise should be an array. + Array format is: <code>[{value: 1, text: "text"}, {...}]</code><br> + For compability it also supports format <code>{value1: "text1", value2: "text2" ...}</code> but it does not guarantee elements order. + If source is **string**, results will be cached for fields with the same source and name. See also <code>sourceCache</code> option. + + @property source + @type string|array|object + @default null + **/ + source:null, + /** + Data automatically prepended to the beginning of dropdown list. + + @property prepend + @type string|array|object + @default false + **/ + prepend:false, + /** + Error message when list cannot be loaded (e.g. ajax error) + + @property sourceError + @type string + @default Error when loading list + **/ + sourceError: 'Error when loading list', + /** + if <code>true</code> and source is **string url** - results will be cached for fields with the same source and name. + Usefull for editable grids. + + @property sourceCache + @type boolean + @default true + @since 1.2.0 + **/ + sourceCache: true + }); + + $.fn.editabletypes.list = List; + +}(window.jQuery)); +/** +Text input + +@class text +@extends abstractinput +@final +@example +<a href="#" id="username" data-type="text" data-pk="1">awesome</a> +<script> +$(function(){ + $('#username').editable({ + url: '/post', + title: 'Enter username' + }); +}); +</script> +**/ +(function ($) { + var Text = function (options) { + this.init('text', options, Text.defaults); + }; + + $.fn.editableutils.inherit(Text, $.fn.editabletypes.abstractinput); + + $.extend(Text.prototype, { + activate: function() { + if(this.$input.is(':visible')) { + this.$input.focus(); + $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length); + } + } + }); + + Text.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <input type="text"> + **/ + tpl: '<input type="text">', + /** + Placeholder attribute of input. Shown when input is empty. + + @property placeholder + @type string + @default null + **/ + placeholder: null + }); + + $.fn.editabletypes.text = Text; + +}(window.jQuery)); + +/** +Textarea input + +@class textarea +@extends abstractinput +@final +@example +<a href="#" id="comments" data-type="textarea" data-pk="1">awesome comment!</a> +<script> +$(function(){ + $('#comments').editable({ + url: '/post', + title: 'Enter comments' + }); +}); +</script> +**/ +(function ($) { + + var Textarea = function (options) { + this.init('textarea', options, Textarea.defaults); + }; + + $.fn.editableutils.inherit(Textarea, $.fn.editabletypes.abstractinput); + + $.extend(Textarea.prototype, { + render: function () { + Textarea.superclass.render.call(this); + + //ctrl + enter + this.$input.keydown(function (e) { + if (e.ctrlKey && e.which === 13) { + $(this).closest('form').submit(); + } + }); + }, + + value2html: function(value, element) { + var html = '', lines; + if(value) { + lines = value.split("\n"); + for (var i = 0; i < lines.length; i++) { + lines[i] = $('<div>').text(lines[i]).html(); + } + html = lines.join('<br>'); + } + $(element).html(html); + }, + + html2value: function(html) { + if(!html) { + return ''; + } + var lines = html.split(/<br\s*\/?>/i); + for (var i = 0; i < lines.length; i++) { + lines[i] = $('<div>').html(lines[i]).text(); + } + return lines.join("\n"); + }, + + activate: function() { + if(this.$input.is(':visible')) { + $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length); + this.$input.focus(); + } + } + }); + + Textarea.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <textarea></textarea> + **/ + tpl:'<textarea></textarea>', + /** + @property inputclass + @default input-large + **/ + inputclass: 'input-large', + /** + Placeholder attribute of input. Shown when input is empty. + + @property placeholder + @type string + @default null + **/ + placeholder: null + }); + + $.fn.editabletypes.textarea = Textarea; + +}(window.jQuery)); + +/** +Select (dropdown) + +@class select +@extends list +@final +@example +<a href="#" id="status" data-type="select" data-pk="1" data-url="/post" data-original-title="Select status"></a> +<script> +$(function(){ + $('#status').editable({ + value: 2, + source: [ + {value: 1, text: 'Active'}, + {value: 2, text: 'Blocked'}, + {value: 3, text: 'Deleted'} + ] + } + }); +}); +</script> +**/ +(function ($) { + + var Select = function (options) { + this.init('select', options, Select.defaults); + }; + + $.fn.editableutils.inherit(Select, $.fn.editabletypes.list); + + $.extend(Select.prototype, { + renderList: function() { + if(!$.isArray(this.sourceData)) { + return; + } + + for(var i=0; i<this.sourceData.length; i++) { + this.$input.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text)); + } + + //enter submit + this.$input.on('keydown.editable', function (e) { + if (e.which === 13) { + $(this).closest('form').submit(); + } + }); + }, + + value2htmlFinal: function(value, element) { + var text = '', item = this.itemByVal(value); + if(item) { + text = item.text; + } + Select.superclass.constructor.superclass.value2html(text, element); + }, + + autosubmit: function() { + this.$input.off('keydown.editable').on('change.editable', function(){ + $(this).closest('form').submit(); + }); + } + }); + + Select.defaults = $.extend({}, $.fn.editabletypes.list.defaults, { + /** + @property tpl + @default <select></select> + **/ + tpl:'<select></select>' + }); + + $.fn.editabletypes.select = Select; + +}(window.jQuery)); +/** +List of checkboxes. +Internally value stored as javascript array of values. + +@class checklist +@extends list +@final +@example +<a href="#" id="options" data-type="checklist" data-pk="1" data-url="/post" data-original-title="Select options"></a> +<script> +$(function(){ + $('#options').editable({ + value: [2, 3], + source: [ + {value: 1, text: 'option1'}, + {value: 2, text: 'option2'}, + {value: 3, text: 'option3'} + ] + } + }); +}); +</script> +**/ +(function ($) { + + var Checklist = function (options) { + this.init('checklist', options, Checklist.defaults); + }; + + $.fn.editableutils.inherit(Checklist, $.fn.editabletypes.list); + + $.extend(Checklist.prototype, { + renderList: function() { + var $label, $div; + if(!$.isArray(this.sourceData)) { + return; + } + + for(var i=0; i<this.sourceData.length; i++) { + $label = $('<label>').append($('<input>', { + type: 'checkbox', + value: this.sourceData[i].value, + name: this.options.name + })) + .append($('<span>').text(' '+this.sourceData[i].text)); + + $('<div>').append($label).appendTo(this.$input); + } + }, + + value2str: function(value) { + return $.isArray(value) ? value.sort().join($.trim(this.options.separator)) : ''; + }, + + //parse separated string + str2value: function(str) { + var reg, value = null; + if(typeof str === 'string' && str.length) { + reg = new RegExp('\\s*'+$.trim(this.options.separator)+'\\s*'); + value = str.split(reg); + } else if($.isArray(str)) { + value = str; + } + return value; + }, + + //set checked on required checkboxes + value2input: function(value) { + var $checks = this.$input.find('input[type="checkbox"]'); + $checks.removeAttr('checked'); + if($.isArray(value) && value.length) { + $checks.each(function(i, el) { + var $el = $(el); + // cannot use $.inArray as it performs strict comparison + $.each(value, function(j, val){ + /*jslint eqeq: true*/ + if($el.val() == val) { + /*jslint eqeq: false*/ + $el.attr('checked', 'checked'); + } + }); + }); + } + }, + + input2value: function() { + var checked = []; + this.$input.find('input:checked').each(function(i, el) { + checked.push($(el).val()); + }); + return checked; + }, + + //collect text of checked boxes + value2htmlFinal: function(value, element) { + var html = [], + /*jslint eqeq: true*/ + checked = $.grep(this.sourceData, function(o){ + return $.grep(value, function(v){ return v == o.value; }).length; + }); + /*jslint eqeq: false*/ + if(checked.length) { + $.each(checked, function(i, v) { html.push($.fn.editableutils.escape(v.text)); }); + $(element).html(html.join('<br>')); + } else { + $(element).empty(); + } + }, + + activate: function() { + this.$input.find('input[type="checkbox"]').first().focus(); + }, + + autosubmit: function() { + this.$input.find('input[type="checkbox"]').on('keydown', function(e){ + if (e.which === 13) { + $(this).closest('form').submit(); + } + }); + } + }); + + Checklist.defaults = $.extend({}, $.fn.editabletypes.list.defaults, { + /** + @property tpl + @default <div></div> + **/ + tpl:'<div></div>', + + /** + @property inputclass + @type string + @default editable-checklist + **/ + inputclass: 'editable-checklist', + + /** + Separator of values when reading from 'data-value' string + + @property separator + @type string + @default ', ' + **/ + separator: ',' + }); + + $.fn.editabletypes.checklist = Checklist; + +}(window.jQuery)); + +/** +HTML5 input types. +Following types are supported: + +* password +* email +* url +* tel +* number +* range + +Learn more about html5 inputs: +http://www.w3.org/wiki/HTML5_form_additions +To check browser compatibility please see: +https://developer.mozilla.org/en-US/docs/HTML/Element/Input + +@class html5types +@extends text +@final +@since 1.3.0 +@example +<a href="#" id="email" data-type="email" data-pk="1">admin@example.com</a> +<script> +$(function(){ + $('#email').editable({ + url: '/post', + title: 'Enter email' + }); +}); +</script> +**/ + +/** +@property tpl +@default depends on type +**/ + +/* +Password +*/ +(function ($) { + var Password = function (options) { + this.init('password', options, Password.defaults); + }; + $.fn.editableutils.inherit(Password, $.fn.editabletypes.text); + $.extend(Password.prototype, { + //do not display password, show '[hidden]' instead + value2html: function(value, element) { + if(value) { + $(element).text('[hidden]'); + } else { + $(element).empty(); + } + }, + //as password not displayed, should not set value by html + html2value: function(html) { + return null; + } + }); + Password.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="password">' + }); + $.fn.editabletypes.password = Password; +}(window.jQuery)); + + +/* +Email +*/ +(function ($) { + var Email = function (options) { + this.init('email', options, Email.defaults); + }; + $.fn.editableutils.inherit(Email, $.fn.editabletypes.text); + Email.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="email">' + }); + $.fn.editabletypes.email = Email; +}(window.jQuery)); + + +/* +Url +*/ +(function ($) { + var Url = function (options) { + this.init('url', options, Url.defaults); + }; + $.fn.editableutils.inherit(Url, $.fn.editabletypes.text); + Url.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="url">' + }); + $.fn.editabletypes.url = Url; +}(window.jQuery)); + + +/* +Tel +*/ +(function ($) { + var Tel = function (options) { + this.init('tel', options, Tel.defaults); + }; + $.fn.editableutils.inherit(Tel, $.fn.editabletypes.text); + Tel.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="tel">' + }); + $.fn.editabletypes.tel = Tel; +}(window.jQuery)); + + +/* +Number +*/ +(function ($) { + var NumberInput = function (options) { + this.init('number', options, NumberInput.defaults); + }; + $.fn.editableutils.inherit(NumberInput, $.fn.editabletypes.text); + $.extend(NumberInput.prototype, { + render: function () { + NumberInput.superclass.render.call(this); + + if (this.options.min !== null) { + this.$input.attr('min', this.options.min); + } + + if (this.options.max !== null) { + this.$input.attr('max', this.options.max); + } + + if (this.options.step !== null) { + this.$input.attr('step', this.options.step); + } + } + }); + NumberInput.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="number">', + inputclass: 'input-mini', + min: null, + max: null, + step: null + }); + $.fn.editabletypes.number = NumberInput; +}(window.jQuery)); + + +/* +Range (inherit from number) +*/ +(function ($) { + var Range = function (options) { + this.init('range', options, Range.defaults); + }; + $.fn.editableutils.inherit(Range, $.fn.editabletypes.number); + $.extend(Range.prototype, { + render: function () { + this.$input = $(this.options.tpl); + var $slider = this.$input.filter('input'); + if(this.options.inputclass) { + $slider.addClass(this.options.inputclass); + } + if (this.options.min !== null) { + $slider.attr('min', this.options.min); + } + + if (this.options.max !== null) { + $slider.attr('max', this.options.max); + } + + if (this.options.step !== null) { + $slider.attr('step', this.options.step); + } + + $slider.on('input', function(){ + $(this).siblings('output').text($(this).val()); + }); + }, + activate: function() { + this.$input.filter('input').focus(); + } + }); + Range.defaults = $.extend({}, $.fn.editabletypes.number.defaults, { + tpl: '<input type="range"><output style="width: 30px; display: inline-block"></output>', + inputclass: 'input-medium' + }); + $.fn.editabletypes.range = Range; +}(window.jQuery)); +/* +Editableform based on Twitter Bootstrap +*/ +(function ($) { + + $.extend($.fn.editableform.Constructor.prototype, { + initTemplate: function() { + this.$form = $($.fn.editableform.template); + this.$form.find('.editable-error-block').addClass('help-block'); + } + }); + + //buttons + $.fn.editableform.buttons = '<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button>'+ + '<button type="button" class="btn editable-cancel"><i class="icon-remove"></i></button>'; + + //error classes + $.fn.editableform.errorGroupClass = 'error'; + $.fn.editableform.errorBlockClass = null; + +}(window.jQuery)); +/** +* Editable Popover +* --------------------- +* requires bootstrap-popover.js +*/ +(function ($) { + + //extend methods + $.extend($.fn.editableContainer.Constructor.prototype, { + containerName: 'popover', + //for compatibility with bootstrap <= 2.2.1 (content inserted into <p> instead of directly .popover-content) + innerCss: $($.fn.popover.defaults.template).find('p').length ? '.popover-content p' : '.popover-content', + + initContainer: function(){ + $.extend(this.containerOptions, { + trigger: 'manual', + selector: false, + content: ' ' + }); + this.call(this.containerOptions); + }, + + setContainerOption: function(key, value) { + this.container().options[key] = value; + }, + + /** + * move popover to new position. This function mainly copied from bootstrap-popover. + */ + /*jshint laxcomma: true*/ + setPosition: function () { + + (function() { + var $tip = this.tip() + , inside + , pos + , actualWidth + , actualHeight + , placement + , tp; + + placement = typeof this.options.placement === 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement; + + inside = /in/.test(placement); + + $tip + // .detach() + //vitalets: remove any placement class because otherwise they dont influence on re-positioning of visible popover + .removeClass('top right bottom left') + .css({ top: 0, left: 0, display: 'block' }); + // .insertAfter(this.$element); + + pos = this.getPosition(inside); + + actualWidth = $tip[0].offsetWidth; + actualHeight = $tip[0].offsetHeight; + + switch (inside ? placement.split(' ')[1] : placement) { + case 'bottom': + tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}; + break; + case 'top': + tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}; + break; + case 'left': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}; + break; + case 'right': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}; + break; + } + + $tip + .offset(tp) + .addClass(placement) + .addClass('in'); + + }).call(this.container()); + /*jshint laxcomma: false*/ + } + }); + + //defaults + /* + $.fn.editableContainer.defaults = $.extend({}, $.fn.popover.defaults, $.fn.editableContainer.defaults, { + + }); + */ + +}(window.jQuery)); +/** +Bootstrap-datepicker. +Description and examples: http://vitalets.github.com/bootstrap-datepicker. +For localization you can include js file from here: https://github.com/eternicode/bootstrap-datepicker/tree/master/js/locales + +@class date +@extends abstractinput +@final +@example +<a href="#" id="dob" data-type="date" data-pk="1" data-url="/post" data-original-title="Select date">15/05/1984</a> +<script> +$(function(){ + $('#dob').editable({ + format: 'yyyy-mm-dd', + viewformat: 'dd/mm/yyyy', + datepicker: { + weekStart: 1 + } + } + }); +}); +</script> +**/ +(function ($) { + + var Date = function (options) { + this.init('date', options, Date.defaults); + + //set popular options directly from settings or data-* attributes + var directOptions = $.fn.editableutils.sliceObj(this.options, ['format']); + + //overriding datepicker config (as by default jQuery extend() is not recursive) + this.options.datepicker = $.extend({}, Date.defaults.datepicker, directOptions, options.datepicker); + + //by default viewformat equals to format + if(!this.options.viewformat) { + this.options.viewformat = this.options.datepicker.format; + } + + //language + this.options.datepicker.language = this.options.datepicker.language || 'en'; + + //store DPglobal + this.dpg = $.fn.datepicker.DPGlobal; + + //store parsed formats + this.parsedFormat = this.dpg.parseFormat(this.options.datepicker.format); + this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat); + }; + + $.fn.editableutils.inherit(Date, $.fn.editabletypes.abstractinput); + + $.extend(Date.prototype, { + render: function () { + Date.superclass.render.call(this); + this.$input.datepicker(this.options.datepicker); + + if(this.options.clear) { + this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){ + e.preventDefault(); + e.stopPropagation(); + this.clear(); + }, this)); + } + }, + + value2html: function(value, element) { + var text = value ? this.dpg.formatDate(value, this.parsedViewFormat, this.options.datepicker.language) : ''; + Date.superclass.value2html(text, element); + }, + + html2value: function(html) { + return html ? this.dpg.parseDate(html, this.parsedViewFormat, this.options.datepicker.language) : null; + }, + + value2str: function(value) { + return value ? this.dpg.formatDate(value, this.parsedFormat, this.options.datepicker.language) : ''; + }, + + str2value: function(str) { + return str ? this.dpg.parseDate(str, this.parsedFormat, this.options.datepicker.language) : null; + }, + + value2submit: function(value) { + return this.value2str(value); + }, + + value2input: function(value) { + this.$input.datepicker('update', value); + }, + + input2value: function() { + return this.$input.data('datepicker').date; + }, + + activate: function() { + }, + + clear: function() { + this.$input.data('datepicker').date = null; + this.$input.find('.active').removeClass('active'); + }, + + autosubmit: function() { + this.$input.on('changeDate', function(e){ + var $form = $(this).closest('form'); + setTimeout(function() { + $form.submit(); + }, 200); + }); + } + + }); + + Date.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <div></div> + **/ + tpl:'<div></div>', + /** + @property inputclass + @default editable-date well + **/ + inputclass: 'editable-date well', + /** + Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br> + Possible tokens are: <code>d, dd, m, mm, yy, yyyy</code> + + @property format + @type string + @default yyyy-mm-dd + **/ + format:'yyyy-mm-dd', + /** + Format used for displaying date. Also applied when converting date from element's text on init. + If not specified equals to <code>format</code> + + @property viewformat + @type string + @default null + **/ + viewformat: null, + /** + Configuration of datepicker. + Full list of options: http://vitalets.github.com/bootstrap-datepicker + + @property datepicker + @type object + @default { + weekStart: 0, + startView: 0, + autoclose: false + } + **/ + datepicker:{ + weekStart: 0, + startView: 0, + autoclose: false + }, + /** + Text shown as clear date button. + If <code>false</code> clear button will not be rendered. + + @property clear + @type boolean|string + @default 'x clear' + **/ + clear: '&times; clear' + }); + + $.fn.editabletypes.date = Date; + +}(window.jQuery)); + +/* ========================================================= + * bootstrap-datepicker.js + * http://www.eyecon.ro/bootstrap-datepicker + * ========================================================= + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * + * 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( $ ) { + + function UTCDate(){ + return new Date(Date.UTC.apply(Date, arguments)); + } + function UTCToday(){ + var today = new Date(); + return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate()); + } + + // Picker object + + var Datepicker = function(element, options) { + var that = this; + + this.element = $(element); + this.language = options.language||this.element.data('date-language')||"en"; + this.language = this.language in dates ? this.language : "en"; + this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy'); + this.isInline = false; + this.isInput = this.element.is('input'); + this.component = this.element.is('.date') ? this.element.find('.add-on') : false; + this.hasInput = this.component && this.element.find('input').length; + if(this.component && this.component.length === 0) + this.component = false; + + if (this.isInput) { //single input + this.element.on({ + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }); + } else if(this.component && this.hasInput) { //component: input + button + // For components that are not readonly, allow keyboard nav + this.element.find('input').on({ + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }); + + this.component.on('click', $.proxy(this.show, this)); + } else if(this.element.is('div')) { //inline datepicker + this.isInline = true; + } else { + this.element.on('click', $.proxy(this.show, this)); + } + + this.picker = $(DPGlobal.template) + .appendTo(this.isInline ? this.element : 'body') + .on({ + click: $.proxy(this.click, this), + mousedown: $.proxy(this.mousedown, this) + }); + + if(this.isInline) { + this.picker.addClass('datepicker-inline'); + } else { + this.picker.addClass('dropdown-menu'); + } + + $(document).on('mousedown', function (e) { + // Clicked outside the datepicker, hide it + if ($(e.target).closest('.datepicker').length == 0) { + that.hide(); + } + }); + + this.autoclose = false; + if ('autoclose' in options) { + this.autoclose = options.autoclose; + } else if ('dateAutoclose' in this.element.data()) { + this.autoclose = this.element.data('date-autoclose'); + } + + this.keyboardNavigation = true; + if ('keyboardNavigation' in options) { + this.keyboardNavigation = options.keyboardNavigation; + } else if ('dateKeyboardNavigation' in this.element.data()) { + this.keyboardNavigation = this.element.data('date-keyboard-navigation'); + } + + switch(options.startView || this.element.data('date-start-view')){ + case 2: + case 'decade': + this.viewMode = this.startViewMode = 2; + break; + case 1: + case 'year': + this.viewMode = this.startViewMode = 1; + break; + case 0: + case 'month': + default: + this.viewMode = this.startViewMode = 0; + break; + } + + this.todayBtn = (options.todayBtn||this.element.data('date-today-btn')||false); + this.todayHighlight = (options.todayHighlight||this.element.data('date-today-highlight')||false); + + this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7); + this.weekEnd = ((this.weekStart + 6) % 7); + this.startDate = -Infinity; + this.endDate = Infinity; + this.setStartDate(options.startDate||this.element.data('date-startdate')); + this.setEndDate(options.endDate||this.element.data('date-enddate')); + this.fillDow(); + this.fillMonths(); + this.update(); + this.showMode(); + + if(this.isInline) { + this.show(); + } + }; + + Datepicker.prototype = { + constructor: Datepicker, + + show: function(e) { + this.picker.show(); + this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); + this.update(); + this.place(); + $(window).on('resize', $.proxy(this.place, this)); + if (e ) { + e.stopPropagation(); + e.preventDefault(); + } + this.element.trigger({ + type: 'show', + date: this.date + }); + }, + + hide: function(e){ + if(this.isInline) return; + this.picker.hide(); + $(window).off('resize', this.place); + this.viewMode = this.startViewMode; + this.showMode(); + if (!this.isInput) { + $(document).off('mousedown', this.hide); + } + if (e && e.currentTarget.value) + this.setValue(); + this.element.trigger({ + type: 'hide', + date: this.date + }); + }, + + getDate: function() { + var d = this.getUTCDate(); + return new Date(d.getTime() + (d.getTimezoneOffset()*60000)) + }, + + getUTCDate: function() { + return this.date; + }, + + setDate: function(d) { + this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000))); + }, + + setUTCDate: function(d) { + this.date = d; + this.setValue(); + }, + + setValue: function() { + var formatted = this.getFormattedDate(); + if (!this.isInput) { + if (this.component){ + this.element.find('input').prop('value', formatted); + } + this.element.data('date', formatted); + } else { + this.element.prop('value', formatted); + } + }, + + getFormattedDate: function(format) { + if(format == undefined) format = this.format; + return DPGlobal.formatDate(this.date, format, this.language); + }, + + setStartDate: function(startDate){ + this.startDate = startDate||-Infinity; + if (this.startDate !== -Infinity) { + this.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language); + } + this.update(); + this.updateNavArrows(); + }, + + setEndDate: function(endDate){ + this.endDate = endDate||Infinity; + if (this.endDate !== Infinity) { + this.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language); + } + this.update(); + this.updateNavArrows(); + }, + + place: function(){ + if(this.isInline) return; + var zIndex = parseInt(this.element.parents().filter(function() { + return $(this).css('z-index') != 'auto'; + }).first().css('z-index'))+10; + var offset = this.component ? this.component.offset() : this.element.offset(); + this.picker.css({ + top: offset.top + this.height, + left: offset.left, + zIndex: zIndex + }); + }, + + update: function(){ + var date, fromArgs = false; + if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) { + date = arguments[0]; + fromArgs = true; + } else { + date = this.isInput ? this.element.prop('value') : this.element.data('date') || this.element.find('input').prop('value'); + } + + this.date = DPGlobal.parseDate(date, this.format, this.language); + + if(fromArgs) this.setValue(); + + if (this.date < this.startDate) { + this.viewDate = new Date(this.startDate); + } else if (this.date > this.endDate) { + this.viewDate = new Date(this.endDate); + } else { + this.viewDate = new Date(this.date); + } + this.fill(); + }, + + fillDow: function(){ + var dowCnt = this.weekStart; + var html = '<tr>'; + while (dowCnt < this.weekStart + 7) { + html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>'; + } + html += '</tr>'; + this.picker.find('.datepicker-days thead').append(html); + }, + + fillMonths: function(){ + var html = ''; + var i = 0 + while (i < 12) { + html += '<span class="month">'+dates[this.language].monthsShort[i++]+'</span>'; + } + this.picker.find('.datepicker-months td').html(html); + }, + + fill: function() { + var d = new Date(this.viewDate), + year = d.getUTCFullYear(), + month = d.getUTCMonth(), + startYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity, + startMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity, + endYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity, + endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity, + currentDate = this.date && this.date.valueOf(), + today = new Date(); + this.picker.find('.datepicker-days thead th:eq(1)') + .text(dates[this.language].months[month]+' '+year); + this.picker.find('tfoot th.today') + .text(dates[this.language].today) + .toggle(this.todayBtn !== false); + this.updateNavArrows(); + this.fillMonths(); + var prevMonth = UTCDate(year, month-1, 28,0,0,0,0), + day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); + prevMonth.setUTCDate(day); + prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7)%7); + var nextMonth = new Date(prevMonth); + nextMonth.setUTCDate(nextMonth.getUTCDate() + 42); + nextMonth = nextMonth.valueOf(); + var html = []; + var clsName; + while(prevMonth.valueOf() < nextMonth) { + if (prevMonth.getUTCDay() == this.weekStart) { + html.push('<tr>'); + } + clsName = ''; + if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) { + clsName += ' old'; + } else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) { + clsName += ' new'; + } + // Compare internal UTC date with local today, not UTC today + if (this.todayHighlight && + prevMonth.getUTCFullYear() == today.getFullYear() && + prevMonth.getUTCMonth() == today.getMonth() && + prevMonth.getUTCDate() == today.getDate()) { + clsName += ' today'; + } + if (currentDate && prevMonth.valueOf() == currentDate) { + clsName += ' active'; + } + if (prevMonth.valueOf() < this.startDate || prevMonth.valueOf() > this.endDate) { + clsName += ' disabled'; + } + html.push('<td class="day'+clsName+'">'+prevMonth.getUTCDate() + '</td>'); + if (prevMonth.getUTCDay() == this.weekEnd) { + html.push('</tr>'); + } + prevMonth.setUTCDate(prevMonth.getUTCDate()+1); + } + this.picker.find('.datepicker-days tbody').empty().append(html.join('')); + var currentYear = this.date && this.date.getUTCFullYear(); + + var months = this.picker.find('.datepicker-months') + .find('th:eq(1)') + .text(year) + .end() + .find('span').removeClass('active'); + if (currentYear && currentYear == year) { + months.eq(this.date.getUTCMonth()).addClass('active'); + } + if (year < startYear || year > endYear) { + months.addClass('disabled'); + } + if (year == startYear) { + months.slice(0, startMonth).addClass('disabled'); + } + if (year == endYear) { + months.slice(endMonth+1).addClass('disabled'); + } + + html = ''; + year = parseInt(year/10, 10) * 10; + var yearCont = this.picker.find('.datepicker-years') + .find('th:eq(1)') + .text(year + '-' + (year + 9)) + .end() + .find('td'); + year -= 1; + for (var i = -1; i < 11; i++) { + html += '<span class="year'+(i == -1 || i == 10 ? ' old' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>'; + year += 1; + } + yearCont.html(html); + }, + + updateNavArrows: function() { + var d = new Date(this.viewDate), + year = d.getUTCFullYear(), + month = d.getUTCMonth(); + switch (this.viewMode) { + case 0: + if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + case 1: + case 2: + if (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + } + }, + + click: function(e) { + e.stopPropagation(); + e.preventDefault(); + var target = $(e.target).closest('span, td, th'); + if (target.length == 1) { + switch(target[0].nodeName.toLowerCase()) { + case 'th': + switch(target[0].className) { + case 'switch': + this.showMode(1); + break; + case 'prev': + case 'next': + var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1); + switch(this.viewMode){ + case 0: + this.viewDate = this.moveMonth(this.viewDate, dir); + break; + case 1: + case 2: + this.viewDate = this.moveYear(this.viewDate, dir); + break; + } + this.fill(); + break; + case 'today': + var date = new Date(); + date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); + + this.showMode(-2); + var which = this.todayBtn == 'linked' ? null : 'view'; + this._setDate(date, which); + break; + } + break; + case 'span': + if (!target.is('.disabled')) { + this.viewDate.setUTCDate(1); + if (target.is('.month')) { + var month = target.parent().find('span').index(target); + this.viewDate.setUTCMonth(month); + this.element.trigger({ + type: 'changeMonth', + date: this.viewDate + }); + } else { + var year = parseInt(target.text(), 10)||0; + this.viewDate.setUTCFullYear(year); + this.element.trigger({ + type: 'changeYear', + date: this.viewDate + }); + } + this.showMode(-1); + this.fill(); + } + break; + case 'td': + if (target.is('.day') && !target.is('.disabled')){ + var day = parseInt(target.text(), 10)||1; + var year = this.viewDate.getUTCFullYear(), + month = this.viewDate.getUTCMonth(); + if (target.is('.old')) { + if (month == 0) { + month = 11; + year -= 1; + } else { + month -= 1; + } + } else if (target.is('.new')) { + if (month == 11) { + month = 0; + year += 1; + } else { + month += 1; + } + } + this._setDate(UTCDate(year, month, day,0,0,0,0)); + } + break; + } + } + }, + + _setDate: function(date, which){ + if (!which || which == 'date') + this.date = date; + if (!which || which == 'view') + this.viewDate = date; + this.fill(); + this.setValue(); + this.element.trigger({ + type: 'changeDate', + date: this.date + }); + var element; + if (this.isInput) { + element = this.element; + } else if (this.component){ + element = this.element.find('input'); + } + if (element) { + element.change(); + if (this.autoclose) { + this.hide(); + } + } + }, + + moveMonth: function(date, dir){ + if (!dir) return date; + var new_date = new Date(date.valueOf()), + day = new_date.getUTCDate(), + month = new_date.getUTCMonth(), + mag = Math.abs(dir), + new_month, test; + dir = dir > 0 ? 1 : -1; + if (mag == 1){ + test = dir == -1 + // If going back one month, make sure month is not current month + // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02) + ? function(){ return new_date.getUTCMonth() == month; } + // If going forward one month, make sure month is as expected + // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02) + : function(){ return new_date.getUTCMonth() != new_month; }; + new_month = month + dir; + new_date.setUTCMonth(new_month); + // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11 + if (new_month < 0 || new_month > 11) + new_month = (new_month + 12) % 12; + } else { + // For magnitudes >1, move one month at a time... + for (var i=0; i<mag; i++) + // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)... + new_date = this.moveMonth(new_date, dir); + // ...then reset the day, keeping it in the new month + new_month = new_date.getUTCMonth(); + new_date.setUTCDate(day); + test = function(){ return new_month != new_date.getUTCMonth(); }; + } + // Common date-resetting loop -- if date is beyond end of month, make it + // end of month + while (test()){ + new_date.setUTCDate(--day); + new_date.setUTCMonth(new_month); + } + return new_date; + }, + + moveYear: function(date, dir){ + return this.moveMonth(date, dir*12); + }, + + dateWithinRange: function(date){ + return date >= this.startDate && date <= this.endDate; + }, + + keydown: function(e){ + if (this.picker.is(':not(:visible)')){ + if (e.keyCode == 27) // allow escape to hide and re-show picker + this.show(); + return; + } + var dateChanged = false, + dir, day, month, + newDate, newViewDate; + switch(e.keyCode){ + case 27: // escape + this.hide(); + e.preventDefault(); + break; + case 37: // left + case 39: // right + if (!this.keyboardNavigation) break; + dir = e.keyCode == 37 ? -1 : 1; + if (e.ctrlKey){ + newDate = this.moveYear(this.date, dir); + newViewDate = this.moveYear(this.viewDate, dir); + } else if (e.shiftKey){ + newDate = this.moveMonth(this.date, dir); + newViewDate = this.moveMonth(this.viewDate, dir); + } else { + newDate = new Date(this.date); + newDate.setUTCDate(this.date.getUTCDate() + dir); + newViewDate = new Date(this.viewDate); + newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir); + } + if (this.dateWithinRange(newDate)){ + this.date = newDate; + this.viewDate = newViewDate; + this.setValue(); + this.update(); + e.preventDefault(); + dateChanged = true; + } + break; + case 38: // up + case 40: // down + if (!this.keyboardNavigation) break; + dir = e.keyCode == 38 ? -1 : 1; + if (e.ctrlKey){ + newDate = this.moveYear(this.date, dir); + newViewDate = this.moveYear(this.viewDate, dir); + } else if (e.shiftKey){ + newDate = this.moveMonth(this.date, dir); + newViewDate = this.moveMonth(this.viewDate, dir); + } else { + newDate = new Date(this.date); + newDate.setUTCDate(this.date.getUTCDate() + dir * 7); + newViewDate = new Date(this.viewDate); + newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7); + } + if (this.dateWithinRange(newDate)){ + this.date = newDate; + this.viewDate = newViewDate; + this.setValue(); + this.update(); + e.preventDefault(); + dateChanged = true; + } + break; + case 13: // enter + this.hide(); + e.preventDefault(); + break; + case 9: // tab + this.hide(); + break; + } + if (dateChanged){ + this.element.trigger({ + type: 'changeDate', + date: this.date + }); + var element; + if (this.isInput) { + element = this.element; + } else if (this.component){ + element = this.element.find('input'); + } + if (element) { + element.change(); + } + } + }, + + showMode: function(dir) { + if (dir) { + this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir)); + } + /* + vitalets: fixing bug of very special conditions: + jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover. + Method show() does not set display css correctly and datepicker is not shown. + Changed to .css('display', 'block') solve the problem. + See https://github.com/vitalets/x-editable/issues/37 + + In jquery 1.7.2+ everything works fine. + */ + //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); + this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block'); + this.updateNavArrows(); + } + }; + + $.fn.datepicker = function ( option ) { + var args = Array.apply(null, arguments); + args.shift(); + return this.each(function () { + var $this = $(this), + data = $this.data('datepicker'), + options = typeof option == 'object' && option; + if (!data) { + $this.data('datepicker', (data = new Datepicker(this, $.extend({}, $.fn.datepicker.defaults,options)))); + } + if (typeof option == 'string' && typeof data[option] == 'function') { + data[option].apply(data, args); + } + }); + }; + + $.fn.datepicker.defaults = { + }; + $.fn.datepicker.Constructor = Datepicker; + var dates = $.fn.datepicker.dates = { + en: { + days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], + daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], + months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], + today: "Today" + } + } + + var DPGlobal = { + modes: [ + { + clsName: 'days', + navFnc: 'Month', + navStep: 1 + }, + { + clsName: 'months', + navFnc: 'FullYear', + navStep: 1 + }, + { + clsName: 'years', + navFnc: 'FullYear', + navStep: 10 + }], + isLeapYear: function (year) { + return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)) + }, + getDaysInMonth: function (year, month) { + return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month] + }, + validParts: /dd?|mm?|MM?|yy(?:yy)?/g, + nonpunctuation: /[^ -\/:-@\[-`{-~\t\n\r]+/g, + parseFormat: function(format){ + // IE treats \0 as a string end in inputs (truncating the value), + // so it's a bad format delimiter, anyway + var separators = format.replace(this.validParts, '\0').split('\0'), + parts = format.match(this.validParts); + if (!separators || !separators.length || !parts || parts.length == 0){ + throw new Error("Invalid date format."); + } + return {separators: separators, parts: parts}; + }, + parseDate: function(date, format, language) { + if (date instanceof Date) return date; + if (/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(date)) { + var part_re = /([-+]\d+)([dmwy])/, + parts = date.match(/([-+]\d+)([dmwy])/g), + part, dir; + date = new Date(); + for (var i=0; i<parts.length; i++) { + part = part_re.exec(parts[i]); + dir = parseInt(part[1]); + switch(part[2]){ + case 'd': + date.setUTCDate(date.getUTCDate() + dir); + break; + case 'm': + date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir); + break; + case 'w': + date.setUTCDate(date.getUTCDate() + dir * 7); + break; + case 'y': + date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir); + break; + } + } + return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0); + } + var parts = date && date.match(this.nonpunctuation) || [], + date = new Date(), + parsed = {}, + setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'], + setters_map = { + yyyy: function(d,v){ return d.setUTCFullYear(v); }, + yy: function(d,v){ return d.setUTCFullYear(2000+v); }, + m: function(d,v){ + v -= 1; + while (v<0) v += 12; + v %= 12; + d.setUTCMonth(v); + while (d.getUTCMonth() != v) + d.setUTCDate(d.getUTCDate()-1); + return d; + }, + d: function(d,v){ return d.setUTCDate(v); } + }, + val, filtered, part; + setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m']; + setters_map['dd'] = setters_map['d']; + date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); + if (parts.length == format.parts.length) { + for (var i=0, cnt = format.parts.length; i < cnt; i++) { + val = parseInt(parts[i], 10); + part = format.parts[i]; + if (isNaN(val)) { + switch(part) { + case 'MM': + filtered = $(dates[language].months).filter(function(){ + var m = this.slice(0, parts[i].length), + p = parts[i].slice(0, m.length); + return m == p; + }); + val = $.inArray(filtered[0], dates[language].months) + 1; + break; + case 'M': + filtered = $(dates[language].monthsShort).filter(function(){ + var m = this.slice(0, parts[i].length), + p = parts[i].slice(0, m.length); + return m == p; + }); + val = $.inArray(filtered[0], dates[language].monthsShort) + 1; + break; + } + } + parsed[part] = val; + } + for (var i=0, s; i<setters_order.length; i++){ + s = setters_order[i]; + if (s in parsed) + setters_map[s](date, parsed[s]) + } + } + return date; + }, + formatDate: function(date, format, language){ + var val = { + d: date.getUTCDate(), + m: date.getUTCMonth() + 1, + M: dates[language].monthsShort[date.getUTCMonth()], + MM: dates[language].months[date.getUTCMonth()], + yy: date.getUTCFullYear().toString().substring(2), + yyyy: date.getUTCFullYear() + }; + val.dd = (val.d < 10 ? '0' : '') + val.d; + val.mm = (val.m < 10 ? '0' : '') + val.m; + var date = [], + seps = $.extend([], format.separators); + for (var i=0, cnt = format.parts.length; i < cnt; i++) { + if (seps.length) + date.push(seps.shift()) + date.push(val[format.parts[i]]); + } + return date.join(''); + }, + headTemplate: '<thead>'+ + '<tr>'+ + '<th class="prev"><i class="icon-arrow-left"/></th>'+ + '<th colspan="5" class="switch"></th>'+ + '<th class="next"><i class="icon-arrow-right"/></th>'+ + '</tr>'+ + '</thead>', + contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>', + footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>' + }; + DPGlobal.template = '<div class="datepicker">'+ + '<div class="datepicker-days">'+ + '<table class=" table-condensed">'+ + DPGlobal.headTemplate+ + '<tbody></tbody>'+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '<div class="datepicker-months">'+ + '<table class="table-condensed">'+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '<div class="datepicker-years">'+ + '<table class="table-condensed">'+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '</div>'; + + $.fn.datepicker.DPGlobal = DPGlobal; + +}( window.jQuery ); diff --git a/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable.min.js b/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable.min.js new file mode 100755 index 0000000..4f3d8fd --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.3.0/bootstrap-editable/js/bootstrap-editable.min.js @@ -0,0 +1,5 @@ +/*! X-editable - v1.3.0 +* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery +* http://github.com/vitalets/x-editable +* Copyright (c) 2012 Vitaliy Potapov; Licensed MIT */ +(function(e){var t=function(t,n){this.options=e.extend({},e.fn.editableform.defaults,n),this.$div=e(t),this.options.scope||(this.options.scope=this),this.initInput()};t.prototype={constructor:t,initInput:function(){var t,n;if(typeof e.fn.editabletypes[this.options.type]!="function"){e.error("Unknown type: "+this.options.type);return}t=e.fn.editabletypes[this.options.type],n=e.fn.editableutils.sliceObj(this.options,e.fn.editableutils.objectKeys(t.defaults)),this.input=new t(n),this.value=this.input.str2value(this.options.value)},initTemplate:function(){this.$form=e(e.fn.editableform.template)},initButtons:function(){this.$form.find(".editable-buttons").append(e.fn.editableform.buttons)},render:function(){this.$loading=e(e.fn.editableform.loading),this.$div.empty().append(this.$loading),this.showLoading(),this.initTemplate(),this.options.showbuttons?this.initButtons():this.$form.find(".editable-buttons").remove(),this.$div.triggerHandler("rendering"),e.when(this.input.render()).then(e.proxy(function(){this.$form.find("div.editable-input").append(this.input.$input),this.options.showbuttons||this.input.autosubmit(),this.input.$clear&&this.$form.find("div.editable-input").append(e('<div class="editable-clear">').append(this.input.$clear)),this.$div.append(this.$form),this.$form.find(".editable-cancel").click(e.proxy(this.cancel,this)),this.input.error?(this.error(this.input.error),this.$form.find(".editable-submit").attr("disabled",!0),this.input.$input.attr("disabled",!0),this.$form.submit(function(e){e.preventDefault()})):(this.error(!1),this.input.$input.removeAttr("disabled"),this.$form.find(".editable-submit").removeAttr("disabled"),this.input.value2input(this.value),this.$form.submit(e.proxy(this.submit,this))),this.$div.triggerHandler("rendered"),this.showForm()},this))},cancel:function(){this.$div.triggerHandler("cancel")},showLoading:function(){var e;this.$form?(this.$loading.width(this.$form.outerWidth()),this.$loading.height(this.$form.outerHeight()),this.$form.hide()):(e=this.$loading.parent().width(),e&&this.$loading.width(e)),this.$loading.show()},showForm:function(e){this.$loading.hide(),this.$form.show(),e!==!1&&this.input.activate(),this.$div.triggerHandler("show")},error:function(t){var n=this.$form.find(".control-group"),r=this.$form.find(".editable-error-block");t===!1?(n.removeClass(e.fn.editableform.errorGroupClass),r.removeClass(e.fn.editableform.errorBlockClass).empty().hide()):(n.addClass(e.fn.editableform.errorGroupClass),r.addClass(e.fn.editableform.errorBlockClass).text(t).show())},submit:function(t){t.stopPropagation(),t.preventDefault();var n,r=this.input.input2value();if(n=this.validate(r)){this.error(n),this.showForm();return}if(!this.options.savenochange&&this.input.value2str(r)==this.input.value2str(this.value)){this.$div.triggerHandler("nochange");return}e.when(this.save(r)).done(e.proxy(function(e){var t=typeof this.options.success=="function"?this.options.success.call(this.options.scope,e,r):null;if(t===!1){this.error(!1),this.showForm(!1);return}if(typeof t=="string"){this.error(t),this.showForm();return}t&&typeof t=="object"&&t.hasOwnProperty("newValue")&&(r=t.newValue),this.error(!1),this.value=r,this.$div.triggerHandler("save",{newValue:r,response:e})},this)).fail(e.proxy(function(e){this.error(typeof e=="string"?e:e.responseText||e.statusText||"Unknown error!"),this.showForm()},this))},save:function(t){var n=this.input.value2submit(t);this.options.pk=e.fn.editableutils.tryParseJson(this.options.pk,!0);var r=typeof this.options.pk=="function"?this.options.pk.call(this.options.scope):this.options.pk,i=!!(typeof this.options.url=="function"||this.options.url&&(this.options.send==="always"||this.options.send==="auto"&&r)),s;if(i)return this.showLoading(),s={name:this.options.name||"",value:n,pk:r},typeof this.options.params=="function"?s=this.options.params.call(this.options.scope,s):(this.options.params=e.fn.editableutils.tryParseJson(this.options.params,!0),e.extend(s,this.options.params)),typeof this.options.url=="function"?this.options.url.call(this.options.scope,s):e.ajax(e.extend({url:this.options.url,data:s,type:"POST"},this.options.ajaxOptions))},validate:function(e){e===undefined&&(e=this.value);if(typeof this.options.validate=="function")return this.options.validate.call(this.options.scope,e)},option:function(e,t){this.options[e]=t,e==="value"&&this.setValue(t)},setValue:function(e,t){t?this.value=this.input.str2value(e):this.value=e}},e.fn.editableform=function(n){var r=arguments;return this.each(function(){var i=e(this),s=i.data("editableform"),o=typeof n=="object"&&n;s||i.data("editableform",s=new t(this,o)),typeof n=="string"&&s[n].apply(s,Array.prototype.slice.call(r,1))})},e.fn.editableform.Constructor=t,e.fn.editableform.defaults={type:"text",url:null,params:null,name:null,pk:null,value:null,send:"auto",validate:null,success:null,ajaxOptions:null,showbuttons:!0,scope:null,savenochange:!1},e.fn.editableform.template='<form class="form-inline editableform"><div class="control-group"><div><div class="editable-input"></div><div class="editable-buttons"></div></div><div class="editable-error-block"></div></div></form>',e.fn.editableform.loading='<div class="editableform-loading"></div>',e.fn.editableform.buttons='<button type="submit" class="editable-submit">ok</button><button type="button" class="editable-cancel">cancel</button>',e.fn.editableform.errorGroupClass=null,e.fn.editableform.errorBlockClass="editable-error"})(window.jQuery),function(e){e.fn.editableutils={inherit:function(e,t){var n=function(){};n.prototype=t.prototype,e.prototype=new n,e.prototype.constructor=e,e.superclass=t.prototype},setCursorPosition:function(e,t){if(e.setSelectionRange)e.setSelectionRange(t,t);else if(e.createTextRange){var n=e.createTextRange();n.collapse(!0),n.moveEnd("character",t),n.moveStart("character",t),n.select()}},tryParseJson:function(e,t){if(typeof e=="string"&&e.length&&e.match(/^[\{\[].*[\}\]]$/))if(t)try{e=(new Function("return "+e))()}catch(n){}finally{return e}else e=(new Function("return "+e))();return e},sliceObj:function(t,n,r){var i,s,o={};if(!e.isArray(n)||!n.length)return o;for(var u=0;u<n.length;u++){i=n[u],t.hasOwnProperty(i)&&(o[i]=t[i]);if(r===!0)continue;s=i.toLowerCase(),t.hasOwnProperty(s)&&(o[i]=t[s])}return o},getConfigData:function(t){var n={};return e.each(t.data(),function(e,t){if(typeof t!="object"||t&&typeof t=="object"&&t.constructor===Object)n[e]=t}),n},objectKeys:function(e){if(Object.keys)return Object.keys(e);if(e!==Object(e))throw new TypeError("Object.keys called on a non-object");var t=[],n;for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.push(n);return t},escape:function(t){return e("<div>").text(t).html()}}}(window.jQuery),function(e){var t=function(e,t){this.init(e,t)};t.prototype={containerName:null,innerCss:null,init:function(n,r){this.$element=e(n),this.options=e.extend({},e.fn.editableContainer.defaults,e.fn.editableutils.getConfigData(this.$element),r),this.splitOptions(),this.initContainer(),this.$element.on("destroyed",e.proxy(function(){this.destroy()},this)),e(document).data("editable-handlers-attached")||(e(document).on("keyup.editable",function(t){t.which===27&&e(".editable-open").editableContainer("hide")}),e(document).on("click.editable",function(n){var r=e(n.target);if(r.is(".editable-container")||r.parents(".editable-container").length||r.parents(".ui-datepicker-header").length)return;t.prototype.closeOthers(n.target)}),e(document).data("editable-handlers-attached",!0))},splitOptions:function(){this.containerOptions={},this.formOptions={};var t=e.fn[this.containerName].defaults;for(var n in this.options)n in t?this.containerOptions[n]=this.options[n]:this.formOptions[n]=this.options[n]},initContainer:function(){this.call(this.containerOptions)},initForm:function(){return this.formOptions.scope=this.$element[0],this.$form=e("<div>").editableform(this.formOptions).on({save:e.proxy(this.save,this),cancel:e.proxy(function(){this.hide("cancel")},this),nochange:e.proxy(function(){this.hide("nochange")},this),show:e.proxy(this.setPosition,this),rendering:e.proxy(this.setPosition,this),rendered:e.proxy(function(){this.$element.triggerHandler("shown")},this)}),this.$form},tip:function(){return this.container().$tip},container:function(){return this.$element.data(this.containerName)},call:function(){this.$element[this.containerName].apply(this.$element,arguments)},show:function(e){this.$element.addClass("editable-open"),e!==!1&&this.closeOthers(this.$element[0]),this.innerShow()},innerShow:function(){this.call("show"),this.tip().addClass("editable-container"),this.initForm(),this.tip().find(this.innerCss).empty().append(this.$form),this.$form.editableform("render")},hide:function(e){if(!this.tip()||!this.tip().is(":visible")||!this.$element.hasClass("editable-open"))return;this.$element.removeClass("editable-open"),this.innerHide(),this.$element.triggerHandler("hidden",e)},innerHide:function(){this.call("hide")},toggle:function(e){this.tip&&this.tip().is(":visible")?this.hide():this.show(e)},setPosition:function(){},save:function(e,t){this.hide("save"),this.$element.triggerHandler("save",t)},option:function(e,t){this.options[e]=t,e in this.containerOptions?(this.containerOptions[e]=t,this.setContainerOption(e,t)):(this.formOptions[e]=t,this.$form&&this.$form.editableform("option",e,t))},setContainerOption:function(e,t){this.call("option",e,t)},destroy:function(){this.call("destroy")},closeOthers:function(t){e(".editable-open").each(function(n,r){if(r===t||e(r).find(t).length)return;var i=e(r),s=i.data("editableContainer");if(!s)return;s.options.onblur==="cancel"?i.data("editableContainer").hide("onblur"):s.options.onblur==="submit"&&i.data("editableContainer").tip().find("form").submit()})},activate:function(){this.tip&&this.tip().is(":visible")&&this.$form&&this.$form.data("editableform").input.activate()}},e.fn.editableContainer=function(n){var r=arguments;return this.each(function(){var i=e(this),s="editableContainer",o=i.data(s),u=typeof n=="object"&&n;o||i.data(s,o=new t(this,u)),typeof n=="string"&&o[n].apply(o,Array.prototype.slice.call(r,1))})},e.fn.editableContainer.Constructor=t,e.fn.editableContainer.defaults={value:null,placement:"top",autohide:!0,onblur:"cancel"},jQuery.event.special.destroyed={remove:function(e){e.handler&&e.handler()}}}(window.jQuery),function(e){var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.editable.defaults,e.fn.editableutils.getConfigData(this.$element),n),this.init()};t.prototype={constructor:t,init:function(){var t,n=!1,r,i;if(!e.fn.editableContainer){e.error("You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)");return}this.options.name=this.options.name||this.$element.attr("id");if(typeof e.fn.editabletypes[this.options.type]!="function"){e.error("Unknown type: "+this.options.type);return}t=e.fn.editabletypes[this.options.type],this.typeOptions=e.fn.editableutils.sliceObj(this.options,e.fn.editableutils.objectKeys(t.defaults)),this.input=new t(this.typeOptions),this.options.value===undefined||this.options.value===null?(this.value=this.input.html2value(e.trim(this.$element.html())),n=!0):(this.options.value=e.fn.editableutils.tryParseJson(this.options.value,!0),typeof this.options.value=="string"?this.value=this.input.str2value(this.options.value):this.value=this.options.value),this.$element.addClass("editable"),this.options.toggle!=="manual"?(this.$element.addClass("editable-click"),this.$element.on(this.options.toggle+".editable",e.proxy(function(e){e.preventDefault();if(this.options.toggle==="mouseenter")this.show();else{var t=this.options.toggle!=="click";this.toggle(t)}},this))):this.$element.attr("tabindex",-1),r=!n&&this.value!==null&&this.value!==undefined,r&=this.options.autotext==="always"||this.options.autotext==="auto"&&!this.$element.text().length,e.when(r?this.render():!0).then(e.proxy(function(){this.options.disabled?this.disable():this.enable(),this.$element.triggerHandler("init",this)},this))},render:function(){if(this.options.display===!1)return;return this.input.options.hasOwnProperty("source")?this.input.value2html(this.value,this.$element[0],this.options.display):typeof this.options.display=="function"?this.options.display.call(this.$element[0],this.value):this.input.value2html(this.value,this.$element[0])},enable:function(){this.options.disabled=!1,this.$element.removeClass("editable-disabled"),this.handleEmpty(),this.options.toggle!=="manual"&&this.$element.attr("tabindex")==="-1"&&this.$element.removeAttr("tabindex")},disable:function(){this.options.disabled=!0,this.hide(),this.$element.addClass("editable-disabled"),this.handleEmpty(),this.$element.attr("tabindex",-1)},toggleDisabled:function(){this.options.disabled?this.enable():this.disable()},option:function(t,n){if(t&&typeof t=="object"){e.each(t,e.proxy(function(t,n){this.option(e.trim(t),n)},this));return}this.options[t]=n;if(t==="disabled"){n?this.disable():this.enable();return}t==="value"&&this.setValue(n),this.container&&this.container.option(t,n)},handleEmpty:function(){if(this.options.display===!1)return;var t="editable-empty";this.options.disabled?this.$element.hasClass(t)&&(this.$element.empty(),this.$element.removeClass(t)):e.trim(this.$element.text())===""?this.$element.addClass(t).text(this.options.emptytext):this.$element.removeClass(t)},show:function(t){if(this.options.disabled)return;if(!this.container){var n=e.extend({},this.options,{value:this.value});this.$element.editableContainer(n),this.$element.on("save.internal",e.proxy(this.save,this)),this.container=this.$element.data("editableContainer")}else if(this.container.tip().is(":visible"))return;this.container.show(t)},hide:function(){this.container&&this.container.hide()},toggle:function(e){this.container&&this.container.tip().is(":visible")?this.hide():this.show(e)},save:function(e,t){typeof this.options.url!="function"&&this.options.display!==!1&&t.response===undefined&&this.input.value2str(this.value)!==this.input.value2str(t.newValue)?this.$element.addClass("editable-unsaved"):this.$element.removeClass("editable-unsaved"),this.setValue(t.newValue)},validate:function(){if(typeof this.options.validate=="function")return this.options.validate.call(this,this.value)},setValue:function(t,n){n?this.value=this.input.str2value(t):this.value=t,this.container&&this.container.option("value",this.value),e.when(this.render()).then(e.proxy(function(){this.handleEmpty()},this))},activate:function(){this.container&&this.container.activate()}},e.fn.editable=function(n){var r={},i=arguments,s="editable";switch(n){case"validate":return this.each(function(){var t=e(this),n=t.data(s),i;n&&(i=n.validate())&&(r[n.options.name]=i)}),r;case"getValue":return this.each(function(){var t=e(this),n=t.data(s);n&&n.value!==undefined&&n.value!==null&&(r[n.options.name]=n.input.value2submit(n.value))}),r;case"submit":var o=arguments[1]||{},u=this,a=this.editable("validate"),f;return e.isEmptyObject(a)?(f=this.editable("getValue"),o.data&&e.extend(f,o.data),e.ajax(e.extend({url:o.url,data:f,type:"POST"},o.ajaxOptions)).success(function(e){typeof o.success=="function"&&o.success.call(u,e,o)}).error(function(){typeof o.error=="function"&&o.error.apply(u,arguments)})):typeof o.error=="function"&&o.error.call(u,a),this}return this.each(function(){var r=e(this),o=r.data(s),u=typeof n=="object"&&n;o||r.data(s,o=new t(this,u)),typeof n=="string"&&o[n].apply(o,Array.prototype.slice.call(i,1))})},e.fn.editable.defaults={type:"text",disabled:!1,toggle:"click",emptytext:"Empty",autotext:"auto",value:null,display:null}}(window.jQuery),function(e){e.fn.editabletypes={};var t=function(){};t.prototype={init:function(t,n,r){this.type=t,this.options=e.extend({},r,n),this.$input=null,this.$clear=null,this.error=null},render:function(){this.$input=e(this.options.tpl),this.options.inputclass&&this.$input.addClass(this.options.inputclass),this.options.placeholder&&this.$input.attr("placeholder",this.options.placeholder)},value2html:function(t,n){e(n).text(t)},html2value:function(t){return e("<div>").html(t).text()},value2str:function(e){return e},str2value:function(e){return e},value2submit:function(e){return e},value2input:function(e){this.$input.val(e)},input2value:function(){return this.$input.val()},activate:function(){this.$input.is(":visible")&&this.$input.focus()},clear:function(){this.$input.val(null)},escape:function(t){return e("<div>").text(t).html()},autosubmit:function(){}},t.defaults={tpl:"",inputclass:"input-medium",name:null},e.extend(e.fn.editabletypes,{abstractinput:t})}(window.jQuery),function(e){var t=function(e){};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{render:function(){t.superclass.render.call(this);var n=e.Deferred();return this.error=null,this.sourceData=null,this.prependData=null,this.onSourceReady(function(){this.renderList(),n.resolve()},function(){this.error=this.options.sourceError,n.resolve()}),n.promise()},html2value:function(e){return null},value2html:function(t,n,r){var i=e.Deferred();return this.onSourceReady(function(){typeof r=="function"?r.call(n,t,this.sourceData):this.value2htmlFinal(t,n),i.resolve()},function(){i.resolve()}),i.promise()},onSourceReady:function(t,n){if(e.isArray(this.sourceData)){t.call(this);return}try{this.options.source=e.fn.editableutils.tryParseJson(this.options.source,!1)}catch(r){n.call(this);return}if(typeof this.options.source=="string"){if(this.options.sourceCache){var i=this.options.source+(this.options.name?"-"+this.options.name:""),s;e(document).data(i)||e(document).data(i,{}),s=e(document).data(i);if(s.loading===!1&&s.sourceData){this.sourceData=s.sourceData,t.call(this);return}if(s.loading===!0){s.callbacks.push(e.proxy(function(){this.sourceData=s.sourceData,t.call(this)},this)),s.err_callbacks.push(e.proxy(n,this));return}s.loading=!0,s.callbacks=[],s.err_callbacks=[]}e.ajax({url:this.options.source,type:"get",cache:!1,data:this.options.name?{name:this.options.name}:{},dataType:"json",success:e.proxy(function(r){s&&(s.loading=!1),this.sourceData=this.makeArray(r),e.isArray(this.sourceData)?(this.doPrepend(),t.call(this),s&&(s.sourceData=this.sourceData,e.each(s.callbacks,function(){this.call()}))):(n.call(this),s&&e.each(s.err_callbacks,function(){this.call()}))},this),error:e.proxy(function(){n.call(this),s&&(s.loading=!1,e.each(s.err_callbacks,function(){this.call()}))},this)})}else this.sourceData=this.makeArray(this.options.source),e.isArray(this.sourceData)?(this.doPrepend(),t.call(this)):n.call(this)},doPrepend:function(){if(this.options.prepend===null||this.options.prepend===undefined)return;e.isArray(this.prependData)||(this.options.prepend=e.fn.editableutils.tryParseJson(this.options.prepend,!0),typeof this.options.prepend=="string"&&(this.options.prepend={"":this.options.prepend}),this.prependData=this.makeArray(this.options.prepend)),e.isArray(this.prependData)&&e.isArray(this.sourceData)&&(this.sourceData=this.prependData.concat(this.sourceData))},renderList:function(){},value2htmlFinal:function(e,t){},makeArray:function(t){var n,r,i=[],s;if(!t||typeof t=="string")return null;if(e.isArray(t)){s=function(e,t){r={value:e,text:t};if(n++>=2)return!1};for(var o=0;o<t.length;o++)typeof t[o]=="object"?(n=0,e.each(t[o],s),n===1?i.push(r):n>1&&t[o].hasOwnProperty("value")&&t[o].hasOwnProperty("text")&&i.push(t[o])):i.push({value:t[o],text:t[o]})}else e.each(t,function(e,t){i.push({value:e,text:t})});return i},itemByVal:function(t){if(e.isArray(this.sourceData))for(var n=0;n<this.sourceData.length;n++)if(this.sourceData[n].value==t)return this.sourceData[n]}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{source:null,prepend:!1,sourceError:"Error when loading list",sourceCache:!0}),e.fn.editabletypes.list=t}(window.jQuery),function(e){var t=function(e){this.init("text",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{activate:function(){this.$input.is(":visible")&&(this.$input.focus(),e.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length))}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',placeholder:null}),e.fn.editabletypes.text=t}(window.jQuery),function(e){var t=function(e){this.init("textarea",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{render:function(){t.superclass.render.call(this),this.$input.keydown(function(t){t.ctrlKey&&t.which===13&&e(this).closest("form").submit()})},value2html:function(t,n){var r="",i;if(t){i=t.split("\n");for(var s=0;s<i.length;s++)i[s]=e("<div>").text(i[s]).html();r=i.join("<br>")}e(n).html(r)},html2value:function(t){if(!t)return"";var n=t.split(/<br\s*\/?>/i);for(var r=0;r<n.length;r++)n[r]=e("<div>").html(n[r]).text();return n.join("\n")},activate:function(){this.$input.is(":visible")&&(e.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length),this.$input.focus())}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{tpl:"<textarea></textarea>",inputclass:"input-large",placeholder:null}),e.fn.editabletypes.textarea=t}(window.jQuery),function(e){var t=function(e){this.init("select",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.list),e.extend(t.prototype,{renderList:function(){if(!e.isArray(this.sourceData))return;for(var t=0;t<this.sourceData.length;t++)this.$input.append(e("<option>",{value:this.sourceData[t].value}).text(this.sourceData[t].text));this.$input.on("keydown.editable",function(t){t.which===13&&e(this).closest("form").submit()})},value2htmlFinal:function(e,n){var r="",i=this.itemByVal(e);i&&(r=i.text),t.superclass.constructor.superclass.value2html(r,n)},autosubmit:function(){this.$input.off("keydown.editable").on("change.editable",function(){e(this).closest("form").submit()})}}),t.defaults=e.extend({},e.fn.editabletypes.list.defaults,{tpl:"<select></select>"}),e.fn.editabletypes.select=t}(window.jQuery),function(e){var t=function(e){this.init("checklist",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.list),e.extend(t.prototype,{renderList:function(){var t,n;if(!e.isArray(this.sourceData))return;for(var r=0;r<this.sourceData.length;r++)t=e("<label>").append(e("<input>",{type:"checkbox",value:this.sourceData[r].value,name:this.options.name})).append(e("<span>").text(" "+this.sourceData[r].text)),e("<div>").append(t).appendTo(this.$input)},value2str:function(t){return e.isArray(t)?t.sort().join(e.trim(this.options.separator)):""},str2value:function(t){var n,r=null;return typeof t=="string"&&t.length?(n=new RegExp("\\s*"+e.trim(this.options.separator)+"\\s*"),r=t.split(n)):e.isArray(t)&&(r=t),r},value2input:function(t){var n=this.$input.find('input[type="checkbox"]');n.removeAttr("checked"),e.isArray(t)&&t.length&&n.each(function(n,r){var i=e(r);e.each(t,function(e,t){i.val()==t&&i.attr("checked","checked")})})},input2value:function(){var t=[];return this.$input.find("input:checked").each(function(n,r){t.push(e(r).val())}),t},value2htmlFinal:function(t,n){var r=[],i=e.grep(this.sourceData,function(n){return e.grep(t,function(e){return e==n.value}).length});i.length?(e.each(i,function(t,n){r.push(e.fn.editableutils.escape(n.text))}),e(n).html(r.join("<br>"))):e(n).empty()},activate:function(){this.$input.find('input[type="checkbox"]').first().focus()},autosubmit:function(){this.$input.find('input[type="checkbox"]').on("keydown",function(t){t.which===13&&e(this).closest("form").submit()})}}),t.defaults=e.extend({},e.fn.editabletypes.list.defaults,{tpl:"<div></div>",inputclass:"editable-checklist",separator:","}),e.fn.editabletypes.checklist=t}(window.jQuery),function(e){var t=function(e){this.init("password",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),e.extend(t.prototype,{value2html:function(t,n){t?e(n).text("[hidden]"):e(n).empty()},html2value:function(e){return null}}),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="password">'}),e.fn.editabletypes.password=t}(window.jQuery),function(e){var t=function(e){this.init("email",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="email">'}),e.fn.editabletypes.email=t}(window.jQuery),function(e){var t=function(e){this.init("url",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="url">'}),e.fn.editabletypes.url=t}(window.jQuery),function(e){var t=function(e){this.init("tel",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="tel">'}),e.fn.editabletypes.tel=t}(window.jQuery),function(e){var t=function(e){this.init("number",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.text),e.extend(t.prototype,{render:function(){t.superclass.render.call(this),this.options.min!==null&&this.$input.attr("min",this.options.min),this.options.max!==null&&this.$input.attr("max",this.options.max),this.options.step!==null&&this.$input.attr("step",this.options.step)}}),t.defaults=e.extend({},e.fn.editabletypes.text.defaults,{tpl:'<input type="number">',inputclass:"input-mini",min:null,max:null,step:null}),e.fn.editabletypes.number=t}(window.jQuery),function(e){var t=function(e){this.init("range",e,t.defaults)};e.fn.editableutils.inherit(t,e.fn.editabletypes.number),e.extend(t.prototype,{render:function(){this.$input=e(this.options.tpl);var t=this.$input.filter("input");this.options.inputclass&&t.addClass(this.options.inputclass),this.options.min!==null&&t.attr("min",this.options.min),this.options.max!==null&&t.attr("max",this.options.max),this.options.step!==null&&t.attr("step",this.options.step),t.on("input",function(){e(this).siblings("output").text(e(this).val())})},activate:function(){this.$input.filter("input").focus()}}),t.defaults=e.extend({},e.fn.editabletypes.number.defaults,{tpl:'<input type="range"><output style="width: 30px; display: inline-block"></output>',inputclass:"input-medium"}),e.fn.editabletypes.range=t}(window.jQuery),function(e){e.extend(e.fn.editableform.Constructor.prototype,{initTemplate:function(){this.$form=e(e.fn.editableform.template),this.$form.find(".editable-error-block").addClass("help-block")}}),e.fn.editableform.buttons='<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button><button type="button" class="btn editable-cancel"><i class="icon-remove"></i></button>',e.fn.editableform.errorGroupClass="error",e.fn.editableform.errorBlockClass=null}(window.jQuery),function(e){e.extend(e.fn.editableContainer.Constructor.prototype,{containerName:"popover",innerCss:e(e.fn.popover.defaults.template).find("p").length?".popover-content p":".popover-content",initContainer:function(){e.extend(this.containerOptions,{trigger:"manual",selector:!1,content:" "}),this.call(this.containerOptions)},setContainerOption:function(e,t){this.container().options[e]=t},setPosition:function(){(function(){var e=this.tip(),t,n,r,i,s,o;s=typeof this.options.placement=="function"?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,t=/in/.test(s),e.removeClass("top right bottom left").css({top:0,left:0,display:"block"}),n=this.getPosition(t),r=e[0].offsetWidth,i=e[0].offsetHeight;switch(t?s.split(" ")[1]:s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}e.offset(o).addClass(s).addClass("in")}).call(this.container())}})}(window.jQuery),function(e){var t=function(n){this.init("date",n,t.defaults);var r=e.fn.editableutils.sliceObj(this.options,["format"]);this.options.datepicker=e.extend({},t.defaults.datepicker,r,n.datepicker),this.options.viewformat||(this.options.viewformat=this.options.datepicker.format),this.options.datepicker.language=this.options.datepicker.language||"en",this.dpg=e.fn.datepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.datepicker.format),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat)};e.fn.editableutils.inherit(t,e.fn.editabletypes.abstractinput),e.extend(t.prototype,{render:function(){t.superclass.render.call(this),this.$input.datepicker(this.options.datepicker),this.options.clear&&(this.$clear=e('<a href="#"></a>').html(this.options.clear).click(e.proxy(function(e){e.preventDefault(),e.stopPropagation(),this.clear()},this)))},value2html:function(e,n){var r=e?this.dpg.formatDate(e,this.parsedViewFormat,this.options.datepicker.language):"";t.superclass.value2html(r,n)},html2value:function(e){return e?this.dpg.parseDate(e,this.parsedViewFormat,this.options.datepicker.language):null},value2str:function(e){return e?this.dpg.formatDate(e,this.parsedFormat,this.options.datepicker.language):""},str2value:function(e){return e?this.dpg.parseDate(e,this.parsedFormat,this.options.datepicker.language):null},value2submit:function(e){return this.value2str(e)},value2input:function(e){this.$input.datepicker("update",e)},input2value:function(){return this.$input.data("datepicker").date},activate:function(){},clear:function(){this.$input.data("datepicker").date=null,this.$input.find(".active").removeClass("active")},autosubmit:function(){this.$input.on("changeDate",function(t){var n=e(this).closest("form");setTimeout(function(){n.submit()},200)})}}),t.defaults=e.extend({},e.fn.editabletypes.abstractinput.defaults,{tpl:"<div></div>",inputclass:"editable-date well",format:"yyyy-mm-dd",viewformat:null,datepicker:{weekStart:0,startView:0,autoclose:!1},clear:"&times; clear"}),e.fn.editabletypes.date=t}(window.jQuery),!function(e){function t(){return new Date(Date.UTC.apply(Date,arguments))}function n(){var e=new Date;return t(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate())}var r=function(t,n){var r=this;this.element=e(t),this.language=n.language||this.element.data("date-language")||"en",this.language=this.language in i?this.language:"en",this.format=s.parseFormat(n.format||this.element.data("date-format")||"mm/dd/yyyy"),this.isInline=!1,this.isInput=this.element.is("input"),this.component=this.element.is(".date")?this.element.find(".add-on"):!1,this.hasInput=this.component&&this.element.find("input").length,this.component&&this.component.length===0&&(this.component=!1),this.isInput?this.element.on({focus:e.proxy(this.show,this),keyup:e.proxy(this.update,this),keydown:e.proxy(this.keydown,this)}):this.component&&this.hasInput?(this.element.find("input").on({focus:e.proxy(this.show,this),keyup:e.proxy(this.update,this),keydown:e.proxy(this.keydown,this)}),this.component.on("click",e.proxy(this.show,this))):this.element.is("div")?this.isInline=!0:this.element.on("click",e.proxy(this.show,this)),this.picker=e(s.template).appendTo(this.isInline?this.element:"body").on({click:e.proxy(this.click,this),mousedown:e.proxy(this.mousedown,this)}),this.isInline?this.picker.addClass("datepicker-inline"):this.picker.addClass("dropdown-menu"),e(document).on("mousedown",function(t){e(t.target).closest(".datepicker").length==0&&r.hide()}),this.autoclose=!1,"autoclose"in n?this.autoclose=n.autoclose:"dateAutoclose"in this.element.data()&&(this.autoclose=this.element.data("date-autoclose")),this.keyboardNavigation=!0,"keyboardNavigation"in n?this.keyboardNavigation=n.keyboardNavigation:"dateKeyboardNavigation"in this.element.data()&&(this.keyboardNavigation=this.element.data("date-keyboard-navigation"));switch(n.startView||this.element.data("date-start-view")){case 2:case"decade":this.viewMode=this.startViewMode=2;break;case 1:case"year":this.viewMode=this.startViewMode=1;break;case 0:case"month":default:this.viewMode=this.startViewMode=0}this.todayBtn=n.todayBtn||this.element.data("date-today-btn")||!1,this.todayHighlight=n.todayHighlight||this.element.data("date-today-highlight")||!1,this.weekStart=(n.weekStart||this.element.data("date-weekstart")||i[this.language].weekStart||0)%7,this.weekEnd=(this.weekStart+6)%7,this.startDate=-Infinity,this.endDate=Infinity,this.setStartDate(n.startDate||this.element.data("date-startdate")),this.setEndDate(n.endDate||this.element.data("date-enddate")),this.fillDow(),this.fillMonths(),this.update(),this.showMode(),this.isInline&&this.show()};r.prototype={constructor:r,show:function(t){this.picker.show(),this.height=this.component?this.component.outerHeight():this.element.outerHeight(),this.update(),this.place(),e(window).on("resize",e.proxy(this.place,this)),t&&(t.stopPropagation(),t.preventDefault()),this.element.trigger({type:"show",date:this.date})},hide:function(t){if(this.isInline)return;this.picker.hide(),e(window).off("resize",this.place),this.viewMode=this.startViewMode,this.showMode(),this.isInput||e(document).off("mousedown",this.hide),t&&t.currentTarget.value&&this.setValue(),this.element.trigger({type:"hide",date:this.date})},getDate:function(){var e=this.getUTCDate();return new Date(e.getTime()+e.getTimezoneOffset()*6e4)},getUTCDate:function(){return this.date},setDate:function(e){this.setUTCDate(new Date(e.getTime()-e.getTimezoneOffset()*6e4))},setUTCDate:function(e){this.date=e,this.setValue()},setValue:function(){var e=this.getFormattedDate();this.isInput?this.element.prop("value",e):(this.component&&this.element.find("input").prop("value",e),this.element.data("date",e))},getFormattedDate:function(e){return e==undefined&&(e=this.format),s.formatDate(this.date,e,this.language)},setStartDate:function(e){this.startDate=e||-Infinity,this.startDate!==-Infinity&&(this.startDate=s.parseDate(this.startDate,this.format,this.language)),this.update(),this.updateNavArrows()},setEndDate:function(e){this.endDate=e||Infinity,this.endDate!==Infinity&&(this.endDate=s.parseDate(this.endDate,this.format,this.language)),this.update(),this.updateNavArrows()},place:function(){if(this.isInline)return;var t=parseInt(this.element.parents().filter(function(){return e(this).css("z-index")!="auto"}).first().css("z-index"))+10,n=this.component?this.component.offset():this.element.offset();this.picker.css({top:n.top+this.height,left:n.left,zIndex:t})},update:function(){var e,t=!1;arguments&&arguments.length&&(typeof arguments[0]=="string"||arguments[0]instanceof Date)?(e=arguments[0],t=!0):e=this.isInput?this.element.prop("value"):this.element.data("date")||this.element.find("input").prop("value"),this.date=s.parseDate(e,this.format,this.language),t&&this.setValue(),this.date<this.startDate?this.viewDate=new Date(this.startDate):this.date>this.endDate?this.viewDate=new Date(this.endDate):this.viewDate=new Date(this.date),this.fill()},fillDow:function(){var e=this.weekStart,t="<tr>";while(e<this.weekStart+7)t+='<th class="dow">'+i[this.language].daysMin[e++%7]+"</th>";t+="</tr>",this.picker.find(".datepicker-days thead").append(t)},fillMonths:function(){var e="",t=0;while(t<12)e+='<span class="month">'+i[this.language].monthsShort[t++]+"</span>";this.picker.find(".datepicker-months td").html(e)},fill:function(){var e=new Date(this.viewDate),n=e.getUTCFullYear(),r=e.getUTCMonth(),o=this.startDate!==-Infinity?this.startDate.getUTCFullYear():-Infinity,u=this.startDate!==-Infinity?this.startDate.getUTCMonth():-Infinity,a=this.endDate!==Infinity?this.endDate.getUTCFullYear():Infinity,f=this.endDate!==Infinity?this.endDate.getUTCMonth():Infinity,l=this.date&&this.date.valueOf(),c=new Date;this.picker.find(".datepicker-days thead th:eq(1)").text(i[this.language].months[r]+" "+n),this.picker.find("tfoot th.today").text(i[this.language].today).toggle(this.todayBtn!==!1),this.updateNavArrows(),this.fillMonths();var h=t(n,r-1,28,0,0,0,0),p=s.getDaysInMonth(h.getUTCFullYear(),h.getUTCMonth());h.setUTCDate(p),h.setUTCDate(p-(h.getUTCDay()-this.weekStart+7)%7);var d=new Date(h);d.setUTCDate(d.getUTCDate()+42),d=d.valueOf();var v=[],m;while(h.valueOf()<d){h.getUTCDay()==this.weekStart&&v.push("<tr>"),m="";if(h.getUTCFullYear()<n||h.getUTCFullYear()==n&&h.getUTCMonth()<r)m+=" old";else if(h.getUTCFullYear()>n||h.getUTCFullYear()==n&&h.getUTCMonth()>r)m+=" new";this.todayHighlight&&h.getUTCFullYear()==c.getFullYear()&&h.getUTCMonth()==c.getMonth()&&h.getUTCDate()==c.getDate()&&(m+=" today"),l&&h.valueOf()==l&&(m+=" active");if(h.valueOf()<this.startDate||h.valueOf()>this.endDate)m+=" disabled";v.push('<td class="day'+m+'">'+h.getUTCDate()+"</td>"),h.getUTCDay()==this.weekEnd&&v.push("</tr>"),h.setUTCDate(h.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(v.join(""));var g=this.date&&this.date.getUTCFullYear(),y=this.picker.find(".datepicker-months").find("th:eq(1)").text(n).end().find("span").removeClass("active");g&&g==n&&y.eq(this.date.getUTCMonth()).addClass("active"),(n<o||n>a)&&y.addClass("disabled"),n==o&&y.slice(0,u).addClass("disabled"),n==a&&y.slice(f+1).addClass("disabled"),v="",n=parseInt(n/10,10)*10;var b=this.picker.find(".datepicker-years").find("th:eq(1)").text(n+"-"+(n+9)).end().find("td");n-=1;for(var w=-1;w<11;w++)v+='<span class="year'+(w==-1||w==10?" old":"")+(g==n?" active":"")+(n<o||n>a?" disabled":"")+'">'+n+"</span>",n+=1;b.html(v)},updateNavArrows:function(){var e=new Date(this.viewDate),t=e.getUTCFullYear(),n=e.getUTCMonth();switch(this.viewMode){case 0:this.startDate!==-Infinity&&t<=this.startDate.getUTCFullYear()&&n<=this.startDate.getUTCMonth()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==Infinity&&t>=this.endDate.getUTCFullYear()&&n>=this.endDate.getUTCMonth()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 1:case 2:this.startDate!==-Infinity&&t<=this.startDate.getUTCFullYear()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),this.endDate!==Infinity&&t>=this.endDate.getUTCFullYear()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"})}},click:function(n){n.stopPropagation(),n.preventDefault();var r=e(n.target).closest("span, td, th");if(r.length==1)switch(r[0].nodeName.toLowerCase()){case"th":switch(r[0].className){case"switch":this.showMode(1);break;case"prev":case"next":var i=s.modes[this.viewMode].navStep*(r[0].className=="prev"?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,i);break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,i)}this.fill();break;case"today":var o=new Date;o=t(o.getFullYear(),o.getMonth(),o.getDate(),0,0,0),this.showMode(-2);var u=this.todayBtn=="linked"?null:"view";this._setDate(o,u)}break;case"span":if(!r.is(".disabled")){this.viewDate.setUTCDate(1);if(r.is(".month")){var a=r.parent().find("span").index(r);this.viewDate.setUTCMonth(a),this.element.trigger({type:"changeMonth",date:this.viewDate})}else{var f=parseInt(r.text(),10)||0;this.viewDate.setUTCFullYear(f),this.element.trigger({type:"changeYear",date:this.viewDate})}this.showMode(-1),this.fill()}break;case"td":if(r.is(".day")&&!r.is(".disabled")){var l=parseInt(r.text(),10)||1,f=this.viewDate.getUTCFullYear(),a=this.viewDate.getUTCMonth();r.is(".old")?a==0?(a=11,f-=1):a-=1:r.is(".new")&&(a==11?(a=0,f+=1):a+=1),this._setDate(t(f,a,l,0,0,0,0))}}},_setDate:function(e,t){if(!t||t=="date")this.date=e;if(!t||t=="view")this.viewDate=e;this.fill(),this.setValue(),this.element.trigger({type:"changeDate",date:this.date});var n;this.isInput?n=this.element:this.component&&(n=this.element.find("input")),n&&(n.change(),this.autoclose&&this.hide())},moveMonth:function(e,t){if(!t)return e;var n=new Date(e.valueOf()),r=n.getUTCDate(),i=n.getUTCMonth(),s=Math.abs(t),o,u;t=t>0?1:-1;if(s==1){u=t==-1?function(){return n.getUTCMonth()==i}:function(){return n.getUTCMonth()!=o},o=i+t,n.setUTCMonth(o);if(o<0||o>11)o=(o+12)%12}else{for(var a=0;a<s;a++)n=this.moveMonth(n,t);o=n.getUTCMonth(),n.setUTCDate(r),u=function(){return o!=n.getUTCMonth()}}while(u())n.setUTCDate(--r),n.setUTCMonth(o);return n},moveYear:function(e,t){return this.moveMonth(e,t*12)},dateWithinRange:function(e){return e>=this.startDate&&e<=this.endDate},keydown:function(e){if(this.picker.is(":not(:visible)")){e.keyCode==27&&this.show();return}var t=!1,n,r,i,s,o;switch(e.keyCode){case 27:this.hide(),e.preventDefault();break;case 37:case 39:if(!this.keyboardNavigation)break;n=e.keyCode==37?-1:1,e.ctrlKey?(s=this.moveYear(this.date,n),o=this.moveYear(this.viewDate,n)):e.shiftKey?(s=this.moveMonth(this.date,n),o=this.moveMonth(this.viewDate,n)):(s=new Date(this.date),s.setUTCDate(this.date.getUTCDate()+n),o=new Date(this.viewDate),o.setUTCDate(this.viewDate.getUTCDate()+n)),this.dateWithinRange(s)&&(this.date=s,this.viewDate=o,this.setValue(),this.update(),e.preventDefault(),t=!0);break;case 38:case 40:if(!this.keyboardNavigation)break;n=e.keyCode==38?-1:1,e.ctrlKey?(s=this.moveYear(this.date,n),o=this.moveYear(this.viewDate,n)):e.shiftKey?(s=this.moveMonth(this.date,n),o=this.moveMonth(this.viewDate,n)):(s=new Date(this.date),s.setUTCDate(this.date.getUTCDate()+n*7),o=new Date(this.viewDate),o.setUTCDate(this.viewDate.getUTCDate()+n*7)),this.dateWithinRange(s)&&(this.date=s,this.viewDate=o,this.setValue(),this.update(),e.preventDefault(),t=!0);break;case 13:this.hide(),e.preventDefault();break;case 9:this.hide()}if(t){this.element.trigger({type:"changeDate",date:this.date});var u;this.isInput?u=this.element:this.component&&(u=this.element.find("input")),u&&u.change()}},showMode:function(e){e&&(this.viewMode=Math.max(0,Math.min(2,this.viewMode+e))),this.picker.find(">div").hide().filter(".datepicker-"+s.modes[this.viewMode].clsName).css("display","block"),this.updateNavArrows()}},e.fn.datepicker=function(t){var n=Array.apply(null,arguments);return n.shift(),this.each(function(){var i=e(this),s=i.data("datepicker"),o=typeof t=="object"&&t;s||i.data("datepicker",s=new r(this,e.extend({},e.fn.datepicker.defaults,o))),typeof t=="string"&&typeof s[t]=="function"&&s[t].apply(s,n)})},e.fn.datepicker.defaults={},e.fn.datepicker.Constructor=r;var i=e.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today"}},s={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(e){return e%4===0&&e%100!==0||e%400===0},getDaysInMonth:function(e,t){return[31,s.isLeapYear(e)?29:28,31,30,31,30,31,31,30,31,30,31][t]},validParts:/dd?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[-`{-~\t\n\r]+/g,parseFormat:function(e){var t=e.replace(this.validParts,"\0").split("\0"),n=e.match(this.validParts);if(!t||!t.length||!n||n.length==0)throw new Error("Invalid date format.");return{separators:t,parts:n}},parseDate:function(n,s,o){if(n instanceof Date)return n;if(/^[-+]\d+[dmwy]([\s,]+[-+]\d+[dmwy])*$/.test(n)){var u=/([-+]\d+)([dmwy])/,a=n.match(/([-+]\d+)([dmwy])/g),f,l;n=new Date;for(var c=0;c<a.length;c++){f=u.exec(a[c]),l=parseInt(f[1]);switch(f[2]){case"d":n.setUTCDate(n.getUTCDate()+l);break;case"m":n=r.prototype.moveMonth.call(r.prototype,n,l);break;case"w":n.setUTCDate(n.getUTCDate()+l*7);break;case"y":n=r.prototype.moveYear.call(r.prototype,n,l)}}return t(n.getUTCFullYear(),n.getUTCMonth(),n.getUTCDate(),0,0,0)}var a=n&&n.match(this.nonpunctuation)||[],n=new Date,h={},p=["yyyy","yy","M","MM","m","mm","d","dd"],d={yyyy:function(e,t){return e.setUTCFullYear(t)},yy:function(e,t){return e.setUTCFullYear(2e3+t)},m:function(e,t){t-=1;while(t<0)t+=12;t%=12,e.setUTCMonth(t);while(e.getUTCMonth()!=t)e.setUTCDate(e.getUTCDate()-1);return e},d:function(e,t){return e.setUTCDate(t)}},v,m,f;d.M=d.MM=d.mm=d.m,d.dd=d.d,n=t(n.getFullYear(),n.getMonth(),n.getDate(),0,0,0);if(a.length==s.parts.length){for(var c=0,g=s.parts.length;c<g;c++){v=parseInt(a[c],10),f=s.parts[c];if(isNaN(v))switch(f){case"MM":m=e(i[o].months).filter(function(){var e=this.slice(0,a[c].length),t=a[c].slice(0,e.length);return e==t}),v=e.inArray(m[0],i[o].months)+1;break;case"M":m=e(i[o].monthsShort).filter(function(){var e=this.slice(0,a[c].length),t=a[c].slice(0,e.length);return e==t}),v=e.inArray(m[0],i[o].monthsShort)+1}h[f]=v}for(var c=0,y;c<p.length;c++)y=p[c],y in h&&d[y](n,h[y])}return n},formatDate:function(t,n,r){var s={d:t.getUTCDate(),m:t.getUTCMonth()+1,M:i[r].monthsShort[t.getUTCMonth()],MM:i[r].months[t.getUTCMonth()],yy:t.getUTCFullYear().toString().substring(2),yyyy:t.getUTCFullYear()};s.dd=(s.d<10?"0":"")+s.d,s.mm=(s.m<10?"0":"")+s.m;var t=[],o=e.extend([],n.separators);for(var u=0,a=n.parts.length;u<a;u++)o.length&&t.push(o.shift()),t.push(s[n.parts[u]]);return t.join("")},headTemplate:'<thead><tr><th class="prev"><i class="icon-arrow-left"/></th><th colspan="5" class="switch"></th><th class="next"><i class="icon-arrow-right"/></th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr></tfoot>'};s.template='<div class="datepicker"><div class="datepicker-days"><table class=" table-condensed">'+s.headTemplate+"<tbody></tbody>"+s.footTemplate+"</table>"+"</div>"+'<div class="datepicker-months">'+'<table class="table-condensed">'+s.headTemplate+s.contTemplate+s.footTemplate+"</table>"+"</div>"+'<div class="datepicker-years">'+'<table class="table-condensed">'+s.headTemplate+s.contTemplate+s.footTemplate+"</table>"+"</div>"+"</div>",e.fn.datepicker.DPGlobal=s}(window.jQuery); \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.3.0/inputs-ext/address/address.css b/src/static/jquery/bootstrap-editable-1.3.0/inputs-ext/address/address.css new file mode 100755 index 0000000..f37a43b --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.3.0/inputs-ext/address/address.css @@ -0,0 +1,9 @@ +.editable-address { + display: block; + margin-bottom: 5px; +} + +.editable-address span { + width: 70px; + display: inline-block; +} \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.3.0/inputs-ext/address/address.js b/src/static/jquery/bootstrap-editable-1.3.0/inputs-ext/address/address.js new file mode 100755 index 0000000..0fa31fd --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.3.0/inputs-ext/address/address.js @@ -0,0 +1,165 @@ +/** +Address editable input. +Internally value stored as {city: "Moscow", street: "Lenina", building: "15"} + +@class address +@extends abstractinput +@final +@example +<a href="#" id="address" data-type="address" data-pk="1">awesome</a> +<script> +$(function(){ + $('#address').editable({ + url: '/post', + title: 'Enter city, street and building #', + value: { + city: "Moscow", + street: "Lenina", + building: "15" + } + }); +}); +</script> +**/ +(function ($) { + var Address = function (options) { + this.init('address', options, Address.defaults); + }; + + //inherit from Abstract input + $.fn.editableutils.inherit(Address, $.fn.editabletypes.abstractinput); + + $.extend(Address.prototype, { + /** + Renders input from tpl + + @method render() + **/ + render: function() { + Address.superclass.render.call(this); + }, + + /** + Default method to show value in element. Can be overwritten by display option. + + @method value2html(value, element) + **/ + value2html: function(value, element) { + if(!value) { + $(element).empty(); + return; + } + var html = $('<div>').text(value.city).html() + ', ' + $('<div>').text(value.street).html() + ' st., bld. ' + $('<div>').text(value.building).html(); + $(element).html(html); + }, + + /** + Gets value from element's html + + @method html2value(html) + **/ + html2value: function(html) { + /* + you may write parsing method to get value by element's html + e.g. "Moscow, st. Lenina, bld. 15" => {city: "Moscow", street: "Lenina", building: "15"} + but for complex structures it's not recommended. + Better set value directly via javascript, e.g. + editable({ + value: { + city: "Moscow", + street: "Lenina", + building: "15" + } + }); + */ + return null; + }, + + /** + Converts value to string. + It is used in internal comparing (not for sending to server). + + @method value2str(value) + **/ + value2str: function(value) { + var str = ''; + if(value) { + for(var k in value) { + str = str + k + ':' + value[k] + ';'; + } + } + return str; + }, + + /* + Converts string to value. Used for reading value from 'data-value' attribute. + + @method str2value(str) + */ + str2value: function(str) { + /* + this is mainly for parsing value defined in data-value attribute. + If you will always set value by javascript, no need to overwrite it + */ + return str; + }, + + /** + Sets value of input. + + @method value2input(value) + @param {mixed} value + **/ + value2input: function(value) { + this.$input.find('input[name="city"]').val(value.city); + this.$input.find('input[name="street"]').val(value.street); + this.$input.find('input[name="building"]').val(value.building); + }, + + /** + Returns value of input. + + @method input2value() + **/ + input2value: function() { + return { + city: this.$input.find('input[name="city"]').val(), + street: this.$input.find('input[name="street"]').val(), + building: this.$input.find('input[name="building"]').val() + }; + }, + + /** + Activates input: sets focus on the first field. + + @method activate() + **/ + activate: function() { + this.$input.find('input[name="city"]').focus(); + }, + + /** + Attaches handler to submit form in case of 'showbuttons=false' mode + + @method autosubmit() + **/ + autosubmit: function() { + this.$input.find('input[type="text"]').keydown(function (e) { + if (e.which === 13) { + $(this).closest('form').submit(); + } + }); + } + }); + + Address.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + tpl: '<div><label><span>City: </span><input type="text" name="city" class="input-small"></label></div>'+ + '<div><label><span>Street: </span><input type="text" name="street" class="input-small"></label></div>'+ + '<div><label><span>Building: </span><input type="text" name="building" class="input-mini"></label></div>', + + inputclass: 'editable-address' + }); + + $.fn.editabletypes.address = Address; + +}(window.jQuery)); \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.5.1/CHANGELOG.txt b/src/static/jquery/bootstrap-editable-1.5.1/CHANGELOG.txt new file mode 100755 index 0000000..4bbc916 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/CHANGELOG.txt @@ -0,0 +1,237 @@ +X-editable changelog +============================= + + +Version 1.5.1 Nov 4, 2013 +---------------------------- +[enh #371] submit single field (vitalets) +[bug] select2: placeholder not shown if value initially empty (vitalets) +[enh #400] allow `validate` to change submitted value, also fix #354 (vitalets) +[enh #396] bs3 popover: placement `auto` (vitalets) +[bug #357] select2: tags mode with space separator (vitalets) +[bug #374] dateui: clear button does not submit (vitalets) + + +Version 1.5.0 Oct 1, 2013 +---------------------------- +[enh #362] add twitter typeahead.js (vitalets) +[enh] select: add `sourceOptions` to modify source request method and params (vitalets) +[enh #377] add bool option `escape` to allow html as content (vitalets) +[bug #344] fix determing empty for html content (vitalets) +[enh] update select2 to 3.4.3 (vitalets) +[enh #343] Bootstrap 3 support (vitalets) + + +Version 1.4.6 Aug 8, 2013 +---------------------------- +[bug #312] can't apply selector more than once (vitalets) +[enh #48] textarea: use `white-space: pre-wrap` instead of nl2br conversion (vitalets) +[enh #286] added HTML5 time input (Doggie52) +[enh] add `defaultValue` option (vitalets) +[enh #313] add composer support (masim) +[enh #300] Fix 'bootstrap popover falls off page if editable is too close to window edge' (belerweb) +[enh #302] allow data-datepicker and data-datetimepicker (vitalets) +[enh #287] add option to disable item in select (vitalets) +[enh #281] add collision flag to adjust tooltip position (vitalets) +[bug #279] fix jQuery UI tooltip z-index to be less than select2 dropdown (vitalets) +[bug #276] support id() and text() functions of select2 (vitalets) + + +Version 1.4.5 Jun 23, 2013 +---------------------------- +[enh #245] highlight element after update (vitalets) +[enh] select2 now works with ajax source (vitalets) +[bug] fix datefield (datetimefield) to return null for incorrect dates (vitalets) +[bug #224] do not close popup when it is saving value (vitalets) +[enh] added `submitValue` to `save` event params (vitalets) +[enh #259] allow `getValue` method to return value itself, not object (vitalets) +[enh] add `destroy` method to inputs (vitalets) +[enh #164] allow emptytext to be html (vitalets) +[enh #78] allow html in editable content (vitalets) +[enh] update container position when datetimepicker viewMode changes (vitalets) +[enh #255] remove xxxView options from first level config of datetimepicker (vitalets) +[enh] if `display` defined as function call it on init (vitalets) +[enh #218] sourceCache now disables cache totally (vitalets) +[bug #156] solve conflict of bootstrap datepicker and jQuery UI datepicker (vitalets) +[enh] update bootstrap-datepicker to 1.1.2 (vitalets) +[enh] allow follow links in disabled state (vitalets) +[enh] update combodate to 1.0.4, fix #222 (vitalets) + + +Version 1.4.4 May 4, 2013 +---------------------------- +[enh #219] added `error` callback (joekaiser) +[enh #198] new value of showbuttons: 'bottom' (vitalets) +[enh #192] add class editable-popup to have diferent css for popup and inline (vitalets) +[enh] update to bootstrap-datepicker 1.0.2 (vitalets) +[enh] update to combodate 1.0.3 with yearDescending and roundTime options (vitalets) +[enh] add 'use strict' directive (vitalets) +[enh #202] allow pk=0 (mdeweerd) +[enh #183] move datepicker icon to center of button (vitalets) +[enh] upgrade to select2 3.3.2 (vitalets) +[enh #176] update to bootstrap 2.3.1 (vitalets) +[bug #171] clear in date & datetime when showbuttons=false (vitalets) +[bug #166] clear button for input type=number (vitalets) +[bug #65] checklist don't show checked for single value (vitalets) +[enh #188] added bootstrap datetime (adeg, vitalets) +[bug] editable-poshytip on inline mode tries to write in $.Poshytip (vitalets) + + +Version 1.4.3 Mar 8, 2013 +---------------------------- +[bug #32] hotfix for jQuery UI 1.9+ (vitalets) + + +Version 1.4.2 Mar 7, 2013 +---------------------------- +[enh #132] combodate options can be defined via data-combodate json string (vitalets) +[enh] source defined as function now has scope of element and can return string used as url (vitalets) +[bug #99] select2 with Hierarchical Data (kev360) +[bug #81] wysihtml5: fix inserting image (vitalets) +[bug] remove $.browser from wysihtml5 input to support jQuery 1.9 (vitalets) +[bug #142] editable poshytip jquery 1.9+ compatibility (spiderpug) +[enh #126] Update bootstrap datepicker library and add minViewMode to options (kev360) +[enh #150] select2 with showbuttons = false (vitalets) +[bug #149] datepicker not shown when showbuttons = false (vitalets) +[bug #133] clear button incorect position due to parent line-height property (vitalets) +[bug #141] data-value ignored for empty elements (vitalets) +[bug #137] fix empty class for delegated element (vitalets) +[enh #121] add support of momentjs 2.0.0 in combodate (vitalets) + + +Version 1.4.1 Jan 18, 2013 +---------------------------- +[enh #62] new option `selector` to work with delegated targets (vitalets) +[enh] new option `unsavedclass` to set css class when value was not sent to server (vitalets) +[enh] new option `emptyclass` to set css class when element is empty (vitalets) +[enh #59] select2 input (vitalets) +[enh #17] typeahead input (vitalets) +[enh] select: support of OPTGROUP via `children` key in source (vitalets) +[enh] checklist: set checked via prop instead of attr (vitalets) + + +Version 1.4.0 Jan 11, 2013 +---------------------------- +[enh] added new input type: combodate (vitalets) +[bug #68] allow arrays for data attributes (adimitrov) +[enh] setValue method updates input if form is open (vitalets) +[enh] select: change source via option method, see #61 (vitalets) +[bug] select: source loaded twice if sourceCache = false (vitalets) +[enh] added `destroy` method, see #61 (vitalets) +[enh] textarea: added `rows` property (vitalets) +[enh #60] added wysihtml5 input (vitalets) +[enh] added IOS-style clear button for text inputs (vitalets) +[enh] date inputs changed in inline mode (vitalets) +[enh #51] popup/inline modes can be toggled via `mode` config option. No more *-inline.js versions of files (vitalets) +[enh] update bootstrap-datepicker to upstream (vitalets) +[enh] 'display' method: added param 'response' allowing to show text directly from server (vitalets) +[enh] new util method `$.fn.editableutils.itemsByValue` to easily get selected items for sourced-inputs (vitalets) +[enh] convert newlines to <br> in error message for more pretty display (vitalets) +[enh #57] remove css height for textarea (vitalets) +[enh] if new value for select is 'null' source should not load (vitalets) +[enh #53] 'name' no more appended to source defined as url (vitalets) +[enh #46] move 'img' dir outside 'css' (vitalets) +[enh #48] fix handling of newlines in textarea input (jmfontaine) +[enh #47] set select source to function (brianchance) +[bug] fix inline container move on next line in IE7 (vitalets) + + +Version 1.3.0 Dec 10, 2012 +---------------------------- +[enh] added html5 inputs support: password, email, url, tel, number, range (vitalets) +[bug #43] fix for bootstrap 2.2.2 (vitalets) +[enh #41] 'abstract' class renamed to 'abstractinput' as abstract is reserved word (vitalets) +[enh #40] 'params' option defined as function overwrites original ajax data instead of appending (vitalets) +[bug] datepicker: error when click on arrows after clear date (vitalets) +[enh] 'hidden' event: added possible value of reason param - 'nochange'. Occurs when form is submitted but value was not changed (vitalets) +[enh] 'submit' method changed: error-callback's parameter simplified (vitalets) +[enh] 'submit' method changed: now when response 200 OK it does not set pk automatically (vitalets) +[enh] 'submit' method changed: removed dataType='json'. Use 'ajaxOptions' to specify dataType if needed (vitalets) +[enh] removed default ajax dataType='json'. Use 'ajaxOptions' to specify dataType if needed (vitalets) +[enh] select: do not show 'sourceError' in element during autotext execution (vitalets) + + +Version 1.2.0 Dec 6, 2012 +---------------------------- +[enh #36] 'submit' method: added 'ajaxOptions' property to modify ajax request (vitalets) +[enh] inputs now internally use 'value2submit' method instead of previous 'value2str' (vitalets) +[enh] editableContainer removed from docs (vitalets) +[enh] editableContainer: removed 'autohide' option and 'cancel' event. Use 'hidden' event instead (vitalets) +[enh] 'hidden' event: added param 'reason' that points to reason caused hiding (vitalets) +[enh] 'select' submit by enter (vitalets) +[bug #37] fix incorrectly shown datepicker in jquery 1.7.1 + webkit (vitalets) +[enh] added url param 'jquery' to run tests in different versions of jquery, e.g. '&jquery=1.7.2' (vitalets) +[enh] 'enablefocus' option removed. More efficient to use 'save/hide' events to set focus to any element (vitalets) +[enh] 'init' event was added due to removal of render event (vitalets) +[enh] 'render' event was removed, use 'display' callback instead (vitalets) +[enh] 'checklist' submit value as array, not comma separated string (vitalets) +[enh] 'checklist' was refactored: options 'viewseparator', 'limit', 'limitText' are supressed by 'display' callback (vitalets) +[enh] new option: 'display' callback. Makes far more flexible rendering value into element's text. (vitalets) +[bug] fix typos (atrophic) +[enh] all callbacks scope changed to element (vitalets) +[enh] new option: 'savenochange' to save or cancel value when it was not changed in form (vitalets) +[enh] composite pk can be defined as JSON in data-pk attribute (vitalets) +[enh #30] new option 'sourceCache' true|false to disable cache for select (vitalets) +[bug #34] inputclass span* broken with fluid bootstrap layout. Classes changed to 'input-*'. (vitalets) +[enh] utils now added to $.fn.editableutils instead of $.fn.editableform.utils (vitalets) +[enh] input types now added to $.fn.editabletypes instead of $.fn.editableform.types (vitalets) +[enh] playground and tests now use requirejs (vitalets) +[bug #27] 'today' button toggle bug in bootstrap-datepicker (vitalets) + + +Version 1.1.1 Nov 30, 2012 +---------------------------- +[enh] 'showbuttons' option to hide buttons in form (vitalets) +[enh] object can be passed in 'option' method to set several options at once (vitalets) +[enh #20] toggle editable by 'dblclick' and 'mouseenter' (vitalets) +[enh] added 'inputs-ext' directory with sample input 'address'. They will not be concatenated to main files (vitalets) +[enh #13] 'onblur' option: to cancel, submit or ignore when user clicks outside the form (vitalets) +[enh] 'ajaxOptions' parameter for advanced ajax configuration (vitalets) +[enh] 'success' callback can return object to overwrite submitted value (vitalets) + + +Version 1.1.0 Nov 27, 2012 +---------------------------- +[enh #11] icon cancel changed to 'cross' (tarciozemel) +[enh] added support for IE7+ (vitalets) +[enh #9] 'name' or 'id' is not required anymore (vitalets) +[enh] 'clear' button added in date and dateui (vitalets) +[enh] form template changed: added DIV.editable-input, DIV.editable.buttons and $.fn.editableform.buttons (vitalets) +[enh] new input type: checklist (vitalets) +[enh] updated docs: inputs dropdown menu, global templates section (vitalets) + + +Version 1.0.1 Nov 22, 2012 +---------------------------- +[enh] contribution guide in README.md (vitalets) +[enh #7] 'shown', 'hidden' events added (vitalets) +[enh #1] params can be a function to calculate it dynamically (vitalets) +[enh #6] do not preventDefault() in click when toggle='manual'. This allows to have clickable links (vitalets) +[bug #3] should not mark element with unsave css if url is user's function (vitalets) + + +Version 1.0.0 Nov 19, 2012 +---------------------------- +Initial release. This library is new life of bootstrap-editable (1.1.4) that was strongly refactored and improved. +Main features: +- support not only bootstrap but any core library: bootstrap, jquery-ui or pure jquery +- different container classes to show form: popover, tooltip, poshytip, etc +- inline and popup versions +- new directory structure and logic in separate js files allowing easy contribution + +It is not fully compatible with bootstrap-editable but has mainly the same interface and api. +Here list of differences to help you to upgrade your application: + +[change] 'toggle' option value can be only click|manual (not toggling element id). In case of 'manual' you should write handler calling 'show' method. +[change] 'validate' option cannot be defined as object anymore. +[change] events 'init', 'update', 'shown', 'hidden' removed. Events 'save', 'cancel' added. Event 'render' remains. +[change] input's option 'template' renamed to 'tpl' (to exclude conflict with container's template). +[change] value can be stored internally as object (previously was always string). Useful for date input. +[change] 'error' callback option is removed. 'success' callback remained. +[enh] 'source' option in select can be array of structure [{value: 1, text: 'abc'}, {...}]. This allows to keep ordering of items in dropdown list. Previous format is supported for compatibility. +[enh] api method 'setValue' to set manually value of editable. +[change] locales directory is excluded from bootstrap-datepicker input. If you need localization you should jus download corresponding file from github. +[change] date and dateui specific options can be set only via 'datepicker' option in first level of config (previously it was possible to set some options directly in config, e.g. weekStart). +[change] if 'url' option defined as function - it is used as submit method instead of ajax (previously it was dynamically return url string and ajax occurred anyway) + +Also all known bugs of bootstrap-editable were closed. diff --git a/src/static/jquery/bootstrap-editable-1.5.1/LICENSE-MIT b/src/static/jquery/bootstrap-editable-1.5.1/LICENSE-MIT new file mode 100755 index 0000000..bc67d5b --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/LICENSE-MIT @@ -0,0 +1,22 @@ +Copyright (c) 2012 Vitaliy Potapov + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/static/jquery/bootstrap-editable-1.5.1/README.md b/src/static/jquery/bootstrap-editable-1.5.1/README.md new file mode 100755 index 0000000..46d8bfb --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/README.md @@ -0,0 +1,124 @@ +# X-editable + +In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery. + +## Live demo +**http://vitalets.github.io/x-editable/demo.html** + +## Documentation +**http://vitalets.github.io/x-editable** + +## How to get it + +### Manual download +Use **http://vitalets.github.io/x-editable** main page. + +### Bower +```` +bower install x-editable +```` + +### CDN +Bootstrap 3 build: +````js +<link href="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/bootstrap3-editable/css/bootstrap-editable.css" rel="stylesheet"/> +<script src="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/bootstrap3-editable/js/bootstrap-editable.min.js"></script> +```` + +Bootstrap 2 build: +````js +<link href="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/bootstrap-editable/css/bootstrap-editable.css" rel="stylesheet"/> +<script src="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/bootstrap-editable/js/bootstrap-editable.min.js"></script> +```` + +jQuery UI build: +````js +<link href="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/jqueryui-editable/css/jqueryui-editable.css" rel="stylesheet"/> +<script src="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/jqueryui-editable/js/jqueryui-editable.min.js"></script> +```` + +jQuery only build: +````js +<link href="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/jquery-editable/css/jquery-editable.css" rel="stylesheet"/> +<script src="//cdnjs.cloudflare.com/ajax/libs/x-editable/1.5.0/jquery-editable/js/jquery-editable-poshytip.min.js"></script> +```` + + +## Reporting issues +Please **provide jsFiddle** when creating issues! +It's really saves much time. Use these as template: +1. [jsFiddle Bootstrap 3](http://jsfiddle.net/xBB5x/2265/) +2. [jsFiddle Bootstrap 2](http://jsfiddle.net/xBB5x/1817/) +3. [jsFiddle jQuery-ui](http://jsfiddle.net/xBB5x/2511/) +4. [jsFiddle jQuery](http://jsfiddle.net/xBB5x/197) +Your feedback is very appreciated! + +## Contribution +A few steps how to start contributing. +Assuming you have [Node.js](http://nodejs.org/) already installed. + +1.Fork *X-editable* on github and clone it to your local mashine: +```` +git clone https://github.com/<your-github-name>/x-editable.git -b dev +```` +2.Install *grunt-cli* globally (if not yet): +```` +npm i -g grunt-cli +```` +3.Install dependencies: +```` +cd x-editable +npm i +```` +4.Make your changes: +```` +vim editable-form.js +```` +5.Write some tests for your changes: +```` +vim /test/unit/*.js +```` +6.Run tests in cli: +```` +grunt test +```` +or directly in browser: +```` +grunt server +```` +and open http://127.0.0.1:8000/test +By default test run on bootstrap 3 popup version, but you can test any other build: + +* bootstrap 3 + * popup: http://127.0.0.1:8000/test/?f=bootstrap3&c=popup + * inline: http://127.0.0.1:8000/test/?f=bootstrap3&c=inline +* bootstrap 2 + * popup: http://127.0.0.1:8000/test/?f=bootstrap2&c=popup + * inline: http://127.0.0.1:8000/test/?f=bootstrap2&c=inline +* jquery-ui + * popup: http://127.0.0.1:8000/test/?f=jqueryui&c=popup + * inline: http://127.0.0.1:8000/test/?f=jqueryui&c=inline +* jquery + poshytip + * popup: http://127.0.0.1:8000/test/?f=plain&c=popup + * inline: http://127.0.0.1:8000/test/?f=plain&c=inline + +7.Commit and push back on github: +```` +git add . +git commit -m'refactor editable form, fix #123' +git push origin +```` +8.Make pull request on github (to `dev` branch). + +Thanks for your support! + +### Local build +To build x-editable locally please run: +```` +grunt build +```` +Result will appear in `dist` directory. + +## License +Copyright (c) 2012 Vitaliy Potapov +Licensed under the MIT license. \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/css/bootstrap-editable.css b/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/css/bootstrap-editable.css new file mode 100755 index 0000000..eaef0de --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/css/bootstrap-editable.css @@ -0,0 +1,663 @@ +/*! X-editable - v1.5.1 +* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery +* http://github.com/vitalets/x-editable +* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */ +.editableform { + margin-bottom: 0; /* overwrites bootstrap margin */ +} + +.editableform .control-group { + margin-bottom: 0; /* overwrites bootstrap margin */ + white-space: nowrap; /* prevent wrapping buttons on new line */ + line-height: 20px; /* overwriting bootstrap line-height. See #133 */ +} + +/* + BS3 width:1005 for inputs breaks editable form in popup + See: https://github.com/vitalets/x-editable/issues/393 +*/ +.editableform .form-control { + width: auto; +} + +.editable-buttons { + display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ + vertical-align: top; + margin-left: 7px; + /* inline-block emulation for IE7*/ + zoom: 1; + *display: inline; +} + +.editable-buttons.editable-buttons-bottom { + display: block; + margin-top: 7px; + margin-left: 0; +} + +.editable-input { + vertical-align: top; + display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */ + width: auto; /* bootstrap-responsive has width: 100% that breakes layout */ + white-space: normal; /* reset white-space decalred in parent*/ + /* display-inline emulation for IE7*/ + zoom: 1; + *display: inline; +} + +.editable-buttons .editable-cancel { + margin-left: 7px; +} + +/*for jquery-ui buttons need set height to look more pretty*/ +.editable-buttons button.ui-button-icon-only { + height: 24px; + width: 30px; +} + +.editableform-loading { + background: url('../img/loading.gif') center center no-repeat; + height: 25px; + width: auto; + min-width: 25px; +} + +.editable-inline .editableform-loading { + background-position: left 5px; +} + + .editable-error-block { + max-width: 300px; + margin: 5px 0 0 0; + width: auto; + white-space: normal; +} + +/*add padding for jquery ui*/ +.editable-error-block.ui-state-error { + padding: 3px; +} + +.editable-error { + color: red; +} + +/* ---- For specific types ---- */ + +.editableform .editable-date { + padding: 0; + margin: 0; + float: left; +} + +/* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */ +.editable-inline .add-on .icon-th { + margin-top: 3px; + margin-left: 1px; +} + + +/* checklist vertical alignment */ +.editable-checklist label input[type="checkbox"], +.editable-checklist label span { + vertical-align: middle; + margin: 0; +} + +.editable-checklist label { + white-space: nowrap; +} + +/* set exact width of textarea to fit buttons toolbar */ +.editable-wysihtml5 { + width: 566px; + height: 250px; +} + +/* clear button shown as link in date inputs */ +.editable-clear { + clear: both; + font-size: 0.9em; + text-decoration: none; + text-align: right; +} + +/* IOS-style clear button for text inputs */ +.editable-clear-x { + background: url('../img/clear.png') center center no-repeat; + display: block; + width: 13px; + height: 13px; + position: absolute; + opacity: 0.6; + z-index: 100; + + top: 50%; + right: 6px; + margin-top: -6px; + +} + +.editable-clear-x:hover { + opacity: 1; +} + +.editable-pre-wrapped { + white-space: pre-wrap; +} +.editable-container.editable-popup { + max-width: none !important; /* without this rule poshytip/tooltip does not stretch */ +} + +.editable-container.popover { + width: auto; /* without this rule popover does not stretch */ +} + +.editable-container.editable-inline { + display: inline-block; + vertical-align: middle; + width: auto; + /* inline-block emulation for IE7*/ + zoom: 1; + *display: inline; +} + +.editable-container.ui-widget { + font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */ + z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */ +} +.editable-click, +a.editable-click, +a.editable-click:hover { + text-decoration: none; + border-bottom: dashed 1px #0088cc; +} + +.editable-click.editable-disabled, +a.editable-click.editable-disabled, +a.editable-click.editable-disabled:hover { + color: #585858; + cursor: default; + border-bottom: none; +} + +.editable-empty, .editable-empty:hover, .editable-empty:focus{ + font-style: italic; + color: #DD1144; + /* border-bottom: none; */ + text-decoration: none; +} + +.editable-unsaved { + font-weight: bold; +} + +.editable-unsaved:after { +/* content: '*'*/ +} + +.editable-bg-transition { + -webkit-transition: background-color 1400ms ease-out; + -moz-transition: background-color 1400ms ease-out; + -o-transition: background-color 1400ms ease-out; + -ms-transition: background-color 1400ms ease-out; + transition: background-color 1400ms ease-out; +} + +/*see https://github.com/vitalets/x-editable/issues/139 */ +.form-horizontal .editable +{ + padding-top: 5px; + display:inline-block; +} + + +/*! + * Datepicker for Bootstrap + * + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + */ +.datepicker { + padding: 4px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + direction: ltr; + /*.dow { + border-top: 1px solid #ddd !important; + }*/ + +} +.datepicker-inline { + width: 220px; +} +.datepicker.datepicker-rtl { + direction: rtl; +} +.datepicker.datepicker-rtl table tr td span { + float: right; +} +.datepicker-dropdown { + top: 0; + left: 0; +} +.datepicker-dropdown:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; + top: -7px; + left: 6px; +} +.datepicker-dropdown:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #ffffff; + position: absolute; + top: -6px; + left: 7px; +} +.datepicker > div { + display: none; +} +.datepicker.days div.datepicker-days { + display: block; +} +.datepicker.months div.datepicker-months { + display: block; +} +.datepicker.years div.datepicker-years { + display: block; +} +.datepicker table { + margin: 0; +} +.datepicker td, +.datepicker th { + text-align: center; + width: 20px; + height: 20px; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + border: none; +} +.table-striped .datepicker table tr td, +.table-striped .datepicker table tr th { + background-color: transparent; +} +.datepicker table tr td.day:hover { + background: #eeeeee; + cursor: pointer; +} +.datepicker table tr td.old, +.datepicker table tr td.new { + color: #999999; +} +.datepicker table tr td.disabled, +.datepicker table tr td.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datepicker table tr td.today, +.datepicker table tr td.today:hover, +.datepicker table tr td.today.disabled, +.datepicker table tr td.today.disabled:hover { + background-color: #fde19a; + background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a)); + background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a); + background-image: -o-linear-gradient(top, #fdd49a, #fdf59a); + background-image: linear-gradient(top, #fdd49a, #fdf59a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0); + border-color: #fdf59a #fdf59a #fbed50; + 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(enabled=false); + color: #000; +} +.datepicker table tr td.today:hover, +.datepicker table tr td.today:hover:hover, +.datepicker table tr td.today.disabled:hover, +.datepicker table tr td.today.disabled:hover:hover, +.datepicker table tr td.today:active, +.datepicker table tr td.today:hover:active, +.datepicker table tr td.today.disabled:active, +.datepicker table tr td.today.disabled:hover:active, +.datepicker table tr td.today.active, +.datepicker table tr td.today:hover.active, +.datepicker table tr td.today.disabled.active, +.datepicker table tr td.today.disabled:hover.active, +.datepicker table tr td.today.disabled, +.datepicker table tr td.today:hover.disabled, +.datepicker table tr td.today.disabled.disabled, +.datepicker table tr td.today.disabled:hover.disabled, +.datepicker table tr td.today[disabled], +.datepicker table tr td.today:hover[disabled], +.datepicker table tr td.today.disabled[disabled], +.datepicker table tr td.today.disabled:hover[disabled] { + background-color: #fdf59a; +} +.datepicker table tr td.today:active, +.datepicker table tr td.today:hover:active, +.datepicker table tr td.today.disabled:active, +.datepicker table tr td.today.disabled:hover:active, +.datepicker table tr td.today.active, +.datepicker table tr td.today:hover.active, +.datepicker table tr td.today.disabled.active, +.datepicker table tr td.today.disabled:hover.active { + background-color: #fbf069 \9; +} +.datepicker table tr td.today:hover:hover { + color: #000; +} +.datepicker table tr td.today.active:hover { + color: #fff; +} +.datepicker table tr td.range, +.datepicker table tr td.range:hover, +.datepicker table tr td.range.disabled, +.datepicker table tr td.range.disabled:hover { + background: #eeeeee; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.datepicker table tr td.range.today, +.datepicker table tr td.range.today:hover, +.datepicker table tr td.range.today.disabled, +.datepicker table tr td.range.today.disabled:hover { + background-color: #f3d17a; + background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a); + background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a)); + background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a); + background-image: -o-linear-gradient(top, #f3c17a, #f3e97a); + background-image: linear-gradient(top, #f3c17a, #f3e97a); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0); + border-color: #f3e97a #f3e97a #edde34; + 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(enabled=false); + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} +.datepicker table tr td.range.today:hover, +.datepicker table tr td.range.today:hover:hover, +.datepicker table tr td.range.today.disabled:hover, +.datepicker table tr td.range.today.disabled:hover:hover, +.datepicker table tr td.range.today:active, +.datepicker table tr td.range.today:hover:active, +.datepicker table tr td.range.today.disabled:active, +.datepicker table tr td.range.today.disabled:hover:active, +.datepicker table tr td.range.today.active, +.datepicker table tr td.range.today:hover.active, +.datepicker table tr td.range.today.disabled.active, +.datepicker table tr td.range.today.disabled:hover.active, +.datepicker table tr td.range.today.disabled, +.datepicker table tr td.range.today:hover.disabled, +.datepicker table tr td.range.today.disabled.disabled, +.datepicker table tr td.range.today.disabled:hover.disabled, +.datepicker table tr td.range.today[disabled], +.datepicker table tr td.range.today:hover[disabled], +.datepicker table tr td.range.today.disabled[disabled], +.datepicker table tr td.range.today.disabled:hover[disabled] { + background-color: #f3e97a; +} +.datepicker table tr td.range.today:active, +.datepicker table tr td.range.today:hover:active, +.datepicker table tr td.range.today.disabled:active, +.datepicker table tr td.range.today.disabled:hover:active, +.datepicker table tr td.range.today.active, +.datepicker table tr td.range.today:hover.active, +.datepicker table tr td.range.today.disabled.active, +.datepicker table tr td.range.today.disabled:hover.active { + background-color: #efe24b \9; +} +.datepicker table tr td.selected, +.datepicker table tr td.selected:hover, +.datepicker table tr td.selected.disabled, +.datepicker table tr td.selected.disabled:hover { + background-color: #9e9e9e; + background-image: -moz-linear-gradient(top, #b3b3b3, #808080); + background-image: -ms-linear-gradient(top, #b3b3b3, #808080); + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080)); + background-image: -webkit-linear-gradient(top, #b3b3b3, #808080); + background-image: -o-linear-gradient(top, #b3b3b3, #808080); + background-image: linear-gradient(top, #b3b3b3, #808080); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0); + border-color: #808080 #808080 #595959; + 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(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datepicker table tr td.selected:hover, +.datepicker table tr td.selected:hover:hover, +.datepicker table tr td.selected.disabled:hover, +.datepicker table tr td.selected.disabled:hover:hover, +.datepicker table tr td.selected:active, +.datepicker table tr td.selected:hover:active, +.datepicker table tr td.selected.disabled:active, +.datepicker table tr td.selected.disabled:hover:active, +.datepicker table tr td.selected.active, +.datepicker table tr td.selected:hover.active, +.datepicker table tr td.selected.disabled.active, +.datepicker table tr td.selected.disabled:hover.active, +.datepicker table tr td.selected.disabled, +.datepicker table tr td.selected:hover.disabled, +.datepicker table tr td.selected.disabled.disabled, +.datepicker table tr td.selected.disabled:hover.disabled, +.datepicker table tr td.selected[disabled], +.datepicker table tr td.selected:hover[disabled], +.datepicker table tr td.selected.disabled[disabled], +.datepicker table tr td.selected.disabled:hover[disabled] { + background-color: #808080; +} +.datepicker table tr td.selected:active, +.datepicker table tr td.selected:hover:active, +.datepicker table tr td.selected.disabled:active, +.datepicker table tr td.selected.disabled:hover:active, +.datepicker table tr td.selected.active, +.datepicker table tr td.selected:hover.active, +.datepicker table tr td.selected.disabled.active, +.datepicker table tr td.selected.disabled:hover.active { + background-color: #666666 \9; +} +.datepicker table tr td.active, +.datepicker table tr td.active:hover, +.datepicker table tr td.active.disabled, +.datepicker table tr td.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-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(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + 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(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datepicker table tr td.active:hover, +.datepicker table tr td.active:hover:hover, +.datepicker table tr td.active.disabled:hover, +.datepicker table tr td.active.disabled:hover:hover, +.datepicker table tr td.active:active, +.datepicker table tr td.active:hover:active, +.datepicker table tr td.active.disabled:active, +.datepicker table tr td.active.disabled:hover:active, +.datepicker table tr td.active.active, +.datepicker table tr td.active:hover.active, +.datepicker table tr td.active.disabled.active, +.datepicker table tr td.active.disabled:hover.active, +.datepicker table tr td.active.disabled, +.datepicker table tr td.active:hover.disabled, +.datepicker table tr td.active.disabled.disabled, +.datepicker table tr td.active.disabled:hover.disabled, +.datepicker table tr td.active[disabled], +.datepicker table tr td.active:hover[disabled], +.datepicker table tr td.active.disabled[disabled], +.datepicker table tr td.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datepicker table tr td.active:active, +.datepicker table tr td.active:hover:active, +.datepicker table tr td.active.disabled:active, +.datepicker table tr td.active.disabled:hover:active, +.datepicker table tr td.active.active, +.datepicker table tr td.active:hover.active, +.datepicker table tr td.active.disabled.active, +.datepicker table tr td.active.disabled:hover.active { + background-color: #003399 \9; +} +.datepicker table tr td span { + display: block; + width: 23%; + height: 54px; + line-height: 54px; + float: left; + margin: 1%; + cursor: pointer; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.datepicker table tr td span:hover { + background: #eeeeee; +} +.datepicker table tr td span.disabled, +.datepicker table tr td span.disabled:hover { + background: none; + color: #999999; + cursor: default; +} +.datepicker table tr td span.active, +.datepicker table tr td span.active:hover, +.datepicker table tr td span.active.disabled, +.datepicker table tr td span.active.disabled:hover { + background-color: #006dcc; + background-image: -moz-linear-gradient(top, #0088cc, #0044cc); + background-image: -ms-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(top, #0088cc, #0044cc); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0); + 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(enabled=false); + color: #fff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} +.datepicker table tr td span.active:hover, +.datepicker table tr td span.active:hover:hover, +.datepicker table tr td span.active.disabled:hover, +.datepicker table tr td span.active.disabled:hover:hover, +.datepicker table tr td span.active:active, +.datepicker table tr td span.active:hover:active, +.datepicker table tr td span.active.disabled:active, +.datepicker table tr td span.active.disabled:hover:active, +.datepicker table tr td span.active.active, +.datepicker table tr td span.active:hover.active, +.datepicker table tr td span.active.disabled.active, +.datepicker table tr td span.active.disabled:hover.active, +.datepicker table tr td span.active.disabled, +.datepicker table tr td span.active:hover.disabled, +.datepicker table tr td span.active.disabled.disabled, +.datepicker table tr td span.active.disabled:hover.disabled, +.datepicker table tr td span.active[disabled], +.datepicker table tr td span.active:hover[disabled], +.datepicker table tr td span.active.disabled[disabled], +.datepicker table tr td span.active.disabled:hover[disabled] { + background-color: #0044cc; +} +.datepicker table tr td span.active:active, +.datepicker table tr td span.active:hover:active, +.datepicker table tr td span.active.disabled:active, +.datepicker table tr td span.active.disabled:hover:active, +.datepicker table tr td span.active.active, +.datepicker table tr td span.active:hover.active, +.datepicker table tr td span.active.disabled.active, +.datepicker table tr td span.active.disabled:hover.active { + background-color: #003399 \9; +} +.datepicker table tr td span.old, +.datepicker table tr td span.new { + color: #999999; +} +.datepicker th.datepicker-switch { + width: 145px; +} +.datepicker thead tr:first-child th, +.datepicker tfoot tr th { + cursor: pointer; +} +.datepicker thead tr:first-child th:hover, +.datepicker tfoot tr th:hover { + background: #eeeeee; +} +.datepicker .cw { + font-size: 10px; + width: 12px; + padding: 0 2px 0 5px; + vertical-align: middle; +} +.datepicker thead tr:first-child th.cw { + cursor: default; + background-color: transparent; +} +.input-append.date .add-on i, +.input-prepend.date .add-on i { + display: block; + cursor: pointer; + width: 16px; + height: 16px; +} +.input-daterange input { + text-align: center; +} +.input-daterange input:first-child { + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; +} +.input-daterange input:last-child { + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; +} +.input-daterange .add-on { + display: inline-block; + width: auto; + min-width: 16px; + height: 18px; + padding: 4px 5px; + font-weight: normal; + line-height: 18px; + text-align: center; + text-shadow: 0 1px 0 #ffffff; + vertical-align: middle; + background-color: #eeeeee; + border: 1px solid #ccc; + margin-left: -5px; + margin-right: -5px; +} diff --git a/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/img/clear.png b/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/img/clear.png new file mode 100755 index 0000000000000000000000000000000000000000..580b52a5be8a644f826def0c7ed6a13f90c0915c GIT binary patch literal 509 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4u6ByT*@`3|I*lDyqr82-2SpV<%OaTa()76WMy zFm^kcZ3hx8D{xE)(qO#|GLJ6IVqjoo^>lFzk+^JnVSiR|B17B9``_m-NuMxfR?C!* zh07MrSo)3sr09zP_wDzlhX=fPF>UDu=?vANf(w(JrZ%)>D41|8J9+Zugm01epVrPx zINBDzitE|2b$6T`9`!DJFmdU=eKrTz=_*cb3=s<v?Oo)1-g4a^y9}17lPf-FGW$Nw z=nnevV^_@nJN4l<`RlLu#Vz}wWD&ApYRyZVl@VQ&ANu7_cw8US@cw4t`Jfm*yBNNr z4Pv?rrp|fOeZ=W|Zt~Z!dQ!n$&))`>8r9VQ%8yxBf7d%v=5Nxh^7ZP6=ia-yr`GWA z@1JRG_RM@X%BIyHqImbIN_g6wl?zIFvhME$`)4a}gbAnqdolZft=%U7g<U~$mw=(8 zTH+c}l9E`GYL#4+3Zxi}3=9o*4UBXRO+pL}tqhH<3{ABSjI0a{esgEFp=ij>PsvQH z#I2z#?2;8wgCxj?;QX|b^2DN42FH~Aq*MjZ+{E<Mpwz^a%EFVWHb6xTp00i_>zopr E0Crl)MgRZ+ literal 0 HcmV?d00001 diff --git a/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/img/loading.gif b/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/img/loading.gif new file mode 100755 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 GIT binary patch literal 1849 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 EAHN$8j{pDw literal 0 HcmV?d00001 diff --git a/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/js/bootstrap-editable.js b/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/js/bootstrap-editable.js new file mode 100755 index 0000000..44ee03d --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/js/bootstrap-editable.js @@ -0,0 +1,7007 @@ +/*! X-editable - v1.5.1 +* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery +* http://github.com/vitalets/x-editable +* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */ +/** +Form with single input element, two buttons and two states: normal/loading. +Applied as jQuery method to DIV tag (not to form tag!). This is because form can be in loading state when spinner shown. +Editableform is linked with one of input types, e.g. 'text', 'select' etc. + +@class editableform +@uses text +@uses textarea +**/ +(function ($) { + "use strict"; + + var EditableForm = function (div, options) { + this.options = $.extend({}, $.fn.editableform.defaults, options); + this.$div = $(div); //div, containing form. Not form tag. Not editable-element. + if(!this.options.scope) { + this.options.scope = this; + } + //nothing shown after init + }; + + EditableForm.prototype = { + constructor: EditableForm, + initInput: function() { //called once + //take input from options (as it is created in editable-element) + this.input = this.options.input; + + //set initial value + //todo: may be add check: typeof str === 'string' ? + this.value = this.input.str2value(this.options.value); + + //prerender: get input.$input + this.input.prerender(); + }, + initTemplate: function() { + this.$form = $($.fn.editableform.template); + }, + initButtons: function() { + var $btn = this.$form.find('.editable-buttons'); + $btn.append($.fn.editableform.buttons); + if(this.options.showbuttons === 'bottom') { + $btn.addClass('editable-buttons-bottom'); + } + }, + /** + Renders editableform + + @method render + **/ + render: function() { + //init loader + this.$loading = $($.fn.editableform.loading); + this.$div.empty().append(this.$loading); + + //init form template and buttons + this.initTemplate(); + if(this.options.showbuttons) { + this.initButtons(); + } else { + this.$form.find('.editable-buttons').remove(); + } + + //show loading state + this.showLoading(); + + //flag showing is form now saving value to server. + //It is needed to wait when closing form. + this.isSaving = false; + + /** + Fired when rendering starts + @event rendering + @param {Object} event event object + **/ + this.$div.triggerHandler('rendering'); + + //init input + this.initInput(); + + //append input to form + this.$form.find('div.editable-input').append(this.input.$tpl); + + //append form to container + this.$div.append(this.$form); + + //render input + $.when(this.input.render()) + .then($.proxy(function () { + //setup input to submit automatically when no buttons shown + if(!this.options.showbuttons) { + this.input.autosubmit(); + } + + //attach 'cancel' handler + this.$form.find('.editable-cancel').click($.proxy(this.cancel, this)); + + if(this.input.error) { + this.error(this.input.error); + this.$form.find('.editable-submit').attr('disabled', true); + this.input.$input.attr('disabled', true); + //prevent form from submitting + this.$form.submit(function(e){ e.preventDefault(); }); + } else { + this.error(false); + this.input.$input.removeAttr('disabled'); + this.$form.find('.editable-submit').removeAttr('disabled'); + var value = (this.value === null || this.value === undefined || this.value === '') ? this.options.defaultValue : this.value; + this.input.value2input(value); + //attach submit handler + this.$form.submit($.proxy(this.submit, this)); + } + + /** + Fired when form is rendered + @event rendered + @param {Object} event event object + **/ + this.$div.triggerHandler('rendered'); + + this.showForm(); + + //call postrender method to perform actions required visibility of form + if(this.input.postrender) { + this.input.postrender(); + } + }, this)); + }, + cancel: function() { + /** + Fired when form was cancelled by user + @event cancel + @param {Object} event event object + **/ + this.$div.triggerHandler('cancel'); + }, + showLoading: function() { + var w, h; + if(this.$form) { + //set loading size equal to form + w = this.$form.outerWidth(); + h = this.$form.outerHeight(); + if(w) { + this.$loading.width(w); + } + if(h) { + this.$loading.height(h); + } + this.$form.hide(); + } else { + //stretch loading to fill container width + w = this.$loading.parent().width(); + if(w) { + this.$loading.width(w); + } + } + this.$loading.show(); + }, + + showForm: function(activate) { + this.$loading.hide(); + this.$form.show(); + if(activate !== false) { + this.input.activate(); + } + /** + Fired when form is shown + @event show + @param {Object} event event object + **/ + this.$div.triggerHandler('show'); + }, + + error: function(msg) { + var $group = this.$form.find('.control-group'), + $block = this.$form.find('.editable-error-block'), + lines; + + if(msg === false) { + $group.removeClass($.fn.editableform.errorGroupClass); + $block.removeClass($.fn.editableform.errorBlockClass).empty().hide(); + } else { + //convert newline to <br> for more pretty error display + if(msg) { + lines = (''+msg).split('\n'); + for (var i = 0; i < lines.length; i++) { + lines[i] = $('<div>').text(lines[i]).html(); + } + msg = lines.join('<br>'); + } + $group.addClass($.fn.editableform.errorGroupClass); + $block.addClass($.fn.editableform.errorBlockClass).html(msg).show(); + } + }, + + submit: function(e) { + e.stopPropagation(); + e.preventDefault(); + + //get new value from input + var newValue = this.input.input2value(); + + //validation: if validate returns string or truthy value - means error + //if returns object like {newValue: '...'} => submitted value is reassigned to it + var error = this.validate(newValue); + if ($.type(error) === 'object' && error.newValue !== undefined) { + newValue = error.newValue; + this.input.value2input(newValue); + if(typeof error.msg === 'string') { + this.error(error.msg); + this.showForm(); + return; + } + } else if (error) { + this.error(error); + this.showForm(); + return; + } + + //if value not changed --> trigger 'nochange' event and return + /*jslint eqeq: true*/ + if (!this.options.savenochange && this.input.value2str(newValue) == this.input.value2str(this.value)) { + /*jslint eqeq: false*/ + /** + Fired when value not changed but form is submitted. Requires savenochange = false. + @event nochange + @param {Object} event event object + **/ + this.$div.triggerHandler('nochange'); + return; + } + + //convert value for submitting to server + var submitValue = this.input.value2submit(newValue); + + this.isSaving = true; + + //sending data to server + $.when(this.save(submitValue)) + .done($.proxy(function(response) { + this.isSaving = false; + + //run success callback + var res = typeof this.options.success === 'function' ? this.options.success.call(this.options.scope, response, newValue) : null; + + //if success callback returns false --> keep form open and do not activate input + if(res === false) { + this.error(false); + this.showForm(false); + return; + } + + //if success callback returns string --> keep form open, show error and activate input + if(typeof res === 'string') { + this.error(res); + this.showForm(); + return; + } + + //if success callback returns object like {newValue: <something>} --> use that value instead of submitted + //it is usefull if you want to chnage value in url-function + if(res && typeof res === 'object' && res.hasOwnProperty('newValue')) { + newValue = res.newValue; + } + + //clear error message + this.error(false); + this.value = newValue; + /** + Fired when form is submitted + @event save + @param {Object} event event object + @param {Object} params additional params + @param {mixed} params.newValue raw new value + @param {mixed} params.submitValue submitted value as string + @param {Object} params.response ajax response + + @example + $('#form-div').on('save'), function(e, params){ + if(params.newValue === 'username') {...} + }); + **/ + this.$div.triggerHandler('save', {newValue: newValue, submitValue: submitValue, response: response}); + }, this)) + .fail($.proxy(function(xhr) { + this.isSaving = false; + + var msg; + if(typeof this.options.error === 'function') { + msg = this.options.error.call(this.options.scope, xhr, newValue); + } else { + msg = typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!'; + } + + this.error(msg); + this.showForm(); + }, this)); + }, + + save: function(submitValue) { + //try parse composite pk defined as json string in data-pk + this.options.pk = $.fn.editableutils.tryParseJson(this.options.pk, true); + + var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this.options.scope) : this.options.pk, + /* + send on server in following cases: + 1. url is function + 2. url is string AND (pk defined OR send option = always) + */ + send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk !== null && pk !== undefined)))), + params; + + if (send) { //send to server + this.showLoading(); + + //standard params + params = { + name: this.options.name || '', + value: submitValue, + pk: pk + }; + + //additional params + if(typeof this.options.params === 'function') { + params = this.options.params.call(this.options.scope, params); + } else { + //try parse json in single quotes (from data-params attribute) + this.options.params = $.fn.editableutils.tryParseJson(this.options.params, true); + $.extend(params, this.options.params); + } + + if(typeof this.options.url === 'function') { //user's function + return this.options.url.call(this.options.scope, params); + } else { + //send ajax to server and return deferred object + return $.ajax($.extend({ + url : this.options.url, + data : params, + type : 'POST' + }, this.options.ajaxOptions)); + } + } + }, + + validate: function (value) { + if (value === undefined) { + value = this.value; + } + if (typeof this.options.validate === 'function') { + return this.options.validate.call(this.options.scope, value); + } + }, + + option: function(key, value) { + if(key in this.options) { + this.options[key] = value; + } + + if(key === 'value') { + this.setValue(value); + } + + //do not pass option to input as it is passed in editable-element + }, + + setValue: function(value, convertStr) { + if(convertStr) { + this.value = this.input.str2value(value); + } else { + this.value = value; + } + + //if form is visible, update input + if(this.$form && this.$form.is(':visible')) { + this.input.value2input(this.value); + } + } + }; + + /* + Initialize editableform. Applied to jQuery object. + + @method $().editableform(options) + @params {Object} options + @example + var $form = $('&lt;div&gt;').editableform({ + type: 'text', + name: 'username', + url: '/post', + value: 'vitaliy' + }); + + //to display form you should call 'render' method + $form.editableform('render'); + */ + $.fn.editableform = function (option) { + var args = arguments; + return this.each(function () { + var $this = $(this), + data = $this.data('editableform'), + options = typeof option === 'object' && option; + if (!data) { + $this.data('editableform', (data = new EditableForm(this, options))); + } + + if (typeof option === 'string') { //call method + data[option].apply(data, Array.prototype.slice.call(args, 1)); + } + }); + }; + + //keep link to constructor to allow inheritance + $.fn.editableform.Constructor = EditableForm; + + //defaults + $.fn.editableform.defaults = { + /* see also defaults for input */ + + /** + Type of input. Can be <code>text|textarea|select|date|checklist</code> + + @property type + @type string + @default 'text' + **/ + type: 'text', + /** + Url for submit, e.g. <code>'/post'</code> + If function - it will be called instead of ajax. Function should return deferred object to run fail/done callbacks. + + @property url + @type string|function + @default null + @example + url: function(params) { + var d = new $.Deferred; + if(params.value === 'abc') { + return d.reject('error message'); //returning error via deferred object + } else { + //async saving data in js model + someModel.asyncSaveMethod({ + ..., + success: function(){ + d.resolve(); + } + }); + return d.promise(); + } + } + **/ + url:null, + /** + Additional params for submit. If defined as <code>object</code> - it is **appended** to original ajax data (pk, name and value). + If defined as <code>function</code> - returned object **overwrites** original ajax data. + @example + params: function(params) { + //originally params contain pk, name and value + params.a = 1; + return params; + } + + @property params + @type object|function + @default null + **/ + params:null, + /** + Name of field. Will be submitted on server. Can be taken from <code>id</code> attribute + + @property name + @type string + @default null + **/ + name: null, + /** + Primary key of editable object (e.g. record id in database). For composite keys use object, e.g. <code>{id: 1, lang: 'en'}</code>. + Can be calculated dynamically via function. + + @property pk + @type string|object|function + @default null + **/ + pk: null, + /** + Initial value. If not defined - will be taken from element's content. + For __select__ type should be defined (as it is ID of shown text). + + @property value + @type string|object + @default null + **/ + value: null, + /** + Value that will be displayed in input if original field value is empty (`null|undefined|''`). + + @property defaultValue + @type string|object + @default null + @since 1.4.6 + **/ + defaultValue: null, + /** + Strategy for sending data on server. Can be `auto|always|never`. + When 'auto' data will be sent on server **only if pk and url defined**, otherwise new value will be stored locally. + + @property send + @type string + @default 'auto' + **/ + send: 'auto', + /** + Function for client-side validation. If returns string - means validation not passed and string showed as error. + Since 1.5.1 you can modify submitted value by returning object from `validate`: + `{newValue: '...'}` or `{newValue: '...', msg: '...'}` + + @property validate + @type function + @default null + @example + validate: function(value) { + if($.trim(value) == '') { + return 'This field is required'; + } + } + **/ + validate: null, + /** + Success callback. Called when value successfully sent on server and **response status = 200**. + Usefull to work with json response. For example, if your backend response can be <code>{success: true}</code> + or <code>{success: false, msg: "server error"}</code> you can check it inside this callback. + If it returns **string** - means error occured and string is shown as error message. + If it returns **object like** <code>{newValue: &lt;something&gt;}</code> - it overwrites value, submitted by user. + Otherwise newValue simply rendered into element. + + @property success + @type function + @default null + @example + success: function(response, newValue) { + if(!response.success) return response.msg; + } + **/ + success: null, + /** + Error callback. Called when request failed (response status != 200). + Usefull when you want to parse error response and display a custom message. + Must return **string** - the message to be displayed in the error block. + + @property error + @type function + @default null + @since 1.4.4 + @example + error: function(response, newValue) { + if(response.status === 500) { + return 'Service unavailable. Please try later.'; + } else { + return response.responseText; + } + } + **/ + error: null, + /** + Additional options for submit ajax request. + List of values: http://api.jquery.com/jQuery.ajax + + @property ajaxOptions + @type object + @default null + @since 1.1.1 + @example + ajaxOptions: { + type: 'put', + dataType: 'json' + } + **/ + ajaxOptions: null, + /** + Where to show buttons: left(true)|bottom|false + Form without buttons is auto-submitted. + + @property showbuttons + @type boolean|string + @default true + @since 1.1.1 + **/ + showbuttons: true, + /** + Scope for callback methods (success, validate). + If <code>null</code> means editableform instance itself. + + @property scope + @type DOMElement|object + @default null + @since 1.2.0 + @private + **/ + scope: null, + /** + Whether to save or cancel value when it was not changed but form was submitted + + @property savenochange + @type boolean + @default false + @since 1.2.0 + **/ + savenochange: false + }; + + /* + Note: following params could redefined in engine: bootstrap or jqueryui: + Classes 'control-group' and 'editable-error-block' must always present! + */ + $.fn.editableform.template = '<form class="form-inline editableform">'+ + '<div class="control-group">' + + '<div><div class="editable-input"></div><div class="editable-buttons"></div></div>'+ + '<div class="editable-error-block"></div>' + + '</div>' + + '</form>'; + + //loading div + $.fn.editableform.loading = '<div class="editableform-loading"></div>'; + + //buttons + $.fn.editableform.buttons = '<button type="submit" class="editable-submit">ok</button>'+ + '<button type="button" class="editable-cancel">cancel</button>'; + + //error class attached to control-group + $.fn.editableform.errorGroupClass = null; + + //error class attached to editable-error-block + $.fn.editableform.errorBlockClass = 'editable-error'; + + //engine + $.fn.editableform.engine = 'jquery'; +}(window.jQuery)); + +/** +* EditableForm utilites +*/ +(function ($) { + "use strict"; + + //utils + $.fn.editableutils = { + /** + * classic JS inheritance function + */ + inherit: function (Child, Parent) { + var F = function() { }; + F.prototype = Parent.prototype; + Child.prototype = new F(); + Child.prototype.constructor = Child; + Child.superclass = Parent.prototype; + }, + + /** + * set caret position in input + * see http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area + */ + setCursorPosition: function(elem, pos) { + if (elem.setSelectionRange) { + elem.setSelectionRange(pos, pos); + } else if (elem.createTextRange) { + var range = elem.createTextRange(); + range.collapse(true); + range.moveEnd('character', pos); + range.moveStart('character', pos); + range.select(); + } + }, + + /** + * function to parse JSON in *single* quotes. (jquery automatically parse only double quotes) + * That allows such code as: <a data-source="{'a': 'b', 'c': 'd'}"> + * safe = true --> means no exception will be thrown + * for details see http://stackoverflow.com/questions/7410348/how-to-set-json-format-to-html5-data-attributes-in-the-jquery + */ + tryParseJson: function(s, safe) { + if (typeof s === 'string' && s.length && s.match(/^[\{\[].*[\}\]]$/)) { + if (safe) { + try { + /*jslint evil: true*/ + s = (new Function('return ' + s))(); + /*jslint evil: false*/ + } catch (e) {} finally { + return s; + } + } else { + /*jslint evil: true*/ + s = (new Function('return ' + s))(); + /*jslint evil: false*/ + } + } + return s; + }, + + /** + * slice object by specified keys + */ + sliceObj: function(obj, keys, caseSensitive /* default: false */) { + var key, keyLower, newObj = {}; + + if (!$.isArray(keys) || !keys.length) { + return newObj; + } + + for (var i = 0; i < keys.length; i++) { + key = keys[i]; + if (obj.hasOwnProperty(key)) { + newObj[key] = obj[key]; + } + + if(caseSensitive === true) { + continue; + } + + //when getting data-* attributes via $.data() it's converted to lowercase. + //details: http://stackoverflow.com/questions/7602565/using-data-attributes-with-jquery + //workaround is code below. + keyLower = key.toLowerCase(); + if (obj.hasOwnProperty(keyLower)) { + newObj[key] = obj[keyLower]; + } + } + + return newObj; + }, + + /* + exclude complex objects from $.data() before pass to config + */ + getConfigData: function($element) { + var data = {}; + $.each($element.data(), function(k, v) { + if(typeof v !== 'object' || (v && typeof v === 'object' && (v.constructor === Object || v.constructor === Array))) { + data[k] = v; + } + }); + return data; + }, + + /* + returns keys of object + */ + objectKeys: function(o) { + if (Object.keys) { + return Object.keys(o); + } else { + if (o !== Object(o)) { + throw new TypeError('Object.keys called on a non-object'); + } + var k=[], p; + for (p in o) { + if (Object.prototype.hasOwnProperty.call(o,p)) { + k.push(p); + } + } + return k; + } + + }, + + /** + method to escape html. + **/ + escape: function(str) { + return $('<div>').text(str).html(); + }, + + /* + returns array items from sourceData having value property equal or inArray of 'value' + */ + itemsByValue: function(value, sourceData, valueProp) { + if(!sourceData || value === null) { + return []; + } + + if (typeof(valueProp) !== "function") { + var idKey = valueProp || 'value'; + valueProp = function (e) { return e[idKey]; }; + } + + var isValArray = $.isArray(value), + result = [], + that = this; + + $.each(sourceData, function(i, o) { + if(o.children) { + result = result.concat(that.itemsByValue(value, o.children, valueProp)); + } else { + /*jslint eqeq: true*/ + if(isValArray) { + if($.grep(value, function(v){ return v == (o && typeof o === 'object' ? valueProp(o) : o); }).length) { + result.push(o); + } + } else { + var itemValue = (o && (typeof o === 'object')) ? valueProp(o) : o; + if(value == itemValue) { + result.push(o); + } + } + /*jslint eqeq: false*/ + } + }); + + return result; + }, + + /* + Returns input by options: type, mode. + */ + createInput: function(options) { + var TypeConstructor, typeOptions, input, + type = options.type; + + //`date` is some kind of virtual type that is transformed to one of exact types + //depending on mode and core lib + if(type === 'date') { + //inline + if(options.mode === 'inline') { + if($.fn.editabletypes.datefield) { + type = 'datefield'; + } else if($.fn.editabletypes.dateuifield) { + type = 'dateuifield'; + } + //popup + } else { + if($.fn.editabletypes.date) { + type = 'date'; + } else if($.fn.editabletypes.dateui) { + type = 'dateui'; + } + } + + //if type still `date` and not exist in types, replace with `combodate` that is base input + if(type === 'date' && !$.fn.editabletypes.date) { + type = 'combodate'; + } + } + + //`datetime` should be datetimefield in 'inline' mode + if(type === 'datetime' && options.mode === 'inline') { + type = 'datetimefield'; + } + + //change wysihtml5 to textarea for jquery UI and plain versions + if(type === 'wysihtml5' && !$.fn.editabletypes[type]) { + type = 'textarea'; + } + + //create input of specified type. Input will be used for converting value, not in form + if(typeof $.fn.editabletypes[type] === 'function') { + TypeConstructor = $.fn.editabletypes[type]; + typeOptions = this.sliceObj(options, this.objectKeys(TypeConstructor.defaults)); + input = new TypeConstructor(typeOptions); + return input; + } else { + $.error('Unknown type: '+ type); + return false; + } + }, + + //see http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr + supportsTransitions: function () { + var b = document.body || document.documentElement, + s = b.style, + p = 'transition', + v = ['Moz', 'Webkit', 'Khtml', 'O', 'ms']; + + if(typeof s[p] === 'string') { + return true; + } + + // Tests for vendor specific prop + p = p.charAt(0).toUpperCase() + p.substr(1); + for(var i=0; i<v.length; i++) { + if(typeof s[v[i] + p] === 'string') { + return true; + } + } + return false; + } + + }; +}(window.jQuery)); + +/** +Attaches stand-alone container with editable-form to HTML element. Element is used only for positioning, value is not stored anywhere.<br> +This method applied internally in <code>$().editable()</code>. You should subscribe on it's events (save / cancel) to get profit of it.<br> +Final realization can be different: bootstrap-popover, jqueryui-tooltip, poshytip, inline-div. It depends on which js file you include.<br> +Applied as jQuery method. + +@class editableContainer +@uses editableform +**/ +(function ($) { + "use strict"; + + var Popup = function (element, options) { + this.init(element, options); + }; + + var Inline = function (element, options) { + this.init(element, options); + }; + + //methods + Popup.prototype = { + containerName: null, //method to call container on element + containerDataName: null, //object name in element's .data() + innerCss: null, //tbd in child class + containerClass: 'editable-container editable-popup', //css class applied to container element + defaults: {}, //container itself defaults + + init: function(element, options) { + this.$element = $(element); + //since 1.4.1 container do not use data-* directly as they already merged into options. + this.options = $.extend({}, $.fn.editableContainer.defaults, options); + this.splitOptions(); + + //set scope of form callbacks to element + this.formOptions.scope = this.$element[0]; + + this.initContainer(); + + //flag to hide container, when saving value will finish + this.delayedHide = false; + + //bind 'destroyed' listener to destroy container when element is removed from dom + this.$element.on('destroyed', $.proxy(function(){ + this.destroy(); + }, this)); + + //attach document handler to close containers on click / escape + if(!$(document).data('editable-handlers-attached')) { + //close all on escape + $(document).on('keyup.editable', function (e) { + if (e.which === 27) { + $('.editable-open').editableContainer('hide'); + //todo: return focus on element + } + }); + + //close containers when click outside + //(mousedown could be better than click, it closes everything also on drag drop) + $(document).on('click.editable', function(e) { + var $target = $(e.target), i, + exclude_classes = ['.editable-container', + '.ui-datepicker-header', + '.datepicker', //in inline mode datepicker is rendered into body + '.modal-backdrop', + '.bootstrap-wysihtml5-insert-image-modal', + '.bootstrap-wysihtml5-insert-link-modal' + ]; + + //check if element is detached. It occurs when clicking in bootstrap datepicker + if (!$.contains(document.documentElement, e.target)) { + return; + } + + //for some reason FF 20 generates extra event (click) in select2 widget with e.target = document + //we need to filter it via construction below. See https://github.com/vitalets/x-editable/issues/199 + //Possibly related to http://stackoverflow.com/questions/10119793/why-does-firefox-react-differently-from-webkit-and-ie-to-click-event-on-selec + if($target.is(document)) { + return; + } + + //if click inside one of exclude classes --> no nothing + for(i=0; i<exclude_classes.length; i++) { + if($target.is(exclude_classes[i]) || $target.parents(exclude_classes[i]).length) { + return; + } + } + + //close all open containers (except one - target) + Popup.prototype.closeOthers(e.target); + }); + + $(document).data('editable-handlers-attached', true); + } + }, + + //split options on containerOptions and formOptions + splitOptions: function() { + this.containerOptions = {}; + this.formOptions = {}; + + if(!$.fn[this.containerName]) { + throw new Error(this.containerName + ' not found. Have you included corresponding js file?'); + } + + //keys defined in container defaults go to container, others go to form + for(var k in this.options) { + if(k in this.defaults) { + this.containerOptions[k] = this.options[k]; + } else { + this.formOptions[k] = this.options[k]; + } + } + }, + + /* + Returns jquery object of container + @method tip() + */ + tip: function() { + return this.container() ? this.container().$tip : null; + }, + + /* returns container object */ + container: function() { + var container; + //first, try get it by `containerDataName` + if(this.containerDataName) { + if(container = this.$element.data(this.containerDataName)) { + return container; + } + } + //second, try `containerName` + container = this.$element.data(this.containerName); + return container; + }, + + /* call native method of underlying container, e.g. this.$element.popover('method') */ + call: function() { + this.$element[this.containerName].apply(this.$element, arguments); + }, + + initContainer: function(){ + this.call(this.containerOptions); + }, + + renderForm: function() { + this.$form + .editableform(this.formOptions) + .on({ + save: $.proxy(this.save, this), //click on submit button (value changed) + nochange: $.proxy(function(){ this.hide('nochange'); }, this), //click on submit button (value NOT changed) + cancel: $.proxy(function(){ this.hide('cancel'); }, this), //click on calcel button + show: $.proxy(function() { + if(this.delayedHide) { + this.hide(this.delayedHide.reason); + this.delayedHide = false; + } else { + this.setPosition(); + } + }, this), //re-position container every time form is shown (occurs each time after loading state) + rendering: $.proxy(this.setPosition, this), //this allows to place container correctly when loading shown + resize: $.proxy(this.setPosition, this), //this allows to re-position container when form size is changed + rendered: $.proxy(function(){ + /** + Fired when container is shown and form is rendered (for select will wait for loading dropdown options). + **Note:** Bootstrap popover has own `shown` event that now cannot be separated from x-editable's one. + The workaround is to check `arguments.length` that is always `2` for x-editable. + + @event shown + @param {Object} event event object + @example + $('#username').on('shown', function(e, editable) { + editable.input.$input.val('overwriting value of input..'); + }); + **/ + /* + TODO: added second param mainly to distinguish from bootstrap's shown event. It's a hotfix that will be solved in future versions via namespaced events. + */ + this.$element.triggerHandler('shown', $(this.options.scope).data('editable')); + }, this) + }) + .editableform('render'); + }, + + /** + Shows container with form + @method show() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + /* Note: poshytip owerwrites this method totally! */ + show: function (closeAll) { + this.$element.addClass('editable-open'); + if(closeAll !== false) { + //close all open containers (except this) + this.closeOthers(this.$element[0]); + } + + //show container itself + this.innerShow(); + this.tip().addClass(this.containerClass); + + /* + Currently, form is re-rendered on every show. + The main reason is that we dont know, what will container do with content when closed: + remove(), detach() or just hide() - it depends on container. + + Detaching form itself before hide and re-insert before show is good solution, + but visually it looks ugly --> container changes size before hide. + */ + + //if form already exist - delete previous data + if(this.$form) { + //todo: destroy prev data! + //this.$form.destroy(); + } + + this.$form = $('<div>'); + + //insert form into container body + if(this.tip().is(this.innerCss)) { + //for inline container + this.tip().append(this.$form); + } else { + this.tip().find(this.innerCss).append(this.$form); + } + + //render form + this.renderForm(); + }, + + /** + Hides container with form + @method hide() + @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|undefined (=manual)</code> + **/ + hide: function(reason) { + if(!this.tip() || !this.tip().is(':visible') || !this.$element.hasClass('editable-open')) { + return; + } + + //if form is saving value, schedule hide + if(this.$form.data('editableform').isSaving) { + this.delayedHide = {reason: reason}; + return; + } else { + this.delayedHide = false; + } + + this.$element.removeClass('editable-open'); + this.innerHide(); + + /** + Fired when container was hidden. It occurs on both save or cancel. + **Note:** Bootstrap popover has own `hidden` event that now cannot be separated from x-editable's one. + The workaround is to check `arguments.length` that is always `2` for x-editable. + + @event hidden + @param {object} event event object + @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|manual</code> + @example + $('#username').on('hidden', function(e, reason) { + if(reason === 'save' || reason === 'cancel') { + //auto-open next editable + $(this).closest('tr').next().find('.editable').editable('show'); + } + }); + **/ + this.$element.triggerHandler('hidden', reason || 'manual'); + }, + + /* internal show method. To be overwritten in child classes */ + innerShow: function () { + + }, + + /* internal hide method. To be overwritten in child classes */ + innerHide: function () { + + }, + + /** + Toggles container visibility (show / hide) + @method toggle() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + toggle: function(closeAll) { + if(this.container() && this.tip() && this.tip().is(':visible')) { + this.hide(); + } else { + this.show(closeAll); + } + }, + + /* + Updates the position of container when content changed. + @method setPosition() + */ + setPosition: function() { + //tbd in child class + }, + + save: function(e, params) { + /** + Fired when new value was submitted. You can use <code>$(this).data('editableContainer')</code> inside handler to access to editableContainer instance + + @event save + @param {Object} event event object + @param {Object} params additional params + @param {mixed} params.newValue submitted value + @param {Object} params.response ajax response + @example + $('#username').on('save', function(e, params) { + //assuming server response: '{success: true}' + var pk = $(this).data('editableContainer').options.pk; + if(params.response && params.response.success) { + alert('value: ' + params.newValue + ' with pk: ' + pk + ' saved!'); + } else { + alert('error!'); + } + }); + **/ + this.$element.triggerHandler('save', params); + + //hide must be after trigger, as saving value may require methods of plugin, applied to input + this.hide('save'); + }, + + /** + Sets new option + + @method option(key, value) + @param {string} key + @param {mixed} value + **/ + option: function(key, value) { + this.options[key] = value; + if(key in this.containerOptions) { + this.containerOptions[key] = value; + this.setContainerOption(key, value); + } else { + this.formOptions[key] = value; + if(this.$form) { + this.$form.editableform('option', key, value); + } + } + }, + + setContainerOption: function(key, value) { + this.call('option', key, value); + }, + + /** + Destroys the container instance + @method destroy() + **/ + destroy: function() { + this.hide(); + this.innerDestroy(); + this.$element.off('destroyed'); + this.$element.removeData('editableContainer'); + }, + + /* to be overwritten in child classes */ + innerDestroy: function() { + + }, + + /* + Closes other containers except one related to passed element. + Other containers can be cancelled or submitted (depends on onblur option) + */ + closeOthers: function(element) { + $('.editable-open').each(function(i, el){ + //do nothing with passed element and it's children + if(el === element || $(el).find(element).length) { + return; + } + + //otherwise cancel or submit all open containers + var $el = $(el), + ec = $el.data('editableContainer'); + + if(!ec) { + return; + } + + if(ec.options.onblur === 'cancel') { + $el.data('editableContainer').hide('onblur'); + } else if(ec.options.onblur === 'submit') { + $el.data('editableContainer').tip().find('form').submit(); + } + }); + + }, + + /** + Activates input of visible container (e.g. set focus) + @method activate() + **/ + activate: function() { + if(this.tip && this.tip().is(':visible') && this.$form) { + this.$form.data('editableform').input.activate(); + } + } + + }; + + /** + jQuery method to initialize editableContainer. + + @method $().editableContainer(options) + @params {Object} options + @example + $('#edit').editableContainer({ + type: 'text', + url: '/post', + pk: 1, + value: 'hello' + }); + **/ + $.fn.editableContainer = function (option) { + var args = arguments; + return this.each(function () { + var $this = $(this), + dataKey = 'editableContainer', + data = $this.data(dataKey), + options = typeof option === 'object' && option, + Constructor = (options.mode === 'inline') ? Inline : Popup; + + if (!data) { + $this.data(dataKey, (data = new Constructor(this, options))); + } + + if (typeof option === 'string') { //call method + data[option].apply(data, Array.prototype.slice.call(args, 1)); + } + }); + }; + + //store constructors + $.fn.editableContainer.Popup = Popup; + $.fn.editableContainer.Inline = Inline; + + //defaults + $.fn.editableContainer.defaults = { + /** + Initial value of form input + + @property value + @type mixed + @default null + @private + **/ + value: null, + /** + Placement of container relative to element. Can be <code>top|right|bottom|left</code>. Not used for inline container. + + @property placement + @type string + @default 'top' + **/ + placement: 'top', + /** + Whether to hide container on save/cancel. + + @property autohide + @type boolean + @default true + @private + **/ + autohide: true, + /** + Action when user clicks outside the container. Can be <code>cancel|submit|ignore</code>. + Setting <code>ignore</code> allows to have several containers open. + + @property onblur + @type string + @default 'cancel' + @since 1.1.1 + **/ + onblur: 'cancel', + + /** + Animation speed (inline mode only) + @property anim + @type string + @default false + **/ + anim: false, + + /** + Mode of editable, can be `popup` or `inline` + + @property mode + @type string + @default 'popup' + @since 1.4.0 + **/ + mode: 'popup' + }; + + /* + * workaround to have 'destroyed' event to destroy popover when element is destroyed + * see http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom + */ + jQuery.event.special.destroyed = { + remove: function(o) { + if (o.handler) { + o.handler(); + } + } + }; + +}(window.jQuery)); + +/** +* Editable Inline +* --------------------- +*/ +(function ($) { + "use strict"; + + //copy prototype from EditableContainer + //extend methods + $.extend($.fn.editableContainer.Inline.prototype, $.fn.editableContainer.Popup.prototype, { + containerName: 'editableform', + innerCss: '.editable-inline', + containerClass: 'editable-container editable-inline', //css class applied to container element + + initContainer: function(){ + //container is <span> element + this.$tip = $('<span></span>'); + + //convert anim to miliseconds (int) + if(!this.options.anim) { + this.options.anim = 0; + } + }, + + splitOptions: function() { + //all options are passed to form + this.containerOptions = {}; + this.formOptions = this.options; + }, + + tip: function() { + return this.$tip; + }, + + innerShow: function () { + this.$element.hide(); + this.tip().insertAfter(this.$element).show(); + }, + + innerHide: function () { + this.$tip.hide(this.options.anim, $.proxy(function() { + this.$element.show(); + this.innerDestroy(); + }, this)); + }, + + innerDestroy: function() { + if(this.tip()) { + this.tip().empty().remove(); + } + } + }); + +}(window.jQuery)); +/** +Makes editable any HTML element on the page. Applied as jQuery method. + +@class editable +@uses editableContainer +**/ +(function ($) { + "use strict"; + + var Editable = function (element, options) { + this.$element = $(element); + //data-* has more priority over js options: because dynamically created elements may change data-* + this.options = $.extend({}, $.fn.editable.defaults, options, $.fn.editableutils.getConfigData(this.$element)); + if(this.options.selector) { + this.initLive(); + } else { + this.init(); + } + + //check for transition support + if(this.options.highlight && !$.fn.editableutils.supportsTransitions()) { + this.options.highlight = false; + } + }; + + Editable.prototype = { + constructor: Editable, + init: function () { + var isValueByText = false, + doAutotext, finalize; + + //name + this.options.name = this.options.name || this.$element.attr('id'); + + //create input of specified type. Input needed already here to convert value for initial display (e.g. show text by id for select) + //also we set scope option to have access to element inside input specific callbacks (e. g. source as function) + this.options.scope = this.$element[0]; + this.input = $.fn.editableutils.createInput(this.options); + if(!this.input) { + return; + } + + //set value from settings or by element's text + if (this.options.value === undefined || this.options.value === null) { + this.value = this.input.html2value($.trim(this.$element.html())); + isValueByText = true; + } else { + /* + value can be string when received from 'data-value' attribute + for complext objects value can be set as json string in data-value attribute, + e.g. data-value="{city: 'Moscow', street: 'Lenina'}" + */ + this.options.value = $.fn.editableutils.tryParseJson(this.options.value, true); + if(typeof this.options.value === 'string') { + this.value = this.input.str2value(this.options.value); + } else { + this.value = this.options.value; + } + } + + //add 'editable' class to every editable element + this.$element.addClass('editable'); + + //specifically for "textarea" add class .editable-pre-wrapped to keep linebreaks + if(this.input.type === 'textarea') { + this.$element.addClass('editable-pre-wrapped'); + } + + //attach handler activating editable. In disabled mode it just prevent default action (useful for links) + if(this.options.toggle !== 'manual') { + this.$element.addClass('editable-click'); + this.$element.on(this.options.toggle + '.editable', $.proxy(function(e){ + //prevent following link if editable enabled + if(!this.options.disabled) { + e.preventDefault(); + } + + //stop propagation not required because in document click handler it checks event target + //e.stopPropagation(); + + if(this.options.toggle === 'mouseenter') { + //for hover only show container + this.show(); + } else { + //when toggle='click' we should not close all other containers as they will be closed automatically in document click listener + var closeAll = (this.options.toggle !== 'click'); + this.toggle(closeAll); + } + }, this)); + } else { + this.$element.attr('tabindex', -1); //do not stop focus on element when toggled manually + } + + //if display is function it's far more convinient to have autotext = always to render correctly on init + //see https://github.com/vitalets/x-editable-yii/issues/34 + if(typeof this.options.display === 'function') { + this.options.autotext = 'always'; + } + + //check conditions for autotext: + switch(this.options.autotext) { + case 'always': + doAutotext = true; + break; + case 'auto': + //if element text is empty and value is defined and value not generated by text --> run autotext + doAutotext = !$.trim(this.$element.text()).length && this.value !== null && this.value !== undefined && !isValueByText; + break; + default: + doAutotext = false; + } + + //depending on autotext run render() or just finilize init + $.when(doAutotext ? this.render() : true).then($.proxy(function() { + if(this.options.disabled) { + this.disable(); + } else { + this.enable(); + } + /** + Fired when element was initialized by `$().editable()` method. + Please note that you should setup `init` handler **before** applying `editable`. + + @event init + @param {Object} event event object + @param {Object} editable editable instance (as here it cannot accessed via data('editable')) + @since 1.2.0 + @example + $('#username').on('init', function(e, editable) { + alert('initialized ' + editable.options.name); + }); + $('#username').editable(); + **/ + this.$element.triggerHandler('init', this); + }, this)); + }, + + /* + Initializes parent element for live editables + */ + initLive: function() { + //store selector + var selector = this.options.selector; + //modify options for child elements + this.options.selector = false; + this.options.autotext = 'never'; + //listen toggle events + this.$element.on(this.options.toggle + '.editable', selector, $.proxy(function(e){ + var $target = $(e.target); + if(!$target.data('editable')) { + //if delegated element initially empty, we need to clear it's text (that was manually set to `empty` by user) + //see https://github.com/vitalets/x-editable/issues/137 + if($target.hasClass(this.options.emptyclass)) { + $target.empty(); + } + $target.editable(this.options).trigger(e); + } + }, this)); + }, + + /* + Renders value into element's text. + Can call custom display method from options. + Can return deferred object. + @method render() + @param {mixed} response server response (if exist) to pass into display function + */ + render: function(response) { + //do not display anything + if(this.options.display === false) { + return; + } + + //if input has `value2htmlFinal` method, we pass callback in third param to be called when source is loaded + if(this.input.value2htmlFinal) { + return this.input.value2html(this.value, this.$element[0], this.options.display, response); + //if display method defined --> use it + } else if(typeof this.options.display === 'function') { + return this.options.display.call(this.$element[0], this.value, response); + //else use input's original value2html() method + } else { + return this.input.value2html(this.value, this.$element[0]); + } + }, + + /** + Enables editable + @method enable() + **/ + enable: function() { + this.options.disabled = false; + this.$element.removeClass('editable-disabled'); + this.handleEmpty(this.isEmpty); + if(this.options.toggle !== 'manual') { + if(this.$element.attr('tabindex') === '-1') { + this.$element.removeAttr('tabindex'); + } + } + }, + + /** + Disables editable + @method disable() + **/ + disable: function() { + this.options.disabled = true; + this.hide(); + this.$element.addClass('editable-disabled'); + this.handleEmpty(this.isEmpty); + //do not stop focus on this element + this.$element.attr('tabindex', -1); + }, + + /** + Toggles enabled / disabled state of editable element + @method toggleDisabled() + **/ + toggleDisabled: function() { + if(this.options.disabled) { + this.enable(); + } else { + this.disable(); + } + }, + + /** + Sets new option + + @method option(key, value) + @param {string|object} key option name or object with several options + @param {mixed} value option new value + @example + $('.editable').editable('option', 'pk', 2); + **/ + option: function(key, value) { + //set option(s) by object + if(key && typeof key === 'object') { + $.each(key, $.proxy(function(k, v){ + this.option($.trim(k), v); + }, this)); + return; + } + + //set option by string + this.options[key] = value; + + //disabled + if(key === 'disabled') { + return value ? this.disable() : this.enable(); + } + + //value + if(key === 'value') { + this.setValue(value); + } + + //transfer new option to container! + if(this.container) { + this.container.option(key, value); + } + + //pass option to input directly (as it points to the same in form) + if(this.input.option) { + this.input.option(key, value); + } + + }, + + /* + * set emptytext if element is empty + */ + handleEmpty: function (isEmpty) { + //do not handle empty if we do not display anything + if(this.options.display === false) { + return; + } + + /* + isEmpty may be set directly as param of method. + It is required when we enable/disable field and can't rely on content + as node content is text: "Empty" that is not empty %) + */ + if(isEmpty !== undefined) { + this.isEmpty = isEmpty; + } else { + //detect empty + //for some inputs we need more smart check + //e.g. wysihtml5 may have <br>, <p></p>, <img> + if(typeof(this.input.isEmpty) === 'function') { + this.isEmpty = this.input.isEmpty(this.$element); + } else { + this.isEmpty = $.trim(this.$element.html()) === ''; + } + } + + //emptytext shown only for enabled + if(!this.options.disabled) { + if (this.isEmpty) { + this.$element.html(this.options.emptytext); + if(this.options.emptyclass) { + this.$element.addClass(this.options.emptyclass); + } + } else if(this.options.emptyclass) { + this.$element.removeClass(this.options.emptyclass); + } + } else { + //below required if element disable property was changed + if(this.isEmpty) { + this.$element.empty(); + if(this.options.emptyclass) { + this.$element.removeClass(this.options.emptyclass); + } + } + } + }, + + /** + Shows container with form + @method show() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + show: function (closeAll) { + if(this.options.disabled) { + return; + } + + //init editableContainer: popover, tooltip, inline, etc.. + if(!this.container) { + var containerOptions = $.extend({}, this.options, { + value: this.value, + input: this.input //pass input to form (as it is already created) + }); + this.$element.editableContainer(containerOptions); + //listen `save` event + this.$element.on("save.internal", $.proxy(this.save, this)); + this.container = this.$element.data('editableContainer'); + } else if(this.container.tip().is(':visible')) { + return; + } + + //show container + this.container.show(closeAll); + }, + + /** + Hides container with form + @method hide() + **/ + hide: function () { + if(this.container) { + this.container.hide(); + } + }, + + /** + Toggles container visibility (show / hide) + @method toggle() + @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true. + **/ + toggle: function(closeAll) { + if(this.container && this.container.tip().is(':visible')) { + this.hide(); + } else { + this.show(closeAll); + } + }, + + /* + * called when form was submitted + */ + save: function(e, params) { + //mark element with unsaved class if needed + if(this.options.unsavedclass) { + /* + Add unsaved css to element if: + - url is not user's function + - value was not sent to server + - params.response === undefined, that means data was not sent + - value changed + */ + var sent = false; + sent = sent || typeof this.options.url === 'function'; + sent = sent || this.options.display === false; + sent = sent || params.response !== undefined; + sent = sent || (this.options.savenochange && this.input.value2str(this.value) !== this.input.value2str(params.newValue)); + + if(sent) { + this.$element.removeClass(this.options.unsavedclass); + } else { + this.$element.addClass(this.options.unsavedclass); + } + } + + //highlight when saving + if(this.options.highlight) { + var $e = this.$element, + bgColor = $e.css('background-color'); + + $e.css('background-color', this.options.highlight); + setTimeout(function(){ + if(bgColor === 'transparent') { + bgColor = ''; + } + $e.css('background-color', bgColor); + $e.addClass('editable-bg-transition'); + setTimeout(function(){ + $e.removeClass('editable-bg-transition'); + }, 1700); + }, 10); + } + + //set new value + this.setValue(params.newValue, false, params.response); + + /** + Fired when new value was submitted. You can use <code>$(this).data('editable')</code> to access to editable instance + + @event save + @param {Object} event event object + @param {Object} params additional params + @param {mixed} params.newValue submitted value + @param {Object} params.response ajax response + @example + $('#username').on('save', function(e, params) { + alert('Saved value: ' + params.newValue); + }); + **/ + //event itself is triggered by editableContainer. Description here is only for documentation + }, + + validate: function () { + if (typeof this.options.validate === 'function') { + return this.options.validate.call(this, this.value); + } + }, + + /** + Sets new value of editable + @method setValue(value, convertStr) + @param {mixed} value new value + @param {boolean} convertStr whether to convert value from string to internal format + **/ + setValue: function(value, convertStr, response) { + if(convertStr) { + this.value = this.input.str2value(value); + } else { + this.value = value; + } + if(this.container) { + this.container.option('value', this.value); + } + $.when(this.render(response)) + .then($.proxy(function() { + this.handleEmpty(); + }, this)); + }, + + /** + Activates input of visible container (e.g. set focus) + @method activate() + **/ + activate: function() { + if(this.container) { + this.container.activate(); + } + }, + + /** + Removes editable feature from element + @method destroy() + **/ + destroy: function() { + this.disable(); + + if(this.container) { + this.container.destroy(); + } + + this.input.destroy(); + + if(this.options.toggle !== 'manual') { + this.$element.removeClass('editable-click'); + this.$element.off(this.options.toggle + '.editable'); + } + + this.$element.off("save.internal"); + + this.$element.removeClass('editable editable-open editable-disabled'); + this.$element.removeData('editable'); + } + }; + + /* EDITABLE PLUGIN DEFINITION + * ======================= */ + + /** + jQuery method to initialize editable element. + + @method $().editable(options) + @params {Object} options + @example + $('#username').editable({ + type: 'text', + url: '/post', + pk: 1 + }); + **/ + $.fn.editable = function (option) { + //special API methods returning non-jquery object + var result = {}, args = arguments, datakey = 'editable'; + switch (option) { + /** + Runs client-side validation for all matched editables + + @method validate() + @returns {Object} validation errors map + @example + $('#username, #fullname').editable('validate'); + // possible result: + { + username: "username is required", + fullname: "fullname should be minimum 3 letters length" + } + **/ + case 'validate': + this.each(function () { + var $this = $(this), data = $this.data(datakey), error; + if (data && (error = data.validate())) { + result[data.options.name] = error; + } + }); + return result; + + /** + Returns current values of editable elements. + Note that it returns an **object** with name-value pairs, not a value itself. It allows to get data from several elements. + If value of some editable is `null` or `undefined` it is excluded from result object. + When param `isSingle` is set to **true** - it is supposed you have single element and will return value of editable instead of object. + + @method getValue() + @param {bool} isSingle whether to return just value of single element + @returns {Object} object of element names and values + @example + $('#username, #fullname').editable('getValue'); + //result: + { + username: "superuser", + fullname: "John" + } + //isSingle = true + $('#username').editable('getValue', true); + //result "superuser" + **/ + case 'getValue': + if(arguments.length === 2 && arguments[1] === true) { //isSingle = true + result = this.eq(0).data(datakey).value; + } else { + this.each(function () { + var $this = $(this), data = $this.data(datakey); + if (data && data.value !== undefined && data.value !== null) { + result[data.options.name] = data.input.value2submit(data.value); + } + }); + } + return result; + + /** + This method collects values from several editable elements and submit them all to server. + Internally it runs client-side validation for all fields and submits only in case of success. + See <a href="#newrecord">creating new records</a> for details. + Since 1.5.1 `submit` can be applied to single element to send data programmatically. In that case + `url`, `success` and `error` is taken from initial options and you can just call `$('#username').editable('submit')`. + + @method submit(options) + @param {object} options + @param {object} options.url url to submit data + @param {object} options.data additional data to submit + @param {object} options.ajaxOptions additional ajax options + @param {function} options.error(obj) error handler + @param {function} options.success(obj,config) success handler + @returns {Object} jQuery object + **/ + case 'submit': //collects value, validate and submit to server for creating new record + var config = arguments[1] || {}, + $elems = this, + errors = this.editable('validate'); + + // validation ok + if($.isEmptyObject(errors)) { + var ajaxOptions = {}; + + // for single element use url, success etc from options + if($elems.length === 1) { + var editable = $elems.data('editable'); + //standard params + var params = { + name: editable.options.name || '', + value: editable.input.value2submit(editable.value), + pk: (typeof editable.options.pk === 'function') ? + editable.options.pk.call(editable.options.scope) : + editable.options.pk + }; + + //additional params + if(typeof editable.options.params === 'function') { + params = editable.options.params.call(editable.options.scope, params); + } else { + //try parse json in single quotes (from data-params attribute) + editable.options.params = $.fn.editableutils.tryParseJson(editable.options.params, true); + $.extend(params, editable.options.params); + } + + ajaxOptions = { + url: editable.options.url, + data: params, + type: 'POST' + }; + + // use success / error from options + config.success = config.success || editable.options.success; + config.error = config.error || editable.options.error; + + // multiple elements + } else { + var values = this.editable('getValue'); + + ajaxOptions = { + url: config.url, + data: values, + type: 'POST' + }; + } + + // ajax success callabck (response 200 OK) + ajaxOptions.success = typeof config.success === 'function' ? function(response) { + config.success.call($elems, response, config); + } : $.noop; + + // ajax error callabck + ajaxOptions.error = typeof config.error === 'function' ? function() { + config.error.apply($elems, arguments); + } : $.noop; + + // extend ajaxOptions + if(config.ajaxOptions) { + $.extend(ajaxOptions, config.ajaxOptions); + } + + // extra data + if(config.data) { + $.extend(ajaxOptions.data, config.data); + } + + // perform ajax request + $.ajax(ajaxOptions); + } else { //client-side validation error + if(typeof config.error === 'function') { + config.error.call($elems, errors); + } + } + return this; + } + + //return jquery object + return this.each(function () { + var $this = $(this), + data = $this.data(datakey), + options = typeof option === 'object' && option; + + //for delegated targets do not store `editable` object for element + //it's allows several different selectors. + //see: https://github.com/vitalets/x-editable/issues/312 + if(options && options.selector) { + data = new Editable(this, options); + return; + } + + if (!data) { + $this.data(datakey, (data = new Editable(this, options))); + } + + if (typeof option === 'string') { //call method + data[option].apply(data, Array.prototype.slice.call(args, 1)); + } + }); + }; + + + $.fn.editable.defaults = { + /** + Type of input. Can be <code>text|textarea|select|date|checklist</code> and more + + @property type + @type string + @default 'text' + **/ + type: 'text', + /** + Sets disabled state of editable + + @property disabled + @type boolean + @default false + **/ + disabled: false, + /** + How to toggle editable. Can be <code>click|dblclick|mouseenter|manual</code>. + When set to <code>manual</code> you should manually call <code>show/hide</code> methods of editable. + **Note**: if you call <code>show</code> or <code>toggle</code> inside **click** handler of some DOM element, + you need to apply <code>e.stopPropagation()</code> because containers are being closed on any click on document. + + @example + $('#edit-button').click(function(e) { + e.stopPropagation(); + $('#username').editable('toggle'); + }); + + @property toggle + @type string + @default 'click' + **/ + toggle: 'click', + /** + Text shown when element is empty. + + @property emptytext + @type string + @default 'Empty' + **/ + emptytext: 'Empty', + /** + Allows to automatically set element's text based on it's value. Can be <code>auto|always|never</code>. Useful for select and date. + For example, if dropdown list is <code>{1: 'a', 2: 'b'}</code> and element's value set to <code>1</code>, it's html will be automatically set to <code>'a'</code>. + <code>auto</code> - text will be automatically set only if element is empty. + <code>always|never</code> - always(never) try to set element's text. + + @property autotext + @type string + @default 'auto' + **/ + autotext: 'auto', + /** + Initial value of input. If not set, taken from element's text. + Note, that if element's text is empty - text is automatically generated from value and can be customized (see `autotext` option). + For example, to display currency sign: + @example + <a id="price" data-type="text" data-value="100"></a> + <script> + $('#price').editable({ + ... + display: function(value) { + $(this).text(value + '$'); + } + }) + </script> + + @property value + @type mixed + @default element's text + **/ + value: null, + /** + Callback to perform custom displaying of value in element's text. + If `null`, default input's display used. + If `false`, no displaying methods will be called, element's text will never change. + Runs under element's scope. + _**Parameters:**_ + + * `value` current value to be displayed + * `response` server response (if display called after ajax submit), since 1.4.0 + + For _inputs with source_ (select, checklist) parameters are different: + + * `value` current value to be displayed + * `sourceData` array of items for current input (e.g. dropdown items) + * `response` server response (if display called after ajax submit), since 1.4.0 + + To get currently selected items use `$.fn.editableutils.itemsByValue(value, sourceData)`. + + @property display + @type function|boolean + @default null + @since 1.2.0 + @example + display: function(value, sourceData) { + //display checklist as comma-separated values + var html = [], + checked = $.fn.editableutils.itemsByValue(value, sourceData); + + if(checked.length) { + $.each(checked, function(i, v) { html.push($.fn.editableutils.escape(v.text)); }); + $(this).html(html.join(', ')); + } else { + $(this).empty(); + } + } + **/ + display: null, + /** + Css class applied when editable text is empty. + + @property emptyclass + @type string + @since 1.4.1 + @default editable-empty + **/ + emptyclass: 'editable-empty', + /** + Css class applied when value was stored but not sent to server (`pk` is empty or `send = 'never'`). + You may set it to `null` if you work with editables locally and submit them together. + + @property unsavedclass + @type string + @since 1.4.1 + @default editable-unsaved + **/ + unsavedclass: 'editable-unsaved', + /** + If selector is provided, editable will be delegated to the specified targets. + Usefull for dynamically generated DOM elements. + **Please note**, that delegated targets can't be initialized with `emptytext` and `autotext` options, + as they actually become editable only after first click. + You should manually set class `editable-click` to these elements. + Also, if element originally empty you should add class `editable-empty`, set `data-value=""` and write emptytext into element: + + @property selector + @type string + @since 1.4.1 + @default null + @example + <div id="user"> + <!-- empty --> + <a href="#" data-name="username" data-type="text" class="editable-click editable-empty" data-value="" title="Username">Empty</a> + <!-- non-empty --> + <a href="#" data-name="group" data-type="select" data-source="/groups" data-value="1" class="editable-click" title="Group">Operator</a> + </div> + + <script> + $('#user').editable({ + selector: 'a', + url: '/post', + pk: 1 + }); + </script> + **/ + selector: null, + /** + Color used to highlight element after update. Implemented via CSS3 transition, works in modern browsers. + + @property highlight + @type string|boolean + @since 1.4.5 + @default #FFFF80 + **/ + highlight: '#FFFF80' + }; + +}(window.jQuery)); + +/** +AbstractInput - base class for all editable inputs. +It defines interface to be implemented by any input type. +To create your own input you can inherit from this class. + +@class abstractinput +**/ +(function ($) { + "use strict"; + + //types + $.fn.editabletypes = {}; + + var AbstractInput = function () { }; + + AbstractInput.prototype = { + /** + Initializes input + + @method init() + **/ + init: function(type, options, defaults) { + this.type = type; + this.options = $.extend({}, defaults, options); + }, + + /* + this method called before render to init $tpl that is inserted in DOM + */ + prerender: function() { + this.$tpl = $(this.options.tpl); //whole tpl as jquery object + this.$input = this.$tpl; //control itself, can be changed in render method + this.$clear = null; //clear button + this.error = null; //error message, if input cannot be rendered + }, + + /** + Renders input from tpl. Can return jQuery deferred object. + Can be overwritten in child objects + + @method render() + **/ + render: function() { + + }, + + /** + Sets element's html by value. + + @method value2html(value, element) + @param {mixed} value + @param {DOMElement} element + **/ + value2html: function(value, element) { + $(element)[this.options.escape ? 'text' : 'html']($.trim(value)); + }, + + /** + Converts element's html to value + + @method html2value(html) + @param {string} html + @returns {mixed} + **/ + html2value: function(html) { + return $('<div>').html(html).text(); + }, + + /** + Converts value to string (for internal compare). For submitting to server used value2submit(). + + @method value2str(value) + @param {mixed} value + @returns {string} + **/ + value2str: function(value) { + return value; + }, + + /** + Converts string received from server into value. Usually from `data-value` attribute. + + @method str2value(str) + @param {string} str + @returns {mixed} + **/ + str2value: function(str) { + return str; + }, + + /** + Converts value for submitting to server. Result can be string or object. + + @method value2submit(value) + @param {mixed} value + @returns {mixed} + **/ + value2submit: function(value) { + return value; + }, + + /** + Sets value of input. + + @method value2input(value) + @param {mixed} value + **/ + value2input: function(value) { + this.$input.val(value); + }, + + /** + Returns value of input. Value can be object (e.g. datepicker) + + @method input2value() + **/ + input2value: function() { + return this.$input.val(); + }, + + /** + Activates input. For text it sets focus. + + @method activate() + **/ + activate: function() { + if(this.$input.is(':visible')) { + this.$input.focus(); + } + }, + + /** + Creates input. + + @method clear() + **/ + clear: function() { + this.$input.val(null); + }, + + /** + method to escape html. + **/ + escape: function(str) { + return $('<div>').text(str).html(); + }, + + /** + attach handler to automatically submit form when value changed (useful when buttons not shown) + **/ + autosubmit: function() { + + }, + + /** + Additional actions when destroying element + **/ + destroy: function() { + }, + + // -------- helper functions -------- + setClass: function() { + if(this.options.inputclass) { + this.$input.addClass(this.options.inputclass); + } + }, + + setAttr: function(attr) { + if (this.options[attr] !== undefined && this.options[attr] !== null) { + this.$input.attr(attr, this.options[attr]); + } + }, + + option: function(key, value) { + this.options[key] = value; + } + + }; + + AbstractInput.defaults = { + /** + HTML template of input. Normally you should not change it. + + @property tpl + @type string + @default '' + **/ + tpl: '', + /** + CSS class automatically applied to input + + @property inputclass + @type string + @default null + **/ + inputclass: null, + + /** + If `true` - html will be escaped in content of element via $.text() method. + If `false` - html will not be escaped, $.html() used. + When you use own `display` function, this option obviosly has no effect. + + @property escape + @type boolean + @since 1.5.0 + @default true + **/ + escape: true, + + //scope for external methods (e.g. source defined as function) + //for internal use only + scope: null, + + //need to re-declare showbuttons here to get it's value from common config (passed only options existing in defaults) + showbuttons: true + }; + + $.extend($.fn.editabletypes, {abstractinput: AbstractInput}); + +}(window.jQuery)); + +/** +List - abstract class for inputs that have source option loaded from js array or via ajax + +@class list +@extends abstractinput +**/ +(function ($) { + "use strict"; + + var List = function (options) { + + }; + + $.fn.editableutils.inherit(List, $.fn.editabletypes.abstractinput); + + $.extend(List.prototype, { + render: function () { + var deferred = $.Deferred(); + + this.error = null; + this.onSourceReady(function () { + this.renderList(); + deferred.resolve(); + }, function () { + this.error = this.options.sourceError; + deferred.resolve(); + }); + + return deferred.promise(); + }, + + html2value: function (html) { + return null; //can't set value by text + }, + + value2html: function (value, element, display, response) { + var deferred = $.Deferred(), + success = function () { + if(typeof display === 'function') { + //custom display method + display.call(element, value, this.sourceData, response); + } else { + this.value2htmlFinal(value, element); + } + deferred.resolve(); + }; + + //for null value just call success without loading source + if(value === null) { + success.call(this); + } else { + this.onSourceReady(success, function () { deferred.resolve(); }); + } + + return deferred.promise(); + }, + + // ------------- additional functions ------------ + + onSourceReady: function (success, error) { + //run source if it function + var source; + if ($.isFunction(this.options.source)) { + source = this.options.source.call(this.options.scope); + this.sourceData = null; + //note: if function returns the same source as URL - sourceData will be taken from cahce and no extra request performed + } else { + source = this.options.source; + } + + //if allready loaded just call success + if(this.options.sourceCache && $.isArray(this.sourceData)) { + success.call(this); + return; + } + + //try parse json in single quotes (for double quotes jquery does automatically) + try { + source = $.fn.editableutils.tryParseJson(source, false); + } catch (e) { + error.call(this); + return; + } + + //loading from url + if (typeof source === 'string') { + //try to get sourceData from cache + if(this.options.sourceCache) { + var cacheID = source, + cache; + + if (!$(document).data(cacheID)) { + $(document).data(cacheID, {}); + } + cache = $(document).data(cacheID); + + //check for cached data + if (cache.loading === false && cache.sourceData) { //take source from cache + this.sourceData = cache.sourceData; + this.doPrepend(); + success.call(this); + return; + } else if (cache.loading === true) { //cache is loading, put callback in stack to be called later + cache.callbacks.push($.proxy(function () { + this.sourceData = cache.sourceData; + this.doPrepend(); + success.call(this); + }, this)); + + //also collecting error callbacks + cache.err_callbacks.push($.proxy(error, this)); + return; + } else { //no cache yet, activate it + cache.loading = true; + cache.callbacks = []; + cache.err_callbacks = []; + } + } + + //ajaxOptions for source. Can be overwritten bt options.sourceOptions + var ajaxOptions = $.extend({ + url: source, + type: 'get', + cache: false, + dataType: 'json', + success: $.proxy(function (data) { + if(cache) { + cache.loading = false; + } + this.sourceData = this.makeArray(data); + if($.isArray(this.sourceData)) { + if(cache) { + //store result in cache + cache.sourceData = this.sourceData; + //run success callbacks for other fields waiting for this source + $.each(cache.callbacks, function () { this.call(); }); + } + this.doPrepend(); + success.call(this); + } else { + error.call(this); + if(cache) { + //run error callbacks for other fields waiting for this source + $.each(cache.err_callbacks, function () { this.call(); }); + } + } + }, this), + error: $.proxy(function () { + error.call(this); + if(cache) { + cache.loading = false; + //run error callbacks for other fields + $.each(cache.err_callbacks, function () { this.call(); }); + } + }, this) + }, this.options.sourceOptions); + + //loading sourceData from server + $.ajax(ajaxOptions); + + } else { //options as json/array + this.sourceData = this.makeArray(source); + + if($.isArray(this.sourceData)) { + this.doPrepend(); + success.call(this); + } else { + error.call(this); + } + } + }, + + doPrepend: function () { + if(this.options.prepend === null || this.options.prepend === undefined) { + return; + } + + if(!$.isArray(this.prependData)) { + //run prepend if it is function (once) + if ($.isFunction(this.options.prepend)) { + this.options.prepend = this.options.prepend.call(this.options.scope); + } + + //try parse json in single quotes + this.options.prepend = $.fn.editableutils.tryParseJson(this.options.prepend, true); + + //convert prepend from string to object + if (typeof this.options.prepend === 'string') { + this.options.prepend = {'': this.options.prepend}; + } + + this.prependData = this.makeArray(this.options.prepend); + } + + if($.isArray(this.prependData) && $.isArray(this.sourceData)) { + this.sourceData = this.prependData.concat(this.sourceData); + } + }, + + /* + renders input list + */ + renderList: function() { + // this method should be overwritten in child class + }, + + /* + set element's html by value + */ + value2htmlFinal: function(value, element) { + // this method should be overwritten in child class + }, + + /** + * convert data to array suitable for sourceData, e.g. [{value: 1, text: 'abc'}, {...}] + */ + makeArray: function(data) { + var count, obj, result = [], item, iterateItem; + if(!data || typeof data === 'string') { + return null; + } + + if($.isArray(data)) { //array + /* + function to iterate inside item of array if item is object. + Caclulates count of keys in item and store in obj. + */ + iterateItem = function (k, v) { + obj = {value: k, text: v}; + if(count++ >= 2) { + return false;// exit from `each` if item has more than one key. + } + }; + + for(var i = 0; i < data.length; i++) { + item = data[i]; + if(typeof item === 'object') { + count = 0; //count of keys inside item + $.each(item, iterateItem); + //case: [{val1: 'text1'}, {val2: 'text2} ...] + if(count === 1) { + result.push(obj); + //case: [{value: 1, text: 'text1'}, {value: 2, text: 'text2'}, ...] + } else if(count > 1) { + //removed check of existance: item.hasOwnProperty('value') && item.hasOwnProperty('text') + if(item.children) { + item.children = this.makeArray(item.children); + } + result.push(item); + } + } else { + //case: ['text1', 'text2' ...] + result.push({value: item, text: item}); + } + } + } else { //case: {val1: 'text1', val2: 'text2, ...} + $.each(data, function (k, v) { + result.push({value: k, text: v}); + }); + } + return result; + }, + + option: function(key, value) { + this.options[key] = value; + if(key === 'source') { + this.sourceData = null; + } + if(key === 'prepend') { + this.prependData = null; + } + } + + }); + + List.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + Source data for list. + If **array** - it should be in format: `[{value: 1, text: "text1"}, {value: 2, text: "text2"}, ...]` + For compability, object format is also supported: `{"1": "text1", "2": "text2" ...}` but it does not guarantee elements order. + + If **string** - considered ajax url to load items. In that case results will be cached for fields with the same source and name. See also `sourceCache` option. + + If **function**, it should return data in format above (since 1.4.0). + + Since 1.4.1 key `children` supported to render OPTGROUP (for **select** input only). + `[{text: "group1", children: [{value: 1, text: "text1"}, {value: 2, text: "text2"}]}, ...]` + + + @property source + @type string | array | object | function + @default null + **/ + source: null, + /** + Data automatically prepended to the beginning of dropdown list. + + @property prepend + @type string | array | object | function + @default false + **/ + prepend: false, + /** + Error message when list cannot be loaded (e.g. ajax error) + + @property sourceError + @type string + @default Error when loading list + **/ + sourceError: 'Error when loading list', + /** + if <code>true</code> and source is **string url** - results will be cached for fields with the same source. + Usefull for editable column in grid to prevent extra requests. + + @property sourceCache + @type boolean + @default true + @since 1.2.0 + **/ + sourceCache: true, + /** + Additional ajax options to be used in $.ajax() when loading list from server. + Useful to send extra parameters (`data` key) or change request method (`type` key). + + @property sourceOptions + @type object|function + @default null + @since 1.5.0 + **/ + sourceOptions: null + }); + + $.fn.editabletypes.list = List; + +}(window.jQuery)); + +/** +Text input + +@class text +@extends abstractinput +@final +@example +<a href="#" id="username" data-type="text" data-pk="1">awesome</a> +<script> +$(function(){ + $('#username').editable({ + url: '/post', + title: 'Enter username' + }); +}); +</script> +**/ +(function ($) { + "use strict"; + + var Text = function (options) { + this.init('text', options, Text.defaults); + }; + + $.fn.editableutils.inherit(Text, $.fn.editabletypes.abstractinput); + + $.extend(Text.prototype, { + render: function() { + this.renderClear(); + this.setClass(); + this.setAttr('placeholder'); + }, + + activate: function() { + if(this.$input.is(':visible')) { + this.$input.focus(); + $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length); + if(this.toggleClear) { + this.toggleClear(); + } + } + }, + + //render clear button + renderClear: function() { + if (this.options.clear) { + this.$clear = $('<span class="editable-clear-x"></span>'); + this.$input.after(this.$clear) + .css('padding-right', 24) + .keyup($.proxy(function(e) { + //arrows, enter, tab, etc + if(~$.inArray(e.keyCode, [40,38,9,13,27])) { + return; + } + + clearTimeout(this.t); + var that = this; + this.t = setTimeout(function() { + that.toggleClear(e); + }, 100); + + }, this)) + .parent().css('position', 'relative'); + + this.$clear.click($.proxy(this.clear, this)); + } + }, + + postrender: function() { + /* + //now `clear` is positioned via css + if(this.$clear) { + //can position clear button only here, when form is shown and height can be calculated +// var h = this.$input.outerHeight(true) || 20, + var h = this.$clear.parent().height(), + delta = (h - this.$clear.height()) / 2; + + //this.$clear.css({bottom: delta, right: delta}); + } + */ + }, + + //show / hide clear button + toggleClear: function(e) { + if(!this.$clear) { + return; + } + + var len = this.$input.val().length, + visible = this.$clear.is(':visible'); + + if(len && !visible) { + this.$clear.show(); + } + + if(!len && visible) { + this.$clear.hide(); + } + }, + + clear: function() { + this.$clear.hide(); + this.$input.val('').focus(); + } + }); + + Text.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <input type="text"> + **/ + tpl: '<input type="text">', + /** + Placeholder attribute of input. Shown when input is empty. + + @property placeholder + @type string + @default null + **/ + placeholder: null, + + /** + Whether to show `clear` button + + @property clear + @type boolean + @default true + **/ + clear: true + }); + + $.fn.editabletypes.text = Text; + +}(window.jQuery)); + +/** +Textarea input + +@class textarea +@extends abstractinput +@final +@example +<a href="#" id="comments" data-type="textarea" data-pk="1">awesome comment!</a> +<script> +$(function(){ + $('#comments').editable({ + url: '/post', + title: 'Enter comments', + rows: 10 + }); +}); +</script> +**/ +(function ($) { + "use strict"; + + var Textarea = function (options) { + this.init('textarea', options, Textarea.defaults); + }; + + $.fn.editableutils.inherit(Textarea, $.fn.editabletypes.abstractinput); + + $.extend(Textarea.prototype, { + render: function () { + this.setClass(); + this.setAttr('placeholder'); + this.setAttr('rows'); + + //ctrl + enter + this.$input.keydown(function (e) { + if (e.ctrlKey && e.which === 13) { + $(this).closest('form').submit(); + } + }); + }, + + //using `white-space: pre-wrap` solves \n <--> BR conversion very elegant! + /* + value2html: function(value, element) { + var html = '', lines; + if(value) { + lines = value.split("\n"); + for (var i = 0; i < lines.length; i++) { + lines[i] = $('<div>').text(lines[i]).html(); + } + html = lines.join('<br>'); + } + $(element).html(html); + }, + + html2value: function(html) { + if(!html) { + return ''; + } + + var regex = new RegExp(String.fromCharCode(10), 'g'); + var lines = html.split(/<br\s*\/?>/i); + for (var i = 0; i < lines.length; i++) { + var text = $('<div>').html(lines[i]).text(); + + // Remove newline characters (\n) to avoid them being converted by value2html() method + // thus adding extra <br> tags + text = text.replace(regex, ''); + + lines[i] = text; + } + return lines.join("\n"); + }, + */ + activate: function() { + $.fn.editabletypes.text.prototype.activate.call(this); + } + }); + + Textarea.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <textarea></textarea> + **/ + tpl:'<textarea></textarea>', + /** + @property inputclass + @default input-large + **/ + inputclass: 'input-large', + /** + Placeholder attribute of input. Shown when input is empty. + + @property placeholder + @type string + @default null + **/ + placeholder: null, + /** + Number of rows in textarea + + @property rows + @type integer + @default 7 + **/ + rows: 7 + }); + + $.fn.editabletypes.textarea = Textarea; + +}(window.jQuery)); + +/** +Select (dropdown) + +@class select +@extends list +@final +@example +<a href="#" id="status" data-type="select" data-pk="1" data-url="/post" data-title="Select status"></a> +<script> +$(function(){ + $('#status').editable({ + value: 2, + source: [ + {value: 1, text: 'Active'}, + {value: 2, text: 'Blocked'}, + {value: 3, text: 'Deleted'} + ] + }); +}); +</script> +**/ +(function ($) { + "use strict"; + + var Select = function (options) { + this.init('select', options, Select.defaults); + }; + + $.fn.editableutils.inherit(Select, $.fn.editabletypes.list); + + $.extend(Select.prototype, { + renderList: function() { + this.$input.empty(); + + var fillItems = function($el, data) { + var attr; + if($.isArray(data)) { + for(var i=0; i<data.length; i++) { + attr = {}; + if(data[i].children) { + attr.label = data[i].text; + $el.append(fillItems($('<optgroup>', attr), data[i].children)); + } else { + attr.value = data[i].value; + if(data[i].disabled) { + attr.disabled = true; + } + $el.append($('<option>', attr).text(data[i].text)); + } + } + } + return $el; + }; + + fillItems(this.$input, this.sourceData); + + this.setClass(); + + //enter submit + this.$input.on('keydown.editable', function (e) { + if (e.which === 13) { + $(this).closest('form').submit(); + } + }); + }, + + value2htmlFinal: function(value, element) { + var text = '', + items = $.fn.editableutils.itemsByValue(value, this.sourceData); + + if(items.length) { + text = items[0].text; + } + + //$(element).text(text); + $.fn.editabletypes.abstractinput.prototype.value2html.call(this, text, element); + }, + + autosubmit: function() { + this.$input.off('keydown.editable').on('change.editable', function(){ + $(this).closest('form').submit(); + }); + } + }); + + Select.defaults = $.extend({}, $.fn.editabletypes.list.defaults, { + /** + @property tpl + @default <select></select> + **/ + tpl:'<select></select>' + }); + + $.fn.editabletypes.select = Select; + +}(window.jQuery)); + +/** +List of checkboxes. +Internally value stored as javascript array of values. + +@class checklist +@extends list +@final +@example +<a href="#" id="options" data-type="checklist" data-pk="1" data-url="/post" data-title="Select options"></a> +<script> +$(function(){ + $('#options').editable({ + value: [2, 3], + source: [ + {value: 1, text: 'option1'}, + {value: 2, text: 'option2'}, + {value: 3, text: 'option3'} + ] + }); +}); +</script> +**/ +(function ($) { + "use strict"; + + var Checklist = function (options) { + this.init('checklist', options, Checklist.defaults); + }; + + $.fn.editableutils.inherit(Checklist, $.fn.editabletypes.list); + + $.extend(Checklist.prototype, { + renderList: function() { + var $label, $div; + + this.$tpl.empty(); + + if(!$.isArray(this.sourceData)) { + return; + } + + for(var i=0; i<this.sourceData.length; i++) { + $label = $('<label>').append($('<input>', { + type: 'checkbox', + value: this.sourceData[i].value + })) + .append($('<span>').text(' '+this.sourceData[i].text)); + + $('<div>').append($label).appendTo(this.$tpl); + } + + this.$input = this.$tpl.find('input[type="checkbox"]'); + this.setClass(); + }, + + value2str: function(value) { + return $.isArray(value) ? value.sort().join($.trim(this.options.separator)) : ''; + }, + + //parse separated string + str2value: function(str) { + var reg, value = null; + if(typeof str === 'string' && str.length) { + reg = new RegExp('\\s*'+$.trim(this.options.separator)+'\\s*'); + value = str.split(reg); + } else if($.isArray(str)) { + value = str; + } else { + value = [str]; + } + return value; + }, + + //set checked on required checkboxes + value2input: function(value) { + this.$input.prop('checked', false); + if($.isArray(value) && value.length) { + this.$input.each(function(i, el) { + var $el = $(el); + // cannot use $.inArray as it performs strict comparison + $.each(value, function(j, val){ + /*jslint eqeq: true*/ + if($el.val() == val) { + /*jslint eqeq: false*/ + $el.prop('checked', true); + } + }); + }); + } + }, + + input2value: function() { + var checked = []; + this.$input.filter(':checked').each(function(i, el) { + checked.push($(el).val()); + }); + return checked; + }, + + //collect text of checked boxes + value2htmlFinal: function(value, element) { + var html = [], + checked = $.fn.editableutils.itemsByValue(value, this.sourceData), + escape = this.options.escape; + + if(checked.length) { + $.each(checked, function(i, v) { + var text = escape ? $.fn.editableutils.escape(v.text) : v.text; + html.push(text); + }); + $(element).html(html.join('<br>')); + } else { + $(element).empty(); + } + }, + + activate: function() { + this.$input.first().focus(); + }, + + autosubmit: function() { + this.$input.on('keydown', function(e){ + if (e.which === 13) { + $(this).closest('form').submit(); + } + }); + } + }); + + Checklist.defaults = $.extend({}, $.fn.editabletypes.list.defaults, { + /** + @property tpl + @default <div></div> + **/ + tpl:'<div class="editable-checklist"></div>', + + /** + @property inputclass + @type string + @default null + **/ + inputclass: null, + + /** + Separator of values when reading from `data-value` attribute + + @property separator + @type string + @default ',' + **/ + separator: ',' + }); + + $.fn.editabletypes.checklist = Checklist; + +}(window.jQuery)); + +/** +HTML5 input types. +Following types are supported: + +* password +* email +* url +* tel +* number +* range +* time + +Learn more about html5 inputs: +http://www.w3.org/wiki/HTML5_form_additions +To check browser compatibility please see: +https://developer.mozilla.org/en-US/docs/HTML/Element/Input + +@class html5types +@extends text +@final +@since 1.3.0 +@example +<a href="#" id="email" data-type="email" data-pk="1">admin@example.com</a> +<script> +$(function(){ + $('#email').editable({ + url: '/post', + title: 'Enter email' + }); +}); +</script> +**/ + +/** +@property tpl +@default depends on type +**/ + +/* +Password +*/ +(function ($) { + "use strict"; + + var Password = function (options) { + this.init('password', options, Password.defaults); + }; + $.fn.editableutils.inherit(Password, $.fn.editabletypes.text); + $.extend(Password.prototype, { + //do not display password, show '[hidden]' instead + value2html: function(value, element) { + if(value) { + $(element).text('[hidden]'); + } else { + $(element).empty(); + } + }, + //as password not displayed, should not set value by html + html2value: function(html) { + return null; + } + }); + Password.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="password">' + }); + $.fn.editabletypes.password = Password; +}(window.jQuery)); + + +/* +Email +*/ +(function ($) { + "use strict"; + + var Email = function (options) { + this.init('email', options, Email.defaults); + }; + $.fn.editableutils.inherit(Email, $.fn.editabletypes.text); + Email.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="email">' + }); + $.fn.editabletypes.email = Email; +}(window.jQuery)); + + +/* +Url +*/ +(function ($) { + "use strict"; + + var Url = function (options) { + this.init('url', options, Url.defaults); + }; + $.fn.editableutils.inherit(Url, $.fn.editabletypes.text); + Url.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="url">' + }); + $.fn.editabletypes.url = Url; +}(window.jQuery)); + + +/* +Tel +*/ +(function ($) { + "use strict"; + + var Tel = function (options) { + this.init('tel', options, Tel.defaults); + }; + $.fn.editableutils.inherit(Tel, $.fn.editabletypes.text); + Tel.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="tel">' + }); + $.fn.editabletypes.tel = Tel; +}(window.jQuery)); + + +/* +Number +*/ +(function ($) { + "use strict"; + + var NumberInput = function (options) { + this.init('number', options, NumberInput.defaults); + }; + $.fn.editableutils.inherit(NumberInput, $.fn.editabletypes.text); + $.extend(NumberInput.prototype, { + render: function () { + NumberInput.superclass.render.call(this); + this.setAttr('min'); + this.setAttr('max'); + this.setAttr('step'); + }, + postrender: function() { + if(this.$clear) { + //increase right ffset for up/down arrows + this.$clear.css({right: 24}); + /* + //can position clear button only here, when form is shown and height can be calculated + var h = this.$input.outerHeight(true) || 20, + delta = (h - this.$clear.height()) / 2; + + //add 12px to offset right for up/down arrows + this.$clear.css({top: delta, right: delta + 16}); + */ + } + } + }); + NumberInput.defaults = $.extend({}, $.fn.editabletypes.text.defaults, { + tpl: '<input type="number">', + inputclass: 'input-mini', + min: null, + max: null, + step: null + }); + $.fn.editabletypes.number = NumberInput; +}(window.jQuery)); + + +/* +Range (inherit from number) +*/ +(function ($) { + "use strict"; + + var Range = function (options) { + this.init('range', options, Range.defaults); + }; + $.fn.editableutils.inherit(Range, $.fn.editabletypes.number); + $.extend(Range.prototype, { + render: function () { + this.$input = this.$tpl.filter('input'); + + this.setClass(); + this.setAttr('min'); + this.setAttr('max'); + this.setAttr('step'); + + this.$input.on('input', function(){ + $(this).siblings('output').text($(this).val()); + }); + }, + activate: function() { + this.$input.focus(); + } + }); + Range.defaults = $.extend({}, $.fn.editabletypes.number.defaults, { + tpl: '<input type="range"><output style="width: 30px; display: inline-block"></output>', + inputclass: 'input-medium' + }); + $.fn.editabletypes.range = Range; +}(window.jQuery)); + +/* +Time +*/ +(function ($) { + "use strict"; + + var Time = function (options) { + this.init('time', options, Time.defaults); + }; + //inherit from abstract, as inheritance from text gives selection error. + $.fn.editableutils.inherit(Time, $.fn.editabletypes.abstractinput); + $.extend(Time.prototype, { + render: function() { + this.setClass(); + } + }); + Time.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + tpl: '<input type="time">' + }); + $.fn.editabletypes.time = Time; +}(window.jQuery)); + +/** +Select2 input. Based on amazing work of Igor Vaynberg https://github.com/ivaynberg/select2. +Please see [original select2 docs](http://ivaynberg.github.com/select2) for detailed description and options. + +You should manually download and include select2 distributive: + + <link href="select2/select2.css" rel="stylesheet" type="text/css"></link> + <script src="select2/select2.js"></script> + +To make it **bootstrap-styled** you can use css from [here](https://github.com/t0m/select2-bootstrap-css): + + <link href="select2-bootstrap.css" rel="stylesheet" type="text/css"></link> + +**Note:** currently `autotext` feature does not work for select2 with `ajax` remote source. +You need initially put both `data-value` and element's text youself: + + <a href="#" data-type="select2" data-value="1">Text1</a> + + +@class select2 +@extends abstractinput +@since 1.4.1 +@final +@example +<a href="#" id="country" data-type="select2" data-pk="1" data-value="ru" data-url="/post" data-title="Select country"></a> +<script> +$(function(){ + //local source + $('#country').editable({ + source: [ + {id: 'gb', text: 'Great Britain'}, + {id: 'us', text: 'United States'}, + {id: 'ru', text: 'Russia'} + ], + select2: { + multiple: true + } + }); + //remote source (simple) + $('#country').editable({ + source: '/getCountries', + select2: { + placeholder: 'Select Country', + minimumInputLength: 1 + } + }); + //remote source (advanced) + $('#country').editable({ + select2: { + placeholder: 'Select Country', + allowClear: true, + minimumInputLength: 3, + id: function (item) { + return item.CountryId; + }, + ajax: { + url: '/getCountries', + dataType: 'json', + data: function (term, page) { + return { query: term }; + }, + results: function (data, page) { + return { results: data }; + } + }, + formatResult: function (item) { + return item.CountryName; + }, + formatSelection: function (item) { + return item.CountryName; + }, + initSelection: function (element, callback) { + return $.get('/getCountryById', { query: element.val() }, function (data) { + callback(data); + }); + } + } + }); +}); +</script> +**/ +(function ($) { + "use strict"; + + var Constructor = function (options) { + this.init('select2', options, Constructor.defaults); + + options.select2 = options.select2 || {}; + + this.sourceData = null; + + //placeholder + if(options.placeholder) { + options.select2.placeholder = options.placeholder; + } + + //if not `tags` mode, use source + if(!options.select2.tags && options.source) { + var source = options.source; + //if source is function, call it (once!) + if ($.isFunction(options.source)) { + source = options.source.call(options.scope); + } + + if (typeof source === 'string') { + options.select2.ajax = options.select2.ajax || {}; + //some default ajax params + if(!options.select2.ajax.data) { + options.select2.ajax.data = function(term) {return { query:term };}; + } + if(!options.select2.ajax.results) { + options.select2.ajax.results = function(data) { return {results:data };}; + } + options.select2.ajax.url = source; + } else { + //check format and convert x-editable format to select2 format (if needed) + this.sourceData = this.convertSource(source); + options.select2.data = this.sourceData; + } + } + + //overriding objects in config (as by default jQuery extend() is not recursive) + this.options.select2 = $.extend({}, Constructor.defaults.select2, options.select2); + + //detect whether it is multi-valued + this.isMultiple = this.options.select2.tags || this.options.select2.multiple; + this.isRemote = ('ajax' in this.options.select2); + + //store function returning ID of item + //should be here as used inautotext for local source + this.idFunc = this.options.select2.id; + if (typeof(this.idFunc) !== "function") { + var idKey = this.idFunc || 'id'; + this.idFunc = function (e) { return e[idKey]; }; + } + + //store function that renders text in select2 + this.formatSelection = this.options.select2.formatSelection; + if (typeof(this.formatSelection) !== "function") { + this.formatSelection = function (e) { return e.text; }; + } + }; + + $.fn.editableutils.inherit(Constructor, $.fn.editabletypes.abstractinput); + + $.extend(Constructor.prototype, { + render: function() { + this.setClass(); + + //can not apply select2 here as it calls initSelection + //over input that does not have correct value yet. + //apply select2 only in value2input + //this.$input.select2(this.options.select2); + + //when data is loaded via ajax, we need to know when it's done to populate listData + if(this.isRemote) { + //listen to loaded event to populate data + this.$input.on('select2-loaded', $.proxy(function(e) { + this.sourceData = e.items.results; + }, this)); + } + + //trigger resize of editableform to re-position container in multi-valued mode + if(this.isMultiple) { + this.$input.on('change', function() { + $(this).closest('form').parent().triggerHandler('resize'); + }); + } + }, + + value2html: function(value, element) { + var text = '', data, + that = this; + + if(this.options.select2.tags) { //in tags mode just assign value + data = value; + //data = $.fn.editableutils.itemsByValue(value, this.options.select2.tags, this.idFunc); + } else if(this.sourceData) { + data = $.fn.editableutils.itemsByValue(value, this.sourceData, this.idFunc); + } else { + //can not get list of possible values + //(e.g. autotext for select2 with ajax source) + } + + //data may be array (when multiple values allowed) + if($.isArray(data)) { + //collect selected data and show with separator + text = []; + $.each(data, function(k, v){ + text.push(v && typeof v === 'object' ? that.formatSelection(v) : v); + }); + } else if(data) { + text = that.formatSelection(data); + } + + text = $.isArray(text) ? text.join(this.options.viewseparator) : text; + + //$(element).text(text); + Constructor.superclass.value2html.call(this, text, element); + }, + + html2value: function(html) { + return this.options.select2.tags ? this.str2value(html, this.options.viewseparator) : null; + }, + + value2input: function(value) { + // if value array => join it anyway + if($.isArray(value)) { + value = value.join(this.getSeparator()); + } + + //for remote source just set value, text is updated by initSelection + if(!this.$input.data('select2')) { + this.$input.val(value); + this.$input.select2(this.options.select2); + } else { + //second argument needed to separate initial change from user's click (for autosubmit) + this.$input.val(value).trigger('change', true); + + //Uncaught Error: cannot call val() if initSelection() is not defined + //this.$input.select2('val', value); + } + + // if defined remote source AND no multiple mode AND no user's initSelection provided --> + // we should somehow get text for provided id. + // The solution is to use element's text as text for that id (exclude empty) + if(this.isRemote && !this.isMultiple && !this.options.select2.initSelection) { + // customId and customText are methods to extract `id` and `text` from data object + // we can use this workaround only if user did not define these methods + // otherwise we cant construct data object + var customId = this.options.select2.id, + customText = this.options.select2.formatSelection; + + if(!customId && !customText) { + var $el = $(this.options.scope); + if (!$el.data('editable').isEmpty) { + var data = {id: value, text: $el.text()}; + this.$input.select2('data', data); + } + } + } + }, + + input2value: function() { + return this.$input.select2('val'); + }, + + str2value: function(str, separator) { + if(typeof str !== 'string' || !this.isMultiple) { + return str; + } + + separator = separator || this.getSeparator(); + + var val, i, l; + + if (str === null || str.length < 1) { + return null; + } + val = str.split(separator); + for (i = 0, l = val.length; i < l; i = i + 1) { + val[i] = $.trim(val[i]); + } + + return val; + }, + + autosubmit: function() { + this.$input.on('change', function(e, isInitial){ + if(!isInitial) { + $(this).closest('form').submit(); + } + }); + }, + + getSeparator: function() { + return this.options.select2.separator || $.fn.select2.defaults.separator; + }, + + /* + Converts source from x-editable format: {value: 1, text: "1"} to + select2 format: {id: 1, text: "1"} + */ + convertSource: function(source) { + if($.isArray(source) && source.length && source[0].value !== undefined) { + for(var i = 0; i<source.length; i++) { + if(source[i].value !== undefined) { + source[i].id = source[i].value; + delete source[i].value; + } + } + } + return source; + }, + + destroy: function() { + if(this.$input.data('select2')) { + this.$input.select2('destroy'); + } + } + + }); + + Constructor.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <input type="hidden"> + **/ + tpl:'<input type="hidden">', + /** + Configuration of select2. [Full list of options](http://ivaynberg.github.com/select2). + + @property select2 + @type object + @default null + **/ + select2: null, + /** + Placeholder attribute of select + + @property placeholder + @type string + @default null + **/ + placeholder: null, + /** + Source data for select. It will be assigned to select2 `data` property and kept here just for convenience. + Please note, that format is different from simple `select` input: use 'id' instead of 'value'. + E.g. `[{id: 1, text: "text1"}, {id: 2, text: "text2"}, ...]`. + + @property source + @type array|string|function + @default null + **/ + source: null, + /** + Separator used to display tags. + + @property viewseparator + @type string + @default ', ' + **/ + viewseparator: ', ' + }); + + $.fn.editabletypes.select2 = Constructor; + +}(window.jQuery)); + +/** +* Combodate - 1.0.5 +* Dropdown date and time picker. +* Converts text input into dropdowns to pick day, month, year, hour, minute and second. +* Uses momentjs as datetime library http://momentjs.com. +* For i18n include corresponding file from https://github.com/timrwood/moment/tree/master/lang +* +* Confusion at noon and midnight - see http://en.wikipedia.org/wiki/12-hour_clock#Confusion_at_noon_and_midnight +* In combodate: +* 12:00 pm --> 12:00 (24-h format, midday) +* 12:00 am --> 00:00 (24-h format, midnight, start of day) +* +* Differs from momentjs parse rules: +* 00:00 pm, 12:00 pm --> 12:00 (24-h format, day not change) +* 00:00 am, 12:00 am --> 00:00 (24-h format, day not change) +* +* +* Author: Vitaliy Potapov +* Project page: http://github.com/vitalets/combodate +* Copyright (c) 2012 Vitaliy Potapov. Released under MIT License. +**/ +(function ($) { + + var Combodate = function (element, options) { + this.$element = $(element); + if(!this.$element.is('input')) { + $.error('Combodate should be applied to INPUT element'); + return; + } + this.options = $.extend({}, $.fn.combodate.defaults, options, this.$element.data()); + this.init(); + }; + + Combodate.prototype = { + constructor: Combodate, + init: function () { + this.map = { + //key regexp moment.method + day: ['D', 'date'], + month: ['M', 'month'], + year: ['Y', 'year'], + hour: ['[Hh]', 'hours'], + minute: ['m', 'minutes'], + second: ['s', 'seconds'], + ampm: ['[Aa]', ''] + }; + + this.$widget = $('<span class="combodate"></span>').html(this.getTemplate()); + + this.initCombos(); + + //update original input on change + this.$widget.on('change', 'select', $.proxy(function(e) { + this.$element.val(this.getValue()).change(); + // update days count if month or year changes + if (this.options.smartDays) { + if ($(e.target).is('.month') || $(e.target).is('.year')) { + this.fillCombo('day'); + } + } + }, this)); + + this.$widget.find('select').css('width', 'auto'); + + // hide original input and insert widget + this.$element.hide().after(this.$widget); + + // set initial value + this.setValue(this.$element.val() || this.options.value); + }, + + /* + Replace tokens in template with <select> elements + */ + getTemplate: function() { + var tpl = this.options.template; + + //first pass + $.each(this.map, function(k, v) { + v = v[0]; + var r = new RegExp(v+'+'), + token = v.length > 1 ? v.substring(1, 2) : v; + + tpl = tpl.replace(r, '{'+token+'}'); + }); + + //replace spaces with &nbsp; + tpl = tpl.replace(/ /g, '&nbsp;'); + + //second pass + $.each(this.map, function(k, v) { + v = v[0]; + var token = v.length > 1 ? v.substring(1, 2) : v; + + tpl = tpl.replace('{'+token+'}', '<select class="'+k+'"></select>'); + }); + + return tpl; + }, + + /* + Initialize combos that presents in template + */ + initCombos: function() { + for (var k in this.map) { + var $c = this.$widget.find('.'+k); + // set properties like this.$day, this.$month etc. + this['$'+k] = $c.length ? $c : null; + // fill with items + this.fillCombo(k); + } + }, + + /* + Fill combo with items + */ + fillCombo: function(k) { + var $combo = this['$'+k]; + if (!$combo) { + return; + } + + // define method name to fill items, e.g `fillDays` + var f = 'fill' + k.charAt(0).toUpperCase() + k.slice(1); + var items = this[f](); + var value = $combo.val(); + + $combo.empty(); + for(var i=0; i<items.length; i++) { + $combo.append('<option value="'+items[i][0]+'">'+items[i][1]+'</option>'); + } + + $combo.val(value); + }, + + /* + Initialize items of combos. Handles `firstItem` option + */ + fillCommon: function(key) { + var values = [], + relTime; + + if(this.options.firstItem === 'name') { + //need both to support moment ver < 2 and >= 2 + relTime = moment.relativeTime || moment.langData()._relativeTime; + var header = typeof relTime[key] === 'function' ? relTime[key](1, true, key, false) : relTime[key]; + //take last entry (see momentjs lang files structure) + header = header.split(' ').reverse()[0]; + values.push(['', header]); + } else if(this.options.firstItem === 'empty') { + values.push(['', '']); + } + return values; + }, + + + /* + fill day + */ + fillDay: function() { + var items = this.fillCommon('d'), name, i, + twoDigit = this.options.template.indexOf('DD') !== -1, + daysCount = 31; + + // detect days count (depends on month and year) + // originally https://github.com/vitalets/combodate/pull/7 + if (this.options.smartDays && this.$month && this.$year) { + var month = parseInt(this.$month.val(), 10); + var year = parseInt(this.$year.val(), 10); + + if (!isNaN(month) && !isNaN(year)) { + daysCount = moment([year, month]).daysInMonth(); + } + } + + for (i = 1; i <= daysCount; i++) { + name = twoDigit ? this.leadZero(i) : i; + items.push([i, name]); + } + return items; + }, + + /* + fill month + */ + fillMonth: function() { + var items = this.fillCommon('M'), name, i, + longNames = this.options.template.indexOf('MMMM') !== -1, + shortNames = this.options.template.indexOf('MMM') !== -1, + twoDigit = this.options.template.indexOf('MM') !== -1; + + for(i=0; i<=11; i++) { + if(longNames) { + //see https://github.com/timrwood/momentjs.com/pull/36 + name = moment().date(1).month(i).format('MMMM'); + } else if(shortNames) { + name = moment().date(1).month(i).format('MMM'); + } else if(twoDigit) { + name = this.leadZero(i+1); + } else { + name = i+1; + } + items.push([i, name]); + } + return items; + }, + + /* + fill year + */ + fillYear: function() { + var items = [], name, i, + longNames = this.options.template.indexOf('YYYY') !== -1; + + for(i=this.options.maxYear; i>=this.options.minYear; i--) { + name = longNames ? i : (i+'').substring(2); + items[this.options.yearDescending ? 'push' : 'unshift']([i, name]); + } + + items = this.fillCommon('y').concat(items); + + return items; + }, + + /* + fill hour + */ + fillHour: function() { + var items = this.fillCommon('h'), name, i, + h12 = this.options.template.indexOf('h') !== -1, + h24 = this.options.template.indexOf('H') !== -1, + twoDigit = this.options.template.toLowerCase().indexOf('hh') !== -1, + min = h12 ? 1 : 0, + max = h12 ? 12 : 23; + + for(i=min; i<=max; i++) { + name = twoDigit ? this.leadZero(i) : i; + items.push([i, name]); + } + return items; + }, + + /* + fill minute + */ + fillMinute: function() { + var items = this.fillCommon('m'), name, i, + twoDigit = this.options.template.indexOf('mm') !== -1; + + for(i=0; i<=59; i+= this.options.minuteStep) { + name = twoDigit ? this.leadZero(i) : i; + items.push([i, name]); + } + return items; + }, + + /* + fill second + */ + fillSecond: function() { + var items = this.fillCommon('s'), name, i, + twoDigit = this.options.template.indexOf('ss') !== -1; + + for(i=0; i<=59; i+= this.options.secondStep) { + name = twoDigit ? this.leadZero(i) : i; + items.push([i, name]); + } + return items; + }, + + /* + fill ampm + */ + fillAmpm: function() { + var ampmL = this.options.template.indexOf('a') !== -1, + ampmU = this.options.template.indexOf('A') !== -1, + items = [ + ['am', ampmL ? 'am' : 'AM'], + ['pm', ampmL ? 'pm' : 'PM'] + ]; + return items; + }, + + /* + Returns current date value from combos. + If format not specified - `options.format` used. + If format = `null` - Moment object returned. + */ + getValue: function(format) { + var dt, values = {}, + that = this, + notSelected = false; + + //getting selected values + $.each(this.map, function(k, v) { + if(k === 'ampm') { + return; + } + var def = k === 'day' ? 1 : 0; + + values[k] = that['$'+k] ? parseInt(that['$'+k].val(), 10) : def; + + if(isNaN(values[k])) { + notSelected = true; + return false; + } + }); + + //if at least one visible combo not selected - return empty string + if(notSelected) { + return ''; + } + + //convert hours 12h --> 24h + if(this.$ampm) { + //12:00 pm --> 12:00 (24-h format, midday), 12:00 am --> 00:00 (24-h format, midnight, start of day) + if(values.hour === 12) { + values.hour = this.$ampm.val() === 'am' ? 0 : 12; + } else { + values.hour = this.$ampm.val() === 'am' ? values.hour : values.hour+12; + } + } + + dt = moment([values.year, values.month, values.day, values.hour, values.minute, values.second]); + + //highlight invalid date + this.highlight(dt); + + format = format === undefined ? this.options.format : format; + if(format === null) { + return dt.isValid() ? dt : null; + } else { + return dt.isValid() ? dt.format(format) : ''; + } + }, + + setValue: function(value) { + if(!value) { + return; + } + + var dt = typeof value === 'string' ? moment(value, this.options.format) : moment(value), + that = this, + values = {}; + + //function to find nearest value in select options + function getNearest($select, value) { + var delta = {}; + $select.children('option').each(function(i, opt){ + var optValue = $(opt).attr('value'), + distance; + + if(optValue === '') return; + distance = Math.abs(optValue - value); + if(typeof delta.distance === 'undefined' || distance < delta.distance) { + delta = {value: optValue, distance: distance}; + } + }); + return delta.value; + } + + if(dt.isValid()) { + //read values from date object + $.each(this.map, function(k, v) { + if(k === 'ampm') { + return; + } + values[k] = dt[v[1]](); + }); + + if(this.$ampm) { + //12:00 pm --> 12:00 (24-h format, midday), 12:00 am --> 00:00 (24-h format, midnight, start of day) + if(values.hour >= 12) { + values.ampm = 'pm'; + if(values.hour > 12) { + values.hour -= 12; + } + } else { + values.ampm = 'am'; + if(values.hour === 0) { + values.hour = 12; + } + } + } + + $.each(values, function(k, v) { + //call val() for each existing combo, e.g. this.$hour.val() + if(that['$'+k]) { + + if(k === 'minute' && that.options.minuteStep > 1 && that.options.roundTime) { + v = getNearest(that['$'+k], v); + } + + if(k === 'second' && that.options.secondStep > 1 && that.options.roundTime) { + v = getNearest(that['$'+k], v); + } + + that['$'+k].val(v); + } + }); + + // update days count + if (this.options.smartDays) { + this.fillCombo('day'); + } + + this.$element.val(dt.format(this.options.format)).change(); + } + }, + + /* + highlight combos if date is invalid + */ + highlight: function(dt) { + if(!dt.isValid()) { + if(this.options.errorClass) { + this.$widget.addClass(this.options.errorClass); + } else { + //store original border color + if(!this.borderColor) { + this.borderColor = this.$widget.find('select').css('border-color'); + } + this.$widget.find('select').css('border-color', 'red'); + } + } else { + if(this.options.errorClass) { + this.$widget.removeClass(this.options.errorClass); + } else { + this.$widget.find('select').css('border-color', this.borderColor); + } + } + }, + + leadZero: function(v) { + return v <= 9 ? '0' + v : v; + }, + + destroy: function() { + this.$widget.remove(); + this.$element.removeData('combodate').show(); + } + + //todo: clear method + }; + + $.fn.combodate = function ( option ) { + var d, args = Array.apply(null, arguments); + args.shift(); + + //getValue returns date as string / object (not jQuery object) + if(option === 'getValue' && this.length && (d = this.eq(0).data('combodate'))) { + return d.getValue.apply(d, args); + } + + return this.each(function () { + var $this = $(this), + data = $this.data('combodate'), + options = typeof option == 'object' && option; + if (!data) { + $this.data('combodate', (data = new Combodate(this, options))); + } + if (typeof option == 'string' && typeof data[option] == 'function') { + data[option].apply(data, args); + } + }); + }; + + $.fn.combodate.defaults = { + //in this format value stored in original input + format: 'DD-MM-YYYY HH:mm', + //in this format items in dropdowns are displayed + template: 'D / MMM / YYYY H : mm', + //initial value, can be `new Date()` + value: null, + minYear: 1970, + maxYear: 2015, + yearDescending: true, + minuteStep: 5, + secondStep: 1, + firstItem: 'empty', //'name', 'empty', 'none' + errorClass: null, + roundTime: true, // whether to round minutes and seconds if step > 1 + smartDays: false // whether days in combo depend on selected month: 31, 30, 28 + }; + +}(window.jQuery)); +/** +Combodate input - dropdown date and time picker. +Based on [combodate](http://vitalets.github.com/combodate) plugin (included). To use it you should manually include [momentjs](http://momentjs.com). + + <script src="js/moment.min.js"></script> + +Allows to input: + +* only date +* only time +* both date and time + +Please note, that format is taken from momentjs and **not compatible** with bootstrap-datepicker / jquery UI datepicker. +Internally value stored as `momentjs` object. + +@class combodate +@extends abstractinput +@final +@since 1.4.0 +@example +<a href="#" id="dob" data-type="combodate" data-pk="1" data-url="/post" data-value="1984-05-15" data-title="Select date"></a> +<script> +$(function(){ + $('#dob').editable({ + format: 'YYYY-MM-DD', + viewformat: 'DD.MM.YYYY', + template: 'D / MMMM / YYYY', + combodate: { + minYear: 2000, + maxYear: 2015, + minuteStep: 1 + } + } + }); +}); +</script> +**/ + +/*global moment*/ + +(function ($) { + "use strict"; + + var Constructor = function (options) { + this.init('combodate', options, Constructor.defaults); + + //by default viewformat equals to format + if(!this.options.viewformat) { + this.options.viewformat = this.options.format; + } + + //try parse combodate config defined as json string in data-combodate + options.combodate = $.fn.editableutils.tryParseJson(options.combodate, true); + + //overriding combodate config (as by default jQuery extend() is not recursive) + this.options.combodate = $.extend({}, Constructor.defaults.combodate, options.combodate, { + format: this.options.format, + template: this.options.template + }); + }; + + $.fn.editableutils.inherit(Constructor, $.fn.editabletypes.abstractinput); + + $.extend(Constructor.prototype, { + render: function () { + this.$input.combodate(this.options.combodate); + + if($.fn.editableform.engine === 'bs3') { + this.$input.siblings().find('select').addClass('form-control'); + } + + if(this.options.inputclass) { + this.$input.siblings().find('select').addClass(this.options.inputclass); + } + //"clear" link + /* + if(this.options.clear) { + this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){ + e.preventDefault(); + e.stopPropagation(); + this.clear(); + }, this)); + + this.$tpl.parent().append($('<div class="editable-clear">').append(this.$clear)); + } + */ + }, + + value2html: function(value, element) { + var text = value ? value.format(this.options.viewformat) : ''; + //$(element).text(text); + Constructor.superclass.value2html.call(this, text, element); + }, + + html2value: function(html) { + return html ? moment(html, this.options.viewformat) : null; + }, + + value2str: function(value) { + return value ? value.format(this.options.format) : ''; + }, + + str2value: function(str) { + return str ? moment(str, this.options.format) : null; + }, + + value2submit: function(value) { + return this.value2str(value); + }, + + value2input: function(value) { + this.$input.combodate('setValue', value); + }, + + input2value: function() { + return this.$input.combodate('getValue', null); + }, + + activate: function() { + this.$input.siblings('.combodate').find('select').eq(0).focus(); + }, + + /* + clear: function() { + this.$input.data('datepicker').date = null; + this.$input.find('.active').removeClass('active'); + }, + */ + + autosubmit: function() { + + } + + }); + + Constructor.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <input type="text"> + **/ + tpl:'<input type="text">', + /** + @property inputclass + @default null + **/ + inputclass: null, + /** + Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br> + See list of tokens in [momentjs docs](http://momentjs.com/docs/#/parsing/string-format) + + @property format + @type string + @default YYYY-MM-DD + **/ + format:'YYYY-MM-DD', + /** + Format used for displaying date. Also applied when converting date from element's text on init. + If not specified equals to `format`. + + @property viewformat + @type string + @default null + **/ + viewformat: null, + /** + Template used for displaying dropdowns. + + @property template + @type string + @default D / MMM / YYYY + **/ + template: 'D / MMM / YYYY', + /** + Configuration of combodate. + Full list of options: http://vitalets.github.com/combodate/#docs + + @property combodate + @type object + @default null + **/ + combodate: null + + /* + (not implemented yet) + Text shown as clear date button. + If <code>false</code> clear button will not be rendered. + + @property clear + @type boolean|string + @default 'x clear' + */ + //clear: '&times; clear' + }); + + $.fn.editabletypes.combodate = Constructor; + +}(window.jQuery)); + +/* +Editableform based on Twitter Bootstrap 2 +*/ +(function ($) { + "use strict"; + + //store parent methods + var pInitInput = $.fn.editableform.Constructor.prototype.initInput; + + $.extend($.fn.editableform.Constructor.prototype, { + initTemplate: function() { + this.$form = $($.fn.editableform.template); + this.$form.find('.editable-error-block').addClass('help-block'); + }, + initInput: function() { + pInitInput.apply(this); + + //for bs2 set default class `input-medium` to standard inputs + var emptyInputClass = this.input.options.inputclass === null || this.input.options.inputclass === false; + var defaultClass = 'input-medium'; + + //add bs2 default class to standard inputs + //if(this.input.$input.is('input,select,textarea')) { + var stdtypes = 'text,select,textarea,password,email,url,tel,number,range,time'.split(','); + if(~$.inArray(this.input.type, stdtypes) && emptyInputClass) { + this.input.options.inputclass = defaultClass; + this.input.$input.addClass(defaultClass); + } + } + }); + + //buttons + $.fn.editableform.buttons = '<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button>'+ + '<button type="button" class="btn editable-cancel"><i class="icon-remove"></i></button>'; + + //error classes + $.fn.editableform.errorGroupClass = 'error'; + $.fn.editableform.errorBlockClass = null; + //engine + $.fn.editableform.engine = 'bs2'; + +}(window.jQuery)); +/** +* Editable Popover +* --------------------- +* requires bootstrap-popover.js +*/ +(function ($) { + "use strict"; + + //extend methods + $.extend($.fn.editableContainer.Popup.prototype, { + containerName: 'popover', + //for compatibility with bootstrap <= 2.2.1 (content inserted into <p> instead of directly .popover-content) + innerCss: $.fn.popover && $($.fn.popover.defaults.template).find('p').length ? '.popover-content p' : '.popover-content', + defaults: $.fn.popover.defaults, + + initContainer: function(){ + $.extend(this.containerOptions, { + trigger: 'manual', + selector: false, + content: ' ', + template: this.defaults.template + }); + + //as template property is used in inputs, hide it from popover + var t; + if(this.$element.data('template')) { + t = this.$element.data('template'); + this.$element.removeData('template'); + } + + this.call(this.containerOptions); + + if(t) { + //restore data('template') + this.$element.data('template', t); + } + }, + + /* show */ + innerShow: function () { + this.call('show'); + }, + + /* hide */ + innerHide: function () { + this.call('hide'); + }, + + /* destroy */ + innerDestroy: function() { + this.call('destroy'); + }, + + setContainerOption: function(key, value) { + this.container().options[key] = value; + }, + + /** + * move popover to new position. This function mainly copied from bootstrap-popover. + */ + /*jshint laxcomma: true*/ + setPosition: function () { + + (function() { + var $tip = this.tip() + , inside + , pos + , actualWidth + , actualHeight + , placement + , tp + , tpt + , tpb + , tpl + , tpr; + + placement = typeof this.options.placement === 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement; + + inside = /in/.test(placement); + + $tip + // .detach() + //vitalets: remove any placement class because otherwise they dont influence on re-positioning of visible popover + .removeClass('top right bottom left') + .css({ top: 0, left: 0, display: 'block' }); + // .insertAfter(this.$element); + + pos = this.getPosition(inside); + + actualWidth = $tip[0].offsetWidth; + actualHeight = $tip[0].offsetHeight; + + placement = inside ? placement.split(' ')[1] : placement; + + tpb = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}; + tpt = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}; + tpl = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}; + tpr = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}; + + switch (placement) { + case 'bottom': + if ((tpb.top + actualHeight) > ($(window).scrollTop() + $(window).height())) { + if (tpt.top > $(window).scrollTop()) { + placement = 'top'; + } else if ((tpr.left + actualWidth) < ($(window).scrollLeft() + $(window).width())) { + placement = 'right'; + } else if (tpl.left > $(window).scrollLeft()) { + placement = 'left'; + } else { + placement = 'right'; + } + } + break; + case 'top': + if (tpt.top < $(window).scrollTop()) { + if ((tpb.top + actualHeight) < ($(window).scrollTop() + $(window).height())) { + placement = 'bottom'; + } else if ((tpr.left + actualWidth) < ($(window).scrollLeft() + $(window).width())) { + placement = 'right'; + } else if (tpl.left > $(window).scrollLeft()) { + placement = 'left'; + } else { + placement = 'right'; + } + } + break; + case 'left': + if (tpl.left < $(window).scrollLeft()) { + if ((tpr.left + actualWidth) < ($(window).scrollLeft() + $(window).width())) { + placement = 'right'; + } else if (tpt.top > $(window).scrollTop()) { + placement = 'top'; + } else if (tpt.top > $(window).scrollTop()) { + placement = 'bottom'; + } else { + placement = 'right'; + } + } + break; + case 'right': + if ((tpr.left + actualWidth) > ($(window).scrollLeft() + $(window).width())) { + if (tpl.left > $(window).scrollLeft()) { + placement = 'left'; + } else if (tpt.top > $(window).scrollTop()) { + placement = 'top'; + } else if (tpt.top > $(window).scrollTop()) { + placement = 'bottom'; + } + } + break; + } + + switch (placement) { + case 'bottom': + tp = tpb; + break; + case 'top': + tp = tpt; + break; + case 'left': + tp = tpl; + break; + case 'right': + tp = tpr; + break; + } + + $tip + .offset(tp) + .addClass(placement) + .addClass('in'); + + }).call(this.container()); + /*jshint laxcomma: false*/ + } + }); + +}(window.jQuery)); + +/* ========================================================= + * bootstrap-datepicker.js + * http://www.eyecon.ro/bootstrap-datepicker + * ========================================================= + * Copyright 2012 Stefan Petre + * Improvements by Andrew Rowls + * + * 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( $ ) { + + function UTCDate(){ + return new Date(Date.UTC.apply(Date, arguments)); + } + function UTCToday(){ + var today = new Date(); + return UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate()); + } + + // Picker object + + var Datepicker = function(element, options) { + var that = this; + + this._process_options(options); + + this.element = $(element); + this.isInline = false; + this.isInput = this.element.is('input'); + this.component = this.element.is('.date') ? this.element.find('.add-on, .btn') : false; + this.hasInput = this.component && this.element.find('input').length; + if(this.component && this.component.length === 0) + this.component = false; + + this.picker = $(DPGlobal.template); + this._buildEvents(); + this._attachEvents(); + + if(this.isInline) { + this.picker.addClass('datepicker-inline').appendTo(this.element); + } else { + this.picker.addClass('datepicker-dropdown dropdown-menu'); + } + + if (this.o.rtl){ + this.picker.addClass('datepicker-rtl'); + this.picker.find('.prev i, .next i') + .toggleClass('icon-arrow-left icon-arrow-right'); + } + + + this.viewMode = this.o.startView; + + if (this.o.calendarWeeks) + this.picker.find('tfoot th.today') + .attr('colspan', function(i, val){ + return parseInt(val) + 1; + }); + + this._allow_update = false; + + this.setStartDate(this.o.startDate); + this.setEndDate(this.o.endDate); + this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled); + + this.fillDow(); + this.fillMonths(); + + this._allow_update = true; + + this.update(); + this.showMode(); + + if(this.isInline) { + this.show(); + } + }; + + Datepicker.prototype = { + constructor: Datepicker, + + _process_options: function(opts){ + // Store raw options for reference + this._o = $.extend({}, this._o, opts); + // Processed options + var o = this.o = $.extend({}, this._o); + + // Check if "de-DE" style date is available, if not language should + // fallback to 2 letter code eg "de" + var lang = o.language; + if (!dates[lang]) { + lang = lang.split('-')[0]; + if (!dates[lang]) + lang = defaults.language; + } + o.language = lang; + + switch(o.startView){ + case 2: + case 'decade': + o.startView = 2; + break; + case 1: + case 'year': + o.startView = 1; + break; + default: + o.startView = 0; + } + + switch (o.minViewMode) { + case 1: + case 'months': + o.minViewMode = 1; + break; + case 2: + case 'years': + o.minViewMode = 2; + break; + default: + o.minViewMode = 0; + } + + o.startView = Math.max(o.startView, o.minViewMode); + + o.weekStart %= 7; + o.weekEnd = ((o.weekStart + 6) % 7); + + var format = DPGlobal.parseFormat(o.format) + if (o.startDate !== -Infinity) { + o.startDate = DPGlobal.parseDate(o.startDate, format, o.language); + } + if (o.endDate !== Infinity) { + o.endDate = DPGlobal.parseDate(o.endDate, format, o.language); + } + + o.daysOfWeekDisabled = o.daysOfWeekDisabled||[]; + if (!$.isArray(o.daysOfWeekDisabled)) + o.daysOfWeekDisabled = o.daysOfWeekDisabled.split(/[,\s]*/); + o.daysOfWeekDisabled = $.map(o.daysOfWeekDisabled, function (d) { + return parseInt(d, 10); + }); + }, + _events: [], + _secondaryEvents: [], + _applyEvents: function(evs){ + for (var i=0, el, ev; i<evs.length; i++){ + el = evs[i][0]; + ev = evs[i][1]; + el.on(ev); + } + }, + _unapplyEvents: function(evs){ + for (var i=0, el, ev; i<evs.length; i++){ + el = evs[i][0]; + ev = evs[i][1]; + el.off(ev); + } + }, + _buildEvents: function(){ + if (this.isInput) { // single input + this._events = [ + [this.element, { + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }] + ]; + } + else if (this.component && this.hasInput){ // component: input + button + this._events = [ + // For components that are not readonly, allow keyboard nav + [this.element.find('input'), { + focus: $.proxy(this.show, this), + keyup: $.proxy(this.update, this), + keydown: $.proxy(this.keydown, this) + }], + [this.component, { + click: $.proxy(this.show, this) + }] + ]; + } + else if (this.element.is('div')) { // inline datepicker + this.isInline = true; + } + else { + this._events = [ + [this.element, { + click: $.proxy(this.show, this) + }] + ]; + } + + this._secondaryEvents = [ + [this.picker, { + click: $.proxy(this.click, this) + }], + [$(window), { + resize: $.proxy(this.place, this) + }], + [$(document), { + mousedown: $.proxy(function (e) { + // Clicked outside the datepicker, hide it + if (!( + this.element.is(e.target) || + this.element.find(e.target).size() || + this.picker.is(e.target) || + this.picker.find(e.target).size() + )) { + this.hide(); + } + }, this) + }] + ]; + }, + _attachEvents: function(){ + this._detachEvents(); + this._applyEvents(this._events); + }, + _detachEvents: function(){ + this._unapplyEvents(this._events); + }, + _attachSecondaryEvents: function(){ + this._detachSecondaryEvents(); + this._applyEvents(this._secondaryEvents); + }, + _detachSecondaryEvents: function(){ + this._unapplyEvents(this._secondaryEvents); + }, + _trigger: function(event, altdate){ + var date = altdate || this.date, + local_date = new Date(date.getTime() + (date.getTimezoneOffset()*60000)); + + this.element.trigger({ + type: event, + date: local_date, + format: $.proxy(function(altformat){ + var format = altformat || this.o.format; + return DPGlobal.formatDate(date, format, this.o.language); + }, this) + }); + }, + + show: function(e) { + if (!this.isInline) + this.picker.appendTo('body'); + this.picker.show(); + this.height = this.component ? this.component.outerHeight() : this.element.outerHeight(); + this.place(); + this._attachSecondaryEvents(); + if (e) { + e.preventDefault(); + } + this._trigger('show'); + }, + + hide: function(e){ + if(this.isInline) return; + if (!this.picker.is(':visible')) return; + this.picker.hide().detach(); + this._detachSecondaryEvents(); + this.viewMode = this.o.startView; + this.showMode(); + + if ( + this.o.forceParse && + ( + this.isInput && this.element.val() || + this.hasInput && this.element.find('input').val() + ) + ) + this.setValue(); + this._trigger('hide'); + }, + + remove: function() { + this.hide(); + this._detachEvents(); + this._detachSecondaryEvents(); + this.picker.remove(); + delete this.element.data().datepicker; + if (!this.isInput) { + delete this.element.data().date; + } + }, + + getDate: function() { + var d = this.getUTCDate(); + return new Date(d.getTime() + (d.getTimezoneOffset()*60000)); + }, + + getUTCDate: function() { + return this.date; + }, + + setDate: function(d) { + this.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset()*60000))); + }, + + setUTCDate: function(d) { + this.date = d; + this.setValue(); + }, + + setValue: function() { + var formatted = this.getFormattedDate(); + if (!this.isInput) { + if (this.component){ + this.element.find('input').val(formatted); + } + } else { + this.element.val(formatted); + } + }, + + getFormattedDate: function(format) { + if (format === undefined) + format = this.o.format; + return DPGlobal.formatDate(this.date, format, this.o.language); + }, + + setStartDate: function(startDate){ + this._process_options({startDate: startDate}); + this.update(); + this.updateNavArrows(); + }, + + setEndDate: function(endDate){ + this._process_options({endDate: endDate}); + this.update(); + this.updateNavArrows(); + }, + + setDaysOfWeekDisabled: function(daysOfWeekDisabled){ + this._process_options({daysOfWeekDisabled: daysOfWeekDisabled}); + this.update(); + this.updateNavArrows(); + }, + + place: function(){ + if(this.isInline) return; + var zIndex = parseInt(this.element.parents().filter(function() { + return $(this).css('z-index') != 'auto'; + }).first().css('z-index'))+10; + var offset = this.component ? this.component.parent().offset() : this.element.offset(); + var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(true); + this.picker.css({ + top: offset.top + height, + left: offset.left, + zIndex: zIndex + }); + }, + + _allow_update: true, + update: function(){ + if (!this._allow_update) return; + + var date, fromArgs = false; + if(arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) { + date = arguments[0]; + fromArgs = true; + } else { + date = this.isInput ? this.element.val() : this.element.data('date') || this.element.find('input').val(); + delete this.element.data().date; + } + + this.date = DPGlobal.parseDate(date, this.o.format, this.o.language); + + if(fromArgs) this.setValue(); + + if (this.date < this.o.startDate) { + this.viewDate = new Date(this.o.startDate); + } else if (this.date > this.o.endDate) { + this.viewDate = new Date(this.o.endDate); + } else { + this.viewDate = new Date(this.date); + } + this.fill(); + }, + + fillDow: function(){ + var dowCnt = this.o.weekStart, + html = '<tr>'; + if(this.o.calendarWeeks){ + var cell = '<th class="cw">&nbsp;</th>'; + html += cell; + this.picker.find('.datepicker-days thead tr:first-child').prepend(cell); + } + while (dowCnt < this.o.weekStart + 7) { + html += '<th class="dow">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>'; + } + html += '</tr>'; + this.picker.find('.datepicker-days thead').append(html); + }, + + fillMonths: function(){ + var html = '', + i = 0; + while (i < 12) { + html += '<span class="month">'+dates[this.o.language].monthsShort[i++]+'</span>'; + } + this.picker.find('.datepicker-months td').html(html); + }, + + setRange: function(range){ + if (!range || !range.length) + delete this.range; + else + this.range = $.map(range, function(d){ return d.valueOf(); }); + this.fill(); + }, + + getClassNames: function(date){ + var cls = [], + year = this.viewDate.getUTCFullYear(), + month = this.viewDate.getUTCMonth(), + currentDate = this.date.valueOf(), + today = new Date(); + if (date.getUTCFullYear() < year || (date.getUTCFullYear() == year && date.getUTCMonth() < month)) { + cls.push('old'); + } else if (date.getUTCFullYear() > year || (date.getUTCFullYear() == year && date.getUTCMonth() > month)) { + cls.push('new'); + } + // Compare internal UTC date with local today, not UTC today + if (this.o.todayHighlight && + date.getUTCFullYear() == today.getFullYear() && + date.getUTCMonth() == today.getMonth() && + date.getUTCDate() == today.getDate()) { + cls.push('today'); + } + if (currentDate && date.valueOf() == currentDate) { + cls.push('active'); + } + if (date.valueOf() < this.o.startDate || date.valueOf() > this.o.endDate || + $.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1) { + cls.push('disabled'); + } + if (this.range){ + if (date > this.range[0] && date < this.range[this.range.length-1]){ + cls.push('range'); + } + if ($.inArray(date.valueOf(), this.range) != -1){ + cls.push('selected'); + } + } + return cls; + }, + + fill: function() { + var d = new Date(this.viewDate), + year = d.getUTCFullYear(), + month = d.getUTCMonth(), + startYear = this.o.startDate !== -Infinity ? this.o.startDate.getUTCFullYear() : -Infinity, + startMonth = this.o.startDate !== -Infinity ? this.o.startDate.getUTCMonth() : -Infinity, + endYear = this.o.endDate !== Infinity ? this.o.endDate.getUTCFullYear() : Infinity, + endMonth = this.o.endDate !== Infinity ? this.o.endDate.getUTCMonth() : Infinity, + currentDate = this.date && this.date.valueOf(), + tooltip; + this.picker.find('.datepicker-days thead th.datepicker-switch') + .text(dates[this.o.language].months[month]+' '+year); + this.picker.find('tfoot th.today') + .text(dates[this.o.language].today) + .toggle(this.o.todayBtn !== false); + this.picker.find('tfoot th.clear') + .text(dates[this.o.language].clear) + .toggle(this.o.clearBtn !== false); + this.updateNavArrows(); + this.fillMonths(); + var prevMonth = UTCDate(year, month-1, 28,0,0,0,0), + day = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth()); + prevMonth.setUTCDate(day); + prevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.o.weekStart + 7)%7); + var nextMonth = new Date(prevMonth); + nextMonth.setUTCDate(nextMonth.getUTCDate() + 42); + nextMonth = nextMonth.valueOf(); + var html = []; + var clsName; + while(prevMonth.valueOf() < nextMonth) { + if (prevMonth.getUTCDay() == this.o.weekStart) { + html.push('<tr>'); + if(this.o.calendarWeeks){ + // ISO 8601: First week contains first thursday. + // ISO also states week starts on Monday, but we can be more abstract here. + var + // Start of current week: based on weekstart/current date + ws = new Date(+prevMonth + (this.o.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5), + // Thursday of this week + th = new Date(+ws + (7 + 4 - ws.getUTCDay()) % 7 * 864e5), + // First Thursday of year, year from thursday + yth = new Date(+(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5), + // Calendar week: ms between thursdays, div ms per day, div 7 days + calWeek = (th - yth) / 864e5 / 7 + 1; + html.push('<td class="cw">'+ calWeek +'</td>'); + + } + } + clsName = this.getClassNames(prevMonth); + clsName.push('day'); + + var before = this.o.beforeShowDay(prevMonth); + if (before === undefined) + before = {}; + else if (typeof(before) === 'boolean') + before = {enabled: before}; + else if (typeof(before) === 'string') + before = {classes: before}; + if (before.enabled === false) + clsName.push('disabled'); + if (before.classes) + clsName = clsName.concat(before.classes.split(/\s+/)); + if (before.tooltip) + tooltip = before.tooltip; + + clsName = $.unique(clsName); + html.push('<td class="'+clsName.join(' ')+'"' + (tooltip ? ' title="'+tooltip+'"' : '') + '>'+prevMonth.getUTCDate() + '</td>'); + if (prevMonth.getUTCDay() == this.o.weekEnd) { + html.push('</tr>'); + } + prevMonth.setUTCDate(prevMonth.getUTCDate()+1); + } + this.picker.find('.datepicker-days tbody').empty().append(html.join('')); + var currentYear = this.date && this.date.getUTCFullYear(); + + var months = this.picker.find('.datepicker-months') + .find('th:eq(1)') + .text(year) + .end() + .find('span').removeClass('active'); + if (currentYear && currentYear == year) { + months.eq(this.date.getUTCMonth()).addClass('active'); + } + if (year < startYear || year > endYear) { + months.addClass('disabled'); + } + if (year == startYear) { + months.slice(0, startMonth).addClass('disabled'); + } + if (year == endYear) { + months.slice(endMonth+1).addClass('disabled'); + } + + html = ''; + year = parseInt(year/10, 10) * 10; + var yearCont = this.picker.find('.datepicker-years') + .find('th:eq(1)') + .text(year + '-' + (year + 9)) + .end() + .find('td'); + year -= 1; + for (var i = -1; i < 11; i++) { + html += '<span class="year'+(i == -1 ? ' old' : i == 10 ? ' new' : '')+(currentYear == year ? ' active' : '')+(year < startYear || year > endYear ? ' disabled' : '')+'">'+year+'</span>'; + year += 1; + } + yearCont.html(html); + }, + + updateNavArrows: function() { + if (!this._allow_update) return; + + var d = new Date(this.viewDate), + year = d.getUTCFullYear(), + month = d.getUTCMonth(); + switch (this.viewMode) { + case 0: + if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear() && month <= this.o.startDate.getUTCMonth()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear() && month >= this.o.endDate.getUTCMonth()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + case 1: + case 2: + if (this.o.startDate !== -Infinity && year <= this.o.startDate.getUTCFullYear()) { + this.picker.find('.prev').css({visibility: 'hidden'}); + } else { + this.picker.find('.prev').css({visibility: 'visible'}); + } + if (this.o.endDate !== Infinity && year >= this.o.endDate.getUTCFullYear()) { + this.picker.find('.next').css({visibility: 'hidden'}); + } else { + this.picker.find('.next').css({visibility: 'visible'}); + } + break; + } + }, + + click: function(e) { + e.preventDefault(); + var target = $(e.target).closest('span, td, th'); + if (target.length == 1) { + switch(target[0].nodeName.toLowerCase()) { + case 'th': + switch(target[0].className) { + case 'datepicker-switch': + this.showMode(1); + break; + case 'prev': + case 'next': + var dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1); + switch(this.viewMode){ + case 0: + this.viewDate = this.moveMonth(this.viewDate, dir); + break; + case 1: + case 2: + this.viewDate = this.moveYear(this.viewDate, dir); + break; + } + this.fill(); + break; + case 'today': + var date = new Date(); + date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); + + this.showMode(-2); + var which = this.o.todayBtn == 'linked' ? null : 'view'; + this._setDate(date, which); + break; + case 'clear': + var element; + if (this.isInput) + element = this.element; + else if (this.component) + element = this.element.find('input'); + if (element) + element.val("").change(); + this._trigger('changeDate'); + this.update(); + if (this.o.autoclose) + this.hide(); + break; + } + break; + case 'span': + if (!target.is('.disabled')) { + this.viewDate.setUTCDate(1); + if (target.is('.month')) { + var day = 1; + var month = target.parent().find('span').index(target); + var year = this.viewDate.getUTCFullYear(); + this.viewDate.setUTCMonth(month); + this._trigger('changeMonth', this.viewDate); + if (this.o.minViewMode === 1) { + this._setDate(UTCDate(year, month, day,0,0,0,0)); + } + } else { + var year = parseInt(target.text(), 10)||0; + var day = 1; + var month = 0; + this.viewDate.setUTCFullYear(year); + this._trigger('changeYear', this.viewDate); + if (this.o.minViewMode === 2) { + this._setDate(UTCDate(year, month, day,0,0,0,0)); + } + } + this.showMode(-1); + this.fill(); + } + break; + case 'td': + if (target.is('.day') && !target.is('.disabled')){ + var day = parseInt(target.text(), 10)||1; + var year = this.viewDate.getUTCFullYear(), + month = this.viewDate.getUTCMonth(); + if (target.is('.old')) { + if (month === 0) { + month = 11; + year -= 1; + } else { + month -= 1; + } + } else if (target.is('.new')) { + if (month == 11) { + month = 0; + year += 1; + } else { + month += 1; + } + } + this._setDate(UTCDate(year, month, day,0,0,0,0)); + } + break; + } + } + }, + + _setDate: function(date, which){ + if (!which || which == 'date') + this.date = new Date(date); + if (!which || which == 'view') + this.viewDate = new Date(date); + this.fill(); + this.setValue(); + this._trigger('changeDate'); + var element; + if (this.isInput) { + element = this.element; + } else if (this.component){ + element = this.element.find('input'); + } + if (element) { + element.change(); + if (this.o.autoclose && (!which || which == 'date')) { + this.hide(); + } + } + }, + + moveMonth: function(date, dir){ + if (!dir) return date; + var new_date = new Date(date.valueOf()), + day = new_date.getUTCDate(), + month = new_date.getUTCMonth(), + mag = Math.abs(dir), + new_month, test; + dir = dir > 0 ? 1 : -1; + if (mag == 1){ + test = dir == -1 + // If going back one month, make sure month is not current month + // (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02) + ? function(){ return new_date.getUTCMonth() == month; } + // If going forward one month, make sure month is as expected + // (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02) + : function(){ return new_date.getUTCMonth() != new_month; }; + new_month = month + dir; + new_date.setUTCMonth(new_month); + // Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11 + if (new_month < 0 || new_month > 11) + new_month = (new_month + 12) % 12; + } else { + // For magnitudes >1, move one month at a time... + for (var i=0; i<mag; i++) + // ...which might decrease the day (eg, Jan 31 to Feb 28, etc)... + new_date = this.moveMonth(new_date, dir); + // ...then reset the day, keeping it in the new month + new_month = new_date.getUTCMonth(); + new_date.setUTCDate(day); + test = function(){ return new_month != new_date.getUTCMonth(); }; + } + // Common date-resetting loop -- if date is beyond end of month, make it + // end of month + while (test()){ + new_date.setUTCDate(--day); + new_date.setUTCMonth(new_month); + } + return new_date; + }, + + moveYear: function(date, dir){ + return this.moveMonth(date, dir*12); + }, + + dateWithinRange: function(date){ + return date >= this.o.startDate && date <= this.o.endDate; + }, + + keydown: function(e){ + if (this.picker.is(':not(:visible)')){ + if (e.keyCode == 27) // allow escape to hide and re-show picker + this.show(); + return; + } + var dateChanged = false, + dir, day, month, + newDate, newViewDate; + switch(e.keyCode){ + case 27: // escape + this.hide(); + e.preventDefault(); + break; + case 37: // left + case 39: // right + if (!this.o.keyboardNavigation) break; + dir = e.keyCode == 37 ? -1 : 1; + if (e.ctrlKey){ + newDate = this.moveYear(this.date, dir); + newViewDate = this.moveYear(this.viewDate, dir); + } else if (e.shiftKey){ + newDate = this.moveMonth(this.date, dir); + newViewDate = this.moveMonth(this.viewDate, dir); + } else { + newDate = new Date(this.date); + newDate.setUTCDate(this.date.getUTCDate() + dir); + newViewDate = new Date(this.viewDate); + newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir); + } + if (this.dateWithinRange(newDate)){ + this.date = newDate; + this.viewDate = newViewDate; + this.setValue(); + this.update(); + e.preventDefault(); + dateChanged = true; + } + break; + case 38: // up + case 40: // down + if (!this.o.keyboardNavigation) break; + dir = e.keyCode == 38 ? -1 : 1; + if (e.ctrlKey){ + newDate = this.moveYear(this.date, dir); + newViewDate = this.moveYear(this.viewDate, dir); + } else if (e.shiftKey){ + newDate = this.moveMonth(this.date, dir); + newViewDate = this.moveMonth(this.viewDate, dir); + } else { + newDate = new Date(this.date); + newDate.setUTCDate(this.date.getUTCDate() + dir * 7); + newViewDate = new Date(this.viewDate); + newViewDate.setUTCDate(this.viewDate.getUTCDate() + dir * 7); + } + if (this.dateWithinRange(newDate)){ + this.date = newDate; + this.viewDate = newViewDate; + this.setValue(); + this.update(); + e.preventDefault(); + dateChanged = true; + } + break; + case 13: // enter + this.hide(); + e.preventDefault(); + break; + case 9: // tab + this.hide(); + break; + } + if (dateChanged){ + this._trigger('changeDate'); + var element; + if (this.isInput) { + element = this.element; + } else if (this.component){ + element = this.element.find('input'); + } + if (element) { + element.change(); + } + } + }, + + showMode: function(dir) { + if (dir) { + this.viewMode = Math.max(this.o.minViewMode, Math.min(2, this.viewMode + dir)); + } + /* + vitalets: fixing bug of very special conditions: + jquery 1.7.1 + webkit + show inline datepicker in bootstrap popover. + Method show() does not set display css correctly and datepicker is not shown. + Changed to .css('display', 'block') solve the problem. + See https://github.com/vitalets/x-editable/issues/37 + + In jquery 1.7.2+ everything works fine. + */ + //this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).show(); + this.picker.find('>div').hide().filter('.datepicker-'+DPGlobal.modes[this.viewMode].clsName).css('display', 'block'); + this.updateNavArrows(); + } + }; + + var DateRangePicker = function(element, options){ + this.element = $(element); + this.inputs = $.map(options.inputs, function(i){ return i.jquery ? i[0] : i; }); + delete options.inputs; + + $(this.inputs) + .datepicker(options) + .bind('changeDate', $.proxy(this.dateUpdated, this)); + + this.pickers = $.map(this.inputs, function(i){ return $(i).data('datepicker'); }); + this.updateDates(); + }; + DateRangePicker.prototype = { + updateDates: function(){ + this.dates = $.map(this.pickers, function(i){ return i.date; }); + this.updateRanges(); + }, + updateRanges: function(){ + var range = $.map(this.dates, function(d){ return d.valueOf(); }); + $.each(this.pickers, function(i, p){ + p.setRange(range); + }); + }, + dateUpdated: function(e){ + var dp = $(e.target).data('datepicker'), + new_date = dp.getUTCDate(), + i = $.inArray(e.target, this.inputs), + l = this.inputs.length; + if (i == -1) return; + + if (new_date < this.dates[i]){ + // Date being moved earlier/left + while (i>=0 && new_date < this.dates[i]){ + this.pickers[i--].setUTCDate(new_date); + } + } + else if (new_date > this.dates[i]){ + // Date being moved later/right + while (i<l && new_date > this.dates[i]){ + this.pickers[i++].setUTCDate(new_date); + } + } + this.updateDates(); + }, + remove: function(){ + $.map(this.pickers, function(p){ p.remove(); }); + delete this.element.data().datepicker; + } + }; + + function opts_from_el(el, prefix){ + // Derive options from element data-attrs + var data = $(el).data(), + out = {}, inkey, + replace = new RegExp('^' + prefix.toLowerCase() + '([A-Z])'), + prefix = new RegExp('^' + prefix.toLowerCase()); + for (var key in data) + if (prefix.test(key)){ + inkey = key.replace(replace, function(_,a){ return a.toLowerCase(); }); + out[inkey] = data[key]; + } + return out; + } + + function opts_from_locale(lang){ + // Derive options from locale plugins + var out = {}; + // Check if "de-DE" style date is available, if not language should + // fallback to 2 letter code eg "de" + if (!dates[lang]) { + lang = lang.split('-')[0] + if (!dates[lang]) + return; + } + var d = dates[lang]; + $.each(locale_opts, function(i,k){ + if (k in d) + out[k] = d[k]; + }); + return out; + } + + var old = $.fn.datepicker; + var datepicker = $.fn.datepicker = function ( option ) { + var args = Array.apply(null, arguments); + args.shift(); + var internal_return, + this_return; + this.each(function () { + var $this = $(this), + data = $this.data('datepicker'), + options = typeof option == 'object' && option; + if (!data) { + var elopts = opts_from_el(this, 'date'), + // Preliminary otions + xopts = $.extend({}, defaults, elopts, options), + locopts = opts_from_locale(xopts.language), + // Options priority: js args, data-attrs, locales, defaults + opts = $.extend({}, defaults, locopts, elopts, options); + if ($this.is('.input-daterange') || opts.inputs){ + var ropts = { + inputs: opts.inputs || $this.find('input').toArray() + }; + $this.data('datepicker', (data = new DateRangePicker(this, $.extend(opts, ropts)))); + } + else{ + $this.data('datepicker', (data = new Datepicker(this, opts))); + } + } + if (typeof option == 'string' && typeof data[option] == 'function') { + internal_return = data[option].apply(data, args); + if (internal_return !== undefined) + return false; + } + }); + if (internal_return !== undefined) + return internal_return; + else + return this; + }; + + var defaults = $.fn.datepicker.defaults = { + autoclose: false, + beforeShowDay: $.noop, + calendarWeeks: false, + clearBtn: false, + daysOfWeekDisabled: [], + endDate: Infinity, + forceParse: true, + format: 'mm/dd/yyyy', + keyboardNavigation: true, + language: 'en', + minViewMode: 0, + rtl: false, + startDate: -Infinity, + startView: 0, + todayBtn: false, + todayHighlight: false, + weekStart: 0 + }; + var locale_opts = $.fn.datepicker.locale_opts = [ + 'format', + 'rtl', + 'weekStart' + ]; + $.fn.datepicker.Constructor = Datepicker; + var dates = $.fn.datepicker.dates = { + en: { + days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], + daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], + months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], + today: "Today", + clear: "Clear" + } + }; + + var DPGlobal = { + modes: [ + { + clsName: 'days', + navFnc: 'Month', + navStep: 1 + }, + { + clsName: 'months', + navFnc: 'FullYear', + navStep: 1 + }, + { + clsName: 'years', + navFnc: 'FullYear', + navStep: 10 + }], + isLeapYear: function (year) { + return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); + }, + getDaysInMonth: function (year, month) { + return [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; + }, + validParts: /dd?|DD?|mm?|MM?|yy(?:yy)?/g, + nonpunctuation: /[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g, + parseFormat: function(format){ + // IE treats \0 as a string end in inputs (truncating the value), + // so it's a bad format delimiter, anyway + var separators = format.replace(this.validParts, '\0').split('\0'), + parts = format.match(this.validParts); + if (!separators || !separators.length || !parts || parts.length === 0){ + throw new Error("Invalid date format."); + } + return {separators: separators, parts: parts}; + }, + parseDate: function(date, format, language) { + if (date instanceof Date) return date; + if (typeof format === 'string') + format = DPGlobal.parseFormat(format); + if (/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(date)) { + var part_re = /([\-+]\d+)([dmwy])/, + parts = date.match(/([\-+]\d+)([dmwy])/g), + part, dir; + date = new Date(); + for (var i=0; i<parts.length; i++) { + part = part_re.exec(parts[i]); + dir = parseInt(part[1]); + switch(part[2]){ + case 'd': + date.setUTCDate(date.getUTCDate() + dir); + break; + case 'm': + date = Datepicker.prototype.moveMonth.call(Datepicker.prototype, date, dir); + break; + case 'w': + date.setUTCDate(date.getUTCDate() + dir * 7); + break; + case 'y': + date = Datepicker.prototype.moveYear.call(Datepicker.prototype, date, dir); + break; + } + } + return UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0); + } + var parts = date && date.match(this.nonpunctuation) || [], + date = new Date(), + parsed = {}, + setters_order = ['yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'd', 'dd'], + setters_map = { + yyyy: function(d,v){ return d.setUTCFullYear(v); }, + yy: function(d,v){ return d.setUTCFullYear(2000+v); }, + m: function(d,v){ + v -= 1; + while (v<0) v += 12; + v %= 12; + d.setUTCMonth(v); + while (d.getUTCMonth() != v) + d.setUTCDate(d.getUTCDate()-1); + return d; + }, + d: function(d,v){ return d.setUTCDate(v); } + }, + val, filtered, part; + setters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m']; + setters_map['dd'] = setters_map['d']; + date = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0); + var fparts = format.parts.slice(); + // Remove noop parts + if (parts.length != fparts.length) { + fparts = $(fparts).filter(function(i,p){ + return $.inArray(p, setters_order) !== -1; + }).toArray(); + } + // Process remainder + if (parts.length == fparts.length) { + for (var i=0, cnt = fparts.length; i < cnt; i++) { + val = parseInt(parts[i], 10); + part = fparts[i]; + if (isNaN(val)) { + switch(part) { + case 'MM': + filtered = $(dates[language].months).filter(function(){ + var m = this.slice(0, parts[i].length), + p = parts[i].slice(0, m.length); + return m == p; + }); + val = $.inArray(filtered[0], dates[language].months) + 1; + break; + case 'M': + filtered = $(dates[language].monthsShort).filter(function(){ + var m = this.slice(0, parts[i].length), + p = parts[i].slice(0, m.length); + return m == p; + }); + val = $.inArray(filtered[0], dates[language].monthsShort) + 1; + break; + } + } + parsed[part] = val; + } + for (var i=0, s; i<setters_order.length; i++){ + s = setters_order[i]; + if (s in parsed && !isNaN(parsed[s])) + setters_map[s](date, parsed[s]); + } + } + return date; + }, + formatDate: function(date, format, language){ + if (typeof format === 'string') + format = DPGlobal.parseFormat(format); + var val = { + d: date.getUTCDate(), + D: dates[language].daysShort[date.getUTCDay()], + DD: dates[language].days[date.getUTCDay()], + m: date.getUTCMonth() + 1, + M: dates[language].monthsShort[date.getUTCMonth()], + MM: dates[language].months[date.getUTCMonth()], + yy: date.getUTCFullYear().toString().substring(2), + yyyy: date.getUTCFullYear() + }; + val.dd = (val.d < 10 ? '0' : '') + val.d; + val.mm = (val.m < 10 ? '0' : '') + val.m; + var date = [], + seps = $.extend([], format.separators); + for (var i=0, cnt = format.parts.length; i <= cnt; i++) { + if (seps.length) + date.push(seps.shift()); + date.push(val[format.parts[i]]); + } + return date.join(''); + }, + headTemplate: '<thead>'+ + '<tr>'+ + '<th class="prev"><i class="icon-arrow-left"/></th>'+ + '<th colspan="5" class="datepicker-switch"></th>'+ + '<th class="next"><i class="icon-arrow-right"/></th>'+ + '</tr>'+ + '</thead>', + contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>', + footTemplate: '<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>' + }; + DPGlobal.template = '<div class="datepicker">'+ + '<div class="datepicker-days">'+ + '<table class=" table-condensed">'+ + DPGlobal.headTemplate+ + '<tbody></tbody>'+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '<div class="datepicker-months">'+ + '<table class="table-condensed">'+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '<div class="datepicker-years">'+ + '<table class="table-condensed">'+ + DPGlobal.headTemplate+ + DPGlobal.contTemplate+ + DPGlobal.footTemplate+ + '</table>'+ + '</div>'+ + '</div>'; + + $.fn.datepicker.DPGlobal = DPGlobal; + + + /* DATEPICKER NO CONFLICT + * =================== */ + + $.fn.datepicker.noConflict = function(){ + $.fn.datepicker = old; + return this; + }; + + + /* DATEPICKER DATA-API + * ================== */ + + $(document).on( + 'focus.datepicker.data-api click.datepicker.data-api', + '[data-provide="datepicker"]', + function(e){ + var $this = $(this); + if ($this.data('datepicker')) return; + e.preventDefault(); + // component click requires us to explicitly show it + datepicker.call($this, 'show'); + } + ); + $(function(){ + //$('[data-provide="datepicker-inline"]').datepicker(); + //vit: changed to support noConflict() + datepicker.call($('[data-provide="datepicker-inline"]')); + }); + +}( window.jQuery )); + +/** +Bootstrap-datepicker. +Description and examples: https://github.com/eternicode/bootstrap-datepicker. +For **i18n** you should include js file from here: https://github.com/eternicode/bootstrap-datepicker/tree/master/js/locales +and set `language` option. +Since 1.4.0 date has different appearance in **popup** and **inline** modes. + +@class date +@extends abstractinput +@final +@example +<a href="#" id="dob" data-type="date" data-pk="1" data-url="/post" data-title="Select date">15/05/1984</a> +<script> +$(function(){ + $('#dob').editable({ + format: 'yyyy-mm-dd', + viewformat: 'dd/mm/yyyy', + datepicker: { + weekStart: 1 + } + } + }); +}); +</script> +**/ +(function ($) { + "use strict"; + + //store bootstrap-datepicker as bdateicker to exclude conflict with jQuery UI one + $.fn.bdatepicker = $.fn.datepicker.noConflict(); + if(!$.fn.datepicker) { //if there were no other datepickers, keep also original name + $.fn.datepicker = $.fn.bdatepicker; + } + + var Date = function (options) { + this.init('date', options, Date.defaults); + this.initPicker(options, Date.defaults); + }; + + $.fn.editableutils.inherit(Date, $.fn.editabletypes.abstractinput); + + $.extend(Date.prototype, { + initPicker: function(options, defaults) { + //'format' is set directly from settings or data-* attributes + + //by default viewformat equals to format + if(!this.options.viewformat) { + this.options.viewformat = this.options.format; + } + + //try parse datepicker config defined as json string in data-datepicker + options.datepicker = $.fn.editableutils.tryParseJson(options.datepicker, true); + + //overriding datepicker config (as by default jQuery extend() is not recursive) + //since 1.4 datepicker internally uses viewformat instead of format. Format is for submit only + this.options.datepicker = $.extend({}, defaults.datepicker, options.datepicker, { + format: this.options.viewformat + }); + + //language + this.options.datepicker.language = this.options.datepicker.language || 'en'; + + //store DPglobal + this.dpg = $.fn.bdatepicker.DPGlobal; + + //store parsed formats + this.parsedFormat = this.dpg.parseFormat(this.options.format); + this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat); + }, + + render: function () { + this.$input.bdatepicker(this.options.datepicker); + + //"clear" link + if(this.options.clear) { + this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){ + e.preventDefault(); + e.stopPropagation(); + this.clear(); + }, this)); + + this.$tpl.parent().append($('<div class="editable-clear">').append(this.$clear)); + } + }, + + value2html: function(value, element) { + var text = value ? this.dpg.formatDate(value, this.parsedViewFormat, this.options.datepicker.language) : ''; + Date.superclass.value2html.call(this, text, element); + }, + + html2value: function(html) { + return this.parseDate(html, this.parsedViewFormat); + }, + + value2str: function(value) { + return value ? this.dpg.formatDate(value, this.parsedFormat, this.options.datepicker.language) : ''; + }, + + str2value: function(str) { + return this.parseDate(str, this.parsedFormat); + }, + + value2submit: function(value) { + return this.value2str(value); + }, + + value2input: function(value) { + this.$input.bdatepicker('update', value); + }, + + input2value: function() { + return this.$input.data('datepicker').date; + }, + + activate: function() { + }, + + clear: function() { + this.$input.data('datepicker').date = null; + this.$input.find('.active').removeClass('active'); + if(!this.options.showbuttons) { + this.$input.closest('form').submit(); + } + }, + + autosubmit: function() { + this.$input.on('mouseup', '.day', function(e){ + if($(e.currentTarget).is('.old') || $(e.currentTarget).is('.new')) { + return; + } + var $form = $(this).closest('form'); + setTimeout(function() { + $form.submit(); + }, 200); + }); + //changedate is not suitable as it triggered when showing datepicker. see #149 + /* + this.$input.on('changeDate', function(e){ + var $form = $(this).closest('form'); + setTimeout(function() { + $form.submit(); + }, 200); + }); + */ + }, + + /* + For incorrect date bootstrap-datepicker returns current date that is not suitable + for datefield. + This function returns null for incorrect date. + */ + parseDate: function(str, format) { + var date = null, formattedBack; + if(str) { + date = this.dpg.parseDate(str, format, this.options.datepicker.language); + if(typeof str === 'string') { + formattedBack = this.dpg.formatDate(date, format, this.options.datepicker.language); + if(str !== formattedBack) { + date = null; + } + } + } + return date; + } + + }); + + Date.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <div></div> + **/ + tpl:'<div class="editable-date well"></div>', + /** + @property inputclass + @default null + **/ + inputclass: null, + /** + Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br> + Possible tokens are: <code>d, dd, m, mm, yy, yyyy</code> + + @property format + @type string + @default yyyy-mm-dd + **/ + format:'yyyy-mm-dd', + /** + Format used for displaying date. Also applied when converting date from element's text on init. + If not specified equals to <code>format</code> + + @property viewformat + @type string + @default null + **/ + viewformat: null, + /** + Configuration of datepicker. + Full list of options: http://bootstrap-datepicker.readthedocs.org/en/latest/options.html + + @property datepicker + @type object + @default { + weekStart: 0, + startView: 0, + minViewMode: 0, + autoclose: false + } + **/ + datepicker:{ + weekStart: 0, + startView: 0, + minViewMode: 0, + autoclose: false + }, + /** + Text shown as clear date button. + If <code>false</code> clear button will not be rendered. + + @property clear + @type boolean|string + @default 'x clear' + **/ + clear: '&times; clear' + }); + + $.fn.editabletypes.date = Date; + +}(window.jQuery)); + +/** +Bootstrap datefield input - modification for inline mode. +Shows normal <input type="text"> and binds popup datepicker. +Automatically shown in inline mode. + +@class datefield +@extends date + +@since 1.4.0 +**/ +(function ($) { + "use strict"; + + var DateField = function (options) { + this.init('datefield', options, DateField.defaults); + this.initPicker(options, DateField.defaults); + }; + + $.fn.editableutils.inherit(DateField, $.fn.editabletypes.date); + + $.extend(DateField.prototype, { + render: function () { + this.$input = this.$tpl.find('input'); + this.setClass(); + this.setAttr('placeholder'); + + //bootstrap-datepicker is set `bdateicker` to exclude conflict with jQuery UI one. (in date.js) + this.$tpl.bdatepicker(this.options.datepicker); + + //need to disable original event handlers + this.$input.off('focus keydown'); + + //update value of datepicker + this.$input.keyup($.proxy(function(){ + this.$tpl.removeData('date'); + this.$tpl.bdatepicker('update'); + }, this)); + + }, + + value2input: function(value) { + this.$input.val(value ? this.dpg.formatDate(value, this.parsedViewFormat, this.options.datepicker.language) : ''); + this.$tpl.bdatepicker('update'); + }, + + input2value: function() { + return this.html2value(this.$input.val()); + }, + + activate: function() { + $.fn.editabletypes.text.prototype.activate.call(this); + }, + + autosubmit: function() { + //reset autosubmit to empty + } + }); + + DateField.defaults = $.extend({}, $.fn.editabletypes.date.defaults, { + /** + @property tpl + **/ + tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>', + /** + @property inputclass + @default 'input-small' + **/ + inputclass: 'input-small', + + /* datepicker config */ + datepicker: { + weekStart: 0, + startView: 0, + minViewMode: 0, + autoclose: true + } + }); + + $.fn.editabletypes.datefield = DateField; + +}(window.jQuery)); +/** +Bootstrap-datetimepicker. +Based on [smalot bootstrap-datetimepicker plugin](https://github.com/smalot/bootstrap-datetimepicker). +Before usage you should manually include dependent js and css: + + <link href="css/datetimepicker.css" rel="stylesheet" type="text/css"></link> + <script src="js/bootstrap-datetimepicker.js"></script> + +For **i18n** you should include js file from here: https://github.com/smalot/bootstrap-datetimepicker/tree/master/js/locales +and set `language` option. + +@class datetime +@extends abstractinput +@final +@since 1.4.4 +@example +<a href="#" id="last_seen" data-type="datetime" data-pk="1" data-url="/post" title="Select date & time">15/03/2013 12:45</a> +<script> +$(function(){ + $('#last_seen').editable({ + format: 'yyyy-mm-dd hh:ii', + viewformat: 'dd/mm/yyyy hh:ii', + datetimepicker: { + weekStart: 1 + } + } + }); +}); +</script> +**/ +(function ($) { + "use strict"; + + var DateTime = function (options) { + this.init('datetime', options, DateTime.defaults); + this.initPicker(options, DateTime.defaults); + }; + + $.fn.editableutils.inherit(DateTime, $.fn.editabletypes.abstractinput); + + $.extend(DateTime.prototype, { + initPicker: function(options, defaults) { + //'format' is set directly from settings or data-* attributes + + //by default viewformat equals to format + if(!this.options.viewformat) { + this.options.viewformat = this.options.format; + } + + //try parse datetimepicker config defined as json string in data-datetimepicker + options.datetimepicker = $.fn.editableutils.tryParseJson(options.datetimepicker, true); + + //overriding datetimepicker config (as by default jQuery extend() is not recursive) + //since 1.4 datetimepicker internally uses viewformat instead of format. Format is for submit only + this.options.datetimepicker = $.extend({}, defaults.datetimepicker, options.datetimepicker, { + format: this.options.viewformat + }); + + //language + this.options.datetimepicker.language = this.options.datetimepicker.language || 'en'; + + //store DPglobal + this.dpg = $.fn.datetimepicker.DPGlobal; + + //store parsed formats + this.parsedFormat = this.dpg.parseFormat(this.options.format, this.options.formatType); + this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat, this.options.formatType); + }, + + render: function () { + this.$input.datetimepicker(this.options.datetimepicker); + + //adjust container position when viewMode changes + //see https://github.com/smalot/bootstrap-datetimepicker/pull/80 + this.$input.on('changeMode', function(e) { + var f = $(this).closest('form').parent(); + //timeout here, otherwise container changes position before form has new size + setTimeout(function(){ + f.triggerHandler('resize'); + }, 0); + }); + + //"clear" link + if(this.options.clear) { + this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){ + e.preventDefault(); + e.stopPropagation(); + this.clear(); + }, this)); + + this.$tpl.parent().append($('<div class="editable-clear">').append(this.$clear)); + } + }, + + value2html: function(value, element) { + //formatDate works with UTCDate! + var text = value ? this.dpg.formatDate(this.toUTC(value), this.parsedViewFormat, this.options.datetimepicker.language, this.options.formatType) : ''; + if(element) { + DateTime.superclass.value2html.call(this, text, element); + } else { + return text; + } + }, + + html2value: function(html) { + //parseDate return utc date! + var value = this.parseDate(html, this.parsedViewFormat); + return value ? this.fromUTC(value) : null; + }, + + value2str: function(value) { + //formatDate works with UTCDate! + return value ? this.dpg.formatDate(this.toUTC(value), this.parsedFormat, this.options.datetimepicker.language, this.options.formatType) : ''; + }, + + str2value: function(str) { + //parseDate return utc date! + var value = this.parseDate(str, this.parsedFormat); + return value ? this.fromUTC(value) : null; + }, + + value2submit: function(value) { + return this.value2str(value); + }, + + value2input: function(value) { + if(value) { + this.$input.data('datetimepicker').setDate(value); + } + }, + + input2value: function() { + //date may be cleared, in that case getDate() triggers error + var dt = this.$input.data('datetimepicker'); + return dt.date ? dt.getDate() : null; + }, + + activate: function() { + }, + + clear: function() { + this.$input.data('datetimepicker').date = null; + this.$input.find('.active').removeClass('active'); + if(!this.options.showbuttons) { + this.$input.closest('form').submit(); + } + }, + + autosubmit: function() { + this.$input.on('mouseup', '.minute', function(e){ + var $form = $(this).closest('form'); + setTimeout(function() { + $form.submit(); + }, 200); + }); + }, + + //convert date from local to utc + toUTC: function(value) { + return value ? new Date(value.valueOf() - value.getTimezoneOffset() * 60000) : value; + }, + + //convert date from utc to local + fromUTC: function(value) { + return value ? new Date(value.valueOf() + value.getTimezoneOffset() * 60000) : value; + }, + + /* + For incorrect date bootstrap-datetimepicker returns current date that is not suitable + for datetimefield. + This function returns null for incorrect date. + */ + parseDate: function(str, format) { + var date = null, formattedBack; + if(str) { + date = this.dpg.parseDate(str, format, this.options.datetimepicker.language, this.options.formatType); + if(typeof str === 'string') { + formattedBack = this.dpg.formatDate(date, format, this.options.datetimepicker.language, this.options.formatType); + if(str !== formattedBack) { + date = null; + } + } + } + return date; + } + + }); + + DateTime.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <div></div> + **/ + tpl:'<div class="editable-date well"></div>', + /** + @property inputclass + @default null + **/ + inputclass: null, + /** + Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br> + Possible tokens are: <code>d, dd, m, mm, yy, yyyy, h, i</code> + + @property format + @type string + @default yyyy-mm-dd hh:ii + **/ + format:'yyyy-mm-dd hh:ii', + formatType:'standard', + /** + Format used for displaying date. Also applied when converting date from element's text on init. + If not specified equals to <code>format</code> + + @property viewformat + @type string + @default null + **/ + viewformat: null, + /** + Configuration of datetimepicker. + Full list of options: https://github.com/smalot/bootstrap-datetimepicker + + @property datetimepicker + @type object + @default { } + **/ + datetimepicker:{ + todayHighlight: false, + autoclose: false + }, + /** + Text shown as clear date button. + If <code>false</code> clear button will not be rendered. + + @property clear + @type boolean|string + @default 'x clear' + **/ + clear: '&times; clear' + }); + + $.fn.editabletypes.datetime = DateTime; + +}(window.jQuery)); +/** +Bootstrap datetimefield input - datetime input for inline mode. +Shows normal <input type="text"> and binds popup datetimepicker. +Automatically shown in inline mode. + +@class datetimefield +@extends datetime + +**/ +(function ($) { + "use strict"; + + var DateTimeField = function (options) { + this.init('datetimefield', options, DateTimeField.defaults); + this.initPicker(options, DateTimeField.defaults); + }; + + $.fn.editableutils.inherit(DateTimeField, $.fn.editabletypes.datetime); + + $.extend(DateTimeField.prototype, { + render: function () { + this.$input = this.$tpl.find('input'); + this.setClass(); + this.setAttr('placeholder'); + + this.$tpl.datetimepicker(this.options.datetimepicker); + + //need to disable original event handlers + this.$input.off('focus keydown'); + + //update value of datepicker + this.$input.keyup($.proxy(function(){ + this.$tpl.removeData('date'); + this.$tpl.datetimepicker('update'); + }, this)); + + }, + + value2input: function(value) { + this.$input.val(this.value2html(value)); + this.$tpl.datetimepicker('update'); + }, + + input2value: function() { + return this.html2value(this.$input.val()); + }, + + activate: function() { + $.fn.editabletypes.text.prototype.activate.call(this); + }, + + autosubmit: function() { + //reset autosubmit to empty + } + }); + + DateTimeField.defaults = $.extend({}, $.fn.editabletypes.datetime.defaults, { + /** + @property tpl + **/ + tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>', + /** + @property inputclass + @default 'input-medium' + **/ + inputclass: 'input-medium', + + /* datetimepicker config */ + datetimepicker:{ + todayHighlight: false, + autoclose: true + } + }); + + $.fn.editabletypes.datetimefield = DateTimeField; + +}(window.jQuery)); +/** +Typeahead input (bootstrap 2 only). Based on Twitter Bootstrap 2 [typeahead](http://getbootstrap.com/2.3.2/javascript.html#typeahead). +Depending on `source` format typeahead operates in two modes: + +* **strings**: + When `source` defined as array of strings, e.g. `['text1', 'text2', 'text3' ...]`. + User can submit one of these strings or any text entered in input (even if it is not matching source). + +* **objects**: + When `source` defined as array of objects, e.g. `[{value: 1, text: "text1"}, {value: 2, text: "text2"}, ...]`. + User can submit only values that are in source (otherwise `null` is submitted). This is more like *dropdown* behavior. + +@class typeahead +@extends list +@since 1.4.1 +@final +@example +<a href="#" id="country" data-type="typeahead" data-pk="1" data-url="/post" data-title="Input country"></a> +<script> +$(function(){ + $('#country').editable({ + value: 'ru', + source: [ + {value: 'gb', text: 'Great Britain'}, + {value: 'us', text: 'United States'}, + {value: 'ru', text: 'Russia'} + ] + }); +}); +</script> +**/ +(function ($) { + "use strict"; + + var Constructor = function (options) { + this.init('typeahead', options, Constructor.defaults); + + //overriding objects in config (as by default jQuery extend() is not recursive) + this.options.typeahead = $.extend({}, Constructor.defaults.typeahead, { + //set default methods for typeahead to work with objects + matcher: this.matcher, + sorter: this.sorter, + highlighter: this.highlighter, + updater: this.updater + }, options.typeahead); + }; + + $.fn.editableutils.inherit(Constructor, $.fn.editabletypes.list); + + $.extend(Constructor.prototype, { + renderList: function() { + this.$input = this.$tpl.is('input') ? this.$tpl : this.$tpl.find('input[type="text"]'); + + //set source of typeahead + this.options.typeahead.source = this.sourceData; + + //apply typeahead + this.$input.typeahead(this.options.typeahead); + + //patch some methods in typeahead + var ta = this.$input.data('typeahead'); + ta.render = $.proxy(this.typeaheadRender, ta); + ta.select = $.proxy(this.typeaheadSelect, ta); + ta.move = $.proxy(this.typeaheadMove, ta); + + this.renderClear(); + this.setClass(); + this.setAttr('placeholder'); + }, + + value2htmlFinal: function(value, element) { + if(this.getIsObjects()) { + var items = $.fn.editableutils.itemsByValue(value, this.sourceData); + value = items.length ? items[0].text : ''; + } + $.fn.editabletypes.abstractinput.prototype.value2html.call(this, value, element); + }, + + html2value: function (html) { + return html ? html : null; + }, + + value2input: function(value) { + if(this.getIsObjects()) { + var items = $.fn.editableutils.itemsByValue(value, this.sourceData); + this.$input.data('value', value).val(items.length ? items[0].text : ''); + } else { + this.$input.val(value); + } + }, + + input2value: function() { + if(this.getIsObjects()) { + var value = this.$input.data('value'), + items = $.fn.editableutils.itemsByValue(value, this.sourceData); + + if(items.length && items[0].text.toLowerCase() === this.$input.val().toLowerCase()) { + return value; + } else { + return null; //entered string not found in source + } + } else { + return this.$input.val(); + } + }, + + /* + if in sourceData values <> texts, typeahead in "objects" mode: + user must pick some value from list, otherwise `null` returned. + if all values == texts put typeahead in "strings" mode: + anything what entered is submited. + */ + getIsObjects: function() { + if(this.isObjects === undefined) { + this.isObjects = false; + for(var i=0; i<this.sourceData.length; i++) { + if(this.sourceData[i].value !== this.sourceData[i].text) { + this.isObjects = true; + break; + } + } + } + return this.isObjects; + }, + + /* + Methods borrowed from text input + */ + activate: $.fn.editabletypes.text.prototype.activate, + renderClear: $.fn.editabletypes.text.prototype.renderClear, + postrender: $.fn.editabletypes.text.prototype.postrender, + toggleClear: $.fn.editabletypes.text.prototype.toggleClear, + clear: function() { + $.fn.editabletypes.text.prototype.clear.call(this); + this.$input.data('value', ''); + }, + + + /* + Typeahead option methods used as defaults + */ + /*jshint eqeqeq:false, curly: false, laxcomma: true, asi: true*/ + matcher: function (item) { + return $.fn.typeahead.Constructor.prototype.matcher.call(this, item.text); + }, + sorter: function (items) { + var beginswith = [] + , caseSensitive = [] + , caseInsensitive = [] + , item + , text; + + while (item = items.shift()) { + text = item.text; + if (!text.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item); + else if (~text.indexOf(this.query)) caseSensitive.push(item); + else caseInsensitive.push(item); + } + + return beginswith.concat(caseSensitive, caseInsensitive); + }, + highlighter: function (item) { + return $.fn.typeahead.Constructor.prototype.highlighter.call(this, item.text); + }, + updater: function (item) { + this.$element.data('value', item.value); + return item.text; + }, + + + /* + Overwrite typeahead's render method to store objects. + There are a lot of disscussion in bootstrap repo on this point and still no result. + See https://github.com/twitter/bootstrap/issues/5967 + + This function just store item via jQuery data() method instead of attr('data-value') + */ + typeaheadRender: function (items) { + var that = this; + + items = $(items).map(function (i, item) { +// i = $(that.options.item).attr('data-value', item) + i = $(that.options.item).data('item', item); + i.find('a').html(that.highlighter(item)); + return i[0]; + }); + + //add option to disable autoselect of first line + //see https://github.com/twitter/bootstrap/pull/4164 + if (this.options.autoSelect) { + items.first().addClass('active'); + } + this.$menu.html(items); + return this; + }, + + //add option to disable autoselect of first line + //see https://github.com/twitter/bootstrap/pull/4164 + typeaheadSelect: function () { + var val = this.$menu.find('.active').data('item') + if(this.options.autoSelect || val){ + this.$element + .val(this.updater(val)) + .change() + } + return this.hide() + }, + + /* + if autoSelect = false and nothing matched we need extra press onEnter that is not convinient. + This patch fixes it. + */ + typeaheadMove: function (e) { + if (!this.shown) return + + switch(e.keyCode) { + case 9: // tab + case 13: // enter + case 27: // escape + if (!this.$menu.find('.active').length) return + e.preventDefault() + break + + case 38: // up arrow + e.preventDefault() + this.prev() + break + + case 40: // down arrow + e.preventDefault() + this.next() + break + } + + e.stopPropagation() + } + + /*jshint eqeqeq: true, curly: true, laxcomma: false, asi: false*/ + + }); + + Constructor.defaults = $.extend({}, $.fn.editabletypes.list.defaults, { + /** + @property tpl + @default <input type="text"> + **/ + tpl:'<input type="text">', + /** + Configuration of typeahead. [Full list of options](http://getbootstrap.com/2.3.2/javascript.html#typeahead). + + @property typeahead + @type object + @default null + **/ + typeahead: null, + /** + Whether to show `clear` button + + @property clear + @type boolean + @default true + **/ + clear: true + }); + + $.fn.editabletypes.typeahead = Constructor; + +}(window.jQuery)); \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/js/bootstrap-editable.min.js b/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/js/bootstrap-editable.min.js new file mode 100755 index 0000000..372f8b0 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/bootstrap-editable/js/bootstrap-editable.min.js @@ -0,0 +1,7 @@ +/*! X-editable - v1.5.1 +* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery +* http://github.com/vitalets/x-editable +* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */ +!function(a){"use strict";var b=function(b,c){this.options=a.extend({},a.fn.editableform.defaults,c),this.$div=a(b),this.options.scope||(this.options.scope=this)};b.prototype={constructor:b,initInput:function(){this.input=this.options.input,this.value=this.input.str2value(this.options.value),this.input.prerender()},initTemplate:function(){this.$form=a(a.fn.editableform.template)},initButtons:function(){var b=this.$form.find(".editable-buttons");b.append(a.fn.editableform.buttons),"bottom"===this.options.showbuttons&&b.addClass("editable-buttons-bottom")},render:function(){this.$loading=a(a.fn.editableform.loading),this.$div.empty().append(this.$loading),this.initTemplate(),this.options.showbuttons?this.initButtons():this.$form.find(".editable-buttons").remove(),this.showLoading(),this.isSaving=!1,this.$div.triggerHandler("rendering"),this.initInput(),this.$form.find("div.editable-input").append(this.input.$tpl),this.$div.append(this.$form),a.when(this.input.render()).then(a.proxy(function(){if(this.options.showbuttons||this.input.autosubmit(),this.$form.find(".editable-cancel").click(a.proxy(this.cancel,this)),this.input.error)this.error(this.input.error),this.$form.find(".editable-submit").attr("disabled",!0),this.input.$input.attr("disabled",!0),this.$form.submit(function(a){a.preventDefault()});else{this.error(!1),this.input.$input.removeAttr("disabled"),this.$form.find(".editable-submit").removeAttr("disabled");var b=null===this.value||void 0===this.value||""===this.value?this.options.defaultValue:this.value;this.input.value2input(b),this.$form.submit(a.proxy(this.submit,this))}this.$div.triggerHandler("rendered"),this.showForm(),this.input.postrender&&this.input.postrender()},this))},cancel:function(){this.$div.triggerHandler("cancel")},showLoading:function(){var a,b;this.$form?(a=this.$form.outerWidth(),b=this.$form.outerHeight(),a&&this.$loading.width(a),b&&this.$loading.height(b),this.$form.hide()):(a=this.$loading.parent().width(),a&&this.$loading.width(a)),this.$loading.show()},showForm:function(a){this.$loading.hide(),this.$form.show(),a!==!1&&this.input.activate(),this.$div.triggerHandler("show")},error:function(b){var c,d=this.$form.find(".control-group"),e=this.$form.find(".editable-error-block");if(b===!1)d.removeClass(a.fn.editableform.errorGroupClass),e.removeClass(a.fn.editableform.errorBlockClass).empty().hide();else{if(b){c=(""+b).split("\n");for(var f=0;f<c.length;f++)c[f]=a("<div>").text(c[f]).html();b=c.join("<br>")}d.addClass(a.fn.editableform.errorGroupClass),e.addClass(a.fn.editableform.errorBlockClass).html(b).show()}},submit:function(b){b.stopPropagation(),b.preventDefault();var c=this.input.input2value(),d=this.validate(c);if("object"===a.type(d)&&void 0!==d.newValue){if(c=d.newValue,this.input.value2input(c),"string"==typeof d.msg)return this.error(d.msg),this.showForm(),void 0}else if(d)return this.error(d),this.showForm(),void 0;if(!this.options.savenochange&&this.input.value2str(c)==this.input.value2str(this.value))return this.$div.triggerHandler("nochange"),void 0;var e=this.input.value2submit(c);this.isSaving=!0,a.when(this.save(e)).done(a.proxy(function(a){this.isSaving=!1;var b="function"==typeof this.options.success?this.options.success.call(this.options.scope,a,c):null;return b===!1?(this.error(!1),this.showForm(!1),void 0):"string"==typeof b?(this.error(b),this.showForm(),void 0):(b&&"object"==typeof b&&b.hasOwnProperty("newValue")&&(c=b.newValue),this.error(!1),this.value=c,this.$div.triggerHandler("save",{newValue:c,submitValue:e,response:a}),void 0)},this)).fail(a.proxy(function(a){this.isSaving=!1;var b;b="function"==typeof this.options.error?this.options.error.call(this.options.scope,a,c):"string"==typeof a?a:a.responseText||a.statusText||"Unknown error!",this.error(b),this.showForm()},this))},save:function(b){this.options.pk=a.fn.editableutils.tryParseJson(this.options.pk,!0);var c,d="function"==typeof this.options.pk?this.options.pk.call(this.options.scope):this.options.pk,e=!!("function"==typeof this.options.url||this.options.url&&("always"===this.options.send||"auto"===this.options.send&&null!==d&&void 0!==d));return e?(this.showLoading(),c={name:this.options.name||"",value:b,pk:d},"function"==typeof this.options.params?c=this.options.params.call(this.options.scope,c):(this.options.params=a.fn.editableutils.tryParseJson(this.options.params,!0),a.extend(c,this.options.params)),"function"==typeof this.options.url?this.options.url.call(this.options.scope,c):a.ajax(a.extend({url:this.options.url,data:c,type:"POST"},this.options.ajaxOptions))):void 0},validate:function(a){return void 0===a&&(a=this.value),"function"==typeof this.options.validate?this.options.validate.call(this.options.scope,a):void 0},option:function(a,b){a in this.options&&(this.options[a]=b),"value"===a&&this.setValue(b)},setValue:function(a,b){this.value=b?this.input.str2value(a):a,this.$form&&this.$form.is(":visible")&&this.input.value2input(this.value)}},a.fn.editableform=function(c){var d=arguments;return this.each(function(){var e=a(this),f=e.data("editableform"),g="object"==typeof c&&c;f||e.data("editableform",f=new b(this,g)),"string"==typeof c&&f[c].apply(f,Array.prototype.slice.call(d,1))})},a.fn.editableform.Constructor=b,a.fn.editableform.defaults={type:"text",url:null,params:null,name:null,pk:null,value:null,defaultValue:null,send:"auto",validate:null,success:null,error:null,ajaxOptions:null,showbuttons:!0,scope:null,savenochange:!1},a.fn.editableform.template='<form class="form-inline editableform"><div class="control-group"><div><div class="editable-input"></div><div class="editable-buttons"></div></div><div class="editable-error-block"></div></div></form>',a.fn.editableform.loading='<div class="editableform-loading"></div>',a.fn.editableform.buttons='<button type="submit" class="editable-submit">ok</button><button type="button" class="editable-cancel">cancel</button>',a.fn.editableform.errorGroupClass=null,a.fn.editableform.errorBlockClass="editable-error",a.fn.editableform.engine="jquery"}(window.jQuery),function(a){"use strict";a.fn.editableutils={inherit:function(a,b){var c=function(){};c.prototype=b.prototype,a.prototype=new c,a.prototype.constructor=a,a.superclass=b.prototype},setCursorPosition:function(a,b){if(a.setSelectionRange)a.setSelectionRange(b,b);else if(a.createTextRange){var c=a.createTextRange();c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",b),c.select()}},tryParseJson:function(a,b){if("string"==typeof a&&a.length&&a.match(/^[\{\[].*[\}\]]$/))if(b)try{a=new Function("return "+a)()}catch(c){}finally{return a}else a=new Function("return "+a)();return a},sliceObj:function(b,c,d){var e,f,g={};if(!a.isArray(c)||!c.length)return g;for(var h=0;h<c.length;h++)e=c[h],b.hasOwnProperty(e)&&(g[e]=b[e]),d!==!0&&(f=e.toLowerCase(),b.hasOwnProperty(f)&&(g[e]=b[f]));return g},getConfigData:function(b){var c={};return a.each(b.data(),function(a,b){("object"!=typeof b||b&&"object"==typeof b&&(b.constructor===Object||b.constructor===Array))&&(c[a]=b)}),c},objectKeys:function(a){if(Object.keys)return Object.keys(a);if(a!==Object(a))throw new TypeError("Object.keys called on a non-object");var b,c=[];for(b in a)Object.prototype.hasOwnProperty.call(a,b)&&c.push(b);return c},escape:function(b){return a("<div>").text(b).html()},itemsByValue:function(b,c,d){if(!c||null===b)return[];if("function"!=typeof d){var e=d||"value";d=function(a){return a[e]}}var f=a.isArray(b),g=[],h=this;return a.each(c,function(c,e){if(e.children)g=g.concat(h.itemsByValue(b,e.children,d));else if(f)a.grep(b,function(a){return a==(e&&"object"==typeof e?d(e):e)}).length&&g.push(e);else{var i=e&&"object"==typeof e?d(e):e;b==i&&g.push(e)}}),g},createInput:function(b){var c,d,e,f=b.type;return"date"===f&&("inline"===b.mode?a.fn.editabletypes.datefield?f="datefield":a.fn.editabletypes.dateuifield&&(f="dateuifield"):a.fn.editabletypes.date?f="date":a.fn.editabletypes.dateui&&(f="dateui"),"date"!==f||a.fn.editabletypes.date||(f="combodate")),"datetime"===f&&"inline"===b.mode&&(f="datetimefield"),"wysihtml5"!==f||a.fn.editabletypes[f]||(f="textarea"),"function"==typeof a.fn.editabletypes[f]?(c=a.fn.editabletypes[f],d=this.sliceObj(b,this.objectKeys(c.defaults)),e=new c(d)):(a.error("Unknown type: "+f),!1)},supportsTransitions:function(){var a=document.body||document.documentElement,b=a.style,c="transition",d=["Moz","Webkit","Khtml","O","ms"];if("string"==typeof b[c])return!0;c=c.charAt(0).toUpperCase()+c.substr(1);for(var e=0;e<d.length;e++)if("string"==typeof b[d[e]+c])return!0;return!1}}}(window.jQuery),function(a){"use strict";var b=function(a,b){this.init(a,b)},c=function(a,b){this.init(a,b)};b.prototype={containerName:null,containerDataName:null,innerCss:null,containerClass:"editable-container editable-popup",defaults:{},init:function(c,d){this.$element=a(c),this.options=a.extend({},a.fn.editableContainer.defaults,d),this.splitOptions(),this.formOptions.scope=this.$element[0],this.initContainer(),this.delayedHide=!1,this.$element.on("destroyed",a.proxy(function(){this.destroy()},this)),a(document).data("editable-handlers-attached")||(a(document).on("keyup.editable",function(b){27===b.which&&a(".editable-open").editableContainer("hide")}),a(document).on("click.editable",function(c){var d,e=a(c.target),f=[".editable-container",".ui-datepicker-header",".datepicker",".modal-backdrop",".bootstrap-wysihtml5-insert-image-modal",".bootstrap-wysihtml5-insert-link-modal"];if(a.contains(document.documentElement,c.target)&&!e.is(document)){for(d=0;d<f.length;d++)if(e.is(f[d])||e.parents(f[d]).length)return;b.prototype.closeOthers(c.target)}}),a(document).data("editable-handlers-attached",!0))},splitOptions:function(){if(this.containerOptions={},this.formOptions={},!a.fn[this.containerName])throw new Error(this.containerName+" not found. Have you included corresponding js file?");for(var b in this.options)b in this.defaults?this.containerOptions[b]=this.options[b]:this.formOptions[b]=this.options[b]},tip:function(){return this.container()?this.container().$tip:null},container:function(){var a;return this.containerDataName&&(a=this.$element.data(this.containerDataName))?a:a=this.$element.data(this.containerName)},call:function(){this.$element[this.containerName].apply(this.$element,arguments)},initContainer:function(){this.call(this.containerOptions)},renderForm:function(){this.$form.editableform(this.formOptions).on({save:a.proxy(this.save,this),nochange:a.proxy(function(){this.hide("nochange")},this),cancel:a.proxy(function(){this.hide("cancel")},this),show:a.proxy(function(){this.delayedHide?(this.hide(this.delayedHide.reason),this.delayedHide=!1):this.setPosition()},this),rendering:a.proxy(this.setPosition,this),resize:a.proxy(this.setPosition,this),rendered:a.proxy(function(){this.$element.triggerHandler("shown",a(this.options.scope).data("editable"))},this)}).editableform("render")},show:function(b){this.$element.addClass("editable-open"),b!==!1&&this.closeOthers(this.$element[0]),this.innerShow(),this.tip().addClass(this.containerClass),this.$form,this.$form=a("<div>"),this.tip().is(this.innerCss)?this.tip().append(this.$form):this.tip().find(this.innerCss).append(this.$form),this.renderForm()},hide:function(a){if(this.tip()&&this.tip().is(":visible")&&this.$element.hasClass("editable-open")){if(this.$form.data("editableform").isSaving)return this.delayedHide={reason:a},void 0;this.delayedHide=!1,this.$element.removeClass("editable-open"),this.innerHide(),this.$element.triggerHandler("hidden",a||"manual")}},innerShow:function(){},innerHide:function(){},toggle:function(a){this.container()&&this.tip()&&this.tip().is(":visible")?this.hide():this.show(a)},setPosition:function(){},save:function(a,b){this.$element.triggerHandler("save",b),this.hide("save")},option:function(a,b){this.options[a]=b,a in this.containerOptions?(this.containerOptions[a]=b,this.setContainerOption(a,b)):(this.formOptions[a]=b,this.$form&&this.$form.editableform("option",a,b))},setContainerOption:function(a,b){this.call("option",a,b)},destroy:function(){this.hide(),this.innerDestroy(),this.$element.off("destroyed"),this.$element.removeData("editableContainer")},innerDestroy:function(){},closeOthers:function(b){a(".editable-open").each(function(c,d){if(d!==b&&!a(d).find(b).length){var e=a(d),f=e.data("editableContainer");f&&("cancel"===f.options.onblur?e.data("editableContainer").hide("onblur"):"submit"===f.options.onblur&&e.data("editableContainer").tip().find("form").submit())}})},activate:function(){this.tip&&this.tip().is(":visible")&&this.$form&&this.$form.data("editableform").input.activate()}},a.fn.editableContainer=function(d){var e=arguments;return this.each(function(){var f=a(this),g="editableContainer",h=f.data(g),i="object"==typeof d&&d,j="inline"===i.mode?c:b;h||f.data(g,h=new j(this,i)),"string"==typeof d&&h[d].apply(h,Array.prototype.slice.call(e,1))})},a.fn.editableContainer.Popup=b,a.fn.editableContainer.Inline=c,a.fn.editableContainer.defaults={value:null,placement:"top",autohide:!0,onblur:"cancel",anim:!1,mode:"popup"},jQuery.event.special.destroyed={remove:function(a){a.handler&&a.handler()}}}(window.jQuery),function(a){"use strict";a.extend(a.fn.editableContainer.Inline.prototype,a.fn.editableContainer.Popup.prototype,{containerName:"editableform",innerCss:".editable-inline",containerClass:"editable-container editable-inline",initContainer:function(){this.$tip=a("<span></span>"),this.options.anim||(this.options.anim=0)},splitOptions:function(){this.containerOptions={},this.formOptions=this.options},tip:function(){return this.$tip},innerShow:function(){this.$element.hide(),this.tip().insertAfter(this.$element).show()},innerHide:function(){this.$tip.hide(this.options.anim,a.proxy(function(){this.$element.show(),this.innerDestroy()},this))},innerDestroy:function(){this.tip()&&this.tip().empty().remove()}})}(window.jQuery),function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.editable.defaults,c,a.fn.editableutils.getConfigData(this.$element)),this.options.selector?this.initLive():this.init(),this.options.highlight&&!a.fn.editableutils.supportsTransitions()&&(this.options.highlight=!1)};b.prototype={constructor:b,init:function(){var b,c=!1;if(this.options.name=this.options.name||this.$element.attr("id"),this.options.scope=this.$element[0],this.input=a.fn.editableutils.createInput(this.options),this.input){switch(void 0===this.options.value||null===this.options.value?(this.value=this.input.html2value(a.trim(this.$element.html())),c=!0):(this.options.value=a.fn.editableutils.tryParseJson(this.options.value,!0),this.value="string"==typeof this.options.value?this.input.str2value(this.options.value):this.options.value),this.$element.addClass("editable"),"textarea"===this.input.type&&this.$element.addClass("editable-pre-wrapped"),"manual"!==this.options.toggle?(this.$element.addClass("editable-click"),this.$element.on(this.options.toggle+".editable",a.proxy(function(a){if(this.options.disabled||a.preventDefault(),"mouseenter"===this.options.toggle)this.show();else{var b="click"!==this.options.toggle;this.toggle(b)}},this))):this.$element.attr("tabindex",-1),"function"==typeof this.options.display&&(this.options.autotext="always"),this.options.autotext){case"always":b=!0;break;case"auto":b=!a.trim(this.$element.text()).length&&null!==this.value&&void 0!==this.value&&!c;break;default:b=!1}a.when(b?this.render():!0).then(a.proxy(function(){this.options.disabled?this.disable():this.enable(),this.$element.triggerHandler("init",this)},this))}},initLive:function(){var b=this.options.selector;this.options.selector=!1,this.options.autotext="never",this.$element.on(this.options.toggle+".editable",b,a.proxy(function(b){var c=a(b.target);c.data("editable")||(c.hasClass(this.options.emptyclass)&&c.empty(),c.editable(this.options).trigger(b))},this))},render:function(a){return this.options.display!==!1?this.input.value2htmlFinal?this.input.value2html(this.value,this.$element[0],this.options.display,a):"function"==typeof this.options.display?this.options.display.call(this.$element[0],this.value,a):this.input.value2html(this.value,this.$element[0]):void 0},enable:function(){this.options.disabled=!1,this.$element.removeClass("editable-disabled"),this.handleEmpty(this.isEmpty),"manual"!==this.options.toggle&&"-1"===this.$element.attr("tabindex")&&this.$element.removeAttr("tabindex")},disable:function(){this.options.disabled=!0,this.hide(),this.$element.addClass("editable-disabled"),this.handleEmpty(this.isEmpty),this.$element.attr("tabindex",-1)},toggleDisabled:function(){this.options.disabled?this.enable():this.disable()},option:function(b,c){return b&&"object"==typeof b?(a.each(b,a.proxy(function(b,c){this.option(a.trim(b),c)},this)),void 0):(this.options[b]=c,"disabled"===b?c?this.disable():this.enable():("value"===b&&this.setValue(c),this.container&&this.container.option(b,c),this.input.option&&this.input.option(b,c),void 0))},handleEmpty:function(b){this.options.display!==!1&&(this.isEmpty=void 0!==b?b:"function"==typeof this.input.isEmpty?this.input.isEmpty(this.$element):""===a.trim(this.$element.html()),this.options.disabled?this.isEmpty&&(this.$element.empty(),this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass)):this.isEmpty?(this.$element.html(this.options.emptytext),this.options.emptyclass&&this.$element.addClass(this.options.emptyclass)):this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass))},show:function(b){if(!this.options.disabled){if(this.container){if(this.container.tip().is(":visible"))return}else{var c=a.extend({},this.options,{value:this.value,input:this.input});this.$element.editableContainer(c),this.$element.on("save.internal",a.proxy(this.save,this)),this.container=this.$element.data("editableContainer")}this.container.show(b)}},hide:function(){this.container&&this.container.hide()},toggle:function(a){this.container&&this.container.tip().is(":visible")?this.hide():this.show(a)},save:function(a,b){if(this.options.unsavedclass){var c=!1;c=c||"function"==typeof this.options.url,c=c||this.options.display===!1,c=c||void 0!==b.response,c=c||this.options.savenochange&&this.input.value2str(this.value)!==this.input.value2str(b.newValue),c?this.$element.removeClass(this.options.unsavedclass):this.$element.addClass(this.options.unsavedclass)}if(this.options.highlight){var d=this.$element,e=d.css("background-color");d.css("background-color",this.options.highlight),setTimeout(function(){"transparent"===e&&(e=""),d.css("background-color",e),d.addClass("editable-bg-transition"),setTimeout(function(){d.removeClass("editable-bg-transition")},1700)},10)}this.setValue(b.newValue,!1,b.response)},validate:function(){return"function"==typeof this.options.validate?this.options.validate.call(this,this.value):void 0},setValue:function(b,c,d){this.value=c?this.input.str2value(b):b,this.container&&this.container.option("value",this.value),a.when(this.render(d)).then(a.proxy(function(){this.handleEmpty()},this))},activate:function(){this.container&&this.container.activate()},destroy:function(){this.disable(),this.container&&this.container.destroy(),this.input.destroy(),"manual"!==this.options.toggle&&(this.$element.removeClass("editable-click"),this.$element.off(this.options.toggle+".editable")),this.$element.off("save.internal"),this.$element.removeClass("editable editable-open editable-disabled"),this.$element.removeData("editable")}},a.fn.editable=function(c){var d={},e=arguments,f="editable";switch(c){case"validate":return this.each(function(){var b,c=a(this),e=c.data(f);e&&(b=e.validate())&&(d[e.options.name]=b)}),d;case"getValue":return 2===arguments.length&&arguments[1]===!0?d=this.eq(0).data(f).value:this.each(function(){var b=a(this),c=b.data(f);c&&void 0!==c.value&&null!==c.value&&(d[c.options.name]=c.input.value2submit(c.value))}),d;case"submit":var g=arguments[1]||{},h=this,i=this.editable("validate");if(a.isEmptyObject(i)){var j={};if(1===h.length){var k=h.data("editable"),l={name:k.options.name||"",value:k.input.value2submit(k.value),pk:"function"==typeof k.options.pk?k.options.pk.call(k.options.scope):k.options.pk};"function"==typeof k.options.params?l=k.options.params.call(k.options.scope,l):(k.options.params=a.fn.editableutils.tryParseJson(k.options.params,!0),a.extend(l,k.options.params)),j={url:k.options.url,data:l,type:"POST"},g.success=g.success||k.options.success,g.error=g.error||k.options.error}else{var m=this.editable("getValue");j={url:g.url,data:m,type:"POST"}}j.success="function"==typeof g.success?function(a){g.success.call(h,a,g)}:a.noop,j.error="function"==typeof g.error?function(){g.error.apply(h,arguments)}:a.noop,g.ajaxOptions&&a.extend(j,g.ajaxOptions),g.data&&a.extend(j.data,g.data),a.ajax(j)}else"function"==typeof g.error&&g.error.call(h,i);return this}return this.each(function(){var d=a(this),g=d.data(f),h="object"==typeof c&&c;return h&&h.selector?(g=new b(this,h),void 0):(g||d.data(f,g=new b(this,h)),"string"==typeof c&&g[c].apply(g,Array.prototype.slice.call(e,1)),void 0)})},a.fn.editable.defaults={type:"text",disabled:!1,toggle:"click",emptytext:"Empty",autotext:"auto",value:null,display:null,emptyclass:"editable-empty",unsavedclass:"editable-unsaved",selector:null,highlight:"#FFFF80"}}(window.jQuery),function(a){"use strict";a.fn.editabletypes={};var b=function(){};b.prototype={init:function(b,c,d){this.type=b,this.options=a.extend({},d,c)},prerender:function(){this.$tpl=a(this.options.tpl),this.$input=this.$tpl,this.$clear=null,this.error=null},render:function(){},value2html:function(b,c){a(c)[this.options.escape?"text":"html"](a.trim(b))},html2value:function(b){return a("<div>").html(b).text()},value2str:function(a){return a},str2value:function(a){return a},value2submit:function(a){return a},value2input:function(a){this.$input.val(a)},input2value:function(){return this.$input.val()},activate:function(){this.$input.is(":visible")&&this.$input.focus()},clear:function(){this.$input.val(null)},escape:function(b){return a("<div>").text(b).html()},autosubmit:function(){},destroy:function(){},setClass:function(){this.options.inputclass&&this.$input.addClass(this.options.inputclass)},setAttr:function(a){void 0!==this.options[a]&&null!==this.options[a]&&this.$input.attr(a,this.options[a])},option:function(a,b){this.options[a]=b}},b.defaults={tpl:"",inputclass:null,escape:!0,scope:null,showbuttons:!0},a.extend(a.fn.editabletypes,{abstractinput:b})}(window.jQuery),function(a){"use strict";var b=function(){};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){var b=a.Deferred();return this.error=null,this.onSourceReady(function(){this.renderList(),b.resolve()},function(){this.error=this.options.sourceError,b.resolve()}),b.promise()},html2value:function(){return null},value2html:function(b,c,d,e){var f=a.Deferred(),g=function(){"function"==typeof d?d.call(c,b,this.sourceData,e):this.value2htmlFinal(b,c),f.resolve()};return null===b?g.call(this):this.onSourceReady(g,function(){f.resolve()}),f.promise()},onSourceReady:function(b,c){var d;if(a.isFunction(this.options.source)?(d=this.options.source.call(this.options.scope),this.sourceData=null):d=this.options.source,this.options.sourceCache&&a.isArray(this.sourceData))return b.call(this),void 0;try{d=a.fn.editableutils.tryParseJson(d,!1)}catch(e){return c.call(this),void 0}if("string"==typeof d){if(this.options.sourceCache){var f,g=d;if(a(document).data(g)||a(document).data(g,{}),f=a(document).data(g),f.loading===!1&&f.sourceData)return this.sourceData=f.sourceData,this.doPrepend(),b.call(this),void 0;if(f.loading===!0)return f.callbacks.push(a.proxy(function(){this.sourceData=f.sourceData,this.doPrepend(),b.call(this)},this)),f.err_callbacks.push(a.proxy(c,this)),void 0;f.loading=!0,f.callbacks=[],f.err_callbacks=[]}var h=a.extend({url:d,type:"get",cache:!1,dataType:"json",success:a.proxy(function(d){f&&(f.loading=!1),this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(f&&(f.sourceData=this.sourceData,a.each(f.callbacks,function(){this.call()})),this.doPrepend(),b.call(this)):(c.call(this),f&&a.each(f.err_callbacks,function(){this.call()}))},this),error:a.proxy(function(){c.call(this),f&&(f.loading=!1,a.each(f.err_callbacks,function(){this.call()}))},this)},this.options.sourceOptions);a.ajax(h)}else this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(this.doPrepend(),b.call(this)):c.call(this)},doPrepend:function(){null!==this.options.prepend&&void 0!==this.options.prepend&&(a.isArray(this.prependData)||(a.isFunction(this.options.prepend)&&(this.options.prepend=this.options.prepend.call(this.options.scope)),this.options.prepend=a.fn.editableutils.tryParseJson(this.options.prepend,!0),"string"==typeof this.options.prepend&&(this.options.prepend={"":this.options.prepend}),this.prependData=this.makeArray(this.options.prepend)),a.isArray(this.prependData)&&a.isArray(this.sourceData)&&(this.sourceData=this.prependData.concat(this.sourceData)))},renderList:function(){},value2htmlFinal:function(){},makeArray:function(b){var c,d,e,f,g=[];if(!b||"string"==typeof b)return null;if(a.isArray(b)){f=function(a,b){return d={value:a,text:b},c++>=2?!1:void 0};for(var h=0;h<b.length;h++)e=b[h],"object"==typeof e?(c=0,a.each(e,f),1===c?g.push(d):c>1&&(e.children&&(e.children=this.makeArray(e.children)),g.push(e))):g.push({value:e,text:e})}else a.each(b,function(a,b){g.push({value:a,text:b})});return g},option:function(a,b){this.options[a]=b,"source"===a&&(this.sourceData=null),"prepend"===a&&(this.prependData=null)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{source:null,prepend:!1,sourceError:"Error when loading list",sourceCache:!0,sourceOptions:null}),a.fn.editabletypes.list=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("text",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.renderClear(),this.setClass(),this.setAttr("placeholder")},activate:function(){this.$input.is(":visible")&&(this.$input.focus(),a.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length),this.toggleClear&&this.toggleClear())},renderClear:function(){this.options.clear&&(this.$clear=a('<span class="editable-clear-x"></span>'),this.$input.after(this.$clear).css("padding-right",24).keyup(a.proxy(function(b){if(!~a.inArray(b.keyCode,[40,38,9,13,27])){clearTimeout(this.t);var c=this;this.t=setTimeout(function(){c.toggleClear(b)},100)}},this)).parent().css("position","relative"),this.$clear.click(a.proxy(this.clear,this)))},postrender:function(){},toggleClear:function(){if(this.$clear){var a=this.$input.val().length,b=this.$clear.is(":visible");a&&!b&&this.$clear.show(),!a&&b&&this.$clear.hide()}},clear:function(){this.$clear.hide(),this.$input.val("").focus()}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',placeholder:null,clear:!0}),a.fn.editabletypes.text=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("textarea",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass(),this.setAttr("placeholder"),this.setAttr("rows"),this.$input.keydown(function(b){b.ctrlKey&&13===b.which&&a(this).closest("form").submit()})},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:"<textarea></textarea>",inputclass:"input-large",placeholder:null,rows:7}),a.fn.editabletypes.textarea=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("select",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){this.$input.empty();var b=function(c,d){var e;if(a.isArray(d))for(var f=0;f<d.length;f++)e={},d[f].children?(e.label=d[f].text,c.append(b(a("<optgroup>",e),d[f].children))):(e.value=d[f].value,d[f].disabled&&(e.disabled=!0),c.append(a("<option>",e).text(d[f].text)));return c};b(this.$input,this.sourceData),this.setClass(),this.$input.on("keydown.editable",function(b){13===b.which&&a(this).closest("form").submit()})},value2htmlFinal:function(b,c){var d="",e=a.fn.editableutils.itemsByValue(b,this.sourceData);e.length&&(d=e[0].text),a.fn.editabletypes.abstractinput.prototype.value2html.call(this,d,c)},autosubmit:function(){this.$input.off("keydown.editable").on("change.editable",function(){a(this).closest("form").submit()})}}),b.defaults=a.extend({},a.fn.editabletypes.list.defaults,{tpl:"<select></select>"}),a.fn.editabletypes.select=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("checklist",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){var b;if(this.$tpl.empty(),a.isArray(this.sourceData)){for(var c=0;c<this.sourceData.length;c++)b=a("<label>").append(a("<input>",{type:"checkbox",value:this.sourceData[c].value})).append(a("<span>").text(" "+this.sourceData[c].text)),a("<div>").append(b).appendTo(this.$tpl);this.$input=this.$tpl.find('input[type="checkbox"]'),this.setClass()}},value2str:function(b){return a.isArray(b)?b.sort().join(a.trim(this.options.separator)):""},str2value:function(b){var c,d=null;return"string"==typeof b&&b.length?(c=new RegExp("\\s*"+a.trim(this.options.separator)+"\\s*"),d=b.split(c)):d=a.isArray(b)?b:[b],d},value2input:function(b){this.$input.prop("checked",!1),a.isArray(b)&&b.length&&this.$input.each(function(c,d){var e=a(d);a.each(b,function(a,b){e.val()==b&&e.prop("checked",!0)})})},input2value:function(){var b=[];return this.$input.filter(":checked").each(function(c,d){b.push(a(d).val())}),b},value2htmlFinal:function(b,c){var d=[],e=a.fn.editableutils.itemsByValue(b,this.sourceData),f=this.options.escape;e.length?(a.each(e,function(b,c){var e=f?a.fn.editableutils.escape(c.text):c.text;d.push(e)}),a(c).html(d.join("<br>"))):a(c).empty()},activate:function(){this.$input.first().focus()},autosubmit:function(){this.$input.on("keydown",function(b){13===b.which&&a(this).closest("form").submit()})}}),b.defaults=a.extend({},a.fn.editabletypes.list.defaults,{tpl:'<div class="editable-checklist"></div>',inputclass:null,separator:","}),a.fn.editabletypes.checklist=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("password",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),a.extend(b.prototype,{value2html:function(b,c){b?a(c).text("[hidden]"):a(c).empty()},html2value:function(){return null}}),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="password">'}),a.fn.editabletypes.password=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("email",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="email">'}),a.fn.editabletypes.email=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("url",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="url">'}),a.fn.editabletypes.url=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("tel",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="tel">'}),a.fn.editabletypes.tel=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("number",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),a.extend(b.prototype,{render:function(){b.superclass.render.call(this),this.setAttr("min"),this.setAttr("max"),this.setAttr("step")},postrender:function(){this.$clear&&this.$clear.css({right:24})}}),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="number">',inputclass:"input-mini",min:null,max:null,step:null}),a.fn.editabletypes.number=b}(window.jQuery),function(a){"use strict"; +var b=function(a){this.init("range",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.number),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.filter("input"),this.setClass(),this.setAttr("min"),this.setAttr("max"),this.setAttr("step"),this.$input.on("input",function(){a(this).siblings("output").text(a(this).val())})},activate:function(){this.$input.focus()}}),b.defaults=a.extend({},a.fn.editabletypes.number.defaults,{tpl:'<input type="range"><output style="width: 30px; display: inline-block"></output>',inputclass:"input-medium"}),a.fn.editabletypes.range=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("time",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass()}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="time">'}),a.fn.editabletypes.time=b}(window.jQuery),function(a){"use strict";var b=function(c){if(this.init("select2",c,b.defaults),c.select2=c.select2||{},this.sourceData=null,c.placeholder&&(c.select2.placeholder=c.placeholder),!c.select2.tags&&c.source){var d=c.source;a.isFunction(c.source)&&(d=c.source.call(c.scope)),"string"==typeof d?(c.select2.ajax=c.select2.ajax||{},c.select2.ajax.data||(c.select2.ajax.data=function(a){return{query:a}}),c.select2.ajax.results||(c.select2.ajax.results=function(a){return{results:a}}),c.select2.ajax.url=d):(this.sourceData=this.convertSource(d),c.select2.data=this.sourceData)}if(this.options.select2=a.extend({},b.defaults.select2,c.select2),this.isMultiple=this.options.select2.tags||this.options.select2.multiple,this.isRemote="ajax"in this.options.select2,this.idFunc=this.options.select2.id,"function"!=typeof this.idFunc){var e=this.idFunc||"id";this.idFunc=function(a){return a[e]}}this.formatSelection=this.options.select2.formatSelection,"function"!=typeof this.formatSelection&&(this.formatSelection=function(a){return a.text})};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass(),this.isRemote&&this.$input.on("select2-loaded",a.proxy(function(a){this.sourceData=a.items.results},this)),this.isMultiple&&this.$input.on("change",function(){a(this).closest("form").parent().triggerHandler("resize")})},value2html:function(c,d){var e,f="",g=this;this.options.select2.tags?e=c:this.sourceData&&(e=a.fn.editableutils.itemsByValue(c,this.sourceData,this.idFunc)),a.isArray(e)?(f=[],a.each(e,function(a,b){f.push(b&&"object"==typeof b?g.formatSelection(b):b)})):e&&(f=g.formatSelection(e)),f=a.isArray(f)?f.join(this.options.viewseparator):f,b.superclass.value2html.call(this,f,d)},html2value:function(a){return this.options.select2.tags?this.str2value(a,this.options.viewseparator):null},value2input:function(b){if(a.isArray(b)&&(b=b.join(this.getSeparator())),this.$input.data("select2")?this.$input.val(b).trigger("change",!0):(this.$input.val(b),this.$input.select2(this.options.select2)),this.isRemote&&!this.isMultiple&&!this.options.select2.initSelection){var c=this.options.select2.id,d=this.options.select2.formatSelection;if(!c&&!d){var e=a(this.options.scope);if(!e.data("editable").isEmpty){var f={id:b,text:e.text()};this.$input.select2("data",f)}}}},input2value:function(){return this.$input.select2("val")},str2value:function(b,c){if("string"!=typeof b||!this.isMultiple)return b;c=c||this.getSeparator();var d,e,f;if(null===b||b.length<1)return null;for(d=b.split(c),e=0,f=d.length;f>e;e+=1)d[e]=a.trim(d[e]);return d},autosubmit:function(){this.$input.on("change",function(b,c){c||a(this).closest("form").submit()})},getSeparator:function(){return this.options.select2.separator||a.fn.select2.defaults.separator},convertSource:function(b){if(a.isArray(b)&&b.length&&void 0!==b[0].value)for(var c=0;c<b.length;c++)void 0!==b[c].value&&(b[c].id=b[c].value,delete b[c].value);return b},destroy:function(){this.$input.data("select2")&&this.$input.select2("destroy")}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="hidden">',select2:null,placeholder:null,source:null,viewseparator:", "}),a.fn.editabletypes.select2=b}(window.jQuery),function(a){var b=function(b,c){return this.$element=a(b),this.$element.is("input")?(this.options=a.extend({},a.fn.combodate.defaults,c,this.$element.data()),this.init(),void 0):(a.error("Combodate should be applied to INPUT element"),void 0)};b.prototype={constructor:b,init:function(){this.map={day:["D","date"],month:["M","month"],year:["Y","year"],hour:["[Hh]","hours"],minute:["m","minutes"],second:["s","seconds"],ampm:["[Aa]",""]},this.$widget=a('<span class="combodate"></span>').html(this.getTemplate()),this.initCombos(),this.$widget.on("change","select",a.proxy(function(b){this.$element.val(this.getValue()).change(),this.options.smartDays&&(a(b.target).is(".month")||a(b.target).is(".year"))&&this.fillCombo("day")},this)),this.$widget.find("select").css("width","auto"),this.$element.hide().after(this.$widget),this.setValue(this.$element.val()||this.options.value)},getTemplate:function(){var b=this.options.template;return a.each(this.map,function(a,c){c=c[0];var d=new RegExp(c+"+"),e=c.length>1?c.substring(1,2):c;b=b.replace(d,"{"+e+"}")}),b=b.replace(/ /g,"&nbsp;"),a.each(this.map,function(a,c){c=c[0];var d=c.length>1?c.substring(1,2):c;b=b.replace("{"+d+"}",'<select class="'+a+'"></select>')}),b},initCombos:function(){for(var a in this.map){var b=this.$widget.find("."+a);this["$"+a]=b.length?b:null,this.fillCombo(a)}},fillCombo:function(a){var b=this["$"+a];if(b){var c="fill"+a.charAt(0).toUpperCase()+a.slice(1),d=this[c](),e=b.val();b.empty();for(var f=0;f<d.length;f++)b.append('<option value="'+d[f][0]+'">'+d[f][1]+"</option>");b.val(e)}},fillCommon:function(a){var b,c=[];if("name"===this.options.firstItem){b=moment.relativeTime||moment.langData()._relativeTime;var d="function"==typeof b[a]?b[a](1,!0,a,!1):b[a];d=d.split(" ").reverse()[0],c.push(["",d])}else"empty"===this.options.firstItem&&c.push(["",""]);return c},fillDay:function(){var a,b,c=this.fillCommon("d"),d=-1!==this.options.template.indexOf("DD"),e=31;if(this.options.smartDays&&this.$month&&this.$year){var f=parseInt(this.$month.val(),10),g=parseInt(this.$year.val(),10);isNaN(f)||isNaN(g)||(e=moment([g,f]).daysInMonth())}for(b=1;e>=b;b++)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillMonth:function(){var a,b,c=this.fillCommon("M"),d=-1!==this.options.template.indexOf("MMMM"),e=-1!==this.options.template.indexOf("MMM"),f=-1!==this.options.template.indexOf("MM");for(b=0;11>=b;b++)a=d?moment().date(1).month(b).format("MMMM"):e?moment().date(1).month(b).format("MMM"):f?this.leadZero(b+1):b+1,c.push([b,a]);return c},fillYear:function(){var a,b,c=[],d=-1!==this.options.template.indexOf("YYYY");for(b=this.options.maxYear;b>=this.options.minYear;b--)a=d?b:(b+"").substring(2),c[this.options.yearDescending?"push":"unshift"]([b,a]);return c=this.fillCommon("y").concat(c)},fillHour:function(){var a,b,c=this.fillCommon("h"),d=-1!==this.options.template.indexOf("h"),e=(-1!==this.options.template.indexOf("H"),-1!==this.options.template.toLowerCase().indexOf("hh")),f=d?1:0,g=d?12:23;for(b=f;g>=b;b++)a=e?this.leadZero(b):b,c.push([b,a]);return c},fillMinute:function(){var a,b,c=this.fillCommon("m"),d=-1!==this.options.template.indexOf("mm");for(b=0;59>=b;b+=this.options.minuteStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillSecond:function(){var a,b,c=this.fillCommon("s"),d=-1!==this.options.template.indexOf("ss");for(b=0;59>=b;b+=this.options.secondStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillAmpm:function(){var a=-1!==this.options.template.indexOf("a"),b=(-1!==this.options.template.indexOf("A"),[["am",a?"am":"AM"],["pm",a?"pm":"PM"]]);return b},getValue:function(b){var c,d={},e=this,f=!1;return a.each(this.map,function(a){if("ampm"!==a){var b="day"===a?1:0;return d[a]=e["$"+a]?parseInt(e["$"+a].val(),10):b,isNaN(d[a])?(f=!0,!1):void 0}}),f?"":(this.$ampm&&(d.hour=12===d.hour?"am"===this.$ampm.val()?0:12:"am"===this.$ampm.val()?d.hour:d.hour+12),c=moment([d.year,d.month,d.day,d.hour,d.minute,d.second]),this.highlight(c),b=void 0===b?this.options.format:b,null===b?c.isValid()?c:null:c.isValid()?c.format(b):"")},setValue:function(b){function c(b,c){var d={};return b.children("option").each(function(b,e){var f,g=a(e).attr("value");""!==g&&(f=Math.abs(g-c),("undefined"==typeof d.distance||f<d.distance)&&(d={value:g,distance:f}))}),d.value}if(b){var d="string"==typeof b?moment(b,this.options.format):moment(b),e=this,f={};d.isValid()&&(a.each(this.map,function(a,b){"ampm"!==a&&(f[a]=d[b[1]]())}),this.$ampm&&(f.hour>=12?(f.ampm="pm",f.hour>12&&(f.hour-=12)):(f.ampm="am",0===f.hour&&(f.hour=12))),a.each(f,function(a,b){e["$"+a]&&("minute"===a&&e.options.minuteStep>1&&e.options.roundTime&&(b=c(e["$"+a],b)),"second"===a&&e.options.secondStep>1&&e.options.roundTime&&(b=c(e["$"+a],b)),e["$"+a].val(b))}),this.options.smartDays&&this.fillCombo("day"),this.$element.val(d.format(this.options.format)).change())}},highlight:function(a){a.isValid()?this.options.errorClass?this.$widget.removeClass(this.options.errorClass):this.$widget.find("select").css("border-color",this.borderColor):this.options.errorClass?this.$widget.addClass(this.options.errorClass):(this.borderColor||(this.borderColor=this.$widget.find("select").css("border-color")),this.$widget.find("select").css("border-color","red"))},leadZero:function(a){return 9>=a?"0"+a:a},destroy:function(){this.$widget.remove(),this.$element.removeData("combodate").show()}},a.fn.combodate=function(c){var d,e=Array.apply(null,arguments);return e.shift(),"getValue"===c&&this.length&&(d=this.eq(0).data("combodate"))?d.getValue.apply(d,e):this.each(function(){var d=a(this),f=d.data("combodate"),g="object"==typeof c&&c;f||d.data("combodate",f=new b(this,g)),"string"==typeof c&&"function"==typeof f[c]&&f[c].apply(f,e)})},a.fn.combodate.defaults={format:"DD-MM-YYYY HH:mm",template:"D / MMM / YYYY H : mm",value:null,minYear:1970,maxYear:2015,yearDescending:!0,minuteStep:5,secondStep:1,firstItem:"empty",errorClass:null,roundTime:!0,smartDays:!1}}(window.jQuery),function(a){"use strict";var b=function(c){this.init("combodate",c,b.defaults),this.options.viewformat||(this.options.viewformat=this.options.format),c.combodate=a.fn.editableutils.tryParseJson(c.combodate,!0),this.options.combodate=a.extend({},b.defaults.combodate,c.combodate,{format:this.options.format,template:this.options.template})};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.$input.combodate(this.options.combodate),"bs3"===a.fn.editableform.engine&&this.$input.siblings().find("select").addClass("form-control"),this.options.inputclass&&this.$input.siblings().find("select").addClass(this.options.inputclass)},value2html:function(a,c){var d=a?a.format(this.options.viewformat):"";b.superclass.value2html.call(this,d,c)},html2value:function(a){return a?moment(a,this.options.viewformat):null},value2str:function(a){return a?a.format(this.options.format):""},str2value:function(a){return a?moment(a,this.options.format):null},value2submit:function(a){return this.value2str(a)},value2input:function(a){this.$input.combodate("setValue",a)},input2value:function(){return this.$input.combodate("getValue",null)},activate:function(){this.$input.siblings(".combodate").find("select").eq(0).focus()},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',inputclass:null,format:"YYYY-MM-DD",viewformat:null,template:"D / MMM / YYYY",combodate:null}),a.fn.editabletypes.combodate=b}(window.jQuery),function(a){"use strict";var b=a.fn.editableform.Constructor.prototype.initInput;a.extend(a.fn.editableform.Constructor.prototype,{initTemplate:function(){this.$form=a(a.fn.editableform.template),this.$form.find(".editable-error-block").addClass("help-block")},initInput:function(){b.apply(this);var c=null===this.input.options.inputclass||this.input.options.inputclass===!1,d="input-medium",e="text,select,textarea,password,email,url,tel,number,range,time".split(",");~a.inArray(this.input.type,e)&&c&&(this.input.options.inputclass=d,this.input.$input.addClass(d))}}),a.fn.editableform.buttons='<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button><button type="button" class="btn editable-cancel"><i class="icon-remove"></i></button>',a.fn.editableform.errorGroupClass="error",a.fn.editableform.errorBlockClass=null,a.fn.editableform.engine="bs2"}(window.jQuery),function(a){"use strict";a.extend(a.fn.editableContainer.Popup.prototype,{containerName:"popover",innerCss:a.fn.popover&&a(a.fn.popover.defaults.template).find("p").length?".popover-content p":".popover-content",defaults:a.fn.popover.defaults,initContainer:function(){a.extend(this.containerOptions,{trigger:"manual",selector:!1,content:" ",template:this.defaults.template});var b;this.$element.data("template")&&(b=this.$element.data("template"),this.$element.removeData("template")),this.call(this.containerOptions),b&&this.$element.data("template",b)},innerShow:function(){this.call("show")},innerHide:function(){this.call("hide")},innerDestroy:function(){this.call("destroy")},setContainerOption:function(a,b){this.container().options[a]=b},setPosition:function(){!function(){var b,c,d,e,f,g,h,i,j,k,l=this.tip();switch(f="function"==typeof this.options.placement?this.options.placement.call(this,l[0],this.$element[0]):this.options.placement,b=/in/.test(f),l.removeClass("top right bottom left").css({top:0,left:0,display:"block"}),c=this.getPosition(b),d=l[0].offsetWidth,e=l[0].offsetHeight,f=b?f.split(" ")[1]:f,i={top:c.top+c.height,left:c.left+c.width/2-d/2},h={top:c.top-e,left:c.left+c.width/2-d/2},j={top:c.top+c.height/2-e/2,left:c.left-d},k={top:c.top+c.height/2-e/2,left:c.left+c.width},f){case"bottom":i.top+e>a(window).scrollTop()+a(window).height()&&(f=h.top>a(window).scrollTop()?"top":k.left+d<a(window).scrollLeft()+a(window).width()?"right":j.left>a(window).scrollLeft()?"left":"right");break;case"top":h.top<a(window).scrollTop()&&(f=i.top+e<a(window).scrollTop()+a(window).height()?"bottom":k.left+d<a(window).scrollLeft()+a(window).width()?"right":j.left>a(window).scrollLeft()?"left":"right");break;case"left":j.left<a(window).scrollLeft()&&(f=k.left+d<a(window).scrollLeft()+a(window).width()?"right":h.top>a(window).scrollTop()?"top":h.top>a(window).scrollTop()?"bottom":"right");break;case"right":k.left+d>a(window).scrollLeft()+a(window).width()&&(j.left>a(window).scrollLeft()?f="left":h.top>a(window).scrollTop()?f="top":h.top>a(window).scrollTop()&&(f="bottom"))}switch(f){case"bottom":g=i;break;case"top":g=h;break;case"left":g=j;break;case"right":g=k}l.offset(g).addClass(f).addClass("in")}.call(this.container())}})}(window.jQuery),function(a){function b(){return new Date(Date.UTC.apply(Date,arguments))}function c(b,c){var d,e=a(b).data(),f={},g=new RegExp("^"+c.toLowerCase()+"([A-Z])"),c=new RegExp("^"+c.toLowerCase());for(var h in e)c.test(h)&&(d=h.replace(g,function(a,b){return b.toLowerCase()}),f[d]=e[h]);return f}function d(b){var c={};if(k[b]||(b=b.split("-")[0],k[b])){var d=k[b];return a.each(j,function(a,b){b in d&&(c[b]=d[b])}),c}}var e=function(b,c){this._process_options(c),this.element=a(b),this.isInline=!1,this.isInput=this.element.is("input"),this.component=this.element.is(".date")?this.element.find(".add-on, .btn"):!1,this.hasInput=this.component&&this.element.find("input").length,this.component&&0===this.component.length&&(this.component=!1),this.picker=a(l.template),this._buildEvents(),this._attachEvents(),this.isInline?this.picker.addClass("datepicker-inline").appendTo(this.element):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.o.rtl&&(this.picker.addClass("datepicker-rtl"),this.picker.find(".prev i, .next i").toggleClass("icon-arrow-left icon-arrow-right")),this.viewMode=this.o.startView,this.o.calendarWeeks&&this.picker.find("tfoot th.today").attr("colspan",function(a,b){return parseInt(b)+1}),this._allow_update=!1,this.setStartDate(this.o.startDate),this.setEndDate(this.o.endDate),this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled),this.fillDow(),this.fillMonths(),this._allow_update=!0,this.update(),this.showMode(),this.isInline&&this.show()};e.prototype={constructor:e,_process_options:function(b){this._o=a.extend({},this._o,b);var c=this.o=a.extend({},this._o),d=c.language;switch(k[d]||(d=d.split("-")[0],k[d]||(d=i.language)),c.language=d,c.startView){case 2:case"decade":c.startView=2;break;case 1:case"year":c.startView=1;break;default:c.startView=0}switch(c.minViewMode){case 1:case"months":c.minViewMode=1;break;case 2:case"years":c.minViewMode=2;break;default:c.minViewMode=0}c.startView=Math.max(c.startView,c.minViewMode),c.weekStart%=7,c.weekEnd=(c.weekStart+6)%7;var e=l.parseFormat(c.format);c.startDate!==-1/0&&(c.startDate=l.parseDate(c.startDate,e,c.language)),1/0!==c.endDate&&(c.endDate=l.parseDate(c.endDate,e,c.language)),c.daysOfWeekDisabled=c.daysOfWeekDisabled||[],a.isArray(c.daysOfWeekDisabled)||(c.daysOfWeekDisabled=c.daysOfWeekDisabled.split(/[,\s]*/)),c.daysOfWeekDisabled=a.map(c.daysOfWeekDisabled,function(a){return parseInt(a,10)})},_events:[],_secondaryEvents:[],_applyEvents:function(a){for(var b,c,d=0;d<a.length;d++)b=a[d][0],c=a[d][1],b.on(c)},_unapplyEvents:function(a){for(var b,c,d=0;d<a.length;d++)b=a[d][0],c=a[d][1],b.off(c)},_buildEvents:function(){this.isInput?this._events=[[this.element,{focus:a.proxy(this.show,this),keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}]]:this.component&&this.hasInput?this._events=[[this.element.find("input"),{focus:a.proxy(this.show,this),keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}],[this.component,{click:a.proxy(this.show,this)}]]:this.element.is("div")?this.isInline=!0:this._events=[[this.element,{click:a.proxy(this.show,this)}]],this._secondaryEvents=[[this.picker,{click:a.proxy(this.click,this)}],[a(window),{resize:a.proxy(this.place,this)}],[a(document),{mousedown:a.proxy(function(a){this.element.is(a.target)||this.element.find(a.target).size()||this.picker.is(a.target)||this.picker.find(a.target).size()||this.hide()},this)}]]},_attachEvents:function(){this._detachEvents(),this._applyEvents(this._events)},_detachEvents:function(){this._unapplyEvents(this._events)},_attachSecondaryEvents:function(){this._detachSecondaryEvents(),this._applyEvents(this._secondaryEvents)},_detachSecondaryEvents:function(){this._unapplyEvents(this._secondaryEvents)},_trigger:function(b,c){var d=c||this.date,e=new Date(d.getTime()+6e4*d.getTimezoneOffset());this.element.trigger({type:b,date:e,format:a.proxy(function(a){var b=a||this.o.format;return l.formatDate(d,b,this.o.language)},this)})},show:function(a){this.isInline||this.picker.appendTo("body"),this.picker.show(),this.height=this.component?this.component.outerHeight():this.element.outerHeight(),this.place(),this._attachSecondaryEvents(),a&&a.preventDefault(),this._trigger("show")},hide:function(){this.isInline||this.picker.is(":visible")&&(this.picker.hide().detach(),this._detachSecondaryEvents(),this.viewMode=this.o.startView,this.showMode(),this.o.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())&&this.setValue(),this._trigger("hide"))},remove:function(){this.hide(),this._detachEvents(),this._detachSecondaryEvents(),this.picker.remove(),delete this.element.data().datepicker,this.isInput||delete this.element.data().date},getDate:function(){var a=this.getUTCDate();return new Date(a.getTime()+6e4*a.getTimezoneOffset())},getUTCDate:function(){return this.date},setDate:function(a){this.setUTCDate(new Date(a.getTime()-6e4*a.getTimezoneOffset()))},setUTCDate:function(a){this.date=a,this.setValue()},setValue:function(){var a=this.getFormattedDate();this.isInput?this.element.val(a):this.component&&this.element.find("input").val(a)},getFormattedDate:function(a){return void 0===a&&(a=this.o.format),l.formatDate(this.date,a,this.o.language)},setStartDate:function(a){this._process_options({startDate:a}),this.update(),this.updateNavArrows()},setEndDate:function(a){this._process_options({endDate:a}),this.update(),this.updateNavArrows()},setDaysOfWeekDisabled:function(a){this._process_options({daysOfWeekDisabled:a}),this.update(),this.updateNavArrows()},place:function(){if(!this.isInline){var b=parseInt(this.element.parents().filter(function(){return"auto"!=a(this).css("z-index")}).first().css("z-index"))+10,c=this.component?this.component.parent().offset():this.element.offset(),d=this.component?this.component.outerHeight(!0):this.element.outerHeight(!0);this.picker.css({top:c.top+d,left:c.left,zIndex:b})}},_allow_update:!0,update:function(){if(this._allow_update){var a,b=!1;arguments&&arguments.length&&("string"==typeof arguments[0]||arguments[0]instanceof Date)?(a=arguments[0],b=!0):(a=this.isInput?this.element.val():this.element.data("date")||this.element.find("input").val(),delete this.element.data().date),this.date=l.parseDate(a,this.o.format,this.o.language),b&&this.setValue(),this.viewDate=this.date<this.o.startDate?new Date(this.o.startDate):this.date>this.o.endDate?new Date(this.o.endDate):new Date(this.date),this.fill()}},fillDow:function(){var a=this.o.weekStart,b="<tr>";if(this.o.calendarWeeks){var c='<th class="cw">&nbsp;</th>';b+=c,this.picker.find(".datepicker-days thead tr:first-child").prepend(c)}for(;a<this.o.weekStart+7;)b+='<th class="dow">'+k[this.o.language].daysMin[a++%7]+"</th>";b+="</tr>",this.picker.find(".datepicker-days thead").append(b)},fillMonths:function(){for(var a="",b=0;12>b;)a+='<span class="month">'+k[this.o.language].monthsShort[b++]+"</span>";this.picker.find(".datepicker-months td").html(a)},setRange:function(b){b&&b.length?this.range=a.map(b,function(a){return a.valueOf()}):delete this.range,this.fill()},getClassNames:function(b){var c=[],d=this.viewDate.getUTCFullYear(),e=this.viewDate.getUTCMonth(),f=this.date.valueOf(),g=new Date;return b.getUTCFullYear()<d||b.getUTCFullYear()==d&&b.getUTCMonth()<e?c.push("old"):(b.getUTCFullYear()>d||b.getUTCFullYear()==d&&b.getUTCMonth()>e)&&c.push("new"),this.o.todayHighlight&&b.getUTCFullYear()==g.getFullYear()&&b.getUTCMonth()==g.getMonth()&&b.getUTCDate()==g.getDate()&&c.push("today"),f&&b.valueOf()==f&&c.push("active"),(b.valueOf()<this.o.startDate||b.valueOf()>this.o.endDate||-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekDisabled))&&c.push("disabled"),this.range&&(b>this.range[0]&&b<this.range[this.range.length-1]&&c.push("range"),-1!=a.inArray(b.valueOf(),this.range)&&c.push("selected")),c},fill:function(){var c,d=new Date(this.viewDate),e=d.getUTCFullYear(),f=d.getUTCMonth(),g=this.o.startDate!==-1/0?this.o.startDate.getUTCFullYear():-1/0,h=this.o.startDate!==-1/0?this.o.startDate.getUTCMonth():-1/0,i=1/0!==this.o.endDate?this.o.endDate.getUTCFullYear():1/0,j=1/0!==this.o.endDate?this.o.endDate.getUTCMonth():1/0;this.date&&this.date.valueOf(),this.picker.find(".datepicker-days thead th.datepicker-switch").text(k[this.o.language].months[f]+" "+e),this.picker.find("tfoot th.today").text(k[this.o.language].today).toggle(this.o.todayBtn!==!1),this.picker.find("tfoot th.clear").text(k[this.o.language].clear).toggle(this.o.clearBtn!==!1),this.updateNavArrows(),this.fillMonths();var m=b(e,f-1,28,0,0,0,0),n=l.getDaysInMonth(m.getUTCFullYear(),m.getUTCMonth());m.setUTCDate(n),m.setUTCDate(n-(m.getUTCDay()-this.o.weekStart+7)%7);var o=new Date(m);o.setUTCDate(o.getUTCDate()+42),o=o.valueOf();for(var p,q=[];m.valueOf()<o;){if(m.getUTCDay()==this.o.weekStart&&(q.push("<tr>"),this.o.calendarWeeks)){var r=new Date(+m+864e5*((this.o.weekStart-m.getUTCDay()-7)%7)),s=new Date(+r+864e5*((11-r.getUTCDay())%7)),t=new Date(+(t=b(s.getUTCFullYear(),0,1))+864e5*((11-t.getUTCDay())%7)),u=(s-t)/864e5/7+1;q.push('<td class="cw">'+u+"</td>")}p=this.getClassNames(m),p.push("day");var v=this.o.beforeShowDay(m);void 0===v?v={}:"boolean"==typeof v?v={enabled:v}:"string"==typeof v&&(v={classes:v}),v.enabled===!1&&p.push("disabled"),v.classes&&(p=p.concat(v.classes.split(/\s+/))),v.tooltip&&(c=v.tooltip),p=a.unique(p),q.push('<td class="'+p.join(" ")+'"'+(c?' title="'+c+'"':"")+">"+m.getUTCDate()+"</td>"),m.getUTCDay()==this.o.weekEnd&&q.push("</tr>"),m.setUTCDate(m.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(q.join(""));var w=this.date&&this.date.getUTCFullYear(),x=this.picker.find(".datepicker-months").find("th:eq(1)").text(e).end().find("span").removeClass("active");w&&w==e&&x.eq(this.date.getUTCMonth()).addClass("active"),(g>e||e>i)&&x.addClass("disabled"),e==g&&x.slice(0,h).addClass("disabled"),e==i&&x.slice(j+1).addClass("disabled"),q="",e=10*parseInt(e/10,10);var y=this.picker.find(".datepicker-years").find("th:eq(1)").text(e+"-"+(e+9)).end().find("td");e-=1;for(var z=-1;11>z;z++)q+='<span class="year'+(-1==z?" old":10==z?" new":"")+(w==e?" active":"")+(g>e||e>i?" disabled":"")+'">'+e+"</span>",e+=1;y.html(q)},updateNavArrows:function(){if(this._allow_update){var a=new Date(this.viewDate),b=a.getUTCFullYear(),c=a.getUTCMonth();switch(this.viewMode){case 0:this.o.startDate!==-1/0&&b<=this.o.startDate.getUTCFullYear()&&c<=this.o.startDate.getUTCMonth()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),1/0!==this.o.endDate&&b>=this.o.endDate.getUTCFullYear()&&c>=this.o.endDate.getUTCMonth()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 1:case 2:this.o.startDate!==-1/0&&b<=this.o.startDate.getUTCFullYear()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),1/0!==this.o.endDate&&b>=this.o.endDate.getUTCFullYear()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"})}}},click:function(c){c.preventDefault();var d=a(c.target).closest("span, td, th");if(1==d.length)switch(d[0].nodeName.toLowerCase()){case"th":switch(d[0].className){case"datepicker-switch":this.showMode(1);break;case"prev":case"next":var e=l.modes[this.viewMode].navStep*("prev"==d[0].className?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,e);break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,e)}this.fill();break;case"today":var f=new Date;f=b(f.getFullYear(),f.getMonth(),f.getDate(),0,0,0),this.showMode(-2);var g="linked"==this.o.todayBtn?null:"view";this._setDate(f,g);break;case"clear":var h;this.isInput?h=this.element:this.component&&(h=this.element.find("input")),h&&h.val("").change(),this._trigger("changeDate"),this.update(),this.o.autoclose&&this.hide()}break;case"span":if(!d.is(".disabled")){if(this.viewDate.setUTCDate(1),d.is(".month")){var i=1,j=d.parent().find("span").index(d),k=this.viewDate.getUTCFullYear();this.viewDate.setUTCMonth(j),this._trigger("changeMonth",this.viewDate),1===this.o.minViewMode&&this._setDate(b(k,j,i,0,0,0,0))}else{var k=parseInt(d.text(),10)||0,i=1,j=0;this.viewDate.setUTCFullYear(k),this._trigger("changeYear",this.viewDate),2===this.o.minViewMode&&this._setDate(b(k,j,i,0,0,0,0))}this.showMode(-1),this.fill()}break;case"td":if(d.is(".day")&&!d.is(".disabled")){var i=parseInt(d.text(),10)||1,k=this.viewDate.getUTCFullYear(),j=this.viewDate.getUTCMonth();d.is(".old")?0===j?(j=11,k-=1):j-=1:d.is(".new")&&(11==j?(j=0,k+=1):j+=1),this._setDate(b(k,j,i,0,0,0,0))}}},_setDate:function(a,b){b&&"date"!=b||(this.date=new Date(a)),b&&"view"!=b||(this.viewDate=new Date(a)),this.fill(),this.setValue(),this._trigger("changeDate");var c;this.isInput?c=this.element:this.component&&(c=this.element.find("input")),c&&(c.change(),!this.o.autoclose||b&&"date"!=b||this.hide())},moveMonth:function(a,b){if(!b)return a;var c,d,e=new Date(a.valueOf()),f=e.getUTCDate(),g=e.getUTCMonth(),h=Math.abs(b);if(b=b>0?1:-1,1==h)d=-1==b?function(){return e.getUTCMonth()==g}:function(){return e.getUTCMonth()!=c},c=g+b,e.setUTCMonth(c),(0>c||c>11)&&(c=(c+12)%12);else{for(var i=0;h>i;i++)e=this.moveMonth(e,b);c=e.getUTCMonth(),e.setUTCDate(f),d=function(){return c!=e.getUTCMonth()}}for(;d();)e.setUTCDate(--f),e.setUTCMonth(c);return e},moveYear:function(a,b){return this.moveMonth(a,12*b)},dateWithinRange:function(a){return a>=this.o.startDate&&a<=this.o.endDate},keydown:function(a){if(this.picker.is(":not(:visible)"))return 27==a.keyCode&&this.show(),void 0;var b,c,d,e=!1;switch(a.keyCode){case 27:this.hide(),a.preventDefault();break;case 37:case 39:if(!this.o.keyboardNavigation)break;b=37==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date),c.setUTCDate(this.date.getUTCDate()+b),d=new Date(this.viewDate),d.setUTCDate(this.viewDate.getUTCDate()+b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 38:case 40:if(!this.o.keyboardNavigation)break;b=38==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date),c.setUTCDate(this.date.getUTCDate()+7*b),d=new Date(this.viewDate),d.setUTCDate(this.viewDate.getUTCDate()+7*b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 13:this.hide(),a.preventDefault();break;case 9:this.hide()}if(e){this._trigger("changeDate");var f;this.isInput?f=this.element:this.component&&(f=this.element.find("input")),f&&f.change()}},showMode:function(a){a&&(this.viewMode=Math.max(this.o.minViewMode,Math.min(2,this.viewMode+a))),this.picker.find(">div").hide().filter(".datepicker-"+l.modes[this.viewMode].clsName).css("display","block"),this.updateNavArrows()}};var f=function(b,c){this.element=a(b),this.inputs=a.map(c.inputs,function(a){return a.jquery?a[0]:a}),delete c.inputs,a(this.inputs).datepicker(c).bind("changeDate",a.proxy(this.dateUpdated,this)),this.pickers=a.map(this.inputs,function(b){return a(b).data("datepicker")}),this.updateDates()};f.prototype={updateDates:function(){this.dates=a.map(this.pickers,function(a){return a.date}),this.updateRanges()},updateRanges:function(){var b=a.map(this.dates,function(a){return a.valueOf()});a.each(this.pickers,function(a,c){c.setRange(b)})},dateUpdated:function(b){var c=a(b.target).data("datepicker"),d=c.getUTCDate(),e=a.inArray(b.target,this.inputs),f=this.inputs.length;if(-1!=e){if(d<this.dates[e])for(;e>=0&&d<this.dates[e];)this.pickers[e--].setUTCDate(d);else if(d>this.dates[e])for(;f>e&&d>this.dates[e];)this.pickers[e++].setUTCDate(d);this.updateDates()}},remove:function(){a.map(this.pickers,function(a){a.remove()}),delete this.element.data().datepicker}};var g=a.fn.datepicker,h=a.fn.datepicker=function(b){var g=Array.apply(null,arguments);g.shift();var h;return this.each(function(){var j=a(this),k=j.data("datepicker"),l="object"==typeof b&&b;if(!k){var m=c(this,"date"),n=a.extend({},i,m,l),o=d(n.language),p=a.extend({},i,o,m,l);if(j.is(".input-daterange")||p.inputs){var q={inputs:p.inputs||j.find("input").toArray()};j.data("datepicker",k=new f(this,a.extend(p,q)))}else j.data("datepicker",k=new e(this,p))}return"string"==typeof b&&"function"==typeof k[b]&&(h=k[b].apply(k,g),void 0!==h)?!1:void 0}),void 0!==h?h:this},i=a.fn.datepicker.defaults={autoclose:!1,beforeShowDay:a.noop,calendarWeeks:!1,clearBtn:!1,daysOfWeekDisabled:[],endDate:1/0,forceParse:!0,format:"mm/dd/yyyy",keyboardNavigation:!0,language:"en",minViewMode:0,rtl:!1,startDate:-1/0,startView:0,todayBtn:!1,todayHighlight:!1,weekStart:0},j=a.fn.datepicker.locale_opts=["format","rtl","weekStart"];a.fn.datepicker.Constructor=e;var k=a.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear"}},l={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(a){return 0===a%4&&0!==a%100||0===a%400 +},getDaysInMonth:function(a,b){return[31,l.isLeapYear(a)?29:28,31,30,31,30,31,31,30,31,30,31][b]},validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,parseFormat:function(a){var b=a.replace(this.validParts,"\0").split("\0"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(c,d,f){if(c instanceof Date)return c;if("string"==typeof d&&(d=l.parseFormat(d)),/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(c)){var g,h,i=/([\-+]\d+)([dmwy])/,j=c.match(/([\-+]\d+)([dmwy])/g);c=new Date;for(var m=0;m<j.length;m++)switch(g=i.exec(j[m]),h=parseInt(g[1]),g[2]){case"d":c.setUTCDate(c.getUTCDate()+h);break;case"m":c=e.prototype.moveMonth.call(e.prototype,c,h);break;case"w":c.setUTCDate(c.getUTCDate()+7*h);break;case"y":c=e.prototype.moveYear.call(e.prototype,c,h)}return b(c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate(),0,0,0)}var n,o,g,j=c&&c.match(this.nonpunctuation)||[],c=new Date,p={},q=["yyyy","yy","M","MM","m","mm","d","dd"],r={yyyy:function(a,b){return a.setUTCFullYear(b)},yy:function(a,b){return a.setUTCFullYear(2e3+b)},m:function(a,b){for(b-=1;0>b;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!=b;)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};r.M=r.MM=r.mm=r.m,r.dd=r.d,c=b(c.getFullYear(),c.getMonth(),c.getDate(),0,0,0);var s=d.parts.slice();if(j.length!=s.length&&(s=a(s).filter(function(b,c){return-1!==a.inArray(c,q)}).toArray()),j.length==s.length){for(var m=0,t=s.length;t>m;m++){if(n=parseInt(j[m],10),g=s[m],isNaN(n))switch(g){case"MM":o=a(k[f].months).filter(function(){var a=this.slice(0,j[m].length),b=j[m].slice(0,a.length);return a==b}),n=a.inArray(o[0],k[f].months)+1;break;case"M":o=a(k[f].monthsShort).filter(function(){var a=this.slice(0,j[m].length),b=j[m].slice(0,a.length);return a==b}),n=a.inArray(o[0],k[f].monthsShort)+1}p[g]=n}for(var u,m=0;m<q.length;m++)u=q[m],u in p&&!isNaN(p[u])&&r[u](c,p[u])}return c},formatDate:function(b,c,d){"string"==typeof c&&(c=l.parseFormat(c));var e={d:b.getUTCDate(),D:k[d].daysShort[b.getUTCDay()],DD:k[d].days[b.getUTCDay()],m:b.getUTCMonth()+1,M:k[d].monthsShort[b.getUTCMonth()],MM:k[d].months[b.getUTCMonth()],yy:b.getUTCFullYear().toString().substring(2),yyyy:b.getUTCFullYear()};e.dd=(e.d<10?"0":"")+e.d,e.mm=(e.m<10?"0":"")+e.m;for(var b=[],f=a.extend([],c.separators),g=0,h=c.parts.length;h>=g;g++)f.length&&b.push(f.shift()),b.push(e[c.parts[g]]);return b.join("")},headTemplate:'<thead><tr><th class="prev"><i class="icon-arrow-left"/></th><th colspan="5" class="datepicker-switch"></th><th class="next"><i class="icon-arrow-right"/></th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};l.template='<div class="datepicker"><div class="datepicker-days"><table class=" table-condensed">'+l.headTemplate+"<tbody></tbody>"+l.footTemplate+"</table>"+"</div>"+'<div class="datepicker-months">'+'<table class="table-condensed">'+l.headTemplate+l.contTemplate+l.footTemplate+"</table>"+"</div>"+'<div class="datepicker-years">'+'<table class="table-condensed">'+l.headTemplate+l.contTemplate+l.footTemplate+"</table>"+"</div>"+"</div>",a.fn.datepicker.DPGlobal=l,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=g,this},a(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(b){var c=a(this);c.data("datepicker")||(b.preventDefault(),h.call(c,"show"))}),a(function(){h.call(a('[data-provide="datepicker-inline"]'))})}(window.jQuery),function(a){"use strict";a.fn.bdatepicker=a.fn.datepicker.noConflict(),a.fn.datepicker||(a.fn.datepicker=a.fn.bdatepicker);var b=function(a){this.init("date",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{initPicker:function(b,c){this.options.viewformat||(this.options.viewformat=this.options.format),b.datepicker=a.fn.editableutils.tryParseJson(b.datepicker,!0),this.options.datepicker=a.extend({},c.datepicker,b.datepicker,{format:this.options.viewformat}),this.options.datepicker.language=this.options.datepicker.language||"en",this.dpg=a.fn.bdatepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.format),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat)},render:function(){this.$input.bdatepicker(this.options.datepicker),this.options.clear&&(this.$clear=a('<a href="#"></a>').html(this.options.clear).click(a.proxy(function(a){a.preventDefault(),a.stopPropagation(),this.clear()},this)),this.$tpl.parent().append(a('<div class="editable-clear">').append(this.$clear)))},value2html:function(a,c){var d=a?this.dpg.formatDate(a,this.parsedViewFormat,this.options.datepicker.language):"";b.superclass.value2html.call(this,d,c)},html2value:function(a){return this.parseDate(a,this.parsedViewFormat)},value2str:function(a){return a?this.dpg.formatDate(a,this.parsedFormat,this.options.datepicker.language):""},str2value:function(a){return this.parseDate(a,this.parsedFormat)},value2submit:function(a){return this.value2str(a)},value2input:function(a){this.$input.bdatepicker("update",a)},input2value:function(){return this.$input.data("datepicker").date},activate:function(){},clear:function(){this.$input.data("datepicker").date=null,this.$input.find(".active").removeClass("active"),this.options.showbuttons||this.$input.closest("form").submit()},autosubmit:function(){this.$input.on("mouseup",".day",function(b){if(!a(b.currentTarget).is(".old")&&!a(b.currentTarget).is(".new")){var c=a(this).closest("form");setTimeout(function(){c.submit()},200)}})},parseDate:function(a,b){var c,d=null;return a&&(d=this.dpg.parseDate(a,b,this.options.datepicker.language),"string"==typeof a&&(c=this.dpg.formatDate(d,b,this.options.datepicker.language),a!==c&&(d=null))),d}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<div class="editable-date well"></div>',inputclass:null,format:"yyyy-mm-dd",viewformat:null,datepicker:{weekStart:0,startView:0,minViewMode:0,autoclose:!1},clear:"&times; clear"}),a.fn.editabletypes.date=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datefield",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.date),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.find("input"),this.setClass(),this.setAttr("placeholder"),this.$tpl.bdatepicker(this.options.datepicker),this.$input.off("focus keydown"),this.$input.keyup(a.proxy(function(){this.$tpl.removeData("date"),this.$tpl.bdatepicker("update")},this))},value2input:function(a){this.$input.val(a?this.dpg.formatDate(a,this.parsedViewFormat,this.options.datepicker.language):""),this.$tpl.bdatepicker("update")},input2value:function(){return this.html2value(this.$input.val())},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.date.defaults,{tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',inputclass:"input-small",datepicker:{weekStart:0,startView:0,minViewMode:0,autoclose:!0}}),a.fn.editabletypes.datefield=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datetime",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{initPicker:function(b,c){this.options.viewformat||(this.options.viewformat=this.options.format),b.datetimepicker=a.fn.editableutils.tryParseJson(b.datetimepicker,!0),this.options.datetimepicker=a.extend({},c.datetimepicker,b.datetimepicker,{format:this.options.viewformat}),this.options.datetimepicker.language=this.options.datetimepicker.language||"en",this.dpg=a.fn.datetimepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.format,this.options.formatType),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat,this.options.formatType)},render:function(){this.$input.datetimepicker(this.options.datetimepicker),this.$input.on("changeMode",function(){var b=a(this).closest("form").parent();setTimeout(function(){b.triggerHandler("resize")},0)}),this.options.clear&&(this.$clear=a('<a href="#"></a>').html(this.options.clear).click(a.proxy(function(a){a.preventDefault(),a.stopPropagation(),this.clear()},this)),this.$tpl.parent().append(a('<div class="editable-clear">').append(this.$clear)))},value2html:function(a,c){var d=a?this.dpg.formatDate(this.toUTC(a),this.parsedViewFormat,this.options.datetimepicker.language,this.options.formatType):"";return c?(b.superclass.value2html.call(this,d,c),void 0):d},html2value:function(a){var b=this.parseDate(a,this.parsedViewFormat);return b?this.fromUTC(b):null},value2str:function(a){return a?this.dpg.formatDate(this.toUTC(a),this.parsedFormat,this.options.datetimepicker.language,this.options.formatType):""},str2value:function(a){var b=this.parseDate(a,this.parsedFormat);return b?this.fromUTC(b):null},value2submit:function(a){return this.value2str(a)},value2input:function(a){a&&this.$input.data("datetimepicker").setDate(a)},input2value:function(){var a=this.$input.data("datetimepicker");return a.date?a.getDate():null},activate:function(){},clear:function(){this.$input.data("datetimepicker").date=null,this.$input.find(".active").removeClass("active"),this.options.showbuttons||this.$input.closest("form").submit()},autosubmit:function(){this.$input.on("mouseup",".minute",function(){var b=a(this).closest("form");setTimeout(function(){b.submit()},200)})},toUTC:function(a){return a?new Date(a.valueOf()-6e4*a.getTimezoneOffset()):a},fromUTC:function(a){return a?new Date(a.valueOf()+6e4*a.getTimezoneOffset()):a},parseDate:function(a,b){var c,d=null;return a&&(d=this.dpg.parseDate(a,b,this.options.datetimepicker.language,this.options.formatType),"string"==typeof a&&(c=this.dpg.formatDate(d,b,this.options.datetimepicker.language,this.options.formatType),a!==c&&(d=null))),d}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<div class="editable-date well"></div>',inputclass:null,format:"yyyy-mm-dd hh:ii",formatType:"standard",viewformat:null,datetimepicker:{todayHighlight:!1,autoclose:!1},clear:"&times; clear"}),a.fn.editabletypes.datetime=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datetimefield",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.datetime),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.find("input"),this.setClass(),this.setAttr("placeholder"),this.$tpl.datetimepicker(this.options.datetimepicker),this.$input.off("focus keydown"),this.$input.keyup(a.proxy(function(){this.$tpl.removeData("date"),this.$tpl.datetimepicker("update")},this))},value2input:function(a){this.$input.val(this.value2html(a)),this.$tpl.datetimepicker("update")},input2value:function(){return this.html2value(this.$input.val())},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.datetime.defaults,{tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',inputclass:"input-medium",datetimepicker:{todayHighlight:!1,autoclose:!0}}),a.fn.editabletypes.datetimefield=b}(window.jQuery),function(a){"use strict";var b=function(c){this.init("typeahead",c,b.defaults),this.options.typeahead=a.extend({},b.defaults.typeahead,{matcher:this.matcher,sorter:this.sorter,highlighter:this.highlighter,updater:this.updater},c.typeahead)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){this.$input=this.$tpl.is("input")?this.$tpl:this.$tpl.find('input[type="text"]'),this.options.typeahead.source=this.sourceData,this.$input.typeahead(this.options.typeahead);var b=this.$input.data("typeahead");b.render=a.proxy(this.typeaheadRender,b),b.select=a.proxy(this.typeaheadSelect,b),b.move=a.proxy(this.typeaheadMove,b),this.renderClear(),this.setClass(),this.setAttr("placeholder")},value2htmlFinal:function(b,c){if(this.getIsObjects()){var d=a.fn.editableutils.itemsByValue(b,this.sourceData);b=d.length?d[0].text:""}a.fn.editabletypes.abstractinput.prototype.value2html.call(this,b,c)},html2value:function(a){return a?a:null},value2input:function(b){if(this.getIsObjects()){var c=a.fn.editableutils.itemsByValue(b,this.sourceData);this.$input.data("value",b).val(c.length?c[0].text:"")}else this.$input.val(b)},input2value:function(){if(this.getIsObjects()){var b=this.$input.data("value"),c=a.fn.editableutils.itemsByValue(b,this.sourceData);return c.length&&c[0].text.toLowerCase()===this.$input.val().toLowerCase()?b:null}return this.$input.val()},getIsObjects:function(){if(void 0===this.isObjects){this.isObjects=!1;for(var a=0;a<this.sourceData.length;a++)if(this.sourceData[a].value!==this.sourceData[a].text){this.isObjects=!0;break}}return this.isObjects},activate:a.fn.editabletypes.text.prototype.activate,renderClear:a.fn.editabletypes.text.prototype.renderClear,postrender:a.fn.editabletypes.text.prototype.postrender,toggleClear:a.fn.editabletypes.text.prototype.toggleClear,clear:function(){a.fn.editabletypes.text.prototype.clear.call(this),this.$input.data("value","")},matcher:function(b){return a.fn.typeahead.Constructor.prototype.matcher.call(this,b.text)},sorter:function(a){for(var b,c,d=[],e=[],f=[];b=a.shift();)c=b.text,c.toLowerCase().indexOf(this.query.toLowerCase())?~c.indexOf(this.query)?e.push(b):f.push(b):d.push(b);return d.concat(e,f)},highlighter:function(b){return a.fn.typeahead.Constructor.prototype.highlighter.call(this,b.text)},updater:function(a){return this.$element.data("value",a.value),a.text},typeaheadRender:function(b){var c=this;return b=a(b).map(function(b,d){return b=a(c.options.item).data("item",d),b.find("a").html(c.highlighter(d)),b[0]}),this.options.autoSelect&&b.first().addClass("active"),this.$menu.html(b),this},typeaheadSelect:function(){var a=this.$menu.find(".active").data("item");return(this.options.autoSelect||a)&&this.$element.val(this.updater(a)).change(),this.hide()},typeaheadMove:function(a){if(this.shown){switch(a.keyCode){case 9:case 13:case 27:if(!this.$menu.find(".active").length)return;a.preventDefault();break;case 38:a.preventDefault(),this.prev();break;case 40:a.preventDefault(),this.next()}a.stopPropagation()}}}),b.defaults=a.extend({},a.fn.editabletypes.list.defaults,{tpl:'<input type="text">',typeahead:null,clear:!0}),a.fn.editabletypes.typeahead=b}(window.jQuery); \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/address/address.css b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/address/address.css new file mode 100755 index 0000000..f37a43b --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/address/address.css @@ -0,0 +1,9 @@ +.editable-address { + display: block; + margin-bottom: 5px; +} + +.editable-address span { + width: 70px; + display: inline-block; +} \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/address/address.js b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/address/address.js new file mode 100755 index 0000000..de3af81 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/address/address.js @@ -0,0 +1,170 @@ +/** +Address editable input. +Internally value stored as {city: "Moscow", street: "Lenina", building: "15"} + +@class address +@extends abstractinput +@final +@example +<a href="#" id="address" data-type="address" data-pk="1">awesome</a> +<script> +$(function(){ + $('#address').editable({ + url: '/post', + title: 'Enter city, street and building #', + value: { + city: "Moscow", + street: "Lenina", + building: "15" + } + }); +}); +</script> +**/ +(function ($) { + "use strict"; + + var Address = function (options) { + this.init('address', options, Address.defaults); + }; + + //inherit from Abstract input + $.fn.editableutils.inherit(Address, $.fn.editabletypes.abstractinput); + + $.extend(Address.prototype, { + /** + Renders input from tpl + + @method render() + **/ + render: function() { + this.$input = this.$tpl.find('input'); + }, + + /** + Default method to show value in element. Can be overwritten by display option. + + @method value2html(value, element) + **/ + value2html: function(value, element) { + if(!value) { + $(element).empty(); + return; + } + var html = $('<div>').text(value.city).html() + ', ' + $('<div>').text(value.street).html() + ' st., bld. ' + $('<div>').text(value.building).html(); + $(element).html(html); + }, + + /** + Gets value from element's html + + @method html2value(html) + **/ + html2value: function(html) { + /* + you may write parsing method to get value by element's html + e.g. "Moscow, st. Lenina, bld. 15" => {city: "Moscow", street: "Lenina", building: "15"} + but for complex structures it's not recommended. + Better set value directly via javascript, e.g. + editable({ + value: { + city: "Moscow", + street: "Lenina", + building: "15" + } + }); + */ + return null; + }, + + /** + Converts value to string. + It is used in internal comparing (not for sending to server). + + @method value2str(value) + **/ + value2str: function(value) { + var str = ''; + if(value) { + for(var k in value) { + str = str + k + ':' + value[k] + ';'; + } + } + return str; + }, + + /* + Converts string to value. Used for reading value from 'data-value' attribute. + + @method str2value(str) + */ + str2value: function(str) { + /* + this is mainly for parsing value defined in data-value attribute. + If you will always set value by javascript, no need to overwrite it + */ + return str; + }, + + /** + Sets value of input. + + @method value2input(value) + @param {mixed} value + **/ + value2input: function(value) { + if(!value) { + return; + } + this.$input.filter('[name="city"]').val(value.city); + this.$input.filter('[name="street"]').val(value.street); + this.$input.filter('[name="building"]').val(value.building); + }, + + /** + Returns value of input. + + @method input2value() + **/ + input2value: function() { + return { + city: this.$input.filter('[name="city"]').val(), + street: this.$input.filter('[name="street"]').val(), + building: this.$input.filter('[name="building"]').val() + }; + }, + + /** + Activates input: sets focus on the first field. + + @method activate() + **/ + activate: function() { + this.$input.filter('[name="city"]').focus(); + }, + + /** + Attaches handler to submit form in case of 'showbuttons=false' mode + + @method autosubmit() + **/ + autosubmit: function() { + this.$input.keydown(function (e) { + if (e.which === 13) { + $(this).closest('form').submit(); + } + }); + } + }); + + Address.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + tpl: '<div class="editable-address"><label><span>City: </span><input type="text" name="city" class="input-small"></label></div>'+ + '<div class="editable-address"><label><span>Street: </span><input type="text" name="street" class="input-small"></label></div>'+ + '<div class="editable-address"><label><span>Building: </span><input type="text" name="building" class="input-mini"></label></div>', + + inputclass: '' + }); + + $.fn.editabletypes.address = Address; + +}(window.jQuery)); \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/lib/typeahead.js b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/lib/typeahead.js new file mode 100755 index 0000000..9365bd6 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/lib/typeahead.js @@ -0,0 +1,1139 @@ +/*! + * typeahead.js 0.9.3 + * https://github.com/twitter/typeahead + * Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT + */ + +(function($) { + var VERSION = "0.9.3"; + var utils = { + isMsie: function() { + var match = /(msie) ([\w.]+)/i.exec(navigator.userAgent); + return match ? parseInt(match[2], 10) : false; + }, + isBlankString: function(str) { + return !str || /^\s*$/.test(str); + }, + escapeRegExChars: function(str) { + return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); + }, + isString: function(obj) { + return typeof obj === "string"; + }, + isNumber: function(obj) { + return typeof obj === "number"; + }, + isArray: $.isArray, + isFunction: $.isFunction, + isObject: $.isPlainObject, + isUndefined: function(obj) { + return typeof obj === "undefined"; + }, + bind: $.proxy, + bindAll: function(obj) { + var val; + for (var key in obj) { + $.isFunction(val = obj[key]) && (obj[key] = $.proxy(val, obj)); + } + }, + indexOf: function(haystack, needle) { + for (var i = 0; i < haystack.length; i++) { + if (haystack[i] === needle) { + return i; + } + } + return -1; + }, + each: $.each, + map: $.map, + filter: $.grep, + every: function(obj, test) { + var result = true; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (!(result = test.call(null, val, key, obj))) { + return false; + } + }); + return !!result; + }, + some: function(obj, test) { + var result = false; + if (!obj) { + return result; + } + $.each(obj, function(key, val) { + if (result = test.call(null, val, key, obj)) { + return false; + } + }); + return !!result; + }, + mixin: $.extend, + getUniqueId: function() { + var counter = 0; + return function() { + return counter++; + }; + }(), + defer: function(fn) { + setTimeout(fn, 0); + }, + debounce: function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments, later, callNow; + later = function() { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + } + }; + callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) { + result = func.apply(context, args); + } + return result; + }; + }, + throttle: function(func, wait) { + var context, args, timeout, result, previous, later; + previous = 0; + later = function() { + previous = new Date(); + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date(), remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }, + tokenizeQuery: function(str) { + return $.trim(str).toLowerCase().split(/[\s]+/); + }, + tokenizeText: function(str) { + return $.trim(str).toLowerCase().split(/[\s\-_]+/); + }, + getProtocol: function() { + return location.protocol; + }, + noop: function() {} + }; + var EventTarget = function() { + var eventSplitter = /\s+/; + return { + on: function(events, callback) { + var event; + if (!callback) { + return this; + } + this._callbacks = this._callbacks || {}; + events = events.split(eventSplitter); + while (event = events.shift()) { + this._callbacks[event] = this._callbacks[event] || []; + this._callbacks[event].push(callback); + } + return this; + }, + trigger: function(events, data) { + var event, callbacks; + if (!this._callbacks) { + return this; + } + events = events.split(eventSplitter); + while (event = events.shift()) { + if (callbacks = this._callbacks[event]) { + for (var i = 0; i < callbacks.length; i += 1) { + callbacks[i].call(this, { + type: event, + data: data + }); + } + } + } + return this; + } + }; + }(); + var EventBus = function() { + var namespace = "typeahead:"; + function EventBus(o) { + if (!o || !o.el) { + $.error("EventBus initialized without el"); + } + this.$el = $(o.el); + } + utils.mixin(EventBus.prototype, { + trigger: function(type) { + var args = [].slice.call(arguments, 1); + this.$el.trigger(namespace + type, args); + } + }); + return EventBus; + }(); + var PersistentStorage = function() { + var ls, methods; + try { + ls = window.localStorage; + ls.setItem("~~~", "!"); + ls.removeItem("~~~"); + } catch (err) { + ls = null; + } + function PersistentStorage(namespace) { + this.prefix = [ "__", namespace, "__" ].join(""); + this.ttlKey = "__ttl__"; + this.keyMatcher = new RegExp("^" + this.prefix); + } + if (ls && window.JSON) { + methods = { + _prefix: function(key) { + return this.prefix + key; + }, + _ttlKey: function(key) { + return this._prefix(key) + this.ttlKey; + }, + get: function(key) { + if (this.isExpired(key)) { + this.remove(key); + } + return decode(ls.getItem(this._prefix(key))); + }, + set: function(key, val, ttl) { + if (utils.isNumber(ttl)) { + ls.setItem(this._ttlKey(key), encode(now() + ttl)); + } else { + ls.removeItem(this._ttlKey(key)); + } + return ls.setItem(this._prefix(key), encode(val)); + }, + remove: function(key) { + ls.removeItem(this._ttlKey(key)); + ls.removeItem(this._prefix(key)); + return this; + }, + clear: function() { + var i, key, keys = [], len = ls.length; + for (i = 0; i < len; i++) { + if ((key = ls.key(i)).match(this.keyMatcher)) { + keys.push(key.replace(this.keyMatcher, "")); + } + } + for (i = keys.length; i--; ) { + this.remove(keys[i]); + } + return this; + }, + isExpired: function(key) { + var ttl = decode(ls.getItem(this._ttlKey(key))); + return utils.isNumber(ttl) && now() > ttl ? true : false; + } + }; + } else { + methods = { + get: utils.noop, + set: utils.noop, + remove: utils.noop, + clear: utils.noop, + isExpired: utils.noop + }; + } + utils.mixin(PersistentStorage.prototype, methods); + return PersistentStorage; + function now() { + return new Date().getTime(); + } + function encode(val) { + return JSON.stringify(utils.isUndefined(val) ? null : val); + } + function decode(val) { + return JSON.parse(val); + } + }(); + var RequestCache = function() { + function RequestCache(o) { + utils.bindAll(this); + o = o || {}; + this.sizeLimit = o.sizeLimit || 10; + this.cache = {}; + this.cachedKeysByAge = []; + } + utils.mixin(RequestCache.prototype, { + get: function(url) { + return this.cache[url]; + }, + set: function(url, resp) { + var requestToEvict; + if (this.cachedKeysByAge.length === this.sizeLimit) { + requestToEvict = this.cachedKeysByAge.shift(); + delete this.cache[requestToEvict]; + } + this.cache[url] = resp; + this.cachedKeysByAge.push(url); + } + }); + return RequestCache; + }(); + var Transport = function() { + var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests, requestCache; + function Transport(o) { + utils.bindAll(this); + o = utils.isString(o) ? { + url: o + } : o; + requestCache = requestCache || new RequestCache(); + maxPendingRequests = utils.isNumber(o.maxParallelRequests) ? o.maxParallelRequests : maxPendingRequests || 6; + this.url = o.url; + this.wildcard = o.wildcard || "%QUERY"; + this.filter = o.filter; + this.replace = o.replace; + this.ajaxSettings = { + type: "get", + cache: o.cache, + timeout: o.timeout, + dataType: o.dataType || "json", + beforeSend: o.beforeSend + }; + this._get = (/^throttle$/i.test(o.rateLimitFn) ? utils.throttle : utils.debounce)(this._get, o.rateLimitWait || 300); + } + utils.mixin(Transport.prototype, { + _get: function(url, cb) { + var that = this; + if (belowPendingRequestsThreshold()) { + this._sendRequest(url).done(done); + } else { + this.onDeckRequestArgs = [].slice.call(arguments, 0); + } + function done(resp) { + var data = that.filter ? that.filter(resp) : resp; + cb && cb(data); + requestCache.set(url, resp); + } + }, + _sendRequest: function(url) { + var that = this, jqXhr = pendingRequests[url]; + if (!jqXhr) { + incrementPendingRequests(); + jqXhr = pendingRequests[url] = $.ajax(url, this.ajaxSettings).always(always); + } + return jqXhr; + function always() { + decrementPendingRequests(); + pendingRequests[url] = null; + if (that.onDeckRequestArgs) { + that._get.apply(that, that.onDeckRequestArgs); + that.onDeckRequestArgs = null; + } + } + }, + get: function(query, cb) { + var that = this, encodedQuery = encodeURIComponent(query || ""), url, resp; + cb = cb || utils.noop; + url = this.replace ? this.replace(this.url, encodedQuery) : this.url.replace(this.wildcard, encodedQuery); + if (resp = requestCache.get(url)) { + utils.defer(function() { + cb(that.filter ? that.filter(resp) : resp); + }); + } else { + this._get(url, cb); + } + return !!resp; + } + }); + return Transport; + function incrementPendingRequests() { + pendingRequestsCount++; + } + function decrementPendingRequests() { + pendingRequestsCount--; + } + function belowPendingRequestsThreshold() { + return pendingRequestsCount < maxPendingRequests; + } + }(); + var Dataset = function() { + var keys = { + thumbprint: "thumbprint", + protocol: "protocol", + itemHash: "itemHash", + adjacencyList: "adjacencyList" + }; + function Dataset(o) { + utils.bindAll(this); + if (utils.isString(o.template) && !o.engine) { + $.error("no template engine specified"); + } + if (!o.local && !o.prefetch && !o.remote) { + $.error("one of local, prefetch, or remote is required"); + } + this.name = o.name || utils.getUniqueId(); + this.limit = o.limit || 5; + this.minLength = o.minLength || 1; + this.header = o.header; + this.footer = o.footer; + this.valueKey = o.valueKey || "value"; + this.template = compileTemplate(o.template, o.engine, this.valueKey); + this.local = o.local; + this.prefetch = o.prefetch; + this.remote = o.remote; + this.itemHash = {}; + this.adjacencyList = {}; + this.storage = o.name ? new PersistentStorage(o.name) : null; + } + utils.mixin(Dataset.prototype, { + _processLocalData: function(data) { + this._mergeProcessedData(this._processData(data)); + }, + _loadPrefetchData: function(o) { + var that = this, thumbprint = VERSION + (o.thumbprint || ""), storedThumbprint, storedProtocol, storedItemHash, storedAdjacencyList, isExpired, deferred; + if (this.storage) { + storedThumbprint = this.storage.get(keys.thumbprint); + storedProtocol = this.storage.get(keys.protocol); + storedItemHash = this.storage.get(keys.itemHash); + storedAdjacencyList = this.storage.get(keys.adjacencyList); + } + isExpired = storedThumbprint !== thumbprint || storedProtocol !== utils.getProtocol(); + o = utils.isString(o) ? { + url: o + } : o; + o.ttl = utils.isNumber(o.ttl) ? o.ttl : 24 * 60 * 60 * 1e3; + if (storedItemHash && storedAdjacencyList && !isExpired) { + this._mergeProcessedData({ + itemHash: storedItemHash, + adjacencyList: storedAdjacencyList + }); + deferred = $.Deferred().resolve(); + } else { + deferred = $.getJSON(o.url).done(processPrefetchData); + } + return deferred; + function processPrefetchData(data) { + var filteredData = o.filter ? o.filter(data) : data, processedData = that._processData(filteredData), itemHash = processedData.itemHash, adjacencyList = processedData.adjacencyList; + if (that.storage) { + that.storage.set(keys.itemHash, itemHash, o.ttl); + that.storage.set(keys.adjacencyList, adjacencyList, o.ttl); + that.storage.set(keys.thumbprint, thumbprint, o.ttl); + that.storage.set(keys.protocol, utils.getProtocol(), o.ttl); + } + that._mergeProcessedData(processedData); + } + }, + _transformDatum: function(datum) { + var value = utils.isString(datum) ? datum : datum[this.valueKey], tokens = datum.tokens || utils.tokenizeText(value), item = { + value: value, + tokens: tokens + }; + if (utils.isString(datum)) { + item.datum = {}; + item.datum[this.valueKey] = datum; + } else { + item.datum = datum; + } + item.tokens = utils.filter(item.tokens, function(token) { + return !utils.isBlankString(token); + }); + item.tokens = utils.map(item.tokens, function(token) { + return token.toLowerCase(); + }); + return item; + }, + _processData: function(data) { + var that = this, itemHash = {}, adjacencyList = {}; + utils.each(data, function(i, datum) { + var item = that._transformDatum(datum), id = utils.getUniqueId(item.value); + itemHash[id] = item; + utils.each(item.tokens, function(i, token) { + var character = token.charAt(0), adjacency = adjacencyList[character] || (adjacencyList[character] = [ id ]); + !~utils.indexOf(adjacency, id) && adjacency.push(id); + }); + }); + return { + itemHash: itemHash, + adjacencyList: adjacencyList + }; + }, + _mergeProcessedData: function(processedData) { + var that = this; + utils.mixin(this.itemHash, processedData.itemHash); + utils.each(processedData.adjacencyList, function(character, adjacency) { + var masterAdjacency = that.adjacencyList[character]; + that.adjacencyList[character] = masterAdjacency ? masterAdjacency.concat(adjacency) : adjacency; + }); + }, + _getLocalSuggestions: function(terms) { + var that = this, firstChars = [], lists = [], shortestList, suggestions = []; + utils.each(terms, function(i, term) { + var firstChar = term.charAt(0); + !~utils.indexOf(firstChars, firstChar) && firstChars.push(firstChar); + }); + utils.each(firstChars, function(i, firstChar) { + var list = that.adjacencyList[firstChar]; + if (!list) { + return false; + } + lists.push(list); + if (!shortestList || list.length < shortestList.length) { + shortestList = list; + } + }); + if (lists.length < firstChars.length) { + return []; + } + utils.each(shortestList, function(i, id) { + var item = that.itemHash[id], isCandidate, isMatch; + isCandidate = utils.every(lists, function(list) { + return ~utils.indexOf(list, id); + }); + isMatch = isCandidate && utils.every(terms, function(term) { + return utils.some(item.tokens, function(token) { + return token.indexOf(term) === 0; + }); + }); + isMatch && suggestions.push(item); + }); + return suggestions; + }, + initialize: function() { + var deferred; + this.local && this._processLocalData(this.local); + this.transport = this.remote ? new Transport(this.remote) : null; + deferred = this.prefetch ? this._loadPrefetchData(this.prefetch) : $.Deferred().resolve(); + this.local = this.prefetch = this.remote = null; + this.initialize = function() { + return deferred; + }; + return deferred; + }, + getSuggestions: function(query, cb) { + var that = this, terms, suggestions, cacheHit = false; + if (query.length < this.minLength) { + return; + } + terms = utils.tokenizeQuery(query); + suggestions = this._getLocalSuggestions(terms).slice(0, this.limit); + if (suggestions.length < this.limit && this.transport) { + cacheHit = this.transport.get(query, processRemoteData); + } + !cacheHit && cb && cb(suggestions); + function processRemoteData(data) { + suggestions = suggestions.slice(0); + utils.each(data, function(i, datum) { + var item = that._transformDatum(datum), isDuplicate; + isDuplicate = utils.some(suggestions, function(suggestion) { + return item.value === suggestion.value; + }); + !isDuplicate && suggestions.push(item); + return suggestions.length < that.limit; + }); + cb && cb(suggestions); + } + } + }); + return Dataset; + function compileTemplate(template, engine, valueKey) { + var renderFn, compiledTemplate; + if (utils.isFunction(template)) { + renderFn = template; + } else if (utils.isString(template)) { + compiledTemplate = engine.compile(template); + renderFn = utils.bind(compiledTemplate.render, compiledTemplate); + } else { + renderFn = function(context) { + return "<p>" + context[valueKey] + "</p>"; + }; + } + return renderFn; + } + }(); + var InputView = function() { + function InputView(o) { + var that = this; + utils.bindAll(this); + this.specialKeyCodeMap = { + 9: "tab", + 27: "esc", + 37: "left", + 39: "right", + 13: "enter", + 38: "up", + 40: "down" + }; + this.$hint = $(o.hint); + this.$input = $(o.input).on("blur.tt", this._handleBlur).on("focus.tt", this._handleFocus).on("keydown.tt", this._handleSpecialKeyEvent); + if (!utils.isMsie()) { + this.$input.on("input.tt", this._compareQueryToInputValue); + } else { + this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) { + if (that.specialKeyCodeMap[$e.which || $e.keyCode]) { + return; + } + utils.defer(that._compareQueryToInputValue); + }); + } + this.query = this.$input.val(); + this.$overflowHelper = buildOverflowHelper(this.$input); + } + utils.mixin(InputView.prototype, EventTarget, { + _handleFocus: function() { + this.trigger("focused"); + }, + _handleBlur: function() { + this.trigger("blured"); + }, + _handleSpecialKeyEvent: function($e) { + var keyName = this.specialKeyCodeMap[$e.which || $e.keyCode]; + keyName && this.trigger(keyName + "Keyed", $e); + }, + _compareQueryToInputValue: function() { + var inputValue = this.getInputValue(), isSameQuery = compareQueries(this.query, inputValue), isSameQueryExceptWhitespace = isSameQuery ? this.query.length !== inputValue.length : false; + if (isSameQueryExceptWhitespace) { + this.trigger("whitespaceChanged", { + value: this.query + }); + } else if (!isSameQuery) { + this.trigger("queryChanged", { + value: this.query = inputValue + }); + } + }, + destroy: function() { + this.$hint.off(".tt"); + this.$input.off(".tt"); + this.$hint = this.$input = this.$overflowHelper = null; + }, + focus: function() { + this.$input.focus(); + }, + blur: function() { + this.$input.blur(); + }, + getQuery: function() { + return this.query; + }, + setQuery: function(query) { + this.query = query; + }, + getInputValue: function() { + return this.$input.val(); + }, + setInputValue: function(value, silent) { + this.$input.val(value); + !silent && this._compareQueryToInputValue(); + }, + getHintValue: function() { + return this.$hint.val(); + }, + setHintValue: function(value) { + this.$hint.val(value); + }, + getLanguageDirection: function() { + return (this.$input.css("direction") || "ltr").toLowerCase(); + }, + isOverflow: function() { + this.$overflowHelper.text(this.getInputValue()); + return this.$overflowHelper.width() > this.$input.width(); + }, + isCursorAtEnd: function() { + var valueLength = this.$input.val().length, selectionStart = this.$input[0].selectionStart, range; + if (utils.isNumber(selectionStart)) { + return selectionStart === valueLength; + } else if (document.selection) { + range = document.selection.createRange(); + range.moveStart("character", -valueLength); + return valueLength === range.text.length; + } + return true; + } + }); + return InputView; + function buildOverflowHelper($input) { + return $("<span></span>").css({ + position: "absolute", + left: "-9999px", + visibility: "hidden", + whiteSpace: "nowrap", + fontFamily: $input.css("font-family"), + fontSize: $input.css("font-size"), + fontStyle: $input.css("font-style"), + fontVariant: $input.css("font-variant"), + fontWeight: $input.css("font-weight"), + wordSpacing: $input.css("word-spacing"), + letterSpacing: $input.css("letter-spacing"), + textIndent: $input.css("text-indent"), + textRendering: $input.css("text-rendering"), + textTransform: $input.css("text-transform") + }).insertAfter($input); + } + function compareQueries(a, b) { + a = (a || "").replace(/^\s*/g, "").replace(/\s{2,}/g, " "); + b = (b || "").replace(/^\s*/g, "").replace(/\s{2,}/g, " "); + return a === b; + } + }(); + var DropdownView = function() { + var html = { + suggestionsList: '<span class="tt-suggestions"></span>' + }, css = { + suggestionsList: { + display: "block" + }, + suggestion: { + whiteSpace: "nowrap", + cursor: "pointer" + }, + suggestionChild: { + whiteSpace: "normal" + } + }; + function DropdownView(o) { + utils.bindAll(this); + this.isOpen = false; + this.isEmpty = true; + this.isMouseOverDropdown = false; + this.$menu = $(o.menu).on("mouseenter.tt", this._handleMouseenter).on("mouseleave.tt", this._handleMouseleave).on("click.tt", ".tt-suggestion", this._handleSelection).on("mouseover.tt", ".tt-suggestion", this._handleMouseover); + } + utils.mixin(DropdownView.prototype, EventTarget, { + _handleMouseenter: function() { + this.isMouseOverDropdown = true; + }, + _handleMouseleave: function() { + this.isMouseOverDropdown = false; + }, + _handleMouseover: function($e) { + var $suggestion = $($e.currentTarget); + this._getSuggestions().removeClass("tt-is-under-cursor"); + $suggestion.addClass("tt-is-under-cursor"); + }, + _handleSelection: function($e) { + var $suggestion = $($e.currentTarget); + this.trigger("suggestionSelected", extractSuggestion($suggestion)); + }, + _show: function() { + this.$menu.css("display", "block"); + }, + _hide: function() { + this.$menu.hide(); + }, + _moveCursor: function(increment) { + var $suggestions, $cur, nextIndex, $underCursor; + if (!this.isVisible()) { + return; + } + $suggestions = this._getSuggestions(); + $cur = $suggestions.filter(".tt-is-under-cursor"); + $cur.removeClass("tt-is-under-cursor"); + nextIndex = $suggestions.index($cur) + increment; + nextIndex = (nextIndex + 1) % ($suggestions.length + 1) - 1; + if (nextIndex === -1) { + this.trigger("cursorRemoved"); + return; + } else if (nextIndex < -1) { + nextIndex = $suggestions.length - 1; + } + $underCursor = $suggestions.eq(nextIndex).addClass("tt-is-under-cursor"); + this._ensureVisibility($underCursor); + this.trigger("cursorMoved", extractSuggestion($underCursor)); + }, + _getSuggestions: function() { + return this.$menu.find(".tt-suggestions > .tt-suggestion"); + }, + _ensureVisibility: function($el) { + var menuHeight = this.$menu.height() + parseInt(this.$menu.css("paddingTop"), 10) + parseInt(this.$menu.css("paddingBottom"), 10), menuScrollTop = this.$menu.scrollTop(), elTop = $el.position().top, elBottom = elTop + $el.outerHeight(true); + if (elTop < 0) { + this.$menu.scrollTop(menuScrollTop + elTop); + } else if (menuHeight < elBottom) { + this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight)); + } + }, + destroy: function() { + this.$menu.off(".tt"); + this.$menu = null; + }, + isVisible: function() { + return this.isOpen && !this.isEmpty; + }, + closeUnlessMouseIsOverDropdown: function() { + if (!this.isMouseOverDropdown) { + this.close(); + } + }, + close: function() { + if (this.isOpen) { + this.isOpen = false; + this.isMouseOverDropdown = false; + this._hide(); + this.$menu.find(".tt-suggestions > .tt-suggestion").removeClass("tt-is-under-cursor"); + this.trigger("closed"); + } + }, + open: function() { + if (!this.isOpen) { + this.isOpen = true; + !this.isEmpty && this._show(); + this.trigger("opened"); + } + }, + setLanguageDirection: function(dir) { + var ltrCss = { + left: "0", + right: "auto" + }, rtlCss = { + left: "auto", + right: " 0" + }; + dir === "ltr" ? this.$menu.css(ltrCss) : this.$menu.css(rtlCss); + }, + moveCursorUp: function() { + this._moveCursor(-1); + }, + moveCursorDown: function() { + this._moveCursor(+1); + }, + getSuggestionUnderCursor: function() { + var $suggestion = this._getSuggestions().filter(".tt-is-under-cursor").first(); + return $suggestion.length > 0 ? extractSuggestion($suggestion) : null; + }, + getFirstSuggestion: function() { + var $suggestion = this._getSuggestions().first(); + return $suggestion.length > 0 ? extractSuggestion($suggestion) : null; + }, + renderSuggestions: function(dataset, suggestions) { + var datasetClassName = "tt-dataset-" + dataset.name, wrapper = '<div class="tt-suggestion">%body</div>', compiledHtml, $suggestionsList, $dataset = this.$menu.find("." + datasetClassName), elBuilder, fragment, $el; + if ($dataset.length === 0) { + $suggestionsList = $(html.suggestionsList).css(css.suggestionsList); + $dataset = $("<div></div>").addClass(datasetClassName).append(dataset.header).append($suggestionsList).append(dataset.footer).appendTo(this.$menu); + } + if (suggestions.length > 0) { + this.isEmpty = false; + this.isOpen && this._show(); + elBuilder = document.createElement("div"); + fragment = document.createDocumentFragment(); + utils.each(suggestions, function(i, suggestion) { + suggestion.dataset = dataset.name; + compiledHtml = dataset.template(suggestion.datum); + elBuilder.innerHTML = wrapper.replace("%body", compiledHtml); + $el = $(elBuilder.firstChild).css(css.suggestion).data("suggestion", suggestion); + $el.children().each(function() { + $(this).css(css.suggestionChild); + }); + fragment.appendChild($el[0]); + }); + $dataset.show().find(".tt-suggestions").html(fragment); + } else { + this.clearSuggestions(dataset.name); + } + this.trigger("suggestionsRendered"); + }, + clearSuggestions: function(datasetName) { + var $datasets = datasetName ? this.$menu.find(".tt-dataset-" + datasetName) : this.$menu.find('[class^="tt-dataset-"]'), $suggestions = $datasets.find(".tt-suggestions"); + $datasets.hide(); + $suggestions.empty(); + if (this._getSuggestions().length === 0) { + this.isEmpty = true; + this._hide(); + } + } + }); + return DropdownView; + function extractSuggestion($el) { + return $el.data("suggestion"); + } + }(); + var TypeaheadView = function() { + var html = { + wrapper: '<span class="twitter-typeahead"></span>', + hint: '<input class="tt-hint" type="text" autocomplete="off" spellcheck="off" disabled>', + dropdown: '<span class="tt-dropdown-menu"></span>' + }, css = { + wrapper: { + position: "relative", + display: "inline-block" + }, + hint: { + position: "absolute", + top: "0", + left: "0", + borderColor: "transparent", + boxShadow: "none" + }, + query: { + position: "relative", + verticalAlign: "top", + backgroundColor: "transparent" + }, + dropdown: { + position: "absolute", + top: "100%", + left: "0", + zIndex: "100", + display: "none" + } + }; + if (utils.isMsie()) { + utils.mixin(css.query, { + backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)" + }); + } + if (utils.isMsie() && utils.isMsie() <= 7) { + utils.mixin(css.wrapper, { + display: "inline", + zoom: "1" + }); + utils.mixin(css.query, { + marginTop: "-1px" + }); + } + function TypeaheadView(o) { + var $menu, $input, $hint; + utils.bindAll(this); + this.$node = buildDomStructure(o.input); + this.datasets = o.datasets; + this.dir = null; + this.eventBus = o.eventBus; + $menu = this.$node.find(".tt-dropdown-menu"); + $input = this.$node.find(".tt-query"); + $hint = this.$node.find(".tt-hint"); + this.dropdownView = new DropdownView({ + menu: $menu + }).on("suggestionSelected", this._handleSelection).on("cursorMoved", this._clearHint).on("cursorMoved", this._setInputValueToSuggestionUnderCursor).on("cursorRemoved", this._setInputValueToQuery).on("cursorRemoved", this._updateHint).on("suggestionsRendered", this._updateHint).on("opened", this._updateHint).on("closed", this._clearHint).on("opened closed", this._propagateEvent); + this.inputView = new InputView({ + input: $input, + hint: $hint + }).on("focused", this._openDropdown).on("blured", this._closeDropdown).on("blured", this._setInputValueToQuery).on("enterKeyed tabKeyed", this._handleSelection).on("queryChanged", this._clearHint).on("queryChanged", this._clearSuggestions).on("queryChanged", this._getSuggestions).on("whitespaceChanged", this._updateHint).on("queryChanged whitespaceChanged", this._openDropdown).on("queryChanged whitespaceChanged", this._setLanguageDirection).on("escKeyed", this._closeDropdown).on("escKeyed", this._setInputValueToQuery).on("tabKeyed upKeyed downKeyed", this._managePreventDefault).on("upKeyed downKeyed", this._moveDropdownCursor).on("upKeyed downKeyed", this._openDropdown).on("tabKeyed leftKeyed rightKeyed", this._autocomplete); + } + utils.mixin(TypeaheadView.prototype, EventTarget, { + _managePreventDefault: function(e) { + var $e = e.data, hint, inputValue, preventDefault = false; + switch (e.type) { + case "tabKeyed": + hint = this.inputView.getHintValue(); + inputValue = this.inputView.getInputValue(); + preventDefault = hint && hint !== inputValue; + break; + + case "upKeyed": + case "downKeyed": + preventDefault = !$e.shiftKey && !$e.ctrlKey && !$e.metaKey; + break; + } + preventDefault && $e.preventDefault(); + }, + _setLanguageDirection: function() { + var dir = this.inputView.getLanguageDirection(); + if (dir !== this.dir) { + this.dir = dir; + this.$node.css("direction", dir); + this.dropdownView.setLanguageDirection(dir); + } + }, + _updateHint: function() { + var suggestion = this.dropdownView.getFirstSuggestion(), hint = suggestion ? suggestion.value : null, dropdownIsVisible = this.dropdownView.isVisible(), inputHasOverflow = this.inputView.isOverflow(), inputValue, query, escapedQuery, beginsWithQuery, match; + if (hint && dropdownIsVisible && !inputHasOverflow) { + inputValue = this.inputView.getInputValue(); + query = inputValue.replace(/\s{2,}/g, " ").replace(/^\s+/g, ""); + escapedQuery = utils.escapeRegExChars(query); + beginsWithQuery = new RegExp("^(?:" + escapedQuery + ")(.*$)", "i"); + match = beginsWithQuery.exec(hint); + this.inputView.setHintValue(inputValue + (match ? match[1] : "")); + } + }, + _clearHint: function() { + this.inputView.setHintValue(""); + }, + _clearSuggestions: function() { + this.dropdownView.clearSuggestions(); + }, + _setInputValueToQuery: function() { + this.inputView.setInputValue(this.inputView.getQuery()); + }, + _setInputValueToSuggestionUnderCursor: function(e) { + var suggestion = e.data; + this.inputView.setInputValue(suggestion.value, true); + }, + _openDropdown: function() { + this.dropdownView.open(); + }, + _closeDropdown: function(e) { + this.dropdownView[e.type === "blured" ? "closeUnlessMouseIsOverDropdown" : "close"](); + }, + _moveDropdownCursor: function(e) { + var $e = e.data; + if (!$e.shiftKey && !$e.ctrlKey && !$e.metaKey) { + this.dropdownView[e.type === "upKeyed" ? "moveCursorUp" : "moveCursorDown"](); + } + }, + _handleSelection: function(e) { + var byClick = e.type === "suggestionSelected", suggestion = byClick ? e.data : this.dropdownView.getSuggestionUnderCursor(); + if (suggestion) { + this.inputView.setInputValue(suggestion.value); + byClick ? this.inputView.focus() : e.data.preventDefault(); + byClick && utils.isMsie() ? utils.defer(this.dropdownView.close) : this.dropdownView.close(); + this.eventBus.trigger("selected", suggestion.datum, suggestion.dataset); + } + }, + _getSuggestions: function() { + var that = this, query = this.inputView.getQuery(); + if (utils.isBlankString(query)) { + return; + } + utils.each(this.datasets, function(i, dataset) { + dataset.getSuggestions(query, function(suggestions) { + if (query === that.inputView.getQuery()) { + that.dropdownView.renderSuggestions(dataset, suggestions); + } + }); + }); + }, + _autocomplete: function(e) { + var isCursorAtEnd, ignoreEvent, query, hint, suggestion; + if (e.type === "rightKeyed" || e.type === "leftKeyed") { + isCursorAtEnd = this.inputView.isCursorAtEnd(); + ignoreEvent = this.inputView.getLanguageDirection() === "ltr" ? e.type === "leftKeyed" : e.type === "rightKeyed"; + if (!isCursorAtEnd || ignoreEvent) { + return; + } + } + query = this.inputView.getQuery(); + hint = this.inputView.getHintValue(); + if (hint !== "" && query !== hint) { + suggestion = this.dropdownView.getFirstSuggestion(); + this.inputView.setInputValue(suggestion.value); + this.eventBus.trigger("autocompleted", suggestion.datum, suggestion.dataset); + } + }, + _propagateEvent: function(e) { + this.eventBus.trigger(e.type); + }, + destroy: function() { + this.inputView.destroy(); + this.dropdownView.destroy(); + destroyDomStructure(this.$node); + this.$node = null; + }, + setQuery: function(query) { + this.inputView.setQuery(query); + this.inputView.setInputValue(query); + this._clearHint(); + this._clearSuggestions(); + this._getSuggestions(); + } + }); + return TypeaheadView; + function buildDomStructure(input) { + var $wrapper = $(html.wrapper), $dropdown = $(html.dropdown), $input = $(input), $hint = $(html.hint); + $wrapper = $wrapper.css(css.wrapper); + $dropdown = $dropdown.css(css.dropdown); + $hint.css(css.hint).css({ + backgroundAttachment: $input.css("background-attachment"), + backgroundClip: $input.css("background-clip"), + backgroundColor: $input.css("background-color"), + backgroundImage: $input.css("background-image"), + backgroundOrigin: $input.css("background-origin"), + backgroundPosition: $input.css("background-position"), + backgroundRepeat: $input.css("background-repeat"), + backgroundSize: $input.css("background-size") + }); + $input.data("ttAttrs", { + dir: $input.attr("dir"), + autocomplete: $input.attr("autocomplete"), + spellcheck: $input.attr("spellcheck"), + style: $input.attr("style") + }); + $input.addClass("tt-query").attr({ + autocomplete: "off", + spellcheck: false + }).css(css.query); + try { + !$input.attr("dir") && $input.attr("dir", "auto"); + } catch (e) {} + return $input.wrap($wrapper).parent().prepend($hint).append($dropdown); + } + function destroyDomStructure($node) { + var $input = $node.find(".tt-query"); + utils.each($input.data("ttAttrs"), function(key, val) { + utils.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val); + }); + $input.detach().removeData("ttAttrs").removeClass("tt-query").insertAfter($node); + $node.remove(); + } + }(); + (function() { + var cache = {}, viewKey = "ttView", methods; + methods = { + initialize: function(datasetDefs) { + var datasets; + datasetDefs = utils.isArray(datasetDefs) ? datasetDefs : [ datasetDefs ]; + if (datasetDefs.length === 0) { + $.error("no datasets provided"); + } + datasets = utils.map(datasetDefs, function(o) { + var dataset = cache[o.name] ? cache[o.name] : new Dataset(o); + if (o.name) { + cache[o.name] = dataset; + } + return dataset; + }); + return this.each(initialize); + function initialize() { + var $input = $(this), deferreds, eventBus = new EventBus({ + el: $input + }); + deferreds = utils.map(datasets, function(dataset) { + return dataset.initialize(); + }); + $input.data(viewKey, new TypeaheadView({ + input: $input, + eventBus: eventBus = new EventBus({ + el: $input + }), + datasets: datasets + })); + $.when.apply($, deferreds).always(function() { + utils.defer(function() { + eventBus.trigger("initialized"); + }); + }); + } + }, + destroy: function() { + return this.each(destroy); + function destroy() { + var $this = $(this), view = $this.data(viewKey); + if (view) { + view.destroy(); + $this.removeData(viewKey); + } + } + }, + setQuery: function(query) { + return this.each(setQuery); + function setQuery() { + var view = $(this).data(viewKey); + view && view.setQuery(query); + } + } + }; + jQuery.fn.typeahead = function(method) { + if (methods[method]) { + return methods[method].apply(this, [].slice.call(arguments, 1)); + } else { + return methods.initialize.apply(this, arguments); + } + }; + })(); +})(window.jQuery); \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/lib/typeahead.js-bootstrap.css b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/lib/typeahead.js-bootstrap.css new file mode 100755 index 0000000..e44b673 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/lib/typeahead.js-bootstrap.css @@ -0,0 +1,49 @@ +.twitter-typeahead .tt-query, +.twitter-typeahead .tt-hint { + margin-bottom: 0; +} + +.tt-dropdown-menu { + min-width: 160px; + margin-top: 2px; + padding: 5px 0; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(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,.2); + -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); + box-shadow: 0 5px 10px rgba(0,0,0,.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; +} + +.tt-suggestion { + display: block; + padding: 3px 20px; +} + +.tt-suggestion.tt-is-under-cursor { + color: #fff; + 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) +} + +.tt-suggestion.tt-is-under-cursor a { + color: #fff; +} + +.tt-suggestion p { + margin: 0; +} diff --git a/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/typeaheadjs.js b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/typeaheadjs.js new file mode 100755 index 0000000..db2256a --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/typeaheadjs/typeaheadjs.js @@ -0,0 +1,86 @@ +/** +Typeahead.js input, based on [Twitter Typeahead](http://twitter.github.io/typeahead.js). +It is mainly replacement of typeahead in Bootstrap 3. + + +@class typeaheadjs +@extends text +@since 1.5.0 +@final +@example +<a href="#" id="country" data-type="typeaheadjs" data-pk="1" data-url="/post" data-title="Input country"></a> +<script> +$(function(){ + $('#country').editable({ + value: 'ru', + typeahead: { + name: 'country', + local: [ + {value: 'ru', tokens: ['Russia']}, + {value: 'gb', tokens: ['Great Britain']}, + {value: 'us', tokens: ['United States']} + ], + template: function(item) { + return item.tokens[0] + ' (' + item.value + ')'; + } + } + }); +}); +</script> +**/ +(function ($) { + "use strict"; + + var Constructor = function (options) { + this.init('typeaheadjs', options, Constructor.defaults); + }; + + $.fn.editableutils.inherit(Constructor, $.fn.editabletypes.text); + + $.extend(Constructor.prototype, { + render: function() { + this.renderClear(); + this.setClass(); + this.setAttr('placeholder'); + this.$input.typeahead(this.options.typeahead); + + // copy `input-sm | input-lg` classes to placeholder input + if($.fn.editableform.engine === 'bs3') { + if(this.$input.hasClass('input-sm')) { + this.$input.siblings('input.tt-hint').addClass('input-sm'); + } + if(this.$input.hasClass('input-lg')) { + this.$input.siblings('input.tt-hint').addClass('input-lg'); + } + } + } + }); + + Constructor.defaults = $.extend({}, $.fn.editabletypes.list.defaults, { + /** + @property tpl + @default <input type="text"> + **/ + tpl:'<input type="text">', + /** + Configuration of typeahead itself. + [Full list of options](https://github.com/twitter/typeahead.js#dataset). + + @property typeahead + @type object + @default null + **/ + typeahead: null, + /** + Whether to show `clear` button + + @property clear + @type boolean + @default true + **/ + clear: true + }); + + $.fn.editabletypes.typeaheadjs = Constructor; + +}(window.jQuery)); \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.css b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.css new file mode 100755 index 0000000..44ed777 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.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; +} diff --git a/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.js b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.js new file mode 100755 index 0000000..695d264 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.js @@ -0,0 +1,499 @@ +!function($, wysi) { + "use strict"; + + var tpl = { + "font-styles": function(locale, options) { + var size = (options && options.size) ? ' btn-'+options.size : ''; + return "<li class='dropdown'>" + + "<a class='btn dropdown-toggle" + size + "' data-toggle='dropdown' href='#'>" + + "<i class='icon-font'></i>&nbsp;<span class='current-font'>" + locale.font_styles.normal + "</span>&nbsp;<b class='caret'></b>" + + "</a>" + + "<ul class='dropdown-menu'>" + + "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='div' tabindex='-1'>" + locale.font_styles.normal + "</a></li>" + + "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h1' tabindex='-1'>" + locale.font_styles.h1 + "</a></li>" + + "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h2' tabindex='-1'>" + locale.font_styles.h2 + "</a></li>" + + "<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h3' tabindex='-1'>" + locale.font_styles.h3 + "</a></li>" + + "</ul>" + + "</li>"; + }, + + "emphasis": function(locale, options) { + var size = (options && options.size) ? ' btn-'+options.size : ''; + return "<li>" + + "<div class='btn-group'>" + + "<a class='btn" + size + "' data-wysihtml5-command='bold' title='CTRL+B' tabindex='-1'>" + locale.emphasis.bold + "</a>" + + "<a class='btn" + size + "' data-wysihtml5-command='italic' title='CTRL+I' tabindex='-1'>" + locale.emphasis.italic + "</a>" + + "<a class='btn" + size + "' data-wysihtml5-command='underline' title='CTRL+U' tabindex='-1'>" + locale.emphasis.underline + "</a>" + + "</div>" + + "</li>"; + }, + + "lists": function(locale, options) { + var size = (options && options.size) ? ' btn-'+options.size : ''; + return "<li>" + + "<div class='btn-group'>" + + "<a class='btn" + size + "' data-wysihtml5-command='insertUnorderedList' title='" + locale.lists.unordered + "' tabindex='-1'><i class='icon-list'></i></a>" + + "<a class='btn" + size + "' data-wysihtml5-command='insertOrderedList' title='" + locale.lists.ordered + "' tabindex='-1'><i class='icon-th-list'></i></a>" + + "<a class='btn" + size + "' data-wysihtml5-command='Outdent' title='" + locale.lists.outdent + "' tabindex='-1'><i class='icon-indent-right'></i></a>" + + "<a class='btn" + size + "' data-wysihtml5-command='Indent' title='" + locale.lists.indent + "' tabindex='-1'><i class='icon-indent-left'></i></a>" + + "</div>" + + "</li>"; + }, + + "link": function(locale, options) { + var size = (options && options.size) ? ' btn-'+options.size : ''; + return "<li>" + + "<div class='bootstrap-wysihtml5-insert-link-modal modal hide fade'>" + + "<div class='modal-header'>" + + "<a class='close' data-dismiss='modal'>&times;</a>" + + "<h3>" + locale.link.insert + "</h3>" + + "</div>" + + "<div class='modal-body'>" + + "<input value='http://' class='bootstrap-wysihtml5-insert-link-url input-xlarge'>" + + "</div>" + + "<div class='modal-footer'>" + + "<a href='#' class='btn' data-dismiss='modal'>" + locale.link.cancel + "</a>" + + "<a href='#' class='btn btn-primary' data-dismiss='modal'>" + locale.link.insert + "</a>" + + "</div>" + + "</div>" + + "<a class='btn" + size + "' data-wysihtml5-command='createLink' title='" + locale.link.insert + "' tabindex='-1'><i class='icon-share'></i></a>" + + "</li>"; + }, + + "image": function(locale, options) { + var size = (options && options.size) ? ' btn-'+options.size : ''; + return "<li>" + + "<div class='bootstrap-wysihtml5-insert-image-modal modal hide fade'>" + + "<div class='modal-header'>" + + "<a class='close' data-dismiss='modal'>&times;</a>" + + "<h3>" + locale.image.insert + "</h3>" + + "</div>" + + "<div class='modal-body'>" + + "<input value='http://' class='bootstrap-wysihtml5-insert-image-url input-xlarge'>" + + "</div>" + + "<div class='modal-footer'>" + + "<a href='#' class='btn' data-dismiss='modal'>" + locale.image.cancel + "</a>" + + "<a href='#' class='btn btn-primary' data-dismiss='modal'>" + locale.image.insert + "</a>" + + "</div>" + + "</div>" + + "<a class='btn" + size + "' data-wysihtml5-command='insertImage' title='" + locale.image.insert + "' tabindex='-1'><i class='icon-picture'></i></a>" + + "</li>"; + }, + + "html": function(locale, options) { + var size = (options && options.size) ? ' btn-'+options.size : ''; + return "<li>" + + "<div class='btn-group'>" + + "<a class='btn" + size + "' data-wysihtml5-action='change_view' title='" + locale.html.edit + "' tabindex='-1'><i class='icon-pencil'></i></a>" + + "</div>" + + "</li>"; + }, + + "color": function(locale, options) { + var size = (options && options.size) ? ' btn-'+options.size : ''; + return "<li class='dropdown'>" + + "<a class='btn dropdown-toggle" + size + "' data-toggle='dropdown' href='#' tabindex='-1'>" + + "<span class='current-color'>" + locale.colours.black + "</span>&nbsp;<b class='caret'></b>" + + "</a>" + + "<ul class='dropdown-menu'>" + + "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='black'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='black'>" + locale.colours.black + "</a></li>" + + "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='silver'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='silver'>" + locale.colours.silver + "</a></li>" + + "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='gray'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='gray'>" + locale.colours.gray + "</a></li>" + + "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='maroon'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='maroon'>" + locale.colours.maroon + "</a></li>" + + "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='red'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='red'>" + locale.colours.red + "</a></li>" + + "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='purple'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='purple'>" + locale.colours.purple + "</a></li>" + + "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='green'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='green'>" + locale.colours.green + "</a></li>" + + "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='olive'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='olive'>" + locale.colours.olive + "</a></li>" + + "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='navy'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='navy'>" + locale.colours.navy + "</a></li>" + + "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='blue'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='blue'>" + locale.colours.blue + "</a></li>" + + "<li><div class='wysihtml5-colors' data-wysihtml5-command-value='orange'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='orange'>" + locale.colours.orange + "</a></li>" + + "</ul>" + + "</li>"; + } + }; + + var templates = function(key, locale, options) { + return tpl[key](locale, options); + }; + + + var Wysihtml5 = function(el, options) { + this.el = el; + var toolbarOpts = options || defaultOptions; + for(var t in toolbarOpts.customTemplates) { + tpl[t] = toolbarOpts.customTemplates[t]; + } + this.toolbar = this.createToolbar(el, toolbarOpts); + 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 || {}; + + // Add the toolbar to a clone of the options object so multiple instances + // of the WYISYWG don't break because "toolbar" is already defined + options = $.extend(true, {}, 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 = $("<ul/>", { + '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], options)); + + 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 caretBookmark; + + var insertImage = function() { + var url = urlInput.val(); + urlInput.val(initialValue); + self.editor.currentView.element.focus(); + if (caretBookmark) { + self.editor.composer.selection.setBookmark(caretBookmark); + caretBookmark = null; + } + 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) { + self.editor.currentView.element.focus(false); + caretBookmark = self.editor.composer.selection.getBookmark(); + insertImageModal.appendTo('body').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 caretBookmark; + + var insertLink = function() { + var url = urlInput.val(); + urlInput.val(initialValue); + self.editor.currentView.element.focus(); + if (caretBookmark) { + self.editor.composer.selection.setBookmark(caretBookmark); + caretBookmark = null; + } + 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) { + self.editor.currentView.element.focus(false); + caretBookmark = self.editor.composer.selection.getBookmark(); + insertLinkModal.appendTo('body').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, + // to allow save and edit files with code tag hacks + "code": 1, + "pre": 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/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.min.js b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.min.js new file mode 100755 index 0000000..59d2961 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.min.js @@ -0,0 +1 @@ +!function($,wysi){"use strict";var tpl={"font-styles":function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"<li class='dropdown'>"+"<a class='btn dropdown-toggle"+size+"' data-toggle='dropdown' href='#'>"+"<i class='icon-font'></i>&nbsp;<span class='current-font'>"+locale.font_styles.normal+"</span>&nbsp;<b class='caret'></b>"+"</a>"+"<ul class='dropdown-menu'>"+"<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='div' tabindex='-1'>"+locale.font_styles.normal+"</a></li>"+"<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h1' tabindex='-1'>"+locale.font_styles.h1+"</a></li>"+"<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h2' tabindex='-1'>"+locale.font_styles.h2+"</a></li>"+"<li><a data-wysihtml5-command='formatBlock' data-wysihtml5-command-value='h3' tabindex='-1'>"+locale.font_styles.h3+"</a></li>"+"</ul>"+"</li>"},emphasis:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"<li>"+"<div class='btn-group'>"+"<a class='btn"+size+"' data-wysihtml5-command='bold' title='CTRL+B' tabindex='-1'>"+locale.emphasis.bold+"</a>"+"<a class='btn"+size+"' data-wysihtml5-command='italic' title='CTRL+I' tabindex='-1'>"+locale.emphasis.italic+"</a>"+"<a class='btn"+size+"' data-wysihtml5-command='underline' title='CTRL+U' tabindex='-1'>"+locale.emphasis.underline+"</a>"+"</div>"+"</li>"},lists:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"<li>"+"<div class='btn-group'>"+"<a class='btn"+size+"' data-wysihtml5-command='insertUnorderedList' title='"+locale.lists.unordered+"' tabindex='-1'><i class='icon-list'></i></a>"+"<a class='btn"+size+"' data-wysihtml5-command='insertOrderedList' title='"+locale.lists.ordered+"' tabindex='-1'><i class='icon-th-list'></i></a>"+"<a class='btn"+size+"' data-wysihtml5-command='Outdent' title='"+locale.lists.outdent+"' tabindex='-1'><i class='icon-indent-right'></i></a>"+"<a class='btn"+size+"' data-wysihtml5-command='Indent' title='"+locale.lists.indent+"' tabindex='-1'><i class='icon-indent-left'></i></a>"+"</div>"+"</li>"},link:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"<li>"+"<div class='bootstrap-wysihtml5-insert-link-modal modal hide fade'>"+"<div class='modal-header'>"+"<a class='close' data-dismiss='modal'>&times;</a>"+"<h3>"+locale.link.insert+"</h3>"+"</div>"+"<div class='modal-body'>"+"<input value='http://' class='bootstrap-wysihtml5-insert-link-url input-xlarge'>"+"</div>"+"<div class='modal-footer'>"+"<a href='#' class='btn' data-dismiss='modal'>"+locale.link.cancel+"</a>"+"<a href='#' class='btn btn-primary' data-dismiss='modal'>"+locale.link.insert+"</a>"+"</div>"+"</div>"+"<a class='btn"+size+"' data-wysihtml5-command='createLink' title='"+locale.link.insert+"' tabindex='-1'><i class='icon-share'></i></a>"+"</li>"},image:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"<li>"+"<div class='bootstrap-wysihtml5-insert-image-modal modal hide fade'>"+"<div class='modal-header'>"+"<a class='close' data-dismiss='modal'>&times;</a>"+"<h3>"+locale.image.insert+"</h3>"+"</div>"+"<div class='modal-body'>"+"<input value='http://' class='bootstrap-wysihtml5-insert-image-url input-xlarge'>"+"</div>"+"<div class='modal-footer'>"+"<a href='#' class='btn' data-dismiss='modal'>"+locale.image.cancel+"</a>"+"<a href='#' class='btn btn-primary' data-dismiss='modal'>"+locale.image.insert+"</a>"+"</div>"+"</div>"+"<a class='btn"+size+"' data-wysihtml5-command='insertImage' title='"+locale.image.insert+"' tabindex='-1'><i class='icon-picture'></i></a>"+"</li>"},html:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"<li>"+"<div class='btn-group'>"+"<a class='btn"+size+"' data-wysihtml5-action='change_view' title='"+locale.html.edit+"' tabindex='-1'><i class='icon-pencil'></i></a>"+"</div>"+"</li>"},color:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"<li class='dropdown'>"+"<a class='btn dropdown-toggle"+size+"' data-toggle='dropdown' href='#' tabindex='-1'>"+"<span class='current-color'>"+locale.colours.black+"</span>&nbsp;<b class='caret'></b>"+"</a>"+"<ul class='dropdown-menu'>"+"<li><div class='wysihtml5-colors' data-wysihtml5-command-value='black'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='black'>"+locale.colours.black+"</a></li>"+"<li><div class='wysihtml5-colors' data-wysihtml5-command-value='silver'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='silver'>"+locale.colours.silver+"</a></li>"+"<li><div class='wysihtml5-colors' data-wysihtml5-command-value='gray'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='gray'>"+locale.colours.gray+"</a></li>"+"<li><div class='wysihtml5-colors' data-wysihtml5-command-value='maroon'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='maroon'>"+locale.colours.maroon+"</a></li>"+"<li><div class='wysihtml5-colors' data-wysihtml5-command-value='red'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='red'>"+locale.colours.red+"</a></li>"+"<li><div class='wysihtml5-colors' data-wysihtml5-command-value='purple'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='purple'>"+locale.colours.purple+"</a></li>"+"<li><div class='wysihtml5-colors' data-wysihtml5-command-value='green'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='green'>"+locale.colours.green+"</a></li>"+"<li><div class='wysihtml5-colors' data-wysihtml5-command-value='olive'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='olive'>"+locale.colours.olive+"</a></li>"+"<li><div class='wysihtml5-colors' data-wysihtml5-command-value='navy'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='navy'>"+locale.colours.navy+"</a></li>"+"<li><div class='wysihtml5-colors' data-wysihtml5-command-value='blue'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='blue'>"+locale.colours.blue+"</a></li>"+"<li><div class='wysihtml5-colors' data-wysihtml5-command-value='orange'></div><a class='wysihtml5-colors-title' data-wysihtml5-command='foreColor' data-wysihtml5-command-value='orange'>"+locale.colours.orange+"</a></li>"+"</ul>"+"</li>"}};var templates=function(key,locale,options){return tpl[key](locale,options)};var Wysihtml5=function(el,options){this.el=el;var toolbarOpts=options||defaultOptions;for(var t in toolbarOpts.customTemplates){tpl[t]=toolbarOpts.customTemplates[t]}this.toolbar=this.createToolbar(el,toolbarOpts);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=$.extend(true,{},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=$("<ul/>",{"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],options));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 caretBookmark;var insertImage=function(){var url=urlInput.val();urlInput.val(initialValue);self.editor.currentView.element.focus();if(caretBookmark){self.editor.composer.selection.setBookmark(caretBookmark);caretBookmark=null}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){self.editor.currentView.element.focus(false);caretBookmark=self.editor.composer.selection.getBookmark();insertImageModal.appendTo("body").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 caretBookmark;var insertLink=function(){var url=urlInput.val();urlInput.val(initialValue);self.editor.currentView.element.focus();if(caretBookmark){self.editor.composer.selection.setBookmark(caretBookmark);caretBookmark=null}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){self.editor.currentView.element.focus(false);caretBookmark=self.editor.composer.selection.getBookmark();insertLinkModal.appendTo("body").modal("show");insertLinkModal.on("click.dismiss.modal",'[data-dismiss="modal"]',function(e){e.stopPropagation()});return false}else{return true}})}};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:{"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"}},span:1,div:1,code:1,pre:1}},stylesheets:["./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); \ No newline at end of file diff --git a/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysihtml5-0.3.0.js b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysihtml5-0.3.0.js new file mode 100755 index 0000000..939dca9 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysihtml5-0.3.0.js @@ -0,0 +1,9521 @@ +/** + * @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 = "<b>x</b>"; + 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): + + <ul id="ul"><li id="a">| a </li><li id="b"> b |</li></ul> + + 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 <pre> 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("<html><head></head><body>12</body></html>"); + 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 <iframe security="restricted"> + * + * http://msdn.microsoft.com/en-us/library/ms534622(v=vs.85).aspx + * http://blogs.msdn.com/b/ie/archive/2008/01/18/using-frames-more-securely.aspx + * + * HTML5 sandboxed iframes are still buggy and their DOM is not reachable from the outside (except when using postMessage) + */ + supportsSandboxedIframes: function() { + return isIE; + }, + + /** + * IE6+7 throw a mixed content warning when the src of an iframe + * is empty/unset or about:blank + * window.querySelector is implemented as of IE8 + */ + throwsMixedContentWarningWhenIframeSrcIsEmpty: function() { + return !("querySelector" in document); + }, + + /** + * Whether the caret is correctly displayed in contentEditable elements + * Firefox sometimes shows a huge caret in the beginning after focusing + */ + displaysCaretInEmptyContentEditableCorrectly: function() { + return !isGecko; + }, + + /** + * Opera and IE are the only browsers who offer the css value + * in the original unit, thx to the currentStyle object + * All other browsers provide the computed style in px via window.getComputedStyle + */ + hasCurrentStyleProperty: function() { + return "currentStyle" in testElement; + }, + + /** + * Whether the browser inserts a <br> when pressing enter in a contentEditable element + */ + insertsLineBreaksOnReturn: function() { + return isGecko; + }, + + supportsPlaceholderAttributeOn: function(element) { + return "placeholder" in element; + }, + + supportsEvent: function(eventName) { + return "on" + eventName in testElement || (function() { + testElement.setAttribute("on" + eventName, "return;"); + return typeof(testElement["on" + eventName]) === "function"; + })(); + }, + + /** + * Opera doesn't correctly fire focus/blur events when clicking in- and outside of iframe + */ + supportsEventsInIframeCorrectly: function() { + return !isOpera; + }, + + /** + * Chrome & Safari only fire the ondrop/ondragend/... events when the ondragover event is cancelled + * with event.preventDefault + * Firefox 3.6 fires those events anyway, but the mozilla doc says that the dragover/dragenter event needs + * to be cancelled + */ + firesOnDropOnlyWhenOnDragOverIsCancelled: function() { + return isWebKit || isGecko; + }, + + /** + * Whether the browser supports the event.dataTransfer property in a proper way + */ + supportsDataTransfer: function() { + try { + // Firefox doesn't support dataTransfer in a safe way, it doesn't strip script code in the html payload (like Chrome does) + return isWebKit && (window.Clipboard || window.DataTransfer).prototype.getData; + } catch(e) { + return false; + } + }, + + /** + * Everything below IE9 doesn't know how to treat HTML5 tags + * + * @param {Object} context The document object on which to check HTML5 support + * + * @example + * wysihtml5.browser.supportsHTML5Tags(document); + */ + supportsHTML5Tags: function(context) { + var element = context.createElement("div"), + html5 = "<article>foo</article>"; + element.innerHTML = html5; + return element.innerHTML.toLowerCase() === html5; + }, + + /** + * Checks whether a document supports a certain queryCommand + * In particular, Opera needs a reference to a document that has a contentEditable in it's dom tree + * in oder to report correct results + * + * @param {Object} doc Document object on which to check for a query command + * @param {String} command The query command to check for + * @return {Boolean} + * + * @example + * wysihtml5.browser.supportsCommand(document, "bold"); + */ + supportsCommand: (function() { + // Following commands are supported but contain bugs in some browsers + var buggyCommands = { + // formatBlock fails with some tags (eg. <blockquote>) + "formatBlock": isIE, + // When inserting unordered or ordered lists in Firefox, Chrome or Safari, the current selection or line gets + // converted into a list (<ul><li>...</li></ul>, <ol><li>...</li></ol>) + // IE and Opera act a bit different here as they convert the entire content of the current block element into a list + "insertUnorderedList": isIE || isOpera || isWebKit, + "insertOrderedList": isIE || isOpera || isWebKit + }; + + // Firefox throws errors for queryCommandSupported, so we have to build up our own object of supported commands + var supported = { + "insertHTML": isGecko + }; + + return function(doc, command) { + var isBuggy = buggyCommands[command]; + if (!isBuggy) { + // Firefox throws errors when invoking queryCommandSupported or queryCommandEnabled + try { + return doc.queryCommandSupported(command); + } catch(e1) {} + + try { + return doc.queryCommandEnabled(command); + } catch(e2) { + return !!supported[command]; + } + } + return false; + }; + })(), + + /** + * IE: URLs starting with: + * www., http://, https://, ftp://, gopher://, mailto:, new:, snews:, telnet:, wasis:, file://, + * nntp://, newsrc:, ldap://, ldaps://, outlook:, mic:// and url: + * will automatically be auto-linked when either the user inserts them via copy&paste or presses the + * space bar when the caret is directly after such an url. + * This behavior cannot easily be avoided in IE < 9 since the logic is hardcoded in the mshtml.dll + * (related blog post on msdn + * http://blogs.msdn.com/b/ieinternals/archive/2009/09/17/prevent-automatic-hyperlinking-in-contenteditable-html.aspx). + */ + doesAutoLinkingInContentEditable: function() { + return isIE; + }, + + /** + * As stated above, IE auto links urls typed into contentEditable elements + * Since IE9 it's possible to prevent this behavior + */ + canDisableAutoLinking: function() { + return this.supportsCommand(document, "AutoUrlDetect"); + }, + + /** + * IE leaves an empty paragraph in the contentEditable element after clearing it + * Chrome/Safari sometimes an empty <div> + */ + clearsContentEditableCorrectly: function() { + return isGecko || isOpera || isWebKit; + }, + + /** + * IE gives wrong results for getAttribute + */ + supportsGetAttributeCorrectly: function() { + var td = document.createElement("td"); + return td.getAttribute("rowspan") != "1"; + }, + + /** + * When clicking on images in IE, Opera and Firefox, they are selected, which makes it easy to interact with them. + * Chrome and Safari both don't support this + */ + canSelectImagesInContentEditable: function() { + return isGecko || isIE || isOpera; + }, + + /** + * When the caret is in an empty list (<ul><li>|</li></ul>) which is the first child in an contentEditable container + * pressing backspace doesn't remove the entire list as done in other browsers + */ + clearsListsInContentEditableCorrectly: function() { + return isGecko || isIE || isWebKit; + }, + + /** + * All browsers except Safari and Chrome automatically scroll the range/caret position into view + */ + autoScrollsToCaret: function() { + return !isWebKit; + }, + + /** + * Check whether the browser automatically closes tags that don't need to be opened + */ + autoClosesUnclosedTags: function() { + var clonedTestElement = testElement.cloneNode(false), + returnValue, + innerHTML; + + clonedTestElement.innerHTML = "<p><div></div>"; + innerHTML = clonedTestElement.innerHTML.toLowerCase(); + returnValue = innerHTML === "<p></p><div></div>" || innerHTML === "<p><div></div></p>"; + + // Cache result by overwriting current function + this.autoClosesUnclosedTags = function() { return returnValue; }; + + return returnValue; + }, + + /** + * Whether the browser supports the native document.getElementsByClassName which returns live NodeLists + */ + supportsNativeGetElementsByClassName: function() { + return String(document.getElementsByClassName).indexOf("[native code]") !== -1; + }, + + /** + * As of now (19.04.2011) only supported by Firefox 4 and Chrome + * See https://developer.mozilla.org/en/DOM/Selection/modify + */ + supportsSelectionModify: function() { + return "getSelection" in window && "modify" in window.getSelection(); + }, + + /** + * Whether the browser supports the classList object for fast className manipulation + * See https://developer.mozilla.org/en/DOM/element.classList + */ + supportsClassList: function() { + return "classList" in testElement; + }, + + /** + * Opera needs a white space after a <br> in order to position the caret correctly + */ + needsSpaceAfterLineBreak: function() { + return isOpera; + }, + + /** + * Whether the browser supports the speech api on the given element + * See http://mikepultz.com/2011/03/accessing-google-speech-api-chrome-11/ + * + * @example + * var input = document.createElement("input"); + * if (wysihtml5.browser.supportsSpeechApiOn(input)) { + * // ... + * } + */ + supportsSpeechApiOn: function(input) { + var chromeVersion = userAgent.match(/Chrome\/(\d+)/) || [, 0]; + return chromeVersion[1] >= 11 && ("onwebkitspeechchange" in input || "speech" in input); + }, + + /** + * IE9 crashes when setting a getter via Object.defineProperty on XMLHttpRequest or XDomainRequest + * See https://connect.microsoft.com/ie/feedback/details/650112 + * or try the POC http://tifftiff.de/ie9_crash/ + */ + crashesWhenDefineProperty: function(property) { + return isIE && (property === "XMLHttpRequest" || property === "XDomainRequest"); + }, + + /** + * IE is the only browser who fires the "focus" event not immediately when .focus() is called on an element + */ + doesAsyncFocus: function() { + return isIE; + }, + + /** + * In IE it's impssible for the user and for the selection library to set the caret after an <img> when it's the lastChild in the document + */ + hasProblemsSettingCaretAfterImg: function() { + return isIE; + }, + + hasUndoInContextMenu: function() { + return isGecko || isChrome || isOpera; + } + }; +})();wysihtml5.lang.array = function(arr) { + return { + /** + * Check whether a given object exists in an array + * + * @example + * wysihtml5.lang.array([1, 2]).contains(1); + * // => true + */ + contains: function(needle) { + if (arr.indexOf) { + return arr.indexOf(needle) !== -1; + } else { + for (var i=0, length=arr.length; i<length; i++) { + if (arr[i] === needle) { return true; } + } + return false; + } + }, + + /** + * Substract one array from another + * + * @example + * wysihtml5.lang.array([1, 2, 3, 4]).without([3, 4]); + * // => [1, 2] + */ + without: function(arrayToSubstract) { + arrayToSubstract = wysihtml5.lang.array(arrayToSubstract); + var newArr = [], + i = 0, + length = arr.length; + for (; i<length; i++) { + if (!arrayToSubstract.contains(arr[i])) { + newArr.push(arr[i]); + } + } + return newArr; + }, + + /** + * Return a clean native array + * + * Following will convert a Live NodeList to a proper Array + * @example + * var childNodes = wysihtml5.lang.array(document.body.childNodes).get(); + */ + get: function() { + var i = 0, + length = arr.length, + newArray = []; + for (; i<length; i++) { + newArray.push(arr[i]); + } + return newArray; + } + }; +};wysihtml5.lang.Dispatcher = Base.extend( + /** @scope wysihtml5.lang.Dialog.prototype */ { + observe: function(eventName, handler) { + this.events = this.events || {}; + this.events[eventName] = this.events[eventName] || []; + this.events[eventName].push(handler); + return this; + }, + + on: function() { + return this.observe.apply(this, wysihtml5.lang.array(arguments).get()); + }, + + fire: function(eventName, payload) { + this.events = this.events || {}; + var handlers = this.events[eventName] || [], + i = 0; + for (; i<handlers.length; i++) { + handlers[i].call(this, payload); + } + return this; + }, + + stopObserving: function(eventName, handler) { + this.events = this.events || {}; + var i = 0, + handlers, + newHandlers; + if (eventName) { + handlers = this.events[eventName] || [], + newHandlers = []; + for (; i<handlers.length; i++) { + if (handlers[i] !== handler && handler) { + newHandlers.push(handlers[i]); + } + } + this.events[eventName] = newHandlers; + } else { + // Clean up all events + this.events = {}; + } + return this; + } +});wysihtml5.lang.object = function(obj) { + return { + /** + * @example + * wysihtml5.lang.object({ foo: 1, bar: 1 }).merge({ bar: 2, baz: 3 }).get(); + * // => { foo: 1, bar: 2, baz: 3 } + */ + merge: function(otherObj) { + for (var i in otherObj) { + obj[i] = otherObj[i]; + } + return this; + }, + + get: function() { + return obj; + }, + + /** + * @example + * wysihtml5.lang.object({ foo: 1 }).clone(); + * // => { foo: 1 } + */ + clone: function() { + var newObj = {}, + i; + for (i in obj) { + newObj[i] = obj[i]; + } + return newObj; + }, + + /** + * @example + * wysihtml5.lang.object([]).isArray(); + * // => true + */ + isArray: function() { + return Object.prototype.toString.call(obj) === "[object Array]"; + } + }; +};(function() { + var WHITE_SPACE_START = /^\s+/, + WHITE_SPACE_END = /\s+$/; + wysihtml5.lang.string = function(str) { + str = String(str); + return { + /** + * @example + * wysihtml5.lang.string(" foo ").trim(); + * // => "foo" + */ + trim: function() { + return str.replace(WHITE_SPACE_START, "").replace(WHITE_SPACE_END, ""); + }, + + /** + * @example + * wysihtml5.lang.string("Hello #{name}").interpolate({ name: "Christopher" }); + * // => "Hello Christopher" + */ + interpolate: function(vars) { + for (var i in vars) { + str = this.replace("#{" + i + "}").by(vars[i]); + } + return str; + }, + + /** + * @example + * wysihtml5.lang.string("Hello Tom").replace("Tom").with("Hans"); + * // => "Hello Hans" + */ + replace: function(search) { + return { + by: function(replace) { + return str.split(search).join(replace); + } + } + } + }; + }; +})();/** + * Find urls in descendant text nodes of an element and auto-links them + * Inspired by http://james.padolsey.com/javascript/find-and-replace-text-with-javascript/ + * + * @param {Element} element Container element in which to search for urls + * + * @example + * <div id="text-container">Please click here: www.google.com</div> + * <script>wysihtml5.dom.autoLink(document.getElementById("text-container"));</script> + */ +(function(wysihtml5) { + var /** + * Don't auto-link urls that are contained in the following elements: + */ + IGNORE_URLS_IN = wysihtml5.lang.array(["CODE", "PRE", "A", "SCRIPT", "HEAD", "TITLE", "STYLE"]), + /** + * revision 1: + * /(\S+\.{1}[^\s\,\.\!]+)/g + * + * revision 2: + * /(\b(((https?|ftp):\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;\[\]]*[-A-Z0-9+&@#\/%=~_|])/gim + * + * put this in the beginning if you don't wan't to match within a word + * (^|[\>\(\{\[\s\>]) + */ + URL_REG_EXP = /((https?:\/\/|www\.)[^\s<]{3,})/gi, + TRAILING_CHAR_REG_EXP = /([^\w\/\-](,?))$/i, + MAX_DISPLAY_LENGTH = 100, + BRACKETS = { ")": "(", "]": "[", "}": "{" }; + + function autoLink(element) { + if (_hasParentThatShouldBeIgnored(element)) { + return element; + } + + if (element === element.ownerDocument.documentElement) { + element = element.ownerDocument.body; + } + + return _parseNode(element); + } + + /** + * This is basically a rebuild of + * the rails auto_link_urls text helper + */ + function _convertUrlsToLinks(str) { + return str.replace(URL_REG_EXP, function(match, url) { + var punctuation = (url.match(TRAILING_CHAR_REG_EXP) || [])[1] || "", + opening = BRACKETS[punctuation]; + url = url.replace(TRAILING_CHAR_REG_EXP, ""); + + if (url.split(opening).length > url.split(punctuation).length) { + url = url + punctuation; + punctuation = ""; + } + var realUrl = url, + displayUrl = url; + if (url.length > MAX_DISPLAY_LENGTH) { + displayUrl = displayUrl.substr(0, MAX_DISPLAY_LENGTH) + "..."; + } + // Add http prefix if necessary + if (realUrl.substr(0, 4) === "www.") { + realUrl = "http://" + realUrl; + } + + return '<a href="' + realUrl + '">' + displayUrl + '</a>' + punctuation; + }); + } + + /** + * Creates or (if already cached) returns a temp element + * for the given document object + */ + function _getTempElement(context) { + var tempElement = context._wysihtml5_tempElement; + if (!tempElement) { + tempElement = context._wysihtml5_tempElement = context.createElement("div"); + } + return tempElement; + } + + /** + * Replaces the original text nodes with the newly auto-linked dom tree + */ + function _wrapMatchesInNode(textNode) { + var parentNode = textNode.parentNode, + tempElement = _getTempElement(parentNode.ownerDocument); + + // We need to insert an empty/temporary <span /> to fix IE quirks + // Elsewise IE would strip white space in the beginning + tempElement.innerHTML = "<span></span>" + _convertUrlsToLinks(textNode.data); + tempElement.removeChild(tempElement.firstChild); + + while (tempElement.firstChild) { + // inserts tempElement.firstChild before textNode + parentNode.insertBefore(tempElement.firstChild, textNode); + } + parentNode.removeChild(textNode); + } + + function _hasParentThatShouldBeIgnored(node) { + var nodeName; + while (node.parentNode) { + node = node.parentNode; + nodeName = node.nodeName; + if (IGNORE_URLS_IN.contains(nodeName)) { + return true; + } else if (nodeName === "body") { + return false; + } + } + return false; + } + + function _parseNode(element) { + if (IGNORE_URLS_IN.contains(element.nodeName)) { + return; + } + + if (element.nodeType === wysihtml5.TEXT_NODE && element.data.match(URL_REG_EXP)) { + _wrapMatchesInNode(element); + return; + } + + var childNodes = wysihtml5.lang.array(element.childNodes).get(), + childNodesLength = childNodes.length, + i = 0; + + for (; i<childNodesLength; i++) { + _parseNode(childNodes[i]); + } + + return element; + } + + wysihtml5.dom.autoLink = autoLink; + + // Reveal url reg exp to the outside + wysihtml5.dom.autoLink.URL_REG_EXP = URL_REG_EXP; +})(wysihtml5);(function(wysihtml5) { + var supportsClassList = wysihtml5.browser.supportsClassList(), + api = wysihtml5.dom; + + api.addClass = function(element, className) { + if (supportsClassList) { + return element.classList.add(className); + } + if (api.hasClass(element, className)) { + return; + } + element.className += " " + className; + }; + + api.removeClass = function(element, className) { + if (supportsClassList) { + return element.classList.remove(className); + } + + element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), " "); + }; + + api.hasClass = function(element, className) { + if (supportsClassList) { + return element.classList.contains(className); + } + + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); + }; +})(wysihtml5); +wysihtml5.dom.contains = (function() { + var documentElement = document.documentElement; + if (documentElement.contains) { + return function(container, element) { + if (element.nodeType !== wysihtml5.ELEMENT_NODE) { + element = element.parentNode; + } + return container !== element && container.contains(element); + }; + } else if (documentElement.compareDocumentPosition) { + return function(container, element) { + // https://developer.mozilla.org/en/DOM/Node.compareDocumentPosition + return !!(container.compareDocumentPosition(element) & 16); + }; + } +})();/** + * Converts an HTML fragment/element into a unordered/ordered list + * + * @param {Element} element The element which should be turned into a list + * @param {String} listType The list type in which to convert the tree (either "ul" or "ol") + * @return {Element} The created list + * + * @example + * <!-- Assume the following dom: --> + * <span id="pseudo-list"> + * eminem<br> + * dr. dre + * <div>50 Cent</div> + * </span> + * + * <script> + * wysihtml5.dom.convertToList(document.getElementById("pseudo-list"), "ul"); + * </script> + * + * <!-- Will result in: --> + * <ul> + * <li>eminem</li> + * <li>dr. dre</li> + * <li>50 Cent</li> + * </ul> + */ +wysihtml5.dom.convertToList = (function() { + function _createListItem(doc, list) { + var listItem = doc.createElement("li"); + list.appendChild(listItem); + return listItem; + } + + function _createList(doc, type) { + return doc.createElement(type); + } + + function convertToList(element, listType) { + if (element.nodeName === "UL" || element.nodeName === "OL" || element.nodeName === "MENU") { + // Already a list + return element; + } + + var doc = element.ownerDocument, + list = _createList(doc, listType), + lineBreaks = element.querySelectorAll("br"), + lineBreaksLength = lineBreaks.length, + childNodes, + childNodesLength, + childNode, + lineBreak, + parentNode, + isBlockElement, + isLineBreak, + currentListItem, + i; + + // First find <br> at the end of inline elements and move them behind them + for (i=0; i<lineBreaksLength; i++) { + lineBreak = lineBreaks[i]; + while ((parentNode = lineBreak.parentNode) && parentNode !== element && parentNode.lastChild === lineBreak) { + if (wysihtml5.dom.getStyle("display").from(parentNode) === "block") { + parentNode.removeChild(lineBreak); + break; + } + wysihtml5.dom.insert(lineBreak).after(lineBreak.parentNode); + } + } + + childNodes = wysihtml5.lang.array(element.childNodes).get(); + childNodesLength = childNodes.length; + + for (i=0; i<childNodesLength; i++) { + currentListItem = currentListItem || _createListItem(doc, list); + childNode = childNodes[i]; + isBlockElement = wysihtml5.dom.getStyle("display").from(childNode) === "block"; + isLineBreak = childNode.nodeName === "BR"; + + if (isBlockElement) { + // Append blockElement to current <li> if empty, otherwise create a new one + currentListItem = currentListItem.firstChild ? _createListItem(doc, list) : currentListItem; + currentListItem.appendChild(childNode); + currentListItem = null; + continue; + } + + if (isLineBreak) { + // Only create a new list item in the next iteration when the current one has already content + currentListItem = currentListItem.firstChild ? null : currentListItem; + continue; + } + + currentListItem.appendChild(childNode); + } + + element.parentNode.replaceChild(list, element); + return list; + } + + return convertToList; +})();/** + * Copy a set of attributes from one element to another + * + * @param {Array} attributesToCopy List of attributes which should be copied + * @return {Object} Returns an object which offers the "from" method which can be invoked with the element where to + * copy the attributes from., this again returns an object which provides a method named "to" which can be invoked + * with the element where to copy the attributes to (see example) + * + * @example + * var textarea = document.querySelector("textarea"), + * div = document.querySelector("div[contenteditable=true]"), + * anotherDiv = document.querySelector("div.preview"); + * wysihtml5.dom.copyAttributes(["spellcheck", "value", "placeholder"]).from(textarea).to(div).andTo(anotherDiv); + * + */ +wysihtml5.dom.copyAttributes = function(attributesToCopy) { + return { + from: function(elementToCopyFrom) { + return { + to: function(elementToCopyTo) { + var attribute, + i = 0, + length = attributesToCopy.length; + for (; i<length; i++) { + attribute = attributesToCopy[i]; + if (typeof(elementToCopyFrom[attribute]) !== "undefined" && elementToCopyFrom[attribute] !== "") { + elementToCopyTo[attribute] = elementToCopyFrom[attribute]; + } + } + return { andTo: arguments.callee }; + } + }; + } + }; +};/** + * Copy a set of styles from one element to another + * Please note that this only works properly across browsers when the element from which to copy the styles + * is in the dom + * + * Interesting article on how to copy styles + * + * @param {Array} stylesToCopy List of styles which should be copied + * @return {Object} Returns an object which offers the "from" method which can be invoked with the element where to + * copy the styles from., this again returns an object which provides a method named "to" which can be invoked + * with the element where to copy the styles to (see example) + * + * @example + * var textarea = document.querySelector("textarea"), + * div = document.querySelector("div[contenteditable=true]"), + * anotherDiv = document.querySelector("div.preview"); + * wysihtml5.dom.copyStyles(["overflow-y", "width", "height"]).from(textarea).to(div).andTo(anotherDiv); + * + */ +(function(dom) { + + /** + * Mozilla, WebKit and Opera recalculate the computed width when box-sizing: boder-box; is set + * So if an element has "width: 200px; -moz-box-sizing: border-box; border: 1px;" then + * its computed css width will be 198px + */ + var BOX_SIZING_PROPERTIES = ["-webkit-box-sizing", "-moz-box-sizing", "-ms-box-sizing", "box-sizing"]; + + var shouldIgnoreBoxSizingBorderBox = function(element) { + if (hasBoxSizingBorderBox(element)) { + return parseInt(dom.getStyle("width").from(element), 10) < element.offsetWidth; + } + return false; + }; + + var hasBoxSizingBorderBox = function(element) { + var i = 0, + length = BOX_SIZING_PROPERTIES.length; + for (; i<length; i++) { + if (dom.getStyle(BOX_SIZING_PROPERTIES[i]).from(element) === "border-box") { + return BOX_SIZING_PROPERTIES[i]; + } + } + }; + + dom.copyStyles = function(stylesToCopy) { + return { + from: function(element) { + if (shouldIgnoreBoxSizingBorderBox(element)) { + stylesToCopy = wysihtml5.lang.array(stylesToCopy).without(BOX_SIZING_PROPERTIES); + } + + var cssText = "", + length = stylesToCopy.length, + i = 0, + property; + for (; i<length; i++) { + property = stylesToCopy[i]; + cssText += property + ":" + dom.getStyle(property).from(element) + ";"; + } + + return { + to: function(element) { + dom.setStyles(cssText).on(element); + return { andTo: arguments.callee }; + } + }; + } + }; + }; +})(wysihtml5.dom);/** + * Event Delegation + * + * @example + * wysihtml5.dom.delegate(document.body, "a", "click", function() { + * // foo + * }); + */ +(function(wysihtml5) { + + wysihtml5.dom.delegate = function(container, selector, eventName, handler) { + return wysihtml5.dom.observe(container, eventName, function(event) { + var target = event.target, + match = wysihtml5.lang.array(container.querySelectorAll(selector)); + + while (target && target !== container) { + if (match.contains(target)) { + handler.call(target, event); + break; + } + target = target.parentNode; + } + }); + }; + +})(wysihtml5);/** + * Returns the given html wrapped in a div element + * + * Fixing IE's inability to treat unknown elements (HTML5 section, article, ...) correctly + * when inserted via innerHTML + * + * @param {String} html The html which should be wrapped in a dom element + * @param {Obejct} [context] Document object of the context the html belongs to + * + * @example + * wysihtml5.dom.getAsDom("<article>foo</article>"); + */ +wysihtml5.dom.getAsDom = (function() { + + var _innerHTMLShiv = function(html, context) { + var tempElement = context.createElement("div"); + tempElement.style.display = "none"; + context.body.appendChild(tempElement); + // IE throws an exception when trying to insert <frameset></frameset> via innerHTML + try { tempElement.innerHTML = html; } catch(e) {} + context.body.removeChild(tempElement); + return tempElement; + }; + + /** + * Make sure IE supports HTML5 tags, which is accomplished by simply creating one instance of each element + */ + var _ensureHTML5Compatibility = function(context) { + if (context._wysihtml5_supportsHTML5Tags) { + return; + } + for (var i=0, length=HTML5_ELEMENTS.length; i<length; i++) { + context.createElement(HTML5_ELEMENTS[i]); + } + context._wysihtml5_supportsHTML5Tags = true; + }; + + + /** + * List of html5 tags + * taken from http://simon.html5.org/html5-elements + */ + var HTML5_ELEMENTS = [ + "abbr", "article", "aside", "audio", "bdi", "canvas", "command", "datalist", "details", "figcaption", + "figure", "footer", "header", "hgroup", "keygen", "mark", "meter", "nav", "output", "progress", + "rp", "rt", "ruby", "svg", "section", "source", "summary", "time", "track", "video", "wbr" + ]; + + return function(html, context) { + context = context || document; + var tempElement; + if (typeof(html) === "object" && html.nodeType) { + tempElement = context.createElement("div"); + tempElement.appendChild(html); + } else if (wysihtml5.browser.supportsHTML5Tags(context)) { + tempElement = context.createElement("div"); + tempElement.innerHTML = html; + } else { + _ensureHTML5Compatibility(context); + tempElement = _innerHTMLShiv(html, context); + } + return tempElement; + }; +})();/** + * Walks the dom tree from the given node up until it finds a match + * Designed for optimal performance. + * + * @param {Element} node The from which to check the parent nodes + * @param {Object} matchingSet Object to match against (possible properties: nodeName, className, classRegExp) + * @param {Number} [levels] How many parents should the function check up from the current node (defaults to 50) + * @return {null|Element} Returns the first element that matched the desiredNodeName(s) + * @example + * var listElement = wysihtml5.dom.getParentElement(document.querySelector("li"), { nodeName: ["MENU", "UL", "OL"] }); + * // ... or ... + * var unorderedListElement = wysihtml5.dom.getParentElement(document.querySelector("li"), { nodeName: "UL" }); + * // ... or ... + * var coloredElement = wysihtml5.dom.getParentElement(myTextNode, { nodeName: "SPAN", className: "wysiwyg-color-red", classRegExp: /wysiwyg-color-[a-z]/g }); + */ +wysihtml5.dom.getParentElement = (function() { + + function _isSameNodeName(nodeName, desiredNodeNames) { + if (!desiredNodeNames || !desiredNodeNames.length) { + return true; + } + + if (typeof(desiredNodeNames) === "string") { + return nodeName === desiredNodeNames; + } else { + return wysihtml5.lang.array(desiredNodeNames).contains(nodeName); + } + } + + function _isElement(node) { + return node.nodeType === wysihtml5.ELEMENT_NODE; + } + + function _hasClassName(element, className, classRegExp) { + var classNames = (element.className || "").match(classRegExp) || []; + if (!className) { + return !!classNames.length; + } + return classNames[classNames.length - 1] === className; + } + + function _getParentElementWithNodeName(node, nodeName, levels) { + while (levels-- && node && node.nodeName !== "BODY") { + if (_isSameNodeName(node.nodeName, nodeName)) { + return node; + } + node = node.parentNode; + } + return null; + } + + function _getParentElementWithNodeNameAndClassName(node, nodeName, className, classRegExp, levels) { + while (levels-- && node && node.nodeName !== "BODY") { + if (_isElement(node) && + _isSameNodeName(node.nodeName, nodeName) && + _hasClassName(node, className, classRegExp)) { + return node; + } + node = node.parentNode; + } + return null; + } + + return function(node, matchingSet, levels) { + levels = levels || 50; // Go max 50 nodes upwards from current node + if (matchingSet.className || matchingSet.classRegExp) { + return _getParentElementWithNodeNameAndClassName( + node, matchingSet.nodeName, matchingSet.className, matchingSet.classRegExp, levels + ); + } else { + return _getParentElementWithNodeName( + node, matchingSet.nodeName, levels + ); + } + }; +})(); +/** + * Get element's style for a specific css property + * + * @param {Element} element The element on which to retrieve the style + * @param {String} property The CSS property to retrieve ("float", "display", "text-align", ...) + * + * @example + * wysihtml5.dom.getStyle("display").from(document.body); + * // => "block" + */ +wysihtml5.dom.getStyle = (function() { + var stylePropertyMapping = { + "float": ("styleFloat" in document.createElement("div").style) ? "styleFloat" : "cssFloat" + }, + REG_EXP_CAMELIZE = /\-[a-z]/g; + + function camelize(str) { + return str.replace(REG_EXP_CAMELIZE, function(match) { + return match.charAt(1).toUpperCase(); + }); + } + + return function(property) { + return { + from: function(element) { + if (element.nodeType !== wysihtml5.ELEMENT_NODE) { + return; + } + + var doc = element.ownerDocument, + camelizedProperty = stylePropertyMapping[property] || camelize(property), + style = element.style, + currentStyle = element.currentStyle, + styleValue = style[camelizedProperty]; + if (styleValue) { + return styleValue; + } + + // currentStyle is no standard and only supported by Opera and IE but it has one important advantage over the standard-compliant + // window.getComputedStyle, since it returns css property values in their original unit: + // If you set an elements width to "50%", window.getComputedStyle will give you it's current width in px while currentStyle + // gives you the original "50%". + // Opera supports both, currentStyle and window.getComputedStyle, that's why checking for currentStyle should have higher prio + if (currentStyle) { + try { + return currentStyle[camelizedProperty]; + } catch(e) { + //ie will occasionally fail for unknown reasons. swallowing exception + } + } + + var win = doc.defaultView || doc.parentWindow, + needsOverflowReset = (property === "height" || property === "width") && element.nodeName === "TEXTAREA", + originalOverflow, + returnValue; + + if (win.getComputedStyle) { + // Chrome and Safari both calculate a wrong width and height for textareas when they have scroll bars + // therfore we remove and restore the scrollbar and calculate the value in between + if (needsOverflowReset) { + originalOverflow = style.overflow; + style.overflow = "hidden"; + } + returnValue = win.getComputedStyle(element, null).getPropertyValue(property); + if (needsOverflowReset) { + style.overflow = originalOverflow || ""; + } + return returnValue; + } + } + }; + }; +})();/** + * High performant way to check whether an element with a specific tag name is in the given document + * Optimized for being heavily executed + * Unleashes the power of live node lists + * + * @param {Object} doc The document object of the context where to check + * @param {String} tagName Upper cased tag name + * @example + * wysihtml5.dom.hasElementWithTagName(document, "IMG"); + */ +wysihtml5.dom.hasElementWithTagName = (function() { + var LIVE_CACHE = {}, + DOCUMENT_IDENTIFIER = 1; + + function _getDocumentIdentifier(doc) { + return doc._wysihtml5_identifier || (doc._wysihtml5_identifier = DOCUMENT_IDENTIFIER++); + } + + return function(doc, tagName) { + var key = _getDocumentIdentifier(doc) + ":" + tagName, + cacheEntry = LIVE_CACHE[key]; + if (!cacheEntry) { + cacheEntry = LIVE_CACHE[key] = doc.getElementsByTagName(tagName); + } + + return cacheEntry.length > 0; + }; +})();/** + * High performant way to check whether an element with a specific class name is in the given document + * Optimized for being heavily executed + * Unleashes the power of live node lists + * + * @param {Object} doc The document object of the context where to check + * @param {String} tagName Upper cased tag name + * @example + * wysihtml5.dom.hasElementWithClassName(document, "foobar"); + */ +(function(wysihtml5) { + var LIVE_CACHE = {}, + DOCUMENT_IDENTIFIER = 1; + + function _getDocumentIdentifier(doc) { + return doc._wysihtml5_identifier || (doc._wysihtml5_identifier = DOCUMENT_IDENTIFIER++); + } + + wysihtml5.dom.hasElementWithClassName = function(doc, className) { + // getElementsByClassName is not supported by IE<9 + // but is sometimes mocked via library code (which then doesn't return live node lists) + if (!wysihtml5.browser.supportsNativeGetElementsByClassName()) { + return !!doc.querySelector("." + className); + } + + var key = _getDocumentIdentifier(doc) + ":" + className, + cacheEntry = LIVE_CACHE[key]; + if (!cacheEntry) { + cacheEntry = LIVE_CACHE[key] = doc.getElementsByClassName(className); + } + + return cacheEntry.length > 0; + }; +})(wysihtml5); +wysihtml5.dom.insert = function(elementToInsert) { + return { + after: function(element) { + element.parentNode.insertBefore(elementToInsert, element.nextSibling); + }, + + before: function(element) { + element.parentNode.insertBefore(elementToInsert, element); + }, + + into: function(element) { + element.appendChild(elementToInsert); + } + }; +};wysihtml5.dom.insertCSS = function(rules) { + rules = rules.join("\n"); + + return { + into: function(doc) { + var head = doc.head || doc.getElementsByTagName("head")[0], + styleElement = doc.createElement("style"); + + styleElement.type = "text/css"; + + if (styleElement.styleSheet) { + styleElement.styleSheet.cssText = rules; + } else { + styleElement.appendChild(doc.createTextNode(rules)); + } + + if (head) { + head.appendChild(styleElement); + } + } + }; +};/** + * Method to set dom events + * + * @example + * wysihtml5.dom.observe(iframe.contentWindow.document.body, ["focus", "blur"], function() { ... }); + */ +wysihtml5.dom.observe = function(element, eventNames, handler) { + eventNames = typeof(eventNames) === "string" ? [eventNames] : eventNames; + + var handlerWrapper, + eventName, + i = 0, + length = eventNames.length; + + for (; i<length; i++) { + eventName = eventNames[i]; + if (element.addEventListener) { + element.addEventListener(eventName, handler, false); + } else { + handlerWrapper = function(event) { + if (!("target" in event)) { + event.target = event.srcElement; + } + event.preventDefault = event.preventDefault || function() { + this.returnValue = false; + }; + event.stopPropagation = event.stopPropagation || function() { + this.cancelBubble = true; + }; + handler.call(element, event); + }; + element.attachEvent("on" + eventName, handlerWrapper); + } + } + + return { + stop: function() { + var eventName, + i = 0, + length = eventNames.length; + for (; i<length; i++) { + eventName = eventNames[i]; + if (element.removeEventListener) { + element.removeEventListener(eventName, handler, false); + } else { + element.detachEvent("on" + eventName, handlerWrapper); + } + } + } + }; +}; +/** + * HTML Sanitizer + * Rewrites the HTML based on given rules + * + * @param {Element|String} elementOrHtml HTML String to be sanitized OR element whose content should be sanitized + * @param {Object} [rules] List of rules for rewriting the HTML, if there's no rule for an element it will + * be converted to a "span". Each rule is a key/value pair where key is the tag to convert, and value the + * desired substitution. + * @param {Object} context Document object in which to parse the html, needed to sandbox the parsing + * + * @return {Element|String} Depends on the elementOrHtml parameter. When html then the sanitized html as string elsewise the element. + * + * @example + * var userHTML = '<div id="foo" onclick="alert(1);"><p><font color="red">foo</font><script>alert(1);</script></p></div>'; + * wysihtml5.dom.parse(userHTML, { + * tags { + * p: "div", // Rename p tags to div tags + * font: "span" // Rename font tags to span tags + * div: true, // Keep them, also possible (same result when passing: "div" or true) + * script: undefined // Remove script elements + * } + * }); + * // => <div><div><span>foo bar</span></div></div> + * + * var userHTML = '<table><tbody><tr><td>I'm a table!</td></tr></tbody></table>'; + * wysihtml5.dom.parse(userHTML); + * // => '<span><span><span><span>I'm a table!</span></span></span></span>' + * + * var userHTML = '<div>foobar<br>foobar</div>'; + * wysihtml5.dom.parse(userHTML, { + * tags: { + * div: undefined, + * br: true + * } + * }); + * // => '' + * + * var userHTML = '<div class="red">foo</div><div class="pink">bar</div>'; + * wysihtml5.dom.parse(userHTML, { + * classes: { + * red: 1, + * green: 1 + * }, + * tags: { + * div: { + * rename_tag: "p" + * } + * } + * }); + * // => '<p class="red">foo</p><p>bar</p>' + */ +wysihtml5.dom.parse = (function() { + + /** + * It's not possible to use a XMLParser/DOMParser as HTML5 is not always well-formed XML + * new DOMParser().parseFromString('<img src="foo.gif">') will cause a parseError since the + * node isn't closed + * + * Therefore we've to use the browser's ordinary HTML parser invoked by setting innerHTML. + */ + var NODE_TYPE_MAPPING = { + "1": _handleElement, + "3": _handleText + }, + // Rename unknown tags to this + DEFAULT_NODE_NAME = "span", + WHITE_SPACE_REG_EXP = /\s+/, + defaultRules = { tags: {}, classes: {} }, + currentRules = {}; + + /** + * Iterates over all childs of the element, recreates them, appends them into a document fragment + * which later replaces the entire body content + */ + function parse(elementOrHtml, rules, context, cleanUp) { + wysihtml5.lang.object(currentRules).merge(defaultRules).merge(rules).get(); + + context = context || elementOrHtml.ownerDocument || document; + var fragment = context.createDocumentFragment(), + isString = typeof(elementOrHtml) === "string", + element, + newNode, + firstChild; + + if (isString) { + element = wysihtml5.dom.getAsDom(elementOrHtml, context); + } else { + element = elementOrHtml; + } + + while (element.firstChild) { + firstChild = element.firstChild; + element.removeChild(firstChild); + newNode = _convert(firstChild, cleanUp); + if (newNode) { + fragment.appendChild(newNode); + } + } + + // Clear element contents + element.innerHTML = ""; + + // Insert new DOM tree + element.appendChild(fragment); + + return isString ? wysihtml5.quirks.getCorrectInnerHTML(element) : element; + } + + function _convert(oldNode, cleanUp) { + var oldNodeType = oldNode.nodeType, + oldChilds = oldNode.childNodes, + oldChildsLength = oldChilds.length, + newNode, + method = NODE_TYPE_MAPPING[oldNodeType], + i = 0; + + newNode = method && method(oldNode); + + if (!newNode) { + return null; + } + + for (i=0; i<oldChildsLength; i++) { + newChild = _convert(oldChilds[i], cleanUp); + if (newChild) { + newNode.appendChild(newChild); + } + } + + // Cleanup senseless <span> elements + if (cleanUp && + newNode.childNodes.length <= 1 && + newNode.nodeName.toLowerCase() === DEFAULT_NODE_NAME && + !newNode.attributes.length) { + return newNode.firstChild; + } + + return newNode; + } + + function _handleElement(oldNode) { + var rule, + newNode, + endTag, + tagRules = currentRules.tags, + nodeName = oldNode.nodeName.toLowerCase(), + scopeName = oldNode.scopeName; + + /** + * We already parsed that element + * ignore it! (yes, this sometimes happens in IE8 when the html is invalid) + */ + if (oldNode._wysihtml5) { + return null; + } + oldNode._wysihtml5 = 1; + + if (oldNode.className === "wysihtml5-temp") { + return null; + } + + /** + * IE is the only browser who doesn't include the namespace in the + * nodeName, that's why we have to prepend it by ourselves + * scopeName is a proprietary IE feature + * read more here http://msdn.microsoft.com/en-us/library/ms534388(v=vs.85).aspx + */ + if (scopeName && scopeName != "HTML") { + nodeName = scopeName + ":" + nodeName; + } + + /** + * Repair node + * IE is a bit bitchy when it comes to invalid nested markup which includes unclosed tags + * A <p> doesn't need to be closed according HTML4-5 spec, we simply replace it with a <div> to preserve its content and layout + */ + if ("outerHTML" in oldNode) { + if (!wysihtml5.browser.autoClosesUnclosedTags() && + oldNode.nodeName === "P" && + oldNode.outerHTML.slice(-4).toLowerCase() !== "</p>") { + nodeName = "div"; + } + } + + if (nodeName in tagRules) { + rule = tagRules[nodeName]; + if (!rule || rule.remove) { + return null; + } + + rule = typeof(rule) === "string" ? { rename_tag: rule } : rule; + } else if (oldNode.firstChild) { + rule = { rename_tag: DEFAULT_NODE_NAME }; + } else { + // Remove empty unknown elements + return null; + } + + newNode = oldNode.ownerDocument.createElement(rule.rename_tag || nodeName); + _handleAttributes(oldNode, newNode, rule); + + oldNode = null; + return newNode; + } + + function _handleAttributes(oldNode, newNode, rule) { + var attributes = {}, // fresh new set of attributes to set on newNode + setClass = rule.set_class, // classes to set + addClass = rule.add_class, // add classes based on existing attributes + setAttributes = rule.set_attributes, // attributes to set on the current node + checkAttributes = rule.check_attributes, // check/convert values of attributes + allowedClasses = currentRules.classes, + i = 0, + classes = [], + newClasses = [], + newUniqueClasses = [], + oldClasses = [], + classesLength, + newClassesLength, + currentClass, + newClass, + attributeName, + newAttributeValue, + method; + + if (setAttributes) { + attributes = wysihtml5.lang.object(setAttributes).clone(); + } + + if (checkAttributes) { + for (attributeName in checkAttributes) { + method = attributeCheckMethods[checkAttributes[attributeName]]; + if (!method) { + continue; + } + newAttributeValue = method(_getAttribute(oldNode, attributeName)); + if (typeof(newAttributeValue) === "string") { + attributes[attributeName] = newAttributeValue; + } + } + } + + if (setClass) { + classes.push(setClass); + } + + if (addClass) { + for (attributeName in addClass) { + method = addClassMethods[addClass[attributeName]]; + if (!method) { + continue; + } + newClass = method(_getAttribute(oldNode, attributeName)); + if (typeof(newClass) === "string") { + classes.push(newClass); + } + } + } + + // make sure that wysihtml5 temp class doesn't get stripped out + allowedClasses["_wysihtml5-temp-placeholder"] = 1; + + // add old classes last + oldClasses = oldNode.getAttribute("class"); + if (oldClasses) { + classes = classes.concat(oldClasses.split(WHITE_SPACE_REG_EXP)); + } + classesLength = classes.length; + for (; i<classesLength; i++) { + currentClass = classes[i]; + if (allowedClasses[currentClass]) { + newClasses.push(currentClass); + } + } + + // remove duplicate entries and preserve class specificity + newClassesLength = newClasses.length; + while (newClassesLength--) { + currentClass = newClasses[newClassesLength]; + if (!wysihtml5.lang.array(newUniqueClasses).contains(currentClass)) { + newUniqueClasses.unshift(currentClass); + } + } + + if (newUniqueClasses.length) { + attributes["class"] = newUniqueClasses.join(" "); + } + + // set attributes on newNode + for (attributeName in attributes) { + // Setting attributes can cause a js error in IE under certain circumstances + // eg. on a <img> under https when it's new attribute value is non-https + // TODO: Investigate this further and check for smarter handling + try { + newNode.setAttribute(attributeName, attributes[attributeName]); + } catch(e) {} + } + + // IE8 sometimes loses the width/height attributes when those are set before the "src" + // so we make sure to set them again + if (attributes.src) { + if (typeof(attributes.width) !== "undefined") { + newNode.setAttribute("width", attributes.width); + } + if (typeof(attributes.height) !== "undefined") { + newNode.setAttribute("height", attributes.height); + } + } + } + + /** + * IE gives wrong results for hasAttribute/getAttribute, for example: + * var td = document.createElement("td"); + * td.getAttribute("rowspan"); // => "1" in IE + * + * Therefore we have to check the element's outerHTML for the attribute + */ + var HAS_GET_ATTRIBUTE_BUG = !wysihtml5.browser.supportsGetAttributeCorrectly(); + function _getAttribute(node, attributeName) { + attributeName = attributeName.toLowerCase(); + var nodeName = node.nodeName; + if (nodeName == "IMG" && attributeName == "src" && _isLoadedImage(node) === true) { + // Get 'src' attribute value via object property since this will always contain the + // full absolute url (http://...) + // this fixes a very annoying bug in firefox (ver 3.6 & 4) and IE 8 where images copied from the same host + // will have relative paths, which the sanitizer strips out (see attributeCheckMethods.url) + return node.src; + } else if (HAS_GET_ATTRIBUTE_BUG && "outerHTML" in node) { + // Don't trust getAttribute/hasAttribute in IE 6-8, instead check the element's outerHTML + var outerHTML = node.outerHTML.toLowerCase(), + // TODO: This might not work for attributes without value: <input disabled> + hasAttribute = outerHTML.indexOf(" " + attributeName + "=") != -1; + + return hasAttribute ? node.getAttribute(attributeName) : null; + } else{ + return node.getAttribute(attributeName); + } + } + + /** + * Check whether the given node is a proper loaded image + * FIXME: Returns undefined when unknown (Chrome, Safari) + */ + function _isLoadedImage(node) { + try { + return node.complete && !node.mozMatchesSelector(":-moz-broken"); + } catch(e) { + if (node.complete && node.readyState === "complete") { + return true; + } + } + } + + function _handleText(oldNode) { + return oldNode.ownerDocument.createTextNode(oldNode.data); + } + + + // ------------ attribute checks ------------ \\ + var attributeCheckMethods = { + url: (function() { + var REG_EXP = /^https?:\/\//i; + return function(attributeValue) { + if (!attributeValue || !attributeValue.match(REG_EXP)) { + return null; + } + return attributeValue.replace(REG_EXP, function(match) { + return match.toLowerCase(); + }); + }; + })(), + + alt: (function() { + var REG_EXP = /[^ a-z0-9_\-]/gi; + return function(attributeValue) { + if (!attributeValue) { + return ""; + } + return attributeValue.replace(REG_EXP, ""); + }; + })(), + + numbers: (function() { + var REG_EXP = /\D/g; + return function(attributeValue) { + attributeValue = (attributeValue || "").replace(REG_EXP, ""); + return attributeValue || null; + }; + })() + }; + + // ------------ class converter (converts an html attribute to a class name) ------------ \\ + var addClassMethods = { + align_img: (function() { + var mapping = { + left: "wysiwyg-float-left", + right: "wysiwyg-float-right" + }; + return function(attributeValue) { + return mapping[String(attributeValue).toLowerCase()]; + }; + })(), + + align_text: (function() { + var mapping = { + left: "wysiwyg-text-align-left", + right: "wysiwyg-text-align-right", + center: "wysiwyg-text-align-center", + justify: "wysiwyg-text-align-justify" + }; + return function(attributeValue) { + return mapping[String(attributeValue).toLowerCase()]; + }; + })(), + + clear_br: (function() { + var mapping = { + left: "wysiwyg-clear-left", + right: "wysiwyg-clear-right", + both: "wysiwyg-clear-both", + all: "wysiwyg-clear-both" + }; + return function(attributeValue) { + return mapping[String(attributeValue).toLowerCase()]; + }; + })(), + + size_font: (function() { + var mapping = { + "1": "wysiwyg-font-size-xx-small", + "2": "wysiwyg-font-size-small", + "3": "wysiwyg-font-size-medium", + "4": "wysiwyg-font-size-large", + "5": "wysiwyg-font-size-x-large", + "6": "wysiwyg-font-size-xx-large", + "7": "wysiwyg-font-size-xx-large", + "-": "wysiwyg-font-size-smaller", + "+": "wysiwyg-font-size-larger" + }; + return function(attributeValue) { + return mapping[String(attributeValue).charAt(0)]; + }; + })() + }; + + return parse; +})();/** + * Checks for empty text node childs and removes them + * + * @param {Element} node The element in which to cleanup + * @example + * wysihtml5.dom.removeEmptyTextNodes(element); + */ +wysihtml5.dom.removeEmptyTextNodes = function(node) { + var childNode, + childNodes = wysihtml5.lang.array(node.childNodes).get(), + childNodesLength = childNodes.length, + i = 0; + for (; i<childNodesLength; i++) { + childNode = childNodes[i]; + if (childNode.nodeType === wysihtml5.TEXT_NODE && childNode.data === "") { + childNode.parentNode.removeChild(childNode); + } + } +}; +/** + * Renames an element (eg. a <div> to a <p>) and keeps its childs + * + * @param {Element} element The list element which should be renamed + * @param {Element} newNodeName The desired tag name + * + * @example + * <!-- Assume the following dom: --> + * <ul id="list"> + * <li>eminem</li> + * <li>dr. dre</li> + * <li>50 Cent</li> + * </ul> + * + * <script> + * wysihtml5.dom.renameElement(document.getElementById("list"), "ol"); + * </script> + * + * <!-- Will result in: --> + * <ol> + * <li>eminem</li> + * <li>dr. dre</li> + * <li>50 Cent</li> + * </ol> + */ +wysihtml5.dom.renameElement = function(element, newNodeName) { + var newElement = element.ownerDocument.createElement(newNodeName), + firstChild; + while (firstChild = element.firstChild) { + newElement.appendChild(firstChild); + } + wysihtml5.dom.copyAttributes(["align", "className"]).from(element).to(newElement); + element.parentNode.replaceChild(newElement, element); + return newElement; +};/** + * Takes an element, removes it and replaces it with it's childs + * + * @param {Object} node The node which to replace with it's child nodes + * @example + * <div id="foo"> + * <span>hello</span> + * </div> + * <script> + * // Remove #foo and replace with it's children + * wysihtml5.dom.replaceWithChildNodes(document.getElementById("foo")); + * </script> + */ +wysihtml5.dom.replaceWithChildNodes = function(node) { + if (!node.parentNode) { + return; + } + + if (!node.firstChild) { + node.parentNode.removeChild(node); + return; + } + + var fragment = node.ownerDocument.createDocumentFragment(); + while (node.firstChild) { + fragment.appendChild(node.firstChild); + } + node.parentNode.replaceChild(fragment, node); + node = fragment = null; +}; +/** + * Unwraps an unordered/ordered list + * + * @param {Element} element The list element which should be unwrapped + * + * @example + * <!-- Assume the following dom: --> + * <ul id="list"> + * <li>eminem</li> + * <li>dr. dre</li> + * <li>50 Cent</li> + * </ul> + * + * <script> + * wysihtml5.dom.resolveList(document.getElementById("list")); + * </script> + * + * <!-- Will result in: --> + * eminem<br> + * dr. dre<br> + * 50 Cent<br> + */ +(function(dom) { + function _isBlockElement(node) { + return dom.getStyle("display").from(node) === "block"; + } + + function _isLineBreak(node) { + return node.nodeName === "BR"; + } + + function _appendLineBreak(element) { + var lineBreak = element.ownerDocument.createElement("br"); + element.appendChild(lineBreak); + } + + function resolveList(list) { + if (list.nodeName !== "MENU" && list.nodeName !== "UL" && list.nodeName !== "OL") { + return; + } + + var doc = list.ownerDocument, + fragment = doc.createDocumentFragment(), + previousSibling = list.previousElementSibling || list.previousSibling, + firstChild, + lastChild, + isLastChild, + shouldAppendLineBreak, + listItem; + + if (previousSibling && !_isBlockElement(previousSibling)) { + _appendLineBreak(fragment); + } + + while (listItem = list.firstChild) { + lastChild = listItem.lastChild; + while (firstChild = listItem.firstChild) { + isLastChild = firstChild === lastChild; + // This needs to be done before appending it to the fragment, as it otherwise will loose style information + shouldAppendLineBreak = isLastChild && !_isBlockElement(firstChild) && !_isLineBreak(firstChild); + fragment.appendChild(firstChild); + if (shouldAppendLineBreak) { + _appendLineBreak(fragment); + } + } + + listItem.parentNode.removeChild(listItem); + } + list.parentNode.replaceChild(fragment, list); + } + + dom.resolveList = resolveList; +})(wysihtml5.dom);/** + * Sandbox for executing javascript, parsing css styles and doing dom operations in a secure way + * + * Browser Compatibility: + * - Secure in MSIE 6+, but only when the user hasn't made changes to his security level "restricted" + * - Partially secure in other browsers (Firefox, Opera, Safari, Chrome, ...) + * + * Please note that this class can't benefit from the HTML5 sandbox attribute for the following reasons: + * - sandboxing doesn't work correctly with inlined content (src="javascript:'<html>...</html>'") + * - sandboxing of physical documents causes that the dom isn't accessible anymore from the outside (iframe.contentWindow, ...) + * - setting the "allow-same-origin" flag would fix that, but then still javascript and dom events refuse to fire + * - therefore the "allow-scripts" flag is needed, which then would deactivate any security, as the js executed inside the iframe + * can do anything as if the sandbox attribute wasn't set + * + * @param {Function} [readyCallback] Method that gets invoked when the sandbox is ready + * @param {Object} [config] Optional parameters + * + * @example + * new wysihtml5.dom.Sandbox(function(sandbox) { + * sandbox.getWindow().document.body.innerHTML = '<img src=foo.gif onerror="alert(document.cookie)">'; + * }); + */ +(function(wysihtml5) { + var /** + * Default configuration + */ + doc = document, + /** + * Properties to unset/protect on the window object + */ + windowProperties = [ + "parent", "top", "opener", "frameElement", "frames", + "localStorage", "globalStorage", "sessionStorage", "indexedDB" + ], + /** + * Properties on the window object which are set to an empty function + */ + windowProperties2 = [ + "open", "close", "openDialog", "showModalDialog", + "alert", "confirm", "prompt", + "openDatabase", "postMessage", + "XMLHttpRequest", "XDomainRequest" + ], + /** + * Properties to unset/protect on the document object + */ + documentProperties = [ + "referrer", + "write", "open", "close" + ]; + + wysihtml5.dom.Sandbox = Base.extend( + /** @scope wysihtml5.dom.Sandbox.prototype */ { + + constructor: function(readyCallback, config) { + this.callback = readyCallback || wysihtml5.EMPTY_FUNCTION; + this.config = wysihtml5.lang.object({}).merge(config).get(); + this.iframe = this._createIframe(); + }, + + insertInto: function(element) { + if (typeof(element) === "string") { + element = doc.getElementById(element); + } + + element.appendChild(this.iframe); + }, + + getIframe: function() { + return this.iframe; + }, + + getWindow: function() { + this._readyError(); + }, + + getDocument: function() { + this._readyError(); + }, + + destroy: function() { + var iframe = this.getIframe(); + iframe.parentNode.removeChild(iframe); + }, + + _readyError: function() { + throw new Error("wysihtml5.Sandbox: Sandbox iframe isn't loaded yet"); + }, + + /** + * Creates the sandbox iframe + * + * Some important notes: + * - We can't use HTML5 sandbox for now: + * setting it causes that the iframe's dom can't be accessed from the outside + * Therefore we need to set the "allow-same-origin" flag which enables accessing the iframe's dom + * But then there's another problem, DOM events (focus, blur, change, keypress, ...) aren't fired. + * In order to make this happen we need to set the "allow-scripts" flag. + * A combination of allow-scripts and allow-same-origin is almost the same as setting no sandbox attribute at all. + * - Chrome & Safari, doesn't seem to support sandboxing correctly when the iframe's html is inlined (no physical document) + * - IE needs to have the security="restricted" attribute set before the iframe is + * inserted into the dom tree + * - Believe it or not but in IE "security" in document.createElement("iframe") is false, even + * though it supports it + * - When an iframe has security="restricted", in IE eval() & execScript() don't work anymore + * - IE doesn't fire the onload event when the content is inlined in the src attribute, therefore we rely + * on the onreadystatechange event + */ + _createIframe: function() { + var that = this, + iframe = doc.createElement("iframe"); + iframe.className = "wysihtml5-sandbox"; + wysihtml5.dom.setAttributes({ + "security": "restricted", + "allowtransparency": "true", + "frameborder": 0, + "width": 0, + "height": 0, + "marginwidth": 0, + "marginheight": 0 + }).on(iframe); + + // Setting the src like this prevents ssl warnings in IE6 + if (wysihtml5.browser.throwsMixedContentWarningWhenIframeSrcIsEmpty()) { + iframe.src = "javascript:'<html></html>'"; + } + + iframe.onload = function() { + iframe.onreadystatechange = iframe.onload = null; + that._onLoadIframe(iframe); + }; + + iframe.onreadystatechange = function() { + if (/loaded|complete/.test(iframe.readyState)) { + iframe.onreadystatechange = iframe.onload = null; + that._onLoadIframe(iframe); + } + }; + + return iframe; + }, + + /** + * Callback for when the iframe has finished loading + */ + _onLoadIframe: function(iframe) { + // don't resume when the iframe got unloaded (eg. by removing it from the dom) + if (!wysihtml5.dom.contains(doc.documentElement, iframe)) { + return; + } + + var that = this, + iframeWindow = iframe.contentWindow, + iframeDocument = iframe.contentWindow.document, + charset = doc.characterSet || doc.charset || "utf-8", + sandboxHtml = this._getHtml({ + charset: charset, + stylesheets: this.config.stylesheets + }); + + // Create the basic dom tree including proper DOCTYPE and charset + iframeDocument.open("text/html", "replace"); + iframeDocument.write(sandboxHtml); + iframeDocument.close(); + + this.getWindow = function() { return iframe.contentWindow; }; + this.getDocument = function() { return iframe.contentWindow.document; }; + + // Catch js errors and pass them to the parent's onerror event + // addEventListener("error") doesn't work properly in some browsers + // TODO: apparently this doesn't work in IE9! + iframeWindow.onerror = function(errorMessage, fileName, lineNumber) { + throw new Error("wysihtml5.Sandbox: " + errorMessage, fileName, lineNumber); + }; + + if (!wysihtml5.browser.supportsSandboxedIframes()) { + // Unset a bunch of sensitive variables + // Please note: This isn't hack safe! + // It more or less just takes care of basic attacks and prevents accidental theft of sensitive information + // IE is secure though, which is the most important thing, since IE is the only browser, who + // takes over scripts & styles into contentEditable elements when copied from external websites + // or applications (Microsoft Word, ...) + var i, length; + for (i=0, length=windowProperties.length; i<length; i++) { + this._unset(iframeWindow, windowProperties[i]); + } + for (i=0, length=windowProperties2.length; i<length; i++) { + this._unset(iframeWindow, windowProperties2[i], wysihtml5.EMPTY_FUNCTION); + } + for (i=0, length=documentProperties.length; i<length; i++) { + this._unset(iframeDocument, documentProperties[i]); + } + // This doesn't work in Safari 5 + // See http://stackoverflow.com/questions/992461/is-it-possible-to-override-document-cookie-in-webkit + this._unset(iframeDocument, "cookie", "", true); + } + + this.loaded = true; + + // Trigger the callback + setTimeout(function() { that.callback(that); }, 0); + }, + + _getHtml: function(templateVars) { + var stylesheets = templateVars.stylesheets, + html = "", + i = 0, + length; + stylesheets = typeof(stylesheets) === "string" ? [stylesheets] : stylesheets; + if (stylesheets) { + length = stylesheets.length; + for (; i<length; i++) { + html += '<link rel="stylesheet" href="' + stylesheets[i] + '">'; + } + } + templateVars.stylesheets = html; + + return wysihtml5.lang.string( + '<!DOCTYPE html><html><head>' + + '<meta charset="#{charset}">#{stylesheets}</head>' + + '<body></body></html>' + ).interpolate(templateVars); + }, + + /** + * Method to unset/override existing variables + * @example + * // Make cookie unreadable and unwritable + * this._unset(document, "cookie", "", true); + */ + _unset: function(object, property, value, setter) { + try { object[property] = value; } catch(e) {} + + try { object.__defineGetter__(property, function() { return value; }); } catch(e) {} + if (setter) { + try { object.__defineSetter__(property, function() {}); } catch(e) {} + } + + if (!wysihtml5.browser.crashesWhenDefineProperty(property)) { + try { + var config = { + get: function() { return value; } + }; + if (setter) { + config.set = function() {}; + } + Object.defineProperty(object, property, config); + } catch(e) {} + } + } + }); +})(wysihtml5); +(function() { + var mapping = { + "className": "class" + }; + wysihtml5.dom.setAttributes = function(attributes) { + return { + on: function(element) { + for (var i in attributes) { + element.setAttribute(mapping[i] || i, attributes[i]); + } + } + } + }; +})();wysihtml5.dom.setStyles = function(styles) { + return { + on: function(element) { + var style = element.style; + if (typeof(styles) === "string") { + style.cssText += ";" + styles; + return; + } + for (var i in styles) { + if (i === "float") { + style.cssFloat = styles[i]; + style.styleFloat = styles[i]; + } else { + style[i] = styles[i]; + } + } + } + }; +};/** + * Simulate HTML5 placeholder attribute + * + * Needed since + * - div[contentEditable] elements don't support it + * - older browsers (such as IE8 and Firefox 3.6) don't support it at all + * + * @param {Object} parent Instance of main wysihtml5.Editor class + * @param {Element} view Instance of wysihtml5.views.* class + * @param {String} placeholderText + * + * @example + * wysihtml.dom.simulatePlaceholder(this, composer, "Foobar"); + */ +(function(dom) { + dom.simulatePlaceholder = function(editor, view, placeholderText) { + var CLASS_NAME = "placeholder", + unset = function() { + if (view.hasPlaceholderSet()) { + view.clear(); + } + dom.removeClass(view.element, CLASS_NAME); + }, + set = function() { + if (view.isEmpty()) { + view.setValue(placeholderText); + dom.addClass(view.element, CLASS_NAME); + } + }; + + editor + .observe("set_placeholder", set) + .observe("unset_placeholder", unset) + .observe("focus:composer", unset) + .observe("paste:composer", unset) + .observe("blur:composer", set); + + set(); + }; +})(wysihtml5.dom); +(function(dom) { + var documentElement = document.documentElement; + if ("textContent" in documentElement) { + dom.setTextContent = function(element, text) { + element.textContent = text; + }; + + dom.getTextContent = function(element) { + return element.textContent; + }; + } else if ("innerText" in documentElement) { + dom.setTextContent = function(element, text) { + element.innerText = text; + }; + + dom.getTextContent = function(element) { + return element.innerText; + }; + } else { + dom.setTextContent = function(element, text) { + element.nodeValue = text; + }; + + dom.getTextContent = function(element) { + return element.nodeValue; + }; + } +})(wysihtml5.dom); + +/** + * Fix most common html formatting misbehaviors of browsers implementation when inserting + * content via copy & paste contentEditable + * + * @author Christopher Blum + */ +wysihtml5.quirks.cleanPastedHTML = (function() { + // TODO: We probably need more rules here + var defaultRules = { + // When pasting underlined links <a> into a contentEditable, IE thinks, it has to insert <u> to keep the styling + "a u": wysihtml5.dom.replaceWithChildNodes + }; + + function cleanPastedHTML(elementOrHtml, rules, context) { + rules = rules || defaultRules; + context = context || elementOrHtml.ownerDocument || document; + + var element, + isString = typeof(elementOrHtml) === "string", + method, + matches, + matchesLength, + i, + j = 0; + if (isString) { + element = wysihtml5.dom.getAsDom(elementOrHtml, context); + } else { + element = elementOrHtml; + } + + for (i in rules) { + matches = element.querySelectorAll(i); + method = rules[i]; + matchesLength = matches.length; + for (; j<matchesLength; j++) { + method(matches[j]); + } + } + + matches = elementOrHtml = rules = null; + + return isString ? element.innerHTML : element; + } + + return cleanPastedHTML; +})();/** + * IE and Opera leave an empty paragraph in the contentEditable element after clearing it + * + * @param {Object} contentEditableElement The contentEditable element to observe for clearing events + * @exaple + * wysihtml5.quirks.ensureProperClearing(myContentEditableElement); + */ +(function(wysihtml5) { + var dom = wysihtml5.dom; + + wysihtml5.quirks.ensureProperClearing = (function() { + var clearIfNecessary = function(event) { + var element = this; + setTimeout(function() { + var innerHTML = element.innerHTML.toLowerCase(); + if (innerHTML == "<p>&nbsp;</p>" || + innerHTML == "<p>&nbsp;</p><p>&nbsp;</p>") { + element.innerHTML = ""; + } + }, 0); + }; + + return function(composer) { + dom.observe(composer.element, ["cut", "keydown"], clearIfNecessary); + }; + })(); + + + + /** + * In Opera when the caret is in the first and only item of a list (<ul><li>|</li></ul>) and the list is the first child of the contentEditable element, it's impossible to delete the list by hitting backspace + * + * @param {Object} contentEditableElement The contentEditable element to observe for clearing events + * @exaple + * wysihtml5.quirks.ensureProperClearing(myContentEditableElement); + */ + wysihtml5.quirks.ensureProperClearingOfLists = (function() { + var ELEMENTS_THAT_CONTAIN_LI = ["OL", "UL", "MENU"]; + + var clearIfNecessary = function(element, contentEditableElement) { + if (!contentEditableElement.firstChild || !wysihtml5.lang.array(ELEMENTS_THAT_CONTAIN_LI).contains(contentEditableElement.firstChild.nodeName)) { + return; + } + + var list = dom.getParentElement(element, { nodeName: ELEMENTS_THAT_CONTAIN_LI }); + if (!list) { + return; + } + + var listIsFirstChildOfContentEditable = list == contentEditableElement.firstChild; + if (!listIsFirstChildOfContentEditable) { + return; + } + + var hasOnlyOneListItem = list.childNodes.length <= 1; + if (!hasOnlyOneListItem) { + return; + } + + var onlyListItemIsEmpty = list.firstChild ? list.firstChild.innerHTML === "" : true; + if (!onlyListItemIsEmpty) { + return; + } + + list.parentNode.removeChild(list); + }; + + return function(composer) { + dom.observe(composer.element, "keydown", function(event) { + if (event.keyCode !== wysihtml5.BACKSPACE_KEY) { + return; + } + + var element = composer.selection.getSelectedNode(); + clearIfNecessary(element, composer.element); + }); + }; + })(); + +})(wysihtml5); +// See https://bugzilla.mozilla.org/show_bug.cgi?id=664398 +// +// In Firefox this: +// var d = document.createElement("div"); +// d.innerHTML ='<a href="~"></a>'; +// d.innerHTML; +// will result in: +// <a href="%7E"></a> +// which is wrong +(function(wysihtml5) { + var TILDE_ESCAPED = "%7E"; + wysihtml5.quirks.getCorrectInnerHTML = function(element) { + var innerHTML = element.innerHTML; + if (innerHTML.indexOf(TILDE_ESCAPED) === -1) { + return innerHTML; + } + + var elementsWithTilde = element.querySelectorAll("[href*='~'], [src*='~']"), + url, + urlToSearch, + length, + i; + for (i=0, length=elementsWithTilde.length; i<length; i++) { + url = elementsWithTilde[i].href || elementsWithTilde[i].src; + urlToSearch = wysihtml5.lang.string(url).replace("~").by(TILDE_ESCAPED); + innerHTML = wysihtml5.lang.string(innerHTML).replace(urlToSearch).by(url); + } + return innerHTML; + }; +})(wysihtml5);/** + * Some browsers don't insert line breaks when hitting return in a contentEditable element + * - Opera & IE insert new <p> on return + * - Chrome & Safari insert new <div> on return + * - Firefox inserts <br> on return (yippie!) + * + * @param {Element} element + * + * @example + * wysihtml5.quirks.insertLineBreakOnReturn(element); + */ +(function(wysihtml5) { + var dom = wysihtml5.dom, + USE_NATIVE_LINE_BREAK_WHEN_CARET_INSIDE_TAGS = ["LI", "P", "H1", "H2", "H3", "H4", "H5", "H6"], + LIST_TAGS = ["UL", "OL", "MENU"]; + + wysihtml5.quirks.insertLineBreakOnReturn = function(composer) { + function unwrap(selectedNode) { + var parentElement = dom.getParentElement(selectedNode, { nodeName: ["P", "DIV"] }, 2); + if (!parentElement) { + return; + } + + var invisibleSpace = document.createTextNode(wysihtml5.INVISIBLE_SPACE); + dom.insert(invisibleSpace).before(parentElement); + dom.replaceWithChildNodes(parentElement); + composer.selection.selectNode(invisibleSpace); + } + + function keyDown(event) { + var keyCode = event.keyCode; + if (event.shiftKey || (keyCode !== wysihtml5.ENTER_KEY && keyCode !== wysihtml5.BACKSPACE_KEY)) { + return; + } + + var element = event.target, + selectedNode = composer.selection.getSelectedNode(), + blockElement = dom.getParentElement(selectedNode, { nodeName: USE_NATIVE_LINE_BREAK_WHEN_CARET_INSIDE_TAGS }, 4); + if (blockElement) { + // Some browsers create <p> elements after leaving a list + // check after keydown of backspace and return whether a <p> got inserted and unwrap it + if (blockElement.nodeName === "LI" && (keyCode === wysihtml5.ENTER_KEY || keyCode === wysihtml5.BACKSPACE_KEY)) { + setTimeout(function() { + var selectedNode = composer.selection.getSelectedNode(), + list, + div; + if (!selectedNode) { + return; + } + + list = dom.getParentElement(selectedNode, { + nodeName: LIST_TAGS + }, 2); + + if (list) { + return; + } + + unwrap(selectedNode); + }, 0); + } else if (blockElement.nodeName.match(/H[1-6]/) && keyCode === wysihtml5.ENTER_KEY) { + setTimeout(function() { + unwrap(composer.selection.getSelectedNode()); + }, 0); + } + return; + } + + if (keyCode === wysihtml5.ENTER_KEY && !wysihtml5.browser.insertsLineBreaksOnReturn()) { + composer.commands.exec("insertLineBreak"); + event.preventDefault(); + } + } + + // keypress doesn't fire when you hit backspace + dom.observe(composer.element.ownerDocument, "keydown", keyDown); + }; +})(wysihtml5);/** + * Force rerendering of a given element + * Needed to fix display misbehaviors of IE + * + * @param {Element} element The element object which needs to be rerendered + * @example + * wysihtml5.quirks.redraw(document.body); + */ +(function(wysihtml5) { + var CLASS_NAME = "wysihtml5-quirks-redraw"; + + wysihtml5.quirks.redraw = function(element) { + wysihtml5.dom.addClass(element, CLASS_NAME); + wysihtml5.dom.removeClass(element, CLASS_NAME); + + // Following hack is needed for firefox to make sure that image resize handles are properly removed + try { + var doc = element.ownerDocument; + doc.execCommand("italic", false, null); + doc.execCommand("italic", false, null); + } catch(e) {} + }; +})(wysihtml5);/** + * Selection API + * + * @example + * var selection = new wysihtml5.Selection(editor); + */ +(function(wysihtml5) { + var dom = wysihtml5.dom; + + function _getCumulativeOffsetTop(element) { + var top = 0; + if (element.parentNode) { + do { + top += element.offsetTop || 0; + element = element.offsetParent; + } while (element); + } + return top; + } + + wysihtml5.Selection = Base.extend( + /** @scope wysihtml5.Selection.prototype */ { + constructor: function(editor) { + // Make sure that our external range library is initialized + window.rangy.init(); + + this.editor = editor; + this.composer = editor.composer; + this.doc = this.composer.doc; + }, + + /** + * Get the current selection as a bookmark to be able to later restore it + * + * @return {Object} An object that represents the current selection + */ + getBookmark: function() { + var range = this.getRange(); + return range && range.cloneRange(); + }, + + /** + * Restore a selection retrieved via wysihtml5.Selection.prototype.getBookmark + * + * @param {Object} bookmark An object that represents the current selection + */ + setBookmark: function(bookmark) { + if (!bookmark) { + return; + } + + this.setSelection(bookmark); + }, + + /** + * Set the caret in front of the given node + * + * @param {Object} node The element or text node where to position the caret in front of + * @example + * selection.setBefore(myElement); + */ + setBefore: function(node) { + var range = rangy.createRange(this.doc); + range.setStartBefore(node); + range.setEndBefore(node); + return this.setSelection(range); + }, + + /** + * Set the caret after the given node + * + * @param {Object} node The element or text node where to position the caret in front of + * @example + * selection.setBefore(myElement); + */ + setAfter: function(node) { + var range = rangy.createRange(this.doc); + range.setStartAfter(node); + range.setEndAfter(node); + return this.setSelection(range); + }, + + /** + * Ability to select/mark nodes + * + * @param {Element} node The node/element to select + * @example + * selection.selectNode(document.getElementById("my-image")); + */ + selectNode: function(node) { + var range = rangy.createRange(this.doc), + isElement = node.nodeType === wysihtml5.ELEMENT_NODE, + canHaveHTML = "canHaveHTML" in node ? node.canHaveHTML : (node.nodeName !== "IMG"), + content = isElement ? node.innerHTML : node.data, + isEmpty = (content === "" || content === wysihtml5.INVISIBLE_SPACE), + displayStyle = dom.getStyle("display").from(node), + isBlockElement = (displayStyle === "block" || displayStyle === "list-item"); + + if (isEmpty && isElement && canHaveHTML) { + // Make sure that caret is visible in node by inserting a zero width no breaking space + try { node.innerHTML = wysihtml5.INVISIBLE_SPACE; } catch(e) {} + } + + if (canHaveHTML) { + range.selectNodeContents(node); + } else { + range.selectNode(node); + } + + if (canHaveHTML && isEmpty && isElement) { + range.collapse(isBlockElement); + } else if (canHaveHTML && isEmpty) { + range.setStartAfter(node); + range.setEndAfter(node); + } + + this.setSelection(range); + }, + + /** + * Get the node which contains the selection + * + * @param {Boolean} [controlRange] (only IE) Whether it should return the selected ControlRange element when the selection type is a "ControlRange" + * @return {Object} The node that contains the caret + * @example + * var nodeThatContainsCaret = selection.getSelectedNode(); + */ + getSelectedNode: function(controlRange) { + var selection, + range; + + if (controlRange && this.doc.selection && this.doc.selection.type === "Control") { + range = this.doc.selection.createRange(); + if (range && range.length) { + return range.item(0); + } + } + + selection = this.getSelection(this.doc); + if (selection.focusNode === selection.anchorNode) { + return selection.focusNode; + } else { + range = this.getRange(this.doc); + return range ? range.commonAncestorContainer : this.doc.body; + } + }, + + executeAndRestore: function(method, restoreScrollPosition) { + var body = this.doc.body, + oldScrollTop = restoreScrollPosition && body.scrollTop, + oldScrollLeft = restoreScrollPosition && body.scrollLeft, + className = "_wysihtml5-temp-placeholder", + placeholderHTML = '<span class="' + className + '">' + wysihtml5.INVISIBLE_SPACE + '</span>', + range = this.getRange(this.doc), + newRange; + + // Nothing selected, execute and say goodbye + if (!range) { + method(body, body); + return; + } + + var node = range.createContextualFragment(placeholderHTML); + range.insertNode(node); + + // Make sure that a potential error doesn't cause our placeholder element to be left as a placeholder + try { + method(range.startContainer, range.endContainer); + } catch(e3) { + setTimeout(function() { throw e3; }, 0); + } + + caretPlaceholder = this.doc.querySelector("." + className); + if (caretPlaceholder) { + newRange = rangy.createRange(this.doc); + newRange.selectNode(caretPlaceholder); + newRange.deleteContents(); + this.setSelection(newRange); + } else { + // fallback for when all hell breaks loose + body.focus(); + } + + if (restoreScrollPosition) { + body.scrollTop = oldScrollTop; + body.scrollLeft = oldScrollLeft; + } + + // Remove it again, just to make sure that the placeholder is definitely out of the dom tree + try { + caretPlaceholder.parentNode.removeChild(caretPlaceholder); + } catch(e4) {} + }, + + /** + * Different approach of preserving the selection (doesn't modify the dom) + * Takes all text nodes in the selection and saves the selection position in the first and last one + */ + executeAndRestoreSimple: function(method) { + var range = this.getRange(), + body = this.doc.body, + newRange, + firstNode, + lastNode, + textNodes, + rangeBackup; + + // Nothing selected, execute and say goodbye + if (!range) { + method(body, body); + return; + } + + textNodes = range.getNodes([3]); + firstNode = textNodes[0] || range.startContainer; + lastNode = textNodes[textNodes.length - 1] || range.endContainer; + + rangeBackup = { + collapsed: range.collapsed, + startContainer: firstNode, + startOffset: firstNode === range.startContainer ? range.startOffset : 0, + endContainer: lastNode, + endOffset: lastNode === range.endContainer ? range.endOffset : lastNode.length + }; + + try { + method(range.startContainer, range.endContainer); + } catch(e) { + setTimeout(function() { throw e; }, 0); + } + + newRange = rangy.createRange(this.doc); + try { newRange.setStart(rangeBackup.startContainer, rangeBackup.startOffset); } catch(e1) {} + try { newRange.setEnd(rangeBackup.endContainer, rangeBackup.endOffset); } catch(e2) {} + try { this.setSelection(newRange); } catch(e3) {} + }, + + /** + * Insert html at the caret position and move the cursor after the inserted html + * + * @param {String} html HTML string to insert + * @example + * selection.insertHTML("<p>foobar</p>"); + */ + insertHTML: function(html) { + var range = rangy.createRange(this.doc), + node = range.createContextualFragment(html), + lastChild = node.lastChild; + this.insertNode(node); + if (lastChild) { + this.setAfter(lastChild); + } + }, + + /** + * Insert a node at the caret position and move the cursor behind it + * + * @param {Object} node HTML string to insert + * @example + * selection.insertNode(document.createTextNode("foobar")); + */ + insertNode: function(node) { + var range = this.getRange(); + if (range) { + range.insertNode(node); + } + }, + + /** + * Wraps current selection with the given node + * + * @param {Object} node The node to surround the selected elements with + */ + surround: function(node) { + var range = this.getRange(); + if (!range) { + return; + } + + try { + // This only works when the range boundaries are not overlapping other elements + range.surroundContents(node); + this.selectNode(node); + } catch(e) { + // fallback + node.appendChild(range.extractContents()); + range.insertNode(node); + } + }, + + /** + * Scroll the current caret position into the view + * FIXME: This is a bit hacky, there might be a smarter way of doing this + * + * @example + * selection.scrollIntoView(); + */ + scrollIntoView: function() { + var doc = this.doc, + hasScrollBars = doc.documentElement.scrollHeight > doc.documentElement.offsetHeight, + tempElement = doc._wysihtml5ScrollIntoViewElement = doc._wysihtml5ScrollIntoViewElement || (function() { + var element = doc.createElement("span"); + // The element needs content in order to be able to calculate it's position properly + element.innerHTML = wysihtml5.INVISIBLE_SPACE; + return element; + })(), + offsetTop; + + if (hasScrollBars) { + this.insertNode(tempElement); + offsetTop = _getCumulativeOffsetTop(tempElement); + tempElement.parentNode.removeChild(tempElement); + if (offsetTop > doc.body.scrollTop) { + doc.body.scrollTop = offsetTop; + } + } + }, + + /** + * Select line where the caret is in + */ + selectLine: function() { + if (wysihtml5.browser.supportsSelectionModify()) { + this._selectLine_W3C(); + } else if (this.doc.selection) { + this._selectLine_MSIE(); + } + }, + + /** + * See https://developer.mozilla.org/en/DOM/Selection/modify + */ + _selectLine_W3C: function() { + var win = this.doc.defaultView, + selection = win.getSelection(); + selection.modify("extend", "left", "lineboundary"); + selection.modify("extend", "right", "lineboundary"); + }, + + _selectLine_MSIE: function() { + var range = this.doc.selection.createRange(), + rangeTop = range.boundingTop, + rangeHeight = range.boundingHeight, + scrollWidth = this.doc.body.scrollWidth, + rangeBottom, + rangeEnd, + measureNode, + i, + j; + + if (!range.moveToPoint) { + return; + } + + if (rangeTop === 0) { + // Don't know why, but when the selection ends at the end of a line + // range.boundingTop is 0 + measureNode = this.doc.createElement("span"); + this.insertNode(measureNode); + rangeTop = measureNode.offsetTop; + measureNode.parentNode.removeChild(measureNode); + } + + rangeTop += 1; + + for (i=-10; i<scrollWidth; i+=2) { + try { + range.moveToPoint(i, rangeTop); + break; + } catch(e1) {} + } + + // Investigate the following in order to handle multi line selections + // rangeBottom = rangeTop + (rangeHeight ? (rangeHeight - 1) : 0); + rangeBottom = rangeTop; + rangeEnd = this.doc.selection.createRange(); + for (j=scrollWidth; j>=0; j--) { + try { + rangeEnd.moveToPoint(j, rangeBottom); + break; + } catch(e2) {} + } + + range.setEndPoint("EndToEnd", rangeEnd); + range.select(); + }, + + getText: function() { + var selection = this.getSelection(); + return selection ? selection.toString() : ""; + }, + + getNodes: function(nodeType, filter) { + var range = this.getRange(); + if (range) { + return range.getNodes([nodeType], filter); + } else { + return []; + } + }, + + getRange: function() { + var selection = this.getSelection(); + return selection && selection.rangeCount && selection.getRangeAt(0); + }, + + getSelection: function() { + return rangy.getSelection(this.doc.defaultView || this.doc.parentWindow); + }, + + setSelection: function(range) { + var win = this.doc.defaultView || this.doc.parentWindow, + selection = rangy.getSelection(win); + return selection.setSingleRange(range); + } + }); + +})(wysihtml5); +/** + * Inspired by the rangy CSS Applier module written by Tim Down and licensed under the MIT license. + * http://code.google.com/p/rangy/ + * + * changed in order to be able ... + * - to use custom tags + * - to detect and replace similar css classes via reg exp + */ +(function(wysihtml5, rangy) { + var defaultTagName = "span"; + + var REG_EXP_WHITE_SPACE = /\s+/g; + + function hasClass(el, cssClass, regExp) { + if (!el.className) { + return false; + } + + var matchingClassNames = el.className.match(regExp) || []; + return matchingClassNames[matchingClassNames.length - 1] === cssClass; + } + + function addClass(el, cssClass, regExp) { + if (el.className) { + removeClass(el, regExp); + el.className += " " + cssClass; + } else { + el.className = cssClass; + } + } + + function removeClass(el, regExp) { + if (el.className) { + el.className = el.className.replace(regExp, ""); + } + } + + function hasSameClasses(el1, el2) { + return el1.className.replace(REG_EXP_WHITE_SPACE, " ") == el2.className.replace(REG_EXP_WHITE_SPACE, " "); + } + + function replaceWithOwnChildren(el) { + var parent = el.parentNode; + while (el.firstChild) { + parent.insertBefore(el.firstChild, el); + } + parent.removeChild(el); + } + + function elementsHaveSameNonClassAttributes(el1, el2) { + if (el1.attributes.length != el2.attributes.length) { + return false; + } + for (var i = 0, len = el1.attributes.length, attr1, attr2, name; i < len; ++i) { + attr1 = el1.attributes[i]; + name = attr1.name; + if (name != "class") { + attr2 = el2.attributes.getNamedItem(name); + if (attr1.specified != attr2.specified) { + return false; + } + if (attr1.specified && attr1.nodeValue !== attr2.nodeValue) { + return false; + } + } + } + return true; + } + + function isSplitPoint(node, offset) { + if (rangy.dom.isCharacterDataNode(node)) { + if (offset == 0) { + return !!node.previousSibling; + } else if (offset == node.length) { + return !!node.nextSibling; + } else { + return true; + } + } + + return offset > 0 && offset < node.childNodes.length; + } + + function splitNodeAt(node, descendantNode, descendantOffset) { + var newNode; + if (rangy.dom.isCharacterDataNode(descendantNode)) { + if (descendantOffset == 0) { + descendantOffset = rangy.dom.getNodeIndex(descendantNode); + descendantNode = descendantNode.parentNode; + } else if (descendantOffset == descendantNode.length) { + descendantOffset = rangy.dom.getNodeIndex(descendantNode) + 1; + descendantNode = descendantNode.parentNode; + } else { + newNode = rangy.dom.splitDataNode(descendantNode, descendantOffset); + } + } + if (!newNode) { + newNode = descendantNode.cloneNode(false); + if (newNode.id) { + newNode.removeAttribute("id"); + } + var child; + while ((child = descendantNode.childNodes[descendantOffset])) { + newNode.appendChild(child); + } + rangy.dom.insertAfter(newNode, descendantNode); + } + return (descendantNode == node) ? newNode : splitNodeAt(node, newNode.parentNode, rangy.dom.getNodeIndex(newNode)); + } + + function Merge(firstNode) { + this.isElementMerge = (firstNode.nodeType == wysihtml5.ELEMENT_NODE); + this.firstTextNode = this.isElementMerge ? firstNode.lastChild : firstNode; + this.textNodes = [this.firstTextNode]; + } + + Merge.prototype = { + doMerge: function() { + var textBits = [], textNode, parent, text; + for (var i = 0, len = this.textNodes.length; i < len; ++i) { + textNode = this.textNodes[i]; + parent = textNode.parentNode; + textBits[i] = textNode.data; + if (i) { + parent.removeChild(textNode); + if (!parent.hasChildNodes()) { + parent.parentNode.removeChild(parent); + } + } + } + this.firstTextNode.data = text = textBits.join(""); + return text; + }, + + getLength: function() { + var i = this.textNodes.length, len = 0; + while (i--) { + len += this.textNodes[i].length; + } + return len; + }, + + toString: function() { + var textBits = []; + for (var i = 0, len = this.textNodes.length; i < len; ++i) { + textBits[i] = "'" + this.textNodes[i].data + "'"; + } + return "[Merge(" + textBits.join(",") + ")]"; + } + }; + + function HTMLApplier(tagNames, cssClass, similarClassRegExp, normalize) { + this.tagNames = tagNames || [defaultTagName]; + this.cssClass = cssClass || ""; + this.similarClassRegExp = similarClassRegExp; + this.normalize = normalize; + this.applyToAnyTagName = false; + } + + HTMLApplier.prototype = { + getAncestorWithClass: function(node) { + var cssClassMatch; + while (node) { + cssClassMatch = this.cssClass ? hasClass(node, this.cssClass, this.similarClassRegExp) : true; + if (node.nodeType == wysihtml5.ELEMENT_NODE && rangy.dom.arrayContains(this.tagNames, node.tagName.toLowerCase()) && cssClassMatch) { + return node; + } + node = node.parentNode; + } + return false; + }, + + // Normalizes nodes after applying a CSS class to a Range. + postApply: function(textNodes, range) { + var firstNode = textNodes[0], lastNode = textNodes[textNodes.length - 1]; + + var merges = [], currentMerge; + + var rangeStartNode = firstNode, rangeEndNode = lastNode; + var rangeStartOffset = 0, rangeEndOffset = lastNode.length; + + var textNode, precedingTextNode; + + for (var i = 0, len = textNodes.length; i < len; ++i) { + textNode = textNodes[i]; + precedingTextNode = this.getAdjacentMergeableTextNode(textNode.parentNode, false); + if (precedingTextNode) { + if (!currentMerge) { + currentMerge = new Merge(precedingTextNode); + merges.push(currentMerge); + } + currentMerge.textNodes.push(textNode); + if (textNode === firstNode) { + rangeStartNode = currentMerge.firstTextNode; + rangeStartOffset = rangeStartNode.length; + } + if (textNode === lastNode) { + rangeEndNode = currentMerge.firstTextNode; + rangeEndOffset = currentMerge.getLength(); + } + } else { + currentMerge = null; + } + } + + // Test whether the first node after the range needs merging + var nextTextNode = this.getAdjacentMergeableTextNode(lastNode.parentNode, true); + if (nextTextNode) { + if (!currentMerge) { + currentMerge = new Merge(lastNode); + merges.push(currentMerge); + } + currentMerge.textNodes.push(nextTextNode); + } + + // Do the merges + if (merges.length) { + for (i = 0, len = merges.length; i < len; ++i) { + merges[i].doMerge(); + } + // Set the range boundaries + range.setStart(rangeStartNode, rangeStartOffset); + range.setEnd(rangeEndNode, rangeEndOffset); + } + }, + + getAdjacentMergeableTextNode: function(node, forward) { + var isTextNode = (node.nodeType == wysihtml5.TEXT_NODE); + var el = isTextNode ? node.parentNode : node; + var adjacentNode; + var propName = forward ? "nextSibling" : "previousSibling"; + if (isTextNode) { + // Can merge if the node's previous/next sibling is a text node + adjacentNode = node[propName]; + if (adjacentNode && adjacentNode.nodeType == wysihtml5.TEXT_NODE) { + return adjacentNode; + } + } else { + // Compare element with its sibling + adjacentNode = el[propName]; + if (adjacentNode && this.areElementsMergeable(node, adjacentNode)) { + return adjacentNode[forward ? "firstChild" : "lastChild"]; + } + } + return null; + }, + + areElementsMergeable: function(el1, el2) { + return rangy.dom.arrayContains(this.tagNames, (el1.tagName || "").toLowerCase()) + && rangy.dom.arrayContains(this.tagNames, (el2.tagName || "").toLowerCase()) + && hasSameClasses(el1, el2) + && elementsHaveSameNonClassAttributes(el1, el2); + }, + + createContainer: function(doc) { + var el = doc.createElement(this.tagNames[0]); + if (this.cssClass) { + el.className = this.cssClass; + } + return el; + }, + + applyToTextNode: function(textNode) { + var parent = textNode.parentNode; + if (parent.childNodes.length == 1 && rangy.dom.arrayContains(this.tagNames, parent.tagName.toLowerCase())) { + if (this.cssClass) { + addClass(parent, this.cssClass, this.similarClassRegExp); + } + } else { + var el = this.createContainer(rangy.dom.getDocument(textNode)); + textNode.parentNode.insertBefore(el, textNode); + el.appendChild(textNode); + } + }, + + isRemovable: function(el) { + return rangy.dom.arrayContains(this.tagNames, el.tagName.toLowerCase()) && wysihtml5.lang.string(el.className).trim() == this.cssClass; + }, + + undoToTextNode: function(textNode, range, ancestorWithClass) { + if (!range.containsNode(ancestorWithClass)) { + // Split out the portion of the ancestor from which we can remove the CSS class + var ancestorRange = range.cloneRange(); + ancestorRange.selectNode(ancestorWithClass); + + if (ancestorRange.isPointInRange(range.endContainer, range.endOffset) && isSplitPoint(range.endContainer, range.endOffset)) { + splitNodeAt(ancestorWithClass, range.endContainer, range.endOffset); + range.setEndAfter(ancestorWithClass); + } + if (ancestorRange.isPointInRange(range.startContainer, range.startOffset) && isSplitPoint(range.startContainer, range.startOffset)) { + ancestorWithClass = splitNodeAt(ancestorWithClass, range.startContainer, range.startOffset); + } + } + + if (this.similarClassRegExp) { + removeClass(ancestorWithClass, this.similarClassRegExp); + } + if (this.isRemovable(ancestorWithClass)) { + replaceWithOwnChildren(ancestorWithClass); + } + }, + + applyToRange: function(range) { + var textNodes = range.getNodes([wysihtml5.TEXT_NODE]); + if (!textNodes.length) { + try { + var node = this.createContainer(range.endContainer.ownerDocument); + range.surroundContents(node); + this.selectNode(range, node); + return; + } catch(e) {} + } + + range.splitBoundaries(); + textNodes = range.getNodes([wysihtml5.TEXT_NODE]); + + if (textNodes.length) { + var textNode; + + for (var i = 0, len = textNodes.length; i < len; ++i) { + textNode = textNodes[i]; + if (!this.getAncestorWithClass(textNode)) { + this.applyToTextNode(textNode); + } + } + + range.setStart(textNodes[0], 0); + textNode = textNodes[textNodes.length - 1]; + range.setEnd(textNode, textNode.length); + + if (this.normalize) { + this.postApply(textNodes, range); + } + } + }, + + undoToRange: function(range) { + var textNodes = range.getNodes([wysihtml5.TEXT_NODE]), textNode, ancestorWithClass; + if (textNodes.length) { + range.splitBoundaries(); + textNodes = range.getNodes([wysihtml5.TEXT_NODE]); + } else { + var doc = range.endContainer.ownerDocument, + node = doc.createTextNode(wysihtml5.INVISIBLE_SPACE); + range.insertNode(node); + range.selectNode(node); + textNodes = [node]; + } + + for (var i = 0, len = textNodes.length; i < len; ++i) { + textNode = textNodes[i]; + ancestorWithClass = this.getAncestorWithClass(textNode); + if (ancestorWithClass) { + this.undoToTextNode(textNode, range, ancestorWithClass); + } + } + + if (len == 1) { + this.selectNode(range, textNodes[0]); + } else { + range.setStart(textNodes[0], 0); + textNode = textNodes[textNodes.length - 1]; + range.setEnd(textNode, textNode.length); + + if (this.normalize) { + this.postApply(textNodes, range); + } + } + }, + + selectNode: function(range, node) { + var isElement = node.nodeType === wysihtml5.ELEMENT_NODE, + canHaveHTML = "canHaveHTML" in node ? node.canHaveHTML : true, + content = isElement ? node.innerHTML : node.data, + isEmpty = (content === "" || content === wysihtml5.INVISIBLE_SPACE); + + if (isEmpty && isElement && canHaveHTML) { + // Make sure that caret is visible in node by inserting a zero width no breaking space + try { node.innerHTML = wysihtml5.INVISIBLE_SPACE; } catch(e) {} + } + range.selectNodeContents(node); + if (isEmpty && isElement) { + range.collapse(false); + } else if (isEmpty) { + range.setStartAfter(node); + range.setEndAfter(node); + } + }, + + getTextSelectedByRange: function(textNode, range) { + var textRange = range.cloneRange(); + textRange.selectNodeContents(textNode); + + var intersectionRange = textRange.intersection(range); + var text = intersectionRange ? intersectionRange.toString() : ""; + textRange.detach(); + + return text; + }, + + isAppliedToRange: function(range) { + var ancestors = [], + ancestor, + textNodes = range.getNodes([wysihtml5.TEXT_NODE]); + if (!textNodes.length) { + ancestor = this.getAncestorWithClass(range.startContainer); + return ancestor ? [ancestor] : false; + } + + for (var i = 0, len = textNodes.length, selectedText; i < len; ++i) { + selectedText = this.getTextSelectedByRange(textNodes[i], range); + ancestor = this.getAncestorWithClass(textNodes[i]); + if (selectedText != "" && !ancestor) { + return false; + } else { + ancestors.push(ancestor); + } + } + return ancestors; + }, + + toggleRange: function(range) { + if (this.isAppliedToRange(range)) { + this.undoToRange(range); + } else { + this.applyToRange(range); + } + } + }; + + wysihtml5.selection.HTMLApplier = HTMLApplier; + +})(wysihtml5, rangy);/** + * Rich Text Query/Formatting Commands + * + * @example + * var commands = new wysihtml5.Commands(editor); + */ +wysihtml5.Commands = Base.extend( + /** @scope wysihtml5.Commands.prototype */ { + constructor: function(editor) { + this.editor = editor; + this.composer = editor.composer; + this.doc = this.composer.doc; + }, + + /** + * Check whether the browser supports the given command + * + * @param {String} command The command string which to check (eg. "bold", "italic", "insertUnorderedList") + * @example + * commands.supports("createLink"); + */ + support: function(command) { + return wysihtml5.browser.supportsCommand(this.doc, command); + }, + + /** + * Check whether the browser supports the given command + * + * @param {String} command The command string which to execute (eg. "bold", "italic", "insertUnorderedList") + * @param {String} [value] The command value parameter, needed for some commands ("createLink", "insertImage", ...), optional for commands that don't require one ("bold", "underline", ...) + * @example + * commands.exec("insertImage", "http://a1.twimg.com/profile_images/113868655/schrei_twitter_reasonably_small.jpg"); + */ + exec: function(command, value) { + var obj = wysihtml5.commands[command], + args = wysihtml5.lang.array(arguments).get(), + method = obj && obj.exec, + result = null; + + this.editor.fire("beforecommand:composer"); + + if (method) { + args.unshift(this.composer); + result = method.apply(obj, args); + } else { + try { + // try/catch for buggy firefox + result = this.doc.execCommand(command, false, value); + } catch(e) {} + } + + this.editor.fire("aftercommand:composer"); + return result; + }, + + /** + * Check whether the current command is active + * If the caret is within a bold text, then calling this with command "bold" should return true + * + * @param {String} command The command string which to check (eg. "bold", "italic", "insertUnorderedList") + * @param {String} [commandValue] The command value parameter (eg. for "insertImage" the image src) + * @return {Boolean} Whether the command is active + * @example + * var isCurrentSelectionBold = commands.state("bold"); + */ + state: function(command, commandValue) { + var obj = wysihtml5.commands[command], + args = wysihtml5.lang.array(arguments).get(), + method = obj && obj.state; + if (method) { + args.unshift(this.composer); + return method.apply(obj, args); + } else { + try { + // try/catch for buggy firefox + return this.doc.queryCommandState(command); + } catch(e) { + return false; + } + } + }, + + /** + * Get the current command's value + * + * @param {String} command The command string which to check (eg. "formatBlock") + * @return {String} The command value + * @example + * var currentBlockElement = commands.value("formatBlock"); + */ + value: function(command) { + var obj = wysihtml5.commands[command], + method = obj && obj.value; + if (method) { + return method.call(obj, this.composer, command); + } else { + try { + // try/catch for buggy firefox + return this.doc.queryCommandValue(command); + } catch(e) { + return null; + } + } + } +}); +(function(wysihtml5) { + var undef; + + wysihtml5.commands.bold = { + exec: function(composer, command) { + return wysihtml5.commands.formatInline.exec(composer, command, "b"); + }, + + state: function(composer, command, color) { + // element.ownerDocument.queryCommandState("bold") results: + // firefox: only <b> + // chrome: <b>, <strong>, <h1>, <h2>, ... + // ie: <b>, <strong> + // opera: <b>, <strong> + return wysihtml5.commands.formatInline.state(composer, command, "b"); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5); + +(function(wysihtml5) { + var undef, + NODE_NAME = "A", + dom = wysihtml5.dom; + + function _removeFormat(composer, anchors) { + var length = anchors.length, + i = 0, + anchor, + codeElement, + textContent; + for (; i<length; i++) { + anchor = anchors[i]; + codeElement = dom.getParentElement(anchor, { nodeName: "code" }); + textContent = dom.getTextContent(anchor); + + // if <a> contains url-like text content, rename it to <code> to prevent re-autolinking + // else replace <a> with its childNodes + if (textContent.match(dom.autoLink.URL_REG_EXP) && !codeElement) { + // <code> element is used to prevent later auto-linking of the content + codeElement = dom.renameElement(anchor, "code"); + } else { + dom.replaceWithChildNodes(anchor); + } + } + } + + function _format(composer, attributes) { + var doc = composer.doc, + tempClass = "_wysihtml5-temp-" + (+new Date()), + tempClassRegExp = /non-matching-class/g, + i = 0, + length, + anchors, + anchor, + hasElementChild, + isEmpty, + elementToSetCaretAfter, + textContent, + whiteSpace, + j; + wysihtml5.commands.formatInline.exec(composer, undef, NODE_NAME, tempClass, tempClassRegExp); + anchors = doc.querySelectorAll(NODE_NAME + "." + tempClass); + length = anchors.length; + for (; i<length; i++) { + anchor = anchors[i]; + anchor.removeAttribute("class"); + for (j in attributes) { + anchor.setAttribute(j, attributes[j]); + } + } + + elementToSetCaretAfter = anchor; + if (length === 1) { + textContent = dom.getTextContent(anchor); + hasElementChild = !!anchor.querySelector("*"); + isEmpty = textContent === "" || textContent === wysihtml5.INVISIBLE_SPACE; + if (!hasElementChild && isEmpty) { + dom.setTextContent(anchor, attributes.text || anchor.href); + whiteSpace = doc.createTextNode(" "); + composer.selection.setAfter(anchor); + composer.selection.insertNode(whiteSpace); + elementToSetCaretAfter = whiteSpace; + } + } + composer.selection.setAfter(elementToSetCaretAfter); + } + + wysihtml5.commands.createLink = { + /** + * TODO: Use HTMLApplier or formatInline here + * + * Turns selection into a link + * If selection is already a link, it removes the link and wraps it with a <code> element + * The <code> element is needed to avoid auto linking + * + * @example + * // either ... + * wysihtml5.commands.createLink.exec(composer, "createLink", "http://www.google.de"); + * // ... or ... + * wysihtml5.commands.createLink.exec(composer, "createLink", { href: "http://www.google.de", target: "_blank" }); + */ + exec: function(composer, command, value) { + var anchors = this.state(composer, command); + if (anchors) { + // Selection contains links + composer.selection.executeAndRestore(function() { + _removeFormat(composer, anchors); + }); + } else { + // Create links + value = typeof(value) === "object" ? value : { href: value }; + _format(composer, value); + } + }, + + state: function(composer, command) { + return wysihtml5.commands.formatInline.state(composer, command, "A"); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);/** + * document.execCommand("fontSize") will create either inline styles (firefox, chrome) or use font tags + * which we don't want + * Instead we set a css class + */ +(function(wysihtml5) { + var undef, + REG_EXP = /wysiwyg-font-size-[a-z\-]+/g; + + wysihtml5.commands.fontSize = { + exec: function(composer, command, size) { + return wysihtml5.commands.formatInline.exec(composer, command, "span", "wysiwyg-font-size-" + size, REG_EXP); + }, + + state: function(composer, command, size) { + return wysihtml5.commands.formatInline.state(composer, command, "span", "wysiwyg-font-size-" + size, REG_EXP); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5); +/** + * document.execCommand("foreColor") will create either inline styles (firefox, chrome) or use font tags + * which we don't want + * Instead we set a css class + */ +(function(wysihtml5) { + var undef, + REG_EXP = /wysiwyg-color-[a-z]+/g; + + wysihtml5.commands.foreColor = { + exec: function(composer, command, color) { + return wysihtml5.commands.formatInline.exec(composer, command, "span", "wysiwyg-color-" + color, REG_EXP); + }, + + state: function(composer, command, color) { + return wysihtml5.commands.formatInline.state(composer, command, "span", "wysiwyg-color-" + color, REG_EXP); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);(function(wysihtml5) { + var undef, + dom = wysihtml5.dom, + DEFAULT_NODE_NAME = "DIV", + // Following elements are grouped + // when the caret is within a H1 and the H4 is invoked, the H1 should turn into H4 + // instead of creating a H4 within a H1 which would result in semantically invalid html + BLOCK_ELEMENTS_GROUP = ["H1", "H2", "H3", "H4", "H5", "H6", "P", "BLOCKQUOTE", DEFAULT_NODE_NAME]; + + /** + * Remove similiar classes (based on classRegExp) + * and add the desired class name + */ + function _addClass(element, className, classRegExp) { + if (element.className) { + _removeClass(element, classRegExp); + element.className += " " + className; + } else { + element.className = className; + } + } + + function _removeClass(element, classRegExp) { + element.className = element.className.replace(classRegExp, ""); + } + + /** + * Check whether given node is a text node and whether it's empty + */ + function _isBlankTextNode(node) { + return node.nodeType === wysihtml5.TEXT_NODE && !wysihtml5.lang.string(node.data).trim(); + } + + /** + * Returns previous sibling node that is not a blank text node + */ + function _getPreviousSiblingThatIsNotBlank(node) { + var previousSibling = node.previousSibling; + while (previousSibling && _isBlankTextNode(previousSibling)) { + previousSibling = previousSibling.previousSibling; + } + return previousSibling; + } + + /** + * Returns next sibling node that is not a blank text node + */ + function _getNextSiblingThatIsNotBlank(node) { + var nextSibling = node.nextSibling; + while (nextSibling && _isBlankTextNode(nextSibling)) { + nextSibling = nextSibling.nextSibling; + } + return nextSibling; + } + + /** + * Adds line breaks before and after the given node if the previous and next siblings + * aren't already causing a visual line break (block element or <br>) + */ + function _addLineBreakBeforeAndAfter(node) { + var doc = node.ownerDocument, + nextSibling = _getNextSiblingThatIsNotBlank(node), + previousSibling = _getPreviousSiblingThatIsNotBlank(node); + + if (nextSibling && !_isLineBreakOrBlockElement(nextSibling)) { + node.parentNode.insertBefore(doc.createElement("br"), nextSibling); + } + if (previousSibling && !_isLineBreakOrBlockElement(previousSibling)) { + node.parentNode.insertBefore(doc.createElement("br"), node); + } + } + + /** + * Removes line breaks before and after the given node + */ + function _removeLineBreakBeforeAndAfter(node) { + var nextSibling = _getNextSiblingThatIsNotBlank(node), + previousSibling = _getPreviousSiblingThatIsNotBlank(node); + + if (nextSibling && _isLineBreak(nextSibling)) { + nextSibling.parentNode.removeChild(nextSibling); + } + if (previousSibling && _isLineBreak(previousSibling)) { + previousSibling.parentNode.removeChild(previousSibling); + } + } + + function _removeLastChildIfLineBreak(node) { + var lastChild = node.lastChild; + if (lastChild && _isLineBreak(lastChild)) { + lastChild.parentNode.removeChild(lastChild); + } + } + + function _isLineBreak(node) { + return node.nodeName === "BR"; + } + + /** + * Checks whether the elment causes a visual line break + * (<br> or block elements) + */ + function _isLineBreakOrBlockElement(element) { + if (_isLineBreak(element)) { + return true; + } + + if (dom.getStyle("display").from(element) === "block") { + return true; + } + + return false; + } + + /** + * Execute native query command + * and if necessary modify the inserted node's className + */ + function _execCommand(doc, command, nodeName, className) { + if (className) { + var eventListener = dom.observe(doc, "DOMNodeInserted", function(event) { + var target = event.target, + displayStyle; + if (target.nodeType !== wysihtml5.ELEMENT_NODE) { + return; + } + displayStyle = dom.getStyle("display").from(target); + if (displayStyle.substr(0, 6) !== "inline") { + // Make sure that only block elements receive the given class + target.className += " " + className; + } + }); + } + doc.execCommand(command, false, nodeName); + if (eventListener) { + eventListener.stop(); + } + } + + function _selectLineAndWrap(composer, element) { + composer.selection.selectLine(); + composer.selection.surround(element); + _removeLineBreakBeforeAndAfter(element); + _removeLastChildIfLineBreak(element); + composer.selection.selectNode(element); + } + + function _hasClasses(element) { + return !!wysihtml5.lang.string(element.className).trim(); + } + + wysihtml5.commands.formatBlock = { + exec: function(composer, command, nodeName, className, classRegExp) { + var doc = composer.doc, + blockElement = this.state(composer, command, nodeName, className, classRegExp), + selectedNode; + + nodeName = typeof(nodeName) === "string" ? nodeName.toUpperCase() : nodeName; + + if (blockElement) { + composer.selection.executeAndRestoreSimple(function() { + if (classRegExp) { + _removeClass(blockElement, classRegExp); + } + var hasClasses = _hasClasses(blockElement); + if (!hasClasses && blockElement.nodeName === (nodeName || DEFAULT_NODE_NAME)) { + // Insert a line break afterwards and beforewards when there are siblings + // that are not of type line break or block element + _addLineBreakBeforeAndAfter(blockElement); + dom.replaceWithChildNodes(blockElement); + } else if (hasClasses) { + // Make sure that styling is kept by renaming the element to <div> and copying over the class name + dom.renameElement(blockElement, DEFAULT_NODE_NAME); + } + }); + return; + } + + // Find similiar block element and rename it (<h2 class="foo"></h2> => <h1 class="foo"></h1>) + if (nodeName === null || wysihtml5.lang.array(BLOCK_ELEMENTS_GROUP).contains(nodeName)) { + selectedNode = composer.selection.getSelectedNode(); + blockElement = dom.getParentElement(selectedNode, { + nodeName: BLOCK_ELEMENTS_GROUP + }); + + if (blockElement) { + composer.selection.executeAndRestoreSimple(function() { + // Rename current block element to new block element and add class + if (nodeName) { + blockElement = dom.renameElement(blockElement, nodeName); + } + if (className) { + _addClass(blockElement, className, classRegExp); + } + }); + return; + } + } + + if (composer.commands.support(command)) { + _execCommand(doc, command, nodeName || DEFAULT_NODE_NAME, className); + return; + } + + blockElement = doc.createElement(nodeName || DEFAULT_NODE_NAME); + if (className) { + blockElement.className = className; + } + _selectLineAndWrap(composer, blockElement); + }, + + state: function(composer, command, nodeName, className, classRegExp) { + nodeName = typeof(nodeName) === "string" ? nodeName.toUpperCase() : nodeName; + var selectedNode = composer.selection.getSelectedNode(); + return dom.getParentElement(selectedNode, { + nodeName: nodeName, + className: className, + classRegExp: classRegExp + }); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);/** + * formatInline scenarios for tag "B" (| = caret, |foo| = selected text) + * + * #1 caret in unformatted text: + * abcdefg| + * output: + * abcdefg<b>|</b> + * + * #2 unformatted text selected: + * abc|deg|h + * output: + * abc<b>|deg|</b>h + * + * #3 unformatted text selected across boundaries: + * ab|c <span>defg|h</span> + * output: + * ab<b>|c </b><span><b>defg</b>|h</span> + * + * #4 formatted text entirely selected + * <b>|abc|</b> + * output: + * |abc| + * + * #5 formatted text partially selected + * <b>ab|c|</b> + * output: + * <b>ab</b>|c| + * + * #6 formatted text selected across boundaries + * <span>ab|c</span> <b>de|fgh</b> + * output: + * <span>ab|c</span> de|<b>fgh</b> + */ +(function(wysihtml5) { + var undef, + // Treat <b> as <strong> and vice versa + ALIAS_MAPPING = { + "strong": "b", + "em": "i", + "b": "strong", + "i": "em" + }, + htmlApplier = {}; + + function _getTagNames(tagName) { + var alias = ALIAS_MAPPING[tagName]; + return alias ? [tagName.toLowerCase(), alias.toLowerCase()] : [tagName.toLowerCase()]; + } + + function _getApplier(tagName, className, classRegExp) { + var identifier = tagName + ":" + className; + if (!htmlApplier[identifier]) { + htmlApplier[identifier] = new wysihtml5.selection.HTMLApplier(_getTagNames(tagName), className, classRegExp, true); + } + return htmlApplier[identifier]; + } + + wysihtml5.commands.formatInline = { + exec: function(composer, command, tagName, className, classRegExp) { + var range = composer.selection.getRange(); + if (!range) { + return false; + } + _getApplier(tagName, className, classRegExp).toggleRange(range); + composer.selection.setSelection(range); + }, + + state: function(composer, command, tagName, className, classRegExp) { + var doc = composer.doc, + aliasTagName = ALIAS_MAPPING[tagName] || tagName, + range; + + // Check whether the document contains a node with the desired tagName + if (!wysihtml5.dom.hasElementWithTagName(doc, tagName) && + !wysihtml5.dom.hasElementWithTagName(doc, aliasTagName)) { + return false; + } + + // Check whether the document contains a node with the desired className + if (className && !wysihtml5.dom.hasElementWithClassName(doc, className)) { + return false; + } + + range = composer.selection.getRange(); + if (!range) { + return false; + } + + return _getApplier(tagName, className, classRegExp).isAppliedToRange(range); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);(function(wysihtml5) { + var undef; + + wysihtml5.commands.insertHTML = { + exec: function(composer, command, html) { + if (composer.commands.support(command)) { + composer.doc.execCommand(command, false, html); + } else { + composer.selection.insertHTML(html); + } + }, + + state: function() { + return false; + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);(function(wysihtml5) { + var NODE_NAME = "IMG"; + + wysihtml5.commands.insertImage = { + /** + * Inserts an <img> + * If selection is already an image link, it removes it + * + * @example + * // either ... + * wysihtml5.commands.insertImage.exec(composer, "insertImage", "http://www.google.de/logo.jpg"); + * // ... or ... + * wysihtml5.commands.insertImage.exec(composer, "insertImage", { src: "http://www.google.de/logo.jpg", title: "foo" }); + */ + exec: function(composer, command, value) { + value = typeof(value) === "object" ? value : { src: value }; + + var doc = composer.doc, + image = this.state(composer), + textNode, + i, + parent; + + if (image) { + // Image already selected, set the caret before it and delete it + composer.selection.setBefore(image); + parent = image.parentNode; + parent.removeChild(image); + + // and it's parent <a> too if it hasn't got any other relevant child nodes + wysihtml5.dom.removeEmptyTextNodes(parent); + if (parent.nodeName === "A" && !parent.firstChild) { + composer.selection.setAfter(parent); + parent.parentNode.removeChild(parent); + } + + // firefox and ie sometimes don't remove the image handles, even though the image got removed + wysihtml5.quirks.redraw(composer.element); + return; + } + + image = doc.createElement(NODE_NAME); + + for (i in value) { + image[i] = value[i]; + } + + composer.selection.insertNode(image); + if (wysihtml5.browser.hasProblemsSettingCaretAfterImg()) { + textNode = doc.createTextNode(wysihtml5.INVISIBLE_SPACE); + composer.selection.insertNode(textNode); + composer.selection.setAfter(textNode); + } else { + composer.selection.setAfter(image); + } + }, + + state: function(composer) { + var doc = composer.doc, + selectedNode, + text, + imagesInSelection; + + if (!wysihtml5.dom.hasElementWithTagName(doc, NODE_NAME)) { + return false; + } + + selectedNode = composer.selection.getSelectedNode(); + if (!selectedNode) { + return false; + } + + if (selectedNode.nodeName === NODE_NAME) { + // This works perfectly in IE + return selectedNode; + } + + if (selectedNode.nodeType !== wysihtml5.ELEMENT_NODE) { + return false; + } + + text = composer.selection.getText(); + text = wysihtml5.lang.string(text).trim(); + if (text) { + return false; + } + + imagesInSelection = composer.selection.getNodes(wysihtml5.ELEMENT_NODE, function(node) { + return node.nodeName === "IMG"; + }); + + if (imagesInSelection.length !== 1) { + return false; + } + + return imagesInSelection[0]; + }, + + value: function(composer) { + var image = this.state(composer); + return image && image.src; + } + }; +})(wysihtml5);(function(wysihtml5) { + var undef, + LINE_BREAK = "<br>" + (wysihtml5.browser.needsSpaceAfterLineBreak() ? " " : ""); + + wysihtml5.commands.insertLineBreak = { + exec: function(composer, command) { + if (composer.commands.support(command)) { + composer.doc.execCommand(command, false, null); + if (!wysihtml5.browser.autoScrollsToCaret()) { + composer.selection.scrollIntoView(); + } + } else { + composer.commands.exec("insertHTML", LINE_BREAK); + } + }, + + state: function() { + return false; + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);(function(wysihtml5) { + var undef; + + wysihtml5.commands.insertOrderedList = { + exec: function(composer, command) { + var doc = composer.doc, + selectedNode = composer.selection.getSelectedNode(), + list = wysihtml5.dom.getParentElement(selectedNode, { nodeName: "OL" }), + otherList = wysihtml5.dom.getParentElement(selectedNode, { nodeName: "UL" }), + tempClassName = "_wysihtml5-temp-" + new Date().getTime(), + isEmpty, + tempElement; + + if (composer.commands.support(command)) { + doc.execCommand(command, false, null); + return; + } + + if (list) { + // Unwrap list + // <ol><li>foo</li><li>bar</li></ol> + // becomes: + // foo<br>bar<br> + composer.selection.executeAndRestoreSimple(function() { + wysihtml5.dom.resolveList(list); + }); + } else if (otherList) { + // Turn an unordered list into an ordered list + // <ul><li>foo</li><li>bar</li></ul> + // becomes: + // <ol><li>foo</li><li>bar</li></ol> + composer.selection.executeAndRestoreSimple(function() { + wysihtml5.dom.renameElement(otherList, "ol"); + }); + } else { + // Create list + composer.commands.exec("formatBlock", "div", tempClassName); + tempElement = doc.querySelector("." + tempClassName); + isEmpty = tempElement.innerHTML === "" || tempElement.innerHTML === wysihtml5.INVISIBLE_SPACE; + composer.selection.executeAndRestoreSimple(function() { + list = wysihtml5.dom.convertToList(tempElement, "ol"); + }); + if (isEmpty) { + composer.selection.selectNode(list.querySelector("li")); + } + } + }, + + state: function(composer) { + var selectedNode = composer.selection.getSelectedNode(); + return wysihtml5.dom.getParentElement(selectedNode, { nodeName: "OL" }); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);(function(wysihtml5) { + var undef; + + wysihtml5.commands.insertUnorderedList = { + exec: function(composer, command) { + var doc = composer.doc, + selectedNode = composer.selection.getSelectedNode(), + list = wysihtml5.dom.getParentElement(selectedNode, { nodeName: "UL" }), + otherList = wysihtml5.dom.getParentElement(selectedNode, { nodeName: "OL" }), + tempClassName = "_wysihtml5-temp-" + new Date().getTime(), + isEmpty, + tempElement; + + if (composer.commands.support(command)) { + doc.execCommand(command, false, null); + return; + } + + if (list) { + // Unwrap list + // <ul><li>foo</li><li>bar</li></ul> + // becomes: + // foo<br>bar<br> + composer.selection.executeAndRestoreSimple(function() { + wysihtml5.dom.resolveList(list); + }); + } else if (otherList) { + // Turn an ordered list into an unordered list + // <ol><li>foo</li><li>bar</li></ol> + // becomes: + // <ul><li>foo</li><li>bar</li></ul> + composer.selection.executeAndRestoreSimple(function() { + wysihtml5.dom.renameElement(otherList, "ul"); + }); + } else { + // Create list + composer.commands.exec("formatBlock", "div", tempClassName); + tempElement = doc.querySelector("." + tempClassName); + isEmpty = tempElement.innerHTML === "" || tempElement.innerHTML === wysihtml5.INVISIBLE_SPACE; + composer.selection.executeAndRestoreSimple(function() { + list = wysihtml5.dom.convertToList(tempElement, "ul"); + }); + if (isEmpty) { + composer.selection.selectNode(list.querySelector("li")); + } + } + }, + + state: function(composer) { + var selectedNode = composer.selection.getSelectedNode(); + return wysihtml5.dom.getParentElement(selectedNode, { nodeName: "UL" }); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);(function(wysihtml5) { + var undef; + + wysihtml5.commands.italic = { + exec: function(composer, command) { + return wysihtml5.commands.formatInline.exec(composer, command, "i"); + }, + + state: function(composer, command, color) { + // element.ownerDocument.queryCommandState("italic") results: + // firefox: only <i> + // chrome: <i>, <em>, <blockquote>, ... + // ie: <i>, <em> + // opera: only <i> + return wysihtml5.commands.formatInline.state(composer, command, "i"); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);(function(wysihtml5) { + var undef, + CLASS_NAME = "wysiwyg-text-align-center", + REG_EXP = /wysiwyg-text-align-[a-z]+/g; + + wysihtml5.commands.justifyCenter = { + exec: function(composer, command) { + return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", null, CLASS_NAME, REG_EXP); + }, + + state: function(composer, command) { + return wysihtml5.commands.formatBlock.state(composer, "formatBlock", null, CLASS_NAME, REG_EXP); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);(function(wysihtml5) { + var undef, + CLASS_NAME = "wysiwyg-text-align-left", + REG_EXP = /wysiwyg-text-align-[a-z]+/g; + + wysihtml5.commands.justifyLeft = { + exec: function(composer, command) { + return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", null, CLASS_NAME, REG_EXP); + }, + + state: function(composer, command) { + return wysihtml5.commands.formatBlock.state(composer, "formatBlock", null, CLASS_NAME, REG_EXP); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);(function(wysihtml5) { + var undef, + CLASS_NAME = "wysiwyg-text-align-right", + REG_EXP = /wysiwyg-text-align-[a-z]+/g; + + wysihtml5.commands.justifyRight = { + exec: function(composer, command) { + return wysihtml5.commands.formatBlock.exec(composer, "formatBlock", null, CLASS_NAME, REG_EXP); + }, + + state: function(composer, command) { + return wysihtml5.commands.formatBlock.state(composer, "formatBlock", null, CLASS_NAME, REG_EXP); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);(function(wysihtml5) { + var undef; + wysihtml5.commands.underline = { + exec: function(composer, command) { + return wysihtml5.commands.formatInline.exec(composer, command, "u"); + }, + + state: function(composer, command) { + return wysihtml5.commands.formatInline.state(composer, command, "u"); + }, + + value: function() { + return undef; + } + }; +})(wysihtml5);/** + * Undo Manager for wysihtml5 + * slightly inspired by http://rniwa.com/editing/undomanager.html#the-undomanager-interface + */ +(function(wysihtml5) { + var Z_KEY = 90, + Y_KEY = 89, + BACKSPACE_KEY = 8, + DELETE_KEY = 46, + MAX_HISTORY_ENTRIES = 40, + UNDO_HTML = '<span id="_wysihtml5-undo" class="_wysihtml5-temp">' + wysihtml5.INVISIBLE_SPACE + '</span>', + REDO_HTML = '<span id="_wysihtml5-redo" class="_wysihtml5-temp">' + wysihtml5.INVISIBLE_SPACE + '</span>', + dom = wysihtml5.dom; + + function cleanTempElements(doc) { + var tempElement; + while (tempElement = doc.querySelector("._wysihtml5-temp")) { + tempElement.parentNode.removeChild(tempElement); + } + } + + wysihtml5.UndoManager = wysihtml5.lang.Dispatcher.extend( + /** @scope wysihtml5.UndoManager.prototype */ { + constructor: function(editor) { + this.editor = editor; + this.composer = editor.composer; + this.element = this.composer.element; + this.history = [this.composer.getValue()]; + this.position = 1; + + // Undo manager currently only supported in browsers who have the insertHTML command (not IE) + if (this.composer.commands.support("insertHTML")) { + this._observe(); + } + }, + + _observe: function() { + var that = this, + doc = this.composer.sandbox.getDocument(), + lastKey; + + // Catch CTRL+Z and CTRL+Y + dom.observe(this.element, "keydown", function(event) { + if (event.altKey || (!event.ctrlKey && !event.metaKey)) { + return; + } + + var keyCode = event.keyCode, + isUndo = keyCode === Z_KEY && !event.shiftKey, + isRedo = (keyCode === Z_KEY && event.shiftKey) || (keyCode === Y_KEY); + + if (isUndo) { + that.undo(); + event.preventDefault(); + } else if (isRedo) { + that.redo(); + event.preventDefault(); + } + }); + + // Catch delete and backspace + dom.observe(this.element, "keydown", function(event) { + var keyCode = event.keyCode; + if (keyCode === lastKey) { + return; + } + + lastKey = keyCode; + + if (keyCode === BACKSPACE_KEY || keyCode === DELETE_KEY) { + that.transact(); + } + }); + + // Now this is very hacky: + // These days browsers don't offer a undo/redo event which we could hook into + // to be notified when the user hits undo/redo in the contextmenu. + // Therefore we simply insert two elements as soon as the contextmenu gets opened. + // The last element being inserted will be immediately be removed again by a exexCommand("undo") + // => When the second element appears in the dom tree then we know the user clicked "redo" in the context menu + // => When the first element disappears from the dom tree then we know the user clicked "undo" in the context menu + if (wysihtml5.browser.hasUndoInContextMenu()) { + var interval, observed, cleanUp = function() { + cleanTempElements(doc); + clearInterval(interval); + }; + + dom.observe(this.element, "contextmenu", function() { + cleanUp(); + that.composer.selection.executeAndRestoreSimple(function() { + if (that.element.lastChild) { + that.composer.selection.setAfter(that.element.lastChild); + } + + // enable undo button in context menu + doc.execCommand("insertHTML", false, UNDO_HTML); + // enable redo button in context menu + doc.execCommand("insertHTML", false, REDO_HTML); + doc.execCommand("undo", false, null); + }); + + interval = setInterval(function() { + if (doc.getElementById("_wysihtml5-redo")) { + cleanUp(); + that.redo(); + } else if (!doc.getElementById("_wysihtml5-undo")) { + cleanUp(); + that.undo(); + } + }, 400); + + if (!observed) { + observed = true; + dom.observe(document, "mousedown", cleanUp); + dom.observe(doc, ["mousedown", "paste", "cut", "copy"], cleanUp); + } + }); + } + + this.editor + .observe("newword:composer", function() { + that.transact(); + }) + + .observe("beforecommand:composer", function() { + that.transact(); + }); + }, + + transact: function() { + var previousHtml = this.history[this.position - 1], + currentHtml = this.composer.getValue(); + + if (currentHtml == previousHtml) { + return; + } + + var length = this.history.length = this.position; + if (length > MAX_HISTORY_ENTRIES) { + this.history.shift(); + this.position--; + } + + this.position++; + this.history.push(currentHtml); + }, + + undo: function() { + this.transact(); + + if (this.position <= 1) { + return; + } + + this.set(this.history[--this.position - 1]); + this.editor.fire("undo:composer"); + }, + + redo: function() { + if (this.position >= this.history.length) { + return; + } + + this.set(this.history[++this.position - 1]); + this.editor.fire("redo:composer"); + }, + + set: function(html) { + this.composer.setValue(html); + this.editor.focus(true); + } + }); +})(wysihtml5); +/** + * TODO: the following methods still need unit test coverage + */ +wysihtml5.views.View = Base.extend( + /** @scope wysihtml5.views.View.prototype */ { + constructor: function(parent, textareaElement, config) { + this.parent = parent; + this.element = textareaElement; + this.config = config; + + this._observeViewChange(); + }, + + _observeViewChange: function() { + var that = this; + this.parent.observe("beforeload", function() { + that.parent.observe("change_view", function(view) { + if (view === that.name) { + that.parent.currentView = that; + that.show(); + // Using tiny delay here to make sure that the placeholder is set before focusing + setTimeout(function() { that.focus(); }, 0); + } else { + that.hide(); + } + }); + }); + }, + + focus: function() { + if (this.element.ownerDocument.querySelector(":focus") === this.element) { + return; + } + + try { this.element.focus(); } catch(e) {} + }, + + hide: function() { + this.element.style.display = "none"; + }, + + show: function() { + this.element.style.display = ""; + }, + + disable: function() { + this.element.setAttribute("disabled", "disabled"); + }, + + enable: function() { + this.element.removeAttribute("disabled"); + } +});(function(wysihtml5) { + var dom = wysihtml5.dom, + browser = wysihtml5.browser; + + wysihtml5.views.Composer = wysihtml5.views.View.extend( + /** @scope wysihtml5.views.Composer.prototype */ { + name: "composer", + + // Needed for firefox in order to display a proper caret in an empty contentEditable + CARET_HACK: "<br>", + + constructor: function(parent, textareaElement, config) { + this.base(parent, textareaElement, config); + this.textarea = this.parent.textarea; + this._initSandbox(); + }, + + clear: function() { + this.element.innerHTML = browser.displaysCaretInEmptyContentEditableCorrectly() ? "" : this.CARET_HACK; + }, + + getValue: function(parse) { + var value = this.isEmpty() ? "" : wysihtml5.quirks.getCorrectInnerHTML(this.element); + + if (parse) { + value = this.parent.parse(value); + } + + // Replace all "zero width no breaking space" chars + // which are used as hacks to enable some functionalities + // Also remove all CARET hacks that somehow got left + value = wysihtml5.lang.string(value).replace(wysihtml5.INVISIBLE_SPACE).by(""); + + return value; + }, + + setValue: function(html, parse) { + if (parse) { + html = this.parent.parse(html); + } + this.element.innerHTML = html; + }, + + show: function() { + this.iframe.style.display = this._displayStyle || ""; + + // Firefox needs this, otherwise contentEditable becomes uneditable + this.disable(); + this.enable(); + }, + + hide: function() { + this._displayStyle = dom.getStyle("display").from(this.iframe); + if (this._displayStyle === "none") { + this._displayStyle = null; + } + this.iframe.style.display = "none"; + }, + + disable: function() { + this.element.removeAttribute("contentEditable"); + this.base(); + }, + + enable: function() { + this.element.setAttribute("contentEditable", "true"); + this.base(); + }, + + focus: function(setToEnd) { + // IE 8 fires the focus event after .focus() + // This is needed by our simulate_placeholder.js to work + // therefore we clear it ourselves this time + if (wysihtml5.browser.doesAsyncFocus() && this.hasPlaceholderSet()) { + this.clear(); + } + + this.base(); + + var lastChild = this.element.lastChild; + if (setToEnd && lastChild) { + if (lastChild.nodeName === "BR") { + this.selection.setBefore(this.element.lastChild); + } else { + this.selection.setAfter(this.element.lastChild); + } + } + }, + + getTextContent: function() { + return dom.getTextContent(this.element); + }, + + hasPlaceholderSet: function() { + return this.getTextContent() == this.textarea.element.getAttribute("placeholder"); + }, + + isEmpty: function() { + var innerHTML = this.element.innerHTML, + elementsWithVisualValue = "blockquote, ul, ol, img, embed, object, table, iframe, svg, video, audio, button, input, select, textarea"; + return innerHTML === "" || + innerHTML === this.CARET_HACK || + this.hasPlaceholderSet() || + (this.getTextContent() === "" && !this.element.querySelector(elementsWithVisualValue)); + }, + + _initSandbox: function() { + var that = this; + + this.sandbox = new dom.Sandbox(function() { + that._create(); + }, { + stylesheets: this.config.stylesheets + }); + this.iframe = this.sandbox.getIframe(); + + // Create hidden field which tells the server after submit, that the user used an wysiwyg editor + var hiddenField = document.createElement("input"); + hiddenField.type = "hidden"; + hiddenField.name = "_wysihtml5_mode"; + hiddenField.value = 1; + + // Store reference to current wysihtml5 instance on the textarea element + var textareaElement = this.textarea.element; + dom.insert(this.iframe).after(textareaElement); + dom.insert(hiddenField).after(textareaElement); + }, + + _create: function() { + var that = this; + + this.doc = this.sandbox.getDocument(); + this.element = this.doc.body; + this.textarea = this.parent.textarea; + this.element.innerHTML = this.textarea.getValue(true); + this.enable(); + + // Make sure our selection handler is ready + this.selection = new wysihtml5.Selection(this.parent); + + // Make sure commands dispatcher is ready + this.commands = new wysihtml5.Commands(this.parent); + + dom.copyAttributes([ + "className", "spellcheck", "title", "lang", "dir", "accessKey" + ]).from(this.textarea.element).to(this.element); + + dom.addClass(this.element, this.config.composerClassName); + + // Make the editor look like the original textarea, by syncing styles + if (this.config.style) { + this.style(); + } + + this.observe(); + + var name = this.config.name; + if (name) { + dom.addClass(this.element, name); + dom.addClass(this.iframe, name); + } + + // Simulate html5 placeholder attribute on contentEditable element + var placeholderText = typeof(this.config.placeholder) === "string" + ? this.config.placeholder + : this.textarea.element.getAttribute("placeholder"); + if (placeholderText) { + dom.simulatePlaceholder(this.parent, this, placeholderText); + } + + // Make sure that the browser avoids using inline styles whenever possible + this.commands.exec("styleWithCSS", false); + + this._initAutoLinking(); + this._initObjectResizing(); + this._initUndoManager(); + + // Simulate html5 autofocus on contentEditable element + if (this.textarea.element.hasAttribute("autofocus") || document.querySelector(":focus") == this.textarea.element) { + setTimeout(function() { that.focus(); }, 100); + } + + wysihtml5.quirks.insertLineBreakOnReturn(this); + + // IE sometimes leaves a single paragraph, which can't be removed by the user + if (!browser.clearsContentEditableCorrectly()) { + wysihtml5.quirks.ensureProperClearing(this); + } + + if (!browser.clearsListsInContentEditableCorrectly()) { + wysihtml5.quirks.ensureProperClearingOfLists(this); + } + + // Set up a sync that makes sure that textarea and editor have the same content + if (this.initSync && this.config.sync) { + this.initSync(); + } + + // Okay hide the textarea, we are ready to go + this.textarea.hide(); + + // Fire global (before-)load event + this.parent.fire("beforeload").fire("load"); + }, + + _initAutoLinking: function() { + var that = this, + supportsDisablingOfAutoLinking = browser.canDisableAutoLinking(), + supportsAutoLinking = browser.doesAutoLinkingInContentEditable(); + if (supportsDisablingOfAutoLinking) { + this.commands.exec("autoUrlDetect", false); + } + + if (!this.config.autoLink) { + return; + } + + // Only do the auto linking by ourselves when the browser doesn't support auto linking + // OR when he supports auto linking but we were able to turn it off (IE9+) + if (!supportsAutoLinking || (supportsAutoLinking && supportsDisablingOfAutoLinking)) { + this.parent.observe("newword:composer", function() { + that.selection.executeAndRestore(function(startContainer, endContainer) { + dom.autoLink(endContainer.parentNode); + }); + }); + } + + // Assuming we have the following: + // <a href="http://www.google.de">http://www.google.de</a> + // If a user now changes the url in the innerHTML we want to make sure that + // it's synchronized with the href attribute (as long as the innerHTML is still a url) + var // Use a live NodeList to check whether there are any links in the document + links = this.sandbox.getDocument().getElementsByTagName("a"), + // The autoLink helper method reveals a reg exp to detect correct urls + urlRegExp = dom.autoLink.URL_REG_EXP, + getTextContent = function(element) { + var textContent = wysihtml5.lang.string(dom.getTextContent(element)).trim(); + if (textContent.substr(0, 4) === "www.") { + textContent = "http://" + textContent; + } + return textContent; + }; + + dom.observe(this.element, "keydown", function(event) { + if (!links.length) { + return; + } + + var selectedNode = that.selection.getSelectedNode(event.target.ownerDocument), + link = dom.getParentElement(selectedNode, { nodeName: "A" }, 4), + textContent; + + if (!link) { + return; + } + + textContent = getTextContent(link); + // keydown is fired before the actual content is changed + // therefore we set a timeout to change the href + setTimeout(function() { + var newTextContent = getTextContent(link); + if (newTextContent === textContent) { + return; + } + + // Only set href when new href looks like a valid url + if (newTextContent.match(urlRegExp)) { + link.setAttribute("href", newTextContent); + } + }, 0); + }); + }, + + _initObjectResizing: function() { + var properties = ["width", "height"], + propertiesLength = properties.length, + element = this.element; + + this.commands.exec("enableObjectResizing", this.config.allowObjectResizing); + + if (this.config.allowObjectResizing) { + // IE sets inline styles after resizing objects + // The following lines make sure that the width/height css properties + // are copied over to the width/height attributes + if (browser.supportsEvent("resizeend")) { + dom.observe(element, "resizeend", function(event) { + var target = event.target || event.srcElement, + style = target.style, + i = 0, + property; + for(; i<propertiesLength; i++) { + property = properties[i]; + if (style[property]) { + target.setAttribute(property, parseInt(style[property], 10)); + style[property] = ""; + } + } + // After resizing IE sometimes forgets to remove the old resize handles + wysihtml5.quirks.redraw(element); + }); + } + } else { + if (browser.supportsEvent("resizestart")) { + dom.observe(element, "resizestart", function(event) { event.preventDefault(); }); + } + } + }, + + _initUndoManager: function() { + new wysihtml5.UndoManager(this.parent); + } + }); +})(wysihtml5);(function(wysihtml5) { + var dom = wysihtml5.dom, + doc = document, + win = window, + HOST_TEMPLATE = doc.createElement("div"), + /** + * Styles to copy from textarea to the composer element + */ + TEXT_FORMATTING = [ + "background-color", + "color", "cursor", + "font-family", "font-size", "font-style", "font-variant", "font-weight", + "line-height", "letter-spacing", + "text-align", "text-decoration", "text-indent", "text-rendering", + "word-break", "word-wrap", "word-spacing" + ], + /** + * Styles to copy from textarea to the iframe + */ + BOX_FORMATTING = [ + "background-color", + "border-collapse", + "border-bottom-color", "border-bottom-style", "border-bottom-width", + "border-left-color", "border-left-style", "border-left-width", + "border-right-color", "border-right-style", "border-right-width", + "border-top-color", "border-top-style", "border-top-width", + "clear", "display", "float", + "margin-bottom", "margin-left", "margin-right", "margin-top", + "outline-color", "outline-offset", "outline-width", "outline-style", + "padding-left", "padding-right", "padding-top", "padding-bottom", + "position", "top", "left", "right", "bottom", "z-index", + "vertical-align", "text-align", + "-webkit-box-sizing", "-moz-box-sizing", "-ms-box-sizing", "box-sizing", + "-webkit-box-shadow", "-moz-box-shadow", "-ms-box-shadow","box-shadow", + "-webkit-border-top-right-radius", "-moz-border-radius-topright", "border-top-right-radius", + "-webkit-border-bottom-right-radius", "-moz-border-radius-bottomright", "border-bottom-right-radius", + "-webkit-border-bottom-left-radius", "-moz-border-radius-bottomleft", "border-bottom-left-radius", + "-webkit-border-top-left-radius", "-moz-border-radius-topleft", "border-top-left-radius", + "width", "height" + ], + /** + * Styles to sync while the window gets resized + */ + RESIZE_STYLE = [ + "width", "height", + "top", "left", "right", "bottom" + ], + ADDITIONAL_CSS_RULES = [ + "html { height: 100%; }", + "body { min-height: 100%; padding: 0; margin: 0; margin-top: -1px; padding-top: 1px; }", + "._wysihtml5-temp { display: none; }", + wysihtml5.browser.isGecko ? + "body.placeholder { color: graytext !important; }" : + "body.placeholder { color: #a9a9a9 !important; }", + "body[disabled] { background-color: #eee !important; color: #999 !important; cursor: default !important; }", + // Ensure that user see's broken images and can delete them + "img:-moz-broken { -moz-force-broken-image-icon: 1; height: 24px; width: 24px; }" + ]; + + /** + * With "setActive" IE offers a smart way of focusing elements without scrolling them into view: + * http://msdn.microsoft.com/en-us/library/ms536738(v=vs.85).aspx + * + * Other browsers need a more hacky way: (pssst don't tell my mama) + * In order to prevent the element being scrolled into view when focusing it, we simply + * move it out of the scrollable area, focus it, and reset it's position + */ + var focusWithoutScrolling = function(element) { + if (element.setActive) { + // Following line could cause a js error when the textarea is invisible + // See https://github.com/xing/wysihtml5/issues/9 + try { element.setActive(); } catch(e) {} + } else { + var elementStyle = element.style, + originalScrollTop = doc.documentElement.scrollTop || doc.body.scrollTop, + originalScrollLeft = doc.documentElement.scrollLeft || doc.body.scrollLeft, + originalStyles = { + position: elementStyle.position, + top: elementStyle.top, + left: elementStyle.left, + WebkitUserSelect: elementStyle.WebkitUserSelect + }; + + dom.setStyles({ + position: "absolute", + top: "-99999px", + left: "-99999px", + // Don't ask why but temporarily setting -webkit-user-select to none makes the whole thing performing smoother + WebkitUserSelect: "none" + }).on(element); + + element.focus(); + + dom.setStyles(originalStyles).on(element); + + if (win.scrollTo) { + // Some browser extensions unset this method to prevent annoyances + // "Better PopUp Blocker" for Chrome http://code.google.com/p/betterpopupblocker/source/browse/trunk/blockStart.js#100 + // Issue: http://code.google.com/p/betterpopupblocker/issues/detail?id=1 + win.scrollTo(originalScrollLeft, originalScrollTop); + } + } + }; + + + wysihtml5.views.Composer.prototype.style = function() { + var that = this, + originalActiveElement = doc.querySelector(":focus"), + textareaElement = this.textarea.element, + hasPlaceholder = textareaElement.hasAttribute("placeholder"), + originalPlaceholder = hasPlaceholder && textareaElement.getAttribute("placeholder"); + this.focusStylesHost = this.focusStylesHost || HOST_TEMPLATE.cloneNode(false); + this.blurStylesHost = this.blurStylesHost || HOST_TEMPLATE.cloneNode(false); + + // Remove placeholder before copying (as the placeholder has an affect on the computed style) + if (hasPlaceholder) { + textareaElement.removeAttribute("placeholder"); + } + + if (textareaElement === originalActiveElement) { + textareaElement.blur(); + } + + // --------- iframe styles (has to be set before editor styles, otherwise IE9 sets wrong fontFamily on blurStylesHost) --------- + dom.copyStyles(BOX_FORMATTING).from(textareaElement).to(this.iframe).andTo(this.blurStylesHost); + + // --------- editor styles --------- + dom.copyStyles(TEXT_FORMATTING).from(textareaElement).to(this.element).andTo(this.blurStylesHost); + + // --------- apply standard rules --------- + dom.insertCSS(ADDITIONAL_CSS_RULES).into(this.element.ownerDocument); + + // --------- :focus styles --------- + focusWithoutScrolling(textareaElement); + dom.copyStyles(BOX_FORMATTING).from(textareaElement).to(this.focusStylesHost); + dom.copyStyles(TEXT_FORMATTING).from(textareaElement).to(this.focusStylesHost); + + // Make sure that we don't change the display style of the iframe when copying styles oblur/onfocus + // this is needed for when the change_view event is fired where the iframe is hidden and then + // the blur event fires and re-displays it + var boxFormattingStyles = wysihtml5.lang.array(BOX_FORMATTING).without(["display"]); + + // --------- restore focus --------- + if (originalActiveElement) { + originalActiveElement.focus(); + } else { + textareaElement.blur(); + } + + // --------- restore placeholder --------- + if (hasPlaceholder) { + textareaElement.setAttribute("placeholder", originalPlaceholder); + } + + // When copying styles, we only get the computed style which is never returned in percent unit + // Therefore we've to recalculate style onresize + if (!wysihtml5.browser.hasCurrentStyleProperty()) { + var winObserver = dom.observe(win, "resize", function() { + // Remove event listener if composer doesn't exist anymore + if (!dom.contains(document.documentElement, that.iframe)) { + winObserver.stop(); + return; + } + var originalTextareaDisplayStyle = dom.getStyle("display").from(textareaElement), + originalComposerDisplayStyle = dom.getStyle("display").from(that.iframe); + textareaElement.style.display = ""; + that.iframe.style.display = "none"; + dom.copyStyles(RESIZE_STYLE) + .from(textareaElement) + .to(that.iframe) + .andTo(that.focusStylesHost) + .andTo(that.blurStylesHost); + that.iframe.style.display = originalComposerDisplayStyle; + textareaElement.style.display = originalTextareaDisplayStyle; + }); + } + + // --------- Sync focus/blur styles --------- + this.parent.observe("focus:composer", function() { + dom.copyStyles(boxFormattingStyles) .from(that.focusStylesHost).to(that.iframe); + dom.copyStyles(TEXT_FORMATTING) .from(that.focusStylesHost).to(that.element); + }); + + this.parent.observe("blur:composer", function() { + dom.copyStyles(boxFormattingStyles) .from(that.blurStylesHost).to(that.iframe); + dom.copyStyles(TEXT_FORMATTING) .from(that.blurStylesHost).to(that.element); + }); + + return this; + }; +})(wysihtml5);/** + * Taking care of events + * - Simulating 'change' event on contentEditable element + * - Handling drag & drop logic + * - Catch paste events + * - Dispatch proprietary newword:composer event + * - Keyboard shortcuts + */ +(function(wysihtml5) { + var dom = wysihtml5.dom, + browser = wysihtml5.browser, + /** + * Map keyCodes to query commands + */ + shortcuts = { + "66": "bold", // B + "73": "italic", // I + "85": "underline" // U + }; + + wysihtml5.views.Composer.prototype.observe = function() { + var that = this, + state = this.getValue(), + iframe = this.sandbox.getIframe(), + element = this.element, + focusBlurElement = browser.supportsEventsInIframeCorrectly() ? element : this.sandbox.getWindow(), + // Firefox < 3.5 doesn't support the drop event, instead it supports a so called "dragdrop" event which behaves almost the same + pasteEvents = browser.supportsEvent("drop") ? ["drop", "paste"] : ["dragdrop", "paste"]; + + // --------- destroy:composer event --------- + dom.observe(iframe, "DOMNodeRemoved", function() { + clearInterval(domNodeRemovedInterval); + that.parent.fire("destroy:composer"); + }); + + // DOMNodeRemoved event is not supported in IE 8 + var domNodeRemovedInterval = setInterval(function() { + if (!dom.contains(document.documentElement, iframe)) { + clearInterval(domNodeRemovedInterval); + that.parent.fire("destroy:composer"); + } + }, 250); + + + // --------- Focus & blur logic --------- + dom.observe(focusBlurElement, "focus", function() { + that.parent.fire("focus").fire("focus:composer"); + + // Delay storing of state until all focus handler are fired + // especially the one which resets the placeholder + setTimeout(function() { state = that.getValue(); }, 0); + }); + + dom.observe(focusBlurElement, "blur", function() { + if (state !== that.getValue()) { + that.parent.fire("change").fire("change:composer"); + } + that.parent.fire("blur").fire("blur:composer"); + }); + + if (wysihtml5.browser.isIos()) { + // When on iPad/iPhone/IPod after clicking outside of editor, the editor loses focus + // but the UI still acts as if the editor has focus (blinking caret and onscreen keyboard visible) + // We prevent that by focusing a temporary input element which immediately loses focus + dom.observe(element, "blur", function() { + var input = element.ownerDocument.createElement("input"), + originalScrollTop = document.documentElement.scrollTop || document.body.scrollTop, + originalScrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; + try { + that.selection.insertNode(input); + } catch(e) { + element.appendChild(input); + } + input.focus(); + input.parentNode.removeChild(input); + + window.scrollTo(originalScrollLeft, originalScrollTop); + }); + } + + // --------- Drag & Drop logic --------- + dom.observe(element, "dragenter", function() { + that.parent.fire("unset_placeholder"); + }); + + if (browser.firesOnDropOnlyWhenOnDragOverIsCancelled()) { + dom.observe(element, ["dragover", "dragenter"], function(event) { + event.preventDefault(); + }); + } + + dom.observe(element, pasteEvents, function(event) { + var dataTransfer = event.dataTransfer, + data; + + if (dataTransfer && browser.supportsDataTransfer()) { + data = dataTransfer.getData("text/html") || dataTransfer.getData("text/plain"); + } + if (data) { + element.focus(); + that.commands.exec("insertHTML", data); + that.parent.fire("paste").fire("paste:composer"); + event.stopPropagation(); + event.preventDefault(); + } else { + setTimeout(function() { + that.parent.fire("paste").fire("paste:composer"); + }, 0); + } + }); + + // --------- neword event --------- + dom.observe(element, "keyup", function(event) { + var keyCode = event.keyCode; + if (keyCode === wysihtml5.SPACE_KEY || keyCode === wysihtml5.ENTER_KEY) { + that.parent.fire("newword:composer"); + } + }); + + this.parent.observe("paste:composer", function() { + setTimeout(function() { that.parent.fire("newword:composer"); }, 0); + }); + + // --------- Make sure that images are selected when clicking on them --------- + if (!browser.canSelectImagesInContentEditable()) { + dom.observe(element, "mousedown", function(event) { + var target = event.target; + if (target.nodeName === "IMG") { + that.selection.selectNode(target); + event.preventDefault(); + } + }); + } + + // --------- Shortcut logic --------- + dom.observe(element, "keydown", function(event) { + var keyCode = event.keyCode, + command = shortcuts[keyCode]; + if ((event.ctrlKey || event.metaKey) && !event.altKey && command) { + that.commands.exec(command); + event.preventDefault(); + } + }); + + // --------- Make sure that when pressing backspace/delete on selected images deletes the image and it's anchor --------- + dom.observe(element, "keydown", function(event) { + var target = that.selection.getSelectedNode(true), + keyCode = event.keyCode, + parent; + if (target && target.nodeName === "IMG" && (keyCode === wysihtml5.BACKSPACE_KEY || keyCode === wysihtml5.DELETE_KEY)) { // 8 => backspace, 46 => delete + parent = target.parentNode; + // delete the <img> + parent.removeChild(target); + // and it's parent <a> too if it hasn't got any other child nodes + if (parent.nodeName === "A" && !parent.firstChild) { + parent.parentNode.removeChild(parent); + } + + setTimeout(function() { wysihtml5.quirks.redraw(element); }, 0); + event.preventDefault(); + } + }); + + // --------- Show url in tooltip when hovering links or images --------- + var titlePrefixes = { + IMG: "Image: ", + A: "Link: " + }; + + dom.observe(element, "mouseover", function(event) { + var target = event.target, + nodeName = target.nodeName, + title; + if (nodeName !== "A" && nodeName !== "IMG") { + return; + } + var hasTitle = target.hasAttribute("title"); + if(!hasTitle){ + title = titlePrefixes[nodeName] + (target.getAttribute("href") || target.getAttribute("src")); + target.setAttribute("title", title); + } + }); + }; +})(wysihtml5);/** + * Class that takes care that the value of the composer and the textarea is always in sync + */ +(function(wysihtml5) { + var INTERVAL = 400; + + wysihtml5.views.Synchronizer = Base.extend( + /** @scope wysihtml5.views.Synchronizer.prototype */ { + + constructor: function(editor, textarea, composer) { + this.editor = editor; + this.textarea = textarea; + this.composer = composer; + + this._observe(); + }, + + /** + * Sync html from composer to textarea + * Takes care of placeholders + * @param {Boolean} shouldParseHtml Whether the html should be sanitized before inserting it into the textarea + */ + fromComposerToTextarea: function(shouldParseHtml) { + this.textarea.setValue(wysihtml5.lang.string(this.composer.getValue()).trim(), shouldParseHtml); + }, + + /** + * Sync value of textarea to composer + * Takes care of placeholders + * @param {Boolean} shouldParseHtml Whether the html should be sanitized before inserting it into the composer + */ + fromTextareaToComposer: function(shouldParseHtml) { + var textareaValue = this.textarea.getValue(); + if (textareaValue) { + this.composer.setValue(textareaValue, shouldParseHtml); + } else { + this.composer.clear(); + this.editor.fire("set_placeholder"); + } + }, + + /** + * Invoke syncing based on view state + * @param {Boolean} shouldParseHtml Whether the html should be sanitized before inserting it into the composer/textarea + */ + sync: function(shouldParseHtml) { + if (this.editor.currentView.name === "textarea") { + this.fromTextareaToComposer(shouldParseHtml); + } else { + this.fromComposerToTextarea(shouldParseHtml); + } + }, + + /** + * Initializes interval-based syncing + * also makes sure that on-submit the composer's content is synced with the textarea + * immediately when the form gets submitted + */ + _observe: function() { + var interval, + that = this, + form = this.textarea.element.form, + startInterval = function() { + interval = setInterval(function() { that.fromComposerToTextarea(); }, INTERVAL); + }, + stopInterval = function() { + clearInterval(interval); + interval = null; + }; + + startInterval(); + + if (form) { + // If the textarea is in a form make sure that after onreset and onsubmit the composer + // has the correct state + wysihtml5.dom.observe(form, "submit", function() { + that.sync(true); + }); + wysihtml5.dom.observe(form, "reset", function() { + setTimeout(function() { that.fromTextareaToComposer(); }, 0); + }); + } + + this.editor.observe("change_view", function(view) { + if (view === "composer" && !interval) { + that.fromTextareaToComposer(true); + startInterval(); + } else if (view === "textarea") { + that.fromComposerToTextarea(true); + stopInterval(); + } + }); + + this.editor.observe("destroy:composer", stopInterval); + } + }); +})(wysihtml5); +wysihtml5.views.Textarea = wysihtml5.views.View.extend( + /** @scope wysihtml5.views.Textarea.prototype */ { + name: "textarea", + + constructor: function(parent, textareaElement, config) { + this.base(parent, textareaElement, config); + + this._observe(); + }, + + clear: function() { + this.element.value = ""; + }, + + getValue: function(parse) { + var value = this.isEmpty() ? "" : this.element.value; + if (parse) { + value = this.parent.parse(value); + } + return value; + }, + + setValue: function(html, parse) { + if (parse) { + html = this.parent.parse(html); + } + this.element.value = html; + }, + + hasPlaceholderSet: function() { + var supportsPlaceholder = wysihtml5.browser.supportsPlaceholderAttributeOn(this.element), + placeholderText = this.element.getAttribute("placeholder") || null, + value = this.element.value, + isEmpty = !value; + return (supportsPlaceholder && isEmpty) || (value === placeholderText); + }, + + isEmpty: function() { + return !wysihtml5.lang.string(this.element.value).trim() || this.hasPlaceholderSet(); + }, + + _observe: function() { + var element = this.element, + parent = this.parent, + eventMapping = { + focusin: "focus", + focusout: "blur" + }, + /** + * Calling focus() or blur() on an element doesn't synchronously trigger the attached focus/blur events + * This is the case for focusin and focusout, so let's use them whenever possible, kkthxbai + */ + events = wysihtml5.browser.supportsEvent("focusin") ? ["focusin", "focusout", "change"] : ["focus", "blur", "change"]; + + parent.observe("beforeload", function() { + wysihtml5.dom.observe(element, events, function(event) { + var eventName = eventMapping[event.type] || event.type; + parent.fire(eventName).fire(eventName + ":textarea"); + }); + + wysihtml5.dom.observe(element, ["paste", "drop"], function() { + setTimeout(function() { parent.fire("paste").fire("paste:textarea"); }, 0); + }); + }); + } +});/** + * Toolbar Dialog + * + * @param {Element} link The toolbar link which causes the dialog to show up + * @param {Element} container The dialog container + * + * @example + * <!-- Toolbar link --> + * <a data-wysihtml5-command="insertImage">insert an image</a> + * + * <!-- Dialog --> + * <div data-wysihtml5-dialog="insertImage" style="display: none;"> + * <label> + * URL: <input data-wysihtml5-dialog-field="src" value="http://"> + * </label> + * <label> + * Alternative text: <input data-wysihtml5-dialog-field="alt" value=""> + * </label> + * </div> + * + * <script> + * var dialog = new wysihtml5.toolbar.Dialog( + * document.querySelector("[data-wysihtml5-command='insertImage']"), + * document.querySelector("[data-wysihtml5-dialog='insertImage']") + * ); + * dialog.observe("save", function(attributes) { + * // do something + * }); + * </script> + */ +(function(wysihtml5) { + var dom = wysihtml5.dom, + CLASS_NAME_OPENED = "wysihtml5-command-dialog-opened", + SELECTOR_FORM_ELEMENTS = "input, select, textarea", + SELECTOR_FIELDS = "[data-wysihtml5-dialog-field]", + ATTRIBUTE_FIELDS = "data-wysihtml5-dialog-field"; + + + wysihtml5.toolbar.Dialog = wysihtml5.lang.Dispatcher.extend( + /** @scope wysihtml5.toolbar.Dialog.prototype */ { + constructor: function(link, container) { + this.link = link; + this.container = container; + }, + + _observe: function() { + if (this._observed) { + return; + } + + var that = this, + callbackWrapper = function(event) { + var attributes = that._serialize(); + if (attributes == that.elementToChange) { + that.fire("edit", attributes); + } else { + that.fire("save", attributes); + } + that.hide(); + event.preventDefault(); + event.stopPropagation(); + }; + + dom.observe(that.link, "click", function(event) { + if (dom.hasClass(that.link, CLASS_NAME_OPENED)) { + setTimeout(function() { that.hide(); }, 0); + } + }); + + dom.observe(this.container, "keydown", function(event) { + var keyCode = event.keyCode; + if (keyCode === wysihtml5.ENTER_KEY) { + callbackWrapper(event); + } + if (keyCode === wysihtml5.ESCAPE_KEY) { + that.hide(); + } + }); + + dom.delegate(this.container, "[data-wysihtml5-dialog-action=save]", "click", callbackWrapper); + + dom.delegate(this.container, "[data-wysihtml5-dialog-action=cancel]", "click", function(event) { + that.fire("cancel"); + that.hide(); + event.preventDefault(); + event.stopPropagation(); + }); + + var formElements = this.container.querySelectorAll(SELECTOR_FORM_ELEMENTS), + i = 0, + length = formElements.length, + _clearInterval = function() { clearInterval(that.interval); }; + for (; i<length; i++) { + dom.observe(formElements[i], "change", _clearInterval); + } + + this._observed = true; + }, + + /** + * Grabs all fields in the dialog and puts them in key=>value style in an object which + * then gets returned + */ + _serialize: function() { + var data = this.elementToChange || {}, + fields = this.container.querySelectorAll(SELECTOR_FIELDS), + length = fields.length, + i = 0; + for (; i<length; i++) { + data[fields[i].getAttribute(ATTRIBUTE_FIELDS)] = fields[i].value; + } + return data; + }, + + /** + * Takes the attributes of the "elementToChange" + * and inserts them in their corresponding dialog input fields + * + * Assume the "elementToChange" looks like this: + * <a href="http://www.google.com" target="_blank">foo</a> + * + * and we have the following dialog: + * <input type="text" data-wysihtml5-dialog-field="href" value=""> + * <input type="text" data-wysihtml5-dialog-field="target" value=""> + * + * after calling _interpolate() the dialog will look like this + * <input type="text" data-wysihtml5-dialog-field="href" value="http://www.google.com"> + * <input type="text" data-wysihtml5-dialog-field="target" value="_blank"> + * + * Basically it adopted the attribute values into the corresponding input fields + * + */ + _interpolate: function(avoidHiddenFields) { + var field, + fieldName, + newValue, + focusedElement = document.querySelector(":focus"), + fields = this.container.querySelectorAll(SELECTOR_FIELDS), + length = fields.length, + i = 0; + for (; i<length; i++) { + field = fields[i]; + + // Never change elements where the user is currently typing in + if (field === focusedElement) { + continue; + } + + // Don't update hidden fields + // See https://github.com/xing/wysihtml5/pull/14 + if (avoidHiddenFields && field.type === "hidden") { + continue; + } + + fieldName = field.getAttribute(ATTRIBUTE_FIELDS); + newValue = this.elementToChange ? (this.elementToChange[fieldName] || "") : field.defaultValue; + field.value = newValue; + } + }, + + /** + * Show the dialog element + */ + show: function(elementToChange) { + var that = this, + firstField = this.container.querySelector(SELECTOR_FORM_ELEMENTS); + this.elementToChange = elementToChange; + this._observe(); + this._interpolate(); + if (elementToChange) { + this.interval = setInterval(function() { that._interpolate(true); }, 500); + } + dom.addClass(this.link, CLASS_NAME_OPENED); + this.container.style.display = ""; + this.fire("show"); + if (firstField && !elementToChange) { + try { + firstField.focus(); + } catch(e) {} + } + }, + + /** + * Hide the dialog element + */ + hide: function() { + clearInterval(this.interval); + this.elementToChange = null; + dom.removeClass(this.link, CLASS_NAME_OPENED); + this.container.style.display = "none"; + this.fire("hide"); + } + }); +})(wysihtml5); +/** + * Converts speech-to-text and inserts this into the editor + * As of now (2011/03/25) this only is supported in Chrome >= 11 + * + * Note that it sends the recorded audio to the google speech recognition api: + * http://stackoverflow.com/questions/4361826/does-chrome-have-buil-in-speech-recognition-for-input-type-text-x-webkit-speec + * + * Current HTML5 draft can be found here + * http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html + * + * "Accessing Google Speech API Chrome 11" + * http://mikepultz.com/2011/03/accessing-google-speech-api-chrome-11/ + */ +(function(wysihtml5) { + var dom = wysihtml5.dom; + + var linkStyles = { + position: "relative" + }; + + var wrapperStyles = { + left: 0, + margin: 0, + opacity: 0, + overflow: "hidden", + padding: 0, + position: "absolute", + top: 0, + zIndex: 1 + }; + + var inputStyles = { + cursor: "inherit", + fontSize: "50px", + height: "50px", + marginTop: "-25px", + outline: 0, + padding: 0, + position: "absolute", + right: "-4px", + top: "50%" + }; + + var inputAttributes = { + "x-webkit-speech": "", + "speech": "" + }; + + wysihtml5.toolbar.Speech = function(parent, link) { + var input = document.createElement("input"); + if (!wysihtml5.browser.supportsSpeechApiOn(input)) { + link.style.display = "none"; + return; + } + + var wrapper = document.createElement("div"); + + wysihtml5.lang.object(wrapperStyles).merge({ + width: link.offsetWidth + "px", + height: link.offsetHeight + "px" + }); + + dom.insert(input).into(wrapper); + dom.insert(wrapper).into(link); + + dom.setStyles(inputStyles).on(input); + dom.setAttributes(inputAttributes).on(input) + + dom.setStyles(wrapperStyles).on(wrapper); + dom.setStyles(linkStyles).on(link); + + var eventName = "onwebkitspeechchange" in input ? "webkitspeechchange" : "speechchange"; + dom.observe(input, eventName, function() { + parent.execCommand("insertText", input.value); + input.value = ""; + }); + + dom.observe(input, "click", function(event) { + if (dom.hasClass(link, "wysihtml5-command-disabled")) { + event.preventDefault(); + } + + event.stopPropagation(); + }); + }; +})(wysihtml5);/** + * Toolbar + * + * @param {Object} parent Reference to instance of Editor instance + * @param {Element} container Reference to the toolbar container element + * + * @example + * <div id="toolbar"> + * <a data-wysihtml5-command="createLink">insert link</a> + * <a data-wysihtml5-command="formatBlock" data-wysihtml5-command-value="h1">insert h1</a> + * </div> + * + * <script> + * var toolbar = new wysihtml5.toolbar.Toolbar(editor, document.getElementById("toolbar")); + * </script> + */ +(function(wysihtml5) { + var CLASS_NAME_COMMAND_DISABLED = "wysihtml5-command-disabled", + CLASS_NAME_COMMANDS_DISABLED = "wysihtml5-commands-disabled", + CLASS_NAME_COMMAND_ACTIVE = "wysihtml5-command-active", + CLASS_NAME_ACTION_ACTIVE = "wysihtml5-action-active", + dom = wysihtml5.dom; + + wysihtml5.toolbar.Toolbar = Base.extend( + /** @scope wysihtml5.toolbar.Toolbar.prototype */ { + constructor: function(editor, container) { + this.editor = editor; + this.container = typeof(container) === "string" ? document.getElementById(container) : container; + this.composer = editor.composer; + + this._getLinks("command"); + this._getLinks("action"); + + this._observe(); + this.show(); + + var speechInputLinks = this.container.querySelectorAll("[data-wysihtml5-command=insertSpeech]"), + length = speechInputLinks.length, + i = 0; + for (; i<length; i++) { + new wysihtml5.toolbar.Speech(this, speechInputLinks[i]); + } + }, + + _getLinks: function(type) { + var links = this[type + "Links"] = wysihtml5.lang.array(this.container.querySelectorAll("[data-wysihtml5-" + type + "]")).get(), + length = links.length, + i = 0, + mapping = this[type + "Mapping"] = {}, + link, + group, + name, + value, + dialog; + for (; i<length; i++) { + link = links[i]; + name = link.getAttribute("data-wysihtml5-" + type); + value = link.getAttribute("data-wysihtml5-" + type + "-value"); + group = this.container.querySelector("[data-wysihtml5-" + type + "-group='" + name + "']"); + dialog = this._getDialog(link, name); + + mapping[name + ":" + value] = { + link: link, + group: group, + name: name, + value: value, + dialog: dialog, + state: false + }; + } + }, + + _getDialog: function(link, command) { + var that = this, + dialogElement = this.container.querySelector("[data-wysihtml5-dialog='" + command + "']"), + dialog, + caretBookmark; + + if (dialogElement) { + dialog = new wysihtml5.toolbar.Dialog(link, dialogElement); + + dialog.observe("show", function() { + caretBookmark = that.composer.selection.getBookmark(); + + that.editor.fire("show:dialog", { command: command, dialogContainer: dialogElement, commandLink: link }); + }); + + dialog.observe("save", function(attributes) { + if (caretBookmark) { + that.composer.selection.setBookmark(caretBookmark); + } + that._execCommand(command, attributes); + + that.editor.fire("save:dialog", { command: command, dialogContainer: dialogElement, commandLink: link }); + }); + + dialog.observe("cancel", function() { + that.editor.focus(false); + that.editor.fire("cancel:dialog", { command: command, dialogContainer: dialogElement, commandLink: link }); + }); + } + return dialog; + }, + + /** + * @example + * var toolbar = new wysihtml5.Toolbar(); + * // Insert a <blockquote> element or wrap current selection in <blockquote> + * toolbar.execCommand("formatBlock", "blockquote"); + */ + execCommand: function(command, commandValue) { + if (this.commandsDisabled) { + return; + } + + var commandObj = this.commandMapping[command + ":" + commandValue]; + + // Show dialog when available + if (commandObj && commandObj.dialog && !commandObj.state) { + commandObj.dialog.show(); + } else { + this._execCommand(command, commandValue); + } + }, + + _execCommand: function(command, commandValue) { + // Make sure that composer is focussed (false => don't move caret to the end) + this.editor.focus(false); + + this.composer.commands.exec(command, commandValue); + this._updateLinkStates(); + }, + + execAction: function(action) { + var editor = this.editor; + switch(action) { + case "change_view": + if (editor.currentView === editor.textarea) { + editor.fire("change_view", "composer"); + } else { + editor.fire("change_view", "textarea"); + } + break; + } + }, + + _observe: function() { + var that = this, + editor = this.editor, + container = this.container, + links = this.commandLinks.concat(this.actionLinks), + length = links.length, + i = 0; + + for (; i<length; i++) { + // 'javascript:;' and unselectable=on Needed for IE, but done in all browsers to make sure that all get the same css applied + // (you know, a:link { ... } doesn't match anchors with missing href attribute) + dom.setAttributes({ + href: "javascript:;", + unselectable: "on" + }).on(links[i]); + } + + // Needed for opera + dom.delegate(container, "[data-wysihtml5-command]", "mousedown", function(event) { event.preventDefault(); }); + + dom.delegate(container, "[data-wysihtml5-command]", "click", function(event) { + var link = this, + command = link.getAttribute("data-wysihtml5-command"), + commandValue = link.getAttribute("data-wysihtml5-command-value"); + that.execCommand(command, commandValue); + event.preventDefault(); + }); + + dom.delegate(container, "[data-wysihtml5-action]", "click", function(event) { + var action = this.getAttribute("data-wysihtml5-action"); + that.execAction(action); + event.preventDefault(); + }); + + editor.observe("focus:composer", function() { + that.bookmark = null; + clearInterval(that.interval); + that.interval = setInterval(function() { that._updateLinkStates(); }, 500); + }); + + editor.observe("blur:composer", function() { + clearInterval(that.interval); + }); + + editor.observe("destroy:composer", function() { + clearInterval(that.interval); + }); + + editor.observe("change_view", function(currentView) { + // Set timeout needed in order to let the blur event fire first + setTimeout(function() { + that.commandsDisabled = (currentView !== "composer"); + that._updateLinkStates(); + if (that.commandsDisabled) { + dom.addClass(container, CLASS_NAME_COMMANDS_DISABLED); + } else { + dom.removeClass(container, CLASS_NAME_COMMANDS_DISABLED); + } + }, 0); + }); + }, + + _updateLinkStates: function() { + var element = this.composer.element, + commandMapping = this.commandMapping, + actionMapping = this.actionMapping, + i, + state, + action, + command; + // every millisecond counts... this is executed quite often + for (i in commandMapping) { + command = commandMapping[i]; + if (this.commandsDisabled) { + state = false; + dom.removeClass(command.link, CLASS_NAME_COMMAND_ACTIVE); + if (command.group) { + dom.removeClass(command.group, CLASS_NAME_COMMAND_ACTIVE); + } + if (command.dialog) { + command.dialog.hide(); + } + } else { + state = this.composer.commands.state(command.name, command.value); + if (wysihtml5.lang.object(state).isArray()) { + // Grab first and only object/element in state array, otherwise convert state into boolean + // to avoid showing a dialog for multiple selected elements which may have different attributes + // eg. when two links with different href are selected, the state will be an array consisting of both link elements + // but the dialog interface can only update one + state = state.length === 1 ? state[0] : true; + } + dom.removeClass(command.link, CLASS_NAME_COMMAND_DISABLED); + if (command.group) { + dom.removeClass(command.group, CLASS_NAME_COMMAND_DISABLED); + } + } + + if (command.state === state) { + continue; + } + + command.state = state; + if (state) { + dom.addClass(command.link, CLASS_NAME_COMMAND_ACTIVE); + if (command.group) { + dom.addClass(command.group, CLASS_NAME_COMMAND_ACTIVE); + } + if (command.dialog) { + if (typeof(state) === "object") { + command.dialog.show(state); + } else { + command.dialog.hide(); + } + } + } else { + dom.removeClass(command.link, CLASS_NAME_COMMAND_ACTIVE); + if (command.group) { + dom.removeClass(command.group, CLASS_NAME_COMMAND_ACTIVE); + } + if (command.dialog) { + command.dialog.hide(); + } + } + } + + for (i in actionMapping) { + action = actionMapping[i]; + + if (action.name === "change_view") { + action.state = this.editor.currentView === this.editor.textarea; + if (action.state) { + dom.addClass(action.link, CLASS_NAME_ACTION_ACTIVE); + } else { + dom.removeClass(action.link, CLASS_NAME_ACTION_ACTIVE); + } + } + } + }, + + show: function() { + this.container.style.display = ""; + }, + + hide: function() { + this.container.style.display = "none"; + } + }); + +})(wysihtml5); +/** + * WYSIHTML5 Editor + * + * @param {Element} textareaElement Reference to the textarea which should be turned into a rich text interface + * @param {Object} [config] See defaultConfig object below for explanation of each individual config option + * + * @events + * load + * beforeload (for internal use only) + * focus + * focus:composer + * focus:textarea + * blur + * blur:composer + * blur:textarea + * change + * change:composer + * change:textarea + * paste + * paste:composer + * paste:textarea + * newword:composer + * destroy:composer + * undo:composer + * redo:composer + * beforecommand:composer + * aftercommand:composer + * change_view + */ +(function(wysihtml5) { + var undef; + + var defaultConfig = { + // Give the editor a name, the name will also be set as class name on the iframe and on the iframe's body + name: undef, + // Whether the editor should look like the textarea (by adopting styles) + style: true, + // Id of the toolbar element, pass falsey value if you don't want any toolbar logic + toolbar: undef, + // Whether urls, entered by the user should automatically become clickable-links + autoLink: true, + // Object which includes parser rules to apply when html gets inserted via copy & paste + // See parser_rules/*.js for examples + parserRules: { tags: { br: {}, span: {}, div: {}, p: {} }, classes: {} }, + // Parser method to use when the user inserts content via copy & paste + parser: wysihtml5.dom.parse, + // Class name which should be set on the contentEditable element in the created sandbox iframe, can be styled via the 'stylesheets' option + composerClassName: "wysihtml5-editor", + // Class name to add to the body when the wysihtml5 editor is supported + bodyClassName: "wysihtml5-supported", + // Array (or single string) of stylesheet urls to be loaded in the editor's iframe + stylesheets: [], + // Placeholder text to use, defaults to the placeholder attribute on the textarea element + placeholderText: undef, + // Whether the composer should allow the user to manually resize images, tables etc. + allowObjectResizing: true, + // Whether the rich text editor should be rendered on touch devices (wysihtml5 >= 0.3.0 comes with basic support for iOS 5) + supportTouchDevices: true + }; + + wysihtml5.Editor = wysihtml5.lang.Dispatcher.extend( + /** @scope wysihtml5.Editor.prototype */ { + constructor: function(textareaElement, config) { + this.textareaElement = typeof(textareaElement) === "string" ? document.getElementById(textareaElement) : textareaElement; + this.config = wysihtml5.lang.object({}).merge(defaultConfig).merge(config).get(); + this.textarea = new wysihtml5.views.Textarea(this, this.textareaElement, this.config); + this.currentView = this.textarea; + this._isCompatible = wysihtml5.browser.supported(); + + // Sort out unsupported/unwanted browsers here + if (!this._isCompatible || (!this.config.supportTouchDevices && wysihtml5.browser.isTouchDevice())) { + var that = this; + setTimeout(function() { that.fire("beforeload").fire("load"); }, 0); + return; + } + + // Add class name to body, to indicate that the editor is supported + wysihtml5.dom.addClass(document.body, this.config.bodyClassName); + + this.composer = new wysihtml5.views.Composer(this, this.textareaElement, this.config); + this.currentView = this.composer; + + if (typeof(this.config.parser) === "function") { + this._initParser(); + } + + this.observe("beforeload", function() { + this.synchronizer = new wysihtml5.views.Synchronizer(this, this.textarea, this.composer); + if (this.config.toolbar) { + this.toolbar = new wysihtml5.toolbar.Toolbar(this, this.config.toolbar); + } + }); + + try { + console.log("Heya! This page is using wysihtml5 for rich text editing. Check out https://github.com/xing/wysihtml5"); + } catch(e) {} + }, + + isCompatible: function() { + return this._isCompatible; + }, + + clear: function() { + this.currentView.clear(); + return this; + }, + + getValue: function(parse) { + return this.currentView.getValue(parse); + }, + + setValue: function(html, parse) { + if (!html) { + return this.clear(); + } + this.currentView.setValue(html, parse); + return this; + }, + + focus: function(setToEnd) { + this.currentView.focus(setToEnd); + return this; + }, + + /** + * Deactivate editor (make it readonly) + */ + disable: function() { + this.currentView.disable(); + return this; + }, + + /** + * Activate editor + */ + enable: function() { + this.currentView.enable(); + return this; + }, + + isEmpty: function() { + return this.currentView.isEmpty(); + }, + + hasPlaceholderSet: function() { + return this.currentView.hasPlaceholderSet(); + }, + + parse: function(htmlOrElement) { + var returnValue = this.config.parser(htmlOrElement, this.config.parserRules, this.composer.sandbox.getDocument(), true); + if (typeof(htmlOrElement) === "object") { + wysihtml5.quirks.redraw(htmlOrElement); + } + return returnValue; + }, + + /** + * Prepare html parser logic + * - Observes for paste and drop + */ + _initParser: function() { + this.observe("paste:composer", function() { + var keepScrollPosition = true, + that = this; + that.composer.selection.executeAndRestore(function() { + wysihtml5.quirks.cleanPastedHTML(that.composer.element); + that.parse(that.composer.element); + }, keepScrollPosition); + }); + + this.observe("paste:textarea", function() { + var value = this.textarea.getValue(), + newValue; + newValue = this.parse(value); + this.textarea.setValue(newValue); + }); + } + }); +})(wysihtml5); diff --git a/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysihtml5-0.3.0.min.js b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysihtml5-0.3.0.min.js new file mode 100755 index 0000000..663816a --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysihtml5-0.3.0.min.js @@ -0,0 +1,261 @@ +/* + 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) + + 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 +*/ +var wysihtml5={version:"0.3.0",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}; +window.rangy=function(){function b(a,b){var c=typeof a[b];return c==k||!!(c==h&&a[b])||"unknown"==c}function c(a,b){return!!(typeof a[b]==h&&a[b])}function a(a,b){return typeof a[b]!=j}function d(a){return function(b,c){for(var d=c.length;d--;)if(!a(b,c[d]))return!1;return!0}}function e(a){return a&&m(a,r)&&x(a,q)}function f(a){window.alert("Rangy not supported in your browser. Reason: "+a);o.initialized=!0;o.supported=!1}function g(){if(!o.initialized){var a,d=!1,h=!1;b(document,"createRange")&& +(a=document.createRange(),m(a,p)&&x(a,n)&&(d=!0),a.detach());if((a=c(document,"body")?document.body:document.getElementsByTagName("body")[0])&&b(a,"createTextRange"))a=a.createTextRange(),e(a)&&(h=!0);!d&&!h&&f("Neither Range nor TextRange are implemented");o.initialized=!0;o.features={implementsDomRange:d,implementsTextRange:h};d=w.concat(z);h=0;for(a=d.length;h<a;++h)try{d[h](o)}catch(j){c(window,"console")&&b(window.console,"log")&&window.console.log("Init listener threw an exception. Continuing.", +j)}}}function i(a){this.name=a;this.supported=this.initialized=!1}var h="object",k="function",j="undefined",n="startContainer startOffset endContainer endOffset collapsed commonAncestorContainer START_TO_START START_TO_END END_TO_START END_TO_END".split(" "),p="setStart setStartBefore setStartAfter setEnd setEndBefore setEndAfter collapse selectNode selectNodeContents compareBoundaryPoints deleteContents extractContents cloneContents insertNode surroundContents cloneRange toString detach".split(" "), +q="boundingHeight boundingLeft boundingTop boundingWidth htmlText text".split(" "),r="collapse compareEndPoints duplicate getBookmark moveToBookmark moveToElementText parentElement pasteHTML select setEndPoint getBoundingClientRect".split(" "),m=d(b),s=d(c),x=d(a),o={version:"1.2.2",initialized:!1,supported:!0,util:{isHostMethod:b,isHostObject:c,isHostProperty:a,areHostMethods:m,areHostObjects:s,areHostProperties:x,isTextRange:e},features:{},modules:{},config:{alertOnWarn:!1,preferTextRange:!1}}; +o.fail=f;o.warn=function(a){a="Rangy warning: "+a;o.config.alertOnWarn?window.alert(a):typeof window.console!=j&&typeof window.console.log!=j&&window.console.log(a)};({}).hasOwnProperty?o.util.extend=function(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}:f("hasOwnProperty not supported");var z=[],w=[];o.init=g;o.addInitListener=function(a){o.initialized?a(o):z.push(a)};var y=[];o.addCreateMissingNativeApiListener=function(a){y.push(a)};o.createMissingNativeApi=function(a){a=a||window;g(); +for(var b=0,c=y.length;b<c;++b)y[b](a)};i.prototype.fail=function(a){this.initialized=!0;this.supported=!1;throw Error("Module '"+this.name+"' failed to load: "+a);};i.prototype.warn=function(a){o.warn("Module "+this.name+": "+a)};i.prototype.createError=function(a){return Error("Error in Rangy "+this.name+" module: "+a)};o.createModule=function(a,b){var c=new i(a);o.modules[a]=c;w.push(function(a){b(a,c);c.initialized=!0;c.supported=!0})};o.requireModules=function(a){for(var b=0,c=a.length,d,h;b< +c;++b){h=a[b];d=o.modules[h];if(!d||!(d instanceof i))throw Error("Module '"+h+"' not found");if(!d.supported)throw Error("Module '"+h+"' not supported");}};var A=!1,s=function(){A||(A=!0,o.initialized||g())};if(typeof window==j)f("No window found");else if(typeof document==j)f("No document found");else return b(document,"addEventListener")&&document.addEventListener("DOMContentLoaded",s,!1),b(window,"addEventListener")?window.addEventListener("load",s,!1):b(window,"attachEvent")?window.attachEvent("onload", +s):f("Window does not have required addEventListener or attachEvent method"),o}(); +rangy.createModule("DomUtil",function(b,c){function a(a){for(var b=0;a=a.previousSibling;)b++;return b}function d(a,b){var c=[],d;for(d=a;d;d=d.parentNode)c.push(d);for(d=b;d;d=d.parentNode)if(m(c,d))return d;return null}function e(a,b,c){for(c=c?a:a.parentNode;c;){a=c.parentNode;if(a===b)return c;c=a}return null}function f(a){a=a.nodeType;return 3==a||4==a||8==a}function g(a,b){var c=b.nextSibling,d=b.parentNode;c?d.insertBefore(a,c):d.appendChild(a);return a}function i(a){if(9==a.nodeType)return a; +if(typeof a.ownerDocument!=p)return a.ownerDocument;if(typeof a.document!=p)return a.document;if(a.parentNode)return i(a.parentNode);throw Error("getDocument: no document found for node");}function h(a){return!a?"[No node]":f(a)?'"'+a.data+'"':1==a.nodeType?"<"+a.nodeName+(a.id?' id="'+a.id+'"':"")+">["+a.childNodes.length+"]":a.nodeName}function k(a){this._next=this.root=a}function j(a,b){this.node=a;this.offset=b}function n(a){this.code=this[a];this.codeName=a;this.message="DOMException: "+this.codeName} +var p="undefined",q=b.util;q.areHostMethods(document,["createDocumentFragment","createElement","createTextNode"])||c.fail("document missing a Node creation method");q.isHostMethod(document,"getElementsByTagName")||c.fail("document missing getElementsByTagName method");var r=document.createElement("div");q.areHostMethods(r,["insertBefore","appendChild","cloneNode"])||c.fail("Incomplete Element implementation");q.isHostProperty(r,"innerHTML")||c.fail("Element is missing innerHTML property");r=document.createTextNode("test"); +q.areHostMethods(r,["splitText","deleteData","insertData","appendData","cloneNode"])||c.fail("Incomplete Text Node implementation");var m=function(a,b){for(var c=a.length;c--;)if(a[c]===b)return!0;return!1};k.prototype={_current:null,hasNext:function(){return!!this._next},next:function(){var a=this._current=this._next,b;if(this._current){b=a.firstChild;if(!b)for(b=null;a!==this.root&&!(b=a.nextSibling);)a=a.parentNode;this._next=b}return this._current},detach:function(){this._current=this._next=this.root= +null}};j.prototype={equals:function(a){return this.node===a.node&this.offset==a.offset},inspect:function(){return"[DomPosition("+h(this.node)+":"+this.offset+")]"}};n.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};n.prototype.toString=function(){return this.message};b.dom={arrayContains:m,isHtmlNamespace:function(a){var b;return typeof a.namespaceURI==p||null===(b=a.namespaceURI)||"http://www.w3.org/1999/xhtml"== +b},parentElement:function(a){a=a.parentNode;return 1==a.nodeType?a:null},getNodeIndex:a,getNodeLength:function(a){var b;return f(a)?a.length:(b=a.childNodes)?b.length:0},getCommonAncestor:d,isAncestorOf:function(a,b,c){for(b=c?b:b.parentNode;b;){if(b===a)return!0;b=b.parentNode}return!1},getClosestAncestorIn:e,isCharacterDataNode:f,insertAfter:g,splitDataNode:function(a,b){var c=a.cloneNode(!1);c.deleteData(0,b);a.deleteData(b,a.length-b);g(c,a);return c},getDocument:i,getWindow:function(a){a=i(a); +if(typeof a.defaultView!=p)return a.defaultView;if(typeof a.parentWindow!=p)return a.parentWindow;throw Error("Cannot get a window object for node");},getIframeWindow:function(a){if(typeof a.contentWindow!=p)return a.contentWindow;if(typeof a.contentDocument!=p)return a.contentDocument.defaultView;throw Error("getIframeWindow: No Window object found for iframe element");},getIframeDocument:function(a){if(typeof a.contentDocument!=p)return a.contentDocument;if(typeof a.contentWindow!=p)return a.contentWindow.document; +throw Error("getIframeWindow: No Document object found for iframe element");},getBody:function(a){return q.isHostObject(a,"body")?a.body:a.getElementsByTagName("body")[0]},getRootContainer:function(a){for(var b;b=a.parentNode;)a=b;return a},comparePoints:function(b,c,h,j){var k;if(b==h)return c===j?0:c<j?-1:1;if(k=e(h,b,!0))return c<=a(k)?-1:1;if(k=e(b,h,!0))return a(k)<j?-1:1;c=d(b,h);b=b===c?c:e(b,c,!0);h=h===c?c:e(h,c,!0);if(b===h)throw Error("comparePoints got to case 4 and childA and childB are the same!"); +for(c=c.firstChild;c;){if(c===b)return-1;if(c===h)return 1;c=c.nextSibling}throw Error("Should not be here!");},inspectNode:h,fragmentFromNodeChildren:function(a){for(var b=i(a).createDocumentFragment(),c;c=a.firstChild;)b.appendChild(c);return b},createIterator:function(a){return new k(a)},DomPosition:j};b.DOMException=n}); +rangy.createModule("DomRange",function(b){function c(a,b){return 3!=a.nodeType&&(l.isAncestorOf(a,b.startContainer,!0)||l.isAncestorOf(a,b.endContainer,!0))}function a(a){return l.getDocument(a.startContainer)}function d(a,b,c){if(b=a._listeners[b])for(var d=0,h=b.length;d<h;++d)b[d].call(a,{target:a,args:c})}function e(a){return new u(a.parentNode,l.getNodeIndex(a))}function f(a){return new u(a.parentNode,l.getNodeIndex(a)+1)}function g(a,b,c){var d=11==a.nodeType?a.firstChild:a;l.isCharacterDataNode(b)? +c==b.length?l.insertAfter(a,b):b.parentNode.insertBefore(a,0==c?b:l.splitDataNode(b,c)):c>=b.childNodes.length?b.appendChild(a):b.insertBefore(a,b.childNodes[c]);return d}function i(b){for(var c,d,h=a(b.range).createDocumentFragment();d=b.next();){c=b.isPartiallySelectedSubtree();d=d.cloneNode(!c);c&&(c=b.getSubtreeIterator(),d.appendChild(i(c)),c.detach(!0));if(10==d.nodeType)throw new B("HIERARCHY_REQUEST_ERR");h.appendChild(d)}return h}function h(a,b,c){for(var d,e,c=c||{stop:!1};d=a.next();)if(a.isPartiallySelectedSubtree())if(!1=== +b(d)){c.stop=!0;break}else{if(d=a.getSubtreeIterator(),h(d,b,c),d.detach(!0),c.stop)break}else for(d=l.createIterator(d);e=d.next();)if(!1===b(e)){c.stop=!0;return}}function k(a){for(var b;a.next();)a.isPartiallySelectedSubtree()?(b=a.getSubtreeIterator(),k(b),b.detach(!0)):a.remove()}function j(b){for(var c,d=a(b.range).createDocumentFragment(),h;c=b.next();){b.isPartiallySelectedSubtree()?(c=c.cloneNode(!1),h=b.getSubtreeIterator(),c.appendChild(j(h)),h.detach(!0)):b.remove();if(10==c.nodeType)throw new B("HIERARCHY_REQUEST_ERR"); +d.appendChild(c)}return d}function n(a,b,c){var d=!(!b||!b.length),e,j=!!c;d&&(e=RegExp("^("+b.join("|")+")$"));var k=[];h(new q(a,!1),function(a){(!d||e.test(a.nodeType))&&(!j||c(a))&&k.push(a)});return k}function p(a){return"["+("undefined"==typeof a.getName?"Range":a.getName())+"("+l.inspectNode(a.startContainer)+":"+a.startOffset+", "+l.inspectNode(a.endContainer)+":"+a.endOffset+")]"}function q(a,b){this.range=a;this.clonePartiallySelectedTextNodes=b;if(!a.collapsed){this.sc=a.startContainer; +this.so=a.startOffset;this.ec=a.endContainer;this.eo=a.endOffset;var c=a.commonAncestorContainer;this.sc===this.ec&&l.isCharacterDataNode(this.sc)?(this.isSingleCharacterDataNode=!0,this._first=this._last=this._next=this.sc):(this._first=this._next=this.sc===c&&!l.isCharacterDataNode(this.sc)?this.sc.childNodes[this.so]:l.getClosestAncestorIn(this.sc,c,!0),this._last=this.ec===c&&!l.isCharacterDataNode(this.ec)?this.ec.childNodes[this.eo-1]:l.getClosestAncestorIn(this.ec,c,!0))}}function r(a){this.code= +this[a];this.codeName=a;this.message="RangeException: "+this.codeName}function m(a,b,c){this.nodes=n(a,b,c);this._next=this.nodes[0];this._position=0}function s(a){return function(b,c){for(var d,h=c?b:b.parentNode;h;){d=h.nodeType;if(l.arrayContains(a,d))return h;h=h.parentNode}return null}}function x(a,b){if($(a,b))throw new r("INVALID_NODE_TYPE_ERR");}function o(a){if(!a.startContainer)throw new B("INVALID_STATE_ERR");}function z(a,b){if(!l.arrayContains(b,a.nodeType))throw new r("INVALID_NODE_TYPE_ERR"); +}function w(a,b){if(0>b||b>(l.isCharacterDataNode(a)?a.length:a.childNodes.length))throw new B("INDEX_SIZE_ERR");}function y(a,b){if(O(a,!0)!==O(b,!0))throw new B("WRONG_DOCUMENT_ERR");}function A(a){if(aa(a,!0))throw new B("NO_MODIFICATION_ALLOWED_ERR");}function t(a,b){if(!a)throw new B(b);}function v(a){o(a);if(!l.arrayContains(G,a.startContainer.nodeType)&&!O(a.startContainer,!0)||!l.arrayContains(G,a.endContainer.nodeType)&&!O(a.endContainer,!0)||!(a.startOffset<=(l.isCharacterDataNode(a.startContainer)? +a.startContainer.length:a.startContainer.childNodes.length))||!(a.endOffset<=(l.isCharacterDataNode(a.endContainer)?a.endContainer.length:a.endContainer.childNodes.length)))throw Error("Range error: Range is no longer valid after DOM mutation ("+a.inspect()+")");}function D(){}function K(a){a.START_TO_START=Q;a.START_TO_END=U;a.END_TO_END=ba;a.END_TO_START=V;a.NODE_BEFORE=W;a.NODE_AFTER=X;a.NODE_BEFORE_AND_AFTER=Y;a.NODE_INSIDE=R}function F(a){K(a);K(a.prototype)}function E(a,b){return function(){v(this); +var c=this.startContainer,d=this.startOffset,e=this.commonAncestorContainer,j=new q(this,!0);c!==e&&(c=l.getClosestAncestorIn(c,e,!0),d=f(c),c=d.node,d=d.offset);h(j,A);j.reset();e=a(j);j.detach();b(this,c,d,c,d);return e}}function I(a,d,h){function g(a,b){return function(c){o(this);z(c,L);z(M(c),G);c=(a?e:f)(c);(b?i:n)(this,c.node,c.offset)}}function i(a,b,c){var h=a.endContainer,e=a.endOffset;if(b!==a.startContainer||c!==a.startOffset){if(M(b)!=M(h)||1==l.comparePoints(b,c,h,e))h=b,e=c;d(a,b,c, +h,e)}}function n(a,b,c){var h=a.startContainer,e=a.startOffset;if(b!==a.endContainer||c!==a.endOffset){if(M(b)!=M(h)||-1==l.comparePoints(b,c,h,e))h=b,e=c;d(a,h,e,b,c)}}a.prototype=new D;b.util.extend(a.prototype,{setStart:function(a,b){o(this);x(a,!0);w(a,b);i(this,a,b)},setEnd:function(a,b){o(this);x(a,!0);w(a,b);n(this,a,b)},setStartBefore:g(!0,!0),setStartAfter:g(!1,!0),setEndBefore:g(!0,!1),setEndAfter:g(!1,!1),collapse:function(a){v(this);a?d(this,this.startContainer,this.startOffset,this.startContainer, +this.startOffset):d(this,this.endContainer,this.endOffset,this.endContainer,this.endOffset)},selectNodeContents:function(a){o(this);x(a,!0);d(this,a,0,a,l.getNodeLength(a))},selectNode:function(a){o(this);x(a,!1);z(a,L);var b=e(a),a=f(a);d(this,b.node,b.offset,a.node,a.offset)},extractContents:E(j,d),deleteContents:E(k,d),canSurroundContents:function(){v(this);A(this.startContainer);A(this.endContainer);var a=new q(this,!0),b=a._first&&c(a._first,this)||a._last&&c(a._last,this);a.detach();return!b}, +detach:function(){h(this)},splitBoundaries:function(){v(this);var a=this.startContainer,b=this.startOffset,c=this.endContainer,h=this.endOffset,e=a===c;l.isCharacterDataNode(c)&&(0<h&&h<c.length)&&l.splitDataNode(c,h);l.isCharacterDataNode(a)&&(0<b&&b<a.length)&&(a=l.splitDataNode(a,b),e?(h-=b,c=a):c==a.parentNode&&h>=l.getNodeIndex(a)&&h++,b=0);d(this,a,b,c,h)},normalizeBoundaries:function(){v(this);var a=this.startContainer,b=this.startOffset,c=this.endContainer,h=this.endOffset,e=function(a){var b= +a.nextSibling;b&&b.nodeType==a.nodeType&&(c=a,h=a.length,a.appendData(b.data),b.parentNode.removeChild(b))},j=function(d){var e=d.previousSibling;if(e&&e.nodeType==d.nodeType){a=d;var j=d.length;b=e.length;d.insertData(0,e.data);e.parentNode.removeChild(e);a==c?(h+=b,c=a):c==d.parentNode&&(e=l.getNodeIndex(d),h==e?(c=d,h=j):h>e&&h--)}},k=!0;l.isCharacterDataNode(c)?c.length==h&&e(c):(0<h&&(k=c.childNodes[h-1])&&l.isCharacterDataNode(k)&&e(k),k=!this.collapsed);k?l.isCharacterDataNode(a)?0==b&&j(a): +b<a.childNodes.length&&(e=a.childNodes[b])&&l.isCharacterDataNode(e)&&j(e):(a=c,b=h);d(this,a,b,c,h)},collapseToPoint:function(a,b){o(this);x(a,!0);w(a,b);(a!==this.startContainer||b!==this.startOffset||a!==this.endContainer||b!==this.endOffset)&&d(this,a,b,a,b)}});F(a)}function N(a){a.collapsed=a.startContainer===a.endContainer&&a.startOffset===a.endOffset;a.commonAncestorContainer=a.collapsed?a.startContainer:l.getCommonAncestor(a.startContainer,a.endContainer)}function J(a,b,c,h,e){var j=a.startContainer!== +b||a.startOffset!==c,k=a.endContainer!==h||a.endOffset!==e;a.startContainer=b;a.startOffset=c;a.endContainer=h;a.endOffset=e;N(a);d(a,"boundarychange",{startMoved:j,endMoved:k})}function C(a){this.startContainer=a;this.startOffset=0;this.endContainer=a;this.endOffset=0;this._listeners={boundarychange:[],detach:[]};N(this)}b.requireModules(["DomUtil"]);var l=b.dom,u=l.DomPosition,B=b.DOMException;q.prototype={_current:null,_next:null,_first:null,_last:null,isSingleCharacterDataNode:!1,reset:function(){this._current= +null;this._next=this._first},hasNext:function(){return!!this._next},next:function(){var a=this._current=this._next;a&&(this._next=a!==this._last?a.nextSibling:null,l.isCharacterDataNode(a)&&this.clonePartiallySelectedTextNodes&&(a===this.ec&&(a=a.cloneNode(!0)).deleteData(this.eo,a.length-this.eo),this._current===this.sc&&(a=a.cloneNode(!0)).deleteData(0,this.so)));return a},remove:function(){var a=this._current,b,c;l.isCharacterDataNode(a)&&(a===this.sc||a===this.ec)?(b=a===this.sc?this.so:0,c=a=== +this.ec?this.eo:a.length,b!=c&&a.deleteData(b,c-b)):a.parentNode&&a.parentNode.removeChild(a)},isPartiallySelectedSubtree:function(){return c(this._current,this.range)},getSubtreeIterator:function(){var b;if(this.isSingleCharacterDataNode)b=this.range.cloneRange(),b.collapse();else{b=new C(a(this.range));var c=this._current,d=c,h=0,e=c,j=l.getNodeLength(c);l.isAncestorOf(c,this.sc,!0)&&(d=this.sc,h=this.so);l.isAncestorOf(c,this.ec,!0)&&(e=this.ec,j=this.eo);J(b,d,h,e,j)}return new q(b,this.clonePartiallySelectedTextNodes)}, +detach:function(a){a&&this.range.detach();this.range=this._current=this._next=this._first=this._last=this.sc=this.so=this.ec=this.eo=null}};r.prototype={BAD_BOUNDARYPOINTS_ERR:1,INVALID_NODE_TYPE_ERR:2};r.prototype.toString=function(){return this.message};m.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 L=[1,3,4,5, +7,8,10],G=[2,9,11],P=[1,3,4,5,7,8,10,11],H=[1,3,4,5,7,8],M=l.getRootContainer,O=s([9,11]),aa=s([5,6,10,12]),$=s([6,10,12]),Z=document.createElement("style"),S=!1;try{Z.innerHTML="<b>x</b>",S=3==Z.firstChild.nodeType}catch(ca){}b.features.htmlParsingConforms=S;var T="startContainer startOffset endContainer endOffset collapsed commonAncestorContainer".split(" "),Q=0,U=1,ba=2,V=3,W=0,X=1,Y=2,R=3;D.prototype={attachListener:function(a,b){this._listeners[a].push(b)},compareBoundaryPoints:function(a,b){v(this); +y(this.startContainer,b.startContainer);var c=a==V||a==Q?"start":"end",d=a==U||a==Q?"start":"end";return l.comparePoints(this[c+"Container"],this[c+"Offset"],b[d+"Container"],b[d+"Offset"])},insertNode:function(a){v(this);z(a,P);A(this.startContainer);if(l.isAncestorOf(a,this.startContainer,!0))throw new B("HIERARCHY_REQUEST_ERR");this.setStartBefore(g(a,this.startContainer,this.startOffset))},cloneContents:function(){v(this);var b,c;if(this.collapsed)return a(this).createDocumentFragment();if(this.startContainer=== +this.endContainer&&l.isCharacterDataNode(this.startContainer))return b=this.startContainer.cloneNode(!0),b.data=b.data.slice(this.startOffset,this.endOffset),c=a(this).createDocumentFragment(),c.appendChild(b),c;c=new q(this,!0);b=i(c);c.detach();return b},canSurroundContents:function(){v(this);A(this.startContainer);A(this.endContainer);var a=new q(this,!0),b=a._first&&c(a._first,this)||a._last&&c(a._last,this);a.detach();return!b},surroundContents:function(a){z(a,H);if(!this.canSurroundContents())throw new r("BAD_BOUNDARYPOINTS_ERR"); +var b=this.extractContents();if(a.hasChildNodes())for(;a.lastChild;)a.removeChild(a.lastChild);g(a,this.startContainer,this.startOffset);a.appendChild(b);this.selectNode(a)},cloneRange:function(){v(this);for(var b=new C(a(this)),c=T.length,d;c--;)d=T[c],b[d]=this[d];return b},toString:function(){v(this);var a=this.startContainer;if(a===this.endContainer&&l.isCharacterDataNode(a))return 3==a.nodeType||4==a.nodeType?a.data.slice(this.startOffset,this.endOffset):"";var b=[],a=new q(this,!0);h(a,function(a){(3== +a.nodeType||4==a.nodeType)&&b.push(a.data)});a.detach();return b.join("")},compareNode:function(a){v(this);var b=a.parentNode,c=l.getNodeIndex(a);if(!b)throw new B("NOT_FOUND_ERR");a=this.comparePoint(b,c);b=this.comparePoint(b,c+1);return 0>a?0<b?Y:W:0<b?X:R},comparePoint:function(a,b){v(this);t(a,"HIERARCHY_REQUEST_ERR");y(a,this.startContainer);return 0>l.comparePoints(a,b,this.startContainer,this.startOffset)?-1:0<l.comparePoints(a,b,this.endContainer,this.endOffset)?1:0},createContextualFragment:S? +function(a){var b=this.startContainer,c=l.getDocument(b);if(!b)throw new B("INVALID_STATE_ERR");var d=null;1==b.nodeType?d=b:l.isCharacterDataNode(b)&&(d=l.parentElement(b));d=null===d||"HTML"==d.nodeName&&l.isHtmlNamespace(l.getDocument(d).documentElement)&&l.isHtmlNamespace(d)?c.createElement("body"):d.cloneNode(!1);d.innerHTML=a;return l.fragmentFromNodeChildren(d)}:function(b){o(this);var c=a(this).createElement("body");c.innerHTML=b;return l.fragmentFromNodeChildren(c)},toHtml:function(){v(this); +var b=a(this).createElement("div");b.appendChild(this.cloneContents());return b.innerHTML},intersectsNode:function(b,c){v(this);t(b,"NOT_FOUND_ERR");if(l.getDocument(b)!==a(this))return!1;var d=b.parentNode,h=l.getNodeIndex(b);t(d,"NOT_FOUND_ERR");var e=l.comparePoints(d,h,this.endContainer,this.endOffset),d=l.comparePoints(d,h+1,this.startContainer,this.startOffset);return c?0>=e&&0<=d:0>e&&0<d},isPointInRange:function(a,b){v(this);t(a,"HIERARCHY_REQUEST_ERR");y(a,this.startContainer);return 0<= +l.comparePoints(a,b,this.startContainer,this.startOffset)&&0>=l.comparePoints(a,b,this.endContainer,this.endOffset)},intersectsRange:function(b,c){v(this);if(a(b)!=a(this))throw new B("WRONG_DOCUMENT_ERR");var d=l.comparePoints(this.startContainer,this.startOffset,b.endContainer,b.endOffset),h=l.comparePoints(this.endContainer,this.endOffset,b.startContainer,b.startOffset);return c?0>=d&&0<=h:0>d&&0<h},intersection:function(a){if(this.intersectsRange(a)){var b=l.comparePoints(this.startContainer, +this.startOffset,a.startContainer,a.startOffset),c=l.comparePoints(this.endContainer,this.endOffset,a.endContainer,a.endOffset),d=this.cloneRange();-1==b&&d.setStart(a.startContainer,a.startOffset);1==c&&d.setEnd(a.endContainer,a.endOffset);return d}return null},union:function(a){if(this.intersectsRange(a,!0)){var b=this.cloneRange();-1==l.comparePoints(a.startContainer,a.startOffset,this.startContainer,this.startOffset)&&b.setStart(a.startContainer,a.startOffset);1==l.comparePoints(a.endContainer, +a.endOffset,this.endContainer,this.endOffset)&&b.setEnd(a.endContainer,a.endOffset);return b}throw new r("Ranges do not intersect");},containsNode:function(a,b){return b?this.intersectsNode(a,!1):this.compareNode(a)==R},containsNodeContents:function(a){return 0<=this.comparePoint(a,0)&&0>=this.comparePoint(a,l.getNodeLength(a))},containsRange:function(a){return this.intersection(a).equals(a)},containsNodeText:function(a){var b=this.cloneRange();b.selectNode(a);var c=b.getNodes([3]);return 0<c.length? +(b.setStart(c[0],0),a=c.pop(),b.setEnd(a,a.length),a=this.containsRange(b),b.detach(),a):this.containsNodeContents(a)},createNodeIterator:function(a,b){v(this);return new m(this,a,b)},getNodes:function(a,b){v(this);return n(this,a,b)},getDocument:function(){return a(this)},collapseBefore:function(a){o(this);this.setEndBefore(a);this.collapse(!1)},collapseAfter:function(a){o(this);this.setStartAfter(a);this.collapse(!0)},getName:function(){return"DomRange"},equals:function(a){return C.rangesEqual(this, +a)},inspect:function(){return p(this)}};I(C,J,function(a){o(a);a.startContainer=a.startOffset=a.endContainer=a.endOffset=null;a.collapsed=a.commonAncestorContainer=null;d(a,"detach",null);a._listeners=null});b.rangePrototype=D.prototype;C.rangeProperties=T;C.RangeIterator=q;C.copyComparisonConstants=F;C.createPrototypeRange=I;C.inspect=p;C.getRangeDocument=a;C.rangesEqual=function(a,b){return a.startContainer===b.startContainer&&a.startOffset===b.startOffset&&a.endContainer===b.endContainer&&a.endOffset=== +b.endOffset};b.DomRange=C;b.RangeException=r}); +rangy.createModule("WrappedRange",function(b){function c(a,b,c,d){var g=a.duplicate();g.collapse(c);var i=g.parentElement();e.isAncestorOf(b,i,!0)||(i=b);if(!i.canHaveHTML)return new f(i.parentNode,e.getNodeIndex(i));var b=e.getDocument(i).createElement("span"),r,m=c?"StartToStart":"StartToEnd";do i.insertBefore(b,b.previousSibling),g.moveToElementText(b);while(0<(r=g.compareEndPoints(m,a))&&b.previousSibling);m=b.nextSibling;if(-1==r&&m&&e.isCharacterDataNode(m)){g.setEndPoint(c?"EndToStart":"EndToEnd", +a);if(/[\r\n]/.test(m.data)){i=g.duplicate();c=i.text.replace(/\r\n/g,"\r").length;for(c=i.moveStart("character",c);-1==i.compareEndPoints("StartToEnd",i);)c++,i.moveStart("character",1)}else c=g.text.length;i=new f(m,c)}else m=(d||!c)&&b.previousSibling,i=(c=(d||c)&&b.nextSibling)&&e.isCharacterDataNode(c)?new f(c,0):m&&e.isCharacterDataNode(m)?new f(m,m.length):new f(i,e.getNodeIndex(b));b.parentNode.removeChild(b);return i}function a(a,b){var c,d,f=a.offset,g=e.getDocument(a.node),i=g.body.createTextRange(), +m=e.isCharacterDataNode(a.node);m?(c=a.node,d=c.parentNode):(c=a.node.childNodes,c=f<c.length?c[f]:null,d=a.node);g=g.createElement("span");g.innerHTML="&#feff;";c?d.insertBefore(g,c):d.appendChild(g);i.moveToElementText(g);i.collapse(!b);d.removeChild(g);if(m)i[b?"moveStart":"moveEnd"]("character",f);return i}b.requireModules(["DomUtil","DomRange"]);var d,e=b.dom,f=e.DomPosition,g=b.DomRange;if(b.features.implementsDomRange&&(!b.features.implementsTextRange||!b.config.preferTextRange))(function(){function a(b){for(var c= +j.length,d;c--;)d=j[c],b[d]=b.nativeRange[d]}var c,j=g.rangeProperties,f;d=function(b){if(!b)throw Error("Range must be specified");this.nativeRange=b;a(this)};g.createPrototypeRange(d,function(a,b,c,d,h){var e=a.endContainer!==d||a.endOffset!=h;if(a.startContainer!==b||a.startOffset!=c||e)a.setEnd(d,h),a.setStart(b,c)},function(a){a.nativeRange.detach();a.detached=!0;for(var b=j.length,c;b--;)c=j[b],a[c]=null});c=d.prototype;c.selectNode=function(b){this.nativeRange.selectNode(b);a(this)};c.deleteContents= +function(){this.nativeRange.deleteContents();a(this)};c.extractContents=function(){var b=this.nativeRange.extractContents();a(this);return b};c.cloneContents=function(){return this.nativeRange.cloneContents()};c.surroundContents=function(b){this.nativeRange.surroundContents(b);a(this)};c.collapse=function(b){this.nativeRange.collapse(b);a(this)};c.cloneRange=function(){return new d(this.nativeRange.cloneRange())};c.refresh=function(){a(this)};c.toString=function(){return this.nativeRange.toString()}; +var i=document.createTextNode("test");e.getBody(document).appendChild(i);var q=document.createRange();q.setStart(i,0);q.setEnd(i,0);try{q.setStart(i,1),c.setStart=function(b,c){this.nativeRange.setStart(b,c);a(this)},c.setEnd=function(b,c){this.nativeRange.setEnd(b,c);a(this)},f=function(b){return function(c){this.nativeRange[b](c);a(this)}}}catch(r){c.setStart=function(b,c){try{this.nativeRange.setStart(b,c)}catch(d){this.nativeRange.setEnd(b,c),this.nativeRange.setStart(b,c)}a(this)},c.setEnd=function(b, +c){try{this.nativeRange.setEnd(b,c)}catch(d){this.nativeRange.setStart(b,c),this.nativeRange.setEnd(b,c)}a(this)},f=function(b,c){return function(d){try{this.nativeRange[b](d)}catch(e){this.nativeRange[c](d),this.nativeRange[b](d)}a(this)}}}c.setStartBefore=f("setStartBefore","setEndBefore");c.setStartAfter=f("setStartAfter","setEndAfter");c.setEndBefore=f("setEndBefore","setStartBefore");c.setEndAfter=f("setEndAfter","setStartAfter");q.selectNodeContents(i);c.selectNodeContents=q.startContainer== +i&&q.endContainer==i&&0==q.startOffset&&q.endOffset==i.length?function(b){this.nativeRange.selectNodeContents(b);a(this)}:function(a){this.setStart(a,0);this.setEnd(a,g.getEndOffset(a))};q.selectNodeContents(i);q.setEnd(i,3);f=document.createRange();f.selectNodeContents(i);f.setEnd(i,4);f.setStart(i,2);c.compareBoundaryPoints=-1==q.compareBoundaryPoints(q.START_TO_END,f)&1==q.compareBoundaryPoints(q.END_TO_START,f)?function(a,b){b=b.nativeRange||b;a==b.START_TO_END?a=b.END_TO_START:a==b.END_TO_START&& +(a=b.START_TO_END);return this.nativeRange.compareBoundaryPoints(a,b)}:function(a,b){return this.nativeRange.compareBoundaryPoints(a,b.nativeRange||b)};b.util.isHostMethod(q,"createContextualFragment")&&(c.createContextualFragment=function(a){return this.nativeRange.createContextualFragment(a)});e.getBody(document).removeChild(i);q.detach();f.detach()})(),b.createNativeRange=function(a){a=a||document;return a.createRange()};else if(b.features.implementsTextRange){d=function(a){this.textRange=a;this.refresh()}; +d.prototype=new g(document);d.prototype.refresh=function(){var a,b,d=this.textRange;a=d.parentElement();var f=d.duplicate();f.collapse(!0);b=f.parentElement();f=d.duplicate();f.collapse(!1);d=f.parentElement();b=b==d?b:e.getCommonAncestor(b,d);b=b==a?b:e.getCommonAncestor(a,b);0==this.textRange.compareEndPoints("StartToEnd",this.textRange)?b=a=c(this.textRange,b,!0,!0):(a=c(this.textRange,b,!0,!1),b=c(this.textRange,b,!1,!1));this.setStart(a.node,a.offset);this.setEnd(b.node,b.offset)};g.copyComparisonConstants(d); +var i=function(){return this}();"undefined"==typeof i.Range&&(i.Range=d);b.createNativeRange=function(a){a=a||document;return a.body.createTextRange()}}b.features.implementsTextRange&&(d.rangeToTextRange=function(b){if(b.collapsed)return a(new f(b.startContainer,b.startOffset),!0);var c=a(new f(b.startContainer,b.startOffset),!0),d=a(new f(b.endContainer,b.endOffset),!1),b=e.getDocument(b.startContainer).body.createTextRange();b.setEndPoint("StartToStart",c);b.setEndPoint("EndToEnd",d);return b}); +d.prototype.getName=function(){return"WrappedRange"};b.WrappedRange=d;b.createRange=function(a){a=a||document;return new d(b.createNativeRange(a))};b.createRangyRange=function(a){a=a||document;return new g(a)};b.createIframeRange=function(a){return b.createRange(e.getIframeDocument(a))};b.createIframeRangyRange=function(a){return b.createRangyRange(e.getIframeDocument(a))};b.addCreateMissingNativeApiListener(function(a){a=a.document;if(typeof a.createRange=="undefined")a.createRange=function(){return b.createRange(this)}; +a=a=null})}); +rangy.createModule("WrappedSelection",function(b,c){function a(a){return(a||window).getSelection()}function d(a){return(a||window).document.selection}function e(a,b,c){var d=c?"end":"start",c=c?"start":"end";a.anchorNode=b[d+"Container"];a.anchorOffset=b[d+"Offset"];a.focusNode=b[c+"Container"];a.focusOffset=b[c+"Offset"]}function f(a){a.anchorNode=a.focusNode=null;a.anchorOffset=a.focusOffset=0;a.rangeCount=0;a.isCollapsed=!0;a._ranges.length=0}function g(a){var c;a instanceof x?(c=a._selectionNativeRange, +c||(c=b.createNativeRange(m.getDocument(a.startContainer)),c.setEnd(a.endContainer,a.endOffset),c.setStart(a.startContainer,a.startOffset),a._selectionNativeRange=c,a.attachListener("detach",function(){this._selectionNativeRange=null}))):a instanceof o?c=a.nativeRange:b.features.implementsDomRange&&a instanceof m.getWindow(a.startContainer).Range&&(c=a);return c}function i(a){var b=a.getNodes(),c;a:if(!b.length||1!=b[0].nodeType)c=!1;else{c=1;for(var d=b.length;c<d;++c)if(!m.isAncestorOf(b[0],b[c])){c= +!1;break a}c=!0}if(!c)throw Error("getSingleElementFromRange: range "+a.inspect()+" did not consist of a single element");return b[0]}function h(a,b){var c=new o(b);a._ranges=[c];e(a,c,!1);a.rangeCount=1;a.isCollapsed=c.collapsed}function k(a){a._ranges.length=0;if("None"==a.docSelection.type)f(a);else{var c=a.docSelection.createRange();if(c&&"undefined"!=typeof c.text)h(a,c);else{a.rangeCount=c.length;for(var d,j=m.getDocument(c.item(0)),k=0;k<a.rangeCount;++k)d=b.createRange(j),d.selectNode(c.item(k)), +a._ranges.push(d);a.isCollapsed=1==a.rangeCount&&a._ranges[0].collapsed;e(a,a._ranges[a.rangeCount-1],!1)}}}function j(a,b){for(var c=a.docSelection.createRange(),d=i(b),e=m.getDocument(c.item(0)),e=m.getBody(e).createControlRange(),h=0,j=c.length;h<j;++h)e.add(c.item(h));try{e.add(d)}catch(f){throw Error("addRange(): Element within the specified Range could not be added to control selection (does it have layout?)");}e.select();k(a)}function n(a,b,c){this.nativeSelection=a;this.docSelection=b;this._ranges= +[];this.win=c;this.refresh()}function p(a,b){for(var c=m.getDocument(b[0].startContainer),c=m.getBody(c).createControlRange(),d=0,e;d<rangeCount;++d){e=i(b[d]);try{c.add(e)}catch(h){throw Error("setRanges(): Element within the one of the specified Ranges could not be added to control selection (does it have layout?)");}}c.select();k(a)}function q(a,b){if(a.anchorNode&&m.getDocument(a.anchorNode)!==m.getDocument(b))throw new z("WRONG_DOCUMENT_ERR");}function r(a){var b=[],c=new w(a.anchorNode,a.anchorOffset), +d=new w(a.focusNode,a.focusOffset),e="function"==typeof a.getName?a.getName():"Selection";if("undefined"!=typeof a.rangeCount)for(var h=0,j=a.rangeCount;h<j;++h)b[h]=x.inspect(a.getRangeAt(h));return"["+e+"(Ranges: "+b.join(", ")+")(anchor: "+c.inspect()+", focus: "+d.inspect()+"]"}b.requireModules(["DomUtil","DomRange","WrappedRange"]);b.config.checkSelectionRanges=!0;var m=b.dom,s=b.util,x=b.DomRange,o=b.WrappedRange,z=b.DOMException,w=m.DomPosition,y,A,t=b.util.isHostMethod(window,"getSelection"), +v=b.util.isHostObject(document,"selection"),D=v&&(!t||b.config.preferTextRange);D?(y=d,b.isSelectionValid=function(a){var a=(a||window).document,b=a.selection;return"None"!=b.type||m.getDocument(b.createRange().parentElement())==a}):t?(y=a,b.isSelectionValid=function(){return!0}):c.fail("Neither document.selection or window.getSelection() detected.");b.getNativeSelection=y;var t=y(),K=b.createNativeRange(document),F=m.getBody(document),E=s.areHostObjects(t,s.areHostProperties(t,["anchorOffset","focusOffset"])); +b.features.selectionHasAnchorAndFocus=E;var I=s.isHostMethod(t,"extend");b.features.selectionHasExtend=I;var N="number"==typeof t.rangeCount;b.features.selectionHasRangeCount=N;var J=!1,C=!0;s.areHostMethods(t,["addRange","getRangeAt","removeAllRanges"])&&("number"==typeof t.rangeCount&&b.features.implementsDomRange)&&function(){var a=document.createElement("iframe");F.appendChild(a);var b=m.getIframeDocument(a);b.open();b.write("<html><head></head><body>12</body></html>");b.close();var c=m.getIframeWindow(a).getSelection(), +d=b.documentElement.lastChild.firstChild,b=b.createRange();b.setStart(d,1);b.collapse(true);c.addRange(b);C=c.rangeCount==1;c.removeAllRanges();var e=b.cloneRange();b.setStart(d,0);e.setEnd(d,2);c.addRange(b);c.addRange(e);J=c.rangeCount==2;b.detach();e.detach();F.removeChild(a)}();b.features.selectionSupportsMultipleRanges=J;b.features.collapsedNonEditableSelectionsSupported=C;var l=!1,u;F&&s.isHostMethod(F,"createControlRange")&&(u=F.createControlRange(),s.areHostProperties(u,["item","add"])&&(l= +!0));b.features.implementsControlRange=l;A=E?function(a){return a.anchorNode===a.focusNode&&a.anchorOffset===a.focusOffset}:function(a){return a.rangeCount?a.getRangeAt(a.rangeCount-1).collapsed:false};var B;s.isHostMethod(t,"getRangeAt")?B=function(a,b){try{return a.getRangeAt(b)}catch(c){return null}}:E&&(B=function(a){var c=m.getDocument(a.anchorNode),c=b.createRange(c);c.setStart(a.anchorNode,a.anchorOffset);c.setEnd(a.focusNode,a.focusOffset);if(c.collapsed!==this.isCollapsed){c.setStart(a.focusNode, +a.focusOffset);c.setEnd(a.anchorNode,a.anchorOffset)}return c});b.getSelection=function(a){var a=a||window,b=a._rangySelection,c=y(a),e=v?d(a):null;if(b){b.nativeSelection=c;b.docSelection=e;b.refresh(a)}else{b=new n(c,e,a);a._rangySelection=b}return b};b.getIframeSelection=function(a){return b.getSelection(m.getIframeWindow(a))};u=n.prototype;if(!D&&E&&s.areHostMethods(t,["removeAllRanges","addRange"])){u.removeAllRanges=function(){this.nativeSelection.removeAllRanges();f(this)};var L=function(a, +c){var d=x.getRangeDocument(c),d=b.createRange(d);d.collapseToPoint(c.endContainer,c.endOffset);a.nativeSelection.addRange(g(d));a.nativeSelection.extend(c.startContainer,c.startOffset);a.refresh()};u.addRange=N?function(a,c){if(l&&v&&this.docSelection.type=="Control")j(this,a);else if(c&&I)L(this,a);else{var d;if(J)d=this.rangeCount;else{this.removeAllRanges();d=0}this.nativeSelection.addRange(g(a));this.rangeCount=this.nativeSelection.rangeCount;if(this.rangeCount==d+1){if(b.config.checkSelectionRanges)(d= +B(this.nativeSelection,this.rangeCount-1))&&!x.rangesEqual(d,a)&&(a=new o(d));this._ranges[this.rangeCount-1]=a;e(this,a,H(this.nativeSelection));this.isCollapsed=A(this)}else this.refresh()}}:function(a,b){if(b&&I)L(this,a);else{this.nativeSelection.addRange(g(a));this.refresh()}};u.setRanges=function(a){if(l&&a.length>1)p(this,a);else{this.removeAllRanges();for(var b=0,c=a.length;b<c;++b)this.addRange(a[b])}}}else if(s.isHostMethod(t,"empty")&&s.isHostMethod(K,"select")&&l&&D)u.removeAllRanges= +function(){try{this.docSelection.empty();if(this.docSelection.type!="None"){var a;if(this.anchorNode)a=m.getDocument(this.anchorNode);else if(this.docSelection.type=="Control"){var b=this.docSelection.createRange();b.length&&(a=m.getDocument(b.item(0)).body.createTextRange())}if(a){a.body.createTextRange().select();this.docSelection.empty()}}}catch(c){}f(this)},u.addRange=function(a){if(this.docSelection.type=="Control")j(this,a);else{o.rangeToTextRange(a).select();this._ranges[0]=a;this.rangeCount= +1;this.isCollapsed=this._ranges[0].collapsed;e(this,a,false)}},u.setRanges=function(a){this.removeAllRanges();var b=a.length;b>1?p(this,a):b&&this.addRange(a[0])};else return c.fail("No means of selecting a Range or TextRange was found"),!1;u.getRangeAt=function(a){if(a<0||a>=this.rangeCount)throw new z("INDEX_SIZE_ERR");return this._ranges[a]};var G;if(D)G=function(a){var c;if(b.isSelectionValid(a.win))c=a.docSelection.createRange();else{c=m.getBody(a.win.document).createTextRange();c.collapse(true)}a.docSelection.type== +"Control"?k(a):c&&typeof c.text!="undefined"?h(a,c):f(a)};else if(s.isHostMethod(t,"getRangeAt")&&"number"==typeof t.rangeCount)G=function(a){if(l&&v&&a.docSelection.type=="Control")k(a);else{a._ranges.length=a.rangeCount=a.nativeSelection.rangeCount;if(a.rangeCount){for(var c=0,d=a.rangeCount;c<d;++c)a._ranges[c]=new b.WrappedRange(a.nativeSelection.getRangeAt(c));e(a,a._ranges[a.rangeCount-1],H(a.nativeSelection));a.isCollapsed=A(a)}else f(a)}};else if(E&&"boolean"==typeof t.isCollapsed&&"boolean"== +typeof K.collapsed&&b.features.implementsDomRange)G=function(a){var b;b=a.nativeSelection;if(b.anchorNode){b=B(b,0);a._ranges=[b];a.rangeCount=1;b=a.nativeSelection;a.anchorNode=b.anchorNode;a.anchorOffset=b.anchorOffset;a.focusNode=b.focusNode;a.focusOffset=b.focusOffset;a.isCollapsed=A(a)}else f(a)};else return c.fail("No means of obtaining a Range or TextRange from the user's selection was found"),!1;u.refresh=function(a){var b=a?this._ranges.slice(0):null;G(this);if(a){a=b.length;if(a!=this._ranges.length)return false; +for(;a--;)if(!x.rangesEqual(b[a],this._ranges[a]))return false;return true}};var P=function(a,b){var c=a.getAllRanges(),d=false;a.removeAllRanges();for(var e=0,h=c.length;e<h;++e)d||b!==c[e]?a.addRange(c[e]):d=true;a.rangeCount||f(a)};u.removeRange=l?function(a){if(this.docSelection.type=="Control"){for(var b=this.docSelection.createRange(),a=i(a),c=m.getDocument(b.item(0)),c=m.getBody(c).createControlRange(),d,e=false,h=0,j=b.length;h<j;++h){d=b.item(h);d!==a||e?c.add(b.item(h)):e=true}c.select(); +k(this)}else P(this,a)}:function(a){P(this,a)};var H;!D&&E&&b.features.implementsDomRange?(H=function(a){var b=false;a.anchorNode&&(b=m.comparePoints(a.anchorNode,a.anchorOffset,a.focusNode,a.focusOffset)==1);return b},u.isBackwards=function(){return H(this)}):H=u.isBackwards=function(){return false};u.toString=function(){for(var a=[],b=0,c=this.rangeCount;b<c;++b)a[b]=""+this._ranges[b];return a.join("")};u.collapse=function(a,c){q(this,a);var d=b.createRange(m.getDocument(a));d.collapseToPoint(a, +c);this.removeAllRanges();this.addRange(d);this.isCollapsed=true};u.collapseToStart=function(){if(this.rangeCount){var a=this._ranges[0];this.collapse(a.startContainer,a.startOffset)}else throw new z("INVALID_STATE_ERR");};u.collapseToEnd=function(){if(this.rangeCount){var a=this._ranges[this.rangeCount-1];this.collapse(a.endContainer,a.endOffset)}else throw new z("INVALID_STATE_ERR");};u.selectAllChildren=function(a){q(this,a);var c=b.createRange(m.getDocument(a));c.selectNodeContents(a);this.removeAllRanges(); +this.addRange(c)};u.deleteFromDocument=function(){if(l&&v&&this.docSelection.type=="Control"){for(var a=this.docSelection.createRange(),b;a.length;){b=a.item(0);a.remove(b);b.parentNode.removeChild(b)}this.refresh()}else if(this.rangeCount){a=this.getAllRanges();this.removeAllRanges();b=0;for(var c=a.length;b<c;++b)a[b].deleteContents();this.addRange(a[c-1])}};u.getAllRanges=function(){return this._ranges.slice(0)};u.setSingleRange=function(a){this.setRanges([a])};u.containsNode=function(a,b){for(var c= +0,d=this._ranges.length;c<d;++c)if(this._ranges[c].containsNode(a,b))return true;return false};u.toHtml=function(){var a="";if(this.rangeCount){for(var a=x.getRangeDocument(this._ranges[0]).createElement("div"),b=0,c=this._ranges.length;b<c;++b)a.appendChild(this._ranges[b].cloneContents());a=a.innerHTML}return a};u.getName=function(){return"WrappedSelection"};u.inspect=function(){return r(this)};u.detach=function(){this.win=this.anchorNode=this.focusNode=this.win._rangySelection=null};n.inspect= +r;b.Selection=n;b.selectionPrototype=u;b.addCreateMissingNativeApiListener(function(a){if(typeof a.getSelection=="undefined")a.getSelection=function(){return b.getSelection(this)};a=null})});var Base=function(){}; +Base.extend=function(b,c){var a=Base.prototype.extend;Base._prototyping=!0;var d=new this;a.call(d,b);d.base=function(){};delete Base._prototyping;var e=d.constructor,f=d.constructor=function(){if(!Base._prototyping)if(this._constructing||this.constructor==f)this._constructing=!0,e.apply(this,arguments),delete this._constructing;else if(null!=arguments[0])return(arguments[0].extend||a).call(arguments[0],d)};f.ancestor=this;f.extend=this.extend;f.forEach=this.forEach;f.implement=this.implement;f.prototype= +d;f.toString=this.toString;f.valueOf=function(a){return"object"==a?f:e.valueOf()};a.call(f,c);"function"==typeof f.init&&f.init();return f}; +Base.prototype={extend:function(b,c){if(1<arguments.length){var a=this[b];if(a&&"function"==typeof c&&(!a.valueOf||a.valueOf()!=c.valueOf())&&/\bbase\b/.test(c)){var d=c.valueOf(),c=function(){var b=this.base||Base.prototype.base;this.base=a;var c=d.apply(this,arguments);this.base=b;return c};c.valueOf=function(a){return"object"==a?c:d};c.toString=Base.toString}this[b]=c}else if(b){var e=Base.prototype.extend;!Base._prototyping&&"function"!=typeof this&&(e=this.extend||e);for(var f={toSource:null}, +g=["constructor","toString","valueOf"],i=Base._prototyping?0:1;h=g[i++];)b[h]!=f[h]&&e.call(this,h,b[h]);for(var h in b)f[h]||e.call(this,h,b[h])}return this}}; +Base=Base.extend({constructor:function(b){this.extend(b)}},{ancestor:Object,version:"1.1",forEach:function(b,c,a){for(var d in b)void 0===this.prototype[d]&&c.call(a,b[d],d,b)},implement:function(){for(var b=0;b<arguments.length;b++)if("function"==typeof arguments[b])arguments[b](this.prototype);else this.prototype.extend(arguments[b]);return this},toString:function(){return""+this.valueOf()}}); +wysihtml5.browser=function(){var b=navigator.userAgent,c=document.createElement("div"),a=-1!==b.indexOf("MSIE")&&-1===b.indexOf("Opera"),d=-1!==b.indexOf("Gecko")&&-1===b.indexOf("KHTML"),e=-1!==b.indexOf("AppleWebKit/"),f=-1!==b.indexOf("Chrome/"),g=-1!==b.indexOf("Opera/");return{USER_AGENT:b,supported:function(){var a=this.USER_AGENT.toLowerCase(),b="contentEditable"in c,d=document.execCommand&&document.queryCommandSupported&&document.queryCommandState,e=document.querySelector&&document.querySelectorAll, +a=this.isIos()&&5>(/ipad|iphone|ipod/.test(a)&&a.match(/ os (\d+).+? like mac os x/)||[,0])[1]||-1!==a.indexOf("opera mobi")||-1!==a.indexOf("hpwos/");return b&&d&&e&&!a},isTouchDevice:function(){return this.supportsEvent("touchmove")},isIos:function(){var a=this.USER_AGENT.toLowerCase();return-1!==a.indexOf("webkit")&&-1!==a.indexOf("mobile")},supportsSandboxedIframes:function(){return a},throwsMixedContentWarningWhenIframeSrcIsEmpty:function(){return!("querySelector"in document)},displaysCaretInEmptyContentEditableCorrectly:function(){return!d}, +hasCurrentStyleProperty:function(){return"currentStyle"in c},insertsLineBreaksOnReturn:function(){return d},supportsPlaceholderAttributeOn:function(a){return"placeholder"in a},supportsEvent:function(a){var b;if(!(b="on"+a in c))c.setAttribute("on"+a,"return;"),b="function"===typeof c["on"+a];return b},supportsEventsInIframeCorrectly:function(){return!g},firesOnDropOnlyWhenOnDragOverIsCancelled:function(){return e||d},supportsDataTransfer:function(){try{return e&&(window.Clipboard||window.DataTransfer).prototype.getData}catch(a){return!1}}, +supportsHTML5Tags:function(a){a=a.createElement("div");a.innerHTML="<article>foo</article>";return"<article>foo</article>"===a.innerHTML.toLowerCase()},supportsCommand:function(){var b={formatBlock:a,insertUnorderedList:a||g||e,insertOrderedList:a||g||e},c={insertHTML:d};return function(a,d){if(!b[d]){try{return a.queryCommandSupported(d)}catch(e){}try{return a.queryCommandEnabled(d)}catch(f){return!!c[d]}}return!1}}(),doesAutoLinkingInContentEditable:function(){return a},canDisableAutoLinking:function(){return this.supportsCommand(document, +"AutoUrlDetect")},clearsContentEditableCorrectly:function(){return d||g||e},supportsGetAttributeCorrectly:function(){return"1"!=document.createElement("td").getAttribute("rowspan")},canSelectImagesInContentEditable:function(){return d||a||g},clearsListsInContentEditableCorrectly:function(){return d||a||e},autoScrollsToCaret:function(){return!e},autoClosesUnclosedTags:function(){var a=c.cloneNode(!1),b;a.innerHTML="<p><div></div>";a=a.innerHTML.toLowerCase();b="<p></p><div></div>"===a||"<p><div></div></p>"=== +a;this.autoClosesUnclosedTags=function(){return b};return b},supportsNativeGetElementsByClassName:function(){return-1!==(""+document.getElementsByClassName).indexOf("[native code]")},supportsSelectionModify:function(){return"getSelection"in window&&"modify"in window.getSelection()},supportsClassList:function(){return"classList"in c},needsSpaceAfterLineBreak:function(){return g},supportsSpeechApiOn:function(a){return 11<=(b.match(/Chrome\/(\d+)/)||[,0])[1]&&("onwebkitspeechchange"in a||"speech"in a)}, +crashesWhenDefineProperty:function(b){return a&&("XMLHttpRequest"===b||"XDomainRequest"===b)},doesAsyncFocus:function(){return a},hasProblemsSettingCaretAfterImg:function(){return a},hasUndoInContextMenu:function(){return d||f||g}}}(); +wysihtml5.lang.array=function(b){return{contains:function(c){if(b.indexOf)return-1!==b.indexOf(c);for(var a=0,d=b.length;a<d;a++)if(b[a]===c)return!0;return!1},without:function(c){for(var c=wysihtml5.lang.array(c),a=[],d=0,e=b.length;d<e;d++)c.contains(b[d])||a.push(b[d]);return a},get:function(){for(var c=0,a=b.length,d=[];c<a;c++)d.push(b[c]);return d}}}; +wysihtml5.lang.Dispatcher=Base.extend({observe:function(b,c){this.events=this.events||{};this.events[b]=this.events[b]||[];this.events[b].push(c);return this},on:function(){return this.observe.apply(this,wysihtml5.lang.array(arguments).get())},fire:function(b,c){this.events=this.events||{};for(var a=this.events[b]||[],d=0;d<a.length;d++)a[d].call(this,c);return this},stopObserving:function(b,c){this.events=this.events||{};var a=0,d,e;if(b){d=this.events[b]||[];for(e=[];a<d.length;a++)d[a]!==c&&c&& +e.push(d[a]);this.events[b]=e}else this.events={};return this}});wysihtml5.lang.object=function(b){return{merge:function(c){for(var a in c)b[a]=c[a];return this},get:function(){return b},clone:function(){var c={},a;for(a in b)c[a]=b[a];return c},isArray:function(){return"[object Array]"===Object.prototype.toString.call(b)}}}; +(function(){var b=/^\s+/,c=/\s+$/;wysihtml5.lang.string=function(a){a=""+a;return{trim:function(){return a.replace(b,"").replace(c,"")},interpolate:function(b){for(var c in b)a=this.replace("#{"+c+"}").by(b[c]);return a},replace:function(b){return{by:function(c){return a.split(b).join(c)}}}}}})(); +(function(b){function c(a){return a.replace(e,function(a,b){var c=(b.match(f)||[])[1]||"",d=i[c],b=b.replace(f,"");b.split(d).length>b.split(c).length&&(b+=c,c="");var e=d=b;b.length>g&&(e=e.substr(0,g)+"...");"www."===d.substr(0,4)&&(d="http://"+d);return'<a href="'+d+'">'+e+"</a>"+c})}function a(h){if(!d.contains(h.nodeName))if(h.nodeType===b.TEXT_NODE&&h.data.match(e)){var f=h.parentNode,j;j=f.ownerDocument;var g=j._wysihtml5_tempElement;g||(g=j._wysihtml5_tempElement=j.createElement("div"));j= +g;j.innerHTML="<span></span>"+c(h.data);for(j.removeChild(j.firstChild);j.firstChild;)f.insertBefore(j.firstChild,h);f.removeChild(h)}else{f=b.lang.array(h.childNodes).get();j=f.length;for(g=0;g<j;g++)a(f[g]);return h}}var d=b.lang.array("CODE PRE A SCRIPT HEAD TITLE STYLE".split(" ")),e=/((https?:\/\/|www\.)[^\s<]{3,})/gi,f=/([^\w\/\-](,?))$/i,g=100,i={")":"(","]":"[","}":"{"};b.dom.autoLink=function(b){var c;a:{c=b;for(var e;c.parentNode;){c=c.parentNode;e=c.nodeName;if(d.contains(e)){c=!0;break a}if("body"=== +e)break}c=!1}if(c)return b;b===b.ownerDocument.documentElement&&(b=b.ownerDocument.body);return a(b)};b.dom.autoLink.URL_REG_EXP=e})(wysihtml5); +(function(b){var c=b.browser.supportsClassList(),a=b.dom;a.addClass=function(b,e){if(c)return b.classList.add(e);a.hasClass(b,e)||(b.className+=" "+e)};a.removeClass=function(a,b){if(c)return a.classList.remove(b);a.className=a.className.replace(RegExp("(^|\\s+)"+b+"(\\s+|$)")," ")};a.hasClass=function(a,b){if(c)return a.classList.contains(b);var f=a.className;return 0<f.length&&(f==b||RegExp("(^|\\s)"+b+"(\\s|$)").test(f))}})(wysihtml5); +wysihtml5.dom.contains=function(){var b=document.documentElement;if(b.contains)return function(b,a){a.nodeType!==wysihtml5.ELEMENT_NODE&&(a=a.parentNode);return b!==a&&b.contains(a)};if(b.compareDocumentPosition)return function(b,a){return!!(b.compareDocumentPosition(a)&16)}}(); +wysihtml5.dom.convertToList=function(){function b(b,a){var d=b.createElement("li");a.appendChild(d);return d}return function(c,a){if("UL"===c.nodeName||"OL"===c.nodeName||"MENU"===c.nodeName)return c;var d=c.ownerDocument,e=d.createElement(a),f=c.querySelectorAll("br"),g=f.length,i,h,k,j,n;for(n=0;n<g;n++)for(i=f[n];(h=i.parentNode)&&h!==c&&h.lastChild===i;){if("block"===wysihtml5.dom.getStyle("display").from(h)){h.removeChild(i);break}wysihtml5.dom.insert(i).after(i.parentNode)}f=wysihtml5.lang.array(c.childNodes).get(); +g=f.length;for(n=0;n<g;n++)j=j||b(d,e),i=f[n],h="block"===wysihtml5.dom.getStyle("display").from(i),k="BR"===i.nodeName,h?(j=j.firstChild?b(d,e):j,j.appendChild(i),j=null):k?j=j.firstChild?null:j:j.appendChild(i);c.parentNode.replaceChild(e,c);return e}}();wysihtml5.dom.copyAttributes=function(b){return{from:function(c){return{to:function(a){for(var d,e=0,f=b.length;e<f;e++)d=b[e],"undefined"!==typeof c[d]&&""!==c[d]&&(a[d]=c[d]);return{andTo:arguments.callee}}}}}}; +(function(b){var c=["-webkit-box-sizing","-moz-box-sizing","-ms-box-sizing","box-sizing"],a=function(a){var e;a:for(var f=0,g=c.length;f<g;f++)if("border-box"===b.getStyle(c[f]).from(a)){e=c[f];break a}return e?parseInt(b.getStyle("width").from(a),10)<a.offsetWidth:!1};b.copyStyles=function(d){return{from:function(e){a(e)&&(d=wysihtml5.lang.array(d).without(c));for(var f="",g=d.length,i=0,h;i<g;i++)h=d[i],f+=h+":"+b.getStyle(h).from(e)+";";return{to:function(a){b.setStyles(f).on(a);return{andTo:arguments.callee}}}}}}})(wysihtml5.dom); +(function(b){b.dom.delegate=function(c,a,d,e){return b.dom.observe(c,d,function(d){for(var g=d.target,i=b.lang.array(c.querySelectorAll(a));g&&g!==c;){if(i.contains(g)){e.call(g,d);break}g=g.parentNode}})}})(wysihtml5); +wysihtml5.dom.getAsDom=function(){var b="abbr article aside audio bdi canvas command datalist details figcaption figure footer header hgroup keygen mark meter nav output progress rp rt ruby svg section source summary time track video wbr".split(" ");return function(c,a){var a=a||document,d;if("object"===typeof c&&c.nodeType)d=a.createElement("div"),d.appendChild(c);else if(wysihtml5.browser.supportsHTML5Tags(a))d=a.createElement("div"),d.innerHTML=c;else{d=a;if(!d._wysihtml5_supportsHTML5Tags){for(var e= +0,f=b.length;e<f;e++)d.createElement(b[e]);d._wysihtml5_supportsHTML5Tags=!0}d=a;e=d.createElement("div");e.style.display="none";d.body.appendChild(e);try{e.innerHTML=c}catch(g){}d.body.removeChild(e);d=e}return d}}(); +wysihtml5.dom.getParentElement=function(){function b(b,a){return!a||!a.length?!0:"string"===typeof a?b===a:wysihtml5.lang.array(a).contains(b)}return function(c,a,d){d=d||50;if(a.className||a.classRegExp){a:{for(var e=a.nodeName,f=a.className,a=a.classRegExp;d--&&c&&"BODY"!==c.nodeName;){var g;if(g=c.nodeType===wysihtml5.ELEMENT_NODE)if(g=b(c.nodeName,e)){g=f;var i=(c.className||"").match(a)||[];g=!g?!!i.length:i[i.length-1]===g}if(g)break a;c=c.parentNode}c=null}return c}a:{e=a.nodeName;for(f=d;f--&& +c&&"BODY"!==c.nodeName;){if(b(c.nodeName,e))break a;c=c.parentNode}c=null}return c}}(); +wysihtml5.dom.getStyle=function(){function b(b){return b.replace(a,function(a){return a.charAt(1).toUpperCase()})}var c={"float":"styleFloat"in document.createElement("div").style?"styleFloat":"cssFloat"},a=/\-[a-z]/g;return function(a){return{from:function(e){if(e.nodeType===wysihtml5.ELEMENT_NODE){var f=e.ownerDocument,g=c[a]||b(a),i=e.style,h=e.currentStyle,k=i[g];if(k)return k;if(h)try{return h[g]}catch(j){}var g=f.defaultView||f.parentWindow,f=("height"===a||"width"===a)&&"TEXTAREA"===e.nodeName, +n;if(g.getComputedStyle)return f&&(n=i.overflow,i.overflow="hidden"),e=g.getComputedStyle(e,null).getPropertyValue(a),f&&(i.overflow=n||""),e}}}}}();wysihtml5.dom.hasElementWithTagName=function(){var b={},c=1;return function(a,d){var e=(a._wysihtml5_identifier||(a._wysihtml5_identifier=c++))+":"+d,f=b[e];f||(f=b[e]=a.getElementsByTagName(d));return 0<f.length}}(); +(function(b){var c={},a=1;b.dom.hasElementWithClassName=function(d,e){if(!b.browser.supportsNativeGetElementsByClassName())return!!d.querySelector("."+e);var f=(d._wysihtml5_identifier||(d._wysihtml5_identifier=a++))+":"+e,g=c[f];g||(g=c[f]=d.getElementsByClassName(e));return 0<g.length}})(wysihtml5);wysihtml5.dom.insert=function(b){return{after:function(c){c.parentNode.insertBefore(b,c.nextSibling)},before:function(c){c.parentNode.insertBefore(b,c)},into:function(c){c.appendChild(b)}}}; +wysihtml5.dom.insertCSS=function(b){b=b.join("\n");return{into:function(c){var a=c.head||c.getElementsByTagName("head")[0],d=c.createElement("style");d.type="text/css";d.styleSheet?d.styleSheet.cssText=b:d.appendChild(c.createTextNode(b));a&&a.appendChild(d)}}}; +wysihtml5.dom.observe=function(b,c,a){for(var c="string"===typeof c?[c]:c,d,e,f=0,g=c.length;f<g;f++)e=c[f],b.addEventListener?b.addEventListener(e,a,!1):(d=function(c){"target"in c||(c.target=c.srcElement);c.preventDefault=c.preventDefault||function(){this.returnValue=false};c.stopPropagation=c.stopPropagation||function(){this.cancelBubble=true};a.call(b,c)},b.attachEvent("on"+e,d));return{stop:function(){for(var e,h=0,f=c.length;h<f;h++)e=c[h],b.removeEventListener?b.removeEventListener(e,a,!1): +b.detachEvent("on"+e,d)}}}; +wysihtml5.dom.parse=function(){function b(c,e){var h=c.childNodes,f=h.length,g;g=a[c.nodeType];var k=0;g=g&&g(c);if(!g)return null;for(k=0;k<f;k++)(newChild=b(h[k],e))&&g.appendChild(newChild);return e&&1>=g.childNodes.length&&g.nodeName.toLowerCase()===d&&!g.attributes.length?g.firstChild:g}function c(a,b){var b=b.toLowerCase(),c;if(c="IMG"==a.nodeName)if(c="src"==b){var d;try{d=a.complete&&!a.mozMatchesSelector(":-moz-broken")}catch(e){a.complete&&"complete"===a.readyState&&(d=!0)}c=!0===d}return c? +a.src:i&&"outerHTML"in a?-1!=a.outerHTML.toLowerCase().indexOf(" "+b+"=")?a.getAttribute(b):null:a.getAttribute(b)}var a={1:function(a){var b,f,i=g.tags;f=a.nodeName.toLowerCase();b=a.scopeName;if(a._wysihtml5)return null;a._wysihtml5=1;if("wysihtml5-temp"===a.className)return null;b&&"HTML"!=b&&(f=b+":"+f);"outerHTML"in a&&!wysihtml5.browser.autoClosesUnclosedTags()&&("P"===a.nodeName&&"</p>"!==a.outerHTML.slice(-4).toLowerCase())&&(f="div");if(f in i){b=i[f];if(!b||b.remove)return null;b="string"=== +typeof b?{rename_tag:b}:b}else if(a.firstChild)b={rename_tag:d};else return null;f=a.ownerDocument.createElement(b.rename_tag||f);var i={},r=b.set_class,m=b.add_class,s=b.set_attributes,x=b.check_attributes,o=g.classes,z=0,w=[];b=[];var y=[],A=[],t;s&&(i=wysihtml5.lang.object(s).clone());if(x)for(t in x)if(s=h[x[t]])s=s(c(a,t)),"string"===typeof s&&(i[t]=s);r&&w.push(r);if(m)for(t in m)if(s=k[m[t]])r=s(c(a,t)),"string"===typeof r&&w.push(r);o["_wysihtml5-temp-placeholder"]=1;(A=a.getAttribute("class"))&& +(w=w.concat(A.split(e)));for(m=w.length;z<m;z++)a=w[z],o[a]&&b.push(a);for(o=b.length;o--;)a=b[o],wysihtml5.lang.array(y).contains(a)||y.unshift(a);y.length&&(i["class"]=y.join(" "));for(t in i)try{f.setAttribute(t,i[t])}catch(v){}i.src&&("undefined"!==typeof i.width&&f.setAttribute("width",i.width),"undefined"!==typeof i.height&&f.setAttribute("height",i.height));return f},3:function(a){return a.ownerDocument.createTextNode(a.data)}},d="span",e=/\s+/,f={tags:{},classes:{}},g={},i=!wysihtml5.browser.supportsGetAttributeCorrectly(), +h={url:function(){var a=/^https?:\/\//i;return function(b){return!b||!b.match(a)?null:b.replace(a,function(a){return a.toLowerCase()})}}(),alt:function(){var a=/[^ a-z0-9_\-]/gi;return function(b){return!b?"":b.replace(a,"")}}(),numbers:function(){var a=/\D/g;return function(b){return(b=(b||"").replace(a,""))||null}}()},k={align_img:function(){var a={left:"wysiwyg-float-left",right:"wysiwyg-float-right"};return function(b){return a[(""+b).toLowerCase()]}}(),align_text:function(){var a={left:"wysiwyg-text-align-left", +right:"wysiwyg-text-align-right",center:"wysiwyg-text-align-center",justify:"wysiwyg-text-align-justify"};return function(b){return a[(""+b).toLowerCase()]}}(),clear_br:function(){var a={left:"wysiwyg-clear-left",right:"wysiwyg-clear-right",both:"wysiwyg-clear-both",all:"wysiwyg-clear-both"};return function(b){return a[(""+b).toLowerCase()]}}(),size_font:function(){var a={1:"wysiwyg-font-size-xx-small",2:"wysiwyg-font-size-small",3:"wysiwyg-font-size-medium",4:"wysiwyg-font-size-large",5:"wysiwyg-font-size-x-large", +6:"wysiwyg-font-size-xx-large",7:"wysiwyg-font-size-xx-large","-":"wysiwyg-font-size-smaller","+":"wysiwyg-font-size-larger"};return function(b){return a[(""+b).charAt(0)]}}()};return function(a,c,d,e){wysihtml5.lang.object(g).merge(f).merge(c).get();for(var d=d||a.ownerDocument||document,c=d.createDocumentFragment(),h="string"===typeof a,a=h?wysihtml5.dom.getAsDom(a,d):a;a.firstChild;)d=a.firstChild,a.removeChild(d),(d=b(d,e))&&c.appendChild(d);a.innerHTML="";a.appendChild(c);return h?wysihtml5.quirks.getCorrectInnerHTML(a): +a}}();wysihtml5.dom.removeEmptyTextNodes=function(b){for(var c=wysihtml5.lang.array(b.childNodes).get(),a=c.length,d=0;d<a;d++)b=c[d],b.nodeType===wysihtml5.TEXT_NODE&&""===b.data&&b.parentNode.removeChild(b)};wysihtml5.dom.renameElement=function(b,c){for(var a=b.ownerDocument.createElement(c),d;d=b.firstChild;)a.appendChild(d);wysihtml5.dom.copyAttributes(["align","className"]).from(b).to(a);b.parentNode.replaceChild(a,b);return a}; +wysihtml5.dom.replaceWithChildNodes=function(b){if(b.parentNode)if(b.firstChild){for(var c=b.ownerDocument.createDocumentFragment();b.firstChild;)c.appendChild(b.firstChild);b.parentNode.replaceChild(c,b)}else b.parentNode.removeChild(b)}; +(function(b){function c(a){var b=a.ownerDocument.createElement("br");a.appendChild(b)}b.resolveList=function(a){if(!("MENU"!==a.nodeName&&"UL"!==a.nodeName&&"OL"!==a.nodeName)){var d=a.ownerDocument.createDocumentFragment(),e=a.previousElementSibling||a.previousSibling,f,g,i;for(e&&"block"!==b.getStyle("display").from(e)&&c(d);i=a.firstChild;){for(f=i.lastChild;e=i.firstChild;)g=(g=e===f)&&"block"!==b.getStyle("display").from(e)&&"BR"!==e.nodeName,d.appendChild(e),g&&c(d);i.parentNode.removeChild(i)}a.parentNode.replaceChild(d, +a)}}})(wysihtml5.dom); +(function(b){var c=document,a="parent top opener frameElement frames localStorage globalStorage sessionStorage indexedDB".split(" "),d="open close openDialog showModalDialog alert confirm prompt openDatabase postMessage XMLHttpRequest XDomainRequest".split(" "),e=["referrer","write","open","close"];b.dom.Sandbox=Base.extend({constructor:function(a,c){this.callback=a||b.EMPTY_FUNCTION;this.config=b.lang.object({}).merge(c).get();this.iframe=this._createIframe()},insertInto:function(a){"string"===typeof a&& +(a=c.getElementById(a));a.appendChild(this.iframe)},getIframe:function(){return this.iframe},getWindow:function(){this._readyError()},getDocument:function(){this._readyError()},destroy:function(){var a=this.getIframe();a.parentNode.removeChild(a)},_readyError:function(){throw Error("wysihtml5.Sandbox: Sandbox iframe isn't loaded yet");},_createIframe:function(){var a=this,d=c.createElement("iframe");d.className="wysihtml5-sandbox";b.dom.setAttributes({security:"restricted",allowtransparency:"true", +frameborder:0,width:0,height:0,marginwidth:0,marginheight:0}).on(d);b.browser.throwsMixedContentWarningWhenIframeSrcIsEmpty()&&(d.src="javascript:'<html></html>'");d.onload=function(){d.onreadystatechange=d.onload=null;a._onLoadIframe(d)};d.onreadystatechange=function(){if(/loaded|complete/.test(d.readyState)){d.onreadystatechange=d.onload=null;a._onLoadIframe(d)}};return d},_onLoadIframe:function(f){if(b.dom.contains(c.documentElement,f)){var g=this,i=f.contentWindow,h=f.contentWindow.document,k= +this._getHtml({charset:c.characterSet||c.charset||"utf-8",stylesheets:this.config.stylesheets});h.open("text/html","replace");h.write(k);h.close();this.getWindow=function(){return f.contentWindow};this.getDocument=function(){return f.contentWindow.document};i.onerror=function(a,b,c){throw Error("wysihtml5.Sandbox: "+a,b,c);};if(!b.browser.supportsSandboxedIframes()){var j,k=0;for(j=a.length;k<j;k++)this._unset(i,a[k]);k=0;for(j=d.length;k<j;k++)this._unset(i,d[k],b.EMPTY_FUNCTION);k=0;for(j=e.length;k< +j;k++)this._unset(h,e[k]);this._unset(h,"cookie","",!0)}this.loaded=!0;setTimeout(function(){g.callback(g)},0)}},_getHtml:function(a){var c=a.stylesheets,d="",e=0,k;if(c="string"===typeof c?[c]:c)for(k=c.length;e<k;e++)d+='<link rel="stylesheet" href="'+c[e]+'">';a.stylesheets=d;return b.lang.string('<!DOCTYPE html><html><head><meta charset="#{charset}">#{stylesheets}</head><body></body></html>').interpolate(a)},_unset:function(a,c,d,e){try{a[c]=d}catch(k){}try{a.__defineGetter__(c,function(){return d})}catch(j){}if(e)try{a.__defineSetter__(c, +function(){})}catch(n){}if(!b.browser.crashesWhenDefineProperty(c))try{var p={get:function(){return d}};e&&(p.set=function(){});Object.defineProperty(a,c,p)}catch(q){}}})})(wysihtml5);(function(){var b={className:"class"};wysihtml5.dom.setAttributes=function(c){return{on:function(a){for(var d in c)a.setAttribute(b[d]||d,c[d])}}}})(); +wysihtml5.dom.setStyles=function(b){return{on:function(c){c=c.style;if("string"===typeof b)c.cssText+=";"+b;else for(var a in b)"float"===a?(c.cssFloat=b[a],c.styleFloat=b[a]):c[a]=b[a]}}}; +(function(b){b.simulatePlaceholder=function(c,a,d){var e=function(){a.hasPlaceholderSet()&&a.clear();b.removeClass(a.element,"placeholder")},f=function(){a.isEmpty()&&(a.setValue(d),b.addClass(a.element,"placeholder"))};c.observe("set_placeholder",f).observe("unset_placeholder",e).observe("focus:composer",e).observe("paste:composer",e).observe("blur:composer",f);f()}})(wysihtml5.dom); +(function(b){var c=document.documentElement;"textContent"in c?(b.setTextContent=function(a,b){a.textContent=b},b.getTextContent=function(a){return a.textContent}):"innerText"in c?(b.setTextContent=function(a,b){a.innerText=b},b.getTextContent=function(a){return a.innerText}):(b.setTextContent=function(a,b){a.nodeValue=b},b.getTextContent=function(a){return a.nodeValue})})(wysihtml5.dom); +wysihtml5.quirks.cleanPastedHTML=function(){var b={"a u":wysihtml5.dom.replaceWithChildNodes};return function(c,a,d){var a=a||b,d=d||c.ownerDocument||document,e="string"===typeof c,f,g,i,h=0,c=e?wysihtml5.dom.getAsDom(c,d):c;for(i in a){f=c.querySelectorAll(i);d=a[i];for(g=f.length;h<g;h++)d(f[h])}return e?c.innerHTML:c}}(); +(function(b){var c=b.dom;b.quirks.ensureProperClearing=function(){var a=function(){var a=this;setTimeout(function(){var b=a.innerHTML.toLowerCase();if("<p>&nbsp;</p>"==b||"<p>&nbsp;</p><p>&nbsp;</p>"==b)a.innerHTML=""},0)};return function(b){c.observe(b.element,["cut","keydown"],a)}}();b.quirks.ensureProperClearingOfLists=function(){var a=["OL","UL","MENU"];return function(d){c.observe(d.element,"keydown",function(e){if(e.keyCode===b.BACKSPACE_KEY){var f=d.selection.getSelectedNode(),e=d.element; +e.firstChild&&b.lang.array(a).contains(e.firstChild.nodeName)&&(f=c.getParentElement(f,{nodeName:a}))&&f==e.firstChild&&1>=f.childNodes.length&&(f.firstChild?""===f.firstChild.innerHTML:1)&&f.parentNode.removeChild(f)}})}}()})(wysihtml5); +(function(b){b.quirks.getCorrectInnerHTML=function(c){var a=c.innerHTML;if(-1===a.indexOf("%7E"))return a;var c=c.querySelectorAll("[href*='~'], [src*='~']"),d,e,f,g;g=0;for(f=c.length;g<f;g++)d=c[g].href||c[g].src,e=b.lang.string(d).replace("~").by("%7E"),a=b.lang.string(a).replace(e).by(d);return a}})(wysihtml5); +(function(b){var c=b.dom,a="LI P H1 H2 H3 H4 H5 H6".split(" "),d=["UL","OL","MENU"];b.quirks.insertLineBreakOnReturn=function(e){function f(a){if(a=c.getParentElement(a,{nodeName:["P","DIV"]},2)){var d=document.createTextNode(b.INVISIBLE_SPACE);c.insert(d).before(a);c.replaceWithChildNodes(a);e.selection.selectNode(d)}}c.observe(e.element.ownerDocument,"keydown",function(g){var i=g.keyCode;if(!(g.shiftKey||i!==b.ENTER_KEY&&i!==b.BACKSPACE_KEY)){var h=e.selection.getSelectedNode();(h=c.getParentElement(h, +{nodeName:a},4))?"LI"===h.nodeName&&(i===b.ENTER_KEY||i===b.BACKSPACE_KEY)?setTimeout(function(){var a=e.selection.getSelectedNode(),b;a&&((b=c.getParentElement(a,{nodeName:d},2))||f(a))},0):h.nodeName.match(/H[1-6]/)&&i===b.ENTER_KEY&&setTimeout(function(){f(e.selection.getSelectedNode())},0):i===b.ENTER_KEY&&!b.browser.insertsLineBreaksOnReturn()&&(e.commands.exec("insertLineBreak"),g.preventDefault())}})}})(wysihtml5); +(function(b){b.quirks.redraw=function(c){b.dom.addClass(c,"wysihtml5-quirks-redraw");b.dom.removeClass(c,"wysihtml5-quirks-redraw");try{var a=c.ownerDocument;a.execCommand("italic",!1,null);a.execCommand("italic",!1,null)}catch(d){}}})(wysihtml5); +(function(b){var c=b.dom;b.Selection=Base.extend({constructor:function(a){window.rangy.init();this.editor=a;this.composer=a.composer;this.doc=this.composer.doc},getBookmark:function(){var a=this.getRange();return a&&a.cloneRange()},setBookmark:function(a){a&&this.setSelection(a)},setBefore:function(a){var b=rangy.createRange(this.doc);b.setStartBefore(a);b.setEndBefore(a);return this.setSelection(b)},setAfter:function(a){var b=rangy.createRange(this.doc);b.setStartAfter(a);b.setEndAfter(a);return this.setSelection(b)}, +selectNode:function(a){var d=rangy.createRange(this.doc),e=a.nodeType===b.ELEMENT_NODE,f="canHaveHTML"in a?a.canHaveHTML:"IMG"!==a.nodeName,g=e?a.innerHTML:a.data,g=""===g||g===b.INVISIBLE_SPACE,i=c.getStyle("display").from(a),i="block"===i||"list-item"===i;if(g&&e&&f)try{a.innerHTML=b.INVISIBLE_SPACE}catch(h){}f?d.selectNodeContents(a):d.selectNode(a);f&&g&&e?d.collapse(i):f&&g&&(d.setStartAfter(a),d.setEndAfter(a));this.setSelection(d)},getSelectedNode:function(a){if(a&&this.doc.selection&&"Control"=== +this.doc.selection.type&&(a=this.doc.selection.createRange())&&a.length)return a.item(0);a=this.getSelection(this.doc);return a.focusNode===a.anchorNode?a.focusNode:(a=this.getRange(this.doc))?a.commonAncestorContainer:this.doc.body},executeAndRestore:function(a,c){var e=this.doc.body,f=c&&e.scrollTop,g=c&&e.scrollLeft,i='<span class="_wysihtml5-temp-placeholder">'+b.INVISIBLE_SPACE+"</span>",h=this.getRange(this.doc);if(h){i=h.createContextualFragment(i);h.insertNode(i);try{a(h.startContainer,h.endContainer)}catch(k){setTimeout(function(){throw k; +},0)}(caretPlaceholder=this.doc.querySelector("._wysihtml5-temp-placeholder"))?(h=rangy.createRange(this.doc),h.selectNode(caretPlaceholder),h.deleteContents(),this.setSelection(h)):e.focus();c&&(e.scrollTop=f,e.scrollLeft=g);try{caretPlaceholder.parentNode.removeChild(caretPlaceholder)}catch(j){}}else a(e,e)},executeAndRestoreSimple:function(a){var b,c,f=this.getRange(),g=this.doc.body,i;if(f){b=f.getNodes([3]);g=b[0]||f.startContainer;i=b[b.length-1]||f.endContainer;b=g===f.startContainer?f.startOffset: +0;c=i===f.endContainer?f.endOffset:i.length;try{a(f.startContainer,f.endContainer)}catch(h){setTimeout(function(){throw h;},0)}a=rangy.createRange(this.doc);try{a.setStart(g,b)}catch(k){}try{a.setEnd(i,c)}catch(j){}try{this.setSelection(a)}catch(n){}}else a(g,g)},insertHTML:function(a){var a=rangy.createRange(this.doc).createContextualFragment(a),b=a.lastChild;this.insertNode(a);b&&this.setAfter(b)},insertNode:function(a){var b=this.getRange();b&&b.insertNode(a)},surround:function(a){var b=this.getRange(); +if(b)try{b.surroundContents(a),this.selectNode(a)}catch(c){a.appendChild(b.extractContents()),b.insertNode(a)}},scrollIntoView:function(){var a=this.doc,c=a.documentElement.scrollHeight>a.documentElement.offsetHeight,e;if(!(e=a._wysihtml5ScrollIntoViewElement))e=a.createElement("span"),e.innerHTML=b.INVISIBLE_SPACE;e=a._wysihtml5ScrollIntoViewElement=e;if(c){this.insertNode(e);var c=e,f=0;if(c.parentNode){do f+=c.offsetTop||0,c=c.offsetParent;while(c)}c=f;e.parentNode.removeChild(e);c>a.body.scrollTop&& +(a.body.scrollTop=c)}},selectLine:function(){b.browser.supportsSelectionModify()?this._selectLine_W3C():this.doc.selection&&this._selectLine_MSIE()},_selectLine_W3C:function(){var a=this.doc.defaultView.getSelection();a.modify("extend","left","lineboundary");a.modify("extend","right","lineboundary")},_selectLine_MSIE:function(){var a=this.doc.selection.createRange(),b=a.boundingTop,c=this.doc.body.scrollWidth,f;if(a.moveToPoint){0===b&&(f=this.doc.createElement("span"),this.insertNode(f),b=f.offsetTop, +f.parentNode.removeChild(f));b+=1;for(f=-10;f<c;f+=2)try{a.moveToPoint(f,b);break}catch(g){}for(f=this.doc.selection.createRange();0<=c;c--)try{f.moveToPoint(c,b);break}catch(i){}a.setEndPoint("EndToEnd",f);a.select()}},getText:function(){var a=this.getSelection();return a?a.toString():""},getNodes:function(a,b){var c=this.getRange();return c?c.getNodes([a],b):[]},getRange:function(){var a=this.getSelection();return a&&a.rangeCount&&a.getRangeAt(0)},getSelection:function(){return rangy.getSelection(this.doc.defaultView|| +this.doc.parentWindow)},setSelection:function(a){return rangy.getSelection(this.doc.defaultView||this.doc.parentWindow).setSingleRange(a)}})})(wysihtml5); +(function(b,c){function a(a,b){return c.dom.isCharacterDataNode(a)?0==b?!!a.previousSibling:b==a.length?!!a.nextSibling:!0:0<b&&b<a.childNodes.length}function d(a,b,e){var f;c.dom.isCharacterDataNode(b)&&(0==e?(e=c.dom.getNodeIndex(b),b=b.parentNode):e==b.length?(e=c.dom.getNodeIndex(b)+1,b=b.parentNode):f=c.dom.splitDataNode(b,e));if(!f){f=b.cloneNode(!1);f.id&&f.removeAttribute("id");for(var g;g=b.childNodes[e];)f.appendChild(g);c.dom.insertAfter(f,b)}return b==a?f:d(a,f.parentNode,c.dom.getNodeIndex(f))} +function e(a){this.firstTextNode=(this.isElementMerge=a.nodeType==b.ELEMENT_NODE)?a.lastChild:a;this.textNodes=[this.firstTextNode]}function f(a,b,c,d){this.tagNames=a||[g];this.cssClass=b||"";this.similarClassRegExp=c;this.normalize=d;this.applyToAnyTagName=!1}var g="span",i=/\s+/g;e.prototype={doMerge:function(){for(var a=[],b,c,d=0,e=this.textNodes.length;d<e;++d)b=this.textNodes[d],c=b.parentNode,a[d]=b.data,d&&(c.removeChild(b),c.hasChildNodes()||c.parentNode.removeChild(c));return this.firstTextNode.data= +a=a.join("")},getLength:function(){for(var a=this.textNodes.length,b=0;a--;)b+=this.textNodes[a].length;return b},toString:function(){for(var a=[],b=0,c=this.textNodes.length;b<c;++b)a[b]="'"+this.textNodes[b].data+"'";return"[Merge("+a.join(",")+")]"}};f.prototype={getAncestorWithClass:function(a){for(var d;a;){if(this.cssClass)if(d=this.cssClass,a.className){var e=a.className.match(this.similarClassRegExp)||[];d=e[e.length-1]===d}else d=!1;else d=!0;if(a.nodeType==b.ELEMENT_NODE&&c.dom.arrayContains(this.tagNames, +a.tagName.toLowerCase())&&d)return a;a=a.parentNode}return!1},postApply:function(a,b){for(var c=a[0],d=a[a.length-1],f=[],g,i=c,m=d,s=0,x=d.length,o,z,w=0,y=a.length;w<y;++w)if(o=a[w],z=this.getAdjacentMergeableTextNode(o.parentNode,!1)){if(g||(g=new e(z),f.push(g)),g.textNodes.push(o),o===c&&(i=g.firstTextNode,s=i.length),o===d)m=g.firstTextNode,x=g.getLength()}else g=null;if(c=this.getAdjacentMergeableTextNode(d.parentNode,!0))g||(g=new e(d),f.push(g)),g.textNodes.push(c);if(f.length){w=0;for(y= +f.length;w<y;++w)f[w].doMerge();b.setStart(i,s);b.setEnd(m,x)}},getAdjacentMergeableTextNode:function(a,c){var d=a.nodeType==b.TEXT_NODE,e=d?a.parentNode:a,f=c?"nextSibling":"previousSibling";if(d){if((d=a[f])&&d.nodeType==b.TEXT_NODE)return d}else if((d=e[f])&&this.areElementsMergeable(a,d))return d[c?"firstChild":"lastChild"];return null},areElementsMergeable:function(a,b){var d;if(d=c.dom.arrayContains(this.tagNames,(a.tagName||"").toLowerCase()))if(d=c.dom.arrayContains(this.tagNames,(b.tagName|| +"").toLowerCase()))if(d=a.className.replace(i," ")==b.className.replace(i," "))a:if(a.attributes.length!=b.attributes.length)d=!1;else{d=0;for(var e=a.attributes.length,f,g;d<e;++d)if(f=a.attributes[d],g=f.name,"class"!=g&&(g=b.attributes.getNamedItem(g),f.specified!=g.specified||f.specified&&f.nodeValue!==g.nodeValue)){d=!1;break a}d=!0}return d},createContainer:function(a){a=a.createElement(this.tagNames[0]);this.cssClass&&(a.className=this.cssClass);return a},applyToTextNode:function(a){var b= +a.parentNode;1==b.childNodes.length&&c.dom.arrayContains(this.tagNames,b.tagName.toLowerCase())?this.cssClass&&(a=this.cssClass,b.className?(b.className&&(b.className=b.className.replace(this.similarClassRegExp,"")),b.className+=" "+a):b.className=a):(b=this.createContainer(c.dom.getDocument(a)),a.parentNode.insertBefore(b,a),b.appendChild(a))},isRemovable:function(a){return c.dom.arrayContains(this.tagNames,a.tagName.toLowerCase())&&b.lang.string(a.className).trim()==this.cssClass},undoToTextNode:function(b, +c,e){c.containsNode(e)||(b=c.cloneRange(),b.selectNode(e),b.isPointInRange(c.endContainer,c.endOffset)&&a(c.endContainer,c.endOffset)&&(d(e,c.endContainer,c.endOffset),c.setEndAfter(e)),b.isPointInRange(c.startContainer,c.startOffset)&&a(c.startContainer,c.startOffset)&&(e=d(e,c.startContainer,c.startOffset)));this.similarClassRegExp&&e.className&&(e.className=e.className.replace(this.similarClassRegExp,""));if(this.isRemovable(e)){c=e;for(e=c.parentNode;c.firstChild;)e.insertBefore(c.firstChild, +c);e.removeChild(c)}},applyToRange:function(a){var c=a.getNodes([b.TEXT_NODE]);if(!c.length)try{var d=this.createContainer(a.endContainer.ownerDocument);a.surroundContents(d);this.selectNode(a,d);return}catch(e){}a.splitBoundaries();c=a.getNodes([b.TEXT_NODE]);if(c.length){for(var f=0,g=c.length;f<g;++f)d=c[f],this.getAncestorWithClass(d)||this.applyToTextNode(d);a.setStart(c[0],0);d=c[c.length-1];a.setEnd(d,d.length);this.normalize&&this.postApply(c,a)}},undoToRange:function(a){var c=a.getNodes([b.TEXT_NODE]), +d,e;c.length?(a.splitBoundaries(),c=a.getNodes([b.TEXT_NODE])):(c=a.endContainer.ownerDocument.createTextNode(b.INVISIBLE_SPACE),a.insertNode(c),a.selectNode(c),c=[c]);for(var f=0,g=c.length;f<g;++f)d=c[f],(e=this.getAncestorWithClass(d))&&this.undoToTextNode(d,a,e);1==g?this.selectNode(a,c[0]):(a.setStart(c[0],0),d=c[c.length-1],a.setEnd(d,d.length),this.normalize&&this.postApply(c,a))},selectNode:function(a,c){var d=c.nodeType===b.ELEMENT_NODE,e="canHaveHTML"in c?c.canHaveHTML:!0,f=d?c.innerHTML: +c.data;if((f=""===f||f===b.INVISIBLE_SPACE)&&d&&e)try{c.innerHTML=b.INVISIBLE_SPACE}catch(g){}a.selectNodeContents(c);f&&d?a.collapse(!1):f&&(a.setStartAfter(c),a.setEndAfter(c))},getTextSelectedByRange:function(a,b){var c=b.cloneRange();c.selectNodeContents(a);var d=c.intersection(b),d=d?d.toString():"";c.detach();return d},isAppliedToRange:function(a){var c=[],d,e=a.getNodes([b.TEXT_NODE]);if(!e.length)return(d=this.getAncestorWithClass(a.startContainer))?[d]:!1;for(var f=0,g=e.length,i;f<g;++f){i= +this.getTextSelectedByRange(e[f],a);d=this.getAncestorWithClass(e[f]);if(""!=i&&!d)return!1;c.push(d)}return c},toggleRange:function(a){this.isAppliedToRange(a)?this.undoToRange(a):this.applyToRange(a)}};b.selection.HTMLApplier=f})(wysihtml5,rangy); +wysihtml5.Commands=Base.extend({constructor:function(b){this.editor=b;this.composer=b.composer;this.doc=this.composer.doc},support:function(b){return wysihtml5.browser.supportsCommand(this.doc,b)},exec:function(b,c){var a=wysihtml5.commands[b],d=wysihtml5.lang.array(arguments).get(),e=a&&a.exec,f=null;this.editor.fire("beforecommand:composer");if(e)d.unshift(this.composer),f=e.apply(a,d);else try{f=this.doc.execCommand(b,!1,c)}catch(g){}this.editor.fire("aftercommand:composer");return f},state:function(b, +c){var a=wysihtml5.commands[b],d=wysihtml5.lang.array(arguments).get(),e=a&&a.state;if(e)return d.unshift(this.composer),e.apply(a,d);try{return this.doc.queryCommandState(b)}catch(f){return!1}},value:function(b){var c=wysihtml5.commands[b],a=c&&c.value;if(a)return a.call(c,this.composer,b);try{return this.doc.queryCommandValue(b)}catch(d){return null}}}); +(function(b){b.commands.bold={exec:function(c,a){return b.commands.formatInline.exec(c,a,"b")},state:function(c,a){return b.commands.formatInline.state(c,a,"b")},value:function(){}}})(wysihtml5); +(function(b){function c(c,g){var i=c.doc,h="_wysihtml5-temp-"+ +new Date,k=0,j,n,p;b.commands.formatInline.exec(c,a,d,h,/non-matching-class/g);j=i.querySelectorAll(d+"."+h);for(h=j.length;k<h;k++)for(p in n=j[k],n.removeAttribute("class"),g)n.setAttribute(p,g[p]);k=n;1===h&&(p=e.getTextContent(n),h=!!n.querySelector("*"),p=""===p||p===b.INVISIBLE_SPACE,!h&&p&&(e.setTextContent(n,g.text||n.href),i=i.createTextNode(" "),c.selection.setAfter(n),c.selection.insertNode(i),k=i));c.selection.setAfter(k)} +var a,d="A",e=b.dom;b.commands.createLink={exec:function(a,b,d){var h=this.state(a,b);h?a.selection.executeAndRestore(function(){for(var a=h.length,b=0,c,d,f;b<a;b++)c=h[b],d=e.getParentElement(c,{nodeName:"code"}),f=e.getTextContent(c),f.match(e.autoLink.URL_REG_EXP)&&!d?e.renameElement(c,"code"):e.replaceWithChildNodes(c)}):(d="object"===typeof d?d:{href:d},c(a,d))},state:function(a,c){return b.commands.formatInline.state(a,c,"A")},value:function(){return a}}})(wysihtml5); +(function(b){var c=/wysiwyg-font-size-[a-z\-]+/g;b.commands.fontSize={exec:function(a,d,e){return b.commands.formatInline.exec(a,d,"span","wysiwyg-font-size-"+e,c)},state:function(a,d,e){return b.commands.formatInline.state(a,d,"span","wysiwyg-font-size-"+e,c)},value:function(){}}})(wysihtml5); +(function(b){var c=/wysiwyg-color-[a-z]+/g;b.commands.foreColor={exec:function(a,d,e){return b.commands.formatInline.exec(a,d,"span","wysiwyg-color-"+e,c)},state:function(a,d,e){return b.commands.formatInline.state(a,d,"span","wysiwyg-color-"+e,c)},value:function(){}}})(wysihtml5); +(function(b){function c(a){for(a=a.previousSibling;a&&a.nodeType===b.TEXT_NODE&&!b.lang.string(a.data).trim();)a=a.previousSibling;return a}function a(a){for(a=a.nextSibling;a&&a.nodeType===b.TEXT_NODE&&!b.lang.string(a.data).trim();)a=a.nextSibling;return a}function d(a){return"BR"===a.nodeName||"block"===g.getStyle("display").from(a)?!0:!1}function e(a,c,d,e){if(e)var f=g.observe(a,"DOMNodeInserted",function(a){var a=a.target,c;a.nodeType===b.ELEMENT_NODE&&(c=g.getStyle("display").from(a),"inline"!== +c.substr(0,6)&&(a.className+=" "+e))});a.execCommand(c,!1,d);f&&f.stop()}function f(b,d){b.selection.selectLine();b.selection.surround(d);var e=a(d),f=c(d);e&&"BR"===e.nodeName&&e.parentNode.removeChild(e);f&&"BR"===f.nodeName&&f.parentNode.removeChild(f);(e=d.lastChild)&&"BR"===e.nodeName&&e.parentNode.removeChild(e);b.selection.selectNode(d)}var g=b.dom,i="H1 H2 H3 H4 H5 H6 P BLOCKQUOTE DIV".split(" ");b.commands.formatBlock={exec:function(h,k,j,n,p){var q=h.doc,r=this.state(h,k,j,n,p),m,j="string"=== +typeof j?j.toUpperCase():j;if(r)h.selection.executeAndRestoreSimple(function(){p&&(r.className=r.className.replace(p,""));var e=!!b.lang.string(r.className).trim();if(!e&&r.nodeName===(j||"DIV")){var e=r,f=e.ownerDocument,h=a(e),i=c(e);h&&!d(h)&&e.parentNode.insertBefore(f.createElement("br"),h);i&&!d(i)&&e.parentNode.insertBefore(f.createElement("br"),e);g.replaceWithChildNodes(r)}else e&&g.renameElement(r,"DIV")});else{if(null===j||b.lang.array(i).contains(j))if(m=h.selection.getSelectedNode(), +r=g.getParentElement(m,{nodeName:i})){h.selection.executeAndRestoreSimple(function(){j&&(r=g.renameElement(r,j));if(n){var a=r;a.className?(a.className=a.className.replace(p,""),a.className+=" "+n):a.className=n}});return}h.commands.support(k)?e(q,k,j||"DIV",n):(r=q.createElement(j||"DIV"),n&&(r.className=n),f(h,r))}},state:function(a,b,c,d,e){c="string"===typeof c?c.toUpperCase():c;a=a.selection.getSelectedNode();return g.getParentElement(a,{nodeName:c,className:d,classRegExp:e})},value:function(){}}})(wysihtml5); +(function(b){function c(c,f,g){var i=c+":"+f;if(!d[i]){var h=d,k=b.selection.HTMLApplier,j=a[c],c=j?[c.toLowerCase(),j.toLowerCase()]:[c.toLowerCase()];h[i]=new k(c,f,g,!0)}return d[i]}var a={strong:"b",em:"i",b:"strong",i:"em"},d={};b.commands.formatInline={exec:function(a,b,d,i,h){b=a.selection.getRange();if(!b)return!1;c(d,i,h).toggleRange(b);a.selection.setSelection(b)},state:function(d,f,g,i,h){var f=d.doc,k=a[g]||g;if(!b.dom.hasElementWithTagName(f,g)&&!b.dom.hasElementWithTagName(f,k)||i&& +!b.dom.hasElementWithClassName(f,i))return!1;d=d.selection.getRange();return!d?!1:c(g,i,h).isAppliedToRange(d)},value:function(){}}})(wysihtml5);(function(b){b.commands.insertHTML={exec:function(b,a,d){b.commands.support(a)?b.doc.execCommand(a,!1,d):b.selection.insertHTML(d)},state:function(){return!1},value:function(){}}})(wysihtml5); +(function(b){b.commands.insertImage={exec:function(c,a,d){var d="object"===typeof d?d:{src:d},e=c.doc,a=this.state(c),f;if(a)c.selection.setBefore(a),d=a.parentNode,d.removeChild(a),b.dom.removeEmptyTextNodes(d),"A"===d.nodeName&&!d.firstChild&&(c.selection.setAfter(d),d.parentNode.removeChild(d)),b.quirks.redraw(c.element);else{a=e.createElement("IMG");for(f in d)a[f]=d[f];c.selection.insertNode(a);b.browser.hasProblemsSettingCaretAfterImg()?(d=e.createTextNode(b.INVISIBLE_SPACE),c.selection.insertNode(d), +c.selection.setAfter(d)):c.selection.setAfter(a)}},state:function(c){var a;if(!b.dom.hasElementWithTagName(c.doc,"IMG"))return!1;a=c.selection.getSelectedNode();if(!a)return!1;if("IMG"===a.nodeName)return a;if(a.nodeType!==b.ELEMENT_NODE)return!1;a=c.selection.getText();if(a=b.lang.string(a).trim())return!1;c=c.selection.getNodes(b.ELEMENT_NODE,function(a){return"IMG"===a.nodeName});return 1!==c.length?!1:c[0]},value:function(b){return(b=this.state(b))&&b.src}}})(wysihtml5); +(function(b){var c="<br>"+(b.browser.needsSpaceAfterLineBreak()?" ":"");b.commands.insertLineBreak={exec:function(a,d){a.commands.support(d)?(a.doc.execCommand(d,!1,null),b.browser.autoScrollsToCaret()||a.selection.scrollIntoView()):a.commands.exec("insertHTML",c)},state:function(){return!1},value:function(){}}})(wysihtml5); +(function(b){b.commands.insertOrderedList={exec:function(c,a){var d=c.doc,e=c.selection.getSelectedNode(),f=b.dom.getParentElement(e,{nodeName:"OL"}),g=b.dom.getParentElement(e,{nodeName:"UL"}),e="_wysihtml5-temp-"+(new Date).getTime(),i;c.commands.support(a)?d.execCommand(a,!1,null):f?c.selection.executeAndRestoreSimple(function(){b.dom.resolveList(f)}):g?c.selection.executeAndRestoreSimple(function(){b.dom.renameElement(g,"ol")}):(c.commands.exec("formatBlock","div",e),i=d.querySelector("."+e), +d=""===i.innerHTML||i.innerHTML===b.INVISIBLE_SPACE,c.selection.executeAndRestoreSimple(function(){f=b.dom.convertToList(i,"ol")}),d&&c.selection.selectNode(f.querySelector("li")))},state:function(c){c=c.selection.getSelectedNode();return b.dom.getParentElement(c,{nodeName:"OL"})},value:function(){}}})(wysihtml5); +(function(b){b.commands.insertUnorderedList={exec:function(c,a){var d=c.doc,e=c.selection.getSelectedNode(),f=b.dom.getParentElement(e,{nodeName:"UL"}),g=b.dom.getParentElement(e,{nodeName:"OL"}),e="_wysihtml5-temp-"+(new Date).getTime(),i;c.commands.support(a)?d.execCommand(a,!1,null):f?c.selection.executeAndRestoreSimple(function(){b.dom.resolveList(f)}):g?c.selection.executeAndRestoreSimple(function(){b.dom.renameElement(g,"ul")}):(c.commands.exec("formatBlock","div",e),i=d.querySelector("."+e), +d=""===i.innerHTML||i.innerHTML===b.INVISIBLE_SPACE,c.selection.executeAndRestoreSimple(function(){f=b.dom.convertToList(i,"ul")}),d&&c.selection.selectNode(f.querySelector("li")))},state:function(c){c=c.selection.getSelectedNode();return b.dom.getParentElement(c,{nodeName:"UL"})},value:function(){}}})(wysihtml5);(function(b){b.commands.italic={exec:function(c,a){return b.commands.formatInline.exec(c,a,"i")},state:function(c,a){return b.commands.formatInline.state(c,a,"i")},value:function(){}}})(wysihtml5); +(function(b){var c=/wysiwyg-text-align-[a-z]+/g;b.commands.justifyCenter={exec:function(a){return b.commands.formatBlock.exec(a,"formatBlock",null,"wysiwyg-text-align-center",c)},state:function(a){return b.commands.formatBlock.state(a,"formatBlock",null,"wysiwyg-text-align-center",c)},value:function(){}}})(wysihtml5); +(function(b){var c=/wysiwyg-text-align-[a-z]+/g;b.commands.justifyLeft={exec:function(a){return b.commands.formatBlock.exec(a,"formatBlock",null,"wysiwyg-text-align-left",c)},state:function(a){return b.commands.formatBlock.state(a,"formatBlock",null,"wysiwyg-text-align-left",c)},value:function(){}}})(wysihtml5); +(function(b){var c=/wysiwyg-text-align-[a-z]+/g;b.commands.justifyRight={exec:function(a){return b.commands.formatBlock.exec(a,"formatBlock",null,"wysiwyg-text-align-right",c)},state:function(a){return b.commands.formatBlock.state(a,"formatBlock",null,"wysiwyg-text-align-right",c)},value:function(){}}})(wysihtml5);(function(b){b.commands.underline={exec:function(c,a){return b.commands.formatInline.exec(c,a,"u")},state:function(c,a){return b.commands.formatInline.state(c,a,"u")},value:function(){}}})(wysihtml5); +(function(b){var c='<span id="_wysihtml5-undo" class="_wysihtml5-temp">'+b.INVISIBLE_SPACE+"</span>",a='<span id="_wysihtml5-redo" class="_wysihtml5-temp">'+b.INVISIBLE_SPACE+"</span>",d=b.dom;b.UndoManager=b.lang.Dispatcher.extend({constructor:function(a){this.editor=a;this.composer=a.composer;this.element=this.composer.element;this.history=[this.composer.getValue()];this.position=1;this.composer.commands.support("insertHTML")&&this._observe()},_observe:function(){var e=this,f=this.composer.sandbox.getDocument(), +g;d.observe(this.element,"keydown",function(a){if(!(a.altKey||!a.ctrlKey&&!a.metaKey)){var b=a.keyCode,c=90===b&&a.shiftKey||89===b;90===b&&!a.shiftKey?(e.undo(),a.preventDefault()):c&&(e.redo(),a.preventDefault())}});d.observe(this.element,"keydown",function(a){a=a.keyCode;a!==g&&(g=a,(8===a||46===a)&&e.transact())});if(b.browser.hasUndoInContextMenu()){var i,h,k=function(){for(var a;a=f.querySelector("._wysihtml5-temp");)a.parentNode.removeChild(a);clearInterval(i)};d.observe(this.element,"contextmenu", +function(){k();e.composer.selection.executeAndRestoreSimple(function(){e.element.lastChild&&e.composer.selection.setAfter(e.element.lastChild);f.execCommand("insertHTML",!1,c);f.execCommand("insertHTML",!1,a);f.execCommand("undo",!1,null)});i=setInterval(function(){f.getElementById("_wysihtml5-redo")?(k(),e.redo()):f.getElementById("_wysihtml5-undo")||(k(),e.undo())},400);h||(h=!0,d.observe(document,"mousedown",k),d.observe(f,["mousedown","paste","cut","copy"],k))})}this.editor.observe("newword:composer", +function(){e.transact()}).observe("beforecommand:composer",function(){e.transact()})},transact:function(){var a=this.history[this.position-1],b=this.composer.getValue();if(b!=a){if(40<(this.history.length=this.position))this.history.shift(),this.position--;this.position++;this.history.push(b)}},undo:function(){this.transact();1>=this.position||(this.set(this.history[--this.position-1]),this.editor.fire("undo:composer"))},redo:function(){this.position>=this.history.length||(this.set(this.history[++this.position- +1]),this.editor.fire("redo:composer"))},set:function(a){this.composer.setValue(a);this.editor.focus(!0)}})})(wysihtml5); +wysihtml5.views.View=Base.extend({constructor:function(b,c,a){this.parent=b;this.element=c;this.config=a;this._observeViewChange()},_observeViewChange:function(){var b=this;this.parent.observe("beforeload",function(){b.parent.observe("change_view",function(c){c===b.name?(b.parent.currentView=b,b.show(),setTimeout(function(){b.focus()},0)):b.hide()})})},focus:function(){if(this.element.ownerDocument.querySelector(":focus")!==this.element)try{this.element.focus()}catch(b){}},hide:function(){this.element.style.display= +"none"},show:function(){this.element.style.display=""},disable:function(){this.element.setAttribute("disabled","disabled")},enable:function(){this.element.removeAttribute("disabled")}}); +(function(b){var c=b.dom,a=b.browser;b.views.Composer=b.views.View.extend({name:"composer",CARET_HACK:"<br>",constructor:function(a,b,c){this.base(a,b,c);this.textarea=this.parent.textarea;this._initSandbox()},clear:function(){this.element.innerHTML=a.displaysCaretInEmptyContentEditableCorrectly()?"":this.CARET_HACK},getValue:function(a){var c=this.isEmpty()?"":b.quirks.getCorrectInnerHTML(this.element);a&&(c=this.parent.parse(c));return c=b.lang.string(c).replace(b.INVISIBLE_SPACE).by("")},setValue:function(a, +b){b&&(a=this.parent.parse(a));this.element.innerHTML=a},show:function(){this.iframe.style.display=this._displayStyle||"";this.disable();this.enable()},hide:function(){this._displayStyle=c.getStyle("display").from(this.iframe);"none"===this._displayStyle&&(this._displayStyle=null);this.iframe.style.display="none"},disable:function(){this.element.removeAttribute("contentEditable");this.base()},enable:function(){this.element.setAttribute("contentEditable","true");this.base()},focus:function(a){b.browser.doesAsyncFocus()&& +this.hasPlaceholderSet()&&this.clear();this.base();var c=this.element.lastChild;a&&c&&("BR"===c.nodeName?this.selection.setBefore(this.element.lastChild):this.selection.setAfter(this.element.lastChild))},getTextContent:function(){return c.getTextContent(this.element)},hasPlaceholderSet:function(){return this.getTextContent()==this.textarea.element.getAttribute("placeholder")},isEmpty:function(){var a=this.element.innerHTML;return""===a||a===this.CARET_HACK||this.hasPlaceholderSet()||""===this.getTextContent()&& +!this.element.querySelector("blockquote, ul, ol, img, embed, object, table, iframe, svg, video, audio, button, input, select, textarea")},_initSandbox:function(){var a=this;this.sandbox=new c.Sandbox(function(){a._create()},{stylesheets:this.config.stylesheets});this.iframe=this.sandbox.getIframe();var b=document.createElement("input");b.type="hidden";b.name="_wysihtml5_mode";b.value=1;var f=this.textarea.element;c.insert(this.iframe).after(f);c.insert(b).after(f)},_create:function(){var d=this;this.doc= +this.sandbox.getDocument();this.element=this.doc.body;this.textarea=this.parent.textarea;this.element.innerHTML=this.textarea.getValue(!0);this.enable();this.selection=new b.Selection(this.parent);this.commands=new b.Commands(this.parent);c.copyAttributes("className spellcheck title lang dir accessKey".split(" ")).from(this.textarea.element).to(this.element);c.addClass(this.element,this.config.composerClassName);this.config.style&&this.style();this.observe();var e=this.config.name;e&&(c.addClass(this.element, +e),c.addClass(this.iframe,e));(e="string"===typeof this.config.placeholder?this.config.placeholder:this.textarea.element.getAttribute("placeholder"))&&c.simulatePlaceholder(this.parent,this,e);this.commands.exec("styleWithCSS",!1);this._initAutoLinking();this._initObjectResizing();this._initUndoManager();(this.textarea.element.hasAttribute("autofocus")||document.querySelector(":focus")==this.textarea.element)&&setTimeout(function(){d.focus()},100);b.quirks.insertLineBreakOnReturn(this);a.clearsContentEditableCorrectly()|| +b.quirks.ensureProperClearing(this);a.clearsListsInContentEditableCorrectly()||b.quirks.ensureProperClearingOfLists(this);this.initSync&&this.config.sync&&this.initSync();this.textarea.hide();this.parent.fire("beforeload").fire("load")},_initAutoLinking:function(){var d=this,e=a.canDisableAutoLinking(),f=a.doesAutoLinkingInContentEditable();e&&this.commands.exec("autoUrlDetect",!1);if(this.config.autoLink){(!f||f&&e)&&this.parent.observe("newword:composer",function(){d.selection.executeAndRestore(function(a, +b){c.autoLink(b.parentNode)})});var g=this.sandbox.getDocument().getElementsByTagName("a"),i=c.autoLink.URL_REG_EXP,h=function(a){a=b.lang.string(c.getTextContent(a)).trim();"www."===a.substr(0,4)&&(a="http://"+a);return a};c.observe(this.element,"keydown",function(a){if(g.length){var a=d.selection.getSelectedNode(a.target.ownerDocument),b=c.getParentElement(a,{nodeName:"A"},4),e;b&&(e=h(b),setTimeout(function(){var a=h(b);a!==e&&a.match(i)&&b.setAttribute("href",a)},0))}})}},_initObjectResizing:function(){var d= +["width","height"],e=d.length,f=this.element;this.commands.exec("enableObjectResizing",this.config.allowObjectResizing);this.config.allowObjectResizing?a.supportsEvent("resizeend")&&c.observe(f,"resizeend",function(a){for(var a=a.target||a.srcElement,c=a.style,h=0,k;h<e;h++)k=d[h],c[k]&&(a.setAttribute(k,parseInt(c[k],10)),c[k]="");b.quirks.redraw(f)}):a.supportsEvent("resizestart")&&c.observe(f,"resizestart",function(a){a.preventDefault()})},_initUndoManager:function(){new b.UndoManager(this.parent)}})})(wysihtml5); +(function(b){var c=b.dom,a=document,d=window,e=a.createElement("div"),f="background-color color cursor font-family font-size font-style font-variant font-weight line-height letter-spacing text-align text-decoration text-indent text-rendering word-break word-wrap word-spacing".split(" "),g="background-color border-collapse border-bottom-color border-bottom-style border-bottom-width border-left-color border-left-style border-left-width border-right-color border-right-style border-right-width border-top-color border-top-style border-top-width clear display float margin-bottom margin-left margin-right margin-top outline-color outline-offset outline-width outline-style padding-left padding-right padding-top padding-bottom position top left right bottom z-index vertical-align text-align -webkit-box-sizing -moz-box-sizing -ms-box-sizing box-sizing -webkit-box-shadow -moz-box-shadow -ms-box-shadow box-shadow -webkit-border-top-right-radius -moz-border-radius-topright border-top-right-radius -webkit-border-bottom-right-radius -moz-border-radius-bottomright border-bottom-right-radius -webkit-border-bottom-left-radius -moz-border-radius-bottomleft border-bottom-left-radius -webkit-border-top-left-radius -moz-border-radius-topleft border-top-left-radius width height".split(" "), +i="width height top left right bottom".split(" "),h=["html { height: 100%; }","body { min-height: 100%; padding: 0; margin: 0; margin-top: -1px; padding-top: 1px; }","._wysihtml5-temp { display: none; }",b.browser.isGecko?"body.placeholder { color: graytext !important; }":"body.placeholder { color: #a9a9a9 !important; }","body[disabled] { background-color: #eee !important; color: #999 !important; cursor: default !important; }","img:-moz-broken { -moz-force-broken-image-icon: 1; height: 24px; width: 24px; }"], +k=function(b){if(b.setActive)try{b.setActive()}catch(e){}else{var f=b.style,h=a.documentElement.scrollTop||a.body.scrollTop,g=a.documentElement.scrollLeft||a.body.scrollLeft,f={position:f.position,top:f.top,left:f.left,WebkitUserSelect:f.WebkitUserSelect};c.setStyles({position:"absolute",top:"-99999px",left:"-99999px",WebkitUserSelect:"none"}).on(b);b.focus();c.setStyles(f).on(b);d.scrollTo&&d.scrollTo(g,h)}};b.views.Composer.prototype.style=function(){var j=this,n=a.querySelector(":focus"),p=this.textarea.element, +q=p.hasAttribute("placeholder"),r=q&&p.getAttribute("placeholder");this.focusStylesHost=this.focusStylesHost||e.cloneNode(!1);this.blurStylesHost=this.blurStylesHost||e.cloneNode(!1);q&&p.removeAttribute("placeholder");p===n&&p.blur();c.copyStyles(g).from(p).to(this.iframe).andTo(this.blurStylesHost);c.copyStyles(f).from(p).to(this.element).andTo(this.blurStylesHost);c.insertCSS(h).into(this.element.ownerDocument);k(p);c.copyStyles(g).from(p).to(this.focusStylesHost);c.copyStyles(f).from(p).to(this.focusStylesHost); +var m=b.lang.array(g).without(["display"]);n?n.focus():p.blur();q&&p.setAttribute("placeholder",r);if(!b.browser.hasCurrentStyleProperty())var s=c.observe(d,"resize",function(){if(c.contains(document.documentElement,j.iframe)){var a=c.getStyle("display").from(p),b=c.getStyle("display").from(j.iframe);p.style.display="";j.iframe.style.display="none";c.copyStyles(i).from(p).to(j.iframe).andTo(j.focusStylesHost).andTo(j.blurStylesHost);j.iframe.style.display=b;p.style.display=a}else s.stop()});this.parent.observe("focus:composer", +function(){c.copyStyles(m).from(j.focusStylesHost).to(j.iframe);c.copyStyles(f).from(j.focusStylesHost).to(j.element)});this.parent.observe("blur:composer",function(){c.copyStyles(m).from(j.blurStylesHost).to(j.iframe);c.copyStyles(f).from(j.blurStylesHost).to(j.element)});return this}})(wysihtml5); +(function(b){var c=b.dom,a=b.browser,d={66:"bold",73:"italic",85:"underline"};b.views.Composer.prototype.observe=function(){var e=this,f=this.getValue(),g=this.sandbox.getIframe(),i=this.element,h=a.supportsEventsInIframeCorrectly()?i:this.sandbox.getWindow(),k=a.supportsEvent("drop")?["drop","paste"]:["dragdrop","paste"];c.observe(g,"DOMNodeRemoved",function(){clearInterval(j);e.parent.fire("destroy:composer")});var j=setInterval(function(){c.contains(document.documentElement,g)||(clearInterval(j), +e.parent.fire("destroy:composer"))},250);c.observe(h,"focus",function(){e.parent.fire("focus").fire("focus:composer");setTimeout(function(){f=e.getValue()},0)});c.observe(h,"blur",function(){f!==e.getValue()&&e.parent.fire("change").fire("change:composer");e.parent.fire("blur").fire("blur:composer")});b.browser.isIos()&&c.observe(i,"blur",function(){var a=i.ownerDocument.createElement("input"),b=document.documentElement.scrollTop||document.body.scrollTop,c=document.documentElement.scrollLeft||document.body.scrollLeft; +try{e.selection.insertNode(a)}catch(d){i.appendChild(a)}a.focus();a.parentNode.removeChild(a);window.scrollTo(c,b)});c.observe(i,"dragenter",function(){e.parent.fire("unset_placeholder")});a.firesOnDropOnlyWhenOnDragOverIsCancelled()&&c.observe(i,["dragover","dragenter"],function(a){a.preventDefault()});c.observe(i,k,function(b){var c=b.dataTransfer,d;c&&a.supportsDataTransfer()&&(d=c.getData("text/html")||c.getData("text/plain"));d?(i.focus(),e.commands.exec("insertHTML",d),e.parent.fire("paste").fire("paste:composer"), +b.stopPropagation(),b.preventDefault()):setTimeout(function(){e.parent.fire("paste").fire("paste:composer")},0)});c.observe(i,"keyup",function(a){a=a.keyCode;(a===b.SPACE_KEY||a===b.ENTER_KEY)&&e.parent.fire("newword:composer")});this.parent.observe("paste:composer",function(){setTimeout(function(){e.parent.fire("newword:composer")},0)});a.canSelectImagesInContentEditable()||c.observe(i,"mousedown",function(a){var b=a.target;"IMG"===b.nodeName&&(e.selection.selectNode(b),a.preventDefault())});c.observe(i, +"keydown",function(a){var b=d[a.keyCode];if((a.ctrlKey||a.metaKey)&&!a.altKey&&b)e.commands.exec(b),a.preventDefault()});c.observe(i,"keydown",function(a){var c=e.selection.getSelectedNode(!0),d=a.keyCode;if(c&&"IMG"===c.nodeName&&(d===b.BACKSPACE_KEY||d===b.DELETE_KEY))d=c.parentNode,d.removeChild(c),"A"===d.nodeName&&!d.firstChild&&d.parentNode.removeChild(d),setTimeout(function(){b.quirks.redraw(i)},0),a.preventDefault()});var n={IMG:"Image: ",A:"Link: "};c.observe(i,"mouseover",function(a){var a= +a.target,b=a.nodeName;!("A"!==b&&"IMG"!==b)&&!a.hasAttribute("title")&&(b=n[b]+(a.getAttribute("href")||a.getAttribute("src")),a.setAttribute("title",b))})}})(wysihtml5); +(function(b){b.views.Synchronizer=Base.extend({constructor:function(b,a,d){this.editor=b;this.textarea=a;this.composer=d;this._observe()},fromComposerToTextarea:function(c){this.textarea.setValue(b.lang.string(this.composer.getValue()).trim(),c)},fromTextareaToComposer:function(b){var a=this.textarea.getValue();a?this.composer.setValue(a,b):(this.composer.clear(),this.editor.fire("set_placeholder"))},sync:function(b){"textarea"===this.editor.currentView.name?this.fromTextareaToComposer(b):this.fromComposerToTextarea(b)}, +_observe:function(){var c,a=this,d=this.textarea.element.form,e=function(){c=setInterval(function(){a.fromComposerToTextarea()},400)},f=function(){clearInterval(c);c=null};e();d&&(b.dom.observe(d,"submit",function(){a.sync(!0)}),b.dom.observe(d,"reset",function(){setTimeout(function(){a.fromTextareaToComposer()},0)}));this.editor.observe("change_view",function(b){if(b==="composer"&&!c){a.fromTextareaToComposer(true);e()}else if(b==="textarea"){a.fromComposerToTextarea(true);f()}});this.editor.observe("destroy:composer", +f)}})})(wysihtml5); +wysihtml5.views.Textarea=wysihtml5.views.View.extend({name:"textarea",constructor:function(b,c,a){this.base(b,c,a);this._observe()},clear:function(){this.element.value=""},getValue:function(b){var c=this.isEmpty()?"":this.element.value;b&&(c=this.parent.parse(c));return c},setValue:function(b,c){c&&(b=this.parent.parse(b));this.element.value=b},hasPlaceholderSet:function(){var b=wysihtml5.browser.supportsPlaceholderAttributeOn(this.element),c=this.element.getAttribute("placeholder")||null,a=this.element.value; +return b&&!a||a===c},isEmpty:function(){return!wysihtml5.lang.string(this.element.value).trim()||this.hasPlaceholderSet()},_observe:function(){var b=this.element,c=this.parent,a={focusin:"focus",focusout:"blur"},d=wysihtml5.browser.supportsEvent("focusin")?["focusin","focusout","change"]:["focus","blur","change"];c.observe("beforeload",function(){wysihtml5.dom.observe(b,d,function(b){b=a[b.type]||b.type;c.fire(b).fire(b+":textarea")});wysihtml5.dom.observe(b,["paste","drop"],function(){setTimeout(function(){c.fire("paste").fire("paste:textarea")}, +0)})})}}); +(function(b){var c=b.dom;b.toolbar.Dialog=b.lang.Dispatcher.extend({constructor:function(a,b){this.link=a;this.container=b},_observe:function(){if(!this._observed){var a=this,d=function(b){var c=a._serialize();c==a.elementToChange?a.fire("edit",c):a.fire("save",c);a.hide();b.preventDefault();b.stopPropagation()};c.observe(a.link,"click",function(){c.hasClass(a.link,"wysihtml5-command-dialog-opened")&&setTimeout(function(){a.hide()},0)});c.observe(this.container,"keydown",function(c){var e=c.keyCode; +e===b.ENTER_KEY&&d(c);e===b.ESCAPE_KEY&&a.hide()});c.delegate(this.container,"[data-wysihtml5-dialog-action=save]","click",d);c.delegate(this.container,"[data-wysihtml5-dialog-action=cancel]","click",function(b){a.fire("cancel");a.hide();b.preventDefault();b.stopPropagation()});for(var e=this.container.querySelectorAll("input, select, textarea"),f=0,g=e.length,i=function(){clearInterval(a.interval)};f<g;f++)c.observe(e[f],"change",i);this._observed=!0}},_serialize:function(){for(var a=this.elementToChange|| +{},b=this.container.querySelectorAll("[data-wysihtml5-dialog-field]"),c=b.length,f=0;f<c;f++)a[b[f].getAttribute("data-wysihtml5-dialog-field")]=b[f].value;return a},_interpolate:function(a){for(var b,c,f=document.querySelector(":focus"),g=this.container.querySelectorAll("[data-wysihtml5-dialog-field]"),i=g.length,h=0;h<i;h++)b=g[h],b!==f&&!(a&&"hidden"===b.type)&&(c=b.getAttribute("data-wysihtml5-dialog-field"),c=this.elementToChange?this.elementToChange[c]||"":b.defaultValue,b.value=c)},show:function(a){var b= +this,e=this.container.querySelector("input, select, textarea");this.elementToChange=a;this._observe();this._interpolate();a&&(this.interval=setInterval(function(){b._interpolate(!0)},500));c.addClass(this.link,"wysihtml5-command-dialog-opened");this.container.style.display="";this.fire("show");if(e&&!a)try{e.focus()}catch(f){}},hide:function(){clearInterval(this.interval);this.elementToChange=null;c.removeClass(this.link,"wysihtml5-command-dialog-opened");this.container.style.display="none";this.fire("hide")}})})(wysihtml5); +(function(b){var c=b.dom,a={position:"relative"},d={left:0,margin:0,opacity:0,overflow:"hidden",padding:0,position:"absolute",top:0,zIndex:1},e={cursor:"inherit",fontSize:"50px",height:"50px",marginTop:"-25px",outline:0,padding:0,position:"absolute",right:"-4px",top:"50%"},f={"x-webkit-speech":"",speech:""};b.toolbar.Speech=function(g,i){var h=document.createElement("input");if(b.browser.supportsSpeechApiOn(h)){var k=document.createElement("div");b.lang.object(d).merge({width:i.offsetWidth+"px",height:i.offsetHeight+ +"px"});c.insert(h).into(k);c.insert(k).into(i);c.setStyles(e).on(h);c.setAttributes(f).on(h);c.setStyles(d).on(k);c.setStyles(a).on(i);c.observe(h,"onwebkitspeechchange"in h?"webkitspeechchange":"speechchange",function(){g.execCommand("insertText",h.value);h.value=""});c.observe(h,"click",function(a){c.hasClass(i,"wysihtml5-command-disabled")&&a.preventDefault();a.stopPropagation()})}else i.style.display="none"}})(wysihtml5); +(function(b){var c=b.dom;b.toolbar.Toolbar=Base.extend({constructor:function(a,c){this.editor=a;this.container="string"===typeof c?document.getElementById(c):c;this.composer=a.composer;this._getLinks("command");this._getLinks("action");this._observe();this.show();for(var e=this.container.querySelectorAll("[data-wysihtml5-command=insertSpeech]"),f=e.length,g=0;g<f;g++)new b.toolbar.Speech(this,e[g])},_getLinks:function(a){for(var c=this[a+"Links"]=b.lang.array(this.container.querySelectorAll("[data-wysihtml5-"+ +a+"]")).get(),e=c.length,f=0,g=this[a+"Mapping"]={},i,h,k,j,n;f<e;f++)i=c[f],k=i.getAttribute("data-wysihtml5-"+a),j=i.getAttribute("data-wysihtml5-"+a+"-value"),h=this.container.querySelector("[data-wysihtml5-"+a+"-group='"+k+"']"),n=this._getDialog(i,k),g[k+":"+j]={link:i,group:h,name:k,value:j,dialog:n,state:!1}},_getDialog:function(a,c){var e=this,f=this.container.querySelector("[data-wysihtml5-dialog='"+c+"']"),g,i;f&&(g=new b.toolbar.Dialog(a,f),g.observe("show",function(){i=e.composer.selection.getBookmark(); +e.editor.fire("show:dialog",{command:c,dialogContainer:f,commandLink:a})}),g.observe("save",function(b){i&&e.composer.selection.setBookmark(i);e._execCommand(c,b);e.editor.fire("save:dialog",{command:c,dialogContainer:f,commandLink:a})}),g.observe("cancel",function(){e.editor.focus(!1);e.editor.fire("cancel:dialog",{command:c,dialogContainer:f,commandLink:a})}));return g},execCommand:function(a,b){if(!this.commandsDisabled){var c=this.commandMapping[a+":"+b];c&&c.dialog&&!c.state?c.dialog.show(): +this._execCommand(a,b)}},_execCommand:function(a,b){this.editor.focus(!1);this.composer.commands.exec(a,b);this._updateLinkStates()},execAction:function(a){var b=this.editor;switch(a){case "change_view":b.currentView===b.textarea?b.fire("change_view","composer"):b.fire("change_view","textarea")}},_observe:function(){for(var a=this,b=this.editor,e=this.container,f=this.commandLinks.concat(this.actionLinks),g=f.length,i=0;i<g;i++)c.setAttributes({href:"javascript:;",unselectable:"on"}).on(f[i]);c.delegate(e, +"[data-wysihtml5-command]","mousedown",function(a){a.preventDefault()});c.delegate(e,"[data-wysihtml5-command]","click",function(b){var c=this.getAttribute("data-wysihtml5-command"),d=this.getAttribute("data-wysihtml5-command-value");a.execCommand(c,d);b.preventDefault()});c.delegate(e,"[data-wysihtml5-action]","click",function(b){var c=this.getAttribute("data-wysihtml5-action");a.execAction(c);b.preventDefault()});b.observe("focus:composer",function(){a.bookmark=null;clearInterval(a.interval);a.interval= +setInterval(function(){a._updateLinkStates()},500)});b.observe("blur:composer",function(){clearInterval(a.interval)});b.observe("destroy:composer",function(){clearInterval(a.interval)});b.observe("change_view",function(b){setTimeout(function(){a.commandsDisabled="composer"!==b;a._updateLinkStates();a.commandsDisabled?c.addClass(e,"wysihtml5-commands-disabled"):c.removeClass(e,"wysihtml5-commands-disabled")},0)})},_updateLinkStates:function(){var a=this.commandMapping,d=this.actionMapping,e,f,g;for(e in a)if(g= +a[e],this.commandsDisabled?(f=!1,c.removeClass(g.link,"wysihtml5-command-active"),g.group&&c.removeClass(g.group,"wysihtml5-command-active"),g.dialog&&g.dialog.hide()):(f=this.composer.commands.state(g.name,g.value),b.lang.object(f).isArray()&&(f=1===f.length?f[0]:!0),c.removeClass(g.link,"wysihtml5-command-disabled"),g.group&&c.removeClass(g.group,"wysihtml5-command-disabled")),g.state!==f)(g.state=f)?(c.addClass(g.link,"wysihtml5-command-active"),g.group&&c.addClass(g.group,"wysihtml5-command-active"), +g.dialog&&("object"===typeof f?g.dialog.show(f):g.dialog.hide())):(c.removeClass(g.link,"wysihtml5-command-active"),g.group&&c.removeClass(g.group,"wysihtml5-command-active"),g.dialog&&g.dialog.hide());for(e in d)a=d[e],"change_view"===a.name&&(a.state=this.editor.currentView===this.editor.textarea,a.state?c.addClass(a.link,"wysihtml5-action-active"):c.removeClass(a.link,"wysihtml5-action-active"))},show:function(){this.container.style.display=""},hide:function(){this.container.style.display="none"}})})(wysihtml5); +(function(b){var c={name:void 0,style:!0,toolbar:void 0,autoLink:!0,parserRules:{tags:{br:{},span:{},div:{},p:{}},classes:{}},parser:b.dom.parse,composerClassName:"wysihtml5-editor",bodyClassName:"wysihtml5-supported",stylesheets:[],placeholderText:void 0,allowObjectResizing:!0,supportTouchDevices:!0};b.Editor=b.lang.Dispatcher.extend({constructor:function(a,d){this.textareaElement="string"===typeof a?document.getElementById(a):a;this.config=b.lang.object({}).merge(c).merge(d).get();this.currentView= +this.textarea=new b.views.Textarea(this,this.textareaElement,this.config);this._isCompatible=b.browser.supported();if(!this._isCompatible||!this.config.supportTouchDevices&&b.browser.isTouchDevice()){var e=this;setTimeout(function(){e.fire("beforeload").fire("load")},0)}else{b.dom.addClass(document.body,this.config.bodyClassName);this.currentView=this.composer=new b.views.Composer(this,this.textareaElement,this.config);"function"===typeof this.config.parser&&this._initParser();this.observe("beforeload", +function(){this.synchronizer=new b.views.Synchronizer(this,this.textarea,this.composer);this.config.toolbar&&(this.toolbar=new b.toolbar.Toolbar(this,this.config.toolbar))});try{console.log("Heya! This page is using wysihtml5 for rich text editing. Check out https://github.com/xing/wysihtml5")}catch(f){}}},isCompatible:function(){return this._isCompatible},clear:function(){this.currentView.clear();return this},getValue:function(a){return this.currentView.getValue(a)},setValue:function(a,b){if(!a)return this.clear(); +this.currentView.setValue(a,b);return this},focus:function(a){this.currentView.focus(a);return this},disable:function(){this.currentView.disable();return this},enable:function(){this.currentView.enable();return this},isEmpty:function(){return this.currentView.isEmpty()},hasPlaceholderSet:function(){return this.currentView.hasPlaceholderSet()},parse:function(a){var c=this.config.parser(a,this.config.parserRules,this.composer.sandbox.getDocument(),!0);"object"===typeof a&&b.quirks.redraw(a);return c}, +_initParser:function(){this.observe("paste:composer",function(){var a=this;a.composer.selection.executeAndRestore(function(){b.quirks.cleanPastedHTML(a.composer.element);a.parse(a.composer.element)},!0)});this.observe("paste:textarea",function(){this.textarea.setValue(this.parse(this.textarea.getValue()))})}})})(wysihtml5); diff --git a/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysiwyg-color.css b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysiwyg-color.css new file mode 100755 index 0000000..86e7895 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysiwyg-color.css @@ -0,0 +1,67 @@ +.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/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/wysihtml5.js b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/wysihtml5.js new file mode 100755 index 0000000..998f840 --- /dev/null +++ b/src/static/jquery/bootstrap-editable-1.5.1/inputs-ext/wysihtml5/wysihtml5.js @@ -0,0 +1,138 @@ +/** +Bootstrap wysihtml5 editor. Based on [bootstrap-wysihtml5](https://github.com/jhollingworth/bootstrap-wysihtml5). +You should include **manually** distributives of `wysihtml5` and `bootstrap-wysihtml5`: + + <link href="js/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.css" rel="stylesheet" type="text/css"></link> + <script src="js/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysihtml5-0.3.0.min.js"></script> + <script src="js/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.min.js"></script> + +And also include `wysihtml5.js` from `inputs-ext` directory of x-editable: + + <script src="js/inputs-ext/wysihtml5/wysihtml5.js"></script> + +**Note:** It's better to use fresh bootstrap-wysihtml5 from it's [master branch](https://github.com/jhollingworth/bootstrap-wysihtml5/tree/master/src) as there is update for correct image insertion. + +@class wysihtml5 +@extends abstractinput +@final +@since 1.4.0 +@example +<div id="comments" data-type="wysihtml5" data-pk="1"><h2>awesome</h2> comment!</div> +<script> +$(function(){ + $('#comments').editable({ + url: '/post', + title: 'Enter comments' + }); +}); +</script> +**/ +(function ($) { + "use strict"; + + var Wysihtml5 = function (options) { + this.init('wysihtml5', options, Wysihtml5.defaults); + + //extend wysihtml5 manually as $.extend not recursive + this.options.wysihtml5 = $.extend({}, Wysihtml5.defaults.wysihtml5, options.wysihtml5); + }; + + $.fn.editableutils.inherit(Wysihtml5, $.fn.editabletypes.abstractinput); + + $.extend(Wysihtml5.prototype, { + render: function () { + var deferred = $.Deferred(), + msieOld; + + //generate unique id as it required for wysihtml5 + this.$input.attr('id', 'textarea_'+(new Date()).getTime()); + + this.setClass(); + this.setAttr('placeholder'); + + //resolve deffered when widget loaded + $.extend(this.options.wysihtml5, { + events: { + load: function() { + deferred.resolve(); + } + } + }); + + this.$input.wysihtml5(this.options.wysihtml5); + + /* + In IE8 wysihtml5 iframe stays on the same line with buttons toolbar (inside popover). + The only solution I found is to add <br>. If you fine better way, please send PR. + */ + msieOld = /msie\s*(8|7|6)/.test(navigator.userAgent.toLowerCase()); + if(msieOld) { + this.$input.before('<br><br>'); + } + + return deferred.promise(); + }, + + value2html: function(value, element) { + $(element).html(value); + }, + + html2value: function(html) { + return html; + }, + + value2input: function(value) { + this.$input.data("wysihtml5").editor.setValue(value, true); + }, + + activate: function() { + this.$input.data("wysihtml5").editor.focus(); + }, + + isEmpty: function($element) { + if($.trim($element.html()) === '') { + return true; + } else if($.trim($element.text()) !== '') { + return false; + } else { + //e.g. '<img>', '<br>', '<p></p>' + return !$element.height() || !$element.width(); + } + } + }); + + Wysihtml5.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, { + /** + @property tpl + @default <textarea></textarea> + **/ + tpl:'<textarea></textarea>', + /** + @property inputclass + @default editable-wysihtml5 + **/ + inputclass: 'editable-wysihtml5', + /** + Placeholder attribute of input. Shown when input is empty. + + @property placeholder + @type string + @default null + **/ + placeholder: null, + /** + Wysihtml5 default options. + See https://github.com/jhollingworth/bootstrap-wysihtml5#options + + @property wysihtml5 + @type object + @default {stylesheets: false} + **/ + wysihtml5: { + stylesheets: false //see https://github.com/jhollingworth/bootstrap-wysihtml5/issues/183 + } + }); + + $.fn.editabletypes.wysihtml5 = Wysihtml5; + +}(window.jQuery)); diff --git a/src/static/jquery/colorbox/README.md b/src/static/jquery/colorbox/README.md new file mode 100755 index 0000000..896c67f --- /dev/null +++ b/src/static/jquery/colorbox/README.md @@ -0,0 +1,527 @@ +## About Colorbox: +A customizable lightbox plugin for jQuery. See the [project page](http://jacklmoore.com/colorbox/) for documentation and a demonstration, and the [FAQ](http://jacklmoore.com/colorbox/faq/) for solutions and examples to common issues. Released under the [MIT license](http://www.opensource.org/licenses/mit-license.php). + +## Changelog: + +### Version 1.4.33 - 2013/10/31 + +* Fixed an issue where private events propagated to the document in versions of jQuery prior to 1.7. Fixes #525, Fixes #526 + +### Version 1.4.32 - 2013/10/16 + +* Updated stylesheets to avoid issue with using `div {max-width:100%}` (Fixes #520) + +### Version 1.4.31 - 2013/9/25 + +* Used setAttribute to set londesc, so that the value is accessible via DOM Node longDesc property #508 + +### Version 1.4.30 - 2013/9/24 + +* Added longdesc and aria-describedby attributes to photos. Fixes #508 + +### Version 1.4.29 - 2013/9/10 + +* Fixed a slideshow regression from 1.4.27 +* Fixed a potential issue with the starting size of #cboxLoadedContent + +### Version 1.4.28 - 2013/9/4 + +* Fixed a potential issue with using the open property with mixed slideshow and non-slideshow groups + +### Version 1.4.27 - 2013/7/16 + +* Fixed a width calculation issue relating to using margin:auto on #cboxLoadedContent. + +### Version 1.4.26 - 2013/6/30 + +* Fixed a regression in IE7 and IE8 that was causing an error. + +### Version 1.4.25 - 2013/6/28 + +* Use an animation speed of zero between same-sized content (fixed). +* Removed temporary fix for jQuery UI 1.8 + +### Version 1.4.24 - 2013/6/24 + +* Added closeButton option. Set to false to remove the close button. + +### Version 1.4.23 - 2013/6/23 + +* Bugfix loading overlay/graphic append order + +### Version 1.4.22 - 2013/6/19 + +* Updated manifest files for the jQuery plugin repository and Bower (no changes to plugin) + +### Version 1.4.21 - 2013/6/6 + +* Replaced new Image() with document.createElement('img') to avoid a potential bug in Chrome 27. + +### Version 1.4.20 - 2013/6/5 + +* Fixing bug/typo from last update. + +### Version 1.4.19 - 2013/6/3 + +* Fixed bug where Colorbox was capturing ctrl+click on assigned links on windows browsers with jQuery 1.7+, rather than ignoring. + +### Version 1.4.18 - 2013/5/30 + +* Fixed a scroll position issue when using $.colorbox.resize() + +### Version 1.4.17 - 2013/5/23 + +* Possible fix for a Chrome 27 issue (https://github.com/jackmoore/colorbox/pull/438#issuecomment-18334804) + +### Version 1.4.16 - 2013/5/20 + +* Added trapFocus setting to allow disabling of focus trapping + +### Version 1.4.15 - 2013/4/22 + +* Added .webp to list of recognized image extensions + +### Version 1.4.14 - 2013/4/16 + +* Added fadeOut property to control the closing fadeOut speed. +* Removed longdesc attribute for now. + +### Version 1.4.13 - 2013/4/11 + +* Fixed an error involving IE7/IE8 and legacy versions of jQuery + +### Version 1.4.12 - 2013/4/9 + +* Fixed a potential conflict with Twitter Bootstrap default img styles. + +### Version 1.4.11 - 2013/4/9 + +* Added `type='button'` to buttons to prevent accidental form submission +* Added alt and longdesc attributes to photo content if they are present on the calling element. + +### Version 1.4.10 - 2013/4/2 + +* Better 'old IE' feature detection that fixes an error with jQuery 2.0.0pre. + +### Version 1.4.9 - 2013/4/2 + +* Fixes bug introduced in previous version. + +### Version 1.4.8 - 2013/4/2 + +* Dropped IE6 support. +* Fixed other issues with $.colorbox.remove. + +### Version 1.4.7 - 2013/4/1 + +* Prevented an error if $.colorbox.remove is called during the transition. + +### Version 1.4.6 - 2013/3/19 + +* Minor change to work around a jQuery 1.4.2 bug for legacy users. + +### Version 1.4.5 - 2013/3/10 + +* Minor change to apply the close and className properties sooner. + +### Version 1.4.4 - 2013/3/10 + +* Fixed an issue with percent-based heights in iOS +* Fixed an issue with ajax requests being applied at the wrong time. + +### Version 1.4.3 - 2013/2/18 + +* Made image preloading aware of retina settings. + +### Version 1.4.2 - 2013/2/18 + +* Removed $.contains for compatibility with jQuery 1.3.x + +### Version 1.4.1 - 2013/2/14 + +* Ignored left and right arrow keypresses if combined with the alt key. + +### Version 1.4.0 - 2013/2/12 + +* Better accessibility: + * Replaced div controls with buttons + * Tabbed navigation confined to modal window + * Added aria role + +### Version 1.3.34 - 2013/2/4 + +* Updated manifest for plugins.jquery.com + +### Version 1.3.33 - 2013/2/4 + +* Added retina display properties: retinaImage, retinaUrl, retinaSuffix +* Fixed iframe scrolling on iOS devices. + +### Version 1.3.32 - 2013/1/31 + +* Improved internal event subscribing & fixed event bug introduced in v1.3.21 + +### Version 1.3.31 - 2013/1/28 + +* Fixed a size-calculation bug introduced in the previous commit. + +### Version 1.3.30 - 2013/1/25 + +* Delayed border-width calculations until after opening, to avoid a bug in FF when using Colorbox in a hidden iframe. + +### Version 1.3.29 - 2013/1/24 + +* Fixes bug with bubbling delegated events, introduced in the previous commit. + +### Version 1.3.28 - 2013/1/24 + +* Fixed compatibility issue with old versions of jQuery (1.3.2-1.4.2) + +### Version 1.3.27 - 2013/1/23 + +* Added className property. + +### Version 1.3.26 - 2013/1/23 + +* Minor bugfix: clear the onload event handler after photo has loaded. + +### Version 1.3.25 - 2013/1/23 + +* Removed grunt file & added Bower component.json. + +### Version 1.3.24 - 2013/1/22 + +* Added generated files (jquery.colorbox.js / jquery.colorbox-min.js) back to the repository. + +### Version 1.3.23 - 2013/1/18 + +* Minor bugfix for calling Colorbox on empty jQuery collections without a selector. + +### Version 1.3.22 - 2013/1/17 + +* Recommit for plugins.jquery.com + +### Version 1.3.21 - 2013/1/15 +Files Changed: *.js + +* Fixed compatibility issues with jQuery 1.9 + +### Version 1.3.20 - August 15 2012 +Files Changed:jquery.colorbox.js + +* Added temporary workaround for jQuery-UI 1.8 bug (http://bugs.jquery.com/ticket/12273) +* Added *.jpe extension to the list of image types. + +### Version 1.3.19 - December 08 2011 +Files Changed:jquery.colorbox.js, colorbox.css (all) + +* Fixed bug related to using the 'fixed' property. +* Optimized the setup procedure to be more efficient. +* Removed $.colorbox.init() as it will no longer be needed (will self-init when called). +* Removed use of $.browser. + +### Version 1.3.18 - October 07 2011 +Files Changed:jquery.colorbox.js/jquery.colorbox-min.js, colorbox.css (all) and example 1's controls.png + +* Fixed a regression where Flash content displayed in Colorbox would be reloaded if the browser window was resized. +* Added safety check to make sure that Colorbox's markup is only added to the DOM a single time, even if $.colorbox.init() is called multiple times. This will allow site owners to manually initialize Colorbox if they need it before the DOM has finished loading. +* Updated the example index.html files to be HTML5 compliant. +* Changed the slideshow behavior so that it immediately moves to the next slide when the slideshow is started. +* Minor regex bugfix to allow automatic detection of image URLs that include fragments. + +### Version 1.3.17 - May 11 2011 +Files Changed:jquery.colorbox.js/jquery.colorbox-min.js + +* Added properties "top", "bottom", "left" and "right" to specify a position relative to the viewport, rather than using the default centering. +* Added property "data" to specify GET or POST data when using Ajax. Colorbox's ajax functionality is handled by jQuery's .load() method, so the data property works the same way as it does with .load(). +* Added property "fixed" which can provide fixed positioning for Colorbox, rather than absolute positioning. This will allow Colorbox to remain in a fixed position within the visitors viewport, despite scrolling. IE6 support for this was not added, it will continue to use the default absolute positioning. +* Fixed ClearType problem with IE7. +* Minor fixes. + +### Version 1.3.16 - March 01 2011 +Files Changed:jquery.colorbox.js/jquery.colorbox-min.js, colorbox.css (all) and example 4 background png files + +* Better IE related transparency workarounds. IE7 and up now uses the same background image sprite as other browsers. +* Added error handling for broken image links. A message will be displayed telling the user that the image could not be loaded. +* Added new property: 'fastIframe' and set it to true by default. Setting to fastIframe:false will delay the loading graphic removal and onComplete event until iframe has completely loaded. +* Ability to redefine $.colorbox.close (or prev, or next) at any time. + +### Version 1.3.15 - October 27 2010 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Minor fixes for specific cases. + +### Version 1.3.14 - October 27 2010 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* In IE6, closing an iframe when using HTTPS no longer generates a security warning. + +### Version 1.3.13 - October 22 2010 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Changed the index.html example files to use YouTube's new embedded link format. +* By default, Colorbox returns focus to the element it was launched from once it closes. This can now be disabled by setting the 'returnFocus' property to false. Focus was causing problems for some users who had their anchor elements inside animated containers. +* Minor bug fix involved in using a combination of slideshow and non-slideshow content. + +### Version 1.3.12 - October 20 2010 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Minor bug fix involved in preloading images when using a function as a value for the href property. + +### Version 1.3.11 - October 19 2010 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Fixed the slideshow functionality that broke with 1.3.10 +* The slideshow now respects the loop property. + +### Version 1.3.10 - October 16 2010 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Fixed compatibility with jQuery 1.4.3 +* The 'open' property now accepts a function as a value, like all of the other properties. +* Preloading now loads the correct href for images when using a dynamic (function) value for the href property. +* Fixed bug in Safari 3 for Win where Colorbox centered on the document, rather than the visitor's viewport. +* May have fixed an issue in Opera 10.6+ where Colorbox would rarely/randomly freeze up while switching between photos in a group. +* Some functionality better encapsulated & minor performance improvements. + +### Version 1.3.9 - July 7 2010 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js/ all colorbox.css (the core styles) + +* Fixed a problem where iframed youtube videos would cause a security alert in IE. +* More code is event driven now, making the source easier to grasp. +* Removed some unnecessary style from the core CSS. + +### Version 1.3.8 - June 21 2010 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Fixed a bug in Chrome where it would sometimes render photos at 0 by 0 width and height (behavior introduced in recent update to Chrome). +* Fixed a bug where the onClosed callback would fire twice (only affected 1.3.7). +* Fixed a bug in IE7 that existed with some iframed websites that use JS to reposition the viewport caused Colorbox to move out of position. +* Abstracted the identifiers (HTML ids & classes, and JS plugin name, method, and events) so that the plugin can be easily rebranded. +* Small changes to improve either code readability or compression. + +### Version 1.3.7 - June 13 2010 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js/index.html + +* $.colorbox can now be used for direct calls and accessing public methods. Example: $.colorbox.close(); +* Resize now accepts 'width', 'innerWidth', 'height' and 'innerHeight'. Example: $.colorbox.resize({width:"100%"}) +* Added option (loop:false) to disable looping in a group. +* Added options (escKey:false, arrowKey:false) to disable esc-key and arrow-key bindings. +* Added method for removing Colorbox from a document: $.colorbox.remove(); +* Fixed a bug where iframed URLs would be truncated if they contained an unencoded apostrophe. +* Now uses the exact href specified on an anchor, rather than the version returned by 'this.href'. This was causing "#example" to be normalized to "http://domain/#example" which interfered with how some users were setting up links to inline content. +* Changed example documents over to HTML5. + +### Version 1.3.6 - Jan 13 2010 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Small change to make Colorbox compatible with jQuery 1.4 + +### Version 1.3.5 - December 15 2009 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Fixed a bug introduced in 1.3.4 with IE7's display of example 2 and 3, and auto-width in Opera. +* Fixed a bug introduced in 1.3.4 where colorbox could not be launched by triggering an element's click event through JavaScript. +* Minor refinements. + +### Version 1.3.4 - December 5 2009 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Event delegation is now used for elements that Colorbox is assigned to, rather than individual click events. +* Additional callbacks have been added to represent other stages of Colorbox's lifecycle. Available callbacks, in order of their execution: onOpen, onLoad, onComplete, onCleanup, onClosed These take place at the same time as the event hooks, but will be better suited than the hooks for targeting specific instances of Colorbox. +* Ajax content is now immediately added to the DOM to be more compatible if that content contains script tags. +* Focus is now returned to the calling element on closing. +* Fixed a bug where maxHeight and maxWidth did not work for non-photo content. +* Direct calls no longer need 'open:true', it is assumed. Example: `$.colorbox({html:'<p>Hi</p>'});` + +### Version 1.3.3 - November 7 2009 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Changed $.colorbox.element() to return a jQuery object rather the DOM element. +* jQuery.colorbox-min.js is compressed with Google's Closure Compiler rather than YUI Compressor. + +### Version 1.3.2 - October 27 2009 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Added 'innerWidth' and 'innerHeight' options to allow people to easily set the size dimensions for Colorbox, without having to anticipate the size of the borders and buttons. +* Renamed 'scrollbars' option to 'scrolling' to be in keeping with the existing HTML attribute. The option now also applies to iframes. +* Bug fix: In Safari, positioning occassionally incorrect when using '100%' dimensions. +* Bug fix: In IE6, the background overlay is briefly not full size when first viewing. +* Bug fix: In Firefox, opening Colorbox causes a split second shift with a small minority of webpage layouts. +* Simplified code in a few areas. + +### Version 1.3.1 - September 16 2009 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js/colorbox.css/colorbox-ie.css(removed) + +* Removed the IE-only stylesheets and conditional comments for example styles 1 & 4. All CSS is handled by a single CSS file for all examples. +* Removed user-agent sniffing from the js and replaced it with feature detection. This will allow correct rendering for visitors masking their agent type. + +### Version 1.3.0 - September 15 2009 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js/colorbox.css + +* Added $.colorbox.resize() method to allow Colorbox to resize it's height if it's contents change. +* Added 'scrollbars' option to allow users to turn off scrollbars when using the resize() method. +* Renamed the 'resize' option to be less ambiguous. It's now 'scalePhotos'. +* Renamed the 'cbox_close' event to be less ambiguous. It's now 'cbox_cleanup'. It is the first thing to happen in the close method while the 'cbox_closed' event is the last to happen. +* Fixed a bug with the slideshow mouseover graphics that appeared after Colorbox is opened a 2nd time. +* Fixed a bug where ClearType may not work in IE6&7 if using the fade transition. +* Minor code optimizations to increase compression. + +### Version 1.2.9 - August 7 2009 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Minor change to enable use with $.getScript(); +* Minor change to the timing of the 'cbox_load' event so that it is more useful. +* Added a direct link to a YouTube video to the examples. + +### Version 1.2.8 - August 5 2009 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Fixed a bug with the overlay in IE6 +* Fixed a bug where left & right keypress events might be prematurely unbound. + +### Version 1.2.7 - July 31 2009 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js, example stylesheets and background images (core styles have not changed and the updates will not affect existing user themes / old example themes) + +* Code cleanup and reduction, better organization and documentation in the full source. +* Added ability to use functions in place of static values for Colorbox's options (thanks Ken!). +* Added an option for straight HTML. Example: `$.colorbox({html:'<p>Howdy</p>', open:true})` +* Added an event for the beginning of the closing process. This is in addition to the event that already existed for when Colorbox had completely closed. 'cbox_close' and 'cbox_closed' respectively. +* Fixed a minor bug in IE6 that would cause a brief content shift in the parent document when opening Colorbox. +* Fixed a minor bug in IE6 that would reveal select elements that had a hidden visibility after closing Colorbox. +* The 'esc' key is unbound now when Colorbox is not open, to avoid any potential conflicts. +* Used background sprites for examples 1 & 4. Put IE-only (non-sprite) background images in a separate folder. +* Example themes 1, 3, & 4 received slight visual tweaks. +* Optimized pngs for smaller file size. +* Added slices, grid, and correct sizing to the Adobe Illustrator file, all theme files are now export ready! + +### Version 1.2.6 - July 15 2009 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Fixed a bug with fixed width/height images in Opera 9.64. +* Fixed a bug with trying to set a value for rel during a direct call to Colorbox. Example: `$.colorbox({rel:'foo', open:true});` +* Changed how href/rel/title settings are determined to avoid users having to manually update Colorbox settings if they use JavaScript to update any of those attributes, after Colorbox has been defined. +* Fixed a FF3 bug where the back button was disabled after closing an iframe. + +### Version 1.2.5 - June 23 2009 +Files Changed: jquery.colorbox.js/jquery.colorbox-min.js + +* Changed the point at which iframe srcs are set (to eliminate the need to refresh the iframe once it has been added to the DOM). +* Removed unnecessary return values for a very slight code reduction. + +### Version 1.2.4 - June 9 2009 +Files Changed: jquery.colorbox.js, jquery.colorbox-min.js + +* Fixed an issue where Colorbox may not close completely if it is closed during a transition animation. +* Minor code reduction. + +### Version 1.2.3 - June 4 2009 +* Fixed a png transparency stacking issue in IE. +* More accurate Ajax auto-sizing if the user was depending on the #cboxLoadedContent ID for CSS styling. +* Added a public function for returning the current html element that Colorbox is associated with. Example use: var that = $.colorbox.element(); +* Added bicubic scaling for resized images in the original IE7. +* Removed the IE6 stylesheet and png files from Example 3. It now uses the same png file for the controls that the rest of the browsers use (an alpha transparency PNG8). This example now only has 2 graphics files and 1 stylesheet. + +### Version 1.2.2 - May 28 2009 +* Fixed an issue with the 'resize' option. + +### Version 1.2.1 - May 28 2009 +* Note: If you are upgrading, update your jquery.colorbox.js and colorbox.css files. +* Added photo resizing. +* Added a maximum width and maximum height. Example: {height:800, maxHeight:'100%'}, would allow the box to be a maximum potential height of 800px, instead of a fixed height of 800px. With maxHeight of 100% the height of Colorbox cannot exceed the height of the browser window. +* Added 'rel' setting to add the ability to set an alternative rel for any Colorbox call. This allows the user to group any combination of elements together for a gallery, or to override an existing rel. attribute so those element are not grouped together, without having to alter their rel in the HTML. +* Added a 'photo' setting to force Colorbox to display a link as a photo. Use this when automatic photo detection fails (such as using a url like 'photo.php' instead of 'photo.jpg', 'photo.jpg#1', or 'photo.jpg?pic=1') +* Removed the need to ever create disposable elements to call colorbox on. Colorbox can now be called directly, without being associated with any existing element, by using the following format: + `$.colorbox({open:true, href:'yourLink.xxx'});` +* Colorbox settings are now persistent and unique for each element. This allows for extremely flexible options for individual elements. You could use this to create a gallery in which each page in the gallery has different settings. One could be a photo with a fade transition, next could be an inline element with an elastic transition with a set width and height, etc. +* For user callbacks, 'this' now refers to the element colorbox was opened from. +* Fixed a minor grouping issue with IE6, when transition type is set to 'none'. +* Added an Adobe Illustrator file that contains the borders and buttons used in the various examples. + +### Version 1.2 - May 13 2009 +* Added a slideshow feature. +* Added re-positioning on browser resize. If the browser is resized, Colorbox will recenter itself onscreen. +* Added hooks for key events: cbox_open, cbox_load, cbox_complete, cbox_closed. +* Fixed an IE transparency-stacking problem, where transparent PNGs would show through to the background overlay. +* Fixed an IE iframe issue where the ifame might shift up and to the left under certain circumstances. +* Fixed an IE6 bug where the loading overlay was not at full height. +* Removed the delay in switching between same-sized gallery content when using transitions. +* Changed how iframes are loaded to make it more compatible with iframed pages that use DOM dependent JavaScript. +* Changed how the JS is structured to be better organized and increase compression. Increased documentation. +* Changed CSS :hover states to a .hover class. This sidesteps a minor IE8 bug with css hover states and allows easier access to hover state user styles from the JavaScript. +* Changed: elements added to the DOM have new ID's. The naming is more consistent and less likely to cause conflicts with existing website stylesheets. All stylesheets have been updated. +* Changed the behavior for prev/next links so that Colorbox does not get hung up on broken links. A visitor can now skip through broken or long-loading links by clicking prev/next buttons. +* Changed the naming of variables in the parameter map to be more concise and intuitive. +* Removed colorbox.css. Combined the colorbox.css styles with jquery.colorbox.js: the css file was not large enough to warrant being a separate file. + +### Version 1.1.6 - April 28 2009 +* Prevented the default action of the next & previous anchors and the left and right keys for gallery mode. +* Fixed a bug where the title element was being added back to the DOM when closing Colorbox while using inline content. +* Fixed a bug where IE7 would crash for example 2. +* Smaller filesize: removed a small amount of unused code and rewrote the HTML injection with less syntax. +* Added a public method for closing Colorbox: $.colorbox.close(). This will allow iframe users to add an event to close Colorbox without having to create an additional function. + +### Version 1.1.5 - April 11 2009 +* Fixed minor issues with exiting Colorbox. + +### Version 1.1.4 - April 08 2009 +* Fixed a bug in the fade transition where Colorbox not close completely if instructed to close during the fade-in portion of the transition. + +### Version 1.1.3 - April 06 2009 +* Fixed an IE6&7 issue with using Colorbox to display animated GIFs. + +### Version 1.1.2 - April 05 2009 +* Added ability to change content when Colorbox is already open. +* Added vertical photo centering now works for all browsers (this feature previously excluded IE6&7). +* Added namespacing to the esc-key keydown event for people who want to disable it: "keydown.colorClose" +* Added 'title' setting to add the ability to set an alternative title for any Colorbox call. +* Fixed rollover navigation issue with IE8. (Added JS-based rollover state due to a browser-bug.) +* Fixed an overflow issue for when the fixed width/height is smaller than the size of a photo. +* Fixed a bug in the fade transition where the border would still come up if Colorbox was closed mid-transition. +* Switch from JSMin to Yui Compressor for minification. Minified code now under 7KB. + +### Version 1.1.1 - March 31 2009 +* More robust image detection regex. Now detects image file types with url fragments and/or query strings. +* Added 'nofollow' exception to rel grouping. +* Changed how images are loaded into the DOM to prevent premature size calculation by Colorbox. +* Added timestamp to iframe name to prevent caching - this was a problem in some browsers if the user had multiple iframes and the visitor left the page and came back, or if they refreshed the page. + +### Version 1.1.0 - March 21 2009 +* Animation is now much smoother and less resource intensive. +* Added support for % sizing. +* Callback option added. +* Inline content now preserves JavaScript events, and changes made while Colorbox is open are also preserved. +* Added 'href' setting to add the ability to set an alternative href for any anchor, or to assign the Colorbox event to non-anchors. + Example: $('button').colorbox({'href':'process.php'}) + Example: $('a[href='http://msn.com']).colorbox({'href':'http://google.com', iframe:true}); +* Photos are now horizontally centered if they are smaller than the lightbox size. Also vertically centered for browsers newer than IE7. +* Buttons in the examples are now included in the 'protected zone'. The lightbox will never expand it's borders or buttons beyond an accessible area of the screen. +* Keypress events don't queue up by holding down the arrow keys. +* Added option to close Colorbox by clicking on the background overlay. +* Added 'none' transition setting. +* Changed 'contentIframe' and 'contentInline' to 'inline' and 'iframe'. Removed 'contentAjax' because it is automatically assumed for non-image file types. +* Changed 'contentWidth' and 'contentHeight' to 'fixedWidth' and 'fixedHeight'. These sizes now reflect the total size of the lightbox, not just the inner content. This is so users can accurately anticipate % sizes without fear of creating scrollbars. +* Clicking on a photo will now switch to the next photo in a set. +* Loading.gif is more stable in it's position. +* Added a minified version. +* Code passes JSLint. + +### Version 1.0.5 - March 11 2009 +* Redo: Fixed a bug where IE would cut off the bottom portion of a photo, if the photo was larger than the document dimensions. + +### Version 1.0.4 - March 10 2009 +* Added an option to allow users to automatically open the lightbox. Example usage: $(".colorbox").colorbox({open:true}); +* Fixed a bug where IE would cut off the bottom portion of a photo, if the photo was larger than the document dimensions. + +### Version 1.0.3 - March 09 2009 +* Fixed vertical centering for Safari 3.0.x. + +### Version 1.0.2 - March 06 2009 +* Corrected a typo. +* Changed the content-type check so that it does not assume all links to photos should actually display photos. This allows for Ajax/inline/and iframe calls on anchors linking to picture file types. + +### Version 1.0.1 - March 05 2009 +* Fixed keydown events (esc, left arrow, right arrow) for Webkit browsers. + +### Version 1.0 - March 03 2009 +* First release diff --git a/src/static/jquery/colorbox/colorbox.css b/src/static/jquery/colorbox/colorbox.css new file mode 100644 index 0000000..7918e42 --- /dev/null +++ b/src/static/jquery/colorbox/colorbox.css @@ -0,0 +1,85 @@ +/* + ColorBox Core Style: + The following CSS is consistent between example themes and should not be altered. +*/ +#colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;} +#cboxOverlay{position:fixed; width:100%; height:100%;} +#cboxMiddleLeft, #cboxBottomLeft{clear:left;} +#cboxContent{position:relative;} +#cboxLoadedContent{overflow:auto;} +#cboxTitle{margin:0;} +#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;} +#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} +.cboxPhoto{float:left; margin:auto; border:0; display:block;} +.cboxIframe{width:100%; height:100%; display:block; border:0;} + +/* + User Style: + Change the following styles to modify the appearance of ColorBox. They are + ordered & tabbed in a way that represents the nesting of the generated HTML. +*/ +#cboxOverlay{background:url(images/overlay.png) repeat 0 0;} +#colorbox{} + #cboxTopLeft{width:21px; height:21px; background:url(images/controls.png) no-repeat -101px 0;} + #cboxTopRight{width:21px; height:21px; background:url(images/controls.png) no-repeat -130px 0;} + #cboxBottomLeft{width:21px; height:21px; background:url(images/controls.png) no-repeat -101px -29px;} + #cboxBottomRight{width:21px; height:21px; background:url(images/controls.png) no-repeat -130px -29px;} + #cboxMiddleLeft{width:21px; background:url(images/controls.png) left top repeat-y;} + #cboxMiddleRight{width:21px; background:url(images/controls.png) right top repeat-y;} + #cboxTopCenter{height:21px; background:url(images/border.png) 0 0 repeat-x;} + #cboxBottomCenter{height:21px; background:url(images/border.png) 0 -29px repeat-x;} + #cboxContent{background:#fff; overflow:hidden;} + .cboxIframe{background:#fff;} + #cboxError{padding:50px; border:1px solid #ccc;} + #cboxLoadedContent{margin-bottom:28px;} + #cboxTitle{position:absolute; bottom:4px; left:0; text-align:center; width:100%; color:#949494;} + #cboxCurrent{position:absolute; bottom:4px; left:58px; color:#949494;} + #cboxSlideshow{position:absolute; bottom:4px; right:30px; color:#0092ef;} + #cboxPrevious{position:absolute; bottom:0; left:0; background:url(images/controls.png) no-repeat -75px 0; width:25px; height:25px; text-indent:-9999px;} + #cboxPrevious:hover{background-position:-75px -25px;} + #cboxNext{position:absolute; bottom:0; left:27px; background:url(images/controls.png) no-repeat -50px 0; width:25px; height:25px; text-indent:-9999px;} + #cboxNext:hover{background-position:-50px -25px;} + #cboxLoadingOverlay{background:url(images/loading_background.png) no-repeat center center;} + #cboxLoadingGraphic{background:url(images/loading.gif) no-repeat center center;} + #cboxClose{position:absolute; bottom:0; right:0; background:url(images/controls.png) no-repeat -25px 0; width:25px; height:25px; text-indent:-9999px;} + #cboxClose:hover{background-position:-25px -25px;} + +/* + The following fixes a problem where IE7 and IE8 replace a PNG's alpha transparency with a black fill + when an alpha filter (opacity change) is set on the element or ancestor element. This style is not applied to or needed in IE9. + See: http://jacklmoore.com/notes/ie-transparency-problems/ +*/ +.cboxIE #cboxTopLeft, +.cboxIE #cboxTopCenter, +.cboxIE #cboxTopRight, +.cboxIE #cboxBottomLeft, +.cboxIE #cboxBottomCenter, +.cboxIE #cboxBottomRight, +.cboxIE #cboxMiddleLeft, +.cboxIE #cboxMiddleRight { + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00FFFFFF,endColorstr=#00FFFFFF); +} + +/* + The following provides PNG transparency support for IE6 + Feel free to remove this and the /ie6/ directory if you have dropped IE6 support. +*/ +.cboxIE6 #cboxTopLeft{background:url(images/ie6/borderTopLeft.png);} +.cboxIE6 #cboxTopCenter{background:url(images/ie6/borderTopCenter.png);} +.cboxIE6 #cboxTopRight{background:url(images/ie6/borderTopRight.png);} +.cboxIE6 #cboxBottomLeft{background:url(images/ie6/borderBottomLeft.png);} +.cboxIE6 #cboxBottomCenter{background:url(images/ie6/borderBottomCenter.png);} +.cboxIE6 #cboxBottomRight{background:url(images/ie6/borderBottomRight.png);} +.cboxIE6 #cboxMiddleLeft{background:url(images/ie6/borderMiddleLeft.png);} +.cboxIE6 #cboxMiddleRight{background:url(images/ie6/borderMiddleRight.png);} + +.cboxIE6 #cboxTopLeft, +.cboxIE6 #cboxTopCenter, +.cboxIE6 #cboxTopRight, +.cboxIE6 #cboxBottomLeft, +.cboxIE6 #cboxBottomCenter, +.cboxIE6 #cboxBottomRight, +.cboxIE6 #cboxMiddleLeft, +.cboxIE6 #cboxMiddleRight { + _behavior: expression(this.src = this.src ? this.src : this.currentStyle.backgroundImage.split('"')[1], this.style.background = "none", this.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=" + this.src + ", sizingMethod='scale')"); +} diff --git a/src/static/jquery/colorbox/glizy/colorbox.css b/src/static/jquery/colorbox/glizy/colorbox.css new file mode 100644 index 0000000..d9a5e90 --- /dev/null +++ b/src/static/jquery/colorbox/glizy/colorbox.css @@ -0,0 +1,55 @@ +/* + Colorbox Core Style: + The following CSS is consistent between example themes and should not be altered. +*/ +#colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;} +#cboxWrapper {max-width:none;} +#cboxOverlay{position:fixed; width:100%; height:100%;} +#cboxMiddleLeft, #cboxBottomLeft{clear:left;} +#cboxContent{position:relative;} +#cboxLoadedContent{overflow:auto; -webkit-overflow-scrolling: touch;} +#cboxTitle{margin:0;} +#cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;} +#cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;} +.cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none; -ms-interpolation-mode:bicubic;} +.cboxIframe{width:100%; height:100%; display:block; border:0;} +#colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box; -moz-box-sizing:content-box; -webkit-box-sizing:content-box;} + +/* + User Style: + Change the following styles to modify the appearance of Colorbox. They are + ordered & tabbed in a way that represents the nesting of the generated HTML. +*/ +#cboxOverlay{background:#fff;} +#colorbox{outline:0;} + #cboxContent{margin-top:32px; overflow:visible; background:#000;} + .cboxIframe{background:#fff;} + #cboxError{padding:50px; border:1px solid #ccc;} + #cboxLoadedContent{background:#000; padding:1px;} + #cboxLoadingGraphic{background:url(images/loading.gif) no-repeat center center;} + #cboxLoadingOverlay{background:#000;} + #cboxTitle{position:absolute; bottom:-40px; left:0; color:#000; height: 40px;} + #cboxCurrent{position:absolute; top:-22px; right:205px; text-indent:-9999px;} + + /* these elements are buttons, and may need to have additional styles reset to avoid unwanted base styles */ + #cboxPrevious, #cboxNext, #cboxSlideshow, #cboxClose {border:0; padding:0; margin:0; overflow:visible; text-indent:-9999px; width:20px; height:20px; position:absolute; top:-20px; background:url(images/controls.png) no-repeat 0 0;} + + /* avoid outlines on :active (mouseclick), but preserve outlines on :focus (tabbed navigating) */ + #cboxPrevious:active, #cboxNext:active, #cboxSlideshow:active, #cboxClose:active {outline:0;} + + #cboxPrevious{background-position:0px 0px; right:44px;} + #cboxPrevious:hover{background-position:0px -25px;} + #cboxNext{background-position:-25px 0px; right:22px;} + #cboxNext:hover{background-position:-25px -25px;} + #cboxClose{background-position:-50px 0px; right:0;} + #cboxClose:hover{background-position:-50px -25px;} + .cboxSlideshow_on #cboxPrevious, .cboxSlideshow_off #cboxPrevious{right:66px;} + .cboxSlideshow_on #cboxSlideshow{background-position:-75px -25px; right:44px;} + .cboxSlideshow_on #cboxSlideshow:hover{background-position:-100px -25px;} + .cboxSlideshow_off #cboxSlideshow{background-position:-100px 0px; right:44px;} + .cboxSlideshow_off #cboxSlideshow:hover{background-position:-75px -25px;} + + +#cboxBottomCenter { + height: 43px; +} \ No newline at end of file diff --git a/src/static/jquery/colorbox/glizy/images/controls.png b/src/static/jquery/colorbox/glizy/images/controls.png new file mode 100755 index 0000000000000000000000000000000000000000..8569b57f1023685883cc8b2002f0763d4e79638d GIT binary patch literal 570 zcmV-A0>%A_P)<h;3K|Lk000e1NJLTq004ae001%w0{{R3Mo=WK0000>P)t-szrVkq zpP%pV@Bjb*hlhs`4-Y>-KYxFJ-{0SWfPer10MF0QmzS5fx3_O^Z?CVf=jZ45_xCR^ zFQ=!ckB^VX$H!k^U)R^yPft$(vqlU600F8=L_t(|UhUP{YV0r!08lO7oqd+}|G)Hl z!i3VX%tTOnA8I`$U=bY@A_e$=M%TN3lY!f+1HvLxga~{?BuQU~C<Ad2_;oN3WHEIT zVixrfBQnMq1bs2FrN;u*L^<6b0wFaj^<40Xh?nokjEE&sb+fxBKQ4=)$IGhGAs+G4 z_YtGS#~MFs4Rl@~V@rR>FD&cP&}kihULVfuoZsnL`Q~xuv-(kN1b~-H0OM{*xPj(Z zH!CNOhW5k_q@1|SN}boap^M|QnCG?;dN+Z!dVAB#n~UhURSK~f1n|Kh0M!3+UH|Rq zde^(&^{WhANm(+>RB+Do)wv+)v?Uoxo50g%A4s-!(kB#kNXfBF2?Rac)Y4OdYNDL( z4|yRqDRnG(a?X8zNABgQB&u$9*W%-n1wDO|M)&E6m%fjfBtF&nQELn5^(nRVcYJ19 zPd1#^{m<*$d7bf{j><Rhh|lUrvB`V?Qpx*iHzeHp=2v%DPF&d96SoEB#33tnrh7vd z$0yt8wh?-_z*@b%X;C~4;kZ>wU@?OCGtb_Kzxa>qde^)D4;WrrV64tv9smFU07*qo IM6N<$f+}YfD*ylh literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/glizy/images/loading.gif b/src/static/jquery/colorbox/glizy/images/loading.gif new file mode 100755 index 0000000000000000000000000000000000000000..19c67bbd0403f3f00d71bfb21a59cb6c55d482ab GIT binary patch literal 9427 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 F{|7Ce#lQdn literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-ar.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-ar.js new file mode 100755 index 0000000..6c4228c --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-ar.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Arabic (ar) + translated by: A.Rhman Sayes +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "الصورة {current} من {total}", + previous: "السابق", + next: "التالي", + close: "إغلاق", + xhrError: "حدث خطأ أثناء تحميل المحتوى.", + imgError: "حدث خطأ أثناء تحميل الصورة.", + slideshowStart: "تشغيل العرض", + slideshowStop: "إيقا٠العرض" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-bg.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-bg.js new file mode 100755 index 0000000..de7e4a1 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-bg.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Bulgarian (bg) + translated by: Marian M.Bida + site: webmax.bg +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "изображение {current} от {total}", + previous: "предишна", + next: "Ñледваща", + close: "затвори", + xhrError: "ÐеуÑпешно зареждане на Ñъдържанието.", + imgError: "ÐеуÑпешно зареждане на изображението.", + slideshowStart: "пуÑни Ñлайд-шоу", + slideshowStop: "Ñпри Ñлайд-шоу" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-ca.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-ca.js new file mode 100755 index 0000000..173c05f --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-ca.js @@ -0,0 +1,13 @@ +/* + jQuery Colorbox language configuration + language: Catala (ca) + translated by: eduard salla +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Imatge {current} de {total}", + previous: "Anterior", + next: "Següent", + close: "Tancar", + xhrError: "Error en la càrrega del contingut.", + imgError: "Error en la càrrega de la imatge." +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-cs.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-cs.js new file mode 100755 index 0000000..9649fd4 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-cs.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Czech (cs) + translated by: Filip Novak + site: mame.napilno.cz/filip-novak +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{current}. obrázek z {total}", + previous: "PÅ™edchozí", + next: "Následující", + close: "Zavřít", + xhrError: "Obsah se nepodaÅ™ilo naÄíst.", + imgError: "Obrázek se nepodaÅ™ilo naÄíst.", + slideshowStart: "Spustit slideshow", + slideshowStop: "Zastavit slideshow" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-da.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-da.js new file mode 100755 index 0000000..676fffe --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-da.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Danish (da) + translated by: danieljuhl + site: danieljuhl.dk +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Billede {current} af {total}", + previous: "Forrige", + next: "Næste", + close: "Luk", + xhrError: "Indholdet fejlede i indlæsningen.", + imgError: "Billedet fejlede i indlæsningen.", + slideshowStart: "Start slideshow", + slideshowStop: "Stop slideshow" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-de.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-de.js new file mode 100755 index 0000000..d489379 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-de.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: German (de) + translated by: wallenium +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Bild {current} von {total}", + previous: "Zurück", + next: "Vor", + close: "Schließen", + xhrError: "Dieser Inhalt konnte nicht geladen werden.", + imgError: "Dieses Bild konnte nicht geladen werden.", + slideshowStart: "Slideshow starten", + slideshowStop: "Slideshow anhalten" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-es.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-es.js new file mode 100755 index 0000000..11296fc --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-es.js @@ -0,0 +1,13 @@ +/* + jQuery Colorbox language configuration + language: Spanish (es) + translated by: migolo +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Imagen {current} de {total}", + previous: "Anterior", + next: "Siguiente", + close: "Cerrar", + xhrError: "Error en la carga del contenido.", + imgError: "Error en la carga de la imagen." +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-et.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-et.js new file mode 100755 index 0000000..60a4e88 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-et.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Estonian (et) + translated by: keevitaja +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{current}/{total}", + previous: "eelmine", + next: "järgmine", + close: "sulge", + xhrError: "Sisu ei õnnestunud laadida.", + imgError: "Pilti ei õnnestunud laadida.", + slideshowStart: "Käivita slaidid", + slideshowStop: "Peata slaidid" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-fa.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-fa.js new file mode 100755 index 0000000..32869a4 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-fa.js @@ -0,0 +1,18 @@ +/* + jQuery Colorbox language configuration + language: Persian (Farsi) + translated by: Mahdi Jaberzadeh Ansari (MJZSoft) + site: www.mjzsoft.ir + email: mahdijaberzadehansari (at) yahoo.co.uk + Please note : Persian language is right to left like arabic. +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "تصویر {current} از {total}", + previous: "قبلی", + next: "بعدی", + close: "بستن", + xhrError: "متاسÙانه محتویات مورد نظر قابل نمایش نیست.", + imgError: "متاسÙانه بارگذاری این عکس با مشکل مواجه شده است.", + slideshowStart: "آغاز نمایش خودکار", + slideshowStop: "توق٠نمایش خودکار" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-fi.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-fi.js new file mode 100755 index 0000000..ac03fe0 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-fi.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Finnish (fi) + translated by: Mikko +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Kuva {current} / {total}", + previous: "Edellinen", + next: "Seuraava", + close: "Sulje", + xhrError: "Sisällön lataaminen epäonnistui.", + imgError: "Kuvan lataaminen epäonnistui.", + slideshowStart: "Aloita kuvaesitys.", + slideshowStop: "Lopeta kuvaesitys." +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-fr.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-fr.js new file mode 100755 index 0000000..f76352b --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-fr.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: French (fr) + translated by: oaubert +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "image {current} sur {total}", + previous: "pr&eacute;c&eacute;dente", + next: "suivante", + close: "fermer", + xhrError: "Impossible de charger ce contenu.", + imgError: "Impossible de charger cette image.", + slideshowStart: "d&eacute;marrer la pr&eacute;sentation", + slideshowStop: "arr&ecirc;ter la pr&eacute;sentation" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-gl.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-gl.js new file mode 100755 index 0000000..3641b51 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-gl.js @@ -0,0 +1,13 @@ +/* + jQuery Colorbox language configuration + language: Galician (gl) + translated by: donatorouco +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Imaxe {current} de {total}", + previous: "Anterior", + next: "Seguinte", + close: "Pechar", + xhrError: "Erro na carga do contido.", + imgError: "Erro na carga da imaxe." +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-he.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-he.js new file mode 100755 index 0000000..78908e3 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-he.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Hebrew (he) + translated by: DavidCo + site: DavidCo.me +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "תמונה {current} מתוך {total}", + previous: "הקוד×", + next: "הב×", + close: "סגור", + xhrError: "שגי××” בטעינת התוכן.", + imgError: "שגי××” בטעינת התמונה.", + slideshowStart: "התחל מצגת", + slideshowStop: "עצור מצגת" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-hr.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-hr.js new file mode 100755 index 0000000..7eb62be --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-hr.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Croatian (hr) + translated by: Mladen Bicanic (base.hr) +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Slika {current} od {total}", + previous: "Prethodna", + next: "Sljedeća", + close: "Zatvori", + xhrError: "NeuspjeÅ¡no uÄitavanje sadržaja.", + imgError: "NeuspjeÅ¡no uÄitavanje slike.", + slideshowStart: "Pokreni slideshow", + slideshowStop: "Zaustavi slideshow" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-hu.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-hu.js new file mode 100755 index 0000000..72e9d36 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-hu.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Hungarian (hu) + translated by: kovadani +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{current}/{total} kép", + previous: "ElÅ‘zÅ‘", + next: "KövetkezÅ‘", + close: "Bezár", + xhrError: "A tartalmat nem sikerült betölteni.", + imgError: "A képet nem sikerült betölteni.", + slideshowStart: "Diavetítés indítása", + slideshowStop: "Diavetítés leállítása" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-id.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-id.js new file mode 100755 index 0000000..81a62df --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-id.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Indonesian (id) + translated by: sarwasunda +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "ke {current} dari {total}", + previous: "Sebelumnya", + next: "Berikutnya", + close: "Tutup", + xhrError: "Konten ini tidak dapat dimuat.", + imgError: "Gambar ini tidak dapat dimuat.", + slideshowStart: "Putar", + slideshowStop: "Berhenti" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-it.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-it.js new file mode 100755 index 0000000..2a4af64 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-it.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Italian (it) + translated by: maur8ino +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Immagine {current} di {total}", + previous: "Precedente", + next: "Successiva", + close: "Chiudi", + xhrError: "Errore nel caricamento del contenuto.", + imgError: "Errore nel caricamento dell'immagine.", + slideshowStart: "Inizia la presentazione", + slideshowStop: "Termina la presentazione" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-ja.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-ja.js new file mode 100755 index 0000000..5480de3 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-ja.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Japanaese (ja) + translated by: Hajime Fujimoto +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{total}枚中{current}æžšç›®", + previous: "å‰", + next: "次", + close: "é–‰ã˜ã‚‹", + xhrError: "コンテンツã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ", + imgError: "ç”»åƒã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ", + slideshowStart: "スライドショー開始", + slideshowStop: "スライドショー終了" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-kr.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-kr.js new file mode 100755 index 0000000..b95702b --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-kr.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Korean (kr) + translated by: lunareffect +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "ì´ {total} 중 {current}", + previous: "ì´ì „", + next: "다ìŒ", + close: "닫기", + xhrError: "컨í…츠를 불러오는 ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤.", + imgError: "ì´ë¯¸ì§€ë¥¼ 불러오는 ë° ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤.", + slideshowStart: "슬ë¼ì´ë“œì‡¼ 시작", + slideshowStop: "슬ë¼ì´ë“œì‡¼ 중지" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-lv.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-lv.js new file mode 100755 index 0000000..e376366 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-lv.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Latvian (lv) + translated by: Matiss Roberts Treinis + site: x0.lv +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "attÄ“ls {current} no {total}", + previous: "iepriekÅ¡Ä“jais", + next: "nÄkamais", + close: "aizvÄ“rt", + xhrError: "NeizdevÄs ielÄdÄ“t saturu.", + imgError: "NeizdevÄs ielÄdÄ“t attÄ“lu.", + slideshowStart: "sÄkt slaidrÄdi", + slideshowStop: "apturÄ“t slaidrÄdi" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-nl.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-nl.js new file mode 100755 index 0000000..dfc658e --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-nl.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Dutch (nl) + translated by: barryvdh +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Afbeelding {current} van {total}", + previous: "Vorige", + next: "Volgende", + close: "Sluiten", + xhrError: "Deze inhoud kan niet geladen worden.", + imgError: "Deze afbeelding kan niet geladen worden.", + slideshowStart: "Diashow starten", + slideshowStop: "Diashow stoppen" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-no.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-no.js new file mode 100755 index 0000000..277c5d3 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-no.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Norwegian (no) + translated by: lars-erik + site: markedspartner.no +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Bilde {current} av {total}", + previous: "Forrige", + next: "Neste", + close: "Lukk", + xhrError: "Feil ved lasting av innhold.", + imgError: "Feil ved lasting av bilde.", + slideshowStart: "Start lysbildefremvisning", + slideshowStop: "Stopp lysbildefremvisning" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-pl.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-pl.js new file mode 100755 index 0000000..1c04dae --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-pl.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Polski (pl) + translated by: Tomasz WasiÅ„ski + site: 2bevisible.pl +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{current}. obrazek z {total}", + previous: "Poprzedni", + next: "NastÄ™pny", + close: "Zamknij", + xhrError: "Nie udaÅ‚o siÄ™ zaÅ‚adować treÅ›ci.", + imgError: "Nie udaÅ‚o siÄ™ zaÅ‚adować obrazka.", + slideshowStart: "rozpocznij pokaz slajdów", + slideshowStop: "zatrzymaj pokaz slajdów" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-pt-br.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-pt-br.js new file mode 100755 index 0000000..73e948b --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-pt-br.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Brazilian Portuguese (pt-br) + translated by: ReinaldoMT +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Imagem {current} de {total}", + previous: "Anterior", + next: "Próxima", + close: "Fechar", + slideshowStart: "iniciar apresentação de slides", + slideshowStop: "parar apresentação de slides", + xhrError: "Erro ao carregar o conteúdo.", + imgError: "Erro ao carregar a imagem." +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-ro.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-ro.js new file mode 100755 index 0000000..0a461e2 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-ro.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Romanian (ro) + translated by: shurub3l +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "imagine {current} din {total}", + previous: "precedenta", + next: "următoarea", + close: "închideÈ›i", + xhrError: "Acest conÈ›inut nu poate fi încărcat.", + imgError: "Această imagine nu poate fi încărcată", + slideshowStart: "începeÈ›i prezentarea (slideshow)", + slideshowStop: "opriÈ›i prezentarea (slideshow)" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-ru.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-ru.js new file mode 100755 index 0000000..1d88b8c --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-ru.js @@ -0,0 +1,16 @@ +/* + jQuery Colorbox language configuration + language: Russian (ru) + translated by: Marfa + site: themarfa.name +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "изображение {current} из {total}", + previous: "назад", + next: "вперёд", + close: "закрыть", + xhrError: "Ðе удалоÑÑŒ загрузить Ñодержимое.", + imgError: "Ðе удалоÑÑŒ загрузить изображение.", + slideshowStart: "начать Ñлайд-шоу", + slideshowStop: "оÑтановить Ñлайд-шоу" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-si.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-si.js new file mode 100755 index 0000000..034b5b3 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-si.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Slovenian (si) + translated by: BoÅ¡tjan PiÅ¡ler (pisler.si) +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Slika {current} od {total}", + previous: "PrejÅ¡nja", + next: "Naslednja", + close: "Zapri", + xhrError: "Vsebine ni bilo mogoÄe naložiti.", + imgError: "Slike ni bilo mogoÄe naložiti.", + slideshowStart: "Zaženi prezentacijo", + slideshowStop: "Zaustavi prezentacijo" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-sk.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-sk.js new file mode 100755 index 0000000..faa9291 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-sk.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Slovak (sk) + translated by: Jaroslav Kostal +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "{current}. obrázok z {total}", + previous: "Predchádzajúci", + next: "Následujúci", + close: "ZatvoriÅ¥", + xhrError: "Obsah sa nepodarilo naÄítaÅ¥.", + imgError: "Obrázok sa nepodarilo naÄítaÅ¥.", + slideshowStart: "SpustiÅ¥ slideshow", + slideshowStop: "zastaviÅ¥ slideshow" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-sr.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-sr.js new file mode 100755 index 0000000..618e73c --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-sr.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Serbian (sr) + translated by: Sasa Stefanovic (baguje.com) +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Slika {current} od {total}", + previous: "Prethodna", + next: "Sledeća", + close: "Zatvori", + xhrError: "NeuspeÅ¡no uÄitavanje sadržaja.", + imgError: "NeuspeÅ¡no uÄitavanje slike.", + slideshowStart: "Pokreni slideshow", + slideshowStop: "Zaustavi slideshow" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-sv.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-sv.js new file mode 100755 index 0000000..01bb1d8 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-sv.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Swedish (sv) + translated by: Mattias Reichel +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Bild {current} av {total}", + previous: "FöregÃ¥ende", + next: "Nästa", + close: "Stäng", + xhrError: "InnehÃ¥llet kunde inte laddas.", + imgError: "Den här bilden kunde inte laddas.", + slideshowStart: "Starta bildspel", + slideshowStop: "Stoppa bildspel" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-tr.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-tr.js new file mode 100755 index 0000000..d467c2e --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-tr.js @@ -0,0 +1,19 @@ +/* + jQuery Colorbox language configuration + language: Turkish (tr) + translated by: Caner ÖNCEL + site: egonomik.com + + edited by: Sinan Eldem + www.sinaneldem.com.tr +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Görsel {current} / {total}", + previous: "Önceki", + next: "Sonraki", + close: "Kapat", + xhrError: "İçerik yüklenirken hata meydana geldi.", + imgError: "Resim yüklenirken hata meydana geldi.", + slideshowStart: "Slaytı BaÅŸlat", + slideshowStop: "Slaytı Durdur" +}); diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-uk.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-uk.js new file mode 100755 index 0000000..3f786d3 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-uk.js @@ -0,0 +1,16 @@ +/* + jQuery ColorBox language configuration + language: Ukrainian (uk) + translated by: Andrew + http://acisoftware.com.ua +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ {current} з {total}", + previous: "попереднє", + next: "наÑтупне", + close: "закрити", + xhrError: "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ вміÑÑ‚.", + imgError: "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ зображеннÑ.", + slideshowStart: "почати Ñлайд-шоу", + slideshowStop: "зупинити Ñлайд-шоу" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-zh-CN.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-zh-CN.js new file mode 100755 index 0000000..770d8ea --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-zh-CN.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Chinese Simplified (zh-CN) + translated by: zhao weiming +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "当å‰å›¾åƒ {current} 总共 {total}", + previous: "å‰ä¸€é¡µ", + next: "åŽä¸€é¡µ", + close: "关闭", + xhrError: "此内容无法加载", + imgError: "此图片无法加载", + slideshowStart: "开始播放幻ç¯ç‰‡", + slideshowStop: "åœæ­¢æ’­æ”¾å¹»ç¯ç‰‡" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/i18n/jquery.colorbox-zh-TW.js b/src/static/jquery/colorbox/i18n/jquery.colorbox-zh-TW.js new file mode 100755 index 0000000..b0c4f12 --- /dev/null +++ b/src/static/jquery/colorbox/i18n/jquery.colorbox-zh-TW.js @@ -0,0 +1,15 @@ +/* + jQuery Colorbox language configuration + language: Chinese Traditional (zh-TW) + translated by: Atans Chiu +*/ +jQuery.extend(jQuery.colorbox.settings, { + current: "圖片 {current} 總共 {total}", + previous: "上一é ", + next: "下一é ", + close: "關閉", + xhrError: "此內容加載失敗.", + imgError: "此圖片加載失敗.", + slideshowStart: "開始幻燈片", + slideshowStop: "çµæŸå¹»ç‡ˆç‰‡" +}); \ No newline at end of file diff --git a/src/static/jquery/colorbox/images/border.png b/src/static/jquery/colorbox/images/border.png new file mode 100644 index 0000000000000000000000000000000000000000..f463a10d838aeba263ff44e5c3578dfe7ba07648 GIT binary patch literal 112 zcmeAS@N?(olHy`uVBq!ia0vp^j6iI}$P6Txn<}3KQfvV}A+A9B|Ns9>Z_d99WHFWm z`2{zujf-{zawI%m978JNrXFPE1@f8<7E8}%%lTu>&#KnM&G`7uteHSj22WQ%mvv4F FO#q`M9f1G< literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/controls.png b/src/static/jquery/colorbox/images/controls.png new file mode 100644 index 0000000000000000000000000000000000000000..dcfd6fb9f178454613123d018bf742c8cc905df7 GIT binary patch literal 2893 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 literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/ie6/borderBottomCenter.png b/src/static/jquery/colorbox/images/ie6/borderBottomCenter.png new file mode 100644 index 0000000000000000000000000000000000000000..0d4475edf4e1ebb18d41db83915a21a9a6bc5977 GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{P$P6U+&JlA5QfvV}A+A9B|Ns9>Z_d99WHFWm z`2{zujf-{za>PAd978JNY7Z)cbT)5ruP-ra%e~G}wTijXxbw&apdf>%tDnm{r-UW| DknJ7# literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/ie6/borderBottomLeft.png b/src/static/jquery/colorbox/images/ie6/borderBottomLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..2775eba899d10d3dc6f8c4044ad69cb89a5f8499 GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw|3?!p1cPs@`>H$6>u0R?BQd3j6Z{H4KpFe*d zCJdtg|NlSbL?0`V#ZwaG7u>*5G5>gk!F7ua0ST$+oA`j@!JaOTAr*10r#A97C`hm- z3dKH%oOr{aLpj2LsW&>nlF|6W##ZJ(&Vq|N!)H`n4WCnOwE6XE$$JkZ%dBmlKK#!l q^N>Y<Lwo20uJsSMO05yTR+ukqCL+e}wKsed$OWFRelF{r5}E)#Izqqz literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/ie6/borderBottomRight.png b/src/static/jquery/colorbox/images/ie6/borderBottomRight.png new file mode 100644 index 0000000000000000000000000000000000000000..f7f51379c0857dd15bdbeac49f35c9ce81f47e23 GIT binary patch literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw|3?!p1cPs@`>H$6>u0R?BQd3j6Z{H4KpFe*d zCJdtg|NlSbL?0`V#ZwaG7u>*5G5>gk!F7ua0ST$+oA`j@p`I>|Ar*0Rk8R{_P!M3f za60r>rSy%6n-)#V7EE~whgkX^aO5~8RysR6J&4z+ys8}98}g<84F4bXKSykNqt5CV sw|{E#e<pv9@&3|UzPEq8{+4;yF-<EGV_(&KT^!^FPgg&ebxsLQ06+vq=>Px# literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/ie6/borderMiddleLeft.png b/src/static/jquery/colorbox/images/ie6/borderMiddleLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..a2d63d156e008a01fde9d2d68c531c34926a924a GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^qCm{Z$P6U8=aokQDYgKg5LY1m|NsA`H|O64NtXoq z1vjjXi*^HYL_A#_Ln`7}8#ZzRc@9(l|2O5zVPs<Xlew7T2~dQ=)78&qol`;+01^-z A-v9sr literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/ie6/borderMiddleRight.png b/src/static/jquery/colorbox/images/ie6/borderMiddleRight.png new file mode 100644 index 0000000000000000000000000000000000000000..fd7c3e849135d3b9abe895d7d8928d9f4228ecd9 GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^qCm{Z$P6U8=aokQDYgKg5LY1m|NsA`H|O64NtXoq z1vjjXi*^HYL_A#_Ln`7}4={29c?}Bx`}+i#nf@{S-+%jSJy3+f)78&qol`;+02r1W A-v9sr literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/ie6/borderTopCenter.png b/src/static/jquery/colorbox/images/ie6/borderTopCenter.png new file mode 100644 index 0000000000000000000000000000000000000000..2937a9cf9e25805fde6d954def25c3e6678fb61b GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{P$P6U+&JlA5QfvV}A+A9B|Ns9>Z_d99WHFWm z`2{zujf-{za>PAd978JNY7Z)cbT)5ruP@Q*%6-Zwv5L7-WU|;#pdf>%tDnm{r-UW| Dg{~b` literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/ie6/borderTopLeft.png b/src/static/jquery/colorbox/images/ie6/borderTopLeft.png new file mode 100644 index 0000000000000000000000000000000000000000..f9d458b5bba4a8cb84b9ee39a3844e258c1dcc20 GIT binary patch literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw|3?!p1cPs@`>H$6>u0R?qNKH*WfByXT?c0H} z|NsBDZcF_MWbu>)`2{yHR2W1EWLV6<eq6#zp?ED&JjBz*F{C1H?y-fu4Gsb>7bmi? zvo+on5)g6V<uEY~U{}rI6mevX7AfbvIaA^1Gy9UIHv?ANor=r%=yzMcpuCFV_0h={ pg3|x4{+PQ@=`LGsSFDV@z1;!PwQc`aJph`|;OXk;vd$@?2>?RfL6QIf literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/ie6/borderTopRight.png b/src/static/jquery/colorbox/images/ie6/borderTopRight.png new file mode 100644 index 0000000000000000000000000000000000000000..74b8583cfbb2e62a84ef04ba01064ecb4d70e72a GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^q9Dw|3?!p1cPs@`>H$6>u0R?Sq^70<1<#*9zkU05 zAmji4|I_}5*Z^5PB|(0{4Ga|#78wHb4Xz)Tc+|OiK2SW!)5S5QBChw?MqY;mf#VnJ z^}ggWcLpW1DoZ@PeSjlp!DT5|UGpg|kLp?vt)3@$_tm@JIJ0M=)Av-}@ro0Ud)StJ qkbTcp`HhbYABf8t?|b<Cc>Zq*G4@Nf;!!};89ZJ6T-G@yGywoYi%4?- literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/loading.gif b/src/static/jquery/colorbox/images/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..b4695d811d4f84ed693eff7b5e6b4d61a3e8c48d GIT binary patch literal 9427 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 BHE;j` literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/loading_background.png b/src/static/jquery/colorbox/images/loading_background.png new file mode 100644 index 0000000000000000000000000000000000000000..6ae83e697352da5bc75ff264f66e978c0928acee GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^8X(NU1|)m_?Z^dEDV{ElArXh)-rUH0z<}q-0eMH| zYUln%f-{b}&YI#V(lF-%L+N@I&VU0<v);c>UU{crc4h8@qAkJEl10~!7q>s;6wwG+ x;Lym#%7w)E5SqaM?W?}pgPY2~zL+0j{rLCv$(}1!-+=Zpc)I$ztaD0e0s!7!I-dXl literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/images/overlay.png b/src/static/jquery/colorbox/images/overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..53ea98f7003cf014cda2f764a7d982e405bd1b5f GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^av;pY3?xs=ZJr3E3<7*YT>t<7&(6-y!NDOSA|fs> z4iv@@^0LaF09818x;TbZ%z1NeAuof1z|jlq0?ZV)A8h5lQLnD@Q>uGq<+3e(rH8NF wGFLG_IXT618W25kEc*C=-akH|?*IRp8MKNmPAJ`FsRUW)>FVdQ&MBb@0FX~HaR2}S literal 0 HcmV?d00001 diff --git a/src/static/jquery/colorbox/jquery.colorbox-min.js b/src/static/jquery/colorbox/jquery.colorbox-min.js new file mode 100755 index 0000000..0ecc662 --- /dev/null +++ b/src/static/jquery/colorbox/jquery.colorbox-min.js @@ -0,0 +1,7 @@ +/*! + Colorbox v1.4.33 - 2013-10-31 + jQuery lightbox and modal window plugin + (c) 2013 Jack Moore - http://www.jacklmoore.com/colorbox + license: http://www.opensource.org/licenses/mit-license.php +*/ +(function(e,t,i){function o(i,o,n){var r=t.createElement(i);return o&&(r.id=Z+o),n&&(r.style.cssText=n),e(r)}function n(){return i.innerHeight?i.innerHeight:e(i).height()}function r(e){var t=k.length,i=(z+e)%t;return 0>i?t+i:i}function h(e,t){return Math.round((/%/.test(e)?("x"===t?E.width():n())/100:1)*parseInt(e,10))}function l(e,t){return e.photo||e.photoRegex.test(t)}function s(e,t){return e.retinaUrl&&i.devicePixelRatio>1?t.replace(e.photoRegex,e.retinaSuffix):t}function a(e){"contains"in g[0]&&!g[0].contains(e.target)&&(e.stopPropagation(),g.focus())}function d(){var t,i=e.data(N,Y);null==i?(B=e.extend({},X),console&&console.log&&console.log("Error: cboxElement missing settings object")):B=e.extend({},i);for(t in B)e.isFunction(B[t])&&"on"!==t.slice(0,2)&&(B[t]=B[t].call(N));B.rel=B.rel||N.rel||e(N).data("rel")||"nofollow",B.href=B.href||e(N).attr("href"),B.title=B.title||N.title,"string"==typeof B.href&&(B.href=e.trim(B.href))}function c(i,o){e(t).trigger(i),lt.triggerHandler(i),e.isFunction(o)&&o.call(N)}function u(i){q||(N=i,d(),k=e(N),z=0,"nofollow"!==B.rel&&(k=e("."+et).filter(function(){var t,i=e.data(this,Y);return i&&(t=e(this).data("rel")||i.rel||this.rel),t===B.rel}),z=k.index(N),-1===z&&(k=k.add(N),z=k.length-1)),w.css({opacity:parseFloat(B.opacity),cursor:B.overlayClose?"pointer":"auto",visibility:"visible"}).show(),J&&g.add(w).removeClass(J),B.className&&g.add(w).addClass(B.className),J=B.className,B.closeButton?K.html(B.close).appendTo(y):K.appendTo("<div/>"),U||(U=$=!0,g.css({visibility:"hidden",display:"block"}),H=o(st,"LoadedContent","width:0; height:0; overflow:hidden"),y.css({width:"",height:""}).append(H),O=x.height()+C.height()+y.outerHeight(!0)-y.height(),_=b.width()+T.width()+y.outerWidth(!0)-y.width(),D=H.outerHeight(!0),A=H.outerWidth(!0),B.w=h(B.initialWidth,"x"),B.h=h(B.initialHeight,"y"),H.css({width:"",height:B.h}),Q.position(),c(tt,B.onOpen),P.add(L).hide(),g.focus(),B.trapFocus&&t.addEventListener&&(t.addEventListener("focus",a,!0),lt.one(rt,function(){t.removeEventListener("focus",a,!0)})),B.returnFocus&&lt.one(rt,function(){e(N).focus()})),m())}function f(){!g&&t.body&&(V=!1,E=e(i),g=o(st).attr({id:Y,"class":e.support.opacity===!1?Z+"IE":"",role:"dialog",tabindex:"-1"}).hide(),w=o(st,"Overlay").hide(),F=e([o(st,"LoadingOverlay")[0],o(st,"LoadingGraphic")[0]]),v=o(st,"Wrapper"),y=o(st,"Content").append(L=o(st,"Title"),S=o(st,"Current"),I=e('<button type="button"/>').attr({id:Z+"Previous"}),R=e('<button type="button"/>').attr({id:Z+"Next"}),M=o("button","Slideshow"),F),K=e('<button type="button"/>').attr({id:Z+"Close"}),v.append(o(st).append(o(st,"TopLeft"),x=o(st,"TopCenter"),o(st,"TopRight")),o(st,!1,"clear:left").append(b=o(st,"MiddleLeft"),y,T=o(st,"MiddleRight")),o(st,!1,"clear:left").append(o(st,"BottomLeft"),C=o(st,"BottomCenter"),o(st,"BottomRight"))).find("div div").css({"float":"left"}),W=o(st,!1,"position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;"),P=R.add(I).add(S).add(M),e(t.body).append(w,g.append(v,W)))}function p(){function i(e){e.which>1||e.shiftKey||e.altKey||e.metaKey||e.ctrlKey||(e.preventDefault(),u(this))}return g?(V||(V=!0,R.click(function(){Q.next()}),I.click(function(){Q.prev()}),K.click(function(){Q.close()}),w.click(function(){B.overlayClose&&Q.close()}),e(t).bind("keydown."+Z,function(e){var t=e.keyCode;U&&B.escKey&&27===t&&(e.preventDefault(),Q.close()),U&&B.arrowKey&&k[1]&&!e.altKey&&(37===t?(e.preventDefault(),I.click()):39===t&&(e.preventDefault(),R.click()))}),e.isFunction(e.fn.on)?e(t).on("click."+Z,"."+et,i):e("."+et).live("click."+Z,i)),!0):!1}function m(){var n,r,a,u=Q.prep,f=++at;$=!0,j=!1,N=k[z],d(),c(ht),c(it,B.onLoad),B.h=B.height?h(B.height,"y")-D-O:B.innerHeight&&h(B.innerHeight,"y"),B.w=B.width?h(B.width,"x")-A-_:B.innerWidth&&h(B.innerWidth,"x"),B.mw=B.w,B.mh=B.h,B.maxWidth&&(B.mw=h(B.maxWidth,"x")-A-_,B.mw=B.w&&B.w<B.mw?B.w:B.mw),B.maxHeight&&(B.mh=h(B.maxHeight,"y")-D-O,B.mh=B.h&&B.h<B.mh?B.h:B.mh),n=B.href,G=setTimeout(function(){F.show()},100),B.inline?(a=o(st).hide().insertBefore(e(n)[0]),lt.one(ht,function(){a.replaceWith(H.children())}),u(e(n))):B.iframe?u(" "):B.html?u(B.html):l(B,n)?(n=s(B,n),j=t.createElement("img"),e(j).addClass(Z+"Photo").bind("error",function(){B.title=!1,u(o(st,"Error").html(B.imgError))}).one("load",function(){var t;f===at&&(e.each(["alt","longdesc","aria-describedby"],function(t,i){var o=e(N).attr(i)||e(N).attr("data-"+i);o&&j.setAttribute(i,o)}),B.retinaImage&&i.devicePixelRatio>1&&(j.height=j.height/i.devicePixelRatio,j.width=j.width/i.devicePixelRatio),B.scalePhotos&&(r=function(){j.height-=j.height*t,j.width-=j.width*t},B.mw&&j.width>B.mw&&(t=(j.width-B.mw)/j.width,r()),B.mh&&j.height>B.mh&&(t=(j.height-B.mh)/j.height,r())),B.h&&(j.style.marginTop=Math.max(B.mh-j.height,0)/2+"px"),k[1]&&(B.loop||k[z+1])&&(j.style.cursor="pointer",j.onclick=function(){Q.next()}),j.style.width=j.width+"px",j.style.height=j.height+"px",setTimeout(function(){u(j)},1))}),setTimeout(function(){j.src=n},1)):n&&W.load(n,B.data,function(t,i){f===at&&u("error"===i?o(st,"Error").html(B.xhrError):e(this).contents())})}var w,g,v,y,x,b,T,C,k,E,H,W,F,L,S,M,R,I,K,P,B,O,_,D,A,N,z,j,U,$,q,G,Q,J,V,X={html:!1,photo:!1,iframe:!1,inline:!1,transition:"elastic",speed:300,fadeOut:300,width:!1,initialWidth:"600",innerWidth:!1,maxWidth:!1,height:!1,initialHeight:"450",innerHeight:!1,maxHeight:!1,scalePhotos:!0,scrolling:!0,href:!1,title:!1,rel:!1,opacity:.9,preloading:!0,className:!1,overlayClose:!0,escKey:!0,arrowKey:!0,top:!1,bottom:!1,left:!1,right:!1,fixed:!1,data:void 0,closeButton:!0,fastIframe:!0,open:!1,reposition:!0,loop:!0,slideshow:!1,slideshowAuto:!0,slideshowSpeed:2500,slideshowStart:"start slideshow",slideshowStop:"stop slideshow",photoRegex:/\.(gif|png|jp(e|g|eg)|bmp|ico|webp)((#|\?).*)?$/i,retinaImage:!1,retinaUrl:!1,retinaSuffix:"@2x.$1",current:"image {current} of {total}",previous:"previous",next:"next",close:"close",xhrError:"This content failed to load.",imgError:"This image failed to load.",returnFocus:!0,trapFocus:!0,onOpen:!1,onLoad:!1,onComplete:!1,onCleanup:!1,onClosed:!1},Y="colorbox",Z="cbox",et=Z+"Element",tt=Z+"_open",it=Z+"_load",ot=Z+"_complete",nt=Z+"_cleanup",rt=Z+"_closed",ht=Z+"_purge",lt=e("<a/>"),st="div",at=0,dt={},ct=function(){function e(){clearTimeout(h)}function t(){(B.loop||k[z+1])&&(e(),h=setTimeout(Q.next,B.slideshowSpeed))}function i(){M.html(B.slideshowStop).unbind(s).one(s,o),lt.bind(ot,t).bind(it,e),g.removeClass(l+"off").addClass(l+"on")}function o(){e(),lt.unbind(ot,t).unbind(it,e),M.html(B.slideshowStart).unbind(s).one(s,function(){Q.next(),i()}),g.removeClass(l+"on").addClass(l+"off")}function n(){r=!1,M.hide(),e(),lt.unbind(ot,t).unbind(it,e),g.removeClass(l+"off "+l+"on")}var r,h,l=Z+"Slideshow_",s="click."+Z;return function(){r?B.slideshow||(lt.unbind(nt,n),n()):B.slideshow&&k[1]&&(r=!0,lt.one(nt,n),B.slideshowAuto?i():o(),M.show())}}();e.colorbox||(e(f),Q=e.fn[Y]=e[Y]=function(t,i){var o=this;if(t=t||{},f(),p()){if(e.isFunction(o))o=e("<a/>"),t.open=!0;else if(!o[0])return o;i&&(t.onComplete=i),o.each(function(){e.data(this,Y,e.extend({},e.data(this,Y)||X,t))}).addClass(et),(e.isFunction(t.open)&&t.open.call(o)||t.open)&&u(o[0])}return o},Q.position=function(t,i){function o(){x[0].style.width=C[0].style.width=y[0].style.width=parseInt(g[0].style.width,10)-_+"px",y[0].style.height=b[0].style.height=T[0].style.height=parseInt(g[0].style.height,10)-O+"px"}var r,l,s,a=0,d=0,c=g.offset();if(E.unbind("resize."+Z),g.css({top:-9e4,left:-9e4}),l=E.scrollTop(),s=E.scrollLeft(),B.fixed?(c.top-=l,c.left-=s,g.css({position:"fixed"})):(a=l,d=s,g.css({position:"absolute"})),d+=B.right!==!1?Math.max(E.width()-B.w-A-_-h(B.right,"x"),0):B.left!==!1?h(B.left,"x"):Math.round(Math.max(E.width()-B.w-A-_,0)/2),a+=B.bottom!==!1?Math.max(n()-B.h-D-O-h(B.bottom,"y"),0):B.top!==!1?h(B.top,"y"):Math.round(Math.max(n()-B.h-D-O,0)/2),g.css({top:c.top,left:c.left,visibility:"visible"}),v[0].style.width=v[0].style.height="9999px",r={width:B.w+A+_,height:B.h+D+O,top:a,left:d},t){var u=0;e.each(r,function(e){return r[e]!==dt[e]?(u=t,void 0):void 0}),t=u}dt=r,t||g.css(r),g.dequeue().animate(r,{duration:t||0,complete:function(){o(),$=!1,v[0].style.width=B.w+A+_+"px",v[0].style.height=B.h+D+O+"px",B.reposition&&setTimeout(function(){E.bind("resize."+Z,Q.position)},1),i&&i()},step:o})},Q.resize=function(e){var t;U&&(e=e||{},e.width&&(B.w=h(e.width,"x")-A-_),e.innerWidth&&(B.w=h(e.innerWidth,"x")),H.css({width:B.w}),e.height&&(B.h=h(e.height,"y")-D-O),e.innerHeight&&(B.h=h(e.innerHeight,"y")),e.innerHeight||e.height||(t=H.scrollTop(),H.css({height:"auto"}),B.h=H.height()),H.css({height:B.h}),t&&H.scrollTop(t),Q.position("none"===B.transition?0:B.speed))},Q.prep=function(i){function n(){return B.w=B.w||H.width(),B.w=B.mw&&B.mw<B.w?B.mw:B.w,B.w}function h(){return B.h=B.h||H.height(),B.h=B.mh&&B.mh<B.h?B.mh:B.h,B.h}if(U){var a,d="none"===B.transition?0:B.speed;H.empty().remove(),H=o(st,"LoadedContent").append(i),H.hide().appendTo(W.show()).css({width:n(),overflow:B.scrolling?"auto":"hidden"}).css({height:h()}).prependTo(y),W.hide(),e(j).css({"float":"none"}),a=function(){function i(){e.support.opacity===!1&&g[0].style.removeAttribute("filter")}var n,h,a=k.length,u="frameBorder",f="allowTransparency";U&&(h=function(){clearTimeout(G),F.hide(),c(ot,B.onComplete)},L.html(B.title).add(H).show(),a>1?("string"==typeof B.current&&S.html(B.current.replace("{current}",z+1).replace("{total}",a)).show(),R[B.loop||a-1>z?"show":"hide"]().html(B.next),I[B.loop||z?"show":"hide"]().html(B.previous),ct(),B.preloading&&e.each([r(-1),r(1)],function(){var i,o,n=k[this],r=e.data(n,Y);r&&r.href?(i=r.href,e.isFunction(i)&&(i=i.call(n))):i=e(n).attr("href"),i&&l(r,i)&&(i=s(r,i),o=t.createElement("img"),o.src=i)})):P.hide(),B.iframe?(n=o("iframe")[0],u in n&&(n[u]=0),f in n&&(n[f]="true"),B.scrolling||(n.scrolling="no"),e(n).attr({src:B.href,name:(new Date).getTime(),"class":Z+"Iframe",allowFullScreen:!0,webkitAllowFullScreen:!0,mozallowfullscreen:!0}).one("load",h).appendTo(H),lt.one(ht,function(){n.src="//about:blank"}),B.fastIframe&&e(n).trigger("load")):h(),"fade"===B.transition?g.fadeTo(d,1,i):i())},"fade"===B.transition?g.fadeTo(d,0,function(){Q.position(0,a)}):Q.position(d,a)}},Q.next=function(){!$&&k[1]&&(B.loop||k[z+1])&&(z=r(1),u(k[z]))},Q.prev=function(){!$&&k[1]&&(B.loop||z)&&(z=r(-1),u(k[z]))},Q.close=function(){U&&!q&&(q=!0,U=!1,c(nt,B.onCleanup),E.unbind("."+Z),w.fadeTo(B.fadeOut||0,0),g.stop().fadeTo(B.fadeOut||0,0,function(){g.add(w).css({opacity:1,cursor:"auto"}).hide(),c(ht),H.empty().remove(),setTimeout(function(){q=!1,c(rt,B.onClosed)},1)}))},Q.remove=function(){g&&(g.stop(),e.colorbox.close(),g.stop().remove(),w.remove(),q=!1,g=null,e("."+et).removeData(Y).removeClass(et),e(t).unbind("click."+Z))},Q.element=function(){return e(N)},Q.settings=X)})(jQuery,document,window); \ No newline at end of file diff --git a/src/static/jquery/colorbox/jquery.colorbox.js b/src/static/jquery/colorbox/jquery.colorbox.js new file mode 100755 index 0000000..321e5a2 --- /dev/null +++ b/src/static/jquery/colorbox/jquery.colorbox.js @@ -0,0 +1,1084 @@ +/*! + Colorbox v1.4.33 - 2013-10-31 + jQuery lightbox and modal window plugin + (c) 2013 Jack Moore - http://www.jacklmoore.com/colorbox + license: http://www.opensource.org/licenses/mit-license.php +*/ +(function ($, document, window) { + var + // Default settings object. + // See http://jacklmoore.com/colorbox for details. + defaults = { + // data sources + html: false, + photo: false, + iframe: false, + inline: false, + + // behavior and appearance + transition: "elastic", + speed: 300, + fadeOut: 300, + width: false, + initialWidth: "600", + innerWidth: false, + maxWidth: false, + height: false, + initialHeight: "450", + innerHeight: false, + maxHeight: false, + scalePhotos: true, + scrolling: true, + href: false, + title: false, + rel: false, + opacity: 0.9, + preloading: true, + className: false, + overlayClose: true, + escKey: true, + arrowKey: true, + top: false, + bottom: false, + left: false, + right: false, + fixed: false, + data: undefined, + closeButton: true, + fastIframe: true, + open: false, + reposition: true, + loop: true, + slideshow: false, + slideshowAuto: true, + slideshowSpeed: 2500, + slideshowStart: "start slideshow", + slideshowStop: "stop slideshow", + photoRegex: /\.(gif|png|jp(e|g|eg)|bmp|ico|webp)((#|\?).*)?$/i, + + // alternate image paths for high-res displays + retinaImage: false, + retinaUrl: false, + retinaSuffix: '@2x.$1', + + // internationalization + current: "image {current} of {total}", + previous: "previous", + next: "next", + close: "close", + xhrError: "This content failed to load.", + imgError: "This image failed to load.", + + // accessbility + returnFocus: true, + trapFocus: true, + + // callbacks + onOpen: false, + onLoad: false, + onComplete: false, + onCleanup: false, + onClosed: false + }, + + // Abstracting the HTML and event identifiers for easy rebranding + colorbox = 'colorbox', + prefix = 'cbox', + boxElement = prefix + 'Element', + + // Events + event_open = prefix + '_open', + event_load = prefix + '_load', + event_complete = prefix + '_complete', + event_cleanup = prefix + '_cleanup', + event_closed = prefix + '_closed', + event_purge = prefix + '_purge', + + // Cached jQuery Object Variables + $overlay, + $box, + $wrap, + $content, + $topBorder, + $leftBorder, + $rightBorder, + $bottomBorder, + $related, + $window, + $loaded, + $loadingBay, + $loadingOverlay, + $title, + $current, + $slideshow, + $next, + $prev, + $close, + $groupControls, + $events = $('<a/>'), // $([]) would be prefered, but there is an issue with jQuery 1.4.2 + + // Variables for cached values or use across multiple functions + settings, + interfaceHeight, + interfaceWidth, + loadedHeight, + loadedWidth, + element, + index, + photo, + open, + active, + closing, + loadingTimer, + publicMethod, + div = "div", + className, + requests = 0, + previousCSS = {}, + init; + + // **************** + // HELPER FUNCTIONS + // **************** + + // Convenience function for creating new jQuery objects + function $tag(tag, id, css) { + var element = document.createElement(tag); + + if (id) { + element.id = prefix + id; + } + + if (css) { + element.style.cssText = css; + } + + return $(element); + } + + // Get the window height using innerHeight when available to avoid an issue with iOS + // http://bugs.jquery.com/ticket/6724 + function winheight() { + return window.innerHeight ? window.innerHeight : $(window).height(); + } + + // Determine the next and previous members in a group. + function getIndex(increment) { + var + max = $related.length, + newIndex = (index + increment) % max; + + return (newIndex < 0) ? max + newIndex : newIndex; + } + + // Convert '%' and 'px' values to integers + function setSize(size, dimension) { + return Math.round((/%/.test(size) ? ((dimension === 'x' ? $window.width() : winheight()) / 100) : 1) * parseInt(size, 10)); + } + + // Checks an href to see if it is a photo. + // There is a force photo option (photo: true) for hrefs that cannot be matched by the regex. + function isImage(settings, url) { + return settings.photo || settings.photoRegex.test(url); + } + + function retinaUrl(settings, url) { + return settings.retinaUrl && window.devicePixelRatio > 1 ? url.replace(settings.photoRegex, settings.retinaSuffix) : url; + } + + function trapFocus(e) { + if ('contains' in $box[0] && !$box[0].contains(e.target)) { + e.stopPropagation(); + $box.focus(); + } + } + + // Assigns function results to their respective properties + function makeSettings() { + var i, + data = $.data(element, colorbox); + + if (data == null) { + settings = $.extend({}, defaults); + if (console && console.log) { + console.log('Error: cboxElement missing settings object'); + } + } else { + settings = $.extend({}, data); + } + + for (i in settings) { + if ($.isFunction(settings[i]) && i.slice(0, 2) !== 'on') { // checks to make sure the function isn't one of the callbacks, they will be handled at the appropriate time. + settings[i] = settings[i].call(element); + } + } + + settings.rel = settings.rel || element.rel || $(element).data('rel') || 'nofollow'; + settings.href = settings.href || $(element).attr('href'); + settings.title = settings.title || element.title; + + if (typeof settings.href === "string") { + settings.href = $.trim(settings.href); + } + } + + function trigger(event, callback) { + // for external use + $(document).trigger(event); + + // for internal use + $events.triggerHandler(event); + + if ($.isFunction(callback)) { + callback.call(element); + } + } + + + var slideshow = (function(){ + var active, + className = prefix + "Slideshow_", + click = "click." + prefix, + timeOut; + + function clear () { + clearTimeout(timeOut); + } + + function set() { + if (settings.loop || $related[index + 1]) { + clear(); + timeOut = setTimeout(publicMethod.next, settings.slideshowSpeed); + } + } + + function start() { + $slideshow + .html(settings.slideshowStop) + .unbind(click) + .one(click, stop); + + $events + .bind(event_complete, set) + .bind(event_load, clear); + + $box.removeClass(className + "off").addClass(className + "on"); + } + + function stop() { + clear(); + + $events + .unbind(event_complete, set) + .unbind(event_load, clear); + + $slideshow + .html(settings.slideshowStart) + .unbind(click) + .one(click, function () { + publicMethod.next(); + start(); + }); + + $box.removeClass(className + "on").addClass(className + "off"); + } + + function reset() { + active = false; + $slideshow.hide(); + clear(); + $events + .unbind(event_complete, set) + .unbind(event_load, clear); + $box.removeClass(className + "off " + className + "on"); + } + + return function(){ + if (active) { + if (!settings.slideshow) { + $events.unbind(event_cleanup, reset); + reset(); + } + } else { + if (settings.slideshow && $related[1]) { + active = true; + $events.one(event_cleanup, reset); + if (settings.slideshowAuto) { + start(); + } else { + stop(); + } + $slideshow.show(); + } + } + }; + + }()); + + + function launch(target) { + if (!closing) { + + element = target; + + makeSettings(); + + $related = $(element); + + index = 0; + + if (settings.rel !== 'nofollow') { + $related = $('.' + boxElement).filter(function () { + var data = $.data(this, colorbox), + relRelated; + + if (data) { + relRelated = $(this).data('rel') || data.rel || this.rel; + } + + return (relRelated === settings.rel); + }); + index = $related.index(element); + + // Check direct calls to Colorbox. + if (index === -1) { + $related = $related.add(element); + index = $related.length - 1; + } + } + + $overlay.css({ + opacity: parseFloat(settings.opacity), + cursor: settings.overlayClose ? "pointer" : "auto", + visibility: 'visible' + }).show(); + + + if (className) { + $box.add($overlay).removeClass(className); + } + if (settings.className) { + $box.add($overlay).addClass(settings.className); + } + className = settings.className; + + if (settings.closeButton) { + $close.html(settings.close).appendTo($content); + } else { + $close.appendTo('<div/>'); + } + + if (!open) { + open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys. + + // Show colorbox so the sizes can be calculated in older versions of jQuery + $box.css({visibility:'hidden', display:'block'}); + + $loaded = $tag(div, 'LoadedContent', 'width:0; height:0; overflow:hidden'); + $content.css({width:'', height:''}).append($loaded); + + // Cache values needed for size calculations + interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height(); + interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width(); + loadedHeight = $loaded.outerHeight(true); + loadedWidth = $loaded.outerWidth(true); + + // Opens inital empty Colorbox prior to content being loaded. + settings.w = setSize(settings.initialWidth, 'x'); + settings.h = setSize(settings.initialHeight, 'y'); + $loaded.css({width:'', height:settings.h}); + publicMethod.position(); + + trigger(event_open, settings.onOpen); + + $groupControls.add($title).hide(); + + $box.focus(); + + if (settings.trapFocus) { + // Confine focus to the modal + // Uses event capturing that is not supported in IE8- + if (document.addEventListener) { + + document.addEventListener('focus', trapFocus, true); + + $events.one(event_closed, function () { + document.removeEventListener('focus', trapFocus, true); + }); + } + } + + // Return focus on closing + if (settings.returnFocus) { + $events.one(event_closed, function () { + $(element).focus(); + }); + } + } + load(); + } + } + + // Colorbox's markup needs to be added to the DOM prior to being called + // so that the browser will go ahead and load the CSS background images. + function appendHTML() { + if (!$box && document.body) { + init = false; + $window = $(window); + $box = $tag(div).attr({ + id: colorbox, + 'class': $.support.opacity === false ? prefix + 'IE' : '', // class for optional IE8 & lower targeted CSS. + role: 'dialog', + tabindex: '-1' + }).hide(); + $overlay = $tag(div, "Overlay").hide(); + $loadingOverlay = $([$tag(div, "LoadingOverlay")[0],$tag(div, "LoadingGraphic")[0]]); + $wrap = $tag(div, "Wrapper"); + $content = $tag(div, "Content").append( + $title = $tag(div, "Title"), + $current = $tag(div, "Current"), + $prev = $('<button type="button"/>').attr({id:prefix+'Previous'}), + $next = $('<button type="button"/>').attr({id:prefix+'Next'}), + $slideshow = $tag('button', "Slideshow"), + $loadingOverlay + ); + + $close = $('<button type="button"/>').attr({id:prefix+'Close'}); + + $wrap.append( // The 3x3 Grid that makes up Colorbox + $tag(div).append( + $tag(div, "TopLeft"), + $topBorder = $tag(div, "TopCenter"), + $tag(div, "TopRight") + ), + $tag(div, false, 'clear:left').append( + $leftBorder = $tag(div, "MiddleLeft"), + $content, + $rightBorder = $tag(div, "MiddleRight") + ), + $tag(div, false, 'clear:left').append( + $tag(div, "BottomLeft"), + $bottomBorder = $tag(div, "BottomCenter"), + $tag(div, "BottomRight") + ) + ).find('div div').css({'float': 'left'}); + + $loadingBay = $tag(div, false, 'position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;'); + + $groupControls = $next.add($prev).add($current).add($slideshow); + + $(document.body).append($overlay, $box.append($wrap, $loadingBay)); + } + } + + // Add Colorbox's event bindings + function addBindings() { + function clickHandler(e) { + // ignore non-left-mouse-clicks and clicks modified with ctrl / command, shift, or alt. + // See: http://jacklmoore.com/notes/click-events/ + if (!(e.which > 1 || e.shiftKey || e.altKey || e.metaKey || e.ctrlKey)) { + e.preventDefault(); + launch(this); + } + } + + if ($box) { + if (!init) { + init = true; + + // Anonymous functions here keep the public method from being cached, thereby allowing them to be redefined on the fly. + $next.click(function () { + publicMethod.next(); + }); + $prev.click(function () { + publicMethod.prev(); + }); + $close.click(function () { + publicMethod.close(); + }); + $overlay.click(function () { + if (settings.overlayClose) { + publicMethod.close(); + } + }); + + // Key Bindings + $(document).bind('keydown.' + prefix, function (e) { + var key = e.keyCode; + if (open && settings.escKey && key === 27) { + e.preventDefault(); + publicMethod.close(); + } + if (open && settings.arrowKey && $related[1] && !e.altKey) { + if (key === 37) { + e.preventDefault(); + $prev.click(); + } else if (key === 39) { + e.preventDefault(); + $next.click(); + } + } + }); + + if ($.isFunction($.fn.on)) { + // For jQuery 1.7+ + $(document).on('click.'+prefix, '.'+boxElement, clickHandler); + } else { + // For jQuery 1.3.x -> 1.6.x + // This code is never reached in jQuery 1.9, so do not contact me about 'live' being removed. + // This is not here for jQuery 1.9, it's here for legacy users. + $('.'+boxElement).live('click.'+prefix, clickHandler); + } + } + return true; + } + return false; + } + + // Don't do anything if Colorbox already exists. + if ($.colorbox) { + return; + } + + // Append the HTML when the DOM loads + $(appendHTML); + + + // **************** + // PUBLIC FUNCTIONS + // Usage format: $.colorbox.close(); + // Usage from within an iframe: parent.jQuery.colorbox.close(); + // **************** + + publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) { + var $this = this; + + options = options || {}; + + appendHTML(); + + if (addBindings()) { + if ($.isFunction($this)) { // assume a call to $.colorbox + $this = $('<a/>'); + options.open = true; + } else if (!$this[0]) { // colorbox being applied to empty collection + return $this; + } + + if (callback) { + options.onComplete = callback; + } + + $this.each(function () { + $.data(this, colorbox, $.extend({}, $.data(this, colorbox) || defaults, options)); + }).addClass(boxElement); + + if (($.isFunction(options.open) && options.open.call($this)) || options.open) { + launch($this[0]); + } + } + + return $this; + }; + + publicMethod.position = function (speed, loadedCallback) { + var + css, + top = 0, + left = 0, + offset = $box.offset(), + scrollTop, + scrollLeft; + + $window.unbind('resize.' + prefix); + + // remove the modal so that it doesn't influence the document width/height + $box.css({top: -9e4, left: -9e4}); + + scrollTop = $window.scrollTop(); + scrollLeft = $window.scrollLeft(); + + if (settings.fixed) { + offset.top -= scrollTop; + offset.left -= scrollLeft; + $box.css({position: 'fixed'}); + } else { + top = scrollTop; + left = scrollLeft; + $box.css({position: 'absolute'}); + } + + // keeps the top and left positions within the browser's viewport. + if (settings.right !== false) { + left += Math.max($window.width() - settings.w - loadedWidth - interfaceWidth - setSize(settings.right, 'x'), 0); + } else if (settings.left !== false) { + left += setSize(settings.left, 'x'); + } else { + left += Math.round(Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2); + } + + if (settings.bottom !== false) { + top += Math.max(winheight() - settings.h - loadedHeight - interfaceHeight - setSize(settings.bottom, 'y'), 0); + } else if (settings.top !== false) { + top += setSize(settings.top, 'y'); + } else { + top += Math.round(Math.max(winheight() - settings.h - loadedHeight - interfaceHeight, 0) / 2); + } + + $box.css({top: offset.top, left: offset.left, visibility:'visible'}); + + // this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly, + // but it has to be shrank down around the size of div#colorbox when it's done. If not, + // it can invoke an obscure IE bug when using iframes. + $wrap[0].style.width = $wrap[0].style.height = "9999px"; + + function modalDimensions() { + $topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = (parseInt($box[0].style.width,10) - interfaceWidth)+'px'; + $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = (parseInt($box[0].style.height,10) - interfaceHeight)+'px'; + } + + css = {width: settings.w + loadedWidth + interfaceWidth, height: settings.h + loadedHeight + interfaceHeight, top: top, left: left}; + + // setting the speed to 0 if the content hasn't changed size or position + if (speed) { + var tempSpeed = 0; + $.each(css, function(i){ + if (css[i] !== previousCSS[i]) { + tempSpeed = speed; + return; + } + }); + speed = tempSpeed; + } + + previousCSS = css; + + if (!speed) { + $box.css(css); + } + + $box.dequeue().animate(css, { + duration: speed || 0, + complete: function () { + modalDimensions(); + + active = false; + + // shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation. + $wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px"; + $wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px"; + + if (settings.reposition) { + setTimeout(function () { // small delay before binding onresize due to an IE8 bug. + $window.bind('resize.' + prefix, publicMethod.position); + }, 1); + } + + if (loadedCallback) { + loadedCallback(); + } + }, + step: modalDimensions + }); + }; + + publicMethod.resize = function (options) { + var scrolltop; + + if (open) { + options = options || {}; + + if (options.width) { + settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth; + } + + if (options.innerWidth) { + settings.w = setSize(options.innerWidth, 'x'); + } + + $loaded.css({width: settings.w}); + + if (options.height) { + settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight; + } + + if (options.innerHeight) { + settings.h = setSize(options.innerHeight, 'y'); + } + + if (!options.innerHeight && !options.height) { + scrolltop = $loaded.scrollTop(); + $loaded.css({height: "auto"}); + settings.h = $loaded.height(); + } + + $loaded.css({height: settings.h}); + + if(scrolltop) { + $loaded.scrollTop(scrolltop); + } + + publicMethod.position(settings.transition === "none" ? 0 : settings.speed); + } + }; + + publicMethod.prep = function (object) { + if (!open) { + return; + } + + var callback, speed = settings.transition === "none" ? 0 : settings.speed; + + $loaded.empty().remove(); // Using empty first may prevent some IE7 issues. + + $loaded = $tag(div, 'LoadedContent').append(object); + + function getWidth() { + settings.w = settings.w || $loaded.width(); + settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w; + return settings.w; + } + function getHeight() { + settings.h = settings.h || $loaded.height(); + settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h; + return settings.h; + } + + $loaded.hide() + .appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations. + .css({width: getWidth(), overflow: settings.scrolling ? 'auto' : 'hidden'}) + .css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height. + .prependTo($content); + + $loadingBay.hide(); + + // floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width. + + $(photo).css({'float': 'none'}); + + callback = function () { + var total = $related.length, + iframe, + frameBorder = 'frameBorder', + allowTransparency = 'allowTransparency', + complete; + + if (!open) { + return; + } + + function removeFilter() { // Needed for IE7 & IE8 in versions of jQuery prior to 1.7.2 + if ($.support.opacity === false) { + $box[0].style.removeAttribute('filter'); + } + } + + complete = function () { + clearTimeout(loadingTimer); + $loadingOverlay.hide(); + trigger(event_complete, settings.onComplete); + }; + + + $title.html(settings.title).add($loaded).show(); + + if (total > 1) { // handle grouping + if (typeof settings.current === "string") { + $current.html(settings.current.replace('{current}', index + 1).replace('{total}', total)).show(); + } + + $next[(settings.loop || index < total - 1) ? "show" : "hide"]().html(settings.next); + $prev[(settings.loop || index) ? "show" : "hide"]().html(settings.previous); + + slideshow(); + + // Preloads images within a rel group + if (settings.preloading) { + $.each([getIndex(-1), getIndex(1)], function(){ + var src, + img, + i = $related[this], + data = $.data(i, colorbox); + + if (data && data.href) { + src = data.href; + if ($.isFunction(src)) { + src = src.call(i); + } + } else { + src = $(i).attr('href'); + } + + if (src && isImage(data, src)) { + src = retinaUrl(data, src); + img = document.createElement('img'); + img.src = src; + } + }); + } + } else { + $groupControls.hide(); + } + + if (settings.iframe) { + iframe = $tag('iframe')[0]; + + if (frameBorder in iframe) { + iframe[frameBorder] = 0; + } + + if (allowTransparency in iframe) { + iframe[allowTransparency] = "true"; + } + + if (!settings.scrolling) { + iframe.scrolling = "no"; + } + + $(iframe) + .attr({ + src: settings.href, + name: (new Date()).getTime(), // give the iframe a unique name to prevent caching + 'class': prefix + 'Iframe', + allowFullScreen : true, // allow HTML5 video to go fullscreen + webkitAllowFullScreen : true, + mozallowfullscreen : true + }) + .one('load', complete) + .appendTo($loaded); + + $events.one(event_purge, function () { + iframe.src = "//about:blank"; + }); + + if (settings.fastIframe) { + $(iframe).trigger('load'); + } + } else { + complete(); + } + + if (settings.transition === 'fade') { + $box.fadeTo(speed, 1, removeFilter); + } else { + removeFilter(); + } + }; + + if (settings.transition === 'fade') { + $box.fadeTo(speed, 0, function () { + publicMethod.position(0, callback); + }); + } else { + publicMethod.position(speed, callback); + } + }; + + function load () { + var href, setResize, prep = publicMethod.prep, $inline, request = ++requests; + + active = true; + + photo = false; + + element = $related[index]; + + makeSettings(); + + trigger(event_purge); + + trigger(event_load, settings.onLoad); + + settings.h = settings.height ? + setSize(settings.height, 'y') - loadedHeight - interfaceHeight : + settings.innerHeight && setSize(settings.innerHeight, 'y'); + + settings.w = settings.width ? + setSize(settings.width, 'x') - loadedWidth - interfaceWidth : + settings.innerWidth && setSize(settings.innerWidth, 'x'); + + // Sets the minimum dimensions for use in image scaling + settings.mw = settings.w; + settings.mh = settings.h; + + // Re-evaluate the minimum width and height based on maxWidth and maxHeight values. + // If the width or height exceed the maxWidth or maxHeight, use the maximum values instead. + if (settings.maxWidth) { + settings.mw = setSize(settings.maxWidth, 'x') - loadedWidth - interfaceWidth; + settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw; + } + if (settings.maxHeight) { + settings.mh = setSize(settings.maxHeight, 'y') - loadedHeight - interfaceHeight; + settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh; + } + + href = settings.href; + + loadingTimer = setTimeout(function () { + $loadingOverlay.show(); + }, 100); + + if (settings.inline) { + // Inserts an empty placeholder where inline content is being pulled from. + // An event is bound to put inline content back when Colorbox closes or loads new content. + $inline = $tag(div).hide().insertBefore($(href)[0]); + + $events.one(event_purge, function () { + $inline.replaceWith($loaded.children()); + }); + + prep($(href)); + } else if (settings.iframe) { + // IFrame element won't be added to the DOM until it is ready to be displayed, + // to avoid problems with DOM-ready JS that might be trying to run in that iframe. + prep(" "); + } else if (settings.html) { + prep(settings.html); + } else if (isImage(settings, href)) { + + href = retinaUrl(settings, href); + + photo = document.createElement('img'); + + $(photo) + .addClass(prefix + 'Photo') + .bind('error',function () { + settings.title = false; + prep($tag(div, 'Error').html(settings.imgError)); + }) + .one('load', function () { + var percent; + + if (request !== requests) { + return; + } + + $.each(['alt', 'longdesc', 'aria-describedby'], function(i,val){ + var attr = $(element).attr(val) || $(element).attr('data-'+val); + if (attr) { + photo.setAttribute(val, attr); + } + }); + + if (settings.retinaImage && window.devicePixelRatio > 1) { + photo.height = photo.height / window.devicePixelRatio; + photo.width = photo.width / window.devicePixelRatio; + } + + if (settings.scalePhotos) { + setResize = function () { + photo.height -= photo.height * percent; + photo.width -= photo.width * percent; + }; + if (settings.mw && photo.width > settings.mw) { + percent = (photo.width - settings.mw) / photo.width; + setResize(); + } + if (settings.mh && photo.height > settings.mh) { + percent = (photo.height - settings.mh) / photo.height; + setResize(); + } + } + + if (settings.h) { + photo.style.marginTop = Math.max(settings.mh - photo.height, 0) / 2 + 'px'; + } + + if ($related[1] && (settings.loop || $related[index + 1])) { + photo.style.cursor = 'pointer'; + photo.onclick = function () { + publicMethod.next(); + }; + } + + photo.style.width = photo.width + 'px'; + photo.style.height = photo.height + 'px'; + + setTimeout(function () { // A pause because Chrome will sometimes report a 0 by 0 size otherwise. + prep(photo); + }, 1); + }); + + setTimeout(function () { // A pause because Opera 10.6+ will sometimes not run the onload function otherwise. + photo.src = href; + }, 1); + } else if (href) { + $loadingBay.load(href, settings.data, function (data, status) { + if (request === requests) { + prep(status === 'error' ? $tag(div, 'Error').html(settings.xhrError) : $(this).contents()); + } + }); + } + } + + // Navigates to the next page/image in a set. + publicMethod.next = function () { + if (!active && $related[1] && (settings.loop || $related[index + 1])) { + index = getIndex(1); + launch($related[index]); + } + }; + + publicMethod.prev = function () { + if (!active && $related[1] && (settings.loop || index)) { + index = getIndex(-1); + launch($related[index]); + } + }; + + // Note: to use this within an iframe use the following format: parent.jQuery.colorbox.close(); + publicMethod.close = function () { + if (open && !closing) { + + closing = true; + + open = false; + + trigger(event_cleanup, settings.onCleanup); + + $window.unbind('.' + prefix); + + $overlay.fadeTo(settings.fadeOut || 0, 0); + + $box.stop().fadeTo(settings.fadeOut || 0, 0, function () { + + $box.add($overlay).css({'opacity': 1, cursor: 'auto'}).hide(); + + trigger(event_purge); + + $loaded.empty().remove(); // Using empty first may prevent some IE7 issues. + + setTimeout(function () { + closing = false; + trigger(event_closed, settings.onClosed); + }, 1); + }); + } + }; + + // Removes changes Colorbox made to the document, but does not remove the plugin. + publicMethod.remove = function () { + if (!$box) { return; } + + $box.stop(); + $.colorbox.close(); + $box.stop().remove(); + $overlay.remove(); + closing = false; + $box = null; + $('.' + boxElement) + .removeData(colorbox) + .removeClass(boxElement); + + $(document).unbind('click.'+prefix); + }; + + // A method for fetching the current element Colorbox is referencing. + // returns a jQuery object. + publicMethod.element = function () { + return $(element); + }; + + publicMethod.settings = defaults; + +}(jQuery, document, window)); diff --git a/src/static/jquery/datatables/media/css/demo_page.css b/src/static/jquery/datatables/media/css/demo_page.css new file mode 100644 index 0000000..ba5b2a6 --- /dev/null +++ b/src/static/jquery/datatables/media/css/demo_page.css @@ -0,0 +1,122 @@ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * General page setup + */ +#dt_example { + font: 80%/1.45em "Lucida Grande", Verdana, Arial, Helvetica, sans-serif; + margin: 0; + padding: 0; + color: #333; + background-color: #fff; +} + + +#dt_example #container { + width: 800px; + margin: 30px auto; + padding: 0; +} + + +#dt_example #footer { + margin: 50px auto 0 auto; + padding: 0; +} + +#dt_example #demo { + margin: 30px auto 0 auto; +} + +#dt_example .demo_jui { + margin: 30px auto 0 auto; +} + +#dt_example .big { + font-size: 1.3em; + font-weight: bold; + line-height: 1.6em; + color: #4E6CA3; +} + +#dt_example .spacer { + height: 20px; + clear: both; +} + +#dt_example .clear { + clear: both; +} + +#dt_example pre { + padding: 15px; + background-color: #F5F5F5; + border: 1px solid #CCCCCC; +} + +#dt_example h1 { + margin-top: 2em; + font-size: 1.3em; + font-weight: normal; + line-height: 1.6em; + color: #4E6CA3; + border-bottom: 1px solid #B0BED9; + clear: both; +} + +#dt_example h2 { + font-size: 1.2em; + font-weight: normal; + line-height: 1.6em; + color: #4E6CA3; + clear: both; +} + +#dt_example a { + color: #0063DC; + text-decoration: none; +} + +#dt_example a:hover { + text-decoration: underline; +} + +#dt_example ul { + color: #4E6CA3; +} + +.css_right { + float: right; +} + +.css_left { + float: left; +} + +.demo_links { + float: left; + width: 50%; + margin-bottom: 1em; +} + +#demo_info { + padding: 5px; + border: 1px solid #B0BED9; + height: 100px; + width: 100%; + overflow: auto; +} + +#dt_example code { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + padding: 2px 4px !important; + white-space: nowrap; + font-size: 0.9em; + + color: #D14; + background-color: #F7F7F9; + + border: 1px solid #E1E1E8; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} diff --git a/src/static/jquery/datatables/media/css/demo_table.css b/src/static/jquery/datatables/media/css/demo_table.css new file mode 100644 index 0000000..12f352d --- /dev/null +++ b/src/static/jquery/datatables/media/css/demo_table.css @@ -0,0 +1,577 @@ +/* + * File: demo_table.css + * CVS: $Id$ + * Description: CSS descriptions for DataTables demo pages + * Author: Allan Jardine + * Created: Tue May 12 06:47:22 BST 2009 + * Modified: $Date$ by $Author$ + * Language: CSS + * Project: DataTables + * + * Copyright 2009 Allan Jardine. All Rights Reserved. + * + * *************************************************************************** + * DESCRIPTION + * + * The styles given here are suitable for the demos that are used with the standard DataTables + * distribution (see www.datatables.net). You will most likely wish to modify these styles to + * meet the layout requirements of your site. + * + * Common issues: + * 'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is + * no conflict between the two pagination types. If you want to use full_numbers pagination + * ensure that you either have "example_alt_pagination" as a body class name, or better yet, + * modify that selector. + * Note that the path used for Images is relative. All images are by default located in + * ../images/ - relative to this CSS file. + */ + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables features + */ + +.dataTables_wrapper { + position: relative; + clear: both; + zoom: 1; /* Feeling sorry for IE */ +} + +.dataTables_processing { + position: absolute; + top: 50%; + left: 50%; + width: 250px; + height: 30px; + margin-left: -125px; + margin-top: -15px; + padding: 14px 0 2px 0; + border: 1px solid #ddd; + text-align: center; + color: #999; + font-size: 14px; + background-color: white; +} + +.dataTables_length { + width: 40%; + float: left; +} + +.dataTables_filter { + width: 50%; + float: right; + text-align: right; +} + +.dataTables_info { + width: 60%; + float: left; +} + +.dataTables_paginate { + float: right; + text-align: right; +} + +/* Pagination nested */ +.paginate_disabled_previous, .paginate_enabled_previous, +.paginate_disabled_next, .paginate_enabled_next { + height: 19px; + float: left; + cursor: pointer; + *cursor: hand; + color: #111 !important; +} +.paginate_disabled_previous:hover, .paginate_enabled_previous:hover, +.paginate_disabled_next:hover, .paginate_enabled_next:hover { + text-decoration: none !important; +} +.paginate_disabled_previous:active, .paginate_enabled_previous:active, +.paginate_disabled_next:active, .paginate_enabled_next:active { + outline: none; +} + +.paginate_disabled_previous, +.paginate_disabled_next { + color: #666 !important; +} +.paginate_disabled_previous, .paginate_enabled_previous { + padding-left: 23px; +} +.paginate_disabled_next, .paginate_enabled_next { + padding-right: 23px; + margin-left: 10px; +} + +.paginate_disabled_previous { + background: url('../images/back_disabled.png') no-repeat top left; +} + +.paginate_enabled_previous { + background: url('../images/back_enabled.png') no-repeat top left; +} +.paginate_enabled_previous:hover { + background: url('../images/back_enabled_hover.png') no-repeat top left; +} + +.paginate_disabled_next { + background: url('../images/forward_disabled.png') no-repeat top right; +} + +.paginate_enabled_next { + background: url('../images/forward_enabled.png') no-repeat top right; +} +.paginate_enabled_next:hover { + background: url('../images/forward_enabled_hover.png') no-repeat top right; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables display + */ +table.display { + margin: 0 auto; + clear: both; + width: 100%; + + /* Note Firefox 3.5 and before have a bug with border-collapse + * ( https://bugzilla.mozilla.org/show%5Fbug.cgi?id=155955 ) + * border-spacing: 0; is one possible option. Conditional-css.com is + * useful for this kind of thing + * + * Further note IE 6/7 has problems when calculating widths with border width. + * It subtracts one px relative to the other browsers from the first column, and + * adds one to the end... + * + * If you want that effect I'd suggest setting a border-top/left on th/td's and + * then filling in the gaps with other borders. + */ +} + +table.display thead th { + padding: 3px 18px 3px 10px; + border-bottom: 1px solid black; + font-weight: bold; + cursor: pointer; + * cursor: hand; +} + +table.display tfoot th { + padding: 3px 18px 3px 10px; + border-top: 1px solid black; + font-weight: bold; +} + +table.display tr.heading2 td { + border-bottom: 1px solid #aaa; +} + +table.display td { + padding: 3px 10px; +} + +table.display td.center { + text-align: center; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables sorting + */ + +.sorting_asc { + background: url('../images/sort_asc.png') no-repeat center right; +} + +.sorting_desc { + background: url('../images/sort_desc.png') no-repeat center right; +} + +.sorting { + background: url('../images/sort_both.png') no-repeat center right; +} + +.sorting_asc_disabled { + background: url('../images/sort_asc_disabled.png') no-repeat center right; +} + +.sorting_desc_disabled { + background: url('../images/sort_desc_disabled.png') no-repeat center right; +} + +table.display thead th:active, +table.display thead td:active { + outline: none; +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables row classes + */ +table.display tr.odd.gradeA { + background-color: #ddffdd; +} + +table.display tr.even.gradeA { + background-color: #eeffee; +} + +table.display tr.odd.gradeC { + background-color: #ddddff; +} + +table.display tr.even.gradeC { + background-color: #eeeeff; +} + +table.display tr.odd.gradeX { + background-color: #ffdddd; +} + +table.display tr.even.gradeX { + background-color: #ffeeee; +} + +table.display tr.odd.gradeU { + background-color: #ddd; +} + +table.display tr.even.gradeU { + background-color: #eee; +} + + +tr.odd { + background-color: #E2E4FF; +} + +tr.even { + background-color: white; +} + + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Misc + */ +.dataTables_scroll { + clear: both; +} + +.dataTables_scrollBody { + *margin-top: -1px; + -webkit-overflow-scrolling: touch; +} + +.top, .bottom { + padding: 15px; + background-color: #F5F5F5; + border: 1px solid #CCCCCC; +} + +.top .dataTables_info { + float: none; +} + +.clear { + clear: both; +} + +.dataTables_empty { + text-align: center; +} + +tfoot input { + margin: 0.5em 0; + width: 100%; + color: #444; +} + +tfoot input.search_init { + color: #999; +} + +td.group { + background-color: #d1cfd0; + border-bottom: 2px solid #A19B9E; + border-top: 2px solid #A19B9E; +} + +td.details { + background-color: #d1cfd0; + border: 2px solid #A19B9E; +} + + +.example_alt_pagination div.dataTables_info { + width: 40%; +} + +.paging_full_numbers { + width: 400px; + height: 22px; + line-height: 22px; +} + +.paging_full_numbers a:active { + outline: none +} + +.paging_full_numbers a:hover { + text-decoration: none; +} + +.paging_full_numbers a.paginate_button, + .paging_full_numbers a.paginate_active { + border: 1px solid #aaa; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + padding: 2px 5px; + margin: 0 3px; + cursor: pointer; + *cursor: hand; + color: #333 !important; +} + +.paging_full_numbers a.paginate_button { + background-color: #ddd; +} + +.paging_full_numbers a.paginate_button:hover { + background-color: #ccc; + text-decoration: none !important; +} + +.paging_full_numbers a.paginate_active { + background-color: #99B3FF; +} + +table.display tr.even.row_selected td { + background-color: #B0BED9; +} + +table.display tr.odd.row_selected td { + background-color: #9FAFD1; +} + + +/* + * Sorting classes for columns + */ +/* For the standard odd/even */ +tr.odd td.sorting_1 { + background-color: #D3D6FF; +} + +tr.odd td.sorting_2 { + background-color: #DADCFF; +} + +tr.odd td.sorting_3 { + background-color: #E0E2FF; +} + +tr.even td.sorting_1 { + background-color: #EAEBFF; +} + +tr.even td.sorting_2 { + background-color: #F2F3FF; +} + +tr.even td.sorting_3 { + background-color: #F9F9FF; +} + + +/* For the Conditional-CSS grading rows */ +/* + Colour calculations (based off the main row colours) + Level 1: + dd > c4 + ee > d5 + Level 2: + dd > d1 + ee > e2 + */ +tr.odd.gradeA td.sorting_1 { + background-color: #c4ffc4; +} + +tr.odd.gradeA td.sorting_2 { + background-color: #d1ffd1; +} + +tr.odd.gradeA td.sorting_3 { + background-color: #d1ffd1; +} + +tr.even.gradeA td.sorting_1 { + background-color: #d5ffd5; +} + +tr.even.gradeA td.sorting_2 { + background-color: #e2ffe2; +} + +tr.even.gradeA td.sorting_3 { + background-color: #e2ffe2; +} + +tr.odd.gradeC td.sorting_1 { + background-color: #c4c4ff; +} + +tr.odd.gradeC td.sorting_2 { + background-color: #d1d1ff; +} + +tr.odd.gradeC td.sorting_3 { + background-color: #d1d1ff; +} + +tr.even.gradeC td.sorting_1 { + background-color: #d5d5ff; +} + +tr.even.gradeC td.sorting_2 { + background-color: #e2e2ff; +} + +tr.even.gradeC td.sorting_3 { + background-color: #e2e2ff; +} + +tr.odd.gradeX td.sorting_1 { + background-color: #ffc4c4; +} + +tr.odd.gradeX td.sorting_2 { + background-color: #ffd1d1; +} + +tr.odd.gradeX td.sorting_3 { + background-color: #ffd1d1; +} + +tr.even.gradeX td.sorting_1 { + background-color: #ffd5d5; +} + +tr.even.gradeX td.sorting_2 { + background-color: #ffe2e2; +} + +tr.even.gradeX td.sorting_3 { + background-color: #ffe2e2; +} + +tr.odd.gradeU td.sorting_1 { + background-color: #c4c4c4; +} + +tr.odd.gradeU td.sorting_2 { + background-color: #d1d1d1; +} + +tr.odd.gradeU td.sorting_3 { + background-color: #d1d1d1; +} + +tr.even.gradeU td.sorting_1 { + background-color: #d5d5d5; +} + +tr.even.gradeU td.sorting_2 { + background-color: #e2e2e2; +} + +tr.even.gradeU td.sorting_3 { + background-color: #e2e2e2; +} + + +/* + * Row highlighting example + */ +.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted { + background-color: #ECFFB3; +} + +.ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted { + background-color: #E6FF99; +} + +.ex_highlight_row #example tr.even:hover { + background-color: #ECFFB3; +} + +.ex_highlight_row #example tr.even:hover td.sorting_1 { + background-color: #DDFF75; +} + +.ex_highlight_row #example tr.even:hover td.sorting_2 { + background-color: #E7FF9E; +} + +.ex_highlight_row #example tr.even:hover td.sorting_3 { + background-color: #E2FF89; +} + +.ex_highlight_row #example tr.odd:hover { + background-color: #E6FF99; +} + +.ex_highlight_row #example tr.odd:hover td.sorting_1 { + background-color: #D6FF5C; +} + +.ex_highlight_row #example tr.odd:hover td.sorting_2 { + background-color: #E0FF84; +} + +.ex_highlight_row #example tr.odd:hover td.sorting_3 { + background-color: #DBFF70; +} + + +/* + * KeyTable + */ +table.KeyTable td { + border: 3px solid transparent; +} + +table.KeyTable td.focus { + border: 3px solid #3366FF; +} + +table.display tr.gradeA { + background-color: #eeffee; +} + +table.display tr.gradeC { + background-color: #ddddff; +} + +table.display tr.gradeX { + background-color: #ffdddd; +} + +table.display tr.gradeU { + background-color: #ddd; +} + +div.box { + height: 100px; + padding: 10px; + overflow: auto; + border: 1px solid #8080FF; + background-color: #E5E5FF; +} diff --git a/src/static/jquery/datatables/media/css/demo_table_jui.css b/src/static/jquery/datatables/media/css/demo_table_jui.css new file mode 100644 index 0000000..a210af5 --- /dev/null +++ b/src/static/jquery/datatables/media/css/demo_table_jui.css @@ -0,0 +1,501 @@ +/* + * File: demo_table_jui.css + * CVS: $Id$ + * Description: CSS descriptions for DataTables demo pages + * Author: Allan Jardine + * Created: Tue May 12 06:47:22 BST 2009 + * Modified: $Date$ by $Author$ + * Language: CSS + * Project: DataTables + * + * Copyright 2009 Allan Jardine. All Rights Reserved. + * + * *************************************************************************** + * DESCRIPTION + * + * The styles given here are suitable for the demos that are used with the standard DataTables + * distribution (see www.datatables.net). You will most likely wish to modify these styles to + * meet the layout requirements of your site. + * + * Common issues: + * 'full_numbers' pagination - I use an extra selector on the body tag to ensure that there is + * no conflict between the two pagination types. If you want to use full_numbers pagination + * ensure that you either have "example_alt_pagination" as a body class name, or better yet, + * modify that selector. + * Note that the path used for Images is relative. All images are by default located in + * ../images/ - relative to this CSS file. + */ + + +/* + * jQuery UI specific styling + */ + +.paging_two_button .ui-button { + float: left; + cursor: pointer; + * cursor: hand; +} + +.paging_full_numbers .ui-button { + padding: 2px 6px; + margin: 0; + cursor: pointer; + * cursor: hand; + color: #333 !important; +} + +.dataTables_paginate .ui-button { + margin-right: -0.1em !important; +} + +.paging_full_numbers { + width: 350px !important; +} + +.dataTables_wrapper .ui-toolbar { + padding: 5px; +} + +.dataTables_paginate { + width: auto; +} + +.dataTables_info { + padding-top: 3px; +} + +table.display thead th { + padding: 3px 0px 3px 10px; + cursor: pointer; + * cursor: hand; +} + +div.dataTables_wrapper .ui-widget-header { + font-weight: normal; +} + + +/* + * Sort arrow icon positioning + */ +table.display thead th div.DataTables_sort_wrapper { + position: relative; + padding-right: 20px; +} + +table.display thead th div.DataTables_sort_wrapper span { + position: absolute; + top: 50%; + margin-top: -8px; + right: 0; +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Everything below this line is the same as demo_table.css. This file is + * required for 'cleanliness' of the markup + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables features + */ + +.dataTables_wrapper { + position: relative; + clear: both; +} + +.dataTables_processing { + position: absolute; + top: 0px; + left: 50%; + width: 250px; + margin-left: -125px; + border: 1px solid #ddd; + text-align: center; + color: #999; + font-size: 11px; + padding: 2px 0; +} + +.dataTables_length { + width: 40%; + float: left; +} + +.dataTables_filter { + width: 50%; + float: right; + text-align: right; +} + +.dataTables_info { + width: 50%; + float: left; +} + +.dataTables_paginate { + float: right; + text-align: right; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables display + */ +table.display { + margin: 0 auto; + width: 100%; + clear: both; + border-collapse: collapse; +} + +table.display tfoot th { + padding: 3px 0px 3px 10px; + font-weight: bold; + font-weight: normal; +} + +table.display tr.heading2 td { + border-bottom: 1px solid #aaa; +} + +table.display td { + padding: 3px 10px; +} + +table.display td.center { + text-align: center; +} + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables sorting + */ + +.sorting_asc { + background: url('../images/sort_asc.png') no-repeat center right; +} + +.sorting_desc { + background: url('../images/sort_desc.png') no-repeat center right; +} + +.sorting { + background: url('../images/sort_both.png') no-repeat center right; +} + +.sorting_asc_disabled { + background: url('../images/sort_asc_disabled.png') no-repeat center right; +} + +.sorting_desc_disabled { + background: url('../images/sort_desc_disabled.png') no-repeat center right; +} + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DataTables row classes + */ +table.display tr.odd.gradeA { + background-color: #ddffdd; +} + +table.display tr.even.gradeA { + background-color: #eeffee; +} + + + + +table.display tr.odd.gradeA { + background-color: #ddffdd; +} + +table.display tr.even.gradeA { + background-color: #eeffee; +} + +table.display tr.odd.gradeC { + background-color: #ddddff; +} + +table.display tr.even.gradeC { + background-color: #eeeeff; +} + +table.display tr.odd.gradeX { + background-color: #ffdddd; +} + +table.display tr.even.gradeX { + background-color: #ffeeee; +} + +table.display tr.odd.gradeU { + background-color: #ddd; +} + +table.display tr.even.gradeU { + background-color: #eee; +} + + +tr.odd { + background-color: #E2E4FF; +} + +tr.even { + background-color: white; +} + + + + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Misc + */ +.dataTables_scroll { + clear: both; +} + +.dataTables_scrollBody { + -webkit-overflow-scrolling: touch; +} + +.top, .bottom { + padding: 15px; + background-color: #F5F5F5; + border: 1px solid #CCCCCC; +} + +.top .dataTables_info { + float: none; +} + +.clear { + clear: both; +} + +.dataTables_empty { + text-align: center; +} + +tfoot input { + margin: 0.5em 0; + width: 100%; + color: #444; +} + +tfoot input.search_init { + color: #999; +} + +td.group { + background-color: #d1cfd0; + border-bottom: 2px solid #A19B9E; + border-top: 2px solid #A19B9E; +} + +td.details { + background-color: #d1cfd0; + border: 2px solid #A19B9E; +} + + +.example_alt_pagination div.dataTables_info { + width: 40%; +} + +.paging_full_numbers a.paginate_button, + .paging_full_numbers a.paginate_active { + border: 1px solid #aaa; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + padding: 2px 5px; + margin: 0 3px; + cursor: pointer; + *cursor: hand; + color: #333 !important; +} + +.paging_full_numbers a.paginate_button { + background-color: #ddd; +} + +.paging_full_numbers a.paginate_button:hover { + background-color: #ccc; + text-decoration: none !important; +} + +.paging_full_numbers a.paginate_active { + background-color: #99B3FF; +} + +table.display tr.even.row_selected td { + background-color: #B0BED9; +} + +table.display tr.odd.row_selected td { + background-color: #9FAFD1; +} + + +/* + * Sorting classes for columns + */ +/* For the standard odd/even */ +tr.odd td.sorting_1 { + background-color: #D3D6FF; +} + +tr.odd td.sorting_2 { + background-color: #DADCFF; +} + +tr.odd td.sorting_3 { + background-color: #E0E2FF; +} + +tr.even td.sorting_1 { + background-color: #EAEBFF; +} + +tr.even td.sorting_2 { + background-color: #F2F3FF; +} + +tr.even td.sorting_3 { + background-color: #F9F9FF; +} + + +/* For the Conditional-CSS grading rows */ +/* + Colour calculations (based off the main row colours) + Level 1: + dd > c4 + ee > d5 + Level 2: + dd > d1 + ee > e2 + */ +tr.odd.gradeA td.sorting_1 { + background-color: #c4ffc4; +} + +tr.odd.gradeA td.sorting_2 { + background-color: #d1ffd1; +} + +tr.odd.gradeA td.sorting_3 { + background-color: #d1ffd1; +} + +tr.even.gradeA td.sorting_1 { + background-color: #d5ffd5; +} + +tr.even.gradeA td.sorting_2 { + background-color: #e2ffe2; +} + +tr.even.gradeA td.sorting_3 { + background-color: #e2ffe2; +} + +tr.odd.gradeC td.sorting_1 { + background-color: #c4c4ff; +} + +tr.odd.gradeC td.sorting_2 { + background-color: #d1d1ff; +} + +tr.odd.gradeC td.sorting_3 { + background-color: #d1d1ff; +} + +tr.even.gradeC td.sorting_1 { + background-color: #d5d5ff; +} + +tr.even.gradeC td.sorting_2 { + background-color: #e2e2ff; +} + +tr.even.gradeC td.sorting_3 { + background-color: #e2e2ff; +} + +tr.odd.gradeX td.sorting_1 { + background-color: #ffc4c4; +} + +tr.odd.gradeX td.sorting_2 { + background-color: #ffd1d1; +} + +tr.odd.gradeX td.sorting_3 { + background-color: #ffd1d1; +} + +tr.even.gradeX td.sorting_1 { + background-color: #ffd5d5; +} + +tr.even.gradeX td.sorting_2 { + background-color: #ffe2e2; +} + +tr.even.gradeX td.sorting_3 { + background-color: #ffe2e2; +} + +tr.odd.gradeU td.sorting_1 { + background-color: #c4c4c4; +} + +tr.odd.gradeU td.sorting_2 { + background-color: #d1d1d1; +} + +tr.odd.gradeU td.sorting_3 { + background-color: #d1d1d1; +} + +tr.even.gradeU td.sorting_1 { + background-color: #d5d5d5; +} + +tr.even.gradeU td.sorting_2 { + background-color: #e2e2e2; +} + +tr.even.gradeU td.sorting_3 { + background-color: #e2e2e2; +} + + +/* + * Row highlighting example + */ +.ex_highlight #example tbody tr.even:hover, #example tbody tr.even td.highlighted { + background-color: #ECFFB3; +} + +.ex_highlight #example tbody tr.odd:hover, #example tbody tr.odd td.highlighted { + background-color: #E6FF99; +} \ No newline at end of file diff --git a/src/static/jquery/datatables/media/css/jquery.dataTables.css b/src/static/jquery/datatables/media/css/jquery.dataTables.css new file mode 100644 index 0000000..7da7fae --- /dev/null +++ b/src/static/jquery/datatables/media/css/jquery.dataTables.css @@ -0,0 +1,221 @@ + +/* + * Table + */ +table.dataTable { + margin: 0 auto; + clear: both; + width: 100%; +} + +table.dataTable thead th { + padding: 3px 18px 3px 10px; + border-bottom: 1px solid black; + font-weight: bold; + cursor: pointer; + *cursor: hand; +} + +table.dataTable tfoot th { + padding: 3px 18px 3px 10px; + border-top: 1px solid black; + font-weight: bold; +} + +table.dataTable td { + padding: 3px 10px; +} + +table.dataTable td.center, +table.dataTable td.dataTables_empty { + text-align: center; +} + +table.dataTable tr.odd { background-color: #E2E4FF; } +table.dataTable tr.even { background-color: white; } + +table.dataTable tr.odd td.sorting_1 { background-color: #D3D6FF; } +table.dataTable tr.odd td.sorting_2 { background-color: #DADCFF; } +table.dataTable tr.odd td.sorting_3 { background-color: #E0E2FF; } +table.dataTable tr.even td.sorting_1 { background-color: #EAEBFF; } +table.dataTable tr.even td.sorting_2 { background-color: #F2F3FF; } +table.dataTable tr.even td.sorting_3 { background-color: #F9F9FF; } + + +/* + * Table wrapper + */ +.dataTables_wrapper { + position: relative; + clear: both; + *zoom: 1; +} + + +/* + * Page length menu + */ +.dataTables_length { + float: left; +} + + +/* + * Filter + */ +.dataTables_filter { + float: right; + text-align: right; +} + + +/* + * Table information + */ +.dataTables_info { + clear: both; + float: left; +} + + +/* + * Pagination + */ +.dataTables_paginate { + float: right; + text-align: right; +} + +/* Two button pagination - previous / next */ +.paginate_disabled_previous, +.paginate_enabled_previous, +.paginate_disabled_next, +.paginate_enabled_next { + height: 19px; + float: left; + cursor: pointer; + *cursor: hand; + color: #111 !important; +} +.paginate_disabled_previous:hover, +.paginate_enabled_previous:hover, +.paginate_disabled_next:hover, +.paginate_enabled_next:hover { + text-decoration: none !important; +} +.paginate_disabled_previous:active, +.paginate_enabled_previous:active, +.paginate_disabled_next:active, +.paginate_enabled_next:active { + outline: none; +} + +.paginate_disabled_previous, +.paginate_disabled_next { + color: #666 !important; +} +.paginate_disabled_previous, +.paginate_enabled_previous { + padding-left: 23px; +} +.paginate_disabled_next, +.paginate_enabled_next { + padding-right: 23px; + margin-left: 10px; +} + +.paginate_enabled_previous { background: url('../images/back_enabled.png') no-repeat top left; } +.paginate_enabled_previous:hover { background: url('../images/back_enabled_hover.png') no-repeat top left; } +.paginate_disabled_previous { background: url('../images/back_disabled.png') no-repeat top left; } + +.paginate_enabled_next { background: url('../images/forward_enabled.png') no-repeat top right; } +.paginate_enabled_next:hover { background: url('../images/forward_enabled_hover.png') no-repeat top right; } +.paginate_disabled_next { background: url('../images/forward_disabled.png') no-repeat top right; } + +/* Full number pagination */ +.paging_full_numbers { + height: 22px; + line-height: 22px; +} +.paging_full_numbers a:active { + outline: none +} +.paging_full_numbers a:hover { + text-decoration: none; +} + +.paging_full_numbers a.paginate_button, +.paging_full_numbers a.paginate_active { + border: 1px solid #aaa; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + padding: 2px 5px; + margin: 0 3px; + cursor: pointer; + *cursor: hand; + color: #333 !important; +} + +.paging_full_numbers a.paginate_button { + background-color: #ddd; +} + +.paging_full_numbers a.paginate_button:hover { + background-color: #ccc; + text-decoration: none !important; +} + +.paging_full_numbers a.paginate_active { + background-color: #99B3FF; +} + + +/* + * Processing indicator + */ +.dataTables_processing { + position: absolute; + top: 50%; + left: 50%; + width: 250px; + height: 30px; + margin-left: -125px; + margin-top: -15px; + padding: 14px 0 2px 0; + border: 1px solid #ddd; + text-align: center; + color: #999; + font-size: 14px; + background-color: white; +} + + +/* + * Sorting + */ +.sorting { background: url('../images/sort_both.png') no-repeat center right; } +.sorting_asc { background: url('../images/sort_asc.png') no-repeat center right; } +.sorting_desc { background: url('../images/sort_desc.png') no-repeat center right; } + +.sorting_asc_disabled { background: url('../images/sort_asc_disabled.png') no-repeat center right; } +.sorting_desc_disabled { background: url('../images/sort_desc_disabled.png') no-repeat center right; } + +table.dataTable thead th:active, +table.dataTable thead td:active { + outline: none; +} + + +/* + * Scrolling + */ +.dataTables_scroll { + clear: both; +} + +.dataTables_scrollBody { + *margin-top: -1px; + -webkit-overflow-scrolling: touch; +} + diff --git a/src/static/jquery/datatables/media/css/jquery.dataTables_themeroller.css b/src/static/jquery/datatables/media/css/jquery.dataTables_themeroller.css new file mode 100644 index 0000000..cf1d4ed --- /dev/null +++ b/src/static/jquery/datatables/media/css/jquery.dataTables_themeroller.css @@ -0,0 +1,244 @@ + + +/* + * Table + */ +table.dataTable { + margin: 0 auto; + clear: both; + width: 100%; + border-collapse: collapse; +} + +table.dataTable thead th { + padding: 3px 0px 3px 10px; + cursor: pointer; + *cursor: hand; +} + +table.dataTable tfoot th { + padding: 3px 10px; +} + +table.dataTable td { + padding: 3px 10px; +} + +table.dataTable td.center, +table.dataTable td.dataTables_empty { + text-align: center; +} + +table.dataTable tr.odd { background-color: #E2E4FF; } +table.dataTable tr.even { background-color: white; } + +table.dataTable tr.odd td.sorting_1 { background-color: #D3D6FF; } +table.dataTable tr.odd td.sorting_2 { background-color: #DADCFF; } +table.dataTable tr.odd td.sorting_3 { background-color: #E0E2FF; } +table.dataTable tr.even td.sorting_1 { background-color: #EAEBFF; } +table.dataTable tr.even td.sorting_2 { background-color: #F2F3FF; } +table.dataTable tr.even td.sorting_3 { background-color: #F9F9FF; } + + +/* + * Table wrapper + */ +.dataTables_wrapper { + position: relative; + clear: both; + *zoom: 1; +} +.dataTables_wrapper .ui-widget-header { + font-weight: normal; +} +.dataTables_wrapper .ui-toolbar { + padding: 5px; +} + + +/* + * Page length menu + */ +.dataTables_length { + float: left; +} + + +/* + * Filter + */ +.dataTables_filter { + float: right; + text-align: right; +} + + +/* + * Table information + */ +.dataTables_info { + padding-top: 3px; + clear: both; + float: left; +} + + +/* + * Pagination + */ +.dataTables_paginate { + float: right; + text-align: right; +} + +.dataTables_paginate .ui-button { + margin-right: -0.1em !important; +} + +.paging_two_button .ui-button { + float: left; + cursor: pointer; + * cursor: hand; +} + +.paging_full_numbers .ui-button { + padding: 2px 6px; + margin: 0; + cursor: pointer; + * cursor: hand; + color: #333 !important; +} + +/* Two button pagination - previous / next */ +.paginate_disabled_previous, +.paginate_enabled_previous, +.paginate_disabled_next, +.paginate_enabled_next { + height: 19px; + float: left; + cursor: pointer; + *cursor: hand; + color: #111 !important; +} +.paginate_disabled_previous:hover, +.paginate_enabled_previous:hover, +.paginate_disabled_next:hover, +.paginate_enabled_next:hover { + text-decoration: none !important; +} +.paginate_disabled_previous:active, +.paginate_enabled_previous:active, +.paginate_disabled_next:active, +.paginate_enabled_next:active { + outline: none; +} + +.paginate_disabled_previous, +.paginate_disabled_next { + color: #666 !important; +} +.paginate_disabled_previous, +.paginate_enabled_previous { + padding-left: 23px; +} +.paginate_disabled_next, +.paginate_enabled_next { + padding-right: 23px; + margin-left: 10px; +} + +.paginate_enabled_previous { background: url('../images/back_enabled.png') no-repeat top left; } +.paginate_enabled_previous:hover { background: url('../images/back_enabled_hover.png') no-repeat top left; } +.paginate_disabled_previous { background: url('../images/back_disabled.png') no-repeat top left; } + +.paginate_enabled_next { background: url('../images/forward_enabled.png') no-repeat top right; } +.paginate_enabled_next:hover { background: url('../images/forward_enabled_hover.png') no-repeat top right; } +.paginate_disabled_next { background: url('../images/forward_disabled.png') no-repeat top right; } + +/* Full number pagination */ +.paging_full_numbers a:active { + outline: none +} +.paging_full_numbers a:hover { + text-decoration: none; +} + +.paging_full_numbers a.paginate_button, +.paging_full_numbers a.paginate_active { + border: 1px solid #aaa; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + padding: 2px 5px; + margin: 0 3px; + cursor: pointer; + *cursor: hand; + color: #333 !important; +} + +.paging_full_numbers a.paginate_button { + background-color: #ddd; +} + +.paging_full_numbers a.paginate_button:hover { + background-color: #ccc; + text-decoration: none !important; +} + +.paging_full_numbers a.paginate_active { + background-color: #99B3FF; +} + + +/* + * Processing indicator + */ +.dataTables_processing { + position: absolute; + top: 50%; + left: 50%; + width: 250px; + height: 30px; + margin-left: -125px; + margin-top: -15px; + padding: 14px 0 2px 0; + border: 1px solid #ddd; + text-align: center; + color: #999; + font-size: 14px; + background-color: white; +} + + +/* + * Sorting + */ +table.dataTable thead th div.DataTables_sort_wrapper { + position: relative; + padding-right: 20px; +} + +table.dataTable thead th div.DataTables_sort_wrapper span { + position: absolute; + top: 50%; + margin-top: -8px; + right: 0; +} + +table.dataTable th:active { + outline: none; +} + + +/* + * Scrolling + */ +.dataTables_scroll { + clear: both; +} + +.dataTables_scrollBody { + *margin-top: -1px; + -webkit-overflow-scrolling: touch; +} + diff --git a/src/static/jquery/datatables/media/images/Sorting icons.psd b/src/static/jquery/datatables/media/images/Sorting icons.psd new file mode 100644 index 0000000000000000000000000000000000000000..53b2e06850767cb57c52b316f0b845b1a8e0ca0e GIT binary patch literal 27490 zcmeG^33yY*)^oGAX}T}$5K3uTx@2jaq_m}N($WHj(w42FkS4cnARAd|!3_{mfhUTH zY|1K#_&`w>abZ<N*=2D-Ux9~!BBID%$$w^Uk|t%5yeIE_|Mzn9&D=9*o0&6b=FXkT zTtz`y1)>mhao`qBLJ(pzsNq?Pf|62BSCWcgaLqBHCE&EOUv}>Xi$*(!wu`FiTD>VJ z{+AE7#EbO0ocN&`rQ%YHimuZaPq5Mz69!ajCydc5b@9D(1=$T*4MvNRwrfNUMuW+g z)sPdf(V461EPydOEnY-e>|=7`WvP->Ns2@wjn5T`M51h~t|qHoUF4F4R8D-I-EPTB zORKN1Ppy}wnys~I5~Wg^CYGj2r76IXVjFL=YZ_8awl0hkw;nZZ(^~ZwyWVUPVZEAa zv%{VfACEKgTuc#lT2DR}ht)uG(P`6Y18t;Dc3T=0GR>nLWV3bJtQxb`sIlj2EEa=a ztHHUXjWg*|NmWxVb!NNSR%f<kr!}*>GR{uJrSU2qsXEr$0{>^FZqQgf#WvYoIcv?v zG$25c#lA%bWR}WGYwTugrP*xA&BtvbDsvZ9q^gjLhU!f^bG<DaYw%%iwpq4^M5{G+ zI#()|h*QMShVn|WA}d{%B~w;;$umqX#7oUOea-mW#FbeYvMh0?OWcd8r8qc|PGi^n znF4RN2Vncs(tBIqXuPcfN=viUW~~D|Rf#&+;n3@{q*Ae}C_ht?o-UTDizJeKWxk?7 zU63i3<)^EaVl}a)ubi(rfL3C%*)=9D?bfN17i1L5KmlmEmrgIazuG=_eNA)U^>I#2 zx!pT4Hfx|&50)W)DOZx6b{o#C;)FJ=oVJ+_4&3*0<x;U&DNd7!;c|(3lUs@ozqhD2 zxus~c<Y1HDo-1|b)&kv9Y5-Jg9Ie*Z(l(IE$V`@I$RQ{oD3hg`(qyST9RlDK>B$)~ zF$4*~fLF+prOM1?nOKr6lPDl4lQX0cWKzI^9=R9-@XB#I1LzQB=`v}rf^>;GQ!SAw z)Y8n1LTRB?kzbUNAum)aRbsg$-)&)^lDUfgmyJ<$gZ?glfGM~80mf#P=^JRnFtr}~ zi4C`{M46p-M}n7;o9V;vCg??IDX20V%+?Bc+R@nYh%PTwOKu;F$ubq0>B;G0Wu}<K z&`NTNl!>JT!^AScXGj>H^kgh0Co!}rv=(3>228plLrh|5O@N^-A%@nM%fL5q4Ezu) zajXDNh;d#r@Dv>5Tx8%uI0jjWi7fa}x+EQ_IEK<f%wXgMR^V6(<%F2<C^G<-OEF#! zz6LRPWV%ENI&q9;l?p7YRA3&Z0`n-9ghweMFxI9d+LTJ1qmt-U;*!8KBQqJiHW@rU zIWt+FtVmWSgJ~p^WQjCcB1@K}CxaIQlSG~jE-wXM=m^jcpo?TcZvkhAegW>@OP-$z z*2q+<rQ(7@m0T*96%-Z~h?PYJDpiqOmEmekpBDS8ecbb~zw`6JL%!YHJ)|t+ZScsW zb7k3ScS3vlU^BTyr7E+UYxD*>*H+%AKvYtw%9JQGGgG9g;Kq04yQ7|By$z-X<I_Ad zkvmRNm_Y%iXE4c2^UU(xGM*{b0|A<g{Xo<+N&}hrW!!+d0_O6|0)8<EyenWXzbxPv zbHKX-=JLw|elZ8UD_}0aEZ`S&z`FwG^2-8#F$cUWU@pHb;1_eiy8`C&%L0Be2fQm_ zF25|`7jwY70_O6|0)8<EyenWXzbxPvbHKX-=JLw|elZ8UD_}0aEZ`S&z`FwG^2-8# zF$cUWU@pHb;1_eiy8`C&%L0Be2fQm_F25|`7jwY70_O6|0)8<EyenWXzbxPvbHKX- z=JLw|elg$Ey9CYWCTSBKmaK<UkqDowWdBUgSw^5@)&Mx6$#UPxnae~%3nMX!dQU`* z)CH0Z6;@g`CYwcLrA^xLgu;m>l#URGqDo{%8e~E?WP!UC(Ew}Fc$bb}2q$QFIthf3 zj$(9lAZdI~lu3tr(ha0sZ9M6Yqz;!zI+(-|xwHsK8cv;Jo+Rc}slamzl|>{k6P{v} zR#O8M1H?R+6oXkZZ@vd3C910+cJpKqOiD9`=)4AL1T}_w-RWYV#pF9toX&rThVv#S zL(qzBl49YU5Mu`d60DejTnb-|eQ^zNt?&umFv1f=FxX~*W92cy)f%{M5o&Iowm8YU z0uh#S$zYtxVKBfApYaW<*4XF)8Y5j<III%VTr?QGf(D<!7Y|Osnsl~-)uXkLa-9<{ z*V-kJBKcIBEh2;2REwGM)t|1hd#4NRW}_>OPZp!{+B!EKr+GFw4olmH82Z~FMfv2z zB{V=sLEw`_iP}pyzt(DYSbR`CvsDjgk7<*`2r|OL3alN@2?7q%p&EzX+=n*NRyc~P z0|crZZ=qex0)`o5Fr~y;D}vjDu0I>j54#NSGA?c!Ured3*4;P^4^LyTS88f~xWcqF z$k7e<5?gU)Y5!_Cvx}L7+-M)>;5xH)LcT#?>$X%lQ~6>y8YKBTx<=zL*Z~Y4M_cW8 zU?1W}`?7~r*OK!|UdD}N^cVE;5I_VCFq^QggY9O^K!@E%yB!151O{-V+pxlFvmG4j zHhc&)aa{{`(p$P=T}TLl>V1*GOuq^z=wcuh_t%@uEa)3Xlii9>MGYHXCF1Xco*E4O z4*XoBwOL9lig4dRaAHb?k4`a~NDNlKa+K*AU#1k7i9}ws`vD`h7AqK;Dg$Pj4i2FM zJOyAwz1@QGxYRM#V=&CZJub!y1q8S?hHDu(neZ@h9)@*B6Zkg^m)W8->M*<$;Ah7< zu-~)$13Yz{o~{S@Fu(~0hfxnO9v@?jv<CVj2iq*cPHXD`76UA_R+g&(&IYFv)_TF! zUa%b;5O|TwY#C3QMAS{&T?B{u6ry6f-ay;!DP{1D0F6~AQkjhwjR~GOOr5b5in{Gs z8bLGBJ&9g?_X2U-GW1J>NSje{dzx|0lFc~tQW#s|S;T&!8CN|Ip^Z-?)cTudT*6|6 z!lxj#VZT>>;;_GXeUU&<Yg4g7J=dQycsTD4c;%Oh^Ya|(6RDXVEW%!`g(IsDs|aQU zT3VFS(ux0NL9b$Yl_R;FuA%YFgBA?|FVmZ9p}9>uJ^8qT-sE%e&`ZO=DCVUBgN$DT z5WV~siW!-TBKF51_Ro6|CprYNN4y3U%F}NBgNGp8^M-ah!}vYGKqs+J#F`07mQ7Ed z3P@F6DbhNu;}{kWzH#Ac9*$yA8`KeXLETUak|H_kh4N4#>Wc=#jB7Z01m;+E$OzBY zdh{5Ygr=hD=mqpLnvWKt<!BXJgVv#q=tHy(eTu$72hb7pEowxk(NE|ix`J-Ptbk92 zQqfc!suR_f>Pbl{1(iz`QvIoNYB)8Ds-;YngL;g5ikeQ%qUKXes8!TE)ce#nYBzO| z`kFdHouhuEZm`%aAuEQ}ftAQgV<}kqtbVLY*2An?)>zgA))dzBthubEthZPjSld`% zu#T`ASwFEZvk^Ol9mnp>PGKw9D)vBj6}yIQWk125#-77o%3j0X%-+TRlHJHY&%Vy# zaiTdQP70?Nr<gOCqved{Ji(d4na_EHvw^dd^Cjm5=OX78H<a6++moBcE#VI1)^h8) zQ@L}vE4b^qpKy<GPjj#Ec)U1X5>L)6<_+hK<~_=r!F!drmbaC6kavoAna}69;rHa{ z@CWiWd^>+Ce;)rW{ucfr{%QWTppc+WLDHb2psFBK(Bz;wL2m|q9CRq?Owi5Xh~Tcl zS-}H?b;09<X9h11-W<F?_;m11L8Kr_kRzxRj2281%oVH=d?Gk5xD*l+5+9-r85E)q znHVxR<n55pLQaHS7e)zt2vx!nLWl5q;Y#6F;n%`Tp`oFPp?RTIq4v<{Lsy0F2>m|v zT3B>gYFJ5_F6_y$1z{V)4uxF^4-W4do*({5_=NB|;qQj;4?iCf9FZ8IiqJ$n5wRfR z{fJ``mm{MiC6NOojgd1V-;CTHc{Yk4l^9hRrHh&pwJd5!)TwB8beCvVv^M&w=;hI$ zM4yh~#U#a)#Eg!a9`pB@eK8kfqhixzhr~9-E{OdowlR(!ml#(PXNa2_w=V8z+>KTp zTIIK*TRqomO{+t#uC{L1I<Ga|dRptXt&g<6(MHs!u+5k@FSgm(=DW6>wmsSoYFpp- zwYHzMJ>M>-U9Wc9cGKFeYxhliR{I|9%iBNNep&lH?Jsxe*r87cONV(Kc62!3F|K1? z$I%^Ucl@~HxlYlYay#ie&F-|N(~qK9QNG9^nk(8Vy4bmW=i<(e&PzJ)>wGglDSmML z<oLDm-*pjmQFN*4GP}$6E*BFzC6p#SmasbEo36oK6<zDPzS4D9*Q<$1i9-{gN!*xt zHmP+|Nz#O*)k(*@g?8)RZEUxt-41u>bysvB)BV-%2YRr2Wb~-(v7pEPo~)jkJ@q|b z?RhYn3&+Jx$xD-ur3h2<Q^uvNPC1bpm)bvda_Yv^3uy^yRcSA#?Mk~P&JY{K%f;VH zq9lDKlO>xaze#&YwbBLB!?I9Wk?cv?CfTp)J=5v**V4brh|Va@cqU_e#vhsTOl#(v z%yaSt`6&59`7uR|qD(PE@tKmVEKokF{7`v4D>KWUwJz(IUMaoC^m?<`+3cijI(vEc zshs#6P0o^>##~YEsNBW5jlDbf*7RQ5`($31JYC+3yfgXT^GD~um4Bf?TwpC&UvO2G zrFvYoRn1oSQBPCvD~u`}TsXh*`=a=w+M?A(7yD%Nd9=^gVs3H2;unjLm2@c4maHnd z*jL{7@xD9z3Hw#_o8Rwb{~rCV{Wq7gO8b_+RC;_s*8!#h8wa9+B?Dg?_+432+1RoV z2Jr@!4O%ehhjK~zW97RlqANyLyjgLjvY>Ki<+p>o4R#FPJ|uj|h#{+nTpg+&I%{a- zu(V;15Bp+x+u{1*o2vL#L#kF(U4E$Wp_d;zJtAYo)DcG?PI|cE;oXn4eZ=s{M<c^W zYDT_0iaToPs5eJ7X$ESRYA#ooR4=T)s8wlS(f*{%)6LeMqjTt4^qHERnprhxYjbK} zsy$cNyKYY1dA&+MU;pdq;?avnUmY`W%*ruN!%)LoV~}x_@qJU2X^d&7xudzke9+R< zGS$*JHf!w5V=r3!Sy$L7+rzd^_86E<?QwK-Jnc9!E_d95ao6gH)W6#h*<fneGrq_8 z=f<CzP&DE7M>&sbAKm^~=f@^JcH;5;$Co@oJyHF{_9weMIpxXI6Z=ejW0GLfm`Qsl zizm;T{QFZwpV~a7!<30rPCeb{>D5!irdp>Sd#2Yji=O2?tABRibF$~=J$GxGZrbP5 z#nb0ZZ<?W<@%i5*f1CR^=kqns@0*!9^R*XvFPL69`eN@F-<TCSYr?EkFO|NuVYX=Y zwAsJEJo4q;bJFK5dPVSx<CVs_{pW6)moV>zc}?@{<{w#5uwd=N_6wg|c=c7?tA}38 zdu`344vVHQy0KWl_^Ty-mTXv>xOC1k-m-Daepo(a`L5R$udiCscE$7+f2=gEY<#2q zjh(CHt5&_){>_=IS*snZ&%HI`tpk5o|9#V%lr>A%#;u+HHhSCf_K)w3dgti6e(Scs zt9W<KdtKjKxITLQv<=jT@f$8~tlQYQY51mt@ArLw`{rJo*ME@u!O9Oif4JbI*pFs@ zEckfJ$IdMiwp`w7*?N9k?Y2|fM{fUi$FLoTcMjUQ?~{I?eD-P4r#p7#@7nTN&SxL) z&f5L{=Zeoaev$dbhCLa3*6+>OyMABhz76~3`!^j>9@u;^`{2iidLP>MrTWWH50@PN z;>ds_2agUu`qi-!#~Q!VeRcM0!`HulGwz$4-%dQvJwENbi0|fn-~Rih|LFdYwT+pL zADvL2*mJVt<hQ4^r+)gU?VnAjr~DB5!<;jn&a65sJ^SIgqH_m+eCWs1KUsddd4B58 zkv}iI(Cxx|zvTV0=i;!7r+>Bn>iliSr8bvV{+|B(_RD3LzrSL<a`Wo6Yi+K*ab0nJ z*Nve!&fKhT;y2Cxqx&D5Z}q!%+-Y<=$-71jnGN8{KsZU`88l)wK!oQL_-z*lm_Ku1 zj?5Z?S|iH&m9r5=^erkWLKF+3V)!BF&qzqVwlq>z3LF<u7)c@BM3APO-=Zl<7!(u~ z93%`57Dk2$LLy_sg~IUI*3r?i(b26Vh2(PGm_*B%3JnPf4GWD33yX*e3k!?EQCJKk z5_vxgoLf<35L73cO~oTtB*l)ToZrEM0L!_P>J6o2mN4AYC^l4%!{zaVf(0Q|OCqdn zvE9T7L~$rKi^Jmbc|lyZPzJ<EHm7rxgquG|6CFQxl9U(o;*xg?x+KJwZ>yH2TPGh> z@w?8dxOn1Mtt}&N>AI&9)h|`*3b!w_XSO;t_$2+?yHj?2={R+%C~5Zcr{8;d=iz_; z{`&e)j-0+cq-NaIIV(1Ndh~}Y@;*ar>z{dL<;Gpd&RmT|EEbfOL(0VGaWhB}I!mHB zP=c}X(Ol`I7h`Y<wv`{eC`+h5VVyinRS~PTrT^NMhYP?@%-DVi3bCw}u5fUsoj&O) z!re=d)LaDTH%Q1Pc}Ak%=yK%?zr@Xd^<0Owr&p?eJ2G_ZyNTcJUw>%Z;t1XrYhP2s ztdj1|1D6NKJ>K#7qGh{!p0>}bxLn@vbmgoH=hwssJA=<4SkZwt!L1RF@{taiQ8g^^ zh+yJd2e2K2jX)OQi2f4}5mKQFnA&2eCOO0dh^W-kQq%*0AjGGl$hs0VG~nC9ycn}0 zR86(>z@w>dE*@}tN&@fN2(^b`rKAMLJ?Z&p^kjtz%Pxm-012ADK?qh0UH5x@kqqI_ zjAe->SrWNO?D|d^s6gz+RCC!Dvpo8v7qgpT%m^2cf+;WDDOd&Yst47vxgJ!acRg5? zTL+cOYSvAZK?FUU*n!-!<-!+ZQqU-)8Nb`R^1>)sdw~Gzyf04*13GUCz=Vj`Eis<s z2JUvpOqeqe0yYTv!2hNX;4#2;vA+i(0s=F{gjH&+wY0qg*6Lv02CvHFSqoAbtd%~i z^8#imS5s}kYq)p>$2{(pe4OO#ZG{aQtsSpL<1{L@+f}|gm=A3Ya%k{~hDTdeU=X?Y z6Ub=R$7=FPm+O4#l~$9@z1SV1(dkNEpK)~K1bEHAoYpzCw7VRUcrDCYiAxTvQg*A^ z;8Uo`=8Cz<P%K<Op}`EFH`NiccRhu+I(?135H#sMI~lkt;jrLUM_cm^wXiE;uY=Fi zkzI*!wJ#d8s%vaygMyJLqpe!_vY~6M1Di&GKiXA9J|XJft|;<gfX*o!&_{v!^d>uP zHNYC5&Rtuf$y}<j+o7sZX*V($io(=`$%Hh0logu^uhF$EauhM34+Szq74XGVxW$46 z4QALQDAm{?_c9G$=k-{-o!x6AvPISJVG-BfK<hh58(~Yz+c@F%bae%80$;n~5{68G zEe0Kvt4|{bS7Ablsm2Uk90<YMI*rLh8<_1R*P}C(Hd^X5HvI$|@2t3u7vaGUp|$WK zG~$0aH*Sr=Y_@vsP{ok!$>-8)ts3J{n(R_|@1^|*%0cEDOK|y6iV-$h;NINZIj)^R z>;Qb&&%qy1^i+UIF2#Z<$Y@K4-2%iRxMc))&8RWyOUjGNA$1<(^G#|zUhIL;oP+mX zBg!wTaJL*$QDiMK-Er^FEkzs?xX8X={*S8?uox(D_dnkqL$?%eP*h~|*&2krt?r#j zOa^+9)txu4vRiw9mB+h)3)ib0{2Ra^EQK#(gXIKlZ>+Jx&IuVGyz1;4OHue)7zPeI zZxUW6!lP+4o}|Hj072p1eGKC<W&qZ0f{yNFHisJt2ZHrvvKNn~?i~aLu)l&gMqvX8 z>oPb@xO}Z42v7m+^=r`>R0}K6X5@f9e;wf&uh#(`TaAm;T0=FiF9#P3r}d^9{1!{B ziqm6EW8B?_$-`!;@unNJ2E2RhW3QS9s|9e_MlCPA3y$9s@HTIl%QAflQ#`Q@ykSBr z9_Q?38L%w5?%Og#wYlCTqD^?*$JNF9T-L$w9zvuBo796%MC9KP8hA-E0Myb#d@T1M zEtDs9I)B@<Ze5-ncC3F9jE1t|hQJoW|D(8n3pD~azV6#Xg25J#eY~v0_|9PX-^9Hw zL&k;&X&I(EKJndsr!TQuU*bD`n|%j6C406@$9-ESl=zNLZ*w^hu})0`yarRGSAagR z-tYDA3RIyrhz6VNMP16Q+PvXt&+)Olu(yR7$+NO(SVg_wuC2q57Tn0F!d#^Hc~B7y z5J)!Ic|EM9FcWe;Kw;KoD#hXhV2H!_fflXZlWPgaFc-|wM84`_Z%_p^GWWuBE1lU< zoo8-z@gs!iUoCNXj^>La_OKQW1AEK>QKpX=O%)i%s-SL|MQ79DhlmUUi#Rl<;h_aP zx97r~Mu$O!s4X5GGY<WG;^tZd&b<eO=G@8OeLnt(DIa_R-h?1i{P=g{^o&%`Ka+wg zdW%)l<8Vvh5uW9#B2*Js4rk-3B#~m?+<})|tSwuJ^J0Cz6e0~@a0Rw_2;`qqcuZvS z#=H|<<zVD6ziW&W0e`617^g#eSoZOZa<1{P`AI<jZS)`R&A1EPd7QgTZ^qr9jXe%u z_uZRAV4PFC`ZBRlpeK8JJh4ZhCqut;4*>slJsCegLSRi7KabUa(u>JX#DAg}Z*|Y? zVD0*Teixkg^MhgVe?=Q=Afvt0S;ad+pdAQRVW3G2?Y#qlIe3s0H#sl0!vLD&#7|DR zqISayHM#Ko5I<~N*zDR2-`^cLUb^P<y939qYd$}c6Pb`=h_@S0-r;IsN{QNCV#*Dr zbUL9XxZH5TAJ=eAoX!(GQa6Aa?vU35DeqrqU$kJseE7jNAMQ9{7%sTaU&s(h0;6ye z0-!NCe<4F)q|kq*CftmSBmJB03bn%*t~PTcNep^yh6#*~TsIGe5E$x0Y$sRxzep1^ zV=9BSHEglly_obu0gTik@a8Rmx8WezNovtEUFiqPb*FK*$%)R~*o%H{ayB`sTVFQq zMPJ`^-gKg$|JY0IyK>Wc!->AWwHKYd0TAcPzP<Zz+;CoZvQF+ja~<Dres$}*^O_U= zaqTXn`2Q>Y=)!HkCK$=U231X{2~oTgP@Nq&5v<}={o$mV#5d6m7{_io(VQCqambK- Y16@Zf7?Q8!JB-NJ(KYBs*Ff|C0Zg4MIsgCw literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/back_disabled.png b/src/static/jquery/datatables/media/images/back_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..881de7976ff98955e2a5487dca66e618a0655f3d GIT binary patch literal 1361 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3HQ$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W}skZsAp(w zVs37(qhMrUXrOOkq;F`XYiMp|Y-D9%pa2C*K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mLM~XjC6r2bc-wVN)jt{^NN*WCb*;)Cl_TFlw{`TDS%8&Ov*1U zu~h=P6yk;40=Thx#n4~^2AF<DVu8M)o&m^9FonLp_?717!c`ZS1f?R}i`C%bkjjEo z{h-w1{L-RiV8o><gRCmBaxO|uEXgkl$<NP$g<?QPeo20DMt*^UbFis`Z(?$09*7TC z@9S&jnO9trn3tUD>0+w{G(j&jGsVin+1c5}%-r12$=KP@(AChw*vQht)WY1&)XmVs z#Kj1v*Cju>G&eP`1g19yq1OVZUQklVEdbi=l3J8mmYU*Ll%J~r_OewbZnv1?G!Lpb z1-DzwaO%|uIz}H9u}BdO69T3l5EGtkfgE_kPt60S_99@i-f{BMZ3YI$qn<8~Ar-gQ zOt$tu93XPMc=CmoA1oW4o1+WYIB!k3r72K4*@xA>;l+b1ClB@qaOE!8@r8RwiN1wc zl+_Cb3(lEQAv#$bmh>Mfe(I7Woy4{G!}EFf?)^FUc%F02^;EH~5owLt3k}+qS-P)U z616t%^wT0PX2liq$807FHoQ4d$0`5rkQ{U2Kkgclu0)Awnd5T>ob((vrABTq*u(RS z>E?oy`!@uw+@i*D$dKV&#I(EL&;9;u$GTQAMM5faVZejQCzo(NvvlZ75dZt%IYnd( z*RL;GX3W}R-P)5>-Zsu`&nUT&Ho^GzHq{#}Ya$hT91>M0@O`!9^}b&yQ@87fac$Vj zkb72h`!2pMTYunpu!r@;1)uFRXDvH<C2MQCLB5EqVe!tGxM@$<Xmq^}jH~^{nDM>O zu{mw?PmW#JOy1f}J}ILj)G2cQ^TrhhTtyr5@7eCYm=Uoy?6qTPsOnt5?2i>S(pg>~ z>M~M93=YlxcD}*xKl_@hz5j0IZGT@9Yu_^8_RN8=&YkAdFR(fGAAWd4CvkG#0^hlN z8>(g;?I=2=cEEAHaL+WiOvRp~fl`n5dTf5V)bNv|ZcjyzLHRnz@2)SdPWo#3tF@Nf ZfT6u;&2Oo-XD5RSIZszVmvv4FO#nm}^+Nyv literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/back_enabled.png b/src/static/jquery/datatables/media/images/back_enabled.png new file mode 100644 index 0000000000000000000000000000000000000000..c608682b04a6d9b8002602450c8ef7e80ebba099 GIT binary patch literal 1379 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3HQ$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W}skZsAp(w zVs37(qhMrUXrOOkq;F`XYiMp|Y-D9%pa2C*K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mLM~XjC6r2bc-wVN)jt{^NN*WCb*;)Cl_TFlw{`TDS%8&Ov*1U zu~h=P6yk;40=Thx#n4~^2AF<DVu8M)o&m^9FonLp_?717!c`ZS1f?R}i`C%bkjjEo z{h-w1{L-RiV8o><gRCmBaxO|uEXgkl$<NP$g<?QPeo20DMt*^UbFis`Z(?$09*7TC z@9S&jnO9trn3tUD>0+w{G(j&jGsVin+1c5}%-q<}$=KP@(AChw*vQht)WY1&)XmVs z#Kj1v*Cju>G&eP`1g19yq1ObbUQklVEdbi=l3J8mmYU*Ll%J~r_Oewb7Ppv~yBe68 zyO`lL52`l>w_A*G>eUB2MjsThND&Pa0;V1i6P|2=9C*S{%>$<PB4D!4X%u8)U|_uN z>EaktaVzQ1|Nr*PTN#9zMHxeRlNl-}v#d8N^Zk>0_uB7B{#OES8f>#2yG~0qw!L6p zdFucF|1%kW<~W?`S<}!e5q#_SzEeiVo81hJjGh}A8F|(J{8J?#FoV5gKjTM#g@4`` zHat7G{ZGytn}0n$K9W8@XQml^^p~IC#Pg_K>J#_+(?*}aZPd`ZZNa#A3a7~tW{o3_ zI{&|(mY(2P<M2mPEKQ=#bld(%PoD@Gu%2pXjuqzkGD*Yibltx{hgg@~SeV#$)xa&` zKoMiI>V%myRe9%s|Nr;*;U>8s5-)SkmAo$(Keu+yr%y+}MlE>zy+BR9?SIdWBY}H< zKKU5g_O$y^9OKN@zGsEyW<{&Edwac(+`RcS*M!N;4lBR&3)I`!79H%>{JYJ#JU4sR zw=W-e8rT2-_sjK!ftX42KgY{w-6eiM*mqC=xu5>dtj80wm*z`6(^6Ws=-8Pfr#M2- zH|Sq%;`zb5)KTvzU)R6$^W*Do?c4e6>`&v<`V~L7?ymp$=Mn1__Wu)kQ(K;TCm0<N zV>xpn=P<ADl0yMzCpKMo_`~$7`@TZ)ho=qo0nz`RV!4Z+imyoYxv=I7_o}`XdpJKI z%U5yU?-2WkJ?lpOBqOUy+=+=NTT%q?7&I_2GgR!^?CWPQ?*l6KJYD@<);T3K0RWQ{ B1v&r# literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/back_enabled_hover.png b/src/static/jquery/datatables/media/images/back_enabled_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..d300f1064b3beac1d7d5274e294494d3143e53a2 GIT binary patch literal 1375 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3HQ$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W}skZsAp(w zVs37(qhMrUXrOOkq;F`XYiMp|Y-D9%pa2C*K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mLM~XjC6r2bc-wVN)jt{^NN*WCb*;)Cl_TFlw{`TDS%8&Ov*1U zu~h=P6yk;40=Thx#n4~^2AF<DVu8M)o&m^9FonLp_?717!c`ZS1f?R}i`C%bkjjEo z{h-w1{L-RiV8o><gRCmBaxO|uEXgkl$<NP$g<?QPeo20DMt*^UbFis`Z(?$09*7TC z@9S&jnO9trn3tUD>0+w{G(j&jGsVi#&A{2f&C=D-$=KD<(AChw*vQht)WY1&)XmVs z#Kj1v*Cju>G&eP`1g19yq1O$kUQklVEdbi=l3J8mmYU*Ll%J~r_OewbZnrq&G!Lpb z1-DyVaO%|uIz}H9u}BdO69T3l5EGtkfgE_kPt60S_99@io@8}5n}LDxvZsq<NX4zB zKmY&RGjC-OW)@`(<xOU&oXoP`h|Tr>#&7*Qma&&|D2p_oRXCd3<KX<IF+??BIp>7) zY)8(V;EL!lR8{!YrXwuuEuySktariS<$U}5@0hthGki2x_{Vvqo>S_XblJrDt*y7` zPn>AToH0Sw=g;r$;tI__7PkF4^xDY!x~Ps)lA51GcnTBmM+UA!h136k{gg`)kQb<L zYn5zEv|ISR;^vJXK8>Fq_VoBPIz)-gPOY!2f65f}=7PcDED2?Ugq;l&g-#qfGN<kQ z@Bjb)r#kZ2^pup9#2?zN&TsDj^Up`WxAX1e-#_#W=(*t%xaa4;yQyuL-MQl#XRdxa z)mct!l}pQK?u@9-8;ZCmOlEdi`JG?mklel4;>QQhO_+II&v(YRhj*tM|Nr;*pX&(& zF_Y$hj+f86OZ@)!^=7=>-T3-YSLKUdZuf3aZ4Y<s?VQ*uxN06_{32G#57J)EF`r~b z{@T~?`C0PS>HF;C{AO_%40X!?e|-Fvdj<bLW$9BKr>7ri>D1+zvG8V_^em6og*g*a z*EjxPy&}Hf@!5mZjQ<yG``5Zl?8zzpfWtEuM7|UckqxXAe%5>6qphxS*AM<H8~&@L nmZ*pyIy8y%q|%N=21YgpNrScB1<wOzK}DXYtDnm{r-UW|8K3s} literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/favicon.ico b/src/static/jquery/datatables/media/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..6eeaa2a0d393190ce748107222d9a026f992e4a7 GIT binary patch literal 894 zcmZQzU<5(|0R|u`!H~hsz#zuJz@P!dKp_SNAO?xUfG{@$0|>*we<X0{?!DZ?LR&jK zJ4*`(D+_yj`}mZUV<%4{DS<No{rlI{+GcBJTomZJrYz@lN9~2?%3V3hT|wRfwpN+B zxv$^6LDrRDRAizmzo(`AZg1n=>Y}F;x;`B~@Mg`jC-vo5%k$%{OoKy1zkdA+(K2o3 zEDKGQQ~gcX+N!Tt<ln6-e!X((x9eB`|NHmj>Ej1|9e2tL(rheJva*5dKY#gZsIRxM zB;!h7<JJ1on-%#_W>5Wi?9l5?>z>S-`t`=OAFp5C?(007k>qM(bnVuyja#;c*qL9N z(Q%=@`f7d2?T&^wySIHjy#MKh?rZrO7i!Bt-@f(!@WDrwB`uD&)%Eqcd3o(gVV7ri zp6ji@(BF7(+uE0x&)(R!?s#YIg_7JW1=-KHZv1@s(DS<L4gNk(j*fnQelrS_FV5;Z zF}eA|vYC(19e;50(BU}~*0+>xD9<^am-%+f#!uU}z9=j>5*%b{WE2`20#tutPWS1# zz4s39d~xOMwaqJzOl{rMU%#oo=xj&xyY1WF&71o?Hs-LOkA<OOT|+}_QrMM+6RvMw z{^IiKhevmxo!@_KTI>D^4SRbV?yXz(e#efNwKXpT1J^s+yE;1`KXoe5&f?1A$<NLo z|MBttt(|L+O=>tYso}un=1c3AzCL>B&D=RpqN3i1hL&lnclP!D`u*G0#bsJv!oAH) z-rc|T`^Wdkrw?7(xb)_p%`Y#WdAn`Pvz+W#0Rbo6-Ha3zp1gPgjDkZ)k6Gz!@9D0( zG^hL4?)Be4zWep#`{$>RUhUoaq@wgyfd9*oU{6tz+SXQhl3284sj;T&{L=I*bGxt4 z@4vfX%A<*$FN^a&MMa!<bG7B?%PuH@D~2#OZ`<zU;hyB_*c#=(G&yozSimf6i&AxU ucVnZ@2@}v1L%4tb{$0CaV_ZU_m8GSrv9VuZ;G~(e-hB9gtQeLL$fW`Ph4SP8 literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/forward_disabled.png b/src/static/jquery/datatables/media/images/forward_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..6a6ded7de821619aedc71d1738c0b73463a4452e GIT binary patch literal 1363 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3HQ$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W}skZsAp(w zVs37(qhMrUXrOOkq;F`XYiMp|Y-D9%pa2C*K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mLM~XjC6r2bc-wVN)jt{^NN*WCb*;)Cl_TFlw{`TDS%8&Ov*1U zu~h=P6yk;40=Thx#n4~^2AF<DVu8M)o&m^9FonLp_?717!c`ZS1f?R}i`C%bkjjEo z{h-w1{L-RiV8o><gRCmBaxO|uEXgkl$<NP$g<?QPeo20DMt*^UbFis`Z(?$09*7TC z@9S&jnO9trn3tUD>0+w{G(j&jGsVin+1c5}%-qS)$=KP@(AChw*vQht)WY1&)XmVs z#Kj1v*Cju>G&eP`1g19yq1PFwUQklVEdbi=l3J8mmYU*Ll%J~r_OewbZns$CG!Lpb z1-Dxqaq86vIz}H9u}BdO69T3l5EGtkfgE_kPt60S_99@ies{+CJ_7^eaZeY=kcwMt zrucd@1&XviUp=W&hC_Vigxz9qe=+JQiRZ>#-OmxVbJNmo0?O0%xE7^$7hDVzS=7nq zBvt-aWrpIMi;ByGX0JatRXb+C`iBGE*Nwm1%=tcVr*ri@cU^6Xtj>)g66P@%1db+s zWSF+QYf((v=9^+`Y}d3l_I1DM*_La4%-~F<iqOupPmA17rUW(EbkF;HUG47s@9eHR zr{8fl70mTeS!Xo!jNOv34{^8jdm7J095R#VVBvFKc)@pJzz&b)m#u$9NW?Q2$h6PB zall}<&3SqE#TR$i*ws(+TAC!FeR-G6#+SR^`AEwg&t-2u__@HMMymh#c8=GRFUN>X zOD#3=6_)Nj)~$1T^@J$qollO4A6gI{9eUN=bCTSutFMe5M0p+_TYIkc<*t8mtFJEc zTKXwVqK$2(et`HF?-Em4wsu<!<_gzaU#tGEjL|!t;N5yfeTD0a=52`&N+cpS`CP8i znd<d@k%rWcW-~^|3;8^oj^}f5ex7x98BduHL+yj~6Vv#NKJ02wGkiVk;$eS*Jxf+p z$Zlz@mz~hL`(;vx_3L#?=RDGP)Q0?N?yipLo6qfkC??74@c(mr@}3>kSTsY4VW0ic bdL|wQU%!)=<|i%z6_yO1u6{1-oD!M<;V$ow literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/forward_enabled.png b/src/static/jquery/datatables/media/images/forward_enabled.png new file mode 100644 index 0000000000000000000000000000000000000000..a4e6b5384b8454ee7f44a8f7c75b0321b7eeb9b1 GIT binary patch literal 1380 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3HQ$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W}skZsAp(w zVs37(qhMrUXrOOkq;F`XYiMp|Y-D9%pa2C*K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mLM~XjC6r2bc-wVN)jt{^NN*WCb*;)Cl_TFlw{`TDS%8&Ov*1U zu~h=P6yk;40=Thx#n4~^2AF<DVu8M)o&m^9FonLp_?717!c`ZS1f?R}i`C%bkjjEo z{h-w1{L-RiV8o><gRCmBaxO|uEXgkl$<NP$g<?QPeo20DMt*^UbFis`Z(?$09*7TC z@9S&jnO9trn3tUD>0+w{G(j&jGsVip+||I$+{MJu$=KP@(AChw*vQht)WY1&)XmVs z#Kj1v*Cju>G&eP`1g19yq1P0rUQklVEdbi=l3J8mmYU*Ll%J~r_OewbZnqfWG!Lpb z1-Dy_aq86vIz}H9u}BdO69T3l5EGtkfgE_kPt60S_99@iW_)h2mVtrshNp{TNX4zB zKmY&RGjC-OW)@`(<xOrhlxSR#{V1QGt?hr?`T4Q)?%vP*Bc}03zKfG7pg?hV&&T)k z=YR6?(OD}r$x1tWwtV}J%B!E5kIr-~T2eLn<MZ?S3BG5}tm&)yGwJi&xn0jfuG}qR z<J#zS)kr8?;`06d`)3H=OM8@*{+w4#C@kW}ouAwE_kWopW)d-@qpQKbUZCxusKG{$ zf+Ef|Z?Bi@*5=nvn?AMPA<pgE4AI%zfqQ-e9Xsb<LSkb0<EN8f2u{DSYTE|Csm`CQ z(sG2D>g)dh`10)R-NpU#bM1=1eo8Z2AYd)<-?^`_sqOFY@6XS7KM&8JXTA5$g^A9S z{TX;`xlCJF@2;-kt^WS)-(qj^YjbRh3Qo21zn9<7##PJs=)J=q?vtT6c$tqWSn$;S z{q^hJt*2*?^Szy4@bTi|;PVYm@{K=qh5oS|v0uoRWd7#=|NZ;-*VL7!+<x}z?DD?z zwfv<AtyP>I+Ui=RzOdW2D@cF)|8@0kar@euUy>OYxL3%Wh|X{LVLRn7b4UH-Q)xXL zlsIOXI?k$WjNtJ4&-&<m!1bDTsZadjajY|&9~rIq>^N(`qv`*KNBfVYRHPjKr+8GT t=fC*;><^O18kWptJjt-AJE?(znPJ1m)BPofdH;jTJx^CZmvv4FO#l_Q2A%)_ literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/forward_enabled_hover.png b/src/static/jquery/datatables/media/images/forward_enabled_hover.png new file mode 100644 index 0000000000000000000000000000000000000000..fc46c5ebf0524b72a509fe2d7c1bc74995cb8a9d GIT binary patch literal 1379 zcmeAS@N?(olHy`uVBq!ia0vp^!XV7S1|*9D%+3HQ$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%u1Od5hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W}skZsAp(w zVs37(qhMrUXrOOkq;F`XYiMp|Y-D9%pa2C*K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mLM~XjC6r2bc-wVN)jt{^NN*WCb*;)Cl_TFlw{`TDS%8&Ov*1U zu~h=P6yk;40=Thx#n4~^2AF<DVu8M)o&m^9FonLp_?717!c`ZS1f?R}i`C%bkjjEo z{h-w1{L-RiV8o><gRCmBaxO|uEXgkl$<NP$g<?QPeo20DMt*^UbFis`Z(?$09*7TC z@9S&jnO9trn3tUD>0+w{G(j&jGsVi#&A{2f&C=1($=KD<(AChw*vQht)WY1&)XmVs z#Kj1v*Cju>G&eP`1g19yq1OqgUQklVEdbi=l3J8mmYU*Ll%J~r_OewbZns$AG!Lpb z1-Dx)aq86vIz}H9u}BdO69T3l5EGtkfgE_kPt60S_99@imN7BvVqjpr?&;zfQgJKk z&;S4S%v%{AKQQkR<Y-#-zRJMhkNKY;|DL_sdwb7)rq=(?hK>wI?VL9s)YsRaG&b6_ z<rC+M^<TKG1Q#t0Kfo`N&UR8TS)nVj{$CAqc2ZJO;gbg<v)8YhX?6VW{|4iL4$)Q9 zCPo~d@$c{Nqdev_Cw6wXPPLvf+dXYz{*9w{>gRo<91_J$Y%O?`e|&#$ZtS+eXp_f= zjUUrLb7!pi%4at>{rxttxB!poqO-MU1}Hz4_scgh+`O`|pzGU*Ppd<;SGk>1td!-8 z=;-~nzrMci*RP)sFMiM0pIiAYg<m?LL-vW}6Nz+1nWsS4{VMqVZ1HbtzPo#OK47_U zVR?Xa#D%?G*Eg(>m$R?>m2vx|wYgZ#kAH7}W-quPuJDiV$o>g2t#=I)c$y9~%y7A9 zTfgc1jk&Lj_4ZX)f0PV(p)9c9_0ar=AL>^e-n9Mw|Nr~<^YZ!qF*`48{dsWi)b|VZ zD%w*xPFz?Y(EM+~bAgn@|LT8!dGP4_dwn}*-YUka%$2Ws1@^aZs%Q9^A9It(GQY{> zGt)+aDgU^S%wM?fC!gsP`E`4^jM#4)q-B&8J6^t!zrwrDf%l)k#^S|Oq%QdIe*R^@ tLh*lxrsW37V+~Wv{w==9!pqEIz%cpgo%)U5J^Y|z&(qb<Wt~$(69B7>2Z8_q literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/sort_asc.png b/src/static/jquery/datatables/media/images/sort_asc.png new file mode 100644 index 0000000000000000000000000000000000000000..a88d7975fe9017e4e5f2289a94bd1ed66a5f59dc GIT binary patch literal 1118 zcmbVLO=#0l98awuV{<Z@!!LxlD0<K~@1>uMt6P_}u4rcI3idKFP2SpU%ZJIE?RL`X zK?Oyo=*5GG2SxDYK=7akJqV&hrl{aWJa`y*5xh+1%i2y4V}gO?edPc9{r;a9vjc}) zn|Cxb4AYwFmvVG%_ui)U^y_4!ujsO!qzYuv8YUIR!Aw%KiWp=JrG#@>(I!s4#N7<z zAJ+2)Qjm`ds$~Qf&n8$kY>H->?w+cxsH2#GA};A>g8lyFDGPKh!5)vuP_{)}*83+N zJUBU!S0_i+E{*Lu1iGsNB``2iK-CyCU7?y_mv{xb_pUh>ESZqe1Y2{eAZLMSIT%EO zFrdOH1W^=3p>Qk~I{<iyAP0F4@c|SQLc9PWs6Q-KbF^V0C#CCJ^ps%BgxCVdRVtNW zB^0!r5{J6Fx;ze^4^WGMJ7E%~8Zh164F(Cjs-xRPw@lzMDn)CYBv|TcEd;}s<z-^i zttX16jH@a(hk}qZ3@@%FYnSBkA2(LCcJmW9=5pAz#vPT`V|aH1OmnxokY`A}5so=J zEs8QGS?aifO_GrkEd3MIbWMOL4iSolVT^~-I6{4)IG>J+k#s5zQ@j{%aIA!l^GQjJ zqA1Uc2%!{8qBKfMNh#9DCnKS_*uZ8?mnf!+8@f8xtz#prVg=E`3bCBLWsNmDAX~PG z<(4fQh=UOzE2?gKXRkc9XeI3Er?HlHECVd%SI}3`hy1_du3@$R$r(qT;k@Sft63UX zv;)2Ea_iH>^6+4jPK-lG<IPpyQ94#vGEy>M{Zw37T<r1BFzx;hUrXn@cb9)YK9k?s zc5~+a{$F?I@W<X;>z>~~zlHzO61x51(V4jcaKrcIVDG$-d>)z}S|7f!xxYhfUE}Kj zug_h&HZN}go22$5Ym1}P8~vYNx7-~$TWFJ;_nh!wFYSAQJF{CCo=xpK8^7?iY1^!H haOA^1<p<mdo-xN}_lDcv4t?_`K9d@d9`>D_`VC7fU=jcT literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/sort_asc_disabled.png b/src/static/jquery/datatables/media/images/sort_asc_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..4e144cf0b1f786a9248a2998311e8109998d8a2d GIT binary patch literal 1050 zcmaJ=O-K|`93R^(@goeAz6hRU)S-61)?IaU({*Myml|8vh4x}JJM&z}b>>Yo&vx~s z*1>{0Sk$FMM28~iln?~vp$<WaghdHmq(cXxOVGuzH|wr;a2t5@-v9CY{r;ctMq=P> zL+z1TilQ3g{c@7*P2Q^6L;g-8^nq-LaWstw(J;=d4x}PF%0Lh|)htXxRiC)>9(Gfd zk2X?ioL0_@8ZsHx!!QNYCTxo8?kU)+mV+2%VAin0^v_psXkh4J`eIPw6kCELM*pM( z2PX$o+GI}a)ajlxpt~Rv0TW^s6wEQp6$@dys4J4Qcg@nE2*J59y%|(mNdO5s5Cj>{ zuW=y`gm{Jzw6(Xlp9TWQb1WyYyx`~C#eg7k94LJ>@#g5mVp5Kkd=V>5k6>(zESt~g znS6jjPL}06J3BoMLGTlV-<`0qTJT$LYgs{tuI3mvHjo88MKy!QahN8NZl++`Te6m0 zDibLfTTpG5XE-mVGEh<e4>ip#w2PB)JKi0I-PD8)*(7w)xTBHA4Yzu(Y*BKcijk8- zXslet#0bL39YHpb27^FRHN*1kB3@C%xaDHi(qLQ;(?o$W3|;IHBC-_Xc|nkPo{#bo zKE_Anh#c$_BEdk1ROZS^8#kea%Upe%D^%oqqhQ*^vkV>MD%4{RGC?tA(byrDwm?jZ z#$wTmdL^!2ITo%WmnFflUSt1hboq)*k9XV}TViYtKD5ZRJ7lb1H!ZJ`CviJ2M^c5A z%=*Sgk8hr8@-<i0wN!t)_50;i>S*Kr`Ol~RJX(fddmmK4eR}<Xuv!;*`0T~h@&LG3 zwc6FYR)xO}%?<5oo88~vEH&(^Y6gqfZr)i__JVzK)4AQ5++4kHWwGw@=ybYKsXczl zcQ<?T9c)P)Twj<uHr+A%z2?x8+%@{;iTaDH2Mg4Nr4wz9ABTQ;uQeVWke~Nmp7{$- C^G(eF literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/sort_both.png b/src/static/jquery/datatables/media/images/sort_both.png new file mode 100644 index 0000000000000000000000000000000000000000..18670406bc01ab2721781822dd6478917745ff54 GIT binary patch literal 1136 zcmaJ>O=#0l98WD1Hz^GK+C=e@fhgE~b#2$Ux^~T`1v5)mw1NlI<aG^O^0MU3c0+I# z#fe@;J&02TMMOL(%n#JD4N=Dg5kZe*c<?fIng?~h%yoLO29o#wkKgb2|9m;0>e}zC z+ge9alrMQeN|SYi`>tC{zIG}!O_oO7k;UC8kBf>8sknx65F`zy2d1H-4fel=trX>@ z^-LCL<%6P%3`TJ=Ov$hao1$9VN|vJbLJV@SM>nJN{L>dS(6uOiBq(#Tm4F5Pz>p2Q zhq^NAP_G)%=(c^JwImV&17Zb~j6Ty5OHq1RS0sD)n5Dro1ouYi-$7;N6i6T&f*`~B zRW8JV5YO;|=5RQ?2M8R`v7Es2f}anI0YT(Au=3Evo2})=wA8uci&#;*fUzaAY_V8m ziU9`MJuDxIL|hF)@DqgJ88op{@|#XmML~j&YU>u(kqKNyC5HxZlqQk>PQkENWld+L zOr&6JNwHX-;oOueKw17j)G$`j4o<^A@%~fT$qZVMO+yC_*eYpUzR7iEi3uAj7}*(w z`YKgS6%a;F0a+l?9R#wX>ZWTi<7HV)nhsV>6(*%9O%xbi*F?TK!383rh#(|*p6}q} zd?z25;!?0(hzA2Li3(Rj>VN@FT;Xbexbdo7cN7eZc$T28pMYAYjSR4yvZz;&C0tc+ zg{xJMrKKvDCBd+6WB+P&<%mp=yImbyVyq56G|9BvWUP^I>ms=lb4e+lDSgg;Us`JO zKB6{wH+j~F#-A4FY3K3qm~Z6m@V6}oQ%8?p-E$dw`#0C$PJfmCV8)v}3>Ydha%`fZ zJk~G*M^A3LGk$Td;R`icF67R~`sBOHv)Hlqlc%$jy~9_oZJcNyWxkbb_O9u#|7hLF z-<-NMLzh3S0YA@8gd1Pt(Df|3@16Y-n=aSvsF@AkI`ioeFg>&H3bXU&vBnE6<F`Dv z=gE<e-UW~SzHwK6r)OdNuBF=g#rCP!Z@NaewRuKPC4A32?Y^7kPqBM-lijtuwQUd2 cHpPZL)Z9?>gIChkL+(Ey+0iB4Z$Eze7t_CX>Hq)$ literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/sort_desc.png b/src/static/jquery/datatables/media/images/sort_desc.png new file mode 100644 index 0000000000000000000000000000000000000000..def071ed5afd264a036f6d9e75856366fd6ad153 GIT binary patch literal 1127 zcmbVMOK8+U7*1U&zKRu5sR)h{1;yRWWV^4}ShvZpU2*HWU2!iy(qy)cZ89;Lb+`3m zMbruv!GjkO!3qksP*5)lD)k}=Dp*ht-n@8G5m8XoN!zU+ih_Y;=AZe$?|)|~*Ri8v z(dtDU$2DZy)jV65`|pB!_H}d7Cv0h=sUqzpC0fy3%q0!dg+a#Bx^W(BM*oq=xP{{a zC9_bZ#q2IgCss)FbwX9kVQ7wPX{|b%-is;d!ri7V^Y8E8=YeU+{JuyQW*r6hnC$~D z?i}bS=mWia!r)uCftISo2rNuBP__DOPpZoN6tBeg{;|M=DHYl)^V3chvpJv;7lTL$ z26Y&PAc{gL+#HL=wg3?#C_qs_Vi3iouqZ(YW*(kdbB&UeSJN}Lm?ZN(lsb|iR4SEF zB^)Adw}29fgwG+0L8cM(`faLJgSNN6#-L(PcTI<y#0Ea2)<w!x=9#C{Ay`f}J4<YP zGl^m;6RMgcpb!)+%a3bH+oO5>+l@K3y+Xf(g*^61+0|J+O6zN2mb<?j@)emk(r(ve zMbY|HqL(df(~K(f>?UNGh6GU@A{1+eF%d@N2(^XdVmhis(y25|iAr;gV=io5OsYy0 zB}Gv|2&GUGrBPB%s*yG^841Ug8a88lRI_zlvuiTDGuXsmv6A9qjS{y&NMEf3ay^6+ zuZK85>5PD^rkl1e`{kLAR>iJ)6dP%mSYRr@k~xQcDE=$%X{_--ITM&Og5Ml}G)wJ> zb)dhUZG9%p4iC23#JFrUCcmwHz{cugMoku~ue-kg{Mj0~%`FeCcz9jAdg}QET-kSG za`+2B_+lRTaeAVz>E`F1pN7h>B=BbGqcz13d%ywZR&4OjkNNrF_U}#EcXDGa@V52B z>JnIW<rtP5*FLy5xa{DKx+PmNxE(mN_xRU^jduh4%fq8D=O4becw{5@k$}r5pMp!{ qL-nP=_~ypl8%E9_dA9N#SI7Pv4V%u6t+Pk{(a)qh)UmchCw>7#s%CHi literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/images/sort_desc_disabled.png b/src/static/jquery/datatables/media/images/sort_desc_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..7824973cc60fc1841b16f2cb39323cefcdc3f942 GIT binary patch literal 1045 zcmaJ=&rj1(9IuWjVlWt@h#q(rlc~7%$2P_q>KN??ODrK{#&I!}_Kh{rzS=%m2N%F- zAW={L0VZBJnRrkSCK{q1NKA||(ZmA>6Hgw9o;Z-;>)3_|u*vIt-<Qwl^Zof&M@NQQ zTh6yo6xEs?mUCop_gC{V@^?miKa#Bzrwe!t6>(X0AeGY5Bm`Mgoq{>2>Xkbiu%Ds= zw2?31f^tL9kQr8eOxQDR!ltPHq-U$zG{j&MP8pU+Z@qp?149?-TQP-IYzdZ(;duv+ z&5z`@`Drbo)5+_g-xG*{39$-1bH;K7Po%550y+EF3=OIfJT20DK^2ryARz~WSeOlI zY%dFXxiA-r#^dp8fM+?DVR?q*LtI>l@B+(%+D8*_j$RaUa;D~sSR!4**cKS3TrP*p zkuY+m7%q`W_!>MPB8ZS%v9RieEVsL^AVXJk3>zEB0=}X;iDt1#lSubcFztq{<<`nX z3dVS<&2VAXPpJ-6l>b9bvw?PT4(`W$ps<^-*pSIV7tJ~vX<V_}cV!Eb167QiJVG<| zDvp*AMs5k&KpKkyMb!+;x2t$X5wezxRZD|eS)_?V*f4Y<8p%lMOeV_n6320AF2!ZI zl$?@dgM2C$>67YQ8ELa7v~ZoP?{i~^a{W;-ZQ@ymjxh)IjDt*2O<6Dwh=q$vY$VY; zc&J{Ds~-?cjVm3>Wk@iL-`IZ|UB4pJ;~yJiON_?gLyJtiL&kbxZhV_OiPfx}%6s1@ zcXoG^ffrPJ;LQ4(`t<(ickJ1j<?`0%!=~KH#qF+B$MwrSJ)eSK;jcw6+2&5H4=s7E zS2lM}yblfRbSgVyTU<LGJXZuAPZprq)&+t`2R>|E0&fC8lSh8sUh5lwUg=l~QoqsK t`nTanN|e2@a&yVMdhy<ayD#mgW|oR{f-jF3U;XhPYBoJ0KO3A_{tM)BOYZ;x literal 0 HcmV?d00001 diff --git a/src/static/jquery/datatables/media/js/jquery.dataTables.bootstrap.js b/src/static/jquery/datatables/media/js/jquery.dataTables.bootstrap.js new file mode 100644 index 0000000..7c552e0 --- /dev/null +++ b/src/static/jquery/datatables/media/js/jquery.dataTables.bootstrap.js @@ -0,0 +1,148 @@ +/* Set the defaults for DataTables initialisation */ +$.extend( true, $.fn.dataTable.defaults, { + "sDom": "<'row-fluid'<'span6'l><'span6'f>r>t<'row-fluid'<'span6'i><'span6'p>>", + "sPaginationType": "bootstrap", + "oLanguage": { + "sLengthMenu": "_MENU_ records per page" + } +} ); + + +/* Default class modification */ +$.extend( $.fn.dataTableExt.oStdClasses, { + "sWrapper": "dataTables_wrapper form-inline" +} ); + + +/* API method to get paging information */ +$.fn.dataTableExt.oApi.fnPagingInfo = function ( oSettings ) +{ + return { + "iStart": oSettings._iDisplayStart, + "iEnd": oSettings.fnDisplayEnd(), + "iLength": oSettings._iDisplayLength, + "iTotal": oSettings.fnRecordsTotal(), + "iFilteredTotal": oSettings.fnRecordsDisplay(), + "iPage": oSettings._iDisplayLength === -1 ? + 0 : Math.ceil( oSettings._iDisplayStart / oSettings._iDisplayLength ), + "iTotalPages": oSettings._iDisplayLength === -1 ? + 0 : Math.ceil( oSettings.fnRecordsDisplay() / oSettings._iDisplayLength ) + }; +}; + + +/* Bootstrap style pagination control */ +$.extend( $.fn.dataTableExt.oPagination, { + "bootstrap": { + "fnInit": function( oSettings, nPaging, fnDraw ) { + var oLang = oSettings.oLanguage.oPaginate; + var fnClickHandler = function ( e ) { + e.preventDefault(); + if ( oSettings.oApi._fnPageChange(oSettings, e.data.action) ) { + fnDraw( oSettings ); + } + }; + + $(nPaging).addClass('pagination').append( + '<ul>'+ + '<li class="prev disabled"><a href="#">&larr; '+oLang.sPrevious+'</a></li>'+ + '<li class="next disabled"><a href="#">'+oLang.sNext+' &rarr; </a></li>'+ + '</ul>' + ); + var els = $('a', nPaging); + $(els[0]).bind( 'click.DT', { action: "previous" }, fnClickHandler ); + $(els[1]).bind( 'click.DT', { action: "next" }, fnClickHandler ); + }, + + "fnUpdate": function ( oSettings, fnDraw ) { + var iListLength = 5; + var oPaging = oSettings.oInstance.fnPagingInfo(); + var an = oSettings.aanFeatures.p; + var i, ien, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2); + + if ( oPaging.iTotalPages < iListLength) { + iStart = 1; + iEnd = oPaging.iTotalPages; + } + else if ( oPaging.iPage <= iHalf ) { + iStart = 1; + iEnd = iListLength; + } else if ( oPaging.iPage >= (oPaging.iTotalPages-iHalf) ) { + iStart = oPaging.iTotalPages - iListLength + 1; + iEnd = oPaging.iTotalPages; + } else { + iStart = oPaging.iPage - iHalf + 1; + iEnd = iStart + iListLength - 1; + } + + for ( i=0, ien=an.length ; i<ien ; i++ ) { + // Remove the middle elements + $('li:gt(0)', an[i]).filter(':not(:last)').remove(); + + // Add the new list items and their event handlers + for ( j=iStart ; j<=iEnd ; j++ ) { + sClass = (j==oPaging.iPage+1) ? 'class="active"' : ''; + $('<li '+sClass+'><a href="#">'+j+'</a></li>') + .insertBefore( $('li:last', an[i])[0] ) + .bind('click', function (e) { + e.preventDefault(); + oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength; + fnDraw( oSettings ); + } ); + } + + // Add / remove disabled classes from the static elements + if ( oPaging.iPage === 0 ) { + $('li:first', an[i]).addClass('disabled'); + } else { + $('li:first', an[i]).removeClass('disabled'); + } + + if ( oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0 ) { + $('li:last', an[i]).addClass('disabled'); + } else { + $('li:last', an[i]).removeClass('disabled'); + } + } + } + } +} ); + + +/* + * TableTools Bootstrap compatibility + * Required TableTools 2.1+ + */ +if ( $.fn.DataTable.TableTools ) { + // Set the classes that TableTools uses to something suitable for Bootstrap + $.extend( true, $.fn.DataTable.TableTools.classes, { + "container": "DTTT btn-group", + "buttons": { + "normal": "btn", + "disabled": "disabled" + }, + "collection": { + "container": "DTTT_dropdown dropdown-menu", + "buttons": { + "normal": "", + "disabled": "disabled" + } + }, + "print": { + "info": "DTTT_print_info modal" + }, + "select": { + "row": "active" + } + } ); + + // Have the collection use a bootstrap compatible dropdown + $.extend( true, $.fn.DataTable.TableTools.DEFAULTS.oTags, { + "collection": { + "container": "ul", + "button": "li", + "liner": "a" + } + } ); +} + diff --git a/src/static/jquery/datatables/media/js/jquery.dataTables.js b/src/static/jquery/datatables/media/js/jquery.dataTables.js new file mode 100644 index 0000000..1d8a220 --- /dev/null +++ b/src/static/jquery/datatables/media/js/jquery.dataTables.js @@ -0,0 +1,12099 @@ +/** + * @summary DataTables + * @description Paginate, search and sort HTML tables + * @version 1.9.4 + * @file jquery.dataTables.js + * @author Allan Jardine (www.sprymedia.co.uk) + * @contact www.sprymedia.co.uk/contact + * + * @copyright Copyright 2008-2012 Allan Jardine, all rights reserved. + * + * This source file is free software, under either the GPL v2 license or a + * BSD style license, available at: + * http://datatables.net/license_gpl2 + * http://datatables.net/license_bsd + * + * This source file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + * + * For details please refer to: http://www.datatables.net + */ + +/*jslint evil: true, undef: true, browser: true */ +/*globals $, jQuery,define,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex,_fnInfoMacros,_fnBrowserDetect,_fnGetColumns*/ + +(/** @lends <global> */function( window, document, undefined ) { + +(function( factory ) { + "use strict"; + + // Define as an AMD module if possible + if ( typeof define === 'function' && define.amd ) + { + define( ['jquery'], factory ); + } + /* Define using browser globals otherwise + * Prevent multiple instantiations if the script is loaded twice + */ + else if ( jQuery && !jQuery.fn.dataTable ) + { + factory( jQuery ); + } +} +(/** @lends <global> */function( $ ) { + "use strict"; + /** + * DataTables is a plug-in for the jQuery Javascript library. It is a + * highly flexible tool, based upon the foundations of progressive + * enhancement, which will add advanced interaction controls to any + * HTML table. For a full list of features please refer to + * <a href="http://datatables.net">DataTables.net</a>. + * + * Note that the <i>DataTable</i> object is not a global variable but is + * aliased to <i>jQuery.fn.DataTable</i> and <i>jQuery.fn.dataTable</i> through which + * it may be accessed. + * + * @class + * @param {object} [oInit={}] Configuration object for DataTables. Options + * are defined by {@link DataTable.defaults} + * @requires jQuery 1.3+ + * + * @example + * // Basic initialisation + * $(document).ready( function { + * $('#example').dataTable(); + * } ); + * + * @example + * // Initialisation with configuration options - in this case, disable + * // pagination and sorting. + * $(document).ready( function { + * $('#example').dataTable( { + * "bPaginate": false, + * "bSort": false + * } ); + * } ); + */ + var DataTable = function( oInit ) + { + + + /** + * Add a column to the list used for the table with default values + * @param {object} oSettings dataTables settings object + * @param {node} nTh The th element for this column + * @memberof DataTable#oApi + */ + function _fnAddColumn( oSettings, nTh ) + { + var oDefaults = DataTable.defaults.columns; + var iCol = oSettings.aoColumns.length; + var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, { + "sSortingClass": oSettings.oClasses.sSortable, + "sSortingClassJUI": oSettings.oClasses.sSortJUI, + "nTh": nTh ? nTh : document.createElement('th'), + "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '', + "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol], + "mData": oDefaults.mData ? oDefaults.oDefaults : iCol + } ); + oSettings.aoColumns.push( oCol ); + + /* Add a column specific filter */ + if ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null ) + { + oSettings.aoPreSearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch ); + } + else + { + var oPre = oSettings.aoPreSearchCols[ iCol ]; + + /* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */ + if ( oPre.bRegex === undefined ) + { + oPre.bRegex = true; + } + + if ( oPre.bSmart === undefined ) + { + oPre.bSmart = true; + } + + if ( oPre.bCaseInsensitive === undefined ) + { + oPre.bCaseInsensitive = true; + } + } + + /* Use the column options function to initialise classes etc */ + _fnColumnOptions( oSettings, iCol, null ); + } + + + /** + * Apply options for a column + * @param {object} oSettings dataTables settings object + * @param {int} iCol column index to consider + * @param {object} oOptions object with sType, bVisible and bSearchable etc + * @memberof DataTable#oApi + */ + function _fnColumnOptions( oSettings, iCol, oOptions ) + { + var oCol = oSettings.aoColumns[ iCol ]; + + /* User specified column options */ + if ( oOptions !== undefined && oOptions !== null ) + { + /* Backwards compatibility for mDataProp */ + if ( oOptions.mDataProp && !oOptions.mData ) + { + oOptions.mData = oOptions.mDataProp; + } + + if ( oOptions.sType !== undefined ) + { + oCol.sType = oOptions.sType; + oCol._bAutoType = false; + } + + $.extend( oCol, oOptions ); + _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); + + /* iDataSort to be applied (backwards compatibility), but aDataSort will take + * priority if defined + */ + if ( oOptions.iDataSort !== undefined ) + { + oCol.aDataSort = [ oOptions.iDataSort ]; + } + _fnMap( oCol, oOptions, "aDataSort" ); + } + + /* Cache the data get and set functions for speed */ + var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null; + var mData = _fnGetObjectDataFn( oCol.mData ); + + oCol.fnGetData = function (oData, sSpecific) { + var innerData = mData( oData, sSpecific ); + + if ( oCol.mRender && (sSpecific && sSpecific !== '') ) + { + return mRender( innerData, sSpecific, oData ); + } + return innerData; + }; + oCol.fnSetData = _fnSetObjectDataFn( oCol.mData ); + + /* Feature sorting overrides column specific when off */ + if ( !oSettings.oFeatures.bSort ) + { + oCol.bSortable = false; + } + + /* Check that the class assignment is correct for sorting */ + if ( !oCol.bSortable || + ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) ) + { + oCol.sSortingClass = oSettings.oClasses.sSortableNone; + oCol.sSortingClassJUI = ""; + } + else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1 ) + { + oCol.sSortingClass = oSettings.oClasses.sSortable; + oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI; + } + else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 ) + { + oCol.sSortingClass = oSettings.oClasses.sSortableAsc; + oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed; + } + else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 ) + { + oCol.sSortingClass = oSettings.oClasses.sSortableDesc; + oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed; + } + } + + + /** + * Adjust the table column widths for new data. Note: you would probably want to + * do a redraw after calling this function! + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnAdjustColumnSizing ( oSettings ) + { + /* Not interested in doing column width calculation if auto-width is disabled */ + if ( oSettings.oFeatures.bAutoWidth === false ) + { + return false; + } + + _fnCalculateColumnWidths( oSettings ); + for ( var i=0 , iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + oSettings.aoColumns[i].nTh.style.width = oSettings.aoColumns[i].sWidth; + } + } + + + /** + * Covert the index of a visible column to the index in the data array (take account + * of hidden columns) + * @param {object} oSettings dataTables settings object + * @param {int} iMatch Visible column index to lookup + * @returns {int} i the data index + * @memberof DataTable#oApi + */ + function _fnVisibleToColumnIndex( oSettings, iMatch ) + { + var aiVis = _fnGetColumns( oSettings, 'bVisible' ); + + return typeof aiVis[iMatch] === 'number' ? + aiVis[iMatch] : + null; + } + + + /** + * Covert the index of an index in the data array and convert it to the visible + * column index (take account of hidden columns) + * @param {int} iMatch Column index to lookup + * @param {object} oSettings dataTables settings object + * @returns {int} i the data index + * @memberof DataTable#oApi + */ + function _fnColumnIndexToVisible( oSettings, iMatch ) + { + var aiVis = _fnGetColumns( oSettings, 'bVisible' ); + var iPos = $.inArray( iMatch, aiVis ); + + return iPos !== -1 ? iPos : null; + } + + + /** + * Get the number of visible columns + * @param {object} oSettings dataTables settings object + * @returns {int} i the number of visible columns + * @memberof DataTable#oApi + */ + function _fnVisbleColumns( oSettings ) + { + return _fnGetColumns( oSettings, 'bVisible' ).length; + } + + + /** + * Get an array of column indexes that match a given property + * @param {object} oSettings dataTables settings object + * @param {string} sParam Parameter in aoColumns to look for - typically + * bVisible or bSearchable + * @returns {array} Array of indexes with matched properties + * @memberof DataTable#oApi + */ + function _fnGetColumns( oSettings, sParam ) + { + var a = []; + + $.map( oSettings.aoColumns, function(val, i) { + if ( val[sParam] ) { + a.push( i ); + } + } ); + + return a; + } + + + /** + * Get the sort type based on an input string + * @param {string} sData data we wish to know the type of + * @returns {string} type (defaults to 'string' if no type can be detected) + * @memberof DataTable#oApi + */ + function _fnDetectType( sData ) + { + var aTypes = DataTable.ext.aTypes; + var iLen = aTypes.length; + + for ( var i=0 ; i<iLen ; i++ ) + { + var sType = aTypes[i]( sData ); + if ( sType !== null ) + { + return sType; + } + } + + return 'string'; + } + + + /** + * Figure out how to reorder a display list + * @param {object} oSettings dataTables settings object + * @returns array {int} aiReturn index list for reordering + * @memberof DataTable#oApi + */ + function _fnReOrderIndex ( oSettings, sColumns ) + { + var aColumns = sColumns.split(','); + var aiReturn = []; + + for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + for ( var j=0 ; j<iLen ; j++ ) + { + if ( oSettings.aoColumns[i].sName == aColumns[j] ) + { + aiReturn.push( j ); + break; + } + } + } + + return aiReturn; + } + + + /** + * Get the column ordering that DataTables expects + * @param {object} oSettings dataTables settings object + * @returns {string} comma separated list of names + * @memberof DataTable#oApi + */ + function _fnColumnOrdering ( oSettings ) + { + var sNames = ''; + for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + sNames += oSettings.aoColumns[i].sName+','; + } + if ( sNames.length == iLen ) + { + return ""; + } + return sNames.slice(0, -1); + } + + + /** + * Take the column definitions and static columns arrays and calculate how + * they relate to column indexes. The callback function will then apply the + * definition found for a column to a suitable configuration object. + * @param {object} oSettings dataTables settings object + * @param {array} aoColDefs The aoColumnDefs array that is to be applied + * @param {array} aoCols The aoColumns array that defines columns individually + * @param {function} fn Callback function - takes two parameters, the calculated + * column index and the definition for that column. + * @memberof DataTable#oApi + */ + function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn ) + { + var i, iLen, j, jLen, k, kLen; + + // Column definitions with aTargets + if ( aoColDefs ) + { + /* Loop over the definitions array - loop in reverse so first instance has priority */ + for ( i=aoColDefs.length-1 ; i>=0 ; i-- ) + { + /* Each definition can target multiple columns, as it is an array */ + var aTargets = aoColDefs[i].aTargets; + if ( !$.isArray( aTargets ) ) + { + _fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) ); + } + + for ( j=0, jLen=aTargets.length ; j<jLen ; j++ ) + { + if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 ) + { + /* Add columns that we don't yet know about */ + while( oSettings.aoColumns.length <= aTargets[j] ) + { + _fnAddColumn( oSettings ); + } + + /* Integer, basic index */ + fn( aTargets[j], aoColDefs[i] ); + } + else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 ) + { + /* Negative integer, right to left column counting */ + fn( oSettings.aoColumns.length+aTargets[j], aoColDefs[i] ); + } + else if ( typeof aTargets[j] === 'string' ) + { + /* Class name matching on TH element */ + for ( k=0, kLen=oSettings.aoColumns.length ; k<kLen ; k++ ) + { + if ( aTargets[j] == "_all" || + $(oSettings.aoColumns[k].nTh).hasClass( aTargets[j] ) ) + { + fn( k, aoColDefs[i] ); + } + } + } + } + } + } + + // Statically defined columns array + if ( aoCols ) + { + for ( i=0, iLen=aoCols.length ; i<iLen ; i++ ) + { + fn( i, aoCols[i] ); + } + } + } + + /** + * Add a data array to the table, creating DOM node etc. This is the parallel to + * _fnGatherData, but for adding rows from a Javascript source, rather than a + * DOM source. + * @param {object} oSettings dataTables settings object + * @param {array} aData data array to be added + * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed + * @memberof DataTable#oApi + */ + function _fnAddData ( oSettings, aDataSupplied ) + { + var oCol; + + /* Take an independent copy of the data source so we can bash it about as we wish */ + var aDataIn = ($.isArray(aDataSupplied)) ? + aDataSupplied.slice() : + $.extend( true, {}, aDataSupplied ); + + /* Create the object for storing information about this new row */ + var iRow = oSettings.aoData.length; + var oData = $.extend( true, {}, DataTable.models.oRow ); + oData._aData = aDataIn; + oSettings.aoData.push( oData ); + + /* Create the cells */ + var nTd, sThisType; + for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + oCol = oSettings.aoColumns[i]; + + /* Use rendered data for filtering / sorting */ + if ( typeof oCol.fnRender === 'function' && oCol.bUseRendered && oCol.mData !== null ) + { + _fnSetCellData( oSettings, iRow, i, _fnRender(oSettings, iRow, i) ); + } + else + { + _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) ); + } + + /* See if we should auto-detect the column type */ + if ( oCol._bAutoType && oCol.sType != 'string' ) + { + /* Attempt to auto detect the type - same as _fnGatherData() */ + var sVarType = _fnGetCellData( oSettings, iRow, i, 'type' ); + if ( sVarType !== null && sVarType !== '' ) + { + sThisType = _fnDetectType( sVarType ); + if ( oCol.sType === null ) + { + oCol.sType = sThisType; + } + else if ( oCol.sType != sThisType && oCol.sType != "html" ) + { + /* String is always the 'fallback' option */ + oCol.sType = 'string'; + } + } + } + } + + /* Add to the display array */ + oSettings.aiDisplayMaster.push( iRow ); + + /* Create the DOM information */ + if ( !oSettings.oFeatures.bDeferRender ) + { + _fnCreateTr( oSettings, iRow ); + } + + return iRow; + } + + + /** + * Read in the data from the target table from the DOM + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnGatherData( oSettings ) + { + var iLoop, i, iLen, j, jLen, jInner, + nTds, nTrs, nTd, nTr, aLocalData, iThisIndex, + iRow, iRows, iColumn, iColumns, sNodeName, + oCol, oData; + + /* + * Process by row first + * Add the data object for the whole table - storing the tr node. Note - no point in getting + * DOM based data if we are going to go and replace it with Ajax source data. + */ + if ( oSettings.bDeferLoading || oSettings.sAjaxSource === null ) + { + nTr = oSettings.nTBody.firstChild; + while ( nTr ) + { + if ( nTr.nodeName.toUpperCase() == "TR" ) + { + iThisIndex = oSettings.aoData.length; + nTr._DT_RowIndex = iThisIndex; + oSettings.aoData.push( $.extend( true, {}, DataTable.models.oRow, { + "nTr": nTr + } ) ); + + oSettings.aiDisplayMaster.push( iThisIndex ); + nTd = nTr.firstChild; + jInner = 0; + while ( nTd ) + { + sNodeName = nTd.nodeName.toUpperCase(); + if ( sNodeName == "TD" || sNodeName == "TH" ) + { + _fnSetCellData( oSettings, iThisIndex, jInner, $.trim(nTd.innerHTML) ); + jInner++; + } + nTd = nTd.nextSibling; + } + } + nTr = nTr.nextSibling; + } + } + + /* Gather in the TD elements of the Table - note that this is basically the same as + * fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet + * setup! + */ + nTrs = _fnGetTrNodes( oSettings ); + nTds = []; + for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) + { + nTd = nTrs[i].firstChild; + while ( nTd ) + { + sNodeName = nTd.nodeName.toUpperCase(); + if ( sNodeName == "TD" || sNodeName == "TH" ) + { + nTds.push( nTd ); + } + nTd = nTd.nextSibling; + } + } + + /* Now process by column */ + for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ ) + { + oCol = oSettings.aoColumns[iColumn]; + + /* Get the title of the column - unless there is a user set one */ + if ( oCol.sTitle === null ) + { + oCol.sTitle = oCol.nTh.innerHTML; + } + + var + bAutoType = oCol._bAutoType, + bRender = typeof oCol.fnRender === 'function', + bClass = oCol.sClass !== null, + bVisible = oCol.bVisible, + nCell, sThisType, sRendered, sValType; + + /* A single loop to rule them all (and be more efficient) */ + if ( bAutoType || bRender || bClass || !bVisible ) + { + for ( iRow=0, iRows=oSettings.aoData.length ; iRow<iRows ; iRow++ ) + { + oData = oSettings.aoData[iRow]; + nCell = nTds[ (iRow*iColumns) + iColumn ]; + + /* Type detection */ + if ( bAutoType && oCol.sType != 'string' ) + { + sValType = _fnGetCellData( oSettings, iRow, iColumn, 'type' ); + if ( sValType !== '' ) + { + sThisType = _fnDetectType( sValType ); + if ( oCol.sType === null ) + { + oCol.sType = sThisType; + } + else if ( oCol.sType != sThisType && + oCol.sType != "html" ) + { + /* String is always the 'fallback' option */ + oCol.sType = 'string'; + } + } + } + + if ( oCol.mRender ) + { + // mRender has been defined, so we need to get the value and set it + nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' ); + } + else if ( oCol.mData !== iColumn ) + { + // If mData is not the same as the column number, then we need to + // get the dev set value. If it is the column, no point in wasting + // time setting the value that is already there! + nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' ); + } + + /* Rendering */ + if ( bRender ) + { + sRendered = _fnRender( oSettings, iRow, iColumn ); + nCell.innerHTML = sRendered; + if ( oCol.bUseRendered ) + { + /* Use the rendered data for filtering / sorting */ + _fnSetCellData( oSettings, iRow, iColumn, sRendered ); + } + } + + /* Classes */ + if ( bClass ) + { + nCell.className += ' '+oCol.sClass; + } + + /* Column visibility */ + if ( !bVisible ) + { + oData._anHidden[iColumn] = nCell; + nCell.parentNode.removeChild( nCell ); + } + else + { + oData._anHidden[iColumn] = null; + } + + if ( oCol.fnCreatedCell ) + { + oCol.fnCreatedCell.call( oSettings.oInstance, + nCell, _fnGetCellData( oSettings, iRow, iColumn, 'display' ), oData._aData, iRow, iColumn + ); + } + } + } + } + + /* Row created callbacks */ + if ( oSettings.aoRowCreatedCallback.length !== 0 ) + { + for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ ) + { + oData = oSettings.aoData[i]; + _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, i] ); + } + } + } + + + /** + * Take a TR element and convert it to an index in aoData + * @param {object} oSettings dataTables settings object + * @param {node} n the TR element to find + * @returns {int} index if the node is found, null if not + * @memberof DataTable#oApi + */ + function _fnNodeToDataIndex( oSettings, n ) + { + return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null; + } + + + /** + * Take a TD element and convert it into a column data index (not the visible index) + * @param {object} oSettings dataTables settings object + * @param {int} iRow The row number the TD/TH can be found in + * @param {node} n The TD/TH element to find + * @returns {int} index if the node is found, -1 if not + * @memberof DataTable#oApi + */ + function _fnNodeToColumnIndex( oSettings, iRow, n ) + { + var anCells = _fnGetTdNodes( oSettings, iRow ); + + for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + if ( anCells[i] === n ) + { + return i; + } + } + return -1; + } + + + /** + * Get an array of data for a given row from the internal data cache + * @param {object} oSettings dataTables settings object + * @param {int} iRow aoData row id + * @param {string} sSpecific data get type ('type' 'filter' 'sort') + * @param {array} aiColumns Array of column indexes to get data from + * @returns {array} Data array + * @memberof DataTable#oApi + */ + function _fnGetRowData( oSettings, iRow, sSpecific, aiColumns ) + { + var out = []; + for ( var i=0, iLen=aiColumns.length ; i<iLen ; i++ ) + { + out.push( _fnGetCellData( oSettings, iRow, aiColumns[i], sSpecific ) ); + } + return out; + } + + + /** + * Get the data for a given cell from the internal cache, taking into account data mapping + * @param {object} oSettings dataTables settings object + * @param {int} iRow aoData row id + * @param {int} iCol Column index + * @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort') + * @returns {*} Cell data + * @memberof DataTable#oApi + */ + function _fnGetCellData( oSettings, iRow, iCol, sSpecific ) + { + var sData; + var oCol = oSettings.aoColumns[iCol]; + var oData = oSettings.aoData[iRow]._aData; + + if ( (sData=oCol.fnGetData( oData, sSpecific )) === undefined ) + { + if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null ) + { + _fnLog( oSettings, 0, "Requested unknown parameter "+ + (typeof oCol.mData=='function' ? '{mData function}' : "'"+oCol.mData+"'")+ + " from the data source for row "+iRow ); + oSettings.iDrawError = oSettings.iDraw; + } + return oCol.sDefaultContent; + } + + /* When the data source is null, we can use default column data */ + if ( sData === null && oCol.sDefaultContent !== null ) + { + sData = oCol.sDefaultContent; + } + else if ( typeof sData === 'function' ) + { + /* If the data source is a function, then we run it and use the return */ + return sData(); + } + + if ( sSpecific == 'display' && sData === null ) + { + return ''; + } + return sData; + } + + + /** + * Set the value for a specific cell, into the internal data cache + * @param {object} oSettings dataTables settings object + * @param {int} iRow aoData row id + * @param {int} iCol Column index + * @param {*} val Value to set + * @memberof DataTable#oApi + */ + function _fnSetCellData( oSettings, iRow, iCol, val ) + { + var oCol = oSettings.aoColumns[iCol]; + var oData = oSettings.aoData[iRow]._aData; + + oCol.fnSetData( oData, val ); + } + + + // Private variable that is used to match array syntax in the data property object + var __reArray = /\[.*?\]$/; + + /** + * Return a function that can be used to get data from a source object, taking + * into account the ability to use nested objects as a source + * @param {string|int|function} mSource The data source for the object + * @returns {function} Data get function + * @memberof DataTable#oApi + */ + function _fnGetObjectDataFn( mSource ) + { + if ( mSource === null ) + { + /* Give an empty string for rendering / sorting etc */ + return function (data, type) { + return null; + }; + } + else if ( typeof mSource === 'function' ) + { + return function (data, type, extra) { + return mSource( data, type, extra ); + }; + } + else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) ) + { + /* If there is a . in the source string then the data source is in a + * nested object so we loop over the data for each level to get the next + * level down. On each loop we test for undefined, and if found immediately + * return. This allows entire objects to be missing and sDefaultContent to + * be used if defined, rather than throwing an error + */ + var fetchData = function (data, type, src) { + var a = src.split('.'); + var arrayNotation, out, innerSrc; + + if ( src !== "" ) + { + for ( var i=0, iLen=a.length ; i<iLen ; i++ ) + { + // Check if we are dealing with an array notation request + arrayNotation = a[i].match(__reArray); + + if ( arrayNotation ) { + a[i] = a[i].replace(__reArray, ''); + + // Condition allows simply [] to be passed in + if ( a[i] !== "" ) { + data = data[ a[i] ]; + } + out = []; + + // Get the remainder of the nested object to get + a.splice( 0, i+1 ); + innerSrc = a.join('.'); + + // Traverse each entry in the array getting the properties requested + for ( var j=0, jLen=data.length ; j<jLen ; j++ ) { + out.push( fetchData( data[j], type, innerSrc ) ); + } + + // If a string is given in between the array notation indicators, that + // is used to join the strings together, otherwise an array is returned + var join = arrayNotation[0].substring(1, arrayNotation[0].length-1); + data = (join==="") ? out : out.join(join); + + // The inner call to fetchData has already traversed through the remainder + // of the source requested, so we exit from the loop + break; + } + + if ( data === null || data[ a[i] ] === undefined ) + { + return undefined; + } + data = data[ a[i] ]; + } + } + + return data; + }; + + return function (data, type) { + return fetchData( data, type, mSource ); + }; + } + else + { + /* Array or flat object mapping */ + return function (data, type) { + return data[mSource]; + }; + } + } + + + /** + * Return a function that can be used to set data from a source object, taking + * into account the ability to use nested objects as a source + * @param {string|int|function} mSource The data source for the object + * @returns {function} Data set function + * @memberof DataTable#oApi + */ + function _fnSetObjectDataFn( mSource ) + { + if ( mSource === null ) + { + /* Nothing to do when the data source is null */ + return function (data, val) {}; + } + else if ( typeof mSource === 'function' ) + { + return function (data, val) { + mSource( data, 'set', val ); + }; + } + else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) ) + { + /* Like the get, we need to get data from a nested object */ + var setData = function (data, val, src) { + var a = src.split('.'), b; + var arrayNotation, o, innerSrc; + + for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) + { + // Check if we are dealing with an array notation request + arrayNotation = a[i].match(__reArray); + + if ( arrayNotation ) + { + a[i] = a[i].replace(__reArray, ''); + data[ a[i] ] = []; + + // Get the remainder of the nested object to set so we can recurse + b = a.slice(); + b.splice( 0, i+1 ); + innerSrc = b.join('.'); + + // Traverse each entry in the array setting the properties requested + for ( var j=0, jLen=val.length ; j<jLen ; j++ ) + { + o = {}; + setData( o, val[j], innerSrc ); + data[ a[i] ].push( o ); + } + + // The inner call to setData has already traversed through the remainder + // of the source and has set the data, thus we can exit here + return; + } + + // If the nested object doesn't currently exist - since we are + // trying to set the value - create it + if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) + { + data[ a[i] ] = {}; + } + data = data[ a[i] ]; + } + + // If array notation is used, we just want to strip it and use the property name + // and assign the value. If it isn't used, then we get the result we want anyway + data[ a[a.length-1].replace(__reArray, '') ] = val; + }; + + return function (data, val) { + return setData( data, val, mSource ); + }; + } + else + { + /* Array or flat object mapping */ + return function (data, val) { + data[mSource] = val; + }; + } + } + + + /** + * Return an array with the full table data + * @param {object} oSettings dataTables settings object + * @returns array {array} aData Master data array + * @memberof DataTable#oApi + */ + function _fnGetDataMaster ( oSettings ) + { + var aData = []; + var iLen = oSettings.aoData.length; + for ( var i=0 ; i<iLen; i++ ) + { + aData.push( oSettings.aoData[i]._aData ); + } + return aData; + } + + + /** + * Nuke the table + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnClearTable( oSettings ) + { + oSettings.aoData.splice( 0, oSettings.aoData.length ); + oSettings.aiDisplayMaster.splice( 0, oSettings.aiDisplayMaster.length ); + oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length ); + _fnCalculateEnd( oSettings ); + } + + + /** + * Take an array of integers (index array) and remove a target integer (value - not + * the key!) + * @param {array} a Index array to target + * @param {int} iTarget value to find + * @memberof DataTable#oApi + */ + function _fnDeleteIndex( a, iTarget ) + { + var iTargetIndex = -1; + + for ( var i=0, iLen=a.length ; i<iLen ; i++ ) + { + if ( a[i] == iTarget ) + { + iTargetIndex = i; + } + else if ( a[i] > iTarget ) + { + a[i]--; + } + } + + if ( iTargetIndex != -1 ) + { + a.splice( iTargetIndex, 1 ); + } + } + + + /** + * Call the developer defined fnRender function for a given cell (row/column) with + * the required parameters and return the result. + * @param {object} oSettings dataTables settings object + * @param {int} iRow aoData index for the row + * @param {int} iCol aoColumns index for the column + * @returns {*} Return of the developer's fnRender function + * @memberof DataTable#oApi + */ + function _fnRender( oSettings, iRow, iCol ) + { + var oCol = oSettings.aoColumns[iCol]; + + return oCol.fnRender( { + "iDataRow": iRow, + "iDataColumn": iCol, + "oSettings": oSettings, + "aData": oSettings.aoData[iRow]._aData, + "mDataProp": oCol.mData + }, _fnGetCellData(oSettings, iRow, iCol, 'display') ); + } + /** + * Create a new TR element (and it's TD children) for a row + * @param {object} oSettings dataTables settings object + * @param {int} iRow Row to consider + * @memberof DataTable#oApi + */ + function _fnCreateTr ( oSettings, iRow ) + { + var oData = oSettings.aoData[iRow]; + var nTd; + + if ( oData.nTr === null ) + { + oData.nTr = document.createElement('tr'); + + /* Use a private property on the node to allow reserve mapping from the node + * to the aoData array for fast look up + */ + oData.nTr._DT_RowIndex = iRow; + + /* Special parameters can be given by the data source to be used on the row */ + if ( oData._aData.DT_RowId ) + { + oData.nTr.id = oData._aData.DT_RowId; + } + + if ( oData._aData.DT_RowClass ) + { + oData.nTr.className = oData._aData.DT_RowClass; + } + + /* Process each column */ + for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + var oCol = oSettings.aoColumns[i]; + nTd = document.createElement( oCol.sCellType ); + + /* Render if needed - if bUseRendered is true then we already have the rendered + * value in the data source - so can just use that + */ + nTd.innerHTML = (typeof oCol.fnRender === 'function' && (!oCol.bUseRendered || oCol.mData === null)) ? + _fnRender( oSettings, iRow, i ) : + _fnGetCellData( oSettings, iRow, i, 'display' ); + + /* Add user defined class */ + if ( oCol.sClass !== null ) + { + nTd.className = oCol.sClass; + } + + if ( oCol.bVisible ) + { + oData.nTr.appendChild( nTd ); + oData._anHidden[i] = null; + } + else + { + oData._anHidden[i] = nTd; + } + + if ( oCol.fnCreatedCell ) + { + oCol.fnCreatedCell.call( oSettings.oInstance, + nTd, _fnGetCellData( oSettings, iRow, i, 'display' ), oData._aData, iRow, i + ); + } + } + + _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, iRow] ); + } + } + + + /** + * Create the HTML header for the table + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnBuildHead( oSettings ) + { + var i, nTh, iLen, j, jLen; + var iThs = $('th, td', oSettings.nTHead).length; + var iCorrector = 0; + var jqChildren; + + /* If there is a header in place - then use it - otherwise it's going to get nuked... */ + if ( iThs !== 0 ) + { + /* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */ + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + nTh = oSettings.aoColumns[i].nTh; + nTh.setAttribute('role', 'columnheader'); + if ( oSettings.aoColumns[i].bSortable ) + { + nTh.setAttribute('tabindex', oSettings.iTabIndex); + nTh.setAttribute('aria-controls', oSettings.sTableId); + } + + if ( oSettings.aoColumns[i].sClass !== null ) + { + $(nTh).addClass( oSettings.aoColumns[i].sClass ); + } + + /* Set the title of the column if it is user defined (not what was auto detected) */ + if ( oSettings.aoColumns[i].sTitle != nTh.innerHTML ) + { + nTh.innerHTML = oSettings.aoColumns[i].sTitle; + } + } + } + else + { + /* We don't have a header in the DOM - so we are going to have to create one */ + var nTr = document.createElement( "tr" ); + + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + nTh = oSettings.aoColumns[i].nTh; + nTh.innerHTML = oSettings.aoColumns[i].sTitle; + nTh.setAttribute('tabindex', '0'); + + if ( oSettings.aoColumns[i].sClass !== null ) + { + $(nTh).addClass( oSettings.aoColumns[i].sClass ); + } + + nTr.appendChild( nTh ); + } + $(oSettings.nTHead).html( '' )[0].appendChild( nTr ); + _fnDetectHeader( oSettings.aoHeader, oSettings.nTHead ); + } + + /* ARIA role for the rows */ + $(oSettings.nTHead).children('tr').attr('role', 'row'); + + /* Add the extra markup needed by jQuery UI's themes */ + if ( oSettings.bJUI ) + { + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + nTh = oSettings.aoColumns[i].nTh; + + var nDiv = document.createElement('div'); + nDiv.className = oSettings.oClasses.sSortJUIWrapper; + $(nTh).contents().appendTo(nDiv); + + var nSpan = document.createElement('span'); + nSpan.className = oSettings.oClasses.sSortIcon; + nDiv.appendChild( nSpan ); + nTh.appendChild( nDiv ); + } + } + + if ( oSettings.oFeatures.bSort ) + { + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + if ( oSettings.aoColumns[i].bSortable !== false ) + { + _fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i ); + } + else + { + $(oSettings.aoColumns[i].nTh).addClass( oSettings.oClasses.sSortableNone ); + } + } + } + + /* Deal with the footer - add classes if required */ + if ( oSettings.oClasses.sFooterTH !== "" ) + { + $(oSettings.nTFoot).children('tr').children('th').addClass( oSettings.oClasses.sFooterTH ); + } + + /* Cache the footer elements */ + if ( oSettings.nTFoot !== null ) + { + var anCells = _fnGetUniqueThs( oSettings, null, oSettings.aoFooter ); + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + if ( anCells[i] ) + { + oSettings.aoColumns[i].nTf = anCells[i]; + if ( oSettings.aoColumns[i].sClass ) + { + $(anCells[i]).addClass( oSettings.aoColumns[i].sClass ); + } + } + } + } + } + + + /** + * Draw the header (or footer) element based on the column visibility states. The + * methodology here is to use the layout array from _fnDetectHeader, modified for + * the instantaneous column visibility, to construct the new layout. The grid is + * traversed over cell at a time in a rows x columns grid fashion, although each + * cell insert can cover multiple elements in the grid - which is tracks using the + * aApplied array. Cell inserts in the grid will only occur where there isn't + * already a cell in that position. + * @param {object} oSettings dataTables settings object + * @param array {objects} aoSource Layout array from _fnDetectHeader + * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc, + * @memberof DataTable#oApi + */ + function _fnDrawHead( oSettings, aoSource, bIncludeHidden ) + { + var i, iLen, j, jLen, k, kLen, n, nLocalTr; + var aoLocal = []; + var aApplied = []; + var iColumns = oSettings.aoColumns.length; + var iRowspan, iColspan; + + if ( bIncludeHidden === undefined ) + { + bIncludeHidden = false; + } + + /* Make a copy of the master layout array, but without the visible columns in it */ + for ( i=0, iLen=aoSource.length ; i<iLen ; i++ ) + { + aoLocal[i] = aoSource[i].slice(); + aoLocal[i].nTr = aoSource[i].nTr; + + /* Remove any columns which are currently hidden */ + for ( j=iColumns-1 ; j>=0 ; j-- ) + { + if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden ) + { + aoLocal[i].splice( j, 1 ); + } + } + + /* Prep the applied array - it needs an element for each row */ + aApplied.push( [] ); + } + + for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ ) + { + nLocalTr = aoLocal[i].nTr; + + /* All cells are going to be replaced, so empty out the row */ + if ( nLocalTr ) + { + while( (n = nLocalTr.firstChild) ) + { + nLocalTr.removeChild( n ); + } + } + + for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ ) + { + iRowspan = 1; + iColspan = 1; + + /* Check to see if there is already a cell (row/colspan) covering our target + * insert point. If there is, then there is nothing to do. + */ + if ( aApplied[i][j] === undefined ) + { + nLocalTr.appendChild( aoLocal[i][j].cell ); + aApplied[i][j] = 1; + + /* Expand the cell to cover as many rows as needed */ + while ( aoLocal[i+iRowspan] !== undefined && + aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell ) + { + aApplied[i+iRowspan][j] = 1; + iRowspan++; + } + + /* Expand the cell to cover as many columns as needed */ + while ( aoLocal[i][j+iColspan] !== undefined && + aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell ) + { + /* Must update the applied array over the rows for the columns */ + for ( k=0 ; k<iRowspan ; k++ ) + { + aApplied[i+k][j+iColspan] = 1; + } + iColspan++; + } + + /* Do the actual expansion in the DOM */ + aoLocal[i][j].cell.rowSpan = iRowspan; + aoLocal[i][j].cell.colSpan = iColspan; + } + } + } + } + + + /** + * Insert the required TR nodes into the table for display + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnDraw( oSettings ) + { + /* Provide a pre-callback function which can be used to cancel the draw is false is returned */ + var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] ); + if ( $.inArray( false, aPreDraw ) !== -1 ) + { + _fnProcessingDisplay( oSettings, false ); + return; + } + + var i, iLen, n; + var anRows = []; + var iRowCount = 0; + var iStripes = oSettings.asStripeClasses.length; + var iOpenRows = oSettings.aoOpenRows.length; + + oSettings.bDrawing = true; + + /* Check and see if we have an initial draw position from state saving */ + if ( oSettings.iInitDisplayStart !== undefined && oSettings.iInitDisplayStart != -1 ) + { + if ( oSettings.oFeatures.bServerSide ) + { + oSettings._iDisplayStart = oSettings.iInitDisplayStart; + } + else + { + oSettings._iDisplayStart = (oSettings.iInitDisplayStart >= oSettings.fnRecordsDisplay()) ? + 0 : oSettings.iInitDisplayStart; + } + oSettings.iInitDisplayStart = -1; + _fnCalculateEnd( oSettings ); + } + + /* Server-side processing draw intercept */ + if ( oSettings.bDeferLoading ) + { + oSettings.bDeferLoading = false; + oSettings.iDraw++; + } + else if ( !oSettings.oFeatures.bServerSide ) + { + oSettings.iDraw++; + } + else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) ) + { + return; + } + + if ( oSettings.aiDisplay.length !== 0 ) + { + var iStart = oSettings._iDisplayStart; + var iEnd = oSettings._iDisplayEnd; + + if ( oSettings.oFeatures.bServerSide ) + { + iStart = 0; + iEnd = oSettings.aoData.length; + } + + for ( var j=iStart ; j<iEnd ; j++ ) + { + var aoData = oSettings.aoData[ oSettings.aiDisplay[j] ]; + if ( aoData.nTr === null ) + { + _fnCreateTr( oSettings, oSettings.aiDisplay[j] ); + } + + var nRow = aoData.nTr; + + /* Remove the old striping classes and then add the new one */ + if ( iStripes !== 0 ) + { + var sStripe = oSettings.asStripeClasses[ iRowCount % iStripes ]; + if ( aoData._sRowStripe != sStripe ) + { + $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe ); + aoData._sRowStripe = sStripe; + } + } + + /* Row callback functions - might want to manipulate the row */ + _fnCallbackFire( oSettings, 'aoRowCallback', null, + [nRow, oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j] ); + + anRows.push( nRow ); + iRowCount++; + + /* If there is an open row - and it is attached to this parent - attach it on redraw */ + if ( iOpenRows !== 0 ) + { + for ( var k=0 ; k<iOpenRows ; k++ ) + { + if ( nRow == oSettings.aoOpenRows[k].nParent ) + { + anRows.push( oSettings.aoOpenRows[k].nTr ); + break; + } + } + } + } + } + else + { + /* Table is empty - create a row with an empty message in it */ + anRows[ 0 ] = document.createElement( 'tr' ); + + if ( oSettings.asStripeClasses[0] ) + { + anRows[ 0 ].className = oSettings.asStripeClasses[0]; + } + + var oLang = oSettings.oLanguage; + var sZero = oLang.sZeroRecords; + if ( oSettings.iDraw == 1 && oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide ) + { + sZero = oLang.sLoadingRecords; + } + else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 ) + { + sZero = oLang.sEmptyTable; + } + + var nTd = document.createElement( 'td' ); + nTd.setAttribute( 'valign', "top" ); + nTd.colSpan = _fnVisbleColumns( oSettings ); + nTd.className = oSettings.oClasses.sRowEmpty; + nTd.innerHTML = _fnInfoMacros( oSettings, sZero ); + + anRows[ iRowCount ].appendChild( nTd ); + } + + /* Header and footer callbacks */ + _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0], + _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] ); + + _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0], + _fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] ); + + /* + * Need to remove any old row from the display - note we can't just empty the tbody using + * $().html('') since this will unbind the jQuery event handlers (even although the node + * still exists!) - equally we can't use innerHTML, since IE throws an exception. + */ + var + nAddFrag = document.createDocumentFragment(), + nRemoveFrag = document.createDocumentFragment(), + nBodyPar, nTrs; + + if ( oSettings.nTBody ) + { + nBodyPar = oSettings.nTBody.parentNode; + nRemoveFrag.appendChild( oSettings.nTBody ); + + /* When doing infinite scrolling, only remove child rows when sorting, filtering or start + * up. When not infinite scroll, always do it. + */ + if ( !oSettings.oScroll.bInfinite || !oSettings._bInitComplete || + oSettings.bSorted || oSettings.bFiltered ) + { + while( (n = oSettings.nTBody.firstChild) ) + { + oSettings.nTBody.removeChild( n ); + } + } + + /* Put the draw table into the dom */ + for ( i=0, iLen=anRows.length ; i<iLen ; i++ ) + { + nAddFrag.appendChild( anRows[i] ); + } + + oSettings.nTBody.appendChild( nAddFrag ); + if ( nBodyPar !== null ) + { + nBodyPar.appendChild( oSettings.nTBody ); + } + } + + /* Call all required callback functions for the end of a draw */ + _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] ); + + /* Draw is complete, sorting and filtering must be as well */ + oSettings.bSorted = false; + oSettings.bFiltered = false; + oSettings.bDrawing = false; + + if ( oSettings.oFeatures.bServerSide ) + { + _fnProcessingDisplay( oSettings, false ); + if ( !oSettings._bInitComplete ) + { + _fnInitComplete( oSettings ); + } + } + } + + + /** + * Redraw the table - taking account of the various features which are enabled + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnReDraw( oSettings ) + { + if ( oSettings.oFeatures.bSort ) + { + /* Sorting will refilter and draw for us */ + _fnSort( oSettings, oSettings.oPreviousSearch ); + } + else if ( oSettings.oFeatures.bFilter ) + { + /* Filtering will redraw for us */ + _fnFilterComplete( oSettings, oSettings.oPreviousSearch ); + } + else + { + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + } + + + /** + * Add the options to the page HTML for the table + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnAddOptionsHtml ( oSettings ) + { + /* + * Create a temporary, empty, div which we can later on replace with what we have generated + * we do it this way to rendering the 'options' html offline - speed :-) + */ + var nHolding = $('<div></div>')[0]; + oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable ); + + /* + * All DataTables are wrapped in a div + */ + oSettings.nTableWrapper = $('<div id="'+oSettings.sTableId+'_wrapper" class="'+oSettings.oClasses.sWrapper+'" role="grid"></div>')[0]; + oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling; + + /* Track where we want to insert the option */ + var nInsertNode = oSettings.nTableWrapper; + + /* Loop over the user set positioning and place the elements as needed */ + var aDom = oSettings.sDom.split(''); + var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j; + for ( var i=0 ; i<aDom.length ; i++ ) + { + iPushFeature = 0; + cOption = aDom[i]; + + if ( cOption == '<' ) + { + /* New container div */ + nNewNode = $('<div></div>')[0]; + + /* Check to see if we should append an id and/or a class name to the container */ + cNext = aDom[i+1]; + if ( cNext == "'" || cNext == '"' ) + { + sAttr = ""; + j = 2; + while ( aDom[i+j] != cNext ) + { + sAttr += aDom[i+j]; + j++; + } + + /* Replace jQuery UI constants */ + if ( sAttr == "H" ) + { + sAttr = oSettings.oClasses.sJUIHeader; + } + else if ( sAttr == "F" ) + { + sAttr = oSettings.oClasses.sJUIFooter; + } + + /* The attribute can be in the format of "#id.class", "#id" or "class" This logic + * breaks the string into parts and applies them as needed + */ + if ( sAttr.indexOf('.') != -1 ) + { + var aSplit = sAttr.split('.'); + nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1); + nNewNode.className = aSplit[1]; + } + else if ( sAttr.charAt(0) == "#" ) + { + nNewNode.id = sAttr.substr(1, sAttr.length-1); + } + else + { + nNewNode.className = sAttr; + } + + i += j; /* Move along the position array */ + } + + nInsertNode.appendChild( nNewNode ); + nInsertNode = nNewNode; + } + else if ( cOption == '>' ) + { + /* End container div */ + nInsertNode = nInsertNode.parentNode; + } + else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange ) + { + /* Length */ + nTmp = _fnFeatureHtmlLength( oSettings ); + iPushFeature = 1; + } + else if ( cOption == 'f' && oSettings.oFeatures.bFilter ) + { + /* Filter */ + nTmp = _fnFeatureHtmlFilter( oSettings ); + iPushFeature = 1; + } + else if ( cOption == 'r' && oSettings.oFeatures.bProcessing ) + { + /* pRocessing */ + nTmp = _fnFeatureHtmlProcessing( oSettings ); + iPushFeature = 1; + } + else if ( cOption == 't' ) + { + /* Table */ + nTmp = _fnFeatureHtmlTable( oSettings ); + iPushFeature = 1; + } + else if ( cOption == 'i' && oSettings.oFeatures.bInfo ) + { + /* Info */ + nTmp = _fnFeatureHtmlInfo( oSettings ); + iPushFeature = 1; + } + else if ( cOption == 'p' && oSettings.oFeatures.bPaginate ) + { + /* Pagination */ + nTmp = _fnFeatureHtmlPaginate( oSettings ); + iPushFeature = 1; + } + else if ( DataTable.ext.aoFeatures.length !== 0 ) + { + /* Plug-in features */ + var aoFeatures = DataTable.ext.aoFeatures; + for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ ) + { + if ( cOption == aoFeatures[k].cFeature ) + { + nTmp = aoFeatures[k].fnInit( oSettings ); + if ( nTmp ) + { + iPushFeature = 1; + } + break; + } + } + } + + /* Add to the 2D features array */ + if ( iPushFeature == 1 && nTmp !== null ) + { + if ( typeof oSettings.aanFeatures[cOption] !== 'object' ) + { + oSettings.aanFeatures[cOption] = []; + } + oSettings.aanFeatures[cOption].push( nTmp ); + nInsertNode.appendChild( nTmp ); + } + } + + /* Built our DOM structure - replace the holding div with what we want */ + nHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding ); + } + + + /** + * Use the DOM source to create up an array of header cells. The idea here is to + * create a layout grid (array) of rows x columns, which contains a reference + * to the cell that that point in the grid (regardless of col/rowspan), such that + * any column / row could be removed and the new grid constructed + * @param array {object} aLayout Array to store the calculated layout in + * @param {node} nThead The header/footer element for the table + * @memberof DataTable#oApi + */ + function _fnDetectHeader ( aLayout, nThead ) + { + var nTrs = $(nThead).children('tr'); + var nTr, nCell; + var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan; + var bUnique; + var fnShiftCol = function ( a, i, j ) { + var k = a[i]; + while ( k[j] ) { + j++; + } + return j; + }; + + aLayout.splice( 0, aLayout.length ); + + /* We know how many rows there are in the layout - so prep it */ + for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) + { + aLayout.push( [] ); + } + + /* Calculate a layout array */ + for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) + { + nTr = nTrs[i]; + iColumn = 0; + + /* For every cell in the row... */ + nCell = nTr.firstChild; + while ( nCell ) { + if ( nCell.nodeName.toUpperCase() == "TD" || + nCell.nodeName.toUpperCase() == "TH" ) + { + /* Get the col and rowspan attributes from the DOM and sanitise them */ + iColspan = nCell.getAttribute('colspan') * 1; + iRowspan = nCell.getAttribute('rowspan') * 1; + iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan; + iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan; + + /* There might be colspan cells already in this row, so shift our target + * accordingly + */ + iColShifted = fnShiftCol( aLayout, i, iColumn ); + + /* Cache calculation for unique columns */ + bUnique = iColspan === 1 ? true : false; + + /* If there is col / rowspan, copy the information into the layout grid */ + for ( l=0 ; l<iColspan ; l++ ) + { + for ( k=0 ; k<iRowspan ; k++ ) + { + aLayout[i+k][iColShifted+l] = { + "cell": nCell, + "unique": bUnique + }; + aLayout[i+k].nTr = nTr; + } + } + } + nCell = nCell.nextSibling; + } + } + } + + + /** + * Get an array of unique th elements, one for each column + * @param {object} oSettings dataTables settings object + * @param {node} nHeader automatically detect the layout from this node - optional + * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional + * @returns array {node} aReturn list of unique th's + * @memberof DataTable#oApi + */ + function _fnGetUniqueThs ( oSettings, nHeader, aLayout ) + { + var aReturn = []; + if ( !aLayout ) + { + aLayout = oSettings.aoHeader; + if ( nHeader ) + { + aLayout = []; + _fnDetectHeader( aLayout, nHeader ); + } + } + + for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ ) + { + for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ ) + { + if ( aLayout[i][j].unique && + (!aReturn[j] || !oSettings.bSortCellsTop) ) + { + aReturn[j] = aLayout[i][j].cell; + } + } + } + + return aReturn; + } + + + + /** + * Update the table using an Ajax call + * @param {object} oSettings dataTables settings object + * @returns {boolean} Block the table drawing or not + * @memberof DataTable#oApi + */ + function _fnAjaxUpdate( oSettings ) + { + if ( oSettings.bAjaxDataGet ) + { + oSettings.iDraw++; + _fnProcessingDisplay( oSettings, true ); + var iColumns = oSettings.aoColumns.length; + var aoData = _fnAjaxParameters( oSettings ); + _fnServerParams( oSettings, aoData ); + + oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData, + function(json) { + _fnAjaxUpdateDraw( oSettings, json ); + }, oSettings ); + return false; + } + else + { + return true; + } + } + + + /** + * Build up the parameters in an object needed for a server-side processing request + * @param {object} oSettings dataTables settings object + * @returns {bool} block the table drawing or not + * @memberof DataTable#oApi + */ + function _fnAjaxParameters( oSettings ) + { + var iColumns = oSettings.aoColumns.length; + var aoData = [], mDataProp, aaSort, aDataSort; + var i, j; + + aoData.push( { "name": "sEcho", "value": oSettings.iDraw } ); + aoData.push( { "name": "iColumns", "value": iColumns } ); + aoData.push( { "name": "sColumns", "value": _fnColumnOrdering(oSettings) } ); + aoData.push( { "name": "iDisplayStart", "value": oSettings._iDisplayStart } ); + aoData.push( { "name": "iDisplayLength", "value": oSettings.oFeatures.bPaginate !== false ? + oSettings._iDisplayLength : -1 } ); + + for ( i=0 ; i<iColumns ; i++ ) + { + mDataProp = oSettings.aoColumns[i].mData; + aoData.push( { "name": "mDataProp_"+i, "value": typeof(mDataProp)==="function" ? 'function' : mDataProp } ); + } + + /* Filtering */ + if ( oSettings.oFeatures.bFilter !== false ) + { + aoData.push( { "name": "sSearch", "value": oSettings.oPreviousSearch.sSearch } ); + aoData.push( { "name": "bRegex", "value": oSettings.oPreviousSearch.bRegex } ); + for ( i=0 ; i<iColumns ; i++ ) + { + aoData.push( { "name": "sSearch_"+i, "value": oSettings.aoPreSearchCols[i].sSearch } ); + aoData.push( { "name": "bRegex_"+i, "value": oSettings.aoPreSearchCols[i].bRegex } ); + aoData.push( { "name": "bSearchable_"+i, "value": oSettings.aoColumns[i].bSearchable } ); + } + } + + /* Sorting */ + if ( oSettings.oFeatures.bSort !== false ) + { + var iCounter = 0; + + aaSort = ( oSettings.aaSortingFixed !== null ) ? + oSettings.aaSortingFixed.concat( oSettings.aaSorting ) : + oSettings.aaSorting.slice(); + + for ( i=0 ; i<aaSort.length ; i++ ) + { + aDataSort = oSettings.aoColumns[ aaSort[i][0] ].aDataSort; + + for ( j=0 ; j<aDataSort.length ; j++ ) + { + aoData.push( { "name": "iSortCol_"+iCounter, "value": aDataSort[j] } ); + aoData.push( { "name": "sSortDir_"+iCounter, "value": aaSort[i][1] } ); + iCounter++; + } + } + aoData.push( { "name": "iSortingCols", "value": iCounter } ); + + for ( i=0 ; i<iColumns ; i++ ) + { + aoData.push( { "name": "bSortable_"+i, "value": oSettings.aoColumns[i].bSortable } ); + } + } + + return aoData; + } + + + /** + * Add Ajax parameters from plug-ins + * @param {object} oSettings dataTables settings object + * @param array {objects} aoData name/value pairs to send to the server + * @memberof DataTable#oApi + */ + function _fnServerParams( oSettings, aoData ) + { + _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [aoData] ); + } + + + /** + * Data the data from the server (nuking the old) and redraw the table + * @param {object} oSettings dataTables settings object + * @param {object} json json data return from the server. + * @param {string} json.sEcho Tracking flag for DataTables to match requests + * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering + * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering + * @param {array} json.aaData The data to display on this page + * @param {string} [json.sColumns] Column ordering (sName, comma separated) + * @memberof DataTable#oApi + */ + function _fnAjaxUpdateDraw ( oSettings, json ) + { + if ( json.sEcho !== undefined ) + { + /* Protect against old returns over-writing a new one. Possible when you get + * very fast interaction, and later queries are completed much faster + */ + if ( json.sEcho*1 < oSettings.iDraw ) + { + return; + } + else + { + oSettings.iDraw = json.sEcho * 1; + } + } + + if ( !oSettings.oScroll.bInfinite || + (oSettings.oScroll.bInfinite && (oSettings.bSorted || oSettings.bFiltered)) ) + { + _fnClearTable( oSettings ); + } + oSettings._iRecordsTotal = parseInt(json.iTotalRecords, 10); + oSettings._iRecordsDisplay = parseInt(json.iTotalDisplayRecords, 10); + + /* Determine if reordering is required */ + var sOrdering = _fnColumnOrdering(oSettings); + var bReOrder = (json.sColumns !== undefined && sOrdering !== "" && json.sColumns != sOrdering ); + var aiIndex; + if ( bReOrder ) + { + aiIndex = _fnReOrderIndex( oSettings, json.sColumns ); + } + + var aData = _fnGetObjectDataFn( oSettings.sAjaxDataProp )( json ); + for ( var i=0, iLen=aData.length ; i<iLen ; i++ ) + { + if ( bReOrder ) + { + /* If we need to re-order, then create a new array with the correct order and add it */ + var aDataSorted = []; + for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ ) + { + aDataSorted.push( aData[i][ aiIndex[j] ] ); + } + _fnAddData( oSettings, aDataSorted ); + } + else + { + /* No re-order required, sever got it "right" - just straight add */ + _fnAddData( oSettings, aData[i] ); + } + } + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + + oSettings.bAjaxDataGet = false; + _fnDraw( oSettings ); + oSettings.bAjaxDataGet = true; + _fnProcessingDisplay( oSettings, false ); + } + + + + /** + * Generate the node required for filtering text + * @returns {node} Filter control element + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlFilter ( oSettings ) + { + var oPreviousSearch = oSettings.oPreviousSearch; + + var sSearchStr = oSettings.oLanguage.sSearch; + sSearchStr = (sSearchStr.indexOf('_INPUT_') !== -1) ? + sSearchStr.replace('_INPUT_', '<input type="text" />') : + sSearchStr==="" ? '<input type="text" />' : sSearchStr+' <input type="text" />'; + + var nFilter = document.createElement( 'div' ); + nFilter.className = oSettings.oClasses.sFilter; + nFilter.innerHTML = '<label>'+sSearchStr+'</label>'; + if ( !oSettings.aanFeatures.f ) + { + nFilter.id = oSettings.sTableId+'_filter'; + } + + var jqFilter = $('input[type="text"]', nFilter); + + // Store a reference to the input element, so other input elements could be + // added to the filter wrapper if needed (submit button for example) + nFilter._DT_Input = jqFilter[0]; + + jqFilter.val( oPreviousSearch.sSearch.replace('"','&quot;') ); + jqFilter.bind( 'keyup.DT', function(e) { + /* Update all other filter input elements for the new display */ + var n = oSettings.aanFeatures.f; + var val = this.value==="" ? "" : this.value; // mental IE8 fix :-( + + for ( var i=0, iLen=n.length ; i<iLen ; i++ ) + { + if ( n[i] != $(this).parents('div.dataTables_filter')[0] ) + { + $(n[i]._DT_Input).val( val ); + } + } + + /* Now do the filter */ + if ( val != oPreviousSearch.sSearch ) + { + _fnFilterComplete( oSettings, { + "sSearch": val, + "bRegex": oPreviousSearch.bRegex, + "bSmart": oPreviousSearch.bSmart , + "bCaseInsensitive": oPreviousSearch.bCaseInsensitive + } ); + } + } ); + + jqFilter + .attr('aria-controls', oSettings.sTableId) + .bind( 'keypress.DT', function(e) { + /* Prevent form submission */ + if ( e.keyCode == 13 ) + { + return false; + } + } + ); + + return nFilter; + } + + + /** + * Filter the table using both the global filter and column based filtering + * @param {object} oSettings dataTables settings object + * @param {object} oSearch search information + * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0) + * @memberof DataTable#oApi + */ + function _fnFilterComplete ( oSettings, oInput, iForce ) + { + var oPrevSearch = oSettings.oPreviousSearch; + var aoPrevSearch = oSettings.aoPreSearchCols; + var fnSaveFilter = function ( oFilter ) { + /* Save the filtering values */ + oPrevSearch.sSearch = oFilter.sSearch; + oPrevSearch.bRegex = oFilter.bRegex; + oPrevSearch.bSmart = oFilter.bSmart; + oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive; + }; + + /* In server-side processing all filtering is done by the server, so no point hanging around here */ + if ( !oSettings.oFeatures.bServerSide ) + { + /* Global filter */ + _fnFilter( oSettings, oInput.sSearch, iForce, oInput.bRegex, oInput.bSmart, oInput.bCaseInsensitive ); + fnSaveFilter( oInput ); + + /* Now do the individual column filter */ + for ( var i=0 ; i<oSettings.aoPreSearchCols.length ; i++ ) + { + _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, aoPrevSearch[i].bRegex, + aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive ); + } + + /* Custom filtering */ + _fnFilterCustom( oSettings ); + } + else + { + fnSaveFilter( oInput ); + } + + /* Tell the draw function we have been filtering */ + oSettings.bFiltered = true; + $(oSettings.oInstance).trigger('filter', oSettings); + + /* Redraw the table */ + oSettings._iDisplayStart = 0; + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + + /* Rebuild search array 'offline' */ + _fnBuildSearchArray( oSettings, 0 ); + } + + + /** + * Apply custom filtering functions + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnFilterCustom( oSettings ) + { + var afnFilters = DataTable.ext.afnFiltering; + var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' ); + + for ( var i=0, iLen=afnFilters.length ; i<iLen ; i++ ) + { + var iCorrector = 0; + for ( var j=0, jLen=oSettings.aiDisplay.length ; j<jLen ; j++ ) + { + var iDisIndex = oSettings.aiDisplay[j-iCorrector]; + var bTest = afnFilters[i]( + oSettings, + _fnGetRowData( oSettings, iDisIndex, 'filter', aiFilterColumns ), + iDisIndex + ); + + /* Check if we should use this row based on the filtering function */ + if ( !bTest ) + { + oSettings.aiDisplay.splice( j-iCorrector, 1 ); + iCorrector++; + } + } + } + } + + + /** + * Filter the table on a per-column basis + * @param {object} oSettings dataTables settings object + * @param {string} sInput string to filter on + * @param {int} iColumn column to filter + * @param {bool} bRegex treat search string as a regular expression or not + * @param {bool} bSmart use smart filtering or not + * @param {bool} bCaseInsensitive Do case insenstive matching or not + * @memberof DataTable#oApi + */ + function _fnFilterColumn ( oSettings, sInput, iColumn, bRegex, bSmart, bCaseInsensitive ) + { + if ( sInput === "" ) + { + return; + } + + var iIndexCorrector = 0; + var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive ); + + for ( var i=oSettings.aiDisplay.length-1 ; i>=0 ; i-- ) + { + var sData = _fnDataToSearch( _fnGetCellData( oSettings, oSettings.aiDisplay[i], iColumn, 'filter' ), + oSettings.aoColumns[iColumn].sType ); + if ( ! rpSearch.test( sData ) ) + { + oSettings.aiDisplay.splice( i, 1 ); + iIndexCorrector++; + } + } + } + + + /** + * Filter the data table based on user input and draw the table + * @param {object} oSettings dataTables settings object + * @param {string} sInput string to filter on + * @param {int} iForce optional - force a research of the master array (1) or not (undefined or 0) + * @param {bool} bRegex treat as a regular expression or not + * @param {bool} bSmart perform smart filtering or not + * @param {bool} bCaseInsensitive Do case insenstive matching or not + * @memberof DataTable#oApi + */ + function _fnFilter( oSettings, sInput, iForce, bRegex, bSmart, bCaseInsensitive ) + { + var i; + var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive ); + var oPrevSearch = oSettings.oPreviousSearch; + + /* Check if we are forcing or not - optional parameter */ + if ( !iForce ) + { + iForce = 0; + } + + /* Need to take account of custom filtering functions - always filter */ + if ( DataTable.ext.afnFiltering.length !== 0 ) + { + iForce = 1; + } + + /* + * If the input is blank - we want the full data set + */ + if ( sInput.length <= 0 ) + { + oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length); + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + } + else + { + /* + * We are starting a new search or the new search string is smaller + * then the old one (i.e. delete). Search from the master array + */ + if ( oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length || + oPrevSearch.sSearch.length > sInput.length || iForce == 1 || + sInput.indexOf(oPrevSearch.sSearch) !== 0 ) + { + /* Nuke the old display array - we are going to rebuild it */ + oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length); + + /* Force a rebuild of the search array */ + _fnBuildSearchArray( oSettings, 1 ); + + /* Search through all records to populate the search array + * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1 + * mapping + */ + for ( i=0 ; i<oSettings.aiDisplayMaster.length ; i++ ) + { + if ( rpSearch.test(oSettings.asDataSearch[i]) ) + { + oSettings.aiDisplay.push( oSettings.aiDisplayMaster[i] ); + } + } + } + else + { + /* Using old search array - refine it - do it this way for speed + * Don't have to search the whole master array again + */ + var iIndexCorrector = 0; + + /* Search the current results */ + for ( i=0 ; i<oSettings.asDataSearch.length ; i++ ) + { + if ( ! rpSearch.test(oSettings.asDataSearch[i]) ) + { + oSettings.aiDisplay.splice( i-iIndexCorrector, 1 ); + iIndexCorrector++; + } + } + } + } + } + + + /** + * Create an array which can be quickly search through + * @param {object} oSettings dataTables settings object + * @param {int} iMaster use the master data array - optional + * @memberof DataTable#oApi + */ + function _fnBuildSearchArray ( oSettings, iMaster ) + { + if ( !oSettings.oFeatures.bServerSide ) + { + /* Clear out the old data */ + oSettings.asDataSearch = []; + + var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' ); + var aiIndex = (iMaster===1) ? + oSettings.aiDisplayMaster : + oSettings.aiDisplay; + + for ( var i=0, iLen=aiIndex.length ; i<iLen ; i++ ) + { + oSettings.asDataSearch[i] = _fnBuildSearchRow( + oSettings, + _fnGetRowData( oSettings, aiIndex[i], 'filter', aiFilterColumns ) + ); + } + } + } + + + /** + * Create a searchable string from a single data row + * @param {object} oSettings dataTables settings object + * @param {array} aData Row data array to use for the data to search + * @memberof DataTable#oApi + */ + function _fnBuildSearchRow( oSettings, aData ) + { + var sSearch = aData.join(' '); + + /* If it looks like there is an HTML entity in the string, attempt to decode it */ + if ( sSearch.indexOf('&') !== -1 ) + { + sSearch = $('<div>').html(sSearch).text(); + } + + // Strip newline characters + return sSearch.replace( /[\n\r]/g, " " ); + } + + /** + * Build a regular expression object suitable for searching a table + * @param {string} sSearch string to search for + * @param {bool} bRegex treat as a regular expression or not + * @param {bool} bSmart perform smart filtering or not + * @param {bool} bCaseInsensitive Do case insensitive matching or not + * @returns {RegExp} constructed object + * @memberof DataTable#oApi + */ + function _fnFilterCreateSearch( sSearch, bRegex, bSmart, bCaseInsensitive ) + { + var asSearch, sRegExpString; + + if ( bSmart ) + { + /* Generate the regular expression to use. Something along the lines of: + * ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$ + */ + asSearch = bRegex ? sSearch.split( ' ' ) : _fnEscapeRegex( sSearch ).split( ' ' ); + sRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$'; + return new RegExp( sRegExpString, bCaseInsensitive ? "i" : "" ); + } + else + { + sSearch = bRegex ? sSearch : _fnEscapeRegex( sSearch ); + return new RegExp( sSearch, bCaseInsensitive ? "i" : "" ); + } + } + + + /** + * Convert raw data into something that the user can search on + * @param {string} sData data to be modified + * @param {string} sType data type + * @returns {string} search string + * @memberof DataTable#oApi + */ + function _fnDataToSearch ( sData, sType ) + { + if ( typeof DataTable.ext.ofnSearch[sType] === "function" ) + { + return DataTable.ext.ofnSearch[sType]( sData ); + } + else if ( sData === null ) + { + return ''; + } + else if ( sType == "html" ) + { + return sData.replace(/[\r\n]/g," ").replace( /<.*?>/g, "" ); + } + else if ( typeof sData === "string" ) + { + return sData.replace(/[\r\n]/g," "); + } + return sData; + } + + + /** + * scape a string such that it can be used in a regular expression + * @param {string} sVal string to escape + * @returns {string} escaped string + * @memberof DataTable#oApi + */ + function _fnEscapeRegex ( sVal ) + { + var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ]; + var reReplace = new RegExp( '(\\' + acEscape.join('|\\') + ')', 'g' ); + return sVal.replace(reReplace, '\\$1'); + } + + + /** + * Generate the node required for the info display + * @param {object} oSettings dataTables settings object + * @returns {node} Information element + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlInfo ( oSettings ) + { + var nInfo = document.createElement( 'div' ); + nInfo.className = oSettings.oClasses.sInfo; + + /* Actions that are to be taken once only for this feature */ + if ( !oSettings.aanFeatures.i ) + { + /* Add draw callback */ + oSettings.aoDrawCallback.push( { + "fn": _fnUpdateInfo, + "sName": "information" + } ); + + /* Add id */ + nInfo.id = oSettings.sTableId+'_info'; + } + oSettings.nTable.setAttribute( 'aria-describedby', oSettings.sTableId+'_info' ); + + return nInfo; + } + + + /** + * Update the information elements in the display + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnUpdateInfo ( oSettings ) + { + /* Show information about the table */ + if ( !oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0 ) + { + return; + } + + var + oLang = oSettings.oLanguage, + iStart = oSettings._iDisplayStart+1, + iEnd = oSettings.fnDisplayEnd(), + iMax = oSettings.fnRecordsTotal(), + iTotal = oSettings.fnRecordsDisplay(), + sOut; + + if ( iTotal === 0 ) + { + /* Empty record set */ + sOut = oLang.sInfoEmpty; + } + else { + /* Normal record set */ + sOut = oLang.sInfo; + } + + if ( iTotal != iMax ) + { + /* Record set after filtering */ + sOut += ' ' + oLang.sInfoFiltered; + } + + // Convert the macros + sOut += oLang.sInfoPostFix; + sOut = _fnInfoMacros( oSettings, sOut ); + + if ( oLang.fnInfoCallback !== null ) + { + sOut = oLang.fnInfoCallback.call( oSettings.oInstance, + oSettings, iStart, iEnd, iMax, iTotal, sOut ); + } + + var n = oSettings.aanFeatures.i; + for ( var i=0, iLen=n.length ; i<iLen ; i++ ) + { + $(n[i]).html( sOut ); + } + } + + + function _fnInfoMacros ( oSettings, str ) + { + var + iStart = oSettings._iDisplayStart+1, + sStart = oSettings.fnFormatNumber( iStart ), + iEnd = oSettings.fnDisplayEnd(), + sEnd = oSettings.fnFormatNumber( iEnd ), + iTotal = oSettings.fnRecordsDisplay(), + sTotal = oSettings.fnFormatNumber( iTotal ), + iMax = oSettings.fnRecordsTotal(), + sMax = oSettings.fnFormatNumber( iMax ); + + // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only + // internally + if ( oSettings.oScroll.bInfinite ) + { + sStart = oSettings.fnFormatNumber( 1 ); + } + + return str. + replace(/_START_/g, sStart). + replace(/_END_/g, sEnd). + replace(/_TOTAL_/g, sTotal). + replace(/_MAX_/g, sMax); + } + + + + /** + * Draw the table for the first time, adding all required features + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnInitialise ( oSettings ) + { + var i, iLen, iAjaxStart=oSettings.iInitDisplayStart; + + /* Ensure that the table data is fully initialised */ + if ( oSettings.bInitialised === false ) + { + setTimeout( function(){ _fnInitialise( oSettings ); }, 200 ); + return; + } + + /* Show the display HTML options */ + _fnAddOptionsHtml( oSettings ); + + /* Build and draw the header / footer for the table */ + _fnBuildHead( oSettings ); + _fnDrawHead( oSettings, oSettings.aoHeader ); + if ( oSettings.nTFoot ) + { + _fnDrawHead( oSettings, oSettings.aoFooter ); + } + + /* Okay to show that something is going on now */ + _fnProcessingDisplay( oSettings, true ); + + /* Calculate sizes for columns */ + if ( oSettings.oFeatures.bAutoWidth ) + { + _fnCalculateColumnWidths( oSettings ); + } + + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + if ( oSettings.aoColumns[i].sWidth !== null ) + { + oSettings.aoColumns[i].nTh.style.width = _fnStringToCss( oSettings.aoColumns[i].sWidth ); + } + } + + /* If there is default sorting required - let's do it. The sort function will do the + * drawing for us. Otherwise we draw the table regardless of the Ajax source - this allows + * the table to look initialised for Ajax sourcing data (show 'loading' message possibly) + */ + if ( oSettings.oFeatures.bSort ) + { + _fnSort( oSettings ); + } + else if ( oSettings.oFeatures.bFilter ) + { + _fnFilterComplete( oSettings, oSettings.oPreviousSearch ); + } + else + { + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + + /* if there is an ajax source load the data */ + if ( oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide ) + { + var aoData = []; + _fnServerParams( oSettings, aoData ); + oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData, function(json) { + var aData = (oSettings.sAjaxDataProp !== "") ? + _fnGetObjectDataFn( oSettings.sAjaxDataProp )(json) : json; + + /* Got the data - add it to the table */ + for ( i=0 ; i<aData.length ; i++ ) + { + _fnAddData( oSettings, aData[i] ); + } + + /* Reset the init display for cookie saving. We've already done a filter, and + * therefore cleared it before. So we need to make it appear 'fresh' + */ + oSettings.iInitDisplayStart = iAjaxStart; + + if ( oSettings.oFeatures.bSort ) + { + _fnSort( oSettings ); + } + else + { + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + + _fnProcessingDisplay( oSettings, false ); + _fnInitComplete( oSettings, json ); + }, oSettings ); + return; + } + + /* Server-side processing initialisation complete is done at the end of _fnDraw */ + if ( !oSettings.oFeatures.bServerSide ) + { + _fnProcessingDisplay( oSettings, false ); + _fnInitComplete( oSettings ); + } + } + + + /** + * Draw the table for the first time, adding all required features + * @param {object} oSettings dataTables settings object + * @param {object} [json] JSON from the server that completed the table, if using Ajax source + * with client-side processing (optional) + * @memberof DataTable#oApi + */ + function _fnInitComplete ( oSettings, json ) + { + oSettings._bInitComplete = true; + _fnCallbackFire( oSettings, 'aoInitComplete', 'init', [oSettings, json] ); + } + + + /** + * Language compatibility - when certain options are given, and others aren't, we + * need to duplicate the values over, in order to provide backwards compatibility + * with older language files. + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnLanguageCompat( oLanguage ) + { + var oDefaults = DataTable.defaults.oLanguage; + + /* Backwards compatibility - if there is no sEmptyTable given, then use the same as + * sZeroRecords - assuming that is given. + */ + if ( !oLanguage.sEmptyTable && oLanguage.sZeroRecords && + oDefaults.sEmptyTable === "No data available in table" ) + { + _fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable' ); + } + + /* Likewise with loading records */ + if ( !oLanguage.sLoadingRecords && oLanguage.sZeroRecords && + oDefaults.sLoadingRecords === "Loading..." ) + { + _fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sLoadingRecords' ); + } + } + + + + /** + * Generate the node required for user display length changing + * @param {object} oSettings dataTables settings object + * @returns {node} Display length feature node + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlLength ( oSettings ) + { + if ( oSettings.oScroll.bInfinite ) + { + return null; + } + + /* This can be overruled by not using the _MENU_ var/macro in the language variable */ + var sName = 'name="'+oSettings.sTableId+'_length"'; + var sStdMenu = '<select size="1" '+sName+'>'; + var i, iLen; + var aLengthMenu = oSettings.aLengthMenu; + + if ( aLengthMenu.length == 2 && typeof aLengthMenu[0] === 'object' && + typeof aLengthMenu[1] === 'object' ) + { + for ( i=0, iLen=aLengthMenu[0].length ; i<iLen ; i++ ) + { + sStdMenu += '<option value="'+aLengthMenu[0][i]+'">'+aLengthMenu[1][i]+'</option>'; + } + } + else + { + for ( i=0, iLen=aLengthMenu.length ; i<iLen ; i++ ) + { + sStdMenu += '<option value="'+aLengthMenu[i]+'">'+aLengthMenu[i]+'</option>'; + } + } + sStdMenu += '</select>'; + + var nLength = document.createElement( 'div' ); + if ( !oSettings.aanFeatures.l ) + { + nLength.id = oSettings.sTableId+'_length'; + } + nLength.className = oSettings.oClasses.sLength; + nLength.innerHTML = '<label>'+oSettings.oLanguage.sLengthMenu.replace( '_MENU_', sStdMenu )+'</label>'; + + /* + * Set the length to the current display length - thanks to Andrea Pavlovic for this fix, + * and Stefan Skopnik for fixing the fix! + */ + $('select option[value="'+oSettings._iDisplayLength+'"]', nLength).attr("selected", true); + + $('select', nLength).bind( 'change.DT', function(e) { + var iVal = $(this).val(); + + /* Update all other length options for the new display */ + var n = oSettings.aanFeatures.l; + for ( i=0, iLen=n.length ; i<iLen ; i++ ) + { + if ( n[i] != this.parentNode ) + { + $('select', n[i]).val( iVal ); + } + } + + /* Redraw the table */ + oSettings._iDisplayLength = parseInt(iVal, 10); + _fnCalculateEnd( oSettings ); + + /* If we have space to show extra rows (backing up from the end point - then do so */ + if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) + { + oSettings._iDisplayStart = oSettings.fnDisplayEnd() - oSettings._iDisplayLength; + if ( oSettings._iDisplayStart < 0 ) + { + oSettings._iDisplayStart = 0; + } + } + + if ( oSettings._iDisplayLength == -1 ) + { + oSettings._iDisplayStart = 0; + } + + _fnDraw( oSettings ); + } ); + + + $('select', nLength).attr('aria-controls', oSettings.sTableId); + + return nLength; + } + + + /** + * Recalculate the end point based on the start point + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnCalculateEnd( oSettings ) + { + if ( oSettings.oFeatures.bPaginate === false ) + { + oSettings._iDisplayEnd = oSettings.aiDisplay.length; + } + else + { + /* Set the end point of the display - based on how many elements there are + * still to display + */ + if ( oSettings._iDisplayStart + oSettings._iDisplayLength > oSettings.aiDisplay.length || + oSettings._iDisplayLength == -1 ) + { + oSettings._iDisplayEnd = oSettings.aiDisplay.length; + } + else + { + oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength; + } + } + } + + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Note that most of the paging logic is done in + * DataTable.ext.oPagination + */ + + /** + * Generate the node required for default pagination + * @param {object} oSettings dataTables settings object + * @returns {node} Pagination feature node + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlPaginate ( oSettings ) + { + if ( oSettings.oScroll.bInfinite ) + { + return null; + } + + var nPaginate = document.createElement( 'div' ); + nPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType; + + DataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, nPaginate, + function( oSettings ) { + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + ); + + /* Add a draw callback for the pagination on first instance, to update the paging display */ + if ( !oSettings.aanFeatures.p ) + { + oSettings.aoDrawCallback.push( { + "fn": function( oSettings ) { + DataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) { + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } ); + }, + "sName": "pagination" + } ); + } + return nPaginate; + } + + + /** + * Alter the display settings to change the page + * @param {object} oSettings dataTables settings object + * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" + * or page number to jump to (integer) + * @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1 + * @memberof DataTable#oApi + */ + function _fnPageChange ( oSettings, mAction ) + { + var iOldStart = oSettings._iDisplayStart; + + if ( typeof mAction === "number" ) + { + oSettings._iDisplayStart = mAction * oSettings._iDisplayLength; + if ( oSettings._iDisplayStart > oSettings.fnRecordsDisplay() ) + { + oSettings._iDisplayStart = 0; + } + } + else if ( mAction == "first" ) + { + oSettings._iDisplayStart = 0; + } + else if ( mAction == "previous" ) + { + oSettings._iDisplayStart = oSettings._iDisplayLength>=0 ? + oSettings._iDisplayStart - oSettings._iDisplayLength : + 0; + + /* Correct for under-run */ + if ( oSettings._iDisplayStart < 0 ) + { + oSettings._iDisplayStart = 0; + } + } + else if ( mAction == "next" ) + { + if ( oSettings._iDisplayLength >= 0 ) + { + /* Make sure we are not over running the display array */ + if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() ) + { + oSettings._iDisplayStart += oSettings._iDisplayLength; + } + } + else + { + oSettings._iDisplayStart = 0; + } + } + else if ( mAction == "last" ) + { + if ( oSettings._iDisplayLength >= 0 ) + { + var iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1; + oSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength; + } + else + { + oSettings._iDisplayStart = 0; + } + } + else + { + _fnLog( oSettings, 0, "Unknown paging action: "+mAction ); + } + $(oSettings.oInstance).trigger('page', oSettings); + + return iOldStart != oSettings._iDisplayStart; + } + + + + /** + * Generate the node required for the processing node + * @param {object} oSettings dataTables settings object + * @returns {node} Processing element + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlProcessing ( oSettings ) + { + var nProcessing = document.createElement( 'div' ); + + if ( !oSettings.aanFeatures.r ) + { + nProcessing.id = oSettings.sTableId+'_processing'; + } + nProcessing.innerHTML = oSettings.oLanguage.sProcessing; + nProcessing.className = oSettings.oClasses.sProcessing; + oSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable ); + + return nProcessing; + } + + + /** + * Display or hide the processing indicator + * @param {object} oSettings dataTables settings object + * @param {bool} bShow Show the processing indicator (true) or not (false) + * @memberof DataTable#oApi + */ + function _fnProcessingDisplay ( oSettings, bShow ) + { + if ( oSettings.oFeatures.bProcessing ) + { + var an = oSettings.aanFeatures.r; + for ( var i=0, iLen=an.length ; i<iLen ; i++ ) + { + an[i].style.visibility = bShow ? "visible" : "hidden"; + } + } + + $(oSettings.oInstance).trigger('processing', [oSettings, bShow]); + } + + /** + * Add any control elements for the table - specifically scrolling + * @param {object} oSettings dataTables settings object + * @returns {node} Node to add to the DOM + * @memberof DataTable#oApi + */ + function _fnFeatureHtmlTable ( oSettings ) + { + /* Check if scrolling is enabled or not - if not then leave the DOM unaltered */ + if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" ) + { + return oSettings.nTable; + } + + /* + * The HTML structure that we want to generate in this function is: + * div - nScroller + * div - nScrollHead + * div - nScrollHeadInner + * table - nScrollHeadTable + * thead - nThead + * div - nScrollBody + * table - oSettings.nTable + * thead - nTheadSize + * tbody - nTbody + * div - nScrollFoot + * div - nScrollFootInner + * table - nScrollFootTable + * tfoot - nTfoot + */ + var + nScroller = document.createElement('div'), + nScrollHead = document.createElement('div'), + nScrollHeadInner = document.createElement('div'), + nScrollBody = document.createElement('div'), + nScrollFoot = document.createElement('div'), + nScrollFootInner = document.createElement('div'), + nScrollHeadTable = oSettings.nTable.cloneNode(false), + nScrollFootTable = oSettings.nTable.cloneNode(false), + nThead = oSettings.nTable.getElementsByTagName('thead')[0], + nTfoot = oSettings.nTable.getElementsByTagName('tfoot').length === 0 ? null : + oSettings.nTable.getElementsByTagName('tfoot')[0], + oClasses = oSettings.oClasses; + + nScrollHead.appendChild( nScrollHeadInner ); + nScrollFoot.appendChild( nScrollFootInner ); + nScrollBody.appendChild( oSettings.nTable ); + nScroller.appendChild( nScrollHead ); + nScroller.appendChild( nScrollBody ); + nScrollHeadInner.appendChild( nScrollHeadTable ); + nScrollHeadTable.appendChild( nThead ); + if ( nTfoot !== null ) + { + nScroller.appendChild( nScrollFoot ); + nScrollFootInner.appendChild( nScrollFootTable ); + nScrollFootTable.appendChild( nTfoot ); + } + + nScroller.className = oClasses.sScrollWrapper; + nScrollHead.className = oClasses.sScrollHead; + nScrollHeadInner.className = oClasses.sScrollHeadInner; + nScrollBody.className = oClasses.sScrollBody; + nScrollFoot.className = oClasses.sScrollFoot; + nScrollFootInner.className = oClasses.sScrollFootInner; + + if ( oSettings.oScroll.bAutoCss ) + { + nScrollHead.style.overflow = "hidden"; + nScrollHead.style.position = "relative"; + nScrollFoot.style.overflow = "hidden"; + nScrollBody.style.overflow = "auto"; + } + + nScrollHead.style.border = "0"; + nScrollHead.style.width = "100%"; + nScrollFoot.style.border = "0"; + nScrollHeadInner.style.width = oSettings.oScroll.sXInner !== "" ? + oSettings.oScroll.sXInner : "100%"; /* will be overwritten */ + + /* Modify attributes to respect the clones */ + nScrollHeadTable.removeAttribute('id'); + nScrollHeadTable.style.marginLeft = "0"; + oSettings.nTable.style.marginLeft = "0"; + if ( nTfoot !== null ) + { + nScrollFootTable.removeAttribute('id'); + nScrollFootTable.style.marginLeft = "0"; + } + + /* Move caption elements from the body to the header, footer or leave where it is + * depending on the configuration. Note that the DTD says there can be only one caption */ + var nCaption = $(oSettings.nTable).children('caption'); + if ( nCaption.length > 0 ) + { + nCaption = nCaption[0]; + if ( nCaption._captionSide === "top" ) + { + nScrollHeadTable.appendChild( nCaption ); + } + else if ( nCaption._captionSide === "bottom" && nTfoot ) + { + nScrollFootTable.appendChild( nCaption ); + } + } + + /* + * Sizing + */ + /* When x-scrolling add the width and a scroller to move the header with the body */ + if ( oSettings.oScroll.sX !== "" ) + { + nScrollHead.style.width = _fnStringToCss( oSettings.oScroll.sX ); + nScrollBody.style.width = _fnStringToCss( oSettings.oScroll.sX ); + + if ( nTfoot !== null ) + { + nScrollFoot.style.width = _fnStringToCss( oSettings.oScroll.sX ); + } + + /* When the body is scrolled, then we also want to scroll the headers */ + $(nScrollBody).scroll( function (e) { + nScrollHead.scrollLeft = this.scrollLeft; + + if ( nTfoot !== null ) + { + nScrollFoot.scrollLeft = this.scrollLeft; + } + } ); + } + + /* When yscrolling, add the height */ + if ( oSettings.oScroll.sY !== "" ) + { + nScrollBody.style.height = _fnStringToCss( oSettings.oScroll.sY ); + } + + /* Redraw - align columns across the tables */ + oSettings.aoDrawCallback.push( { + "fn": _fnScrollDraw, + "sName": "scrolling" + } ); + + /* Infinite scrolling event handlers */ + if ( oSettings.oScroll.bInfinite ) + { + $(nScrollBody).scroll( function() { + /* Use a blocker to stop scrolling from loading more data while other data is still loading */ + if ( !oSettings.bDrawing && $(this).scrollTop() !== 0 ) + { + /* Check if we should load the next data set */ + if ( $(this).scrollTop() + $(this).height() > + $(oSettings.nTable).height() - oSettings.oScroll.iLoadGap ) + { + /* Only do the redraw if we have to - we might be at the end of the data */ + if ( oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay() ) + { + _fnPageChange( oSettings, 'next' ); + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + } + } + } ); + } + + oSettings.nScrollHead = nScrollHead; + oSettings.nScrollFoot = nScrollFoot; + + return nScroller; + } + + + /** + * Update the various tables for resizing. It's a bit of a pig this function, but + * basically the idea to: + * 1. Re-create the table inside the scrolling div + * 2. Take live measurements from the DOM + * 3. Apply the measurements + * 4. Clean up + * @param {object} o dataTables settings object + * @returns {node} Node to add to the DOM + * @memberof DataTable#oApi + */ + function _fnScrollDraw ( o ) + { + var + nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0], + nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0], + nScrollBody = o.nTable.parentNode, + i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis, + nTheadSize, nTfootSize, + iWidth, aApplied=[], aAppliedFooter=[], iSanityWidth, + nScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null, + nScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null, + ie67 = o.oBrowser.bScrollOversize, + zeroOut = function(nSizer) { + oStyle = nSizer.style; + oStyle.paddingTop = "0"; + oStyle.paddingBottom = "0"; + oStyle.borderTopWidth = "0"; + oStyle.borderBottomWidth = "0"; + oStyle.height = 0; + }; + + /* + * 1. Re-create the table inside the scrolling div + */ + + /* Remove the old minimised thead and tfoot elements in the inner table */ + $(o.nTable).children('thead, tfoot').remove(); + + /* Clone the current header and footer elements and then place it into the inner table */ + nTheadSize = $(o.nTHead).clone()[0]; + o.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] ); + anHeadToSize = o.nTHead.getElementsByTagName('tr'); + anHeadSizers = nTheadSize.getElementsByTagName('tr'); + + if ( o.nTFoot !== null ) + { + nTfootSize = $(o.nTFoot).clone()[0]; + o.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] ); + anFootToSize = o.nTFoot.getElementsByTagName('tr'); + anFootSizers = nTfootSize.getElementsByTagName('tr'); + } + + /* + * 2. Take live measurements from the DOM - do not alter the DOM itself! + */ + + /* Remove old sizing and apply the calculated column widths + * Get the unique column headers in the newly created (cloned) header. We want to apply the + * calculated sizes to this header + */ + if ( o.oScroll.sX === "" ) + { + nScrollBody.style.width = '100%'; + nScrollHeadInner.parentNode.style.width = '100%'; + } + + var nThs = _fnGetUniqueThs( o, nTheadSize ); + for ( i=0, iLen=nThs.length ; i<iLen ; i++ ) + { + iVis = _fnVisibleToColumnIndex( o, i ); + nThs[i].style.width = o.aoColumns[iVis].sWidth; + } + + if ( o.nTFoot !== null ) + { + _fnApplyToChildren( function(n) { + n.style.width = ""; + }, anFootSizers ); + } + + // If scroll collapse is enabled, when we put the headers back into the body for sizing, we + // will end up forcing the scrollbar to appear, making our measurements wrong for when we + // then hide it (end of this function), so add the header height to the body scroller. + if ( o.oScroll.bCollapse && o.oScroll.sY !== "" ) + { + nScrollBody.style.height = (nScrollBody.offsetHeight + o.nTHead.offsetHeight)+"px"; + } + + /* Size the table as a whole */ + iSanityWidth = $(o.nTable).outerWidth(); + if ( o.oScroll.sX === "" ) + { + /* No x scrolling */ + o.nTable.style.width = "100%"; + + /* I know this is rubbish - but IE7 will make the width of the table when 100% include + * the scrollbar - which is shouldn't. When there is a scrollbar we need to take this + * into account. + */ + if ( ie67 && ($('tbody', nScrollBody).height() > nScrollBody.offsetHeight || + $(nScrollBody).css('overflow-y') == "scroll") ) + { + o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth); + } + } + else + { + if ( o.oScroll.sXInner !== "" ) + { + /* x scroll inner has been given - use it */ + o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner); + } + else if ( iSanityWidth == $(nScrollBody).width() && + $(nScrollBody).height() < $(o.nTable).height() ) + { + /* There is y-scrolling - try to take account of the y scroll bar */ + o.nTable.style.width = _fnStringToCss( iSanityWidth-o.oScroll.iBarWidth ); + if ( $(o.nTable).outerWidth() > iSanityWidth-o.oScroll.iBarWidth ) + { + /* Not possible to take account of it */ + o.nTable.style.width = _fnStringToCss( iSanityWidth ); + } + } + else + { + /* All else fails */ + o.nTable.style.width = _fnStringToCss( iSanityWidth ); + } + } + + /* Recalculate the sanity width - now that we've applied the required width, before it was + * a temporary variable. This is required because the column width calculation is done + * before this table DOM is created. + */ + iSanityWidth = $(o.nTable).outerWidth(); + + /* We want the hidden header to have zero height, so remove padding and borders. Then + * set the width based on the real headers + */ + + // Apply all styles in one pass. Invalidates layout only once because we don't read any + // DOM properties. + _fnApplyToChildren( zeroOut, anHeadSizers ); + + // Read all widths in next pass. Forces layout only once because we do not change + // any DOM properties. + _fnApplyToChildren( function(nSizer) { + aApplied.push( _fnStringToCss( $(nSizer).width() ) ); + }, anHeadSizers ); + + // Apply all widths in final pass. Invalidates layout only once because we do not + // read any DOM properties. + _fnApplyToChildren( function(nToSize, i) { + nToSize.style.width = aApplied[i]; + }, anHeadToSize ); + + $(anHeadSizers).height(0); + + /* Same again with the footer if we have one */ + if ( o.nTFoot !== null ) + { + _fnApplyToChildren( zeroOut, anFootSizers ); + + _fnApplyToChildren( function(nSizer) { + aAppliedFooter.push( _fnStringToCss( $(nSizer).width() ) ); + }, anFootSizers ); + + _fnApplyToChildren( function(nToSize, i) { + nToSize.style.width = aAppliedFooter[i]; + }, anFootToSize ); + + $(anFootSizers).height(0); + } + + /* + * 3. Apply the measurements + */ + + /* "Hide" the header and footer that we used for the sizing. We want to also fix their width + * to what they currently are + */ + _fnApplyToChildren( function(nSizer, i) { + nSizer.innerHTML = ""; + nSizer.style.width = aApplied[i]; + }, anHeadSizers ); + + if ( o.nTFoot !== null ) + { + _fnApplyToChildren( function(nSizer, i) { + nSizer.innerHTML = ""; + nSizer.style.width = aAppliedFooter[i]; + }, anFootSizers ); + } + + /* Sanity check that the table is of a sensible width. If not then we are going to get + * misalignment - try to prevent this by not allowing the table to shrink below its min width + */ + if ( $(o.nTable).outerWidth() < iSanityWidth ) + { + /* The min width depends upon if we have a vertical scrollbar visible or not */ + var iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight || + $(nScrollBody).css('overflow-y') == "scroll")) ? + iSanityWidth+o.oScroll.iBarWidth : iSanityWidth; + + /* IE6/7 are a law unto themselves... */ + if ( ie67 && (nScrollBody.scrollHeight > + nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll") ) + { + o.nTable.style.width = _fnStringToCss( iCorrection-o.oScroll.iBarWidth ); + } + + /* Apply the calculated minimum width to the table wrappers */ + nScrollBody.style.width = _fnStringToCss( iCorrection ); + o.nScrollHead.style.width = _fnStringToCss( iCorrection ); + + if ( o.nTFoot !== null ) + { + o.nScrollFoot.style.width = _fnStringToCss( iCorrection ); + } + + /* And give the user a warning that we've stopped the table getting too small */ + if ( o.oScroll.sX === "" ) + { + _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+ + " misalignment. The table has been drawn at its minimum possible width." ); + } + else if ( o.oScroll.sXInner !== "" ) + { + _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+ + " misalignment. Increase the sScrollXInner value or remove it to allow automatic"+ + " calculation" ); + } + } + else + { + nScrollBody.style.width = _fnStringToCss( '100%' ); + o.nScrollHead.style.width = _fnStringToCss( '100%' ); + + if ( o.nTFoot !== null ) + { + o.nScrollFoot.style.width = _fnStringToCss( '100%' ); + } + } + + + /* + * 4. Clean up + */ + if ( o.oScroll.sY === "" ) + { + /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting + * the scrollbar height from the visible display, rather than adding it on. We need to + * set the height in order to sort this. Don't want to do it in any other browsers. + */ + if ( ie67 ) + { + nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+o.oScroll.iBarWidth ); + } + } + + if ( o.oScroll.sY !== "" && o.oScroll.bCollapse ) + { + nScrollBody.style.height = _fnStringToCss( o.oScroll.sY ); + + var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ? + o.oScroll.iBarWidth : 0; + if ( o.nTable.offsetHeight < nScrollBody.offsetHeight ) + { + nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+iExtra ); + } + } + + /* Finally set the width's of the header and footer tables */ + var iOuterWidth = $(o.nTable).outerWidth(); + nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth ); + nScrollHeadInner.style.width = _fnStringToCss( iOuterWidth ); + + // Figure out if there are scrollbar present - if so then we need a the header and footer to + // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar) + var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll"; + nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px"; + + if ( o.nTFoot !== null ) + { + nScrollFootTable.style.width = _fnStringToCss( iOuterWidth ); + nScrollFootInner.style.width = _fnStringToCss( iOuterWidth ); + nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px"; + } + + /* Adjust the position of the header in case we loose the y-scrollbar */ + $(nScrollBody).scroll(); + + /* If sorting or filtering has occurred, jump the scrolling back to the top */ + if ( o.bSorted || o.bFiltered ) + { + nScrollBody.scrollTop = 0; + } + } + + + /** + * Apply a given function to the display child nodes of an element array (typically + * TD children of TR rows + * @param {function} fn Method to apply to the objects + * @param array {nodes} an1 List of elements to look through for display children + * @param array {nodes} an2 Another list (identical structure to the first) - optional + * @memberof DataTable#oApi + */ + function _fnApplyToChildren( fn, an1, an2 ) + { + var index=0, i=0, iLen=an1.length; + var nNode1, nNode2; + + while ( i < iLen ) + { + nNode1 = an1[i].firstChild; + nNode2 = an2 ? an2[i].firstChild : null; + while ( nNode1 ) + { + if ( nNode1.nodeType === 1 ) + { + if ( an2 ) + { + fn( nNode1, nNode2, index ); + } + else + { + fn( nNode1, index ); + } + index++; + } + nNode1 = nNode1.nextSibling; + nNode2 = an2 ? nNode2.nextSibling : null; + } + i++; + } + } + + /** + * Convert a CSS unit width to pixels (e.g. 2em) + * @param {string} sWidth width to be converted + * @param {node} nParent parent to get the with for (required for relative widths) - optional + * @returns {int} iWidth width in pixels + * @memberof DataTable#oApi + */ + function _fnConvertToWidth ( sWidth, nParent ) + { + if ( !sWidth || sWidth === null || sWidth === '' ) + { + return 0; + } + + if ( !nParent ) + { + nParent = document.body; + } + + var iWidth; + var nTmp = document.createElement( "div" ); + nTmp.style.width = _fnStringToCss( sWidth ); + + nParent.appendChild( nTmp ); + iWidth = nTmp.offsetWidth; + nParent.removeChild( nTmp ); + + return ( iWidth ); + } + + + /** + * Calculate the width of columns for the table + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnCalculateColumnWidths ( oSettings ) + { + var iTableWidth = oSettings.nTable.offsetWidth; + var iUserInputs = 0; + var iTmpWidth; + var iVisibleColumns = 0; + var iColums = oSettings.aoColumns.length; + var i, iIndex, iCorrector, iWidth; + var oHeaders = $('th', oSettings.nTHead); + var widthAttr = oSettings.nTable.getAttribute('width'); + var nWrapper = oSettings.nTable.parentNode; + + /* Convert any user input sizes into pixel sizes */ + for ( i=0 ; i<iColums ; i++ ) + { + if ( oSettings.aoColumns[i].bVisible ) + { + iVisibleColumns++; + + if ( oSettings.aoColumns[i].sWidth !== null ) + { + iTmpWidth = _fnConvertToWidth( oSettings.aoColumns[i].sWidthOrig, + nWrapper ); + if ( iTmpWidth !== null ) + { + oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth ); + } + + iUserInputs++; + } + } + } + + /* If the number of columns in the DOM equals the number that we have to process in + * DataTables, then we can use the offsets that are created by the web-browser. No custom + * sizes can be set in order for this to happen, nor scrolling used + */ + if ( iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums && + oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" ) + { + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + iTmpWidth = $(oHeaders[i]).width(); + if ( iTmpWidth !== null ) + { + oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth ); + } + } + } + else + { + /* Otherwise we are going to have to do some calculations to get the width of each column. + * Construct a 1 row table with the widest node in the data, and any user defined widths, + * then insert it into the DOM and allow the browser to do all the hard work of + * calculating table widths. + */ + var + nCalcTmp = oSettings.nTable.cloneNode( false ), + nTheadClone = oSettings.nTHead.cloneNode(true), + nBody = document.createElement( 'tbody' ), + nTr = document.createElement( 'tr' ), + nDivSizing; + + nCalcTmp.removeAttribute( "id" ); + nCalcTmp.appendChild( nTheadClone ); + if ( oSettings.nTFoot !== null ) + { + nCalcTmp.appendChild( oSettings.nTFoot.cloneNode(true) ); + _fnApplyToChildren( function(n) { + n.style.width = ""; + }, nCalcTmp.getElementsByTagName('tr') ); + } + + nCalcTmp.appendChild( nBody ); + nBody.appendChild( nTr ); + + /* Remove any sizing that was previously applied by the styles */ + var jqColSizing = $('thead th', nCalcTmp); + if ( jqColSizing.length === 0 ) + { + jqColSizing = $('tbody tr:eq(0)>td', nCalcTmp); + } + + /* Apply custom sizing to the cloned header */ + var nThs = _fnGetUniqueThs( oSettings, nTheadClone ); + iCorrector = 0; + for ( i=0 ; i<iColums ; i++ ) + { + var oColumn = oSettings.aoColumns[i]; + if ( oColumn.bVisible && oColumn.sWidthOrig !== null && oColumn.sWidthOrig !== "" ) + { + nThs[i-iCorrector].style.width = _fnStringToCss( oColumn.sWidthOrig ); + } + else if ( oColumn.bVisible ) + { + nThs[i-iCorrector].style.width = ""; + } + else + { + iCorrector++; + } + } + + /* Find the biggest td for each column and put it into the table */ + for ( i=0 ; i<iColums ; i++ ) + { + if ( oSettings.aoColumns[i].bVisible ) + { + var nTd = _fnGetWidestNode( oSettings, i ); + if ( nTd !== null ) + { + nTd = nTd.cloneNode(true); + if ( oSettings.aoColumns[i].sContentPadding !== "" ) + { + nTd.innerHTML += oSettings.aoColumns[i].sContentPadding; + } + nTr.appendChild( nTd ); + } + } + } + + /* Build the table and 'display' it */ + nWrapper.appendChild( nCalcTmp ); + + /* When scrolling (X or Y) we want to set the width of the table as appropriate. However, + * when not scrolling leave the table width as it is. This results in slightly different, + * but I think correct behaviour + */ + if ( oSettings.oScroll.sX !== "" && oSettings.oScroll.sXInner !== "" ) + { + nCalcTmp.style.width = _fnStringToCss(oSettings.oScroll.sXInner); + } + else if ( oSettings.oScroll.sX !== "" ) + { + nCalcTmp.style.width = ""; + if ( $(nCalcTmp).width() < nWrapper.offsetWidth ) + { + nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth ); + } + } + else if ( oSettings.oScroll.sY !== "" ) + { + nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth ); + } + else if ( widthAttr ) + { + nCalcTmp.style.width = _fnStringToCss( widthAttr ); + } + nCalcTmp.style.visibility = "hidden"; + + /* Scrolling considerations */ + _fnScrollingWidthAdjust( oSettings, nCalcTmp ); + + /* Read the width's calculated by the browser and store them for use by the caller. We + * first of all try to use the elements in the body, but it is possible that there are + * no elements there, under which circumstances we use the header elements + */ + var oNodes = $("tbody tr:eq(0)", nCalcTmp).children(); + if ( oNodes.length === 0 ) + { + oNodes = _fnGetUniqueThs( oSettings, $('thead', nCalcTmp)[0] ); + } + + /* Browsers need a bit of a hand when a width is assigned to any columns when + * x-scrolling as they tend to collapse the table to the min-width, even if + * we sent the column widths. So we need to keep track of what the table width + * should be by summing the user given values, and the automatic values + */ + if ( oSettings.oScroll.sX !== "" ) + { + var iTotal = 0; + iCorrector = 0; + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + if ( oSettings.aoColumns[i].bVisible ) + { + if ( oSettings.aoColumns[i].sWidthOrig === null ) + { + iTotal += $(oNodes[iCorrector]).outerWidth(); + } + else + { + iTotal += parseInt(oSettings.aoColumns[i].sWidth.replace('px',''), 10) + + ($(oNodes[iCorrector]).outerWidth() - $(oNodes[iCorrector]).width()); + } + iCorrector++; + } + } + + nCalcTmp.style.width = _fnStringToCss( iTotal ); + oSettings.nTable.style.width = _fnStringToCss( iTotal ); + } + + iCorrector = 0; + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + if ( oSettings.aoColumns[i].bVisible ) + { + iWidth = $(oNodes[iCorrector]).width(); + if ( iWidth !== null && iWidth > 0 ) + { + oSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth ); + } + iCorrector++; + } + } + + var cssWidth = $(nCalcTmp).css('width'); + oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ? + cssWidth : _fnStringToCss( $(nCalcTmp).outerWidth() ); + nCalcTmp.parentNode.removeChild( nCalcTmp ); + } + + if ( widthAttr ) + { + oSettings.nTable.style.width = _fnStringToCss( widthAttr ); + } + } + + + /** + * Adjust a table's width to take account of scrolling + * @param {object} oSettings dataTables settings object + * @param {node} n table node + * @memberof DataTable#oApi + */ + function _fnScrollingWidthAdjust ( oSettings, n ) + { + if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "" ) + { + /* When y-scrolling only, we want to remove the width of the scroll bar so the table + * + scroll bar will fit into the area avaialble. + */ + var iOrigWidth = $(n).width(); + n.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth ); + } + else if ( oSettings.oScroll.sX !== "" ) + { + /* When x-scrolling both ways, fix the table at it's current size, without adjusting */ + n.style.width = _fnStringToCss( $(n).outerWidth() ); + } + } + + + /** + * Get the widest node + * @param {object} oSettings dataTables settings object + * @param {int} iCol column of interest + * @returns {node} widest table node + * @memberof DataTable#oApi + */ + function _fnGetWidestNode( oSettings, iCol ) + { + var iMaxIndex = _fnGetMaxLenString( oSettings, iCol ); + if ( iMaxIndex < 0 ) + { + return null; + } + + if ( oSettings.aoData[iMaxIndex].nTr === null ) + { + var n = document.createElement('td'); + n.innerHTML = _fnGetCellData( oSettings, iMaxIndex, iCol, '' ); + return n; + } + return _fnGetTdNodes(oSettings, iMaxIndex)[iCol]; + } + + + /** + * Get the maximum strlen for each data column + * @param {object} oSettings dataTables settings object + * @param {int} iCol column of interest + * @returns {string} max string length for each column + * @memberof DataTable#oApi + */ + function _fnGetMaxLenString( oSettings, iCol ) + { + var iMax = -1; + var iMaxIndex = -1; + + for ( var i=0 ; i<oSettings.aoData.length ; i++ ) + { + var s = _fnGetCellData( oSettings, i, iCol, 'display' )+""; + s = s.replace( /<.*?>/g, "" ); + if ( s.length > iMax ) + { + iMax = s.length; + iMaxIndex = i; + } + } + + return iMaxIndex; + } + + + /** + * Append a CSS unit (only if required) to a string + * @param {array} aArray1 first array + * @param {array} aArray2 second array + * @returns {int} 0 if match, 1 if length is different, 2 if no match + * @memberof DataTable#oApi + */ + function _fnStringToCss( s ) + { + if ( s === null ) + { + return "0px"; + } + + if ( typeof s == 'number' ) + { + if ( s < 0 ) + { + return "0px"; + } + return s+"px"; + } + + /* Check if the last character is not 0-9 */ + var c = s.charCodeAt( s.length-1 ); + if (c < 0x30 || c > 0x39) + { + return s; + } + return s+"px"; + } + + + /** + * Get the width of a scroll bar in this browser being used + * @returns {int} width in pixels + * @memberof DataTable#oApi + */ + function _fnScrollBarWidth () + { + var inner = document.createElement('p'); + var style = inner.style; + style.width = "100%"; + style.height = "200px"; + style.padding = "0px"; + + var outer = document.createElement('div'); + style = outer.style; + style.position = "absolute"; + style.top = "0px"; + style.left = "0px"; + style.visibility = "hidden"; + style.width = "200px"; + style.height = "150px"; + style.padding = "0px"; + style.overflow = "hidden"; + outer.appendChild(inner); + + document.body.appendChild(outer); + var w1 = inner.offsetWidth; + outer.style.overflow = 'scroll'; + var w2 = inner.offsetWidth; + if ( w1 == w2 ) + { + w2 = outer.clientWidth; + } + + document.body.removeChild(outer); + return (w1 - w2); + } + + /** + * Change the order of the table + * @param {object} oSettings dataTables settings object + * @param {bool} bApplyClasses optional - should we apply classes or not + * @memberof DataTable#oApi + */ + function _fnSort ( oSettings, bApplyClasses ) + { + var + i, iLen, j, jLen, k, kLen, + sDataType, nTh, + aaSort = [], + aiOrig = [], + oSort = DataTable.ext.oSort, + aoData = oSettings.aoData, + aoColumns = oSettings.aoColumns, + oAria = oSettings.oLanguage.oAria; + + /* No sorting required if server-side or no sorting array */ + if ( !oSettings.oFeatures.bServerSide && + (oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null) ) + { + aaSort = ( oSettings.aaSortingFixed !== null ) ? + oSettings.aaSortingFixed.concat( oSettings.aaSorting ) : + oSettings.aaSorting.slice(); + + /* If there is a sorting data type, and a function belonging to it, then we need to + * get the data from the developer's function and apply it for this column + */ + for ( i=0 ; i<aaSort.length ; i++ ) + { + var iColumn = aaSort[i][0]; + var iVisColumn = _fnColumnIndexToVisible( oSettings, iColumn ); + sDataType = oSettings.aoColumns[ iColumn ].sSortDataType; + if ( DataTable.ext.afnSortData[sDataType] ) + { + var aData = DataTable.ext.afnSortData[sDataType].call( + oSettings.oInstance, oSettings, iColumn, iVisColumn + ); + if ( aData.length === aoData.length ) + { + for ( j=0, jLen=aoData.length ; j<jLen ; j++ ) + { + _fnSetCellData( oSettings, j, iColumn, aData[j] ); + } + } + else + { + _fnLog( oSettings, 0, "Returned data sort array (col "+iColumn+") is the wrong length" ); + } + } + } + + /* Create a value - key array of the current row positions such that we can use their + * current position during the sort, if values match, in order to perform stable sorting + */ + for ( i=0, iLen=oSettings.aiDisplayMaster.length ; i<iLen ; i++ ) + { + aiOrig[ oSettings.aiDisplayMaster[i] ] = i; + } + + /* Build an internal data array which is specific to the sort, so we can get and prep + * the data to be sorted only once, rather than needing to do it every time the sorting + * function runs. This make the sorting function a very simple comparison + */ + var iSortLen = aaSort.length; + var fnSortFormat, aDataSort; + for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + for ( j=0 ; j<iSortLen ; j++ ) + { + aDataSort = aoColumns[ aaSort[j][0] ].aDataSort; + + for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ ) + { + sDataType = aoColumns[ aDataSort[k] ].sType; + fnSortFormat = oSort[ (sDataType ? sDataType : 'string')+"-pre" ]; + + aoData[i]._aSortData[ aDataSort[k] ] = fnSortFormat ? + fnSortFormat( _fnGetCellData( oSettings, i, aDataSort[k], 'sort' ) ) : + _fnGetCellData( oSettings, i, aDataSort[k], 'sort' ); + } + } + } + + /* Do the sort - here we want multi-column sorting based on a given data source (column) + * and sorting function (from oSort) in a certain direction. It's reasonably complex to + * follow on it's own, but this is what we want (example two column sorting): + * fnLocalSorting = function(a,b){ + * var iTest; + * iTest = oSort['string-asc']('data11', 'data12'); + * if (iTest !== 0) + * return iTest; + * iTest = oSort['numeric-desc']('data21', 'data22'); + * if (iTest !== 0) + * return iTest; + * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] ); + * } + * Basically we have a test for each sorting column, if the data in that column is equal, + * test the next column. If all columns match, then we use a numeric sort on the row + * positions in the original data array to provide a stable sort. + */ + oSettings.aiDisplayMaster.sort( function ( a, b ) { + var k, l, lLen, iTest, aDataSort, sDataType; + for ( k=0 ; k<iSortLen ; k++ ) + { + aDataSort = aoColumns[ aaSort[k][0] ].aDataSort; + + for ( l=0, lLen=aDataSort.length ; l<lLen ; l++ ) + { + sDataType = aoColumns[ aDataSort[l] ].sType; + + iTest = oSort[ (sDataType ? sDataType : 'string')+"-"+aaSort[k][1] ]( + aoData[a]._aSortData[ aDataSort[l] ], + aoData[b]._aSortData[ aDataSort[l] ] + ); + + if ( iTest !== 0 ) + { + return iTest; + } + } + } + + return oSort['numeric-asc']( aiOrig[a], aiOrig[b] ); + } ); + } + + /* Alter the sorting classes to take account of the changes */ + if ( (bApplyClasses === undefined || bApplyClasses) && !oSettings.oFeatures.bDeferRender ) + { + _fnSortingClasses( oSettings ); + } + + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + var sTitle = aoColumns[i].sTitle.replace( /<.*?>/g, "" ); + nTh = aoColumns[i].nTh; + nTh.removeAttribute('aria-sort'); + nTh.removeAttribute('aria-label'); + + /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */ + if ( aoColumns[i].bSortable ) + { + if ( aaSort.length > 0 && aaSort[0][0] == i ) + { + nTh.setAttribute('aria-sort', aaSort[0][1]=="asc" ? "ascending" : "descending" ); + + var nextSort = (aoColumns[i].asSorting[ aaSort[0][2]+1 ]) ? + aoColumns[i].asSorting[ aaSort[0][2]+1 ] : aoColumns[i].asSorting[0]; + nTh.setAttribute('aria-label', sTitle+ + (nextSort=="asc" ? oAria.sSortAscending : oAria.sSortDescending) ); + } + else + { + nTh.setAttribute('aria-label', sTitle+ + (aoColumns[i].asSorting[0]=="asc" ? oAria.sSortAscending : oAria.sSortDescending) ); + } + } + else + { + nTh.setAttribute('aria-label', sTitle); + } + } + + /* Tell the draw function that we have sorted the data */ + oSettings.bSorted = true; + $(oSettings.oInstance).trigger('sort', oSettings); + + /* Copy the master data into the draw array and re-draw */ + if ( oSettings.oFeatures.bFilter ) + { + /* _fnFilter() will redraw the table for us */ + _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 ); + } + else + { + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + oSettings._iDisplayStart = 0; /* reset display back to page 0 */ + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + } + + + /** + * Attach a sort handler (click) to a node + * @param {object} oSettings dataTables settings object + * @param {node} nNode node to attach the handler to + * @param {int} iDataIndex column sorting index + * @param {function} [fnCallback] callback function + * @memberof DataTable#oApi + */ + function _fnSortAttachListener ( oSettings, nNode, iDataIndex, fnCallback ) + { + _fnBindAction( nNode, {}, function (e) { + /* If the column is not sortable - don't to anything */ + if ( oSettings.aoColumns[iDataIndex].bSortable === false ) + { + return; + } + + /* + * This is a little bit odd I admit... I declare a temporary function inside the scope of + * _fnBuildHead and the click handler in order that the code presented here can be used + * twice - once for when bProcessing is enabled, and another time for when it is + * disabled, as we need to perform slightly different actions. + * Basically the issue here is that the Javascript engine in modern browsers don't + * appear to allow the rendering engine to update the display while it is still executing + * it's thread (well - it does but only after long intervals). This means that the + * 'processing' display doesn't appear for a table sort. To break the js thread up a bit + * I force an execution break by using setTimeout - but this breaks the expected + * thread continuation for the end-developer's point of view (their code would execute + * too early), so we only do it when we absolutely have to. + */ + var fnInnerSorting = function () { + var iColumn, iNextSort; + + /* If the shift key is pressed then we are multiple column sorting */ + if ( e.shiftKey ) + { + /* Are we already doing some kind of sort on this column? */ + var bFound = false; + for ( var i=0 ; i<oSettings.aaSorting.length ; i++ ) + { + if ( oSettings.aaSorting[i][0] == iDataIndex ) + { + bFound = true; + iColumn = oSettings.aaSorting[i][0]; + iNextSort = oSettings.aaSorting[i][2]+1; + + if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] ) + { + /* Reached the end of the sorting options, remove from multi-col sort */ + oSettings.aaSorting.splice( i, 1 ); + } + else + { + /* Move onto next sorting direction */ + oSettings.aaSorting[i][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort]; + oSettings.aaSorting[i][2] = iNextSort; + } + break; + } + } + + /* No sort yet - add it in */ + if ( bFound === false ) + { + oSettings.aaSorting.push( [ iDataIndex, + oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] ); + } + } + else + { + /* If no shift key then single column sort */ + if ( oSettings.aaSorting.length == 1 && oSettings.aaSorting[0][0] == iDataIndex ) + { + iColumn = oSettings.aaSorting[0][0]; + iNextSort = oSettings.aaSorting[0][2]+1; + if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] ) + { + iNextSort = 0; + } + oSettings.aaSorting[0][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort]; + oSettings.aaSorting[0][2] = iNextSort; + } + else + { + oSettings.aaSorting.splice( 0, oSettings.aaSorting.length ); + oSettings.aaSorting.push( [ iDataIndex, + oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] ); + } + } + + /* Run the sort */ + _fnSort( oSettings ); + }; /* /fnInnerSorting */ + + if ( !oSettings.oFeatures.bProcessing ) + { + fnInnerSorting(); + } + else + { + _fnProcessingDisplay( oSettings, true ); + setTimeout( function() { + fnInnerSorting(); + if ( !oSettings.oFeatures.bServerSide ) + { + _fnProcessingDisplay( oSettings, false ); + } + }, 0 ); + } + + /* Call the user specified callback function - used for async user interaction */ + if ( typeof fnCallback == 'function' ) + { + fnCallback( oSettings ); + } + } ); + } + + + /** + * Set the sorting classes on the header, Note: it is safe to call this function + * when bSort and bSortClasses are false + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnSortingClasses( oSettings ) + { + var i, iLen, j, jLen, iFound; + var aaSort, sClass; + var iColumns = oSettings.aoColumns.length; + var oClasses = oSettings.oClasses; + + for ( i=0 ; i<iColumns ; i++ ) + { + if ( oSettings.aoColumns[i].bSortable ) + { + $(oSettings.aoColumns[i].nTh).removeClass( oClasses.sSortAsc +" "+ oClasses.sSortDesc + + " "+ oSettings.aoColumns[i].sSortingClass ); + } + } + + if ( oSettings.aaSortingFixed !== null ) + { + aaSort = oSettings.aaSortingFixed.concat( oSettings.aaSorting ); + } + else + { + aaSort = oSettings.aaSorting.slice(); + } + + /* Apply the required classes to the header */ + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + if ( oSettings.aoColumns[i].bSortable ) + { + sClass = oSettings.aoColumns[i].sSortingClass; + iFound = -1; + for ( j=0 ; j<aaSort.length ; j++ ) + { + if ( aaSort[j][0] == i ) + { + sClass = ( aaSort[j][1] == "asc" ) ? + oClasses.sSortAsc : oClasses.sSortDesc; + iFound = j; + break; + } + } + $(oSettings.aoColumns[i].nTh).addClass( sClass ); + + if ( oSettings.bJUI ) + { + /* jQuery UI uses extra markup */ + var jqSpan = $("span."+oClasses.sSortIcon, oSettings.aoColumns[i].nTh); + jqSpan.removeClass(oClasses.sSortJUIAsc +" "+ oClasses.sSortJUIDesc +" "+ + oClasses.sSortJUI +" "+ oClasses.sSortJUIAscAllowed +" "+ oClasses.sSortJUIDescAllowed ); + + var sSpanClass; + if ( iFound == -1 ) + { + sSpanClass = oSettings.aoColumns[i].sSortingClassJUI; + } + else if ( aaSort[iFound][1] == "asc" ) + { + sSpanClass = oClasses.sSortJUIAsc; + } + else + { + sSpanClass = oClasses.sSortJUIDesc; + } + + jqSpan.addClass( sSpanClass ); + } + } + else + { + /* No sorting on this column, so add the base class. This will have been assigned by + * _fnAddColumn + */ + $(oSettings.aoColumns[i].nTh).addClass( oSettings.aoColumns[i].sSortingClass ); + } + } + + /* + * Apply the required classes to the table body + * Note that this is given as a feature switch since it can significantly slow down a sort + * on large data sets (adding and removing of classes is always slow at the best of times..) + * Further to this, note that this code is admittedly fairly ugly. It could be made a lot + * simpler using jQuery selectors and add/removeClass, but that is significantly slower + * (on the order of 5 times slower) - hence the direct DOM manipulation here. + * Note that for deferred drawing we do use jQuery - the reason being that taking the first + * row found to see if the whole column needs processed can miss classes since the first + * column might be new. + */ + sClass = oClasses.sSortColumn; + + if ( oSettings.oFeatures.bSort && oSettings.oFeatures.bSortClasses ) + { + var nTds = _fnGetTdNodes( oSettings ); + + /* Determine what the sorting class for each column should be */ + var iClass, iTargetCol; + var asClasses = []; + for (i = 0; i < iColumns; i++) + { + asClasses.push(""); + } + for (i = 0, iClass = 1; i < aaSort.length; i++) + { + iTargetCol = parseInt( aaSort[i][0], 10 ); + asClasses[iTargetCol] = sClass + iClass; + + if ( iClass < 3 ) + { + iClass++; + } + } + + /* Make changes to the classes for each cell as needed */ + var reClass = new RegExp(sClass + "[123]"); + var sTmpClass, sCurrentClass, sNewClass; + for ( i=0, iLen=nTds.length; i<iLen; i++ ) + { + /* Determine which column we're looking at */ + iTargetCol = i % iColumns; + + /* What is the full list of classes now */ + sCurrentClass = nTds[i].className; + /* What sorting class should be applied? */ + sNewClass = asClasses[iTargetCol]; + /* What would the new full list be if we did a replacement? */ + sTmpClass = sCurrentClass.replace(reClass, sNewClass); + + if ( sTmpClass != sCurrentClass ) + { + /* We changed something */ + nTds[i].className = $.trim( sTmpClass ); + } + else if ( sNewClass.length > 0 && sCurrentClass.indexOf(sNewClass) == -1 ) + { + /* We need to add a class */ + nTds[i].className = sCurrentClass + " " + sNewClass; + } + } + } + } + + + + /** + * Save the state of a table in a cookie such that the page can be reloaded + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnSaveState ( oSettings ) + { + if ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying ) + { + return; + } + + /* Store the interesting variables */ + var i, iLen, bInfinite=oSettings.oScroll.bInfinite; + var oState = { + "iCreate": new Date().getTime(), + "iStart": (bInfinite ? 0 : oSettings._iDisplayStart), + "iEnd": (bInfinite ? oSettings._iDisplayLength : oSettings._iDisplayEnd), + "iLength": oSettings._iDisplayLength, + "aaSorting": $.extend( true, [], oSettings.aaSorting ), + "oSearch": $.extend( true, {}, oSettings.oPreviousSearch ), + "aoSearchCols": $.extend( true, [], oSettings.aoPreSearchCols ), + "abVisCols": [] + }; + + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + oState.abVisCols.push( oSettings.aoColumns[i].bVisible ); + } + + _fnCallbackFire( oSettings, "aoStateSaveParams", 'stateSaveParams', [oSettings, oState] ); + + oSettings.fnStateSave.call( oSettings.oInstance, oSettings, oState ); + } + + + /** + * Attempt to load a saved table state from a cookie + * @param {object} oSettings dataTables settings object + * @param {object} oInit DataTables init object so we can override settings + * @memberof DataTable#oApi + */ + function _fnLoadState ( oSettings, oInit ) + { + if ( !oSettings.oFeatures.bStateSave ) + { + return; + } + + var oData = oSettings.fnStateLoad.call( oSettings.oInstance, oSettings ); + if ( !oData ) + { + return; + } + + /* Allow custom and plug-in manipulation functions to alter the saved data set and + * cancelling of loading by returning false + */ + var abStateLoad = _fnCallbackFire( oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData] ); + if ( $.inArray( false, abStateLoad ) !== -1 ) + { + return; + } + + /* Store the saved state so it might be accessed at any time */ + oSettings.oLoadedState = $.extend( true, {}, oData ); + + /* Restore key features */ + oSettings._iDisplayStart = oData.iStart; + oSettings.iInitDisplayStart = oData.iStart; + oSettings._iDisplayEnd = oData.iEnd; + oSettings._iDisplayLength = oData.iLength; + oSettings.aaSorting = oData.aaSorting.slice(); + oSettings.saved_aaSorting = oData.aaSorting.slice(); + + /* Search filtering */ + $.extend( oSettings.oPreviousSearch, oData.oSearch ); + $.extend( true, oSettings.aoPreSearchCols, oData.aoSearchCols ); + + /* Column visibility state + * Pass back visibility settings to the init handler, but to do not here override + * the init object that the user might have passed in + */ + oInit.saved_aoColumns = []; + for ( var i=0 ; i<oData.abVisCols.length ; i++ ) + { + oInit.saved_aoColumns[i] = {}; + oInit.saved_aoColumns[i].bVisible = oData.abVisCols[i]; + } + + _fnCallbackFire( oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData] ); + } + + + /** + * Create a new cookie with a value to store the state of a table + * @param {string} sName name of the cookie to create + * @param {string} sValue the value the cookie should take + * @param {int} iSecs duration of the cookie + * @param {string} sBaseName sName is made up of the base + file name - this is the base + * @param {function} fnCallback User definable function to modify the cookie + * @memberof DataTable#oApi + */ + function _fnCreateCookie ( sName, sValue, iSecs, sBaseName, fnCallback ) + { + var date = new Date(); + date.setTime( date.getTime()+(iSecs*1000) ); + + /* + * Shocking but true - it would appear IE has major issues with having the path not having + * a trailing slash on it. We need the cookie to be available based on the path, so we + * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the + * patch to use at least some of the path + */ + var aParts = window.location.pathname.split('/'); + var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g,"").toLowerCase(); + var sFullCookie, oData; + + if ( fnCallback !== null ) + { + oData = (typeof $.parseJSON === 'function') ? + $.parseJSON( sValue ) : eval( '('+sValue+')' ); + sFullCookie = fnCallback( sNameFile, oData, date.toGMTString(), + aParts.join('/')+"/" ); + } + else + { + sFullCookie = sNameFile + "=" + encodeURIComponent(sValue) + + "; expires=" + date.toGMTString() +"; path=" + aParts.join('/')+"/"; + } + + /* Are we going to go over the cookie limit of 4KiB? If so, try to delete a cookies + * belonging to DataTables. + */ + var + aCookies =document.cookie.split(';'), + iNewCookieLen = sFullCookie.split(';')[0].length, + aOldCookies = []; + + if ( iNewCookieLen+document.cookie.length+10 > 4096 ) /* Magic 10 for padding */ + { + for ( var i=0, iLen=aCookies.length ; i<iLen ; i++ ) + { + if ( aCookies[i].indexOf( sBaseName ) != -1 ) + { + /* It's a DataTables cookie, so eval it and check the time stamp */ + var aSplitCookie = aCookies[i].split('='); + try { + oData = eval( '('+decodeURIComponent(aSplitCookie[1])+')' ); + + if ( oData && oData.iCreate ) + { + aOldCookies.push( { + "name": aSplitCookie[0], + "time": oData.iCreate + } ); + } + } + catch( e ) {} + } + } + + // Make sure we delete the oldest ones first + aOldCookies.sort( function (a, b) { + return b.time - a.time; + } ); + + // Eliminate as many old DataTables cookies as we need to + while ( iNewCookieLen + document.cookie.length + 10 > 4096 ) { + if ( aOldCookies.length === 0 ) { + // Deleted all DT cookies and still not enough space. Can't state save + return; + } + + var old = aOldCookies.pop(); + document.cookie = old.name+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+ + aParts.join('/') + "/"; + } + } + + document.cookie = sFullCookie; + } + + + /** + * Read an old cookie to get a cookie with an old table state + * @param {string} sName name of the cookie to read + * @returns {string} contents of the cookie - or null if no cookie with that name found + * @memberof DataTable#oApi + */ + function _fnReadCookie ( sName ) + { + var + aParts = window.location.pathname.split('/'), + sNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\/:]/g,"").toLowerCase() + '=', + sCookieContents = document.cookie.split(';'); + + for( var i=0 ; i<sCookieContents.length ; i++ ) + { + var c = sCookieContents[i]; + + while (c.charAt(0)==' ') + { + c = c.substring(1,c.length); + } + + if (c.indexOf(sNameEQ) === 0) + { + return decodeURIComponent( c.substring(sNameEQ.length,c.length) ); + } + } + return null; + } + + + /** + * Return the settings object for a particular table + * @param {node} nTable table we are using as a dataTable + * @returns {object} Settings object - or null if not found + * @memberof DataTable#oApi + */ + function _fnSettingsFromNode ( nTable ) + { + for ( var i=0 ; i<DataTable.settings.length ; i++ ) + { + if ( DataTable.settings[i].nTable === nTable ) + { + return DataTable.settings[i]; + } + } + + return null; + } + + + /** + * Return an array with the TR nodes for the table + * @param {object} oSettings dataTables settings object + * @returns {array} TR array + * @memberof DataTable#oApi + */ + function _fnGetTrNodes ( oSettings ) + { + var aNodes = []; + var aoData = oSettings.aoData; + for ( var i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + if ( aoData[i].nTr !== null ) + { + aNodes.push( aoData[i].nTr ); + } + } + return aNodes; + } + + + /** + * Return an flat array with all TD nodes for the table, or row + * @param {object} oSettings dataTables settings object + * @param {int} [iIndividualRow] aoData index to get the nodes for - optional + * if not given then the return array will contain all nodes for the table + * @returns {array} TD array + * @memberof DataTable#oApi + */ + function _fnGetTdNodes ( oSettings, iIndividualRow ) + { + var anReturn = []; + var iCorrector; + var anTds, nTd; + var iRow, iRows=oSettings.aoData.length, + iColumn, iColumns, oData, sNodeName, iStart=0, iEnd=iRows; + + /* Allow the collection to be limited to just one row */ + if ( iIndividualRow !== undefined ) + { + iStart = iIndividualRow; + iEnd = iIndividualRow+1; + } + + for ( iRow=iStart ; iRow<iEnd ; iRow++ ) + { + oData = oSettings.aoData[iRow]; + if ( oData.nTr !== null ) + { + /* get the TD child nodes - taking into account text etc nodes */ + anTds = []; + nTd = oData.nTr.firstChild; + while ( nTd ) + { + sNodeName = nTd.nodeName.toLowerCase(); + if ( sNodeName == 'td' || sNodeName == 'th' ) + { + anTds.push( nTd ); + } + nTd = nTd.nextSibling; + } + + iCorrector = 0; + for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ ) + { + if ( oSettings.aoColumns[iColumn].bVisible ) + { + anReturn.push( anTds[iColumn-iCorrector] ); + } + else + { + anReturn.push( oData._anHidden[iColumn] ); + iCorrector++; + } + } + } + } + + return anReturn; + } + + + /** + * Log an error message + * @param {object} oSettings dataTables settings object + * @param {int} iLevel log error messages, or display them to the user + * @param {string} sMesg error message + * @memberof DataTable#oApi + */ + function _fnLog( oSettings, iLevel, sMesg ) + { + var sAlert = (oSettings===null) ? + "DataTables warning: "+sMesg : + "DataTables warning (table id = '"+oSettings.sTableId+"'): "+sMesg; + + if ( iLevel === 0 ) + { + if ( DataTable.ext.sErrMode == 'alert' ) + { + alert( sAlert ); + } + else + { + throw new Error(sAlert); + } + return; + } + else if ( window.console && console.log ) + { + console.log( sAlert ); + } + } + + + /** + * See if a property is defined on one object, if so assign it to the other object + * @param {object} oRet target object + * @param {object} oSrc source object + * @param {string} sName property + * @param {string} [sMappedName] name to map too - optional, sName used if not given + * @memberof DataTable#oApi + */ + function _fnMap( oRet, oSrc, sName, sMappedName ) + { + if ( sMappedName === undefined ) + { + sMappedName = sName; + } + if ( oSrc[sName] !== undefined ) + { + oRet[sMappedName] = oSrc[sName]; + } + } + + + /** + * Extend objects - very similar to jQuery.extend, but deep copy objects, and shallow + * copy arrays. The reason we need to do this, is that we don't want to deep copy array + * init values (such as aaSorting) since the dev wouldn't be able to override them, but + * we do want to deep copy arrays. + * @param {object} oOut Object to extend + * @param {object} oExtender Object from which the properties will be applied to oOut + * @returns {object} oOut Reference, just for convenience - oOut === the return. + * @memberof DataTable#oApi + * @todo This doesn't take account of arrays inside the deep copied objects. + */ + function _fnExtend( oOut, oExtender ) + { + var val; + + for ( var prop in oExtender ) + { + if ( oExtender.hasOwnProperty(prop) ) + { + val = oExtender[prop]; + + if ( typeof oInit[prop] === 'object' && val !== null && $.isArray(val) === false ) + { + $.extend( true, oOut[prop], val ); + } + else + { + oOut[prop] = val; + } + } + } + + return oOut; + } + + + /** + * Bind an event handers to allow a click or return key to activate the callback. + * This is good for accessibility since a return on the keyboard will have the + * same effect as a click, if the element has focus. + * @param {element} n Element to bind the action to + * @param {object} oData Data object to pass to the triggered function + * @param {function} fn Callback function for when the event is triggered + * @memberof DataTable#oApi + */ + function _fnBindAction( n, oData, fn ) + { + $(n) + .bind( 'click.DT', oData, function (e) { + n.blur(); // Remove focus outline for mouse users + fn(e); + } ) + .bind( 'keypress.DT', oData, function (e){ + if ( e.which === 13 ) { + fn(e); + } } ) + .bind( 'selectstart.DT', function () { + /* Take the brutal approach to cancelling text selection */ + return false; + } ); + } + + + /** + * Register a callback function. Easily allows a callback function to be added to + * an array store of callback functions that can then all be called together. + * @param {object} oSettings dataTables settings object + * @param {string} sStore Name of the array storage for the callbacks in oSettings + * @param {function} fn Function to be called back + * @param {string} sName Identifying name for the callback (i.e. a label) + * @memberof DataTable#oApi + */ + function _fnCallbackReg( oSettings, sStore, fn, sName ) + { + if ( fn ) + { + oSettings[sStore].push( { + "fn": fn, + "sName": sName + } ); + } + } + + + /** + * Fire callback functions and trigger events. Note that the loop over the callback + * array store is done backwards! Further note that you do not want to fire off triggers + * in time sensitive applications (for example cell creation) as its slow. + * @param {object} oSettings dataTables settings object + * @param {string} sStore Name of the array storage for the callbacks in oSettings + * @param {string} sTrigger Name of the jQuery custom event to trigger. If null no trigger + * is fired + * @param {array} aArgs Array of arguments to pass to the callback function / trigger + * @memberof DataTable#oApi + */ + function _fnCallbackFire( oSettings, sStore, sTrigger, aArgs ) + { + var aoStore = oSettings[sStore]; + var aRet =[]; + + for ( var i=aoStore.length-1 ; i>=0 ; i-- ) + { + aRet.push( aoStore[i].fn.apply( oSettings.oInstance, aArgs ) ); + } + + if ( sTrigger !== null ) + { + $(oSettings.oInstance).trigger(sTrigger, aArgs); + } + + return aRet; + } + + + /** + * JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other + * library, then we use that as it is fast, safe and accurate. If the function isn't + * available then we need to built it ourselves - the inspiration for this function comes + * from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is + * not perfect and absolutely should not be used as a replacement to json2.js - but it does + * do what we need, without requiring a dependency for DataTables. + * @param {object} o JSON object to be converted + * @returns {string} JSON string + * @memberof DataTable#oApi + */ + var _fnJsonString = (window.JSON) ? JSON.stringify : function( o ) + { + /* Not an object or array */ + var sType = typeof o; + if (sType !== "object" || o === null) + { + // simple data type + if (sType === "string") + { + o = '"'+o+'"'; + } + return o+""; + } + + /* If object or array, need to recurse over it */ + var + sProp, mValue, + json = [], + bArr = $.isArray(o); + + for (sProp in o) + { + mValue = o[sProp]; + sType = typeof mValue; + + if (sType === "string") + { + mValue = '"'+mValue+'"'; + } + else if (sType === "object" && mValue !== null) + { + mValue = _fnJsonString(mValue); + } + + json.push((bArr ? "" : '"'+sProp+'":') + mValue); + } + + return (bArr ? "[" : "{") + json + (bArr ? "]" : "}"); + }; + + + /** + * From some browsers (specifically IE6/7) we need special handling to work around browser + * bugs - this function is used to detect when these workarounds are needed. + * @param {object} oSettings dataTables settings object + * @memberof DataTable#oApi + */ + function _fnBrowserDetect( oSettings ) + { + /* IE6/7 will oversize a width 100% element inside a scrolling element, to include the + * width of the scrollbar, while other browsers ensure the inner element is contained + * without forcing scrolling + */ + var n = $( + '<div style="position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden">'+ + '<div style="position:absolute; top:1px; left:1px; width:100px; overflow:scroll;">'+ + '<div id="DT_BrowserTest" style="width:100%; height:10px;"></div>'+ + '</div>'+ + '</div>')[0]; + + document.body.appendChild( n ); + oSettings.oBrowser.bScrollOversize = $('#DT_BrowserTest', n)[0].offsetWidth === 100 ? true : false; + document.body.removeChild( n ); + } + + + /** + * Perform a jQuery selector action on the table's TR elements (from the tbody) and + * return the resulting jQuery object. + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on + * @param {object} [oOpts] Optional parameters for modifying the rows to be included + * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter + * criterion ("applied") or all TR elements (i.e. no filter). + * @param {string} [oOpts.order=current] Order of the TR elements in the processed array. + * Can be either 'current', whereby the current sorting of the table is used, or + * 'original' whereby the original order the data was read into the table is used. + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page + * ("current") or not ("all"). If 'current' is given, then order is assumed to be + * 'current' and filter is 'applied', regardless of what they might be given as. + * @returns {object} jQuery object, filtered by the given selector. + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Highlight every second row + * oTable.$('tr:odd').css('backgroundColor', 'blue'); + * } ); + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Filter to rows with 'Webkit' in them, add a background colour and then + * // remove the filter, thus highlighting the 'Webkit' rows only. + * oTable.fnFilter('Webkit'); + * oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue'); + * oTable.fnFilter(''); + * } ); + */ + this.$ = function ( sSelector, oOpts ) + { + var i, iLen, a = [], tr; + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var aoData = oSettings.aoData; + var aiDisplay = oSettings.aiDisplay; + var aiDisplayMaster = oSettings.aiDisplayMaster; + + if ( !oOpts ) + { + oOpts = {}; + } + + oOpts = $.extend( {}, { + "filter": "none", // applied + "order": "current", // "original" + "page": "all" // current + }, oOpts ); + + // Current page implies that order=current and fitler=applied, since it is fairly + // senseless otherwise + if ( oOpts.page == 'current' ) + { + for ( i=oSettings._iDisplayStart, iLen=oSettings.fnDisplayEnd() ; i<iLen ; i++ ) + { + tr = aoData[ aiDisplay[i] ].nTr; + if ( tr ) + { + a.push( tr ); + } + } + } + else if ( oOpts.order == "current" && oOpts.filter == "none" ) + { + for ( i=0, iLen=aiDisplayMaster.length ; i<iLen ; i++ ) + { + tr = aoData[ aiDisplayMaster[i] ].nTr; + if ( tr ) + { + a.push( tr ); + } + } + } + else if ( oOpts.order == "current" && oOpts.filter == "applied" ) + { + for ( i=0, iLen=aiDisplay.length ; i<iLen ; i++ ) + { + tr = aoData[ aiDisplay[i] ].nTr; + if ( tr ) + { + a.push( tr ); + } + } + } + else if ( oOpts.order == "original" && oOpts.filter == "none" ) + { + for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + tr = aoData[ i ].nTr ; + if ( tr ) + { + a.push( tr ); + } + } + } + else if ( oOpts.order == "original" && oOpts.filter == "applied" ) + { + for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + tr = aoData[ i ].nTr; + if ( $.inArray( i, aiDisplay ) !== -1 && tr ) + { + a.push( tr ); + } + } + } + else + { + _fnLog( oSettings, 1, "Unknown selection options" ); + } + + /* We need to filter on the TR elements and also 'find' in their descendants + * to make the selector act like it would in a full table - so we need + * to build both results and then combine them together + */ + var jqA = $(a); + var jqTRs = jqA.filter( sSelector ); + var jqDescendants = jqA.find( sSelector ); + + return $( [].concat($.makeArray(jqTRs), $.makeArray(jqDescendants)) ); + }; + + + /** + * Almost identical to $ in operation, but in this case returns the data for the matched + * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes + * rather than any descendants, so the data can be obtained for the row/cell. If matching + * rows are found, the data returned is the original data array/object that was used to + * create the row (or a generated array if from a DOM source). + * + * This method is often useful in-combination with $ where both functions are given the + * same parameters and the array indexes will match identically. + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on + * @param {object} [oOpts] Optional parameters for modifying the rows to be included + * @param {string} [oOpts.filter=none] Select elements that meet the current filter + * criterion ("applied") or all elements (i.e. no filter). + * @param {string} [oOpts.order=current] Order of the data in the processed array. + * Can be either 'current', whereby the current sorting of the table is used, or + * 'original' whereby the original order the data was read into the table is used. + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page + * ("current") or not ("all"). If 'current' is given, then order is assumed to be + * 'current' and filter is 'applied', regardless of what they might be given as. + * @returns {array} Data for the matched elements. If any elements, as a result of the + * selector, were not TR, TD or TH elements in the DataTable, they will have a null + * entry in the array. + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Get the data from the first row in the table + * var data = oTable._('tr:first'); + * + * // Do something useful with the data + * alert( "First cell is: "+data[0] ); + * } ); + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Filter to 'Webkit' and get all data for + * oTable.fnFilter('Webkit'); + * var data = oTable._('tr', {"filter": "applied"}); + * + * // Do something with the data + * alert( data.length+" rows matched the filter" ); + * } ); + */ + this._ = function ( sSelector, oOpts ) + { + var aOut = []; + var i, iLen, iIndex; + var aTrs = this.$( sSelector, oOpts ); + + for ( i=0, iLen=aTrs.length ; i<iLen ; i++ ) + { + aOut.push( this.fnGetData(aTrs[i]) ); + } + + return aOut; + }; + + + /** + * Add a single new row or multiple rows of data to the table. Please note + * that this is suitable for client-side processing only - if you are using + * server-side processing (i.e. "bServerSide": true), then to add data, you + * must add it to the data source, i.e. the server-side, through an Ajax call. + * @param {array|object} mData The data to be added to the table. This can be: + * <ul> + * <li>1D array of data - add a single row with the data provided</li> + * <li>2D array of arrays - add multiple rows in a single call</li> + * <li>object - data object when using <i>mData</i></li> + * <li>array of objects - multiple data objects when using <i>mData</i></li> + * </ul> + * @param {bool} [bRedraw=true] redraw the table or not + * @returns {array} An array of integers, representing the list of indexes in + * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to + * the table. + * @dtopt API + * + * @example + * // Global var for counter + * var giCount = 2; + * + * $(document).ready(function() { + * $('#example').dataTable(); + * } ); + * + * function fnClickAddRow() { + * $('#example').dataTable().fnAddData( [ + * giCount+".1", + * giCount+".2", + * giCount+".3", + * giCount+".4" ] + * ); + * + * giCount++; + * } + */ + this.fnAddData = function( mData, bRedraw ) + { + if ( mData.length === 0 ) + { + return []; + } + + var aiReturn = []; + var iTest; + + /* Find settings from table node */ + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + /* Check if we want to add multiple rows or not */ + if ( typeof mData[0] === "object" && mData[0] !== null ) + { + for ( var i=0 ; i<mData.length ; i++ ) + { + iTest = _fnAddData( oSettings, mData[i] ); + if ( iTest == -1 ) + { + return aiReturn; + } + aiReturn.push( iTest ); + } + } + else + { + iTest = _fnAddData( oSettings, mData ); + if ( iTest == -1 ) + { + return aiReturn; + } + aiReturn.push( iTest ); + } + + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + + if ( bRedraw === undefined || bRedraw ) + { + _fnReDraw( oSettings ); + } + return aiReturn; + }; + + + /** + * This function will make DataTables recalculate the column sizes, based on the data + * contained in the table and the sizes applied to the columns (in the DOM, CSS or + * through the sWidth parameter). This can be useful when the width of the table's + * parent element changes (for example a window resize). + * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false + * } ); + * + * $(window).bind('resize', function () { + * oTable.fnAdjustColumnSizing(); + * } ); + * } ); + */ + this.fnAdjustColumnSizing = function ( bRedraw ) + { + var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]); + _fnAdjustColumnSizing( oSettings ); + + if ( bRedraw === undefined || bRedraw ) + { + this.fnDraw( false ); + } + else if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" ) + { + /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ + this.oApi._fnScrollDraw(oSettings); + } + }; + + + /** + * Quickly and simply clear a table + * @param {bool} [bRedraw=true] redraw the table or not + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) + * oTable.fnClearTable(); + * } ); + */ + this.fnClearTable = function( bRedraw ) + { + /* Find settings from table node */ + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + _fnClearTable( oSettings ); + + if ( bRedraw === undefined || bRedraw ) + { + _fnDraw( oSettings ); + } + }; + + + /** + * The exact opposite of 'opening' a row, this function will close any rows which + * are currently 'open'. + * @param {node} nTr the table row to 'close' + * @returns {int} 0 on success, or 1 if failed (can't find the row) + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnClose = function( nTr ) + { + /* Find settings from table node */ + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ ) + { + if ( oSettings.aoOpenRows[i].nParent == nTr ) + { + var nTrParent = oSettings.aoOpenRows[i].nTr.parentNode; + if ( nTrParent ) + { + /* Remove it if it is currently on display */ + nTrParent.removeChild( oSettings.aoOpenRows[i].nTr ); + } + oSettings.aoOpenRows.splice( i, 1 ); + return 0; + } + } + return 1; + }; + + + /** + * Remove a row for the table + * @param {mixed} mTarget The index of the row from aoData to be deleted, or + * the TR element you want to delete + * @param {function|null} [fnCallBack] Callback function + * @param {bool} [bRedraw=true] Redraw the table or not + * @returns {array} The row that was deleted + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Immediately remove the first row + * oTable.fnDeleteRow( 0 ); + * } ); + */ + this.fnDeleteRow = function( mTarget, fnCallBack, bRedraw ) + { + /* Find settings from table node */ + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var i, iLen, iAODataIndex; + + iAODataIndex = (typeof mTarget === 'object') ? + _fnNodeToDataIndex(oSettings, mTarget) : mTarget; + + /* Return the data array from this row */ + var oData = oSettings.aoData.splice( iAODataIndex, 1 ); + + /* Update the _DT_RowIndex parameter */ + for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ ) + { + if ( oSettings.aoData[i].nTr !== null ) + { + oSettings.aoData[i].nTr._DT_RowIndex = i; + } + } + + /* Remove the target row from the search array */ + var iDisplayIndex = $.inArray( iAODataIndex, oSettings.aiDisplay ); + oSettings.asDataSearch.splice( iDisplayIndex, 1 ); + + /* Delete from the display arrays */ + _fnDeleteIndex( oSettings.aiDisplayMaster, iAODataIndex ); + _fnDeleteIndex( oSettings.aiDisplay, iAODataIndex ); + + /* If there is a user callback function - call it */ + if ( typeof fnCallBack === "function" ) + { + fnCallBack.call( this, oSettings, oData ); + } + + /* Check for an 'overflow' they case for displaying the table */ + if ( oSettings._iDisplayStart >= oSettings.fnRecordsDisplay() ) + { + oSettings._iDisplayStart -= oSettings._iDisplayLength; + if ( oSettings._iDisplayStart < 0 ) + { + oSettings._iDisplayStart = 0; + } + } + + if ( bRedraw === undefined || bRedraw ) + { + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + + return oData; + }; + + + /** + * Restore the table to it's original state in the DOM by removing all of DataTables + * enhancements, alterations to the DOM structure of the table and event listeners. + * @param {boolean} [bRemove=false] Completely remove the table from the DOM + * @dtopt API + * + * @example + * $(document).ready(function() { + * // This example is fairly pointless in reality, but shows how fnDestroy can be used + * var oTable = $('#example').dataTable(); + * oTable.fnDestroy(); + * } ); + */ + this.fnDestroy = function ( bRemove ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var nOrig = oSettings.nTableWrapper.parentNode; + var nBody = oSettings.nTBody; + var i, iLen; + + bRemove = (bRemove===undefined) ? false : bRemove; + + /* Flag to note that the table is currently being destroyed - no action should be taken */ + oSettings.bDestroying = true; + + /* Fire off the destroy callbacks for plug-ins etc */ + _fnCallbackFire( oSettings, "aoDestroyCallback", "destroy", [oSettings] ); + + /* If the table is not being removed, restore the hidden columns */ + if ( !bRemove ) + { + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) + { + if ( oSettings.aoColumns[i].bVisible === false ) + { + this.fnSetColumnVis( i, true ); + } + } + } + + /* Blitz all DT events */ + $(oSettings.nTableWrapper).find('*').andSelf().unbind('.DT'); + + /* If there is an 'empty' indicator row, remove it */ + $('tbody>tr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove(); + + /* When scrolling we had to break the table up - restore it */ + if ( oSettings.nTable != oSettings.nTHead.parentNode ) + { + $(oSettings.nTable).children('thead').remove(); + oSettings.nTable.appendChild( oSettings.nTHead ); + } + + if ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode ) + { + $(oSettings.nTable).children('tfoot').remove(); + oSettings.nTable.appendChild( oSettings.nTFoot ); + } + + /* Remove the DataTables generated nodes, events and classes */ + oSettings.nTable.parentNode.removeChild( oSettings.nTable ); + $(oSettings.nTableWrapper).remove(); + + oSettings.aaSorting = []; + oSettings.aaSortingFixed = []; + _fnSortingClasses( oSettings ); + + $(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripeClasses.join(' ') ); + + $('th, td', oSettings.nTHead).removeClass( [ + oSettings.oClasses.sSortable, + oSettings.oClasses.sSortableAsc, + oSettings.oClasses.sSortableDesc, + oSettings.oClasses.sSortableNone ].join(' ') + ); + if ( oSettings.bJUI ) + { + $('th span.'+oSettings.oClasses.sSortIcon + + ', td span.'+oSettings.oClasses.sSortIcon, oSettings.nTHead).remove(); + + $('th, td', oSettings.nTHead).each( function () { + var jqWrapper = $('div.'+oSettings.oClasses.sSortJUIWrapper, this); + var kids = jqWrapper.contents(); + $(this).append( kids ); + jqWrapper.remove(); + } ); + } + + /* Add the TR elements back into the table in their original order */ + if ( !bRemove && oSettings.nTableReinsertBefore ) + { + nOrig.insertBefore( oSettings.nTable, oSettings.nTableReinsertBefore ); + } + else if ( !bRemove ) + { + nOrig.appendChild( oSettings.nTable ); + } + + for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ ) + { + if ( oSettings.aoData[i].nTr !== null ) + { + nBody.appendChild( oSettings.aoData[i].nTr ); + } + } + + /* Restore the width of the original table */ + if ( oSettings.oFeatures.bAutoWidth === true ) + { + oSettings.nTable.style.width = _fnStringToCss(oSettings.sDestroyWidth); + } + + /* If the were originally stripe classes - then we add them back here. Note + * this is not fool proof (for example if not all rows had stripe classes - but + * it's a good effort without getting carried away + */ + iLen = oSettings.asDestroyStripes.length; + if (iLen) + { + var anRows = $(nBody).children('tr'); + for ( i=0 ; i<iLen ; i++ ) + { + anRows.filter(':nth-child(' + iLen + 'n + ' + i + ')').addClass( oSettings.asDestroyStripes[i] ); + } + } + + /* Remove the settings object from the settings array */ + for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ ) + { + if ( DataTable.settings[i] == oSettings ) + { + DataTable.settings.splice( i, 1 ); + } + } + + /* End it all */ + oSettings = null; + oInit = null; + }; + + + /** + * Redraw the table + * @param {bool} [bComplete=true] Re-filter and resort (if enabled) the table before the draw. + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Re-draw the table - you wouldn't want to do it here, but it's an example :-) + * oTable.fnDraw(); + * } ); + */ + this.fnDraw = function( bComplete ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + if ( bComplete === false ) + { + _fnCalculateEnd( oSettings ); + _fnDraw( oSettings ); + } + else + { + _fnReDraw( oSettings ); + } + }; + + + /** + * Filter the input based on data + * @param {string} sInput String to filter the table on + * @param {int|null} [iColumn] Column to limit filtering to + * @param {bool} [bRegex=false] Treat as regular expression or not + * @param {bool} [bSmart=true] Perform smart filtering or not + * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) + * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sometime later - filter... + * oTable.fnFilter( 'test string' ); + * } ); + */ + this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + if ( !oSettings.oFeatures.bFilter ) + { + return; + } + + if ( bRegex === undefined || bRegex === null ) + { + bRegex = false; + } + + if ( bSmart === undefined || bSmart === null ) + { + bSmart = true; + } + + if ( bShowGlobal === undefined || bShowGlobal === null ) + { + bShowGlobal = true; + } + + if ( bCaseInsensitive === undefined || bCaseInsensitive === null ) + { + bCaseInsensitive = true; + } + + if ( iColumn === undefined || iColumn === null ) + { + /* Global filter */ + _fnFilterComplete( oSettings, { + "sSearch":sInput+"", + "bRegex": bRegex, + "bSmart": bSmart, + "bCaseInsensitive": bCaseInsensitive + }, 1 ); + + if ( bShowGlobal && oSettings.aanFeatures.f ) + { + var n = oSettings.aanFeatures.f; + for ( var i=0, iLen=n.length ; i<iLen ; i++ ) + { + // IE9 throws an 'unknown error' if document.activeElement is used + // inside an iframe or frame... + try { + if ( n[i]._DT_Input != document.activeElement ) + { + $(n[i]._DT_Input).val( sInput ); + } + } + catch ( e ) { + $(n[i]._DT_Input).val( sInput ); + } + } + } + } + else + { + /* Single column filter */ + $.extend( oSettings.aoPreSearchCols[ iColumn ], { + "sSearch": sInput+"", + "bRegex": bRegex, + "bSmart": bSmart, + "bCaseInsensitive": bCaseInsensitive + } ); + _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 ); + } + }; + + + /** + * Get the data for the whole table, an individual row or an individual cell based on the + * provided parameters. + * @param {int|node} [mRow] A TR row node, TD/TH cell node or an integer. If given as + * a TR node then the data source for the whole row will be returned. If given as a + * TD/TH cell node then iCol will be automatically calculated and the data for the + * cell returned. If given as an integer, then this is treated as the aoData internal + * data index for the row (see fnGetPosition) and the data for that row used. + * @param {int} [iCol] Optional column index that you want the data of. + * @returns {array|object|string} If mRow is undefined, then the data for all rows is + * returned. If mRow is defined, just data for that row, and is iCol is + * defined, only data for the designated cell is returned. + * @dtopt API + * + * @example + * // Row data + * $(document).ready(function() { + * oTable = $('#example').dataTable(); + * + * oTable.$('tr').click( function () { + * var data = oTable.fnGetData( this ); + * // ... do something with the array / object of data for the row + * } ); + * } ); + * + * @example + * // Individual cell data + * $(document).ready(function() { + * oTable = $('#example').dataTable(); + * + * oTable.$('td').click( function () { + * var sData = oTable.fnGetData( this ); + * alert( 'The cell clicked on had the value of '+sData ); + * } ); + * } ); + */ + this.fnGetData = function( mRow, iCol ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + if ( mRow !== undefined ) + { + var iRow = mRow; + if ( typeof mRow === 'object' ) + { + var sNode = mRow.nodeName.toLowerCase(); + if (sNode === "tr" ) + { + iRow = _fnNodeToDataIndex(oSettings, mRow); + } + else if ( sNode === "td" ) + { + iRow = _fnNodeToDataIndex(oSettings, mRow.parentNode); + iCol = _fnNodeToColumnIndex( oSettings, iRow, mRow ); + } + } + + if ( iCol !== undefined ) + { + return _fnGetCellData( oSettings, iRow, iCol, '' ); + } + return (oSettings.aoData[iRow]!==undefined) ? + oSettings.aoData[iRow]._aData : null; + } + return _fnGetDataMaster( oSettings ); + }; + + + /** + * Get an array of the TR nodes that are used in the table's body. Note that you will + * typically want to use the '$' API method in preference to this as it is more + * flexible. + * @param {int} [iRow] Optional row index for the TR element you want + * @returns {array|node} If iRow is undefined, returns an array of all TR elements + * in the table's body, or iRow is defined, just the TR element requested. + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Get the nodes from the table + * var nNodes = oTable.fnGetNodes( ); + * } ); + */ + this.fnGetNodes = function( iRow ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + if ( iRow !== undefined ) { + return (oSettings.aoData[iRow]!==undefined) ? + oSettings.aoData[iRow].nTr : null; + } + return _fnGetTrNodes( oSettings ); + }; + + + /** + * Get the array indexes of a particular cell from it's DOM element + * and column index including hidden columns + * @param {node} nNode this can either be a TR, TD or TH in the table's body + * @returns {int} If nNode is given as a TR, then a single index is returned, or + * if given as a cell, an array of [row index, column index (visible), + * column index (all)] is given. + * @dtopt API + * + * @example + * $(document).ready(function() { + * $('#example tbody td').click( function () { + * // Get the position of the current data from the node + * var aPos = oTable.fnGetPosition( this ); + * + * // Get the data array for this row + * var aData = oTable.fnGetData( aPos[0] ); + * + * // Update the data array and return the value + * aData[ aPos[1] ] = 'clicked'; + * this.innerHTML = 'clicked'; + * } ); + * + * // Init DataTables + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnGetPosition = function( nNode ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var sNodeName = nNode.nodeName.toUpperCase(); + + if ( sNodeName == "TR" ) + { + return _fnNodeToDataIndex(oSettings, nNode); + } + else if ( sNodeName == "TD" || sNodeName == "TH" ) + { + var iDataIndex = _fnNodeToDataIndex( oSettings, nNode.parentNode ); + var iColumnIndex = _fnNodeToColumnIndex( oSettings, iDataIndex, nNode ); + return [ iDataIndex, _fnColumnIndexToVisible(oSettings, iColumnIndex ), iColumnIndex ]; + } + return null; + }; + + + /** + * Check to see if a row is 'open' or not. + * @param {node} nTr the table row to check + * @returns {boolean} true if the row is currently open, false otherwise + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnIsOpen = function( nTr ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var aoOpenRows = oSettings.aoOpenRows; + + for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ ) + { + if ( oSettings.aoOpenRows[i].nParent == nTr ) + { + return true; + } + } + return false; + }; + + + /** + * This function will place a new row directly after a row which is currently + * on display on the page, with the HTML contents that is passed into the + * function. This can be used, for example, to ask for confirmation that a + * particular record should be deleted. + * @param {node} nTr The table row to 'open' + * @param {string|node|jQuery} mHtml The HTML to put into the row + * @param {string} sClass Class to give the new TD cell + * @returns {node} The row opened. Note that if the table row passed in as the + * first parameter, is not found in the table, this method will silently + * return. + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable; + * + * // 'open' an information row when a row is clicked on + * $('#example tbody tr').click( function () { + * if ( oTable.fnIsOpen(this) ) { + * oTable.fnClose( this ); + * } else { + * oTable.fnOpen( this, "Temporary row opened", "info_row" ); + * } + * } ); + * + * oTable = $('#example').dataTable(); + * } ); + */ + this.fnOpen = function( nTr, mHtml, sClass ) + { + /* Find settings from table node */ + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + + /* Check that the row given is in the table */ + var nTableRows = _fnGetTrNodes( oSettings ); + if ( $.inArray(nTr, nTableRows) === -1 ) + { + return; + } + + /* the old open one if there is one */ + this.fnClose( nTr ); + + var nNewRow = document.createElement("tr"); + var nNewCell = document.createElement("td"); + nNewRow.appendChild( nNewCell ); + nNewCell.className = sClass; + nNewCell.colSpan = _fnVisbleColumns( oSettings ); + + if (typeof mHtml === "string") + { + nNewCell.innerHTML = mHtml; + } + else + { + $(nNewCell).html( mHtml ); + } + + /* If the nTr isn't on the page at the moment - then we don't insert at the moment */ + var nTrs = $('tr', oSettings.nTBody); + if ( $.inArray(nTr, nTrs) != -1 ) + { + $(nNewRow).insertAfter(nTr); + } + + oSettings.aoOpenRows.push( { + "nTr": nNewRow, + "nParent": nTr + } ); + + return nNewRow; + }; + + + /** + * Change the pagination - provides the internal logic for pagination in a simple API + * function. With this function you can have a DataTables table go to the next, + * previous, first or last pages. + * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" + * or page number to jump to (integer), note that page 0 is the first page. + * @param {bool} [bRedraw=true] Redraw the table or not + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * oTable.fnPageChange( 'next' ); + * } ); + */ + this.fnPageChange = function ( mAction, bRedraw ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + _fnPageChange( oSettings, mAction ); + _fnCalculateEnd( oSettings ); + + if ( bRedraw === undefined || bRedraw ) + { + _fnDraw( oSettings ); + } + }; + + + /** + * Show a particular column + * @param {int} iCol The column whose display should be changed + * @param {bool} bShow Show (true) or hide (false) the column + * @param {bool} [bRedraw=true] Redraw the table or not + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Hide the second column after initialisation + * oTable.fnSetColumnVis( 1, false ); + * } ); + */ + this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var i, iLen; + var aoColumns = oSettings.aoColumns; + var aoData = oSettings.aoData; + var nTd, bAppend, iBefore; + + /* No point in doing anything if we are requesting what is already true */ + if ( aoColumns[iCol].bVisible == bShow ) + { + return; + } + + /* Show the column */ + if ( bShow ) + { + var iInsert = 0; + for ( i=0 ; i<iCol ; i++ ) + { + if ( aoColumns[i].bVisible ) + { + iInsert++; + } + } + + /* Need to decide if we should use appendChild or insertBefore */ + bAppend = (iInsert >= _fnVisbleColumns( oSettings )); + + /* Which coloumn should we be inserting before? */ + if ( !bAppend ) + { + for ( i=iCol ; i<aoColumns.length ; i++ ) + { + if ( aoColumns[i].bVisible ) + { + iBefore = i; + break; + } + } + } + + for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + if ( aoData[i].nTr !== null ) + { + if ( bAppend ) + { + aoData[i].nTr.appendChild( + aoData[i]._anHidden[iCol] + ); + } + else + { + aoData[i].nTr.insertBefore( + aoData[i]._anHidden[iCol], + _fnGetTdNodes( oSettings, i )[iBefore] ); + } + } + } + } + else + { + /* Remove a column from display */ + for ( i=0, iLen=aoData.length ; i<iLen ; i++ ) + { + if ( aoData[i].nTr !== null ) + { + nTd = _fnGetTdNodes( oSettings, i )[iCol]; + aoData[i]._anHidden[iCol] = nTd; + nTd.parentNode.removeChild( nTd ); + } + } + } + + /* Clear to set the visible flag */ + aoColumns[iCol].bVisible = bShow; + + /* Redraw the header and footer based on the new column visibility */ + _fnDrawHead( oSettings, oSettings.aoHeader ); + if ( oSettings.nTFoot ) + { + _fnDrawHead( oSettings, oSettings.aoFooter ); + } + + /* If there are any 'open' rows, then we need to alter the colspan for this col change */ + for ( i=0, iLen=oSettings.aoOpenRows.length ; i<iLen ; i++ ) + { + oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns( oSettings ); + } + + /* Do a redraw incase anything depending on the table columns needs it + * (built-in: scrolling) + */ + if ( bRedraw === undefined || bRedraw ) + { + _fnAdjustColumnSizing( oSettings ); + _fnDraw( oSettings ); + } + + _fnSaveState( oSettings ); + }; + + + /** + * Get the settings for a particular table for external manipulation + * @returns {object} DataTables settings object. See + * {@link DataTable.models.oSettings} + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * var oSettings = oTable.fnSettings(); + * + * // Show an example parameter from the settings + * alert( oSettings._iDisplayStart ); + * } ); + */ + this.fnSettings = function() + { + return _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + }; + + + /** + * Sort the table by a particular column + * @param {int} iCol the data index to sort on. Note that this will not match the + * 'display index' if you have hidden data entries + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sort immediately with columns 0 and 1 + * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); + * } ); + */ + this.fnSort = function( aaSort ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + oSettings.aaSorting = aaSort; + _fnSort( oSettings ); + }; + + + /** + * Attach a sort listener to an element for a given column + * @param {node} nNode the element to attach the sort listener to + * @param {int} iColumn the column that a click on this node will sort on + * @param {function} [fnCallback] callback function when sort is run + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * + * // Sort on column 1, when 'sorter' is clicked on + * oTable.fnSortListener( document.getElementById('sorter'), 1 ); + * } ); + */ + this.fnSortListener = function( nNode, iColumn, fnCallback ) + { + _fnSortAttachListener( _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ), nNode, iColumn, + fnCallback ); + }; + + + /** + * Update a table cell or row - this method will accept either a single value to + * update the cell with, an array of values with one element for each column or + * an object in the same format as the original data source. The function is + * self-referencing in order to make the multi column updates easier. + * @param {object|array|string} mData Data to update the cell/row with + * @param {node|int} mRow TR element you want to update or the aoData index + * @param {int} [iColumn] The column to update (not used of mData is an array or object) + * @param {bool} [bRedraw=true] Redraw the table or not + * @param {bool} [bAction=true] Perform pre-draw actions or not + * @returns {int} 0 on success, 1 on error + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell + * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row + * } ); + */ + this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) + { + var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ); + var i, iLen, sDisplay; + var iRow = (typeof mRow === 'object') ? + _fnNodeToDataIndex(oSettings, mRow) : mRow; + + if ( $.isArray(mData) && iColumn === undefined ) + { + /* Array update - update the whole row */ + oSettings.aoData[iRow]._aData = mData.slice(); + + /* Flag to the function that we are recursing */ + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false ); + } + } + else if ( $.isPlainObject(mData) && iColumn === undefined ) + { + /* Object update - update the whole row - assume the developer gets the object right */ + oSettings.aoData[iRow]._aData = $.extend( true, {}, mData ); + + for ( i=0 ; i<oSettings.aoColumns.length ; i++ ) + { + this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false ); + } + } + else + { + /* Individual cell update */ + _fnSetCellData( oSettings, iRow, iColumn, mData ); + sDisplay = _fnGetCellData( oSettings, iRow, iColumn, 'display' ); + + var oCol = oSettings.aoColumns[iColumn]; + if ( oCol.fnRender !== null ) + { + sDisplay = _fnRender( oSettings, iRow, iColumn ); + if ( oCol.bUseRendered ) + { + _fnSetCellData( oSettings, iRow, iColumn, sDisplay ); + } + } + + if ( oSettings.aoData[iRow].nTr !== null ) + { + /* Do the actual HTML update */ + _fnGetTdNodes( oSettings, iRow )[iColumn].innerHTML = sDisplay; + } + } + + /* Modify the search index for this row (strictly this is likely not needed, since fnReDraw + * will rebuild the search array - however, the redraw might be disabled by the user) + */ + var iDisplayIndex = $.inArray( iRow, oSettings.aiDisplay ); + oSettings.asDataSearch[iDisplayIndex] = _fnBuildSearchRow( + oSettings, + _fnGetRowData( oSettings, iRow, 'filter', _fnGetColumns( oSettings, 'bSearchable' ) ) + ); + + /* Perform pre-draw actions */ + if ( bAction === undefined || bAction ) + { + _fnAdjustColumnSizing( oSettings ); + } + + /* Redraw the table */ + if ( bRedraw === undefined || bRedraw ) + { + _fnReDraw( oSettings ); + } + return 0; + }; + + + /** + * Provide a common method for plug-ins to check the version of DataTables being used, in order + * to ensure compatibility. + * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the + * formats "X" and "X.Y" are also acceptable. + * @returns {boolean} true if this version of DataTables is greater or equal to the required + * version, or false if this version of DataTales is not suitable + * @method + * @dtopt API + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * alert( oTable.fnVersionCheck( '1.9.0' ) ); + * } ); + */ + this.fnVersionCheck = DataTable.ext.fnVersionCheck; + + + /* + * This is really a good bit rubbish this method of exposing the internal methods + * publicly... - To be fixed in 2.0 using methods on the prototype + */ + + + /** + * Create a wrapper function for exporting an internal functions to an external API. + * @param {string} sFunc API function name + * @returns {function} wrapped function + * @memberof DataTable#oApi + */ + function _fnExternApiFunc (sFunc) + { + return function() { + var aArgs = [_fnSettingsFromNode(this[DataTable.ext.iApiIndex])].concat( + Array.prototype.slice.call(arguments) ); + return DataTable.ext.oApi[sFunc].apply( this, aArgs ); + }; + } + + + /** + * Reference to internal functions for use by plug-in developers. Note that these + * methods are references to internal functions and are considered to be private. + * If you use these methods, be aware that they are liable to change between versions + * (check the upgrade notes). + * @namespace + */ + this.oApi = { + "_fnExternApiFunc": _fnExternApiFunc, + "_fnInitialise": _fnInitialise, + "_fnInitComplete": _fnInitComplete, + "_fnLanguageCompat": _fnLanguageCompat, + "_fnAddColumn": _fnAddColumn, + "_fnColumnOptions": _fnColumnOptions, + "_fnAddData": _fnAddData, + "_fnCreateTr": _fnCreateTr, + "_fnGatherData": _fnGatherData, + "_fnBuildHead": _fnBuildHead, + "_fnDrawHead": _fnDrawHead, + "_fnDraw": _fnDraw, + "_fnReDraw": _fnReDraw, + "_fnAjaxUpdate": _fnAjaxUpdate, + "_fnAjaxParameters": _fnAjaxParameters, + "_fnAjaxUpdateDraw": _fnAjaxUpdateDraw, + "_fnServerParams": _fnServerParams, + "_fnAddOptionsHtml": _fnAddOptionsHtml, + "_fnFeatureHtmlTable": _fnFeatureHtmlTable, + "_fnScrollDraw": _fnScrollDraw, + "_fnAdjustColumnSizing": _fnAdjustColumnSizing, + "_fnFeatureHtmlFilter": _fnFeatureHtmlFilter, + "_fnFilterComplete": _fnFilterComplete, + "_fnFilterCustom": _fnFilterCustom, + "_fnFilterColumn": _fnFilterColumn, + "_fnFilter": _fnFilter, + "_fnBuildSearchArray": _fnBuildSearchArray, + "_fnBuildSearchRow": _fnBuildSearchRow, + "_fnFilterCreateSearch": _fnFilterCreateSearch, + "_fnDataToSearch": _fnDataToSearch, + "_fnSort": _fnSort, + "_fnSortAttachListener": _fnSortAttachListener, + "_fnSortingClasses": _fnSortingClasses, + "_fnFeatureHtmlPaginate": _fnFeatureHtmlPaginate, + "_fnPageChange": _fnPageChange, + "_fnFeatureHtmlInfo": _fnFeatureHtmlInfo, + "_fnUpdateInfo": _fnUpdateInfo, + "_fnFeatureHtmlLength": _fnFeatureHtmlLength, + "_fnFeatureHtmlProcessing": _fnFeatureHtmlProcessing, + "_fnProcessingDisplay": _fnProcessingDisplay, + "_fnVisibleToColumnIndex": _fnVisibleToColumnIndex, + "_fnColumnIndexToVisible": _fnColumnIndexToVisible, + "_fnNodeToDataIndex": _fnNodeToDataIndex, + "_fnVisbleColumns": _fnVisbleColumns, + "_fnCalculateEnd": _fnCalculateEnd, + "_fnConvertToWidth": _fnConvertToWidth, + "_fnCalculateColumnWidths": _fnCalculateColumnWidths, + "_fnScrollingWidthAdjust": _fnScrollingWidthAdjust, + "_fnGetWidestNode": _fnGetWidestNode, + "_fnGetMaxLenString": _fnGetMaxLenString, + "_fnStringToCss": _fnStringToCss, + "_fnDetectType": _fnDetectType, + "_fnSettingsFromNode": _fnSettingsFromNode, + "_fnGetDataMaster": _fnGetDataMaster, + "_fnGetTrNodes": _fnGetTrNodes, + "_fnGetTdNodes": _fnGetTdNodes, + "_fnEscapeRegex": _fnEscapeRegex, + "_fnDeleteIndex": _fnDeleteIndex, + "_fnReOrderIndex": _fnReOrderIndex, + "_fnColumnOrdering": _fnColumnOrdering, + "_fnLog": _fnLog, + "_fnClearTable": _fnClearTable, + "_fnSaveState": _fnSaveState, + "_fnLoadState": _fnLoadState, + "_fnCreateCookie": _fnCreateCookie, + "_fnReadCookie": _fnReadCookie, + "_fnDetectHeader": _fnDetectHeader, + "_fnGetUniqueThs": _fnGetUniqueThs, + "_fnScrollBarWidth": _fnScrollBarWidth, + "_fnApplyToChildren": _fnApplyToChildren, + "_fnMap": _fnMap, + "_fnGetRowData": _fnGetRowData, + "_fnGetCellData": _fnGetCellData, + "_fnSetCellData": _fnSetCellData, + "_fnGetObjectDataFn": _fnGetObjectDataFn, + "_fnSetObjectDataFn": _fnSetObjectDataFn, + "_fnApplyColumnDefs": _fnApplyColumnDefs, + "_fnBindAction": _fnBindAction, + "_fnExtend": _fnExtend, + "_fnCallbackReg": _fnCallbackReg, + "_fnCallbackFire": _fnCallbackFire, + "_fnJsonString": _fnJsonString, + "_fnRender": _fnRender, + "_fnNodeToColumnIndex": _fnNodeToColumnIndex, + "_fnInfoMacros": _fnInfoMacros, + "_fnBrowserDetect": _fnBrowserDetect, + "_fnGetColumns": _fnGetColumns + }; + + $.extend( DataTable.ext.oApi, this.oApi ); + + for ( var sFunc in DataTable.ext.oApi ) + { + if ( sFunc ) + { + this[sFunc] = _fnExternApiFunc(sFunc); + } + } + + + var _that = this; + this.each(function() { + var i=0, iLen, j, jLen, k, kLen; + var sId = this.getAttribute( 'id' ); + var bInitHandedOff = false; + var bUsePassedData = false; + + + /* Sanity check */ + if ( this.nodeName.toLowerCase() != 'table' ) + { + _fnLog( null, 0, "Attempted to initialise DataTables on a node which is not a "+ + "table: "+this.nodeName ); + return; + } + + /* Check to see if we are re-initialising a table */ + for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ ) + { + /* Base check on table node */ + if ( DataTable.settings[i].nTable == this ) + { + if ( oInit === undefined || oInit.bRetrieve ) + { + return DataTable.settings[i].oInstance; + } + else if ( oInit.bDestroy ) + { + DataTable.settings[i].oInstance.fnDestroy(); + break; + } + else + { + _fnLog( DataTable.settings[i], 0, "Cannot reinitialise DataTable.\n\n"+ + "To retrieve the DataTables object for this table, pass no arguments or see "+ + "the docs for bRetrieve and bDestroy" ); + return; + } + } + + /* If the element we are initialising has the same ID as a table which was previously + * initialised, but the table nodes don't match (from before) then we destroy the old + * instance by simply deleting it. This is under the assumption that the table has been + * destroyed by other methods. Anyone using non-id selectors will need to do this manually + */ + if ( DataTable.settings[i].sTableId == this.id ) + { + DataTable.settings.splice( i, 1 ); + break; + } + } + + /* Ensure the table has an ID - required for accessibility */ + if ( sId === null || sId === "" ) + { + sId = "DataTables_Table_"+(DataTable.ext._oExternConfig.iNextUnique++); + this.id = sId; + } + + /* Create the settings object for this table and set some of the default parameters */ + var oSettings = $.extend( true, {}, DataTable.models.oSettings, { + "nTable": this, + "oApi": _that.oApi, + "oInit": oInit, + "sDestroyWidth": $(this).width(), + "sInstance": sId, + "sTableId": sId + } ); + DataTable.settings.push( oSettings ); + + // Need to add the instance after the instance after the settings object has been added + // to the settings array, so we can self reference the table instance if more than one + oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable(); + + /* Setting up the initialisation object */ + if ( !oInit ) + { + oInit = {}; + } + + // Backwards compatibility, before we apply all the defaults + if ( oInit.oLanguage ) + { + _fnLanguageCompat( oInit.oLanguage ); + } + + oInit = _fnExtend( $.extend(true, {}, DataTable.defaults), oInit ); + + // Map the initialisation options onto the settings object + _fnMap( oSettings.oFeatures, oInit, "bPaginate" ); + _fnMap( oSettings.oFeatures, oInit, "bLengthChange" ); + _fnMap( oSettings.oFeatures, oInit, "bFilter" ); + _fnMap( oSettings.oFeatures, oInit, "bSort" ); + _fnMap( oSettings.oFeatures, oInit, "bInfo" ); + _fnMap( oSettings.oFeatures, oInit, "bProcessing" ); + _fnMap( oSettings.oFeatures, oInit, "bAutoWidth" ); + _fnMap( oSettings.oFeatures, oInit, "bSortClasses" ); + _fnMap( oSettings.oFeatures, oInit, "bServerSide" ); + _fnMap( oSettings.oFeatures, oInit, "bDeferRender" ); + _fnMap( oSettings.oScroll, oInit, "sScrollX", "sX" ); + _fnMap( oSettings.oScroll, oInit, "sScrollXInner", "sXInner" ); + _fnMap( oSettings.oScroll, oInit, "sScrollY", "sY" ); + _fnMap( oSettings.oScroll, oInit, "bScrollCollapse", "bCollapse" ); + _fnMap( oSettings.oScroll, oInit, "bScrollInfinite", "bInfinite" ); + _fnMap( oSettings.oScroll, oInit, "iScrollLoadGap", "iLoadGap" ); + _fnMap( oSettings.oScroll, oInit, "bScrollAutoCss", "bAutoCss" ); + _fnMap( oSettings, oInit, "asStripeClasses" ); + _fnMap( oSettings, oInit, "asStripClasses", "asStripeClasses" ); // legacy + _fnMap( oSettings, oInit, "fnServerData" ); + _fnMap( oSettings, oInit, "fnFormatNumber" ); + _fnMap( oSettings, oInit, "sServerMethod" ); + _fnMap( oSettings, oInit, "aaSorting" ); + _fnMap( oSettings, oInit, "aaSortingFixed" ); + _fnMap( oSettings, oInit, "aLengthMenu" ); + _fnMap( oSettings, oInit, "sPaginationType" ); + _fnMap( oSettings, oInit, "sAjaxSource" ); + _fnMap( oSettings, oInit, "sAjaxDataProp" ); + _fnMap( oSettings, oInit, "iCookieDuration" ); + _fnMap( oSettings, oInit, "sCookiePrefix" ); + _fnMap( oSettings, oInit, "sDom" ); + _fnMap( oSettings, oInit, "bSortCellsTop" ); + _fnMap( oSettings, oInit, "iTabIndex" ); + _fnMap( oSettings, oInit, "oSearch", "oPreviousSearch" ); + _fnMap( oSettings, oInit, "aoSearchCols", "aoPreSearchCols" ); + _fnMap( oSettings, oInit, "iDisplayLength", "_iDisplayLength" ); + _fnMap( oSettings, oInit, "bJQueryUI", "bJUI" ); + _fnMap( oSettings, oInit, "fnCookieCallback" ); + _fnMap( oSettings, oInit, "fnStateLoad" ); + _fnMap( oSettings, oInit, "fnStateSave" ); + _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" ); + + /* Callback functions which are array driven */ + _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' ); + _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' ); + _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' ); + _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' ); + _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' ); + _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' ); + _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' ); + _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' ); + + if ( oSettings.oFeatures.bServerSide && oSettings.oFeatures.bSort && + oSettings.oFeatures.bSortClasses ) + { + /* Enable sort classes for server-side processing. Safe to do it here, since server-side + * processing must be enabled by the developer + */ + _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'server_side_sort_classes' ); + } + else if ( oSettings.oFeatures.bDeferRender ) + { + _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'defer_sort_classes' ); + } + + if ( oInit.bJQueryUI ) + { + /* Use the JUI classes object for display. You could clone the oStdClasses object if + * you want to have multiple tables with multiple independent classes + */ + $.extend( oSettings.oClasses, DataTable.ext.oJUIClasses ); + + if ( oInit.sDom === DataTable.defaults.sDom && DataTable.defaults.sDom === "lfrtip" ) + { + /* Set the DOM to use a layout suitable for jQuery UI's theming */ + oSettings.sDom = '<"H"lfr>t<"F"ip>'; + } + } + else + { + $.extend( oSettings.oClasses, DataTable.ext.oStdClasses ); + } + $(this).addClass( oSettings.oClasses.sTable ); + + /* Calculate the scroll bar width and cache it for use later on */ + if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" ) + { + oSettings.oScroll.iBarWidth = _fnScrollBarWidth(); + } + + if ( oSettings.iInitDisplayStart === undefined ) + { + /* Display start point, taking into account the save saving */ + oSettings.iInitDisplayStart = oInit.iDisplayStart; + oSettings._iDisplayStart = oInit.iDisplayStart; + } + + /* Must be done after everything which can be overridden by a cookie! */ + if ( oInit.bStateSave ) + { + oSettings.oFeatures.bStateSave = true; + _fnLoadState( oSettings, oInit ); + _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' ); + } + + if ( oInit.iDeferLoading !== null ) + { + oSettings.bDeferLoading = true; + var tmp = $.isArray( oInit.iDeferLoading ); + oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading; + oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading; + } + + if ( oInit.aaData !== null ) + { + bUsePassedData = true; + } + + /* Language definitions */ + if ( oInit.oLanguage.sUrl !== "" ) + { + /* Get the language definitions from a file - because this Ajax call makes the language + * get async to the remainder of this function we use bInitHandedOff to indicate that + * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor + */ + oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl; + $.getJSON( oSettings.oLanguage.sUrl, null, function( json ) { + _fnLanguageCompat( json ); + $.extend( true, oSettings.oLanguage, oInit.oLanguage, json ); + _fnInitialise( oSettings ); + } ); + bInitHandedOff = true; + } + else + { + $.extend( true, oSettings.oLanguage, oInit.oLanguage ); + } + + + /* + * Stripes + */ + if ( oInit.asStripeClasses === null ) + { + oSettings.asStripeClasses =[ + oSettings.oClasses.sStripeOdd, + oSettings.oClasses.sStripeEven + ]; + } + + /* Remove row stripe classes if they are already on the table row */ + iLen=oSettings.asStripeClasses.length; + oSettings.asDestroyStripes = []; + if (iLen) + { + var bStripeRemove = false; + var anRows = $(this).children('tbody').children('tr:lt(' + iLen + ')'); + for ( i=0 ; i<iLen ; i++ ) + { + if ( anRows.hasClass( oSettings.asStripeClasses[i] ) ) + { + bStripeRemove = true; + + /* Store the classes which we are about to remove so they can be re-added on destroy */ + oSettings.asDestroyStripes.push( oSettings.asStripeClasses[i] ); + } + } + + if ( bStripeRemove ) + { + anRows.removeClass( oSettings.asStripeClasses.join(' ') ); + } + } + + /* + * Columns + * See if we should load columns automatically or use defined ones + */ + var anThs = []; + var aoColumnsInit; + var nThead = this.getElementsByTagName('thead'); + if ( nThead.length !== 0 ) + { + _fnDetectHeader( oSettings.aoHeader, nThead[0] ); + anThs = _fnGetUniqueThs( oSettings ); + } + + /* If not given a column array, generate one with nulls */ + if ( oInit.aoColumns === null ) + { + aoColumnsInit = []; + for ( i=0, iLen=anThs.length ; i<iLen ; i++ ) + { + aoColumnsInit.push( null ); + } + } + else + { + aoColumnsInit = oInit.aoColumns; + } + + /* Add the columns */ + for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ ) + { + /* Short cut - use the loop to check if we have column visibility state to restore */ + if ( oInit.saved_aoColumns !== undefined && oInit.saved_aoColumns.length == iLen ) + { + if ( aoColumnsInit[i] === null ) + { + aoColumnsInit[i] = {}; + } + aoColumnsInit[i].bVisible = oInit.saved_aoColumns[i].bVisible; + } + + _fnAddColumn( oSettings, anThs ? anThs[i] : null ); + } + + /* Apply the column definitions */ + _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) { + _fnColumnOptions( oSettings, iCol, oDef ); + } ); + + + /* + * Sorting + * Check the aaSorting array + */ + for ( i=0, iLen=oSettings.aaSorting.length ; i<iLen ; i++ ) + { + if ( oSettings.aaSorting[i][0] >= oSettings.aoColumns.length ) + { + oSettings.aaSorting[i][0] = 0; + } + var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ]; + + /* Add a default sorting index */ + if ( oSettings.aaSorting[i][2] === undefined ) + { + oSettings.aaSorting[i][2] = 0; + } + + /* If aaSorting is not defined, then we use the first indicator in asSorting */ + if ( oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined ) + { + oSettings.aaSorting[i][1] = oColumn.asSorting[0]; + } + + /* Set the current sorting index based on aoColumns.asSorting */ + for ( j=0, jLen=oColumn.asSorting.length ; j<jLen ; j++ ) + { + if ( oSettings.aaSorting[i][1] == oColumn.asSorting[j] ) + { + oSettings.aaSorting[i][2] = j; + break; + } + } + } + + /* Do a first pass on the sorting classes (allows any size changes to be taken into + * account, and also will apply sorting disabled classes if disabled + */ + _fnSortingClasses( oSettings ); + + + /* + * Final init + * Cache the header, body and footer as required, creating them if needed + */ + + /* Browser support detection */ + _fnBrowserDetect( oSettings ); + + // Work around for Webkit bug 83867 - store the caption-side before removing from doc + var captions = $(this).children('caption').each( function () { + this._captionSide = $(this).css('caption-side'); + } ); + + var thead = $(this).children('thead'); + if ( thead.length === 0 ) + { + thead = [ document.createElement( 'thead' ) ]; + this.appendChild( thead[0] ); + } + oSettings.nTHead = thead[0]; + + var tbody = $(this).children('tbody'); + if ( tbody.length === 0 ) + { + tbody = [ document.createElement( 'tbody' ) ]; + this.appendChild( tbody[0] ); + } + oSettings.nTBody = tbody[0]; + oSettings.nTBody.setAttribute( "role", "alert" ); + oSettings.nTBody.setAttribute( "aria-live", "polite" ); + oSettings.nTBody.setAttribute( "aria-relevant", "all" ); + + var tfoot = $(this).children('tfoot'); + if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) + { + // If we are a scrolling table, and no footer has been given, then we need to create + // a tfoot element for the caption element to be appended to + tfoot = [ document.createElement( 'tfoot' ) ]; + this.appendChild( tfoot[0] ); + } + + if ( tfoot.length > 0 ) + { + oSettings.nTFoot = tfoot[0]; + _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot ); + } + + /* Check if there is data passing into the constructor */ + if ( bUsePassedData ) + { + for ( i=0 ; i<oInit.aaData.length ; i++ ) + { + _fnAddData( oSettings, oInit.aaData[ i ] ); + } + } + else + { + /* Grab the data from the page */ + _fnGatherData( oSettings ); + } + + /* Copy the data index array */ + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); + + /* Initialisation complete - table can be drawn */ + oSettings.bInitialised = true; + + /* Check if we need to initialise the table (it might not have been handed off to the + * language processor) + */ + if ( bInitHandedOff === false ) + { + _fnInitialise( oSettings ); + } + } ); + _that = null; + return this; + }; + + + + /** + * Provide a common method for plug-ins to check the version of DataTables being used, in order + * to ensure compatibility. + * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the + * formats "X" and "X.Y" are also acceptable. + * @returns {boolean} true if this version of DataTables is greater or equal to the required + * version, or false if this version of DataTales is not suitable + * @static + * @dtopt API-Static + * + * @example + * alert( $.fn.dataTable.fnVersionCheck( '1.9.0' ) ); + */ + DataTable.fnVersionCheck = function( sVersion ) + { + /* This is cheap, but effective */ + var fnZPad = function (Zpad, count) + { + while(Zpad.length < count) { + Zpad += '0'; + } + return Zpad; + }; + var aThis = DataTable.ext.sVersion.split('.'); + var aThat = sVersion.split('.'); + var sThis = '', sThat = ''; + + for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) + { + sThis += fnZPad( aThis[i], 3 ); + sThat += fnZPad( aThat[i], 3 ); + } + + return parseInt(sThis, 10) >= parseInt(sThat, 10); + }; + + + /** + * Check if a TABLE node is a DataTable table already or not. + * @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other + * node types can be passed in, but will always return false). + * @returns {boolean} true the table given is a DataTable, or false otherwise + * @static + * @dtopt API-Static + * + * @example + * var ex = document.getElementById('example'); + * if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) { + * $(ex).dataTable(); + * } + */ + DataTable.fnIsDataTable = function ( nTable ) + { + var o = DataTable.settings; + + for ( var i=0 ; i<o.length ; i++ ) + { + if ( o[i].nTable === nTable || o[i].nScrollHead === nTable || o[i].nScrollFoot === nTable ) + { + return true; + } + } + + return false; + }; + + + /** + * Get all DataTable tables that have been initialised - optionally you can select to + * get only currently visible tables. + * @param {boolean} [bVisible=false] Flag to indicate if you want all (default) or + * visible tables only. + * @returns {array} Array of TABLE nodes (not DataTable instances) which are DataTables + * @static + * @dtopt API-Static + * + * @example + * var table = $.fn.dataTable.fnTables(true); + * if ( table.length > 0 ) { + * $(table).dataTable().fnAdjustColumnSizing(); + * } + */ + DataTable.fnTables = function ( bVisible ) + { + var out = []; + + jQuery.each( DataTable.settings, function (i, o) { + if ( !bVisible || (bVisible === true && $(o.nTable).is(':visible')) ) + { + out.push( o.nTable ); + } + } ); + + return out; + }; + + + /** + * Version string for plug-ins to check compatibility. Allowed format is + * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and + * e are optional + * @member + * @type string + * @default Version number + */ + DataTable.version = "1.9.4"; + + /** + * Private data store, containing all of the settings objects that are created for the + * tables on a given page. + * + * Note that the <i>DataTable.settings</i> object is aliased to <i>jQuery.fn.dataTableExt</i> + * through which it may be accessed and manipulated, or <i>jQuery.fn.dataTable.settings</i>. + * @member + * @type array + * @default [] + * @private + */ + DataTable.settings = []; + + /** + * Object models container, for the various models that DataTables has available + * to it. These models define the objects that are used to hold the active state + * and configuration of the table. + * @namespace + */ + DataTable.models = {}; + + + /** + * DataTables extension options and plug-ins. This namespace acts as a collection "area" + * for plug-ins that can be used to extend the default DataTables behaviour - indeed many + * of the build in methods use this method to provide their own capabilities (sorting methods + * for example). + * + * Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed + * and modified by plug-ins. + * @namespace + */ + DataTable.models.ext = { + /** + * Plug-in filtering functions - this method of filtering is complimentary to the default + * type based filtering, and a lot more comprehensive as it allows you complete control + * over the filtering logic. Each element in this array is a function (parameters + * described below) that is called for every row in the table, and your logic decides if + * it should be included in the filtered data set or not. + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> + * <li>{array|object} Data for the row to be processed (same as the original format + * that was passed in as the data source, or an array from a DOM data source</li> + * <li>{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can + * be useful to retrieve the TR element if you need DOM interaction.</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{boolean} Include the row in the filtered result set (true) or not (false)</li> + * </ul> + * </il> + * </ul> + * @type array + * @default [] + * + * @example + * // The following example shows custom filtering being applied to the fourth column (i.e. + * // the aData[3] index) based on two input values from the end-user, matching the data in + * // a certain range. + * $.fn.dataTableExt.afnFiltering.push( + * function( oSettings, aData, iDataIndex ) { + * var iMin = document.getElementById('min').value * 1; + * var iMax = document.getElementById('max').value * 1; + * var iVersion = aData[3] == "-" ? 0 : aData[3]*1; + * if ( iMin == "" && iMax == "" ) { + * return true; + * } + * else if ( iMin == "" && iVersion < iMax ) { + * return true; + * } + * else if ( iMin < iVersion && "" == iMax ) { + * return true; + * } + * else if ( iMin < iVersion && iVersion < iMax ) { + * return true; + * } + * return false; + * } + * ); + */ + "afnFiltering": [], + + + /** + * Plug-in sorting functions - this method of sorting is complimentary to the default type + * based sorting that DataTables does automatically, allowing much greater control over the + * the data that is being used to sort a column. This is useful if you want to do sorting + * based on live data (for example the contents of an 'input' element) rather than just the + * static string that DataTables knows of. The way these plug-ins work is that you create + * an array of the values you wish to be sorted for the column in question and then return + * that array. Which pre-sorting function is run here depends on the sSortDataType parameter + * that is used for the column (if any). This is the corollary of <i>ofnSearch</i> for sort + * data. + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> + * <li>{int} Target column index</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{array} Data for the column to be sorted upon</li> + * </ul> + * </il> + * </ul> + * + * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for + * the different uses that DataTables can put the data to. Specifically <i>mData</i> when + * used as a function will give you a 'type' (sorting, filtering etc) that you can use to + * prepare the data as required for the different types. As such, this method is deprecated. + * @type array + * @default [] + * @deprecated + * + * @example + * // Updating the cached sorting information with user entered values in HTML input elements + * jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn ) + * { + * var aData = []; + * $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () { + * aData.push( this.value ); + * } ); + * return aData; + * } + */ + "afnSortData": [], + + + /** + * Feature plug-ins - This is an array of objects which describe the feature plug-ins that are + * available to DataTables. These feature plug-ins are accessible through the sDom initialisation + * option. As such, each feature plug-in must describe a function that is used to initialise + * itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name + * of the feature (sFeature). Thus the objects attached to this method must provide: + * <ul> + * <li>{function} fnInit Initialisation of the plug-in + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{node|null} The element which contains your feature. Note that the return + * may also be void if your plug-in does not require to inject any DOM elements + * into DataTables control (sDom) - for example this might be useful when + * developing a plug-in which allows table control via keyboard entry.</li> + * </ul> + * </il> + * </ul> + * </li> + * <li>{character} cFeature Character that will be matched in sDom - case sensitive</li> + * <li>{string} sFeature Feature name</li> + * </ul> + * @type array + * @default [] + * + * @example + * // How TableTools initialises itself. + * $.fn.dataTableExt.aoFeatures.push( { + * "fnInit": function( oSettings ) { + * return new TableTools( { "oDTSettings": oSettings } ); + * }, + * "cFeature": "T", + * "sFeature": "TableTools" + * } ); + */ + "aoFeatures": [], + + + /** + * Type detection plug-in functions - DataTables utilises types to define how sorting and + * filtering behave, and types can be either be defined by the developer (sType for the + * column) or they can be automatically detected by the methods in this array. The functions + * defined in the array are quite simple, taking a single parameter (the data to analyse) + * and returning the type if it is a known type, or null otherwise. + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{*} Data from the column cell to be analysed</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{string|null} Data type detected, or null if unknown (and thus pass it + * on to the other type detection functions.</li> + * </ul> + * </il> + * </ul> + * @type array + * @default [] + * + * @example + * // Currency type detection plug-in: + * jQuery.fn.dataTableExt.aTypes.push( + * function ( sData ) { + * var sValidChars = "0123456789.-"; + * var Char; + * + * // Check the numeric part + * for ( i=1 ; i<sData.length ; i++ ) { + * Char = sData.charAt(i); + * if (sValidChars.indexOf(Char) == -1) { + * return null; + * } + * } + * + * // Check prefixed by currency + * if ( sData.charAt(0) == '$' || sData.charAt(0) == '&pound;' ) { + * return 'currency'; + * } + * return null; + * } + * ); + */ + "aTypes": [], + + + /** + * Provide a common method for plug-ins to check the version of DataTables being used, + * in order to ensure compatibility. + * @type function + * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note + * that the formats "X" and "X.Y" are also acceptable. + * @returns {boolean} true if this version of DataTables is greater or equal to the + * required version, or false if this version of DataTales is not suitable + * + * @example + * $(document).ready(function() { + * var oTable = $('#example').dataTable(); + * alert( oTable.fnVersionCheck( '1.9.0' ) ); + * } ); + */ + "fnVersionCheck": DataTable.fnVersionCheck, + + + /** + * Index for what 'this' index API functions should use + * @type int + * @default 0 + */ + "iApiIndex": 0, + + + /** + * Pre-processing of filtering data plug-ins - When you assign the sType for a column + * (or have it automatically detected for you by DataTables or a type detection plug-in), + * you will typically be using this for custom sorting, but it can also be used to provide + * custom filtering by allowing you to pre-processing the data and returning the data in + * the format that should be filtered upon. This is done by adding functions this object + * with a parameter name which matches the sType for that target column. This is the + * corollary of <i>afnSortData</i> for filtering data. + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{*} Data from the column cell to be prepared for filtering</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{string|null} Formatted string that will be used for the filtering.</li> + * </ul> + * </il> + * </ul> + * + * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for + * the different uses that DataTables can put the data to. Specifically <i>mData</i> when + * used as a function will give you a 'type' (sorting, filtering etc) that you can use to + * prepare the data as required for the different types. As such, this method is deprecated. + * @type object + * @default {} + * @deprecated + * + * @example + * $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) { + * return sData.replace(/\n/g," ").replace( /<.*?>/g, "" ); + * } + */ + "ofnSearch": {}, + + + /** + * Container for all private functions in DataTables so they can be exposed externally + * @type object + * @default {} + */ + "oApi": {}, + + + /** + * Storage for the various classes that DataTables uses + * @type object + * @default {} + */ + "oStdClasses": {}, + + + /** + * Storage for the various classes that DataTables uses - jQuery UI suitable + * @type object + * @default {} + */ + "oJUIClasses": {}, + + + /** + * Pagination plug-in methods - The style and controls of the pagination can significantly + * impact on how the end user interacts with the data in your table, and DataTables allows + * the addition of pagination controls by extending this object, which can then be enabled + * through the <i>sPaginationType</i> initialisation parameter. Each pagination type that + * is added is an object (the property name of which is what <i>sPaginationType</i> refers + * to) that has two properties, both methods that are used by DataTables to update the + * control's state. + * <ul> + * <li> + * fnInit - Initialisation of the paging controls. Called only during initialisation + * of the table. It is expected that this function will add the required DOM elements + * to the page for the paging controls to work. The element pointer + * 'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging + * controls (note that this is a 2D array to allow for multiple instances of each + * DataTables DOM element). It is suggested that you add the controls to this element + * as children + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> + * <li>{node} Container into which the pagination controls must be inserted</li> + * <li>{function} Draw callback function - whenever the controls cause a page + * change, this method must be called to redraw the table.</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>No return required</li> + * </ul> + * </il> + * </ul> + * </il> + * <li> + * fnInit - This function is called whenever the paging status of the table changes and is + * typically used to update classes and/or text of the paging controls to reflex the new + * status. + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li> + * <li>{function} Draw callback function - in case you need to redraw the table again + * or attach new event listeners</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>No return required</li> + * </ul> + * </il> + * </ul> + * </il> + * </ul> + * @type object + * @default {} + * + * @example + * $.fn.dataTableExt.oPagination.four_button = { + * "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) { + * nFirst = document.createElement( 'span' ); + * nPrevious = document.createElement( 'span' ); + * nNext = document.createElement( 'span' ); + * nLast = document.createElement( 'span' ); + * + * nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) ); + * nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) ); + * nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) ); + * nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) ); + * + * nFirst.className = "paginate_button first"; + * nPrevious.className = "paginate_button previous"; + * nNext.className="paginate_button next"; + * nLast.className = "paginate_button last"; + * + * nPaging.appendChild( nFirst ); + * nPaging.appendChild( nPrevious ); + * nPaging.appendChild( nNext ); + * nPaging.appendChild( nLast ); + * + * $(nFirst).click( function () { + * oSettings.oApi._fnPageChange( oSettings, "first" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nPrevious).click( function() { + * oSettings.oApi._fnPageChange( oSettings, "previous" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nNext).click( function() { + * oSettings.oApi._fnPageChange( oSettings, "next" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nLast).click( function() { + * oSettings.oApi._fnPageChange( oSettings, "last" ); + * fnCallbackDraw( oSettings ); + * } ); + * + * $(nFirst).bind( 'selectstart', function () { return false; } ); + * $(nPrevious).bind( 'selectstart', function () { return false; } ); + * $(nNext).bind( 'selectstart', function () { return false; } ); + * $(nLast).bind( 'selectstart', function () { return false; } ); + * }, + * + * "fnUpdate": function ( oSettings, fnCallbackDraw ) { + * if ( !oSettings.aanFeatures.p ) { + * return; + * } + * + * // Loop over each instance of the pager + * var an = oSettings.aanFeatures.p; + * for ( var i=0, iLen=an.length ; i<iLen ; i++ ) { + * var buttons = an[i].getElementsByTagName('span'); + * if ( oSettings._iDisplayStart === 0 ) { + * buttons[0].className = "paginate_disabled_previous"; + * buttons[1].className = "paginate_disabled_previous"; + * } + * else { + * buttons[0].className = "paginate_enabled_previous"; + * buttons[1].className = "paginate_enabled_previous"; + * } + * + * if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) { + * buttons[2].className = "paginate_disabled_next"; + * buttons[3].className = "paginate_disabled_next"; + * } + * else { + * buttons[2].className = "paginate_enabled_next"; + * buttons[3].className = "paginate_enabled_next"; + * } + * } + * } + * }; + */ + "oPagination": {}, + + + /** + * Sorting plug-in methods - Sorting in DataTables is based on the detected type of the + * data column (you can add your own type detection functions, or override automatic + * detection using sType). With this specific type given to the column, DataTables will + * apply the required sort from the functions in the object. Each sort type must provide + * two mandatory methods, one each for ascending and descending sorting, and can optionally + * provide a pre-formatting method that will help speed up sorting by allowing DataTables + * to pre-format the sort data only once (rather than every time the actual sort functions + * are run). The two sorting functions are typical Javascript sort methods: + * <ul> + * <li> + * Function input parameters: + * <ul> + * <li>{*} Data to compare to the second parameter</li> + * <li>{*} Data to compare to the first parameter</li> + * </ul> + * </li> + * <li> + * Function return: + * <ul> + * <li>{int} Sorting match: <0 if first parameter should be sorted lower than + * the second parameter, ===0 if the two parameters are equal and >0 if + * the first parameter should be sorted height than the second parameter.</li> + * </ul> + * </il> + * </ul> + * @type object + * @default {} + * + * @example + * // Case-sensitive string sorting, with no pre-formatting method + * $.extend( $.fn.dataTableExt.oSort, { + * "string-case-asc": function(x,y) { + * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + * }, + * "string-case-desc": function(x,y) { + * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + * } + * } ); + * + * @example + * // Case-insensitive string sorting, with pre-formatting + * $.extend( $.fn.dataTableExt.oSort, { + * "string-pre": function(x) { + * return x.toLowerCase(); + * }, + * "string-asc": function(x,y) { + * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + * }, + * "string-desc": function(x,y) { + * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + * } + * } ); + */ + "oSort": {}, + + + /** + * Version string for plug-ins to check compatibility. Allowed format is + * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and + * e are optional + * @type string + * @default Version number + */ + "sVersion": DataTable.version, + + + /** + * How should DataTables report an error. Can take the value 'alert' or 'throw' + * @type string + * @default alert + */ + "sErrMode": "alert", + + + /** + * Store information for DataTables to access globally about other instances + * @namespace + * @private + */ + "_oExternConfig": { + /* int:iNextUnique - next unique number for an instance */ + "iNextUnique": 0 + } + }; + + + + + /** + * Template object for the way in which DataTables holds information about + * search information for the global filter and individual column filters. + * @namespace + */ + DataTable.models.oSearch = { + /** + * Flag to indicate if the filtering should be case insensitive or not + * @type boolean + * @default true + */ + "bCaseInsensitive": true, + + /** + * Applied search term + * @type string + * @default <i>Empty string</i> + */ + "sSearch": "", + + /** + * Flag to indicate if the search term should be interpreted as a + * regular expression (true) or not (false) and therefore and special + * regex characters escaped. + * @type boolean + * @default false + */ + "bRegex": false, + + /** + * Flag to indicate if DataTables is to use its smart filtering or not. + * @type boolean + * @default true + */ + "bSmart": true + }; + + + + + /** + * Template object for the way in which DataTables holds information about + * each individual row. This is the object format used for the settings + * aoData array. + * @namespace + */ + DataTable.models.oRow = { + /** + * TR element for the row + * @type node + * @default null + */ + "nTr": null, + + /** + * Data object from the original data source for the row. This is either + * an array if using the traditional form of DataTables, or an object if + * using mData options. The exact type will depend on the passed in + * data from the data source, or will be an array if using DOM a data + * source. + * @type array|object + * @default [] + */ + "_aData": [], + + /** + * Sorting data cache - this array is ostensibly the same length as the + * number of columns (although each index is generated only as it is + * needed), and holds the data that is used for sorting each column in the + * row. We do this cache generation at the start of the sort in order that + * the formatting of the sort data need be done only once for each cell + * per sort. This array should not be read from or written to by anything + * other than the master sorting methods. + * @type array + * @default [] + * @private + */ + "_aSortData": [], + + /** + * Array of TD elements that are cached for hidden rows, so they can be + * reinserted into the table if a column is made visible again (or to act + * as a store if a column is made hidden). Only hidden columns have a + * reference in the array. For non-hidden columns the value is either + * undefined or null. + * @type array nodes + * @default [] + * @private + */ + "_anHidden": [], + + /** + * Cache of the class name that DataTables has applied to the row, so we + * can quickly look at this variable rather than needing to do a DOM check + * on className for the nTr property. + * @type string + * @default <i>Empty string</i> + * @private + */ + "_sRowStripe": "" + }; + + + + /** + * Template object for the column information object in DataTables. This object + * is held in the settings aoColumns array and contains all the information that + * DataTables needs about each individual column. + * + * Note that this object is related to {@link DataTable.defaults.columns} + * but this one is the internal data store for DataTables's cache of columns. + * It should NOT be manipulated outside of DataTables. Any configuration should + * be done through the initialisation options. + * @namespace + */ + DataTable.models.oColumn = { + /** + * A list of the columns that sorting should occur on when this column + * is sorted. That this property is an array allows multi-column sorting + * to be defined for a column (for example first name / last name columns + * would benefit from this). The values are integers pointing to the + * columns to be sorted on (typically it will be a single integer pointing + * at itself, but that doesn't need to be the case). + * @type array + */ + "aDataSort": null, + + /** + * Define the sorting directions that are applied to the column, in sequence + * as the column is repeatedly sorted upon - i.e. the first value is used + * as the sorting direction when the column if first sorted (clicked on). + * Sort it again (click again) and it will move on to the next index. + * Repeat until loop. + * @type array + */ + "asSorting": null, + + /** + * Flag to indicate if the column is searchable, and thus should be included + * in the filtering or not. + * @type boolean + */ + "bSearchable": null, + + /** + * Flag to indicate if the column is sortable or not. + * @type boolean + */ + "bSortable": null, + + /** + * <code>Deprecated</code> When using fnRender, you have two options for what + * to do with the data, and this property serves as the switch. Firstly, you + * can have the sorting and filtering use the rendered value (true - default), + * or you can have the sorting and filtering us the original value (false). + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type boolean + * @deprecated + */ + "bUseRendered": null, + + /** + * Flag to indicate if the column is currently visible in the table or not + * @type boolean + */ + "bVisible": null, + + /** + * Flag to indicate to the type detection method if the automatic type + * detection should be used, or if a column type (sType) has been specified + * @type boolean + * @default true + * @private + */ + "_bAutoType": true, + + /** + * Developer definable function that is called whenever a cell is created (Ajax source, + * etc) or processed for input (DOM source). This can be used as a compliment to mRender + * allowing you to modify the DOM element (add background colour for example) when the + * element is available. + * @type function + * @param {element} nTd The TD node that has been created + * @param {*} sData The Data for the cell + * @param {array|object} oData The data for the whole row + * @param {int} iRow The row index for the aoData data store + * @default null + */ + "fnCreatedCell": null, + + /** + * Function to get data from a cell in a column. You should <b>never</b> + * access data directly through _aData internally in DataTables - always use + * the method attached to this property. It allows mData to function as + * required. This function is automatically assigned by the column + * initialisation method + * @type function + * @param {array|object} oData The data array/object for the array + * (i.e. aoData[]._aData) + * @param {string} sSpecific The specific data type you want to get - + * 'display', 'type' 'filter' 'sort' + * @returns {*} The data for the cell from the given row's data + * @default null + */ + "fnGetData": null, + + /** + * <code>Deprecated</code> Custom display function that will be called for the + * display of each cell in this column. + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type function + * @param {object} o Object with the following parameters: + * @param {int} o.iDataRow The row in aoData + * @param {int} o.iDataColumn The column in question + * @param {array} o.aData The data for the row in question + * @param {object} o.oSettings The settings object for this DataTables instance + * @returns {string} The string you which to use in the display + * @default null + * @deprecated + */ + "fnRender": null, + + /** + * Function to set data for a cell in the column. You should <b>never</b> + * set the data directly to _aData internally in DataTables - always use + * this method. It allows mData to function as required. This function + * is automatically assigned by the column initialisation method + * @type function + * @param {array|object} oData The data array/object for the array + * (i.e. aoData[]._aData) + * @param {*} sValue Value to set + * @default null + */ + "fnSetData": null, + + /** + * Property to read the value for the cells in the column from the data + * source array / object. If null, then the default content is used, if a + * function is given then the return from the function is used. + * @type function|int|string|null + * @default null + */ + "mData": null, + + /** + * Partner property to mData which is used (only when defined) to get + * the data - i.e. it is basically the same as mData, but without the + * 'set' option, and also the data fed to it is the result from mData. + * This is the rendering method to match the data method of mData. + * @type function|int|string|null + * @default null + */ + "mRender": null, + + /** + * Unique header TH/TD element for this column - this is what the sorting + * listener is attached to (if sorting is enabled.) + * @type node + * @default null + */ + "nTh": null, + + /** + * Unique footer TH/TD element for this column (if there is one). Not used + * in DataTables as such, but can be used for plug-ins to reference the + * footer for each column. + * @type node + * @default null + */ + "nTf": null, + + /** + * The class to apply to all TD elements in the table's TBODY for the column + * @type string + * @default null + */ + "sClass": null, + + /** + * When DataTables calculates the column widths to assign to each column, + * it finds the longest string in each column and then constructs a + * temporary table and reads the widths from that. The problem with this + * is that "mmm" is much wider then "iiii", but the latter is a longer + * string - thus the calculation can go wrong (doing it properly and putting + * it into an DOM object and measuring that is horribly(!) slow). Thus as + * a "work around" we provide this option. It will append its value to the + * text that is found to be the longest string for the column - i.e. padding. + * @type string + */ + "sContentPadding": null, + + /** + * Allows a default value to be given for a column's data, and will be used + * whenever a null data source is encountered (this can be because mData + * is set to null, or because the data source itself is null). + * @type string + * @default null + */ + "sDefaultContent": null, + + /** + * Name for the column, allowing reference to the column by name as well as + * by index (needs a lookup to work by name). + * @type string + */ + "sName": null, + + /** + * Custom sorting data type - defines which of the available plug-ins in + * afnSortData the custom sorting will use - if any is defined. + * @type string + * @default std + */ + "sSortDataType": 'std', + + /** + * Class to be applied to the header element when sorting on this column + * @type string + * @default null + */ + "sSortingClass": null, + + /** + * Class to be applied to the header element when sorting on this column - + * when jQuery UI theming is used. + * @type string + * @default null + */ + "sSortingClassJUI": null, + + /** + * Title of the column - what is seen in the TH element (nTh). + * @type string + */ + "sTitle": null, + + /** + * Column sorting and filtering type + * @type string + * @default null + */ + "sType": null, + + /** + * Width of the column + * @type string + * @default null + */ + "sWidth": null, + + /** + * Width of the column when it was first "encountered" + * @type string + * @default null + */ + "sWidthOrig": null + }; + + + + /** + * Initialisation options that can be given to DataTables at initialisation + * time. + * @namespace + */ + DataTable.defaults = { + /** + * An array of data to use for the table, passed in at initialisation which + * will be used in preference to any data which is already in the DOM. This is + * particularly useful for constructing tables purely in Javascript, for + * example with a custom Ajax call. + * @type array + * @default null + * @dtopt Option + * + * @example + * // Using a 2D array data source + * $(document).ready( function () { + * $('#example').dataTable( { + * "aaData": [ + * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'], + * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'], + * ], + * "aoColumns": [ + * { "sTitle": "Engine" }, + * { "sTitle": "Browser" }, + * { "sTitle": "Platform" }, + * { "sTitle": "Version" }, + * { "sTitle": "Grade" } + * ] + * } ); + * } ); + * + * @example + * // Using an array of objects as a data source (mData) + * $(document).ready( function () { + * $('#example').dataTable( { + * "aaData": [ + * { + * "engine": "Trident", + * "browser": "Internet Explorer 4.0", + * "platform": "Win 95+", + * "version": 4, + * "grade": "X" + * }, + * { + * "engine": "Trident", + * "browser": "Internet Explorer 5.0", + * "platform": "Win 95+", + * "version": 5, + * "grade": "C" + * } + * ], + * "aoColumns": [ + * { "sTitle": "Engine", "mData": "engine" }, + * { "sTitle": "Browser", "mData": "browser" }, + * { "sTitle": "Platform", "mData": "platform" }, + * { "sTitle": "Version", "mData": "version" }, + * { "sTitle": "Grade", "mData": "grade" } + * ] + * } ); + * } ); + */ + "aaData": null, + + + /** + * If sorting is enabled, then DataTables will perform a first pass sort on + * initialisation. You can define which column(s) the sort is performed upon, + * and the sorting direction, with this variable. The aaSorting array should + * contain an array for each column to be sorted initially containing the + * column's index and a direction string ('asc' or 'desc'). + * @type array + * @default [[0,'asc']] + * @dtopt Option + * + * @example + * // Sort by 3rd column first, and then 4th column + * $(document).ready( function() { + * $('#example').dataTable( { + * "aaSorting": [[2,'asc'], [3,'desc']] + * } ); + * } ); + * + * // No initial sorting + * $(document).ready( function() { + * $('#example').dataTable( { + * "aaSorting": [] + * } ); + * } ); + */ + "aaSorting": [[0,'asc']], + + + /** + * This parameter is basically identical to the aaSorting parameter, but + * cannot be overridden by user interaction with the table. What this means + * is that you could have a column (visible or hidden) which the sorting will + * always be forced on first - any sorting after that (from the user) will + * then be performed as required. This can be useful for grouping rows + * together. + * @type array + * @default null + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aaSortingFixed": [[0,'asc']] + * } ); + * } ) + */ + "aaSortingFixed": null, + + + /** + * This parameter allows you to readily specify the entries in the length drop + * down menu that DataTables shows when pagination is enabled. It can be + * either a 1D array of options which will be used for both the displayed + * option and the value, or a 2D array which will use the array in the first + * position as the value, and the array in the second position as the + * displayed options (useful for language strings such as 'All'). + * @type array + * @default [ 10, 25, 50, 100 ] + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]] + * } ); + * } ); + * + * @example + * // Setting the default display length as well as length menu + * // This is likely to be wanted if you remove the '10' option which + * // is the iDisplayLength default. + * $(document).ready( function() { + * $('#example').dataTable( { + * "iDisplayLength": 25, + * "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]] + * } ); + * } ); + */ + "aLengthMenu": [ 10, 25, 50, 100 ], + + + /** + * The aoColumns option in the initialisation parameter allows you to define + * details about the way individual columns behave. For a full list of + * column options that can be set, please see + * {@link DataTable.defaults.columns}. Note that if you use aoColumns to + * define your columns, you must have an entry in the array for every single + * column that you have in your table (these can be null if you don't which + * to specify any options). + * @member + */ + "aoColumns": null, + + /** + * Very similar to aoColumns, aoColumnDefs allows you to target a specific + * column, multiple columns, or all columns, using the aTargets property of + * each object in the array. This allows great flexibility when creating + * tables, as the aoColumnDefs arrays can be of any length, targeting the + * columns you specifically want. aoColumnDefs may use any of the column + * options available: {@link DataTable.defaults.columns}, but it _must_ + * have aTargets defined in each object in the array. Values in the aTargets + * array may be: + * <ul> + * <li>a string - class name will be matched on the TH for the column</li> + * <li>0 or a positive integer - column index counting from the left</li> + * <li>a negative integer - column index counting from the right</li> + * <li>the string "_all" - all columns (i.e. assign a default)</li> + * </ul> + * @member + */ + "aoColumnDefs": null, + + + /** + * Basically the same as oSearch, this parameter defines the individual column + * filtering state at initialisation time. The array must be of the same size + * as the number of columns, and each element be an object with the parameters + * "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also + * accepted and the default will be used. + * @type array + * @default [] + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoSearchCols": [ + * null, + * { "sSearch": "My filter" }, + * null, + * { "sSearch": "^[0-9]", "bEscapeRegex": false } + * ] + * } ); + * } ) + */ + "aoSearchCols": [], + + + /** + * An array of CSS classes that should be applied to displayed rows. This + * array may be of any length, and DataTables will apply each class + * sequentially, looping when required. + * @type array + * @default null <i>Will take the values determined by the oClasses.sStripe* + * options</i> + * @dtopt Option + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "asStripeClasses": [ 'strip1', 'strip2', 'strip3' ] + * } ); + * } ) + */ + "asStripeClasses": null, + + + /** + * Enable or disable automatic column width calculation. This can be disabled + * as an optimisation (it takes some time to calculate the widths) if the + * tables widths are passed in using aoColumns. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bAutoWidth": false + * } ); + * } ); + */ + "bAutoWidth": true, + + + /** + * Deferred rendering can provide DataTables with a huge speed boost when you + * are using an Ajax or JS data source for the table. This option, when set to + * true, will cause DataTables to defer the creation of the table elements for + * each row until they are needed for a draw - saving a significant amount of + * time. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/arrays.txt", + * "bDeferRender": true + * } ); + * } ); + */ + "bDeferRender": false, + + + /** + * Replace a DataTable which matches the given selector and replace it with + * one which has the properties of the new initialisation object passed. If no + * table matches the selector, then the new DataTable will be constructed as + * per normal. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false + * } ); + * + * // Some time later.... + * $('#example').dataTable( { + * "bFilter": false, + * "bDestroy": true + * } ); + * } ); + */ + "bDestroy": false, + + + /** + * Enable or disable filtering of data. Filtering in DataTables is "smart" in + * that it allows the end user to input multiple words (space separated) and + * will match a row containing those words, even if not in the order that was + * specified (this allow matching across multiple columns). Note that if you + * wish to use filtering in DataTables this must remain 'true' - to remove the + * default filtering input box and retain filtering abilities, please use + * {@link DataTable.defaults.sDom}. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bFilter": false + * } ); + * } ); + */ + "bFilter": true, + + + /** + * Enable or disable the table information display. This shows information + * about the data that is currently visible on the page, including information + * about filtered data if that action is being performed. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bInfo": false + * } ); + * } ); + */ + "bInfo": true, + + + /** + * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some + * slightly different and additional mark-up from what DataTables has + * traditionally used). + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bJQueryUI": true + * } ); + * } ); + */ + "bJQueryUI": false, + + + /** + * Allows the end user to select the size of a formatted page from a select + * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate). + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bLengthChange": false + * } ); + * } ); + */ + "bLengthChange": true, + + + /** + * Enable or disable pagination. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bPaginate": false + * } ); + * } ); + */ + "bPaginate": true, + + + /** + * Enable or disable the display of a 'processing' indicator when the table is + * being processed (e.g. a sort). This is particularly useful for tables with + * large amounts of data where it can take a noticeable amount of time to sort + * the entries. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bProcessing": true + * } ); + * } ); + */ + "bProcessing": false, + + + /** + * Retrieve the DataTables object for the given selector. Note that if the + * table has already been initialised, this parameter will cause DataTables + * to simply return the object that has already been set up - it will not take + * account of any changes you might have made to the initialisation object + * passed to DataTables (setting this parameter to true is an acknowledgement + * that you understand this). bDestroy can be used to reinitialise a table if + * you need. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * initTable(); + * tableActions(); + * } ); + * + * function initTable () + * { + * return $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false, + * "bRetrieve": true + * } ); + * } + * + * function tableActions () + * { + * var oTable = initTable(); + * // perform API operations with oTable + * } + */ + "bRetrieve": false, + + + /** + * Indicate if DataTables should be allowed to set the padding / margin + * etc for the scrolling header elements or not. Typically you will want + * this. + * @type boolean + * @default true + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bScrollAutoCss": false, + * "sScrollY": "200px" + * } ); + * } ); + */ + "bScrollAutoCss": true, + + + /** + * When vertical (y) scrolling is enabled, DataTables will force the height of + * the table's viewport to the given height at all times (useful for layout). + * However, this can look odd when filtering data down to a small data set, + * and the footer is left "floating" further down. This parameter (when + * enabled) will cause DataTables to collapse the table's viewport down when + * the result set will fit within the given Y height. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollY": "200", + * "bScrollCollapse": true + * } ); + * } ); + */ + "bScrollCollapse": false, + + + /** + * Enable infinite scrolling for DataTables (to be used in combination with + * sScrollY). Infinite scrolling means that DataTables will continually load + * data as a user scrolls through a table, which is very useful for large + * dataset. This cannot be used with pagination, which is automatically + * disabled. Note - the Scroller extra for DataTables is recommended in + * in preference to this option. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bScrollInfinite": true, + * "bScrollCollapse": true, + * "sScrollY": "200px" + * } ); + * } ); + */ + "bScrollInfinite": false, + + + /** + * Configure DataTables to use server-side processing. Note that the + * sAjaxSource parameter must also be given in order to give DataTables a + * source to obtain the required data for each draw. + * @type boolean + * @default false + * @dtopt Features + * @dtopt Server-side + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "xhr.php" + * } ); + * } ); + */ + "bServerSide": false, + + + /** + * Enable or disable sorting of columns. Sorting of individual columns can be + * disabled by the "bSortable" option for each column. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bSort": false + * } ); + * } ); + */ + "bSort": true, + + + /** + * Allows control over whether DataTables should use the top (true) unique + * cell that is found for a single column, or the bottom (false - default). + * This is useful when using complex headers. + * @type boolean + * @default false + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bSortCellsTop": true + * } ); + * } ); + */ + "bSortCellsTop": false, + + + /** + * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and + * 'sorting_3' to the columns which are currently being sorted on. This is + * presented as a feature switch as it can increase processing time (while + * classes are removed and added) so for large data sets you might want to + * turn this off. + * @type boolean + * @default true + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bSortClasses": false + * } ); + * } ); + */ + "bSortClasses": true, + + + /** + * Enable or disable state saving. When enabled a cookie will be used to save + * table display information such as pagination information, display length, + * filtering and sorting. As such when the end user reloads the page the + * display display will match what thy had previously set up. + * @type boolean + * @default false + * @dtopt Features + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "bStateSave": true + * } ); + * } ); + */ + "bStateSave": false, + + + /** + * Customise the cookie and / or the parameters being stored when using + * DataTables with state saving enabled. This function is called whenever + * the cookie is modified, and it expects a fully formed cookie string to be + * returned. Note that the data object passed in is a Javascript object which + * must be converted to a string (JSON.stringify for example). + * @type function + * @param {string} sName Name of the cookie defined by DataTables + * @param {object} oData Data to be stored in the cookie + * @param {string} sExpires Cookie expires string + * @param {string} sPath Path of the cookie to set + * @returns {string} Cookie formatted string (which should be encoded by + * using encodeURIComponent()) + * @dtopt Callbacks + * + * @example + * $(document).ready( function () { + * $('#example').dataTable( { + * "fnCookieCallback": function (sName, oData, sExpires, sPath) { + * // Customise oData or sName or whatever else here + * return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath; + * } + * } ); + * } ); + */ + "fnCookieCallback": null, + + + /** + * This function is called when a TR element is created (and all TD child + * elements have been inserted), or registered if using a DOM source, allowing + * manipulation of the TR element (adding classes etc). + * @type function + * @param {node} nRow "TR" element for the current row + * @param {array} aData Raw data array for this row + * @param {int} iDataIndex The index of this row in aoData + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnCreatedRow": function( nRow, aData, iDataIndex ) { + * // Bold the grade for all 'A' grade browsers + * if ( aData[4] == "A" ) + * { + * $('td:eq(4)', nRow).html( '<b>A</b>' ); + * } + * } + * } ); + * } ); + */ + "fnCreatedRow": null, + + + /** + * This function is called on every 'draw' event, and allows you to + * dynamically modify any aspect you want about the created DOM. + * @type function + * @param {object} oSettings DataTables settings object + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnDrawCallback": function( oSettings ) { + * alert( 'DataTables has redrawn the table' ); + * } + * } ); + * } ); + */ + "fnDrawCallback": null, + + + /** + * Identical to fnHeaderCallback() but for the table footer this function + * allows you to modify the table footer on every 'draw' even. + * @type function + * @param {node} nFoot "TR" element for the footer + * @param {array} aData Full table data (as derived from the original HTML) + * @param {int} iStart Index for the current display starting point in the + * display array + * @param {int} iEnd Index for the current display ending point in the + * display array + * @param {array int} aiDisplay Index array to translate the visual position + * to the full data array + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) { + * nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart; + * } + * } ); + * } ) + */ + "fnFooterCallback": null, + + + /** + * When rendering large numbers in the information element for the table + * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers + * to have a comma separator for the 'thousands' units (e.g. 1 million is + * rendered as "1,000,000") to help readability for the end user. This + * function will override the default method DataTables uses. + * @type function + * @member + * @param {int} iIn number to be formatted + * @returns {string} formatted string for DataTables to show the number + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnFormatNumber": function ( iIn ) { + * if ( iIn &lt; 1000 ) { + * return iIn; + * } else { + * var + * s=(iIn+""), + * a=s.split(""), out="", + * iLen=s.length; + * + * for ( var i=0 ; i&lt;iLen ; i++ ) { + * if ( i%3 === 0 &amp;&amp; i !== 0 ) { + * out = "'"+out; + * } + * out = a[iLen-i-1]+out; + * } + * } + * return out; + * }; + * } ); + * } ); + */ + "fnFormatNumber": function ( iIn ) { + if ( iIn < 1000 ) + { + // A small optimisation for what is likely to be the majority of use cases + return iIn; + } + + var s=(iIn+""), a=s.split(""), out="", iLen=s.length; + + for ( var i=0 ; i<iLen ; i++ ) + { + if ( i%3 === 0 && i !== 0 ) + { + out = this.oLanguage.sInfoThousands+out; + } + out = a[iLen-i-1]+out; + } + return out; + }, + + + /** + * This function is called on every 'draw' event, and allows you to + * dynamically modify the header row. This can be used to calculate and + * display useful information about the table. + * @type function + * @param {node} nHead "TR" element for the header + * @param {array} aData Full table data (as derived from the original HTML) + * @param {int} iStart Index for the current display starting point in the + * display array + * @param {int} iEnd Index for the current display ending point in the + * display array + * @param {array int} aiDisplay Index array to translate the visual position + * to the full data array + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnHeaderCallback": function( nHead, aData, iStart, iEnd, aiDisplay ) { + * nHead.getElementsByTagName('th')[0].innerHTML = "Displaying "+(iEnd-iStart)+" records"; + * } + * } ); + * } ) + */ + "fnHeaderCallback": null, + + + /** + * The information element can be used to convey information about the current + * state of the table. Although the internationalisation options presented by + * DataTables are quite capable of dealing with most customisations, there may + * be times where you wish to customise the string further. This callback + * allows you to do exactly that. + * @type function + * @param {object} oSettings DataTables settings object + * @param {int} iStart Starting position in data for the draw + * @param {int} iEnd End position in data for the draw + * @param {int} iMax Total number of rows in the table (regardless of + * filtering) + * @param {int} iTotal Total number of rows in the data set, after filtering + * @param {string} sPre The string that DataTables has formatted using it's + * own rules + * @returns {string} The string to be displayed in the information element. + * @dtopt Callbacks + * + * @example + * $('#example').dataTable( { + * "fnInfoCallback": function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) { + * return iStart +" to "+ iEnd; + * } + * } ); + */ + "fnInfoCallback": null, + + + /** + * Called when the table has been initialised. Normally DataTables will + * initialise sequentially and there will be no need for this function, + * however, this does not hold true when using external language information + * since that is obtained using an async XHR call. + * @type function + * @param {object} oSettings DataTables settings object + * @param {object} json The JSON object request from the server - only + * present if client-side Ajax sourced data is used + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnInitComplete": function(oSettings, json) { + * alert( 'DataTables has finished its initialisation.' ); + * } + * } ); + * } ) + */ + "fnInitComplete": null, + + + /** + * Called at the very start of each table draw and can be used to cancel the + * draw by returning false, any other return (including undefined) results in + * the full draw occurring). + * @type function + * @param {object} oSettings DataTables settings object + * @returns {boolean} False will cancel the draw, anything else (including no + * return) will allow it to complete. + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnPreDrawCallback": function( oSettings ) { + * if ( $('#test').val() == 1 ) { + * return false; + * } + * } + * } ); + * } ); + */ + "fnPreDrawCallback": null, + + + /** + * This function allows you to 'post process' each row after it have been + * generated for each table draw, but before it is rendered on screen. This + * function might be used for setting the row class name etc. + * @type function + * @param {node} nRow "TR" element for the current row + * @param {array} aData Raw data array for this row + * @param {int} iDisplayIndex The display index for the current table draw + * @param {int} iDisplayIndexFull The index of the data in the full list of + * rows (after filtering) + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) { + * // Bold the grade for all 'A' grade browsers + * if ( aData[4] == "A" ) + * { + * $('td:eq(4)', nRow).html( '<b>A</b>' ); + * } + * } + * } ); + * } ); + */ + "fnRowCallback": null, + + + /** + * This parameter allows you to override the default function which obtains + * the data from the server ($.getJSON) so something more suitable for your + * application. For example you could use POST data, or pull information from + * a Gears or AIR database. + * @type function + * @member + * @param {string} sSource HTTP source to obtain the data from (sAjaxSource) + * @param {array} aoData A key/value pair object containing the data to send + * to the server + * @param {function} fnCallback to be called on completion of the data get + * process that will draw the data on the page. + * @param {object} oSettings DataTables settings object + * @dtopt Callbacks + * @dtopt Server-side + * + * @example + * // POST data to server + * $(document).ready( function() { + * $('#example').dataTable( { + * "bProcessing": true, + * "bServerSide": true, + * "sAjaxSource": "xhr.php", + * "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) { + * oSettings.jqXHR = $.ajax( { + * "dataType": 'json', + * "type": "POST", + * "url": sSource, + * "data": aoData, + * "success": fnCallback + * } ); + * } + * } ); + * } ); + */ + "fnServerData": function ( sUrl, aoData, fnCallback, oSettings ) { + oSettings.jqXHR = $.ajax( { + "url": sUrl, + "data": aoData, + "success": function (json) { + if ( json.sError ) { + oSettings.oApi._fnLog( oSettings, 0, json.sError ); + } + + $(oSettings.oInstance).trigger('xhr', [oSettings, json]); + fnCallback( json ); + }, + "dataType": "json", + "cache": false, + "type": oSettings.sServerMethod, + "error": function (xhr, error, thrown) { + if ( error == "parsererror" ) { + oSettings.oApi._fnLog( oSettings, 0, "DataTables warning: JSON data from "+ + "server could not be parsed. This is caused by a JSON formatting error." ); + } + } + } ); + }, + + + /** + * It is often useful to send extra data to the server when making an Ajax + * request - for example custom filtering information, and this callback + * function makes it trivial to send extra information to the server. The + * passed in parameter is the data set that has been constructed by + * DataTables, and you can add to this or modify it as you require. + * @type function + * @param {array} aoData Data array (array of objects which are name/value + * pairs) that has been constructed by DataTables and will be sent to the + * server. In the case of Ajax sourced data with server-side processing + * this will be an empty array, for server-side processing there will be a + * significant number of parameters! + * @returns {undefined} Ensure that you modify the aoData array passed in, + * as this is passed by reference. + * @dtopt Callbacks + * @dtopt Server-side + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bProcessing": true, + * "bServerSide": true, + * "sAjaxSource": "scripts/server_processing.php", + * "fnServerParams": function ( aoData ) { + * aoData.push( { "name": "more_data", "value": "my_value" } ); + * } + * } ); + * } ); + */ + "fnServerParams": null, + + + /** + * Load the table state. With this function you can define from where, and how, the + * state of a table is loaded. By default DataTables will load from its state saving + * cookie, but you might wish to use local storage (HTML5) or a server-side database. + * @type function + * @member + * @param {object} oSettings DataTables settings object + * @return {object} The DataTables state object to be loaded + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoad": function (oSettings) { + * var o; + * + * // Send an Ajax request to the server to get the data. Note that + * // this is a synchronous request. + * $.ajax( { + * "url": "/state_load", + * "async": false, + * "dataType": "json", + * "success": function (json) { + * o = json; + * } + * } ); + * + * return o; + * } + * } ); + * } ); + */ + "fnStateLoad": function ( oSettings ) { + var sData = this.oApi._fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance ); + var oData; + + try { + oData = (typeof $.parseJSON === 'function') ? + $.parseJSON(sData) : eval( '('+sData+')' ); + } catch (e) { + oData = null; + } + + return oData; + }, + + + /** + * Callback which allows modification of the saved state prior to loading that state. + * This callback is called when the table is loading state from the stored data, but + * prior to the settings object being modified by the saved state. Note that for + * plug-in authors, you should use the 'stateLoadParams' event to load parameters for + * a plug-in. + * @type function + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object that is to be loaded + * @dtopt Callbacks + * + * @example + * // Remove a saved filter, so filtering is never loaded + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoadParams": function (oSettings, oData) { + * oData.oSearch.sSearch = ""; + * } + * } ); + * } ); + * + * @example + * // Disallow state loading by returning false + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoadParams": function (oSettings, oData) { + * return false; + * } + * } ); + * } ); + */ + "fnStateLoadParams": null, + + + /** + * Callback that is called when the state has been loaded from the state saving method + * and the DataTables settings object has been modified as a result of the loaded state. + * @type function + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object that was loaded + * @dtopt Callbacks + * + * @example + * // Show an alert with the filtering value that was saved + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateLoaded": function (oSettings, oData) { + * alert( 'Saved filter was: '+oData.oSearch.sSearch ); + * } + * } ); + * } ); + */ + "fnStateLoaded": null, + + + /** + * Save the table state. This function allows you to define where and how the state + * information for the table is stored - by default it will use a cookie, but you + * might want to use local storage (HTML5) or a server-side database. + * @type function + * @member + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object to be saved + * @dtopt Callbacks + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateSave": function (oSettings, oData) { + * // Send an Ajax request to the server with the state object + * $.ajax( { + * "url": "/state_save", + * "data": oData, + * "dataType": "json", + * "method": "POST" + * "success": function () {} + * } ); + * } + * } ); + * } ); + */ + "fnStateSave": function ( oSettings, oData ) { + this.oApi._fnCreateCookie( + oSettings.sCookiePrefix+oSettings.sInstance, + this.oApi._fnJsonString(oData), + oSettings.iCookieDuration, + oSettings.sCookiePrefix, + oSettings.fnCookieCallback + ); + }, + + + /** + * Callback which allows modification of the state to be saved. Called when the table + * has changed state a new state save is required. This method allows modification of + * the state saving object prior to actually doing the save, including addition or + * other state properties or modification. Note that for plug-in authors, you should + * use the 'stateSaveParams' event to save parameters for a plug-in. + * @type function + * @param {object} oSettings DataTables settings object + * @param {object} oData The state object to be saved + * @dtopt Callbacks + * + * @example + * // Remove a saved filter, so filtering is never saved + * $(document).ready( function() { + * $('#example').dataTable( { + * "bStateSave": true, + * "fnStateSaveParams": function (oSettings, oData) { + * oData.oSearch.sSearch = ""; + * } + * } ); + * } ); + */ + "fnStateSaveParams": null, + + + /** + * Duration of the cookie which is used for storing session information. This + * value is given in seconds. + * @type int + * @default 7200 <i>(2 hours)</i> + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iCookieDuration": 60*60*24; // 1 day + * } ); + * } ) + */ + "iCookieDuration": 7200, + + + /** + * When enabled DataTables will not make a request to the server for the first + * page draw - rather it will use the data already on the page (no sorting etc + * will be applied to it), thus saving on an XHR at load time. iDeferLoading + * is used to indicate that deferred loading is required, but it is also used + * to tell DataTables how many records there are in the full table (allowing + * the information element and pagination to be displayed correctly). In the case + * where a filtering is applied to the table on initial load, this can be + * indicated by giving the parameter as an array, where the first element is + * the number of records available after filtering and the second element is the + * number of records without filtering (allowing the table information element + * to be shown correctly). + * @type int | array + * @default null + * @dtopt Options + * + * @example + * // 57 records available in the table, no filtering applied + * $(document).ready( function() { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "scripts/server_processing.php", + * "iDeferLoading": 57 + * } ); + * } ); + * + * @example + * // 57 records after filtering, 100 without filtering (an initial filter applied) + * $(document).ready( function() { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "scripts/server_processing.php", + * "iDeferLoading": [ 57, 100 ], + * "oSearch": { + * "sSearch": "my_filter" + * } + * } ); + * } ); + */ + "iDeferLoading": null, + + + /** + * Number of rows to display on a single page when using pagination. If + * feature enabled (bLengthChange) then the end user will be able to override + * this to a custom setting using a pop-up menu. + * @type int + * @default 10 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iDisplayLength": 50 + * } ); + * } ) + */ + "iDisplayLength": 10, + + + /** + * Define the starting point for data display when using DataTables with + * pagination. Note that this parameter is the number of records, rather than + * the page number, so if you have 10 records per page and want to start on + * the third page, it should be "20". + * @type int + * @default 0 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iDisplayStart": 20 + * } ); + * } ) + */ + "iDisplayStart": 0, + + + /** + * The scroll gap is the amount of scrolling that is left to go before + * DataTables will load the next 'page' of data automatically. You typically + * want a gap which is big enough that the scrolling will be smooth for the + * user, while not so large that it will load more data than need. + * @type int + * @default 100 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bScrollInfinite": true, + * "bScrollCollapse": true, + * "sScrollY": "200px", + * "iScrollLoadGap": 50 + * } ); + * } ); + */ + "iScrollLoadGap": 100, + + + /** + * By default DataTables allows keyboard navigation of the table (sorting, paging, + * and filtering) by adding a tabindex attribute to the required elements. This + * allows you to tab through the controls and press the enter key to activate them. + * The tabindex is default 0, meaning that the tab follows the flow of the document. + * You can overrule this using this parameter if you wish. Use a value of -1 to + * disable built-in keyboard navigation. + * @type int + * @default 0 + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "iTabIndex": 1 + * } ); + * } ); + */ + "iTabIndex": 0, + + + /** + * All strings that DataTables uses in the user interface that it creates + * are defined in this object, allowing you to modified them individually or + * completely replace them all as required. + * @namespace + */ + "oLanguage": { + /** + * Strings that are used for WAI-ARIA labels and controls only (these are not + * actually visible on the page, but will be read by screenreaders, and thus + * must be internationalised as well). + * @namespace + */ + "oAria": { + /** + * ARIA label that is added to the table headers when the column may be + * sorted ascending by activing the column (click or return when focused). + * Note that the column header is prefixed to this string. + * @type string + * @default : activate to sort column ascending + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oAria": { + * "sSortAscending": " - click/return to sort ascending" + * } + * } + * } ); + * } ); + */ + "sSortAscending": ": activate to sort column ascending", + + /** + * ARIA label that is added to the table headers when the column may be + * sorted descending by activing the column (click or return when focused). + * Note that the column header is prefixed to this string. + * @type string + * @default : activate to sort column ascending + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oAria": { + * "sSortDescending": " - click/return to sort descending" + * } + * } + * } ); + * } ); + */ + "sSortDescending": ": activate to sort column descending" + }, + + /** + * Pagination string used by DataTables for the two built-in pagination + * control types ("two_button" and "full_numbers") + * @namespace + */ + "oPaginate": { + /** + * Text to use when using the 'full_numbers' type of pagination for the + * button to take the user to the first page. + * @type string + * @default First + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sFirst": "First page" + * } + * } + * } ); + * } ); + */ + "sFirst": "First", + + + /** + * Text to use when using the 'full_numbers' type of pagination for the + * button to take the user to the last page. + * @type string + * @default Last + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sLast": "Last page" + * } + * } + * } ); + * } ); + */ + "sLast": "Last", + + + /** + * Text to use for the 'next' pagination button (to take the user to the + * next page). + * @type string + * @default Next + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sNext": "Next page" + * } + * } + * } ); + * } ); + */ + "sNext": "Next", + + + /** + * Text to use for the 'previous' pagination button (to take the user to + * the previous page). + * @type string + * @default Previous + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "oPaginate": { + * "sPrevious": "Previous page" + * } + * } + * } ); + * } ); + */ + "sPrevious": "Previous" + }, + + /** + * This string is shown in preference to sZeroRecords when the table is + * empty of data (regardless of filtering). Note that this is an optional + * parameter - if it is not given, the value of sZeroRecords will be used + * instead (either the default or given value). + * @type string + * @default No data available in table + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sEmptyTable": "No data available in table" + * } + * } ); + * } ); + */ + "sEmptyTable": "No data available in table", + + + /** + * This string gives information to the end user about the information that + * is current on display on the page. The _START_, _END_ and _TOTAL_ + * variables are all dynamically replaced as the table display updates, and + * can be freely moved or removed as the language requirements change. + * @type string + * @default Showing _START_ to _END_ of _TOTAL_ entries + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)" + * } + * } ); + * } ); + */ + "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries", + + + /** + * Display information string for when the table is empty. Typically the + * format of this string should match sInfo. + * @type string + * @default Showing 0 to 0 of 0 entries + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoEmpty": "No entries to show" + * } + * } ); + * } ); + */ + "sInfoEmpty": "Showing 0 to 0 of 0 entries", + + + /** + * When a user filters the information in a table, this string is appended + * to the information (sInfo) to give an idea of how strong the filtering + * is. The variable _MAX_ is dynamically updated. + * @type string + * @default (filtered from _MAX_ total entries) + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoFiltered": " - filtering from _MAX_ records" + * } + * } ); + * } ); + */ + "sInfoFiltered": "(filtered from _MAX_ total entries)", + + + /** + * If can be useful to append extra information to the info string at times, + * and this variable does exactly that. This information will be appended to + * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are + * being used) at all times. + * @type string + * @default <i>Empty string</i> + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoPostFix": "All records shown are derived from real information." + * } + * } ); + * } ); + */ + "sInfoPostFix": "", + + + /** + * DataTables has a build in number formatter (fnFormatNumber) which is used + * to format large numbers that are used in the table information. By + * default a comma is used, but this can be trivially changed to any + * character you wish with this parameter. + * @type string + * @default , + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sInfoThousands": "'" + * } + * } ); + * } ); + */ + "sInfoThousands": ",", + + + /** + * Detail the action that will be taken when the drop down menu for the + * pagination length option is changed. The '_MENU_' variable is replaced + * with a default select list of 10, 25, 50 and 100, and can be replaced + * with a custom select box if required. + * @type string + * @default Show _MENU_ entries + * @dtopt Language + * + * @example + * // Language change only + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sLengthMenu": "Display _MENU_ records" + * } + * } ); + * } ); + * + * @example + * // Language and options change + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sLengthMenu": 'Display <select>'+ + * '<option value="10">10</option>'+ + * '<option value="20">20</option>'+ + * '<option value="30">30</option>'+ + * '<option value="40">40</option>'+ + * '<option value="50">50</option>'+ + * '<option value="-1">All</option>'+ + * '</select> records' + * } + * } ); + * } ); + */ + "sLengthMenu": "Show _MENU_ entries", + + + /** + * When using Ajax sourced data and during the first draw when DataTables is + * gathering the data, this message is shown in an empty row in the table to + * indicate to the end user the the data is being loaded. Note that this + * parameter is not used when loading data by server-side processing, just + * Ajax sourced data with client-side processing. + * @type string + * @default Loading... + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sLoadingRecords": "Please wait - loading..." + * } + * } ); + * } ); + */ + "sLoadingRecords": "Loading...", + + + /** + * Text which is displayed when the table is processing a user action + * (usually a sort command or similar). + * @type string + * @default Processing... + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sProcessing": "DataTables is currently busy" + * } + * } ); + * } ); + */ + "sProcessing": "Processing...", + + + /** + * Details the actions that will be taken when the user types into the + * filtering input text box. The variable "_INPUT_", if used in the string, + * is replaced with the HTML text box for the filtering input allowing + * control over where it appears in the string. If "_INPUT_" is not given + * then the input box is appended to the string automatically. + * @type string + * @default Search: + * @dtopt Language + * + * @example + * // Input text box will be appended at the end automatically + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sSearch": "Filter records:" + * } + * } ); + * } ); + * + * @example + * // Specify where the filter should appear + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sSearch": "Apply filter _INPUT_ to table" + * } + * } ); + * } ); + */ + "sSearch": "Search:", + + + /** + * All of the language information can be stored in a file on the + * server-side, which DataTables will look up if this parameter is passed. + * It must store the URL of the language file, which is in a JSON format, + * and the object has the same properties as the oLanguage object in the + * initialiser object (i.e. the above parameters). Please refer to one of + * the example language files to see how this works in action. + * @type string + * @default <i>Empty string - i.e. disabled</i> + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sUrl": "http://www.sprymedia.co.uk/dataTables/lang.txt" + * } + * } ); + * } ); + */ + "sUrl": "", + + + /** + * Text shown inside the table records when the is no information to be + * displayed after filtering. sEmptyTable is shown when there is simply no + * information in the table at all (regardless of filtering). + * @type string + * @default No matching records found + * @dtopt Language + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oLanguage": { + * "sZeroRecords": "No records to display" + * } + * } ); + * } ); + */ + "sZeroRecords": "No matching records found" + }, + + + /** + * This parameter allows you to have define the global filtering state at + * initialisation time. As an object the "sSearch" parameter must be + * defined, but all other parameters are optional. When "bRegex" is true, + * the search string will be treated as a regular expression, when false + * (default) it will be treated as a straight string. When "bSmart" + * DataTables will use it's smart filtering methods (to word match at + * any point in the data), when false this will not be done. + * @namespace + * @extends DataTable.models.oSearch + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "oSearch": {"sSearch": "Initial search"} + * } ); + * } ) + */ + "oSearch": $.extend( {}, DataTable.models.oSearch ), + + + /** + * By default DataTables will look for the property 'aaData' when obtaining + * data from an Ajax source or for server-side processing - this parameter + * allows that property to be changed. You can use Javascript dotted object + * notation to get a data source for multiple levels of nesting. + * @type string + * @default aaData + * @dtopt Options + * @dtopt Server-side + * + * @example + * // Get data from { "data": [...] } + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/data.txt", + * "sAjaxDataProp": "data" + * } ); + * } ); + * + * @example + * // Get data from { "data": { "inner": [...] } } + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/data.txt", + * "sAjaxDataProp": "data.inner" + * } ); + * } ); + */ + "sAjaxDataProp": "aaData", + + + /** + * You can instruct DataTables to load data from an external source using this + * parameter (use aData if you want to pass data in you already have). Simply + * provide a url a JSON object can be obtained from. This object must include + * the parameter 'aaData' which is the data source for the table. + * @type string + * @default null + * @dtopt Options + * @dtopt Server-side + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php" + * } ); + * } ) + */ + "sAjaxSource": null, + + + /** + * This parameter can be used to override the default prefix that DataTables + * assigns to a cookie when state saving is enabled. + * @type string + * @default SpryMedia_DataTables_ + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sCookiePrefix": "my_datatable_", + * } ); + * } ); + */ + "sCookiePrefix": "SpryMedia_DataTables_", + + + /** + * This initialisation variable allows you to specify exactly where in the + * DOM you want DataTables to inject the various controls it adds to the page + * (for example you might want the pagination controls at the top of the + * table). DIV elements (with or without a custom class) can also be added to + * aid styling. The follow syntax is used: + * <ul> + * <li>The following options are allowed: + * <ul> + * <li>'l' - Length changing</li + * <li>'f' - Filtering input</li> + * <li>'t' - The table!</li> + * <li>'i' - Information</li> + * <li>'p' - Pagination</li> + * <li>'r' - pRocessing</li> + * </ul> + * </li> + * <li>The following constants are allowed: + * <ul> + * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li> + * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li> + * </ul> + * </li> + * <li>The following syntax is expected: + * <ul> + * <li>'&lt;' and '&gt;' - div elements</li> + * <li>'&lt;"class" and '&gt;' - div with a class</li> + * <li>'&lt;"#id" and '&gt;' - div with an ID</li> + * </ul> + * </li> + * <li>Examples: + * <ul> + * <li>'&lt;"wrapper"flipt&gt;'</li> + * <li>'&lt;lf&lt;t&gt;ip&gt;'</li> + * </ul> + * </li> + * </ul> + * @type string + * @default lfrtip <i>(when bJQueryUI is false)</i> <b>or</b> + * <"H"lfr>t<"F"ip> <i>(when bJQueryUI is true)</i> + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sDom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;' + * } ); + * } ); + */ + "sDom": "lfrtip", + + + /** + * DataTables features two different built-in pagination interaction methods + * ('two_button' or 'full_numbers') which present different page controls to + * the end user. Further methods can be added using the API (see below). + * @type string + * @default two_button + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sPaginationType": "full_numbers" + * } ); + * } ) + */ + "sPaginationType": "two_button", + + + /** + * Enable horizontal scrolling. When a table is too wide to fit into a certain + * layout, or you have a large number of columns in the table, you can enable + * x-scrolling to show the table in a viewport, which can be scrolled. This + * property can be any CSS unit, or a number (in which case it will be treated + * as a pixel measurement). + * @type string + * @default <i>blank string - i.e. disabled</i> + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollX": "100%", + * "bScrollCollapse": true + * } ); + * } ); + */ + "sScrollX": "", + + + /** + * This property can be used to force a DataTable to use more width than it + * might otherwise do when x-scrolling is enabled. For example if you have a + * table which requires to be well spaced, this parameter is useful for + * "over-sizing" the table, and thus forcing scrolling. This property can by + * any CSS unit, or a number (in which case it will be treated as a pixel + * measurement). + * @type string + * @default <i>blank string - i.e. disabled</i> + * @dtopt Options + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollX": "100%", + * "sScrollXInner": "110%" + * } ); + * } ); + */ + "sScrollXInner": "", + + + /** + * Enable vertical scrolling. Vertical scrolling will constrain the DataTable + * to the given height, and enable scrolling for any data which overflows the + * current viewport. This can be used as an alternative to paging to display + * a lot of data in a small area (although paging and scrolling can both be + * enabled at the same time). This property can be any CSS unit, or a number + * (in which case it will be treated as a pixel measurement). + * @type string + * @default <i>blank string - i.e. disabled</i> + * @dtopt Features + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "sScrollY": "200px", + * "bPaginate": false + * } ); + * } ); + */ + "sScrollY": "", + + + /** + * Set the HTTP method that is used to make the Ajax call for server-side + * processing or Ajax sourced data. + * @type string + * @default GET + * @dtopt Options + * @dtopt Server-side + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "bServerSide": true, + * "sAjaxSource": "scripts/post.php", + * "sServerMethod": "POST" + * } ); + * } ); + */ + "sServerMethod": "GET" + }; + + + + /** + * Column options that can be given to DataTables at initialisation time. + * @namespace + */ + DataTable.defaults.columns = { + /** + * Allows a column's sorting to take multiple columns into account when + * doing a sort. For example first name / last name columns make sense to + * do a multi-column sort over the two columns. + * @type array + * @default null <i>Takes the value of the column index automatically</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] }, + * { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] }, + * { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "aDataSort": [ 0, 1 ] }, + * { "aDataSort": [ 1, 0 ] }, + * { "aDataSort": [ 2, 3, 4 ] }, + * null, + * null + * ] + * } ); + * } ); + */ + "aDataSort": null, + + + /** + * You can control the default sorting direction, and even alter the behaviour + * of the sort handler (i.e. only allow ascending sorting etc) using this + * parameter. + * @type array + * @default [ 'asc', 'desc' ] + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "asSorting": [ "asc" ], "aTargets": [ 1 ] }, + * { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] }, + * { "asSorting": [ "desc" ], "aTargets": [ 3 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * { "asSorting": [ "asc" ] }, + * { "asSorting": [ "desc", "asc", "asc" ] }, + * { "asSorting": [ "desc" ] }, + * null + * ] + * } ); + * } ); + */ + "asSorting": [ 'asc', 'desc' ], + + + /** + * Enable or disable filtering on the data in this column. + * @type boolean + * @default true + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "bSearchable": false, "aTargets": [ 0 ] } + * ] } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "bSearchable": false }, + * null, + * null, + * null, + * null + * ] } ); + * } ); + */ + "bSearchable": true, + + + /** + * Enable or disable sorting on this column. + * @type boolean + * @default true + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "bSortable": false, "aTargets": [ 0 ] } + * ] } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "bSortable": false }, + * null, + * null, + * null, + * null + * ] } ); + * } ); + */ + "bSortable": true, + + + /** + * <code>Deprecated</code> When using fnRender() for a column, you may wish + * to use the original data (before rendering) for sorting and filtering + * (the default is to used the rendered data that the user can see). This + * may be useful for dates etc. + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type boolean + * @default true + * @dtopt Columns + * @deprecated + */ + "bUseRendered": true, + + + /** + * Enable or disable the display of this column. + * @type boolean + * @default true + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "bVisible": false, "aTargets": [ 0 ] } + * ] } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "bVisible": false }, + * null, + * null, + * null, + * null + * ] } ); + * } ); + */ + "bVisible": true, + + + /** + * Developer definable function that is called whenever a cell is created (Ajax source, + * etc) or processed for input (DOM source). This can be used as a compliment to mRender + * allowing you to modify the DOM element (add background colour for example) when the + * element is available. + * @type function + * @param {element} nTd The TD node that has been created + * @param {*} sData The Data for the cell + * @param {array|object} oData The data for the whole row + * @param {int} iRow The row index for the aoData data store + * @param {int} iCol The column index for aoColumns + * @dtopt Columns + * + * @example + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ { + * "aTargets": [3], + * "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) { + * if ( sData == "1.7" ) { + * $(nTd).css('color', 'blue') + * } + * } + * } ] + * }); + * } ); + */ + "fnCreatedCell": null, + + + /** + * <code>Deprecated</code> Custom display function that will be called for the + * display of each cell in this column. + * + * Please note that this option has now been deprecated and will be removed + * in the next version of DataTables. Please use mRender / mData rather than + * fnRender. + * @type function + * @param {object} o Object with the following parameters: + * @param {int} o.iDataRow The row in aoData + * @param {int} o.iDataColumn The column in question + * @param {array} o.aData The data for the row in question + * @param {object} o.oSettings The settings object for this DataTables instance + * @param {object} o.mDataProp The data property used for this column + * @param {*} val The current cell value + * @returns {string} The string you which to use in the display + * @dtopt Columns + * @deprecated + */ + "fnRender": null, + + + /** + * The column index (starting from 0!) that you wish a sort to be performed + * upon when this column is selected for sorting. This can be used for sorting + * on hidden columns for example. + * @type int + * @default -1 <i>Use automatically calculated column index</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "iDataSort": 1, "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "iDataSort": 1 }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "iDataSort": -1, + + + /** + * This parameter has been replaced by mData in DataTables to ensure naming + * consistency. mDataProp can still be used, as there is backwards compatibility + * in DataTables for this option, but it is strongly recommended that you use + * mData in preference to mDataProp. + * @name DataTable.defaults.columns.mDataProp + */ + + + /** + * This property can be used to read data from any JSON data source property, + * including deeply nested objects / properties. mData can be given in a + * number of different ways which effect its behaviour: + * <ul> + * <li>integer - treated as an array index for the data source. This is the + * default that DataTables uses (incrementally increased for each column).</li> + * <li>string - read an object property from the data source. Note that you can + * use Javascript dotted notation to read deep properties / arrays from the + * data source.</li> + * <li>null - the sDefaultContent option will be used for the cell (null + * by default, so you will need to specify the default content you want - + * typically an empty string). This can be useful on generated columns such + * as edit / delete action columns.</li> + * <li>function - the function given will be executed whenever DataTables + * needs to set or get the data for a cell in the column. The function + * takes three parameters: + * <ul> + * <li>{array|object} The data source for the row</li> + * <li>{string} The type call data requested - this will be 'set' when + * setting data or 'filter', 'display', 'type', 'sort' or undefined when + * gathering data. Note that when <i>undefined</i> is given for the type + * DataTables expects to get the raw data for the object back</li> + * <li>{*} Data to set when the second parameter is 'set'.</li> + * </ul> + * The return value from the function is not required when 'set' is the type + * of call, but otherwise the return is what will be used for the data + * requested.</li> + * </ul> + * + * Note that prior to DataTables 1.9.2 mData was called mDataProp. The name change + * reflects the flexibility of this property and is consistent with the naming of + * mRender. If 'mDataProp' is given, then it will still be used by DataTables, as + * it automatically maps the old name to the new if required. + * @type string|int|function|null + * @default null <i>Use automatically calculated column index</i> + * @dtopt Columns + * + * @example + * // Read table data from objects + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/deep.txt", + * "aoColumns": [ + * { "mData": "engine" }, + * { "mData": "browser" }, + * { "mData": "platform.inner" }, + * { "mData": "platform.details.0" }, + * { "mData": "platform.details.1" } + * ] + * } ); + * } ); + * + * @example + * // Using mData as a function to provide different information for + * // sorting, filtering and display. In this case, currency (price) + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "aoColumnDefs": [ { + * "aTargets": [ 0 ], + * "mData": function ( source, type, val ) { + * if (type === 'set') { + * source.price = val; + * // Store the computed dislay and filter values for efficiency + * source.price_display = val=="" ? "" : "$"+numberFormat(val); + * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val; + * return; + * } + * else if (type === 'display') { + * return source.price_display; + * } + * else if (type === 'filter') { + * return source.price_filter; + * } + * // 'sort', 'type' and undefined all just use the integer + * return source.price; + * } + * } ] + * } ); + * } ); + */ + "mData": null, + + + /** + * This property is the rendering partner to mData and it is suggested that + * when you want to manipulate data for display (including filtering, sorting etc) + * but not altering the underlying data for the table, use this property. mData + * can actually do everything this property can and more, but this parameter is + * easier to use since there is no 'set' option. Like mData is can be given + * in a number of different ways to effect its behaviour, with the addition of + * supporting array syntax for easy outputting of arrays (including arrays of + * objects): + * <ul> + * <li>integer - treated as an array index for the data source. This is the + * default that DataTables uses (incrementally increased for each column).</li> + * <li>string - read an object property from the data source. Note that you can + * use Javascript dotted notation to read deep properties / arrays from the + * data source and also array brackets to indicate that the data reader should + * loop over the data source array. When characters are given between the array + * brackets, these characters are used to join the data source array together. + * For example: "accounts[, ].name" would result in a comma separated list with + * the 'name' value from the 'accounts' array of objects.</li> + * <li>function - the function given will be executed whenever DataTables + * needs to set or get the data for a cell in the column. The function + * takes three parameters: + * <ul> + * <li>{array|object} The data source for the row (based on mData)</li> + * <li>{string} The type call data requested - this will be 'filter', 'display', + * 'type' or 'sort'.</li> + * <li>{array|object} The full data source for the row (not based on mData)</li> + * </ul> + * The return value from the function is what will be used for the data + * requested.</li> + * </ul> + * @type string|int|function|null + * @default null <i>Use mData</i> + * @dtopt Columns + * + * @example + * // Create a comma separated list from an array of objects + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "sAjaxSource": "sources/deep.txt", + * "aoColumns": [ + * { "mData": "engine" }, + * { "mData": "browser" }, + * { + * "mData": "platform", + * "mRender": "[, ].name" + * } + * ] + * } ); + * } ); + * + * @example + * // Use as a function to create a link from the data source + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "aoColumnDefs": [ + * { + * "aTargets": [ 0 ], + * "mData": "download_link", + * "mRender": function ( data, type, full ) { + * return '<a href="'+data+'">Download</a>'; + * } + * ] + * } ); + * } ); + */ + "mRender": null, + + + /** + * Change the cell type created for the column - either TD cells or TH cells. This + * can be useful as TH cells have semantic meaning in the table body, allowing them + * to act as a header for a row (you may wish to add scope='row' to the TH elements). + * @type string + * @default td + * @dtopt Columns + * + * @example + * // Make the first column use TH cells + * $(document).ready( function() { + * var oTable = $('#example').dataTable( { + * "aoColumnDefs": [ { + * "aTargets": [ 0 ], + * "sCellType": "th" + * } ] + * } ); + * } ); + */ + "sCellType": "td", + + + /** + * Class to give to each cell in this column. + * @type string + * @default <i>Empty string</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sClass": "my_class", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sClass": "my_class" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sClass": "", + + /** + * When DataTables calculates the column widths to assign to each column, + * it finds the longest string in each column and then constructs a + * temporary table and reads the widths from that. The problem with this + * is that "mmm" is much wider then "iiii", but the latter is a longer + * string - thus the calculation can go wrong (doing it properly and putting + * it into an DOM object and measuring that is horribly(!) slow). Thus as + * a "work around" we provide this option. It will append its value to the + * text that is found to be the longest string for the column - i.e. padding. + * Generally you shouldn't need this, and it is not documented on the + * general DataTables.net documentation + * @type string + * @default <i>Empty string<i> + * @dtopt Columns + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * null, + * null, + * { + * "sContentPadding": "mmm" + * } + * ] + * } ); + * } ); + */ + "sContentPadding": "", + + + /** + * Allows a default value to be given for a column's data, and will be used + * whenever a null data source is encountered (this can be because mData + * is set to null, or because the data source itself is null). + * @type string + * @default null + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { + * "mData": null, + * "sDefaultContent": "Edit", + * "aTargets": [ -1 ] + * } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * null, + * null, + * { + * "mData": null, + * "sDefaultContent": "Edit" + * } + * ] + * } ); + * } ); + */ + "sDefaultContent": null, + + + /** + * This parameter is only used in DataTables' server-side processing. It can + * be exceptionally useful to know what columns are being displayed on the + * client side, and to map these to database fields. When defined, the names + * also allow DataTables to reorder information from the server if it comes + * back in an unexpected order (i.e. if you switch your columns around on the + * client-side, your server-side code does not also need updating). + * @type string + * @default <i>Empty string</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sName": "engine", "aTargets": [ 0 ] }, + * { "sName": "browser", "aTargets": [ 1 ] }, + * { "sName": "platform", "aTargets": [ 2 ] }, + * { "sName": "version", "aTargets": [ 3 ] }, + * { "sName": "grade", "aTargets": [ 4 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sName": "engine" }, + * { "sName": "browser" }, + * { "sName": "platform" }, + * { "sName": "version" }, + * { "sName": "grade" } + * ] + * } ); + * } ); + */ + "sName": "", + + + /** + * Defines a data source type for the sorting which can be used to read + * real-time information from the table (updating the internally cached + * version) prior to sorting. This allows sorting to occur on user editable + * elements such as form inputs. + * @type string + * @default std + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] }, + * { "sType": "numeric", "aTargets": [ 3 ] }, + * { "sSortDataType": "dom-select", "aTargets": [ 4 ] }, + * { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * null, + * null, + * { "sSortDataType": "dom-text" }, + * { "sSortDataType": "dom-text", "sType": "numeric" }, + * { "sSortDataType": "dom-select" }, + * { "sSortDataType": "dom-checkbox" } + * ] + * } ); + * } ); + */ + "sSortDataType": "std", + + + /** + * The title of this column. + * @type string + * @default null <i>Derived from the 'TH' value for this column in the + * original HTML table.</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sTitle": "My column title", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sTitle": "My column title" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sTitle": null, + + + /** + * The type allows you to specify how the data for this column will be sorted. + * Four types (string, numeric, date and html (which will strip HTML tags + * before sorting)) are currently available. Note that only date formats + * understood by Javascript's Date() object will be accepted as type date. For + * example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 'numeric', + * 'date' or 'html' (by default). Further types can be adding through + * plug-ins. + * @type string + * @default null <i>Auto-detected from raw data</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sType": "html", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sType": "html" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sType": null, + + + /** + * Defining the width of the column, this parameter may take any CSS value + * (3em, 20px etc). DataTables apples 'smart' widths to columns which have not + * been given a specific width through this interface ensuring that the table + * remains readable. + * @type string + * @default null <i>Automatic</i> + * @dtopt Columns + * + * @example + * // Using aoColumnDefs + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumnDefs": [ + * { "sWidth": "20%", "aTargets": [ 0 ] } + * ] + * } ); + * } ); + * + * @example + * // Using aoColumns + * $(document).ready( function() { + * $('#example').dataTable( { + * "aoColumns": [ + * { "sWidth": "20%" }, + * null, + * null, + * null, + * null + * ] + * } ); + * } ); + */ + "sWidth": null + }; + + + + /** + * DataTables settings object - this holds all the information needed for a + * given table, including configuration, data and current application of the + * table options. DataTables does not have a single instance for each DataTable + * with the settings attached to that instance, but rather instances of the + * DataTable "class" are created on-the-fly as needed (typically by a + * $().dataTable() call) and the settings object is then applied to that + * instance. + * + * Note that this object is related to {@link DataTable.defaults} but this + * one is the internal data store for DataTables's cache of columns. It should + * NOT be manipulated outside of DataTables. Any configuration should be done + * through the initialisation options. + * @namespace + * @todo Really should attach the settings object to individual instances so we + * don't need to create new instances on each $().dataTable() call (if the + * table already exists). It would also save passing oSettings around and + * into every single function. However, this is a very significant + * architecture change for DataTables and will almost certainly break + * backwards compatibility with older installations. This is something that + * will be done in 2.0. + */ + DataTable.models.oSettings = { + /** + * Primary features of DataTables and their enablement state. + * @namespace + */ + "oFeatures": { + + /** + * Flag to say if DataTables should automatically try to calculate the + * optimum table and columns widths (true) or not (false). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bAutoWidth": null, + + /** + * Delay the creation of TR and TD elements until they are actually + * needed by a driven page draw. This can give a significant speed + * increase for Ajax source and Javascript source data, but makes no + * difference at all fro DOM and server-side processing tables. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bDeferRender": null, + + /** + * Enable filtering on the table or not. Note that if this is disabled + * then there is no filtering at all on the table, including fnFilter. + * To just remove the filtering input use sDom and remove the 'f' option. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bFilter": null, + + /** + * Table information element (the 'Showing x of y records' div) enable + * flag. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bInfo": null, + + /** + * Present a user control allowing the end user to change the page size + * when pagination is enabled. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bLengthChange": null, + + /** + * Pagination enabled or not. Note that if this is disabled then length + * changing must also be disabled. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bPaginate": null, + + /** + * Processing indicator enable flag whenever DataTables is enacting a + * user request - typically an Ajax request for server-side processing. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bProcessing": null, + + /** + * Server-side processing enabled flag - when enabled DataTables will + * get all data from the server for every draw - there is no filtering, + * sorting or paging done on the client-side. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bServerSide": null, + + /** + * Sorting enablement flag. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bSort": null, + + /** + * Apply a class to the columns which are being sorted to provide a + * visual highlight or not. This can slow things down when enabled since + * there is a lot of DOM interaction. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bSortClasses": null, + + /** + * State saving enablement flag. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bStateSave": null + }, + + + /** + * Scrolling settings for a table. + * @namespace + */ + "oScroll": { + /** + * Indicate if DataTables should be allowed to set the padding / margin + * etc for the scrolling header elements or not. Typically you will want + * this. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bAutoCss": null, + + /** + * When the table is shorter in height than sScrollY, collapse the + * table container down to the height of the table (when true). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bCollapse": null, + + /** + * Infinite scrolling enablement flag. Now deprecated in favour of + * using the Scroller plug-in. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bInfinite": null, + + /** + * Width of the scrollbar for the web-browser's platform. Calculated + * during table initialisation. + * @type int + * @default 0 + */ + "iBarWidth": 0, + + /** + * Space (in pixels) between the bottom of the scrolling container and + * the bottom of the scrolling viewport before the next page is loaded + * when using infinite scrolling. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type int + */ + "iLoadGap": null, + + /** + * Viewport width for horizontal scrolling. Horizontal scrolling is + * disabled if an empty string. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sX": null, + + /** + * Width to expand the table to when using x-scrolling. Typically you + * should not need to use this. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @deprecated + */ + "sXInner": null, + + /** + * Viewport height for vertical scrolling. Vertical scrolling is disabled + * if an empty string. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sY": null + }, + + /** + * Language information for the table. + * @namespace + * @extends DataTable.defaults.oLanguage + */ + "oLanguage": { + /** + * Information callback function. See + * {@link DataTable.defaults.fnInfoCallback} + * @type function + * @default null + */ + "fnInfoCallback": null + }, + + /** + * Browser support parameters + * @namespace + */ + "oBrowser": { + /** + * Indicate if the browser incorrectly calculates width:100% inside a + * scrolling element (IE6/7) + * @type boolean + * @default false + */ + "bScrollOversize": false + }, + + /** + * Array referencing the nodes which are used for the features. The + * parameters of this object match what is allowed by sDom - i.e. + * <ul> + * <li>'l' - Length changing</li> + * <li>'f' - Filtering input</li> + * <li>'t' - The table!</li> + * <li>'i' - Information</li> + * <li>'p' - Pagination</li> + * <li>'r' - pRocessing</li> + * </ul> + * @type array + * @default [] + */ + "aanFeatures": [], + + /** + * Store data information - see {@link DataTable.models.oRow} for detailed + * information. + * @type array + * @default [] + */ + "aoData": [], + + /** + * Array of indexes which are in the current display (after filtering etc) + * @type array + * @default [] + */ + "aiDisplay": [], + + /** + * Array of indexes for display - no filtering + * @type array + * @default [] + */ + "aiDisplayMaster": [], + + /** + * Store information about each column that is in use + * @type array + * @default [] + */ + "aoColumns": [], + + /** + * Store information about the table's header + * @type array + * @default [] + */ + "aoHeader": [], + + /** + * Store information about the table's footer + * @type array + * @default [] + */ + "aoFooter": [], + + /** + * Search data array for regular expression searching + * @type array + * @default [] + */ + "asDataSearch": [], + + /** + * Store the applied global search information in case we want to force a + * research or compare the old search to a new one. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @namespace + * @extends DataTable.models.oSearch + */ + "oPreviousSearch": {}, + + /** + * Store the applied search for each column - see + * {@link DataTable.models.oSearch} for the format that is used for the + * filtering information for each column. + * @type array + * @default [] + */ + "aoPreSearchCols": [], + + /** + * Sorting that is applied to the table. Note that the inner arrays are + * used in the following manner: + * <ul> + * <li>Index 0 - column number</li> + * <li>Index 1 - current sorting direction</li> + * <li>Index 2 - index of asSorting for this column</li> + * </ul> + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array + * @todo These inner arrays should really be objects + */ + "aaSorting": null, + + /** + * Sorting that is always applied to the table (i.e. prefixed in front of + * aaSorting). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array|null + * @default null + */ + "aaSortingFixed": null, + + /** + * Classes to use for the striping of a table. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array + * @default [] + */ + "asStripeClasses": null, + + /** + * If restoring a table - we should restore its striping classes as well + * @type array + * @default [] + */ + "asDestroyStripes": [], + + /** + * If restoring a table - we should restore its width + * @type int + * @default 0 + */ + "sDestroyWidth": 0, + + /** + * Callback functions array for every time a row is inserted (i.e. on a draw). + * @type array + * @default [] + */ + "aoRowCallback": [], + + /** + * Callback functions for the header on each draw. + * @type array + * @default [] + */ + "aoHeaderCallback": [], + + /** + * Callback function for the footer on each draw. + * @type array + * @default [] + */ + "aoFooterCallback": [], + + /** + * Array of callback functions for draw callback functions + * @type array + * @default [] + */ + "aoDrawCallback": [], + + /** + * Array of callback functions for row created function + * @type array + * @default [] + */ + "aoRowCreatedCallback": [], + + /** + * Callback functions for just before the table is redrawn. A return of + * false will be used to cancel the draw. + * @type array + * @default [] + */ + "aoPreDrawCallback": [], + + /** + * Callback functions for when the table has been initialised. + * @type array + * @default [] + */ + "aoInitComplete": [], + + + /** + * Callbacks for modifying the settings to be stored for state saving, prior to + * saving state. + * @type array + * @default [] + */ + "aoStateSaveParams": [], + + /** + * Callbacks for modifying the settings that have been stored for state saving + * prior to using the stored values to restore the state. + * @type array + * @default [] + */ + "aoStateLoadParams": [], + + /** + * Callbacks for operating on the settings object once the saved state has been + * loaded + * @type array + * @default [] + */ + "aoStateLoaded": [], + + /** + * Cache the table ID for quick access + * @type string + * @default <i>Empty string</i> + */ + "sTableId": "", + + /** + * The TABLE node for the main table + * @type node + * @default null + */ + "nTable": null, + + /** + * Permanent ref to the thead element + * @type node + * @default null + */ + "nTHead": null, + + /** + * Permanent ref to the tfoot element - if it exists + * @type node + * @default null + */ + "nTFoot": null, + + /** + * Permanent ref to the tbody element + * @type node + * @default null + */ + "nTBody": null, + + /** + * Cache the wrapper node (contains all DataTables controlled elements) + * @type node + * @default null + */ + "nTableWrapper": null, + + /** + * Indicate if when using server-side processing the loading of data + * should be deferred until the second draw. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + * @default false + */ + "bDeferLoading": false, + + /** + * Indicate if all required information has been read in + * @type boolean + * @default false + */ + "bInitialised": false, + + /** + * Information about open rows. Each object in the array has the parameters + * 'nTr' and 'nParent' + * @type array + * @default [] + */ + "aoOpenRows": [], + + /** + * Dictate the positioning of DataTables' control elements - see + * {@link DataTable.model.oInit.sDom}. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default null + */ + "sDom": null, + + /** + * Which type of pagination should be used. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default two_button + */ + "sPaginationType": "two_button", + + /** + * The cookie duration (for bStateSave) in seconds. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type int + * @default 0 + */ + "iCookieDuration": 0, + + /** + * The cookie name prefix. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default <i>Empty string</i> + */ + "sCookiePrefix": "", + + /** + * Callback function for cookie creation. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type function + * @default null + */ + "fnCookieCallback": null, + + /** + * Array of callback functions for state saving. Each array element is an + * object with the following parameters: + * <ul> + * <li>function:fn - function to call. Takes two parameters, oSettings + * and the JSON string to save that has been thus far created. Returns + * a JSON string to be inserted into a json object + * (i.e. '"param": [ 0, 1, 2]')</li> + * <li>string:sName - name of callback</li> + * </ul> + * @type array + * @default [] + */ + "aoStateSave": [], + + /** + * Array of callback functions for state loading. Each array element is an + * object with the following parameters: + * <ul> + * <li>function:fn - function to call. Takes two parameters, oSettings + * and the object stored. May return false to cancel state loading</li> + * <li>string:sName - name of callback</li> + * </ul> + * @type array + * @default [] + */ + "aoStateLoad": [], + + /** + * State that was loaded from the cookie. Useful for back reference + * @type object + * @default null + */ + "oLoadedState": null, + + /** + * Source url for AJAX data for the table. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + * @default null + */ + "sAjaxSource": null, + + /** + * Property from a given object from which to read the table data from. This + * can be an empty string (when not server-side processing), in which case + * it is assumed an an array is given directly. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sAjaxDataProp": null, + + /** + * Note if draw should be blocked while getting data + * @type boolean + * @default true + */ + "bAjaxDataGet": true, + + /** + * The last jQuery XHR object that was used for server-side data gathering. + * This can be used for working with the XHR information in one of the + * callbacks + * @type object + * @default null + */ + "jqXHR": null, + + /** + * Function to get the server-side data. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type function + */ + "fnServerData": null, + + /** + * Functions which are called prior to sending an Ajax request so extra + * parameters can easily be sent to the server + * @type array + * @default [] + */ + "aoServerParams": [], + + /** + * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if + * required). + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type string + */ + "sServerMethod": null, + + /** + * Format numbers for display. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type function + */ + "fnFormatNumber": null, + + /** + * List of options that can be used for the user selectable length menu. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type array + * @default [] + */ + "aLengthMenu": null, + + /** + * Counter for the draws that the table does. Also used as a tracker for + * server-side processing + * @type int + * @default 0 + */ + "iDraw": 0, + + /** + * Indicate if a redraw is being done - useful for Ajax + * @type boolean + * @default false + */ + "bDrawing": false, + + /** + * Draw index (iDraw) of the last error when parsing the returned data + * @type int + * @default -1 + */ + "iDrawError": -1, + + /** + * Paging display length + * @type int + * @default 10 + */ + "_iDisplayLength": 10, + + /** + * Paging start point - aiDisplay index + * @type int + * @default 0 + */ + "_iDisplayStart": 0, + + /** + * Paging end point - aiDisplay index. Use fnDisplayEnd rather than + * this property to get the end point + * @type int + * @default 10 + * @private + */ + "_iDisplayEnd": 10, + + /** + * Server-side processing - number of records in the result set + * (i.e. before filtering), Use fnRecordsTotal rather than + * this property to get the value of the number of records, regardless of + * the server-side processing setting. + * @type int + * @default 0 + * @private + */ + "_iRecordsTotal": 0, + + /** + * Server-side processing - number of records in the current display set + * (i.e. after filtering). Use fnRecordsDisplay rather than + * this property to get the value of the number of records, regardless of + * the server-side processing setting. + * @type boolean + * @default 0 + * @private + */ + "_iRecordsDisplay": 0, + + /** + * Flag to indicate if jQuery UI marking and classes should be used. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bJUI": null, + + /** + * The classes to use for the table + * @type object + * @default {} + */ + "oClasses": {}, + + /** + * Flag attached to the settings object so you can check in the draw + * callback if filtering has been done in the draw. Deprecated in favour of + * events. + * @type boolean + * @default false + * @deprecated + */ + "bFiltered": false, + + /** + * Flag attached to the settings object so you can check in the draw + * callback if sorting has been done in the draw. Deprecated in favour of + * events. + * @type boolean + * @default false + * @deprecated + */ + "bSorted": false, + + /** + * Indicate that if multiple rows are in the header and there is more than + * one unique cell per column, if the top one (true) or bottom one (false) + * should be used for sorting / title by DataTables. + * Note that this parameter will be set by the initialisation routine. To + * set a default use {@link DataTable.defaults}. + * @type boolean + */ + "bSortCellsTop": null, + + /** + * Initialisation object that is used for the table + * @type object + * @default null + */ + "oInit": null, + + /** + * Destroy callback functions - for plug-ins to attach themselves to the + * destroy so they can clean up markup and events. + * @type array + * @default [] + */ + "aoDestroyCallback": [], + + + /** + * Get the number of records in the current record set, before filtering + * @type function + */ + "fnRecordsTotal": function () + { + if ( this.oFeatures.bServerSide ) { + return parseInt(this._iRecordsTotal, 10); + } else { + return this.aiDisplayMaster.length; + } + }, + + /** + * Get the number of records in the current record set, after filtering + * @type function + */ + "fnRecordsDisplay": function () + { + if ( this.oFeatures.bServerSide ) { + return parseInt(this._iRecordsDisplay, 10); + } else { + return this.aiDisplay.length; + } + }, + + /** + * Set the display end point - aiDisplay index + * @type function + * @todo Should do away with _iDisplayEnd and calculate it on-the-fly here + */ + "fnDisplayEnd": function () + { + if ( this.oFeatures.bServerSide ) { + if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) { + return this._iDisplayStart+this.aiDisplay.length; + } else { + return Math.min( this._iDisplayStart+this._iDisplayLength, + this._iRecordsDisplay ); + } + } else { + return this._iDisplayEnd; + } + }, + + /** + * The DataTables object for this table + * @type object + * @default null + */ + "oInstance": null, + + /** + * Unique identifier for each instance of the DataTables object. If there + * is an ID on the table node, then it takes that value, otherwise an + * incrementing internal counter is used. + * @type string + * @default null + */ + "sInstance": null, + + /** + * tabindex attribute value that is added to DataTables control elements, allowing + * keyboard navigation of the table and its controls. + */ + "iTabIndex": 0, + + /** + * DIV container for the footer scrolling table if scrolling + */ + "nScrollHead": null, + + /** + * DIV container for the footer scrolling table if scrolling + */ + "nScrollFoot": null + }; + + /** + * Extension object for DataTables that is used to provide all extension options. + * + * Note that the <i>DataTable.ext</i> object is available through + * <i>jQuery.fn.dataTable.ext</i> where it may be accessed and manipulated. It is + * also aliased to <i>jQuery.fn.dataTableExt</i> for historic reasons. + * @namespace + * @extends DataTable.models.ext + */ + DataTable.ext = $.extend( true, {}, DataTable.models.ext ); + + $.extend( DataTable.ext.oStdClasses, { + "sTable": "dataTable", + + /* Two buttons buttons */ + "sPagePrevEnabled": "paginate_enabled_previous", + "sPagePrevDisabled": "paginate_disabled_previous", + "sPageNextEnabled": "paginate_enabled_next", + "sPageNextDisabled": "paginate_disabled_next", + "sPageJUINext": "", + "sPageJUIPrev": "", + + /* Full numbers paging buttons */ + "sPageButton": "paginate_button", + "sPageButtonActive": "paginate_active", + "sPageButtonStaticDisabled": "paginate_button paginate_button_disabled", + "sPageFirst": "first", + "sPagePrevious": "previous", + "sPageNext": "next", + "sPageLast": "last", + + /* Striping classes */ + "sStripeOdd": "odd", + "sStripeEven": "even", + + /* Empty row */ + "sRowEmpty": "dataTables_empty", + + /* Features */ + "sWrapper": "dataTables_wrapper", + "sFilter": "dataTables_filter", + "sInfo": "dataTables_info", + "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */ + "sLength": "dataTables_length", + "sProcessing": "dataTables_processing", + + /* Sorting */ + "sSortAsc": "sorting_asc", + "sSortDesc": "sorting_desc", + "sSortable": "sorting", /* Sortable in both directions */ + "sSortableAsc": "sorting_asc_disabled", + "sSortableDesc": "sorting_desc_disabled", + "sSortableNone": "sorting_disabled", + "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */ + "sSortJUIAsc": "", + "sSortJUIDesc": "", + "sSortJUI": "", + "sSortJUIAscAllowed": "", + "sSortJUIDescAllowed": "", + "sSortJUIWrapper": "", + "sSortIcon": "", + + /* Scrolling */ + "sScrollWrapper": "dataTables_scroll", + "sScrollHead": "dataTables_scrollHead", + "sScrollHeadInner": "dataTables_scrollHeadInner", + "sScrollBody": "dataTables_scrollBody", + "sScrollFoot": "dataTables_scrollFoot", + "sScrollFootInner": "dataTables_scrollFootInner", + + /* Misc */ + "sFooterTH": "", + "sJUIHeader": "", + "sJUIFooter": "" + } ); + + + $.extend( DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, { + /* Two buttons buttons */ + "sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left", + "sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled", + "sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right", + "sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled", + "sPageJUINext": "ui-icon ui-icon-circle-arrow-e", + "sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w", + + /* Full numbers paging buttons */ + "sPageButton": "fg-button ui-button ui-state-default", + "sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled", + "sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled", + "sPageFirst": "first ui-corner-tl ui-corner-bl", + "sPageLast": "last ui-corner-tr ui-corner-br", + + /* Features */ + "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+ + "ui-buttonset-multi paging_", /* Note that the type is postfixed */ + + /* Sorting */ + "sSortAsc": "ui-state-default", + "sSortDesc": "ui-state-default", + "sSortable": "ui-state-default", + "sSortableAsc": "ui-state-default", + "sSortableDesc": "ui-state-default", + "sSortableNone": "ui-state-default", + "sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n", + "sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s", + "sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s", + "sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n", + "sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s", + "sSortJUIWrapper": "DataTables_sort_wrapper", + "sSortIcon": "DataTables_sort_icon", + + /* Scrolling */ + "sScrollHead": "dataTables_scrollHead ui-state-default", + "sScrollFoot": "dataTables_scrollFoot ui-state-default", + + /* Misc */ + "sFooterTH": "ui-state-default", + "sJUIHeader": "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix", + "sJUIFooter": "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix" + } ); + + /* + * Variable: oPagination + * Purpose: + * Scope: jQuery.fn.dataTableExt + */ + $.extend( DataTable.ext.oPagination, { + /* + * Variable: two_button + * Purpose: Standard two button (forward/back) pagination + * Scope: jQuery.fn.dataTableExt.oPagination + */ + "two_button": { + /* + * Function: oPagination.two_button.fnInit + * Purpose: Initialise dom elements required for pagination with forward/back buttons only + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * node:nPaging - the DIV which contains this pagination control + * function:fnCallbackDraw - draw function which must be called on update + */ + "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) + { + var oLang = oSettings.oLanguage.oPaginate; + var oClasses = oSettings.oClasses; + var fnClickHandler = function ( e ) { + if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) ) + { + fnCallbackDraw( oSettings ); + } + }; + + var sAppend = (!oSettings.bJUI) ? + '<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sPrevious+'</a>'+ + '<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sNext+'</a>' + : + '<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUIPrev+'"></span></a>'+ + '<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUINext+'"></span></a>'; + $(nPaging).append( sAppend ); + + var els = $('a', nPaging); + var nPrevious = els[0], + nNext = els[1]; + + oSettings.oApi._fnBindAction( nPrevious, {action: "previous"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler ); + + /* ID the first elements only */ + if ( !oSettings.aanFeatures.p ) + { + nPaging.id = oSettings.sTableId+'_paginate'; + nPrevious.id = oSettings.sTableId+'_previous'; + nNext.id = oSettings.sTableId+'_next'; + + nPrevious.setAttribute('aria-controls', oSettings.sTableId); + nNext.setAttribute('aria-controls', oSettings.sTableId); + } + }, + + /* + * Function: oPagination.two_button.fnUpdate + * Purpose: Update the two button pagination at the end of the draw + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * function:fnCallbackDraw - draw function to call on page change + */ + "fnUpdate": function ( oSettings, fnCallbackDraw ) + { + if ( !oSettings.aanFeatures.p ) + { + return; + } + + var oClasses = oSettings.oClasses; + var an = oSettings.aanFeatures.p; + var nNode; + + /* Loop over each instance of the pager */ + for ( var i=0, iLen=an.length ; i<iLen ; i++ ) + { + nNode = an[i].firstChild; + if ( nNode ) + { + /* Previous page */ + nNode.className = ( oSettings._iDisplayStart === 0 ) ? + oClasses.sPagePrevDisabled : oClasses.sPagePrevEnabled; + + /* Next page */ + nNode = nNode.nextSibling; + nNode.className = ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ? + oClasses.sPageNextDisabled : oClasses.sPageNextEnabled; + } + } + } + }, + + + /* + * Variable: iFullNumbersShowPages + * Purpose: Change the number of pages which can be seen + * Scope: jQuery.fn.dataTableExt.oPagination + */ + "iFullNumbersShowPages": 5, + + /* + * Variable: full_numbers + * Purpose: Full numbers pagination + * Scope: jQuery.fn.dataTableExt.oPagination + */ + "full_numbers": { + /* + * Function: oPagination.full_numbers.fnInit + * Purpose: Initialise dom elements required for pagination with a list of the pages + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * node:nPaging - the DIV which contains this pagination control + * function:fnCallbackDraw - draw function which must be called on update + */ + "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) + { + var oLang = oSettings.oLanguage.oPaginate; + var oClasses = oSettings.oClasses; + var fnClickHandler = function ( e ) { + if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) ) + { + fnCallbackDraw( oSettings ); + } + }; + + $(nPaging).append( + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageFirst+'">'+oLang.sFirst+'</a>'+ + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPagePrevious+'">'+oLang.sPrevious+'</a>'+ + '<span></span>'+ + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageNext+'">'+oLang.sNext+'</a>'+ + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageLast+'">'+oLang.sLast+'</a>' + ); + var els = $('a', nPaging); + var nFirst = els[0], + nPrev = els[1], + nNext = els[2], + nLast = els[3]; + + oSettings.oApi._fnBindAction( nFirst, {action: "first"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nPrev, {action: "previous"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler ); + oSettings.oApi._fnBindAction( nLast, {action: "last"}, fnClickHandler ); + + /* ID the first elements only */ + if ( !oSettings.aanFeatures.p ) + { + nPaging.id = oSettings.sTableId+'_paginate'; + nFirst.id =oSettings.sTableId+'_first'; + nPrev.id =oSettings.sTableId+'_previous'; + nNext.id =oSettings.sTableId+'_next'; + nLast.id =oSettings.sTableId+'_last'; + } + }, + + /* + * Function: oPagination.full_numbers.fnUpdate + * Purpose: Update the list of page buttons shows + * Returns: - + * Inputs: object:oSettings - dataTables settings object + * function:fnCallbackDraw - draw function to call on page change + */ + "fnUpdate": function ( oSettings, fnCallbackDraw ) + { + if ( !oSettings.aanFeatures.p ) + { + return; + } + + var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages; + var iPageCountHalf = Math.floor(iPageCount / 2); + var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength); + var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1; + var sList = ""; + var iStartButton, iEndButton, i, iLen; + var oClasses = oSettings.oClasses; + var anButtons, anStatic, nPaginateList, nNode; + var an = oSettings.aanFeatures.p; + var fnBind = function (j) { + oSettings.oApi._fnBindAction( this, {"page": j+iStartButton-1}, function(e) { + /* Use the information in the element to jump to the required page */ + oSettings.oApi._fnPageChange( oSettings, e.data.page ); + fnCallbackDraw( oSettings ); + e.preventDefault(); + } ); + }; + + /* Pages calculation */ + if ( oSettings._iDisplayLength === -1 ) + { + iStartButton = 1; + iEndButton = 1; + iCurrentPage = 1; + } + else if (iPages < iPageCount) + { + iStartButton = 1; + iEndButton = iPages; + } + else if (iCurrentPage <= iPageCountHalf) + { + iStartButton = 1; + iEndButton = iPageCount; + } + else if (iCurrentPage >= (iPages - iPageCountHalf)) + { + iStartButton = iPages - iPageCount + 1; + iEndButton = iPages; + } + else + { + iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1; + iEndButton = iStartButton + iPageCount - 1; + } + + + /* Build the dynamic list */ + for ( i=iStartButton ; i<=iEndButton ; i++ ) + { + sList += (iCurrentPage !== i) ? + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+'">'+oSettings.fnFormatNumber(i)+'</a>' : + '<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButtonActive+'">'+oSettings.fnFormatNumber(i)+'</a>'; + } + + /* Loop over each instance of the pager */ + for ( i=0, iLen=an.length ; i<iLen ; i++ ) + { + nNode = an[i]; + if ( !nNode.hasChildNodes() ) + { + continue; + } + + /* Build up the dynamic list first - html and listeners */ + $('span:eq(0)', nNode) + .html( sList ) + .children('a').each( fnBind ); + + /* Update the permanent button's classes */ + anButtons = nNode.getElementsByTagName('a'); + anStatic = [ + anButtons[0], anButtons[1], + anButtons[anButtons.length-2], anButtons[anButtons.length-1] + ]; + + $(anStatic).removeClass( oClasses.sPageButton+" "+oClasses.sPageButtonActive+" "+oClasses.sPageButtonStaticDisabled ); + $([anStatic[0], anStatic[1]]).addClass( + (iCurrentPage==1) ? + oClasses.sPageButtonStaticDisabled : + oClasses.sPageButton + ); + $([anStatic[2], anStatic[3]]).addClass( + (iPages===0 || iCurrentPage===iPages || oSettings._iDisplayLength===-1) ? + oClasses.sPageButtonStaticDisabled : + oClasses.sPageButton + ); + } + } + } + } ); + + $.extend( DataTable.ext.oSort, { + /* + * text sorting + */ + "string-pre": function ( a ) + { + if ( typeof a != 'string' ) { + a = (a !== null && a.toString) ? a.toString() : ''; + } + return a.toLowerCase(); + }, + + "string-asc": function ( x, y ) + { + return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + }, + + "string-desc": function ( x, y ) + { + return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + }, + + + /* + * html sorting (ignore html tags) + */ + "html-pre": function ( a ) + { + return a.replace( /<.*?>/g, "" ).toLowerCase(); + }, + + "html-asc": function ( x, y ) + { + return ((x < y) ? -1 : ((x > y) ? 1 : 0)); + }, + + "html-desc": function ( x, y ) + { + return ((x < y) ? 1 : ((x > y) ? -1 : 0)); + }, + + + /* + * date sorting + */ + "date-pre": function ( a ) + { + var x = Date.parse( a ); + + if ( isNaN(x) || x==="" ) + { + x = Date.parse( "01/01/1970 00:00:00" ); + } + return x; + }, + + "date-asc": function ( x, y ) + { + return x - y; + }, + + "date-desc": function ( x, y ) + { + return y - x; + }, + + + /* + * numerical sorting + */ + "numeric-pre": function ( a ) + { + return (a=="-" || a==="") ? 0 : a*1; + }, + + "numeric-asc": function ( x, y ) + { + return x - y; + }, + + "numeric-desc": function ( x, y ) + { + return y - x; + } + } ); + + + $.extend( DataTable.ext.aTypes, [ + /* + * Function: - + * Purpose: Check to see if a string is numeric + * Returns: string:'numeric' or null + * Inputs: mixed:sText - string to check + */ + function ( sData ) + { + /* Allow zero length strings as a number */ + if ( typeof sData === 'number' ) + { + return 'numeric'; + } + else if ( typeof sData !== 'string' ) + { + return null; + } + + var sValidFirstChars = "0123456789-"; + var sValidChars = "0123456789."; + var Char; + var bDecimal = false; + + /* Check for a valid first char (no period and allow negatives) */ + Char = sData.charAt(0); + if (sValidFirstChars.indexOf(Char) == -1) + { + return null; + } + + /* Check all the other characters are valid */ + for ( var i=1 ; i<sData.length ; i++ ) + { + Char = sData.charAt(i); + if (sValidChars.indexOf(Char) == -1) + { + return null; + } + + /* Only allowed one decimal place... */ + if ( Char == "." ) + { + if ( bDecimal ) + { + return null; + } + bDecimal = true; + } + } + + return 'numeric'; + }, + + /* + * Function: - + * Purpose: Check to see if a string is actually a formatted date + * Returns: string:'date' or null + * Inputs: string:sText - string to check + */ + function ( sData ) + { + var iParse = Date.parse(sData); + if ( (iParse !== null && !isNaN(iParse)) || (typeof sData === 'string' && sData.length === 0) ) + { + return 'date'; + } + return null; + }, + + /* + * Function: - + * Purpose: Check to see if a string should be treated as an HTML string + * Returns: string:'html' or null + * Inputs: string:sText - string to check + */ + function ( sData ) + { + if ( typeof sData === 'string' && sData.indexOf('<') != -1 && sData.indexOf('>') != -1 ) + { + return 'html'; + } + return null; + } + ] ); + + + // jQuery aliases + $.fn.DataTable = DataTable; + $.fn.dataTable = DataTable; + $.fn.dataTableSettings = DataTable.settings; + $.fn.dataTableExt = DataTable.ext; + + + // Information about events fired by DataTables - for documentation. + /** + * Draw event, fired whenever the table is redrawn on the page, at the same point as + * fnDrawCallback. This may be useful for binding events or performing calculations when + * the table is altered at all. + * @name DataTable#draw + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * Filter event, fired when the filtering applied to the table (using the build in global + * global filter, or column filters) is altered. + * @name DataTable#filter + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * Page change event, fired when the paging of the table is altered. + * @name DataTable#page + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * Sort event, fired when the sorting applied to the table is altered. + * @name DataTable#sort + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ + + /** + * DataTables initialisation complete event, fired when the table is fully drawn, + * including Ajax data loaded, if Ajax data is required. + * @name DataTable#init + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The JSON object request from the server - only + * present if client-side Ajax sourced data is used</li></ol> + */ + + /** + * State save event, fired when the table has changed state a new state save is required. + * This method allows modification of the state saving object prior to actually doing the + * save, including addition or other state properties (for plug-ins) or modification + * of a DataTables core property. + * @name DataTable#stateSaveParams + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The state information to be saved + */ + + /** + * State load event, fired when the table is loading state from the stored data, but + * prior to the settings object being modified by the saved state - allowing modification + * of the saved state is required or loading of state for a plug-in. + * @name DataTable#stateLoadParams + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The saved state information + */ + + /** + * State loaded event, fired when state has been loaded from stored data and the settings + * object has been modified by the loaded data. + * @name DataTable#stateLoaded + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {object} json The saved state information + */ + + /** + * Processing event, fired when DataTables is doing some kind of processing (be it, + * sort, filter or anything else). Can be used to indicate to the end user that + * there is something happening, or that something has finished. + * @name DataTable#processing + * @event + * @param {event} e jQuery event object + * @param {object} oSettings DataTables settings object + * @param {boolean} bShow Flag for if DataTables is doing processing or not + */ + + /** + * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to + * made to the server for new data (note that this trigger is called in fnServerData, + * if you override fnServerData and which to use this event, you need to trigger it in + * you success function). + * @name DataTable#xhr + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + * @param {object} json JSON returned from the server + */ + + /** + * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing + * the bDestroy:true parameter in the initialisation object. This can be used to remove + * bound events, added DOM nodes, etc. + * @name DataTable#destroy + * @event + * @param {event} e jQuery event object + * @param {object} o DataTables settings object {@link DataTable.models.oSettings} + */ +})); + +}(window, document)); + diff --git a/src/static/jquery/datatables/media/js/jquery.dataTables.min.js b/src/static/jquery/datatables/media/js/jquery.dataTables.min.js new file mode 100644 index 0000000..02694a4 --- /dev/null +++ b/src/static/jquery/datatables/media/js/jquery.dataTables.min.js @@ -0,0 +1,155 @@ +/* + * File: jquery.dataTables.min.js + * Version: 1.9.4 + * Author: Allan Jardine (www.sprymedia.co.uk) + * Info: www.datatables.net + * + * Copyright 2008-2012 Allan Jardine, all rights reserved. + * + * This source file is free software, under either the GPL v2 license or a + * BSD style license, available at: + * http://datatables.net/license_gpl2 + * http://datatables.net/license_bsd + * + * This source file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. + */ +(function(X,l,n){var L=function(h){var j=function(e){function o(a,b){var c=j.defaults.columns,d=a.aoColumns.length,c=h.extend({},j.models.oColumn,c,{sSortingClass:a.oClasses.sSortable,sSortingClassJUI:a.oClasses.sSortJUI,nTh:b?b:l.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.oDefaults:d});a.aoColumns.push(c);if(a.aoPreSearchCols[d]===n||null===a.aoPreSearchCols[d])a.aoPreSearchCols[d]=h.extend({},j.models.oSearch);else if(c=a.aoPreSearchCols[d], +c.bRegex===n&&(c.bRegex=!0),c.bSmart===n&&(c.bSmart=!0),c.bCaseInsensitive===n)c.bCaseInsensitive=!0;m(a,d,null)}function m(a,b,c){var d=a.aoColumns[b];c!==n&&null!==c&&(c.mDataProp&&!c.mData&&(c.mData=c.mDataProp),c.sType!==n&&(d.sType=c.sType,d._bAutoType=!1),h.extend(d,c),p(d,c,"sWidth","sWidthOrig"),c.iDataSort!==n&&(d.aDataSort=[c.iDataSort]),p(d,c,"aDataSort"));var i=d.mRender?Q(d.mRender):null,f=Q(d.mData);d.fnGetData=function(a,b){var c=f(a,b);return d.mRender&&b&&""!==b?i(c,b,a):c};d.fnSetData= +L(d.mData);a.oFeatures.bSort||(d.bSortable=!1);!d.bSortable||-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableNone,d.sSortingClassJUI=""):-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortable,d.sSortingClassJUI=a.oClasses.sSortJUI):-1!=h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableAsc,d.sSortingClassJUI=a.oClasses.sSortJUIAscAllowed):-1== +h.inArray("asc",d.asSorting)&&-1!=h.inArray("desc",d.asSorting)&&(d.sSortingClass=a.oClasses.sSortableDesc,d.sSortingClassJUI=a.oClasses.sSortJUIDescAllowed)}function k(a){if(!1===a.oFeatures.bAutoWidth)return!1;da(a);for(var b=0,c=a.aoColumns.length;b<c;b++)a.aoColumns[b].nTh.style.width=a.aoColumns[b].sWidth}function G(a,b){var c=r(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function R(a,b){var c=r(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}function t(a){return r(a,"bVisible").length} +function r(a,b){var c=[];h.map(a.aoColumns,function(a,i){a[b]&&c.push(i)});return c}function B(a){for(var b=j.ext.aTypes,c=b.length,d=0;d<c;d++){var i=b[d](a);if(null!==i)return i}return"string"}function u(a,b){for(var c=b.split(","),d=[],i=0,f=a.aoColumns.length;i<f;i++)for(var g=0;g<f;g++)if(a.aoColumns[i].sName==c[g]){d.push(g);break}return d}function M(a){for(var b="",c=0,d=a.aoColumns.length;c<d;c++)b+=a.aoColumns[c].sName+",";return b.length==d?"":b.slice(0,-1)}function ta(a,b,c,d){var i,f, +g,e,w;if(b)for(i=b.length-1;0<=i;i--){var j=b[i].aTargets;h.isArray(j)||D(a,1,"aTargets must be an array of targets, not a "+typeof j);f=0;for(g=j.length;f<g;f++)if("number"===typeof j[f]&&0<=j[f]){for(;a.aoColumns.length<=j[f];)o(a);d(j[f],b[i])}else if("number"===typeof j[f]&&0>j[f])d(a.aoColumns.length+j[f],b[i]);else if("string"===typeof j[f]){e=0;for(w=a.aoColumns.length;e<w;e++)("_all"==j[f]||h(a.aoColumns[e].nTh).hasClass(j[f]))&&d(e,b[i])}}if(c){i=0;for(a=c.length;i<a;i++)d(i,c[i])}}function H(a, +b){var c;c=h.isArray(b)?b.slice():h.extend(!0,{},b);var d=a.aoData.length,i=h.extend(!0,{},j.models.oRow);i._aData=c;a.aoData.push(i);for(var f,i=0,g=a.aoColumns.length;i<g;i++)c=a.aoColumns[i],"function"===typeof c.fnRender&&c.bUseRendered&&null!==c.mData?F(a,d,i,S(a,d,i)):F(a,d,i,v(a,d,i)),c._bAutoType&&"string"!=c.sType&&(f=v(a,d,i,"type"),null!==f&&""!==f&&(f=B(f),null===c.sType?c.sType=f:c.sType!=f&&"html"!=c.sType&&(c.sType="string")));a.aiDisplayMaster.push(d);a.oFeatures.bDeferRender||ea(a, +d);return d}function ua(a){var b,c,d,i,f,g,e;if(a.bDeferLoading||null===a.sAjaxSource)for(b=a.nTBody.firstChild;b;){if("TR"==b.nodeName.toUpperCase()){c=a.aoData.length;b._DT_RowIndex=c;a.aoData.push(h.extend(!0,{},j.models.oRow,{nTr:b}));a.aiDisplayMaster.push(c);f=b.firstChild;for(d=0;f;){g=f.nodeName.toUpperCase();if("TD"==g||"TH"==g)F(a,c,d,h.trim(f.innerHTML)),d++;f=f.nextSibling}}b=b.nextSibling}i=T(a);d=[];b=0;for(c=i.length;b<c;b++)for(f=i[b].firstChild;f;)g=f.nodeName.toUpperCase(),("TD"== +g||"TH"==g)&&d.push(f),f=f.nextSibling;c=0;for(i=a.aoColumns.length;c<i;c++){e=a.aoColumns[c];null===e.sTitle&&(e.sTitle=e.nTh.innerHTML);var w=e._bAutoType,o="function"===typeof e.fnRender,k=null!==e.sClass,n=e.bVisible,m,p;if(w||o||k||!n){g=0;for(b=a.aoData.length;g<b;g++)f=a.aoData[g],m=d[g*i+c],w&&"string"!=e.sType&&(p=v(a,g,c,"type"),""!==p&&(p=B(p),null===e.sType?e.sType=p:e.sType!=p&&"html"!=e.sType&&(e.sType="string"))),e.mRender?m.innerHTML=v(a,g,c,"display"):e.mData!==c&&(m.innerHTML=v(a, +g,c,"display")),o&&(p=S(a,g,c),m.innerHTML=p,e.bUseRendered&&F(a,g,c,p)),k&&(m.className+=" "+e.sClass),n?f._anHidden[c]=null:(f._anHidden[c]=m,m.parentNode.removeChild(m)),e.fnCreatedCell&&e.fnCreatedCell.call(a.oInstance,m,v(a,g,c,"display"),f._aData,g,c)}}if(0!==a.aoRowCreatedCallback.length){b=0;for(c=a.aoData.length;b<c;b++)f=a.aoData[b],A(a,"aoRowCreatedCallback",null,[f.nTr,f._aData,b])}}function I(a,b){return b._DT_RowIndex!==n?b._DT_RowIndex:null}function fa(a,b,c){for(var b=J(a,b),d=0,a= +a.aoColumns.length;d<a;d++)if(b[d]===c)return d;return-1}function Y(a,b,c,d){for(var i=[],f=0,g=d.length;f<g;f++)i.push(v(a,b,d[f],c));return i}function v(a,b,c,d){var i=a.aoColumns[c];if((c=i.fnGetData(a.aoData[b]._aData,d))===n)return a.iDrawError!=a.iDraw&&null===i.sDefaultContent&&(D(a,0,"Requested unknown parameter "+("function"==typeof i.mData?"{mData function}":"'"+i.mData+"'")+" from the data source for row "+b),a.iDrawError=a.iDraw),i.sDefaultContent;if(null===c&&null!==i.sDefaultContent)c= +i.sDefaultContent;else if("function"===typeof c)return c();return"display"==d&&null===c?"":c}function F(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d)}function Q(a){if(null===a)return function(){return null};if("function"===typeof a)return function(b,d,i){return a(b,d,i)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("["))){var b=function(a,d,i){var f=i.split("."),g;if(""!==i){var e=0;for(g=f.length;e<g;e++){if(i=f[e].match(U)){f[e]=f[e].replace(U,"");""!==f[e]&&(a=a[f[e]]); +g=[];f.splice(0,e+1);for(var f=f.join("."),e=0,h=a.length;e<h;e++)g.push(b(a[e],d,f));a=i[0].substring(1,i[0].length-1);a=""===a?g:g.join(a);break}if(null===a||a[f[e]]===n)return n;a=a[f[e]]}}return a};return function(c,d){return b(c,d,a)}}return function(b){return b[a]}}function L(a){if(null===a)return function(){};if("function"===typeof a)return function(b,d){a(b,"set",d)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("["))){var b=function(a,d,i){var i=i.split("."),f,g,e=0;for(g= +i.length-1;e<g;e++){if(f=i[e].match(U)){i[e]=i[e].replace(U,"");a[i[e]]=[];f=i.slice();f.splice(0,e+1);g=f.join(".");for(var h=0,j=d.length;h<j;h++)f={},b(f,d[h],g),a[i[e]].push(f);return}if(null===a[i[e]]||a[i[e]]===n)a[i[e]]={};a=a[i[e]]}a[i[i.length-1].replace(U,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Z(a){for(var b=[],c=a.aoData.length,d=0;d<c;d++)b.push(a.aoData[d]._aData);return b}function ga(a){a.aoData.splice(0,a.aoData.length);a.aiDisplayMaster.splice(0, +a.aiDisplayMaster.length);a.aiDisplay.splice(0,a.aiDisplay.length);y(a)}function ha(a,b){for(var c=-1,d=0,i=a.length;d<i;d++)a[d]==b?c=d:a[d]>b&&a[d]--; -1!=c&&a.splice(c,1)}function S(a,b,c){var d=a.aoColumns[c];return d.fnRender({iDataRow:b,iDataColumn:c,oSettings:a,aData:a.aoData[b]._aData,mDataProp:d.mData},v(a,b,c,"display"))}function ea(a,b){var c=a.aoData[b],d;if(null===c.nTr){c.nTr=l.createElement("tr");c.nTr._DT_RowIndex=b;c._aData.DT_RowId&&(c.nTr.id=c._aData.DT_RowId);c._aData.DT_RowClass&& +(c.nTr.className=c._aData.DT_RowClass);for(var i=0,f=a.aoColumns.length;i<f;i++){var g=a.aoColumns[i];d=l.createElement(g.sCellType);d.innerHTML="function"===typeof g.fnRender&&(!g.bUseRendered||null===g.mData)?S(a,b,i):v(a,b,i,"display");null!==g.sClass&&(d.className=g.sClass);g.bVisible?(c.nTr.appendChild(d),c._anHidden[i]=null):c._anHidden[i]=d;g.fnCreatedCell&&g.fnCreatedCell.call(a.oInstance,d,v(a,b,i,"display"),c._aData,b,i)}A(a,"aoRowCreatedCallback",null,[c.nTr,c._aData,b])}}function va(a){var b, +c,d;if(0!==h("th, td",a.nTHead).length){b=0;for(d=a.aoColumns.length;b<d;b++)if(c=a.aoColumns[b].nTh,c.setAttribute("role","columnheader"),a.aoColumns[b].bSortable&&(c.setAttribute("tabindex",a.iTabIndex),c.setAttribute("aria-controls",a.sTableId)),null!==a.aoColumns[b].sClass&&h(c).addClass(a.aoColumns[b].sClass),a.aoColumns[b].sTitle!=c.innerHTML)c.innerHTML=a.aoColumns[b].sTitle}else{var i=l.createElement("tr");b=0;for(d=a.aoColumns.length;b<d;b++)c=a.aoColumns[b].nTh,c.innerHTML=a.aoColumns[b].sTitle, +c.setAttribute("tabindex","0"),null!==a.aoColumns[b].sClass&&h(c).addClass(a.aoColumns[b].sClass),i.appendChild(c);h(a.nTHead).html("")[0].appendChild(i);V(a.aoHeader,a.nTHead)}h(a.nTHead).children("tr").attr("role","row");if(a.bJUI){b=0;for(d=a.aoColumns.length;b<d;b++){c=a.aoColumns[b].nTh;i=l.createElement("div");i.className=a.oClasses.sSortJUIWrapper;h(c).contents().appendTo(i);var f=l.createElement("span");f.className=a.oClasses.sSortIcon;i.appendChild(f);c.appendChild(i)}}if(a.oFeatures.bSort)for(b= +0;b<a.aoColumns.length;b++)!1!==a.aoColumns[b].bSortable?ia(a,a.aoColumns[b].nTh,b):h(a.aoColumns[b].nTh).addClass(a.oClasses.sSortableNone);""!==a.oClasses.sFooterTH&&h(a.nTFoot).children("tr").children("th").addClass(a.oClasses.sFooterTH);if(null!==a.nTFoot){c=N(a,null,a.aoFooter);b=0;for(d=a.aoColumns.length;b<d;b++)c[b]&&(a.aoColumns[b].nTf=c[b],a.aoColumns[b].sClass&&h(c[b]).addClass(a.aoColumns[b].sClass))}}function W(a,b,c){var d,i,f,g=[],e=[],h=a.aoColumns.length,j;c===n&&(c=!1);d=0;for(i= +b.length;d<i;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=h-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[d].splice(f,1);e.push([])}d=0;for(i=g.length;d<i;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(j=h=1,e[d][f]===n){a.appendChild(g[d][f].cell);for(e[d][f]=1;g[d+h]!==n&&g[d][f].cell==g[d+h][f].cell;)e[d+h][f]=1,h++;for(;g[d][f+j]!==n&&g[d][f].cell==g[d][f+j].cell;){for(c=0;c<h;c++)e[d+c][f+j]=1;j++}g[d][f].cell.rowSpan=h;g[d][f].cell.colSpan=j}}}function x(a){var b= +A(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))E(a,!1);else{var c,d,b=[],i=0,f=a.asStripeClasses.length;c=a.aoOpenRows.length;a.bDrawing=!0;a.iInitDisplayStart!==n&&-1!=a.iInitDisplayStart&&(a._iDisplayStart=a.oFeatures.bServerSide?a.iInitDisplayStart:a.iInitDisplayStart>=a.fnRecordsDisplay()?0:a.iInitDisplayStart,a.iInitDisplayStart=-1,y(a));if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++;else if(a.oFeatures.bServerSide){if(!a.bDestroying&&!wa(a))return}else a.iDraw++;if(0!==a.aiDisplay.length){var g= +a._iDisplayStart;d=a._iDisplayEnd;a.oFeatures.bServerSide&&(g=0,d=a.aoData.length);for(;g<d;g++){var e=a.aoData[a.aiDisplay[g]];null===e.nTr&&ea(a,a.aiDisplay[g]);var j=e.nTr;if(0!==f){var o=a.asStripeClasses[i%f];e._sRowStripe!=o&&(h(j).removeClass(e._sRowStripe).addClass(o),e._sRowStripe=o)}A(a,"aoRowCallback",null,[j,a.aoData[a.aiDisplay[g]]._aData,i,g]);b.push(j);i++;if(0!==c)for(e=0;e<c;e++)if(j==a.aoOpenRows[e].nParent){b.push(a.aoOpenRows[e].nTr);break}}}else b[0]=l.createElement("tr"),a.asStripeClasses[0]&& +(b[0].className=a.asStripeClasses[0]),c=a.oLanguage,f=c.sZeroRecords,1==a.iDraw&&null!==a.sAjaxSource&&!a.oFeatures.bServerSide?f=c.sLoadingRecords:c.sEmptyTable&&0===a.fnRecordsTotal()&&(f=c.sEmptyTable),c=l.createElement("td"),c.setAttribute("valign","top"),c.colSpan=t(a),c.className=a.oClasses.sRowEmpty,c.innerHTML=ja(a,f),b[i].appendChild(c);A(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Z(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay]);A(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0], +Z(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay]);i=l.createDocumentFragment();c=l.createDocumentFragment();if(a.nTBody){f=a.nTBody.parentNode;c.appendChild(a.nTBody);if(!a.oScroll.bInfinite||!a._bInitComplete||a.bSorted||a.bFiltered)for(;c=a.nTBody.firstChild;)a.nTBody.removeChild(c);c=0;for(d=b.length;c<d;c++)i.appendChild(b[c]);a.nTBody.appendChild(i);null!==f&&f.appendChild(a.nTBody)}A(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1;a.oFeatures.bServerSide&&(E(a,!1), +a._bInitComplete||$(a))}}function aa(a){a.oFeatures.bSort?O(a,a.oPreviousSearch):a.oFeatures.bFilter?K(a,a.oPreviousSearch):(y(a),x(a))}function xa(a){var b=h("<div></div>")[0];a.nTable.parentNode.insertBefore(b,a.nTable);a.nTableWrapper=h('<div id="'+a.sTableId+'_wrapper" class="'+a.oClasses.sWrapper+'" role="grid"></div>')[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var c=a.nTableWrapper,d=a.sDom.split(""),i,f,g,e,w,o,k,m=0;m<d.length;m++){f=0;g=d[m];if("<"==g){e=h("<div></div>")[0];w=d[m+ +1];if("'"==w||'"'==w){o="";for(k=2;d[m+k]!=w;)o+=d[m+k],k++;"H"==o?o=a.oClasses.sJUIHeader:"F"==o&&(o=a.oClasses.sJUIFooter);-1!=o.indexOf(".")?(w=o.split("."),e.id=w[0].substr(1,w[0].length-1),e.className=w[1]):"#"==o.charAt(0)?e.id=o.substr(1,o.length-1):e.className=o;m+=k}c.appendChild(e);c=e}else if(">"==g)c=c.parentNode;else if("l"==g&&a.oFeatures.bPaginate&&a.oFeatures.bLengthChange)i=ya(a),f=1;else if("f"==g&&a.oFeatures.bFilter)i=za(a),f=1;else if("r"==g&&a.oFeatures.bProcessing)i=Aa(a),f= +1;else if("t"==g)i=Ba(a),f=1;else if("i"==g&&a.oFeatures.bInfo)i=Ca(a),f=1;else if("p"==g&&a.oFeatures.bPaginate)i=Da(a),f=1;else if(0!==j.ext.aoFeatures.length){e=j.ext.aoFeatures;k=0;for(w=e.length;k<w;k++)if(g==e[k].cFeature){(i=e[k].fnInit(a))&&(f=1);break}}1==f&&null!==i&&("object"!==typeof a.aanFeatures[g]&&(a.aanFeatures[g]=[]),a.aanFeatures[g].push(i),c.appendChild(i))}b.parentNode.replaceChild(a.nTableWrapper,b)}function V(a,b){var c=h(b).children("tr"),d,i,f,g,e,j,o,k,m,p;a.splice(0,a.length); +f=0;for(j=c.length;f<j;f++)a.push([]);f=0;for(j=c.length;f<j;f++){d=c[f];for(i=d.firstChild;i;){if("TD"==i.nodeName.toUpperCase()||"TH"==i.nodeName.toUpperCase()){k=1*i.getAttribute("colspan");m=1*i.getAttribute("rowspan");k=!k||0===k||1===k?1:k;m=!m||0===m||1===m?1:m;g=0;for(e=a[f];e[g];)g++;o=g;p=1===k?!0:!1;for(e=0;e<k;e++)for(g=0;g<m;g++)a[f+g][o+e]={cell:i,unique:p},a[f+g].nTr=d}i=i.nextSibling}}}function N(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],V(c,b)));for(var b=0,i=c.length;b<i;b++)for(var f= +0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function wa(a){if(a.bAjaxDataGet){a.iDraw++;E(a,!0);var b=Ea(a);ka(a,b);a.fnServerData.call(a.oInstance,a.sAjaxSource,b,function(b){Fa(a,b)},a);return!1}return!0}function Ea(a){var b=a.aoColumns.length,c=[],d,i,f,g;c.push({name:"sEcho",value:a.iDraw});c.push({name:"iColumns",value:b});c.push({name:"sColumns",value:M(a)});c.push({name:"iDisplayStart",value:a._iDisplayStart});c.push({name:"iDisplayLength", +value:!1!==a.oFeatures.bPaginate?a._iDisplayLength:-1});for(f=0;f<b;f++)d=a.aoColumns[f].mData,c.push({name:"mDataProp_"+f,value:"function"===typeof d?"function":d});if(!1!==a.oFeatures.bFilter){c.push({name:"sSearch",value:a.oPreviousSearch.sSearch});c.push({name:"bRegex",value:a.oPreviousSearch.bRegex});for(f=0;f<b;f++)c.push({name:"sSearch_"+f,value:a.aoPreSearchCols[f].sSearch}),c.push({name:"bRegex_"+f,value:a.aoPreSearchCols[f].bRegex}),c.push({name:"bSearchable_"+f,value:a.aoColumns[f].bSearchable})}if(!1!== +a.oFeatures.bSort){var e=0;d=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(f=0;f<d.length;f++){i=a.aoColumns[d[f][0]].aDataSort;for(g=0;g<i.length;g++)c.push({name:"iSortCol_"+e,value:i[g]}),c.push({name:"sSortDir_"+e,value:d[f][1]}),e++}c.push({name:"iSortingCols",value:e});for(f=0;f<b;f++)c.push({name:"bSortable_"+f,value:a.aoColumns[f].bSortable})}return c}function ka(a,b){A(a,"aoServerParams","serverParams",[b])}function Fa(a,b){if(b.sEcho!==n){if(1*b.sEcho< +a.iDraw)return;a.iDraw=1*b.sEcho}(!a.oScroll.bInfinite||a.oScroll.bInfinite&&(a.bSorted||a.bFiltered))&&ga(a);a._iRecordsTotal=parseInt(b.iTotalRecords,10);a._iRecordsDisplay=parseInt(b.iTotalDisplayRecords,10);var c=M(a),c=b.sColumns!==n&&""!==c&&b.sColumns!=c,d;c&&(d=u(a,b.sColumns));for(var i=Q(a.sAjaxDataProp)(b),f=0,g=i.length;f<g;f++)if(c){for(var e=[],h=0,j=a.aoColumns.length;h<j;h++)e.push(i[f][d[h]]);H(a,e)}else H(a,i[f]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;x(a);a.bAjaxDataGet= +!0;E(a,!1)}function za(a){var b=a.oPreviousSearch,c=a.oLanguage.sSearch,c=-1!==c.indexOf("_INPUT_")?c.replace("_INPUT_",'<input type="text" />'):""===c?'<input type="text" />':c+' <input type="text" />',d=l.createElement("div");d.className=a.oClasses.sFilter;d.innerHTML="<label>"+c+"</label>";a.aanFeatures.f||(d.id=a.sTableId+"_filter");c=h('input[type="text"]',d);d._DT_Input=c[0];c.val(b.sSearch.replace('"',"&quot;"));c.bind("keyup.DT",function(){for(var c=a.aanFeatures.f,d=this.value===""?"":this.value, +g=0,e=c.length;g<e;g++)c[g]!=h(this).parents("div.dataTables_filter")[0]&&h(c[g]._DT_Input).val(d);d!=b.sSearch&&K(a,{sSearch:d,bRegex:b.bRegex,bSmart:b.bSmart,bCaseInsensitive:b.bCaseInsensitive})});c.attr("aria-controls",a.sTableId).bind("keypress.DT",function(a){if(a.keyCode==13)return false});return d}function K(a,b,c){var d=a.oPreviousSearch,i=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};if(a.oFeatures.bServerSide)f(b); +else{Ga(a,b.sSearch,c,b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<a.aoPreSearchCols.length;b++)Ha(a,i[b].sSearch,b,i[b].bRegex,i[b].bSmart,i[b].bCaseInsensitive);Ia(a)}a.bFiltered=!0;h(a.oInstance).trigger("filter",a);a._iDisplayStart=0;y(a);x(a);la(a,0)}function Ia(a){for(var b=j.ext.afnFiltering,c=r(a,"bSearchable"),d=0,i=b.length;d<i;d++)for(var f=0,g=0,e=a.aiDisplay.length;g<e;g++){var h=a.aiDisplay[g-f];b[d](a,Y(a,h,"filter",c),h)||(a.aiDisplay.splice(g-f,1),f++)}}function Ha(a,b,c, +d,i,f){if(""!==b)for(var g=0,b=ma(b,d,i,f),d=a.aiDisplay.length-1;0<=d;d--)i=Ja(v(a,a.aiDisplay[d],c,"filter"),a.aoColumns[c].sType),b.test(i)||(a.aiDisplay.splice(d,1),g++)}function Ga(a,b,c,d,i,f){d=ma(b,d,i,f);i=a.oPreviousSearch;c||(c=0);0!==j.ext.afnFiltering.length&&(c=1);if(0>=b.length)a.aiDisplay.splice(0,a.aiDisplay.length),a.aiDisplay=a.aiDisplayMaster.slice();else if(a.aiDisplay.length==a.aiDisplayMaster.length||i.sSearch.length>b.length||1==c||0!==b.indexOf(i.sSearch)){a.aiDisplay.splice(0, +a.aiDisplay.length);la(a,1);for(b=0;b<a.aiDisplayMaster.length;b++)d.test(a.asDataSearch[b])&&a.aiDisplay.push(a.aiDisplayMaster[b])}else for(b=c=0;b<a.asDataSearch.length;b++)d.test(a.asDataSearch[b])||(a.aiDisplay.splice(b-c,1),c++)}function la(a,b){if(!a.oFeatures.bServerSide){a.asDataSearch=[];for(var c=r(a,"bSearchable"),d=1===b?a.aiDisplayMaster:a.aiDisplay,i=0,f=d.length;i<f;i++)a.asDataSearch[i]=na(a,Y(a,d[i],"filter",c))}}function na(a,b){var c=b.join(" ");-1!==c.indexOf("&")&&(c=h("<div>").html(c).text()); +return c.replace(/[\n\r]/g," ")}function ma(a,b,c,d){if(c)return a=b?a.split(" "):oa(a).split(" "),a="^(?=.*?"+a.join(")(?=.*?")+").*$",RegExp(a,d?"i":"");a=b?a:oa(a);return RegExp(a,d?"i":"")}function Ja(a,b){return"function"===typeof j.ext.ofnSearch[b]?j.ext.ofnSearch[b](a):null===a?"":"html"==b?a.replace(/[\r\n]/g," ").replace(/<.*?>/g,""):"string"===typeof a?a.replace(/[\r\n]/g," "):a}function oa(a){return a.replace(RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"), +"\\$1")}function Ca(a){var b=l.createElement("div");b.className=a.oClasses.sInfo;a.aanFeatures.i||(a.aoDrawCallback.push({fn:Ka,sName:"information"}),b.id=a.sTableId+"_info");a.nTable.setAttribute("aria-describedby",a.sTableId+"_info");return b}function Ka(a){if(a.oFeatures.bInfo&&0!==a.aanFeatures.i.length){var b=a.oLanguage,c=a._iDisplayStart+1,d=a.fnDisplayEnd(),i=a.fnRecordsTotal(),f=a.fnRecordsDisplay(),g;g=0===f?b.sInfoEmpty:b.sInfo;f!=i&&(g+=" "+b.sInfoFiltered);g+=b.sInfoPostFix;g=ja(a,g); +null!==b.fnInfoCallback&&(g=b.fnInfoCallback.call(a.oInstance,a,c,d,i,f,g));a=a.aanFeatures.i;b=0;for(c=a.length;b<c;b++)h(a[b]).html(g)}}function ja(a,b){var c=a.fnFormatNumber(a._iDisplayStart+1),d=a.fnDisplayEnd(),d=a.fnFormatNumber(d),i=a.fnRecordsDisplay(),i=a.fnFormatNumber(i),f=a.fnRecordsTotal(),f=a.fnFormatNumber(f);a.oScroll.bInfinite&&(c=a.fnFormatNumber(1));return b.replace(/_START_/g,c).replace(/_END_/g,d).replace(/_TOTAL_/g,i).replace(/_MAX_/g,f)}function ba(a){var b,c,d=a.iInitDisplayStart; +if(!1===a.bInitialised)setTimeout(function(){ba(a)},200);else{xa(a);va(a);W(a,a.aoHeader);a.nTFoot&&W(a,a.aoFooter);E(a,!0);a.oFeatures.bAutoWidth&&da(a);b=0;for(c=a.aoColumns.length;b<c;b++)null!==a.aoColumns[b].sWidth&&(a.aoColumns[b].nTh.style.width=q(a.aoColumns[b].sWidth));a.oFeatures.bSort?O(a):a.oFeatures.bFilter?K(a,a.oPreviousSearch):(a.aiDisplay=a.aiDisplayMaster.slice(),y(a),x(a));null!==a.sAjaxSource&&!a.oFeatures.bServerSide?(c=[],ka(a,c),a.fnServerData.call(a.oInstance,a.sAjaxSource, +c,function(c){var f=a.sAjaxDataProp!==""?Q(a.sAjaxDataProp)(c):c;for(b=0;b<f.length;b++)H(a,f[b]);a.iInitDisplayStart=d;if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();y(a);x(a)}E(a,false);$(a,c)},a)):a.oFeatures.bServerSide||(E(a,!1),$(a))}}function $(a,b){a._bInitComplete=!0;A(a,"aoInitComplete","init",[a,b])}function pa(a){var b=j.defaults.oLanguage;!a.sEmptyTable&&(a.sZeroRecords&&"No data available in table"===b.sEmptyTable)&&p(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&& +(a.sZeroRecords&&"Loading..."===b.sLoadingRecords)&&p(a,a,"sZeroRecords","sLoadingRecords")}function ya(a){if(a.oScroll.bInfinite)return null;var b='<select size="1" '+('name="'+a.sTableId+'_length"')+">",c,d,i=a.aLengthMenu;if(2==i.length&&"object"===typeof i[0]&&"object"===typeof i[1]){c=0;for(d=i[0].length;c<d;c++)b+='<option value="'+i[0][c]+'">'+i[1][c]+"</option>"}else{c=0;for(d=i.length;c<d;c++)b+='<option value="'+i[c]+'">'+i[c]+"</option>"}b+="</select>";i=l.createElement("div");a.aanFeatures.l|| +(i.id=a.sTableId+"_length");i.className=a.oClasses.sLength;i.innerHTML="<label>"+a.oLanguage.sLengthMenu.replace("_MENU_",b)+"</label>";h('select option[value="'+a._iDisplayLength+'"]',i).attr("selected",!0);h("select",i).bind("change.DT",function(){var b=h(this).val(),i=a.aanFeatures.l;c=0;for(d=i.length;c<d;c++)i[c]!=this.parentNode&&h("select",i[c]).val(b);a._iDisplayLength=parseInt(b,10);y(a);if(a.fnDisplayEnd()==a.fnRecordsDisplay()){a._iDisplayStart=a.fnDisplayEnd()-a._iDisplayLength;if(a._iDisplayStart< +0)a._iDisplayStart=0}if(a._iDisplayLength==-1)a._iDisplayStart=0;x(a)});h("select",i).attr("aria-controls",a.sTableId);return i}function y(a){a._iDisplayEnd=!1===a.oFeatures.bPaginate?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength>a.aiDisplay.length||-1==a._iDisplayLength?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength}function Da(a){if(a.oScroll.bInfinite)return null;var b=l.createElement("div");b.className=a.oClasses.sPaging+a.sPaginationType;j.ext.oPagination[a.sPaginationType].fnInit(a, +b,function(a){y(a);x(a)});a.aanFeatures.p||a.aoDrawCallback.push({fn:function(a){j.ext.oPagination[a.sPaginationType].fnUpdate(a,function(a){y(a);x(a)})},sName:"pagination"});return b}function qa(a,b){var c=a._iDisplayStart;if("number"===typeof b)a._iDisplayStart=b*a._iDisplayLength,a._iDisplayStart>a.fnRecordsDisplay()&&(a._iDisplayStart=0);else if("first"==b)a._iDisplayStart=0;else if("previous"==b)a._iDisplayStart=0<=a._iDisplayLength?a._iDisplayStart-a._iDisplayLength:0,0>a._iDisplayStart&&(a._iDisplayStart= +0);else if("next"==b)0<=a._iDisplayLength?a._iDisplayStart+a._iDisplayLength<a.fnRecordsDisplay()&&(a._iDisplayStart+=a._iDisplayLength):a._iDisplayStart=0;else if("last"==b)if(0<=a._iDisplayLength){var d=parseInt((a.fnRecordsDisplay()-1)/a._iDisplayLength,10)+1;a._iDisplayStart=(d-1)*a._iDisplayLength}else a._iDisplayStart=0;else D(a,0,"Unknown paging action: "+b);h(a.oInstance).trigger("page",a);return c!=a._iDisplayStart}function Aa(a){var b=l.createElement("div");a.aanFeatures.r||(b.id=a.sTableId+ +"_processing");b.innerHTML=a.oLanguage.sProcessing;b.className=a.oClasses.sProcessing;a.nTable.parentNode.insertBefore(b,a.nTable);return b}function E(a,b){if(a.oFeatures.bProcessing)for(var c=a.aanFeatures.r,d=0,i=c.length;d<i;d++)c[d].style.visibility=b?"visible":"hidden";h(a.oInstance).trigger("processing",[a,b])}function Ba(a){if(""===a.oScroll.sX&&""===a.oScroll.sY)return a.nTable;var b=l.createElement("div"),c=l.createElement("div"),d=l.createElement("div"),i=l.createElement("div"),f=l.createElement("div"), +g=l.createElement("div"),e=a.nTable.cloneNode(!1),j=a.nTable.cloneNode(!1),o=a.nTable.getElementsByTagName("thead")[0],k=0===a.nTable.getElementsByTagName("tfoot").length?null:a.nTable.getElementsByTagName("tfoot")[0],m=a.oClasses;c.appendChild(d);f.appendChild(g);i.appendChild(a.nTable);b.appendChild(c);b.appendChild(i);d.appendChild(e);e.appendChild(o);null!==k&&(b.appendChild(f),g.appendChild(j),j.appendChild(k));b.className=m.sScrollWrapper;c.className=m.sScrollHead;d.className=m.sScrollHeadInner; +i.className=m.sScrollBody;f.className=m.sScrollFoot;g.className=m.sScrollFootInner;a.oScroll.bAutoCss&&(c.style.overflow="hidden",c.style.position="relative",f.style.overflow="hidden",i.style.overflow="auto");c.style.border="0";c.style.width="100%";f.style.border="0";d.style.width=""!==a.oScroll.sXInner?a.oScroll.sXInner:"100%";e.removeAttribute("id");e.style.marginLeft="0";a.nTable.style.marginLeft="0";null!==k&&(j.removeAttribute("id"),j.style.marginLeft="0");d=h(a.nTable).children("caption");0< +d.length&&(d=d[0],"top"===d._captionSide?e.appendChild(d):"bottom"===d._captionSide&&k&&j.appendChild(d));""!==a.oScroll.sX&&(c.style.width=q(a.oScroll.sX),i.style.width=q(a.oScroll.sX),null!==k&&(f.style.width=q(a.oScroll.sX)),h(i).scroll(function(){c.scrollLeft=this.scrollLeft;if(k!==null)f.scrollLeft=this.scrollLeft}));""!==a.oScroll.sY&&(i.style.height=q(a.oScroll.sY));a.aoDrawCallback.push({fn:La,sName:"scrolling"});a.oScroll.bInfinite&&h(i).scroll(function(){if(!a.bDrawing&&h(this).scrollTop()!== +0&&h(this).scrollTop()+h(this).height()>h(a.nTable).height()-a.oScroll.iLoadGap&&a.fnDisplayEnd()<a.fnRecordsDisplay()){qa(a,"next");y(a);x(a)}});a.nScrollHead=c;a.nScrollFoot=f;return b}function La(a){var b=a.nScrollHead.getElementsByTagName("div")[0],c=b.getElementsByTagName("table")[0],d=a.nTable.parentNode,i,f,g,e,j,o,k,m,p=[],n=[],l=null!==a.nTFoot?a.nScrollFoot.getElementsByTagName("div")[0]:null,R=null!==a.nTFoot?l.getElementsByTagName("table")[0]:null,r=a.oBrowser.bScrollOversize,s=function(a){k= +a.style;k.paddingTop="0";k.paddingBottom="0";k.borderTopWidth="0";k.borderBottomWidth="0";k.height=0};h(a.nTable).children("thead, tfoot").remove();i=h(a.nTHead).clone()[0];a.nTable.insertBefore(i,a.nTable.childNodes[0]);g=a.nTHead.getElementsByTagName("tr");e=i.getElementsByTagName("tr");null!==a.nTFoot&&(j=h(a.nTFoot).clone()[0],a.nTable.insertBefore(j,a.nTable.childNodes[1]),o=a.nTFoot.getElementsByTagName("tr"),j=j.getElementsByTagName("tr"));""===a.oScroll.sX&&(d.style.width="100%",b.parentNode.style.width= +"100%");var t=N(a,i);i=0;for(f=t.length;i<f;i++)m=G(a,i),t[i].style.width=a.aoColumns[m].sWidth;null!==a.nTFoot&&C(function(a){a.style.width=""},j);a.oScroll.bCollapse&&""!==a.oScroll.sY&&(d.style.height=d.offsetHeight+a.nTHead.offsetHeight+"px");i=h(a.nTable).outerWidth();if(""===a.oScroll.sX){if(a.nTable.style.width="100%",r&&(h("tbody",d).height()>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(h(a.nTable).outerWidth()-a.oScroll.iBarWidth)}else""!==a.oScroll.sXInner?a.nTable.style.width= +q(a.oScroll.sXInner):i==h(d).width()&&h(d).height()<h(a.nTable).height()?(a.nTable.style.width=q(i-a.oScroll.iBarWidth),h(a.nTable).outerWidth()>i-a.oScroll.iBarWidth&&(a.nTable.style.width=q(i))):a.nTable.style.width=q(i);i=h(a.nTable).outerWidth();C(s,e);C(function(a){p.push(q(h(a).width()))},e);C(function(a,b){a.style.width=p[b]},g);h(e).height(0);null!==a.nTFoot&&(C(s,j),C(function(a){n.push(q(h(a).width()))},j),C(function(a,b){a.style.width=n[b]},o),h(j).height(0));C(function(a,b){a.innerHTML= +"";a.style.width=p[b]},e);null!==a.nTFoot&&C(function(a,b){a.innerHTML="";a.style.width=n[b]},j);if(h(a.nTable).outerWidth()<i){g=d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")?i+a.oScroll.iBarWidth:i;if(r&&(d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(g-a.oScroll.iBarWidth);d.style.width=q(g);a.nScrollHead.style.width=q(g);null!==a.nTFoot&&(a.nScrollFoot.style.width=q(g));""===a.oScroll.sX?D(a,1,"The table cannot fit into the current element which will cause column misalignment. The table has been drawn at its minimum possible width."): +""!==a.oScroll.sXInner&&D(a,1,"The table cannot fit into the current element which will cause column misalignment. Increase the sScrollXInner value or remove it to allow automatic calculation")}else d.style.width=q("100%"),a.nScrollHead.style.width=q("100%"),null!==a.nTFoot&&(a.nScrollFoot.style.width=q("100%"));""===a.oScroll.sY&&r&&(d.style.height=q(a.nTable.offsetHeight+a.oScroll.iBarWidth));""!==a.oScroll.sY&&a.oScroll.bCollapse&&(d.style.height=q(a.oScroll.sY),r=""!==a.oScroll.sX&&a.nTable.offsetWidth> +d.offsetWidth?a.oScroll.iBarWidth:0,a.nTable.offsetHeight<d.offsetHeight&&(d.style.height=q(a.nTable.offsetHeight+r)));r=h(a.nTable).outerWidth();c.style.width=q(r);b.style.width=q(r);c=h(a.nTable).height()>d.clientHeight||"scroll"==h(d).css("overflow-y");b.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px";null!==a.nTFoot&&(R.style.width=q(r),l.style.width=q(r),l.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px");h(d).scroll();if(a.bSorted||a.bFiltered)d.scrollTop=0}function C(a,b,c){for(var d= +0,i=0,f=b.length,g,e;i<f;){g=b[i].firstChild;for(e=c?c[i].firstChild:null;g;)1===g.nodeType&&(c?a(g,e,d):a(g,d),d++),g=g.nextSibling,e=c?e.nextSibling:null;i++}}function Ma(a,b){if(!a||null===a||""===a)return 0;b||(b=l.body);var c,d=l.createElement("div");d.style.width=q(a);b.appendChild(d);c=d.offsetWidth;b.removeChild(d);return c}function da(a){var b=0,c,d=0,i=a.aoColumns.length,f,e,j=h("th",a.nTHead),o=a.nTable.getAttribute("width");e=a.nTable.parentNode;for(f=0;f<i;f++)a.aoColumns[f].bVisible&& +(d++,null!==a.aoColumns[f].sWidth&&(c=Ma(a.aoColumns[f].sWidthOrig,e),null!==c&&(a.aoColumns[f].sWidth=q(c)),b++));if(i==j.length&&0===b&&d==i&&""===a.oScroll.sX&&""===a.oScroll.sY)for(f=0;f<a.aoColumns.length;f++)c=h(j[f]).width(),null!==c&&(a.aoColumns[f].sWidth=q(c));else{b=a.nTable.cloneNode(!1);f=a.nTHead.cloneNode(!0);d=l.createElement("tbody");c=l.createElement("tr");b.removeAttribute("id");b.appendChild(f);null!==a.nTFoot&&(b.appendChild(a.nTFoot.cloneNode(!0)),C(function(a){a.style.width= +""},b.getElementsByTagName("tr")));b.appendChild(d);d.appendChild(c);d=h("thead th",b);0===d.length&&(d=h("tbody tr:eq(0)>td",b));j=N(a,f);for(f=d=0;f<i;f++){var k=a.aoColumns[f];k.bVisible&&null!==k.sWidthOrig&&""!==k.sWidthOrig?j[f-d].style.width=q(k.sWidthOrig):k.bVisible?j[f-d].style.width="":d++}for(f=0;f<i;f++)a.aoColumns[f].bVisible&&(d=Na(a,f),null!==d&&(d=d.cloneNode(!0),""!==a.aoColumns[f].sContentPadding&&(d.innerHTML+=a.aoColumns[f].sContentPadding),c.appendChild(d)));e.appendChild(b); +""!==a.oScroll.sX&&""!==a.oScroll.sXInner?b.style.width=q(a.oScroll.sXInner):""!==a.oScroll.sX?(b.style.width="",h(b).width()<e.offsetWidth&&(b.style.width=q(e.offsetWidth))):""!==a.oScroll.sY?b.style.width=q(e.offsetWidth):o&&(b.style.width=q(o));b.style.visibility="hidden";Oa(a,b);i=h("tbody tr:eq(0)",b).children();0===i.length&&(i=N(a,h("thead",b)[0]));if(""!==a.oScroll.sX){for(f=d=e=0;f<a.aoColumns.length;f++)a.aoColumns[f].bVisible&&(e=null===a.aoColumns[f].sWidthOrig?e+h(i[d]).outerWidth(): +e+(parseInt(a.aoColumns[f].sWidth.replace("px",""),10)+(h(i[d]).outerWidth()-h(i[d]).width())),d++);b.style.width=q(e);a.nTable.style.width=q(e)}for(f=d=0;f<a.aoColumns.length;f++)a.aoColumns[f].bVisible&&(e=h(i[d]).width(),null!==e&&0<e&&(a.aoColumns[f].sWidth=q(e)),d++);i=h(b).css("width");a.nTable.style.width=-1!==i.indexOf("%")?i:q(h(b).outerWidth());b.parentNode.removeChild(b)}o&&(a.nTable.style.width=q(o))}function Oa(a,b){""===a.oScroll.sX&&""!==a.oScroll.sY?(h(b).width(),b.style.width=q(h(b).outerWidth()- +a.oScroll.iBarWidth)):""!==a.oScroll.sX&&(b.style.width=q(h(b).outerWidth()))}function Na(a,b){var c=Pa(a,b);if(0>c)return null;if(null===a.aoData[c].nTr){var d=l.createElement("td");d.innerHTML=v(a,c,b,"");return d}return J(a,c)[b]}function Pa(a,b){for(var c=-1,d=-1,i=0;i<a.aoData.length;i++){var e=v(a,i,b,"display")+"",e=e.replace(/<.*?>/g,"");e.length>c&&(c=e.length,d=i)}return d}function q(a){if(null===a)return"0px";if("number"==typeof a)return 0>a?"0px":a+"px";var b=a.charCodeAt(a.length-1); +return 48>b||57<b?a:a+"px"}function Qa(){var a=l.createElement("p"),b=a.style;b.width="100%";b.height="200px";b.padding="0px";var c=l.createElement("div"),b=c.style;b.position="absolute";b.top="0px";b.left="0px";b.visibility="hidden";b.width="200px";b.height="150px";b.padding="0px";b.overflow="hidden";c.appendChild(a);l.body.appendChild(c);b=a.offsetWidth;c.style.overflow="scroll";a=a.offsetWidth;b==a&&(a=c.clientWidth);l.body.removeChild(c);return b-a}function O(a,b){var c,d,i,e,g,k,o=[],m=[],p= +j.ext.oSort,l=a.aoData,q=a.aoColumns,G=a.oLanguage.oAria;if(!a.oFeatures.bServerSide&&(0!==a.aaSorting.length||null!==a.aaSortingFixed)){o=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(c=0;c<o.length;c++)if(d=o[c][0],i=R(a,d),e=a.aoColumns[d].sSortDataType,j.ext.afnSortData[e])if(g=j.ext.afnSortData[e].call(a.oInstance,a,d,i),g.length===l.length){i=0;for(e=l.length;i<e;i++)F(a,i,d,g[i])}else D(a,0,"Returned data sort array (col "+d+") is the wrong length");c= +0;for(d=a.aiDisplayMaster.length;c<d;c++)m[a.aiDisplayMaster[c]]=c;var r=o.length,s;c=0;for(d=l.length;c<d;c++)for(i=0;i<r;i++){s=q[o[i][0]].aDataSort;g=0;for(k=s.length;g<k;g++)e=q[s[g]].sType,e=p[(e?e:"string")+"-pre"],l[c]._aSortData[s[g]]=e?e(v(a,c,s[g],"sort")):v(a,c,s[g],"sort")}a.aiDisplayMaster.sort(function(a,b){var c,d,e,i,f;for(c=0;c<r;c++){f=q[o[c][0]].aDataSort;d=0;for(e=f.length;d<e;d++)if(i=q[f[d]].sType,i=p[(i?i:"string")+"-"+o[c][1]](l[a]._aSortData[f[d]],l[b]._aSortData[f[d]]),0!== +i)return i}return p["numeric-asc"](m[a],m[b])})}(b===n||b)&&!a.oFeatures.bDeferRender&&P(a);c=0;for(d=a.aoColumns.length;c<d;c++)e=q[c].sTitle.replace(/<.*?>/g,""),i=q[c].nTh,i.removeAttribute("aria-sort"),i.removeAttribute("aria-label"),q[c].bSortable?0<o.length&&o[0][0]==c?(i.setAttribute("aria-sort","asc"==o[0][1]?"ascending":"descending"),i.setAttribute("aria-label",e+("asc"==(q[c].asSorting[o[0][2]+1]?q[c].asSorting[o[0][2]+1]:q[c].asSorting[0])?G.sSortAscending:G.sSortDescending))):i.setAttribute("aria-label", +e+("asc"==q[c].asSorting[0]?G.sSortAscending:G.sSortDescending)):i.setAttribute("aria-label",e);a.bSorted=!0;h(a.oInstance).trigger("sort",a);a.oFeatures.bFilter?K(a,a.oPreviousSearch,1):(a.aiDisplay=a.aiDisplayMaster.slice(),a._iDisplayStart=0,y(a),x(a))}function ia(a,b,c,d){Ra(b,{},function(b){if(!1!==a.aoColumns[c].bSortable){var e=function(){var d,e;if(b.shiftKey){for(var f=!1,h=0;h<a.aaSorting.length;h++)if(a.aaSorting[h][0]==c){f=!0;d=a.aaSorting[h][0];e=a.aaSorting[h][2]+1;a.aoColumns[d].asSorting[e]? +(a.aaSorting[h][1]=a.aoColumns[d].asSorting[e],a.aaSorting[h][2]=e):a.aaSorting.splice(h,1);break}!1===f&&a.aaSorting.push([c,a.aoColumns[c].asSorting[0],0])}else 1==a.aaSorting.length&&a.aaSorting[0][0]==c?(d=a.aaSorting[0][0],e=a.aaSorting[0][2]+1,a.aoColumns[d].asSorting[e]||(e=0),a.aaSorting[0][1]=a.aoColumns[d].asSorting[e],a.aaSorting[0][2]=e):(a.aaSorting.splice(0,a.aaSorting.length),a.aaSorting.push([c,a.aoColumns[c].asSorting[0],0]));O(a)};a.oFeatures.bProcessing?(E(a,!0),setTimeout(function(){e(); +a.oFeatures.bServerSide||E(a,!1)},0)):e();"function"==typeof d&&d(a)}})}function P(a){var b,c,d,e,f,g=a.aoColumns.length,j=a.oClasses;for(b=0;b<g;b++)a.aoColumns[b].bSortable&&h(a.aoColumns[b].nTh).removeClass(j.sSortAsc+" "+j.sSortDesc+" "+a.aoColumns[b].sSortingClass);c=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(b=0;b<a.aoColumns.length;b++)if(a.aoColumns[b].bSortable){f=a.aoColumns[b].sSortingClass;e=-1;for(d=0;d<c.length;d++)if(c[d][0]==b){f="asc"==c[d][1]? +j.sSortAsc:j.sSortDesc;e=d;break}h(a.aoColumns[b].nTh).addClass(f);a.bJUI&&(f=h("span."+j.sSortIcon,a.aoColumns[b].nTh),f.removeClass(j.sSortJUIAsc+" "+j.sSortJUIDesc+" "+j.sSortJUI+" "+j.sSortJUIAscAllowed+" "+j.sSortJUIDescAllowed),f.addClass(-1==e?a.aoColumns[b].sSortingClassJUI:"asc"==c[e][1]?j.sSortJUIAsc:j.sSortJUIDesc))}else h(a.aoColumns[b].nTh).addClass(a.aoColumns[b].sSortingClass);f=j.sSortColumn;if(a.oFeatures.bSort&&a.oFeatures.bSortClasses){a=J(a);e=[];for(b=0;b<g;b++)e.push("");b=0; +for(d=1;b<c.length;b++)j=parseInt(c[b][0],10),e[j]=f+d,3>d&&d++;f=RegExp(f+"[123]");var o;b=0;for(c=a.length;b<c;b++)j=b%g,d=a[b].className,o=e[j],j=d.replace(f,o),j!=d?a[b].className=h.trim(j):0<o.length&&-1==d.indexOf(o)&&(a[b].className=d+" "+o)}}function ra(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b,c;b=a.oScroll.bInfinite;var d={iCreate:(new Date).getTime(),iStart:b?0:a._iDisplayStart,iEnd:b?a._iDisplayLength:a._iDisplayEnd,iLength:a._iDisplayLength,aaSorting:h.extend(!0,[],a.aaSorting), +oSearch:h.extend(!0,{},a.oPreviousSearch),aoSearchCols:h.extend(!0,[],a.aoPreSearchCols),abVisCols:[]};b=0;for(c=a.aoColumns.length;b<c;b++)d.abVisCols.push(a.aoColumns[b].bVisible);A(a,"aoStateSaveParams","stateSaveParams",[a,d]);a.fnStateSave.call(a.oInstance,a,d)}}function Sa(a,b){if(a.oFeatures.bStateSave){var c=a.fnStateLoad.call(a.oInstance,a);if(c){var d=A(a,"aoStateLoadParams","stateLoadParams",[a,c]);if(-1===h.inArray(!1,d)){a.oLoadedState=h.extend(!0,{},c);a._iDisplayStart=c.iStart;a.iInitDisplayStart= +c.iStart;a._iDisplayEnd=c.iEnd;a._iDisplayLength=c.iLength;a.aaSorting=c.aaSorting.slice();a.saved_aaSorting=c.aaSorting.slice();h.extend(a.oPreviousSearch,c.oSearch);h.extend(!0,a.aoPreSearchCols,c.aoSearchCols);b.saved_aoColumns=[];for(d=0;d<c.abVisCols.length;d++)b.saved_aoColumns[d]={},b.saved_aoColumns[d].bVisible=c.abVisCols[d];A(a,"aoStateLoaded","stateLoaded",[a,c])}}}}function s(a){for(var b=0;b<j.settings.length;b++)if(j.settings[b].nTable===a)return j.settings[b];return null}function T(a){for(var b= +[],a=a.aoData,c=0,d=a.length;c<d;c++)null!==a[c].nTr&&b.push(a[c].nTr);return b}function J(a,b){var c=[],d,e,f,g,h,j;e=0;var o=a.aoData.length;b!==n&&(e=b,o=b+1);for(f=e;f<o;f++)if(j=a.aoData[f],null!==j.nTr){e=[];for(d=j.nTr.firstChild;d;)g=d.nodeName.toLowerCase(),("td"==g||"th"==g)&&e.push(d),d=d.nextSibling;g=d=0;for(h=a.aoColumns.length;g<h;g++)a.aoColumns[g].bVisible?c.push(e[g-d]):(c.push(j._anHidden[g]),d++)}return c}function D(a,b,c){a=null===a?"DataTables warning: "+c:"DataTables warning (table id = '"+ +a.sTableId+"'): "+c;if(0===b)if("alert"==j.ext.sErrMode)alert(a);else throw Error(a);else X.console&&console.log&&console.log(a)}function p(a,b,c,d){d===n&&(d=c);b[c]!==n&&(a[d]=b[c])}function Ta(a,b){var c,d;for(d in b)b.hasOwnProperty(d)&&(c=b[d],"object"===typeof e[d]&&null!==c&&!1===h.isArray(c)?h.extend(!0,a[d],c):a[d]=c);return a}function Ra(a,b,c){h(a).bind("click.DT",b,function(b){a.blur();c(b)}).bind("keypress.DT",b,function(a){13===a.which&&c(a)}).bind("selectstart.DT",function(){return!1})} +function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function A(a,b,c,d){for(var b=a[b],e=[],f=b.length-1;0<=f;f--)e.push(b[f].fn.apply(a.oInstance,d));null!==c&&h(a.oInstance).trigger(c,d);return e}function Ua(a){var b=h('<div style="position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden"><div style="position:absolute; top:1px; left:1px; width:100px; overflow:scroll;"><div id="DT_BrowserTest" style="width:100%; height:10px;"></div></div></div>')[0];l.body.appendChild(b);a.oBrowser.bScrollOversize= +100===h("#DT_BrowserTest",b)[0].offsetWidth?!0:!1;l.body.removeChild(b)}function Va(a){return function(){var b=[s(this[j.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return j.ext.oApi[a].apply(this,b)}}var U=/\[.*?\]$/,Wa=X.JSON?JSON.stringify:function(a){var b=typeof a;if("object"!==b||null===a)return"string"===b&&(a='"'+a+'"'),a+"";var c,d,e=[],f=h.isArray(a);for(c in a)d=a[c],b=typeof d,"string"===b?d='"'+d+'"':"object"===b&&null!==d&&(d=Wa(d)),e.push((f?"":'"'+c+'":')+d);return(f? +"[":"{")+e+(f?"]":"}")};this.$=function(a,b){var c,d,e=[],f;d=s(this[j.ext.iApiIndex]);var g=d.aoData,o=d.aiDisplay,k=d.aiDisplayMaster;b||(b={});b=h.extend({},{filter:"none",order:"current",page:"all"},b);if("current"==b.page){c=d._iDisplayStart;for(d=d.fnDisplayEnd();c<d;c++)(f=g[o[c]].nTr)&&e.push(f)}else if("current"==b.order&&"none"==b.filter){c=0;for(d=k.length;c<d;c++)(f=g[k[c]].nTr)&&e.push(f)}else if("current"==b.order&&"applied"==b.filter){c=0;for(d=o.length;c<d;c++)(f=g[o[c]].nTr)&&e.push(f)}else if("original"== +b.order&&"none"==b.filter){c=0;for(d=g.length;c<d;c++)(f=g[c].nTr)&&e.push(f)}else if("original"==b.order&&"applied"==b.filter){c=0;for(d=g.length;c<d;c++)f=g[c].nTr,-1!==h.inArray(c,o)&&f&&e.push(f)}else D(d,1,"Unknown selection options");e=h(e);c=e.filter(a);e=e.find(a);return h([].concat(h.makeArray(c),h.makeArray(e)))};this._=function(a,b){var c=[],d,e,f=this.$(a,b);d=0;for(e=f.length;d<e;d++)c.push(this.fnGetData(f[d]));return c};this.fnAddData=function(a,b){if(0===a.length)return[];var c=[], +d,e=s(this[j.ext.iApiIndex]);if("object"===typeof a[0]&&null!==a[0])for(var f=0;f<a.length;f++){d=H(e,a[f]);if(-1==d)return c;c.push(d)}else{d=H(e,a);if(-1==d)return c;c.push(d)}e.aiDisplay=e.aiDisplayMaster.slice();(b===n||b)&&aa(e);return c};this.fnAdjustColumnSizing=function(a){var b=s(this[j.ext.iApiIndex]);k(b);a===n||a?this.fnDraw(!1):(""!==b.oScroll.sX||""!==b.oScroll.sY)&&this.oApi._fnScrollDraw(b)};this.fnClearTable=function(a){var b=s(this[j.ext.iApiIndex]);ga(b);(a===n||a)&&x(b)};this.fnClose= +function(a){for(var b=s(this[j.ext.iApiIndex]),c=0;c<b.aoOpenRows.length;c++)if(b.aoOpenRows[c].nParent==a)return(a=b.aoOpenRows[c].nTr.parentNode)&&a.removeChild(b.aoOpenRows[c].nTr),b.aoOpenRows.splice(c,1),0;return 1};this.fnDeleteRow=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e,f,a="object"===typeof a?I(d,a):a,g=d.aoData.splice(a,1);e=0;for(f=d.aoData.length;e<f;e++)null!==d.aoData[e].nTr&&(d.aoData[e].nTr._DT_RowIndex=e);e=h.inArray(a,d.aiDisplay);d.asDataSearch.splice(e,1);ha(d.aiDisplayMaster, +a);ha(d.aiDisplay,a);"function"===typeof b&&b.call(this,d,g);d._iDisplayStart>=d.fnRecordsDisplay()&&(d._iDisplayStart-=d._iDisplayLength,0>d._iDisplayStart&&(d._iDisplayStart=0));if(c===n||c)y(d),x(d);return g};this.fnDestroy=function(a){var b=s(this[j.ext.iApiIndex]),c=b.nTableWrapper.parentNode,d=b.nTBody,i,f,a=a===n?!1:a;b.bDestroying=!0;A(b,"aoDestroyCallback","destroy",[b]);if(!a){i=0;for(f=b.aoColumns.length;i<f;i++)!1===b.aoColumns[i].bVisible&&this.fnSetColumnVis(i,!0)}h(b.nTableWrapper).find("*").andSelf().unbind(".DT"); +h("tbody>tr>td."+b.oClasses.sRowEmpty,b.nTable).parent().remove();b.nTable!=b.nTHead.parentNode&&(h(b.nTable).children("thead").remove(),b.nTable.appendChild(b.nTHead));b.nTFoot&&b.nTable!=b.nTFoot.parentNode&&(h(b.nTable).children("tfoot").remove(),b.nTable.appendChild(b.nTFoot));b.nTable.parentNode.removeChild(b.nTable);h(b.nTableWrapper).remove();b.aaSorting=[];b.aaSortingFixed=[];P(b);h(T(b)).removeClass(b.asStripeClasses.join(" "));h("th, td",b.nTHead).removeClass([b.oClasses.sSortable,b.oClasses.sSortableAsc, +b.oClasses.sSortableDesc,b.oClasses.sSortableNone].join(" "));b.bJUI&&(h("th span."+b.oClasses.sSortIcon+", td span."+b.oClasses.sSortIcon,b.nTHead).remove(),h("th, td",b.nTHead).each(function(){var a=h("div."+b.oClasses.sSortJUIWrapper,this),c=a.contents();h(this).append(c);a.remove()}));!a&&b.nTableReinsertBefore?c.insertBefore(b.nTable,b.nTableReinsertBefore):a||c.appendChild(b.nTable);i=0;for(f=b.aoData.length;i<f;i++)null!==b.aoData[i].nTr&&d.appendChild(b.aoData[i].nTr);!0===b.oFeatures.bAutoWidth&& +(b.nTable.style.width=q(b.sDestroyWidth));if(f=b.asDestroyStripes.length){a=h(d).children("tr");for(i=0;i<f;i++)a.filter(":nth-child("+f+"n + "+i+")").addClass(b.asDestroyStripes[i])}i=0;for(f=j.settings.length;i<f;i++)j.settings[i]==b&&j.settings.splice(i,1);e=b=null};this.fnDraw=function(a){var b=s(this[j.ext.iApiIndex]);!1===a?(y(b),x(b)):aa(b)};this.fnFilter=function(a,b,c,d,e,f){var g=s(this[j.ext.iApiIndex]);if(g.oFeatures.bFilter){if(c===n||null===c)c=!1;if(d===n||null===d)d=!0;if(e===n||null=== +e)e=!0;if(f===n||null===f)f=!0;if(b===n||null===b){if(K(g,{sSearch:a+"",bRegex:c,bSmart:d,bCaseInsensitive:f},1),e&&g.aanFeatures.f){b=g.aanFeatures.f;c=0;for(d=b.length;c<d;c++)try{b[c]._DT_Input!=l.activeElement&&h(b[c]._DT_Input).val(a)}catch(o){h(b[c]._DT_Input).val(a)}}}else h.extend(g.aoPreSearchCols[b],{sSearch:a+"",bRegex:c,bSmart:d,bCaseInsensitive:f}),K(g,g.oPreviousSearch,1)}};this.fnGetData=function(a,b){var c=s(this[j.ext.iApiIndex]);if(a!==n){var d=a;if("object"===typeof a){var e=a.nodeName.toLowerCase(); +"tr"===e?d=I(c,a):"td"===e&&(d=I(c,a.parentNode),b=fa(c,d,a))}return b!==n?v(c,d,b,""):c.aoData[d]!==n?c.aoData[d]._aData:null}return Z(c)};this.fnGetNodes=function(a){var b=s(this[j.ext.iApiIndex]);return a!==n?b.aoData[a]!==n?b.aoData[a].nTr:null:T(b)};this.fnGetPosition=function(a){var b=s(this[j.ext.iApiIndex]),c=a.nodeName.toUpperCase();return"TR"==c?I(b,a):"TD"==c||"TH"==c?(c=I(b,a.parentNode),a=fa(b,c,a),[c,R(b,a),a]):null};this.fnIsOpen=function(a){for(var b=s(this[j.ext.iApiIndex]),c=0;c< +b.aoOpenRows.length;c++)if(b.aoOpenRows[c].nParent==a)return!0;return!1};this.fnOpen=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e=T(d);if(-1!==h.inArray(a,e)){this.fnClose(a);var e=l.createElement("tr"),f=l.createElement("td");e.appendChild(f);f.className=c;f.colSpan=t(d);"string"===typeof b?f.innerHTML=b:h(f).html(b);b=h("tr",d.nTBody);-1!=h.inArray(a,b)&&h(e).insertAfter(a);d.aoOpenRows.push({nTr:e,nParent:a});return e}};this.fnPageChange=function(a,b){var c=s(this[j.ext.iApiIndex]);qa(c,a); +y(c);(b===n||b)&&x(c)};this.fnSetColumnVis=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e,f,g=d.aoColumns,h=d.aoData,o,m;if(g[a].bVisible!=b){if(b){for(e=f=0;e<a;e++)g[e].bVisible&&f++;m=f>=t(d);if(!m)for(e=a;e<g.length;e++)if(g[e].bVisible){o=e;break}e=0;for(f=h.length;e<f;e++)null!==h[e].nTr&&(m?h[e].nTr.appendChild(h[e]._anHidden[a]):h[e].nTr.insertBefore(h[e]._anHidden[a],J(d,e)[o]))}else{e=0;for(f=h.length;e<f;e++)null!==h[e].nTr&&(o=J(d,e)[a],h[e]._anHidden[a]=o,o.parentNode.removeChild(o))}g[a].bVisible= +b;W(d,d.aoHeader);d.nTFoot&&W(d,d.aoFooter);e=0;for(f=d.aoOpenRows.length;e<f;e++)d.aoOpenRows[e].nTr.colSpan=t(d);if(c===n||c)k(d),x(d);ra(d)}};this.fnSettings=function(){return s(this[j.ext.iApiIndex])};this.fnSort=function(a){var b=s(this[j.ext.iApiIndex]);b.aaSorting=a;O(b)};this.fnSortListener=function(a,b,c){ia(s(this[j.ext.iApiIndex]),a,b,c)};this.fnUpdate=function(a,b,c,d,e){var f=s(this[j.ext.iApiIndex]),b="object"===typeof b?I(f,b):b;if(h.isArray(a)&&c===n){f.aoData[b]._aData=a.slice(); +for(c=0;c<f.aoColumns.length;c++)this.fnUpdate(v(f,b,c),b,c,!1,!1)}else if(h.isPlainObject(a)&&c===n){f.aoData[b]._aData=h.extend(!0,{},a);for(c=0;c<f.aoColumns.length;c++)this.fnUpdate(v(f,b,c),b,c,!1,!1)}else{F(f,b,c,a);var a=v(f,b,c,"display"),g=f.aoColumns[c];null!==g.fnRender&&(a=S(f,b,c),g.bUseRendered&&F(f,b,c,a));null!==f.aoData[b].nTr&&(J(f,b)[c].innerHTML=a)}c=h.inArray(b,f.aiDisplay);f.asDataSearch[c]=na(f,Y(f,b,"filter",r(f,"bSearchable")));(e===n||e)&&k(f);(d===n||d)&&aa(f);return 0}; +this.fnVersionCheck=j.ext.fnVersionCheck;this.oApi={_fnExternApiFunc:Va,_fnInitialise:ba,_fnInitComplete:$,_fnLanguageCompat:pa,_fnAddColumn:o,_fnColumnOptions:m,_fnAddData:H,_fnCreateTr:ea,_fnGatherData:ua,_fnBuildHead:va,_fnDrawHead:W,_fnDraw:x,_fnReDraw:aa,_fnAjaxUpdate:wa,_fnAjaxParameters:Ea,_fnAjaxUpdateDraw:Fa,_fnServerParams:ka,_fnAddOptionsHtml:xa,_fnFeatureHtmlTable:Ba,_fnScrollDraw:La,_fnAdjustColumnSizing:k,_fnFeatureHtmlFilter:za,_fnFilterComplete:K,_fnFilterCustom:Ia,_fnFilterColumn:Ha, +_fnFilter:Ga,_fnBuildSearchArray:la,_fnBuildSearchRow:na,_fnFilterCreateSearch:ma,_fnDataToSearch:Ja,_fnSort:O,_fnSortAttachListener:ia,_fnSortingClasses:P,_fnFeatureHtmlPaginate:Da,_fnPageChange:qa,_fnFeatureHtmlInfo:Ca,_fnUpdateInfo:Ka,_fnFeatureHtmlLength:ya,_fnFeatureHtmlProcessing:Aa,_fnProcessingDisplay:E,_fnVisibleToColumnIndex:G,_fnColumnIndexToVisible:R,_fnNodeToDataIndex:I,_fnVisbleColumns:t,_fnCalculateEnd:y,_fnConvertToWidth:Ma,_fnCalculateColumnWidths:da,_fnScrollingWidthAdjust:Oa,_fnGetWidestNode:Na, +_fnGetMaxLenString:Pa,_fnStringToCss:q,_fnDetectType:B,_fnSettingsFromNode:s,_fnGetDataMaster:Z,_fnGetTrNodes:T,_fnGetTdNodes:J,_fnEscapeRegex:oa,_fnDeleteIndex:ha,_fnReOrderIndex:u,_fnColumnOrdering:M,_fnLog:D,_fnClearTable:ga,_fnSaveState:ra,_fnLoadState:Sa,_fnCreateCookie:function(a,b,c,d,e){var f=new Date;f.setTime(f.getTime()+1E3*c);var c=X.location.pathname.split("/"),a=a+"_"+c.pop().replace(/[\/:]/g,"").toLowerCase(),g;null!==e?(g="function"===typeof h.parseJSON?h.parseJSON(b):eval("("+b+")"), +b=e(a,g,f.toGMTString(),c.join("/")+"/")):b=a+"="+encodeURIComponent(b)+"; expires="+f.toGMTString()+"; path="+c.join("/")+"/";a=l.cookie.split(";");e=b.split(";")[0].length;f=[];if(4096<e+l.cookie.length+10){for(var j=0,o=a.length;j<o;j++)if(-1!=a[j].indexOf(d)){var k=a[j].split("=");try{(g=eval("("+decodeURIComponent(k[1])+")"))&&g.iCreate&&f.push({name:k[0],time:g.iCreate})}catch(m){}}for(f.sort(function(a,b){return b.time-a.time});4096<e+l.cookie.length+10;){if(0===f.length)return;d=f.pop();l.cookie= +d.name+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+c.join("/")+"/"}}l.cookie=b},_fnReadCookie:function(a){for(var b=X.location.pathname.split("/"),a=a+"_"+b[b.length-1].replace(/[\/:]/g,"").toLowerCase()+"=",b=l.cookie.split(";"),c=0;c<b.length;c++){for(var d=b[c];" "==d.charAt(0);)d=d.substring(1,d.length);if(0===d.indexOf(a))return decodeURIComponent(d.substring(a.length,d.length))}return null},_fnDetectHeader:V,_fnGetUniqueThs:N,_fnScrollBarWidth:Qa,_fnApplyToChildren:C,_fnMap:p,_fnGetRowData:Y, +_fnGetCellData:v,_fnSetCellData:F,_fnGetObjectDataFn:Q,_fnSetObjectDataFn:L,_fnApplyColumnDefs:ta,_fnBindAction:Ra,_fnExtend:Ta,_fnCallbackReg:z,_fnCallbackFire:A,_fnJsonString:Wa,_fnRender:S,_fnNodeToColumnIndex:fa,_fnInfoMacros:ja,_fnBrowserDetect:Ua,_fnGetColumns:r};h.extend(j.ext.oApi,this.oApi);for(var sa in j.ext.oApi)sa&&(this[sa]=Va(sa));var ca=this;this.each(function(){var a=0,b,c,d;c=this.getAttribute("id");var i=!1,f=!1;if("table"!=this.nodeName.toLowerCase())D(null,0,"Attempted to initialise DataTables on a node which is not a table: "+ +this.nodeName);else{a=0;for(b=j.settings.length;a<b;a++){if(j.settings[a].nTable==this){if(e===n||e.bRetrieve)return j.settings[a].oInstance;if(e.bDestroy){j.settings[a].oInstance.fnDestroy();break}else{D(j.settings[a],0,"Cannot reinitialise DataTable.\n\nTo retrieve the DataTables object for this table, pass no arguments or see the docs for bRetrieve and bDestroy");return}}if(j.settings[a].sTableId==this.id){j.settings.splice(a,1);break}}if(null===c||""===c)this.id=c="DataTables_Table_"+j.ext._oExternConfig.iNextUnique++; +var g=h.extend(!0,{},j.models.oSettings,{nTable:this,oApi:ca.oApi,oInit:e,sDestroyWidth:h(this).width(),sInstance:c,sTableId:c});j.settings.push(g);g.oInstance=1===ca.length?ca:h(this).dataTable();e||(e={});e.oLanguage&&pa(e.oLanguage);e=Ta(h.extend(!0,{},j.defaults),e);p(g.oFeatures,e,"bPaginate");p(g.oFeatures,e,"bLengthChange");p(g.oFeatures,e,"bFilter");p(g.oFeatures,e,"bSort");p(g.oFeatures,e,"bInfo");p(g.oFeatures,e,"bProcessing");p(g.oFeatures,e,"bAutoWidth");p(g.oFeatures,e,"bSortClasses"); +p(g.oFeatures,e,"bServerSide");p(g.oFeatures,e,"bDeferRender");p(g.oScroll,e,"sScrollX","sX");p(g.oScroll,e,"sScrollXInner","sXInner");p(g.oScroll,e,"sScrollY","sY");p(g.oScroll,e,"bScrollCollapse","bCollapse");p(g.oScroll,e,"bScrollInfinite","bInfinite");p(g.oScroll,e,"iScrollLoadGap","iLoadGap");p(g.oScroll,e,"bScrollAutoCss","bAutoCss");p(g,e,"asStripeClasses");p(g,e,"asStripClasses","asStripeClasses");p(g,e,"fnServerData");p(g,e,"fnFormatNumber");p(g,e,"sServerMethod");p(g,e,"aaSorting");p(g, +e,"aaSortingFixed");p(g,e,"aLengthMenu");p(g,e,"sPaginationType");p(g,e,"sAjaxSource");p(g,e,"sAjaxDataProp");p(g,e,"iCookieDuration");p(g,e,"sCookiePrefix");p(g,e,"sDom");p(g,e,"bSortCellsTop");p(g,e,"iTabIndex");p(g,e,"oSearch","oPreviousSearch");p(g,e,"aoSearchCols","aoPreSearchCols");p(g,e,"iDisplayLength","_iDisplayLength");p(g,e,"bJQueryUI","bJUI");p(g,e,"fnCookieCallback");p(g,e,"fnStateLoad");p(g,e,"fnStateSave");p(g.oLanguage,e,"fnInfoCallback");z(g,"aoDrawCallback",e.fnDrawCallback,"user"); +z(g,"aoServerParams",e.fnServerParams,"user");z(g,"aoStateSaveParams",e.fnStateSaveParams,"user");z(g,"aoStateLoadParams",e.fnStateLoadParams,"user");z(g,"aoStateLoaded",e.fnStateLoaded,"user");z(g,"aoRowCallback",e.fnRowCallback,"user");z(g,"aoRowCreatedCallback",e.fnCreatedRow,"user");z(g,"aoHeaderCallback",e.fnHeaderCallback,"user");z(g,"aoFooterCallback",e.fnFooterCallback,"user");z(g,"aoInitComplete",e.fnInitComplete,"user");z(g,"aoPreDrawCallback",e.fnPreDrawCallback,"user");g.oFeatures.bServerSide&& +g.oFeatures.bSort&&g.oFeatures.bSortClasses?z(g,"aoDrawCallback",P,"server_side_sort_classes"):g.oFeatures.bDeferRender&&z(g,"aoDrawCallback",P,"defer_sort_classes");e.bJQueryUI?(h.extend(g.oClasses,j.ext.oJUIClasses),e.sDom===j.defaults.sDom&&"lfrtip"===j.defaults.sDom&&(g.sDom='<"H"lfr>t<"F"ip>')):h.extend(g.oClasses,j.ext.oStdClasses);h(this).addClass(g.oClasses.sTable);if(""!==g.oScroll.sX||""!==g.oScroll.sY)g.oScroll.iBarWidth=Qa();g.iInitDisplayStart===n&&(g.iInitDisplayStart=e.iDisplayStart, +g._iDisplayStart=e.iDisplayStart);e.bStateSave&&(g.oFeatures.bStateSave=!0,Sa(g,e),z(g,"aoDrawCallback",ra,"state_save"));null!==e.iDeferLoading&&(g.bDeferLoading=!0,a=h.isArray(e.iDeferLoading),g._iRecordsDisplay=a?e.iDeferLoading[0]:e.iDeferLoading,g._iRecordsTotal=a?e.iDeferLoading[1]:e.iDeferLoading);null!==e.aaData&&(f=!0);""!==e.oLanguage.sUrl?(g.oLanguage.sUrl=e.oLanguage.sUrl,h.getJSON(g.oLanguage.sUrl,null,function(a){pa(a);h.extend(true,g.oLanguage,e.oLanguage,a);ba(g)}),i=!0):h.extend(!0, +g.oLanguage,e.oLanguage);null===e.asStripeClasses&&(g.asStripeClasses=[g.oClasses.sStripeOdd,g.oClasses.sStripeEven]);b=g.asStripeClasses.length;g.asDestroyStripes=[];if(b){c=!1;d=h(this).children("tbody").children("tr:lt("+b+")");for(a=0;a<b;a++)d.hasClass(g.asStripeClasses[a])&&(c=!0,g.asDestroyStripes.push(g.asStripeClasses[a]));c&&d.removeClass(g.asStripeClasses.join(" "))}c=[];a=this.getElementsByTagName("thead");0!==a.length&&(V(g.aoHeader,a[0]),c=N(g));if(null===e.aoColumns){d=[];a=0;for(b= +c.length;a<b;a++)d.push(null)}else d=e.aoColumns;a=0;for(b=d.length;a<b;a++)e.saved_aoColumns!==n&&e.saved_aoColumns.length==b&&(null===d[a]&&(d[a]={}),d[a].bVisible=e.saved_aoColumns[a].bVisible),o(g,c?c[a]:null);ta(g,e.aoColumnDefs,d,function(a,b){m(g,a,b)});a=0;for(b=g.aaSorting.length;a<b;a++){g.aaSorting[a][0]>=g.aoColumns.length&&(g.aaSorting[a][0]=0);var k=g.aoColumns[g.aaSorting[a][0]];g.aaSorting[a][2]===n&&(g.aaSorting[a][2]=0);e.aaSorting===n&&g.saved_aaSorting===n&&(g.aaSorting[a][1]= +k.asSorting[0]);c=0;for(d=k.asSorting.length;c<d;c++)if(g.aaSorting[a][1]==k.asSorting[c]){g.aaSorting[a][2]=c;break}}P(g);Ua(g);a=h(this).children("caption").each(function(){this._captionSide=h(this).css("caption-side")});b=h(this).children("thead");0===b.length&&(b=[l.createElement("thead")],this.appendChild(b[0]));g.nTHead=b[0];b=h(this).children("tbody");0===b.length&&(b=[l.createElement("tbody")],this.appendChild(b[0]));g.nTBody=b[0];g.nTBody.setAttribute("role","alert");g.nTBody.setAttribute("aria-live", +"polite");g.nTBody.setAttribute("aria-relevant","all");b=h(this).children("tfoot");if(0===b.length&&0<a.length&&(""!==g.oScroll.sX||""!==g.oScroll.sY))b=[l.createElement("tfoot")],this.appendChild(b[0]);0<b.length&&(g.nTFoot=b[0],V(g.aoFooter,g.nTFoot));if(f)for(a=0;a<e.aaData.length;a++)H(g,e.aaData[a]);else ua(g);g.aiDisplay=g.aiDisplayMaster.slice();g.bInitialised=!0;!1===i&&ba(g)}});ca=null;return this};j.fnVersionCheck=function(e){for(var h=function(e,h){for(;e.length<h;)e+="0";return e},m=j.ext.sVersion.split("."), +e=e.split("."),k="",n="",l=0,t=e.length;l<t;l++)k+=h(m[l],3),n+=h(e[l],3);return parseInt(k,10)>=parseInt(n,10)};j.fnIsDataTable=function(e){for(var h=j.settings,m=0;m<h.length;m++)if(h[m].nTable===e||h[m].nScrollHead===e||h[m].nScrollFoot===e)return!0;return!1};j.fnTables=function(e){var o=[];jQuery.each(j.settings,function(j,k){(!e||!0===e&&h(k.nTable).is(":visible"))&&o.push(k.nTable)});return o};j.version="1.9.4";j.settings=[];j.models={};j.models.ext={afnFiltering:[],afnSortData:[],aoFeatures:[], +aTypes:[],fnVersionCheck:j.fnVersionCheck,iApiIndex:0,ofnSearch:{},oApi:{},oStdClasses:{},oJUIClasses:{},oPagination:{},oSort:{},sVersion:j.version,sErrMode:"alert",_oExternConfig:{iNextUnique:0}};j.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};j.models.oRow={nTr:null,_aData:[],_aSortData:[],_anHidden:[],_sRowStripe:""};j.models.oColumn={aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bUseRendered:null,bVisible:null,_bAutoType:!0,fnCreatedCell:null,fnGetData:null, +fnRender:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};j.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0, +bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollAutoCss:!0,bScrollCollapse:!1,bScrollInfinite:!1,bServerSide:!1,bSort:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCookieCallback:null,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(e){if(1E3>e)return e;for(var h=e+"",e=h.split(""),j="",h=h.length,k=0;k<h;k++)0===k%3&&0!==k&&(j=this.oLanguage.sInfoThousands+j),j=e[h-k-1]+j;return j},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null, +fnRowCallback:null,fnServerData:function(e,j,m,k){k.jqXHR=h.ajax({url:e,data:j,success:function(e){e.sError&&k.oApi._fnLog(k,0,e.sError);h(k.oInstance).trigger("xhr",[k,e]);m(e)},dataType:"json",cache:!1,type:k.sServerMethod,error:function(e,h){"parsererror"==h&&k.oApi._fnLog(k,0,"DataTables warning: JSON data from server could not be parsed. This is caused by a JSON formatting error.")}})},fnServerParams:null,fnStateLoad:function(e){var e=this.oApi._fnReadCookie(e.sCookiePrefix+e.sInstance),j;try{j= +"function"===typeof h.parseJSON?h.parseJSON(e):eval("("+e+")")}catch(m){j=null}return j},fnStateLoadParams:null,fnStateLoaded:null,fnStateSave:function(e,h){this.oApi._fnCreateCookie(e.sCookiePrefix+e.sInstance,this.oApi._fnJsonString(h),e.iCookieDuration,e.sCookiePrefix,e.fnCookieCallback)},fnStateSaveParams:null,iCookieDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iScrollLoadGap:100,iTabIndex:0,oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"}, +oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sInfoThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},j.models.oSearch),sAjaxDataProp:"aaData", +sAjaxSource:null,sCookiePrefix:"SpryMedia_DataTables_",sDom:"lfrtip",sPaginationType:"two_button",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET"};j.defaults.columns={aDataSort:null,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bUseRendered:!0,bVisible:!0,fnCreatedCell:null,fnRender:null,iDataSort:-1,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};j.models.oSettings={oFeatures:{bAutoWidth:null, +bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortClasses:null,bStateSave:null},oScroll:{bAutoCss:null,bCollapse:null,bInfinite:null,iBarWidth:0,iLoadGap:null,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1},aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aoColumns:[],aoHeader:[],aoFooter:[],asDataSearch:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:null, +asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,sPaginationType:"two_button",iCookieDuration:0,sCookiePrefix:"",fnCookieCallback:null,aoStateSave:[],aoStateLoad:[], +oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iDisplayEnd:10,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return this.oFeatures.bServerSide?parseInt(this._iRecordsTotal,10):this.aiDisplayMaster.length}, +fnRecordsDisplay:function(){return this.oFeatures.bServerSide?parseInt(this._iRecordsDisplay,10):this.aiDisplay.length},fnDisplayEnd:function(){return this.oFeatures.bServerSide?!1===this.oFeatures.bPaginate||-1==this._iDisplayLength?this._iDisplayStart+this.aiDisplay.length:Math.min(this._iDisplayStart+this._iDisplayLength,this._iRecordsDisplay):this._iDisplayEnd},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null};j.ext=h.extend(!0,{},j.models.ext);h.extend(j.ext.oStdClasses, +{sTable:"dataTable",sPagePrevEnabled:"paginate_enabled_previous",sPagePrevDisabled:"paginate_disabled_previous",sPageNextEnabled:"paginate_enabled_next",sPageNextDisabled:"paginate_disabled_next",sPageJUINext:"",sPageJUIPrev:"",sPageButton:"paginate_button",sPageButtonActive:"paginate_active",sPageButtonStaticDisabled:"paginate_button paginate_button_disabled",sPageFirst:"first",sPagePrevious:"previous",sPageNext:"next",sPageLast:"last",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty", +sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"", +sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sFooterTH:"",sJUIHeader:"",sJUIFooter:""});h.extend(j.ext.oJUIClasses,j.ext.oStdClasses,{sPagePrevEnabled:"fg-button ui-button ui-state-default ui-corner-left",sPagePrevDisabled:"fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",sPageNextEnabled:"fg-button ui-button ui-state-default ui-corner-right", +sPageNextDisabled:"fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",sPageJUINext:"ui-icon ui-icon-circle-arrow-e",sPageJUIPrev:"ui-icon ui-icon-circle-arrow-w",sPageButton:"fg-button ui-button ui-state-default",sPageButtonActive:"fg-button ui-button ui-state-default ui-state-disabled",sPageButtonStaticDisabled:"fg-button ui-button ui-state-default ui-state-disabled",sPageFirst:"first ui-corner-tl ui-corner-bl",sPageLast:"last ui-corner-tr ui-corner-br",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_", +sSortAsc:"ui-state-default",sSortDesc:"ui-state-default",sSortable:"ui-state-default",sSortableAsc:"ui-state-default",sSortableDesc:"ui-state-default",sSortableNone:"ui-state-default",sSortJUIAsc:"css_right ui-icon ui-icon-triangle-1-n",sSortJUIDesc:"css_right ui-icon ui-icon-triangle-1-s",sSortJUI:"css_right ui-icon ui-icon-carat-2-n-s",sSortJUIAscAllowed:"css_right ui-icon ui-icon-carat-1-n",sSortJUIDescAllowed:"css_right ui-icon ui-icon-carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon", +sScrollHead:"dataTables_scrollHead ui-state-default",sScrollFoot:"dataTables_scrollFoot ui-state-default",sFooterTH:"ui-state-default",sJUIHeader:"fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",sJUIFooter:"fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"});h.extend(j.ext.oPagination,{two_button:{fnInit:function(e,j,m){var k=e.oLanguage.oPaginate,n=function(h){e.oApi._fnPageChange(e,h.data.action)&&m(e)},k=!e.bJUI?'<a class="'+ +e.oClasses.sPagePrevDisabled+'" tabindex="'+e.iTabIndex+'" role="button">'+k.sPrevious+'</a><a class="'+e.oClasses.sPageNextDisabled+'" tabindex="'+e.iTabIndex+'" role="button">'+k.sNext+"</a>":'<a class="'+e.oClasses.sPagePrevDisabled+'" tabindex="'+e.iTabIndex+'" role="button"><span class="'+e.oClasses.sPageJUIPrev+'"></span></a><a class="'+e.oClasses.sPageNextDisabled+'" tabindex="'+e.iTabIndex+'" role="button"><span class="'+e.oClasses.sPageJUINext+'"></span></a>';h(j).append(k);var l=h("a",j), +k=l[0],l=l[1];e.oApi._fnBindAction(k,{action:"previous"},n);e.oApi._fnBindAction(l,{action:"next"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_previous",l.id=e.sTableId+"_next",k.setAttribute("aria-controls",e.sTableId),l.setAttribute("aria-controls",e.sTableId))},fnUpdate:function(e){if(e.aanFeatures.p)for(var h=e.oClasses,j=e.aanFeatures.p,k,l=0,n=j.length;l<n;l++)if(k=j[l].firstChild)k.className=0===e._iDisplayStart?h.sPagePrevDisabled:h.sPagePrevEnabled,k=k.nextSibling, +k.className=e.fnDisplayEnd()==e.fnRecordsDisplay()?h.sPageNextDisabled:h.sPageNextEnabled}},iFullNumbersShowPages:5,full_numbers:{fnInit:function(e,j,m){var k=e.oLanguage.oPaginate,l=e.oClasses,n=function(h){e.oApi._fnPageChange(e,h.data.action)&&m(e)};h(j).append('<a tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPageFirst+'">'+k.sFirst+'</a><a tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPagePrevious+'">'+k.sPrevious+'</a><span></span><a tabindex="'+e.iTabIndex+'" class="'+ +l.sPageButton+" "+l.sPageNext+'">'+k.sNext+'</a><a tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPageLast+'">'+k.sLast+"</a>");var t=h("a",j),k=t[0],l=t[1],r=t[2],t=t[3];e.oApi._fnBindAction(k,{action:"first"},n);e.oApi._fnBindAction(l,{action:"previous"},n);e.oApi._fnBindAction(r,{action:"next"},n);e.oApi._fnBindAction(t,{action:"last"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_first",l.id=e.sTableId+"_previous",r.id=e.sTableId+"_next",t.id=e.sTableId+"_last")}, +fnUpdate:function(e,o){if(e.aanFeatures.p){var m=j.ext.oPagination.iFullNumbersShowPages,k=Math.floor(m/2),l=Math.ceil(e.fnRecordsDisplay()/e._iDisplayLength),n=Math.ceil(e._iDisplayStart/e._iDisplayLength)+1,t="",r,B=e.oClasses,u,M=e.aanFeatures.p,L=function(h){e.oApi._fnBindAction(this,{page:h+r-1},function(h){e.oApi._fnPageChange(e,h.data.page);o(e);h.preventDefault()})};-1===e._iDisplayLength?n=k=r=1:l<m?(r=1,k=l):n<=k?(r=1,k=m):n>=l-k?(r=l-m+1,k=l):(r=n-Math.ceil(m/2)+1,k=r+m-1);for(m=r;m<=k;m++)t+= +n!==m?'<a tabindex="'+e.iTabIndex+'" class="'+B.sPageButton+'">'+e.fnFormatNumber(m)+"</a>":'<a tabindex="'+e.iTabIndex+'" class="'+B.sPageButtonActive+'">'+e.fnFormatNumber(m)+"</a>";m=0;for(k=M.length;m<k;m++)u=M[m],u.hasChildNodes()&&(h("span:eq(0)",u).html(t).children("a").each(L),u=u.getElementsByTagName("a"),u=[u[0],u[1],u[u.length-2],u[u.length-1]],h(u).removeClass(B.sPageButton+" "+B.sPageButtonActive+" "+B.sPageButtonStaticDisabled),h([u[0],u[1]]).addClass(1==n?B.sPageButtonStaticDisabled: +B.sPageButton),h([u[2],u[3]]).addClass(0===l||n===l||-1===e._iDisplayLength?B.sPageButtonStaticDisabled:B.sPageButton))}}}});h.extend(j.ext.oSort,{"string-pre":function(e){"string"!=typeof e&&(e=null!==e&&e.toString?e.toString():"");return e.toLowerCase()},"string-asc":function(e,h){return e<h?-1:e>h?1:0},"string-desc":function(e,h){return e<h?1:e>h?-1:0},"html-pre":function(e){return e.replace(/<.*?>/g,"").toLowerCase()},"html-asc":function(e,h){return e<h?-1:e>h?1:0},"html-desc":function(e,h){return e< +h?1:e>h?-1:0},"date-pre":function(e){e=Date.parse(e);if(isNaN(e)||""===e)e=Date.parse("01/01/1970 00:00:00");return e},"date-asc":function(e,h){return e-h},"date-desc":function(e,h){return h-e},"numeric-pre":function(e){return"-"==e||""===e?0:1*e},"numeric-asc":function(e,h){return e-h},"numeric-desc":function(e,h){return h-e}});h.extend(j.ext.aTypes,[function(e){if("number"===typeof e)return"numeric";if("string"!==typeof e)return null;var h,j=!1;h=e.charAt(0);if(-1=="0123456789-".indexOf(h))return null; +for(var k=1;k<e.length;k++){h=e.charAt(k);if(-1=="0123456789.".indexOf(h))return null;if("."==h){if(j)return null;j=!0}}return"numeric"},function(e){var h=Date.parse(e);return null!==h&&!isNaN(h)||"string"===typeof e&&0===e.length?"date":null},function(e){return"string"===typeof e&&-1!=e.indexOf("<")&&-1!=e.indexOf(">")?"html":null}]);h.fn.DataTable=j;h.fn.dataTable=j;h.fn.dataTableSettings=j.settings;h.fn.dataTableExt=j.ext};"function"===typeof define&&define.amd?define(["jquery"],L):jQuery&&!jQuery.fn.dataTable&& +L(jQuery)})(window,document); diff --git a/src/static/jquery/datatables/media/js/jquery.js b/src/static/jquery/datatables/media/js/jquery.js new file mode 100644 index 0000000..63174a0 --- /dev/null +++ b/src/static/jquery/datatables/media/js/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call(" ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/src/static/jquery/jquery-1.8.3.min.js b/src/static/jquery/jquery-1.8.3.min.js new file mode 100644 index 0000000..83589da --- /dev/null +++ b/src/static/jquery/jquery-1.8.3.min.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.3 jquery.com | jquery.org/license */ +(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r<i;r++)v.event.add(t,n,u[n][r])}o.data&&(o.data=v.extend({},o.data))}function Ot(e,t){var n;if(t.nodeType!==1)return;t.clearAttributes&&t.clearAttributes(),t.mergeAttributes&&t.mergeAttributes(e),n=t.nodeName.toLowerCase(),n==="object"?(t.parentNode&&(t.outerHTML=e.outerHTML),v.support.html5Clone&&e.innerHTML&&!v.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):n==="input"&&Et.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):n==="option"?t.selected=e.defaultSelected:n==="input"||n==="textarea"?t.defaultValue=e.defaultValue:n==="script"&&t.text!==e.text&&(t.text=e.text),t.removeAttribute(v.expando)}function Mt(e){return typeof e.getElementsByTagName!="undefined"?e.getElementsByTagName("*"):typeof e.querySelectorAll!="undefined"?e.querySelectorAll("*"):[]}function _t(e){Et.test(e.type)&&(e.defaultChecked=e.checked)}function Qt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Jt.length;while(i--){t=Jt[i]+n;if(t in e)return t}return r}function Gt(e,t){return e=t||e,v.css(e,"display")==="none"||!v.contains(e.ownerDocument,e)}function Yt(e,t){var n,r,i=[],s=0,o=e.length;for(;s<o;s++){n=e[s];if(!n.style)continue;i[s]=v._data(n,"olddisplay"),t?(!i[s]&&n.style.display==="none"&&(n.style.display=""),n.style.display===""&&Gt(n)&&(i[s]=v._data(n,"olddisplay",nn(n.nodeName)))):(r=Dt(n,"display"),!i[s]&&r!=="none"&&v._data(n,"olddisplay",r))}for(s=0;s<o;s++){n=e[s];if(!n.style)continue;if(!t||n.style.display==="none"||n.style.display==="")n.style.display=t?i[s]||"":"none"}return e}function Zt(e,t,n){var r=Rt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function en(e,t,n,r){var i=n===(r?"border":"content")?4:t==="width"?1:0,s=0;for(;i<4;i+=2)n==="margin"&&(s+=v.css(e,n+$t[i],!0)),r?(n==="content"&&(s-=parseFloat(Dt(e,"padding"+$t[i]))||0),n!=="margin"&&(s-=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0)):(s+=parseFloat(Dt(e,"padding"+$t[i]))||0,n!=="padding"&&(s+=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0));return s}function tn(e,t,n){var r=t==="width"?e.offsetWidth:e.offsetHeight,i=!0,s=v.support.boxSizing&&v.css(e,"boxSizing")==="border-box";if(r<=0||r==null){r=Dt(e,t);if(r<0||r==null)r=e.style[t];if(Ut.test(r))return r;i=s&&(v.support.boxSizingReliable||r===e.style[t]),r=parseFloat(r)||0}return r+en(e,t,n||(s?"border":"content"),i)+"px"}function nn(e){if(Wt[e])return Wt[e];var t=v("<"+e+">").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write("<!doctype html><html><body>"),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u<a;u++)r=o[u],s=/^\+/.test(r),s&&(r=r.substr(1)||"*"),i=e[r]=e[r]||[],i[s?"unshift":"push"](n)}}function kn(e,n,r,i,s,o){s=s||n.dataTypes[0],o=o||{},o[s]=!0;var u,a=e[s],f=0,l=a?a.length:0,c=e===Sn;for(;f<l&&(c||!u);f++)u=a[f](n,r,i),typeof u=="string"&&(!c||o[u]?u=t:(n.dataTypes.unshift(u),u=kn(e,n,r,i,u,o)));return(c||!u)&&!o["*"]&&(u=kn(e,n,r,i,"*",o)),u}function Ln(e,n){var r,i,s=v.ajaxSettings.flatOptions||{};for(r in n)n[r]!==t&&((s[r]?e:i||(i={}))[r]=n[r]);i&&v.extend(!0,e,i)}function An(e,n,r){var i,s,o,u,a=e.contents,f=e.dataTypes,l=e.responseFields;for(s in l)s in r&&(n[l[s]]=r[s]);while(f[0]==="*")f.shift(),i===t&&(i=e.mimeType||n.getResponseHeader("content-type"));if(i)for(s in a)if(a[s]&&a[s].test(i)){f.unshift(s);break}if(f[0]in r)o=f[0];else{for(s in r){if(!f[0]||e.converters[s+" "+f[0]]){o=s;break}u||(u=s)}o=o||u}if(o)return o!==f[0]&&f.unshift(o),r[o]}function On(e,t){var n,r,i,s,o=e.dataTypes.slice(),u=o[0],a={},f=0;e.dataFilter&&(t=e.dataFilter(t,e.dataType));if(o[1])for(n in e.converters)a[n.toLowerCase()]=e.converters[n];for(;i=o[++f];)if(i!=="*"){if(u!=="*"&&u!==i){n=a[u+" "+i]||a["* "+i];if(!n)for(r in a){s=r.split(" ");if(s[1]===i){n=a[u+" "+s[0]]||a["* "+s[0]];if(n){n===!0?n=a[r]:a[r]!==!0&&(i=s[0],o.splice(f--,0,i));break}}}if(n!==!0)if(n&&e["throws"])t=n(t);else try{t=n(t)}catch(l){return{state:"parsererror",error:n?l:"No conversion from "+u+" to "+i}}}u=i}return{state:"success",data:t}}function Fn(){try{return new e.XMLHttpRequest}catch(t){}}function In(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function $n(){return setTimeout(function(){qn=t},0),qn=v.now()}function Jn(e,t){v.each(t,function(t,n){var r=(Vn[t]||[]).concat(Vn["*"]),i=0,s=r.length;for(;i<s;i++)if(r[i].call(e,t,n))return})}function Kn(e,t,n){var r,i=0,s=0,o=Xn.length,u=v.Deferred().always(function(){delete a.elem}),a=function(){var t=qn||$n(),n=Math.max(0,f.startTime+f.duration-t),r=n/f.duration||0,i=1-r,s=0,o=f.tweens.length;for(;s<o;s++)f.tweens[s].run(i);return u.notifyWith(e,[f,i,n]),i<1&&o?n:(u.resolveWith(e,[f]),!1)},f=u.promise({elem:e,props:v.extend({},t),opts:v.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:qn||$n(),duration:n.duration,tweens:[],createTween:function(t,n,r){var i=v.Tween(e,f.opts,t,n,f.opts.specialEasing[t]||f.opts.easing);return f.tweens.push(i),i},stop:function(t){var n=0,r=t?f.tweens.length:0;for(;n<r;n++)f.tweens[n].run(1);return t?u.resolveWith(e,[f,t]):u.rejectWith(e,[f,t]),this}}),l=f.props;Qn(l,f.opts.specialEasing);for(;i<o;i++){r=Xn[i].call(f,e,l,f.opts);if(r)return r}return Jn(f,l),v.isFunction(f.opts.start)&&f.opts.start.call(e,f),v.fx.timer(v.extend(a,{anim:f,queue:f.opts.queue,elem:e})),f.progress(f.opts.progress).done(f.opts.done,f.opts.complete).fail(f.opts.fail).always(f.opts.always)}function Qn(e,t){var n,r,i,s,o;for(n in e){r=v.camelCase(n),i=t[r],s=e[n],v.isArray(s)&&(i=s[1],s=e[n]=s[0]),n!==r&&(e[r]=s,delete e[n]),o=v.cssHooks[r];if(o&&"expand"in o){s=o.expand(s),delete e[r];for(n in s)n in e||(e[n]=s[n],t[n]=i)}else t[r]=i}}function Gn(e,t,n){var r,i,s,o,u,a,f,l,c,h=this,p=e.style,d={},m=[],g=e.nodeType&&Gt(e);n.queue||(l=v._queueHooks(e,"fx"),l.unqueued==null&&(l.unqueued=0,c=l.empty.fire,l.empty.fire=function(){l.unqueued||c()}),l.unqueued++,h.always(function(){h.always(function(){l.unqueued--,v.queue(e,"fx").length||l.empty.fire()})})),e.nodeType===1&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],v.css(e,"display")==="inline"&&v.css(e,"float")==="none"&&(!v.support.inlineBlockNeedsLayout||nn(e.nodeName)==="inline"?p.display="inline-block":p.zoom=1)),n.overflow&&(p.overflow="hidden",v.support.shrinkWrapBlocks||h.done(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t){s=t[r];if(Un.exec(s)){delete t[r],a=a||s==="toggle";if(s===(g?"hide":"show"))continue;m.push(r)}}o=m.length;if(o){u=v._data(e,"fxshow")||v._data(e,"fxshow",{}),"hidden"in u&&(g=u.hidden),a&&(u.hidden=!g),g?v(e).show():h.done(function(){v(e).hide()}),h.done(function(){var t;v.removeData(e,"fxshow",!0);for(t in d)v.style(e,t,d[t])});for(r=0;r<o;r++)i=m[r],f=h.createTween(i,g?u[i]:0),d[i]=u[i]||v.style(e,i),i in u||(u[i]=f.start,g&&(f.end=f.start,f.start=i==="width"||i==="height"?1:0))}}function Yn(e,t,n,r,i){return new Yn.prototype.init(e,t,n,r,i)}function Zn(e,t){var n,r={height:e},i=0;t=t?1:0;for(;i<4;i+=2-t)n=$t[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}function tr(e){return v.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:!1}var n,r,i=e.document,s=e.location,o=e.navigator,u=e.jQuery,a=e.$,f=Array.prototype.push,l=Array.prototype.slice,c=Array.prototype.indexOf,h=Object.prototype.toString,p=Object.prototype.hasOwnProperty,d=String.prototype.trim,v=function(e,t){return new v.fn.init(e,t,n)},m=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,g=/\S/,y=/\s+/,b=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,w=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a<f;a++)if((e=arguments[a])!=null)for(n in e){r=u[n],i=e[n];if(u===i)continue;l&&i&&(v.isPlainObject(i)||(s=v.isArray(i)))?(s?(s=!1,o=r&&v.isArray(r)?r:[]):o=r&&v.isPlainObject(r)?r:{},u[n]=v.extend(l,o,i)):i!==t&&(u[n]=i)}return u},v.extend({noConflict:function(t){return e.$===v&&(e.$=a),t&&e.jQuery===v&&(e.jQuery=u),v},isReady:!1,readyWait:1,holdReady:function(e){e?v.readyWait++:v.ready(!0)},ready:function(e){if(e===!0?--v.readyWait:v.isReady)return;if(!i.body)return setTimeout(v.ready,1);v.isReady=!0;if(e!==!0&&--v.readyWait>0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s<o;)if(n.apply(e[s++],r)===!1)break}else if(u){for(i in e)if(n.call(e[i],i,e[i])===!1)break}else for(;s<o;)if(n.call(e[s],s,e[s++])===!1)break;return e},trim:d&&!d.call("\ufeff\u00a0")?function(e){return e==null?"":d.call(e)}:function(e){return e==null?"":(e+"").replace(b,"")},makeArray:function(e,t){var n,r=t||[];return e!=null&&(n=v.type(e),e.length==null||n==="string"||n==="function"||n==="regexp"||v.isWindow(e)?f.call(r,e):v.merge(r,e)),r},inArray:function(e,t,n){var r;if(t){if(c)return c.call(t,e,n);r=t.length,n=n?n<0?Math.max(0,r+n):n:0;for(;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,s=0;if(typeof r=="number")for(;s<r;s++)e[i++]=n[s];else while(n[s]!==t)e[i++]=n[s++];return e.length=i,e},grep:function(e,t,n){var r,i=[],s=0,o=e.length;n=!!n;for(;s<o;s++)r=!!t(e[s],s),n!==r&&i.push(e[s]);return i},map:function(e,n,r){var i,s,o=[],u=0,a=e.length,f=e instanceof v||a!==t&&typeof a=="number"&&(a>0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u<a;u++)i=n(e[u],u,r),i!=null&&(o[o.length]=i);else for(s in e)i=n(e[s],s,r),i!=null&&(o[o.length]=i);return o.concat.apply([],o)},guid:1,proxy:function(e,n){var r,i,s;return typeof n=="string"&&(r=e[n],n=e,e=r),v.isFunction(e)?(i=l.call(arguments,2),s=function(){return e.apply(n,i.concat(l.call(arguments)))},s.guid=e.guid=e.guid||v.guid++,s):t},access:function(e,n,r,i,s,o,u){var a,f=r==null,l=0,c=e.length;if(r&&typeof r=="object"){for(l in r)v.access(e,n,l,r[l],1,o,i);s=1}else if(i!==t){a=u===t&&v.isFunction(i),f&&(a?(a=n,n=function(e,t,n){return a.call(v(e),n)}):(n.call(e,i),n=null));if(n)for(;l<c;l++)n(e[l],r,a?i.call(e[l],l,n(e[l],r)):i,u);s=1}return s?e:f?n.call(e):c?n(e[0],r):o},now:function(){return(new Date).getTime()}}),v.ready.promise=function(t){if(!r){r=v.Deferred();if(i.readyState==="complete")setTimeout(v.ready,1);else if(i.addEventListener)i.addEventListener("DOMContentLoaded",A,!1),e.addEventListener("load",v.ready,!1);else{i.attachEvent("onreadystatechange",A),e.attachEvent("onload",v.ready);var n=!1;try{n=e.frameElement==null&&i.documentElement}catch(s){}n&&n.doScroll&&function o(){if(!v.isReady){try{n.doScroll("left")}catch(e){return setTimeout(o,50)}v.ready()}}()}}return r.promise(t)},v.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(e,t){O["[object "+t+"]"]=t.toLowerCase()}),n=v(i);var M={};v.Callbacks=function(e){e=typeof e=="string"?M[e]||_(e):v.extend({},e);var n,r,i,s,o,u,a=[],f=!e.once&&[],l=function(t){n=e.memory&&t,r=!0,u=s||0,s=0,o=a.length,i=!0;for(;a&&u<o;u++)if(a[u].apply(t[0],t[1])===!1&&e.stopOnFalse){n=!1;break}i=!1,a&&(f?f.length&&l(f.shift()):n?a=[]:c.disable())},c={add:function(){if(a){var t=a.length;(function r(t){v.each(t,function(t,n){var i=v.type(n);i==="function"?(!e.unique||!c.has(n))&&a.push(n):n&&n.length&&i!=="string"&&r(n)})})(arguments),i?o=a.length:n&&(s=t,l(n))}return this},remove:function(){return a&&v.each(arguments,function(e,t){var n;while((n=v.inArray(t,a,n))>-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t<r;t++)n[t]&&v.isFunction(n[t].promise)?n[t].promise().done(o(t,f,n)).fail(s.reject).progress(o(t,a,u)):--i}return i||s.resolveWith(f,n),s.promise()}}),v.support=function(){var t,n,r,s,o,u,a,f,l,c,h,p=i.createElement("div");p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="<table><tr><td></td><td>t</td></tr></table>",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="<div></div>",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i<s;i++)delete r[t[i]];if(!(n?B:v.isEmptyObject)(r))return}}if(!n){delete u[a].data;if(!B(u[a]))return}o?v.cleanData([e],!0):v.support.deleteExpando||u!=u.window?delete u[a]:u[a]=null},_data:function(e,t,n){return v.data(e,t,n,!0)},acceptData:function(e){var t=e.nodeName&&v.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),v.fn.extend({data:function(e,n){var r,i,s,o,u,a=this[0],f=0,l=null;if(e===t){if(this.length){l=v.data(a);if(a.nodeType===1&&!v._data(a,"parsedAttrs")){s=a.attributes;for(u=s.length;f<u;f++)o=s[f].name,o.indexOf("data-")||(o=v.camelCase(o.substring(5)),H(a,o,l[o]));v._data(a,"parsedAttrs",!0)}}return l}return typeof e=="object"?this.each(function(){v.data(this,e)}):(r=e.split(".",2),r[1]=r[1]?"."+r[1]:"",i=r[1]+"!",v.access(this,function(n){if(n===t)return l=this.triggerHandler("getData"+i,[r[0]]),l===t&&a&&(l=v.data(a,e),l=H(a,e,l)),l===t&&r[1]?this.data(r[0]):l;r[1]=n,this.each(function(){var t=v(this);t.triggerHandler("setData"+i,r),v.data(this,e,n),t.triggerHandler("changeData"+i,r)})},null,n,arguments.length>1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length<r?v.queue(this[0],e):n===t?this:this.each(function(){var t=v.queue(this,e,n);v._queueHooks(this,e),e==="fx"&&t[0]!=="inprogress"&&v.dequeue(this,e)})},dequeue:function(e){return this.each(function(){v.dequeue(this,e)})},delay:function(e,t){return e=v.fx?v.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,s=v.Deferred(),o=this,u=this.length,a=function(){--i||s.resolveWith(o,[o])};typeof e!="string"&&(n=e,e=t),e=e||"fx";while(u--)r=v._data(o[u],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(a));return a(),s.promise(n)}});var j,F,I,q=/[\t\r\n]/g,R=/\r/g,U=/^(?:button|input)$/i,z=/^(?:button|input|object|select|textarea)$/i,W=/^a(?:rea|)$/i,X=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,V=v.support.getSetAttribute;v.fn.extend({attr:function(e,t){return v.access(this,v.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n<r;n++){i=this[n];if(i.nodeType===1)if(!i.className&&t.length===1)i.className=e;else{s=" "+i.className+" ";for(o=0,u=t.length;o<u;o++)s.indexOf(" "+t[o]+" ")<0&&(s+=t[o]+" ");i.className=v.trim(s)}}}return this},removeClass:function(e){var n,r,i,s,o,u,a;if(v.isFunction(e))return this.each(function(t){v(this).removeClass(e.call(this,t,this.className))});if(e&&typeof e=="string"||e===t){n=(e||"").split(y);for(u=0,a=this.length;u<a;u++){i=this[u];if(i.nodeType===1&&i.className){r=(" "+i.className+" ").replace(q," ");for(s=0,o=n.length;s<o;s++)while(r.indexOf(" "+n[s]+" ")>=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n<r;n++)if(this[n].nodeType===1&&(" "+this[n].className+" ").replace(q," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a<u;a++){n=r[a];if((n.selected||a===i)&&(v.support.optDisabled?!n.disabled:n.getAttribute("disabled")===null)&&(!n.parentNode.disabled||!v.nodeName(n.parentNode,"optgroup"))){t=v(n).val();if(s)return t;o.push(t)}}return o},set:function(e,t){var n=v.makeArray(t);return v(e).find("option").each(function(){this.selected=v.inArray(v(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o<r.length;o++)i=r[o],i&&(n=v.propFix[i]||i,s=X.test(i),s||v.attr(e,i,""),e.removeAttribute(V?i:n),s&&n in e&&(e[n]=!1))}},attrHooks:{type:{set:function(e,t){if(U.test(e.nodeName)&&e.parentNode)v.error("type property can't be changed");else if(!v.support.radioValue&&t==="radio"&&v.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}},value:{get:function(e,t){return j&&v.nodeName(e,"button")?j.get(e,t):t in e?e.value:null},set:function(e,t,n){if(j&&v.nodeName(e,"button"))return j.set(e,t,n);e.value=t}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,s,o,u=e.nodeType;if(!e||u===3||u===8||u===2)return;return o=u!==1||!v.isXMLDoc(e),o&&(n=v.propFix[n]||n,s=v.propHooks[n]),r!==t?s&&"set"in s&&(i=s.set(e,r,n))!==t?i:e[n]=r:s&&"get"in s&&(i=s.get(e,n))!==null?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):z.test(e.nodeName)||W.test(e.nodeName)&&e.href?0:t}}}}),F={get:function(e,n){var r,i=v.prop(e,n);return i===!0||typeof i!="boolean"&&(r=e.getAttributeNode(n))&&r.nodeValue!==!1?n.toLowerCase():t},set:function(e,t,n){var r;return t===!1?v.removeAttr(e,n):(r=v.propFix[n]||n,r in e&&(e[r]=!0),e.setAttribute(n,n.toLowerCase())),n}},V||(I={name:!0,id:!0,coords:!0},j=v.valHooks.button={get:function(e,n){var r;return r=e.getAttributeNode(n),r&&(I[n]?r.value!=="":r.specified)?r.value:t},set:function(e,t,n){var r=e.getAttributeNode(n);return r||(r=i.createAttribute(n),e.setAttributeNode(r)),r.value=t+""}},v.each(["width","height"],function(e,t){v.attrHooks[t]=v.extend(v.attrHooks[t],{set:function(e,n){if(n==="")return e.setAttribute(t,"auto"),n}})}),v.attrHooks.contenteditable={get:j.get,set:function(e,t,n){t===""&&(t="false"),j.set(e,t,n)}}),v.support.hrefNormalized||v.each(["href","src","width","height"],function(e,n){v.attrHooks[n]=v.extend(v.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return r===null?t:r}})}),v.support.style||(v.attrHooks.style={get:function(e){return e.style.cssText.toLowerCase()||t},set:function(e,t){return e.style.cssText=t+""}}),v.support.optSelected||(v.propHooks.selected=v.extend(v.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),v.support.enctype||(v.propFix.enctype="encoding"),v.support.checkOn||v.each(["radio","checkbox"],function(){v.valHooks[this]={get:function(e){return e.getAttribute("value")===null?"on":e.value}}}),v.each(["radio","checkbox"],function(){v.valHooks[this]=v.extend(v.valHooks[this],{set:function(e,t){if(v.isArray(t))return e.checked=v.inArray(v(e).val(),t)>=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f<n.length;f++){l=J.exec(n[f])||[],c=l[1],h=(l[2]||"").split(".").sort(),g=v.event.special[c]||{},c=(s?g.delegateType:g.bindType)||c,g=v.event.special[c]||{},p=v.extend({type:c,origType:l[1],data:i,handler:r,guid:r.guid,selector:s,needsContext:s&&v.expr.match.needsContext.test(s),namespace:h.join(".")},d),m=a[c];if(!m){m=a[c]=[],m.delegateCount=0;if(!g.setup||g.setup.call(e,i,h,u)===!1)e.addEventListener?e.addEventListener(c,u,!1):e.attachEvent&&e.attachEvent("on"+c,u)}g.add&&(g.add.call(e,p),p.handler.guid||(p.handler.guid=r.guid)),s?m.splice(m.delegateCount++,0,p):m.push(p),v.event.global[c]=!0}e=null},global:{},remove:function(e,t,n,r,i){var s,o,u,a,f,l,c,h,p,d,m,g=v.hasData(e)&&v._data(e);if(!g||!(h=g.events))return;t=v.trim(Z(t||"")).split(" ");for(s=0;s<t.length;s++){o=J.exec(t[s])||[],u=a=o[1],f=o[2];if(!u){for(u in h)v.event.remove(e,u+t[s],n,r,!0);continue}p=v.event.special[u]||{},u=(r?p.delegateType:p.bindType)||u,d=h[u]||[],l=d.length,f=f?new RegExp("(^|\\.)"+f.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(c=0;c<d.length;c++)m=d[c],(i||a===m.origType)&&(!n||n.guid===m.guid)&&(!f||f.test(m.namespace))&&(!r||r===m.selector||r==="**"&&m.selector)&&(d.splice(c--,1),m.selector&&d.delegateCount--,p.remove&&p.remove.call(e,m));d.length===0&&l!==d.length&&((!p.teardown||p.teardown.call(e,f,g.handle)===!1)&&v.removeEvent(e,u,g.handle),delete h[u])}v.isEmptyObject(h)&&(delete g.handle,v.removeData(e,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(n,r,s,o){if(!s||s.nodeType!==3&&s.nodeType!==8){var u,a,f,l,c,h,p,d,m,g,y=n.type||n,b=[];if(Y.test(y+v.event.triggered))return;y.indexOf("!")>=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f<m.length&&!n.isPropagationStopped();f++)l=m[f][0],n.type=m[f][1],d=(v._data(l,"events")||{})[n.type]&&v._data(l,"handle"),d&&d.apply(l,r),d=h&&l[h],d&&v.acceptData(l)&&d.apply&&d.apply(l,r)===!1&&n.preventDefault();return n.type=y,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(s.ownerDocument,r)===!1)&&(y!=="click"||!v.nodeName(s,"a"))&&v.acceptData(s)&&h&&s[y]&&(y!=="focus"&&y!=="blur"||n.target.offsetWidth!==0)&&!v.isWindow(s)&&(c=s[h],c&&(s[h]=null),v.event.triggered=y,s[y](),v.event.triggered=t,c&&(s[h]=c)),n.result}return},dispatch:function(n){n=v.event.fix(n||e.event);var r,i,s,o,u,a,f,c,h,p,d=(v._data(this,"events")||{})[n.type]||[],m=d.delegateCount,g=l.call(arguments),y=!n.exclusive&&!n.namespace,b=v.event.special[n.type]||{},w=[];g[0]=n,n.delegateTarget=this;if(b.preDispatch&&b.preDispatch.call(this,n)===!1)return;if(m&&(!n.button||n.type!=="click"))for(s=n.target;s!=this;s=s.parentNode||this)if(s.disabled!==!0||n.type!=="click"){u={},f=[];for(r=0;r<m;r++)c=d[r],h=c.selector,u[h]===t&&(u[h]=c.needsContext?v(h,this).index(s)>=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r<w.length&&!n.isPropagationStopped();r++){a=w[r],n.currentTarget=a.elem;for(i=0;i<a.matches.length&&!n.isImmediatePropagationStopped();i++){c=a.matches[i];if(y||!n.namespace&&!c.namespace||n.namespace_re&&n.namespace_re.test(c.namespace))n.data=c.data,n.handleObj=c,o=((v.event.special[c.origType]||{}).handle||c.handler).apply(a.elem,g),o!==t&&(n.result=o,o===!1&&(n.preventDefault(),n.stopPropagation()))}}return b.postDispatch&&b.postDispatch.call(this,n),n.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return e.which==null&&(e.which=t.charCode!=null?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,s,o,u=n.button,a=n.fromElement;return e.pageX==null&&n.clientX!=null&&(r=e.target.ownerDocument||i,s=r.documentElement,o=r.body,e.pageX=n.clientX+(s&&s.scrollLeft||o&&o.scrollLeft||0)-(s&&s.clientLeft||o&&o.clientLeft||0),e.pageY=n.clientY+(s&&s.scrollTop||o&&o.scrollTop||0)-(s&&s.clientTop||o&&o.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?n.toElement:a),!e.which&&u!==t&&(e.which=u&1?1:u&2?3:u&4?2:0),e}},fix:function(e){if(e[v.expando])return e;var t,n,r=e,s=v.event.fixHooks[e.type]||{},o=s.props?this.props.concat(s.props):this.props;e=v.Event(r);for(t=o.length;t;)n=o[--t],e[n]=r[n];return e.target||(e.target=r.srcElement||i),e.target.nodeType===3&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,r):e},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(e,t,n){v.isWindow(this)&&(this.onbeforeunload=n)},teardown:function(e,t){this.onbeforeunload===t&&(this.onbeforeunload=null)}}},simulate:function(e,t,n,r){var i=v.extend(new v.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?v.event.trigger(i,null,t):v.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},v.event.handle=v.event.dispatch,v.removeEvent=i.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]=="undefined"&&(e[r]=null),e.detachEvent(r,n))},v.Event=function(e,t){if(!(this instanceof v.Event))return new v.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?tt:et):this.type=e,t&&v.extend(this,t),this.timeStamp=e&&e.timeStamp||v.now(),this[v.expando]=!0},v.Event.prototype={preventDefault:function(){this.isDefaultPrevented=tt;var e=this.originalEvent;if(!e)return;e.preventDefault?e.preventDefault():e.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=tt;var e=this.originalEvent;if(!e)return;e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=tt,this.stopPropagation()},isDefaultPrevented:et,isPropagationStopped:et,isImmediatePropagationStopped:et},v.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){v.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,s=e.handleObj,o=s.selector;if(!i||i!==r&&!v.contains(r,i))e.type=s.origType,n=s.handler.apply(this,arguments),e.type=t;return n}}}),v.support.submitBubbles||(v.event.special.submit={setup:function(){if(v.nodeName(this,"form"))return!1;v.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=v.nodeName(n,"input")||v.nodeName(n,"button")?n.form:t;r&&!v._data(r,"_submit_attached")&&(v.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),v._data(r,"_submit_attached",!0))})},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&v.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){if(v.nodeName(this,"form"))return!1;v.event.remove(this,"._submit")}}),v.support.changeBubbles||(v.event.special.change={setup:function(){if($.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")v.event.add(this,"propertychange._change",function(e){e.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),v.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),v.event.simulate("change",this,e,!0)});return!1}v.event.add(this,"beforeactivate._change",function(e){var t=e.target;$.test(t.nodeName)&&!v._data(t,"_change_attached")&&(v.event.add(t,"change._change",function(e){this.parentNode&&!e.isSimulated&&!e.isTrigger&&v.event.simulate("change",this.parentNode,e,!0)}),v._data(t,"_change_attached",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||t.type!=="radio"&&t.type!=="checkbox")return e.handleObj.handler.apply(this,arguments)},teardown:function(){return v.event.remove(this,"._change"),!$.test(this.nodeName)}}),v.support.focusinBubbles||v.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){v.event.simulate(t,e.target,v.event.fix(e),!0)};v.event.special[t]={setup:function(){n++===0&&i.addEventListener(e,r,!0)},teardown:function(){--n===0&&i.removeEventListener(e,r,!0)}}}),v.fn.extend({on:function(e,n,r,i,s){var o,u;if(typeof e=="object"){typeof n!="string"&&(r=r||n,n=t);for(u in e)this.on(u,n,r,e[u],s);return this}r==null&&i==null?(i=n,r=n=t):i==null&&(typeof n=="string"?(i=r,r=t):(i=r,r=n,n=t));if(i===!1)i=et;else if(!i)return this;return s===1&&(o=i,i=function(e){return v().off(e),o.apply(this,arguments)},i.guid=o.guid||(o.guid=v.guid++)),this.each(function(){v.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,s;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,v(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if(typeof e=="object"){for(s in e)this.off(s,n,e[s]);return this}if(n===!1||typeof n=="function")r=n,n=t;return r===!1&&(r=et),this.each(function(){v.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},live:function(e,t,n){return v(this.context).on(e,this.selector,t,n),this},die:function(e,t){return v(this.context).off(e,this.selector||"**",t),this},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return arguments.length===1?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){v.event.trigger(e,t,this)})},triggerHandler:function(e,t){if(this[0])return v.event.trigger(e,t,this[0],!0)},toggle:function(e){var t=arguments,n=e.guid||v.guid++,r=0,i=function(n){var i=(v._data(this,"lastToggle"+e.guid)||0)%r;return v._data(this,"lastToggle"+e.guid,i+1),n.preventDefault(),t[i].apply(this,arguments)||!1};i.guid=n;while(r<t.length)t[r++].guid=n;return this.click(i)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),v.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){v.fn[t]=function(e,n){return n==null&&(n=e,e=null),arguments.length>0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u<a;u++)if(s=e[u])if(!n||n(s,r,i))o.push(s),f&&t.push(u);return o}function ct(e,t,n,r,i,s){return r&&!r[d]&&(r=ct(r)),i&&!i[d]&&(i=ct(i,s)),N(function(s,o,u,a){var f,l,c,h=[],p=[],d=o.length,v=s||dt(t||"*",u.nodeType?[u]:u,[]),m=e&&(s||!t)?lt(v,h,e,u,a):v,g=n?i||(s?e:d||r)?[]:o:m;n&&n(m,g,u,a);if(r){f=lt(g,p),r(f,[],u,a),l=f.length;while(l--)if(c=f[l])g[p[l]]=!(m[p[l]]=c)}if(s){if(i||e){if(i){f=[],l=g.length;while(l--)(c=g[l])&&f.push(m[l]=c);i(null,g=[],f,a)}l=g.length;while(l--)(c=g[l])&&(f=i?T.call(s,c):h[l])>-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a<s;a++)if(n=i.relative[e[a].type])h=[at(ft(h),n)];else{n=i.filter[e[a].type].apply(null,e[a].matches);if(n[d]){r=++a;for(;r<s;r++)if(i.relative[e[r].type])break;return ct(a>1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a<r&&ht(e.slice(a,r)),r<s&&ht(e=e.slice(r)),r<s&&e.join(""))}h.push(n)}return ft(h)}function pt(e,t){var r=t.length>0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r<i;r++)nt(e,t[r],n);return n}function vt(e,t,n,r,s){var o,u,f,l,c,h=ut(e),p=h.length;if(!r&&h.length===1){u=h[0]=h[0].slice(0);if(u.length>2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;t<n;t++)if(this[t]===e)return t;return-1},N=function(e,t){return e[d]=t==null||t,e},C=function(){var e={},t=[];return N(function(n,r){return t.push(n)>i.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="<a name='"+d+"'></a><div name='"+d+"'></div>",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:st(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:st(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},f=y.compareDocumentPosition?function(e,t){return e===t?(l=!0,0):(!e.compareDocumentPosition||!t.compareDocumentPosition?e.compareDocumentPosition:e.compareDocumentPosition(t)&4)?-1:1}:function(e,t){if(e===t)return l=!0,0;if(e.sourceIndex&&t.sourceIndex)return e.sourceIndex-t.sourceIndex;var n,r,i=[],s=[],o=e.parentNode,u=t.parentNode,a=o;if(o===u)return ot(e,t);if(!o)return-1;if(!u)return 1;while(a)i.unshift(a),a=a.parentNode;a=u;while(a)s.unshift(a),a=a.parentNode;n=i.length,r=s.length;for(var f=0;f<n&&f<r;f++)if(i[f]!==s[f])return ot(i[f],s[f]);return f===n?ot(e,s[f],-1):ot(i[f],t,1)},[0,0].sort(f),h=!l,nt.uniqueSort=function(e){var t,n=[],r=1,i=0;l=h,e.sort(f);if(l){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e},nt.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},a=nt.compile=function(e,t){var n,r=[],i=[],s=A[d][e+" "];if(!s){t||(t=ut(e)),n=t.length;while(n--)s=ht(t[n]),s[d]?r.push(s):i.push(s);s=A(e,pt(i,r))}return s},g.querySelectorAll&&function(){var e,t=vt,n=/'|\\/g,r=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,i=[":focus"],s=[":active"],u=y.matchesSelector||y.mozMatchesSelector||y.webkitMatchesSelector||y.oMatchesSelector||y.msMatchesSelector;K(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="<p test=''></p>",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="<input type='hidden'/>",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t<n;t++)if(v.contains(u[t],this))return!0});o=this.pushStack("","find",e);for(t=0,n=this.length;t<n;t++){r=o.length,v.find(e,this[t],o);if(t>0)for(i=r;i<o.length;i++)for(s=0;s<r;s++)if(o[s]===o[i]){o.splice(i--,1);break}}return o},has:function(e){var t,n=v(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(v.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1),"not",e)},filter:function(e){return this.pushStack(ft(this,e,!0),"filter",e)},is:function(e){return!!e&&(typeof e=="string"?st.test(e)?v(e,this.context).index(this[0])>=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r<i;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&n.nodeType!==11){if(o?o.index(n)>-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/<tbody/i,gt=/<|&#?\w+;/,yt=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,wt=new RegExp("<(?:"+ct+")[\\s/>]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,Nt={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X<div>","</div>"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1></$2>");try{for(;r<i;r++)n=this[r]||{},n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),n.innerHTML=e);n=0}catch(s){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){return ut(this[0])?this.length?this.pushStack(v(v.isFunction(e)?e():e),"replaceWith",e):this:v.isFunction(e)?this.each(function(t){var n=v(this),r=n.html();n.replaceWith(e.call(this,t,r))}):(typeof e!="string"&&(e=v(e).detach()),this.each(function(){var t=this.nextSibling,n=this.parentNode;v(this).remove(),t?v(t).before(e):v(n).append(e)}))},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=[].concat.apply([],e);var i,s,o,u,a=0,f=e[0],l=[],c=this.length;if(!v.support.checkClone&&c>1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a<c;a++)r.call(n&&v.nodeName(this[a],"table")?Lt(this[a],"tbody"):this[a],a===u?o:v.clone(o,!0,!0))}o=s=null,l.length&&v.each(l,function(e,t){t.src?v.ajax?v.ajax({url:t.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):v.error("no ajax"):v.globalEval((t.text||t.textContent||t.innerHTML||"").replace(Tt,"")),t.parentNode&&t.parentNode.removeChild(t)})}return this}}),v.buildFragment=function(e,n,r){var s,o,u,a=e[0];return n=n||i,n=!n.nodeType&&n[0]||n,n=n.ownerDocument||n,e.length===1&&typeof a=="string"&&a.length<512&&n===i&&a.charAt(0)==="<"&&!bt.test(a)&&(v.support.checkClone||!St.test(a))&&(v.support.html5Clone||!wt.test(a))&&(o=!0,s=v.fragments[a],u=s!==t),s||(s=n.createDocumentFragment(),v.clean(e,n,s,r),o&&(v.fragments[a]=u&&s)),{fragment:s,cacheable:o}},v.fragments={},v.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){v.fn[e]=function(n){var r,i=0,s=[],o=v(n),u=o.length,a=this.length===1&&this[0].parentNode;if((a==null||a&&a.nodeType===11&&a.childNodes.length===1)&&u===1)return o[t](this[0]),this;for(;i<u;i++)r=(i>0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1></$2>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]==="<table>"&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("<div>").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r<i;r++)n=e[r],Vn[n]=Vn[n]||[],Vn[n].unshift(t)},prefilter:function(e,t){t?Xn.unshift(e):Xn.push(e)}}),v.Tween=Yn,Yn.prototype={constructor:Yn,init:function(e,t,n,r,i,s){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=s||(v.cssNumber[n]?"":"px")},cur:function(){var e=Yn.propHooks[this.prop];return e&&e.get?e.get(this):Yn.propHooks._default.get(this)},run:function(e){var t,n=Yn.propHooks[this.prop];return this.options.duration?this.pos=t=v.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):Yn.propHooks._default.set(this),this}},Yn.prototype.init.prototype=Yn.prototype,Yn.propHooks={_default:{get:function(e){var t;return e.elem[e.prop]==null||!!e.elem.style&&e.elem.style[e.prop]!=null?(t=v.css(e.elem,e.prop,!1,""),!t||t==="auto"?0:t):e.elem[e.prop]},set:function(e){v.fx.step[e.prop]?v.fx.step[e.prop](e):e.elem.style&&(e.elem.style[v.cssProps[e.prop]]!=null||v.cssHooks[e.prop])?v.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},Yn.propHooks.scrollTop=Yn.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},v.each(["toggle","show","hide"],function(e,t){var n=v.fn[t];v.fn[t]=function(r,i,s){return r==null||typeof r=="boolean"||!e&&v.isFunction(r)&&v.isFunction(i)?n.apply(this,arguments):this.animate(Zn(t,!0),r,i,s)}}),v.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Gt).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=v.isEmptyObject(e),s=v.speed(t,n,r),o=function(){var t=Kn(this,v.extend({},e),s);i&&t.stop(!0)};return i||s.queue===!1?this.each(o):this.queue(s.queue,o)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return typeof e!="string"&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=e!=null&&e+"queueHooks",s=v.timers,o=v._data(this);if(n)o[n]&&o[n].stop&&i(o[n]);else for(n in o)o[n]&&o[n].stop&&Wn.test(n)&&i(o[n]);for(n=s.length;n--;)s[n].elem===this&&(e==null||s[n].queue===e)&&(s[n].anim.stop(r),t=!1,s.splice(n,1));(t||!r)&&v.dequeue(this,e)})}}),v.each({slideDown:Zn("show"),slideUp:Zn("hide"),slideToggle:Zn("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){v.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),v.speed=function(e,t,n){var r=e&&typeof e=="object"?v.extend({},e):{complete:n||!n&&t||v.isFunction(e)&&e,duration:e,easing:n&&t||t&&!v.isFunction(t)&&t};r.duration=v.fx.off?0:typeof r.duration=="number"?r.duration:r.duration in v.fx.speeds?v.fx.speeds[r.duration]:v.fx.speeds._default;if(r.queue==null||r.queue===!0)r.queue="fx";return r.old=r.complete,r.complete=function(){v.isFunction(r.old)&&r.old.call(this),r.queue&&v.dequeue(this,r.queue)},r},v.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},v.timers=[],v.fx=Yn.prototype.init,v.fx.tick=function(){var e,n=v.timers,r=0;qn=v.now();for(;r<n.length;r++)e=n[r],!e()&&n[r]===e&&n.splice(r--,1);n.length||v.fx.stop(),qn=t},v.fx.timer=function(e){e()&&v.timers.push(e)&&!Rn&&(Rn=setInterval(v.fx.tick,v.fx.interval))},v.fx.interval=13,v.fx.stop=function(){clearInterval(Rn),Rn=null},v.fx.speeds={slow:600,fast:200,_default:400},v.fx.step={},v.expr&&v.expr.filters&&(v.expr.filters.animated=function(e){return v.grep(v.timers,function(t){return e===t.elem}).length});var er=/^(?:body|html)$/i;v.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){v.offset.setOffset(this,e,t)});var n,r,i,s,o,u,a,f={top:0,left:0},l=this[0],c=l&&l.ownerDocument;if(!c)return;return(r=c.body)===l?v.offset.bodyOffset(l):(n=c.documentElement,v.contains(n,l)?(typeof l.getBoundingClientRect!="undefined"&&(f=l.getBoundingClientRect()),i=tr(c),s=n.clientTop||r.clientTop||0,o=n.clientLeft||r.clientLeft||0,u=i.pageYOffset||n.scrollTop,a=i.pageXOffset||n.scrollLeft,{top:f.top+u-s,left:f.left+a-o}):f)},v.offset={bodyOffset:function(e){var t=e.offsetTop,n=e.offsetLeft;return v.support.doesNotIncludeMarginInBodyOffset&&(t+=parseFloat(v.css(e,"marginTop"))||0,n+=parseFloat(v.css(e,"marginLeft"))||0),{top:t,left:n}},setOffset:function(e,t,n){var r=v.css(e,"position");r==="static"&&(e.style.position="relative");var i=v(e),s=i.offset(),o=v.css(e,"top"),u=v.css(e,"left"),a=(r==="absolute"||r==="fixed")&&v.inArray("auto",[o,u])>-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window); \ No newline at end of file diff --git a/src/static/jquery/jquery-jstree/jquery.cookie.js b/src/static/jquery/jquery-jstree/jquery.cookie.js new file mode 100755 index 0000000..6df1fac --- /dev/null +++ b/src/static/jquery/jquery-jstree/jquery.cookie.js @@ -0,0 +1,96 @@ +/** + * Cookie plugin + * + * Copyright (c) 2006 Klaus Hartl (stilbuero.de) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ + +/** + * Create a cookie with the given name and value and other optional parameters. + * + * @example $.cookie('the_cookie', 'the_value'); + * @desc Set the value of a cookie. + * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true }); + * @desc Create a cookie with all available options. + * @example $.cookie('the_cookie', 'the_value'); + * @desc Create a session cookie. + * @example $.cookie('the_cookie', null); + * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain + * used when the cookie was set. + * + * @param String name The name of the cookie. + * @param String value The value of the cookie. + * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. + * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. + * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. + * If set to null or omitted, the cookie will be a session cookie and will not be retained + * when the the browser exits. + * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). + * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). + * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will + * require a secure protocol (like HTTPS). + * @type undefined + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ + +/** + * Get the value of a cookie with the given name. + * + * @example $.cookie('the_cookie'); + * @desc Get the value of a cookie. + * + * @param String name The name of the cookie. + * @return The value of the cookie. + * @type String + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ +jQuery.cookie = function(name, value, options) { + if (typeof value != 'undefined') { // name and value given, set cookie + options = options || {}; + if (value === null) { + value = ''; + options.expires = -1; + } + var expires = ''; + if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { + var date; + if (typeof options.expires == 'number') { + date = new Date(); + date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); + } else { + date = options.expires; + } + expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE + } + // CAUTION: Needed to parenthesize options.path and options.domain + // in the following expressions, otherwise they evaluate to undefined + // in the packed version for some reason... + var path = options.path ? '; path=' + (options.path) : ''; + var domain = options.domain ? '; domain=' + (options.domain) : ''; + var secure = options.secure ? '; secure' : ''; + document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); + } else { // only name given, get cookie + var cookieValue = null; + if (document.cookie && document.cookie != '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) == (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; + } +}; \ No newline at end of file diff --git a/src/static/jquery/jquery-jstree/jquery.jstree.js b/src/static/jquery/jquery-jstree/jquery.jstree.js new file mode 100755 index 0000000..b4aac3e --- /dev/null +++ b/src/static/jquery/jquery-jstree/jquery.jstree.js @@ -0,0 +1,4561 @@ +/* + * jsTree 1.0-rc3 + * http://jstree.com/ + * + * Copyright (c) 2010 Ivan Bozhanov (vakata.com) + * + * Licensed same as jquery - under the terms of either the MIT License or the GPL Version 2 License + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * $Date: 2011-02-09 01:17:14 +0200 (ÑÑ€, 09 февр 2011) $ + * $Revision: 236 $ + */ + +/*jslint browser: true, onevar: true, undef: true, bitwise: true, strict: true */ +/*global window : false, clearInterval: false, clearTimeout: false, document: false, setInterval: false, setTimeout: false, jQuery: false, navigator: false, XSLTProcessor: false, DOMParser: false, XMLSerializer: false, ActiveXObject: false */ + +"use strict"; + +// top wrapper to prevent multiple inclusion (is this OK?) +(function () { if(jQuery && jQuery.jstree) { return; } + var is_ie6 = false, is_ie7 = false, is_ff2 = false; + +/* + * jsTree core + */ +(function ($) { + // Common functions not related to jsTree + // decided to move them to a `vakata` "namespace" + $.vakata = {}; + // CSS related functions + $.vakata.css = { + get_css : function(rule_name, delete_flag, sheet) { + rule_name = rule_name.toLowerCase(); + var css_rules = sheet.cssRules || sheet.rules, + j = 0; + do { + if(css_rules.length && j > css_rules.length + 5) { return false; } + if(css_rules[j].selectorText && css_rules[j].selectorText.toLowerCase() == rule_name) { + if(delete_flag === true) { + if(sheet.removeRule) { sheet.removeRule(j); } + if(sheet.deleteRule) { sheet.deleteRule(j); } + return true; + } + else { return css_rules[j]; } + } + } + while (css_rules[++j]); + return false; + }, + add_css : function(rule_name, sheet) { + if($.jstree.css.get_css(rule_name, false, sheet)) { return false; } + if(sheet.insertRule) { sheet.insertRule(rule_name + ' { }', 0); } else { sheet.addRule(rule_name, null, 0); } + return $.vakata.css.get_css(rule_name); + }, + remove_css : function(rule_name, sheet) { + return $.vakata.css.get_css(rule_name, true, sheet); + }, + add_sheet : function(opts) { + var tmp = false, is_new = true; + if(opts.str) { + if(opts.title) { tmp = $("style[id='" + opts.title + "-stylesheet']")[0]; } + if(tmp) { is_new = false; } + else { + tmp = document.createElement("style"); + tmp.setAttribute('type',"text/css"); + if(opts.title) { tmp.setAttribute("id", opts.title + "-stylesheet"); } + } + if(tmp.styleSheet) { + if(is_new) { + document.getElementsByTagName("head")[0].appendChild(tmp); + tmp.styleSheet.cssText = opts.str; + } + else { + tmp.styleSheet.cssText = tmp.styleSheet.cssText + " " + opts.str; + } + } + else { + tmp.appendChild(document.createTextNode(opts.str)); + document.getElementsByTagName("head")[0].appendChild(tmp); + } + return tmp.sheet || tmp.styleSheet; + } + if(opts.url) { + if(document.createStyleSheet) { + try { tmp = document.createStyleSheet(opts.url); } catch (e) { } + } + else { + tmp = document.createElement('link'); + tmp.rel = 'stylesheet'; + tmp.type = 'text/css'; + tmp.media = "all"; + tmp.href = opts.url; + document.getElementsByTagName("head")[0].appendChild(tmp); + return tmp.styleSheet; + } + } + } + }; + + // private variables + var instances = [], // instance array (used by $.jstree.reference/create/focused) + focused_instance = -1, // the index in the instance array of the currently focused instance + plugins = {}, // list of included plugins + prepared_move = {}; // for the move_node function + + // jQuery plugin wrapper (thanks to jquery UI widget function) + $.fn.jstree = function (settings) { + var isMethodCall = (typeof settings == 'string'), // is this a method call like $().jstree("open_node") + args = Array.prototype.slice.call(arguments, 1), + returnValue = this; + + // if a method call execute the method on all selected instances + if(isMethodCall) { + if(settings.substring(0, 1) == '_') { return returnValue; } + this.each(function() { + var instance = instances[$.data(this, "jstree_instance_id")], + methodValue = (instance && $.isFunction(instance[settings])) ? instance[settings].apply(instance, args) : instance; + if(typeof methodValue !== "undefined" && (settings.indexOf("is_") === 0 || (methodValue !== true && methodValue !== false))) { returnValue = methodValue; return false; } + }); + } + else { + this.each(function() { + // extend settings and allow for multiple hashes and $.data + var instance_id = $.data(this, "jstree_instance_id"), + a = [], + b = settings ? $.extend({}, true, settings) : {}, + c = $(this), + s = false, + t = []; + a = a.concat(args); + if(c.data("jstree")) { a.push(c.data("jstree")); } + b = a.length ? $.extend.apply(null, [true, b].concat(a)) : b; + + // if an instance already exists, destroy it first + if(typeof instance_id !== "undefined" && instances[instance_id]) { instances[instance_id].destroy(); } + // push a new empty object to the instances array + instance_id = parseInt(instances.push({}),10) - 1; + // store the jstree instance id to the container element + $.data(this, "jstree_instance_id", instance_id); + // clean up all plugins + b.plugins = $.isArray(b.plugins) ? b.plugins : $.jstree.defaults.plugins.slice(); + b.plugins.unshift("core"); + // only unique plugins + b.plugins = b.plugins.sort().join(",,").replace(/(,|^)([^,]+)(,,\2)+(,|$)/g,"$1$2$4").replace(/,,+/g,",").replace(/,$/,"").split(","); + + // extend defaults with passed data + s = $.extend(true, {}, $.jstree.defaults, b); + s.plugins = b.plugins; + $.each(plugins, function (i, val) { + if($.inArray(i, s.plugins) === -1) { s[i] = null; delete s[i]; } + else { t.push(i); } + }); + s.plugins = t; + + // push the new object to the instances array (at the same time set the default classes to the container) and init + instances[instance_id] = new $.jstree._instance(instance_id, $(this).addClass("jstree jstree-" + instance_id), s); + // init all activated plugins for this instance + $.each(instances[instance_id]._get_settings().plugins, function (i, val) { instances[instance_id].data[val] = {}; }); + $.each(instances[instance_id]._get_settings().plugins, function (i, val) { if(plugins[val]) { plugins[val].__init.apply(instances[instance_id]); } }); + // initialize the instance + setTimeout(function() { if(instances[instance_id]) { instances[instance_id].init(); } }, 0); + }); + } + // return the jquery selection (or if it was a method call that returned a value - the returned value) + return returnValue; + }; + // object to store exposed functions and objects + $.jstree = { + defaults : { + plugins : [] + }, + _focused : function () { return instances[focused_instance] || null; }, + _reference : function (needle) { + // get by instance id + if(instances[needle]) { return instances[needle]; } + // get by DOM (if still no luck - return null + var o = $(needle); + if(!o.length && typeof needle === "string") { o = $("#" + needle); } + if(!o.length) { return null; } + return instances[o.closest(".jstree").data("jstree_instance_id")] || null; + }, + _instance : function (index, container, settings) { + // for plugins to store data in + this.data = { core : {} }; + this.get_settings = function () { return $.extend(true, {}, settings); }; + this._get_settings = function () { return settings; }; + this.get_index = function () { return index; }; + this.get_container = function () { return container; }; + this.get_container_ul = function () { return container.children("ul:eq(0)"); }; + this._set_settings = function (s) { + settings = $.extend(true, {}, settings, s); + }; + }, + _fn : { }, + plugin : function (pname, pdata) { + pdata = $.extend({}, { + __init : $.noop, + __destroy : $.noop, + _fn : {}, + defaults : false + }, pdata); + plugins[pname] = pdata; + + $.jstree.defaults[pname] = pdata.defaults; + $.each(pdata._fn, function (i, val) { + val.plugin = pname; + val.old = $.jstree._fn[i]; + $.jstree._fn[i] = function () { + var rslt, + func = val, + args = Array.prototype.slice.call(arguments), + evnt = new $.Event("before.jstree"), + rlbk = false; + + if(this.data.core.locked === true && i !== "unlock" && i !== "is_locked") { return; } + + // Check if function belongs to the included plugins of this instance + do { + if(func && func.plugin && $.inArray(func.plugin, this._get_settings().plugins) !== -1) { break; } + func = func.old; + } while(func); + if(!func) { return; } + + // context and function to trigger events, then finally call the function + if(i.indexOf("_") === 0) { + rslt = func.apply(this, args); + } + else { + rslt = this.get_container().triggerHandler(evnt, { "func" : i, "inst" : this, "args" : args, "plugin" : func.plugin }); + if(rslt === false) { return; } + if(typeof rslt !== "undefined") { args = rslt; } + + rslt = func.apply( + $.extend({}, this, { + __callback : function (data) { + this.get_container().triggerHandler( i + '.jstree', { "inst" : this, "args" : args, "rslt" : data, "rlbk" : rlbk }); + }, + __rollback : function () { + rlbk = this.get_rollback(); + return rlbk; + }, + __call_old : function (replace_arguments) { + return func.old.apply(this, (replace_arguments ? Array.prototype.slice.call(arguments, 1) : args ) ); + } + }), args); + } + + // return the result + return rslt; + }; + $.jstree._fn[i].old = val.old; + $.jstree._fn[i].plugin = pname; + }); + }, + rollback : function (rb) { + if(rb) { + if(!$.isArray(rb)) { rb = [ rb ]; } + $.each(rb, function (i, val) { + instances[val.i].set_rollback(val.h, val.d); + }); + } + } + }; + // set the prototype for all instances + $.jstree._fn = $.jstree._instance.prototype = {}; + + // load the css when DOM is ready + $(function() { + // code is copied from jQuery ($.browser is deprecated + there is a bug in IE) + var u = navigator.userAgent.toLowerCase(), + v = (u.match( /.+?(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [0,'0'])[1], + css_string = '' + + '.jstree ul, .jstree li { display:block; margin:0 0 0 0; padding:0 0 0 0; list-style-type:none; } ' + + '.jstree li { display:block; min-height:18px; line-height:18px; white-space:nowrap; margin-left:18px; min-width:18px; } ' + + '.jstree-rtl li { margin-left:0; margin-right:18px; } ' + + '.jstree > ul > li { margin-left:0px; } ' + + '.jstree-rtl > ul > li { margin-right:0px; } ' + + '.jstree ins { display:inline-block; text-decoration:none; width:18px; height:18px; margin:0 0 0 0; padding:0; } ' + + '.jstree a { display:inline-block; line-height:16px; height:16px; color:black; white-space:nowrap; text-decoration:none; padding:1px 2px; margin:0; } ' + + '.jstree a:focus { outline: none; } ' + + '.jstree a > ins { height:16px; width:16px; } ' + + '.jstree a > .jstree-icon { margin-right:3px; } ' + + '.jstree-rtl a > .jstree-icon { margin-left:3px; margin-right:0; } ' + + 'li.jstree-open > ul { display:block; } ' + + 'li.jstree-closed > ul { display:none; } '; + // Correct IE 6 (does not support the > CSS selector) + if(/msie/.test(u) && parseInt(v, 10) == 6) { + is_ie6 = true; + + // fix image flicker and lack of caching + try { + document.execCommand("BackgroundImageCache", false, true); + } catch (err) { } + + css_string += '' + + '.jstree li { height:18px; margin-left:0; margin-right:0; } ' + + '.jstree li li { margin-left:18px; } ' + + '.jstree-rtl li li { margin-left:0px; margin-right:18px; } ' + + 'li.jstree-open ul { display:block; } ' + + 'li.jstree-closed ul { display:none !important; } ' + + '.jstree li a { display:inline; border-width:0 !important; padding:0px 2px !important; } ' + + '.jstree li a ins { height:16px; width:16px; margin-right:3px; } ' + + '.jstree-rtl li a ins { margin-right:0px; margin-left:3px; } '; + } + // Correct IE 7 (shifts anchor nodes onhover) + if(/msie/.test(u) && parseInt(v, 10) == 7) { + is_ie7 = true; + css_string += '.jstree li a { border-width:0 !important; padding:0px 2px !important; } '; + } + // correct ff2 lack of display:inline-block + if(!/compatible/.test(u) && /mozilla/.test(u) && parseFloat(v, 10) < 1.9) { + is_ff2 = true; + css_string += '' + + '.jstree ins { display:-moz-inline-box; } ' + + '.jstree li { line-height:12px; } ' + // WHY?? + '.jstree a { display:-moz-inline-box; } ' + + '.jstree .jstree-no-icons .jstree-checkbox { display:-moz-inline-stack !important; } '; + /* this shouldn't be here as it is theme specific */ + } + // the default stylesheet + $.vakata.css.add_sheet({ str : css_string, title : "jstree" }); + }); + + // core functions (open, close, create, update, delete) + $.jstree.plugin("core", { + __init : function () { + this.data.core.locked = false; + this.data.core.to_open = this.get_settings().core.initially_open; + this.data.core.to_load = this.get_settings().core.initially_load; + }, + defaults : { + html_titles : false, + animation : 500, + initially_open : [], + initially_load : [], + open_parents : true, + notify_plugins : true, + rtl : false, + load_open : false, + strings : { + loading : "Loading ...", + new_node : "New node", + multiple_selection : "Multiple selection" + } + }, + _fn : { + init : function () { + this.set_focus(); + if(this._get_settings().core.rtl) { + this.get_container().addClass("jstree-rtl").css("direction", "rtl"); + } + this.get_container().html("<ul><li class='jstree-last jstree-leaf'><ins>&#160;</ins><a class='jstree-loading' href='#'><ins class='jstree-icon'>&#160;</ins>" + this._get_string("loading") + "</a></li></ul>"); + this.data.core.li_height = this.get_container_ul().find("li.jstree-closed, li.jstree-leaf").eq(0).height() || 18; + + this.get_container() + .delegate("li > ins", "click.jstree", $.proxy(function (event) { + var trgt = $(event.target); + // if(trgt.is("ins") && event.pageY - trgt.offset().top < this.data.core.li_height) { this.toggle_node(trgt); } + this.toggle_node(trgt); + }, this)) + .bind("mousedown.jstree", $.proxy(function () { + this.set_focus(); // This used to be setTimeout(set_focus,0) - why? + }, this)) + .bind("dblclick.jstree", function (event) { + var sel; + if(document.selection && document.selection.empty) { document.selection.empty(); } + else { + if(window.getSelection) { + sel = window.getSelection(); + try { + sel.removeAllRanges(); + sel.collapse(); + } catch (err) { } + } + } + }); + if(this._get_settings().core.notify_plugins) { + this.get_container() + .bind("load_node.jstree", $.proxy(function (e, data) { + var o = this._get_node(data.rslt.obj), + t = this; + if(o === -1) { o = this.get_container_ul(); } + if(!o.length) { return; } + o.find("li").each(function () { + var th = $(this); + if(th.data("jstree")) { + $.each(th.data("jstree"), function (plugin, values) { + if(t.data[plugin] && $.isFunction(t["_" + plugin + "_notify"])) { + t["_" + plugin + "_notify"].call(t, th, values); + } + }); + } + }); + }, this)); + } + if(this._get_settings().core.load_open) { + this.get_container() + .bind("load_node.jstree", $.proxy(function (e, data) { + var o = this._get_node(data.rslt.obj), + t = this; + if(o === -1) { o = this.get_container_ul(); } + if(!o.length) { return; } + o.find("li.jstree-open:not(:has(ul))").each(function () { + t.load_node(this, $.noop, $.noop); + }); + }, this)); + } + this.__callback(); + this.load_node(-1, function () { this.loaded(); this.reload_nodes(); }); + }, + destroy : function () { + var i, + n = this.get_index(), + s = this._get_settings(), + _this = this; + + $.each(s.plugins, function (i, val) { + try { plugins[val].__destroy.apply(_this); } catch(err) { } + }); + this.__callback(); + // set focus to another instance if this one is focused + if(this.is_focused()) { + for(i in instances) { + if(instances.hasOwnProperty(i) && i != n) { + instances[i].set_focus(); + break; + } + } + } + // if no other instance found + if(n === focused_instance) { focused_instance = -1; } + // remove all traces of jstree in the DOM (only the ones set using jstree*) and cleans all events + this.get_container() + .unbind(".jstree") + .undelegate(".jstree") + .removeData("jstree_instance_id") + .find("[class^='jstree']") + .andSelf() + .attr("class", function () { return this.className.replace(/jstree[^ ]*|$/ig,''); }); + $(document) + .unbind(".jstree-" + n) + .undelegate(".jstree-" + n); + // remove the actual data + instances[n] = null; + delete instances[n]; + }, + + _core_notify : function (n, data) { + if(data.opened) { + this.open_node(n, false, true); + } + }, + + lock : function () { + this.data.core.locked = true; + this.get_container().children("ul").addClass("jstree-locked").css("opacity","0.7"); + this.__callback({}); + }, + unlock : function () { + this.data.core.locked = false; + this.get_container().children("ul").removeClass("jstree-locked").css("opacity","1"); + this.__callback({}); + }, + is_locked : function () { return this.data.core.locked; }, + save_opened : function () { + var _this = this; + this.data.core.to_open = []; + this.get_container_ul().find("li.jstree-open").each(function () { + if(this.id) { _this.data.core.to_open.push("#" + this.id.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:")); } + }); + this.__callback(_this.data.core.to_open); + }, + save_loaded : function () { }, + reload_nodes : function (is_callback) { + var _this = this, + done = true, + current = [], + remaining = []; + if(!is_callback) { + this.data.core.reopen = false; + this.data.core.refreshing = true; + this.data.core.to_open = $.map($.makeArray(this.data.core.to_open), function (n) { return "#" + n.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:"); }); + this.data.core.to_load = $.map($.makeArray(this.data.core.to_load), function (n) { return "#" + n.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:"); }); + if(this.data.core.to_open.length) { + this.data.core.to_load = this.data.core.to_load.concat(this.data.core.to_open); + } + } + if(this.data.core.to_load.length) { + $.each(this.data.core.to_load, function (i, val) { + if(val == "#") { return true; } + if($(val).length) { current.push(val); } + else { remaining.push(val); } + }); + if(current.length) { + this.data.core.to_load = remaining; + $.each(current, function (i, val) { + if(!_this._is_loaded(val)) { + _this.load_node(val, function () { _this.reload_nodes(true); }, function () { _this.reload_nodes(true); }); + done = false; + } + }); + } + } + if(this.data.core.to_open.length) { + $.each(this.data.core.to_open, function (i, val) { + _this.open_node(val, false, true); + }); + } + if(done) { + // TODO: find a more elegant approach to syncronizing returning requests + if(this.data.core.reopen) { clearTimeout(this.data.core.reopen); } + this.data.core.reopen = setTimeout(function () { _this.__callback({}, _this); }, 50); + this.data.core.refreshing = false; + this.reopen(); + } + }, + reopen : function () { + var _this = this; + if(this.data.core.to_open.length) { + $.each(this.data.core.to_open, function (i, val) { + _this.open_node(val, false, true); + }); + } + this.__callback({}); + }, + refresh : function (obj) { + var _this = this; + this.save_opened(); + if(!obj) { obj = -1; } + obj = this._get_node(obj); + if(!obj) { obj = -1; } + if(obj !== -1) { obj.children("UL").remove(); } + else { this.get_container_ul().empty(); } + this.load_node(obj, function () { _this.__callback({ "obj" : obj}); _this.reload_nodes(); }); + }, + // Dummy function to fire after the first load (so that there is a jstree.loaded event) + loaded : function () { + this.__callback(); + }, + // deal with focus + set_focus : function () { + if(this.is_focused()) { return; } + var f = $.jstree._focused(); + if(f) { f.unset_focus(); } + + this.get_container().addClass("jstree-focused"); + focused_instance = this.get_index(); + this.__callback(); + }, + is_focused : function () { + return focused_instance == this.get_index(); + }, + unset_focus : function () { + if(this.is_focused()) { + this.get_container().removeClass("jstree-focused"); + focused_instance = -1; + } + this.__callback(); + }, + + // traverse + _get_node : function (obj) { + var $obj = $(obj, this.get_container()); + if($obj.is(".jstree") || obj == -1) { return -1; } + $obj = $obj.closest("li", this.get_container()); + return $obj.length ? $obj : false; + }, + _get_next : function (obj, strict) { + obj = this._get_node(obj); + if(obj === -1) { return this.get_container().find("> ul > li:first-child"); } + if(!obj.length) { return false; } + if(strict) { return (obj.nextAll("li").size() > 0) ? obj.nextAll("li:eq(0)") : false; } + + if(obj.hasClass("jstree-open")) { return obj.find("li:eq(0)"); } + else if(obj.nextAll("li").size() > 0) { return obj.nextAll("li:eq(0)"); } + else { return obj.parentsUntil(".jstree","li").next("li").eq(0); } + }, + _get_prev : function (obj, strict) { + obj = this._get_node(obj); + if(obj === -1) { return this.get_container().find("> ul > li:last-child"); } + if(!obj.length) { return false; } + if(strict) { return (obj.prevAll("li").length > 0) ? obj.prevAll("li:eq(0)") : false; } + + if(obj.prev("li").length) { + obj = obj.prev("li").eq(0); + while(obj.hasClass("jstree-open")) { obj = obj.children("ul:eq(0)").children("li:last"); } + return obj; + } + else { var o = obj.parentsUntil(".jstree","li:eq(0)"); return o.length ? o : false; } + }, + _get_parent : function (obj) { + obj = this._get_node(obj); + if(obj == -1 || !obj.length) { return false; } + var o = obj.parentsUntil(".jstree", "li:eq(0)"); + return o.length ? o : -1; + }, + _get_children : function (obj) { + obj = this._get_node(obj); + if(obj === -1) { return this.get_container().children("ul:eq(0)").children("li"); } + if(!obj.length) { return false; } + return obj.children("ul:eq(0)").children("li"); + }, + get_path : function (obj, id_mode) { + var p = [], + _this = this; + obj = this._get_node(obj); + if(obj === -1 || !obj || !obj.length) { return false; } + obj.parentsUntil(".jstree", "li").each(function () { + p.push( id_mode ? this.id : _this.get_text(this) ); + }); + p.reverse(); + p.push( id_mode ? obj.attr("id") : this.get_text(obj) ); + return p; + }, + + // string functions + _get_string : function (key) { + return this._get_settings().core.strings[key] || key; + }, + + is_open : function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-open"); }, + is_closed : function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-closed"); }, + is_leaf : function (obj) { obj = this._get_node(obj); return obj && obj !== -1 && obj.hasClass("jstree-leaf"); }, + correct_state : function (obj) { + obj = this._get_node(obj); + if(!obj || obj === -1) { return false; } + obj.removeClass("jstree-closed jstree-open").addClass("jstree-leaf").children("ul").remove(); + this.__callback({ "obj" : obj }); + }, + // open/close + open_node : function (obj, callback, skip_animation) { + obj = this._get_node(obj); + if(!obj.length) { return false; } + if(!obj.hasClass("jstree-closed")) { if(callback) { callback.call(); } return false; } + var s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation, + t = this; + if(!this._is_loaded(obj)) { + obj.children("a").addClass("jstree-loading"); + this.load_node(obj, function () { t.open_node(obj, callback, skip_animation); }, callback); + } + else { + if(this._get_settings().core.open_parents) { + obj.parentsUntil(".jstree",".jstree-closed").each(function () { + t.open_node(this, false, true); + }); + } + if(s) { obj.children("ul").css("display","none"); } + obj.removeClass("jstree-closed").addClass("jstree-open").children("a").removeClass("jstree-loading"); + if(s) { obj.children("ul").stop(true, true).slideDown(s, function () { this.style.display = ""; t.after_open(obj); }); } + else { t.after_open(obj); } + this.__callback({ "obj" : obj }); + if(callback) { callback.call(); } + } + }, + after_open : function (obj) { this.__callback({ "obj" : obj }); }, + close_node : function (obj, skip_animation) { + obj = this._get_node(obj); + var s = skip_animation || is_ie6 ? 0 : this._get_settings().core.animation, + t = this; + if(!obj.length || !obj.hasClass("jstree-open")) { return false; } + if(s) { obj.children("ul").attr("style","display:block !important"); } + obj.removeClass("jstree-open").addClass("jstree-closed"); + if(s) { obj.children("ul").stop(true, true).slideUp(s, function () { this.style.display = ""; t.after_close(obj); }); } + else { t.after_close(obj); } + this.__callback({ "obj" : obj }); + }, + after_close : function (obj) { this.__callback({ "obj" : obj }); }, + toggle_node : function (obj) { + obj = this._get_node(obj); + if(obj.hasClass("jstree-closed")) { return this.open_node(obj); } + if(obj.hasClass("jstree-open")) { return this.close_node(obj); } + }, + open_all : function (obj, do_animation, original_obj) { + obj = obj ? this._get_node(obj) : -1; + if(!obj || obj === -1) { obj = this.get_container_ul(); } + if(original_obj) { + obj = obj.find("li.jstree-closed"); + } + else { + original_obj = obj; + if(obj.is(".jstree-closed")) { obj = obj.find("li.jstree-closed").andSelf(); } + else { obj = obj.find("li.jstree-closed"); } + } + var _this = this; + obj.each(function () { + var __this = this; + if(!_this._is_loaded(this)) { _this.open_node(this, function() { _this.open_all(__this, do_animation, original_obj); }, !do_animation); } + else { _this.open_node(this, false, !do_animation); } + }); + // so that callback is fired AFTER all nodes are open + if(original_obj.find('li.jstree-closed').length === 0) { this.__callback({ "obj" : original_obj }); } + }, + close_all : function (obj, do_animation) { + var _this = this; + obj = obj ? this._get_node(obj) : this.get_container(); + if(!obj || obj === -1) { obj = this.get_container_ul(); } + obj.find("li.jstree-open").andSelf().each(function () { _this.close_node(this, !do_animation); }); + this.__callback({ "obj" : obj }); + }, + clean_node : function (obj) { + obj = obj && obj != -1 ? $(obj) : this.get_container_ul(); + obj = obj.is("li") ? obj.find("li").andSelf() : obj.find("li"); + obj.removeClass("jstree-last") + .filter("li:last-child").addClass("jstree-last").end() + .filter(":has(li)") + .not(".jstree-open").removeClass("jstree-leaf").addClass("jstree-closed"); + obj.not(".jstree-open, .jstree-closed").addClass("jstree-leaf").children("ul").remove(); + this.__callback({ "obj" : obj }); + }, + // rollback + get_rollback : function () { + this.__callback(); + return { i : this.get_index(), h : this.get_container().children("ul").clone(true), d : this.data }; + }, + set_rollback : function (html, data) { + this.get_container().empty().append(html); + this.data = data; + this.__callback(); + }, + // Dummy functions to be overwritten by any datastore plugin included + load_node : function (obj, s_call, e_call) { this.__callback({ "obj" : obj }); }, + _is_loaded : function (obj) { return true; }, + + // Basic operations: create + create_node : function (obj, position, js, callback, is_loaded) { + obj = this._get_node(obj); + position = typeof position === "undefined" ? "last" : position; + var d = $("<li />"), + s = this._get_settings().core, + tmp; + + if(obj !== -1 && !obj.length) { return false; } + if(!is_loaded && !this._is_loaded(obj)) { this.load_node(obj, function () { this.create_node(obj, position, js, callback, true); }); return false; } + + this.__rollback(); + + if(typeof js === "string") { js = { "data" : js }; } + if(!js) { js = {}; } + if(js.attr) { d.attr(js.attr); } + if(js.metadata) { d.data(js.metadata); } + if(js.state) { d.addClass("jstree-" + js.state); } + if(!js.data) { js.data = this._get_string("new_node"); } + if(!$.isArray(js.data)) { tmp = js.data; js.data = []; js.data.push(tmp); } + $.each(js.data, function (i, m) { + tmp = $("<a />"); + if($.isFunction(m)) { m = m.call(this, js); } + if(typeof m == "string") { tmp.attr('href','#')[ s.html_titles ? "html" : "text" ](m); } + else { + if(!m.attr) { m.attr = {}; } + if(!m.attr.href) { m.attr.href = '#'; } + tmp.attr(m.attr)[ s.html_titles ? "html" : "text" ](m.title); + if(m.language) { tmp.addClass(m.language); } + } + tmp.prepend("<ins class='jstree-icon'>&#160;</ins>"); + if(!m.icon && js.icon) { m.icon = js.icon; } + if(m.icon) { + if(m.icon.indexOf("/") === -1) { tmp.children("ins").addClass(m.icon); } + else { tmp.children("ins").css("background","url('" + m.icon + "') center center no-repeat"); } + } + d.append(tmp); + }); + d.prepend("<ins class='jstree-icon'>&#160;</ins>"); + if(obj === -1) { + obj = this.get_container(); + if(position === "before") { position = "first"; } + if(position === "after") { position = "last"; } + } + switch(position) { + case "before": obj.before(d); tmp = this._get_parent(obj); break; + case "after" : obj.after(d); tmp = this._get_parent(obj); break; + case "inside": + case "first" : + if(!obj.children("ul").length) { obj.append("<ul />"); } + obj.children("ul").prepend(d); + tmp = obj; + break; + case "last": + if(!obj.children("ul").length) { obj.append("<ul />"); } + obj.children("ul").append(d); + tmp = obj; + break; + default: + if(!obj.children("ul").length) { obj.append("<ul />"); } + if(!position) { position = 0; } + tmp = obj.children("ul").children("li").eq(position); + if(tmp.length) { tmp.before(d); } + else { obj.children("ul").append(d); } + tmp = obj; + break; + } + if(tmp === -1 || tmp.get(0) === this.get_container().get(0)) { tmp = -1; } + this.clean_node(tmp); + this.__callback({ "obj" : d, "parent" : tmp }); + if(callback) { callback.call(this, d); } + return d; + }, + // Basic operations: rename (deal with text) + get_text : function (obj) { + obj = this._get_node(obj); + if(!obj.length) { return false; } + var s = this._get_settings().core.html_titles; + obj = obj.children("a:eq(0)"); + if(s) { + obj = obj.clone(); + obj.children("INS").remove(); + return obj.html(); + } + else { + obj = obj.contents().filter(function() { return this.nodeType == 3; })[0]; + return obj.nodeValue; + } + }, + set_text : function (obj, val) { + obj = this._get_node(obj); + if(!obj.length) { return false; } + obj = obj.children("a:eq(0)"); + if(this._get_settings().core.html_titles) { + var tmp = obj.children("INS").clone(); + obj.html(val).prepend(tmp); + this.__callback({ "obj" : obj, "name" : val }); + return true; + } + else { + obj = obj.contents().filter(function() { return this.nodeType == 3; })[0]; + this.__callback({ "obj" : obj, "name" : val }); + return (obj.nodeValue = val); + } + }, + rename_node : function (obj, val) { + obj = this._get_node(obj); + this.__rollback(); + if(obj && obj.length && this.set_text.apply(this, Array.prototype.slice.call(arguments))) { this.__callback({ "obj" : obj, "name" : val }); } + }, + // Basic operations: deleting nodes + delete_node : function (obj) { + obj = this._get_node(obj); + if(!obj.length) { return false; } + this.__rollback(); + var p = this._get_parent(obj), prev = $([]), t = this; + obj.each(function () { + prev = prev.add(t._get_prev(this)); + }); + obj = obj.detach(); + if(p !== -1 && p.find("> ul > li").length === 0) { + p.removeClass("jstree-open jstree-closed").addClass("jstree-leaf"); + } + this.clean_node(p); + this.__callback({ "obj" : obj, "prev" : prev, "parent" : p }); + return obj; + }, + prepare_move : function (o, r, pos, cb, is_cb) { + var p = {}; + + p.ot = $.jstree._reference(o) || this; + p.o = p.ot._get_node(o); + p.r = r === - 1 ? -1 : this._get_node(r); + p.p = (typeof pos === "undefined" || pos === false) ? "last" : pos; // TODO: move to a setting + if(!is_cb && prepared_move.o && prepared_move.o[0] === p.o[0] && prepared_move.r[0] === p.r[0] && prepared_move.p === p.p) { + this.__callback(prepared_move); + if(cb) { cb.call(this, prepared_move); } + return; + } + p.ot = $.jstree._reference(p.o) || this; + p.rt = $.jstree._reference(p.r) || this; // r === -1 ? p.ot : $.jstree._reference(p.r) || this + if(p.r === -1 || !p.r) { + p.cr = -1; + switch(p.p) { + case "first": + case "before": + case "inside": + p.cp = 0; + break; + case "after": + case "last": + p.cp = p.rt.get_container().find(" > ul > li").length; + break; + default: + p.cp = p.p; + break; + } + } + else { + if(!/^(before|after)$/.test(p.p) && !this._is_loaded(p.r)) { + return this.load_node(p.r, function () { this.prepare_move(o, r, pos, cb, true); }); + } + switch(p.p) { + case "before": + p.cp = p.r.index(); + p.cr = p.rt._get_parent(p.r); + break; + case "after": + p.cp = p.r.index() + 1; + p.cr = p.rt._get_parent(p.r); + break; + case "inside": + case "first": + p.cp = 0; + p.cr = p.r; + break; + case "last": + p.cp = p.r.find(" > ul > li").length; + p.cr = p.r; + break; + default: + p.cp = p.p; + p.cr = p.r; + break; + } + } + p.np = p.cr == -1 ? p.rt.get_container() : p.cr; + p.op = p.ot._get_parent(p.o); + p.cop = p.o.index(); + if(p.op === -1) { p.op = p.ot ? p.ot.get_container() : this.get_container(); } + if(!/^(before|after)$/.test(p.p) && p.op && p.np && p.op[0] === p.np[0] && p.o.index() < p.cp) { p.cp++; } + //if(p.p === "before" && p.op && p.np && p.op[0] === p.np[0] && p.o.index() < p.cp) { p.cp--; } + p.or = p.np.find(" > ul > li:nth-child(" + (p.cp + 1) + ")"); + prepared_move = p; + this.__callback(prepared_move); + if(cb) { cb.call(this, prepared_move); } + }, + check_move : function () { + var obj = prepared_move, ret = true, r = obj.r === -1 ? this.get_container() : obj.r; + if(!obj || !obj.o || obj.or[0] === obj.o[0]) { return false; } + if(!obj.cy) { + if(obj.op && obj.np && obj.op[0] === obj.np[0] && obj.cp - 1 === obj.o.index()) { return false; } + obj.o.each(function () { + if(r.parentsUntil(".jstree", "li").andSelf().index(this) !== -1) { ret = false; return false; } + }); + } + return ret; + }, + move_node : function (obj, ref, position, is_copy, is_prepared, skip_check) { + if(!is_prepared) { + return this.prepare_move(obj, ref, position, function (p) { + this.move_node(p, false, false, is_copy, true, skip_check); + }); + } + if(is_copy) { + prepared_move.cy = true; + } + if(!skip_check && !this.check_move()) { return false; } + + this.__rollback(); + var o = false; + if(is_copy) { + o = obj.o.clone(true); + o.find("*[id]").andSelf().each(function () { + if(this.id) { this.id = "copy_" + this.id; } + }); + } + else { o = obj.o; } + + if(obj.or.length) { obj.or.before(o); } + else { + if(!obj.np.children("ul").length) { $("<ul />").appendTo(obj.np); } + obj.np.children("ul:eq(0)").append(o); + } + + try { + obj.ot.clean_node(obj.op); + obj.rt.clean_node(obj.np); + if(!obj.op.find("> ul > li").length) { + obj.op.removeClass("jstree-open jstree-closed").addClass("jstree-leaf").children("ul").remove(); + } + } catch (e) { } + + if(is_copy) { + prepared_move.cy = true; + prepared_move.oc = o; + } + this.__callback(prepared_move); + return prepared_move; + }, + _get_move : function () { return prepared_move; } + } + }); +})(jQuery); +//*/ + +/* + * jsTree ui plugin + * This plugins handles selecting/deselecting/hovering/dehovering nodes + */ +(function ($) { + var scrollbar_width, e1, e2; + $(function() { + if (/msie/.test(navigator.userAgent.toLowerCase())) { + e1 = $('<textarea cols="10" rows="2"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body'); + e2 = $('<textarea cols="10" rows="2" style="overflow: hidden;"></textarea>').css({ position: 'absolute', top: -1000, left: 0 }).appendTo('body'); + scrollbar_width = e1.width() - e2.width(); + e1.add(e2).remove(); + } + else { + e1 = $('<div />').css({ width: 100, height: 100, overflow: 'auto', position: 'absolute', top: -1000, left: 0 }) + .prependTo('body').append('<div />').find('div').css({ width: '100%', height: 200 }); + scrollbar_width = 100 - e1.width(); + e1.parent().remove(); + } + }); + $.jstree.plugin("ui", { + __init : function () { + this.data.ui.selected = $(); + this.data.ui.last_selected = false; + this.data.ui.hovered = null; + this.data.ui.to_select = this.get_settings().ui.initially_select; + + this.get_container() + .delegate("a", "click.jstree", $.proxy(function (event) { + event.preventDefault(); + event.currentTarget.blur(); + if(!$(event.currentTarget).hasClass("jstree-loading")) { + this.select_node(event.currentTarget, true, event); + } + }, this)) + .delegate("a", "mouseenter.jstree", $.proxy(function (event) { + if(!$(event.currentTarget).hasClass("jstree-loading")) { + this.hover_node(event.target); + } + }, this)) + .delegate("a", "mouseleave.jstree", $.proxy(function (event) { + if(!$(event.currentTarget).hasClass("jstree-loading")) { + this.dehover_node(event.target); + } + }, this)) + .bind("reopen.jstree", $.proxy(function () { + this.reselect(); + }, this)) + .bind("get_rollback.jstree", $.proxy(function () { + this.dehover_node(); + this.save_selected(); + }, this)) + .bind("set_rollback.jstree", $.proxy(function () { + this.reselect(); + }, this)) + .bind("close_node.jstree", $.proxy(function (event, data) { + var s = this._get_settings().ui, + obj = this._get_node(data.rslt.obj), + clk = (obj && obj.length) ? obj.children("ul").find("a.jstree-clicked") : $(), + _this = this; + if(s.selected_parent_close === false || !clk.length) { return; } + clk.each(function () { + _this.deselect_node(this); + if(s.selected_parent_close === "select_parent") { _this.select_node(obj); } + }); + }, this)) + .bind("delete_node.jstree", $.proxy(function (event, data) { + var s = this._get_settings().ui.select_prev_on_delete, + obj = this._get_node(data.rslt.obj), + clk = (obj && obj.length) ? obj.find("a.jstree-clicked") : [], + _this = this; + clk.each(function () { _this.deselect_node(this); }); + if(s && clk.length) { + data.rslt.prev.each(function () { + if(this.parentNode) { _this.select_node(this); return false; /* if return false is removed all prev nodes will be selected */} + }); + } + }, this)) + .bind("move_node.jstree", $.proxy(function (event, data) { + if(data.rslt.cy) { + data.rslt.oc.find("a.jstree-clicked").removeClass("jstree-clicked"); + } + }, this)); + }, + defaults : { + select_limit : -1, // 0, 1, 2 ... or -1 for unlimited + select_multiple_modifier : "ctrl", // on, or ctrl, shift, alt + select_range_modifier : "shift", + selected_parent_close : "select_parent", // false, "deselect", "select_parent" + selected_parent_open : true, + select_prev_on_delete : true, + disable_selecting_children : false, + initially_select : [] + }, + _fn : { + _get_node : function (obj, allow_multiple) { + if(typeof obj === "undefined" || obj === null) { return allow_multiple ? this.data.ui.selected : this.data.ui.last_selected; } + var $obj = $(obj, this.get_container()); + if($obj.is(".jstree") || obj == -1) { return -1; } + $obj = $obj.closest("li", this.get_container()); + return $obj.length ? $obj : false; + }, + _ui_notify : function (n, data) { + if(data.selected) { + this.select_node(n, false); + } + }, + save_selected : function () { + var _this = this; + this.data.ui.to_select = []; + this.data.ui.selected.each(function () { if(this.id) { _this.data.ui.to_select.push("#" + this.id.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:")); } }); + this.__callback(this.data.ui.to_select); + }, + reselect : function () { + var _this = this, + s = this.data.ui.to_select; + s = $.map($.makeArray(s), function (n) { return "#" + n.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:"); }); + // this.deselect_all(); WHY deselect, breaks plugin state notifier? + $.each(s, function (i, val) { if(val && val !== "#") { _this.select_node(val); } }); + this.data.ui.selected = this.data.ui.selected.filter(function () { return this.parentNode; }); + this.__callback(); + }, + refresh : function (obj) { + this.save_selected(); + return this.__call_old(); + }, + hover_node : function (obj) { + obj = this._get_node(obj); + if(!obj.length) { return false; } + //if(this.data.ui.hovered && obj.get(0) === this.data.ui.hovered.get(0)) { return; } + if(!obj.hasClass("jstree-hovered")) { this.dehover_node(); } + this.data.ui.hovered = obj.children("a").addClass("jstree-hovered").parent(); + this._fix_scroll(obj); + this.__callback({ "obj" : obj }); + }, + dehover_node : function () { + var obj = this.data.ui.hovered, p; + if(!obj || !obj.length) { return false; } + p = obj.children("a").removeClass("jstree-hovered").parent(); + if(this.data.ui.hovered[0] === p[0]) { this.data.ui.hovered = null; } + this.__callback({ "obj" : obj }); + }, + select_node : function (obj, check, e) { + obj = this._get_node(obj); + if(obj == -1 || !obj || !obj.length) { return false; } + var s = this._get_settings().ui, + is_multiple = (s.select_multiple_modifier == "on" || (s.select_multiple_modifier !== false && e && e[s.select_multiple_modifier + "Key"])), + is_range = (s.select_range_modifier !== false && e && e[s.select_range_modifier + "Key"] && this.data.ui.last_selected && this.data.ui.last_selected[0] !== obj[0] && this.data.ui.last_selected.parent()[0] === obj.parent()[0]), + is_selected = this.is_selected(obj), + proceed = true, + t = this; + if(check) { + if(s.disable_selecting_children && is_multiple && + ( + (obj.parentsUntil(".jstree","li").children("a.jstree-clicked").length) || + (obj.children("ul").find("a.jstree-clicked:eq(0)").length) + ) + ) { + return false; + } + proceed = false; + switch(!0) { + case (is_range): + this.data.ui.last_selected.addClass("jstree-last-selected"); + obj = obj[ obj.index() < this.data.ui.last_selected.index() ? "nextUntil" : "prevUntil" ](".jstree-last-selected").andSelf(); + if(s.select_limit == -1 || obj.length < s.select_limit) { + this.data.ui.last_selected.removeClass("jstree-last-selected"); + this.data.ui.selected.each(function () { + if(this !== t.data.ui.last_selected[0]) { t.deselect_node(this); } + }); + is_selected = false; + proceed = true; + } + else { + proceed = false; + } + break; + case (is_selected && !is_multiple): + this.deselect_all(); + is_selected = false; + proceed = true; + break; + case (!is_selected && !is_multiple): + if(s.select_limit == -1 || s.select_limit > 0) { + this.deselect_all(); + proceed = true; + } + break; + case (is_selected && is_multiple): + this.deselect_node(obj); + break; + case (!is_selected && is_multiple): + if(s.select_limit == -1 || this.data.ui.selected.length + 1 <= s.select_limit) { + proceed = true; + } + break; + } + } + if(proceed && !is_selected) { + if(!is_range) { this.data.ui.last_selected = obj; } + obj.children("a").addClass("jstree-clicked"); + if(s.selected_parent_open) { + obj.parents(".jstree-closed").each(function () { t.open_node(this, false, true); }); + } + this.data.ui.selected = this.data.ui.selected.add(obj); + this._fix_scroll(obj.eq(0)); + this.__callback({ "obj" : obj, "e" : e }); + } + }, + _fix_scroll : function (obj) { + var c = this.get_container()[0], t; + if(c.scrollHeight > c.offsetHeight) { + obj = this._get_node(obj); + if(!obj || obj === -1 || !obj.length || !obj.is(":visible")) { return; } + t = obj.offset().top - this.get_container().offset().top; + if(t < 0) { + c.scrollTop = c.scrollTop + t - 1; + } + if(t + this.data.core.li_height + (c.scrollWidth > c.offsetWidth ? scrollbar_width : 0) > c.offsetHeight) { + c.scrollTop = c.scrollTop + (t - c.offsetHeight + this.data.core.li_height + 1 + (c.scrollWidth > c.offsetWidth ? scrollbar_width : 0)); + } + } + }, + deselect_node : function (obj) { + obj = this._get_node(obj); + if(!obj.length) { return false; } + if(this.is_selected(obj)) { + obj.children("a").removeClass("jstree-clicked"); + this.data.ui.selected = this.data.ui.selected.not(obj); + if(this.data.ui.last_selected.get(0) === obj.get(0)) { this.data.ui.last_selected = this.data.ui.selected.eq(0); } + this.__callback({ "obj" : obj }); + } + }, + toggle_select : function (obj) { + obj = this._get_node(obj); + if(!obj.length) { return false; } + if(this.is_selected(obj)) { this.deselect_node(obj); } + else { this.select_node(obj); } + }, + is_selected : function (obj) { return this.data.ui.selected.index(this._get_node(obj)) >= 0; }, + get_selected : function (context) { + return context ? $(context).find("a.jstree-clicked").parent() : this.data.ui.selected; + }, + deselect_all : function (context) { + var ret = context ? $(context).find("a.jstree-clicked").parent() : this.get_container().find("a.jstree-clicked").parent(); + ret.children("a.jstree-clicked").removeClass("jstree-clicked"); + this.data.ui.selected = $([]); + this.data.ui.last_selected = false; + this.__callback({ "obj" : ret }); + } + } + }); + // include the selection plugin by default + $.jstree.defaults.plugins.push("ui"); +})(jQuery); +//*/ + +/* + * jsTree CRRM plugin + * Handles creating/renaming/removing/moving nodes by user interaction. + */ +(function ($) { + $.jstree.plugin("crrm", { + __init : function () { + this.get_container() + .bind("move_node.jstree", $.proxy(function (e, data) { + if(this._get_settings().crrm.move.open_onmove) { + var t = this; + data.rslt.np.parentsUntil(".jstree").andSelf().filter(".jstree-closed").each(function () { + t.open_node(this, false, true); + }); + } + }, this)); + }, + defaults : { + input_width_limit : 200, + move : { + always_copy : false, // false, true or "multitree" + open_onmove : true, + default_position : "last", + check_move : function (m) { return true; } + } + }, + _fn : { + _show_input : function (obj, callback) { + obj = this._get_node(obj); + var rtl = this._get_settings().core.rtl, + w = this._get_settings().crrm.input_width_limit, + w1 = obj.children("ins").width(), + w2 = obj.find("> a:visible > ins").width() * obj.find("> a:visible > ins").length, + t = this.get_text(obj), + h1 = $("<div />", { css : { "position" : "absolute", "top" : "-200px", "left" : (rtl ? "0px" : "-1000px"), "visibility" : "hidden" } }).appendTo("body"), + h2 = obj.css("position","relative").append( + $("<input />", { + "value" : t, + "class" : "jstree-rename-input", + // "size" : t.length, + "css" : { + "padding" : "0", + "border" : "1px solid silver", + "position" : "absolute", + "left" : (rtl ? "auto" : (w1 + w2 + 4) + "px"), + "right" : (rtl ? (w1 + w2 + 4) + "px" : "auto"), + "top" : "0px", + "height" : (this.data.core.li_height - 2) + "px", + "lineHeight" : (this.data.core.li_height - 2) + "px", + "width" : "150px" // will be set a bit further down + }, + "blur" : $.proxy(function () { + var i = obj.children(".jstree-rename-input"), + v = i.val(); + if(v === "") { v = t; } + h1.remove(); + i.remove(); // rollback purposes + this.set_text(obj,t); // rollback purposes + this.rename_node(obj, v); + callback.call(this, obj, v, t); + obj.css("position",""); + }, this), + "keyup" : function (event) { + var key = event.keyCode || event.which; + if(key == 27) { this.value = t; this.blur(); return; } + else if(key == 13) { this.blur(); return; } + else { + h2.width(Math.min(h1.text("pW" + this.value).width(),w)); + } + }, + "keypress" : function(event) { + var key = event.keyCode || event.which; + if(key == 13) { return false; } + } + }) + ).children(".jstree-rename-input"); + this.set_text(obj, ""); + h1.css({ + fontFamily : h2.css('fontFamily') || '', + fontSize : h2.css('fontSize') || '', + fontWeight : h2.css('fontWeight') || '', + fontStyle : h2.css('fontStyle') || '', + fontStretch : h2.css('fontStretch') || '', + fontVariant : h2.css('fontVariant') || '', + letterSpacing : h2.css('letterSpacing') || '', + wordSpacing : h2.css('wordSpacing') || '' + }); + h2.width(Math.min(h1.text("pW" + h2[0].value).width(),w))[0].select(); + }, + rename : function (obj) { + obj = this._get_node(obj); + this.__rollback(); + var f = this.__callback; + this._show_input(obj, function (obj, new_name, old_name) { + f.call(this, { "obj" : obj, "new_name" : new_name, "old_name" : old_name }); + }); + }, + create : function (obj, position, js, callback, skip_rename) { + var t, _this = this; + obj = this._get_node(obj); + if(!obj) { obj = -1; } + this.__rollback(); + t = this.create_node(obj, position, js, function (t) { + var p = this._get_parent(t), + pos = $(t).index(); + if(callback) { callback.call(this, t); } + if(p.length && p.hasClass("jstree-closed")) { this.open_node(p, false, true); } + if(!skip_rename) { + this._show_input(t, function (obj, new_name, old_name) { + _this.__callback({ "obj" : obj, "name" : new_name, "parent" : p, "position" : pos }); + }); + } + else { _this.__callback({ "obj" : t, "name" : this.get_text(t), "parent" : p, "position" : pos }); } + }); + return t; + }, + remove : function (obj) { + obj = this._get_node(obj, true); + var p = this._get_parent(obj), prev = this._get_prev(obj); + this.__rollback(); + obj = this.delete_node(obj); + if(obj !== false) { this.__callback({ "obj" : obj, "prev" : prev, "parent" : p }); } + }, + check_move : function () { + if(!this.__call_old()) { return false; } + var s = this._get_settings().crrm.move; + if(!s.check_move.call(this, this._get_move())) { return false; } + return true; + }, + move_node : function (obj, ref, position, is_copy, is_prepared, skip_check) { + var s = this._get_settings().crrm.move; + if(!is_prepared) { + if(typeof position === "undefined") { position = s.default_position; } + if(position === "inside" && !s.default_position.match(/^(before|after)$/)) { position = s.default_position; } + return this.__call_old(true, obj, ref, position, is_copy, false, skip_check); + } + // if the move is already prepared + if(s.always_copy === true || (s.always_copy === "multitree" && obj.rt.get_index() !== obj.ot.get_index() )) { + is_copy = true; + } + this.__call_old(true, obj, ref, position, is_copy, true, skip_check); + }, + + cut : function (obj) { + obj = this._get_node(obj, true); + if(!obj || !obj.length) { return false; } + this.data.crrm.cp_nodes = false; + this.data.crrm.ct_nodes = obj; + this.__callback({ "obj" : obj }); + }, + copy : function (obj) { + obj = this._get_node(obj, true); + if(!obj || !obj.length) { return false; } + this.data.crrm.ct_nodes = false; + this.data.crrm.cp_nodes = obj; + this.__callback({ "obj" : obj }); + }, + paste : function (obj) { + obj = this._get_node(obj); + if(!obj || !obj.length) { return false; } + var nodes = this.data.crrm.ct_nodes ? this.data.crrm.ct_nodes : this.data.crrm.cp_nodes; + if(!this.data.crrm.ct_nodes && !this.data.crrm.cp_nodes) { return false; } + if(this.data.crrm.ct_nodes) { this.move_node(this.data.crrm.ct_nodes, obj); this.data.crrm.ct_nodes = false; } + if(this.data.crrm.cp_nodes) { this.move_node(this.data.crrm.cp_nodes, obj, false, true); } + this.__callback({ "obj" : obj, "nodes" : nodes }); + } + } + }); + // include the crr plugin by default + // $.jstree.defaults.plugins.push("crrm"); +})(jQuery); +//*/ + +/* + * jsTree themes plugin + * Handles loading and setting themes, as well as detecting path to themes, etc. + */ +(function ($) { + var themes_loaded = []; + // this variable stores the path to the themes folder - if left as false - it will be autodetected + $.jstree._themes = false; + $.jstree.plugin("themes", { + __init : function () { + this.get_container() + .bind("init.jstree", $.proxy(function () { + var s = this._get_settings().themes; + this.data.themes.dots = s.dots; + this.data.themes.icons = s.icons; + this.set_theme(s.theme, s.url); + }, this)) + .bind("loaded.jstree", $.proxy(function () { + // bound here too, as simple HTML tree's won't honor dots & icons otherwise + if(!this.data.themes.dots) { this.hide_dots(); } + else { this.show_dots(); } + if(!this.data.themes.icons) { this.hide_icons(); } + else { this.show_icons(); } + }, this)); + }, + defaults : { + theme : "default", + url : false, + dots : true, + icons : true + }, + _fn : { + set_theme : function (theme_name, theme_url) { + if(!theme_name) { return false; } + if(!theme_url) { theme_url = $.jstree._themes + theme_name + '/style.css'; } + if($.inArray(theme_url, themes_loaded) == -1) { + $.vakata.css.add_sheet({ "url" : theme_url }); + themes_loaded.push(theme_url); + } + if(this.data.themes.theme != theme_name) { + this.get_container().removeClass('jstree-' + this.data.themes.theme); + this.data.themes.theme = theme_name; + } + this.get_container().addClass('jstree-' + theme_name); + if(!this.data.themes.dots) { this.hide_dots(); } + else { this.show_dots(); } + if(!this.data.themes.icons) { this.hide_icons(); } + else { this.show_icons(); } + this.__callback(); + }, + get_theme : function () { return this.data.themes.theme; }, + + show_dots : function () { this.data.themes.dots = true; this.get_container().children("ul").removeClass("jstree-no-dots"); }, + hide_dots : function () { this.data.themes.dots = false; this.get_container().children("ul").addClass("jstree-no-dots"); }, + toggle_dots : function () { if(this.data.themes.dots) { this.hide_dots(); } else { this.show_dots(); } }, + + show_icons : function () { this.data.themes.icons = true; this.get_container().children("ul").removeClass("jstree-no-icons"); }, + hide_icons : function () { this.data.themes.icons = false; this.get_container().children("ul").addClass("jstree-no-icons"); }, + toggle_icons: function () { if(this.data.themes.icons) { this.hide_icons(); } else { this.show_icons(); } } + } + }); + // autodetect themes path + $(function () { + if($.jstree._themes === false) { + $("script").each(function () { + if(this.src.toString().match(/jquery\.jstree[^\/]*?\.js(\?.*)?$/)) { + $.jstree._themes = this.src.toString().replace(/jquery\.jstree[^\/]*?\.js(\?.*)?$/, "") + 'themes/'; + return false; + } + }); + } + if($.jstree._themes === false) { $.jstree._themes = "themes/"; } + }); + // include the themes plugin by default + $.jstree.defaults.plugins.push("themes"); +})(jQuery); +//*/ + +/* + * jsTree hotkeys plugin + * Enables keyboard navigation for all tree instances + * Depends on the jstree ui & jquery hotkeys plugins + */ +(function ($) { + var bound = []; + function exec(i, event) { + var f = $.jstree._focused(), tmp; + if(f && f.data && f.data.hotkeys && f.data.hotkeys.enabled) { + tmp = f._get_settings().hotkeys[i]; + if(tmp) { return tmp.call(f, event); } + } + } + $.jstree.plugin("hotkeys", { + __init : function () { + if(typeof $.hotkeys === "undefined") { throw "jsTree hotkeys: jQuery hotkeys plugin not included."; } + if(!this.data.ui) { throw "jsTree hotkeys: jsTree UI plugin not included."; } + $.each(this._get_settings().hotkeys, function (i, v) { + if(v !== false && $.inArray(i, bound) == -1) { + $(document).bind("keydown", i, function (event) { return exec(i, event); }); + bound.push(i); + } + }); + this.get_container() + .bind("lock.jstree", $.proxy(function () { + if(this.data.hotkeys.enabled) { this.data.hotkeys.enabled = false; this.data.hotkeys.revert = true; } + }, this)) + .bind("unlock.jstree", $.proxy(function () { + if(this.data.hotkeys.revert) { this.data.hotkeys.enabled = true; } + }, this)); + this.enable_hotkeys(); + }, + defaults : { + "up" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected || -1; + this.hover_node(this._get_prev(o)); + return false; + }, + "ctrl+up" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected || -1; + this.hover_node(this._get_prev(o)); + return false; + }, + "shift+up" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected || -1; + this.hover_node(this._get_prev(o)); + return false; + }, + "down" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected || -1; + this.hover_node(this._get_next(o)); + return false; + }, + "ctrl+down" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected || -1; + this.hover_node(this._get_next(o)); + return false; + }, + "shift+down" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected || -1; + this.hover_node(this._get_next(o)); + return false; + }, + "left" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected; + if(o) { + if(o.hasClass("jstree-open")) { this.close_node(o); } + else { this.hover_node(this._get_prev(o)); } + } + return false; + }, + "ctrl+left" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected; + if(o) { + if(o.hasClass("jstree-open")) { this.close_node(o); } + else { this.hover_node(this._get_prev(o)); } + } + return false; + }, + "shift+left" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected; + if(o) { + if(o.hasClass("jstree-open")) { this.close_node(o); } + else { this.hover_node(this._get_prev(o)); } + } + return false; + }, + "right" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected; + if(o && o.length) { + if(o.hasClass("jstree-closed")) { this.open_node(o); } + else { this.hover_node(this._get_next(o)); } + } + return false; + }, + "ctrl+right" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected; + if(o && o.length) { + if(o.hasClass("jstree-closed")) { this.open_node(o); } + else { this.hover_node(this._get_next(o)); } + } + return false; + }, + "shift+right" : function () { + var o = this.data.ui.hovered || this.data.ui.last_selected; + if(o && o.length) { + if(o.hasClass("jstree-closed")) { this.open_node(o); } + else { this.hover_node(this._get_next(o)); } + } + return false; + }, + "space" : function () { + if(this.data.ui.hovered) { this.data.ui.hovered.children("a:eq(0)").click(); } + return false; + }, + "ctrl+space" : function (event) { + event.type = "click"; + if(this.data.ui.hovered) { this.data.ui.hovered.children("a:eq(0)").trigger(event); } + return false; + }, + "shift+space" : function (event) { + event.type = "click"; + if(this.data.ui.hovered) { this.data.ui.hovered.children("a:eq(0)").trigger(event); } + return false; + }, + "f2" : function () { this.rename(this.data.ui.hovered || this.data.ui.last_selected); }, + "del" : function () { this.remove(this.data.ui.hovered || this._get_node(null)); } + }, + _fn : { + enable_hotkeys : function () { + this.data.hotkeys.enabled = true; + }, + disable_hotkeys : function () { + this.data.hotkeys.enabled = false; + } + } + }); +})(jQuery); +//*/ + +/* + * jsTree JSON plugin + * The JSON data store. Datastores are build by overriding the `load_node` and `_is_loaded` functions. + */ +(function ($) { + $.jstree.plugin("json_data", { + __init : function() { + var s = this._get_settings().json_data; + if(s.progressive_unload) { + this.get_container().bind("after_close.jstree", function (e, data) { + data.rslt.obj.children("ul").remove(); + }); + } + }, + defaults : { + // `data` can be a function: + // * accepts two arguments - node being loaded and a callback to pass the result to + // * will be executed in the current tree's scope & ajax won't be supported + data : false, + ajax : false, + correct_state : true, + progressive_render : false, + progressive_unload : false + }, + _fn : { + load_node : function (obj, s_call, e_call) { var _this = this; this.load_node_json(obj, function () { _this.__callback({ "obj" : _this._get_node(obj) }); s_call.call(this); }, e_call); }, + _is_loaded : function (obj) { + var s = this._get_settings().json_data; + obj = this._get_node(obj); + return obj == -1 || !obj || (!s.ajax && !s.progressive_render && !$.isFunction(s.data)) || obj.is(".jstree-open, .jstree-leaf") || obj.children("ul").children("li").length > 0; + }, + refresh : function (obj) { + obj = this._get_node(obj); + var s = this._get_settings().json_data; + if(obj && obj !== -1 && s.progressive_unload && ($.isFunction(s.data) || !!s.ajax)) { + obj.removeData("jstree_children"); + } + return this.__call_old(); + }, + load_node_json : function (obj, s_call, e_call) { + var s = this.get_settings().json_data, d, + error_func = function () {}, + success_func = function () {}; + obj = this._get_node(obj); + + if(obj && obj !== -1 && (s.progressive_render || s.progressive_unload) && !obj.is(".jstree-open, .jstree-leaf") && obj.children("ul").children("li").length === 0 && obj.data("jstree_children")) { + d = this._parse_json(obj.data("jstree_children"), obj); + if(d) { + obj.append(d); + if(!s.progressive_unload) { obj.removeData("jstree_children"); } + } + this.clean_node(obj); + if(s_call) { s_call.call(this); } + return; + } + + if(obj && obj !== -1) { + if(obj.data("jstree_is_loading")) { return; } + else { obj.data("jstree_is_loading",true); } + } + switch(!0) { + case (!s.data && !s.ajax): throw "Neither data nor ajax settings supplied."; + // function option added here for easier model integration (also supporting async - see callback) + case ($.isFunction(s.data)): + s.data.call(this, obj, $.proxy(function (d) { + d = this._parse_json(d, obj); + if(!d) { + if(obj === -1 || !obj) { + if(s.correct_state) { this.get_container().children("ul").empty(); } + } + else { + obj.children("a.jstree-loading").removeClass("jstree-loading"); + obj.removeData("jstree_is_loading"); + if(s.correct_state) { this.correct_state(obj); } + } + if(e_call) { e_call.call(this); } + } + else { + if(obj === -1 || !obj) { this.get_container().children("ul").empty().append(d.children()); } + else { obj.append(d).children("a.jstree-loading").removeClass("jstree-loading"); obj.removeData("jstree_is_loading"); } + this.clean_node(obj); + if(s_call) { s_call.call(this); } + } + }, this)); + break; + case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)): + if(!obj || obj == -1) { + d = this._parse_json(s.data, obj); + if(d) { + this.get_container().children("ul").empty().append(d.children()); + this.clean_node(); + } + else { + if(s.correct_state) { this.get_container().children("ul").empty(); } + } + } + if(s_call) { s_call.call(this); } + break; + case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1): + error_func = function (x, t, e) { + var ef = this.get_settings().json_data.ajax.error; + if(ef) { ef.call(this, x, t, e); } + if(obj != -1 && obj.length) { + obj.children("a.jstree-loading").removeClass("jstree-loading"); + obj.removeData("jstree_is_loading"); + if(t === "success" && s.correct_state) { this.correct_state(obj); } + } + else { + if(t === "success" && s.correct_state) { this.get_container().children("ul").empty(); } + } + if(e_call) { e_call.call(this); } + }; + success_func = function (d, t, x) { + var sf = this.get_settings().json_data.ajax.success; + if(sf) { d = sf.call(this,d,t,x) || d; } + if(d === "" || (d && d.toString && d.toString().replace(/^[\s\n]+$/,"") === "") || (!$.isArray(d) && !$.isPlainObject(d))) { + return error_func.call(this, x, t, ""); + } + d = this._parse_json(d, obj); + if(d) { + if(obj === -1 || !obj) { this.get_container().children("ul").empty().append(d.children()); } + else { obj.append(d).children("a.jstree-loading").removeClass("jstree-loading"); obj.removeData("jstree_is_loading"); } + this.clean_node(obj); + if(s_call) { s_call.call(this); } + } + else { + if(obj === -1 || !obj) { + if(s.correct_state) { + this.get_container().children("ul").empty(); + if(s_call) { s_call.call(this); } + } + } + else { + obj.children("a.jstree-loading").removeClass("jstree-loading"); + obj.removeData("jstree_is_loading"); + if(s.correct_state) { + this.correct_state(obj); + if(s_call) { s_call.call(this); } + } + } + } + }; + s.ajax.context = this; + s.ajax.error = error_func; + s.ajax.success = success_func; + if(!s.ajax.dataType) { s.ajax.dataType = "json"; } + if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); } + if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); } + $.ajax(s.ajax); + break; + } + }, + _parse_json : function (js, obj, is_callback) { + var d = false, + p = this._get_settings(), + s = p.json_data, + t = p.core.html_titles, + tmp, i, j, ul1, ul2; + + if(!js) { return d; } + if(s.progressive_unload && obj && obj !== -1) { + obj.data("jstree_children", d); + } + if($.isArray(js)) { + d = $(); + if(!js.length) { return false; } + for(i = 0, j = js.length; i < j; i++) { + tmp = this._parse_json(js[i], obj, true); + if(tmp.length) { d = d.add(tmp); } + } + } + else { + if(typeof js == "string") { js = { data : js }; } + if(!js.data && js.data !== "") { return d; } + d = $("<li />"); + if(js.attr) { d.attr(js.attr); } + if(js.metadata) { d.data(js.metadata); } + if(js.state) { d.addClass("jstree-" + js.state); } + if(!$.isArray(js.data)) { tmp = js.data; js.data = []; js.data.push(tmp); } + $.each(js.data, function (i, m) { + tmp = $("<a />"); + if($.isFunction(m)) { m = m.call(this, js); } + if(typeof m == "string") { tmp.attr('href','#')[ t ? "html" : "text" ](m); } + else { + if(!m.attr) { m.attr = {}; } + if(!m.attr.href) { m.attr.href = '#'; } + tmp.attr(m.attr)[ t ? "html" : "text" ](m.title); + if(m.language) { tmp.addClass(m.language); } + } + tmp.prepend("<ins class='jstree-icon'>&#160;</ins>"); + if(!m.icon && js.icon) { m.icon = js.icon; } + if(m.icon) { + if(m.icon.indexOf("/") === -1) { tmp.children("ins").addClass(m.icon); } + else { tmp.children("ins").css("background","url('" + m.icon + "') center center no-repeat"); } + } + d.append(tmp); + }); + d.prepend("<ins class='jstree-icon'>&#160;</ins>"); + if(js.children) { + if(s.progressive_render && js.state !== "open") { + d.addClass("jstree-closed").data("jstree_children", js.children); + } + else { + if(s.progressive_unload) { d.data("jstree_children", js.children); } + if($.isArray(js.children) && js.children.length) { + tmp = this._parse_json(js.children, obj, true); + if(tmp.length) { + ul2 = $("<ul />"); + ul2.append(tmp); + d.append(ul2); + } + } + } + } + } + if(!is_callback) { + ul1 = $("<ul />"); + ul1.append(d); + d = ul1; + } + return d; + }, + get_json : function (obj, li_attr, a_attr, is_callback) { + var result = [], + s = this._get_settings(), + _this = this, + tmp1, tmp2, li, a, t, lang; + obj = this._get_node(obj); + if(!obj || obj === -1) { obj = this.get_container().find("> ul > li"); } + li_attr = $.isArray(li_attr) ? li_attr : [ "id", "class" ]; + if(!is_callback && this.data.types) { li_attr.push(s.types.type_attr); } + a_attr = $.isArray(a_attr) ? a_attr : [ ]; + + obj.each(function () { + li = $(this); + tmp1 = { data : [] }; + if(li_attr.length) { tmp1.attr = { }; } + $.each(li_attr, function (i, v) { + tmp2 = li.attr(v); + if(tmp2 && tmp2.length && tmp2.replace(/jstree[^ ]*/ig,'').length) { + tmp1.attr[v] = (" " + tmp2).replace(/ jstree[^ ]*/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,""); + } + }); + if(li.hasClass("jstree-open")) { tmp1.state = "open"; } + if(li.hasClass("jstree-closed")) { tmp1.state = "closed"; } + if(li.data()) { tmp1.metadata = li.data(); } + a = li.children("a"); + a.each(function () { + t = $(this); + if( + a_attr.length || + $.inArray("languages", s.plugins) !== -1 || + t.children("ins").get(0).style.backgroundImage.length || + (t.children("ins").get(0).className && t.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').length) + ) { + lang = false; + if($.inArray("languages", s.plugins) !== -1 && $.isArray(s.languages) && s.languages.length) { + $.each(s.languages, function (l, lv) { + if(t.hasClass(lv)) { + lang = lv; + return false; + } + }); + } + tmp2 = { attr : { }, title : _this.get_text(t, lang) }; + $.each(a_attr, function (k, z) { + tmp2.attr[z] = (" " + (t.attr(z) || "")).replace(/ jstree[^ ]*/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,""); + }); + if($.inArray("languages", s.plugins) !== -1 && $.isArray(s.languages) && s.languages.length) { + $.each(s.languages, function (k, z) { + if(t.hasClass(z)) { tmp2.language = z; return true; } + }); + } + if(t.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\s+$/ig,"").length) { + tmp2.icon = t.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,""); + } + if(t.children("ins").get(0).style.backgroundImage.length) { + tmp2.icon = t.children("ins").get(0).style.backgroundImage.replace("url(","").replace(")",""); + } + } + else { + tmp2 = _this.get_text(t); + } + if(a.length > 1) { tmp1.data.push(tmp2); } + else { tmp1.data = tmp2; } + }); + li = li.find("> ul > li"); + if(li.length) { tmp1.children = _this.get_json(li, li_attr, a_attr, true); } + result.push(tmp1); + }); + return result; + } + } + }); +})(jQuery); +//*/ + +/* + * jsTree languages plugin + * Adds support for multiple language versions in one tree + * This basically allows for many titles coexisting in one node, but only one of them being visible at any given time + * This is useful for maintaining the same structure in many languages (hence the name of the plugin) + */ +(function ($) { + var sh = false; + $.jstree.plugin("languages", { + __init : function () { this._load_css(); }, + defaults : [], + _fn : { + set_lang : function (i) { + var langs = this._get_settings().languages, + st = false, + selector = ".jstree-" + this.get_index() + ' a'; + if(!$.isArray(langs) || langs.length === 0) { return false; } + if($.inArray(i,langs) == -1) { + if(!!langs[i]) { i = langs[i]; } + else { return false; } + } + if(i == this.data.languages.current_language) { return true; } + st = $.vakata.css.get_css(selector + "." + this.data.languages.current_language, false, sh); + if(st !== false) { st.style.display = "none"; } + st = $.vakata.css.get_css(selector + "." + i, false, sh); + if(st !== false) { st.style.display = ""; } + this.data.languages.current_language = i; + this.__callback(i); + return true; + }, + get_lang : function () { + return this.data.languages.current_language; + }, + _get_string : function (key, lang) { + var langs = this._get_settings().languages, + s = this._get_settings().core.strings; + if($.isArray(langs) && langs.length) { + lang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language; + } + if(s[lang] && s[lang][key]) { return s[lang][key]; } + if(s[key]) { return s[key]; } + return key; + }, + get_text : function (obj, lang) { + obj = this._get_node(obj) || this.data.ui.last_selected; + if(!obj.size()) { return false; } + var langs = this._get_settings().languages, + s = this._get_settings().core.html_titles; + if($.isArray(langs) && langs.length) { + lang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language; + obj = obj.children("a." + lang); + } + else { obj = obj.children("a:eq(0)"); } + if(s) { + obj = obj.clone(); + obj.children("INS").remove(); + return obj.html(); + } + else { + obj = obj.contents().filter(function() { return this.nodeType == 3; })[0]; + return obj.nodeValue; + } + }, + set_text : function (obj, val, lang) { + obj = this._get_node(obj) || this.data.ui.last_selected; + if(!obj.size()) { return false; } + var langs = this._get_settings().languages, + s = this._get_settings().core.html_titles, + tmp; + if($.isArray(langs) && langs.length) { + lang = (lang && $.inArray(lang,langs) != -1) ? lang : this.data.languages.current_language; + obj = obj.children("a." + lang); + } + else { obj = obj.children("a:eq(0)"); } + if(s) { + tmp = obj.children("INS").clone(); + obj.html(val).prepend(tmp); + this.__callback({ "obj" : obj, "name" : val, "lang" : lang }); + return true; + } + else { + obj = obj.contents().filter(function() { return this.nodeType == 3; })[0]; + this.__callback({ "obj" : obj, "name" : val, "lang" : lang }); + return (obj.nodeValue = val); + } + }, + _load_css : function () { + var langs = this._get_settings().languages, + str = "/* languages css */", + selector = ".jstree-" + this.get_index() + ' a', + ln; + if($.isArray(langs) && langs.length) { + this.data.languages.current_language = langs[0]; + for(ln = 0; ln < langs.length; ln++) { + str += selector + "." + langs[ln] + " {"; + if(langs[ln] != this.data.languages.current_language) { str += " display:none; "; } + str += " } "; + } + sh = $.vakata.css.add_sheet({ 'str' : str, 'title' : "jstree-languages" }); + } + }, + create_node : function (obj, position, js, callback) { + var t = this.__call_old(true, obj, position, js, function (t) { + var langs = this._get_settings().languages, + a = t.children("a"), + ln; + if($.isArray(langs) && langs.length) { + for(ln = 0; ln < langs.length; ln++) { + if(!a.is("." + langs[ln])) { + t.append(a.eq(0).clone().removeClass(langs.join(" ")).addClass(langs[ln])); + } + } + a.not("." + langs.join(", .")).remove(); + } + if(callback) { callback.call(this, t); } + }); + return t; + } + } + }); +})(jQuery); +//*/ + +/* + * jsTree cookies plugin + * Stores the currently opened/selected nodes in a cookie and then restores them + * Depends on the jquery.cookie plugin + */ +(function ($) { + $.jstree.plugin("cookies", { + __init : function () { + if(typeof $.cookie === "undefined") { throw "jsTree cookie: jQuery cookie plugin not included."; } + + var s = this._get_settings().cookies, + tmp; + if(!!s.save_loaded) { + tmp = $.cookie(s.save_loaded); + if(tmp && tmp.length) { this.data.core.to_load = tmp.split(","); } + } + if(!!s.save_opened) { + tmp = $.cookie(s.save_opened); + if(tmp && tmp.length) { this.data.core.to_open = tmp.split(","); } + } + if(!!s.save_selected) { + tmp = $.cookie(s.save_selected); + if(tmp && tmp.length && this.data.ui) { this.data.ui.to_select = tmp.split(","); } + } + this.get_container() + .one( ( this.data.ui ? "reselect" : "reopen" ) + ".jstree", $.proxy(function () { + this.get_container() + .bind("open_node.jstree close_node.jstree select_node.jstree deselect_node.jstree", $.proxy(function (e) { + if(this._get_settings().cookies.auto_save) { this.save_cookie((e.handleObj.namespace + e.handleObj.type).replace("jstree","")); } + }, this)); + }, this)); + }, + defaults : { + save_loaded : "jstree_load", + save_opened : "jstree_open", + save_selected : "jstree_select", + auto_save : true, + cookie_options : {} + }, + _fn : { + save_cookie : function (c) { + if(this.data.core.refreshing) { return; } + var s = this._get_settings().cookies; + if(!c) { // if called manually and not by event + if(s.save_loaded) { + this.save_loaded(); + $.cookie(s.save_loaded, this.data.core.to_load.join(","), s.cookie_options); + } + if(s.save_opened) { + this.save_opened(); + $.cookie(s.save_opened, this.data.core.to_open.join(","), s.cookie_options); + } + if(s.save_selected && this.data.ui) { + this.save_selected(); + $.cookie(s.save_selected, this.data.ui.to_select.join(","), s.cookie_options); + } + return; + } + switch(c) { + case "open_node": + case "close_node": + if(!!s.save_opened) { + this.save_opened(); + $.cookie(s.save_opened, this.data.core.to_open.join(","), s.cookie_options); + } + if(!!s.save_loaded) { + this.save_loaded(); + $.cookie(s.save_loaded, this.data.core.to_load.join(","), s.cookie_options); + } + break; + case "select_node": + case "deselect_node": + if(!!s.save_selected && this.data.ui) { + this.save_selected(); + $.cookie(s.save_selected, this.data.ui.to_select.join(","), s.cookie_options); + } + break; + } + } + } + }); + // include cookies by default + // $.jstree.defaults.plugins.push("cookies"); +})(jQuery); +//*/ + +/* + * jsTree sort plugin + * Sorts items alphabetically (or using any other function) + */ +(function ($) { + $.jstree.plugin("sort", { + __init : function () { + this.get_container() + .bind("load_node.jstree", $.proxy(function (e, data) { + var obj = this._get_node(data.rslt.obj); + obj = obj === -1 ? this.get_container().children("ul") : obj.children("ul"); + this.sort(obj); + }, this)) + .bind("rename_node.jstree create_node.jstree create.jstree", $.proxy(function (e, data) { + this.sort(data.rslt.obj.parent()); + }, this)) + .bind("move_node.jstree", $.proxy(function (e, data) { + var m = data.rslt.np == -1 ? this.get_container() : data.rslt.np; + this.sort(m.children("ul")); + }, this)); + }, + defaults : function (a, b) { return this.get_text(a) > this.get_text(b) ? 1 : -1; }, + _fn : { + sort : function (obj) { + var s = this._get_settings().sort, + t = this; + obj.append($.makeArray(obj.children("li")).sort($.proxy(s, t))); + obj.find("> li > ul").each(function() { t.sort($(this)); }); + this.clean_node(obj); + } + } + }); +})(jQuery); +//*/ + +/* + * jsTree DND plugin + * Drag and drop plugin for moving/copying nodes + */ +(function ($) { + var o = false, + r = false, + m = false, + ml = false, + sli = false, + sti = false, + dir1 = false, + dir2 = false, + last_pos = false; + $.vakata.dnd = { + is_down : false, + is_drag : false, + helper : false, + scroll_spd : 10, + init_x : 0, + init_y : 0, + threshold : 5, + helper_left : 5, + helper_top : 10, + user_data : {}, + + drag_start : function (e, data, html) { + if($.vakata.dnd.is_drag) { $.vakata.drag_stop({}); } + try { + e.currentTarget.unselectable = "on"; + e.currentTarget.onselectstart = function() { return false; }; + if(e.currentTarget.style) { e.currentTarget.style.MozUserSelect = "none"; } + } catch(err) { } + $.vakata.dnd.init_x = e.pageX; + $.vakata.dnd.init_y = e.pageY; + $.vakata.dnd.user_data = data; + $.vakata.dnd.is_down = true; + $.vakata.dnd.helper = $("<div id='vakata-dragged' />").html(html); //.fadeTo(10,0.25); + $(document).bind("mousemove", $.vakata.dnd.drag); + $(document).bind("mouseup", $.vakata.dnd.drag_stop); + return false; + }, + drag : function (e) { + if(!$.vakata.dnd.is_down) { return; } + if(!$.vakata.dnd.is_drag) { + if(Math.abs(e.pageX - $.vakata.dnd.init_x) > 5 || Math.abs(e.pageY - $.vakata.dnd.init_y) > 5) { + $.vakata.dnd.helper.appendTo("body"); + $.vakata.dnd.is_drag = true; + $(document).triggerHandler("drag_start.vakata", { "event" : e, "data" : $.vakata.dnd.user_data }); + } + else { return; } + } + + // maybe use a scrolling parent element instead of document? + if(e.type === "mousemove") { // thought of adding scroll in order to move the helper, but mouse poisition is n/a + var d = $(document), t = d.scrollTop(), l = d.scrollLeft(); + if(e.pageY - t < 20) { + if(sti && dir1 === "down") { clearInterval(sti); sti = false; } + if(!sti) { dir1 = "up"; sti = setInterval(function () { $(document).scrollTop($(document).scrollTop() - $.vakata.dnd.scroll_spd); }, 150); } + } + else { + if(sti && dir1 === "up") { clearInterval(sti); sti = false; } + } + if($(window).height() - (e.pageY - t) < 20) { + if(sti && dir1 === "up") { clearInterval(sti); sti = false; } + if(!sti) { dir1 = "down"; sti = setInterval(function () { $(document).scrollTop($(document).scrollTop() + $.vakata.dnd.scroll_spd); }, 150); } + } + else { + if(sti && dir1 === "down") { clearInterval(sti); sti = false; } + } + + if(e.pageX - l < 20) { + if(sli && dir2 === "right") { clearInterval(sli); sli = false; } + if(!sli) { dir2 = "left"; sli = setInterval(function () { $(document).scrollLeft($(document).scrollLeft() - $.vakata.dnd.scroll_spd); }, 150); } + } + else { + if(sli && dir2 === "left") { clearInterval(sli); sli = false; } + } + if($(window).width() - (e.pageX - l) < 20) { + if(sli && dir2 === "left") { clearInterval(sli); sli = false; } + if(!sli) { dir2 = "right"; sli = setInterval(function () { $(document).scrollLeft($(document).scrollLeft() + $.vakata.dnd.scroll_spd); }, 150); } + } + else { + if(sli && dir2 === "right") { clearInterval(sli); sli = false; } + } + } + + $.vakata.dnd.helper.css({ left : (e.pageX + $.vakata.dnd.helper_left) + "px", top : (e.pageY + $.vakata.dnd.helper_top) + "px" }); + $(document).triggerHandler("drag.vakata", { "event" : e, "data" : $.vakata.dnd.user_data }); + }, + drag_stop : function (e) { + if(sli) { clearInterval(sli); } + if(sti) { clearInterval(sti); } + $(document).unbind("mousemove", $.vakata.dnd.drag); + $(document).unbind("mouseup", $.vakata.dnd.drag_stop); + $(document).triggerHandler("drag_stop.vakata", { "event" : e, "data" : $.vakata.dnd.user_data }); + $.vakata.dnd.helper.remove(); + $.vakata.dnd.init_x = 0; + $.vakata.dnd.init_y = 0; + $.vakata.dnd.user_data = {}; + $.vakata.dnd.is_down = false; + $.vakata.dnd.is_drag = false; + } + }; + $(function() { + var css_string = '#vakata-dragged { display:block; margin:0 0 0 0; padding:4px 4px 4px 24px; position:absolute; top:-2000px; line-height:16px; z-index:10000; } '; + $.vakata.css.add_sheet({ str : css_string, title : "vakata" }); + }); + + $.jstree.plugin("dnd", { + __init : function () { + this.data.dnd = { + active : false, + after : false, + inside : false, + before : false, + off : false, + prepared : false, + w : 0, + to1 : false, + to2 : false, + cof : false, + cw : false, + ch : false, + i1 : false, + i2 : false, + mto : false + }; + this.get_container() + .bind("mouseenter.jstree", $.proxy(function (e) { + if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) { + if(this.data.themes) { + m.attr("class", "jstree-" + this.data.themes.theme); + if(ml) { ml.attr("class", "jstree-" + this.data.themes.theme); } + $.vakata.dnd.helper.attr("class", "jstree-dnd-helper jstree-" + this.data.themes.theme); + } + //if($(e.currentTarget).find("> ul > li").length === 0) { + if(e.currentTarget === e.target && $.vakata.dnd.user_data.obj && $($.vakata.dnd.user_data.obj).length && $($.vakata.dnd.user_data.obj).parents(".jstree:eq(0)")[0] !== e.target) { // node should not be from the same tree + var tr = $.jstree._reference(e.target), dc; + if(tr.data.dnd.foreign) { + dc = tr._get_settings().dnd.drag_check.call(this, { "o" : o, "r" : tr.get_container(), is_root : true }); + if(dc === true || dc.inside === true || dc.before === true || dc.after === true) { + $.vakata.dnd.helper.children("ins").attr("class","jstree-ok"); + } + } + else { + tr.prepare_move(o, tr.get_container(), "last"); + if(tr.check_move()) { + $.vakata.dnd.helper.children("ins").attr("class","jstree-ok"); + } + } + } + } + }, this)) + .bind("mouseup.jstree", $.proxy(function (e) { + //if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && $(e.currentTarget).find("> ul > li").length === 0) { + if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && e.currentTarget === e.target && $.vakata.dnd.user_data.obj && $($.vakata.dnd.user_data.obj).length && $($.vakata.dnd.user_data.obj).parents(".jstree:eq(0)")[0] !== e.target) { // node should not be from the same tree + var tr = $.jstree._reference(e.currentTarget), dc; + if(tr.data.dnd.foreign) { + dc = tr._get_settings().dnd.drag_check.call(this, { "o" : o, "r" : tr.get_container(), is_root : true }); + if(dc === true || dc.inside === true || dc.before === true || dc.after === true) { + tr._get_settings().dnd.drag_finish.call(this, { "o" : o, "r" : tr.get_container(), is_root : true }); + } + } + else { + tr.move_node(o, tr.get_container(), "last", e[tr._get_settings().dnd.copy_modifier + "Key"]); + } + } + }, this)) + .bind("mouseleave.jstree", $.proxy(function (e) { + if(e.relatedTarget && e.relatedTarget.id && e.relatedTarget.id === "jstree-marker-line") { + return false; + } + if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) { + if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); } + if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); } + if(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); } + if(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); } + if($.vakata.dnd.helper.children("ins").hasClass("jstree-ok")) { + $.vakata.dnd.helper.children("ins").attr("class","jstree-invalid"); + } + } + }, this)) + .bind("mousemove.jstree", $.proxy(function (e) { + if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) { + var cnt = this.get_container()[0]; + + // Horizontal scroll + if(e.pageX + 24 > this.data.dnd.cof.left + this.data.dnd.cw) { + if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); } + this.data.dnd.i1 = setInterval($.proxy(function () { this.scrollLeft += $.vakata.dnd.scroll_spd; }, cnt), 100); + } + else if(e.pageX - 24 < this.data.dnd.cof.left) { + if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); } + this.data.dnd.i1 = setInterval($.proxy(function () { this.scrollLeft -= $.vakata.dnd.scroll_spd; }, cnt), 100); + } + else { + if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); } + } + + // Vertical scroll + if(e.pageY + 24 > this.data.dnd.cof.top + this.data.dnd.ch) { + if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); } + this.data.dnd.i2 = setInterval($.proxy(function () { this.scrollTop += $.vakata.dnd.scroll_spd; }, cnt), 100); + } + else if(e.pageY - 24 < this.data.dnd.cof.top) { + if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); } + this.data.dnd.i2 = setInterval($.proxy(function () { this.scrollTop -= $.vakata.dnd.scroll_spd; }, cnt), 100); + } + else { + if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); } + } + + } + }, this)) + .bind("scroll.jstree", $.proxy(function (e) { + if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && m && ml) { + m.hide(); + ml.hide(); + } + }, this)) + .delegate("a", "mousedown.jstree", $.proxy(function (e) { + if(e.which === 1) { + this.start_drag(e.currentTarget, e); + return false; + } + }, this)) + .delegate("a", "mouseenter.jstree", $.proxy(function (e) { + if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) { + this.dnd_enter(e.currentTarget); + } + }, this)) + .delegate("a", "mousemove.jstree", $.proxy(function (e) { + if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) { + if(!r || !r.length || r.children("a")[0] !== e.currentTarget) { + this.dnd_enter(e.currentTarget); + } + if(typeof this.data.dnd.off.top === "undefined") { this.data.dnd.off = $(e.target).offset(); } + this.data.dnd.w = (e.pageY - (this.data.dnd.off.top || 0)) % this.data.core.li_height; + if(this.data.dnd.w < 0) { this.data.dnd.w += this.data.core.li_height; } + this.dnd_show(); + } + }, this)) + .delegate("a", "mouseleave.jstree", $.proxy(function (e) { + if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) { + if(e.relatedTarget && e.relatedTarget.id && e.relatedTarget.id === "jstree-marker-line") { + return false; + } + if(m) { m.hide(); } + if(ml) { ml.hide(); } + /* + var ec = $(e.currentTarget).closest("li"), + er = $(e.relatedTarget).closest("li"); + if(er[0] !== ec.prev()[0] && er[0] !== ec.next()[0]) { + if(m) { m.hide(); } + if(ml) { ml.hide(); } + } + */ + this.data.dnd.mto = setTimeout( + (function (t) { return function () { t.dnd_leave(e); }; })(this), + 0); + } + }, this)) + .delegate("a", "mouseup.jstree", $.proxy(function (e) { + if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree) { + this.dnd_finish(e); + } + }, this)); + + $(document) + .bind("drag_stop.vakata", $.proxy(function () { + if(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); } + if(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); } + if(this.data.dnd.i1) { clearInterval(this.data.dnd.i1); } + if(this.data.dnd.i2) { clearInterval(this.data.dnd.i2); } + this.data.dnd.after = false; + this.data.dnd.before = false; + this.data.dnd.inside = false; + this.data.dnd.off = false; + this.data.dnd.prepared = false; + this.data.dnd.w = false; + this.data.dnd.to1 = false; + this.data.dnd.to2 = false; + this.data.dnd.i1 = false; + this.data.dnd.i2 = false; + this.data.dnd.active = false; + this.data.dnd.foreign = false; + if(m) { m.css({ "top" : "-2000px" }); } + if(ml) { ml.css({ "top" : "-2000px" }); } + }, this)) + .bind("drag_start.vakata", $.proxy(function (e, data) { + if(data.data.jstree) { + var et = $(data.event.target); + if(et.closest(".jstree").hasClass("jstree-" + this.get_index())) { + this.dnd_enter(et); + } + } + }, this)); + /* + .bind("keydown.jstree-" + this.get_index() + " keyup.jstree-" + this.get_index(), $.proxy(function(e) { + if($.vakata.dnd.is_drag && $.vakata.dnd.user_data.jstree && !this.data.dnd.foreign) { + var h = $.vakata.dnd.helper.children("ins"); + if(e[this._get_settings().dnd.copy_modifier + "Key"] && h.hasClass("jstree-ok")) { + h.parent().html(h.parent().html().replace(/ \(Copy\)$/, "") + " (Copy)"); + } + else { + h.parent().html(h.parent().html().replace(/ \(Copy\)$/, "")); + } + } + }, this)); */ + + + + var s = this._get_settings().dnd; + if(s.drag_target) { + $(document) + .delegate(s.drag_target, "mousedown.jstree-" + this.get_index(), $.proxy(function (e) { + o = e.target; + $.vakata.dnd.drag_start(e, { jstree : true, obj : e.target }, "<ins class='jstree-icon'></ins>" + $(e.target).text() ); + if(this.data.themes) { + if(m) { m.attr("class", "jstree-" + this.data.themes.theme); } + if(ml) { ml.attr("class", "jstree-" + this.data.themes.theme); } + $.vakata.dnd.helper.attr("class", "jstree-dnd-helper jstree-" + this.data.themes.theme); + } + $.vakata.dnd.helper.children("ins").attr("class","jstree-invalid"); + var cnt = this.get_container(); + this.data.dnd.cof = cnt.offset(); + this.data.dnd.cw = parseInt(cnt.width(),10); + this.data.dnd.ch = parseInt(cnt.height(),10); + this.data.dnd.foreign = true; + e.preventDefault(); + }, this)); + } + if(s.drop_target) { + $(document) + .delegate(s.drop_target, "mouseenter.jstree-" + this.get_index(), $.proxy(function (e) { + if(this.data.dnd.active && this._get_settings().dnd.drop_check.call(this, { "o" : o, "r" : $(e.target), "e" : e })) { + $.vakata.dnd.helper.children("ins").attr("class","jstree-ok"); + } + }, this)) + .delegate(s.drop_target, "mouseleave.jstree-" + this.get_index(), $.proxy(function (e) { + if(this.data.dnd.active) { + $.vakata.dnd.helper.children("ins").attr("class","jstree-invalid"); + } + }, this)) + .delegate(s.drop_target, "mouseup.jstree-" + this.get_index(), $.proxy(function (e) { + if(this.data.dnd.active && $.vakata.dnd.helper.children("ins").hasClass("jstree-ok")) { + this._get_settings().dnd.drop_finish.call(this, { "o" : o, "r" : $(e.target), "e" : e }); + } + }, this)); + } + }, + defaults : { + copy_modifier : "ctrl", + check_timeout : 100, + open_timeout : 500, + drop_target : ".jstree-drop", + drop_check : function (data) { return true; }, + drop_finish : $.noop, + drag_target : ".jstree-draggable", + drag_finish : $.noop, + drag_check : function (data) { return { after : false, before : false, inside : true }; } + }, + _fn : { + dnd_prepare : function () { + if(!r || !r.length) { return; } + this.data.dnd.off = r.offset(); + if(this._get_settings().core.rtl) { + this.data.dnd.off.right = this.data.dnd.off.left + r.width(); + } + if(this.data.dnd.foreign) { + var a = this._get_settings().dnd.drag_check.call(this, { "o" : o, "r" : r }); + this.data.dnd.after = a.after; + this.data.dnd.before = a.before; + this.data.dnd.inside = a.inside; + this.data.dnd.prepared = true; + return this.dnd_show(); + } + this.prepare_move(o, r, "before"); + this.data.dnd.before = this.check_move(); + this.prepare_move(o, r, "after"); + this.data.dnd.after = this.check_move(); + if(this._is_loaded(r)) { + this.prepare_move(o, r, "inside"); + this.data.dnd.inside = this.check_move(); + } + else { + this.data.dnd.inside = false; + } + this.data.dnd.prepared = true; + return this.dnd_show(); + }, + dnd_show : function () { + if(!this.data.dnd.prepared) { return; } + var o = ["before","inside","after"], + r = false, + rtl = this._get_settings().core.rtl, + pos; + if(this.data.dnd.w < this.data.core.li_height/3) { o = ["before","inside","after"]; } + else if(this.data.dnd.w <= this.data.core.li_height*2/3) { + o = this.data.dnd.w < this.data.core.li_height/2 ? ["inside","before","after"] : ["inside","after","before"]; + } + else { o = ["after","inside","before"]; } + $.each(o, $.proxy(function (i, val) { + if(this.data.dnd[val]) { + $.vakata.dnd.helper.children("ins").attr("class","jstree-ok"); + r = val; + return false; + } + }, this)); + if(r === false) { $.vakata.dnd.helper.children("ins").attr("class","jstree-invalid"); } + + pos = rtl ? (this.data.dnd.off.right - 18) : (this.data.dnd.off.left + 10); + switch(r) { + case "before": + m.css({ "left" : pos + "px", "top" : (this.data.dnd.off.top - 6) + "px" }).show(); + if(ml) { ml.css({ "left" : (pos + 8) + "px", "top" : (this.data.dnd.off.top - 1) + "px" }).show(); } + break; + case "after": + m.css({ "left" : pos + "px", "top" : (this.data.dnd.off.top + this.data.core.li_height - 6) + "px" }).show(); + if(ml) { ml.css({ "left" : (pos + 8) + "px", "top" : (this.data.dnd.off.top + this.data.core.li_height - 1) + "px" }).show(); } + break; + case "inside": + m.css({ "left" : pos + ( rtl ? -4 : 4) + "px", "top" : (this.data.dnd.off.top + this.data.core.li_height/2 - 5) + "px" }).show(); + if(ml) { ml.hide(); } + break; + default: + m.hide(); + if(ml) { ml.hide(); } + break; + } + last_pos = r; + return r; + }, + dnd_open : function () { + this.data.dnd.to2 = false; + this.open_node(r, $.proxy(this.dnd_prepare,this), true); + }, + dnd_finish : function (e) { + if(this.data.dnd.foreign) { + if(this.data.dnd.after || this.data.dnd.before || this.data.dnd.inside) { + this._get_settings().dnd.drag_finish.call(this, { "o" : o, "r" : r, "p" : last_pos }); + } + } + else { + this.dnd_prepare(); + this.move_node(o, r, last_pos, e[this._get_settings().dnd.copy_modifier + "Key"]); + } + o = false; + r = false; + m.hide(); + if(ml) { ml.hide(); } + }, + dnd_enter : function (obj) { + if(this.data.dnd.mto) { + clearTimeout(this.data.dnd.mto); + this.data.dnd.mto = false; + } + var s = this._get_settings().dnd; + this.data.dnd.prepared = false; + r = this._get_node(obj); + if(s.check_timeout) { + // do the calculations after a minimal timeout (users tend to drag quickly to the desired location) + if(this.data.dnd.to1) { clearTimeout(this.data.dnd.to1); } + this.data.dnd.to1 = setTimeout($.proxy(this.dnd_prepare, this), s.check_timeout); + } + else { + this.dnd_prepare(); + } + if(s.open_timeout) { + if(this.data.dnd.to2) { clearTimeout(this.data.dnd.to2); } + if(r && r.length && r.hasClass("jstree-closed")) { + // if the node is closed - open it, then recalculate + this.data.dnd.to2 = setTimeout($.proxy(this.dnd_open, this), s.open_timeout); + } + } + else { + if(r && r.length && r.hasClass("jstree-closed")) { + this.dnd_open(); + } + } + }, + dnd_leave : function (e) { + this.data.dnd.after = false; + this.data.dnd.before = false; + this.data.dnd.inside = false; + $.vakata.dnd.helper.children("ins").attr("class","jstree-invalid"); + m.hide(); + if(ml) { ml.hide(); } + if(r && r[0] === e.target.parentNode) { + if(this.data.dnd.to1) { + clearTimeout(this.data.dnd.to1); + this.data.dnd.to1 = false; + } + if(this.data.dnd.to2) { + clearTimeout(this.data.dnd.to2); + this.data.dnd.to2 = false; + } + } + }, + start_drag : function (obj, e) { + o = this._get_node(obj); + if(this.data.ui && this.is_selected(o)) { o = this._get_node(null, true); } + var dt = o.length > 1 ? this._get_string("multiple_selection") : this.get_text(o), + cnt = this.get_container(); + if(!this._get_settings().core.html_titles) { dt = dt.replace(/</ig,"&lt;").replace(/>/ig,"&gt;"); } + $.vakata.dnd.drag_start(e, { jstree : true, obj : o }, "<ins class='jstree-icon'></ins>" + dt ); + if(this.data.themes) { + if(m) { m.attr("class", "jstree-" + this.data.themes.theme); } + if(ml) { ml.attr("class", "jstree-" + this.data.themes.theme); } + $.vakata.dnd.helper.attr("class", "jstree-dnd-helper jstree-" + this.data.themes.theme); + } + this.data.dnd.cof = cnt.offset(); + this.data.dnd.cw = parseInt(cnt.width(),10); + this.data.dnd.ch = parseInt(cnt.height(),10); + this.data.dnd.active = true; + } + } + }); + $(function() { + var css_string = '' + + '#vakata-dragged ins { display:block; text-decoration:none; width:16px; height:16px; margin:0 0 0 0; padding:0; position:absolute; top:4px; left:4px; ' + + ' -moz-border-radius:4px; border-radius:4px; -webkit-border-radius:4px; ' + + '} ' + + '#vakata-dragged .jstree-ok { background:green; } ' + + '#vakata-dragged .jstree-invalid { background:red; } ' + + '#jstree-marker { padding:0; margin:0; font-size:12px; overflow:hidden; height:12px; width:8px; position:absolute; top:-30px; z-index:10001; background-repeat:no-repeat; display:none; background-color:transparent; text-shadow:1px 1px 1px white; color:black; line-height:10px; } ' + + '#jstree-marker-line { padding:0; margin:0; line-height:0%; font-size:1px; overflow:hidden; height:1px; width:100px; position:absolute; top:-30px; z-index:10000; background-repeat:no-repeat; display:none; background-color:#456c43; ' + + ' cursor:pointer; border:1px solid #eeeeee; border-left:0; -moz-box-shadow: 0px 0px 2px #666; -webkit-box-shadow: 0px 0px 2px #666; box-shadow: 0px 0px 2px #666; ' + + ' -moz-border-radius:1px; border-radius:1px; -webkit-border-radius:1px; ' + + '}' + + ''; + $.vakata.css.add_sheet({ str : css_string, title : "jstree" }); + m = $("<div />").attr({ id : "jstree-marker" }).hide().html("&raquo;") + .bind("mouseleave mouseenter", function (e) { + m.hide(); + ml.hide(); + e.preventDefault(); + e.stopImmediatePropagation(); + return false; + }) + .appendTo("body"); + ml = $("<div />").attr({ id : "jstree-marker-line" }).hide() + .bind("mouseup", function (e) { + if(r && r.length) { + r.children("a").trigger(e); + e.preventDefault(); + e.stopImmediatePropagation(); + return false; + } + }) + .bind("mouseleave", function (e) { + var rt = $(e.relatedTarget); + if(rt.is(".jstree") || rt.closest(".jstree").length === 0) { + if(r && r.length) { + r.children("a").trigger(e); + m.hide(); + ml.hide(); + e.preventDefault(); + e.stopImmediatePropagation(); + return false; + } + } + }) + .appendTo("body"); + $(document).bind("drag_start.vakata", function (e, data) { + if(data.data.jstree) { m.show(); if(ml) { ml.show(); } } + }); + $(document).bind("drag_stop.vakata", function (e, data) { + if(data.data.jstree) { m.hide(); if(ml) { ml.hide(); } } + }); + }); +})(jQuery); +//*/ + +/* + * jsTree checkbox plugin + * Inserts checkboxes in front of every node + * Depends on the ui plugin + * DOES NOT WORK NICELY WITH MULTITREE DRAG'N'DROP + */ +(function ($) { + $.jstree.plugin("checkbox", { + __init : function () { + this.data.checkbox.noui = this._get_settings().checkbox.override_ui; + if(this.data.ui && this.data.checkbox.noui) { + this.select_node = this.deselect_node = this.deselect_all = $.noop; + this.get_selected = this.get_checked; + } + + this.get_container() + .bind("open_node.jstree create_node.jstree clean_node.jstree refresh.jstree", $.proxy(function (e, data) { + this._prepare_checkboxes(data.rslt.obj); + }, this)) + .bind("loaded.jstree", $.proxy(function (e) { + this._prepare_checkboxes(); + }, this)) + .delegate( (this.data.ui && this.data.checkbox.noui ? "a" : "ins.jstree-checkbox") , "click.jstree", $.proxy(function (e) { + e.preventDefault(); + if(this._get_node(e.target).hasClass("jstree-checked")) { this.uncheck_node(e.target); } + else { this.check_node(e.target); } + if(this.data.ui && this.data.checkbox.noui) { + this.save_selected(); + if(this.data.cookies) { this.save_cookie("select_node"); } + } + else { + e.stopImmediatePropagation(); + return false; + } + }, this)); + }, + defaults : { + override_ui : false, + two_state : false, + real_checkboxes : false, + checked_parent_open : true, + real_checkboxes_names : function (n) { return [ ("check_" + (n[0].id || Math.ceil(Math.random() * 10000))) , 1]; } + }, + __destroy : function () { + this.get_container() + .find("input.jstree-real-checkbox").removeClass("jstree-real-checkbox").end() + .find("ins.jstree-checkbox").remove(); + }, + _fn : { + _checkbox_notify : function (n, data) { + if(data.checked) { + this.check_node(n, false); + } + }, + _prepare_checkboxes : function (obj) { + obj = !obj || obj == -1 ? this.get_container().find("> ul > li") : this._get_node(obj); + if(obj === false) { return; } // added for removing root nodes + var c, _this = this, t, ts = this._get_settings().checkbox.two_state, rc = this._get_settings().checkbox.real_checkboxes, rcn = this._get_settings().checkbox.real_checkboxes_names; + obj.each(function () { + t = $(this); + c = t.is("li") && (t.hasClass("jstree-checked") || (rc && t.children(":checked").length)) ? "jstree-checked" : "jstree-unchecked"; + t.find("li").andSelf().each(function () { + var $t = $(this), nm; + $t.children("a" + (_this.data.languages ? "" : ":eq(0)") ).not(":has(.jstree-checkbox)").prepend("<ins class='jstree-checkbox'>&#160;</ins>").parent().not(".jstree-checked, .jstree-unchecked").addClass( ts ? "jstree-unchecked" : c ); + if(rc) { + if(!$t.children(":checkbox").length) { + nm = rcn.call(_this, $t); + $t.prepend("<input type='checkbox' class='jstree-real-checkbox' id='" + nm[0] + "' name='" + nm[0] + "' value='" + nm[1] + "' />"); + } + else { + $t.children(":checkbox").addClass("jstree-real-checkbox"); + } + } + if(!ts) { + if(c === "jstree-checked" || $t.hasClass("jstree-checked") || $t.children(':checked').length) { + $t.find("li").andSelf().addClass("jstree-checked").children(":checkbox").prop("checked", true); + } + } + else { + if($t.hasClass("jstree-checked") || $t.children(':checked').length) { + $t.addClass("jstree-checked").children(":checkbox").prop("checked", true); + } + } + }); + }); + if(!ts) { + obj.find(".jstree-checked").parent().parent().each(function () { _this._repair_state(this); }); + } + }, + change_state : function (obj, state) { + obj = this._get_node(obj); + var coll = false, rc = this._get_settings().checkbox.real_checkboxes; + if(!obj || obj === -1) { return false; } + state = (state === false || state === true) ? state : obj.hasClass("jstree-checked"); + if(this._get_settings().checkbox.two_state) { + if(state) { + obj.removeClass("jstree-checked").addClass("jstree-unchecked"); + if(rc) { obj.children(":checkbox").prop("checked", false); } + } + else { + obj.removeClass("jstree-unchecked").addClass("jstree-checked"); + if(rc) { obj.children(":checkbox").prop("checked", true); } + } + } + else { + if(state) { + coll = obj.find("li").andSelf(); + if(!coll.filter(".jstree-checked, .jstree-undetermined").length) { return false; } + coll.removeClass("jstree-checked jstree-undetermined").addClass("jstree-unchecked"); + if(rc) { coll.children(":checkbox").prop("checked", false); } + } + else { + coll = obj.find("li").andSelf(); + if(!coll.filter(".jstree-unchecked, .jstree-undetermined").length) { return false; } + coll.removeClass("jstree-unchecked jstree-undetermined").addClass("jstree-checked"); + if(rc) { coll.children(":checkbox").prop("checked", true); } + if(this.data.ui) { this.data.ui.last_selected = obj; } + this.data.checkbox.last_selected = obj; + } + obj.parentsUntil(".jstree", "li").each(function () { + var $this = $(this); + if(state) { + if($this.children("ul").children("li.jstree-checked, li.jstree-undetermined").length) { + $this.parentsUntil(".jstree", "li").andSelf().removeClass("jstree-checked jstree-unchecked").addClass("jstree-undetermined"); + if(rc) { $this.parentsUntil(".jstree", "li").andSelf().children(":checkbox").prop("checked", false); } + return false; + } + else { + $this.removeClass("jstree-checked jstree-undetermined").addClass("jstree-unchecked"); + if(rc) { $this.children(":checkbox").prop("checked", false); } + } + } + else { + if($this.children("ul").children("li.jstree-unchecked, li.jstree-undetermined").length) { + $this.parentsUntil(".jstree", "li").andSelf().removeClass("jstree-checked jstree-unchecked").addClass("jstree-undetermined"); + if(rc) { $this.parentsUntil(".jstree", "li").andSelf().children(":checkbox").prop("checked", false); } + return false; + } + else { + $this.removeClass("jstree-unchecked jstree-undetermined").addClass("jstree-checked"); + if(rc) { $this.children(":checkbox").prop("checked", true); } + } + } + }); + } + if(this.data.ui && this.data.checkbox.noui) { this.data.ui.selected = this.get_checked(); } + this.__callback(obj); + return true; + }, + check_node : function (obj) { + if(this.change_state(obj, false)) { + obj = this._get_node(obj); + if(this._get_settings().checkbox.checked_parent_open) { + var t = this; + obj.parents(".jstree-closed").each(function () { t.open_node(this, false, true); }); + } + this.__callback({ "obj" : obj }); + } + }, + uncheck_node : function (obj) { + if(this.change_state(obj, true)) { this.__callback({ "obj" : this._get_node(obj) }); } + }, + check_all : function () { + var _this = this, + coll = this._get_settings().checkbox.two_state ? this.get_container_ul().find("li") : this.get_container_ul().children("li"); + coll.each(function () { + _this.change_state(this, false); + }); + this.__callback(); + }, + uncheck_all : function () { + var _this = this, + coll = this._get_settings().checkbox.two_state ? this.get_container_ul().find("li") : this.get_container_ul().children("li"); + coll.each(function () { + _this.change_state(this, true); + }); + this.__callback(); + }, + + is_checked : function(obj) { + obj = this._get_node(obj); + return obj.length ? obj.is(".jstree-checked") : false; + }, + get_checked : function (obj, get_all) { + obj = !obj || obj === -1 ? this.get_container() : this._get_node(obj); + return get_all || this._get_settings().checkbox.two_state ? obj.find(".jstree-checked") : obj.find("> ul > .jstree-checked, .jstree-undetermined > ul > .jstree-checked"); + }, + get_unchecked : function (obj, get_all) { + obj = !obj || obj === -1 ? this.get_container() : this._get_node(obj); + return get_all || this._get_settings().checkbox.two_state ? obj.find(".jstree-unchecked") : obj.find("> ul > .jstree-unchecked, .jstree-undetermined > ul > .jstree-unchecked"); + }, + + show_checkboxes : function () { this.get_container().children("ul").removeClass("jstree-no-checkboxes"); }, + hide_checkboxes : function () { this.get_container().children("ul").addClass("jstree-no-checkboxes"); }, + + _repair_state : function (obj) { + obj = this._get_node(obj); + if(!obj.length) { return; } + if(this._get_settings().checkbox.two_state) { + obj.find('li').andSelf().not('.jstree-checked').removeClass('jstree-undetermined').addClass('jstree-unchecked').children(':checkbox').prop('checked', true); + return; + } + var rc = this._get_settings().checkbox.real_checkboxes, + a = obj.find("> ul > .jstree-checked").length, + b = obj.find("> ul > .jstree-undetermined").length, + c = obj.find("> ul > li").length; + if(c === 0) { if(obj.hasClass("jstree-undetermined")) { this.change_state(obj, false); } } + else if(a === 0 && b === 0) { this.change_state(obj, true); } + else if(a === c) { this.change_state(obj, false); } + else { + obj.parentsUntil(".jstree","li").andSelf().removeClass("jstree-checked jstree-unchecked").addClass("jstree-undetermined"); + if(rc) { obj.parentsUntil(".jstree", "li").andSelf().children(":checkbox").prop("checked", false); } + } + }, + reselect : function () { + if(this.data.ui && this.data.checkbox.noui) { + var _this = this, + s = this.data.ui.to_select; + s = $.map($.makeArray(s), function (n) { return "#" + n.toString().replace(/^#/,"").replace(/\\\//g,"/").replace(/\//g,"\\\/").replace(/\\\./g,".").replace(/\./g,"\\.").replace(/\:/g,"\\:"); }); + this.deselect_all(); + $.each(s, function (i, val) { _this.check_node(val); }); + this.__callback(); + } + else { + this.__call_old(); + } + }, + save_loaded : function () { + var _this = this; + this.data.core.to_load = []; + this.get_container_ul().find("li.jstree-closed.jstree-undetermined").each(function () { + if(this.id) { _this.data.core.to_load.push("#" + this.id); } + }); + } + } + }); + $(function() { + var css_string = '.jstree .jstree-real-checkbox { display:none; } '; + $.vakata.css.add_sheet({ str : css_string, title : "jstree" }); + }); +})(jQuery); +//*/ + +/* + * jsTree XML plugin + * The XML data store. Datastores are build by overriding the `load_node` and `_is_loaded` functions. + */ +(function ($) { + $.vakata.xslt = function (xml, xsl, callback) { + var r = false, p, q, s; + // IE9 + if(r === false && window.ActiveXObject) { + try { + r = new ActiveXObject("Msxml2.XSLTemplate"); + q = new ActiveXObject("Msxml2.DOMDocument"); + q.loadXML(xml); + s = new ActiveXObject("Msxml2.FreeThreadedDOMDocument"); + s.loadXML(xsl); + r.stylesheet = s; + p = r.createProcessor(); + p.input = q; + p.transform(); + r = p.output; + } + catch (e) { } + } + xml = $.parseXML(xml); + xsl = $.parseXML(xsl); + // FF, Chrome + if(r === false && typeof (XSLTProcessor) !== "undefined") { + p = new XSLTProcessor(); + p.importStylesheet(xsl); + r = p.transformToFragment(xml, document); + r = $('<div />').append(r).html(); + } + // OLD IE + if(r === false && typeof (xml.transformNode) !== "undefined") { + r = xml.transformNode(xsl); + } + callback.call(null, r); + }; + var xsl = { + 'nest' : '<' + '?xml version="1.0" encoding="utf-8" ?>' + + '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >' + + '<xsl:output method="html" encoding="utf-8" omit-xml-declaration="yes" standalone="no" indent="no" media-type="text/html" />' + + '<xsl:template match="/">' + + ' <xsl:call-template name="nodes">' + + ' <xsl:with-param name="node" select="/root" />' + + ' </xsl:call-template>' + + '</xsl:template>' + + '<xsl:template name="nodes">' + + ' <xsl:param name="node" />' + + ' <ul>' + + ' <xsl:for-each select="$node/item">' + + ' <xsl:variable name="children" select="count(./item) &gt; 0" />' + + ' <li>' + + ' <xsl:attribute name="class">' + + ' <xsl:if test="position() = last()">jstree-last </xsl:if>' + + ' <xsl:choose>' + + ' <xsl:when test="@state = \'open\'">jstree-open </xsl:when>' + + ' <xsl:when test="$children or @hasChildren or @state = \'closed\'">jstree-closed </xsl:when>' + + ' <xsl:otherwise>jstree-leaf </xsl:otherwise>' + + ' </xsl:choose>' + + ' <xsl:value-of select="@class" />' + + ' </xsl:attribute>' + + ' <xsl:for-each select="@*">' + + ' <xsl:if test="name() != \'class\' and name() != \'state\' and name() != \'hasChildren\'">' + + ' <xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + + ' </xsl:if>' + + ' </xsl:for-each>' + + ' <ins class="jstree-icon"><xsl:text>&#xa0;</xsl:text></ins>' + + ' <xsl:for-each select="content/name">' + + ' <a>' + + ' <xsl:attribute name="href">' + + ' <xsl:choose>' + + ' <xsl:when test="@href"><xsl:value-of select="@href" /></xsl:when>' + + ' <xsl:otherwise>#</xsl:otherwise>' + + ' </xsl:choose>' + + ' </xsl:attribute>' + + ' <xsl:attribute name="class"><xsl:value-of select="@lang" /> <xsl:value-of select="@class" /></xsl:attribute>' + + ' <xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute>' + + ' <xsl:for-each select="@*">' + + ' <xsl:if test="name() != \'style\' and name() != \'class\' and name() != \'href\'">' + + ' <xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + + ' </xsl:if>' + + ' </xsl:for-each>' + + ' <ins>' + + ' <xsl:attribute name="class">jstree-icon ' + + ' <xsl:if test="string-length(attribute::icon) > 0 and not(contains(@icon,\'/\'))"><xsl:value-of select="@icon" /></xsl:if>' + + ' </xsl:attribute>' + + ' <xsl:if test="string-length(attribute::icon) > 0 and contains(@icon,\'/\')"><xsl:attribute name="style">background:url(<xsl:value-of select="@icon" />) center center no-repeat;</xsl:attribute></xsl:if>' + + ' <xsl:text>&#xa0;</xsl:text>' + + ' </ins>' + + ' <xsl:copy-of select="./child::node()" />' + + ' </a>' + + ' </xsl:for-each>' + + ' <xsl:if test="$children or @hasChildren"><xsl:call-template name="nodes"><xsl:with-param name="node" select="current()" /></xsl:call-template></xsl:if>' + + ' </li>' + + ' </xsl:for-each>' + + ' </ul>' + + '</xsl:template>' + + '</xsl:stylesheet>', + + 'flat' : '<' + '?xml version="1.0" encoding="utf-8" ?>' + + '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >' + + '<xsl:output method="html" encoding="utf-8" omit-xml-declaration="yes" standalone="no" indent="no" media-type="text/xml" />' + + '<xsl:template match="/">' + + ' <ul>' + + ' <xsl:for-each select="//item[not(@parent_id) or @parent_id=0 or not(@parent_id = //item/@id)]">' + /* the last `or` may be removed */ + ' <xsl:call-template name="nodes">' + + ' <xsl:with-param name="node" select="." />' + + ' <xsl:with-param name="is_last" select="number(position() = last())" />' + + ' </xsl:call-template>' + + ' </xsl:for-each>' + + ' </ul>' + + '</xsl:template>' + + '<xsl:template name="nodes">' + + ' <xsl:param name="node" />' + + ' <xsl:param name="is_last" />' + + ' <xsl:variable name="children" select="count(//item[@parent_id=$node/attribute::id]) &gt; 0" />' + + ' <li>' + + ' <xsl:attribute name="class">' + + ' <xsl:if test="$is_last = true()">jstree-last </xsl:if>' + + ' <xsl:choose>' + + ' <xsl:when test="@state = \'open\'">jstree-open </xsl:when>' + + ' <xsl:when test="$children or @hasChildren or @state = \'closed\'">jstree-closed </xsl:when>' + + ' <xsl:otherwise>jstree-leaf </xsl:otherwise>' + + ' </xsl:choose>' + + ' <xsl:value-of select="@class" />' + + ' </xsl:attribute>' + + ' <xsl:for-each select="@*">' + + ' <xsl:if test="name() != \'parent_id\' and name() != \'hasChildren\' and name() != \'class\' and name() != \'state\'">' + + ' <xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + + ' </xsl:if>' + + ' </xsl:for-each>' + + ' <ins class="jstree-icon"><xsl:text>&#xa0;</xsl:text></ins>' + + ' <xsl:for-each select="content/name">' + + ' <a>' + + ' <xsl:attribute name="href">' + + ' <xsl:choose>' + + ' <xsl:when test="@href"><xsl:value-of select="@href" /></xsl:when>' + + ' <xsl:otherwise>#</xsl:otherwise>' + + ' </xsl:choose>' + + ' </xsl:attribute>' + + ' <xsl:attribute name="class"><xsl:value-of select="@lang" /> <xsl:value-of select="@class" /></xsl:attribute>' + + ' <xsl:attribute name="style"><xsl:value-of select="@style" /></xsl:attribute>' + + ' <xsl:for-each select="@*">' + + ' <xsl:if test="name() != \'style\' and name() != \'class\' and name() != \'href\'">' + + ' <xsl:attribute name="{name()}"><xsl:value-of select="." /></xsl:attribute>' + + ' </xsl:if>' + + ' </xsl:for-each>' + + ' <ins>' + + ' <xsl:attribute name="class">jstree-icon ' + + ' <xsl:if test="string-length(attribute::icon) > 0 and not(contains(@icon,\'/\'))"><xsl:value-of select="@icon" /></xsl:if>' + + ' </xsl:attribute>' + + ' <xsl:if test="string-length(attribute::icon) > 0 and contains(@icon,\'/\')"><xsl:attribute name="style">background:url(<xsl:value-of select="@icon" />) center center no-repeat;</xsl:attribute></xsl:if>' + + ' <xsl:text>&#xa0;</xsl:text>' + + ' </ins>' + + ' <xsl:copy-of select="./child::node()" />' + + ' </a>' + + ' </xsl:for-each>' + + ' <xsl:if test="$children">' + + ' <ul>' + + ' <xsl:for-each select="//item[@parent_id=$node/attribute::id]">' + + ' <xsl:call-template name="nodes">' + + ' <xsl:with-param name="node" select="." />' + + ' <xsl:with-param name="is_last" select="number(position() = last())" />' + + ' </xsl:call-template>' + + ' </xsl:for-each>' + + ' </ul>' + + ' </xsl:if>' + + ' </li>' + + '</xsl:template>' + + '</xsl:stylesheet>' + }, + escape_xml = function(string) { + return string + .toString() + .replace(/&/g, '&amp;') + .replace(/</g, '&lt;') + .replace(/>/g, '&gt;') + .replace(/"/g, '&quot;') + .replace(/'/g, '&apos;'); + }; + $.jstree.plugin("xml_data", { + defaults : { + data : false, + ajax : false, + xsl : "flat", + clean_node : false, + correct_state : true, + get_skip_empty : false, + get_include_preamble : true + }, + _fn : { + load_node : function (obj, s_call, e_call) { var _this = this; this.load_node_xml(obj, function () { _this.__callback({ "obj" : _this._get_node(obj) }); s_call.call(this); }, e_call); }, + _is_loaded : function (obj) { + var s = this._get_settings().xml_data; + obj = this._get_node(obj); + return obj == -1 || !obj || (!s.ajax && !$.isFunction(s.data)) || obj.is(".jstree-open, .jstree-leaf") || obj.children("ul").children("li").size() > 0; + }, + load_node_xml : function (obj, s_call, e_call) { + var s = this.get_settings().xml_data, + error_func = function () {}, + success_func = function () {}; + + obj = this._get_node(obj); + if(obj && obj !== -1) { + if(obj.data("jstree_is_loading")) { return; } + else { obj.data("jstree_is_loading",true); } + } + switch(!0) { + case (!s.data && !s.ajax): throw "Neither data nor ajax settings supplied."; + case ($.isFunction(s.data)): + s.data.call(this, obj, $.proxy(function (d) { + this.parse_xml(d, $.proxy(function (d) { + if(d) { + d = d.replace(/ ?xmlns="[^"]*"/ig, ""); + if(d.length > 10) { + d = $(d); + if(obj === -1 || !obj) { this.get_container().children("ul").empty().append(d.children()); } + else { obj.children("a.jstree-loading").removeClass("jstree-loading"); obj.append(d); obj.removeData("jstree_is_loading"); } + if(s.clean_node) { this.clean_node(obj); } + if(s_call) { s_call.call(this); } + } + else { + if(obj && obj !== -1) { + obj.children("a.jstree-loading").removeClass("jstree-loading"); + obj.removeData("jstree_is_loading"); + if(s.correct_state) { + this.correct_state(obj); + if(s_call) { s_call.call(this); } + } + } + else { + if(s.correct_state) { + this.get_container().children("ul").empty(); + if(s_call) { s_call.call(this); } + } + } + } + } + }, this)); + }, this)); + break; + case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)): + if(!obj || obj == -1) { + this.parse_xml(s.data, $.proxy(function (d) { + if(d) { + d = d.replace(/ ?xmlns="[^"]*"/ig, ""); + if(d.length > 10) { + d = $(d); + this.get_container().children("ul").empty().append(d.children()); + if(s.clean_node) { this.clean_node(obj); } + if(s_call) { s_call.call(this); } + } + } + else { + if(s.correct_state) { + this.get_container().children("ul").empty(); + if(s_call) { s_call.call(this); } + } + } + }, this)); + } + break; + case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1): + error_func = function (x, t, e) { + var ef = this.get_settings().xml_data.ajax.error; + if(ef) { ef.call(this, x, t, e); } + if(obj !== -1 && obj.length) { + obj.children("a.jstree-loading").removeClass("jstree-loading"); + obj.removeData("jstree_is_loading"); + if(t === "success" && s.correct_state) { this.correct_state(obj); } + } + else { + if(t === "success" && s.correct_state) { this.get_container().children("ul").empty(); } + } + if(e_call) { e_call.call(this); } + }; + success_func = function (d, t, x) { + d = x.responseText; + var sf = this.get_settings().xml_data.ajax.success; + if(sf) { d = sf.call(this,d,t,x) || d; } + if(d === "" || (d && d.toString && d.toString().replace(/^[\s\n]+$/,"") === "")) { + return error_func.call(this, x, t, ""); + } + this.parse_xml(d, $.proxy(function (d) { + if(d) { + d = d.replace(/ ?xmlns="[^"]*"/ig, ""); + if(d.length > 10) { + d = $(d); + if(obj === -1 || !obj) { this.get_container().children("ul").empty().append(d.children()); } + else { obj.children("a.jstree-loading").removeClass("jstree-loading"); obj.append(d); obj.removeData("jstree_is_loading"); } + if(s.clean_node) { this.clean_node(obj); } + if(s_call) { s_call.call(this); } + } + else { + if(obj && obj !== -1) { + obj.children("a.jstree-loading").removeClass("jstree-loading"); + obj.removeData("jstree_is_loading"); + if(s.correct_state) { + this.correct_state(obj); + if(s_call) { s_call.call(this); } + } + } + else { + if(s.correct_state) { + this.get_container().children("ul").empty(); + if(s_call) { s_call.call(this); } + } + } + } + } + }, this)); + }; + s.ajax.context = this; + s.ajax.error = error_func; + s.ajax.success = success_func; + if(!s.ajax.dataType) { s.ajax.dataType = "xml"; } + if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); } + if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); } + $.ajax(s.ajax); + break; + } + }, + parse_xml : function (xml, callback) { + var s = this._get_settings().xml_data; + $.vakata.xslt(xml, xsl[s.xsl], callback); + }, + get_xml : function (tp, obj, li_attr, a_attr, is_callback) { + var result = "", + s = this._get_settings(), + _this = this, + tmp1, tmp2, li, a, lang; + if(!tp) { tp = "flat"; } + if(!is_callback) { is_callback = 0; } + obj = this._get_node(obj); + if(!obj || obj === -1) { obj = this.get_container().find("> ul > li"); } + li_attr = $.isArray(li_attr) ? li_attr : [ "id", "class" ]; + if(!is_callback && this.data.types && $.inArray(s.types.type_attr, li_attr) === -1) { li_attr.push(s.types.type_attr); } + + a_attr = $.isArray(a_attr) ? a_attr : [ ]; + + if(!is_callback) { + if(s.xml_data.get_include_preamble) { + result += '<' + '?xml version="1.0" encoding="UTF-8"?' + '>'; + } + result += "<root>"; + } + obj.each(function () { + result += "<item"; + li = $(this); + $.each(li_attr, function (i, v) { + var t = li.attr(v); + if(!s.xml_data.get_skip_empty || typeof t !== "undefined") { + result += " " + v + "=\"" + escape_xml((" " + (t || "")).replace(/ jstree[^ ]*/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,"")) + "\""; + } + }); + if(li.hasClass("jstree-open")) { result += " state=\"open\""; } + if(li.hasClass("jstree-closed")) { result += " state=\"closed\""; } + if(tp === "flat") { result += " parent_id=\"" + escape_xml(is_callback) + "\""; } + result += ">"; + result += "<content>"; + a = li.children("a"); + a.each(function () { + tmp1 = $(this); + lang = false; + result += "<name"; + if($.inArray("languages", s.plugins) !== -1) { + $.each(s.languages, function (k, z) { + if(tmp1.hasClass(z)) { result += " lang=\"" + escape_xml(z) + "\""; lang = z; return false; } + }); + } + if(a_attr.length) { + $.each(a_attr, function (k, z) { + var t = tmp1.attr(z); + if(!s.xml_data.get_skip_empty || typeof t !== "undefined") { + result += " " + z + "=\"" + escape_xml((" " + t || "").replace(/ jstree[^ ]*/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,"")) + "\""; + } + }); + } + if(tmp1.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/^\s+$/ig,"").length) { + result += ' icon="' + escape_xml(tmp1.children("ins").get(0).className.replace(/jstree[^ ]*|$/ig,'').replace(/\s+$/ig," ").replace(/^ /,"").replace(/ $/,"")) + '"'; + } + if(tmp1.children("ins").get(0).style.backgroundImage.length) { + result += ' icon="' + escape_xml(tmp1.children("ins").get(0).style.backgroundImage.replace("url(","").replace(")","").replace(/'/ig,"").replace(/"/ig,"")) + '"'; + } + result += ">"; + result += "<![CDATA[" + _this.get_text(tmp1, lang) + "]]>"; + result += "</name>"; + }); + result += "</content>"; + tmp2 = li[0].id || true; + li = li.find("> ul > li"); + if(li.length) { tmp2 = _this.get_xml(tp, li, li_attr, a_attr, tmp2); } + else { tmp2 = ""; } + if(tp == "nest") { result += tmp2; } + result += "</item>"; + if(tp == "flat") { result += tmp2; } + }); + if(!is_callback) { result += "</root>"; } + return result; + } + } + }); +})(jQuery); +//*/ + +/* + * jsTree search plugin + * Enables both sync and async search on the tree + * DOES NOT WORK WITH JSON PROGRESSIVE RENDER + */ +(function ($) { + if($().jquery.split('.')[1] >= 8) { + $.expr[':'].jstree_contains = $.expr.createPseudo(function(search) { + return function(a) { + return (a.textContent || a.innerText || "").toLowerCase().indexOf(search.toLowerCase())>=0; + }; + }); + $.expr[':'].jstree_title_contains = $.expr.createPseudo(function(search) { + return function(a) { + return (a.getAttribute("title") || "").toLowerCase().indexOf(search.toLowerCase())>=0; + }; + }); + } + else { + $.expr[':'].jstree_contains = function(a,i,m){ + return (a.textContent || a.innerText || "").toLowerCase().indexOf(m[3].toLowerCase())>=0; + }; + $.expr[':'].jstree_title_contains = function(a,i,m) { + return (a.getAttribute("title") || "").toLowerCase().indexOf(m[3].toLowerCase())>=0; + }; + } + $.jstree.plugin("search", { + __init : function () { + this.data.search.str = ""; + this.data.search.result = $(); + if(this._get_settings().search.show_only_matches) { + this.get_container() + .bind("search.jstree", function (e, data) { + $(this).children("ul").find("li").hide().removeClass("jstree-last"); + data.rslt.nodes.parentsUntil(".jstree").andSelf().show() + .filter("ul").each(function () { $(this).children("li:visible").eq(-1).addClass("jstree-last"); }); + }) + .bind("clear_search.jstree", function () { + $(this).children("ul").find("li").css("display","").end().end().jstree("clean_node", -1); + }); + } + }, + defaults : { + ajax : false, + search_method : "jstree_contains", // for case insensitive - jstree_contains + show_only_matches : false + }, + _fn : { + search : function (str, skip_async) { + if($.trim(str) === "") { this.clear_search(); return; } + var s = this.get_settings().search, + t = this, + error_func = function () { }, + success_func = function () { }; + this.data.search.str = str; + + if(!skip_async && s.ajax !== false && this.get_container_ul().find("li.jstree-closed:not(:has(ul)):eq(0)").length > 0) { + this.search.supress_callback = true; + error_func = function () { }; + success_func = function (d, t, x) { + var sf = this.get_settings().search.ajax.success; + if(sf) { d = sf.call(this,d,t,x) || d; } + this.data.search.to_open = d; + this._search_open(); + }; + s.ajax.context = this; + s.ajax.error = error_func; + s.ajax.success = success_func; + if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, str); } + if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, str); } + if(!s.ajax.data) { s.ajax.data = { "search_string" : str }; } + if(!s.ajax.dataType || /^json/.exec(s.ajax.dataType)) { s.ajax.dataType = "json"; } + $.ajax(s.ajax); + return; + } + if(this.data.search.result.length) { this.clear_search(); } + this.data.search.result = this.get_container().find("a" + (this.data.languages ? "." + this.get_lang() : "" ) + ":" + (s.search_method) + "(" + this.data.search.str + ")"); + this.data.search.result.addClass("jstree-search").parent().parents(".jstree-closed").each(function () { + t.open_node(this, false, true); + }); + this.__callback({ nodes : this.data.search.result, str : str }); + }, + clear_search : function (str) { + this.data.search.result.removeClass("jstree-search"); + this.__callback(this.data.search.result); + this.data.search.result = $(); + }, + _search_open : function (is_callback) { + var _this = this, + done = true, + current = [], + remaining = []; + if(this.data.search.to_open.length) { + $.each(this.data.search.to_open, function (i, val) { + if(val == "#") { return true; } + if($(val).length && $(val).is(".jstree-closed")) { current.push(val); } + else { remaining.push(val); } + }); + if(current.length) { + this.data.search.to_open = remaining; + $.each(current, function (i, val) { + _this.open_node(val, function () { _this._search_open(true); }); + }); + done = false; + } + } + if(done) { this.search(this.data.search.str, true); } + } + } + }); +})(jQuery); +//*/ + +/* + * jsTree contextmenu plugin + */ +(function ($) { + $.vakata.context = { + hide_on_mouseleave : false, + + cnt : $("<div id='vakata-contextmenu' />"), + vis : false, + tgt : false, + par : false, + func : false, + data : false, + rtl : false, + show : function (s, t, x, y, d, p, rtl) { + $.vakata.context.rtl = !!rtl; + var html = $.vakata.context.parse(s), h, w; + if(!html) { return; } + $.vakata.context.vis = true; + $.vakata.context.tgt = t; + $.vakata.context.par = p || t || null; + $.vakata.context.data = d || null; + $.vakata.context.cnt + .html(html) + .css({ "visibility" : "hidden", "display" : "block", "left" : 0, "top" : 0 }); + + if($.vakata.context.hide_on_mouseleave) { + $.vakata.context.cnt + .one("mouseleave", function(e) { $.vakata.context.hide(); }); + } + + h = $.vakata.context.cnt.height(); + w = $.vakata.context.cnt.width(); + if(x + w > $(document).width()) { + x = $(document).width() - (w + 5); + $.vakata.context.cnt.find("li > ul").addClass("right"); + } + if(y + h > $(document).height()) { + y = y - (h + t[0].offsetHeight); + $.vakata.context.cnt.find("li > ul").addClass("bottom"); + } + + $.vakata.context.cnt + .css({ "left" : x, "top" : y }) + .find("li:has(ul)") + .bind("mouseenter", function (e) { + var w = $(document).width(), + h = $(document).height(), + ul = $(this).children("ul").show(); + if(w !== $(document).width()) { ul.toggleClass("right"); } + if(h !== $(document).height()) { ul.toggleClass("bottom"); } + }) + .bind("mouseleave", function (e) { + $(this).children("ul").hide(); + }) + .end() + .css({ "visibility" : "visible" }) + .show(); + $(document).triggerHandler("context_show.vakata"); + }, + hide : function () { + $.vakata.context.vis = false; + $.vakata.context.cnt.attr("class","").css({ "visibility" : "hidden" }); + $(document).triggerHandler("context_hide.vakata"); + }, + parse : function (s, is_callback) { + if(!s) { return false; } + var str = "", + tmp = false, + was_sep = true; + if(!is_callback) { $.vakata.context.func = {}; } + str += "<ul>"; + $.each(s, function (i, val) { + if(!val) { return true; } + $.vakata.context.func[i] = val.action; + if(!was_sep && val.separator_before) { + str += "<li class='vakata-separator vakata-separator-before'></li>"; + } + was_sep = false; + str += "<li class='" + (val._class || "") + (val._disabled ? " jstree-contextmenu-disabled " : "") + "'><ins "; + if(val.icon && val.icon.indexOf("/") === -1) { str += " class='" + val.icon + "' "; } + if(val.icon && val.icon.indexOf("/") !== -1) { str += " style='background:url(" + val.icon + ") center center no-repeat;' "; } + str += ">&#160;</ins><a href='#' rel='" + i + "'>"; + if(val.submenu) { + str += "<span style='float:" + ($.vakata.context.rtl ? "left" : "right") + ";'>&raquo;</span>"; + } + str += val.label + "</a>"; + if(val.submenu) { + tmp = $.vakata.context.parse(val.submenu, true); + if(tmp) { str += tmp; } + } + str += "</li>"; + if(val.separator_after) { + str += "<li class='vakata-separator vakata-separator-after'></li>"; + was_sep = true; + } + }); + str = str.replace(/<li class\='vakata-separator vakata-separator-after'\><\/li\>$/,""); + str += "</ul>"; + $(document).triggerHandler("context_parse.vakata"); + return str.length > 10 ? str : false; + }, + exec : function (i) { + if($.isFunction($.vakata.context.func[i])) { + // if is string - eval and call it! + $.vakata.context.func[i].call($.vakata.context.data, $.vakata.context.par); + return true; + } + else { return false; } + } + }; + $(function () { + var css_string = '' + + '#vakata-contextmenu { display:block; visibility:hidden; left:0; top:-200px; position:absolute; margin:0; padding:0; min-width:180px; background:#ebebeb; border:1px solid silver; z-index:10000; *width:180px; } ' + + '#vakata-contextmenu ul { min-width:180px; *width:180px; } ' + + '#vakata-contextmenu ul, #vakata-contextmenu li { margin:0; padding:0; list-style-type:none; display:block; } ' + + '#vakata-contextmenu li { line-height:20px; min-height:20px; position:relative; padding:0px; } ' + + '#vakata-contextmenu li a { padding:1px 6px; line-height:17px; display:block; text-decoration:none; margin:1px 1px 0 1px; } ' + + '#vakata-contextmenu li ins { float:left; width:16px; height:16px; text-decoration:none; margin-right:2px; } ' + + '#vakata-contextmenu li a:hover, #vakata-contextmenu li.vakata-hover > a { background:gray; color:white; } ' + + '#vakata-contextmenu li ul { display:none; position:absolute; top:-2px; left:100%; background:#ebebeb; border:1px solid gray; } ' + + '#vakata-contextmenu .right { right:100%; left:auto; } ' + + '#vakata-contextmenu .bottom { bottom:-1px; top:auto; } ' + + '#vakata-contextmenu li.vakata-separator { min-height:0; height:1px; line-height:1px; font-size:1px; overflow:hidden; margin:0 2px; background:silver; /* border-top:1px solid #fefefe; */ padding:0; } '; + $.vakata.css.add_sheet({ str : css_string, title : "vakata" }); + $.vakata.context.cnt + .delegate("a","click", function (e) { e.preventDefault(); }) + .delegate("a","mouseup", function (e) { + if(!$(this).parent().hasClass("jstree-contextmenu-disabled") && $.vakata.context.exec($(this).attr("rel"))) { + $.vakata.context.hide(); + } + else { $(this).blur(); } + }) + .delegate("a","mouseover", function () { + $.vakata.context.cnt.find(".vakata-hover").removeClass("vakata-hover"); + }) + .appendTo("body"); + $(document).bind("mousedown", function (e) { if($.vakata.context.vis && !$.contains($.vakata.context.cnt[0], e.target)) { $.vakata.context.hide(); } }); + if(typeof $.hotkeys !== "undefined") { + $(document) + .bind("keydown", "up", function (e) { + if($.vakata.context.vis) { + var o = $.vakata.context.cnt.find("ul:visible").last().children(".vakata-hover").removeClass("vakata-hover").prevAll("li:not(.vakata-separator)").first(); + if(!o.length) { o = $.vakata.context.cnt.find("ul:visible").last().children("li:not(.vakata-separator)").last(); } + o.addClass("vakata-hover"); + e.stopImmediatePropagation(); + e.preventDefault(); + } + }) + .bind("keydown", "down", function (e) { + if($.vakata.context.vis) { + var o = $.vakata.context.cnt.find("ul:visible").last().children(".vakata-hover").removeClass("vakata-hover").nextAll("li:not(.vakata-separator)").first(); + if(!o.length) { o = $.vakata.context.cnt.find("ul:visible").last().children("li:not(.vakata-separator)").first(); } + o.addClass("vakata-hover"); + e.stopImmediatePropagation(); + e.preventDefault(); + } + }) + .bind("keydown", "right", function (e) { + if($.vakata.context.vis) { + $.vakata.context.cnt.find(".vakata-hover").children("ul").show().children("li:not(.vakata-separator)").removeClass("vakata-hover").first().addClass("vakata-hover"); + e.stopImmediatePropagation(); + e.preventDefault(); + } + }) + .bind("keydown", "left", function (e) { + if($.vakata.context.vis) { + $.vakata.context.cnt.find(".vakata-hover").children("ul").hide().children(".vakata-separator").removeClass("vakata-hover"); + e.stopImmediatePropagation(); + e.preventDefault(); + } + }) + .bind("keydown", "esc", function (e) { + $.vakata.context.hide(); + e.preventDefault(); + }) + .bind("keydown", "space", function (e) { + $.vakata.context.cnt.find(".vakata-hover").last().children("a").click(); + e.preventDefault(); + }); + } + }); + + $.jstree.plugin("contextmenu", { + __init : function () { + this.get_container() + .delegate("a", "contextmenu.jstree", $.proxy(function (e) { + e.preventDefault(); + if(!$(e.currentTarget).hasClass("jstree-loading")) { + this.show_contextmenu(e.currentTarget, e.pageX, e.pageY); + } + }, this)) + .delegate("a", "click.jstree", $.proxy(function (e) { + if(this.data.contextmenu) { + $.vakata.context.hide(); + } + }, this)) + .bind("destroy.jstree", $.proxy(function () { + // TODO: move this to descruct method + if(this.data.contextmenu) { + $.vakata.context.hide(); + } + }, this)); + $(document).bind("context_hide.vakata", $.proxy(function () { this.data.contextmenu = false; }, this)); + }, + defaults : { + select_node : false, // requires UI plugin + show_at_node : true, + items : { // Could be a function that should return an object like this one + "create" : { + "separator_before" : false, + "separator_after" : true, + "label" : "Create", + "action" : function (obj) { this.create(obj); } + }, + "rename" : { + "separator_before" : false, + "separator_after" : false, + "label" : "Rename", + "action" : function (obj) { this.rename(obj); } + }, + "remove" : { + "separator_before" : false, + "icon" : false, + "separator_after" : false, + "label" : "Delete", + "action" : function (obj) { if(this.is_selected(obj)) { this.remove(); } else { this.remove(obj); } } + }, + "ccp" : { + "separator_before" : true, + "icon" : false, + "separator_after" : false, + "label" : "Edit", + "action" : false, + "submenu" : { + "cut" : { + "separator_before" : false, + "separator_after" : false, + "label" : "Cut", + "action" : function (obj) { this.cut(obj); } + }, + "copy" : { + "separator_before" : false, + "icon" : false, + "separator_after" : false, + "label" : "Copy", + "action" : function (obj) { this.copy(obj); } + }, + "paste" : { + "separator_before" : false, + "icon" : false, + "separator_after" : false, + "label" : "Paste", + "action" : function (obj) { this.paste(obj); } + } + } + } + } + }, + _fn : { + show_contextmenu : function (obj, x, y) { + obj = this._get_node(obj); + var s = this.get_settings().contextmenu, + a = obj.children("a:visible:eq(0)"), + o = false, + i = false; + if(s.select_node && this.data.ui && !this.is_selected(obj)) { + this.deselect_all(); + this.select_node(obj, true); + } + if(s.show_at_node || typeof x === "undefined" || typeof y === "undefined") { + o = a.offset(); + x = o.left; + y = o.top + this.data.core.li_height; + } + i = obj.data("jstree") && obj.data("jstree").contextmenu ? obj.data("jstree").contextmenu : s.items; + if($.isFunction(i)) { i = i.call(this, obj); } + this.data.contextmenu = true; + $.vakata.context.show(i, a, x, y, this, obj, this._get_settings().core.rtl); + if(this.data.themes) { $.vakata.context.cnt.attr("class", "jstree-" + this.data.themes.theme + "-context"); } + } + } + }); +})(jQuery); +//*/ + +/* + * jsTree types plugin + * Adds support types of nodes + * You can set an attribute on each li node, that represents its type. + * According to the type setting the node may get custom icon/validation rules + */ +(function ($) { + $.jstree.plugin("types", { + __init : function () { + var s = this._get_settings().types; + this.data.types.attach_to = []; + this.get_container() + .bind("init.jstree", $.proxy(function () { + var types = s.types, + attr = s.type_attr, + icons_css = "", + _this = this; + + $.each(types, function (i, tp) { + $.each(tp, function (k, v) { + if(!/^(max_depth|max_children|icon|valid_children)$/.test(k)) { _this.data.types.attach_to.push(k); } + }); + if(!tp.icon) { return true; } + if( tp.icon.image || tp.icon.position) { + if(i == "default") { icons_css += '.jstree-' + _this.get_index() + ' a > .jstree-icon { '; } + else { icons_css += '.jstree-' + _this.get_index() + ' li[' + attr + '="' + i + '"] > a > .jstree-icon { '; } + if(tp.icon.image) { icons_css += ' background-image:url(' + tp.icon.image + '); '; } + if(tp.icon.position){ icons_css += ' background-position:' + tp.icon.position + '; '; } + else { icons_css += ' background-position:0 0; '; } + icons_css += '} '; + } + }); + if(icons_css !== "") { $.vakata.css.add_sheet({ 'str' : icons_css, title : "jstree-types" }); } + }, this)) + .bind("before.jstree", $.proxy(function (e, data) { + var s, t, + o = this._get_settings().types.use_data ? this._get_node(data.args[0]) : false, + d = o && o !== -1 && o.length ? o.data("jstree") : false; + if(d && d.types && d.types[data.func] === false) { e.stopImmediatePropagation(); return false; } + if($.inArray(data.func, this.data.types.attach_to) !== -1) { + if(!data.args[0] || (!data.args[0].tagName && !data.args[0].jquery)) { return; } + s = this._get_settings().types.types; + t = this._get_type(data.args[0]); + if( + ( + (s[t] && typeof s[t][data.func] !== "undefined") || + (s["default"] && typeof s["default"][data.func] !== "undefined") + ) && this._check(data.func, data.args[0]) === false + ) { + e.stopImmediatePropagation(); + return false; + } + } + }, this)); + if(is_ie6) { + this.get_container() + .bind("load_node.jstree set_type.jstree", $.proxy(function (e, data) { + var r = data && data.rslt && data.rslt.obj && data.rslt.obj !== -1 ? this._get_node(data.rslt.obj).parent() : this.get_container_ul(), + c = false, + s = this._get_settings().types; + $.each(s.types, function (i, tp) { + if(tp.icon && (tp.icon.image || tp.icon.position)) { + c = i === "default" ? r.find("li > a > .jstree-icon") : r.find("li[" + s.type_attr + "='" + i + "'] > a > .jstree-icon"); + if(tp.icon.image) { c.css("backgroundImage","url(" + tp.icon.image + ")"); } + c.css("backgroundPosition", tp.icon.position || "0 0"); + } + }); + }, this)); + } + }, + defaults : { + // defines maximum number of root nodes (-1 means unlimited, -2 means disable max_children checking) + max_children : -1, + // defines the maximum depth of the tree (-1 means unlimited, -2 means disable max_depth checking) + max_depth : -1, + // defines valid node types for the root nodes + valid_children : "all", + + // whether to use $.data + use_data : false, + // where is the type stores (the rel attribute of the LI element) + type_attr : "rel", + // a list of types + types : { + // the default type + "default" : { + "max_children" : -1, + "max_depth" : -1, + "valid_children": "all" + + // Bound functions - you can bind any other function here (using boolean or function) + //"select_node" : true + } + } + }, + _fn : { + _types_notify : function (n, data) { + if(data.type && this._get_settings().types.use_data) { + this.set_type(data.type, n); + } + }, + _get_type : function (obj) { + obj = this._get_node(obj); + return (!obj || !obj.length) ? false : obj.attr(this._get_settings().types.type_attr) || "default"; + }, + set_type : function (str, obj) { + obj = this._get_node(obj); + var ret = (!obj.length || !str) ? false : obj.attr(this._get_settings().types.type_attr, str); + if(ret) { this.__callback({ obj : obj, type : str}); } + return ret; + }, + _check : function (rule, obj, opts) { + obj = this._get_node(obj); + var v = false, t = this._get_type(obj), d = 0, _this = this, s = this._get_settings().types, data = false; + if(obj === -1) { + if(!!s[rule]) { v = s[rule]; } + else { return; } + } + else { + if(t === false) { return; } + data = s.use_data ? obj.data("jstree") : false; + if(data && data.types && typeof data.types[rule] !== "undefined") { v = data.types[rule]; } + else if(!!s.types[t] && typeof s.types[t][rule] !== "undefined") { v = s.types[t][rule]; } + else if(!!s.types["default"] && typeof s.types["default"][rule] !== "undefined") { v = s.types["default"][rule]; } + } + if($.isFunction(v)) { v = v.call(this, obj); } + if(rule === "max_depth" && obj !== -1 && opts !== false && s.max_depth !== -2 && v !== 0) { + // also include the node itself - otherwise if root node it is not checked + obj.children("a:eq(0)").parentsUntil(".jstree","li").each(function (i) { + // check if current depth already exceeds global tree depth + if(s.max_depth !== -1 && s.max_depth - (i + 1) <= 0) { v = 0; return false; } + d = (i === 0) ? v : _this._check(rule, this, false); + // check if current node max depth is already matched or exceeded + if(d !== -1 && d - (i + 1) <= 0) { v = 0; return false; } + // otherwise - set the max depth to the current value minus current depth + if(d >= 0 && (d - (i + 1) < v || v < 0) ) { v = d - (i + 1); } + // if the global tree depth exists and it minus the nodes calculated so far is less than `v` or `v` is unlimited + if(s.max_depth >= 0 && (s.max_depth - (i + 1) < v || v < 0) ) { v = s.max_depth - (i + 1); } + }); + } + return v; + }, + check_move : function () { + if(!this.__call_old()) { return false; } + var m = this._get_move(), + s = m.rt._get_settings().types, + mc = m.rt._check("max_children", m.cr), + md = m.rt._check("max_depth", m.cr), + vc = m.rt._check("valid_children", m.cr), + ch = 0, d = 1, t; + + if(vc === "none") { return false; } + if($.isArray(vc) && m.ot && m.ot._get_type) { + m.o.each(function () { + if($.inArray(m.ot._get_type(this), vc) === -1) { d = false; return false; } + }); + if(d === false) { return false; } + } + if(s.max_children !== -2 && mc !== -1) { + ch = m.cr === -1 ? this.get_container().find("> ul > li").not(m.o).length : m.cr.find("> ul > li").not(m.o).length; + if(ch + m.o.length > mc) { return false; } + } + if(s.max_depth !== -2 && md !== -1) { + d = 0; + if(md === 0) { return false; } + if(typeof m.o.d === "undefined") { + // TODO: deal with progressive rendering and async when checking max_depth (how to know the depth of the moved node) + t = m.o; + while(t.length > 0) { + t = t.find("> ul > li"); + d ++; + } + m.o.d = d; + } + if(md - m.o.d < 0) { return false; } + } + return true; + }, + create_node : function (obj, position, js, callback, is_loaded, skip_check) { + if(!skip_check && (is_loaded || this._is_loaded(obj))) { + var p = (typeof position == "string" && position.match(/^before|after$/i) && obj !== -1) ? this._get_parent(obj) : this._get_node(obj), + s = this._get_settings().types, + mc = this._check("max_children", p), + md = this._check("max_depth", p), + vc = this._check("valid_children", p), + ch; + if(typeof js === "string") { js = { data : js }; } + if(!js) { js = {}; } + if(vc === "none") { return false; } + if($.isArray(vc)) { + if(!js.attr || !js.attr[s.type_attr]) { + if(!js.attr) { js.attr = {}; } + js.attr[s.type_attr] = vc[0]; + } + else { + if($.inArray(js.attr[s.type_attr], vc) === -1) { return false; } + } + } + if(s.max_children !== -2 && mc !== -1) { + ch = p === -1 ? this.get_container().find("> ul > li").length : p.find("> ul > li").length; + if(ch + 1 > mc) { return false; } + } + if(s.max_depth !== -2 && md !== -1 && (md - 1) < 0) { return false; } + } + return this.__call_old(true, obj, position, js, callback, is_loaded, skip_check); + } + } + }); +})(jQuery); +//*/ + +/* + * jsTree HTML plugin + * The HTML data store. Datastores are build by replacing the `load_node` and `_is_loaded` functions. + */ +(function ($) { + $.jstree.plugin("html_data", { + __init : function () { + // this used to use html() and clean the whitespace, but this way any attached data was lost + this.data.html_data.original_container_html = this.get_container().find(" > ul > li").clone(true); + // remove white space from LI node - otherwise nodes appear a bit to the right + this.data.html_data.original_container_html.find("li").andSelf().contents().filter(function() { return this.nodeType == 3; }).remove(); + }, + defaults : { + data : false, + ajax : false, + correct_state : true + }, + _fn : { + load_node : function (obj, s_call, e_call) { var _this = this; this.load_node_html(obj, function () { _this.__callback({ "obj" : _this._get_node(obj) }); s_call.call(this); }, e_call); }, + _is_loaded : function (obj) { + obj = this._get_node(obj); + return obj == -1 || !obj || (!this._get_settings().html_data.ajax && !$.isFunction(this._get_settings().html_data.data)) || obj.is(".jstree-open, .jstree-leaf") || obj.children("ul").children("li").size() > 0; + }, + load_node_html : function (obj, s_call, e_call) { + var d, + s = this.get_settings().html_data, + error_func = function () {}, + success_func = function () {}; + obj = this._get_node(obj); + if(obj && obj !== -1) { + if(obj.data("jstree_is_loading")) { return; } + else { obj.data("jstree_is_loading",true); } + } + switch(!0) { + case ($.isFunction(s.data)): + s.data.call(this, obj, $.proxy(function (d) { + if(d && d !== "" && d.toString && d.toString().replace(/^[\s\n]+$/,"") !== "") { + d = $(d); + if(!d.is("ul")) { d = $("<ul />").append(d); } + if(obj == -1 || !obj) { this.get_container().children("ul").empty().append(d.children()).find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end().filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); } + else { obj.children("a.jstree-loading").removeClass("jstree-loading"); obj.append(d).children("ul").find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end().filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); obj.removeData("jstree_is_loading"); } + this.clean_node(obj); + if(s_call) { s_call.call(this); } + } + else { + if(obj && obj !== -1) { + obj.children("a.jstree-loading").removeClass("jstree-loading"); + obj.removeData("jstree_is_loading"); + if(s.correct_state) { + this.correct_state(obj); + if(s_call) { s_call.call(this); } + } + } + else { + if(s.correct_state) { + this.get_container().children("ul").empty(); + if(s_call) { s_call.call(this); } + } + } + } + }, this)); + break; + case (!s.data && !s.ajax): + if(!obj || obj == -1) { + this.get_container() + .children("ul").empty() + .append(this.data.html_data.original_container_html) + .find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end() + .filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); + this.clean_node(); + } + if(s_call) { s_call.call(this); } + break; + case (!!s.data && !s.ajax) || (!!s.data && !!s.ajax && (!obj || obj === -1)): + if(!obj || obj == -1) { + d = $(s.data); + if(!d.is("ul")) { d = $("<ul />").append(d); } + this.get_container() + .children("ul").empty().append(d.children()) + .find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end() + .filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); + this.clean_node(); + } + if(s_call) { s_call.call(this); } + break; + case (!s.data && !!s.ajax) || (!!s.data && !!s.ajax && obj && obj !== -1): + obj = this._get_node(obj); + error_func = function (x, t, e) { + var ef = this.get_settings().html_data.ajax.error; + if(ef) { ef.call(this, x, t, e); } + if(obj != -1 && obj.length) { + obj.children("a.jstree-loading").removeClass("jstree-loading"); + obj.removeData("jstree_is_loading"); + if(t === "success" && s.correct_state) { this.correct_state(obj); } + } + else { + if(t === "success" && s.correct_state) { this.get_container().children("ul").empty(); } + } + if(e_call) { e_call.call(this); } + }; + success_func = function (d, t, x) { + var sf = this.get_settings().html_data.ajax.success; + if(sf) { d = sf.call(this,d,t,x) || d; } + if(d === "" || (d && d.toString && d.toString().replace(/^[\s\n]+$/,"") === "")) { + return error_func.call(this, x, t, ""); + } + if(d) { + d = $(d); + if(!d.is("ul")) { d = $("<ul />").append(d); } + if(obj == -1 || !obj) { this.get_container().children("ul").empty().append(d.children()).find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end().filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); } + else { obj.children("a.jstree-loading").removeClass("jstree-loading"); obj.append(d).children("ul").find("li, a").filter(function () { return !this.firstChild || !this.firstChild.tagName || this.firstChild.tagName !== "INS"; }).prepend("<ins class='jstree-icon'>&#160;</ins>").end().filter("a").children("ins:first-child").not(".jstree-icon").addClass("jstree-icon"); obj.removeData("jstree_is_loading"); } + this.clean_node(obj); + if(s_call) { s_call.call(this); } + } + else { + if(obj && obj !== -1) { + obj.children("a.jstree-loading").removeClass("jstree-loading"); + obj.removeData("jstree_is_loading"); + if(s.correct_state) { + this.correct_state(obj); + if(s_call) { s_call.call(this); } + } + } + else { + if(s.correct_state) { + this.get_container().children("ul").empty(); + if(s_call) { s_call.call(this); } + } + } + } + }; + s.ajax.context = this; + s.ajax.error = error_func; + s.ajax.success = success_func; + if(!s.ajax.dataType) { s.ajax.dataType = "html"; } + if($.isFunction(s.ajax.url)) { s.ajax.url = s.ajax.url.call(this, obj); } + if($.isFunction(s.ajax.data)) { s.ajax.data = s.ajax.data.call(this, obj); } + $.ajax(s.ajax); + break; + } + } + } + }); + // include the HTML data plugin by default + $.jstree.defaults.plugins.push("html_data"); +})(jQuery); +//*/ + +/* + * jsTree themeroller plugin + * Adds support for jQuery UI themes. Include this at the end of your plugins list, also make sure "themes" is not included. + */ +(function ($) { + $.jstree.plugin("themeroller", { + __init : function () { + var s = this._get_settings().themeroller; + this.get_container() + .addClass("ui-widget-content") + .addClass("jstree-themeroller") + .delegate("a","mouseenter.jstree", function (e) { + if(!$(e.currentTarget).hasClass("jstree-loading")) { + $(this).addClass(s.item_h); + } + }) + .delegate("a","mouseleave.jstree", function () { + $(this).removeClass(s.item_h); + }) + .bind("init.jstree", $.proxy(function (e, data) { + data.inst.get_container().find("> ul > li > .jstree-loading > ins").addClass("ui-icon-refresh"); + this._themeroller(data.inst.get_container().find("> ul > li")); + }, this)) + .bind("open_node.jstree create_node.jstree", $.proxy(function (e, data) { + this._themeroller(data.rslt.obj); + }, this)) + .bind("loaded.jstree refresh.jstree", $.proxy(function (e) { + this._themeroller(); + }, this)) + .bind("close_node.jstree", $.proxy(function (e, data) { + this._themeroller(data.rslt.obj); + }, this)) + .bind("delete_node.jstree", $.proxy(function (e, data) { + this._themeroller(data.rslt.parent); + }, this)) + .bind("correct_state.jstree", $.proxy(function (e, data) { + data.rslt.obj + .children("ins.jstree-icon").removeClass(s.opened + " " + s.closed + " ui-icon").end() + .find("> a > ins.ui-icon") + .filter(function() { + return this.className.toString() + .replace(s.item_clsd,"").replace(s.item_open,"").replace(s.item_leaf,"") + .indexOf("ui-icon-") === -1; + }).removeClass(s.item_open + " " + s.item_clsd).addClass(s.item_leaf || "jstree-no-icon"); + }, this)) + .bind("select_node.jstree", $.proxy(function (e, data) { + data.rslt.obj.children("a").addClass(s.item_a); + }, this)) + .bind("deselect_node.jstree deselect_all.jstree", $.proxy(function (e, data) { + this.get_container() + .find("a." + s.item_a).removeClass(s.item_a).end() + .find("a.jstree-clicked").addClass(s.item_a); + }, this)) + .bind("dehover_node.jstree", $.proxy(function (e, data) { + data.rslt.obj.children("a").removeClass(s.item_h); + }, this)) + .bind("hover_node.jstree", $.proxy(function (e, data) { + this.get_container() + .find("a." + s.item_h).not(data.rslt.obj).removeClass(s.item_h); + data.rslt.obj.children("a").addClass(s.item_h); + }, this)) + .bind("move_node.jstree", $.proxy(function (e, data) { + this._themeroller(data.rslt.o); + this._themeroller(data.rslt.op); + }, this)); + }, + __destroy : function () { + var s = this._get_settings().themeroller, + c = [ "ui-icon" ]; + $.each(s, function (i, v) { + v = v.split(" "); + if(v.length) { c = c.concat(v); } + }); + this.get_container() + .removeClass("ui-widget-content") + .find("." + c.join(", .")).removeClass(c.join(" ")); + }, + _fn : { + _themeroller : function (obj) { + var s = this._get_settings().themeroller; + obj = (!obj || obj == -1) ? this.get_container_ul() : this._get_node(obj); + obj = (!obj || obj == -1) ? this.get_container_ul() : obj.parent(); + obj + .find("li.jstree-closed") + .children("ins.jstree-icon").removeClass(s.opened).addClass("ui-icon " + s.closed).end() + .children("a").addClass(s.item) + .children("ins.jstree-icon").addClass("ui-icon") + .filter(function() { + return this.className.toString() + .replace(s.item_clsd,"").replace(s.item_open,"").replace(s.item_leaf,"") + .indexOf("ui-icon-") === -1; + }).removeClass(s.item_leaf + " " + s.item_open).addClass(s.item_clsd || "jstree-no-icon") + .end() + .end() + .end() + .end() + .find("li.jstree-open") + .children("ins.jstree-icon").removeClass(s.closed).addClass("ui-icon " + s.opened).end() + .children("a").addClass(s.item) + .children("ins.jstree-icon").addClass("ui-icon") + .filter(function() { + return this.className.toString() + .replace(s.item_clsd,"").replace(s.item_open,"").replace(s.item_leaf,"") + .indexOf("ui-icon-") === -1; + }).removeClass(s.item_leaf + " " + s.item_clsd).addClass(s.item_open || "jstree-no-icon") + .end() + .end() + .end() + .end() + .find("li.jstree-leaf") + .children("ins.jstree-icon").removeClass(s.closed + " ui-icon " + s.opened).end() + .children("a").addClass(s.item) + .children("ins.jstree-icon").addClass("ui-icon") + .filter(function() { + return this.className.toString() + .replace(s.item_clsd,"").replace(s.item_open,"").replace(s.item_leaf,"") + .indexOf("ui-icon-") === -1; + }).removeClass(s.item_clsd + " " + s.item_open).addClass(s.item_leaf || "jstree-no-icon"); + } + }, + defaults : { + "opened" : "ui-icon-triangle-1-se", + "closed" : "ui-icon-triangle-1-e", + "item" : "ui-state-default", + "item_h" : "ui-state-hover", + "item_a" : "ui-state-active", + "item_open" : "ui-icon-folder-open", + "item_clsd" : "ui-icon-folder-collapsed", + "item_leaf" : "ui-icon-document" + } + }); + $(function() { + var css_string = '' + + '.jstree-themeroller .ui-icon { overflow:visible; } ' + + '.jstree-themeroller a { padding:0 2px; } ' + + '.jstree-themeroller .jstree-no-icon { display:none; }'; + $.vakata.css.add_sheet({ str : css_string, title : "jstree" }); + }); +})(jQuery); +//*/ + +/* + * jsTree unique plugin + * Forces different names amongst siblings (still a bit experimental) + * NOTE: does not check language versions (it will not be possible to have nodes with the same title, even in different languages) + */ +(function ($) { + $.jstree.plugin("unique", { + __init : function () { + this.get_container() + .bind("before.jstree", $.proxy(function (e, data) { + var nms = [], res = true, p, t; + if(data.func == "move_node") { + // obj, ref, position, is_copy, is_prepared, skip_check + if(data.args[4] === true) { + if(data.args[0].o && data.args[0].o.length) { + data.args[0].o.children("a").each(function () { nms.push($(this).text().replace(/^\s+/g,"")); }); + res = this._check_unique(nms, data.args[0].np.find("> ul > li").not(data.args[0].o), "move_node"); + } + } + } + if(data.func == "create_node") { + // obj, position, js, callback, is_loaded + if(data.args[4] || this._is_loaded(data.args[0])) { + p = this._get_node(data.args[0]); + if(data.args[1] && (data.args[1] === "before" || data.args[1] === "after")) { + p = this._get_parent(data.args[0]); + if(!p || p === -1) { p = this.get_container(); } + } + if(typeof data.args[2] === "string") { nms.push(data.args[2]); } + else if(!data.args[2] || !data.args[2].data) { nms.push(this._get_string("new_node")); } + else { nms.push(data.args[2].data); } + res = this._check_unique(nms, p.find("> ul > li"), "create_node"); + } + } + if(data.func == "rename_node") { + // obj, val + nms.push(data.args[1]); + t = this._get_node(data.args[0]); + p = this._get_parent(t); + if(!p || p === -1) { p = this.get_container(); } + res = this._check_unique(nms, p.find("> ul > li").not(t), "rename_node"); + } + if(!res) { + e.stopPropagation(); + return false; + } + }, this)); + }, + defaults : { + error_callback : $.noop + }, + _fn : { + _check_unique : function (nms, p, func) { + var cnms = [], ok = true; + p.children("a").each(function () { cnms.push($(this).text().replace(/^\s+/g,"")); }); + if(!cnms.length || !nms.length) { return true; } + $.each(nms, function (i, v) { + if($.inArray(v, cnms) !== -1) { + ok = false; + return false; + } + }); + if(!ok) { + this._get_settings().unique.error_callback.call(null, nms, p, func); + } + return ok; + }, + check_move : function () { + if(!this.__call_old()) { return false; } + var p = this._get_move(), nms = []; + if(p.o && p.o.length) { + p.o.children("a").each(function () { nms.push($(this).text().replace(/^\s+/g,"")); }); + return this._check_unique(nms, p.np.find("> ul > li").not(p.o), "check_move"); + } + return true; + } + } + }); +})(jQuery); +//*/ + +/* + * jsTree wholerow plugin + * Makes select and hover work on the entire width of the node + * MAY BE HEAVY IN LARGE DOM + */ +(function ($) { + $.jstree.plugin("wholerow", { + __init : function () { + if(!this.data.ui) { throw "jsTree wholerow: jsTree UI plugin not included."; } + this.data.wholerow.html = false; + this.data.wholerow.to = false; + this.get_container() + .bind("init.jstree", $.proxy(function (e, data) { + this._get_settings().core.animation = 0; + }, this)) + .bind("open_node.jstree create_node.jstree clean_node.jstree loaded.jstree", $.proxy(function (e, data) { + this._prepare_wholerow_span( data && data.rslt && data.rslt.obj ? data.rslt.obj : -1 ); + }, this)) + .bind("search.jstree clear_search.jstree reopen.jstree after_open.jstree after_close.jstree create_node.jstree delete_node.jstree clean_node.jstree", $.proxy(function (e, data) { + if(this.data.to) { clearTimeout(this.data.to); } + this.data.to = setTimeout( (function (t, o) { return function() { t._prepare_wholerow_ul(o); }; })(this, data && data.rslt && data.rslt.obj ? data.rslt.obj : -1), 0); + }, this)) + .bind("deselect_all.jstree", $.proxy(function (e, data) { + this.get_container().find(" > .jstree-wholerow .jstree-clicked").removeClass("jstree-clicked " + (this.data.themeroller ? this._get_settings().themeroller.item_a : "" )); + }, this)) + .bind("select_node.jstree deselect_node.jstree ", $.proxy(function (e, data) { + data.rslt.obj.each(function () { + var ref = data.inst.get_container().find(" > .jstree-wholerow li:visible:eq(" + ( parseInt((($(this).offset().top - data.inst.get_container().offset().top + data.inst.get_container()[0].scrollTop) / data.inst.data.core.li_height),10)) + ")"); + // ref.children("a")[e.type === "select_node" ? "addClass" : "removeClass"]("jstree-clicked"); + ref.children("a").attr("class",data.rslt.obj.children("a").attr("class")); + }); + }, this)) + .bind("hover_node.jstree dehover_node.jstree", $.proxy(function (e, data) { + this.get_container().find(" > .jstree-wholerow .jstree-hovered").removeClass("jstree-hovered " + (this.data.themeroller ? this._get_settings().themeroller.item_h : "" )); + if(e.type === "hover_node") { + var ref = this.get_container().find(" > .jstree-wholerow li:visible:eq(" + ( parseInt(((data.rslt.obj.offset().top - this.get_container().offset().top + this.get_container()[0].scrollTop) / this.data.core.li_height),10)) + ")"); + // ref.children("a").addClass("jstree-hovered"); + ref.children("a").attr("class",data.rslt.obj.children(".jstree-hovered").attr("class")); + } + }, this)) + .delegate(".jstree-wholerow-span, ins.jstree-icon, li", "click.jstree", function (e) { + var n = $(e.currentTarget); + if(e.target.tagName === "A" || (e.target.tagName === "INS" && n.closest("li").is(".jstree-open, .jstree-closed"))) { return; } + n.closest("li").children("a:visible:eq(0)").click(); + e.stopImmediatePropagation(); + }) + .delegate("li", "mouseover.jstree", $.proxy(function (e) { + e.stopImmediatePropagation(); + if($(e.currentTarget).children(".jstree-hovered, .jstree-clicked").length) { return false; } + this.hover_node(e.currentTarget); + return false; + }, this)) + .delegate("li", "mouseleave.jstree", $.proxy(function (e) { + if($(e.currentTarget).children("a").hasClass("jstree-hovered").length) { return; } + this.dehover_node(e.currentTarget); + }, this)); + if(is_ie7 || is_ie6) { + $.vakata.css.add_sheet({ str : ".jstree-" + this.get_index() + " { position:relative; } ", title : "jstree" }); + } + }, + defaults : { + }, + __destroy : function () { + this.get_container().children(".jstree-wholerow").remove(); + this.get_container().find(".jstree-wholerow-span").remove(); + }, + _fn : { + _prepare_wholerow_span : function (obj) { + obj = !obj || obj == -1 ? this.get_container().find("> ul > li") : this._get_node(obj); + if(obj === false) { return; } // added for removing root nodes + obj.each(function () { + $(this).find("li").andSelf().each(function () { + var $t = $(this); + if($t.children(".jstree-wholerow-span").length) { return true; } + $t.prepend("<span class='jstree-wholerow-span' style='width:" + ($t.parentsUntil(".jstree","li").length * 18) + "px;'>&#160;</span>"); + }); + }); + }, + _prepare_wholerow_ul : function () { + var o = this.get_container().children("ul").eq(0), h = o.html(); + o.addClass("jstree-wholerow-real"); + if(this.data.wholerow.last_html !== h) { + this.data.wholerow.last_html = h; + this.get_container().children(".jstree-wholerow").remove(); + this.get_container().append( + o.clone().removeClass("jstree-wholerow-real") + .wrapAll("<div class='jstree-wholerow' />").parent() + .width(o.parent()[0].scrollWidth) + .css("top", (o.height() + ( is_ie7 ? 5 : 0)) * -1 ) + .find("li[id]").each(function () { this.removeAttribute("id"); }).end() + ); + } + } + } + }); + $(function() { + var css_string = '' + + '.jstree .jstree-wholerow-real { position:relative; z-index:1; } ' + + '.jstree .jstree-wholerow-real li { cursor:pointer; } ' + + '.jstree .jstree-wholerow-real a { border-left-color:transparent !important; border-right-color:transparent !important; } ' + + '.jstree .jstree-wholerow { position:relative; z-index:0; height:0; } ' + + '.jstree .jstree-wholerow ul, .jstree .jstree-wholerow li { width:100%; } ' + + '.jstree .jstree-wholerow, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow li, .jstree .jstree-wholerow a { margin:0 !important; padding:0 !important; } ' + + '.jstree .jstree-wholerow, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow li { background:transparent !important; }' + + '.jstree .jstree-wholerow ins, .jstree .jstree-wholerow span, .jstree .jstree-wholerow input { display:none !important; }' + + '.jstree .jstree-wholerow a, .jstree .jstree-wholerow a:hover { text-indent:-9999px; !important; width:100%; padding:0 !important; border-right-width:0px !important; border-left-width:0px !important; } ' + + '.jstree .jstree-wholerow-span { position:absolute; left:0; margin:0px; padding:0; height:18px; border-width:0; padding:0; z-index:0; }'; + if(is_ff2) { + css_string += '' + + '.jstree .jstree-wholerow a { display:block; height:18px; margin:0; padding:0; border:0; } ' + + '.jstree .jstree-wholerow-real a { border-color:transparent !important; } '; + } + if(is_ie7 || is_ie6) { + css_string += '' + + '.jstree .jstree-wholerow, .jstree .jstree-wholerow li, .jstree .jstree-wholerow ul, .jstree .jstree-wholerow a { margin:0; padding:0; line-height:18px; } ' + + '.jstree .jstree-wholerow a { display:block; height:18px; line-height:18px; overflow:hidden; } '; + } + $.vakata.css.add_sheet({ str : css_string, title : "jstree" }); + }); +})(jQuery); +//*/ + +/* +* jsTree model plugin +* This plugin gets jstree to use a class model to retrieve data, creating great dynamism +*/ +(function ($) { + var nodeInterface = ["getChildren","getChildrenCount","getAttr","getName","getProps"], + validateInterface = function(obj, inter) { + var valid = true; + obj = obj || {}; + inter = [].concat(inter); + $.each(inter, function (i, v) { + if(!$.isFunction(obj[v])) { valid = false; return false; } + }); + return valid; + }; + $.jstree.plugin("model", { + __init : function () { + if(!this.data.json_data) { throw "jsTree model: jsTree json_data plugin not included."; } + this._get_settings().json_data.data = function (n, b) { + var obj = (n == -1) ? this._get_settings().model.object : n.data("jstree_model"); + if(!validateInterface(obj, nodeInterface)) { return b.call(null, false); } + if(this._get_settings().model.async) { + obj.getChildren($.proxy(function (data) { + this.model_done(data, b); + }, this)); + } + else { + this.model_done(obj.getChildren(), b); + } + }; + }, + defaults : { + object : false, + id_prefix : false, + async : false + }, + _fn : { + model_done : function (data, callback) { + var ret = [], + s = this._get_settings(), + _this = this; + + if(!$.isArray(data)) { data = [data]; } + $.each(data, function (i, nd) { + var r = nd.getProps() || {}; + r.attr = nd.getAttr() || {}; + if(nd.getChildrenCount()) { r.state = "closed"; } + r.data = nd.getName(); + if(!$.isArray(r.data)) { r.data = [r.data]; } + if(_this.data.types && $.isFunction(nd.getType)) { + r.attr[s.types.type_attr] = nd.getType(); + } + if(r.attr.id && s.model.id_prefix) { r.attr.id = s.model.id_prefix + r.attr.id; } + if(!r.metadata) { r.metadata = { }; } + r.metadata.jstree_model = nd; + ret.push(r); + }); + callback.call(null, ret); + } + } + }); +})(jQuery); +//*/ + +})(); \ No newline at end of file diff --git a/src/static/jquery/jquery-jstree/themes/apple/bg.jpg b/src/static/jquery/jquery-jstree/themes/apple/bg.jpg new file mode 100755 index 0000000000000000000000000000000000000000..3aad05d8fadd75f8d9e02866f695b486f0b46343 GIT binary patch literal 331 zcmex=<NpH&0WUXCHwH!~28I+MWcdGvLC~c%IlGd9k%5JQfx!kS^p1hgF(p4Kl_BK- zP=xXSZH5*GHWn5ZRu(o^RyIyHAm-*^W8>iF;o{=v;^GnD0RsUZK7IjyJ|1CV5fNcw z8EI*08F@HhWM^mR<>8eO5Ri}(6%>_%OAyQWe}F-dgF%IXk(p7Dfk}{&S&;Gn5r#;h zvzdX8L;}n#9E^<UqRfm;ECP%SOsHxZ7X~ql2m)0zBIyVESWxKyEe0NDpn5@OK?Zw< XOYd45;+|jbJ!N~<NG0n8|Nol+zjH3u literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/apple/d.png b/src/static/jquery/jquery-jstree/themes/apple/d.png new file mode 100755 index 0000000000000000000000000000000000000000..2463ba6df91e1668434abdd623bbca914a4fcbe6 GIT binary patch literal 7765 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 b_WuI_=b@>S5J7qt00000NkvXXu0mjf{8{<q literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/apple/dot_for_ie.gif b/src/static/jquery/jquery-jstree/themes/apple/dot_for_ie.gif new file mode 100755 index 0000000000000000000000000000000000000000..c0cc5fda7cfb9539720de442a3caca9c9a3fc4cb GIT binary patch literal 43 vcmZ?wbhEHbWMW`qXkcKFla>7c|G(l-7DfgJMg|=QAOOiQFfqBrF<1it%E1S( literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/apple/style.css b/src/static/jquery/jquery-jstree/themes/apple/style.css new file mode 100755 index 0000000..d0c4163 --- /dev/null +++ b/src/static/jquery/jquery-jstree/themes/apple/style.css @@ -0,0 +1,61 @@ +/* + * jsTree apple theme 1.0 + * Supported features: dots/no-dots, icons/no-icons, focused, loading + * Supported plugins: ui (hovered, clicked), checkbox, contextmenu, search + */ + +.jstree-apple > ul { background:url("bg.jpg") left top repeat; } +.jstree-apple li, +.jstree-apple ins { background-image:url("d.png"); background-repeat:no-repeat; background-color:transparent; } +.jstree-apple li { background-position:-90px 0; background-repeat:repeat-y; } +.jstree-apple li.jstree-last { background:transparent; } +.jstree-apple .jstree-open > ins { background-position:-72px 0; } +.jstree-apple .jstree-closed > ins { background-position:-54px 0; } +.jstree-apple .jstree-leaf > ins { background-position:-36px 0; } + +.jstree-apple a { border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; text-shadow:1px 1px 1px white; } +.jstree-apple .jstree-hovered { background:#e7f4f9; border:1px solid #d8f0fa; padding:0 3px 0 1px; text-shadow:1px 1px 1px silver; } +.jstree-apple .jstree-clicked { background:#beebff; border:1px solid #99defd; padding:0 3px 0 1px; } +.jstree-apple a .jstree-icon { background-position:-56px -20px; } +.jstree-apple a.jstree-loading .jstree-icon { background:url("throbber.gif") center center no-repeat !important; } + +.jstree-apple.jstree-focused { background:white; } + +.jstree-apple .jstree-no-dots li, +.jstree-apple .jstree-no-dots .jstree-leaf > ins { background:transparent; } +.jstree-apple .jstree-no-dots .jstree-open > ins { background-position:-18px 0; } +.jstree-apple .jstree-no-dots .jstree-closed > ins { background-position:0 0; } + +.jstree-apple .jstree-no-icons a .jstree-icon { display:none; } + +.jstree-apple .jstree-search { font-style:italic; } + +.jstree-apple .jstree-no-icons .jstree-checkbox { display:inline-block; } +.jstree-apple .jstree-no-checkboxes .jstree-checkbox { display:none !important; } +.jstree-apple .jstree-checked > a > .jstree-checkbox { background-position:-38px -19px; } +.jstree-apple .jstree-unchecked > a > .jstree-checkbox { background-position:-2px -19px; } +.jstree-apple .jstree-undetermined > a > .jstree-checkbox { background-position:-20px -19px; } +.jstree-apple .jstree-checked > a > .checkbox:hover { background-position:-38px -37px; } +.jstree-apple .jstree-unchecked > a > .jstree-checkbox:hover { background-position:-2px -37px; } +.jstree-apple .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-20px -37px; } + +#vakata-dragged.jstree-apple ins { background:transparent !important; } +#vakata-dragged.jstree-apple .jstree-ok { background:url("d.png") -2px -53px no-repeat !important; } +#vakata-dragged.jstree-apple .jstree-invalid { background:url("d.png") -18px -53px no-repeat !important; } +#jstree-marker.jstree-apple { background:url("d.png") -41px -57px no-repeat !important; text-indent:-100px; } + +.jstree-apple a.jstree-search { color:aqua; } +.jstree-apple .jstree-locked a { color:silver; cursor:default; } + +#vakata-contextmenu.jstree-apple-context, +#vakata-contextmenu.jstree-apple-context li ul { background:#f0f0f0; border:1px solid #979797; -moz-box-shadow: 1px 1px 2px #999; -webkit-box-shadow: 1px 1px 2px #999; box-shadow: 1px 1px 2px #999; } +#vakata-contextmenu.jstree-apple-context li { } +#vakata-contextmenu.jstree-apple-context a { color:black; } +#vakata-contextmenu.jstree-apple-context a:hover, +#vakata-contextmenu.jstree-apple-context .vakata-hover > a { padding:0 5px; background:#e8eff7; border:1px solid #aecff7; color:black; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; } +#vakata-contextmenu.jstree-apple-context li.jstree-contextmenu-disabled a, +#vakata-contextmenu.jstree-apple-context li.jstree-contextmenu-disabled a:hover { color:silver; background:transparent; border:0; padding:1px 4px; } +#vakata-contextmenu.jstree-apple-context li.vakata-separator { background:white; border-top:1px solid #e0e0e0; margin:0; } +#vakata-contextmenu.jstree-apple-context li ul { margin-left:-4px; } + +/* TODO: IE6 support - the `>` selectors */ \ No newline at end of file diff --git a/src/static/jquery/jquery-jstree/themes/apple/throbber.gif b/src/static/jquery/jquery-jstree/themes/apple/throbber.gif new file mode 100755 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 GIT binary patch literal 1849 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 EAHN$8j{pDw literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/classic/d.gif b/src/static/jquery/jquery-jstree/themes/classic/d.gif new file mode 100755 index 0000000000000000000000000000000000000000..6eb0004ce3544f9973ddbd5a2c450fc0e1a354b1 GIT binary patch literal 3003 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 literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/classic/d.png b/src/static/jquery/jquery-jstree/themes/classic/d.png new file mode 100755 index 0000000000000000000000000000000000000000..275daeca2d6ae2ba9cf59bd23a194d13a35a825d GIT binary patch literal 7535 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 FV1ky2eG>ox literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/classic/dot_for_ie.gif b/src/static/jquery/jquery-jstree/themes/classic/dot_for_ie.gif new file mode 100755 index 0000000000000000000000000000000000000000..c0cc5fda7cfb9539720de442a3caca9c9a3fc4cb GIT binary patch literal 43 vcmZ?wbhEHbWMW`qXkcKFla>7c|G(l-7DfgJMg|=QAOOiQFfqBrF<1it%E1S( literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/classic/style.css b/src/static/jquery/jquery-jstree/themes/classic/style.css new file mode 100755 index 0000000..0351b4c --- /dev/null +++ b/src/static/jquery/jquery-jstree/themes/classic/style.css @@ -0,0 +1,77 @@ +/* + * jsTree classic theme 1.0 + * Supported features: dots/no-dots, icons/no-icons, focused, loading + * Supported plugins: ui (hovered, clicked), checkbox, contextmenu, search + */ + +.jstree-classic li, +.jstree-classic ins { background-image:url("d.png"); background-repeat:no-repeat; background-color:transparent; } +.jstree-classic li { background-position:-90px 0; background-repeat:repeat-y; } +.jstree-classic li.jstree-last { background:transparent; } +.jstree-classic .jstree-open > ins { background-position:-72px 0; } +.jstree-classic .jstree-closed > ins { background-position:-54px 0; } +.jstree-classic .jstree-leaf > ins { background-position:-36px 0; } + +.jstree-classic .jstree-hovered { background:#e7f4f9; border:1px solid #e7f4f9; padding:0 2px 0 1px; } +.jstree-classic .jstree-clicked { background:navy; border:1px solid navy; padding:0 2px 0 1px; color:white; } +.jstree-classic a .jstree-icon { background-position:-56px -19px; } +.jstree-classic .jstree-open > a .jstree-icon { background-position:-56px -36px; } +.jstree-classic a.jstree-loading .jstree-icon { background:url("throbber.gif") center center no-repeat !important; } + +.jstree-classic.jstree-focused { background:white; } + +.jstree-classic .jstree-no-dots li, +.jstree-classic .jstree-no-dots .jstree-leaf > ins { background:transparent; } +.jstree-classic .jstree-no-dots .jstree-open > ins { background-position:-18px 0; } +.jstree-classic .jstree-no-dots .jstree-closed > ins { background-position:0 0; } + +.jstree-classic .jstree-no-icons a .jstree-icon { display:none; } + +.jstree-classic .jstree-search { font-style:italic; } + +.jstree-classic .jstree-no-icons .jstree-checkbox { display:inline-block; } +.jstree-classic .jstree-no-checkboxes .jstree-checkbox { display:none !important; } +.jstree-classic .jstree-checked > a > .jstree-checkbox { background-position:-38px -19px; } +.jstree-classic .jstree-unchecked > a > .jstree-checkbox { background-position:-2px -19px; } +.jstree-classic .jstree-undetermined > a > .jstree-checkbox { background-position:-20px -19px; } +.jstree-classic .jstree-checked > a > .jstree-checkbox:hover { background-position:-38px -37px; } +.jstree-classic .jstree-unchecked > a > .jstree-checkbox:hover { background-position:-2px -37px; } +.jstree-classic .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-20px -37px; } + +#vakata-dragged.jstree-classic ins { background:transparent !important; } +#vakata-dragged.jstree-classic .jstree-ok { background:url("d.png") -2px -53px no-repeat !important; } +#vakata-dragged.jstree-classic .jstree-invalid { background:url("d.png") -18px -53px no-repeat !important; } +#jstree-marker.jstree-classic { background:url("d.png") -41px -57px no-repeat !important; text-indent:-100px; } + +.jstree-classic a.jstree-search { color:aqua; } +.jstree-classic .jstree-locked a { color:silver; cursor:default; } + +#vakata-contextmenu.jstree-classic-context, +#vakata-contextmenu.jstree-classic-context li ul { background:#f0f0f0; border:1px solid #979797; -moz-box-shadow: 1px 1px 2px #999; -webkit-box-shadow: 1px 1px 2px #999; box-shadow: 1px 1px 2px #999; } +#vakata-contextmenu.jstree-classic-context li { } +#vakata-contextmenu.jstree-classic-context a { color:black; } +#vakata-contextmenu.jstree-classic-context a:hover, +#vakata-contextmenu.jstree-classic-context .vakata-hover > a { padding:0 5px; background:#e8eff7; border:1px solid #aecff7; color:black; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; } +#vakata-contextmenu.jstree-classic-context li.jstree-contextmenu-disabled a, +#vakata-contextmenu.jstree-classic-context li.jstree-contextmenu-disabled a:hover { color:silver; background:transparent; border:0; padding:1px 4px; } +#vakata-contextmenu.jstree-classic-context li.vakata-separator { background:white; border-top:1px solid #e0e0e0; margin:0; } +#vakata-contextmenu.jstree-classic-context li ul { margin-left:-4px; } + +/* IE6 BEGIN */ +.jstree-classic li, +.jstree-classic ins, +#vakata-dragged.jstree-classic .jstree-invalid, +#vakata-dragged.jstree-classic .jstree-ok, +#jstree-marker.jstree-classic { _background-image:url("d.gif"); } +.jstree-classic .jstree-open ins { _background-position:-72px 0; } +.jstree-classic .jstree-closed ins { _background-position:-54px 0; } +.jstree-classic .jstree-leaf ins { _background-position:-36px 0; } +.jstree-classic .jstree-open a ins.jstree-icon { _background-position:-56px -36px; } +.jstree-classic .jstree-closed a ins.jstree-icon { _background-position:-56px -19px; } +.jstree-classic .jstree-leaf a ins.jstree-icon { _background-position:-56px -19px; } +#vakata-contextmenu.jstree-classic-context ins { _display:none; } +#vakata-contextmenu.jstree-classic-context li { _zoom:1; } +.jstree-classic .jstree-undetermined a .jstree-checkbox { _background-position:-20px -19px; } +.jstree-classic .jstree-checked a .jstree-checkbox { _background-position:-38px -19px; } +.jstree-classic .jstree-unchecked a .jstree-checkbox { _background-position:-2px -19px; } +/* IE6 END */ \ No newline at end of file diff --git a/src/static/jquery/jquery-jstree/themes/classic/throbber.gif b/src/static/jquery/jquery-jstree/themes/classic/throbber.gif new file mode 100755 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 GIT binary patch literal 1849 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 EAHN$8j{pDw literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/default-rtl/d.gif b/src/static/jquery/jquery-jstree/themes/default-rtl/d.gif new file mode 100755 index 0000000000000000000000000000000000000000..d85aba049b5c45649fcbb889a3765c39f3a3678a GIT binary patch literal 2872 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 Wyk?VI+|VR%xy)xy^O_GNAOJf<b&a<G literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/default-rtl/d.png b/src/static/jquery/jquery-jstree/themes/default-rtl/d.png new file mode 100755 index 0000000000000000000000000000000000000000..5179cf64e4adc0a09bf0d0e321cf5665d722f5a3 GIT binary patch literal 7459 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 literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/default-rtl/dots.gif b/src/static/jquery/jquery-jstree/themes/default-rtl/dots.gif new file mode 100755 index 0000000000000000000000000000000000000000..00433648c0769d3b473e6c972e6314f16e5a29f6 GIT binary patch literal 132 zcmZ?wbhEHb6k^C>XkcKFm6iVg|G(l-7DfgJMg|=QAOOiQFh%$DujG2o@7!&2t}F81 zi%)NALp7pQE0R)nt;u<`&t1p+tMlofyEoVVvS#&m4*XdBM8(|u%G$3jZi&HJrDaFc ka&IroI(@dv{ej`poLAGXzuGqAZ(00B0V}?F8Vn590H|{~1^@s6 literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/default-rtl/style.css b/src/static/jquery/jquery-jstree/themes/default-rtl/style.css new file mode 100755 index 0000000..1343cf3 --- /dev/null +++ b/src/static/jquery/jquery-jstree/themes/default-rtl/style.css @@ -0,0 +1,84 @@ +/* + * jsTree default-rtl theme 1.0 + * Supported features: dots/no-dots, icons/no-icons, focused, loading + * Supported plugins: ui (hovered, clicked), checkbox, contextmenu, search + */ + +.jstree-default-rtl li, +.jstree-default-rtl ins { background-image:url("d.png"); background-repeat:no-repeat; background-color:transparent; } +.jstree-default-rtl li { background-position:-90px 0; background-repeat:repeat-y; } +.jstree-default-rtl li.jstree-last { background:transparent; } +.jstree-default-rtl .jstree-open > ins { background-position:-72px 0; } +.jstree-default-rtl .jstree-closed > ins { background-position:-54px 0; } +.jstree-default-rtl .jstree-leaf > ins { background-position:-36px 0; } + +.jstree-default-rtl .jstree-hovered { background:#e7f4f9; border:1px solid #d8f0fa; padding:0 2px 0 1px; } +.jstree-default-rtl .jstree-clicked { background:#beebff; border:1px solid #99defd; padding:0 2px 0 1px; } +.jstree-default-rtl a .jstree-icon { background-position:-56px -19px; } +.jstree-default-rtl a.jstree-loading .jstree-icon { background:url("throbber.gif") center center no-repeat !important; } + +.jstree-default-rtl.jstree-focused { background:#ffffee; } + +.jstree-default-rtl .jstree-no-dots li, +.jstree-default-rtl .jstree-no-dots .jstree-leaf > ins { background:transparent; } +.jstree-default-rtl .jstree-no-dots .jstree-open > ins { background-position:-18px 0; } +.jstree-default-rtl .jstree-no-dots .jstree-closed > ins { background-position:0 0; } + +.jstree-default-rtl .jstree-no-icons a .jstree-icon { display:none; } + +.jstree-default-rtl .jstree-search { font-style:italic; } + +.jstree-default-rtl .jstree-no-icons .jstree-checkbox { display:inline-block; } +.jstree-default-rtl .jstree-no-checkboxes .jstree-checkbox { display:none !important; } +.jstree-default-rtl .jstree-checked > a > .jstree-checkbox { background-position:-38px -19px; } +.jstree-default-rtl .jstree-unchecked > a > .jstree-checkbox { background-position:-2px -19px; } +.jstree-default-rtl .jstree-undetermined > a > .jstree-checkbox { background-position:-20px -19px; } +.jstree-default-rtl .jstree-checked > a > .jstree-checkbox:hover { background-position:-38px -37px; } +.jstree-default-rtl .jstree-unchecked > a > .jstree-checkbox:hover { background-position:-2px -37px; } +.jstree-default-rtl .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-20px -37px; } + +#vakata-dragged.jstree-default-rtl ins { background:transparent !important; } +#vakata-dragged.jstree-default-rtl .jstree-ok { background:url("d.png") -2px -53px no-repeat !important; } +#vakata-dragged.jstree-default-rtl .jstree-invalid { background:url("d.png") -18px -53px no-repeat !important; } +#jstree-marker.jstree-default-rtl { background:url("d.png") -41px -57px no-repeat !important; text-indent:-100px; } + +.jstree-default-rtl a.jstree-search { color:aqua; } +.jstree-default-rtl .jstree-locked a { color:silver; cursor:default; } + +#vakata-contextmenu.jstree-default-rtl-context, +#vakata-contextmenu.jstree-default-rtl-context li ul { background:#f0f0f0; border:1px solid #979797; -moz-box-shadow: 1px 1px 2px #999; -webkit-box-shadow: 1px 1px 2px #999; box-shadow: 1px 1px 2px #999; } +#vakata-contextmenu.jstree-default-rtl-context li { } +#vakata-contextmenu.jstree-default-rtl-context a { color:black; } +#vakata-contextmenu.jstree-default-rtl-context a:hover, +#vakata-contextmenu.jstree-default-rtl-context .vakata-hover > a { padding:0 5px; background:#e8eff7; border:1px solid #aecff7; color:black; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; } +#vakata-contextmenu.jstree-default-rtl-context li.jstree-contextmenu-disabled a, +#vakata-contextmenu.jstree-default-rtl-context li.jstree-contextmenu-disabled a:hover { color:silver; background:transparent; border:0; padding:1px 4px; } +#vakata-contextmenu.jstree-default-rtl-context li.vakata-separator { background:white; border-top:1px solid #e0e0e0; margin:0; } +#vakata-contextmenu.jstree-default-rtl-context li ul { margin-left:-4px; } + +/* IE6 BEGIN */ +.jstree-default-rtl li, +.jstree-default-rtl ins, +#vakata-dragged.jstree-default-rtl .jstree-invalid, +#vakata-dragged.jstree-default-rtl .jstree-ok, +#jstree-marker.jstree-default-rtl { _background-image:url("d.gif"); } +.jstree-default-rtl .jstree-open ins { _background-position:-72px 0; } +.jstree-default-rtl .jstree-closed ins { _background-position:-54px 0; } +.jstree-default-rtl .jstree-leaf ins { _background-position:-36px 0; } +.jstree-default-rtl a ins.jstree-icon { _background-position:-56px -19px; } +#vakata-contextmenu.jstree-default-rtl-context ins { _display:none; } +#vakata-contextmenu.jstree-default-rtl-context li { _zoom:1; } +.jstree-default-rtl .jstree-undetermined a .jstree-checkbox { _background-position:-18px -19px; } +.jstree-default-rtl .jstree-checked a .jstree-checkbox { _background-position:-36px -19px; } +.jstree-default-rtl .jstree-unchecked a .jstree-checkbox { _background-position:0px -19px; } +/* IE6 END */ + +/* RTL part */ +.jstree-default-rtl .jstree-hovered, .jstree-default-rtl .jstree-clicked { padding:0 1px 0 2px; } +.jstree-default-rtl li { background-image:url("dots.gif"); background-position: 100% 0px; } +.jstree-default-rtl .jstree-checked > a > .jstree-checkbox { background-position:-36px -19px; margin-left:2px; } +.jstree-default-rtl .jstree-unchecked > a > .jstree-checkbox { background-position:0px -19px; margin-left:2px; } +.jstree-default-rtl .jstree-undetermined > a > .jstree-checkbox { background-position:-18px -19px; margin-left:2px; } +.jstree-default-rtl .jstree-checked > a > .jstree-checkbox:hover { background-position:-36px -37px; } +.jstree-default-rtl .jstree-unchecked > a > .jstree-checkbox:hover { background-position:0px -37px; } +.jstree-default-rtl .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-18px -37px; } \ No newline at end of file diff --git a/src/static/jquery/jquery-jstree/themes/default-rtl/throbber.gif b/src/static/jquery/jquery-jstree/themes/default-rtl/throbber.gif new file mode 100755 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 GIT binary patch literal 1849 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 EAHN$8j{pDw literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/default/d.gif b/src/static/jquery/jquery-jstree/themes/default/d.gif new file mode 100755 index 0000000000000000000000000000000000000000..0e958d38716d93d4050a993398dec77490f836c7 GIT binary patch literal 2944 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 literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/default/d.png b/src/static/jquery/jquery-jstree/themes/default/d.png new file mode 100755 index 0000000000000000000000000000000000000000..8540175a04b0cd303e3966d1727f30ee9b8a7254 GIT binary patch literal 7635 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 B#iIZK literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-jstree/themes/default/style.css b/src/static/jquery/jquery-jstree/themes/default/style.css new file mode 100755 index 0000000..7ef6a04 --- /dev/null +++ b/src/static/jquery/jquery-jstree/themes/default/style.css @@ -0,0 +1,74 @@ +/* + * jsTree default theme 1.0 + * Supported features: dots/no-dots, icons/no-icons, focused, loading + * Supported plugins: ui (hovered, clicked), checkbox, contextmenu, search + */ + +.jstree-default li, +.jstree-default ins { background-image:url("d.png"); background-repeat:no-repeat; background-color:transparent; } +.jstree-default li { background-position:-90px 0; background-repeat:repeat-y; } +.jstree-default li.jstree-last { background:transparent; } +.jstree-default .jstree-open > ins { background-position:-72px 0; } +.jstree-default .jstree-closed > ins { background-position:-54px 0; } +.jstree-default .jstree-leaf > ins { background-position:-36px 0; } + +.jstree-default .jstree-hovered { background:#e7f4f9; border:1px solid #d8f0fa; padding:0 2px 0 1px; } +.jstree-default .jstree-clicked { background:#beebff; border:1px solid #99defd; padding:0 2px 0 1px; } +.jstree-default a .jstree-icon { background-position:-56px -19px; } +.jstree-default a.jstree-loading .jstree-icon { background:url("throbber.gif") center center no-repeat !important; } + +.jstree-default.jstree-focused { background:#ffffee; } + +.jstree-default .jstree-no-dots li, +.jstree-default .jstree-no-dots .jstree-leaf > ins { background:transparent; } +.jstree-default .jstree-no-dots .jstree-open > ins { background-position:-18px 0; } +.jstree-default .jstree-no-dots .jstree-closed > ins { background-position:0 0; } + +.jstree-default .jstree-no-icons a .jstree-icon { display:none; } + +.jstree-default .jstree-search { font-style:italic; } + +.jstree-default .jstree-no-icons .jstree-checkbox { display:inline-block; } +.jstree-default .jstree-no-checkboxes .jstree-checkbox { display:none !important; } +.jstree-default .jstree-checked > a > .jstree-checkbox { background-position:-38px -19px; } +.jstree-default .jstree-unchecked > a > .jstree-checkbox { background-position:-2px -19px; } +.jstree-default .jstree-undetermined > a > .jstree-checkbox { background-position:-20px -19px; } +.jstree-default .jstree-checked > a > .jstree-checkbox:hover { background-position:-38px -37px; } +.jstree-default .jstree-unchecked > a > .jstree-checkbox:hover { background-position:-2px -37px; } +.jstree-default .jstree-undetermined > a > .jstree-checkbox:hover { background-position:-20px -37px; } + +#vakata-dragged.jstree-default ins { background:transparent !important; } +#vakata-dragged.jstree-default .jstree-ok { background:url("d.png") -2px -53px no-repeat !important; } +#vakata-dragged.jstree-default .jstree-invalid { background:url("d.png") -18px -53px no-repeat !important; } +#jstree-marker.jstree-default { background:url("d.png") -41px -57px no-repeat !important; text-indent:-100px; } + +.jstree-default a.jstree-search { color:aqua; } +.jstree-default .jstree-locked a { color:silver; cursor:default; } + +#vakata-contextmenu.jstree-default-context, +#vakata-contextmenu.jstree-default-context li ul { background:#f0f0f0; border:1px solid #979797; -moz-box-shadow: 1px 1px 2px #999; -webkit-box-shadow: 1px 1px 2px #999; box-shadow: 1px 1px 2px #999; } +#vakata-contextmenu.jstree-default-context li { } +#vakata-contextmenu.jstree-default-context a { color:black; } +#vakata-contextmenu.jstree-default-context a:hover, +#vakata-contextmenu.jstree-default-context .vakata-hover > a { padding:0 5px; background:#e8eff7; border:1px solid #aecff7; color:black; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; } +#vakata-contextmenu.jstree-default-context li.jstree-contextmenu-disabled a, +#vakata-contextmenu.jstree-default-context li.jstree-contextmenu-disabled a:hover { color:silver; background:transparent; border:0; padding:1px 4px; } +#vakata-contextmenu.jstree-default-context li.vakata-separator { background:white; border-top:1px solid #e0e0e0; margin:0; } +#vakata-contextmenu.jstree-default-context li ul { margin-left:-4px; } + +/* IE6 BEGIN */ +.jstree-default li, +.jstree-default ins, +#vakata-dragged.jstree-default .jstree-invalid, +#vakata-dragged.jstree-default .jstree-ok, +#jstree-marker.jstree-default { _background-image:url("d.gif"); } +.jstree-default .jstree-open ins { _background-position:-72px 0; } +.jstree-default .jstree-closed ins { _background-position:-54px 0; } +.jstree-default .jstree-leaf ins { _background-position:-36px 0; } +.jstree-default a ins.jstree-icon { _background-position:-56px -19px; } +#vakata-contextmenu.jstree-default-context ins { _display:none; } +#vakata-contextmenu.jstree-default-context li { _zoom:1; } +.jstree-default .jstree-undetermined a .jstree-checkbox { _background-position:-20px -19px; } +.jstree-default .jstree-checked a .jstree-checkbox { _background-position:-38px -19px; } +.jstree-default .jstree-unchecked a .jstree-checkbox { _background-position:-2px -19px; } +/* IE6 END */ \ No newline at end of file diff --git a/src/static/jquery/jquery-jstree/themes/default/throbber.gif b/src/static/jquery/jquery-jstree/themes/default/throbber.gif new file mode 100755 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 GIT binary patch literal 1849 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 EAHN$8j{pDw literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-transform/README.md b/src/static/jquery/jquery-transform/README.md new file mode 100755 index 0000000..80d26a3 --- /dev/null +++ b/src/static/jquery/jquery-transform/README.md @@ -0,0 +1,81 @@ +jquery.transform2d.js adds 2d transform capabilities to jQuery `css()` and `animate()` functions. + +Usage: +====== + +Set transform with a string +--------------------------- + + $(elem).css('transform', 'translate(50px, 30px) rotate(25deg) scale(2,.5) skew(-35deg)'); + $(elem).animate({transform: 'translateY(-100px) rotate(1rad) scaleX(2) skewY(42deg)'}); + +You can use the following list of transform components: + +- `translateX(<number>px)` +- `translateY(<number>px)` +- combined: `translate(<number>px, <number>px)` *the second number is optional and defaults to 0* +- `scaleX(<number>)` +- `scaleY(<number>)` +- combined: `scale(<number>, <number>)` *the second number is optional and defaults to the value of the first one* +- `rotate(<angle>)` *units for angles are *rad* (default), *deg* or *grad*.* +- `skew(<angle>)` +- `skew(<angle>)` +- combined: `skew(<angle>, <angle>)` *the second angle is optional and defaults to 0* +- `matrix(<number>, <number>, <number>, <number>, <number>, <number>)`* + +*`matrix` gives you more control about the resulting transformation, using a [matrix construction set](http://www.useragentman.com/matrix/). +When using it in animations however, it makes it impossible to predict how the current and target transformations are going to be interpolated; there is no way to tell whether elements are going to rotate clockwise or anti-clockwise for instance. + +Get transform +------------- + +returns a computed transform matrix. + + $(elem).css('transform') == 'matrix(0,1,-1,0,100,50)'; + +Set transform-origin with a string +---------------------------------- + + $(elem).css('transform-origin', 'top left'); + $(elem).animate({transformOrigin: 'top left'}); + +Get transform-origin +-------------------- + + $(elem).css('transform-origin') + +Usually the returned units are in pixels however Firefox and IE-less-than-9 may return percentages. + +Relative animations +------------------- + +Relative animations are possible by prepending "+=" at the end of the transform string. + + $(elem).css('transform', 'rotate(45deg)'); + // using the following syntax, elem will always rotate 90deg anticlockwise + $(elem).animate({transform: '+=rotate(-90deg)'}); + +Limitations: +============ + +- requires jQuery 1.4.3+, +- units must be px or deg (TODO) + + +Potential Translation Issues in IE 8 and Below +---------------------------------------------- + +Since translate and transform-origin is unavailable in IE 8 and below, we have to emulate it using `top` and `left` properties of the element style. This library tries to emulate translate and transform-origin using position relative to reposition the element. While this closely emulates the expected behavior, if the element is already positioned, the existing position is respected as much as possible. + +- absolute positioned elements are repositioned using marginTop and marginLeft to avoid conclicts +- inline styles for top and left (or marginTop and marginLeft) will be overwritten +- changes in the height or width of the element will not be dynamically reflected +- IE 7 and below incorrectly alter the offset height and width of the element to match the transformed offset height and width + + +License +======= + +Dual licensed under GPL and MIT licenses. + +Copyright (c) 2010 [Louis-Rémi Babé](http://twitter.com/louis_remi). \ No newline at end of file diff --git a/src/static/jquery/jquery-transform/jquery.transform2d.js b/src/static/jquery/jquery-transform/jquery.transform2d.js new file mode 100755 index 0000000..b09085b --- /dev/null +++ b/src/static/jquery/jquery-transform/jquery.transform2d.js @@ -0,0 +1,935 @@ +/* + * transform: A jQuery cssHooks adding cross-browser 2d transform capabilities to $.fn.css() and $.fn.animate() + * + * limitations: + * - requires jQuery 1.4.3+ + * - Should you use the *translate* property, then your elements need to be absolutely positionned in a relatively positionned wrapper **or it will fail in IE678**. + * - transformOrigin is not accessible + * + * latest version and complete README available on Github: + * https://github.com/louisremi/jquery.transform.js + * + * Copyright 2011 @louis_remi + * Licensed under the MIT license. + * + * This saved you an hour of work? + * Send me music http://www.amazon.co.uk/wishlist/HNTU0468LQON + * + */ +(function( $, window, document, Math, undefined ) { +"use strict"; + +/* + * Feature tests and global variables + */ +var div = document.createElement("div"), + divStyle = div.style, + propertyName = "transform", + suffix = "Transform", + testProperties = [ + propertyName, + "O" + suffix, + "ms" + suffix, + "Webkit" + suffix, + "Moz" + suffix + ], + originSuffix = "Origin", + originPropertyCssName = propertyName + "-origin", + originPropertyName = propertyName + originSuffix, + i = testProperties.length, + supportProperty, + supportOriginProperty, + supportMatrixFilter, + supportFloat32Array = "Float32Array" in window, + propertyHook, + propertyGet, + originPropertyHook, + originPropertyGet, + originPropertySet, + rMatrix = /Matrix([^)]*)/, + rAffine = /^\s*matrix\(\s*1\s*,\s*0\s*,\s*0\s*,\s*1\s*(?:,\s*0(?:px)?\s*){2}\)\s*$/, + runits = /^([\+\-]=)?(-?[\d+\.\-]+)([a-z]+|%)?(.*?)$/i, + rperc = /%/, + _parseFloat = parseFloat, + _relative = "relative", + _static = "static", + _position = "position", + _translate = "translate", + _rotate = "rotate", + _scale = "scale", + _skew = "skew", + _matrix = "matrix"; + +// test different vendor prefixes of this property +while ( i-- ) { + if ( testProperties[i] in divStyle ) { + $.support[propertyName] = supportProperty = testProperties[i]; + continue; + } +} +supportOriginProperty = supportProperty + originSuffix; + +// IE678 alternative +if ( !supportProperty ) { + $.support.matrixFilter = supportMatrixFilter = divStyle.filter === ""; +} + +// px isn"t the default unit of this property +$.cssNumber[propertyName] = true; +$.cssNumber[originPropertyName] = true; + +/* + * fn.css() hooks + */ +if ( supportProperty && supportProperty != propertyName ) { + // Modern browsers can use jQuery.cssProps as a basic hook + $.cssProps[propertyName] = supportProperty; + $.cssProps[originPropertyName] = supportOriginProperty; + + // Firefox needs a complete hook because it stuffs matrix with "px" + if ( supportProperty == "Moz" + suffix ) { + propertyHook = { + get: function( elem, computed ) { + return (computed ? + // remove "px" from the computed matrix + $.css( elem, supportProperty ).split("px").join(""): + elem.style[supportProperty] + ); + }, + set: function( elem, value ) { + // add "px" to matrices + elem.style[supportProperty] = /matrix\([^)p]*\)/.test(value) ? + value.replace(/matrix((?:[^,]*,){4})([^,]*),([^)]*)/, _matrix+"$1$2px,$3px"): + value; + } + }; + /* Fix two jQuery bugs still present in 1.5.1 + * - rupper is incompatible with IE9, see http://jqbug.com/8346 + * - jQuery.css is not really jQuery.cssProps aware, see http://jqbug.com/8402 + */ + } else if ( /^1\.[0-5](?:\.|$)/.test($.fn.jquery) ) { + propertyHook = { + get: function( elem, computed ) { + return (computed ? + $.css( elem, supportProperty.replace(/^ms/, "Ms") ): + elem.style[supportProperty] + ); + } + }; + } + /* TODO: leverage hardware acceleration of 3d transform in Webkit only + else if ( supportProperty == "Webkit" + suffix && support3dTransform ) { + propertyHook = { + set: function( elem, value ) { + elem.style[supportProperty] = + value.replace(); + } + } + }*/ + +} else if ( supportMatrixFilter ) { + var translateX = suffix + "-translate-x", + translateY = suffix + "-translate-y" + ; + + propertyHook = { + get: function( elem, computed ) { + var $elem = $(elem), + elemStyle = ( computed && elem.currentStyle ? elem.currentStyle : elem.style ), + matrix; + + if ( elemStyle && rMatrix.test( elemStyle.filter ) ) { + matrix = RegExp.$1.split(","); + matrix = [ + matrix[0].split("=")[1], + matrix[2].split("=")[1], + matrix[1].split("=")[1], + matrix[3].split("=")[1] + ]; + } else { + matrix = [1,0,0,1]; + } + matrix[4] = $elem.data(translateX) || 0; + matrix[5] = $elem.data(translateY) || 0; + return _matrix+"(" + matrix + ")"; + }, + set: function( elem, value, animate ) { + var $elem = $(elem), + elemStyle = elem.style, + currentStyle, + Matrix, + filter, + centerOrigin; + + if ( !animate ) { + elemStyle.zoom = 1; + } + + value = matrix(value); + + // rotate, scale and skew + //if ( !animate || animate.M ) { + Matrix = [ + "Matrix("+ + "M11="+value[0], + "M12="+value[2], + "M21="+value[1], + "M22="+value[3], + "SizingMethod='auto expand'" + ].join(); + filter = ( currentStyle = elem.currentStyle ) && currentStyle.filter || elemStyle.filter || ""; + + elemStyle.filter = rMatrix.test(filter) ? + filter.replace(rMatrix, Matrix) : + filter + " progid:DXImageTransform.Microsoft." + Matrix + ")"; + + // remember the translation for later + $elem.data(translateX, value[4]); + $elem.data(translateY, value[5]); + + // fake the origin + originPropertySet(elem); + //} + } + }; + + + // handle transform-origin + originPropertyHook = { + get: function( elem, computed ) { + // TODO: handle computed + var $elem = $(elem), + origin = $elem.data(originPropertyCssName) + ; + + // try to look it up in the existing CSS + if (!origin) { + // ordered backwards because we loop backwards + var testProperties = [ + //"-o-" + originPropertyCssName, + //"-moz-" + originPropertyCssName, + //"-webkit-" + originPropertyCssName, + "-ms-" + originPropertyCssName, + originPropertyCssName + ], + i = testProperties.length, + currStyle = elem.currentStyle + ; + + // loop backwards + while ( i-- ) { + if ( testProperties[i] in currStyle ) { + origin = currStyle[testProperties[i]]; + $elem.data(originPropertyCssName, origin); + break; + } + } + } + + // otherwise use the default + if (!origin) { + origin = "50% 50%"; // use percentages instead of keywords + $elem.data(originPropertyCssName, origin); + } + + return origin; + }, + + set: function( elem, value ) { + var $elem = $(elem), + transform = propertyGet(elem) + ; + + // save it if there"s a new value + // NOTE: undefined means we"re trying to set a transform and need to handle translation + if (value !== undefined) { $elem.data(originPropertyCssName, value) } + + // if there"s no transform, don"t do anything + if (!transform) { + return; + } + + // convert the transform into a useful array + transform = matrix(transform); + + // fake the origin with some fancy css + // we also fake the translation here + var tx = transform[4] || $elem.data(translateX) || 0, + ty = transform[5] || $elem.data(translateY) || 0, + origin = keywordsToPerc(value === undefined ? originPropertyGet(elem) : value).split(" ") + ; + + // calculate and return the correct size + // find the real size of the original object + // (IE reports the size of the transformed object) + // the ratio is basically the transformed size of 1x1 object + var ratio = transformOffset(transform, 1, 1), + width = $elem.outerWidth() / ratio.width, + height = $elem.outerHeight() / ratio.height, + i = 2, matches + ; + + // turn the origin into unitless pixels + while (i--) { + matches = origin[i].match(runits); + if (matches[3] !== "px") { + origin[i] = matches[3] === "%" ? percentageToPx(origin[i], elem, i, ratio, width, height) : toPx(origin[i], elem); + } else { + origin[i] = _parseFloat(origin[i]); + } + } + + // find the origin offset + var toCenter = transformVector(transform, origin[0], origin[1]), + fromCenter = transformVector(transform, 0, 0), + offset = { + top: fromCenter[1] - (toCenter[1] - origin[1]), + left: fromCenter[0] - (toCenter[0] - origin[0]) + }, + sides = transformSides(transform, width, height) + ; + + // apply the css + var cssPosition = $elem.css(_position), + usePosition = cssPosition === _relative || cssPosition === _static || $.transform.centerOrigin === _position, + css = {}, + propTop = usePosition ? "top" : "marginTop" , + propLeft = usePosition ? "left" : "marginLeft" , + top = offset.top + ty + sides.top, + left = offset.left + tx + sides.left, + cssTop = 0, + cssLeft = 0, + currentTop, + currentLeft, + elemStyle = elem.style, + currStyle = elem.currentStyle + ; + + if (cssPosition === _static) { + css[_position] = _relative; + } else { + // try to respect an existing top/left if it"s in the CSS + // blank out the inline styles, we"re going to overwrite them anyway + elemStyle[propTop] = null; + elemStyle[propLeft] = null; + + // look up the CSS styles + currentTop = currStyle[propTop]; + currentLeft = currStyle[propLeft]; + + // if they"re not "auto" then use those + // TODO: handle non-pixel units and percentages + if (currentTop !== "auto") { cssTop = parseInt(currentTop, 10); } + if (currentLeft !== "auto") { cssLeft = parseInt(currentLeft, 10); } + } + + css[propTop] = top + cssTop; + css[propLeft] = left + cssLeft; + $elem.css(css); + } + }; +} +// populate jQuery.cssHooks with the appropriate hook if necessary +if ( propertyHook ) { + $.cssHooks[propertyName] = propertyHook; +} +if (originPropertyHook) { + $.cssHooks[originPropertyName] = originPropertyHook; +} +// we need a unique setter for the animation logic +propertyGet = propertyHook && propertyHook.get || $.css; +originPropertyGet = originPropertyHook && originPropertyHook.get || $.css; +originPropertySet = originPropertyHook && originPropertyHook.set || $.css; + +/* + * fn.animate() hooks + */ +$.fx.step.transform = function( fx ) { + var elem = fx.elem, + start = fx.start, + end = fx.end, + pos = fx.pos, + transform = "", i, startVal, endVal, unit; + + // fx.end and fx.start need to be converted to interpolation lists + if ( !start || typeof start === "string" ) { + + // the following block can be commented out with jQuery 1.5.1+, see #7912 + if ( !start ) { + start = propertyGet( elem, supportProperty ); + } + + // force layout only once per animation + if ( supportMatrixFilter ) { + elem.style.zoom = 1; + } + + // replace "+=" in relative animations (-= is meaningless with transforms) + // TODO: this is not how people would expect this to work. it makes more sense to support something like: rotate(+=45deg) translate(-=10px, +=15px) + end = end.split("+=").join(start); + + // parse both transform to generate interpolation list of same length + return $.extend( fx, interpolationList( start, end ) ); + } + + i = start.length; + + // interpolate functions of the list one by one + while ( i-- ) { + startVal = start[i]; + endVal = end[i]; + unit = +false; + + switch ( startVal[0] ) { + + case _translate: + unit = "px"; + case _scale: + unit || ( unit = " "); + case _skew: + unit || ( unit = "rad" ); + + transform = startVal[0] + "(" + + (startVal[1][0] + (endVal[1][0] - startVal[1][0]) * pos) + unit +","+ + (startVal[1][1] + (endVal[1][1] - startVal[1][1]) * pos) + unit + ")"+ + transform; + break; + + case _rotate: + transform = _rotate + "(" + + (startVal[1] + (endVal[1] - startVal[1]) * pos) +"rad)"+ + transform; + break; + } + } + + fx.origin && ( transform = fx.origin + transform ); + + propertyHook && propertyHook.set ? + propertyHook.set( elem, transform, +true ): + elem.style[supportProperty] = transform; +}; + + +/* + * fn.animate() hooks for transform-origin + */ +$.fx.step.transformOrigin = function( fx ) { + var elem = fx.elem, + start, + value = [], + pos = fx.pos, + i = 2, + relativeUnit, + unit = [], + startVal, + endVal, + ratio; + + if ( !fx.state ) { + // correct for keywords + startVal = keywordsToPerc(originPropertyGet( elem, supportOriginProperty )).split(" "); + endVal = keywordsToPerc(fx.end).split(" "); + + // TODO: use a unit conversion library! + while(i--) { + // parse the end value for the +=/-= prefix + relativeUnit = endVal[i].match(runits)[1]; + + // get the height/width ratio for IE + if ( supportMatrixFilter) { + ratio = transformOffset(matrix(propertyGet(elem)), 1, 1); + } + + // convert the start value + startVal[i] = convertOriginValue(startVal[i], elem, i, ratio); + endVal[i] = convertOriginValue(endVal[i], elem, i, ratio); + + // handle +=/-= prefixes + if (relativeUnit) { + endVal[i] = startVal[i] + (relativeUnit === "+=" ? 1 : -1) * endVal[i] + } + } + i = 2; + + // record the doctored values on the fx object + fx.start = startVal; + fx.end = endVal; + fx.unit = "px"; + } + + // read the doctored values from the fx object + start = fx.start; + + // animate the values + while (i--) { + value[i] = (start[i] + (fx.end[i] - start[i]) * pos) + fx.unit; + } + value = value.join(" "); + + // set it and forget it + supportMatrixFilter ? originPropertySet( elem, value ) : elem.style[supportOriginProperty] = value; +} + +// convert a value for the origin animation, accounting for +=/-= +function convertOriginValue(value, elem, useHeight, useRatio) { + var matches = value.match(runits); + value = matches[2] + matches[3]; + if (matches[3] !== "px") { + value = matches[3] === "%" ? percentageToPx(value, elem, useHeight, useRatio) : toPx(value, elem); + } else { + value = _parseFloat(value); + } + return value; +} + +/* + * Utility functions + */ + +// keywords +function keywordsToPerc (value) { + var _top = "top", + _right = "right", + _bottom = "bottom", + _center = "center", + _left = "left", + _space = " ", + _0 = "0", + _50 = "50%", + _100 = "100%", + split, + i = 2; + + switch (value) { + case _top + _space + _left: // no break + case _left + _space + _top: + value = _0 + _space + _0; + break; + case _top: // no break + case _top + _space + _center: // no break + case _center + _space + _top: + value = _50 + _space + _0; + break; + case _right + _space + _top: // no break + case _top + _space + _right: + value = _100 + _space + _0; + break; + case _left: // no break + case _left + _space + _center: // no break + case _center + _space + _left: + value = _0 + _space + _50; + break; + case _right: // no break + case _right + _space + _center: // no break + case _center + _space + _right: + value = _100 + _space + _50; + break; + case _bottom + _space + _left: // no break + case _left + _space + _bottom: + value = _0 + _space + _100; + break; + case _bottom: // no break + case _bottom + _space + _center: // no break + case _center + _space + _bottom: + value = _50 + _space + _100; + break; + case _bottom + _space + _right: // no break + case _right + _space + _bottom: + value = _100 + _space + _100; + break; + case _center: // no break + case _center + _space + _center: + value = _50 + _space + _50; + break; + default: + // handle mixed keywords and other units + // TODO: this isn"t 100% to spec. mixed units and keywords require the keyword in the correct position + split = value.split(_space); + if (split[1] === undefined) { split[1] = split[0]; } + while(i--) { + switch(split[i]) { + case _left: // no break + case _top: + split[i] = _0; + break; + case _right: // no break + case _bottom: + split[i] = _100; + break; + case _center: + split[i] = _50; + } + } + value = split.join(_space); + } + return value; +} + +// convert a vector +function transformVector(a, x, y) { + return [ + a[0] * x + a[2] * y, + a[1] * x + a[3] * y + ]; +} + +// calculate the corner vectors +function transformCorners(a, x, y) { + return [ + /* tl */ transformVector(a, 0, 0), + /* bl */ transformVector(a, 0, y), + /* tr */ transformVector(a, x, 0), + /* br */ transformVector(a, x, y) + ]; +} + +// measure the length of the sides +// TODO: arrays are faster than objects (and compress better) +function transformSides(a, x, y) { + // The corners of the box + var c = transformCorners(a, x, y); + + return { + top: Math.min(c[0][1], c[2][1], c[3][1], c[1][1]), + bottom: Math.max(c[0][1], c[2][1], c[3][1], c[1][1]), + left: Math.min(c[0][0], c[2][0], c[3][0], c[1][0]), + right: Math.max(c[0][0], c[2][0], c[3][0], c[1][0]) + }; +} + +// measure the offset height and width +// TODO: arrays are faster than objects (and compress better) +function transformOffset(a, x, y) { + // The sides of the box + var s = transformSides(a, x, y); + + // return offset + return { + height: Math.abs(s.bottom - s.top), + width: Math.abs(s.right - s.left) + }; +} + +// turns a transform string into its "matrix(A,B,C,D,X,Y)" form (as an array, though) +// column-major order +function matrix( transform ) { + transform = transform.split(")"); + var trim = $.trim + , i = -1 + // last element of the array is an empty string, get rid of it + , l = transform.length -1 + , split, prop, val + , prev = supportFloat32Array ? new Float32Array(6) : [] + , curr = supportFloat32Array ? new Float32Array(6) : [] + , rslt = supportFloat32Array ? new Float32Array(6) : [1,0,0,1,0,0] + ; + + prev[0] = prev[3] = rslt[0] = rslt[3] = 1; + prev[1] = prev[2] = prev[4] = prev[5] = 0; + + // Loop through the transform properties, parse and multiply them + while ( ++i < l ) { + split = transform[i].split("("); + prop = trim(split[0]); + val = split[1]; + curr[0] = curr[3] = 1; + curr[1] = curr[2] = curr[4] = curr[5] = 0; + + switch (prop) { + case _translate+"X": + curr[4] = parseInt(val, 10); + break; + + case _translate+"Y": + curr[5] = parseInt(val, 10); + break; + + case _translate: + val = val.split(","); + curr[4] = parseInt(val[0], 10); + curr[5] = parseInt(val[1] || 0, 10); + break; + + case _rotate: + val = toRadian(val); + curr[0] = Math.cos(val); + curr[1] = Math.sin(val); + curr[2] = -curr[1]; + curr[3] = curr[0]; + break; + + case _scale+"X": + curr[0] = +val; + break; + + case _scale+"Y": + curr[3] = val; + break; + + case _scale: + val = val.split(","); + curr[0] = val[0]; + curr[3] = val.length>1 ? val[1] : val[0]; + break; + + case _skew+"X": + curr[2] = Math.tan(toRadian(val)); + break; + + case _skew+"Y": + curr[1] = Math.tan(toRadian(val)); + break; + + case _skew: + val = val.split(","); + curr[2] = Math.tan(toRadian(val[0])); + val[1] && ( curr[1] = Math.tan(toRadian(val[1])) ); + break; + + case _matrix: + val = val.split(","); + curr[0] = val[0]; + curr[1] = val[1]; + curr[2] = val[2]; + curr[3] = val[3]; + curr[4] = parseInt(val[4], 10); + curr[5] = parseInt(val[5], 10); + break; + } + + // Matrix product (array is in column-major order!) + rslt[0] = prev[0] * curr[0] + prev[2] * curr[1]; + rslt[1] = prev[1] * curr[0] + prev[3] * curr[1]; + rslt[2] = prev[0] * curr[2] + prev[2] * curr[3]; + rslt[3] = prev[1] * curr[2] + prev[3] * curr[3]; + rslt[4] = prev[0] * curr[4] + prev[2] * curr[5] + prev[4]; + rslt[5] = prev[1] * curr[4] + prev[3] * curr[5] + prev[5]; + + prev = [rslt[0],rslt[1],rslt[2],rslt[3],rslt[4],rslt[5]]; + } + return rslt; +} + +// turns a matrix into its rotate, scale and skew components +// algorithm from http://hg.mozilla.org/mozilla-central/file/7cb3e9795d04/layout/style/nsStyleAnimation.cpp +function unmatrix(matrix) { + var scaleX + , scaleY + , skew + , A = matrix[0] + , B = matrix[1] + , C = matrix[2] + , D = matrix[3] + ; + + // Make sure matrix is not singular + if ( A * D - B * C ) { + // step (3) + scaleX = Math.sqrt( A * A + B * B ); + A /= scaleX; + B /= scaleX; + // step (4) + skew = A * C + B * D; + C -= A * skew; + D -= B * skew; + // step (5) + scaleY = Math.sqrt( C * C + D * D ); + C /= scaleY; + D /= scaleY; + skew /= scaleY; + // step (6) + if ( A * D < B * C ) { + //scaleY = -scaleY; + //skew = -skew; + A = -A; + B = -B; + skew = -skew; + scaleX = -scaleX; + } + + // matrix is singular and cannot be interpolated + } else { + throw new Error("matrix is singular"); + } + + // The recomposition order is very important + // see http://hg.mozilla.org/mozilla-central/file/7cb3e9795d04/layout/style/nsStyleAnimation.cpp#l971 + return [ + [_translate, [+matrix[4], +matrix[5]]], + [_rotate, Math.atan2(B, A)], + [_skew, [Math.atan(skew), 0]], + [_scale, [scaleX, scaleY]] + ]; +} + +// build the list of transform functions to interpolate +// use the algorithm described at http://dev.w3.org/csswg/css3-2d-transforms/#animation +function interpolationList( start, end ) { + var list = { + start: [], + end: [] + }, + i = -1, l, + currStart, currEnd, currType; + + // get rid of affine transform matrix + ( start == "none" || isAffine( start ) ) && ( start = "" ); + ( end == "none" || isAffine( end ) ) && ( end = "" ); + + // if end starts with the current computed style, this is a relative animation + // store computed style as the origin, remove it from start and end + if ( start && end && !end.indexOf("matrix") && toArray( start ).join() == toArray( end.split(")")[0] ).join() ) { + list.origin = start; + start = ""; + end = end.slice( end.indexOf(")") +1 ); + } + + if ( !start && !end ) { return; } + + // start or end are affine, or list of transform functions are identical + // => functions will be interpolated individually + if ( !start || !end || functionList(start) == functionList(end) ) { + + start && ( start = start.split(")") ) && ( l = start.length ); + end && ( end = end.split(")") ) && ( l = end.length ); + + while ( ++i < l-1 ) { + start[i] && ( currStart = start[i].split("(") ); + end[i] && ( currEnd = end[i].split("(") ); + currType = $.trim( ( currStart || currEnd )[0] ); + + append( list.start, parseFunction( currType, currStart ? currStart[1] : 0 ) ); + append( list.end, parseFunction( currType, currEnd ? currEnd[1] : 0 ) ); + } + + // otherwise, functions will be composed to a single matrix + } else { + list.start = unmatrix(matrix(start)); + list.end = unmatrix(matrix(end)) + } + + return list; +} + +function parseFunction( type, value ) { + var + // default value is 1 for scale, 0 otherwise + defaultValue = +(!type.indexOf(_scale)), + // value is parsed to radian for skew, int otherwise + valueParser = !type.indexOf(_skew) ? toRadian : _parseFloat, + scaleX, + cat = type.replace( /[XY]/, "" ); + + switch ( type ) { + case _translate+"Y": + case _scale+"Y": + case _skew+"Y": + + value = [ + defaultValue, + value ? + valueParser( value ): + defaultValue + ]; + break; + + case _translate+"X": + case _translate: + case _scale+"X": + scaleX = 1; + case _scale: + case _skew+"X": + case _skew: + + value = value ? + ( value = value.split(",") ) && [ + valueParser( value[0] ), + valueParser( value.length>1 ? value[1] : type == _scale ? scaleX || value[0] : defaultValue+"" ) + ]: + [defaultValue, defaultValue]; + break; + + case _rotate: + value = value ? toRadian( value ) : 0; + break; + + case _matrix: + return unmatrix( value ? toArray(value) : [1,0,0,1,0,0] ); + break; + } + + return [[ cat, value ]]; +} + +function isAffine( matrix ) { + return rAffine.test(matrix); +} + +function functionList( transform ) { + return transform.replace(/(?:\([^)]*\))|\s/g, ""); +} + +function append( arr1, arr2, value ) { + while ( value = arr2.shift() ) { + arr1.push( value ); + } +} + +// converts an angle string in any unit to a radian Float +function toRadian(value) { + var val = _parseFloat(value), PI = Math.PI; + + // TODO: why use the tilde here? seems useless, it"s not like you"d ever want to see deg as the first character + return ~value.indexOf("deg") ? + val * (PI / 180): + ~value.indexOf("grad") ? + val * (PI / 200): + ~value.indexOf("turn") ? + val * (PI / 0.5): + val; +} + +function toPx(value, elem, prop) { + prop = prop || "left"; + var style = elem.style[prop], + inStyle = style !== undefined && style !== null, + curr = $.css(elem, prop), // read the current value + val; + + // set the style on the target element + $.style( elem, prop, value); + val = $.css(elem, prop); + + // reset the style back to what it was + inStyle ? $.style( this, prop, curr) : elem.style[prop] = null; + return _parseFloat(val); +} + +function percentageToPx(value, elem, useHeight, useRatio, width, height) { + var ratio = 1, + $elem = $(elem), + outer = (useHeight ? height : width) || $elem["outer" + (useHeight ? "Height" : "Width")](); + + // IE doesn"t report the height and width properly + if ( supportMatrixFilter ) { + ratio = useRatio[(useHeight ? "height" : "width")]; + } + + // TODO: Chrome appears to use innerHeight/Width + value = outer * _parseFloat(value) / 100 / ratio; + return value; +} + +// Converts "matrix(A,B,C,D,X,Y)" to [A,B,C,D,X,Y] +function toArray(matrix) { + // remove the unit of X and Y for Firefox + matrix = /([^,]*),([^,]*),([^,]*),([^,]*),([^,p]*)(?:px)?,([^)p]*)(?:px)?/.exec(matrix); + return [matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], matrix[6]]; +} + +$.transform = { + centerOrigin: _position +}; + +})( jQuery, window, document, Math ); diff --git a/src/static/jquery/jquery-transform/jquery.transform3d.js b/src/static/jquery/jquery-transform/jquery.transform3d.js new file mode 100755 index 0000000..4a4fc86 --- /dev/null +++ b/src/static/jquery/jquery-transform/jquery.transform3d.js @@ -0,0 +1,95 @@ +/* + * transform: A jQuery cssHooks adding 2D/3D transform capabilities to $.fn.css() and $.fn.animate() + * + * Requirements: + * - jQuery 1.5.1+ + * - jquery.transition.js for animations + * - browser implementing W3C's CSS 2DTransforms for 2D tranform + * - browser implementing W3C's CSS 3DTransforms for 3D tranform + * + * latest version and complete README available on Github: + * https://github.com/louisremi/jquery.transform.js + * + * Copyright 2011 @louis_remi + * Licensed under the MIT license. + * + * This saved you an hour of work? + * Send me music http://www.amazon.co.uk/wishlist/HNTU0468LQON + * + */ +(function( $, window, document ) { +"use strict"; + +var div = document.createElement("div"), + divStyle = div.style, + prefixes = [ + "O", + "ms", + "Webkit", + "Moz" + ], + prefix, + i = prefixes.length, + properties = [ + "transform", + "transformOrigin", + "transformStyle", + "perspective", + "perspectiveOrigin", + "backfaceVisibility" + ], + property, + j = prefixes.length; + +// Find the right prefix +while ( i-- ) { + if ( prefixes[i] + leadingUppercase( properties[0] ) in divStyle ) { + prefix = prefixes[i]; + continue; + } +} + +// This browser is not compatible with transforms +if ( !prefix ) { return; } + +// Build cssHooks for each property +while ( j-- ) { + property = prefix + leadingUppercase( properties[j] ); + + if ( property in divStyle ) { + + // px isn't the default unit of this property + $.cssNumber[ properties[j] ] = true; + + // populate cssProps + $.cssProps[ properties[j] ] = property; + + // MozTranform requires a complete hook because "px" is required in translate + property === "MozTransform" && ($.cssHooks[ properties[j] ] = { + get: function( elem, computed ) { + return (computed ? + // remove "px" from the computed matrix + $.css( elem, property ).split("px").join(""): + elem.style[property] + ); + }, + set: function( elem, value ) { + // add "px" to matrices + /matrix\([^)p]*\)/.test(value) && ( + value = value.replace(/matrix((?:[^,]*,){4})([^,]*),([^)]*)/, "matrix$1$2px,$3px") + ); + /matrix3d\([^)p]*\)/.test(value) && ( + value = value.replace(/matrix3d((?:[^,]*,){12})([^,]*),([^,]*),([^,]*)/, "matrix3d$1$2px,$3px,$4px") + ); + elem.style[property] = value; + } + }); + + } +} + +function leadingUppercase( word ) { + return word.slice(0,1).toUpperCase() + word.slice(1); +} + +})( jQuery, window, document ); \ No newline at end of file diff --git a/src/static/jquery/jquery-ui/jquery-ui-1.10.4.custom.min.js b/src/static/jquery/jquery-ui/jquery-ui-1.10.4.custom.min.js new file mode 100755 index 0000000..408787a --- /dev/null +++ b/src/static/jquery/jquery-ui/jquery-ui-1.10.4.custom.min.js @@ -0,0 +1,6 @@ +/*! jQuery UI - v1.10.4 - 2014-06-17 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.dialog.js, jquery.ui.menu.js +* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ + +(function(e,t){function i(t,i){var s,a,o,r=t.nodeName.toLowerCase();return"area"===r?(s=t.parentNode,a=s.name,t.href&&a&&"map"===s.nodeName.toLowerCase()?(o=e("img[usemap=#"+a+"]")[0],!!o&&n(o)):!1):(/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||i:i)&&n(t)}function n(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var s=0,a=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.4",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,n){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),n&&n.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var n,s,a=e(this[0]);a.length&&a[0]!==document;){if(n=a.css("position"),("absolute"===n||"relative"===n||"fixed"===n)&&(s=parseInt(a.css("zIndex"),10),!isNaN(s)&&0!==s))return s;a=a.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++s)})},removeUniqueId:function(){return this.each(function(){a.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,n){return!!e.data(t,n[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),s=isNaN(n);return(s||n>=0)&&i(t,!s)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,n){function s(t,i,n,s){return e.each(a,function(){i-=parseFloat(e.css(t,"padding"+this))||0,n&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var a="Width"===n?["Left","Right"]:["Top","Bottom"],o=n.toLowerCase(),r={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+n]=function(i){return i===t?r["inner"+n].call(this):this.each(function(){e(this).css(o,s(this,i)+"px")})},e.fn["outer"+n]=function(t,i){return"number"!=typeof t?r["outer"+n].call(this,t):this.each(function(){e(this).css(o,s(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,n){var s,a=e.ui[t].prototype;for(s in n)a.plugins[s]=a.plugins[s]||[],a.plugins[s].push([i,n[s]])},call:function(e,t,i){var n,s=e.plugins[t];if(s&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(n=0;s.length>n;n++)e.options[s[n][0]]&&s[n][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var n=i&&"left"===i?"scrollLeft":"scrollTop",s=!1;return t[n]>0?!0:(t[n]=1,s=t[n]>0,t[n]=0,s)}})})(jQuery);(function(t,e){var i=0,s=Array.prototype.slice,n=t.cleanData;t.cleanData=function(e){for(var i,s=0;null!=(i=e[s]);s++)try{t(i).triggerHandler("remove")}catch(a){}n(e)},t.widget=function(i,s,n){var a,o,r,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=t.Widget),t.expr[":"][a.toLowerCase()]=function(e){return!!t.data(e,a)},t[u]=t[u]||{},o=t[u][i],r=t[u][i]=function(t,i){return this._createWidget?(arguments.length&&this._createWidget(t,i),e):new r(t,i)},t.extend(r,o,{version:n.version,_proto:t.extend({},n),_childConstructors:[]}),h=new s,h.options=t.widget.extend({},h.options),t.each(n,function(i,n){return t.isFunction(n)?(l[i]=function(){var t=function(){return s.prototype[i].apply(this,arguments)},e=function(t){return s.prototype[i].apply(this,t)};return function(){var i,s=this._super,a=this._superApply;return this._super=t,this._superApply=e,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),e):(l[i]=n,e)}),r.prototype=t.widget.extend(h,{widgetEventPrefix:o?h.widgetEventPrefix||i:i},l,{constructor:r,namespace:u,widgetName:i,widgetFullName:a}),o?(t.each(o._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,r,i._proto)}),delete o._childConstructors):s._childConstructors.push(r),t.widget.bridge(i,r)},t.widget.extend=function(i){for(var n,a,o=s.call(arguments,1),r=0,h=o.length;h>r;r++)for(n in o[r])a=o[r][n],o[r].hasOwnProperty(n)&&a!==e&&(i[n]=t.isPlainObject(a)?t.isPlainObject(i[n])?t.widget.extend({},i[n],a):t.widget.extend({},a):a);return i},t.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;t.fn[i]=function(o){var r="string"==typeof o,h=s.call(arguments,1),l=this;return o=!r&&h.length?t.widget.extend.apply(null,[o].concat(h)):o,r?this.each(function(){var s,n=t.data(this,a);return n?t.isFunction(n[o])&&"_"!==o.charAt(0)?(s=n[o].apply(n,h),s!==n&&s!==e?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):e):t.error("no such method '"+o+"' for "+i+" widget instance"):t.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+o+"'")}):this.each(function(){var e=t.data(this,a);e?e.option(o||{})._init():t.data(this,a,new n(o,this))}),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this.bindings=t(),this.hoverable=t(),this.focusable=t(),s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(i,s){var n,a,o,r=i;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof i)if(r={},n=i.split("."),i=n.shift(),n.length){for(a=r[i]=t.widget.extend({},this.options[i]),o=0;n.length-1>o;o++)a[n[o]]=a[n[o]]||{},a=a[n[o]];if(i=n.pop(),1===arguments.length)return a[i]===e?null:a[i];a[i]=s}else{if(1===arguments.length)return this.options[i]===e?null:this.options[i];r[i]=s}return this._setOptions(r),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!e).attr("aria-disabled",e),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,o=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=t(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),t.each(n,function(n,r){function h(){return i||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof r?o[r]:r).apply(o,arguments):e}"string"!=typeof r&&(h.guid=r.guid=r.guid||h.guid||t.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+o.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(t,e){e=(e||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(e).undelegate(e)},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,i,s){var n,a,o=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(t.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),o=!t.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){t(this)[e](),a&&a.call(s[0]),i()})}})})(jQuery);(function(t){var e=!1;t(document).mouseup(function(){e=!1}),t.widget("ui.mouse",{version:"1.10.4",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.bind("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).bind("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!e){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?t(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===t.data(i.target,this.widgetName+".preventClickEvent")&&t.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return s._mouseMove(t)},this._mouseUpDelegate=function(t){return s._mouseUp(t)},t(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),e=!0,!0)):!0}},_mouseMove:function(e){return t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button?this._mouseUp(e):this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){return t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),!1},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(t,e){function i(t,e,i){return[parseFloat(t[0])*(p.test(t[0])?e/100:1),parseFloat(t[1])*(p.test(t[1])?i/100:1)]}function s(e,i){return parseInt(t.css(e,i),10)||0}function n(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}t.ui=t.ui||{};var a,o=Math.max,r=Math.abs,l=Math.round,h=/left|center|right/,c=/top|center|bottom/,u=/[\+\-]\d+(\.[\d]+)?%?/,d=/^\w+/,p=/%$/,f=t.fn.position;t.position={scrollbarWidth:function(){if(a!==e)return a;var i,s,n=t("<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=n.children()[0];return t("body").append(n),i=o.offsetWidth,n.css("overflow","scroll"),s=o.offsetWidth,i===s&&(s=n[0].clientWidth),n.remove(),a=i-s},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,a="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:a?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]),n=!!i[0]&&9===i[0].nodeType;return{element:i,isWindow:s,isDocument:n,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s?i.width():i.outerWidth(),height:s?i.height():i.outerHeight()}}},t.fn.position=function(e){if(!e||!e.of)return f.apply(this,arguments);e=t.extend({},e);var a,p,g,m,v,_,b=t(e.of),y=t.position.getWithinInfo(e.within),k=t.position.getScrollInfo(y),D=(e.collision||"flip").split(" "),w={};return _=n(b),b[0].preventDefault&&(e.at="left top"),p=_.width,g=_.height,m=_.offset,v=t.extend({},m),t.each(["my","at"],function(){var t,i,s=(e[this]||"").split(" ");1===s.length&&(s=h.test(s[0])?s.concat(["center"]):c.test(s[0])?["center"].concat(s):["center","center"]),s[0]=h.test(s[0])?s[0]:"center",s[1]=c.test(s[1])?s[1]:"center",t=u.exec(s[0]),i=u.exec(s[1]),w[this]=[t?t[0]:0,i?i[0]:0],e[this]=[d.exec(s[0])[0],d.exec(s[1])[0]]}),1===D.length&&(D[1]=D[0]),"right"===e.at[0]?v.left+=p:"center"===e.at[0]&&(v.left+=p/2),"bottom"===e.at[1]?v.top+=g:"center"===e.at[1]&&(v.top+=g/2),a=i(w.at,p,g),v.left+=a[0],v.top+=a[1],this.each(function(){var n,h,c=t(this),u=c.outerWidth(),d=c.outerHeight(),f=s(this,"marginLeft"),_=s(this,"marginTop"),x=u+f+s(this,"marginRight")+k.width,C=d+_+s(this,"marginBottom")+k.height,M=t.extend({},v),T=i(w.my,c.outerWidth(),c.outerHeight());"right"===e.my[0]?M.left-=u:"center"===e.my[0]&&(M.left-=u/2),"bottom"===e.my[1]?M.top-=d:"center"===e.my[1]&&(M.top-=d/2),M.left+=T[0],M.top+=T[1],t.support.offsetFractions||(M.left=l(M.left),M.top=l(M.top)),n={marginLeft:f,marginTop:_},t.each(["left","top"],function(i,s){t.ui.position[D[i]]&&t.ui.position[D[i]][s](M,{targetWidth:p,targetHeight:g,elemWidth:u,elemHeight:d,collisionPosition:n,collisionWidth:x,collisionHeight:C,offset:[a[0]+T[0],a[1]+T[1]],my:e.my,at:e.at,within:y,elem:c})}),e.using&&(h=function(t){var i=m.left-M.left,s=i+p-u,n=m.top-M.top,a=n+g-d,l={target:{element:b,left:m.left,top:m.top,width:p,height:g},element:{element:c,left:M.left,top:M.top,width:u,height:d},horizontal:0>s?"left":i>0?"right":"center",vertical:0>a?"top":n>0?"bottom":"middle"};u>p&&p>r(i+s)&&(l.horizontal="center"),d>g&&g>r(n+a)&&(l.vertical="middle"),l.important=o(r(i),r(s))>o(r(n),r(a))?"horizontal":"vertical",e.using.call(this,t,l)}),c.offset(t.extend(M,{using:h}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,l=n-r,h=r+e.collisionWidth-a-n;e.collisionWidth>a?l>0&&0>=h?(i=t.left+l+e.collisionWidth-a-n,t.left+=l-i):t.left=h>0&&0>=l?n:l>h?n+a-e.collisionWidth:n:l>0?t.left+=l:h>0?t.left-=h:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,l=n-r,h=r+e.collisionHeight-a-n;e.collisionHeight>a?l>0&&0>=h?(i=t.top+l+e.collisionHeight-a-n,t.top+=l-i):t.top=h>0&&0>=l?n:l>h?n+a-e.collisionHeight:n:l>0?t.top+=l:h>0?t.top-=h:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,a=n.offset.left+n.scrollLeft,o=n.width,l=n.isWindow?n.scrollLeft:n.offset.left,h=t.left-e.collisionPosition.marginLeft,c=h-l,u=h+e.collisionWidth-o-l,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-o-a,(0>i||r(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-l,(s>0||u>r(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,a=n.offset.top+n.scrollTop,o=n.height,l=n.isWindow?n.scrollTop:n.offset.top,h=t.top-e.collisionPosition.marginTop,c=h-l,u=h+e.collisionHeight-o-l,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-o-a,t.top+p+f+g>c&&(0>s||r(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-l,t.top+p+f+g>u&&(i>0||u>r(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}},function(){var e,i,s,n,a,o=document.getElementsByTagName("body")[0],r=document.createElement("div");e=document.createElement(o?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&t.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(a in s)e.style[a]=s[a];e.appendChild(r),i=o||document.documentElement,i.insertBefore(e,i.firstChild),r.style.cssText="position: absolute; left: 10.7432222px;",n=t(r).offset().left,t.support.offsetFractions=n>10&&11>n,e.innerHTML="",i.removeChild(e)}()})(jQuery);(function(t){t.widget("ui.draggable",t.ui.mouse,{version:"1.10.4",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,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?: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(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(t(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){t("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(t(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_mouseDrag:function(e,i){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"original"!==this.options.helper||t.contains(this.element[0].ownerDocument,this.element[0])?("invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1):!1},_mouseUp:function(e){return t("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return s.parents("body").length||s.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s[0]===this.element[0]||/(fixed|absolute)/.test(s.css("position"))||s.css("position","absolute"),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.element.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.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 e,i,s,n=this.options;return n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):"document"===n.containment?(this.containment=[0,0,t(document).width()-this.helperProportions.width-this.margins.left,(t(document).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):n.containment.constructor===Array?(this.containment=n.containment,undefined):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e="hidden"!==i.css("overflow"),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=i),undefined):(this.containment=null,undefined)},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent;return this.offset.scroll||(this.offset.scroll={top:n.scrollTop(),left:n.scrollLeft()}),{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top)*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)*s}},_generatePosition:function(e){var i,s,n,a,o=this.options,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,l=e.pageX,h=e.pageY;return this.offset.scroll||(this.offset.scroll={top:r.scrollTop(),left:r.scrollLeft()}),this.originalPosition&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.left<i[0]&&(l=i[0]+this.offset.click.left),e.pageY-this.offset.click.top<i[1]&&(h=i[1]+this.offset.click.top),e.pageX-this.offset.click.left>i[2]&&(l=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(h=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,h=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((l-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,l=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a)),{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top),left:l-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)}},_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(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s]),"drag"===e&&(this.positionAbs=this._convertPositionTo("absolute")),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i){var s=t(this).data("ui-draggable"),n=s.options,a=t.extend({},i,{item:s.element});s.sortables=[],t(n.connectToSortable).each(function(){var i=t.data(this,"ui-sortable");i&&!i.options.disabled&&(s.sortables.push({instance:i,shouldRevert:i.options.revert}),i.refreshPositions(),i._trigger("activate",e,a))})},stop:function(e,i){var s=t(this).data("ui-draggable"),n=t.extend({},i,{item:s.element});t.each(s.sortables,function(){this.instance.isOver?(this.instance.isOver=0,s.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(e),this.instance.options.helper=this.instance.options._helper,"original"===s.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",e,n))})},drag:function(e,i){var s=t(this).data("ui-draggable"),n=this;t.each(s.sortables,function(){var a=!1,o=this;this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(a=!0,t.each(s.sortables,function(){return this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&t.contains(o.instance.element[0],this.instance.element[0])&&(a=!1),a})),a?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=t(n).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return i.helper[0]},e.target=this.instance.currentItem[0],this.instance._mouseCapture(e,!0),this.instance._mouseStart(e,!0,!0),this.instance.offset.click.top=s.offset.click.top,this.instance.offset.click.left=s.offset.click.left,this.instance.offset.parent.left-=s.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=s.offset.parent.top-this.instance.offset.parent.top,s._trigger("toSortable",e),s.dropped=this.instance.element,s.currentItem=s.element,this.instance.fromOutside=s),this.instance.currentItem&&this.instance._mouseDrag(e)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",e,this.instance._uiHash(this.instance)),this.instance._mouseStop(e,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),s._trigger("fromSortable",e),s.dropped=!1)})}}),t.ui.plugin.add("draggable","cursor",{start:function(){var e=t("body"),i=t(this).data("ui-draggable").options;e.css("cursor")&&(i._cursor=e.css("cursor")),e.css("cursor",i.cursor)},stop:function(){var e=t(this).data("ui-draggable").options;e._cursor&&t("body").css("cursor",e._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("opacity")&&(n._opacity=s.css("opacity")),s.css("opacity",n.opacity)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._opacity&&t(i.helper).css("opacity",s._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(){var e=t(this).data("ui-draggable");e.scrollParent[0]!==document&&"HTML"!==e.scrollParent[0].tagName&&(e.overflowOffset=e.scrollParent.offset())},drag:function(e){var i=t(this).data("ui-draggable"),s=i.options,n=!1;i.scrollParent[0]!==document&&"HTML"!==i.scrollParent[0].tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-e.pageY<s.scrollSensitivity?i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop+s.scrollSpeed:e.pageY-i.overflowOffset.top<s.scrollSensitivity&&(i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop-s.scrollSpeed)),s.axis&&"y"===s.axis||(i.overflowOffset.left+i.scrollParent[0].offsetWidth-e.pageX<s.scrollSensitivity?i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft+s.scrollSpeed:e.pageX-i.overflowOffset.left<s.scrollSensitivity&&(i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft-s.scrollSpeed))):(s.axis&&"x"===s.axis||(e.pageY-t(document).scrollTop()<s.scrollSensitivity?n=t(document).scrollTop(t(document).scrollTop()-s.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<s.scrollSensitivity&&(n=t(document).scrollTop(t(document).scrollTop()+s.scrollSpeed))),s.axis&&"y"===s.axis||(e.pageX-t(document).scrollLeft()<s.scrollSensitivity?n=t(document).scrollLeft(t(document).scrollLeft()-s.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<s.scrollSensitivity&&(n=t(document).scrollLeft(t(document).scrollLeft()+s.scrollSpeed)))),n!==!1&&t.ui.ddmanager&&!s.dropBehaviour&&t.ui.ddmanager.prepareOffsets(i,e)}}),t.ui.plugin.add("draggable","snap",{start:function(){var e=t(this).data("ui-draggable"),i=e.options;e.snapElements=[],t(i.snap.constructor!==String?i.snap.items||":data(ui-draggable)":i.snap).each(function(){var i=t(this),s=i.offset();this!==e.element[0]&&e.snapElements.push({item:this,width:i.outerWidth(),height:i.outerHeight(),top:s.top,left:s.left})})},drag:function(e,i){var s,n,a,o,r,l,h,c,u,d,p=t(this).data("ui-draggable"),g=p.options,f=g.snapTolerance,m=i.offset.left,_=m+p.helperProportions.width,v=i.offset.top,b=v+p.helperProportions.height;for(u=p.snapElements.length-1;u>=0;u--)r=p.snapElements[u].left,l=r+p.snapElements[u].width,h=p.snapElements[u].top,c=h+p.snapElements[u].height,r-f>_||m>l+f||h-f>b||v>c+f||!t.contains(p.snapElements[u].item.ownerDocument,p.snapElements[u].item)?(p.snapElements[u].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=!1):("inner"!==g.snapMode&&(s=f>=Math.abs(h-b),n=f>=Math.abs(c-v),a=f>=Math.abs(r-_),o=f>=Math.abs(l-m),s&&(i.position.top=p._convertPositionTo("relative",{top:h-p.helperProportions.height,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r-p.helperProportions.width}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:l}).left-p.margins.left)),d=s||n||a||o,"outer"!==g.snapMode&&(s=f>=Math.abs(h-v),n=f>=Math.abs(c-b),a=f>=Math.abs(r-m),o=f>=Math.abs(l-_),s&&(i.position.top=p._convertPositionTo("relative",{top:h,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c-p.helperProportions.height,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:l-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[u].snapping&&(s||n||a||o||d)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=s||n||a||o||d)}}),t.ui.plugin.add("draggable","stack",{start:function(){var e,i=this.data("ui-draggable").options,s=t.makeArray(t(i.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});s.length&&(e=parseInt(t(s[0]).css("zIndex"),10)||0,t(s).each(function(i){t(this).css("zIndex",e+i)}),this.css("zIndex",e+s.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("zIndex")&&(n._zIndex=s.css("zIndex")),s.css("zIndex",n.zIndex)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._zIndex&&t(i.helper).css("zIndex",s._zIndex)}})})(jQuery);(function(t){function e(t,e,i){return t>e&&e+i>t}t.widget("ui.droppable",{version:"1.10.4",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var e,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=t.isFunction(s)?s:function(t){return t.is(s)},this.proportions=function(){return arguments.length?(e=arguments[0],undefined):e?e:e={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},t.ui.ddmanager.droppables[i.scope]=t.ui.ddmanager.droppables[i.scope]||[],t.ui.ddmanager.droppables[i.scope].push(this),i.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){for(var e=0,i=t.ui.ddmanager.droppables[this.options.scope];i.length>e;e++)i[e]===this&&i.splice(e,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(e,i){"accept"===e&&(this.accept=t.isFunction(i)?i:function(t){return t.is(i)}),t.Widget.prototype._setOption.apply(this,arguments)},_activate:function(e){var i=t.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",e,this.ui(i))},_deactivate:function(e){var i=t.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",e,this.ui(i))},_over:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",e,this.ui(i)))},_out:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",e,this.ui(i)))},_drop:function(e,i){var s=i||t.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var e=t.data(this,"ui-droppable");return e.options.greedy&&!e.options.disabled&&e.options.scope===s.options.scope&&e.accept.call(e.element[0],s.currentItem||s.element)&&t.ui.intersect(s,t.extend(e,{offset:e.element.offset()}),e.options.tolerance)?(n=!0,!1):undefined}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",e,this.ui(s)),this.element):!1):!1},ui:function(t){return{draggable:t.currentItem||t.element,helper:t.helper,position:t.position,offset:t.positionAbs}}}),t.ui.intersect=function(t,i,s){if(!i.offset)return!1;var n,a,o=(t.positionAbs||t.position.absolute).left,r=(t.positionAbs||t.position.absolute).top,l=o+t.helperProportions.width,h=r+t.helperProportions.height,c=i.offset.left,u=i.offset.top,d=c+i.proportions().width,p=u+i.proportions().height;switch(s){case"fit":return o>=c&&d>=l&&r>=u&&p>=h;case"intersect":return o+t.helperProportions.width/2>c&&d>l-t.helperProportions.width/2&&r+t.helperProportions.height/2>u&&p>h-t.helperProportions.height/2;case"pointer":return n=(t.positionAbs||t.position.absolute).left+(t.clickOffset||t.offset.click).left,a=(t.positionAbs||t.position.absolute).top+(t.clickOffset||t.offset.click).top,e(a,u,i.proportions().height)&&e(n,c,i.proportions().width);case"touch":return(r>=u&&p>=r||h>=u&&p>=h||u>r&&h>p)&&(o>=c&&d>=o||l>=c&&d>=l||c>o&&l>d);default:return!1}},t.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,i){var s,n,a=t.ui.ddmanager.droppables[e.options.scope]||[],o=i?i.type:null,r=(e.currentItem||e.element).find(":data(ui-droppable)").addBack();t:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||e&&!a[s].accept.call(a[s].element[0],e.currentItem||e.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions().height=0;continue t}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions({width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight}))}},drop:function(e,i){var s=!1;return t.each((t.ui.ddmanager.droppables[e.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&t.ui.intersect(e,this,this.options.tolerance)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],e.currentItem||e.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(e,i){e.element.parentsUntil("body").bind("scroll.droppable",function(){e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)})},drag:function(e,i){e.options.refreshPositions&&t.ui.ddmanager.prepareOffsets(e,i),t.each(t.ui.ddmanager.droppables[e.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=t.ui.intersect(e,this,this.options.tolerance),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return t.data(this,"ui-droppable").options.scope===n}),a.length&&(s=t.data(a[0],"ui-droppable"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(e,i){e.element.parentsUntil("body").unbind("scroll.droppable"),e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)}}})(jQuery);(function(t){function e(t){return parseInt(t,10)||0}function i(t){return!isNaN(parseInt(t,10))}t.widget("ui.resizable",t.ui.mouse,{version:"1.10.4",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:90,resize:null,start:null,stop:null},_create:function(){var e,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(t("<div class='ui-wrapper' style='overflow: hidden;'></div>").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("ui-resizable",this.element.data("ui-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=r.handles||(t(".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"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),e=this.handles.split(","),this.handles={},i=0;e.length>i;i++)s=t.trim(e[i]),a="ui-resizable-"+s,n=t("<div class='ui-resizable-handle "+a+"'></div>"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(e){var i,s,n,a;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=t(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=t(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,a),this._proportionallyResize()),t(this.handles[i]).length},this._renderAxis(this.element),this._handles=t(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),t(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(t(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(t(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),l=this.element;return this.resizing=!0,/absolute/.test(l.css("position"))?l.css({position:"absolute",top:l.css("top"),left:l.css("left")}):l.is(".ui-draggable")&&l.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=e(this.helper.css("left")),n=e(this.helper.css("top")),o.containment&&(s+=t(o.containment).scrollLeft()||0,n+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:l.width(),height:l.height()},this.originalSize=this._helper?{width:l.outerWidth(),height:l.outerHeight()}:{width:l.width(),height:l.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:l.outerWidth()-l.width(),height:l.outerHeight()-l.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===a?this.axis+"-resize":a),l.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(e){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,l=this.position.left,h=this.size.width,u=this.size.height,c=e.pageX-a.left||0,d=e.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[e,c,d]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==l&&(n.left=this.position.left+"px"),this.size.width!==h&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(n)||this._trigger("resize",e,this.ui()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,a,o,r,l,h=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&t.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,l=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,h.animate||this.element.css(t.extend(o,{top:l,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!h.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(t){var e,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),i(t.left)&&(this.position.left=t.left),i(t.top)&&(this.position.top=t.top),i(t.height)&&(this.size.height=t.height),i(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,s=this.size,n=this.axis;return i(t.height)?t.width=t.height*this.aspectRatio:i(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===n&&(t.left=e.left+(s.width-t.width),t.top=null),"nw"===n&&(t.top=e.top+(s.height-t.height),t.left=e.left+(s.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,s=this.axis,n=i(t.width)&&e.maxWidth&&e.maxWidth<t.width,a=i(t.height)&&e.maxHeight&&e.maxHeight<t.height,o=i(t.width)&&e.minWidth&&e.minWidth>t.width,r=i(t.height)&&e.minHeight&&e.minHeight>t.height,l=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(t.width=e.minWidth),r&&(t.height=e.minHeight),n&&(t.width=e.maxWidth),a&&(t.height=e.maxHeight),o&&u&&(t.left=l-e.minWidth),n&&u&&(t.left=l-e.maxWidth),r&&c&&(t.top=h-e.minHeight),a&&c&&(t.top=h-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var t,e,i,s,n,a=this.helper||this.element;for(t=0;this._proportionallyResizeElements.length>t;t++){if(n=this._proportionallyResizeElements[t],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],e=0;i.length>e;e++)this.borderDif[e]=(parseInt(i[e],10)||0)+(parseInt(s[e],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,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}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&t.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,l={width:i.size.width-r,height:i.size.height-o},h=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(l,u&&h?{top:u,left:h}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,l,h=t(this).data("ui-resizable"),u=h.options,c=h.element,d=u.containment,p=d instanceof t?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(h.containerElement=t(p),/document/.test(d)||d===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(i=t(p),s=[],t(["Top","Right","Left","Bottom"]).each(function(t,n){s[t]=e(i.css("padding"+n))}),h.containerOffset=i.offset(),h.containerPosition=i.position(),h.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=h.containerOffset,a=h.containerSize.height,o=h.containerSize.width,r=t.ui.hasScroll(p,"left")?p.scrollWidth:o,l=t.ui.hasScroll(p)?p.scrollHeight:a,h.parentData={element:p,left:n.left,top:n.top,width:r,height:l}))},resize:function(e){var i,s,n,a,o=t(this).data("ui-resizable"),r=o.options,l=o.containerOffset,h=o.position,u=o._aspectRatio||e.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=l),h.left<(o._helper?l.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-l.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?l.left:0),h.top<(o._helper?l.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-l.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?l.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-l.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=Math.abs(o.parentData.left)),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.containerOffset,n=e.containerPosition,a=e.containerElement,o=t(e.helper),r=o.offset(),l=o.outerWidth()-e.sizeDiff.width,h=o.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(a.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h}),e._helper&&!i.animate&&/static/.test(a.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=function(e){t(e).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseInt(e.width(),10),height:parseInt(e.height(),10),left:parseInt(e.css("left"),10),top:parseInt(e.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):t.each(i.alsoResize,function(t){s(t)})},resize:function(e,i){var s=t(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},l=function(e,s){t(e).each(function(){var e=t(this),n=t(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(n[e]||0)+(r[e]||0);i&&i>=0&&(a[e]=i||null)}),e.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?l(n.alsoResize):t.each(n.alsoResize,function(t,e){l(t,e)})},stop:function(){t(this).removeData("resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size;e.ghost=e.originalElement.clone(),e.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("string"==typeof i.ghost?i.ghost:""),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).data("ui-resizable");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).data("ui-resizable");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size,n=e.originalSize,a=e.originalPosition,o=e.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,l=r[0]||1,h=r[1]||1,u=Math.round((s.width-n.width)/l)*l,c=Math.round((s.height-n.height)/h)*h,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,g=i.maxHeight&&p>i.maxHeight,m=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,m&&(d+=l),v&&(p+=h),f&&(d-=l),g&&(p-=h),/^(se|s|e)$/.test(o)?(e.size.width=d,e.size.height=p):/^(ne)$/.test(o)?(e.size.width=d,e.size.height=p,e.position.top=a.top-c):/^(sw)$/.test(o)?(e.size.width=d,e.size.height=p,e.position.left=a.left-u):(p-h>0?(e.size.height=p,e.position.top=a.top-c):(e.size.height=h,e.position.top=a.top+n.height-h),d-l>0?(e.size.width=d,e.position.left=a.left-u):(e.size.width=l,e.position.left=a.left+n.width-l))}})})(jQuery);(function(t){t.widget("ui.selectable",t.ui.mouse,{version:"1.10.4",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var e,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){e=t(i.options.filter,i.element[0]),e.addClass("ui-selectee"),e.each(function(){var e=t(this),i=e.offset();t.data(this,"selectable-item",{element:this,$element:e,left:i.left,top:i.top,right:i.left+e.outerWidth(),bottom:i.top+e.outerHeight(),startselected:!1,selected:e.hasClass("ui-selected"),selecting:e.hasClass("ui-selecting"),unselecting:e.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=e.addClass("ui-selectee"),this._mouseInit(),this.helper=t("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(e){var i=this,s=this.options;this.opos=[e.pageX,e.pageY],this.options.disabled||(this.selectees=t(s.filter,this.element[0]),this._trigger("start",e),t(s.appendTo).append(this.helper),this.helper.css({left:e.pageX,top:e.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=t.data(this,"selectable-item");s.startselected=!0,e.metaKey||e.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",e,{unselecting:s.element}))}),t(e.target).parents().addBack().each(function(){var s,n=t.data(this,"selectable-item");return n?(s=!e.metaKey&&!e.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",e,{selecting:n.element}):i._trigger("unselecting",e,{unselecting:n.element}),!1):undefined}))},_mouseDrag:function(e){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=e.pageX,l=e.pageY;return a>r&&(i=r,r=a,a=i),o>l&&(i=l,l=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:l-o}),this.selectees.each(function(){var i=t.data(this,"selectable-item"),h=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?h=!(i.left>r||a>i.right||i.top>l||o>i.bottom):"fit"===n.tolerance&&(h=i.left>a&&r>i.right&&i.top>o&&l>i.bottom),h?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",e,{selecting:i.element}))):(i.selecting&&((e.metaKey||e.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",e,{unselecting:i.element}))),i.selected&&(e.metaKey||e.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",e,{unselecting:i.element})))))}),!1}},_mouseStop:function(e){var i=this;return this.dragged=!1,t(".ui-unselecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",e,{unselected:s.element})}),t(".ui-selecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",e,{selected:s.element})}),this._trigger("stop",e),this.helper.remove(),!1}})})(jQuery);(function(t){function e(t,e,i){return t>e&&e+i>t}function i(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))}t.widget("ui.sortable",t.ui.mouse,{version:"1.10.4",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,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var t=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===t.axis||i(this.items[0].item):!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 t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_setOption:function(e,i){"disabled"===e?(this.options[e]=i,this.widget().toggleClass("ui-sortable-disabled",!!i)):t.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(e,i){var s=null,n=!1,a=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,a.widgetName+"-item")===a?(s=t(this),!1):undefined}),t.data(e.target,a.widgetName+"-item")===a&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,a,o=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),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},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.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(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,o.cursorAt&&this._adjustOffsetFromHelper(o.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),o.containment&&this._setContainment(),o.cursor&&"auto"!==o.cursor&&(a=this.document.find("body"),this.storedCursor=a.css("cursor"),a.css("cursor",o.cursor),this.storedStylesheet=t("<style>*{ cursor: "+o.cursor+" !important; }</style>").appendTo(a)),o.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",o.opacity)),o.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",o.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!o.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,a,o=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY<o.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+o.scrollSpeed:e.pageY-this.overflowOffset.top<o.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-o.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-e.pageX<o.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+o.scrollSpeed:e.pageX-this.overflowOffset.left<o.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-o.scrollSpeed)):(e.pageY-t(document).scrollTop()<o.scrollSensitivity?r=t(document).scrollTop(t(document).scrollTop()-o.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<o.scrollSensitivity&&(r=t(document).scrollTop(t(document).scrollTop()+o.scrollSpeed)),e.pageX-t(document).scrollLeft()<o.scrollSensitivity?r=t(document).scrollLeft(t(document).scrollLeft()-o.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<o.scrollSensitivity&&(r=t(document).scrollLeft(t(document).scrollLeft()+o.scrollSpeed))),r!==!1&&t.ui.ddmanager&&!o.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],a=this._intersectsWithPointer(s),a&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===a?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===a?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),a=this.options.axis,o={};a&&"x"!==a||(o.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),a&&"y"!==a||(o.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(o,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,a=t.left,o=a+t.width,r=t.top,h=r+t.height,l=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+l>r&&h>s+l,d="y"===this.options.axis||e+c>a&&o>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>a&&o>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var i="x"===this.options.axis||e(this.positionAbs.top+this.offset.click.top,t.top,t.height),s="y"===this.options.axis||e(this.positionAbs.left+this.offset.click.left,t.left,t.width),n=i&&s,a=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return n?this.floating?o&&"right"===o||"down"===a?2:1:a&&("down"===a?2:1):!1},_intersectsWithSides:function(t){var i=e(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),s=e(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),n=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return this.floating&&a?"right"===a&&s||"left"===a&&!s:n&&("down"===n&&i||"up"===n&&!i)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){function i(){r.push(this)}var s,n,a,o,r=[],h=[],l=this._connectWith();if(l&&e)for(s=l.length-1;s>=0;s--)for(a=t(l[s]),n=a.length-1;n>=0;n--)o=t.data(a[n],this.widgetFullName),o&&o!==this&&!o.options.disabled&&h.push([t.isFunction(o.options.items)?o.options.items.call(o.element):t(o.options.items,o.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),o]);for(h.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=h.length-1;s>=0;s--)h[s][0].each(i);return t(r)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,a,o,r,h,l,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i]),s=n.length-1;s>=0;s--)a=t.data(n[s],this.widgetFullName),a&&a!==this&&!a.options.disabled&&(u.push([t.isFunction(a.options.items)?a.options.items.call(a.element[0],e,{item:this.currentItem}):t(a.options.items,a.element),a]),this.containers.push(a));for(i=u.length-1;i>=0;i--)for(o=u[i][1],r=u[i][0],s=0,l=r.length;l>s;s++)h=t(r[s]),h.data(this.widgetName+"-item",o),c.push({item:h,instance:o,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,a;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),a=n.offset(),s.left=a.left,s.top=a.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)a=this.containers[i].element.offset(),this.containers[i].containerCache.left=a.left,this.containers[i].containerCache.top=a.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]).addClass(i||e.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?e.currentItem.children().each(function(){t("<td>&#160;</td>",e.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(n)}):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_contactContainers:function(s){var n,a,o,r,h,l,c,u,d,p,f=null,g=null;for(n=this.containers.length-1;n>=0;n--)if(!t.contains(this.currentItem[0],this.containers[n].element[0]))if(this._intersectsWith(this.containers[n].containerCache)){if(f&&t.contains(this.containers[n].element[0],f.element[0]))continue;f=this.containers[n],g=n}else this.containers[n].containerCache.over&&(this.containers[n]._trigger("out",s,this._uiHash(this)),this.containers[n].containerCache.over=0);if(f)if(1===this.containers.length)this.containers[g].containerCache.over||(this.containers[g]._trigger("over",s,this._uiHash(this)),this.containers[g].containerCache.over=1);else{for(o=1e4,r=null,p=f.floating||i(this.currentItem),h=p?"left":"top",l=p?"width":"height",c=this.positionAbs[h]+this.offset.click[h],a=this.items.length-1;a>=0;a--)t.contains(this.containers[g].element[0],this.items[a].item[0])&&this.items[a].item[0]!==this.currentItem[0]&&(!p||e(this.positionAbs.top+this.offset.click.top,this.items[a].top,this.items[a].height))&&(u=this.items[a].item.offset()[h],d=!1,Math.abs(u-c)>Math.abs(u+this.items[a][l]-c)&&(d=!0,u+=this.items[a][l]),o>Math.abs(u-c)&&(o=Math.abs(u-c),r=this.items[a],this.direction=d?"up":"down"));if(!r&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[g])return;r?this._rearrange(s,r,null,!0):this._rearrange(s,null,this.containers[g].element,!0),this._trigger("change",s,this._uiHash()),this.containers[g]._trigger("change",s,this._uiHash(this)),this.currentContainer=this.containers[g],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[g]._trigger("over",s,this._uiHash(this)),this.containers[g].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[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")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.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 e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,t("document"===n.containment?document:window).width()-this.helperProportions.width-this.margins.left,(t("document"===n.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():a?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():a?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,a=e.pageX,o=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.left<this.containment[0]&&(a=this.containment[0]+this.offset.click.left),e.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),e.pageX-this.offset.click.left>this.containment[2]&&(a=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1],o=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((a-this.originalPageX)/n.grid[0])*n.grid[0],a=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:a-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,this.cancelHelperRemoval){if(!e){for(this._trigger("beforeStop",t,this._uiHash()),s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}if(e||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,!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}})})(jQuery);(function(e){e.widget("ui.autocomplete",{version:"1.10.4",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var t,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return t=!0,s=!0,i=!0,undefined;t=!1,s=!1,i=!1;var a=e.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:t=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:t=!0,this._move("nextPage",n);break;case a.UP:t=!0,this._keyEvent("previous",n);break;case a.DOWN:t=!0,this._keyEvent("next",n);break;case a.ENTER:case a.NUMPAD_ENTER:this.menu.active&&(t=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),undefined;if(!i){var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(e){return s?(s=!1,e.preventDefault(),undefined):(this._searchTimeout(e),undefined)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,undefined):(clearTimeout(this.searching),this.close(e),this._change(e),undefined)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().data("ui-menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(s){s.target===t.element[0]||s.target===i||e.contains(i,s.target)||t.close()})})},menufocus:function(t,i){if(this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type)))return this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)}),undefined;var s=i.item.data("ui-autocomplete-item");!1!==this._trigger("focus",t,{item:s})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(s.value):this.liveRegion.text(s.value)},menuselect:function(e,t){var i=t.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",e,{item:i})&&this._value(i.value),this.term=this._value(),this.close(e),this.selectedItem=i}}),this.liveRegion=e("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertBefore(this.element),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),"source"===e&&this._initSource(),"appendTo"===e&&this.menu.element.appendTo(this._appendTo()),"disabled"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,i,s=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(i,s){s(e.ui.autocomplete.filter(t,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(t,n){s.xhr&&s.xhr.abort(),s.xhr=e.ajax({url:i,data:t,dataType:"json",success:function(e){n(e)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length<this.options.minLength?this.close(t):this._trigger("search",t)!==!1?this._search(e):undefined},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var t=++this.requestIndex;return e.proxy(function(e){t===this.requestIndex&&this.__response(e),this.pending--,this.pending||this.element.removeClass("ui-autocomplete-loading")},this)},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return"string"==typeof t?{label:t,value:t}:e.extend({label:t.label||t.value,value:t.value||t.label},t)})},_suggest:function(t){var i=this.menu.element.empty();this._renderMenu(i,t),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,i){var s=this;e.each(i,function(e,i){s._renderItemData(t,i)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,i){return e("<li>").append(e("<a>").text(i.label)).appendTo(t)},_move:function(e,t){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this._value(this.term),this.menu.blur(),undefined):(this.menu[e](t),undefined):(this.search(null,t),undefined)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,i){var s=RegExp(e.ui.autocomplete.escapeRegex(i),"i");return e.grep(t,function(e){return s.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments),this.options.disabled||this.cancelSearch||(t=e&&e.length?this.options.messages.results(e.length):this.options.messages.noResults,this.liveRegion.text(t))}})})(jQuery);(function(e){var t,i="ui-button ui-widget ui-state-default ui-corner-all",n="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",s=function(){var t=e(this);setTimeout(function(){t.find(":ui-button").button("refresh")},1)},a=function(t){var i=t.name,n=t.form,s=e([]);return i&&(i=i.replace(/'/g,"\\'"),s=n?e(n).find("[name='"+i+"']"):e("[name='"+i+"']",t.ownerDocument).filter(function(){return!this.form})),s};e.widget("ui.button",{version:"1.10.4",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,s),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var n=this,o=this.options,r="checkbox"===this.type||"radio"===this.type,h=r?"":"ui-state-active";null===o.label&&(o.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(i).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){o.disabled||this===t&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){o.disabled||e(this).removeClass(h)}).bind("click"+this.eventNamespace,function(e){o.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this._on({focus:function(){this.buttonElement.addClass("ui-state-focus")},blur:function(){this.buttonElement.removeClass("ui-state-focus")}}),r&&this.element.bind("change"+this.eventNamespace,function(){n.refresh()}),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return o.disabled?!1:undefined}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(o.disabled)return!1;e(this).addClass("ui-state-active"),n.buttonElement.attr("aria-pressed","true");var t=n.element[0];a(t).not(t).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return o.disabled?!1:(e(this).addClass("ui-state-active"),t=this,n.document.one("mouseup",function(){t=null}),undefined)}).bind("mouseup"+this.eventNamespace,function(){return o.disabled?!1:(e(this).removeClass("ui-state-active"),undefined)}).bind("keydown"+this.eventNamespace,function(t){return o.disabled?!1:((t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active"),undefined)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",o.disabled),this._resetButton()},_determineButtonType:function(){var e,t,i;this.type=this.element.is("[type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),i=this.element.is(":checked"),i&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(i+" ui-state-active "+n).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){return this._super(e,t),"disabled"===e?(this.element.prop("disabled",!!t),t&&this.buttonElement.removeClass("ui-state-focus"),undefined):(this._resetButton(),undefined)},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),"radio"===this.type?a(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),undefined;var t=this.buttonElement.removeClass(n),i=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),s=this.options.icons,a=s.primary&&s.secondary,o=[];s.primary||s.secondary?(this.options.text&&o.push("ui-button-text-icon"+(a?"s":s.primary?"-primary":"-secondary")),s.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+s.primary+"'></span>"),s.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+s.secondary+"'></span>"),this.options.text||(o.push(a?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(i)))):o.push("ui-button-text-only"),t.addClass(o.join(" "))}}),e.widget("ui.buttonset",{version:"1.10.4",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){"disabled"===e&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t="rtl"===this.element.css("direction");this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(e){var t={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.10.4",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var i=e(this).css(t).offset().top;0>i&&e(this).css("top",t.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).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},disable:e.noop,enable:e.noop,close:function(t){var i,a=this;if(this._isOpen&&this._trigger("beforeClose",t)!==!1){if(this._isOpen=!1,this._destroyOverlay(),!this.opener.filter(":focusable").focus().length)try{i=this.document[0].activeElement,i&&"body"!==i.nodeName.toLowerCase()&&e(i).blur()}catch(s){}this._hide(this.uiDialog,this.options.hide,function(){a._trigger("close",t)})}},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(e,t){var i=!!this.uiDialog.nextAll(":visible").insertBefore(this.uiDialog).length;return i&&!t&&this._trigger("focus",e),i},open:function(){var t=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),undefined):(this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._trigger("open"),undefined)},_focusTabbable:function(){var e=this.element.find("[autofocus]");e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function i(){var t=this.document[0].activeElement,i=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);i||this._focusTabbable()}t.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=e("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE)return t.preventDefault(),this.close(t),undefined;if(t.keyCode===e.ui.keyCode.TAB){var i=this.uiDialog.find(":tabbable"),a=i.filter(":first"),s=i.filter(":last");t.target!==s[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==a[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(s.focus(1),t.preventDefault()):(a.focus(1),t.preventDefault())}},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("<button type='button'></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html("&#160;"),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),e.isEmptyObject(i)||e.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),undefined):(e.each(i,function(i,a){var s,n;a=e.isFunction(a)?{click:a,text:i}:a,a=e.extend({type:"button"},a),s=a.click,a.click=function(){s.apply(t.element[0],arguments)},n={icons:a.icons,text:a.showText},delete a.icons,delete a.showText,e("<button></button>",a).button(n).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),undefined)},_makeDraggable:function(){function t(e){return{position:e.position,offset:e.offset}}var i=this,a=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(a,s){e(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",a,t(s))},drag:function(e,a){i._trigger("drag",e,t(a))},stop:function(s,n){a.position=[n.position.left-i.document.scrollLeft(),n.position.top-i.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",s,t(n))}})},_makeResizable:function(){function t(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var i=this,a=this.options,s=a.resizable,n=this.uiDialog.css("position"),r="string"==typeof s?s:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:a.maxWidth,maxHeight:a.maxHeight,minWidth:a.minWidth,minHeight:this._minHeight(),handles:r,start:function(a,s){e(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",a,t(s))},resize:function(e,a){i._trigger("resize",e,t(a))},stop:function(s,n){a.height=e(this).height(),a.width=e(this).width(),e(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",s,t(n))}}).css("position",n)},_minHeight:function(){var e=this.options;return"auto"===e.height?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(a){var s=this,n=!1,r={};e.each(a,function(e,a){s._setOption(e,a),e in t&&(n=!0),e in i&&(r[e]=a)}),n&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",r)},_setOption:function(e,t){var i,a,s=this.uiDialog;"dialogClass"===e&&s.removeClass(this.options.dialogClass).addClass(t),"disabled"!==e&&(this._super(e,t),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:""+t}),"draggable"===e&&(i=s.is(":data(ui-draggable)"),i&&!t&&s.draggable("destroy"),!i&&t&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(a=s.is(":data(ui-resizable)"),a&&!t&&s.resizable("destroy"),a&&"string"==typeof t&&s.resizable("option","handles",t),a||t===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var e,t,i,a=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),a.minWidth>a.width&&(a.width=a.minWidth),e=this.uiDialog.css({height:"auto",width:a.width}).outerHeight(),t=Math.max(0,a.minHeight-e),i="number"==typeof a.maxHeight?Math.max(0,a.maxHeight-e):"none","auto"===a.height?this.element.css({minHeight:t,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,a.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=e(this);return e("<div>").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return e(t.target).closest(".ui-dialog").length?!0:!!e(t.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var t=this,i=this.widgetFullName;e.ui.dialog.overlayInstances||this._delay(function(){e.ui.dialog.overlayInstances&&this.document.bind("focusin.dialog",function(a){t._allowInteraction(a)||(a.preventDefault(),e(".ui-dialog:visible:last .ui-dialog-content").data(i)._focusTabbable())})}),this.overlay=e("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),e.ui.dialog.overlayInstances++}},_destroyOverlay:function(){this.options.modal&&this.overlay&&(e.ui.dialog.overlayInstances--,e.ui.dialog.overlayInstances||this.document.unbind("focusin.dialog"),this.overlay.remove(),this.overlay=null)}}),e.ui.dialog.overlayInstances=0,e.uiBackCompat!==!1&&e.widget("ui.dialog",e.ui.dialog,{_position:function(){var t,i=this.options.position,a=[],s=[0,0];i?(("string"==typeof i||"object"==typeof i&&"0"in i)&&(a=i.split?i.split(" "):[i[0],i[1]],1===a.length&&(a[1]=a[0]),e.each(["left","top"],function(e,t){+a[e]===a[e]&&(s[e]=a[e],a[e]=t)}),i={my:a[0]+(0>s[0]?s[0]:"+"+s[0])+" "+a[1]+(0>s[1]?s[1]:"+"+s[1]),at:a.join(" ")}),i=e.extend({},e.ui.dialog.prototype.options.position,i)):i=e.ui.dialog.prototype.options.position,t=this.uiDialog.is(":visible"),t||this.uiDialog.show(),this.uiDialog.position(i),t||this.uiDialog.hide()}})})(jQuery);(function(t){t.widget("ui.menu",{version:"1.10.4",defaultElement:"<ul>",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.mouseHandled=!1,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,t.proxy(function(t){this.options.disabled&&t.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(t){t.preventDefault()},"click .ui-state-disabled > a":function(t){t.preventDefault()},"click .ui-menu-item:has(a)":function(e){var i=t(e.target).closest(".ui-menu-item");!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(e),e.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(e):!this.element.is(":focus")&&t(this.document[0].activeElement).closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){var i=t(e.currentTarget);i.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(e,i)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.children(".ui-menu-item").eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){t.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){t(e.target).closest(".ui-menu").length||this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().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 e=t(this);e.data("ui-menu-submenu-carat")&&e.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(e){function i(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var s,n,a,o,r,l=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:l=!1,n=this.previousFilter||"",a=String.fromCharCode(e.keyCode),o=!1,clearTimeout(this.filterTimer),a===n?o=!0:a=n+a,r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())}),s=o&&-1!==s.index(this.active.next())?this.active.nextAll(".ui-menu-item"):s,s.length||(a=String.fromCharCode(e.keyCode),r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())})),s.length?(this.focus(e,s),s.length>1?(this.previousFilter=a,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}l&&e.preventDefault()},_activate:function(t){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i=this.options.icons.submenu,s=this.element.find(this.options.menus);this.element.toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length),s.filter(":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"}).each(function(){var e=t(this),s=e.prev("a"),n=t("<span>").addClass("ui-menu-icon ui-icon "+i).data("ui-menu-submenu-carat",!0);s.attr("aria-haspopup","true").prepend(n),e.attr("aria-labelledby",s.attr("id"))}),e=s.add(this.element),e.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()}),e.children(":not(.ui-menu-item)").each(function(){var e=t(this);/[^\-\u2014\u2013\s]/.test(e.text())||e.addClass("ui-widget-content ui-menu-divider")}),e.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){"icons"===t&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(e.submenu),this._super(t,e)},focus:function(t,e){var i,s;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=e.height(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",t,{item:this.active}))},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},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(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.children(".ui-menu-item")[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())),undefined):(this.next(e),undefined)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item").first())),undefined):(this.next(e),undefined)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(e){this.active=this.active||t(e.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(e,!0),this._trigger("select",e,i)}})})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_flat_0_aaaaaa_40x100.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100755 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}<irI&an_s0pV!D+$FtuP31JO&3=I&aE+u|=5A)Hv$*VMh&S3C#^>bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_55_fbf9ee_1x400.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100755 index 0000000000000000000000000000000000000000..ad3d6346e00f246102f72f2e026ed0491988b394 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnour0hLi978O6-<~(*I$*%ybaDOn z{W;e!B}_MSUQoPXhYd^Y6RUoS1yepnPx`2Kz)7OXQG!!=-jY=F+d2OOy?#DnJ32>z UEim$g7SJdLPgg&ebxsLQ09~*s;{X5v literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_65_ffffff_1x400.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_65_ffffff_1x400.png new file mode 100755 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O<Z9>;M1& literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_75_dadada_1x400.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_75_dadada_1x400.png new file mode 100755 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uP<E-4iDYHYX${Ii)G?xY5!0{fvg8SC7yQ4u<2&oOc%dd<Zm-fx*+& K&t;ucLK6Ud-y?JY literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_75_e6e6e6_1x400.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_75_e6e6e6_1x400.png new file mode 100755 index 0000000000000000000000000000000000000000..86c2baa655eac8539db34f8d9adb69ec1226201c GIT binary patch literal 110 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq)a_s978O6-<~$)Vo(rZKDhVK z|J9WTLT^QIG;Q^ml{ow8HvtEZhta#LLqp$|vO7%bGjI7IBizcw`SFI!bT^;@44$rj JF6*2UngEbSBdP!Z literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_75_ffffff_1x400.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_glass_75_ffffff_1x400.png new file mode 100755 index 0000000000000000000000000000000000000000..e65ca1297c7b0fca6d0d10c4c5475b8c20cf0e62 GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq>MaW978O6-<~?i$)F&>d~nX+ z>vO)oJQ&&FVaKefeOt$qOR>f~^ebnN_=~%qdHEa<EzM*v3QM<K=@A9$X7F_Nb6Mw< G&;$VN7$B1X literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100755 index 0000000000000000000000000000000000000000..7c9fa6c6edcfcdd3e5b77e6f547b719e6fc66e30 GIT binary patch literal 101 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l#Zv1V~E7m<ccpZF4n8Dv9Yx& zy8QY7U*2m$;l+;n|NjK_PainIAnKgVYt6(keT9{lbLSy{pgsmqS3j3^P6<r_2PGZu literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_inset-soft_95_fef1ec_1x100.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-bg_inset-soft_95_fef1ec_1x100.png new file mode 100755 index 0000000000000000000000000000000000000000..0e05810fffe0b6b8ac320e55d1eb4ba259b89d92 GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0l#{26V~E7myXUR>S{Ou}E*`%9 zKPdOkfrN+ZlHSt7(uY{3{#;wiJb&Ugx1>W4qtrSDm(4hFaaY-$3p3x|sIU3`%J?Qj YcLn#R=pC)AfTl5cy85}Sb4q9e0MP_2(*OVf literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_222222_256x240.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_222222_256x240.png new file mode 100755 index 0000000000000000000000000000000000000000..b273ff111d219c9b9a8b96d57683d0075fb7871a GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_2e83ff_256x240.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_2e83ff_256x240.png new file mode 100755 index 0000000000000000000000000000000000000000..09d1cdc856c292c4ab6dd818c7543ac0828bd616 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_454545_256x240.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_454545_256x240.png new file mode 100755 index 0000000000000000000000000000000000000000..59bd45b907c4fd965697774ce8c5fc6b2fd9c105 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_888888_256x240.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_888888_256x240.png new file mode 100755 index 0000000000000000000000000000000000000000..6d02426c114be4b57aabc0a80b8a63d9e56b9eb6 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_cd0a0a_256x240.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_cd0a0a_256x240.png new file mode 100755 index 0000000000000000000000000000000000000000..2ab019b73ec11a485fa09378f3a0e155194f6a5d GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_f6cf3b_256x240.png b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/images/ui-icons_f6cf3b_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..c9869351a735079f529d069545729f6e905f80e4 GIT binary patch literal 8884 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 Y`xtn(*dR-}!vwf$a^1Mm&@<(K0cnc1rT_o{ literal 0 HcmV?d00001 diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/jquery-ui-1.10.0.custom.css b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/jquery-ui-1.10.0.custom.css new file mode 100644 index 0000000..3b7a2c1 --- /dev/null +++ b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/jquery-ui-1.10.0.custom.css @@ -0,0 +1,1614 @@ +/*! + * jQuery UI Bootstrap (0.5) + * http://addyosmani.github.com/jquery-ui-bootstrap + * + * Copyright 2012 - 2013, Addy Osmani + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Portions copyright jQuery UI & Twitter Bootstrap + */ + + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { + border: 0; clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; +} +.ui-helper-clearfix:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} +.ui-helper-clearfix { + /*display: inline-block; */ + display:block; + min-height: 0; /* support: IE7 */ +} +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { + height:1%; +} + +/* end clearfix */ +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter:Alpha(Opacity=0); +} +.ui-front { + z-index: 100; +} + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +/* + * jQuery UI Resizable 1.10.0 + * + * Copyright 2013, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://api.jqueryui.com/resizable/ + */ + +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + z-index: 99999; + display: block; +} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; +} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; +} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} + +/* + * jQuery UI Selectable 1.10.0 + * + * Copyright 2013, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://jqueryui.com/selectable/ + */ +.ui-selectable-helper { + position: absolute; + z-index: 100; + border:1px dotted black; +} + +/* + * jQuery UI CSS Framework 1.10.0 + * + * Copyright 2013, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/ + */ + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size:13px; } +.ui-widget .ui-widget { font-size: 1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1em; } +.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_75_ffffff_1x400.png) 50% 50% repeat-x; color: #404040; } +.ui-widget-content a { color: #404040; } +.ui-widget-header { + font-weight:bold; + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + border:1px solid #666; + + } +.ui-widget-header a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { + + background-color: #e6e6e6; + background-repeat: no-repeat; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); + background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); + + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + + color: #333; + font-size: 13px; + line-height: normal; + border: 1px solid #ccc; + border-bottom-color: #bbb; + -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); + -webkit-transition: 0.1s linear background-image; + -moz-transition: 0.1s linear background-image; + -ms-transition: 0.1s linear background-image; + -o-transition: 0.1s linear background-image; + transition: 0.1s linear background-image; + overflow: visible; + + } + + +.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { + background-position: 0 -15px; + color: #333; + text-decoration: none; + } + +.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #212121; text-decoration: none; } +.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; font-weight: normal; color: #212121; } +.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; } +.ui-widget :active { outline: none; } + +/* Interaction Cues +----------------------------------*/ + + +.ui-state-highlight p, .ui-state-error p, .ui-state-default p{ + font-size: 13px; + font-weight: normal; + line-height: 18px; + margin:7px 15px; +} +.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight { + + + position: relative; + margin-bottom: 18px; + color: #404040; + background-color: #eedc94; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94)); + background-image: -moz-linear-gradient(top, #fceec1, #eedc94); + background-image: -ms-linear-gradient(top, #fceec1, #eedc94); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94)); + background-image: -webkit-linear-gradient(top, #fceec1, #eedc94); + background-image: -o-linear-gradient(top, #fceec1, #eedc94); + background-image: linear-gradient(top, #fceec1, #eedc94); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #eedc94 #eedc94 #e4c652; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + border-width: 1px; + border-style: solid; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + + +} +.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error { + + + position: relative; + margin-bottom: 18px; + color: #ffffff; + border-width: 1px; + border-style: solid; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); + background-color: #c43c35; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35)); + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(top, #ee5f5b, #c43c35); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #c43c35 #c43c35 #882a25; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + + +} +.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } +.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */ + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_f6cf3b_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, +.ui-corner-top, +.ui-corner-left, +.ui-corner-tl { + -moz-border-radius-topleft: 4px; + -webkit-border-top-left-radius: 4px; + -khtml-border-top-left-radius: 4px; + border-top-left-radius: 4px; +} +.ui-corner-all, +.ui-corner-top, +.ui-corner-right, +.ui-corner-tr { + -moz-border-radius-topright: 4px; + -webkit-border-top-right-radius: 4px; + -khtml-border-top-right-radius: 4px; + border-top-right-radius: 4px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-left, +.ui-corner-bl { + -moz-border-radius-bottomleft: 4px; + -webkit-border-bottom-left-radius: 4px; + -khtml-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-right, +.ui-corner-br { + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-right-radius: 4px; + -khtml-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; +} + + +/* Overlays */ + +.ui-widget-overlay { + background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; + opacity: .30; + filter:Alpha(Opacity=30); +} + +.ui-widget-shadow { + margin: -8px 0 0 -8px; + padding: 8px; + background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; + opacity: .30;filter:Alpha(Opacity=30); + -moz-border-radius: 8px; + -khtml-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; +} + +/* + * jQuery UI Accordion 1.10.0 + * + * Copyright 2013, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://jqueryui.com/accordion/ + */ + +/* IE/Win - Fix animation bug - #4615 */ + +.ui-accordion { + width: 100%; +} +.ui-accordion .ui-accordion-header { + cursor: pointer; + position: relative; + margin-top: 1px; + zoom: 1; + font-weight:bold; +} +.ui-accordion .ui-accordion-li-fix { + display: inline; +} +.ui-accordion .ui-accordion-header-active { + border-bottom: 0 !important; +} +.ui-accordion .ui-accordion-header a { + display: block; + font-size: 1em; + padding: .5em .5em .5em 1.7em; +} +.ui-accordion-icons .ui-accordion-header a { + padding-left: 2.2em; +} +.ui-accordion .ui-accordion-header .ui-icon { + position: absolute; + left: .5em; + top: 50%; + margin-top: -8px; +} +.ui-accordion .ui-accordion-content { + padding: 1em 2.2em; + border-top: 0; + margin-top: -2px; + position: relative; + top: 1px; + margin-bottom: 2px; + overflow: auto; + display: none; + zoom: 1; +} +.ui-accordion .ui-accordion-content-active { + display: block; +} + +/* + * jQuery UI Autocomplete 1.10.0 + * + * Copyright 2013, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://jqueryui.com/autocomplete/ + */ + +.ui-autocomplete { + position: absolute; + top: 0; + left: 0; + cursor: default; +} + +/* + * jQuery UI Button 1.10.0 + * + * Copyright 2013, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Button#theming + */ + +.ui-button { + + cursor: pointer; + display: inline-block; + background-color: #e6e6e6; + background-repeat: no-repeat; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); + background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); + padding: 5px 14px 6px; + margin: 0; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + color: #333; + font-size: 13px; + line-height: normal; + border: 1px solid #ccc; + border-bottom-color: #bbb; + + -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); + -webkit-transition: 0.1s linear background-image; + -moz-transition: 0.1s linear background-image; + -ms-transition: 0.1s linear background-image; + -o-transition: 0.1s linear background-image; + transition: 0.1s linear background-image; + overflow: visible; +} /* the overflow property removes extra width in IE */ + +.ui-button-primary { + color: #ffffff; + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} + + +.ui-button-success{ + color:#ffffff; + background-color: #57a957; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957)); + background-image: -moz-linear-gradient(top, #62c462, #57a957); + background-image: -ms-linear-gradient(top, #62c462, #57a957); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957)); + background-image: -webkit-linear-gradient(top, #62c462, #57a957); + background-image: -o-linear-gradient(top, #62c462, #57a957); + background-image: linear-gradient(top, #62c462, #57a957); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #57a957 #57a957 #3d773d; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} + +.ui-button-error{ + color:#ffffff; + background-color: #c43c35; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35)); + background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35)); + background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); + background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); + background-image: linear-gradient(top, #ee5f5b, #c43c35); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #c43c35 #c43c35 #882a25; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} + +.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ +button.ui-button-icon-only { } /* button elements seem to need a little more width */ +.ui-button-icons-only { width: 3.4em; } +button.ui-button-icons-only { width: 3.7em; } + +/*button text element */ + +.ui-button .ui-button-text { display: block; } +.ui-button-text-only .ui-button-text { } +.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; /*tempfix*/ display:none;} +.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } +.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } +.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } +/* no icon support for input elements, provide padding by default */ +/* input.ui-button { padding: .4em 1em; } */ + +/*button icon element(s) */ +.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { top: 50%; margin-top:-3px; margin-bottom:3px; } +.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } +.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } +.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } +.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } + +/*button sets*/ + + +.ui-buttonset { margin-right: 7px; } +.ui-buttonset .ui-state-active { + color: #ffffff; + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +.ui-buttonset .ui-button { margin-left: 0; margin-right: -.4em; } + +/* workarounds */ +button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ + + +/* + * jQuery UI Menu 1.10.0 + * +* Copyright 2013, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ + +.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; float:left; outline: none; } +.ui-menu .ui-menu { margin-top: -3px; position: absolute; } +.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1;float: left;clear: left; width: 100%; } +.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; } +.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; } +.ui-menu .ui-menu-item a.ui-state-focus, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: 0; + color: #ffffff; + background: #0064cd; + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +/* Fix problem with border in ui-state-active */ +.ui-menu .ui-menu-item a.ui-state-active { + padding: 1px .4em; +} + +.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; } +.ui-menu .ui-state-disabled a { cursor: default; } + +/* icon support */ +.ui-menu-icons { position: relative; } +.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; } + +/* left-aligned */ +.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; } + +/* right-aligned */ +.ui-menu .ui-menu-icon { position: static; float: right; } + +.ui-menu { width: 200px; margin-bottom: 2em; } + + +/* + * jQuery UI spinner 1.10.0 + * +* Copyright 2013, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Menu#theming + */ + +.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; } +.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; } +.ui-spinner{} +.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; } +.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */ +.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */ +.ui-spinner-up { top: 0; } +.ui-spinner-down { bottom: 0; } + +/* TR overrides */ +.ui-spinner .ui-icon-triangle-1-s { + /* need to fix icons sprite */ + background-position:-65px -16px; +} + +/* + * jQuery UI Dialog 1.10.0 + * + * Copyright 2013, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Dialog#theming + */ +.ui-dialog { + position: absolute; + top: 0; + left: 0; + padding: .2em; + width: 300px; + overflow: hidden; + outline: 0; + background-clip: padding-box; + background-color: #FFFFFF; + border: 1px solid rgba(0, 0, 0, 0.3); + border-radius: 6px 6px 6px 6px; + box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3); + /*left: 50%; + margin-left: -280px;*/ + outline: medium none; + position: fixed; + /*top: 10%; + width: 560px;*/ + z-index: 1050; +} +.ui-dialog .ui-dialog-titlebar { /*padding: .4em 1em;*/ + position: relative; + padding:5px 15px; + border:0px 0px 0px 1px solid; + border-color: white; + padding: 5px 15px; + font-size: 18px; + text-decoration:none; + background:none; + -moz-border-radius-bottomright: 0px; + -webkit-border-bottom-right-radius: 0px; + -khtml-border-bottom-right-radius: 0px; + + -moz-border-radius-bottomleft: 0px; + -webkit-border-bottom-left-radius: 0px; + -khtml-border-bottom-left-radius: 0px; + border-bottom-left-radius: 0px; + border-bottom:1px solid #ccc; +} +.ui-dialog .ui-dialog-title { + float: left; + color:#404040; + font-weight:bold; + margin-top:5px; + margin-bottom:5px; + padding:5px; + text-overflow: ellipsis; + overflow: hidden; +} +.ui-dialog .ui-dialog-titlebar-close { + position: absolute; + right: .3em; + top: 50%; + width: 19px; + margin: -20px 0 0 0; + padding: 1px; + height: 18px; + font-size: 20px; + font-weight: bold; + line-height: 13.5px; + text-shadow: 0 1px 0 #ffffff; + filter: alpha(opacity=25); + -khtml-opacity: 0.25; + -moz-opacity: 0.25; + opacity: 0.25; + background:none; + border-width: 0; + border:none; + box-shadow: none; +} + +.ui-dialog .ui-dialog-titlebar-close span { + display: block; + margin: 1px; + text-indent: 9999px; +} + +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 1px; filter: alpha(opacity=90); + -khtml-opacity: 0.90; + -moz-opacity: 0.90; + opacity: 0.90; +} + +.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } + +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0 0; + background-image: none; + margin: .5em 0 0 0; + background-color: #f5f5f5; + padding: 5px 15px 5px; + 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; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; + zoom: 1; + margin-bottom: 0; + +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } +.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } + +.ui-dialog-buttonpane .ui-dialog-buttonset .ui-button{ + color: #ffffff; + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); +} +/* + * jQuery UI Slider 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Slider#theming + */ +.ui-slider { position: relative; text-align: left; } +.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } +.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; + + color: #ffffff; + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + +} + +.ui-slider-horizontal { height: .8em; } +.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } +.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } +.ui-slider-horizontal .ui-slider-range-min { left: 0; } +.ui-slider-horizontal .ui-slider-range-max { right: 0; } + +.ui-slider-vertical { width: .8em; height: 100px; } +.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } +.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } +.ui-slider-vertical .ui-slider-range-min { bottom: 0; } +.ui-slider-vertical .ui-slider-range-max { top: 0; } + +/* + * jQuery UI Tabs 1.9.2 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://jqueryui.com/tabs/ + */ + .ui-tabs .ui-tabs-nav{ background:none; border-color: #ddd;border-style: solid;border-width: 0 0 1px;} +.ui-tabs { position: relative; padding: .2em; zoom: 1; border:0px;} /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ + + +.ui-tabs .ui-tabs-nav li:hover, .ui-tabs .ui-tabs-nav li a:hover{ + background:whiteSmoke; + border-bottom:1px solid #ddd; + padding-bottom:0px; + color:#00438A; +} + +.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; border-bottom:1px solid #DDD; } +.ui-tabs .ui-tabs-nav li { text-decoration: none; list-style: none; float: left; position: relative; top: 1px; padding: 0px 0px 1px 0px; white-space: nowrap; background:none; border:0px; } + +.ui-tabs-nav .ui-state-default{ + -webkit-box-shadow: 0px 0px 0px #ffffff; /* Saf3-4, iOS 4.0.2 - 4.2, Android 2.3+ */ + -moz-box-shadow: 0px 0px 0px #ffffff; /* FF3.5 - 3.6 */ + box-shadow: 0px 0px 0px #ffffff; /* Opera 10.5, IE9, FF4+, Chrome 6+, iOS 5 */ +} +.ui-tabs .ui-tabs-nav li a { + float: left; + text-decoration: none; + cursor: text; + padding: 0 15px; + margin-right: 2px; + line-height: 34px; + border: 1px solid transparent; + -webkit-border-radius: 4px 4px 0 0; + -moz-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; + + + } + +.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: 0; padding-bottom: 0px; outline:none;} +.ui-tabs .ui-tabs-nav li.ui-tabs-active , .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { + background-color: #ffffff; + border: 1px solid #ddd; + border-bottom-color: #ffffff; + cursor: default; + color:gray; + outline:none; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active a{background-color: #ffffff;outline:none;border:none;} +.ui-tabs .ui-tabs-nav li.ui-tabs-active:hover{ + background:#ffffff; + outline:none; + margin-bottom:0px; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; } +.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; color:#0069D6; background:none; font-weight:normal; margin-bottom:-1px;} +/* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } +.ui-tabs-panel .ui-button{text-decoration:none;} +.ui-tabs .ui-tabs-hide { display: none !important; } + + +/* IE fix for background inheritance from ui-widget*/ +.ui-tabs .ui-tabs-nav li{ + filter:none; +} + +/* + * jQuery UI Tooltip 1.9.0 + * + * Copyright 2012-10-11, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://jqueryui.com/tooltip/ + */ +.ui-tooltip { + padding:8px; + position:absolute; + z-index:9999; + max-width: 300px; + -o-box-shadow: 0 0 5px #ddd; + -moz-box-shadow: 0 0 5px #ddd; + -webkit-box-shadow: 0 0 5px #ddd; + /*box-shadow: 0 2px 5px #ddd;*/ + box-shadow: inset 0 1px 0 #ffffff; +} + +body .ui-tooltip { border-width:2px; } + +/* + * jQuery UI Datepicker 1.9.0 + * + * Copyright 2012-10-11, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://jqueryui.com/datepicker/ + */ +.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; border:0px; font-weight: bold; width: 100%; padding: 4px 0; background-color: #f5f5f5; color: #808080; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } + +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { /*top: 1px;*/ } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } + +.ui-datepicker .ui-datepicker-prev-hover { /*left:1px;*/ } +.ui-datepicker .ui-datepicker-next-hover { /*right:1px;*/ } + +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +} + +.ui-datepicker th{ + font-weight: bold; + color: gray; +} + +.ui-datepicker-today a:hover{ + background-color: #808080; + color: #ffffff; + +} +.ui-datepicker-today a{ + background-color: #BFBFBF; + cursor: pointer; + padding: 0 4px; + margin-bottom:0px; + +} + + +.ui-datepicker td a{ + margin-bottom:0px; + border:0px; +} + +.ui-datepicker td:hover{ + color: #ffffff; +} + +.ui-datepicker td .ui-state-default { + border:0px; + background:none; + margin-bottom:0px; + padding:5px; + color:gray; + text-align: center; + filter:none; +} + + +.ui-datepicker td .ui-state-active{ + background:#BFBFBF; + margin-bottom:0px; + font-size:normal; + text-shadow: 0px; + color: #ffffff; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} + +.ui-datepicker td .ui-state-hover { + color: #ffffff; + background: #0064cd; + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; +} + +/* + * jQuery UI Progressbar 1.8.16 + * + * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Progressbar#theming + */ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; + +/*this can be removed if ui-widget-header is blue*/ + color: #ffffff; + background-color: #0064cd; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd)); + background-image: -moz-linear-gradient(top, #049cdb, #0064cd); + background-image: -ms-linear-gradient(top, #049cdb, #0064cd); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd)); + background-image: -webkit-linear-gradient(top, #049cdb, #0064cd); + background-image: -o-linear-gradient(top, #049cdb, #0064cd); + background-image: linear-gradient(top, #049cdb, #0064cd); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0); + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + border-color: #0064cd #0064cd #003f81; + border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); + } + + + +/*** Input field styling from Bootstrap **/ + input, textarea { + -webkit-transition: border linear 0.2s, box-shadow linear 0.2s; + -moz-transition: border linear 0.2s, box-shadow linear 0.2s; + -ms-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; + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); +} +input:focus, textarea:focus { + outline: 0; + border-color: rgba(82, 168, 236, 0.8); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); +} +input[type=file]:focus, input[type=checkbox]:focus, select:focus { + -webkit-box-shadow: none; + -moz-box-shadow: none; + box-shadow: none; + outline: 1px dotted #666; +} + +input[type="text"], +input[type="password"], +.ui-autocomplete-input, +textarea, +.uneditable-input { + display: inline-block; + padding: 4px; + font-size: 13px; + line-height: 18px; + color: #808080; + border: 1px solid #ccc; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + + + +/**Toolbar**/ + +.ui-toolbar{ + padding: 7px 14px; + margin: 0 0 18px; + background-color: #f5f5f5; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#ffffff), to(#f5f5f5)); + background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f5f5f5)); + background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); + background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); + background-image: linear-gradient(top, #ffffff, #f5f5f5); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); + border: 1px solid #ddd; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + -webkit-box-shadow: inset 0 1px 0 #ffffff; + -moz-box-shadow: inset 0 1px 0 #ffffff; + box-shadow: inset 0 1px 0 #ffffff; +} + + +/***Dialog fixes**/ + +.ui-dialog-buttonset .ui-button:nth-child(2){ + cursor: pointer; + display: inline-block; + background-color: #e6e6e6; + background-repeat: no-repeat; + background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6); + background-image: -ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: -o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + background-image: linear-gradient(#ffffff, #ffffff 25%, #e6e6e6); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0); + padding: 5px 14px 6px; + text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75); + color: #333; + font-size: 13px; + line-height: normal; + border: 1px solid #ccc; + border-bottom-color: #bbb; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + -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); + -webkit-transition: 0.1s linear all; + -moz-transition: 0.1s linear all; + -ms-transition: 0.1s linear all; + -o-transition: 0.1s linear all; + transition: 0.1s linear all; + overflow: visible; +} + + + +/***Wijmo Theming**/ + +div.wijmo-wijmenu{ + padding:0 20px; + background-color: #222; + background-color: #222222; + background-repeat: repeat-x; + background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222)); + background-image: -moz-linear-gradient(top, #333333, #222222); + background-image: -ms-linear-gradient(top, #333333, #222222); + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222)); + background-image: -webkit-linear-gradient(top, #333333, #222222); + background-image: -o-linear-gradient(top, #333333, #222222); + background-image: linear-gradient(top, #333333, #222222); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); + -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); +} + +.wijmo-wijmenu .ui-state-default{ + box-shadow: none; + color:#BFBFBF; +} + +.wijmo-wijmenu .ui-state-default .wijmo-wijmenu-text{ + color:#BFBFBF; +} + +.wijmo-wijmenu .ui-state-hover{ + background: #444; + background: rgba(255, 255, 255, 0.05); +} + +.wijmo-wijmenu .ui-state-hover .wijmo-wijmenu-text{ + color:#ffffff; +} + +div.wijmo-wijmenu .ui-widget-header h3{ + position: relative; + margin-top:1px; + padding:0; +} + +.wijmo-wijmenu h3 a{ + color: #FFFFFF; + display: block; + float: left; + font-size: 20px; + font-weight: 200; + line-height: 1; + margin-left: -20px; + margin-top:1px; + padding: 8px 20px 12px; +} + +.wijmo-wijmenu h3 a:hover{ + background-color: rgba(255, 255, 255, 0.05); + color: #FFFFFF; + text-decoration: none; +} + +.wijmo-wijmenu .ui-widget-header{ + border:0px; +} + +.wijmo-wijmenu .wijmo-wijmenu-parent .wijmo-wijmenu-child{ + padding: 0.3em 0; +} + +div.wijmo-wijmenu .wijmo-wijmenu-item .wijmo-wijmenu-child{ + background: #333; + border:0; + margin:0; + padding: 6px 0; + width:160px; + -webkit-border-radius: 0 0 6px 6px; + -moz-border-radius: 0 0 6px 6px; + border-radius: 0 0 6px 6px; + -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + -moz-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + +div.wijmo-wijmenu .wijmo-wijmenu-item{ + margin:0; + border:0; +} + +.wijmo-wijmenu a.wijmo-wijmenu-link{ + margin:0; + line-height: 19px; + padding: 10px 10px 11px; + border:0; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius:0; +} + +div.wijmo-wijmenu .wijmo-wijmenu-child .wijmo-wijmenu-link{ + display:block; + float:none; + padding: 4px 15px; + width:auto; +} + +div.wijmo-wijmenu .wijmo-wijmenu-child .wijmo-wijmenu-text +{ + float:none; +} + +.wijmo-wijmenu .wijmo-wijmenu-item .wijmo-wijmenu-child .ui-state-hover { + background: #191919; +} + +.wijmo-wijmenu .wijmo-wijmenu-item .wijmo-wijmenu-separator{ + padding: 5px 0; + background-image: none; + background-color: #222; + border-top: 1px solid #444; + border-bottom:0; + border-left:0; + border-right:0; +} + +.wijmo-wijmenu .wijmo-wijmenu-item input { + -moz-transition: none 0s ease 0s; + background-color: rgba(255, 255, 255, 0.3); + border: 1px solid #111111; + border-radius: 4px 4px 4px 4px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1) inset, 0 1px 0 rgba(255, 255, 255, 0.25); + color: rgba(255, 255, 255, 0.75); + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + line-height: 1; + margin: 5px 10px 0 10px; + padding: 4px 9px; + width:100px; +} + +.wijmo-wijmenu .wijmo-wijmenu-item input:hover { + background-color: rgba(255, 255, 255, 0.5); + color: #FFFFFF; +} + +.wijmo-wijmenu .wijmo-wijmenu-item input:focus { + background-color: #FFFFFF; + border: 0 none; + box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); + color: #404040; + outline: 0 none; + padding: 5px 10px; + text-shadow: 0 1px 0 #FFFFFF; +} + + +.wijmo-wijmenu .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { + text-shadow:none; +} + + +.wijmo-wijmenu .ui-state-default{ + box-shadow: none; + color:#BFBFBF; + filter: none; +} + diff --git a/src/static/jquery/jquery-ui/jquery-ui-bootstrap/jquery.ui.1.10.0.ie.css b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/jquery.ui.1.10.0.ie.css new file mode 100644 index 0000000..b7392b0 --- /dev/null +++ b/src/static/jquery/jquery-ui/jquery-ui-bootstrap/jquery.ui.1.10.0.ie.css @@ -0,0 +1,16 @@ + +.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-left, .ui-corner-bottom{ border-radius:0px;} +/* + * jQuery UI Tabs 1.9.0 + * + * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://jqueryui.com/tabs/ + */ + +.ui-state-active,.ui-tabs-selected { border-radius:0px;} +.ui-tabs-selected { border-radius:0px;} +.ui-tabs .ui-tabs-nav li{ filter:none;} +.ui-tabs .ui-tabs-nav li a { border-radius:0px; } diff --git a/src/static/jquery/jquery.qtip/jquery.qtip.min.css b/src/static/jquery/jquery.qtip/jquery.qtip.min.css new file mode 100755 index 0000000..e470d33 --- /dev/null +++ b/src/static/jquery/jquery.qtip/jquery.qtip.min.css @@ -0,0 +1,2 @@ +/* qTip2 v2.2.0 css3 | qtip2.com | Licensed MIT, GPL | Thu Nov 21 2013 23:04:06 */ +.qtip{position:absolute;left:-28000px;top:-28000px;display:none;max-width:280px;min-width:50px;font-size:10.5px;line-height:12px;direction:ltr;box-shadow:none;padding:0}.qtip-content{position:relative;padding:5px 9px;overflow:hidden;text-align:left;word-wrap:break-word}.qtip-titlebar{position:relative;padding:5px 35px 5px 10px;overflow:hidden;border-width:0 0 1px;font-weight:700}.qtip-titlebar+.qtip-content{border-top-width:0!important}.qtip-close{position:absolute;right:-9px;top:-9px;cursor:pointer;outline:medium none;border-width:1px;border-style:solid;border-color:transparent}.qtip-titlebar .qtip-close{right:4px;top:50%;margin-top:-9px}* html .qtip-titlebar .qtip-close{top:16px}.qtip-titlebar .ui-icon,.qtip-icon .ui-icon{display:block;text-indent:-1000em;direction:ltr}.qtip-icon,.qtip-icon .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;text-decoration:none}.qtip-icon .ui-icon{width:18px;height:14px;line-height:14px;text-align:center;text-indent:0;font:400 bold 10px/13px Tahoma,sans-serif;color:inherit;background:transparent none no-repeat -100em -100em}.qtip-focus{}.qtip-hover{}.qtip-default{border-width:1px;border-style:solid;border-color:#F1D031;background-color:#FFFFA3;color:#555}.qtip-default .qtip-titlebar{background-color:#FFEF93}.qtip-default .qtip-icon{border-color:#CCC;background:#F1F1F1;color:#777}.qtip-default .qtip-titlebar .qtip-close{border-color:#AAA;color:#111}.qtip-shadow{-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);-moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);box-shadow:1px 1px 3px 1px rgba(0,0,0,.15)}.qtip-rounded,.qtip-tipsy,.qtip-bootstrap{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.qtip-rounded .qtip-titlebar{-moz-border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.qtip-youtube{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 3px #333;-moz-box-shadow:0 0 3px #333;box-shadow:0 0 3px #333;color:#fff;border-width:0;background:#4A4A4A;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4A4A4A),color-stop(100%,#000));background-image:-webkit-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-moz-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-ms-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-o-linear-gradient(top,#4A4A4A 0,#000 100%)}.qtip-youtube .qtip-titlebar{background-color:#4A4A4A;background-color:rgba(0,0,0,0)}.qtip-youtube .qtip-content{padding:.75em;font:12px arial,sans-serif;filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#4a4a4a, EndColorStr=#000000);-ms-filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#4a4a4a, EndColorStr=#000000);"}.qtip-youtube .qtip-icon{border-color:#222}.qtip-youtube .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-jtools{background:#232323;background:rgba(0,0,0,.7);background-image:-webkit-gradient(linear,left top,left bottom,from(#717171),to(#232323));background-image:-moz-linear-gradient(top,#717171,#232323);background-image:-webkit-linear-gradient(top,#717171,#232323);background-image:-ms-linear-gradient(top,#717171,#232323);background-image:-o-linear-gradient(top,#717171,#232323);border:2px solid #ddd;border:2px solid rgba(241,241,241,1);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 12px #333;-moz-box-shadow:0 0 12px #333;box-shadow:0 0 12px #333}.qtip-jtools .qtip-titlebar{background-color:transparent;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171, endColorstr=#4A4A4A);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171, endColorstr=#4A4A4A)"}.qtip-jtools .qtip-content{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A, endColorstr=#232323);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A, endColorstr=#232323)"}.qtip-jtools .qtip-titlebar,.qtip-jtools .qtip-content{background:transparent;color:#fff;border:0 dashed transparent}.qtip-jtools .qtip-icon{border-color:#555}.qtip-jtools .qtip-titlebar .ui-state-hover{border-color:#333}.qtip-cluetip{-webkit-box-shadow:4px 4px 5px rgba(0,0,0,.4);-moz-box-shadow:4px 4px 5px rgba(0,0,0,.4);box-shadow:4px 4px 5px rgba(0,0,0,.4);background-color:#D9D9C2;color:#111;border:0 dashed transparent}.qtip-cluetip .qtip-titlebar{background-color:#87876A;color:#fff;border:0 dashed transparent}.qtip-cluetip .qtip-icon{border-color:#808064}.qtip-cluetip .qtip-titlebar .ui-state-hover{border-color:#696952;color:#696952}.qtip-tipsy{background:#000;background:rgba(0,0,0,.87);color:#fff;border:0 solid transparent;font-size:11px;font-family:'Lucida Grande',sans-serif;font-weight:700;line-height:16px;text-shadow:0 1px #000}.qtip-tipsy .qtip-titlebar{padding:6px 35px 0 10px;background-color:transparent}.qtip-tipsy .qtip-content{padding:6px 10px}.qtip-tipsy .qtip-icon{border-color:#222;text-shadow:none}.qtip-tipsy .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-tipped{border:3px solid #959FA9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-color:#F9F9F9;color:#454545;font-weight:400;font-family:serif}.qtip-tipped .qtip-titlebar{border-bottom-width:0;color:#fff;background:#3A79B8;background-image:-webkit-gradient(linear,left top,left bottom,from(#3A79B8),to(#2E629D));background-image:-webkit-linear-gradient(top,#3A79B8,#2E629D);background-image:-moz-linear-gradient(top,#3A79B8,#2E629D);background-image:-ms-linear-gradient(top,#3A79B8,#2E629D);background-image:-o-linear-gradient(top,#3A79B8,#2E629D);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8, endColorstr=#2E629D);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8, endColorstr=#2E629D)"}.qtip-tipped .qtip-icon{border:2px solid #285589;background:#285589}.qtip-tipped .qtip-icon .ui-icon{background-color:#FBFBFB;color:#555}.qtip-bootstrap{font-size:14px;line-height:20px;color:#333;padding:1px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(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,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.qtip-bootstrap .qtip-titlebar{padding:8px 14px;margin:0;font-size:14px;font-weight:400;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}.qtip-bootstrap .qtip-titlebar .qtip-close{right:11px;top:45%;border-style:none}.qtip-bootstrap .qtip-content{padding:9px 14px}.qtip-bootstrap .qtip-icon{background:transparent}.qtip-bootstrap .qtip-icon .ui-icon{width:auto;height:auto;float:right;font-size:20px;font-weight:700;line-height:18px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.qtip-bootstrap .qtip-icon .ui-icon:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}.qtip:not(.ie9haxors) div.qtip-content,.qtip:not(.ie9haxors) div.qtip-titlebar{filter:none;-ms-filter:none} \ No newline at end of file diff --git a/src/static/jquery/jquery.qtip/jquery.qtip.min.js b/src/static/jquery/jquery.qtip/jquery.qtip.min.js new file mode 100755 index 0000000..e0446a0 --- /dev/null +++ b/src/static/jquery/jquery.qtip/jquery.qtip.min.js @@ -0,0 +1,5 @@ +/* qTip2 v2.2.0 None | qtip2.com | Licensed MIT, GPL | Thu Nov 21 2013 21:17:12 */ +!function(a,b,c){!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):jQuery&&!jQuery.fn.qtip&&a(jQuery)}(function(d){"use strict";function e(a,b,c,e){this.id=c,this.target=a,this.tooltip=A,this.elements={target:a},this._id=J+"-"+c,this.timers={img:{}},this.options=b,this.plugins={},this.cache={event:{},target:d(),disabled:z,attr:e,onTooltip:z,lastClass:""},this.rendered=this.destroyed=this.disabled=this.waiting=this.hiddenDuringWait=this.positioning=this.triggering=z}function f(a){return a===A||"object"!==d.type(a)}function g(a){return!(d.isFunction(a)||a&&a.attr||a.length||"object"===d.type(a)&&(a.jquery||a.then))}function h(a){var b,c,e,h;return f(a)?z:(f(a.metadata)&&(a.metadata={type:a.metadata}),"content"in a&&(b=a.content,f(b)||b.jquery||b.done?b=a.content={text:c=g(b)?z:b}:c=b.text,"ajax"in b&&(e=b.ajax,h=e&&e.once!==z,delete b.ajax,b.text=function(a,b){var f=c||d(this).attr(b.options.content.attr)||"Loading...",g=d.ajax(d.extend({},e,{context:b})).then(e.success,A,e.error).then(function(a){return a&&h&&b.set("content.text",a),a},function(a,c,d){b.destroyed||0===a.status||b.set("content.text",c+": "+d)});return h?f:(b.set("content.text",f),g)}),"title"in b&&(f(b.title)||(b.button=b.title.button,b.title=b.title.text),g(b.title||z)&&(b.title=z))),"position"in a&&f(a.position)&&(a.position={my:a.position,at:a.position}),"show"in a&&f(a.show)&&(a.show=a.show.jquery?{target:a.show}:a.show===y?{ready:y}:{event:a.show}),"hide"in a&&f(a.hide)&&(a.hide=a.hide.jquery?{target:a.hide}:{event:a.hide}),"style"in a&&f(a.style)&&(a.style={classes:a.style}),d.each(I,function(){this.sanitize&&this.sanitize(a)}),a)}function i(a,b){for(var c,d=0,e=a,f=b.split(".");e=e[f[d++]];)d<f.length&&(c=e);return[c||a,f.pop()]}function j(a,b){var c,d,e;for(c in this.checks)for(d in this.checks[c])(e=new RegExp(d,"i").exec(a))&&(b.push(e),("builtin"===c||this.plugins[c])&&this.checks[c][d].apply(this.plugins[c]||this,b))}function k(a){return M.concat("").join(a?"-"+a+" ":" ")}function l(c){return c&&{type:c.type,pageX:c.pageX,pageY:c.pageY,target:c.target,relatedTarget:c.relatedTarget,scrollX:c.scrollX||a.pageXOffset||b.body.scrollLeft||b.documentElement.scrollLeft,scrollY:c.scrollY||a.pageYOffset||b.body.scrollTop||b.documentElement.scrollTop}||{}}function m(a,b){return b>0?setTimeout(d.proxy(a,this),b):(a.call(this),void 0)}function n(a){return this.tooltip.hasClass(T)?z:(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this.timers.show=m.call(this,function(){this.toggle(y,a)},this.options.show.delay),void 0)}function o(a){if(this.tooltip.hasClass(T))return z;var b=d(a.relatedTarget),c=b.closest(N)[0]===this.tooltip[0],e=b[0]===this.options.show.target[0];if(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this!==b[0]&&"mouse"===this.options.position.target&&c||this.options.hide.fixed&&/mouse(out|leave|move)/.test(a.type)&&(c||e))try{a.preventDefault(),a.stopImmediatePropagation()}catch(f){}else this.timers.hide=m.call(this,function(){this.toggle(z,a)},this.options.hide.delay,this)}function p(a){return this.tooltip.hasClass(T)||!this.options.hide.inactive?z:(clearTimeout(this.timers.inactive),this.timers.inactive=m.call(this,function(){this.hide(a)},this.options.hide.inactive),void 0)}function q(a){this.rendered&&this.tooltip[0].offsetWidth>0&&this.reposition(a)}function r(a,c,e){d(b.body).delegate(a,(c.split?c:c.join($+" "))+$,function(){var a=t.api[d.attr(this,L)];a&&!a.disabled&&e.apply(a,arguments)})}function s(a,c,f){var g,i,j,k,l,m=d(b.body),n=a[0]===b?m:a,o=a.metadata?a.metadata(f.metadata):A,p="html5"===f.metadata.type&&o?o[f.metadata.name]:A,q=a.data(f.metadata.name||"qtipopts");try{q="string"==typeof q?d.parseJSON(q):q}catch(r){}if(k=d.extend(y,{},t.defaults,f,"object"==typeof q?h(q):A,h(p||o)),i=k.position,k.id=c,"boolean"==typeof k.content.text){if(j=a.attr(k.content.attr),k.content.attr===z||!j)return z;k.content.text=j}if(i.container.length||(i.container=m),i.target===z&&(i.target=n),k.show.target===z&&(k.show.target=n),k.show.solo===y&&(k.show.solo=i.container.closest("body")),k.hide.target===z&&(k.hide.target=n),k.position.viewport===y&&(k.position.viewport=i.container),i.container=i.container.eq(0),i.at=new v(i.at,y),i.my=new v(i.my),a.data(J))if(k.overwrite)a.qtip("destroy",!0);else if(k.overwrite===z)return z;return a.attr(K,c),k.suppress&&(l=a.attr("title"))&&a.removeAttr("title").attr(V,l).attr("title",""),g=new e(a,k,c,!!j),a.data(J,g),a.one("remove.qtip-"+c+" removeqtip.qtip-"+c,function(){var a;(a=d(this).data(J))&&a.destroy(!0)}),g}var t,u,v,w,x,y=!0,z=!1,A=null,B="x",C="y",D="top",E="left",F="bottom",G="right",H="center",I={},J="qtip",K="data-hasqtip",L="data-qtip-id",M=["ui-widget","ui-tooltip"],N="."+J,O="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),P=J+"-fixed",Q=J+"-default",R=J+"-focus",S=J+"-hover",T=J+"-disabled",U="_replacedByqTip",V="oldtitle",W={ie:function(){for(var a=3,c=b.createElement("div");(c.innerHTML="<!--[if gt IE "+ ++a+"]><i></i><![endif]-->")&&c.getElementsByTagName("i")[0];);return a>4?a:0/0}(),iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))||z};u=e.prototype,u._when=function(a){return d.when.apply(d,a)},u.render=function(a){if(this.rendered||this.destroyed)return this;var b,c=this,e=this.options,f=this.cache,g=this.elements,h=e.content.text,i=e.content.title,j=e.content.button,k=e.position,l=("."+this._id+" ",[]);return d.attr(this.target[0],"aria-describedby",this._id),this.tooltip=g.tooltip=b=d("<div/>",{id:this._id,"class":[J,Q,e.style.classes,J+"-pos-"+e.position.my.abbrev()].join(" "),width:e.style.width||"",height:e.style.height||"",tracking:"mouse"===k.target&&k.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":z,"aria-describedby":this._id+"-content","aria-hidden":y}).toggleClass(T,this.disabled).attr(L,this.id).data(J,this).appendTo(k.container).append(g.content=d("<div />",{"class":J+"-content",id:this._id+"-content","aria-atomic":y})),this.rendered=-1,this.positioning=y,i&&(this._createTitle(),d.isFunction(i)||l.push(this._updateTitle(i,z))),j&&this._createButton(),d.isFunction(h)||l.push(this._updateContent(h,z)),this.rendered=y,this._setWidget(),d.each(I,function(a){var b;"render"===this.initialize&&(b=this(c))&&(c.plugins[a]=b)}),this._unassignEvents(),this._assignEvents(),this._when(l).then(function(){c._trigger("render"),c.positioning=z,c.hiddenDuringWait||!e.show.ready&&!a||c.toggle(y,f.event,z),c.hiddenDuringWait=z}),t.api[this.id]=this,this},u.destroy=function(a){function b(){if(!this.destroyed){this.destroyed=y;var a=this.target,b=a.attr(V);this.rendered&&this.tooltip.stop(1,0).find("*").remove().end().remove(),d.each(this.plugins,function(){this.destroy&&this.destroy()}),clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this._unassignEvents(),a.removeData(J).removeAttr(L).removeAttr(K).removeAttr("aria-describedby"),this.options.suppress&&b&&a.attr("title",b).removeAttr(V),this._unbind(a),this.options=this.elements=this.cache=this.timers=this.plugins=this.mouse=A,delete t.api[this.id]}}return this.destroyed?this.target:(a===y&&"hide"!==this.triggering||!this.rendered?b.call(this):(this.tooltip.one("tooltiphidden",d.proxy(b,this)),!this.triggering&&this.hide()),this.target)},w=u.checks={builtin:{"^id$":function(a,b,c,e){var f=c===y?t.nextid:c,g=J+"-"+f;f!==z&&f.length>0&&!d("#"+g).length?(this._id=g,this.rendered&&(this.tooltip[0].id=this._id,this.elements.content[0].id=this._id+"-content",this.elements.title[0].id=this._id+"-title")):a[b]=e},"^prerender":function(a,b,c){c&&!this.rendered&&this.render(this.options.show.ready)},"^content.text$":function(a,b,c){this._updateContent(c)},"^content.attr$":function(a,b,c,d){this.options.content.text===this.target.attr(d)&&this._updateContent(this.target.attr(c))},"^content.title$":function(a,b,c){return c?(c&&!this.elements.title&&this._createTitle(),this._updateTitle(c),void 0):this._removeTitle()},"^content.button$":function(a,b,c){this._updateButton(c)},"^content.title.(text|button)$":function(a,b,c){this.set("content."+b,c)},"^position.(my|at)$":function(a,b,c){"string"==typeof c&&(a[b]=new v(c,"at"===b))},"^position.container$":function(a,b,c){this.rendered&&this.tooltip.appendTo(c)},"^show.ready$":function(a,b,c){c&&(!this.rendered&&this.render(y)||this.toggle(y))},"^style.classes$":function(a,b,c,d){this.rendered&&this.tooltip.removeClass(d).addClass(c)},"^style.(width|height)":function(a,b,c){this.rendered&&this.tooltip.css(b,c)},"^style.widget|content.title":function(){this.rendered&&this._setWidget()},"^style.def":function(a,b,c){this.rendered&&this.tooltip.toggleClass(Q,!!c)},"^events.(render|show|move|hide|focus|blur)$":function(a,b,c){this.rendered&&this.tooltip[(d.isFunction(c)?"":"un")+"bind"]("tooltip"+b,c)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){if(this.rendered){var a=this.options.position;this.tooltip.attr("tracking","mouse"===a.target&&a.adjust.mouse),this._unassignEvents(),this._assignEvents()}}}},u.get=function(a){if(this.destroyed)return this;var b=i(this.options,a.toLowerCase()),c=b[0][b[1]];return c.precedance?c.string():c};var X=/^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i,Y=/^prerender|show\.ready/i;u.set=function(a,b){if(this.destroyed)return this;var c,e=this.rendered,f=z,g=this.options;return this.checks,"string"==typeof a?(c=a,a={},a[c]=b):a=d.extend({},a),d.each(a,function(b,c){if(e&&Y.test(b))return delete a[b],void 0;var h,j=i(g,b.toLowerCase());h=j[0][j[1]],j[0][j[1]]=c&&c.nodeType?d(c):c,f=X.test(b)||f,a[b]=[j[0],j[1],c,h]}),h(g),this.positioning=y,d.each(a,d.proxy(j,this)),this.positioning=z,this.rendered&&this.tooltip[0].offsetWidth>0&&f&&this.reposition("mouse"===g.position.target?A:this.cache.event),this},u._update=function(a,b){var c=this,e=this.cache;return this.rendered&&a?(d.isFunction(a)&&(a=a.call(this.elements.target,e.event,this)||""),d.isFunction(a.then)?(e.waiting=y,a.then(function(a){return e.waiting=z,c._update(a,b)},A,function(a){return c._update(a,b)})):a===z||!a&&""!==a?z:(a.jquery&&a.length>0?b.empty().append(a.css({display:"block",visibility:"visible"})):b.html(a),this._waitForContent(b).then(function(a){a.images&&a.images.length&&c.rendered&&c.tooltip[0].offsetWidth>0&&c.reposition(e.event,!a.length)}))):z},u._waitForContent=function(a){var b=this.cache;return b.waiting=y,(d.fn.imagesLoaded?a.imagesLoaded():d.Deferred().resolve([])).done(function(){b.waiting=z}).promise()},u._updateContent=function(a,b){this._update(a,this.elements.content,b)},u._updateTitle=function(a,b){this._update(a,this.elements.title,b)===z&&this._removeTitle(z)},u._createTitle=function(){var a=this.elements,b=this._id+"-title";a.titlebar&&this._removeTitle(),a.titlebar=d("<div />",{"class":J+"-titlebar "+(this.options.style.widget?k("header"):"")}).append(a.title=d("<div />",{id:b,"class":J+"-title","aria-atomic":y})).insertBefore(a.content).delegate(".qtip-close","mousedown keydown mouseup keyup mouseout",function(a){d(this).toggleClass("ui-state-active ui-state-focus","down"===a.type.substr(-4))}).delegate(".qtip-close","mouseover mouseout",function(a){d(this).toggleClass("ui-state-hover","mouseover"===a.type)}),this.options.content.button&&this._createButton()},u._removeTitle=function(a){var b=this.elements;b.title&&(b.titlebar.remove(),b.titlebar=b.title=b.button=A,a!==z&&this.reposition())},u.reposition=function(c,e){if(!this.rendered||this.positioning||this.destroyed)return this;this.positioning=y;var f,g,h=this.cache,i=this.tooltip,j=this.options.position,k=j.target,l=j.my,m=j.at,n=j.viewport,o=j.container,p=j.adjust,q=p.method.split(" "),r=i.outerWidth(z),s=i.outerHeight(z),t=0,u=0,v=i.css("position"),w={left:0,top:0},x=i[0].offsetWidth>0,A=c&&"scroll"===c.type,B=d(a),C=o[0].ownerDocument,J=this.mouse;if(d.isArray(k)&&2===k.length)m={x:E,y:D},w={left:k[0],top:k[1]};else if("mouse"===k)m={x:E,y:D},!J||!J.pageX||!p.mouse&&c&&c.pageX?c&&c.pageX||((!p.mouse||this.options.show.distance)&&h.origin&&h.origin.pageX?c=h.origin:(!c||c&&("resize"===c.type||"scroll"===c.type))&&(c=h.event)):c=J,"static"!==v&&(w=o.offset()),C.body.offsetWidth!==(a.innerWidth||C.documentElement.clientWidth)&&(g=d(b.body).offset()),w={left:c.pageX-w.left+(g&&g.left||0),top:c.pageY-w.top+(g&&g.top||0)},p.mouse&&A&&J&&(w.left-=(J.scrollX||0)-B.scrollLeft(),w.top-=(J.scrollY||0)-B.scrollTop());else{if("event"===k?c&&c.target&&"scroll"!==c.type&&"resize"!==c.type?h.target=d(c.target):c.target||(h.target=this.elements.target):"event"!==k&&(h.target=d(k.jquery?k:this.elements.target)),k=h.target,k=d(k).eq(0),0===k.length)return this;k[0]===b||k[0]===a?(t=W.iOS?a.innerWidth:k.width(),u=W.iOS?a.innerHeight:k.height(),k[0]===a&&(w={top:(n||k).scrollTop(),left:(n||k).scrollLeft()})):I.imagemap&&k.is("area")?f=I.imagemap(this,k,m,I.viewport?q:z):I.svg&&k&&k[0].ownerSVGElement?f=I.svg(this,k,m,I.viewport?q:z):(t=k.outerWidth(z),u=k.outerHeight(z),w=k.offset()),f&&(t=f.width,u=f.height,g=f.offset,w=f.position),w=this.reposition.offset(k,w,o),(W.iOS>3.1&&W.iOS<4.1||W.iOS>=4.3&&W.iOS<4.33||!W.iOS&&"fixed"===v)&&(w.left-=B.scrollLeft(),w.top-=B.scrollTop()),(!f||f&&f.adjustable!==z)&&(w.left+=m.x===G?t:m.x===H?t/2:0,w.top+=m.y===F?u:m.y===H?u/2:0)}return w.left+=p.x+(l.x===G?-r:l.x===H?-r/2:0),w.top+=p.y+(l.y===F?-s:l.y===H?-s/2:0),I.viewport?(w.adjusted=I.viewport(this,w,j,t,u,r,s),g&&w.adjusted.left&&(w.left+=g.left),g&&w.adjusted.top&&(w.top+=g.top)):w.adjusted={left:0,top:0},this._trigger("move",[w,n.elem||n],c)?(delete w.adjusted,e===z||!x||isNaN(w.left)||isNaN(w.top)||"mouse"===k||!d.isFunction(j.effect)?i.css(w):d.isFunction(j.effect)&&(j.effect.call(i,this,d.extend({},w)),i.queue(function(a){d(this).css({opacity:"",height:""}),W.ie&&this.style.removeAttribute("filter"),a()})),this.positioning=z,this):this},u.reposition.offset=function(a,c,e){function f(a,b){c.left+=b*a.scrollLeft(),c.top+=b*a.scrollTop()}if(!e[0])return c;var g,h,i,j,k=d(a[0].ownerDocument),l=!!W.ie&&"CSS1Compat"!==b.compatMode,m=e[0];do"static"!==(h=d.css(m,"position"))&&("fixed"===h?(i=m.getBoundingClientRect(),f(k,-1)):(i=d(m).position(),i.left+=parseFloat(d.css(m,"borderLeftWidth"))||0,i.top+=parseFloat(d.css(m,"borderTopWidth"))||0),c.left-=i.left+(parseFloat(d.css(m,"marginLeft"))||0),c.top-=i.top+(parseFloat(d.css(m,"marginTop"))||0),g||"hidden"===(j=d.css(m,"overflow"))||"visible"===j||(g=d(m)));while(m=m.offsetParent);return g&&(g[0]!==k[0]||l)&&f(g,1),c};var Z=(v=u.reposition.Corner=function(a,b){a=(""+a).replace(/([A-Z])/," $1").replace(/middle/gi,H).toLowerCase(),this.x=(a.match(/left|right/i)||a.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(a.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase(),this.forceY=!!b;var c=a.charAt(0);this.precedance="t"===c||"b"===c?C:B}).prototype;Z.invert=function(a,b){this[a]=this[a]===E?G:this[a]===G?E:b||this[a]},Z.string=function(){var a=this.x,b=this.y;return a===b?a:this.precedance===C||this.forceY&&"center"!==b?b+" "+a:a+" "+b},Z.abbrev=function(){var a=this.string().split(" ");return a[0].charAt(0)+(a[1]&&a[1].charAt(0)||"")},Z.clone=function(){return new v(this.string(),this.forceY)},u.toggle=function(a,c){var e=this.cache,f=this.options,g=this.tooltip;if(c){if(/over|enter/.test(c.type)&&/out|leave/.test(e.event.type)&&f.show.target.add(c.target).length===f.show.target.length&&g.has(c.relatedTarget).length)return this;e.event=l(c)}if(this.waiting&&!a&&(this.hiddenDuringWait=y),!this.rendered)return a?this.render(1):this;if(this.destroyed||this.disabled)return this;var h,i,j,k=a?"show":"hide",m=this.options[k],n=(this.options[a?"hide":"show"],this.options.position),o=this.options.content,p=this.tooltip.css("width"),q=this.tooltip.is(":visible"),r=a||1===m.target.length,s=!c||m.target.length<2||e.target[0]===c.target;return(typeof a).search("boolean|number")&&(a=!q),h=!g.is(":animated")&&q===a&&s,i=h?A:!!this._trigger(k,[90]),this.destroyed?this:(i!==z&&a&&this.focus(c),!i||h?this:(d.attr(g[0],"aria-hidden",!a),a?(e.origin=l(this.mouse),d.isFunction(o.text)&&this._updateContent(o.text,z),d.isFunction(o.title)&&this._updateTitle(o.title,z),!x&&"mouse"===n.target&&n.adjust.mouse&&(d(b).bind("mousemove."+J,this._storeMouse),x=y),p||g.css("width",g.outerWidth(z)),this.reposition(c,arguments[2]),p||g.css("width",""),m.solo&&("string"==typeof m.solo?d(m.solo):d(N,m.solo)).not(g).not(m.target).qtip("hide",d.Event("tooltipsolo"))):(clearTimeout(this.timers.show),delete e.origin,x&&!d(N+'[tracking="true"]:visible',m.solo).not(g).length&&(d(b).unbind("mousemove."+J),x=z),this.blur(c)),j=d.proxy(function(){a?(W.ie&&g[0].style.removeAttribute("filter"),g.css("overflow",""),"string"==typeof m.autofocus&&d(this.options.show.autofocus,g).focus(),this.options.show.target.trigger("qtip-"+this.id+"-inactive")):g.css({display:"",visibility:"",opacity:"",left:"",top:""}),this._trigger(a?"visible":"hidden")},this),m.effect===z||r===z?(g[k](),j()):d.isFunction(m.effect)?(g.stop(1,1),m.effect.call(g,this),g.queue("fx",function(a){j(),a()})):g.fadeTo(90,a?1:0,j),a&&m.target.trigger("qtip-"+this.id+"-inactive"),this))},u.show=function(a){return this.toggle(y,a)},u.hide=function(a){return this.toggle(z,a)},u.focus=function(a){if(!this.rendered||this.destroyed)return this;var b=d(N),c=this.tooltip,e=parseInt(c[0].style.zIndex,10),f=t.zindex+b.length;return c.hasClass(R)||this._trigger("focus",[f],a)&&(e!==f&&(b.each(function(){this.style.zIndex>e&&(this.style.zIndex=this.style.zIndex-1)}),b.filter("."+R).qtip("blur",a)),c.addClass(R)[0].style.zIndex=f),this},u.blur=function(a){return!this.rendered||this.destroyed?this:(this.tooltip.removeClass(R),this._trigger("blur",[this.tooltip.css("zIndex")],a),this)},u.disable=function(a){return this.destroyed?this:("toggle"===a?a=!(this.rendered?this.tooltip.hasClass(T):this.disabled):"boolean"!=typeof a&&(a=y),this.rendered&&this.tooltip.toggleClass(T,a).attr("aria-disabled",a),this.disabled=!!a,this)},u.enable=function(){return this.disable(z)},u._createButton=function(){var a=this,b=this.elements,c=b.tooltip,e=this.options.content.button,f="string"==typeof e,g=f?e:"Close tooltip";b.button&&b.button.remove(),b.button=e.jquery?e:d("<a />",{"class":"qtip-close "+(this.options.style.widget?"":J+"-icon"),title:g,"aria-label":g}).prepend(d("<span />",{"class":"ui-icon ui-icon-close",html:"&times;"})),b.button.appendTo(b.titlebar||c).attr("role","button").click(function(b){return c.hasClass(T)||a.hide(b),z})},u._updateButton=function(a){if(!this.rendered)return z;var b=this.elements.button;a?this._createButton():b.remove()},u._setWidget=function(){var a=this.options.style.widget,b=this.elements,c=b.tooltip,d=c.hasClass(T);c.removeClass(T),T=a?"ui-state-disabled":"qtip-disabled",c.toggleClass(T,d),c.toggleClass("ui-helper-reset "+k(),a).toggleClass(Q,this.options.style.def&&!a),b.content&&b.content.toggleClass(k("content"),a),b.titlebar&&b.titlebar.toggleClass(k("header"),a),b.button&&b.button.toggleClass(J+"-icon",!a)},u._storeMouse=function(a){(this.mouse=l(a)).type="mousemove"},u._bind=function(a,b,c,e,f){var g="."+this._id+(e?"-"+e:"");b.length&&d(a).bind((b.split?b:b.join(g+" "))+g,d.proxy(c,f||this))},u._unbind=function(a,b){d(a).unbind("."+this._id+(b?"-"+b:""))};var $="."+J;d(function(){r(N,["mouseenter","mouseleave"],function(a){var b="mouseenter"===a.type,c=d(a.currentTarget),e=d(a.relatedTarget||a.target),f=this.options;b?(this.focus(a),c.hasClass(P)&&!c.hasClass(T)&&clearTimeout(this.timers.hide)):"mouse"===f.position.target&&f.hide.event&&f.show.target&&!e.closest(f.show.target[0]).length&&this.hide(a),c.toggleClass(S,b)}),r("["+L+"]",O,p)}),u._trigger=function(a,b,c){var e=d.Event("tooltip"+a);return e.originalEvent=c&&d.extend({},c)||this.cache.event||A,this.triggering=a,this.tooltip.trigger(e,[this].concat(b||[])),this.triggering=z,!e.isDefaultPrevented()},u._bindEvents=function(a,b,c,e,f,g){if(e.add(c).length===e.length){var h=[];b=d.map(b,function(b){var c=d.inArray(b,a);return c>-1?(h.push(a.splice(c,1)[0]),void 0):b}),h.length&&this._bind(c,h,function(a){var b=this.rendered?this.tooltip[0].offsetWidth>0:!1;(b?g:f).call(this,a)})}this._bind(c,a,f),this._bind(e,b,g)},u._assignInitialEvents=function(a){function b(a){return this.disabled||this.destroyed?z:(this.cache.event=l(a),this.cache.target=a?d(a.target):[c],clearTimeout(this.timers.show),this.timers.show=m.call(this,function(){this.render("object"==typeof a||e.show.ready)},e.show.delay),void 0)}var e=this.options,f=e.show.target,g=e.hide.target,h=e.show.event?d.trim(""+e.show.event).split(" "):[],i=e.hide.event?d.trim(""+e.hide.event).split(" "):[];/mouse(over|enter)/i.test(e.show.event)&&!/mouse(out|leave)/i.test(e.hide.event)&&i.push("mouseleave"),this._bind(f,"mousemove",function(a){this._storeMouse(a),this.cache.onTarget=y}),this._bindEvents(h,i,f,g,b,function(){clearTimeout(this.timers.show)}),(e.show.ready||e.prerender)&&b.call(this,a)},u._assignEvents=function(){var c=this,e=this.options,f=e.position,g=this.tooltip,h=e.show.target,i=e.hide.target,j=f.container,k=f.viewport,l=d(b),m=(d(b.body),d(a)),r=e.show.event?d.trim(""+e.show.event).split(" "):[],s=e.hide.event?d.trim(""+e.hide.event).split(" "):[];d.each(e.events,function(a,b){c._bind(g,"toggle"===a?["tooltipshow","tooltiphide"]:["tooltip"+a],b,null,g)}),/mouse(out|leave)/i.test(e.hide.event)&&"window"===e.hide.leave&&this._bind(l,["mouseout","blur"],function(a){/select|option/.test(a.target.nodeName)||a.relatedTarget||this.hide(a)}),e.hide.fixed?i=i.add(g.addClass(P)):/mouse(over|enter)/i.test(e.show.event)&&this._bind(i,"mouseleave",function(){clearTimeout(this.timers.show)}),(""+e.hide.event).indexOf("unfocus")>-1&&this._bind(j.closest("html"),["mousedown","touchstart"],function(a){var b=d(a.target),c=this.rendered&&!this.tooltip.hasClass(T)&&this.tooltip[0].offsetWidth>0,e=b.parents(N).filter(this.tooltip[0]).length>0;b[0]===this.target[0]||b[0]===this.tooltip[0]||e||this.target.has(b[0]).length||!c||this.hide(a)}),"number"==typeof e.hide.inactive&&(this._bind(h,"qtip-"+this.id+"-inactive",p),this._bind(i.add(g),t.inactiveEvents,p,"-inactive")),this._bindEvents(r,s,h,i,n,o),this._bind(h.add(g),"mousemove",function(a){if("number"==typeof e.hide.distance){var b=this.cache.origin||{},c=this.options.hide.distance,d=Math.abs;(d(a.pageX-b.pageX)>=c||d(a.pageY-b.pageY)>=c)&&this.hide(a)}this._storeMouse(a)}),"mouse"===f.target&&f.adjust.mouse&&(e.hide.event&&this._bind(h,["mouseenter","mouseleave"],function(a){this.cache.onTarget="mouseenter"===a.type}),this._bind(l,"mousemove",function(a){this.rendered&&this.cache.onTarget&&!this.tooltip.hasClass(T)&&this.tooltip[0].offsetWidth>0&&this.reposition(a)})),(f.adjust.resize||k.length)&&this._bind(d.event.special.resize?k:m,"resize",q),f.adjust.scroll&&this._bind(m.add(f.container),"scroll",q)},u._unassignEvents=function(){var c=[this.options.show.target[0],this.options.hide.target[0],this.rendered&&this.tooltip[0],this.options.position.container[0],this.options.position.viewport[0],this.options.position.container.closest("html")[0],a,b];this._unbind(d([]).pushStack(d.grep(c,function(a){return"object"==typeof a})))},t=d.fn.qtip=function(a,b,e){var f=(""+a).toLowerCase(),g=A,i=d.makeArray(arguments).slice(1),j=i[i.length-1],k=this[0]?d.data(this[0],J):A;return!arguments.length&&k||"api"===f?k:"string"==typeof a?(this.each(function(){var a=d.data(this,J);if(!a)return y;if(j&&j.timeStamp&&(a.cache.event=j),!b||"option"!==f&&"options"!==f)a[f]&&a[f].apply(a,i);else{if(e===c&&!d.isPlainObject(b))return g=a.get(b),z;a.set(b,e)}}),g!==A?g:this):"object"!=typeof a&&arguments.length?void 0:(k=h(d.extend(y,{},a)),this.each(function(a){var b,c;return c=d.isArray(k.id)?k.id[a]:k.id,c=!c||c===z||c.length<1||t.api[c]?t.nextid++:c,b=s(d(this),c,k),b===z?y:(t.api[c]=b,d.each(I,function(){"initialize"===this.initialize&&this(b)}),b._assignInitialEvents(j),void 0)}))},d.qtip=e,t.api={},d.each({attr:function(a,b){if(this.length){var c=this[0],e="title",f=d.data(c,"qtip");if(a===e&&f&&"object"==typeof f&&f.options.suppress)return arguments.length<2?d.attr(c,V):(f&&f.options.content.attr===e&&f.cache.attr&&f.set("content.text",b),this.attr(V,b))}return d.fn["attr"+U].apply(this,arguments)},clone:function(a){var b=(d([]),d.fn["clone"+U].apply(this,arguments));return a||b.filter("["+V+"]").attr("title",function(){return d.attr(this,V)}).removeAttr(V),b}},function(a,b){if(!b||d.fn[a+U])return y;var c=d.fn[a+U]=d.fn[a];d.fn[a]=function(){return b.apply(this,arguments)||c.apply(this,arguments)}}),d.ui||(d["cleanData"+U]=d.cleanData,d.cleanData=function(a){for(var b,c=0;(b=d(a[c])).length;c++)if(b.attr(K))try{b.triggerHandler("removeqtip")}catch(e){}d["cleanData"+U].apply(this,arguments)}),t.version="2.2.0",t.nextid=0,t.inactiveEvents=O,t.zindex=15e3,t.defaults={prerender:z,id:z,overwrite:y,suppress:y,content:{text:y,attr:"title",title:z,button:z},position:{my:"top left",at:"bottom right",target:z,container:z,viewport:z,adjust:{x:0,y:0,mouse:y,scroll:y,resize:y,method:"flipinvert flipinvert"},effect:function(a,b){d(this).animate(b,{duration:200,queue:z})}},show:{target:z,event:"mouseenter",effect:y,delay:90,solo:z,ready:z,autofocus:z},hide:{target:z,event:"mouseleave",effect:y,delay:0,fixed:z,inactive:z,leave:"window",distance:z},style:{classes:"",widget:z,width:z,height:z,def:y},events:{render:A,move:A,show:A,hide:A,toggle:A,visible:A,hidden:A,focus:A,blur:A}}})}(window,document); +/* +//@ sourceMappingURL=http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0//var/www/build/tmp/tmp-7738rebulc0/jquery.qtip.min.map +*/ \ No newline at end of file diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine-da.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-da.js new file mode 100644 index 0000000..6707c0e --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-da.js @@ -0,0 +1,122 @@ +(function($){ + $.fn.validationEngineLanguage = function(){ + }; + $.validationEngineLanguage = { + newLang: function(){ + $.validationEngineLanguage.allRules = { + "required": { // Add your regex rules here, you can take telephone as an example + "regex": "none", + "alertText": "* Dette felt kræves udfyldt", + "alertTextCheckboxMultiple": "* Vælg venligst en af mulighederne", + "alertTextCheckboxe": "* Dette felt er krævet" + }, + "minSize": { + "regex": "none", + "alertText": "* Minimum ", + "alertText2": " tegn tilladt" + }, + "maxSize": { + "regex": "none", + "alertText": "* Maksimum ", + "alertText2": " tegn tilladt" + }, + "min": { + "regex": "none", + "alertText": "* Den mindste værdi er " + }, + "max": { + "regex": "none", + "alertText": "* Den maksimale værdi er " + }, + "past": { + "regex": "none", + "alertText": "* Datoen skal være før " + }, + "future": { + "regex": "none", + "alertText": "* Datoen skal være efter " + }, + "maxCheckbox": { + "regex": "none", + "alertText": "* Antallet af valg overskredet" + }, + "minCheckbox": { + "regex": "none", + "alertText": "* Vælg venligst ", + "alertText2": " muligheder" + }, + "equals": { + "regex": "none", + "alertText": "* Felterne er ikke ens" + }, + "phone": { + // credit: jquery.h5validate.js / orefalo + "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, + "alertText": "* Ikke gyldig telefonnummer" + }, + "email": { + // Simplified, was not working in the Iphone browser + "regex": /^([A-Za-z0-9_\-\.\'])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,6})$/, + "alertText": "* Ikke gyldig e-mail" + }, + "integer": { + "regex": /^[\-\+]?\d+$/, + "alertText": "* Ikke et korrekt tal" + }, + "number": { + // Number, including positive, negative, and floating decimal. credit: orefalo + "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/, + "alertText": "* Ugyldig decimaltal" + }, + "date": { + // Date in ISO format. Credit: bassistance + "regex": /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/, + "alertText": "* Ugyldig dato, skal være i formatet Ã…Ã…Ã…Ã…-MM-DD" + }, + "ipv4": { + "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/, + "alertText": "* Ugyldig IP adresse" + }, + "url": { + "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/, + "alertText": "* Ugyldig URL" + }, + "onlyNumberSp": { + "regex": /^[0-9\ ]+$/, + "alertText": "* Kun tal" + }, + "onlyLetterSp": { + "regex": /^[a-zA-Z\ \']+$/, + "alertText": "* Kun bogstaver" + }, + "onlyLetterNumber": { + "regex": /^[0-9a-zA-Z]+$/, + "alertText": "* Ingen specialtegn tilladt" + }, + // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings + "ajaxUserCall": { + "url": "ajaxValidateFieldUser", + // you may want to pass extra data on the ajax call + "extraData": "name=eric", + "alertText": "* Denne bruger er allerede taget", + "alertTextLoad": "* Kontrollere, vent venligst" + }, + "ajaxNameCall": { + // remote json service location + "url": "ajaxValidateFieldName", + // error + "alertText": "* Dette navn er allerede taget", + // if you provide an "alertTextOk", it will show as a green prompt when the field validates + "alertTextOk": "* Dette navn er ledig", + // speaks by itself + "alertTextLoad": "* Kontrollere, vent venligst" + }, + "validate2fields": { + "alertText": "* Indsæt venligst HELLO" + } + }; + + } + }; + $.validationEngineLanguage.newLang(); +})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine-de.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-de.js new file mode 100644 index 0000000..9bf36ba --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-de.js @@ -0,0 +1,126 @@ + +(function($){ + $.fn.validationEngineLanguage = function(){ + }; + $.validationEngineLanguage = { + newLang: function(){ + $.validationEngineLanguage.allRules = { + "required": { // Add your regex rules here, you can take telephone as an example + "regex": "none", + "alertText": "* Dieses Feld ist ein Pflichtfeld", + "alertTextCheckboxMultiple": "* Bitte wählen Sie eine Option", + "alertTextCheckboxe": "* Dieses Feld ist ein Pflichtfeld" + }, + "minSize": { + "regex": "none", + "alertText": "* Mindestens ", + "alertText2": " Zeichen benötigt" + }, + "maxSize": { + "regex": "none", + "alertText": "* Maximal ", + "alertText2": " Zeichen erlaubt" + }, + "min": { + "regex": "none", + "alertText": "* Mindeswert ist " + }, + "max": { + "regex": "none", + "alertText": "* Maximalwert ist " + }, + "past": { + "regex": "none", + "alertText": "* Datum vor " + }, + "future": { + "regex": "none", + "alertText": "* Datum nach " + }, + "maxCheckbox": { + "regex": "none", + "alertText": "* Maximale Anzahl Markierungen überschritten" + }, + "minCheckbox": { + "regex": "none", + "alertText": "* Bitte wählen Sie ", + "alertText2": " Optionen" + }, + "equals": { + "regex": "none", + "alertText": "* Felder stimmen nicht überein" + }, + "phone": { + // credit: jquery.h5validate.js / orefalo + "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, + "alertText": "* Ungültige Telefonnummer" + }, + "email": { + // Simplified, was not working in the Iphone browser + "regex": /^([A-Za-z0-9_\-\.\'])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,6})$/, + "alertText": "* Ungültige E-Mail Adresse" + }, + "integer": { + "regex": /^[\-\+]?\d+$/, + "alertText": "* Keine gültige Ganzzahl" + }, + "number": { + // Number, including positive, negative, and floating decimal. credit: orefalo + "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/, + "alertText": "* Keine gültige Fließkommazahl" + }, + "date": { + // Date in ISO format. Credit: bassistance + "regex": /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/, + "alertText": "* Ungültiges Datumsformat, erwartet wird das Format JJJJ-MM-TT" + }, + "ipv4": { + "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/, + "alertText": "* Ungültige IP Adresse" + }, + "url": { + "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/, + "alertText": "* Ungültige URL" + }, + "onlyNumberSp": { + "regex": /^[0-9\ ]+$/, + "alertText": "* Nur Zahlen erlaubt" + }, + "onlyLetterSp": { + "regex": /^[a-zA-Z\ \']+$/, + "alertText": "* Nur Buchstaben erlaubt" + }, + "onlyLetterNumber": { + "regex": /^[0-9a-zA-Z]+$/, + "alertText": "* Keine Sonderzeichen erlaubt" + }, + // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings + "ajaxUserCall": { + "url": "ajaxValidateFieldUser", + // you may want to pass extra data on the ajax call + "extraData": "name=eric", + "alertText": "* Dieser Benutzer ist bereits vergeben", + "alertTextLoad": "* Ãœberprüfe Angaben, bitte warten" + }, + "ajaxNameCall": { + // remote json service location + "url": "ajaxValidateFieldName", + // error + "alertText": "* Dieser Name ist bereits vergeben", + // if you provide an "alertTextOk", it will show as a green prompt when the field validates + "alertTextOk": "* Dieser Name ist verfügbar", + // speaks by itself + "alertTextLoad": "* Ãœberprüfe Angaben, bitte warten" + }, + "validate2fields": { + "alertText": "* Bitte HELLO eingeben" + } + }; + + } + }; + $.validationEngineLanguage.newLang(); +})(jQuery); + + + diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine-en.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-en.js new file mode 100644 index 0000000..4ab845b --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-en.js @@ -0,0 +1,122 @@ +(function($){ + $.fn.validationEngineLanguage = function(){ + }; + $.validationEngineLanguage = { + newLang: function(){ + $.validationEngineLanguage.allRules = { + "required": { // Add your regex rules here, you can take telephone as an example + "regex": "none", + "alertText": "* This field is required", + "alertTextCheckboxMultiple": "* Please select an option", + "alertTextCheckboxe": "* This checkbox is required" + }, + "minSize": { + "regex": "none", + "alertText": "* Minimum ", + "alertText2": " characters allowed" + }, + "maxSize": { + "regex": "none", + "alertText": "* Maximum ", + "alertText2": " characters allowed" + }, + "min": { + "regex": "none", + "alertText": "* Minimum value is " + }, + "max": { + "regex": "none", + "alertText": "* Maximum value is " + }, + "past": { + "regex": "none", + "alertText": "* Date prior to " + }, + "future": { + "regex": "none", + "alertText": "* Date past " + }, + "maxCheckbox": { + "regex": "none", + "alertText": "* Checks allowed Exceeded" + }, + "minCheckbox": { + "regex": "none", + "alertText": "* Please select ", + "alertText2": " options" + }, + "equals": { + "regex": "none", + "alertText": "* Fields do not match" + }, + "phone": { + // credit: jquery.h5validate.js / orefalo + "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, + "alertText": "* Invalid phone number" + }, + "email": { + // Simplified, was not working in the Iphone browser + "regex": /^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,6})$/, + "alertText": "* Invalid email address" + }, + "integer": { + "regex": /^[\-\+]?\d+$/, + "alertText": "* Not a valid integer" + }, + "number": { + // Number, including positive, negative, and floating decimal. credit: orefalo + "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/, + "alertText": "* Invalid floating decimal number" + }, + "date": { + // Date in ISO format. Credit: bassistance + "regex": /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/, + "alertText": "* Invalid date, must be in YYYY-MM-DD format" + }, + "ipv4": { + "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/, + "alertText": "* Invalid IP address" + }, + "url": { + "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/, + "alertText": "* Invalid URL" + }, + "onlyNumberSp": { + "regex": /^[0-9\ ]+$/, + "alertText": "* Numbers only" + }, + "onlyLetterSp": { + "regex": /^[a-zA-Z\ \']+$/, + "alertText": "* Letters only" + }, + "onlyLetterNumber": { + "regex": /^[0-9a-zA-Z]+$/, + "alertText": "* No special characters allowed" + }, + // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings + "ajaxUserCall": { + "url": "ajaxValidateFieldUser", + // you may want to pass extra data on the ajax call + "extraData": "name=eric", + "alertText": "* This user is already taken", + "alertTextLoad": "* Validating, please wait" + }, + "ajaxNameCall": { + // remote json service location + "url": "ajaxValidateFieldName", + // error + "alertText": "* This name is already taken", + // if you provide an "alertTextOk", it will show as a green prompt when the field validates + "alertTextOk": "* This name is available", + // speaks by itself + "alertTextLoad": "* Validating, please wait" + }, + "validate2fields": { + "alertText": "* Please input HELLO" + } + }; + + } + }; + $.validationEngineLanguage.newLang(); +})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine-es.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-es.js new file mode 100644 index 0000000..bb01289 --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-es.js @@ -0,0 +1,124 @@ + +(function($){ + $.fn.validationEngineLanguage = function(){ + }; + $.validationEngineLanguage = { + newLang: function(){ + $.validationEngineLanguage.allRules = { + "required": { // Add your regex rules here, you can take telephone as an example + "regex": "none", + "alertText": "* Este campo está requerido", + "alertTextCheckboxMultiple": "* Por favor selecciona una opción", + "alertTextCheckboxe": "* Este checkbox está requerido" + }, + "minSize": { + "regex": "none", + "alertText": "* Mínimo de ", + "alertText2": " caracteres autorizados" + }, + "maxSize": { + "regex": "none", + "alertText": "* Máximo de ", + "alertText2": " caracteres autorizados" + }, + "min": { + "regex": "none", + "alertText": "* Valor mínimo es " + }, + "max": { + "regex": "none", + "alertText": "* Valor máximo es " + }, + "past": { + "regex": "none", + "alertText": "* Fecha anterior a " + }, + "future": { + "regex": "none", + "alertText": "* Fecha posterior a " + }, + "maxCheckbox": { + "regex": "none", + "alertText": "* Se ha excedido el número de opciones permitidas" + }, + "minCheckbox": { + "regex": "none", + "alertText": "* Por favor seleccione ", + "alertText2": " opciones" + }, + "equals": { + "regex": "none", + "alertText": "* Los campos no coinciden" + }, + "phone": { + // credit: jquery.h5validate.js / orefalo + "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, + "alertText": "* Número de teléfono inválido" + }, + "email": { + // Shamelessly lifted from Scott Gonzalez via the Bassistance Validation plugin http://projects.scottsplayground.com/email_address_validation/ + "regex": /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/, + "alertText": "* Correo inválido" + }, + "integer": { + "regex": /^[\-\+]?\d+$/, + "alertText": "* No es un valor entero válido" + }, + "number": { + // Number, including positive, negative, and floating decimal. credit: orefalo + "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/, + "alertText": "* No es un valor decimal válido" + }, + "date": { + // Date in ISO format. Credit: bassistance + "regex": /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/, + "alertText": "* Fecha inválida, por favor utilize el formato AAAA-MM-DD" + }, + "ipv4": { + "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/, + "alertText": "* Direccion IP inválida" + }, + "url": { + "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/, + "alertText": "* URL Inválida" + }, + "onlyNumberSp": { + "regex": /^[0-9\ ]+$/, + "alertText": "* Sólo números" + }, + "onlyLetterSp": { + "regex": /^[a-zA-Z\ \']+$/, + "alertText": "* Sólo letras" + }, + "onlyLetterNumber": { + "regex": /^[0-9a-zA-Z]+$/, + "alertText": "* No se permiten caracteres especiales" + }, + // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings + "ajaxUserCall": { + "url": "ajaxValidateFieldUser", + // you may want to pass extra data on the ajax call + "extraData": "name=eric", + "alertTextLoad": "* Cargando, espere por favor", + "alertText": "* Este nombre de usuario ya se encuentra usado" + }, + "ajaxNameCall": { + // remote json service location + "url": "ajaxValidateFieldName", + // error + "alertText": "* Este nombre ya se encuentra usado", + // if you provide an "alertTextOk", it will show as a green prompt when the field validates + "alertTextOk": "* Este nombre está disponible", + // speaks by itself + "alertTextLoad": "* Cargando, espere por favor" + }, + "validate2fields": { + "alertText": "* Por favor entrar HELLO" + } + }; + + } + }; + $.validationEngineLanguage.newLang(); +})(jQuery); + diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine-fr.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-fr.js new file mode 100644 index 0000000..85d4efd --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-fr.js @@ -0,0 +1,116 @@ +(function($){ + $.fn.validationEngineLanguage = function(){ + }; + $.validationEngineLanguage = { + newLang: function(){ + $.validationEngineLanguage.allRules = { + "required": { + "regex": "none", + "alertText": "* Ce champs est requis", + "alertTextCheckboxMultiple": "* Choisir une option", + "alertTextCheckboxe": "* Cette option est requise" + }, + "minSize": { + "regex": "none", + "alertText": "* Minimum ", + "alertText2": " caracteres requis" + }, + "maxSize": { + "regex": "none", + "alertText": "* Maximum ", + "alertText2": " caracteres requis" + }, + "min": { + "regex": "none", + "alertText": "* Valeur minimum requise " + }, + "max": { + "regex": "none", + "alertText": "* Valeur maximum requise " + }, + "past": { + "regex": "none", + "alertText": "* Date antérieure au " + }, + "future": { + "regex": "none", + "alertText": "* Date postérieure au " + }, + "maxCheckbox": { + "regex": "none", + "alertText": "* Nombre max de choix excédé" + }, + "minCheckbox": { + "regex": "none", + "alertText": "* Veuillez choisir ", + "alertText2": " options" + }, + "equals": { + "regex": "none", + "alertText": "* Votre champs n'est pas identique" + }, + "phone": { + // credit: jquery.h5validate.js / orefalo + "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, + "alertText": "* Numéro de téléphone invalide" + }, + "email": { + // Shamelessly lifted from Scott Gonzalez via the Bassistance Validation plugin http://projects.scottsplayground.com/email_address_validation/ + "regex": /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/, + "alertText": "* Adresse email invalide" + }, + "integer": { + "regex": /^[\-\+]?\d+$/, + "alertText": "* Nombre entier invalide" + }, + "number": { + // Number, including positive, negative, and floating decimal. credit: orefalo + "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/, + "alertText": "* Nombre flottant invalide" + }, + "date": { + // Date in ISO format. Credit: bassistance + "regex": /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/, + "alertText": "* Date invalide, format YYYY-MM-DD requis" + }, + "ipv4": { + "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/, + "alertText": "* Adresse IP invalide" + }, + "url": { + "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/, + "alertText": "* URL invalide" + }, + "onlyNumberSp": { + "regex": /^[0-9\ ]+$/, + "alertText": "* Seules les chiffres sont acceptées" + }, + "onlyLetterSp": { + "regex": /^[a-zA-Z\ \']+$/, + "alertText": "* Seules les lettres sont acceptées" + }, + "onlyLetterNumber": { + "regex": /^[0-9a-zA-Z]+$/, + "alertText": "* Aucun caractère spécial n'est accepté" + }, + // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings + "ajaxUserCall": { + "url": "ajaxValidateFieldUser", + "extraData": "name=eric", + "alertTextLoad": "* Chargement, veuillez attendre", + "alertText": "* Ce nom est déjà pris" + }, + "ajaxNameCall": { + "url": "ajaxValidateFieldName", + "alertText": "* Ce nom est déjà pris", + "alertTextOk": "*Ce nom est disponible", + "alertTextLoad": "* Chargement, veuillez attendre" + }, + "validate2fields": { + "alertText": "Veuillez taper le mot HELLO" + } + }; + } + }; + $.validationEngineLanguage.newLang(); +})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine-it.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-it.js new file mode 100644 index 0000000..9c58224 --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-it.js @@ -0,0 +1,116 @@ +(function($){ + $.fn.validationEngineLanguage = function(){}; + $.validationEngineLanguage = { + newLang: function(){ + $.validationEngineLanguage.allRules = { + "required": { // Add your regex rules here, you can take telephone as an example + "regex": "none", + "alertText": "Campo richiesto", + "alertTextCheckboxMultiple": "Per favore selezionare un'opzione", + "alertTextCheckboxe": "E' richiesta la selezione della casella" + }, + "minSize": { + "regex": "none", + "alertText": "* Minimo ", + "alertText2": " caratteri permessi" + }, + "maxSize": { + "regex": "none", + "alertText": "* Massimo ", + "alertText2": " caratteri permessi" + }, + "length": { + "regex": "none", + "alertText": "Fra ", + "alertText2": " e ", + "alertText3": " caratteri permessi" + }, + "maxCheckbox": { + "regex": "none", + "alertText": "Numero di caselle da selezionare in eccesso" + }, + "minCheckbox": { + "regex": "none", + "alertText": "Per favore selezionare ", + "alertText2": " opzioni" + }, + "equals": { + "regex": "none", + "alertText": "I campi non corrispondono" + }, + "phone": { + // credit: jquery.h5validate.js / orefalo + "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, + "alertText": "Numero di telefono non corretto" + }, + "email": { + // Shamelessly lifted from Scott Gonzalez via the Bassistance Validation plugin http://projects.scottsplayground.com/email_address_validation/ + "regex": /^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,6})$/, + "alertText": "Email non valida" + }, + "integer": { + "regex": /^[\-\+]?\d+$/, + "alertText": "Numero intero non corretto" + }, + "number": { + // Number, including positive, negative, and floating decimal. Credit: bassistance + "regex": /^[\-\+]?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)$/, + "alertText": "Numero decimale non corretto" + }, + "date": { + // Date in ISO format. Credit: bassistance + "regex": /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/, + "alertText": "Data non corretta, re-inserire secondo formato AAAA-MM-GG" + }, + + "ipv4": { + "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/, + "alertText": "IP non corretto" + }, + "url": { + "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/, + "alertText": "URL non corretta" + }, + "onlyNumber": { + "regex": /^[0-9\ ]+$/, + "alertText": "Solo numeri" + }, + "onlyLetter": { + "regex": /^[a-zA-Z\ \']+$/, + "alertText": "Solo lettere" + }, + "onlyLetterNumber": { + "regex": /^[0-9a-zA-Z\ \']+$/, + "alertText": "* Non sono permessi caratteri speciali" + }, + "name": { + "regex": /^[^0-9<>\=,.\!\?]+$/, + "alertText": "Campo richiesto" + }, + "validate2fields": { + "nname": "validate2fields", + "alertText": "Occorre inserire nome e cognome" + }, + "noSpecialCharacters": { + "regex": /^[0-9a-zA-Z]+$/, + "alertText": "Caratteri speciali non permessi" + }, + "ajaxUserCall": { + "file": "ajaxValidateFieldName", + "extraData": "name=eric", + "alertTextLoad": "Caricamento, attendere per favore", + "alertText": "Questo user � gi� stato utilizzato" + }, + "ajaxNameCall": { + "file": "ajaxValidateFieldName", + "alertText": "Questo nome � gi� stato utilizzato", + "alertTextOk": "Questo nome � disponibile", + "alertTextLoad": "Caricamento, attendere per favore" + } + + }; + + } + }; + $.validationEngineLanguage.newLang(); +})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine-ja.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-ja.js new file mode 100644 index 0000000..74ec775 --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-ja.js @@ -0,0 +1,136 @@ +;/***************************************************************** + * Japanese language file for jquery.validationEngine.js (ver2.0) + * + * Transrator: tomotomo ( Tomoyuki SUGITA ) + * http://tomotomoSnippet.blogspot.com/ + * Licenced under the MIT Licence + *******************************************************************/ +(function($){ + $.fn.validationEngineLanguage = function(){ + }; + $.validationEngineLanguage = { + newLang: function(){ + $.validationEngineLanguage.allRules = { + "required": { // Add your regex rules here, you can take telephone as an example + "regex": "none", + "alertText": "* 必須項目ã§ã™", + "alertTextCheckboxMultiple": "* é¸æŠžã—ã¦ãã ã•ã„", + "alertTextCheckboxe": "* ãƒã‚§ãƒƒã‚¯ãƒœãƒƒã‚¯ã‚¹ã‚’ãƒã‚§ãƒƒã‚¯ã—ã¦ãã ã•ã„" + }, + "minSize": { + "regex": "none", + "alertText": "* ", + "alertText2": "文字以上ã«ã—ã¦ãã ã•ã„" + }, + "maxSize": { + "regex": "none", + "alertText": "* ", + "alertText2": "文字以下ã«ã—ã¦ãã ã•ã„" + }, + "min": { + "regex": "none", + "alertText": "* ", + "alertText2": " 以上ã®æ•°å€¤ã«ã—ã¦ãã ã•ã„" + }, + "max": { + "regex": "none", + "alertText": "* ", + "alertText2": " 以下ã®æ•°å€¤ã«ã—ã¦ãã ã•ã„" + }, + "past": { + "regex": "none", + "alertText": "* ", + "alertText2": " よりéŽåŽ»ã®æ—¥ä»˜ã«ã—ã¦ãã ã•ã„" + }, + "future": { + "regex": "none", + "alertText": "* ", + "alertText2": " より最近ã®æ—¥ä»˜ã«ã—ã¦ãã ã•ã„" + }, + "maxCheckbox": { + "regex": "none", + "alertText": "* ãƒã‚§ãƒƒã‚¯ã—ã™ãŽã§ã™" + }, + "minCheckbox": { + "regex": "none", + "alertText": "* ", + "alertText2": "ã¤ä»¥ä¸Šãƒã‚§ãƒƒã‚¯ã—ã¦ãã ã•ã„" + }, + "equals": { + "regex": "none", + "alertText": "* 入力ã•ã‚ŒãŸå€¤ãŒä¸€è‡´ã—ã¾ã›ã‚“" + }, + "phone": { + // credit: jquery.h5validate.js / orefalo + "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, + "alertText": "* 電話番å·ãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“" + }, + "email": { + // Simplified, was not working in the Iphone browser + "regex": /^([A-Za-z0-9_\-\.\'])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,6})$/, + "alertText": "* メールアドレスãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“" + }, + "integer": { + "regex": /^[\-\+]?\d+$/, + "alertText": "* æ•´æ•°ã‚’åŠè§’ã§å…¥åŠ›ã—ã¦ãã ã•ã„" + }, + "number": { + // Number, including positive, negative, and floating decimal. credit: orefalo + "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/, + "alertText": "* 数値をåŠè§’ã§å…¥åŠ›ã—ã¦ãã ã•ã„" + }, + "date": { + // Date in ISO format. Credit: bassistance + "regex": /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/, + "alertText": "* 日付ã¯åŠè§’㧠YYYY-MM-DD ã®å½¢å¼ã§å…¥åŠ›ã—ã¦ãã ã•ã„" + }, + "ipv4": { + "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/, + "alertText": "* IPアドレスãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“" + }, + "url": { + "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/, + "alertText": "* URLãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“" + }, + "onlyNumberSp": { + "regex": /^[0-9\ ]+$/, + "alertText": "* åŠè§’æ•°å­—ã§å…¥åŠ›ã—ã¦ãã ã•ã„" + }, + "onlyLetterSp": { + "regex": /^[a-zA-Z\ \']+$/, + "alertText": "* åŠè§’アルファベットã§å…¥åŠ›ã—ã¦ãã ã•ã„" + }, + "onlyLetterNumber": { + "regex": /^[0-9a-zA-Z]+$/, + "alertText": "* åŠè§’英数ã§å…¥åŠ›ã—ã¦ãã ã•ã„" + }, + // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings + "ajaxUserCall": { + "url": "ajaxValidateFieldUser", + // you may want to pass extra data on the ajax call + "extraData": "name=eric", + "alertText": "* This user is already taken", + "alertTextLoad": "* Validating, please wait" + }, + "ajaxNameCall": { + // remote json service location + "url": "ajaxValidateFieldName", + // error + "alertText": "* This name is already taken", + // if you provide an "alertTextOk", it will show as a green prompt when the field validates + "alertTextOk": "* This name is available", + // speaks by itself + "alertTextLoad": "* Validating, please wait" + }, + "validate2fields": { + "alertText": "* 『HELLOã€ã¨å…¥åŠ›ã—ã¦ãã ã•ã„" + } + }; + + } + }; + $.validationEngineLanguage.newLang(); +})(jQuery); + + + diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine-nl.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-nl.js new file mode 100644 index 0000000..b6fd418 --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-nl.js @@ -0,0 +1,123 @@ +(function($){ + $.fn.validationEngineLanguage = function(){ + }; + $.validationEngineLanguage = { + newLang: function(){ + $.validationEngineLanguage.allRules = { + "required": { // Add your regex rules here, you can take telephone as an example + "regex": "geen", + "alertText": "* Dit veld is verplicht", + "alertTextCheckboxMultiple": "* Selecteer a.u.b. een optie", + "alertTextCheckboxe": "* Dit selectievakje is verplicht" + }, + "minSize": { + "regex": "none", + "alertText": "* Minimaal ", + "alertText2": " karakters toegestaan" + }, + "maxSize": { + "regex": "none", + "alertText": "* Maximaal ", + "alertText2": " karakters toegestaan" + }, + "min": { + "regex": "none", + "alertText": "* Minimale waarde is " + }, + "max": { + "regex": "none", + "alertText": "* Maximale waarde is " + }, + "past": { + "regex": "none", + "alertText": "* Datum voorafgaand aan " + }, + "future": { + "regex": "none", + "alertText": "* Datum na " + }, + "maxCheckbox": { + "regex": "none", + "alertText": "* Toegestane aantal vinkjes overschreden" + }, + "minCheckbox": { + "regex": "none", + "alertText": "* Selecteer a.u.b. ", + "alertText2": " opties" + }, + "equals": { + "regex": "none", + "alertText": "* Velden komen niet overeen" + }, + "phone": { + // credit: jquery.h5validate.js / orefalo + "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, + "alertText": "* Ongeldig telefoonnummer" + }, + "email": { + // Simplified, was not working in the Iphone browser + "regex": /^([A-Za-z0-9_\-\.\'])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,6})$/, + "alertText": "* Ongeldig e-mailadres" + }, + "integer": { + "regex": /^[\-\+]?\d+$/, + "alertText": "* Ongeldig geheel getal" + }, + "number": { + // Number, including positive, negative, and floating decimal. credit: orefalo + "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/, + "alertText": "* Ongeldig drijvende comma getal" + }, + "date": { + // Date in ISO format. Credit: bassistance + "regex": /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/, + "alertText": "* Ongeldige datum, formaat moet JJJJ-MM-DD zijn" + }, + "ipv4": { + "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/, + "alertText": "* Ongeldig IP-adres" + }, + "url": { + "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/, + "alertText": "* Ongeldige URL" + }, + "onlyNumberSp": { + "regex": /^[0-9\ ]+$/, + "alertText": "* Alleen cijfers" + }, + "onlyLetterSp": { + "regex": /^[a-zA-Z\ \']+$/, + "alertText": "* Alleen leestekens" + }, + "onlyLetterNumber": { + "regex": /^[0-9a-zA-Z]+$/, + "alertText": "* Geen vreemde tekens toegestaan" + }, + // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings + "ajaxUserCall": { + "url": "ajaxValidateFieldUser", + // you may want to pass extra data on the ajax call + "extraData": "name=eric", + "alertText": "* Deze gebruiker bestaat al", + "alertTextLoad": "* Bezig met valideren, even geduld aub" + }, + "ajaxNameCall": { + // remote json service location + "url": "ajaxValidateFieldName", + // error + "alertText": "* Deze naam bestaat al", + // if you provide an "alertTextOk", it will show as a green prompt when the field validates + "alertTextOk": "* Deze naam is beschikbaar", + // speaks by itself + "alertTextLoad": "* Bezig met valideren, even geduld aub" + }, + "validate2fields": { + "alertText": "* Voer aub HELLO in" + } + }; + + } + }; + $.validationEngineLanguage.newLang(); +})(jQuery); + diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine-pt.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-pt.js new file mode 100644 index 0000000..0ea7b11 --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-pt.js @@ -0,0 +1,122 @@ +(function($){ + $.fn.validationEngineLanguage = function(){ + }; + $.validationEngineLanguage = { + newLang: function(){ + $.validationEngineLanguage.allRules = { + "required": { // Add your regex rules here, you can take telephone as an example + "regex": "none", + "alertText": "* Campo obrigatório", + "alertTextCheckboxMultiple": "* Selecione uma opção", + "alertTextCheckboxe": "* Campo obrigatório" + }, + "minSize": { + "regex": "none", + "alertText": "* Mínimo ", + "alertText2": " carateres permitidos" + }, + "maxSize": { + "regex": "none", + "alertText": "* Máximo ", + "alertText2": " carateres permitidos" + }, + "min": { + "regex": "none", + "alertText": "* O valor mínimo é " + }, + "max": { + "regex": "none", + "alertText": "* O valor máximo é " + }, + "past": { + "regex": "none", + "alertText": "* Data anterior a " + }, + "future": { + "regex": "none", + "alertText": "* Data posterior a " + }, + "maxCheckbox": { + "regex": "none", + "alertText": "* Foi ultrapassado o número máximo de escolhas" + }, + "minCheckbox": { + "regex": "none", + "alertText": "* Selecione ", + "alertText2": " opções" + }, + "equals": { + "regex": "none", + "alertText": "* Os campos não correspondem" + }, + "phone": { + // credit: jquery.h5validate.js / orefalo + "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, + "alertText": "* Número de telefone inválido" + }, + "email": { + // Shamelessly lifted from Scott Gonzalez via the Bassistance Validation plugin http://projects.scottsplayground.com/email_address_validation/ + "regex": /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/, + "alertText": "* Endereço de email inválido" + }, + "integer": { + "regex": /^[\-\+]?\d+$/, + "alertText": "* Não é um número inteiro" + }, + "number": { + // Number, including positive, negative, and floating decimal. credit: orefalo + "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/, + "alertText": "* Não é um número decimal" + }, + "date": { + // Date in ISO format. Credit: bassistance + "regex": /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/, + "alertText": "* Data inválida, o formato deve de ser AAAA-MM-DD" + }, + "ipv4": { + "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/, + "alertText": "* Número IP inválido" + }, + "url": { + "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/, + "alertText": "* URL inválido" + }, + "onlyNumberSp": { + "regex": /^[0-9\ ]+$/, + "alertText": "* Só é permitido números" + }, + "onlyLetterSp": { + "regex": /^[a-zA-Z\ \']+$/, + "alertText": "* Só é permitido letras" + }, + "onlyLetterNumber": { + "regex": /^[0-9a-zA-Z]+$/, + "alertText": "* Só é permitido letras e números" + }, + // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings + "ajaxUserCall": { + "url": "ajaxValidateFieldUser", + // you may want to pass extra data on the ajax call + "extraData": "name=eric", + "alertText": "* Nome de utilizador não disponível", + "alertTextLoad": "* A validar, por favor aguarde" + }, + "ajaxNameCall": { + // remote json service location + "url": "ajaxValidateFieldName", + // error + "alertText": "* Nome não disponível", + // if you provide an "alertTextOk", it will show as a green prompt when the field validates + "alertTextOk": "* Nome disponível", + // speaks by itself + "alertTextLoad": "* A validar, por favor aguarde" + }, + "validate2fields": { + "alertText": "* Escreva HELLO" + } + }; + + } + }; + $.validationEngineLanguage.newLang(); +})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine-ro.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-ro.js new file mode 100644 index 0000000..385cb6f --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-ro.js @@ -0,0 +1,122 @@ +(function($){ + $.fn.validationEngineLanguage = function(){ + }; + $.validationEngineLanguage = { + newLang: function(){ + $.validationEngineLanguage.allRules = { + "required": { // Add your regex rules here, you can take telephone as an example + "regex": "none", + "alertText": "* Acest camp este obligatoriu", + "alertTextCheckboxMultiple": "* Selectati o optiune", + "alertTextCheckboxe": "* Aceasta optiune este obligatorie" + }, + "minSize": { + "regex": "none", + "alertText": "* Minim ", + "alertText2": " caractere permise" + }, + "maxSize": { + "regex": "none", + "alertText": "* Maxim ", + "alertText2": " caractere permise" + }, + "min": { + "regex": "none", + "alertText": "* Valoarea minima este " + }, + "max": { + "regex": "none", + "alertText": "* Valoarea maxima este " + }, + "past": { + "regex": "none", + "alertText": "* Data inainte de " + }, + "future": { + "regex": "none", + "alertText": "* Data dupa " + }, + "maxCheckbox": { + "regex": "none", + "alertText": "* Limita maxima de optiuni a fost depasita" + }, + "minCheckbox": { + "regex": "none", + "alertText": "* Selectati cel putin ", + "alertText2": " optiuni" + }, + "equals": { + "regex": "none", + "alertText": "* Campurile nu coincid" + }, + "phone": { + // credit: jquery.h5validate.js / orefalo + "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, + "alertText": "* Numar de telefon eronat" + }, + "email": { + // Shamelessly lifted from Scott Gonzalez via the Bassistance Validation plugin http://projects.scottsplayground.com/email_address_validation/ + "regex": /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/, + "alertText": "* Adresa de email eronata" + }, + "integer": { + "regex": /^[\-\+]?\d+$/, + "alertText": "* Numar intreg eronat" + }, + "number": { + // Number, including positive, negative, and floating decimal. credit: orefalo + "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/, + "alertText": "* Numar zecimal eronat" + }, + "date": { + // Date in ISO format. Credit: bassistance + "regex": /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/, + "alertText": "* Data eronata, formatul de introducere este: YYYY-MM-DD" + }, + "ipv4": { + "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/, + "alertText": "* Adresa IP eronata" + }, + "url": { + "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/, + "alertText": "* URL eronat" + }, + "onlyNumberSp": { + "regex": /^[0-9\ ]+$/, + "alertText": "* Doar numere" + }, + "onlyLetterSp": { + "regex": /^[a-zA-Z\ \']+$/, + "alertText": "* Doar litere" + }, + "onlyLetterNumber": { + "regex": /^[0-9a-zA-Z]+$/, + "alertText": "* Caracterele speciale (',', '.', '-', etc) nu sunt permise" + }, + // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings + "ajaxUserCall": { + "url": "ajaxValidateFieldUser", + // you may want to pass extra data on the ajax call + "extraData": "name=eric", + "alertText": "* Acest nume de utilizator este deja folosit", + "alertTextLoad": "* Se valideaza, va rugam asteptati" + }, + "ajaxNameCall": { + // remote json service location + "url": "ajaxValidateFieldName", + // error + "alertText": "* Acest nume este deja folosit", + // if you provide an "alertTextOk", it will show as a green prompt when the field validates + "alertTextOk": "* Acest nume este disponibil", + // speaks by itself + "alertTextLoad": "* Se valideaza, va rugam asteptati" + }, + "validate2fields": { + "alertText": "* Introduceti: HELLO" + } + }; + + } + }; + $.validationEngineLanguage.newLang(); +})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine-ru.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-ru.js new file mode 100644 index 0000000..e013839 --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine-ru.js @@ -0,0 +1,123 @@ +(function($){ + $.fn.validationEngineLanguage = function(){ + }; + $.validationEngineLanguage = { + newLang: function(){ + $.validationEngineLanguage.allRules = { + "required": { // Add your regex rules here, you can take telephone as an example + "regex": "none", + "alertText": "* Ðеобходимо заполнить", + "alertTextCheckboxMultiple": "* Ð’Ñ‹ должны выбрать вариант", + "alertTextCheckboxe": "* Ðеобходимо отметить" + }, + "minSize": { + "regex": "none", + "alertText": "* Минимум ", + "alertText2": " Ñимвола(ов)" + }, + "maxSize": { + "regex": "none", + "alertText": "* МакÑимум ", + "alertText2": " Ñимвола(ов)" + }, + "min": { + "regex": "none", + "alertText": "* Минимальное значение " + }, + "max": { + "regex": "none", + "alertText": "* МакÑимальное значение " + }, + "past": { + "regex": "none", + "alertText": "* Дата до " + }, + "future": { + "regex": "none", + "alertText": "* Дата от " + }, + "maxCheckbox": { + "regex": "none", + "alertText": "* ÐÐµÐ»ÑŒÐ·Ñ Ð²Ñ‹Ð±Ñ€Ð°Ñ‚ÑŒ Ñтолько вариантов" + }, + "minCheckbox": { + "regex": "none", + "alertText": "* ПожалуйÑта, выберите ", + "alertText2": " опцию(ии)" + }, + "equals": { + "regex": "none", + "alertText": "* ÐŸÐ¾Ð»Ñ Ð½Ðµ Ñовпадают" + }, + "phone": { + // credit: jquery.h5validate.js / orefalo + "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/, + "alertText": "* Ðеправильный формат телефона" + }, + "email": { + // Shamelessly lifted from Scott Gonzalez via the Bassistance Validation plugin http://projects.scottsplayground.com/email_address_validation/ + "regex": /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/, + "alertText": "* Ðеверный формат email" + }, + "integer": { + "regex": /^[\-\+]?\d+$/, + "alertText": "* Ðе целое чиÑло" + }, + "number": { + // Number, including positive, negative, and floating decimal. credit: orefalo + "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/, + "alertText": "* Ðеправильное чиÑло Ñ Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰ÐµÐ¹ точкой" + }, + "date": { + // Date in russian-specific format + "regex": /^\d{1,2}[\.]\d{1,2}[\.]\d{4}$/, + "alertText": "* ÐÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ð°Ñ Ð´Ð°Ñ‚Ð° (должно быть в ДД.MM.ГГГГ формате)" + }, + "ipv4": { + "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/, + "alertText": "* Ðеправильный IP-адреÑ" + }, + "url": { + "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/, + "alertText": "* Ðеправильный URL" + }, + "onlyNumberSp": { + "regex": /^[0-9\ ]+$/, + "alertText": "* Только чиÑла" + }, + "onlyLetterSp": { + "regex": /^[a-zA-Z\u0400-\u04FF\ \']+$/, + "alertText": "* Только буквы" + }, + "onlyLetterNumber": { + "regex": /^[0-9a-zA-Z\u0400-\u04FF]+$/, + "alertText": "* Запрещены Ñпециальные Ñимволы" + }, + // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings + "ajaxUserCall": { + "url": "ajaxValidateFieldUser", + // you may want to pass extra data on the ajax call + "extraData": "name=eric", + "alertText": "* Этот пользователь уже занÑÑ‚", + "alertTextLoad": "* Проверка, подождите..." + }, + "ajaxNameCall": { + // remote json service location + "url": "ajaxValidateFieldName", + // error + "alertText": "* Это Ð¸Ð¼Ñ ÑƒÐ¶Ðµ занÑто", + // if you provide an "alertTextOk", it will show as a green prompt when the field validates + "alertTextOk": "* Это Ð¸Ð¼Ñ Ð´Ð¾Ñтупно", + // speaks by itself + "alertTextLoad": "* Проверка, подождите..." + }, + "validate2fields": { + "alertText": "* ПожалуйÑта, введите HELLO" + } + }; + + } + }; + $.validationEngineLanguage.newLang(); +})(jQuery); + diff --git a/src/static/jquery/jquery.validationEngine/jquery.validationEngine.js b/src/static/jquery/jquery.validationEngine/jquery.validationEngine.js new file mode 100755 index 0000000..106299a --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/jquery.validationEngine.js @@ -0,0 +1,1180 @@ +/* + * Inline Form Validation Engine 2.0 Beta, jQuery plugin + * + * Copyright(c) 2010, Cedric Dugas + * http://www.position-absolute.com + * + * 2.0 Rewrite by Olivier Refalo + * http://www.crionics.com + * + * Form validation engine allowing custom regex rules to be added. + * Licensed under the MIT License + */ +(function($) { + + var methods = { + + /** + * Kind of the constructor, called before any action + * @param {Map} user options + */ + init: function(options) { + var form = this; + if (form.data('jqv') === undefined || form.data('jqv') == null ) { + methods._saveOptions(form, options); + + // bind all formError elements to close on click + $(".formError").live("click", function() { + $(this).fadeOut(150, function() { + + // remove prompt once invisible + $(this).remove(); + }); + }); + } + }, + /** + * Attachs jQuery.validationEngine to form.submit and field.blur events + * Takes an optional params: a list of options + * ie. jQuery("#formID1").validationEngine('attach', {promptPosition : "centerRight"}); + */ + attach: function(userOptions) { + var form = this; + var options; + + if(userOptions) + options = methods._saveOptions(form, userOptions); + else + options = form.data('jqv'); + + if (!options.binded) { + if (options.bindMethod == "bind"){ + if ( options.validationEventTrigger != "none" || options.validationEventTrigger != "" ) + { + // bind fields + form.find("[class*=validate]:not([type=checkbox])").bind(options.validationEventTrigger, methods._onFieldEvent); + form.find("[class*=validate][type=checkbox]").bind("click", methods._onFieldEvent); + } + // bind form.submit + form.bind("submit", methods._onSubmitEvent); + } else if (options.bindMethod == "live") { + if ( options.validationEventTrigger != "none" || options.validationEventTrigger != "" ) + { + // bind fields with LIVE (for persistant state) + form.find("[class*=validate]:not([type=checkbox])").live(options.validationEventTrigger, methods._onFieldEvent); + form.find("[class*=validate][type=checkbox]").live("click", methods._onFieldEvent); + } + // bind form.submit + form.live("submit", methods._onSubmitEvent); + } + options.binded = true; + } + + }, + /** + * Unregisters any bindings that may point to jQuery.validaitonEngine + */ + detach: function() { + var form = this; + var options = form.data('jqv'); + if (options.binded) { + + // unbind fields + form.find("[class*=validate]").not("[type=checkbox]").unbind(options.validationEventTrigger, methods._onFieldEvent); + form.find("[class*=validate][type=checkbox]").unbind("click", methods._onFieldEvent); + // unbind form.submit + form.unbind("submit", methods.onAjaxFormComplete); + + + // unbind live fields (kill) + form.find("[class*=validate]").not("[type=checkbox]").die(options.validationEventTrigger, methods._onFieldEvent); + form.find("[class*=validate][type=checkbox]").die("click", methods._onFieldEvent); + // unbind form.submit + form.die("submit", methods.onAjaxFormComplete); + + form.removeData('jqv'); + } + }, + /** + * Validates the form fields, shows prompts accordingly. + * Note: There is no ajax form validation with this method, only field ajax validation are evaluated + * + * @return true if the form validates, false if it fails + */ + validate: function() { + return methods._validateFields(this); + }, + /** + * Validates one field, shows prompt accordingly. + * Note: There is no ajax form validation with this method, only field ajax validation are evaluated + * + * @return true if the form validates, false if it fails + */ + validateField: function(el) { + var options = $(this).data('jqv'); + return methods._validateField($(el), options); + }, + /** + * Validates the form fields, shows prompts accordingly. + * Note: this methods performs fields and form ajax validations(if setup) + * + * @return true if the form validates, false if it fails, undefined if ajax is used for form validation + */ + validateform: function() { + return methods._onSubmitEvent(this); + }, + /** + * Displays a prompt on a element. + * Note that the element needs an id! + * + * @param {String} promptText html text to display type + * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red) + * @param {String} possible values topLeft, topRight, bottomLeft, centerRight, bottomRight + */ + showPrompt: function(promptText, type, promptPosition, showArrow) { + + var form = this.closest('form'); + var options = form.data('jqv'); + // No option, take default one + if(!options) options = methods._saveOptions(this, options); + if(promptPosition) + options.promptPosition=promptPosition; + options.showArrow = showArrow===true; + + methods._showPrompt(this, promptText, type, false, options); + }, + /** + * Closes all error prompts on the page + */ + hidePrompt: function() { + var promptClass = "."+ methods._getClassName($(this).attr("id")) + "formError" + $(promptClass).fadeTo("fast", 0.3, function() { + $(this).remove(); + }); + }, + /** + * Closes form error prompts, CAN be invidual + */ + hide: function() { + if($(this).is("form")){ + var closingtag = "parentForm"+$(this).attr('id'); + }else{ + + var closingtag = $(this).attr('id') +"formError" + } + $('.'+closingtag).fadeTo("fast", 0.3, function() { + $(this).remove(); + }); + }, + /** + * Closes all error prompts on the page + */ + hideAll: function() { + $('.formError').fadeTo("fast", 0.3, function() { + $(this).remove(); + }); + }, + /** + * Typically called when user exists a field using tab or a mouse click, triggers a field + * validation + */ + _onFieldEvent: function() { + var field = $(this); + var form = field.closest('form'); + var options = form.data('jqv'); + // validate the current field + methods._validateField(field, options); + }, + /** + * Called when the form is submited, shows prompts accordingly + * + * @param {jqObject} + * form + * @return false if form submission needs to be cancelled + */ + _onSubmitEvent: function() { + + var form = $(this); + + // validate each field (- skip field ajax validation, no necessary since we will perform an ajax form validation) + var r=methods._validateFields(form, true); + + var options = form.data('jqv'); + // validate the form using AJAX + if (r && options.ajaxFormValidation) { + methods._validateFormWithAjax(form, options); + return false; + } + + if(options.onValidationComplete) { + options.onValidationComplete(form, r); + return false; + } + return r; + }, + /** + * Return true if the ajax field validations passed so far + * @param {Object} options + * @return true, is all ajax validation passed so far (remember ajax is async) + */ + _checkAjaxStatus: function(options) { + var status = true; + $.each(options.ajaxValidCache, function(key, value) { + if (value === false) { + status = false; + // break the each + return false; + } + }); + return status; + }, + /** + * Validates form fields, shows prompts accordingly + * + * @param {jqObject} + * form + * @param {skipAjaxFieldValidation} + * boolean - when set to true, ajax field validation is skipped, typically used when the submit button is clicked + * + * @return true if form is valid, false if not, undefined if ajax form validation is done + */ + _validateFields: function(form, skipAjaxFieldValidation) { + + var options = form.data('jqv'); + + // this variable is set to true if an error is found + var errorFound = false; + + // first, evaluate status of non ajax fields + form.find('[class*=validate]').not(':hidden').each( function() { + var field = $(this); + // fields being valiated though ajax are marked with 'ajaxed', + // skip them + if (!field.hasClass("ajaxed")) + errorFound |= methods._validateField(field, options, skipAjaxFieldValidation); + }); + // second, check to see if all ajax calls completed ok + errorFound |= !methods._checkAjaxStatus(options); + + // thrird, check status and scroll the container accordingly + if (errorFound) { + if (options.scroll) { + + // get the position of the first error, there should be at least one, no need to check this + //var destination = form.find(".formError:not('.greenPopup'):first").offset().top; + + // look for the visually top prompt + var destination = Number.MAX_VALUE; + + var lst = $(".formError:not('.greenPopup')"); + for (var i = 0; i < lst.length; i++) { + var d = $(lst[i]).offset().top; + if (d < destination) + destination = d; + } + + if (!options.isOverflown) + $("html:not(:animated),body:not(:animated)").animate({ + scrollTop: destination + }, 1100); + else { + var overflowDIV = $(options.overflownDIV); + var scrollContainerScroll = overflowDIV.scrollTop(); + var scrollContainerPos = -parseInt(overflowDIV.offset().top); + + destination += scrollContainerScroll + scrollContainerPos - 5; + var scrollContainer = $(options.overflownDIV + ":not(:animated)"); + + scrollContainer.animate({ + scrollTop: destination + }, 1100); + } + } + return false; + } + return true; + }, + /** + * This method is called to perform an ajax form validation. + * During this process all the (field, value) pairs are sent to the server which returns a list of invalid fields or true + * + * @param {jqObject} form + * @param {Map} options + */ + _validateFormWithAjax: function(form, options) { + + var data = form.serialize(); + + $.ajax({ + type: "GET", + url: form.attr("action"), + cache: false, + dataType: "json", + data: data, + form: form, + methods: methods, + options: options, + beforeSend: function() { + return options.onBeforeAjaxFormValidation(form, options); + }, + error: function(data, transport) { + methods._ajaxError(data, transport); + }, + success: function(json) { + + if (json !== true) { + + // getting to this case doesn't necessary means that the form is invalid + // the server may return green or closing prompt actions + // this flag helps figuring it out + var errorInForm=false; + for (var i = 0; i < json.length; i++) { + var value = json[i]; + + var errorFieldId = value[0]; + var errorField = $($("#" + errorFieldId)[0]); + + // make sure we found the element + if (errorField.length == 1) { + + // promptText or selector + var msg = value[2]; + + if (value[1] === true) { + + if (msg == "") + // if for some reason, status==true and error="", just close the prompt + methods._closePrompt(errorField); + else { + // the field is valid, but we are displaying a green prompt + if (options.allrules[msg]) { + var txt = options.allrules[msg].alertTextOk; + if (txt) + msg = txt; + } + methods._showPrompt(errorField, msg, "pass", false, options); + } + } else { + // the field is invalid, show the red error prompt + errorInForm|=true; + if (options.allrules[msg]) { + var txt = options.allrules[msg].alertText; + if (txt) + msg = txt; + } + methods._showPrompt(errorField, msg, "", false, options); + } + } + } + options.onAjaxFormComplete(!errorInForm, form, json, options); + } else + options.onAjaxFormComplete(true, form, "", options); + } + }); + + }, + /** + * Validates field, shows prompts accordingly + * + * @param {jqObject} + * field + * @param {Array[String]} + * field's validation rules + * @param {Map} + * user options + * @return true if field is valid + */ + _validateField: function(field, options, skipAjaxFieldValidation) { + + if (!field.attr("id")) + $.error("jQueryValidate: an ID attribute is required for this field: " + field.attr("name") + " class:" + + field.attr("class")); + + var rulesParsing = field.attr('class'); + var getRules = /validate\[(.*)\]/.exec(rulesParsing); + if (getRules === null) + return false; + var str = getRules[1]; + var rules = str.split(/\[|,|\]/); + + // true if we ran the ajax validation, tells the logic to stop messing with prompts + var isAjaxValidator = false; + var fieldName = field.attr("name"); + var promptText = ""; + var required = false; + options.isError = false; + options.showArrow = true; + optional = false; + + for (var i = 0; i < rules.length; i++) { + + var errorMsg = undefined; + switch (rules[i]) { + + case "optional": + optional = true; + break; + case "required": + required = true; + errorMsg = methods._required(field, rules, i, options); + break; + case "custom": + errorMsg = methods._customRegex(field, rules, i, options); + break; + case "ajax": + if(skipAjaxFieldValidation===false) { + // ajax has its own prompts handling technique + methods._ajax(field, rules, i, options); + isAjaxValidator = true; + } + break; + case "minSize": + errorMsg = methods._minSize(field, rules, i, options); + break; + case "maxSize": + errorMsg = methods._maxSize(field, rules, i, options); + break; + case "min": + errorMsg = methods._min(field, rules, i, options); + break; + case "max": + errorMsg = methods._max(field, rules, i, options); + break; + case "past": + errorMsg = methods._past(field, rules, i, options); + break; + case "future": + errorMsg = methods._future(field, rules, i, options); + break; + case "maxCheckbox": + errorMsg = methods._maxCheckbox(field, rules, i, options); + field = $($("input[name='" + fieldName + "']")); + break; + case "minCheckbox": + errorMsg = methods._minCheckbox(field, rules, i, options); + field = $($("input[name='" + fieldName + "']")); + break; + case "equals": + errorMsg = methods._equals(field, rules, i, options); + break; + case "funcCall": + errorMsg = methods._funcCall(field, rules, i, options); + break; + + default: + //$.error("jQueryValidator rule not found"+rules[i]); + } + + if (errorMsg !== undefined && ( options.showAllErrors || promptText == "" ) ) { + promptText += errorMsg + "<br/>"; + options.isError = true; + } + + } + // If the rules required is not added, an empty field is not validated + if(!required && !optional ){ + if(field.val() == "") options.isError = false; + } + // Hack for radio/checkbox group button, the validation go into the + // first radio/checkbox of the group + var fieldType = field.attr("type"); + + if ((fieldType == "radio" || fieldType == "checkbox") && $("input[name='" + fieldName + "']").size() > 1) { + field = $($("input[name='" + fieldName + "'][type!=hidden]:first")); + options.showArrow = false; + } + + if (!isAjaxValidator) { + if (options.isError) + methods._showPrompt(field, promptText, "", false, options); + else + methods._closePrompt(field); + } + return options.isError; + }, + /** + * Required validation + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _required: function(field, rules, i, options) { + switch (field.attr("type")) { + case "text": + case "password": + case "textarea": + case "file": + default: + if (!field.val()) + return options.allrules[rules[i]].alertText; + break; + case "radio": + case "checkbox": + var name = field.attr("name"); + if ($("input[name='" + name + "']:checked").size() === 0) { + + if ($("input[name='" + name + "']").size() === 1) + return options.allrules[rules[i]].alertTextCheckboxe; + else + return options.allrules[rules[i]].alertTextCheckboxMultiple; + } + break; + // required for <select> + case "select-one": + // added by paul@kinetek.net for select boxes, Thank you + if (!field.val()) + return options.allrules[rules[i]].alertText; + break; + case "select-multiple": + // added by paul@kinetek.net for select boxes, Thank you + if (!field.find("option:selected").val()) + return options.allrules[rules[i]].alertText; + break; + } + }, + /** + * Validate Regex rules + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _customRegex: function(field, rules, i, options) { + var customRule = rules[i + 1]; + var rule = options.allrules[customRule]; + if(rule===undefined) { + alert("jqv:custom rule not found "+customRule); + return; + } + + var ex=rule.regex; + if(ex===undefined) { + alert("jqv:custom regex not found "+customRule); + return; + } + var pattern = new RegExp(ex); + + if (!pattern.test(field.attr('value'))) + return options.allrules[customRule].alertText; + }, + /** + * Validate custom function outside of the engine scope + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _funcCall: function(field, rules, i, options) { + var functionName = rules[i + 1]; + var fn = window[functionName]; + if (typeof(fn) === 'function') + return fn(field, rules, i, options); + + }, + /** + * Field match + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _equals: function(field, rules, i, options) { + var equalsField = rules[i + 1]; + + if (field.attr('value') != $("#" + equalsField).attr('value')) + return options.allrules.equals.alertText; + }, + /** + * Check the maximum size (in characters) + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _maxSize: function(field, rules, i, options) { + var max = rules[i + 1]; + var len = field.attr('value').length; + + if (len > max) { + var rule = options.allrules.maxSize; + return rule.alertText + max + rule.alertText2; + } + }, + /** + * Check the minimum size (in characters) + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _minSize: function(field, rules, i, options) { + var min = rules[i + 1]; + var len = field.attr('value').length; + + if (len < min) { + var rule = options.allrules.minSize; + return rule.alertText + min + rule.alertText2; + } + }, + /** + * Check number minimum value + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _min: function(field, rules, i, options) { + var min = parseFloat(rules[i + 1]); + var len = parseFloat(field.attr('value')); + + if (len < min) { + var rule = options.allrules.min; + if (rule.alertText2) return rule.alertText + min + rule.alertText2; + return rule.alertText + min; + } + }, + /** + * Check number maximum value + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _max: function(field, rules, i, options) { + var max = parseFloat(rules[i + 1]); + var len = parseFloat(field.attr('value')); + + if (len >max ) { + var rule = options.allrules.max; + if (rule.alertText2) return rule.alertText + max + rule.alertText2; + //orefalo: to review, also do the translations + return rule.alertText + max; + } + }, + /** + * Checks date is in the past + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _past: function(field, rules, i, options) { + + var p=rules[i + 1]; + var pdate = (p.toLowerCase() == "now")? new Date():methods._parseDate(p); + var vdate = methods._parseDate(field.attr('value')); + + if (vdate > pdate ) { + var rule = options.allrules.past; + if (rule.alertText2) return rule.alertText + methods._dateToString(pdate) + rule.alertText2; + return rule.alertText + methods._dateToString(pdate); + } + }, + /** + * Checks date is in the past + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _future: function(field, rules, i, options) { + + var p=rules[i + 1]; + var pdate = (p.toLowerCase() == "now")? new Date():methods._parseDate(p); + var vdate = methods._parseDate(field.attr('value')); + + if (vdate < pdate ) { + var rule = options.allrules.future; + if (rule.alertText2) return rule.alertText + methods._dateToString(pdate) + rule.alertText2; + return rule.alertText + methods._dateToString(pdate); + } + }, + /** + * Max number of checkbox selected + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _maxCheckbox: function(field, rules, i, options) { + + var nbCheck = rules[i + 1]; + var groupname = field.attr("name"); + var groupSize = $("input[name='" + groupname + "']:checked").size(); + if (groupSize > nbCheck) { + options.showArrow = false; + return options.allrules.maxCheckbox.alertText; + } + }, + /** + * Min number of checkbox selected + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return an error string if validation failed + */ + _minCheckbox: function(field, rules, i, options) { + + var nbCheck = rules[i + 1]; + var groupname = field.attr("name"); + var groupSize = $("input[name='" + groupname + "']:checked").size(); + if (groupSize < nbCheck) { + options.showArrow = false; + return options.allrules.minCheckbox.alertText + " " + nbCheck + " " + + options.allrules.minCheckbox.alertText2; + } + }, + /** + * Ajax field validation + * + * @param {jqObject} field + * @param {Array[String]} rules + * @param {int} i rules index + * @param {Map} + * user options + * @return nothing! the ajax validator handles the prompts itself + */ + _ajax: function(field, rules, i, options) { + + var errorSelector = rules[i + 1]; + var rule = options.allrules[errorSelector]; + var extraData = rule.extraData; + + if (!extraData) + extraData = ""; + + if (!options.isError) { + $.ajax({ + type: "GET", + url: rule.url, + cache: false, + dataType: "json", + data: "fieldId=" + field.attr("id") + "&fieldValue=" + field.attr("value") + "&extraData=" + extraData, + field: field, + rule: rule, + methods: methods, + options: options, + beforeSend: function() { + // build the loading prompt + var loadingText = rule.alertTextLoad; + if (loadingText) + methods._showPrompt(field, loadingText, "load", true, options); + }, + error: function(data, transport) { + methods._ajaxError(data, transport); + }, + success: function(json) { + + // asynchronously called on success, data is the json answer from the server + var errorFieldId = json[0]; + var errorField = $($("#" + errorFieldId)[0]); + // make sure we found the element + if (errorField.length == 1) { + + var status = json[1]; + + if (status === false) { + // Houston we got a problem + options.ajaxValidCache[errorFieldId] = false; + options.isError = true; + var promptText = rule.alertText; + methods._showPrompt(errorField, promptText, "", true, options); + } else { + if (options.ajaxValidCache[errorFieldId] !== undefined) + options.ajaxValidCache[errorFieldId] = true; + + // see if we should display a green prompt + var alertTextOk = rule.alertTextOk; + if (alertTextOk) + methods._showPrompt(errorField, alertTextOk, "pass", true, options); + else + methods._closePrompt(errorField); + } + } + } + }); + } + }, + /** + * Common method to handle ajax errors + * + * @param {Object} data + * @param {Object} transport + */ + _ajaxError: function(data, transport) { + if(data.status === 0 && transport === null) + alert("The page is not served from a server! ajax call failed"); + else if(console) + console.log("Ajax error: " + data.status + " " + transport); + }, + /** + * date -> string + * + * @param {Object} date + */ + _dateToString: function(date) { + + return date.getFullYear()+"-"+(date.getMonth()+1)+"-"+date.getDate(); + }, + /** + * Parses an ISO date + * @param {String} d + */ + _parseDate: function(d) { + + var dateParts = d.split("-"); + if(dateParts!==d) + dateParts = d.split("/"); + return new Date(dateParts[0], (dateParts[1] - 1) ,dateParts[2]); + }, + /** + * Builds or updates a prompt with the given information + * + * @param {jqObject} field + * @param {String} promptText html text to display type + * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red) + * @param {boolean} ajaxed - use to mark fields than being validated with ajax + * @param {Map} options user options + */ + _showPrompt: function(field, promptText, type, ajaxed, options) { + var prompt = methods._getPrompt(field); + if (prompt) + methods._updatePrompt(field, prompt, promptText, type, ajaxed, options); + else + methods._buildPrompt(field, promptText, type, ajaxed, options); + }, + /** + * Builds and shades a prompt for the given field. + * + * @param {jqObject} field + * @param {String} promptText html text to display type + * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red) + * @param {boolean} ajaxed - use to mark fields than being validated with ajax + * @param {Map} options user options + */ + _buildPrompt: function(field, promptText, type, ajaxed, options) { + + // create the prompt + var prompt = $('<div>'); + prompt.addClass(methods._getClassName(field.attr("id")) + "formError"); + // add a class name to identify the parent form of the prompt + if(field.is(":input")) prompt.addClass("parentForm"+methods._getClassName(field.parents('form').attr("id"))); + prompt.addClass("formError"); + + switch (type) { + case "pass": + prompt.addClass("greenPopup"); + break; + case "load": + prompt.addClass("blackPopup"); + } + if (ajaxed) + prompt.addClass("ajaxed"); + + // create the prompt content + var promptContent = $('<div>').addClass("formErrorContent").html(promptText).appendTo(prompt); + // create the css arrow pointing at the field + // note that there is no triangle on max-checkbox and radio + if (options.showArrow) { + var arrow = $('<div>').addClass("formErrorArrow"); + + switch (options.promptPosition) { + case "bottomLeft": + case "bottomRight": + prompt.find(".formErrorContent").before(arrow); + arrow.addClass("formErrorArrowBottom").html('<div class="line1"><!-- --></div><div class="line2"><!-- --></div><div class="line3"><!-- --></div><div class="line4"><!-- --></div><div class="line5"><!-- --></div><div class="line6"><!-- --></div><div class="line7"><!-- --></div><div class="line8"><!-- --></div><div class="line9"><!-- --></div><div class="line10"><!-- --></div>'); + break; + case "topLeft": + case "topRight": + arrow.html('<div class="line10"><!-- --></div><div class="line9"><!-- --></div><div class="line8"><!-- --></div><div class="line7"><!-- --></div><div class="line6"><!-- --></div><div class="line5"><!-- --></div><div class="line4"><!-- --></div><div class="line3"><!-- --></div><div class="line2"><!-- --></div><div class="line1"><!-- --></div>'); + prompt.append(arrow); + break; + } + } + + //Cedric: Needed if a container is in position:relative + // insert prompt in the form or in the overflown container? + if (options.isOverflown) + field.before(prompt); + else + $("body").append(prompt); + + var pos = methods._calculatePosition(field, prompt, options); + prompt.css({ + "top": pos.callerTopPosition, + "left": pos.callerleftPosition, + "marginTop": pos.marginTopSize, + "opacity": 0 + }); + + return prompt.animate({ + "opacity": 0.87 + }); + + }, + /** + * Updates the prompt text field - the field for which the prompt + * @param {jqObject} field + * @param {String} promptText html text to display type + * @param {String} type the type of bubble: 'pass' (green), 'load' (black) anything else (red) + * @param {boolean} ajaxed - use to mark fields than being validated with ajax + * @param {Map} options user options + */ + _updatePrompt: function(field, prompt, promptText, type, ajaxed, options) { + + if (prompt) { + if (type == "pass") + prompt.addClass("greenPopup"); + else + prompt.removeClass("greenPopup"); + + if (type == "load") + prompt.addClass("blackPopup"); + else + prompt.removeClass("blackPopup"); + + if (ajaxed) + prompt.addClass("ajaxed"); + else + prompt.removeClass("ajaxed"); + + prompt.find(".formErrorContent").html(promptText); + + var pos = methods._calculatePosition(field, prompt, options); + prompt.animate({ + "top": pos.callerTopPosition, + "marginTop": pos.marginTopSize + }); + } + }, + /** + * Closes the prompt associated with the given field + * + * @param {jqObject} + * field + */ + _closePrompt: function(field) { + + var prompt = methods._getPrompt(field); + if (prompt) + prompt.fadeTo("fast", 0, function() { + prompt.remove(); + }); + }, + closePrompt: function(field) { + return methods._closePrompt(field); + }, + /** + * Returns the error prompt matching the field if any + * + * @param {jqObject} + * field + * @return undefined or the error prompt (jqObject) + */ + _getPrompt: function(field) { + + var className = "." + methods._getClassName(field.attr("id")) + "formError"; + var match = $(className)[0]; + if (match) + return $(match); + }, + /** + * Calculates prompt position + * + * @param {jqObject} + * field + * @param {jqObject} + * the prompt + * @param {Map} + * options + * @return positions + */ + _calculatePosition: function(field, promptElmt, options) { + + var promptTopPosition, promptleftPosition, marginTopSize; + var fieldWidth = field.width(); + var promptHeight = promptElmt.height(); + + var overflow = options.isOverflown; + if (overflow) { + // is the form contained in an overflown container? + promptTopPosition = promptleftPosition = 0; + // compensation for the arrow + marginTopSize = -promptHeight; + } else { + var offset = field.offset(); + promptTopPosition = offset.top; + promptleftPosition = offset.left; + marginTopSize = 0; + } + + switch (options.promptPosition) { + + default: + case "topRight": + if (overflow) + // Is the form contained in an overflown container? + promptleftPosition += fieldWidth - 30; + else { + promptleftPosition += fieldWidth - 30; + promptTopPosition += -promptHeight; + } + break; + case "topLeft": + promptTopPosition += -promptHeight - 10; + break; + case "centerRight": + promptleftPosition += fieldWidth + 13; + break; + case "bottomLeft": + promptTopPosition = promptTopPosition + field.height() + 15; + break; + case "bottomRight": + promptleftPosition += fieldWidth - 30; + promptTopPosition += field.height() + 5; + } + + return { + "callerTopPosition": promptTopPosition + "px", + "callerleftPosition": promptleftPosition + "px", + "marginTopSize": marginTopSize + "px" + }; + }, + /** + * Saves the user options and variables in the form.data + * + * @param {jqObject} + * form - the form where the user option should be saved + * @param {Map} + * options - the user options + * @return the user options (extended from the defaults) + */ + _saveOptions: function(form, options) { + + // is there a language localisation ? + if ($.validationEngineLanguage) + var allRules = $.validationEngineLanguage.allRules; + else + $.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page"); + + var userOptions = $.extend({ + + // Name of the event triggering field validation + validationEventTrigger: "blur", + // Automatically scroll viewport to the first error + scroll: true, + // Opening box position, possible locations are: topLeft, + // topRight, bottomLeft, centerRight, bottomRight + promptPosition: "topRight", + bindMethod:"bind", + showAllErrors: true, + + // if set to true, the form data is sent asynchronously via ajax to the form.action url (get) + ajaxFormValidation: false, + // Ajax form validation callback method: boolean onComplete(form, status, errors, options) + // retuns false if the form.submit event needs to be canceled. + onAjaxFormComplete: $.noop, + // called right before the ajax call, may return false to cancel + onBeforeAjaxFormValidation: $.noop, + // Stops form from submitting and execute function assiciated with it + onValidationComplete: false, + + // Used when the form is displayed within a scrolling DIV + isOverflown: false, + overflownDIV: "", + + // --- Internals DO NOT TOUCH or OVERLOAD --- + // validation rules and i18 + allrules: allRules, + // true when form and fields are binded + binded: false, + // set to true, when the prompt arrow needs to be displayed + showArrow: true, + // did one of the validation fail ? kept global to stop further ajax validations + isError: false, + // Caches field validation status, typically only bad status are created. + // the array is used during ajax form validation to detect issues early and prevent an expensive submit + ajaxValidCache: {} + + }, options); + + form.data('jqv', userOptions); + return userOptions; + }, + + /** + * Removes forbidden characters from class name + * @param {String} className + */ + _getClassName: function(className) { + return className.replace(":","_").replace(".","_"); + } + }; + + /** + * Plugin entry point. + * You may pass an action as a parameter or a list of options. + * if none, the init and attach methods are being called. + * Remember: if you pass options, the attached method is NOT called automatically + * + * @param {String} + * method (optional) action + */ + $.fn.validationEngine = function(method) { + + var form = $(this); + if(!form[0]) return false; // stop here if the form does not exist + + if (typeof(method) === 'string' && method.charAt(0) != '_' && methods[method]) { + + // make sure init is called once + if(method != "showPrompt" && method != "hidePrompt" && method != "hide" && method != "hideAll") + methods.init.apply(form); + + return methods[method].apply(form, Array.prototype.slice.call(arguments, 1)); + } else if (typeof method === 'object' || !method) { + // default constructor with or without arguments + methods.init.apply(form, arguments); + return methods.attach.apply(form); + } else { + $.error('Method ' + method + ' does not exist in jQuery.validationEngine'); + } + }; +})(jQuery); diff --git a/src/static/jquery/jquery.validationEngine/validationEngine.jquery.css b/src/static/jquery/jquery.validationEngine/validationEngine.jquery.css new file mode 100755 index 0000000..771410a --- /dev/null +++ b/src/static/jquery/jquery.validationEngine/validationEngine.jquery.css @@ -0,0 +1,142 @@ +.inputContainer { + position: relative; + float: left; +} + +.formError { + position: absolute; + top: 300px; + left: 300px; + display: block; + z-index: 5000; + cursor: pointer; +} + +.ajaxSubmit { + padding: 20px; + background: #55ea55; + border: 1px solid #999; + display: none +} + +.formError .formErrorContent { + width: 100%; + background: #ee0101; + position:relative; + z-index:5001; + color: #fff; + width: 150px; + font-family: tahoma; + font-size: 11px; + border: 2px solid #ddd; + box-shadow: 0 0 6px #000; + -moz-box-shadow: 0 0 6px #000; + -webkit-box-shadow: 0 0 6px #000; + padding: 4px 10px 4px 10px; + border-radius: 6px; + -moz-border-radius: 6px; + -webkit-border-radius: 6px; +} + +.greenPopup .formErrorContent { + background: #33be40; +} + +.blackPopup .formErrorContent { + background: #393939; + color: #FFF; +} + +.formError .formErrorArrow { + width: 15px; + margin: -2px 0 0 13px; + position:relative; + z-index: 5006; +} + +.formError .formErrorArrowBottom { + box-shadow: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + margin: 0px 0 0 12px; + top:2px; +} + +.formError .formErrorArrow div { + border-left: 2px solid #ddd; + border-right: 2px solid #ddd; + box-shadow: 0 2px 3px #444; + -moz-box-shadow: 0 2px 3px #444; + -webkit-box-shadow: 0 2px 3px #444; + font-size: 0px; + height: 1px; + background: #ee0101; + margin: 0 auto; + line-height: 0; + font-size: 0; + display: block; +} + +.formError .formErrorArrowBottom div { + box-shadow: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; +} + +.greenPopup .formErrorArrow div { + background: #33be40; +} + +.blackPopup .formErrorArrow div { + background: #393939; + color: #FFF; +} + +.formError .formErrorArrow .line10 { + width: 15px; + border: none; +} + +.formError .formErrorArrow .line9 { + width: 13px; + border: none; +} + +.formError .formErrorArrow .line8 { + width: 11px; +} + +.formError .formErrorArrow .line7 { + width: 9px; +} + +.formError .formErrorArrow .line6 { + width: 7px; +} + +.formError .formErrorArrow .line5 { + width: 5px; +} + +.formError .formErrorArrow .line4 { + width: 3px; +} + +.formError .formErrorArrow .line3 { + width: 1px; + border-left: 2px solid #ddd; + border-right: 2px solid #ddd; + border-bottom: 0 solid #ddd; +} + +.formError .formErrorArrow .line2 { + width: 3px; + border: none; + background: #ddd; +} + +.formError .formErrorArrow .line1 { + width: 1px; + border: none; + background: #ddd; +} \ No newline at end of file diff --git a/src/static/jquery/select2-3.4.6/LICENSE b/src/static/jquery/select2-3.4.6/LICENSE new file mode 100755 index 0000000..0247cc7 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/LICENSE @@ -0,0 +1,18 @@ +Copyright 2014 Igor Vaynberg + +Version: @@ver@@ Timestamp: @@timestamp@@ + +This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU +General Public License version 2 (the "GPL License"). You may choose either license to govern your +use of this software only upon the condition that you accept all of the terms of either the Apache +License or the GPL License. + +You may obtain a copy of the Apache License and the GPL License at: + +http://www.apache.org/licenses/LICENSE-2.0 +http://www.gnu.org/licenses/gpl-2.0.html + +Unless required by applicable law or agreed to in writing, software distributed under the Apache License +or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the Apache License and the GPL License for the specific language governing +permissions and limitations under the Apache License and the GPL License. diff --git a/src/static/jquery/select2-3.4.6/README.md b/src/static/jquery/select2-3.4.6/README.md new file mode 100755 index 0000000..8784c86 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/README.md @@ -0,0 +1,84 @@ +Select2 +======= + +Select2 is a jQuery-based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results. + +To get started, checkout examples and documentation at http://ivaynberg.github.com/select2 + +Use cases +--------- + +* Enhancing native selects with search. +* Enhancing native selects with a better multi-select interface. +* Loading data from JavaScript: easily load items via ajax and have them searchable. +* Nesting optgroups: native selects only support one level of nested. Select2 does not have this restriction. +* Tagging: ability to add new items on the fly. +* Working with large, remote datasets: ability to partially load a dataset based on the search term. +* Paging of large datasets: easy support for loading more pages when the results are scrolled to the end. +* Templating: support for custom rendering of results and selections. + +Browser compatibility +--------------------- +* IE 8+ +* Chrome 8+ +* Firefox 10+ +* Safari 3+ +* Opera 10.6+ + +Integrations +------------ + +* [Wicket-Select2](https://github.com/ivaynberg/wicket-select2) (Java / [Apache Wicket](http://wicket.apache.org)) +* [select2-rails](https://github.com/argerim/select2-rails) (Ruby on Rails) +* [AngularUI](http://angular-ui.github.com/#directives-select2) ([AngularJS](angularjs.org)) +* [Django](https://github.com/applegrew/django-select2) +* [Symfony](https://github.com/19Gerhard85/sfSelect2WidgetsPlugin) +* [Symfony2](https://github.com/avocode/FormExtensions) +* [Bootstrap](https://github.com/t0m/select2-bootstrap-css) (CSS skin) +* [Yii](https://github.com/tonybolzan/yii-select2) + +Internationalization (i18n) +--------------------------- + +Select2 supports multiple languages by simply including the right +language JS file (`select2_locale_it.js`, `select2_locale_nl.js`, etc.). + +Missing a language? Just copy `select2_locale_en.js.template`, translate +it, and make a pull request back to Select2 here on GitHub. + +Bug tracker +----------- + +Have a bug? Please create an issue here on GitHub! + +https://github.com/ivaynberg/select2/issues + +Mailing list +------------ + +Have a question? Ask on our mailing list! + +select2@googlegroups.com + +https://groups.google.com/d/forum/select2 + + +Copyright and license +--------------------- + +Copyright 2012 Igor Vaynberg + +This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU +General Public License version 2 (the "GPL License"). You may choose either license to govern your +use of this software only upon the condition that you accept all of the terms of either the Apache +License or the GPL License. + +You may obtain a copy of the Apache License and the GPL License in the LICENSE file, or at: + +http://www.apache.org/licenses/LICENSE-2.0 +http://www.gnu.org/licenses/gpl-2.0.html + +Unless required by applicable law or agreed to in writing, software distributed under the Apache License +or the GPL License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the Apache License and the GPL License for the specific language governing +permissions and limitations under the Apache License and the GPL License. diff --git a/src/static/jquery/select2-3.4.6/bower.json b/src/static/jquery/select2-3.4.6/bower.json new file mode 100755 index 0000000..e8ea780 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/bower.json @@ -0,0 +1,8 @@ +{ + "name": "select2", + "version": "3.4.6", + "main": ["select2.js", "select2.css", "select2.png", "select2x2.png", "select2-spinner.gif"], + "dependencies": { + "jquery": ">= 1.7.1" + } +} diff --git a/src/static/jquery/select2-3.4.6/component.json b/src/static/jquery/select2-3.4.6/component.json new file mode 100755 index 0000000..4a747f2 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/component.json @@ -0,0 +1,66 @@ +{ + "name": "select2", + "repo": "ivaynberg/select2", + "description": "Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.", + "version": "3.4.6", + "demo": "http://ivaynberg.github.io/select2/", + "keywords": [ + "jquery" + ], + "main": "select2.js", + "styles": [ + "select2.css", + "select2-bootstrap.css" + ], + "scripts": [ + "select2.js", + "select2_locale_ar.js", + "select2_locale_bg.js", + "select2_locale_ca.js", + "select2_locale_cs.js", + "select2_locale_da.js", + "select2_locale_de.js", + "select2_locale_el.js", + "select2_locale_es.js", + "select2_locale_et.js", + "select2_locale_eu.js", + "select2_locale_fa.js", + "select2_locale_fi.js", + "select2_locale_fr.js", + "select2_locale_gl.js", + "select2_locale_he.js", + "select2_locale_hr.js", + "select2_locale_hu.js", + "select2_locale_id.js", + "select2_locale_is.js", + "select2_locale_it.js", + "select2_locale_ja.js", + "select2_locale_ka.js", + "select2_locale_ko.js", + "select2_locale_lt.js", + "select2_locale_lv.js", + "select2_locale_mk.js", + "select2_locale_ms.js", + "select2_locale_nl.js", + "select2_locale_no.js", + "select2_locale_pl.js", + "select2_locale_pt-BR.js", + "select2_locale_pt-PT.js", + "select2_locale_ro.js", + "select2_locale_ru.js", + "select2_locale_sk.js", + "select2_locale_sv.js", + "select2_locale_th.js", + "select2_locale_tr.js", + "select2_locale_uk.js", + "select2_locale_vi.js", + "select2_locale_zh-CN.js", + "select2_locale_zh-TW.js" + ], + "images": [ + "select2-spinner.gif", + "select2.png", + "select2x2.png" + ], + "license": "MIT" +} diff --git a/src/static/jquery/select2-3.4.6/composer.json b/src/static/jquery/select2-3.4.6/composer.json new file mode 100755 index 0000000..ab2e2b7 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/composer.json @@ -0,0 +1,29 @@ +{ + "name": + "ivaynberg/select2", + "description": "Select2 is a jQuery based replacement for select boxes.", + "version": "3.4.6", + "type": "component", + "homepage": "http://ivaynberg.github.io/select2/", + "license": "Apache-2.0", + "require": { + "robloach/component-installer": "*", + "components/jquery": ">=1.7.1" + }, + "extra": { + "component": { + "scripts": [ + "select2.js" + ], + "files": [ + "select2.js", + "select2_locale_*.js", + "select2.css", + "select2-bootstrap.css", + "select2-spinner.gif", + "select2.png", + "select2x2.png" + ] + } + } +} diff --git a/src/static/jquery/select2-3.4.6/package.json b/src/static/jquery/select2-3.4.6/package.json new file mode 100755 index 0000000..065dbc9 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/package.json @@ -0,0 +1,20 @@ +{ + "name" : "Select2", + "description": "Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.", + "homepage": "http://ivaynberg.github.io/select2", + "author": "Igor Vaynberg", + "repository": {"type": "git", "url": "git://github.com/ivaynberg/select2.git"}, + "main": "select2.js", + "version": "3.4.6", + "jspm": { + "main": "select2", + "files": ["select2.js", "select2.png", "select2.css", "select2-spinner.gif"], + "shim": { + "select2": { + "imports": ["jquery", "./select2.css!"], + "exports": "$" + } + }, + "buildConfig": { "uglify": true } + } +} diff --git a/src/static/jquery/select2-3.4.6/release.sh b/src/static/jquery/select2-3.4.6/release.sh new file mode 100755 index 0000000..0d2e279 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/release.sh @@ -0,0 +1,79 @@ +#!/bin/bash +set -e + +echo -n "Enter the version for this release: " + +read ver + +if [ ! $ver ]; then + echo "Invalid version." + exit +fi + +name="select2" +js="$name.js" +mini="$name.min.js" +css="$name.css" +release="$name-$ver" +tag="$ver" +branch="build-$ver" +curbranch=`git branch | grep "*" | sed "s/* //"` +timestamp=$(date) +tokens="s/@@ver@@/$ver/g;s/\@@timestamp@@/$timestamp/g" +remote="github" + +echo "Pulling from origin" + +git pull + +echo "Updating Version Identifiers" + +sed -E -e "s/\"version\": \"([0-9\.]+)\",/\"version\": \"$ver\",/g" -i -- bower.json select2.jquery.json component.json composer.json package.json + +git add bower.json +git add select2.jquery.json +git add component.json +git add composer.json +git add package.json + +git commit -m "modified version identifiers in descriptors for release $ver" +git push + +git branch "$branch" +git checkout "$branch" + +echo "Tokenizing..." + +find . -name "$js" | xargs -I{} sed -e "$tokens" -i -- {} +find . -name "$css" | xargs -I{} sed -e "$tokens" -i -- {} + +sed -e "s/latest/$ver/g" -i -- bower.json + +git add "$js" +git add "$css" + +echo "Minifying..." + +echo "/*" > "$mini" +cat LICENSE | sed "$tokens" >> "$mini" +echo "*/" >> "$mini" + +curl -s \ + --data-urlencode "js_code@$js" \ + http://marijnhaverbeke.nl/uglifyjs \ + >> "$mini" + +git add "$mini" + +git commit -m "release $ver" + +echo "Tagging..." +git tag -a "$tag" -m "tagged version $ver" +git push "$remote" --tags + +echo "Cleaning Up..." + +git checkout "$curbranch" +git branch -D "$branch" + +echo "Done" diff --git a/src/static/jquery/select2-3.4.6/select2-bootstrap.css b/src/static/jquery/select2-3.4.6/select2-bootstrap.css new file mode 100755 index 0000000..3b83f0a --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2-bootstrap.css @@ -0,0 +1,87 @@ +.form-control .select2-choice { + border: 0; + border-radius: 2px; +} + +.form-control .select2-choice .select2-arrow { + border-radius: 0 2px 2px 0; +} + +.form-control.select2-container { + height: auto !important; + padding: 0; +} + +.form-control.select2-container.select2-dropdown-open { + border-color: #5897FB; + border-radius: 3px 3px 0 0; +} + +.form-control .select2-container.select2-dropdown-open .select2-choices { + border-radius: 3px 3px 0 0; +} + +.form-control.select2-container .select2-choices { + border: 0 !important; + border-radius: 3px; +} + +.control-group.warning .select2-container .select2-choice, +.control-group.warning .select2-container .select2-choices, +.control-group.warning .select2-container-active .select2-choice, +.control-group.warning .select2-container-active .select2-choices, +.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choice, +.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choices, +.control-group.warning .select2-container-multi.select2-container-active .select2-choices { + border: 1px solid #C09853 !important; +} + +.control-group.warning .select2-container .select2-choice div { + border-left: 1px solid #C09853 !important; + background: #FCF8E3 !important; +} + +.control-group.error .select2-container .select2-choice, +.control-group.error .select2-container .select2-choices, +.control-group.error .select2-container-active .select2-choice, +.control-group.error .select2-container-active .select2-choices, +.control-group.error .select2-dropdown-open.select2-drop-above .select2-choice, +.control-group.error .select2-dropdown-open.select2-drop-above .select2-choices, +.control-group.error .select2-container-multi.select2-container-active .select2-choices { + border: 1px solid #B94A48 !important; +} + +.control-group.error .select2-container .select2-choice div { + border-left: 1px solid #B94A48 !important; + background: #F2DEDE !important; +} + +.control-group.info .select2-container .select2-choice, +.control-group.info .select2-container .select2-choices, +.control-group.info .select2-container-active .select2-choice, +.control-group.info .select2-container-active .select2-choices, +.control-group.info .select2-dropdown-open.select2-drop-above .select2-choice, +.control-group.info .select2-dropdown-open.select2-drop-above .select2-choices, +.control-group.info .select2-container-multi.select2-container-active .select2-choices { + border: 1px solid #3A87AD !important; +} + +.control-group.info .select2-container .select2-choice div { + border-left: 1px solid #3A87AD !important; + background: #D9EDF7 !important; +} + +.control-group.success .select2-container .select2-choice, +.control-group.success .select2-container .select2-choices, +.control-group.success .select2-container-active .select2-choice, +.control-group.success .select2-container-active .select2-choices, +.control-group.success .select2-dropdown-open.select2-drop-above .select2-choice, +.control-group.success .select2-dropdown-open.select2-drop-above .select2-choices, +.control-group.success .select2-container-multi.select2-container-active .select2-choices { + border: 1px solid #468847 !important; +} + +.control-group.success .select2-container .select2-choice div { + border-left: 1px solid #468847 !important; + background: #DFF0D8 !important; +} diff --git a/src/static/jquery/select2-3.4.6/select2-spinner.gif b/src/static/jquery/select2-3.4.6/select2-spinner.gif new file mode 100755 index 0000000000000000000000000000000000000000..5b33f7e54f4e55b6b8774d86d96895db9af044b4 GIT binary patch literal 1849 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 EAHN$8j{pDw literal 0 HcmV?d00001 diff --git a/src/static/jquery/select2-3.4.6/select2.css b/src/static/jquery/select2-3.4.6/select2.css new file mode 100755 index 0000000..4b2a2a8 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2.css @@ -0,0 +1,646 @@ +/* +Version: 3.4.6 Timestamp: Sat Mar 22 22:30:15 EDT 2014 +*/ +.select2-container { + margin: 0; + position: relative; + display: inline-block; + /* inline-block for ie7 */ + zoom: 1; + *display: inline; + vertical-align: middle; +} + +.select2-container, +.select2-drop, +.select2-search, +.select2-search input { + /* + Force border-box so that % widths fit the parent + container without overlap because of margin/padding. + More Info : http://www.quirksmode.org/css/box.html + */ + -webkit-box-sizing: border-box; /* webkit */ + -moz-box-sizing: border-box; /* firefox */ + box-sizing: border-box; /* css3 */ +} + +.select2-container .select2-choice { + display: block; + height: 26px; + padding: 0 0 0 8px; + overflow: hidden; + position: relative; + + border: 1px solid #aaa; + white-space: nowrap; + line-height: 26px; + color: #444; + text-decoration: none; + + border-radius: 4px; + + background-clip: padding-box; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + background-color: #fff; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.5, #fff)); + background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 50%); + background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 50%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#eeeeee', GradientType = 0); + background-image: linear-gradient(to top, #eee 0%, #fff 50%); +} + +.select2-container.select2-drop-above .select2-choice { + border-bottom-color: #aaa; + + border-radius: 0 0 4px 4px; + + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.9, #fff)); + background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 90%); + background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 90%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); + background-image: linear-gradient(to bottom, #eee 0%, #fff 90%); +} + +.select2-container.select2-allowclear .select2-choice .select2-chosen { + margin-right: 42px; +} + +.select2-container .select2-choice > .select2-chosen { + margin-right: 26px; + display: block; + overflow: hidden; + + white-space: nowrap; + + text-overflow: ellipsis; + float: none; + width: auto; +} + +.select2-container .select2-choice abbr { + display: none; + width: 12px; + height: 12px; + position: absolute; + right: 24px; + top: 8px; + + font-size: 1px; + text-decoration: none; + + border: 0; + background: url('select2.png') right top no-repeat; + cursor: pointer; + outline: 0; +} + +.select2-container.select2-allowclear .select2-choice abbr { + display: inline-block; +} + +.select2-container .select2-choice abbr:hover { + background-position: right -11px; + cursor: pointer; +} + +.select2-drop-mask { + border: 0; + margin: 0; + padding: 0; + position: fixed; + left: 0; + top: 0; + min-height: 100%; + min-width: 100%; + height: auto; + width: auto; + opacity: 0; + z-index: 9998; + /* styles required for IE to work */ + background-color: #fff; + filter: alpha(opacity=0); +} + +.select2-drop { + width: 100%; + margin-top: -1px; + position: absolute; + z-index: 9999; + top: 100%; + + background: #fff; + color: #000; + border: 1px solid #aaa; + border-top: 0; + + border-radius: 0 0 4px 4px; + + -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15); + box-shadow: 0 4px 5px rgba(0, 0, 0, .15); +} + +.select2-drop.select2-drop-above { + margin-top: 1px; + border-top: 1px solid #aaa; + border-bottom: 0; + + border-radius: 4px 4px 0 0; + + -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); + box-shadow: 0 -4px 5px rgba(0, 0, 0, .15); +} + +.select2-drop-active { + border: 1px solid #5897fb; + border-top: none; +} + +.select2-drop.select2-drop-above.select2-drop-active { + border-top: 1px solid #5897fb; +} + +.select2-drop-auto-width { + border-top: 1px solid #aaa; + width: auto; +} + +.select2-drop-auto-width .select2-search { + padding-top: 4px; +} + +.select2-container .select2-choice .select2-arrow { + display: inline-block; + width: 18px; + height: 100%; + position: absolute; + right: 0; + top: 0; + + border-left: 1px solid #aaa; + border-radius: 0 4px 4px 0; + + background-clip: padding-box; + + background: #ccc; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee)); + background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%); + background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0); + background-image: linear-gradient(to top, #ccc 0%, #eee 60%); +} + +.select2-container .select2-choice .select2-arrow b { + display: block; + width: 100%; + height: 100%; + background: url('select2.png') no-repeat 0 1px; +} + +.select2-search { + display: inline-block; + width: 100%; + min-height: 26px; + margin: 0; + padding-left: 4px; + padding-right: 4px; + + position: relative; + z-index: 10000; + + white-space: nowrap; +} + +.select2-search input { + width: 100%; + height: auto !important; + min-height: 26px; + padding: 4px 20px 4px 5px; + margin: 0; + + outline: 0; + font-family: sans-serif; + font-size: 1em; + + border: 1px solid #aaa; + border-radius: 0; + + -webkit-box-shadow: none; + box-shadow: none; + + background: #fff url('select2.png') no-repeat 100% -22px; + background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee)); + background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%); + background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%); + background: url('select2.png') no-repeat 100% -22px, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0; +} + +.select2-drop.select2-drop-above .select2-search input { + margin-top: 4px; +} + +.select2-search input.select2-active { + background: #fff url('select2-spinner.gif') no-repeat 100%; + background: url('select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee)); + background: url('select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%); + background: url('select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%); + background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(to bottom, #fff 85%, #eee 99%) 0 0; +} + +.select2-container-active .select2-choice, +.select2-container-active .select2-choices { + border: 1px solid #5897fb; + outline: none; + + -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3); + box-shadow: 0 0 5px rgba(0, 0, 0, .3); +} + +.select2-dropdown-open .select2-choice { + border-bottom-color: transparent; + -webkit-box-shadow: 0 1px 0 #fff inset; + box-shadow: 0 1px 0 #fff inset; + + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + + background-color: #eee; + background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(0.5, #eee)); + background-image: -webkit-linear-gradient(center bottom, #fff 0%, #eee 50%); + background-image: -moz-linear-gradient(center bottom, #fff 0%, #eee 50%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0); + background-image: linear-gradient(to top, #fff 0%, #eee 50%); +} + +.select2-dropdown-open.select2-drop-above .select2-choice, +.select2-dropdown-open.select2-drop-above .select2-choices { + border: 1px solid #5897fb; + border-top-color: transparent; + + background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(0.5, #eee)); + background-image: -webkit-linear-gradient(center top, #fff 0%, #eee 50%); + background-image: -moz-linear-gradient(center top, #fff 0%, #eee 50%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0); + background-image: linear-gradient(to bottom, #fff 0%, #eee 50%); +} + +.select2-dropdown-open .select2-choice .select2-arrow { + background: transparent; + border-left: none; + filter: none; +} +.select2-dropdown-open .select2-choice .select2-arrow b { + background-position: -18px 1px; +} + +.select2-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +/* results */ +.select2-results { + max-height: 200px; + padding: 0 0 0 4px; + margin: 4px 4px 4px 0; + position: relative; + overflow-x: hidden; + overflow-y: auto; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +.select2-results ul.select2-result-sub { + margin: 0; + padding-left: 0; +} + +.select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px } +.select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px } +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px } +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px } +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px } +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px } +.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px } + +.select2-results li { + list-style: none; + display: list-item; + background-image: none; +} + +.select2-results li.select2-result-with-children > .select2-result-label { + font-weight: bold; +} + +.select2-results .select2-result-label { + padding: 3px 7px 4px; + margin: 0; + cursor: pointer; + + min-height: 1em; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.select2-results .select2-highlighted { + background: #3875d7; + color: #fff; +} + +.select2-results li em { + background: #feffde; + font-style: normal; +} + +.select2-results .select2-highlighted em { + background: transparent; +} + +.select2-results .select2-highlighted ul { + background: #fff; + color: #000; +} + + +.select2-results .select2-no-results, +.select2-results .select2-searching, +.select2-results .select2-selection-limit { + background: #f4f4f4; + display: list-item; + padding-left: 5px; +} + +/* +disabled look for disabled choices in the results dropdown +*/ +.select2-results .select2-disabled.select2-highlighted { + color: #666; + background: #f4f4f4; + display: list-item; + cursor: default; +} +.select2-results .select2-disabled { + background: #f4f4f4; + display: list-item; + cursor: default; +} + +.select2-results .select2-selected { + display: none; +} + +.select2-more-results.select2-active { + background: #f4f4f4 url('select2-spinner.gif') no-repeat 100%; +} + +.select2-more-results { + background: #f4f4f4; + display: list-item; +} + +/* disabled styles */ + +.select2-container.select2-container-disabled .select2-choice { + background-color: #f4f4f4; + background-image: none; + border: 1px solid #ddd; + cursor: default; +} + +.select2-container.select2-container-disabled .select2-choice .select2-arrow { + background-color: #f4f4f4; + background-image: none; + border-left: 0; +} + +.select2-container.select2-container-disabled .select2-choice abbr { + display: none; +} + + +/* multiselect */ + +.select2-container-multi .select2-choices { + height: auto !important; + height: 1%; + margin: 0; + padding: 0; + position: relative; + + border: 1px solid #aaa; + cursor: text; + overflow: hidden; + + background-color: #fff; + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eee), color-stop(15%, #fff)); + background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%); + background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%); + background-image: linear-gradient(to bottom, #eee 1%, #fff 15%); +} + +.select2-locked { + padding: 3px 5px 3px 5px !important; +} + +.select2-container-multi .select2-choices { + min-height: 26px; +} + +.select2-container-multi.select2-container-active .select2-choices { + border: 1px solid #5897fb; + outline: none; + + -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3); + box-shadow: 0 0 5px rgba(0, 0, 0, .3); +} +.select2-container-multi .select2-choices li { + float: left; + list-style: none; +} +html[dir="rtl"] .select2-container-multi .select2-choices li +{ + float: right; +} +.select2-container-multi .select2-choices .select2-search-field { + margin: 0; + padding: 0; + white-space: nowrap; +} + +.select2-container-multi .select2-choices .select2-search-field input { + padding: 5px; + margin: 1px 0; + + font-family: sans-serif; + font-size: 100%; + color: #666; + outline: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + background: transparent !important; +} + +.select2-container-multi .select2-choices .select2-search-field input.select2-active { + background: #fff url('select2-spinner.gif') no-repeat 100% !important; +} + +.select2-default { + color: #999 !important; +} + +.select2-container-multi .select2-choices .select2-search-choice { + padding: 3px 5px 3px 18px; + margin: 3px 0 3px 5px; + position: relative; + + line-height: 13px; + color: #333; + cursor: default; + border: 1px solid #aaaaaa; + + border-radius: 3px; + + -webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05); + box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05); + + background-clip: padding-box; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + background-color: #e4e4e4; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0); + background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee)); + background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); + background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); + background-image: linear-gradient(to top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%); +} +html[dir="rtl"] .select2-container-multi .select2-choices .select2-search-choice +{ + margin-left: 0; + margin-right: 5px; +} +.select2-container-multi .select2-choices .select2-search-choice .select2-chosen { + cursor: default; +} +.select2-container-multi .select2-choices .select2-search-choice-focus { + background: #d4d4d4; +} + +.select2-search-choice-close { + display: block; + width: 12px; + height: 13px; + position: absolute; + right: 3px; + top: 4px; + + font-size: 1px; + outline: none; + background: url('select2.png') right top no-repeat; +} +html[dir="rtl"] .select2-search-choice-close { + right: auto; + left: 3px; +} + +.select2-container-multi .select2-search-choice-close { + left: 3px; +} + +.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover { + background-position: right -11px; +} +.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close { + background-position: right -11px; +} + +/* disabled styles */ +.select2-container-multi.select2-container-disabled .select2-choices { + background-color: #f4f4f4; + background-image: none; + border: 1px solid #ddd; + cursor: default; +} + +.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice { + padding: 3px 5px 3px 5px; + border: 1px solid #ddd; + background-image: none; + background-color: #f4f4f4; +} + +.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { display: none; + background: none; +} +/* end multiselect */ + + +.select2-result-selectable .select2-match, +.select2-result-unselectable .select2-match { + text-decoration: underline; +} + +.select2-offscreen, .select2-offscreen:focus { + clip: rect(0 0 0 0) !important; + width: 1px !important; + height: 1px !important; + border: 0 !important; + margin: 0 !important; + padding: 0 !important; + overflow: hidden !important; + position: absolute !important; + outline: 0 !important; + left: 0px !important; + top: 0px !important; +} + +.select2-display-none { + display: none; +} + +.select2-measure-scrollbar { + position: absolute; + top: -10000px; + left: -10000px; + width: 100px; + height: 100px; + overflow: scroll; +} + +/* Retina-ize icons */ + +@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 2dppx) { + .select2-search input, + .select2-search-choice-close, + .select2-container .select2-choice abbr, + .select2-container .select2-choice .select2-arrow b { + background-image: url('select2x2.png') !important; + background-repeat: no-repeat !important; + background-size: 60px 40px !important; + } + + .select2-search input { + background-position: 100% -21px !important; + } +} diff --git a/src/static/jquery/select2-3.4.6/select2.jquery.json b/src/static/jquery/select2-3.4.6/select2.jquery.json new file mode 100755 index 0000000..1407f55 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2.jquery.json @@ -0,0 +1,36 @@ +{ + "name": "select2", + "title": "Select2", + "description": "Select2 is a jQuery based replacement for select boxes. It supports searching, remote data sets, and infinite scrolling of results.", + "keywords": [ + "select", + "autocomplete", + "typeahead", + "dropdown", + "multiselect", + "tag", + "tagging" + ], + "version": "3.4.6", + "author": { + "name": "Igor Vaynberg", + "url": "https://github.com/ivaynberg" + }, + "licenses": [ + { + "type": "Apache", + "url": "http://www.apache.org/licenses/LICENSE-2.0" + }, + { + "type": "GPL v2", + "url": "http://www.gnu.org/licenses/gpl-2.0.html" + } + ], + "bugs": "https://github.com/ivaynberg/select2/issues", + "homepage": "http://ivaynberg.github.com/select2", + "docs": "http://ivaynberg.github.com/select2/", + "download": "https://github.com/ivaynberg/select2/tags", + "dependencies": { + "jquery": ">=1.7.1" + } +} diff --git a/src/static/jquery/select2-3.4.6/select2.js b/src/static/jquery/select2-3.4.6/select2.js new file mode 100755 index 0000000..f2a75f3 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2.js @@ -0,0 +1,3397 @@ +/* +Copyright 2012 Igor Vaynberg + +Version: 3.4.6 Timestamp: Sat Mar 22 22:30:15 EDT 2014 + +This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU +General Public License version 2 (the "GPL License"). You may choose either license to govern your +use of this software only upon the condition that you accept all of the terms of either the Apache +License or the GPL License. + +You may obtain a copy of the Apache License and the GPL License at: + + http://www.apache.org/licenses/LICENSE-2.0 + http://www.gnu.org/licenses/gpl-2.0.html + +Unless required by applicable law or agreed to in writing, software distributed under the +Apache License or the GPL License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the Apache License and the GPL License for +the specific language governing permissions and limitations under the Apache License and the GPL License. +*/ +(function ($) { + if(typeof $.fn.each2 == "undefined") { + $.extend($.fn, { + /* + * 4-10 times faster .each replacement + * use it carefully, as it overrides jQuery context of element on each iteration + */ + each2 : function (c) { + var j = $([0]), i = -1, l = this.length; + while ( + ++i < l + && (j.context = j[0] = this[i]) + && c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object + ); + return this; + } + }); + } +})(jQuery); + +(function ($, undefined) { + "use strict"; + /*global document, window, jQuery, console */ + + if (window.Select2 !== undefined) { + return; + } + + var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer, + lastMousePosition={x:0,y:0}, $document, scrollBarDimensions, + + KEY = { + TAB: 9, + ENTER: 13, + ESC: 27, + SPACE: 32, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + SHIFT: 16, + CTRL: 17, + ALT: 18, + PAGE_UP: 33, + PAGE_DOWN: 34, + HOME: 36, + END: 35, + BACKSPACE: 8, + DELETE: 46, + isArrow: function (k) { + k = k.which ? k.which : k; + switch (k) { + case KEY.LEFT: + case KEY.RIGHT: + case KEY.UP: + case KEY.DOWN: + return true; + } + return false; + }, + isControl: function (e) { + var k = e.which; + switch (k) { + case KEY.SHIFT: + case KEY.CTRL: + case KEY.ALT: + return true; + } + + if (e.metaKey) return true; + + return false; + }, + isFunctionKey: function (k) { + k = k.which ? k.which : k; + return k >= 112 && k <= 123; + } + }, + MEASURE_SCROLLBAR_TEMPLATE = "<div class='select2-measure-scrollbar'></div>", + + DIACRITICS = {"\u24B6":"A","\uFF21":"A","\u00C0":"A","\u00C1":"A","\u00C2":"A","\u1EA6":"A","\u1EA4":"A","\u1EAA":"A","\u1EA8":"A","\u00C3":"A","\u0100":"A","\u0102":"A","\u1EB0":"A","\u1EAE":"A","\u1EB4":"A","\u1EB2":"A","\u0226":"A","\u01E0":"A","\u00C4":"A","\u01DE":"A","\u1EA2":"A","\u00C5":"A","\u01FA":"A","\u01CD":"A","\u0200":"A","\u0202":"A","\u1EA0":"A","\u1EAC":"A","\u1EB6":"A","\u1E00":"A","\u0104":"A","\u023A":"A","\u2C6F":"A","\uA732":"AA","\u00C6":"AE","\u01FC":"AE","\u01E2":"AE","\uA734":"AO","\uA736":"AU","\uA738":"AV","\uA73A":"AV","\uA73C":"AY","\u24B7":"B","\uFF22":"B","\u1E02":"B","\u1E04":"B","\u1E06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24B8":"C","\uFF23":"C","\u0106":"C","\u0108":"C","\u010A":"C","\u010C":"C","\u00C7":"C","\u1E08":"C","\u0187":"C","\u023B":"C","\uA73E":"C","\u24B9":"D","\uFF24":"D","\u1E0A":"D","\u010E":"D","\u1E0C":"D","\u1E10":"D","\u1E12":"D","\u1E0E":"D","\u0110":"D","\u018B":"D","\u018A":"D","\u0189":"D","\uA779":"D","\u01F1":"DZ","\u01C4":"DZ","\u01F2":"Dz","\u01C5":"Dz","\u24BA":"E","\uFF25":"E","\u00C8":"E","\u00C9":"E","\u00CA":"E","\u1EC0":"E","\u1EBE":"E","\u1EC4":"E","\u1EC2":"E","\u1EBC":"E","\u0112":"E","\u1E14":"E","\u1E16":"E","\u0114":"E","\u0116":"E","\u00CB":"E","\u1EBA":"E","\u011A":"E","\u0204":"E","\u0206":"E","\u1EB8":"E","\u1EC6":"E","\u0228":"E","\u1E1C":"E","\u0118":"E","\u1E18":"E","\u1E1A":"E","\u0190":"E","\u018E":"E","\u24BB":"F","\uFF26":"F","\u1E1E":"F","\u0191":"F","\uA77B":"F","\u24BC":"G","\uFF27":"G","\u01F4":"G","\u011C":"G","\u1E20":"G","\u011E":"G","\u0120":"G","\u01E6":"G","\u0122":"G","\u01E4":"G","\u0193":"G","\uA7A0":"G","\uA77D":"G","\uA77E":"G","\u24BD":"H","\uFF28":"H","\u0124":"H","\u1E22":"H","\u1E26":"H","\u021E":"H","\u1E24":"H","\u1E28":"H","\u1E2A":"H","\u0126":"H","\u2C67":"H","\u2C75":"H","\uA78D":"H","\u24BE":"I","\uFF29":"I","\u00CC":"I","\u00CD":"I","\u00CE":"I","\u0128":"I","\u012A":"I","\u012C":"I","\u0130":"I","\u00CF":"I","\u1E2E":"I","\u1EC8":"I","\u01CF":"I","\u0208":"I","\u020A":"I","\u1ECA":"I","\u012E":"I","\u1E2C":"I","\u0197":"I","\u24BF":"J","\uFF2A":"J","\u0134":"J","\u0248":"J","\u24C0":"K","\uFF2B":"K","\u1E30":"K","\u01E8":"K","\u1E32":"K","\u0136":"K","\u1E34":"K","\u0198":"K","\u2C69":"K","\uA740":"K","\uA742":"K","\uA744":"K","\uA7A2":"K","\u24C1":"L","\uFF2C":"L","\u013F":"L","\u0139":"L","\u013D":"L","\u1E36":"L","\u1E38":"L","\u013B":"L","\u1E3C":"L","\u1E3A":"L","\u0141":"L","\u023D":"L","\u2C62":"L","\u2C60":"L","\uA748":"L","\uA746":"L","\uA780":"L","\u01C7":"LJ","\u01C8":"Lj","\u24C2":"M","\uFF2D":"M","\u1E3E":"M","\u1E40":"M","\u1E42":"M","\u2C6E":"M","\u019C":"M","\u24C3":"N","\uFF2E":"N","\u01F8":"N","\u0143":"N","\u00D1":"N","\u1E44":"N","\u0147":"N","\u1E46":"N","\u0145":"N","\u1E4A":"N","\u1E48":"N","\u0220":"N","\u019D":"N","\uA790":"N","\uA7A4":"N","\u01CA":"NJ","\u01CB":"Nj","\u24C4":"O","\uFF2F":"O","\u00D2":"O","\u00D3":"O","\u00D4":"O","\u1ED2":"O","\u1ED0":"O","\u1ED6":"O","\u1ED4":"O","\u00D5":"O","\u1E4C":"O","\u022C":"O","\u1E4E":"O","\u014C":"O","\u1E50":"O","\u1E52":"O","\u014E":"O","\u022E":"O","\u0230":"O","\u00D6":"O","\u022A":"O","\u1ECE":"O","\u0150":"O","\u01D1":"O","\u020C":"O","\u020E":"O","\u01A0":"O","\u1EDC":"O","\u1EDA":"O","\u1EE0":"O","\u1EDE":"O","\u1EE2":"O","\u1ECC":"O","\u1ED8":"O","\u01EA":"O","\u01EC":"O","\u00D8":"O","\u01FE":"O","\u0186":"O","\u019F":"O","\uA74A":"O","\uA74C":"O","\u01A2":"OI","\uA74E":"OO","\u0222":"OU","\u24C5":"P","\uFF30":"P","\u1E54":"P","\u1E56":"P","\u01A4":"P","\u2C63":"P","\uA750":"P","\uA752":"P","\uA754":"P","\u24C6":"Q","\uFF31":"Q","\uA756":"Q","\uA758":"Q","\u024A":"Q","\u24C7":"R","\uFF32":"R","\u0154":"R","\u1E58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1E5A":"R","\u1E5C":"R","\u0156":"R","\u1E5E":"R","\u024C":"R","\u2C64":"R","\uA75A":"R","\uA7A6":"R","\uA782":"R","\u24C8":"S","\uFF33":"S","\u1E9E":"S","\u015A":"S","\u1E64":"S","\u015C":"S","\u1E60":"S","\u0160":"S","\u1E66":"S","\u1E62":"S","\u1E68":"S","\u0218":"S","\u015E":"S","\u2C7E":"S","\uA7A8":"S","\uA784":"S","\u24C9":"T","\uFF34":"T","\u1E6A":"T","\u0164":"T","\u1E6C":"T","\u021A":"T","\u0162":"T","\u1E70":"T","\u1E6E":"T","\u0166":"T","\u01AC":"T","\u01AE":"T","\u023E":"T","\uA786":"T","\uA728":"TZ","\u24CA":"U","\uFF35":"U","\u00D9":"U","\u00DA":"U","\u00DB":"U","\u0168":"U","\u1E78":"U","\u016A":"U","\u1E7A":"U","\u016C":"U","\u00DC":"U","\u01DB":"U","\u01D7":"U","\u01D5":"U","\u01D9":"U","\u1EE6":"U","\u016E":"U","\u0170":"U","\u01D3":"U","\u0214":"U","\u0216":"U","\u01AF":"U","\u1EEA":"U","\u1EE8":"U","\u1EEE":"U","\u1EEC":"U","\u1EF0":"U","\u1EE4":"U","\u1E72":"U","\u0172":"U","\u1E76":"U","\u1E74":"U","\u0244":"U","\u24CB":"V","\uFF36":"V","\u1E7C":"V","\u1E7E":"V","\u01B2":"V","\uA75E":"V","\u0245":"V","\uA760":"VY","\u24CC":"W","\uFF37":"W","\u1E80":"W","\u1E82":"W","\u0174":"W","\u1E86":"W","\u1E84":"W","\u1E88":"W","\u2C72":"W","\u24CD":"X","\uFF38":"X","\u1E8A":"X","\u1E8C":"X","\u24CE":"Y","\uFF39":"Y","\u1EF2":"Y","\u00DD":"Y","\u0176":"Y","\u1EF8":"Y","\u0232":"Y","\u1E8E":"Y","\u0178":"Y","\u1EF6":"Y","\u1EF4":"Y","\u01B3":"Y","\u024E":"Y","\u1EFE":"Y","\u24CF":"Z","\uFF3A":"Z","\u0179":"Z","\u1E90":"Z","\u017B":"Z","\u017D":"Z","\u1E92":"Z","\u1E94":"Z","\u01B5":"Z","\u0224":"Z","\u2C7F":"Z","\u2C6B":"Z","\uA762":"Z","\u24D0":"a","\uFF41":"a","\u1E9A":"a","\u00E0":"a","\u00E1":"a","\u00E2":"a","\u1EA7":"a","\u1EA5":"a","\u1EAB":"a","\u1EA9":"a","\u00E3":"a","\u0101":"a","\u0103":"a","\u1EB1":"a","\u1EAF":"a","\u1EB5":"a","\u1EB3":"a","\u0227":"a","\u01E1":"a","\u00E4":"a","\u01DF":"a","\u1EA3":"a","\u00E5":"a","\u01FB":"a","\u01CE":"a","\u0201":"a","\u0203":"a","\u1EA1":"a","\u1EAD":"a","\u1EB7":"a","\u1E01":"a","\u0105":"a","\u2C65":"a","\u0250":"a","\uA733":"aa","\u00E6":"ae","\u01FD":"ae","\u01E3":"ae","\uA735":"ao","\uA737":"au","\uA739":"av","\uA73B":"av","\uA73D":"ay","\u24D1":"b","\uFF42":"b","\u1E03":"b","\u1E05":"b","\u1E07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24D2":"c","\uFF43":"c","\u0107":"c","\u0109":"c","\u010B":"c","\u010D":"c","\u00E7":"c","\u1E09":"c","\u0188":"c","\u023C":"c","\uA73F":"c","\u2184":"c","\u24D3":"d","\uFF44":"d","\u1E0B":"d","\u010F":"d","\u1E0D":"d","\u1E11":"d","\u1E13":"d","\u1E0F":"d","\u0111":"d","\u018C":"d","\u0256":"d","\u0257":"d","\uA77A":"d","\u01F3":"dz","\u01C6":"dz","\u24D4":"e","\uFF45":"e","\u00E8":"e","\u00E9":"e","\u00EA":"e","\u1EC1":"e","\u1EBF":"e","\u1EC5":"e","\u1EC3":"e","\u1EBD":"e","\u0113":"e","\u1E15":"e","\u1E17":"e","\u0115":"e","\u0117":"e","\u00EB":"e","\u1EBB":"e","\u011B":"e","\u0205":"e","\u0207":"e","\u1EB9":"e","\u1EC7":"e","\u0229":"e","\u1E1D":"e","\u0119":"e","\u1E19":"e","\u1E1B":"e","\u0247":"e","\u025B":"e","\u01DD":"e","\u24D5":"f","\uFF46":"f","\u1E1F":"f","\u0192":"f","\uA77C":"f","\u24D6":"g","\uFF47":"g","\u01F5":"g","\u011D":"g","\u1E21":"g","\u011F":"g","\u0121":"g","\u01E7":"g","\u0123":"g","\u01E5":"g","\u0260":"g","\uA7A1":"g","\u1D79":"g","\uA77F":"g","\u24D7":"h","\uFF48":"h","\u0125":"h","\u1E23":"h","\u1E27":"h","\u021F":"h","\u1E25":"h","\u1E29":"h","\u1E2B":"h","\u1E96":"h","\u0127":"h","\u2C68":"h","\u2C76":"h","\u0265":"h","\u0195":"hv","\u24D8":"i","\uFF49":"i","\u00EC":"i","\u00ED":"i","\u00EE":"i","\u0129":"i","\u012B":"i","\u012D":"i","\u00EF":"i","\u1E2F":"i","\u1EC9":"i","\u01D0":"i","\u0209":"i","\u020B":"i","\u1ECB":"i","\u012F":"i","\u1E2D":"i","\u0268":"i","\u0131":"i","\u24D9":"j","\uFF4A":"j","\u0135":"j","\u01F0":"j","\u0249":"j","\u24DA":"k","\uFF4B":"k","\u1E31":"k","\u01E9":"k","\u1E33":"k","\u0137":"k","\u1E35":"k","\u0199":"k","\u2C6A":"k","\uA741":"k","\uA743":"k","\uA745":"k","\uA7A3":"k","\u24DB":"l","\uFF4C":"l","\u0140":"l","\u013A":"l","\u013E":"l","\u1E37":"l","\u1E39":"l","\u013C":"l","\u1E3D":"l","\u1E3B":"l","\u017F":"l","\u0142":"l","\u019A":"l","\u026B":"l","\u2C61":"l","\uA749":"l","\uA781":"l","\uA747":"l","\u01C9":"lj","\u24DC":"m","\uFF4D":"m","\u1E3F":"m","\u1E41":"m","\u1E43":"m","\u0271":"m","\u026F":"m","\u24DD":"n","\uFF4E":"n","\u01F9":"n","\u0144":"n","\u00F1":"n","\u1E45":"n","\u0148":"n","\u1E47":"n","\u0146":"n","\u1E4B":"n","\u1E49":"n","\u019E":"n","\u0272":"n","\u0149":"n","\uA791":"n","\uA7A5":"n","\u01CC":"nj","\u24DE":"o","\uFF4F":"o","\u00F2":"o","\u00F3":"o","\u00F4":"o","\u1ED3":"o","\u1ED1":"o","\u1ED7":"o","\u1ED5":"o","\u00F5":"o","\u1E4D":"o","\u022D":"o","\u1E4F":"o","\u014D":"o","\u1E51":"o","\u1E53":"o","\u014F":"o","\u022F":"o","\u0231":"o","\u00F6":"o","\u022B":"o","\u1ECF":"o","\u0151":"o","\u01D2":"o","\u020D":"o","\u020F":"o","\u01A1":"o","\u1EDD":"o","\u1EDB":"o","\u1EE1":"o","\u1EDF":"o","\u1EE3":"o","\u1ECD":"o","\u1ED9":"o","\u01EB":"o","\u01ED":"o","\u00F8":"o","\u01FF":"o","\u0254":"o","\uA74B":"o","\uA74D":"o","\u0275":"o","\u01A3":"oi","\u0223":"ou","\uA74F":"oo","\u24DF":"p","\uFF50":"p","\u1E55":"p","\u1E57":"p","\u01A5":"p","\u1D7D":"p","\uA751":"p","\uA753":"p","\uA755":"p","\u24E0":"q","\uFF51":"q","\u024B":"q","\uA757":"q","\uA759":"q","\u24E1":"r","\uFF52":"r","\u0155":"r","\u1E59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1E5B":"r","\u1E5D":"r","\u0157":"r","\u1E5F":"r","\u024D":"r","\u027D":"r","\uA75B":"r","\uA7A7":"r","\uA783":"r","\u24E2":"s","\uFF53":"s","\u00DF":"s","\u015B":"s","\u1E65":"s","\u015D":"s","\u1E61":"s","\u0161":"s","\u1E67":"s","\u1E63":"s","\u1E69":"s","\u0219":"s","\u015F":"s","\u023F":"s","\uA7A9":"s","\uA785":"s","\u1E9B":"s","\u24E3":"t","\uFF54":"t","\u1E6B":"t","\u1E97":"t","\u0165":"t","\u1E6D":"t","\u021B":"t","\u0163":"t","\u1E71":"t","\u1E6F":"t","\u0167":"t","\u01AD":"t","\u0288":"t","\u2C66":"t","\uA787":"t","\uA729":"tz","\u24E4":"u","\uFF55":"u","\u00F9":"u","\u00FA":"u","\u00FB":"u","\u0169":"u","\u1E79":"u","\u016B":"u","\u1E7B":"u","\u016D":"u","\u00FC":"u","\u01DC":"u","\u01D8":"u","\u01D6":"u","\u01DA":"u","\u1EE7":"u","\u016F":"u","\u0171":"u","\u01D4":"u","\u0215":"u","\u0217":"u","\u01B0":"u","\u1EEB":"u","\u1EE9":"u","\u1EEF":"u","\u1EED":"u","\u1EF1":"u","\u1EE5":"u","\u1E73":"u","\u0173":"u","\u1E77":"u","\u1E75":"u","\u0289":"u","\u24E5":"v","\uFF56":"v","\u1E7D":"v","\u1E7F":"v","\u028B":"v","\uA75F":"v","\u028C":"v","\uA761":"vy","\u24E6":"w","\uFF57":"w","\u1E81":"w","\u1E83":"w","\u0175":"w","\u1E87":"w","\u1E85":"w","\u1E98":"w","\u1E89":"w","\u2C73":"w","\u24E7":"x","\uFF58":"x","\u1E8B":"x","\u1E8D":"x","\u24E8":"y","\uFF59":"y","\u1EF3":"y","\u00FD":"y","\u0177":"y","\u1EF9":"y","\u0233":"y","\u1E8F":"y","\u00FF":"y","\u1EF7":"y","\u1E99":"y","\u1EF5":"y","\u01B4":"y","\u024F":"y","\u1EFF":"y","\u24E9":"z","\uFF5A":"z","\u017A":"z","\u1E91":"z","\u017C":"z","\u017E":"z","\u1E93":"z","\u1E95":"z","\u01B6":"z","\u0225":"z","\u0240":"z","\u2C6C":"z","\uA763":"z"}; + + $document = $(document); + + nextUid=(function() { var counter=1; return function() { return counter++; }; }()); + + + function reinsertElement(element) { + var placeholder = $(document.createTextNode('')); + + element.before(placeholder); + placeholder.before(element); + placeholder.remove(); + } + + function stripDiacritics(str) { + var ret, i, l, c; + + if (!str || str.length < 1) return str; + + ret = ""; + for (i = 0, l = str.length; i < l; i++) { + c = str.charAt(i); + ret += DIACRITICS[c] || c; + } + return ret; + } + + function indexOf(value, array) { + var i = 0, l = array.length; + for (; i < l; i = i + 1) { + if (equal(value, array[i])) return i; + } + return -1; + } + + function measureScrollbar () { + var $template = $( MEASURE_SCROLLBAR_TEMPLATE ); + $template.appendTo('body'); + + var dim = { + width: $template.width() - $template[0].clientWidth, + height: $template.height() - $template[0].clientHeight + }; + $template.remove(); + + return dim; + } + + /** + * Compares equality of a and b + * @param a + * @param b + */ + function equal(a, b) { + if (a === b) return true; + if (a === undefined || b === undefined) return false; + if (a === null || b === null) return false; + // Check whether 'a' or 'b' is a string (primitive or object). + // The concatenation of an empty string (+'') converts its argument to a string's primitive. + if (a.constructor === String) return a+'' === b+''; // a+'' - in case 'a' is a String object + if (b.constructor === String) return b+'' === a+''; // b+'' - in case 'b' is a String object + return false; + } + + /** + * Splits the string into an array of values, trimming each value. An empty array is returned for nulls or empty + * strings + * @param string + * @param separator + */ + function splitVal(string, separator) { + var val, i, l; + if (string === null || string.length < 1) return []; + val = string.split(separator); + for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]); + return val; + } + + function getSideBorderPadding(element) { + return element.outerWidth(false) - element.width(); + } + + function installKeyUpChangeEvent(element) { + var key="keyup-change-value"; + element.on("keydown", function () { + if ($.data(element, key) === undefined) { + $.data(element, key, element.val()); + } + }); + element.on("keyup", function () { + var val= $.data(element, key); + if (val !== undefined && element.val() !== val) { + $.removeData(element, key); + element.trigger("keyup-change"); + } + }); + } + + $document.on("mousemove", function (e) { + lastMousePosition.x = e.pageX; + lastMousePosition.y = e.pageY; + }); + + /** + * filters mouse events so an event is fired only if the mouse moved. + * + * filters out mouse events that occur when mouse is stationary but + * the elements under the pointer are scrolled. + */ + function installFilteredMouseMove(element) { + element.on("mousemove", function (e) { + var lastpos = lastMousePosition; + if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) { + $(e.target).trigger("mousemove-filtered", e); + } + }); + } + + /** + * Debounces a function. Returns a function that calls the original fn function only if no invocations have been made + * within the last quietMillis milliseconds. + * + * @param quietMillis number of milliseconds to wait before invoking fn + * @param fn function to be debounced + * @param ctx object to be used as this reference within fn + * @return debounced version of fn + */ + function debounce(quietMillis, fn, ctx) { + ctx = ctx || undefined; + var timeout; + return function () { + var args = arguments; + window.clearTimeout(timeout); + timeout = window.setTimeout(function() { + fn.apply(ctx, args); + }, quietMillis); + }; + } + + /** + * A simple implementation of a thunk + * @param formula function used to lazily initialize the thunk + * @return {Function} + */ + function thunk(formula) { + var evaluated = false, + value; + return function() { + if (evaluated === false) { value = formula(); evaluated = true; } + return value; + }; + }; + + function installDebouncedScroll(threshold, element) { + var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);}); + element.on("scroll", function (e) { + if (indexOf(e.target, element.get()) >= 0) notify(e); + }); + } + + function focus($el) { + if ($el[0] === document.activeElement) return; + + /* set the focus in a 0 timeout - that way the focus is set after the processing + of the current event has finished - which seems like the only reliable way + to set focus */ + window.setTimeout(function() { + var el=$el[0], pos=$el.val().length, range; + + $el.focus(); + + /* make sure el received focus so we do not error out when trying to manipulate the caret. + sometimes modals or others listeners may steal it after its set */ + var isVisible = (el.offsetWidth > 0 || el.offsetHeight > 0); + if (isVisible && el === document.activeElement) { + + /* after the focus is set move the caret to the end, necessary when we val() + just before setting focus */ + if(el.setSelectionRange) + { + el.setSelectionRange(pos, pos); + } + else if (el.createTextRange) { + range = el.createTextRange(); + range.collapse(false); + range.select(); + } + } + }, 0); + } + + function getCursorInfo(el) { + el = $(el)[0]; + var offset = 0; + var length = 0; + if ('selectionStart' in el) { + offset = el.selectionStart; + length = el.selectionEnd - offset; + } else if ('selection' in document) { + el.focus(); + var sel = document.selection.createRange(); + length = document.selection.createRange().text.length; + sel.moveStart('character', -el.value.length); + offset = sel.text.length - length; + } + return { offset: offset, length: length }; + } + + function killEvent(event) { + event.preventDefault(); + event.stopPropagation(); + } + function killEventImmediately(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + + function measureTextWidth(e) { + if (!sizer){ + var style = e[0].currentStyle || window.getComputedStyle(e[0], null); + sizer = $(document.createElement("div")).css({ + position: "absolute", + left: "-10000px", + top: "-10000px", + display: "none", + fontSize: style.fontSize, + fontFamily: style.fontFamily, + fontStyle: style.fontStyle, + fontWeight: style.fontWeight, + letterSpacing: style.letterSpacing, + textTransform: style.textTransform, + whiteSpace: "nowrap" + }); + sizer.attr("class","select2-sizer"); + $("body").append(sizer); + } + sizer.text(e.val()); + return sizer.width(); + } + + function syncCssClasses(dest, src, adapter) { + var classes, replacements = [], adapted; + + classes = dest.attr("class"); + if (classes) { + classes = '' + classes; // for IE which returns object + $(classes.split(" ")).each2(function() { + if (this.indexOf("select2-") === 0) { + replacements.push(this); + } + }); + } + classes = src.attr("class"); + if (classes) { + classes = '' + classes; // for IE which returns object + $(classes.split(" ")).each2(function() { + if (this.indexOf("select2-") !== 0) { + adapted = adapter(this); + if (adapted) { + replacements.push(adapted); + } + } + }); + } + dest.attr("class", replacements.join(" ")); + } + + + function markMatch(text, term, markup, escapeMarkup) { + var match=stripDiacritics(text.toUpperCase()).indexOf(stripDiacritics(term.toUpperCase())), + tl=term.length; + + if (match<0) { + markup.push(escapeMarkup(text)); + return; + } + + markup.push(escapeMarkup(text.substring(0, match))); + markup.push("<span class='select2-match'>"); + markup.push(escapeMarkup(text.substring(match, match + tl))); + markup.push("</span>"); + markup.push(escapeMarkup(text.substring(match + tl, text.length))); + } + + function defaultEscapeMarkup(markup) { + var replace_map = { + '\\': '&#92;', + '&': '&amp;', + '<': '&lt;', + '>': '&gt;', + '"': '&quot;', + "'": '&#39;', + "/": '&#47;' + }; + + return String(markup).replace(/[&<>"'\/\\]/g, function (match) { + return replace_map[match]; + }); + } + + /** + * Produces an ajax-based query function + * + * @param options object containing configuration parameters + * @param options.params parameter map for the transport ajax call, can contain such options as cache, jsonpCallback, etc. see $.ajax + * @param options.transport function that will be used to execute the ajax request. must be compatible with parameters supported by $.ajax + * @param options.url url for the data + * @param options.data a function(searchTerm, pageNumber, context) that should return an object containing query string parameters for the above url. + * @param options.dataType request data type: ajax, jsonp, other datatypes supported by jQuery's $.ajax function or the transport function if specified + * @param options.quietMillis (optional) milliseconds to wait before making the ajaxRequest, helps debounce the ajax function if invoked too often + * @param options.results a function(remoteData, pageNumber) that converts data returned form the remote request to the format expected by Select2. + * The expected format is an object containing the following keys: + * results array of objects that will be used as choices + * more (optional) boolean indicating whether there are more results available + * Example: {results:[{id:1, text:'Red'},{id:2, text:'Blue'}], more:true} + */ + function ajax(options) { + var timeout, // current scheduled but not yet executed request + handler = null, + quietMillis = options.quietMillis || 100, + ajaxUrl = options.url, + self = this; + + return function (query) { + window.clearTimeout(timeout); + timeout = window.setTimeout(function () { + var data = options.data, // ajax data function + url = ajaxUrl, // ajax url string or function + transport = options.transport || $.fn.select2.ajaxDefaults.transport, + // deprecated - to be removed in 4.0 - use params instead + deprecated = { + type: options.type || 'GET', // set type of request (GET or POST) + cache: options.cache || false, + jsonpCallback: options.jsonpCallback||undefined, + dataType: options.dataType||"json" + }, + params = $.extend({}, $.fn.select2.ajaxDefaults.params, deprecated); + + data = data ? data.call(self, query.term, query.page, query.context) : null; + url = (typeof url === 'function') ? url.call(self, query.term, query.page, query.context) : url; + + if (handler && typeof handler.abort === "function") { handler.abort(); } + + if (options.params) { + if ($.isFunction(options.params)) { + $.extend(params, options.params.call(self)); + } else { + $.extend(params, options.params); + } + } + + $.extend(params, { + url: url, + dataType: options.dataType, + data: data, + success: function (data) { + // TODO - replace query.page with query so users have access to term, page, etc. + var results = options.results(data, query.page); + query.callback(results); + } + }); + handler = transport.call(self, params); + }, quietMillis); + }; + } + + /** + * Produces a query function that works with a local array + * + * @param options object containing configuration parameters. The options parameter can either be an array or an + * object. + * + * If the array form is used it is assumed that it contains objects with 'id' and 'text' keys. + * + * If the object form is used ti is assumed that it contains 'data' and 'text' keys. The 'data' key should contain + * an array of objects that will be used as choices. These objects must contain at least an 'id' key. The 'text' + * key can either be a String in which case it is expected that each element in the 'data' array has a key with the + * value of 'text' which will be used to match choices. Alternatively, text can be a function(item) that can extract + * the text. + */ + function local(options) { + var data = options, // data elements + dataText, + tmp, + text = function (item) { return ""+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search + + if ($.isArray(data)) { + tmp = data; + data = { results: tmp }; + } + + if ($.isFunction(data) === false) { + tmp = data; + data = function() { return tmp; }; + } + + var dataItem = data(); + if (dataItem.text) { + text = dataItem.text; + // if text is not a function we assume it to be a key name + if (!$.isFunction(text)) { + dataText = dataItem.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available + text = function (item) { return item[dataText]; }; + } + } + + return function (query) { + var t = query.term, filtered = { results: [] }, process; + if (t === "") { + query.callback(data()); + return; + } + + process = function(datum, collection) { + var group, attr; + datum = datum[0]; + if (datum.children) { + group = {}; + for (attr in datum) { + if (datum.hasOwnProperty(attr)) group[attr]=datum[attr]; + } + group.children=[]; + $(datum.children).each2(function(i, childDatum) { process(childDatum, group.children); }); + if (group.children.length || query.matcher(t, text(group), datum)) { + collection.push(group); + } + } else { + if (query.matcher(t, text(datum), datum)) { + collection.push(datum); + } + } + }; + + $(data().results).each2(function(i, datum) { process(datum, filtered.results); }); + query.callback(filtered); + }; + } + + // TODO javadoc + function tags(data) { + var isFunc = $.isFunction(data); + return function (query) { + var t = query.term, filtered = {results: []}; + $(isFunc ? data() : data).each(function () { + var isObject = this.text !== undefined, + text = isObject ? this.text : this; + if (t === "" || query.matcher(t, text)) { + filtered.results.push(isObject ? this : {id: this, text: this}); + } + }); + query.callback(filtered); + }; + } + + /** + * Checks if the formatter function should be used. + * + * Throws an error if it is not a function. Returns true if it should be used, + * false if no formatting should be performed. + * + * @param formatter + */ + function checkFormatter(formatter, formatterName) { + if ($.isFunction(formatter)) return true; + if (!formatter) return false; + if (typeof(formatter) === 'string') return true; + throw new Error(formatterName +" must be a string, function, or falsy value"); + } + + function evaluate(val) { + if ($.isFunction(val)) { + var args = Array.prototype.slice.call(arguments, 1); + return val.apply(null, args); + } + return val; + } + + function countResults(results) { + var count = 0; + $.each(results, function(i, item) { + if (item.children) { + count += countResults(item.children); + } else { + count++; + } + }); + return count; + } + + /** + * Default tokenizer. This function uses breaks the input on substring match of any string from the + * opts.tokenSeparators array and uses opts.createSearchChoice to create the choice object. Both of those + * two options have to be defined in order for the tokenizer to work. + * + * @param input text user has typed so far or pasted into the search field + * @param selection currently selected choices + * @param selectCallback function(choice) callback tho add the choice to selection + * @param opts select2's opts + * @return undefined/null to leave the current input unchanged, or a string to change the input to the returned value + */ + function defaultTokenizer(input, selection, selectCallback, opts) { + var original = input, // store the original so we can compare and know if we need to tell the search to update its text + dupe = false, // check for whether a token we extracted represents a duplicate selected choice + token, // token + index, // position at which the separator was found + i, l, // looping variables + separator; // the matched separator + + if (!opts.createSearchChoice || !opts.tokenSeparators || opts.tokenSeparators.length < 1) return undefined; + + while (true) { + index = -1; + + for (i = 0, l = opts.tokenSeparators.length; i < l; i++) { + separator = opts.tokenSeparators[i]; + index = input.indexOf(separator); + if (index >= 0) break; + } + + if (index < 0) break; // did not find any token separator in the input string, bail + + token = input.substring(0, index); + input = input.substring(index + separator.length); + + if (token.length > 0) { + token = opts.createSearchChoice.call(this, token, selection); + if (token !== undefined && token !== null && opts.id(token) !== undefined && opts.id(token) !== null) { + dupe = false; + for (i = 0, l = selection.length; i < l; i++) { + if (equal(opts.id(token), opts.id(selection[i]))) { + dupe = true; break; + } + } + + if (!dupe) selectCallback(token); + } + } + } + + if (original!==input) return input; + } + + /** + * Creates a new class + * + * @param superClass + * @param methods + */ + function clazz(SuperClass, methods) { + var constructor = function () {}; + constructor.prototype = new SuperClass; + constructor.prototype.constructor = constructor; + constructor.prototype.parent = SuperClass.prototype; + constructor.prototype = $.extend(constructor.prototype, methods); + return constructor; + } + + AbstractSelect2 = clazz(Object, { + + // abstract + bind: function (func) { + var self = this; + return function () { + func.apply(self, arguments); + }; + }, + + // abstract + init: function (opts) { + var results, search, resultsSelector = ".select2-results"; + + // prepare options + this.opts = opts = this.prepareOpts(opts); + + this.id=opts.id; + + // destroy if called on an existing component + if (opts.element.data("select2") !== undefined && + opts.element.data("select2") !== null) { + opts.element.data("select2").destroy(); + } + + this.container = this.createContainer(); + + this.liveRegion = $("<span>", { + role: "status", + "aria-live": "polite" + }) + .addClass("select2-hidden-accessible") + .appendTo(document.body); + + this.containerId="s2id_"+(opts.element.attr("id") || "autogen"+nextUid()).replace(/([;&,\-\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1'); + this.containerSelector="#"+this.containerId; + this.container.attr("id", this.containerId); + + // cache the body so future lookups are cheap + this.body = thunk(function() { return opts.element.closest("body"); }); + + syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass); + + this.container.attr("style", opts.element.attr("style")); + this.container.css(evaluate(opts.containerCss)); + this.container.addClass(evaluate(opts.containerCssClass)); + + this.elementTabIndex = this.opts.element.attr("tabindex"); + + // swap container for the element + this.opts.element + .data("select2", this) + .attr("tabindex", "-1") + .before(this.container) + .on("click.select2", killEvent); // do not leak click events + + this.container.data("select2", this); + + this.dropdown = this.container.find(".select2-drop"); + + syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass); + + this.dropdown.addClass(evaluate(opts.dropdownCssClass)); + this.dropdown.data("select2", this); + this.dropdown.on("click", killEvent); + + this.results = results = this.container.find(resultsSelector); + this.search = search = this.container.find("input.select2-input"); + + this.queryCount = 0; + this.resultsPage = 0; + this.context = null; + + // initialize the container + this.initContainer(); + + this.container.on("click", killEvent); + + installFilteredMouseMove(this.results); + this.dropdown.on("mousemove-filtered touchstart touchmove touchend", resultsSelector, this.bind(this.highlightUnderEvent)); + this.dropdown.on("touchend", resultsSelector, this.bind(this.selectHighlighted)); + this.dropdown.on("touchmove", resultsSelector, this.bind(this.touchMoved)); + this.dropdown.on("touchstart touchend", resultsSelector, this.bind(this.clearTouchMoved)); + + installDebouncedScroll(80, this.results); + this.dropdown.on("scroll-debounced", resultsSelector, this.bind(this.loadMoreIfNeeded)); + + // do not propagate change event from the search field out of the component + $(this.container).on("change", ".select2-input", function(e) {e.stopPropagation();}); + $(this.dropdown).on("change", ".select2-input", function(e) {e.stopPropagation();}); + + // if jquery.mousewheel plugin is installed we can prevent out-of-bounds scrolling of results via mousewheel + if ($.fn.mousewheel) { + results.mousewheel(function (e, delta, deltaX, deltaY) { + var top = results.scrollTop(); + if (deltaY > 0 && top - deltaY <= 0) { + results.scrollTop(0); + killEvent(e); + } else if (deltaY < 0 && results.get(0).scrollHeight - results.scrollTop() + deltaY <= results.height()) { + results.scrollTop(results.get(0).scrollHeight - results.height()); + killEvent(e); + } + }); + } + + installKeyUpChangeEvent(search); + search.on("keyup-change input paste", this.bind(this.updateResults)); + search.on("focus", function () { search.addClass("select2-focused"); }); + search.on("blur", function () { search.removeClass("select2-focused");}); + + this.dropdown.on("mouseup", resultsSelector, this.bind(function (e) { + if ($(e.target).closest(".select2-result-selectable").length > 0) { + this.highlightUnderEvent(e); + this.selectHighlighted(e); + } + })); + + // trap all mouse events from leaving the dropdown. sometimes there may be a modal that is listening + // for mouse events outside of itself so it can close itself. since the dropdown is now outside the select2's + // dom it will trigger the popup close, which is not what we want + // focusin can cause focus wars between modals and select2 since the dropdown is outside the modal. + this.dropdown.on("click mouseup mousedown focusin", function (e) { e.stopPropagation(); }); + + this.nextSearchTerm = undefined; + + if ($.isFunction(this.opts.initSelection)) { + // initialize selection based on the current value of the source element + this.initSelection(); + + // if the user has provided a function that can set selection based on the value of the source element + // we monitor the change event on the element and trigger it, allowing for two way synchronization + this.monitorSource(); + } + + if (opts.maximumInputLength !== null) { + this.search.attr("maxlength", opts.maximumInputLength); + } + + var disabled = opts.element.prop("disabled"); + if (disabled === undefined) disabled = false; + this.enable(!disabled); + + var readonly = opts.element.prop("readonly"); + if (readonly === undefined) readonly = false; + this.readonly(readonly); + + // Calculate size of scrollbar + scrollBarDimensions = scrollBarDimensions || measureScrollbar(); + + this.autofocus = opts.element.prop("autofocus"); + opts.element.prop("autofocus", false); + if (this.autofocus) this.focus(); + + this.search.attr("placeholder", opts.searchInputPlaceholder); + }, + + // abstract + destroy: function () { + var element=this.opts.element, select2 = element.data("select2"); + + this.close(); + + if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; } + + if (select2 !== undefined) { + select2.container.remove(); + select2.liveRegion.remove(); + select2.dropdown.remove(); + element + .removeClass("select2-offscreen") + .removeData("select2") + .off(".select2") + .prop("autofocus", this.autofocus || false); + if (this.elementTabIndex) { + element.attr({tabindex: this.elementTabIndex}); + } else { + element.removeAttr("tabindex"); + } + element.show(); + } + }, + + // abstract + optionToData: function(element) { + if (element.is("option")) { + return { + id:element.prop("value"), + text:element.text(), + element: element.get(), + css: element.attr("class"), + disabled: element.prop("disabled"), + locked: equal(element.attr("locked"), "locked") || equal(element.data("locked"), true) + }; + } else if (element.is("optgroup")) { + return { + text:element.attr("label"), + children:[], + element: element.get(), + css: element.attr("class") + }; + } + }, + + // abstract + prepareOpts: function (opts) { + var element, select, idKey, ajaxUrl, self = this; + + element = opts.element; + + if (element.get(0).tagName.toLowerCase() === "select") { + this.select = select = opts.element; + } + + if (select) { + // these options are not allowed when attached to a select because they are picked up off the element itself + $.each(["id", "multiple", "ajax", "query", "createSearchChoice", "initSelection", "data", "tags"], function () { + if (this in opts) { + throw new Error("Option '" + this + "' is not allowed for Select2 when attached to a <select> element."); + } + }); + } + + opts = $.extend({}, { + populateResults: function(container, results, query) { + var populate, id=this.opts.id, liveRegion=this.liveRegion; + + populate=function(results, container, depth) { + + var i, l, result, selectable, disabled, compound, node, label, innerContainer, formatted; + + results = opts.sortResults(results, container, query); + + for (i = 0, l = results.length; i < l; i = i + 1) { + + result=results[i]; + + disabled = (result.disabled === true); + selectable = (!disabled) && (id(result) !== undefined); + + compound=result.children && result.children.length > 0; + + node=$("<li></li>"); + node.addClass("select2-results-dept-"+depth); + node.addClass("select2-result"); + node.addClass(selectable ? "select2-result-selectable" : "select2-result-unselectable"); + if (disabled) { node.addClass("select2-disabled"); } + if (compound) { node.addClass("select2-result-with-children"); } + node.addClass(self.opts.formatResultCssClass(result)); + node.attr("role", "presentation"); + + label=$(document.createElement("div")); + label.addClass("select2-result-label"); + label.attr("id", "select2-result-label-" + nextUid()); + label.attr("role", "option"); + + formatted=opts.formatResult(result, label, query, self.opts.escapeMarkup); + if (formatted!==undefined) { + label.html(formatted); + node.append(label); + } + + + if (compound) { + + innerContainer=$("<ul></ul>"); + innerContainer.addClass("select2-result-sub"); + populate(result.children, innerContainer, depth+1); + node.append(innerContainer); + } + + node.data("select2-data", result); + container.append(node); + } + + liveRegion.text(opts.formatMatches(results.length)); + }; + + populate(results, container, 0); + } + }, $.fn.select2.defaults, opts); + + if (typeof(opts.id) !== "function") { + idKey = opts.id; + opts.id = function (e) { return e[idKey]; }; + } + + if ($.isArray(opts.element.data("select2Tags"))) { + if ("tags" in opts) { + throw "tags specified as both an attribute 'data-select2-tags' and in options of Select2 " + opts.element.attr("id"); + } + opts.tags=opts.element.data("select2Tags"); + } + + if (select) { + opts.query = this.bind(function (query) { + var data = { results: [], more: false }, + term = query.term, + children, placeholderOption, process; + + process=function(element, collection) { + var group; + if (element.is("option")) { + if (query.matcher(term, element.text(), element)) { + collection.push(self.optionToData(element)); + } + } else if (element.is("optgroup")) { + group=self.optionToData(element); + element.children().each2(function(i, elm) { process(elm, group.children); }); + if (group.children.length>0) { + collection.push(group); + } + } + }; + + children=element.children(); + + // ignore the placeholder option if there is one + if (this.getPlaceholder() !== undefined && children.length > 0) { + placeholderOption = this.getPlaceholderOption(); + if (placeholderOption) { + children=children.not(placeholderOption); + } + } + + children.each2(function(i, elm) { process(elm, data.results); }); + + query.callback(data); + }); + // this is needed because inside val() we construct choices from options and there id is hardcoded + opts.id=function(e) { return e.id; }; + } else { + if (!("query" in opts)) { + + if ("ajax" in opts) { + ajaxUrl = opts.element.data("ajax-url"); + if (ajaxUrl && ajaxUrl.length > 0) { + opts.ajax.url = ajaxUrl; + } + opts.query = ajax.call(opts.element, opts.ajax); + } else if ("data" in opts) { + opts.query = local(opts.data); + } else if ("tags" in opts) { + opts.query = tags(opts.tags); + if (opts.createSearchChoice === undefined) { + opts.createSearchChoice = function (term) { return {id: $.trim(term), text: $.trim(term)}; }; + } + if (opts.initSelection === undefined) { + opts.initSelection = function (element, callback) { + var data = []; + $(splitVal(element.val(), opts.separator)).each(function () { + var obj = { id: this, text: this }, + tags = opts.tags; + if ($.isFunction(tags)) tags=tags(); + $(tags).each(function() { if (equal(this.id, obj.id)) { obj = this; return false; } }); + data.push(obj); + }); + + callback(data); + }; + } + } + } + } + if (typeof(opts.query) !== "function") { + throw "query function not defined for Select2 " + opts.element.attr("id"); + } + + if (opts.createSearchChoicePosition === 'top') { + opts.createSearchChoicePosition = function(list, item) { list.unshift(item); }; + } + else if (opts.createSearchChoicePosition === 'bottom') { + opts.createSearchChoicePosition = function(list, item) { list.push(item); }; + } + else if (typeof(opts.createSearchChoicePosition) !== "function") { + throw "invalid createSearchChoicePosition option must be 'top', 'bottom' or a custom function"; + } + + return opts; + }, + + /** + * Monitor the original element for changes and update select2 accordingly + */ + // abstract + monitorSource: function () { + var el = this.opts.element, sync, observer; + + el.on("change.select2", this.bind(function (e) { + if (this.opts.element.data("select2-change-triggered") !== true) { + this.initSelection(); + } + })); + + sync = this.bind(function () { + + // sync enabled state + var disabled = el.prop("disabled"); + if (disabled === undefined) disabled = false; + this.enable(!disabled); + + var readonly = el.prop("readonly"); + if (readonly === undefined) readonly = false; + this.readonly(readonly); + + syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass); + this.container.addClass(evaluate(this.opts.containerCssClass)); + + syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass); + this.dropdown.addClass(evaluate(this.opts.dropdownCssClass)); + + }); + + // IE8-10 + el.on("propertychange.select2", sync); + + // hold onto a reference of the callback to work around a chromium bug + if (this.mutationCallback === undefined) { + this.mutationCallback = function (mutations) { + mutations.forEach(sync); + } + } + + // safari, chrome, firefox, IE11 + observer = window.MutationObserver || window.WebKitMutationObserver|| window.MozMutationObserver; + if (observer !== undefined) { + if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; } + this.propertyObserver = new observer(this.mutationCallback); + this.propertyObserver.observe(el.get(0), { attributes:true, subtree:false }); + } + }, + + // abstract + triggerSelect: function(data) { + var evt = $.Event("select2-selecting", { val: this.id(data), object: data }); + this.opts.element.trigger(evt); + return !evt.isDefaultPrevented(); + }, + + /** + * Triggers the change event on the source element + */ + // abstract + triggerChange: function (details) { + + details = details || {}; + details= $.extend({}, details, { type: "change", val: this.val() }); + // prevents recursive triggering + this.opts.element.data("select2-change-triggered", true); + this.opts.element.trigger(details); + this.opts.element.data("select2-change-triggered", false); + + // some validation frameworks ignore the change event and listen instead to keyup, click for selects + // so here we trigger the click event manually + this.opts.element.click(); + + // ValidationEngine ignores the change event and listens instead to blur + // so here we trigger the blur event manually if so desired + if (this.opts.blurOnChange) + this.opts.element.blur(); + }, + + //abstract + isInterfaceEnabled: function() + { + return this.enabledInterface === true; + }, + + // abstract + enableInterface: function() { + var enabled = this._enabled && !this._readonly, + disabled = !enabled; + + if (enabled === this.enabledInterface) return false; + + this.container.toggleClass("select2-container-disabled", disabled); + this.close(); + this.enabledInterface = enabled; + + return true; + }, + + // abstract + enable: function(enabled) { + if (enabled === undefined) enabled = true; + if (this._enabled === enabled) return; + this._enabled = enabled; + + this.opts.element.prop("disabled", !enabled); + this.enableInterface(); + }, + + // abstract + disable: function() { + this.enable(false); + }, + + // abstract + readonly: function(enabled) { + if (enabled === undefined) enabled = false; + if (this._readonly === enabled) return; + this._readonly = enabled; + + this.opts.element.prop("readonly", enabled); + this.enableInterface(); + }, + + // abstract + opened: function () { + return this.container.hasClass("select2-dropdown-open"); + }, + + // abstract + positionDropdown: function() { + var $dropdown = this.dropdown, + offset = this.container.offset(), + height = this.container.outerHeight(false), + width = this.container.outerWidth(false), + dropHeight = $dropdown.outerHeight(false), + $window = $(window), + windowWidth = $window.width(), + windowHeight = $window.height(), + viewPortRight = $window.scrollLeft() + windowWidth, + viewportBottom = $window.scrollTop() + windowHeight, + dropTop = offset.top + height, + dropLeft = offset.left, + enoughRoomBelow = dropTop + dropHeight <= viewportBottom, + enoughRoomAbove = (offset.top - dropHeight) >= $window.scrollTop(), + dropWidth = $dropdown.outerWidth(false), + enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight, + aboveNow = $dropdown.hasClass("select2-drop-above"), + bodyOffset, + above, + changeDirection, + css, + resultsListNode; + + // always prefer the current above/below alignment, unless there is not enough room + if (aboveNow) { + above = true; + if (!enoughRoomAbove && enoughRoomBelow) { + changeDirection = true; + above = false; + } + } else { + above = false; + if (!enoughRoomBelow && enoughRoomAbove) { + changeDirection = true; + above = true; + } + } + + //if we are changing direction we need to get positions when dropdown is hidden; + if (changeDirection) { + $dropdown.hide(); + offset = this.container.offset(); + height = this.container.outerHeight(false); + width = this.container.outerWidth(false); + dropHeight = $dropdown.outerHeight(false); + viewPortRight = $window.scrollLeft() + windowWidth; + viewportBottom = $window.scrollTop() + windowHeight; + dropTop = offset.top + height; + dropLeft = offset.left; + dropWidth = $dropdown.outerWidth(false); + enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight; + $dropdown.show(); + } + + if (this.opts.dropdownAutoWidth) { + resultsListNode = $('.select2-results', $dropdown)[0]; + $dropdown.addClass('select2-drop-auto-width'); + $dropdown.css('width', ''); + // Add scrollbar width to dropdown if vertical scrollbar is present + dropWidth = $dropdown.outerWidth(false) + (resultsListNode.scrollHeight === resultsListNode.clientHeight ? 0 : scrollBarDimensions.width); + dropWidth > width ? width = dropWidth : dropWidth = width; + enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight; + } + else { + this.container.removeClass('select2-drop-auto-width'); + } + + //console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow); + //console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove); + + // fix positioning when body has an offset and is not position: static + if (this.body().css('position') !== 'static') { + bodyOffset = this.body().offset(); + dropTop -= bodyOffset.top; + dropLeft -= bodyOffset.left; + } + + if (!enoughRoomOnRight) { + dropLeft = offset.left + this.container.outerWidth(false) - dropWidth; + } + + css = { + left: dropLeft, + width: width + }; + + if (above) { + css.top = offset.top - dropHeight; + css.bottom = 'auto'; + this.container.addClass("select2-drop-above"); + $dropdown.addClass("select2-drop-above"); + } + else { + css.top = dropTop; + css.bottom = 'auto'; + this.container.removeClass("select2-drop-above"); + $dropdown.removeClass("select2-drop-above"); + } + css = $.extend(css, evaluate(this.opts.dropdownCss)); + + $dropdown.css(css); + }, + + // abstract + shouldOpen: function() { + var event; + + if (this.opened()) return false; + + if (this._enabled === false || this._readonly === true) return false; + + event = $.Event("select2-opening"); + this.opts.element.trigger(event); + return !event.isDefaultPrevented(); + }, + + // abstract + clearDropdownAlignmentPreference: function() { + // clear the classes used to figure out the preference of where the dropdown should be opened + this.container.removeClass("select2-drop-above"); + this.dropdown.removeClass("select2-drop-above"); + }, + + /** + * Opens the dropdown + * + * @return {Boolean} whether or not dropdown was opened. This method will return false if, for example, + * the dropdown is already open, or if the 'open' event listener on the element called preventDefault(). + */ + // abstract + open: function () { + + if (!this.shouldOpen()) return false; + + this.opening(); + + return true; + }, + + /** + * Performs the opening of the dropdown + */ + // abstract + opening: function() { + var cid = this.containerId, + scroll = "scroll." + cid, + resize = "resize."+cid, + orient = "orientationchange."+cid, + mask; + + this.container.addClass("select2-dropdown-open").addClass("select2-container-active"); + + this.clearDropdownAlignmentPreference(); + + if(this.dropdown[0] !== this.body().children().last()[0]) { + this.dropdown.detach().appendTo(this.body()); + } + + // create the dropdown mask if doesn't already exist + mask = $("#select2-drop-mask"); + if (mask.length == 0) { + mask = $(document.createElement("div")); + mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask"); + mask.hide(); + mask.appendTo(this.body()); + mask.on("mousedown touchstart click", function (e) { + // Prevent IE from generating a click event on the body + reinsertElement(mask); + + var dropdown = $("#select2-drop"), self; + if (dropdown.length > 0) { + self=dropdown.data("select2"); + if (self.opts.selectOnBlur) { + self.selectHighlighted({noFocus: true}); + } + self.close(); + e.preventDefault(); + e.stopPropagation(); + } + }); + } + + // ensure the mask is always right before the dropdown + if (this.dropdown.prev()[0] !== mask[0]) { + this.dropdown.before(mask); + } + + // move the global id to the correct dropdown + $("#select2-drop").removeAttr("id"); + this.dropdown.attr("id", "select2-drop"); + + // show the elements + mask.show(); + + this.positionDropdown(); + this.dropdown.show(); + this.positionDropdown(); + + this.dropdown.addClass("select2-drop-active"); + + // attach listeners to events that can change the position of the container and thus require + // the position of the dropdown to be updated as well so it does not come unglued from the container + var that = this; + this.container.parents().add(window).each(function () { + $(this).on(resize+" "+scroll+" "+orient, function (e) { + that.positionDropdown(); + }); + }); + + + }, + + // abstract + close: function () { + if (!this.opened()) return; + + var cid = this.containerId, + scroll = "scroll." + cid, + resize = "resize."+cid, + orient = "orientationchange."+cid; + + // unbind event listeners + this.container.parents().add(window).each(function () { $(this).off(scroll).off(resize).off(orient); }); + + this.clearDropdownAlignmentPreference(); + + $("#select2-drop-mask").hide(); + this.dropdown.removeAttr("id"); // only the active dropdown has the select2-drop id + this.dropdown.hide(); + this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active"); + this.results.empty(); + + + this.clearSearch(); + this.search.removeClass("select2-active"); + this.opts.element.trigger($.Event("select2-close")); + }, + + /** + * Opens control, sets input value, and updates results. + */ + // abstract + externalSearch: function (term) { + this.open(); + this.search.val(term); + this.updateResults(false); + }, + + // abstract + clearSearch: function () { + + }, + + //abstract + getMaximumSelectionSize: function() { + return evaluate(this.opts.maximumSelectionSize); + }, + + // abstract + ensureHighlightVisible: function () { + var results = this.results, children, index, child, hb, rb, y, more; + + index = this.highlight(); + + if (index < 0) return; + + if (index == 0) { + + // if the first element is highlighted scroll all the way to the top, + // that way any unselectable headers above it will also be scrolled + // into view + + results.scrollTop(0); + return; + } + + children = this.findHighlightableChoices().find('.select2-result-label'); + + child = $(children[index]); + + hb = child.offset().top + child.outerHeight(true); + + // if this is the last child lets also make sure select2-more-results is visible + if (index === children.length - 1) { + more = results.find("li.select2-more-results"); + if (more.length > 0) { + hb = more.offset().top + more.outerHeight(true); + } + } + + rb = results.offset().top + results.outerHeight(true); + if (hb > rb) { + results.scrollTop(results.scrollTop() + (hb - rb)); + } + y = child.offset().top - results.offset().top; + + // make sure the top of the element is visible + if (y < 0 && child.css('display') != 'none' ) { + results.scrollTop(results.scrollTop() + y); // y is negative + } + }, + + // abstract + findHighlightableChoices: function() { + return this.results.find(".select2-result-selectable:not(.select2-disabled):not(.select2-selected)"); + }, + + // abstract + moveHighlight: function (delta) { + var choices = this.findHighlightableChoices(), + index = this.highlight(); + + while (index > -1 && index < choices.length) { + index += delta; + var choice = $(choices[index]); + if (choice.hasClass("select2-result-selectable") && !choice.hasClass("select2-disabled") && !choice.hasClass("select2-selected")) { + this.highlight(index); + break; + } + } + }, + + // abstract + highlight: function (index) { + var choices = this.findHighlightableChoices(), + choice, + data; + + if (arguments.length === 0) { + return indexOf(choices.filter(".select2-highlighted")[0], choices.get()); + } + + if (index >= choices.length) index = choices.length - 1; + if (index < 0) index = 0; + + this.removeHighlight(); + + choice = $(choices[index]); + choice.addClass("select2-highlighted"); + + // ensure assistive technology can determine the active choice + this.search.attr("aria-activedescendant", choice.find(".select2-result-label").attr("id")); + + this.ensureHighlightVisible(); + + this.liveRegion.text(choice.text()); + + data = choice.data("select2-data"); + if (data) { + this.opts.element.trigger({ type: "select2-highlight", val: this.id(data), choice: data }); + } + }, + + removeHighlight: function() { + this.results.find(".select2-highlighted").removeClass("select2-highlighted"); + }, + + touchMoved: function() { + this._touchMoved = true; + }, + + clearTouchMoved: function() { + this._touchMoved = false; + }, + + // abstract + countSelectableResults: function() { + return this.findHighlightableChoices().length; + }, + + // abstract + highlightUnderEvent: function (event) { + var el = $(event.target).closest(".select2-result-selectable"); + if (el.length > 0 && !el.is(".select2-highlighted")) { + var choices = this.findHighlightableChoices(); + this.highlight(choices.index(el)); + } else if (el.length == 0) { + // if we are over an unselectable item remove all highlights + this.removeHighlight(); + } + }, + + // abstract + loadMoreIfNeeded: function () { + var results = this.results, + more = results.find("li.select2-more-results"), + below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible + page = this.resultsPage + 1, + self=this, + term=this.search.val(), + context=this.context; + + if (more.length === 0) return; + below = more.offset().top - results.offset().top - results.height(); + + if (below <= this.opts.loadMorePadding) { + more.addClass("select2-active"); + this.opts.query({ + element: this.opts.element, + term: term, + page: page, + context: context, + matcher: this.opts.matcher, + callback: this.bind(function (data) { + + // ignore a response if the select2 has been closed before it was received + if (!self.opened()) return; + + + self.opts.populateResults.call(this, results, data.results, {term: term, page: page, context:context}); + self.postprocessResults(data, false, false); + + if (data.more===true) { + more.detach().appendTo(results).text(evaluate(self.opts.formatLoadMore, page+1)); + window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10); + } else { + more.remove(); + } + self.positionDropdown(); + self.resultsPage = page; + self.context = data.context; + this.opts.element.trigger({ type: "select2-loaded", items: data }); + })}); + } + }, + + /** + * Default tokenizer function which does nothing + */ + tokenize: function() { + + }, + + /** + * @param initial whether or not this is the call to this method right after the dropdown has been opened + */ + // abstract + updateResults: function (initial) { + var search = this.search, + results = this.results, + opts = this.opts, + data, + self = this, + input, + term = search.val(), + lastTerm = $.data(this.container, "select2-last-term"), + // sequence number used to drop out-of-order responses + queryNumber; + + // prevent duplicate queries against the same term + if (initial !== true && lastTerm && equal(term, lastTerm)) return; + + $.data(this.container, "select2-last-term", term); + + // if the search is currently hidden we do not alter the results + if (initial !== true && (this.showSearchInput === false || !this.opened())) { + return; + } + + function postRender() { + search.removeClass("select2-active"); + self.positionDropdown(); + if (results.find('.select2-no-results,.select2-selection-limit,.select2-searching').length) { + self.liveRegion.text(results.text()); + } + else { + self.liveRegion.text(self.opts.formatMatches(results.find('.select2-result-selectable').length)); + } + } + + function render(html) { + results.html(html); + postRender(); + } + + queryNumber = ++this.queryCount; + + var maxSelSize = this.getMaximumSelectionSize(); + if (maxSelSize >=1) { + data = this.data(); + if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) { + render("<li class='select2-selection-limit'>" + evaluate(opts.formatSelectionTooBig, maxSelSize) + "</li>"); + return; + } + } + + if (search.val().length < opts.minimumInputLength) { + if (checkFormatter(opts.formatInputTooShort, "formatInputTooShort")) { + render("<li class='select2-no-results'>" + evaluate(opts.formatInputTooShort, search.val(), opts.minimumInputLength) + "</li>"); + } else { + render(""); + } + if (initial && this.showSearch) this.showSearch(true); + return; + } + + if (opts.maximumInputLength && search.val().length > opts.maximumInputLength) { + if (checkFormatter(opts.formatInputTooLong, "formatInputTooLong")) { + render("<li class='select2-no-results'>" + evaluate(opts.formatInputTooLong, search.val(), opts.maximumInputLength) + "</li>"); + } else { + render(""); + } + return; + } + + if (opts.formatSearching && this.findHighlightableChoices().length === 0) { + render("<li class='select2-searching'>" + evaluate(opts.formatSearching) + "</li>"); + } + + search.addClass("select2-active"); + + this.removeHighlight(); + + // give the tokenizer a chance to pre-process the input + input = this.tokenize(); + if (input != undefined && input != null) { + search.val(input); + } + + this.resultsPage = 1; + + opts.query({ + element: opts.element, + term: search.val(), + page: this.resultsPage, + context: null, + matcher: opts.matcher, + callback: this.bind(function (data) { + var def; // default choice + + // ignore old responses + if (queryNumber != this.queryCount) { + return; + } + + // ignore a response if the select2 has been closed before it was received + if (!this.opened()) { + this.search.removeClass("select2-active"); + return; + } + + // save context, if any + this.context = (data.context===undefined) ? null : data.context; + // create a default choice and prepend it to the list + if (this.opts.createSearchChoice && search.val() !== "") { + def = this.opts.createSearchChoice.call(self, search.val(), data.results); + if (def !== undefined && def !== null && self.id(def) !== undefined && self.id(def) !== null) { + if ($(data.results).filter( + function () { + return equal(self.id(this), self.id(def)); + }).length === 0) { + this.opts.createSearchChoicePosition(data.results, def); + } + } + } + + if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, "formatNoMatches")) { + render("<li class='select2-no-results'>" + evaluate(opts.formatNoMatches, search.val()) + "</li>"); + return; + } + + results.empty(); + self.opts.populateResults.call(this, results, data.results, {term: search.val(), page: this.resultsPage, context:null}); + + if (data.more === true && checkFormatter(opts.formatLoadMore, "formatLoadMore")) { + results.append("<li class='select2-more-results'>" + self.opts.escapeMarkup(evaluate(opts.formatLoadMore, this.resultsPage)) + "</li>"); + window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10); + } + + this.postprocessResults(data, initial); + + postRender(); + + this.opts.element.trigger({ type: "select2-loaded", items: data }); + })}); + }, + + // abstract + cancel: function () { + this.close(); + }, + + // abstract + blur: function () { + // if selectOnBlur == true, select the currently highlighted option + if (this.opts.selectOnBlur) + this.selectHighlighted({noFocus: true}); + + this.close(); + this.container.removeClass("select2-container-active"); + // synonymous to .is(':focus'), which is available in jquery >= 1.6 + if (this.search[0] === document.activeElement) { this.search.blur(); } + this.clearSearch(); + this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); + }, + + // abstract + focusSearch: function () { + focus(this.search); + }, + + // abstract + selectHighlighted: function (options) { + if (this._touchMoved) { + this.clearTouchMoved(); + return; + } + var index=this.highlight(), + highlighted=this.results.find(".select2-highlighted"), + data = highlighted.closest('.select2-result').data("select2-data"); + + if (data) { + this.highlight(index); + this.onSelect(data, options); + } else if (options && options.noFocus) { + this.close(); + } + }, + + // abstract + getPlaceholder: function () { + var placeholderOption; + return this.opts.element.attr("placeholder") || + this.opts.element.attr("data-placeholder") || // jquery 1.4 compat + this.opts.element.data("placeholder") || + this.opts.placeholder || + ((placeholderOption = this.getPlaceholderOption()) !== undefined ? placeholderOption.text() : undefined); + }, + + // abstract + getPlaceholderOption: function() { + if (this.select) { + var firstOption = this.select.children('option').first(); + if (this.opts.placeholderOption !== undefined ) { + //Determine the placeholder option based on the specified placeholderOption setting + return (this.opts.placeholderOption === "first" && firstOption) || + (typeof this.opts.placeholderOption === "function" && this.opts.placeholderOption(this.select)); + } else if (firstOption.text() === "" && firstOption.val() === "") { + //No explicit placeholder option specified, use the first if it's blank + return firstOption; + } + } + }, + + /** + * Get the desired width for the container element. This is + * derived first from option `width` passed to select2, then + * the inline 'style' on the original element, and finally + * falls back to the jQuery calculated element width. + */ + // abstract + initContainerWidth: function () { + function resolveContainerWidth() { + var style, attrs, matches, i, l, attr; + + if (this.opts.width === "off") { + return null; + } else if (this.opts.width === "element"){ + return this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px'; + } else if (this.opts.width === "copy" || this.opts.width === "resolve") { + // check if there is inline style on the element that contains width + style = this.opts.element.attr('style'); + if (style !== undefined) { + attrs = style.split(';'); + for (i = 0, l = attrs.length; i < l; i = i + 1) { + attr = attrs[i].replace(/\s/g, ''); + matches = attr.match(/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i); + if (matches !== null && matches.length >= 1) + return matches[1]; + } + } + + if (this.opts.width === "resolve") { + // next check if css('width') can resolve a width that is percent based, this is sometimes possible + // when attached to input type=hidden or elements hidden via css + style = this.opts.element.css('width'); + if (style.indexOf("%") > 0) return style; + + // finally, fallback on the calculated width of the element + return (this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px'); + } + + return null; + } else if ($.isFunction(this.opts.width)) { + return this.opts.width(); + } else { + return this.opts.width; + } + }; + + var width = resolveContainerWidth.call(this); + if (width !== null) { + this.container.css("width", width); + } + } + }); + + SingleSelect2 = clazz(AbstractSelect2, { + + // single + + createContainer: function () { + var container = $(document.createElement("div")).attr({ + "class": "select2-container" + }).html([ + "<a href='javascript:void(0)' class='select2-choice' tabindex='-1'>", + " <span class='select2-chosen'>&nbsp;</span><abbr class='select2-search-choice-close'></abbr>", + " <span class='select2-arrow' role='presentation'><b role='presentation'></b></span>", + "</a>", + "<label for='' class='select2-offscreen'></label>", + "<input class='select2-focusser select2-offscreen' type='text' aria-haspopup='true' role='button' />", + "<div class='select2-drop select2-display-none'>", + " <div class='select2-search'>", + " <label for='' class='select2-offscreen'></label>", + " <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input' role='combobox' aria-expanded='true'", + " aria-autocomplete='list' />", + " </div>", + " <ul class='select2-results' role='listbox'>", + " </ul>", + "</div>"].join("")); + return container; + }, + + // single + enableInterface: function() { + if (this.parent.enableInterface.apply(this, arguments)) { + this.focusser.prop("disabled", !this.isInterfaceEnabled()); + } + }, + + // single + opening: function () { + var el, range, len; + + if (this.opts.minimumResultsForSearch >= 0) { + this.showSearch(true); + } + + this.parent.opening.apply(this, arguments); + + if (this.showSearchInput !== false) { + // IE appends focusser.val() at the end of field :/ so we manually insert it at the beginning using a range + // all other browsers handle this just fine + + this.search.val(this.focusser.val()); + } + this.search.focus(); + // move the cursor to the end after focussing, otherwise it will be at the beginning and + // new text will appear *before* focusser.val() + el = this.search.get(0); + if (el.createTextRange) { + range = el.createTextRange(); + range.collapse(false); + range.select(); + } else if (el.setSelectionRange) { + len = this.search.val().length; + el.setSelectionRange(len, len); + } + + // initializes search's value with nextSearchTerm (if defined by user) + // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter + if(this.search.val() === "") { + if(this.nextSearchTerm != undefined){ + this.search.val(this.nextSearchTerm); + this.search.select(); + } + } + + this.focusser.prop("disabled", true).val(""); + this.updateResults(true); + this.opts.element.trigger($.Event("select2-open")); + }, + + // single + close: function () { + if (!this.opened()) return; + this.parent.close.apply(this, arguments); + + this.focusser.prop("disabled", false); + + if (this.opts.shouldFocusInput(this)) { + this.focusser.focus(); + } + }, + + // single + focus: function () { + if (this.opened()) { + this.close(); + } else { + this.focusser.prop("disabled", false); + if (this.opts.shouldFocusInput(this)) { + this.focusser.focus(); + } + } + }, + + // single + isFocused: function () { + return this.container.hasClass("select2-container-active"); + }, + + // single + cancel: function () { + this.parent.cancel.apply(this, arguments); + this.focusser.prop("disabled", false); + + if (this.opts.shouldFocusInput(this)) { + this.focusser.focus(); + } + }, + + // single + destroy: function() { + $("label[for='" + this.focusser.attr('id') + "']") + .attr('for', this.opts.element.attr("id")); + this.parent.destroy.apply(this, arguments); + }, + + // single + initContainer: function () { + + var selection, + container = this.container, + dropdown = this.dropdown, + idSuffix = nextUid(), + elementLabel; + + if (this.opts.minimumResultsForSearch < 0) { + this.showSearch(false); + } else { + this.showSearch(true); + } + + this.selection = selection = container.find(".select2-choice"); + + this.focusser = container.find(".select2-focusser"); + + // add aria associations + selection.find(".select2-chosen").attr("id", "select2-chosen-"+idSuffix); + this.focusser.attr("aria-labelledby", "select2-chosen-"+idSuffix); + this.results.attr("id", "select2-results-"+idSuffix); + this.search.attr("aria-owns", "select2-results-"+idSuffix); + + // rewrite labels from original element to focusser + this.focusser.attr("id", "s2id_autogen"+idSuffix); + + elementLabel = $("label[for='" + this.opts.element.attr("id") + "']"); + + this.focusser.prev() + .text(elementLabel.text()) + .attr('for', this.focusser.attr('id')); + + // Ensure the original element retains an accessible name + var originalTitle = this.opts.element.attr("title"); + this.opts.element.attr("title", (originalTitle || elementLabel.text())); + + this.focusser.attr("tabindex", this.elementTabIndex); + + // write label for search field using the label from the focusser element + this.search.attr("id", this.focusser.attr('id') + '_search'); + + this.search.prev() + .text($("label[for='" + this.focusser.attr('id') + "']").text()) + .attr('for', this.search.attr('id')); + + this.search.on("keydown", this.bind(function (e) { + if (!this.isInterfaceEnabled()) return; + + if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) { + // prevent the page from scrolling + killEvent(e); + return; + } + + switch (e.which) { + case KEY.UP: + case KEY.DOWN: + this.moveHighlight((e.which === KEY.UP) ? -1 : 1); + killEvent(e); + return; + case KEY.ENTER: + this.selectHighlighted(); + killEvent(e); + return; + case KEY.TAB: + this.selectHighlighted({noFocus: true}); + return; + case KEY.ESC: + this.cancel(e); + killEvent(e); + return; + } + })); + + this.search.on("blur", this.bind(function(e) { + // a workaround for chrome to keep the search field focussed when the scroll bar is used to scroll the dropdown. + // without this the search field loses focus which is annoying + if (document.activeElement === this.body().get(0)) { + window.setTimeout(this.bind(function() { + if (this.opened()) { + this.search.focus(); + } + }), 0); + } + })); + + this.focusser.on("keydown", this.bind(function (e) { + if (!this.isInterfaceEnabled()) return; + + if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) { + return; + } + + if (this.opts.openOnEnter === false && e.which === KEY.ENTER) { + killEvent(e); + return; + } + + if (e.which == KEY.DOWN || e.which == KEY.UP + || (e.which == KEY.ENTER && this.opts.openOnEnter)) { + + if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) return; + + this.open(); + killEvent(e); + return; + } + + if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) { + if (this.opts.allowClear) { + this.clear(); + } + killEvent(e); + return; + } + })); + + + installKeyUpChangeEvent(this.focusser); + this.focusser.on("keyup-change input", this.bind(function(e) { + if (this.opts.minimumResultsForSearch >= 0) { + e.stopPropagation(); + if (this.opened()) return; + this.open(); + } + })); + + selection.on("mousedown touchstart", "abbr", this.bind(function (e) { + if (!this.isInterfaceEnabled()) return; + this.clear(); + killEventImmediately(e); + this.close(); + this.selection.focus(); + })); + + selection.on("mousedown touchstart", this.bind(function (e) { + // Prevent IE from generating a click event on the body + reinsertElement(selection); + + if (!this.container.hasClass("select2-container-active")) { + this.opts.element.trigger($.Event("select2-focus")); + } + + if (this.opened()) { + this.close(); + } else if (this.isInterfaceEnabled()) { + this.open(); + } + + killEvent(e); + })); + + dropdown.on("mousedown touchstart", this.bind(function() { this.search.focus(); })); + + selection.on("focus", this.bind(function(e) { + killEvent(e); + })); + + this.focusser.on("focus", this.bind(function(){ + if (!this.container.hasClass("select2-container-active")) { + this.opts.element.trigger($.Event("select2-focus")); + } + this.container.addClass("select2-container-active"); + })).on("blur", this.bind(function() { + if (!this.opened()) { + this.container.removeClass("select2-container-active"); + this.opts.element.trigger($.Event("select2-blur")); + } + })); + this.search.on("focus", this.bind(function(){ + if (!this.container.hasClass("select2-container-active")) { + this.opts.element.trigger($.Event("select2-focus")); + } + this.container.addClass("select2-container-active"); + })); + + this.initContainerWidth(); + this.opts.element.addClass("select2-offscreen"); + this.setPlaceholder(); + + }, + + // single + clear: function(triggerChange) { + var data=this.selection.data("select2-data"); + if (data) { // guard against queued quick consecutive clicks + var evt = $.Event("select2-clearing"); + this.opts.element.trigger(evt); + if (evt.isDefaultPrevented()) { + return; + } + var placeholderOption = this.getPlaceholderOption(); + this.opts.element.val(placeholderOption ? placeholderOption.val() : ""); + this.selection.find(".select2-chosen").empty(); + this.selection.removeData("select2-data"); + this.setPlaceholder(); + + if (triggerChange !== false){ + this.opts.element.trigger({ type: "select2-removed", val: this.id(data), choice: data }); + this.triggerChange({removed:data}); + } + } + }, + + /** + * Sets selection based on source element's value + */ + // single + initSelection: function () { + var selected; + if (this.isPlaceholderOptionSelected()) { + this.updateSelection(null); + this.close(); + this.setPlaceholder(); + } else { + var self = this; + this.opts.initSelection.call(null, this.opts.element, function(selected){ + if (selected !== undefined && selected !== null) { + self.updateSelection(selected); + self.close(); + self.setPlaceholder(); + self.nextSearchTerm = self.opts.nextSearchTerm(selected, self.search.val()); + } + }); + } + }, + + isPlaceholderOptionSelected: function() { + var placeholderOption; + if (!this.getPlaceholder()) return false; // no placeholder specified so no option should be considered + return ((placeholderOption = this.getPlaceholderOption()) !== undefined && placeholderOption.prop("selected")) + || (this.opts.element.val() === "") + || (this.opts.element.val() === undefined) + || (this.opts.element.val() === null); + }, + + // single + prepareOpts: function () { + var opts = this.parent.prepareOpts.apply(this, arguments), + self=this; + + if (opts.element.get(0).tagName.toLowerCase() === "select") { + // install the selection initializer + opts.initSelection = function (element, callback) { + var selected = element.find("option").filter(function() { return this.selected && !this.disabled }); + // a single select box always has a value, no need to null check 'selected' + callback(self.optionToData(selected)); + }; + } else if ("data" in opts) { + // install default initSelection when applied to hidden input and data is local + opts.initSelection = opts.initSelection || function (element, callback) { + var id = element.val(); + //search in data by id, storing the actual matching item + var match = null; + opts.query({ + matcher: function(term, text, el){ + var is_match = equal(id, opts.id(el)); + if (is_match) { + match = el; + } + return is_match; + }, + callback: !$.isFunction(callback) ? $.noop : function() { + callback(match); + } + }); + }; + } + + return opts; + }, + + // single + getPlaceholder: function() { + // if a placeholder is specified on a single select without a valid placeholder option ignore it + if (this.select) { + if (this.getPlaceholderOption() === undefined) { + return undefined; + } + } + + return this.parent.getPlaceholder.apply(this, arguments); + }, + + // single + setPlaceholder: function () { + var placeholder = this.getPlaceholder(); + + if (this.isPlaceholderOptionSelected() && placeholder !== undefined) { + + // check for a placeholder option if attached to a select + if (this.select && this.getPlaceholderOption() === undefined) return; + + this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(placeholder)); + + this.selection.addClass("select2-default"); + + this.container.removeClass("select2-allowclear"); + } + }, + + // single + postprocessResults: function (data, initial, noHighlightUpdate) { + var selected = 0, self = this, showSearchInput = true; + + // find the selected element in the result list + + this.findHighlightableChoices().each2(function (i, elm) { + if (equal(self.id(elm.data("select2-data")), self.opts.element.val())) { + selected = i; + return false; + } + }); + + // and highlight it + if (noHighlightUpdate !== false) { + if (initial === true && selected >= 0) { + this.highlight(selected); + } else { + this.highlight(0); + } + } + + // hide the search box if this is the first we got the results and there are enough of them for search + + if (initial === true) { + var min = this.opts.minimumResultsForSearch; + if (min >= 0) { + this.showSearch(countResults(data.results) >= min); + } + } + }, + + // single + showSearch: function(showSearchInput) { + if (this.showSearchInput === showSearchInput) return; + + this.showSearchInput = showSearchInput; + + this.dropdown.find(".select2-search").toggleClass("select2-search-hidden", !showSearchInput); + this.dropdown.find(".select2-search").toggleClass("select2-offscreen", !showSearchInput); + //add "select2-with-searchbox" to the container if search box is shown + $(this.dropdown, this.container).toggleClass("select2-with-searchbox", showSearchInput); + }, + + // single + onSelect: function (data, options) { + + if (!this.triggerSelect(data)) { return; } + + var old = this.opts.element.val(), + oldData = this.data(); + + this.opts.element.val(this.id(data)); + this.updateSelection(data); + + this.opts.element.trigger({ type: "select2-selected", val: this.id(data), choice: data }); + + this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val()); + this.close(); + + if ((!options || !options.noFocus) && this.opts.shouldFocusInput(this)) { + this.focusser.focus(); + } + + if (!equal(old, this.id(data))) { + this.triggerChange({ added: data, removed: oldData }); + } + }, + + // single + updateSelection: function (data) { + + var container=this.selection.find(".select2-chosen"), formatted, cssClass; + + this.selection.data("select2-data", data); + + container.empty(); + if (data !== null) { + formatted=this.opts.formatSelection(data, container, this.opts.escapeMarkup); + } + if (formatted !== undefined) { + container.append(formatted); + } + cssClass=this.opts.formatSelectionCssClass(data, container); + if (cssClass !== undefined) { + container.addClass(cssClass); + } + + this.selection.removeClass("select2-default"); + + if (this.opts.allowClear && this.getPlaceholder() !== undefined) { + this.container.addClass("select2-allowclear"); + } + }, + + // single + val: function () { + var val, + triggerChange = false, + data = null, + self = this, + oldData = this.data(); + + if (arguments.length === 0) { + return this.opts.element.val(); + } + + val = arguments[0]; + + if (arguments.length > 1) { + triggerChange = arguments[1]; + } + + if (this.select) { + this.select + .val(val) + .find("option").filter(function() { return this.selected }).each2(function (i, elm) { + data = self.optionToData(elm); + return false; + }); + this.updateSelection(data); + this.setPlaceholder(); + if (triggerChange) { + this.triggerChange({added: data, removed:oldData}); + } + } else { + // val is an id. !val is true for [undefined,null,'',0] - 0 is legal + if (!val && val !== 0) { + this.clear(triggerChange); + return; + } + if (this.opts.initSelection === undefined) { + throw new Error("cannot call val() if initSelection() is not defined"); + } + this.opts.element.val(val); + this.opts.initSelection(this.opts.element, function(data){ + self.opts.element.val(!data ? "" : self.id(data)); + self.updateSelection(data); + self.setPlaceholder(); + if (triggerChange) { + self.triggerChange({added: data, removed:oldData}); + } + }); + } + }, + + // single + clearSearch: function () { + this.search.val(""); + this.focusser.val(""); + }, + + // single + data: function(value) { + var data, + triggerChange = false; + + if (arguments.length === 0) { + data = this.selection.data("select2-data"); + if (data == undefined) data = null; + return data; + } else { + if (arguments.length > 1) { + triggerChange = arguments[1]; + } + if (!value) { + this.clear(triggerChange); + } else { + data = this.data(); + this.opts.element.val(!value ? "" : this.id(value)); + this.updateSelection(value); + if (triggerChange) { + this.triggerChange({added: value, removed:data}); + } + } + } + } + }); + + MultiSelect2 = clazz(AbstractSelect2, { + + // multi + createContainer: function () { + var container = $(document.createElement("div")).attr({ + "class": "select2-container select2-container-multi" + }).html([ + "<ul class='select2-choices'>", + " <li class='select2-search-field'>", + " <label for='' class='select2-offscreen'></label>", + " <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input'>", + " </li>", + "</ul>", + "<div class='select2-drop select2-drop-multi select2-display-none'>", + " <ul class='select2-results'>", + " </ul>", + "</div>"].join("")); + return container; + }, + + // multi + prepareOpts: function () { + var opts = this.parent.prepareOpts.apply(this, arguments), + self=this; + + // TODO validate placeholder is a string if specified + + if (opts.element.get(0).tagName.toLowerCase() === "select") { + // install the selection initializer + opts.initSelection = function (element, callback) { + + var data = []; + + element.find("option").filter(function() { return this.selected && !this.disabled }).each2(function (i, elm) { + data.push(self.optionToData(elm)); + }); + callback(data); + }; + } else if ("data" in opts) { + // install default initSelection when applied to hidden input and data is local + opts.initSelection = opts.initSelection || function (element, callback) { + var ids = splitVal(element.val(), opts.separator); + //search in data by array of ids, storing matching items in a list + var matches = []; + opts.query({ + matcher: function(term, text, el){ + var is_match = $.grep(ids, function(id) { + return equal(id, opts.id(el)); + }).length; + if (is_match) { + matches.push(el); + } + return is_match; + }, + callback: !$.isFunction(callback) ? $.noop : function() { + // reorder matches based on the order they appear in the ids array because right now + // they are in the order in which they appear in data array + var ordered = []; + for (var i = 0; i < ids.length; i++) { + var id = ids[i]; + for (var j = 0; j < matches.length; j++) { + var match = matches[j]; + if (equal(id, opts.id(match))) { + ordered.push(match); + matches.splice(j, 1); + break; + } + } + } + callback(ordered); + } + }); + }; + } + + return opts; + }, + + // multi + selectChoice: function (choice) { + + var selected = this.container.find(".select2-search-choice-focus"); + if (selected.length && choice && choice[0] == selected[0]) { + + } else { + if (selected.length) { + this.opts.element.trigger("choice-deselected", selected); + } + selected.removeClass("select2-search-choice-focus"); + if (choice && choice.length) { + this.close(); + choice.addClass("select2-search-choice-focus"); + this.opts.element.trigger("choice-selected", choice); + } + } + }, + + // multi + destroy: function() { + $("label[for='" + this.search.attr('id') + "']") + .attr('for', this.opts.element.attr("id")); + this.parent.destroy.apply(this, arguments); + }, + + // multi + initContainer: function () { + + var selector = ".select2-choices", selection; + + this.searchContainer = this.container.find(".select2-search-field"); + this.selection = selection = this.container.find(selector); + + var _this = this; + this.selection.on("click", ".select2-search-choice:not(.select2-locked)", function (e) { + //killEvent(e); + _this.search[0].focus(); + _this.selectChoice($(this)); + }); + + // rewrite labels from original element to focusser + this.search.attr("id", "s2id_autogen"+nextUid()); + + this.search.prev() + .text($("label[for='" + this.opts.element.attr("id") + "']").text()) + .attr('for', this.search.attr('id')); + + this.search.on("input paste", this.bind(function() { + if (!this.isInterfaceEnabled()) return; + if (!this.opened()) { + this.open(); + } + })); + + this.search.attr("tabindex", this.elementTabIndex); + + this.keydowns = 0; + this.search.on("keydown", this.bind(function (e) { + if (!this.isInterfaceEnabled()) return; + + ++this.keydowns; + var selected = selection.find(".select2-search-choice-focus"); + var prev = selected.prev(".select2-search-choice:not(.select2-locked)"); + var next = selected.next(".select2-search-choice:not(.select2-locked)"); + var pos = getCursorInfo(this.search); + + if (selected.length && + (e.which == KEY.LEFT || e.which == KEY.RIGHT || e.which == KEY.BACKSPACE || e.which == KEY.DELETE || e.which == KEY.ENTER)) { + var selectedChoice = selected; + if (e.which == KEY.LEFT && prev.length) { + selectedChoice = prev; + } + else if (e.which == KEY.RIGHT) { + selectedChoice = next.length ? next : null; + } + else if (e.which === KEY.BACKSPACE) { + if (this.unselect(selected.first())) { + this.search.width(10); + selectedChoice = prev.length ? prev : next; + } + } else if (e.which == KEY.DELETE) { + if (this.unselect(selected.first())) { + this.search.width(10); + selectedChoice = next.length ? next : null; + } + } else if (e.which == KEY.ENTER) { + selectedChoice = null; + } + + this.selectChoice(selectedChoice); + killEvent(e); + if (!selectedChoice || !selectedChoice.length) { + this.open(); + } + return; + } else if (((e.which === KEY.BACKSPACE && this.keydowns == 1) + || e.which == KEY.LEFT) && (pos.offset == 0 && !pos.length)) { + + this.selectChoice(selection.find(".select2-search-choice:not(.select2-locked)").last()); + killEvent(e); + return; + } else { + this.selectChoice(null); + } + + if (this.opened()) { + switch (e.which) { + case KEY.UP: + case KEY.DOWN: + this.moveHighlight((e.which === KEY.UP) ? -1 : 1); + killEvent(e); + return; + case KEY.ENTER: + this.selectHighlighted(); + killEvent(e); + return; + case KEY.TAB: + this.selectHighlighted({noFocus:true}); + this.close(); + return; + case KEY.ESC: + this.cancel(e); + killEvent(e); + return; + } + } + + if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) + || e.which === KEY.BACKSPACE || e.which === KEY.ESC) { + return; + } + + if (e.which === KEY.ENTER) { + if (this.opts.openOnEnter === false) { + return; + } else if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) { + return; + } + } + + this.open(); + + if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) { + // prevent the page from scrolling + killEvent(e); + } + + if (e.which === KEY.ENTER) { + // prevent form from being submitted + killEvent(e); + } + + })); + + this.search.on("keyup", this.bind(function (e) { + this.keydowns = 0; + this.resizeSearch(); + }) + ); + + this.search.on("blur", this.bind(function(e) { + this.container.removeClass("select2-container-active"); + this.search.removeClass("select2-focused"); + this.selectChoice(null); + if (!this.opened()) this.clearSearch(); + e.stopImmediatePropagation(); + this.opts.element.trigger($.Event("select2-blur")); + })); + + this.container.on("click", selector, this.bind(function (e) { + if (!this.isInterfaceEnabled()) return; + if ($(e.target).closest(".select2-search-choice").length > 0) { + // clicked inside a select2 search choice, do not open + return; + } + this.selectChoice(null); + this.clearPlaceholder(); + if (!this.container.hasClass("select2-container-active")) { + this.opts.element.trigger($.Event("select2-focus")); + } + this.open(); + this.focusSearch(); + e.preventDefault(); + })); + + this.container.on("focus", selector, this.bind(function () { + if (!this.isInterfaceEnabled()) return; + if (!this.container.hasClass("select2-container-active")) { + this.opts.element.trigger($.Event("select2-focus")); + } + this.container.addClass("select2-container-active"); + this.dropdown.addClass("select2-drop-active"); + this.clearPlaceholder(); + })); + + this.initContainerWidth(); + this.opts.element.addClass("select2-offscreen"); + + // set the placeholder if necessary + this.clearSearch(); + }, + + // multi + enableInterface: function() { + if (this.parent.enableInterface.apply(this, arguments)) { + this.search.prop("disabled", !this.isInterfaceEnabled()); + } + }, + + // multi + initSelection: function () { + var data; + if (this.opts.element.val() === "" && this.opts.element.text() === "") { + this.updateSelection([]); + this.close(); + // set the placeholder if necessary + this.clearSearch(); + } + if (this.select || this.opts.element.val() !== "") { + var self = this; + this.opts.initSelection.call(null, this.opts.element, function(data){ + if (data !== undefined && data !== null) { + self.updateSelection(data); + self.close(); + // set the placeholder if necessary + self.clearSearch(); + } + }); + } + }, + + // multi + clearSearch: function () { + var placeholder = this.getPlaceholder(), + maxWidth = this.getMaxSearchWidth(); + + if (placeholder !== undefined && this.getVal().length === 0 && this.search.hasClass("select2-focused") === false) { + this.search.val(placeholder).addClass("select2-default"); + // stretch the search box to full width of the container so as much of the placeholder is visible as possible + // we could call this.resizeSearch(), but we do not because that requires a sizer and we do not want to create one so early because of a firefox bug, see #944 + this.search.width(maxWidth > 0 ? maxWidth : this.container.css("width")); + } else { + this.search.val("").width(10); + } + }, + + // multi + clearPlaceholder: function () { + if (this.search.hasClass("select2-default")) { + this.search.val("").removeClass("select2-default"); + } + }, + + // multi + opening: function () { + this.clearPlaceholder(); // should be done before super so placeholder is not used to search + this.resizeSearch(); + + this.parent.opening.apply(this, arguments); + + this.focusSearch(); + + // initializes search's value with nextSearchTerm (if defined by user) + // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter + if(this.search.val() === "") { + if(this.nextSearchTerm != undefined){ + this.search.val(this.nextSearchTerm); + this.search.select(); + } + } + + this.updateResults(true); + this.search.focus(); + this.opts.element.trigger($.Event("select2-open")); + }, + + // multi + close: function () { + if (!this.opened()) return; + this.parent.close.apply(this, arguments); + }, + + // multi + focus: function () { + this.close(); + this.search.focus(); + }, + + // multi + isFocused: function () { + return this.search.hasClass("select2-focused"); + }, + + // multi + updateSelection: function (data) { + var ids = [], filtered = [], self = this; + + // filter out duplicates + $(data).each(function () { + if (indexOf(self.id(this), ids) < 0) { + ids.push(self.id(this)); + filtered.push(this); + } + }); + data = filtered; + + this.selection.find(".select2-search-choice").remove(); + $(data).each(function () { + self.addSelectedChoice(this); + }); + self.postprocessResults(); + }, + + // multi + tokenize: function() { + var input = this.search.val(); + input = this.opts.tokenizer.call(this, input, this.data(), this.bind(this.onSelect), this.opts); + if (input != null && input != undefined) { + this.search.val(input); + if (input.length > 0) { + this.open(); + } + } + + }, + + // multi + onSelect: function (data, options) { + + if (!this.triggerSelect(data)) { return; } + + this.addSelectedChoice(data); + + this.opts.element.trigger({ type: "selected", val: this.id(data), choice: data }); + + // keep track of the search's value before it gets cleared + this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val()); + + this.clearSearch(); + this.updateResults(); + + if (this.select || !this.opts.closeOnSelect) this.postprocessResults(data, false, this.opts.closeOnSelect===true); + + if (this.opts.closeOnSelect) { + this.close(); + this.search.width(10); + } else { + if (this.countSelectableResults()>0) { + this.search.width(10); + this.resizeSearch(); + if (this.getMaximumSelectionSize() > 0 && this.val().length >= this.getMaximumSelectionSize()) { + // if we reached max selection size repaint the results so choices + // are replaced with the max selection reached message + this.updateResults(true); + } else { + // initializes search's value with nextSearchTerm and update search result + if(this.nextSearchTerm != undefined){ + this.search.val(this.nextSearchTerm); + this.updateResults(); + this.search.select(); + } + } + this.positionDropdown(); + } else { + // if nothing left to select close + this.close(); + this.search.width(10); + } + } + + // since its not possible to select an element that has already been + // added we do not need to check if this is a new element before firing change + this.triggerChange({ added: data }); + + if (!options || !options.noFocus) + this.focusSearch(); + }, + + // multi + cancel: function () { + this.close(); + this.focusSearch(); + }, + + addSelectedChoice: function (data) { + var enableChoice = !data.locked, + enabledItem = $( + "<li class='select2-search-choice'>" + + " <div></div>" + + " <a href='#' class='select2-search-choice-close' tabindex='-1'></a>" + + "</li>"), + disabledItem = $( + "<li class='select2-search-choice select2-locked'>" + + "<div></div>" + + "</li>"); + var choice = enableChoice ? enabledItem : disabledItem, + id = this.id(data), + val = this.getVal(), + formatted, + cssClass; + + formatted=this.opts.formatSelection(data, choice.find("div"), this.opts.escapeMarkup); + if (formatted != undefined) { + choice.find("div").replaceWith("<div>"+formatted+"</div>"); + } + cssClass=this.opts.formatSelectionCssClass(data, choice.find("div")); + if (cssClass != undefined) { + choice.addClass(cssClass); + } + + if(enableChoice){ + choice.find(".select2-search-choice-close") + .on("mousedown", killEvent) + .on("click dblclick", this.bind(function (e) { + if (!this.isInterfaceEnabled()) return; + + this.unselect($(e.target)); + this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"); + killEvent(e); + this.close(); + this.focusSearch(); + })).on("focus", this.bind(function () { + if (!this.isInterfaceEnabled()) return; + this.container.addClass("select2-container-active"); + this.dropdown.addClass("select2-drop-active"); + })); + } + + choice.data("select2-data", data); + choice.insertBefore(this.searchContainer); + + val.push(id); + this.setVal(val); + }, + + // multi + unselect: function (selected) { + var val = this.getVal(), + data, + index; + selected = selected.closest(".select2-search-choice"); + + if (selected.length === 0) { + throw "Invalid argument: " + selected + ". Must be .select2-search-choice"; + } + + data = selected.data("select2-data"); + + if (!data) { + // prevent a race condition when the 'x' is clicked really fast repeatedly the event can be queued + // and invoked on an element already removed + return; + } + + var evt = $.Event("select2-removing"); + evt.val = this.id(data); + evt.choice = data; + this.opts.element.trigger(evt); + + if (evt.isDefaultPrevented()) { + return false; + } + + while((index = indexOf(this.id(data), val)) >= 0) { + val.splice(index, 1); + this.setVal(val); + if (this.select) this.postprocessResults(); + } + + selected.remove(); + + this.opts.element.trigger({ type: "select2-removed", val: this.id(data), choice: data }); + this.triggerChange({ removed: data }); + + return true; + }, + + // multi + postprocessResults: function (data, initial, noHighlightUpdate) { + var val = this.getVal(), + choices = this.results.find(".select2-result"), + compound = this.results.find(".select2-result-with-children"), + self = this; + + choices.each2(function (i, choice) { + var id = self.id(choice.data("select2-data")); + if (indexOf(id, val) >= 0) { + choice.addClass("select2-selected"); + // mark all children of the selected parent as selected + choice.find(".select2-result-selectable").addClass("select2-selected"); + } + }); + + compound.each2(function(i, choice) { + // hide an optgroup if it doesn't have any selectable children + if (!choice.is('.select2-result-selectable') + && choice.find(".select2-result-selectable:not(.select2-selected)").length === 0) { + choice.addClass("select2-selected"); + } + }); + + if (this.highlight() == -1 && noHighlightUpdate !== false){ + self.highlight(0); + } + + //If all results are chosen render formatNoMatches + if(!this.opts.createSearchChoice && !choices.filter('.select2-result:not(.select2-selected)').length > 0){ + if(!data || data && !data.more && this.results.find(".select2-no-results").length === 0) { + if (checkFormatter(self.opts.formatNoMatches, "formatNoMatches")) { + this.results.append("<li class='select2-no-results'>" + evaluate(self.opts.formatNoMatches, self.search.val()) + "</li>"); + } + } + } + + }, + + // multi + getMaxSearchWidth: function() { + return this.selection.width() - getSideBorderPadding(this.search); + }, + + // multi + resizeSearch: function () { + var minimumWidth, left, maxWidth, containerLeft, searchWidth, + sideBorderPadding = getSideBorderPadding(this.search); + + minimumWidth = measureTextWidth(this.search) + 10; + + left = this.search.offset().left; + + maxWidth = this.selection.width(); + containerLeft = this.selection.offset().left; + + searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding; + + if (searchWidth < minimumWidth) { + searchWidth = maxWidth - sideBorderPadding; + } + + if (searchWidth < 40) { + searchWidth = maxWidth - sideBorderPadding; + } + + if (searchWidth <= 0) { + searchWidth = minimumWidth; + } + + this.search.width(Math.floor(searchWidth)); + }, + + // multi + getVal: function () { + var val; + if (this.select) { + val = this.select.val(); + return val === null ? [] : val; + } else { + val = this.opts.element.val(); + return splitVal(val, this.opts.separator); + } + }, + + // multi + setVal: function (val) { + var unique; + if (this.select) { + this.select.val(val); + } else { + unique = []; + // filter out duplicates + $(val).each(function () { + if (indexOf(this, unique) < 0) unique.push(this); + }); + this.opts.element.val(unique.length === 0 ? "" : unique.join(this.opts.separator)); + } + }, + + // multi + buildChangeDetails: function (old, current) { + var current = current.slice(0), + old = old.slice(0); + + // remove intersection from each array + for (var i = 0; i < current.length; i++) { + for (var j = 0; j < old.length; j++) { + if (equal(this.opts.id(current[i]), this.opts.id(old[j]))) { + current.splice(i, 1); + if(i>0){ + i--; + } + old.splice(j, 1); + j--; + } + } + } + + return {added: current, removed: old}; + }, + + + // multi + val: function (val, triggerChange) { + var oldData, self=this; + + if (arguments.length === 0) { + return this.getVal(); + } + + oldData=this.data(); + if (!oldData.length) oldData=[]; + + // val is an id. !val is true for [undefined,null,'',0] - 0 is legal + if (!val && val !== 0) { + this.opts.element.val(""); + this.updateSelection([]); + this.clearSearch(); + if (triggerChange) { + this.triggerChange({added: this.data(), removed: oldData}); + } + return; + } + + // val is a list of ids + this.setVal(val); + + if (this.select) { + this.opts.initSelection(this.select, this.bind(this.updateSelection)); + if (triggerChange) { + this.triggerChange(this.buildChangeDetails(oldData, this.data())); + } + } else { + if (this.opts.initSelection === undefined) { + throw new Error("val() cannot be called if initSelection() is not defined"); + } + + this.opts.initSelection(this.opts.element, function(data){ + var ids=$.map(data, self.id); + self.setVal(ids); + self.updateSelection(data); + self.clearSearch(); + if (triggerChange) { + self.triggerChange(self.buildChangeDetails(oldData, self.data())); + } + }); + } + this.clearSearch(); + }, + + // multi + onSortStart: function() { + if (this.select) { + throw new Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead."); + } + + // collapse search field into 0 width so its container can be collapsed as well + this.search.width(0); + // hide the container + this.searchContainer.hide(); + }, + + // multi + onSortEnd:function() { + + var val=[], self=this; + + // show search and move it to the end of the list + this.searchContainer.show(); + // make sure the search container is the last item in the list + this.searchContainer.appendTo(this.searchContainer.parent()); + // since we collapsed the width in dragStarted, we resize it here + this.resizeSearch(); + + // update selection + this.selection.find(".select2-search-choice").each(function() { + val.push(self.opts.id($(this).data("select2-data"))); + }); + this.setVal(val); + this.triggerChange(); + }, + + // multi + data: function(values, triggerChange) { + var self=this, ids, old; + if (arguments.length === 0) { + return this.selection + .children(".select2-search-choice") + .map(function() { return $(this).data("select2-data"); }) + .get(); + } else { + old = this.data(); + if (!values) { values = []; } + ids = $.map(values, function(e) { return self.opts.id(e); }); + this.setVal(ids); + this.updateSelection(values); + this.clearSearch(); + if (triggerChange) { + this.triggerChange(this.buildChangeDetails(old, this.data())); + } + } + } + }); + + $.fn.select2 = function () { + + var args = Array.prototype.slice.call(arguments, 0), + opts, + select2, + method, value, multiple, + allowedMethods = ["val", "destroy", "opened", "open", "close", "focus", "isFocused", "container", "dropdown", "onSortStart", "onSortEnd", "enable", "disable", "readonly", "positionDropdown", "data", "search"], + valueMethods = ["opened", "isFocused", "container", "dropdown"], + propertyMethods = ["val", "data"], + methodsMap = { search: "externalSearch" }; + + this.each(function () { + if (args.length === 0 || typeof(args[0]) === "object") { + opts = args.length === 0 ? {} : $.extend({}, args[0]); + opts.element = $(this); + + if (opts.element.get(0).tagName.toLowerCase() === "select") { + multiple = opts.element.prop("multiple"); + } else { + multiple = opts.multiple || false; + if ("tags" in opts) {opts.multiple = multiple = true;} + } + + select2 = multiple ? new window.Select2["class"].multi() : new window.Select2["class"].single(); + select2.init(opts); + } else if (typeof(args[0]) === "string") { + + if (indexOf(args[0], allowedMethods) < 0) { + throw "Unknown method: " + args[0]; + } + + value = undefined; + select2 = $(this).data("select2"); + if (select2 === undefined) return; + + method=args[0]; + + if (method === "container") { + value = select2.container; + } else if (method === "dropdown") { + value = select2.dropdown; + } else { + if (methodsMap[method]) method = methodsMap[method]; + + value = select2[method].apply(select2, args.slice(1)); + } + if (indexOf(args[0], valueMethods) >= 0 + || (indexOf(args[0], propertyMethods) && args.length == 1)) { + return false; // abort the iteration, ready to return first matched value + } + } else { + throw "Invalid arguments to select2 plugin: " + args; + } + }); + return (value === undefined) ? this : value; + }; + + // plugin defaults, accessible to users + $.fn.select2.defaults = { + width: "copy", + loadMorePadding: 0, + closeOnSelect: true, + openOnEnter: true, + containerCss: {}, + dropdownCss: {}, + containerCssClass: "", + dropdownCssClass: "", + formatResult: function(result, container, query, escapeMarkup) { + var markup=[]; + markMatch(result.text, query.term, markup, escapeMarkup); + return markup.join(""); + }, + formatSelection: function (data, container, escapeMarkup) { + return data ? escapeMarkup(data.text) : undefined; + }, + sortResults: function (results, container, query) { + return results; + }, + formatResultCssClass: function(data) {return data.css;}, + formatSelectionCssClass: function(data, container) {return undefined;}, + formatMatches: function (matches) { return matches + " results are available, use up and down arrow keys to navigate."; }, + formatNoMatches: function () { return "No matches found"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " or more character" + (n == 1? "" : "s"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1? "" : "s"); }, + formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Loading more results…"; }, + formatSearching: function () { return "Searching…"; }, + minimumResultsForSearch: 0, + minimumInputLength: 0, + maximumInputLength: null, + maximumSelectionSize: 0, + id: function (e) { return e == undefined ? null : e.id; }, + matcher: function(term, text) { + return stripDiacritics(''+text).toUpperCase().indexOf(stripDiacritics(''+term).toUpperCase()) >= 0; + }, + separator: ",", + tokenSeparators: [], + tokenizer: defaultTokenizer, + escapeMarkup: defaultEscapeMarkup, + blurOnChange: false, + selectOnBlur: false, + adaptContainerCssClass: function(c) { return c; }, + adaptDropdownCssClass: function(c) { return null; }, + nextSearchTerm: function(selectedObject, currentSearchTerm) { return undefined; }, + searchInputPlaceholder: '', + createSearchChoicePosition: 'top', + shouldFocusInput: function (instance) { + // Never focus the input if search is disabled + if (instance.opts.minimumResultsForSearch < 0) { + return false; + } + + return true; + } + }; + + $.fn.select2.ajaxDefaults = { + transport: $.ajax, + params: { + type: "GET", + cache: false, + dataType: "json" + } + }; + + // exports + window.Select2 = { + query: { + ajax: ajax, + local: local, + tags: tags + }, util: { + debounce: debounce, + markMatch: markMatch, + escapeMarkup: defaultEscapeMarkup, + stripDiacritics: stripDiacritics + }, "class": { + "abstract": AbstractSelect2, + "single": SingleSelect2, + "multi": MultiSelect2 + } + }; + +}(jQuery)); diff --git a/src/static/jquery/select2-3.4.6/select2.min.js b/src/static/jquery/select2-3.4.6/select2.min.js new file mode 100755 index 0000000..335c85e --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2.min.js @@ -0,0 +1,22 @@ +/* +Copyright 2014 Igor Vaynberg + +Version: 3.4.6 Timestamp: Sat Mar 22 22:30:15 EDT 2014 + +This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU +General Public License version 2 (the "GPL License"). You may choose either license to govern your +use of this software only upon the condition that you accept all of the terms of either the Apache +License or the GPL License. + +You may obtain a copy of the Apache License and the GPL License at: + +http://www.apache.org/licenses/LICENSE-2.0 +http://www.gnu.org/licenses/gpl-2.0.html + +Unless required by applicable law or agreed to in writing, software distributed under the Apache License +or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +either express or implied. See the Apache License and the GPL License for the specific language governing +permissions and limitations under the Apache License and the GPL License. +*/ +!function(a){"undefined"==typeof a.fn.each2&&a.extend(a.fn,{each2:function(b){for(var c=a([0]),d=-1,e=this.length;++d<e&&(c.context=c[0]=this[d])&&b.call(c[0],d,c)!==!1;);return this}})}(jQuery),function(a,b){"use strict";function n(b){var c=a(document.createTextNode(""));b.before(c),c.before(b),c.remove()}function o(a){var b,c,d,e;if(!a||a.length<1)return a;for(b="",c=0,d=a.length;d>c;c++)e=a.charAt(c),b+=m[e]||e;return b}function p(a,b){for(var c=0,d=b.length;d>c;c+=1)if(r(a,b[c]))return c;return-1}function q(){var b=a(l);b.appendTo("body");var c={width:b.width()-b[0].clientWidth,height:b.height()-b[0].clientHeight};return b.remove(),c}function r(a,c){return a===c?!0:a===b||c===b?!1:null===a||null===c?!1:a.constructor===String?a+""==c+"":c.constructor===String?c+""==a+"":!1}function s(b,c){var d,e,f;if(null===b||b.length<1)return[];for(d=b.split(c),e=0,f=d.length;f>e;e+=1)d[e]=a.trim(d[e]);return d}function t(a){return a.outerWidth(!1)-a.width()}function u(c){var d="keyup-change-value";c.on("keydown",function(){a.data(c,d)===b&&a.data(c,d,c.val())}),c.on("keyup",function(){var e=a.data(c,d);e!==b&&c.val()!==e&&(a.removeData(c,d),c.trigger("keyup-change"))})}function v(c){c.on("mousemove",function(c){var d=i;(d===b||d.x!==c.pageX||d.y!==c.pageY)&&a(c.target).trigger("mousemove-filtered",c)})}function w(a,c,d){d=d||b;var e;return function(){var b=arguments;window.clearTimeout(e),e=window.setTimeout(function(){c.apply(d,b)},a)}}function x(a){var c,b=!1;return function(){return b===!1&&(c=a(),b=!0),c}}function y(a,b){var c=w(a,function(a){b.trigger("scroll-debounced",a)});b.on("scroll",function(a){p(a.target,b.get())>=0&&c(a)})}function z(a){a[0]!==document.activeElement&&window.setTimeout(function(){var d,b=a[0],c=a.val().length;a.focus();var e=b.offsetWidth>0||b.offsetHeight>0;e&&b===document.activeElement&&(b.setSelectionRange?b.setSelectionRange(c,c):b.createTextRange&&(d=b.createTextRange(),d.collapse(!1),d.select()))},0)}function A(b){b=a(b)[0];var c=0,d=0;if("selectionStart"in b)c=b.selectionStart,d=b.selectionEnd-c;else if("selection"in document){b.focus();var e=document.selection.createRange();d=document.selection.createRange().text.length,e.moveStart("character",-b.value.length),c=e.text.length-d}return{offset:c,length:d}}function B(a){a.preventDefault(),a.stopPropagation()}function C(a){a.preventDefault(),a.stopImmediatePropagation()}function D(b){if(!h){var c=b[0].currentStyle||window.getComputedStyle(b[0],null);h=a(document.createElement("div")).css({position:"absolute",left:"-10000px",top:"-10000px",display:"none",fontSize:c.fontSize,fontFamily:c.fontFamily,fontStyle:c.fontStyle,fontWeight:c.fontWeight,letterSpacing:c.letterSpacing,textTransform:c.textTransform,whiteSpace:"nowrap"}),h.attr("class","select2-sizer"),a("body").append(h)}return h.text(b.val()),h.width()}function E(b,c,d){var e,g,f=[];e=b.attr("class"),e&&(e=""+e,a(e.split(" ")).each2(function(){0===this.indexOf("select2-")&&f.push(this)})),e=c.attr("class"),e&&(e=""+e,a(e.split(" ")).each2(function(){0!==this.indexOf("select2-")&&(g=d(this),g&&f.push(g))})),b.attr("class",f.join(" "))}function F(a,b,c,d){var e=o(a.toUpperCase()).indexOf(o(b.toUpperCase())),f=b.length;return 0>e?(c.push(d(a)),void 0):(c.push(d(a.substring(0,e))),c.push("<span class='select2-match'>"),c.push(d(a.substring(e,e+f))),c.push("</span>"),c.push(d(a.substring(e+f,a.length))),void 0)}function G(a){var b={"\\":"&#92;","&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#47;"};return String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})}function H(c){var d,e=null,f=c.quietMillis||100,g=c.url,h=this;return function(i){window.clearTimeout(d),d=window.setTimeout(function(){var d=c.data,f=g,j=c.transport||a.fn.select2.ajaxDefaults.transport,k={type:c.type||"GET",cache:c.cache||!1,jsonpCallback:c.jsonpCallback||b,dataType:c.dataType||"json"},l=a.extend({},a.fn.select2.ajaxDefaults.params,k);d=d?d.call(h,i.term,i.page,i.context):null,f="function"==typeof f?f.call(h,i.term,i.page,i.context):f,e&&"function"==typeof e.abort&&e.abort(),c.params&&(a.isFunction(c.params)?a.extend(l,c.params.call(h)):a.extend(l,c.params)),a.extend(l,{url:f,dataType:c.dataType,data:d,success:function(a){var b=c.results(a,i.page);i.callback(b)}}),e=j.call(h,l)},f)}}function I(b){var d,e,c=b,f=function(a){return""+a.text};a.isArray(c)&&(e=c,c={results:e}),a.isFunction(c)===!1&&(e=c,c=function(){return e});var g=c();return g.text&&(f=g.text,a.isFunction(f)||(d=g.text,f=function(a){return a[d]})),function(b){var g,d=b.term,e={results:[]};return""===d?(b.callback(c()),void 0):(g=function(c,e){var h,i;if(c=c[0],c.children){h={};for(i in c)c.hasOwnProperty(i)&&(h[i]=c[i]);h.children=[],a(c.children).each2(function(a,b){g(b,h.children)}),(h.children.length||b.matcher(d,f(h),c))&&e.push(h)}else b.matcher(d,f(c),c)&&e.push(c)},a(c().results).each2(function(a,b){g(b,e.results)}),b.callback(e),void 0)}}function J(c){var d=a.isFunction(c);return function(e){var f=e.term,g={results:[]};a(d?c():c).each(function(){var a=this.text!==b,c=a?this.text:this;(""===f||e.matcher(f,c))&&g.results.push(a?this:{id:this,text:this})}),e.callback(g)}}function K(b,c){if(a.isFunction(b))return!0;if(!b)return!1;if("string"==typeof b)return!0;throw new Error(c+" must be a string, function, or falsy value")}function L(b){if(a.isFunction(b)){var c=Array.prototype.slice.call(arguments,1);return b.apply(null,c)}return b}function M(b){var c=0;return a.each(b,function(a,b){b.children?c+=M(b.children):c++}),c}function N(a,c,d,e){var h,i,j,k,l,f=a,g=!1;if(!e.createSearchChoice||!e.tokenSeparators||e.tokenSeparators.length<1)return b;for(;;){for(i=-1,j=0,k=e.tokenSeparators.length;k>j&&(l=e.tokenSeparators[j],i=a.indexOf(l),!(i>=0));j++);if(0>i)break;if(h=a.substring(0,i),a=a.substring(i+l.length),h.length>0&&(h=e.createSearchChoice.call(this,h,c),h!==b&&null!==h&&e.id(h)!==b&&null!==e.id(h))){for(g=!1,j=0,k=c.length;k>j;j++)if(r(e.id(h),e.id(c[j]))){g=!0;break}g||d(h)}}return f!==a?a:void 0}function O(b,c){var d=function(){};return d.prototype=new b,d.prototype.constructor=d,d.prototype.parent=b.prototype,d.prototype=a.extend(d.prototype,c),d}if(window.Select2===b){var c,d,e,f,g,h,j,k,i={x:0,y:0},c={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,isArrow:function(a){switch(a=a.which?a.which:a){case c.LEFT:case c.RIGHT:case c.UP:case c.DOWN:return!0}return!1},isControl:function(a){var b=a.which;switch(b){case c.SHIFT:case c.CTRL:case c.ALT:return!0}return a.metaKey?!0:!1},isFunctionKey:function(a){return a=a.which?a.which:a,a>=112&&123>=a}},l="<div class='select2-measure-scrollbar'></div>",m={"\u24b6":"A","\uff21":"A","\xc0":"A","\xc1":"A","\xc2":"A","\u1ea6":"A","\u1ea4":"A","\u1eaa":"A","\u1ea8":"A","\xc3":"A","\u0100":"A","\u0102":"A","\u1eb0":"A","\u1eae":"A","\u1eb4":"A","\u1eb2":"A","\u0226":"A","\u01e0":"A","\xc4":"A","\u01de":"A","\u1ea2":"A","\xc5":"A","\u01fa":"A","\u01cd":"A","\u0200":"A","\u0202":"A","\u1ea0":"A","\u1eac":"A","\u1eb6":"A","\u1e00":"A","\u0104":"A","\u023a":"A","\u2c6f":"A","\ua732":"AA","\xc6":"AE","\u01fc":"AE","\u01e2":"AE","\ua734":"AO","\ua736":"AU","\ua738":"AV","\ua73a":"AV","\ua73c":"AY","\u24b7":"B","\uff22":"B","\u1e02":"B","\u1e04":"B","\u1e06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24b8":"C","\uff23":"C","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\xc7":"C","\u1e08":"C","\u0187":"C","\u023b":"C","\ua73e":"C","\u24b9":"D","\uff24":"D","\u1e0a":"D","\u010e":"D","\u1e0c":"D","\u1e10":"D","\u1e12":"D","\u1e0e":"D","\u0110":"D","\u018b":"D","\u018a":"D","\u0189":"D","\ua779":"D","\u01f1":"DZ","\u01c4":"DZ","\u01f2":"Dz","\u01c5":"Dz","\u24ba":"E","\uff25":"E","\xc8":"E","\xc9":"E","\xca":"E","\u1ec0":"E","\u1ebe":"E","\u1ec4":"E","\u1ec2":"E","\u1ebc":"E","\u0112":"E","\u1e14":"E","\u1e16":"E","\u0114":"E","\u0116":"E","\xcb":"E","\u1eba":"E","\u011a":"E","\u0204":"E","\u0206":"E","\u1eb8":"E","\u1ec6":"E","\u0228":"E","\u1e1c":"E","\u0118":"E","\u1e18":"E","\u1e1a":"E","\u0190":"E","\u018e":"E","\u24bb":"F","\uff26":"F","\u1e1e":"F","\u0191":"F","\ua77b":"F","\u24bc":"G","\uff27":"G","\u01f4":"G","\u011c":"G","\u1e20":"G","\u011e":"G","\u0120":"G","\u01e6":"G","\u0122":"G","\u01e4":"G","\u0193":"G","\ua7a0":"G","\ua77d":"G","\ua77e":"G","\u24bd":"H","\uff28":"H","\u0124":"H","\u1e22":"H","\u1e26":"H","\u021e":"H","\u1e24":"H","\u1e28":"H","\u1e2a":"H","\u0126":"H","\u2c67":"H","\u2c75":"H","\ua78d":"H","\u24be":"I","\uff29":"I","\xcc":"I","\xcd":"I","\xce":"I","\u0128":"I","\u012a":"I","\u012c":"I","\u0130":"I","\xcf":"I","\u1e2e":"I","\u1ec8":"I","\u01cf":"I","\u0208":"I","\u020a":"I","\u1eca":"I","\u012e":"I","\u1e2c":"I","\u0197":"I","\u24bf":"J","\uff2a":"J","\u0134":"J","\u0248":"J","\u24c0":"K","\uff2b":"K","\u1e30":"K","\u01e8":"K","\u1e32":"K","\u0136":"K","\u1e34":"K","\u0198":"K","\u2c69":"K","\ua740":"K","\ua742":"K","\ua744":"K","\ua7a2":"K","\u24c1":"L","\uff2c":"L","\u013f":"L","\u0139":"L","\u013d":"L","\u1e36":"L","\u1e38":"L","\u013b":"L","\u1e3c":"L","\u1e3a":"L","\u0141":"L","\u023d":"L","\u2c62":"L","\u2c60":"L","\ua748":"L","\ua746":"L","\ua780":"L","\u01c7":"LJ","\u01c8":"Lj","\u24c2":"M","\uff2d":"M","\u1e3e":"M","\u1e40":"M","\u1e42":"M","\u2c6e":"M","\u019c":"M","\u24c3":"N","\uff2e":"N","\u01f8":"N","\u0143":"N","\xd1":"N","\u1e44":"N","\u0147":"N","\u1e46":"N","\u0145":"N","\u1e4a":"N","\u1e48":"N","\u0220":"N","\u019d":"N","\ua790":"N","\ua7a4":"N","\u01ca":"NJ","\u01cb":"Nj","\u24c4":"O","\uff2f":"O","\xd2":"O","\xd3":"O","\xd4":"O","\u1ed2":"O","\u1ed0":"O","\u1ed6":"O","\u1ed4":"O","\xd5":"O","\u1e4c":"O","\u022c":"O","\u1e4e":"O","\u014c":"O","\u1e50":"O","\u1e52":"O","\u014e":"O","\u022e":"O","\u0230":"O","\xd6":"O","\u022a":"O","\u1ece":"O","\u0150":"O","\u01d1":"O","\u020c":"O","\u020e":"O","\u01a0":"O","\u1edc":"O","\u1eda":"O","\u1ee0":"O","\u1ede":"O","\u1ee2":"O","\u1ecc":"O","\u1ed8":"O","\u01ea":"O","\u01ec":"O","\xd8":"O","\u01fe":"O","\u0186":"O","\u019f":"O","\ua74a":"O","\ua74c":"O","\u01a2":"OI","\ua74e":"OO","\u0222":"OU","\u24c5":"P","\uff30":"P","\u1e54":"P","\u1e56":"P","\u01a4":"P","\u2c63":"P","\ua750":"P","\ua752":"P","\ua754":"P","\u24c6":"Q","\uff31":"Q","\ua756":"Q","\ua758":"Q","\u024a":"Q","\u24c7":"R","\uff32":"R","\u0154":"R","\u1e58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1e5a":"R","\u1e5c":"R","\u0156":"R","\u1e5e":"R","\u024c":"R","\u2c64":"R","\ua75a":"R","\ua7a6":"R","\ua782":"R","\u24c8":"S","\uff33":"S","\u1e9e":"S","\u015a":"S","\u1e64":"S","\u015c":"S","\u1e60":"S","\u0160":"S","\u1e66":"S","\u1e62":"S","\u1e68":"S","\u0218":"S","\u015e":"S","\u2c7e":"S","\ua7a8":"S","\ua784":"S","\u24c9":"T","\uff34":"T","\u1e6a":"T","\u0164":"T","\u1e6c":"T","\u021a":"T","\u0162":"T","\u1e70":"T","\u1e6e":"T","\u0166":"T","\u01ac":"T","\u01ae":"T","\u023e":"T","\ua786":"T","\ua728":"TZ","\u24ca":"U","\uff35":"U","\xd9":"U","\xda":"U","\xdb":"U","\u0168":"U","\u1e78":"U","\u016a":"U","\u1e7a":"U","\u016c":"U","\xdc":"U","\u01db":"U","\u01d7":"U","\u01d5":"U","\u01d9":"U","\u1ee6":"U","\u016e":"U","\u0170":"U","\u01d3":"U","\u0214":"U","\u0216":"U","\u01af":"U","\u1eea":"U","\u1ee8":"U","\u1eee":"U","\u1eec":"U","\u1ef0":"U","\u1ee4":"U","\u1e72":"U","\u0172":"U","\u1e76":"U","\u1e74":"U","\u0244":"U","\u24cb":"V","\uff36":"V","\u1e7c":"V","\u1e7e":"V","\u01b2":"V","\ua75e":"V","\u0245":"V","\ua760":"VY","\u24cc":"W","\uff37":"W","\u1e80":"W","\u1e82":"W","\u0174":"W","\u1e86":"W","\u1e84":"W","\u1e88":"W","\u2c72":"W","\u24cd":"X","\uff38":"X","\u1e8a":"X","\u1e8c":"X","\u24ce":"Y","\uff39":"Y","\u1ef2":"Y","\xdd":"Y","\u0176":"Y","\u1ef8":"Y","\u0232":"Y","\u1e8e":"Y","\u0178":"Y","\u1ef6":"Y","\u1ef4":"Y","\u01b3":"Y","\u024e":"Y","\u1efe":"Y","\u24cf":"Z","\uff3a":"Z","\u0179":"Z","\u1e90":"Z","\u017b":"Z","\u017d":"Z","\u1e92":"Z","\u1e94":"Z","\u01b5":"Z","\u0224":"Z","\u2c7f":"Z","\u2c6b":"Z","\ua762":"Z","\u24d0":"a","\uff41":"a","\u1e9a":"a","\xe0":"a","\xe1":"a","\xe2":"a","\u1ea7":"a","\u1ea5":"a","\u1eab":"a","\u1ea9":"a","\xe3":"a","\u0101":"a","\u0103":"a","\u1eb1":"a","\u1eaf":"a","\u1eb5":"a","\u1eb3":"a","\u0227":"a","\u01e1":"a","\xe4":"a","\u01df":"a","\u1ea3":"a","\xe5":"a","\u01fb":"a","\u01ce":"a","\u0201":"a","\u0203":"a","\u1ea1":"a","\u1ead":"a","\u1eb7":"a","\u1e01":"a","\u0105":"a","\u2c65":"a","\u0250":"a","\ua733":"aa","\xe6":"ae","\u01fd":"ae","\u01e3":"ae","\ua735":"ao","\ua737":"au","\ua739":"av","\ua73b":"av","\ua73d":"ay","\u24d1":"b","\uff42":"b","\u1e03":"b","\u1e05":"b","\u1e07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24d2":"c","\uff43":"c","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\xe7":"c","\u1e09":"c","\u0188":"c","\u023c":"c","\ua73f":"c","\u2184":"c","\u24d3":"d","\uff44":"d","\u1e0b":"d","\u010f":"d","\u1e0d":"d","\u1e11":"d","\u1e13":"d","\u1e0f":"d","\u0111":"d","\u018c":"d","\u0256":"d","\u0257":"d","\ua77a":"d","\u01f3":"dz","\u01c6":"dz","\u24d4":"e","\uff45":"e","\xe8":"e","\xe9":"e","\xea":"e","\u1ec1":"e","\u1ebf":"e","\u1ec5":"e","\u1ec3":"e","\u1ebd":"e","\u0113":"e","\u1e15":"e","\u1e17":"e","\u0115":"e","\u0117":"e","\xeb":"e","\u1ebb":"e","\u011b":"e","\u0205":"e","\u0207":"e","\u1eb9":"e","\u1ec7":"e","\u0229":"e","\u1e1d":"e","\u0119":"e","\u1e19":"e","\u1e1b":"e","\u0247":"e","\u025b":"e","\u01dd":"e","\u24d5":"f","\uff46":"f","\u1e1f":"f","\u0192":"f","\ua77c":"f","\u24d6":"g","\uff47":"g","\u01f5":"g","\u011d":"g","\u1e21":"g","\u011f":"g","\u0121":"g","\u01e7":"g","\u0123":"g","\u01e5":"g","\u0260":"g","\ua7a1":"g","\u1d79":"g","\ua77f":"g","\u24d7":"h","\uff48":"h","\u0125":"h","\u1e23":"h","\u1e27":"h","\u021f":"h","\u1e25":"h","\u1e29":"h","\u1e2b":"h","\u1e96":"h","\u0127":"h","\u2c68":"h","\u2c76":"h","\u0265":"h","\u0195":"hv","\u24d8":"i","\uff49":"i","\xec":"i","\xed":"i","\xee":"i","\u0129":"i","\u012b":"i","\u012d":"i","\xef":"i","\u1e2f":"i","\u1ec9":"i","\u01d0":"i","\u0209":"i","\u020b":"i","\u1ecb":"i","\u012f":"i","\u1e2d":"i","\u0268":"i","\u0131":"i","\u24d9":"j","\uff4a":"j","\u0135":"j","\u01f0":"j","\u0249":"j","\u24da":"k","\uff4b":"k","\u1e31":"k","\u01e9":"k","\u1e33":"k","\u0137":"k","\u1e35":"k","\u0199":"k","\u2c6a":"k","\ua741":"k","\ua743":"k","\ua745":"k","\ua7a3":"k","\u24db":"l","\uff4c":"l","\u0140":"l","\u013a":"l","\u013e":"l","\u1e37":"l","\u1e39":"l","\u013c":"l","\u1e3d":"l","\u1e3b":"l","\u017f":"l","\u0142":"l","\u019a":"l","\u026b":"l","\u2c61":"l","\ua749":"l","\ua781":"l","\ua747":"l","\u01c9":"lj","\u24dc":"m","\uff4d":"m","\u1e3f":"m","\u1e41":"m","\u1e43":"m","\u0271":"m","\u026f":"m","\u24dd":"n","\uff4e":"n","\u01f9":"n","\u0144":"n","\xf1":"n","\u1e45":"n","\u0148":"n","\u1e47":"n","\u0146":"n","\u1e4b":"n","\u1e49":"n","\u019e":"n","\u0272":"n","\u0149":"n","\ua791":"n","\ua7a5":"n","\u01cc":"nj","\u24de":"o","\uff4f":"o","\xf2":"o","\xf3":"o","\xf4":"o","\u1ed3":"o","\u1ed1":"o","\u1ed7":"o","\u1ed5":"o","\xf5":"o","\u1e4d":"o","\u022d":"o","\u1e4f":"o","\u014d":"o","\u1e51":"o","\u1e53":"o","\u014f":"o","\u022f":"o","\u0231":"o","\xf6":"o","\u022b":"o","\u1ecf":"o","\u0151":"o","\u01d2":"o","\u020d":"o","\u020f":"o","\u01a1":"o","\u1edd":"o","\u1edb":"o","\u1ee1":"o","\u1edf":"o","\u1ee3":"o","\u1ecd":"o","\u1ed9":"o","\u01eb":"o","\u01ed":"o","\xf8":"o","\u01ff":"o","\u0254":"o","\ua74b":"o","\ua74d":"o","\u0275":"o","\u01a3":"oi","\u0223":"ou","\ua74f":"oo","\u24df":"p","\uff50":"p","\u1e55":"p","\u1e57":"p","\u01a5":"p","\u1d7d":"p","\ua751":"p","\ua753":"p","\ua755":"p","\u24e0":"q","\uff51":"q","\u024b":"q","\ua757":"q","\ua759":"q","\u24e1":"r","\uff52":"r","\u0155":"r","\u1e59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1e5b":"r","\u1e5d":"r","\u0157":"r","\u1e5f":"r","\u024d":"r","\u027d":"r","\ua75b":"r","\ua7a7":"r","\ua783":"r","\u24e2":"s","\uff53":"s","\xdf":"s","\u015b":"s","\u1e65":"s","\u015d":"s","\u1e61":"s","\u0161":"s","\u1e67":"s","\u1e63":"s","\u1e69":"s","\u0219":"s","\u015f":"s","\u023f":"s","\ua7a9":"s","\ua785":"s","\u1e9b":"s","\u24e3":"t","\uff54":"t","\u1e6b":"t","\u1e97":"t","\u0165":"t","\u1e6d":"t","\u021b":"t","\u0163":"t","\u1e71":"t","\u1e6f":"t","\u0167":"t","\u01ad":"t","\u0288":"t","\u2c66":"t","\ua787":"t","\ua729":"tz","\u24e4":"u","\uff55":"u","\xf9":"u","\xfa":"u","\xfb":"u","\u0169":"u","\u1e79":"u","\u016b":"u","\u1e7b":"u","\u016d":"u","\xfc":"u","\u01dc":"u","\u01d8":"u","\u01d6":"u","\u01da":"u","\u1ee7":"u","\u016f":"u","\u0171":"u","\u01d4":"u","\u0215":"u","\u0217":"u","\u01b0":"u","\u1eeb":"u","\u1ee9":"u","\u1eef":"u","\u1eed":"u","\u1ef1":"u","\u1ee5":"u","\u1e73":"u","\u0173":"u","\u1e77":"u","\u1e75":"u","\u0289":"u","\u24e5":"v","\uff56":"v","\u1e7d":"v","\u1e7f":"v","\u028b":"v","\ua75f":"v","\u028c":"v","\ua761":"vy","\u24e6":"w","\uff57":"w","\u1e81":"w","\u1e83":"w","\u0175":"w","\u1e87":"w","\u1e85":"w","\u1e98":"w","\u1e89":"w","\u2c73":"w","\u24e7":"x","\uff58":"x","\u1e8b":"x","\u1e8d":"x","\u24e8":"y","\uff59":"y","\u1ef3":"y","\xfd":"y","\u0177":"y","\u1ef9":"y","\u0233":"y","\u1e8f":"y","\xff":"y","\u1ef7":"y","\u1e99":"y","\u1ef5":"y","\u01b4":"y","\u024f":"y","\u1eff":"y","\u24e9":"z","\uff5a":"z","\u017a":"z","\u1e91":"z","\u017c":"z","\u017e":"z","\u1e93":"z","\u1e95":"z","\u01b6":"z","\u0225":"z","\u0240":"z","\u2c6c":"z","\ua763":"z"};j=a(document),g=function(){var a=1;return function(){return a++}}(),j.on("mousemove",function(a){i.x=a.pageX,i.y=a.pageY}),d=O(Object,{bind:function(a){var b=this;return function(){a.apply(b,arguments)}},init:function(c){var d,e,f=".select2-results";this.opts=c=this.prepareOpts(c),this.id=c.id,c.element.data("select2")!==b&&null!==c.element.data("select2")&&c.element.data("select2").destroy(),this.container=this.createContainer(),this.liveRegion=a("<span>",{role:"status","aria-live":"polite"}).addClass("select2-hidden-accessible").appendTo(document.body),this.containerId="s2id_"+(c.element.attr("id")||"autogen"+g()).replace(/([;&,\-\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g,"\\$1"),this.containerSelector="#"+this.containerId,this.container.attr("id",this.containerId),this.body=x(function(){return c.element.closest("body")}),E(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.attr("style",c.element.attr("style")),this.container.css(L(c.containerCss)),this.container.addClass(L(c.containerCssClass)),this.elementTabIndex=this.opts.element.attr("tabindex"),this.opts.element.data("select2",this).attr("tabindex","-1").before(this.container).on("click.select2",B),this.container.data("select2",this),this.dropdown=this.container.find(".select2-drop"),E(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(L(c.dropdownCssClass)),this.dropdown.data("select2",this),this.dropdown.on("click",B),this.results=d=this.container.find(f),this.search=e=this.container.find("input.select2-input"),this.queryCount=0,this.resultsPage=0,this.context=null,this.initContainer(),this.container.on("click",B),v(this.results),this.dropdown.on("mousemove-filtered touchstart touchmove touchend",f,this.bind(this.highlightUnderEvent)),this.dropdown.on("touchend",f,this.bind(this.selectHighlighted)),this.dropdown.on("touchmove",f,this.bind(this.touchMoved)),this.dropdown.on("touchstart touchend",f,this.bind(this.clearTouchMoved)),y(80,this.results),this.dropdown.on("scroll-debounced",f,this.bind(this.loadMoreIfNeeded)),a(this.container).on("change",".select2-input",function(a){a.stopPropagation()}),a(this.dropdown).on("change",".select2-input",function(a){a.stopPropagation()}),a.fn.mousewheel&&d.mousewheel(function(a,b,c,e){var f=d.scrollTop();e>0&&0>=f-e?(d.scrollTop(0),B(a)):0>e&&d.get(0).scrollHeight-d.scrollTop()+e<=d.height()&&(d.scrollTop(d.get(0).scrollHeight-d.height()),B(a))}),u(e),e.on("keyup-change input paste",this.bind(this.updateResults)),e.on("focus",function(){e.addClass("select2-focused")}),e.on("blur",function(){e.removeClass("select2-focused")}),this.dropdown.on("mouseup",f,this.bind(function(b){a(b.target).closest(".select2-result-selectable").length>0&&(this.highlightUnderEvent(b),this.selectHighlighted(b))})),this.dropdown.on("click mouseup mousedown focusin",function(a){a.stopPropagation()}),this.nextSearchTerm=b,a.isFunction(this.opts.initSelection)&&(this.initSelection(),this.monitorSource()),null!==c.maximumInputLength&&this.search.attr("maxlength",c.maximumInputLength);var h=c.element.prop("disabled");h===b&&(h=!1),this.enable(!h);var i=c.element.prop("readonly");i===b&&(i=!1),this.readonly(i),k=k||q(),this.autofocus=c.element.prop("autofocus"),c.element.prop("autofocus",!1),this.autofocus&&this.focus(),this.search.attr("placeholder",c.searchInputPlaceholder)},destroy:function(){var a=this.opts.element,c=a.data("select2");this.close(),this.propertyObserver&&(delete this.propertyObserver,this.propertyObserver=null),c!==b&&(c.container.remove(),c.liveRegion.remove(),c.dropdown.remove(),a.removeClass("select2-offscreen").removeData("select2").off(".select2").prop("autofocus",this.autofocus||!1),this.elementTabIndex?a.attr({tabindex:this.elementTabIndex}):a.removeAttr("tabindex"),a.show())},optionToData:function(a){return a.is("option")?{id:a.prop("value"),text:a.text(),element:a.get(),css:a.attr("class"),disabled:a.prop("disabled"),locked:r(a.attr("locked"),"locked")||r(a.data("locked"),!0)}:a.is("optgroup")?{text:a.attr("label"),children:[],element:a.get(),css:a.attr("class")}:void 0},prepareOpts:function(c){var d,e,f,h,i=this;if(d=c.element,"select"===d.get(0).tagName.toLowerCase()&&(this.select=e=c.element),e&&a.each(["id","multiple","ajax","query","createSearchChoice","initSelection","data","tags"],function(){if(this in c)throw new Error("Option '"+this+"' is not allowed for Select2 when attached to a <select> element.")}),c=a.extend({},{populateResults:function(d,e,f){var h,j=this.opts.id,k=this.liveRegion;h=function(d,e,l){var m,n,o,p,q,r,s,t,u,v;for(d=c.sortResults(d,e,f),m=0,n=d.length;n>m;m+=1)o=d[m],q=o.disabled===!0,p=!q&&j(o)!==b,r=o.children&&o.children.length>0,s=a("<li></li>"),s.addClass("select2-results-dept-"+l),s.addClass("select2-result"),s.addClass(p?"select2-result-selectable":"select2-result-unselectable"),q&&s.addClass("select2-disabled"),r&&s.addClass("select2-result-with-children"),s.addClass(i.opts.formatResultCssClass(o)),s.attr("role","presentation"),t=a(document.createElement("div")),t.addClass("select2-result-label"),t.attr("id","select2-result-label-"+g()),t.attr("role","option"),v=c.formatResult(o,t,f,i.opts.escapeMarkup),v!==b&&(t.html(v),s.append(t)),r&&(u=a("<ul></ul>"),u.addClass("select2-result-sub"),h(o.children,u,l+1),s.append(u)),s.data("select2-data",o),e.append(s);k.text(c.formatMatches(d.length))},h(e,d,0)}},a.fn.select2.defaults,c),"function"!=typeof c.id&&(f=c.id,c.id=function(a){return a[f]}),a.isArray(c.element.data("select2Tags"))){if("tags"in c)throw"tags specified as both an attribute 'data-select2-tags' and in options of Select2 "+c.element.attr("id");c.tags=c.element.data("select2Tags")}if(e?(c.query=this.bind(function(a){var f,g,h,c={results:[],more:!1},e=a.term;h=function(b,c){var d;b.is("option")?a.matcher(e,b.text(),b)&&c.push(i.optionToData(b)):b.is("optgroup")&&(d=i.optionToData(b),b.children().each2(function(a,b){h(b,d.children)}),d.children.length>0&&c.push(d))},f=d.children(),this.getPlaceholder()!==b&&f.length>0&&(g=this.getPlaceholderOption(),g&&(f=f.not(g))),f.each2(function(a,b){h(b,c.results)}),a.callback(c)}),c.id=function(a){return a.id}):"query"in c||("ajax"in c?(h=c.element.data("ajax-url"),h&&h.length>0&&(c.ajax.url=h),c.query=H.call(c.element,c.ajax)):"data"in c?c.query=I(c.data):"tags"in c&&(c.query=J(c.tags),c.createSearchChoice===b&&(c.createSearchChoice=function(b){return{id:a.trim(b),text:a.trim(b)}}),c.initSelection===b&&(c.initSelection=function(b,d){var e=[];a(s(b.val(),c.separator)).each(function(){var b={id:this,text:this},d=c.tags;a.isFunction(d)&&(d=d()),a(d).each(function(){return r(this.id,b.id)?(b=this,!1):void 0}),e.push(b)}),d(e)}))),"function"!=typeof c.query)throw"query function not defined for Select2 "+c.element.attr("id");if("top"===c.createSearchChoicePosition)c.createSearchChoicePosition=function(a,b){a.unshift(b)};else if("bottom"===c.createSearchChoicePosition)c.createSearchChoicePosition=function(a,b){a.push(b)};else if("function"!=typeof c.createSearchChoicePosition)throw"invalid createSearchChoicePosition option must be 'top', 'bottom' or a custom function";return c},monitorSource:function(){var c,d,a=this.opts.element;a.on("change.select2",this.bind(function(){this.opts.element.data("select2-change-triggered")!==!0&&this.initSelection()})),c=this.bind(function(){var c=a.prop("disabled");c===b&&(c=!1),this.enable(!c);var d=a.prop("readonly");d===b&&(d=!1),this.readonly(d),E(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.addClass(L(this.opts.containerCssClass)),E(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(L(this.opts.dropdownCssClass))}),a.on("propertychange.select2",c),this.mutationCallback===b&&(this.mutationCallback=function(a){a.forEach(c)}),d=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver,d!==b&&(this.propertyObserver&&(delete this.propertyObserver,this.propertyObserver=null),this.propertyObserver=new d(this.mutationCallback),this.propertyObserver.observe(a.get(0),{attributes:!0,subtree:!1}))},triggerSelect:function(b){var c=a.Event("select2-selecting",{val:this.id(b),object:b});return this.opts.element.trigger(c),!c.isDefaultPrevented()},triggerChange:function(b){b=b||{},b=a.extend({},b,{type:"change",val:this.val()}),this.opts.element.data("select2-change-triggered",!0),this.opts.element.trigger(b),this.opts.element.data("select2-change-triggered",!1),this.opts.element.click(),this.opts.blurOnChange&&this.opts.element.blur()},isInterfaceEnabled:function(){return this.enabledInterface===!0},enableInterface:function(){var a=this._enabled&&!this._readonly,b=!a;return a===this.enabledInterface?!1:(this.container.toggleClass("select2-container-disabled",b),this.close(),this.enabledInterface=a,!0)},enable:function(a){a===b&&(a=!0),this._enabled!==a&&(this._enabled=a,this.opts.element.prop("disabled",!a),this.enableInterface())},disable:function(){this.enable(!1)},readonly:function(a){a===b&&(a=!1),this._readonly!==a&&(this._readonly=a,this.opts.element.prop("readonly",a),this.enableInterface())},opened:function(){return this.container.hasClass("select2-dropdown-open")},positionDropdown:function(){var t,u,v,w,x,b=this.dropdown,c=this.container.offset(),d=this.container.outerHeight(!1),e=this.container.outerWidth(!1),f=b.outerHeight(!1),g=a(window),h=g.width(),i=g.height(),j=g.scrollLeft()+h,l=g.scrollTop()+i,m=c.top+d,n=c.left,o=l>=m+f,p=c.top-f>=g.scrollTop(),q=b.outerWidth(!1),r=j>=n+q,s=b.hasClass("select2-drop-above");s?(u=!0,!p&&o&&(v=!0,u=!1)):(u=!1,!o&&p&&(v=!0,u=!0)),v&&(b.hide(),c=this.container.offset(),d=this.container.outerHeight(!1),e=this.container.outerWidth(!1),f=b.outerHeight(!1),j=g.scrollLeft()+h,l=g.scrollTop()+i,m=c.top+d,n=c.left,q=b.outerWidth(!1),r=j>=n+q,b.show()),this.opts.dropdownAutoWidth?(x=a(".select2-results",b)[0],b.addClass("select2-drop-auto-width"),b.css("width",""),q=b.outerWidth(!1)+(x.scrollHeight===x.clientHeight?0:k.width),q>e?e=q:q=e,r=j>=n+q):this.container.removeClass("select2-drop-auto-width"),"static"!==this.body().css("position")&&(t=this.body().offset(),m-=t.top,n-=t.left),r||(n=c.left+this.container.outerWidth(!1)-q),w={left:n,width:e},u?(w.top=c.top-f,w.bottom="auto",this.container.addClass("select2-drop-above"),b.addClass("select2-drop-above")):(w.top=m,w.bottom="auto",this.container.removeClass("select2-drop-above"),b.removeClass("select2-drop-above")),w=a.extend(w,L(this.opts.dropdownCss)),b.css(w)},shouldOpen:function(){var b;return this.opened()?!1:this._enabled===!1||this._readonly===!0?!1:(b=a.Event("select2-opening"),this.opts.element.trigger(b),!b.isDefaultPrevented())},clearDropdownAlignmentPreference:function(){this.container.removeClass("select2-drop-above"),this.dropdown.removeClass("select2-drop-above")},open:function(){return this.shouldOpen()?(this.opening(),!0):!1},opening:function(){var f,b=this.containerId,c="scroll."+b,d="resize."+b,e="orientationchange."+b;this.container.addClass("select2-dropdown-open").addClass("select2-container-active"),this.clearDropdownAlignmentPreference(),this.dropdown[0]!==this.body().children().last()[0]&&this.dropdown.detach().appendTo(this.body()),f=a("#select2-drop-mask"),0==f.length&&(f=a(document.createElement("div")),f.attr("id","select2-drop-mask").attr("class","select2-drop-mask"),f.hide(),f.appendTo(this.body()),f.on("mousedown touchstart click",function(b){n(f);var d,c=a("#select2-drop");c.length>0&&(d=c.data("select2"),d.opts.selectOnBlur&&d.selectHighlighted({noFocus:!0}),d.close(),b.preventDefault(),b.stopPropagation())})),this.dropdown.prev()[0]!==f[0]&&this.dropdown.before(f),a("#select2-drop").removeAttr("id"),this.dropdown.attr("id","select2-drop"),f.show(),this.positionDropdown(),this.dropdown.show(),this.positionDropdown(),this.dropdown.addClass("select2-drop-active");var g=this;this.container.parents().add(window).each(function(){a(this).on(d+" "+c+" "+e,function(){g.positionDropdown()})})},close:function(){if(this.opened()){var b=this.containerId,c="scroll."+b,d="resize."+b,e="orientationchange."+b;this.container.parents().add(window).each(function(){a(this).off(c).off(d).off(e)}),this.clearDropdownAlignmentPreference(),a("#select2-drop-mask").hide(),this.dropdown.removeAttr("id"),this.dropdown.hide(),this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active"),this.results.empty(),this.clearSearch(),this.search.removeClass("select2-active"),this.opts.element.trigger(a.Event("select2-close"))}},externalSearch:function(a){this.open(),this.search.val(a),this.updateResults(!1)},clearSearch:function(){},getMaximumSelectionSize:function(){return L(this.opts.maximumSelectionSize)},ensureHighlightVisible:function(){var c,d,e,f,g,h,i,b=this.results;if(d=this.highlight(),!(0>d)){if(0==d)return b.scrollTop(0),void 0;c=this.findHighlightableChoices().find(".select2-result-label"),e=a(c[d]),f=e.offset().top+e.outerHeight(!0),d===c.length-1&&(i=b.find("li.select2-more-results"),i.length>0&&(f=i.offset().top+i.outerHeight(!0))),g=b.offset().top+b.outerHeight(!0),f>g&&b.scrollTop(b.scrollTop()+(f-g)),h=e.offset().top-b.offset().top,0>h&&"none"!=e.css("display")&&b.scrollTop(b.scrollTop()+h)}},findHighlightableChoices:function(){return this.results.find(".select2-result-selectable:not(.select2-disabled):not(.select2-selected)")},moveHighlight:function(b){for(var c=this.findHighlightableChoices(),d=this.highlight();d>-1&&d<c.length;){d+=b;var e=a(c[d]);if(e.hasClass("select2-result-selectable")&&!e.hasClass("select2-disabled")&&!e.hasClass("select2-selected")){this.highlight(d);break}}},highlight:function(b){var d,e,c=this.findHighlightableChoices();return 0===arguments.length?p(c.filter(".select2-highlighted")[0],c.get()):(b>=c.length&&(b=c.length-1),0>b&&(b=0),this.removeHighlight(),d=a(c[b]),d.addClass("select2-highlighted"),this.search.attr("aria-activedescendant",d.find(".select2-result-label").attr("id")),this.ensureHighlightVisible(),this.liveRegion.text(d.text()),e=d.data("select2-data"),e&&this.opts.element.trigger({type:"select2-highlight",val:this.id(e),choice:e}),void 0)},removeHighlight:function(){this.results.find(".select2-highlighted").removeClass("select2-highlighted")},touchMoved:function(){this._touchMoved=!0},clearTouchMoved:function(){this._touchMoved=!1},countSelectableResults:function(){return this.findHighlightableChoices().length},highlightUnderEvent:function(b){var c=a(b.target).closest(".select2-result-selectable");if(c.length>0&&!c.is(".select2-highlighted")){var d=this.findHighlightableChoices();this.highlight(d.index(c))}else 0==c.length&&this.removeHighlight()},loadMoreIfNeeded:function(){var c,a=this.results,b=a.find("li.select2-more-results"),d=this.resultsPage+1,e=this,f=this.search.val(),g=this.context; +0!==b.length&&(c=b.offset().top-a.offset().top-a.height(),c<=this.opts.loadMorePadding&&(b.addClass("select2-active"),this.opts.query({element:this.opts.element,term:f,page:d,context:g,matcher:this.opts.matcher,callback:this.bind(function(c){e.opened()&&(e.opts.populateResults.call(this,a,c.results,{term:f,page:d,context:g}),e.postprocessResults(c,!1,!1),c.more===!0?(b.detach().appendTo(a).text(L(e.opts.formatLoadMore,d+1)),window.setTimeout(function(){e.loadMoreIfNeeded()},10)):b.remove(),e.positionDropdown(),e.resultsPage=d,e.context=c.context,this.opts.element.trigger({type:"select2-loaded",items:c}))})})))},tokenize:function(){},updateResults:function(c){function m(){d.removeClass("select2-active"),h.positionDropdown(),e.find(".select2-no-results,.select2-selection-limit,.select2-searching").length?h.liveRegion.text(e.text()):h.liveRegion.text(h.opts.formatMatches(e.find(".select2-result-selectable").length))}function n(a){e.html(a),m()}var g,i,l,d=this.search,e=this.results,f=this.opts,h=this,j=d.val(),k=a.data(this.container,"select2-last-term");if((c===!0||!k||!r(j,k))&&(a.data(this.container,"select2-last-term",j),c===!0||this.showSearchInput!==!1&&this.opened())){l=++this.queryCount;var o=this.getMaximumSelectionSize();if(o>=1&&(g=this.data(),a.isArray(g)&&g.length>=o&&K(f.formatSelectionTooBig,"formatSelectionTooBig")))return n("<li class='select2-selection-limit'>"+L(f.formatSelectionTooBig,o)+"</li>"),void 0;if(d.val().length<f.minimumInputLength)return K(f.formatInputTooShort,"formatInputTooShort")?n("<li class='select2-no-results'>"+L(f.formatInputTooShort,d.val(),f.minimumInputLength)+"</li>"):n(""),c&&this.showSearch&&this.showSearch(!0),void 0;if(f.maximumInputLength&&d.val().length>f.maximumInputLength)return K(f.formatInputTooLong,"formatInputTooLong")?n("<li class='select2-no-results'>"+L(f.formatInputTooLong,d.val(),f.maximumInputLength)+"</li>"):n(""),void 0;f.formatSearching&&0===this.findHighlightableChoices().length&&n("<li class='select2-searching'>"+L(f.formatSearching)+"</li>"),d.addClass("select2-active"),this.removeHighlight(),i=this.tokenize(),i!=b&&null!=i&&d.val(i),this.resultsPage=1,f.query({element:f.element,term:d.val(),page:this.resultsPage,context:null,matcher:f.matcher,callback:this.bind(function(g){var i;if(l==this.queryCount){if(!this.opened())return this.search.removeClass("select2-active"),void 0;if(this.context=g.context===b?null:g.context,this.opts.createSearchChoice&&""!==d.val()&&(i=this.opts.createSearchChoice.call(h,d.val(),g.results),i!==b&&null!==i&&h.id(i)!==b&&null!==h.id(i)&&0===a(g.results).filter(function(){return r(h.id(this),h.id(i))}).length&&this.opts.createSearchChoicePosition(g.results,i)),0===g.results.length&&K(f.formatNoMatches,"formatNoMatches"))return n("<li class='select2-no-results'>"+L(f.formatNoMatches,d.val())+"</li>"),void 0;e.empty(),h.opts.populateResults.call(this,e,g.results,{term:d.val(),page:this.resultsPage,context:null}),g.more===!0&&K(f.formatLoadMore,"formatLoadMore")&&(e.append("<li class='select2-more-results'>"+h.opts.escapeMarkup(L(f.formatLoadMore,this.resultsPage))+"</li>"),window.setTimeout(function(){h.loadMoreIfNeeded()},10)),this.postprocessResults(g,c),m(),this.opts.element.trigger({type:"select2-loaded",items:g})}})})}},cancel:function(){this.close()},blur:function(){this.opts.selectOnBlur&&this.selectHighlighted({noFocus:!0}),this.close(),this.container.removeClass("select2-container-active"),this.search[0]===document.activeElement&&this.search.blur(),this.clearSearch(),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus")},focusSearch:function(){z(this.search)},selectHighlighted:function(a){if(this._touchMoved)return this.clearTouchMoved(),void 0;var b=this.highlight(),c=this.results.find(".select2-highlighted"),d=c.closest(".select2-result").data("select2-data");d?(this.highlight(b),this.onSelect(d,a)):a&&a.noFocus&&this.close()},getPlaceholder:function(){var a;return this.opts.element.attr("placeholder")||this.opts.element.attr("data-placeholder")||this.opts.element.data("placeholder")||this.opts.placeholder||((a=this.getPlaceholderOption())!==b?a.text():b)},getPlaceholderOption:function(){if(this.select){var a=this.select.children("option").first();if(this.opts.placeholderOption!==b)return"first"===this.opts.placeholderOption&&a||"function"==typeof this.opts.placeholderOption&&this.opts.placeholderOption(this.select);if(""===a.text()&&""===a.val())return a}},initContainerWidth:function(){function c(){var c,d,e,f,g,h;if("off"===this.opts.width)return null;if("element"===this.opts.width)return 0===this.opts.element.outerWidth(!1)?"auto":this.opts.element.outerWidth(!1)+"px";if("copy"===this.opts.width||"resolve"===this.opts.width){if(c=this.opts.element.attr("style"),c!==b)for(d=c.split(";"),f=0,g=d.length;g>f;f+=1)if(h=d[f].replace(/\s/g,""),e=h.match(/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i),null!==e&&e.length>=1)return e[1];return"resolve"===this.opts.width?(c=this.opts.element.css("width"),c.indexOf("%")>0?c:0===this.opts.element.outerWidth(!1)?"auto":this.opts.element.outerWidth(!1)+"px"):null}return a.isFunction(this.opts.width)?this.opts.width():this.opts.width}var d=c.call(this);null!==d&&this.container.css("width",d)}}),e=O(d,{createContainer:function(){var b=a(document.createElement("div")).attr({"class":"select2-container"}).html(["<a href='javascript:void(0)' class='select2-choice' tabindex='-1'>"," <span class='select2-chosen'>&nbsp;</span><abbr class='select2-search-choice-close'></abbr>"," <span class='select2-arrow' role='presentation'><b role='presentation'></b></span>","</a>","<label for='' class='select2-offscreen'></label>","<input class='select2-focusser select2-offscreen' type='text' aria-haspopup='true' role='button' />","<div class='select2-drop select2-display-none'>"," <div class='select2-search'>"," <label for='' class='select2-offscreen'></label>"," <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input' role='combobox' aria-expanded='true'"," aria-autocomplete='list' />"," </div>"," <ul class='select2-results' role='listbox'>"," </ul>","</div>"].join(""));return b},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.focusser.prop("disabled",!this.isInterfaceEnabled())},opening:function(){var c,d,e;this.opts.minimumResultsForSearch>=0&&this.showSearch(!0),this.parent.opening.apply(this,arguments),this.showSearchInput!==!1&&this.search.val(this.focusser.val()),this.search.focus(),c=this.search.get(0),c.createTextRange?(d=c.createTextRange(),d.collapse(!1),d.select()):c.setSelectionRange&&(e=this.search.val().length,c.setSelectionRange(e,e)),""===this.search.val()&&this.nextSearchTerm!=b&&(this.search.val(this.nextSearchTerm),this.search.select()),this.focusser.prop("disabled",!0).val(""),this.updateResults(!0),this.opts.element.trigger(a.Event("select2-open"))},close:function(){this.opened()&&(this.parent.close.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},focus:function(){this.opened()?this.close():(this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},isFocused:function(){return this.container.hasClass("select2-container-active")},cancel:function(){this.parent.cancel.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus()},destroy:function(){a("label[for='"+this.focusser.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments)},initContainer:function(){var b,h,d=this.container,e=this.dropdown,f=g();this.opts.minimumResultsForSearch<0?this.showSearch(!1):this.showSearch(!0),this.selection=b=d.find(".select2-choice"),this.focusser=d.find(".select2-focusser"),b.find(".select2-chosen").attr("id","select2-chosen-"+f),this.focusser.attr("aria-labelledby","select2-chosen-"+f),this.results.attr("id","select2-results-"+f),this.search.attr("aria-owns","select2-results-"+f),this.focusser.attr("id","s2id_autogen"+f),h=a("label[for='"+this.opts.element.attr("id")+"']"),this.focusser.prev().text(h.text()).attr("for",this.focusser.attr("id"));var i=this.opts.element.attr("title");this.opts.element.attr("title",i||h.text()),this.focusser.attr("tabindex",this.elementTabIndex),this.search.attr("id",this.focusser.attr("id")+"_search"),this.search.prev().text(a("label[for='"+this.focusser.attr("id")+"']").text()).attr("for",this.search.attr("id")),this.search.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()){if(a.which===c.PAGE_UP||a.which===c.PAGE_DOWN)return B(a),void 0;switch(a.which){case c.UP:case c.DOWN:return this.moveHighlight(a.which===c.UP?-1:1),B(a),void 0;case c.ENTER:return this.selectHighlighted(),B(a),void 0;case c.TAB:return this.selectHighlighted({noFocus:!0}),void 0;case c.ESC:return this.cancel(a),B(a),void 0}}})),this.search.on("blur",this.bind(function(){document.activeElement===this.body().get(0)&&window.setTimeout(this.bind(function(){this.opened()&&this.search.focus()}),0)})),this.focusser.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()&&a.which!==c.TAB&&!c.isControl(a)&&!c.isFunctionKey(a)&&a.which!==c.ESC){if(this.opts.openOnEnter===!1&&a.which===c.ENTER)return B(a),void 0;if(a.which==c.DOWN||a.which==c.UP||a.which==c.ENTER&&this.opts.openOnEnter){if(a.altKey||a.ctrlKey||a.shiftKey||a.metaKey)return;return this.open(),B(a),void 0}return a.which==c.DELETE||a.which==c.BACKSPACE?(this.opts.allowClear&&this.clear(),B(a),void 0):void 0}})),u(this.focusser),this.focusser.on("keyup-change input",this.bind(function(a){if(this.opts.minimumResultsForSearch>=0){if(a.stopPropagation(),this.opened())return;this.open()}})),b.on("mousedown touchstart","abbr",this.bind(function(a){this.isInterfaceEnabled()&&(this.clear(),C(a),this.close(),this.selection.focus())})),b.on("mousedown touchstart",this.bind(function(c){n(b),this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.opened()?this.close():this.isInterfaceEnabled()&&this.open(),B(c)})),e.on("mousedown touchstart",this.bind(function(){this.search.focus()})),b.on("focus",this.bind(function(a){B(a)})),this.focusser.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})).on("blur",this.bind(function(){this.opened()||(this.container.removeClass("select2-container-active"),this.opts.element.trigger(a.Event("select2-blur")))})),this.search.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.setPlaceholder()},clear:function(b){var c=this.selection.data("select2-data");if(c){var d=a.Event("select2-clearing");if(this.opts.element.trigger(d),d.isDefaultPrevented())return;var e=this.getPlaceholderOption();this.opts.element.val(e?e.val():""),this.selection.find(".select2-chosen").empty(),this.selection.removeData("select2-data"),this.setPlaceholder(),b!==!1&&(this.opts.element.trigger({type:"select2-removed",val:this.id(c),choice:c}),this.triggerChange({removed:c}))}},initSelection:function(){if(this.isPlaceholderOptionSelected())this.updateSelection(null),this.close(),this.setPlaceholder();else{var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.setPlaceholder(),c.nextSearchTerm=c.opts.nextSearchTerm(a,c.search.val()))})}},isPlaceholderOptionSelected:function(){var a;return this.getPlaceholder()?(a=this.getPlaceholderOption())!==b&&a.prop("selected")||""===this.opts.element.val()||this.opts.element.val()===b||null===this.opts.element.val():!1},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=a.find("option").filter(function(){return this.selected&&!this.disabled});b(c.optionToData(d))}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=c.val(),f=null;b.query({matcher:function(a,c,d){var g=r(e,b.id(d));return g&&(f=d),g},callback:a.isFunction(d)?function(){d(f)}:a.noop})}),b},getPlaceholder:function(){return this.select&&this.getPlaceholderOption()===b?b:this.parent.getPlaceholder.apply(this,arguments)},setPlaceholder:function(){var a=this.getPlaceholder();if(this.isPlaceholderOptionSelected()&&a!==b){if(this.select&&this.getPlaceholderOption()===b)return;this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(a)),this.selection.addClass("select2-default"),this.container.removeClass("select2-allowclear")}},postprocessResults:function(a,b,c){var d=0,e=this;if(this.findHighlightableChoices().each2(function(a,b){return r(e.id(b.data("select2-data")),e.opts.element.val())?(d=a,!1):void 0}),c!==!1&&(b===!0&&d>=0?this.highlight(d):this.highlight(0)),b===!0){var g=this.opts.minimumResultsForSearch;g>=0&&this.showSearch(M(a.results)>=g)}},showSearch:function(b){this.showSearchInput!==b&&(this.showSearchInput=b,this.dropdown.find(".select2-search").toggleClass("select2-search-hidden",!b),this.dropdown.find(".select2-search").toggleClass("select2-offscreen",!b),a(this.dropdown,this.container).toggleClass("select2-with-searchbox",b))},onSelect:function(a,b){if(this.triggerSelect(a)){var c=this.opts.element.val(),d=this.data();this.opts.element.val(this.id(a)),this.updateSelection(a),this.opts.element.trigger({type:"select2-selected",val:this.id(a),choice:a}),this.nextSearchTerm=this.opts.nextSearchTerm(a,this.search.val()),this.close(),b&&b.noFocus||!this.opts.shouldFocusInput(this)||this.focusser.focus(),r(c,this.id(a))||this.triggerChange({added:a,removed:d})}},updateSelection:function(a){var d,e,c=this.selection.find(".select2-chosen");this.selection.data("select2-data",a),c.empty(),null!==a&&(d=this.opts.formatSelection(a,c,this.opts.escapeMarkup)),d!==b&&c.append(d),e=this.opts.formatSelectionCssClass(a,c),e!==b&&c.addClass(e),this.selection.removeClass("select2-default"),this.opts.allowClear&&this.getPlaceholder()!==b&&this.container.addClass("select2-allowclear")},val:function(){var a,c=!1,d=null,e=this,f=this.data();if(0===arguments.length)return this.opts.element.val();if(a=arguments[0],arguments.length>1&&(c=arguments[1]),this.select)this.select.val(a).find("option").filter(function(){return this.selected}).each2(function(a,b){return d=e.optionToData(b),!1}),this.updateSelection(d),this.setPlaceholder(),c&&this.triggerChange({added:d,removed:f});else{if(!a&&0!==a)return this.clear(c),void 0;if(this.opts.initSelection===b)throw new Error("cannot call val() if initSelection() is not defined");this.opts.element.val(a),this.opts.initSelection(this.opts.element,function(a){e.opts.element.val(a?e.id(a):""),e.updateSelection(a),e.setPlaceholder(),c&&e.triggerChange({added:a,removed:f})})}},clearSearch:function(){this.search.val(""),this.focusser.val("")},data:function(a){var c,d=!1;return 0===arguments.length?(c=this.selection.data("select2-data"),c==b&&(c=null),c):(arguments.length>1&&(d=arguments[1]),a?(c=this.data(),this.opts.element.val(a?this.id(a):""),this.updateSelection(a),d&&this.triggerChange({added:a,removed:c})):this.clear(d),void 0)}}),f=O(d,{createContainer:function(){var b=a(document.createElement("div")).attr({"class":"select2-container select2-container-multi"}).html(["<ul class='select2-choices'>"," <li class='select2-search-field'>"," <label for='' class='select2-offscreen'></label>"," <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input'>"," </li>","</ul>","<div class='select2-drop select2-drop-multi select2-display-none'>"," <ul class='select2-results'>"," </ul>","</div>"].join(""));return b},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=[];a.find("option").filter(function(){return this.selected&&!this.disabled}).each2(function(a,b){d.push(c.optionToData(b))}),b(d)}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=s(c.val(),b.separator),f=[];b.query({matcher:function(c,d,g){var h=a.grep(e,function(a){return r(a,b.id(g))}).length;return h&&f.push(g),h},callback:a.isFunction(d)?function(){for(var a=[],c=0;c<e.length;c++)for(var g=e[c],h=0;h<f.length;h++){var i=f[h];if(r(g,b.id(i))){a.push(i),f.splice(h,1);break}}d(a)}:a.noop})}),b},selectChoice:function(a){var b=this.container.find(".select2-search-choice-focus");b.length&&a&&a[0]==b[0]||(b.length&&this.opts.element.trigger("choice-deselected",b),b.removeClass("select2-search-choice-focus"),a&&a.length&&(this.close(),a.addClass("select2-search-choice-focus"),this.opts.element.trigger("choice-selected",a)))},destroy:function(){a("label[for='"+this.search.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments)},initContainer:function(){var d,b=".select2-choices";this.searchContainer=this.container.find(".select2-search-field"),this.selection=d=this.container.find(b);var e=this;this.selection.on("click",".select2-search-choice:not(.select2-locked)",function(){e.search[0].focus(),e.selectChoice(a(this))}),this.search.attr("id","s2id_autogen"+g()),this.search.prev().text(a("label[for='"+this.opts.element.attr("id")+"']").text()).attr("for",this.search.attr("id")),this.search.on("input paste",this.bind(function(){this.isInterfaceEnabled()&&(this.opened()||this.open())})),this.search.attr("tabindex",this.elementTabIndex),this.keydowns=0,this.search.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()){++this.keydowns;var b=d.find(".select2-search-choice-focus"),e=b.prev(".select2-search-choice:not(.select2-locked)"),f=b.next(".select2-search-choice:not(.select2-locked)"),g=A(this.search);if(b.length&&(a.which==c.LEFT||a.which==c.RIGHT||a.which==c.BACKSPACE||a.which==c.DELETE||a.which==c.ENTER)){var h=b;return a.which==c.LEFT&&e.length?h=e:a.which==c.RIGHT?h=f.length?f:null:a.which===c.BACKSPACE?this.unselect(b.first())&&(this.search.width(10),h=e.length?e:f):a.which==c.DELETE?this.unselect(b.first())&&(this.search.width(10),h=f.length?f:null):a.which==c.ENTER&&(h=null),this.selectChoice(h),B(a),h&&h.length||this.open(),void 0}if((a.which===c.BACKSPACE&&1==this.keydowns||a.which==c.LEFT)&&0==g.offset&&!g.length)return this.selectChoice(d.find(".select2-search-choice:not(.select2-locked)").last()),B(a),void 0;if(this.selectChoice(null),this.opened())switch(a.which){case c.UP:case c.DOWN:return this.moveHighlight(a.which===c.UP?-1:1),B(a),void 0;case c.ENTER:return this.selectHighlighted(),B(a),void 0;case c.TAB:return this.selectHighlighted({noFocus:!0}),this.close(),void 0;case c.ESC:return this.cancel(a),B(a),void 0}if(a.which!==c.TAB&&!c.isControl(a)&&!c.isFunctionKey(a)&&a.which!==c.BACKSPACE&&a.which!==c.ESC){if(a.which===c.ENTER){if(this.opts.openOnEnter===!1)return;if(a.altKey||a.ctrlKey||a.shiftKey||a.metaKey)return}this.open(),(a.which===c.PAGE_UP||a.which===c.PAGE_DOWN)&&B(a),a.which===c.ENTER&&B(a)}}})),this.search.on("keyup",this.bind(function(){this.keydowns=0,this.resizeSearch()})),this.search.on("blur",this.bind(function(b){this.container.removeClass("select2-container-active"),this.search.removeClass("select2-focused"),this.selectChoice(null),this.opened()||this.clearSearch(),b.stopImmediatePropagation(),this.opts.element.trigger(a.Event("select2-blur"))})),this.container.on("click",b,this.bind(function(b){this.isInterfaceEnabled()&&(a(b.target).closest(".select2-search-choice").length>0||(this.selectChoice(null),this.clearPlaceholder(),this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.open(),this.focusSearch(),b.preventDefault()))})),this.container.on("focus",b,this.bind(function(){this.isInterfaceEnabled()&&(this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"),this.clearPlaceholder())})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.clearSearch()},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.search.prop("disabled",!this.isInterfaceEnabled())},initSelection:function(){if(""===this.opts.element.val()&&""===this.opts.element.text()&&(this.updateSelection([]),this.close(),this.clearSearch()),this.select||""!==this.opts.element.val()){var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.clearSearch())})}},clearSearch:function(){var a=this.getPlaceholder(),c=this.getMaxSearchWidth();a!==b&&0===this.getVal().length&&this.search.hasClass("select2-focused")===!1?(this.search.val(a).addClass("select2-default"),this.search.width(c>0?c:this.container.css("width"))):this.search.val("").width(10)},clearPlaceholder:function(){this.search.hasClass("select2-default")&&this.search.val("").removeClass("select2-default")},opening:function(){this.clearPlaceholder(),this.resizeSearch(),this.parent.opening.apply(this,arguments),this.focusSearch(),""===this.search.val()&&this.nextSearchTerm!=b&&(this.search.val(this.nextSearchTerm),this.search.select()),this.updateResults(!0),this.search.focus(),this.opts.element.trigger(a.Event("select2-open"))},close:function(){this.opened()&&this.parent.close.apply(this,arguments)},focus:function(){this.close(),this.search.focus()},isFocused:function(){return this.search.hasClass("select2-focused")},updateSelection:function(b){var c=[],d=[],e=this;a(b).each(function(){p(e.id(this),c)<0&&(c.push(e.id(this)),d.push(this))}),b=d,this.selection.find(".select2-search-choice").remove(),a(b).each(function(){e.addSelectedChoice(this)}),e.postprocessResults()},tokenize:function(){var a=this.search.val();a=this.opts.tokenizer.call(this,a,this.data(),this.bind(this.onSelect),this.opts),null!=a&&a!=b&&(this.search.val(a),a.length>0&&this.open())},onSelect:function(a,c){this.triggerSelect(a)&&(this.addSelectedChoice(a),this.opts.element.trigger({type:"selected",val:this.id(a),choice:a}),this.nextSearchTerm=this.opts.nextSearchTerm(a,this.search.val()),this.clearSearch(),this.updateResults(),(this.select||!this.opts.closeOnSelect)&&this.postprocessResults(a,!1,this.opts.closeOnSelect===!0),this.opts.closeOnSelect?(this.close(),this.search.width(10)):this.countSelectableResults()>0?(this.search.width(10),this.resizeSearch(),this.getMaximumSelectionSize()>0&&this.val().length>=this.getMaximumSelectionSize()?this.updateResults(!0):this.nextSearchTerm!=b&&(this.search.val(this.nextSearchTerm),this.updateResults(),this.search.select()),this.positionDropdown()):(this.close(),this.search.width(10)),this.triggerChange({added:a}),c&&c.noFocus||this.focusSearch())},cancel:function(){this.close(),this.focusSearch()},addSelectedChoice:function(c){var j,k,d=!c.locked,e=a("<li class='select2-search-choice'> <div></div> <a href='#' class='select2-search-choice-close' tabindex='-1'></a></li>"),f=a("<li class='select2-search-choice select2-locked'><div></div></li>"),g=d?e:f,h=this.id(c),i=this.getVal();j=this.opts.formatSelection(c,g.find("div"),this.opts.escapeMarkup),j!=b&&g.find("div").replaceWith("<div>"+j+"</div>"),k=this.opts.formatSelectionCssClass(c,g.find("div")),k!=b&&g.addClass(k),d&&g.find(".select2-search-choice-close").on("mousedown",B).on("click dblclick",this.bind(function(b){this.isInterfaceEnabled()&&(this.unselect(a(b.target)),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"),B(b),this.close(),this.focusSearch())})).on("focus",this.bind(function(){this.isInterfaceEnabled()&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"))})),g.data("select2-data",c),g.insertBefore(this.searchContainer),i.push(h),this.setVal(i)},unselect:function(b){var d,e,c=this.getVal();if(b=b.closest(".select2-search-choice"),0===b.length)throw"Invalid argument: "+b+". Must be .select2-search-choice";if(d=b.data("select2-data")){var f=a.Event("select2-removing");if(f.val=this.id(d),f.choice=d,this.opts.element.trigger(f),f.isDefaultPrevented())return!1;for(;(e=p(this.id(d),c))>=0;)c.splice(e,1),this.setVal(c),this.select&&this.postprocessResults();return b.remove(),this.opts.element.trigger({type:"select2-removed",val:this.id(d),choice:d}),this.triggerChange({removed:d}),!0}},postprocessResults:function(a,b,c){var d=this.getVal(),e=this.results.find(".select2-result"),f=this.results.find(".select2-result-with-children"),g=this;e.each2(function(a,b){var c=g.id(b.data("select2-data"));p(c,d)>=0&&(b.addClass("select2-selected"),b.find(".select2-result-selectable").addClass("select2-selected"))}),f.each2(function(a,b){b.is(".select2-result-selectable")||0!==b.find(".select2-result-selectable:not(.select2-selected)").length||b.addClass("select2-selected")}),-1==this.highlight()&&c!==!1&&g.highlight(0),!this.opts.createSearchChoice&&!e.filter(".select2-result:not(.select2-selected)").length>0&&(!a||a&&!a.more&&0===this.results.find(".select2-no-results").length)&&K(g.opts.formatNoMatches,"formatNoMatches")&&this.results.append("<li class='select2-no-results'>"+L(g.opts.formatNoMatches,g.search.val())+"</li>")},getMaxSearchWidth:function(){return this.selection.width()-t(this.search)},resizeSearch:function(){var a,b,c,d,e,f=t(this.search);a=D(this.search)+10,b=this.search.offset().left,c=this.selection.width(),d=this.selection.offset().left,e=c-(b-d)-f,a>e&&(e=c-f),40>e&&(e=c-f),0>=e&&(e=a),this.search.width(Math.floor(e))},getVal:function(){var a;return this.select?(a=this.select.val(),null===a?[]:a):(a=this.opts.element.val(),s(a,this.opts.separator))},setVal:function(b){var c;this.select?this.select.val(b):(c=[],a(b).each(function(){p(this,c)<0&&c.push(this)}),this.opts.element.val(0===c.length?"":c.join(this.opts.separator)))},buildChangeDetails:function(a,b){for(var b=b.slice(0),a=a.slice(0),c=0;c<b.length;c++)for(var d=0;d<a.length;d++)r(this.opts.id(b[c]),this.opts.id(a[d]))&&(b.splice(c,1),c>0&&c--,a.splice(d,1),d--);return{added:b,removed:a}},val:function(c,d){var e,f=this;if(0===arguments.length)return this.getVal();if(e=this.data(),e.length||(e=[]),!c&&0!==c)return this.opts.element.val(""),this.updateSelection([]),this.clearSearch(),d&&this.triggerChange({added:this.data(),removed:e}),void 0;if(this.setVal(c),this.select)this.opts.initSelection(this.select,this.bind(this.updateSelection)),d&&this.triggerChange(this.buildChangeDetails(e,this.data()));else{if(this.opts.initSelection===b)throw new Error("val() cannot be called if initSelection() is not defined");this.opts.initSelection(this.opts.element,function(b){var c=a.map(b,f.id);f.setVal(c),f.updateSelection(b),f.clearSearch(),d&&f.triggerChange(f.buildChangeDetails(e,f.data()))})}this.clearSearch()},onSortStart:function(){if(this.select)throw new Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead.");this.search.width(0),this.searchContainer.hide()},onSortEnd:function(){var b=[],c=this;this.searchContainer.show(),this.searchContainer.appendTo(this.searchContainer.parent()),this.resizeSearch(),this.selection.find(".select2-search-choice").each(function(){b.push(c.opts.id(a(this).data("select2-data")))}),this.setVal(b),this.triggerChange()},data:function(b,c){var e,f,d=this;return 0===arguments.length?this.selection.children(".select2-search-choice").map(function(){return a(this).data("select2-data")}).get():(f=this.data(),b||(b=[]),e=a.map(b,function(a){return d.opts.id(a)}),this.setVal(e),this.updateSelection(b),this.clearSearch(),c&&this.triggerChange(this.buildChangeDetails(f,this.data())),void 0)}}),a.fn.select2=function(){var d,e,f,g,h,c=Array.prototype.slice.call(arguments,0),i=["val","destroy","opened","open","close","focus","isFocused","container","dropdown","onSortStart","onSortEnd","enable","disable","readonly","positionDropdown","data","search"],j=["opened","isFocused","container","dropdown"],k=["val","data"],l={search:"externalSearch"};return this.each(function(){if(0===c.length||"object"==typeof c[0])d=0===c.length?{}:a.extend({},c[0]),d.element=a(this),"select"===d.element.get(0).tagName.toLowerCase()?h=d.element.prop("multiple"):(h=d.multiple||!1,"tags"in d&&(d.multiple=h=!0)),e=h?new window.Select2["class"].multi:new window.Select2["class"].single,e.init(d);else{if("string"!=typeof c[0])throw"Invalid arguments to select2 plugin: "+c;if(p(c[0],i)<0)throw"Unknown method: "+c[0];if(g=b,e=a(this).data("select2"),e===b)return;if(f=c[0],"container"===f?g=e.container:"dropdown"===f?g=e.dropdown:(l[f]&&(f=l[f]),g=e[f].apply(e,c.slice(1))),p(c[0],j)>=0||p(c[0],k)&&1==c.length)return!1}}),g===b?this:g},a.fn.select2.defaults={width:"copy",loadMorePadding:0,closeOnSelect:!0,openOnEnter:!0,containerCss:{},dropdownCss:{},containerCssClass:"",dropdownCssClass:"",formatResult:function(a,b,c,d){var e=[];return F(a.text,c.term,e,d),e.join("")},formatSelection:function(a,c,d){return a?d(a.text):b},sortResults:function(a){return a},formatResultCssClass:function(a){return a.css},formatSelectionCssClass:function(){return b},formatMatches:function(a){return a+" results are available, use up and down arrow keys to navigate."},formatNoMatches:function(){return"No matches found"},formatInputTooShort:function(a,b){var c=b-a.length;return"Please enter "+c+" or more character"+(1==c?"":"s")},formatInputTooLong:function(a,b){var c=a.length-b;return"Please delete "+c+" character"+(1==c?"":"s")},formatSelectionTooBig:function(a){return"You can only select "+a+" item"+(1==a?"":"s")},formatLoadMore:function(){return"Loading more results\u2026"},formatSearching:function(){return"Searching\u2026"},minimumResultsForSearch:0,minimumInputLength:0,maximumInputLength:null,maximumSelectionSize:0,id:function(a){return a==b?null:a.id},matcher:function(a,b){return o(""+b).toUpperCase().indexOf(o(""+a).toUpperCase())>=0},separator:",",tokenSeparators:[],tokenizer:N,escapeMarkup:G,blurOnChange:!1,selectOnBlur:!1,adaptContainerCssClass:function(a){return a},adaptDropdownCssClass:function(){return null},nextSearchTerm:function(){return b},searchInputPlaceholder:"",createSearchChoicePosition:"top",shouldFocusInput:function(a){return a.opts.minimumResultsForSearch<0?!1:!0}},a.fn.select2.ajaxDefaults={transport:a.ajax,params:{type:"GET",cache:!1,dataType:"json"}},window.Select2={query:{ajax:H,local:I,tags:J},util:{debounce:w,markMatch:F,escapeMarkup:G,stripDiacritics:o},"class":{"abstract":d,single:e,multi:f}}}}(jQuery); \ No newline at end of file diff --git a/src/static/jquery/select2-3.4.6/select2.png b/src/static/jquery/select2-3.4.6/select2.png new file mode 100755 index 0000000000000000000000000000000000000000..1d804ffb99699b9e030f1010314de0970b5a000d GIT binary patch literal 613 zcmV-r0-F7aP)<h;3K|Lk000e1NJLTq002Ay001Zm1^@s6qPv;@0006kNkl<Zc-rmR z&r1|x9LMps2uh5F)-GaQDk#Z_4iR>#WY!I$JQV$)A5aAS1BM||2XVJl=+L1^1S1H% zM-&lx?NZpUrHhn>fk<>POqf2sh40}xxGZfc+t+#Eb(q<Oecn6I%nq|DNy|zSyexzN z$5AL0?&Dan9pN5UxC<ug5`<4^!bTJ!40{Z2#(M~pn1C$$pw}f`kJpeHM`McNHFyg? zK;|>Hy9_3*1(U%t9t)QDnI#YAL(|ACV(>)>6WD-t!8tutHkdb^#3`HzoJG3A2@T`% zA|K@o*b!`R#(7)PWrMFn2))Ca3MR4(zaT`Zr61*kZK5NPnZwQszxh$fyv3?&4c>$q z2m=+yc0dRXRAsPDxF6sD;@rK4JGdR_``1S~o6Xi@2&aR6hcSrEp9HVRzEqVDqB<bN zXhRETAUt&UJ4{pqo<W$!4+ziE?D9@4ilQ3gUO=XZ)oyPsiQA7akeNo#WiVk!@H1G( zkAmgh?J@W$gqNtpN{mA2@w%j2(GYBBaKPD;E<cjsBsd99f~(<?&RR6i%jfeou7io} z!W3j)q1|OLVRs>n<1%hR=D4e1f^ra^A|34Cjc=Gny{F(o#MrvPYgZuTJOz(n)-F<| zj()qR;C={)N<0RRvDZ^@6ND+W*}gh-Lip(MDt!(zMSO)!j2j+*hxgzC-e3$@(O2p* zu;+gddm(cZwXTCLx*Ky4THOa*^b^F`woveIeCK^0aR|TJ00000NkvXXu0mjfA#WC6 literal 0 HcmV?d00001 diff --git a/src/static/jquery/select2-3.4.6/select2_locale_ar.js b/src/static/jquery/select2-3.4.6/select2_locale_ar.js new file mode 100755 index 0000000..92d7e39 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_ar.js @@ -0,0 +1,17 @@ +/** + * Select2 Arabic translation. + * + * Author: Adel KEDJOUR <adel@kedjour.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "لم يتم العثور على مطابقات"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; if (n == 1){ return "الرجاء إدخال حر٠واحد على الأكثر"; } return n == 2 ? "الرجاء إدخال حرÙين على الأكثر" : "الجاء إدخال " + n + " على الأكثر"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; if (n == 1){ return "الرجاء إدخال حر٠واحد على الأقل"; } return n == 2 ? "الرجاء إدخال حرÙين على الأقل" : "الجاء إدخال " + n + " على الأقل "; }, + formatSelectionTooBig: function (limit) { if (n == 1){ return "يمكنك أن تختار إختيار واحد Ùقط"; } return n == 2 ? "يمكنك أن تختار إختيارين Ùقط" : "يمكنك أن تختار " + n + " إختيارات Ùقط"; }, + formatLoadMore: function (pageNumber) { return "تحميل المزيد من النتائج…"; }, + formatSearching: function () { return "البحث…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_bg.js b/src/static/jquery/select2-3.4.6/select2_locale_bg.js new file mode 100755 index 0000000..585d28a --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_bg.js @@ -0,0 +1,18 @@ +/** + * Select2 Bulgarian translation. + * + * @author Lubomir Vikev <lubomirvikev@gmail.com> + * @author Uriy Efremochkin <efremochkin@uriy.me> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "ÐÑма намерени ÑъвпадениÑ"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "ÐœÐ¾Ð»Ñ Ð²ÑŠÐ²ÐµÐ´ÐµÑ‚Ðµ още " + n + " Ñимвол" + (n > 1 ? "а" : ""); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "ÐœÐ¾Ð»Ñ Ð²ÑŠÐ²ÐµÐ´ÐµÑ‚Ðµ Ñ " + n + " по-малко Ñимвол" + (n > 1 ? "а" : ""); }, + formatSelectionTooBig: function (limit) { return "Можете да направите до " + limit + (limit > 1 ? " избора" : " избор"); }, + formatLoadMore: function (pageNumber) { return "Зареждат Ñе още…"; }, + formatSearching: function () { return "ТърÑене…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_ca.js b/src/static/jquery/select2-3.4.6/select2_locale_ca.js new file mode 100755 index 0000000..7e19d3c --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_ca.js @@ -0,0 +1,17 @@ +/** + * Select2 Catalan translation. + * + * Author: David Planella <david.planella@gmail.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "No s'ha trobat cap coincidència"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Introduïu " + n + " caràcter" + (n == 1 ? "" : "s") + " més"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Introduïu " + n + " caràcter" + (n == 1? "" : "s") + "menys"; }, + formatSelectionTooBig: function (limit) { return "Només podeu seleccionar " + limit + " element" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "S'estan carregant més resultats…"; }, + formatSearching: function () { return "S'està cercant…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_cs.js b/src/static/jquery/select2-3.4.6/select2_locale_cs.js new file mode 100755 index 0000000..376b54a --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_cs.js @@ -0,0 +1,49 @@ +/** + * Select2 Czech translation. + * + * Author: Michal Marek <ahoj@michal-marek.cz> + * Author - sklonovani: David Vallner <david@vallner.net> + */ +(function ($) { + "use strict"; + // use text for the numbers 2 through 4 + var smallNumbers = { + 2: function(masc) { return (masc ? "dva" : "dvÄ›"); }, + 3: function() { return "tÅ™i"; }, + 4: function() { return "ÄtyÅ™i"; } + } + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nenalezeny žádné položky"; }, + formatInputTooShort: function (input, min) { + var n = min - input.length; + if (n == 1) { + return "Prosím zadejte jeÅ¡tÄ› jeden znak"; + } else if (n <= 4) { + return "Prosím zadejte jeÅ¡tÄ› další "+smallNumbers[n](true)+" znaky"; + } else { + return "Prosím zadejte jeÅ¡tÄ› dalších "+n+" znaků"; + } + }, + formatInputTooLong: function (input, max) { + var n = input.length - max; + if (n == 1) { + return "Prosím zadejte o jeden znak ménÄ›"; + } else if (n <= 4) { + return "Prosím zadejte o "+smallNumbers[n](true)+" znaky ménÄ›"; + } else { + return "Prosím zadejte o "+n+" znaků ménÄ›"; + } + }, + formatSelectionTooBig: function (limit) { + if (limit == 1) { + return "Můžete zvolit jen jednu položku"; + } else if (limit <= 4) { + return "Můžete zvolit maximálnÄ› "+smallNumbers[limit](false)+" položky"; + } else { + return "Můžete zvolit maximálnÄ› "+limit+" položek"; + } + }, + formatLoadMore: function (pageNumber) { return "NaÄítají se další výsledky…"; }, + formatSearching: function () { return "Vyhledávání…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_da.js b/src/static/jquery/select2-3.4.6/select2_locale_da.js new file mode 100755 index 0000000..dbce3e1 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_da.js @@ -0,0 +1,17 @@ +/** + * Select2 Danish translation. + * + * Author: Anders Jenbo <anders@jenbo.dk> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Ingen resultater fundet"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Angiv venligst " + n + " tegn mere"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Angiv venligst " + n + " tegn mindre"; }, + formatSelectionTooBig: function (limit) { return "Du kan kun vælge " + limit + " emne" + (limit === 1 ? "" : "r"); }, + formatLoadMore: function (pageNumber) { return "Indlæser flere resultater…"; }, + formatSearching: function () { return "Søger…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_de.js b/src/static/jquery/select2-3.4.6/select2_locale_de.js new file mode 100755 index 0000000..93b18e8 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_de.js @@ -0,0 +1,15 @@ +/** + * Select2 German translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Keine Ãœbereinstimmungen gefunden"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Bitte " + n + " Zeichen mehr eingeben"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Bitte " + n + " Zeichen weniger eingeben"; }, + formatSelectionTooBig: function (limit) { return "Sie können nur " + limit + " Eintr" + (limit === 1 ? "ag" : "äge") + " auswählen"; }, + formatLoadMore: function (pageNumber) { return "Lade mehr Ergebnisse…"; }, + formatSearching: function () { return "Suche…"; } + }); +})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/select2-3.4.6/select2_locale_el.js b/src/static/jquery/select2-3.4.6/select2_locale_el.js new file mode 100755 index 0000000..e94b02c --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_el.js @@ -0,0 +1,17 @@ +/** + * Select2 Greek translation. + * + * @author Uriy Efremochkin <efremochkin@uriy.me> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Δεν βÏέθηκαν αποτελέσματα"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "ΠαÏακαλοÏμε εισάγετε " + n + " πεÏισσότεÏο" + (n > 1 ? "Ï…Ï‚" : "") + " χαÏακτήÏ" + (n > 1 ? "ες" : "α"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "ΠαÏακαλοÏμε διαγÏάψτε " + n + " χαÏακτήÏ" + (n > 1 ? "ες" : "α"); }, + formatSelectionTooBig: function (limit) { return "ΜποÏείτε να επιλέξετε μόνο " + limit + " αντικείμεν" + (limit > 1 ? "α" : "ο"); }, + formatLoadMore: function (pageNumber) { return "ΦόÏτωση πεÏισσότεÏων…"; }, + formatSearching: function () { return "Αναζήτηση…"; } + }); +})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/select2-3.4.6/select2_locale_en.js.template b/src/static/jquery/select2-3.4.6/select2_locale_en.js.template new file mode 100755 index 0000000..f66bcc8 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_en.js.template @@ -0,0 +1,18 @@ +/** + * Select2 <Language> translation. + * + * Author: Your Name <your@email> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatMatches: function (matches) { return matches + " results are available, use up and down arrow keys to navigate."; }, + formatNoMatches: function () { return "No matches found"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " more character" + (n == 1 ? "" : "s"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1 ? "" : "s"); }, + formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Loading more results…"; }, + formatSearching: function () { return "Searching…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_es.js b/src/static/jquery/select2-3.4.6/select2_locale_es.js new file mode 100755 index 0000000..f2b5817 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_es.js @@ -0,0 +1,15 @@ +/** + * Select2 Spanish translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "No se encontraron resultados"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Por favor, introduzca " + n + " car" + (n == 1? "ácter" : "acteres"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Por favor, elimine " + n + " car" + (n == 1? "ácter" : "acteres"); }, + formatSelectionTooBig: function (limit) { return "Sólo puede seleccionar " + limit + " elemento" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Cargando más resultados…"; }, + formatSearching: function () { return "Buscando…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_et.js b/src/static/jquery/select2-3.4.6/select2_locale_et.js new file mode 100755 index 0000000..a4045d2 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_et.js @@ -0,0 +1,17 @@ +/** + * Select2 Estonian translation. + * + * Author: Kuldar Kalvik <kuldar@kalvik.ee> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Tulemused puuduvad"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Sisesta " + n + " täht" + (n == 1 ? "" : "e") + " rohkem"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Sisesta " + n + " täht" + (n == 1? "" : "e") + " vähem"; }, + formatSelectionTooBig: function (limit) { return "Saad vaid " + limit + " tulemus" + (limit == 1 ? "e" : "t") + " valida"; }, + formatLoadMore: function (pageNumber) { return "Laen tulemusi.."; }, + formatSearching: function () { return "Otsin.."; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_eu.js b/src/static/jquery/select2-3.4.6/select2_locale_eu.js new file mode 100755 index 0000000..1da1a70 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_eu.js @@ -0,0 +1,43 @@ +/** + * Select2 Basque translation. + * + * Author: Julen Ruiz Aizpuru <julenx at gmail dot com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { + return "Ez da bat datorrenik aurkitu"; + }, + formatInputTooShort: function (input, min) { + var n = min - input.length; + if (n === 1) { + return "Idatzi karaktere bat gehiago"; + } else { + return "Idatzi " + n + " karaktere gehiago"; + } + }, + formatInputTooLong: function (input, max) { + var n = input.length - max; + if (n === 1) { + return "Idatzi karaktere bat gutxiago"; + } else { + return "Idatzi " + n + " karaktere gutxiago"; + } + }, + formatSelectionTooBig: function (limit) { + if (limit === 1 ) { + return "Elementu bakarra hauta dezakezu"; + } else { + return limit + " elementu hauta ditzakezu soilik"; + } + }, + formatLoadMore: function (pageNumber) { + return "Emaitza gehiago kargatzen…"; + }, + formatSearching: function () { + return "Bilatzen…"; + } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_fa.js b/src/static/jquery/select2-3.4.6/select2_locale_fa.js new file mode 100755 index 0000000..a9e95af --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_fa.js @@ -0,0 +1,19 @@ +/** + * Select2 Persian translation. + * + * Author: Ali Choopan <choopan@arsh.co> + * Author: Ebrahim Byagowi <ebrahim@gnu.org> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatMatches: function (matches) { return matches + " نتیجه موجود است، کلیدهای جهت بالا Ùˆ پایین را برای گشتن استÙاده کنید."; }, + formatNoMatches: function () { return "نتیجه‌ای یاÙت نشد."; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "لطÙاً " + n + " نویسه بیشتر وارد نمایید"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "لطÙاً " + n + " نویسه را حذ٠کنید."; }, + formatSelectionTooBig: function (limit) { return "شما Ùقط می‌توانید " + limit + " مورد را انتخاب کنید"; }, + formatLoadMore: function (pageNumber) { return "در حال بارگیری موارد بیشتر…"; }, + formatSearching: function () { return "در حال جستجو…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_fi.js b/src/static/jquery/select2-3.4.6/select2_locale_fi.js new file mode 100755 index 0000000..9bed310 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_fi.js @@ -0,0 +1,28 @@ +/** + * Select2 Finnish translation + */ +(function ($) { + "use strict"; + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { + return "Ei tuloksia"; + }, + formatInputTooShort: function (input, min) { + var n = min - input.length; + return "Ole hyvä ja anna " + n + " merkkiä lisää"; + }, + formatInputTooLong: function (input, max) { + var n = input.length - max; + return "Ole hyvä ja anna " + n + " merkkiä vähemmän"; + }, + formatSelectionTooBig: function (limit) { + return "Voit valita ainoastaan " + limit + " kpl"; + }, + formatLoadMore: function (pageNumber) { + return "Ladataan lisää tuloksia…"; + }, + formatSearching: function () { + return "Etsitään…"; + } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_fr.js b/src/static/jquery/select2-3.4.6/select2_locale_fr.js new file mode 100755 index 0000000..d8c87d4 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_fr.js @@ -0,0 +1,15 @@ +/** + * Select2 French translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Aucun résultat trouvé"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Merci de saisir " + n + " caractère" + (n == 1? "" : "s") + " de plus"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Merci de supprimer " + n + " caractère" + (n == 1? "" : "s"); }, + formatSelectionTooBig: function (limit) { return "Vous pouvez seulement sélectionner " + limit + " élément" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Chargement de résultats supplémentaires…"; }, + formatSearching: function () { return "Recherche en cours…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_gl.js b/src/static/jquery/select2-3.4.6/select2_locale_gl.js new file mode 100755 index 0000000..8032632 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_gl.js @@ -0,0 +1,43 @@ +/** + * Select2 Galician translation + * + * Author: Leandro Regueiro <leandro.regueiro@gmail.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { + return "Non se atoparon resultados"; + }, + formatInputTooShort: function (input, min) { + var n = min - input.length; + if (n === 1) { + return "Engada un carácter"; + } else { + return "Engada " + n + " caracteres"; + } + }, + formatInputTooLong: function (input, max) { + var n = input.length - max; + if (n === 1) { + return "Elimine un carácter"; + } else { + return "Elimine " + n + " caracteres"; + } + }, + formatSelectionTooBig: function (limit) { + if (limit === 1 ) { + return "Só pode seleccionar un elemento"; + } else { + return "Só pode seleccionar " + limit + " elementos"; + } + }, + formatLoadMore: function (pageNumber) { + return "Cargando máis resultados…"; + }, + formatSearching: function () { + return "Buscando…"; + } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_he.js b/src/static/jquery/select2-3.4.6/select2_locale_he.js new file mode 100755 index 0000000..0038541 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_he.js @@ -0,0 +1,17 @@ +/** +* Select2 Hebrew translation. +* +* Author: Yakir Sitbon <http://www.yakirs.net/> +*/ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "×œ× × ×ž×¦×ו הת×מות"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "× × ×œ×”×–×™×Ÿ עוד " + n + " ×ª×•×•×™× × ×•×¡×¤×™×"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "× × ×œ×”×–×™×Ÿ פחות " + n + " תווי×"; }, + formatSelectionTooBig: function (limit) { return "ניתן לבחור " + limit + " פריטי×"; }, + formatLoadMore: function (pageNumber) { return "טוען תוצ×ות נוספות…"; }, + formatSearching: function () { return "מחפש…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_hr.js b/src/static/jquery/select2-3.4.6/select2_locale_hr.js new file mode 100755 index 0000000..c293725 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_hr.js @@ -0,0 +1,22 @@ +/** + * Select2 Croatian translation. + * + * @author Edi Modrić <edi.modric@gmail.com> + * @author Uriy Efremochkin <efremochkin@uriy.me> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nema rezultata"; }, + formatInputTooShort: function (input, min) { return "Unesite joÅ¡" + character(min - input.length); }, + formatInputTooLong: function (input, max) { return "Unesite" + character(input.length - max) + " manje"; }, + formatSelectionTooBig: function (limit) { return "Maksimalan broj odabranih stavki je " + limit; }, + formatLoadMore: function (pageNumber) { return "UÄitavanje rezultata…"; }, + formatSearching: function () { return "Pretraga…"; } + }); + + function character (n) { + return " " + n + " znak" + (n%10 < 5 && n%10 > 0 && (n%100 < 5 || n%100 > 19) ? n%10 > 1 ? "a" : "" : "ova"); + } +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_hu.js b/src/static/jquery/select2-3.4.6/select2_locale_hu.js new file mode 100755 index 0000000..a8c3088 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_hu.js @@ -0,0 +1,15 @@ +/** + * Select2 Hungarian translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nincs találat."; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Túl rövid. Még " + n + " karakter hiányzik."; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Túl hosszú. " + n + " karakterrel több, mint kellene."; }, + formatSelectionTooBig: function (limit) { return "Csak " + limit + " elemet lehet kiválasztani."; }, + formatLoadMore: function (pageNumber) { return "Töltés…"; }, + formatSearching: function () { return "Keresés…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_id.js b/src/static/jquery/select2-3.4.6/select2_locale_id.js new file mode 100755 index 0000000..5474540 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_id.js @@ -0,0 +1,17 @@ +/** + * Select2 Indonesian translation. + * + * Author: Ibrahim Yusuf <ibrahim7usuf@gmail.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Tidak ada data yang sesuai"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Masukkan " + n + " huruf lagi" + (n == 1 ? "" : "s"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Hapus " + n + " huruf" + (n == 1 ? "" : "s"); }, + formatSelectionTooBig: function (limit) { return "Anda hanya dapat memilih " + limit + " pilihan" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Mengambil data…"; }, + formatSearching: function () { return "Mencari…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_is.js b/src/static/jquery/select2-3.4.6/select2_locale_is.js new file mode 100755 index 0000000..aecc6cd --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_is.js @@ -0,0 +1,15 @@ +/** + * Select2 Icelandic translation. + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Ekkert fannst"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Vinsamlegast skrifið " + n + " staf" + (n > 1 ? "i" : "") + " í viðbót"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Vinsamlegast styttið texta um " + n + " staf" + (n > 1 ? "i" : ""); }, + formatSelectionTooBig: function (limit) { return "Þú getur aðeins valið " + limit + " atriði"; }, + formatLoadMore: function (pageNumber) { return "Sæki fleiri niðurstöður…"; }, + formatSearching: function () { return "Leita…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_it.js b/src/static/jquery/select2-3.4.6/select2_locale_it.js new file mode 100755 index 0000000..d4e24de --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_it.js @@ -0,0 +1,15 @@ +/** + * Select2 Italian translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nessuna corrispondenza trovata"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Inserisci ancora " + n + " caratter" + (n == 1? "e" : "i"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Inserisci " + n + " caratter" + (n == 1? "e" : "i") + " in meno"; }, + formatSelectionTooBig: function (limit) { return "Puoi selezionare solo " + limit + " element" + (limit == 1 ? "o" : "i"); }, + formatLoadMore: function (pageNumber) { return "Caricamento in corso…"; }, + formatSearching: function () { return "Ricerca…"; } + }); +})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/select2-3.4.6/select2_locale_ja.js b/src/static/jquery/select2-3.4.6/select2_locale_ja.js new file mode 100755 index 0000000..81106e7 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_ja.js @@ -0,0 +1,15 @@ +/** + * Select2 Japanese translation. + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "該当ãªã—"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "後" + n + "文字入れã¦ãã ã•ã„"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "検索文字列ãŒ" + n + "文字長ã™ãŽã¾ã™"; }, + formatSelectionTooBig: function (limit) { return "最多ã§" + limit + "é …ç›®ã¾ã§ã—ã‹é¸æŠžã§ãã¾ã›ã‚“"; }, + formatLoadMore: function (pageNumber) { return "読込中・・・"; }, + formatSearching: function () { return "検索中・・・"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_ka.js b/src/static/jquery/select2-3.4.6/select2_locale_ka.js new file mode 100755 index 0000000..366cc2d --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_ka.js @@ -0,0 +1,17 @@ +/** + * Select2 Georgian (Kartuli) translation. + * + * Author: Dimitri Kurashvili dimakura@gmail.com + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "ვერ მáƒáƒ˜áƒ«áƒ”ბნáƒ"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "გთხáƒáƒ•áƒ— შეიყვáƒáƒœáƒáƒ— კიდევ " + n + " სიმბáƒáƒšáƒ"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "გთხáƒáƒ•áƒ— წáƒáƒ¨áƒáƒšáƒáƒ— " + n + " სიმბáƒáƒšáƒ"; }, + formatSelectionTooBig: function (limit) { return "თქვენ შეგიძლიáƒáƒ— მხáƒáƒšáƒáƒ“ " + limit + " ჩáƒáƒœáƒáƒ¬áƒ”რის მáƒáƒœáƒ˜áƒ¨áƒ•áƒœáƒ"; }, + formatLoadMore: function (pageNumber) { return "შედეგის ჩáƒáƒ¢áƒ•áƒ˜áƒ áƒ—ვáƒâ€¦"; }, + formatSearching: function () { return "ძებნáƒâ€¦"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_ko.js b/src/static/jquery/select2-3.4.6/select2_locale_ko.js new file mode 100755 index 0000000..1a84d21 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_ko.js @@ -0,0 +1,17 @@ +/** + * Select2 Korean translation. + * + * @author Swen Mun <longfinfunnel@gmail.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "ê²°ê³¼ ì—†ìŒ"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "너무 짧습니다. "+n+"ê¸€ìž ë” ìž…ë ¥í•´ì£¼ì„¸ìš”."; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "너무 ê¹ë‹ˆë‹¤. "+n+"ê¸€ìž ì§€ì›Œì£¼ì„¸ìš”."; }, + formatSelectionTooBig: function (limit) { return "최대 "+limit+"개까지만 ì„ íƒí•˜ì‹¤ 수 있습니다."; }, + formatLoadMore: function (pageNumber) { return "불러오는 중…"; }, + formatSearching: function () { return "검색 중…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_lt.js b/src/static/jquery/select2-3.4.6/select2_locale_lt.js new file mode 100755 index 0000000..2e2f950 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_lt.js @@ -0,0 +1,24 @@ +/** + * Select2 Lithuanian translation. + * + * @author CRONUS Karmalakas <cronus dot karmalakas at gmail dot com> + * @author Uriy Efremochkin <efremochkin@uriy.me> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Atitikmenų nerasta"; }, + formatInputTooShort: function (input, min) { return "Ä®raÅ¡ykite dar" + character(min - input.length); }, + formatInputTooLong: function (input, max) { return "PaÅ¡alinkite" + character(input.length - max); }, + formatSelectionTooBig: function (limit) { + return "JÅ«s galite pasirinkti tik " + limit + " element" + ((limit%100 > 9 && limit%100 < 21) || limit%10 == 0 ? "ų" : limit%10 > 1 ? "us" : "Ä…"); + }, + formatLoadMore: function (pageNumber) { return "Kraunama daugiau rezultatų…"; }, + formatSearching: function () { return "IeÅ¡koma…"; } + }); + + function character (n) { + return " " + n + " simbol" + ((n%100 > 9 && n%100 < 21) || n%10 == 0 ? "ių" : n%10 > 1 ? "ius" : "į"); + } +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_lv.js b/src/static/jquery/select2-3.4.6/select2_locale_lv.js new file mode 100755 index 0000000..b300ec7 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_lv.js @@ -0,0 +1,17 @@ +/** + * Select2 Latvian translation. + * + * @author Uriy Efremochkin <efremochkin@uriy.me> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "SakritÄ«bu nav"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "LÅ«dzu ievadiet vÄ“l " + n + " simbol" + (n == 11 ? "us" : n%10 == 1 ? "u" : "us"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "LÅ«dzu ievadiet par " + n + " simbol" + (n == 11 ? "iem" : n%10 == 1 ? "u" : "iem") + " mazÄk"; }, + formatSelectionTooBig: function (limit) { return "JÅ«s varat izvÄ“lÄ“ties ne vairÄk kÄ " + limit + " element" + (limit == 11 ? "us" : limit%10 == 1 ? "u" : "us"); }, + formatLoadMore: function (pageNumber) { return "Datu ielÄde…"; }, + formatSearching: function () { return "MeklÄ“Å¡ana…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_mk.js b/src/static/jquery/select2-3.4.6/select2_locale_mk.js new file mode 100755 index 0000000..513562c --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_mk.js @@ -0,0 +1,17 @@ +/** + * Select2 Macedonian translation. + * + * Author: Marko Aleksic <psybaron@gmail.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Ðема пронајдено Ñовпаѓања"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Ве молиме внеÑете уште " + n + " карактер" + (n == 1 ? "" : "и"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Ве молиме внеÑете " + n + " помалку карактер" + (n == 1? "" : "и"); }, + formatSelectionTooBig: function (limit) { return "Можете да изберете Ñамо " + limit + " Ñтавк" + (limit == 1 ? "а" : "и"); }, + formatLoadMore: function (pageNumber) { return "Вчитување резултати…"; }, + formatSearching: function () { return "Пребарување…"; } + }); +})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/select2-3.4.6/select2_locale_ms.js b/src/static/jquery/select2-3.4.6/select2_locale_ms.js new file mode 100755 index 0000000..262042a --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_ms.js @@ -0,0 +1,17 @@ +/** + * Select2 Malay translation. + * + * Author: Kepoweran <kepoweran@gmail.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Tiada padanan yang ditemui"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Sila masukkan " + n + " aksara lagi"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Sila hapuskan " + n + " aksara"; }, + formatSelectionTooBig: function (limit) { return "Anda hanya boleh memilih " + limit + " pilihan"; }, + formatLoadMore: function (pageNumber) { return "Sedang memuatkan keputusan…"; }, + formatSearching: function () { return "Mencari…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_nl.js b/src/static/jquery/select2-3.4.6/select2_locale_nl.js new file mode 100755 index 0000000..5b5c415 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_nl.js @@ -0,0 +1,15 @@ +/** + * Select2 Dutch translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Geen resultaten gevonden"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Vul " + n + " karakter" + (n == 1? "" : "s") + " meer in"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Vul " + n + " karakter" + (n == 1? "" : "s") + " minder in"; }, + formatSelectionTooBig: function (limit) { return "Maximaal " + limit + " item" + (limit == 1 ? "" : "s") + " toegestaan"; }, + formatLoadMore: function (pageNumber) { return "Meer resultaten laden…"; }, + formatSearching: function () { return "Zoeken…"; } + }); +})(jQuery); \ No newline at end of file diff --git a/src/static/jquery/select2-3.4.6/select2_locale_no.js b/src/static/jquery/select2-3.4.6/select2_locale_no.js new file mode 100755 index 0000000..ab61c08 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_no.js @@ -0,0 +1,18 @@ +/** + * Select2 Norwegian translation. + * + * Author: Torgeir Veimo <torgeir.veimo@gmail.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Ingen treff"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Vennligst skriv inn " + n + (n>1 ? " flere tegn" : " tegn til"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Vennligst fjern " + n + " tegn"; }, + formatSelectionTooBig: function (limit) { return "Du kan velge maks " + limit + " elementer"; }, + formatLoadMore: function (pageNumber) { return "Laster flere resultater…"; }, + formatSearching: function () { return "Søker…"; } + }); +})(jQuery); + diff --git a/src/static/jquery/select2-3.4.6/select2_locale_pl.js b/src/static/jquery/select2-3.4.6/select2_locale_pl.js new file mode 100755 index 0000000..75054e7 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_pl.js @@ -0,0 +1,22 @@ +/** + * Select2 Polish translation. + * + * @author Jan Kondratowicz <jan@kondratowicz.pl> + * @author Uriy Efremochkin <efremochkin@uriy.me> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Brak wyników"; }, + formatInputTooShort: function (input, min) { return "Wpisz jeszcze" + character(min - input.length, "znak", "i"); }, + formatInputTooLong: function (input, max) { return "Wpisana fraza jest za dÅ‚uga o" + character(input.length - max, "znak", "i"); }, + formatSelectionTooBig: function (limit) { return "Możesz zaznaczyć najwyżej" + character(limit, "element", "y"); }, + formatLoadMore: function (pageNumber) { return "Åadowanie wyników…"; }, + formatSearching: function () { return "Szukanie…"; } + }); + + function character (n, word, pluralSuffix) { + return " " + n + " " + word + (n == 1 ? "" : n%10 < 5 && n%10 > 1 && (n%100 < 5 || n%100 > 20) ? pluralSuffix : "ów"); + } +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_pt-BR.js b/src/static/jquery/select2-3.4.6/select2_locale_pt-BR.js new file mode 100755 index 0000000..d60b182 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_pt-BR.js @@ -0,0 +1,15 @@ +/** + * Select2 Brazilian Portuguese translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nenhum resultado encontrado"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Informe " + n + " caractere" + (n == 1? "" : "s"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Apague " + n + " caractere" + (n == 1? "" : "s"); }, + formatSelectionTooBig: function (limit) { return "Só é possível selecionar " + limit + " elemento" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Carregando mais resultados…"; }, + formatSearching: function () { return "Buscando…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_pt-PT.js b/src/static/jquery/select2-3.4.6/select2_locale_pt-PT.js new file mode 100755 index 0000000..cced7cf --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_pt-PT.js @@ -0,0 +1,15 @@ +/** + * Select2 Portuguese (Portugal) translation + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nenhum resultado encontrado"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Introduza " + n + " car" + (n == 1 ? "ácter" : "acteres"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Apague " + n + " car" + (n == 1 ? "ácter" : "acteres"); }, + formatSelectionTooBig: function (limit) { return "Só é possível selecionar " + limit + " elemento" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "A carregar mais resultados…"; }, + formatSearching: function () { return "A pesquisar…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_ro.js b/src/static/jquery/select2-3.4.6/select2_locale_ro.js new file mode 100755 index 0000000..87eca4c --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_ro.js @@ -0,0 +1,15 @@ +/** + * Select2 Romanian translation. + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Nu a fost găsit nimic"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Vă rugăm să introduceÈ›i incă " + n + " caracter" + (n == 1 ? "" : "e"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Vă rugăm să introduceÈ›i mai puÈ›in de " + n + " caracter" + (n == 1? "" : "e"); }, + formatSelectionTooBig: function (limit) { return "AveÈ›i voie să selectaÈ›i cel mult " + limit + " element" + (limit == 1 ? "" : "e"); }, + formatLoadMore: function (pageNumber) { return "Se încarcă…"; }, + formatSearching: function () { return "Căutare…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_rs.js b/src/static/jquery/select2-3.4.6/select2_locale_rs.js new file mode 100755 index 0000000..300c01b --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_rs.js @@ -0,0 +1,17 @@ +/** + * Select2 Serbian translation. + * + * @author Limon Monte <limon.monte@gmail.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "NiÅ¡ta nije pronaÄ‘eno"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Ukucajte bar joÅ¡ " + n + " simbol" + (n % 10 == 1 && n % 100 != 11 ? "" : "a"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "ObriÅ¡ite " + n + " simbol" + (n % 10 == 1 && n % 100 != 11 ? "" : "a"); }, + formatSelectionTooBig: function (limit) { return "Možete izabrati samo " + limit + " stavk" + (limit % 10 == 1 && limit % 100 != 11 ? "u" : (limit % 10 >= 2 && limit % 10 <= 4 && (limit % 100 < 12 || limit % 100 > 14)? "e" : "i")); }, + formatLoadMore: function (pageNumber) { return "Preuzimanje joÅ¡ rezultata…"; }, + formatSearching: function () { return "Pretraga…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_ru.js b/src/static/jquery/select2-3.4.6/select2_locale_ru.js new file mode 100755 index 0000000..0f45ce0 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_ru.js @@ -0,0 +1,21 @@ +/** + * Select2 Russian translation. + * + * @author Uriy Efremochkin <efremochkin@uriy.me> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Совпадений не найдено"; }, + formatInputTooShort: function (input, min) { return "ПожалуйÑта, введите еще" + character(min - input.length); }, + formatInputTooLong: function (input, max) { return "ПожалуйÑта, введите на" + character(input.length - max) + " меньше"; }, + formatSelectionTooBig: function (limit) { return "Ð’Ñ‹ можете выбрать не более " + limit + " Ñлемент" + (limit%10 == 1 && limit%100 != 11 ? "а" : "ов"); }, + formatLoadMore: function (pageNumber) { return "Загрузка данных…"; }, + formatSearching: function () { return "ПоиÑк…"; } + }); + + function character (n) { + return " " + n + " Ñимвол" + (n%10 < 5 && n%10 > 0 && (n%100 < 5 || n%100 > 20) ? n%10 > 1 ? "a" : "" : "ов"); + } +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_sk.js b/src/static/jquery/select2-3.4.6/select2_locale_sk.js new file mode 100755 index 0000000..772f304 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_sk.js @@ -0,0 +1,48 @@ +/** + * Select2 Slovak translation. + * + * Author: David Vallner <david@vallner.net> + */ +(function ($) { + "use strict"; + // use text for the numbers 2 through 4 + var smallNumbers = { + 2: function(masc) { return (masc ? "dva" : "dve"); }, + 3: function() { return "tri"; }, + 4: function() { return "Å¡tyri"; } + } + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "NenaÅ¡li sa žiadne položky"; }, + formatInputTooShort: function (input, min) { + var n = min - input.length; + if (n == 1) { + return "Prosím zadajte eÅ¡te jeden znak"; + } else if (n <= 4) { + return "Prosím zadajte eÅ¡te ÄalÅ¡ie "+smallNumbers[n](true)+" znaky"; + } else { + return "Prosím zadajte eÅ¡te Äalších "+n+" znakov"; + } + }, + formatInputTooLong: function (input, max) { + var n = input.length - max; + if (n == 1) { + return "Prosím zadajte o jeden znak menej"; + } else if (n <= 4) { + return "Prosím zadajte o "+smallNumbers[n](true)+" znaky menej"; + } else { + return "Prosím zadajte o "+n+" znakov menej"; + } + }, + formatSelectionTooBig: function (limit) { + if (limit == 1) { + return "Môžete zvoliÅ¥ len jednu položku"; + } else if (limit <= 4) { + return "Môžete zvoliÅ¥ najviac "+smallNumbers[limit](false)+" položky"; + } else { + return "Môžete zvoliÅ¥ najviac "+limit+" položiek"; + } + }, + formatLoadMore: function (pageNumber) { return "NaÄítavajú sa ÄalÅ¡ie výsledky…"; }, + formatSearching: function () { return "Vyhľadávanie…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_sv.js b/src/static/jquery/select2-3.4.6/select2_locale_sv.js new file mode 100755 index 0000000..d611189 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_sv.js @@ -0,0 +1,17 @@ +/** + * Select2 Swedish translation. + * + * Author: Jens Rantil <jens.rantil@telavox.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Inga träffar"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Var god skriv in " + n + (n>1 ? " till tecken" : " tecken till"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Var god sudda ut " + n + " tecken"; }, + formatSelectionTooBig: function (limit) { return "Du kan max välja " + limit + " element"; }, + formatLoadMore: function (pageNumber) { return "Laddar fler resultat…"; }, + formatSearching: function () { return "Söker…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_th.js b/src/static/jquery/select2-3.4.6/select2_locale_th.js new file mode 100755 index 0000000..df59bda --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_th.js @@ -0,0 +1,17 @@ +/** + * Select2 Thai translation. + * + * Author: Atsawin Chaowanakritsanakul <joke@nakhon.net> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "ไม่พบข้อมูล"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "โปรดพิมพ์เพิ่มอีภ" + n + " ตัวอัà¸à¸©à¸£"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "โปรดลบออภ" + n + " ตัวอัà¸à¸©à¸£"; }, + formatSelectionTooBig: function (limit) { return "คุณสามารถเลือà¸à¹„ด้ไม่เà¸à¸´à¸™ " + limit + " รายà¸à¸²à¸£"; }, + formatLoadMore: function (pageNumber) { return "à¸à¸³à¸¥à¸±à¸‡à¸„้นข้อมูลเพิ่ม…"; }, + formatSearching: function () { return "à¸à¸³à¸¥à¸±à¸‡à¸„้นข้อมูล…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_tr.js b/src/static/jquery/select2-3.4.6/select2_locale_tr.js new file mode 100755 index 0000000..f834dad --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_tr.js @@ -0,0 +1,17 @@ +/** + * Select2 Turkish translation. + * + * Author: Salim KAYABAÅžI <salim.kayabasi@gmail.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Sonuç bulunamadı"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "En az " + n + " karakter daha girmelisiniz"; }, + formatInputTooLong: function (input, max) { var n = input.length - max; return n + " karakter azaltmalısınız"; }, + formatSelectionTooBig: function (limit) { return "Sadece " + limit + " seçim yapabilirsiniz"; }, + formatLoadMore: function (pageNumber) { return "Daha fazla…"; }, + formatSearching: function () { return "Aranıyor…"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_uk.js b/src/static/jquery/select2-3.4.6/select2_locale_uk.js new file mode 100755 index 0000000..6b22e8f --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_uk.js @@ -0,0 +1,22 @@ +/** + * Select2 Ukrainian translation. + * + * @author bigmihail <bigmihail@bigmir.net> + * @author Uriy Efremochkin <efremochkin@uriy.me> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Ðічого не знайдено"; }, + formatInputTooShort: function (input, min) { return "Введіть буль лаÑка ще" + character(min - input.length, "Ñимвол"); }, + formatInputTooLong: function (input, max) { return "Введіть буль лаÑка на" + character(input.length - max, "Ñимвол") + " менше"; }, + formatSelectionTooBig: function (limit) { return "Ви можете вибрати лише" + character(limit, "елемент"); }, + formatLoadMore: function (pageNumber) { return "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ…â€¦"; }, + formatSearching: function () { return "Пошук…"; } + }); + + function character (n, word) { + return " " + n + " " + word + (n%10 < 5 && n%10 > 0 && (n%100 < 5 || n%100 > 19) ? n%10 > 1 ? "и" : "" : "ів"); + } +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_vi.js b/src/static/jquery/select2-3.4.6/select2_locale_vi.js new file mode 100755 index 0000000..5dbc275 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_vi.js @@ -0,0 +1,18 @@ +/** + * Select2 Vietnamese translation. + * + * Author: Long Nguyen <olragon@gmail.com> + */ +(function ($) { + "use strict"; + + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "Không tìm thấy kết quả"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "Vui lòng nhập nhiá»u hÆ¡n " + n + " ký tá»±" + (n == 1 ? "" : "s"); }, + formatInputTooLong: function (input, max) { var n = input.length - max; return "Vui lòng nhập ít hÆ¡n " + n + " ký tá»±" + (n == 1? "" : "s"); }, + formatSelectionTooBig: function (limit) { return "Chỉ có thể chá»n được " + limit + " tùy chá»n" + (limit == 1 ? "" : "s"); }, + formatLoadMore: function (pageNumber) { return "Äang lấy thêm kết quả…"; }, + formatSearching: function () { return "Äang tìm…"; } + }); +})(jQuery); + diff --git a/src/static/jquery/select2-3.4.6/select2_locale_zh-CN.js b/src/static/jquery/select2-3.4.6/select2_locale_zh-CN.js new file mode 100755 index 0000000..6add3c5 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_zh-CN.js @@ -0,0 +1,14 @@ +/** + * Select2 Chinese translation + */ +(function ($) { + "use strict"; + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "没有找到匹é…项"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "请å†è¾“å…¥" + n + "个字符";}, + formatInputTooLong: function (input, max) { var n = input.length - max; return "请删掉" + n + "个字符";}, + formatSelectionTooBig: function (limit) { return "ä½ åªèƒ½é€‰æ‹©æœ€å¤š" + limit + "项"; }, + formatLoadMore: function (pageNumber) { return "加载结果中…"; }, + formatSearching: function () { return "æœç´¢ä¸­â€¦"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2_locale_zh-TW.js b/src/static/jquery/select2-3.4.6/select2_locale_zh-TW.js new file mode 100755 index 0000000..f072381 --- /dev/null +++ b/src/static/jquery/select2-3.4.6/select2_locale_zh-TW.js @@ -0,0 +1,14 @@ +/** + * Select2 Traditional Chinese translation + */ +(function ($) { + "use strict"; + $.extend($.fn.select2.defaults, { + formatNoMatches: function () { return "沒有找到相符的項目"; }, + formatInputTooShort: function (input, min) { var n = min - input.length; return "è«‹å†è¼¸å…¥" + n + "個字元";}, + formatInputTooLong: function (input, max) { var n = input.length - max; return "請刪掉" + n + "個字元";}, + formatSelectionTooBig: function (limit) { return "ä½ åªèƒ½é¸æ“‡æœ€å¤š" + limit + "é …"; }, + formatLoadMore: function (pageNumber) { return "載入中…"; }, + formatSearching: function () { return "æœå°‹ä¸­â€¦"; } + }); +})(jQuery); diff --git a/src/static/jquery/select2-3.4.6/select2x2.png b/src/static/jquery/select2-3.4.6/select2x2.png new file mode 100755 index 0000000000000000000000000000000000000000..4bdd5c961d452c49dfa0789c2c7ffb82c238fc24 GIT binary patch literal 845 zcmV-T1G4;yP)<h;3K|Lk000e1NJLTq004LZ002-31^@s6(wnh~0009NNkl<Zc-rlq zv2GJV5I`eA5ebSzqy-%%f8hdLP~9h_qV^Xci^>upQ6WKflyv?C|ADVW!U!t`EpA+x zB)5#EjWk-_X77YJZtQo`E0SF)^1bZr%<ScI;+%s6=ICz#f&syRU}(wBHJi=KJtvV% z&q1&qv^eJpB{$ANuo1Mlh~(%T1ltp=DYaY#8zmuerN1Ub+fTAw3X&{)g1bmADU*y5 zUblqhl?+n{vw|Hrl|2~9qJcUX=wx*w)_|YxX&9mxeE=mzu0C`g40D>)B7Cd`*OK*r z5WG-7e-R9G9^69ksDt29&oyHqxPSt|-S>xi3%PTd+GjY+BGF|nWC(7D-sd(kxqd9~ zS@2YF5vB+>dP8+$l^{oO3-lEWiGA*QI<ZQyKyWv~v4m^Xqu?O1N>U)Wds#9M6RZ9N zcQ4y4)xqQOxD=vwu%7cz1nY#$lT&y8HCmkWgpwQP#3dhnYj9|2aS_R}IUF_^6s#$= zTm%~>A#oM?KIg$kh=<`gJkeoHa2LrulVy$Yx+N_0R3$4I!R*0677f(FKqm`2_o4~W z0h}fQZ`lC^1A+m;fM7uI(R1`S0KtG@KrkQ}5DW+&@cTnDVIow56KciMk7a899t0bC zC1KI<NAq=n6MhK=f(@YLo(pv#^;)>{TsMe5NAR%GD_5`B-@<p{rSMpIB)k$<!Y=ql zC=fhg{GPi}!nVSD;k03YekgqMb862<$PheS!4oBGC%j9%)a;J%LAX>ad4k~K3SO%H z_M31|`HV?E6)u$E3c&*<*n20+V@mRCop>R5;DWuZCmjSo7p@R&OYl<!6QXYf&j`^5 z2wIX~h5Ie!o(UI9@DjnpE|YYF<D+mlkwJf^OtRPLs6AUR@T@`Z1L2FXRdRPirluiy zpsh;Xe!LWZ2ycXE!VBT8@Kdi`MTuYwhYjIDL;SG8HBchh)^TC22*vJVk`Zj@z<=2w zxbkC}P{t%9`0)R&U5Q}xg42=_Y+Z0#a)n^ig42=_Y+P_C8Nv2R^{Fc*c#2>^@G<ZQ XF(xQ&SEjMs00000NkvXXu0mjf{}FjY literal 0 HcmV?d00001 diff --git a/src/static/jquery/visualsearch-0.5.0/backbone-1.1.0.js b/src/static/jquery/visualsearch-0.5.0/backbone-1.1.0.js new file mode 100755 index 0000000..5963d76 --- /dev/null +++ b/src/static/jquery/visualsearch-0.5.0/backbone-1.1.0.js @@ -0,0 +1,1581 @@ +// Backbone.js 1.1.0 + +// (c) 2010-2011 Jeremy Ashkenas, DocumentCloud Inc. +// (c) 2011-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Backbone may be freely distributed under the MIT license. +// For all details and documentation: +// http://backbonejs.org + +(function(){ + + // Initial Setup + // ------------- + + // Save a reference to the global object (`window` in the browser, `exports` + // on the server). + var root = this; + + // Save the previous value of the `Backbone` variable, so that it can be + // restored later on, if `noConflict` is used. + var previousBackbone = root.Backbone; + + // Create local references to array methods we'll want to use later. + var array = []; + var push = array.push; + var slice = array.slice; + var splice = array.splice; + + // The top-level namespace. All public Backbone classes and modules will + // be attached to this. Exported for both the browser and the server. + var Backbone; + if (typeof exports !== 'undefined') { + Backbone = exports; + } else { + Backbone = root.Backbone = {}; + } + + // Current version of the library. Keep in sync with `package.json`. + Backbone.VERSION = '1.1.0'; + + // Require Underscore, if we're on the server, and it's not already present. + var _ = root._; + if (!_ && (typeof require !== 'undefined')) _ = require('underscore'); + + // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns + // the `$` variable. + Backbone.$ = root.jQuery || root.Zepto || root.ender || root.$; + + // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable + // to its previous owner. Returns a reference to this Backbone object. + Backbone.noConflict = function() { + root.Backbone = previousBackbone; + return this; + }; + + // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option + // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and + // set a `X-Http-Method-Override` header. + Backbone.emulateHTTP = false; + + // Turn on `emulateJSON` to support legacy servers that can't deal with direct + // `application/json` requests ... will encode the body as + // `application/x-www-form-urlencoded` instead and will send the model in a + // form param named `model`. + Backbone.emulateJSON = false; + + // Backbone.Events + // --------------- + + // A module that can be mixed in to *any object* in order to provide it with + // custom events. You may bind with `on` or remove with `off` callback + // functions to an event; `trigger`-ing an event fires all callbacks in + // succession. + // + // var object = {}; + // _.extend(object, Backbone.Events); + // object.on('expand', function(){ alert('expanded'); }); + // object.trigger('expand'); + // + var Events = Backbone.Events = { + + // Bind an event to a `callback` function. Passing `"all"` will bind + // the callback to all events fired. + on: function(name, callback, context) { + if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this; + this._events || (this._events = {}); + var events = this._events[name] || (this._events[name] = []); + events.push({callback: callback, context: context, ctx: context || this}); + return this; + }, + + // Bind an event to only be triggered a single time. After the first time + // the callback is invoked, it will be removed. + once: function(name, callback, context) { + if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this; + var self = this; + var once = _.once(function() { + self.off(name, once); + callback.apply(this, arguments); + }); + once._callback = callback; + return this.on(name, once, context); + }, + + // Remove one or many callbacks. If `context` is null, removes all + // callbacks with that function. If `callback` is null, removes all + // callbacks for the event. If `name` is null, removes all bound + // callbacks for all events. + off: function(name, callback, context) { + var retain, ev, events, names, i, l, j, k; + if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; + if (!name && !callback && !context) { + this._events = {}; + return this; + } + names = name ? [name] : _.keys(this._events); + for (i = 0, l = names.length; i < l; i++) { + name = names[i]; + if (events = this._events[name]) { + this._events[name] = retain = []; + if (callback || context) { + for (j = 0, k = events.length; j < k; j++) { + ev = events[j]; + if ((callback && callback !== ev.callback && callback !== ev.callback._callback) || + (context && context !== ev.context)) { + retain.push(ev); + } + } + } + if (!retain.length) delete this._events[name]; + } + } + + return this; + }, + + // Trigger one or many events, firing all bound callbacks. Callbacks are + // passed the same arguments as `trigger` is, apart from the event name + // (unless you're listening on `"all"`, which will cause your callback to + // receive the true name of the event as the first argument). + trigger: function(name) { + if (!this._events) return this; + var args = slice.call(arguments, 1); + if (!eventsApi(this, 'trigger', name, args)) return this; + var events = this._events[name]; + var allEvents = this._events.all; + if (events) triggerEvents(events, args); + if (allEvents) triggerEvents(allEvents, arguments); + return this; + }, + + // Tell this object to stop listening to either specific events ... or + // to every object it's currently listening to. + stopListening: function(obj, name, callback) { + var listeningTo = this._listeningTo; + if (!listeningTo) return this; + var remove = !name && !callback; + if (!callback && typeof name === 'object') callback = this; + if (obj) (listeningTo = {})[obj._listenId] = obj; + for (var id in listeningTo) { + obj = listeningTo[id]; + obj.off(name, callback, this); + if (remove || _.isEmpty(obj._events)) delete this._listeningTo[id]; + } + return this; + } + + }; + + // Regular expression used to split event strings. + var eventSplitter = /\s+/; + + // Implement fancy features of the Events API such as multiple event + // names `"change blur"` and jQuery-style event maps `{change: action}` + // in terms of the existing API. + var eventsApi = function(obj, action, name, rest) { + if (!name) return true; + + // Handle event maps. + if (typeof name === 'object') { + for (var key in name) { + obj[action].apply(obj, [key, name[key]].concat(rest)); + } + return false; + } + + // Handle space separated event names. + if (eventSplitter.test(name)) { + var names = name.split(eventSplitter); + for (var i = 0, l = names.length; i < l; i++) { + obj[action].apply(obj, [names[i]].concat(rest)); + } + return false; + } + + return true; + }; + + // A difficult-to-believe, but optimized internal dispatch function for + // triggering events. Tries to keep the usual cases speedy (most internal + // Backbone events have 3 arguments). + var triggerEvents = function(events, args) { + var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; + switch (args.length) { + case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; + case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return; + case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return; + case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return; + default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); + } + }; + + var listenMethods = {listenTo: 'on', listenToOnce: 'once'}; + + // Inversion-of-control versions of `on` and `once`. Tell *this* object to + // listen to an event in another object ... keeping track of what it's + // listening to. + _.each(listenMethods, function(implementation, method) { + Events[method] = function(obj, name, callback) { + var listeningTo = this._listeningTo || (this._listeningTo = {}); + var id = obj._listenId || (obj._listenId = _.uniqueId('l')); + listeningTo[id] = obj; + if (!callback && typeof name === 'object') callback = this; + obj[implementation](name, callback, this); + return this; + }; + }); + + // Aliases for backwards compatibility. + Events.bind = Events.on; + Events.unbind = Events.off; + + // Allow the `Backbone` object to serve as a global event bus, for folks who + // want global "pubsub" in a convenient place. + _.extend(Backbone, Events); + + // Backbone.Model + // -------------- + + // Backbone **Models** are the basic data object in the framework -- + // frequently representing a row in a table in a database on your server. + // A discrete chunk of data and a bunch of useful, related methods for + // performing computations and transformations on that data. + + // Create a new model with the specified attributes. A client id (`cid`) + // is automatically generated and assigned for you. + var Model = Backbone.Model = function(attributes, options) { + var attrs = attributes || {}; + options || (options = {}); + this.cid = _.uniqueId('c'); + this.attributes = {}; + if (options.collection) this.collection = options.collection; + if (options.parse) attrs = this.parse(attrs, options) || {}; + attrs = _.defaults({}, attrs, _.result(this, 'defaults')); + this.set(attrs, options); + this.changed = {}; + this.initialize.apply(this, arguments); + }; + + // Attach all inheritable methods to the Model prototype. + _.extend(Model.prototype, Events, { + + // A hash of attributes whose current and previous value differ. + changed: null, + + // The value returned during the last failed validation. + validationError: null, + + // The default name for the JSON `id` attribute is `"id"`. MongoDB and + // CouchDB users may want to set this to `"_id"`. + idAttribute: 'id', + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // Return a copy of the model's `attributes` object. + toJSON: function(options) { + return _.clone(this.attributes); + }, + + // Proxy `Backbone.sync` by default -- but override this if you need + // custom syncing semantics for *this* particular model. + sync: function() { + return Backbone.sync.apply(this, arguments); + }, + + // Get the value of an attribute. + get: function(attr) { + return this.attributes[attr]; + }, + + // Get the HTML-escaped value of an attribute. + escape: function(attr) { + return _.escape(this.get(attr)); + }, + + // Returns `true` if the attribute contains a value that is not null + // or undefined. + has: function(attr) { + return this.get(attr) != null; + }, + + // Set a hash of model attributes on the object, firing `"change"`. This is + // the core primitive operation of a model, updating the data and notifying + // anyone who needs to know about the change in state. The heart of the beast. + set: function(key, val, options) { + var attr, attrs, unset, changes, silent, changing, prev, current; + if (key == null) return this; + + // Handle both `"key", value` and `{key: value}` -style arguments. + if (typeof key === 'object') { + attrs = key; + options = val; + } else { + (attrs = {})[key] = val; + } + + options || (options = {}); + + // Run validation. + if (!this._validate(attrs, options)) return false; + + // Extract attributes and options. + unset = options.unset; + silent = options.silent; + changes = []; + changing = this._changing; + this._changing = true; + + if (!changing) { + this._previousAttributes = _.clone(this.attributes); + this.changed = {}; + } + current = this.attributes, prev = this._previousAttributes; + + // Check for changes of `id`. + if (this.idAttribute in attrs) this.id = attrs[this.idAttribute]; + + // For each `set` attribute, update or delete the current value. + for (attr in attrs) { + val = attrs[attr]; + if (!_.isEqual(current[attr], val)) changes.push(attr); + if (!_.isEqual(prev[attr], val)) { + this.changed[attr] = val; + } else { + delete this.changed[attr]; + } + unset ? delete current[attr] : current[attr] = val; + } + + // Trigger all relevant attribute changes. + if (!silent) { + if (changes.length) this._pending = true; + for (var i = 0, l = changes.length; i < l; i++) { + this.trigger('change:' + changes[i], this, current[changes[i]], options); + } + } + + // You might be wondering why there's a `while` loop here. Changes can + // be recursively nested within `"change"` events. + if (changing) return this; + if (!silent) { + while (this._pending) { + this._pending = false; + this.trigger('change', this, options); + } + } + this._pending = false; + this._changing = false; + return this; + }, + + // Remove an attribute from the model, firing `"change"`. `unset` is a noop + // if the attribute doesn't exist. + unset: function(attr, options) { + return this.set(attr, void 0, _.extend({}, options, {unset: true})); + }, + + // Clear all attributes on the model, firing `"change"`. + clear: function(options) { + var attrs = {}; + for (var key in this.attributes) attrs[key] = void 0; + return this.set(attrs, _.extend({}, options, {unset: true})); + }, + + // Determine if the model has changed since the last `"change"` event. + // If you specify an attribute name, determine if that attribute has changed. + hasChanged: function(attr) { + if (attr == null) return !_.isEmpty(this.changed); + return _.has(this.changed, attr); + }, + + // Return an object containing all the attributes that have changed, or + // false if there are no changed attributes. Useful for determining what + // parts of a view need to be updated and/or what attributes need to be + // persisted to the server. Unset attributes will be set to undefined. + // You can also pass an attributes object to diff against the model, + // determining if there *would be* a change. + changedAttributes: function(diff) { + if (!diff) return this.hasChanged() ? _.clone(this.changed) : false; + var val, changed = false; + var old = this._changing ? this._previousAttributes : this.attributes; + for (var attr in diff) { + if (_.isEqual(old[attr], (val = diff[attr]))) continue; + (changed || (changed = {}))[attr] = val; + } + return changed; + }, + + // Get the previous value of an attribute, recorded at the time the last + // `"change"` event was fired. + previous: function(attr) { + if (attr == null || !this._previousAttributes) return null; + return this._previousAttributes[attr]; + }, + + // Get all of the attributes of the model at the time of the previous + // `"change"` event. + previousAttributes: function() { + return _.clone(this._previousAttributes); + }, + + // Fetch the model from the server. If the server's representation of the + // model differs from its current attributes, they will be overridden, + // triggering a `"change"` event. + fetch: function(options) { + options = options ? _.clone(options) : {}; + if (options.parse === void 0) options.parse = true; + var model = this; + var success = options.success; + options.success = function(resp) { + if (!model.set(model.parse(resp, options), options)) return false; + if (success) success(model, resp, options); + model.trigger('sync', model, resp, options); + }; + wrapError(this, options); + return this.sync('read', this, options); + }, + + // Set a hash of model attributes, and sync the model to the server. + // If the server returns an attributes hash that differs, the model's + // state will be `set` again. + save: function(key, val, options) { + var attrs, method, xhr, attributes = this.attributes; + + // Handle both `"key", value` and `{key: value}` -style arguments. + if (key == null || typeof key === 'object') { + attrs = key; + options = val; + } else { + (attrs = {})[key] = val; + } + + options = _.extend({validate: true}, options); + + // If we're not waiting and attributes exist, save acts as + // `set(attr).save(null, opts)` with validation. Otherwise, check if + // the model will be valid when the attributes, if any, are set. + if (attrs && !options.wait) { + if (!this.set(attrs, options)) return false; + } else { + if (!this._validate(attrs, options)) return false; + } + + // Set temporary attributes if `{wait: true}`. + if (attrs && options.wait) { + this.attributes = _.extend({}, attributes, attrs); + } + + // After a successful server-side save, the client is (optionally) + // updated with the server-side state. + if (options.parse === void 0) options.parse = true; + var model = this; + var success = options.success; + options.success = function(resp) { + // Ensure attributes are restored during synchronous saves. + model.attributes = attributes; + var serverAttrs = model.parse(resp, options); + if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs); + if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) { + return false; + } + if (success) success(model, resp, options); + model.trigger('sync', model, resp, options); + }; + wrapError(this, options); + + method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update'); + if (method === 'patch') options.attrs = attrs; + xhr = this.sync(method, this, options); + + // Restore attributes. + if (attrs && options.wait) this.attributes = attributes; + + return xhr; + }, + + // Destroy this model on the server if it was already persisted. + // Optimistically removes the model from its collection, if it has one. + // If `wait: true` is passed, waits for the server to respond before removal. + destroy: function(options) { + options = options ? _.clone(options) : {}; + var model = this; + var success = options.success; + + var destroy = function() { + model.trigger('destroy', model, model.collection, options); + }; + + options.success = function(resp) { + if (options.wait || model.isNew()) destroy(); + if (success) success(model, resp, options); + if (!model.isNew()) model.trigger('sync', model, resp, options); + }; + + if (this.isNew()) { + options.success(); + return false; + } + wrapError(this, options); + + var xhr = this.sync('delete', this, options); + if (!options.wait) destroy(); + return xhr; + }, + + // Default URL for the model's representation on the server -- if you're + // using Backbone's restful methods, override this to change the endpoint + // that will be called. + url: function() { + var base = _.result(this, 'urlRoot') || _.result(this.collection, 'url') || urlError(); + if (this.isNew()) return base; + return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id); + }, + + // **parse** converts a response into the hash of attributes to be `set` on + // the model. The default implementation is just to pass the response along. + parse: function(resp, options) { + return resp; + }, + + // Create a new model with identical attributes to this one. + clone: function() { + return new this.constructor(this.attributes); + }, + + // A model is new if it has never been saved to the server, and lacks an id. + isNew: function() { + return this.id == null; + }, + + // Check if the model is currently in a valid state. + isValid: function(options) { + return this._validate({}, _.extend(options || {}, { validate: true })); + }, + + // Run validation against the next complete set of model attributes, + // returning `true` if all is well. Otherwise, fire an `"invalid"` event. + _validate: function(attrs, options) { + if (!options.validate || !this.validate) return true; + attrs = _.extend({}, this.attributes, attrs); + var error = this.validationError = this.validate(attrs, options) || null; + if (!error) return true; + this.trigger('invalid', this, error, _.extend(options, {validationError: error})); + return false; + } + + }); + + // Underscore methods that we want to implement on the Model. + var modelMethods = ['keys', 'values', 'pairs', 'invert', 'pick', 'omit']; + + // Mix in each Underscore method as a proxy to `Model#attributes`. + _.each(modelMethods, function(method) { + Model.prototype[method] = function() { + var args = slice.call(arguments); + args.unshift(this.attributes); + return _[method].apply(_, args); + }; + }); + + // Backbone.Collection + // ------------------- + + // If models tend to represent a single row of data, a Backbone Collection is + // more analagous to a table full of data ... or a small slice or page of that + // table, or a collection of rows that belong together for a particular reason + // -- all of the messages in this particular folder, all of the documents + // belonging to this particular author, and so on. Collections maintain + // indexes of their models, both in order, and for lookup by `id`. + + // Create a new **Collection**, perhaps to contain a specific type of `model`. + // If a `comparator` is specified, the Collection will maintain + // its models in sort order, as they're added and removed. + var Collection = Backbone.Collection = function(models, options) { + options || (options = {}); + if (options.model) this.model = options.model; + if (options.comparator !== void 0) this.comparator = options.comparator; + this._reset(); + this.initialize.apply(this, arguments); + if (models) this.reset(models, _.extend({silent: true}, options)); + }; + + // Default options for `Collection#set`. + var setOptions = {add: true, remove: true, merge: true}; + var addOptions = {add: true, remove: false}; + + // Define the Collection's inheritable methods. + _.extend(Collection.prototype, Events, { + + // The default model for a collection is just a **Backbone.Model**. + // This should be overridden in most cases. + model: Model, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // The JSON representation of a Collection is an array of the + // models' attributes. + toJSON: function(options) { + return this.map(function(model){ return model.toJSON(options); }); + }, + + // Proxy `Backbone.sync` by default. + sync: function() { + return Backbone.sync.apply(this, arguments); + }, + + // Add a model, or list of models to the set. + add: function(models, options) { + return this.set(models, _.extend({merge: false}, options, addOptions)); + }, + + // Remove a model, or a list of models from the set. + remove: function(models, options) { + var singular = !_.isArray(models); + models = singular ? [models] : _.clone(models); + options || (options = {}); + var i, l, index, model; + for (i = 0, l = models.length; i < l; i++) { + model = models[i] = this.get(models[i]); + if (!model) continue; + delete this._byId[model.id]; + delete this._byId[model.cid]; + index = this.indexOf(model); + this.models.splice(index, 1); + this.length--; + if (!options.silent) { + options.index = index; + model.trigger('remove', model, this, options); + } + this._removeReference(model); + } + return singular ? models[0] : models; + }, + + // Update a collection by `set`-ing a new list of models, adding new ones, + // removing models that are no longer present, and merging models that + // already exist in the collection, as necessary. Similar to **Model#set**, + // the core operation for updating the data contained by the collection. + set: function(models, options) { + options = _.defaults({}, options, setOptions); + if (options.parse) models = this.parse(models, options); + var singular = !_.isArray(models); + models = singular ? (models ? [models] : []) : _.clone(models); + var i, l, id, model, attrs, existing, sort; + var at = options.at; + var targetModel = this.model; + var sortable = this.comparator && (at == null) && options.sort !== false; + var sortAttr = _.isString(this.comparator) ? this.comparator : null; + var toAdd = [], toRemove = [], modelMap = {}; + var add = options.add, merge = options.merge, remove = options.remove; + var order = !sortable && add && remove ? [] : false; + + // Turn bare objects into model references, and prevent invalid models + // from being added. + for (i = 0, l = models.length; i < l; i++) { + attrs = models[i]; + if (attrs instanceof Model) { + id = model = attrs; + } else { + id = attrs[targetModel.prototype.idAttribute]; + } + + // If a duplicate is found, prevent it from being added and + // optionally merge it into the existing model. + if (existing = this.get(id)) { + if (remove) modelMap[existing.cid] = true; + if (merge) { + attrs = attrs === model ? model.attributes : attrs; + if (options.parse) attrs = existing.parse(attrs, options); + existing.set(attrs, options); + if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true; + } + models[i] = existing; + + // If this is a new, valid model, push it to the `toAdd` list. + } else if (add) { + model = models[i] = this._prepareModel(attrs, options); + if (!model) continue; + toAdd.push(model); + + // Listen to added models' events, and index models for lookup by + // `id` and by `cid`. + model.on('all', this._onModelEvent, this); + this._byId[model.cid] = model; + if (model.id != null) this._byId[model.id] = model; + } + if (order) order.push(existing || model); + } + + // Remove nonexistent models if appropriate. + if (remove) { + for (i = 0, l = this.length; i < l; ++i) { + if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model); + } + if (toRemove.length) this.remove(toRemove, options); + } + + // See if sorting is needed, update `length` and splice in new models. + if (toAdd.length || (order && order.length)) { + if (sortable) sort = true; + this.length += toAdd.length; + if (at != null) { + for (i = 0, l = toAdd.length; i < l; i++) { + this.models.splice(at + i, 0, toAdd[i]); + } + } else { + if (order) this.models.length = 0; + var orderedModels = order || toAdd; + for (i = 0, l = orderedModels.length; i < l; i++) { + this.models.push(orderedModels[i]); + } + } + } + + // Silently sort the collection if appropriate. + if (sort) this.sort({silent: true}); + + // Unless silenced, it's time to fire all appropriate add/sort events. + if (!options.silent) { + for (i = 0, l = toAdd.length; i < l; i++) { + (model = toAdd[i]).trigger('add', model, this, options); + } + if (sort || (order && order.length)) this.trigger('sort', this, options); + } + + // Return the added (or merged) model (or models). + return singular ? models[0] : models; + }, + + // When you have more items than you want to add or remove individually, + // you can reset the entire set with a new list of models, without firing + // any granular `add` or `remove` events. Fires `reset` when finished. + // Useful for bulk operations and optimizations. + reset: function(models, options) { + options || (options = {}); + for (var i = 0, l = this.models.length; i < l; i++) { + this._removeReference(this.models[i]); + } + options.previousModels = this.models; + this._reset(); + models = this.add(models, _.extend({silent: true}, options)); + if (!options.silent) this.trigger('reset', this, options); + return models; + }, + + // Add a model to the end of the collection. + push: function(model, options) { + return this.add(model, _.extend({at: this.length}, options)); + }, + + // Remove a model from the end of the collection. + pop: function(options) { + var model = this.at(this.length - 1); + this.remove(model, options); + return model; + }, + + // Add a model to the beginning of the collection. + unshift: function(model, options) { + return this.add(model, _.extend({at: 0}, options)); + }, + + // Remove a model from the beginning of the collection. + shift: function(options) { + var model = this.at(0); + this.remove(model, options); + return model; + }, + + // Slice out a sub-array of models from the collection. + slice: function() { + return slice.apply(this.models, arguments); + }, + + // Get a model from the set by id. + get: function(obj) { + if (obj == null) return void 0; + return this._byId[obj.id] || this._byId[obj.cid] || this._byId[obj]; + }, + + // Get the model at the given index. + at: function(index) { + return this.models[index]; + }, + + // Return models with matching attributes. Useful for simple cases of + // `filter`. + where: function(attrs, first) { + if (_.isEmpty(attrs)) return first ? void 0 : []; + return this[first ? 'find' : 'filter'](function(model) { + for (var key in attrs) { + if (attrs[key] !== model.get(key)) return false; + } + return true; + }); + }, + + // Return the first model with matching attributes. Useful for simple cases + // of `find`. + findWhere: function(attrs) { + return this.where(attrs, true); + }, + + // Force the collection to re-sort itself. You don't need to call this under + // normal circumstances, as the set will maintain sort order as each item + // is added. + sort: function(options) { + if (!this.comparator) throw new Error('Cannot sort a set without a comparator'); + options || (options = {}); + + // Run sort based on type of `comparator`. + if (_.isString(this.comparator) || this.comparator.length === 1) { + this.models = this.sortBy(this.comparator, this); + } else { + this.models.sort(_.bind(this.comparator, this)); + } + + if (!options.silent) this.trigger('sort', this, options); + return this; + }, + + // Pluck an attribute from each model in the collection. + pluck: function(attr) { + return _.invoke(this.models, 'get', attr); + }, + + // Fetch the default set of models for this collection, resetting the + // collection when they arrive. If `reset: true` is passed, the response + // data will be passed through the `reset` method instead of `set`. + fetch: function(options) { + options = options ? _.clone(options) : {}; + if (options.parse === void 0) options.parse = true; + var success = options.success; + var collection = this; + options.success = function(resp) { + var method = options.reset ? 'reset' : 'set'; + collection[method](resp, options); + if (success) success(collection, resp, options); + collection.trigger('sync', collection, resp, options); + }; + wrapError(this, options); + return this.sync('read', this, options); + }, + + // Create a new instance of a model in this collection. Add the model to the + // collection immediately, unless `wait: true` is passed, in which case we + // wait for the server to agree. + create: function(model, options) { + options = options ? _.clone(options) : {}; + if (!(model = this._prepareModel(model, options))) return false; + if (!options.wait) this.add(model, options); + var collection = this; + var success = options.success; + options.success = function(model, resp, options) { + if (options.wait) collection.add(model, options); + if (success) success(model, resp, options); + }; + model.save(null, options); + return model; + }, + + // **parse** converts a response into a list of models to be added to the + // collection. The default implementation is just to pass it through. + parse: function(resp, options) { + return resp; + }, + + // Create a new collection with an identical list of models as this one. + clone: function() { + return new this.constructor(this.models); + }, + + // Private method to reset all internal state. Called when the collection + // is first initialized or reset. + _reset: function() { + this.length = 0; + this.models = []; + this._byId = {}; + }, + + // Prepare a hash of attributes (or other model) to be added to this + // collection. + _prepareModel: function(attrs, options) { + if (attrs instanceof Model) { + if (!attrs.collection) attrs.collection = this; + return attrs; + } + options = options ? _.clone(options) : {}; + options.collection = this; + var model = new this.model(attrs, options); + if (!model.validationError) return model; + this.trigger('invalid', this, model.validationError, options); + return false; + }, + + // Internal method to sever a model's ties to a collection. + _removeReference: function(model) { + if (this === model.collection) delete model.collection; + model.off('all', this._onModelEvent, this); + }, + + // Internal method called every time a model in the set fires an event. + // Sets need to update their indexes when models change ids. All other + // events simply proxy through. "add" and "remove" events that originate + // in other collections are ignored. + _onModelEvent: function(event, model, collection, options) { + if ((event === 'add' || event === 'remove') && collection !== this) return; + if (event === 'destroy') this.remove(model, options); + if (model && event === 'change:' + model.idAttribute) { + delete this._byId[model.previous(model.idAttribute)]; + if (model.id != null) this._byId[model.id] = model; + } + this.trigger.apply(this, arguments); + } + + }); + + // Underscore methods that we want to implement on the Collection. + // 90% of the core usefulness of Backbone Collections is actually implemented + // right here: + var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl', + 'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select', + 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke', + 'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest', + 'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle', + 'lastIndexOf', 'isEmpty', 'chain']; + + // Mix in each Underscore method as a proxy to `Collection#models`. + _.each(methods, function(method) { + Collection.prototype[method] = function() { + var args = slice.call(arguments); + args.unshift(this.models); + return _[method].apply(_, args); + }; + }); + + // Underscore methods that take a property name as an argument. + var attributeMethods = ['groupBy', 'countBy', 'sortBy']; + + // Use attributes instead of properties. + _.each(attributeMethods, function(method) { + Collection.prototype[method] = function(value, context) { + var iterator = _.isFunction(value) ? value : function(model) { + return model.get(value); + }; + return _[method](this.models, iterator, context); + }; + }); + + // Backbone.View + // ------------- + + // Backbone Views are almost more convention than they are actual code. A View + // is simply a JavaScript object that represents a logical chunk of UI in the + // DOM. This might be a single item, an entire list, a sidebar or panel, or + // even the surrounding frame which wraps your whole app. Defining a chunk of + // UI as a **View** allows you to define your DOM events declaratively, without + // having to worry about render order ... and makes it easy for the view to + // react to specific changes in the state of your models. + + // Creating a Backbone.View creates its initial element outside of the DOM, + // if an existing element is not provided... + var View = Backbone.View = function(options) { + this.cid = _.uniqueId('view'); + options || (options = {}); + _.extend(this, _.pick(options, viewOptions)); + this._ensureElement(); + this.initialize.apply(this, arguments); + this.delegateEvents(); + }; + + // Cached regex to split keys for `delegate`. + var delegateEventSplitter = /^(\S+)\s*(.*)$/; + + // List of view options to be merged as properties. + var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events']; + + // Set up all inheritable **Backbone.View** properties and methods. + _.extend(View.prototype, Events, { + + // The default `tagName` of a View's element is `"div"`. + tagName: 'div', + + // jQuery delegate for element lookup, scoped to DOM elements within the + // current view. This should be preferred to global lookups where possible. + $: function(selector) { + return this.$el.find(selector); + }, + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // **render** is the core function that your view should override, in order + // to populate its element (`this.el`), with the appropriate HTML. The + // convention is for **render** to always return `this`. + render: function() { + return this; + }, + + // Remove this view by taking the element out of the DOM, and removing any + // applicable Backbone.Events listeners. + remove: function() { + this.$el.remove(); + this.stopListening(); + return this; + }, + + // Change the view's element (`this.el` property), including event + // re-delegation. + setElement: function(element, delegate) { + if (this.$el) this.undelegateEvents(); + this.$el = element instanceof Backbone.$ ? element : Backbone.$(element); + this.el = this.$el[0]; + if (delegate !== false) this.delegateEvents(); + return this; + }, + + // Set callbacks, where `this.events` is a hash of + // + // *{"event selector": "callback"}* + // + // { + // 'mousedown .title': 'edit', + // 'click .button': 'save', + // 'click .open': function(e) { ... } + // } + // + // pairs. Callbacks will be bound to the view, with `this` set properly. + // Uses event delegation for efficiency. + // Omitting the selector binds the event to `this.el`. + // This only works for delegate-able events: not `focus`, `blur`, and + // not `change`, `submit`, and `reset` in Internet Explorer. + delegateEvents: function(events) { + if (!(events || (events = _.result(this, 'events')))) return this; + this.undelegateEvents(); + for (var key in events) { + var method = events[key]; + if (!_.isFunction(method)) method = this[events[key]]; + if (!method) continue; + + var match = key.match(delegateEventSplitter); + var eventName = match[1], selector = match[2]; + method = _.bind(method, this); + eventName += '.delegateEvents' + this.cid; + if (selector === '') { + this.$el.on(eventName, method); + } else { + this.$el.on(eventName, selector, method); + } + } + return this; + }, + + // Clears all callbacks previously bound to the view with `delegateEvents`. + // You usually don't need to use this, but may wish to if you have multiple + // Backbone views attached to the same DOM element. + undelegateEvents: function() { + this.$el.off('.delegateEvents' + this.cid); + return this; + }, + + // Ensure that the View has a DOM element to render into. + // If `this.el` is a string, pass it through `$()`, take the first + // matching element, and re-assign it to `el`. Otherwise, create + // an element from the `id`, `className` and `tagName` properties. + _ensureElement: function() { + if (!this.el) { + var attrs = _.extend({}, _.result(this, 'attributes')); + if (this.id) attrs.id = _.result(this, 'id'); + if (this.className) attrs['class'] = _.result(this, 'className'); + var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs); + this.setElement($el, false); + } else { + this.setElement(_.result(this, 'el'), false); + } + } + + }); + + // Backbone.sync + // ------------- + + // Override this function to change the manner in which Backbone persists + // models to the server. You will be passed the type of request, and the + // model in question. By default, makes a RESTful Ajax request + // to the model's `url()`. Some possible customizations could be: + // + // * Use `setTimeout` to batch rapid-fire updates into a single request. + // * Send up the models as XML instead of JSON. + // * Persist models via WebSockets instead of Ajax. + // + // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests + // as `POST`, with a `_method` parameter containing the true HTTP method, + // as well as all requests with the body as `application/x-www-form-urlencoded` + // instead of `application/json` with the model in a param named `model`. + // Useful when interfacing with server-side languages like **PHP** that make + // it difficult to read the body of `PUT` requests. + Backbone.sync = function(method, model, options) { + var type = methodMap[method]; + + // Default options, unless specified. + _.defaults(options || (options = {}), { + emulateHTTP: Backbone.emulateHTTP, + emulateJSON: Backbone.emulateJSON + }); + + // Default JSON-request options. + var params = {type: type, dataType: 'json'}; + + // Ensure that we have a URL. + if (!options.url) { + params.url = _.result(model, 'url') || urlError(); + } + + // Ensure that we have the appropriate request data. + if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { + params.contentType = 'application/json'; + params.data = JSON.stringify(options.attrs || model.toJSON(options)); + } + + // For older servers, emulate JSON by encoding the request into an HTML-form. + if (options.emulateJSON) { + params.contentType = 'application/x-www-form-urlencoded'; + params.data = params.data ? {model: params.data} : {}; + } + + // For older servers, emulate HTTP by mimicking the HTTP method with `_method` + // And an `X-HTTP-Method-Override` header. + if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) { + params.type = 'POST'; + if (options.emulateJSON) params.data._method = type; + var beforeSend = options.beforeSend; + options.beforeSend = function(xhr) { + xhr.setRequestHeader('X-HTTP-Method-Override', type); + if (beforeSend) return beforeSend.apply(this, arguments); + }; + } + + // Don't process data on a non-GET request. + if (params.type !== 'GET' && !options.emulateJSON) { + params.processData = false; + } + + // If we're sending a `PATCH` request, and we're in an old Internet Explorer + // that still has ActiveX enabled by default, override jQuery to use that + // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8. + if (params.type === 'PATCH' && noXhrPatch) { + params.xhr = function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + }; + } + + // Make the request, allowing the user to override any Ajax options. + var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); + model.trigger('request', model, xhr, options); + return xhr; + }; + + var noXhrPatch = typeof window !== 'undefined' && !!window.ActiveXObject && !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent); + + // Map from CRUD to HTTP for our default `Backbone.sync` implementation. + var methodMap = { + 'create': 'POST', + 'update': 'PUT', + 'patch': 'PATCH', + 'delete': 'DELETE', + 'read': 'GET' + }; + + // Set the default implementation of `Backbone.ajax` to proxy through to `$`. + // Override this if you'd like to use a different library. + Backbone.ajax = function() { + return Backbone.$.ajax.apply(Backbone.$, arguments); + }; + + // Backbone.Router + // --------------- + + // Routers map faux-URLs to actions, and fire events when routes are + // matched. Creating a new one sets its `routes` hash, if not set statically. + var Router = Backbone.Router = function(options) { + options || (options = {}); + if (options.routes) this.routes = options.routes; + this._bindRoutes(); + this.initialize.apply(this, arguments); + }; + + // Cached regular expressions for matching named param parts and splatted + // parts of route strings. + var optionalParam = /\((.*?)\)/g; + var namedParam = /(\(\?)?:\w+/g; + var splatParam = /\*\w+/g; + var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; + + // Set up all inheritable **Backbone.Router** properties and methods. + _.extend(Router.prototype, Events, { + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // Manually bind a single named route to a callback. For example: + // + // this.route('search/:query/p:num', 'search', function(query, num) { + // ... + // }); + // + route: function(route, name, callback) { + if (!_.isRegExp(route)) route = this._routeToRegExp(route); + if (_.isFunction(name)) { + callback = name; + name = ''; + } + if (!callback) callback = this[name]; + var router = this; + Backbone.history.route(route, function(fragment) { + var args = router._extractParameters(route, fragment); + callback && callback.apply(router, args); + router.trigger.apply(router, ['route:' + name].concat(args)); + router.trigger('route', name, args); + Backbone.history.trigger('route', router, name, args); + }); + return this; + }, + + // Simple proxy to `Backbone.history` to save a fragment into the history. + navigate: function(fragment, options) { + Backbone.history.navigate(fragment, options); + return this; + }, + + // Bind all defined routes to `Backbone.history`. We have to reverse the + // order of the routes here to support behavior where the most general + // routes can be defined at the bottom of the route map. + _bindRoutes: function() { + if (!this.routes) return; + this.routes = _.result(this, 'routes'); + var route, routes = _.keys(this.routes); + while ((route = routes.pop()) != null) { + this.route(route, this.routes[route]); + } + }, + + // Convert a route string into a regular expression, suitable for matching + // against the current location hash. + _routeToRegExp: function(route) { + route = route.replace(escapeRegExp, '\\$&') + .replace(optionalParam, '(?:$1)?') + .replace(namedParam, function(match, optional) { + return optional ? match : '([^\/]+)'; + }) + .replace(splatParam, '(.*?)'); + return new RegExp('^' + route + '$'); + }, + + // Given a route, and a URL fragment that it matches, return the array of + // extracted decoded parameters. Empty or unmatched parameters will be + // treated as `null` to normalize cross-browser behavior. + _extractParameters: function(route, fragment) { + var params = route.exec(fragment).slice(1); + return _.map(params, function(param) { + return param ? decodeURIComponent(param) : null; + }); + } + + }); + + // Backbone.History + // ---------------- + + // Handles cross-browser history management, based on either + // [pushState](http://diveintohtml5.info/history.html) and real URLs, or + // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange) + // and URL fragments. If the browser supports neither (old IE, natch), + // falls back to polling. + var History = Backbone.History = function() { + this.handlers = []; + _.bindAll(this, 'checkUrl'); + + // Ensure that `History` can be used outside of the browser. + if (typeof window !== 'undefined') { + this.location = window.location; + this.history = window.history; + } + }; + + // Cached regex for stripping a leading hash/slash and trailing space. + var routeStripper = /^[#\/]|\s+$/g; + + // Cached regex for stripping leading and trailing slashes. + var rootStripper = /^\/+|\/+$/g; + + // Cached regex for detecting MSIE. + var isExplorer = /msie [\w.]+/; + + // Cached regex for removing a trailing slash. + var trailingSlash = /\/$/; + + // Cached regex for stripping urls of hash and query. + var pathStripper = /[?#].*$/; + + // Has the history handling already been started? + History.started = false; + + // Set up all inheritable **Backbone.History** properties and methods. + _.extend(History.prototype, Events, { + + // The default interval to poll for hash changes, if necessary, is + // twenty times a second. + interval: 50, + + // Gets the true hash value. Cannot use location.hash directly due to bug + // in Firefox where location.hash will always be decoded. + getHash: function(window) { + var match = (window || this).location.href.match(/#(.*)$/); + return match ? match[1] : ''; + }, + + // Get the cross-browser normalized URL fragment, either from the URL, + // the hash, or the override. + getFragment: function(fragment, forcePushState) { + if (fragment == null) { + if (this._hasPushState || !this._wantsHashChange || forcePushState) { + fragment = this.location.pathname; + var root = this.root.replace(trailingSlash, ''); + if (!fragment.indexOf(root)) fragment = fragment.slice(root.length); + } else { + fragment = this.getHash(); + } + } + return fragment.replace(routeStripper, ''); + }, + + // Start the hash change handling, returning `true` if the current URL matches + // an existing route, and `false` otherwise. + start: function(options) { + if (History.started) throw new Error("Backbone.history has already been started"); + History.started = true; + + // Figure out the initial configuration. Do we need an iframe? + // Is pushState desired ... is it available? + this.options = _.extend({root: '/'}, this.options, options); + this.root = this.options.root; + this._wantsHashChange = this.options.hashChange !== false; + this._wantsPushState = !!this.options.pushState; + this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); + var fragment = this.getFragment(); + var docMode = document.documentMode; + var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); + + // Normalize root to always include a leading and trailing slash. + this.root = ('/' + this.root + '/').replace(rootStripper, '/'); + + if (oldIE && this._wantsHashChange) { + this.iframe = Backbone.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow; + this.navigate(fragment); + } + + // Depending on whether we're using pushState or hashes, and whether + // 'onhashchange' is supported, determine how we check the URL state. + if (this._hasPushState) { + Backbone.$(window).on('popstate', this.checkUrl); + } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) { + Backbone.$(window).on('hashchange', this.checkUrl); + } else if (this._wantsHashChange) { + this._checkUrlInterval = setInterval(this.checkUrl, this.interval); + } + + // Determine if we need to change the base url, for a pushState link + // opened by a non-pushState browser. + this.fragment = fragment; + var loc = this.location; + var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root; + + // Transition from hashChange to pushState or vice versa if both are + // requested. + if (this._wantsHashChange && this._wantsPushState) { + + // If we've started off with a route from a `pushState`-enabled + // browser, but we're currently in a browser that doesn't support it... + if (!this._hasPushState && !atRoot) { + this.fragment = this.getFragment(null, true); + this.location.replace(this.root + this.location.search + '#' + this.fragment); + // Return immediately as browser will do redirect to new url + return true; + + // Or if we've started out with a hash-based route, but we're currently + // in a browser where it could be `pushState`-based instead... + } else if (this._hasPushState && atRoot && loc.hash) { + this.fragment = this.getHash().replace(routeStripper, ''); + this.history.replaceState({}, document.title, this.root + this.fragment + loc.search); + } + + } + + if (!this.options.silent) return this.loadUrl(); + }, + + // Disable Backbone.history, perhaps temporarily. Not useful in a real app, + // but possibly useful for unit testing Routers. + stop: function() { + Backbone.$(window).off('popstate', this.checkUrl).off('hashchange', this.checkUrl); + clearInterval(this._checkUrlInterval); + History.started = false; + }, + + // Add a route to be tested when the fragment changes. Routes added later + // may override previous routes. + route: function(route, callback) { + this.handlers.unshift({route: route, callback: callback}); + }, + + // Checks the current URL to see if it has changed, and if it has, + // calls `loadUrl`, normalizing across the hidden iframe. + checkUrl: function(e) { + var current = this.getFragment(); + if (current === this.fragment && this.iframe) { + current = this.getFragment(this.getHash(this.iframe)); + } + if (current === this.fragment) return false; + if (this.iframe) this.navigate(current); + this.loadUrl(); + }, + + // Attempt to load the current URL fragment. If a route succeeds with a + // match, returns `true`. If no defined routes matches the fragment, + // returns `false`. + loadUrl: function(fragment) { + fragment = this.fragment = this.getFragment(fragment); + return _.any(this.handlers, function(handler) { + if (handler.route.test(fragment)) { + handler.callback(fragment); + return true; + } + }); + }, + + // Save a fragment into the hash history, or replace the URL state if the + // 'replace' option is passed. You are responsible for properly URL-encoding + // the fragment in advance. + // + // The options object can contain `trigger: true` if you wish to have the + // route callback be fired (not usually desirable), or `replace: true`, if + // you wish to modify the current URL without adding an entry to the history. + navigate: function(fragment, options) { + if (!History.started) return false; + if (!options || options === true) options = {trigger: !!options}; + + var url = this.root + (fragment = this.getFragment(fragment || '')); + + // Strip the fragment of the query and hash for matching. + fragment = fragment.replace(pathStripper, ''); + + if (this.fragment === fragment) return; + this.fragment = fragment; + + // Don't include a trailing slash on the root. + if (fragment === '' && url !== '/') url = url.slice(0, -1); + + // If pushState is available, we use it to set the fragment as a real URL. + if (this._hasPushState) { + this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url); + + // If hash changes haven't been explicitly disabled, update the hash + // fragment to store history. + } else if (this._wantsHashChange) { + this._updateHash(this.location, fragment, options.replace); + if (this.iframe && (fragment !== this.getFragment(this.getHash(this.iframe)))) { + // Opening and closing the iframe tricks IE7 and earlier to push a + // history entry on hash-tag change. When replace is true, we don't + // want this. + if(!options.replace) this.iframe.document.open().close(); + this._updateHash(this.iframe.location, fragment, options.replace); + } + + // If you've told us that you explicitly don't want fallback hashchange- + // based history, then `navigate` becomes a page refresh. + } else { + return this.location.assign(url); + } + if (options.trigger) return this.loadUrl(fragment); + }, + + // Update the hash location, either replacing the current entry, or adding + // a new one to the browser history. + _updateHash: function(location, fragment, replace) { + if (replace) { + var href = location.href.replace(/(javascript:|#).*$/, ''); + location.replace(href + '#' + fragment); + } else { + // Some browsers require that `hash` contains a leading #. + location.hash = '#' + fragment; + } + } + + }); + + // Create the default Backbone.history. + Backbone.history = new History; + + // Helpers + // ------- + + // Helper function to correctly set up the prototype chain, for subclasses. + // Similar to `goog.inherits`, but uses a hash of prototype properties and + // class properties to be extended. + var extend = function(protoProps, staticProps) { + var parent = this; + var child; + + // The constructor function for the new subclass is either defined by you + // (the "constructor" property in your `extend` definition), or defaulted + // by us to simply call the parent's constructor. + if (protoProps && _.has(protoProps, 'constructor')) { + child = protoProps.constructor; + } else { + child = function(){ return parent.apply(this, arguments); }; + } + + // Add static properties to the constructor function, if supplied. + _.extend(child, parent, staticProps); + + // Set the prototype chain to inherit from `parent`, without calling + // `parent`'s constructor function. + var Surrogate = function(){ this.constructor = child; }; + Surrogate.prototype = parent.prototype; + child.prototype = new Surrogate; + + // Add prototype properties (instance properties) to the subclass, + // if supplied. + if (protoProps) _.extend(child.prototype, protoProps); + + // Set a convenience property in case the parent's prototype is needed + // later. + child.__super__ = parent.prototype; + + return child; + }; + + // Set up inheritance for the model, collection, router, view and history. + Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend; + + // Throw an error when a URL is needed, and none is supplied. + var urlError = function() { + throw new Error('A "url" property or function must be specified'); + }; + + // Wrap an optional error callback with a fallback error event. + var wrapError = function(model, options) { + var error = options.error; + options.error = function(resp) { + if (error) error(model, resp, options); + model.trigger('error', model, resp, options); + }; + }; + +}).call(this); \ No newline at end of file diff --git a/src/static/jquery/visualsearch-0.5.0/visualsearch-datauri.css b/src/static/jquery/visualsearch-0.5.0/visualsearch-datauri.css new file mode 100755 index 0000000..54e39ac --- /dev/null +++ b/src/static/jquery/visualsearch-0.5.0/visualsearch-datauri.css @@ -0,0 +1,341 @@ +.VS-search .VS-icon { + background-repeat: no-repeat; + background-position: center center; + vertical-align: middle; + width: 16px; height: 16px; +} + .VS-search .VS-icon-cancel { + width: 11px; height: 11px; + background-position: center 0; + background-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAWCAYAAAAW5GZjAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAb9JREFUeNqUUr1qAkEQ3j0khQp6kihaeGgEEa18gTQR0iRY+BaBSMDGwidIEUKqFL6BopgqBAJ5AMFGjUU0d4WHEvwJarvZ77gRIzGYgb1hZr+Z75vZ40IIzqTNZrPj8Xicn0wmmcViEXS73aaqqq+BQODG6/W+A8MBNk3zfDAY3C6Xy0O2ZS6X6zMSiVwHg8FHLjtq7Xb7RQKj7BeTzVCgJ5PJU2U0GhUk7REuMpkMi8fjFggeMeecrVYrFRId0CgTAgDDMFg4HLbA8IjJgHNgGEr0er0fQIphUmZAwdSUADUB4RFDsz3oSMF6CLzZkQqgGebz+Z75dDqNdTqdp13bgDmdTj2VSp0oWHg0Gr2UNH2Z/9o+yMv7K4/HY/C/XhDUfr//jl7QQVT9fp/V63VWqVRYt9tliUSCZbPZg1wux9Lp9PqFeK1Wu9A0DdXz7YM87i0FrVZLs4Fi1wmFQh/NZjOmVKvVgq7rR/QflMtlixGedjwcDlUpMQ9tbzalkAAB2/R297mNW+sT2wUbUnA//V/nYrH4QOBNABUQuFQq3TNMuc82sDVrz41G42yvPeODAwZQ0QzwiJEnzLcAAwBJ6WXlwoBgZAAAAABJRU5ErkJggg=="); + cursor: pointer; + } + .VS-search .VS-icon-cancel:hover { + background-position: center -11px; + } + .VS-search .VS-icon-search { + width: 12px; height: 12px; + background-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAUZJREFUeNpUUM2qgmAQzS8NiUgLzTIXLZQW1QuI9AY9QPSW9gQ9QiriwpJQEBVrVWT2d7p2L9xZzDdzZs7M+YYqy/J8Ptu2vd/v4zgeDAaqqk4mE47jar9GnU6nzWbjOA5FUa/Xq0Jns9l8Pud5vkpp58cwAOzhcBhFkeu6GNztdg3D+Db5vo9nOp2iiWGYTqdDCMFe4LquI0aVpGmKR9M0lmUbjQY8YiBJklTb4YkoilBzOBzq9TogeMQIJEmqmlAlo9EIyXa7tSyrKAp4xEBkWUb5q2k8Hh+PR8/zwjCEgufz+aESstvtoKnVan2GgY31kBkEAfT1ej1FUZDiNIIgrFYr9H1ug3teLpfH43G/3/FBUJGu1+s8z8FZLpc0mmiabrfbf5fEumazuVgsTNO8Xq+3242qRNT+G0CMz7IMzH6//xZgAA60tj6rqzxpAAAAAElFTkSuQmCC"); + } + +/*------------------------------ RESET + DEFAULT STYLES ---------------------------------*/ + +/* +Eric Meyer's final reset.css +Source: http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ +*/ +.VS-search div, .VS-search span, .VS-search a, .VS-search img, +.VS-search ul, .VS-search li, .VS-search form, .VS-search label, +.VS-interface ul, .VS-interface li, .VS-interface { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} + +.VS-search :focus { + outline: 0; +} +.VS-search { + line-height: 1; + color: black; +} +.VS-search ol, .VS-search ul { + list-style: none; +} + +/* ===================== */ +/* = General and Reset = */ +/* ===================== */ + +.VS-search { + font-family: Arial, sans-serif; + color: #373737; + font-size: 12px; +} +.VS-search input { + display: block; + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + outline: none; + margin: 0; padding: 4px; + background: transparent; + font-size: 16px; + line-height: 20px; + width: 100%; +} +.VS-interface, .VS-search .dialog, .VS-search input { + font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important; + line-height: 1.1em; +} + +/* ========== */ +/* = Layout = */ +/* ========== */ + +.VS-search .VS-search-box { + cursor: text; + position: relative; + background: transparent; + border: 2px solid #ccc; + border-radius: 16px; -webkit-border-radius: 16px; -moz-border-radius: 16px; + background-color: #fafafa; + -webkit-box-shadow: inset 0px 0px 3px #ccc; + -moz-box-shadow: inset 0px 0px 3px #ccc; + box-shadow: inset 0px 0px 3px #ccc; + min-height: 28px; + height: auto; +} + .VS-search.VS-readonly .VS-search-box { + cursor: default; + } + .VS-search .VS-search-box.VS-focus { + border-color: #acf; + -webkit-box-shadow: inset 0px 0px 3px #acf; + -moz-box-shadow: inset 0px 0px 3px #acf; + box-shadow: inset 0px 0px 3px #acf; + } + .VS-search .VS-placeholder { + position: absolute; + top: 7px; + left: 4px; + margin: 0 20px 0 22px; + color: #808080; + font-size: 14px; + } + .VS-search .VS-search-box.VS-focus .VS-placeholder, + .VS-search .VS-search-box .VS-placeholder.VS-hidden { + display: none; + } + .VS-search .VS-search-inner { + position: relative; + margin: 0 20px 0 22px; + overflow: hidden; + } + .VS-search input { + width: 100px; + } + .VS-search input, + .VS-search .VS-input-width-tester { + padding: 6px 0; + float: left; + color: #808080; + font: 13px/17px Helvetica, Arial; + } + .VS-search.VS-focus input { + color: #606060; + } + .VS-search .VS-icon-search { + position: absolute; + left: 9px; top: 8px; + } + .VS-search .VS-icon-cancel { + position: absolute; + right: 9px; top: 8px; + } + .VS-search.VS-readonly .VS-icon-cancel { + display: none; + } + +/* ================ */ +/* = Search Facet = */ +/* ================ */ + +.VS-search .search_facet { + float: left; + margin: 0; + padding: 0 0 0 14px; + position: relative; + border: 1px solid transparent; + height: 20px; + margin: 3px -3px 3px 0; +} + .VS-search.VS-readonly .search_facet { + padding-left: 0; + } + .VS-search .search_facet.is_selected { + margin-left: -3px; + -webkit-border-radius: 16px; + -moz-border-radius: 16px; + border-radius: 16px; + background-color: #d2e6fd; + background-image: -moz-linear-gradient(top, #d2e6fd, #b0d1f9); /* FF3.6 */ + background-image: -webkit-gradient(linear, left top, left bottom, from(#d2e6fd), to(#b0d1f9)); /* Saf4+, Chrome */ + background-image: linear-gradient(top, #d2e6fd, #b0d1f9); + border: 1px solid #6eadf5; + } + .VS-search .search_facet .category { + float: left; + text-transform: uppercase; + font-weight: bold; + font-size: 10px; + color: #808080; + padding: 8px 0 5px; + line-height: 13px; + cursor: pointer; + padding: 4px 0 0; + } + .VS-search.VS-readonly .search_facet .category { + cursor: default; + } + .VS-search .search_facet.is_selected .category { + margin-left: 3px; + } + .VS-search .search_facet .search_facet_input_container { + float: left; + } + .VS-search .search_facet input { + margin: 0; + padding: 0; + color: #000; + font-size: 13px; + line-height: 16px; + padding: 5px 0 5px 4px; + height: 16px; + width: auto; + z-index: 100; + position: relative; + padding-top: 1px; + padding-bottom: 2px; + padding-right: 3px; + + } + .VS-search .search_facet.is_editing input, + .VS-search .search_facet.is_selected input { + color: #000; + } + .VS-search.VS-readonly .search_facet .search_facet_remove { + display: none; + } + .VS-search .search_facet .search_facet_remove { + position: absolute; + left: 0; + top: 4px; + } + .VS-search .search_facet.is_selected .search_facet_remove { + opacity: 0.4; + left: 3px; + filter: alpha(opacity=40); + background-position: center -11px; + } + .VS-search .search_facet .search_facet_remove:hover { + opacity: 1; + } + .VS-search .search_facet.is_editing .category, + .VS-search .search_facet.is_selected .category { + color: #000; + } + .VS-search .search_facet.search_facet_maybe_delete .category, + .VS-search .search_facet.search_facet_maybe_delete input { + color: darkred; + } + +/* ================ */ +/* = Search Input = */ +/* ================ */ + +.VS-search .search_input { + height: 28px; + float: left; + margin-left: -1px; +} + .VS-search .search_input input { + padding: 6px 3px 6px 2px; + line-height: 10px; + height: 22px; + margin-top: -4px; + width: 10px; + z-index: 100; + min-width: 4px; + position: relative; + } + .VS-search .search_input.is_editing input { + color: #202020; + } + +/* ================ */ +/* = Autocomplete = */ +/* ================ */ + +.ui-helper-hidden-accessible { + display: none; +} + +.VS-interface.ui-autocomplete { + position: absolute; + border: 1px solid #C0C0C0; + border-top: 1px solid #D9D9D9; + background-color: #F6F6F6; + cursor: pointer; + z-index: 10000; + padding: 0; + margin: 0; + width: auto; + min-width: 80px; + max-width: 220px; + max-height: 240px; + overflow-y: auto; + overflow-x: hidden; + font-size: 13px; + top: 5px; + opacity: 0.97; + box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -webkit-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -moz-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); +} + .VS-interface.ui-autocomplete .ui-autocomplete-category { + text-transform: capitalize; + font-size: 11px; + padding: 4px 4px 4px; + border-top: 1px solid #A2A2A2; + border-bottom: 1px solid #A2A2A2; + background-color: #B7B7B7; + text-shadow: 0 -1px 0 #999; + font-weight: bold; + color: white; + cursor: default; + } + .VS-interface.ui-autocomplete .ui-menu-item { + float: none; + } + .VS-interface.ui-autocomplete .ui-menu-item a { + color: #000; + outline: none; + display: block; + padding: 3px 4px 5px; + border-radius: none; + line-height: 1; + background-color: #F8F8F8; + background-image: -moz-linear-gradient(top, #F8F8F8, #F3F3F3); /* FF3.6 */ + background-image: -webkit-gradient(linear, left top, left bottom, from(#F8F8F8), to(#F3F3F3)); /* Saf4+, Chrome */ + background-image: linear-gradient(top, #F8F8F8, #F3F3F3); + border-top: 1px solid #FAFAFA; + border-bottom: 1px solid #f0f0f0; + } + .VS-interface.ui-autocomplete .ui-menu-item a:active { + outline: none; + } + .VS-interface.ui-autocomplete .ui-menu-item .ui-state-hover, .VS-interface.ui-autocomplete .ui-menu-item .ui-state-focus { + background-color: #6483F7; + background-image: -moz-linear-gradient(top, #648bF5, #2465f3); /* FF3.6 */ + background-image: -webkit-gradient(linear, left top, left bottom, from(#648bF5), to(#2465f3)); /* Saf4+, Chrome */ + background-image: linear-gradient(top, #648bF5, #2465f3); + border-top: 1px solid #5b83ec; + border-bottom: 1px solid #1459e9; + border-left: none; + border-right: none; + color: white; + margin: 0; + } + .VS-interface.ui-autocomplete .ui-corner-all { + border-radius: 0; + } + .VS-interface.ui-autocomplete li { + list-style: none; + width: auto; + } diff --git a/src/static/jquery/visualsearch-0.5.0/visualsearch.css b/src/static/jquery/visualsearch-0.5.0/visualsearch.css new file mode 100755 index 0000000..06083fe --- /dev/null +++ b/src/static/jquery/visualsearch-0.5.0/visualsearch.css @@ -0,0 +1,341 @@ +.VS-search .VS-icon { + background-repeat: no-repeat; + background-position: center center; + vertical-align: middle; + width: 16px; height: 16px; +} + .VS-search .VS-icon-cancel { + width: 11px; height: 11px; + background-position: center 0; + background-image: url(../images/embed/icons/cancel_search.png?1311104738); + cursor: pointer; + } + .VS-search .VS-icon-cancel:hover { + background-position: center -11px; + } + .VS-search .VS-icon-search { + width: 12px; height: 12px; + background-image: url(../images/embed/icons/search_glyph.png?1311104738); + } + +/*------------------------------ RESET + DEFAULT STYLES ---------------------------------*/ + +/* +Eric Meyer's final reset.css +Source: http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ +*/ +.VS-search div, .VS-search span, .VS-search a, .VS-search img, +.VS-search ul, .VS-search li, .VS-search form, .VS-search label, +.VS-interface ul, .VS-interface li, .VS-interface { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} + +.VS-search :focus { + outline: 0; +} +.VS-search { + line-height: 1; + color: black; +} +.VS-search ol, .VS-search ul { + list-style: none; +} + +/* ===================== */ +/* = General and Reset = */ +/* ===================== */ + +.VS-search { + font-family: Arial, sans-serif; + color: #373737; + font-size: 12px; +} +.VS-search input { + display: block; + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; + outline: none; + margin: 0; padding: 4px; + background: transparent; + font-size: 16px; + line-height: 20px; + width: 100%; +} +.VS-interface, .VS-search .dialog, .VS-search input { + font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important; + line-height: 1.1em; +} + +/* ========== */ +/* = Layout = */ +/* ========== */ + +.VS-search .VS-search-box { + cursor: text; + position: relative; + background: transparent; + border: 2px solid #ccc; + border-radius: 16px; -webkit-border-radius: 16px; -moz-border-radius: 16px; + background-color: #fafafa; + -webkit-box-shadow: inset 0px 0px 3px #ccc; + -moz-box-shadow: inset 0px 0px 3px #ccc; + box-shadow: inset 0px 0px 3px #ccc; + min-height: 28px; + height: auto; +} + .VS-search.VS-readonly .VS-search-box { + cursor: default; + } + .VS-search .VS-search-box.VS-focus { + border-color: #acf; + -webkit-box-shadow: inset 0px 0px 3px #acf; + -moz-box-shadow: inset 0px 0px 3px #acf; + box-shadow: inset 0px 0px 3px #acf; + } + .VS-search .VS-placeholder { + position: absolute; + top: 7px; + left: 4px; + margin: 0 20px 0 22px; + color: #808080; + font-size: 14px; + } + .VS-search .VS-search-box.VS-focus .VS-placeholder, + .VS-search .VS-search-box .VS-placeholder.VS-hidden { + display: none; + } + .VS-search .VS-search-inner { + position: relative; + margin: 0 20px 0 22px; + overflow: hidden; + } + .VS-search input { + width: 100px; + } + .VS-search input, + .VS-search .VS-input-width-tester { + padding: 6px 0; + float: left; + color: #808080; + font: 13px/17px Helvetica, Arial; + } + .VS-search.VS-focus input { + color: #606060; + } + .VS-search .VS-icon-search { + position: absolute; + left: 9px; top: 8px; + } + .VS-search .VS-icon-cancel { + position: absolute; + right: 9px; top: 8px; + } + .VS-search.VS-readonly .VS-icon-cancel { + display: none; + } + +/* ================ */ +/* = Search Facet = */ +/* ================ */ + +.VS-search .search_facet { + float: left; + margin: 0; + padding: 0 0 0 14px; + position: relative; + border: 1px solid transparent; + height: 20px; + margin: 3px -3px 3px 0; +} + .VS-search.VS-readonly .search_facet { + padding-left: 0; + } + .VS-search .search_facet.is_selected { + margin-left: -3px; + -webkit-border-radius: 16px; + -moz-border-radius: 16px; + border-radius: 16px; + background-color: #d2e6fd; + background-image: -moz-linear-gradient(top, #d2e6fd, #b0d1f9); /* FF3.6 */ + background-image: -webkit-gradient(linear, left top, left bottom, from(#d2e6fd), to(#b0d1f9)); /* Saf4+, Chrome */ + background-image: linear-gradient(top, #d2e6fd, #b0d1f9); + border: 1px solid #6eadf5; + } + .VS-search .search_facet .category { + float: left; + text-transform: uppercase; + font-weight: bold; + font-size: 10px; + color: #808080; + padding: 8px 0 5px; + line-height: 13px; + cursor: pointer; + padding: 4px 0 0; + } + .VS-search.VS-readonly .search_facet .category { + cursor: default; + } + .VS-search .search_facet.is_selected .category { + margin-left: 3px; + } + .VS-search .search_facet .search_facet_input_container { + float: left; + } + .VS-search .search_facet input { + margin: 0; + padding: 0; + color: #000; + font-size: 13px; + line-height: 16px; + padding: 5px 0 5px 4px; + height: 16px; + width: auto; + z-index: 100; + position: relative; + padding-top: 1px; + padding-bottom: 2px; + padding-right: 3px; + + } + .VS-search .search_facet.is_editing input, + .VS-search .search_facet.is_selected input { + color: #000; + } + .VS-search.VS-readonly .search_facet .search_facet_remove { + display: none; + } + .VS-search .search_facet .search_facet_remove { + position: absolute; + left: 0; + top: 4px; + } + .VS-search .search_facet.is_selected .search_facet_remove { + opacity: 0.4; + left: 3px; + filter: alpha(opacity=40); + background-position: center -11px; + } + .VS-search .search_facet .search_facet_remove:hover { + opacity: 1; + } + .VS-search .search_facet.is_editing .category, + .VS-search .search_facet.is_selected .category { + color: #000; + } + .VS-search .search_facet.search_facet_maybe_delete .category, + .VS-search .search_facet.search_facet_maybe_delete input { + color: darkred; + } + +/* ================ */ +/* = Search Input = */ +/* ================ */ + +.VS-search .search_input { + height: 28px; + float: left; + margin-left: -1px; +} + .VS-search .search_input input { + padding: 6px 3px 6px 2px; + line-height: 10px; + height: 22px; + margin-top: -4px; + width: 10px; + z-index: 100; + min-width: 4px; + position: relative; + } + .VS-search .search_input.is_editing input { + color: #202020; + } + +/* ================ */ +/* = Autocomplete = */ +/* ================ */ + +.ui-helper-hidden-accessible { + display: none; +} + +.VS-interface.ui-autocomplete { + position: absolute; + border: 1px solid #C0C0C0; + border-top: 1px solid #D9D9D9; + background-color: #F6F6F6; + cursor: pointer; + z-index: 10000; + padding: 0; + margin: 0; + width: auto; + min-width: 80px; + max-width: 220px; + max-height: 240px; + overflow-y: auto; + overflow-x: hidden; + font-size: 13px; + top: 5px; + opacity: 0.97; + box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -webkit-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -moz-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); +} + .VS-interface.ui-autocomplete .ui-autocomplete-category { + text-transform: capitalize; + font-size: 11px; + padding: 4px 4px 4px; + border-top: 1px solid #A2A2A2; + border-bottom: 1px solid #A2A2A2; + background-color: #B7B7B7; + text-shadow: 0 -1px 0 #999; + font-weight: bold; + color: white; + cursor: default; + } + .VS-interface.ui-autocomplete .ui-menu-item { + float: none; + } + .VS-interface.ui-autocomplete .ui-menu-item a { + color: #000; + outline: none; + display: block; + padding: 3px 4px 5px; + border-radius: none; + line-height: 1; + background-color: #F8F8F8; + background-image: -moz-linear-gradient(top, #F8F8F8, #F3F3F3); /* FF3.6 */ + background-image: -webkit-gradient(linear, left top, left bottom, from(#F8F8F8), to(#F3F3F3)); /* Saf4+, Chrome */ + background-image: linear-gradient(top, #F8F8F8, #F3F3F3); + border-top: 1px solid #FAFAFA; + border-bottom: 1px solid #f0f0f0; + } + .VS-interface.ui-autocomplete .ui-menu-item a:active { + outline: none; + } + .VS-interface.ui-autocomplete .ui-menu-item .ui-state-hover, .VS-interface.ui-autocomplete .ui-menu-item .ui-state-focus { + background-color: #6483F7; + background-image: -moz-linear-gradient(top, #648bF5, #2465f3); /* FF3.6 */ + background-image: -webkit-gradient(linear, left top, left bottom, from(#648bF5), to(#2465f3)); /* Saf4+, Chrome */ + background-image: linear-gradient(top, #648bF5, #2465f3); + border-top: 1px solid #5b83ec; + border-bottom: 1px solid #1459e9; + border-left: none; + border-right: none; + color: white; + margin: 0; + } + .VS-interface.ui-autocomplete .ui-corner-all { + border-radius: 0; + } + .VS-interface.ui-autocomplete li { + list-style: none; + width: auto; + } diff --git a/src/static/jquery/visualsearch-0.5.0/visualsearch.js b/src/static/jquery/visualsearch-0.5.0/visualsearch.js new file mode 100755 index 0000000..6d03e18 --- /dev/null +++ b/src/static/jquery/visualsearch-0.5.0/visualsearch.js @@ -0,0 +1,1969 @@ +// This is the annotated source code for +// [VisualSearch.js](http://documentcloud.github.com/visualsearch/), +// a rich search box for real data. +// +// The annotated source HTML is generated by +// [Docco](http://jashkenas.github.com/docco/). + +/** @license VisualSearch.js 0.4.0 + * (c) 2011 Samuel Clay, @samuelclay, DocumentCloud Inc. + * VisualSearch.js may be freely distributed under the MIT license. + * For all details and documentation: + * http://documentcloud.github.com/visualsearch + */ + +(function() { + + var $ = jQuery; // Handle namespaced jQuery + + // Setting up VisualSearch globals. These will eventually be made instance-based. + if (!window.VS) window.VS = {}; + if (!VS.app) VS.app = {}; + if (!VS.ui) VS.ui = {}; + if (!VS.model) VS.model = {}; + if (!VS.utils) VS.utils = {}; + + // Sets the version for VisualSearch to be used programatically elsewhere. + VS.VERSION = '0.5.0'; + + VS.VisualSearch = function(options) { + var defaults = { + container : '', + query : '', + autosearch : true, + unquotable : [], + remainder : 'text', + showFacets : true, + readOnly : false, + callbacks : { + search : $.noop, + focus : $.noop, + blur : $.noop, + facetMatches : $.noop, + valueMatches : $.noop, + clearSearch : $.noop, + removedFacet : $.noop + } + }; + this.options = _.extend({}, defaults, options); + this.options.callbacks = _.extend({}, defaults.callbacks, options.callbacks); + + VS.app.hotkeys.initialize(); + this.searchQuery = new VS.model.SearchQuery(); + this.searchBox = new VS.ui.SearchBox({ + app: this, + showFacets: this.options.showFacets + }); + + if (options.container) { + var searchBox = this.searchBox.render().el; + $(this.options.container).html(searchBox); + } + this.searchBox.value(this.options.query || ''); + + // Disable page caching for browsers that incorrectly cache the visual search inputs. + // This forces the browser to re-render the page when it is retrieved in its history. + $(window).bind('unload', function(e) {}); + + // Gives the user back a reference to the `searchBox` so they + // can use public methods. + return this; + }; + + // Entry-point used to tie all parts of VisualSearch together. It will either attach + // itself to `options.container`, or pass back the `searchBox` so it can be rendered + // at will. + VS.init = function(options) { + return new VS.VisualSearch(options); + }; + +})(); + +(function() { + +var $ = jQuery; // Handle namespaced jQuery + +// The search box is responsible for managing the many facet views and input views. +VS.ui.SearchBox = Backbone.View.extend({ + + id : 'search', + + events : { + 'click .VS-cancel-search-box' : 'clearSearch', + 'mousedown .VS-search-box' : 'maybeFocusSearch', + 'dblclick .VS-search-box' : 'highlightSearch', + 'click .VS-search-box' : 'maybeTripleClick' + }, + + // Creating a new SearchBox registers handlers for re-rendering facets when necessary, + // as well as handling typing when a facet is selected. + initialize : function(options) { + this.options = _.extend({}, this.options, options); + + this.app = this.options.app; + this.flags = { + allSelected : false + }; + this.facetViews = []; + this.inputViews = []; + _.bindAll(this, 'renderFacets', '_maybeDisableFacets', 'disableFacets', + 'deselectAllFacets', 'addedFacet', 'removedFacet', 'changedFacet'); + this.app.searchQuery + .bind('reset', this.renderFacets) + .bind('add', this.addedFacet) + .bind('remove', this.removedFacet) + .bind('change', this.changedFacet); + $(document).bind('keydown', this._maybeDisableFacets); + }, + + // Renders the search box, but requires placement on the page through `this.el`. + render : function() { + $(this.el).append(JST['search_box']({ + readOnly: this.app.options.readOnly + })); + $(document.body).setMode('no', 'search'); + + return this; + }, + + // # Querying Facets # + + // Either gets a serialized query string or sets the faceted query from a query string. + value : function(query) { + if (query == null) return this.serialize(); + return this.setQuery(query); + }, + + // Uses the VS.app.searchQuery collection to serialize the current query from the various + // facets that are in the search box. + serialize : function() { + var query = []; + var inputViewsCount = this.inputViews.length; + + this.app.searchQuery.each(_.bind(function(facet, i) { + query.push(this.inputViews[i].value()); + query.push(facet.serialize()); + }, this)); + + if (inputViewsCount) { + query.push(this.inputViews[inputViewsCount-1].value()); + } + + return _.compact(query).join(' '); + }, + + // Returns any facet views that are currently selected. Useful for changing the value + // callbacks based on what else is in the search box and which facet is being edited. + selected: function() { + return _.select(this.facetViews, function(view) { + return view.modes.editing == 'is' || view.modes.selected == 'is'; + }); + }, + + // Similar to `this.selected`, returns any facet models that are currently selected. + selectedModels: function() { + return _.pluck(this.selected(), 'model'); + }, + + // Takes a query string and uses the SearchParser to parse and render it. Note that + // `VS.app.SearchParser` refreshes the `VS.app.searchQuery` collection, which is bound + // here to call `this.renderFacets`. + setQuery : function(query) { + this.currentQuery = query; + VS.app.SearchParser.parse(this.app, query); + }, + + // Returns the position of a facet/input view. Useful when moving between facets. + viewPosition : function(view) { + var views = view.type == 'facet' ? this.facetViews : this.inputViews; + var position = _.indexOf(views, view); + if (position == -1) position = 0; + return position; + }, + + // Used to launch a search. Hitting enter or clicking the search button. + searchEvent : function(e) { + var query = this.value(); + this.focusSearch(e); + this.value(query); + this.app.options.callbacks.search(query, this.app.searchQuery); + }, + + // # Rendering Facets # + + // Add a new facet. Facet will be focused and ready to accept a value. Can also + // specify position, in the case of adding facets from an inbetween input. + addFacet : function(category, initialQuery, position) { + category = VS.utils.inflector.trim(category); + initialQuery = VS.utils.inflector.trim(initialQuery || ''); + if (!category) return; + + var model = new VS.model.SearchFacet({ + category : category, + value : initialQuery || '', + app : this.app + }); + this.app.searchQuery.add(model, {at: position}); + }, + + // Renders a newly added facet, and selects it. + addedFacet : function (model) { + this.renderFacets(); + var facetView = _.detect(this.facetViews, function(view) { + if (view.model == model) return true; + }); + + _.defer(function() { + facetView.enableEdit(); + }); + }, + + // Changing a facet programmatically re-renders it. + changedFacet: function () { + this.renderFacets(); + }, + + // When removing a facet, potentially do something. For now, the adjacent + // remaining facet is selected, but this is handled by the facet's view, + // since its position is unknown by the time the collection triggers this + // remove callback. + removedFacet : function (facet, query, options) { + this.app.options.callbacks.removedFacet(facet, query, options); + }, + + // Renders each facet as a searchFacet view. + renderFacets : function() { + this.facetViews = []; + this.inputViews = []; + + this.$('.VS-search-inner').empty(); + + this.app.searchQuery.each(_.bind(this.renderFacet, this)); + + // Add on an n+1 empty search input on the very end. + this.renderSearchInput(); + this.renderPlaceholder(); + }, + + // Render a single facet, using its category and query value. + renderFacet : function(facet, position) { + var view = new VS.ui.SearchFacet({ + app : this.app, + model : facet, + order : position + }); + + // Input first, facet second. + this.renderSearchInput(); + this.facetViews.push(view); + this.$('.VS-search-inner').children().eq(position*2).after(view.render().el); + + view.calculateSize(); + _.defer(_.bind(view.calculateSize, view)); + + return view; + }, + + // Render a single input, used to create and autocomplete facets + renderSearchInput : function() { + var input = new VS.ui.SearchInput({ + position: this.inputViews.length, + app: this.app, + showFacets: this.options.showFacets + }); + this.$('.VS-search-inner').append(input.render().el); + this.inputViews.push(input); + }, + + // Handles showing/hiding the placeholder text + renderPlaceholder : function() { + var $placeholder = this.$('.VS-placeholder'); + if (this.app.searchQuery.length) { + $placeholder.addClass("VS-hidden"); + } else { + $placeholder.removeClass("VS-hidden") + .text(this.app.options.placeholder); + } + }, + + // # Modifying Facets # + + // Clears out the search box. Command+A + delete can trigger this, as can a cancel button. + // + // If a `clearSearch` callback was provided, the callback is invoked and + // provided with a function performs the actual removal of the data. This + // allows third-party developers to either clear data asynchronously, or + // prior to performing their custom "clear" logic. + clearSearch : function(e) { + if (this.app.options.readOnly) return; + var actualClearSearch = _.bind(function() { + this.disableFacets(); + this.value(''); + this.flags.allSelected = false; + this.searchEvent(e); + this.focusSearch(e); + }, this); + + if (this.app.options.callbacks.clearSearch != $.noop) { + this.app.options.callbacks.clearSearch(actualClearSearch); + } else { + actualClearSearch(); + } + }, + + // Command+A selects all facets. + selectAllFacets : function() { + this.flags.allSelected = true; + + $(document).one('click.selectAllFacets', this.deselectAllFacets); + + _.each(this.facetViews, function(facetView, i) { + facetView.selectFacet(); + }); + _.each(this.inputViews, function(inputView, i) { + inputView.selectText(); + }); + }, + + // Used by facets and input to see if all facets are currently selected. + allSelected : function(deselect) { + if (deselect) this.flags.allSelected = false; + return this.flags.allSelected; + }, + + // After `selectAllFacets` is engaged, this method is bound to the entire document. + // This immediate disables and deselects all facets, but it also checks if the user + // has clicked on either a facet or an input, and properly selects the view. + deselectAllFacets : function(e) { + this.disableFacets(); + + if (this.$(e.target).is('.category,input')) { + var el = $(e.target).closest('.search_facet,.search_input'); + var view = _.detect(this.facetViews.concat(this.inputViews), function(v) { + return v.el == el[0]; + }); + if (view.type == 'facet') { + view.selectFacet(); + } else if (view.type == 'input') { + _.defer(function() { + view.enableEdit(true); + }); + } + } + }, + + // Disables all facets except for the passed in view. Used when switching between + // facets, so as not to have to keep state of active facets. + disableFacets : function(keepView) { + _.each(this.inputViews, function(view) { + if (view && view != keepView && + (view.modes.editing == 'is' || view.modes.selected == 'is')) { + view.disableEdit(); + } + }); + _.each(this.facetViews, function(view) { + if (view && view != keepView && + (view.modes.editing == 'is' || view.modes.selected == 'is')) { + view.disableEdit(); + view.deselectFacet(); + } + }); + + this.flags.allSelected = false; + this.removeFocus(); + $(document).unbind('click.selectAllFacets'); + }, + + // Resize all inputs to account for extra keystrokes which may be changing the facet + // width incorrectly. This is a safety check to ensure inputs are correctly sized. + resizeFacets : function(view) { + _.each(this.facetViews, function(facetView, i) { + if (!view || facetView == view) { + facetView.resize(); + } + }); + }, + + // Handles keydown events on the document. Used to complete the Cmd+A deletion, and + // blurring focus. + _maybeDisableFacets : function(e) { + if (this.flags.allSelected && VS.app.hotkeys.key(e) == 'backspace') { + e.preventDefault(); + this.clearSearch(e); + return false; + } else if (this.flags.allSelected && VS.app.hotkeys.printable(e)) { + this.clearSearch(e); + } + }, + + // # Focusing Facets # + + // Move focus between facets and inputs. Takes a direction as well as many options + // for skipping over inputs and only to facets, placement of cursor position in facet + // (i.e. at the end), and selecting the text in the input/facet. + focusNextFacet : function(currentView, direction, options) { + options = options || {}; + var viewCount = this.facetViews.length; + var viewPosition = options.viewPosition || this.viewPosition(currentView); + + if (!options.skipToFacet) { + // Correct for bouncing between matching text and facet arrays. + if (currentView.type == 'text' && direction > 0) direction -= 1; + if (currentView.type == 'facet' && direction < 0) direction += 1; + } else if (options.skipToFacet && currentView.type == 'text' && + viewCount == viewPosition && direction >= 0) { + // Special case of looping around to a facet from the last search input box. + return false; + } + var view, next = Math.min(viewCount, viewPosition + direction); + + if (currentView.type == 'text') { + if (next >= 0 && next < viewCount) { + view = this.facetViews[next]; + } else if (next == viewCount) { + view = this.inputViews[this.inputViews.length-1]; + } + if (view && options.selectFacet && view.type == 'facet') { + view.selectFacet(); + } else if (view) { + view.enableEdit(); + view.setCursorAtEnd(direction || options.startAtEnd); + } + } else if (currentView.type == 'facet') { + if (options.skipToFacet) { + if (next >= viewCount || next < 0) { + view = _.last(this.inputViews); + view.enableEdit(); + } else { + view = this.facetViews[next]; + view.enableEdit(); + view.setCursorAtEnd(direction || options.startAtEnd); + } + } else { + view = this.inputViews[next]; + view.enableEdit(); + } + } + if (options.selectText) view.selectText(); + this.resizeFacets(); + + return true; + }, + + maybeFocusSearch : function(e) { + if (this.app.options.readOnly) return; + if ($(e.target).is('.VS-search-box') || + $(e.target).is('.VS-search-inner') || + e.type == 'keydown') { + this.focusSearch(e); + } + }, + + // Bring focus to last input field. + focusSearch : function(e, selectText) { + if (this.app.options.readOnly) return; + var view = this.inputViews[this.inputViews.length-1]; + view.enableEdit(selectText); + if (!selectText) view.setCursorAtEnd(-1); + if (e.type == 'keydown') { + view.keydown(e); + view.box.trigger('keydown'); + } + _.defer(_.bind(function() { + if (!this.$('input:focus').length) { + view.enableEdit(selectText); + } + }, this)); + }, + + // Double-clicking on the search wrapper should select the existing text in + // the last search input. Also start the triple-click timer. + highlightSearch : function(e) { + if (this.app.options.readOnly) return; + if ($(e.target).is('.VS-search-box') || + $(e.target).is('.VS-search-inner') || + e.type == 'keydown') { + var lastinput = this.inputViews[this.inputViews.length-1]; + lastinput.startTripleClickTimer(); + this.focusSearch(e, true); + } + }, + + maybeTripleClick : function(e) { + var lastinput = this.inputViews[this.inputViews.length-1]; + return lastinput.maybeTripleClick(e); + }, + + // Used to show the user is focused on some input inside the search box. + addFocus : function() { + if (this.app.options.readOnly) return; + this.app.options.callbacks.focus(); + this.$('.VS-search-box').addClass('VS-focus'); + }, + + // User is no longer focused on anything in the search box. + removeFocus : function() { + this.app.options.callbacks.blur(); + var focus = _.any(this.facetViews.concat(this.inputViews), function(view) { + return view.isFocused(); + }); + if (!focus) this.$('.VS-search-box').removeClass('VS-focus'); + }, + + // Show a menu which adds pre-defined facets to the search box. This is unused for now. + showFacetCategoryMenu : function(e) { + e.preventDefault(); + e.stopPropagation(); + if (this.facetCategoryMenu && this.facetCategoryMenu.modes.open == 'is') { + return this.facetCategoryMenu.close(); + } + + var items = [ + {title: 'Account', onClick: _.bind(this.addFacet, this, 'account', '')}, + {title: 'Project', onClick: _.bind(this.addFacet, this, 'project', '')}, + {title: 'Filter', onClick: _.bind(this.addFacet, this, 'filter', '')}, + {title: 'Access', onClick: _.bind(this.addFacet, this, 'access', '')} + ]; + + var menu = this.facetCategoryMenu || (this.facetCategoryMenu = new dc.ui.Menu({ + items : items, + standalone : true + })); + + this.$('.VS-icon-search').after(menu.render().open().content); + return false; + } + +}); + +})(); + +(function() { + +var $ = jQuery; // Handle namespaced jQuery + +// This is the visual search facet that holds the category and its autocompleted +// input field. +VS.ui.SearchFacet = Backbone.View.extend({ + + type : 'facet', + + className : 'search_facet', + + events : { + 'click .category' : 'selectFacet', + 'keydown input' : 'keydown', + 'mousedown input' : 'enableEdit', + 'mouseover .VS-icon-cancel' : 'showDelete', + 'mouseout .VS-icon-cancel' : 'hideDelete', + 'click .VS-icon-cancel' : 'remove' + }, + + initialize : function(options) { + this.options = _.extend({}, this.options, options); + + this.flags = { + canClose : false + }; + _.bindAll(this, 'set', 'keydown', 'deselectFacet', 'deferDisableEdit'); + this.app = this.options.app; + }, + + // Rendering the facet sets up autocompletion, events on blur, and populates + // the facet's input with its starting value. + render : function() { + $(this.el).html(JST['search_facet']({ + model : this.model, + readOnly: this.app.options.readOnly + })); + + this.setMode('not', 'editing'); + this.setMode('not', 'selected'); + this.box = this.$('input'); + this.box.val(this.model.label()); + this.box.bind('blur', this.deferDisableEdit); + // Handle paste events with `propertychange` + this.box.bind('input propertychange', this.keydown); + this.setupAutocomplete(); + + return this; + }, + + // This method is used to setup the facet's input to auto-grow. + // This is defered in the searchBox so it can be attached to the + // DOM to get the correct font-size. + calculateSize : function() { + this.box.autoGrowInput(); + this.box.unbind('updated.autogrow'); + this.box.bind('updated.autogrow', _.bind(this.moveAutocomplete, this)); + }, + + // Forces a recalculation of this facet's input field's value. Called when + // the facet is focused, removed, or otherwise modified. + resize : function(e) { + this.box.trigger('resize.autogrow', e); + }, + + // Watches the facet's input field to see if it matches the beginnings of + // words in `autocompleteValues`, which is different for every category. + // If the value, when selected from the autocompletion menu, is different + // than what it was, commit the facet and search for it. + setupAutocomplete : function() { + this.box.autocomplete({ + source : _.bind(this.autocompleteValues, this), + minLength : 0, + delay : 0, + autoFocus : true, + position : {offset : "0 5"}, + create : _.bind(function(e, ui) { + $(this.el).find('.ui-autocomplete-input').css('z-index','auto'); + }, this), + select : _.bind(function(e, ui) { + e.preventDefault(); + var originalValue = this.model.get('value'); + this.set(ui.item.value); + if (originalValue != ui.item.value || this.box.val() != ui.item.value) { + if (this.app.options.autosearch) { + this.search(e); + } else { + this.app.searchBox.renderFacets(); + this.app.searchBox.focusNextFacet(this, 1, {viewPosition: this.options.order}); + } + } + return false; + }, this), + open : _.bind(function(e, ui) { + var box = this.box; + this.box.autocomplete('widget').find('.ui-menu-item').each(function() { + var $value = $(this), + autoCompleteData = $value.data('item.autocomplete') || $value.data('ui-autocomplete-item'); + + if (autoCompleteData['value'] == box.val() && box.data('ui-autocomplete').menu.activate) { + box.data('ui-autocomplete').menu.activate(new $.Event("mouseover"), $value); + } + }); + }, this) + }); + + this.box.autocomplete('widget').addClass('VS-interface'); + }, + + // As the facet's input field grows, it may move to the next line in the + // search box. `autoGrowInput` triggers an `updated` event on the input + // field, which is bound to this method to move the autocomplete menu. + moveAutocomplete : function() { + var autocomplete = this.box.data('ui-autocomplete'); + if (autocomplete) { + autocomplete.menu.element.position({ + my : "left top", + at : "left bottom", + of : this.box.data('ui-autocomplete').element, + collision : "flip", + offset : "0 5" + }); + } + }, + + // When a user enters a facet and it is being edited, immediately show + // the autocomplete menu and size it to match the contents. + searchAutocomplete : function(e) { + var autocomplete = this.box.data('ui-autocomplete'); + if (autocomplete) { + var menu = autocomplete.menu.element; + autocomplete.search(); + + // Resize the menu based on the correctly measured width of what's bigger: + // the menu's original size or the menu items' new size. + menu.outerWidth(Math.max( + menu.width('').outerWidth(), + autocomplete.element.outerWidth() + )); + } + }, + + // Closes the autocomplete menu. Called on disabling, selecting, deselecting, + // and anything else that takes focus out of the facet's input field. + closeAutocomplete : function() { + var autocomplete = this.box.data('ui-autocomplete'); + if (autocomplete) autocomplete.close(); + }, + + // Search terms used in the autocomplete menu. These are specific to the facet, + // and only match for the facet's category. The values are then matched on the + // first letter of any word in matches, and finally sorted according to the + // value's own category. You can pass `preserveOrder` as an option in the + // `facetMatches` callback to skip any further ordering done client-side. + autocompleteValues : function(req, resp) { + var category = this.model.get('category'); + var value = this.model.get('value'); + var searchTerm = req.term; + + this.app.options.callbacks.valueMatches(category, searchTerm, function(matches, options) { + options = options || {}; + matches = matches || []; + + if (searchTerm && value != searchTerm) { + if (options.preserveMatches) { + resp(matches); + } else { + var re = VS.utils.inflector.escapeRegExp(searchTerm || ''); + var matcher = new RegExp('\\b' + re, 'i'); + matches = $.grep(matches, function(item) { + return matcher.test(item) || + matcher.test(item.value) || + matcher.test(item.label); + }); + } + } + + if (options.preserveOrder) { + resp(matches); + } else { + resp(_.sortBy(matches, function(match) { + if (match == value || match.value == value) return ''; + else return match; + })); + } + }); + + }, + + // Sets the facet's model's value. + set : function(value) { + if (!value) return; + this.model.set({'value': value}); + }, + + // Before the searchBox performs a search, we need to close the + // autocomplete menu. + search : function(e, direction) { + if (!direction) direction = 1; + this.closeAutocomplete(); + this.app.searchBox.searchEvent(e); + _.defer(_.bind(function() { + this.app.searchBox.focusNextFacet(this, direction, {viewPosition: this.options.order}); + }, this)); + }, + + // Begin editing the facet's input. This is called when the user enters + // the input either from another facet or directly clicking on it. + // + // This method tells all other facets and inputs to disable so it can have + // the sole focus. It also prepares the autocompletion menu. + enableEdit : function() { + if (this.app.options.readOnly) return; + if (this.modes.editing != 'is') { + this.setMode('is', 'editing'); + this.deselectFacet(); + if (this.box.val() == '') { + this.box.val(this.model.get('value')); + } + } + + this.flags.canClose = false; + this.app.searchBox.disableFacets(this); + this.app.searchBox.addFocus(); + _.defer(_.bind(function() { + this.app.searchBox.addFocus(); + }, this)); + this.resize(); + this.searchAutocomplete(); + this.box.focus(); + }, + + // When the user blurs the input, they may either be going to another input + // or off the search box entirely. If they go to another input, this facet + // will be instantly disabled, and the canClose flag will be turned back off. + // + // However, if the user clicks elsewhere on the page, this method starts a timer + // that checks if any of the other inputs are selected or are being edited. If + // not, then it can finally close itself and its autocomplete menu. + deferDisableEdit : function() { + this.flags.canClose = true; + _.delay(_.bind(function() { + if (this.flags.canClose && !this.box.is(':focus') && + this.modes.editing == 'is' && this.modes.selected != 'is') { + this.disableEdit(); + } + }, this), 250); + }, + + // Called either by other facets receiving focus or by the timer in `deferDisableEdit`, + // this method will turn off the facet, remove any text selection, and close + // the autocomplete menu. + disableEdit : function() { + var newFacetQuery = VS.utils.inflector.trim(this.box.val()); + if (newFacetQuery != this.model.get('value')) { + this.set(newFacetQuery); + } + this.flags.canClose = false; + this.box.selectRange(0, 0); + this.box.blur(); + this.setMode('not', 'editing'); + this.closeAutocomplete(); + this.app.searchBox.removeFocus(); + }, + + // Selects the facet, which blurs the facet's input and highlights the facet. + // If this is the only facet being selected (and not part of a select all event), + // we attach a mouse/keyboard watcher to check if the next action by the user + // should delete this facet or just deselect it. + selectFacet : function(e) { + if (e) e.preventDefault(); + if (this.app.options.readOnly) return; + var allSelected = this.app.searchBox.allSelected(); + if (this.modes.selected == 'is') return; + + if (this.box.is(':focus')) { + this.box.setCursorPosition(0); + this.box.blur(); + } + + this.flags.canClose = false; + this.closeAutocomplete(); + this.setMode('is', 'selected'); + this.setMode('not', 'editing'); + if (!allSelected || e) { + $(document).unbind('keydown.facet', this.keydown); + $(document).unbind('click.facet', this.deselectFacet); + _.defer(_.bind(function() { + $(document).unbind('keydown.facet').bind('keydown.facet', this.keydown); + $(document).unbind('click.facet').one('click.facet', this.deselectFacet); + }, this)); + this.app.searchBox.disableFacets(this); + this.app.searchBox.addFocus(); + } + return false; + }, + + // Turns off highlighting on the facet. Called in a variety of ways, this + // only deselects the facet if it is selected, and then cleans up the + // keyboard/mouse watchers that were created when the facet was first + // selected. + deselectFacet : function(e) { + if (e) e.preventDefault(); + if (this.modes.selected == 'is') { + this.setMode('not', 'selected'); + this.closeAutocomplete(); + this.app.searchBox.removeFocus(); + } + $(document).unbind('keydown.facet', this.keydown); + $(document).unbind('click.facet', this.deselectFacet); + return false; + }, + + // Is the user currently focused in this facet's input field? + isFocused : function() { + return this.box.is(':focus'); + }, + + // Hovering over the delete button styles the facet so the user knows that + // the delete button will kill the entire facet. + showDelete : function() { + $(this.el).addClass('search_facet_maybe_delete'); + }, + + // On `mouseout`, the user is no longer hovering on the delete button. + hideDelete : function() { + $(this.el).removeClass('search_facet_maybe_delete'); + }, + + // When switching between facets, depending on the direction the cursor is + // coming from, the cursor in this facet's input field should match the original + // direction. + setCursorAtEnd : function(direction) { + if (direction == -1) { + this.box.setCursorPosition(this.box.val().length); + } else { + this.box.setCursorPosition(0); + } + }, + + // Deletes the facet and sends the cursor over to the nearest input field. + remove : function(e) { + var committed = this.model.get('value'); + this.deselectFacet(); + this.disableEdit(); + this.app.searchQuery.remove(this.model); + if (committed && this.app.options.autosearch) { + this.search(e, -1); + } else { + this.app.searchBox.renderFacets(); + this.app.searchBox.focusNextFacet(this, -1, {viewPosition: this.options.order}); + } + }, + + // Selects the text in the facet's input field. When the user tabs between + // facets, convention is to highlight the entire field. + selectText: function() { + this.box.selectRange(0, this.box.val().length); + }, + + // Handles all keyboard inputs when in the facet's input field. This checks + // for movement between facets and inputs, entering a new value that needs + // to be autocompleted, as well as the removal of this facet. + keydown : function(e) { + var key = VS.app.hotkeys.key(e); + + if (key == 'enter' && this.box.val()) { + this.disableEdit(); + this.search(e); + } else if (key == 'left') { + if (this.modes.selected == 'is') { + this.deselectFacet(); + this.app.searchBox.focusNextFacet(this, -1, {startAtEnd: -1}); + } else if (this.box.getCursorPosition() == 0 && !this.box.getSelection().length) { + this.selectFacet(); + } + } else if (key == 'right') { + if (this.modes.selected == 'is') { + e.preventDefault(); + this.deselectFacet(); + this.setCursorAtEnd(0); + this.enableEdit(); + } else if (this.box.getCursorPosition() == this.box.val().length) { + e.preventDefault(); + this.disableEdit(); + this.app.searchBox.focusNextFacet(this, 1); + } + } else if (VS.app.hotkeys.shift && key == 'tab') { + e.preventDefault(); + this.app.searchBox.focusNextFacet(this, -1, { + startAtEnd : -1, + skipToFacet : true, + selectText : true + }); + } else if (key == 'tab') { + e.preventDefault(); + this.app.searchBox.focusNextFacet(this, 1, { + skipToFacet : true, + selectText : true + }); + } else if (VS.app.hotkeys.command && (e.which == 97 || e.which == 65)) { + e.preventDefault(); + this.app.searchBox.selectAllFacets(); + return false; + } else if (VS.app.hotkeys.printable(e) && this.modes.selected == 'is') { + this.app.searchBox.focusNextFacet(this, -1, {startAtEnd: -1}); + this.remove(e); + } else if (key == 'backspace') { + $(document).on('keydown.backspace', function(e) { + if (VS.app.hotkeys.key(e) === 'backspace') { + e.preventDefault(); + } + }); + + $(document).on('keyup.backspace', function(e) { + $(document).off('.backspace'); + }); + + if (this.modes.selected == 'is') { + e.preventDefault(); + this.remove(e); + } else if (this.box.getCursorPosition() == 0 && + !this.box.getSelection().length) { + e.preventDefault(); + this.selectFacet(); + } + e.stopPropagation(); + } + + // Handle paste events + if (e.which == null) { + // this.searchAutocomplete(e); + _.defer(_.bind(this.resize, this, e)); + } else { + this.resize(e); + } + } + +}); + +})(); + +(function() { + +var $ = jQuery; // Handle namespaced jQuery + +// This is the visual search input that is responsible for creating new facets. +// There is one input placed in between all facets. +VS.ui.SearchInput = Backbone.View.extend({ + + type : 'text', + + className : 'search_input ui-menu', + + events : { + 'keypress input' : 'keypress', + 'keydown input' : 'keydown', + 'keyup input' : 'keyup', + 'click input' : 'maybeTripleClick', + 'dblclick input' : 'startTripleClickTimer' + }, + + initialize : function(options) { + this.options = _.extend({}, this.options, options); + + this.app = this.options.app; + this.flags = { + canClose : false + }; + _.bindAll(this, 'removeFocus', 'addFocus', 'moveAutocomplete', 'deferDisableEdit'); + }, + + // Rendering the input sets up autocomplete, events on focusing and blurring + // the input, and the auto-grow of the input. + render : function() { + $(this.el).html(JST['search_input']({ + readOnly: this.app.options.readOnly + })); + + this.setMode('not', 'editing'); + this.setMode('not', 'selected'); + this.box = this.$('input'); + this.box.autoGrowInput(); + this.box.bind('updated.autogrow', this.moveAutocomplete); + this.box.bind('blur', this.deferDisableEdit); + this.box.bind('focus', this.addFocus); + this.setupAutocomplete(); + + return this; + }, + + // Watches the input and presents an autocompleted menu, taking the + // remainder of the input field and adding a separate facet for it. + // + // See `addTextFacetRemainder` for explanation on how the remainder works. + setupAutocomplete : function() { + this.box.autocomplete({ + minLength : this.options.showFacets ? 0 : 1, + delay : 50, + autoFocus : true, + position : {offset : "0 -1"}, + source : _.bind(this.autocompleteValues, this), + // Prevent changing the input value on focus of an option + focus : function() { return false; }, + create : _.bind(function(e, ui) { + $(this.el).find('.ui-autocomplete-input').css('z-index','auto'); + }, this), + select : _.bind(function(e, ui) { + e.preventDefault(); + // stopPropogation does weird things in jquery-ui 1.9 + // e.stopPropagation(); + var remainder = this.addTextFacetRemainder(ui.item.label || ui.item.value); + var position = this.options.position + (remainder ? 1 : 0); + this.app.searchBox.addFacet(ui.item instanceof String ? ui.item : ui.item.value, '', position); + return false; + }, this) + }); + + // Renders the results grouped by the categories they belong to. + this.box.data('ui-autocomplete')._renderMenu = function(ul, items) { + var category = ''; + _.each(items, _.bind(function(item, i) { + if (item.category && item.category != category) { + ul.append('<li class="ui-autocomplete-category">'+item.category+'</li>'); + category = item.category; + } + + if(this._renderItemData) { + this._renderItemData(ul, item); + } else { + this._renderItem(ul, item); + } + + }, this)); + }; + + this.box.autocomplete('widget').addClass('VS-interface'); + }, + + // Search terms used in the autocomplete menu. The values are matched on the + // first letter of any word in matches, and finally sorted according to the + // value's own category. You can pass `preserveOrder` as an option in the + // `facetMatches` callback to skip any further ordering done client-side. + autocompleteValues : function(req, resp) { + var searchTerm = req.term; + var lastWord = searchTerm.match(/\w+\*?$/); // Autocomplete only last word. + var re = VS.utils.inflector.escapeRegExp(lastWord && lastWord[0] || ''); + this.app.options.callbacks.facetMatches(function(prefixes, options) { + options = options || {}; + prefixes = prefixes || []; + + // Only match from the beginning of the word. + var matcher = new RegExp('^' + re, 'i'); + var matches = $.grep(prefixes, function(item) { + return item && matcher.test(item.label || item); + }); + + if (options.preserveOrder) { + resp(matches); + } else { + resp(_.sortBy(matches, function(match) { + if (match.label) return match.category + '-' + match.label; + else return match; + })); + } + }); + + }, + + // Closes the autocomplete menu. Called on disabling, selecting, deselecting, + // and anything else that takes focus out of the facet's input field. + closeAutocomplete : function() { + var autocomplete = this.box.data('ui-autocomplete'); + if (autocomplete) autocomplete.close(); + }, + + // As the input field grows, it may move to the next line in the + // search box. `autoGrowInput` triggers an `updated` event on the input + // field, which is bound to this method to move the autocomplete menu. + moveAutocomplete : function() { + var autocomplete = this.box.data('ui-autocomplete'); + if (autocomplete) { + autocomplete.menu.element.position({ + my : "left top", + at : "left bottom", + of : this.box.data('ui-autocomplete').element, + collision : "none", + offset : '0 -1' + }); + } + }, + + // When a user enters a facet and it is being edited, immediately show + // the autocomplete menu and size it to match the contents. + searchAutocomplete : function(e) { + var autocomplete = this.box.data('ui-autocomplete'); + if (autocomplete) { + var menu = autocomplete.menu.element; + autocomplete.search(); + + // Resize the menu based on the correctly measured width of what's bigger: + // the menu's original size or the menu items' new size. + menu.outerWidth(Math.max( + menu.width('').outerWidth(), + autocomplete.element.outerWidth() + )); + } + }, + + // If a user searches for "word word category", the category would be + // matched and autocompleted, and when selected, the "word word" would + // also be caught as the remainder and then added in its own facet. + addTextFacetRemainder : function(facetValue) { + var boxValue = this.box.val(); + var lastWord = boxValue.match(/\b(\w+)$/); + + if (!lastWord) { + return ''; + } + + var matcher = new RegExp(lastWord[0], "i"); + if (facetValue.search(matcher) == 0) { + boxValue = boxValue.replace(/\b(\w+)$/, ''); + } + boxValue = boxValue.replace('^\s+|\s+$', ''); + + if (boxValue) { + this.app.searchBox.addFacet(this.app.options.remainder, boxValue, this.options.position); + } + + return boxValue; + }, + + // Directly called to focus the input. This is different from `addFocus` + // because this is not called by a focus event. This instead calls a + // focus event causing the input to become focused. + enableEdit : function(selectText) { + this.addFocus(); + if (selectText) { + this.selectText(); + } + this.box.focus(); + }, + + // Event called on user focus on the input. Tells all other input and facets + // to give up focus, and starts revving the autocomplete. + addFocus : function() { + this.flags.canClose = false; + if (!this.app.searchBox.allSelected()) { + this.app.searchBox.disableFacets(this); + } + this.app.searchBox.addFocus(); + this.setMode('is', 'editing'); + this.setMode('not', 'selected'); + if (!this.app.searchBox.allSelected()) { + this.searchAutocomplete(); + } + }, + + // Directly called to blur the input. This is different from `removeFocus` + // because this is not called by a blur event. + disableEdit : function() { + this.box.blur(); + this.removeFocus(); + }, + + // Event called when user blur's the input, either through the keyboard tabbing + // away or the mouse clicking off. Cleans up + removeFocus : function() { + this.flags.canClose = false; + this.app.searchBox.removeFocus(); + this.setMode('not', 'editing'); + this.setMode('not', 'selected'); + this.closeAutocomplete(); + }, + + // When the user blurs the input, they may either be going to another input + // or off the search box entirely. If they go to another input, this facet + // will be instantly disabled, and the canClose flag will be turned back off. + // + // However, if the user clicks elsewhere on the page, this method starts a timer + // that checks if any of the other inputs are selected or are being edited. If + // not, then it can finally close itself and its autocomplete menu. + deferDisableEdit : function() { + this.flags.canClose = true; + _.delay(_.bind(function() { + if (this.flags.canClose && + !this.box.is(':focus') && + this.modes.editing == 'is') { + this.disableEdit(); + } + }, this), 250); + }, + + // Starts a timer that will cause a triple-click, which highlights all facets. + startTripleClickTimer : function() { + this.tripleClickTimer = setTimeout(_.bind(function() { + this.tripleClickTimer = null; + }, this), 500); + }, + + // Event on click that checks if a triple click is in play. The + // `tripleClickTimer` is counting down, ready to be engaged and intercept + // the click event to force a select all instead. + maybeTripleClick : function(e) { + if (this.app.options.readOnly) return; + if (!!this.tripleClickTimer) { + e.preventDefault(); + this.app.searchBox.selectAllFacets(); + return false; + } + }, + + // Is the user currently focused in the input field? + isFocused : function() { + return this.box.is(':focus'); + }, + + // When serializing the facets, the inputs need to also have their values represented, + // in case they contain text that is not yet faceted (but will be once the search is + // completed). + value : function() { + return this.box.val(); + }, + + // When switching between facets and inputs, depending on the direction the cursor + // is coming from, the cursor in this facet's input field should match the original + // direction. + setCursorAtEnd : function(direction) { + if (direction == -1) { + this.box.setCursorPosition(this.box.val().length); + } else { + this.box.setCursorPosition(0); + } + }, + + // Selects the entire range of text in the input. Useful when tabbing between inputs + // and facets. + selectText : function() { + this.box.selectRange(0, this.box.val().length); + if (!this.app.searchBox.allSelected()) { + this.box.focus(); + } else { + this.setMode('is', 'selected'); + } + }, + + // Before the searchBox performs a search, we need to close the + // autocomplete menu. + search : function(e, direction) { + if (!direction) direction = 0; + this.closeAutocomplete(); + this.app.searchBox.searchEvent(e); + _.defer(_.bind(function() { + this.app.searchBox.focusNextFacet(this, direction); + }, this)); + }, + + // Callback fired on key press in the search box. We search when they hit return. + keypress : function(e) { + var key = VS.app.hotkeys.key(e); + + if (key == 'enter') { + return this.search(e, 100); + } else if (VS.app.hotkeys.colon(e)) { + this.box.trigger('resize.autogrow', e); + var query = this.box.val(); + var prefixes = []; + this.app.options.callbacks.facetMatches(function(p) { + prefixes = p; + }); + var labels = _.map(prefixes, function(prefix) { + if (prefix.label) return prefix.label; + else return prefix; + }); + if (_.contains(labels, query)) { + e.preventDefault(); + var remainder = this.addTextFacetRemainder(query); + var position = this.options.position + (remainder?1:0); + this.app.searchBox.addFacet(query, '', position); + return false; + } + } else if (key == 'backspace') { + if (this.box.getCursorPosition() == 0 && !this.box.getSelection().length) { + e.preventDefault(); + e.stopPropagation(); + e.stopImmediatePropagation(); + this.app.searchBox.resizeFacets(); + return false; + } + } + }, + + // Handles all keyboard inputs when in the input field. This checks + // for movement between facets and inputs, entering a new value that needs + // to be autocompleted, as well as stepping between facets with backspace. + keydown : function(e) { + var key = VS.app.hotkeys.key(e); + + if (key == 'left') { + if (this.box.getCursorPosition() == 0) { + e.preventDefault(); + this.app.searchBox.focusNextFacet(this, -1, {startAtEnd: -1}); + } + } else if (key == 'right') { + if (this.box.getCursorPosition() == this.box.val().length) { + e.preventDefault(); + this.app.searchBox.focusNextFacet(this, 1, {selectFacet: true}); + } + } else if (VS.app.hotkeys.shift && key == 'tab') { + e.preventDefault(); + this.app.searchBox.focusNextFacet(this, -1, {selectText: true}); + } else if (key == 'tab') { + var value = this.box.val(); + if (value.length) { + e.preventDefault(); + var remainder = this.addTextFacetRemainder(value); + var position = this.options.position + (remainder?1:0); + if (value != remainder) { + this.app.searchBox.addFacet(value, '', position); + } + } else { + var foundFacet = this.app.searchBox.focusNextFacet(this, 0, { + skipToFacet: true, + selectText: true + }); + if (foundFacet) { + e.preventDefault(); + } + } + } else if (VS.app.hotkeys.command && + String.fromCharCode(e.which).toLowerCase() == 'a') { + e.preventDefault(); + this.app.searchBox.selectAllFacets(); + return false; + } else if (key == 'backspace' && !this.app.searchBox.allSelected()) { + if (this.box.getCursorPosition() == 0 && !this.box.getSelection().length) { + e.preventDefault(); + this.app.searchBox.focusNextFacet(this, -1, {backspace: true}); + return false; + } + } else if (key == 'end') { + var view = this.app.searchBox.inputViews[this.app.searchBox.inputViews.length-1]; + view.setCursorAtEnd(-1); + } else if (key == 'home') { + var view = this.app.searchBox.inputViews[0]; + view.setCursorAtEnd(-1); + } + + }, + + // We should get the value of an input should be done + // on keyup since keydown gets the previous value and not the current one + keyup : function(e) { + this.box.trigger('resize.autogrow', e); + } + +}); + +})(); + +(function(){ + + var $ = jQuery; // Handle namespaced jQuery + + // Makes the view enter a mode. Modes have both a 'mode' and a 'group', + // and are mutually exclusive with any other modes in the same group. + // Setting will update the view's modes hash, as well as set an HTML class + // of *[mode]_[group]* on the view's element. Convenient way to swap styles + // and behavior. + Backbone.View.prototype.setMode = function(mode, group) { + this.modes || (this.modes = {}); + if (this.modes[group] === mode) return; + $(this.el).setMode(mode, group); + this.modes[group] = mode; + }; + +})(); +(function() { + +var $ = jQuery; // Handle namespaced jQuery + +// DocumentCloud workspace hotkeys. To tell if a key is currently being pressed, +// just ask `VS.app.hotkeys.[key]` on `keypress`, or ask `VS.app.hotkeys.key(e)` +// on `keydown`. +// +// For the most headache-free way to use this utility, check modifier keys, +// like shift and command, with `VS.app.hotkeys.shift`, and check every other +// key with `VS.app.hotkeys.key(e) == 'key_name'`. +VS.app.hotkeys = { + + // Keys that will be mapped to the `hotkeys` namespace. + KEYS: { + '16': 'shift', + '17': 'command', + '91': 'command', + '93': 'command', + '224': 'command', + '13': 'enter', + '37': 'left', + '38': 'upArrow', + '39': 'right', + '40': 'downArrow', + '46': 'delete', + '8': 'backspace', + '35': 'end', + '36': 'home', + '9': 'tab', + '188': 'comma' + }, + + // Binds global keydown and keyup events to listen for keys that match `this.KEYS`. + initialize : function() { + _.bindAll(this, 'down', 'up', 'blur'); + $(document).bind('keydown', this.down); + $(document).bind('keyup', this.up); + $(window).bind('blur', this.blur); + }, + + // On `keydown`, turn on all keys that match. + down : function(e) { + var key = this.KEYS[e.which]; + if (key) this[key] = true; + }, + + // On `keyup`, turn off all keys that match. + up : function(e) { + var key = this.KEYS[e.which]; + if (key) this[key] = false; + }, + + // If an input is blurred, all keys need to be turned off, since they are no longer + // able to modify the document. + blur : function(e) { + for (var key in this.KEYS) this[this.KEYS[key]] = false; + }, + + // Check a key from an event and return the common english name. + key : function(e) { + return this.KEYS[e.which]; + }, + + // Colon is special, since the value is different between browsers. + colon : function(e) { + var charCode = e.which; + return charCode && String.fromCharCode(charCode) == ":"; + }, + + // Check a key from an event and match it against any known characters. + // The `keyCode` is different depending on the event type: `keydown` vs. `keypress`. + // + // These were determined by looping through every `keyCode` and `charCode` that + // resulted from `keydown` and `keypress` events and counting what was printable. + printable : function(e) { + var code = e.which; + if (e.type == 'keydown') { + if (code == 32 || // space + (code >= 48 && code <= 90) || // 0-1a-z + (code >= 96 && code <= 111) || // 0-9+-/*. + (code >= 186 && code <= 192) || // ;=,-./^ + (code >= 219 && code <= 222)) { // (\)' + return true; + } + } else { + // [space]!"#$%&'()*+,-.0-9:;<=>?@A-Z[\]^_`a-z{|} and unicode characters + if ((code >= 32 && code <= 126) || + (code >= 160 && code <= 500) || + (String.fromCharCode(code) == ":")) { + return true; + } + } + return false; + } + +}; + +})(); +(function() { + +var $ = jQuery; // Handle namespaced jQuery + +// Naive English transformations on words. Only used for a few transformations +// in VisualSearch.js. +VS.utils.inflector = { + + // Delegate to the ECMA5 String.prototype.trim function, if available. + trim : function(s) { + return s.trim ? s.trim() : s.replace(/^\s+|\s+$/g, ''); + }, + + // Escape strings that are going to be used in a regex. Escapes punctuation + // that would be incorrect in a regex. + escapeRegExp : function(s) { + return s.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1'); + } +}; + +})(); +(function() { + +var $ = jQuery; // Handle namespaced jQuery + +$.fn.extend({ + + // Makes the selector enter a mode. Modes have both a 'mode' and a 'group', + // and are mutually exclusive with any other modes in the same group. + // Setting will update the view's modes hash, as well as set an HTML class + // of *[mode]_[group]* on the view's element. Convenient way to swap styles + // and behavior. + setMode : function(state, group) { + group = group || 'mode'; + var re = new RegExp("\\w+_" + group + "(\\s|$)", 'g'); + var mode = (state === null) ? "" : state + "_" + group; + this.each(function() { + this.className = (this.className.replace(re, '')+' '+mode) + .replace(/\s\s/g, ' '); + }); + return mode; + }, + + // When attached to an input element, this will cause the width of the input + // to match its contents. This calculates the width of the contents of the input + // by measuring a hidden shadow div that should match the styling of the input. + autoGrowInput: function() { + return this.each(function() { + var $input = $(this); + var $tester = $('<div />').css({ + opacity : 0, + top : -9999, + left : -9999, + position : 'absolute', + whiteSpace : 'nowrap' + }).addClass('VS-input-width-tester').addClass('VS-interface'); + + // Watch for input value changes on all of these events. `resize` + // event is called explicitly when the input has been changed without + // a single keypress. + var events = 'keydown.autogrow keypress.autogrow ' + + 'resize.autogrow change.autogrow'; + $input.next('.VS-input-width-tester').remove(); + $input.after($tester); + $input.unbind(events).bind(events, function(e, realEvent) { + if (realEvent) e = realEvent; + var value = $input.val(); + + // Watching for the backspace key is tricky because it may not + // actually be deleting the character, but instead the key gets + // redirected to move the cursor from facet to facet. + if (VS.app.hotkeys.key(e) == 'backspace') { + var position = $input.getCursorPosition(); + if (position > 0) value = value.slice(0, position-1) + + value.slice(position, value.length); + } else if (VS.app.hotkeys.printable(e) && + !VS.app.hotkeys.command) { + value += String.fromCharCode(e.which); + } + value = value.replace(/&/g, '&amp;') + .replace(/\s/g,'&nbsp;') + .replace(/</g, '&lt;') + .replace(/>/g, '&gt;'); + + $tester.html(value); + + $input.width($tester.width() + 3 + parseInt($input.css('min-width'))); + $input.trigger('updated.autogrow'); + }); + + // Sets the width of the input on initialization. + $input.trigger('resize.autogrow'); + }); + }, + + + // Cross-browser method used for calculating where the cursor is in an + // input field. + getCursorPosition: function() { + var position = 0; + var input = this.get(0); + + if (document.selection) { // IE + input.focus(); + var sel = document.selection.createRange(); + var selLen = document.selection.createRange().text.length; + sel.moveStart('character', -input.value.length); + position = sel.text.length - selLen; + } else if (input && $(input).is(':visible') && + input.selectionStart != null) { // Firefox/Safari + position = input.selectionStart; + } + + return position; + }, + + // A simple proxy for `selectRange` that sets the cursor position in an + // input field. + setCursorPosition: function(position) { + return this.each(function() { + return $(this).selectRange(position, position); + }); + }, + + // Cross-browser way to select text in an input field. + selectRange: function(start, end) { + return this.filter(':visible').each(function() { + if (this.setSelectionRange) { // FF/Webkit + this.focus(); + this.setSelectionRange(start, end); + } else if (this.createTextRange) { // IE + var range = this.createTextRange(); + range.collapse(true); + range.moveEnd('character', end); + range.moveStart('character', start); + if (end - start >= 0) range.select(); + } + }); + }, + + // Returns an object that contains the text selection range values for + // an input field. + getSelection: function() { + var input = this[0]; + + if (input.selectionStart != null) { // FF/Webkit + var start = input.selectionStart; + var end = input.selectionEnd; + return { + start : start, + end : end, + length : end-start, + text : input.value.substr(start, end-start) + }; + } else if (document.selection) { // IE + var range = document.selection.createRange(); + if (range) { + var textRange = input.createTextRange(); + var copyRange = textRange.duplicate(); + textRange.moveToBookmark(range.getBookmark()); + copyRange.setEndPoint('EndToStart', textRange); + var start = copyRange.text.length; + var end = start + range.text.length; + return { + start : start, + end : end, + length : end-start, + text : range.text + }; + } + } + return {start: 0, end: 0, length: 0}; + } + +}); + +// Debugging in Internet Explorer. This allows you to use +// `console.log(['message', var1, var2, ...])`. Just remove the `false` and +// add your console.logs. This will automatically stringify objects using +// `JSON.stringify', so you can read what's going out. Think of this as a +// *Diet Firebug Lite Zero with Lemon*. +if (false) { + window.console = {}; + var _$ied; + window.console.log = function(msg) { + if (_.isArray(msg)) { + var message = msg[0]; + var vars = _.map(msg.slice(1), function(arg) { + return JSON.stringify(arg); + }).join(' - '); + } + if(!_$ied){ + _$ied = $('<div><ol></ol></div>').css({ + 'position': 'fixed', + 'bottom': 10, + 'left': 10, + 'zIndex': 20000, + 'width': $('body').width() - 80, + 'border': '1px solid #000', + 'padding': '10px', + 'backgroundColor': '#fff', + 'fontFamily': 'arial,helvetica,sans-serif', + 'fontSize': '11px' + }); + $('body').append(_$ied); + } + var $message = $('<li>'+message+' - '+vars+'</li>').css({ + 'borderBottom': '1px solid #999999' + }); + _$ied.find('ol').append($message); + _.delay(function() { + $message.fadeOut(500); + }, 5000); + }; + +} + +})(); + +(function() { + +var $ = jQuery; // Handle namespaced jQuery + +// Used to extract keywords and facets from the free text search. +var QUOTES_RE = "('[^']+'|\"[^\"]+\")"; +var FREETEXT_RE = "('[^']+'|\"[^\"]+\"|[^'\"\\s]\\S*)"; +var CATEGORY_RE = FREETEXT_RE + ':\\s*'; +VS.app.SearchParser = { + + // Matches `category: "free text"`, with and without quotes. + ALL_FIELDS : new RegExp(CATEGORY_RE + FREETEXT_RE, 'g'), + + // Matches a single category without the text. Used to correctly extract facets. + CATEGORY : new RegExp(CATEGORY_RE), + + // Called to parse a query into a collection of `SearchFacet` models. + parse : function(instance, query) { + var searchFacets = this._extractAllFacets(instance, query); + instance.searchQuery.reset(searchFacets); + return searchFacets; + }, + + // Walks the query and extracts facets, categories, and free text. + _extractAllFacets : function(instance, query) { + var facets = []; + var originalQuery = query; + while (query) { + var category, value; + originalQuery = query; + var field = this._extractNextField(query); + if (!field) { + category = instance.options.remainder; + value = this._extractSearchText(query); + query = VS.utils.inflector.trim(query.replace(value, '')); + } else if (field.indexOf(':') != -1) { + category = field.match(this.CATEGORY)[1].replace(/(^['"]|['"]$)/g, ''); + value = field.replace(this.CATEGORY, '').replace(/(^['"]|['"]$)/g, ''); + query = VS.utils.inflector.trim(query.replace(field, '')); + } else if (field.indexOf(':') == -1) { + category = instance.options.remainder; + value = field; + query = VS.utils.inflector.trim(query.replace(value, '')); + } + + if (category && value) { + var searchFacet = new VS.model.SearchFacet({ + category : category, + value : VS.utils.inflector.trim(value), + app : instance + }); + facets.push(searchFacet); + } + if (originalQuery == query) break; + } + + return facets; + }, + + // Extracts the first field found, capturing any free text that comes + // before the category. + _extractNextField : function(query) { + var textRe = new RegExp('^\\s*(\\S+)\\s+(?=' + QUOTES_RE + FREETEXT_RE + ')'); + var textMatch = query.match(textRe); + if (textMatch && textMatch.length >= 1) { + return textMatch[1]; + } else { + return this._extractFirstField(query); + } + }, + + // If there is no free text before the facet, extract the category and value. + _extractFirstField : function(query) { + var fields = query.match(this.ALL_FIELDS); + return fields && fields.length && fields[0]; + }, + + // If the found match is not a category and facet, extract the trimmed free text. + _extractSearchText : function(query) { + query = query || ''; + var text = VS.utils.inflector.trim(query.replace(this.ALL_FIELDS, '')); + return text; + } + +}; + +})(); + +(function() { + +var $ = jQuery; // Handle namespaced jQuery + +// The model that holds individual search facets and their categories. +// Held in a collection by `VS.app.searchQuery`. +VS.model.SearchFacet = Backbone.Model.extend({ + + // Extract the category and value and serialize it in preparation for + // turning the entire searchBox into a search query that can be sent + // to the server for parsing and searching. + serialize : function() { + var category = this.quoteCategory(this.get('category')); + var value = VS.utils.inflector.trim(this.get('value')); + var remainder = this.get("app").options.remainder; + + if (!value) return ''; + + if (!_.contains(this.get("app").options.unquotable || [], category) && category != remainder) { + value = this.quoteValue(value); + } + + if (category != remainder) { + category = category + ': '; + } else { + category = ""; + } + return category + value; + }, + + // Wrap categories that have spaces or any kind of quote with opposite matching + // quotes to preserve the complex category during serialization. + quoteCategory : function(category) { + var hasDoubleQuote = (/"/).test(category); + var hasSingleQuote = (/'/).test(category); + var hasSpace = (/\s/).test(category); + + if (hasDoubleQuote && !hasSingleQuote) { + return "'" + category + "'"; + } else if (hasSpace || (hasSingleQuote && !hasDoubleQuote)) { + return '"' + category + '"'; + } else { + return category; + } + }, + + // Wrap values that have quotes in opposite matching quotes. If a value has + // both single and double quotes, just use the double quotes. + quoteValue : function(value) { + var hasDoubleQuote = (/"/).test(value); + var hasSingleQuote = (/'/).test(value); + + if (hasDoubleQuote && !hasSingleQuote) { + return "'" + value + "'"; + } else { + return '"' + value + '"'; + } + }, + + // If provided, use a custom label instead of the raw value. + label : function() { + return this.get('label') || this.get('value'); + } + +}); + +})(); +(function() { + +var $ = jQuery; // Handle namespaced jQuery + +// Collection which holds all of the individual facets (category: value). +// Used for finding and removing specific facets. +VS.model.SearchQuery = Backbone.Collection.extend({ + + // Model holds the category and value of the facet. + model : VS.model.SearchFacet, + + // Turns all of the facets into a single serialized string. + serialize : function() { + return this.map(function(facet){ return facet.serialize(); }).join(' '); + }, + + facets : function() { + return this.map(function(facet) { + var value = {}; + value[facet.get('category')] = facet.get('value'); + return value; + }); + }, + + // Find a facet by its category. Multiple facets with the same category + // is fine, but only the first is returned. + find : function(category) { + var facet = this.detect(function(facet) { + return facet.get('category').toLowerCase() == category.toLowerCase(); + }); + return facet && facet.get('value'); + }, + + // Counts the number of times a specific category is in the search query. + count : function(category) { + return this.select(function(facet) { + return facet.get('category').toLowerCase() == category.toLowerCase(); + }).length; + }, + + // Returns an array of extracted values from each facet in a category. + values : function(category) { + var facets = this.select(function(facet) { + return facet.get('category').toLowerCase() == category.toLowerCase(); + }); + return _.map(facets, function(facet) { return facet.get('value'); }); + }, + + // Checks all facets for matches of either a category or both category and value. + has : function(category, value) { + return this.any(function(facet) { + var categoryMatched = facet.get('category').toLowerCase() == category.toLowerCase(); + if (!value) return categoryMatched; + return categoryMatched && facet.get('value') == value; + }); + }, + + // Used to temporarily hide specific categories and serialize the search query. + withoutCategory : function() { + var categories = _.map(_.toArray(arguments), function(cat) { return cat.toLowerCase(); }); + return this.map(function(facet) { + if (!_.include(categories, facet.get('category').toLowerCase())) { + return facet.serialize(); + }; + }).join(' '); + } + +}); + +})(); +(function(){ +window.JST = window.JST || {}; + +window.JST['search_box'] = _.template('<div class="VS-search <% if (readOnly) { %>VS-readonly<% } %>">\n <div class="VS-search-box-wrapper VS-search-box">\n <div class="VS-icon VS-icon-search"></div>\n <div class="VS-placeholder"></div>\n <div class="VS-search-inner"></div>\n <div class="VS-icon VS-icon-cancel VS-cancel-search-box" title="clear search"></div>\n </div>\n</div>'); +window.JST['search_facet'] = _.template('<% if (model.has(\'category\')) { %>\n <div class="category"><%= model.get(\'category\') %>:</div>\n<% } %>\n\n<div class="search_facet_input_container">\n <input type="text" class="search_facet_input ui-menu VS-interface" value="" <% if (readOnly) { %>disabled="disabled"<% } %> />\n</div>\n\n<div class="search_facet_remove VS-icon VS-icon-cancel"></div>'); +window.JST['search_input'] = _.template('<input type="text" class="ui-menu" <% if (readOnly) { %>disabled="disabled"<% } %> />'); +})(); \ No newline at end of file diff --git a/src/static/js/slick/ajax-loader.gif b/src/static/js/slick/ajax-loader.gif new file mode 100755 index 0000000000000000000000000000000000000000..e0e6e9760bc04861cc4771e327f22ed7962e0858 GIT binary patch literal 4178 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 literal 0 HcmV?d00001 diff --git a/src/static/js/slick/config.rb b/src/static/js/slick/config.rb new file mode 100755 index 0000000..81f5ae3 --- /dev/null +++ b/src/static/js/slick/config.rb @@ -0,0 +1,10 @@ +css_dir = "." +sass_dir = "." +images_dir = "." +fonts_dir = "fonts" +relative_assets = true + +output_style = :compact +line_comments = false + +preferred_syntax = :scss \ No newline at end of file diff --git a/src/static/js/slick/fonts/slick.eot b/src/static/js/slick/fonts/slick.eot new file mode 100755 index 0000000000000000000000000000000000000000..2cbab9ca97723bc24c50315a0a9bd155db4e0aa5 GIT binary patch literal 2048 zcmcgtO>7%Q6n^9V^B-}NZk*EEVeMi&O%prb7zafaL6A786eTJs%>e;R;y4y|oY<}i z5)vjt;=&>7feV}}ai#*PAS5oRLOp@#1tg<V32}vTXfFtvZ)V4hle7nf#Mra*-uK>{ z_p`I}$V;?l5Ha!)A0E<tf&j9|ICXvrOUrUW@f0wq#s2GedSFTVsX-Mg(<;3Iq>nC8 zkxFz4m_v0SVOj=KhgO+tv`H3aDNU1*9JB<$9X&!VQfR4Ac<F`e4>vv~GM)n(S(uwI zP>yu)qu{N@7c=(ay}v($(F*wG)vB`<56yoK{s!jjC8x2~>0l=^EXcj3%3JHRA6<Km zNI8qF$2W@38nNtOko}CA-vFTe=Fwnlf`5FY+T794(K+x}!G|lgRfq1eE3h92-(Pih zw&;0Ufc#1D)}~V}YN>a>A<{O0ZEn>X&CKUE{OdnKJ}+`Zes`|-FTNT&dzS)k{lDMd zc?WV5Yl0H2&DvnS^7UXV{5g_#^+EG0^$t}a2F=}nrQC{ZJuTIkhu9uz<YnjCI<N(~ z-la$Bz1}m>68^}NcC@rUzlL3$*kyLRbDPqv-Qlsw2;7Lcy_kqz{J1gl7BeDsUk1mm zBBY9_f+9l|h-1ZLd$G%SSA6tvolk!G^;YxNcGsJb<H2wSWB`Q3T=!ieU%SFy?BCMx z@t+6I(*H0D^Z{LEVZ4Oy={Zg~p|dQX%dq6Bc!=pk=3~qd&+wF;Hx1p;<EdmSnVZf} z=k4L}@SnT7zN;BtEvoAmFY0<!^BR9dN9@VBC+(4Fm)PFb`=F+cXogQ+Sy6ok$eRaL zxGr)&6iZ?{{{(_@pKeHq=pnJN(VieQ8Q7QI81{oX5C!yjXb%d8-LK0rMD~E>S^LQ5 z?5U$!?eFs}j@Xc?pJ6ECEH5!HsG*xEBz{viuj-VI1c!vTQ=-<g+FSyy>HKh*wf){! zK-YYuV>8i6WY7!-0zq>y5{bq~tYbP;m6YO%ojIM$B*#yjGzSLElPAWLnX%OAXu=x| zurFF(e<0vXrCh5ScZ*P8M1i5=QB$Vrn!MuLhXx`EuPP6AkUo^(3B$b*l(dHoic4Cd z7%pq~TT-F(v7|K$&{vYyf#2j`w(0}oM}1w|gElZIX@#DlF-fb?*^{(}#&AW_I`D6M z+eo8QUPU)K)JiTCOP4ARdP+ewlBQVeXf{Q%$QDh-q8ZTp4aw!R=o}Mb+GsqSqe5-7 zS*X=ZMaxc4S~HgLh&7v=$W7RjS*YyqLNcC*G_vJly-}`hTG=$Z+EJ^+H`LMl3H=!L z^Dqxn=zW^=JN0_)&3d`C(ew$jQe1CBg=^uS#AObu5A!&O1h1eoGTg0QU&6<CzyHX4 Jm)l$9`VTQ&{XGBx literal 0 HcmV?d00001 diff --git a/src/static/js/slick/fonts/slick.svg b/src/static/js/slick/fonts/slick.svg new file mode 100755 index 0000000..b36a66a --- /dev/null +++ b/src/static/js/slick/fonts/slick.svg @@ -0,0 +1,14 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata>Generated by Fontastic.me</metadata> +<defs> +<font id="slick" horiz-adv-x="512"> +<font-face font-family="slick" units-per-em="512" ascent="480" descent="-32"/> +<missing-glyph horiz-adv-x="512" /> + +<glyph unicode="&#8594;" d="M241 113l130 130c4 4 6 8 6 13 0 5-2 9-6 13l-130 130c-3 3-7 5-12 5-5 0-10-2-13-5l-29-30c-4-3-6-7-6-12 0-5 2-10 6-13l87-88-87-88c-4-3-6-8-6-13 0-5 2-9 6-12l29-30c3-3 8-5 13-5 5 0 9 2 12 5z m234 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/> +<glyph unicode="&#8592;" d="M296 113l29 30c4 3 6 7 6 12 0 5-2 10-6 13l-87 88 87 88c4 3 6 8 6 13 0 5-2 9-6 12l-29 30c-3 3-8 5-13 5-5 0-9-2-12-5l-130-130c-4-4-6-8-6-13 0-5 2-9 6-13l130-130c3-3 7-5 12-5 5 0 10 2 13 5z m179 143c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/> +<glyph unicode="&#8226;" d="M475 256c0-40-9-77-29-110-20-34-46-60-80-80-33-20-70-29-110-29-40 0-77 9-110 29-34 20-60 46-80 80-20 33-29 70-29 110 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/> +<glyph unicode="&#97;" d="M475 439l0-128c0-5-1-9-5-13-4-4-8-5-13-5l-128 0c-8 0-13 3-17 11-3 7-2 14 4 20l40 39c-28 26-62 39-100 39-20 0-39-4-57-11-18-8-33-18-46-32-14-13-24-28-32-46-7-18-11-37-11-57 0-20 4-39 11-57 8-18 18-33 32-46 13-14 28-24 46-32 18-7 37-11 57-11 23 0 44 5 64 15 20 9 38 23 51 42 2 1 4 3 7 3 3 0 5-1 7-3l39-39c2-2 3-3 3-6 0-2-1-4-2-6-21-25-46-45-76-59-29-14-60-20-93-20-30 0-58 5-85 17-27 12-51 27-70 47-20 19-35 43-47 70-12 27-17 55-17 85 0 30 5 58 17 85 12 27 27 51 47 70 19 20 43 35 70 47 27 12 55 17 85 17 28 0 55-5 81-15 26-11 50-26 70-45l37 37c6 6 12 7 20 4 8-4 11-9 11-17z"/> +</font></defs></svg> diff --git a/src/static/js/slick/fonts/slick.ttf b/src/static/js/slick/fonts/slick.ttf new file mode 100755 index 0000000000000000000000000000000000000000..9d03461b653373f7cda3b4af104c6bca07f9892b GIT binary patch literal 1892 zcmcgtO>7%Q7=7dYvttuC>BcFo9o8<6(=@T2jd4&^kqQzA6;LWbX$}ZjQpdJ%;>2-9 zkdO!w5*H3p4_x3>i8B>Q1tD=k2=xS_7m$ofCB&7VLwiBUyq#S)NmC98iCxXk_rBjZ z-_FiL0C)h~P;kCfdj6T!@2-CY7*A3gpP!v8p#YtDgxFemE@v;?`RijqED<j*uR80g z=-d~?*EwFPIGgL84l}{9Xb)EEudmF!f9+*JIRga7s%7UQ#KfPp{m4<QQlb13&=_kH zKU`gHZRzK5j`%8Ztln65a7SEW{21|(RcC7*Php<+M~SU9XSJ+l-ue>Is?@EmH#S?j zPi)rLf1rI1?%Fth|LVxXOVKm85e`rRe7mvr=G{4sv}lVqaS)za#z;-pQ&4s@?Y~s1 zF)-`LxQ;^V&iZa50I>@VLGiR$p>E!vZ{tC{&2B&od7j&{9xM+5=U3(~;w+rxWpS%> z3t7?bxa@oeU5f6^LH6=?gSl=w;=b<-L~c|ZD)Rvmxk8naW2KV2$;*6K?zInfKK$wD zo2{E0-D=X#hu|LQwtx$hrMosccZ~;>{}Qmqf4;bv{)elCcX3t3_yW4S=NPy{XGF1( z6T>G{QK1i*4+%p)W0Q8#G;~8xWrj1ug{k6H(H@Kq{;{L$JDL&H61sljg03gDpz&K` z$j-l!w}%p4VPi+{rJFXS86kCPNevkkZya!OeYxg)xTL3wkC2S_^eB<hKX4Hv`$%X$ zvCq03_Q)JyK|hz;{m6*BeK|^I_gTDXA4)DBJG`pBJWp`{4Ve0A!6weQEp{7f=q4M< zd(w8hI%#u(1G3sl*=xVsu7zGx#le_p_XM}Yx)vH4oleB#{bnQ_j+p)Ncp^1q9o2=Z zWRyVi^r=E_c<lHIv#-xQaeQnzH<~$>NCzWf@#%K3CmarCGG5fQmm=C5R~V=S)Qo9* zAuoFI(Y|;(sQMc_g7^H7Nbp>U_;LUSQogJpi8WtV>GOdvYY5|WU)HI=;eOd_h?*Yu z*OLS2MZYgAcpRg?tkP%Kmo>z2#g}#Jzs4r&s9_ne0-N>PGN)%zMg^CschDp(S1#2Z z3MDkittICsJ<70PBa1xeX^y>29-iQzV_XiKJ}yG3vDPXznw7F;XY<yyB`b2CD2x}z z?fe8?_Of*OEV5FQ`kJh7F_T*pi{<8Kt+8fJWC;#O-FreEKA#MBP9PuxLcu$j?QxpT y#%s-5rP>Nfv0h$j(Z%)RImyGEQZL6bS0%B+KcnE;+N~vPeDmw~?!W86Kjv>PckT%Q literal 0 HcmV?d00001 diff --git a/src/static/js/slick/fonts/slick.woff b/src/static/js/slick/fonts/slick.woff new file mode 100755 index 0000000000000000000000000000000000000000..8ee99721bb81b59a5e1ceee1d3256b15f907d96b GIT binary patch literal 1380 zcmZWoc~H_>9DiItQdGPuZL>_xgDjCHpv=4wk37&Nx3m(F$RqMd4ZI>#sTnIvS4$mr zYIRq0kV)NX%VjCA6!RLbG&S?cF0*sBT4Nv8fBW8i=FR8xz30vMSTKtf%;5wBfD-@$ zfCs-1ptSG*j~9z&2>@yZ0O&0cW$QnM8L(KKKmafd=)DGFt!Us*gAdc21vQSALs$X| zzy|;1M1fiY<e?B;wwXpACE`JjX@i^%^YX0-OhxoTo&W%>Db!#MKm#b}&(TnX8WVDD zJ{!y|8WSx_7DJ5-xq%i~f8a0TiD5phwg&PQI5s%K6CH#a^aW$E#u1#|iQ5VBN0Z^a z+Wrh7ECB|f#O1CR`r?f}Ogj%bMA#Kog;~-(rbgn@>1o4d$4nYiRyuAWwB_b_E;YM} zZ@NV6aV$`k?$I^#Wy?FR9QXZfCw>r^*1y-k$0lC+Q7Ne`X`$=sB1Wy`n;#2J7g5fr zwyHxDSEMClZ`L6n$e70#EAWLIl3&MaoK(k+l#St%Y&(Sx=VqDv(*x+{1v@swNPOd5 z_D&(udjRFH?3%?ol%y>x6(M%<A8*&(7kTBF<%WcyTz%>zP2C#?oZgpRVvQB6J2<-s z1XZ2vz<(2aNi{4LTCF&Bx<P(Up4mCd$l2bwEv}U6r+@hpDRr8jSZtp+Wli-Cd0m<H zGSPnO%a~$TKjO^@J(1o^66~_e=?{N?(RQTYv67}%FvqV6yxV<bKg*QX@z0tbnRHiY z1SiZte3))@QXae2xAkyy#O9uN_0(QsdmrB^PNx9n(Hqt{obji<UwcwTcYT0J&wLl7 zui}tQ@*AUAS?qMRWVm*R442_jrvKz5VNQ*^r#}ubJ%7l}mzMBX%}eFkx}`PEo7x9! zIVG``GiYD7O?6Oh#H-!NQd8s)G}hho6a>GP@+$wvm5GG@1!A5n$t7wEd@)dWbK1t7 zAI3J92@9!?&4dSMUJZ6VPu@Y5=2}-+<UZKTV6N7vG%P3H{zyMUj6+ap(CA~40b}w- zjKjv$R{GDj6W1cWPhx0WjY{6n*D3S1*1ybcOtv*yv+5t+d*X%lMKX&P0L0}{TrO7t zvX3sv<H5ijVbgOS6@*Lhjo)knE_V{c*Fg-qd@j~=6&ZPB2C%7su8kA&x#cQVx9Zl@ z){7k~)uci7-xOa;6PZkQRwPlR9vBS9x*(J*&6ZN{n<Dr;X1iZL@rxU`KdNO}L&Grj zG1DT2KMr95y4nEl?6+QoQm#3|LJUu#-kROYScTv%@3yLLsjz|{$u=Z=hah(OdyU&3 z3*!aN)Mw(t%5k-<6yWm@>pk@x!aH)vCoky=Cjr>DnYdb;5B3lEE)C=baaLJ_-dKR1 zWr9+1d0o&|%I}m3VT=Au5?NY}TCUN7+x*?X<*rIq)!7En?lfx*iHingK58Bf7Yt(K z_X`<Zb(}Uvbk;St)!i`HZRCPimhXA152Mu{p2l_iYWh*3*XcqdE6?m-GS6{pLubvl zxf>Li%+9B6@V=(#S<IuqL#|Js!D@^twFIZ@d=p7msdEykFMTFIVyAV(ugckg!MKzo zw~OX*i#wPH-nP-8F>WT`XQx%ekcKa;n!7{j@jA|tbPOhjX{3cs;}XV-aNF@z-Qg~t z^N?v#oy+p0z}5Q)3S^P$>6P=;iqWo=dqdtaskSzCVSy7fDSNx#E>`??q5M<koyGJ_ h+w>PtvepFdF46=ngEMs$@2`LCj^yh_!*S07+<yv>8;<}0 literal 0 HcmV?d00001 diff --git a/src/static/js/slick/slick-script.js b/src/static/js/slick/slick-script.js new file mode 100755 index 0000000..c4c5bc4 --- /dev/null +++ b/src/static/js/slick/slick-script.js @@ -0,0 +1,193 @@ +$(document).ready(function() { + $('.single-item').slick({ + dots: true, + infinite: true, + speed: 300, + slidesToShow: 1, + slidesToScroll: 1 + }); + $('.multiple-items').slick({ + dots: true, + infinite: true, + speed: 1000, + slidesToShow: 3, + slidesToScroll: 3 + }); + $('.one-time').slick({ + dots: true, + infinite: false, + placeholders: false, + speed: 300, + slidesToShow: 5, + touchMove: false, + slidesToScroll: 1 + }); + $('.uneven').slick({ + dots: true, + infinite: true, + speed: 300, + slidesToShow: 4, + slidesToScroll: 4 + }); + $('.responsive').slick({ + dots: true, + infinite: false, + speed: 300, + slidesToShow: 4, + slidesToScroll: 4, + responsive: [{ + breakpoint: 1024, + settings: { + slidesToShow: 3, + slidesToScroll: 3, + infinite: true, + dots: true + } + }, { + breakpoint: 600, + settings: { + slidesToShow: 2, + slidesToScroll: 2 + } + }, { + breakpoint: 480, + settings: { + slidesToShow: 1, + slidesToScroll: 1 + } + }] + }); + + $('.center').slick({ + centerMode: true, + infinite: true, + centerPadding: '60px', + slidesToShow: 3, + responsive: [{ + breakpoint: 768, + settings: { + arrows: false, + centerMode: true, + centerPadding: '40px', + slidesToShow: 3 + } + }, { + breakpoint: 480, + settings: { + arrows: false, + centerMode: true, + centerPadding: '40px', + slidesToShow: 1 + } + }] + }); + $('.lazy').slick({ + lazyLoad: 'ondemand', + slidesToShow: 3, + slidesToScroll: 1 + }); + $('.autoplay').slick({ + dots: true, + infinite: true, + speed: 1000, + slidesToShow: 4, + slidesToScroll: 1, + autoplay: true, + autoplaySpeed: 2000 + }); + + $('.fade').slick({ + dots: true, + infinite: true, + speed: 500, + fade: true, + slide: 'div', + cssEase: 'linear' + }); + + $('.add-remove').slick({ + dots: true, + slidesToShow: 3, + slidesToScroll: 3 + }); + var slideIndex = 1; + $('.js-add-slide').on('click', function() { + slideIndex++; + $('.add-remove').slickAdd('<div><h3>' + slideIndex + '</h3></div>'); + }); + + $('.js-remove-slide').on('click', function() { + $('.add-remove').slickRemove(slideIndex - 1); + if (slideIndex !== 0){ + slideIndex--; + } + }); + + $('.filtering').slick({ + dots: true, + slidesToShow: 4, + slidesToScroll: 4 + }); + var filtered = false; + $('.js-filter').on('click', function() { + if (filtered === false) { + $('.filtering').slickFilter(':even'); + $(this).text('Unfilter Slides'); + filtered = true; + } else { + $('.filtering').slickUnfilter(); + $(this).text('Filter Slides'); + filtered = false; + } + }); + + $('.slider-for').slick({ + slidesToShow: 1, + slidesToScroll: 1, + arrows: false, + fade: true, + asNavFor: '.slider-nav' + }); + $('.slider-nav').slick({ + slidesToShow: 3, + slidesToScroll: 1, + asNavFor: '.slider-for', + dots: true, + centerMode: true, + focusOnSelect: true + }); + + $(window).on('scroll', function() { + if ($(window).scrollTop() > 166) { + $('.fixed-header').show(); + } else { + $('.fixed-header').hide(); + } + }); + + $('ul.nav a').on('click', function(event) { + event.preventDefault(); + var targetID = $(this).attr('href'); + var targetST = $(targetID).offset().top - 48; + $('body, html').animate({ + scrollTop: targetST + 'px' + }, 300); + }); + + $('.single-item-rtl').slick({ + dots: true, + infinite: true, + speed: 300, + slidesToShow: 1, + slidesToScroll: 1, + rtl: true + }); + $('.multiple-items-rtl').slick({ + dots: true, + infinite: true, + slidesToShow: 3, + slidesToScroll: 3, + rtl: true + }); + + }); \ No newline at end of file diff --git a/src/static/js/slick/slick.css b/src/static/js/slick/slick.css new file mode 100755 index 0000000..fcbbda3 --- /dev/null +++ b/src/static/js/slick/slick.css @@ -0,0 +1,55 @@ +/* Slider */ +.slick-slider { position: relative; display: block; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -ms-touch-action: none; -webkit-tap-highlight-color: transparent; } + +.slick-list { position: relative; overflow: hidden; display: block; margin: 0; padding: 0; } +.slick-list:focus { outline: none; } +.slick-loading .slick-list { background: white url("./ajax-loader.gif") center center no-repeat; } +.slick-list.dragging { cursor: pointer; cursor: hand; } + +.slick-slider .slick-list, .slick-track, .slick-slide, .slick-slide img { -webkit-transform: translate3d(0, 0, 0); -moz-transform: translate3d(0, 0, 0); -ms-transform: translate3d(0, 0, 0); -o-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } + +.slick-track { position: relative; left: 0; top: 0; display: block; zoom: 1; } +.slick-track:before, .slick-track:after { content: ""; display: table; } +.slick-track:after { clear: both; } +.slick-loading .slick-track { visibility: hidden; } + +.slick-slide { float: left; height: 100%; min-height: 1px; display: none; } +.slick-slide img { display: block; } +.slick-slide.slick-loading img { display: none; } +.slick-slide.dragging img { pointer-events: none; } +.slick-initialized .slick-slide { display: block; } +.slick-loading .slick-slide { visibility: hidden; } +.slick-vertical .slick-slide { display: block; height: auto; border: 1px solid transparent; } + +/* Icons */ +@font-face { font-family: "slick"; src: url("./fonts/slick.eot"); src: url("./fonts/slick.eot?#iefix") format("embedded-opentype"), url("./fonts/slick.woff") format("woff"), url("./fonts/slick.ttf") format("truetype"), url("./fonts/slick.svg#slick") format("svg"); font-weight: normal; font-style: normal; } +/* Arrows */ +.slick-prev, .slick-next { position: absolute; display: block; height: 20px; width: 20px; line-height: 0; font-size: 0; cursor: pointer; background: transparent; color: transparent; top: 50%; margin-top: -10px; padding: 0; border: none; outline: none; } +.slick-prev:hover, .slick-prev:focus, .slick-next:hover, .slick-next:focus { outline: none; background: transparent; color: transparent; } +.slick-prev:hover:before, .slick-prev:focus:before, .slick-next:hover:before, .slick-next:focus:before { opacity: 1; } +.slick-prev.slick-disabled:before, .slick-next.slick-disabled:before { opacity: 0.25; } + +.slick-prev:before, .slick-next:before { font-family: "slick"; font-size: 20px; line-height: 1; color: white; opacity: 0.75; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } + +.slick-prev { left: -25px; } +.slick-prev:before { content: "\2190"; } + +.slick-next { right: -25px; } +.slick-next:before { content: "\2192"; } + +/* Dots */ +.slick-slider { margin-bottom: 30px; } + +.slick-dots { position: absolute; bottom: -45px; list-style: none; display: block; text-align: center; padding: 0; width: 100%; } +.slick-dots li { position: relative; display: inline-block; height: 20px; width: 20px; margin: 0 5px; padding: 0; cursor: pointer; } +.slick-dots li button { border: 0; background: transparent; display: block; height: 20px; width: 20px; outline: none; line-height: 0; font-size: 0; color: transparent; padding: 5px; cursor: pointer; } +.slick-dots li button:hover, .slick-dots li button:focus { outline: none; } +.slick-dots li button:hover:before, .slick-dots li button:focus:before { opacity: 1; } +.slick-dots li button:before { position: absolute; top: 0; left: 0; content: "\2022"; width: 20px; height: 20px; font-family: "slick"; font-size: 6px; line-height: 20px; text-align: center; color: black; opacity: 0.25; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } +.slick-dots li.slick-active button:before { color: black; opacity: 0.75; } + +[dir="rtl"] .slick-next {right: auto;left: -25px;} +[dir="rtl"] .slick-next:before {content: "\2190";} +[dir="rtl"] .slick-prev {right: -25px;left: auto;} +[dir="rtl"] .slick-prev:before {content: "\2192";} +[dir="rtl"] .slick-slide {float: right;} \ No newline at end of file diff --git a/src/static/js/slick/slick.js b/src/static/js/slick/slick.js new file mode 100755 index 0000000..b9fee11 --- /dev/null +++ b/src/static/js/slick/slick.js @@ -0,0 +1,1851 @@ +/* + _ _ _ _ + ___| (_) ___| | __ (_)___ +/ __| | |/ __| |/ / | / __| +\__ \ | | (__| < _ | \__ \ +|___/_|_|\___|_|\_(_)/ |___/ + |__/ + + Version: 1.3.7 + Author: Ken Wheeler + Website: http://kenwheeler.github.io + Docs: http://kenwheeler.github.io/slick + Repo: http://github.com/kenwheeler/slick + Issues: http://github.com/kenwheeler/slick/issues + + */ + +/* global window, document, define, jQuery, setInterval, clearInterval */ + +(function(factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } else { + factory(jQuery); + } + +}(function($) { + 'use strict'; + var Slick = window.Slick || {}; + + Slick = (function() { + + var instanceUid = 0; + + function Slick(element, settings) { + + var _ = this, + responsiveSettings, breakpoint; + + _.defaults = { + accessibility: true, + appendArrows: $(element), + arrows: true, + asNavFor: null, + prevArrow: '<button type="button" data-role="none" class="slick-prev">Previous</button>', + nextArrow: '<button type="button" data-role="none" class="slick-next">Next</button>', + autoplay: false, + autoplaySpeed: 3000, + centerMode: false, + centerPadding: '50px', + cssEase: 'ease', + customPaging: function(slider, i) { + return '<button type="button" data-role="none">' + (i + 1) + '</button>'; + }, + dots: false, + dotsClass: 'slick-dots', + draggable: true, + easing: 'linear', + fade: false, + focusOnSelect: false, + infinite: true, + lazyLoad: 'ondemand', + onBeforeChange: null, + onAfterChange: null, + onInit: null, + onReInit: null, + pauseOnHover: true, + pauseOnDotsHover: false, + responsive: null, + rtl: false, + slide: 'div', + slidesToShow: 1, + slidesToScroll: 1, + speed: 300, + swipe: true, + touchMove: true, + touchThreshold: 5, + useCSS: true, + vertical: false, + waitForAnimate: true + }; + + _.initials = { + animating: false, + dragging: false, + autoPlayTimer: null, + currentSlide: 0, + currentLeft: null, + direction: 1, + $dots: null, + listWidth: null, + listHeight: null, + loadIndex: 0, + $nextArrow: null, + $prevArrow: null, + slideCount: null, + slideWidth: null, + $slideTrack: null, + $slides: null, + sliding: false, + slideOffset: 0, + swipeLeft: null, + $list: null, + touchObject: {}, + transformsEnabled: false + }; + + $.extend(_, _.initials); + + _.activeBreakpoint = null; + _.animType = null; + _.animProp = null; + _.breakpoints = []; + _.breakpointSettings = []; + _.cssTransitions = false; + _.paused = false; + _.positionProp = null; + _.$slider = $(element); + _.$slidesCache = null; + _.transformType = null; + _.transitionType = null; + _.windowWidth = 0; + _.windowTimer = null; + + _.options = $.extend({}, _.defaults, settings); + + _.originalSettings = _.options; + responsiveSettings = _.options.responsive || null; + + if (responsiveSettings && responsiveSettings.length > -1) { + for (breakpoint in responsiveSettings) { + if (responsiveSettings.hasOwnProperty(breakpoint)) { + _.breakpoints.push(responsiveSettings[ + breakpoint].breakpoint); + _.breakpointSettings[responsiveSettings[ + breakpoint].breakpoint] = + responsiveSettings[breakpoint].settings; + } + } + _.breakpoints.sort(function(a, b) { + return b - a; + }); + } + + _.autoPlay = $.proxy(_.autoPlay, _); + _.autoPlayClear = $.proxy(_.autoPlayClear, _); + _.changeSlide = $.proxy(_.changeSlide, _); + _.selectHandler = $.proxy(_.selectHandler, _); + _.setPosition = $.proxy(_.setPosition, _); + _.swipeHandler = $.proxy(_.swipeHandler, _); + _.dragHandler = $.proxy(_.dragHandler, _); + _.keyHandler = $.proxy(_.keyHandler, _); + _.autoPlayIterator = $.proxy(_.autoPlayIterator, _); + + _.instanceUid = instanceUid++; + + // A simple way to check for HTML strings + // Strict HTML recognition (must start with <) + // Extracted from jQuery v1.11 source + _.htmlExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/; + + _.init(); + + } + + return Slick; + + }()); + + Slick.prototype.addSlide = function(markup, index, addBefore) { + + var _ = this; + + if (typeof(index) === 'boolean') { + addBefore = index; + index = null; + } else if (index < 0 || (index >= _.slideCount)) { + return false; + } + + _.unload(); + + if (typeof(index) === 'number') { + if (index === 0 && _.$slides.length === 0) { + $(markup).appendTo(_.$slideTrack); + } else if (addBefore) { + $(markup).insertBefore(_.$slides.eq(index)); + } else { + $(markup).insertAfter(_.$slides.eq(index)); + } + } else { + if (addBefore === true) { + $(markup).prependTo(_.$slideTrack); + } else { + $(markup).appendTo(_.$slideTrack); + } + } + + _.$slides = _.$slideTrack.children(this.options.slide); + + _.$slideTrack.children(this.options.slide).detach(); + + _.$slideTrack.append(_.$slides); + + _.$slides.each(function(index, element) { + $(element).attr("index",index); + }); + + _.$slidesCache = _.$slides; + + _.reinit(); + + }; + + Slick.prototype.animateSlide = function(targetLeft, callback) { + + var animProps = {}, _ = this; + + if (_.options.rtl === true && _.options.vertical === false) { + targetLeft = -targetLeft; + } + if (_.transformsEnabled === false) { + if (_.options.vertical === false) { + _.$slideTrack.animate({ + left: targetLeft + }, _.options.speed, _.options.easing, callback); + } else { + _.$slideTrack.animate({ + top: targetLeft + }, _.options.speed, _.options.easing, callback); + } + + } else { + + if (_.cssTransitions === false) { + + $({ + animStart: _.currentLeft + }).animate({ + animStart: targetLeft + }, { + duration: _.options.speed, + easing: _.options.easing, + step: function(now) { + if (_.options.vertical === false) { + animProps[_.animType] = 'translate(' + + now + 'px, 0px)'; + _.$slideTrack.css(animProps); + } else { + animProps[_.animType] = 'translate(0px,' + + now + 'px)'; + _.$slideTrack.css(animProps); + } + }, + complete: function() { + if (callback) { + callback.call(); + } + } + }); + + } else { + + _.applyTransition(); + + if (_.options.vertical === false) { + animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)'; + } else { + animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)'; + } + _.$slideTrack.css(animProps); + + if (callback) { + setTimeout(function() { + + _.disableTransition(); + + callback.call(); + }, _.options.speed); + } + + } + + } + + }; + + Slick.prototype.applyTransition = function(slide) { + + var _ = this, + transition = {}; + + if (_.options.fade === false) { + transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase; + } else { + transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase; + } + + if (_.options.fade === false) { + _.$slideTrack.css(transition); + } else { + _.$slides.eq(slide).css(transition); + } + + }; + + Slick.prototype.autoPlay = function() { + + var _ = this; + + if (_.autoPlayTimer) { + clearInterval(_.autoPlayTimer); + } + + if (_.slideCount > _.options.slidesToShow && _.paused !== true) { + _.autoPlayTimer = setInterval(_.autoPlayIterator, + _.options.autoplaySpeed); + } + + }; + + Slick.prototype.autoPlayClear = function() { + + var _ = this; + + if (_.autoPlayTimer) { + clearInterval(_.autoPlayTimer); + } + + }; + + Slick.prototype.autoPlayIterator = function() { + + var _ = this; + var asNavFor = _.options.asNavFor != null ? $(_.options.asNavFor).getSlick() : null; + + if (_.options.infinite === false) { + + if (_.direction === 1) { + + if ((_.currentSlide + 1) === _.slideCount - + 1) { + _.direction = 0; + } + + _.slideHandler(_.currentSlide + _.options.slidesToScroll); + if(asNavFor != null) asNavFor.slideHandler(asNavFor.currentSlide + asNavFor.options.slidesToScroll); + + } else { + + if ((_.currentSlide - 1 === 0)) { + + _.direction = 1; + + } + + _.slideHandler(_.currentSlide - _.options.slidesToScroll); + if(asNavFor != null) asNavFor.slideHandler(asNavFor.currentSlide - asNavFor.options.slidesToScroll); + + } + + } else { + + _.slideHandler(_.currentSlide + _.options.slidesToScroll); + if(asNavFor != null) asNavFor.slideHandler(asNavFor.currentSlide + asNavFor.options.slidesToScroll); + + } + + }; + + Slick.prototype.buildArrows = function() { + + var _ = this; + + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { + + _.$prevArrow = $(_.options.prevArrow); + _.$nextArrow = $(_.options.nextArrow); + + if (_.htmlExpr.test(_.options.prevArrow)) { + _.$prevArrow.appendTo(_.options.appendArrows); + } + + if (_.htmlExpr.test(_.options.nextArrow)) { + _.$nextArrow.appendTo(_.options.appendArrows); + } + + if (_.options.infinite !== true) { + _.$prevArrow.addClass('slick-disabled'); + } + + } + + }; + + Slick.prototype.buildDots = function() { + + var _ = this, + i, dotString; + + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { + + dotString = '<ul class="' + _.options.dotsClass + '">'; + + for (i = 0; i <= _.getDotCount(); i += 1) { + dotString += '<li>' + _.options.customPaging.call(this, _, i) + '</li>'; + } + + dotString += '</ul>'; + + _.$dots = $(dotString).appendTo( + _.$slider); + + _.$dots.find('li').first().addClass( + 'slick-active'); + + } + + }; + + Slick.prototype.buildOut = function() { + + var _ = this; + + _.$slides = _.$slider.children(_.options.slide + + ':not(.slick-cloned)').addClass( + 'slick-slide'); + _.slideCount = _.$slides.length; + + _.$slides.each(function(index, element) { + $(element).attr("index",index); + }); + + _.$slidesCache = _.$slides; + + _.$slider.addClass('slick-slider'); + + _.$slideTrack = (_.slideCount === 0) ? + $('<div class="slick-track"/>').appendTo(_.$slider) : + _.$slides.wrapAll('<div class="slick-track"/>').parent(); + + _.$list = _.$slideTrack.wrap( + '<div class="slick-list"/>').parent(); + _.$slideTrack.css('opacity', 0); + + if (_.options.centerMode === true) { + _.options.slidesToScroll = 1; + if (_.options.slidesToShow % 2 === 0) { + _.options.slidesToShow = 3; + } + } + + $('img[data-lazy]', _.$slider).not('[src]').addClass('slick-loading'); + + _.setupInfinite(); + + _.buildArrows(); + + _.buildDots(); + + _.updateDots(); + + if (_.options.accessibility === true) { + _.$list.prop('tabIndex', 0); + } + + _.setSlideClasses(typeof this.currentSlide === 'number' ? this.currentSlide : 0); + + if (_.options.draggable === true) { + _.$list.addClass('draggable'); + } + + }; + + Slick.prototype.checkResponsive = function() { + + var _ = this, + breakpoint, targetBreakpoint; + + if (_.originalSettings.responsive && _.originalSettings + .responsive.length > -1 && _.originalSettings.responsive !== null) { + + targetBreakpoint = null; + + for (breakpoint in _.breakpoints) { + if (_.breakpoints.hasOwnProperty(breakpoint)) { + if ($(window).width() < _.breakpoints[ + breakpoint]) { + targetBreakpoint = _.breakpoints[ + breakpoint]; + } + } + } + + if (targetBreakpoint !== null) { + if (_.activeBreakpoint !== null) { + if (targetBreakpoint !== _.activeBreakpoint) { + _.activeBreakpoint = + targetBreakpoint; + _.options = $.extend({}, _.options, + _.breakpointSettings[ + targetBreakpoint]); + _.refresh(); + } + } else { + _.activeBreakpoint = targetBreakpoint; + _.options = $.extend({}, _.options, + _.breakpointSettings[ + targetBreakpoint]); + _.refresh(); + } + } else { + if (_.activeBreakpoint !== null) { + _.activeBreakpoint = null; + _.options = $.extend({}, _.options, + _.originalSettings); + _.refresh(); + } + } + + } + + }; + + Slick.prototype.changeSlide = function(event) { + + var _ = this, + $target = $(event.target); + var asNavFor = _.options.asNavFor != null ? $(_.options.asNavFor).getSlick() : null; + + // If target is a link, prevent default action. + $target.is('a') && event.preventDefault(); + + switch (event.data.message) { + + case 'previous': + if (_.slideCount > _.options.slidesToShow) { + _.slideHandler(_.currentSlide - _.options + .slidesToScroll); + if(asNavFor != null) asNavFor.slideHandler(asNavFor.currentSlide - asNavFor.options.slidesToScroll); + } + break; + + case 'next': + if (_.slideCount > _.options.slidesToShow) { + _.slideHandler(_.currentSlide + _.options + .slidesToScroll); + if(asNavFor != null) asNavFor.slideHandler(asNavFor.currentSlide + asNavFor.options.slidesToScroll); + } + break; + + case 'index': + var index = $(event.target).parent().index() * _.options.slidesToScroll; + _.slideHandler(index); + if(asNavFor != null) asNavFor.slideHandler(index); break; + + default: + return false; + } + + }; + + Slick.prototype.destroy = function() { + + var _ = this; + + _.autoPlayClear(); + + _.touchObject = {}; + + $('.slick-cloned', _.$slider).remove(); + if (_.$dots) { + _.$dots.remove(); + } + if (_.$prevArrow) { + _.$prevArrow.remove(); + _.$nextArrow.remove(); + } + if (_.$slides.parent().hasClass('slick-track')) { + _.$slides.unwrap().unwrap(); + } + _.$slides.removeClass( + 'slick-slide slick-active slick-visible').removeAttr('style'); + _.$slider.removeClass('slick-slider'); + _.$slider.removeClass('slick-initialized'); + + _.$list.off('.slick'); + $(window).off('.slick-' + _.instanceUid); + $(document).off('.slick-' + _.instanceUid); + + }; + + Slick.prototype.disableTransition = function(slide) { + + var _ = this, + transition = {}; + + transition[_.transitionType] = ""; + + if (_.options.fade === false) { + _.$slideTrack.css(transition); + } else { + _.$slides.eq(slide).css(transition); + } + + }; + + Slick.prototype.fadeSlide = function(slideIndex, callback) { + + var _ = this; + + if (_.cssTransitions === false) { + + _.$slides.eq(slideIndex).css({ + zIndex: 1000 + }); + + _.$slides.eq(slideIndex).animate({ + opacity: 1 + }, _.options.speed, _.options.easing, callback); + + } else { + + _.applyTransition(slideIndex); + + _.$slides.eq(slideIndex).css({ + opacity: 1, + zIndex: 1000 + }); + + if (callback) { + setTimeout(function() { + + _.disableTransition(slideIndex); + + callback.call(); + }, _.options.speed); + } + + } + + }; + + Slick.prototype.filterSlides = function(filter) { + + var _ = this; + + if (filter !== null) { + + _.unload(); + + _.$slideTrack.children(this.options.slide).detach(); + + _.$slidesCache.filter(filter).appendTo(_.$slideTrack); + + _.reinit(); + + } + + }; + + Slick.prototype.getCurrent = function() { + + var _ = this; + + return _.currentSlide; + + }; + + Slick.prototype.getDotCount = function() { + + var _ = this, + breaker = 0, + dotCounter = 0, + dotCount = 0, + dotLimit; + + dotLimit = _.options.infinite === true ? _.slideCount + _.options.slidesToShow - _.options.slidesToScroll : _.slideCount; + + while (breaker < dotLimit) { + dotCount++; + dotCounter += _.options.slidesToScroll; + breaker = dotCounter + _.options.slidesToShow; + } + + return dotCount; + + }; + + Slick.prototype.getLeft = function(slideIndex) { + + var _ = this, + targetLeft, + verticalHeight, + verticalOffset = 0; + + _.slideOffset = 0; + verticalHeight = _.$slides.first().outerHeight(); + + if (_.options.infinite === true) { + if (_.slideCount > _.options.slidesToShow) { + _.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1; + verticalOffset = (verticalHeight * _.options.slidesToShow) * -1; + } + if (_.slideCount % _.options.slidesToScroll !== 0) { + if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) { + _.slideOffset = ((_.slideCount % _.options.slidesToShow) * _.slideWidth) * -1; + verticalOffset = ((_.slideCount % _.options.slidesToShow) * verticalHeight) * -1; + } + } + } else { + if (_.slideCount % _.options.slidesToShow !== 0) { + if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) { + _.slideOffset = (_.options.slidesToShow * _.slideWidth) - ((_.slideCount % _.options.slidesToShow) * _.slideWidth); + verticalOffset = ((_.slideCount % _.options.slidesToShow) * verticalHeight); + } + } + } + + if (_.options.centerMode === true && _.options.infinite === true) { + _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth; + } else if (_.options.centerMode === true) { + _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2); + } + + if (_.options.vertical === false) { + targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset; + } else { + targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset; + } + + return targetLeft; + + }; + + Slick.prototype.init = function() { + + var _ = this; + + if (!$(_.$slider).hasClass('slick-initialized')) { + + $(_.$slider).addClass('slick-initialized'); + _.buildOut(); + _.setProps(); + _.startLoad(); + _.loadSlider(); + _.initializeEvents(); + _.checkResponsive(); + } + + if (_.options.onInit !== null) { + _.options.onInit.call(this, _); + } + + }; + + Slick.prototype.initArrowEvents = function() { + + var _ = this; + + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { + _.$prevArrow.on('click.slick', { + message: 'previous' + }, _.changeSlide); + _.$nextArrow.on('click.slick', { + message: 'next' + }, _.changeSlide); + } + + }; + + Slick.prototype.initDotEvents = function() { + + var _ = this; + + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { + $('li', _.$dots).on('click.slick', { + message: 'index' + }, _.changeSlide); + } + + if (_.options.dots === true && _.options.pauseOnDotsHover === true && _.options.autoplay === true) { + $('li', _.$dots) + .on('mouseenter.slick', _.autoPlayClear) + .on('mouseleave.slick', _.autoPlay); + } + + }; + + Slick.prototype.initializeEvents = function() { + + var _ = this; + + _.initArrowEvents(); + + _.initDotEvents(); + + _.$list.on('touchstart.slick mousedown.slick', { + action: 'start' + }, _.swipeHandler); + _.$list.on('touchmove.slick mousemove.slick', { + action: 'move' + }, _.swipeHandler); + _.$list.on('touchend.slick mouseup.slick', { + action: 'end' + }, _.swipeHandler); + _.$list.on('touchcancel.slick mouseleave.slick', { + action: 'end' + }, _.swipeHandler); + + if (_.options.pauseOnHover === true && _.options.autoplay === true) { + _.$list.on('mouseenter.slick', _.autoPlayClear); + _.$list.on('mouseleave.slick', _.autoPlay); + } + + if(_.options.accessibility === true) { + _.$list.on('keydown.slick', _.keyHandler); + } + + if(_.options.focusOnSelect === true) { + $(_.options.slide, _.$slideTrack).on('click.slick', _.selectHandler); + } + + $(window).on('orientationchange.slick.slick-' + _.instanceUid, function() { + _.checkResponsive(); + _.setPosition(); + }); + + $(window).on('resize.slick.slick-' + _.instanceUid, function() { + if ($(window).width() !== _.windowWidth) { + clearTimeout(_.windowDelay); + _.windowDelay = window.setTimeout(function() { + _.windowWidth = $(window).width(); + _.checkResponsive(); + _.setPosition(); + }, 50); + } + }); + + $(window).on('load.slick.slick-' + _.instanceUid, _.setPosition); + $(document).on('ready.slick.slick-' + _.instanceUid, _.setPosition); + + }; + + Slick.prototype.initUI = function() { + + var _ = this; + + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { + + _.$prevArrow.show(); + _.$nextArrow.show(); + + } + + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { + + _.$dots.show(); + + } + + if (_.options.autoplay === true) { + + _.autoPlay(); + + } + + }; + + Slick.prototype.keyHandler = function(event) { + + var _ = this; + + if (event.keyCode === 37) { + _.changeSlide({ + data: { + message: 'previous' + } + }); + } else if (event.keyCode === 39) { + _.changeSlide({ + data: { + message: 'next' + } + }); + } + + }; + + Slick.prototype.lazyLoad = function() { + + var _ = this, + loadRange, cloneRange, rangeStart, rangeEnd; + + function loadImages(imagesScope) { + $('img[data-lazy]', imagesScope).each(function() { + var image = $(this), + imageSource = $(this).attr('data-lazy') + "?" + new Date().getTime(); + + image + .load(function() { image.animate({ opacity: 1 }, 200); }) + .css({ opacity: 0 }) + .attr('src', imageSource) + .removeAttr('data-lazy') + .removeClass('slick-loading'); + }); + } + + if (_.options.centerMode === true) { + if (_.options.infinite === true) { + rangeStart = _.currentSlide + (_.options.slidesToShow/2 + 1); + rangeEnd = rangeStart + _.options.slidesToShow + 2; + } else { + rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow/2 + 1)); + rangeEnd = 2 + (_.options.slidesToShow/2 + 1) + _.currentSlide; + } + } else { + rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide; + rangeEnd = rangeStart + _.options.slidesToShow; + if (_.options.fade === true ) { + if(rangeStart > 0) rangeStart--; + if(rangeEnd <= _.slideCount) rangeEnd++; + } + } + + loadRange = _.$slider.find('.slick-slide').slice(rangeStart, rangeEnd); + loadImages(loadRange); + + if (_.slideCount == 1){ + cloneRange = _.$slider.find('.slick-slide') + loadImages(cloneRange) + }else + if (_.currentSlide >= _.slideCount - _.options.slidesToShow) { + cloneRange = _.$slider.find('.slick-cloned').slice(0, _.options.slidesToShow); + loadImages(cloneRange) + } else if (_.currentSlide === 0) { + cloneRange = _.$slider.find('.slick-cloned').slice(_.options.slidesToShow * -1); + loadImages(cloneRange); + } + + }; + + Slick.prototype.loadSlider = function() { + + var _ = this; + + _.setPosition(); + + _.$slideTrack.css({ + opacity: 1 + }); + + _.$slider.removeClass('slick-loading'); + + _.initUI(); + + if (_.options.lazyLoad === 'progressive') { + _.progressiveLazyLoad(); + } + + }; + + Slick.prototype.postSlide = function(index) { + + var _ = this; + + if (_.options.onAfterChange !== null) { + _.options.onAfterChange.call(this, _, index); + } + + _.animating = false; + + _.setPosition(); + + _.swipeLeft = null; + + if (_.options.autoplay === true && _.paused === false) { + _.autoPlay(); + } + + }; + + Slick.prototype.progressiveLazyLoad = function() { + + var _ = this, + imgCount, targetImage; + + imgCount = $('img[data-lazy]').length; + + if (imgCount > 0) { + targetImage = $('img[data-lazy]', _.$slider).first(); + targetImage.attr('src', targetImage.attr('data-lazy')).removeClass('slick-loading').load(function() { + targetImage.removeAttr('data-lazy'); + _.progressiveLazyLoad(); + }); + } + + }; + + Slick.prototype.refresh = function() { + + var _ = this, + currentSlide = _.currentSlide; + + _.destroy(); + + $.extend(_, _.initials); + + _.currentSlide = currentSlide; + _.init(); + + }; + + Slick.prototype.reinit = function() { + + var _ = this; + + _.$slides = _.$slideTrack.children(_.options.slide).addClass( + 'slick-slide'); + + _.slideCount = _.$slides.length; + + if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) { + _.currentSlide = _.currentSlide - _.options.slidesToScroll; + } + + _.setProps(); + + _.setupInfinite(); + + _.buildArrows(); + + _.updateArrows(); + + _.initArrowEvents(); + + _.buildDots(); + + _.updateDots(); + + _.initDotEvents(); + + if(_.options.focusOnSelect === true) { + $(_.options.slide, _.$slideTrack).on('click.slick', _.selectHandler); + } + + _.setSlideClasses(0); + + _.setPosition(); + + if (_.options.onReInit !== null) { + _.options.onReInit.call(this, _); + } + + }; + + Slick.prototype.removeSlide = function(index, removeBefore) { + + var _ = this; + + if (typeof(index) === 'boolean') { + removeBefore = index; + index = removeBefore === true ? 0 : _.slideCount - 1; + } else { + index = removeBefore === true ? --index : index; + } + + if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) { + return false; + } + + _.unload(); + + _.$slideTrack.children(this.options.slide).eq(index).remove(); + + _.$slides = _.$slideTrack.children(this.options.slide); + + _.$slideTrack.children(this.options.slide).detach(); + + _.$slideTrack.append(_.$slides); + + _.$slidesCache = _.$slides; + + _.reinit(); + + }; + + Slick.prototype.setCSS = function(position) { + + var _ = this, + positionProps = {}, x, y; + + if (_.options.rtl === true) { + position = -position; + } + x = _.positionProp == 'left' ? position + 'px' : '0px'; + y = _.positionProp == 'top' ? position + 'px' : '0px'; + + positionProps[_.positionProp] = position; + + if (_.transformsEnabled === false) { + _.$slideTrack.css(positionProps); + } else { + positionProps = {}; + if (_.cssTransitions === false) { + positionProps[_.animType] = 'translate(' + x + ', ' + y + ')'; + _.$slideTrack.css(positionProps); + } else { + positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)'; + _.$slideTrack.css(positionProps); + } + } + + }; + + Slick.prototype.setDimensions = function() { + + var _ = this; + + if (_.options.vertical === false) { + if (_.options.centerMode === true) { + _.$list.css({ + padding: ('0px ' + _.options.centerPadding) + }); + } + } else { + _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow); + if (_.options.centerMode === true) { + _.$list.css({ + padding: (_.options.centerPadding + ' 0px') + }); + } + } + + _.listWidth = _.$list.width(); + _.listHeight = _.$list.height(); + + + if(_.options.vertical === false) { + _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow); + _.$slideTrack.width(Math.ceil((_.slideWidth * _.$slideTrack.children('.slick-slide').length))); + + } else { + _.slideWidth = Math.ceil(_.listWidth); + _.$slideTrack.height(Math.ceil((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length))); + + } + + var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width(); + _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset); + + }; + + Slick.prototype.setFade = function() { + + var _ = this, + targetLeft; + + _.$slides.each(function(index, element) { + targetLeft = (_.slideWidth * index) * -1; + $(element).css({ + position: 'relative', + left: targetLeft, + top: 0, + zIndex: 800, + opacity: 0 + }); + }); + + _.$slides.eq(_.currentSlide).css({ + zIndex: 900, + opacity: 1 + }); + + }; + + Slick.prototype.setPosition = function() { + + var _ = this; + + _.setDimensions(); + + if (_.options.fade === false) { + _.setCSS(_.getLeft(_.currentSlide)); + } else { + _.setFade(); + } + + }; + + Slick.prototype.setProps = function() { + + var _ = this, + bodyStyle = document.body.style; + + _.positionProp = _.options.vertical === true ? 'top' : 'left'; + + if (_.positionProp === 'top') { + _.$slider.addClass('slick-vertical'); + } else { + _.$slider.removeClass('slick-vertical'); + } + + if (bodyStyle.WebkitTransition !== undefined || + bodyStyle.MozTransition !== undefined || + bodyStyle.msTransition !== undefined) { + if(_.options.useCSS === true) { + _.cssTransitions = true; + } + } + + if (bodyStyle.OTransform !== undefined) { + _.animType = 'OTransform'; + _.transformType = "-o-transform"; + _.transitionType = 'OTransition'; + if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false; + } + if (bodyStyle.MozTransform !== undefined) { + _.animType = 'MozTransform'; + _.transformType = "-moz-transform"; + _.transitionType = 'MozTransition'; + if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false; + } + if (bodyStyle.webkitTransform !== undefined) { + _.animType = 'webkitTransform'; + _.transformType = "-webkit-transform"; + _.transitionType = 'webkitTransition'; + if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false; + } + if (bodyStyle.msTransform !== undefined) { + _.animType = 'msTransform'; + _.transformType = "-ms-transform"; + _.transitionType = 'msTransition'; + if (bodyStyle.msTransform === undefined) _.animType = false; + } + if (bodyStyle.transform !== undefined && _.animType !== false) { + _.animType = 'transform'; + _.transformType = "transform"; + _.transitionType = 'transition'; + } + _.transformsEnabled = (_.animType !== null && _.animType !== false); + + }; + + + Slick.prototype.setSlideClasses = function(index) { + + var _ = this, + centerOffset, allSlides, indexOffset, remainder; + + _.$slider.find('.slick-slide').removeClass('slick-active').removeClass('slick-center'); + allSlides = _.$slider.find('.slick-slide'); + + if (_.options.centerMode === true) { + + centerOffset = Math.floor(_.options.slidesToShow / 2); + + if(_.options.infinite === true) { + + if (index >= centerOffset && index <= (_.slideCount - 1) - centerOffset) { + _.$slides.slice(index - centerOffset, index + centerOffset + 1).addClass('slick-active'); + } else { + indexOffset = _.options.slidesToShow + index; + allSlides.slice(indexOffset - centerOffset + 1, indexOffset + centerOffset + 2).addClass('slick-active'); + } + + if (index === 0) { + allSlides.eq(allSlides.length - 1 - _.options.slidesToShow).addClass('slick-center'); + } else if (index === _.slideCount - 1) { + allSlides.eq(_.options.slidesToShow).addClass('slick-center'); + } + + } + + _.$slides.eq(index).addClass('slick-center'); + + } else { + + if (index >= 0 && index <= (_.slideCount - _.options.slidesToShow)) { + _.$slides.slice(index, index + _.options.slidesToShow).addClass('slick-active'); + } else if ( allSlides.length <= _.options.slidesToShow ) { + allSlides.addClass('slick-active'); + } else { + remainder = _.slideCount%_.options.slidesToShow; + indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index; + if(_.options.slidesToShow == _.options.slidesToScroll && (_.slideCount - index) < _.options.slidesToShow) { + allSlides.slice(indexOffset-(_.options.slidesToShow-remainder), indexOffset + remainder).addClass('slick-active'); + } else { + allSlides.slice(indexOffset, indexOffset + _.options.slidesToShow).addClass('slick-active'); + } + } + + } + + if (_.options.lazyLoad === 'ondemand') { + _.lazyLoad(); + } + + }; + + Slick.prototype.setupInfinite = function() { + + var _ = this, + i, slideIndex, infiniteCount; + + if (_.options.fade === true || _.options.vertical === true) { + _.options.centerMode = false; + } + + if (_.options.infinite === true && _.options.fade === false) { + + slideIndex = null; + + if (_.slideCount > _.options.slidesToShow) { + + if (_.options.centerMode === true) { + infiniteCount = _.options.slidesToShow + 1; + } else { + infiniteCount = _.options.slidesToShow; + } + + for (i = _.slideCount; i > (_.slideCount - + infiniteCount); i -= 1) { + slideIndex = i - 1; + $(_.$slides[slideIndex]).clone(true).attr('id', '').prependTo( + _.$slideTrack).addClass('slick-cloned'); + } + for (i = 0; i < infiniteCount; i += 1) { + slideIndex = i; + $(_.$slides[slideIndex]).clone(true).attr('id', '').appendTo( + _.$slideTrack).addClass('slick-cloned'); + } + _.$slideTrack.find('.slick-cloned').find('[id]').each(function() { + $(this).attr('id', ''); + }); + + } + + } + + }; + + Slick.prototype.selectHandler = function(event) { + + var _ = this; + var asNavFor = _.options.asNavFor != null ? $(_.options.asNavFor).getSlick() : null; + var index = parseInt($(event.target).parent().attr("index")); + if(!index) index = 0; + + if(_.slideCount <= _.options.slidesToShow){ + return; + } + _.slideHandler(index); + + if(asNavFor != null){ + if(asNavFor.slideCount <= asNavFor.options.slidesToShow){ + return; + } + asNavFor.slideHandler(index); + } + }; + + Slick.prototype.slideHandler = function(index) { + + var targetSlide, animSlide, slideLeft, unevenOffset, targetLeft = null, + _ = this; + + if (_.animating === true && _.options.waitForAnimate === true) { + return false; + } + + targetSlide = index; + targetLeft = _.getLeft(targetSlide); + slideLeft = _.getLeft(_.currentSlide); + + unevenOffset = _.slideCount % _.options.slidesToScroll !== 0 ? _.options.slidesToScroll : 0; + + _.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft; + + if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > (_.slideCount - _.options.slidesToShow + unevenOffset))) { + if(_.options.fade === false) { + targetSlide = _.currentSlide; + _.animateSlide(slideLeft, function() { + _.postSlide(targetSlide); + }); + } + return false; + } else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > (_.slideCount - _.options.slidesToScroll))) { + if(_.options.fade === false) { + targetSlide = _.currentSlide; + _.animateSlide(slideLeft, function() { + _.postSlide(targetSlide); + }); + } + return false; + } + + if (_.options.autoplay === true) { + clearInterval(_.autoPlayTimer); + } + + if (targetSlide < 0) { + if (_.slideCount % _.options.slidesToScroll !== 0) { + animSlide = _.slideCount - (_.slideCount % _.options.slidesToScroll); + } else { + animSlide = _.slideCount - _.options.slidesToScroll; + } + } else if (targetSlide > (_.slideCount - 1)) { + animSlide = 0; + } else { + animSlide = targetSlide; + } + + _.animating = true; + + if (_.options.onBeforeChange !== null && index !== _.currentSlide) { + _.options.onBeforeChange.call(this, _, _.currentSlide, animSlide); + } + + _.currentSlide = animSlide; + + _.setSlideClasses(_.currentSlide); + + _.updateDots(); + _.updateArrows(); + + if (_.options.fade === true) { + _.fadeSlide(animSlide, function() { + _.postSlide(animSlide); + }); + return false; + } + + _.animateSlide(targetLeft, function() { + _.postSlide(animSlide); + }); + + }; + + Slick.prototype.startLoad = function() { + + var _ = this; + + if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { + + _.$prevArrow.hide(); + _.$nextArrow.hide(); + + } + + if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { + + _.$dots.hide(); + + } + + _.$slider.addClass('slick-loading'); + + }; + + Slick.prototype.swipeDirection = function() { + + var xDist, yDist, r, swipeAngle, _ = this; + + xDist = _.touchObject.startX - _.touchObject.curX; + yDist = _.touchObject.startY - _.touchObject.curY; + r = Math.atan2(yDist, xDist); + + swipeAngle = Math.round(r * 180 / Math.PI); + if (swipeAngle < 0) { + swipeAngle = 360 - Math.abs(swipeAngle); + } + + if ((swipeAngle <= 45) && (swipeAngle >= 0)) { + return 'left'; + } + if ((swipeAngle <= 360) && (swipeAngle >= 315)) { + return 'left'; + } + if ((swipeAngle >= 135) && (swipeAngle <= 225)) { + return 'right'; + } + + return 'vertical'; + + }; + + Slick.prototype.swipeEnd = function(event) { + + var _ = this; + var asNavFor = _.options.asNavFor != null ? $(_.options.asNavFor).getSlick() : null; + + _.dragging = false; + + if (_.touchObject.curX === undefined) { + return false; + } + + if (_.touchObject.swipeLength >= _.touchObject.minSwipe) { + $(event.target).on('click.slick', function(event) { + event.stopImmediatePropagation(); + event.stopPropagation(); + event.preventDefault(); + $(event.target).off('click.slick'); + }); + + switch (_.swipeDirection()) { + case 'left': + _.slideHandler(_.currentSlide + _.options.slidesToScroll); + if(asNavFor != null) asNavFor.slideHandler(asNavFor.currentSlide + asNavFor.options.slidesToScroll); + _.touchObject = {}; + break; + + case 'right': + _.slideHandler(_.currentSlide - _.options.slidesToScroll); + if(asNavFor != null) asNavFor.slideHandler(asNavFor.currentSlide - asNavFor.options.slidesToScroll); + _.touchObject = {}; + break; + } + } else { + if(_.touchObject.startX !== _.touchObject.curX) { + _.slideHandler(_.currentSlide); + if(asNavFor != null) asNavFor.slideHandler(asNavFor.currentSlide); + _.touchObject = {}; + } + } + + }; + + Slick.prototype.swipeHandler = function(event) { + + var _ = this; + + if ((_.options.swipe === false) || ('ontouchend' in document && _.options.swipe === false)) { + return; + } else if ((_.options.draggable === false) || (_.options.draggable === false && !event.originalEvent.touches)) { + return; + } + + _.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ? + event.originalEvent.touches.length : 1; + + _.touchObject.minSwipe = _.listWidth / _.options + .touchThreshold; + + switch (event.data.action) { + + case 'start': + _.swipeStart(event); + break; + + case 'move': + _.swipeMove(event); + break; + + case 'end': + _.swipeEnd(event); + break; + + } + + }; + + Slick.prototype.swipeMove = function(event) { + + var _ = this, + curLeft, swipeDirection, positionOffset, touches; + + touches = event.originalEvent !== undefined ? event.originalEvent.touches : null; + + curLeft = _.getLeft(_.currentSlide); + + if (!_.dragging || touches && touches.length !== 1) { + return false; + } + + _.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX; + _.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY; + + _.touchObject.swipeLength = Math.round(Math.sqrt( + Math.pow(_.touchObject.curX - _.touchObject.startX, 2))); + + swipeDirection = _.swipeDirection(); + + if (swipeDirection === 'vertical') { + return; + } + + if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) { + event.preventDefault(); + } + + positionOffset = _.touchObject.curX > _.touchObject.startX ? 1 : -1; + + if (_.options.vertical === false) { + _.swipeLeft = curLeft + _.touchObject.swipeLength * positionOffset; + } else { + _.swipeLeft = curLeft + (_.touchObject + .swipeLength * (_.$list.height() / _.listWidth)) * positionOffset; + } + + if (_.options.fade === true || _.options.touchMove === false) { + return false; + } + + if (_.animating === true) { + _.swipeLeft = null; + return false; + } + + _.setCSS(_.swipeLeft); + + }; + + Slick.prototype.swipeStart = function(event) { + + var _ = this, + touches; + + if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) { + _.touchObject = {}; + return false; + } + + if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) { + touches = event.originalEvent.touches[0]; + } + + _.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX; + _.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY; + + _.dragging = true; + + }; + + Slick.prototype.unfilterSlides = function() { + + var _ = this; + + if (_.$slidesCache !== null) { + + _.unload(); + + _.$slideTrack.children(this.options.slide).detach(); + + _.$slidesCache.appendTo(_.$slideTrack); + + _.reinit(); + + } + + }; + + Slick.prototype.unload = function() { + + var _ = this; + + $('.slick-cloned', _.$slider).remove(); + if (_.$dots) { + _.$dots.remove(); + } + if (_.$prevArrow) { + _.$prevArrow.remove(); + _.$nextArrow.remove(); + } + _.$slides.removeClass( + 'slick-slide slick-active slick-visible').removeAttr('style'); + + }; + + Slick.prototype.updateArrows = function() { + + var _ = this; + + if (_.options.arrows === true && _.options.infinite !== + true && _.slideCount > _.options.slidesToShow) { + _.$prevArrow.removeClass('slick-disabled'); + _.$nextArrow.removeClass('slick-disabled'); + if (_.currentSlide === 0) { + _.$prevArrow.addClass('slick-disabled'); + _.$nextArrow.removeClass('slick-disabled'); + } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow) { + _.$nextArrow.addClass('slick-disabled'); + _.$prevArrow.removeClass('slick-disabled'); + } + } + + }; + + Slick.prototype.updateDots = function() { + + var _ = this; + + if (_.$dots !== null) { + + _.$dots.find('li').removeClass('slick-active'); + _.$dots.find('li').eq(Math.floor(_.currentSlide / _.options.slidesToScroll)).addClass('slick-active'); + + } + + }; + + $.fn.slick = function(options) { + var _ = this; + return _.each(function(index, element) { + + element.slick = new Slick(element, options); + + }); + }; + + $.fn.slickAdd = function(slide, slideIndex, addBefore) { + var _ = this; + return _.each(function(index, element) { + + element.slick.addSlide(slide, slideIndex, addBefore); + + }); + }; + + $.fn.slickCurrentSlide = function() { + var _ = this; + return _.get(0).slick.getCurrent(); + }; + + $.fn.slickFilter = function(filter) { + var _ = this; + return _.each(function(index, element) { + + element.slick.filterSlides(filter); + + }); + }; + + $.fn.slickGoTo = function(slide) { + var _ = this; + return _.each(function(index, element) { + + var asNavFor = element.slick.options.asNavFor != null ? $(element.slick.options.asNavFor) : null; + if(asNavFor != null) asNavFor.slickGoTo(slide); + element.slick.slideHandler(slide); + + }); + }; + + $.fn.slickNext = function() { + var _ = this; + return _.each(function(index, element) { + + element.slick.changeSlide({ + data: { + message: 'next' + } + }); + + }); + }; + + $.fn.slickPause = function() { + var _ = this; + return _.each(function(index, element) { + + element.slick.autoPlayClear(); + element.slick.paused = true; + + }); + }; + + $.fn.slickPlay = function() { + var _ = this; + return _.each(function(index, element) { + + element.slick.paused = false; + element.slick.autoPlay(); + + }); + }; + + $.fn.slickPrev = function() { + var _ = this; + return _.each(function(index, element) { + + element.slick.changeSlide({ + data: { + message: 'previous' + } + }); + + }); + }; + + $.fn.slickRemove = function(slideIndex, removeBefore) { + var _ = this; + return _.each(function(index, element) { + + element.slick.removeSlide(slideIndex, removeBefore); + + }); + }; + + $.fn.slickGetOption = function(option) { + var _ = this; + return _.get(0).slick.options[option]; + }; + + $.fn.slickSetOption = function(option, value, refresh) { + var _ = this; + return _.each(function(index, element) { + + element.slick.options[option] = value; + + if (refresh === true) { + element.slick.unload(); + element.slick.reinit(); + } + + }); + }; + + $.fn.slickUnfilter = function() { + var _ = this; + return _.each(function(index, element) { + + element.slick.unfilterSlides(); + + }); + }; + + $.fn.unslick = function() { + var _ = this; + return _.each(function(index, element) { + + if (element.slick) { + element.slick.destroy(); + } + + }); + }; + + $.fn.getSlick = function() { + var s = null; + var _ = this; + _.each(function(index, element) { + s = element.slick; + }); + + return s; + }; + +})); diff --git a/src/static/js/slick/slick.min.js b/src/static/js/slick/slick.min.js new file mode 100755 index 0000000..ee4b59e --- /dev/null +++ b/src/static/js/slick/slick.min.js @@ -0,0 +1 @@ +!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a(jQuery)}(function(a){"use strict";var b=window.Slick||{};b=function(){function c(c,d){var f,g,e=this;if(e.defaults={accessibility:!0,appendArrows:a(c),arrows:!0,asNavFor:null,prevArrow:'<button type="button" data-role="none" class="slick-prev">Previous</button>',nextArrow:'<button type="button" data-role="none" class="slick-next">Next</button>',autoplay:!1,autoplaySpeed:3e3,centerMode:!1,centerPadding:"50px",cssEase:"ease",customPaging:function(a,b){return'<button type="button" data-role="none">'+(b+1)+"</button>"},dots:!1,dotsClass:"slick-dots",draggable:!0,easing:"linear",fade:!1,focusOnSelect:!1,infinite:!0,lazyLoad:"ondemand",onBeforeChange:null,onAfterChange:null,onInit:null,onReInit:null,pauseOnHover:!0,pauseOnDotsHover:!1,responsive:null,rtl:!1,slide:"div",slidesToShow:1,slidesToScroll:1,speed:300,swipe:!0,touchMove:!0,touchThreshold:5,useCSS:!0,vertical:!1},e.initials={animating:!1,dragging:!1,autoPlayTimer:null,currentSlide:0,currentLeft:null,direction:1,$dots:null,listWidth:null,listHeight:null,loadIndex:0,$nextArrow:null,$prevArrow:null,slideCount:null,slideWidth:null,$slideTrack:null,$slides:null,sliding:!1,slideOffset:0,swipeLeft:null,$list:null,touchObject:{},transformsEnabled:!1},a.extend(e,e.initials),e.activeBreakpoint=null,e.animType=null,e.animProp=null,e.breakpoints=[],e.breakpointSettings=[],e.cssTransitions=!1,e.paused=!1,e.positionProp=null,e.$slider=a(c),e.$slidesCache=null,e.transformType=null,e.transitionType=null,e.windowWidth=0,e.windowTimer=null,e.options=a.extend({},e.defaults,d),e.originalSettings=e.options,f=e.options.responsive||null,f&&f.length>-1){for(g in f)f.hasOwnProperty(g)&&(e.breakpoints.push(f[g].breakpoint),e.breakpointSettings[f[g].breakpoint]=f[g].settings);e.breakpoints.sort(function(a,b){return b-a})}e.autoPlay=a.proxy(e.autoPlay,e),e.autoPlayClear=a.proxy(e.autoPlayClear,e),e.changeSlide=a.proxy(e.changeSlide,e),e.selectHandler=a.proxy(e.selectHandler,e),e.setPosition=a.proxy(e.setPosition,e),e.swipeHandler=a.proxy(e.swipeHandler,e),e.dragHandler=a.proxy(e.dragHandler,e),e.keyHandler=a.proxy(e.keyHandler,e),e.autoPlayIterator=a.proxy(e.autoPlayIterator,e),e.instanceUid=b++,e.htmlExpr=/^(?:\s*(<[\w\W]+>)[^>]*)$/,e.init()}var b=0;return c}(),b.prototype.addSlide=function(b,c,d){var e=this;if("boolean"==typeof c)d=c,c=null;else if(0>c||c>=e.slideCount)return!1;e.unload(),"number"==typeof c?0===c&&0===e.$slides.length?a(b).appendTo(e.$slideTrack):d?a(b).insertBefore(e.$slides.eq(c)):a(b).insertAfter(e.$slides.eq(c)):d===!0?a(b).prependTo(e.$slideTrack):a(b).appendTo(e.$slideTrack),e.$slides=e.$slideTrack.children(this.options.slide),e.$slideTrack.children(this.options.slide).detach(),e.$slideTrack.append(e.$slides),e.$slides.each(function(b,c){a(c).attr("index",b)}),e.$slidesCache=e.$slides,e.reinit()},b.prototype.animateSlide=function(b,c){var d={},e=this;e.options.rtl===!0&&e.options.vertical===!1&&(b=-b),e.transformsEnabled===!1?e.options.vertical===!1?e.$slideTrack.animate({left:b},e.options.speed,e.options.easing,c):e.$slideTrack.animate({top:b},e.options.speed,e.options.easing,c):e.cssTransitions===!1?a({animStart:e.currentLeft}).animate({animStart:b},{duration:e.options.speed,easing:e.options.easing,step:function(a){e.options.vertical===!1?(d[e.animType]="translate("+a+"px, 0px)",e.$slideTrack.css(d)):(d[e.animType]="translate(0px,"+a+"px)",e.$slideTrack.css(d))},complete:function(){c&&c.call()}}):(e.applyTransition(),d[e.animType]=e.options.vertical===!1?"translate3d("+b+"px, 0px, 0px)":"translate3d(0px,"+b+"px, 0px)",e.$slideTrack.css(d),c&&setTimeout(function(){e.disableTransition(),c.call()},e.options.speed))},b.prototype.applyTransition=function(a){var b=this,c={};c[b.transitionType]=b.options.fade===!1?b.transformType+" "+b.options.speed+"ms "+b.options.cssEase:"opacity "+b.options.speed+"ms "+b.options.cssEase,b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.autoPlay=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer),a.slideCount>a.options.slidesToShow&&a.paused!==!0&&(a.autoPlayTimer=setInterval(a.autoPlayIterator,a.options.autoplaySpeed))},b.prototype.autoPlayClear=function(){var a=this;a.autoPlayTimer&&clearInterval(a.autoPlayTimer)},b.prototype.autoPlayIterator=function(){var b=this,c=null!=b.options.asNavFor?a(b.options.asNavFor).getSlick():null;b.options.infinite===!1?1===b.direction?(b.currentSlide+1===b.slideCount-1&&(b.direction=0),b.slideHandler(b.currentSlide+b.options.slidesToScroll),null!=c&&c.slideHandler(c.currentSlide+c.options.slidesToScroll)):(0===b.currentSlide-1&&(b.direction=1),b.slideHandler(b.currentSlide-b.options.slidesToScroll),null!=c&&c.slideHandler(c.currentSlide-c.options.slidesToScroll)):(b.slideHandler(b.currentSlide+b.options.slidesToScroll),null!=c&&c.slideHandler(c.currentSlide+c.options.slidesToScroll))},b.prototype.buildArrows=function(){var b=this;b.options.arrows===!0&&b.slideCount>b.options.slidesToShow&&(b.$prevArrow=a(b.options.prevArrow),b.$nextArrow=a(b.options.nextArrow),b.htmlExpr.test(b.options.prevArrow)&&b.$prevArrow.appendTo(b.options.appendArrows),b.htmlExpr.test(b.options.nextArrow)&&b.$nextArrow.appendTo(b.options.appendArrows),b.options.infinite!==!0&&b.$prevArrow.addClass("slick-disabled"))},b.prototype.buildDots=function(){var c,d,b=this;if(b.options.dots===!0&&b.slideCount>b.options.slidesToShow){for(d='<ul class="'+b.options.dotsClass+'">',c=0;c<=b.getDotCount();c+=1)d+="<li>"+b.options.customPaging.call(this,b,c)+"</li>";d+="</ul>",b.$dots=a(d).appendTo(b.$slider),b.$dots.find("li").first().addClass("slick-active")}},b.prototype.buildOut=function(){var b=this;b.$slides=b.$slider.children(b.options.slide+":not(.slick-cloned)").addClass("slick-slide"),b.slideCount=b.$slides.length,b.$slides.each(function(b,c){a(c).attr("index",b)}),b.$slidesCache=b.$slides,b.$slider.addClass("slick-slider"),b.$slideTrack=0===b.slideCount?a('<div class="slick-track"/>').appendTo(b.$slider):b.$slides.wrapAll('<div class="slick-track"/>').parent(),b.$list=b.$slideTrack.wrap('<div class="slick-list"/>').parent(),b.$slideTrack.css("opacity",0),b.options.centerMode===!0&&(b.options.slidesToScroll=1,0===b.options.slidesToShow%2&&(b.options.slidesToShow=3)),a("img[data-lazy]",b.$slider).not("[src]").addClass("slick-loading"),b.setupInfinite(),b.buildArrows(),b.buildDots(),b.updateDots(),b.options.accessibility===!0&&b.$list.prop("tabIndex",0),b.setSlideClasses("number"==typeof this.currentSlide?this.currentSlide:0),b.options.draggable===!0&&b.$list.addClass("draggable")},b.prototype.checkResponsive=function(){var c,d,b=this;if(b.originalSettings.responsive&&b.originalSettings.responsive.length>-1&&null!==b.originalSettings.responsive){d=null;for(c in b.breakpoints)b.breakpoints.hasOwnProperty(c)&&a(window).width()<b.breakpoints[c]&&(d=b.breakpoints[c]);null!==d?null!==b.activeBreakpoint?d!==b.activeBreakpoint&&(b.activeBreakpoint=d,b.options=a.extend({},b.options,b.breakpointSettings[d]),b.refresh()):(b.activeBreakpoint=d,b.options=a.extend({},b.options,b.breakpointSettings[d]),b.refresh()):null!==b.activeBreakpoint&&(b.activeBreakpoint=null,b.options=a.extend({},b.options,b.originalSettings),b.refresh())}},b.prototype.changeSlide=function(b){var c=this,d=a(b.target),e=null!=c.options.asNavFor?a(c.options.asNavFor).getSlick():null;switch(d.is("a")&&b.preventDefault(),b.data.message){case"previous":c.slideCount>c.options.slidesToShow&&(c.slideHandler(c.currentSlide-c.options.slidesToScroll),null!=e&&e.slideHandler(e.currentSlide-e.options.slidesToScroll));break;case"next":c.slideCount>c.options.slidesToShow&&(c.slideHandler(c.currentSlide+c.options.slidesToScroll),null!=e&&e.slideHandler(e.currentSlide+e.options.slidesToScroll));break;case"index":var f=a(b.target).parent().index()*c.options.slidesToScroll;c.slideHandler(f),null!=e&&e.slideHandler(f);break;default:return!1}},b.prototype.destroy=function(){var b=this;b.autoPlayClear(),b.touchObject={},a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&(b.$prevArrow.remove(),b.$nextArrow.remove()),b.$slides.parent().hasClass("slick-track")&&b.$slides.unwrap().unwrap(),b.$slides.removeClass("slick-slide slick-active slick-visible").removeAttr("style"),b.$slider.removeClass("slick-slider"),b.$slider.removeClass("slick-initialized"),b.$list.off(".slick"),a(window).off(".slick-"+b.instanceUid),a(document).off(".slick-"+b.instanceUid)},b.prototype.disableTransition=function(a){var b=this,c={};c[b.transitionType]="",b.options.fade===!1?b.$slideTrack.css(c):b.$slides.eq(a).css(c)},b.prototype.fadeSlide=function(a,b){var c=this;c.cssTransitions===!1?(c.$slides.eq(a).css({zIndex:1e3}),c.$slides.eq(a).animate({opacity:1},c.options.speed,c.options.easing,b)):(c.applyTransition(a),c.$slides.eq(a).css({opacity:1,zIndex:1e3}),b&&setTimeout(function(){c.disableTransition(a),b.call()},c.options.speed))},b.prototype.filterSlides=function(a){var b=this;null!==a&&(b.unload(),b.$slideTrack.children(this.options.slide).detach(),b.$slidesCache.filter(a).appendTo(b.$slideTrack),b.reinit())},b.prototype.getCurrent=function(){var a=this;return a.currentSlide},b.prototype.getDotCount=function(){var e,a=this,b=0,c=0,d=0;for(e=a.options.infinite===!0?a.slideCount+a.options.slidesToShow-a.options.slidesToScroll:a.slideCount;e>b;)d++,c+=a.options.slidesToScroll,b=c+a.options.slidesToShow;return d},b.prototype.getLeft=function(a){var c,d,b=this,e=0;return b.slideOffset=0,d=b.$slides.first().outerHeight(),b.options.infinite===!0?(b.slideCount>b.options.slidesToShow&&(b.slideOffset=-1*b.slideWidth*b.options.slidesToShow,e=-1*d*b.options.slidesToShow),0!==b.slideCount%b.options.slidesToScroll&&a+b.options.slidesToScroll>b.slideCount&&b.slideCount>b.options.slidesToShow&&(b.slideOffset=-1*b.slideCount%b.options.slidesToShow*b.slideWidth,e=-1*b.slideCount%b.options.slidesToShow*d)):0!==b.slideCount%b.options.slidesToShow&&a+b.options.slidesToScroll>b.slideCount&&b.slideCount>b.options.slidesToShow&&(b.slideOffset=b.options.slidesToShow*b.slideWidth-b.slideCount%b.options.slidesToShow*b.slideWidth,e=b.slideCount%b.options.slidesToShow*d),b.options.centerMode===!0&&b.options.infinite===!0?b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)-b.slideWidth:b.options.centerMode===!0&&(b.slideOffset+=b.slideWidth*Math.floor(b.options.slidesToShow/2)),c=b.options.vertical===!1?-1*a*b.slideWidth+b.slideOffset:-1*a*d+e},b.prototype.init=function(){var b=this;a(b.$slider).hasClass("slick-initialized")||(a(b.$slider).addClass("slick-initialized"),b.buildOut(),b.setProps(),b.startLoad(),b.loadSlider(),b.initializeEvents(),b.checkResponsive()),null!==b.options.onInit&&b.options.onInit.call(this,b)},b.prototype.initArrowEvents=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.on("click.slick",{message:"previous"},a.changeSlide),a.$nextArrow.on("click.slick",{message:"next"},a.changeSlide))},b.prototype.initDotEvents=function(){var b=this;b.options.dots===!0&&b.slideCount>b.options.slidesToShow&&a("li",b.$dots).on("click.slick",{message:"index"},b.changeSlide),b.options.dots===!0&&b.options.pauseOnDotsHover===!0&&b.options.autoplay===!0&&a("li",b.$dots).on("mouseenter.slick",b.autoPlayClear).on("mouseleave.slick",b.autoPlay)},b.prototype.initializeEvents=function(){var b=this;b.initArrowEvents(),b.initDotEvents(),b.$list.on("touchstart.slick mousedown.slick",{action:"start"},b.swipeHandler),b.$list.on("touchmove.slick mousemove.slick",{action:"move"},b.swipeHandler),b.$list.on("touchend.slick mouseup.slick",{action:"end"},b.swipeHandler),b.$list.on("touchcancel.slick mouseleave.slick",{action:"end"},b.swipeHandler),b.options.pauseOnHover===!0&&b.options.autoplay===!0&&(b.$list.on("mouseenter.slick",b.autoPlayClear),b.$list.on("mouseleave.slick",b.autoPlay)),b.options.accessibility===!0&&b.$list.on("keydown.slick",b.keyHandler),b.options.focusOnSelect===!0&&a(b.options.slide,b.$slideTrack).on("click.slick",b.selectHandler),a(window).on("orientationchange.slick.slick-"+b.instanceUid,function(){b.checkResponsive(),b.setPosition()}),a(window).on("resize.slick.slick-"+b.instanceUid,function(){a(window).width()!==b.windowWidth&&(clearTimeout(b.windowDelay),b.windowDelay=window.setTimeout(function(){b.windowWidth=a(window).width(),b.checkResponsive(),b.setPosition()},50))}),a(window).on("load.slick.slick-"+b.instanceUid,b.setPosition),a(document).on("ready.slick.slick-"+b.instanceUid,b.setPosition)},b.prototype.initUI=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.show(),a.$nextArrow.show()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.show(),a.options.autoplay===!0&&a.autoPlay()},b.prototype.keyHandler=function(a){var b=this;37===a.keyCode?b.changeSlide({data:{message:"previous"}}):39===a.keyCode&&b.changeSlide({data:{message:"next"}})},b.prototype.lazyLoad=function(){function g(b){a("img[data-lazy]",b).each(function(){var b=a(this),c=a(this).attr("data-lazy")+"?"+(new Date).getTime();b.load(function(){b.animate({opacity:1},200)}).css({opacity:0}).attr("src",c).removeAttr("data-lazy").removeClass("slick-loading")})}var c,d,e,f,b=this;b.options.centerMode===!0||b.options.fade===!0?(e=b.options.slidesToShow+b.currentSlide-1,f=e+b.options.slidesToShow+2):(e=b.options.infinite?b.options.slidesToShow+b.currentSlide:b.currentSlide,f=e+b.options.slidesToShow),c=b.$slider.find(".slick-slide").slice(e,f),g(c),1==b.slideCount?(d=b.$slider.find(".slick-slide"),g(d)):b.currentSlide>=b.slideCount-b.options.slidesToShow?(d=b.$slider.find(".slick-cloned").slice(0,b.options.slidesToShow),g(d)):0===b.currentSlide&&(d=b.$slider.find(".slick-cloned").slice(-1*b.options.slidesToShow),g(d))},b.prototype.loadSlider=function(){var a=this;a.setPosition(),a.$slideTrack.css({opacity:1}),a.$slider.removeClass("slick-loading"),a.initUI(),"progressive"===a.options.lazyLoad&&a.progressiveLazyLoad()},b.prototype.postSlide=function(a){var b=this;null!==b.options.onAfterChange&&b.options.onAfterChange.call(this,b,a),b.animating=!1,b.setPosition(),b.swipeLeft=null,b.options.autoplay===!0&&b.paused===!1&&b.autoPlay()},b.prototype.progressiveLazyLoad=function(){var c,d,b=this;c=a("img[data-lazy]").length,c>0&&(d=a("img[data-lazy]",b.$slider).first(),d.attr("src",d.attr("data-lazy")).removeClass("slick-loading").load(function(){d.removeAttr("data-lazy"),b.progressiveLazyLoad()}))},b.prototype.refresh=function(){var b=this,c=b.currentSlide;b.destroy(),a.extend(b,b.initials),b.currentSlide=c,b.init()},b.prototype.reinit=function(){var b=this;b.$slides=b.$slideTrack.children(b.options.slide).addClass("slick-slide"),b.slideCount=b.$slides.length,b.currentSlide>=b.slideCount&&0!==b.currentSlide&&(b.currentSlide=b.currentSlide-b.options.slidesToScroll),b.setProps(),b.setupInfinite(),b.buildArrows(),b.updateArrows(),b.initArrowEvents(),b.buildDots(),b.updateDots(),b.initDotEvents(),b.options.focusOnSelect===!0&&a(b.options.slide,b.$slideTrack).on("click.slick",b.selectHandler),b.setSlideClasses(0),b.setPosition(),null!==b.options.onReInit&&b.options.onReInit.call(this,b)},b.prototype.removeSlide=function(a,b){var c=this;return"boolean"==typeof a?(b=a,a=b===!0?0:c.slideCount-1):a=b===!0?--a:a,c.slideCount<1||0>a||a>c.slideCount-1?!1:(c.unload(),c.$slideTrack.children(this.options.slide).eq(a).remove(),c.$slides=c.$slideTrack.children(this.options.slide),c.$slideTrack.children(this.options.slide).detach(),c.$slideTrack.append(c.$slides),c.$slidesCache=c.$slides,c.reinit(),void 0)},b.prototype.setCSS=function(a){var d,e,b=this,c={};b.options.rtl===!0&&(a=-a),d="left"==b.positionProp?a+"px":"0px",e="top"==b.positionProp?a+"px":"0px",c[b.positionProp]=a,b.transformsEnabled===!1?b.$slideTrack.css(c):(c={},b.cssTransitions===!1?(c[b.animType]="translate("+d+", "+e+")",b.$slideTrack.css(c)):(c[b.animType]="translate3d("+d+", "+e+", 0px)",b.$slideTrack.css(c)))},b.prototype.setDimensions=function(){var a=this;a.options.vertical===!1?a.options.centerMode===!0&&a.$list.css({padding:"0px "+a.options.centerPadding}):(a.$list.height(a.$slides.first().outerHeight(!0)*a.options.slidesToShow),a.options.centerMode===!0&&a.$list.css({padding:a.options.centerPadding+" 0px"})),a.listWidth=a.$list.width(),a.listHeight=a.$list.height(),a.options.vertical===!1?(a.slideWidth=Math.ceil(a.listWidth/a.options.slidesToShow),a.$slideTrack.width(Math.ceil(a.slideWidth*a.$slideTrack.children(".slick-slide").length))):(a.slideWidth=Math.ceil(a.listWidth),a.$slideTrack.height(Math.ceil(a.$slides.first().outerHeight(!0)*a.$slideTrack.children(".slick-slide").length)));var b=a.$slides.first().outerWidth(!0)-a.$slides.first().width();a.$slideTrack.children(".slick-slide").width(a.slideWidth-b)},b.prototype.setFade=function(){var c,b=this;b.$slides.each(function(d,e){c=-1*b.slideWidth*d,a(e).css({position:"relative",left:c,top:0,zIndex:800,opacity:0})}),b.$slides.eq(b.currentSlide).css({zIndex:900,opacity:1})},b.prototype.setPosition=function(){var a=this;a.setDimensions(),a.options.fade===!1?a.setCSS(a.getLeft(a.currentSlide)):a.setFade()},b.prototype.setProps=function(){var a=this;a.positionProp=a.options.vertical===!0?"top":"left","top"===a.positionProp?a.$slider.addClass("slick-vertical"):a.$slider.removeClass("slick-vertical"),(void 0!==document.body.style.WebkitTransition||void 0!==document.body.style.MozTransition||void 0!==document.body.style.msTransition)&&a.options.useCSS===!0&&(a.cssTransitions=!0),void 0!==document.body.style.MozTransform&&(a.animType="MozTransform",a.transformType="-moz-transform",a.transitionType="MozTransition"),void 0!==document.body.style.webkitTransform&&(a.animType="webkitTransform",a.transformType="-webkit-transform",a.transitionType="webkitTransition"),void 0!==document.body.style.msTransform&&(a.animType="msTransform",a.transformType="-ms-transform",a.transitionType="msTransition"),void 0!==document.body.style.transform&&(a.animType="transform",a.transformType="transform",a.transitionType="transition"),a.transformsEnabled=null!==a.animType},b.prototype.setSlideClasses=function(a){var c,d,e,f,b=this;b.$slider.find(".slick-slide").removeClass("slick-active").removeClass("slick-center"),d=b.$slider.find(".slick-slide"),b.options.centerMode===!0?(c=Math.floor(b.options.slidesToShow/2),b.options.infinite===!0&&(a>=c&&a<=b.slideCount-1-c?b.$slides.slice(a-c,a+c+1).addClass("slick-active"):(e=b.options.slidesToShow+a,d.slice(e-c+1,e+c+2).addClass("slick-active")),0===a?d.eq(d.length-1-b.options.slidesToShow).addClass("slick-center"):a===b.slideCount-1&&d.eq(b.options.slidesToShow).addClass("slick-center")),b.$slides.eq(a).addClass("slick-center")):a>=0&&a<=b.slideCount-b.options.slidesToShow?b.$slides.slice(a,a+b.options.slidesToShow).addClass("slick-active"):d.length<=b.options.slidesToShow?d.addClass("slick-active"):(f=b.slideCount%b.options.slidesToShow,e=b.options.infinite===!0?b.options.slidesToShow+a:a,b.options.slidesToShow==b.options.slidesToScroll&&b.slideCount-a<b.options.slidesToShow?d.slice(e-(b.options.slidesToShow-f),e+f).addClass("slick-active"):d.slice(e,e+b.options.slidesToShow).addClass("slick-active")),"ondemand"===b.options.lazyLoad&&b.lazyLoad()},b.prototype.setupInfinite=function(){var c,d,e,b=this;if((b.options.fade===!0||b.options.vertical===!0)&&(b.options.centerMode=!1),b.options.infinite===!0&&b.options.fade===!1&&(d=null,b.slideCount>b.options.slidesToShow)){for(e=b.options.centerMode===!0?b.options.slidesToShow+1:b.options.slidesToShow,c=b.slideCount;c>b.slideCount-e;c-=1)d=c-1,a(b.$slides[d]).clone(!0).attr("id","").prependTo(b.$slideTrack).addClass("slick-cloned");for(c=0;e>c;c+=1)d=c,a(b.$slides[d]).clone(!0).attr("id","").appendTo(b.$slideTrack).addClass("slick-cloned");b.$slideTrack.find(".slick-cloned").find("[id]").each(function(){a(this).attr("id","")})}},b.prototype.selectHandler=function(b){var c=this,d=null!=c.options.asNavFor?a(c.options.asNavFor).getSlick():null,e=parseInt(a(b.target).parent().attr("index"));if(e||(e=0),!(c.slideCount<=c.options.slidesToShow)&&(c.slideHandler(e),null!=d)){if(d.slideCount<=d.options.slidesToShow)return;d.slideHandler(e)}},b.prototype.slideHandler=function(a){var b,c,d,e,f=null,g=this;return g.animating===!0?!1:(b=a,f=g.getLeft(b),d=g.getLeft(g.currentSlide),e=0!==g.slideCount%g.options.slidesToScroll?g.options.slidesToScroll:0,g.currentLeft=null===g.swipeLeft?d:g.swipeLeft,g.options.infinite===!1&&g.options.centerMode===!1&&(0>a||a>g.slideCount-g.options.slidesToShow+e)?(g.options.fade===!1&&(b=g.currentSlide,g.animateSlide(d,function(){g.postSlide(b)})),!1):g.options.infinite===!1&&g.options.centerMode===!0&&(0>a||a>g.slideCount-g.options.slidesToScroll)?(g.options.fade===!1&&(b=g.currentSlide,g.animateSlide(d,function(){g.postSlide(b)})),!1):(g.options.autoplay===!0&&clearInterval(g.autoPlayTimer),c=0>b?0!==g.slideCount%g.options.slidesToScroll?g.slideCount-g.slideCount%g.options.slidesToScroll:g.slideCount-g.options.slidesToScroll:b>g.slideCount-1?0:b,g.animating=!0,null!==g.options.onBeforeChange&&a!==g.currentSlide&&g.options.onBeforeChange.call(this,g,g.currentSlide,c),g.currentSlide=c,g.setSlideClasses(g.currentSlide),g.updateDots(),g.updateArrows(),g.options.fade===!0?(g.fadeSlide(c,function(){g.postSlide(c)}),!1):(g.animateSlide(f,function(){g.postSlide(c)}),void 0)))},b.prototype.startLoad=function(){var a=this;a.options.arrows===!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.hide(),a.$nextArrow.hide()),a.options.dots===!0&&a.slideCount>a.options.slidesToShow&&a.$dots.hide(),a.$slider.addClass("slick-loading")},b.prototype.swipeDirection=function(){var a,b,c,d,e=this;return a=e.touchObject.startX-e.touchObject.curX,b=e.touchObject.startY-e.touchObject.curY,c=Math.atan2(b,a),d=Math.round(180*c/Math.PI),0>d&&(d=360-Math.abs(d)),45>=d&&d>=0?"left":360>=d&&d>=315?"left":d>=135&&225>=d?"right":"vertical"},b.prototype.swipeEnd=function(b){var c=this,d=null!=c.options.asNavFor?a(c.options.asNavFor).getSlick():null;if(c.dragging=!1,void 0===c.touchObject.curX)return!1;if(c.touchObject.swipeLength>=c.touchObject.minSwipe)switch(a(b.target).on("click.slick",function(b){b.stopImmediatePropagation(),b.stopPropagation(),b.preventDefault(),a(b.target).off("click.slick")}),c.swipeDirection()){case"left":c.slideHandler(c.currentSlide+c.options.slidesToScroll),null!=d&&d.slideHandler(d.currentSlide+d.options.slidesToScroll),c.touchObject={};break;case"right":c.slideHandler(c.currentSlide-c.options.slidesToScroll),null!=d&&d.slideHandler(d.currentSlide-d.options.slidesToScroll),c.touchObject={}}else c.touchObject.startX!==c.touchObject.curX&&(c.slideHandler(c.currentSlide),null!=d&&d.slideHandler(d.currentSlide),c.touchObject={})},b.prototype.swipeHandler=function(a){var b=this;if(!(b.options.swipe===!1||"ontouchend"in document&&b.options.swipe===!1||b.options.draggable===!1||b.options.draggable===!1&&!a.originalEvent.touches))switch(b.touchObject.fingerCount=a.originalEvent&&void 0!==a.originalEvent.touches?a.originalEvent.touches.length:1,b.touchObject.minSwipe=b.listWidth/b.options.touchThreshold,a.data.action){case"start":b.swipeStart(a);break;case"move":b.swipeMove(a);break;case"end":b.swipeEnd(a)}},b.prototype.swipeMove=function(a){var c,d,e,f,b=this;return f=void 0!==a.originalEvent?a.originalEvent.touches:null,c=b.getLeft(b.currentSlide),!b.dragging||f&&1!==f.length?!1:(b.touchObject.curX=void 0!==f?f[0].pageX:a.clientX,b.touchObject.curY=void 0!==f?f[0].pageY:a.clientY,b.touchObject.swipeLength=Math.round(Math.sqrt(Math.pow(b.touchObject.curX-b.touchObject.startX,2))),d=b.swipeDirection(),"vertical"!==d?(void 0!==a.originalEvent&&b.touchObject.swipeLength>4&&a.preventDefault(),e=b.touchObject.curX>b.touchObject.startX?1:-1,b.swipeLeft=b.options.vertical===!1?c+b.touchObject.swipeLength*e:c+b.touchObject.swipeLength*(b.$list.height()/b.listWidth)*e,b.options.fade===!0||b.options.touchMove===!1?!1:b.animating===!0?(b.swipeLeft=null,!1):(b.setCSS(b.swipeLeft),void 0)):void 0)},b.prototype.swipeStart=function(a){var c,b=this;return 1!==b.touchObject.fingerCount||b.slideCount<=b.options.slidesToShow?(b.touchObject={},!1):(void 0!==a.originalEvent&&void 0!==a.originalEvent.touches&&(c=a.originalEvent.touches[0]),b.touchObject.startX=b.touchObject.curX=void 0!==c?c.pageX:a.clientX,b.touchObject.startY=b.touchObject.curY=void 0!==c?c.pageY:a.clientY,b.dragging=!0,void 0)},b.prototype.unfilterSlides=function(){var a=this;null!==a.$slidesCache&&(a.unload(),a.$slideTrack.children(this.options.slide).detach(),a.$slidesCache.appendTo(a.$slideTrack),a.reinit())},b.prototype.unload=function(){var b=this;a(".slick-cloned",b.$slider).remove(),b.$dots&&b.$dots.remove(),b.$prevArrow&&(b.$prevArrow.remove(),b.$nextArrow.remove()),b.$slides.removeClass("slick-slide slick-active slick-visible").removeAttr("style")},b.prototype.updateArrows=function(){var a=this;a.options.arrows===!0&&a.options.infinite!==!0&&a.slideCount>a.options.slidesToShow&&(a.$prevArrow.removeClass("slick-disabled"),a.$nextArrow.removeClass("slick-disabled"),0===a.currentSlide?(a.$prevArrow.addClass("slick-disabled"),a.$nextArrow.removeClass("slick-disabled")):a.currentSlide>=a.slideCount-a.options.slidesToShow&&(a.$nextArrow.addClass("slick-disabled"),a.$prevArrow.removeClass("slick-disabled")))},b.prototype.updateDots=function(){var a=this;null!==a.$dots&&(a.$dots.find("li").removeClass("slick-active"),a.$dots.find("li").eq(Math.floor(a.currentSlide/a.options.slidesToScroll)).addClass("slick-active"))},a.fn.slick=function(a){var c=this;return c.each(function(c,d){d.slick=new b(d,a)})},a.fn.slickAdd=function(a,b,c){var d=this;return d.each(function(d,e){e.slick.addSlide(a,b,c)})},a.fn.slickCurrentSlide=function(){var a=this;return a.get(0).slick.getCurrent()},a.fn.slickFilter=function(a){var b=this;return b.each(function(b,c){c.slick.filterSlides(a)})},a.fn.slickGoTo=function(b){var c=this;return c.each(function(c,d){var e=null!=d.slick.options.asNavFor?a(d.slick.options.asNavFor):null;null!=e&&e.slickGoTo(b),d.slick.slideHandler(b)})},a.fn.slickNext=function(){var a=this;return a.each(function(a,b){b.slick.changeSlide({data:{message:"next"}})})},a.fn.slickPause=function(){var a=this;return a.each(function(a,b){b.slick.autoPlayClear(),b.slick.paused=!0})},a.fn.slickPlay=function(){var a=this;return a.each(function(a,b){b.slick.paused=!1,b.slick.autoPlay()})},a.fn.slickPrev=function(){var a=this;return a.each(function(a,b){b.slick.changeSlide({data:{message:"previous"}})})},a.fn.slickRemove=function(a,b){var c=this;return c.each(function(c,d){d.slick.removeSlide(a,b)})},a.fn.slickGetOption=function(a){var b=this;return b.get(0).slick.options[a]},a.fn.slickSetOption=function(a,b,c){var d=this;return d.each(function(d,e){e.slick.options[a]=b,c===!0&&(e.slick.unload(),e.slick.reinit())})},a.fn.slickUnfilter=function(){var a=this;return a.each(function(a,b){b.slick.unfilterSlides()})},a.fn.unslick=function(){var a=this;return a.each(function(a,b){b.slick&&b.slick.destroy()})},a.fn.getSlick=function(){var a=null,b=this;return b.each(function(b,c){a=c.slick}),a}}); \ No newline at end of file diff --git a/src/static/js/slick/slick.scss b/src/static/js/slick/slick.scss new file mode 100755 index 0000000..c34f6b0 --- /dev/null +++ b/src/static/js/slick/slick.scss @@ -0,0 +1,286 @@ +@charset "UTF-8"; + +// Default Variables + +$slick-font-path: "./fonts/" !default; +$slick-font-family: "slick" !default; +$slick-loader-path: "./" !default; +$slick-arrow-color: white !default; +$slick-dot-color: black !default; +$slick-dot-color-active: $slick-dot-color !default; +$slick-prev-character: '\2190' !default; +$slick-next-character: '\2192' !default; +$slick-dot-character: '\2022' !default; +$slick-dot-size: 6px !default; +$opacity-default: .75; +$opacity-on-hover: 1; +$opacity-not-active: .25; + + +@function slick-image-url($url) { + @if function-exists(image-url) { + @return image-url($url, false, false); + } + @else { + @return url($slick-loader-path + $url); + } +} + +@function slick-font-url($url) { + @if function-exists(font-url) { + @return font-url($url); + } + @else { + @return url($slick-font-path + $url); + } +} + +/* Slider */ + +.slick-slider { + position: relative; + display: block; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -ms-touch-action: none; + -webkit-tap-highlight-color: transparent; +} +.slick-list { + position: relative; + overflow: hidden; + display: block; + margin: 0; + padding: 0; + + &:focus { + outline: none; + } + + .slick-loading & { + background: #fff slick-image-url("ajax-loader.gif") center center no-repeat; + } + + &.dragging { + cursor: pointer; + cursor: hand; + } +} +.slick-slider .slick-list, +.slick-track, +.slick-slide, +.slick-slide img { + -webkit-transform: translate3d(0, 0, 0); + -moz-transform: translate3d(0, 0, 0); + -ms-transform: translate3d(0, 0, 0); + -o-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); +} +.slick-track { + position: relative; + left: 0; + top: 0; + display: block; + zoom: 1; + + &:before, + &:after { + content: ""; + display: table; + } + + &:after { + clear: both; + } + + .slick-loading & { + visibility: hidden; + } +} +.slick-slide { + float: left; + height: 100%; + min-height: 1px; + [dir="rtl"] & { + float: right; + } + img { + display: block; + } + &.slick-loading img { + display: none; + } + + display: none; + + &.dragging img { + pointer-events: none; + } + + .slick-initialized & { + display: block; + } + + .slick-loading & { + visibility: hidden; + } + + .slick-vertical & { + display: block; + height: auto; + border: 1px solid transparent; + } +} + +/* Icons */ +@if $slick-font-family == "slick" { + @font-face { + font-family:"slick"; + src: slick-font-url("slick.eot"); + src: slick-font-url("slick.eot?#iefix") format("embedded-opentype"), + slick-font-url("slick.woff") format("woff"), + slick-font-url("slick.ttf") format("truetype"), + slick-font-url("slick.svg#slick") format("svg"); + font-weight: normal; + font-style: normal; + } +} + +/* Arrows */ + +.slick-prev, +.slick-next { + position: absolute; + display: block; + height: 20px; + width: 20px; + line-height: 0; + font-size: 0; + cursor: pointer; + background: transparent; + color: transparent; + top: 50%; + margin-top: -10px; + padding: 0; + border: none; + outline: none; + &:hover, &:focus { + outline: none; + background: transparent; + color: transparent; + &:before { + opacity: $opacity-on-hover; + } + } + &.slick-disabled:before { + opacity: $opacity-not-active; + } +} +.slick-prev:before, .slick-next:before { + font-family: $slick-font-family; + font-size: 20px; + line-height: 1; + color: $slick-arrow-color; + opacity: $opacity-default; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.slick-prev { + left: -25px; + [dir="rtl"] & { + left: auto; + right: -25px; + } + &:before { + content: $slick-prev-character; + [dir="rtl"] & { + content: $slick-next-character; + } + } +} +.slick-next { + right: -25px; + [dir="rtl"] & { + left: -25px; + right: auto; + } + &:before { + content: $slick-next-character; + [dir="rtl"] & { + content: $slick-prev-character; + } + } +} + +/* Dots */ + +.slick-slider { + margin-bottom: 30px; +} +.slick-dots { + position: absolute; + bottom: -45px; + list-style: none; + display: block; + text-align: center; + padding: 0; + width: 100%; + + li { + position: relative; + display: inline-block; + height: 20px; + width: 20px; + margin: 0 5px; + padding: 0; + cursor: pointer; + + button { + border: 0; + background: transparent; + display: block; + height: 20px; + width: 20px; + outline: none; + line-height: 0; + font-size: 0; + color: transparent; + padding: 5px; + cursor: pointer; + &:hover, &:focus { + outline: none; + &:before { + opacity: $opacity-on-hover; + } + } + + &:before { + position: absolute; + top: 0; + left: 0; + content: $slick-dot-character; + width: 20px; + height: 20px; + font-family: $slick-font-family; + font-size: $slick-dot-size; + line-height: 20px; + text-align: center; + color: $slick-dot-color; + opacity: $opacity-not-active; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + + } + + &.slick-active button:before { + color: $slick-dot-color-active; + opacity: $opacity-default; + } + } +} diff --git a/src/static/mediaelement/background.png b/src/static/mediaelement/background.png new file mode 100755 index 0000000000000000000000000000000000000000..fd428412ae26af13dab448ec833b1cb603e37ee9 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1G9-c0aAr-gYoHrC?P~c(M$o@YsOF*1w?-55oQ{94SCl?~X dlYaFB3@*Kl;yd0~_5jUf@O1TaS?83{1OV-(FBAX( literal 0 HcmV?d00001 diff --git a/src/static/mediaelement/bigplay.png b/src/static/mediaelement/bigplay.png new file mode 100755 index 0000000000000000000000000000000000000000..694553e31c387188b6bde397a5200c212aff2dc5 GIT binary patch literal 3001 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 J;~KO(@jp;uhBg2I literal 0 HcmV?d00001 diff --git a/src/static/mediaelement/bigplay.svg b/src/static/mediaelement/bigplay.svg new file mode 100755 index 0000000..c2f62bb --- /dev/null +++ b/src/static/mediaelement/bigplay.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?> <!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1 --> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg id="bigplay-gradient.fw-Page%201" viewBox="0 0 100 200" style="background-color:#ffffff00" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" x="0px" y="0px" width="100px" height="200px" > <defs> <radialGradient id="gradient1" cx="50%" cy="50%" r="50%"> <stop stop-color="#222222" stop-opacity="0" offset="70%"/> <stop stop-color="#222222" stop-opacity="0.0118" offset="70.202%"/> <stop stop-color="#333333" stop-opacity="1" offset="85%"/> <stop stop-color="#333333" stop-opacity="0" offset="100%"/> </radialGradient> <radialGradient id="gradient2" cx="50%" cy="50%" r="50%"> <stop stop-color="#bbbbbb" stop-opacity="0" offset="70%"/> <stop stop-color="#bbbbbb" stop-opacity="0.0118" offset="70.202%"/> <stop stop-color="#bbbbbb" stop-opacity="1" offset="85%"/> <stop stop-color="#bbbbbb" stop-opacity="0" offset="100%"/> </radialGradient> <filter id="filter1" x="-100%" y="-100%" width="300%" height="300%"> <!-- Glow --> <feColorMatrix result="out" in="SourceGraphic" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.251 0"/> <feMorphology result="out" in="out" operator="dilate" radius="3"/> <feGaussianBlur result="out" in="out" stdDeviation="1.5"/> <feBlend in="SourceGraphic" in2="out" mode="normal" result="Glow1"/> </filter> <filter id="filter2" x="-100%" y="-100%" width="300%" height="300%"> <!-- Glow --> <feColorMatrix result="out" in="SourceGraphic" type="matrix" values="0 0 0 0.8667 0 0 0 0 0.8667 0 0 0 0 0.8667 0 0 0 0 0.251 0"/> <feMorphology result="out" in="out" operator="dilate" radius="3"/> <feGaussianBlur result="out" in="out" stdDeviation="1.5"/> <feBlend in="SourceGraphic" in2="out" mode="normal" result="Glow2"/> </filter> </defs> <g id="Background"> </g> <g id="dark%20shadow"> <path d="M 22 50 C 22 34.5358 34.5358 22 50 22 C 65.4642 22 78 34.5358 78 50 C 78 65.4642 65.4642 78 50 78 C 34.5358 78 22 65.4642 22 50 ZM 5 50 C 5 74.8531 25.1469 95 50 95 C 74.8531 95 95 74.8531 95 50 C 95 25.1469 74.8531 5 50 5 C 25.1469 5 5 25.1469 5 50 Z" fill="url(#gradient1)"/> <path d="M 22 150 C 22 134.5358 34.5358 122 50 122 C 65.4642 122 78 134.5358 78 150 C 78 165.4642 65.4642 178 50 178 C 34.5358 178 22 165.4642 22 150 ZM 5 150 C 5 174.8531 25.1469 195 50 195 C 74.8531 195 95 174.8531 95 150 C 95 125.1469 74.8531 105 50 105 C 25.1469 105 5 125.1469 5 150 Z" fill="url(#gradient2)"/> </g> <g id="dark"> <path id="Polygon" filter="url(#filter1)" d="M 72.5 49.5 L 38.75 68.9856 L 38.75 30.0144 L 72.5 49.5 Z" fill="#ffffff"/> <path id="Ellipse" d="M 13 50.5 C 13 29.7891 29.7891 13 50.5 13 C 71.2109 13 88 29.7891 88 50.5 C 88 71.2109 71.2109 88 50.5 88 C 29.7891 88 13 71.2109 13 50.5 Z" stroke="#ffffff" stroke-width="5" fill="none"/> </g> <g id="light"> <path id="Polygon2" filter="url(#filter2)" d="M 72.5 149.5 L 38.75 168.9856 L 38.75 130.0144 L 72.5 149.5 Z" fill="#ffffff"/> <path id="Ellipse2" d="M 13 150.5 C 13 129.7891 29.7891 113 50.5 113 C 71.2109 113 88 129.7891 88 150.5 C 88 171.211 71.2109 188 50.5 188 C 29.7891 188 13 171.211 13 150.5 Z" stroke="#ffffff" stroke-width="5" fill="none"/> </g> </svg> \ No newline at end of file diff --git a/src/static/mediaelement/controls-ted.png b/src/static/mediaelement/controls-ted.png new file mode 100755 index 0000000000000000000000000000000000000000..3aac05aa83cb7fed54831a19d85a8c267e939720 GIT binary patch literal 1559 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 JPDHLkV1l~`FgySN literal 0 HcmV?d00001 diff --git a/src/static/mediaelement/controls-wmp-bg.png b/src/static/mediaelement/controls-wmp-bg.png new file mode 100755 index 0000000000000000000000000000000000000000..89bb9b95602ecfca6290f6006f817da365da7b90 GIT binary patch literal 1960 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 A)c^nh literal 0 HcmV?d00001 diff --git a/src/static/mediaelement/controls-wmp.png b/src/static/mediaelement/controls-wmp.png new file mode 100755 index 0000000000000000000000000000000000000000..4775ef5b02faf2b826d35dfc72511b6b27fea87b GIT binary patch literal 5511 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 JPDHLkV1kZU;|2f# literal 0 HcmV?d00001 diff --git a/src/static/mediaelement/controls.png b/src/static/mediaelement/controls.png new file mode 100755 index 0000000000000000000000000000000000000000..f6a857d800b64264443af4609e0ebf7175593d8f GIT binary patch literal 1892 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 C_uXs& literal 0 HcmV?d00001 diff --git a/src/static/mediaelement/controls.svg b/src/static/mediaelement/controls.svg new file mode 100755 index 0000000..af3bd41 --- /dev/null +++ b/src/static/mediaelement/controls.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?> <!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1 --> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg id="controls.fw-Page%201" viewBox="0 0 144 32" style="background-color:#ffffff00" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" x="0px" y="0px" width="144px" height="32px" > <defs> <radialGradient id="gradient1" cx="50%" cy="50%" r="50%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#f2f2f2" stop-opacity="0.2" offset="100%"/> </radialGradient> <linearGradient id="gradient2" x1="50%" y1="-7.8652%" x2="50%" y2="249.6629%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient3" x1="50%" y1="0%" x2="50%" y2="238.75%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient4" x1="50%" y1="0%" x2="50%" y2="100%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient5" x1="50%" y1="-33.3333%" x2="50%" y2="152.0833%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient6" x1="50%" y1="0%" x2="50%" y2="100%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient7" x1="50%" y1="-33.3333%" x2="50%" y2="152.0833%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient8" x1="50%" y1="0%" x2="50%" y2="100%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient9" x1="50%" y1="0%" x2="50%" y2="100%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient10" x1="50%" y1="0%" x2="50%" y2="100%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient11" x1="50%" y1="0%" x2="50%" y2="100%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient12" x1="50%" y1="0%" x2="50%" y2="238.75%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient13" x1="40%" y1="-140%" x2="40%" y2="98.75%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient14" x1="50%" y1="0%" x2="50%" y2="238.75%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient15" x1="60%" y1="-140%" x2="60%" y2="98.75%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient16" x1="50%" y1="0%" x2="50%" y2="298.4375%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient17" x1="50%" y1="0%" x2="50%" y2="238.75%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient18" x1="50%" y1="-200%" x2="50%" y2="100%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient19" x1="50%" y1="-200%" x2="50%" y2="110.9375%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient20" x1="55%" y1="0%" x2="55%" y2="100%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="100%"/> </linearGradient> <linearGradient id="gradient21" x1="50%" y1="0%" x2="50%" y2="100%"> <stop stop-color="#ffffff" stop-opacity="1" offset="0%"/> <stop stop-color="#c8c8c8" stop-opacity="1" offset="99.4444%"/> </linearGradient> </defs> <g id="BG"> </g> <g id="controls"> <path id="Line" d="M 98.5 7.5 L 109.5 7.5 " stroke="#ffffff" stroke-width="1" fill="none"/> <path id="Line2" d="M 98.5 3.5 L 109.5 3.5 " stroke="#ffffff" stroke-width="1" fill="none"/> <path id="Line3" d="M 98.5 11.5 L 109.5 11.5 " stroke="#ffffff" stroke-width="1" fill="none"/> <path id="Ellipse" d="M 108 11.5 C 108 10.6716 108.4477 10 109 10 C 109.5523 10 110 10.6716 110 11.5 C 110 12.3284 109.5523 13 109 13 C 108.4477 13 108 12.3284 108 11.5 Z" fill="#ffffff"/> <path id="Ellipse2" d="M 104 7.5 C 104 6.6716 104.4477 6 105 6 C 105.5523 6 106 6.6716 106 7.5 C 106 8.3284 105.5523 9 105 9 C 104.4477 9 104 8.3284 104 7.5 Z" fill="#ffffff"/> <path id="Ellipse3" d="M 108 3.5 C 108 2.6716 108.4477 2 109 2 C 109.5523 2 110 2.6716 110 3.5 C 110 4.3284 109.5523 5 109 5 C 108.4477 5 108 4.3284 108 3.5 Z" fill="#ffffff"/> </g> <g id="backlight"> <g id="off"> <rect x="83" y="21" width="10" height="6" stroke="#ffffff" stroke-width="1" fill="#333333"/> </g> <g id="on"> <path id="Ellipse4" d="M 81 8 C 81 5.2385 84.134 3 88 3 C 91.866 3 95 5.2385 95 8 C 95 10.7615 91.866 13 88 13 C 84.134 13 81 10.7615 81 8 Z" fill="url(#gradient1)"/> <rect x="83" y="5" width="10" height="6" stroke="#ffffff" stroke-width="1" fill="#333333"/> </g> </g> <g id="loop"> <g id="on2"> <path d="M 73.795 4.205 C 75.2155 4.8785 76.2 6.3234 76.2 8 C 76.2 10.3196 74.3196 12.2 72 12.2 C 69.6804 12.2 67.8 10.3196 67.8 8 C 67.8 6.3234 68.7845 4.8785 70.205 4.205 L 68.875 2.875 C 67.1501 3.9289 66 5.8306 66 8 C 66 11.3138 68.6862 14 72 14 C 75.3138 14 78 11.3138 78 8 C 78 5.8306 76.8499 3.9289 75.125 2.875 L 73.795 4.205 Z" fill="url(#gradient2)"/> <path d="M 71 2 L 66 2 L 71 7 L 71 2 Z" fill="url(#gradient3)"/> </g> <g id="off2"> <path d="M 73.795 20.205 C 75.2155 20.8785 76.2 22.3234 76.2 24 C 76.2 26.3196 74.3196 28.2 72 28.2 C 69.6804 28.2 67.8 26.3196 67.8 24 C 67.8 22.3234 68.7845 20.8785 70.205 20.205 L 68.875 18.875 C 67.1501 19.9289 66 21.8306 66 24 C 66 27.3138 68.6862 30 72 30 C 75.3138 30 78 27.3138 78 24 C 78 21.8306 76.8499 19.9289 75.125 18.875 L 73.795 20.205 Z" fill="#a8a8b7"/> <path d="M 71 18 L 66 18 L 71 23 L 71 18 Z" fill="#a8a8b7"/> </g> </g> <g id="cc"> <rect visibility="hidden" x="49" y="2" width="14" height="12" stroke="#b0b0b0" stroke-width="1" fill="none"/> <text visibility="hidden" x="49" y="17" width="14" fill="#ffffff" style="font-size: 10px; color: #ffffff; font-family: Arial; text-align: center; "><tspan><![CDATA[cc]]></tspan></text> <path d="M 55 7 C 50.2813 3.7813 50.063 12.9405 55 10 " stroke="#ffffff" stroke-width="1" fill="none"/> <path d="M 60 7 C 55.2813 3.7813 55.063 12.9405 60 10 " stroke="#ffffff" stroke-width="1" fill="none"/> <path d="M 50 3 L 62 3 L 62 13 L 50 13 L 50 3 ZM 49 2 L 49 14 L 63 14 L 63 2 L 49 2 Z" fill="url(#gradient4)"/> <rect x="49" y="2" width="14" height="12" fill="none"/> </g> <g id="volume"> <g id="no%20sound"> <rect x="17" y="5" width="5" height="6" fill="url(#gradient5)"/> <path d="M 21 5 L 25 2 L 25 14 L 21 11.0625 L 21 5 Z" fill="url(#gradient6)"/> </g> <g id="sound%20bars"> <rect x="17" y="21" width="5" height="6" fill="url(#gradient7)"/> <path d="M 21 21 L 25 18 L 25 30 L 21 27.0625 L 21 21 Z" fill="url(#gradient8)"/> <path d="M 27 18 C 27 18 30.0625 17.375 30 24 C 29.9375 30.625 27 30 27 30 " stroke="#ffffff" stroke-width="1" fill="none"/> <path d="M 26 21.0079 C 26 21.0079 28.041 20.6962 27.9994 24 C 27.9577 27.3038 26 26.9921 26 26.9921 " stroke="#ffffff" stroke-width="1" fill="none"/> </g> </g> <g id="play/pause"> <g id="play"> <path id="Polygon" d="M 14 8.5 L 3 14 L 3 3 L 14 8.5 Z" fill="url(#gradient9)"/> </g> <g id="pause"> <rect x="3" y="18" width="3" height="12" fill="url(#gradient10)"/> <rect x="10" y="18" width="3" height="12" fill="url(#gradient11)"/> </g> </g> <g id="fullscreen"> <g id="enter%201"> <path d="M 34 2 L 39 2 L 34 7 L 34 2 Z" fill="url(#gradient12)"/> <path d="M 34 14 L 39 14 L 34 9 L 34 14 Z" fill="url(#gradient13)"/> <path d="M 46 2 L 41 2 L 46 7 L 46 2 Z" fill="url(#gradient14)"/> <path d="M 46 14 L 41 14 L 46 9 L 46 14 Z" fill="url(#gradient15)"/> </g> <g id="exit"> <path d="M 42 22 L 46 22 L 42 18 L 42 22 Z" fill="url(#gradient16)"/> <path d="M 38 22 L 38 18 L 34 22 L 38 22 Z" fill="url(#gradient17)"/> <path d="M 38 26 L 34 26 L 38 30 L 38 26 Z" fill="url(#gradient18)"/> <path d="M 42 26 L 42 30 L 46 26 L 42 26 Z" fill="url(#gradient19)"/> </g> </g> <g id="stop"> <rect x="115" y="3" width="10" height="10" fill="url(#gradient20)"/> </g> <g id="chooser"> <path d="M 135.2346 6.1522 C 136.2551 5.7295 137.4251 6.2141 137.8478 7.2346 C 138.2704 8.2551 137.7859 9.425 136.7654 9.8478 C 135.7449 10.2705 134.5749 9.7859 134.1522 8.7654 C 133.7295 7.7449 134.2141 6.5749 135.2346 6.1522 ZM 133.2735 1.4176 L 136 4.0054 L 138.7265 1.4176 L 138.8246 5.1754 L 142.5824 5.2735 L 139.9946 8 L 142.5824 10.7265 L 138.8246 10.8246 L 138.7265 14.5824 L 136 11.9946 L 133.2735 14.5824 L 133.1754 10.8246 L 129.4176 10.7265 L 132.0054 8 L 129.4176 5.2735 L 133.1754 5.1754 L 133.2735 1.4176 Z" fill="url(#gradient21)"/> </g> </svg> \ No newline at end of file diff --git a/src/static/mediaelement/flashmediaelement.swf b/src/static/mediaelement/flashmediaelement.swf new file mode 100755 index 0000000000000000000000000000000000000000..2a5cb8da778c1659dbf164ce9d5fb19d246e20d6 GIT binary patch literal 28709 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 U82)>e5B#6Soac%9-x%4so%w;e`~Uy| literal 0 HcmV?d00001 diff --git a/src/static/mediaelement/loading.gif b/src/static/mediaelement/loading.gif new file mode 100755 index 0000000000000000000000000000000000000000..612222be5e474c36c345042dd6f697fa1d16a6a0 GIT binary patch literal 6224 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 a%CSF@A_b&47t_EYjD0%aV6(nOxBn04F1xn? literal 0 HcmV?d00001 diff --git a/src/static/mediaelement/mediaelement-and-player.js b/src/static/mediaelement/mediaelement-and-player.js new file mode 100755 index 0000000..6a44276 --- /dev/null +++ b/src/static/mediaelement/mediaelement-and-player.js @@ -0,0 +1,5045 @@ +/*! +* MediaElement.js +* HTML5 <video> and <audio> shim and player +* http://mediaelementjs.com/ +* +* Creates a JavaScript object that mimics HTML5 MediaElement API +* for browsers that don't understand HTML5 or can't play the provided codec +* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3 +* +* Copyright 2010-2013, John Dyer (http://j.hn) +* License: MIT +* +*/ +// Namespace +var mejs = mejs || {}; + +// version number +mejs.version = '2.12.0'; + +// player number (for missing, same id attr) +mejs.meIndex = 0; + +// media types accepted by plugins +mejs.plugins = { + silverlight: [ + {version: [3,0], types: ['video/mp4','video/m4v','video/mov','video/wmv','audio/wma','audio/m4a','audio/mp3','audio/wav','audio/mpeg']} + ], + flash: [ + {version: [9,0,124], types: ['video/mp4','video/m4v','video/mov','video/flv','video/rtmp','video/x-flv','audio/flv','audio/x-flv','audio/mp3','audio/m4a','audio/mpeg', 'video/youtube', 'video/x-youtube']} + //,{version: [12,0], types: ['video/webm']} // for future reference (hopefully!) + ], + youtube: [ + {version: null, types: ['video/youtube', 'video/x-youtube', 'audio/youtube', 'audio/x-youtube']} + ], + vimeo: [ + {version: null, types: ['video/vimeo', 'video/x-vimeo']} + ] +}; + +/* +Utility methods +*/ +mejs.Utility = { + encodeUrl: function(url) { + return encodeURIComponent(url); //.replace(/\?/gi,'%3F').replace(/=/gi,'%3D').replace(/&/gi,'%26'); + }, + escapeHTML: function(s) { + return s.toString().split('&').join('&amp;').split('<').join('&lt;').split('"').join('&quot;'); + }, + absolutizeUrl: function(url) { + var el = document.createElement('div'); + el.innerHTML = '<a href="' + this.escapeHTML(url) + '">x</a>'; + return el.firstChild.href; + }, + getScriptPath: function(scriptNames) { + var + i = 0, + j, + codePath = '', + testname = '', + slashPos, + filenamePos, + scriptUrl, + scriptPath, + scriptFilename, + scripts = document.getElementsByTagName('script'), + il = scripts.length, + jl = scriptNames.length; + + // go through all <script> tags + for (; i < il; i++) { + scriptUrl = scripts[i].src; + slashPos = scriptUrl.lastIndexOf('/'); + if (slashPos > -1) { + scriptFilename = scriptUrl.substring(slashPos + 1); + scriptPath = scriptUrl.substring(0, slashPos + 1); + } else { + scriptFilename = scriptUrl; + scriptPath = ''; + } + + // see if any <script> tags have a file name that matches the + for (j = 0; j < jl; j++) { + testname = scriptNames[j]; + filenamePos = scriptFilename.indexOf(testname); + if (filenamePos > -1) { + codePath = scriptPath; + break; + } + } + + // if we found a path, then break and return it + if (codePath !== '') { + break; + } + } + + // send the best path back + return codePath; + }, + secondsToTimeCode: function(time, forceHours, showFrameCount, fps) { + //add framecount + if (typeof showFrameCount == 'undefined') { + showFrameCount=false; + } else if(typeof fps == 'undefined') { + fps = 25; + } + + var hours = Math.floor(time / 3600) % 24, + minutes = Math.floor(time / 60) % 60, + seconds = Math.floor(time % 60), + frames = Math.floor(((time % 1)*fps).toFixed(3)), + result = + ( (forceHours || hours > 0) ? (hours < 10 ? '0' + hours : hours) + ':' : '') + + (minutes < 10 ? '0' + minutes : minutes) + ':' + + (seconds < 10 ? '0' + seconds : seconds) + + ((showFrameCount) ? ':' + (frames < 10 ? '0' + frames : frames) : ''); + + return result; + }, + + timeCodeToSeconds: function(hh_mm_ss_ff, forceHours, showFrameCount, fps){ + if (typeof showFrameCount == 'undefined') { + showFrameCount=false; + } else if(typeof fps == 'undefined') { + fps = 25; + } + + var tc_array = hh_mm_ss_ff.split(":"), + tc_hh = parseInt(tc_array[0], 10), + tc_mm = parseInt(tc_array[1], 10), + tc_ss = parseInt(tc_array[2], 10), + tc_ff = 0, + tc_in_seconds = 0; + + if (showFrameCount) { + tc_ff = parseInt(tc_array[3])/fps; + } + + tc_in_seconds = ( tc_hh * 3600 ) + ( tc_mm * 60 ) + tc_ss + tc_ff; + + return tc_in_seconds; + }, + + + convertSMPTEtoSeconds: function (SMPTE) { + if (typeof SMPTE != 'string') + return false; + + SMPTE = SMPTE.replace(',', '.'); + + var secs = 0, + decimalLen = (SMPTE.indexOf('.') != -1) ? SMPTE.split('.')[1].length : 0, + multiplier = 1; + + SMPTE = SMPTE.split(':').reverse(); + + for (var i = 0; i < SMPTE.length; i++) { + multiplier = 1; + if (i > 0) { + multiplier = Math.pow(60, i); + } + secs += Number(SMPTE[i]) * multiplier; + } + return Number(secs.toFixed(decimalLen)); + }, + + /* borrowed from SWFObject: http://code.google.com/p/swfobject/source/browse/trunk/swfobject/src/swfobject.js#474 */ + removeSwf: function(id) { + var obj = document.getElementById(id); + if (obj && /object|embed/i.test(obj.nodeName)) { + if (mejs.MediaFeatures.isIE) { + obj.style.display = "none"; + (function(){ + if (obj.readyState == 4) { + mejs.Utility.removeObjectInIE(id); + } else { + setTimeout(arguments.callee, 10); + } + })(); + } else { + obj.parentNode.removeChild(obj); + } + } + }, + removeObjectInIE: function(id) { + var obj = document.getElementById(id); + if (obj) { + for (var i in obj) { + if (typeof obj[i] == "function") { + obj[i] = null; + } + } + obj.parentNode.removeChild(obj); + } + } +}; + + +// Core detector, plugins are added below +mejs.PluginDetector = { + + // main public function to test a plug version number PluginDetector.hasPluginVersion('flash',[9,0,125]); + hasPluginVersion: function(plugin, v) { + var pv = this.plugins[plugin]; + v[1] = v[1] || 0; + v[2] = v[2] || 0; + return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false; + }, + + // cached values + nav: window.navigator, + ua: window.navigator.userAgent.toLowerCase(), + + // stored version numbers + plugins: [], + + // runs detectPlugin() and stores the version number + addPlugin: function(p, pluginName, mimeType, activeX, axDetect) { + this.plugins[p] = this.detectPlugin(pluginName, mimeType, activeX, axDetect); + }, + + // get the version number from the mimetype (all but IE) or ActiveX (IE) + detectPlugin: function(pluginName, mimeType, activeX, axDetect) { + + var version = [0,0,0], + description, + i, + ax; + + // Firefox, Webkit, Opera + if (typeof(this.nav.plugins) != 'undefined' && typeof this.nav.plugins[pluginName] == 'object') { + description = this.nav.plugins[pluginName].description; + if (description && !(typeof this.nav.mimeTypes != 'undefined' && this.nav.mimeTypes[mimeType] && !this.nav.mimeTypes[mimeType].enabledPlugin)) { + version = description.replace(pluginName, '').replace(/^\s+/,'').replace(/\sr/gi,'.').split('.'); + for (i=0; i<version.length; i++) { + version[i] = parseInt(version[i].match(/\d+/), 10); + } + } + // Internet Explorer / ActiveX + } else if (typeof(window.ActiveXObject) != 'undefined') { + try { + ax = new ActiveXObject(activeX); + if (ax) { + version = axDetect(ax); + } + } + catch (e) { } + } + return version; + } +}; + +// Add Flash detection +mejs.PluginDetector.addPlugin('flash','Shockwave Flash','application/x-shockwave-flash','ShockwaveFlash.ShockwaveFlash', function(ax) { + // adapted from SWFObject + var version = [], + d = ax.GetVariable("$version"); + if (d) { + d = d.split(" ")[1].split(","); + version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; + } + return version; +}); + +// Add Silverlight detection +mejs.PluginDetector.addPlugin('silverlight','Silverlight Plug-In','application/x-silverlight-2','AgControl.AgControl', function (ax) { + // Silverlight cannot report its version number to IE + // but it does have a isVersionSupported function, so we have to loop through it to get a version number. + // adapted from http://www.silverlightversion.com/ + var v = [0,0,0,0], + loopMatch = function(ax, v, i, n) { + while(ax.isVersionSupported(v[0]+ "."+ v[1] + "." + v[2] + "." + v[3])){ + v[i]+=n; + } + v[i] -= n; + }; + loopMatch(ax, v, 0, 1); + loopMatch(ax, v, 1, 1); + loopMatch(ax, v, 2, 10000); // the third place in the version number is usually 5 digits (4.0.xxxxx) + loopMatch(ax, v, 2, 1000); + loopMatch(ax, v, 2, 100); + loopMatch(ax, v, 2, 10); + loopMatch(ax, v, 2, 1); + loopMatch(ax, v, 3, 1); + + return v; +}); +// add adobe acrobat +/* +PluginDetector.addPlugin('acrobat','Adobe Acrobat','application/pdf','AcroPDF.PDF', function (ax) { + var version = [], + d = ax.GetVersions().split(',')[0].split('=')[1].split('.'); + + if (d) { + version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; + } + return version; +}); +*/ +// necessary detection (fixes for <IE9) +mejs.MediaFeatures = { + init: function() { + var + t = this, + d = document, + nav = mejs.PluginDetector.nav, + ua = mejs.PluginDetector.ua.toLowerCase(), + i, + v, + html5Elements = ['source','track','audio','video']; + + // detect browsers (only the ones that have some kind of quirk we need to work around) + t.isiPad = (ua.match(/ipad/i) !== null); + t.isiPhone = (ua.match(/iphone/i) !== null); + t.isiOS = t.isiPhone || t.isiPad; + t.isAndroid = (ua.match(/android/i) !== null); + t.isBustedAndroid = (ua.match(/android 2\.[12]/) !== null); + t.isBustedNativeHTTPS = (location.protocol === 'https:' && (ua.match(/android [12]\./) !== null || ua.match(/macintosh.* version.* safari/) !== null)); + t.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1); + t.isChrome = (ua.match(/chrome/gi) !== null); + t.isFirefox = (ua.match(/firefox/gi) !== null); + t.isWebkit = (ua.match(/webkit/gi) !== null); + t.isGecko = (ua.match(/gecko/gi) !== null) && !t.isWebkit; + t.isOpera = (ua.match(/opera/gi) !== null); + t.hasTouch = ('ontouchstart' in window); + + // borrowed from Modernizr + t.svg = !! document.createElementNS && + !! document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect; + + // create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection + for (i=0; i<html5Elements.length; i++) { + v = document.createElement(html5Elements[i]); + } + + t.supportsMediaTag = (typeof v.canPlayType !== 'undefined' || t.isBustedAndroid); + + // Fix for IE9 on Windows 7N / Windows 7KN (Media Player not installer) + try{ + v.canPlayType("video/mp4"); + }catch(e){ + t.supportsMediaTag = false; + } + + // detect native JavaScript fullscreen (Safari/Firefox only, Chrome still fails) + + // iOS + t.hasSemiNativeFullScreen = (typeof v.webkitEnterFullscreen !== 'undefined'); + + // Webkit/firefox + t.hasWebkitNativeFullScreen = (typeof v.webkitRequestFullScreen !== 'undefined'); + t.hasMozNativeFullScreen = (typeof v.mozRequestFullScreen !== 'undefined'); + + t.hasTrueNativeFullScreen = (t.hasWebkitNativeFullScreen || t.hasMozNativeFullScreen); + t.nativeFullScreenEnabled = t.hasTrueNativeFullScreen; + if (t.hasMozNativeFullScreen) { + t.nativeFullScreenEnabled = v.mozFullScreenEnabled; + } + + + if (this.isChrome) { + t.hasSemiNativeFullScreen = false; + } + + if (t.hasTrueNativeFullScreen) { + t.fullScreenEventName = (t.hasWebkitNativeFullScreen) ? 'webkitfullscreenchange' : 'mozfullscreenchange'; + + + t.isFullScreen = function() { + if (v.mozRequestFullScreen) { + return d.mozFullScreen; + } else if (v.webkitRequestFullScreen) { + return d.webkitIsFullScreen; + } + } + + t.requestFullScreen = function(el) { + + if (t.hasWebkitNativeFullScreen) { + el.webkitRequestFullScreen(); + } else if (t.hasMozNativeFullScreen) { + el.mozRequestFullScreen(); + } + } + + t.cancelFullScreen = function() { + if (t.hasWebkitNativeFullScreen) { + document.webkitCancelFullScreen(); + } else if (t.hasMozNativeFullScreen) { + document.mozCancelFullScreen(); + } + } + + } + + + // OS X 10.5 can't do this even if it says it can :( + if (t.hasSemiNativeFullScreen && ua.match(/mac os x 10_5/i)) { + t.hasNativeFullScreen = false; + t.hasSemiNativeFullScreen = false; + } + + } +}; +mejs.MediaFeatures.init(); + +/* +extension methods to <video> or <audio> object to bring it into parity with PluginMediaElement (see below) +*/ +mejs.HtmlMediaElement = { + pluginType: 'native', + isFullScreen: false, + + setCurrentTime: function (time) { + this.currentTime = time; + }, + + setMuted: function (muted) { + this.muted = muted; + }, + + setVolume: function (volume) { + this.volume = volume; + }, + + // for parity with the plugin versions + stop: function () { + this.pause(); + }, + + // This can be a url string + // or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}] + setSrc: function (url) { + + // Fix for IE9 which can't set .src when there are <source> elements. Awesome, right? + var + existingSources = this.getElementsByTagName('source'); + while (existingSources.length > 0){ + this.removeChild(existingSources[0]); + } + + if (typeof url == 'string') { + this.src = url; + } else { + var i, media; + + for (i=0; i<url.length; i++) { + media = url[i]; + if (this.canPlayType(media.type)) { + this.src = media.src; + break; + } + } + } + }, + + setVideoSize: function (width, height) { + this.width = width; + this.height = height; + } +}; + +/* +Mimics the <video/audio> element by calling Flash's External Interface or Silverlights [ScriptableMember] +*/ +mejs.PluginMediaElement = function (pluginid, pluginType, mediaUrl) { + this.id = pluginid; + this.pluginType = pluginType; + this.src = mediaUrl; + this.events = {}; + this.attributes = {}; +}; + +// JavaScript values and ExternalInterface methods that match HTML5 video properties methods +// http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/fl/video/FLVPlayback.html +// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html +mejs.PluginMediaElement.prototype = { + + // special + pluginElement: null, + pluginType: '', + isFullScreen: false, + + // not implemented :( + playbackRate: -1, + defaultPlaybackRate: -1, + seekable: [], + played: [], + + // HTML5 read-only properties + paused: true, + ended: false, + seeking: false, + duration: 0, + error: null, + tagName: '', + + // HTML5 get/set properties, but only set (updated by event handlers) + muted: false, + volume: 1, + currentTime: 0, + + // HTML5 methods + play: function () { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + this.pluginApi.playVideo(); + } else { + this.pluginApi.playMedia(); + } + this.paused = false; + } + }, + load: function () { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + } else { + this.pluginApi.loadMedia(); + } + + this.paused = false; + } + }, + pause: function () { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + this.pluginApi.pauseVideo(); + } else { + this.pluginApi.pauseMedia(); + } + + + this.paused = true; + } + }, + stop: function () { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + this.pluginApi.stopVideo(); + } else { + this.pluginApi.stopMedia(); + } + this.paused = true; + } + }, + canPlayType: function(type) { + var i, + j, + pluginInfo, + pluginVersions = mejs.plugins[this.pluginType]; + + for (i=0; i<pluginVersions.length; i++) { + pluginInfo = pluginVersions[i]; + + // test if user has the correct plugin version + if (mejs.PluginDetector.hasPluginVersion(this.pluginType, pluginInfo.version)) { + + // test for plugin playback types + for (j=0; j<pluginInfo.types.length; j++) { + // find plugin that can play the type + if (type == pluginInfo.types[j]) { + return 'probably'; + } + } + } + } + + return ''; + }, + + positionFullscreenButton: function(x,y,visibleAndAbove) { + if (this.pluginApi != null && this.pluginApi.positionFullscreenButton) { + this.pluginApi.positionFullscreenButton(Math.floor(x),Math.floor(y),visibleAndAbove); + } + }, + + hideFullscreenButton: function() { + if (this.pluginApi != null && this.pluginApi.hideFullscreenButton) { + this.pluginApi.hideFullscreenButton(); + } + }, + + + // custom methods since not all JavaScript implementations support get/set + + // This can be a url string + // or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}] + setSrc: function (url) { + if (typeof url == 'string') { + this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(url)); + this.src = mejs.Utility.absolutizeUrl(url); + } else { + var i, media; + + for (i=0; i<url.length; i++) { + media = url[i]; + if (this.canPlayType(media.type)) { + this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(media.src)); + this.src = mejs.Utility.absolutizeUrl(url); + break; + } + } + } + + }, + setCurrentTime: function (time) { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + this.pluginApi.seekTo(time); + } else { + this.pluginApi.setCurrentTime(time); + } + + + + this.currentTime = time; + } + }, + setVolume: function (volume) { + if (this.pluginApi != null) { + // same on YouTube and MEjs + if (this.pluginType == 'youtube') { + this.pluginApi.setVolume(volume * 100); + } else { + this.pluginApi.setVolume(volume); + } + this.volume = volume; + } + }, + setMuted: function (muted) { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + if (muted) { + this.pluginApi.mute(); + } else { + this.pluginApi.unMute(); + } + this.muted = muted; + this.dispatchEvent('volumechange'); + } else { + this.pluginApi.setMuted(muted); + } + this.muted = muted; + } + }, + + // additional non-HTML5 methods + setVideoSize: function (width, height) { + + //if (this.pluginType == 'flash' || this.pluginType == 'silverlight') { + if ( this.pluginElement.style) { + this.pluginElement.style.width = width + 'px'; + this.pluginElement.style.height = height + 'px'; + } + if (this.pluginApi != null && this.pluginApi.setVideoSize) { + this.pluginApi.setVideoSize(width, height); + } + //} + }, + + setFullscreen: function (fullscreen) { + if (this.pluginApi != null && this.pluginApi.setFullscreen) { + this.pluginApi.setFullscreen(fullscreen); + } + }, + + enterFullScreen: function() { + if (this.pluginApi != null && this.pluginApi.setFullscreen) { + this.setFullscreen(true); + } + + }, + + exitFullScreen: function() { + if (this.pluginApi != null && this.pluginApi.setFullscreen) { + this.setFullscreen(false); + } + }, + + // start: fake events + addEventListener: function (eventName, callback, bubble) { + this.events[eventName] = this.events[eventName] || []; + this.events[eventName].push(callback); + }, + removeEventListener: function (eventName, callback) { + if (!eventName) { this.events = {}; return true; } + var callbacks = this.events[eventName]; + if (!callbacks) return true; + if (!callback) { this.events[eventName] = []; return true; } + for (i = 0; i < callbacks.length; i++) { + if (callbacks[i] === callback) { + this.events[eventName].splice(i, 1); + return true; + } + } + return false; + }, + dispatchEvent: function (eventName) { + var i, + args, + callbacks = this.events[eventName]; + + if (callbacks) { + args = Array.prototype.slice.call(arguments, 1); + for (i = 0; i < callbacks.length; i++) { + callbacks[i].apply(null, args); + } + } + }, + // end: fake events + + // fake DOM attribute methods + hasAttribute: function(name){ + return (name in this.attributes); + }, + removeAttribute: function(name){ + delete this.attributes[name]; + }, + getAttribute: function(name){ + if (this.hasAttribute(name)) { + return this.attributes[name]; + } + return ''; + }, + setAttribute: function(name, value){ + this.attributes[name] = value; + }, + + remove: function() { + mejs.Utility.removeSwf(this.pluginElement.id); + mejs.MediaPluginBridge.unregisterPluginElement(this.pluginElement.id); + } +}; + +// Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties +mejs.MediaPluginBridge = { + + pluginMediaElements:{}, + htmlMediaElements:{}, + + registerPluginElement: function (id, pluginMediaElement, htmlMediaElement) { + this.pluginMediaElements[id] = pluginMediaElement; + this.htmlMediaElements[id] = htmlMediaElement; + }, + + unregisterPluginElement: function (id) { + delete this.pluginMediaElements[id]; + delete this.htmlMediaElements[id]; + }, + + // when Flash/Silverlight is ready, it calls out to this method + initPlugin: function (id) { + + var pluginMediaElement = this.pluginMediaElements[id], + htmlMediaElement = this.htmlMediaElements[id]; + + if (pluginMediaElement) { + // find the javascript bridge + switch (pluginMediaElement.pluginType) { + case "flash": + pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id); + break; + case "silverlight": + pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id); + pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS; + break; + } + + if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) { + pluginMediaElement.success(pluginMediaElement, htmlMediaElement); + } + } + }, + + // receives events from Flash/Silverlight and sends them out as HTML5 media events + // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html + fireEvent: function (id, eventName, values) { + + var + e, + i, + bufferedTime, + pluginMediaElement = this.pluginMediaElements[id]; + + // fake event object to mimic real HTML media event. + e = { + type: eventName, + target: pluginMediaElement + }; + + // attach all values to element and event object + for (i in values) { + pluginMediaElement[i] = values[i]; + e[i] = values[i]; + } + + // fake the newer W3C buffered TimeRange (loaded and total have been removed) + bufferedTime = values.bufferedTime || 0; + + e.target.buffered = e.buffered = { + start: function(index) { + return 0; + }, + end: function (index) { + return bufferedTime; + }, + length: 1 + }; + + pluginMediaElement.dispatchEvent(e.type, e); + } +}; + +/* +Default options +*/ +mejs.MediaElementDefaults = { + // allows testing on HTML5, flash, silverlight + // auto: attempts to detect what the browser can do + // auto_plugin: prefer plugins and then attempt native HTML5 + // native: forces HTML5 playback + // shim: disallows HTML5, will attempt either Flash or Silverlight + // none: forces fallback view + mode: 'auto', + // remove or reorder to change plugin priority and availability + plugins: ['flash','silverlight','youtube','vimeo'], + // shows debug errors on screen + enablePluginDebug: false, + // overrides the type specified, useful for dynamic instantiation + type: '', + // path to Flash and Silverlight plugins + pluginPath: mejs.Utility.getScriptPath(['mediaelement.js','mediaelement.min.js','mediaelement-and-player.js','mediaelement-and-player.min.js']), + // name of flash file + flashName: 'flashmediaelement.swf', + // streamer for RTMP streaming + flashStreamer: '', + // turns on the smoothing filter in Flash + enablePluginSmoothing: false, + // enabled pseudo-streaming (seek) on .mp4 files + enablePseudoStreaming: false, + // start query parameter sent to server for pseudo-streaming + pseudoStreamingStartQueryParam: 'start', + // name of silverlight file + silverlightName: 'silverlightmediaelement.xap', + // default if the <video width> is not specified + defaultVideoWidth: 480, + // default if the <video height> is not specified + defaultVideoHeight: 270, + // overrides <video width> + pluginWidth: -1, + // overrides <video height> + pluginHeight: -1, + // additional plugin variables in 'key=value' form + pluginVars: [], + // rate in milliseconds for Flash and Silverlight to fire the timeupdate event + // larger number is less accurate, but less strain on plugin->JavaScript bridge + timerRate: 250, + // initial volume for player + startVolume: 0.8, + success: function () { }, + error: function () { } +}; + +/* +Determines if a browser supports the <video> or <audio> element +and returns either the native element or a Flash/Silverlight version that +mimics HTML5 MediaElement +*/ +mejs.MediaElement = function (el, o) { + return mejs.HtmlMediaElementShim.create(el,o); +}; + +mejs.HtmlMediaElementShim = { + + create: function(el, o) { + var + options = mejs.MediaElementDefaults, + htmlMediaElement = (typeof(el) == 'string') ? document.getElementById(el) : el, + tagName = htmlMediaElement.tagName.toLowerCase(), + isMediaTag = (tagName === 'audio' || tagName === 'video'), + src = (isMediaTag) ? htmlMediaElement.getAttribute('src') : htmlMediaElement.getAttribute('href'), + poster = htmlMediaElement.getAttribute('poster'), + autoplay = htmlMediaElement.getAttribute('autoplay'), + preload = htmlMediaElement.getAttribute('preload'), + controls = htmlMediaElement.getAttribute('controls'), + playback, + prop; + + // extend options + for (prop in o) { + options[prop] = o[prop]; + } + + // clean up attributes + src = (typeof src == 'undefined' || src === null || src == '') ? null : src; + poster = (typeof poster == 'undefined' || poster === null) ? '' : poster; + preload = (typeof preload == 'undefined' || preload === null || preload === 'false') ? 'none' : preload; + autoplay = !(typeof autoplay == 'undefined' || autoplay === null || autoplay === 'false'); + controls = !(typeof controls == 'undefined' || controls === null || controls === 'false'); + + // test for HTML5 and plugin capabilities + playback = this.determinePlayback(htmlMediaElement, options, mejs.MediaFeatures.supportsMediaTag, isMediaTag, src); + playback.url = (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : ''; + + if (playback.method == 'native') { + // second fix for android + if (mejs.MediaFeatures.isBustedAndroid) { + htmlMediaElement.src = playback.url; + htmlMediaElement.addEventListener('click', function() { + htmlMediaElement.play(); + }, false); + } + + // add methods to native HTMLMediaElement + return this.updateNative(playback, options, autoplay, preload); + } else if (playback.method !== '') { + // create plugin to mimic HTMLMediaElement + + return this.createPlugin( playback, options, poster, autoplay, preload, controls); + } else { + // boo, no HTML5, no Flash, no Silverlight. + this.createErrorMessage( playback, options, poster ); + + return this; + } + }, + + determinePlayback: function(htmlMediaElement, options, supportsMediaTag, isMediaTag, src) { + var + mediaFiles = [], + i, + j, + k, + l, + n, + type, + result = { method: '', url: '', htmlMediaElement: htmlMediaElement, isVideo: (htmlMediaElement.tagName.toLowerCase() != 'audio')}, + pluginName, + pluginVersions, + pluginInfo, + dummy, + media; + + // STEP 1: Get URL and type from <video src> or <source src> + + // supplied type overrides <video type> and <source type> + if (typeof options.type != 'undefined' && options.type !== '') { + + // accept either string or array of types + if (typeof options.type == 'string') { + mediaFiles.push({type:options.type, url:src}); + } else { + + for (i=0; i<options.type.length; i++) { + mediaFiles.push({type:options.type[i], url:src}); + } + } + + // test for src attribute first + } else if (src !== null) { + type = this.formatType(src, htmlMediaElement.getAttribute('type')); + mediaFiles.push({type:type, url:src}); + + // then test for <source> elements + } else { + // test <source> types to see if they are usable + for (i = 0; i < htmlMediaElement.childNodes.length; i++) { + n = htmlMediaElement.childNodes[i]; + if (n.nodeType == 1 && n.tagName.toLowerCase() == 'source') { + src = n.getAttribute('src'); + type = this.formatType(src, n.getAttribute('type')); + media = n.getAttribute('media'); + + if (!media || !window.matchMedia || (window.matchMedia && window.matchMedia(media).matches)) { + mediaFiles.push({type:type, url:src}); + } + } + } + } + + // in the case of dynamicly created players + // check for audio types + if (!isMediaTag && mediaFiles.length > 0 && mediaFiles[0].url !== null && this.getTypeFromFile(mediaFiles[0].url).indexOf('audio') > -1) { + result.isVideo = false; + } + + + // STEP 2: Test for playback method + + // special case for Android which sadly doesn't implement the canPlayType function (always returns '') + if (mejs.MediaFeatures.isBustedAndroid) { + htmlMediaElement.canPlayType = function(type) { + return (type.match(/video\/(mp4|m4v)/gi) !== null) ? 'maybe' : ''; + }; + } + + + // test for native playback first + if (supportsMediaTag && (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'native') && !(mejs.MediaFeatures.isBustedNativeHTTPS)) { + + if (!isMediaTag) { + + // create a real HTML5 Media Element + dummy = document.createElement( result.isVideo ? 'video' : 'audio'); + htmlMediaElement.parentNode.insertBefore(dummy, htmlMediaElement); + htmlMediaElement.style.display = 'none'; + + // use this one from now on + result.htmlMediaElement = htmlMediaElement = dummy; + } + + for (i=0; i<mediaFiles.length; i++) { + // normal check + if (htmlMediaElement.canPlayType(mediaFiles[i].type).replace(/no/, '') !== '' + // special case for Mac/Safari 5.0.3 which answers '' to canPlayType('audio/mp3') but 'maybe' to canPlayType('audio/mpeg') + || htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/mp3/,'mpeg')).replace(/no/, '') !== '') { + result.method = 'native'; + result.url = mediaFiles[i].url; + break; + } + } + + if (result.method === 'native') { + if (result.url !== null) { + htmlMediaElement.src = result.url; + } + + // if `auto_plugin` mode, then cache the native result but try plugins. + if (options.mode !== 'auto_plugin') { + return result; + } + } + } + + // if native playback didn't work, then test plugins + if (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'shim') { + for (i=0; i<mediaFiles.length; i++) { + type = mediaFiles[i].type; + + // test all plugins in order of preference [silverlight, flash] + for (j=0; j<options.plugins.length; j++) { + + pluginName = options.plugins[j]; + + // test version of plugin (for future features) + pluginVersions = mejs.plugins[pluginName]; + + for (k=0; k<pluginVersions.length; k++) { + pluginInfo = pluginVersions[k]; + + // test if user has the correct plugin version + + // for youtube/vimeo + if (pluginInfo.version == null || + + mejs.PluginDetector.hasPluginVersion(pluginName, pluginInfo.version)) { + + // test for plugin playback types + for (l=0; l<pluginInfo.types.length; l++) { + // find plugin that can play the type + if (type == pluginInfo.types[l]) { + result.method = pluginName; + result.url = mediaFiles[i].url; + return result; + } + } + } + } + } + } + } + + // at this point, being in 'auto_plugin' mode implies that we tried plugins but failed. + // if we have native support then return that. + if (options.mode === 'auto_plugin' && result.method === 'native') { + return result; + } + + // what if there's nothing to play? just grab the first available + if (result.method === '' && mediaFiles.length > 0) { + result.url = mediaFiles[0].url; + } + + return result; + }, + + formatType: function(url, type) { + var ext; + + // if no type is supplied, fake it with the extension + if (url && !type) { + return this.getTypeFromFile(url); + } else { + // only return the mime part of the type in case the attribute contains the codec + // see http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#the-source-element + // `video/mp4; codecs="avc1.42E01E, mp4a.40.2"` becomes `video/mp4` + + if (type && ~type.indexOf(';')) { + return type.substr(0, type.indexOf(';')); + } else { + return type; + } + } + }, + + getTypeFromFile: function(url) { + url = url.split('?')[0]; + var ext = url.substring(url.lastIndexOf('.') + 1).toLowerCase(); + return (/(mp4|m4v|ogg|ogv|webm|webmv|flv|wmv|mpeg|mov)/gi.test(ext) ? 'video' : 'audio') + '/' + this.getTypeFromExtension(ext); + }, + + getTypeFromExtension: function(ext) { + + switch (ext) { + case 'mp4': + case 'm4v': + return 'mp4'; + case 'webm': + case 'webma': + case 'webmv': + return 'webm'; + case 'ogg': + case 'oga': + case 'ogv': + return 'ogg'; + default: + return ext; + } + }, + + createErrorMessage: function(playback, options, poster) { + var + htmlMediaElement = playback.htmlMediaElement, + errorContainer = document.createElement('div'); + + errorContainer.className = 'me-cannotplay'; + + try { + errorContainer.style.width = htmlMediaElement.width + 'px'; + errorContainer.style.height = htmlMediaElement.height + 'px'; + } catch (e) {} + + if (options.customError) { + errorContainer.innerHTML = options.customError; + } else { + errorContainer.innerHTML = (poster !== '') ? + '<a href="' + playback.url + '"><img src="' + poster + '" width="100%" height="100%" /></a>' : + '<a href="' + playback.url + '"><span>' + mejs.i18n.t('Download File') + '</span></a>'; + } + + htmlMediaElement.parentNode.insertBefore(errorContainer, htmlMediaElement); + htmlMediaElement.style.display = 'none'; + + options.error(htmlMediaElement); + }, + + createPlugin:function(playback, options, poster, autoplay, preload, controls) { + var + htmlMediaElement = playback.htmlMediaElement, + width = 1, + height = 1, + pluginid = 'me_' + playback.method + '_' + (mejs.meIndex++), + pluginMediaElement = new mejs.PluginMediaElement(pluginid, playback.method, playback.url), + container = document.createElement('div'), + specialIEContainer, + node, + initVars; + + // copy tagName from html media element + pluginMediaElement.tagName = htmlMediaElement.tagName + + // copy attributes from html media element to plugin media element + for (var i = 0; i < htmlMediaElement.attributes.length; i++) { + var attribute = htmlMediaElement.attributes[i]; + if (attribute.specified == true) { + pluginMediaElement.setAttribute(attribute.name, attribute.value); + } + } + + // check for placement inside a <p> tag (sometimes WYSIWYG editors do this) + node = htmlMediaElement.parentNode; + while (node !== null && node.tagName.toLowerCase() != 'body') { + if (node.parentNode.tagName.toLowerCase() == 'p') { + node.parentNode.parentNode.insertBefore(node, node.parentNode); + break; + } + node = node.parentNode; + } + + if (playback.isVideo) { + width = (options.pluginWidth > 0) ? options.pluginWidth : (options.videoWidth > 0) ? options.videoWidth : (htmlMediaElement.getAttribute('width') !== null) ? htmlMediaElement.getAttribute('width') : options.defaultVideoWidth; + height = (options.pluginHeight > 0) ? options.pluginHeight : (options.videoHeight > 0) ? options.videoHeight : (htmlMediaElement.getAttribute('height') !== null) ? htmlMediaElement.getAttribute('height') : options.defaultVideoHeight; + + // in case of '%' make sure it's encoded + width = mejs.Utility.encodeUrl(width); + height = mejs.Utility.encodeUrl(height); + + } else { + if (options.enablePluginDebug) { + width = 320; + height = 240; + } + } + + // register plugin + pluginMediaElement.success = options.success; + mejs.MediaPluginBridge.registerPluginElement(pluginid, pluginMediaElement, htmlMediaElement); + + // add container (must be added to DOM before inserting HTML for IE) + container.className = 'me-plugin'; + container.id = pluginid + '_container'; + + if (playback.isVideo) { + htmlMediaElement.parentNode.insertBefore(container, htmlMediaElement); + } else { + document.body.insertBefore(container, document.body.childNodes[0]); + } + + // flash/silverlight vars + initVars = [ + 'id=' + pluginid, + 'isvideo=' + ((playback.isVideo) ? "true" : "false"), + 'autoplay=' + ((autoplay) ? "true" : "false"), + 'preload=' + preload, + 'width=' + width, + 'startvolume=' + options.startVolume, + 'timerrate=' + options.timerRate, + 'flashstreamer=' + options.flashStreamer, + 'height=' + height, + 'pseudostreamstart=' + options.pseudoStreamingStartQueryParam]; + + if (playback.url !== null) { + if (playback.method == 'flash') { + initVars.push('file=' + mejs.Utility.encodeUrl(playback.url)); + } else { + initVars.push('file=' + playback.url); + } + } + if (options.enablePluginDebug) { + initVars.push('debug=true'); + } + if (options.enablePluginSmoothing) { + initVars.push('smoothing=true'); + } + if (options.enablePseudoStreaming) { + initVars.push('pseudostreaming=true'); + } + if (controls) { + initVars.push('controls=true'); // shows controls in the plugin if desired + } + if (options.pluginVars) { + initVars = initVars.concat(options.pluginVars); + } + + switch (playback.method) { + case 'silverlight': + container.innerHTML = +'<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="' + pluginid + '" name="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' + +'<param name="initParams" value="' + initVars.join(',') + '" />' + +'<param name="windowless" value="true" />' + +'<param name="background" value="black" />' + +'<param name="minRuntimeVersion" value="3.0.0.0" />' + +'<param name="autoUpgrade" value="true" />' + +'<param name="source" value="' + options.pluginPath + options.silverlightName + '" />' + +'</object>'; + break; + + case 'flash': + + if (mejs.MediaFeatures.isIE) { + specialIEContainer = document.createElement('div'); + container.appendChild(specialIEContainer); + specialIEContainer.outerHTML = +'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' + +'id="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' + +'<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' + +'<param name="flashvars" value="' + initVars.join('&amp;') + '" />' + +'<param name="quality" value="high" />' + +'<param name="bgcolor" value="#000000" />' + +'<param name="wmode" value="transparent" />' + +'<param name="allowScriptAccess" value="always" />' + +'<param name="allowFullScreen" value="true" />' + +'</object>'; + + } else { + + container.innerHTML = +'<embed id="' + pluginid + '" name="' + pluginid + '" ' + +'play="true" ' + +'loop="false" ' + +'quality="high" ' + +'bgcolor="#000000" ' + +'wmode="transparent" ' + +'allowScriptAccess="always" ' + +'allowFullScreen="true" ' + +'type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" ' + +'src="' + options.pluginPath + options.flashName + '" ' + +'flashvars="' + initVars.join('&') + '" ' + +'width="' + width + '" ' + +'height="' + height + '" ' + +'class="mejs-shim"></embed>'; + } + break; + + case 'youtube': + + + var + videoId = playback.url.substr(playback.url.lastIndexOf('=')+1); + youtubeSettings = { + container: container, + containerId: container.id, + pluginMediaElement: pluginMediaElement, + pluginId: pluginid, + videoId: videoId, + height: height, + width: width + }; + + if (mejs.PluginDetector.hasPluginVersion('flash', [10,0,0]) ) { + mejs.YouTubeApi.createFlash(youtubeSettings); + } else { + mejs.YouTubeApi.enqueueIframe(youtubeSettings); + } + + break; + + // DEMO Code. Does NOT work. + case 'vimeo': + //console.log('vimeoid'); + + pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1); + + container.innerHTML ='<iframe src="http://player.vimeo.com/video/' + pluginMediaElement.vimeoid + '?portrait=0&byline=0&title=0" width="' + width +'" height="' + height +'" frameborder="0" class="mejs-shim"></iframe>'; + + /* + container.innerHTML = + '<object width="' + width + '" height="' + height + '" class="mejs-shim">' + + '<param name="allowfullscreen" value="true" />' + + '<param name="allowscriptaccess" value="always" />' + + '<param name="flashvars" value="api=1" />' + + '<param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + pluginMediaElement.vimeoid + '&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" />' + + '<embed src="//vimeo.com/moogaloop.swf?api=1&amp;clip_id=' + pluginMediaElement.vimeoid + '&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="' + width + '" height="' + height + '" class="mejs-shim"></embed>' + + '</object>'; + */ + + break; + } + // hide original element + htmlMediaElement.style.display = 'none'; + + // FYI: options.success will be fired by the MediaPluginBridge + + return pluginMediaElement; + }, + + updateNative: function(playback, options, autoplay, preload) { + + var htmlMediaElement = playback.htmlMediaElement, + m; + + + // add methods to video object to bring it into parity with Flash Object + for (m in mejs.HtmlMediaElement) { + htmlMediaElement[m] = mejs.HtmlMediaElement[m]; + } + + /* + Chrome now supports preload="none" + if (mejs.MediaFeatures.isChrome) { + + // special case to enforce preload attribute (Chrome doesn't respect this) + if (preload === 'none' && !autoplay) { + + // forces the browser to stop loading (note: fails in IE9) + htmlMediaElement.src = ''; + htmlMediaElement.load(); + htmlMediaElement.canceledPreload = true; + + htmlMediaElement.addEventListener('play',function() { + if (htmlMediaElement.canceledPreload) { + htmlMediaElement.src = playback.url; + htmlMediaElement.load(); + htmlMediaElement.play(); + htmlMediaElement.canceledPreload = false; + } + }, false); + // for some reason Chrome forgets how to autoplay sometimes. + } else if (autoplay) { + htmlMediaElement.load(); + htmlMediaElement.play(); + } + } + */ + + // fire success code + options.success(htmlMediaElement, htmlMediaElement); + + return htmlMediaElement; + } +}; + +/* + - test on IE (object vs. embed) + - determine when to use iframe (Firefox, Safari, Mobile) vs. Flash (Chrome, IE) + - fullscreen? +*/ + +// YouTube Flash and Iframe API +mejs.YouTubeApi = { + isIframeStarted: false, + isIframeLoaded: false, + loadIframeApi: function() { + if (!this.isIframeStarted) { + var tag = document.createElement('script'); + tag.src = "//www.youtube.com/player_api"; + var firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + this.isIframeStarted = true; + } + }, + iframeQueue: [], + enqueueIframe: function(yt) { + + if (this.isLoaded) { + this.createIframe(yt); + } else { + this.loadIframeApi(); + this.iframeQueue.push(yt); + } + }, + createIframe: function(settings) { + + var + pluginMediaElement = settings.pluginMediaElement, + player = new YT.Player(settings.containerId, { + height: settings.height, + width: settings.width, + videoId: settings.videoId, + playerVars: {controls:0}, + events: { + 'onReady': function() { + + // hook up iframe object to MEjs + settings.pluginMediaElement.pluginApi = player; + + // init mejs + mejs.MediaPluginBridge.initPlugin(settings.pluginId); + + // create timer + setInterval(function() { + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate'); + }, 250); + }, + 'onStateChange': function(e) { + + mejs.YouTubeApi.handleStateChange(e.data, player, pluginMediaElement); + + } + } + }); + }, + + createEvent: function (player, pluginMediaElement, eventName) { + var obj = { + type: eventName, + target: pluginMediaElement + }; + + if (player && player.getDuration) { + + // time + pluginMediaElement.currentTime = obj.currentTime = player.getCurrentTime(); + pluginMediaElement.duration = obj.duration = player.getDuration(); + + // state + obj.paused = pluginMediaElement.paused; + obj.ended = pluginMediaElement.ended; + + // sound + obj.muted = player.isMuted(); + obj.volume = player.getVolume() / 100; + + // progress + obj.bytesTotal = player.getVideoBytesTotal(); + obj.bufferedBytes = player.getVideoBytesLoaded(); + + // fake the W3C buffered TimeRange + var bufferedTime = obj.bufferedBytes / obj.bytesTotal * obj.duration; + + obj.target.buffered = obj.buffered = { + start: function(index) { + return 0; + }, + end: function (index) { + return bufferedTime; + }, + length: 1 + }; + + } + + // send event up the chain + pluginMediaElement.dispatchEvent(obj.type, obj); + }, + + iFrameReady: function() { + + this.isLoaded = true; + this.isIframeLoaded = true; + + while (this.iframeQueue.length > 0) { + var settings = this.iframeQueue.pop(); + this.createIframe(settings); + } + }, + + // FLASH! + flashPlayers: {}, + createFlash: function(settings) { + + this.flashPlayers[settings.pluginId] = settings; + + /* + settings.container.innerHTML = + '<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0" ' + + 'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' + + '<param name="allowScriptAccess" value="always">' + + '<param name="wmode" value="transparent">' + + '</object>'; + */ + + var specialIEContainer, + youtubeUrl = '//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0'; + + if (mejs.MediaFeatures.isIE) { + + specialIEContainer = document.createElement('div'); + settings.container.appendChild(specialIEContainer); + specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' + +'id="' + settings.pluginId + '" width="' + settings.width + '" height="' + settings.height + '" class="mejs-shim">' + + '<param name="movie" value="' + youtubeUrl + '" />' + + '<param name="wmode" value="transparent" />' + + '<param name="allowScriptAccess" value="always" />' + + '<param name="allowFullScreen" value="true" />' + +'</object>'; + } else { + settings.container.innerHTML = + '<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="' + youtubeUrl + '" ' + + 'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' + + '<param name="allowScriptAccess" value="always">' + + '<param name="wmode" value="transparent">' + + '</object>'; + } + + }, + + flashReady: function(id) { + var + settings = this.flashPlayers[id], + player = document.getElementById(id), + pluginMediaElement = settings.pluginMediaElement; + + // hook up and return to MediaELementPlayer.success + pluginMediaElement.pluginApi = + pluginMediaElement.pluginElement = player; + mejs.MediaPluginBridge.initPlugin(id); + + // load the youtube video + player.cueVideoById(settings.videoId); + + var callbackName = settings.containerId + '_callback'; + + window[callbackName] = function(e) { + mejs.YouTubeApi.handleStateChange(e, player, pluginMediaElement); + } + + player.addEventListener('onStateChange', callbackName); + + setInterval(function() { + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate'); + }, 250); + }, + + handleStateChange: function(youTubeState, player, pluginMediaElement) { + switch (youTubeState) { + case -1: // not started + pluginMediaElement.paused = true; + pluginMediaElement.ended = true; + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'loadedmetadata'); + //createYouTubeEvent(player, pluginMediaElement, 'loadeddata'); + break; + case 0: + pluginMediaElement.paused = false; + pluginMediaElement.ended = true; + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'ended'); + break; + case 1: + pluginMediaElement.paused = false; + pluginMediaElement.ended = false; + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'play'); + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'playing'); + break; + case 2: + pluginMediaElement.paused = true; + pluginMediaElement.ended = false; + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'pause'); + break; + case 3: // buffering + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'progress'); + break; + case 5: + // cued? + break; + + } + + } +} +// IFRAME +function onYouTubePlayerAPIReady() { + mejs.YouTubeApi.iFrameReady(); +} +// FLASH +function onYouTubePlayerReady(id) { + mejs.YouTubeApi.flashReady(id); +} + +window.mejs = mejs; +window.MediaElement = mejs.MediaElement; + +/*! + * Adds Internationalization and localization to objects. + * + * What is the concept beyond i18n? + * http://en.wikipedia.org/wiki/Internationalization_and_localization + * + * + * This file both i18n methods and locale which is used to translate + * strings into other languages. + * + * Default translations are not available, you have to add them + * through locale objects which are named exactly as the langcode + * they stand for. The default language is always english (en). + * + * + * Wrapper built to be able to attach the i18n object to + * other objects without changing more than one line. + * + * + * LICENSE: + * + * The i18n file uses methods from the Drupal project (drupal.js): + * - i18n.methods.t() (modified) + * - i18n.methods.checkPlain() (full copy) + * - i18n.methods.formatString() (full copy) + * + * The Drupal project is (like mediaelementjs) licensed under GPLv2. + * - http://drupal.org/licensing/faq/#q1 + * - https://github.com/johndyer/mediaelement + * - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * + * + * @author + * Tim Latz (latz.tim@gmail.com) + * + * @see + * me-i18n-locale.js + * + * @params + * - context - document, iframe .. + * - exports - CommonJS, window .. + * + */ +;(function(context, exports, undefined) { + "use strict"; + var i18n = { + "locale": { + "strings" : {} + }, + "methods" : {} + }; +// start i18n + + + /** + * Get the current browser's language + * + * @see: i18n.methods.t() + */ + i18n.locale.getLanguage = function () { + return i18n.locale || { + "language" : navigator.language + }; + }; + + /** + * Store the language the locale object was initialized with + */ + i18n.locale.INIT_LANGUAGE = i18n.locale.getLanguage(); + + + /** + * Encode special characters in a plain-text string for display as HTML. + */ + i18n.methods.checkPlain = function (str) { + var character, regex, + replace = { + '&': '&amp;', + '"': '&quot;', + '<': '&lt;', + '>': '&gt;' + }; + str = String(str); + for (character in replace) { + if (replace.hasOwnProperty(character)) { + regex = new RegExp(character, 'g'); + str = str.replace(regex, replace[character]); + } + } + return str; + }; + + /** + * Replace placeholders with sanitized values in a string. + * + * @param str + * A string with placeholders. + * @param args + * An object of replacements pairs to make. Incidences of any key in this + * array are replaced with the corresponding value. Based on the first + * character of the key, the value is escaped and/or themed: + * - !variable: inserted as is + * - @variable: escape plain text to HTML (i18n.methods.checkPlain) + * - %variable: escape text and theme as a placeholder for user-submitted + * content (checkPlain + <em class="placeholder" > ) + * + * @see i18n.methods.t() + */ + i18n.methods.formatString = function(str, args) { + // Transform arguments before inserting them. + for (var key in args) { + switch (key.charAt(0)) { + // Escaped only. + case '@': + args[key] = i18n.methods.checkPlain(args[key]); + break; + // Pass-through. + case '!': + break; + // Escaped and placeholder. + case '%': + default: + args[key] = '<em class="placeholder">' + i18n.methods.checkPlain(args[key]) + '</em>'; + break; + } + str = str.replace(key, args[key]); + } + return str; + }; + + /** + * Translate strings to the page language or a given language. + * + * See the documentation of the server-side t() function for further details. + * + * @param str + * A string containing the English string to translate. + * @param args + * An object of replacements pairs to make after translation. Incidences + * of any key in this array are replaced with the corresponding value. + * See i18n.methods.formatString(). + * + * @param options + * - 'context' (defaults to the default context): The context the source string + * belongs to. + * + * @return + * The translated string. + */ + i18n.methods.t = function (str, args, options) { + + // Fetch the localized version of the string. + if (i18n.locale.strings && i18n.locale.strings[options.context] && i18n.locale.strings[options.context][str]) { + str = i18n.locale.strings[options.context][str]; + } + + if (args) { + str = i18n.methods.formatString(str, args); + } + return str; + }; + + + /** + * Wrapper for i18n.methods.t() + * + * @see i18n.methods.t() + * @throws InvalidArgumentException + */ + i18n.t = function(str, args, options) { + + if (typeof str === 'string' && str.length > 0) { + + // check every time due languge can change for + // different reasons (translation, lang switcher ..) + var lang = i18n.locale.getLanguage(); + + options = options || { + "context" : lang.language + }; + + return i18n.methods.t(str, args, options); + } + else { + throw { + "name" : 'InvalidArgumentException', + "message" : 'First argument is either not a string or empty.' + } + } + }; + +// end i18n + exports.i18n = i18n; +}(document, mejs)); + +;(function(exports, undefined) { + + "use strict"; + + if ( mejs.i18n.locale.language && mejs.i18n.locale.strings ) { + exports[mejs.i18n.locale.language] = mejs.i18n.locale.strings; + } + +}(mejs.i18n.locale.strings)); + +/*! + * This is a i18n.locale language object. + * + *<de> German translation by Tim Latz, latz.tim@gmail.com + * + * @author + * Tim Latz (latz.tim@gmail.com) + * + * @see + * me-i18n.js + * + * @params + * - exports - CommonJS, window .. + */ +;(function(exports, undefined) { + + "use strict"; + + exports.de = { + "Fullscreen" : "Vollbild", + "Go Fullscreen" : "Vollbild an", + "Turn off Fullscreen" : "Vollbild aus", + "Close" : "Schließen" + }; + +}(mejs.i18n.locale.strings)); +/*! + * This is a i18n.locale language object. + * + *<de> Traditional chinese translation by Tim Latz, latz.tim@gmail.com + * + * @author + * Tim Latz (latz.tim@gmail.com) + * + * @see + * me-i18n.js + * + * @params + * - exports - CommonJS, window .. + */ +;(function(exports, undefined) { + + "use strict"; + + exports.zh = { + "Fullscreen" : "全螢幕", + "Go Fullscreen" : "å…¨å±æ¨¡å¼", + "Turn off Fullscreen" : "退出全å±æ¨¡å¼", + "Close" : "關閉" + }; + +}(mejs.i18n.locale.strings)); + + +/*! + * MediaElementPlayer + * http://mediaelementjs.com/ + * + * Creates a controller bar for HTML5 <video> add <audio> tags + * using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper) + * + * Copyright 2010-2013, John Dyer (http://j.hn/) + * License: MIT + * + */ +if (typeof jQuery != 'undefined') { + mejs.$ = jQuery; +} else if (typeof ender != 'undefined') { + mejs.$ = ender; +} +(function ($) { + + // default player values + mejs.MepDefaults = { + // url to poster (to fix iOS 3.x) + poster: '', + // default if the <video width> is not specified + defaultVideoWidth: 480, + // default if the <video height> is not specified + defaultVideoHeight: 270, + // if set, overrides <video width> + videoWidth: -1, + // if set, overrides <video height> + videoHeight: -1, + // default if the user doesn't specify + defaultAudioWidth: 400, + // default if the user doesn't specify + defaultAudioHeight: 30, + + // default amount to move back when back key is pressed + defaultSeekBackwardInterval: function(media) { + return (media.duration * 0.05); + }, + // default amount to move forward when forward key is pressed + defaultSeekForwardInterval: function(media) { + return (media.duration * 0.05); + }, + + // width of audio player + audioWidth: -1, + // height of audio player + audioHeight: -1, + // initial volume when the player starts (overrided by user cookie) + startVolume: 0.8, + // useful for <audio> player loops + loop: false, + // rewind to beginning when media ends + autoRewind: true, + // resize to media dimensions + enableAutosize: true, + // forces the hour marker (##:00:00) + alwaysShowHours: false, + + // show framecount in timecode (##:00:00:00) + showTimecodeFrameCount: false, + // used when showTimecodeFrameCount is set to true + framesPerSecond: 25, + + // automatically calculate the width of the progress bar based on the sizes of other elements + autosizeProgress : true, + // Hide controls when playing and mouse is not over the video + alwaysShowControls: false, + // Display the video control + hideVideoControlsOnLoad: false, + // Enable click video element to toggle play/pause + clickToPlayPause: true, + // force iPad's native controls + iPadUseNativeControls: false, + // force iPhone's native controls + iPhoneUseNativeControls: false, + // force Android's native controls + AndroidUseNativeControls: false, + // features to show + features: ['playpause','current','progress','duration','tracks','volume','fullscreen'], + // only for dynamic + isVideo: true, + + // turns keyboard support on and off for this instance + enableKeyboard: true, + + // whenthis player starts, it will pause other players + pauseOtherPlayers: true, + + // array of keyboard actions such as play pause + keyActions: [ + { + keys: [ + 32, // SPACE + 179 // GOOGLE play/pause button + ], + action: function(player, media) { + if (media.paused || media.ended) { + media.play(); + } else { + media.pause(); + } + } + }, + { + keys: [38], // UP + action: function(player, media) { + var newVolume = Math.min(media.volume + 0.1, 1); + media.setVolume(newVolume); + } + }, + { + keys: [40], // DOWN + action: function(player, media) { + var newVolume = Math.max(media.volume - 0.1, 0); + media.setVolume(newVolume); + } + }, + { + keys: [ + 37, // LEFT + 227 // Google TV rewind + ], + action: function(player, media) { + if (!isNaN(media.duration) && media.duration > 0) { + if (player.isVideo) { + player.showControls(); + player.startControlsTimer(); + } + + // 5% + var newTime = Math.max(media.currentTime - player.options.defaultSeekBackwardInterval(media), 0); + media.setCurrentTime(newTime); + } + } + }, + { + keys: [ + 39, // RIGHT + 228 // Google TV forward + ], + action: function(player, media) { + if (!isNaN(media.duration) && media.duration > 0) { + if (player.isVideo) { + player.showControls(); + player.startControlsTimer(); + } + + // 5% + var newTime = Math.min(media.currentTime + player.options.defaultSeekForwardInterval(media), media.duration); + media.setCurrentTime(newTime); + } + } + }, + { + keys: [70], // f + action: function(player, media) { + if (typeof player.enterFullScreen != 'undefined') { + if (player.isFullScreen) { + player.exitFullScreen(); + } else { + player.enterFullScreen(); + } + } + } + } + ] + }; + + mejs.mepIndex = 0; + + mejs.players = {}; + + // wraps a MediaElement object in player controls + mejs.MediaElementPlayer = function(node, o) { + // enforce object, even without "new" (via John Resig) + if ( !(this instanceof mejs.MediaElementPlayer) ) { + return new mejs.MediaElementPlayer(node, o); + } + + var t = this; + + // these will be reset after the MediaElement.success fires + t.$media = t.$node = $(node); + t.node = t.media = t.$media[0]; + + // check for existing player + if (typeof t.node.player != 'undefined') { + return t.node.player; + } else { + // attach player to DOM node for reference + t.node.player = t; + } + + + // try to get options from data-mejsoptions + if (typeof o == 'undefined') { + o = t.$node.data('mejsoptions'); + } + + // extend default options + t.options = $.extend({},mejs.MepDefaults,o); + + // unique ID + t.id = 'mep_' + mejs.mepIndex++; + + // add to player array (for focus events) + mejs.players[t.id] = t; + + // start up + t.init(); + + return t; + }; + + // actual player + mejs.MediaElementPlayer.prototype = { + + hasFocus: false, + + controlsAreVisible: true, + + init: function() { + + var + t = this, + mf = mejs.MediaFeatures, + // options for MediaElement (shim) + meOptions = $.extend(true, {}, t.options, { + success: function(media, domNode) { t.meReady(media, domNode); }, + error: function(e) { t.handleError(e);} + }), + tagName = t.media.tagName.toLowerCase(); + + t.isDynamic = (tagName !== 'audio' && tagName !== 'video'); + + if (t.isDynamic) { + // get video from src or href? + t.isVideo = t.options.isVideo; + } else { + t.isVideo = (tagName !== 'audio' && t.options.isVideo); + } + + // use native controls in iPad, iPhone, and Android + if ((mf.isiPad && t.options.iPadUseNativeControls) || (mf.isiPhone && t.options.iPhoneUseNativeControls)) { + + // add controls and stop + t.$media.attr('controls', 'controls'); + + // attempt to fix iOS 3 bug + //t.$media.removeAttr('poster'); + // no Issue found on iOS3 -ttroxell + + // override Apple's autoplay override for iPads + if (mf.isiPad && t.media.getAttribute('autoplay') !== null) { + t.media.load(); + t.media.play(); + } + + } else if (mf.isAndroid && t.options.AndroidUseNativeControls) { + + // leave default player + + } else { + + // DESKTOP: use MediaElementPlayer controls + + // remove native controls + t.$media.removeAttr('controls'); + + // build container + t.container = + $('<div id="' + t.id + '" class="mejs-container ' + (mejs.MediaFeatures.svg ? 'svg' : 'no-svg') + '">'+ + '<div class="mejs-inner">'+ + '<div class="mejs-mediaelement"></div>'+ + '<div class="mejs-layers"></div>'+ + '<div class="mejs-controls"></div>'+ + '<div class="mejs-clear"></div>'+ + '</div>' + + '</div>') + .addClass(t.$media[0].className) + .insertBefore(t.$media); + + // add classes for user and content + t.container.addClass( + (mf.isAndroid ? 'mejs-android ' : '') + + (mf.isiOS ? 'mejs-ios ' : '') + + (mf.isiPad ? 'mejs-ipad ' : '') + + (mf.isiPhone ? 'mejs-iphone ' : '') + + (t.isVideo ? 'mejs-video ' : 'mejs-audio ') + ); + + + // move the <video/video> tag into the right spot + if (mf.isiOS) { + + // sadly, you can't move nodes in iOS, so we have to destroy and recreate it! + var $newMedia = t.$media.clone(); + + t.container.find('.mejs-mediaelement').append($newMedia); + + t.$media.remove(); + t.$node = t.$media = $newMedia; + t.node = t.media = $newMedia[0] + + } else { + + // normal way of moving it into place (doesn't work on iOS) + t.container.find('.mejs-mediaelement').append(t.$media); + } + + // find parts + t.controls = t.container.find('.mejs-controls'); + t.layers = t.container.find('.mejs-layers'); + + // determine the size + + /* size priority: + (1) videoWidth (forced), + (2) style="width;height;" + (3) width attribute, + (4) defaultVideoWidth (for unspecified cases) + */ + + var tagType = (t.isVideo ? 'video' : 'audio'), + capsTagName = tagType.substring(0,1).toUpperCase() + tagType.substring(1); + + + if (t.options[tagType + 'Width'] > 0 || t.options[tagType + 'Width'].toString().indexOf('%') > -1) { + t.width = t.options[tagType + 'Width']; + } else if (t.media.style.width !== '' && t.media.style.width !== null) { + t.width = t.media.style.width; + } else if (t.media.getAttribute('width') !== null) { + t.width = t.$media.attr('width'); + } else { + t.width = t.options['default' + capsTagName + 'Width']; + } + + if (t.options[tagType + 'Height'] > 0 || t.options[tagType + 'Height'].toString().indexOf('%') > -1) { + t.height = t.options[tagType + 'Height']; + } else if (t.media.style.height !== '' && t.media.style.height !== null) { + t.height = t.media.style.height; + } else if (t.$media[0].getAttribute('height') !== null) { + t.height = t.$media.attr('height'); + } else { + t.height = t.options['default' + capsTagName + 'Height']; + } + + // set the size, while we wait for the plugins to load below + t.setPlayerSize(t.width, t.height); + + // create MediaElementShim + meOptions.pluginWidth = t.width; + meOptions.pluginHeight = t.height; + } + + // create MediaElement shim + mejs.MediaElement(t.$media[0], meOptions); + + if (typeof(t.container) != 'undefined'){ + // controls are shown when loaded + t.container.trigger('controlsshown'); + } + }, + + showControls: function(doAnimation) { + var t = this; + + doAnimation = typeof doAnimation == 'undefined' || doAnimation; + + if (t.controlsAreVisible) + return; + + if (doAnimation) { + t.controls + .css('visibility','visible') + .stop(true, true).fadeIn(200, function() { + t.controlsAreVisible = true; + t.container.trigger('controlsshown'); + }); + + // any additional controls people might add and want to hide + t.container.find('.mejs-control') + .css('visibility','visible') + .stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;}); + + } else { + t.controls + .css('visibility','visible') + .css('display','block'); + + // any additional controls people might add and want to hide + t.container.find('.mejs-control') + .css('visibility','visible') + .css('display','block'); + + t.controlsAreVisible = true; + t.container.trigger('controlsshown'); + } + + t.setControlsSize(); + + }, + + hideControls: function(doAnimation) { + var t = this; + + doAnimation = typeof doAnimation == 'undefined' || doAnimation; + + if (!t.controlsAreVisible) + return; + + if (doAnimation) { + // fade out main controls + t.controls.stop(true, true).fadeOut(200, function() { + $(this) + .css('visibility','hidden') + .css('display','block'); + + t.controlsAreVisible = false; + t.container.trigger('controlshidden'); + }); + + // any additional controls people might add and want to hide + t.container.find('.mejs-control').stop(true, true).fadeOut(200, function() { + $(this) + .css('visibility','hidden') + .css('display','block'); + }); + } else { + + // hide main controls + t.controls + .css('visibility','hidden') + .css('display','block'); + + // hide others + t.container.find('.mejs-control') + .css('visibility','hidden') + .css('display','block'); + + t.controlsAreVisible = false; + t.container.trigger('controlshidden'); + } + }, + + controlsTimer: null, + + startControlsTimer: function(timeout) { + + var t = this; + + timeout = typeof timeout != 'undefined' ? timeout : 1500; + + t.killControlsTimer('start'); + + t.controlsTimer = setTimeout(function() { + //console.log('timer fired'); + t.hideControls(); + t.killControlsTimer('hide'); + }, timeout); + }, + + killControlsTimer: function(src) { + + var t = this; + + if (t.controlsTimer !== null) { + clearTimeout(t.controlsTimer); + delete t.controlsTimer; + t.controlsTimer = null; + } + }, + + controlsEnabled: true, + + disableControls: function() { + var t= this; + + t.killControlsTimer(); + t.hideControls(false); + this.controlsEnabled = false; + }, + + enableControls: function() { + var t= this; + + t.showControls(false); + + t.controlsEnabled = true; + }, + + + // Sets up all controls and events + meReady: function(media, domNode) { + + + var t = this, + mf = mejs.MediaFeatures, + autoplayAttr = domNode.getAttribute('autoplay'), + autoplay = !(typeof autoplayAttr == 'undefined' || autoplayAttr === null || autoplayAttr === 'false'), + featureIndex, + feature; + + // make sure it can't create itself again if a plugin reloads + if (t.created) { + return; + } else { + t.created = true; + } + + t.media = media; + t.domNode = domNode; + + if (!(mf.isAndroid && t.options.AndroidUseNativeControls) && !(mf.isiPad && t.options.iPadUseNativeControls) && !(mf.isiPhone && t.options.iPhoneUseNativeControls)) { + + // two built in features + t.buildposter(t, t.controls, t.layers, t.media); + t.buildkeyboard(t, t.controls, t.layers, t.media); + t.buildoverlays(t, t.controls, t.layers, t.media); + + // grab for use by features + t.findTracks(); + + // add user-defined features/controls + for (featureIndex in t.options.features) { + feature = t.options.features[featureIndex]; + if (t['build' + feature]) { + try { + t['build' + feature](t, t.controls, t.layers, t.media); + } catch (e) { + // TODO: report control error + //throw e; + //console.log('error building ' + feature); + //console.log(e); + } + } + } + + t.container.trigger('controlsready'); + + // reset all layers and controls + t.setPlayerSize(t.width, t.height); + t.setControlsSize(); + + + // controls fade + if (t.isVideo) { + + if (mejs.MediaFeatures.hasTouch) { + + // for touch devices (iOS, Android) + // show/hide without animation on touch + + t.$media.bind('touchstart', function() { + + + // toggle controls + if (t.controlsAreVisible) { + t.hideControls(false); + } else { + if (t.controlsEnabled) { + t.showControls(false); + } + } + }); + + } else { + + // create callback here since it needs access to current + // MediaElement object + mejs.MediaElementPlayer.prototype.clickToPlayPauseCallback = function() { + console.log('media clicked', t.media, t.media.paused); + + if (t.options.clickToPlayPause) { + if (t.media.paused) { + t.media.play(); + } else { + t.media.pause(); + } + } + }; + + // click to play/pause + t.media.addEventListener('click', t.clickToPlayPauseCallback); + + // show/hide controls + t.container + .bind('mouseenter mouseover', function () { + if (t.controlsEnabled) { + if (!t.options.alwaysShowControls) { + t.killControlsTimer('enter'); + t.showControls(); + t.startControlsTimer(2500); + } + } + }) + .bind('mousemove', function() { + if (t.controlsEnabled) { + if (!t.controlsAreVisible) { + t.showControls(); + } + //t.killControlsTimer('move'); + if (!t.options.alwaysShowControls) { + t.startControlsTimer(2500); + } + } + }) + .bind('mouseleave', function () { + if (t.controlsEnabled) { + if (!t.media.paused && !t.options.alwaysShowControls) { + t.startControlsTimer(1000); + } + } + }); + } + + if(t.options.hideVideoControlsOnLoad) { + t.hideControls(false); + } + + // check for autoplay + if (autoplay && !t.options.alwaysShowControls) { + t.hideControls(); + } + + // resizer + if (t.options.enableAutosize) { + t.media.addEventListener('loadedmetadata', function(e) { + // if the <video height> was not set and the options.videoHeight was not set + // then resize to the real dimensions + if (t.options.videoHeight <= 0 && t.domNode.getAttribute('height') === null && !isNaN(e.target.videoHeight)) { + t.setPlayerSize(e.target.videoWidth, e.target.videoHeight); + t.setControlsSize(); + t.media.setVideoSize(e.target.videoWidth, e.target.videoHeight); + } + }, false); + } + } + + // EVENTS + + // FOCUS: when a video starts playing, it takes focus from other players (possibily pausing them) + media.addEventListener('play', function() { + var playerIndex; + + // go through all other players + for (playerIndex in mejs.players) { + var p = mejs.players[playerIndex]; + if (p.id != t.id && t.options.pauseOtherPlayers && !p.paused && !p.ended) { + p.pause(); + } + p.hasFocus = false; + } + + t.hasFocus = true; + },false); + + + // ended for all + t.media.addEventListener('ended', function (e) { + if(t.options.autoRewind) { + try{ + t.media.setCurrentTime(0); + } catch (exp) { + + } + } + t.media.pause(); + + if (t.setProgressRail) { + t.setProgressRail(); + } + if (t.setCurrentRail) { + t.setCurrentRail(); + } + + if (t.options.loop) { + t.media.play(); + } else if (!t.options.alwaysShowControls && t.controlsEnabled) { + t.showControls(); + } + }, false); + + // resize on the first play + t.media.addEventListener('loadedmetadata', function(e) { + if (t.updateDuration) { + t.updateDuration(); + } + if (t.updateCurrent) { + t.updateCurrent(); + } + + if (!t.isFullScreen) { + t.setPlayerSize(t.width, t.height); + t.setControlsSize(); + } + }, false); + + + // webkit has trouble doing this without a delay + setTimeout(function () { + t.setPlayerSize(t.width, t.height); + t.setControlsSize(); + }, 50); + + // adjust controls whenever window sizes (used to be in fullscreen only) + t.globalBind('resize', function() { + + // don't resize for fullscreen mode + if ( !(t.isFullScreen || (mejs.MediaFeatures.hasTrueNativeFullScreen && document.webkitIsFullScreen)) ) { + t.setPlayerSize(t.width, t.height); + } + + // always adjust controls + t.setControlsSize(); + }); + + // TEMP: needs to be moved somewhere else + if (t.media.pluginType == 'youtube') { + t.container.find('.mejs-overlay-play').hide(); + } + } + + // force autoplay for HTML5 + if (autoplay && media.pluginType == 'native') { + media.load(); + media.play(); + } + + + if (t.options.success) { + + if (typeof t.options.success == 'string') { + window[t.options.success](t.media, t.domNode, t); + } else { + t.options.success(t.media, t.domNode, t); + } + } + }, + + handleError: function(e) { + var t = this; + + t.controls.hide(); + + // Tell user that the file cannot be played + if (t.options.error) { + t.options.error(e); + } + }, + + setPlayerSize: function(width,height) { + var t = this; + + if (typeof width != 'undefined') { + t.width = width; + } + + if (typeof height != 'undefined') { + t.height = height; + } + + // detect 100% mode - use currentStyle for IE since css() doesn't return percentages + if (t.height.toString().indexOf('%') > 0 || t.$node.css('max-width') === '100%' || (t.$node[0].currentStyle && t.$node[0].currentStyle.maxWidth === '100%')) { + + // do we have the native dimensions yet? + var + nativeWidth = t.isVideo ? ((t.media.videoWidth && t.media.videoWidth > 0) ? t.media.videoWidth : t.options.defaultVideoWidth) : t.options.defaultAudioWidth, + nativeHeight = t.isVideo ? ((t.media.videoHeight && t.media.videoHeight > 0) ? t.media.videoHeight : t.options.defaultVideoHeight) : t.options.defaultAudioHeight, + parentWidth = t.container.parent().closest(':visible').width(), + newHeight = t.isVideo || !t.options.autosizeProgress ? parseInt(parentWidth * nativeHeight/nativeWidth, 10) : nativeHeight; + + if (t.container.parent()[0].tagName.toLowerCase() === 'body') { // && t.container.siblings().count == 0) { + parentWidth = $(window).width(); + newHeight = $(window).height(); + } + + if ( newHeight != 0 && parentWidth != 0 ) { + // set outer container size + t.container + .width(parentWidth) + .height(newHeight); + + // set native <video> or <audio> and shims + t.$media.add(t.container.find('.mejs-shim')) + .width('100%') + .height('100%'); + + // if shim is ready, send the size to the embeded plugin + if (t.isVideo) { + if (t.media.setVideoSize) { + t.media.setVideoSize(parentWidth, newHeight); + } + } + + // set the layers + t.layers.children('.mejs-layer') + .width('100%') + .height('100%'); + } + + + } else { + + t.container + .width(t.width) + .height(t.height); + + t.layers.children('.mejs-layer') + .width(t.width) + .height(t.height); + + } + + // special case for big play button so it doesn't go over the controls area + var playLayer = t.layers.find('.mejs-overlay-play'), + playButton = playLayer.find('.mejs-overlay-button'); + + playLayer.height(t.container.height() - t.controls.height()); + playButton.css('margin-top', '-' + (playButton.height()/2 - t.controls.height()/2).toString() + 'px' ); + + }, + + setControlsSize: function() { + var t = this, + usedWidth = 0, + railWidth = 0, + rail = t.controls.find('.mejs-time-rail'), + total = t.controls.find('.mejs-time-total'), + current = t.controls.find('.mejs-time-current'), + loaded = t.controls.find('.mejs-time-loaded'), + others = rail.siblings(); + + + // allow the size to come from custom CSS + if (t.options && !t.options.autosizeProgress) { + // Also, frontends devs can be more flexible + // due the opportunity of absolute positioning. + railWidth = parseInt(rail.css('width')); + } + + // attempt to autosize + if (railWidth === 0 || !railWidth) { + + // find the size of all the other controls besides the rail + others.each(function() { + var $this = $(this); + if ($this.css('position') != 'absolute' && $this.is(':visible')) { + usedWidth += $(this).outerWidth(true); + } + }); + + // fit the rail into the remaining space + railWidth = t.controls.width() - usedWidth - (rail.outerWidth(true) - rail.width()); + } + + // outer area + rail.width(railWidth); + // dark space + total.width(railWidth - (total.outerWidth(true) - total.width())); + + if (t.setProgressRail) + t.setProgressRail(); + if (t.setCurrentRail) + t.setCurrentRail(); + }, + + + buildposter: function(player, controls, layers, media) { + var t = this, + poster = + $('<div class="mejs-poster mejs-layer">' + + '</div>') + .appendTo(layers), + posterUrl = player.$media.attr('poster'); + + // prioriy goes to option (this is useful if you need to support iOS 3.x (iOS completely fails with poster) + if (player.options.poster !== '') { + posterUrl = player.options.poster; + } + + // second, try the real poster + if (posterUrl !== '' && posterUrl != null) { + t.setPoster(posterUrl); + } else { + poster.hide(); + } + + media.addEventListener('play',function() { + poster.hide(); + }, false); + }, + + setPoster: function(url) { + var t = this, + posterDiv = t.container.find('.mejs-poster'), + posterImg = posterDiv.find('img'); + + if (posterImg.length == 0) { + posterImg = $('<img width="100%" height="100%" />').appendTo(posterDiv); + } + + posterImg.attr('src', url); + posterDiv.css({'background-image' : 'url(' + url + ')'}); + }, + + buildoverlays: function(player, controls, layers, media) { + var t = this; + if (!player.isVideo) + return; + + var + loading = + $('<div class="mejs-overlay mejs-layer">'+ + '<div class="mejs-overlay-loading"><span></span></div>'+ + '</div>') + .hide() // start out hidden + .appendTo(layers), + error = + $('<div class="mejs-overlay mejs-layer">'+ + '<div class="mejs-overlay-error"></div>'+ + '</div>') + .hide() // start out hidden + .appendTo(layers), + // this needs to come last so it's on top + bigPlay = + $('<div class="mejs-overlay mejs-layer mejs-overlay-play">'+ + '<div class="mejs-overlay-button"></div>'+ + '</div>') + .appendTo(layers) + .click(function() { + if (t.options.clickToPlayPause) { + if (media.paused) { + media.play(); + } else { + media.pause(); + } + } + }); + + /* + if (mejs.MediaFeatures.isiOS || mejs.MediaFeatures.isAndroid) { + bigPlay.remove(); + loading.remove(); + } + */ + + + // show/hide big play button + media.addEventListener('play',function() { + bigPlay.hide(); + loading.hide(); + controls.find('.mejs-time-buffering').hide(); + error.hide(); + }, false); + + media.addEventListener('playing', function() { + bigPlay.hide(); + loading.hide(); + controls.find('.mejs-time-buffering').hide(); + error.hide(); + }, false); + + media.addEventListener('seeking', function() { + loading.show(); + controls.find('.mejs-time-buffering').show(); + }, false); + + media.addEventListener('seeked', function() { + loading.hide(); + controls.find('.mejs-time-buffering').hide(); + }, false); + + media.addEventListener('pause',function() { + if (!mejs.MediaFeatures.isiPhone) { + bigPlay.show(); + } + }, false); + + media.addEventListener('waiting', function() { + loading.show(); + controls.find('.mejs-time-buffering').show(); + }, false); + + + // show/hide loading + media.addEventListener('loadeddata',function() { + // for some reason Chrome is firing this event + //if (mejs.MediaFeatures.isChrome && media.getAttribute && media.getAttribute('preload') === 'none') + // return; + + loading.show(); + controls.find('.mejs-time-buffering').show(); + }, false); + media.addEventListener('canplay',function() { + loading.hide(); + controls.find('.mejs-time-buffering').hide(); + }, false); + + // error handling + media.addEventListener('error',function() { + loading.hide(); + controls.find('.mejs-time-buffering').hide(); + error.show(); + error.find('mejs-overlay-error').html("Error loading this resource"); + }, false); + }, + + buildkeyboard: function(player, controls, layers, media) { + + var t = this; + + // listen for key presses + t.globalBind('keydown', function(e) { + + if (player.hasFocus && player.options.enableKeyboard) { + + // find a matching key + for (var i=0, il=player.options.keyActions.length; i<il; i++) { + var keyAction = player.options.keyActions[i]; + + for (var j=0, jl=keyAction.keys.length; j<jl; j++) { + if (e.keyCode == keyAction.keys[j]) { + e.preventDefault(); + keyAction.action(player, media, e.keyCode); + return false; + } + } + } + } + + return true; + }); + + // check if someone clicked outside a player region, then kill its focus + t.globalBind('click', function(event) { + if ($(event.target).closest('.mejs-container').length == 0) { + player.hasFocus = false; + } + }); + + }, + + findTracks: function() { + var t = this, + tracktags = t.$media.find('track'); + + // store for use by plugins + t.tracks = []; + tracktags.each(function(index, track) { + + track = $(track); + + t.tracks.push({ + srclang: (track.attr('srclang')) ? track.attr('srclang').toLowerCase() : '', + src: track.attr('src'), + kind: track.attr('kind'), + label: track.attr('label') || '', + entries: [], + isLoaded: false + }); + }); + }, + changeSkin: function(className) { + this.container[0].className = 'mejs-container ' + className; + this.setPlayerSize(this.width, this.height); + this.setControlsSize(); + }, + play: function() { + this.media.play(); + }, + pause: function() { + this.media.pause(); + }, + load: function() { + this.media.load(); + }, + setMuted: function(muted) { + this.media.setMuted(muted); + }, + setCurrentTime: function(time) { + this.media.setCurrentTime(time); + }, + getCurrentTime: function() { + return this.media.currentTime; + }, + setVolume: function(volume) { + this.media.setVolume(volume); + }, + getVolume: function() { + return this.media.volume; + }, + setSrc: function(src) { + this.media.setSrc(src); + }, + remove: function() { + var t = this, featureIndex, feature; + + // invoke features cleanup + for (featureIndex in t.options.features) { + feature = t.options.features[featureIndex]; + if (t['clean' + feature]) { + try { + t['clean' + feature](t); + } catch (e) { + // TODO: report control error + //throw e; + //console.log('error building ' + feature); + //console.log(e); + } + } + } + + if (t.media.pluginType === 'native') { + t.$media.prop('controls', true); + } else { + t.media.remove(); + } + + // grab video and put it back in place + if (!t.isDynamic) { + if (t.media.pluginType === 'native') { + // detach events from the video + // TODO: detach event listeners better than this; + // also detach ONLY the events attached by this plugin! + //t.$node.clone().insertBefore(t.container); + //t.$node.remove(); + } + /*else*/ t.$node.insertBefore(t.container) + } + + // Remove the player from the mejs.players object so that pauseOtherPlayers doesn't blow up when trying to pause a non existance flash api. + delete mejs.players[t.id]; + + t.container.remove(); + t.globalUnbind(); + delete t.node.player; + } + }; + + (function(){ + var rwindow = /^((after|before)print|(before)?unload|hashchange|message|o(ff|n)line|page(hide|show)|popstate|resize|storage)\b/; + + function splitEvents(events, id) { + // add player ID as an event namespace so it's easier to unbind them all later + var ret = {d: [], w: []}; + $.each((events || '').split(' '), function(k, v){ + var eventname = v + '.' + id; + if (eventname.indexOf('.') === 0) { + ret.d.push(eventname); + ret.w.push(eventname); + } + else { + ret[rwindow.test(v) ? 'w' : 'd'].push(eventname); + } + }); + ret.d = ret.d.join(' '); + ret.w = ret.w.join(' '); + return ret; + } + + mejs.MediaElementPlayer.prototype.globalBind = function(events, data, callback) { + var t = this; + events = splitEvents(events, t.id); + if (events.d) $(document).bind(events.d, data, callback); + if (events.w) $(window).bind(events.w, data, callback); + }; + + mejs.MediaElementPlayer.prototype.globalUnbind = function(events, callback) { + var t = this; + events = splitEvents(events, t.id); + if (events.d) $(document).unbind(events.d, callback); + if (events.w) $(window).unbind(events.w, callback); + }; + })(); + + // turn into jQuery plugin + if (typeof jQuery != 'undefined') { + jQuery.fn.mediaelementplayer = function (options) { + if (options === false) { + this.each(function () { + var player = jQuery(this).data('mediaelementplayer'); + if (player) { + player.remove(); + } + jQuery(this).removeData('mediaelementplayer'); + }); + } + else { + this.each(function () { + jQuery(this).data('mediaelementplayer', new mejs.MediaElementPlayer(this, options)); + }); + } + return this; + }; + } + + $(document).ready(function() { + // auto enable using JSON attribute + $('.mejs-player').mediaelementplayer(); + }); + + // push out to window + window.MediaElementPlayer = mejs.MediaElementPlayer; + +})(mejs.$); + +(function($) { + + $.extend(mejs.MepDefaults, { + playpauseText: mejs.i18n.t('Play/Pause') + }); + + // PLAY/pause BUTTON + $.extend(MediaElementPlayer.prototype, { + buildplaypause: function(player, controls, layers, media) { + var + t = this, + play = + $('<div class="mejs-button mejs-playpause-button mejs-play" >' + + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.playpauseText + '" aria-label="' + t.options.playpauseText + '"></button>' + + '</div>') + .appendTo(controls) + .click(function(e) { + e.preventDefault(); + + if (media.paused) { + media.play(); + } else { + media.pause(); + } + + return false; + }); + + media.addEventListener('play',function() { + play.removeClass('mejs-play').addClass('mejs-pause'); + }, false); + media.addEventListener('playing',function() { + play.removeClass('mejs-play').addClass('mejs-pause'); + }, false); + + + media.addEventListener('pause',function() { + play.removeClass('mejs-pause').addClass('mejs-play'); + }, false); + media.addEventListener('paused',function() { + play.removeClass('mejs-pause').addClass('mejs-play'); + }, false); + } + }); + +})(mejs.$); + +(function($) { + + $.extend(mejs.MepDefaults, { + stopText: 'Stop' + }); + + // STOP BUTTON + $.extend(MediaElementPlayer.prototype, { + buildstop: function(player, controls, layers, media) { + var t = this, + stop = + $('<div class="mejs-button mejs-stop-button mejs-stop">' + + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.stopText + '" aria-label="' + t.options.stopText + '"></button>' + + '</div>') + .appendTo(controls) + .click(function() { + if (!media.paused) { + media.pause(); + } + if (media.currentTime > 0) { + media.setCurrentTime(0); + media.pause(); + controls.find('.mejs-time-current').width('0px'); + controls.find('.mejs-time-handle').css('left', '0px'); + controls.find('.mejs-time-float-current').html( mejs.Utility.secondsToTimeCode(0) ); + controls.find('.mejs-currenttime').html( mejs.Utility.secondsToTimeCode(0) ); + layers.find('.mejs-poster').show(); + } + }); + } + }); + +})(mejs.$); + +(function($) { + // progress/loaded bar + $.extend(MediaElementPlayer.prototype, { + buildprogress: function(player, controls, layers, media) { + + $('<div class="mejs-time-rail">'+ + '<span class="mejs-time-total">'+ + '<span class="mejs-time-buffering"></span>'+ + '<span class="mejs-time-loaded"></span>'+ + '<span class="mejs-time-current"></span>'+ + '<span class="mejs-time-handle"></span>'+ + '<span class="mejs-time-float">' + + '<span class="mejs-time-float-current">00:00</span>' + + '<span class="mejs-time-float-corner"></span>' + + '</span>'+ + '</span>'+ + '</div>') + .appendTo(controls); + controls.find('.mejs-time-buffering').hide(); + + var + t = this, + total = controls.find('.mejs-time-total'), + loaded = controls.find('.mejs-time-loaded'), + current = controls.find('.mejs-time-current'), + handle = controls.find('.mejs-time-handle'), + timefloat = controls.find('.mejs-time-float'), + timefloatcurrent = controls.find('.mejs-time-float-current'), + handleMouseMove = function (e) { + // mouse position relative to the object + var x = e.pageX, + offset = total.offset(), + width = total.outerWidth(true), + percentage = 0, + newTime = 0, + pos = 0; + + + if (media.duration) { + if (x < offset.left) { + x = offset.left; + } else if (x > width + offset.left) { + x = width + offset.left; + } + + pos = x - offset.left; + percentage = (pos / width); + newTime = (percentage <= 0.02) ? 0 : percentage * media.duration; + + // seek to where the mouse is + if (mouseIsDown && newTime !== media.currentTime) { + media.setCurrentTime(newTime); + } + + // position floating time box + if (!mejs.MediaFeatures.hasTouch) { + timefloat.css('left', pos); + timefloatcurrent.html( mejs.Utility.secondsToTimeCode(newTime) ); + timefloat.show(); + } + } + }, + mouseIsDown = false, + mouseIsOver = false; + + // handle clicks + //controls.find('.mejs-time-rail').delegate('span', 'click', handleMouseMove); + total + .bind('mousedown', function (e) { + // only handle left clicks + if (e.which === 1) { + mouseIsDown = true; + handleMouseMove(e); + t.globalBind('mousemove.dur', function(e) { + handleMouseMove(e); + }); + t.globalBind('mouseup.dur', function (e) { + mouseIsDown = false; + timefloat.hide(); + t.globalUnbind('.dur'); + }); + return false; + } + }) + .bind('mouseenter', function(e) { + mouseIsOver = true; + t.globalBind('mousemove.dur', function(e) { + handleMouseMove(e); + }); + if (!mejs.MediaFeatures.hasTouch) { + timefloat.show(); + } + }) + .bind('mouseleave',function(e) { + mouseIsOver = false; + if (!mouseIsDown) { + t.globalUnbind('.dur'); + timefloat.hide(); + } + }); + + // loading + media.addEventListener('progress', function (e) { + player.setProgressRail(e); + player.setCurrentRail(e); + }, false); + + // current time + media.addEventListener('timeupdate', function(e) { + player.setProgressRail(e); + player.setCurrentRail(e); + }, false); + + + // store for later use + t.loaded = loaded; + t.total = total; + t.current = current; + t.handle = handle; + }, + setProgressRail: function(e) { + + var + t = this, + target = (e != undefined) ? e.target : t.media, + percent = null; + + // newest HTML5 spec has buffered array (FF4, Webkit) + if (target && target.buffered && target.buffered.length > 0 && target.buffered.end && target.duration) { + // TODO: account for a real array with multiple values (only Firefox 4 has this so far) + percent = target.buffered.end(0) / target.duration; + } + // Some browsers (e.g., FF3.6 and Safari 5) cannot calculate target.bufferered.end() + // to be anything other than 0. If the byte count is available we use this instead. + // Browsers that support the else if do not seem to have the bufferedBytes value and + // should skip to there. Tested in Safari 5, Webkit head, FF3.6, Chrome 6, IE 7/8. + else if (target && target.bytesTotal != undefined && target.bytesTotal > 0 && target.bufferedBytes != undefined) { + percent = target.bufferedBytes / target.bytesTotal; + } + // Firefox 3 with an Ogg file seems to go this way + else if (e && e.lengthComputable && e.total != 0) { + percent = e.loaded/e.total; + } + + // finally update the progress bar + if (percent !== null) { + percent = Math.min(1, Math.max(0, percent)); + // update loaded bar + if (t.loaded && t.total) { + t.loaded.width(t.total.width() * percent); + } + } + }, + setCurrentRail: function() { + + var t = this; + + if (t.media.currentTime != undefined && t.media.duration) { + + // update bar and handle + if (t.total && t.handle) { + var + newWidth = Math.round(t.total.width() * t.media.currentTime / t.media.duration), + handlePos = newWidth - Math.round(t.handle.outerWidth(true) / 2); + + t.current.width(newWidth); + t.handle.css('left', handlePos); + } + } + + } + }); +})(mejs.$); + +(function($) { + + // options + $.extend(mejs.MepDefaults, { + duration: -1, + timeAndDurationSeparator: ' <span> / </span> ' + }); + + + // current and duration 00:00 / 00:00 + $.extend(MediaElementPlayer.prototype, { + buildcurrent: function(player, controls, layers, media) { + var t = this; + + $('<div class="mejs-time">'+ + '<span class="mejs-currenttime">' + (player.options.alwaysShowHours ? '00:' : '') + + (player.options.showTimecodeFrameCount? '00:00:00':'00:00')+ '</span>'+ + '</div>') + .appendTo(controls); + + t.currenttime = t.controls.find('.mejs-currenttime'); + + media.addEventListener('timeupdate',function() { + player.updateCurrent(); + }, false); + }, + + + buildduration: function(player, controls, layers, media) { + var t = this; + + if (controls.children().last().find('.mejs-currenttime').length > 0) { + $(t.options.timeAndDurationSeparator + + '<span class="mejs-duration">' + + (t.options.duration > 0 ? + mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25) : + ((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00')) + ) + + '</span>') + .appendTo(controls.find('.mejs-time')); + } else { + + // add class to current time + controls.find('.mejs-currenttime').parent().addClass('mejs-currenttime-container'); + + $('<div class="mejs-time mejs-duration-container">'+ + '<span class="mejs-duration">' + + (t.options.duration > 0 ? + mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25) : + ((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00')) + ) + + '</span>' + + '</div>') + .appendTo(controls); + } + + t.durationD = t.controls.find('.mejs-duration'); + + media.addEventListener('timeupdate',function() { + player.updateDuration(); + }, false); + }, + + updateCurrent: function() { + var t = this; + + if (t.currenttime) { + t.currenttime.html(mejs.Utility.secondsToTimeCode(t.media.currentTime, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25)); + } + }, + + updateDuration: function() { + var t = this; + + //Toggle the long video class if the video is longer than an hour. + t.container.toggleClass("mejs-long-video", t.media.duration > 3600); + + if (t.durationD && (t.options.duration > 0 || t.media.duration)) { + t.durationD.html(mejs.Utility.secondsToTimeCode(t.options.duration > 0 ? t.options.duration : t.media.duration, t.options.alwaysShowHours, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25)); + } + } + }); + +})(mejs.$); + +(function($) { + + $.extend(mejs.MepDefaults, { + muteText: mejs.i18n.t('Mute Toggle'), + hideVolumeOnTouchDevices: true, + + audioVolume: 'horizontal', + videoVolume: 'vertical' + }); + + $.extend(MediaElementPlayer.prototype, { + buildvolume: function(player, controls, layers, media) { + + // Android and iOS don't support volume controls + if (mejs.MediaFeatures.hasTouch && this.options.hideVolumeOnTouchDevices) + return; + + var t = this, + mode = (t.isVideo) ? t.options.videoVolume : t.options.audioVolume, + mute = (mode == 'horizontal') ? + + // horizontal version + $('<div class="mejs-button mejs-volume-button mejs-mute">'+ + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '" aria-label="' + t.options.muteText + '"></button>'+ + '</div>' + + '<div class="mejs-horizontal-volume-slider">'+ // outer background + '<div class="mejs-horizontal-volume-total"></div>'+ // line background + '<div class="mejs-horizontal-volume-current"></div>'+ // current volume + '<div class="mejs-horizontal-volume-handle"></div>'+ // handle + '</div>' + ) + .appendTo(controls) : + + // vertical version + $('<div class="mejs-button mejs-volume-button mejs-mute">'+ + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '" aria-label="' + t.options.muteText + '"></button>'+ + '<div class="mejs-volume-slider">'+ // outer background + '<div class="mejs-volume-total"></div>'+ // line background + '<div class="mejs-volume-current"></div>'+ // current volume + '<div class="mejs-volume-handle"></div>'+ // handle + '</div>'+ + '</div>') + .appendTo(controls), + volumeSlider = t.container.find('.mejs-volume-slider, .mejs-horizontal-volume-slider'), + volumeTotal = t.container.find('.mejs-volume-total, .mejs-horizontal-volume-total'), + volumeCurrent = t.container.find('.mejs-volume-current, .mejs-horizontal-volume-current'), + volumeHandle = t.container.find('.mejs-volume-handle, .mejs-horizontal-volume-handle'), + + positionVolumeHandle = function(volume, secondTry) { + + if (!volumeSlider.is(':visible') && typeof secondTry == 'undefined') { + volumeSlider.show(); + positionVolumeHandle(volume, true); + volumeSlider.hide() + return; + } + + // correct to 0-1 + volume = Math.max(0,volume); + volume = Math.min(volume,1); + + // ajust mute button style + if (volume == 0) { + mute.removeClass('mejs-mute').addClass('mejs-unmute'); + } else { + mute.removeClass('mejs-unmute').addClass('mejs-mute'); + } + + // position slider + if (mode == 'vertical') { + var + + // height of the full size volume slider background + totalHeight = volumeTotal.height(), + + // top/left of full size volume slider background + totalPosition = volumeTotal.position(), + + // the new top position based on the current volume + // 70% volume on 100px height == top:30px + newTop = totalHeight - (totalHeight * volume); + + // handle + volumeHandle.css('top', Math.round(totalPosition.top + newTop - (volumeHandle.height() / 2))); + + // show the current visibility + volumeCurrent.height(totalHeight - newTop ); + volumeCurrent.css('top', totalPosition.top + newTop); + } else { + var + + // height of the full size volume slider background + totalWidth = volumeTotal.width(), + + // top/left of full size volume slider background + totalPosition = volumeTotal.position(), + + // the new left position based on the current volume + newLeft = totalWidth * volume; + + // handle + volumeHandle.css('left', Math.round(totalPosition.left + newLeft - (volumeHandle.width() / 2))); + + // rezize the current part of the volume bar + volumeCurrent.width( Math.round(newLeft) ); + } + }, + handleVolumeMove = function(e) { + + var volume = null, + totalOffset = volumeTotal.offset(); + + // calculate the new volume based on the moust position + if (mode == 'vertical') { + + var + railHeight = volumeTotal.height(), + totalTop = parseInt(volumeTotal.css('top').replace(/px/,''),10), + newY = e.pageY - totalOffset.top; + + volume = (railHeight - newY) / railHeight; + + // the controls just hide themselves (usually when mouse moves too far up) + if (totalOffset.top == 0 || totalOffset.left == 0) + return; + + } else { + var + railWidth = volumeTotal.width(), + newX = e.pageX - totalOffset.left; + + volume = newX / railWidth; + } + + // ensure the volume isn't outside 0-1 + volume = Math.max(0,volume); + volume = Math.min(volume,1); + + // position the slider and handle + positionVolumeHandle(volume); + + // set the media object (this will trigger the volumechanged event) + if (volume == 0) { + media.setMuted(true); + } else { + media.setMuted(false); + } + media.setVolume(volume); + }, + mouseIsDown = false, + mouseIsOver = false; + + // SLIDER + + mute + .hover(function() { + volumeSlider.show(); + mouseIsOver = true; + }, function() { + mouseIsOver = false; + + if (!mouseIsDown && mode == 'vertical') { + volumeSlider.hide(); + } + }); + + volumeSlider + .bind('mouseover', function() { + mouseIsOver = true; + }) + .bind('mousedown', function (e) { + handleVolumeMove(e); + t.globalBind('mousemove.vol', function(e) { + handleVolumeMove(e); + }); + t.globalBind('mouseup.vol', function () { + mouseIsDown = false; + t.globalUnbind('.vol'); + + if (!mouseIsOver && mode == 'vertical') { + volumeSlider.hide(); + } + }); + mouseIsDown = true; + + return false; + }); + + + // MUTE button + mute.find('button').click(function() { + media.setMuted( !media.muted ); + }); + + // listen for volume change events from other sources + media.addEventListener('volumechange', function(e) { + if (!mouseIsDown) { + if (media.muted) { + positionVolumeHandle(0); + mute.removeClass('mejs-mute').addClass('mejs-unmute'); + } else { + positionVolumeHandle(media.volume); + mute.removeClass('mejs-unmute').addClass('mejs-mute'); + } + } + }, false); + + if (t.container.is(':visible')) { + // set initial volume + positionVolumeHandle(player.options.startVolume); + + // mutes the media and sets the volume icon muted if the initial volume is set to 0 + if (player.options.startVolume === 0) { + media.setMuted(true); + } + + // shim gets the startvolume as a parameter, but we have to set it on the native <video> and <audio> elements + if (media.pluginType === 'native') { + media.setVolume(player.options.startVolume); + } + } + } + }); + +})(mejs.$); + +(function($) { + + $.extend(mejs.MepDefaults, { + usePluginFullScreen: true, + newWindowCallback: function() { return '';}, + fullscreenText: mejs.i18n.t('Fullscreen') + }); + + $.extend(MediaElementPlayer.prototype, { + + isFullScreen: false, + + isNativeFullScreen: false, + + docStyleOverflow: null, + + isInIframe: false, + + buildfullscreen: function(player, controls, layers, media) { + + if (!player.isVideo) + return; + + player.isInIframe = (window.location != window.parent.location); + + // native events + if (mejs.MediaFeatures.hasTrueNativeFullScreen) { + + // chrome doesn't alays fire this in an iframe + var func = function(e) { + + if (mejs.MediaFeatures.isFullScreen()) { + player.isNativeFullScreen = true; + // reset the controls once we are fully in full screen + player.setControlsSize(); + } else { + player.isNativeFullScreen = false; + // when a user presses ESC + // make sure to put the player back into place + player.exitFullScreen(); + } + }; + + if (mejs.MediaFeatures.hasMozNativeFullScreen) { + player.globalBind(mejs.MediaFeatures.fullScreenEventName, func); + } else { + player.container.bind(mejs.MediaFeatures.fullScreenEventName, func); + } + } + + var t = this, + normalHeight = 0, + normalWidth = 0, + container = player.container, + fullscreenBtn = + $('<div class="mejs-button mejs-fullscreen-button">' + + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.fullscreenText + '" aria-label="' + t.options.fullscreenText + '"></button>' + + '</div>') + .appendTo(controls); + + if (t.media.pluginType === 'native' || (!t.options.usePluginFullScreen && !mejs.MediaFeatures.isFirefox)) { + + fullscreenBtn.click(function() { + var isFullScreen = (mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || player.isFullScreen; + + if (isFullScreen) { + player.exitFullScreen(); + } else { + player.enterFullScreen(); + } + }); + + } else { + + var hideTimeout = null, + supportsPointerEvents = (function() { + // TAKEN FROM MODERNIZR + var element = document.createElement('x'), + documentElement = document.documentElement, + getComputedStyle = window.getComputedStyle, + supports; + if(!('pointerEvents' in element.style)){ + return false; + } + element.style.pointerEvents = 'auto'; + element.style.pointerEvents = 'x'; + documentElement.appendChild(element); + supports = getComputedStyle && + getComputedStyle(element, '').pointerEvents === 'auto'; + documentElement.removeChild(element); + return !!supports; + })(); + + //console.log('supportsPointerEvents', supportsPointerEvents); + + if (supportsPointerEvents && !mejs.MediaFeatures.isOpera) { // opera doesn't allow this :( + + // allows clicking through the fullscreen button and controls down directly to Flash + + /* + When a user puts his mouse over the fullscreen button, the controls are disabled + So we put a div over the video and another one on iether side of the fullscreen button + that caputre mouse movement + and restore the controls once the mouse moves outside of the fullscreen button + */ + + var fullscreenIsDisabled = false, + restoreControls = function() { + if (fullscreenIsDisabled) { + // hide the hovers + for (var i in hoverDivs) { + hoverDivs[i].hide(); + } + + // restore the control bar + fullscreenBtn.css('pointer-events', ''); + t.controls.css('pointer-events', ''); + + // prevent clicks from pausing video + t.media.removeEventListener('click', t.clickToPlayPauseCallback); + + // store for later + fullscreenIsDisabled = false; + } + }, + hoverDivs = {}, + hoverDivNames = ['top', 'left', 'right', 'bottom'], + i, len, + positionHoverDivs = function() { + var fullScreenBtnOffsetLeft = fullscreenBtn.offset().left - t.container.offset().left, + fullScreenBtnOffsetTop = fullscreenBtn.offset().top - t.container.offset().top, + fullScreenBtnWidth = fullscreenBtn.outerWidth(true), + fullScreenBtnHeight = fullscreenBtn.outerHeight(true), + containerWidth = t.container.width(), + containerHeight = t.container.height(); + + for (i in hoverDivs) { + hoverDivs[i].css({position: 'absolute', top: 0, left: 0}); //, backgroundColor: '#f00'}); + } + + // over video, but not controls + hoverDivs['top'] + .width( containerWidth ) + .height( fullScreenBtnOffsetTop ); + + // over controls, but not the fullscreen button + hoverDivs['left'] + .width( fullScreenBtnOffsetLeft ) + .height( fullScreenBtnHeight ) + .css({top: fullScreenBtnOffsetTop}); + + // after the fullscreen button + hoverDivs['right'] + .width( containerWidth - fullScreenBtnOffsetLeft - fullScreenBtnWidth ) + .height( fullScreenBtnHeight ) + .css({top: fullScreenBtnOffsetTop, + left: fullScreenBtnOffsetLeft + fullScreenBtnWidth}); + + // under the fullscreen button + hoverDivs['bottom'] + .width( containerWidth ) + .height( containerHeight - fullScreenBtnHeight - fullScreenBtnOffsetTop ) + .css({top: fullScreenBtnOffsetTop + fullScreenBtnHeight}); + }; + + t.globalBind('resize', function() { + positionHoverDivs(); + }); + + for (i = 0, len = hoverDivNames.length; i < len; i++) { + hoverDivs[hoverDivNames[i]] = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls).hide(); + } + + // on hover, kill the fullscreen button's HTML handling, allowing clicks down to Flash + fullscreenBtn.on('mouseover',function() { + + if (!t.isFullScreen) { + + var buttonPos = fullscreenBtn.offset(), + containerPos = player.container.offset(); + + // move the button in Flash into place + media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, false); + + // allows click through + fullscreenBtn.css('pointer-events', 'none'); + t.controls.css('pointer-events', 'none'); + + // restore click-to-play + t.media.addEventListener('click', t.clickToPlayPauseCallback); + + // show the divs that will restore things + for (i in hoverDivs) { + hoverDivs[i].show(); + } + + positionHoverDivs(); + + fullscreenIsDisabled = true; + } + + }); + + // restore controls anytime the user enters or leaves fullscreen + media.addEventListener('fullscreenchange', function(e) { + t.isFullScreen = !t.isFullScreen; + // don't allow plugin click to pause video - messes with + // plugin's controls + if (t.isFullScreen) { + t.media.removeEventListener('click', t.clickToPlayPauseCallback); + } else { + t.media.addEventListener('click', t.clickToPlayPauseCallback); + } + restoreControls(); + }); + + + // the mouseout event doesn't work on the fullscren button, because we already killed the pointer-events + // so we use the document.mousemove event to restore controls when the mouse moves outside the fullscreen button + + t.globalBind('mousemove', function(e) { + + // if the mouse is anywhere but the fullsceen button, then restore it all + if (fullscreenIsDisabled) { + + var fullscreenBtnPos = fullscreenBtn.offset(); + + + if (e.pageY < fullscreenBtnPos.top || e.pageY > fullscreenBtnPos.top + fullscreenBtn.outerHeight(true) || + e.pageX < fullscreenBtnPos.left || e.pageX > fullscreenBtnPos.left + fullscreenBtn.outerWidth(true) + ) { + + fullscreenBtn.css('pointer-events', ''); + t.controls.css('pointer-events', ''); + + fullscreenIsDisabled = false; + } + } + }); + + + + } else { + + // the hover state will show the fullscreen button in Flash to hover up and click + + fullscreenBtn + .on('mouseover', function() { + + if (hideTimeout !== null) { + clearTimeout(hideTimeout); + delete hideTimeout; + } + + var buttonPos = fullscreenBtn.offset(), + containerPos = player.container.offset(); + + media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, true); + + }) + .on('mouseout', function() { + + if (hideTimeout !== null) { + clearTimeout(hideTimeout); + delete hideTimeout; + } + + hideTimeout = setTimeout(function() { + media.hideFullscreenButton(); + }, 1500); + + + }); + } + } + + player.fullscreenBtn = fullscreenBtn; + + t.globalBind('keydown',function (e) { + if (((mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || t.isFullScreen) && e.keyCode == 27) { + player.exitFullScreen(); + } + }); + + }, + + cleanfullscreen: function(player) { + player.exitFullScreen(); + }, + + containerSizeTimeout: null, + + enterFullScreen: function() { + + var t = this; + + // firefox+flash can't adjust plugin sizes without resetting :( + if (t.media.pluginType !== 'native' && (mejs.MediaFeatures.isFirefox || t.options.usePluginFullScreen)) { + //t.media.setFullscreen(true); + //player.isFullScreen = true; + return; + } + + // store overflow + docStyleOverflow = document.documentElement.style.overflow; + // set it to not show scroll bars so 100% will work + document.documentElement.style.overflow = 'hidden'; + + // store sizing + normalHeight = t.container.height(); + normalWidth = t.container.width(); + + // attempt to do true fullscreen (Safari 5.1 and Firefox Nightly only for now) + if (t.media.pluginType === 'native') { + if (mejs.MediaFeatures.hasTrueNativeFullScreen) { + + mejs.MediaFeatures.requestFullScreen(t.container[0]); + //return; + + if (t.isInIframe) { + // sometimes exiting from fullscreen doesn't work + // notably in Chrome <iframe>. Fixed in version 17 + setTimeout(function checkFullscreen() { + + if (t.isNativeFullScreen) { + + // check if the video is suddenly not really fullscreen + if ($(window).width() !== screen.width) { + // manually exit + t.exitFullScreen(); + } else { + // test again + setTimeout(checkFullscreen, 500); + } + } + + + }, 500); + } + + } else if (mejs.MediaFeatures.hasSemiNativeFullScreen) { + t.media.webkitEnterFullscreen(); + return; + } + } + + // check for iframe launch + if (t.isInIframe) { + var url = t.options.newWindowCallback(this); + + + if (url !== '') { + + // launch immediately + if (!mejs.MediaFeatures.hasTrueNativeFullScreen) { + t.pause(); + window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no'); + return; + } else { + setTimeout(function() { + if (!t.isNativeFullScreen) { + t.pause(); + window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no'); + } + }, 250); + } + } + + } + + // full window code + + + + // make full size + t.container + .addClass('mejs-container-fullscreen') + .width('100%') + .height('100%'); + //.css({position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, overflow: 'hidden', width: '100%', height: '100%', 'z-index': 1000}); + + // Only needed for safari 5.1 native full screen, can cause display issues elsewhere + // Actually, it seems to be needed for IE8, too + //if (mejs.MediaFeatures.hasTrueNativeFullScreen) { + t.containerSizeTimeout = setTimeout(function() { + t.container.css({width: '100%', height: '100%'}); + t.setControlsSize(); + }, 500); + //} + + if (t.media.pluginType === 'native') { + t.$media + .width('100%') + .height('100%'); + } else { + t.container.find('.mejs-shim') + .width('100%') + .height('100%'); + + //if (!mejs.MediaFeatures.hasTrueNativeFullScreen) { + t.media.setVideoSize($(window).width(),$(window).height()); + //} + } + + t.layers.children('div') + .width('100%') + .height('100%'); + + if (t.fullscreenBtn) { + t.fullscreenBtn + .removeClass('mejs-fullscreen') + .addClass('mejs-unfullscreen'); + } + + t.setControlsSize(); + t.isFullScreen = true; + }, + + exitFullScreen: function() { + + var t = this; + + // Prevent container from attempting to stretch a second time + clearTimeout(t.containerSizeTimeout); + + // firefox can't adjust plugins + if (t.media.pluginType !== 'native' && mejs.MediaFeatures.isFirefox) { + t.media.setFullscreen(false); + //player.isFullScreen = false; + return; + } + + // come outo of native fullscreen + if (mejs.MediaFeatures.hasTrueNativeFullScreen && (mejs.MediaFeatures.isFullScreen() || t.isFullScreen)) { + mejs.MediaFeatures.cancelFullScreen(); + } + + // restore scroll bars to document + document.documentElement.style.overflow = docStyleOverflow; + + t.container + .removeClass('mejs-container-fullscreen') + .width(normalWidth) + .height(normalHeight); + //.css({position: '', left: '', top: '', right: '', bottom: '', overflow: 'inherit', width: normalWidth + 'px', height: normalHeight + 'px', 'z-index': 1}); + + if (t.media.pluginType === 'native') { + t.$media + .width(normalWidth) + .height(normalHeight); + } else { + t.container.find('.mejs-shim') + .width(normalWidth) + .height(normalHeight); + + t.media.setVideoSize(normalWidth, normalHeight); + } + + t.layers.children('div') + .width(normalWidth) + .height(normalHeight); + + t.fullscreenBtn + .removeClass('mejs-unfullscreen') + .addClass('mejs-fullscreen'); + + t.setControlsSize(); + t.isFullScreen = false; + } + }); + +})(mejs.$); + +(function($) { + + // add extra default options + $.extend(mejs.MepDefaults, { + // this will automatically turn on a <track> + startLanguage: '', + + tracksText: mejs.i18n.t('Captions/Subtitles'), + + // option to remove the [cc] button when no <track kind="subtitles"> are present + hideCaptionsButtonWhenEmpty: true, + + // If true and we only have one track, change captions to popup + toggleCaptionsButtonWhenOnlyOne: false, + + // #id or .class + slidesSelector: '' + }); + + $.extend(MediaElementPlayer.prototype, { + + hasChapters: false, + + buildtracks: function(player, controls, layers, media) { + if (player.tracks.length == 0) + return; + + var t = this, + i, + options = ''; + + player.chapters = + $('<div class="mejs-chapters mejs-layer"></div>') + .prependTo(layers).hide(); + player.captions = + $('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position mejs-captions-position-hover"><span class="mejs-captions-text"></span></div></div>') + .prependTo(layers).hide(); + player.captionsText = player.captions.find('.mejs-captions-text'); + player.captionsButton = + $('<div class="mejs-button mejs-captions-button">'+ + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.tracksText + '" aria-label="' + t.options.tracksText + '"></button>'+ + '<div class="mejs-captions-selector">'+ + '<ul>'+ + '<li>'+ + '<input type="radio" name="' + player.id + '_captions" id="' + player.id + '_captions_none" value="none" checked="checked" />' + + '<label for="' + player.id + '_captions_none">' + mejs.i18n.t('None') +'</label>'+ + '</li>' + + '</ul>'+ + '</div>'+ + '</div>') + .appendTo(controls); + + + var subtitleCount = 0; + for (i=0; i<player.tracks.length; i++) { + if (player.tracks[i].kind == 'subtitles') { + subtitleCount++; + } + } + + // if only one language then just make the button a toggle + if (t.options.toggleCaptionsButtonWhenOnlyOne && subtitleCount == 1){ + // click + player.captionsButton.on('click',function() { + if (player.selectedTrack == null) { + var lang = player.tracks[0].srclang; + } else { + var lang = 'none'; + } + player.setTrack(lang); + }); + } else { + // hover + player.captionsButton.hover(function() { + $(this).find('.mejs-captions-selector').css('visibility','visible'); + }, function() { + $(this).find('.mejs-captions-selector').css('visibility','hidden'); + }) + + // handle clicks to the language radio buttons + .on('click','input[type=radio]',function() { + lang = this.value; + player.setTrack(lang); + }); + + } + + if (!player.options.alwaysShowControls) { + // move with controls + player.container + .bind('controlsshown', function () { + // push captions above controls + player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover'); + + }) + .bind('controlshidden', function () { + if (!media.paused) { + // move back to normal place + player.container.find('.mejs-captions-position').removeClass('mejs-captions-position-hover'); + } + }); + } else { + player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover'); + } + + player.trackToLoad = -1; + player.selectedTrack = null; + player.isLoadingTrack = false; + + + + // add to list + for (i=0; i<player.tracks.length; i++) { + if (player.tracks[i].kind == 'subtitles') { + player.addTrackButton(player.tracks[i].srclang, player.tracks[i].label); + } + } + + // start loading tracks + player.loadNextTrack(); + + + media.addEventListener('timeupdate',function(e) { + player.displayCaptions(); + }, false); + + if (player.options.slidesSelector != '') { + player.slidesContainer = $(player.options.slidesSelector); + + media.addEventListener('timeupdate',function(e) { + player.displaySlides(); + }, false); + + } + + media.addEventListener('loadedmetadata', function(e) { + player.displayChapters(); + }, false); + + player.container.hover( + function () { + // chapters + if (player.hasChapters) { + player.chapters.css('visibility','visible'); + player.chapters.fadeIn(200).height(player.chapters.find('.mejs-chapter').outerHeight()); + } + }, + function () { + if (player.hasChapters && !media.paused) { + player.chapters.fadeOut(200, function() { + $(this).css('visibility','hidden'); + $(this).css('display','block'); + }); + } + }); + + // check for autoplay + if (player.node.getAttribute('autoplay') !== null) { + player.chapters.css('visibility','hidden'); + } + }, + + setTrack: function(lang){ + + var t = this, + i; + + if (lang == 'none') { + t.selectedTrack = null; + t.captionsButton.removeClass('mejs-captions-enabled'); + } else { + for (i=0; i<t.tracks.length; i++) { + if (t.tracks[i].srclang == lang) { + if (t.selectedTrack == null) + t.captionsButton.addClass('mejs-captions-enabled'); + t.selectedTrack = t.tracks[i]; + t.captions.attr('lang', t.selectedTrack.srclang); + t.displayCaptions(); + break; + } + } + } + }, + + loadNextTrack: function() { + var t = this; + + t.trackToLoad++; + if (t.trackToLoad < t.tracks.length) { + t.isLoadingTrack = true; + t.loadTrack(t.trackToLoad); + } else { + // add done? + t.isLoadingTrack = false; + + t.checkForTracks(); + } + }, + + loadTrack: function(index){ + var + t = this, + track = t.tracks[index], + after = function() { + + track.isLoaded = true; + + // create button + //t.addTrackButton(track.srclang); + t.enableTrackButton(track.srclang, track.label); + + t.loadNextTrack(); + + }; + + + $.ajax({ + url: track.src, + dataType: "text", + success: function(d) { + + // parse the loaded file + if (typeof d == "string" && (/<tt\s+xml/ig).exec(d)) { + track.entries = mejs.TrackFormatParser.dfxp.parse(d); + } else { + track.entries = mejs.TrackFormatParser.webvvt.parse(d); + } + + after(); + + if (track.kind == 'chapters') { + t.media.addEventListener('play', function(e) { + if (t.media.duration > 0) { + t.displayChapters(track); + } + }, false); + } + + if (track.kind == 'slides') { + t.setupSlides(track); + } + }, + error: function() { + t.loadNextTrack(); + } + }); + }, + + enableTrackButton: function(lang, label) { + var t = this; + + if (label === '') { + label = mejs.language.codes[lang] || lang; + } + + t.captionsButton + .find('input[value=' + lang + ']') + .prop('disabled',false) + .siblings('label') + .html( label ); + + // auto select + if (t.options.startLanguage == lang) { + $('#' + t.id + '_captions_' + lang).click(); + } + + t.adjustLanguageBox(); + }, + + addTrackButton: function(lang, label) { + var t = this; + if (label === '') { + label = mejs.language.codes[lang] || lang; + } + + t.captionsButton.find('ul').append( + $('<li>'+ + '<input type="radio" name="' + t.id + '_captions" id="' + t.id + '_captions_' + lang + '" value="' + lang + '" disabled="disabled" />' + + '<label for="' + t.id + '_captions_' + lang + '">' + label + ' (loading)' + '</label>'+ + '</li>') + ); + + t.adjustLanguageBox(); + + // remove this from the dropdownlist (if it exists) + t.container.find('.mejs-captions-translations option[value=' + lang + ']').remove(); + }, + + adjustLanguageBox:function() { + var t = this; + // adjust the size of the outer box + t.captionsButton.find('.mejs-captions-selector').height( + t.captionsButton.find('.mejs-captions-selector ul').outerHeight(true) + + t.captionsButton.find('.mejs-captions-translations').outerHeight(true) + ); + }, + + checkForTracks: function() { + var + t = this, + hasSubtitles = false; + + // check if any subtitles + if (t.options.hideCaptionsButtonWhenEmpty) { + for (i=0; i<t.tracks.length; i++) { + if (t.tracks[i].kind == 'subtitles') { + hasSubtitles = true; + break; + } + } + + if (!hasSubtitles) { + t.captionsButton.hide(); + t.setControlsSize(); + } + } + }, + + displayCaptions: function() { + + if (typeof this.tracks == 'undefined') + return; + + var + t = this, + i, + track = t.selectedTrack; + + if (track != null && track.isLoaded) { + for (i=0; i<track.entries.times.length; i++) { + if (t.media.currentTime >= track.entries.times[i].start && t.media.currentTime <= track.entries.times[i].stop){ + t.captionsText.html(track.entries.text[i]); + t.captions.show().height(0); + return; // exit out if one is visible; + } + } + t.captions.hide(); + } else { + t.captions.hide(); + } + }, + + setupSlides: function(track) { + var t = this; + + t.slides = track; + t.slides.entries.imgs = [t.slides.entries.text.length]; + t.showSlide(0); + + }, + + showSlide: function(index) { + if (typeof this.tracks == 'undefined' || typeof this.slidesContainer == 'undefined') { + return; + } + + var t = this, + url = t.slides.entries.text[index], + img = t.slides.entries.imgs[index]; + + if (typeof img == 'undefined' || typeof img.fadeIn == 'undefined') { + + t.slides.entries.imgs[index] = img = $('<img src="' + url + '">') + .on('load', function() { + img.appendTo(t.slidesContainer) + .hide() + .fadeIn() + .siblings(':visible') + .fadeOut(); + + }); + + } else { + + if (!img.is(':visible') && !img.is(':animated')) { + + console.log('showing existing slide'); + + img.fadeIn() + .siblings(':visible') + .fadeOut(); + } + } + + }, + + displaySlides: function() { + + if (typeof this.slides == 'undefined') + return; + + var + t = this, + slides = t.slides, + i; + + for (i=0; i<slides.entries.times.length; i++) { + if (t.media.currentTime >= slides.entries.times[i].start && t.media.currentTime <= slides.entries.times[i].stop){ + + t.showSlide(i); + + return; // exit out if one is visible; + } + } + }, + + displayChapters: function() { + var + t = this, + i; + + for (i=0; i<t.tracks.length; i++) { + if (t.tracks[i].kind == 'chapters' && t.tracks[i].isLoaded) { + t.drawChapters(t.tracks[i]); + t.hasChapters = true; + break; + } + } + }, + + drawChapters: function(chapters) { + var + t = this, + i, + dur, + //width, + //left, + percent = 0, + usedPercent = 0; + + t.chapters.empty(); + + for (i=0; i<chapters.entries.times.length; i++) { + dur = chapters.entries.times[i].stop - chapters.entries.times[i].start; + percent = Math.floor(dur / t.media.duration * 100); + if (percent + usedPercent > 100 || // too large + i == chapters.entries.times.length-1 && percent + usedPercent < 100) // not going to fill it in + { + percent = 100 - usedPercent; + } + //width = Math.floor(t.width * dur / t.media.duration); + //left = Math.floor(t.width * chapters.entries.times[i].start / t.media.duration); + //if (left + width > t.width) { + // width = t.width - left; + //} + + t.chapters.append( $( + '<div class="mejs-chapter" rel="' + chapters.entries.times[i].start + '" style="left: ' + usedPercent.toString() + '%;width: ' + percent.toString() + '%;">' + + '<div class="mejs-chapter-block' + ((i==chapters.entries.times.length-1) ? ' mejs-chapter-block-last' : '') + '">' + + '<span class="ch-title">' + chapters.entries.text[i] + '</span>' + + '<span class="ch-time">' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].start) + '&ndash;' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].stop) + '</span>' + + '</div>' + + '</div>')); + usedPercent += percent; + } + + t.chapters.find('div.mejs-chapter').click(function() { + t.media.setCurrentTime( parseFloat( $(this).attr('rel') ) ); + if (t.media.paused) { + t.media.play(); + } + }); + + t.chapters.show(); + } + }); + + + + mejs.language = { + codes: { + af:'Afrikaans', + sq:'Albanian', + ar:'Arabic', + be:'Belarusian', + bg:'Bulgarian', + ca:'Catalan', + zh:'Chinese', + 'zh-cn':'Chinese Simplified', + 'zh-tw':'Chinese Traditional', + hr:'Croatian', + cs:'Czech', + da:'Danish', + nl:'Dutch', + en:'English', + et:'Estonian', + tl:'Filipino', + fi:'Finnish', + fr:'French', + gl:'Galician', + de:'German', + el:'Greek', + ht:'Haitian Creole', + iw:'Hebrew', + hi:'Hindi', + hu:'Hungarian', + is:'Icelandic', + id:'Indonesian', + ga:'Irish', + it:'Italian', + ja:'Japanese', + ko:'Korean', + lv:'Latvian', + lt:'Lithuanian', + mk:'Macedonian', + ms:'Malay', + mt:'Maltese', + no:'Norwegian', + fa:'Persian', + pl:'Polish', + pt:'Portuguese', + //'pt-pt':'Portuguese (Portugal)', + ro:'Romanian', + ru:'Russian', + sr:'Serbian', + sk:'Slovak', + sl:'Slovenian', + es:'Spanish', + sw:'Swahili', + sv:'Swedish', + tl:'Tagalog', + th:'Thai', + tr:'Turkish', + uk:'Ukrainian', + vi:'Vietnamese', + cy:'Welsh', + yi:'Yiddish' + } + }; + + /* + Parses WebVVT format which should be formatted as + ================================ + WEBVTT + + 1 + 00:00:01,1 --> 00:00:05,000 + A line of text + + 2 + 00:01:15,1 --> 00:02:05,000 + A second line of text + + =============================== + + Adapted from: http://www.delphiki.com/html5/playr + */ + mejs.TrackFormatParser = { + webvvt: { + // match start "chapter-" (or anythingelse) + pattern_identifier: /^([a-zA-z]+-)?[0-9]+$/, + pattern_timecode: /^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/, + + parse: function(trackText) { + var + i = 0, + lines = mejs.TrackFormatParser.split2(trackText, /\r?\n/), + entries = {text:[], times:[]}, + timecode, + text; + for(; i<lines.length; i++) { + // check for the line number + if (this.pattern_identifier.exec(lines[i])){ + // skip to the next line where the start --> end time code should be + i++; + timecode = this.pattern_timecode.exec(lines[i]); + + if (timecode && i<lines.length){ + i++; + // grab all the (possibly multi-line) text that follows + text = lines[i]; + i++; + while(lines[i] !== '' && i<lines.length){ + text = text + '\n' + lines[i]; + i++; + } + text = $.trim(text).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>"); + // Text is in a different array so I can use .join + entries.text.push(text); + entries.times.push( + { + start: (mejs.Utility.convertSMPTEtoSeconds(timecode[1]) == 0) ? 0.200 : mejs.Utility.convertSMPTEtoSeconds(timecode[1]), + stop: mejs.Utility.convertSMPTEtoSeconds(timecode[3]), + settings: timecode[5] + }); + } + } + } + return entries; + } + }, + // Thanks to Justin Capella: https://github.com/johndyer/mediaelement/pull/420 + dfxp: { + parse: function(trackText) { + trackText = $(trackText).filter("tt"); + var + i = 0, + container = trackText.children("div").eq(0), + lines = container.find("p"), + styleNode = trackText.find("#" + container.attr("style")), + styles, + begin, + end, + text, + entries = {text:[], times:[]}; + + + if (styleNode.length) { + var attributes = styleNode.removeAttr("id").get(0).attributes; + if (attributes.length) { + styles = {}; + for (i = 0; i < attributes.length; i++) { + styles[attributes[i].name.split(":")[1]] = attributes[i].value; + } + } + } + + for(i = 0; i<lines.length; i++) { + var style; + var _temp_times = { + start: null, + stop: null, + style: null + }; + if (lines.eq(i).attr("begin")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("begin")); + if (!_temp_times.start && lines.eq(i-1).attr("end")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i-1).attr("end")); + if (lines.eq(i).attr("end")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("end")); + if (!_temp_times.stop && lines.eq(i+1).attr("begin")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i+1).attr("begin")); + if (styles) { + style = ""; + for (var _style in styles) { + style += _style + ":" + styles[_style] + ";"; + } + } + if (style) _temp_times.style = style; + if (_temp_times.start == 0) _temp_times.start = 0.200; + entries.times.push(_temp_times); + text = $.trim(lines.eq(i).html()).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>"); + entries.text.push(text); + if (entries.times.start == 0) entries.times.start = 2; + } + return entries; + } + }, + split2: function (text, regex) { + // normal version for compliant browsers + // see below for IE fix + return text.split(regex); + } + }; + + // test for browsers with bad String.split method. + if ('x\n\ny'.split(/\n/gi).length != 3) { + // add super slow IE8 and below version + mejs.TrackFormatParser.split2 = function(text, regex) { + var + parts = [], + chunk = '', + i; + + for (i=0; i<text.length; i++) { + chunk += text.substring(i,i+1); + if (regex.test(chunk)) { + parts.push(chunk.replace(regex, '')); + chunk = ''; + } + } + parts.push(chunk); + return parts; + } + } + +})(mejs.$); + +/* +* ContextMenu Plugin +* +* +*/ + +(function($) { + +$.extend(mejs.MepDefaults, + { 'contextMenuItems': [ + // demo of a fullscreen option + { + render: function(player) { + + // check for fullscreen plugin + if (typeof player.enterFullScreen == 'undefined') + return null; + + if (player.isFullScreen) { + return mejs.i18n.t('Turn off Fullscreen'); + } else { + return mejs.i18n.t('Go Fullscreen'); + } + }, + click: function(player) { + if (player.isFullScreen) { + player.exitFullScreen(); + } else { + player.enterFullScreen(); + } + } + } + , + // demo of a mute/unmute button + { + render: function(player) { + if (player.media.muted) { + return mejs.i18n.t('Unmute'); + } else { + return mejs.i18n.t('Mute'); + } + }, + click: function(player) { + if (player.media.muted) { + player.setMuted(false); + } else { + player.setMuted(true); + } + } + }, + // separator + { + isSeparator: true + } + , + // demo of simple download video + { + render: function(player) { + return mejs.i18n.t('Download Video'); + }, + click: function(player) { + window.location.href = player.media.currentSrc; + } + } + ]} +); + + + $.extend(MediaElementPlayer.prototype, { + buildcontextmenu: function(player, controls, layers, media) { + + // create context menu + player.contextMenu = $('<div class="mejs-contextmenu"></div>') + .appendTo($('body')) + .hide(); + + // create events for showing context menu + player.container.bind('contextmenu', function(e) { + if (player.isContextMenuEnabled) { + e.preventDefault(); + player.renderContextMenu(e.clientX-1, e.clientY-1); + return false; + } + }); + player.container.bind('click', function() { + player.contextMenu.hide(); + }); + player.contextMenu.bind('mouseleave', function() { + + //console.log('context hover out'); + player.startContextMenuTimer(); + + }); + }, + + cleancontextmenu: function(player) { + player.contextMenu.remove(); + }, + + isContextMenuEnabled: true, + enableContextMenu: function() { + this.isContextMenuEnabled = true; + }, + disableContextMenu: function() { + this.isContextMenuEnabled = false; + }, + + contextMenuTimeout: null, + startContextMenuTimer: function() { + //console.log('startContextMenuTimer'); + + var t = this; + + t.killContextMenuTimer(); + + t.contextMenuTimer = setTimeout(function() { + t.hideContextMenu(); + t.killContextMenuTimer(); + }, 750); + }, + killContextMenuTimer: function() { + var timer = this.contextMenuTimer; + + //console.log('killContextMenuTimer', timer); + + if (timer != null) { + clearTimeout(timer); + delete timer; + timer = null; + } + }, + + hideContextMenu: function() { + this.contextMenu.hide(); + }, + + renderContextMenu: function(x,y) { + + // alway re-render the items so that things like "turn fullscreen on" and "turn fullscreen off" are always written correctly + var t = this, + html = '', + items = t.options.contextMenuItems; + + for (var i=0, il=items.length; i<il; i++) { + + if (items[i].isSeparator) { + html += '<div class="mejs-contextmenu-separator"></div>'; + } else { + + var rendered = items[i].render(t); + + // render can return null if the item doesn't need to be used at the moment + if (rendered != null) { + html += '<div class="mejs-contextmenu-item" data-itemindex="' + i + '" id="element-' + (Math.random()*1000000) + '">' + rendered + '</div>'; + } + } + } + + // position and show the context menu + t.contextMenu + .empty() + .append($(html)) + .css({top:y, left:x}) + .show(); + + // bind events + t.contextMenu.find('.mejs-contextmenu-item').each(function() { + + // which one is this? + var $dom = $(this), + itemIndex = parseInt( $dom.data('itemindex'), 10 ), + item = t.options.contextMenuItems[itemIndex]; + + // bind extra functionality? + if (typeof item.show != 'undefined') + item.show( $dom , t); + + // bind click action + $dom.click(function() { + // perform click action + if (typeof item.click != 'undefined') + item.click(t); + + // close + t.contextMenu.hide(); + }); + }); + + // stop the controls from hiding + setTimeout(function() { + t.killControlsTimer('rev3'); + }, 100); + + } + }); + +})(mejs.$); +/** + * Postroll plugin + */ +(function($) { + + $.extend(mejs.MepDefaults, { + postrollCloseText: mejs.i18n.t('Close') + }); + + // Postroll + $.extend(MediaElementPlayer.prototype, { + buildpostroll: function(player, controls, layers, media) { + var + t = this, + postrollLink = t.container.find('link[rel="postroll"]').attr('href'); + + if (typeof postrollLink !== 'undefined') { + player.postroll = + $('<div class="mejs-postroll-layer mejs-layer"><a class="mejs-postroll-close" onclick="$(this).parent().hide();return false;">' + t.options.postrollCloseText + '</a><div class="mejs-postroll-layer-content"></div></div>').prependTo(layers).hide(); + + t.media.addEventListener('ended', function (e) { + $.ajax({ + dataType: 'html', + url: postrollLink, + success: function (data, textStatus) { + layers.find('.mejs-postroll-layer-content').html(data); + } + }); + player.postroll.show(); + }, false); + } + } + }); + +})(mejs.$); + diff --git a/src/static/mediaelement/mediaelement-and-player.min.js b/src/static/mediaelement/mediaelement-and-player.min.js new file mode 100755 index 0000000..64550a4 --- /dev/null +++ b/src/static/mediaelement/mediaelement-and-player.min.js @@ -0,0 +1,172 @@ +/*! +* MediaElement.js +* HTML5 <video> and <audio> shim and player +* http://mediaelementjs.com/ +* +* Creates a JavaScript object that mimics HTML5 MediaElement API +* for browsers that don't understand HTML5 or can't play the provided codec +* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3 +* +* Copyright 2010-2013, John Dyer (http://j.hn) +* License: MIT +* +*/var mejs=mejs||{};mejs.version="2.12.0";mejs.meIndex=0; +mejs.plugins={silverlight:[{version:[3,0],types:["video/mp4","video/m4v","video/mov","video/wmv","audio/wma","audio/m4a","audio/mp3","audio/wav","audio/mpeg"]}],flash:[{version:[9,0,124],types:["video/mp4","video/m4v","video/mov","video/flv","video/rtmp","video/x-flv","audio/flv","audio/x-flv","audio/mp3","audio/m4a","audio/mpeg","video/youtube","video/x-youtube"]}],youtube:[{version:null,types:["video/youtube","video/x-youtube","audio/youtube","audio/x-youtube"]}],vimeo:[{version:null,types:["video/vimeo", +"video/x-vimeo"]}]}; +mejs.Utility={encodeUrl:function(a){return encodeURIComponent(a)},escapeHTML:function(a){return a.toString().split("&").join("&amp;").split("<").join("&lt;").split('"').join("&quot;")},absolutizeUrl:function(a){var b=document.createElement("div");b.innerHTML='<a href="'+this.escapeHTML(a)+'">x</a>';return b.firstChild.href},getScriptPath:function(a){for(var b=0,c,d="",e="",f,g,h=document.getElementsByTagName("script"),l=h.length,j=a.length;b<l;b++){f=h[b].src;c=f.lastIndexOf("/");if(c>-1){g=f.substring(c+ +1);f=f.substring(0,c+1)}else{g=f;f=""}for(c=0;c<j;c++){e=a[c];e=g.indexOf(e);if(e>-1){d=f;break}}if(d!=="")break}return d},secondsToTimeCode:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d=="undefined")d=25;var e=Math.floor(a/3600)%24,f=Math.floor(a/60)%60,g=Math.floor(a%60);a=Math.floor((a%1*d).toFixed(3));return(b||e>0?(e<10?"0"+e:e)+":":"")+(f<10?"0"+f:f)+":"+(g<10?"0"+g:g)+(c?":"+(a<10?"0"+a:a):"")},timeCodeToSeconds:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d== +"undefined")d=25;a=a.split(":");b=parseInt(a[0],10);var e=parseInt(a[1],10),f=parseInt(a[2],10),g=0,h=0;if(c)g=parseInt(a[3])/d;return h=b*3600+e*60+f+g},convertSMPTEtoSeconds:function(a){if(typeof a!="string")return false;a=a.replace(",",".");var b=0,c=a.indexOf(".")!=-1?a.split(".")[1].length:0,d=1;a=a.split(":").reverse();for(var e=0;e<a.length;e++){d=1;if(e>0)d=Math.pow(60,e);b+=Number(a[e])*d}return Number(b.toFixed(c))},removeSwf:function(a){var b=document.getElementById(a);if(b&&/object|embed/i.test(b.nodeName))if(mejs.MediaFeatures.isIE){b.style.display= +"none";(function(){b.readyState==4?mejs.Utility.removeObjectInIE(a):setTimeout(arguments.callee,10)})()}else b.parentNode.removeChild(b)},removeObjectInIE:function(a){if(a=document.getElementById(a)){for(var b in a)if(typeof a[b]=="function")a[b]=null;a.parentNode.removeChild(a)}}}; +mejs.PluginDetector={hasPluginVersion:function(a,b){var c=this.plugins[a];b[1]=b[1]||0;b[2]=b[2]||0;return c[0]>b[0]||c[0]==b[0]&&c[1]>b[1]||c[0]==b[0]&&c[1]==b[1]&&c[2]>=b[2]?true:false},nav:window.navigator,ua:window.navigator.userAgent.toLowerCase(),plugins:[],addPlugin:function(a,b,c,d,e){this.plugins[a]=this.detectPlugin(b,c,d,e)},detectPlugin:function(a,b,c,d){var e=[0,0,0],f;if(typeof this.nav.plugins!="undefined"&&typeof this.nav.plugins[a]=="object"){if((c=this.nav.plugins[a].description)&& +!(typeof this.nav.mimeTypes!="undefined"&&this.nav.mimeTypes[b]&&!this.nav.mimeTypes[b].enabledPlugin)){e=c.replace(a,"").replace(/^\s+/,"").replace(/\sr/gi,".").split(".");for(a=0;a<e.length;a++)e[a]=parseInt(e[a].match(/\d+/),10)}}else if(typeof window.ActiveXObject!="undefined")try{if(f=new ActiveXObject(c))e=d(f)}catch(g){}return e}}; +mejs.PluginDetector.addPlugin("flash","Shockwave Flash","application/x-shockwave-flash","ShockwaveFlash.ShockwaveFlash",function(a){var b=[];if(a=a.GetVariable("$version")){a=a.split(" ")[1].split(",");b=[parseInt(a[0],10),parseInt(a[1],10),parseInt(a[2],10)]}return b}); +mejs.PluginDetector.addPlugin("silverlight","Silverlight Plug-In","application/x-silverlight-2","AgControl.AgControl",function(a){var b=[0,0,0,0],c=function(d,e,f,g){for(;d.isVersionSupported(e[0]+"."+e[1]+"."+e[2]+"."+e[3]);)e[f]+=g;e[f]-=g};c(a,b,0,1);c(a,b,1,1);c(a,b,2,1E4);c(a,b,2,1E3);c(a,b,2,100);c(a,b,2,10);c(a,b,2,1);c(a,b,3,1);return b}); +mejs.MediaFeatures={init:function(){var a=this,b=document,c=mejs.PluginDetector.nav,d=mejs.PluginDetector.ua.toLowerCase(),e,f=["source","track","audio","video"];a.isiPad=d.match(/ipad/i)!==null;a.isiPhone=d.match(/iphone/i)!==null;a.isiOS=a.isiPhone||a.isiPad;a.isAndroid=d.match(/android/i)!==null;a.isBustedAndroid=d.match(/android 2\.[12]/)!==null;a.isBustedNativeHTTPS=location.protocol==="https:"&&(d.match(/android [12]\./)!==null||d.match(/macintosh.* version.* safari/)!==null);a.isIE=c.appName.toLowerCase().indexOf("microsoft")!= +-1;a.isChrome=d.match(/chrome/gi)!==null;a.isFirefox=d.match(/firefox/gi)!==null;a.isWebkit=d.match(/webkit/gi)!==null;a.isGecko=d.match(/gecko/gi)!==null&&!a.isWebkit;a.isOpera=d.match(/opera/gi)!==null;a.hasTouch="ontouchstart"in window;a.svg=!!document.createElementNS&&!!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect;for(c=0;c<f.length;c++)e=document.createElement(f[c]);a.supportsMediaTag=typeof e.canPlayType!=="undefined"||a.isBustedAndroid;try{e.canPlayType("video/mp4")}catch(g){a.supportsMediaTag= +false}a.hasSemiNativeFullScreen=typeof e.webkitEnterFullscreen!=="undefined";a.hasWebkitNativeFullScreen=typeof e.webkitRequestFullScreen!=="undefined";a.hasMozNativeFullScreen=typeof e.mozRequestFullScreen!=="undefined";a.hasTrueNativeFullScreen=a.hasWebkitNativeFullScreen||a.hasMozNativeFullScreen;a.nativeFullScreenEnabled=a.hasTrueNativeFullScreen;if(a.hasMozNativeFullScreen)a.nativeFullScreenEnabled=e.mozFullScreenEnabled;if(this.isChrome)a.hasSemiNativeFullScreen=false;if(a.hasTrueNativeFullScreen){a.fullScreenEventName= +a.hasWebkitNativeFullScreen?"webkitfullscreenchange":"mozfullscreenchange";a.isFullScreen=function(){if(e.mozRequestFullScreen)return b.mozFullScreen;else if(e.webkitRequestFullScreen)return b.webkitIsFullScreen};a.requestFullScreen=function(h){if(a.hasWebkitNativeFullScreen)h.webkitRequestFullScreen();else a.hasMozNativeFullScreen&&h.mozRequestFullScreen()};a.cancelFullScreen=function(){if(a.hasWebkitNativeFullScreen)document.webkitCancelFullScreen();else a.hasMozNativeFullScreen&&document.mozCancelFullScreen()}}if(a.hasSemiNativeFullScreen&& +d.match(/mac os x 10_5/i)){a.hasNativeFullScreen=false;a.hasSemiNativeFullScreen=false}}};mejs.MediaFeatures.init(); +mejs.HtmlMediaElement={pluginType:"native",isFullScreen:false,setCurrentTime:function(a){this.currentTime=a},setMuted:function(a){this.muted=a},setVolume:function(a){this.volume=a},stop:function(){this.pause()},setSrc:function(a){for(var b=this.getElementsByTagName("source");b.length>0;)this.removeChild(b[0]);if(typeof a=="string")this.src=a;else{var c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type)){this.src=c.src;break}}}},setVideoSize:function(a,b){this.width=a;this.height=b}}; +mejs.PluginMediaElement=function(a,b,c){this.id=a;this.pluginType=b;this.src=c;this.events={};this.attributes={}}; +mejs.PluginMediaElement.prototype={pluginElement:null,pluginType:"",isFullScreen:false,playbackRate:-1,defaultPlaybackRate:-1,seekable:[],played:[],paused:true,ended:false,seeking:false,duration:0,error:null,tagName:"",muted:false,volume:1,currentTime:0,play:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.playVideo():this.pluginApi.playMedia();this.paused=false}},load:function(){if(this.pluginApi!=null){this.pluginType!="youtube"&&this.pluginApi.loadMedia();this.paused= +false}},pause:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.pauseVideo():this.pluginApi.pauseMedia();this.paused=true}},stop:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.stopVideo():this.pluginApi.stopMedia();this.paused=true}},canPlayType:function(a){var b,c,d,e=mejs.plugins[this.pluginType];for(b=0;b<e.length;b++){d=e[b];if(mejs.PluginDetector.hasPluginVersion(this.pluginType,d.version))for(c=0;c<d.types.length;c++)if(a==d.types[c])return"probably"}return""}, +positionFullscreenButton:function(a,b,c){this.pluginApi!=null&&this.pluginApi.positionFullscreenButton&&this.pluginApi.positionFullscreenButton(Math.floor(a),Math.floor(b),c)},hideFullscreenButton:function(){this.pluginApi!=null&&this.pluginApi.hideFullscreenButton&&this.pluginApi.hideFullscreenButton()},setSrc:function(a){if(typeof a=="string"){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(a));this.src=mejs.Utility.absolutizeUrl(a)}else{var b,c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type)){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(c.src)); +this.src=mejs.Utility.absolutizeUrl(a);break}}}},setCurrentTime:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.seekTo(a):this.pluginApi.setCurrentTime(a);this.currentTime=a}},setVolume:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.setVolume(a*100):this.pluginApi.setVolume(a);this.volume=a}},setMuted:function(a){if(this.pluginApi!=null){if(this.pluginType=="youtube"){a?this.pluginApi.mute():this.pluginApi.unMute();this.muted=a;this.dispatchEvent("volumechange")}else this.pluginApi.setMuted(a); +this.muted=a}},setVideoSize:function(a,b){if(this.pluginElement.style){this.pluginElement.style.width=a+"px";this.pluginElement.style.height=b+"px"}this.pluginApi!=null&&this.pluginApi.setVideoSize&&this.pluginApi.setVideoSize(a,b)},setFullscreen:function(a){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.pluginApi.setFullscreen(a)},enterFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.setFullscreen(true)},exitFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&& +this.setFullscreen(false)},addEventListener:function(a,b){this.events[a]=this.events[a]||[];this.events[a].push(b)},removeEventListener:function(a,b){if(!a){this.events={};return true}var c=this.events[a];if(!c)return true;if(!b){this.events[a]=[];return true}for(i=0;i<c.length;i++)if(c[i]===b){this.events[a].splice(i,1);return true}return false},dispatchEvent:function(a){var b,c,d=this.events[a];if(d){c=Array.prototype.slice.call(arguments,1);for(b=0;b<d.length;b++)d[b].apply(null,c)}},hasAttribute:function(a){return a in +this.attributes},removeAttribute:function(a){delete this.attributes[a]},getAttribute:function(a){if(this.hasAttribute(a))return this.attributes[a];return""},setAttribute:function(a,b){this.attributes[a]=b},remove:function(){mejs.Utility.removeSwf(this.pluginElement.id);mejs.MediaPluginBridge.unregisterPluginElement(this.pluginElement.id)}}; +mejs.MediaPluginBridge={pluginMediaElements:{},htmlMediaElements:{},registerPluginElement:function(a,b,c){this.pluginMediaElements[a]=b;this.htmlMediaElements[a]=c},unregisterPluginElement:function(a){delete this.pluginMediaElements[a];delete this.htmlMediaElements[a]},initPlugin:function(a){var b=this.pluginMediaElements[a],c=this.htmlMediaElements[a];if(b){switch(b.pluginType){case "flash":b.pluginElement=b.pluginApi=document.getElementById(a);break;case "silverlight":b.pluginElement=document.getElementById(b.id); +b.pluginApi=b.pluginElement.Content.MediaElementJS}b.pluginApi!=null&&b.success&&b.success(b,c)}},fireEvent:function(a,b,c){var d,e;a=this.pluginMediaElements[a];b={type:b,target:a};for(d in c){a[d]=c[d];b[d]=c[d]}e=c.bufferedTime||0;b.target.buffered=b.buffered={start:function(){return 0},end:function(){return e},length:1};a.dispatchEvent(b.type,b)}}; +mejs.MediaElementDefaults={mode:"auto",plugins:["flash","silverlight","youtube","vimeo"],enablePluginDebug:false,type:"",pluginPath:mejs.Utility.getScriptPath(["mediaelement.js","mediaelement.min.js","mediaelement-and-player.js","mediaelement-and-player.min.js"]),flashName:"flashmediaelement.swf",flashStreamer:"",enablePluginSmoothing:false,enablePseudoStreaming:false,pseudoStreamingStartQueryParam:"start",silverlightName:"silverlightmediaelement.xap",defaultVideoWidth:480,defaultVideoHeight:270, +pluginWidth:-1,pluginHeight:-1,pluginVars:[],timerRate:250,startVolume:0.8,success:function(){},error:function(){}};mejs.MediaElement=function(a,b){return mejs.HtmlMediaElementShim.create(a,b)}; +mejs.HtmlMediaElementShim={create:function(a,b){var c=mejs.MediaElementDefaults,d=typeof a=="string"?document.getElementById(a):a,e=d.tagName.toLowerCase(),f=e==="audio"||e==="video",g=f?d.getAttribute("src"):d.getAttribute("href");e=d.getAttribute("poster");var h=d.getAttribute("autoplay"),l=d.getAttribute("preload"),j=d.getAttribute("controls"),k;for(k in b)c[k]=b[k];g=typeof g=="undefined"||g===null||g==""?null:g;e=typeof e=="undefined"||e===null?"":e;l=typeof l=="undefined"||l===null||l==="false"? +"none":l;h=!(typeof h=="undefined"||h===null||h==="false");j=!(typeof j=="undefined"||j===null||j==="false");k=this.determinePlayback(d,c,mejs.MediaFeatures.supportsMediaTag,f,g);k.url=k.url!==null?mejs.Utility.absolutizeUrl(k.url):"";if(k.method=="native"){if(mejs.MediaFeatures.isBustedAndroid){d.src=k.url;d.addEventListener("click",function(){d.play()},false)}return this.updateNative(k,c,h,l)}else if(k.method!=="")return this.createPlugin(k,c,e,h,l,j);else{this.createErrorMessage(k,c,e);return this}}, +determinePlayback:function(a,b,c,d,e){var f=[],g,h,l,j={method:"",url:"",htmlMediaElement:a,isVideo:a.tagName.toLowerCase()!="audio"},k;if(typeof b.type!="undefined"&&b.type!=="")if(typeof b.type=="string")f.push({type:b.type,url:e});else for(g=0;g<b.type.length;g++)f.push({type:b.type[g],url:e});else if(e!==null){l=this.formatType(e,a.getAttribute("type"));f.push({type:l,url:e})}else for(g=0;g<a.childNodes.length;g++){h=a.childNodes[g];if(h.nodeType==1&&h.tagName.toLowerCase()=="source"){e=h.getAttribute("src"); +l=this.formatType(e,h.getAttribute("type"));h=h.getAttribute("media");if(!h||!window.matchMedia||window.matchMedia&&window.matchMedia(h).matches)f.push({type:l,url:e})}}if(!d&&f.length>0&&f[0].url!==null&&this.getTypeFromFile(f[0].url).indexOf("audio")>-1)j.isVideo=false;if(mejs.MediaFeatures.isBustedAndroid)a.canPlayType=function(m){return m.match(/video\/(mp4|m4v)/gi)!==null?"maybe":""};if(c&&(b.mode==="auto"||b.mode==="auto_plugin"||b.mode==="native")&&!mejs.MediaFeatures.isBustedNativeHTTPS){if(!d){g= +document.createElement(j.isVideo?"video":"audio");a.parentNode.insertBefore(g,a);a.style.display="none";j.htmlMediaElement=a=g}for(g=0;g<f.length;g++)if(a.canPlayType(f[g].type).replace(/no/,"")!==""||a.canPlayType(f[g].type.replace(/mp3/,"mpeg")).replace(/no/,"")!==""){j.method="native";j.url=f[g].url;break}if(j.method==="native"){if(j.url!==null)a.src=j.url;if(b.mode!=="auto_plugin")return j}}if(b.mode==="auto"||b.mode==="auto_plugin"||b.mode==="shim")for(g=0;g<f.length;g++){l=f[g].type;for(a=0;a< +b.plugins.length;a++){e=b.plugins[a];h=mejs.plugins[e];for(c=0;c<h.length;c++){k=h[c];if(k.version==null||mejs.PluginDetector.hasPluginVersion(e,k.version))for(d=0;d<k.types.length;d++)if(l==k.types[d]){j.method=e;j.url=f[g].url;return j}}}}if(b.mode==="auto_plugin"&&j.method==="native")return j;if(j.method===""&&f.length>0)j.url=f[0].url;return j},formatType:function(a,b){return a&&!b?this.getTypeFromFile(a):b&&~b.indexOf(";")?b.substr(0,b.indexOf(";")):b},getTypeFromFile:function(a){a=a.split("?")[0]; +a=a.substring(a.lastIndexOf(".")+1).toLowerCase();return(/(mp4|m4v|ogg|ogv|webm|webmv|flv|wmv|mpeg|mov)/gi.test(a)?"video":"audio")+"/"+this.getTypeFromExtension(a)},getTypeFromExtension:function(a){switch(a){case "mp4":case "m4v":return"mp4";case "webm":case "webma":case "webmv":return"webm";case "ogg":case "oga":case "ogv":return"ogg";default:return a}},createErrorMessage:function(a,b,c){var d=a.htmlMediaElement,e=document.createElement("div");e.className="me-cannotplay";try{e.style.width=d.width+ +"px";e.style.height=d.height+"px"}catch(f){}e.innerHTML=b.customError?b.customError:c!==""?'<a href="'+a.url+'"><img src="'+c+'" width="100%" height="100%" /></a>':'<a href="'+a.url+'"><span>'+mejs.i18n.t("Download File")+"</span></a>";d.parentNode.insertBefore(e,d);d.style.display="none";b.error(d)},createPlugin:function(a,b,c,d,e,f){c=a.htmlMediaElement;var g=1,h=1,l="me_"+a.method+"_"+mejs.meIndex++,j=new mejs.PluginMediaElement(l,a.method,a.url),k=document.createElement("div"),m;j.tagName=c.tagName; +for(m=0;m<c.attributes.length;m++){var n=c.attributes[m];n.specified==true&&j.setAttribute(n.name,n.value)}for(m=c.parentNode;m!==null&&m.tagName.toLowerCase()!="body";){if(m.parentNode.tagName.toLowerCase()=="p"){m.parentNode.parentNode.insertBefore(m,m.parentNode);break}m=m.parentNode}if(a.isVideo){g=b.pluginWidth>0?b.pluginWidth:b.videoWidth>0?b.videoWidth:c.getAttribute("width")!==null?c.getAttribute("width"):b.defaultVideoWidth;h=b.pluginHeight>0?b.pluginHeight:b.videoHeight>0?b.videoHeight: +c.getAttribute("height")!==null?c.getAttribute("height"):b.defaultVideoHeight;g=mejs.Utility.encodeUrl(g);h=mejs.Utility.encodeUrl(h)}else if(b.enablePluginDebug){g=320;h=240}j.success=b.success;mejs.MediaPluginBridge.registerPluginElement(l,j,c);k.className="me-plugin";k.id=l+"_container";a.isVideo?c.parentNode.insertBefore(k,c):document.body.insertBefore(k,document.body.childNodes[0]);d=["id="+l,"isvideo="+(a.isVideo?"true":"false"),"autoplay="+(d?"true":"false"),"preload="+e,"width="+g,"startvolume="+ +b.startVolume,"timerrate="+b.timerRate,"flashstreamer="+b.flashStreamer,"height="+h,"pseudostreamstart="+b.pseudoStreamingStartQueryParam];if(a.url!==null)a.method=="flash"?d.push("file="+mejs.Utility.encodeUrl(a.url)):d.push("file="+a.url);b.enablePluginDebug&&d.push("debug=true");b.enablePluginSmoothing&&d.push("smoothing=true");b.enablePseudoStreaming&&d.push("pseudostreaming=true");f&&d.push("controls=true");if(b.pluginVars)d=d.concat(b.pluginVars);switch(a.method){case "silverlight":k.innerHTML= +'<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="'+l+'" name="'+l+'" width="'+g+'" height="'+h+'" class="mejs-shim"><param name="initParams" value="'+d.join(",")+'" /><param name="windowless" value="true" /><param name="background" value="black" /><param name="minRuntimeVersion" value="3.0.0.0" /><param name="autoUpgrade" value="true" /><param name="source" value="'+b.pluginPath+b.silverlightName+'" /></object>';break;case "flash":if(mejs.MediaFeatures.isIE){a= +document.createElement("div");k.appendChild(a);a.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+l+'" width="'+g+'" height="'+h+'" class="mejs-shim"><param name="movie" value="'+b.pluginPath+b.flashName+"?x="+new Date+'" /><param name="flashvars" value="'+d.join("&amp;")+'" /><param name="quality" value="high" /><param name="bgcolor" value="#000000" /><param name="wmode" value="transparent" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /></object>'}else k.innerHTML= +'<embed id="'+l+'" name="'+l+'" play="true" loop="false" quality="high" bgcolor="#000000" wmode="transparent" allowScriptAccess="always" allowFullScreen="true" type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" src="'+b.pluginPath+b.flashName+'" flashvars="'+d.join("&")+'" width="'+g+'" height="'+h+'" class="mejs-shim"></embed>';break;case "youtube":b=a.url.substr(a.url.lastIndexOf("=")+1);youtubeSettings={container:k,containerId:k.id,pluginMediaElement:j,pluginId:l, +videoId:b,height:h,width:g};mejs.PluginDetector.hasPluginVersion("flash",[10,0,0])?mejs.YouTubeApi.createFlash(youtubeSettings):mejs.YouTubeApi.enqueueIframe(youtubeSettings);break;case "vimeo":j.vimeoid=a.url.substr(a.url.lastIndexOf("/")+1);k.innerHTML='<iframe src="http://player.vimeo.com/video/'+j.vimeoid+'?portrait=0&byline=0&title=0" width="'+g+'" height="'+h+'" frameborder="0" class="mejs-shim"></iframe>'}c.style.display="none";return j},updateNative:function(a,b){var c=a.htmlMediaElement, +d;for(d in mejs.HtmlMediaElement)c[d]=mejs.HtmlMediaElement[d];b.success(c,c);return c}}; +mejs.YouTubeApi={isIframeStarted:false,isIframeLoaded:false,loadIframeApi:function(){if(!this.isIframeStarted){var a=document.createElement("script");a.src="//www.youtube.com/player_api";var b=document.getElementsByTagName("script")[0];b.parentNode.insertBefore(a,b);this.isIframeStarted=true}},iframeQueue:[],enqueueIframe:function(a){if(this.isLoaded)this.createIframe(a);else{this.loadIframeApi();this.iframeQueue.push(a)}},createIframe:function(a){var b=a.pluginMediaElement,c=new YT.Player(a.containerId, +{height:a.height,width:a.width,videoId:a.videoId,playerVars:{controls:0},events:{onReady:function(){a.pluginMediaElement.pluginApi=c;mejs.MediaPluginBridge.initPlugin(a.pluginId);setInterval(function(){mejs.YouTubeApi.createEvent(c,b,"timeupdate")},250)},onStateChange:function(d){mejs.YouTubeApi.handleStateChange(d.data,c,b)}}})},createEvent:function(a,b,c){c={type:c,target:b};if(a&&a.getDuration){b.currentTime=c.currentTime=a.getCurrentTime();b.duration=c.duration=a.getDuration();c.paused=b.paused; +c.ended=b.ended;c.muted=a.isMuted();c.volume=a.getVolume()/100;c.bytesTotal=a.getVideoBytesTotal();c.bufferedBytes=a.getVideoBytesLoaded();var d=c.bufferedBytes/c.bytesTotal*c.duration;c.target.buffered=c.buffered={start:function(){return 0},end:function(){return d},length:1}}b.dispatchEvent(c.type,c)},iFrameReady:function(){for(this.isIframeLoaded=this.isLoaded=true;this.iframeQueue.length>0;)this.createIframe(this.iframeQueue.pop())},flashPlayers:{},createFlash:function(a){this.flashPlayers[a.pluginId]= +a;var b,c="//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid="+a.pluginId+"&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0";if(mejs.MediaFeatures.isIE){b=document.createElement("div");a.container.appendChild(b);b.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+a.pluginId+'" width="'+a.width+'" height="'+a.height+'" class="mejs-shim"><param name="movie" value="'+ +c+'" /><param name="wmode" value="transparent" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /></object>'}else a.container.innerHTML='<object type="application/x-shockwave-flash" id="'+a.pluginId+'" data="'+c+'" width="'+a.width+'" height="'+a.height+'" style="visibility: visible; " class="mejs-shim"><param name="allowScriptAccess" value="always"><param name="wmode" value="transparent"></object>'},flashReady:function(a){var b=this.flashPlayers[a],c= +document.getElementById(a),d=b.pluginMediaElement;d.pluginApi=d.pluginElement=c;mejs.MediaPluginBridge.initPlugin(a);c.cueVideoById(b.videoId);a=b.containerId+"_callback";window[a]=function(e){mejs.YouTubeApi.handleStateChange(e,c,d)};c.addEventListener("onStateChange",a);setInterval(function(){mejs.YouTubeApi.createEvent(c,d,"timeupdate")},250)},handleStateChange:function(a,b,c){switch(a){case -1:c.paused=true;c.ended=true;mejs.YouTubeApi.createEvent(b,c,"loadedmetadata");break;case 0:c.paused=false; +c.ended=true;mejs.YouTubeApi.createEvent(b,c,"ended");break;case 1:c.paused=false;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"play");mejs.YouTubeApi.createEvent(b,c,"playing");break;case 2:c.paused=true;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"pause");break;case 3:mejs.YouTubeApi.createEvent(b,c,"progress")}}};function onYouTubePlayerAPIReady(){mejs.YouTubeApi.iFrameReady()}function onYouTubePlayerReady(a){mejs.YouTubeApi.flashReady(a)}window.mejs=mejs;window.MediaElement=mejs.MediaElement; +(function(a,b){var c={locale:{strings:{}},methods:{}};c.locale.getLanguage=function(){return c.locale||{language:navigator.language}};c.locale.INIT_LANGUAGE=c.locale.getLanguage();c.methods.checkPlain=function(d){var e,f,g={"&":"&amp;",'"':"&quot;","<":"&lt;",">":"&gt;"};d=String(d);for(e in g)if(g.hasOwnProperty(e)){f=RegExp(e,"g");d=d.replace(f,g[e])}return d};c.methods.formatString=function(d,e){for(var f in e){switch(f.charAt(0)){case "@":e[f]=c.methods.checkPlain(e[f]);break;case "!":break;default:e[f]= +'<em class="placeholder">'+c.methods.checkPlain(e[f])+"</em>"}d=d.replace(f,e[f])}return d};c.methods.t=function(d,e,f){if(c.locale.strings&&c.locale.strings[f.context]&&c.locale.strings[f.context][d])d=c.locale.strings[f.context][d];if(e)d=c.methods.formatString(d,e);return d};c.t=function(d,e,f){if(typeof d==="string"&&d.length>0){var g=c.locale.getLanguage();f=f||{context:g.language};return c.methods.t(d,e,f)}else throw{name:"InvalidArgumentException",message:"First argument is either not a string or empty."}; +};b.i18n=c})(document,mejs);(function(a){if(mejs.i18n.locale.language&&mejs.i18n.locale.strings)a[mejs.i18n.locale.language]=mejs.i18n.locale.strings})(mejs.i18n.locale.strings);(function(a){a.de={Fullscreen:"Vollbild","Go Fullscreen":"Vollbild an","Turn off Fullscreen":"Vollbild aus",Close:"Schlie\u00dfen"}})(mejs.i18n.locale.strings);(function(a){a.zh={Fullscreen:"\u5168\u87a2\u5e55","Go Fullscreen":"\u5168\u5c4f\u6a21\u5f0f","Turn off Fullscreen":"\u9000\u51fa\u5168\u5c4f\u6a21\u5f0f",Close:"\u95dc\u9589"}})(mejs.i18n.locale.strings); + +/*! + * MediaElementPlayer + * http://mediaelementjs.com/ + * + * Creates a controller bar for HTML5 <video> add <audio> tags + * using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper) + * + * Copyright 2010-2013, John Dyer (http://j.hn/) + * License: MIT + * + */if(typeof jQuery!="undefined")mejs.$=jQuery;else if(typeof ender!="undefined")mejs.$=ender; +(function(f){mejs.MepDefaults={poster:"",defaultVideoWidth:480,defaultVideoHeight:270,videoWidth:-1,videoHeight:-1,defaultAudioWidth:400,defaultAudioHeight:30,defaultSeekBackwardInterval:function(a){return a.duration*0.05},defaultSeekForwardInterval:function(a){return a.duration*0.05},audioWidth:-1,audioHeight:-1,startVolume:0.8,loop:false,autoRewind:true,enableAutosize:true,alwaysShowHours:false,showTimecodeFrameCount:false,framesPerSecond:25,autosizeProgress:true,alwaysShowControls:false,hideVideoControlsOnLoad:false, +clickToPlayPause:true,iPadUseNativeControls:false,iPhoneUseNativeControls:false,AndroidUseNativeControls:false,features:["playpause","current","progress","duration","tracks","volume","fullscreen"],isVideo:true,enableKeyboard:true,pauseOtherPlayers:true,keyActions:[{keys:[32,179],action:function(a,b){b.paused||b.ended?b.play():b.pause()}},{keys:[38],action:function(a,b){b.setVolume(Math.min(b.volume+0.1,1))}},{keys:[40],action:function(a,b){b.setVolume(Math.max(b.volume-0.1,0))}},{keys:[37,227],action:function(a, +b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}var c=Math.max(b.currentTime-a.options.defaultSeekBackwardInterval(b),0);b.setCurrentTime(c)}}},{keys:[39,228],action:function(a,b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}var c=Math.min(b.currentTime+a.options.defaultSeekForwardInterval(b),b.duration);b.setCurrentTime(c)}}},{keys:[70],action:function(a){if(typeof a.enterFullScreen!="undefined")a.isFullScreen? +a.exitFullScreen():a.enterFullScreen()}}]};mejs.mepIndex=0;mejs.players={};mejs.MediaElementPlayer=function(a,b){if(!(this instanceof mejs.MediaElementPlayer))return new mejs.MediaElementPlayer(a,b);this.$media=this.$node=f(a);this.node=this.media=this.$media[0];if(typeof this.node.player!="undefined")return this.node.player;else this.node.player=this;if(typeof b=="undefined")b=this.$node.data("mejsoptions");this.options=f.extend({},mejs.MepDefaults,b);this.id="mep_"+mejs.mepIndex++;mejs.players[this.id]= +this;this.init();return this};mejs.MediaElementPlayer.prototype={hasFocus:false,controlsAreVisible:true,init:function(){var a=this,b=mejs.MediaFeatures,c=f.extend(true,{},a.options,{success:function(d,g){a.meReady(d,g)},error:function(d){a.handleError(d)}}),e=a.media.tagName.toLowerCase();a.isDynamic=e!=="audio"&&e!=="video";a.isVideo=a.isDynamic?a.options.isVideo:e!=="audio"&&a.options.isVideo;if(b.isiPad&&a.options.iPadUseNativeControls||b.isiPhone&&a.options.iPhoneUseNativeControls){a.$media.attr("controls", +"controls");if(b.isiPad&&a.media.getAttribute("autoplay")!==null){a.media.load();a.media.play()}}else if(!(b.isAndroid&&a.options.AndroidUseNativeControls)){a.$media.removeAttr("controls");a.container=f('<div id="'+a.id+'" class="mejs-container '+(mejs.MediaFeatures.svg?"svg":"no-svg")+'"><div class="mejs-inner"><div class="mejs-mediaelement"></div><div class="mejs-layers"></div><div class="mejs-controls"></div><div class="mejs-clear"></div></div></div>').addClass(a.$media[0].className).insertBefore(a.$media); +a.container.addClass((b.isAndroid?"mejs-android ":"")+(b.isiOS?"mejs-ios ":"")+(b.isiPad?"mejs-ipad ":"")+(b.isiPhone?"mejs-iphone ":"")+(a.isVideo?"mejs-video ":"mejs-audio "));if(b.isiOS){b=a.$media.clone();a.container.find(".mejs-mediaelement").append(b);a.$media.remove();a.$node=a.$media=b;a.node=a.media=b[0]}else a.container.find(".mejs-mediaelement").append(a.$media);a.controls=a.container.find(".mejs-controls");a.layers=a.container.find(".mejs-layers");b=a.isVideo?"video":"audio";e=b.substring(0, +1).toUpperCase()+b.substring(1);a.width=a.options[b+"Width"]>0||a.options[b+"Width"].toString().indexOf("%")>-1?a.options[b+"Width"]:a.media.style.width!==""&&a.media.style.width!==null?a.media.style.width:a.media.getAttribute("width")!==null?a.$media.attr("width"):a.options["default"+e+"Width"];a.height=a.options[b+"Height"]>0||a.options[b+"Height"].toString().indexOf("%")>-1?a.options[b+"Height"]:a.media.style.height!==""&&a.media.style.height!==null?a.media.style.height:a.$media[0].getAttribute("height")!== +null?a.$media.attr("height"):a.options["default"+e+"Height"];a.setPlayerSize(a.width,a.height);c.pluginWidth=a.width;c.pluginHeight=a.height}mejs.MediaElement(a.$media[0],c);typeof a.container!="undefined"&&a.container.trigger("controlsshown")},showControls:function(a){var b=this;a=typeof a=="undefined"||a;if(!b.controlsAreVisible){if(a){b.controls.css("visibility","visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true;b.container.trigger("controlsshown")});b.container.find(".mejs-control").css("visibility", +"visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true})}else{b.controls.css("visibility","visible").css("display","block");b.container.find(".mejs-control").css("visibility","visible").css("display","block");b.controlsAreVisible=true;b.container.trigger("controlsshown")}b.setControlsSize()}},hideControls:function(a){var b=this;a=typeof a=="undefined"||a;if(b.controlsAreVisible)if(a){b.controls.stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display", +"block");b.controlsAreVisible=false;b.container.trigger("controlshidden")});b.container.find(".mejs-control").stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display","block")})}else{b.controls.css("visibility","hidden").css("display","block");b.container.find(".mejs-control").css("visibility","hidden").css("display","block");b.controlsAreVisible=false;b.container.trigger("controlshidden")}},controlsTimer:null,startControlsTimer:function(a){var b=this;a=typeof a!="undefined"? +a:1500;b.killControlsTimer("start");b.controlsTimer=setTimeout(function(){b.hideControls();b.killControlsTimer("hide")},a)},killControlsTimer:function(){if(this.controlsTimer!==null){clearTimeout(this.controlsTimer);delete this.controlsTimer;this.controlsTimer=null}},controlsEnabled:true,disableControls:function(){this.killControlsTimer();this.hideControls(false);this.controlsEnabled=false},enableControls:function(){this.showControls(false);this.controlsEnabled=true},meReady:function(a,b){var c=this, +e=mejs.MediaFeatures,d=b.getAttribute("autoplay");d=!(typeof d=="undefined"||d===null||d==="false");var g;if(!c.created){c.created=true;c.media=a;c.domNode=b;if(!(e.isAndroid&&c.options.AndroidUseNativeControls)&&!(e.isiPad&&c.options.iPadUseNativeControls)&&!(e.isiPhone&&c.options.iPhoneUseNativeControls)){c.buildposter(c,c.controls,c.layers,c.media);c.buildkeyboard(c,c.controls,c.layers,c.media);c.buildoverlays(c,c.controls,c.layers,c.media);c.findTracks();for(g in c.options.features){e=c.options.features[g]; +if(c["build"+e])try{c["build"+e](c,c.controls,c.layers,c.media)}catch(k){}}c.container.trigger("controlsready");c.setPlayerSize(c.width,c.height);c.setControlsSize();if(c.isVideo){if(mejs.MediaFeatures.hasTouch)c.$media.bind("touchstart",function(){if(c.controlsAreVisible)c.hideControls(false);else c.controlsEnabled&&c.showControls(false)});else{mejs.MediaElementPlayer.prototype.clickToPlayPauseCallback=function(){console.log("media clicked",c.media,c.media.paused);if(c.options.clickToPlayPause)c.media.paused? +c.media.play():c.media.pause()};c.media.addEventListener("click",c.clickToPlayPauseCallback);c.container.bind("mouseenter mouseover",function(){if(c.controlsEnabled)if(!c.options.alwaysShowControls){c.killControlsTimer("enter");c.showControls();c.startControlsTimer(2500)}}).bind("mousemove",function(){if(c.controlsEnabled){c.controlsAreVisible||c.showControls();c.options.alwaysShowControls||c.startControlsTimer(2500)}}).bind("mouseleave",function(){c.controlsEnabled&&!c.media.paused&&!c.options.alwaysShowControls&& +c.startControlsTimer(1E3)})}c.options.hideVideoControlsOnLoad&&c.hideControls(false);d&&!c.options.alwaysShowControls&&c.hideControls();c.options.enableAutosize&&c.media.addEventListener("loadedmetadata",function(j){if(c.options.videoHeight<=0&&c.domNode.getAttribute("height")===null&&!isNaN(j.target.videoHeight)){c.setPlayerSize(j.target.videoWidth,j.target.videoHeight);c.setControlsSize();c.media.setVideoSize(j.target.videoWidth,j.target.videoHeight)}},false)}a.addEventListener("play",function(){for(var j in mejs.players){var m= +mejs.players[j];m.id!=c.id&&c.options.pauseOtherPlayers&&!m.paused&&!m.ended&&m.pause();m.hasFocus=false}c.hasFocus=true},false);c.media.addEventListener("ended",function(){if(c.options.autoRewind)try{c.media.setCurrentTime(0)}catch(j){}c.media.pause();c.setProgressRail&&c.setProgressRail();c.setCurrentRail&&c.setCurrentRail();if(c.options.loop)c.media.play();else!c.options.alwaysShowControls&&c.controlsEnabled&&c.showControls()},false);c.media.addEventListener("loadedmetadata",function(){c.updateDuration&& +c.updateDuration();c.updateCurrent&&c.updateCurrent();if(!c.isFullScreen){c.setPlayerSize(c.width,c.height);c.setControlsSize()}},false);setTimeout(function(){c.setPlayerSize(c.width,c.height);c.setControlsSize()},50);c.globalBind("resize",function(){c.isFullScreen||mejs.MediaFeatures.hasTrueNativeFullScreen&&document.webkitIsFullScreen||c.setPlayerSize(c.width,c.height);c.setControlsSize()});c.media.pluginType=="youtube"&&c.container.find(".mejs-overlay-play").hide()}if(d&&a.pluginType=="native"){a.load(); +a.play()}if(c.options.success)typeof c.options.success=="string"?window[c.options.success](c.media,c.domNode,c):c.options.success(c.media,c.domNode,c)}},handleError:function(a){this.controls.hide();this.options.error&&this.options.error(a)},setPlayerSize:function(a,b){if(typeof a!="undefined")this.width=a;if(typeof b!="undefined")this.height=b;if(this.height.toString().indexOf("%")>0||this.$node.css("max-width")==="100%"||this.$node[0].currentStyle&&this.$node[0].currentStyle.maxWidth==="100%"){var c= +this.isVideo?this.media.videoWidth&&this.media.videoWidth>0?this.media.videoWidth:this.options.defaultVideoWidth:this.options.defaultAudioWidth,e=this.isVideo?this.media.videoHeight&&this.media.videoHeight>0?this.media.videoHeight:this.options.defaultVideoHeight:this.options.defaultAudioHeight,d=this.container.parent().closest(":visible").width();c=this.isVideo||!this.options.autosizeProgress?parseInt(d*e/c,10):e;if(this.container.parent()[0].tagName.toLowerCase()==="body"){d=f(window).width();c= +f(window).height()}if(c!=0&&d!=0){this.container.width(d).height(c);this.$media.add(this.container.find(".mejs-shim")).width("100%").height("100%");this.isVideo&&this.media.setVideoSize&&this.media.setVideoSize(d,c);this.layers.children(".mejs-layer").width("100%").height("100%")}}else{this.container.width(this.width).height(this.height);this.layers.children(".mejs-layer").width(this.width).height(this.height)}d=this.layers.find(".mejs-overlay-play");c=d.find(".mejs-overlay-button");d.height(this.container.height()- +this.controls.height());c.css("margin-top","-"+(c.height()/2-this.controls.height()/2).toString()+"px")},setControlsSize:function(){var a=0,b=0,c=this.controls.find(".mejs-time-rail"),e=this.controls.find(".mejs-time-total");this.controls.find(".mejs-time-current");this.controls.find(".mejs-time-loaded");var d=c.siblings();if(this.options&&!this.options.autosizeProgress)b=parseInt(c.css("width"));if(b===0||!b){d.each(function(){var g=f(this);if(g.css("position")!="absolute"&&g.is(":visible"))a+=f(this).outerWidth(true)}); +b=this.controls.width()-a-(c.outerWidth(true)-c.width())}c.width(b);e.width(b-(e.outerWidth(true)-e.width()));this.setProgressRail&&this.setProgressRail();this.setCurrentRail&&this.setCurrentRail()},buildposter:function(a,b,c,e){var d=f('<div class="mejs-poster mejs-layer"></div>').appendTo(c);b=a.$media.attr("poster");if(a.options.poster!=="")b=a.options.poster;b!==""&&b!=null?this.setPoster(b):d.hide();e.addEventListener("play",function(){d.hide()},false)},setPoster:function(a){var b=this.container.find(".mejs-poster"), +c=b.find("img");if(c.length==0)c=f('<img width="100%" height="100%" />').appendTo(b);c.attr("src",a);b.css({"background-image":"url("+a+")"})},buildoverlays:function(a,b,c,e){var d=this;if(a.isVideo){var g=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-loading"><span></span></div></div>').hide().appendTo(c),k=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-error"></div></div>').hide().appendTo(c),j=f('<div class="mejs-overlay mejs-layer mejs-overlay-play"><div class="mejs-overlay-button"></div></div>').appendTo(c).click(function(){if(d.options.clickToPlayPause)e.paused? +e.play():e.pause()});e.addEventListener("play",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide();k.hide()},false);e.addEventListener("playing",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide();k.hide()},false);e.addEventListener("seeking",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("seeked",function(){g.hide();b.find(".mejs-time-buffering").hide()},false);e.addEventListener("pause",function(){mejs.MediaFeatures.isiPhone||j.show()}, +false);e.addEventListener("waiting",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("loadeddata",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("canplay",function(){g.hide();b.find(".mejs-time-buffering").hide()},false);e.addEventListener("error",function(){g.hide();b.find(".mejs-time-buffering").hide();k.show();k.find("mejs-overlay-error").html("Error loading this resource")},false)}},buildkeyboard:function(a,b,c,e){this.globalBind("keydown", +function(d){if(a.hasFocus&&a.options.enableKeyboard)for(var g=0,k=a.options.keyActions.length;g<k;g++)for(var j=a.options.keyActions[g],m=0,q=j.keys.length;m<q;m++)if(d.keyCode==j.keys[m]){d.preventDefault();j.action(a,e,d.keyCode);return false}return true});this.globalBind("click",function(d){if(f(d.target).closest(".mejs-container").length==0)a.hasFocus=false})},findTracks:function(){var a=this,b=a.$media.find("track");a.tracks=[];b.each(function(c,e){e=f(e);a.tracks.push({srclang:e.attr("srclang")? +e.attr("srclang").toLowerCase():"",src:e.attr("src"),kind:e.attr("kind"),label:e.attr("label")||"",entries:[],isLoaded:false})})},changeSkin:function(a){this.container[0].className="mejs-container "+a;this.setPlayerSize(this.width,this.height);this.setControlsSize()},play:function(){this.media.play()},pause:function(){this.media.pause()},load:function(){this.media.load()},setMuted:function(a){this.media.setMuted(a)},setCurrentTime:function(a){this.media.setCurrentTime(a)},getCurrentTime:function(){return this.media.currentTime}, +setVolume:function(a){this.media.setVolume(a)},getVolume:function(){return this.media.volume},setSrc:function(a){this.media.setSrc(a)},remove:function(){var a,b;for(a in this.options.features){b=this.options.features[a];if(this["clean"+b])try{this["clean"+b](this)}catch(c){}}this.media.pluginType==="native"?this.$media.prop("controls",true):this.media.remove();this.isDynamic||this.$node.insertBefore(this.container);delete mejs.players[this.id];this.container.remove();this.globalUnbind();delete this.node.player}}; +(function(){function a(c,e){var d={d:[],w:[]};f.each((c||"").split(" "),function(g,k){var j=k+"."+e;if(j.indexOf(".")===0){d.d.push(j);d.w.push(j)}else d[b.test(k)?"w":"d"].push(j)});d.d=d.d.join(" ");d.w=d.w.join(" ");return d}var b=/^((after|before)print|(before)?unload|hashchange|message|o(ff|n)line|page(hide|show)|popstate|resize|storage)\b/;mejs.MediaElementPlayer.prototype.globalBind=function(c,e,d){c=a(c,this.id);c.d&&f(document).bind(c.d,e,d);c.w&&f(window).bind(c.w,e,d)};mejs.MediaElementPlayer.prototype.globalUnbind= +function(c,e){c=a(c,this.id);c.d&&f(document).unbind(c.d,e);c.w&&f(window).unbind(c.w,e)}})();if(typeof jQuery!="undefined")jQuery.fn.mediaelementplayer=function(a){a===false?this.each(function(){var b=jQuery(this).data("mediaelementplayer");b&&b.remove();jQuery(this).removeData("mediaelementplayer")}):this.each(function(){jQuery(this).data("mediaelementplayer",new mejs.MediaElementPlayer(this,a))});return this};f(document).ready(function(){f(".mejs-player").mediaelementplayer()});window.MediaElementPlayer= +mejs.MediaElementPlayer})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{playpauseText:mejs.i18n.t("Play/Pause")});f.extend(MediaElementPlayer.prototype,{buildplaypause:function(a,b,c,e){var d=f('<div class="mejs-button mejs-playpause-button mejs-play" ><button type="button" aria-controls="'+this.id+'" title="'+this.options.playpauseText+'" aria-label="'+this.options.playpauseText+'"></button></div>').appendTo(b).click(function(g){g.preventDefault();e.paused?e.play():e.pause();return false});e.addEventListener("play",function(){d.removeClass("mejs-play").addClass("mejs-pause")}, +false);e.addEventListener("playing",function(){d.removeClass("mejs-play").addClass("mejs-pause")},false);e.addEventListener("pause",function(){d.removeClass("mejs-pause").addClass("mejs-play")},false);e.addEventListener("paused",function(){d.removeClass("mejs-pause").addClass("mejs-play")},false)}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{stopText:"Stop"});f.extend(MediaElementPlayer.prototype,{buildstop:function(a,b,c,e){f('<div class="mejs-button mejs-stop-button mejs-stop"><button type="button" aria-controls="'+this.id+'" title="'+this.options.stopText+'" aria-label="'+this.options.stopText+'"></button></div>').appendTo(b).click(function(){e.paused||e.pause();if(e.currentTime>0){e.setCurrentTime(0);e.pause();b.find(".mejs-time-current").width("0px");b.find(".mejs-time-handle").css("left", +"0px");b.find(".mejs-time-float-current").html(mejs.Utility.secondsToTimeCode(0));b.find(".mejs-currenttime").html(mejs.Utility.secondsToTimeCode(0));c.find(".mejs-poster").show()}})}})})(mejs.$); +(function(f){f.extend(MediaElementPlayer.prototype,{buildprogress:function(a,b,c,e){f('<div class="mejs-time-rail"><span class="mejs-time-total"><span class="mejs-time-buffering"></span><span class="mejs-time-loaded"></span><span class="mejs-time-current"></span><span class="mejs-time-handle"></span><span class="mejs-time-float"><span class="mejs-time-float-current">00:00</span><span class="mejs-time-float-corner"></span></span></span></div>').appendTo(b);b.find(".mejs-time-buffering").hide();var d= +this,g=b.find(".mejs-time-total");c=b.find(".mejs-time-loaded");var k=b.find(".mejs-time-current"),j=b.find(".mejs-time-handle"),m=b.find(".mejs-time-float"),q=b.find(".mejs-time-float-current"),p=function(h){h=h.pageX;var l=g.offset(),r=g.outerWidth(true),n=0,o=n=0;if(e.duration){if(h<l.left)h=l.left;else if(h>r+l.left)h=r+l.left;o=h-l.left;n=o/r;n=n<=0.02?0:n*e.duration;t&&n!==e.currentTime&&e.setCurrentTime(n);if(!mejs.MediaFeatures.hasTouch){m.css("left",o);q.html(mejs.Utility.secondsToTimeCode(n)); +m.show()}}},t=false;g.bind("mousedown",function(h){if(h.which===1){t=true;p(h);d.globalBind("mousemove.dur",function(l){p(l)});d.globalBind("mouseup.dur",function(){t=false;m.hide();d.globalUnbind(".dur")});return false}}).bind("mouseenter",function(){d.globalBind("mousemove.dur",function(h){p(h)});mejs.MediaFeatures.hasTouch||m.show()}).bind("mouseleave",function(){if(!t){d.globalUnbind(".dur");m.hide()}});e.addEventListener("progress",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false); +e.addEventListener("timeupdate",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false);d.loaded=c;d.total=g;d.current=k;d.handle=j},setProgressRail:function(a){var b=a!=undefined?a.target:this.media,c=null;if(b&&b.buffered&&b.buffered.length>0&&b.buffered.end&&b.duration)c=b.buffered.end(0)/b.duration;else if(b&&b.bytesTotal!=undefined&&b.bytesTotal>0&&b.bufferedBytes!=undefined)c=b.bufferedBytes/b.bytesTotal;else if(a&&a.lengthComputable&&a.total!=0)c=a.loaded/a.total;if(c!==null){c=Math.min(1, +Math.max(0,c));this.loaded&&this.total&&this.loaded.width(this.total.width()*c)}},setCurrentRail:function(){if(this.media.currentTime!=undefined&&this.media.duration)if(this.total&&this.handle){var a=Math.round(this.total.width()*this.media.currentTime/this.media.duration),b=a-Math.round(this.handle.outerWidth(true)/2);this.current.width(a);this.handle.css("left",b)}}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{duration:-1,timeAndDurationSeparator:" <span> / </span> "});f.extend(MediaElementPlayer.prototype,{buildcurrent:function(a,b,c,e){f('<div class="mejs-time"><span class="mejs-currenttime">'+(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00")+"</span></div>").appendTo(b);this.currenttime=this.controls.find(".mejs-currenttime");e.addEventListener("timeupdate",function(){a.updateCurrent()},false)},buildduration:function(a, +b,c,e){if(b.children().last().find(".mejs-currenttime").length>0)f(this.options.timeAndDurationSeparator+'<span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span>").appendTo(b.find(".mejs-time"));else{b.find(".mejs-currenttime").parent().addClass("mejs-currenttime-container"); +f('<div class="mejs-time mejs-duration-container"><span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span></div>").appendTo(b)}this.durationD=this.controls.find(".mejs-duration");e.addEventListener("timeupdate",function(){a.updateDuration()}, +false)},updateCurrent:function(){if(this.currenttime)this.currenttime.html(mejs.Utility.secondsToTimeCode(this.media.currentTime,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))},updateDuration:function(){this.container.toggleClass("mejs-long-video",this.media.duration>3600);if(this.durationD&&(this.options.duration>0||this.media.duration))this.durationD.html(mejs.Utility.secondsToTimeCode(this.options.duration>0?this.options.duration: +this.media.duration,this.options.alwaysShowHours,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{muteText:mejs.i18n.t("Mute Toggle"),hideVolumeOnTouchDevices:true,audioVolume:"horizontal",videoVolume:"vertical"});f.extend(MediaElementPlayer.prototype,{buildvolume:function(a,b,c,e){if(!(mejs.MediaFeatures.hasTouch&&this.options.hideVolumeOnTouchDevices)){var d=this,g=d.isVideo?d.options.videoVolume:d.options.audioVolume,k=g=="horizontal"?f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+d.id+'" title="'+d.options.muteText+ +'" aria-label="'+d.options.muteText+'"></button></div><div class="mejs-horizontal-volume-slider"><div class="mejs-horizontal-volume-total"></div><div class="mejs-horizontal-volume-current"></div><div class="mejs-horizontal-volume-handle"></div></div>').appendTo(b):f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+d.id+'" title="'+d.options.muteText+'" aria-label="'+d.options.muteText+'"></button><div class="mejs-volume-slider"><div class="mejs-volume-total"></div><div class="mejs-volume-current"></div><div class="mejs-volume-handle"></div></div></div>').appendTo(b), +j=d.container.find(".mejs-volume-slider, .mejs-horizontal-volume-slider"),m=d.container.find(".mejs-volume-total, .mejs-horizontal-volume-total"),q=d.container.find(".mejs-volume-current, .mejs-horizontal-volume-current"),p=d.container.find(".mejs-volume-handle, .mejs-horizontal-volume-handle"),t=function(n,o){if(!j.is(":visible")&&typeof o=="undefined"){j.show();t(n,true);j.hide()}else{n=Math.max(0,n);n=Math.min(n,1);n==0?k.removeClass("mejs-mute").addClass("mejs-unmute"):k.removeClass("mejs-unmute").addClass("mejs-mute"); +if(g=="vertical"){var s=m.height(),u=m.position(),v=s-s*n;p.css("top",Math.round(u.top+v-p.height()/2));q.height(s-v);q.css("top",u.top+v)}else{s=m.width();u=m.position();s=s*n;p.css("left",Math.round(u.left+s-p.width()/2));q.width(Math.round(s))}}},h=function(n){var o=null,s=m.offset();if(g=="vertical"){o=m.height();parseInt(m.css("top").replace(/px/,""),10);o=(o-(n.pageY-s.top))/o;if(s.top==0||s.left==0)return}else{o=m.width();o=(n.pageX-s.left)/o}o=Math.max(0,o);o=Math.min(o,1);t(o);o==0?e.setMuted(true): +e.setMuted(false);e.setVolume(o)},l=false,r=false;k.hover(function(){j.show();r=true},function(){r=false;!l&&g=="vertical"&&j.hide()});j.bind("mouseover",function(){r=true}).bind("mousedown",function(n){h(n);d.globalBind("mousemove.vol",function(o){h(o)});d.globalBind("mouseup.vol",function(){l=false;d.globalUnbind(".vol");!r&&g=="vertical"&&j.hide()});l=true;return false});k.find("button").click(function(){e.setMuted(!e.muted)});e.addEventListener("volumechange",function(){if(!l)if(e.muted){t(0); +k.removeClass("mejs-mute").addClass("mejs-unmute")}else{t(e.volume);k.removeClass("mejs-unmute").addClass("mejs-mute")}},false);if(d.container.is(":visible")){t(a.options.startVolume);a.options.startVolume===0&&e.setMuted(true);e.pluginType==="native"&&e.setVolume(a.options.startVolume)}}}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{usePluginFullScreen:true,newWindowCallback:function(){return""},fullscreenText:mejs.i18n.t("Fullscreen")});f.extend(MediaElementPlayer.prototype,{isFullScreen:false,isNativeFullScreen:false,docStyleOverflow:null,isInIframe:false,buildfullscreen:function(a,b,c,e){if(a.isVideo){a.isInIframe=window.location!=window.parent.location;if(mejs.MediaFeatures.hasTrueNativeFullScreen){c=function(){if(mejs.MediaFeatures.isFullScreen()){a.isNativeFullScreen=true;a.setControlsSize()}else{a.isNativeFullScreen= +false;a.exitFullScreen()}};mejs.MediaFeatures.hasMozNativeFullScreen?a.globalBind(mejs.MediaFeatures.fullScreenEventName,c):a.container.bind(mejs.MediaFeatures.fullScreenEventName,c)}var d=this,g=f('<div class="mejs-button mejs-fullscreen-button"><button type="button" aria-controls="'+d.id+'" title="'+d.options.fullscreenText+'" aria-label="'+d.options.fullscreenText+'"></button></div>').appendTo(b);if(d.media.pluginType==="native"||!d.options.usePluginFullScreen&&!mejs.MediaFeatures.isFirefox)g.click(function(){mejs.MediaFeatures.hasTrueNativeFullScreen&& +mejs.MediaFeatures.isFullScreen()||a.isFullScreen?a.exitFullScreen():a.enterFullScreen()});else{var k=null;if(function(){var h=document.createElement("x"),l=document.documentElement,r=window.getComputedStyle;if(!("pointerEvents"in h.style))return false;h.style.pointerEvents="auto";h.style.pointerEvents="x";l.appendChild(h);r=r&&r(h,"").pointerEvents==="auto";l.removeChild(h);return!!r}()&&!mejs.MediaFeatures.isOpera){var j=false,m=function(){if(j){for(var h in q)q[h].hide();g.css("pointer-events", +"");d.controls.css("pointer-events","");d.media.removeEventListener("click",d.clickToPlayPauseCallback);j=false}},q={};b=["top","left","right","bottom"];var p,t=function(){var h=g.offset().left-d.container.offset().left,l=g.offset().top-d.container.offset().top,r=g.outerWidth(true),n=g.outerHeight(true),o=d.container.width(),s=d.container.height();for(p in q)q[p].css({position:"absolute",top:0,left:0});q.top.width(o).height(l);q.left.width(h).height(n).css({top:l});q.right.width(o-h-r).height(n).css({top:l, +left:h+r});q.bottom.width(o).height(s-n-l).css({top:l+n})};d.globalBind("resize",function(){t()});p=0;for(c=b.length;p<c;p++)q[b[p]]=f('<div class="mejs-fullscreen-hover" />').appendTo(d.container).mouseover(m).hide();g.on("mouseover",function(){if(!d.isFullScreen){var h=g.offset(),l=a.container.offset();e.positionFullscreenButton(h.left-l.left,h.top-l.top,false);g.css("pointer-events","none");d.controls.css("pointer-events","none");d.media.addEventListener("click",d.clickToPlayPauseCallback);for(p in q)q[p].show(); +t();j=true}});e.addEventListener("fullscreenchange",function(){d.isFullScreen=!d.isFullScreen;d.isFullScreen?d.media.removeEventListener("click",d.clickToPlayPauseCallback):d.media.addEventListener("click",d.clickToPlayPauseCallback);m()});d.globalBind("mousemove",function(h){if(j){var l=g.offset();if(h.pageY<l.top||h.pageY>l.top+g.outerHeight(true)||h.pageX<l.left||h.pageX>l.left+g.outerWidth(true)){g.css("pointer-events","");d.controls.css("pointer-events","");j=false}}})}else g.on("mouseover", +function(){if(k!==null){clearTimeout(k);delete k}var h=g.offset(),l=a.container.offset();e.positionFullscreenButton(h.left-l.left,h.top-l.top,true)}).on("mouseout",function(){if(k!==null){clearTimeout(k);delete k}k=setTimeout(function(){e.hideFullscreenButton()},1500)})}a.fullscreenBtn=g;d.globalBind("keydown",function(h){if((mejs.MediaFeatures.hasTrueNativeFullScreen&&mejs.MediaFeatures.isFullScreen()||d.isFullScreen)&&h.keyCode==27)a.exitFullScreen()})}},cleanfullscreen:function(a){a.exitFullScreen()}, +containerSizeTimeout:null,enterFullScreen:function(){var a=this;if(!(a.media.pluginType!=="native"&&(mejs.MediaFeatures.isFirefox||a.options.usePluginFullScreen))){docStyleOverflow=document.documentElement.style.overflow;document.documentElement.style.overflow="hidden";normalHeight=a.container.height();normalWidth=a.container.width();if(a.media.pluginType==="native")if(mejs.MediaFeatures.hasTrueNativeFullScreen){mejs.MediaFeatures.requestFullScreen(a.container[0]);a.isInIframe&&setTimeout(function c(){if(a.isNativeFullScreen)f(window).width()!== +screen.width?a.exitFullScreen():setTimeout(c,500)},500)}else if(mejs.MediaFeatures.hasSemiNativeFullScreen){a.media.webkitEnterFullscreen();return}if(a.isInIframe){var b=a.options.newWindowCallback(this);if(b!=="")if(mejs.MediaFeatures.hasTrueNativeFullScreen)setTimeout(function(){if(!a.isNativeFullScreen){a.pause();window.open(b,a.id,"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no")}},250);else{a.pause();window.open(b,a.id, +"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no");return}}a.container.addClass("mejs-container-fullscreen").width("100%").height("100%");a.containerSizeTimeout=setTimeout(function(){a.container.css({width:"100%",height:"100%"});a.setControlsSize()},500);if(a.media.pluginType==="native")a.$media.width("100%").height("100%");else{a.container.find(".mejs-shim").width("100%").height("100%");a.media.setVideoSize(f(window).width(), +f(window).height())}a.layers.children("div").width("100%").height("100%");a.fullscreenBtn&&a.fullscreenBtn.removeClass("mejs-fullscreen").addClass("mejs-unfullscreen");a.setControlsSize();a.isFullScreen=true}},exitFullScreen:function(){clearTimeout(this.containerSizeTimeout);if(this.media.pluginType!=="native"&&mejs.MediaFeatures.isFirefox)this.media.setFullscreen(false);else{if(mejs.MediaFeatures.hasTrueNativeFullScreen&&(mejs.MediaFeatures.isFullScreen()||this.isFullScreen))mejs.MediaFeatures.cancelFullScreen(); +document.documentElement.style.overflow=docStyleOverflow;this.container.removeClass("mejs-container-fullscreen").width(normalWidth).height(normalHeight);if(this.media.pluginType==="native")this.$media.width(normalWidth).height(normalHeight);else{this.container.find(".mejs-shim").width(normalWidth).height(normalHeight);this.media.setVideoSize(normalWidth,normalHeight)}this.layers.children("div").width(normalWidth).height(normalHeight);this.fullscreenBtn.removeClass("mejs-unfullscreen").addClass("mejs-fullscreen"); +this.setControlsSize();this.isFullScreen=false}}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{startLanguage:"",tracksText:mejs.i18n.t("Captions/Subtitles"),hideCaptionsButtonWhenEmpty:true,toggleCaptionsButtonWhenOnlyOne:false,slidesSelector:""});f.extend(MediaElementPlayer.prototype,{hasChapters:false,buildtracks:function(a,b,c,e){if(a.tracks.length!=0){a.chapters=f('<div class="mejs-chapters mejs-layer"></div>').prependTo(c).hide();a.captions=f('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position mejs-captions-position-hover"><span class="mejs-captions-text"></span></div></div>').prependTo(c).hide();a.captionsText= +a.captions.find(".mejs-captions-text");a.captionsButton=f('<div class="mejs-button mejs-captions-button"><button type="button" aria-controls="'+this.id+'" title="'+this.options.tracksText+'" aria-label="'+this.options.tracksText+'"></button><div class="mejs-captions-selector"><ul><li><input type="radio" name="'+a.id+'_captions" id="'+a.id+'_captions_none" value="none" checked="checked" /><label for="'+a.id+'_captions_none">'+mejs.i18n.t("None")+"</label></li></ul></div></div>").appendTo(b);for(b= +c=0;b<a.tracks.length;b++)a.tracks[b].kind=="subtitles"&&c++;this.options.toggleCaptionsButtonWhenOnlyOne&&c==1?a.captionsButton.on("click",function(){a.setTrack(a.selectedTrack==null?a.tracks[0].srclang:"none")}):a.captionsButton.hover(function(){f(this).find(".mejs-captions-selector").css("visibility","visible")},function(){f(this).find(".mejs-captions-selector").css("visibility","hidden")}).on("click","input[type=radio]",function(){lang=this.value;a.setTrack(lang)});a.options.alwaysShowControls? +a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover"):a.container.bind("controlsshown",function(){a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover")}).bind("controlshidden",function(){e.paused||a.container.find(".mejs-captions-position").removeClass("mejs-captions-position-hover")});a.trackToLoad=-1;a.selectedTrack=null;a.isLoadingTrack=false;for(b=0;b<a.tracks.length;b++)a.tracks[b].kind=="subtitles"&&a.addTrackButton(a.tracks[b].srclang, +a.tracks[b].label);a.loadNextTrack();e.addEventListener("timeupdate",function(){a.displayCaptions()},false);if(a.options.slidesSelector!=""){a.slidesContainer=f(a.options.slidesSelector);e.addEventListener("timeupdate",function(){a.displaySlides()},false)}e.addEventListener("loadedmetadata",function(){a.displayChapters()},false);a.container.hover(function(){if(a.hasChapters){a.chapters.css("visibility","visible");a.chapters.fadeIn(200).height(a.chapters.find(".mejs-chapter").outerHeight())}},function(){a.hasChapters&& +!e.paused&&a.chapters.fadeOut(200,function(){f(this).css("visibility","hidden");f(this).css("display","block")})});a.node.getAttribute("autoplay")!==null&&a.chapters.css("visibility","hidden")}},setTrack:function(a){var b;if(a=="none"){this.selectedTrack=null;this.captionsButton.removeClass("mejs-captions-enabled")}else for(b=0;b<this.tracks.length;b++)if(this.tracks[b].srclang==a){this.selectedTrack==null&&this.captionsButton.addClass("mejs-captions-enabled");this.selectedTrack=this.tracks[b];this.captions.attr("lang", +this.selectedTrack.srclang);this.displayCaptions();break}},loadNextTrack:function(){this.trackToLoad++;if(this.trackToLoad<this.tracks.length){this.isLoadingTrack=true;this.loadTrack(this.trackToLoad)}else{this.isLoadingTrack=false;this.checkForTracks()}},loadTrack:function(a){var b=this,c=b.tracks[a];f.ajax({url:c.src,dataType:"text",success:function(e){c.entries=typeof e=="string"&&/<tt\s+xml/ig.exec(e)?mejs.TrackFormatParser.dfxp.parse(e):mejs.TrackFormatParser.webvvt.parse(e);c.isLoaded=true; +b.enableTrackButton(c.srclang,c.label);b.loadNextTrack();c.kind=="chapters"&&b.media.addEventListener("play",function(){b.media.duration>0&&b.displayChapters(c)},false);c.kind=="slides"&&b.setupSlides(c)},error:function(){b.loadNextTrack()}})},enableTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||a;this.captionsButton.find("input[value="+a+"]").prop("disabled",false).siblings("label").html(b);this.options.startLanguage==a&&f("#"+this.id+"_captions_"+a).click();this.adjustLanguageBox()}, +addTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||a;this.captionsButton.find("ul").append(f('<li><input type="radio" name="'+this.id+'_captions" id="'+this.id+"_captions_"+a+'" value="'+a+'" disabled="disabled" /><label for="'+this.id+"_captions_"+a+'">'+b+" (loading)</label></li>"));this.adjustLanguageBox();this.container.find(".mejs-captions-translations option[value="+a+"]").remove()},adjustLanguageBox:function(){this.captionsButton.find(".mejs-captions-selector").height(this.captionsButton.find(".mejs-captions-selector ul").outerHeight(true)+ +this.captionsButton.find(".mejs-captions-translations").outerHeight(true))},checkForTracks:function(){var a=false;if(this.options.hideCaptionsButtonWhenEmpty){for(i=0;i<this.tracks.length;i++)if(this.tracks[i].kind=="subtitles"){a=true;break}if(!a){this.captionsButton.hide();this.setControlsSize()}}},displayCaptions:function(){if(typeof this.tracks!="undefined"){var a,b=this.selectedTrack;if(b!=null&&b.isLoaded)for(a=0;a<b.entries.times.length;a++)if(this.media.currentTime>=b.entries.times[a].start&& +this.media.currentTime<=b.entries.times[a].stop){this.captionsText.html(b.entries.text[a]);this.captions.show().height(0);return}this.captions.hide()}},setupSlides:function(a){this.slides=a;this.slides.entries.imgs=[this.slides.entries.text.length];this.showSlide(0)},showSlide:function(a){if(!(typeof this.tracks=="undefined"||typeof this.slidesContainer=="undefined")){var b=this,c=b.slides.entries.text[a],e=b.slides.entries.imgs[a];if(typeof e=="undefined"||typeof e.fadeIn=="undefined")b.slides.entries.imgs[a]= +e=f('<img src="'+c+'">').on("load",function(){e.appendTo(b.slidesContainer).hide().fadeIn().siblings(":visible").fadeOut()});else if(!e.is(":visible")&&!e.is(":animated")){console.log("showing existing slide");e.fadeIn().siblings(":visible").fadeOut()}}},displaySlides:function(){if(typeof this.slides!="undefined"){var a=this.slides,b;for(b=0;b<a.entries.times.length;b++)if(this.media.currentTime>=a.entries.times[b].start&&this.media.currentTime<=a.entries.times[b].stop){this.showSlide(b);break}}}, +displayChapters:function(){var a;for(a=0;a<this.tracks.length;a++)if(this.tracks[a].kind=="chapters"&&this.tracks[a].isLoaded){this.drawChapters(this.tracks[a]);this.hasChapters=true;break}},drawChapters:function(a){var b=this,c,e,d=e=0;b.chapters.empty();for(c=0;c<a.entries.times.length;c++){e=a.entries.times[c].stop-a.entries.times[c].start;e=Math.floor(e/b.media.duration*100);if(e+d>100||c==a.entries.times.length-1&&e+d<100)e=100-d;b.chapters.append(f('<div class="mejs-chapter" rel="'+a.entries.times[c].start+ +'" style="left: '+d.toString()+"%;width: "+e.toString()+'%;"><div class="mejs-chapter-block'+(c==a.entries.times.length-1?" mejs-chapter-block-last":"")+'"><span class="ch-title">'+a.entries.text[c]+'</span><span class="ch-time">'+mejs.Utility.secondsToTimeCode(a.entries.times[c].start)+"&ndash;"+mejs.Utility.secondsToTimeCode(a.entries.times[c].stop)+"</span></div></div>"));d+=e}b.chapters.find("div.mejs-chapter").click(function(){b.media.setCurrentTime(parseFloat(f(this).attr("rel")));b.media.paused&& +b.media.play()});b.chapters.show()}});mejs.language={codes:{af:"Afrikaans",sq:"Albanian",ar:"Arabic",be:"Belarusian",bg:"Bulgarian",ca:"Catalan",zh:"Chinese","zh-cn":"Chinese Simplified","zh-tw":"Chinese Traditional",hr:"Croatian",cs:"Czech",da:"Danish",nl:"Dutch",en:"English",et:"Estonian",tl:"Filipino",fi:"Finnish",fr:"French",gl:"Galician",de:"German",el:"Greek",ht:"Haitian Creole",iw:"Hebrew",hi:"Hindi",hu:"Hungarian",is:"Icelandic",id:"Indonesian",ga:"Irish",it:"Italian",ja:"Japanese",ko:"Korean", +lv:"Latvian",lt:"Lithuanian",mk:"Macedonian",ms:"Malay",mt:"Maltese",no:"Norwegian",fa:"Persian",pl:"Polish",pt:"Portuguese",ro:"Romanian",ru:"Russian",sr:"Serbian",sk:"Slovak",sl:"Slovenian",es:"Spanish",sw:"Swahili",sv:"Swedish",tl:"Tagalog",th:"Thai",tr:"Turkish",uk:"Ukrainian",vi:"Vietnamese",cy:"Welsh",yi:"Yiddish"}};mejs.TrackFormatParser={webvvt:{pattern_identifier:/^([a-zA-z]+-)?[0-9]+$/,pattern_timecode:/^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/, +parse:function(a){var b=0;a=mejs.TrackFormatParser.split2(a,/\r?\n/);for(var c={text:[],times:[]},e,d;b<a.length;b++)if(this.pattern_identifier.exec(a[b])){b++;if((e=this.pattern_timecode.exec(a[b]))&&b<a.length){b++;d=a[b];for(b++;a[b]!==""&&b<a.length;){d=d+"\n"+a[b];b++}d=f.trim(d).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig,"<a href='$1' target='_blank'>$1</a>");c.text.push(d);c.times.push({start:mejs.Utility.convertSMPTEtoSeconds(e[1])==0?0.2:mejs.Utility.convertSMPTEtoSeconds(e[1]), +stop:mejs.Utility.convertSMPTEtoSeconds(e[3]),settings:e[5]})}}return c}},dfxp:{parse:function(a){a=f(a).filter("tt");var b=0;b=a.children("div").eq(0);var c=b.find("p");b=a.find("#"+b.attr("style"));var e,d;a={text:[],times:[]};if(b.length){d=b.removeAttr("id").get(0).attributes;if(d.length){e={};for(b=0;b<d.length;b++)e[d[b].name.split(":")[1]]=d[b].value}}for(b=0;b<c.length;b++){var g;d={start:null,stop:null,style:null};if(c.eq(b).attr("begin"))d.start=mejs.Utility.convertSMPTEtoSeconds(c.eq(b).attr("begin")); +if(!d.start&&c.eq(b-1).attr("end"))d.start=mejs.Utility.convertSMPTEtoSeconds(c.eq(b-1).attr("end"));if(c.eq(b).attr("end"))d.stop=mejs.Utility.convertSMPTEtoSeconds(c.eq(b).attr("end"));if(!d.stop&&c.eq(b+1).attr("begin"))d.stop=mejs.Utility.convertSMPTEtoSeconds(c.eq(b+1).attr("begin"));if(e){g="";for(var k in e)g+=k+":"+e[k]+";"}if(g)d.style=g;if(d.start==0)d.start=0.2;a.times.push(d);d=f.trim(c.eq(b).html()).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, +"<a href='$1' target='_blank'>$1</a>");a.text.push(d);if(a.times.start==0)a.times.start=2}return a}},split2:function(a,b){return a.split(b)}};if("x\n\ny".split(/\n/gi).length!=3)mejs.TrackFormatParser.split2=function(a,b){var c=[],e="",d;for(d=0;d<a.length;d++){e+=a.substring(d,d+1);if(b.test(e)){c.push(e.replace(b,""));e=""}}c.push(e);return c}})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{contextMenuItems:[{render:function(a){if(typeof a.enterFullScreen=="undefined")return null;return a.isFullScreen?mejs.i18n.t("Turn off Fullscreen"):mejs.i18n.t("Go Fullscreen")},click:function(a){a.isFullScreen?a.exitFullScreen():a.enterFullScreen()}},{render:function(a){return a.media.muted?mejs.i18n.t("Unmute"):mejs.i18n.t("Mute")},click:function(a){a.media.muted?a.setMuted(false):a.setMuted(true)}},{isSeparator:true},{render:function(){return mejs.i18n.t("Download Video")}, +click:function(a){window.location.href=a.media.currentSrc}}]});f.extend(MediaElementPlayer.prototype,{buildcontextmenu:function(a){a.contextMenu=f('<div class="mejs-contextmenu"></div>').appendTo(f("body")).hide();a.container.bind("contextmenu",function(b){if(a.isContextMenuEnabled){b.preventDefault();a.renderContextMenu(b.clientX-1,b.clientY-1);return false}});a.container.bind("click",function(){a.contextMenu.hide()});a.contextMenu.bind("mouseleave",function(){a.startContextMenuTimer()})},cleancontextmenu:function(a){a.contextMenu.remove()}, +isContextMenuEnabled:true,enableContextMenu:function(){this.isContextMenuEnabled=true},disableContextMenu:function(){this.isContextMenuEnabled=false},contextMenuTimeout:null,startContextMenuTimer:function(){var a=this;a.killContextMenuTimer();a.contextMenuTimer=setTimeout(function(){a.hideContextMenu();a.killContextMenuTimer()},750)},killContextMenuTimer:function(){var a=this.contextMenuTimer;if(a!=null){clearTimeout(a);delete a}},hideContextMenu:function(){this.contextMenu.hide()},renderContextMenu:function(a, +b){for(var c=this,e="",d=c.options.contextMenuItems,g=0,k=d.length;g<k;g++)if(d[g].isSeparator)e+='<div class="mejs-contextmenu-separator"></div>';else{var j=d[g].render(c);if(j!=null)e+='<div class="mejs-contextmenu-item" data-itemindex="'+g+'" id="element-'+Math.random()*1E6+'">'+j+"</div>"}c.contextMenu.empty().append(f(e)).css({top:b,left:a}).show();c.contextMenu.find(".mejs-contextmenu-item").each(function(){var m=f(this),q=parseInt(m.data("itemindex"),10),p=c.options.contextMenuItems[q];typeof p.show!= +"undefined"&&p.show(m,c);m.click(function(){typeof p.click!="undefined"&&p.click(c);c.contextMenu.hide()})});setTimeout(function(){c.killControlsTimer("rev3")},100)}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{postrollCloseText:mejs.i18n.t("Close")});f.extend(MediaElementPlayer.prototype,{buildpostroll:function(a,b,c){var e=this.container.find('link[rel="postroll"]').attr("href");if(typeof e!=="undefined"){a.postroll=f('<div class="mejs-postroll-layer mejs-layer"><a class="mejs-postroll-close" onclick="$(this).parent().hide();return false;">'+this.options.postrollCloseText+'</a><div class="mejs-postroll-layer-content"></div></div>').prependTo(c).hide();this.media.addEventListener("ended", +function(){f.ajax({dataType:"html",url:e,success:function(d){c.find(".mejs-postroll-layer-content").html(d)}});a.postroll.show()},false)}}})})(mejs.$); + diff --git a/src/static/mediaelement/mediaelement.js b/src/static/mediaelement/mediaelement.js new file mode 100755 index 0000000..67c64ff --- /dev/null +++ b/src/static/mediaelement/mediaelement.js @@ -0,0 +1,1890 @@ +/*! +* MediaElement.js +* HTML5 <video> and <audio> shim and player +* http://mediaelementjs.com/ +* +* Creates a JavaScript object that mimics HTML5 MediaElement API +* for browsers that don't understand HTML5 or can't play the provided codec +* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3 +* +* Copyright 2010-2013, John Dyer (http://j.hn) +* License: MIT +* +*/ +// Namespace +var mejs = mejs || {}; + +// version number +mejs.version = '2.12.0'; + +// player number (for missing, same id attr) +mejs.meIndex = 0; + +// media types accepted by plugins +mejs.plugins = { + silverlight: [ + {version: [3,0], types: ['video/mp4','video/m4v','video/mov','video/wmv','audio/wma','audio/m4a','audio/mp3','audio/wav','audio/mpeg']} + ], + flash: [ + {version: [9,0,124], types: ['video/mp4','video/m4v','video/mov','video/flv','video/rtmp','video/x-flv','audio/flv','audio/x-flv','audio/mp3','audio/m4a','audio/mpeg', 'video/youtube', 'video/x-youtube']} + //,{version: [12,0], types: ['video/webm']} // for future reference (hopefully!) + ], + youtube: [ + {version: null, types: ['video/youtube', 'video/x-youtube', 'audio/youtube', 'audio/x-youtube']} + ], + vimeo: [ + {version: null, types: ['video/vimeo', 'video/x-vimeo']} + ] +}; + +/* +Utility methods +*/ +mejs.Utility = { + encodeUrl: function(url) { + return encodeURIComponent(url); //.replace(/\?/gi,'%3F').replace(/=/gi,'%3D').replace(/&/gi,'%26'); + }, + escapeHTML: function(s) { + return s.toString().split('&').join('&amp;').split('<').join('&lt;').split('"').join('&quot;'); + }, + absolutizeUrl: function(url) { + var el = document.createElement('div'); + el.innerHTML = '<a href="' + this.escapeHTML(url) + '">x</a>'; + return el.firstChild.href; + }, + getScriptPath: function(scriptNames) { + var + i = 0, + j, + codePath = '', + testname = '', + slashPos, + filenamePos, + scriptUrl, + scriptPath, + scriptFilename, + scripts = document.getElementsByTagName('script'), + il = scripts.length, + jl = scriptNames.length; + + // go through all <script> tags + for (; i < il; i++) { + scriptUrl = scripts[i].src; + slashPos = scriptUrl.lastIndexOf('/'); + if (slashPos > -1) { + scriptFilename = scriptUrl.substring(slashPos + 1); + scriptPath = scriptUrl.substring(0, slashPos + 1); + } else { + scriptFilename = scriptUrl; + scriptPath = ''; + } + + // see if any <script> tags have a file name that matches the + for (j = 0; j < jl; j++) { + testname = scriptNames[j]; + filenamePos = scriptFilename.indexOf(testname); + if (filenamePos > -1) { + codePath = scriptPath; + break; + } + } + + // if we found a path, then break and return it + if (codePath !== '') { + break; + } + } + + // send the best path back + return codePath; + }, + secondsToTimeCode: function(time, forceHours, showFrameCount, fps) { + //add framecount + if (typeof showFrameCount == 'undefined') { + showFrameCount=false; + } else if(typeof fps == 'undefined') { + fps = 25; + } + + var hours = Math.floor(time / 3600) % 24, + minutes = Math.floor(time / 60) % 60, + seconds = Math.floor(time % 60), + frames = Math.floor(((time % 1)*fps).toFixed(3)), + result = + ( (forceHours || hours > 0) ? (hours < 10 ? '0' + hours : hours) + ':' : '') + + (minutes < 10 ? '0' + minutes : minutes) + ':' + + (seconds < 10 ? '0' + seconds : seconds) + + ((showFrameCount) ? ':' + (frames < 10 ? '0' + frames : frames) : ''); + + return result; + }, + + timeCodeToSeconds: function(hh_mm_ss_ff, forceHours, showFrameCount, fps){ + if (typeof showFrameCount == 'undefined') { + showFrameCount=false; + } else if(typeof fps == 'undefined') { + fps = 25; + } + + var tc_array = hh_mm_ss_ff.split(":"), + tc_hh = parseInt(tc_array[0], 10), + tc_mm = parseInt(tc_array[1], 10), + tc_ss = parseInt(tc_array[2], 10), + tc_ff = 0, + tc_in_seconds = 0; + + if (showFrameCount) { + tc_ff = parseInt(tc_array[3])/fps; + } + + tc_in_seconds = ( tc_hh * 3600 ) + ( tc_mm * 60 ) + tc_ss + tc_ff; + + return tc_in_seconds; + }, + + + convertSMPTEtoSeconds: function (SMPTE) { + if (typeof SMPTE != 'string') + return false; + + SMPTE = SMPTE.replace(',', '.'); + + var secs = 0, + decimalLen = (SMPTE.indexOf('.') != -1) ? SMPTE.split('.')[1].length : 0, + multiplier = 1; + + SMPTE = SMPTE.split(':').reverse(); + + for (var i = 0; i < SMPTE.length; i++) { + multiplier = 1; + if (i > 0) { + multiplier = Math.pow(60, i); + } + secs += Number(SMPTE[i]) * multiplier; + } + return Number(secs.toFixed(decimalLen)); + }, + + /* borrowed from SWFObject: http://code.google.com/p/swfobject/source/browse/trunk/swfobject/src/swfobject.js#474 */ + removeSwf: function(id) { + var obj = document.getElementById(id); + if (obj && /object|embed/i.test(obj.nodeName)) { + if (mejs.MediaFeatures.isIE) { + obj.style.display = "none"; + (function(){ + if (obj.readyState == 4) { + mejs.Utility.removeObjectInIE(id); + } else { + setTimeout(arguments.callee, 10); + } + })(); + } else { + obj.parentNode.removeChild(obj); + } + } + }, + removeObjectInIE: function(id) { + var obj = document.getElementById(id); + if (obj) { + for (var i in obj) { + if (typeof obj[i] == "function") { + obj[i] = null; + } + } + obj.parentNode.removeChild(obj); + } + } +}; + + +// Core detector, plugins are added below +mejs.PluginDetector = { + + // main public function to test a plug version number PluginDetector.hasPluginVersion('flash',[9,0,125]); + hasPluginVersion: function(plugin, v) { + var pv = this.plugins[plugin]; + v[1] = v[1] || 0; + v[2] = v[2] || 0; + return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false; + }, + + // cached values + nav: window.navigator, + ua: window.navigator.userAgent.toLowerCase(), + + // stored version numbers + plugins: [], + + // runs detectPlugin() and stores the version number + addPlugin: function(p, pluginName, mimeType, activeX, axDetect) { + this.plugins[p] = this.detectPlugin(pluginName, mimeType, activeX, axDetect); + }, + + // get the version number from the mimetype (all but IE) or ActiveX (IE) + detectPlugin: function(pluginName, mimeType, activeX, axDetect) { + + var version = [0,0,0], + description, + i, + ax; + + // Firefox, Webkit, Opera + if (typeof(this.nav.plugins) != 'undefined' && typeof this.nav.plugins[pluginName] == 'object') { + description = this.nav.plugins[pluginName].description; + if (description && !(typeof this.nav.mimeTypes != 'undefined' && this.nav.mimeTypes[mimeType] && !this.nav.mimeTypes[mimeType].enabledPlugin)) { + version = description.replace(pluginName, '').replace(/^\s+/,'').replace(/\sr/gi,'.').split('.'); + for (i=0; i<version.length; i++) { + version[i] = parseInt(version[i].match(/\d+/), 10); + } + } + // Internet Explorer / ActiveX + } else if (typeof(window.ActiveXObject) != 'undefined') { + try { + ax = new ActiveXObject(activeX); + if (ax) { + version = axDetect(ax); + } + } + catch (e) { } + } + return version; + } +}; + +// Add Flash detection +mejs.PluginDetector.addPlugin('flash','Shockwave Flash','application/x-shockwave-flash','ShockwaveFlash.ShockwaveFlash', function(ax) { + // adapted from SWFObject + var version = [], + d = ax.GetVariable("$version"); + if (d) { + d = d.split(" ")[1].split(","); + version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; + } + return version; +}); + +// Add Silverlight detection +mejs.PluginDetector.addPlugin('silverlight','Silverlight Plug-In','application/x-silverlight-2','AgControl.AgControl', function (ax) { + // Silverlight cannot report its version number to IE + // but it does have a isVersionSupported function, so we have to loop through it to get a version number. + // adapted from http://www.silverlightversion.com/ + var v = [0,0,0,0], + loopMatch = function(ax, v, i, n) { + while(ax.isVersionSupported(v[0]+ "."+ v[1] + "." + v[2] + "." + v[3])){ + v[i]+=n; + } + v[i] -= n; + }; + loopMatch(ax, v, 0, 1); + loopMatch(ax, v, 1, 1); + loopMatch(ax, v, 2, 10000); // the third place in the version number is usually 5 digits (4.0.xxxxx) + loopMatch(ax, v, 2, 1000); + loopMatch(ax, v, 2, 100); + loopMatch(ax, v, 2, 10); + loopMatch(ax, v, 2, 1); + loopMatch(ax, v, 3, 1); + + return v; +}); +// add adobe acrobat +/* +PluginDetector.addPlugin('acrobat','Adobe Acrobat','application/pdf','AcroPDF.PDF', function (ax) { + var version = [], + d = ax.GetVersions().split(',')[0].split('=')[1].split('.'); + + if (d) { + version = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)]; + } + return version; +}); +*/ +// necessary detection (fixes for <IE9) +mejs.MediaFeatures = { + init: function() { + var + t = this, + d = document, + nav = mejs.PluginDetector.nav, + ua = mejs.PluginDetector.ua.toLowerCase(), + i, + v, + html5Elements = ['source','track','audio','video']; + + // detect browsers (only the ones that have some kind of quirk we need to work around) + t.isiPad = (ua.match(/ipad/i) !== null); + t.isiPhone = (ua.match(/iphone/i) !== null); + t.isiOS = t.isiPhone || t.isiPad; + t.isAndroid = (ua.match(/android/i) !== null); + t.isBustedAndroid = (ua.match(/android 2\.[12]/) !== null); + t.isBustedNativeHTTPS = (location.protocol === 'https:' && (ua.match(/android [12]\./) !== null || ua.match(/macintosh.* version.* safari/) !== null)); + t.isIE = (nav.appName.toLowerCase().indexOf("microsoft") != -1); + t.isChrome = (ua.match(/chrome/gi) !== null); + t.isFirefox = (ua.match(/firefox/gi) !== null); + t.isWebkit = (ua.match(/webkit/gi) !== null); + t.isGecko = (ua.match(/gecko/gi) !== null) && !t.isWebkit; + t.isOpera = (ua.match(/opera/gi) !== null); + t.hasTouch = ('ontouchstart' in window); + + // borrowed from Modernizr + t.svg = !! document.createElementNS && + !! document.createElementNS('http://www.w3.org/2000/svg','svg').createSVGRect; + + // create HTML5 media elements for IE before 9, get a <video> element for fullscreen detection + for (i=0; i<html5Elements.length; i++) { + v = document.createElement(html5Elements[i]); + } + + t.supportsMediaTag = (typeof v.canPlayType !== 'undefined' || t.isBustedAndroid); + + // Fix for IE9 on Windows 7N / Windows 7KN (Media Player not installer) + try{ + v.canPlayType("video/mp4"); + }catch(e){ + t.supportsMediaTag = false; + } + + // detect native JavaScript fullscreen (Safari/Firefox only, Chrome still fails) + + // iOS + t.hasSemiNativeFullScreen = (typeof v.webkitEnterFullscreen !== 'undefined'); + + // Webkit/firefox + t.hasWebkitNativeFullScreen = (typeof v.webkitRequestFullScreen !== 'undefined'); + t.hasMozNativeFullScreen = (typeof v.mozRequestFullScreen !== 'undefined'); + + t.hasTrueNativeFullScreen = (t.hasWebkitNativeFullScreen || t.hasMozNativeFullScreen); + t.nativeFullScreenEnabled = t.hasTrueNativeFullScreen; + if (t.hasMozNativeFullScreen) { + t.nativeFullScreenEnabled = v.mozFullScreenEnabled; + } + + + if (this.isChrome) { + t.hasSemiNativeFullScreen = false; + } + + if (t.hasTrueNativeFullScreen) { + t.fullScreenEventName = (t.hasWebkitNativeFullScreen) ? 'webkitfullscreenchange' : 'mozfullscreenchange'; + + + t.isFullScreen = function() { + if (v.mozRequestFullScreen) { + return d.mozFullScreen; + } else if (v.webkitRequestFullScreen) { + return d.webkitIsFullScreen; + } + } + + t.requestFullScreen = function(el) { + + if (t.hasWebkitNativeFullScreen) { + el.webkitRequestFullScreen(); + } else if (t.hasMozNativeFullScreen) { + el.mozRequestFullScreen(); + } + } + + t.cancelFullScreen = function() { + if (t.hasWebkitNativeFullScreen) { + document.webkitCancelFullScreen(); + } else if (t.hasMozNativeFullScreen) { + document.mozCancelFullScreen(); + } + } + + } + + + // OS X 10.5 can't do this even if it says it can :( + if (t.hasSemiNativeFullScreen && ua.match(/mac os x 10_5/i)) { + t.hasNativeFullScreen = false; + t.hasSemiNativeFullScreen = false; + } + + } +}; +mejs.MediaFeatures.init(); + +/* +extension methods to <video> or <audio> object to bring it into parity with PluginMediaElement (see below) +*/ +mejs.HtmlMediaElement = { + pluginType: 'native', + isFullScreen: false, + + setCurrentTime: function (time) { + this.currentTime = time; + }, + + setMuted: function (muted) { + this.muted = muted; + }, + + setVolume: function (volume) { + this.volume = volume; + }, + + // for parity with the plugin versions + stop: function () { + this.pause(); + }, + + // This can be a url string + // or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}] + setSrc: function (url) { + + // Fix for IE9 which can't set .src when there are <source> elements. Awesome, right? + var + existingSources = this.getElementsByTagName('source'); + while (existingSources.length > 0){ + this.removeChild(existingSources[0]); + } + + if (typeof url == 'string') { + this.src = url; + } else { + var i, media; + + for (i=0; i<url.length; i++) { + media = url[i]; + if (this.canPlayType(media.type)) { + this.src = media.src; + break; + } + } + } + }, + + setVideoSize: function (width, height) { + this.width = width; + this.height = height; + } +}; + +/* +Mimics the <video/audio> element by calling Flash's External Interface or Silverlights [ScriptableMember] +*/ +mejs.PluginMediaElement = function (pluginid, pluginType, mediaUrl) { + this.id = pluginid; + this.pluginType = pluginType; + this.src = mediaUrl; + this.events = {}; + this.attributes = {}; +}; + +// JavaScript values and ExternalInterface methods that match HTML5 video properties methods +// http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/fl/video/FLVPlayback.html +// http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html +mejs.PluginMediaElement.prototype = { + + // special + pluginElement: null, + pluginType: '', + isFullScreen: false, + + // not implemented :( + playbackRate: -1, + defaultPlaybackRate: -1, + seekable: [], + played: [], + + // HTML5 read-only properties + paused: true, + ended: false, + seeking: false, + duration: 0, + error: null, + tagName: '', + + // HTML5 get/set properties, but only set (updated by event handlers) + muted: false, + volume: 1, + currentTime: 0, + + // HTML5 methods + play: function () { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + this.pluginApi.playVideo(); + } else { + this.pluginApi.playMedia(); + } + this.paused = false; + } + }, + load: function () { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + } else { + this.pluginApi.loadMedia(); + } + + this.paused = false; + } + }, + pause: function () { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + this.pluginApi.pauseVideo(); + } else { + this.pluginApi.pauseMedia(); + } + + + this.paused = true; + } + }, + stop: function () { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + this.pluginApi.stopVideo(); + } else { + this.pluginApi.stopMedia(); + } + this.paused = true; + } + }, + canPlayType: function(type) { + var i, + j, + pluginInfo, + pluginVersions = mejs.plugins[this.pluginType]; + + for (i=0; i<pluginVersions.length; i++) { + pluginInfo = pluginVersions[i]; + + // test if user has the correct plugin version + if (mejs.PluginDetector.hasPluginVersion(this.pluginType, pluginInfo.version)) { + + // test for plugin playback types + for (j=0; j<pluginInfo.types.length; j++) { + // find plugin that can play the type + if (type == pluginInfo.types[j]) { + return 'probably'; + } + } + } + } + + return ''; + }, + + positionFullscreenButton: function(x,y,visibleAndAbove) { + if (this.pluginApi != null && this.pluginApi.positionFullscreenButton) { + this.pluginApi.positionFullscreenButton(Math.floor(x),Math.floor(y),visibleAndAbove); + } + }, + + hideFullscreenButton: function() { + if (this.pluginApi != null && this.pluginApi.hideFullscreenButton) { + this.pluginApi.hideFullscreenButton(); + } + }, + + + // custom methods since not all JavaScript implementations support get/set + + // This can be a url string + // or an array [{src:'file.mp4',type:'video/mp4'},{src:'file.webm',type:'video/webm'}] + setSrc: function (url) { + if (typeof url == 'string') { + this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(url)); + this.src = mejs.Utility.absolutizeUrl(url); + } else { + var i, media; + + for (i=0; i<url.length; i++) { + media = url[i]; + if (this.canPlayType(media.type)) { + this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(media.src)); + this.src = mejs.Utility.absolutizeUrl(url); + break; + } + } + } + + }, + setCurrentTime: function (time) { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + this.pluginApi.seekTo(time); + } else { + this.pluginApi.setCurrentTime(time); + } + + + + this.currentTime = time; + } + }, + setVolume: function (volume) { + if (this.pluginApi != null) { + // same on YouTube and MEjs + if (this.pluginType == 'youtube') { + this.pluginApi.setVolume(volume * 100); + } else { + this.pluginApi.setVolume(volume); + } + this.volume = volume; + } + }, + setMuted: function (muted) { + if (this.pluginApi != null) { + if (this.pluginType == 'youtube') { + if (muted) { + this.pluginApi.mute(); + } else { + this.pluginApi.unMute(); + } + this.muted = muted; + this.dispatchEvent('volumechange'); + } else { + this.pluginApi.setMuted(muted); + } + this.muted = muted; + } + }, + + // additional non-HTML5 methods + setVideoSize: function (width, height) { + + //if (this.pluginType == 'flash' || this.pluginType == 'silverlight') { + if ( this.pluginElement.style) { + this.pluginElement.style.width = width + 'px'; + this.pluginElement.style.height = height + 'px'; + } + if (this.pluginApi != null && this.pluginApi.setVideoSize) { + this.pluginApi.setVideoSize(width, height); + } + //} + }, + + setFullscreen: function (fullscreen) { + if (this.pluginApi != null && this.pluginApi.setFullscreen) { + this.pluginApi.setFullscreen(fullscreen); + } + }, + + enterFullScreen: function() { + if (this.pluginApi != null && this.pluginApi.setFullscreen) { + this.setFullscreen(true); + } + + }, + + exitFullScreen: function() { + if (this.pluginApi != null && this.pluginApi.setFullscreen) { + this.setFullscreen(false); + } + }, + + // start: fake events + addEventListener: function (eventName, callback, bubble) { + this.events[eventName] = this.events[eventName] || []; + this.events[eventName].push(callback); + }, + removeEventListener: function (eventName, callback) { + if (!eventName) { this.events = {}; return true; } + var callbacks = this.events[eventName]; + if (!callbacks) return true; + if (!callback) { this.events[eventName] = []; return true; } + for (i = 0; i < callbacks.length; i++) { + if (callbacks[i] === callback) { + this.events[eventName].splice(i, 1); + return true; + } + } + return false; + }, + dispatchEvent: function (eventName) { + var i, + args, + callbacks = this.events[eventName]; + + if (callbacks) { + args = Array.prototype.slice.call(arguments, 1); + for (i = 0; i < callbacks.length; i++) { + callbacks[i].apply(null, args); + } + } + }, + // end: fake events + + // fake DOM attribute methods + hasAttribute: function(name){ + return (name in this.attributes); + }, + removeAttribute: function(name){ + delete this.attributes[name]; + }, + getAttribute: function(name){ + if (this.hasAttribute(name)) { + return this.attributes[name]; + } + return ''; + }, + setAttribute: function(name, value){ + this.attributes[name] = value; + }, + + remove: function() { + mejs.Utility.removeSwf(this.pluginElement.id); + mejs.MediaPluginBridge.unregisterPluginElement(this.pluginElement.id); + } +}; + +// Handles calls from Flash/Silverlight and reports them as native <video/audio> events and properties +mejs.MediaPluginBridge = { + + pluginMediaElements:{}, + htmlMediaElements:{}, + + registerPluginElement: function (id, pluginMediaElement, htmlMediaElement) { + this.pluginMediaElements[id] = pluginMediaElement; + this.htmlMediaElements[id] = htmlMediaElement; + }, + + unregisterPluginElement: function (id) { + delete this.pluginMediaElements[id]; + delete this.htmlMediaElements[id]; + }, + + // when Flash/Silverlight is ready, it calls out to this method + initPlugin: function (id) { + + var pluginMediaElement = this.pluginMediaElements[id], + htmlMediaElement = this.htmlMediaElements[id]; + + if (pluginMediaElement) { + // find the javascript bridge + switch (pluginMediaElement.pluginType) { + case "flash": + pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id); + break; + case "silverlight": + pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id); + pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS; + break; + } + + if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) { + pluginMediaElement.success(pluginMediaElement, htmlMediaElement); + } + } + }, + + // receives events from Flash/Silverlight and sends them out as HTML5 media events + // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html + fireEvent: function (id, eventName, values) { + + var + e, + i, + bufferedTime, + pluginMediaElement = this.pluginMediaElements[id]; + + // fake event object to mimic real HTML media event. + e = { + type: eventName, + target: pluginMediaElement + }; + + // attach all values to element and event object + for (i in values) { + pluginMediaElement[i] = values[i]; + e[i] = values[i]; + } + + // fake the newer W3C buffered TimeRange (loaded and total have been removed) + bufferedTime = values.bufferedTime || 0; + + e.target.buffered = e.buffered = { + start: function(index) { + return 0; + }, + end: function (index) { + return bufferedTime; + }, + length: 1 + }; + + pluginMediaElement.dispatchEvent(e.type, e); + } +}; + +/* +Default options +*/ +mejs.MediaElementDefaults = { + // allows testing on HTML5, flash, silverlight + // auto: attempts to detect what the browser can do + // auto_plugin: prefer plugins and then attempt native HTML5 + // native: forces HTML5 playback + // shim: disallows HTML5, will attempt either Flash or Silverlight + // none: forces fallback view + mode: 'auto', + // remove or reorder to change plugin priority and availability + plugins: ['flash','silverlight','youtube','vimeo'], + // shows debug errors on screen + enablePluginDebug: false, + // overrides the type specified, useful for dynamic instantiation + type: '', + // path to Flash and Silverlight plugins + pluginPath: mejs.Utility.getScriptPath(['mediaelement.js','mediaelement.min.js','mediaelement-and-player.js','mediaelement-and-player.min.js']), + // name of flash file + flashName: 'flashmediaelement.swf', + // streamer for RTMP streaming + flashStreamer: '', + // turns on the smoothing filter in Flash + enablePluginSmoothing: false, + // enabled pseudo-streaming (seek) on .mp4 files + enablePseudoStreaming: false, + // start query parameter sent to server for pseudo-streaming + pseudoStreamingStartQueryParam: 'start', + // name of silverlight file + silverlightName: 'silverlightmediaelement.xap', + // default if the <video width> is not specified + defaultVideoWidth: 480, + // default if the <video height> is not specified + defaultVideoHeight: 270, + // overrides <video width> + pluginWidth: -1, + // overrides <video height> + pluginHeight: -1, + // additional plugin variables in 'key=value' form + pluginVars: [], + // rate in milliseconds for Flash and Silverlight to fire the timeupdate event + // larger number is less accurate, but less strain on plugin->JavaScript bridge + timerRate: 250, + // initial volume for player + startVolume: 0.8, + success: function () { }, + error: function () { } +}; + +/* +Determines if a browser supports the <video> or <audio> element +and returns either the native element or a Flash/Silverlight version that +mimics HTML5 MediaElement +*/ +mejs.MediaElement = function (el, o) { + return mejs.HtmlMediaElementShim.create(el,o); +}; + +mejs.HtmlMediaElementShim = { + + create: function(el, o) { + var + options = mejs.MediaElementDefaults, + htmlMediaElement = (typeof(el) == 'string') ? document.getElementById(el) : el, + tagName = htmlMediaElement.tagName.toLowerCase(), + isMediaTag = (tagName === 'audio' || tagName === 'video'), + src = (isMediaTag) ? htmlMediaElement.getAttribute('src') : htmlMediaElement.getAttribute('href'), + poster = htmlMediaElement.getAttribute('poster'), + autoplay = htmlMediaElement.getAttribute('autoplay'), + preload = htmlMediaElement.getAttribute('preload'), + controls = htmlMediaElement.getAttribute('controls'), + playback, + prop; + + // extend options + for (prop in o) { + options[prop] = o[prop]; + } + + // clean up attributes + src = (typeof src == 'undefined' || src === null || src == '') ? null : src; + poster = (typeof poster == 'undefined' || poster === null) ? '' : poster; + preload = (typeof preload == 'undefined' || preload === null || preload === 'false') ? 'none' : preload; + autoplay = !(typeof autoplay == 'undefined' || autoplay === null || autoplay === 'false'); + controls = !(typeof controls == 'undefined' || controls === null || controls === 'false'); + + // test for HTML5 and plugin capabilities + playback = this.determinePlayback(htmlMediaElement, options, mejs.MediaFeatures.supportsMediaTag, isMediaTag, src); + playback.url = (playback.url !== null) ? mejs.Utility.absolutizeUrl(playback.url) : ''; + + if (playback.method == 'native') { + // second fix for android + if (mejs.MediaFeatures.isBustedAndroid) { + htmlMediaElement.src = playback.url; + htmlMediaElement.addEventListener('click', function() { + htmlMediaElement.play(); + }, false); + } + + // add methods to native HTMLMediaElement + return this.updateNative(playback, options, autoplay, preload); + } else if (playback.method !== '') { + // create plugin to mimic HTMLMediaElement + + return this.createPlugin( playback, options, poster, autoplay, preload, controls); + } else { + // boo, no HTML5, no Flash, no Silverlight. + this.createErrorMessage( playback, options, poster ); + + return this; + } + }, + + determinePlayback: function(htmlMediaElement, options, supportsMediaTag, isMediaTag, src) { + var + mediaFiles = [], + i, + j, + k, + l, + n, + type, + result = { method: '', url: '', htmlMediaElement: htmlMediaElement, isVideo: (htmlMediaElement.tagName.toLowerCase() != 'audio')}, + pluginName, + pluginVersions, + pluginInfo, + dummy, + media; + + // STEP 1: Get URL and type from <video src> or <source src> + + // supplied type overrides <video type> and <source type> + if (typeof options.type != 'undefined' && options.type !== '') { + + // accept either string or array of types + if (typeof options.type == 'string') { + mediaFiles.push({type:options.type, url:src}); + } else { + + for (i=0; i<options.type.length; i++) { + mediaFiles.push({type:options.type[i], url:src}); + } + } + + // test for src attribute first + } else if (src !== null) { + type = this.formatType(src, htmlMediaElement.getAttribute('type')); + mediaFiles.push({type:type, url:src}); + + // then test for <source> elements + } else { + // test <source> types to see if they are usable + for (i = 0; i < htmlMediaElement.childNodes.length; i++) { + n = htmlMediaElement.childNodes[i]; + if (n.nodeType == 1 && n.tagName.toLowerCase() == 'source') { + src = n.getAttribute('src'); + type = this.formatType(src, n.getAttribute('type')); + media = n.getAttribute('media'); + + if (!media || !window.matchMedia || (window.matchMedia && window.matchMedia(media).matches)) { + mediaFiles.push({type:type, url:src}); + } + } + } + } + + // in the case of dynamicly created players + // check for audio types + if (!isMediaTag && mediaFiles.length > 0 && mediaFiles[0].url !== null && this.getTypeFromFile(mediaFiles[0].url).indexOf('audio') > -1) { + result.isVideo = false; + } + + + // STEP 2: Test for playback method + + // special case for Android which sadly doesn't implement the canPlayType function (always returns '') + if (mejs.MediaFeatures.isBustedAndroid) { + htmlMediaElement.canPlayType = function(type) { + return (type.match(/video\/(mp4|m4v)/gi) !== null) ? 'maybe' : ''; + }; + } + + + // test for native playback first + if (supportsMediaTag && (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'native') && !(mejs.MediaFeatures.isBustedNativeHTTPS)) { + + if (!isMediaTag) { + + // create a real HTML5 Media Element + dummy = document.createElement( result.isVideo ? 'video' : 'audio'); + htmlMediaElement.parentNode.insertBefore(dummy, htmlMediaElement); + htmlMediaElement.style.display = 'none'; + + // use this one from now on + result.htmlMediaElement = htmlMediaElement = dummy; + } + + for (i=0; i<mediaFiles.length; i++) { + // normal check + if (htmlMediaElement.canPlayType(mediaFiles[i].type).replace(/no/, '') !== '' + // special case for Mac/Safari 5.0.3 which answers '' to canPlayType('audio/mp3') but 'maybe' to canPlayType('audio/mpeg') + || htmlMediaElement.canPlayType(mediaFiles[i].type.replace(/mp3/,'mpeg')).replace(/no/, '') !== '') { + result.method = 'native'; + result.url = mediaFiles[i].url; + break; + } + } + + if (result.method === 'native') { + if (result.url !== null) { + htmlMediaElement.src = result.url; + } + + // if `auto_plugin` mode, then cache the native result but try plugins. + if (options.mode !== 'auto_plugin') { + return result; + } + } + } + + // if native playback didn't work, then test plugins + if (options.mode === 'auto' || options.mode === 'auto_plugin' || options.mode === 'shim') { + for (i=0; i<mediaFiles.length; i++) { + type = mediaFiles[i].type; + + // test all plugins in order of preference [silverlight, flash] + for (j=0; j<options.plugins.length; j++) { + + pluginName = options.plugins[j]; + + // test version of plugin (for future features) + pluginVersions = mejs.plugins[pluginName]; + + for (k=0; k<pluginVersions.length; k++) { + pluginInfo = pluginVersions[k]; + + // test if user has the correct plugin version + + // for youtube/vimeo + if (pluginInfo.version == null || + + mejs.PluginDetector.hasPluginVersion(pluginName, pluginInfo.version)) { + + // test for plugin playback types + for (l=0; l<pluginInfo.types.length; l++) { + // find plugin that can play the type + if (type == pluginInfo.types[l]) { + result.method = pluginName; + result.url = mediaFiles[i].url; + return result; + } + } + } + } + } + } + } + + // at this point, being in 'auto_plugin' mode implies that we tried plugins but failed. + // if we have native support then return that. + if (options.mode === 'auto_plugin' && result.method === 'native') { + return result; + } + + // what if there's nothing to play? just grab the first available + if (result.method === '' && mediaFiles.length > 0) { + result.url = mediaFiles[0].url; + } + + return result; + }, + + formatType: function(url, type) { + var ext; + + // if no type is supplied, fake it with the extension + if (url && !type) { + return this.getTypeFromFile(url); + } else { + // only return the mime part of the type in case the attribute contains the codec + // see http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#the-source-element + // `video/mp4; codecs="avc1.42E01E, mp4a.40.2"` becomes `video/mp4` + + if (type && ~type.indexOf(';')) { + return type.substr(0, type.indexOf(';')); + } else { + return type; + } + } + }, + + getTypeFromFile: function(url) { + url = url.split('?')[0]; + var ext = url.substring(url.lastIndexOf('.') + 1).toLowerCase(); + return (/(mp4|m4v|ogg|ogv|webm|webmv|flv|wmv|mpeg|mov)/gi.test(ext) ? 'video' : 'audio') + '/' + this.getTypeFromExtension(ext); + }, + + getTypeFromExtension: function(ext) { + + switch (ext) { + case 'mp4': + case 'm4v': + return 'mp4'; + case 'webm': + case 'webma': + case 'webmv': + return 'webm'; + case 'ogg': + case 'oga': + case 'ogv': + return 'ogg'; + default: + return ext; + } + }, + + createErrorMessage: function(playback, options, poster) { + var + htmlMediaElement = playback.htmlMediaElement, + errorContainer = document.createElement('div'); + + errorContainer.className = 'me-cannotplay'; + + try { + errorContainer.style.width = htmlMediaElement.width + 'px'; + errorContainer.style.height = htmlMediaElement.height + 'px'; + } catch (e) {} + + if (options.customError) { + errorContainer.innerHTML = options.customError; + } else { + errorContainer.innerHTML = (poster !== '') ? + '<a href="' + playback.url + '"><img src="' + poster + '" width="100%" height="100%" /></a>' : + '<a href="' + playback.url + '"><span>' + mejs.i18n.t('Download File') + '</span></a>'; + } + + htmlMediaElement.parentNode.insertBefore(errorContainer, htmlMediaElement); + htmlMediaElement.style.display = 'none'; + + options.error(htmlMediaElement); + }, + + createPlugin:function(playback, options, poster, autoplay, preload, controls) { + var + htmlMediaElement = playback.htmlMediaElement, + width = 1, + height = 1, + pluginid = 'me_' + playback.method + '_' + (mejs.meIndex++), + pluginMediaElement = new mejs.PluginMediaElement(pluginid, playback.method, playback.url), + container = document.createElement('div'), + specialIEContainer, + node, + initVars; + + // copy tagName from html media element + pluginMediaElement.tagName = htmlMediaElement.tagName + + // copy attributes from html media element to plugin media element + for (var i = 0; i < htmlMediaElement.attributes.length; i++) { + var attribute = htmlMediaElement.attributes[i]; + if (attribute.specified == true) { + pluginMediaElement.setAttribute(attribute.name, attribute.value); + } + } + + // check for placement inside a <p> tag (sometimes WYSIWYG editors do this) + node = htmlMediaElement.parentNode; + while (node !== null && node.tagName.toLowerCase() != 'body') { + if (node.parentNode.tagName.toLowerCase() == 'p') { + node.parentNode.parentNode.insertBefore(node, node.parentNode); + break; + } + node = node.parentNode; + } + + if (playback.isVideo) { + width = (options.pluginWidth > 0) ? options.pluginWidth : (options.videoWidth > 0) ? options.videoWidth : (htmlMediaElement.getAttribute('width') !== null) ? htmlMediaElement.getAttribute('width') : options.defaultVideoWidth; + height = (options.pluginHeight > 0) ? options.pluginHeight : (options.videoHeight > 0) ? options.videoHeight : (htmlMediaElement.getAttribute('height') !== null) ? htmlMediaElement.getAttribute('height') : options.defaultVideoHeight; + + // in case of '%' make sure it's encoded + width = mejs.Utility.encodeUrl(width); + height = mejs.Utility.encodeUrl(height); + + } else { + if (options.enablePluginDebug) { + width = 320; + height = 240; + } + } + + // register plugin + pluginMediaElement.success = options.success; + mejs.MediaPluginBridge.registerPluginElement(pluginid, pluginMediaElement, htmlMediaElement); + + // add container (must be added to DOM before inserting HTML for IE) + container.className = 'me-plugin'; + container.id = pluginid + '_container'; + + if (playback.isVideo) { + htmlMediaElement.parentNode.insertBefore(container, htmlMediaElement); + } else { + document.body.insertBefore(container, document.body.childNodes[0]); + } + + // flash/silverlight vars + initVars = [ + 'id=' + pluginid, + 'isvideo=' + ((playback.isVideo) ? "true" : "false"), + 'autoplay=' + ((autoplay) ? "true" : "false"), + 'preload=' + preload, + 'width=' + width, + 'startvolume=' + options.startVolume, + 'timerrate=' + options.timerRate, + 'flashstreamer=' + options.flashStreamer, + 'height=' + height, + 'pseudostreamstart=' + options.pseudoStreamingStartQueryParam]; + + if (playback.url !== null) { + if (playback.method == 'flash') { + initVars.push('file=' + mejs.Utility.encodeUrl(playback.url)); + } else { + initVars.push('file=' + playback.url); + } + } + if (options.enablePluginDebug) { + initVars.push('debug=true'); + } + if (options.enablePluginSmoothing) { + initVars.push('smoothing=true'); + } + if (options.enablePseudoStreaming) { + initVars.push('pseudostreaming=true'); + } + if (controls) { + initVars.push('controls=true'); // shows controls in the plugin if desired + } + if (options.pluginVars) { + initVars = initVars.concat(options.pluginVars); + } + + switch (playback.method) { + case 'silverlight': + container.innerHTML = +'<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="' + pluginid + '" name="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' + +'<param name="initParams" value="' + initVars.join(',') + '" />' + +'<param name="windowless" value="true" />' + +'<param name="background" value="black" />' + +'<param name="minRuntimeVersion" value="3.0.0.0" />' + +'<param name="autoUpgrade" value="true" />' + +'<param name="source" value="' + options.pluginPath + options.silverlightName + '" />' + +'</object>'; + break; + + case 'flash': + + if (mejs.MediaFeatures.isIE) { + specialIEContainer = document.createElement('div'); + container.appendChild(specialIEContainer); + specialIEContainer.outerHTML = +'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' + +'id="' + pluginid + '" width="' + width + '" height="' + height + '" class="mejs-shim">' + +'<param name="movie" value="' + options.pluginPath + options.flashName + '?x=' + (new Date()) + '" />' + +'<param name="flashvars" value="' + initVars.join('&amp;') + '" />' + +'<param name="quality" value="high" />' + +'<param name="bgcolor" value="#000000" />' + +'<param name="wmode" value="transparent" />' + +'<param name="allowScriptAccess" value="always" />' + +'<param name="allowFullScreen" value="true" />' + +'</object>'; + + } else { + + container.innerHTML = +'<embed id="' + pluginid + '" name="' + pluginid + '" ' + +'play="true" ' + +'loop="false" ' + +'quality="high" ' + +'bgcolor="#000000" ' + +'wmode="transparent" ' + +'allowScriptAccess="always" ' + +'allowFullScreen="true" ' + +'type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" ' + +'src="' + options.pluginPath + options.flashName + '" ' + +'flashvars="' + initVars.join('&') + '" ' + +'width="' + width + '" ' + +'height="' + height + '" ' + +'class="mejs-shim"></embed>'; + } + break; + + case 'youtube': + + + var + videoId = playback.url.substr(playback.url.lastIndexOf('=')+1); + youtubeSettings = { + container: container, + containerId: container.id, + pluginMediaElement: pluginMediaElement, + pluginId: pluginid, + videoId: videoId, + height: height, + width: width + }; + + if (mejs.PluginDetector.hasPluginVersion('flash', [10,0,0]) ) { + mejs.YouTubeApi.createFlash(youtubeSettings); + } else { + mejs.YouTubeApi.enqueueIframe(youtubeSettings); + } + + break; + + // DEMO Code. Does NOT work. + case 'vimeo': + //console.log('vimeoid'); + + pluginMediaElement.vimeoid = playback.url.substr(playback.url.lastIndexOf('/')+1); + + container.innerHTML ='<iframe src="http://player.vimeo.com/video/' + pluginMediaElement.vimeoid + '?portrait=0&byline=0&title=0" width="' + width +'" height="' + height +'" frameborder="0" class="mejs-shim"></iframe>'; + + /* + container.innerHTML = + '<object width="' + width + '" height="' + height + '" class="mejs-shim">' + + '<param name="allowfullscreen" value="true" />' + + '<param name="allowscriptaccess" value="always" />' + + '<param name="flashvars" value="api=1" />' + + '<param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + pluginMediaElement.vimeoid + '&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" />' + + '<embed src="//vimeo.com/moogaloop.swf?api=1&amp;clip_id=' + pluginMediaElement.vimeoid + '&amp;server=vimeo.com&amp;show_title=0&amp;show_byline=0&amp;show_portrait=0&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="' + width + '" height="' + height + '" class="mejs-shim"></embed>' + + '</object>'; + */ + + break; + } + // hide original element + htmlMediaElement.style.display = 'none'; + + // FYI: options.success will be fired by the MediaPluginBridge + + return pluginMediaElement; + }, + + updateNative: function(playback, options, autoplay, preload) { + + var htmlMediaElement = playback.htmlMediaElement, + m; + + + // add methods to video object to bring it into parity with Flash Object + for (m in mejs.HtmlMediaElement) { + htmlMediaElement[m] = mejs.HtmlMediaElement[m]; + } + + /* + Chrome now supports preload="none" + if (mejs.MediaFeatures.isChrome) { + + // special case to enforce preload attribute (Chrome doesn't respect this) + if (preload === 'none' && !autoplay) { + + // forces the browser to stop loading (note: fails in IE9) + htmlMediaElement.src = ''; + htmlMediaElement.load(); + htmlMediaElement.canceledPreload = true; + + htmlMediaElement.addEventListener('play',function() { + if (htmlMediaElement.canceledPreload) { + htmlMediaElement.src = playback.url; + htmlMediaElement.load(); + htmlMediaElement.play(); + htmlMediaElement.canceledPreload = false; + } + }, false); + // for some reason Chrome forgets how to autoplay sometimes. + } else if (autoplay) { + htmlMediaElement.load(); + htmlMediaElement.play(); + } + } + */ + + // fire success code + options.success(htmlMediaElement, htmlMediaElement); + + return htmlMediaElement; + } +}; + +/* + - test on IE (object vs. embed) + - determine when to use iframe (Firefox, Safari, Mobile) vs. Flash (Chrome, IE) + - fullscreen? +*/ + +// YouTube Flash and Iframe API +mejs.YouTubeApi = { + isIframeStarted: false, + isIframeLoaded: false, + loadIframeApi: function() { + if (!this.isIframeStarted) { + var tag = document.createElement('script'); + tag.src = "//www.youtube.com/player_api"; + var firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + this.isIframeStarted = true; + } + }, + iframeQueue: [], + enqueueIframe: function(yt) { + + if (this.isLoaded) { + this.createIframe(yt); + } else { + this.loadIframeApi(); + this.iframeQueue.push(yt); + } + }, + createIframe: function(settings) { + + var + pluginMediaElement = settings.pluginMediaElement, + player = new YT.Player(settings.containerId, { + height: settings.height, + width: settings.width, + videoId: settings.videoId, + playerVars: {controls:0}, + events: { + 'onReady': function() { + + // hook up iframe object to MEjs + settings.pluginMediaElement.pluginApi = player; + + // init mejs + mejs.MediaPluginBridge.initPlugin(settings.pluginId); + + // create timer + setInterval(function() { + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate'); + }, 250); + }, + 'onStateChange': function(e) { + + mejs.YouTubeApi.handleStateChange(e.data, player, pluginMediaElement); + + } + } + }); + }, + + createEvent: function (player, pluginMediaElement, eventName) { + var obj = { + type: eventName, + target: pluginMediaElement + }; + + if (player && player.getDuration) { + + // time + pluginMediaElement.currentTime = obj.currentTime = player.getCurrentTime(); + pluginMediaElement.duration = obj.duration = player.getDuration(); + + // state + obj.paused = pluginMediaElement.paused; + obj.ended = pluginMediaElement.ended; + + // sound + obj.muted = player.isMuted(); + obj.volume = player.getVolume() / 100; + + // progress + obj.bytesTotal = player.getVideoBytesTotal(); + obj.bufferedBytes = player.getVideoBytesLoaded(); + + // fake the W3C buffered TimeRange + var bufferedTime = obj.bufferedBytes / obj.bytesTotal * obj.duration; + + obj.target.buffered = obj.buffered = { + start: function(index) { + return 0; + }, + end: function (index) { + return bufferedTime; + }, + length: 1 + }; + + } + + // send event up the chain + pluginMediaElement.dispatchEvent(obj.type, obj); + }, + + iFrameReady: function() { + + this.isLoaded = true; + this.isIframeLoaded = true; + + while (this.iframeQueue.length > 0) { + var settings = this.iframeQueue.pop(); + this.createIframe(settings); + } + }, + + // FLASH! + flashPlayers: {}, + createFlash: function(settings) { + + this.flashPlayers[settings.pluginId] = settings; + + /* + settings.container.innerHTML = + '<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0" ' + + 'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' + + '<param name="allowScriptAccess" value="always">' + + '<param name="wmode" value="transparent">' + + '</object>'; + */ + + var specialIEContainer, + youtubeUrl = '//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid=' + settings.pluginId + '&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0'; + + if (mejs.MediaFeatures.isIE) { + + specialIEContainer = document.createElement('div'); + settings.container.appendChild(specialIEContainer); + specialIEContainer.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" ' + +'id="' + settings.pluginId + '" width="' + settings.width + '" height="' + settings.height + '" class="mejs-shim">' + + '<param name="movie" value="' + youtubeUrl + '" />' + + '<param name="wmode" value="transparent" />' + + '<param name="allowScriptAccess" value="always" />' + + '<param name="allowFullScreen" value="true" />' + +'</object>'; + } else { + settings.container.innerHTML = + '<object type="application/x-shockwave-flash" id="' + settings.pluginId + '" data="' + youtubeUrl + '" ' + + 'width="' + settings.width + '" height="' + settings.height + '" style="visibility: visible; " class="mejs-shim">' + + '<param name="allowScriptAccess" value="always">' + + '<param name="wmode" value="transparent">' + + '</object>'; + } + + }, + + flashReady: function(id) { + var + settings = this.flashPlayers[id], + player = document.getElementById(id), + pluginMediaElement = settings.pluginMediaElement; + + // hook up and return to MediaELementPlayer.success + pluginMediaElement.pluginApi = + pluginMediaElement.pluginElement = player; + mejs.MediaPluginBridge.initPlugin(id); + + // load the youtube video + player.cueVideoById(settings.videoId); + + var callbackName = settings.containerId + '_callback'; + + window[callbackName] = function(e) { + mejs.YouTubeApi.handleStateChange(e, player, pluginMediaElement); + } + + player.addEventListener('onStateChange', callbackName); + + setInterval(function() { + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'timeupdate'); + }, 250); + }, + + handleStateChange: function(youTubeState, player, pluginMediaElement) { + switch (youTubeState) { + case -1: // not started + pluginMediaElement.paused = true; + pluginMediaElement.ended = true; + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'loadedmetadata'); + //createYouTubeEvent(player, pluginMediaElement, 'loadeddata'); + break; + case 0: + pluginMediaElement.paused = false; + pluginMediaElement.ended = true; + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'ended'); + break; + case 1: + pluginMediaElement.paused = false; + pluginMediaElement.ended = false; + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'play'); + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'playing'); + break; + case 2: + pluginMediaElement.paused = true; + pluginMediaElement.ended = false; + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'pause'); + break; + case 3: // buffering + mejs.YouTubeApi.createEvent(player, pluginMediaElement, 'progress'); + break; + case 5: + // cued? + break; + + } + + } +} +// IFRAME +function onYouTubePlayerAPIReady() { + mejs.YouTubeApi.iFrameReady(); +} +// FLASH +function onYouTubePlayerReady(id) { + mejs.YouTubeApi.flashReady(id); +} + +window.mejs = mejs; +window.MediaElement = mejs.MediaElement; + +/*! + * Adds Internationalization and localization to objects. + * + * What is the concept beyond i18n? + * http://en.wikipedia.org/wiki/Internationalization_and_localization + * + * + * This file both i18n methods and locale which is used to translate + * strings into other languages. + * + * Default translations are not available, you have to add them + * through locale objects which are named exactly as the langcode + * they stand for. The default language is always english (en). + * + * + * Wrapper built to be able to attach the i18n object to + * other objects without changing more than one line. + * + * + * LICENSE: + * + * The i18n file uses methods from the Drupal project (drupal.js): + * - i18n.methods.t() (modified) + * - i18n.methods.checkPlain() (full copy) + * - i18n.methods.formatString() (full copy) + * + * The Drupal project is (like mediaelementjs) licensed under GPLv2. + * - http://drupal.org/licensing/faq/#q1 + * - https://github.com/johndyer/mediaelement + * - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * + * + * @author + * Tim Latz (latz.tim@gmail.com) + * + * @see + * me-i18n-locale.js + * + * @params + * - context - document, iframe .. + * - exports - CommonJS, window .. + * + */ +;(function(context, exports, undefined) { + "use strict"; + var i18n = { + "locale": { + "strings" : {} + }, + "methods" : {} + }; +// start i18n + + + /** + * Get the current browser's language + * + * @see: i18n.methods.t() + */ + i18n.locale.getLanguage = function () { + return i18n.locale || { + "language" : navigator.language + }; + }; + + /** + * Store the language the locale object was initialized with + */ + i18n.locale.INIT_LANGUAGE = i18n.locale.getLanguage(); + + + /** + * Encode special characters in a plain-text string for display as HTML. + */ + i18n.methods.checkPlain = function (str) { + var character, regex, + replace = { + '&': '&amp;', + '"': '&quot;', + '<': '&lt;', + '>': '&gt;' + }; + str = String(str); + for (character in replace) { + if (replace.hasOwnProperty(character)) { + regex = new RegExp(character, 'g'); + str = str.replace(regex, replace[character]); + } + } + return str; + }; + + /** + * Replace placeholders with sanitized values in a string. + * + * @param str + * A string with placeholders. + * @param args + * An object of replacements pairs to make. Incidences of any key in this + * array are replaced with the corresponding value. Based on the first + * character of the key, the value is escaped and/or themed: + * - !variable: inserted as is + * - @variable: escape plain text to HTML (i18n.methods.checkPlain) + * - %variable: escape text and theme as a placeholder for user-submitted + * content (checkPlain + <em class="placeholder" > ) + * + * @see i18n.methods.t() + */ + i18n.methods.formatString = function(str, args) { + // Transform arguments before inserting them. + for (var key in args) { + switch (key.charAt(0)) { + // Escaped only. + case '@': + args[key] = i18n.methods.checkPlain(args[key]); + break; + // Pass-through. + case '!': + break; + // Escaped and placeholder. + case '%': + default: + args[key] = '<em class="placeholder">' + i18n.methods.checkPlain(args[key]) + '</em>'; + break; + } + str = str.replace(key, args[key]); + } + return str; + }; + + /** + * Translate strings to the page language or a given language. + * + * See the documentation of the server-side t() function for further details. + * + * @param str + * A string containing the English string to translate. + * @param args + * An object of replacements pairs to make after translation. Incidences + * of any key in this array are replaced with the corresponding value. + * See i18n.methods.formatString(). + * + * @param options + * - 'context' (defaults to the default context): The context the source string + * belongs to. + * + * @return + * The translated string. + */ + i18n.methods.t = function (str, args, options) { + + // Fetch the localized version of the string. + if (i18n.locale.strings && i18n.locale.strings[options.context] && i18n.locale.strings[options.context][str]) { + str = i18n.locale.strings[options.context][str]; + } + + if (args) { + str = i18n.methods.formatString(str, args); + } + return str; + }; + + + /** + * Wrapper for i18n.methods.t() + * + * @see i18n.methods.t() + * @throws InvalidArgumentException + */ + i18n.t = function(str, args, options) { + + if (typeof str === 'string' && str.length > 0) { + + // check every time due languge can change for + // different reasons (translation, lang switcher ..) + var lang = i18n.locale.getLanguage(); + + options = options || { + "context" : lang.language + }; + + return i18n.methods.t(str, args, options); + } + else { + throw { + "name" : 'InvalidArgumentException', + "message" : 'First argument is either not a string or empty.' + } + } + }; + +// end i18n + exports.i18n = i18n; +}(document, mejs)); + +;(function(exports, undefined) { + + "use strict"; + + if ( mejs.i18n.locale.language && mejs.i18n.locale.strings ) { + exports[mejs.i18n.locale.language] = mejs.i18n.locale.strings; + } + +}(mejs.i18n.locale.strings)); + +/*! + * This is a i18n.locale language object. + * + *<de> German translation by Tim Latz, latz.tim@gmail.com + * + * @author + * Tim Latz (latz.tim@gmail.com) + * + * @see + * me-i18n.js + * + * @params + * - exports - CommonJS, window .. + */ +;(function(exports, undefined) { + + "use strict"; + + exports.de = { + "Fullscreen" : "Vollbild", + "Go Fullscreen" : "Vollbild an", + "Turn off Fullscreen" : "Vollbild aus", + "Close" : "Schließen" + }; + +}(mejs.i18n.locale.strings)); +/*! + * This is a i18n.locale language object. + * + *<de> Traditional chinese translation by Tim Latz, latz.tim@gmail.com + * + * @author + * Tim Latz (latz.tim@gmail.com) + * + * @see + * me-i18n.js + * + * @params + * - exports - CommonJS, window .. + */ +;(function(exports, undefined) { + + "use strict"; + + exports.zh = { + "Fullscreen" : "全螢幕", + "Go Fullscreen" : "å…¨å±æ¨¡å¼", + "Turn off Fullscreen" : "退出全å±æ¨¡å¼", + "Close" : "關閉" + }; + +}(mejs.i18n.locale.strings)); + diff --git a/src/static/mediaelement/mediaelement.min.js b/src/static/mediaelement/mediaelement.min.js new file mode 100755 index 0000000..962ce4f --- /dev/null +++ b/src/static/mediaelement/mediaelement.min.js @@ -0,0 +1,67 @@ +/*! +* MediaElement.js +* HTML5 <video> and <audio> shim and player +* http://mediaelementjs.com/ +* +* Creates a JavaScript object that mimics HTML5 MediaElement API +* for browsers that don't understand HTML5 or can't play the provided codec +* Can play MP4 (H.264), Ogg, WebM, FLV, WMV, WMA, ACC, and MP3 +* +* Copyright 2010-2013, John Dyer (http://j.hn) +* License: MIT +* +*/var mejs=mejs||{};mejs.version="2.12.0";mejs.meIndex=0; +mejs.plugins={silverlight:[{version:[3,0],types:["video/mp4","video/m4v","video/mov","video/wmv","audio/wma","audio/m4a","audio/mp3","audio/wav","audio/mpeg"]}],flash:[{version:[9,0,124],types:["video/mp4","video/m4v","video/mov","video/flv","video/rtmp","video/x-flv","audio/flv","audio/x-flv","audio/mp3","audio/m4a","audio/mpeg","video/youtube","video/x-youtube"]}],youtube:[{version:null,types:["video/youtube","video/x-youtube","audio/youtube","audio/x-youtube"]}],vimeo:[{version:null,types:["video/vimeo", +"video/x-vimeo"]}]}; +mejs.Utility={encodeUrl:function(a){return encodeURIComponent(a)},escapeHTML:function(a){return a.toString().split("&").join("&amp;").split("<").join("&lt;").split('"').join("&quot;")},absolutizeUrl:function(a){var b=document.createElement("div");b.innerHTML='<a href="'+this.escapeHTML(a)+'">x</a>';return b.firstChild.href},getScriptPath:function(a){for(var b=0,c,d="",e="",f,g,h=document.getElementsByTagName("script"),l=h.length,j=a.length;b<l;b++){f=h[b].src;c=f.lastIndexOf("/");if(c>-1){g=f.substring(c+ +1);f=f.substring(0,c+1)}else{g=f;f=""}for(c=0;c<j;c++){e=a[c];e=g.indexOf(e);if(e>-1){d=f;break}}if(d!=="")break}return d},secondsToTimeCode:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d=="undefined")d=25;var e=Math.floor(a/3600)%24,f=Math.floor(a/60)%60,g=Math.floor(a%60);a=Math.floor((a%1*d).toFixed(3));return(b||e>0?(e<10?"0"+e:e)+":":"")+(f<10?"0"+f:f)+":"+(g<10?"0"+g:g)+(c?":"+(a<10?"0"+a:a):"")},timeCodeToSeconds:function(a,b,c,d){if(typeof c=="undefined")c=false;else if(typeof d== +"undefined")d=25;a=a.split(":");b=parseInt(a[0],10);var e=parseInt(a[1],10),f=parseInt(a[2],10),g=0,h=0;if(c)g=parseInt(a[3])/d;return h=b*3600+e*60+f+g},convertSMPTEtoSeconds:function(a){if(typeof a!="string")return false;a=a.replace(",",".");var b=0,c=a.indexOf(".")!=-1?a.split(".")[1].length:0,d=1;a=a.split(":").reverse();for(var e=0;e<a.length;e++){d=1;if(e>0)d=Math.pow(60,e);b+=Number(a[e])*d}return Number(b.toFixed(c))},removeSwf:function(a){var b=document.getElementById(a);if(b&&/object|embed/i.test(b.nodeName))if(mejs.MediaFeatures.isIE){b.style.display= +"none";(function(){b.readyState==4?mejs.Utility.removeObjectInIE(a):setTimeout(arguments.callee,10)})()}else b.parentNode.removeChild(b)},removeObjectInIE:function(a){if(a=document.getElementById(a)){for(var b in a)if(typeof a[b]=="function")a[b]=null;a.parentNode.removeChild(a)}}}; +mejs.PluginDetector={hasPluginVersion:function(a,b){var c=this.plugins[a];b[1]=b[1]||0;b[2]=b[2]||0;return c[0]>b[0]||c[0]==b[0]&&c[1]>b[1]||c[0]==b[0]&&c[1]==b[1]&&c[2]>=b[2]?true:false},nav:window.navigator,ua:window.navigator.userAgent.toLowerCase(),plugins:[],addPlugin:function(a,b,c,d,e){this.plugins[a]=this.detectPlugin(b,c,d,e)},detectPlugin:function(a,b,c,d){var e=[0,0,0],f;if(typeof this.nav.plugins!="undefined"&&typeof this.nav.plugins[a]=="object"){if((c=this.nav.plugins[a].description)&& +!(typeof this.nav.mimeTypes!="undefined"&&this.nav.mimeTypes[b]&&!this.nav.mimeTypes[b].enabledPlugin)){e=c.replace(a,"").replace(/^\s+/,"").replace(/\sr/gi,".").split(".");for(a=0;a<e.length;a++)e[a]=parseInt(e[a].match(/\d+/),10)}}else if(typeof window.ActiveXObject!="undefined")try{if(f=new ActiveXObject(c))e=d(f)}catch(g){}return e}}; +mejs.PluginDetector.addPlugin("flash","Shockwave Flash","application/x-shockwave-flash","ShockwaveFlash.ShockwaveFlash",function(a){var b=[];if(a=a.GetVariable("$version")){a=a.split(" ")[1].split(",");b=[parseInt(a[0],10),parseInt(a[1],10),parseInt(a[2],10)]}return b}); +mejs.PluginDetector.addPlugin("silverlight","Silverlight Plug-In","application/x-silverlight-2","AgControl.AgControl",function(a){var b=[0,0,0,0],c=function(d,e,f,g){for(;d.isVersionSupported(e[0]+"."+e[1]+"."+e[2]+"."+e[3]);)e[f]+=g;e[f]-=g};c(a,b,0,1);c(a,b,1,1);c(a,b,2,1E4);c(a,b,2,1E3);c(a,b,2,100);c(a,b,2,10);c(a,b,2,1);c(a,b,3,1);return b}); +mejs.MediaFeatures={init:function(){var a=this,b=document,c=mejs.PluginDetector.nav,d=mejs.PluginDetector.ua.toLowerCase(),e,f=["source","track","audio","video"];a.isiPad=d.match(/ipad/i)!==null;a.isiPhone=d.match(/iphone/i)!==null;a.isiOS=a.isiPhone||a.isiPad;a.isAndroid=d.match(/android/i)!==null;a.isBustedAndroid=d.match(/android 2\.[12]/)!==null;a.isBustedNativeHTTPS=location.protocol==="https:"&&(d.match(/android [12]\./)!==null||d.match(/macintosh.* version.* safari/)!==null);a.isIE=c.appName.toLowerCase().indexOf("microsoft")!= +-1;a.isChrome=d.match(/chrome/gi)!==null;a.isFirefox=d.match(/firefox/gi)!==null;a.isWebkit=d.match(/webkit/gi)!==null;a.isGecko=d.match(/gecko/gi)!==null&&!a.isWebkit;a.isOpera=d.match(/opera/gi)!==null;a.hasTouch="ontouchstart"in window;a.svg=!!document.createElementNS&&!!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect;for(c=0;c<f.length;c++)e=document.createElement(f[c]);a.supportsMediaTag=typeof e.canPlayType!=="undefined"||a.isBustedAndroid;try{e.canPlayType("video/mp4")}catch(g){a.supportsMediaTag= +false}a.hasSemiNativeFullScreen=typeof e.webkitEnterFullscreen!=="undefined";a.hasWebkitNativeFullScreen=typeof e.webkitRequestFullScreen!=="undefined";a.hasMozNativeFullScreen=typeof e.mozRequestFullScreen!=="undefined";a.hasTrueNativeFullScreen=a.hasWebkitNativeFullScreen||a.hasMozNativeFullScreen;a.nativeFullScreenEnabled=a.hasTrueNativeFullScreen;if(a.hasMozNativeFullScreen)a.nativeFullScreenEnabled=e.mozFullScreenEnabled;if(this.isChrome)a.hasSemiNativeFullScreen=false;if(a.hasTrueNativeFullScreen){a.fullScreenEventName= +a.hasWebkitNativeFullScreen?"webkitfullscreenchange":"mozfullscreenchange";a.isFullScreen=function(){if(e.mozRequestFullScreen)return b.mozFullScreen;else if(e.webkitRequestFullScreen)return b.webkitIsFullScreen};a.requestFullScreen=function(h){if(a.hasWebkitNativeFullScreen)h.webkitRequestFullScreen();else a.hasMozNativeFullScreen&&h.mozRequestFullScreen()};a.cancelFullScreen=function(){if(a.hasWebkitNativeFullScreen)document.webkitCancelFullScreen();else a.hasMozNativeFullScreen&&document.mozCancelFullScreen()}}if(a.hasSemiNativeFullScreen&& +d.match(/mac os x 10_5/i)){a.hasNativeFullScreen=false;a.hasSemiNativeFullScreen=false}}};mejs.MediaFeatures.init(); +mejs.HtmlMediaElement={pluginType:"native",isFullScreen:false,setCurrentTime:function(a){this.currentTime=a},setMuted:function(a){this.muted=a},setVolume:function(a){this.volume=a},stop:function(){this.pause()},setSrc:function(a){for(var b=this.getElementsByTagName("source");b.length>0;)this.removeChild(b[0]);if(typeof a=="string")this.src=a;else{var c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type)){this.src=c.src;break}}}},setVideoSize:function(a,b){this.width=a;this.height=b}}; +mejs.PluginMediaElement=function(a,b,c){this.id=a;this.pluginType=b;this.src=c;this.events={};this.attributes={}}; +mejs.PluginMediaElement.prototype={pluginElement:null,pluginType:"",isFullScreen:false,playbackRate:-1,defaultPlaybackRate:-1,seekable:[],played:[],paused:true,ended:false,seeking:false,duration:0,error:null,tagName:"",muted:false,volume:1,currentTime:0,play:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.playVideo():this.pluginApi.playMedia();this.paused=false}},load:function(){if(this.pluginApi!=null){this.pluginType!="youtube"&&this.pluginApi.loadMedia();this.paused= +false}},pause:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.pauseVideo():this.pluginApi.pauseMedia();this.paused=true}},stop:function(){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.stopVideo():this.pluginApi.stopMedia();this.paused=true}},canPlayType:function(a){var b,c,d,e=mejs.plugins[this.pluginType];for(b=0;b<e.length;b++){d=e[b];if(mejs.PluginDetector.hasPluginVersion(this.pluginType,d.version))for(c=0;c<d.types.length;c++)if(a==d.types[c])return"probably"}return""}, +positionFullscreenButton:function(a,b,c){this.pluginApi!=null&&this.pluginApi.positionFullscreenButton&&this.pluginApi.positionFullscreenButton(Math.floor(a),Math.floor(b),c)},hideFullscreenButton:function(){this.pluginApi!=null&&this.pluginApi.hideFullscreenButton&&this.pluginApi.hideFullscreenButton()},setSrc:function(a){if(typeof a=="string"){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(a));this.src=mejs.Utility.absolutizeUrl(a)}else{var b,c;for(b=0;b<a.length;b++){c=a[b];if(this.canPlayType(c.type)){this.pluginApi.setSrc(mejs.Utility.absolutizeUrl(c.src)); +this.src=mejs.Utility.absolutizeUrl(a);break}}}},setCurrentTime:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.seekTo(a):this.pluginApi.setCurrentTime(a);this.currentTime=a}},setVolume:function(a){if(this.pluginApi!=null){this.pluginType=="youtube"?this.pluginApi.setVolume(a*100):this.pluginApi.setVolume(a);this.volume=a}},setMuted:function(a){if(this.pluginApi!=null){if(this.pluginType=="youtube"){a?this.pluginApi.mute():this.pluginApi.unMute();this.muted=a;this.dispatchEvent("volumechange")}else this.pluginApi.setMuted(a); +this.muted=a}},setVideoSize:function(a,b){if(this.pluginElement.style){this.pluginElement.style.width=a+"px";this.pluginElement.style.height=b+"px"}this.pluginApi!=null&&this.pluginApi.setVideoSize&&this.pluginApi.setVideoSize(a,b)},setFullscreen:function(a){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.pluginApi.setFullscreen(a)},enterFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&&this.setFullscreen(true)},exitFullScreen:function(){this.pluginApi!=null&&this.pluginApi.setFullscreen&& +this.setFullscreen(false)},addEventListener:function(a,b){this.events[a]=this.events[a]||[];this.events[a].push(b)},removeEventListener:function(a,b){if(!a){this.events={};return true}var c=this.events[a];if(!c)return true;if(!b){this.events[a]=[];return true}for(i=0;i<c.length;i++)if(c[i]===b){this.events[a].splice(i,1);return true}return false},dispatchEvent:function(a){var b,c,d=this.events[a];if(d){c=Array.prototype.slice.call(arguments,1);for(b=0;b<d.length;b++)d[b].apply(null,c)}},hasAttribute:function(a){return a in +this.attributes},removeAttribute:function(a){delete this.attributes[a]},getAttribute:function(a){if(this.hasAttribute(a))return this.attributes[a];return""},setAttribute:function(a,b){this.attributes[a]=b},remove:function(){mejs.Utility.removeSwf(this.pluginElement.id);mejs.MediaPluginBridge.unregisterPluginElement(this.pluginElement.id)}}; +mejs.MediaPluginBridge={pluginMediaElements:{},htmlMediaElements:{},registerPluginElement:function(a,b,c){this.pluginMediaElements[a]=b;this.htmlMediaElements[a]=c},unregisterPluginElement:function(a){delete this.pluginMediaElements[a];delete this.htmlMediaElements[a]},initPlugin:function(a){var b=this.pluginMediaElements[a],c=this.htmlMediaElements[a];if(b){switch(b.pluginType){case "flash":b.pluginElement=b.pluginApi=document.getElementById(a);break;case "silverlight":b.pluginElement=document.getElementById(b.id); +b.pluginApi=b.pluginElement.Content.MediaElementJS}b.pluginApi!=null&&b.success&&b.success(b,c)}},fireEvent:function(a,b,c){var d,e;a=this.pluginMediaElements[a];b={type:b,target:a};for(d in c){a[d]=c[d];b[d]=c[d]}e=c.bufferedTime||0;b.target.buffered=b.buffered={start:function(){return 0},end:function(){return e},length:1};a.dispatchEvent(b.type,b)}}; +mejs.MediaElementDefaults={mode:"auto",plugins:["flash","silverlight","youtube","vimeo"],enablePluginDebug:false,type:"",pluginPath:mejs.Utility.getScriptPath(["mediaelement.js","mediaelement.min.js","mediaelement-and-player.js","mediaelement-and-player.min.js"]),flashName:"flashmediaelement.swf",flashStreamer:"",enablePluginSmoothing:false,enablePseudoStreaming:false,pseudoStreamingStartQueryParam:"start",silverlightName:"silverlightmediaelement.xap",defaultVideoWidth:480,defaultVideoHeight:270, +pluginWidth:-1,pluginHeight:-1,pluginVars:[],timerRate:250,startVolume:0.8,success:function(){},error:function(){}};mejs.MediaElement=function(a,b){return mejs.HtmlMediaElementShim.create(a,b)}; +mejs.HtmlMediaElementShim={create:function(a,b){var c=mejs.MediaElementDefaults,d=typeof a=="string"?document.getElementById(a):a,e=d.tagName.toLowerCase(),f=e==="audio"||e==="video",g=f?d.getAttribute("src"):d.getAttribute("href");e=d.getAttribute("poster");var h=d.getAttribute("autoplay"),l=d.getAttribute("preload"),j=d.getAttribute("controls"),k;for(k in b)c[k]=b[k];g=typeof g=="undefined"||g===null||g==""?null:g;e=typeof e=="undefined"||e===null?"":e;l=typeof l=="undefined"||l===null||l==="false"? +"none":l;h=!(typeof h=="undefined"||h===null||h==="false");j=!(typeof j=="undefined"||j===null||j==="false");k=this.determinePlayback(d,c,mejs.MediaFeatures.supportsMediaTag,f,g);k.url=k.url!==null?mejs.Utility.absolutizeUrl(k.url):"";if(k.method=="native"){if(mejs.MediaFeatures.isBustedAndroid){d.src=k.url;d.addEventListener("click",function(){d.play()},false)}return this.updateNative(k,c,h,l)}else if(k.method!=="")return this.createPlugin(k,c,e,h,l,j);else{this.createErrorMessage(k,c,e);return this}}, +determinePlayback:function(a,b,c,d,e){var f=[],g,h,l,j={method:"",url:"",htmlMediaElement:a,isVideo:a.tagName.toLowerCase()!="audio"},k;if(typeof b.type!="undefined"&&b.type!=="")if(typeof b.type=="string")f.push({type:b.type,url:e});else for(g=0;g<b.type.length;g++)f.push({type:b.type[g],url:e});else if(e!==null){l=this.formatType(e,a.getAttribute("type"));f.push({type:l,url:e})}else for(g=0;g<a.childNodes.length;g++){h=a.childNodes[g];if(h.nodeType==1&&h.tagName.toLowerCase()=="source"){e=h.getAttribute("src"); +l=this.formatType(e,h.getAttribute("type"));h=h.getAttribute("media");if(!h||!window.matchMedia||window.matchMedia&&window.matchMedia(h).matches)f.push({type:l,url:e})}}if(!d&&f.length>0&&f[0].url!==null&&this.getTypeFromFile(f[0].url).indexOf("audio")>-1)j.isVideo=false;if(mejs.MediaFeatures.isBustedAndroid)a.canPlayType=function(m){return m.match(/video\/(mp4|m4v)/gi)!==null?"maybe":""};if(c&&(b.mode==="auto"||b.mode==="auto_plugin"||b.mode==="native")&&!mejs.MediaFeatures.isBustedNativeHTTPS){if(!d){g= +document.createElement(j.isVideo?"video":"audio");a.parentNode.insertBefore(g,a);a.style.display="none";j.htmlMediaElement=a=g}for(g=0;g<f.length;g++)if(a.canPlayType(f[g].type).replace(/no/,"")!==""||a.canPlayType(f[g].type.replace(/mp3/,"mpeg")).replace(/no/,"")!==""){j.method="native";j.url=f[g].url;break}if(j.method==="native"){if(j.url!==null)a.src=j.url;if(b.mode!=="auto_plugin")return j}}if(b.mode==="auto"||b.mode==="auto_plugin"||b.mode==="shim")for(g=0;g<f.length;g++){l=f[g].type;for(a=0;a< +b.plugins.length;a++){e=b.plugins[a];h=mejs.plugins[e];for(c=0;c<h.length;c++){k=h[c];if(k.version==null||mejs.PluginDetector.hasPluginVersion(e,k.version))for(d=0;d<k.types.length;d++)if(l==k.types[d]){j.method=e;j.url=f[g].url;return j}}}}if(b.mode==="auto_plugin"&&j.method==="native")return j;if(j.method===""&&f.length>0)j.url=f[0].url;return j},formatType:function(a,b){return a&&!b?this.getTypeFromFile(a):b&&~b.indexOf(";")?b.substr(0,b.indexOf(";")):b},getTypeFromFile:function(a){a=a.split("?")[0]; +a=a.substring(a.lastIndexOf(".")+1).toLowerCase();return(/(mp4|m4v|ogg|ogv|webm|webmv|flv|wmv|mpeg|mov)/gi.test(a)?"video":"audio")+"/"+this.getTypeFromExtension(a)},getTypeFromExtension:function(a){switch(a){case "mp4":case "m4v":return"mp4";case "webm":case "webma":case "webmv":return"webm";case "ogg":case "oga":case "ogv":return"ogg";default:return a}},createErrorMessage:function(a,b,c){var d=a.htmlMediaElement,e=document.createElement("div");e.className="me-cannotplay";try{e.style.width=d.width+ +"px";e.style.height=d.height+"px"}catch(f){}e.innerHTML=b.customError?b.customError:c!==""?'<a href="'+a.url+'"><img src="'+c+'" width="100%" height="100%" /></a>':'<a href="'+a.url+'"><span>'+mejs.i18n.t("Download File")+"</span></a>";d.parentNode.insertBefore(e,d);d.style.display="none";b.error(d)},createPlugin:function(a,b,c,d,e,f){c=a.htmlMediaElement;var g=1,h=1,l="me_"+a.method+"_"+mejs.meIndex++,j=new mejs.PluginMediaElement(l,a.method,a.url),k=document.createElement("div"),m;j.tagName=c.tagName; +for(m=0;m<c.attributes.length;m++){var n=c.attributes[m];n.specified==true&&j.setAttribute(n.name,n.value)}for(m=c.parentNode;m!==null&&m.tagName.toLowerCase()!="body";){if(m.parentNode.tagName.toLowerCase()=="p"){m.parentNode.parentNode.insertBefore(m,m.parentNode);break}m=m.parentNode}if(a.isVideo){g=b.pluginWidth>0?b.pluginWidth:b.videoWidth>0?b.videoWidth:c.getAttribute("width")!==null?c.getAttribute("width"):b.defaultVideoWidth;h=b.pluginHeight>0?b.pluginHeight:b.videoHeight>0?b.videoHeight: +c.getAttribute("height")!==null?c.getAttribute("height"):b.defaultVideoHeight;g=mejs.Utility.encodeUrl(g);h=mejs.Utility.encodeUrl(h)}else if(b.enablePluginDebug){g=320;h=240}j.success=b.success;mejs.MediaPluginBridge.registerPluginElement(l,j,c);k.className="me-plugin";k.id=l+"_container";a.isVideo?c.parentNode.insertBefore(k,c):document.body.insertBefore(k,document.body.childNodes[0]);d=["id="+l,"isvideo="+(a.isVideo?"true":"false"),"autoplay="+(d?"true":"false"),"preload="+e,"width="+g,"startvolume="+ +b.startVolume,"timerrate="+b.timerRate,"flashstreamer="+b.flashStreamer,"height="+h,"pseudostreamstart="+b.pseudoStreamingStartQueryParam];if(a.url!==null)a.method=="flash"?d.push("file="+mejs.Utility.encodeUrl(a.url)):d.push("file="+a.url);b.enablePluginDebug&&d.push("debug=true");b.enablePluginSmoothing&&d.push("smoothing=true");b.enablePseudoStreaming&&d.push("pseudostreaming=true");f&&d.push("controls=true");if(b.pluginVars)d=d.concat(b.pluginVars);switch(a.method){case "silverlight":k.innerHTML= +'<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="'+l+'" name="'+l+'" width="'+g+'" height="'+h+'" class="mejs-shim"><param name="initParams" value="'+d.join(",")+'" /><param name="windowless" value="true" /><param name="background" value="black" /><param name="minRuntimeVersion" value="3.0.0.0" /><param name="autoUpgrade" value="true" /><param name="source" value="'+b.pluginPath+b.silverlightName+'" /></object>';break;case "flash":if(mejs.MediaFeatures.isIE){a= +document.createElement("div");k.appendChild(a);a.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+l+'" width="'+g+'" height="'+h+'" class="mejs-shim"><param name="movie" value="'+b.pluginPath+b.flashName+"?x="+new Date+'" /><param name="flashvars" value="'+d.join("&amp;")+'" /><param name="quality" value="high" /><param name="bgcolor" value="#000000" /><param name="wmode" value="transparent" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /></object>'}else k.innerHTML= +'<embed id="'+l+'" name="'+l+'" play="true" loop="false" quality="high" bgcolor="#000000" wmode="transparent" allowScriptAccess="always" allowFullScreen="true" type="application/x-shockwave-flash" pluginspage="//www.macromedia.com/go/getflashplayer" src="'+b.pluginPath+b.flashName+'" flashvars="'+d.join("&")+'" width="'+g+'" height="'+h+'" class="mejs-shim"></embed>';break;case "youtube":b=a.url.substr(a.url.lastIndexOf("=")+1);youtubeSettings={container:k,containerId:k.id,pluginMediaElement:j,pluginId:l, +videoId:b,height:h,width:g};mejs.PluginDetector.hasPluginVersion("flash",[10,0,0])?mejs.YouTubeApi.createFlash(youtubeSettings):mejs.YouTubeApi.enqueueIframe(youtubeSettings);break;case "vimeo":j.vimeoid=a.url.substr(a.url.lastIndexOf("/")+1);k.innerHTML='<iframe src="http://player.vimeo.com/video/'+j.vimeoid+'?portrait=0&byline=0&title=0" width="'+g+'" height="'+h+'" frameborder="0" class="mejs-shim"></iframe>'}c.style.display="none";return j},updateNative:function(a,b){var c=a.htmlMediaElement, +d;for(d in mejs.HtmlMediaElement)c[d]=mejs.HtmlMediaElement[d];b.success(c,c);return c}}; +mejs.YouTubeApi={isIframeStarted:false,isIframeLoaded:false,loadIframeApi:function(){if(!this.isIframeStarted){var a=document.createElement("script");a.src="//www.youtube.com/player_api";var b=document.getElementsByTagName("script")[0];b.parentNode.insertBefore(a,b);this.isIframeStarted=true}},iframeQueue:[],enqueueIframe:function(a){if(this.isLoaded)this.createIframe(a);else{this.loadIframeApi();this.iframeQueue.push(a)}},createIframe:function(a){var b=a.pluginMediaElement,c=new YT.Player(a.containerId, +{height:a.height,width:a.width,videoId:a.videoId,playerVars:{controls:0},events:{onReady:function(){a.pluginMediaElement.pluginApi=c;mejs.MediaPluginBridge.initPlugin(a.pluginId);setInterval(function(){mejs.YouTubeApi.createEvent(c,b,"timeupdate")},250)},onStateChange:function(d){mejs.YouTubeApi.handleStateChange(d.data,c,b)}}})},createEvent:function(a,b,c){c={type:c,target:b};if(a&&a.getDuration){b.currentTime=c.currentTime=a.getCurrentTime();b.duration=c.duration=a.getDuration();c.paused=b.paused; +c.ended=b.ended;c.muted=a.isMuted();c.volume=a.getVolume()/100;c.bytesTotal=a.getVideoBytesTotal();c.bufferedBytes=a.getVideoBytesLoaded();var d=c.bufferedBytes/c.bytesTotal*c.duration;c.target.buffered=c.buffered={start:function(){return 0},end:function(){return d},length:1}}b.dispatchEvent(c.type,c)},iFrameReady:function(){for(this.isIframeLoaded=this.isLoaded=true;this.iframeQueue.length>0;)this.createIframe(this.iframeQueue.pop())},flashPlayers:{},createFlash:function(a){this.flashPlayers[a.pluginId]= +a;var b,c="//www.youtube.com/apiplayer?enablejsapi=1&amp;playerapiid="+a.pluginId+"&amp;version=3&amp;autoplay=0&amp;controls=0&amp;modestbranding=1&loop=0";if(mejs.MediaFeatures.isIE){b=document.createElement("div");a.container.appendChild(b);b.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" id="'+a.pluginId+'" width="'+a.width+'" height="'+a.height+'" class="mejs-shim"><param name="movie" value="'+ +c+'" /><param name="wmode" value="transparent" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /></object>'}else a.container.innerHTML='<object type="application/x-shockwave-flash" id="'+a.pluginId+'" data="'+c+'" width="'+a.width+'" height="'+a.height+'" style="visibility: visible; " class="mejs-shim"><param name="allowScriptAccess" value="always"><param name="wmode" value="transparent"></object>'},flashReady:function(a){var b=this.flashPlayers[a],c= +document.getElementById(a),d=b.pluginMediaElement;d.pluginApi=d.pluginElement=c;mejs.MediaPluginBridge.initPlugin(a);c.cueVideoById(b.videoId);a=b.containerId+"_callback";window[a]=function(e){mejs.YouTubeApi.handleStateChange(e,c,d)};c.addEventListener("onStateChange",a);setInterval(function(){mejs.YouTubeApi.createEvent(c,d,"timeupdate")},250)},handleStateChange:function(a,b,c){switch(a){case -1:c.paused=true;c.ended=true;mejs.YouTubeApi.createEvent(b,c,"loadedmetadata");break;case 0:c.paused=false; +c.ended=true;mejs.YouTubeApi.createEvent(b,c,"ended");break;case 1:c.paused=false;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"play");mejs.YouTubeApi.createEvent(b,c,"playing");break;case 2:c.paused=true;c.ended=false;mejs.YouTubeApi.createEvent(b,c,"pause");break;case 3:mejs.YouTubeApi.createEvent(b,c,"progress")}}};function onYouTubePlayerAPIReady(){mejs.YouTubeApi.iFrameReady()}function onYouTubePlayerReady(a){mejs.YouTubeApi.flashReady(a)}window.mejs=mejs;window.MediaElement=mejs.MediaElement; +(function(a,b){var c={locale:{strings:{}},methods:{}};c.locale.getLanguage=function(){return c.locale||{language:navigator.language}};c.locale.INIT_LANGUAGE=c.locale.getLanguage();c.methods.checkPlain=function(d){var e,f,g={"&":"&amp;",'"':"&quot;","<":"&lt;",">":"&gt;"};d=String(d);for(e in g)if(g.hasOwnProperty(e)){f=RegExp(e,"g");d=d.replace(f,g[e])}return d};c.methods.formatString=function(d,e){for(var f in e){switch(f.charAt(0)){case "@":e[f]=c.methods.checkPlain(e[f]);break;case "!":break;default:e[f]= +'<em class="placeholder">'+c.methods.checkPlain(e[f])+"</em>"}d=d.replace(f,e[f])}return d};c.methods.t=function(d,e,f){if(c.locale.strings&&c.locale.strings[f.context]&&c.locale.strings[f.context][d])d=c.locale.strings[f.context][d];if(e)d=c.methods.formatString(d,e);return d};c.t=function(d,e,f){if(typeof d==="string"&&d.length>0){var g=c.locale.getLanguage();f=f||{context:g.language};return c.methods.t(d,e,f)}else throw{name:"InvalidArgumentException",message:"First argument is either not a string or empty."}; +};b.i18n=c})(document,mejs);(function(a){if(mejs.i18n.locale.language&&mejs.i18n.locale.strings)a[mejs.i18n.locale.language]=mejs.i18n.locale.strings})(mejs.i18n.locale.strings);(function(a){a.de={Fullscreen:"Vollbild","Go Fullscreen":"Vollbild an","Turn off Fullscreen":"Vollbild aus",Close:"Schlie\u00dfen"}})(mejs.i18n.locale.strings);(function(a){a.zh={Fullscreen:"\u5168\u87a2\u5e55","Go Fullscreen":"\u5168\u5c4f\u6a21\u5f0f","Turn off Fullscreen":"\u9000\u51fa\u5168\u5c4f\u6a21\u5f0f",Close:"\u95dc\u9589"}})(mejs.i18n.locale.strings); diff --git a/src/static/mediaelement/mediaelementplayer.css b/src/static/mediaelement/mediaelementplayer.css new file mode 100755 index 0000000..6516c09 --- /dev/null +++ b/src/static/mediaelement/mediaelementplayer.css @@ -0,0 +1,864 @@ +.mejs-container { + position: relative; + background: #000; + font-family: Helvetica, Arial; + text-align: left; + vertical-align: top; + text-indent: 0; +} + +.me-plugin { + position: absolute; +} + +.mejs-embed, .mejs-embed body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + background: #000; + overflow: hidden; +} + +.mejs-container-fullscreen { + position: fixed; + left: 0; + top: 0; + right: 0; + bottom: 0; + overflow: hidden; + z-index: 1000; +} +.mejs-container-fullscreen .mejs-mediaelement, +.mejs-container-fullscreen video { + width: 100%; + height: 100%; +} + +.mejs-clear { + clear: both; +} + +/* Start: LAYERS */ +.mejs-background { + position: absolute; + top: 0; + left: 0; +} + +.mejs-mediaelement { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.mejs-poster { + position: absolute; + top: 0; + left: 0; + background-size: contain ; + background-position: 50% 50% ; + background-repeat: no-repeat ; +} +:root .mejs-poster img { + display: none ; +} + +.mejs-poster img { + border: 0; + padding: 0; + border: 0; +} + +.mejs-overlay { + position: absolute; + top: 0; + left: 0; +} + +.mejs-overlay-play { + cursor: pointer; +} + +.mejs-overlay-button { + position: absolute; + top: 50%; + left: 50%; + width: 100px; + height: 100px; + margin: -50px 0 0 -50px; + background: url(bigplay.svg) no-repeat; +} + +.no-svg .mejs-overlay-button { + background-image: url(bigplay.png); +} + +.mejs-overlay:hover .mejs-overlay-button { + background-position: 0 -100px ; +} + +.mejs-overlay-loading { + position: absolute; + top: 50%; + left: 50%; + width: 80px; + height: 80px; + margin: -40px 0 0 -40px; + background: #333; + background: url(background.png); + background: rgba(0, 0, 0, 0.9); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.9)), to(rgba(0,0,0,0.9))); + background: -webkit-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9)); + background: -moz-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9)); + background: -o-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9)); + background: -ms-linear-gradient(top, rgba(50,50,50,0.9), rgba(0,0,0,0.9)); + background: linear-gradient(rgba(50,50,50,0.9), rgba(0,0,0,0.9)); +} + +.mejs-overlay-loading span { + display: block; + width: 80px; + height: 80px; + background: transparent url(loading.gif) 50% 50% no-repeat; +} + +/* End: LAYERS */ + +/* Start: CONTROL BAR */ +.mejs-container .mejs-controls { + position: absolute; + list-style-type: none; + margin: 0; + padding: 0; + bottom: 0; + left: 0; + background: url(background.png); + background: rgba(0, 0, 0, 0.7); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.7)), to(rgba(0,0,0,0.7))); + background: -webkit-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -moz-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -o-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -ms-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: linear-gradient(rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + height: 30px; + width: 100%; +} +.mejs-container .mejs-controls div { + list-style-type: none; + background-image: none; + display: block; + float: left; + margin: 0; + padding: 0; + width: 26px; + height: 26px; + font-size: 11px; + line-height: 11px; + font-family: Helvetica, Arial; + border: 0; +} + +.mejs-controls .mejs-button button { + cursor: pointer; + display: block; + font-size: 0; + line-height: 0; + text-decoration: none; + margin: 7px 5px; + padding: 0; + position: absolute; + height: 16px; + width: 16px; + border: 0; + background: transparent url(controls.svg) no-repeat; +} + +.no-svg .mejs-controls .mejs-button button { + background-image: url(controls.png); +} + +/* :focus for accessibility */ +.mejs-controls .mejs-button button:focus { + outline: solid 1px yellow; +} + +/* End: CONTROL BAR */ + +/* Start: Time (Current / Duration) */ +.mejs-container .mejs-controls .mejs-time { + color: #fff; + display: block; + height: 17px; + width: auto; + padding: 8px 3px 0 3px ; + overflow: hidden; + text-align: center; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +.mejs-container .mejs-controls .mejs-time span { + color: #fff; + font-size: 11px; + line-height: 12px; + display: block; + float: left; + margin: 1px 2px 0 0; + width: auto; +} +/* End: Time (Current / Duration) */ + +/* Start: Play/Pause/Stop */ +.mejs-controls .mejs-play button { + background-position: 0 0; +} + +.mejs-controls .mejs-pause button { + background-position: 0 -16px; +} + +.mejs-controls .mejs-stop button { + background-position: -112px 0; +} +/* Start: Play/Pause/Stop */ + +/* Start: Progress Bar */ +.mejs-controls div.mejs-time-rail { + width: 200px; + padding-top: 5px; +} + +.mejs-controls .mejs-time-rail span { + display: block; + position: absolute; + width: 180px; + height: 10px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + cursor: pointer; +} + +.mejs-controls .mejs-time-rail .mejs-time-total { + margin: 5px; + background: #333; + background: rgba(50,50,50,0.8); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(30,30,30,0.8)), to(rgba(60,60,60,0.8))); + background: -webkit-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -moz-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -o-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -ms-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: linear-gradient(rgba(30,30,30,0.8), rgba(60,60,60,0.8)); +} + +.mejs-controls .mejs-time-rail .mejs-time-buffering { + width: 100%; + 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: -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: -ms-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: 15px 15px; + -moz-background-size: 15px 15px; + -o-background-size: 15px 15px; + background-size: 15px 15px; + -webkit-animation: buffering-stripes 2s linear infinite; + -moz-animation: buffering-stripes 2s linear infinite; + -ms-animation: buffering-stripes 2s linear infinite; + -o-animation: buffering-stripes 2s linear infinite; + animation: buffering-stripes 2s linear infinite; +} + +@-webkit-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} } +@-moz-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} } +@-ms-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} } +@-o-keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} } +@keyframes buffering-stripes { from {background-position: 0 0;} to {background-position: 30px 0;} } + +.mejs-controls .mejs-time-rail .mejs-time-loaded { + background: #3caac8; + background: rgba(60,170,200,0.8); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(44,124,145,0.8)), to(rgba(78,183,212,0.8))); + background: -webkit-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8)); + background: -moz-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8)); + background: -o-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8)); + background: -ms-linear-gradient(top, rgba(44,124,145,0.8), rgba(78,183,212,0.8)); + background: linear-gradient(rgba(44,124,145,0.8), rgba(78,183,212,0.8)); + width: 0; +} + +.mejs-controls .mejs-time-rail .mejs-time-current { + background: #fff; + background: rgba(255,255,255,0.8); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255,255,255,0.9)), to(rgba(200,200,200,0.8))); + background: -webkit-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -moz-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -o-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -ms-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: linear-gradient(rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + width: 0; +} + +.mejs-controls .mejs-time-rail .mejs-time-handle { + display: none; + position: absolute; + margin: 0; + width: 10px; + background: #fff; + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; + cursor: pointer; + border: solid 2px #333; + top: -2px; + text-align: center; +} + +.mejs-controls .mejs-time-rail .mejs-time-float { + position: absolute; + display: none; + background: #eee; + width: 36px; + height: 17px; + border: solid 1px #333; + top: -26px; + margin-left: -18px; + text-align: center; + color: #111; +} + +.mejs-controls .mejs-time-rail .mejs-time-float-current { + margin: 2px; + width: 30px; + display: block; + text-align: center; + left: 0; +} + +.mejs-controls .mejs-time-rail .mejs-time-float-corner { + position: absolute; + display: block; + width: 0; + height: 0; + line-height: 0; + border: solid 5px #eee; + border-color: #eee transparent transparent transparent; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + top: 15px; + left: 13px; +} + +.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float { + width: 48px; +} + +.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-current { + width: 44px; +} + +.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-corner { + left: 18px; +} + +/* +.mejs-controls .mejs-time-rail:hover .mejs-time-handle { + visibility:visible; +} +*/ +/* End: Progress Bar */ + +/* Start: Fullscreen */ +.mejs-controls .mejs-fullscreen-button button { + background-position: -32px 0; +} + +.mejs-controls .mejs-unfullscreen button { + background-position: -32px -16px; +} +/* End: Fullscreen */ + + +/* Start: Mute/Volume */ +.mejs-controls .mejs-volume-button { +} + +.mejs-controls .mejs-mute button { + background-position: -16px -16px; +} + +.mejs-controls .mejs-unmute button { + background-position: -16px 0; +} + +.mejs-controls .mejs-volume-button { + position: relative; +} + +.mejs-controls .mejs-volume-button .mejs-volume-slider { + display: none; + height: 115px; + width: 25px; + background: url(background.png); + background: rgba(50, 50, 50, 0.7); + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; + top: -115px; + left: 0; + z-index: 1; + position: absolute; + margin: 0; +} + +.mejs-controls .mejs-volume-button:hover { + -webkit-border-radius: 0 0 4px 4px; + -moz-border-radius: 0 0 4px 4px; + border-radius: 0 0 4px 4px; +} + +/* +.mejs-controls .mejs-volume-button:hover .mejs-volume-slider { + display: block; +} +*/ + +.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-total { + position: absolute; + left: 11px; + top: 8px; + width: 2px; + height: 100px; + background: #ddd; + background: rgba(255, 255, 255, 0.5); + margin: 0; +} + +.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-current { + position: absolute; + left: 11px; + top: 8px; + width: 2px; + height: 100px; + background: #ddd; + background: rgba(255, 255, 255, 0.9); + margin: 0; +} + +.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-handle { + position: absolute; + left: 4px; + top: -3px; + width: 16px; + height: 6px; + background: #ddd; + background: rgba(255, 255, 255, 0.9); + cursor: N-resize; + -webkit-border-radius: 1px; + -moz-border-radius: 1px; + border-radius: 1px; + margin: 0; +} + +/* horizontal version */ +.mejs-controls div.mejs-horizontal-volume-slider { + height: 26px; + width: 60px; + position: relative; +} + +.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total { + position: absolute; + left: 0; + top: 11px; + width: 50px; + height: 8px; + margin: 0; + padding: 0; + font-size: 1px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + background: #333; + background: rgba(50,50,50,0.8); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(30,30,30,0.8)), to(rgba(60,60,60,0.8))); + background: -webkit-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -moz-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -o-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: -ms-linear-gradient(top, rgba(30,30,30,0.8), rgba(60,60,60,0.8)); + background: linear-gradient(rgba(30,30,30,0.8), rgba(60,60,60,0.8)); +} + +.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-current { + position: absolute; + left: 0; + top: 11px; + width: 50px; + height: 8px; + margin: 0; + padding: 0; + font-size: 1px; + -webkit-border-radius: 2px; + -moz-border-radius: 2px; + border-radius: 2px; + background: #fff; + background: rgba(255,255,255,0.8); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(255,255,255,0.9)), to(rgba(200,200,200,0.8))); + background: -webkit-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -moz-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -o-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: -ms-linear-gradient(top, rgba(255,255,255,0.9), rgba(200,200,200,0.8)); + background: linear-gradient(rgba(255,255,255,0.9), rgba(200,200,200,0.8)); +} + +.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-handle { + display: none; +} + +/* End: Mute/Volume */ + +/* Start: Track (Captions and Chapters) */ +.mejs-controls .mejs-captions-button { + position: relative; +} + +.mejs-controls .mejs-captions-button button { + background-position: -48px 0; +} +.mejs-controls .mejs-captions-button .mejs-captions-selector { + visibility: hidden; + position: absolute; + bottom: 26px; + right: -10px; + width: 130px; + height: 100px; + background: url(background.png); + background: rgba(50,50,50,0.7); + border: solid 1px transparent; + padding: 10px; + overflow: hidden; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +/* +.mejs-controls .mejs-captions-button:hover .mejs-captions-selector { + visibility: visible; +} +*/ + +.mejs-controls .mejs-captions-button .mejs-captions-selector ul { + margin: 0; + padding: 0; + display: block; + list-style-type: none !important; + overflow: hidden; +} + +.mejs-controls .mejs-captions-button .mejs-captions-selector ul li { + margin: 0 0 6px 0; + padding: 0; + list-style-type: none !important; + display: block; + color: #fff; + overflow: hidden; +} + +.mejs-controls .mejs-captions-button .mejs-captions-selector ul li input { + clear: both; + float: left; + margin: 3px 3px 0 5px; +} + +.mejs-controls .mejs-captions-button .mejs-captions-selector ul li label { + width: 100px; + float: left; + padding: 4px 0 0 0; + line-height: 15px; + font-family: helvetica, arial; + font-size: 10px; +} + +.mejs-controls .mejs-captions-button .mejs-captions-translations { + font-size: 10px; + margin: 0 0 5px 0; +} + +.mejs-chapters { + position: absolute; + top: 0; + left: 0; + -xborder-right: solid 1px #fff; + width: 10000px; + z-index: 1; +} + +.mejs-chapters .mejs-chapter { + position: absolute; + float: left; + background: #222; + background: rgba(0, 0, 0, 0.7); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(50,50,50,0.7)), to(rgba(0,0,0,0.7))); + background: -webkit-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -moz-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -o-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: -ms-linear-gradient(top, rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + background: linear-gradient(rgba(50,50,50,0.7), rgba(0,0,0,0.7)); + filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr=#323232,endColorstr=#000000); + overflow: hidden; + border: 0; +} + +.mejs-chapters .mejs-chapter .mejs-chapter-block { + font-size: 11px; + color: #fff; + padding: 5px; + display: block; + border-right: solid 1px #333; + border-bottom: solid 1px #333; + cursor: pointer; +} + +.mejs-chapters .mejs-chapter .mejs-chapter-block-last { + border-right: none; +} + +.mejs-chapters .mejs-chapter .mejs-chapter-block:hover { + background: #666; + background: rgba(102,102,102, 0.7); + background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(102,102,102,0.7)), to(rgba(50,50,50,0.6))); + background: -webkit-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6)); + background: -moz-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6)); + background: -o-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6)); + background: -ms-linear-gradient(top, rgba(102,102,102,0.7), rgba(50,50,50,0.6)); + background: linear-gradient(rgba(102,102,102,0.7), rgba(50,50,50,0.6)); + filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, startColorstr=#666666,endColorstr=#323232); +} + +.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-title { + font-size: 12px; + font-weight: bold; + display: block; + white-space: nowrap; + text-overflow: ellipsis; + margin: 0 0 3px 0; + line-height: 12px; +} + +.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-timespan { + font-size: 12px; + line-height: 12px; + margin: 3px 0 4px 0; + display: block; + white-space: nowrap; + text-overflow: ellipsis; +} + +.mejs-captions-layer { + position: absolute; + bottom: 0; + left: 0; + text-align:center; + line-height: 22px; + font-size: 12px; + color: #fff; +} + +.mejs-captions-layer a { + color: #fff; + text-decoration: underline; +} + +.mejs-captions-layer[lang=ar] { + font-size: 20px; + font-weight: normal; +} + +.mejs-captions-position { + position: absolute; + width: 100%; + bottom: 15px; + left: 0; +} + +.mejs-captions-position-hover { + bottom: 45px; +} + +.mejs-captions-text { + padding: 3px 5px; + background: url(background.png); + background: rgba(20, 20, 20, 0.8); + +} +/* End: Track (Captions and Chapters) */ + +/* Start: Error */ +.me-cannotplay { +} + +.me-cannotplay a { + color: #fff; + font-weight: bold; +} + +.me-cannotplay span { + padding: 15px; + display: block; +} +/* End: Error */ + + +/* Start: Loop */ +.mejs-controls .mejs-loop-off button { + background-position: -64px -16px; +} + +.mejs-controls .mejs-loop-on button { + background-position: -64px 0; +} + +/* End: Loop */ + +/* Start: backlight */ +.mejs-controls .mejs-backlight-off button { + background-position: -80px -16px; +} + +.mejs-controls .mejs-backlight-on button { + background-position: -80px 0; +} +/* End: backlight */ + +/* Start: Picture Controls */ +.mejs-controls .mejs-picturecontrols-button { + background-position: -96px 0; +} +/* End: Picture Controls */ + + +/* context menu */ +.mejs-contextmenu { + position: absolute; + width: 150px; + padding: 10px; + border-radius: 4px; + top: 0; + left: 0; + background: #fff; + border: solid 1px #999; + z-index: 1001; /* make sure it shows on fullscreen */ +} +.mejs-contextmenu .mejs-contextmenu-separator { + height: 1px; + font-size: 0; + margin: 5px 6px; + background: #333; +} + +.mejs-contextmenu .mejs-contextmenu-item { + font-family: Helvetica, Arial; + font-size: 12px; + padding: 4px 6px; + cursor: pointer; + color: #333; +} +.mejs-contextmenu .mejs-contextmenu-item:hover { + background: #2C7C91; + color: #fff; +} + +/* Start: Source Chooser */ +.mejs-controls .mejs-sourcechooser-button { + position: relative; +} + +.mejs-controls .mejs-sourcechooser-button button { + background-position: -128px 0; +} + +.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector { + visibility: hidden; + position: absolute; + bottom: 26px; + right: -10px; + width: 130px; + height: 100px; + background: url(background.png); + background: rgba(50,50,50,0.7); + border: solid 1px transparent; + padding: 10px; + overflow: hidden; + -webkit-border-radius: 0; + -moz-border-radius: 0; + border-radius: 0; +} + +.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul { + margin: 0; + padding: 0; + display: block; + list-style-type: none !important; + overflow: hidden; +} + +.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li { + margin: 0 0 6px 0; + padding: 0; + list-style-type: none !important; + display: block; + color: #fff; + overflow: hidden; +} + +.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li input { + clear: both; + float: left; + margin: 3px 3px 0 5px; +} + +.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li label { + width: 100px; + float: left; + padding: 4px 0 0 0; + line-height: 15px; + font-family: helvetica, arial; + font-size: 10px; +} +/* End: Source Chooser */ + +/* Start: Postroll */ +.mejs-postroll-layer { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + background: url(background.png); + background: rgba(50,50,50,0.7); + z-index: 1000; + overflow: hidden; +} +.mejs-postroll-layer-content { + width: 100%; + height: 100%; +} +.mejs-postroll-close { + position: absolute; + right: 0; + top: 0; + background: url(background.png); + background: rgba(50,50,50,0.7); + color: #fff; + padding: 4px; + z-index: 100; + cursor: pointer; +} +/* End: Postroll */ diff --git a/src/static/mediaelement/mediaelementplayer.js b/src/static/mediaelement/mediaelementplayer.js new file mode 100755 index 0000000..8514e94 --- /dev/null +++ b/src/static/mediaelement/mediaelementplayer.js @@ -0,0 +1,3153 @@ +/*! + * MediaElementPlayer + * http://mediaelementjs.com/ + * + * Creates a controller bar for HTML5 <video> add <audio> tags + * using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper) + * + * Copyright 2010-2013, John Dyer (http://j.hn/) + * License: MIT + * + */ +if (typeof jQuery != 'undefined') { + mejs.$ = jQuery; +} else if (typeof ender != 'undefined') { + mejs.$ = ender; +} +(function ($) { + + // default player values + mejs.MepDefaults = { + // url to poster (to fix iOS 3.x) + poster: '', + // default if the <video width> is not specified + defaultVideoWidth: 480, + // default if the <video height> is not specified + defaultVideoHeight: 270, + // if set, overrides <video width> + videoWidth: -1, + // if set, overrides <video height> + videoHeight: -1, + // default if the user doesn't specify + defaultAudioWidth: 400, + // default if the user doesn't specify + defaultAudioHeight: 30, + + // default amount to move back when back key is pressed + defaultSeekBackwardInterval: function(media) { + return (media.duration * 0.05); + }, + // default amount to move forward when forward key is pressed + defaultSeekForwardInterval: function(media) { + return (media.duration * 0.05); + }, + + // width of audio player + audioWidth: -1, + // height of audio player + audioHeight: -1, + // initial volume when the player starts (overrided by user cookie) + startVolume: 0.8, + // useful for <audio> player loops + loop: false, + // rewind to beginning when media ends + autoRewind: true, + // resize to media dimensions + enableAutosize: true, + // forces the hour marker (##:00:00) + alwaysShowHours: false, + + // show framecount in timecode (##:00:00:00) + showTimecodeFrameCount: false, + // used when showTimecodeFrameCount is set to true + framesPerSecond: 25, + + // automatically calculate the width of the progress bar based on the sizes of other elements + autosizeProgress : true, + // Hide controls when playing and mouse is not over the video + alwaysShowControls: false, + // Display the video control + hideVideoControlsOnLoad: false, + // Enable click video element to toggle play/pause + clickToPlayPause: true, + // force iPad's native controls + iPadUseNativeControls: false, + // force iPhone's native controls + iPhoneUseNativeControls: false, + // force Android's native controls + AndroidUseNativeControls: false, + // features to show + features: ['playpause','current','progress','duration','tracks','volume','fullscreen'], + // only for dynamic + isVideo: true, + + // turns keyboard support on and off for this instance + enableKeyboard: true, + + // whenthis player starts, it will pause other players + pauseOtherPlayers: true, + + // array of keyboard actions such as play pause + keyActions: [ + { + keys: [ + 32, // SPACE + 179 // GOOGLE play/pause button + ], + action: function(player, media) { + if (media.paused || media.ended) { + media.play(); + } else { + media.pause(); + } + } + }, + { + keys: [38], // UP + action: function(player, media) { + var newVolume = Math.min(media.volume + 0.1, 1); + media.setVolume(newVolume); + } + }, + { + keys: [40], // DOWN + action: function(player, media) { + var newVolume = Math.max(media.volume - 0.1, 0); + media.setVolume(newVolume); + } + }, + { + keys: [ + 37, // LEFT + 227 // Google TV rewind + ], + action: function(player, media) { + if (!isNaN(media.duration) && media.duration > 0) { + if (player.isVideo) { + player.showControls(); + player.startControlsTimer(); + } + + // 5% + var newTime = Math.max(media.currentTime - player.options.defaultSeekBackwardInterval(media), 0); + media.setCurrentTime(newTime); + } + } + }, + { + keys: [ + 39, // RIGHT + 228 // Google TV forward + ], + action: function(player, media) { + if (!isNaN(media.duration) && media.duration > 0) { + if (player.isVideo) { + player.showControls(); + player.startControlsTimer(); + } + + // 5% + var newTime = Math.min(media.currentTime + player.options.defaultSeekForwardInterval(media), media.duration); + media.setCurrentTime(newTime); + } + } + }, + { + keys: [70], // f + action: function(player, media) { + if (typeof player.enterFullScreen != 'undefined') { + if (player.isFullScreen) { + player.exitFullScreen(); + } else { + player.enterFullScreen(); + } + } + } + } + ] + }; + + mejs.mepIndex = 0; + + mejs.players = {}; + + // wraps a MediaElement object in player controls + mejs.MediaElementPlayer = function(node, o) { + // enforce object, even without "new" (via John Resig) + if ( !(this instanceof mejs.MediaElementPlayer) ) { + return new mejs.MediaElementPlayer(node, o); + } + + var t = this; + + // these will be reset after the MediaElement.success fires + t.$media = t.$node = $(node); + t.node = t.media = t.$media[0]; + + // check for existing player + if (typeof t.node.player != 'undefined') { + return t.node.player; + } else { + // attach player to DOM node for reference + t.node.player = t; + } + + + // try to get options from data-mejsoptions + if (typeof o == 'undefined') { + o = t.$node.data('mejsoptions'); + } + + // extend default options + t.options = $.extend({},mejs.MepDefaults,o); + + // unique ID + t.id = 'mep_' + mejs.mepIndex++; + + // add to player array (for focus events) + mejs.players[t.id] = t; + + // start up + t.init(); + + return t; + }; + + // actual player + mejs.MediaElementPlayer.prototype = { + + hasFocus: false, + + controlsAreVisible: true, + + init: function() { + + var + t = this, + mf = mejs.MediaFeatures, + // options for MediaElement (shim) + meOptions = $.extend(true, {}, t.options, { + success: function(media, domNode) { t.meReady(media, domNode); }, + error: function(e) { t.handleError(e);} + }), + tagName = t.media.tagName.toLowerCase(); + + t.isDynamic = (tagName !== 'audio' && tagName !== 'video'); + + if (t.isDynamic) { + // get video from src or href? + t.isVideo = t.options.isVideo; + } else { + t.isVideo = (tagName !== 'audio' && t.options.isVideo); + } + + // use native controls in iPad, iPhone, and Android + if ((mf.isiPad && t.options.iPadUseNativeControls) || (mf.isiPhone && t.options.iPhoneUseNativeControls)) { + + // add controls and stop + t.$media.attr('controls', 'controls'); + + // attempt to fix iOS 3 bug + //t.$media.removeAttr('poster'); + // no Issue found on iOS3 -ttroxell + + // override Apple's autoplay override for iPads + if (mf.isiPad && t.media.getAttribute('autoplay') !== null) { + t.media.load(); + t.media.play(); + } + + } else if (mf.isAndroid && t.options.AndroidUseNativeControls) { + + // leave default player + + } else { + + // DESKTOP: use MediaElementPlayer controls + + // remove native controls + t.$media.removeAttr('controls'); + + // build container + t.container = + $('<div id="' + t.id + '" class="mejs-container ' + (mejs.MediaFeatures.svg ? 'svg' : 'no-svg') + '">'+ + '<div class="mejs-inner">'+ + '<div class="mejs-mediaelement"></div>'+ + '<div class="mejs-layers"></div>'+ + '<div class="mejs-controls"></div>'+ + '<div class="mejs-clear"></div>'+ + '</div>' + + '</div>') + .addClass(t.$media[0].className) + .insertBefore(t.$media); + + // add classes for user and content + t.container.addClass( + (mf.isAndroid ? 'mejs-android ' : '') + + (mf.isiOS ? 'mejs-ios ' : '') + + (mf.isiPad ? 'mejs-ipad ' : '') + + (mf.isiPhone ? 'mejs-iphone ' : '') + + (t.isVideo ? 'mejs-video ' : 'mejs-audio ') + ); + + + // move the <video/video> tag into the right spot + if (mf.isiOS) { + + // sadly, you can't move nodes in iOS, so we have to destroy and recreate it! + var $newMedia = t.$media.clone(); + + t.container.find('.mejs-mediaelement').append($newMedia); + + t.$media.remove(); + t.$node = t.$media = $newMedia; + t.node = t.media = $newMedia[0] + + } else { + + // normal way of moving it into place (doesn't work on iOS) + t.container.find('.mejs-mediaelement').append(t.$media); + } + + // find parts + t.controls = t.container.find('.mejs-controls'); + t.layers = t.container.find('.mejs-layers'); + + // determine the size + + /* size priority: + (1) videoWidth (forced), + (2) style="width;height;" + (3) width attribute, + (4) defaultVideoWidth (for unspecified cases) + */ + + var tagType = (t.isVideo ? 'video' : 'audio'), + capsTagName = tagType.substring(0,1).toUpperCase() + tagType.substring(1); + + + if (t.options[tagType + 'Width'] > 0 || t.options[tagType + 'Width'].toString().indexOf('%') > -1) { + t.width = t.options[tagType + 'Width']; + } else if (t.media.style.width !== '' && t.media.style.width !== null) { + t.width = t.media.style.width; + } else if (t.media.getAttribute('width') !== null) { + t.width = t.$media.attr('width'); + } else { + t.width = t.options['default' + capsTagName + 'Width']; + } + + if (t.options[tagType + 'Height'] > 0 || t.options[tagType + 'Height'].toString().indexOf('%') > -1) { + t.height = t.options[tagType + 'Height']; + } else if (t.media.style.height !== '' && t.media.style.height !== null) { + t.height = t.media.style.height; + } else if (t.$media[0].getAttribute('height') !== null) { + t.height = t.$media.attr('height'); + } else { + t.height = t.options['default' + capsTagName + 'Height']; + } + + // set the size, while we wait for the plugins to load below + t.setPlayerSize(t.width, t.height); + + // create MediaElementShim + meOptions.pluginWidth = t.width; + meOptions.pluginHeight = t.height; + } + + // create MediaElement shim + mejs.MediaElement(t.$media[0], meOptions); + + if (typeof(t.container) != 'undefined'){ + // controls are shown when loaded + t.container.trigger('controlsshown'); + } + }, + + showControls: function(doAnimation) { + var t = this; + + doAnimation = typeof doAnimation == 'undefined' || doAnimation; + + if (t.controlsAreVisible) + return; + + if (doAnimation) { + t.controls + .css('visibility','visible') + .stop(true, true).fadeIn(200, function() { + t.controlsAreVisible = true; + t.container.trigger('controlsshown'); + }); + + // any additional controls people might add and want to hide + t.container.find('.mejs-control') + .css('visibility','visible') + .stop(true, true).fadeIn(200, function() {t.controlsAreVisible = true;}); + + } else { + t.controls + .css('visibility','visible') + .css('display','block'); + + // any additional controls people might add and want to hide + t.container.find('.mejs-control') + .css('visibility','visible') + .css('display','block'); + + t.controlsAreVisible = true; + t.container.trigger('controlsshown'); + } + + t.setControlsSize(); + + }, + + hideControls: function(doAnimation) { + var t = this; + + doAnimation = typeof doAnimation == 'undefined' || doAnimation; + + if (!t.controlsAreVisible) + return; + + if (doAnimation) { + // fade out main controls + t.controls.stop(true, true).fadeOut(200, function() { + $(this) + .css('visibility','hidden') + .css('display','block'); + + t.controlsAreVisible = false; + t.container.trigger('controlshidden'); + }); + + // any additional controls people might add and want to hide + t.container.find('.mejs-control').stop(true, true).fadeOut(200, function() { + $(this) + .css('visibility','hidden') + .css('display','block'); + }); + } else { + + // hide main controls + t.controls + .css('visibility','hidden') + .css('display','block'); + + // hide others + t.container.find('.mejs-control') + .css('visibility','hidden') + .css('display','block'); + + t.controlsAreVisible = false; + t.container.trigger('controlshidden'); + } + }, + + controlsTimer: null, + + startControlsTimer: function(timeout) { + + var t = this; + + timeout = typeof timeout != 'undefined' ? timeout : 1500; + + t.killControlsTimer('start'); + + t.controlsTimer = setTimeout(function() { + //console.log('timer fired'); + t.hideControls(); + t.killControlsTimer('hide'); + }, timeout); + }, + + killControlsTimer: function(src) { + + var t = this; + + if (t.controlsTimer !== null) { + clearTimeout(t.controlsTimer); + delete t.controlsTimer; + t.controlsTimer = null; + } + }, + + controlsEnabled: true, + + disableControls: function() { + var t= this; + + t.killControlsTimer(); + t.hideControls(false); + this.controlsEnabled = false; + }, + + enableControls: function() { + var t= this; + + t.showControls(false); + + t.controlsEnabled = true; + }, + + + // Sets up all controls and events + meReady: function(media, domNode) { + + + var t = this, + mf = mejs.MediaFeatures, + autoplayAttr = domNode.getAttribute('autoplay'), + autoplay = !(typeof autoplayAttr == 'undefined' || autoplayAttr === null || autoplayAttr === 'false'), + featureIndex, + feature; + + // make sure it can't create itself again if a plugin reloads + if (t.created) { + return; + } else { + t.created = true; + } + + t.media = media; + t.domNode = domNode; + + if (!(mf.isAndroid && t.options.AndroidUseNativeControls) && !(mf.isiPad && t.options.iPadUseNativeControls) && !(mf.isiPhone && t.options.iPhoneUseNativeControls)) { + + // two built in features + t.buildposter(t, t.controls, t.layers, t.media); + t.buildkeyboard(t, t.controls, t.layers, t.media); + t.buildoverlays(t, t.controls, t.layers, t.media); + + // grab for use by features + t.findTracks(); + + // add user-defined features/controls + for (featureIndex in t.options.features) { + feature = t.options.features[featureIndex]; + if (t['build' + feature]) { + try { + t['build' + feature](t, t.controls, t.layers, t.media); + } catch (e) { + // TODO: report control error + //throw e; + //console.log('error building ' + feature); + //console.log(e); + } + } + } + + t.container.trigger('controlsready'); + + // reset all layers and controls + t.setPlayerSize(t.width, t.height); + t.setControlsSize(); + + + // controls fade + if (t.isVideo) { + + if (mejs.MediaFeatures.hasTouch) { + + // for touch devices (iOS, Android) + // show/hide without animation on touch + + t.$media.bind('touchstart', function() { + + + // toggle controls + if (t.controlsAreVisible) { + t.hideControls(false); + } else { + if (t.controlsEnabled) { + t.showControls(false); + } + } + }); + + } else { + + // create callback here since it needs access to current + // MediaElement object + mejs.MediaElementPlayer.prototype.clickToPlayPauseCallback = function() { + console.log('media clicked', t.media, t.media.paused); + + if (t.options.clickToPlayPause) { + if (t.media.paused) { + t.media.play(); + } else { + t.media.pause(); + } + } + }; + + // click to play/pause + t.media.addEventListener('click', t.clickToPlayPauseCallback); + + // show/hide controls + t.container + .bind('mouseenter mouseover', function () { + if (t.controlsEnabled) { + if (!t.options.alwaysShowControls) { + t.killControlsTimer('enter'); + t.showControls(); + t.startControlsTimer(2500); + } + } + }) + .bind('mousemove', function() { + if (t.controlsEnabled) { + if (!t.controlsAreVisible) { + t.showControls(); + } + //t.killControlsTimer('move'); + if (!t.options.alwaysShowControls) { + t.startControlsTimer(2500); + } + } + }) + .bind('mouseleave', function () { + if (t.controlsEnabled) { + if (!t.media.paused && !t.options.alwaysShowControls) { + t.startControlsTimer(1000); + } + } + }); + } + + if(t.options.hideVideoControlsOnLoad) { + t.hideControls(false); + } + + // check for autoplay + if (autoplay && !t.options.alwaysShowControls) { + t.hideControls(); + } + + // resizer + if (t.options.enableAutosize) { + t.media.addEventListener('loadedmetadata', function(e) { + // if the <video height> was not set and the options.videoHeight was not set + // then resize to the real dimensions + if (t.options.videoHeight <= 0 && t.domNode.getAttribute('height') === null && !isNaN(e.target.videoHeight)) { + t.setPlayerSize(e.target.videoWidth, e.target.videoHeight); + t.setControlsSize(); + t.media.setVideoSize(e.target.videoWidth, e.target.videoHeight); + } + }, false); + } + } + + // EVENTS + + // FOCUS: when a video starts playing, it takes focus from other players (possibily pausing them) + media.addEventListener('play', function() { + var playerIndex; + + // go through all other players + for (playerIndex in mejs.players) { + var p = mejs.players[playerIndex]; + if (p.id != t.id && t.options.pauseOtherPlayers && !p.paused && !p.ended) { + p.pause(); + } + p.hasFocus = false; + } + + t.hasFocus = true; + },false); + + + // ended for all + t.media.addEventListener('ended', function (e) { + if(t.options.autoRewind) { + try{ + t.media.setCurrentTime(0); + } catch (exp) { + + } + } + t.media.pause(); + + if (t.setProgressRail) { + t.setProgressRail(); + } + if (t.setCurrentRail) { + t.setCurrentRail(); + } + + if (t.options.loop) { + t.media.play(); + } else if (!t.options.alwaysShowControls && t.controlsEnabled) { + t.showControls(); + } + }, false); + + // resize on the first play + t.media.addEventListener('loadedmetadata', function(e) { + if (t.updateDuration) { + t.updateDuration(); + } + if (t.updateCurrent) { + t.updateCurrent(); + } + + if (!t.isFullScreen) { + t.setPlayerSize(t.width, t.height); + t.setControlsSize(); + } + }, false); + + + // webkit has trouble doing this without a delay + setTimeout(function () { + t.setPlayerSize(t.width, t.height); + t.setControlsSize(); + }, 50); + + // adjust controls whenever window sizes (used to be in fullscreen only) + t.globalBind('resize', function() { + + // don't resize for fullscreen mode + if ( !(t.isFullScreen || (mejs.MediaFeatures.hasTrueNativeFullScreen && document.webkitIsFullScreen)) ) { + t.setPlayerSize(t.width, t.height); + } + + // always adjust controls + t.setControlsSize(); + }); + + // TEMP: needs to be moved somewhere else + if (t.media.pluginType == 'youtube') { + t.container.find('.mejs-overlay-play').hide(); + } + } + + // force autoplay for HTML5 + if (autoplay && media.pluginType == 'native') { + media.load(); + media.play(); + } + + + if (t.options.success) { + + if (typeof t.options.success == 'string') { + window[t.options.success](t.media, t.domNode, t); + } else { + t.options.success(t.media, t.domNode, t); + } + } + }, + + handleError: function(e) { + var t = this; + + t.controls.hide(); + + // Tell user that the file cannot be played + if (t.options.error) { + t.options.error(e); + } + }, + + setPlayerSize: function(width,height) { + var t = this; + + if (typeof width != 'undefined') { + t.width = width; + } + + if (typeof height != 'undefined') { + t.height = height; + } + + // detect 100% mode - use currentStyle for IE since css() doesn't return percentages + if (t.height.toString().indexOf('%') > 0 || t.$node.css('max-width') === '100%' || (t.$node[0].currentStyle && t.$node[0].currentStyle.maxWidth === '100%')) { + + // do we have the native dimensions yet? + var + nativeWidth = t.isVideo ? ((t.media.videoWidth && t.media.videoWidth > 0) ? t.media.videoWidth : t.options.defaultVideoWidth) : t.options.defaultAudioWidth, + nativeHeight = t.isVideo ? ((t.media.videoHeight && t.media.videoHeight > 0) ? t.media.videoHeight : t.options.defaultVideoHeight) : t.options.defaultAudioHeight, + parentWidth = t.container.parent().closest(':visible').width(), + newHeight = t.isVideo || !t.options.autosizeProgress ? parseInt(parentWidth * nativeHeight/nativeWidth, 10) : nativeHeight; + + if (t.container.parent()[0].tagName.toLowerCase() === 'body') { // && t.container.siblings().count == 0) { + parentWidth = $(window).width(); + newHeight = $(window).height(); + } + + if ( newHeight != 0 && parentWidth != 0 ) { + // set outer container size + t.container + .width(parentWidth) + .height(newHeight); + + // set native <video> or <audio> and shims + t.$media.add(t.container.find('.mejs-shim')) + .width('100%') + .height('100%'); + + // if shim is ready, send the size to the embeded plugin + if (t.isVideo) { + if (t.media.setVideoSize) { + t.media.setVideoSize(parentWidth, newHeight); + } + } + + // set the layers + t.layers.children('.mejs-layer') + .width('100%') + .height('100%'); + } + + + } else { + + t.container + .width(t.width) + .height(t.height); + + t.layers.children('.mejs-layer') + .width(t.width) + .height(t.height); + + } + + // special case for big play button so it doesn't go over the controls area + var playLayer = t.layers.find('.mejs-overlay-play'), + playButton = playLayer.find('.mejs-overlay-button'); + + playLayer.height(t.container.height() - t.controls.height()); + playButton.css('margin-top', '-' + (playButton.height()/2 - t.controls.height()/2).toString() + 'px' ); + + }, + + setControlsSize: function() { + var t = this, + usedWidth = 0, + railWidth = 0, + rail = t.controls.find('.mejs-time-rail'), + total = t.controls.find('.mejs-time-total'), + current = t.controls.find('.mejs-time-current'), + loaded = t.controls.find('.mejs-time-loaded'), + others = rail.siblings(); + + + // allow the size to come from custom CSS + if (t.options && !t.options.autosizeProgress) { + // Also, frontends devs can be more flexible + // due the opportunity of absolute positioning. + railWidth = parseInt(rail.css('width')); + } + + // attempt to autosize + if (railWidth === 0 || !railWidth) { + + // find the size of all the other controls besides the rail + others.each(function() { + var $this = $(this); + if ($this.css('position') != 'absolute' && $this.is(':visible')) { + usedWidth += $(this).outerWidth(true); + } + }); + + // fit the rail into the remaining space + railWidth = t.controls.width() - usedWidth - (rail.outerWidth(true) - rail.width()); + } + + // outer area + rail.width(railWidth); + // dark space + total.width(railWidth - (total.outerWidth(true) - total.width())); + + if (t.setProgressRail) + t.setProgressRail(); + if (t.setCurrentRail) + t.setCurrentRail(); + }, + + + buildposter: function(player, controls, layers, media) { + var t = this, + poster = + $('<div class="mejs-poster mejs-layer">' + + '</div>') + .appendTo(layers), + posterUrl = player.$media.attr('poster'); + + // prioriy goes to option (this is useful if you need to support iOS 3.x (iOS completely fails with poster) + if (player.options.poster !== '') { + posterUrl = player.options.poster; + } + + // second, try the real poster + if (posterUrl !== '' && posterUrl != null) { + t.setPoster(posterUrl); + } else { + poster.hide(); + } + + media.addEventListener('play',function() { + poster.hide(); + }, false); + }, + + setPoster: function(url) { + var t = this, + posterDiv = t.container.find('.mejs-poster'), + posterImg = posterDiv.find('img'); + + if (posterImg.length == 0) { + posterImg = $('<img width="100%" height="100%" />').appendTo(posterDiv); + } + + posterImg.attr('src', url); + posterDiv.css({'background-image' : 'url(' + url + ')'}); + }, + + buildoverlays: function(player, controls, layers, media) { + var t = this; + if (!player.isVideo) + return; + + var + loading = + $('<div class="mejs-overlay mejs-layer">'+ + '<div class="mejs-overlay-loading"><span></span></div>'+ + '</div>') + .hide() // start out hidden + .appendTo(layers), + error = + $('<div class="mejs-overlay mejs-layer">'+ + '<div class="mejs-overlay-error"></div>'+ + '</div>') + .hide() // start out hidden + .appendTo(layers), + // this needs to come last so it's on top + bigPlay = + $('<div class="mejs-overlay mejs-layer mejs-overlay-play">'+ + '<div class="mejs-overlay-button"></div>'+ + '</div>') + .appendTo(layers) + .click(function() { + if (t.options.clickToPlayPause) { + if (media.paused) { + media.play(); + } else { + media.pause(); + } + } + }); + + /* + if (mejs.MediaFeatures.isiOS || mejs.MediaFeatures.isAndroid) { + bigPlay.remove(); + loading.remove(); + } + */ + + + // show/hide big play button + media.addEventListener('play',function() { + bigPlay.hide(); + loading.hide(); + controls.find('.mejs-time-buffering').hide(); + error.hide(); + }, false); + + media.addEventListener('playing', function() { + bigPlay.hide(); + loading.hide(); + controls.find('.mejs-time-buffering').hide(); + error.hide(); + }, false); + + media.addEventListener('seeking', function() { + loading.show(); + controls.find('.mejs-time-buffering').show(); + }, false); + + media.addEventListener('seeked', function() { + loading.hide(); + controls.find('.mejs-time-buffering').hide(); + }, false); + + media.addEventListener('pause',function() { + if (!mejs.MediaFeatures.isiPhone) { + bigPlay.show(); + } + }, false); + + media.addEventListener('waiting', function() { + loading.show(); + controls.find('.mejs-time-buffering').show(); + }, false); + + + // show/hide loading + media.addEventListener('loadeddata',function() { + // for some reason Chrome is firing this event + //if (mejs.MediaFeatures.isChrome && media.getAttribute && media.getAttribute('preload') === 'none') + // return; + + loading.show(); + controls.find('.mejs-time-buffering').show(); + }, false); + media.addEventListener('canplay',function() { + loading.hide(); + controls.find('.mejs-time-buffering').hide(); + }, false); + + // error handling + media.addEventListener('error',function() { + loading.hide(); + controls.find('.mejs-time-buffering').hide(); + error.show(); + error.find('mejs-overlay-error').html("Error loading this resource"); + }, false); + }, + + buildkeyboard: function(player, controls, layers, media) { + + var t = this; + + // listen for key presses + t.globalBind('keydown', function(e) { + + if (player.hasFocus && player.options.enableKeyboard) { + + // find a matching key + for (var i=0, il=player.options.keyActions.length; i<il; i++) { + var keyAction = player.options.keyActions[i]; + + for (var j=0, jl=keyAction.keys.length; j<jl; j++) { + if (e.keyCode == keyAction.keys[j]) { + e.preventDefault(); + keyAction.action(player, media, e.keyCode); + return false; + } + } + } + } + + return true; + }); + + // check if someone clicked outside a player region, then kill its focus + t.globalBind('click', function(event) { + if ($(event.target).closest('.mejs-container').length == 0) { + player.hasFocus = false; + } + }); + + }, + + findTracks: function() { + var t = this, + tracktags = t.$media.find('track'); + + // store for use by plugins + t.tracks = []; + tracktags.each(function(index, track) { + + track = $(track); + + t.tracks.push({ + srclang: (track.attr('srclang')) ? track.attr('srclang').toLowerCase() : '', + src: track.attr('src'), + kind: track.attr('kind'), + label: track.attr('label') || '', + entries: [], + isLoaded: false + }); + }); + }, + changeSkin: function(className) { + this.container[0].className = 'mejs-container ' + className; + this.setPlayerSize(this.width, this.height); + this.setControlsSize(); + }, + play: function() { + this.media.play(); + }, + pause: function() { + this.media.pause(); + }, + load: function() { + this.media.load(); + }, + setMuted: function(muted) { + this.media.setMuted(muted); + }, + setCurrentTime: function(time) { + this.media.setCurrentTime(time); + }, + getCurrentTime: function() { + return this.media.currentTime; + }, + setVolume: function(volume) { + this.media.setVolume(volume); + }, + getVolume: function() { + return this.media.volume; + }, + setSrc: function(src) { + this.media.setSrc(src); + }, + remove: function() { + var t = this, featureIndex, feature; + + // invoke features cleanup + for (featureIndex in t.options.features) { + feature = t.options.features[featureIndex]; + if (t['clean' + feature]) { + try { + t['clean' + feature](t); + } catch (e) { + // TODO: report control error + //throw e; + //console.log('error building ' + feature); + //console.log(e); + } + } + } + + if (t.media.pluginType === 'native') { + t.$media.prop('controls', true); + } else { + t.media.remove(); + } + + // grab video and put it back in place + if (!t.isDynamic) { + if (t.media.pluginType === 'native') { + // detach events from the video + // TODO: detach event listeners better than this; + // also detach ONLY the events attached by this plugin! + //t.$node.clone().insertBefore(t.container); + //t.$node.remove(); + } + /*else*/ t.$node.insertBefore(t.container) + } + + // Remove the player from the mejs.players object so that pauseOtherPlayers doesn't blow up when trying to pause a non existance flash api. + delete mejs.players[t.id]; + + t.container.remove(); + t.globalUnbind(); + delete t.node.player; + } + }; + + (function(){ + var rwindow = /^((after|before)print|(before)?unload|hashchange|message|o(ff|n)line|page(hide|show)|popstate|resize|storage)\b/; + + function splitEvents(events, id) { + // add player ID as an event namespace so it's easier to unbind them all later + var ret = {d: [], w: []}; + $.each((events || '').split(' '), function(k, v){ + var eventname = v + '.' + id; + if (eventname.indexOf('.') === 0) { + ret.d.push(eventname); + ret.w.push(eventname); + } + else { + ret[rwindow.test(v) ? 'w' : 'd'].push(eventname); + } + }); + ret.d = ret.d.join(' '); + ret.w = ret.w.join(' '); + return ret; + } + + mejs.MediaElementPlayer.prototype.globalBind = function(events, data, callback) { + var t = this; + events = splitEvents(events, t.id); + if (events.d) $(document).bind(events.d, data, callback); + if (events.w) $(window).bind(events.w, data, callback); + }; + + mejs.MediaElementPlayer.prototype.globalUnbind = function(events, callback) { + var t = this; + events = splitEvents(events, t.id); + if (events.d) $(document).unbind(events.d, callback); + if (events.w) $(window).unbind(events.w, callback); + }; + })(); + + // turn into jQuery plugin + if (typeof jQuery != 'undefined') { + jQuery.fn.mediaelementplayer = function (options) { + if (options === false) { + this.each(function () { + var player = jQuery(this).data('mediaelementplayer'); + if (player) { + player.remove(); + } + jQuery(this).removeData('mediaelementplayer'); + }); + } + else { + this.each(function () { + jQuery(this).data('mediaelementplayer', new mejs.MediaElementPlayer(this, options)); + }); + } + return this; + }; + } + + $(document).ready(function() { + // auto enable using JSON attribute + $('.mejs-player').mediaelementplayer(); + }); + + // push out to window + window.MediaElementPlayer = mejs.MediaElementPlayer; + +})(mejs.$); + +(function($) { + + $.extend(mejs.MepDefaults, { + playpauseText: mejs.i18n.t('Play/Pause') + }); + + // PLAY/pause BUTTON + $.extend(MediaElementPlayer.prototype, { + buildplaypause: function(player, controls, layers, media) { + var + t = this, + play = + $('<div class="mejs-button mejs-playpause-button mejs-play" >' + + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.playpauseText + '" aria-label="' + t.options.playpauseText + '"></button>' + + '</div>') + .appendTo(controls) + .click(function(e) { + e.preventDefault(); + + if (media.paused) { + media.play(); + } else { + media.pause(); + } + + return false; + }); + + media.addEventListener('play',function() { + play.removeClass('mejs-play').addClass('mejs-pause'); + }, false); + media.addEventListener('playing',function() { + play.removeClass('mejs-play').addClass('mejs-pause'); + }, false); + + + media.addEventListener('pause',function() { + play.removeClass('mejs-pause').addClass('mejs-play'); + }, false); + media.addEventListener('paused',function() { + play.removeClass('mejs-pause').addClass('mejs-play'); + }, false); + } + }); + +})(mejs.$); + +(function($) { + + $.extend(mejs.MepDefaults, { + stopText: 'Stop' + }); + + // STOP BUTTON + $.extend(MediaElementPlayer.prototype, { + buildstop: function(player, controls, layers, media) { + var t = this, + stop = + $('<div class="mejs-button mejs-stop-button mejs-stop">' + + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.stopText + '" aria-label="' + t.options.stopText + '"></button>' + + '</div>') + .appendTo(controls) + .click(function() { + if (!media.paused) { + media.pause(); + } + if (media.currentTime > 0) { + media.setCurrentTime(0); + media.pause(); + controls.find('.mejs-time-current').width('0px'); + controls.find('.mejs-time-handle').css('left', '0px'); + controls.find('.mejs-time-float-current').html( mejs.Utility.secondsToTimeCode(0) ); + controls.find('.mejs-currenttime').html( mejs.Utility.secondsToTimeCode(0) ); + layers.find('.mejs-poster').show(); + } + }); + } + }); + +})(mejs.$); + +(function($) { + // progress/loaded bar + $.extend(MediaElementPlayer.prototype, { + buildprogress: function(player, controls, layers, media) { + + $('<div class="mejs-time-rail">'+ + '<span class="mejs-time-total">'+ + '<span class="mejs-time-buffering"></span>'+ + '<span class="mejs-time-loaded"></span>'+ + '<span class="mejs-time-current"></span>'+ + '<span class="mejs-time-handle"></span>'+ + '<span class="mejs-time-float">' + + '<span class="mejs-time-float-current">00:00</span>' + + '<span class="mejs-time-float-corner"></span>' + + '</span>'+ + '</span>'+ + '</div>') + .appendTo(controls); + controls.find('.mejs-time-buffering').hide(); + + var + t = this, + total = controls.find('.mejs-time-total'), + loaded = controls.find('.mejs-time-loaded'), + current = controls.find('.mejs-time-current'), + handle = controls.find('.mejs-time-handle'), + timefloat = controls.find('.mejs-time-float'), + timefloatcurrent = controls.find('.mejs-time-float-current'), + handleMouseMove = function (e) { + // mouse position relative to the object + var x = e.pageX, + offset = total.offset(), + width = total.outerWidth(true), + percentage = 0, + newTime = 0, + pos = 0; + + + if (media.duration) { + if (x < offset.left) { + x = offset.left; + } else if (x > width + offset.left) { + x = width + offset.left; + } + + pos = x - offset.left; + percentage = (pos / width); + newTime = (percentage <= 0.02) ? 0 : percentage * media.duration; + + // seek to where the mouse is + if (mouseIsDown && newTime !== media.currentTime) { + media.setCurrentTime(newTime); + } + + // position floating time box + if (!mejs.MediaFeatures.hasTouch) { + timefloat.css('left', pos); + timefloatcurrent.html( mejs.Utility.secondsToTimeCode(newTime) ); + timefloat.show(); + } + } + }, + mouseIsDown = false, + mouseIsOver = false; + + // handle clicks + //controls.find('.mejs-time-rail').delegate('span', 'click', handleMouseMove); + total + .bind('mousedown', function (e) { + // only handle left clicks + if (e.which === 1) { + mouseIsDown = true; + handleMouseMove(e); + t.globalBind('mousemove.dur', function(e) { + handleMouseMove(e); + }); + t.globalBind('mouseup.dur', function (e) { + mouseIsDown = false; + timefloat.hide(); + t.globalUnbind('.dur'); + }); + return false; + } + }) + .bind('mouseenter', function(e) { + mouseIsOver = true; + t.globalBind('mousemove.dur', function(e) { + handleMouseMove(e); + }); + if (!mejs.MediaFeatures.hasTouch) { + timefloat.show(); + } + }) + .bind('mouseleave',function(e) { + mouseIsOver = false; + if (!mouseIsDown) { + t.globalUnbind('.dur'); + timefloat.hide(); + } + }); + + // loading + media.addEventListener('progress', function (e) { + player.setProgressRail(e); + player.setCurrentRail(e); + }, false); + + // current time + media.addEventListener('timeupdate', function(e) { + player.setProgressRail(e); + player.setCurrentRail(e); + }, false); + + + // store for later use + t.loaded = loaded; + t.total = total; + t.current = current; + t.handle = handle; + }, + setProgressRail: function(e) { + + var + t = this, + target = (e != undefined) ? e.target : t.media, + percent = null; + + // newest HTML5 spec has buffered array (FF4, Webkit) + if (target && target.buffered && target.buffered.length > 0 && target.buffered.end && target.duration) { + // TODO: account for a real array with multiple values (only Firefox 4 has this so far) + percent = target.buffered.end(0) / target.duration; + } + // Some browsers (e.g., FF3.6 and Safari 5) cannot calculate target.bufferered.end() + // to be anything other than 0. If the byte count is available we use this instead. + // Browsers that support the else if do not seem to have the bufferedBytes value and + // should skip to there. Tested in Safari 5, Webkit head, FF3.6, Chrome 6, IE 7/8. + else if (target && target.bytesTotal != undefined && target.bytesTotal > 0 && target.bufferedBytes != undefined) { + percent = target.bufferedBytes / target.bytesTotal; + } + // Firefox 3 with an Ogg file seems to go this way + else if (e && e.lengthComputable && e.total != 0) { + percent = e.loaded/e.total; + } + + // finally update the progress bar + if (percent !== null) { + percent = Math.min(1, Math.max(0, percent)); + // update loaded bar + if (t.loaded && t.total) { + t.loaded.width(t.total.width() * percent); + } + } + }, + setCurrentRail: function() { + + var t = this; + + if (t.media.currentTime != undefined && t.media.duration) { + + // update bar and handle + if (t.total && t.handle) { + var + newWidth = Math.round(t.total.width() * t.media.currentTime / t.media.duration), + handlePos = newWidth - Math.round(t.handle.outerWidth(true) / 2); + + t.current.width(newWidth); + t.handle.css('left', handlePos); + } + } + + } + }); +})(mejs.$); + +(function($) { + + // options + $.extend(mejs.MepDefaults, { + duration: -1, + timeAndDurationSeparator: ' <span> / </span> ' + }); + + + // current and duration 00:00 / 00:00 + $.extend(MediaElementPlayer.prototype, { + buildcurrent: function(player, controls, layers, media) { + var t = this; + + $('<div class="mejs-time">'+ + '<span class="mejs-currenttime">' + (player.options.alwaysShowHours ? '00:' : '') + + (player.options.showTimecodeFrameCount? '00:00:00':'00:00')+ '</span>'+ + '</div>') + .appendTo(controls); + + t.currenttime = t.controls.find('.mejs-currenttime'); + + media.addEventListener('timeupdate',function() { + player.updateCurrent(); + }, false); + }, + + + buildduration: function(player, controls, layers, media) { + var t = this; + + if (controls.children().last().find('.mejs-currenttime').length > 0) { + $(t.options.timeAndDurationSeparator + + '<span class="mejs-duration">' + + (t.options.duration > 0 ? + mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25) : + ((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00')) + ) + + '</span>') + .appendTo(controls.find('.mejs-time')); + } else { + + // add class to current time + controls.find('.mejs-currenttime').parent().addClass('mejs-currenttime-container'); + + $('<div class="mejs-time mejs-duration-container">'+ + '<span class="mejs-duration">' + + (t.options.duration > 0 ? + mejs.Utility.secondsToTimeCode(t.options.duration, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25) : + ((player.options.alwaysShowHours ? '00:' : '') + (player.options.showTimecodeFrameCount? '00:00:00':'00:00')) + ) + + '</span>' + + '</div>') + .appendTo(controls); + } + + t.durationD = t.controls.find('.mejs-duration'); + + media.addEventListener('timeupdate',function() { + player.updateDuration(); + }, false); + }, + + updateCurrent: function() { + var t = this; + + if (t.currenttime) { + t.currenttime.html(mejs.Utility.secondsToTimeCode(t.media.currentTime, t.options.alwaysShowHours || t.media.duration > 3600, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25)); + } + }, + + updateDuration: function() { + var t = this; + + //Toggle the long video class if the video is longer than an hour. + t.container.toggleClass("mejs-long-video", t.media.duration > 3600); + + if (t.durationD && (t.options.duration > 0 || t.media.duration)) { + t.durationD.html(mejs.Utility.secondsToTimeCode(t.options.duration > 0 ? t.options.duration : t.media.duration, t.options.alwaysShowHours, t.options.showTimecodeFrameCount, t.options.framesPerSecond || 25)); + } + } + }); + +})(mejs.$); + +(function($) { + + $.extend(mejs.MepDefaults, { + muteText: mejs.i18n.t('Mute Toggle'), + hideVolumeOnTouchDevices: true, + + audioVolume: 'horizontal', + videoVolume: 'vertical' + }); + + $.extend(MediaElementPlayer.prototype, { + buildvolume: function(player, controls, layers, media) { + + // Android and iOS don't support volume controls + if (mejs.MediaFeatures.hasTouch && this.options.hideVolumeOnTouchDevices) + return; + + var t = this, + mode = (t.isVideo) ? t.options.videoVolume : t.options.audioVolume, + mute = (mode == 'horizontal') ? + + // horizontal version + $('<div class="mejs-button mejs-volume-button mejs-mute">'+ + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '" aria-label="' + t.options.muteText + '"></button>'+ + '</div>' + + '<div class="mejs-horizontal-volume-slider">'+ // outer background + '<div class="mejs-horizontal-volume-total"></div>'+ // line background + '<div class="mejs-horizontal-volume-current"></div>'+ // current volume + '<div class="mejs-horizontal-volume-handle"></div>'+ // handle + '</div>' + ) + .appendTo(controls) : + + // vertical version + $('<div class="mejs-button mejs-volume-button mejs-mute">'+ + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.muteText + '" aria-label="' + t.options.muteText + '"></button>'+ + '<div class="mejs-volume-slider">'+ // outer background + '<div class="mejs-volume-total"></div>'+ // line background + '<div class="mejs-volume-current"></div>'+ // current volume + '<div class="mejs-volume-handle"></div>'+ // handle + '</div>'+ + '</div>') + .appendTo(controls), + volumeSlider = t.container.find('.mejs-volume-slider, .mejs-horizontal-volume-slider'), + volumeTotal = t.container.find('.mejs-volume-total, .mejs-horizontal-volume-total'), + volumeCurrent = t.container.find('.mejs-volume-current, .mejs-horizontal-volume-current'), + volumeHandle = t.container.find('.mejs-volume-handle, .mejs-horizontal-volume-handle'), + + positionVolumeHandle = function(volume, secondTry) { + + if (!volumeSlider.is(':visible') && typeof secondTry == 'undefined') { + volumeSlider.show(); + positionVolumeHandle(volume, true); + volumeSlider.hide() + return; + } + + // correct to 0-1 + volume = Math.max(0,volume); + volume = Math.min(volume,1); + + // ajust mute button style + if (volume == 0) { + mute.removeClass('mejs-mute').addClass('mejs-unmute'); + } else { + mute.removeClass('mejs-unmute').addClass('mejs-mute'); + } + + // position slider + if (mode == 'vertical') { + var + + // height of the full size volume slider background + totalHeight = volumeTotal.height(), + + // top/left of full size volume slider background + totalPosition = volumeTotal.position(), + + // the new top position based on the current volume + // 70% volume on 100px height == top:30px + newTop = totalHeight - (totalHeight * volume); + + // handle + volumeHandle.css('top', Math.round(totalPosition.top + newTop - (volumeHandle.height() / 2))); + + // show the current visibility + volumeCurrent.height(totalHeight - newTop ); + volumeCurrent.css('top', totalPosition.top + newTop); + } else { + var + + // height of the full size volume slider background + totalWidth = volumeTotal.width(), + + // top/left of full size volume slider background + totalPosition = volumeTotal.position(), + + // the new left position based on the current volume + newLeft = totalWidth * volume; + + // handle + volumeHandle.css('left', Math.round(totalPosition.left + newLeft - (volumeHandle.width() / 2))); + + // rezize the current part of the volume bar + volumeCurrent.width( Math.round(newLeft) ); + } + }, + handleVolumeMove = function(e) { + + var volume = null, + totalOffset = volumeTotal.offset(); + + // calculate the new volume based on the moust position + if (mode == 'vertical') { + + var + railHeight = volumeTotal.height(), + totalTop = parseInt(volumeTotal.css('top').replace(/px/,''),10), + newY = e.pageY - totalOffset.top; + + volume = (railHeight - newY) / railHeight; + + // the controls just hide themselves (usually when mouse moves too far up) + if (totalOffset.top == 0 || totalOffset.left == 0) + return; + + } else { + var + railWidth = volumeTotal.width(), + newX = e.pageX - totalOffset.left; + + volume = newX / railWidth; + } + + // ensure the volume isn't outside 0-1 + volume = Math.max(0,volume); + volume = Math.min(volume,1); + + // position the slider and handle + positionVolumeHandle(volume); + + // set the media object (this will trigger the volumechanged event) + if (volume == 0) { + media.setMuted(true); + } else { + media.setMuted(false); + } + media.setVolume(volume); + }, + mouseIsDown = false, + mouseIsOver = false; + + // SLIDER + + mute + .hover(function() { + volumeSlider.show(); + mouseIsOver = true; + }, function() { + mouseIsOver = false; + + if (!mouseIsDown && mode == 'vertical') { + volumeSlider.hide(); + } + }); + + volumeSlider + .bind('mouseover', function() { + mouseIsOver = true; + }) + .bind('mousedown', function (e) { + handleVolumeMove(e); + t.globalBind('mousemove.vol', function(e) { + handleVolumeMove(e); + }); + t.globalBind('mouseup.vol', function () { + mouseIsDown = false; + t.globalUnbind('.vol'); + + if (!mouseIsOver && mode == 'vertical') { + volumeSlider.hide(); + } + }); + mouseIsDown = true; + + return false; + }); + + + // MUTE button + mute.find('button').click(function() { + media.setMuted( !media.muted ); + }); + + // listen for volume change events from other sources + media.addEventListener('volumechange', function(e) { + if (!mouseIsDown) { + if (media.muted) { + positionVolumeHandle(0); + mute.removeClass('mejs-mute').addClass('mejs-unmute'); + } else { + positionVolumeHandle(media.volume); + mute.removeClass('mejs-unmute').addClass('mejs-mute'); + } + } + }, false); + + if (t.container.is(':visible')) { + // set initial volume + positionVolumeHandle(player.options.startVolume); + + // mutes the media and sets the volume icon muted if the initial volume is set to 0 + if (player.options.startVolume === 0) { + media.setMuted(true); + } + + // shim gets the startvolume as a parameter, but we have to set it on the native <video> and <audio> elements + if (media.pluginType === 'native') { + media.setVolume(player.options.startVolume); + } + } + } + }); + +})(mejs.$); + +(function($) { + + $.extend(mejs.MepDefaults, { + usePluginFullScreen: true, + newWindowCallback: function() { return '';}, + fullscreenText: mejs.i18n.t('Fullscreen') + }); + + $.extend(MediaElementPlayer.prototype, { + + isFullScreen: false, + + isNativeFullScreen: false, + + docStyleOverflow: null, + + isInIframe: false, + + buildfullscreen: function(player, controls, layers, media) { + + if (!player.isVideo) + return; + + player.isInIframe = (window.location != window.parent.location); + + // native events + if (mejs.MediaFeatures.hasTrueNativeFullScreen) { + + // chrome doesn't alays fire this in an iframe + var func = function(e) { + + if (mejs.MediaFeatures.isFullScreen()) { + player.isNativeFullScreen = true; + // reset the controls once we are fully in full screen + player.setControlsSize(); + } else { + player.isNativeFullScreen = false; + // when a user presses ESC + // make sure to put the player back into place + player.exitFullScreen(); + } + }; + + if (mejs.MediaFeatures.hasMozNativeFullScreen) { + player.globalBind(mejs.MediaFeatures.fullScreenEventName, func); + } else { + player.container.bind(mejs.MediaFeatures.fullScreenEventName, func); + } + } + + var t = this, + normalHeight = 0, + normalWidth = 0, + container = player.container, + fullscreenBtn = + $('<div class="mejs-button mejs-fullscreen-button">' + + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.fullscreenText + '" aria-label="' + t.options.fullscreenText + '"></button>' + + '</div>') + .appendTo(controls); + + if (t.media.pluginType === 'native' || (!t.options.usePluginFullScreen && !mejs.MediaFeatures.isFirefox)) { + + fullscreenBtn.click(function() { + var isFullScreen = (mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || player.isFullScreen; + + if (isFullScreen) { + player.exitFullScreen(); + } else { + player.enterFullScreen(); + } + }); + + } else { + + var hideTimeout = null, + supportsPointerEvents = (function() { + // TAKEN FROM MODERNIZR + var element = document.createElement('x'), + documentElement = document.documentElement, + getComputedStyle = window.getComputedStyle, + supports; + if(!('pointerEvents' in element.style)){ + return false; + } + element.style.pointerEvents = 'auto'; + element.style.pointerEvents = 'x'; + documentElement.appendChild(element); + supports = getComputedStyle && + getComputedStyle(element, '').pointerEvents === 'auto'; + documentElement.removeChild(element); + return !!supports; + })(); + + //console.log('supportsPointerEvents', supportsPointerEvents); + + if (supportsPointerEvents && !mejs.MediaFeatures.isOpera) { // opera doesn't allow this :( + + // allows clicking through the fullscreen button and controls down directly to Flash + + /* + When a user puts his mouse over the fullscreen button, the controls are disabled + So we put a div over the video and another one on iether side of the fullscreen button + that caputre mouse movement + and restore the controls once the mouse moves outside of the fullscreen button + */ + + var fullscreenIsDisabled = false, + restoreControls = function() { + if (fullscreenIsDisabled) { + // hide the hovers + for (var i in hoverDivs) { + hoverDivs[i].hide(); + } + + // restore the control bar + fullscreenBtn.css('pointer-events', ''); + t.controls.css('pointer-events', ''); + + // prevent clicks from pausing video + t.media.removeEventListener('click', t.clickToPlayPauseCallback); + + // store for later + fullscreenIsDisabled = false; + } + }, + hoverDivs = {}, + hoverDivNames = ['top', 'left', 'right', 'bottom'], + i, len, + positionHoverDivs = function() { + var fullScreenBtnOffsetLeft = fullscreenBtn.offset().left - t.container.offset().left, + fullScreenBtnOffsetTop = fullscreenBtn.offset().top - t.container.offset().top, + fullScreenBtnWidth = fullscreenBtn.outerWidth(true), + fullScreenBtnHeight = fullscreenBtn.outerHeight(true), + containerWidth = t.container.width(), + containerHeight = t.container.height(); + + for (i in hoverDivs) { + hoverDivs[i].css({position: 'absolute', top: 0, left: 0}); //, backgroundColor: '#f00'}); + } + + // over video, but not controls + hoverDivs['top'] + .width( containerWidth ) + .height( fullScreenBtnOffsetTop ); + + // over controls, but not the fullscreen button + hoverDivs['left'] + .width( fullScreenBtnOffsetLeft ) + .height( fullScreenBtnHeight ) + .css({top: fullScreenBtnOffsetTop}); + + // after the fullscreen button + hoverDivs['right'] + .width( containerWidth - fullScreenBtnOffsetLeft - fullScreenBtnWidth ) + .height( fullScreenBtnHeight ) + .css({top: fullScreenBtnOffsetTop, + left: fullScreenBtnOffsetLeft + fullScreenBtnWidth}); + + // under the fullscreen button + hoverDivs['bottom'] + .width( containerWidth ) + .height( containerHeight - fullScreenBtnHeight - fullScreenBtnOffsetTop ) + .css({top: fullScreenBtnOffsetTop + fullScreenBtnHeight}); + }; + + t.globalBind('resize', function() { + positionHoverDivs(); + }); + + for (i = 0, len = hoverDivNames.length; i < len; i++) { + hoverDivs[hoverDivNames[i]] = $('<div class="mejs-fullscreen-hover" />').appendTo(t.container).mouseover(restoreControls).hide(); + } + + // on hover, kill the fullscreen button's HTML handling, allowing clicks down to Flash + fullscreenBtn.on('mouseover',function() { + + if (!t.isFullScreen) { + + var buttonPos = fullscreenBtn.offset(), + containerPos = player.container.offset(); + + // move the button in Flash into place + media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, false); + + // allows click through + fullscreenBtn.css('pointer-events', 'none'); + t.controls.css('pointer-events', 'none'); + + // restore click-to-play + t.media.addEventListener('click', t.clickToPlayPauseCallback); + + // show the divs that will restore things + for (i in hoverDivs) { + hoverDivs[i].show(); + } + + positionHoverDivs(); + + fullscreenIsDisabled = true; + } + + }); + + // restore controls anytime the user enters or leaves fullscreen + media.addEventListener('fullscreenchange', function(e) { + t.isFullScreen = !t.isFullScreen; + // don't allow plugin click to pause video - messes with + // plugin's controls + if (t.isFullScreen) { + t.media.removeEventListener('click', t.clickToPlayPauseCallback); + } else { + t.media.addEventListener('click', t.clickToPlayPauseCallback); + } + restoreControls(); + }); + + + // the mouseout event doesn't work on the fullscren button, because we already killed the pointer-events + // so we use the document.mousemove event to restore controls when the mouse moves outside the fullscreen button + + t.globalBind('mousemove', function(e) { + + // if the mouse is anywhere but the fullsceen button, then restore it all + if (fullscreenIsDisabled) { + + var fullscreenBtnPos = fullscreenBtn.offset(); + + + if (e.pageY < fullscreenBtnPos.top || e.pageY > fullscreenBtnPos.top + fullscreenBtn.outerHeight(true) || + e.pageX < fullscreenBtnPos.left || e.pageX > fullscreenBtnPos.left + fullscreenBtn.outerWidth(true) + ) { + + fullscreenBtn.css('pointer-events', ''); + t.controls.css('pointer-events', ''); + + fullscreenIsDisabled = false; + } + } + }); + + + + } else { + + // the hover state will show the fullscreen button in Flash to hover up and click + + fullscreenBtn + .on('mouseover', function() { + + if (hideTimeout !== null) { + clearTimeout(hideTimeout); + delete hideTimeout; + } + + var buttonPos = fullscreenBtn.offset(), + containerPos = player.container.offset(); + + media.positionFullscreenButton(buttonPos.left - containerPos.left, buttonPos.top - containerPos.top, true); + + }) + .on('mouseout', function() { + + if (hideTimeout !== null) { + clearTimeout(hideTimeout); + delete hideTimeout; + } + + hideTimeout = setTimeout(function() { + media.hideFullscreenButton(); + }, 1500); + + + }); + } + } + + player.fullscreenBtn = fullscreenBtn; + + t.globalBind('keydown',function (e) { + if (((mejs.MediaFeatures.hasTrueNativeFullScreen && mejs.MediaFeatures.isFullScreen()) || t.isFullScreen) && e.keyCode == 27) { + player.exitFullScreen(); + } + }); + + }, + + cleanfullscreen: function(player) { + player.exitFullScreen(); + }, + + containerSizeTimeout: null, + + enterFullScreen: function() { + + var t = this; + + // firefox+flash can't adjust plugin sizes without resetting :( + if (t.media.pluginType !== 'native' && (mejs.MediaFeatures.isFirefox || t.options.usePluginFullScreen)) { + //t.media.setFullscreen(true); + //player.isFullScreen = true; + return; + } + + // store overflow + docStyleOverflow = document.documentElement.style.overflow; + // set it to not show scroll bars so 100% will work + document.documentElement.style.overflow = 'hidden'; + + // store sizing + normalHeight = t.container.height(); + normalWidth = t.container.width(); + + // attempt to do true fullscreen (Safari 5.1 and Firefox Nightly only for now) + if (t.media.pluginType === 'native') { + if (mejs.MediaFeatures.hasTrueNativeFullScreen) { + + mejs.MediaFeatures.requestFullScreen(t.container[0]); + //return; + + if (t.isInIframe) { + // sometimes exiting from fullscreen doesn't work + // notably in Chrome <iframe>. Fixed in version 17 + setTimeout(function checkFullscreen() { + + if (t.isNativeFullScreen) { + + // check if the video is suddenly not really fullscreen + if ($(window).width() !== screen.width) { + // manually exit + t.exitFullScreen(); + } else { + // test again + setTimeout(checkFullscreen, 500); + } + } + + + }, 500); + } + + } else if (mejs.MediaFeatures.hasSemiNativeFullScreen) { + t.media.webkitEnterFullscreen(); + return; + } + } + + // check for iframe launch + if (t.isInIframe) { + var url = t.options.newWindowCallback(this); + + + if (url !== '') { + + // launch immediately + if (!mejs.MediaFeatures.hasTrueNativeFullScreen) { + t.pause(); + window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no'); + return; + } else { + setTimeout(function() { + if (!t.isNativeFullScreen) { + t.pause(); + window.open(url, t.id, 'top=0,left=0,width=' + screen.availWidth + ',height=' + screen.availHeight + ',resizable=yes,scrollbars=no,status=no,toolbar=no'); + } + }, 250); + } + } + + } + + // full window code + + + + // make full size + t.container + .addClass('mejs-container-fullscreen') + .width('100%') + .height('100%'); + //.css({position: 'fixed', left: 0, top: 0, right: 0, bottom: 0, overflow: 'hidden', width: '100%', height: '100%', 'z-index': 1000}); + + // Only needed for safari 5.1 native full screen, can cause display issues elsewhere + // Actually, it seems to be needed for IE8, too + //if (mejs.MediaFeatures.hasTrueNativeFullScreen) { + t.containerSizeTimeout = setTimeout(function() { + t.container.css({width: '100%', height: '100%'}); + t.setControlsSize(); + }, 500); + //} + + if (t.media.pluginType === 'native') { + t.$media + .width('100%') + .height('100%'); + } else { + t.container.find('.mejs-shim') + .width('100%') + .height('100%'); + + //if (!mejs.MediaFeatures.hasTrueNativeFullScreen) { + t.media.setVideoSize($(window).width(),$(window).height()); + //} + } + + t.layers.children('div') + .width('100%') + .height('100%'); + + if (t.fullscreenBtn) { + t.fullscreenBtn + .removeClass('mejs-fullscreen') + .addClass('mejs-unfullscreen'); + } + + t.setControlsSize(); + t.isFullScreen = true; + }, + + exitFullScreen: function() { + + var t = this; + + // Prevent container from attempting to stretch a second time + clearTimeout(t.containerSizeTimeout); + + // firefox can't adjust plugins + if (t.media.pluginType !== 'native' && mejs.MediaFeatures.isFirefox) { + t.media.setFullscreen(false); + //player.isFullScreen = false; + return; + } + + // come outo of native fullscreen + if (mejs.MediaFeatures.hasTrueNativeFullScreen && (mejs.MediaFeatures.isFullScreen() || t.isFullScreen)) { + mejs.MediaFeatures.cancelFullScreen(); + } + + // restore scroll bars to document + document.documentElement.style.overflow = docStyleOverflow; + + t.container + .removeClass('mejs-container-fullscreen') + .width(normalWidth) + .height(normalHeight); + //.css({position: '', left: '', top: '', right: '', bottom: '', overflow: 'inherit', width: normalWidth + 'px', height: normalHeight + 'px', 'z-index': 1}); + + if (t.media.pluginType === 'native') { + t.$media + .width(normalWidth) + .height(normalHeight); + } else { + t.container.find('.mejs-shim') + .width(normalWidth) + .height(normalHeight); + + t.media.setVideoSize(normalWidth, normalHeight); + } + + t.layers.children('div') + .width(normalWidth) + .height(normalHeight); + + t.fullscreenBtn + .removeClass('mejs-unfullscreen') + .addClass('mejs-fullscreen'); + + t.setControlsSize(); + t.isFullScreen = false; + } + }); + +})(mejs.$); + +(function($) { + + // add extra default options + $.extend(mejs.MepDefaults, { + // this will automatically turn on a <track> + startLanguage: '', + + tracksText: mejs.i18n.t('Captions/Subtitles'), + + // option to remove the [cc] button when no <track kind="subtitles"> are present + hideCaptionsButtonWhenEmpty: true, + + // If true and we only have one track, change captions to popup + toggleCaptionsButtonWhenOnlyOne: false, + + // #id or .class + slidesSelector: '' + }); + + $.extend(MediaElementPlayer.prototype, { + + hasChapters: false, + + buildtracks: function(player, controls, layers, media) { + if (player.tracks.length == 0) + return; + + var t = this, + i, + options = ''; + + player.chapters = + $('<div class="mejs-chapters mejs-layer"></div>') + .prependTo(layers).hide(); + player.captions = + $('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position mejs-captions-position-hover"><span class="mejs-captions-text"></span></div></div>') + .prependTo(layers).hide(); + player.captionsText = player.captions.find('.mejs-captions-text'); + player.captionsButton = + $('<div class="mejs-button mejs-captions-button">'+ + '<button type="button" aria-controls="' + t.id + '" title="' + t.options.tracksText + '" aria-label="' + t.options.tracksText + '"></button>'+ + '<div class="mejs-captions-selector">'+ + '<ul>'+ + '<li>'+ + '<input type="radio" name="' + player.id + '_captions" id="' + player.id + '_captions_none" value="none" checked="checked" />' + + '<label for="' + player.id + '_captions_none">' + mejs.i18n.t('None') +'</label>'+ + '</li>' + + '</ul>'+ + '</div>'+ + '</div>') + .appendTo(controls); + + + var subtitleCount = 0; + for (i=0; i<player.tracks.length; i++) { + if (player.tracks[i].kind == 'subtitles') { + subtitleCount++; + } + } + + // if only one language then just make the button a toggle + if (t.options.toggleCaptionsButtonWhenOnlyOne && subtitleCount == 1){ + // click + player.captionsButton.on('click',function() { + if (player.selectedTrack == null) { + var lang = player.tracks[0].srclang; + } else { + var lang = 'none'; + } + player.setTrack(lang); + }); + } else { + // hover + player.captionsButton.hover(function() { + $(this).find('.mejs-captions-selector').css('visibility','visible'); + }, function() { + $(this).find('.mejs-captions-selector').css('visibility','hidden'); + }) + + // handle clicks to the language radio buttons + .on('click','input[type=radio]',function() { + lang = this.value; + player.setTrack(lang); + }); + + } + + if (!player.options.alwaysShowControls) { + // move with controls + player.container + .bind('controlsshown', function () { + // push captions above controls + player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover'); + + }) + .bind('controlshidden', function () { + if (!media.paused) { + // move back to normal place + player.container.find('.mejs-captions-position').removeClass('mejs-captions-position-hover'); + } + }); + } else { + player.container.find('.mejs-captions-position').addClass('mejs-captions-position-hover'); + } + + player.trackToLoad = -1; + player.selectedTrack = null; + player.isLoadingTrack = false; + + + + // add to list + for (i=0; i<player.tracks.length; i++) { + if (player.tracks[i].kind == 'subtitles') { + player.addTrackButton(player.tracks[i].srclang, player.tracks[i].label); + } + } + + // start loading tracks + player.loadNextTrack(); + + + media.addEventListener('timeupdate',function(e) { + player.displayCaptions(); + }, false); + + if (player.options.slidesSelector != '') { + player.slidesContainer = $(player.options.slidesSelector); + + media.addEventListener('timeupdate',function(e) { + player.displaySlides(); + }, false); + + } + + media.addEventListener('loadedmetadata', function(e) { + player.displayChapters(); + }, false); + + player.container.hover( + function () { + // chapters + if (player.hasChapters) { + player.chapters.css('visibility','visible'); + player.chapters.fadeIn(200).height(player.chapters.find('.mejs-chapter').outerHeight()); + } + }, + function () { + if (player.hasChapters && !media.paused) { + player.chapters.fadeOut(200, function() { + $(this).css('visibility','hidden'); + $(this).css('display','block'); + }); + } + }); + + // check for autoplay + if (player.node.getAttribute('autoplay') !== null) { + player.chapters.css('visibility','hidden'); + } + }, + + setTrack: function(lang){ + + var t = this, + i; + + if (lang == 'none') { + t.selectedTrack = null; + t.captionsButton.removeClass('mejs-captions-enabled'); + } else { + for (i=0; i<t.tracks.length; i++) { + if (t.tracks[i].srclang == lang) { + if (t.selectedTrack == null) + t.captionsButton.addClass('mejs-captions-enabled'); + t.selectedTrack = t.tracks[i]; + t.captions.attr('lang', t.selectedTrack.srclang); + t.displayCaptions(); + break; + } + } + } + }, + + loadNextTrack: function() { + var t = this; + + t.trackToLoad++; + if (t.trackToLoad < t.tracks.length) { + t.isLoadingTrack = true; + t.loadTrack(t.trackToLoad); + } else { + // add done? + t.isLoadingTrack = false; + + t.checkForTracks(); + } + }, + + loadTrack: function(index){ + var + t = this, + track = t.tracks[index], + after = function() { + + track.isLoaded = true; + + // create button + //t.addTrackButton(track.srclang); + t.enableTrackButton(track.srclang, track.label); + + t.loadNextTrack(); + + }; + + + $.ajax({ + url: track.src, + dataType: "text", + success: function(d) { + + // parse the loaded file + if (typeof d == "string" && (/<tt\s+xml/ig).exec(d)) { + track.entries = mejs.TrackFormatParser.dfxp.parse(d); + } else { + track.entries = mejs.TrackFormatParser.webvvt.parse(d); + } + + after(); + + if (track.kind == 'chapters') { + t.media.addEventListener('play', function(e) { + if (t.media.duration > 0) { + t.displayChapters(track); + } + }, false); + } + + if (track.kind == 'slides') { + t.setupSlides(track); + } + }, + error: function() { + t.loadNextTrack(); + } + }); + }, + + enableTrackButton: function(lang, label) { + var t = this; + + if (label === '') { + label = mejs.language.codes[lang] || lang; + } + + t.captionsButton + .find('input[value=' + lang + ']') + .prop('disabled',false) + .siblings('label') + .html( label ); + + // auto select + if (t.options.startLanguage == lang) { + $('#' + t.id + '_captions_' + lang).click(); + } + + t.adjustLanguageBox(); + }, + + addTrackButton: function(lang, label) { + var t = this; + if (label === '') { + label = mejs.language.codes[lang] || lang; + } + + t.captionsButton.find('ul').append( + $('<li>'+ + '<input type="radio" name="' + t.id + '_captions" id="' + t.id + '_captions_' + lang + '" value="' + lang + '" disabled="disabled" />' + + '<label for="' + t.id + '_captions_' + lang + '">' + label + ' (loading)' + '</label>'+ + '</li>') + ); + + t.adjustLanguageBox(); + + // remove this from the dropdownlist (if it exists) + t.container.find('.mejs-captions-translations option[value=' + lang + ']').remove(); + }, + + adjustLanguageBox:function() { + var t = this; + // adjust the size of the outer box + t.captionsButton.find('.mejs-captions-selector').height( + t.captionsButton.find('.mejs-captions-selector ul').outerHeight(true) + + t.captionsButton.find('.mejs-captions-translations').outerHeight(true) + ); + }, + + checkForTracks: function() { + var + t = this, + hasSubtitles = false; + + // check if any subtitles + if (t.options.hideCaptionsButtonWhenEmpty) { + for (i=0; i<t.tracks.length; i++) { + if (t.tracks[i].kind == 'subtitles') { + hasSubtitles = true; + break; + } + } + + if (!hasSubtitles) { + t.captionsButton.hide(); + t.setControlsSize(); + } + } + }, + + displayCaptions: function() { + + if (typeof this.tracks == 'undefined') + return; + + var + t = this, + i, + track = t.selectedTrack; + + if (track != null && track.isLoaded) { + for (i=0; i<track.entries.times.length; i++) { + if (t.media.currentTime >= track.entries.times[i].start && t.media.currentTime <= track.entries.times[i].stop){ + t.captionsText.html(track.entries.text[i]); + t.captions.show().height(0); + return; // exit out if one is visible; + } + } + t.captions.hide(); + } else { + t.captions.hide(); + } + }, + + setupSlides: function(track) { + var t = this; + + t.slides = track; + t.slides.entries.imgs = [t.slides.entries.text.length]; + t.showSlide(0); + + }, + + showSlide: function(index) { + if (typeof this.tracks == 'undefined' || typeof this.slidesContainer == 'undefined') { + return; + } + + var t = this, + url = t.slides.entries.text[index], + img = t.slides.entries.imgs[index]; + + if (typeof img == 'undefined' || typeof img.fadeIn == 'undefined') { + + t.slides.entries.imgs[index] = img = $('<img src="' + url + '">') + .on('load', function() { + img.appendTo(t.slidesContainer) + .hide() + .fadeIn() + .siblings(':visible') + .fadeOut(); + + }); + + } else { + + if (!img.is(':visible') && !img.is(':animated')) { + + console.log('showing existing slide'); + + img.fadeIn() + .siblings(':visible') + .fadeOut(); + } + } + + }, + + displaySlides: function() { + + if (typeof this.slides == 'undefined') + return; + + var + t = this, + slides = t.slides, + i; + + for (i=0; i<slides.entries.times.length; i++) { + if (t.media.currentTime >= slides.entries.times[i].start && t.media.currentTime <= slides.entries.times[i].stop){ + + t.showSlide(i); + + return; // exit out if one is visible; + } + } + }, + + displayChapters: function() { + var + t = this, + i; + + for (i=0; i<t.tracks.length; i++) { + if (t.tracks[i].kind == 'chapters' && t.tracks[i].isLoaded) { + t.drawChapters(t.tracks[i]); + t.hasChapters = true; + break; + } + } + }, + + drawChapters: function(chapters) { + var + t = this, + i, + dur, + //width, + //left, + percent = 0, + usedPercent = 0; + + t.chapters.empty(); + + for (i=0; i<chapters.entries.times.length; i++) { + dur = chapters.entries.times[i].stop - chapters.entries.times[i].start; + percent = Math.floor(dur / t.media.duration * 100); + if (percent + usedPercent > 100 || // too large + i == chapters.entries.times.length-1 && percent + usedPercent < 100) // not going to fill it in + { + percent = 100 - usedPercent; + } + //width = Math.floor(t.width * dur / t.media.duration); + //left = Math.floor(t.width * chapters.entries.times[i].start / t.media.duration); + //if (left + width > t.width) { + // width = t.width - left; + //} + + t.chapters.append( $( + '<div class="mejs-chapter" rel="' + chapters.entries.times[i].start + '" style="left: ' + usedPercent.toString() + '%;width: ' + percent.toString() + '%;">' + + '<div class="mejs-chapter-block' + ((i==chapters.entries.times.length-1) ? ' mejs-chapter-block-last' : '') + '">' + + '<span class="ch-title">' + chapters.entries.text[i] + '</span>' + + '<span class="ch-time">' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].start) + '&ndash;' + mejs.Utility.secondsToTimeCode(chapters.entries.times[i].stop) + '</span>' + + '</div>' + + '</div>')); + usedPercent += percent; + } + + t.chapters.find('div.mejs-chapter').click(function() { + t.media.setCurrentTime( parseFloat( $(this).attr('rel') ) ); + if (t.media.paused) { + t.media.play(); + } + }); + + t.chapters.show(); + } + }); + + + + mejs.language = { + codes: { + af:'Afrikaans', + sq:'Albanian', + ar:'Arabic', + be:'Belarusian', + bg:'Bulgarian', + ca:'Catalan', + zh:'Chinese', + 'zh-cn':'Chinese Simplified', + 'zh-tw':'Chinese Traditional', + hr:'Croatian', + cs:'Czech', + da:'Danish', + nl:'Dutch', + en:'English', + et:'Estonian', + tl:'Filipino', + fi:'Finnish', + fr:'French', + gl:'Galician', + de:'German', + el:'Greek', + ht:'Haitian Creole', + iw:'Hebrew', + hi:'Hindi', + hu:'Hungarian', + is:'Icelandic', + id:'Indonesian', + ga:'Irish', + it:'Italian', + ja:'Japanese', + ko:'Korean', + lv:'Latvian', + lt:'Lithuanian', + mk:'Macedonian', + ms:'Malay', + mt:'Maltese', + no:'Norwegian', + fa:'Persian', + pl:'Polish', + pt:'Portuguese', + //'pt-pt':'Portuguese (Portugal)', + ro:'Romanian', + ru:'Russian', + sr:'Serbian', + sk:'Slovak', + sl:'Slovenian', + es:'Spanish', + sw:'Swahili', + sv:'Swedish', + tl:'Tagalog', + th:'Thai', + tr:'Turkish', + uk:'Ukrainian', + vi:'Vietnamese', + cy:'Welsh', + yi:'Yiddish' + } + }; + + /* + Parses WebVVT format which should be formatted as + ================================ + WEBVTT + + 1 + 00:00:01,1 --> 00:00:05,000 + A line of text + + 2 + 00:01:15,1 --> 00:02:05,000 + A second line of text + + =============================== + + Adapted from: http://www.delphiki.com/html5/playr + */ + mejs.TrackFormatParser = { + webvvt: { + // match start "chapter-" (or anythingelse) + pattern_identifier: /^([a-zA-z]+-)?[0-9]+$/, + pattern_timecode: /^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/, + + parse: function(trackText) { + var + i = 0, + lines = mejs.TrackFormatParser.split2(trackText, /\r?\n/), + entries = {text:[], times:[]}, + timecode, + text; + for(; i<lines.length; i++) { + // check for the line number + if (this.pattern_identifier.exec(lines[i])){ + // skip to the next line where the start --> end time code should be + i++; + timecode = this.pattern_timecode.exec(lines[i]); + + if (timecode && i<lines.length){ + i++; + // grab all the (possibly multi-line) text that follows + text = lines[i]; + i++; + while(lines[i] !== '' && i<lines.length){ + text = text + '\n' + lines[i]; + i++; + } + text = $.trim(text).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>"); + // Text is in a different array so I can use .join + entries.text.push(text); + entries.times.push( + { + start: (mejs.Utility.convertSMPTEtoSeconds(timecode[1]) == 0) ? 0.200 : mejs.Utility.convertSMPTEtoSeconds(timecode[1]), + stop: mejs.Utility.convertSMPTEtoSeconds(timecode[3]), + settings: timecode[5] + }); + } + } + } + return entries; + } + }, + // Thanks to Justin Capella: https://github.com/johndyer/mediaelement/pull/420 + dfxp: { + parse: function(trackText) { + trackText = $(trackText).filter("tt"); + var + i = 0, + container = trackText.children("div").eq(0), + lines = container.find("p"), + styleNode = trackText.find("#" + container.attr("style")), + styles, + begin, + end, + text, + entries = {text:[], times:[]}; + + + if (styleNode.length) { + var attributes = styleNode.removeAttr("id").get(0).attributes; + if (attributes.length) { + styles = {}; + for (i = 0; i < attributes.length; i++) { + styles[attributes[i].name.split(":")[1]] = attributes[i].value; + } + } + } + + for(i = 0; i<lines.length; i++) { + var style; + var _temp_times = { + start: null, + stop: null, + style: null + }; + if (lines.eq(i).attr("begin")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("begin")); + if (!_temp_times.start && lines.eq(i-1).attr("end")) _temp_times.start = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i-1).attr("end")); + if (lines.eq(i).attr("end")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i).attr("end")); + if (!_temp_times.stop && lines.eq(i+1).attr("begin")) _temp_times.stop = mejs.Utility.convertSMPTEtoSeconds(lines.eq(i+1).attr("begin")); + if (styles) { + style = ""; + for (var _style in styles) { + style += _style + ":" + styles[_style] + ";"; + } + } + if (style) _temp_times.style = style; + if (_temp_times.start == 0) _temp_times.start = 0.200; + entries.times.push(_temp_times); + text = $.trim(lines.eq(i).html()).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, "<a href='$1' target='_blank'>$1</a>"); + entries.text.push(text); + if (entries.times.start == 0) entries.times.start = 2; + } + return entries; + } + }, + split2: function (text, regex) { + // normal version for compliant browsers + // see below for IE fix + return text.split(regex); + } + }; + + // test for browsers with bad String.split method. + if ('x\n\ny'.split(/\n/gi).length != 3) { + // add super slow IE8 and below version + mejs.TrackFormatParser.split2 = function(text, regex) { + var + parts = [], + chunk = '', + i; + + for (i=0; i<text.length; i++) { + chunk += text.substring(i,i+1); + if (regex.test(chunk)) { + parts.push(chunk.replace(regex, '')); + chunk = ''; + } + } + parts.push(chunk); + return parts; + } + } + +})(mejs.$); + +/* +* ContextMenu Plugin +* +* +*/ + +(function($) { + +$.extend(mejs.MepDefaults, + { 'contextMenuItems': [ + // demo of a fullscreen option + { + render: function(player) { + + // check for fullscreen plugin + if (typeof player.enterFullScreen == 'undefined') + return null; + + if (player.isFullScreen) { + return mejs.i18n.t('Turn off Fullscreen'); + } else { + return mejs.i18n.t('Go Fullscreen'); + } + }, + click: function(player) { + if (player.isFullScreen) { + player.exitFullScreen(); + } else { + player.enterFullScreen(); + } + } + } + , + // demo of a mute/unmute button + { + render: function(player) { + if (player.media.muted) { + return mejs.i18n.t('Unmute'); + } else { + return mejs.i18n.t('Mute'); + } + }, + click: function(player) { + if (player.media.muted) { + player.setMuted(false); + } else { + player.setMuted(true); + } + } + }, + // separator + { + isSeparator: true + } + , + // demo of simple download video + { + render: function(player) { + return mejs.i18n.t('Download Video'); + }, + click: function(player) { + window.location.href = player.media.currentSrc; + } + } + ]} +); + + + $.extend(MediaElementPlayer.prototype, { + buildcontextmenu: function(player, controls, layers, media) { + + // create context menu + player.contextMenu = $('<div class="mejs-contextmenu"></div>') + .appendTo($('body')) + .hide(); + + // create events for showing context menu + player.container.bind('contextmenu', function(e) { + if (player.isContextMenuEnabled) { + e.preventDefault(); + player.renderContextMenu(e.clientX-1, e.clientY-1); + return false; + } + }); + player.container.bind('click', function() { + player.contextMenu.hide(); + }); + player.contextMenu.bind('mouseleave', function() { + + //console.log('context hover out'); + player.startContextMenuTimer(); + + }); + }, + + cleancontextmenu: function(player) { + player.contextMenu.remove(); + }, + + isContextMenuEnabled: true, + enableContextMenu: function() { + this.isContextMenuEnabled = true; + }, + disableContextMenu: function() { + this.isContextMenuEnabled = false; + }, + + contextMenuTimeout: null, + startContextMenuTimer: function() { + //console.log('startContextMenuTimer'); + + var t = this; + + t.killContextMenuTimer(); + + t.contextMenuTimer = setTimeout(function() { + t.hideContextMenu(); + t.killContextMenuTimer(); + }, 750); + }, + killContextMenuTimer: function() { + var timer = this.contextMenuTimer; + + //console.log('killContextMenuTimer', timer); + + if (timer != null) { + clearTimeout(timer); + delete timer; + timer = null; + } + }, + + hideContextMenu: function() { + this.contextMenu.hide(); + }, + + renderContextMenu: function(x,y) { + + // alway re-render the items so that things like "turn fullscreen on" and "turn fullscreen off" are always written correctly + var t = this, + html = '', + items = t.options.contextMenuItems; + + for (var i=0, il=items.length; i<il; i++) { + + if (items[i].isSeparator) { + html += '<div class="mejs-contextmenu-separator"></div>'; + } else { + + var rendered = items[i].render(t); + + // render can return null if the item doesn't need to be used at the moment + if (rendered != null) { + html += '<div class="mejs-contextmenu-item" data-itemindex="' + i + '" id="element-' + (Math.random()*1000000) + '">' + rendered + '</div>'; + } + } + } + + // position and show the context menu + t.contextMenu + .empty() + .append($(html)) + .css({top:y, left:x}) + .show(); + + // bind events + t.contextMenu.find('.mejs-contextmenu-item').each(function() { + + // which one is this? + var $dom = $(this), + itemIndex = parseInt( $dom.data('itemindex'), 10 ), + item = t.options.contextMenuItems[itemIndex]; + + // bind extra functionality? + if (typeof item.show != 'undefined') + item.show( $dom , t); + + // bind click action + $dom.click(function() { + // perform click action + if (typeof item.click != 'undefined') + item.click(t); + + // close + t.contextMenu.hide(); + }); + }); + + // stop the controls from hiding + setTimeout(function() { + t.killControlsTimer('rev3'); + }, 100); + + } + }); + +})(mejs.$); +/** + * Postroll plugin + */ +(function($) { + + $.extend(mejs.MepDefaults, { + postrollCloseText: mejs.i18n.t('Close') + }); + + // Postroll + $.extend(MediaElementPlayer.prototype, { + buildpostroll: function(player, controls, layers, media) { + var + t = this, + postrollLink = t.container.find('link[rel="postroll"]').attr('href'); + + if (typeof postrollLink !== 'undefined') { + player.postroll = + $('<div class="mejs-postroll-layer mejs-layer"><a class="mejs-postroll-close" onclick="$(this).parent().hide();return false;">' + t.options.postrollCloseText + '</a><div class="mejs-postroll-layer-content"></div></div>').prependTo(layers).hide(); + + t.media.addEventListener('ended', function (e) { + $.ajax({ + dataType: 'html', + url: postrollLink, + success: function (data, textStatus) { + layers.find('.mejs-postroll-layer-content').html(data); + } + }); + player.postroll.show(); + }, false); + } + } + }); + +})(mejs.$); diff --git a/src/static/mediaelement/mediaelementplayer.min.css b/src/static/mediaelement/mediaelementplayer.min.css new file mode 100755 index 0000000..4746c32 --- /dev/null +++ b/src/static/mediaelement/mediaelementplayer.min.css @@ -0,0 +1 @@ +.mejs-container{position:relative;background:#000;font-family:Helvetica,Arial;text-align:left;vertical-align:top;text-indent:0;}.me-plugin{position:absolute;}.mejs-embed,.mejs-embed body{width:100%;height:100%;margin:0;padding:0;background:#000;overflow:hidden;}.mejs-container-fullscreen{position:fixed;left:0;top:0;right:0;bottom:0;overflow:hidden;z-index:1000;}.mejs-container-fullscreen .mejs-mediaelement,.mejs-container-fullscreen video{width:100%;height:100%;}.mejs-clear{clear:both;}.mejs-background{position:absolute;top:0;left:0;}.mejs-mediaelement{position:absolute;top:0;left:0;width:100%;height:100%;}.mejs-poster{position:absolute;top:0;left:0;background-size:contain;background-position:50% 50%;background-repeat:no-repeat;}:root .mejs-poster img{display:none;}.mejs-poster img{border:0;padding:0;border:0;}.mejs-overlay{position:absolute;top:0;left:0;}.mejs-overlay-play{cursor:pointer;}.mejs-overlay-button{position:absolute;top:50%;left:50%;width:100px;height:100px;margin:-50px 0 0 -50px;background:url(bigplay.svg) no-repeat;}.no-svg .mejs-overlay-button{background-image:url(bigplay.png);}.mejs-overlay:hover .mejs-overlay-button{background-position:0 -100px;}.mejs-overlay-loading{position:absolute;top:50%;left:50%;width:80px;height:80px;margin:-40px 0 0 -40px;background:#333;background:url(background.png);background:rgba(0,0,0,0.9);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.9)),to(rgba(0,0,0,0.9)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-moz-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-o-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:-ms-linear-gradient(top,rgba(50,50,50,0.9),rgba(0,0,0,0.9));background:linear-gradient(rgba(50,50,50,0.9),rgba(0,0,0,0.9));}.mejs-overlay-loading span{display:block;width:80px;height:80px;background:transparent url(loading.gif) 50% 50% no-repeat;}.mejs-container .mejs-controls{position:absolute;list-style-type:none;margin:0;padding:0;bottom:0;left:0;background:url(background.png);background:rgba(0,0,0,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.7)),to(rgba(0,0,0,0.7)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-moz-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-o-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-ms-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:linear-gradient(rgba(50,50,50,0.7),rgba(0,0,0,0.7));height:30px;width:100%;}.mejs-container .mejs-controls div{list-style-type:none;background-image:none;display:block;float:left;margin:0;padding:0;width:26px;height:26px;font-size:11px;line-height:11px;font-family:Helvetica,Arial;border:0;}.mejs-controls .mejs-button button{cursor:pointer;display:block;font-size:0;line-height:0;text-decoration:none;margin:7px 5px;padding:0;position:absolute;height:16px;width:16px;border:0;background:transparent url(controls.svg) no-repeat;}.no-svg .mejs-controls .mejs-button button{background-image:url(controls.png);}.mejs-controls .mejs-button button:focus{outline:solid 1px yellow;}.mejs-container .mejs-controls .mejs-time{color:#fff;display:block;height:17px;width:auto;padding:8px 3px 0 3px;overflow:hidden;text-align:center;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}.mejs-container .mejs-controls .mejs-time span{color:#fff;font-size:11px;line-height:12px;display:block;float:left;margin:1px 2px 0 0;width:auto;}.mejs-controls .mejs-play button{background-position:0 0;}.mejs-controls .mejs-pause button{background-position:0 -16px;}.mejs-controls .mejs-stop button{background-position:-112px 0;}.mejs-controls div.mejs-time-rail{width:200px;padding-top:5px;}.mejs-controls .mejs-time-rail span{display:block;position:absolute;width:180px;height:10px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;cursor:pointer;}.mejs-controls .mejs-time-rail .mejs-time-total{margin:5px;background:#333;background:rgba(50,50,50,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(30,30,30,0.8)),to(rgba(60,60,60,0.8)));background:-webkit-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-moz-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-o-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-ms-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:linear-gradient(rgba(30,30,30,0.8),rgba(60,60,60,0.8));}.mejs-controls .mejs-time-rail .mejs-time-buffering{width:100%;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:-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:-ms-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:15px 15px;-moz-background-size:15px 15px;-o-background-size:15px 15px;background-size:15px 15px;-webkit-animation:buffering-stripes 2s linear infinite;-moz-animation:buffering-stripes 2s linear infinite;-ms-animation:buffering-stripes 2s linear infinite;-o-animation:buffering-stripes 2s linear infinite;animation:buffering-stripes 2s linear infinite;}@-webkit-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-moz-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-ms-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@-o-keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}@keyframes buffering-stripes{from{background-position:0 0;}to{background-position:30px 0;}}.mejs-controls .mejs-time-rail .mejs-time-loaded{background:#3caac8;background:rgba(60,170,200,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(44,124,145,0.8)),to(rgba(78,183,212,0.8)));background:-webkit-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-moz-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-o-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:-ms-linear-gradient(top,rgba(44,124,145,0.8),rgba(78,183,212,0.8));background:linear-gradient(rgba(44,124,145,0.8),rgba(78,183,212,0.8));width:0;}.mejs-controls .mejs-time-rail .mejs-time-current{background:#fff;background:rgba(255,255,255,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(255,255,255,0.9)),to(rgba(200,200,200,0.8)));background:-webkit-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-moz-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-o-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-ms-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:linear-gradient(rgba(255,255,255,0.9),rgba(200,200,200,0.8));width:0;}.mejs-controls .mejs-time-rail .mejs-time-handle{display:none;position:absolute;margin:0;width:10px;background:#fff;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;cursor:pointer;border:solid 2px #333;top:-2px;text-align:center;}.mejs-controls .mejs-time-rail .mejs-time-float{position:absolute;display:none;background:#eee;width:36px;height:17px;border:solid 1px #333;top:-26px;margin-left:-18px;text-align:center;color:#111;}.mejs-controls .mejs-time-rail .mejs-time-float-current{margin:2px;width:30px;display:block;text-align:center;left:0;}.mejs-controls .mejs-time-rail .mejs-time-float-corner{position:absolute;display:block;width:0;height:0;line-height:0;border:solid 5px #eee;border-color:#eee transparent transparent transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;top:15px;left:13px;}.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float{width:48px;}.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-current{width:44px;}.mejs-long-video .mejs-controls .mejs-time-rail .mejs-time-float-corner{left:18px;}.mejs-controls .mejs-fullscreen-button button{background-position:-32px 0;}.mejs-controls .mejs-unfullscreen button{background-position:-32px -16px;}.mejs-controls .mejs-mute button{background-position:-16px -16px;}.mejs-controls .mejs-unmute button{background-position:-16px 0;}.mejs-controls .mejs-volume-button{position:relative;}.mejs-controls .mejs-volume-button .mejs-volume-slider{display:none;height:115px;width:25px;background:url(background.png);background:rgba(50,50,50,0.7);-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;top:-115px;left:0;z-index:1;position:absolute;margin:0;}.mejs-controls .mejs-volume-button:hover{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-total{position:absolute;left:11px;top:8px;width:2px;height:100px;background:#ddd;background:rgba(255,255,255,0.5);margin:0;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-current{position:absolute;left:11px;top:8px;width:2px;height:100px;background:#ddd;background:rgba(255,255,255,0.9);margin:0;}.mejs-controls .mejs-volume-button .mejs-volume-slider .mejs-volume-handle{position:absolute;left:4px;top:-3px;width:16px;height:6px;background:#ddd;background:rgba(255,255,255,0.9);cursor:N-resize;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;margin:0;}.mejs-controls div.mejs-horizontal-volume-slider{height:26px;width:60px;position:relative;}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-total{position:absolute;left:0;top:11px;width:50px;height:8px;margin:0;padding:0;font-size:1px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;background:#333;background:rgba(50,50,50,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(30,30,30,0.8)),to(rgba(60,60,60,0.8)));background:-webkit-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-moz-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-o-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:-ms-linear-gradient(top,rgba(30,30,30,0.8),rgba(60,60,60,0.8));background:linear-gradient(rgba(30,30,30,0.8),rgba(60,60,60,0.8));}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-current{position:absolute;left:0;top:11px;width:50px;height:8px;margin:0;padding:0;font-size:1px;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;background:#fff;background:rgba(255,255,255,0.8);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(255,255,255,0.9)),to(rgba(200,200,200,0.8)));background:-webkit-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-moz-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-o-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:-ms-linear-gradient(top,rgba(255,255,255,0.9),rgba(200,200,200,0.8));background:linear-gradient(rgba(255,255,255,0.9),rgba(200,200,200,0.8));}.mejs-controls .mejs-horizontal-volume-slider .mejs-horizontal-volume-handle{display:none;}.mejs-controls .mejs-captions-button{position:relative;}.mejs-controls .mejs-captions-button button{background-position:-48px 0;}.mejs-controls .mejs-captions-button .mejs-captions-selector{visibility:hidden;position:absolute;bottom:26px;right:-10px;width:130px;height:100px;background:url(background.png);background:rgba(50,50,50,0.7);border:solid 1px transparent;padding:10px;overflow:hidden;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul{margin:0;padding:0;display:block;list-style-type:none!important;overflow:hidden;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li{margin:0 0 6px 0;padding:0;list-style-type:none!important;display:block;color:#fff;overflow:hidden;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li input{clear:both;float:left;margin:3px 3px 0 5px;}.mejs-controls .mejs-captions-button .mejs-captions-selector ul li label{width:100px;float:left;padding:4px 0 0 0;line-height:15px;font-family:helvetica,arial;font-size:10px;}.mejs-controls .mejs-captions-button .mejs-captions-translations{font-size:10px;margin:0 0 5px 0;}.mejs-chapters{position:absolute;top:0;left:0;-xborder-right:solid 1px #fff;width:10000px;z-index:1;}.mejs-chapters .mejs-chapter{position:absolute;float:left;background:#222;background:rgba(0,0,0,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(50,50,50,0.7)),to(rgba(0,0,0,0.7)));background:-webkit-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-moz-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-o-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:-ms-linear-gradient(top,rgba(50,50,50,0.7),rgba(0,0,0,0.7));background:linear-gradient(rgba(50,50,50,0.7),rgba(0,0,0,0.7));filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,startColorstr=#323232,endColorstr=#000000);overflow:hidden;border:0;}.mejs-chapters .mejs-chapter .mejs-chapter-block{font-size:11px;color:#fff;padding:5px;display:block;border-right:solid 1px #333;border-bottom:solid 1px #333;cursor:pointer;}.mejs-chapters .mejs-chapter .mejs-chapter-block-last{border-right:none;}.mejs-chapters .mejs-chapter .mejs-chapter-block:hover{background:#666;background:rgba(102,102,102,0.7);background:-webkit-gradient(linear,0% 0,0% 100%,from(rgba(102,102,102,0.7)),to(rgba(50,50,50,0.6)));background:-webkit-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-moz-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-o-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:-ms-linear-gradient(top,rgba(102,102,102,0.7),rgba(50,50,50,0.6));background:linear-gradient(rgba(102,102,102,0.7),rgba(50,50,50,0.6));filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,startColorstr=#666666,endColorstr=#323232);}.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-title{font-size:12px;font-weight:bold;display:block;white-space:nowrap;text-overflow:ellipsis;margin:0 0 3px 0;line-height:12px;}.mejs-chapters .mejs-chapter .mejs-chapter-block .ch-timespan{font-size:12px;line-height:12px;margin:3px 0 4px 0;display:block;white-space:nowrap;text-overflow:ellipsis;}.mejs-captions-layer{position:absolute;bottom:0;left:0;text-align:center;line-height:22px;font-size:12px;color:#fff;}.mejs-captions-layer a{color:#fff;text-decoration:underline;}.mejs-captions-layer[lang=ar]{font-size:20px;font-weight:normal;}.mejs-captions-position{position:absolute;width:100%;bottom:15px;left:0;}.mejs-captions-position-hover{bottom:45px;}.mejs-captions-text{padding:3px 5px;background:url(background.png);background:rgba(20,20,20,0.8);}.me-cannotplay a{color:#fff;font-weight:bold;}.me-cannotplay span{padding:15px;display:block;}.mejs-controls .mejs-loop-off button{background-position:-64px -16px;}.mejs-controls .mejs-loop-on button{background-position:-64px 0;}.mejs-controls .mejs-backlight-off button{background-position:-80px -16px;}.mejs-controls .mejs-backlight-on button{background-position:-80px 0;}.mejs-controls .mejs-picturecontrols-button{background-position:-96px 0;}.mejs-contextmenu{position:absolute;width:150px;padding:10px;border-radius:4px;top:0;left:0;background:#fff;border:solid 1px #999;z-index:1001;}.mejs-contextmenu .mejs-contextmenu-separator{height:1px;font-size:0;margin:5px 6px;background:#333;}.mejs-contextmenu .mejs-contextmenu-item{font-family:Helvetica,Arial;font-size:12px;padding:4px 6px;cursor:pointer;color:#333;}.mejs-contextmenu .mejs-contextmenu-item:hover{background:#2C7C91;color:#fff;}.mejs-controls .mejs-sourcechooser-button{position:relative;}.mejs-controls .mejs-sourcechooser-button button{background-position:-128px 0;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector{visibility:hidden;position:absolute;bottom:26px;right:-10px;width:130px;height:100px;background:url(background.png);background:rgba(50,50,50,0.7);border:solid 1px transparent;padding:10px;overflow:hidden;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul{margin:0;padding:0;display:block;list-style-type:none!important;overflow:hidden;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li{margin:0 0 6px 0;padding:0;list-style-type:none!important;display:block;color:#fff;overflow:hidden;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li input{clear:both;float:left;margin:3px 3px 0 5px;}.mejs-controls .mejs-sourcechooser-button .mejs-sourcechooser-selector ul li label{width:100px;float:left;padding:4px 0 0 0;line-height:15px;font-family:helvetica,arial;font-size:10px;}.mejs-postroll-layer{position:absolute;bottom:0;left:0;width:100%;height:100%;background:url(background.png);background:rgba(50,50,50,0.7);z-index:1000;overflow:hidden;}.mejs-postroll-layer-content{width:100%;height:100%;}.mejs-postroll-close{position:absolute;right:0;top:0;background:url(background.png);background:rgba(50,50,50,0.7);color:#fff;padding:4px;z-index:100;cursor:pointer;} \ No newline at end of file diff --git a/src/static/mediaelement/mediaelementplayer.min.js b/src/static/mediaelement/mediaelementplayer.min.js new file mode 100755 index 0000000..0706b7d --- /dev/null +++ b/src/static/mediaelement/mediaelementplayer.min.js @@ -0,0 +1,103 @@ +/*! + * MediaElementPlayer + * http://mediaelementjs.com/ + * + * Creates a controller bar for HTML5 <video> add <audio> tags + * using jQuery and MediaElement.js (HTML5 Flash/Silverlight wrapper) + * + * Copyright 2010-2013, John Dyer (http://j.hn/) + * License: MIT + * + */if(typeof jQuery!="undefined")mejs.$=jQuery;else if(typeof ender!="undefined")mejs.$=ender; +(function(f){mejs.MepDefaults={poster:"",defaultVideoWidth:480,defaultVideoHeight:270,videoWidth:-1,videoHeight:-1,defaultAudioWidth:400,defaultAudioHeight:30,defaultSeekBackwardInterval:function(a){return a.duration*0.05},defaultSeekForwardInterval:function(a){return a.duration*0.05},audioWidth:-1,audioHeight:-1,startVolume:0.8,loop:false,autoRewind:true,enableAutosize:true,alwaysShowHours:false,showTimecodeFrameCount:false,framesPerSecond:25,autosizeProgress:true,alwaysShowControls:false,hideVideoControlsOnLoad:false, +clickToPlayPause:true,iPadUseNativeControls:false,iPhoneUseNativeControls:false,AndroidUseNativeControls:false,features:["playpause","current","progress","duration","tracks","volume","fullscreen"],isVideo:true,enableKeyboard:true,pauseOtherPlayers:true,keyActions:[{keys:[32,179],action:function(a,b){b.paused||b.ended?b.play():b.pause()}},{keys:[38],action:function(a,b){b.setVolume(Math.min(b.volume+0.1,1))}},{keys:[40],action:function(a,b){b.setVolume(Math.max(b.volume-0.1,0))}},{keys:[37,227],action:function(a, +b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}var c=Math.max(b.currentTime-a.options.defaultSeekBackwardInterval(b),0);b.setCurrentTime(c)}}},{keys:[39,228],action:function(a,b){if(!isNaN(b.duration)&&b.duration>0){if(a.isVideo){a.showControls();a.startControlsTimer()}var c=Math.min(b.currentTime+a.options.defaultSeekForwardInterval(b),b.duration);b.setCurrentTime(c)}}},{keys:[70],action:function(a){if(typeof a.enterFullScreen!="undefined")a.isFullScreen? +a.exitFullScreen():a.enterFullScreen()}}]};mejs.mepIndex=0;mejs.players={};mejs.MediaElementPlayer=function(a,b){if(!(this instanceof mejs.MediaElementPlayer))return new mejs.MediaElementPlayer(a,b);this.$media=this.$node=f(a);this.node=this.media=this.$media[0];if(typeof this.node.player!="undefined")return this.node.player;else this.node.player=this;if(typeof b=="undefined")b=this.$node.data("mejsoptions");this.options=f.extend({},mejs.MepDefaults,b);this.id="mep_"+mejs.mepIndex++;mejs.players[this.id]= +this;this.init();return this};mejs.MediaElementPlayer.prototype={hasFocus:false,controlsAreVisible:true,init:function(){var a=this,b=mejs.MediaFeatures,c=f.extend(true,{},a.options,{success:function(d,g){a.meReady(d,g)},error:function(d){a.handleError(d)}}),e=a.media.tagName.toLowerCase();a.isDynamic=e!=="audio"&&e!=="video";a.isVideo=a.isDynamic?a.options.isVideo:e!=="audio"&&a.options.isVideo;if(b.isiPad&&a.options.iPadUseNativeControls||b.isiPhone&&a.options.iPhoneUseNativeControls){a.$media.attr("controls", +"controls");if(b.isiPad&&a.media.getAttribute("autoplay")!==null){a.media.load();a.media.play()}}else if(!(b.isAndroid&&a.options.AndroidUseNativeControls)){a.$media.removeAttr("controls");a.container=f('<div id="'+a.id+'" class="mejs-container '+(mejs.MediaFeatures.svg?"svg":"no-svg")+'"><div class="mejs-inner"><div class="mejs-mediaelement"></div><div class="mejs-layers"></div><div class="mejs-controls"></div><div class="mejs-clear"></div></div></div>').addClass(a.$media[0].className).insertBefore(a.$media); +a.container.addClass((b.isAndroid?"mejs-android ":"")+(b.isiOS?"mejs-ios ":"")+(b.isiPad?"mejs-ipad ":"")+(b.isiPhone?"mejs-iphone ":"")+(a.isVideo?"mejs-video ":"mejs-audio "));if(b.isiOS){b=a.$media.clone();a.container.find(".mejs-mediaelement").append(b);a.$media.remove();a.$node=a.$media=b;a.node=a.media=b[0]}else a.container.find(".mejs-mediaelement").append(a.$media);a.controls=a.container.find(".mejs-controls");a.layers=a.container.find(".mejs-layers");b=a.isVideo?"video":"audio";e=b.substring(0, +1).toUpperCase()+b.substring(1);a.width=a.options[b+"Width"]>0||a.options[b+"Width"].toString().indexOf("%")>-1?a.options[b+"Width"]:a.media.style.width!==""&&a.media.style.width!==null?a.media.style.width:a.media.getAttribute("width")!==null?a.$media.attr("width"):a.options["default"+e+"Width"];a.height=a.options[b+"Height"]>0||a.options[b+"Height"].toString().indexOf("%")>-1?a.options[b+"Height"]:a.media.style.height!==""&&a.media.style.height!==null?a.media.style.height:a.$media[0].getAttribute("height")!== +null?a.$media.attr("height"):a.options["default"+e+"Height"];a.setPlayerSize(a.width,a.height);c.pluginWidth=a.width;c.pluginHeight=a.height}mejs.MediaElement(a.$media[0],c);typeof a.container!="undefined"&&a.container.trigger("controlsshown")},showControls:function(a){var b=this;a=typeof a=="undefined"||a;if(!b.controlsAreVisible){if(a){b.controls.css("visibility","visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true;b.container.trigger("controlsshown")});b.container.find(".mejs-control").css("visibility", +"visible").stop(true,true).fadeIn(200,function(){b.controlsAreVisible=true})}else{b.controls.css("visibility","visible").css("display","block");b.container.find(".mejs-control").css("visibility","visible").css("display","block");b.controlsAreVisible=true;b.container.trigger("controlsshown")}b.setControlsSize()}},hideControls:function(a){var b=this;a=typeof a=="undefined"||a;if(b.controlsAreVisible)if(a){b.controls.stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display", +"block");b.controlsAreVisible=false;b.container.trigger("controlshidden")});b.container.find(".mejs-control").stop(true,true).fadeOut(200,function(){f(this).css("visibility","hidden").css("display","block")})}else{b.controls.css("visibility","hidden").css("display","block");b.container.find(".mejs-control").css("visibility","hidden").css("display","block");b.controlsAreVisible=false;b.container.trigger("controlshidden")}},controlsTimer:null,startControlsTimer:function(a){var b=this;a=typeof a!="undefined"? +a:1500;b.killControlsTimer("start");b.controlsTimer=setTimeout(function(){b.hideControls();b.killControlsTimer("hide")},a)},killControlsTimer:function(){if(this.controlsTimer!==null){clearTimeout(this.controlsTimer);delete this.controlsTimer;this.controlsTimer=null}},controlsEnabled:true,disableControls:function(){this.killControlsTimer();this.hideControls(false);this.controlsEnabled=false},enableControls:function(){this.showControls(false);this.controlsEnabled=true},meReady:function(a,b){var c=this, +e=mejs.MediaFeatures,d=b.getAttribute("autoplay");d=!(typeof d=="undefined"||d===null||d==="false");var g;if(!c.created){c.created=true;c.media=a;c.domNode=b;if(!(e.isAndroid&&c.options.AndroidUseNativeControls)&&!(e.isiPad&&c.options.iPadUseNativeControls)&&!(e.isiPhone&&c.options.iPhoneUseNativeControls)){c.buildposter(c,c.controls,c.layers,c.media);c.buildkeyboard(c,c.controls,c.layers,c.media);c.buildoverlays(c,c.controls,c.layers,c.media);c.findTracks();for(g in c.options.features){e=c.options.features[g]; +if(c["build"+e])try{c["build"+e](c,c.controls,c.layers,c.media)}catch(k){}}c.container.trigger("controlsready");c.setPlayerSize(c.width,c.height);c.setControlsSize();if(c.isVideo){if(mejs.MediaFeatures.hasTouch)c.$media.bind("touchstart",function(){if(c.controlsAreVisible)c.hideControls(false);else c.controlsEnabled&&c.showControls(false)});else{mejs.MediaElementPlayer.prototype.clickToPlayPauseCallback=function(){console.log("media clicked",c.media,c.media.paused);if(c.options.clickToPlayPause)c.media.paused? +c.media.play():c.media.pause()};c.media.addEventListener("click",c.clickToPlayPauseCallback);c.container.bind("mouseenter mouseover",function(){if(c.controlsEnabled)if(!c.options.alwaysShowControls){c.killControlsTimer("enter");c.showControls();c.startControlsTimer(2500)}}).bind("mousemove",function(){if(c.controlsEnabled){c.controlsAreVisible||c.showControls();c.options.alwaysShowControls||c.startControlsTimer(2500)}}).bind("mouseleave",function(){c.controlsEnabled&&!c.media.paused&&!c.options.alwaysShowControls&& +c.startControlsTimer(1E3)})}c.options.hideVideoControlsOnLoad&&c.hideControls(false);d&&!c.options.alwaysShowControls&&c.hideControls();c.options.enableAutosize&&c.media.addEventListener("loadedmetadata",function(j){if(c.options.videoHeight<=0&&c.domNode.getAttribute("height")===null&&!isNaN(j.target.videoHeight)){c.setPlayerSize(j.target.videoWidth,j.target.videoHeight);c.setControlsSize();c.media.setVideoSize(j.target.videoWidth,j.target.videoHeight)}},false)}a.addEventListener("play",function(){for(var j in mejs.players){var m= +mejs.players[j];m.id!=c.id&&c.options.pauseOtherPlayers&&!m.paused&&!m.ended&&m.pause();m.hasFocus=false}c.hasFocus=true},false);c.media.addEventListener("ended",function(){if(c.options.autoRewind)try{c.media.setCurrentTime(0)}catch(j){}c.media.pause();c.setProgressRail&&c.setProgressRail();c.setCurrentRail&&c.setCurrentRail();if(c.options.loop)c.media.play();else!c.options.alwaysShowControls&&c.controlsEnabled&&c.showControls()},false);c.media.addEventListener("loadedmetadata",function(){c.updateDuration&& +c.updateDuration();c.updateCurrent&&c.updateCurrent();if(!c.isFullScreen){c.setPlayerSize(c.width,c.height);c.setControlsSize()}},false);setTimeout(function(){c.setPlayerSize(c.width,c.height);c.setControlsSize()},50);c.globalBind("resize",function(){c.isFullScreen||mejs.MediaFeatures.hasTrueNativeFullScreen&&document.webkitIsFullScreen||c.setPlayerSize(c.width,c.height);c.setControlsSize()});c.media.pluginType=="youtube"&&c.container.find(".mejs-overlay-play").hide()}if(d&&a.pluginType=="native"){a.load(); +a.play()}if(c.options.success)typeof c.options.success=="string"?window[c.options.success](c.media,c.domNode,c):c.options.success(c.media,c.domNode,c)}},handleError:function(a){this.controls.hide();this.options.error&&this.options.error(a)},setPlayerSize:function(a,b){if(typeof a!="undefined")this.width=a;if(typeof b!="undefined")this.height=b;if(this.height.toString().indexOf("%")>0||this.$node.css("max-width")==="100%"||this.$node[0].currentStyle&&this.$node[0].currentStyle.maxWidth==="100%"){var c= +this.isVideo?this.media.videoWidth&&this.media.videoWidth>0?this.media.videoWidth:this.options.defaultVideoWidth:this.options.defaultAudioWidth,e=this.isVideo?this.media.videoHeight&&this.media.videoHeight>0?this.media.videoHeight:this.options.defaultVideoHeight:this.options.defaultAudioHeight,d=this.container.parent().closest(":visible").width();c=this.isVideo||!this.options.autosizeProgress?parseInt(d*e/c,10):e;if(this.container.parent()[0].tagName.toLowerCase()==="body"){d=f(window).width();c= +f(window).height()}if(c!=0&&d!=0){this.container.width(d).height(c);this.$media.add(this.container.find(".mejs-shim")).width("100%").height("100%");this.isVideo&&this.media.setVideoSize&&this.media.setVideoSize(d,c);this.layers.children(".mejs-layer").width("100%").height("100%")}}else{this.container.width(this.width).height(this.height);this.layers.children(".mejs-layer").width(this.width).height(this.height)}d=this.layers.find(".mejs-overlay-play");c=d.find(".mejs-overlay-button");d.height(this.container.height()- +this.controls.height());c.css("margin-top","-"+(c.height()/2-this.controls.height()/2).toString()+"px")},setControlsSize:function(){var a=0,b=0,c=this.controls.find(".mejs-time-rail"),e=this.controls.find(".mejs-time-total");this.controls.find(".mejs-time-current");this.controls.find(".mejs-time-loaded");var d=c.siblings();if(this.options&&!this.options.autosizeProgress)b=parseInt(c.css("width"));if(b===0||!b){d.each(function(){var g=f(this);if(g.css("position")!="absolute"&&g.is(":visible"))a+=f(this).outerWidth(true)}); +b=this.controls.width()-a-(c.outerWidth(true)-c.width())}c.width(b);e.width(b-(e.outerWidth(true)-e.width()));this.setProgressRail&&this.setProgressRail();this.setCurrentRail&&this.setCurrentRail()},buildposter:function(a,b,c,e){var d=f('<div class="mejs-poster mejs-layer"></div>').appendTo(c);b=a.$media.attr("poster");if(a.options.poster!=="")b=a.options.poster;b!==""&&b!=null?this.setPoster(b):d.hide();e.addEventListener("play",function(){d.hide()},false)},setPoster:function(a){var b=this.container.find(".mejs-poster"), +c=b.find("img");if(c.length==0)c=f('<img width="100%" height="100%" />').appendTo(b);c.attr("src",a);b.css({"background-image":"url("+a+")"})},buildoverlays:function(a,b,c,e){var d=this;if(a.isVideo){var g=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-loading"><span></span></div></div>').hide().appendTo(c),k=f('<div class="mejs-overlay mejs-layer"><div class="mejs-overlay-error"></div></div>').hide().appendTo(c),j=f('<div class="mejs-overlay mejs-layer mejs-overlay-play"><div class="mejs-overlay-button"></div></div>').appendTo(c).click(function(){if(d.options.clickToPlayPause)e.paused? +e.play():e.pause()});e.addEventListener("play",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide();k.hide()},false);e.addEventListener("playing",function(){j.hide();g.hide();b.find(".mejs-time-buffering").hide();k.hide()},false);e.addEventListener("seeking",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("seeked",function(){g.hide();b.find(".mejs-time-buffering").hide()},false);e.addEventListener("pause",function(){mejs.MediaFeatures.isiPhone||j.show()}, +false);e.addEventListener("waiting",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("loadeddata",function(){g.show();b.find(".mejs-time-buffering").show()},false);e.addEventListener("canplay",function(){g.hide();b.find(".mejs-time-buffering").hide()},false);e.addEventListener("error",function(){g.hide();b.find(".mejs-time-buffering").hide();k.show();k.find("mejs-overlay-error").html("Error loading this resource")},false)}},buildkeyboard:function(a,b,c,e){this.globalBind("keydown", +function(d){if(a.hasFocus&&a.options.enableKeyboard)for(var g=0,k=a.options.keyActions.length;g<k;g++)for(var j=a.options.keyActions[g],m=0,q=j.keys.length;m<q;m++)if(d.keyCode==j.keys[m]){d.preventDefault();j.action(a,e,d.keyCode);return false}return true});this.globalBind("click",function(d){if(f(d.target).closest(".mejs-container").length==0)a.hasFocus=false})},findTracks:function(){var a=this,b=a.$media.find("track");a.tracks=[];b.each(function(c,e){e=f(e);a.tracks.push({srclang:e.attr("srclang")? +e.attr("srclang").toLowerCase():"",src:e.attr("src"),kind:e.attr("kind"),label:e.attr("label")||"",entries:[],isLoaded:false})})},changeSkin:function(a){this.container[0].className="mejs-container "+a;this.setPlayerSize(this.width,this.height);this.setControlsSize()},play:function(){this.media.play()},pause:function(){this.media.pause()},load:function(){this.media.load()},setMuted:function(a){this.media.setMuted(a)},setCurrentTime:function(a){this.media.setCurrentTime(a)},getCurrentTime:function(){return this.media.currentTime}, +setVolume:function(a){this.media.setVolume(a)},getVolume:function(){return this.media.volume},setSrc:function(a){this.media.setSrc(a)},remove:function(){var a,b;for(a in this.options.features){b=this.options.features[a];if(this["clean"+b])try{this["clean"+b](this)}catch(c){}}this.media.pluginType==="native"?this.$media.prop("controls",true):this.media.remove();this.isDynamic||this.$node.insertBefore(this.container);delete mejs.players[this.id];this.container.remove();this.globalUnbind();delete this.node.player}}; +(function(){function a(c,e){var d={d:[],w:[]};f.each((c||"").split(" "),function(g,k){var j=k+"."+e;if(j.indexOf(".")===0){d.d.push(j);d.w.push(j)}else d[b.test(k)?"w":"d"].push(j)});d.d=d.d.join(" ");d.w=d.w.join(" ");return d}var b=/^((after|before)print|(before)?unload|hashchange|message|o(ff|n)line|page(hide|show)|popstate|resize|storage)\b/;mejs.MediaElementPlayer.prototype.globalBind=function(c,e,d){c=a(c,this.id);c.d&&f(document).bind(c.d,e,d);c.w&&f(window).bind(c.w,e,d)};mejs.MediaElementPlayer.prototype.globalUnbind= +function(c,e){c=a(c,this.id);c.d&&f(document).unbind(c.d,e);c.w&&f(window).unbind(c.w,e)}})();if(typeof jQuery!="undefined")jQuery.fn.mediaelementplayer=function(a){a===false?this.each(function(){var b=jQuery(this).data("mediaelementplayer");b&&b.remove();jQuery(this).removeData("mediaelementplayer")}):this.each(function(){jQuery(this).data("mediaelementplayer",new mejs.MediaElementPlayer(this,a))});return this};f(document).ready(function(){f(".mejs-player").mediaelementplayer()});window.MediaElementPlayer= +mejs.MediaElementPlayer})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{playpauseText:mejs.i18n.t("Play/Pause")});f.extend(MediaElementPlayer.prototype,{buildplaypause:function(a,b,c,e){var d=f('<div class="mejs-button mejs-playpause-button mejs-play" ><button type="button" aria-controls="'+this.id+'" title="'+this.options.playpauseText+'" aria-label="'+this.options.playpauseText+'"></button></div>').appendTo(b).click(function(g){g.preventDefault();e.paused?e.play():e.pause();return false});e.addEventListener("play",function(){d.removeClass("mejs-play").addClass("mejs-pause")}, +false);e.addEventListener("playing",function(){d.removeClass("mejs-play").addClass("mejs-pause")},false);e.addEventListener("pause",function(){d.removeClass("mejs-pause").addClass("mejs-play")},false);e.addEventListener("paused",function(){d.removeClass("mejs-pause").addClass("mejs-play")},false)}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{stopText:"Stop"});f.extend(MediaElementPlayer.prototype,{buildstop:function(a,b,c,e){f('<div class="mejs-button mejs-stop-button mejs-stop"><button type="button" aria-controls="'+this.id+'" title="'+this.options.stopText+'" aria-label="'+this.options.stopText+'"></button></div>').appendTo(b).click(function(){e.paused||e.pause();if(e.currentTime>0){e.setCurrentTime(0);e.pause();b.find(".mejs-time-current").width("0px");b.find(".mejs-time-handle").css("left", +"0px");b.find(".mejs-time-float-current").html(mejs.Utility.secondsToTimeCode(0));b.find(".mejs-currenttime").html(mejs.Utility.secondsToTimeCode(0));c.find(".mejs-poster").show()}})}})})(mejs.$); +(function(f){f.extend(MediaElementPlayer.prototype,{buildprogress:function(a,b,c,e){f('<div class="mejs-time-rail"><span class="mejs-time-total"><span class="mejs-time-buffering"></span><span class="mejs-time-loaded"></span><span class="mejs-time-current"></span><span class="mejs-time-handle"></span><span class="mejs-time-float"><span class="mejs-time-float-current">00:00</span><span class="mejs-time-float-corner"></span></span></span></div>').appendTo(b);b.find(".mejs-time-buffering").hide();var d= +this,g=b.find(".mejs-time-total");c=b.find(".mejs-time-loaded");var k=b.find(".mejs-time-current"),j=b.find(".mejs-time-handle"),m=b.find(".mejs-time-float"),q=b.find(".mejs-time-float-current"),p=function(h){h=h.pageX;var l=g.offset(),r=g.outerWidth(true),n=0,o=n=0;if(e.duration){if(h<l.left)h=l.left;else if(h>r+l.left)h=r+l.left;o=h-l.left;n=o/r;n=n<=0.02?0:n*e.duration;t&&n!==e.currentTime&&e.setCurrentTime(n);if(!mejs.MediaFeatures.hasTouch){m.css("left",o);q.html(mejs.Utility.secondsToTimeCode(n)); +m.show()}}},t=false;g.bind("mousedown",function(h){if(h.which===1){t=true;p(h);d.globalBind("mousemove.dur",function(l){p(l)});d.globalBind("mouseup.dur",function(){t=false;m.hide();d.globalUnbind(".dur")});return false}}).bind("mouseenter",function(){d.globalBind("mousemove.dur",function(h){p(h)});mejs.MediaFeatures.hasTouch||m.show()}).bind("mouseleave",function(){if(!t){d.globalUnbind(".dur");m.hide()}});e.addEventListener("progress",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false); +e.addEventListener("timeupdate",function(h){a.setProgressRail(h);a.setCurrentRail(h)},false);d.loaded=c;d.total=g;d.current=k;d.handle=j},setProgressRail:function(a){var b=a!=undefined?a.target:this.media,c=null;if(b&&b.buffered&&b.buffered.length>0&&b.buffered.end&&b.duration)c=b.buffered.end(0)/b.duration;else if(b&&b.bytesTotal!=undefined&&b.bytesTotal>0&&b.bufferedBytes!=undefined)c=b.bufferedBytes/b.bytesTotal;else if(a&&a.lengthComputable&&a.total!=0)c=a.loaded/a.total;if(c!==null){c=Math.min(1, +Math.max(0,c));this.loaded&&this.total&&this.loaded.width(this.total.width()*c)}},setCurrentRail:function(){if(this.media.currentTime!=undefined&&this.media.duration)if(this.total&&this.handle){var a=Math.round(this.total.width()*this.media.currentTime/this.media.duration),b=a-Math.round(this.handle.outerWidth(true)/2);this.current.width(a);this.handle.css("left",b)}}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{duration:-1,timeAndDurationSeparator:" <span> / </span> "});f.extend(MediaElementPlayer.prototype,{buildcurrent:function(a,b,c,e){f('<div class="mejs-time"><span class="mejs-currenttime">'+(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00")+"</span></div>").appendTo(b);this.currenttime=this.controls.find(".mejs-currenttime");e.addEventListener("timeupdate",function(){a.updateCurrent()},false)},buildduration:function(a, +b,c,e){if(b.children().last().find(".mejs-currenttime").length>0)f(this.options.timeAndDurationSeparator+'<span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span>").appendTo(b.find(".mejs-time"));else{b.find(".mejs-currenttime").parent().addClass("mejs-currenttime-container"); +f('<div class="mejs-time mejs-duration-container"><span class="mejs-duration">'+(this.options.duration>0?mejs.Utility.secondsToTimeCode(this.options.duration,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25):(a.options.alwaysShowHours?"00:":"")+(a.options.showTimecodeFrameCount?"00:00:00":"00:00"))+"</span></div>").appendTo(b)}this.durationD=this.controls.find(".mejs-duration");e.addEventListener("timeupdate",function(){a.updateDuration()}, +false)},updateCurrent:function(){if(this.currenttime)this.currenttime.html(mejs.Utility.secondsToTimeCode(this.media.currentTime,this.options.alwaysShowHours||this.media.duration>3600,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))},updateDuration:function(){this.container.toggleClass("mejs-long-video",this.media.duration>3600);if(this.durationD&&(this.options.duration>0||this.media.duration))this.durationD.html(mejs.Utility.secondsToTimeCode(this.options.duration>0?this.options.duration: +this.media.duration,this.options.alwaysShowHours,this.options.showTimecodeFrameCount,this.options.framesPerSecond||25))}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{muteText:mejs.i18n.t("Mute Toggle"),hideVolumeOnTouchDevices:true,audioVolume:"horizontal",videoVolume:"vertical"});f.extend(MediaElementPlayer.prototype,{buildvolume:function(a,b,c,e){if(!(mejs.MediaFeatures.hasTouch&&this.options.hideVolumeOnTouchDevices)){var d=this,g=d.isVideo?d.options.videoVolume:d.options.audioVolume,k=g=="horizontal"?f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+d.id+'" title="'+d.options.muteText+ +'" aria-label="'+d.options.muteText+'"></button></div><div class="mejs-horizontal-volume-slider"><div class="mejs-horizontal-volume-total"></div><div class="mejs-horizontal-volume-current"></div><div class="mejs-horizontal-volume-handle"></div></div>').appendTo(b):f('<div class="mejs-button mejs-volume-button mejs-mute"><button type="button" aria-controls="'+d.id+'" title="'+d.options.muteText+'" aria-label="'+d.options.muteText+'"></button><div class="mejs-volume-slider"><div class="mejs-volume-total"></div><div class="mejs-volume-current"></div><div class="mejs-volume-handle"></div></div></div>').appendTo(b), +j=d.container.find(".mejs-volume-slider, .mejs-horizontal-volume-slider"),m=d.container.find(".mejs-volume-total, .mejs-horizontal-volume-total"),q=d.container.find(".mejs-volume-current, .mejs-horizontal-volume-current"),p=d.container.find(".mejs-volume-handle, .mejs-horizontal-volume-handle"),t=function(n,o){if(!j.is(":visible")&&typeof o=="undefined"){j.show();t(n,true);j.hide()}else{n=Math.max(0,n);n=Math.min(n,1);n==0?k.removeClass("mejs-mute").addClass("mejs-unmute"):k.removeClass("mejs-unmute").addClass("mejs-mute"); +if(g=="vertical"){var s=m.height(),u=m.position(),v=s-s*n;p.css("top",Math.round(u.top+v-p.height()/2));q.height(s-v);q.css("top",u.top+v)}else{s=m.width();u=m.position();s=s*n;p.css("left",Math.round(u.left+s-p.width()/2));q.width(Math.round(s))}}},h=function(n){var o=null,s=m.offset();if(g=="vertical"){o=m.height();parseInt(m.css("top").replace(/px/,""),10);o=(o-(n.pageY-s.top))/o;if(s.top==0||s.left==0)return}else{o=m.width();o=(n.pageX-s.left)/o}o=Math.max(0,o);o=Math.min(o,1);t(o);o==0?e.setMuted(true): +e.setMuted(false);e.setVolume(o)},l=false,r=false;k.hover(function(){j.show();r=true},function(){r=false;!l&&g=="vertical"&&j.hide()});j.bind("mouseover",function(){r=true}).bind("mousedown",function(n){h(n);d.globalBind("mousemove.vol",function(o){h(o)});d.globalBind("mouseup.vol",function(){l=false;d.globalUnbind(".vol");!r&&g=="vertical"&&j.hide()});l=true;return false});k.find("button").click(function(){e.setMuted(!e.muted)});e.addEventListener("volumechange",function(){if(!l)if(e.muted){t(0); +k.removeClass("mejs-mute").addClass("mejs-unmute")}else{t(e.volume);k.removeClass("mejs-unmute").addClass("mejs-mute")}},false);if(d.container.is(":visible")){t(a.options.startVolume);a.options.startVolume===0&&e.setMuted(true);e.pluginType==="native"&&e.setVolume(a.options.startVolume)}}}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{usePluginFullScreen:true,newWindowCallback:function(){return""},fullscreenText:mejs.i18n.t("Fullscreen")});f.extend(MediaElementPlayer.prototype,{isFullScreen:false,isNativeFullScreen:false,docStyleOverflow:null,isInIframe:false,buildfullscreen:function(a,b,c,e){if(a.isVideo){a.isInIframe=window.location!=window.parent.location;if(mejs.MediaFeatures.hasTrueNativeFullScreen){c=function(){if(mejs.MediaFeatures.isFullScreen()){a.isNativeFullScreen=true;a.setControlsSize()}else{a.isNativeFullScreen= +false;a.exitFullScreen()}};mejs.MediaFeatures.hasMozNativeFullScreen?a.globalBind(mejs.MediaFeatures.fullScreenEventName,c):a.container.bind(mejs.MediaFeatures.fullScreenEventName,c)}var d=this,g=f('<div class="mejs-button mejs-fullscreen-button"><button type="button" aria-controls="'+d.id+'" title="'+d.options.fullscreenText+'" aria-label="'+d.options.fullscreenText+'"></button></div>').appendTo(b);if(d.media.pluginType==="native"||!d.options.usePluginFullScreen&&!mejs.MediaFeatures.isFirefox)g.click(function(){mejs.MediaFeatures.hasTrueNativeFullScreen&& +mejs.MediaFeatures.isFullScreen()||a.isFullScreen?a.exitFullScreen():a.enterFullScreen()});else{var k=null;if(function(){var h=document.createElement("x"),l=document.documentElement,r=window.getComputedStyle;if(!("pointerEvents"in h.style))return false;h.style.pointerEvents="auto";h.style.pointerEvents="x";l.appendChild(h);r=r&&r(h,"").pointerEvents==="auto";l.removeChild(h);return!!r}()&&!mejs.MediaFeatures.isOpera){var j=false,m=function(){if(j){for(var h in q)q[h].hide();g.css("pointer-events", +"");d.controls.css("pointer-events","");d.media.removeEventListener("click",d.clickToPlayPauseCallback);j=false}},q={};b=["top","left","right","bottom"];var p,t=function(){var h=g.offset().left-d.container.offset().left,l=g.offset().top-d.container.offset().top,r=g.outerWidth(true),n=g.outerHeight(true),o=d.container.width(),s=d.container.height();for(p in q)q[p].css({position:"absolute",top:0,left:0});q.top.width(o).height(l);q.left.width(h).height(n).css({top:l});q.right.width(o-h-r).height(n).css({top:l, +left:h+r});q.bottom.width(o).height(s-n-l).css({top:l+n})};d.globalBind("resize",function(){t()});p=0;for(c=b.length;p<c;p++)q[b[p]]=f('<div class="mejs-fullscreen-hover" />').appendTo(d.container).mouseover(m).hide();g.on("mouseover",function(){if(!d.isFullScreen){var h=g.offset(),l=a.container.offset();e.positionFullscreenButton(h.left-l.left,h.top-l.top,false);g.css("pointer-events","none");d.controls.css("pointer-events","none");d.media.addEventListener("click",d.clickToPlayPauseCallback);for(p in q)q[p].show(); +t();j=true}});e.addEventListener("fullscreenchange",function(){d.isFullScreen=!d.isFullScreen;d.isFullScreen?d.media.removeEventListener("click",d.clickToPlayPauseCallback):d.media.addEventListener("click",d.clickToPlayPauseCallback);m()});d.globalBind("mousemove",function(h){if(j){var l=g.offset();if(h.pageY<l.top||h.pageY>l.top+g.outerHeight(true)||h.pageX<l.left||h.pageX>l.left+g.outerWidth(true)){g.css("pointer-events","");d.controls.css("pointer-events","");j=false}}})}else g.on("mouseover", +function(){if(k!==null){clearTimeout(k);delete k}var h=g.offset(),l=a.container.offset();e.positionFullscreenButton(h.left-l.left,h.top-l.top,true)}).on("mouseout",function(){if(k!==null){clearTimeout(k);delete k}k=setTimeout(function(){e.hideFullscreenButton()},1500)})}a.fullscreenBtn=g;d.globalBind("keydown",function(h){if((mejs.MediaFeatures.hasTrueNativeFullScreen&&mejs.MediaFeatures.isFullScreen()||d.isFullScreen)&&h.keyCode==27)a.exitFullScreen()})}},cleanfullscreen:function(a){a.exitFullScreen()}, +containerSizeTimeout:null,enterFullScreen:function(){var a=this;if(!(a.media.pluginType!=="native"&&(mejs.MediaFeatures.isFirefox||a.options.usePluginFullScreen))){docStyleOverflow=document.documentElement.style.overflow;document.documentElement.style.overflow="hidden";normalHeight=a.container.height();normalWidth=a.container.width();if(a.media.pluginType==="native")if(mejs.MediaFeatures.hasTrueNativeFullScreen){mejs.MediaFeatures.requestFullScreen(a.container[0]);a.isInIframe&&setTimeout(function c(){if(a.isNativeFullScreen)f(window).width()!== +screen.width?a.exitFullScreen():setTimeout(c,500)},500)}else if(mejs.MediaFeatures.hasSemiNativeFullScreen){a.media.webkitEnterFullscreen();return}if(a.isInIframe){var b=a.options.newWindowCallback(this);if(b!=="")if(mejs.MediaFeatures.hasTrueNativeFullScreen)setTimeout(function(){if(!a.isNativeFullScreen){a.pause();window.open(b,a.id,"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no")}},250);else{a.pause();window.open(b,a.id, +"top=0,left=0,width="+screen.availWidth+",height="+screen.availHeight+",resizable=yes,scrollbars=no,status=no,toolbar=no");return}}a.container.addClass("mejs-container-fullscreen").width("100%").height("100%");a.containerSizeTimeout=setTimeout(function(){a.container.css({width:"100%",height:"100%"});a.setControlsSize()},500);if(a.media.pluginType==="native")a.$media.width("100%").height("100%");else{a.container.find(".mejs-shim").width("100%").height("100%");a.media.setVideoSize(f(window).width(), +f(window).height())}a.layers.children("div").width("100%").height("100%");a.fullscreenBtn&&a.fullscreenBtn.removeClass("mejs-fullscreen").addClass("mejs-unfullscreen");a.setControlsSize();a.isFullScreen=true}},exitFullScreen:function(){clearTimeout(this.containerSizeTimeout);if(this.media.pluginType!=="native"&&mejs.MediaFeatures.isFirefox)this.media.setFullscreen(false);else{if(mejs.MediaFeatures.hasTrueNativeFullScreen&&(mejs.MediaFeatures.isFullScreen()||this.isFullScreen))mejs.MediaFeatures.cancelFullScreen(); +document.documentElement.style.overflow=docStyleOverflow;this.container.removeClass("mejs-container-fullscreen").width(normalWidth).height(normalHeight);if(this.media.pluginType==="native")this.$media.width(normalWidth).height(normalHeight);else{this.container.find(".mejs-shim").width(normalWidth).height(normalHeight);this.media.setVideoSize(normalWidth,normalHeight)}this.layers.children("div").width(normalWidth).height(normalHeight);this.fullscreenBtn.removeClass("mejs-unfullscreen").addClass("mejs-fullscreen"); +this.setControlsSize();this.isFullScreen=false}}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{startLanguage:"",tracksText:mejs.i18n.t("Captions/Subtitles"),hideCaptionsButtonWhenEmpty:true,toggleCaptionsButtonWhenOnlyOne:false,slidesSelector:""});f.extend(MediaElementPlayer.prototype,{hasChapters:false,buildtracks:function(a,b,c,e){if(a.tracks.length!=0){a.chapters=f('<div class="mejs-chapters mejs-layer"></div>').prependTo(c).hide();a.captions=f('<div class="mejs-captions-layer mejs-layer"><div class="mejs-captions-position mejs-captions-position-hover"><span class="mejs-captions-text"></span></div></div>').prependTo(c).hide();a.captionsText= +a.captions.find(".mejs-captions-text");a.captionsButton=f('<div class="mejs-button mejs-captions-button"><button type="button" aria-controls="'+this.id+'" title="'+this.options.tracksText+'" aria-label="'+this.options.tracksText+'"></button><div class="mejs-captions-selector"><ul><li><input type="radio" name="'+a.id+'_captions" id="'+a.id+'_captions_none" value="none" checked="checked" /><label for="'+a.id+'_captions_none">'+mejs.i18n.t("None")+"</label></li></ul></div></div>").appendTo(b);for(b= +c=0;b<a.tracks.length;b++)a.tracks[b].kind=="subtitles"&&c++;this.options.toggleCaptionsButtonWhenOnlyOne&&c==1?a.captionsButton.on("click",function(){a.setTrack(a.selectedTrack==null?a.tracks[0].srclang:"none")}):a.captionsButton.hover(function(){f(this).find(".mejs-captions-selector").css("visibility","visible")},function(){f(this).find(".mejs-captions-selector").css("visibility","hidden")}).on("click","input[type=radio]",function(){lang=this.value;a.setTrack(lang)});a.options.alwaysShowControls? +a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover"):a.container.bind("controlsshown",function(){a.container.find(".mejs-captions-position").addClass("mejs-captions-position-hover")}).bind("controlshidden",function(){e.paused||a.container.find(".mejs-captions-position").removeClass("mejs-captions-position-hover")});a.trackToLoad=-1;a.selectedTrack=null;a.isLoadingTrack=false;for(b=0;b<a.tracks.length;b++)a.tracks[b].kind=="subtitles"&&a.addTrackButton(a.tracks[b].srclang, +a.tracks[b].label);a.loadNextTrack();e.addEventListener("timeupdate",function(){a.displayCaptions()},false);if(a.options.slidesSelector!=""){a.slidesContainer=f(a.options.slidesSelector);e.addEventListener("timeupdate",function(){a.displaySlides()},false)}e.addEventListener("loadedmetadata",function(){a.displayChapters()},false);a.container.hover(function(){if(a.hasChapters){a.chapters.css("visibility","visible");a.chapters.fadeIn(200).height(a.chapters.find(".mejs-chapter").outerHeight())}},function(){a.hasChapters&& +!e.paused&&a.chapters.fadeOut(200,function(){f(this).css("visibility","hidden");f(this).css("display","block")})});a.node.getAttribute("autoplay")!==null&&a.chapters.css("visibility","hidden")}},setTrack:function(a){var b;if(a=="none"){this.selectedTrack=null;this.captionsButton.removeClass("mejs-captions-enabled")}else for(b=0;b<this.tracks.length;b++)if(this.tracks[b].srclang==a){this.selectedTrack==null&&this.captionsButton.addClass("mejs-captions-enabled");this.selectedTrack=this.tracks[b];this.captions.attr("lang", +this.selectedTrack.srclang);this.displayCaptions();break}},loadNextTrack:function(){this.trackToLoad++;if(this.trackToLoad<this.tracks.length){this.isLoadingTrack=true;this.loadTrack(this.trackToLoad)}else{this.isLoadingTrack=false;this.checkForTracks()}},loadTrack:function(a){var b=this,c=b.tracks[a];f.ajax({url:c.src,dataType:"text",success:function(e){c.entries=typeof e=="string"&&/<tt\s+xml/ig.exec(e)?mejs.TrackFormatParser.dfxp.parse(e):mejs.TrackFormatParser.webvvt.parse(e);c.isLoaded=true; +b.enableTrackButton(c.srclang,c.label);b.loadNextTrack();c.kind=="chapters"&&b.media.addEventListener("play",function(){b.media.duration>0&&b.displayChapters(c)},false);c.kind=="slides"&&b.setupSlides(c)},error:function(){b.loadNextTrack()}})},enableTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||a;this.captionsButton.find("input[value="+a+"]").prop("disabled",false).siblings("label").html(b);this.options.startLanguage==a&&f("#"+this.id+"_captions_"+a).click();this.adjustLanguageBox()}, +addTrackButton:function(a,b){if(b==="")b=mejs.language.codes[a]||a;this.captionsButton.find("ul").append(f('<li><input type="radio" name="'+this.id+'_captions" id="'+this.id+"_captions_"+a+'" value="'+a+'" disabled="disabled" /><label for="'+this.id+"_captions_"+a+'">'+b+" (loading)</label></li>"));this.adjustLanguageBox();this.container.find(".mejs-captions-translations option[value="+a+"]").remove()},adjustLanguageBox:function(){this.captionsButton.find(".mejs-captions-selector").height(this.captionsButton.find(".mejs-captions-selector ul").outerHeight(true)+ +this.captionsButton.find(".mejs-captions-translations").outerHeight(true))},checkForTracks:function(){var a=false;if(this.options.hideCaptionsButtonWhenEmpty){for(i=0;i<this.tracks.length;i++)if(this.tracks[i].kind=="subtitles"){a=true;break}if(!a){this.captionsButton.hide();this.setControlsSize()}}},displayCaptions:function(){if(typeof this.tracks!="undefined"){var a,b=this.selectedTrack;if(b!=null&&b.isLoaded)for(a=0;a<b.entries.times.length;a++)if(this.media.currentTime>=b.entries.times[a].start&& +this.media.currentTime<=b.entries.times[a].stop){this.captionsText.html(b.entries.text[a]);this.captions.show().height(0);return}this.captions.hide()}},setupSlides:function(a){this.slides=a;this.slides.entries.imgs=[this.slides.entries.text.length];this.showSlide(0)},showSlide:function(a){if(!(typeof this.tracks=="undefined"||typeof this.slidesContainer=="undefined")){var b=this,c=b.slides.entries.text[a],e=b.slides.entries.imgs[a];if(typeof e=="undefined"||typeof e.fadeIn=="undefined")b.slides.entries.imgs[a]= +e=f('<img src="'+c+'">').on("load",function(){e.appendTo(b.slidesContainer).hide().fadeIn().siblings(":visible").fadeOut()});else if(!e.is(":visible")&&!e.is(":animated")){console.log("showing existing slide");e.fadeIn().siblings(":visible").fadeOut()}}},displaySlides:function(){if(typeof this.slides!="undefined"){var a=this.slides,b;for(b=0;b<a.entries.times.length;b++)if(this.media.currentTime>=a.entries.times[b].start&&this.media.currentTime<=a.entries.times[b].stop){this.showSlide(b);break}}}, +displayChapters:function(){var a;for(a=0;a<this.tracks.length;a++)if(this.tracks[a].kind=="chapters"&&this.tracks[a].isLoaded){this.drawChapters(this.tracks[a]);this.hasChapters=true;break}},drawChapters:function(a){var b=this,c,e,d=e=0;b.chapters.empty();for(c=0;c<a.entries.times.length;c++){e=a.entries.times[c].stop-a.entries.times[c].start;e=Math.floor(e/b.media.duration*100);if(e+d>100||c==a.entries.times.length-1&&e+d<100)e=100-d;b.chapters.append(f('<div class="mejs-chapter" rel="'+a.entries.times[c].start+ +'" style="left: '+d.toString()+"%;width: "+e.toString()+'%;"><div class="mejs-chapter-block'+(c==a.entries.times.length-1?" mejs-chapter-block-last":"")+'"><span class="ch-title">'+a.entries.text[c]+'</span><span class="ch-time">'+mejs.Utility.secondsToTimeCode(a.entries.times[c].start)+"&ndash;"+mejs.Utility.secondsToTimeCode(a.entries.times[c].stop)+"</span></div></div>"));d+=e}b.chapters.find("div.mejs-chapter").click(function(){b.media.setCurrentTime(parseFloat(f(this).attr("rel")));b.media.paused&& +b.media.play()});b.chapters.show()}});mejs.language={codes:{af:"Afrikaans",sq:"Albanian",ar:"Arabic",be:"Belarusian",bg:"Bulgarian",ca:"Catalan",zh:"Chinese","zh-cn":"Chinese Simplified","zh-tw":"Chinese Traditional",hr:"Croatian",cs:"Czech",da:"Danish",nl:"Dutch",en:"English",et:"Estonian",tl:"Filipino",fi:"Finnish",fr:"French",gl:"Galician",de:"German",el:"Greek",ht:"Haitian Creole",iw:"Hebrew",hi:"Hindi",hu:"Hungarian",is:"Icelandic",id:"Indonesian",ga:"Irish",it:"Italian",ja:"Japanese",ko:"Korean", +lv:"Latvian",lt:"Lithuanian",mk:"Macedonian",ms:"Malay",mt:"Maltese",no:"Norwegian",fa:"Persian",pl:"Polish",pt:"Portuguese",ro:"Romanian",ru:"Russian",sr:"Serbian",sk:"Slovak",sl:"Slovenian",es:"Spanish",sw:"Swahili",sv:"Swedish",tl:"Tagalog",th:"Thai",tr:"Turkish",uk:"Ukrainian",vi:"Vietnamese",cy:"Welsh",yi:"Yiddish"}};mejs.TrackFormatParser={webvvt:{pattern_identifier:/^([a-zA-z]+-)?[0-9]+$/,pattern_timecode:/^([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{1,3})?) --\> ([0-9]{2}:[0-9]{2}:[0-9]{2}([,.][0-9]{3})?)(.*)$/, +parse:function(a){var b=0;a=mejs.TrackFormatParser.split2(a,/\r?\n/);for(var c={text:[],times:[]},e,d;b<a.length;b++)if(this.pattern_identifier.exec(a[b])){b++;if((e=this.pattern_timecode.exec(a[b]))&&b<a.length){b++;d=a[b];for(b++;a[b]!==""&&b<a.length;){d=d+"\n"+a[b];b++}d=f.trim(d).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig,"<a href='$1' target='_blank'>$1</a>");c.text.push(d);c.times.push({start:mejs.Utility.convertSMPTEtoSeconds(e[1])==0?0.2:mejs.Utility.convertSMPTEtoSeconds(e[1]), +stop:mejs.Utility.convertSMPTEtoSeconds(e[3]),settings:e[5]})}}return c}},dfxp:{parse:function(a){a=f(a).filter("tt");var b=0;b=a.children("div").eq(0);var c=b.find("p");b=a.find("#"+b.attr("style"));var e,d;a={text:[],times:[]};if(b.length){d=b.removeAttr("id").get(0).attributes;if(d.length){e={};for(b=0;b<d.length;b++)e[d[b].name.split(":")[1]]=d[b].value}}for(b=0;b<c.length;b++){var g;d={start:null,stop:null,style:null};if(c.eq(b).attr("begin"))d.start=mejs.Utility.convertSMPTEtoSeconds(c.eq(b).attr("begin")); +if(!d.start&&c.eq(b-1).attr("end"))d.start=mejs.Utility.convertSMPTEtoSeconds(c.eq(b-1).attr("end"));if(c.eq(b).attr("end"))d.stop=mejs.Utility.convertSMPTEtoSeconds(c.eq(b).attr("end"));if(!d.stop&&c.eq(b+1).attr("begin"))d.stop=mejs.Utility.convertSMPTEtoSeconds(c.eq(b+1).attr("begin"));if(e){g="";for(var k in e)g+=k+":"+e[k]+";"}if(g)d.style=g;if(d.start==0)d.start=0.2;a.times.push(d);d=f.trim(c.eq(b).html()).replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig, +"<a href='$1' target='_blank'>$1</a>");a.text.push(d);if(a.times.start==0)a.times.start=2}return a}},split2:function(a,b){return a.split(b)}};if("x\n\ny".split(/\n/gi).length!=3)mejs.TrackFormatParser.split2=function(a,b){var c=[],e="",d;for(d=0;d<a.length;d++){e+=a.substring(d,d+1);if(b.test(e)){c.push(e.replace(b,""));e=""}}c.push(e);return c}})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{contextMenuItems:[{render:function(a){if(typeof a.enterFullScreen=="undefined")return null;return a.isFullScreen?mejs.i18n.t("Turn off Fullscreen"):mejs.i18n.t("Go Fullscreen")},click:function(a){a.isFullScreen?a.exitFullScreen():a.enterFullScreen()}},{render:function(a){return a.media.muted?mejs.i18n.t("Unmute"):mejs.i18n.t("Mute")},click:function(a){a.media.muted?a.setMuted(false):a.setMuted(true)}},{isSeparator:true},{render:function(){return mejs.i18n.t("Download Video")}, +click:function(a){window.location.href=a.media.currentSrc}}]});f.extend(MediaElementPlayer.prototype,{buildcontextmenu:function(a){a.contextMenu=f('<div class="mejs-contextmenu"></div>').appendTo(f("body")).hide();a.container.bind("contextmenu",function(b){if(a.isContextMenuEnabled){b.preventDefault();a.renderContextMenu(b.clientX-1,b.clientY-1);return false}});a.container.bind("click",function(){a.contextMenu.hide()});a.contextMenu.bind("mouseleave",function(){a.startContextMenuTimer()})},cleancontextmenu:function(a){a.contextMenu.remove()}, +isContextMenuEnabled:true,enableContextMenu:function(){this.isContextMenuEnabled=true},disableContextMenu:function(){this.isContextMenuEnabled=false},contextMenuTimeout:null,startContextMenuTimer:function(){var a=this;a.killContextMenuTimer();a.contextMenuTimer=setTimeout(function(){a.hideContextMenu();a.killContextMenuTimer()},750)},killContextMenuTimer:function(){var a=this.contextMenuTimer;if(a!=null){clearTimeout(a);delete a}},hideContextMenu:function(){this.contextMenu.hide()},renderContextMenu:function(a, +b){for(var c=this,e="",d=c.options.contextMenuItems,g=0,k=d.length;g<k;g++)if(d[g].isSeparator)e+='<div class="mejs-contextmenu-separator"></div>';else{var j=d[g].render(c);if(j!=null)e+='<div class="mejs-contextmenu-item" data-itemindex="'+g+'" id="element-'+Math.random()*1E6+'">'+j+"</div>"}c.contextMenu.empty().append(f(e)).css({top:b,left:a}).show();c.contextMenu.find(".mejs-contextmenu-item").each(function(){var m=f(this),q=parseInt(m.data("itemindex"),10),p=c.options.contextMenuItems[q];typeof p.show!= +"undefined"&&p.show(m,c);m.click(function(){typeof p.click!="undefined"&&p.click(c);c.contextMenu.hide()})});setTimeout(function(){c.killControlsTimer("rev3")},100)}})})(mejs.$); +(function(f){f.extend(mejs.MepDefaults,{postrollCloseText:mejs.i18n.t("Close")});f.extend(MediaElementPlayer.prototype,{buildpostroll:function(a,b,c){var e=this.container.find('link[rel="postroll"]').attr("href");if(typeof e!=="undefined"){a.postroll=f('<div class="mejs-postroll-layer mejs-layer"><a class="mejs-postroll-close" onclick="$(this).parent().hide();return false;">'+this.options.postrollCloseText+'</a><div class="mejs-postroll-layer-content"></div></div>').prependTo(c).hide();this.media.addEventListener("ended", +function(){f.ajax({dataType:"html",url:e,success:function(d){c.find(".mejs-postroll-layer-content").html(d)}});a.postroll.show()},false)}}})})(mejs.$); diff --git a/src/static/mediaelement/mejs-skins.css b/src/static/mediaelement/mejs-skins.css new file mode 100755 index 0000000..814b9d4 --- /dev/null +++ b/src/static/mediaelement/mejs-skins.css @@ -0,0 +1,283 @@ +/* TED player */ +.mejs-container.mejs-ted { + +} +.mejs-ted .mejs-controls { + background: #eee; + height: 65px; +} + +.mejs-ted .mejs-button, +.mejs-ted .mejs-time { + position: absolute; + background: #ddd; +} +.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-total { + background-color: none; + background: url(controls-ted.png) repeat-x 0 -52px; + height: 6px; +} +.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-loaded { + background-color: none; + background: url(controls-ted.png) repeat-x 0 -52px; + width: 0; + height: 6px; +} +.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-current { + width: 0; + height: 6px; + background-color: none; + background: url(controls-ted.png) repeat-x 0 -59px; +} +.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-handle { + display: block; + margin: 0; + width: 14px; + height: 21px; + top: -7px; + border: 0; + background: url(controls-ted.png) no-repeat 0 0; +} +.mejs-ted .mejs-controls .mejs-time-rail .mejs-time-float { + display: none; +} +.mejs-ted .mejs-controls .mejs-playpause-button { + top: 29px; + left: 9px; + width: 49px; + height: 28px; +} +.mejs-ted .mejs-controls .mejs-playpause-button button { + width: 49px; + height: 28px; + background: url(controls-ted.png) no-repeat -50px -23px; + margin: 0; + padding: 0; +} +.mejs-ted .mejs-controls .mejs-pause button { + background-position: 0 -23px; +} + +.mejs-ted .mejs-controls .mejs-fullscreen-button { + top: 34px; + right: 9px; + width: 17px; + height: 15px; + background : none; +} +.mejs-ted .mejs-controls .mejs-fullscreen-button button { + width: 19px; + height: 17px; + background: transparent url(controls-ted.png) no-repeat 0 -66px; + margin: 0; + padding: 0; +} +.mejs-ted .mejs-controls .mejs-unfullscreen button { + background: transparent url(controls-ted.png) no-repeat -21px -66px; + margin: 0; + padding: 0; +} +.mejs-ted .mejs-controls .mejs-volume-button { + top: 30px; + right: 35px; + width: 24px; + height: 22px; +} +.mejs-ted .mejs-controls .mejs-mute button { + background: url(controls-ted.png) no-repeat -15px 0; + width: 24px; + height: 22px; + margin: 0; + padding: 0; +} +.mejs-ted .mejs-controls .mejs-unmute button { + background: url(controls-ted.png) no-repeat -40px 0; + width: 24px; + height: 22px; + margin: 0; + padding: 0; +} +.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-slider { + background: #fff; + border: solid 1px #aaa; + border-width: 1px 1px 0 1px; + width: 22px; + height: 65px; + top: -65px; +} +.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-total { + background: url(controls-ted.png) repeat-y -41px -66px; + left: 8px; + width: 6px; + height: 50px; +} +.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-current { + left: 8px; + width: 6px; + background: url(controls-ted.png) repeat-y -48px -66px; + height: 50px; +} + +.mejs-ted .mejs-controls .mejs-volume-button .mejs-volume-handle { + display: none; +} + +.mejs-ted .mejs-controls .mejs-time span { + color: #333; +} +.mejs-ted .mejs-controls .mejs-currenttime-container { + position: absolute; + top: 32px; + right: 100px; + border: solid 1px #999; + background: #fff; + color: #333; + padding-top: 2px; + border-radius: 3px; + color: #333; +} +.mejs-ted .mejs-controls .mejs-duration-container { + + position: absolute; + top: 32px; + right: 65px; + border: solid 1px #999; + background: #fff; + color: #333; + padding-top: 2px; + border-radius: 3px; + color: #333; +} + +.mejs-ted .mejs-controls .mejs-time button{ + color: #333; +} +.mejs-ted .mejs-controls .mejs-captions-button { + display: none; +} +/* END: TED player */ + + +/* WMP player */ +.mejs-container.mejs-wmp { + +} +.mejs-wmp .mejs-controls { + background: transparent url(controls-wmp-bg.png) center 16px no-repeat; + height: 65px; +} + +.mejs-wmp .mejs-button, +.mejs-wmp .mejs-time { + position: absolute; + background: transparent; +} +.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-total { + background-color: transparent; + border: solid 1px #ccc; + height: 3px; +} +.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-loaded { + background-color: rgba(255,255,255,0.3); + width: 0; + height: 3px; +} +.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-current { + width: 0; + height: 1px; + background-color: #014CB6; + border: solid 1px #7FC9FA; + border-width: 1px 0; + border-color: #7FC9FA #fff #619FF2 #fff; +} +.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-handle { + display: block; + margin: 0; + width: 16px; + height: 9px; + top: -3px; + border: 0; + background: url(controls-wmp.png) no-repeat 0 -80px; +} +.mejs-wmp .mejs-controls .mejs-time-rail .mejs-time-float { + display: none; +} +.mejs-wmp .mejs-controls .mejs-playpause-button { + top: 10px; + left: 50%; + margin: 10px 0 0 -20px; + width: 40px; + height: 40px; + +} +.mejs-wmp .mejs-controls .mejs-playpause-button button { + width: 40px; + height: 40px; + background: url(controls-wmp.png) no-repeat 0 0; + margin: 0; + padding: 0; +} +.mejs-wmp .mejs-controls .mejs-pause button { + background-position: 0 -40px; +} + +.mejs-wmp .mejs-controls .mejs-currenttime-container { + position: absolute; + top: 25px; + left: 50%; + margin-left: -93px; +} +.mejs-wmp .mejs-controls .mejs-duration-container { + position: absolute; + top: 25px; + left: 50%; + margin-left: -58px; +} + + +.mejs-wmp .mejs-controls .mejs-volume-button { + top: 32px; + right: 50%; + margin-right: -55px; + width: 20px; + height: 15px; +} +.mejs-wmp .mejs-controls .mejs-volume-button button { + margin: 0; + padding: 0; + background: url(controls-wmp.png) no-repeat -42px -17px; + width: 20px; + height: 15px; +} +.mejs-wmp .mejs-controls .mejs-unmute button { + margin: 0; + padding: 0; + background: url(controls-wmp.png) no-repeat -42px 0; + width: 20px; + height: 15px; +} +.mejs-wmp .mejs-controls .mejs-volume-button .mejs-volume-slider { + background: rgba(102,102,102,0.6); +} + +.mejs-wmp .mejs-controls .mejs-fullscreen-button { + top: 32px; + right: 50%; + margin-right: -82px; + width: 15px; + height: 14px; +} +.mejs-wmp .mejs-controls .mejs-fullscreen-button button { + margin: 0; + padding: 0; + background: url(controls-wmp.png) no-repeat -63px 0; + width: 15px; + height: 14px; +} +.mejs-wmp .mejs-controls .mejs-captions-button { + display: none; +} +/* END: WMP player */ + + + diff --git a/src/static/mediaelement/silverlightmediaelement.xap b/src/static/mediaelement/silverlightmediaelement.xap new file mode 100755 index 0000000000000000000000000000000000000000..9d55c2e46ae51017ab91f61b05cf4f4838ab10ab GIT binary patch literal 12461 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 Y;npiigG2o9V37YT{69ou_}||D0@79*!2kdN literal 0 HcmV?d00001 diff --git a/src/static/movio/assets/img/loader_white.gif b/src/static/movio/assets/img/loader_white.gif new file mode 100644 index 0000000000000000000000000000000000000000..3288d1035d70bb86517e2c233f1a904e41f06b29 GIT binary patch literal 3208 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 Bt<?Yk literal 0 HcmV?d00001 diff --git a/src/static/movio/js/movio.js b/src/static/movio/js/movio.js new file mode 100755 index 0000000..1213cfe --- /dev/null +++ b/src/static/movio/js/movio.js @@ -0,0 +1,173 @@ +var Movio = { + init: function() { + Movio.initImageSlider('.js-imageList'); + Movio.initTooltip(); + Movio.initThesaurus(); + Movio.fixPlaceholderInOldBrowser(); + Movio.fixVideoResize(); + }, + + initImageSlider: function(sel) { + $(sel+' .slide').each( + function(index) { + $(this).css( "z-index", -index*2+2 ); + } + ); + + var funInitSlick = function(sel) { + $(sel).slick({ + dots: false, + infinite: false, + speed: 700, + slidesToShow: 6, + slidesToScroll: 1, + responsive: [{ + breakpoint: 1024, + settings: { + slidesToShow: 3, + slidesToScroll: 1, + infinite: true, + dots: false + } + }, { + breakpoint: 600, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + }, { + breakpoint: 480, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + }] + }); + }; + + var $sel = $(sel), + $collapse = $sel.closest('div.collapse'); + + if ($collapse.length==0 || $collapse.hasClass('in')) { + funInitSlick(sel); + } else { + $collapse.on('show.bs.collapse', function () { + $collapse.off('show.bs.collapse'); + $(sel).css({'height': '10px', 'overflow': 'hidden'}); + setTimeout(function(){ + funInitSlick(sel); + $(sel).css({'height': 'auto', 'overflow': 'auto'}); + }, 50) + }) + } + }, + + initTooltip: function() { + $("[rel='tooltip']").tooltip(); + $('#element').tooltip('show') + }, + + initThesaurus: function() { + $('a.js-thesaurus').click(function(e){ + e.preventDefault(); + e.stopPropagation(); + + // show popup + var $el = $(this), + $body = $('body'), + offset = $el.position(), + popup = $('.js-thesaurus-popup'), + popupTitle = $('.js-thesaurus-title'), + popupResult = $('.js-thesaurus-result'); + + popupTitle.html($el.html()); + popupResult.html('loading ...'); + popup.css({ position: 'absolute', + 'z-index': 2000, + top: offset.top + 30, + left: offset.left - popup.width() + 30 + ($el.width()/2)}); + popup.fadeIn(); + $body.animate({scrollTop: $body.scrollTop() + $el.offset().top - 10}, 400); + + var clickHandler = function() { + popup.fadeOut(); + $(document).unbind('click', clickHandler); + } + $(document).bind('click', clickHandler); + + $.ajax({ + url: Glizy.ajaxUrl+$el.data('url'), + success: function(data) { + popupResult.html(data); + } + }); + + }); + }, + + fixPlaceholderInOldBrowser: function() { + if($.browser.msie){ + $('input[placeholder]').each(function(){ + + var input = $(this); + + $(input).val(input.attr('placeholder')); + + $(input).focus(function(){ + if (input.val() == input.attr('placeholder')) { + input.val(''); + } + }); + + $(input).blur(function(){ + if (input.val() == '' || input.val() == input.attr('placeholder')) { + input.val(input.attr('placeholder')); + } + }); + }); + }; + }, + + fixVideoResize: function() { + $(window).load(function(){ + // VIDEO YOUTUBE LIQUID + // Find all YouTube videos + var $allVideos = $(".item-box iframe[src^='http://www.youtube.com']"), + + // The element that is fluid width + $fluidEl = $(".item-box"); + + // Figure out and save aspect ratio for each video + $allVideos.each(function() { + + $(this) + .data('aspectRatio', this.height / this.width) + + // and remove the hard coded width/height + .removeAttr('height') + .removeAttr('width'); + + }); + + // When the window is resized + // (You'll probably want to debounce this) + $(window).resize(function() { + + var newWidth = $fluidEl.width(); + + // Resize all videos according to their own aspect ratio + $allVideos.each(function() { + + var $el = $(this); + $el + .width(newWidth) + .height(newWidth * $el.data('aspectRatio')); + + }); + + // Kick off one resize to fix all videos on page load + }).resize(); + + }); + } +}; \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/AttachmentsList.html b/src/static/movio/templates/Default/skins/AttachmentsList.html new file mode 100644 index 0000000..5d49b4c --- /dev/null +++ b/src/static/movio/templates/Default/skins/AttachmentsList.html @@ -0,0 +1,3 @@ +<span tal:omit-tag="" + metal:use-macro="_macro.html/boxAttachments" + tal:define="attaches Component" /> diff --git a/src/static/movio/templates/Default/skins/BoxList.html b/src/static/movio/templates/Default/skins/BoxList.html new file mode 100644 index 0000000..5d53da6 --- /dev/null +++ b/src/static/movio/templates/Default/skins/BoxList.html @@ -0,0 +1,43 @@ +<span tal:omit-tag="" tal:repeat="item Component"> + <div class="content-box row-fluid "> + <span tal:omit-tag="" tal:repeat="subitem item"> + <span tal:omit-tag="" tal:condition="php: subitem.type == 'imageText'"> + <article tal:attributes="style subitem/style; class php: 'box height-rid col-md-' . subitem.width"> + <h1><a tal:attributes="href subitem/pageId" tal:content="subitem/title"></a> <a tal:attributes="href subitem/pageId"><i class="ico-box fa fa-arrow-right"></i></a></h1> + <div class="container"> + <a tal:attributes="href subitem/pageId" tal:content="structure subitem/image/__html__"></a> + <span tal:omit-tag="" tal:content="structure subitem/text" /> + </div> + </article> + </span> + + <span tal:omit-tag="" tal:condition="php: subitem.type == 'imageLink'"> + <article tal:attributes="style subitem/style; class php: 'box height-rid col-md-' . subitem.width"> + <h1><a tal:attributes="href subitem/pageId" tal:content="subitem/title"></a> <a tal:attributes="href subitem/pageId"><i class="ico-box fa fa-arrow-right"></i></a></h1> + <div class="container"> + <a tal:attributes="href subitem/pageId" tal:content="structure subitem/image/__html__"></a> + <a tal:attributes="href subitem/pageId" class="link-to-reserv"><span tal:omit-tag="" tal:content="subitem/linkTitle" /><span></span></a> + </div> + </article> + </span> + + <span tal:omit-tag="" tal:condition="php: subitem.type == 'timeline'"> + <article tal:attributes="style subitem/style; class php: 'box height-rid col-md-' . subitem.width"> + <h1><a tal:attributes="href subitem/pageId" tal:content="subitem/title"></a> <a tal:attributes="href subitem/pageId"><i class="ico-box fa fa-arrow-right"></i></a></h1> + <div class="container"> + + </div> + </article> + </span> + + <span tal:omit-tag="" tal:condition="php: subitem.type == 'text'"> + <article tal:attributes="style subitem/style; class php: 'box height-rid col-md-' . subitem.width"> + <h1><a tal:attributes="href subitem/pageId" tal:content="subitem/title"></a> <a tal:attributes="href subitem/pageId"><i class="ico-box fa fa-arrow-right"></i></a></h1> + <div class="container"> + + </div> + </article> + </span> + </span> + </div> +</span> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/BoxSearch.html b/src/static/movio/templates/Default/skins/BoxSearch.html new file mode 100644 index 0000000..0f134a5 --- /dev/null +++ b/src/static/movio/templates/Default/skins/BoxSearch.html @@ -0,0 +1,6 @@ +<form method="get" tal:attributes="action SearchBox/__url__" class="top-search"> +<p> +<label tal:content="SearchBox/label"></label><input type="text" name="search" tal:attributes="placeholder php:__T('GLZ_SEARCH')" /> +<input type="submit" class="button" name="" tal:attributes="value php:__T('GLZ_SEARCH')" /> +</p> +</form> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/BoxSidebar.html b/src/static/movio/templates/Default/skins/BoxSidebar.html new file mode 100644 index 0000000..d5301c2 --- /dev/null +++ b/src/static/movio/templates/Default/skins/BoxSidebar.html @@ -0,0 +1,34 @@ +<span tal:omit-tag="" tal:repeat="item Component"> + <div class="content-box row-fluid "> + <span tal:omit-tag="" tal:repeat="subitem item"> + <span tal:omit-tag="" tal:condition="php: subitem.type == 'imageText'"> + <article class="box"> + <h1><a tal:attributes="href subitem/pageId" tal:content="subitem/title"></a> <i class="ico arrow-dx"></i></h1> + <div class="container"> + <a tal:attributes="href subitem/pageId" tal:content="structure subitem/image/__html__"></a> + <span tal:omit-tag="" tal:content="structure subitem/text" /> + </div> + </article> + </span> + + <span tal:omit-tag="" tal:condition="php: subitem.type == 'imageLink'"> + <article class="box"> + <h1><a tal:attributes="href subitem/pageId" tal:content="subitem/title"></a> <i class="ico arrow-dx"></i></h1> + <div class="container"> + <a tal:attributes="href subitem/pageId" tal:content="structure subitem/image/__html__"></a> + <a tal:attributes="href subitem/pageId" class="link-to-reserv"><span tal:omit-tag="" tal:content="subitem/linkTitle" /><span></span></a> + </div> + </article> + </span> + + <span tal:omit-tag="" tal:condition="php: subitem.type == 'text'"> + <article class="box"> + <h1><a tal:attributes="href subitem/pageId" tal:content="subitem/title"></a> <i class="ico arrow-dx"></i></h1> + <div class="container"> + <span tal:omit-tag="" tal:content="structure subitem/text" /> + </div> + </article> + </span> + </span> + </div> +</span> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/Cover.html b/src/static/movio/templates/Default/skins/Cover.html new file mode 100644 index 0000000..91074c5 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Cover.html @@ -0,0 +1,10 @@ +<div tal:attributes="style php:(Component['width'] ? 'margin: auto;; width: ' . Component['width'] . 'px;;' : '') . (Component['margin'] ? 'margin-top: ' . Component['margin'] . 'px;;' : '')"> + <span tal:omit-tag="" tal:content="structure Component/text" /> + <div class="clearfix" tal:condition="php: Component['image']['mediaId'] > 0"> + <a tal:attributes="href Component/pageId"> + <span tal:omit-tag="" tal:content="structure Component/image/__html__" /> + </a> + </div> + <span tal:omit-tag="" tal:content="structure Component/textAfter" /> +</div> + diff --git a/src/static/movio/templates/Default/skins/DictionaryList.html b/src/static/movio/templates/Default/skins/DictionaryList.html new file mode 100644 index 0000000..ba45f8a --- /dev/null +++ b/src/static/movio/templates/Default/skins/DictionaryList.html @@ -0,0 +1,89 @@ +<div tal:condition="php: count(Component['records']) GT 0"> + <span tal:omit-tag="" tal:condition="php: Component['type'] == 'generic'"> + <section class="results-content" tal:repeat="item Component/records"> + <span tal:omit-tag="" tal:condition="php: !empty(item['taggedDocuments'])"> + <h2 tal:content="item/term/term" style="margin-bottom: 20px"/> + <article class="item clearfix" tal:repeat="subitem item/taggedDocuments" style="margin-left: 20px"> + <h1> + <a tal:attributes="href subitem/url; title subitem/title" tal:content="structure subitem/title"></a> + </h1> + <p tal:condition="subitem/description" tal:content="structure subitem/description" /> + </article> + </span> + </section> + </span> + + <span tal:omit-tag="" tal:condition="php: Component['type'] == 'geographical'"> + <div id="googlemap" class="google-maps" style="width: 100%; height: 600px"></div> + <script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script> + <script> + jQuery( function(){ + var geo = {lat: "41.872389", long: '12.4801', zoom: 5}; + var terms = <span tal:omit-tag="" tal:content="structure Component/records" />; + var geocoder; + var map; + var infowindow = new google.maps.InfoWindow(); + + var latlng = new google.maps.LatLng(geo.lat, geo.long); + var mapOptions = { + mapTypeId: google.maps.MapTypeId.ROADMAP + } + var map = new google.maps.Map(document.getElementById("googlemap"), mapOptions); + + var latlngbounds = new google.maps.LatLngBounds(); + $(terms).each(function(i, item) { + var term = item.term; + var geoTerm = term.geo.split(','); + if ( $.isNumeric(geoTerm[0]) + '&&' + $.isNumeric(geoTerm[1]) ) { + var ll = new google.maps.LatLng(geoTerm[0], geoTerm[1]); + var m = new google.maps.Marker({ + map: map, + position: ll, + title: term.term + }); + latlngbounds.extend(ll); + } + + var content = '<h4>'+term.term+'</h4>'; + $(item.taggedDocuments).each(function(i, document) { + content += '<li><a href="'+document.url+'">'+document.title+'</a></li>'; + }); + makeInfoWindowEvent(map, infowindow, content, m); + }); + map.setCenter(latlngbounds.getCenter()); + map.fitBounds(latlngbounds); + + function makeInfoWindowEvent(map, infowindow, contentString, marker) { + google.maps.event.addListener(marker, 'click', function() { + infowindow.setContent(contentString); + infowindow.open(map, marker); + }); + } + }) + </script> + </span> + + <span tal:omit-tag="" tal:condition="php: Component['type'] == 'chronologic'"> + <div id="timeline-embed"></div> + <script> + var embed_path = 'static/timelinejs/'; + var timeline_config = { + width: '100%', + height: '600', + source: '<span tal:omit-tag="" tal:content="structure Component/source" />', + embed_id: 'timeline-embed', + font: '<span tal:omit-tag="" tal:content="structure Component/font" />', + hash_bookmark: false, + debug: false, + lang: '<span tal:omit-tag="" tal:content="structure Component/lang" />', + css: 'static/timelinejs/css/timeline.css', + js: 'static/timelinejs/js/timeline-min.js' + } + </script> + <script src="static/timelinejs/js/storyjs-embed.js"></script> + </span> + +</div> +<span tal:omit-tag="" tal:condition="php: count(Component['records'])==0"> + <p tal:content="php:__Tp('MW_NO_RECORD_FOUND')"></p> +</span> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/DigitalExhibition.html b/src/static/movio/templates/Default/skins/DigitalExhibition.html new file mode 100644 index 0000000..3e51e58 --- /dev/null +++ b/src/static/movio/templates/Default/skins/DigitalExhibition.html @@ -0,0 +1,99 @@ +<div class="clearfix"> + <figure class="main-img align-right" tal:condition="php: Component['banner']['mediaId'] > 0"> + <span tal:omit-tag="" tal:content="structure Component/banner/__html__" /> + <figcaption class="description" tal:content="structure Component/banner/title"></figcaption> + </figure> + <dl class="properties"> + <span tal:omit-tag="" tal:condition="Component/targetUser"> + <dt tal:content="php: __T('Users')"></dt> + <dd tal:content="Component/targetUser"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/date"> + <dt tal:content="php: __Tp('Creation date')"></dt> + <dd tal:content="Component/date"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/language"> + <dt tal:content="php: __T('Language')"></dt> + <dd tal:content="Component/language"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/urlExternal"> + <dt tal:content="php: __T('Exhibition url')"></dt> + <dd tal:content="structure php: __Link::formatLink(Component['urlExternal'])"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/identifier"> + <dt tal:content="php: __T('Identifier')"></dt> + <dd tal:content="Component/identifier"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/category"> + <dt tal:content="php: __T('Subject')"></dt> + <dd tal:content="Component/category"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/linkedExhibition"> + <dt tal:content="php: __T('Physycal alternative')"></dt> + <dd tal:content="structure php: __Link::formatLink(Component['linkedExhibition'])"></dd> + </span> + </dl> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['description'])"> + <h3 tal:content="structure php: __T('Abstract')" /> + <span tal:omit-tag="" tal:content="structure Component/description" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['credits'])"> + <h3 tal:content="structure php: __T('Credits')" /> + <span tal:omit-tag="" tal:content="structure Component/credits" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['sponsor1'])"> + <h3 tal:content="structure php: __T('Patronages')" /> + <span tal:omit-tag="" tal:content="structure Component/sponsor1" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['sponsor2'])"> + <h3 tal:content="structure php: __T('Promoters')" /> + <span tal:omit-tag="" tal:content="structure Component/sponsor2" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['sponsor3'])"> + <h3 tal:content="structure php: __T('Sponsors')" /> + <span tal:omit-tag="" tal:content="structure Component/sponsor3" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['honoraryCommittee'])"> + <h3 tal:content="structure php: __T('Committee of Honor')" /> + <span tal:omit-tag="" tal:content="structure Component/honoraryCommittee" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['scientificCommittee'])"> + <h3 tal:content="structure php: __T('Scientific Committee')" /> + <span tal:omit-tag="" tal:content="structure Component/scientificCommittee" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['dedication'])"> + <h3 tal:content="structure php: __T('Dedication')" /> + <span tal:omit-tag="" tal:content="structure Component/dedication" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['aknowledgements'])"> + <h3 tal:content="structure php: __T('Aknowledgements')" /> + <span tal:omit-tag="" tal:content="structure Component/aknowledgements" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['contacts'])"> + <h3 tal:content="structure php: __T('Contacts')" /> + <span tal:omit-tag="" tal:content="structure Component/contacts" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['services'])"> + <h3 tal:content="structure php: __T('Services')" /> + <span tal:omit-tag="" tal:content="structure Component/services" /> + </span> + <div class="content-box row-fluid clearfix" tal:condition="php: Component['video']['mediaId'] > 0"> + <h3 tal:content="php: __T('Presentation video')" /> + <script> +$(function(){ + jQuery('video,audio').mediaelementplayer(); +}); + </script> + <video tal:attributes="src Component/video/src;"/> + </div> + + <span tal:omit-tag="" + metal:use-macro="_macro.html/boxImageList" + tal:define="images Component/images; + start '0'; + title php: __T('Images')" /> + + <span tal:omit-tag="" + metal:use-macro="_macro.html/boxAttachments" + tal:define="attaches Component/attaches" /> +</div> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/Entity_entry.html b/src/static/movio/templates/Default/skins/Entity_entry.html new file mode 100644 index 0000000..14bdce3 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Entity_entry.html @@ -0,0 +1,99 @@ +<div class="clearfix"> + <div class="col-md-5 block-inner-aside pull-right col-xs-12"> + <span tal:omit-tag="" tal:condition="php: count(Component['attributes'].properties)"> + <dl class="new-properties new-dl clearfix"> + <span tal:omit-tag="" tal:repeat="attribute Component/attributes/properties"> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'property'"> + <span tal:omit-tag="" tal:condition="php: Component[attribute['name']] != ''"> + <dt tal:condition="php: attribute['label']" tal:content="php: attribute['label']"></dt> + <dd tal:content="structure php:Component[attribute['name']]"></dd> + </span> + </span> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'date'"> + <span tal:omit-tag="" tal:condition="php: Component[attribute['name']] != ''"> + <dt tal:condition="php: attribute['label']" tal:content="php: attribute['label']"></dt> + <dd tal:content="php:glz_defaultDate2locale( __T('GLZ_DATE_FORMAT'), Component[attribute['name']])"></dd> + </span> + </span> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'thesaurus'"> + <span tal:omit-tag="" tal:condition="php: count(Component[attribute['name']])"> + <dt tal:condition="php: attribute['label']" tal:content="php: attribute['label']"></dt> + <dd> + <ul class="tag-list"> + <li tal:repeat="item php:Component[attribute['name']]"><a href="#" class="js-thesaurus" tal:attributes="data-url item/url; title item/title; data-type item/type" tal:content="structure item/title"></a>&nbsp;</li> + </ul> + </dd> + </span> + </span> + + </span> + </dl> + </span> + + <span tal:omit-tag="" tal:repeat="attribute Component/attributes/figure"> + <figure class="main-img align-right clearfix" tal:condition="php: Component[attribute['name']]['mediaId']"> + <span tal:omit-tag="" tal:content="structure php:Component[attribute['name']]['__html__']" /> + <figcaption class="description" tal:attributes="style php: 'max-width:' . Component[attribute['name']]['width'] . 'px'" tal:content="structure php:Component[attribute['name']]['title']"></figcaption> + </figure> + </span> + + <div style="width:490px;display:none" class="block-my-pop-up js-thesaurus-popup"> + <div style="top:0;right:0;margin:-15px 15px 0 0;" class="arrow"></div> + <h2 class="block-title js-thesaurus-title"></h2> + <div class="block-my-pop-up-container js-thesaurus-result" style="height: 400px;overflow:auto;"> + <div class="results-content"></div> + </div> + </div> + </div> + + <span tal:omit-tag="" tal:condition="php: count(Component['attributes'].body)"> + <span tal:omit-tag="" tal:repeat="attribute Component/attributes/body"> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'longtext'"> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component[attribute['name']])"> + <h3 tal:condition="php: attribute['label']" tal:content="php: attribute['label']" /> + <span tal:omit-tag="" tal:content="structure php:Component[attribute['name']]" /> + </span> + </span> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'imagelist'"> + <span tal:omit-tag="" tal:condition="php: count(Component[attribute['name']]['content'])"> + <div class="clearfix-left clearfix-right"> + <h3 tal:condition="php: attribute['label']" tal:content="php: attribute['label']" /> + <div class="slider imageList clearfix js-imageList"> + <div class="slide" tal:repeat="item php:Component[attribute['name']]['content']" tal:content="structure item/__html__" /> + </div> + </div> + </span> + </span> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'media'"> + <span tal:omit-tag="" tal:condition="php: Component[attribute['name']]['__html__'] != ''"> + <h3 tal:condition="php: attribute['label']" tal:content="php: attribute['label']" /> + <span tal:omit-tag="" tal:content="structure php:Component[attribute['name']]['__html__']" /> + </span> + </span> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'medialist'"> + <span tal:omit-tag="" tal:condition="php: count(Component[attribute['name']]['content'])"> + <h3 tal:condition="php: attribute['label']" tal:content="php: attribute['label']" /> + <ul class="downloadList"> + <li tal:repeat="item php:Component[attribute['name']]['content']" tal:content="structure item/__html__" /> + </ul> + </span> + </span> + + </span> + </span> + + <span tal:condition="php: property_exists(Component['relations'], 'photogallery')" tal:content="structure Component/relations/photogallery" /> + <span tal:condition="php: property_exists(Component['relations'], 'europeanaRelatedContents')" tal:content="structure Component/relations/europeanaRelatedContents" /> + <span tal:condition="php: property_exists(Component['relations'], 'relations')" tal:content="structure Component/relations/relations" /> + <span tal:condition="php: property_exists(Component['relations'], 'referenceRelations')" tal:content="structure Component/relations/referenceRelations" /> + <span tal:condition="php: property_exists(Component['relations'], 'relationsGraph')" tal:content="structure Component/relations/relationsGraph" /> + + +</div> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/Entity_list.html b/src/static/movio/templates/Default/skins/Entity_list.html new file mode 100644 index 0000000..cde2ca7 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Entity_list.html @@ -0,0 +1,42 @@ +<section class="results-content clearfix" tal:condition="php: !is_null(Component.records)"> + <h3 tal:condition="Component/title" tal:content="structure Component/title"/> + <span tal:omit-tag="" tal:condition="php: Component.records.count() > 0"> + <span tal:omit-tag="" tal:repeat="item Component/records" tal:attributes="class item/__cssClass__"> + + <span tal:omit-tag="" tal:condition="php: Component.params.visualization == 'list'"> + <article class="item clearfix"> + <h1><a href="" tal:attributes="href item/__url__; title item/title" tal:content="item/title"></a></h1> + </article> + </span> + + <span tal:omit-tag="" tal:condition="php: Component.params.visualization == 'listWithDescription'"> + <article class="item clearfix"> + <h1><a href="" tal:attributes="href item/__url__; title item/title" tal:content="item/title"></a></h1> + <span tal:omit-tag="" tal:condition="php: Component.params.attributes.description && item.keyInDataExists(Component.params.attributes.description)" tal:content="structure php: item->{Component.params.attributes.description}" /> + </article> + </span> + + <span tal:omit-tag="" tal:condition="php: Component.params.visualization == 'icons'"> + <h4><a href="" tal:attributes="href item/__url__; title item/title" tal:content="structure item/__image"></a></h4> + </span> + + <span tal:omit-tag="" tal:condition="php: Component.params.visualization == 'listAndIcons'"> + <span tal:omit-tag="" tal:condition="php: (repeat.item.index % 4) == 0" tal:content="structure php: ('<div class=\'row-fluid\'>')" /> + <div class="item in-grid col-md-3 clearfix"> + <figure> + <a href="" tal:attributes="href item/__url__; title item/title" tal:content="structure item/__image"></a> + </figure> + <h2><a href="" tal:attributes="href item/__url__; title item/title" tal:content="item/title"></a></h2> + <div class="wrapper-link"> + <a href="" tal:attributes="href item/__url__; title item/title"><i class="fa fa-arrow-right"></i></a> + </div> + </div> + <span tal:omit-tag="" tal:condition="php: (repeat.item.index % 4) == 3 || repeat.item.end" tal:content="structure php:('</div>') " /> + </span> + + </span> + </span> + <span tal:omit-tag="" tal:condition="php: Component.records.count() == 0"> + <p tal:content="php:__Tp('MW_NO_RECORD_FOUND')"></p> + </span> +</section> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/Entity_moduleImageLink.html b/src/static/movio/templates/Default/skins/Entity_moduleImageLink.html new file mode 100644 index 0000000..5ce3812 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Entity_moduleImageLink.html @@ -0,0 +1,16 @@ +<article class="box collapsible big relationImageLink" tal:condition="php: Component"> + <h1><span tal:omit-tag="" tal:content="structure Component/label" /> <i class="ico-box fa fa-link"></i></h1> + <button data-toggle="collapse" class="show-content-box" type="button" tal:attributes="data-target php: '#' . Component['id']"></button> + <div class="collapse" tal:attributes="id Component/id"> + <div class="container"> + <span tal:omit-tag="" tal:repeat="item Component/content"> + <span tal:omit-tag="" tal:condition="php: (repeat.item.index % 3) == 0" tal:content="structure php: ('<div class=\'row-fluid\'>')" /> + <div class="item col-md-4"> + <figure tal:condition= "exists:item/__image"><a tal:attributes="href item/url; title item/title" tal:content="structure item/__image/__html__"></a></figure> + <h2><a tal:attributes="href item/url; title item/title" tal:content="structure item/title"></a></h2> + </div> + <span tal:omit-tag="" tal:condition="php: (repeat.item.index % 3) == 2 || repeat.item.end" tal:content="structure php:('</div>') " /> + </span> + </div> + </div> +</article> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/Entity_relationImage.html b/src/static/movio/templates/Default/skins/Entity_relationImage.html new file mode 100644 index 0000000..0d55d2e --- /dev/null +++ b/src/static/movio/templates/Default/skins/Entity_relationImage.html @@ -0,0 +1,27 @@ +<article class="box collapsible big relationImage" tal:condition="php: Component"> + <h1><span tal:omit-tag="" tal:content="structure Component/relation" /> <i class="ico-box fa fa-link"></i></h1> + <button data-toggle="collapse" class="show-content-box" type="button" tal:attributes="data-target php: '#' . Component['id']"></button> + <div class="collapse" tal:attributes="id Component/id"> + <div class="container"> + <div class="slider js-relationImage clearfix"> + <div class="slide" tal:repeat="item Component/content"> + <a tal:condition="exists:item/__image" tal:attributes="href item/url; title item/title" tal:content="structure item/__image/__html__"> + <span class="popup" > + <span class="popup-text" tal:content="item/title"> + <span class="popup-arrow"></span> + </span> + </span> + </a> + </div> + </div> + </div> + </div> + <script> +$(function() { + var targetId = '#<span tal:omit-tag="" tal:content="Component/id"/>'; + Movio.initImageSlider(targetId+' .js-relationImage'); +}); +</script> +</article> + + diff --git a/src/static/movio/templates/Default/skins/Entity_relationImageLink.html b/src/static/movio/templates/Default/skins/Entity_relationImageLink.html new file mode 100644 index 0000000..1e95f99 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Entity_relationImageLink.html @@ -0,0 +1,16 @@ +<article class="box collapsible big relationImageLink" tal:condition="php: Component"> + <h1><span tal:omit-tag="" tal:content="structure Component/relation" /> <i class="ico-box fa fa-link"></i></h1> + <button data-toggle="collapse" class="show-content-box" type="button" tal:attributes="data-target php: '#' . Component['id']"></button> + <div class="collapse" tal:attributes="id Component/id"> + <div class="container"> + <span tal:omit-tag="" tal:repeat="item Component/content"> + <span tal:omit-tag="" tal:condition="php: (repeat.item.index % 3) == 0" tal:content="structure php: ('<div class=\'row-fluid\'>')" /> + <div class="item col-md-4" > + <figure tal:condition= "exists:item/__image"><a tal:attributes="href item/url; title item/title" tal:content="structure item/__image/__html__"></a></figure> + <h2><a tal:attributes="href item/url; title item/title" tal:content="structure item/title"></a></h2> + </div> + <span tal:omit-tag="" tal:condition="php: (repeat.item.index % 3) == 2 || repeat.item.end" tal:content="structure php:('</div>') " /> + </span> + </div> + </div> +</article> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/Entity_relationLink.html b/src/static/movio/templates/Default/skins/Entity_relationLink.html new file mode 100644 index 0000000..30fd140 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Entity_relationLink.html @@ -0,0 +1,13 @@ +<article class="box collapsible big relationLink" tal:condition="php: Component"> + <h1><span tal:omit-tag="" tal:content="structure Component/relation" /> <i class="ico-box fa fa-link"></i></h1> + <button data-toggle="collapse" class="show-content-box" type="button" tal:attributes="data-target php: '#' . Component['id']"></button> + <div class="collapse" tal:attributes="id Component/id"> + <div class="container"> + <div class="row-fluid"> + <ul class="item-list"> + <li tal:repeat="item Component/content"><a tal:attributes="href item/url; title item/title" tal:content="structure item/title"></a></li> + </ul> + </div> + </div> + </div> +</article> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/EuropeanaRelatedContents.html b/src/static/movio/templates/Default/skins/EuropeanaRelatedContents.html new file mode 100644 index 0000000..4f42b6c --- /dev/null +++ b/src/static/movio/templates/Default/skins/EuropeanaRelatedContents.html @@ -0,0 +1,46 @@ +<span tal:omit-tag="" tal:condition="php: Component['ajax']"> + <span tal:omit-tag="" tal:condition="php: !Component['error']" class="wrapper-box-summary no-padding clearfix"> + <div class="slider js-europeanaRalated clearfix"> + <div class="slide" tal:repeat="item Component/records"> + <a target="_blank" tal:attributes="href item/url; title item/title"> + <img tal:attributes="src item/image; title item/title" width="56" height="56" /> + <span class="popup" > + <span class="popup-text">Nascita di diversi stati in Europa + <span class="popup-arrow"></span> + </span> + </span> + </a> + </div> + </div> + </span> + <span tal:omit-tag="" tal:condition="php: Component['error']" class="wrapper-box-summary no-padding clearfix"> + <h1 tal:content="structure Component/error" /> + </span> +</span> + +<span tal:omit-tag="" tal:condition="php: !Component['ajax'] "> + <article class="box collapsible big relationImage" tal:condition="php: Component"> + <h1><span tal:omit-tag="" tal:content="structure Component/label" /></h1> + <button data-toggle="collapse" class="show-content-box" type="button" tal:attributes="data-target php: '#' . Component['id']"></button> + <div class="collapse" tal:attributes="id Component/id"> + <div class="container"> + <div style="text-align: center"> + <img src="static/movio/assets/img/loader_white.gif" style="border: 0; margin: 20px" /> + </div> + </div> + </div> + </article> + <script> +$(function() { + var targetId = '#<span tal:omit-tag="" tal:content="Component/id" />'; + jQuery.ajax({ + url: '<span tal:omit-tag="" tal:content="structure Component/ajaxUrl" />', + dataType: 'json', + success: function( data ) { + $(targetId+' div.container').html(data.content); + Movio.initImageSlider(targetId+' .js-europeanaRalated'); + } + }); +}); + </script> +</span> diff --git a/src/static/movio/templates/Default/skins/Exhibition.html b/src/static/movio/templates/Default/skins/Exhibition.html new file mode 100644 index 0000000..37f30ad --- /dev/null +++ b/src/static/movio/templates/Default/skins/Exhibition.html @@ -0,0 +1,139 @@ +<div class="clearfix"> + <figure class="main-img align-right" tal:condition="php: Component['banner']['mediaId'] > 0"> + <span tal:omit-tag="" tal:content="structure Component/banner/__html__" /> + <figcaption class="description" tal:content="structure Component/banner/title"></figcaption> + </figure> + <dl class="properties"> + <span tal:omit-tag="" tal:condition="Component/date"> + <dt tal:content="php: __T('Date')"></dt> + <dd tal:content="Component/date"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/place"> + <dt tal:content="php: __T('Nation, Region, Province')"></dt> + <dd tal:content="Component/place"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/town"> + <dt tal:content="structure php: __T('Town')"></dt> + <dd tal:content="Component/town"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/venue"> + <dt tal:content="php: __T('Venue')"></dt> + <dd tal:content="Component/venue"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/address"> + <dt tal:content="php: __T('Address')"></dt> + <dd tal:content="Component/address"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/geo"> + <dt tal:content="php: __T('Venue Geolocation')"></dt> + <dd tal:content="Component/geo"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/targetUser"> + <dt tal:content="php: __T('Users')"></dt> + <dd tal:content="Component/targetUser"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/category"> + <dt tal:content="php: __T('Subject')"></dt> + <dd tal:content="Component/category"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/linkedDigitalExhibition"> + <dt tal:content="php: __T('Digital alternative')"></dt> + <dd tal:content="structure php: __Link::formatLink(Component['linkedDigitalExhibition'])"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/openingTime"> + <dt tal:content="php: __T('Timetable')"></dt> + <dd tal:content="Component/openingTime"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/ticket"> + <dt tal:content="php: __T('Access')"></dt> + <dd tal:content="Component/ticket"></dd> + </span> + <span tal:omit-tag="" tal:condition="Component/vernissage"> + <dt tal:content="php: __T('Vernissage')"></dt> + <dd tal:content="Component/vernissage"></dd> + </span> + + </dl> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['abstract'])"> + <span tal:omit-tag="" tal:content="structure Component/abstract" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['ticketOffice'])"> + <h3 tal:content="structure php: __T('Ticket Office')" /> + <span tal:omit-tag="" tal:content="structure Component/ticketOffice" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['catalog'])"> + <h3 tal:content="structure php: __T('Catalog')" /> + <span tal:omit-tag="" tal:content="structure Component/catalog" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['sponsor1'])"> + <h3 tal:content="structure php: __T('Patronages')" /> + <span tal:omit-tag="" tal:content="structure Component/sponsor1" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['sponsor2'])"> + <h3 tal:content="structure php: __T('Promoting organisations')" /> + <span tal:omit-tag="" tal:content="structure Component/sponsor2" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['sponsor3'])"> + <h3 tal:content="structure php: __T('Sponsors')" /> + <span tal:omit-tag="" tal:content="structure Component/sponsor3" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['honoraryCommittee'])"> + <h3 tal:content="structure php: __T('Committee of Honor')" /> + <span tal:omit-tag="" tal:content="structure Component/honoraryCommittee" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['scientificCommittee'])"> + <h3 tal:content="structure php: __T('Scientific Committee')" /> + <span tal:omit-tag="" tal:content="structure Component/scientificCommittee" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['dedication'])"> + <h3 tal:content="structure php: __T('Dedication')" /> + <span tal:omit-tag="" tal:content="structure Component/dedication" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['aknowledgements'])"> + <h3 tal:content="structure php: __T('Aknowledgements')" /> + <span tal:omit-tag="" tal:content="structure Component/aknowledgements" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['promotion'])"> + <h3 tal:content="structure php: __T('Promotion')" /> + <span tal:omit-tag="" tal:content="structure Component/promotion" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['pressOffice'])"> + <h3 tal:content="structure php: __T('Press Office')" /> + <span tal:omit-tag="" tal:content="structure Component/pressOffice" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['projectConstruction'])"> + <h3 tal:content="structure php: __T('Exhibition project')" /> + <span tal:omit-tag="" tal:content="structure Component/projectConstruction" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['reviews'])"> + <h3 tal:content="structure php: __T('Reviews')" /> + <span tal:omit-tag="" tal:content="structure Component/reviews" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['contacts'])"> + <h3 tal:content="structure php: __T('Contacts')" /> + <span tal:omit-tag="" tal:content="structure Component/contacts" /> + </span> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component['services'])"> + <h3 tal:content="structure php: __T('Services')" /> + <span tal:omit-tag="" tal:content="structure Component/services" /> + </span> + <div class="content-box row-fluid clearfix" tal:condition="php: Component['video']['mediaId'] > 0"> + <h3 tal:content="php: __T('Presentation video')" /> + <script> +$(function(){ + jQuery('video,audio').mediaelementplayer(); +}); + </script> + <video tal:attributes="src Component/video/src;"/> + </div> + + <span tal:omit-tag="" + metal:use-macro="_macro.html/boxImageList" + tal:define="images Component/images; + start '0'; + title php: __T('Images')" /> + + <span tal:omit-tag="" + metal:use-macro="_macro.html/boxAttachments" + tal:define="attaches Component/attaches" /> +</div> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/GoogleMap.html b/src/static/movio/templates/Default/skins/GoogleMap.html new file mode 100644 index 0000000..dfbecc2 --- /dev/null +++ b/src/static/movio/templates/Default/skins/GoogleMap.html @@ -0,0 +1,5 @@ +<div tal:attributes="id id" tal:condition="Component/geo"> + <span tal:omit-tag="" + metal:use-macro="GoogleMap_macro.html/map" + tal:define="Component Component" /> +</div> diff --git a/src/static/movio/templates/Default/skins/GoogleMap_macro.html b/src/static/movio/templates/Default/skins/GoogleMap_macro.html new file mode 100644 index 0000000..c8a609c --- /dev/null +++ b/src/static/movio/templates/Default/skins/GoogleMap_macro.html @@ -0,0 +1,102 @@ +<span metal:define-macro="map"> + <div id="googlemap" class="google-maps" tal:attributes="style Component/style; data-geo Component/geo; data-poi Component/markers; data-path Component/pathEnable"></div> + +<script tal:attributes="src Component/jsSrc"></script> +<script> +// <![CDATA[ +jQuery( function(){ + var canvas = $('#googlemap'), + geo = canvas.data('geo'), + poi = canvas.data('poi'), + path = canvas.data('path'), + infowindow = new google.maps.InfoWindow(); + latlng = new google.maps.LatLng(geo.lat, geo.long), + mapOptions = { + zoom: geo.zoom, + center: latlng, + mapTypeId: google.maps.MapTypeId.ROADMAP + }, + polyCoordinates = [], + poiNumbers = poi.length, + map = new google.maps.Map(canvas[0], mapOptions), + latLngBounds = new google.maps.LatLngBounds(), + + jQuery(poi).each(function(i, item) { + var m, + title = item.title, + content = (item.title ? '<h4>' + item.title + '</h4>' : '') + + item.text + '<p>' + item.image + '</p>' + '<p>' + item.link + '</p>'; + + + m = new google.maps.Marker({ + map: map, + position: new google.maps.LatLng(item.lat, item.long), + title: title + }); + + if (content) { + makeInfoWindowEvent(map, infowindow, content, m); + $('a.js-toggleMapMarker[data-item="'+i+'"]').click(function(e){ + e.preventDefault(); + infowindow.setContent(content); + infowindow.open(map, m); + }); + } + polyCoordinates.push(m.position); + latLngBounds.extend(m.position); + }); + + if (poiNumbers) { + map.fitBounds(latLngBounds); + } + + if (path==1 && poiNumbers>1) { + var path = new google.maps.Polyline({ + path: polyCoordinates, + strokeColor: "#FF0000", + strokeOpacity: 0.5, + strokeWeight: 4 + }); + path.setMap(map); + } else if (path>1 && poiNumbers>1) { + var directionsService = new google.maps.DirectionsService(), + travelMode = [google.maps.TravelMode.BICYCLING, google.maps.TravelMode.DRIVING, google.maps.TravelMode.TRANSIT, google.maps.TravelMode.WALKING]; + + jQuery(poi).each(function(i, item) { + if (i==poiNumbers-1) return; + + var request = { + origin: new google.maps.LatLng(poi[i].lat, poi[i].long), + destination: new google.maps.LatLng(poi[i+1].lat, poi[i+1].long), + optimizeWaypoints: false, + travelMode: travelMode[path-2] + }; + directionsService.route(request, function(response, status) { + if (response.status=="OK") { + var path = new google.maps.Polyline({ + path: response.routes[0].overview_path, + strokeColor: "#000088", + strokeOpacity: 0.5, + strokeWeight: 4 + }); + path.setMap(map); + } + }); + }); + } + + function makeInfoWindowEvent(map, infowindow, contentString, marker) { + google.maps.event.addListener(marker, 'click', function() { + infowindow.setContent(contentString); + infowindow.open(map, marker); + + $.each($('.gm-style-iw'), function(k, v) { + $(v).css('overflow', 'hidden'); + $(v).children().css('overflow', 'hidden'); + }); + }); + } +}) +// ]]> +</script> +</span> diff --git a/src/static/movio/templates/Default/skins/HomeImageSlider.html b/src/static/movio/templates/Default/skins/HomeImageSlider.html new file mode 100644 index 0000000..ec13233 --- /dev/null +++ b/src/static/movio/templates/Default/skins/HomeImageSlider.html @@ -0,0 +1,26 @@ +<article class="slideshow col-md-9 big"> + <div class="slider single-item js-sliderhome"> + <div class="slide" tal:attributes="style php:Template::homeSliderImage(item)" tal:repeat="item Component"> + <div class="description"> + <h1><a tal:attributes="href item/pageId" tal:content="item/title"></a></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <a class="link-continue" tal:attributes="href item/pageId" tal:content="php: __T('read more')"></a> + </div> + </div> + </div> +<script> +$(function() { + $('.js-sliderhome').slick({ + dots: true, + autoplay: true, + autoplaySpeed: Glizy.slideShowSpeed, + arrows:false, + infinite: true, + speed: 700, + pauseOnDotsHover: true, + slidesToShow: 1, + slidesToScroll: 1 + }); +}); +</script> +</article> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/ImagesList.html b/src/static/movio/templates/Default/skins/ImagesList.html new file mode 100644 index 0000000..3905efc --- /dev/null +++ b/src/static/movio/templates/Default/skins/ImagesList.html @@ -0,0 +1,5 @@ +<span tal:omit-tag="" + metal:use-macro="_macro.html/boxImageList" + tal:define="images Component; + start '0'; + title ''" /> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/Login.html b/src/static/movio/templates/Default/skins/Login.html new file mode 100644 index 0000000..378d932 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Login.html @@ -0,0 +1,34 @@ +<div class="alert error" tal:condition="Component/errorLabel"> + <h4 tal:content="php:__T('Alert')"></h4> + <p tal:content="structure Component/errorLabel"></p> +</div> +<form class="my-form login clearfix"> + <div class="control-group"> + <label for="" tal:attributes="for Component/userField" tal:content="structure Component/userLabel"></label> + <div class="controls"> + <i class="ico fa fa-user"></i> + <input type="text" tal:attributes="id Component/userField; name Component/userField" /> + </div> + </div> + + <div class="control-group"> + <label for="" tal:attributes="for Component/passwordField" tal:content="structure Component/passwordLabel"></label> + <div class="controls"> + <i class="ico fa fa-lock"></i> + <input type="password" tal:attributes="id Component/passwordField; name Component/passwordField" /> + </div> + </div> + + <div class="control-group"> + <div class="pull-left"> + <p> + <a class="link" tal:attributes="href Component/__url__" tal:content="structure Component/registrationLabel"></a> + <br /> + <a class="link" tal:attributes="href Component/askPasswordUrl" tal:content="structure Component/askPasswordLabel"></a> + </p> + </div> + <div class="pull-right"> + <input type="submit" tal:attributes="name Component/submitName;value Component/confirmLabel" /> + </div> + </div> +</form> diff --git a/src/static/movio/templates/Default/skins/News_entry.html b/src/static/movio/templates/Default/skins/News_entry.html new file mode 100644 index 0000000..318613f --- /dev/null +++ b/src/static/movio/templates/Default/skins/News_entry.html @@ -0,0 +1,27 @@ +<h2 tal:content="Component/title" /> +<h4 tal:condition="php: Component.place || Component.dateDescription"> + <span tal:omit-tag="" tal:condition="Component/place" tal:content="Component/place" /><span tal:omit-tag="" tal:condition="php: Component.place && Component.dateDescription" tal:content="string:, " /> + <span tal:omit-tag="" tal:condition="Component/dateDescription" tal:content="Component/dateDescription" /> +</h4> +<h5 tal:condition="php: Component.category || Component.urlExternal" > + <span tal:omit-tag="" tal:condition="Component/category" tal:content="Component/category" /><span tal:omit-tag="" tal:condition="php: Component.category && Component.urlExternal" tal:content="string:, " /> + <span tal:omit-tag="" tal:condition="Component/urlExternal" tal:content="structure php: __Link::formatLink(Component.urlExternal, Component.urlLabel)" /> +</h5> +<figure tal:condition="php: Component.images[0]" class="main-img align-right" tal:content="structure php: Component.images[0].image['__html__']" /> +<article tal:omit-tag="" tal:condition="php: !glz_empty(Component.body)"> + <span tal:omit-tag="" tal:content="structure Component/body" /> +</article> +<section tal:omit-tag="" tal:condition="php: !glz_empty(Component.contacts)" class="item clearfix"> + <h3 tal:content="structure php: __T('Contacts')" /> + <span tal:omit-tag="" tal:content="structure Component/contacts" /> +</section> + +<span tal:omit-tag="" + metal:use-macro="_macro.html/boxImageList" + tal:define="images Component/images; + start '1'; + title php: __T('Images')" /> + +<span tal:omit-tag="" + metal:use-macro="_macro.html/boxAttachments" + tal:define="attaches Component/attaches" /> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/News_list.html b/src/static/movio/templates/Default/skins/News_list.html new file mode 100644 index 0000000..a011bea --- /dev/null +++ b/src/static/movio/templates/Default/skins/News_list.html @@ -0,0 +1,24 @@ +<section class="results-content" tal:condition="php: !is_null(Component.records)"> + <h3 tal:content="structure Component/title"/> + <span tal:omit-tag="" tal:condition="php: Component.records.count() > 0"> + <article tal:repeat="item Component/records" class="item clearfix"> + <figure tal:condition="php: item.images[0]"> + <a href="" tal:attributes="href item/__url__; title item/title"> + <img tal:attributes="src php: item.images[0].image['src']; alt item/title" /> + </a> + </figure> + <h1> + <a href="" tal:attributes="href item/__url__; title item/title"> + <span tal:content="item/title" /> + </a> + </h1> + <p tal:condition="php: item.keyInDataExists('bodyShort')" tal:content="structure item/bodyShort" /> + </article> + </span> + <span tal:omit-tag="" tal:condition="php: Component.records.count() == 0"> + <article class="item clearfix" > + <p tal:content="php:__T('MW_NO_RECORD_FOUND')" /> + </article> + </span> + <div class="clear"></div> +</section> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/Photogallery.html b/src/static/movio/templates/Default/skins/Photogallery.html new file mode 100644 index 0000000..7fe3272 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Photogallery.html @@ -0,0 +1,20 @@ +<div tal:attributes="class php: Component['type'] . ' wrapper-galleria-io'" tal:condition="php: count(Component['images'])"> +<div class="content-galleria-io"> + <div id="galleria"></div> + <script src="static/galleria/galleria-1.4.2.min.js"></script> + <script> +var data = []; +<span tal:omit-tag="" tal:repeat="item Component/images"> +data.push({ "title": "<span tal:omit-tag="" tal:content="structure php:glz_stringToJs(item.image['title'])" />", + "description": "<span tal:omit-tag="" tal:content="structure php:glz_stringToJs(item.image['description'], true)" />", + "thumb": "<span tal:omit-tag="" tal:content="php:org_glizy_helpers_Media::getResizedImageUrlById(item.image['mediaId'], false, __Config::get('THUMB_WIDTH'), __Config::get('THUMB_HEIGHT'), true)" />", + "image": "<span tal:omit-tag="" tal:content="php:org_glizy_helpers_Media::getUrlById(item.image['mediaId'])" />" + }); +</span> +Galleria.loadTheme('static/galleria/themes/movio/galleria.<span tal:omit-tag="" tal:content="Component/type" />.js'); +Galleria.run('#galleria', { + dataSource: data, imageCrop: <span tal:omit-tag="" tal:content="Component/imageCrop" />, imagePan: <span tal:omit-tag="" tal:content="Component/imagePan" />, imagePosition: '<span tal:omit-tag="" tal:content="Component/imagePosition" />' +}); +</script> +</div> +</div> diff --git a/src/static/movio/templates/Default/skins/Search.html b/src/static/movio/templates/Default/skins/Search.html new file mode 100644 index 0000000..076f23d --- /dev/null +++ b/src/static/movio/templates/Default/skins/Search.html @@ -0,0 +1,23 @@ +<span tal:omit-tag=""> + <div class="control-group"> + <label for="search" class="large-label" tal:content="Component/label" /> + <div class="controls with-button"> + <input type="text" name="search" id="search" class="input-large" tal:attributes="value Component/value"/> + <input type="submit" class="submitButton" tal:attributes="value Component/buttonLabel"/> + </div> + </div> + <p tal:content="structure Component/comment" /> + <span tal:omit-tag="" tal:condition="php: !is_null(Component['result'])" > + <section class="results-content" tal:condition="php: count(Component['result'])"> + <div class="heading-row"> + <h2 tal:content="structure Component/comment1"/> + <p tal:content="structure Component/total"/> + </div> + <article class="item clearfix" tal:repeat="item Component/result"> + <h1 tal:content="structure item/__url__"></h1> + <p tal:condition="item/description" tal:content="structure item/description" /> + </article> + </section> + <span tal:condition="php: !count(Component['result'])" tal:content="php:__T('MW_NO_RECORD_FOUND')" /> + </span> +</span> diff --git a/src/static/movio/templates/Default/skins/Share.html b/src/static/movio/templates/Default/skins/Share.html new file mode 100644 index 0000000..6ab1ee0 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Share.html @@ -0,0 +1,24 @@ +<span tal:omit-tag="" tal:repeat="item Component"> + <span tal:omit-tag="" tal:condition="php: item['id'] != 'btn_fbLike' && item['id'] != 'btn_google+1'"> + <a tal:attributes="id item/id; name item/name; href item/href; title item/title; class item/a_class" target="_blank" style="background-image:none; text-decoration:none;"> + <i tal:attributes="class item/i_class" style="text-decoration:none;"></i> + </a> + </span> + <span tal:omit-tag="" tal:condition="php: item['id'] == 'btn_fbLike'"> + <script>(function(d, s, id) { + var js, fjs = d.getElementsByTagName(s)[0]; + if (d.getElementById(id)) return; + js = d.createElement(s); js.id = id; + js.src = "//connect.facebook.net/it_IT/sdk.js#xfbml=1&version=v2.0"; + fjs.parentNode.insertBefore(js, fjs); + }(document, 'script', 'facebook-jssdk')); + </script> + <div tal:attributes="id item/id; name item/name; data-href item/href; class item/i_class" data-layout="button_count" data-action="like" data-show-faces="false" data-share="false" style="cursor: default;"> + </div> + <div id="fb-root"></div> + </span> + <span tal:omit-tag="" tal:condition="php: item['id'] == 'btn_google+1'"> + <div class="g-plusone" data-annotation="none"></div> + <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script> + </span> +</span> diff --git a/src/static/movio/templates/Default/skins/Storyteller.html b/src/static/movio/templates/Default/skins/Storyteller.html new file mode 100644 index 0000000..fe29643 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Storyteller.html @@ -0,0 +1,323 @@ +<div class="storyteller"> + <nav id="nav-bar"> + <ul class="js-storytellerNav"> + <li class="active"><a href="" tal:content="php: __T('Full history')"></a></li> + <li><a href="" class="js-audio" tal:content="php: __T('Audio')"></a></li> + <li><a href="" class="js-video" tal:content="php: __T('Video')"></a></li> + <li><a href="" class="js-image" tal:content="php: __T('Images')"></a></li> + <li><a href="" class="js-text" tal:content="php: __T('Texts')"></a></li> + </ul> + </nav> + <script src="static/galleria/galleria-1.4.2.min.js"></script> + <script> +var galleries = []; +function galleriaio_loadNext() { + if (galleries.length) { + var callback = galleries.shift(); + callback(); + } +} + +$(function(){ + $(".js-storytellerNav a").each(function(index, el){ + var el = $(el); + var cssClass = el.attr("class"); + if (cssClass && $("div.content-story > article."+cssClass).length==0) { + el.parent().hide(); + } + }); + $(".js-storytellerNav a").click(function(e){ + e.preventDefault(); + var el = $(this); + el.parent().siblings().removeClass("active"); + el.parent().addClass("active"); + + + var cssClass = el.attr("class"); + if (cssClass) { + $("div.content-story > article."+cssClass).slideDown(300); + $("div.content-story > article:not(."+cssClass+")").addClass("js-itemHidden").slideUp(300); + } else { + $("div.content-story > article.js-itemHidden").slideDown(300); + } + $("div.content-story > article.js-formComment").slideUp(300); + }) + + $("a.js-writeComment").click(function(e){ + e.preventDefault(); + $(this).closest("article.item-box").next().slideDown(300); + }); + + $(".js-formCommentCancel").click(function(e){ + e.preventDefault(); + $(this).closest("article.item-box").slideUp(300); + }); + + $(".js-formComment form").submit(function(){ + var form = $(this); + if (!form.find("input#authorName").val()) { + alert("Insert the name"); + return false; + } + if (!form.find("input#authorEmail").val()) { + alert("Insert the email"); + return false; + } + if (!form.find("textarea#text").val()) { + alert("Insert the comment text"); + return false; + } + + }); + + $("a.js-commentsMoreLink").click(function(e){ + e.preventDefault(); + $(this).parent().parent().find(".js-commentsMore").slideDown(300); + $(this).hide(); + }); + + jQuery('video,audio').mediaelementplayer(); + galleriaio_loadNext(); + + if (location.hash.indexOf('form') || location.hash.indexOf('comments')) { + $('a[name='+location.hash.substr(1)+']').parent().slideDown(300); + } +}); + </script> + + <div class="content-story"> + + <span tal:omit-tag="" tal:repeat="item Component"> + <a tal:attributes="name item/hash"></a> + <article class="item-box link js-text" tal:condition="php:item.type=='text'"> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <article class="item-linked"> + <div class="clearfix"> + <figure class="main-img align-right" tal:condition="item/image" tal:content="structure php:org_glizy_helpers_Media::getResizedImageById(item.image, false, 320, 320)"> + </figure> + + <div tal:condition="item/audio" style="float:right; margin: 30px 0 0 15px;"> + <audio controls="" tal:attributes="src php:org_glizy_helpers_Media::getFileUrlById(item.audio, true)" /> + </div> + <div tal:condition="item/video" style="float:right; margin: 0 15px 0 0;"> + <video width="300" height="200" controls="" tal:attributes="src php:org_glizy_helpers_Media::getFileUrlById(item.video, true)" /> + </div> + + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <h2 class="tipe-box" tal:condition="item/subtitle" tal:content="item/subtitle"></h2> + <span tal:omit-tag="" tal:content="structure item/text" /> + </div> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from ''" /> + </article> + </div> + </article> + + <article class="item-box js-video" tal:condition="php:item.type=='youtube'"> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <article class="item-linked"> + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <iframe width="640" height="360" frameborder="0" allowfullscreen="" tal:attributes="src item/url"></iframe> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from 'Youtube'" /> + </article> + </div> + </article> + + <article class="item-box js-video" tal:condition="php:item.type=='vimeo'"> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <article class="item-linked"> + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <iframe width="640" height="360" frameborder="0" allowfullscreen="" tal:attributes="src item/url"></iframe> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from 'Vimeo'" /> + </article> + </div> + </article> + + <article class="item-box link js-image" tal:condition="php:item.type=='image'"> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <article class="item-linked"> + <div class="clearfix"> + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <figure tal:condition="item/image" style="max-width:100%" tal:content="structure php:org_glizy_helpers_Media::getImageById(item.image)"> + </figure> + </div> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from ''" /> + </article> + </div> + </article> + + <article class="item-box link js-audio" tal:condition="php:item.type=='audio'"> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <article class="item-linked"> + <div class="clearfix"> + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <audio controls="" width="100%" tal:attributes="src php:org_glizy_helpers_Media::getFileUrlById(item.audio, true)" /> + </div> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from ''" /> + </article> + </div> + </article> + + <article class="item-box link js-video" tal:condition="php:item.type=='video'"> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <article class="item-linked"> + <div class="clearfix"> + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <video controls="" width="100%" style="max-width: 100%" tal:attributes="src php:org_glizy_helpers_Media::getFileUrlById(item.video, true)" /> + </div> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from ''" /> + </article> + </div> + </article> + + <article class="item-box gallery js-image" tal:condition="php:item.type=='photogallery'"> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <h4 class="tipe-box big"><span tal:omit-tag="" tal:content="item/title"/><i class="ico gallery"></i></h4> + <span tal:omit-tag="" tal:content="structure item/text" /> + <div tal:attributes="class php: 'wrapper-galleria-io ' . item.galleryType" tal:condition="php: item.gallery AND item.gallery.count()"> + <div class="content-galleria-io" > + <div tal:attributes="id php: 'galleria' . item.hash" style="height: 500px"></div> + <script> +galleries.push(function(){ + var data = []; + <span tal:omit-tag="" tal:repeat="subitem item/gallery"> + data.push({ "title": "<span tal:omit-tag="" tal:content="structure php: glz_stringToJs(subitem.media_title)" />", + "description": "<span tal:omit-tag="" tal:content="structure php: glz_stringToJs(subitem.media_description, true)" />", + "thumb": "<span tal:omit-tag="" tal:content="php:org_glizy_helpers_Media::getResizedImageUrlById(subitem.media_id, false, __Config::get('THUMB_WIDTH'), __Config::get('THUMB_HEIGHT'), true)" />", + "image": "<span tal:omit-tag="" tal:content="php:org_glizy_helpers_Media::getUrlById(subitem.media_id)" />" + }); + </span> + Galleria.loadTheme('static/galleria/themes/movio/galleria.<span tal:omit-tag="" tal:content="item/galleryType" />.js'); + Galleria.run('<span tal:omit-tag="" tal:content="php: '#galleria' . item.hash" />', { + dataSource: data, imageCrop: <span tal:omit-tag="" tal:content="item/galleryImageCrop" />, imagePan: <span tal:omit-tag="" tal:content="item/galleryImagePan" />, imagePosition: '<span tal:omit-tag="" tal:content="item/galleryImagePosition" />' + }); + + Galleria.ready(function() { + galleriaio_loadNext(); + }); +}); + </script> + </div> + </div> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from ''" /> + </div> + </article> + + <span tal:omit-tag="" tal:condition="item/commentsEnabled" metal:use-macro="formComments" tal:define="item item" /> + <span tal:omit-tag="" tal:condition="item/commentsEnabled" metal:use-macro="comments" tal:define="item item" /> + </span> + </div> + +</div> + + +<div class="functions" metal:define-macro="functions"> + <span tal:omit-tag="" tal:condition="php:count(item.documents)"> + <h4 tal:content="php: __T('Insights')"></h4> + <ul class="insights clearfix" tal:condition="item/documents" > + <span tal:omit-tag="" tal:repeat="subItem item/documents"> + <li tal:condition="subItem" tal:content="structure subItem"></li> + </span> + </ul> + </span> + <div class="from" tal:condition="from"><span>FROM:</span> <span tal:omit-tag="" tal:content="from" /></div> + <div class="actions clearfix"> + <ul class="sx" tal:condition="item/commentsEnabled"> + <li tal:condition="item/externalLink"><a tal:attributes="href item/externalLink" target="_blank"><i class="fa fa-external-link"></i></a></li> + <li tal:condition="item/numComments"><i class="fa fa-comment"></i><a tal:attributes="href php: '#comments_' . item.hash"> <span tal:omit-tag="" tal:content="item/numComments" /> comments</a></li> + <li><i class="fa fa-pencil"></i><a class="js-writeComment" href="" tal:content="php: __T('Write comment')"></a></li> + </ul> + + <ul class="dx"> + <li><a tal:attributes="href item/urlPermalink">permalink</a></li> + <li><a target="_blank" tal:attributes="href item/urlFacebook"><i class="fa fa-facebook"></i></a></li> + <li><a target="_blank" tal:attributes="href item/urlTwitter"><i class="fa fa-twitter"></i> </a></li> + </ul> + + </div> +</div> + +<article class="item-box comment js-comments" metal:define-macro="comments" tal:condition="item/numComments"> + <a tal:attributes="name php: 'comments_' . item.hash"></a> + <span class="arrow-big"></span> + + <div class="content-box-item"> + <h4 class="tipe-box">Comments</h4> + <span tal:omit-tag="" tal:repeat="subItem item/comments"> + <article class="item-comment" tal:condition="php: repeat.subItem.number <= 5"> + <h2 class="title" tal:content="subItem/authorName"></h2> + <div tal:content="structure subItem/text"></div> + </article> + </span> + <span tal:condition="php: item.comments.count() > 5"> + <div class="archive-link"> + <a href="" class="js-commentsMoreLink">show more comments</a> + </div> + <div style="display:none;" class="js-commentsMore"> + <span tal:omit-tag="" tal:repeat="subItem item/comments"> + <article class="item-comment" tal:condition="php: repeat.subItem.number > 5"> + <h2 class="title" tal:content="subItem/authorName"></h2> + <div tal:content="structure subItem/text"></div> + </article> + </span> + </div> + </span> + </div> +</article> + +<article class="item-box comment js-formComment" style="display: none" metal:define-macro="formComments"> + <a tal:attributes="name php: 'form_' . item.hash"></a> + <span class="arrow-big"></span> + + <div class="alert error" tal:condition="item/formError"> + <h4 tal:content="structure item/formError" /> + <p>&nbsp;</p> + </div> + + <form action="" method="POST"> + <input type="hidden" name="hash" tal:attributes="value item/hash"/> + <input type="hidden" name="action" value="PostComment"/> + <p><label><span>Name</span> + <input type="text" value="" id="authorName" name="authorName" tal:attributes="value item/formAuthor" /> + </label> + </p> + <p> + <label><span>Email</span> + <input type="text" value="" id="authorEmail" name="authorEmail" tal:attributes="value item/formEmail" /> + </label> + </p> + <p> + <label><span>Comment text</span> + <textarea name="text" id="text" tal:content="item/formText"></textarea> + </label> + </p> + <p> + <span tal:omit-tag="" tal:content="structure item/captcha" /> + <label><span>Verify code</span> + <input type="text" value="" id="captcha" name="captcha"/> + </label> + </p> + <p class="align-center"> + <input type="submit" value="Post"/> + <input type="reset" value="Cancel" class="js-formCommentCancel"/> + </p> + </form> +</article> diff --git a/src/static/movio/templates/Default/skins/Timeline.html b/src/static/movio/templates/Default/skins/Timeline.html new file mode 100644 index 0000000..af29abb --- /dev/null +++ b/src/static/movio/templates/Default/skins/Timeline.html @@ -0,0 +1,18 @@ +<div id="timeline-embed"></div> +<script> +var embed_path = 'static/timelinejs/'; +var timeline_config = { + width: '<span tal:omit-tag="" tal:content="structure Component/width" />', + height: '<span tal:omit-tag="" tal:content="structure Component/height" />', + source: '<span tal:omit-tag="" tal:content="structure Component/source" />', + embed_id: 'timeline-embed', + hash_bookmark: true, + font: '<span tal:omit-tag="" tal:content="structure Component/font" />', + debug: false, + lang: '<span tal:omit-tag="" tal:content="structure Component/lang" />', + maptype: '<span tal:omit-tag="" tal:content="structure Component/maptype" />', + css: 'static/timelinejs/css/timeline.css', + js: 'static/timelinejs/js/timeline-min.js' +} +</script> +<script src="static/timelinejs/js/storyjs-embed.js"></script> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/TouristOperators_entry.html b/src/static/movio/templates/Default/skins/TouristOperators_entry.html new file mode 100644 index 0000000..3b891fe --- /dev/null +++ b/src/static/movio/templates/Default/skins/TouristOperators_entry.html @@ -0,0 +1,38 @@ +<div class="col-md-5 block-inner-aside pull-right col-xs-12" tal:condition="php: Component.images[0]"> + <figure class="main-img align-right" tal:content="structure php: Component.images[0].image['__html__']" /> +</div> + +<h3 tal:condition="php: Component.type || Component.externalUrl"> + <span tal:omit-tag="" tal:condition="Component/type" tal:content="Component/type" /> + <span tal:omit-tag="" tal:condition="php: Component.type && Component.externalUrl" tal:content="string:-" /> + <span tal:omit-tag="" tal:condition="Component/externalUrl" tal:content="structure php: __Link::formatLink(Component.externalUrl, Component.externalUrl, Component.externalUrl, '', '')" /> +</h3> +<article tal:condition="Component/description" tal:content="structure Component/description" class="item clearfix"/> +<div class="clearfix"> + <div class="col-md-5 col-padding-right"> + <section class="results-content" tal:condition="php: count(Component.locations)" > + <section tal:repeat="item Component/locations" class="item"> + <h4 tal:condition="item/locationDescription" > + <a href="#" tal:condition="item/coordinates" class="no-undeline js-toggleMapMarker" tal:attributes="data-item repeat/item/index" ><i class="fa fa-map-marker"></i> <span tal:omit-tag="" tal:content="structure item/locationDescription" /></a> + </h4> + <p tal:condition="item/location" tal:content="structure item/location" /> + </section> + </section> + </div> + <div class="col-md-7"> + <span tal:omit-tag="" + metal:use-macro="GoogleMap_macro.html/map" + tal:define="Component Component/map" /> + + </div> +</div> + +<span tal:omit-tag="" + metal:use-macro="_macro.html/boxImageList" + tal:define="images Component/images; + start '1'; + title php: __T('Images')" /> + +<span tal:omit-tag="" + metal:use-macro="_macro.html/boxAttachments" + tal:define="attaches Component/attaches" /> diff --git a/src/static/movio/templates/Default/skins/TouristOperators_list.html b/src/static/movio/templates/Default/skins/TouristOperators_list.html new file mode 100644 index 0000000..a011bea --- /dev/null +++ b/src/static/movio/templates/Default/skins/TouristOperators_list.html @@ -0,0 +1,24 @@ +<section class="results-content" tal:condition="php: !is_null(Component.records)"> + <h3 tal:content="structure Component/title"/> + <span tal:omit-tag="" tal:condition="php: Component.records.count() > 0"> + <article tal:repeat="item Component/records" class="item clearfix"> + <figure tal:condition="php: item.images[0]"> + <a href="" tal:attributes="href item/__url__; title item/title"> + <img tal:attributes="src php: item.images[0].image['src']; alt item/title" /> + </a> + </figure> + <h1> + <a href="" tal:attributes="href item/__url__; title item/title"> + <span tal:content="item/title" /> + </a> + </h1> + <p tal:condition="php: item.keyInDataExists('bodyShort')" tal:content="structure item/bodyShort" /> + </article> + </span> + <span tal:omit-tag="" tal:condition="php: Component.records.count() == 0"> + <article class="item clearfix" > + <p tal:content="php:__T('MW_NO_RECORD_FOUND')" /> + </article> + </span> + <div class="clear"></div> +</section> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/TouristOperators_map.html b/src/static/movio/templates/Default/skins/TouristOperators_map.html new file mode 100644 index 0000000..d06f03e --- /dev/null +++ b/src/static/movio/templates/Default/skins/TouristOperators_map.html @@ -0,0 +1,7 @@ +<section class="results-content" tal:condition="php: !is_null(Component)"> + <h3 tal:content="structure Component/title"/> + <span tal:omit-tag="" + metal:use-macro="GoogleMap_macro.html/map" + tal:define="Component Component" /> + +</section> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/Unity3D.html b/src/static/movio/templates/Default/skins/Unity3D.html new file mode 100644 index 0000000..81ac2f2 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Unity3D.html @@ -0,0 +1,104 @@ +<span tal:omit-tag="" tal:condition="php: count(Component)"> + <script type="text/javascript"> + <!-- + var unityObjectUrl = "http://webplayer.unity3d.com/download_webplayer-3.x/3.0/uo/UnityObject2.js"; + if (document.location.protocol == 'https:') + unityObjectUrl = unityObjectUrl.replace("http://", "https://ssl-"); + document.write('<script type="text\/javascript" src="' + unityObjectUrl + '"><\/script>'); + --> + </script> + <script type="text/javascript"> + var config = { + width: '<span tal:omit-tag="" tal:content="structure Component/width" />', + height: '<span tal:omit-tag="" tal:content="structure Component/height" />', + params: { + logoimage: '<span tal:omit-tag="" tal:content="structure Component/logoimage" />', + backgroundcolor: '<span tal:omit-tag="" tal:content="structure Component/backgroundColor" />', + bordercolor: '<span tal:omit-tag="" tal:content="structure Component/borderColor" />', + textcolor: '<span tal:omit-tag="" tal:content="structure Component/textColor" />', + disableContextMenu: '<span tal:omit-tag="" tal:content="structure Component/disableContextMenu" />', + disableFullscreen: '<span tal:omit-tag="" tal:content="structure Component/disableFullscreen" />', + attributes: '<span tal:omit-tag="" tal:content="structure Component/attributes" />' + } + }; + var u = new UnityObject2(config); + + jQuery(function() { + var missingScreen = jQuery("#unityPlayer").find(".missing"); + var brokenScreen = jQuery("#unityPlayer").find(".broken"); + missingScreen.hide(); + brokenScreen.hide(); + + u.observeProgress(function (progress) { + switch(progress.pluginStatus) { + case "broken": + brokenScreen.find("a").click(function (e) { + e.stopPropagation(); + e.preventDefault(); + u.installPlugin(); + return false; + }); + brokenScreen.show(); + break; + case "missing": + missingScreen.find("a").click(function (e) { + e.stopPropagation(); + e.preventDefault(); + u.installPlugin(); + return false; + }); + missingScreen.show(); + break; + case "installed": + missingScreen.remove(); + break; + case "first": + break; + } + }); + u.initPlugin(jQuery("#unityPlayer")[0], 'getFile.php?id=<span tal:omit-tag="" tal:content="structure Component/fileId" />'); + }); + </script> + <style type="text/css"> + div.broken, + div.missing { + margin: auto; + position: relative; + top: 50%; + width: 193px; + } + div.broken a, + div.missing a { + height: 63px; + position: relative; + top: -31px; + } + div.broken img, + div.missing img { + border-width: 0px; + } + div.broken { + display: none; + } + div#unityPlayer { + cursor: default; + height: '<span tal:omit-tag="" tal:content="structure Component/height" />px'; + width: '<span tal:omit-tag="" tal:content="structure Component/width" />px'; + } + </style> + <div id="unityPlayer"> + <div class="missing"> + <a href="http://unity3d.com/webplayer/" title="Unity Web Player. Install now!"> + <img alt="Unity Web Player. Install now!" src="http://webplayer.unity3d.com/installation/getunity.png" width="193" height="63" /> + </a> + </div> + <div class="broken"> + <a href="http://unity3d.com/webplayer/" title="Unity Web Player. Install now! Restart your browser after install."> + <img alt="Unity Web Player. Install now! Restart your browser after install." src="http://webplayer.unity3d.com/installation/getunityrestart.png" width="193" height="63" /> + </a> + </div> + </div> +</span> +<span tal:omit-tag="" tal:condition="php: !count(Component)"> + <p><b>Nessun file Unity3D selezionato!</b></p> +</span> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/Video.html b/src/static/movio/templates/Default/skins/Video.html new file mode 100644 index 0000000..bc37175 --- /dev/null +++ b/src/static/movio/templates/Default/skins/Video.html @@ -0,0 +1,9 @@ +<div class="content-box row-fluid"> + <script> +$(function(){ + jQuery('video,audio').mediaelementplayer(); +}); + </script> + + <video tal:attributes="src Component/video/src; width Component/width; height Component/height" /> +</div> \ No newline at end of file diff --git a/src/static/movio/templates/Default/skins/_macro.html b/src/static/movio/templates/Default/skins/_macro.html new file mode 100644 index 0000000..76a4b5e --- /dev/null +++ b/src/static/movio/templates/Default/skins/_macro.html @@ -0,0 +1,16 @@ +<div class="row-fluid clearfix" tal:condition="php: count(images) > start" metal:define-macro="boxImageList"> + <h3 tal:condition="title" tal:content="title" /> + <div class="slider imageList clearfix js-imageList"> + <span tal:omit-tag="" tal:repeat="item images"> + <span tal:condition="php: repeat.item.number > start" class="slide" tal:content="structure item/image/__html__" /> + </span> + </div> +</div> + +<span tal:omit-tag="" tal:condition="php: count(attaches)" metal:define-macro="boxAttachments"> + <h3 tal:content="php: __T('Download files')" class="downloadTitle" /> + <ul class="downloadList"> + <li tal:repeat="item attaches" tal:content="structure item/media/__html__" /> + </ul> +</span> + diff --git a/src/static/movio/templates/Minimal-in-blue/Template.php b/src/static/movio/templates/Minimal-in-blue/Template.php new file mode 100644 index 0000000..3b81671 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/Template.php @@ -0,0 +1,224 @@ +<?php +class Template extends GlizyObject +{ + const TEMPLATE_NAME = 'Minimal-in-blue'; + + function render($application, $view, $templateData) + { + $templateData = $this->getTemplateDataFromCache($templateData); + + $siteProp = unserialize(org_glizy_Registry::get(__Config::get('REGISTRY_SITE_PROP').$view->_application->getLanguage(), '')); + $view->addOutputCode($templateData->css, 'css'); + $view->addOutputCode($siteProp['title'], 'siteTitle'); + $view->addOutputCode($siteProp['subtitle'], 'siteSubtitle'); + if ($templateData->footerLogo) { + $view->addOutputCode($templateData->footerLogo, 'logoFooter'); + } + $view->setAttribute('templateFileName', 'page.php'); + } + + private function getTemplateDataFromCache($templateData) + { + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + // $templateProxy->invalidateCache(); + $cache = $templateProxy->getTemplateCache(); + + $cssFileName = __Paths::get('CACHE').md5($this->getClassName().'_'.$templateData->__id).'.css'; + $self = $this; + $templateData = $cache->get($cssFileName, array(), function() use ($self, $templateData, $cssFileName) { + $newTemplateData = new StdClass; + $newTemplateData->footerLogo = ''; + + $self->updateTemplateData($templateData); + $self->compileCss($templateData, $cssFileName); + + $templateData->footerLogo = @json_decode($templateData->footerLogo); + if ($templateData->footerLogo && $templateData->footerLogo->id) { + $image = org_glizy_helpers_Media::getImageById($templateData->footerLogo->id); + if ($templateData->footerLogoLink) { + $image = __Link::formatLink($templateData->footerLogoLink, $templateData->footerLogoTitle, $image); + } + $newTemplateData->footerLogo = $image; + } + + $newTemplateData->css = $templateData->css; + return $newTemplateData; + }); + + return $templateData; + } + + public function updateTemplateData(&$templateData) + { + $elements = explode(',', 'c-body-background,c-text,c-text-heading,c-color-link,c-color-link-hover,c-box-image-border,c-navigation-background,c-sidebar-link,c-sidebar-link-hover,c-languages-link,c-languages-link-hover,c-metanavigation-link,c-metanavigation-link-hover,c-slider-background,c-slider-text,c-box-border,c-box-background,c-box-header-link,c-box-text,c-icon-in-box,c-icon-in-box-background,c-color-border-button,c-color-arrow-button-slider,c-color-arrow-button-slider-hover,c-form-border,c-form-required,c-form-input-text,c-form-input-background,c-form-button-primary,c-form-button,c-form-button-text,c-timeline-theme,c-storyteller-background,c-storyteller-item-background,c-storyteller-border,c-storyteller-navigation-link,c-footer-border,c-footer-text,c-svg-path-stroke,c-svg-node-border,c-svg-main-node-background,c-svg-text-link,c-svg-text-node,c-svg-text-main-node,c-svg-node-background'); + $colors = explode(',', '#FFFFFF,#333333,#333333,#0099FF,#008ae6,#CCCCCC,#0099FF,#0099FF,#008ae6,#545453,#0099FF,#5E5E5D,#0099FF,#CCCCCC,#FFFFFF,#CCCCCC,#FFFFFF,#545453,#333333,#FFFFFF,#CCCCCC,#CCCCCC,#333333,0099FF,#CCCCCC,#CCCCCC,#333333,#FFFFFF,#0099FF,#0099FF,#FFFFFF,#0099FF,,#FFFFFF,#CCCCCC,#7A7A7A,#CCCCCC,#5E5E5D,#000000,#CFCED3,#D3D3D3,#CC3522,#000000,#000000,#FFFFFF'); + $numElements = count($elements); + + for ($i=0; $i<$numElements; $i++) { + if (!property_exists($templateData, $elements[$i])) { + $templateData->{$elements[$i]} = $colors[$i]; + } + } + } + + + public function compileCss(&$templateData, $cssFileName) + { + glz_importLib('lessphp/lessc.inc.php'); + $less = new lessc; + $less->setImportDir(array(__DIR__.'/less/')); + $css = file_get_contents(__DIR__.'/less/styles.less'); + $css = $this->applyCssVariables($templateData, $less, $css); + $css = $this->applyFont($templateData, $less, $css); + $css = $less->compile($css); + $css = $this->fixUrl($css); + $css = $this->addLogoAndCustomCss($templateData, $css); + file_put_contents($cssFileName, $css); + $templateData->css = '<link rel="stylesheet" href="'.$cssFileName.'" type="text/css" media="screen" />'; + } + + private function applyFont(&$templateData, $less, $css) + { + $font1 = $templateData->font1 == 'default' ? 'Titillium Web' : $templateData->font1; + $font2 = $templateData->font2 == 'default' ? 'PT Sans' : $templateData->font2; + + $fonts = '@import url(http://fonts.googleapis.com/css?family='.str_replace(' ', '+', $font1).':400,700,600);'.PHP_EOL. + '@font-1: \''.$font1.'\', sans-serif;'.PHP_EOL. + '@import url(http://fonts.googleapis.com/css?family='.str_replace(' ', '+', $font2).':400,700);'.PHP_EOL. + '@font-2: \''.$font2.'\', sans-serif;'.PHP_EOL; + return $css.PHP_EOL.$fonts; + } + + private function fixUrl($css) + { + $css = str_replace( + array('../img/', '../font/'), + array('../static/movio/templates/'.self::TEMPLATE_NAME.'/img/', '../static/movio/templates/'.self::TEMPLATE_NAME.'/font/'), + $css); + return $css; + } + + private function addLogoAndCustomCss(&$templateData, $css) + { + $templateData->headerLogo = @json_decode($templateData->headerLogo); + if ($templateData->headerLogo) { + $image = org_glizycms_mediaArchive_MediaManager::getMediaById($templateData->headerLogo->id); + $fileName = $image->getFileName(); + $sizes = $image->getOriginalSizes(); + + $templateData->customCss .= <<<EOD +header .site-logo { + background: url("../{$fileName}") no-repeat ; + width: {$sizes['width']}px; + height: {$sizes['height']}px; +} +EOD; + } + + $css .= PHP_EOL.$templateData->customCss; + return $css; + } + + private function applyCssVariables(&$templateData, $less, $css) + { + $variables = array(); + foreach ($templateData as $k=>$v) { + if (strpos($k, 'c-')===0) { + if (strlen($v)==0) { + $v = 'transparent'; + } + else if (strlen($v)!=7) { + $v = '#000000'; + } + $variables[$k] = $v; + } + } + $less->setVariables($variables); + + if ($templateData->{'c-body-background'}) + { + $css .= <<<EOD +body { + background: @c-body-background; +} +EOD; + } + + $css .= <<<EOD +@text: @c-text; +@text-heading: @c-text-heading; +@color-link: @c-color-link; +@color-link-hover: @c-color-link-hover; +@breadkcrumbs-link: @c-color-link; +@breadkcrumbs-link-hover: @c-color-link-hover; + +@navigation-background: @c-navigation-background; +@sidebar-link: @c-sidebar-link; +@sidebar-link-hover: @c-sidebar-link-hover; +@languages-link: @c-languages-link; +@languages-link-hover: @c-languages-link-hover; +@metanavigation-link: @c-metanavigation-link; +@metanavigation-link-hover: @c-metanavigation-link-hover; + +@slider-background: @c-slider-background; +@slider-text: @c-slider-text; +@slider-bullet-background: @c-slider-text; +@slider-bullet-background-selected: darken(@c-slider-background, 5);; + +@icon-in-page:lighten(@text, 30); +@icon-in-box:@c-icon-in-box; +@icon-in-box-background:@c-icon-in-box-background; + +@box-image-border: @c-box-image-border; +@box-background: @c-box-background; +@box-border:@c-box-border; +@box-header-link:@c-box-header-link; +@box-relation-item-border:@c-box-image-border; +@box-text: @c-box-text; + +@color-border-button: @c-color-border-button; +@color-arrow-button-slider: @c-color-arrow-button-slider; +@color-arrow-button-slider-hover: @c-color-arrow-button-slider-hover; + +@form-border: @c-form-border; +@form-required: @c-form-required; +@form-button: @c-form-button; +@form-button-text: @c-form-button-text; +@form-button-primary: @c-form-button-primary; +@form-button-primary-text:@c-form-button-text; +@form-input-text:@c-form-input-text; +@form-input-background:@c-form-input-background; + +@timeline-theme: @c-timeline-theme; + +@storyteller-background: @c-storyteller-background; +@storyteller-icon: lighten(@c-text, 70); +@storyteller-border: @c-storyteller-border; +@storyteller-item-background: @c-storyteller-item-background; +@storyteller-comments-background: @c-storyteller-item-background; +@storyteller-link: @c-color-link; +@storyteller-link-hover: @color-link-hover; +@storyteller-navigation-link: @c-storyteller-navigation-link; +@storyteller-image-border: @c-box-image-border; + +@footer-border: @c-footer-border; +@footer-text: @c-footer-text; + +@svg-path-stroke:@c-svg-path-stroke; +@svg-main-node-background:@c-svg-main-node-background; +@svg-node-border:@c-svg-node-border; +@svg-text-link:@c-svg-text-link; +@svg-text-node:@c-svg-text-node; +@svg-text-main-node:@c-svg-text-main-node; +@svg-node-background:@c-svg-node-background; + +EOD; + return $css; + } + + + + public static function homeSliderImage($item) { + return 'background:url('.$item->image['src'].') no-repeat 0 0;'; + } +} \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/Template.xml b/src/static/movio/templates/Minimal-in-blue/Template.xml new file mode 100644 index 0000000..89a0c6f --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/Template.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:EmptyComponent + xmlns:m="movio.views.components.*"> + + <glz:Modifier target="navigation" attribute="editableRegion" value="menu" /> + <glz:Modifier target="navigation" attribute="drawAllChilds" value="true" /> + <glz:Modifier target="navigation" attribute="showOnlyChilds" value="false" reprocess="true"/> + + <glz:ConfigValue key="movio.thumb.entityList.width" action="set" value="242" /> + <glz:ConfigValue key="movio.thumb.entityList.height" action="set" value="135" /> + <glz:ConfigValue key="movio.thumb.entityList.crop" action="set" value="true" /> + <glz:ConfigValue key="movio.thumb.homeSlider.width" action="set" value="1200" /> + <glz:ConfigValue key="movio.thumb.homeSlider.height" action="set" value="290" /> + <glz:ConfigValue key="movio.thumb.homeSlider.crop" action="set" value="true" /> + +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/TemplateAdmin.xml b/src/static/movio/templates/Minimal-in-blue/TemplateAdmin.xml new file mode 100644 index 0000000..c87a84c --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/TemplateAdmin.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:EmptyComponent + xmlns:m="movio.views.components.*"> + +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/TemplateAdminGlobal.xml b/src/static/movio/templates/Minimal-in-blue/TemplateAdminGlobal.xml new file mode 100644 index 0000000..05aab78 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/TemplateAdminGlobal.xml @@ -0,0 +1,144 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:EmptyComponent + xmlns:m="movio.views.components.*"> + + <glz:Fieldset label="{i18n:Header logo}"> + <glz:Image id="headerLogo" label="{i18n:Logo}" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Footer logo}"> + <glz:Image id="footerLogo" label="{i18n:Additional logo}" /> + <glz:Input id="footerLogoLink" label="{i18n:Logo link}" /> + <glz:Input id="footerLogoTitle" label="{i18n:Logo title}" /> + </glz:Fieldset> + + <glz:List id="font1" label="{i18n:Font primary}"> + <glz:ListItem key="default" value="{i18n:Default}" /> + <glz:ListItem key="Alegreya" value="Alegreya" /> + <glz:ListItem key="Cinzel" value="Cinzel" /> + <glz:ListItem key="Inconsolata" value="Inconsolata" /> + <glz:ListItem key="Jacques Francois" value="Jacques Francois" /> + <glz:ListItem key="Karla" value="Karla" /> + <glz:ListItem key="Lato" value="Lato" /> + <glz:ListItem key="Lora" value="Lora" /> + <glz:ListItem key="Libre Baskerville" value="Libre Baskerville" /> + <glz:ListItem key="Merriweather" value="Merriweather" /> + <glz:ListItem key="Montserrat" value="Montserrat" /> + <glz:ListItem key="Muli" value="Muli" /> + <glz:ListItem key="Neuton" value="Neuton" /> + <glz:ListItem key="Open Sans" value="Open Sans" /> + <glz:ListItem key="Oswald" value="Oswald" /> + <glz:ListItem key="Playfair Display" value="Playfair Display" /> + <glz:ListItem key="PT Sans" value="PT Sans" /> + <glz:ListItem key="Quattrocento Sans" value="Quattrocento Sans" /> + <glz:ListItem key="Raleway" value="Raleway" /> + <glz:ListItem key="Roboto" value="Roboto" /> + <glz:ListItem key="Roboto Slab" value="Roboto Slab" /> + <glz:ListItem key="Scada" value="Scada" /> + <glz:ListItem key="Titillium Web" value="Titillium Web" /> + </glz:List> + <glz:List id="font2" label="{i18n:Font secondary}"> + <glz:ListItem key="default" value="{i18n:Default}" /> + <glz:ListItem key="Alegreya" value="Alegreya" /> + <glz:ListItem key="Cinzel" value="Cinzel" /> + <glz:ListItem key="Inconsolata" value="Inconsolata" /> + <glz:ListItem key="Jacques Francois" value="Jacques Francois" /> + <glz:ListItem key="Karla" value="Karla" /> + <glz:ListItem key="Lato" value="Lato" /> + <glz:ListItem key="Lora" value="Lora" /> + <glz:ListItem key="Libre Baskerville" value="Libre Baskerville" /> + <glz:ListItem key="Merriweather" value="Merriweather" /> + <glz:ListItem key="Montserrat" value="Montserrat" /> + <glz:ListItem key="Muli" value="Muli" /> + <glz:ListItem key="Neuton" value="Neuton" /> + <glz:ListItem key="Open Sans" value="Open Sans" /> + <glz:ListItem key="Oswald" value="Oswald" /> + <glz:ListItem key="Playfair Display" value="Playfair Display" /> + <glz:ListItem key="PT Sans" value="PT Sans" /> + <glz:ListItem key="Quattrocento Sans" value="Quattrocento Sans" /> + <glz:ListItem key="Raleway" value="Raleway" /> + <glz:ListItem key="Roboto" value="Roboto" /> + <glz:ListItem key="Roboto Slab" value="Roboto Slab" /> + <glz:ListItem key="Scada" value="Scada" /> + <glz:ListItem key="Titillium Web" value="Titillium Web" /> + </glz:List> + + <glz:Fieldset label="{i18n:Colors}"> + <glz:List label="{i18n:Preset}" data="type=valuesPreset;elements=c-body-background,c-text,c-text-heading,c-color-link,c-color-link-hover,c-box-image-border,c-navigation-background,c-sidebar-link,c-sidebar-link-hover,c-languages-link,c-languages-link-hover,c-metanavigation-link,c-metanavigation-link-hover,c-slider-background,c-slider-text,c-box-border,c-box-background,c-box-header-link,c-box-text,c-icon-in-box,c-icon-in-box-background,c-color-border-button,c-color-arrow-button-slider,c-color-arrow-button-slider-hover,c-form-border,c-form-required,c-form-input-text,c-form-input-background,c-form-button-primary,c-form-button,c-form-button-text,c-timeline-theme,c-storyteller-background,c-storyteller-item-background,c-storyteller-border,c-storyteller-navigation-link,c-footer-border,c-footer-text,c-svg-path-stroke,c-svg-node-border,c-svg-main-node-background,c-svg-text-link,c-svg-text-node,c-svg-text-main-node,c-svg-node-background"> + <glz:ListItem value="-" key="" /> + <glz:ListItem value="{i18n:Preset 1}" key="0" options="#FFFFFF,#333333,#333333,#0099FF,#008ae6,#CCCCCC,#0099FF,#0099FF,#008ae6,#545453,#0099FF,#5E5E5D,#0099FF,#CCCCCC,#FFFFFF,#CCCCCC,#FFFFFF,#545453,#333333,#FFFFFF,#CCCCCC,#CCCCCC,#333333,0099FF,#CCCCCC,#CCCCCC,#333333,#FFFFFF,#0099FF,#0099FF,#FFFFFF,#0099FF,,#FFFFFF,#CCCCCC,#7A7A7A,#CCCCCC,#5E5E5D,#000000,#CFCED3,#D3D3D3,#CC3522,#000000,#000000,#FFFFFF" /> + </glz:List> + + <glz:Fieldset label="{i18n:General}"> + <glz:Input id="c-body-background" label="{i18n:Background}" data="type=colorPicker" required="false" /> + <glz:Input id="c-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-text-heading" label="{i18n:Heading}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-link" label="{i18n:Link}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-link-hover" label="{i18n:Link Hover}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-image-border" label="{i18n:Image border}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Navigation}"> + <glz:Input id="c-navigation-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-sidebar-link" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-sidebar-link-hover" label="{i18n:Text Hover/Selected}" data="type=colorPicker" required="true" /> + <glz:Input id="c-languages-link" label="{i18n:Language Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-languages-link-hover" label="{i18n:Language Hover/Selected}" data="type=colorPicker" required="true" /> + <glz:Input id="c-metanavigation-link" label="{i18n:Metanavigation Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-metanavigation-link-hover" label="{i18n:Metanavigation Hover/Selected}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Slider Home}"> + <glz:Input id="c-slider-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-slider-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Box}"> + <glz:Input id="c-box-border" label="{i18n:Border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-header-link" label="{i18n:Title}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-icon-in-box" label="{i18n:Icon}" data="type=colorPicker" required="true" /> + <glz:Input id="c-icon-in-box-background" label="{i18n:Icon background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-border-button" label="{i18n:Collapsible button border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-arrow-button-slider" label="{i18n:Collapsible button icon}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-arrow-button-slider-hover" label="{i18n:Collapsible button icon hover}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Forms}"> + <glz:Input id="c-form-border" label="{i18n:Border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-required" label="{i18n:Border required}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-input-text" label="{i18n:Field text color}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-input-background" label="{i18n:Field background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-button-primary" label="{i18n:Primary button}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-button" label="{i18n:Secondary button}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-button-text" label="{i18n:Button text}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Tools}"> + <glz:Input id="c-timeline-theme" label="{i18n:Timeline theme}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-background" label="{i18n:Storyteller background}" data="type=colorPicker" required="false" /> + <glz:Input id="c-storyteller-item-background" label="{i18n:Storyteller background items}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-border" label="{i18n:Storyteller border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-navigation-link" label="{i18n:Storyteller link}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Graph}"> + <glz:Input id="c-svg-path-stroke" label="{i18n:Path color}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-node-border" label="{i18n:node border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-main-node-background" label="{i18n:Main node}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-text-link" label="{i18n:Link}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-text-node" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-text-main-node" label="{i18n:Text main node}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-node-background" label="{i18n:Node background}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Footer}"> + <glz:Input id="c-footer-border" label="{i18n:Border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-footer-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + </glz:Fieldset> + + + <glz:Input id="customCss" label="{i18n:Custom css}" size="90" type="multiline" rows="10" cols="70" /> +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/font/font-awesome/FontAwesome.otf b/src/static/movio/templates/Minimal-in-blue/font/font-awesome/FontAwesome.otf new file mode 100644 index 0000000000000000000000000000000000000000..8b0f54e47e1d356dcf1496942a50e228e0f1ee14 GIT binary patch literal 62856 zcmcfp2Y3_5)&LBzEbU6(wGF`%u_do$I-wUs=poc3^xzP>t859|l91%ydy%{4ZewH9 zLNU#OK%5)jlp7M#adH#VlN(Y<F$u{?9vQwfE1Qt_{_pd=&;NYS=VdizXU@#doO9;1 zWm9nQCd!k_qQun5m21`nQkq8_D9U>~MSVYG)7F`Dsts8mQIv>+ztD)dFw+9OVG%`1 zdML`ns?&x=Qnp|IfM+dm&(}ePcdqmf<on<ruZy!LIb*$T6eXQSQ4A9omShs;Z-z&d z18&9;7N>37+Ghm#p%f+FVKQ2*chjkzF#ZB~9w-bef!xGBr6D7h{6UGOP@t%*!8rhr zqTX&D_txFJckW8F88SgJ<w0uU4@wMm7c$bUyYMH?cE5n|O!yIHP}F8hln(_lBNJ6p zG$oOgO6Eejz@2(nsGUOjuTK9XXG%6(sO41PA46l&S)vMPA}p1Zf|&-wMg9~b4|gr( z{oxi`z%K_ScV0|AK#d>DOYW<usZrFtp?c=NdMUMqT02xPqr9kwp}Z%>Qiq1}9HpST zU`<34PZ)C!_3}_&M2)6kC53tq%16Wv<;B!kk^fL$a$g&o8ZTNrRL|U3FQqy}Aw%^t z%FjbIl=r0M9>Z`rYKq77t&gt{++@-k0@oM~*1+}p2(7`Q4V*n=HYq=vsI?g5v}-nP z3|{}}ibb1(*R0;YdDD}@+q7nj-e?F6nlWp}oWMD=X3yOms||yGW^I(#9B4HL0`>*2 zG{Pq6qjlCmi#Eba+D94TAv}p9V_D5%k=nR0b4*~E)oRv<#|upiMk~z0GGmR=Yz-V5 ze^pq5HgIj2Au?HKwVD>qoJsnJx#u=RZ=|+Tk5lVmJ2z1#N=q3aw}vu8YK7c-N>4=y zwHEjdq-Iky;2wVdD3u7c7HAy@>636rQ}I+R6-Jq%%_eFi6$}s_rB+ajpcD*stEugP zo136*FtrWZo1wQ}7%h+r0@$<Qo&)2|f!u6rF0_q>R$<VJjBbYCD4|y%%+3fkR!S#4 zSqUW*l?*NPFbAD5chV;Ua>MYWppE&yKBVk^ODoieQIXI-PMCWPv<icsq+U;j!#n*2 z#Q?oXiL8nRW=qz>3^jr9p7*cDDu9q6%xx{?3;;b@n3omixrmwx*YNmZf9p3xm@i;8 zp?TpJjUB@J0D^@;Vq@WEgcj}}s2gf=U*-SLs=qz||El20$!O-RlsfnS_J9)6lK^rf z@F|+|fem;DctSVzuQ6lCs>g=*`}C{(m-TP#-`gM6ukSbXXY`l%AL#GuKiB_u|L6U` z^xwJVb4z_|(yht2X53nKYvZlGw+y#3Zk69U@CS95u-8E9*x%q${UiIw^e^w<+#lK> z-M_Ej)SuN~+27uOroXrU-Tp88`)^UVM&1epcn{s0b!+*p&9_2tnQmp>swD94ennAt zcir7`_tDR9d~W}I%Sf-0+(^%nvXRn}u#+RjBRxinMp7g0j<_@8_K4p{{5Im&i2f13 zj`+pr(-A+9_-Vw=5kHRjVZ`?%z8i6aJ1^|@`u}w?=l`!y{<jB&`-*|PdWf?qlc*QY zmn<rQ&VrMWqC&{2^gnO%Y^ZJzK}2XjTo&@AEVP02{%6o98R`wBPPi#|KLUfahdLz< zc~X{UQFDgd2xAP@59i7Fk}RSBa?*|viv&`VAD-V39H_f{SAYx80Peju<oG3Ugmy#u zq4&D?KKII`AG9HThEt(0sfU~7@4?HWQiS&zYJ2~4#^df?NftE^?sx*{|9CGK+Ce{n zHBT7V-Pe1#KdBpjZ;~G_508DX&oGQE_q>JYkcahKF7zYy(4XAHaLAh7>kswf;WDJ8 zodnW*&mk}LA4<ubgqyloKaK3wa2o=9c&!8&PzL$tF3I16Io$q#rdgDNv>ATyzs;HS z&jMIk)X1SUY8WQ8mk8qz!5gX{ac?|#KNXah-`{R{t;jx;+arrw4mTM?C=b`)g9B|K zKbe$=Z!xqbc>xxr!#G3cIJ_43-sk>0XiMsaXE3e+56S@N-W&nebhy1GS=0t{!`!CB zeXl$`20SDCO)=z#yl@A)%foXM<_FJ&aY(!S?qN9ajLc&>wDpF%>BD`=97%ujZX|^{ zkUJb;(Bvllh3Ak$Tkm1o9O@S+z@h#=rtsbr<wc%JvfR%|ooFZzaLHWfk(AVvv4!y= zC3XMXJ=_k`>Eayd0}DguL&kx00m+ja=Bpt$)C)Jj(+GE#@N5{qN_YooPx`~Xe7HP3 z{%{$_+eqqQIN>I3Ngv^P)=&zdhx-v8M)G7X!|w&{r;s|*7v>g7Gy(!cXqP3lRov@8 zR1fWh=MwT9Zqok0{>Y@@?`{gwSN{7?L`gvE7m2*?lX6LUm1893w2Pdz9?n{^!(W2e zdWpaFl9b@u0BLprBcj#q)KgjW@7iqlGG5Yvz*k2E1b+8G7f(?i1&<P?5`}^sNe_Su zp{B-C(?AvsqLxt0KzdwDZ2-w}Hx&Ysl@6q}{UBAPQ`uA*RZBHf?bHeCEcG1KOT9u} zq28xHrM{#3sXwVf5oiP=nP{X)AySDnqH&^!L_wluqQ^wRq7YH6$RtV?6^d#_Eus$5 zNzpmc1<_^Ei=tOVS41C(z83u``bG4+2#M}^upXm5R34K&f;^Ubto3-(V~0nShtVV1 zqrjuWqtT<&qs!xhN3X~09(^8Pdh~nT_HcN(#1gT$*k7y`PZUoR&lN8euM}?*Zxcs| zjp7t>vA9XxDLyUk5nmBs6~80?xA;He-^DJ8RN^C1NybWMO6ExxOV&s>OP-SKlxQUu zNxCEtRJdwMgQQb(MDmQ}tmIiqujCEMHOY0!H<H^lLo4Ws^i+B_J)d4euckNAPtzf^ zj*g@E(+PAMok{1?WpowYOn1<S=p*!bx`+NJ{V)0|-A8{-|3(io9*h?wXVlC?%q%8| zS<0+pHZ$9q-Aov>kBMipnS7>{u``WKCv$?i#JtM9$^4u7g87d5nYqQ>kup*r>4Q>U zI$1hRI!8KRx>mYFs*@&5bEW0dI%&J~sPvTdy!1usRp|%PFQwl}f0q6xb;-PBD%k|t zY}tI-V%aj;YS{+aQ?dwIjLaxYk`>BoWsR~9*)iEk*+tn)va7OpWS_{smHjSrdP+V0 zJk_4#J?D9@_1xwe?HTK7@=Wl|@+|Uf_B`o%#`BWri=J<Je&qS3=Z~JZJqKA4%dw+a zB|DLw!cJ#rv2)q^>_T=4`v|*&UBhl-L)Zv5p0%+J>@(~s_AL7X`wDx7eUJT&{SSMK z9pETV%t<)~r{X4Z^SBk<7A}m7;^H_fm&|2x`CJ88%QbUt++pq*cal5LUErSMUf^El zUgJLCKIVSme)FQdBwi!E<X&UECU`yMHQj5r*F3L<UQ4|m_1fvBjgAeoSmNR>`Us0Q z%p9T98WOazMw1pS4`!>y8fGSUh&Ik-O^&x{%~AT;IIAusHq0EYwdzPtZ?PI<%-T3( zf;Poyj0@2lgv1zcHAY2Q^wEZ}*a%}ZXpR=04ir-WpbZI&wOaLYTC*`MGSZl6h=r8Y z4d>%cq(*NDHzt{4!;(WH^yY|Ityyc*hFL*fHES(8GA!v5YmA7AiVce<mJ^fCXwX^` zjIr@?+7K9gC`X_UW#diz%@M{(Z8*FsB-XHK_-6?>8e_;!6kC&7Z?Hyy8O0n%G}drq zY^2^A7ORi2YLl!XIxW$Sg>0fe(yD_8(T0#%Z4_w&Inczd&{N0@YP37MFWzF+M<tUv z>kX06M(8q>71~9GMQF*2ge2%AwMG*R7f)W-5CO{_W(pxQ1Gtd{5P-01VNw=dm{|+^ z6%j+0-eT37Lc+r$ViLp5kx^l=IKzeEl&qvF4E7NA%LH2ey@o@10m4vTyAQN~fSq7A zx?gWNFHF`H8*d3AI~%7r4CUPWFH{<1gk*m_3<L%Qp`bTJ8HJ1`!mI^rh0X~3NTxls zwa~}C$KheHh{A4%na##T_tFYE_i_r^c$51f*;ru}2qFMd=u@;IQSq^{Ls?5)SZu5| zDIzv3F6`b+qV-W$uzN&B>0u(tfF`iWB#nqQTC}hv2E8F#m?<omK^qYkt2IQzXkf@N z#zh$8;$ZXQ!lDh@d#e*~8eSVR9kbS&sMW&W7)>SuDFTQn3UEkkc8@TWC!-F{GC^ww z>q*$~q;*EKK82V{VgW}(B4CfL)<iv^oLQI^!4rb2LcxuuAuy)d7^6)FDzgkt(PGub z$Aw!$;!OgnxeH`|q$m(Hpl*~v;%?F=y9pE<t2e{|Zn-zj6mQYNO90+$%|OIJ>4q56 z4)D)xH0hF~^)O1fFcUYy3iJruY7hufKutIFVd8R^gr`Ecp*I_TDL24)U<VN~fG2?C zWc?z|7K<)2G8{G*7RL~-jg5^UYZe8oX4UFoXF>$r5ORbRg-pCjNXR?8@hRjlg!)^B z(D!dOu%iM74)q`)qGOHW+C($Zqs|&;iLn3^gGC89>$Oo4U_&EF=f-R>g=zQ41JxU% z^ai~(IaX`22o=$0BP<fEARt<NWVkjA=s6<Z8Ugk;Q<zCW5536(Ml-U)A>n|0z*CK8 zK%DqkW2^;?Z85-a0Z6ni9$1JOKmq#-j|FR7G;j-Zd_)ZF6-)}K?p{V%<Y=QY8d&Z< zqP?#STLowXY{VKOER>Lg*B4T<l<u5+i3nRYSS(=UBe&2&$ixFKyN?WE|A#OLCTWb- zMu){l0^bie!Zr?}CTTQ`r6dm=)@spP;XO=%vS!%bFcYvZE$~nsFtPa9a3EpW%V@2z za>BUeba0p4h(`{lkhn<bWz`vh225H@ydEZR(GqNNj~ErD)kYbOk;3^SaBwnsydL<w zAsTv_2%8U!g8{<~5!yIyWQ^V#MdkpY_i3%+TCG_ptY_4$C~c%M9+o}?W(B`wq5f7O ztk>Ua;!S@mlEwb3uRAAna%X|R34lqnNUbFX_%$pF{0bXxjWdRmGt^CFZcG*MWq&*% zpD-JDPJjsSWiSA$4WFQ~!(<C@e?Ma)i*z4zB1LTy%tJVrBaCEMEW){MiG#tTfHxcB zw7O_GC{1CJz<h))CI_(qh@=Aj13pH=3c^7_qyWHMttmDcngB)vdm~K9%@cs+-8@>L z(g@%$q;&`!M=`(;0H;FcJiPEeUTy)bGXu%#O;$^MxH}UvXTe-kd`b#g8@(3xP*30x znc%M+5eqCjy*4&-n6<mdC&xhua5}(+c)dlZg>xnX2oC%!5s^Uj?t@SuO@S=#uW(bx z{WX6b2|^FDjXG;w?7RqzWiB8Wa4|QJBTGftngtFZz*C@qy(Q$Y1K?iO@DUL*ch+1% z9wK1j&>$1McLEb&Zk8+5#cF{jf&aTxfx3yPAYib-S%s<1oju2WfRYkWB~Tuak9)I+ z(-1(skh!xT*2bHo!{JN-dNJ<<FF|~Gj5#sf8bJu^9#IJ#A)M?m@ZWIYD|6>8yjM5m zG60rH7zk-~uZGNixK`kLe=CruA#>*j!96b-j;Z)?t?(j4`6Spia^GJE{4Ojx680Zt zNWe8%t069;H$XAk92OS^LR}2VREDV856=$Q!%mO|6<}C_6UCa{zd}W<5upDiblg`Y z4Cvl7f*bc0-6U;-JxByu&zNWdaxxqBk$}(fNs-__0UlzBNj3priZ@%}*dQl4?7A@u zxFO-}z(C>X2fT<kgv^~kpNQxB1Z{YHbV5v`Rv&JJ0}1|x%zb!{@QQ%IZcYg`LGIZO zpJcFpWODFeexwnO)u989EbGGy5<u_-@l2RN$lL|9+((7GXoQM6aL<Js)_=h~xaY(D zFx(5^Uig1;Mv2A|_1Y7BU6a5869!7Og{q>Os4u7+;J0*%HiJsMQxqoBiu59bC{I)* zIwpEv)GK;ZbY1kl=qJ%1q5%)ugY$R_l;6D`VIDe<SWtj(di*XPC4OAIL0m09B0ete z5}y;lEq-78kt9GePV%^9lVrPOH>j?~k_t(Uq#ab(*CcOB-jjSFxlRYtLG(g8nl{qO zbOHT5{ZCLqIVOM^&rD@zGV_^TOav3dn3%)Nr_5K(_smbsZ;XR+Nxh{3(y`L%(je&q z=^E)esaBdKO_%0LE2WLn1JX|EJJNqkKa+kfy&=6R{Z;m$EI>A1Hd!`RHd8iFwn+Af zOe@pN;$&u7o$Qe8l<aNU2eOZ4pUJ+K-S8B7(w-AM*LZIB+~XPL83RgXj;GDD(epXa ze|vr*sFF@r&Q4(Gu**Pc+zx7^l`UYaKy7ScJJ>VqKiD_fkJ-=Jui1W386V`Pb1S)E zZZ{Xs={O@7&!utMTpf3Udy%`wead~q-Q@bYKfGjKDz6z{L0&7o9`}0EYlm03m(I)J zmEe`?mG4#O)#laVb=0fN>w?#dUN3vS=Jl4>2VS3feeLyw*Uw(Rc{#l9deh#V_egJz z_ayH*-iy4Kd2jIE?ESR2*4ylz<z4Ju?cM0z=6%e&%e&kAlJ^VVFL}S?{i*kN-nYH6 z_gx>xhxHlZ<LjgGnd&poXQ|H$pC^1a`2_py@Y(C5_p$n<`egaoeCm8!d^&ti`JD5) z=+ooV`vyCf9|-;$^yqcWZhqYw{_19)yA#adxmW?$T+N-}@hsQD2GF5<`GA4;gKS1- zZf1d|AhSHfo{jo&pI?4;O;L@irl!2AT7#~kYc$88xkv%mTn$&q<KQ5cTfySK2|Vgs zz;g3hr`;7imvz{2@O&28uPXi;o8cTw@K5L`*Ah<g{*$k)YT#da^8I99?XZu&zlh|l z0{?-}!}SMA(RuU-T=!B^uSW85>~0u+4bSNe2Avwqk&^$DHRv=KS#CD3;S~8SQm|;x zN%uXOg<%H!6sOWpT07MECb~&~iaal%Kr~kA@W=0<cU=B1NU@M2NFDxYEDF2;t<>ly z{t+$Uxdi~XHN7!e%}J9R(_7UXGlAu{@LgPTdU`T9mC4D=%h61g=2Yj|)i)V?b+ui? zE#uW(1@DS-MfI`{o?I@T&abi;)~M_?7x@=n*uipt?Z;r>c-GlBp66Pcnp(J_b~W~k zJU4;W8IE;z9Xr-_5FpZ3`8gH2s@$By{Co|!66RIRN3*C1^>ST?V>+@U!LTF2up`?- zL$|?lw4^nqr~{nKnUu7&6b%lRrZlCsr~{Z@h76@~^htykcl!R`V4$yrCB3Hbq$w<b zk75zewKg`ka+6sfGzLklcy24qXe&^cxQa!=ia9KIRcXWf_UuKx+NS%@jt;eL_46N= zsBQnwe|ClXZOkIcsf%sZFSMOJ*e1h|9KdVeLYI|aJo9c(uR6DF|Hs{b$lh#2lP24g zEmz*Mzo~ljt(=rA8XKDQ%hg2nvt#xz%}tc`Y<p(S!%F--e(VYSNRpac#sW%cdCqAM zkhCl8JpKxQMdPMvyh}cXMNJHXawf}JQ{t0yG&tV1%T=<1HW$Wb#wn8<QtC6*4hsJ{ z&s9X1<dx*-Dfc&6jx{z^RyU{}PoXR>n746_@NOa-3Klzp2l^gn2VQjbAuo0?#JQLL z$Mz}bSE*b<%<3&$R%={A(pBfD{9}jO88R43TRRf@j!umu(~;H5a&uR%M853YmDj$} zIQyjET)Xy-no~>!4446Ue9XYDW$(ym^9NXsBiI!j&bBmH*VjYd5uCtsQXS7>`8HO> zDbN}`0?ouLy46Rz8=vn%p8Uqm@ezB}D0m6pght^=)w6thX?kgz2G3qG5zoOZl-P#$ z;62Eu9_V9|U>i5{jy^LBsJUYYou6NrldH_F$f?R#6Z}L^@PMpQjwrgSs={8Q<o2)$ zHWmgiWnl%Z923fOiZmWGh*`|zFX0-G#%J-a;3=#lm_e&~Qbu2*F9Ekv5Ub%9vFm2> zoOChE&E(fDVqJZ+_^S(9K%?|z4Qv@&$Gd<tVBid{B?wZ-5(lIR(#e3@NS@DgyICyf z6k1rSgHZK7@~%9fLSB7E1<z^nFa5jlO_jaQR@$g3YbdR)QdSo?7adWjSEp1ZRfg4X zX(=c*RX%+%yE6B1VO42wDVpS0gfPw36t%IK@U*HtczM+fAR3O41&0=~YL}e3z-nA_ z>6owP0l%>_y%&IxVx)<zdfg=UDucRE3S3<pZYuAPOQ!PNKlp9%YKluNr$}V+7!0KG zB2b3H)y-@Rz0j+1bi2CI9N@FPLF@o9%c6lGMb7j4{~7lTeiOav7x&Clhj-a!t|~{B z)Q1qehN~!S($p5&^J;P`^X=0PY(22GHMGUhR(7!JaILJov9zU4S^8?puO+ujua~^& zUz(9)%U6Y!&^F7ym@>7#jOLcGPC4#d!g42=Yrv!#JYwQRKph}ax;`_tIz`20);H(1 zsJH++i<8d1wvyoE7px2R-tQK>V~5{WU|KHT4=~~?>;J-zTfD!37u?D8Q>s%Z8#$yy z%h5wD_x>xdywB+ughWP$WMyPzRwT*3=TpiXGn-0FZKbMbDvnhisqR1g!-dcPCCh&K zU-?&5z+T@$$>=nPF5$IkC4LdF#0#)`=@RwFOYj1u#w%4&w-#zI;XGu*dusADPKoOm z8YZ0Itm0}4+W;2`1!=edNfwuq23(9Y^AiBwidZ$*g5<m!^`Sn%;c|k*Evg!OS$U17 zqqe!@u#%g_Um&PuM{@TKS-@>O$1LZ$6+E(!Uc|#A>nDKry|{>zcC#+K%kF13+aeB` z9VD9p6UpVd$^V7B9CH{zE9`mIIchS3J(9JvNG|5m;2dy7E#^4~49g)Y8pA2@Lg!dK zg2BOf!)Nnef3=~Zrna)izq+0-OJ%Z4GBT8|Rd_LG9C|4SxZ~=3jfW$p9$pYw$y_dg z$>JhlV>uJMiW^X%#R@E9a470Q>roqx9zaWQErSDbk~yp(uQ0DT&%cNvuP5iE^LQ+u z26PNWna=x2;dpDwYtF2PX<;eXb<CjS6zx~()~W-IEh@)trnNRbIbV~oj!w=`N>5R_ zZZpZ*jjdH0&h{xRQ82^3_v)+fai0dznTkb#fpNA>TZj!$wMBp(y(a5G+OcF=O-IX7 zI1yn7^P5|gEmh6+^=fi-zRxzcYPfTi=c-TFqDL>HS)ZW?kxW)_xu>W{<;ZnRK<Ch( z8Xt@0Eq-4o#~65yv9cUF3^@gm9oFIHaOp@2sF=hPoFo;n_<al~#p$c)^n#qsbmc`h zyE3~bUtL&LRa~tqFSnJJYdEQcN8WT}rM<pUiR9ASg4*0Fb#7HwSx%9Q!!kdvjaR#X z1Dkm+Gcz?mMU|3TRiCNh@M)Y3*J<ug9uC8bDp(3Q|D19Kw8yaNS+Krb5U>UuRK|0& z{yIfL1XJ`OLv>qeQ+d6Ac^h59<d^1`=Bn#=U&97^(2H~a2LopSVPeXX>pu}O!d{)1 zv*gVuu9H;FWrMuddxQ0v#UA3Pz#$I+SM%g3Mhc$GgAw6?7&+-zJQ9zbG>QEFIth(L zBY*uBja2)zlewX3ESktV<fu=~CBe*kV_7)fmb2X8&cU5<8srz{`2)L0R!0!BJA!^^ z<zHsNs&8P`14N_%_C=E91I9{gw!bAi)w*9f#QcF-kFvRG%7#|(kcAq7!sL)W1k__T zb3d?RE*&l98#!xzLR+S~pti24PF2Uz$;sJfv(j8^ZUq^OPHsJveMoiaP;D!q2VGy^ zT!ogf`I+?^pr5rYx9@YFL$lex=#Ntn;jEq)gtL{vc{^WIA*#Ko=zylGq@uW@sJy5Q zR+>ZS|5(mkM&oHz$Xv$b>E&ZkH^c3ZkKeyP{@`J>81Zl|K725KKL~og7cTUw&+r2C zUk9>oB)d(Z<z?(LAaaq-%8NO(Il^W>#5JNP*mUmDq4TywX6_8%+DKj@yYsN}P;F;x zs~Sy06X}*#uDQ7i4t1y4@e^&gBNN(#@|4_eym;lN^{dj7Q_?EUGMmj-qU3N8NR(vr zL5@U0AW!DyaDfW~n7L>qoU7ycb%~=uC}_($bO<ngGQ4jFA#7Ok|M8DgtY&bEa|(^; zLpnHxUOk4}ofM&uQP(F_SuDyu)+fWP0Kx-a3}jK^h|mo7ArNlyn0CM{fr$}D#x-QL z*%}(SPkAfv>;~RAg|+gl_}Tm%SPM9pFM`C+p(U`f$Ogj39`p#D49F9Oe2B)Y(1=eW zw)bneg>cL|gV(T-@p*5{tE=Jcu_#{Qxp*GXIvt3kkYHpQ3rMZzl>31_u>s6-4t1k$ z+%4rq9}T342VUdi$!t^dQ!_JRmu7%?geCz#$k7y78#|!3og3_v;<;Rny}YW5!%{qk zYr=}g#4>emYj$g9vy8LVs?h8`L_|TiBLNz~6T}mIn`7Q#x%%eXmYM^ywlbt>Y*KQW ztPgGNM5|#@Lho##(bo(L9oRr~qe#cANDc%f=kjIw`MHHTDlBJG(mA{ekB4g&=UR+@ z#y>k2b08anAWukZCeRZa(ch0ofCOX(Es0wN+K`%qt+#QuZ7_-y0m}#2?n`dsD*wD% zU9TxGD=jNm!ZzETgs?z(%&2dH6S29assTs?*$2o*DW}7G$(=zkCn=n0K=g91j%PTP zO^O&KdH%vD8V)3XPz7L>;2B8w07~qv;%G|;IoyGV`0yOvTG|Z!pBsQ#a448*<@V{7 zdf2gEhBIedl9SbV5}wF0Z(rH8R)gfF3J%|GPxzE<#INuQA;=Fuj>54gr^1)E;a_nA zo)4mW8(@oc8NVA2@UCNk;D%})%w{#z2H@ok=K_g?v+@cKVge`%egi3pAfR$7s)V8% zDeAC@I!=iS?|Kv_iSmi9WFEB;;){P5Rf%dKM4(>OC~6j+5}g+P=`qz~g~xw9Zi~l? z6U67mcO<+dT5?YEC%uhsrC(z<F?Q*jvT)fiU{470{DNJ_R<K`i%ef5D^-qGX{)G26 zpIDz{pUWc-jSPPv`~mF)&y1=ab<Ee_w@ThT+H3Uf2fO`Z{c8O#_<ikn+h6S;>|gAE zO*vJ0Soy8esY(oZgqQLER6n4etX{4*s1K;GsNYi~jhAMuW{;*_b1QI4;QGKH$2>CT zA7i<(=f?Sr+dQskyn1}e_?r{PPpF*GHsRt#zlr~zR50n=$@LGNnX+igA5%|F+cqs@ z+S}6~n7(}aZ!^p@%4hsObLz||W*(ijYF6oN<?Q$88s|0!b<g*lKX!iN{1+cy`S8Vu z@q(obzFFv6q+MLTWbTr%C1p!TEq#9J;Ih@rl9v7Fk;df{mLGp~*@{P3PF}Ta^^<F| z*IZxw=-RrqU#~CUz;0Nxp<u%g8*?}2Z!FwcylKhin$6#Cd30;Q);EGXpPKem&{G?p zYTWkB)7N%9y5rE!hj*UeW!^n~55ITD-rl`$?Y$l%3K<&$PTG*1kc!Z8p~u6fge$|J ziO@upMM@$~+DY2hsHUi2qE|%M=pNPmtY4%r(toyZ#lHP9nwU$mdt={<+ZXqK95w_R zo-)K5vJ7^^vxZ*`gGMjoX5&jHu_*?eLDi;{`*-e--2b7u-F(ARX{ol@EjO$Stijgb z<9|<RPdu9VucSFihmxlxrzU@%Qj~fy^^>$QX$5KDr7zAHmywn^Dl<Cs*(_r=oxL}^ zHv9D)Dras^UCxc%mvjHjTbUP@mzL+qUzq=8zN27fK}Er@g<}gl3kQpmicS`bi+2`x zm6X|(wl7Q5%N{IiDSy7=*@~AczOH<z(pcG1`JXCj)zqpVtIyUl_4^tgXn3j7*yv~~ zZH{QJXzp$KvK1XL9r&efL0eASyX~6xpAJsxn0%!2=s%BDJ!5^Q=lB!Hn~#5R;?t8c zC%aCWyNqW>pJ_O|<!sm4D`)Y!HRpDmmz?iBf2Vs>_m=Lh-A{Et-MyoGSNERokiok) zBnhB3NFqWKByj{Ii5OXtL=iv-I)VcRzH|jku>?yL&Y*4VU{JsS#rOmaeBcup%p(vg z?BW3W4M&OsA3!q@+*i8Vuj{V(uR|WXD@)op>iqEmJe@|bq0uaUO$x21Z|qu<pxfxb z4twY}wlBG&^G65p3}`iDqb^}d*GB)V*rRLX^@J;3@BmGxq1Q2BlchX*O$sfiU(sD} z@4DiD6?t@BNw~hT%io8vkKcG#kRym8HjF~Zx`IIPC3YqUWQhzy%o+}8AzjM)3})I; zpK}&^P9#V(&R}#>aWJ_xUXAmZ_~hhx4bGFsw<aG{qdewdYwJM`de`}>0wse^@d)0B zL-DjAP%<cWR&qsrO9oniAMh)vsVTCn>gua%Yc&7*ptG~HMb>n%yYV^Ir+quNu8Y~X zOsAO}fxX6IZ{=QTe4}1~-O+ORpvERWcIMrGol^hUixhq6Nu^Kwy$j!Uz@hXT4-9Ss z-^eat$rCh}7lHN*%g%HL&}$Su8|+c)fPpL~YD3OWLx-U)QRDO)^r8pth-2Z11unc6 zgng%-ae6tu=(e_wW5-~S1W_f(E39}MY+<0HH}t}`?3|LK9Q9xyw$l+A#;7pmon0@m z&K*)1ESq+ndV%!`g!5xSUcduLyEub)22bZfY4K@?Qx%R1r~Nu#$Db%*0|u7If<;f- zZs~|Wl!(S*4>TT2kOs?S>p%Q{+3%`Sh&B5C`;XrEP=ho`23o%ajYA%X+By!lcghCs z(t*>G`3tf5iS25v9E+7>u>TlY=(eddSF1{x5@z+(?=Ec9VE;d`68_zm&3^yMUl5~Q z0Git}{%n4T8P1e5L>?Gep2ptkLk#cJzMcm|(|{by6<_nIywA5V(E)G8Gcom+3bm`G z563%p(Fbx;4q8>~c*j#Xi_WWWENE06tM5GgA^R;KAldIYrnu%>=<-IpTt0YLpJO5Z z7ka_5=ykNkF$!&QjdCo4<9+{Y{}-4YM?Pfn-Sr?2iLE?(P=OM*p<nSObu4}mYw&is z9z>d0w2DX66fl@N?-1iD^%I(}!F>Y{#DE3uA#DGd2hEe5<#MzbG*8eJ9rAVS*a7>X z{S<r0p22qk`~aNQ1;#8VR5|1>`8p!61R*K0CV=3?EN|rl+Y>-AblM$u#nWsCFL|0B zfQG|)pZ4~I6JVA_-Cz?4mQ3W`hJitlTLhF*gLObK6@qDS+lA0x(4E2J0agpr&cu^; zCO{MD_+OBcSu~yntMX9y*I=$xBgAa|S3PuJ@wbLP?TrDFLn7oI!1w?W6b|fFfXJWR zs>T5*;3zvdesBW5jGjNr;s6}*4v+5OI|y>`@(7+gbxs`u84}+uPY@vw00iu76xufo z;xcky3)%Z&;>+Yhm+!$8%J?!scS9CB;mhtZ2z){+m9XdqJo!a-xeFw$i9EJ~O~`HB z##U^V3ifpbIY!5;!OjkR*D9R>68VYgd@_*MUtkE$$-fkUxcc07c}E{~7;XvDp<s)E z!A9|N6X-ao5Qxr-pGFhaTQ4li3VSkiYyF~^!(?dmLm%RY@O&li!YOcdk(3yv(EJb4 zLumBR>X)Cb|1|XFuvZq>JsB#)PveQe{;jxBiN^8{5K0jUrRqVzDg~18#Ciz@>FQUv zymy!<s^ZW@Kr;{{`%OW;QiHBf%-vu@?gf*73y=GH!IannriosDAh?CU1N9&uwg6@> z&*Od810Fl&u{>a&NYRqnoKmjF>yBohOh1`&!vECeGZ#-?l2ulhSKE~}#We+0>ac&U zetlbytST=DEOI$HMPT2?V*?FMarLpa{zkN(ZYfS}NLFDp%px<jP?NeT|B1YfvDvX1 zhBU1H)2}L*bkt)Np19AVAx4iJC78;q^3-Scp5A+ES87~FTy_lJX!J`f%1lmEVzV@* zKDDJtjn<iJ^^N;lV*K^HqeAq1WCeLe&^Na%w=z%t?3VX7^zM>@Hdbg?*+HWKXULd8 zkEK16c|6<yC|*yelr?9xs*ss!ZLDvu&@{hR^=9>z<F&^djx~WTi-JRi^gM-BXwr#J zO_lJ%P?KM+j(RToqQ0m3Sp73~C(wqYe$D0etxZb6>UdZ=x9l%!V#N--vs)1Y?7`7@ zUn0ko6}wEv0^s#bf$8Y;nt{g#<aZvE4h9WeQGi{zyrQP6s?;C7$5fWs^UDjL$DV!; zYs?xJzs{^ii|L-kP3O0%2<dN%*qNwVjTh7S^*#K}JL?(jac%ZDYG)tV*nU7B0QlzT zKnrl#fR<?oZs+J$l-bHk%G9oF4uk8O%Rm>G6c;O9Rxkp~37xp$cQT7Cj!TNVhT`^& zI&4Hw_&KKS<?+)}T!ccyy4KplbpC@8uA3QI#R+v8{;xk;nO{>_Q{rzgsVT3nbUx<z zz|Z-Z>jS!=s=ByFFeTQM)>Kqhz5aopk1G=ntHm(bZMG8dQ$BhNn1}_Fh1}7Nti)0c zsT@ogRyZ#PtP12$h;{@IwrJG15JZTZim@zu2-s#H3a(^DF9b*f!~-`SXB4TWX_;v% zT*RcM)i;-FDx{sz1Pp>3(E_#;_tAw?r_B|uIG=Ss?X=o8Z{QexDBE<<q{81pgC-nI zCzocV1ClOck~11xOEpa>7`o%{7?Ua9oUL)qyK{_Ai_VIOP#S7N&Z?ckpe>SiZNU9u zm_q=i4bJZ5(sVGj!PB!f7mo=XL{82L5inMgk&7V{T*SK~8Nwgw=%`(Z+g00lwVjUA zU=<3WUD{k?Dq6tekKu^y$hJ1`S7AGt=)v}92iHh2woB0rmiQX{&<vjV84k2o9?kCb z_u0X_O+UygUoddnal3;>w_)RM|6e?WpRxG1qwgX1Z!msyPF7Ub7d7P6Vlc}3fyKQX z{8za}`FR?A4PT@4^9plwl!99goGkcu9*=ILU}-~rO?{;X|K@0ah;2_8fQ@>SAE*Hu zm<Fp1csmV2@-9<WSz1+AiFA%UKj(G^>0Ehb1*Q3A1^#G9oZ@s=Z~7@U&T;h6C(|Pi z>r_B2x`_Sz(lt28)kCN2v$jPmT?xPQJ9rqtDh3Y{nDII?+Y{^5u5Q$qRByH=X89*( zW+qsbz#re{>&mNY!JH4q<+i%|_71QcjvmY20Be`s_Y9ba=Ca)^9*q@#$RFGQTd(6C zD%WBR767mVjOD@V9ovsqp^2K>2HSzmI?N+AtVd2c@Vk<n!h$>*_I(IXT8ZbX?y>VB zUjx`hNA3vvLF4-_R%7+suyd>U8$5c5_dOFpf9J3&TGE@)C^juSC%r(E5|OF3M9T2A z8F=ALyha5M-v?g!X1a!$w-VTSu>AxDq`vRwfu|HHXh4~<Xv;G6w8}xF=a3Ek`K6|` z%vN5eJOr!<Tx#$}G*aTRc<aY_yUIm__pJn@d75HdQL!?mF%3*yyO^e0dt;@h<$V3w z&T}#}?R&KFJG4dx13a*E?vENW?JQy1?L_3cce%|k1g}B%LAS@Ss82Ems1$xOV3LYd zQZf7^ACwPErhQ-=qI=PN*toxoi7wD18i~ga#t4S9Cs+(>0-SQeQgF!}1ZYz~VPn9c zflBaRv=`n3Qn*Usc#Ek45eF0^LSR7lb6Mh?HnDpSg`cyk1F(<aMGuhtCOy}2sQZ!< z#$UIV4Z%x+24|~c4V8^X&6^<njd&4?uvpW#uEV1=`!fvbmQ-0%dS;46IhZ1y!`IiA zSJkOMKx(x38VH4kZ*U-5uYw(Z;H4{w)*Nf<Xgs4N3|Dv!pb40Zyb@*(?^4G*)e6T< z*8}KR*VAx4fPZz(#G<w_=O?S%cA^dYXe>JR%Ob?7Vgyf{qpy_(zgvuS>Vj=cLo{pa z>7>`QufDBBFQFGv3;F@B7jX-I>9Oo}NgLE_GwF{*7W7V4osfp`C!~n`<x?a&ra>D{ zw)N2Ge`)&ziIhHfGEX#uH_&MpKf(LB?vesIuAl_mzgzL^#-FF3QCH;Vl;)~*24l45 z5hQEJ5XpdL?T;v<j~Tma?4=bo>L1Qt`RP}9%>a6BA^|X!|NjdB_-jxI_CZ_l=Idxa zYiv&H$kZH3Ka|;-Ec<2Ut6=@}QDUDhSUP#7+LCO}G^NX|nW;%e<re<5;1*IN=m`B$ zh?2m14X;DTaToFiV1}mD&U8&<ZgW9X?$NZPDTk9}peK6&gty{QB@UeeDHPTFlZ+|G zw6xsRg7jROB|R<Gpq#_oiOWe1@|ZUQfao=HuG@eZe387J{Tl^<-MpOj{lY=cP6d|7 zv&?{8BBXG}xhwA2@AxVlz99blN<kB-QINLapmfMb59J2s*sd4^`f$pbO5WXzC=`&x za>h5%56KxP0ZU4iv*KA7w1xTwa7;q_g#*D8$PI$hF$~8E;@fbZi2er?M%mste&UVe zXw>l^U;pv=3AlcE<A*oM-|;to`~iw@_-5YiePgsE#^%sFbjpMTTY}1^x4HJY^vd=& z+d<VErHWl_R<<o`Gh1)B)v12i&eqim=Gg5}fga=&ZS27|Tbl}v8hY}^U#V|9MGd#+ zeRuR`bsVs@gC%!6-!asMhrUoVYP&o013VF$Y}v!c#M)vvv%XnW?}_8K<El6I3{As# z%_Ee1DkTbs-safn(El}Wy=$LRfbFw^2aRn5p!n!F?|1!!(Et8V5!?Tv0hj+?y2H{4 z&W-eaR;wCbc^|Dib=dME@s<w70i0$7iR3~!43YD}VAJyjXg|>d7Zho235`~JX|gRb zKMD8VG5SSkg(gI)?#yI@*VMn7sL4H8YOkr6)!UoP8&pmwgM1I4LNhLF(2)Uk<K_Iz z`%n9KnZw$5s|L%Ml$3(P6isP4_C1}8`LGTCsa8v3VNy|YZAx)U{<er|mVIf7@!5IS z{M1@&aYDgv-5k@N?Bt~Mf+Sf%N^N{WQr6S@MR7Y)O$jN5mf}o%MoDUkr7*ELF<om5 zY2GUvcLs?T-BJzAWWM_5tuGI0&{3GgrM%1L)BbmQiaYoP*xmuWA#-d1{e#Gs%)-H1 z3V!CN*g%le07XA#MFctBD?u3lXkwE9ndA;UR5;-W2L-Vx2t4t~zOIQMeLLvuvFdfm z&h*ChY0s+hG&GGqt6lNTHq~GdSc<yWNyi2SjfDV=HK2Xrpnvh8Arl=8_N*OvRe&^0 zJP_=>4S`SY@Fxs`Oc(;0h69>rvKnWwBS-<;xgEr(x6DibxmxA2Gpm<A^|)EH9Yid6 zlE`ZA$fdvXYEbwe1N(_|KdT-L2K5}y(0lPl;QV-m1&Pfu8I2%Hxqd*a=-hRD^_dxG zXC7bNvBpsBx32_K<#>IW%yoQloTB&TirQB-&)3iy;JKCM^{C2fZQ!-8vmGcos@_>` zs?06jUahZ9Zjxoy<Tte`n`(|UJ*$2ZP3XGOa@Mh}*zY@>bQv>rMOIl>wlW*yIdawc z1=gI%9Q>fsugF}o-=uuC4DGI?OOHNR`nu}nH;VJ$(-gdSwdhq<X}ztcN?BigpzyFd zs!?x`sfa1J)}+_xR%RYZI~n&{!VBr=Onvb$rJmk@W#7k9H=}Qc{2cNd4s%%jvfAlw zjKypNx$@+o4rjYuNztkC8QK0BIZ;`gvb1@o{Ir7NC4Rv6u>6NdZ#d`u?6~~Z{9B`t z1-<VZ>wD7iVv{1TrJ$)^S%f-D(W5jPFReasvb;xyJU+{ge@XLF!sW1Y>t#pxHf&n1 zT#>nH|1Pz8XL!_BlgzYrRr(xN=<d4q9U9-*bZ3U5<dp4ji?a0RQsh<iUE$mQ#V2it zTb1^IUZ^;!Ld=)u9WQHM*>QBka^;w~<(os*A)DqVV3{f`x~wu*<2rlCTY(;`{I>jL zIg(cYQuReK+EM8DP0?Fb7i+$1ey6Rcv#0a&>5I>wJl%P&@mbk{muvs|59Qaf*EhbW z_U+#I{v1%Pj(mLjABWnTWxgjboH*Xqepc3gw(i1Z<%PWN^t0;pv+-Sq<A!JSha=k} z+Q3{@Eo)t~-o9D&D5Fm-&CSWq@fy3g#5FPlH{@3=xRQIeu&KoVRB=ZE>_cH?QCUG% zdPQ{U<|=F`!^+a9%Ut<>^NXIy4^bDT=A~pM$7F<O@5nV30ofK7Pxk}EXhDL=HeeUy zQIe+8ljSc|epLNx<+&2Hv)J#eoSyvJVp(xRZAqo7qS02?sVS|j0sdQYpuC~XUfxvR zR@xC&6<?lL8eI`l9a>vlUt%w-s(;S!0?Is#=3GHno8CWo>lpI)FKe$jT79zST+OkX zwj*_?YR}i6x1XsyQCHPo(E_mQ%IeFS(o1y3!G*H?$*YP&RM{3=S)>NP*O)ZkUffX9 zT;l&u;qy61(`3n|nI*aE+#T^)mAc-5XO|S1md4@P{+a8x;&v0(<c6l}lPv!GGqf2` zXXtYF=cg8=%=ZH$#RyaZf<pzKiALj*$a|Ed3ROC`zK?2=+;_?m-dB0zX3a-O56BwZ zzW<P~Fc;x~QtVmjTJBedcNXIDg|oWY^3xi76py}?mH<cbol$b2>YMUovWmkUrJ&Pu zXoQi+mlzyVO8Y8*2502splvA@57<9pE;b(RGHHC@z@yN7Q&))11UB+fcs{K&H5xCf zKDlFG%!H&Hbw@N1lr{f|?xO7oSi+$#0O~rDel$eo146*S?V*`hq6(0H%N<Ho@!0#m z*J19L@68?U|B#nen2SNm^i)=c(0FGtnY+4+tvIcziQ=Dj&;9znxqt4S`&O9y`;6;J zn0pV*o!%LMy%l&q8b#}l7}G<Pi|^P!kzO=5>P%`pACJ<RY$07He*{^&%XGByqVkgg z`(kOx(e$n(Y6RW7j@T~hj`;hm<z4dkiKTB6*!e)sw?kn73frLIev&l_tdOgCcf&jK zNnnm7?HqPRu+U-<s+@Atz+son`wNu2Gz@F#**#!Tp2Pn2<Fge&f^iC2760HNh*9{7 zAyWyUmn&jO)g@N=ftFx6cE|^;ij{0GF)XQZH|~buw;~e!R!)N7h=-X3T|&g`46wQ4 z;756(7rN~XRtV8z;Djczm!P}u28-8LIK#nKEmR6oMgerY%larU*jlSt5{h^@wZmGg zF3-&=%Z131{ESSEYm#dsjTTC$v4i(T;toP2t}}Q%j}}QClU$Q%cXSb)T*w<jJO+Xz z**X|Z?351#KLds#ms~-dBrdzlj)PDT?gOg?4z}{rn;^LfeqHc1NMD8%Fa{JO8#vUZ zwY&!EhK$8n9tk#+yQ2e%#P=t2;|9vanY3e-^J7JRaehI8+I7x#jxH#Gf+{1&-cVIm zRavQVoO7I`D=VR(YOv>IXr6*_&%wUIKAOx$>g;p&(WnhH6fYKMq71sza*elGHFyzT zNPIVF5n6Pb9n8$&3wSgMoXv3B$C6Mh1fewGk~#e>zp;A#;b65xG}uIkv|TbiuX_H{ zk&Epb2jy&{55H9X#uX)4CZOX@#Zq2#rw<$&plbvIOi;aXCP=0bJUn3c-RxUQ+%1X* z{>fL~SNpafs_Cq6Q#Z8rzSI7;tgaj)tW-6%1zF{q_Q!hHHYCdG6KgDHrSE2tnfv2@ z*#3!n`zLrG>Rg06WEV2S+hbHQ5ecCgnnkz+d`6wy7t4G@cPx&bJ`uY72A&*2kiR() z6bXoV6U+i~@qib)t=M{V>dOo`ML-S4(`fXOqhDdqDM`!8!N1|({Bm;AN^<Nu_R=PZ z0{IR7=4ZDzmD+P;pSW%)8glD0E7h5m8O7Pz>(==Jist4j@u&|VHkfH@Du$@Qy2AQ$ zyS=B!4<fT`i|dMO^XxelvX-cbng}p&Jj_oW2vQ6N4F=H|kW=amat6_87Mi6vbH?_1 z)EOc<`9+=CV2g^HIn$3|{deEdK7nW|F)T$p{|RpZ2EL1mh8*`i(hGBPQqz(%5_4o( z`FUBHO1$p_h~j0cD$B|$HD^1XYkL8lWaV`Y&C1ra#uPQgFhD?x*H~QhFpsjGg$gtR zNZuj$a|a#f<`fs@YOF%s5Dvyc(!s!o@fF;TccZyDzB*fzTLocQs)~xz(h5yOmA$dJ zF&3qCqA8z#FZ<8ODDYWiQlX$j{QhQZN4C1C#$H^bYH23n4@3`w7l94=fqx>Apu-Qm z??=AR!Q1>cw5nx=g{6hW@|2gSS+|amKUv#qsXH{+_oKfB=iXcIlJfGBa)=<j$oKTP zm)!rq)*PiepI4kXVS6Fw1o+83{9;b*u*Jj-ss>elxEVFOi~iUHd&I=pcASXucdT%& zI1%%L?ZgRx=S$9)Xz&P5Vg--jbHH8UD3D7bnD#I%oeT0z8Q3~q@{90U0|W>Iq7TOh z1NXBNgAP&M96-(t7<7ax5CV`lsF`;0Kr{)mF%V-31dg>2)dn!v5Y0Px-e3)^bLR_u zAk-tD0EPi=Wb4oq5)tMOdh~ZfmOf-|vv(;;YY^!I0+^8?SJRo`dC@ukP#kZu9gS@X z7<kv2;1}CsPSYvD2_V%SN;}@722TKSP%dA~y1@1bUQVzR+b6Sk<e(D#t!@=R)ba>R zCS-&8Ac`H_`5nyExf3wSe-KjId?+zTryShb!;;qltDAkOl@Z$Z084;cCoF^bIV@Ee zi3{;N-Umb2864mq;zq|m6=t(Nu}cM>#x8r?A+v@+MLw**Gn*WdKniw<k%W0p17qnF z7Hk~L1DMgG-hq8$XG)Z!XUAu@7hd@AL%*IL+h;ppaHTks{TwNd6nD{o`G-4t7TR|1 z^dAfy)a=}0TiCPHe;5Sv1Q-Kfz>(tq8euTdsi8Zq0<U~zIc-H_*$#`^k>W~rrMOat z%m0Qa9T0xxB&|C-8&94BV}cy@fj6lSv`8TpH^P5~fbH1MJPwr1O5YI>fq5L>0N%zO zpw)L380LDgt&xsGhe10dgc}3xt5^u(a<_ofE8Q_ik&>4J5mvKj)0vr&g(IvQf*&EM z=Wz@dRD$rSN=YG=v%iJN&b$_g?5u8v$WA1*LC~f?kA!<xw?O5$-$EQ;OEtvt<v|=D z0YaLQ*uLr(RZ9!0{B|~kCReAVC{yxCY!?}Zv?G<NDN4tKC;{eA;^0TwT3Fxq09xX_ zfEMzu^RDwlb4(Sc1Fph5Ft$6?l#G4j+jm)%fD;_k98=$AZ;)ZCU>H=1=V$Z2@4m*i z!)jf11|vI|n8CTKI0gr=6lqxSh(fRxsD;zUZFwYAz1w8iX;p%+pFb`A>8H=%KcT*I z^vK~Cl@~X6uZ!LX%cM?9PfXsuNtT-rdYCFNudJd#gZ+NZs4Z-@H~OP-Um>6O(8DSS zoDRl3UI$DI2g5tT@K!iGt*{MN6a;gygZes?bp@Y<Q+y|T6Kt059O~Q2yX-fmp**lo zEFX}QnFa|ng+o~G3IbpPBas942S`qV#1#r*XbfEALuE+R%wv%hkH0|T_e0TmsF}<@ z%c>!A_yRcap%RV1Aj6_&7Kx;2d?<pB7w~wfnFKWq`VNg_@i=BDior|KQXJDGL*oGC zI4O?V30BahJ8_H*kAt@3m>wJhEtaB~olpbt#z|334}xAjC<c118n(C(eCF5#Vdr28 zhfs6)`GWPw6Vb$5knrR}JjqVP6Cns42{o9+qa&z+h;-6})RHXpqEQT52cDgK*8Cc0 zG&z7K-0}nR#z*l{KRgM7F@e-4Oc-Kq2)w|D%n-PF$ltNZv4}=v761g|P8#_5cQ9Pg zfzAgN_$6F~iy<6bG~wjS^VH4)XFmPX{1X$gNO>m}zo^*y)xKLutVI8W?{JDyFB1Q@ zZ_8I|ht9Q2;aCbEKK)ESZ-CDnes(Q&ErZV-ejfVF;b+G(wNC)OE>Uz9__G-Nz3=RO zZ6z2L7<36;qB{jz2UcO}R4@MkgsPa&d5c9es2Nn#RuU84VO2XdgMo<WKm0e{*+Do1 zX$_w_T|$>>XE1Z^x!2y&xJLkH-3zbN3m%kH8KljihA<z?zDB)DACnGnmoKL+z=1lg zYKY9gOv5Zz?uFpKi|pFxHeDmGDhSBGL?7oZ>JNb<b)JA&LAPnkDM0FMAdCs@xyuu; zvyRuvCo)4LG(dQ428e?&aScs^xnnv77#8?Krn5r>-ug>0nsnuBd*6X?d6;)zd+r*T zW2CS(mmnq)+H`6@{E%?I6J&tp0rb`DATh%L%b^w|O)E&6u#ND-5T68qh?oB|I~X|p z2@cFJ@H7ifZHSfthPe--wSja<bhq6>qP6Yd#K)hyrfmUFjYbnTCJU^_5+x3N53hR# z%hh$(x|pT}S$1`GUZbk5zWG3NVQWdVrl`BPyIbklk4}H?SP7qr0PoF%gUtaaGMsqM zLWgx1?>y+dy%z!%qyh8|Q3L#d1ncPA3r`1b?*eB7@SU5^Ai{UTK*kTiV-(5hX({SM zd~#Y-s|GzOZEb1-=Sncs(wLU4DMm9C=_P4d;9uOpB&F3gYEqmc8a&F?73#_=d%0bO zOpM)LR8Xa<E-cT>QxY8$jL6_Ykc&_$lHY{ri9Qr?lgOz-=rM)PkfMXZbcU8L&C61U zPD*?Y2U(X+x>f4h?fg<fzFr}*Ag4N$GwO&cJCAl`--PPWZEC!YfzJ%)(G7K-t*2B% zn6$$S+t;wJ^^7~_+#QSl*aqWH(EH_hAyCyqx+ikO(Z^Kx2dHaY>lZ<A(=7g`ONjC! zU&w%q7M#wYO#wgt;shv~&OXHi7JM}`pTG~}$JM*`hV0rIBFoH3&r1e3!?CW`>c;v8 z4XQz@C<#qQf2!cj1MkmH#g|cl&Gf^j-P?oJ;GFSuJ$4<3t(D<3({U9}#P2J0<+>`p zx+3xLwwx_^=b~}Sgz9{Iih9qH1F>&>{Td2=L3RG-`qbw&u{VB6y{SUe(A4wqAe9D; z`f9Wr?Y)Yw${Ma#zj>8d_#v(fJp@s(pg{&fWG{s1xT8FPC^iG04cu0s8#oI-dO3!C z)ukmxrS$QQT{BkW8dtF1<*URuP!?W^j$vPQNohq19dkwZ{d=g!5q!$w3*la{n*$Ow zUgQWy<G~XIlnkz$NANMc9)F<19{|wx2r4u`0*@OF#)es+$RgGzEM20+!Y5$lgGgk% zp73!5klC!oV0sw!Bc3E1j0Am&#K2=_`gF{E#5?~3I_9BVaD%GRO91;@6o!!sBm6B6 z15UVJlbMifg<$;}h~Zb`mtatMfFQsDp>I(rdKs<P)VJ4k9D*6c{^bo%*zqFTqrj`K z0}ED-L-YQ7lH=Y5N2KgwHM;7!Gd!UgSo#r<?xL-Vy8PPgDu`R3{%W!+Gdn*!U-Q%y zx^DBvs!hZp`8p24ui%}UjKn;%MQN_KG$g9wdzQ!0!*~kXHdmINqJJt?nOT)xo3GAn z|8YyJs;;i8wo23U9~ABIMq0-RlKO+!v$9Ni#<f*(wCHHTQ8hm4DxuM%Z^0K9i_k`; zBN)pShx6Jq4yu=e0r>&+03P}IdMxon^wJ+EegJG^7B0Xxyc%CLKZ^bQ;6Uhr6Dl5U z*PMIqT+i`;$Qlk-w;v`8L*z602~b(lJVNvDvqSXW2=x9Z55$h2lomT!MMg<l_7J_- zHfT~Dd+4h2+UiO|?^Q$eo=@n#pgcEU8RIZ2y5mC+?^f*&-5(yW8MK2G8y{J^t0U4s zvg29HbE<7D^W3wY=Q=bU=SrWCKPMwN3vw}?0!KqA{8OyEii6foor;5Skl)~RG&j3E zvoJT$pE!>4@`|!bbNtJ)t8(lGj!JyO57)!Bt(Pt>F0vKDH>o6MXX+Gi=;uJYQV7SX zDF7jBiywIBDywp93TsRJOKtE~7}!oUH*Z3GK79S*zYT3e^>CeVRgw<&V*iqIh%Zr9 zSC>^(g0^$Bwx+V7sNNq3IoG3kXx`16S5eTqtNx(10=0Et1*sM6Fn;`rt0#cl1;ImD zSRpS5K1Zw^3dHeOM<bRUgm`}iaKLWdCxwbW@|`n8%mDsF3rFyvRY4jBJB8F;=J?@G z?zYa`1?;+57Imk?mw<w~1wKu1S_kjJb%SGBfX@NRJFNeseHdshAf7qlKEXO?44hY> zu@muwpA$d5brnd044QhC_)A~aod2Qw`<K6x4GavPS40CWDW19x{E6OMG!fIoX9Ula z;Rdt;t?NQBs6bMM?-z4Ge3iIcehg0gc3g+W8q1UBErzW!Ol@613;W+2<YQnF?Whik zHJz^<diB`LGDN-n#tr1JLUuTQn$mNI!u^CVo6w&w_!i5R3)ckl6*hv8Y`)<uE$yiX z%bpRmHqdEaWbrzz&j}61dibytPIBpstZN$jH|}w4acn{VMm>&c>N|F)9h5%!0F8W~ zOX7qE><;<;HLE}y1wH9Hs3Sy80@-H}q@3Y{UXUS<^Hw5*49O3md?gc|=`UFU{A{4D zfsjB9Qhx~vM5zLGEd^u)kVD*p1(97&Lo5)Q4r>Qeb258EQC(D1Sf$265MffCpAA7} zu0Bx7gPCP)Q$bU99Yk<~t)Ve9xh6@Kl$@ImT2Y@%PG@Hoq@^K<Fbala4CHfjLF5_u zYHBmYTRMUudN&v%n?YDVRCz8+4Kb7Od2C*JE+`0K!waUt?g3F^4uFG$XY*;5X|-7z zM4+bEx8@vB9RU3Sv?elcZCzy(M2Q8uy~vCCQMNi_L3Lx4ugNL@+b8t{?&7K^pIilB z$@rdxctkiv`qr`mcoXw{cF8AeAui}Pk3!+&-NCDLx?%USSa=6uOYlMRG^Vz#5rSMg zat;+9R1X|OKD4jyWJTxE6J&f6a|#i-LH$5h`*}Q~e<B*8hLDBF$Z7&lk^Vn~y$4`Z zRsTK?LWWU!l_c0E&AmkgSt6r=3|TT1WQPs1M=33(P4`My+N4dIr0L#^(H1CB1!V70 z2VzA<P<T-hQ4}qno17GX&q*q;@Av=x{r*Opb?><+=iYnHXFSjIS=0spgd563i}N>f zk6XpVsBFQsxjg;O?JtUpi3k7a-Q)VbjFx<d$WDE7jwjy<{-Tny;+h&2c=|v8CUZA$ z)1+o2NNcr`@A2LJ8|1aC<OQ{}RSXycb%1rws4H3^Sz*o9$sRkXmqh))#z^p^5OnrL zT96U!bV&0UA4tr&01wKZ1Wri52v{5IWWTVOE3@X5)PWd`LyY*b0<Rx?Un5OP9qk>T zvu)6pLrfF{lxH+gg0LQH5P-V>h`o9|_GVmVuA$1Ut2S;}6C%w{$x2C4(R#2LTireA zGXTz?AH*3;N=>Ee2jA~L^BMn|dECX&Z;-VqG#0AMi!9bMen9!STMt!W*k*AJ@r}uQ zOwxJ#0$W;D`|_L0>bXB)X}$J3c{4?dR8nb)ib(I>Bhm|}!`AHMjyMjLHP^%~-Mo6` zw)brZ^7oZWu@o)zM-Yj0asEV>kgepk&VHgHWG&VNHI`!fX8XTrvGZR*G;ak;<wY@> z_W2{SfrA;dl|CgNoxWurPdk&P60(Nu^~V4|r@17&e~&0W^3bDNU~(%E9)-op%uY-c z!!*o*9Hxl@^o{X&85^7#&^;#N47#r>34Hv6m?MO%%Dp&A&K~$gK==z0Z!KOreIzYJ zA#wr=C8jcPn25upDggj}Cvm6@vF=Xfc`&lY418P3?p#c^TJ*y6+{M}Iawy-Ig>1DK zY~u>H*|&zM-k0?pe*4j*+qWO>+>w@4$0gOJ?bxYe?;qVB-jj3QZPzMy(gsqpp^5YA zFX&!-O}Fjd=*mbQYb6XH(N}FJ(GedN384c>e;Q10bUcFbZU6}(KwzBws*Q6FYaiCZ zZ#>h|a>fHt=4mJiy?<X6S$X5tI(7BkyVX3x{}Hl`$itDual>OObZ6j8`8bz?L28{2 zw?jE)-rUJk=AOM;r}^|8;JYqI*Z+LN$?fbzkl5X$ltsyf3BcYCtWMdHv^{aV?~eVu z_U_y-&9MQ@s@g$iq|>$<&YF(d2q6oj0kB)y(C~t={B60uI#4%?j0yP(YC21tkd&N| z!6z;?Xbnq3Q^JzN5~<{SpB&GQAwU;D7aGMQZ2-R`&61Xr&NZyxwPDBF#4vqW>NfgX zxDR65@rf!rQ<9LESY+hLz;MUbg3zK+-;i~|8$#AgK|X~5LkN-i*M)PyeIgfQ&ov|Y zKxE(5B-QHcQhlqzLP;<e>5J54mbj=OuLx1%qt?^b<J)s<^J)u;WQb3OXUCnOBXrwd z!CS3nyIqx=X~Tpbv@f`6>w&`B{My_)@>-2gp*gR(Pz9{PZ%WcbGeJfMYUJa}R{xq( z!4Wm+0@+>hv3$}5nLGtwdB2d)!dJ|$Z2<q#=};np0W!PWmvokKvG6zmVo=VOkrDU) zKtN@rsv8tb$qS4OD<~exz@K@6tixsUHc<>BieX4oF0#rORpS2BDwoUT1t*y&<5l|L z6PbO#Ve63PCayBPXnBxIzSa7(#u8(Wjs~D<?7LLN(dTgeQ}LdC^eMi4!E1ZxtAm`1 z1~D4Fj@;$=bBFla`kMM3JAZz-nY`Nap_FK<C(x&HdIyX^DiJ8l2^usCl(LLGO*xKE z7Vo-LcHvXi#~J6gT;zUU`btwT78=ln^RM)4phIWRSife|s=$>}bToL~v?1%ZN$GZW z!(kqL9+nsmT)E>$aPm%m1+I3V)#N2Ly7HrVueeoKd$91>F;#VDO?nmAaHRC?IaN1U zZ&vT<U}Vl?WY%M3o+FBBPX=f9N%<F<K!&uk!5R7AgX3;hPMbCREsnN{>C^W|P??H8 zt(!nK+>8$!$*cVzZrvGPA673t_b$aqj8zAT<+D#>a3p8$?kzvX?;}qU@g5?BC5kU9 zNte%;U|{64t<grnWVrWq)$>-UaPaW-@T5p?cToA-<*J~B<&ohWw)w!cW5@;|KTS&P zdM@^C&=Jm7WvQuF;Sk3XkA)rN%thJ7MXHv_mUYKCt3-bAB$=I!*|QU!uBKhZbP#=E z{Sx{zpByqec&nOX;AWqEGK|~B`?q~EWY@agEBCD0xAy$>Ep+Iw{iNP-%OAfs{d|<K zzmRj`Bh{xd7lJQwWU`oz5l3(e3CDM9|BKOtfzE5iJm)96rOcAd(1@}m-6~^bjM?Lw zpoEb&la9;G<lJAn&$z!5&Wem?I+KheGgM?ZnRg!cb3dpD44-*|s|h)lRkKri=>!=I z%ex;^FJ#^vx*H}$k2uZ0HJ)?}>4_CsabMZA&Jc#Ys@R)F(Rw9Lnly(JKiTo73>MNq zq;8P#^nSs+0)*yGh>sxm?VNs(q>+3~)5-AR<@jg7zvM1>+fC`5PU709ONw3o%D0y+ z7|mswByTJ^_0cCMPF%l!bkVeIUby+#Unxi=_cmXCea8A#Yht<dcvEDQ%I!nrvLqJg z)0rP;sYqNOqxi_K(^tsz%#RoMrGdQrB?(D(#rkX9f3X>s;gSNn2s#9Pz3USvXoF>* z1qz5+X8?tr|2n`1gQ*WEI3#r%uqSZ+d-PuzdxCevO7{WvelUF<ye*-x_zM`Oah5`T zi5iP_R!L!DiJ3btM2UonutgqV77^N}GKeN^MUqcDO4d>a4`d{OX2>D4?1)DchD@fD zkx%dkAp|kmQ5vKI{Ml#3kIgO2u;~m?lEMpM-UP%pX}gRT#qSnQ+qz-D6$q_np!we% z#v?kG2bBWvH=AG#w*FfNQ__W`u+YjV21KEFU3k~oQ%RRJQ(xlui|RfS2y{pT?e^Yl zoa-{#q3lO}fkjxdhI{XB1CWzLfSViu(}yU&meJ<>;tZL)HC{G=GR2dFGCGgM(hcOp zc<#XBrr@#!>B(h9OJ=BM1i{H1Fk=7*NWK%0{1(am0WAXt1hurZ6dgNxgexm*+I8T# zlzdnWQp*O$sKYg~>3mgubySt5{$3Fhd@G5fmb|miIhNGRb505zc}JO(V|1k3puUlv zVK8KvQ|##wWHRMgrSb{-)fbf+_Ed`@!;qN;Vuv*?H#5f~&5~GivT_Y}>8uM%b55o; z-2&{m$(U)(uo!Ha)=Zn(Y?0OnDswC*yTN9#rXh)#k(r%lO}85C#+)1}!T?>BW?Q-) z$N&gO7?C!&r8$gJd2c<)gch?+dfA|~r&?1?TuPcDJ<V>&%jV_J>m7EhjX#&CG}$0P zV@ffmr)Q^Sg970&18-w9*`%(;t~pG_3l3q!?yMtxnd!T?G&{m;R=oLg7VQ$ITGp7= z0HX<~kKqLViyF`ZX25vy#L&qLUWauretq((&qI0l`2SD>mMinB4LhRCn7V~eVN$Fu zP8}EPK`3b5+K*vxxV7R}@zhr)XmR%Is!M9}cy<ODXb$ND@}ghYCgxcaZirX*0kIH8 zPed@g9wrK4O67Kc`A~#{lblPHh)*p=Y^G!o7xFsonl=>4h%WV1ykvRAQnh@pe{fv& z4*p=(dxuqWYvqlw>o-&+{ZrCN-X*Vc=MP?M_+-0u_wDcZ{HT^2{IRNumXT-n?|1B1 z=UB5$IlSCH!4a1o75#4VyDL-+@<Yp)aV2XV^k2&{Kbw^;dg7})2V=-TsUf9k@1eZI zhg5&8xk1I;y7kHH>C;qngg&E|n<mgMFK<}W8?E_|-7;dsv_(>?r_%!H$Fxa>!;Y#Q zJ9<UL>g6hQci^?554dATb{-)j(lvyL)qjwGIrcmNyA&2j9QlLX#>zGk0YGw8Y0t7} z+PSpKrBzXR^BU&X&u^5LYzx}8W!6yo_5yY2rrM%#o=*P_5TfpV$aHB!P1v68r^wsi zT~yTvH^kL(o6l@H7j!ncBI0PIU5a>aR+@U_l(_iK{L;vv`C;!$gXTofeoHlI-^ltA zT-B`Yb9QUn=r{!HR+Diroen%7dND$}<<__Be^h^bp}gTdf2j6ML*-FvabwA+ds(pZ zfy~tgkh^zYV6#uF7?F{H%UG1<8ZS<g_sWv}Tjow;P7#}Ez!}9(ezcFoJx1t1^w!W3 z?lJEEBEPQJT@FbBQ7n+nWBkAS%56!Dlf${UgK76=Q`K+H+Fm`Ar(3_KDI{eK*(%jt z3cdKT>dFz){i9u6Ud{1>I<?i7Wwi2T>7Ua+C0nKW(N#L#O8VmTb*iYcu)G-VbL#WM zVB#}Tnp{>JQ?dU;^5Q{tb#;WkoZk^g`b@ONNX>?<bOUB1XPH0aM0P&tC+>@cw$|lV z&JBAfW_sGk2aaE^xi)jdl+Z~D(#vy3?jNKE2l!>$n@$b0gjsPmDvM|;F6?1sv2^RQ zIPGi|?RvKFzvprb%}a_`)ksZQMw5yTAzf$>(l?k(3k}H#QAb9ZEm3?k?uKUuk(V;1 z0kjJRW^{l$G%VY)jeiZi*l`QV47KnB`AX0W<BPJ2Ohx?V!>7+4Y>~o`MOdo|%T7~g ztikuX2)V9J2nk6(w;zD`)Jvp^Mu}<N0PrW`cm#XL(Izsk{X=rk`5}pt>>^E~ZbSS; z*Zo|tkcpTS>s^~L9X82BTR}R4cv3St*PGj)R#a0_X1e$m*diS>$m?OMsKW65c8;8T z2qltca@XV1dl(1Eoof*~XJi8x{H;z{FSP9exv)nilVk%B2LX|SCB|DoZk;N_`j5Ha zfm4p<M|=y4ULFmPzn$I$aGoU|T@S?Jkbmijnd$tTdL%n#EOep74qIeGTfWBKCV?o8 z3(zDb1_ZV=yl(7fg)b;(cNO#HcFCYH_%CHF2^<7nGeqOzT@9owex!k=QX|ffIxa3< zujdnz(qdy&R4v(D8`=nt-?<QCpoX3FoOH8gdl*omYH?X9at3@sp{>+ZCKVh;WeoWp z!RedSOtNV<G1Hsm75aOb)MUysu~w6k_{5~NIJDYJvbk>SZX+jr6)3EAuWfXHB@Hz1 z*tT1Z%x77N9dMLF)@rHLlYr?8v#Bd{f!E2LX(Zsj_iYzfEdpHoG0XPApRP0j%oYmH zH372)r{QV58!G6OWQY(cDz%mumZ_c9;<EC@SolLj+>s(E!38L{r&g!da&(FCyXaHh zTSq6V+pEPB-&#5a39%*a-$kimsk%@VZH>T5DAQEB)a1F&9uXUySp`T0k{@LV^lE`2 z)43IDw=N!0st66~CZ0kgZqupf=+wI-NWS?J>DKd`AvZoHk~h9?2HX3Y1LW5basVP9 zQ)yo**yCs^M#IQ5Nb|UVQ_>=`oZ5(p+IL7vwS?Gr5E~-s_*B}>pE|w<1xf*0YgcA) zb+^h|zWy3{CmmLekB({(b8c4RO;#JZO1@Pg9MStcc@vM`bLbNKZ5zFcKtUEbn>}!p zZGeE@CEuw?1bqojhSYJ^d`n@WYLZO8n}rw>Es0jd(eU;o`W^ijy-SPeHf|?YHBcUY z)exx$>suGuI|zWULPQ5<G$L*G?di3?X|+)mVKzGFh|ftf%U+wdJ-W;{raaUhmPThS z^jSvcq<c2--DcmG784E5Der^i1@GO&H!M9WDm`o&o#R7ioeZ;wViVu!m^AEulFss> zbC$6U(!zYx@m+ZgR#f1G@P}<;3-h&yRYcXMlR3+L7SdU1o=tqqqPM5j+R3bwK1b*r zTUdEiU7Bxg`gVI+Ir1)?57IN7D50=CwOnnpXJ^~^T6;x>t@a3+<3naGME9|wFZ*d} zwF}8CA2R1it*xTMUh8Y~{4{B|)9fZ5g4hilQ#m<?bFr1pNm`|R@0HOSc~leZ)K=xx zIdi6R^joplA^jQNV^fDi`s}#nv@24AbUe<(n_fTk(bex;TlnU~`wlmrEUYZ3DyWiH z=N~819cr|9>srtNTrC5pzoQab;fOx*LftZPakKsXgDT($l>er~IP`$3R?+c;=JLVI z1J`U^Bi$S_ZTK?gH^FH_7yfoXFF)82agksD$D=KztGZQI*;IJI@}88uA%@nc6z-8f z&wl1HB8TrijVRaR_cE(h9`ZU)Kc*b{p2ZNI8;4W}8t*dcC_(EXhsv|dEoI#5YTenx zsv28OK_w^O`g&kP^nnjl4MiVR*0AxII_LbAPcB~g7-E`YdF1Pt2Yg5rs{7X(Zf!qC zMY;m6Kv$qEifCN8Z$<M8>7<scLmsIc;4}bqQp|>x-8rmP{Gw&kZa0ST8=C{0gFle| zICm8pPgQEhS_q(TthBExUc+O2aIMH-yl~)+Nh$kX_>Gp;g=;G}NYP;<Qp5?W8I>~* zEaC8zOa>91Zz8H*jAQmxTSL=B{HoWhE<R|wtcF*>Vq`3j^3St>Nh80zDn<t4h105( z-<^Zgs=(6orYfi%9`vIjS0}Y__$B)mHbxdk6hstAb@^0!e23~*!?pXI{D)ga@!^2W z2xdz@zHspqPX6nvE9d7-<>|K)IayU%^FdLA`hx?}fepwKVnEe6z~QsH)z!SEtlSJ~ z$L9`@rw}qxSe0ZZ?E;f?u94fn1iwd}5N|Rj@NzO|L*?4S)fSvu3Gv4ONTGAbVL)UE zVz_0J;x()6E7kOk0N60YsEUkV_2XRrgJ6v5MkzYe7;<~sG8Ju>u%5nx=sX((KqW6X zJ*c|K?fawt5$WoQPW;bH1;di#y$@)YrIV<PlNaoaj?T8k@T+z6bSu>1;kJTEJ}_u) z^m6s)mBkg?JU@AF6T54s&A#|ChY@*a`T(j>4+y$;YdaAgt1jTH3#tpMicU7-E@_sw zwtRo}k*Yx=|D?&OK*%B|6xm<}E=lxPfoPLg3Koi|I5P6v=niqTW1OA}YTNLTi@3Pq z!DSVGiT8Rc*ojLFcL;vzvf<M<hj6%c0+$C%2hFA9S5cLU4!Z+ue(ZZ6*h==ZVWS+P zKr+mMNWb8I@#k=OjPU-P!$rHxrRb8esMu7bZfU7JaE!N_MDo2&WWMPSq9X4w@2nKC zEa35r5T$%824FO|NsP4LT#@_`&{n{2$=`yk)ZoEHBV+ii!9VQK0D6p9XJj1!uMX4~ z+ea{o<%b?=7+$TTVFwz{kuUZWi4e;jg?1<uA<#BpXb|R;FZN3F4gTQ?=F9^`n@i@3 z+_?5NXprI!JLabzF^L}rGY}ZMMRIz`4>1T9JAemRW@W%KrRN}jqujjEH*af_w`GD! zLeWhkmhC`e<na$boRKkwioct*ngA>N@d85;c?QJO>>Spt9L=(xV;sbuabP_HIL-T` zC2wooCJCsBb3KFN>7F(FNn0GrJWYBNxzRy1Ao~`Vm6sMD#;yUR^Pr-vx<5;^t9Fw< zI15L}l*a2fQ>s4LQRg^Pk$WPtf=C_mo3HHFuhz)F#S_`?E>q^)kyOga&vaxYrby+# z;A4ov=A;=x&dA6}sf!Pci8V`eO=0obsuV*~R$5A`K0i7>Cp}STPfo~Biip)0Cudmo z$>}+e)=SGUXBQ+}Oj3g}Bg3G!Ch8MXQj=44shP%@*rc$AG--C$W>YqAPO@%_EKIhh z@5s#0EHGuI79_?S^YwPAr+a!^9Ng!4z21^pnvt5DWXd!o13qs{%-b3pZ<l80WEd@c zW>T6xJ;U2$c+|=1hQhFf@a#}&RN<y_J?Aj&GCFdKY{q<Rfwj<PE6#r3ym^x$CKH)- zW0KTpwPu6*VzF9Ow&aRTTY){PD8-y0O)wY6N2?P`wi?WQepFd%MV>S@GeU3Vl8w=o zIr*lH%*;$<azU&urNC$jZMK;c(zoU%+9UHbcW%pw$uy)z=1LQ+NqGtOILB5;dPRDP zxjdy<nwK6^k*F@v?XqO@`ogt)ax2W1h}?|qoaAi1HN}clx-B_BrZ~bFk(iNFo{^hY z7@cJ(lA57-fPbZ7ML7it`B|08MJa{xwnT@)vhi@CCCZTefu%s2Wz5P}<rJh{D#_NH zGPhf-=A7dAY$L+@xkd!f_4YJdrg?3h$&_O^+0(7k==i*y$rfOsEg3oI?%w$F{z+-J zEjKGyU1rRSFHA98GjcPnmfQlf-R#INH0NfdLw`0c*JR3szJuNonUtI%P0dI%q-GkB z@6X6)=j^6_S4n+QV?N^RX^ymXYnINOA<d7k$tyM;N>6$AWqWc~JfQB5#5|kBoKt4C zLEIt9o(T-WI!k%AJ-0R^*MN2g9M|Wk7wF@Y?WV>QL!#7Xu{v_q4wE@D$50ejb1cUg zW8V#AlRYy(JdqtZV~;*RIXfZ>Qpa)SiShVk+HQSHat1K=2?^2Jv1Yp|LTAii+5*N@ zW3pLqNG`QHwxpRVEu~o%Y2Fr!43)Ura%|<9He*40cA`a}6JHosnrksvK?)Sxytqf7 zYELQ4&CAU%w^)myV;YoMs>&<0m<qVO_=*BMmuEYY>_~T{??CX!>wb7{u-r6zd;(%Q zb;&X5_$@|Tjy)&G?l725`BgR(epg~ndQM7yW=@LK4so*Tbi1)U-xM#+$uV29RoMx) zxKcB;Aft_$TzX2pImM7^3Xim8CKg9##o}rMjWaDZBNaa{Gs6&LFy)!8`MIpaxQXe= z$DNfXt0^yAWhyDnHx=V%Vq~n+;(~(wf_zJLW|5&Lt2U!1JH6D51T;>z)sAG49XyXb zTV-`YLS9l>Vxc}KH=`gox1=mTs>D!gu%#F3Gjb~I=4@$sPOiQ%xhT0R%@~zuv}Hmi zJ|iCyu-E$2ZqukHoZ0wEe&V3cm44zt&~92LX`DX7>q`3KiI>_Ikr&(FXn(_pW$+&% zPp8p1$2rG|oZW<J%8I1os3;mw`$TW%=z>2*U~mEk`G&}0v*+il3ep|PcCLBWz^X~= zbeR{?1gV0#WITwLQ!n%R4F%1OK-O4fojrUR7aT~IEJWV$u>)yb7AEy171>LcO(cr; zR%N)%>FC<=2O$xv&}nW!#3s(K>sKAJ8E{a=Oe!PUo$TX|m6S8NaajjR#~CXTl7-~I zr8AHgvNAm`rpg7Em>HJ}Kde{7a4Z1_cPiRJs1AU-Cp4{F8vxyH4{+<CZPo68r$-%? zGBMzRZJ_PYHpqTXlDS(mG;q+`7=y>Hu*oC<7W#?0xT2I0<9ZouT}fIhTo|C$-CFTB zU0irFpRBWPg-e02eSp})1OGvj+tbBr-x`k+NQeFdNE9_7QP{mC3Ol4p*_On!7xu*K ziyHE(jJ@z-&3L{+!%TgGMFyda%v3IM9OOSc^v;;7m92wuD|`>1YSFcj?|)ELnX4>S zT>Pq)sVk_u*R4o3m0M`-Xxio8vR`?k5`X;ly+eOkq^>jVFFaAw3Pcp0r_1qpp74QC z()zPM3GfJM1^mf$v>rq7y?r8L=59q0g4Z-cdBZ|#0iBENHG-<uD^}(fui`Bc=7<Q@ z;E*AUCUAdb-h21sF;X1v*Lz2RdjV_W(L^ZQz!hCU7x;-+Jr2N&;ojg!_Yz>VwcZcs z)1hR(d{QTQN+&;26TEgZUL%T)2}=o6gGo>ZtkxQ`mMOm0)~a?DR99ATn;UnmJFb31 zCV!#R@pU^kH*%E~)%iQ2Xqy~U#*=k)ov17(FMOM-eZF&nGB`;W8O1ej-nxIWnt82@ z_it_7%tuD)l0!P$$Fb=;vhKD9NzT6;Swq*dMxdJOlD98Vei`za_B6+~5}jHwao2eD z*oi^&wfwL<qBEx(u3cAs5z@Ng6zA!ve4zgHf=Ro^spWq9@smOpEZ~`xr)a^#EfdG9 z#_fFbw3hR9alxt2gTGK;|GeSMY5vYI(R^*tgt01lRj2VgC!JcrLELk#NPDU^_)9e! z{GxT|sZ%^~hkZn+PS$_^1q^5}2t*GMh@Jtgrc*iMG~*6%bq9(+I1b_Z8FO{(R&r$a zI4CZ>NH=?g>*KQ_%`$LuPx>02)`435k8r&|i!pVE%qzRGfK4EGl<q9&ZjsQdMe;Rp z@okzGcQ3I!t9`eKJ~QEDf6`N(s1cK%Cx0f-OyJuqoPo-UdQp=^=tUInUXl%xiY=tp zJyF!YT<lT23eZO)aT0)pN)|#itt6m(HW`Kh!LaNW;0@$kCxAk(fDJxW^R<SYoS_tQ zgqO++9aY9k-^{AS^5{IOXz{V8B%71fdVQuLg>Rqgevv-)QHB|hY+pxxPGe?c%I{Mj z(5J3QPmSoe>s9rT@u7?6^Ya#kjJLnx=zXOx={!Zc;MRlSd+IaC^D7SWHdaw0ophVz zBTwx_yG=?-PfJTr@vT_7IDfwS)xN<CMgVy+WoqA)-f3^_9DjD9bn%%lLcdqbXLq{y z%dS(mc=FVzSAKE)ZfVSDOsUVw&N1hh$x|QsIMFeY!NIhb^RRY6WLVKso>y3IsRFGx zr7EUS>PMG5`zXV=tw~y;me+KeHKk(zES`4yWc_a!&q!<PnhOrAFI<gUcabNZrtRx9 zYrb?udxCP^tjSTc)$-?0u2@r0vyGp1X5Vk5(<jpX7eB4Is6O1B6kf+)oWH&g?KDkF zrV36aG&0QQY>UM=*KW(r&8@5RxxPFhRTPz!2)P|SfE{$Sk_HUeR+pNao|~HMn`t&? z8!aihJ_w?Th=_3j;U3Ls*ST9oLYo`J$m`^5D-?k&Ilg2H;e=B6Kuk>3u?F)oPAi*| zVID(ErQ?m~wfsSopSUtn16rkc-I7?{I-cBsr#c7IZ-98=#4Q^(@a}<VXv2mr6Bnx5 zAxwZhgl5`&o`p8CRWl7#${$>TX#EKZz2_XS^t=*Mfh+Lt0|b$SfxsYJDFlGY6(B(i zPQ~LkCDS_qEKE)Yd%u#fHRyRFclCf&h=n}gIS0KqVHGPNa$NE8WPtL{hFkAk;*huf zN_1e|g6jEd`qc2@^eJt%_P{z`7~~!V8Y`5v)Rkw?R^mC`#=8dzgGBKq$(2>A{X2K; ztEx(gFG1+i{S_n>Y8Po$Bi?yu#Dayj`_^;qrOq<ZvLjnR{6qy+@uv{8d+C!8gO?xS zgx}qNc-nQSE6<$yyWNKfJAO8)UvqCYuuEgW0NK>%y?$5U<eg>hrJ|XaZmqwg2KDe6 zJO=YXLO{X>CqO`|kw5{0-Nfv{)E@*mw~#YIS{Z{hN!E^K&mBM&?0$D+yaf*+TvD+= zE}@7gyXkIGVPff;Xw_qd#O-h)a7wk_xGBPjPh*u0Qg+BhG?K;+nFvhnBE~_3{3hd= zx!U|SSq|Af$eSY`s#R*SSJ#d|z*#$FEl~~VFN-yIMFk=B254^bHbmEpWULknV70Ec zUH{7$PHosfw__I{>5OU7(eD?cc(9W=%JEk5pnJoka`Mb3K(L=C@|WA>)Ahm&Bb8TH zo_MQ-`-w<IcTmM-;3J9rl>bSIyvo0!(cGXmNmi}fym;e^y7@lMmX^%<s<j(pH?3b& zQ5(w58z#c0?;dK2ysZA?_9ck6nVk~lOJey`{<EoEV)=>$H<G@p2V+hT8b58_)Xm(j zIiek<J9q6-H&(_3@*`>FRytD^W5I(XkHvnXWE#+fK)l}dg;M^M9u|=N`R9ecJtfHd z%CC+uFRduf$5fFd9&H*uTIDa6D<<?McO*c)H#cEH4wGSX1hdHtvMQNJ9txu-m+GO% z0TRX|p&l1B^g<iJ$Ge3Y)z3L$1uHV+$$k6LE-gxDoH(>BsB~lLv|aP6mKD*Lng_kV z@{n}pp@_prRp+XX9@@|CKXkF;3-#AmgJ+%RcW>M?ZFip{qtCbL1s0K|#0>Do`-Y1t z*SWM4X$R8kCf3X;S(z&>n5ea{SJR2~#nmH*@<T_w+Z)<IvrFD-n9dc4l!lgvONAW3 zcdl$b99|VIJ+*ZEqWP*7ajUkh<$~9)30WK~jajlhWwm<wyY}L>{F<Uo<smg8HKFz4 z`}Jk9$2Z*SZS+|wiOSeyUc%)JFfK|}B}();X*n5OUTSs9em(JD>l69;N5<3YZ$7pc zo#amz9;-eE!QZ{xYpNR?t9KVSNq1Z+y!x4{(O3`UIWh;C6bxe5v3o;)9Db)eN*f$< zMv|_h{*;^L3y%1SdMa-kk0zApr1^2S$+WwQ-j=*<9h<M^ipT7jeqhOgB^TCQ-y+>| z{ik^Hl=|me`BklaYt@BaN1Kl9+t*xouyj{ZbKY@09va91soatvbW1JEQkiOv6@{vD zTcN|jS*_cxAJ}(h??43)DLjZghst3r&8X#K%<rU4PoHM-rK|HqBgMwyMVY^vcV^cm zRq1?-;_bnfRXKBf<aNa~ve1BayjR-zgr!{arr34c)+R+oM4}pT_~y7xdTI2W87b4$ zbLSK{%;wir1=Z{JZ#fnBamI}V(&%F%F`{Bqd5!9;oP&-$uC%Z&_kjBSW{d3r?~oW< zvWrBf_z=@-^(xa+;{v4H^Nia0rg`eP`DW{@yk*_`>`m%~#4J-HZ^6B>pdhn2tIQ<z z6J7ChC4pK8PN-OJ*2!9yVp2G{lp$HLMlektq_lC<lYrSsHg#PO`~|{pO!bmsCKz6k z2Q!crL1HSYo+>s#UZW_8VjT<+r(+%4s}GyoysBgnvww{23nm_@wD$26ukXAae*n|i z?wYOi|C6!2{`41-K|P@3o>aimrDQ3BNO3ksw`BPyKbH&tBMg;}P!-bj1xXxPN|!Rr zKOIy`8*Fwz5$;zph?F*PE&W`F$-Lt-fbM;iv&rJwOo)~}U!aRGki}&21(7q%J>s~m zJ<>V!xQ7m`0X(hy_Z@SyoWQ!eF9Y(@q1+|Ou@ze^99cvbi7b|4TaKCx70Z7G3?1sS zj{BI*8IJfdD7_vg_r_&WVPOc)BH6!Gq}Aq)ovea(@x-t4j`1yGZ>~k*eLnV8^5-5j zL5p(;83RNq1O1p`FZLr=#9ZePYZqiMKS5-xn$*x|IOD184~x!8vx+Z$O9U?LXjUtr zJmQaT-TZX-!gr>;`;x9dH!AwV+h40mpI^vqvJHs?F{nywXaW+uljy>?Dwfx8;EQ6- z>4vC`gw(){L_-wFt9GgX!6m>=G0Y}7EX6`65YZOUK#+n?)3G#yX1)H#q2t@Qcj=Ur zz${hVoXvAWR!Ad1{Y?Lb+7sLR(%FxUB0V5!&=-$v>^;jvyJR^~;5KH6(@&@TS#_6n z{2S87g&)oO3?1+K;kP%gG%lJsb!9Kz0B$roeqBvo{ux02tz-;bk>?>z9Sgr|Jk`Ec zv0@iG9%oL2v<o_(nP`aibi5}z4hdKl*+Qm+InhquC-dnBbon?G7s6@gsBs66hjJ_F zo2=uJqZW+byj<!Gd|BhtLVKbcJY#JOEa@zAO&CR9MN-w##W{MO60!6bzv_LJGsnhd z#i@Z}nz4n-r}6Z;y+rgn>8=)@7u%~X44i$K{Gr_Ze(<p~s`~u8yq#R8F5IXCv@M|V z)<oVtMM9pvL|!Z>D!^kV3b{%$a5Pj}W>TLSREi+|z+V9Zm`XGsJRsdT*M=Y9`QpK> zGvpy0%tpYX>9{W*C<9C$!EYJTYomDNxjK=7O=OH(cw0=>GoV^1E(|Wrsf?ChnbAl) z4+a-1JOaH|k`s$*qe`2&aNAOFFaeOEj=Mtj1rmFKATL9vT!#%fb36t-f-K!nW=@Bx zQv&<GeU+=zRe+u8=-E)#4WL^-hdHs1WS$_emzHE1OSy-W$%}7Le-(Y!`MZ*KTizE0 z)v2!#fJ2F_1?S^MGV><Qp#wSkB6v9Oypxs)lX?1DI9DU+JQakY#?oG7VRg0HQp3sV zs^l$65t~)>>z6dH;^;I3tzR*ez9o%Z9k*h+ipG=bF}Rldk|7Nbh=fDuZhe0GM;K&{ z^yG2ahCW1BLCSD7Eg{eKy@c;8k<cdU>muO+mM}JcOz5qBRmaeR5iX}l?y=!TCcPi# zIi#V5W<0gYuAXIISed#89JTv+(`=N)g~jW`BgcL1gFa|PMC{fA+|E#52%k)c$U!2m zw+&D<NTk#0bb@D~v^KzGOeE6*j6)xwmIY}nF*LG(lbfOeo)vdL7?-f}oQ!|q>;x?U z3M~MeY_bNN{Z^s%E+8oLG)%j|!QNmFoh5tx7Yp2UZV>=zRJdB9M(NhNwU`mpFe4%u z!z4_Bg6r5U3!4e8uqh6(a!{}j!N>&035-k#uX*r&_~nSmyr2O}DWFG^#?|Ho?NSd{ z0-ERUHt3-%9=G9Vf>FT4$1#7yj_H`d+mkSlN8Lq>^Vl>$3rYhsSU=f&blUr+lXV(a zj!x5nU*`N+8N3-KSHoZ)i!iB(L0*(eXO8SOo_6-=pwrI1zPL1!rz6QTbSyIFqlsuk zZQ#z}Mrr#V1cqF#UGGf#EC9&%31a_+Bl`{hjf$==<52;w6B&YkkbacD`yqMiwHqEi z_8a7>yN5o+*Dx}N;C2~II!W(b{N^{7&~lC-g>(#gxqCVJ#`%EUl!uasu3k#|&Es(L zjkwZJ^ny~}^s{No=Tw9{dE&(W1Fw!pki?uNCX&y-_{qfkb+xnyE6G_%2)#suIe93Z z`bOVrt9W^n8R4dz;;fuO8IOB#S>&d0OtQ<eGq;L6Uvui>571FM0^$+x-cD{xy8WPm zRS&UL`4zC81!$v!96bh^{rO{oD(uMtSEIZLm<o$KF?G~`|45!cMqX4yNb!lxwMXuH z7=7h4BJal=?4X%tOPOAD8dFErP)@HmMdu~@%A0_X>_fKnAu;N|6|cbuV6n+Foe$s- z;41f_<_8AcUtkw89`yPxaiO6+yL-T%?2aNm)`CJ+p`jqf!3FQC+Im=BSDjZ@&hOoQ zWbY}JS6kdYP#B0f3@R6?7i?U%F_4dmPDW9r6+0q!1#^xRD7mN;lME>+J@^~_O_YL6 zN}?*!n&e2~b_GZ5SfSpggYX`|F>u+&1s&y&1m<jdD<GZPdt~o!zN|bCb;}NKtqR`7 zr8o)<h3dirs{>9u`p9CDp`meG)~ldk&6wMNxjX$$d;XJj0_!;fat`|IxL^gvNVqzJ zcBD+0;Eqs!`0nmek)uO<zclmZ?Y+0pY}@{O)r~8suiJhTy8AeG@2T9K0&wK+l!{HM zfl}cNeK=Ca#3iw_mZAx8le9`9#ob5f<4(b&4<0FW!cjWrE`6DcDX7p_slh4~S5@Sf z74UaS@1tZinb5&uMU4TM0uHwTIvysFdOYy#4p_C)VqL}0v#nY`>dn{Y^;zv(cewU+ z`PJ?BeFBb&=)_-M0UWBIiqs=YlPCmm%nVWf%}nF6Bp!0we)=cKY5W~cgtaWL0(?%h zdKXh=V#^BbGub^%b6Ol5OF=2B^dJ<6bz?I9aM5C`V+p@7Z{?P#gvi9mB;P&X_CF({ ziq9uLB2THX4wM45@*!fsT><syV>N#R|9R(SKe|=<1o1x`l_~zBj(jNlyX0M5Pea%q zSAi{2osnTOW$<qQeq_9`R%C&al1)_|RUXD=(HoM;n8avEMXYH5C^I1^z988*Ew>;e zA38W$(7_S<|3;UzA2mc4MpmWynygk+j=HQQuQ-<%n*6$^+lw<x^##6Qy0o(J80KjK zoDoGR$WbWN#PC`_!i*)_`>*4y!Mmodsj~Z2%hU~7(MqZv0H7{yh2A3EY|j?h2UECq zK<fYPBQ~2t8G!_J_WJZt*>)~g+9M-#BGeI)8EKKc`%B4Nvu3^Z)~t&kkHb_<dE}O# z26PC|c<>ySnqx|fM@3xdHpDF=o83~iTjuUeH@myN#+!^;#!S^Fjl+(_1b6D(seRw5 zf4WH|vO;wcQORzc|4IGR4ZJN<7vk+ry#40X`UU6sbh{lix<Lr2JA;(0&QL!|Wp-6| zWo4DA^4XUmf8*h2TX8qA>%n6KIbiTRv05rYxKMba4FSlTw?mw!(f}m(7FkOITv{(| zZ3g5(+5=!<NT8Z~LPP?wn>W<JrU89^k|QzK7ttfsI%q|_0YM^2QDSLuHMbz5=&g^| z3;3F7A|LJfME--^<<v2hT^IV|(Lvw@Zql6mGj!@E&FfGX3+ORp+gq!ba?ueHhz3s{ zG5eKdDw5J@aWWCj{&n)LsOpHy=ql;zquV}iQGtuTk~~Y^1^@&6l9lvXx*TD>9*Bq+ z04Z+6qX5@=?aRA|UK!8HU025c;GgR+4T+5j+N=t9=t^R_xY!h3xN380@QxTRHNg-Y zr;`6L{rHx1+}yfz>o2P>pWAn?jz4$2{zD{$Qj7Q<Wu?0sRW&Kqaiv^IsiV3^)fm$d zQp)B2`NN-AzK~w|V)u8y<A%pDclWG?px$~UqWoNyC=?c7M7lzZ4f1QLOn&V%sF<PP zFiu`s5z09dEg(72?{w-wXT=T@RG}5Es?~Tnt{(eE=T-HL0d7#4l98I8#?e10VpQoV znW^fORErHXCZOOEw915<W+|gp169_B;EhL4fz`jl_c}<afB>Xh0NOs(lKyVf8K8_! zh=<Ro1HB~L8(wOoItg<C9T3(>4S+w$AE+<su;ikcZzh6ln916p4`%^c5e+skfJhQ> z*<iMKuQUhM;m*W0ApZl`o)*_8iz726$0L_xmXa)6OFpJ4C%B!{(%zV)y8iCb5rb8i z01Nb%X22_{rbUAAam03*j&G0bwccOt-)rATBl(EX%*~rsbfx5r&=ZqJtK@%pxokI% zw|)uPzLk<@TXP8nQ&SeL1)3Q!l97K7AORdJM-uSoeFDqFTaAPj9bj^-tsdzt;<(Is z1^8cntdsn)p2;sjh4s<!+dbcxjXXK!S}5n{e}d~IA;H_>!Xa;>f|WN;lWs7X4BY;R z)!Ub;Jw=|YtL*vZyt~g&GNF$|UtX0~t@a`Xm#q$67r~?XYy<S#)v(rJ8qx)DfdWV{ z6bXGKbQAEM6Chg94^|#8K{u{#Kl$mmxTIKI5Z+5O(IJeeBh9c3*^I7WIkxt;9y1<j zTEre`Gn|Tlq|spLb#gf%n(S)+O*R8>TEJEHKdNz_1?2GmfhJ^ib)KLJIiLyuCzkL( zNJ1tz%g!(R$I_4<46OoeLv98Vp<>1+<bix`cPL>C<7d33X+eB}u=<s(Y$Ytwftq$5 z>hC$Vq&FDtl4!uQ5EAy})F6=!V^wt0GqI6g8gRupETL01|9su9kc>Vt>5EXVy`rPy zlCwhc#r6}eH&jf|89ZbMQX=52G-E#<7J;4Y672$jH&vWR-#sN2Tn++KO1pN2hA~ng z!2X)%?>CPX?q((GEuc^A($1B2wlHl)qWfF9-O=K$1n#XnJ;Pg6dIn>smvW3TkGmVY zwhqIj3lqXqdiwvm(f`lauV9u$W2kQR6=J%Hm?%2Iy8y_T(VLlj;e>k;1NVaU_Pp$S zhET$!PZU3Sfq!Jde|H=NY3bxaAlkP#f93HOf)IPwzAlrei5iH5xe0E@%JC5T?*qFC zuriYZ0ARO63Sa>IsRWr^2KV}DnLJ~P;Ap^rLvKJV53NV009CDMGom8!j5>LH1^_kO z5zicfD2!JXf-Oy$jO5NrL}Nz&9gWGh0o!V2(HI~3pC_$3`8l?1DH)2>$?PClWC~}1 zQT7ocuJE3kmDn2^X6$;RtstXsTIz|;{CUz7o(T(!TDnPv%VuZD9xM`K+7q-Q1pDz2 z+fbI>6R7dNCMYxjwF;-hyI^7j9q=4$Fg*m^XMM!nAmF(2KlLBU@UDuzf}yDExE=A) zV?~dk2bu;kMh=;9+}{7VB?H(k*(xDz?3N6|n+6YkJgWhdr6b7mKhZXHX9CXhM*IO- zGApZrHn(uJt%2%VL^B{tgjxOynWh;4(!F>_Pz$m)@*8+bwL~WxAPx$GJZ3`>QKU+! zHe7TNHgLEol`4XQs$>m8B6;I|F%G5^L2Wt!dt+V{-$!dxnFLdt2=8?*q^&^&p^2=9 zEDuN?7fp8!D=&bsi2}Z6{Kl+t>dDZX<RN~DlL-a_@aishd1C_7ik!`o7IZ)>LO3Ic zDnxD_dul-hqm@l^s8~xjaruv+h7On|idw)tm2~rvD6~qbxwX0-*zj$cO96ZsZAEYr z?=<jj5r7Nu*RTyC{nm>3B-<F9Li???NyE0qmX9<-vp@W6)XwaD$hEYKQv!Xnc+^?+ zmZV=I!<st<_kEB5&u6e(*iMDmNw|xFUj+N8$08>APkOqRl4mh}C`aJ4t|L63P4s+* zm2)^+>pEQ4?eSlpV+z-COqWiHy7yCL|2#;?28Gzb)BgXhAUW1_R-~Mj@=528E!n^X z`AC&;o%Ns%Jz#H7dEPpkad21%I!%XWs!b*|16I%I1<qCpn|o0AegcX{I9pLbi$!LI zW^urbX&WGUz$6Lx%=qk<N@y-)*1&yO!82Im7l4lL?Ba)><hz(|9ZFYg0_H`K8Xkk^ z)(*gYkh4t*yTaA#wGzRxi^g|bU?Q)gI>v6ml{rAX@UvBS*x^CMLvgM968Z7RT?Z(? z)39>CJbpwLj@8206k{}9aN|$H&=Taf+R>0p3meqiIx2W0Afi>?dGoVjsQu%OFFRYy zG>?<Aj*x&OP)KcHtK)s4^?nxtWMk#ZjT=|4+_?AP!M*I?Mx@-=v3A`K3<}y698Y?U z>a5>+st<GDF+^;Mk~t1uFX6ERs|hZ>E`N)wIf1@FWfstEn5Zk}Fx(6dp*0Yfsh|k- z*3LrWi_LEAn<7~td_Jc(5K4?ID`m^DY^UM2t3{ICi7`c&bhuvw0J@OJ3iw9(_4Jmp zV`j`4Gp1$6*PJ}_`iCuF^TK4R^?;@Sma~`)<gU97w;&shJPoU2&h!L0S1s<nOG}Q; zoVjGlOd`b?g6{D1*z5iKj~&~;|MjsybMl@)U%&n{j{#zYlIC{U@g1u?$_&c8zagXR z1TEMZ3~(dvgd+eV>eUbP6ZiKhhzalmy6TB!HCQ^34Ra4XM{ht}1@Se6s2py`KSES^ zm&9_PItlXCdtY~NTVq_4xrR5zWyHj(q6^|GitP40J6Bu@`Rr;bqH&+1W`sZH8mjmS zc8(7ARd;}eP@o2**{b{!gWBUu$m92*=V{||n#s|zVhGeVegGQvt3M)8I`X5Iq?8Z& z)DtH%PpVIzu;iZL9UomT_z2(ph+rxz!RW|jCF!%4@B@g5D?8;ldscNV_FCX4939-} ztwHn|zH0EmyjRt|dg;Ua@b~DmeXh`<>cDBS6DFwUIp&sWxdF86T7a(msA!jb`poe@ z9D?;4L8&99YEnr4s)HJ^4}a`oK9NBf&r1}Bc?t6Zw-f3WV(wrj6|^Fu1%cbarTq%` z6za~cTFB%6!D6QU-*iPVzv3dqCB^31Ht*7D^bn682@jR=DTyh14pMM`iB<<r*}PEw zxK$jn#lEB1QRo1;=>x=hns<NNcv6i!wW>aCE0*CbGEzC%fAM6<k~rumBImuYGy*Gs zhi+ii6pVDFvc^!IT*<WrPpgMk3a(M{XELTs(jj<)roJbgPkefo2kiDQ(e~Zt?;V7R ziU$m8ExN0<KuRD)Sgp+89ld9BeqjE_Xnmm6e{<hAX;%c=`hNE3W?sL0WBF!%pgww2 zexQ^NKL*}WC-R0GdWo+fiZ}ci?@ke>_0vSa8o>|uwn#20$?zrMD|Mo80PKz^b0<1{ z39k<<-?UrbsNY+jzgzle<Acw@g&<uYyy@S_=LhbM-ksl=U%p4bTZ$HMvlf{HZ$YUY zK|4*>u4u!Z3>9yOpzY`Jh_o|Evk*YESoYzOoy3BF$k~ccye6aCT8%s!73dX^rqou+ zbTauNqF9RG{60J^#ZnE1N(=AmAhP!}V4XNHamu4Tvdl3WPJZa>*?E(B7Ny3gf2%;_ z<Hri|dm6eIn$R(1FBFPoN3Va+L)C8V_e8do^ibnN2u72=Odtan!+$>>!GOYtUh9s1 zC4bxi?2*vbtO;NiUz=G&b*QY3`F4PWA#30gqPRASY-63qmjN0q+5u*byl1CQ?QQ?H zp|j1qVSC4h-W?8W<Y5y!1!$hU8*J@#7|mb+J<Y*ZLTjPDv5EKP;Ac7w@U~0SXjjSq z))hb=UdEcCcVYHNr#)&u9Nsf1|6`BPLV%~LU?r&`3h*r<K&Z&YkK?gCK@%=Xxp^ji zb`I^LUKf~)f<#-3L?``UIZg+u<=-H}I(E@4>cb27p`Zfe@iI|@v_zzf7yijdyni(L zBmt7pEkWGdxl1X3*IWLGlP4~(TeB~MRY3C86q0|#Y9Jkf`zMpX`?E~`O*HCbMX=gN z^2Cod1*}3A>5Sf7#8;L1MO8H{3gGGN3#SW(!9-z40t4OMi%Y3dNuN)qFR!4|1yV8- zg|E+&SB{cy`O+$xFrq7c-aubkL}jz2WUhofb&>QvPrBQr6!lD7-D{ux(!gL_ekf1o zND^}rt%)}2SqQN`e~J!BPX}X`gh|Y$CD|ovGT`2VxkSPjrWYCtGo*0miE0fQ_VEvg zr1Tw$Fuv>H#dO#>s@f+dizVr`b;j)&4S9DumyHK`>{)n1W&b@CY#`**kI3Z77>u7~ zPX?l6806F0K)iQR)-eoBo*FWc;_xm4g5;4JSBrbaRM}(rSuXI<aL3W7{6xz;AM%s* z=_0ff4U|!tq2|MEH7KJlIR-IQ_XhU{D4+^>g6!$BV<O>>>x9x;np_rZomuJ=XN^fV z#JZpMb3O7wEti;5!=+fC5<^*@wN!Z8PxOqBvv)fm=>cNE7GbN4pJ+N3G~keyD&0MW zp7m(Er|^>KiV3qq1AwM6WCJLcuW_I$LlmHu?kty*Vv~mCK+-jqaEosZ{Ec?qP2UQk zb*6YnLa{*#$?PnPx**?{Z{_WU$V8kc>r|-M>esbe_(HjKdBNKkfG@pD#?Gl1xfV$v z{e5lM?2nR(ut-D}6(|qBpYYyn2P(SycuKl%PlzpwQD;eFViH0Vc^ctf<~B{5oszKn z{Z+m~C;I1bccy4%TFJJ0b$(G!ZZR(`AbNq7e@!h0y+K`HQg<+oA1-8)zsR4We_(uL z{JPdC3u_I#qROR(o}7DfvJt2~cp>eIZHWoN_7L9?du`M%Cd<_-4z38>nZ~i`t5sc7 zRalkJI{{E)+Uc))%^%?urZ`x#cSY{Il6J)*&ufWrsyzTj7j@3NVv<En1%+7^Nrk?N z1yNavNszP5@@c<|NoWkVzy%5EEM0pW87y<Q!IF591vhk%!EA?be!oa|zu|uOtoxXW zv*3B%M?hD8A6|)P9X%l9Q1_LssCb3=lft{Y%E<v4f8P_g;pF$<mrdS3^Xz8cNZ0pV zNoUPj8owZRahOz2gmlT-#{HMBs^s^*As)|mT>C}9;O1>!H*>P8=k4Jhd8DiBF3oG? z>Lfp(s3F6Sp;j+`^Vb&AF7@v3!P08yL<#{d0({`_uyDYlBj5e~P9CQhW{@(wjJ&bt zbIip;Glr&B45f{t1RyJ*10mPz{kr~!{(l+#*#h8Mza!tpmPQvw75K)0n7y6u=m5?F zfxB_zjO>kjeQ6y&PK_yuDvU0T^~Dj$zv-P0VCt8jJwc_OKDFz!FIDb#=O(56*-l9n ziRH1S^xx!;j~5C%?#(ASSnYz~H^-^Q?RxVRaIoLe?@D9K6DyKf%Vi{uZYSGsYijc9 z)O9r;EN>k?Ni7pOpBwo<e~P<VX#QLy3?OgVnKP8dY&b2`|8gpr9oI{S<e~TkqJUfr zs`|bH>$)#iQ$JBB7NcRH3IJUllabj3ll>QA4#dbvbH`UY_ElfmF8I@XvbXNs#Oio% z+8VMco8Qsy5N*od6#{j0hj`DfoqO<+(;)(yXp9g{x^IM#%YAT!{6zC{*8wFVKP#^- z(#X%=0YK|ZWFR$?M49si=f9P-`xqK8E&_M`Rs~5@5#K(yXzvlTf;Qil?JnD=KKa3> zMZEkhc~cf`PT(w|A|YSg4RM|BShL3<x!;GRlCe0<f{w$q$^{&z^^S}kLyTj{mpnPd z%j^)TPY$sq@V2b6Y`^yqI6zExJeT7=fM?D325I3XDccds`VNwKPL#zS<$POtIC90# zC2D-SVN=}JaIBV(9h=vuF05GLyQ1=N$T2mxYuZz?qXy-)U5>_mxhJCzLq)PQvMv&s z_Zi)V2r@$+iZyh)vTg3qRKiiYw*OT1rY%)9IzFU6{os45oB1~jZ*b;3`*}-_)GU!V zr6Z*)-bN+r$rE?n1l*Q%fh3BGbRK@bchCN)I)^rX)=pJzir5ma<3hHqOkb@YH7dVw zG@opq1C3s(JQSXli6ug~LStEGIsW-3-ngm1sebREZD&1SQ(aZR=Su(6M6M!|pU<`Z zetQn>%+YSNOAviZHR|)NSO55<BJX!DJ3k-s1FIza%b;stsXpIz>}!rZ)d2crH#O;e z{`T+8!DN*`tavCwk>+ki6mhLal8y?H9$8q}Y=|U6ujME_u}sn&#O32M1P%zv0}ud^ zO6}>%-s1%@|Hy^m8IQ>vW>i?ZKESH}%G!RN)ChN!DSOlR?S}-1r^)ffZ*G5^`|UT8 z>w)k9OWLTLJ`WL~8-)LTT4Xmz`8?DRJF)wGy6WqYTPf0f7La6JNtaEWQr<9&gECsu z?xwVT>c5YPkd*|Wmv)i+dE%oa-QK0L?<l8cVNC>)ot+_yjN)TOutht&S`mYFwIX~0 zERce}=s%Jh^UkQ{i$kTX9Jm(IQmDc?SiF!$UL6wmDB(6Ouhnx1ix?dMDCa)=a&5kF zo0JQq;Km?-gxIK$CwwUU!}{z3%!)$ka_BTTosZ$|!a|+_!?<}VAZ8lc417V4wNF0r z0LNA%hI$VT-S1AC?<1s!DPG<rIDjIU1W&m^2|dVE8<S--r>Tv`EK?@$)(#LQWa<;+ zRrIvjQDKELqu1{Z$_ptD<K#cm71Lj#3k}I}L51t<<D>>ho-q#+8EmaGXG7e5E7_#R zH6f-w*1n2MsF$j}*;|SM5h_3lp2GUxXBYPniZAi`iA9;fRtyk5(PD*Mjl3z>mgC4{ zj;RjJh|Uf815|P)U>O}t4;HLuWm#NN46@zx$51o1aP#KQd3*L`_rIcil1<4-&oHS0 zpR^=%T%NvVhL5-84(x?&3r}|5V&L8pbZ4gCl9Zd`ix3%dLXd&80n&{cGzy|~*lc;( zdA=3Gzph^R==`~}zL1AXxeLtKEf|?l8=gtNMzm1;HN8%*%WwIKKXv9PcMzWt;ydOS z=`UmHzs`Uf;s+5f@+$qBa2m2-%>KS1-n%O)vXn22v<9VaqEp*jeaOGXz$m=#%z@1S zc`78WEKug}Nr1c5xR(k`ed=Wbd-_)Mu(wZ(hF+i-d{8~|LW{;%s1ka5sH=bP=3MRB z4LbDoOa$(N55*rCS`Qz7i>;Tsm$IEYAHqKGXuSIXB4|b<H_@(Vb9&*X#<%xFW}M-m z|JjRFq2+(<h6*mp|LNevhv**b6naK3V6TV0aU@c;nDy>2L4OA`_1n-^_~3@d_1HCD z**-#CjDibJAMp}*Go^h+rVI&v{A&cM7m+u`h2WbnUPzXltRm4Ow;*0Fz<iU6{iuO_ zfN-y$YmIP~ju5V)SQM7Aav<-WU4ZACPmXmi@Du;oh3o(@ZVo*Lt(ZgN^>n_-k4_WM z?RY<p-gU>);qK97_)hYQh#nJ9rh;=8t#BSfD52a>G@P{u&mZ0=b4U9Mdc@~Y9T3SD zJ?SgI=+a{81l6qdF|)VY#ED6%Ne14KWJz=+|N4s05J>7y97dOhN}XyrrUN{6542>Y z_=|%lZvF&1N|bEiiBVsy<mgC={2J8`!~`V22oWT0yIM?_Zl@FP3?a|``m2v4&jLh< zw7`&*o2bTd<gJ5nI7wn|Qh|Xp<>Vka&*Y7N{80pk@DQ?xK1VL8$t3_-o&#BJ2>&Ah z`kss0TjWOmQ-L)XC=<-jm65pl|5>=!)r{m&yRJ!dLh~w84CA2Gh<ryY%G3%hk<YG6 zUvRDPrwc2!J`odVkG;%i{M(^^PxCwbj6Q;9FI0QkGdVyW;ql~|eU7;wg&qD99D?G8 z23Y)N<#>cc5rlj4)XmS82TfOjq4jZxk4LPgYsVjm*t^2Xd+3IPJ$FIO5AOaSuPU=s zGE&lszoxL%#K%LGXcQSmR~JiTvlEHG%;v~(n8@W=RN*z1(#ui-YI@m7-KJrOBDRAt z3}Wa%xQDSF60n2aZpkwVrLn>&_oz}gG)v!e&G(1$@M?6py+w)36$#{IeWo7V8;doW zk19yQ{OD9jstYPB3b=~=T2x#{LcZ0fLSF!Si7qKJO3y0Yuk;h=(f7!E-A}P<NF8tF zR+qzdMd`lczCy0hD*_%OcTM{MWi#m8<T1Mq9}ACbYTnDL3HN2xZ+2VNlq<b8VBjge z;4@(Y?Ups++JtLaq}#P?Qh6nl3tw^!rD2x%$~QgcA9G7k9Ol?kUx<izzjlpu%epqf z_u7Ok+HJxFpjW&599@b!Ge=##%ipIPriIruP>uamh7f=X>x0-E*QbBg;7l=8i{cg* zbsds+tw`FzkVY6mp`3-62sbm`w^k4C?lQg~$q)%RTP!-;#bt4gQs!4>Y>z8PYC+)> zzH>=dcnE}O6+Us%nW1?R&~~UwsKqVQu7HsVhHV-W>j6}onrs4$$yaYJNGm|0@=<VE za9h<@6;<a$g)j-Lr1t;~uu+qeQuVkM_1OuzDNOCyC(Z6ark}L7D{3`i5%Cdv&=xJB zCDBar*vBh6$h3}qO3HJ#>#L<z`iSB%#NM2Lh|3a+V^B~?Lqc4)NJtmwM9*|bUBrc{ z)jQp7q#J#Njl#w!(_J#Df+{WU<TJ=(m9h)9<7F42uP{NmXpxB3>yn%RprcsWuT0BL zFrre|L3$9Cx{L{+@}?G<9S(Ak97Lrqb5W`tvX|{sm9!aoJ)v2^6Kcn`w0J(ad$+0S zQdZLjUsn06X+ze`4S0Eo9P-HP?s3I>Fy@|ToJ~L%w#Dgm;9#OI7Aq2GD}<Ib%qn-i zyZ*_1UoX_N&!Wo=JMwCLtMjT$>ePa6y~eFW21sytS`L845#YH6+aO=)N(P(OTc8Kk z=PYS_cwQV3WDuXGvwH?loyAWY6;1o^qUq*@)PzKX)R<u~WvEk9a&pu7^jt6?7m*bz zlJyagd{==&k<^t`*W_{4c{>bc(G2H+<xWbbk=y>L;({!^HyqpS2~Q(v4)cM<^+X6w ztyLm-<q)~|OK`0rg+_Xzw#qyJ(qfzsl{l+~;p%pUI6NW|SAag!ysd~`0a~Bfg7V}_ zb!B;8DWbNmg0`sKT&J(}CF=IM21HA|`4E@Zleb{`5Qj_4@?dCI7^%#!G}a}si&^Va zniQQEsg8_Jj>WK|;e=@8w){xni2SO=8nsg)_PX)V&MEkRHS20c_`fo_Jhp&y!+(n| z+GdW_`$p&!Bf?d%AHxeHs`Ol?zRp};gte*Fr?eoiyix@fa2<@m$Ee}s(k_+ZpXRZa zrR>mEcKb!c<ek!n^*4<~c78x|y13Sn7^N}Skeg~vg*rfLrqnb!JU|Wn^UJ@G!KfAV zqPVy)zu3apkgjHjF)uyW*Padq0kwOj*tp-c+tMHv;>9H$n~2Sh%)E5FZ*F=@4mQ~& zCjCApJ%1o$uYMAntu8f`=H-;WPloxJb4`v6y8%)Gsb*<*#_+0MYOvQFbQWzK%J+jR zrFgLBW3h2l*81!q>DwUmP?5yL==n)ZKlm1??m6T`HF@^O2H@0+t&Wn65~*i)*-ST+ z5ENBdBq&K70!OHCIg~`o<6Tyv7nbJ{V);=ln{T^^O62j_?A$jp@?x2co+ClxhhKa` zM8DmhX3FMl1{7q>c4RXY*zZK{lUHaePs*2C(*g1ZzDZ5(C{HnpM)Nd$Ao-VuzBpL( zlUv@Ob+bQ2%;zAchS&)MPkch`56H4MV(a4C0Ps3Vr|WLecdl~urPH+A2ai-g+_?-~ zR)6xGKMtFlj=?kMW#`(gjvJ)U|LN;Hpqse1u4Qb^3>uphdx$MrBU<PXY6vwBCA2s+ zhi*CsgS+M4BzIeKkuAw`?*$At1_w+C1PCo5gir#clR!ua>B-BLeP!Oi$MD|wul29* zUjj>-raLot&OP^>v-kEaD#-!udsYF0^8M)MI*!aoQ&p&JNCNbC5leS&N4@@7`i7Dg z5bZ>=Xg+wP-Xe;PW0X`rc+DutK@1{FV~!}1M1t!vH#I9WeHb{OQd5lamXyK_OdbZ2 z<UJgn$AWmj0(--L&tu8%Hq4`^k}b*sy}j^lUqK1wFfs#$g#(>?2KJo7b$pf4osB-R zx054D(-nV!IrJuOnb(s$L|z2((f2!jIy8=nGZZf(!}%&hokD28<#aw057I?)XP=f| ztw449NV<SbrEhU*CUcfWMb<DjYY_r?CTmV<ni&y5U$El&(NU00j%h+(;<^3Ak3%>C zmpBpSm5<5HyJVIVu(dj8`)>m)$|R`F*W~Eeia&9&j@~6lrz`$qD<tzx_cG*){dS?n z08GD^B|~r0spu*OCEak?=qkr6v74i|#&7XT=twvc`3~J{pY3VQ&=sYqpg5z`Ny;CY zdP7Q~o_y-K<%xdwoMPw%*rAtc=M2R#=@b1LAvEH{U=oOyX%Tf%kU%_}ffBoGg8ejD zWqX=?HVafacA`{s3|qlKM~x+ef0{^@8loRaEc8vXh*paRM>{%JZ-0d2(7#6E=vv?r zw7AM1eV_fLUz&;A<!8@BANHtJIP&moKQeGyaRdU|OsV)3@fyq)TNQRIc_`$7P(zuE z%GBIEA9C80Oa>FNhd`s4y<jybT?{I_J%oe!e2r<7?C6IMAMBI!bf5eg<ULRFGIK!M zC!PtE_BqMe-KgaDE@Y(r$cueYI?VJQke~C-Io3W~p@*%YY9=vRpOmc`PaSfH6Eli9 z<fU0DmP8eOo=L)*EX`=Fp_G{@t;tT7)~Ff1J`=-!28cBB_4nz|p47=-O@=TB&^kH~ zA9tW?!r_o7<%1VOh4U%vW9CN435A_I88Sm!SMYRQsZC<-Ca*~A0?~UMDVby$U4o3~ z_hdY#DN8^hHcd*nSAl17JoshDyD#;2DL?`@9_uDvqU+)O71Hsn`zo5lZr_%hyG=t3 z()Xpbkj>q*#}I^IG2IQ>TVMJLOXPW&Ju5$~-nG}Hp+^8}GUS>-Q*OvqIfk<_*(pI= zREE49D$f&x=u)}+QnHab)Sla}qQ$Jc0Szc*a^LPW99Gc+`~togGsId-7JXDlvMR}% zm%gLJ+c@{P?{&TZMKbZ?=w8R$0$oKvuN^9q2kc+ubFiOk=G(&r;0_zAr-<Yt`yFX$ zqKgrcNqGas@bCk=&B3?~@KE|93dp9zdGfdm7ix;op>XK{oo}!jAQr;d4`CK>{uiu3 zKhi;-Iiu)toKQcm7^+5b+*gY3JK(yWrpQUvB<0BSSgZB6f+VtCiu*l}AE^Nb@wpA0 z8~vZ%agF<qct-Kp33b}jgY-<KxsTMh)swtk9^zoRI9RqkpS4<U147d4LlT)T#elPL zH6IOCf2HW@q#lybIbVT_ihk-|4}9>z2Z!H$DOcG~P0f%rLD_)%EReH%(L?*bPgh`Y zyeS=^dx{+gc(S?l6m|RIaD7Ml@3)(M2Y1Gy2xdT1n*(F+D@f#B*ss1rq<*qR5!}7C z2&DyB+cN~4-G?*q&0R!w^nF|Gps7XbectlMEmC2Egg=ItghTlWyFx;D?+R^hZ)<L8 zuSMc=%5_9*5DD_Y6WciwN5Py^_-pdLp(5SK6t`L|)>^LVy_WM|DeoA_LaHrMh+DR% z`0AFYtk5mnu_GubaLX?L%`3)GJ|LUhlN}nmN7*Z|yZ412%oW>mFGhbD#RVXxtJ+A0 zsw$Y<hy)o5RQHTm8jqgp=&HDsajT)e>VV~t^@!n!4h+a;@8q21O0)LqTE&BhYtEgP zLQpgNYLB3717AXD4{1jGLwD_N4rxa<DIP<!0CJJeR^%jDX+h^soDAF3OGXLS)`ESd z%Dj__?*t#Q9>NbC(I1LE5K(Ws6@O`G*OpU@8z&pNtRzF6>QyG5p+l)^V*r(D-iTTj zy*rl+%nc5O>ZZW%X$}RU=ArCIls~qj-T&a0{XvI!SeKQour4q0J-U^PgpI_tx${-< z`SABNx>~&@t(7DDn7_We_m@#~I{JKI2ZDyEIV6KF5$^2Wi>Iy;kB{vcKVeoMLZ*EB z{gq7*N<L1xT=;S3*^(=|3k6rMeEby&ac{qQsAmjG687j5Vs*Mgs}9*)baHE<RaIq) z-=m=uS@*0Vg@E!65Du~jtrfMk*7!g%knMerR0%Y3!Do({pW0`B!4Usd!XkQriIz;E zDmAmvlB<C^HkT<$-C}x_4bO`&(2238veX)oZItb6)NKEl1vJqtwB^)imWj=2aiw9Z zNNrMhw1!Mw<j{ZI&W6?2CDo~#DodM-HHBq)4F^ChRv|28!gCX|l<`^m)C84QS8-7D z5%Ids9!_sgsuCOG!fbm~fnmuJv6`gVjL;oQDzH0>LQ3Prh^nUKHr2sqTT`W`7%WzK zWt_3dSX!%etm*z#IH;?Pj?%{kqE>?qw8YoeSSt>S_I-{sNTq+e<z>T!m}z42iVa&< zrgMoB9>ze`FyeSGqiW5{q76rr&vP-~7#`e(l;yX^2UTB-whJeYo;Pu2kcR_)M-4_v zyeATG&AE&dTS}L6Rj(K(OvTo{S=}0e`oBi}+4T0r_ad()9*;ksc%1u;IZfA`0#5W6 zLpC_vgdOR@K+HzOh9~0$!)*<5nxv}q76gO`vWJUWN^$O$jkbfT1C7ZMRhrV+q7a<> zKo(-3uEG&EI4mMDLKU58u1wctmE=@l;&S|B+Q7Q^<75ejH26_EBOF7Ot<+LerXlSg zI~dl!h@8Vj$PA3@s~2t&=GLu;<h8HAB7c0D5%YW#3Hpt=&j0P==kec{f0p*Z^i9Hp z(rcLy^6xz$&hEW8TY5H=F5y^mU3g+*dSaqT&#;MQW$9(AMq6!{hCCnvLRVs4aB!k_ zlj#3F`*=O65FA%Vu<rIx*V?ZPc}PAQhqgPe2xr)By8>hOszRbm8qzeGW!ZIYO1tX5 zL&ioMbjEBkDX$2V<;tqk=4y?7z<oz5OMWCH1^=8q>CxgYT}13|)!v}WL&2I2le)*; zXWg06G8)Xbx9qPxplWM~4X|p8V)FL*E0O;u4=h56AtonP%!x^h(<N}bBLm_f`?b5` zV7Ml>UVr$slDx*AHg{AthzA?nDvqnV+TsHnHI)(OovW3@KyJ<YmudIc+DhsRMPs3{ zx?TAonQ{Ex^P=FN92p#vRDWC~0qpV8x|V%5t-nYE*zWDUX#(L8&Il(iV%+CT&d)J( z)o{SyG*DkC65>4unx?Z;m#&DN#YIq;T*R0;^cu<<=rfI=2d$j-(TY21Tr?ihHvz#^ z0fPCap$2kscZx5culk&8ATCCbIkC#e@!l>DVIeJ_Ps-(knHt~PH)?%b$5$^fLr%2* zH&V|MH~UaIsiEHrr&ABd;v6G(SNN+o?T!zO(8NZh?pUpaGriipqbghsY-o$`QXOxr zIM|@6YA_$cmAOa07bZBKV?ttLlb|M-UR;_ZS%8unrQLagLu7a5M;0cE5$2kd7S(}+ z)o-_J{8)FntmXl7Tu7sMGm!YRKkV)n47o-?_d3Lyl(_m`Dw+n3luY=i>3U;QQ8K*g zR?l3J{^zQw$>EotY)m%kz4Rt4WF$!%(^i4`CtMf%QcHzF+5HY=ZY&wP!Xy>VV0I-& zX_GY$>*HbZ!3HIcKz`_T5~HnEk?qp1rPe}Ak;Y^(l&0J0eLMBcH5iR5dqdBRA{&-j zyij};hfxj@fyka)Boc9w?h?U}o=pAd4`O_3Qf!zcA*o9%EJj?WIM-sb;K}*b6Kyq! zh*Je+T5_$0m|zx~3rbYv4W_v?E&){?&(m;2F52p1&kzdJ4EjvHV_fepPqYt=yf#Oe zNsnb|UTK-BS#as!U_z3r%7J_<vumM!pfuR(>_fU&i<Op=iY66V##oE9(!gdMLq{S$ zg9#4Yo<6BZ4<Sky9jgOa6hXaoeM)wUN~iA&>RFR(p9J-60G9Oy^{SHrRl4a}rL&?0 z#cm!*h8oD&ARvsQewlq^oRw>!5j4s`flk)qJ%UDP#_8tFiyFo4r5Xb!Z9~E4jQ9Oi zBi4@kY~Dj17eOLO6zU>Wm^nll8c2lZq4l#HHNSAJM1y0Kp~y5yeL&%K*{XK75AVJv z&<C{Mo=k6$pGb$?uA}(^9We$HR)^q*<>uxZ<vA?<i5{XO9?7YUwI@N>G?z6Rjk$6o zYfqNcPj7j<+!q|uAs)~=dn!36x2Mu`0x)&w$s^ifPa-$uj-+mID@)(73TCOUubRP3 zc))(f;8wf!Od+mNSRyK+cTKLGj$ymk8091bH;cMD9zUL9e@xwawMGW_t4;KF3Bo6% zp-qVu-9i!_-Tl@Q8yPL{eb)Y*u!9coew8jg3_d4Eg}p_XLkHUbMICp@Ksn9pUI^{O zsrI3cFUhla<!8I$+>Qz-ZoR%_RAXPZWC4K6i!kAz4>8DB(Xv+&`<{)0mf2W77a60K zq@NHN78WQzKEnitH67G+dy~Oz^0xF%o0Kr(d+2r`vMb0QvYnW_(z}v7F(o!Iz1}Q6 zWZx%X#xGJO0P=G{S*ipCe>%o1CCJlX1&OedP8UI^?htkc1??2+TxMs`{tgY9&UWnI z-+{qxE<Ob9)X?c@3E2U5^GWxq45dxE28PNeO@hCJ&n%VQpG2_OB^nCk_wN&#Mv6H$ z*=LbK_}}Ca=I!zX<=^A?6jkqdr`If;SJ*ENJl`k(YVH}1k&<4J+lMny4ABZh$rQPx ziWy3$$j34E&D{&_n|l|^kr*)dC1XJJ`aLvoCc`a?!haK<M;9mi_awqTsNT8z{qE_) zXQR(7+9uB4WuWd~?7qI`k1M)wIO1F*l+giWp&B+oC;j7o%OnG`etiGl*N4ap7s%9c zm2?P4(h%14^?fPr6+ImpOUD}N$g1g<3Ff6255IrS`hkTkJ3#z$$+F-px?B2VE4Xuy zs|Dl1wsRXx5er)9m};P>$hx>x&y0lfQRSl=#(13@MF#BoE0(O=O@ggt;je$4OCX-j zzi?!6&s#!aTk+w@{i{Eo);hb6hF+!##WXr<uzpbdhyb6^;X6_$Hqh-y=+-unhb%WN zIK7P{@+o9U0FjaeQ6!|CEPMD~(+BO=%N-=-FbO#bu>i?kTud?_5atUq?F$0L{+DDi z`jw6R_63>x1^J!WoV)LLj~9xU&E2?W|B8CU59gY=6D`+vtW<tcE+qd!xvS&0E(_bX zG=Fiyq_5}QE529!$+x<D9PzQMgrLs1iZ>KdRV@{bR28`?eO+4U_TyVVO23dsWXZ%S z_n*=WMIW1vb#ZU^CJWK?OUC+arNVqVF^vvs^s!B@-*!Fj6W#TcYlS7AB_<LCF7nd` zNKp^*I;fA>774EhwFwb)au}T$ik<v7hwqG`s)cl-j*cuJVI9^q<Aa_13@6jxjv%8# z$cQ*H+I;zD^O+j%M&ljZog(sbIhmP3Ci$O>zo_llP!W|Gk`>93ir=I_Vs|ykaIz~& zs5Aa7RqJQPEeT%}zBX|4mVhn0)`TvL;b<_K<7j6W6ungzAeII+?e5sqvG;iR8PM6B z`5^V0>Vxwp8`x+{F4SJx&yh@a?VLFgvsIgSSZV?_5oK}JsSTXIG3(rYrCkI=MutOX z_XJCo2LVcf_#q=oh`X>}yD5HqDwn!_OQyeS^~NIGcFlH>v4%8+*2gsInmAo^28Lbx zNKn8{W4p=@*R(brXl^`E)lq%e_HNMy4iCsNRPijPP4on_s9;M`tXLFlORUmy35_l3 z2UO?JR~<SJ?RnNdu_tN}O5IUhI!%qxe@UjU2w6BS9!Jzrd4mU9%O>mkvJEMD$;Em? zkWfI5S;{tyRGW(nOeT^1Y4<3$<ROXY)h8l|BlR>3g(W$*Gz%rjI!Fp{snYhTVA#wM z>7NddG<}Yg?MNxKrrR(s;D=D1CD{NiYqJ(3N`?x@5f~7_Vgzw%DGwuUqGfDpR$ZY8 z5O|J0)!{+^@szL(smdSKPtXi@5BjGi&6ZPA=v7i!WVI=AXqUT^@Ue6><guaH&7AIj zLHJP(_(X<Dba;?I^~K3~DVbg=nd!P@B~G0VLfsg4LuqSrvCf()0wE5r9wh4i@iZY{ zZ<e$^sE33|_Lhgk`i7HFh2@p2-}b-4`CrlA`bv4b_LHL@i1lq9hu=FE`1bCDyX(25 zzVmBms@AVaiCV1DF5aLEQEB}x)vs%+7p$<XS5bD{hA}=GpV2$P(Kt>?UpYx<{!D#D z>htTbQ~p#PIA*OotEoM6!g@s2c}gF3K@)xPxbC3p?za%__*QfNyCdH;e9k#sy<IFq zQ7%O2a!ol!IcCa*O<TWi-nx0=Q*%bXQ*h8!SJYn8Uf<sS_S^f9SD)mn-nAU>#0)q? zQl9LdV{Z}+y>lFA*zP&w<lgcKmtMR(KIopq_UxG^Jl6D%VtO?6Ik{Es@>qKBo!Fz1 z_|<w4u!HT`3Ol<M1IIQD^IM(m`koFUI=-@|rlPW@wjwS%IzBE+W1lfF>dCU&nkUPm zHNB_l8^TI||5X~tTz2Jg|8wWMj-M0lbJ_R(kFOGYx?+XLqkG3QZ@#<!lK3fOq%m@A z^!~Zy*oeenfQost)06MF*o*JJdr3nRd)^nWlNSnb719g5((_YuveM^4K)C76g=O<p z^A;wCy{VZ;JhO^Y^U|}u(z9|v)O?-3;7JG18;ikkva)9)Lne>K;RoFi?ct6@;hcZh z%2ocGR*Fwr`J@2|ki5IO^PQTQN95ZI`^k@wRTH*4uR5tLecy?i#LDN3Pzwp{)v$*@ z-#4GwyWi3o*zwV~P468nZ#&;!3ky6gwTwJh<6gDogP*&{^mGe*^K!HnBWF#o%&XQI z*zb}AOM$*RBpJ*Bm4(JwOFl>ca=a=OgA6e<J|hXvu@S41@+vJwHgjoCr8%4HenhFT z?Ernols%J+O2|n_*0_(9$tJ8@ew->YmvZg{WtU`Gs}lUuRs|dLYs~vO_kOZxW#%T^ z0b{FiUv_0$L3*JsH6c9E@3qL+(-x*KEeh<=*<#{zva>TwQ>`(ayKDj@D-SK(yfeo5 z`(D$Y56}en{@jpHE*F`v2DL;sQ1Or5N8&5B=G2;~6N#TRy$i25D=UucYe&?Ot5eI4 zS@-GBn2zC4K67Q3+n<mT`-?Z;`{Qcvo!paM)VVA2Wcb<JpLNt)n@e&m(hs`$q;`!T zJ}rA^Zjw2%bo0@7cU>uIDYO*sx3!kERkdN8Y|iOGgDIy<UkK%9L%J?8e12k7dPr(e z+Sa_Kd1d?j8<UF)sw*lj<_43khRe$@udta5@(rKu0R3@4*`Q|wjrwq7I2WE*8U@g_ zF+N70otPQ(VgA0n*7Em{<hJKFZpxj_C7-XVjuuOkeBro?*7o$al+tOLX{9To(!)~Y zE#-}tM*S7PtX0{?Bg=Biayr7AGP&>Km#(wE$+<r(E0oz5c2#!LCB?df`U7-O3w>_e zOV^6ajrE0=_QoH!6X)%>w8x@aQY^>AE=(z1%2mExvMX#NSDt<t+AF<W_f;Vql}n<# zk4v^JH5bg%8gpKzDGTx0jGUax5{Y&>E-QkwPowLE{G`-`l)RXNjVEgAICsuTCc|yw z`pINaw~whxDc6@46~uD%brL9K>$CEdIb~_3$XVe~d08eKrm!_Bxslu%1c)+q+WgF% z*z}CJ)FORxnYqA<t@17UnriTw7pJEcYs~4kjNDAl{((21yU@yoRT*SpxHg}<-H7}m z?BpgoYAsG5Ef^ITub;hS)?%t?tik2GX}S>iVd}oDBc>+nnU?aFwUv8JJ1=K*?#o?d zvfr|*e{U_U$*;YX@Jrm^zGV8WZ#Z|IOy;uq+O|vK-$i|za=qXa)4lcNnc3&px6i45 zJ(t@NkdYXwq1+n@6Z3}Ujmf9|tV5GGES#`q)ryrN)OqLVn6-N%vlr*a8aGswUVZN_ z^+bi%CY((Dj_*JuGd6l{`t<f$)$=RnTDMyxiu6)eu&KSn*qYaxT%l{!HD*_vt(?hR znqQaGlHF#iD%oFEb~xz-w=p4pXOy@r#;+n=8yw#GdiL7vo!d88?s(EID|g(@ycb8F z55MVuKId+>?Jn`mKWyyC>o9Uhj~a51Y3^kQ`=1MWH{v@>O?7kA?aSv{(C2kBpPPrs z><{TPxBL7x7yG?G5)iDdBrXW-xp;#v!o~f|9&@{}XV%o%36iMAi|2l%jK%=TwoDO~ zqfK_`%^8$N5TC1lpy?fSqh$q0eeHh<Y1yecso9)?{)2MMh4hB_qk1Ueq-Z<{X-7h4 z%UC2@$(^*{$pcMQKxIIA05^!B(D%z%=vCU3AFnzJZUk>kKbC%LP9bje6~J9Laos-j zh7e4b4yBXmh>_`scayiKqMU5^0kU*OX%^ReygN?7?9HG789PMF?cdQCg`Dj1bO<%P zg#6hy5Oq$|+qjaG?-iX^xg#@2#`?YpfB}hg#0hCe8u>1b4&mI_W?HjKGObCiiLHtI zNy)$dCS&vRexNRA>Cim-5=UIpF#%Xg(tBo0nbJ`}G5e5@x;w~ws9$rj*n<VSnXVm2 zmxJDG`ETTzv-?k86aTT$@d%*YJ9qfhWk1WLS`8iEE=MMUx?IF1!O8mHBCny`Xq69T zSL|53L>!$>AmXQ*yee|_igU@g<1~Lo%E^$uWcD&TS4sX&gN1v+U#|N|w45-VI;FIG zfqw0(!)xu@4E+Z2<dPZtCQB5bK&sN+llRRyxkRJikg;~H61t~X=~cVesZ%D)331&= zUk2Y(x!;j6>wvD2G@7<rf?V%$-{LL5j8f9;*A0Z3e?2GP)A4V|zvW@!yOIJ_p-e_W zgh^|Iz>Z@yxOBpr65BeIhsxTU8bwTO-Q<mp?PVRRL+uISjlg)&<@O==p|p}z%H3<` zU#E;={(Q$bj&D5Y&o@x!`h2_e`TBgq8m?Wpe`Ei~b51uSSoFY!sHE78UgNm#xIqg^ zq1=+1j9^Q0G9(7TaYkKZV-0(&V!Z5Q9Ak^qteMtauiQL|KITWY`xXORYBQNFn(mP9 zkg94!YizZb<O6s1-0Um6n1Uh@5B#6v@k+NJ(v2@6zk$5JdA-7}McyAZsYr7?UD^$h zl(bYTJ)P2RZUXXN%J(=K`cgr5tx%Owr7wfP77Cj$Z1+9!n#$q9yym-M`F23mB$@HV z3@E_*Dq8oIH&se5#Y1@)^<=2Q@e&H4vUMrIvLa90!1$h8cL@mr=7W<bKhOYa>4$tk zNwzh^qM-)+OLF4b#Uk|bP##vfFQFA&)s89MooA#eMPF+qia2fGKh)2fyKj;i3K6v$ zN5RuDh4odOK6>=DNdCV3co++OrG3X`#}4U3&#=p=g?qZ1c6R@L1|?eEr6gIPf7pY= z4(%oU?;m@8_x@K~j;`b4%A2CzQ@z(*TUo9-dh)BI->&*&(O$}j1#tF>i||a;0NT&| z8zGS!&y(06lGQ)BAM%!;Mm~mKhp@dBfAJ0l`|Ei9_gz{pk`}s8K)o0epL7v1dLj{P zG?|T-Y>QX61&sdrwCj;4xxiX7!SgRdf+0_zMZ3m%N*kw?hZ<56yyzloq+Jj71^S%S z46n2dbR8wVz|yWUQk7b^-YZ*ggn9###768!jTvdVx_rG?zP>o!oK3pMcw%E@T#GYA za|X(A3rN>PG=mx?rT0t=XqO9%K^lVJBVFSxS(ZGr$qVHM7K;+iB3+N<?qT2-LCqT{ z;Rv-zS^X`+99@3J_=ZYmSGssIeM|M<g1)0<CCMgLpKBHk4uDJUu5_^E3_W9K4;{)k zwSx!bu3)XtY>BOktqLuS&~brtUyYxo%28vd(`5XI67K&m4fLT}bPf7?ZFy)e=a`g8 zKcn9}CMyZJ3{R0Jl!?}p=TI?+{^8db`a)rhBwGvy0!g-b403ZjQJ4r|1BheCqS|FN z_;E)nE_=&$sITq;AA=+sw;FT|01X#POn*|k^QKfq?1O2}7W+-08?@kFGyHZ1!E3yp zQFxI73M5Wn^X$FLP-)Qsg;zv`VS7Uak(MqtjG!Kv1O1JZ6GOSWNo|m)+C*ctVbHyZ z^wQbNGRstw%p2mYOF_|YAf6aQ7mLWDN%;9WpzL!sXuzns4ji0n{2utzcX}SV-t>?> zhq)M#kXlrZlLg@I8;U9pyyLY102_%zuQs~J(2`d4yf+(K=KhH{o77_z3`s|(0D;<> zBag~YNJYpqJ~b^$+(_M)4K+Z*hlZ?4i7w^V@3;K~hUML@_r}(VK}Fia8OCA8DY@&x ziW;%2ET<~_Xlh*$XK2_~Fj2J9ytP3F<&NluZ6nAw&amQ-O^Cjy)g)MP^tjUS0uelC zO*!(diLnMlVnXR24XBhP?$|=CCy_LXn933MV%avxD`8Q2W$pnnhm5~bXHZ_N{hq%1 zXfbEFx$dl0B<2D+Q5lyK7lSg>y!R7~Fhe;oszDC8CX%eiBc>n|-+7eS$qlHP`Uldz zC;{6JJsOFJ?lsav)X&=o{Y=(cKP4;e0YvdHBD#~i-P1^+5aRC}<6pC>Ch2rbSM#xp z)m^dg#FVWL_2(WEH$fk#O^YjvE6%L4R9Y%(iz_oK(@in@IF8I6BwQrQ*D$FW(Lo2d z)5!~b>9fAn{UYcphWf)tMBVQOGWXMq#2Z4fNS0U8HHh*qrYD0r_d*|fG6b<iWh_~P zf0*PgCMWlilb~RxN^HoHOIZT(rp%pTtztxRe4*_?^Nsuuf{v~DnoiE5OXhIKmEonw z#pds`Zf`z1@>g2^B8{feKug`Fv+3+na6?{F(v$XQ=^{I4Pat=IOpOv>>vj=VUVgcL zc08Krvo}2^sA#WgZ);2|1a8P(1KUyDnbI8898|nDWheYNeNe@o{rdg-0~MD24Yw1% zTlpbEXh0-GhUo?R+PidWAT|m}i`-QlP#kb5@=!5h>d7;^zZw6{OSRN}7j?#J-LC4L z?J4ak9n~f6+>h#$WI_;R`4nWJ<b`?5|NIEByWl_p#XT<Q#<Mq&^&7zfG88AVfVyzY zz!dmgAn{Tmfco6Qi^NIeNb{DP1^W0+=(b*UJgcNDu7aRKPL(350k~%cVAMY;dj`^a z0q5R=@&EB9(GiFEHuzfKK}Kev2xU~|RpLWd^aUQw_q|<ekAyWm-(7cCqWuFaoPB{n zKO<%IeR|KJY`xd;Q~7V4!EP8{W=|67w{TRZ)6Wdbyf(v^IVR+r66}i{8^}ZvaDwmb zp0w7W%+8=MWW0%<k7`-_2FF4=Pi%KAu@`+|P{t1lAH8eR0u<FQC0iXs;Ob3u3@7c! z$msKk4d>FWkQPYE<sxEYBO)NPry*@d7(qX<T)u}kMANgx-<~C+Hp52hu9M=M(!V-L znYi47^?gLz1#dbU{G;-F;8qmvjkK0Q6tY%+4sl|n6XhDaH$mwGBn}mJjSF#^`~cDA z-tQ1wo;-oNXcpl(?11w~&I`NL7%4}C!s02b72y0s6zA1sIF^I64a7Jg$O7+0T7K#i zf~*@)39@EMFtWcvjs*smzH&;GDocb?$;nx1$eH*dXA+;HkBL!6TVg9x0OG)cG^;Jk zrjkswq%--yl~Arz!=KSUttE#8(g}Wt|1hQzfQOuWipd`WwN!#MFN~r_Oz49Sk=OqQ zIl;6Wnt1YpoW{I@tV$5gRMKmt1l(iSz+)dlrjgV;qJ8CG0$o3n#@aW?YxLUENR?v) zlYoLHfaE+JGnoMLw)_YE7oR=o!?ny`y6N>;5p%sLqyABEwddY~=7?66J%}M`j&OOj zr7o!+!)Tv+0fv&kyhC!&Hu5E6J03m%Ci`%|9`w8*B)|SLu+|f4z@mvWro6Z;K<g8_ zzGhTsAej|P<ndP$Ka4(~cr^W3<dGd$R=u&jn2RW|H0~|uir7b2Kl<vI^ZP4LR~=0` zoN{1w>E`k^W?%EV(n(oV`O$)#v(FOQzOxM{>fS9l&RK|TP1&flv#^A(+&EEu(fn;r z=bDxP<A&6Y97_MgC4F%NiK1JgrP3xXYGbtSVeW@evyFlmIt36&)H1Heb<L00*b@$` ze>|)vi%~c?1(jy`9cr@oihO(rpybjAhveZ+VeFm+#p!lWi6Ba<0{>fK$93><JgEam zC;FQqUQ%azMh%f|scsjwYL`(~gEdmA+W)6MT%s@dzh7ZZKqfR{XvS{5G;F)N_WgAO zHwH3ckAyaNry>1hPBJ&ybFv|_7iAM<Q)P2yi)FsD7+HcWMV2PZk{M)XnN8LtJ0km3 z_POj|GKZ7GX@Jx7P6M4ZPD7nWIgNLk?DUS)d8f-xpE%ug`q}Asr@x(OKUqI{zp?!$ z_j{$^!hZGr4)*)2U$3)^^Rv!7odcbdoHL#Cor|2yovWSeoi94yb{Xd4=d#viqsw-e zAeShYWS2UZ8!n%@{NvK&@>o7Vu9gpxkCu;@zbaoKUm{;AUoYP*-!9)RkC7+Jb@HR~ z6Y}%&JMu^JKjoC^$1sd5^DHxlna0d!<}(|aEzC}44->+aGF41H)52V2t}r*5JIpW4 z-^{;RXSP2(fOThIVAbr4?09w#yM$fKZeq8wfov!n&1SMKY%6=3z0Tfe|6m_;E?j@k zjT^_!<b1gxPRkW>_1ppO2zQnHn!CsS*1v!MXZtJrPwxLl|K<JH^xxD!uzyVdr2e`6 z3;SF9SM`6p|MC7G_rKr2N1;%7C_EKv#W2N4#Y>9$igk*OiZDg0B41%uR4M8eEsEoc z4;5c2epe91W4<5XpI7li_>uf%{uSPbU%{{D*YSaTI3L4j@g}~Uujlvi2l-C^1b>#l z#9!ra@}KkH@b~%Ok!56DJzR&nj&+^n`m*aB*VkSBT-Uj7a^3E_+cn%Z#x>DZ@0#gq za5cM@x;D8UaXsdG%JrP<2d-CKue;uH{m%7Q*MD3eyScdacN^g5?k2hobsOn6-fg<u ze79w8Z@KxqZFSq}w#O~hphkx6XY#XsmN-Bdtmbpn1&Z0wTOrv6C}+|RRSX=YU{Q)H zNs&($`Q0HQyZI9J0T@M)Puz@G@bEKHy~Q(Q6uj_cw<m|tfN-o+7^#++LTAyR>CcW? z4*U|uFI`ly;}rZHg@%7gA@V@v@{`pX9?(?*KQo!1hlNjBh#=MuYs`aMt6Mh$)G)e{ z_!Zddc=3NFF?(6TV@4$MHemV55+M0O6NvCXND3Pi5{f@S!M}=@55|F>(ql;67$VQi z#!1Xl^UQb!Uzt>TU4d$2UKp<CrMZ`eZ)<63;|Ih0=FQb_|5mBY%gxWu6N^#?eVD1r z$O#M#-VwUP3v(2sUJu}%>##Dt&#%d<%t1>tQZx{BLkVj9+r!N<VoHKOE-j9W$)Q3L zkcETTL?R?r=ZM9zmiUqcE;VNB@OWj8F*`p;OfUIoX`#w?>$ftC#*&Md1z0@SVTqPo zBWx;O2v@`?`l#@DiAzW1rOU!IixfN(7wb;WR7=bS;QYnk>FSdw*Wr9$QuD%8HIGVg zzX@u7ySi1)6Z1AKl<uks25V_zA)!5`lLbnNX=@4Dt)U*^@N?Ot=HGy7gv^;=eRRud z{)oB+Q&T^OpH9)^0b%NyfHRJyvwsxJ))%i`qofO8f>$w<4iKpeJb=x<6lFTWd3hn4 z>BzdySVtDCE?qEL-q(D+{Na}0!<*7uGWTVb=aktBD&bTWR3(?_Y&(u^J{<Tp$EzHH z21lSHP{{+rVSY*(YGxcBs8O}MvK1K>;1(fQ=oL>;jKrJbIpPgPlAuom4vF+5@{#;d zz-#+g1NZ=j&>m2(4j{vjnvw85e2rlV(mqn}>Ot?4W>35j^f&|+t%-@*8A+PW@uAx` zf#jdCo0_*Bix)FW%d*Q<`&&wC>NIv=`z*V!W0pL+u0^+BRaTZ~D%BjTXzuJ%ddvH> zU7?+uD@0RLVt%4(04^K<Kip0Zk3McEqnh_u=yeADas>}+%L345^1<l0_B{rBpnbQJ ze-U2>Zcy+GQLi~sU8R6r80y~d(z_ECh^H~r)#NT-SeByTpYRC$hc-aOlNgM6$v_1C zMhpfMHh7+Yq70;+FVyU77W0^)vA!dyt12YiR1~ApL5DB3U<Z|ZmSmP@mS=LQjfc{^ zR3KXK2MFsX4X**97IccBrvhk}$x<v$RE%+WJOU$^^y!$QkJlD74md5X8kAM?NHrd4 z5hIu68}P%WyXLV>%}-a`1MC6lh<(#wSQuWY2FSV7-l;<ssKbwySSevk;6imW=?V$! z6OD}#3Bf$IkG80lOoiQj8}yD0Z38cLJZ;l}zDPQ6iAC>U-+ucq*b%7`6Ib9V%j16n zY5$>qi$%+r6gAJzQ}gH4-80IiyI-#8o}pLp=M=p&%5f6q>fRZt3SQ#9;z3tGT1^M@ zE)x__?9h{m^%GmvCsD!UQhV@_geZa}1WyNp+E2ifH3j$2TQ1|*t7{ef1jS=NW}|xP z>wu>$hmnE89A70}BVXD8I__hjJ_cL3l>wJ{zNOq;ZYuH0FM?QL5tq;8rRS%c((AXP zbe$H;iIL&ADPV1%FkZnq;o1E3f(%ne_xj%To(&Pz<~AkIW*23dGEBYeyVrY0G{mH$ zKY<Jptiv$373D=GCHQH$lTwe5Rq%c6X1riPt3frS#pQ01D(|(d7B#}K^IFXJ`PJ&j zH<{7!Sy!w1XhSr*Ez$PCf#uDJGyrx4K*1A^c=#>g-}2xM#R?ugS*Ljf<2-n8R>liY z_&A=@abPFUlw?CpNiz2YqFG#=FLAvhASTCMEW;0&e@ByGk9Y_Tn9)BbsX+rmBw7aI z$&k)gv@DyvtK{Po(o<6SM73o1cyE`}*y;a$@e(WmXN+?8!qo~XD9N)hiSb3y`QQ;1 z7o{6%=AkgczpgM)KVDu}S9;(eu3ScjX5G4pI2$yLc;nZpStp&L6lg*01%LihKV>D4 zh|tGj;8<{e#Wg&Jn-zRSgW*U+1Mg%oDV%w5k{F0Tk1$TJxfM<%Q7HhS=X11Ku^CAb zi3{Tw$L-LCCnQC2sjM+vo?%Qi>O^auk*`+_cuMC>eP%qB`5~_<`0a{bK%Sth(hbCu z#Fxw;+tm*KIdIUm@9N{A6M5;;kp?k|W{Yo3sMA`+NK0sDTx{Q?qUHxrojMq&&hjM| zV_vbw1mQAOHmgg`%!H(DiWiUzjq-{1FIjYAQ1hS*z&k}Bme*--sI`%r*L>uXykxhA z@2G9;d<W(aVr{i4HL)dPtW|4_(WhtWGLq9dJ{7zB{GcAdHZ5CRvRFl(=&rSRS_YF{ zYcVZ$BD+qJ!5DIbe+eEn3V-&E+V{&Z`{a1&93B!pn4hRPxo*0emppp2{RMIa^tG;- z4R+E1;)YszZ<l5s^y>ymaO?^9D1S};U;^KbX8`sUQm9@$?LT%b1vU0qK#)oQpPu~1 z5|RI~k7R)Vk29nh(3~XK9zUIOL4~x(n6D0A)&LciUy#S~li2FGlJGF4gu$0CZBt2O zb)|Tp<%O{dJ{kSlmdqbaI-sq`Bc{RA)W>?v$HrxbTC`q~mb!#S6(6GB1M2{jQC<XH zne>zr4UfpzM)b|+6>&*Cd1m<U^cl%I0LtY|R^(_7pRBojSy`G}mQyP7?3-%7$Y9DX z`Y+Fp&1S2pR1PRAE;gIYUUs>?Nq*mP8KhpWgynDUB>cpQJ1IYRZU^PR|GtCpH>Dv$ z%T7=LWV%r;aRl&Ar@fhh2n;Ueg}G>lN1>WG6%`blVN2i@*+8U|Y~zJhemj<o^}lrE z(_`nZeev;>>7wHweybP}6B8X5@%KxfR$ED_&C1m@@Wa#tpo&|RQIu{=FH0?@8WQVC zTX=%e;B}(;gs9JwK`4%x+xMj6p5dl?@N8R*IU+*D!_s5MyqE_eGrk~6!?Wlp!@x5& zAFpBHOyvb>)LF3N{Iy2)weu?$i2VCl>wSsNR6!>rnm)I4sfMR)Zfv%E=N7|y)ol7) zeqI^|hcOZ*ecz83!uH+39kYQOD4G8+3EES}GhBSFlffum38#9=2qCl5XH$5xSkb~e zcTrY2r{En(-OxDNPGA0uzDQmkhYgn~c%ynid>SMYP|b2v0!n9O!}{Xcf%%0X_k;)h za-TDrl6Z5RHJ;NI6=(3iC)a%-B@Qq&RrGOX-(-2<H*aF(<>^frK3@0;=11^m`Z>X( zY&S$i@C`655t3m+StJj!Bv5Sgabg3;UJz9>u$}N#se$_QtTb>x;gy6moZ={ko&aAu z(1$8idxA~2aB0Zwd(DJR!(AvgS&KB*3Ug&i1$XNVFX0-x5o_inB%hC$cdB`b)}#>T zY#tySuseKd1;|HOiK^Qqn)n_dq<QTX^&X!1EkvttegT*KDSsdCCZ1j%mJf~drv@H@ ztKB?oI))3-7`W)LD>0iDd}CdCJ>1^9%;wli9$KqfXst#{TC2RU9ge!hU<Ats_=~`6 zfb@iKDDd%#iSa!0BI?V$m=7p!DtNAW0m&ww8kv+-11@fPQk)UzP+4h#cqlJOeiM%f zy9ZyPswn3{{eu>{l5u$GDu^pCUj~|^P&2$(s({I(A>l|zdeA5g^DojrwX{*0oX5K$ oMn#JeYGU{pbzL1U=O}QI<Cx4B=r}K`2S}bYAE*l4!^>p<2eKYy*8l(j literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.eot b/src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.eot new file mode 100755 index 0000000000000000000000000000000000000000..7c79c6a6bc9a128a2a8eaffbe49a4338625fdbc2 GIT binary patch literal 38205 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 E0QL`y%>V!Z literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.svg b/src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.svg new file mode 100755 index 0000000..45fdf33 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.svg @@ -0,0 +1,414 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata></metadata> +<defs> +<font id="fontawesomeregular" horiz-adv-x="1536" > +<font-face units-per-em="1792" ascent="1536" descent="-256" /> +<missing-glyph horiz-adv-x="448" /> +<glyph unicode=" " horiz-adv-x="448" /> +<glyph unicode="&#x09;" horiz-adv-x="448" /> +<glyph unicode="&#xa0;" horiz-adv-x="448" /> +<glyph unicode="&#xa8;" horiz-adv-x="1792" /> +<glyph unicode="&#xa9;" horiz-adv-x="1792" /> +<glyph unicode="&#xae;" horiz-adv-x="1792" /> +<glyph unicode="&#xb4;" horiz-adv-x="1792" /> +<glyph unicode="&#xc6;" horiz-adv-x="1792" /> +<glyph unicode="&#x2000;" horiz-adv-x="768" /> +<glyph unicode="&#x2001;" /> +<glyph unicode="&#x2002;" horiz-adv-x="768" /> +<glyph unicode="&#x2003;" /> +<glyph unicode="&#x2004;" horiz-adv-x="512" /> +<glyph unicode="&#x2005;" horiz-adv-x="384" /> +<glyph unicode="&#x2006;" horiz-adv-x="256" /> +<glyph unicode="&#x2007;" horiz-adv-x="256" /> +<glyph unicode="&#x2008;" horiz-adv-x="192" /> +<glyph unicode="&#x2009;" horiz-adv-x="307" /> +<glyph unicode="&#x200a;" horiz-adv-x="85" /> +<glyph unicode="&#x202f;" horiz-adv-x="307" /> +<glyph unicode="&#x205f;" horiz-adv-x="384" /> +<glyph unicode="&#x2122;" horiz-adv-x="1792" /> +<glyph unicode="&#x221e;" horiz-adv-x="1792" /> +<glyph unicode="&#x2260;" horiz-adv-x="1792" /> +<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" /> +<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" /> +<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" /> +<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" /> +<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" /> +<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" /> +<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" /> +<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" /> +<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" /> +<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " /> +<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" /> +<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" /> +<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" /> +<glyph unicode="&#xf016;" horiz-adv-x="1280" d="M128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280zM768 896h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376zM1280 864v-896q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h640q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88z " /> +<glyph unicode="&#xf017;" d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" /> +<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136 q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" /> +<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273 t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01b;" d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198 t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" /> +<glyph unicode="&#xf01d;" d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q14 0 25 -9 l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" /> +<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" /> +<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" /> +<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" /> +<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" /> +<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" /> +<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" /> +<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" /> +<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" /> +<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" /> +<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" /> +<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" /> +<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" /> +<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q73 -1 153.5 -2t119 -1.5t52.5 -0.5l29 2q-32 95 -92 241q-53 132 -92 211zM21 -128h-21l2 79q22 7 80 18q89 16 110 31q20 16 48 68l237 616l280 724h75h53l11 -21l205 -480q103 -242 124 -297q39 -102 96 -235q26 -58 65 -164q24 -67 65 -149 q22 -49 35 -57q22 -19 69 -23q47 -6 103 -27q6 -39 6 -57q0 -14 -1 -26q-80 0 -192 8q-93 8 -189 8q-79 0 -135 -2l-200 -11l-58 -2q0 45 4 78l131 28q56 13 68 23q12 12 12 27t-6 32l-47 114l-92 228l-450 2q-29 -65 -104 -274q-23 -64 -23 -84q0 -31 17 -43 q26 -21 103 -32q3 0 13.5 -2t30 -5t40.5 -6q1 -28 1 -58q0 -17 -2 -27q-66 0 -349 20l-48 -8q-81 -14 -167 -14z" /> +<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q76 -32 140 -32q131 0 216 41t122 113q38 70 38 181q0 114 -41 180q-58 94 -141 126q-80 32 -247 32q-74 0 -101 -10v-144l-1 -173l3 -270q0 -15 12 -44zM541 761q43 -7 109 -7q175 0 264 65t89 224q0 112 -85 187q-84 75 -255 75q-52 0 -130 -13q0 -44 2 -77 q7 -122 6 -279l-1 -98q0 -43 1 -77zM0 -128l2 94q45 9 68 12q77 12 123 31q17 27 21 51q9 66 9 194l-2 497q-5 256 -9 404q-1 87 -11 109q-1 4 -12 12q-18 12 -69 15q-30 2 -114 13l-4 83l260 6l380 13l45 1q5 0 14 0.5t14 0.5q1 0 21.5 -0.5t40.5 -0.5h74q88 0 191 -27 q43 -13 96 -39q57 -29 102 -76q44 -47 65 -104t21 -122q0 -70 -32 -128t-95 -105q-26 -20 -150 -77q177 -41 267 -146q92 -106 92 -236q0 -76 -29 -161q-21 -62 -71 -117q-66 -72 -140 -108q-73 -36 -203 -60q-82 -15 -198 -11l-197 4q-84 2 -298 -11q-33 -3 -272 -11z" /> +<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q4 1 77 20q76 19 116 39q29 37 41 101l27 139l56 268l12 64q8 44 17 84.5t16 67t12.5 46.5t9 30.5t3.5 11.5l29 157l16 63l22 135l8 50v38q-41 22 -144 28q-28 2 -38 4l19 103l317 -14q39 -2 73 -2q66 0 214 9q33 2 68 4.5t36 2.5q-2 -19 -6 -38 q-7 -29 -13 -51q-55 -19 -109 -31q-64 -16 -101 -31q-12 -31 -24 -88q-9 -44 -13 -82q-44 -199 -66 -306l-61 -311l-38 -158l-43 -235l-12 -45q-2 -7 1 -27q64 -15 119 -21q36 -5 66 -10q-1 -29 -7 -58q-7 -31 -9 -41q-18 0 -23 -1q-24 -2 -42 -2q-9 0 -28 3q-19 4 -145 17 l-198 2q-41 1 -174 -11q-74 -7 -98 -9z" /> +<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l215 -1h293l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -42.5 2t-103.5 -1t-111 -1 q-34 0 -67 -5q-10 -97 -8 -136l1 -152v-332l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-88 0 -233 -14q-48 -4 -70 -4q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q8 192 6 433l-5 428q-1 62 -0.5 118.5t0.5 102.5t-2 57t-6 15q-6 5 -14 6q-38 6 -148 6q-43 0 -100 -13.5t-73 -24.5q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1744 128q33 0 42 -18.5t-11 -44.5 l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80z" /> +<glyph unicode="&#xf035;" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l446 -1h318l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -58.5 2t-138.5 -1t-128 -1 q-94 0 -127 -5q-10 -97 -8 -136l1 -152v52l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-82 0 -233 -13q-45 -5 -70 -5q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q6 137 6 433l-5 44q0 265 -2 278q-2 11 -6 15q-6 5 -14 6q-38 6 -148 6q-50 0 -168.5 -14t-132.5 -24q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1505 113q26 -20 26 -49t-26 -49l-162 -126 q-26 -20 -44.5 -11t-18.5 42v80h-1024v-80q0 -33 -18.5 -42t-44.5 11l-162 126q-26 20 -26 49t26 49l162 126q26 20 44.5 11t18.5 -42v-80h1024v80q0 33 18.5 42t44.5 -11z" /> +<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03d;" horiz-adv-x="1792" d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5 q39 -17 39 -59z" /> +<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" /> +<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" /> +<glyph unicode="&#xf042;" d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" /> +<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" /> +<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" /> +<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" /> +<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" /> +<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" /> +<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" /> +<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" /> +<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" /> +<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" /> +<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" /> +<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" /> +<glyph unicode="&#xf053;" horiz-adv-x="1152" d="M742 -37l-652 651q-37 37 -37 90.5t37 90.5l652 651q37 37 90.5 37t90.5 -37l75 -75q37 -37 37 -90.5t-37 -90.5l-486 -486l486 -485q37 -38 37 -91t-37 -90l-75 -75q-37 -37 -90.5 -37t-90.5 37z" /> +<glyph unicode="&#xf054;" horiz-adv-x="1152" d="M1099 704q0 -52 -37 -91l-652 -651q-37 -37 -90 -37t-90 37l-76 75q-37 39 -37 91q0 53 37 90l486 486l-486 485q-37 39 -37 91q0 53 37 90l76 75q36 38 90 38t90 -38l652 -651q37 -37 37 -90z" /> +<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" /> +<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf059;" d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59 q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05a;" d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf05c;" d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23 l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05d;" d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198 t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05e;" d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61 t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" /> +<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" /> +<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" /> +<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" /> +<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" /> +<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" /> +<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" /> +<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" /> +<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" /> +<glyph unicode="&#xf06b;" d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5 t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" /> +<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" /> +<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" /> +<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " /> +<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" /> +<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9 q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" /> +<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" /> +<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" /> +<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf077;" horiz-adv-x="1664" d="M1611 320q0 -53 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-486 485l-486 -485q-36 -38 -90 -38t-90 38l-75 75q-38 36 -38 90q0 53 38 91l651 651q37 37 90 37q52 0 91 -37l650 -651q38 -38 38 -91z" /> +<glyph unicode="&#xf078;" horiz-adv-x="1664" d="M1611 832q0 -53 -37 -90l-651 -651q-38 -38 -91 -38q-54 0 -90 38l-651 651q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l486 -486l486 486q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" /> +<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " /> +<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf080;" horiz-adv-x="1920" d="M512 512v-384h-256v384h256zM896 1024v-896h-256v896h256zM1280 768v-640h-256v640h256zM1664 1152v-1024h-256v1024h256zM1792 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5z M1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf081;" d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4 q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5 t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf082;" d="M1307 618l23 219h-198v109q0 49 15.5 68.5t71.5 19.5h110v219h-175q-152 0 -218 -72t-66 -213v-131h-131v-219h131v-635h262v635h175zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960 q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" /> +<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" /> +<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" /> +<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" /> +<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" /> +<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" /> +<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" /> +<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" /> +<glyph unicode="&#xf08c;" d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5 q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" /> +<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf092;" d="M394 184q-8 -9 -20 3q-13 11 -4 19q8 9 20 -3q12 -11 4 -19zM352 245q9 -12 0 -19q-8 -6 -17 7t0 18q9 7 17 -6zM291 305q-5 -7 -13 -2q-10 5 -7 12q3 5 13 2q10 -5 7 -12zM322 271q-6 -7 -16 3q-9 11 -2 16q6 6 16 -3q9 -11 2 -16zM451 159q-4 -12 -19 -6q-17 4 -13 15 t19 7q16 -5 13 -16zM514 154q0 -11 -16 -11q-17 -2 -17 11q0 11 16 11q17 2 17 -11zM572 164q2 -10 -14 -14t-18 8t14 15q16 2 18 -9zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-224q-16 0 -24.5 1t-19.5 5t-16 14.5t-5 27.5v239q0 97 -52 142q57 6 102.5 18t94 39 t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103 q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -103t0.5 -68q0 -22 -11 -33.5t-22 -13t-33 -1.5 h-224q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92 t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" /> +<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" /> +<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" /> +<glyph unicode="&#xf096;" horiz-adv-x="1408" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" /> +<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf099;" horiz-adv-x="1664" d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41 q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" /> +<glyph unicode="&#xf09a;" horiz-adv-x="768" d="M511 980h257l-30 -284h-227v-824h-341v824h-170v284h170v171q0 182 86 275.5t283 93.5h227v-284h-142q-39 0 -62.5 -6.5t-34 -23.5t-13.5 -34.5t-3 -49.5v-142z" /> +<glyph unicode="&#xf09b;" d="M1536 640q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -39.5 7t-12.5 30v211q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5 q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23 q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -89t0.5 -54q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5 t316.5 -131.5t131.5 -316.5z" /> +<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" /> +<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" /> +<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" /> +<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" /> +<glyph unicode="&#xf0a2;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM183 128h1298q-164 181 -246.5 411.5t-82.5 484.5q0 256 -320 256t-320 -256q0 -254 -82.5 -484.5t-246.5 -411.5zM1664 128q0 -52 -38 -90t-90 -38 h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" /> +<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" /> +<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" /> +<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" /> +<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33 t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580 q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100 q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" /> +<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0ac;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11 q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 10.5t-9.5 10.5q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5 q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5 q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5 t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-5 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3 q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25 q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5 t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5 t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10t17 -20q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21 q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5 q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3 q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5 t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q7 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5 q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7 q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" /> +<glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" /> +<glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" /> +<glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf0b2;" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z " /> +<glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75 t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5 t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" /> +<glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15 t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207 q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" /> +<glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " /> +<glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" /> +<glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148 q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108 q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6 q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" /> +<glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" /> +<glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235 z" /> +<glyph unicode="&#xf0c7;" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0c8;" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf0c9;" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5 t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23 l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" /> +<glyph unicode="&#xf0cd;" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41 q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472 q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" /> +<glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192 q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192 q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113 z" /> +<glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" /> +<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" /> +<glyph unicode="&#xf0d4;" d="M678 -57q0 -38 -10 -71h-380q-95 0 -171.5 56.5t-103.5 147.5q24 45 69 77.5t100 49.5t107 24t107 7q32 0 49 -2q6 -4 30.5 -21t33 -23t31 -23t32 -25.5t27.5 -25.5t26.5 -29.5t21 -30.5t17.5 -34.5t9.5 -36t4.5 -40.5zM385 294q-234 -7 -385 -85v433q103 -118 273 -118 q32 0 70 5q-21 -61 -21 -86q0 -67 63 -149zM558 805q0 -100 -43.5 -160.5t-140.5 -60.5q-51 0 -97 26t-78 67.5t-56 93.5t-35.5 104t-11.5 99q0 96 51.5 165t144.5 69q66 0 119 -41t84 -104t47 -130t16 -128zM1536 896v-736q0 -119 -84.5 -203.5t-203.5 -84.5h-468 q39 73 39 157q0 66 -22 122.5t-55.5 93t-72 71t-72 59.5t-55.5 54.5t-22 59.5q0 36 23 68t56 61.5t65.5 64.5t55.5 93t23 131t-26.5 145.5t-75.5 118.5q-6 6 -14 11t-12.5 7.5t-10 9.5t-10.5 17h135l135 64h-437q-138 0 -244.5 -38.5t-182.5 -133.5q0 126 81 213t207 87h960 q119 0 203.5 -84.5t84.5 -203.5v-96h-256v256h-128v-256h-256v-128h256v-256h128v256h256z" /> +<glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M876 71q0 21 -4.5 40.5t-9.5 36t-17.5 34.5t-21 30.5t-26.5 29.5t-27.5 25.5t-32 25.5t-31 23t-33 23t-30.5 21q-17 2 -50 2q-54 0 -106 -7t-108 -25t-98 -46t-69 -75t-27 -107q0 -68 35.5 -121.5t93 -84t120.5 -45.5t127 -15q59 0 112.5 12.5t100.5 39t74.5 73.5 t27.5 110zM756 933q0 60 -16.5 127.5t-47 130.5t-84 104t-119.5 41q-93 0 -144 -69t-51 -165q0 -47 11.5 -99t35.5 -104t56 -93.5t78 -67.5t97 -26q97 0 140.5 60.5t43.5 160.5zM625 1408h437l-135 -79h-135q71 -45 110 -126t39 -169q0 -74 -23 -131.5t-56 -92.5t-66 -64.5 t-56 -61t-23 -67.5q0 -26 16.5 -51t43 -48t58.5 -48t64 -55.5t58.5 -66t43 -85t16.5 -106.5q0 -160 -140 -282q-152 -131 -420 -131q-59 0 -119.5 10t-122 33.5t-108.5 58t-77 89t-30 121.5q0 61 37 135q32 64 96 110.5t145 71t155 36t150 13.5q-64 83 -64 149q0 12 2 23.5 t5 19.5t8 21.5t7 21.5q-40 -5 -70 -5q-149 0 -255.5 98t-106.5 246q0 140 95 250.5t234 141.5q94 20 187 20zM1664 1152v-128h-256v-256h-128v256h-256v128h256v256h128v-256h256z" /> +<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf0da;" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" /> +<glyph unicode="&#xf0e1;" d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329 q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" /> +<glyph unicode="&#xf0e2;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" /> +<glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14 q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28 q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" /> +<glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5 t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29 q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" /> +<glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5 t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" /> +<glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5 t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129 q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" /> +<glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" /> +<glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68 z" /> +<glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69 q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47 q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5 t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" /> +<glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" /> +<glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" /> +<glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" /> +<glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68 t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252 t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" /> +<glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" /> +<glyph unicode="&#xf0f3;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1664 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5 q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" /> +<glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f6;" horiz-adv-x="1280" d="M1024 352v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1024 608v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280z M768 896h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376zM1280 864v-896q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h640q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5 t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320 v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152 q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96 q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q261 -58 287 -93z" /> +<glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" /> +<glyph unicode="&#xf0fd;" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf0fe;" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf100;" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" /> +<glyph unicode="&#xf101;" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf102;" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf103;" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf104;" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf105;" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf106;" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf107;" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf108;" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf109;" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" /> +<glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf10b;" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf10c;" d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103 t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" /> +<glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" /> +<glyph unicode="&#xf110;" horiz-adv-x="1568" d="M496 192q0 -60 -42.5 -102t-101.5 -42q-60 0 -102 42t-42 102t42 102t102 42q59 0 101.5 -42t42.5 -102zM928 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -66 -47 -113t-113 -47t-113 47t-47 113 t47 113t113 47t113 -47t47 -113zM1360 192q0 -46 -33 -79t-79 -33t-79 33t-33 79t33 79t79 33t79 -33t33 -79zM528 1088q0 -73 -51.5 -124.5t-124.5 -51.5t-124.5 51.5t-51.5 124.5t51.5 124.5t124.5 51.5t124.5 -51.5t51.5 -124.5zM992 1280q0 -80 -56 -136t-136 -56 t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1536 640q0 -40 -28 -68t-68 -28t-68 28t-28 68t28 68t68 28t68 -28t28 -68zM1328 1088q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5z" /> +<glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" /> +<glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" /> +<glyph unicode="&#xf114;" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf115;" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z " /> +<glyph unicode="&#xf116;" horiz-adv-x="1792" /> +<glyph unicode="&#xf117;" horiz-adv-x="1792" /> +<glyph unicode="&#xf118;" d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5 t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf119;" d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204 t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf11a;" d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf11b;" horiz-adv-x="1920" d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150 t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" /> +<glyph unicode="&#xf11c;" horiz-adv-x="1920" d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16 h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16 h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96 q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896 h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="&#xf11d;" horiz-adv-x="1792" d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9 h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102 q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" /> +<glyph unicode="&#xf11e;" horiz-adv-x="1792" d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2 q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266 q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8 q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" /> +<glyph unicode="&#xf120;" horiz-adv-x="1664" d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9 t9 -23z" /> +<glyph unicode="&#xf121;" horiz-adv-x="1920" d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5 l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" /> +<glyph unicode="&#xf122;" horiz-adv-x="1792" d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1 q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" /> +<glyph unicode="&#xf123;" horiz-adv-x="1664" d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5 l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" /> +<glyph unicode="&#xf124;" horiz-adv-x="1408" d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" /> +<glyph unicode="&#xf125;" horiz-adv-x="1664" d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23 v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf126;" horiz-adv-x="1024" d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5 q-2 -287 -226 -414q-68 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497 q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" /> +<glyph unicode="&#xf127;" horiz-adv-x="1664" d="M439 265l-256 -256q-10 -9 -23 -9q-12 0 -23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320 q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18 l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9 t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" /> +<glyph unicode="&#xf128;" horiz-adv-x="1024" d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5 t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" /> +<glyph unicode="&#xf129;" horiz-adv-x="640" d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192 q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf12a;" horiz-adv-x="640" d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" /> +<glyph unicode="&#xf12b;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1534 846v-206h-514l-3 27 q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5t-65.5 -51.5t-30.5 -63h232v80 h126z" /> +<glyph unicode="&#xf12c;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1536 -50v-206h-514l-4 27 q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73h232v80h126z" /> +<glyph unicode="&#xf12d;" horiz-adv-x="1920" d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" /> +<glyph unicode="&#xf12e;" horiz-adv-x="1664" d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5 t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89 q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117 q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" /> +<glyph unicode="&#xf130;" horiz-adv-x="1152" d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5 t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" /> +<glyph unicode="&#xf131;" horiz-adv-x="1408" d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128 q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23 t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" /> +<glyph unicode="&#xf132;" horiz-adv-x="1280" d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150 t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf133;" horiz-adv-x="1664" d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf134;" horiz-adv-x="1408" d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800 q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113 q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" /> +<glyph unicode="&#xf135;" horiz-adv-x="1664" d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1 q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" /> +<glyph unicode="&#xf136;" horiz-adv-x="1792" d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" /> +<glyph unicode="&#xf137;" d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf138;" d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf139;" d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf13a;" d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf13b;" horiz-adv-x="1408" d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" /> +<glyph unicode="&#xf13c;" horiz-adv-x="1792" d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" /> +<glyph unicode="&#xf13d;" horiz-adv-x="1792" d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-13 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352 q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19 t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf13e;" horiz-adv-x="1152" d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181 v-320h736z" /> +<glyph unicode="&#xf140;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150 t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf141;" horiz-adv-x="1408" d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf142;" horiz-adv-x="384" d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf143;" d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 232 -177 396t-396 177q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128q13 0 23 10 t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf144;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56 q16 -8 32 -8q17 0 32 9z" /> +<glyph unicode="&#xf145;" horiz-adv-x="1792" d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136 t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" /> +<glyph unicode="&#xf146;" d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" /> +<glyph unicode="&#xf147;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5 t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf148;" horiz-adv-x="1024" d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" /> +<glyph unicode="&#xf149;" horiz-adv-x="1024" d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" /> +<glyph unicode="&#xf14a;" d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5 t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14b;" d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14c;" d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14d;" d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q10 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5 t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14e;" d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf150;" d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf151;" d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf152;" d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf153;" horiz-adv-x="1024" d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9 t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26 l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" /> +<glyph unicode="&#xf154;" horiz-adv-x="1024" d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7 q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" /> +<glyph unicode="&#xf155;" horiz-adv-x="1024" d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43 t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5 t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50 t53 -63.5t31.5 -76.5t13 -94z" /> +<glyph unicode="&#xf156;" horiz-adv-x="898" d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102 q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf157;" horiz-adv-x="1027" d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61 l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" /> +<glyph unicode="&#xf158;" horiz-adv-x="1280" d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128 q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" /> +<glyph unicode="&#xf159;" horiz-adv-x="1792" d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23 t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28 q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf15a;" horiz-adv-x="1280" d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164 l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30 t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" /> +<glyph unicode="&#xf15b;" horiz-adv-x="1280" d="M1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544v-544q0 -40 28 -68t68 -28h544zM1277 896h-509v509q82 -15 132 -65l312 -312q50 -50 65 -132z" /> +<glyph unicode="&#xf15c;" horiz-adv-x="1280" d="M1024 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1024 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28 t-28 68v1344q0 40 28 68t68 28h544v-544q0 -40 28 -68t68 -28h544zM1277 896h-509v509q82 -15 132 -65l312 -312q50 -50 65 -132z" /> +<glyph unicode="&#xf15d;" horiz-adv-x="1664" d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23 v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162 l230 -662h70z" /> +<glyph unicode="&#xf15e;" horiz-adv-x="1664" d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150 v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248 v119h121z" /> +<glyph unicode="&#xf160;" horiz-adv-x="1792" d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832 q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf161;" horiz-adv-x="1792" d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192 q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf162;" d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23 zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5 t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" /> +<glyph unicode="&#xf163;" d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9 t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13 q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" /> +<glyph unicode="&#xf164;" horiz-adv-x="1664" d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76 q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5 t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" /> +<glyph unicode="&#xf165;" horiz-adv-x="1664" d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135 t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121 t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" /> +<glyph unicode="&#xf166;" d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 16 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15 q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38 q21 -28 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5 q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78l24 -69t23 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38q-51 0 -78 -38 q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf167;" d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73 q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51 q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99 q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-37 -51 -106 -51q-67 0 -105 51 q-28 38 -28 118v175q0 80 28 117q38 51 105 51q69 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" /> +<glyph unicode="&#xf168;" horiz-adv-x="1408" d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942 q25 45 64 45h241q22 0 31 -15z" /> +<glyph unicode="&#xf169;" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" /> +<glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" /> +<glyph unicode="&#xf16c;" horiz-adv-x="1408" d="M928 135v-151l-707 -1v151zM1169 481v-701l-1 -35v-1h-1132l-35 1h-1v736h121v-618h928v618h120zM241 393l704 -65l-13 -150l-705 65zM309 709l683 -183l-39 -146l-683 183zM472 1058l609 -360l-77 -130l-609 360zM832 1389l398 -585l-124 -85l-399 584zM1285 1536 l121 -697l-149 -26l-121 697z" /> +<glyph unicode="&#xf16d;" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139v1142q0 81 58 139 t139 58h1142q81 0 139 -58t58 -139z" /> +<glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" /> +<glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf171;" horiz-adv-x="1408" d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22 t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18 t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5 t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" /> +<glyph unicode="&#xf172;" d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5 t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf173;" horiz-adv-x="1024" d="M390 1408h219v-388h364v-241h-364v-394q0 -136 14 -172q13 -37 52 -60q50 -31 117 -31q117 0 232 76v-242q-102 -48 -178 -65q-77 -19 -173 -19q-105 0 -186 27q-78 25 -138 75q-58 51 -79 105q-22 54 -22 161v539h-170v217q91 30 155 84q64 55 103 132q39 78 54 196z " /> +<glyph unicode="&#xf174;" d="M1123 127v181q-88 -56 -174 -56q-51 0 -88 23q-29 17 -39 45q-11 30 -11 129v295h274v181h-274v291h-164q-11 -90 -40 -147t-78 -99q-48 -40 -116 -63v-163h127v-404q0 -78 17 -121q17 -42 59 -78q43 -37 104 -57q62 -20 140 -20q67 0 129 14q57 13 134 49zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf175;" horiz-adv-x="768" d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" /> +<glyph unicode="&#xf176;" horiz-adv-x="768" d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" /> +<glyph unicode="&#xf177;" horiz-adv-x="1792" d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf178;" horiz-adv-x="1792" d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" /> +<glyph unicode="&#xf179;" horiz-adv-x="1408" d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q112 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65 q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" /> +<glyph unicode="&#xf17a;" horiz-adv-x="1664" d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" /> +<glyph unicode="&#xf17b;" horiz-adv-x="1408" d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30 t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5 h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" /> +<glyph unicode="&#xf17c;" d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-7 -10 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7 q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15 q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5 t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19 q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63 q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18l-4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92 q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152 q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-14 -1 -7 -7l4 -2 q14 -4 18 -31q0 -3 8 2zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5t-30 -18.5 t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43q-19 4 -51 9.5 t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49t-14 -48 q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54q110 143 124 195 q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5t-40.5 -33.5t-61 -14 q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5t15.5 47.5q1 -31 8 -56.5 t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" /> +<glyph unicode="&#xf17d;" d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81 t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19 q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -6 6.5 -17.5t7.5 -16.5q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6 t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf17e;" d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5 t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5 q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80 q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" /> +<glyph unicode="&#xf180;" horiz-adv-x="1664" d="M1483 512l-587 -587q-52 -53 -127.5 -53t-128.5 53l-587 587q-53 53 -53 128t53 128l587 587q53 53 128 53t128 -53l265 -265l-398 -399l-188 188q-42 42 -99 42q-59 0 -100 -41l-120 -121q-42 -40 -42 -99q0 -58 42 -100l406 -408q30 -28 67 -37l6 -4h28q60 0 99 41 l619 619l2 -3q53 -53 53 -128t-53 -128zM1406 1138l120 -120q14 -15 14 -36t-14 -36l-730 -730q-17 -15 -37 -15v0q-4 0 -6 1q-18 2 -30 14l-407 408q-14 15 -14 36t14 35l121 120q13 15 35 15t36 -15l252 -252l574 575q15 15 36 15t36 -15z" /> +<glyph unicode="&#xf181;" d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408 q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf182;" horiz-adv-x="1280" d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43 q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" /> +<glyph unicode="&#xf183;" horiz-adv-x="1024" d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" /> +<glyph unicode="&#xf184;" d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf185;" horiz-adv-x="1792" d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4 l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94 q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" /> +<glyph unicode="&#xf186;" d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61 t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" /> +<glyph unicode="&#xf187;" horiz-adv-x="1792" d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536 q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf188;" horiz-adv-x="1664" d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207 q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19 t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" /> +<glyph unicode="&#xf189;" horiz-adv-x="1920" d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-78 -100 -90 -131q-17 -41 14 -81q17 -21 81 -82h1l1 -1l1 -1l2 -2q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58 t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6 q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q17 19 38 30q53 26 239 24 q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2 q39 5 64 -2.5t31 -16.5z" /> +<glyph unicode="&#xf18a;" horiz-adv-x="1792" d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12 q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422 q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178 q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" /> +<glyph unicode="&#xf18b;" d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495 q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" /> +<glyph unicode="&#xf18c;" horiz-adv-x="1408" d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5 t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56 t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -5 1 -50.5t-1 -71.5q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5 t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5z" /> +<glyph unicode="&#xf18d;" horiz-adv-x="1280" d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z " /> +<glyph unicode="&#xf18e;" d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf190;" d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf191;" d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf192;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5 t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf193;" horiz-adv-x="1664" d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128 q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 16 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" /> +<glyph unicode="&#xf194;" d="M1254 899q16 85 -21 132q-52 65 -187 45q-17 -3 -41 -12.5t-57.5 -30.5t-64.5 -48.5t-59.5 -70t-44.5 -91.5q80 7 113.5 -16t26.5 -99q-5 -52 -52 -143q-43 -78 -71 -99q-44 -32 -87 14q-23 24 -37.5 64.5t-19 73t-10 84t-8.5 71.5q-23 129 -34 164q-12 37 -35.5 69 t-50.5 40q-57 16 -127 -25q-54 -32 -136.5 -106t-122.5 -102v-7q16 -8 25.5 -26t21.5 -20q21 -3 54.5 8.5t58 10.5t41.5 -30q11 -18 18.5 -38.5t15 -48t12.5 -40.5q17 -46 53 -187q36 -146 57 -197q42 -99 103 -125q43 -12 85 -1.5t76 31.5q131 77 250 237 q104 139 172.5 292.5t82.5 226.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf195;" horiz-adv-x="1152" d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160 q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf196;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832 q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf197;" horiz-adv-x="1792" /> +<glyph unicode="&#xf198;" horiz-adv-x="1792" /> +<glyph unicode="&#xf199;" horiz-adv-x="1792" /> +<glyph unicode="&#xf19a;" horiz-adv-x="1792" /> +<glyph unicode="&#xf19b;" horiz-adv-x="1792" /> +<glyph unicode="&#xf19c;" horiz-adv-x="1792" /> +<glyph unicode="&#xf19d;" horiz-adv-x="1792" /> +<glyph unicode="&#xf19e;" horiz-adv-x="1792" /> +<glyph unicode="&#xf500;" horiz-adv-x="1792" /> +</font> +</defs></svg> \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.ttf b/src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.ttf new file mode 100755 index 0000000000000000000000000000000000000000..e89738de5eaf8fca33a2f2cdc5cb4929caa62b71 GIT binary patch literal 80652 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.woff b/src/static/movio/templates/Minimal-in-blue/font/font-awesome/fontawesome-webfont.woff new file mode 100755 index 0000000000000000000000000000000000000000..8c1748aab7a790d510fb3f42a8a8971d96efa79d GIT binary patch literal 44432 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 VoBs<Y3))5i00001Qg^x6008Up2bBN- literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/img/bg/bg-body.png b/src/static/movio/templates/Minimal-in-blue/img/bg/bg-body.png new file mode 100644 index 0000000000000000000000000000000000000000..ddd976de99a87fdb49723ab97617c93cd05a686e GIT binary patch literal 469 zcmV;`0V@89P)<h;3K|Lk000e1NJLTq0015U0015Y0{{R3$sV(j00003b3#c}2nYz< z;ZNWI000tDOjJej@$vWf_xbtx_4W1t|Nryz^J1(;)c^nh32;bRa{vH}NB{teNCEK* za6$k803LKjSaefwW^{L9a%BKPWN%_+AVz6&Wp{6KYjYq&Q#CFzs~<?~0000NbVXQn zLvm$dbZKvHAXI5>WdJlSFgPtTFflY*l~D@-009k2L_t&-l|7L`s>Co1LtVn`qlzA& zl-WmPdXEWV?thgpckv5_Dt2t?HKdd5*T@_46PZAco?`;9wIY?cGxHWe-jP`931&6& z2r|_v;?Y-FCNa~R{s;;Lw&rX6LQ#@XUMUW(n0trsqqO&gJZErutOs?3e!_uv{Obh> zZMaV&?N8dymxR=o3>VtM`1lwt5zkoL;|&K>d?pTO@&5gS>+WO4d24(7BSx;&sVpBf z588lHa6Td3pFXY9fCJhuefqPf0yWIf<?1mfV$?j}6DOPr#kX~1$ys}$<~(=dZT1FZ zi)s4SfoDHr+dV4z<n1bc=IqMy`?iLEhMDe9iZ+9TPLSp2%x(JvXNW<aL)0LI00000 LNkvXXu0mjfG`-4O literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/img/bg/bg-box.png b/src/static/movio/templates/Minimal-in-blue/img/bg/bg-box.png new file mode 100644 index 0000000000000000000000000000000000000000..f54bbaf2212814e8b8021699fac05f6cf2d14d20 GIT binary patch literal 800 zcmV+*1K<3KP)<h;3K|Lk000e1NJLTq001cf001fo1^@s6F7$F(00004b3#c}2nYxW zd<bNS00009a7bBm000WZ000WZ0W>Kjs{jB19&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gH7+r$A4ux}000<tMObu0a%Ew3X>V>IRB3Hx05LQzFg7hRFflWgTr)!e z00MMLL_t(oh0U1Vj;b&eg};`D7!xr{CMLfByBROQpBQ4W&~w3QEr=s1$gG=j9BsbY zKdXBq4u^x0QlhnHN@=Z8N};tzN(q3Jk}wQWN+|%=>-Ch34$^<EwdQ)gA{UE=n3V3n zEEG`7YL;b4fW=}V(lkYDJzCnE=Qe@-NX}+6_qi|(D@cGij>Y+Wu7!L^HO~!#p!U8} z3S$faMNzo-%Ch7k)k%_=D2i$a456|t5keqD_v&&r+5AHs$0AMB!QiZ<l)V6LG=WD* zfX!wj&gb)}HQGf=se9wJDUM@tJRZNvRFhw`Pay$*etuj;r;s)FUm;=oh~|0z8WO6A zj_spOS>Jq_ZeL^jsIQ_ZT+{S|gu6YB9ZhTM^ZC50%f1JU<)c<*S-N|?bK|tB%}4Ej zKLjMy2adNO;j!!c+$PUtj6o?yp65U{XykeRcz5^JkavAi6wbt<YR+G8oUXE6Zx8)M zK@dEg@per%<=fMzpv`Q&)!ok&$FbP$c0(Ok(_oMQ+wE3lS;qBx?e#r>ENj!CkO0f& zQe;`yns(o&{I$VvmNpFz33tP{R-(18tV9Ust+sx<IKn89P#J!fW$yPd3<2EG&_|;| z0<2c6+7;T|5S3D$>UUH~s8WBqT*&jhwi#N`*=+XGwnm49Dx#OmrFPf*DR1*eUtfWQ z&*ssuLBjj<=vN`(y?ONOkkEgxp9B*6ZK0DvLifFXQb?G7ukWS9;b3mJo4MU?#u(#% zCP`u@kEE3~d@Fwd`7@AEf%;wV9`sKQ)>Lz6l2U%YEsmxAes7{ELTmkZApuUOlNs`n e_-HzvPUau0G^Ak#XRj6j0000<MNUMnLSTY$f^Js; literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/img/bg/bg-description.png b/src/static/movio/templates/Minimal-in-blue/img/bg/bg-description.png new file mode 100644 index 0000000000000000000000000000000000000000..fae27607a8a20104f6d3d5c489ff54bc755a5f05 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blmSQK*5Dp-y;YjHK@;M7UB8wRq zxP?HN@zUM8KR`jb64!{5;QX|b^2DN42FH~Aq*MjB%%art{G#k)1?ON>J;T-V9<PBa z#X%~ai&7IyGV}8kLNaqx87y=S%yo?n42>^OZp{QL;q`QJ4B?oWY+z<)$IQSqhcWH+ SnG|iH1cRrmpUXO@geCx@8!hqx literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/img/bg/bg-opacity.png b/src/static/movio/templates/Minimal-in-blue/img/bg/bg-opacity.png new file mode 100644 index 0000000000000000000000000000000000000000..859f2ea65f22658c9a33a79999d86c2be1983097 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blmSQK*5Dp-y;YjHK@;M7UB8wRq zx;#Lb@grA(6HrjD#5JNMI6tkVJh3R1!7(L2DOJHOvnaJZzbLy{!8zDe&v3Q8$7`TU zaga*qqSVBa%=|oskj&gv1`}Na3tb}vLzAeff!shPyq+$OAsjQ41Fo7_GBYrFF#3ln RJOsIj!PC{xWt~$(699N5ELi{m literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/img/ico/alert-error.png b/src/static/movio/templates/Minimal-in-blue/img/ico/alert-error.png new file mode 100644 index 0000000000000000000000000000000000000000..b2e8b957f30efe4892854be097591f71b5a2ac54 GIT binary patch literal 1454 zcmV;f1yTBmP)<h;3K|Lk000e1NJLTq001li001Tk1^@s6zaM#L00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy5G%YYT zEiy1MGk$A`KmY&$9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00ja`L_t(oh0U35Xj5kt$A7o2owbcjHt}sR2ClR+Ww3n_>W49P6PbcIP`WP*?$b7u zGPZ#Oi`2a#qE+eYONZ5}owMuIy5ZU(tE*JBSU084;tR7)o3^n{ZeDDYd-fssiOG_* zd9!-p4+;02^Zatoea^j43mG;M$q|t^MC8>>=gz2!h($z>h{!#8WSt_i=Sj0gnF-sb zD93JI7yrL^!noyVrq;^IP@ZaFap3-4+*R8#90LGkzwjajWn0kl^4E*VZB5g@NOvJE z-2@`C6!=X%Zk!dLhG3QD6fVG0Ru13=7HOK+oz8k$=>(fr2H<OH!WgoHNQC@1uQS?q z9v~0cn(kt00gK26V1+Sc$JcxY5s4|!>3YQD23T))Wb%PUBnPv)o>TQ09(P>ez@Qy( z^BEOd_C$bzoj~!}&A;(o_#H8fapgUCiol>9V1<Z$GO55KG9R!4=tmF4t!%gqj~n-~ zgDQp9?9k)@6Rd8Y??MY>_ijg2GJl<wnKg~ftZBqz{TQB^8oK7Ya*@%lzW|EO9FHH^ z+%zl2<HmVpA0kFb(^juz+VWK)->D^UlDB+SgpaFkpSo-{JN0;hfh_>;UmG#pI$}sj zxkU?=&oWcw7A=hM8M}KMZ)-CI$6V4?P72uEEG2<~ew-(dU>HV(1W~R5QwS2}H&Xi@ zMsUonOm@sA3@joR%#Ai&TNQH>JmL)xB+4(KyU@=zD32|V1sJFTiXYzS#Cz$_*uZg! zWBEEy)Z!oL2PjEq%q0XYBCi9b0FFK1#GSQ?R#<8H`@PD`YIZO)z(6^G^URNo+HDwO z#FWG!79_5}`%){u>sKK-=BhFREFx=xm4;hq_;}5@PqSnzEQY~g<(JB{)a+z>z`#a; z2ghsh>#nFBA7@I0@kURHaE<oc7&-leaxYH{SVSs-62INX@Xz%VzAvOwVKEFGbq6ur zIt0hu+LVCJO|S-_f5%qD2u!H>Q)2wMfIfnwZodlHm=ZAN81r1ag8SN)aoZZYB_ss= zoT=c8PXe)y#$$~2+aNgRDv|;=pFX7kecQ_?Y^jpoc3!18VG6zNe8Ta4+e6QgHSxw= zyb5mu7(86fXkSml3pyI=7(84ZN-}u38b?E2!tw6T%Xm63!#HCu>JVxkd-ex(7u}^R z)Ml78n=)$-^Xq<5Uzcf`)*OC4R)wtqeS5#f?{Z-nlC*MPDkN{=YbnJ(wDn>?6e{kf z|HDO8*u2>{`?|a6-tcZp6`J>X1vB1W4S=t^i#r?NCy->9vhxcltUpI~fd$|LP16pj zYoQ8@$n%)h?cM!##7lRgdiJe%6s#AxICXvzvp@PQ={$bjiEZ~+3e6h+W5REVN??w& zwFSMSJ>iWKt|_zTs$4sO%>Ywo&rK<p<Lpm(Z*>7I4j*$_W_6bW>jS!zo?Y7#I#kAz z-qEh|ZU!0wMr}PQ=j+|IP30?7$Ehsy^jZlpP=APrz4ue9h!_U0j&}ME?pBLTANix1 zo}CqG<#RMOK=3$K381MlrgyY+>%;dZ+7Ag^c7cU}?#f7>qT18s&Y1_WEDKlyFw}H1 z<<`ZL-{s6$o}s3bihoHCFbt5LZwdYZ?<usrmy6ZMtD5;bcLE^ba^m^t#uEdJWzz~5 zkZqX`U;`Eb!Bd5Zw93<Kts?RYL_g_f08iULQ?6>7_CS644_Lf%-}b0WfdBvi07*qo IM6N<$f>2qYivR!s literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/img/ico/alert-ok.png b/src/static/movio/templates/Minimal-in-blue/img/ico/alert-ok.png new file mode 100644 index 0000000000000000000000000000000000000000..1028f985b374e276ccd6a3f1eed040ad1bcb77b6 GIT binary patch literal 1289 zcmV+k1@`)hP)<h;3K|Lk000e1NJLTq001HY001Be1^@s6caN&c00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy5G%YYT zEiy1MGk$A`KmY&$9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00do0L_t(og|(PlOk7nIhQB>bnW4z7+*2sUVB-W-l%_%r)&Oa(XiRLisnI5ltv-N> zB|d2%G--Wq2z{s+Vod5S#Rsq?3QFr#FvS!~M60PvrxFU~Higawn6rGCIb@ibGeZlk zWG8!{^PfH6ti9J+dmY6(n~3ZODuGhK4qQ-5bp_pDZv;PtM7GaGq(}!@R~Qi~5)qe( zNWZgNx+lMu-)4Jc-sjO_Tq1Hp2T|(?@-0w1>>lE>^Sh<%8{?8Gd7y%=3B~%QlfdzH z0TGcSK=ZujrG5Nk7Q`E-$%@aXD*XV!AHbugb$~Df4FFf}{J^~CMnns1W8NE#dmR8a zpwhh7AiycWHs*Ekw`<T)lo*#nmSqco1F)|th=|kxbpU<N@6kjv)Rv`G>s>prxYizN z02sJ)k;(Z{Ls7P+fPCvVfKlKbfHeaVk#~W;bBi+!&Gtt1#*Wn8dbb6bSThh2$spj3 zU#2_o_*{nChZ0NKv>^weS1EN|f0?b7M;d|LVb|~c;~Fv)#ha{@r#+_+TY~Sc8YGZQ z4tg~=KToxziO*15l2k#w$qH~@DfP*UKt!YzKq)m4gQWqWZ@Lrb!i1qH$(+Xa)Ea$w zD)fHX3r$37M5G7k2l_>%M?^{tU{3%Qx93ObcV56JKEw9ZrWf?b&IV^+-OM2q*8rUW zx4k0(WLh>?0GCDNX{FS!LE7!W`v4awTG3?D&>Nc*ig+;b5eN!bLl6<k$G_?5ojOnN zR0jZivR<b+xjX^r6Op4qYx@Dfm6>iFu0IVS0CuInq<34CQW4iL*du2E+fDahT$*fO zy4W%HDIV=EWvSHw%|T~}TCe8f(qtRHXd5)Sf=o*u1j5xwX9f_FCSb2~VUpI7rm&sg zHU1^HJPvAe4g)mf&zN+Le}&sOX9!_2B~X?5vOa7v6awZzwyXj;H_~W0@u1U=pz(ap z8vr(k>l%Yjd$hSJORdIY+6WQCH4Fs*dD3>nb&XNaaMXzhW`05wjmJ_dX&Y^hx+EzZ zGN{aWQ6GkdYpAJ!M+O1gnSbA7%;Sjl%!=%lykk6^R0jTVea%Rx?>UoFY7zJm;H|=s z*papyO?<0rTN1YE5QgCzYGweXRDFP~?%A9}6eQaCX5@6#<Q2{K<Q&qwhT$4&%g(HU zywM2cj(Ub^{jVwJz6rG_QlDX8UOo83b!RO7($XxWQtBM=B+#2{-O7=|4|zOwSHv@C zq-HT$sm(pCPZu>@LoF=VD5Y)&{>c~CxJ35nz0JP7I^yFjX!xSGo$0k$;}T&7;TjVp z2<TPdDBvzjtLDwZlVn>8&_s*avMmMFWFOQYj~T9EzZXjoC=EXYD%`%ibly6PeWGod zrZ}aX1Np~D@O$I5QmTHX0QX#O2I^IRt++TR*JrQF_1UZ9TAW)})85;x_gVV}ifVg= zqS_ufJm0ges`eF;H2j|#00xv&)Auuv4g&B$LpZhz*wdpE00000NkvXXu0mjf$zViH literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/img/ico/arrow-baloon-big.png b/src/static/movio/templates/Minimal-in-blue/img/ico/arrow-baloon-big.png new file mode 100644 index 0000000000000000000000000000000000000000..7348b99777331bbeb13f4e09145d57b41f1558ae GIT binary patch literal 599 zcmV-d0;v6oP)<h;3K|Lk000e1NJLTq000sI000mO1^@s68wM|200004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy4G%YYT zEiy1MGnHI3LjV8(9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00FB>L_t(Ijh&LQZlgdDhJV%vTCK=H7Gw&)231ni+!Lg^Yfwm=G|4Nt;3@JDDR=-X z1g3)$Su`#!Bt&z24fr?{pHKOv)k-@v-~KzZ8kW+=#Q<nomVE~R-}gTNC;-34U42sf z7lZ*=0nm%0cx{?SHBF<6qId<Mk1;mp{u8tUpod|2Q&pAfx=wXnr>d$_VHn=bU>8A? zn{NP&vMjf4+p1w0)G!RHZCh2A<raW3=6vdE>dOj%o+OE1*R|^V{sij#Ue$H2k|goZ zTxl4o=P>4ZUL>UiV}HVoF-R%ld0sSgb8<94&;YP3%N|VAd?cd9+ldIKX+CCI_HbT1 zU3nTe=R9&<_fj9>x-K~9(Y$8iD9`g}BD&+8Uj%W^K}2_Xo<E;E(g0|29N!8dwo=NA zkV#TX2qCs{9N#WLK@hxImIYncuYz=4hh<p^g5YfqLYk)cLWmdJwy#1a*|rTK#7ml{ z_rN%QB3g|5nx^kSL=gaJyWQ>w5xs9VoBxK))wV5;$Ky|C7{-(1IA4MQfa5qY4C6`L l@AqoGUVj+`0Efc?zX1VMievRbFK++<002ovPDHLkV1j6L@8tjh literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/img/ico/arrow-baloon.png b/src/static/movio/templates/Minimal-in-blue/img/ico/arrow-baloon.png new file mode 100644 index 0000000000000000000000000000000000000000..8bf5f098b4317b167bb4c1f6a5212b274d546970 GIT binary patch literal 381 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)8<3o<+3y6TSc;uILpXq-h9ji|$mcBZh%9Dc z;1&X5#!GkW{s09fN?apKoQqNuOEUBG6hbm{QyB~`bq$PkjSLKp|2Iuz0;-V%sR_<c zD=AMbN@Z|N$xljEaLX)8Ezd8?E>>_3Hq|p+E${IfsPdwxi(`n!#MVCBuI2y{xAVo^ zc?VtZxTeT%X1v|F@{*tY39X=;?FV8TuP#t9(^~YS>!5wyEE|rV#qp&-ceKBk2rXqu zln`<ijNW){(lSkkM*Z8{mcHKQ`@pubLqdV=#OFDwk>CEwGd6V8FmJD%r`eTM|L|>J z<NalsFMj`%5SS?c;LX)*rM58+F6SJKd@t|MI_M_OoE>|e=Wqc}hsUd{n{<9J-nJE} zoAIPY-;~r!o;{y9142cwMcu!9makz|TmyeH&pFG6%lG!TuUqvh<SW+)mL{8o<F9pv RYJi?&@O1TaS?83{1OQkbk#hh5 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/img/logo-mobile.png b/src/static/movio/templates/Minimal-in-blue/img/logo-mobile.png new file mode 100644 index 0000000000000000000000000000000000000000..1f96a29d629e23853987df36b87d9a28a249efe8 GIT binary patch literal 1223 zcmeAS@N?(olHy`uVBq!ia0vp^6+mpl!3HE9|NS`%q*#ibJVQ8upoSx*1IXtr@Q5sC zVCZrLVMg}jvkn6V#Y<cxN}P*Q6H7Al^Atidb5j{ibPX(YjSLJ;qNWCN1C_{ulmzFe zm6RtIr7}3C<R_&nxMdclmgg5`7b`dio9Y>^miKrKv{1&=#WAE}&fD1=^Ilm=9RL6P z#kwb~le}Ul+c0!mZSPpelFFatKh<`{n~ry)XBHgjY1pY$*>Ff|<ulef>=xxK-f-__ zb>iIe>0^E-<MZD#|KFT946R?9`HNjB@#o*WvJ>WrYep0-NjNyMiPfD;Ool{`|B=$z z9qYQE7VX^ZyZf%&=9?@_O}?AD2ChiBURqdN+q-=Ea;3xnGA5}wPEv`vm+lhS^0S7| z$>Uvi*Q5EH(<dYt&1?wbI&7df@Aso7_r-$CE^BHmy<o!I>z4fb7^mWkvfT<T4uK*w zmT@uwMf)B<>G~*my)<!_n#^&>_1BpdS(arU`d)jaut%fILDO|<P~-DT_pjxf?>h=K z2r%8=_VBmee;p1c28Y#GZ{0k9)&{8hvrWdVX~iMs#eoOkmP!Auo4?<063gR{63qu0 zrlmFpb!Bbs(mDO0QtsZpdlfs=nd>!<rEi!d;VQUE=ka@8G43^CtJjuwE&9+|;<GMq zd-vC>v$q)^OuG3xR(0mnz);ay%NE{$uiT}yXU`soz$tr^t2(-EQv{uUB=E8^FUdT` z-f;HA&73x!(*dim3bZL&&E;co2n}sXoS}WpPUp1KtYsXB1sFC&tp&<mGCBJ8t!~5j zzef4><|{+AqBmCWy%+d6NNcLWOdkUoKA_h&=^V~5IVGAbFD}Z%uxs7to9Dw+Xa8KI zvT<9^vCZ=<lin=8n89!$Y-Y;!&1)ab_?K5yUe3-?^L4XVA;&a!hFNFTVy+)8v0`P= z5$ldI{8sqUwqo;>8Xfy-sgBo6RXm%rww^k=Eo$u@!>(sHVqCwt2Z~HNof;DxJ6Gm) zQq#@e{CR)vtl6d74$4<Fd>1_!R(4Nf`WyXb-(%~)0hRK!AJ&iE-M^WmZ&AkTJy%|r zTJ$l;Uf&qC_Q5W_oZHWS$F2=~oSVK`vf=-!%dcN+=iF|4UTMIi9Nwd3VHPgHl3^mX zXU`_vzXCwVgoduUp3UOeP_>uOOY@OM+hYrL`L*YiD)z?ZzYX4&%gg`_#wLXa{#y_H zcGw`~!_k;15j~&zK#d*yQjvY{<$D5EDvMXH;yS(Qhj9JMkVA(LJHN9zfBrm269X{X zAAg*2JmL3G%|E~T>g8kgrvHiAS$S>u&Yg@)MJAtY*}p$Vudu$pzi8*4&_iWMccj$Y zJ8>{7raUjy&6i_{@B270|EF4Z_|1h=lujERDdh3J?4bEHbz*3vv*9_%doj!XwiVyG zynW4s*d8}!8#}vy?>in=%Gt+z^*wgyOgmC|re1$l$ltYpJPuBJG@+iK<jlwVJpRp3 WAE|Si0qMXJg~8L+&t;ucLK6U4ZzC)K literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/img/logo.png b/src/static/movio/templates/Minimal-in-blue/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b040188710e70fc2f244c3bb30e22682e1a46d2c GIT binary patch literal 1979 zcma)7{X5fpAOEh%LfX{H5~JO6PP=K7smPS4d77u0$J;X_&%;zQ^dO-;beE*Y$kPyx zFd0)_#f~GRmNU*aBRR`iEJrmg+&kBG{{iQR_xpW)Uf1h-U!TwG^S)m1LN5=eJ?gsZ z008W9adsdm>!va=;2p}${kfU1EIZTfT!>&WSTN@~t32)|I|rr%K#}v`0a{Tf+bKaf z#W8^5lM+L@5Rpa#Y@<^mNrt$%G}48Xw1jj+dmoEqW~~O!QYBO8Z>D`3DS{H0l59wf zOCkXnQ}ij*<7hKXP`S4T0H{G-9BhdfX-hN|S$An4r$VgAul(!&gF3_?42C7%kx^@I ziC4Yh68p5M(Y)R`qw25^VW&AGyagFa!0(9#X%zT<z`w>q3uhggXPci}-!B@BjIHjo z)PDOm_`X<}^DZ^_ynI&iX{l@c$ZoOxiecpN_HX)t?PJheEY!(a?x1&Av@bP};`s{t z&j7zSY{;Xawq=>DzdcI|g1*xKEK}#>n|!DV&-l`Xw7&n8eB9p0&rrK&YgNTedT7R6 zCKntEaFoA7utQ7JwE)j*YctI#(H!LD*{}b<LSe9+;Cgi7uk<{~)49x<Rmr$u>6<#P zeKlvk`Uj5yQ`o?HYq<E4ZKMU_vFvn}$1^b}jL5_AFi8Tf>e<ZDevx19R5EOsVx@W+ zZ@j9&UHx*2eZId<dZ}wVu_q{id???$brKe3>oXK-h5?lmzFlJ1pae{J-oSDR5T1}Q z%3KQX2E01>sV|vJX??;)iXLb8^}HK-kSY&OMhIyFGv?Z0$9sQzmfo8p-deP<E0`mL zfklc{y{2PN(B{Th={Wt&$~@IZLen@*+~%wf;OfjCj=`cz;n)Y`k~<^OHgo|q#N+_z ztn2#LreXnSN8S1!2v%~qT<$Rx%C}obN5>A#Nxj=VIyyQM{oirPO5NQjp&d7<eeH+7 zES&O~*a1+tx3Z5{&Ync;X-)cQMBG|f&E%w_>u=uF*pJOg=?iY3j8~E|9~D~_s4zSa zZ+yos7xX@*&`5l`r0&U6QXs)q@5h&O=qitjQ4-)a^t%6o?8)?FNMvrV0kG>DsCq&s ze*=zsjTx)Cop_?3&1M?`V!1mn`qrKs_D7FMXz5&7mq~(E)gyg=26lWjrt8J!iZxx$ zT|iCT?^1q;PxD=wqFVBU`t>p?n~e?OgAA)Y)Z|eBteg}Gl#RtS@#30^Z!@xO=yVzl zd^iuXnPcz_gs?)q!Mdsd@jbeKxZzVEWj(quhP69S^W}3&i6V;)Po8}a03rO;Zc4vs zfz@l$N@%VL^S$^k-r^Jb`0&Kq`nqKht~_ip0S&7`X`0*_NlZ!tU5<dQ1*_LeH_Ef| z!&56OsmO9d)~^d`&SEDgCtx-czGxGVsN^G;S`fBLc|}(YYx}A;3hYz>{2d6)oL?(c zJ;Gp4dRq(;EjG2oF7`=T9ii-vwUv2#yRU$$zn^XAx|mrl$&@dPUSeDH5Ramgq<($D zS`G88<YN_wN;wR)J8#(}f5KVA*SI!aYwzCDl9E%B09B=y?!5S(pmU*F`T^fn4wiD3 z&Oam$9{8;>OThHDZ}W5GXZVI1z~SxxHu_|I-AhzXL{282$QDaz7y3gU4+)mecTESs zsJQ#&%{k|zogX<)Wyp~NMqxeI+fuM<E%freV)aGJM^Tr}hpA!?{n>P4%K$^A=@tV? zHM_8N<f9w77HMG74_<$p!45Ei8yM6Pbh^G$ZMOAGB@)S+(e%trI}w>5;ia*CY`v8# zQ{?>QxX2pp?e+g@zg3kM&>du&xcXI*ZCy)5&h0v}cJHqGJ(B3$2PWEm-}TTAekZ7b z8o`ONh8yVV!SW*>7;A-4PcdFpjzp6+X*8Ph6N$*4so$Szo2=$R=r-9b(L=<&&;BgV zfe7+mi4ZfE)@Kbb4dGXfOI*(a;SU=Byu#R@MJ5A4endSl?j<^{PY;f)7;S258kC`Q z17}_bf&@(LxP4g3yvfGK%Dmc4$j6+?FZ?GapDH6acLIeDkNjFgB;HtD9;6tzQ$DfX zIB4z{*z0Pft?c1%GhyK_5Q$VTQ*G$ZMoP&t4h~Ooxmw>2K!*d!lQ{64Vo=J8jg4KW z!gZ3Xu~|&vFOlK2RfSwu;d-RJu=8Y5vlT2CaeGQ65($MWmy3&wn>^{pcU%_Sc-=av z&;jbYHfmZZq^^CQQ~F0tS7lLdY^;-o-odC+gEQ4*F<sM|rZuUDRU|_6Ekbj5XD4)E zQ*AGt%w37*VOl5Sk5_)6DeWqSf^$dwsdsGz^{(MIVK8$Q=US+-cFT;L*~EL1*us*H z7CWeToVd5fTFE=J!)d7PJ|c(yi`Y$Rl-`KCH{hn!mKHNj`vvaM$=-I1Hk8$ll4s2C z&Q&SQF?}q-Mo%8~Pa(M+b*h6d6K^`HK%uw!mVECvzj7%N*$|`gpfOwdfL|NjuRb+Z z4l4jF#)*>sRcqpcYQ26ox#{5PFlLqE36Wmi;+7Tst3C@+Qnp-p%8vEpd+=iQKLx(4 Z-Qa&4&Tlk6quif>i=&4_yIuIz{{i3Cynp}z literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/img/logo_movio.png b/src/static/movio/templates/Minimal-in-blue/img/logo_movio.png new file mode 100644 index 0000000000000000000000000000000000000000..d7cffcac6eb10d96c4be0be6893d2145667d7658 GIT binary patch literal 1878 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 QrvLx|07*qoM6N<$f`-m>mjD0& literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/js/bootstrap.min.js b/src/static/movio/templates/Minimal-in-blue/js/bootstrap.min.js new file mode 100755 index 0000000..b04a0e8 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/js/bootstrap.min.js @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.1.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.isLoading=!1};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",f.resetText||d.data("resetText",d[e]()),d[e](f[b]||this.options[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},b.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});return this.$element.trigger(j),j.isDefaultPrevented()?void 0:(this.sliding=!0,f&&this.pause(),this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")),f&&this.cycle(),this)};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);!e&&f.toggle&&"show"==c&&(c=!c),e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(b){a(d).remove(),a(e).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown",h),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=" li:not(.divider):visible a",i=f.find("[role=menu]"+h+", [role=listbox]"+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j<i.length-1&&j++,~j||(j=0),i.eq(j).focus()}}}};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.dropdown.Constructor=f,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu], [role=listbox]",f.prototype.keydown)}(jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show().scrollTop(0),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)}))},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=a.support.transition&&c;if(this.$backdrop=a('<div class="modal-backdrop '+c+'" />').appendTo(document.body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());c.is("a")&&b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this,d=this.tip();this.setContent(),this.options.animation&&d.addClass("fade");var e="function"==typeof this.options.placement?this.options.placement.call(this,d[0],this.$element[0]):this.options.placement,f=/\s?auto?\s?/i,g=f.test(e);g&&(e=e.replace(f,"")||"top"),d.detach().css({top:0,left:0,display:"block"}).addClass(e),this.options.container?d.appendTo(this.options.container):d.insertAfter(this.$element);var h=this.getPosition(),i=d[0].offsetWidth,j=d[0].offsetHeight;if(g){var k=this.$element.parent(),l=e,m=document.documentElement.scrollTop||document.body.scrollTop,n="body"==this.options.container?window.innerWidth:k.outerWidth(),o="body"==this.options.container?window.innerHeight:k.outerHeight(),p="body"==this.options.container?0:k.offset().left;e="bottom"==e&&h.top+h.height+j-m>o?"top":"top"==e&&h.top-m-j<0?"bottom":"right"==e&&h.right+i>n?"left":"left"==e&&h.left-i<p?"right":e,d.removeClass(l).addClass(e)}var q=this.getCalculatedOffset(e,h,i,j);this.applyPlacement(q,e),this.hoverState=null;var r=function(){c.$element.trigger("shown.bs."+c.type)};a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,r).emulateTransitionEnd(150):r()}},b.prototype.applyPlacement=function(b,c){var d,e=this.tip(),f=e[0].offsetWidth,g=e[0].offsetHeight,h=parseInt(e.css("margin-top"),10),i=parseInt(e.css("margin-left"),10);isNaN(h)&&(h=0),isNaN(i)&&(i=0),b.top=b.top+h,b.left=b.left+i,a.offset.setOffset(e[0],a.extend({using:function(a){e.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),e.addClass("in");var j=e[0].offsetWidth,k=e[0].offsetHeight;if("top"==c&&k!=g&&(d=!0,b.top=b.top+g-k),/bottom|top/.test(c)){var l=0;b.left<0&&(l=-2*b.left,b.left=0,e.offset(b),j=e[0].offsetWidth,k=e[0].offsetHeight),this.replaceArrow(l-f+j,j,"left")}else this.replaceArrow(k-g,k,"top");d&&e.offset(b)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach(),c.$element.trigger("hidden.bs."+c.type)}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.hoverState=null,this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(a(c).is("body")?window:c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);{var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})}},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(b.RESET).addClass("affix");var a=this.$window.scrollTop(),c=this.$element.offset();return this.pinnedOffset=c.top-a},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"top"==this.affixed&&(e.top+=d),"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(b.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:c-h-this.$element.height()}))}}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/js/jquery-1.8.2.min.js b/src/static/movio/templates/Minimal-in-blue/js/jquery-1.8.2.min.js new file mode 100755 index 0000000..bc3fbc8 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/js/jquery-1.8.2.min.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call(" ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/js/main.js b/src/static/movio/templates/Minimal-in-blue/js/main.js new file mode 100755 index 0000000..3abd062 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/js/main.js @@ -0,0 +1,10 @@ +$(function() { + Movio.init(); + + // SHOW MENU + $('.btn-menu').on('click', function(e) { + $('.js-header').toggleClass("show-menu"); + $('.item-box').toggleClass("ie-hide-iframe"); + e.preventDefault(); + }); +}); diff --git a/src/static/movio/templates/Minimal-in-blue/less/element.less b/src/static/movio/templates/Minimal-in-blue/less/element.less new file mode 100755 index 0000000..0a3ecb8 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/element.less @@ -0,0 +1,1271 @@ +/** + * Search form in top bar + */ +form.top-search { + float:right; + position:relative; + p { + .padding-margin-reset(); + label, input[type="text"] { + display:inline-block; + float:left; + } + label { + padding:4px 8px 0 0; + color:#fff; + display:none; + } + input[type="text"] { + width:250px; + height: 30px + } + + input[type="submit"] { + width:35px; + height:24px; + padding:0; + text-indent:-9999px; + background:transparent; + position:absolute; + top:0; + right:0; + z-index:3; + margin:3px 3px 0 0; + border-left:1px solid @form-border; + .border-radius(0); + } + + .fa { + z-index:2; + top:0; + right:0; + position:absolute; + font-size:17px; + margin:6px 12px 0 0; + color:@icon-in-page; + } + } +} + +/** + * Page title + */ + .box-title { + padding-bottom:10px; + margin-bottom:0; + + h1 { + border-bottom:1px @solid @box-border; + margin-bottom:8px; + } + + h2 { + font-style:italic; + font-size:20px; + } + +} + +/** + * Box with collapse button + */ +.box { + position:relative; + background:@box-background; + margin-bottom:40px; + padding:0; + + &.col-md-1 { + .grid(4, 1, 4.5%); + float:left; + + &:last-child { + margin-right:0; + } + + } + + &.col-md-2 { + .grid(4, 2, 4.5%); + float:left; + + &:last-child { + margin-right:0; + } + + } + + &.col-md-3 { + .grid(4, 3, 4.5%); + float:left; + + &:last-child { + margin-right:0; + } + + } + + &.col-md-4 { + .grid(4, 4, 0); + float:left; + + &:last-child { + margin-right:0; + } + + } + + .box-shadow (@x: 0, @y: 0, @blur:3px, @color: #999); + + + h1 { + .padding-margin-reset(); + font-size:18px; + line-height:1.2em; + font-weight:600; + padding:10px; + + a { + + &:hover { + text-decoration:none; + } + + } + + } + + .container { + .padding-margin-reset(); + position:relative; + width:auto; + margin:0 10px; + padding:10px 0; + border-top:1px solid @box-border; + } + + .wrapper-link { + height:23px; + background:#f0f0f0; + text-align:right; + padding:0 8px; + font-size:15px; + border-top:1px solid @box-border; + } + + img { + margin-bottom:0; + } + + p { + word-break:break-strict; + font-size:13px; + color:@text; + .padding-margin-reset(); + + a { + color:@text; + + &:hover { + text-decoration:none; + } + + } + } + + .show-content-box { + border:1px @solid @color-border-button; + position:absolute; + width:18px; + height:17px; + display:block; + text-indent:-9999px; + cursor:pointer; + top:0; + margin-top:0; + margin-left:0; + padding:0; + .border-radius(0); + background:transparent; + &:after { + top:50%; + margin-top:-1px; + content:" "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border: @solid transparent; + border-top-color:@color-arrow-button-slider; + border-width: 6px; + left: 50%; + margin-left: -6px; + } + &:hover { + &:after { + border-top-color:@color-arrow-button-slider-hover; + } + } + &.collapsed { + &:after { + top:50%; + margin-top:-9px; + content:" "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border: @solid transparent; + border-color:transparent; + border-bottom-color:@color-arrow-button-slider; + border-width: 6px; + left: 50%; + margin-left: -6px; + } + &:hover { + &:after { + border-bottom-color:@color-arrow-button-slider-hover; + } + } + } + } +} + + +/** + * Home slider + */ +article.slideshow { + min-height:290px; + position:relative; + background-color:transparent; + z-index:2; + padding:0; + overflow:hidden; + margin-bottom:40px; + padding-top:12px; + border-top:1px solid @color1; + + .slide { + margin:0 0 0 0; + padding:0; + height:290px; + @media (max-width: 480px) { + height:360px; + background-position:bottom!important; + background-size:320px; + } + img { + width:70%; + float:right; + margin:0; + .box-sizing(); + height:290px!important; + @media (max-width: 480px) { + width:100%!important; + float:none!important; + height:auto!important; + } + } + .description { + float:left; + width:385px; + .box-sizing(); + background:url(../img/bg/bg-opacity.png) repeat; + margin-left:0; + padding-left:15px; + min-height:290px; + margin-left:20px; + position:relative; + @media (max-width: 480px) { + min-height:200px!important; + padding-left:10px; + width:100%!important; + } + background-color:none; + + h1 { + font-family: @font-1; + font-weight: 600; + font-size:45px; + margin:45px 0 10px 0; + line-height:1em; + text-align:center; + text-transform:uppercase; + a { + color:@slider-text; + text-decoration:none; + } + } + p { + font-size:18px; + margin:0; + text-align:center; + line-height:1.3em; + color:@slider-text; + } + a.link-continue { + display:block; + margin-top:5px; + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + text-indent:-9999px; + } + + } + } + } + +/** + * Main image in entity detail + */ +figure.main-img { + padding:0; + position:relative; + padding:0 15px 10px 0; + margin: 0; + max-width:auto; + margin-bottom:15px; + background:@white; + .box-shadow (@x: 0, @y: 0, @blur:3px, @color: #999); + + img { + padding:0; + border:0; + float:left; + margin-bottom:8px + } + .description { + font-size: 12px; + line-height: 1.2em; + padding:0; + margin:0; + position:relative; + bottom:0; + float:left; + clear:left; + width:auto; + padding-right:10px; + word-wrap:break-word; + + strong { + display:block; + } + } + + &.align-left { + float:left; + margin-right:20px; + padding-right:0; + } + + &.align-right { + float:right; + margin-left:20px; + padding-right:0; + img { + float:right; + } + .description { + float:left; + text-align:left; + clear:right; + padding-left:10px; + padding-right:0; + } + } + +} + +/** + * Search results + */ +.results-content { + .item { + border-bottom:1px solid @box-border; + padding-bottom:15px; + margin-bottom:15px; + + p { + padding-bottom:0; + margin-bottom:0; + } + + h1 { + font-size:18px; + padding-bottom:10px; + } + + img { + padding:6px; + border:1px solid @box-border; + float:left; + margin-right:10px; + } + + &.col-md-3 { + .grid(4, 1, 4.5%); + float:left; + + &:last-child { + margin-right:0; + } + + } + + h2 { + .padding-margin-reset(); + font-size:18px; + line-height:1.2em; + font-weight:600; + padding:10px; + + a { + + &:hover { + text-decoration:none; + } + + } + + } + + .wrapper-link { + height:23px; + background:#f0f0f0; + text-align:right; + padding:0 8px; + font-size:15px; + border-top:1px solid @box-border; + position:absolute; + bottom:0; + width:100%; + } + + &.in-grid { + min-height:244px; + margin-bottom:40px; + position:relative; + background:@box-background; + padding:0; + .box-shadow (@x: 0, @y: 0, @blur:3px, @color: #999); + + img { + padding:0; + border:0; + float:none; + } + + } + + } +} + +.box.collapsible { + box-shadow:none; + background:none; + + .ico-box { + display:none; + } + + .container { + border:0; + padding:0 5px!important; + margin:0!important; + + } + + h1 { + font-size:14px; + font-family: @font-1; + font-weight: 600; + line-height:14px; + padding:0 14px 6px 26px; + margin:0; + background-color:transparent; + border-bottom:1px @solid @box-border; + color:@box-header-link; + a { + color:@box-header-link; + text-decoration:none; + } + } +} + +/** + * Entity relations image + */ +.relationImage { + clear:both; + width:100%; + margin-bottom:20px!important; + + .slider { + padding-left:33px; + margin-top:15px!important; + } + + .slide { + padding:2px; + } + + img { + width:auto!important; + padding:0; + border:0; + .border-radius(0); + .box-shadow (@x: 0, @y: 0, @blur:4px, @color:#666); + } + +} + + +/** + * Entity relations links + */ +.relationLink { + .item-list { + padding:0; + margin:0 0; + li { + list-style:none; + padding-left:0; + border-bottom:1px @solid @box-relation-item-border; + font-family:@font-2; + + a { + text-decoration:none; + display:block; + color:@box-text; + line-height:30px; + padding-left:26px; + position:relative; + &:before { + display:block; + position:absolute; + width:15px; + height:10px; + top:0; + left:0; + margin:0 0 0 0; + font-family:'FontAwesome'; + content: @fa-var-eye; + color:@color-arrow-button-slider-hover; + } + &:hover { + &:before { + color:@box-text; + } + } + } + &:last-child { + border:0; + a { + padding-bottom:0; + margin-bottom:0; + } + } + } + } +} + +/** + * Entity relations image link + */ +.relationImageLink { + + .row-fluid { + margin-top:15px; + } + + .item { + .box-shadow (@x: 0, @y: 0, @blur:3px, @color: #999); + min-height:60px; + margin-bottom:15px; + background:@white; + padding:10px; + + img { + display:block; + margin:0 auto; + margin-bottom:12px; + } + + h2 { + padding:0 10px 0 0!important; + font-size:14px; + margin-bottom:5px; + } + + p { + font-size:12px; + padding:0 0; + line-height:1.2em; + } + + .grid(4, 1, 3.5%); + float:left; + + &:last-child { + margin-right:0; + } + + } + + .slider { + margin-top:15px; + padding-left:33px; + padding-right:10px; + + .slide { + + } + + .item { + margin-right:0; + width:120px!important; + padding:0; + height:150px; + overflow:hidden; + + h2, p { + padding-left:10px!important; + padding-right:10px!important; + } + + } + } +} + + +/** + * Storyteller + */ +.storyteller { + background:@storyteller-background; + border:0; + padding-bottom:15px; + margin-bottom:20px; + .box-sizing(); + width:100%; + clear:both; + + #nav-bar { + min-height:40px; + background:transparent; + margin-top:15px; + ul { + text-align:center; + .padding-margin-reset(); + margin-left:10px; + @media (max-width: 480px) { + margin-left:-1px; + margin-right:-1px; + margin-top:-1px; + } + li { + list-style:none; + display:inline; + padding:0 15px; + + @media (max-width: 480px) { + display:block; + float:none; + } + &:hover, &.active { + background-color:transparent; + @media (max-width: 480px) { + background-color:transparent; + } + a { + color:@text; + text-decoration:none; + border-bottom:4px solid @storyteller-link-hover; + } + } + border-right:1px solid @storyteller-border; + a { + display:inline-block; + color:@storyteller-navigation-link; + text-decoration:none; + font-size:18px; + margin-left:5px; + } + &:last-child { + border-right:1px solid @storyteller-border; + } + } + } + } + + .content-story { + padding-top:40px; + + .item-box { + position:relative; + background: @storyteller-item-background; + display:block; + width:100%; + margin:0 auto 25px auto; + padding:10px; + .box-sizing(); + .box-shadow (@x: 0, @y: 0, @blur:3px, @color: #999); + + h1 { + font-size: 18px; + } + h2 { + font-size: 16px; + } + h4 { + font-size: 14px; + } + + &.with-angle-icon { + background:@storyteller-item-background url(../img/bg/bg-box.png) 99.8% 2px no-repeat; + } + + &.ie-hide-iframe { + + @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { + + iframe { + display:none; + } + + } + + + } + + .box-angle { + font-size:15px; + position:absolute; + right:0; + top:0; + margin:7px 5px 0 0; + } + + &.comment { + background:@storyteller-comments-background; + + form { + margin-top:20px; + width:100%; + max-width:250px; + display:block; + margin-left:auto; + margin-right:auto; + + span { + text-align:left; + display:block; + margin-right:0; + } + input[type="text"], textarea { + display:inline-block; + width:250px!important; + } + } + } + &.gallery { + background:@storyteller-item-background; + } + .arrow-big { + display:none; + } + iframe { + width: 100%; + margin: 0 0 30px 0; + } + .functions { + .from { + color:@storyteller-link; + span { + font-weight:bold; + color:@text; + } + } + .actions { + border-top:1px solid @storyteller-border; + margin-top:4px; + padding-top:4px; + padding-bottom:8px; + ul { + .padding-margin-reset(); + padding-top:8px; + &.dx { + float:right; + li a { + text-decoration:none; + } + li i { + font-size:18px; + } + } + &.sx { + float:left; + } + li { + list-style:none; + display:inline; + border-right:1px solid @storyteller-border; + padding:5px 10px; + &:last-child { + border:0; + } + i { + color:@storyteller-icon; + margin-right:5px; + } + a { + display:inline-block; + text-decoration:none; + padding:0; + line-height:16px; + &:hover { + text-decoration:underline; + } + } + } + } + } + } + .archive-link { + text-align:center; + padding-top:5px; + } + + .item-comment { + border-bottom:1px solid @storyteller-border; + padding-bottom:10px; + margin-bottom:10px; + &:last-child { + border-bottom:0; + padding-bottom:0; + margin-bottom:0; + } + } + .content-box-item { + + h4 { + font-size:18px; + } + + } + .story-gallery { + border-top:1px solid @storyteller-border; + padding-top:20px; + padding-bottom:20px; + padding-left:10px; + padding-right:10px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + .mini-photo { + border:1px solid transparent; + padding-right:0px; + float:left; + width:82px; + height:82px; + position:relative; + margin-right:12px; + margin-bottom:12px; + &:last-child { + margin-right:0; + } + img { + width:82px; + height:82px; + margin:0; + float:none; + padding:2px; + margin-right:8px; + border:1px @solid @storyteller-image-border; + .border-radius (2px); + } + &:last-child { + &:hover { + .popup { + margin-left:-80px; + .popup-arrow { + right:0; + left:auto; + margin-right:8px; + } + } + } + } + &:hover { + .popup { + visibility:visible; + } + } + } + } + } + } + ul.insights { + list-style: none; + margin: 10px 0; + padding: 0; + li { + float: left; + padding-right: 10px; + margin-right: 10px; + border-right: 1px solid @storyteller-border; + &:last-child { + margin-right: 0; + padding-right: 0; + border: 0; + } + } + } +} + + +/** + * Gallery.io override + */ +.wrapper-galleria-io { + padding:5px; + border:1px @solid @box-border; + margin-bottom:40px; + clear:both; + + .content-galleria-io { + max-width:100%; + font-family: @font-1; + &:hover { + .galleria-info-description { + opacity:1; + filter: alpha(opacity=100); + } + } + .galleria-info { + margin-bottom:10px; + } + .galleria-info-description { + opacity:0; + filter: alpha(opacity=0); + position:absolute; + margin:0 0 31px -15px; + bottom:0; + display:block; + width:100%; + background: url(../img/bg/bg-description.png) repeat; + padding:5px 15px; + padding-right:40px; + .box-sizing(); + border-top:1px @solid #000; + border-right:1px @solid #000; + width:430px; + } + } + .galleria-counter { + margin-bottom:10px; + margin-right:46px; + } + + &.slider { + border: 0; + } + + #galleria.sfogliatore { + .galleria-info { + position: absolute; + height:15px; + left:0px; + bottom:0; + margin-bottom:5px!important; + color: #bbb; + margin-right:40px; + } + .galleria-info-description { + margin:0 0 16px -5px; + } + } + + #galleria.slider { + .galleria-info-text { + top:auto; + bottom:0; + margin-bottom:-12px; + } + } +} + + +/** + * Image list + */ +.imageList { + clear:both; + width:100%; + padding-left:33px; + margin-bottom:20px!important; + + .slide { + padding:2px; + } + + img { + width:auto!important; + padding:0; + border:0; + .border-radius(0); + .box-shadow (@x: 0, @y: 0, @blur:4px, @color:#666); + } + +} + +/* row-fluid */ +.row-fluid { + + &.content-box { + padding:0 0; + } + + &.grid { + + } + +} + +.box-title { + position:relative; + + .print-ico { + top:0; + right:0; + position:absolute; + margin:15px 0 0 0; + } + +} + +/* box-gallery-description */ +.box-gallery-description { + display:block; + margin:0 auto!important; + padding:0 40px; + .grid(4, 2,0); + border-left:1px solid @box-border; + border-right:1px solid @box-border; +} + +/** + * Timeline + */ +.storyjs-embed.sized-embed { + border-radius: 0; +} + +.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content h3, .vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3 { + color: @timeline-theme !important; +} + +.vco-timeline .vco-navigation .timenav-background .timenav-line, +.vco-timeline .vco-navigation .timenav .content .marker.active .line, +.vco-timeline .vco-navigation .timenav .content .marker.active .dot { + background-color: @timeline-theme !important; +} + +.vco-timeline .vco-navigation .timenav .content .marker .line .event-line { + background: @timeline-theme !important; +} + + +/* ImageHotspot */ + +.movio-hotspotContainer { + position: relative; + border:1px @solid @box-image-border; + .border-radius (2px); + padding: 3px; + display: inline-block; + width: 100%; + + .movio-imageHotspot-scale { + position: absolute; + left: 0; + top: 0; + } + + + .movio-hotspot, .movio-hotspot-circle { + border: 2px solid @white; + .box-shadow(0, 0, 2px, @black); + position: absolute; + z-index: 999; + cursor: pointer; + + &:hover { + border: 2px solid @color-link; + } + } + + .movio-hotspot-circle { + border-radius: 50%; + } + + img { + max-width: 100%; + height: auto; + } + + +} + +/** +/* attach +*/ +.attach { + padding: 10px; + border:1px @solid @box-border; + + .box-title { + font-size: 18px; + border-bottom: 0; + .pmr(); + padding-bottom: 10px; + color:@text; + } + + .container { + border:0; + background: none; + padding:0; + } + + ul { + .pmr(); + + li { + &.active { + a { + background:@bg-link-attach-hover; + color:@color-link-attach-hover; + + &:hover { + background:@bg-link-attach-hover; + color:@color-link-attach-hover; + } + + } + } + + a { + background:@bg-link-attach; + color:@color-link-attach; + + &:hover { + background:@bg-link-attach-hover; + color:@color-link-attach-hover; + } + + } + + } + + } + +} +/** +/* new-dl +*/ +.new-dl { + border:1px @solid @box-border; + padding:10px; + background: @bg-dl; + + dd, dt { + float: left; + padding:5px 0; + } + + dt { + clear: both; + } + + dd { + } + +} +/** +/* tag-list +*/ +.tag-list, .insights { + .pmr(); + + li { + display: inline; + + a { + display: inline-block; + font-size: 12px; + color: @color-tag-attach; + background: @bg-tag-attach; + padding: 2px 5px; + .border-radius(4px); + margin-top: 2px; + text-decoration: none; + + &:hover { + text-decoration: none; + color: @color-tag-attach-hover; + background: @bg-tag-attach-hover; + } + + } + + } + +} +/** +/* block-my-pop-up +*/ +.block-my-pop-up { + position: absolute; + max-width: 490px; + background:@bg-block-my-pop-up; + z-index: 99; + border: 4px @solid @box-border; + + .arrow { + width: 0; + height: 0; + border-left:15px solid transparent; + border-right:15px solid transparent; + border-bottom:15px solid @box-border; + position: absolute; + } + + .block-title { + padding: 10px; + font-size:20px; + border-bottom: 1px @solid @box-border; + } + + .block-my-pop-up-container { + position: relative; + padding:10px; + padding-top: 0; + + &.no-padding { + padding:0; + margin-top: -15px; + } + + } + + .results-content { + position: relative; + } + + +} \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/bordered-pulled.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/bordered-pulled.less new file mode 100644 index 0000000..9bb4d3a --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/bordered-pulled.less @@ -0,0 +1,16 @@ +// Bordered & Pulled +// ------------------------- + +.@{fa-css-prefix}-border { + padding: .2em .25em .15em; + border: @solid .08em @fa-border-color; + border-radius: .1em; +} + +.pull-right { float: right; } +.pull-left { float: left; } + +.@{fa-css-prefix} { + &.pull-left { margin-right: .3em; } + &.pull-right { margin-left: .3em; } +} diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/core.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/core.less new file mode 100644 index 0000000..6d223bc --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/core.less @@ -0,0 +1,12 @@ +// Base Class Definition +// ------------------------- + +.@{fa-css-prefix} { + display: inline-block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/fixed-width.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/fixed-width.less new file mode 100644 index 0000000..110289f --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/fixed-width.less @@ -0,0 +1,6 @@ +// Fixed Width Icons +// ------------------------- +.@{fa-css-prefix}-fw { + width: (18em / 14); + text-align: center; +} diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/font-awesome.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/font-awesome.less new file mode 100644 index 0000000..96d2f22 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/font-awesome.less @@ -0,0 +1,17 @@ +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ + +@import "variables"; +@import "mixins"; +@import "path"; +@import "core"; +@import "larger"; +@import "fixed-width"; +@import "list"; +@import "bordered-pulled"; +@import "spinning"; +@import "rotated-flipped"; +@import "stacked"; +@import "icons"; diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/icons.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/icons.less new file mode 100644 index 0000000..bf0f856 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/icons.less @@ -0,0 +1,412 @@ +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ + +.@{fa-css-prefix}-glass:before { content: @fa-var-glass; } +.@{fa-css-prefix}-music:before { content: @fa-var-music; } +.@{fa-css-prefix}-search:before { content: @fa-var-search; } +.@{fa-css-prefix}-envelope-o:before { content: @fa-var-envelope-o; } +.@{fa-css-prefix}-heart:before { content: @fa-var-heart; } +.@{fa-css-prefix}-star:before { content: @fa-var-star; } +.@{fa-css-prefix}-star-o:before { content: @fa-var-star-o; } +.@{fa-css-prefix}-user:before { content: @fa-var-user; } +.@{fa-css-prefix}-film:before { content: @fa-var-film; } +.@{fa-css-prefix}-th-large:before { content: @fa-var-th-large; } +.@{fa-css-prefix}-th:before { content: @fa-var-th; } +.@{fa-css-prefix}-th-list:before { content: @fa-var-th-list; } +.@{fa-css-prefix}-check:before { content: @fa-var-check; } +.@{fa-css-prefix}-times:before { content: @fa-var-times; } +.@{fa-css-prefix}-search-plus:before { content: @fa-var-search-plus; } +.@{fa-css-prefix}-search-minus:before { content: @fa-var-search-minus; } +.@{fa-css-prefix}-power-off:before { content: @fa-var-power-off; } +.@{fa-css-prefix}-signal:before { content: @fa-var-signal; } +.@{fa-css-prefix}-gear:before, +.@{fa-css-prefix}-cog:before { content: @fa-var-cog; } +.@{fa-css-prefix}-trash-o:before { content: @fa-var-trash-o; } +.@{fa-css-prefix}-home:before { content: @fa-var-home; } +.@{fa-css-prefix}-file-o:before { content: @fa-var-file-o; } +.@{fa-css-prefix}-clock-o:before { content: @fa-var-clock-o; } +.@{fa-css-prefix}-road:before { content: @fa-var-road; } +.@{fa-css-prefix}-download:before { content: @fa-var-download; } +.@{fa-css-prefix}-arrow-circle-o-down:before { content: @fa-var-arrow-circle-o-down; } +.@{fa-css-prefix}-arrow-circle-o-up:before { content: @fa-var-arrow-circle-o-up; } +.@{fa-css-prefix}-inbox:before { content: @fa-var-inbox; } +.@{fa-css-prefix}-play-circle-o:before { content: @fa-var-play-circle-o; } +.@{fa-css-prefix}-rotate-right:before, +.@{fa-css-prefix}-repeat:before { content: @fa-var-repeat; } +.@{fa-css-prefix}-refresh:before { content: @fa-var-refresh; } +.@{fa-css-prefix}-list-alt:before { content: @fa-var-list-alt; } +.@{fa-css-prefix}-lock:before { content: @fa-var-lock; } +.@{fa-css-prefix}-flag:before { content: @fa-var-flag; } +.@{fa-css-prefix}-headphones:before { content: @fa-var-headphones; } +.@{fa-css-prefix}-volume-off:before { content: @fa-var-volume-off; } +.@{fa-css-prefix}-volume-down:before { content: @fa-var-volume-down; } +.@{fa-css-prefix}-volume-up:before { content: @fa-var-volume-up; } +.@{fa-css-prefix}-qrcode:before { content: @fa-var-qrcode; } +.@{fa-css-prefix}-barcode:before { content: @fa-var-barcode; } +.@{fa-css-prefix}-tag:before { content: @fa-var-tag; } +.@{fa-css-prefix}-tags:before { content: @fa-var-tags; } +.@{fa-css-prefix}-book:before { content: @fa-var-book; } +.@{fa-css-prefix}-bookmark:before { content: @fa-var-bookmark; } +.@{fa-css-prefix}-print:before { content: @fa-var-print; } +.@{fa-css-prefix}-camera:before { content: @fa-var-camera; } +.@{fa-css-prefix}-font:before { content: @fa-var-font; } +.@{fa-css-prefix}-bold:before { content: @fa-var-bold; } +.@{fa-css-prefix}-italic:before { content: @fa-var-italic; } +.@{fa-css-prefix}-text-height:before { content: @fa-var-text-height; } +.@{fa-css-prefix}-text-width:before { content: @fa-var-text-width; } +.@{fa-css-prefix}-align-left:before { content: @fa-var-align-left; } +.@{fa-css-prefix}-align-center:before { content: @fa-var-align-center; } +.@{fa-css-prefix}-align-right:before { content: @fa-var-align-right; } +.@{fa-css-prefix}-align-justify:before { content: @fa-var-align-justify; } +.@{fa-css-prefix}-list:before { content: @fa-var-list; } +.@{fa-css-prefix}-dedent:before, +.@{fa-css-prefix}-outdent:before { content: @fa-var-outdent; } +.@{fa-css-prefix}-indent:before { content: @fa-var-indent; } +.@{fa-css-prefix}-video-camera:before { content: @fa-var-video-camera; } +.@{fa-css-prefix}-picture-o:before { content: @fa-var-picture-o; } +.@{fa-css-prefix}-pencil:before { content: @fa-var-pencil; } +.@{fa-css-prefix}-map-marker:before { content: @fa-var-map-marker; } +.@{fa-css-prefix}-adjust:before { content: @fa-var-adjust; } +.@{fa-css-prefix}-tint:before { content: @fa-var-tint; } +.@{fa-css-prefix}-edit:before, +.@{fa-css-prefix}-pencil-square-o:before { content: @fa-var-pencil-square-o; } +.@{fa-css-prefix}-share-square-o:before { content: @fa-var-share-square-o; } +.@{fa-css-prefix}-check-square-o:before { content: @fa-var-check-square-o; } +.@{fa-css-prefix}-arrows:before { content: @fa-var-arrows; } +.@{fa-css-prefix}-step-backward:before { content: @fa-var-step-backward; } +.@{fa-css-prefix}-fast-backward:before { content: @fa-var-fast-backward; } +.@{fa-css-prefix}-backward:before { content: @fa-var-backward; } +.@{fa-css-prefix}-play:before { content: @fa-var-play; } +.@{fa-css-prefix}-pause:before { content: @fa-var-pause; } +.@{fa-css-prefix}-stop:before { content: @fa-var-stop; } +.@{fa-css-prefix}-forward:before { content: @fa-var-forward; } +.@{fa-css-prefix}-fast-forward:before { content: @fa-var-fast-forward; } +.@{fa-css-prefix}-step-forward:before { content: @fa-var-step-forward; } +.@{fa-css-prefix}-eject:before { content: @fa-var-eject; } +.@{fa-css-prefix}-chevron-left:before { content: @fa-var-chevron-left; } +.@{fa-css-prefix}-chevron-right:before { content: @fa-var-chevron-right; } +.@{fa-css-prefix}-plus-circle:before { content: @fa-var-plus-circle; } +.@{fa-css-prefix}-minus-circle:before { content: @fa-var-minus-circle; } +.@{fa-css-prefix}-times-circle:before { content: @fa-var-times-circle; } +.@{fa-css-prefix}-check-circle:before { content: @fa-var-check-circle; } +.@{fa-css-prefix}-question-circle:before { content: @fa-var-question-circle; } +.@{fa-css-prefix}-info-circle:before { content: @fa-var-info-circle; } +.@{fa-css-prefix}-crosshairs:before { content: @fa-var-crosshairs; } +.@{fa-css-prefix}-times-circle-o:before { content: @fa-var-times-circle-o; } +.@{fa-css-prefix}-check-circle-o:before { content: @fa-var-check-circle-o; } +.@{fa-css-prefix}-ban:before { content: @fa-var-ban; } +.@{fa-css-prefix}-arrow-left:before { content: @fa-var-arrow-left; } +.@{fa-css-prefix}-arrow-right:before { content: @fa-var-arrow-right; } +.@{fa-css-prefix}-arrow-up:before { content: @fa-var-arrow-up; } +.@{fa-css-prefix}-arrow-down:before { content: @fa-var-arrow-down; } +.@{fa-css-prefix}-mail-forward:before, +.@{fa-css-prefix}-share:before { content: @fa-var-share; } +.@{fa-css-prefix}-expand:before { content: @fa-var-expand; } +.@{fa-css-prefix}-compress:before { content: @fa-var-compress; } +.@{fa-css-prefix}-plus:before { content: @fa-var-plus; } +.@{fa-css-prefix}-minus:before { content: @fa-var-minus; } +.@{fa-css-prefix}-asterisk:before { content: @fa-var-asterisk; } +.@{fa-css-prefix}-exclamation-circle:before { content: @fa-var-exclamation-circle; } +.@{fa-css-prefix}-gift:before { content: @fa-var-gift; } +.@{fa-css-prefix}-leaf:before { content: @fa-var-leaf; } +.@{fa-css-prefix}-fire:before { content: @fa-var-fire; } +.@{fa-css-prefix}-eye:before { content: @fa-var-eye; } +.@{fa-css-prefix}-eye-slash:before { content: @fa-var-eye-slash; } +.@{fa-css-prefix}-warning:before, +.@{fa-css-prefix}-exclamation-triangle:before { content: @fa-var-exclamation-triangle; } +.@{fa-css-prefix}-plane:before { content: @fa-var-plane; } +.@{fa-css-prefix}-calendar:before { content: @fa-var-calendar; } +.@{fa-css-prefix}-random:before { content: @fa-var-random; } +.@{fa-css-prefix}-comment:before { content: @fa-var-comment; } +.@{fa-css-prefix}-magnet:before { content: @fa-var-magnet; } +.@{fa-css-prefix}-chevron-up:before { content: @fa-var-chevron-up; } +.@{fa-css-prefix}-chevron-down:before { content: @fa-var-chevron-down; } +.@{fa-css-prefix}-retweet:before { content: @fa-var-retweet; } +.@{fa-css-prefix}-shopping-cart:before { content: @fa-var-shopping-cart; } +.@{fa-css-prefix}-folder:before { content: @fa-var-folder; } +.@{fa-css-prefix}-folder-open:before { content: @fa-var-folder-open; } +.@{fa-css-prefix}-arrows-v:before { content: @fa-var-arrows-v; } +.@{fa-css-prefix}-arrows-h:before { content: @fa-var-arrows-h; } +.@{fa-css-prefix}-bar-chart-o:before { content: @fa-var-bar-chart-o; } +.@{fa-css-prefix}-twitter-square:before { content: @fa-var-twitter-square; } +.@{fa-css-prefix}-facebook-square:before { content: @fa-var-facebook-square; } +.@{fa-css-prefix}-camera-retro:before { content: @fa-var-camera-retro; } +.@{fa-css-prefix}-key:before { content: @fa-var-key; } +.@{fa-css-prefix}-gears:before, +.@{fa-css-prefix}-cogs:before { content: @fa-var-cogs; } +.@{fa-css-prefix}-comments:before { content: @fa-var-comments; } +.@{fa-css-prefix}-thumbs-o-up:before { content: @fa-var-thumbs-o-up; } +.@{fa-css-prefix}-thumbs-o-down:before { content: @fa-var-thumbs-o-down; } +.@{fa-css-prefix}-star-half:before { content: @fa-var-star-half; } +.@{fa-css-prefix}-heart-o:before { content: @fa-var-heart-o; } +.@{fa-css-prefix}-sign-out:before { content: @fa-var-sign-out; } +.@{fa-css-prefix}-linkedin-square:before { content: @fa-var-linkedin-square; } +.@{fa-css-prefix}-thumb-tack:before { content: @fa-var-thumb-tack; } +.@{fa-css-prefix}-external-link:before { content: @fa-var-external-link; } +.@{fa-css-prefix}-sign-in:before { content: @fa-var-sign-in; } +.@{fa-css-prefix}-trophy:before { content: @fa-var-trophy; } +.@{fa-css-prefix}-github-square:before { content: @fa-var-github-square; } +.@{fa-css-prefix}-upload:before { content: @fa-var-upload; } +.@{fa-css-prefix}-lemon-o:before { content: @fa-var-lemon-o; } +.@{fa-css-prefix}-phone:before { content: @fa-var-phone; } +.@{fa-css-prefix}-square-o:before { content: @fa-var-square-o; } +.@{fa-css-prefix}-bookmark-o:before { content: @fa-var-bookmark-o; } +.@{fa-css-prefix}-phone-square:before { content: @fa-var-phone-square; } +.@{fa-css-prefix}-twitter:before { content: @fa-var-twitter; } +.@{fa-css-prefix}-facebook:before { content: @fa-var-facebook; } +.@{fa-css-prefix}-github:before { content: @fa-var-github; } +.@{fa-css-prefix}-unlock:before { content: @fa-var-unlock; } +.@{fa-css-prefix}-credit-card:before { content: @fa-var-credit-card; } +.@{fa-css-prefix}-rss:before { content: @fa-var-rss; } +.@{fa-css-prefix}-hdd-o:before { content: @fa-var-hdd-o; } +.@{fa-css-prefix}-bullhorn:before { content: @fa-var-bullhorn; } +.@{fa-css-prefix}-bell:before { content: @fa-var-bell; } +.@{fa-css-prefix}-certificate:before { content: @fa-var-certificate; } +.@{fa-css-prefix}-hand-o-right:before { content: @fa-var-hand-o-right; } +.@{fa-css-prefix}-hand-o-left:before { content: @fa-var-hand-o-left; } +.@{fa-css-prefix}-hand-o-up:before { content: @fa-var-hand-o-up; } +.@{fa-css-prefix}-hand-o-down:before { content: @fa-var-hand-o-down; } +.@{fa-css-prefix}-arrow-circle-left:before { content: @fa-var-arrow-circle-left; } +.@{fa-css-prefix}-arrow-circle-right:before { content: @fa-var-arrow-circle-right; } +.@{fa-css-prefix}-arrow-circle-up:before { content: @fa-var-arrow-circle-up; } +.@{fa-css-prefix}-arrow-circle-down:before { content: @fa-var-arrow-circle-down; } +.@{fa-css-prefix}-globe:before { content: @fa-var-globe; } +.@{fa-css-prefix}-wrench:before { content: @fa-var-wrench; } +.@{fa-css-prefix}-tasks:before { content: @fa-var-tasks; } +.@{fa-css-prefix}-filter:before { content: @fa-var-filter; } +.@{fa-css-prefix}-briefcase:before { content: @fa-var-briefcase; } +.@{fa-css-prefix}-arrows-alt:before { content: @fa-var-arrows-alt; } +.@{fa-css-prefix}-group:before, +.@{fa-css-prefix}-users:before { content: @fa-var-users; } +.@{fa-css-prefix}-chain:before, +.@{fa-css-prefix}-link:before { content: @fa-var-link; } +.@{fa-css-prefix}-cloud:before { content: @fa-var-cloud; } +.@{fa-css-prefix}-flask:before { content: @fa-var-flask; } +.@{fa-css-prefix}-cut:before, +.@{fa-css-prefix}-scissors:before { content: @fa-var-scissors; } +.@{fa-css-prefix}-copy:before, +.@{fa-css-prefix}-files-o:before { content: @fa-var-files-o; } +.@{fa-css-prefix}-paperclip:before { content: @fa-var-paperclip; } +.@{fa-css-prefix}-save:before, +.@{fa-css-prefix}-floppy-o:before { content: @fa-var-floppy-o; } +.@{fa-css-prefix}-square:before { content: @fa-var-square; } +.@{fa-css-prefix}-bars:before { content: @fa-var-bars; } +.@{fa-css-prefix}-list-ul:before { content: @fa-var-list-ul; } +.@{fa-css-prefix}-list-ol:before { content: @fa-var-list-ol; } +.@{fa-css-prefix}-strikethrough:before { content: @fa-var-strikethrough; } +.@{fa-css-prefix}-underline:before { content: @fa-var-underline; } +.@{fa-css-prefix}-table:before { content: @fa-var-table; } +.@{fa-css-prefix}-magic:before { content: @fa-var-magic; } +.@{fa-css-prefix}-truck:before { content: @fa-var-truck; } +.@{fa-css-prefix}-pinterest:before { content: @fa-var-pinterest; } +.@{fa-css-prefix}-pinterest-square:before { content: @fa-var-pinterest-square; } +.@{fa-css-prefix}-google-plus-square:before { content: @fa-var-google-plus-square; } +.@{fa-css-prefix}-google-plus:before { content: @fa-var-google-plus; } +.@{fa-css-prefix}-money:before { content: @fa-var-money; } +.@{fa-css-prefix}-caret-down:before { content: @fa-var-caret-down; } +.@{fa-css-prefix}-caret-up:before { content: @fa-var-caret-up; } +.@{fa-css-prefix}-caret-left:before { content: @fa-var-caret-left; } +.@{fa-css-prefix}-caret-right:before { content: @fa-var-caret-right; } +.@{fa-css-prefix}-columns:before { content: @fa-var-columns; } +.@{fa-css-prefix}-unsorted:before, +.@{fa-css-prefix}-sort:before { content: @fa-var-sort; } +.@{fa-css-prefix}-sort-down:before, +.@{fa-css-prefix}-sort-asc:before { content: @fa-var-sort-asc; } +.@{fa-css-prefix}-sort-up:before, +.@{fa-css-prefix}-sort-desc:before { content: @fa-var-sort-desc; } +.@{fa-css-prefix}-envelope:before { content: @fa-var-envelope; } +.@{fa-css-prefix}-linkedin:before { content: @fa-var-linkedin; } +.@{fa-css-prefix}-rotate-left:before, +.@{fa-css-prefix}-undo:before { content: @fa-var-undo; } +.@{fa-css-prefix}-legal:before, +.@{fa-css-prefix}-gavel:before { content: @fa-var-gavel; } +.@{fa-css-prefix}-dashboard:before, +.@{fa-css-prefix}-tachometer:before { content: @fa-var-tachometer; } +.@{fa-css-prefix}-comment-o:before { content: @fa-var-comment-o; } +.@{fa-css-prefix}-comments-o:before { content: @fa-var-comments-o; } +.@{fa-css-prefix}-flash:before, +.@{fa-css-prefix}-bolt:before { content: @fa-var-bolt; } +.@{fa-css-prefix}-sitemap:before { content: @fa-var-sitemap; } +.@{fa-css-prefix}-umbrella:before { content: @fa-var-umbrella; } +.@{fa-css-prefix}-paste:before, +.@{fa-css-prefix}-clipboard:before { content: @fa-var-clipboard; } +.@{fa-css-prefix}-lightbulb-o:before { content: @fa-var-lightbulb-o; } +.@{fa-css-prefix}-exchange:before { content: @fa-var-exchange; } +.@{fa-css-prefix}-cloud-download:before { content: @fa-var-cloud-download; } +.@{fa-css-prefix}-cloud-upload:before { content: @fa-var-cloud-upload; } +.@{fa-css-prefix}-user-md:before { content: @fa-var-user-md; } +.@{fa-css-prefix}-stethoscope:before { content: @fa-var-stethoscope; } +.@{fa-css-prefix}-suitcase:before { content: @fa-var-suitcase; } +.@{fa-css-prefix}-bell-o:before { content: @fa-var-bell-o; } +.@{fa-css-prefix}-coffee:before { content: @fa-var-coffee; } +.@{fa-css-prefix}-cutlery:before { content: @fa-var-cutlery; } +.@{fa-css-prefix}-file-text-o:before { content: @fa-var-file-text-o; } +.@{fa-css-prefix}-building-o:before { content: @fa-var-building-o; } +.@{fa-css-prefix}-hospital-o:before { content: @fa-var-hospital-o; } +.@{fa-css-prefix}-ambulance:before { content: @fa-var-ambulance; } +.@{fa-css-prefix}-medkit:before { content: @fa-var-medkit; } +.@{fa-css-prefix}-fighter-jet:before { content: @fa-var-fighter-jet; } +.@{fa-css-prefix}-beer:before { content: @fa-var-beer; } +.@{fa-css-prefix}-h-square:before { content: @fa-var-h-square; } +.@{fa-css-prefix}-plus-square:before { content: @fa-var-plus-square; } +.@{fa-css-prefix}-angle-double-left:before { content: @fa-var-angle-double-left; } +.@{fa-css-prefix}-angle-double-right:before { content: @fa-var-angle-double-right; } +.@{fa-css-prefix}-angle-double-up:before { content: @fa-var-angle-double-up; } +.@{fa-css-prefix}-angle-double-down:before { content: @fa-var-angle-double-down; } +.@{fa-css-prefix}-angle-left:before { content: @fa-var-angle-left; } +.@{fa-css-prefix}-angle-right:before { content: @fa-var-angle-right; } +.@{fa-css-prefix}-angle-up:before { content: @fa-var-angle-up; } +.@{fa-css-prefix}-angle-down:before { content: @fa-var-angle-down; } +.@{fa-css-prefix}-desktop:before { content: @fa-var-desktop; } +.@{fa-css-prefix}-laptop:before { content: @fa-var-laptop; } +.@{fa-css-prefix}-tablet:before { content: @fa-var-tablet; } +.@{fa-css-prefix}-mobile-phone:before, +.@{fa-css-prefix}-mobile:before { content: @fa-var-mobile; } +.@{fa-css-prefix}-circle-o:before { content: @fa-var-circle-o; } +.@{fa-css-prefix}-quote-left:before { content: @fa-var-quote-left; } +.@{fa-css-prefix}-quote-right:before { content: @fa-var-quote-right; } +.@{fa-css-prefix}-spinner:before { content: @fa-var-spinner; } +.@{fa-css-prefix}-circle:before { content: @fa-var-circle; } +.@{fa-css-prefix}-mail-reply:before, +.@{fa-css-prefix}-reply:before { content: @fa-var-reply; } +.@{fa-css-prefix}-github-alt:before { content: @fa-var-github-alt; } +.@{fa-css-prefix}-folder-o:before { content: @fa-var-folder-o; } +.@{fa-css-prefix}-folder-open-o:before { content: @fa-var-folder-open-o; } +.@{fa-css-prefix}-smile-o:before { content: @fa-var-smile-o; } +.@{fa-css-prefix}-frown-o:before { content: @fa-var-frown-o; } +.@{fa-css-prefix}-meh-o:before { content: @fa-var-meh-o; } +.@{fa-css-prefix}-gamepad:before { content: @fa-var-gamepad; } +.@{fa-css-prefix}-keyboard-o:before { content: @fa-var-keyboard-o; } +.@{fa-css-prefix}-flag-o:before { content: @fa-var-flag-o; } +.@{fa-css-prefix}-flag-checkered:before { content: @fa-var-flag-checkered; } +.@{fa-css-prefix}-terminal:before { content: @fa-var-terminal; } +.@{fa-css-prefix}-code:before { content: @fa-var-code; } +.@{fa-css-prefix}-reply-all:before { content: @fa-var-reply-all; } +.@{fa-css-prefix}-mail-reply-all:before { content: @fa-var-mail-reply-all; } +.@{fa-css-prefix}-star-half-empty:before, +.@{fa-css-prefix}-star-half-full:before, +.@{fa-css-prefix}-star-half-o:before { content: @fa-var-star-half-o; } +.@{fa-css-prefix}-location-arrow:before { content: @fa-var-location-arrow; } +.@{fa-css-prefix}-crop:before { content: @fa-var-crop; } +.@{fa-css-prefix}-code-fork:before { content: @fa-var-code-fork; } +.@{fa-css-prefix}-unlink:before, +.@{fa-css-prefix}-chain-broken:before { content: @fa-var-chain-broken; } +.@{fa-css-prefix}-question:before { content: @fa-var-question; } +.@{fa-css-prefix}-info:before { content: @fa-var-info; } +.@{fa-css-prefix}-exclamation:before { content: @fa-var-exclamation; } +.@{fa-css-prefix}-superscript:before { content: @fa-var-superscript; } +.@{fa-css-prefix}-subscript:before { content: @fa-var-subscript; } +.@{fa-css-prefix}-eraser:before { content: @fa-var-eraser; } +.@{fa-css-prefix}-puzzle-piece:before { content: @fa-var-puzzle-piece; } +.@{fa-css-prefix}-microphone:before { content: @fa-var-microphone; } +.@{fa-css-prefix}-microphone-slash:before { content: @fa-var-microphone-slash; } +.@{fa-css-prefix}-shield:before { content: @fa-var-shield; } +.@{fa-css-prefix}-calendar-o:before { content: @fa-var-calendar-o; } +.@{fa-css-prefix}-fire-extinguisher:before { content: @fa-var-fire-extinguisher; } +.@{fa-css-prefix}-rocket:before { content: @fa-var-rocket; } +.@{fa-css-prefix}-maxcdn:before { content: @fa-var-maxcdn; } +.@{fa-css-prefix}-chevron-circle-left:before { content: @fa-var-chevron-circle-left; } +.@{fa-css-prefix}-chevron-circle-right:before { content: @fa-var-chevron-circle-right; } +.@{fa-css-prefix}-chevron-circle-up:before { content: @fa-var-chevron-circle-up; } +.@{fa-css-prefix}-chevron-circle-down:before { content: @fa-var-chevron-circle-down; } +.@{fa-css-prefix}-html5:before { content: @fa-var-html5; } +.@{fa-css-prefix}-css3:before { content: @fa-var-css3; } +.@{fa-css-prefix}-anchor:before { content: @fa-var-anchor; } +.@{fa-css-prefix}-unlock-alt:before { content: @fa-var-unlock-alt; } +.@{fa-css-prefix}-bullseye:before { content: @fa-var-bullseye; } +.@{fa-css-prefix}-ellipsis-h:before { content: @fa-var-ellipsis-h; } +.@{fa-css-prefix}-ellipsis-v:before { content: @fa-var-ellipsis-v; } +.@{fa-css-prefix}-rss-square:before { content: @fa-var-rss-square; } +.@{fa-css-prefix}-play-circle:before { content: @fa-var-play-circle; } +.@{fa-css-prefix}-ticket:before { content: @fa-var-ticket; } +.@{fa-css-prefix}-minus-square:before { content: @fa-var-minus-square; } +.@{fa-css-prefix}-minus-square-o:before { content: @fa-var-minus-square-o; } +.@{fa-css-prefix}-level-up:before { content: @fa-var-level-up; } +.@{fa-css-prefix}-level-down:before { content: @fa-var-level-down; } +.@{fa-css-prefix}-check-square:before { content: @fa-var-check-square; } +.@{fa-css-prefix}-pencil-square:before { content: @fa-var-pencil-square; } +.@{fa-css-prefix}-external-link-square:before { content: @fa-var-external-link-square; } +.@{fa-css-prefix}-share-square:before { content: @fa-var-share-square; } +.@{fa-css-prefix}-compass:before { content: @fa-var-compass; } +.@{fa-css-prefix}-toggle-down:before, +.@{fa-css-prefix}-caret-square-o-down:before { content: @fa-var-caret-square-o-down; } +.@{fa-css-prefix}-toggle-up:before, +.@{fa-css-prefix}-caret-square-o-up:before { content: @fa-var-caret-square-o-up; } +.@{fa-css-prefix}-toggle-right:before, +.@{fa-css-prefix}-caret-square-o-right:before { content: @fa-var-caret-square-o-right; } +.@{fa-css-prefix}-euro:before, +.@{fa-css-prefix}-eur:before { content: @fa-var-eur; } +.@{fa-css-prefix}-gbp:before { content: @fa-var-gbp; } +.@{fa-css-prefix}-dollar:before, +.@{fa-css-prefix}-usd:before { content: @fa-var-usd; } +.@{fa-css-prefix}-rupee:before, +.@{fa-css-prefix}-inr:before { content: @fa-var-inr; } +.@{fa-css-prefix}-cny:before, +.@{fa-css-prefix}-rmb:before, +.@{fa-css-prefix}-yen:before, +.@{fa-css-prefix}-jpy:before { content: @fa-var-jpy; } +.@{fa-css-prefix}-ruble:before, +.@{fa-css-prefix}-rouble:before, +.@{fa-css-prefix}-rub:before { content: @fa-var-rub; } +.@{fa-css-prefix}-won:before, +.@{fa-css-prefix}-krw:before { content: @fa-var-krw; } +.@{fa-css-prefix}-bitcoin:before, +.@{fa-css-prefix}-btc:before { content: @fa-var-btc; } +.@{fa-css-prefix}-file:before { content: @fa-var-file; } +.@{fa-css-prefix}-file-text:before { content: @fa-var-file-text; } +.@{fa-css-prefix}-sort-alpha-asc:before { content: @fa-var-sort-alpha-asc; } +.@{fa-css-prefix}-sort-alpha-desc:before { content: @fa-var-sort-alpha-desc; } +.@{fa-css-prefix}-sort-amount-asc:before { content: @fa-var-sort-amount-asc; } +.@{fa-css-prefix}-sort-amount-desc:before { content: @fa-var-sort-amount-desc; } +.@{fa-css-prefix}-sort-numeric-asc:before { content: @fa-var-sort-numeric-asc; } +.@{fa-css-prefix}-sort-numeric-desc:before { content: @fa-var-sort-numeric-desc; } +.@{fa-css-prefix}-thumbs-up:before { content: @fa-var-thumbs-up; } +.@{fa-css-prefix}-thumbs-down:before { content: @fa-var-thumbs-down; } +.@{fa-css-prefix}-youtube-square:before { content: @fa-var-youtube-square; } +.@{fa-css-prefix}-youtube:before { content: @fa-var-youtube; } +.@{fa-css-prefix}-xing:before { content: @fa-var-xing; } +.@{fa-css-prefix}-xing-square:before { content: @fa-var-xing-square; } +.@{fa-css-prefix}-youtube-play:before { content: @fa-var-youtube-play; } +.@{fa-css-prefix}-dropbox:before { content: @fa-var-dropbox; } +.@{fa-css-prefix}-stack-overflow:before { content: @fa-var-stack-overflow; } +.@{fa-css-prefix}-instagram:before { content: @fa-var-instagram; } +.@{fa-css-prefix}-flickr:before { content: @fa-var-flickr; } +.@{fa-css-prefix}-adn:before { content: @fa-var-adn; } +.@{fa-css-prefix}-bitbucket:before { content: @fa-var-bitbucket; } +.@{fa-css-prefix}-bitbucket-square:before { content: @fa-var-bitbucket-square; } +.@{fa-css-prefix}-tumblr:before { content: @fa-var-tumblr; } +.@{fa-css-prefix}-tumblr-square:before { content: @fa-var-tumblr-square; } +.@{fa-css-prefix}-long-arrow-down:before { content: @fa-var-long-arrow-down; } +.@{fa-css-prefix}-long-arrow-up:before { content: @fa-var-long-arrow-up; } +.@{fa-css-prefix}-long-arrow-left:before { content: @fa-var-long-arrow-left; } +.@{fa-css-prefix}-long-arrow-right:before { content: @fa-var-long-arrow-right; } +.@{fa-css-prefix}-apple:before { content: @fa-var-apple; } +.@{fa-css-prefix}-windows:before { content: @fa-var-windows; } +.@{fa-css-prefix}-android:before { content: @fa-var-android; } +.@{fa-css-prefix}-linux:before { content: @fa-var-linux; } +.@{fa-css-prefix}-dribbble:before { content: @fa-var-dribbble; } +.@{fa-css-prefix}-skype:before { content: @fa-var-skype; } +.@{fa-css-prefix}-foursquare:before { content: @fa-var-foursquare; } +.@{fa-css-prefix}-trello:before { content: @fa-var-trello; } +.@{fa-css-prefix}-female:before { content: @fa-var-female; } +.@{fa-css-prefix}-male:before { content: @fa-var-male; } +.@{fa-css-prefix}-gittip:before { content: @fa-var-gittip; } +.@{fa-css-prefix}-sun-o:before { content: @fa-var-sun-o; } +.@{fa-css-prefix}-moon-o:before { content: @fa-var-moon-o; } +.@{fa-css-prefix}-archive:before { content: @fa-var-archive; } +.@{fa-css-prefix}-bug:before { content: @fa-var-bug; } +.@{fa-css-prefix}-vk:before { content: @fa-var-vk; } +.@{fa-css-prefix}-weibo:before { content: @fa-var-weibo; } +.@{fa-css-prefix}-renren:before { content: @fa-var-renren; } +.@{fa-css-prefix}-pagelines:before { content: @fa-var-pagelines; } +.@{fa-css-prefix}-stack-exchange:before { content: @fa-var-stack-exchange; } +.@{fa-css-prefix}-arrow-circle-o-right:before { content: @fa-var-arrow-circle-o-right; } +.@{fa-css-prefix}-arrow-circle-o-left:before { content: @fa-var-arrow-circle-o-left; } +.@{fa-css-prefix}-toggle-left:before, +.@{fa-css-prefix}-caret-square-o-left:before { content: @fa-var-caret-square-o-left; } +.@{fa-css-prefix}-dot-circle-o:before { content: @fa-var-dot-circle-o; } +.@{fa-css-prefix}-wheelchair:before { content: @fa-var-wheelchair; } +.@{fa-css-prefix}-vimeo-square:before { content: @fa-var-vimeo-square; } +.@{fa-css-prefix}-turkish-lira:before, +.@{fa-css-prefix}-try:before { content: @fa-var-try; } +.@{fa-css-prefix}-plus-square-o:before { content: @fa-var-plus-square-o; } diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/larger.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/larger.less new file mode 100644 index 0000000..c9d6467 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/larger.less @@ -0,0 +1,13 @@ +// Icon Sizes +// ------------------------- + +/* makes the font 33% larger relative to the icon container */ +.@{fa-css-prefix}-lg { + font-size: (4em / 3); + line-height: (3em / 4); + vertical-align: -15%; +} +.@{fa-css-prefix}-2x { font-size: 2em; } +.@{fa-css-prefix}-3x { font-size: 3em; } +.@{fa-css-prefix}-4x { font-size: 4em; } +.@{fa-css-prefix}-5x { font-size: 5em; } diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/list.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/list.less new file mode 100644 index 0000000..eed9340 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/list.less @@ -0,0 +1,19 @@ +// List Icons +// ------------------------- + +.@{fa-css-prefix}-ul { + padding-left: 0; + margin-left: @fa-li-width; + list-style-type: none; + > li { position: relative; } +} +.@{fa-css-prefix}-li { + position: absolute; + left: -@fa-li-width; + width: @fa-li-width; + top: (2em / 14); + text-align: center; + &.@{fa-css-prefix}-lg { + left: -@fa-li-width + (4em / 14); + } +} diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/mixins.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/mixins.less new file mode 100644 index 0000000..19e5a64 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/mixins.less @@ -0,0 +1,20 @@ +// Mixins +// -------------------------- + +.fa-icon-rotate(@degrees, @rotation) { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation); + -webkit-transform: rotate(@degrees); + -moz-transform: rotate(@degrees); + -ms-transform: rotate(@degrees); + -o-transform: rotate(@degrees); + transform: rotate(@degrees); +} + +.fa-icon-flip(@horiz, @vert, @rotation) { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1); + -webkit-transform: scale(@horiz, @vert); + -moz-transform: scale(@horiz, @vert); + -ms-transform: scale(@horiz, @vert); + -o-transform: scale(@horiz, @vert); + transform: scale(@horiz, @vert); +} diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/path.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/path.less new file mode 100644 index 0000000..c5a6912 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/path.less @@ -0,0 +1,14 @@ +/* FONT PATH + * -------------------------- */ + +@font-face { + font-family: 'FontAwesome'; + src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); + src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), + url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), + url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), + url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); +// src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts + font-weight: normal; + font-style: normal; +} diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/rotated-flipped.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/rotated-flipped.less new file mode 100644 index 0000000..8fff3a6 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/rotated-flipped.less @@ -0,0 +1,9 @@ +// Rotated & Flipped Icons +// ------------------------- + +.@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } +.@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } +.@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } + +.@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } +.@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/spinning.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/spinning.less new file mode 100644 index 0000000..60828fe --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/spinning.less @@ -0,0 +1,30 @@ +// Spinning Icons +// -------------------------- + +.@{fa-css-prefix}-spin { + -webkit-animation: spin 2s infinite linear; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} + +@-moz-keyframes spin { + 0% { -moz-transform: rotate(0deg); } + 100% { -moz-transform: rotate(359deg); } +} +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(359deg); } +} +@-o-keyframes spin { + 0% { -o-transform: rotate(0deg); } + 100% { -o-transform: rotate(359deg); } +} +@-ms-keyframes spin { + 0% { -ms-transform: rotate(0deg); } + 100% { -ms-transform: rotate(359deg); } +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(359deg); } +} diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/stacked.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/stacked.less new file mode 100644 index 0000000..fc53fb0 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/stacked.less @@ -0,0 +1,20 @@ +// Stacked Icons +// ------------------------- + +.@{fa-css-prefix}-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.@{fa-css-prefix}-stack-1x { line-height: inherit; } +.@{fa-css-prefix}-stack-2x { font-size: 2em; } +.@{fa-css-prefix}-inverse { color: @fa-inverse; } diff --git a/src/static/movio/templates/Minimal-in-blue/less/font-awesome/variables.less b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/variables.less new file mode 100644 index 0000000..3ab7a75 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/font-awesome/variables.less @@ -0,0 +1,381 @@ +// Variables +// -------------------------- + +//@fa-font-path: "../font/font-awesome"; +@fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts"; // for referencing Bootstrap CDN font files directly +@fa-css-prefix: fa; +@fa-version: "4.0.3"; +@fa-border-color: #eee; +@fa-inverse: #fff; +@fa-li-width: (30em / 14); + +@fa-var-glass: "\f000"; +@fa-var-music: "\f001"; +@fa-var-search: "\f002"; +@fa-var-envelope-o: "\f003"; +@fa-var-heart: "\f004"; +@fa-var-star: "\f005"; +@fa-var-star-o: "\f006"; +@fa-var-user: "\f007"; +@fa-var-film: "\f008"; +@fa-var-th-large: "\f009"; +@fa-var-th: "\f00a"; +@fa-var-th-list: "\f00b"; +@fa-var-check: "\f00c"; +@fa-var-times: "\f00d"; +@fa-var-search-plus: "\f00e"; +@fa-var-search-minus: "\f010"; +@fa-var-power-off: "\f011"; +@fa-var-signal: "\f012"; +@fa-var-cog: "\f013"; +@fa-var-trash-o: "\f014"; +@fa-var-home: "\f015"; +@fa-var-file-o: "\f016"; +@fa-var-clock-o: "\f017"; +@fa-var-road: "\f018"; +@fa-var-download: "\f019"; +@fa-var-arrow-circle-o-down: "\f01a"; +@fa-var-arrow-circle-o-up: "\f01b"; +@fa-var-inbox: "\f01c"; +@fa-var-play-circle-o: "\f01d"; +@fa-var-repeat: "\f01e"; +@fa-var-refresh: "\f021"; +@fa-var-list-alt: "\f022"; +@fa-var-lock: "\f023"; +@fa-var-flag: "\f024"; +@fa-var-headphones: "\f025"; +@fa-var-volume-off: "\f026"; +@fa-var-volume-down: "\f027"; +@fa-var-volume-up: "\f028"; +@fa-var-qrcode: "\f029"; +@fa-var-barcode: "\f02a"; +@fa-var-tag: "\f02b"; +@fa-var-tags: "\f02c"; +@fa-var-book: "\f02d"; +@fa-var-bookmark: "\f02e"; +@fa-var-print: "\f02f"; +@fa-var-camera: "\f030"; +@fa-var-font: "\f031"; +@fa-var-bold: "\f032"; +@fa-var-italic: "\f033"; +@fa-var-text-height: "\f034"; +@fa-var-text-width: "\f035"; +@fa-var-align-left: "\f036"; +@fa-var-align-center: "\f037"; +@fa-var-align-right: "\f038"; +@fa-var-align-justify: "\f039"; +@fa-var-list: "\f03a"; +@fa-var-outdent: "\f03b"; +@fa-var-indent: "\f03c"; +@fa-var-video-camera: "\f03d"; +@fa-var-picture-o: "\f03e"; +@fa-var-pencil: "\f040"; +@fa-var-map-marker: "\f041"; +@fa-var-adjust: "\f042"; +@fa-var-tint: "\f043"; +@fa-var-pencil-square-o: "\f044"; +@fa-var-share-square-o: "\f045"; +@fa-var-check-square-o: "\f046"; +@fa-var-arrows: "\f047"; +@fa-var-step-backward: "\f048"; +@fa-var-fast-backward: "\f049"; +@fa-var-backward: "\f04a"; +@fa-var-play: "\f04b"; +@fa-var-pause: "\f04c"; +@fa-var-stop: "\f04d"; +@fa-var-forward: "\f04e"; +@fa-var-fast-forward: "\f050"; +@fa-var-step-forward: "\f051"; +@fa-var-eject: "\f052"; +@fa-var-chevron-left: "\f053"; +@fa-var-chevron-right: "\f054"; +@fa-var-plus-circle: "\f055"; +@fa-var-minus-circle: "\f056"; +@fa-var-times-circle: "\f057"; +@fa-var-check-circle: "\f058"; +@fa-var-question-circle: "\f059"; +@fa-var-info-circle: "\f05a"; +@fa-var-crosshairs: "\f05b"; +@fa-var-times-circle-o: "\f05c"; +@fa-var-check-circle-o: "\f05d"; +@fa-var-ban: "\f05e"; +@fa-var-arrow-left: "\f060"; +@fa-var-arrow-right: "\f061"; +@fa-var-arrow-up: "\f062"; +@fa-var-arrow-down: "\f063"; +@fa-var-share: "\f064"; +@fa-var-expand: "\f065"; +@fa-var-compress: "\f066"; +@fa-var-plus: "\f067"; +@fa-var-minus: "\f068"; +@fa-var-asterisk: "\f069"; +@fa-var-exclamation-circle: "\f06a"; +@fa-var-gift: "\f06b"; +@fa-var-leaf: "\f06c"; +@fa-var-fire: "\f06d"; +@fa-var-eye: "\f06e"; +@fa-var-eye-slash: "\f070"; +@fa-var-exclamation-triangle: "\f071"; +@fa-var-plane: "\f072"; +@fa-var-calendar: "\f073"; +@fa-var-random: "\f074"; +@fa-var-comment: "\f075"; +@fa-var-magnet: "\f076"; +@fa-var-chevron-up: "\f077"; +@fa-var-chevron-down: "\f078"; +@fa-var-retweet: "\f079"; +@fa-var-shopping-cart: "\f07a"; +@fa-var-folder: "\f07b"; +@fa-var-folder-open: "\f07c"; +@fa-var-arrows-v: "\f07d"; +@fa-var-arrows-h: "\f07e"; +@fa-var-bar-chart-o: "\f080"; +@fa-var-twitter-square: "\f081"; +@fa-var-facebook-square: "\f082"; +@fa-var-camera-retro: "\f083"; +@fa-var-key: "\f084"; +@fa-var-cogs: "\f085"; +@fa-var-comments: "\f086"; +@fa-var-thumbs-o-up: "\f087"; +@fa-var-thumbs-o-down: "\f088"; +@fa-var-star-half: "\f089"; +@fa-var-heart-o: "\f08a"; +@fa-var-sign-out: "\f08b"; +@fa-var-linkedin-square: "\f08c"; +@fa-var-thumb-tack: "\f08d"; +@fa-var-external-link: "\f08e"; +@fa-var-sign-in: "\f090"; +@fa-var-trophy: "\f091"; +@fa-var-github-square: "\f092"; +@fa-var-upload: "\f093"; +@fa-var-lemon-o: "\f094"; +@fa-var-phone: "\f095"; +@fa-var-square-o: "\f096"; +@fa-var-bookmark-o: "\f097"; +@fa-var-phone-square: "\f098"; +@fa-var-twitter: "\f099"; +@fa-var-facebook: "\f09a"; +@fa-var-github: "\f09b"; +@fa-var-unlock: "\f09c"; +@fa-var-credit-card: "\f09d"; +@fa-var-rss: "\f09e"; +@fa-var-hdd-o: "\f0a0"; +@fa-var-bullhorn: "\f0a1"; +@fa-var-bell: "\f0f3"; +@fa-var-certificate: "\f0a3"; +@fa-var-hand-o-right: "\f0a4"; +@fa-var-hand-o-left: "\f0a5"; +@fa-var-hand-o-up: "\f0a6"; +@fa-var-hand-o-down: "\f0a7"; +@fa-var-arrow-circle-left: "\f0a8"; +@fa-var-arrow-circle-right: "\f0a9"; +@fa-var-arrow-circle-up: "\f0aa"; +@fa-var-arrow-circle-down: "\f0ab"; +@fa-var-globe: "\f0ac"; +@fa-var-wrench: "\f0ad"; +@fa-var-tasks: "\f0ae"; +@fa-var-filter: "\f0b0"; +@fa-var-briefcase: "\f0b1"; +@fa-var-arrows-alt: "\f0b2"; +@fa-var-users: "\f0c0"; +@fa-var-link: "\f0c1"; +@fa-var-cloud: "\f0c2"; +@fa-var-flask: "\f0c3"; +@fa-var-scissors: "\f0c4"; +@fa-var-files-o: "\f0c5"; +@fa-var-paperclip: "\f0c6"; +@fa-var-floppy-o: "\f0c7"; +@fa-var-square: "\f0c8"; +@fa-var-bars: "\f0c9"; +@fa-var-list-ul: "\f0ca"; +@fa-var-list-ol: "\f0cb"; +@fa-var-strikethrough: "\f0cc"; +@fa-var-underline: "\f0cd"; +@fa-var-table: "\f0ce"; +@fa-var-magic: "\f0d0"; +@fa-var-truck: "\f0d1"; +@fa-var-pinterest: "\f0d2"; +@fa-var-pinterest-square: "\f0d3"; +@fa-var-google-plus-square: "\f0d4"; +@fa-var-google-plus: "\f0d5"; +@fa-var-money: "\f0d6"; +@fa-var-caret-down: "\f0d7"; +@fa-var-caret-up: "\f0d8"; +@fa-var-caret-left: "\f0d9"; +@fa-var-caret-right: "\f0da"; +@fa-var-columns: "\f0db"; +@fa-var-sort: "\f0dc"; +@fa-var-sort-asc: "\f0dd"; +@fa-var-sort-desc: "\f0de"; +@fa-var-envelope: "\f0e0"; +@fa-var-linkedin: "\f0e1"; +@fa-var-undo: "\f0e2"; +@fa-var-gavel: "\f0e3"; +@fa-var-tachometer: "\f0e4"; +@fa-var-comment-o: "\f0e5"; +@fa-var-comments-o: "\f0e6"; +@fa-var-bolt: "\f0e7"; +@fa-var-sitemap: "\f0e8"; +@fa-var-umbrella: "\f0e9"; +@fa-var-clipboard: "\f0ea"; +@fa-var-lightbulb-o: "\f0eb"; +@fa-var-exchange: "\f0ec"; +@fa-var-cloud-download: "\f0ed"; +@fa-var-cloud-upload: "\f0ee"; +@fa-var-user-md: "\f0f0"; +@fa-var-stethoscope: "\f0f1"; +@fa-var-suitcase: "\f0f2"; +@fa-var-bell-o: "\f0a2"; +@fa-var-coffee: "\f0f4"; +@fa-var-cutlery: "\f0f5"; +@fa-var-file-text-o: "\f0f6"; +@fa-var-building-o: "\f0f7"; +@fa-var-hospital-o: "\f0f8"; +@fa-var-ambulance: "\f0f9"; +@fa-var-medkit: "\f0fa"; +@fa-var-fighter-jet: "\f0fb"; +@fa-var-beer: "\f0fc"; +@fa-var-h-square: "\f0fd"; +@fa-var-plus-square: "\f0fe"; +@fa-var-angle-double-left: "\f100"; +@fa-var-angle-double-right: "\f101"; +@fa-var-angle-double-up: "\f102"; +@fa-var-angle-double-down: "\f103"; +@fa-var-angle-left: "\f104"; +@fa-var-angle-right: "\f105"; +@fa-var-angle-up: "\f106"; +@fa-var-angle-down: "\f107"; +@fa-var-desktop: "\f108"; +@fa-var-laptop: "\f109"; +@fa-var-tablet: "\f10a"; +@fa-var-mobile: "\f10b"; +@fa-var-circle-o: "\f10c"; +@fa-var-quote-left: "\f10d"; +@fa-var-quote-right: "\f10e"; +@fa-var-spinner: "\f110"; +@fa-var-circle: "\f111"; +@fa-var-reply: "\f112"; +@fa-var-github-alt: "\f113"; +@fa-var-folder-o: "\f114"; +@fa-var-folder-open-o: "\f115"; +@fa-var-smile-o: "\f118"; +@fa-var-frown-o: "\f119"; +@fa-var-meh-o: "\f11a"; +@fa-var-gamepad: "\f11b"; +@fa-var-keyboard-o: "\f11c"; +@fa-var-flag-o: "\f11d"; +@fa-var-flag-checkered: "\f11e"; +@fa-var-terminal: "\f120"; +@fa-var-code: "\f121"; +@fa-var-reply-all: "\f122"; +@fa-var-mail-reply-all: "\f122"; +@fa-var-star-half-o: "\f123"; +@fa-var-location-arrow: "\f124"; +@fa-var-crop: "\f125"; +@fa-var-code-fork: "\f126"; +@fa-var-chain-broken: "\f127"; +@fa-var-question: "\f128"; +@fa-var-info: "\f129"; +@fa-var-exclamation: "\f12a"; +@fa-var-superscript: "\f12b"; +@fa-var-subscript: "\f12c"; +@fa-var-eraser: "\f12d"; +@fa-var-puzzle-piece: "\f12e"; +@fa-var-microphone: "\f130"; +@fa-var-microphone-slash: "\f131"; +@fa-var-shield: "\f132"; +@fa-var-calendar-o: "\f133"; +@fa-var-fire-extinguisher: "\f134"; +@fa-var-rocket: "\f135"; +@fa-var-maxcdn: "\f136"; +@fa-var-chevron-circle-left: "\f137"; +@fa-var-chevron-circle-right: "\f138"; +@fa-var-chevron-circle-up: "\f139"; +@fa-var-chevron-circle-down: "\f13a"; +@fa-var-html5: "\f13b"; +@fa-var-css3: "\f13c"; +@fa-var-anchor: "\f13d"; +@fa-var-unlock-alt: "\f13e"; +@fa-var-bullseye: "\f140"; +@fa-var-ellipsis-h: "\f141"; +@fa-var-ellipsis-v: "\f142"; +@fa-var-rss-square: "\f143"; +@fa-var-play-circle: "\f144"; +@fa-var-ticket: "\f145"; +@fa-var-minus-square: "\f146"; +@fa-var-minus-square-o: "\f147"; +@fa-var-level-up: "\f148"; +@fa-var-level-down: "\f149"; +@fa-var-check-square: "\f14a"; +@fa-var-pencil-square: "\f14b"; +@fa-var-external-link-square: "\f14c"; +@fa-var-share-square: "\f14d"; +@fa-var-compass: "\f14e"; +@fa-var-caret-square-o-down: "\f150"; +@fa-var-caret-square-o-up: "\f151"; +@fa-var-caret-square-o-right: "\f152"; +@fa-var-eur: "\f153"; +@fa-var-gbp: "\f154"; +@fa-var-usd: "\f155"; +@fa-var-inr: "\f156"; +@fa-var-jpy: "\f157"; +@fa-var-rub: "\f158"; +@fa-var-krw: "\f159"; +@fa-var-btc: "\f15a"; +@fa-var-file: "\f15b"; +@fa-var-file-text: "\f15c"; +@fa-var-sort-alpha-asc: "\f15d"; +@fa-var-sort-alpha-desc: "\f15e"; +@fa-var-sort-amount-asc: "\f160"; +@fa-var-sort-amount-desc: "\f161"; +@fa-var-sort-numeric-asc: "\f162"; +@fa-var-sort-numeric-desc: "\f163"; +@fa-var-thumbs-up: "\f164"; +@fa-var-thumbs-down: "\f165"; +@fa-var-youtube-square: "\f166"; +@fa-var-youtube: "\f167"; +@fa-var-xing: "\f168"; +@fa-var-xing-square: "\f169"; +@fa-var-youtube-play: "\f16a"; +@fa-var-dropbox: "\f16b"; +@fa-var-stack-overflow: "\f16c"; +@fa-var-instagram: "\f16d"; +@fa-var-flickr: "\f16e"; +@fa-var-adn: "\f170"; +@fa-var-bitbucket: "\f171"; +@fa-var-bitbucket-square: "\f172"; +@fa-var-tumblr: "\f173"; +@fa-var-tumblr-square: "\f174"; +@fa-var-long-arrow-down: "\f175"; +@fa-var-long-arrow-up: "\f176"; +@fa-var-long-arrow-left: "\f177"; +@fa-var-long-arrow-right: "\f178"; +@fa-var-apple: "\f179"; +@fa-var-windows: "\f17a"; +@fa-var-android: "\f17b"; +@fa-var-linux: "\f17c"; +@fa-var-dribbble: "\f17d"; +@fa-var-skype: "\f17e"; +@fa-var-foursquare: "\f180"; +@fa-var-trello: "\f181"; +@fa-var-female: "\f182"; +@fa-var-male: "\f183"; +@fa-var-gittip: "\f184"; +@fa-var-sun-o: "\f185"; +@fa-var-moon-o: "\f186"; +@fa-var-archive: "\f187"; +@fa-var-bug: "\f188"; +@fa-var-vk: "\f189"; +@fa-var-weibo: "\f18a"; +@fa-var-renren: "\f18b"; +@fa-var-pagelines: "\f18c"; +@fa-var-stack-exchange: "\f18d"; +@fa-var-arrow-circle-o-right: "\f18e"; +@fa-var-arrow-circle-o-left: "\f190"; +@fa-var-caret-square-o-left: "\f191"; +@fa-var-dot-circle-o: "\f192"; +@fa-var-wheelchair: "\f193"; +@fa-var-vimeo-square: "\f194"; +@fa-var-try: "\f195"; +@fa-var-plus-square-o: "\f196"; + diff --git a/src/static/movio/templates/Minimal-in-blue/less/global.less b/src/static/movio/templates/Minimal-in-blue/less/global.less new file mode 100755 index 0000000..2e76d1b --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/global.less @@ -0,0 +1,351 @@ +body { + background: url(../img/bg/bg-body.png) repeat; + font-family:@font-1; + font-size:14px; + font-weight:normal; + overflow-x:hidden; +} +* { + .box-sizing(); +} + +/** + * Typography + */ +h1, h2, h3, h4, h5, h6 { + color: @text-heading; + font-family:@font-2; +} +a { + color:@color-link; + + &:hover { + color:@color-link-hover; + } +} + +dt { + float: left; + font-weight:bold; + padding-right:10px; +} + +dd { + margin-left:0; +} + +dl { + &.small { + dt { + width: 70px; + } + dd { + margin-left: 70px; + } + } + &.medium { + dt { + width: 170px; + } + dd { + margin-left: 170px; + } + } + &.large { + dt { + width: 250px; + } + dd { + margin-left: 250px; + } + } +} + +.main-content { + padding:0; + h1 { + .padding-margin-reset(); + } + h2 { + .padding-margin-reset(); + margin-bottom:15px; + } + + .print-ico { + float:right; + } + + p { + line-height:1.8em; + padding-bottom:15px; + font-family:@font-2; + font-size:15px; + } +} + +/** + * Image + */ +img { + max-width:100%; + border: 0; + &.thumb, &.left, &.right, &.center { + float:left; + margin: 0.5em; + padding:0; + border:0; + .box-shadow (@x: 0, @y: 0, @blur:3px, @color: #999); + } + &.left { + margin-left: 0; + } + &.right { + margin-right: 0; + clear:right; + float:right; + } + &.center { + clear:both; + float:none; + margin:auto; + display: block; + } + &.noBorder { + border: 0; + padding: 0; + } +} + +/** + * Form + */ +input[type="text"], input[type="password"], input[type="email"] { + .input-style(100%); + + &.input-large { + width:450px; + } + &.input-small { + width:160px; + } +} + +label { + &.required { + &:after { + content:" *"; + } + } +} + +select { + width:auto; + &.select-large { + width:450px; + } + &.select-small { + width:160px; + } + &.select-medium { + width:260px; + } +} + +input[type="submit"], button, input[type="button"], input[type="reset"] { + .button-style(auto); +} + +input[type="submit"] { + background:@form-button-primary; + color:@form-button-primary-text; +} + +textarea { + border:1px @solid @color1; + width:100%; + padding:4px; + height:150px; + .border-radius(5px); + &.textarea-large { + width:450px; + } +} + +.my-form { + &.no-border-row { + .control-group { + border:0; + } + } + .control-group { + padding-bottom:10px; + } + .controls { + margin-left:0; + &.with-button { + input[type="submit"], input[type="button"], input[type="reset"], button { + margin-top:0; + margin-left:5px; + } + } + } + + &.form-horizontal { + .control-group { + clear:both; + margin-bottom:15px; + padding-bottom:15px; + border-bottom:1px @solid @color1; + label { + display:inline-block; + width:160px; + } + .controls { + display:inline-block; + } + } + } + + &.all-in-row { + + .control-group, .controls, label { + border:0; + float:left; + margin:0; + width:auto; + + input[type="text"] { + margin-top:2px; + } + + input[type="submit"], + input[type="button"], + input[type="reset"], + button { + margin-top:0; + margin-right:5px; + } + + } + label { + display:inline-block; + width:160px; + } + + .controls, label { + margin-right:15px; + } + + } + +} + +/** + * global selectors + */ +.clearfix-left { + clear:left; +} + +.clearfix-right { + clear:right; +} + +.align-center { + text-align:center!important; +} + +.align-right { + text-align:right!important; +} + +.first-box { + margin-left:0!important; +} + +.error { + color:@color-error; +} + +.ok { + color:@color-success; +} + +.alert { + margin-bottom:14px; + + &.error { + background:url(../img/ico/alert-error.png) 0 0 no-repeat; + padding-left:50px; + + h4, p { + .padding-margin-reset(); + } + + h4 { + color:@color-error; + } + + } + + &.ok { + background:url(../img/ico/alert-ok.png) 0 0 no-repeat; + padding-left:50px; + + h4 { + color:@color-success; + } + + h4, p { + .padding-margin-reset(); + } + + } + +} + +.ico-box { + display:block; + position:absolute; + width:30px!important; + height:30px!important; + top:0; + right:0; + margin-right:10px; + background:@icon-in-box-background; + color:@icon-in-box; + text-align:center; + padding-top:7px; + font-size:15px; + &.icon-film { + padding-left:5px; + } +} + +.icon-grey { + color:@icon-in-page; + font-size:20px; +} + + +span.superzoom { + background: @form-button-primary; + border-radius: 4px; + color: @form-button-primary-text; + padding: 2px 4px; + position: absolute; + text-align: center; + width: 60px; + cursor: pointer; +} + + +a.no-undeline { + text-decoration: none; +} + +.col-padding-left, +.col-padding-right { + padding-right: 15px; +} + diff --git a/src/static/movio/templates/Minimal-in-blue/less/libs/bootstrap-social.less b/src/static/movio/templates/Minimal-in-blue/less/libs/bootstrap-social.less new file mode 100644 index 0000000..4424e99 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/libs/bootstrap-social.less @@ -0,0 +1,100 @@ +/* + * Social Buttons for Bootstrap + * + * Copyright 2013-2014 Panayiotis Lipiridis + * Licensed under the MIT License + * + * https://github.com/lipis/bootstrap-social + */ + +.btn-social{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.btn-social :first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)} +.btn-social.btn-lg{padding-left:61px}.btn-social.btn-lg :first-child{line-height:45px;width:45px;font-size:1.8em} +.btn-social.btn-sm{padding-left:38px}.btn-social.btn-sm :first-child{line-height:28px;width:28px;font-size:1.4em} +.btn-social.btn-xs{padding-left:30px}.btn-social.btn-xs :first-child{line-height:20px;width:20px;font-size:1.2em} +.btn-social-icon{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:34px;width:34px;padding:0}.btn-social-icon :first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)} +.btn-social-icon.btn-lg{padding-left:61px}.btn-social-icon.btn-lg :first-child{line-height:45px;width:45px;font-size:1.8em} +.btn-social-icon.btn-sm{padding-left:38px}.btn-social-icon.btn-sm :first-child{line-height:28px;width:28px;font-size:1.4em} +.btn-social-icon.btn-xs{padding-left:30px}.btn-social-icon.btn-xs :first-child{line-height:20px;width:20px;font-size:1.2em} +.btn-social-icon :first-child{border:none;text-align:center;width:100% !important} +.btn-social-icon.btn-lg{height:45px;width:45px;padding-left:0;padding-right:0} +.btn-social-icon.btn-sm{height:30px;width:30px;padding-left:0;padding-right:0} +.btn-social-icon.btn-xs{height:22px;width:22px;padding-left:0;padding-right:0} +.btn-adn{color:#fff;background-color:#d87a68;border-color:rgba(0,0,0,0.2)}.btn-adn:hover,.btn-adn:focus,.btn-adn:active,.btn-adn.active,.open .dropdown-toggle.btn-adn{color:#fff;background-color:#d05d48;border-color:rgba(0,0,0,0.2)} +.btn-adn:active,.btn-adn.active,.open .dropdown-toggle.btn-adn{background-image:none} +.btn-adn.disabled,.btn-adn[disabled],fieldset[disabled] .btn-adn,.btn-adn.disabled:hover,.btn-adn[disabled]:hover,fieldset[disabled] .btn-adn:hover,.btn-adn.disabled:focus,.btn-adn[disabled]:focus,fieldset[disabled] .btn-adn:focus,.btn-adn.disabled:active,.btn-adn[disabled]:active,fieldset[disabled] .btn-adn:active,.btn-adn.disabled.active,.btn-adn[disabled].active,fieldset[disabled] .btn-adn.active{background-color:#d87a68;border-color:rgba(0,0,0,0.2)} +.btn-adn .badge{color:#d87a68;background-color:#fff} +.btn-bitbucket{color:#fff;background-color:#205081;border-color:rgba(0,0,0,0.2)}.btn-bitbucket:hover,.btn-bitbucket:focus,.btn-bitbucket:active,.btn-bitbucket.active,.open .dropdown-toggle.btn-bitbucket{color:#fff;background-color:#183c60;border-color:rgba(0,0,0,0.2)} +.btn-bitbucket:active,.btn-bitbucket.active,.open .dropdown-toggle.btn-bitbucket{background-image:none} +.btn-bitbucket.disabled,.btn-bitbucket[disabled],fieldset[disabled] .btn-bitbucket,.btn-bitbucket.disabled:hover,.btn-bitbucket[disabled]:hover,fieldset[disabled] .btn-bitbucket:hover,.btn-bitbucket.disabled:focus,.btn-bitbucket[disabled]:focus,fieldset[disabled] .btn-bitbucket:focus,.btn-bitbucket.disabled:active,.btn-bitbucket[disabled]:active,fieldset[disabled] .btn-bitbucket:active,.btn-bitbucket.disabled.active,.btn-bitbucket[disabled].active,fieldset[disabled] .btn-bitbucket.active{background-color:#205081;border-color:rgba(0,0,0,0.2)} +.btn-bitbucket .badge{color:#205081;background-color:#fff} +.btn-dropbox{color:#fff;background-color:#1087dd;border-color:rgba(0,0,0,0.2)}.btn-dropbox:hover,.btn-dropbox:focus,.btn-dropbox:active,.btn-dropbox.active,.open .dropdown-toggle.btn-dropbox{color:#fff;background-color:#0d70b7;border-color:rgba(0,0,0,0.2)} +.btn-dropbox:active,.btn-dropbox.active,.open .dropdown-toggle.btn-dropbox{background-image:none} +.btn-dropbox.disabled,.btn-dropbox[disabled],fieldset[disabled] .btn-dropbox,.btn-dropbox.disabled:hover,.btn-dropbox[disabled]:hover,fieldset[disabled] .btn-dropbox:hover,.btn-dropbox.disabled:focus,.btn-dropbox[disabled]:focus,fieldset[disabled] .btn-dropbox:focus,.btn-dropbox.disabled:active,.btn-dropbox[disabled]:active,fieldset[disabled] .btn-dropbox:active,.btn-dropbox.disabled.active,.btn-dropbox[disabled].active,fieldset[disabled] .btn-dropbox.active{background-color:#1087dd;border-color:rgba(0,0,0,0.2)} +.btn-dropbox .badge{color:#1087dd;background-color:#fff} +.btn-facebook{color:#fff;background-color:#3b5998;border-color:rgba(0,0,0,0.2)}.btn-facebook:hover,.btn-facebook:focus,.btn-facebook:active,.btn-facebook.active,.open .dropdown-toggle.btn-facebook{color:#fff;background-color:#30487b;border-color:rgba(0,0,0,0.2)} +.btn-facebook:active,.btn-facebook.active,.open .dropdown-toggle.btn-facebook{background-image:none} +.btn-facebook.disabled,.btn-facebook[disabled],fieldset[disabled] .btn-facebook,.btn-facebook.disabled:hover,.btn-facebook[disabled]:hover,fieldset[disabled] .btn-facebook:hover,.btn-facebook.disabled:focus,.btn-facebook[disabled]:focus,fieldset[disabled] .btn-facebook:focus,.btn-facebook.disabled:active,.btn-facebook[disabled]:active,fieldset[disabled] .btn-facebook:active,.btn-facebook.disabled.active,.btn-facebook[disabled].active,fieldset[disabled] .btn-facebook.active{background-color:#3b5998;border-color:rgba(0,0,0,0.2)} +.btn-facebook .badge{color:#3b5998;background-color:#fff} +.btn-flickr{color:#fff;background-color:#ff0084;border-color:rgba(0,0,0,0.2)}.btn-flickr:hover,.btn-flickr:focus,.btn-flickr:active,.btn-flickr.active,.open .dropdown-toggle.btn-flickr{color:#fff;background-color:#d6006f;border-color:rgba(0,0,0,0.2)} +.btn-flickr:active,.btn-flickr.active,.open .dropdown-toggle.btn-flickr{background-image:none} +.btn-flickr.disabled,.btn-flickr[disabled],fieldset[disabled] .btn-flickr,.btn-flickr.disabled:hover,.btn-flickr[disabled]:hover,fieldset[disabled] .btn-flickr:hover,.btn-flickr.disabled:focus,.btn-flickr[disabled]:focus,fieldset[disabled] .btn-flickr:focus,.btn-flickr.disabled:active,.btn-flickr[disabled]:active,fieldset[disabled] .btn-flickr:active,.btn-flickr.disabled.active,.btn-flickr[disabled].active,fieldset[disabled] .btn-flickr.active{background-color:#ff0084;border-color:rgba(0,0,0,0.2)} +.btn-flickr .badge{color:#ff0084;background-color:#fff} +.btn-foursquare{color:#fff;background-color:#0072b1;border-color:rgba(0,0,0,0.2)}.btn-foursquare:hover,.btn-foursquare:focus,.btn-foursquare:active,.btn-foursquare.active,.open .dropdown-toggle.btn-foursquare{color:#fff;background-color:#005888;border-color:rgba(0,0,0,0.2)} +.btn-foursquare:active,.btn-foursquare.active,.open .dropdown-toggle.btn-foursquare{background-image:none} +.btn-foursquare.disabled,.btn-foursquare[disabled],fieldset[disabled] .btn-foursquare,.btn-foursquare.disabled:hover,.btn-foursquare[disabled]:hover,fieldset[disabled] .btn-foursquare:hover,.btn-foursquare.disabled:focus,.btn-foursquare[disabled]:focus,fieldset[disabled] .btn-foursquare:focus,.btn-foursquare.disabled:active,.btn-foursquare[disabled]:active,fieldset[disabled] .btn-foursquare:active,.btn-foursquare.disabled.active,.btn-foursquare[disabled].active,fieldset[disabled] .btn-foursquare.active{background-color:#0072b1;border-color:rgba(0,0,0,0.2)} +.btn-foursquare .badge{color:#0072b1;background-color:#fff} +.btn-github{color:#fff;background-color:#444;border-color:rgba(0,0,0,0.2)}.btn-github:hover,.btn-github:focus,.btn-github:active,.btn-github.active,.open .dropdown-toggle.btn-github{color:#fff;background-color:#303030;border-color:rgba(0,0,0,0.2)} +.btn-github:active,.btn-github.active,.open .dropdown-toggle.btn-github{background-image:none} +.btn-github.disabled,.btn-github[disabled],fieldset[disabled] .btn-github,.btn-github.disabled:hover,.btn-github[disabled]:hover,fieldset[disabled] .btn-github:hover,.btn-github.disabled:focus,.btn-github[disabled]:focus,fieldset[disabled] .btn-github:focus,.btn-github.disabled:active,.btn-github[disabled]:active,fieldset[disabled] .btn-github:active,.btn-github.disabled.active,.btn-github[disabled].active,fieldset[disabled] .btn-github.active{background-color:#444;border-color:rgba(0,0,0,0.2)} +.btn-github .badge{color:#444;background-color:#fff} +.btn-google-plus{color:#fff;background-color:#dd4b39;border-color:rgba(0,0,0,0.2)}.btn-google-plus:hover,.btn-google-plus:focus,.btn-google-plus:active,.btn-google-plus.active,.open .dropdown-toggle.btn-google-plus{color:#fff;background-color:#ca3523;border-color:rgba(0,0,0,0.2)} +.btn-google-plus:active,.btn-google-plus.active,.open .dropdown-toggle.btn-google-plus{background-image:none} +.btn-google-plus.disabled,.btn-google-plus[disabled],fieldset[disabled] .btn-google-plus,.btn-google-plus.disabled:hover,.btn-google-plus[disabled]:hover,fieldset[disabled] .btn-google-plus:hover,.btn-google-plus.disabled:focus,.btn-google-plus[disabled]:focus,fieldset[disabled] .btn-google-plus:focus,.btn-google-plus.disabled:active,.btn-google-plus[disabled]:active,fieldset[disabled] .btn-google-plus:active,.btn-google-plus.disabled.active,.btn-google-plus[disabled].active,fieldset[disabled] .btn-google-plus.active{background-color:#dd4b39;border-color:rgba(0,0,0,0.2)} +.btn-google-plus .badge{color:#dd4b39;background-color:#fff} +.btn-instagram{color:#fff;background-color:#3f729b;border-color:rgba(0,0,0,0.2)}.btn-instagram:hover,.btn-instagram:focus,.btn-instagram:active,.btn-instagram.active,.open .dropdown-toggle.btn-instagram{color:#fff;background-color:#335d7e;border-color:rgba(0,0,0,0.2)} +.btn-instagram:active,.btn-instagram.active,.open .dropdown-toggle.btn-instagram{background-image:none} +.btn-instagram.disabled,.btn-instagram[disabled],fieldset[disabled] .btn-instagram,.btn-instagram.disabled:hover,.btn-instagram[disabled]:hover,fieldset[disabled] .btn-instagram:hover,.btn-instagram.disabled:focus,.btn-instagram[disabled]:focus,fieldset[disabled] .btn-instagram:focus,.btn-instagram.disabled:active,.btn-instagram[disabled]:active,fieldset[disabled] .btn-instagram:active,.btn-instagram.disabled.active,.btn-instagram[disabled].active,fieldset[disabled] .btn-instagram.active{background-color:#3f729b;border-color:rgba(0,0,0,0.2)} +.btn-instagram .badge{color:#3f729b;background-color:#fff} +.btn-linkedin{color:#fff;background-color:#007bb6;border-color:rgba(0,0,0,0.2)}.btn-linkedin:hover,.btn-linkedin:focus,.btn-linkedin:active,.btn-linkedin.active,.open .dropdown-toggle.btn-linkedin{color:#fff;background-color:#005f8d;border-color:rgba(0,0,0,0.2)} +.btn-linkedin:active,.btn-linkedin.active,.open .dropdown-toggle.btn-linkedin{background-image:none} +.btn-linkedin.disabled,.btn-linkedin[disabled],fieldset[disabled] .btn-linkedin,.btn-linkedin.disabled:hover,.btn-linkedin[disabled]:hover,fieldset[disabled] .btn-linkedin:hover,.btn-linkedin.disabled:focus,.btn-linkedin[disabled]:focus,fieldset[disabled] .btn-linkedin:focus,.btn-linkedin.disabled:active,.btn-linkedin[disabled]:active,fieldset[disabled] .btn-linkedin:active,.btn-linkedin.disabled.active,.btn-linkedin[disabled].active,fieldset[disabled] .btn-linkedin.active{background-color:#007bb6;border-color:rgba(0,0,0,0.2)} +.btn-linkedin .badge{color:#007bb6;background-color:#fff} +.btn-microsoft{color:#fff;background-color:#2672ec;border-color:rgba(0,0,0,0.2)}.btn-microsoft:hover,.btn-microsoft:focus,.btn-microsoft:active,.btn-microsoft.active,.open .dropdown-toggle.btn-microsoft{color:#fff;background-color:#135ed6;border-color:rgba(0,0,0,0.2)} +.btn-microsoft:active,.btn-microsoft.active,.open .dropdown-toggle.btn-microsoft{background-image:none} +.btn-microsoft.disabled,.btn-microsoft[disabled],fieldset[disabled] .btn-microsoft,.btn-microsoft.disabled:hover,.btn-microsoft[disabled]:hover,fieldset[disabled] .btn-microsoft:hover,.btn-microsoft.disabled:focus,.btn-microsoft[disabled]:focus,fieldset[disabled] .btn-microsoft:focus,.btn-microsoft.disabled:active,.btn-microsoft[disabled]:active,fieldset[disabled] .btn-microsoft:active,.btn-microsoft.disabled.active,.btn-microsoft[disabled].active,fieldset[disabled] .btn-microsoft.active{background-color:#2672ec;border-color:rgba(0,0,0,0.2)} +.btn-microsoft .badge{color:#2672ec;background-color:#fff} +.btn-openid{color:#fff;background-color:#f7931e;border-color:rgba(0,0,0,0.2)}.btn-openid:hover,.btn-openid:focus,.btn-openid:active,.btn-openid.active,.open .dropdown-toggle.btn-openid{color:#fff;background-color:#e47f08;border-color:rgba(0,0,0,0.2)} +.btn-openid:active,.btn-openid.active,.open .dropdown-toggle.btn-openid{background-image:none} +.btn-openid.disabled,.btn-openid[disabled],fieldset[disabled] .btn-openid,.btn-openid.disabled:hover,.btn-openid[disabled]:hover,fieldset[disabled] .btn-openid:hover,.btn-openid.disabled:focus,.btn-openid[disabled]:focus,fieldset[disabled] .btn-openid:focus,.btn-openid.disabled:active,.btn-openid[disabled]:active,fieldset[disabled] .btn-openid:active,.btn-openid.disabled.active,.btn-openid[disabled].active,fieldset[disabled] .btn-openid.active{background-color:#f7931e;border-color:rgba(0,0,0,0.2)} +.btn-openid .badge{color:#f7931e;background-color:#fff} +.btn-reddit{color:#000;background-color:#eff7ff;border-color:rgba(0,0,0,0.2)}.btn-reddit:hover,.btn-reddit:focus,.btn-reddit:active,.btn-reddit.active,.open .dropdown-toggle.btn-reddit{color:#000;background-color:#c6e3ff;border-color:rgba(0,0,0,0.2)} +.btn-reddit:active,.btn-reddit.active,.open .dropdown-toggle.btn-reddit{background-image:none} +.btn-reddit.disabled,.btn-reddit[disabled],fieldset[disabled] .btn-reddit,.btn-reddit.disabled:hover,.btn-reddit[disabled]:hover,fieldset[disabled] .btn-reddit:hover,.btn-reddit.disabled:focus,.btn-reddit[disabled]:focus,fieldset[disabled] .btn-reddit:focus,.btn-reddit.disabled:active,.btn-reddit[disabled]:active,fieldset[disabled] .btn-reddit:active,.btn-reddit.disabled.active,.btn-reddit[disabled].active,fieldset[disabled] .btn-reddit.active{background-color:#eff7ff;border-color:rgba(0,0,0,0.2)} +.btn-reddit .badge{color:#eff7ff;background-color:#000} +.btn-soundcloud{color:#fff;background-color:#f50;border-color:rgba(0,0,0,0.2)}.btn-soundcloud:hover,.btn-soundcloud:focus,.btn-soundcloud:active,.btn-soundcloud.active,.open .dropdown-toggle.btn-soundcloud{color:#fff;background-color:#d64700;border-color:rgba(0,0,0,0.2)} +.btn-soundcloud:active,.btn-soundcloud.active,.open .dropdown-toggle.btn-soundcloud{background-image:none} +.btn-soundcloud.disabled,.btn-soundcloud[disabled],fieldset[disabled] .btn-soundcloud,.btn-soundcloud.disabled:hover,.btn-soundcloud[disabled]:hover,fieldset[disabled] .btn-soundcloud:hover,.btn-soundcloud.disabled:focus,.btn-soundcloud[disabled]:focus,fieldset[disabled] .btn-soundcloud:focus,.btn-soundcloud.disabled:active,.btn-soundcloud[disabled]:active,fieldset[disabled] .btn-soundcloud:active,.btn-soundcloud.disabled.active,.btn-soundcloud[disabled].active,fieldset[disabled] .btn-soundcloud.active{background-color:#f50;border-color:rgba(0,0,0,0.2)} +.btn-soundcloud .badge{color:#f50;background-color:#fff} +.btn-tumblr{color:#fff;background-color:#2c4762;border-color:rgba(0,0,0,0.2)}.btn-tumblr:hover,.btn-tumblr:focus,.btn-tumblr:active,.btn-tumblr.active,.open .dropdown-toggle.btn-tumblr{color:#fff;background-color:#1f3346;border-color:rgba(0,0,0,0.2)} +.btn-tumblr:active,.btn-tumblr.active,.open .dropdown-toggle.btn-tumblr{background-image:none} +.btn-tumblr.disabled,.btn-tumblr[disabled],fieldset[disabled] .btn-tumblr,.btn-tumblr.disabled:hover,.btn-tumblr[disabled]:hover,fieldset[disabled] .btn-tumblr:hover,.btn-tumblr.disabled:focus,.btn-tumblr[disabled]:focus,fieldset[disabled] .btn-tumblr:focus,.btn-tumblr.disabled:active,.btn-tumblr[disabled]:active,fieldset[disabled] .btn-tumblr:active,.btn-tumblr.disabled.active,.btn-tumblr[disabled].active,fieldset[disabled] .btn-tumblr.active{background-color:#2c4762;border-color:rgba(0,0,0,0.2)} +.btn-tumblr .badge{color:#2c4762;background-color:#fff} +.btn-twitter{color:#fff;background-color:#55acee;border-color:rgba(0,0,0,0.2)}.btn-twitter:hover,.btn-twitter:focus,.btn-twitter:active,.btn-twitter.active,.open .dropdown-toggle.btn-twitter{color:#fff;background-color:#309aea;border-color:rgba(0,0,0,0.2)} +.btn-twitter:active,.btn-twitter.active,.open .dropdown-toggle.btn-twitter{background-image:none} +.btn-twitter.disabled,.btn-twitter[disabled],fieldset[disabled] .btn-twitter,.btn-twitter.disabled:hover,.btn-twitter[disabled]:hover,fieldset[disabled] .btn-twitter:hover,.btn-twitter.disabled:focus,.btn-twitter[disabled]:focus,fieldset[disabled] .btn-twitter:focus,.btn-twitter.disabled:active,.btn-twitter[disabled]:active,fieldset[disabled] .btn-twitter:active,.btn-twitter.disabled.active,.btn-twitter[disabled].active,fieldset[disabled] .btn-twitter.active{background-color:#55acee;border-color:rgba(0,0,0,0.2)} +.btn-twitter .badge{color:#55acee;background-color:#fff} +.btn-vimeo{color:#fff;background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)}.btn-vimeo:hover,.btn-vimeo:focus,.btn-vimeo:active,.btn-vimeo.active,.open .dropdown-toggle.btn-vimeo{color:#fff;background-color:#129cc9;border-color:rgba(0,0,0,0.2)} +.btn-vimeo:active,.btn-vimeo.active,.open .dropdown-toggle.btn-vimeo{background-image:none} +.btn-vimeo.disabled,.btn-vimeo[disabled],fieldset[disabled] .btn-vimeo,.btn-vimeo.disabled:hover,.btn-vimeo[disabled]:hover,fieldset[disabled] .btn-vimeo:hover,.btn-vimeo.disabled:focus,.btn-vimeo[disabled]:focus,fieldset[disabled] .btn-vimeo:focus,.btn-vimeo.disabled:active,.btn-vimeo[disabled]:active,fieldset[disabled] .btn-vimeo:active,.btn-vimeo.disabled.active,.btn-vimeo[disabled].active,fieldset[disabled] .btn-vimeo.active{background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)} +.btn-vimeo .badge{color:#1ab7ea;background-color:#fff} +.btn-vk{color:#fff;background-color:#587ea3;border-color:rgba(0,0,0,0.2)}.btn-vk:hover,.btn-vk:focus,.btn-vk:active,.btn-vk.active,.open .dropdown-toggle.btn-vk{color:#fff;background-color:#4a6a89;border-color:rgba(0,0,0,0.2)} +.btn-vk:active,.btn-vk.active,.open .dropdown-toggle.btn-vk{background-image:none} +.btn-vk.disabled,.btn-vk[disabled],fieldset[disabled] .btn-vk,.btn-vk.disabled:hover,.btn-vk[disabled]:hover,fieldset[disabled] .btn-vk:hover,.btn-vk.disabled:focus,.btn-vk[disabled]:focus,fieldset[disabled] .btn-vk:focus,.btn-vk.disabled:active,.btn-vk[disabled]:active,fieldset[disabled] .btn-vk:active,.btn-vk.disabled.active,.btn-vk[disabled].active,fieldset[disabled] .btn-vk.active{background-color:#587ea3;border-color:rgba(0,0,0,0.2)} +.btn-vk .badge{color:#587ea3;background-color:#fff} +.btn-yahoo{color:#fff;background-color:#720e9e;border-color:rgba(0,0,0,0.2)}.btn-yahoo:hover,.btn-yahoo:focus,.btn-yahoo:active,.btn-yahoo.active,.open .dropdown-toggle.btn-yahoo{color:#fff;background-color:#570b79;border-color:rgba(0,0,0,0.2)} +.btn-yahoo:active,.btn-yahoo.active,.open .dropdown-toggle.btn-yahoo{background-image:none} +.btn-yahoo.disabled,.btn-yahoo[disabled],fieldset[disabled] .btn-yahoo,.btn-yahoo.disabled:hover,.btn-yahoo[disabled]:hover,fieldset[disabled] .btn-yahoo:hover,.btn-yahoo.disabled:focus,.btn-yahoo[disabled]:focus,fieldset[disabled] .btn-yahoo:focus,.btn-yahoo.disabled:active,.btn-yahoo[disabled]:active,fieldset[disabled] .btn-yahoo:active,.btn-yahoo.disabled.active,.btn-yahoo[disabled].active,fieldset[disabled] .btn-yahoo.active{background-color:#720e9e;border-color:rgba(0,0,0,0.2)} +.btn-yahoo .badge{color:#720e9e;background-color:#fff} +.btn-pinterest{color:#fff;background-color:#d94752;border-color:rgba(0,0,0,0.2)}.btn-pinterest:hover,.btn-pinterest:focus,.btn-pinterest:active,.btn-pinterest.active,.open .dropdown-toggle.btn-pinterest{color:#fff;background-color:#cb2027;border-color:rgba(0,0,0,0.2)} +.btn-pinterest:active,.btn-pinterest.active,.open .dropdown-toggle.btn-pinterest{background-image:none} +.btn-pinterest.disabled,.btn-pinterest[disabled],fieldset[disabled] .btn-pinterest,.btn-pinterest.disabled:hover,.btn-pinterest[disabled]:hover,fieldset[disabled] .btn-pinterest:hover,.btn-pinterest.disabled:focus,.btn-pinterest[disabled]:focus,fieldset[disabled] .btn-pinterest:focus,.btn-pinterest.disabled:active,.btn-pinterest[disabled]:active,fieldset[disabled] .btn-pinterest:active,.btn-pinterest.disabled.active,.btn-pinterest[disabled].active,fieldset[disabled] .btn-pinterest.active{background-color:#d94752;border-color:rgba(0,0,0,0.2)} diff --git a/src/static/movio/templates/Minimal-in-blue/less/libs/bootstrap.less b/src/static/movio/templates/Minimal-in-blue/less/libs/bootstrap.less new file mode 100755 index 0000000..b48afb5 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/libs/bootstrap.less @@ -0,0 +1,2820 @@ +/*! + * Bootstrap v3.1.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px @solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +@media print { + * { + text-shadow: none !important; + color: #000 !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) ")"; + } + 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; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .table td, + .table th { + background-color: #fff !important; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px @solid #000; + } + .table { + border-collapse: collapse !important; + } + .table-bordered th, + .table-bordered td { + border: 1px @solid #ddd !important; + } +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 62.5%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333333; + background-color: #ffffff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #428bca; + text-decoration: none; +} +a:hover, +a:focus { + color: #2a6496; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px @solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #999999; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 200; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +cite { + font-style: normal; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-muted { + color: #999999; +} +.text-primary { + color: #428bca; +} +a.text-primary:hover { + color: #3071a9; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #428bca; +} +a.bg-primary:hover { + background-color: #3071a9; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px @solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px @solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #999999; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px @solid #eeeeee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +blockquote:before, +blockquote:after { + content: ""; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + white-space: nowrap; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 3px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px @solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: 0%; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: 0%; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: 0%; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: 0%; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: 0%; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: 0%; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: 0%; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: 0%; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + max-width: 100%; + background-color: transparent; +} +th { + text-align: left; +} +.table { + width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px @solid #dddddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px @solid #dddddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.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 > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px @solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px @solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.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 col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +@media (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + overflow-x: scroll; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px @solid #dddddd; + -webkit-overflow-scrolling: touch; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px @solid #e5e5e5; +} +label { + display: inline-block; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + /* IE8-9 */ + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; + background-color: #ffffff; + background-image: none; + border: 1px @solid #cccccc; + border-radius: 4px; + -webkit-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-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #999999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999999; +} +.form-control::-webkit-input-placeholder { + color: #999999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; + opacity: 1; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +input[type="date"] { + line-height: 34px; +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + display: block; + min-height: 20px; + margin-top: 10px; + margin-bottom: 10px; + padding-left: 20px; +} +.radio label, +.checkbox label { + display: inline; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + float: left; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +.radio[disabled], +.radio-inline[disabled], +.checkbox[disabled], +.checkbox-inline[disabled], +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"], +fieldset[disabled] .radio, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.has-feedback .form-control-feedback { + position: absolute; + top: 25px; + right: 0; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} +.has-error .form-control-feedback { + color: #a94442; +} +.form-control-static { + margin-bottom: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + padding-left: 0; + vertical-align: middle; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .control-label, +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +.form-horizontal .form-control-static { + padding-top: 7px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + top: 0; + right: 15px; +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + cursor: pointer; + background-image: none; + border: 1px @solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + color: #333333; + background-color: #ebebeb; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default .badge { + color: #ffffff; + background-color: #333333; +} +.btn-primary { + color: #ffffff; + background-color: #428bca; + border-color: #357ebd; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #3276b1; + border-color: #285e8e; +} +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #428bca; + border-color: #357ebd; +} +.btn-primary .badge { + color: #428bca; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #47a447; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #39b3d7; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ed9c28; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #d2322d; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #ffffff; +} +.btn-link { + color: #428bca; + font-weight: normal; + cursor: pointer; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #2a6496; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #999999; + text-decoration: none; +} +.btn-lg { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.btn-sm { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; + padding-left: 0; + padding-right: 0; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + transition: height 0.35s ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px @solid; + border-right: 4px @solid transparent; + border-left: 4px @solid transparent; +} +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.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; + font-size: 14px; + background-color: #ffffff; + border: 1px @solid #cccccc; + border: 1px @solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #428bca; +} +.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; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #999999; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px @solid; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px @solid #cccccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.clearfix:before, +.clearfix:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.nav:before, +.nav:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.nav:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} + diff --git a/src/static/movio/templates/Minimal-in-blue/less/libs/mixin.less b/src/static/movio/templates/Minimal-in-blue/less/libs/mixin.less new file mode 100755 index 0000000..73a2e71 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/libs/mixin.less @@ -0,0 +1,100 @@ +.padding-margin-reset() { + padding:0; + margin:0; +} + +.margin-reset() { +margin:0; +} + +.padding-reset() { +padding:0; +} + +.pmr() { + .padding-reset(); + .margin-reset(); +} + +.box-sizing() { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.input-style (@width) { + background:@form-input-background; + border:0; + box-shadow:0; + color:@form-input-text; + width:@width; + padding:2px; + font-size:14px; + border:1px @solid @form-border; + height: 30px; + .border-radius(5px); + &.required { + border:2px solid @form-required; + } +} +.button-style (@width) { + .button(auto, @form-button); + border:0; +} +.button(@width, @background:@form-button) { + background:@background; + width:@width; + text-align:center; + color:@form-button-text; + line-height:1em; + height:30px; + display:inline-block; + padding:0 15px 0 15px; + font-size:14px; + line-height:30px; + .border-radius(5px); + text-decoration:none; + &:hover { + text-decoration:none; + } +} +.border-radius (@radius) { + border-radius: @radius; + -moz-border-radius: @radius; + -webkit-border-radius: @radius; +} + +.icon-font() { + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #999) { + box-shadow: @arguments; + -moz-box-shadow: @arguments; + -webkit-box-shadow: @arguments; +} + +.grid(@col, @span, @margin) { + width: ((100% - (@margin * (@col - 1))) / @col * @span) + (@margin * (@span - 1)); + margin-right: @margin; +} + +/* define transition */ + +.transition (@time:.4s){ + -moz-transition:all @time ease-in-out; + -webkit-transition:all @time ease-in-out; + -o-transition:all @time ease-in-out; + transition:all @time ease-in-out; + backface-visibility: hidden; + webkit-backface-visibility: hidden; + } + +.opacity (@opacity:.5){ + opacity:@opacity; +/* filter: alpha(opacity=@opacity);*/ + } diff --git a/src/static/movio/templates/Minimal-in-blue/less/mobile.less b/src/static/movio/templates/Minimal-in-blue/less/mobile.less new file mode 100755 index 0000000..848fc45 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/mobile.less @@ -0,0 +1,253 @@ +@media (max-width: 979px) { + .navbar-toggle, .show-nav-for-iphone, .show-footer-nav-for-iphone { + display:block; + } + .navbar-toggle { + margin-left:15px; + } + .show-footer-nav-for-iphone { + margin-top:10px; + } + .collapse { + display:none; + } + .sx { + width:100%; + float:none; + } + .main-content { + width:100%; + float:none; + + .row-fluid { + padding-left:20px; + padding-right:20px; + } + + } + + .site-logo { + margin-left:20px; + } + + .languages { + padding-right:10px; + } + + .btn-menu { + &.show, &.close { + margin-right:20px; + } + } + + .main-content { + padding-left:20px; + padding-right:20px; + } + + footer { + + .clearfix { + padding-left:20px; + padding-right:20px; + } + + } + #topbar { + padding-bottom:8px; + form { + display:none; + } + } +#outer { + padding-left:0; + padding-right:0; +} + +} + + +@media (max-width: 765px) { + + /* slideshow */ + article.slideshow { + .description { + min-height:200px!important; + padding-left:10px; + width:100%!important; + margin-left:0; + background-color:@slider-background; + max-width:100%!important; + margin-left:0!important; + } + } +} + +@media (max-width: 650px) { + + .top-search { + display:none; + } + + figure.main-img { + float:left!important; + margin-left:0!important; + +} + +.main-content { + + p, .properties, h1,h2,h3,h4 { + clear:both; + } + + img { + + &.right, &.left { + display:block; + margin:0 auto; + float:none; + margin-bottom:12px; + } + + } + +} + + .site-logo { + width:253px; + height:52px; + top:30px; + left:50%!important; + margin-left:-126px; + } + + + .box, .item.in-grid, .box.relationImageLink .item { + + &.col-md-3, &.col-md-1, &.col-md-4, &.col-md-2 { + width:100%!important; + max-width:300px; + float:none; + margin-right:0!important; + margin:0 auto!important; + margin-right:auto!important; + margin-bottom:20px!important; + + &:last-child { + margin-right:auto!important; + } + + } + + } + + footer { + padding-bottom:12px; + + .logo-footer { + float:none; + } + + .pull-left, .pull-right { + float:none; + width:100%; + text-align:center; + } + + .pull-right { + + ul { + text-align:center; + + } + + } + + &:before { + content:""; + display:none; + } + + } + +} + +@media (max-width: 480px) { + + .site-logo { + width:120px!important; + margin-left:-60px!important; + background:url(../img/logo-mobile.png) no-repeat!important; + } + + input[type="text"], input[type="password"], input[type="email"] { + + &.input-large { + width:280px; + } + + } + + select { + width:auto; + &.select-large { + width:280px; + } + &.select-small { + width:160px; + } + &.select-medium { + width:260px; + } + } + + .box-gallery-description { + width:100%; + } + + .results-content { + + .item { + + img { + display:block; + margin:0 auto; + float:none; + margin-bottom:12px; + } + + h1 { + text-align:center; + } + + } + + } + + .storyteller { + + #nav-bar { + + + ul { + + li { + border-right:0!important; + } + + } + + } + + } + +} + +/* iPads (portrait) ----------- */ +@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : portrait) { +} + +/* iPads (landscape) ----------- */ +@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : landscape) { +} diff --git a/src/static/movio/templates/Minimal-in-blue/less/navigation.less b/src/static/movio/templates/Minimal-in-blue/less/navigation.less new file mode 100644 index 0000000..f0675c4 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/navigation.less @@ -0,0 +1,145 @@ +/** + * Language navigation + */ +.languages { + float:left; + margin-top:5px; + ul { + .padding-margin-reset(); + li { + display:inline; + padding:0 0 0 4px; + &:last-child { + border-right:0; + } + a { + display:inline-block; + margin-right:6px; + color:@languages-link; + &.active { + text-decoration:underline; + color:@languages-link-hover; + } + } + } + } +} + +/** + * Matanavigation + */ +.metanavigation { + margin-left:20px; + float:left; + margin-top:5px; + ul { + .padding-margin-reset(); + li { + display:inline; + padding:0 0 0 4px; + a { + display:inline-block; + margin-right:6px; + &.active { + text-decoration:underline; + } + } + } + } +} + +/** + * Navigation menu + */ +.menu { + padding:15px 0; + position:relative; + ul { + margin-left:0; + padding-left:15px; + li { + margin-bottom:5px; + a { + color: @sidebar-link; + font-size:16px; + &:hover { + color: @sidebar-link-hover; + } + &.active { + color: @sidebar-link-hover; + text-decoration:underline; + } + } + } + } +} + +/** + * Breadcrumb + */ +.breadcrumb { + margin:0 0; + margin-bottom:30px; + border-bottom:0; + ul { + .padding-margin-reset(); + li { + display:inline; + font-style:italic; + a { + color: @breadkcrumbs-link-breadcrumd; + font-style:normal; + &:hover { + color: @breadkcrumbs-link-hover; + } + } + } + } +} + +/** + * Pagination + */ +.pagination { + width:100%; + + ul { + padding:0; + width:100%; + min-height:29px; + text-align:center; + text-align:center; + + li { + display:inline; + a { + border:0; + background:none; + float:none; + color:@text; + display:inline-block; + padding-top:0; + margin-top:7px; + padding-bottom:0; + line-height:1em; + font-size:14px; + outline:none; + padding:0 5px 0 5px; + border-left:1px @solid @box-border; + &:hover { + text-decoration:underline; + } + } + &.active a { + text-decoration:underline; + } + &:first-child > a { + border:0; + padding-left:17px; + } + &:last-child > a { + padding-right:17px; + } + } + } +} \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/less/slick.less b/src/static/movio/templates/Minimal-in-blue/less/slick.less new file mode 100755 index 0000000..7e17251 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/slick.less @@ -0,0 +1,137 @@ +/* slick */ +#outer { + + .slider { + margin-bottom:0; + + } + + /* dots */ + .slick-dots { + + li.slick-active { + + button { + background-color:@slider-bullet-background-selected; + border:1px solid @slider-bullet-background; + } + + } + + li button { + width:12px; + height:12px; + padding:0; + .border-radius(100px); + background-color:@slider-bullet-background; + border:1px solid @slider-bullet-background; + + &:hover { + background:#E3001B; + } + + &:before { + display:none; + } + + } + } + + /* Arrows */ + + .slick-prev:before, .slick-next:before { + font-family: 'FontAwesome'; + content:@fa-var-caret-left; + color:@color-arrow-button-slider; + opacity:1; + font-size:25px; + font-weight:lighter; + + } + + .slick-disabled { + display:none!important; + } + + .slick-next:before { + content:@fa-var-caret-right; + margin-right:-3px; + } + + .slick-prev, .slick-next { + width:20px; + height:40px; + padding-top:4px; + top:50%; + margin-top:-23px; + border:0; + .border-radius(0); + background:none; + + &:hover { + + &:before { + color:@color-arrow-button-slider-hover; + } + } + + + } + + .slick-prev { + left:0; + } + + .slick-next { + right:0; + } + + .slideshow { + + .slick-prev, .slick-next { + width:20px; + height:40px; + padding-top:4px; + top:auto; + bottom:0; + margin-top:0; + margin-bottom:20px; + border:0; + .border-radius(0); + background:none; + } + + .slick-prev { + margin-left:40px; + } + + .slick-next { + margin-left:365px; + left:0; + @media (max-width: 765px) { + margin-left:0; + right:0; + left:auto; + margin-right:20px; + } + + } + + .slick-prev:before, .slick-next:before { + font-family: 'FontAwesome'; + content:"\f053"; + color:@color-arrow-button-slider; + opacity:1; + font-weight:lighter; + color:@slider-text; + font-size:30px; + + } + + .slick-next:before { + content:"\f054"; + } + + } + +} \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/less/structure.less b/src/static/movio/templates/Minimal-in-blue/less/structure.less new file mode 100755 index 0000000..576edba --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/structure.less @@ -0,0 +1,329 @@ +.container-fluid { + padding:0; +} + +.content-box { + min-height:290px; + position:relative; +} + +.navbar-toggle, .show-nav-for-iphone, .show-footer-nav-for-iphone { + display:none; +} + +#outer { + padding-bottom:25px; + width:100%; + max-width:@max-width-outer; + margin:0 auto; + + @media (max-width:1260px) { + padding-left:20px; + padding-right:20px; + } + +} + +#topbar { + font-size:14px; + min-height:52px; + padding-top:10px; + padding-left:10px; + padding-right:10px; + background:@black; +} + +header { + padding:0 0; + position:relative; + min-height:97px; + + + &.show-menu { + + .menu { + display:block; + .opacity(1); + } + + .btn-menu.close { + display:block; + } + + .btn-menu.open { + display:none; + } + + } + + .menu, .btn-menu.close { + display:none; + } + + h1,h2 { + .padding-margin-reset(); + } + + .site-logo { + background:url(../img/logo.png) 0 0 no-repeat; + width:253px; + height:52px; + position:absolute; + top:30px; + left:0; + text-indent:-9999px; + } + + .languages { + display:block; + height:25px; + width:100%; + text-align:right; + margin:0 0 12px 0; + padding-top:5px; + + ul { + + li { + + a { + color:@languages-link; + + &.active, &:hover { + color:@languages-link-hover; + text-decoration:none; + } + + } + + } + + } + + } + + .btn-menu { + display:block; + float:right; + cursor:pointer; + margin-left:25px; + margin-top:3px; + z-index:1005; + + &.show { + + .wrapper-icon { + display:inline-block; + width:25px; + height:25px; + border:1px solid @box-header-link; + text-align:center; + line-height:23px; + cursor:pointer; + float:left; + margin-right:5px; + } + + .fa { + color:@box-header-link; + } + + .wrapper-text { + display:inline-block; + float:left; + color:@box-header-link; + font-weight:600; + text-transform:uppercase; + font-size:13px; + line-height:25px; + } + + } + + &.close { + position:absolute; + top:0; + right:0; + margin-top:45px; + margin-right:15px; + + .wrapper-icon { + display:inline-block; + width:auto; + height:25px; + border:1px solid @color-link; + text-align:center; + line-height:21px; + cursor:pointer; + float:left; + margin-right:5px; + } + + .fa { + color:@white; + } + + .wrapper-text { + display:inline-block; + float:left; + color:@white; + font-weight:600; + text-transform:uppercase; + font-size:13px; + line-height:25px; + } + } + + } + + .menu { + position:absolute; + top:0; + left:0; + z-index:1000; + width:100%; + background:@navigation-background; + padding-top:60px; + .transition(); + + ul { + padding-left:20px; + + li { + list-style:none; + + a { + color:@white; + font-size:22px; + text-transform:uppercase; + font-weight:lighter; + + &:hover, &.active { + text-decoration:none; + color:@black; + } + + } + + ul { + + li { + + a { + font-size:18px; + text-transform:none; + } + + } + + } + + } + + } + + } + +} + +footer { + width:100%; + max-width:@max-width-outer; + clear:both; + margin:0 auto; + background:@footer-background; + font-size:12px; + position:relative; + color:@footer-text; + padding-bottom:10px; + + @media (max-width:1260px) { + .clearfix { + padding-left:20px; + padding-right:20px; + } + } + + &:before { + content:""; + display:block; + width:100%; + height:1px; + background:@footer-border; + position:absolute; + top:0; + margin:17px 0 0 0; + } + + .logo-footer { + float:right; + margin-left:10px; + margin-top: 22px; + } + + ul { + .padding-margin-reset(); + padding-bottom:7px; + margin-right:-8px; + + li { + display:inline; + border-right:1px solid @footer-border; + padding-right:8px; + + &:last-child { + border-right:0; + } + + a { + color:@metanavigation-link; + display:inline-block; + text-transform:uppercase; + padding-left:5px; + + &:hover, &.active { + text-decoration:none; + color:@metanavigation-link-hover; + } + + } + + } + + } + + #info-page { + padding:0 0; + + p { + font-size:10px; + padding-top:0; + line-height:1em; + } + + } +} + +.sx { + float:left; + + nav { + margin:0; + } + + #nav-collapse { + .padding-margin-reset(); + } +} + + +@media (min-width: 979px) { + header, footer, .sx { + .collapse { + display:block; + height:auto!important; + } + } +} + + diff --git a/src/static/movio/templates/Minimal-in-blue/less/styles.less b/src/static/movio/templates/Minimal-in-blue/less/styles.less new file mode 100755 index 0000000..8c78b47 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/styles.less @@ -0,0 +1,140 @@ +/** + * Import libraries + * + * Bootstrap custom build: + * Print media styles + * Typography + * Code + * Grid system + * Tables + * Forms + * Buttons + * Input groups + * Badges + * Component animations (for JS) + * Dropdowns + * Basic utilities + * Responsive utilities +*/ +@import "libs/bootstrap.less"; +@import "libs/mixin.less"; +@import "font-awesome/font-awesome.less"; +@import "libs/bootstrap-social.less"; + +/** + * Import theme parts +*/ +@import "global.less"; +@import "structure.less"; +@import "navigation.less"; +@import "element.less"; +@import "slick.less"; +@import "mobile.less"; +@import "svg.less"; + +@font-1: 'Titillium Web', sans-serif; +@font-2: 'PT Sans', sans-serif; + +/*define colors */ +@white:#fff; +@black:#000; +@color1:#CCC; +@color4:#7A7A7A; +@color5:#C6C6C6; +@color7:#F5F5F5; +@color8:#0099FF; +@color9:#545453; +@color10:#5E5E5D; +@color11:#333; +@color12:#CC0000; +@color-success:green; +@color-error:red; +@solid:solid; + +/*define theme colors */ +@text: @color11; +@text-heading: @color11; +@color-link: @color8; +@color-link-hover: darken(@color8, 5); +@breadkcrumbs-link: @color-link; +@breadkcrumbs-link-hover: @color-link-hover; + +@navigation-background:@color8; +@sidebar-link: @color-link; +@sidebar-link-hover: @color-link-hover; + +@languages-link:@color9; +@languages-link-hover:@color-link; +@metanavigation-link: @color10; +@metanavigation-link-hover: @color-link; + +@slider-background:@color1; +@slider-text:@white; +@slider-bullet-background: @black; +@slider-bullet-background-selected: @color1; + +@icon-in-page:lighten(@text, 30); +@icon-in-box:@white; +@icon-in-box-background:@color1; + +@box-image-border:@color1; +@box-background:@white; +@box-border:@color1; +@box-header-link:@color9; +@box-relation-item-border:@color1; +@box-text:@black; + +@color-border-button:@color1; +@color-arrow-button-slider:@color11; +@color-arrow-button-slider-hover:@color8; + +@form-border: @color1; +@form-required: @color1; +@form-button: @color4; +@form-button-text: @white; +@form-button-primary: @color8; +@form-button-primary-text:@white; +@form-input-text:@text; +@form-input-background:@white; + +@timeline-theme: @color8; + +@storyteller-background:transparent; +@storyteller-icon: lighten(@text, 70); +@storyteller-border:@color1; +@storyteller-item-background: @white; +@storyteller-comments-background:@white; +@storyteller-link: @color8; +@storyteller-link-hover: @color7; +@storyteller-navigation-link: @color4; +@storyteller-image-border: @color5; + +@footer-background:transparent; +@footer-border: @color1; +@footer-text: @color10; + + +/* custom for this template */ +@max-width-outer:1200px; +@breadkcrumbs-link-breadcrumd:@color11; + +@color-link-attach:@white; +@color-link-attach-hover:@white; +@bg-link-attach:@color1; +@bg-link-attach-hover:@color9; + +@color-tag-attach:@white; +@color-tag-attach-hover:#666; +@bg-tag-attach:#666; +@bg-tag-attach-hover:@color1; +@bg-dl:#fafafa; +@bg-block-my-pop-up:#fafafa; + +@svg-path-stroke:#000000; +@svg-main-node-background:#D3D3D3; +@svg-node-border:#CFCED3; +@svg-text-link:#CC3522; +@svg-text-link-hover:darken(@svg-text-link, 15); +@svg-text-node:#000000; +@svg-text-main-node:#000000; +@svg-node-background:#FFFFFF; \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/less/svg.less b/src/static/movio/templates/Minimal-in-blue/less/svg.less new file mode 100644 index 0000000..8af1567 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/less/svg.less @@ -0,0 +1,59 @@ +svg { + overflow: hidden; +} + +/* Stile testo delle entità */ +g.nodes tspan { + font-family: Helvetica, sans-serif; + font-size: 14px; + color: @svg-text-node; +} +/* Stile testo delle entità in HTML */ +g.nodes div { + white-space: nowrap; + padding: 2px 5px 2px 5px; + font-family: Helvetica, sans-serif; + font-size: 14px; + color: @svg-text-node; +} + +/* Stile testo delle entità principali */ +g.nodes tspan.main-node { + fill: @svg-text-main-node !important; +} +/* Stile testo delle entità principali in HTML */ +div.main-node { + padding: 2px 7px 2px 7px; + font-family: Helvetica, sans-serif; + font-size: 14px; + color: @svg-text-main-node !important; +} + +/* Stile testo delle relazioni */ +g.edgeLabels tspan { + +} +/* Stile riquadro delle entità */ +.node rect { + stroke: @svg-node-border; + stroke-width: 2px; + fill: @svg-node-background; +} +.node a { + color: @svg-text-link; + text-decoration: underline; +} +.node a:hover { + color: @svg-text-link-hover; +} +/* Stile riquadro delle entità principali */ +.node rect.main-node { + fill: @svg-main-node-background; +} +/* Stile delle frecce */ +.edgePath path { + stroke: @svg-path-stroke; + stroke-width: 1.5px; + fill: none; +} + diff --git a/src/static/movio/templates/Minimal-in-blue/page.php b/src/static/movio/templates/Minimal-in-blue/page.php new file mode 100644 index 0000000..4e1cf75 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/page.php @@ -0,0 +1,143 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title><?php print $docTitle?></title> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> + <script>window.jQuery || document.write('<script src="js/jquery-1.8.2.min.js"><\/script>')</script> + <?php print $css?> + <link rel="stylesheet" type="text/css" href="../../../mediaelement/mediaelementplayer.css" charset="utf-8"> + <link rel="stylesheet" type="text/css" href="../../../js/slick/slick.css"> + <?php print $head?> +</head> + +<body> + <!-- outer --> + <div id="outer"> + + <!-- content --> + <div class="clearfix container-fluid"> + + <!-- header show-menu --> + <header class="row-fluid js-header clearfix"> + + <a href="<?php print GLZ_HOST; ?>" class="site-logo"><?php print $siteTitle; ?></a> + + <!-- langs --> + <nav class="languages"> + <?php print $languages; ?> + </nav> + <!-- langs --> + + <a class="btn-menu show" > + <span class="wrapper-icon"> + <i class="fa fa-align-justify"></i> + </span> + <span class="wrapper-text">menu</span> + </a> + + <a class="btn-menu close"> + <span class="wrapper-icon"> + <i class="fa fa-times"></i> + </span> + <span class="wrapper-text">close</span> + </a> + +<!-- +TODO menù dell'utente +userMenu + +--> + <?php print $search; ?> + + <!-- nax sx --> + <nav class="menu"> + <?php print $menu; ?> + </nav> + <!-- nav sx --> + + </header> + <!-- header --> + + <!-- content-box --> + <div class="content-box row-fluid clearfix"> + + <!-- article --> + <article class="main-content col-md-12"> + <?php if ($breadcrumbs) { ?> + <nav class="breadcrumb"> + <?php print $breadcrumbs; ?> + </nav> + <?php } ?> + <?php if ($pageTitle) { ?> + <div class="box-title clearfix"> + <?php print $pageTitle; ?> + <a href="javascript:window.print()" class="print-ico"><i class="fa fa-print icon-grey"></i></a> + </div> + <?php } ?> + <?php print $content; ?> + <?php print $afterContent; ?> + + </article> + <!-- article --> + </div> + <!-- content-box --> + </div> + <!-- content --> + </div> + <!-- outer --> + + <!-- footer --> + <footer> + <div class="clearfix"> + + <div class="pull-left"> + + <!-- info-page --> + <div id="info-page" class="visible-desktop"> + <div class="container-fluid"> + <p><?php print $docUpdate;?></p> + </div> + </div> + <!-- info-page --> + + <p>&copy; 2014 MOVIO - Lorem .... </p> + <?php print $sharing; ?> + + </div> + +<!-- +TODO; +copyright +print $linkFooter; +--> + + <div class="pull-right"> + + <?php print $metanavigation; ?> + + <div class="logo-footer"> + <?php print $logoFooter; ?> + <a href="http://www.movio.beniculturali.it" title="Movio - Online Virtual Exhibition"> + <img src="img/logo_movio.png" alt="Movio - Online Virtual Exhibition" title="Movio - Online Virtual Exhibition" > + </a> + </div> + + </div> + + </div> + </footer> + <!-- footer --> + + <script src="js/bootstrap.min.js"></script> + <script src="js/main.js"></script> + <script src="../../js/movio.js"></script> + <script src="../../../mediaelement/mediaelement-and-player.js" type="text/javascript"></script> + <script src="../../../js/slick/slick.min.js"></script> + + <?php print $tail; ?> +</body> +</html> \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/preview.jpg b/src/static/movio/templates/Minimal-in-blue/preview.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3c5c8dbcfe78332e7cb282e50a9c91ef90c16fa7 GIT binary patch literal 15548 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Minimal-in-blue/skins/BoxList.html b/src/static/movio/templates/Minimal-in-blue/skins/BoxList.html new file mode 100644 index 0000000..78d1528 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/skins/BoxList.html @@ -0,0 +1,21 @@ +<span tal:omit-tag="" tal:repeat="item Component"> + <div class="content-box row-fluid "> + <span tal:omit-tag="" tal:repeat="subitem item"> + <span tal:omit-tag=""> + <article tal:attributes="style subitem/style; class php: 'box col-md-' . subitem.width/3"> + <a tal:condition="subitem/image/__html__" tal:attributes="href subitem/pageId; title subitem/title" tal:content="structure subitem/image/__html__"></a> + <h1><a tal:attributes="href subitem/pageId; title subitem/title" tal:content="subitem/title"></a></h1> + <div class="container" tal:condition="php: subitem.type == 'imageText'"> + <span tal:omit-tag="" tal:content="structure subitem/text" /> + </div> + <div class="wrapper-link"> + <a tal:attributes="href subitem/pageId; title subitem/title"> + <span tal:condition="php: subitem.type == 'imageLink'" tal:omit-tag="" tal:content="subitem/linkTitle" /> + <i class="fa fa-arrow-right"></i> + </a> + </div> + </article> + </span> + </span> + </div> +</span> \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/skins/BoxSearch.html b/src/static/movio/templates/Minimal-in-blue/skins/BoxSearch.html new file mode 100644 index 0000000..0748086 --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/skins/BoxSearch.html @@ -0,0 +1,7 @@ +<form class="top-search" method="get" tal:attributes="action SearchBox/__url__"> +<p> +<label tal:content="SearchBox/label"></label><input type="text" name="search" tal:attributes="placeholder php:__T('GLZ_SEARCH')" /> +<input type="submit" class="button" name="" tal:attributes="value php:__T('GLZ_SEARCH')" /> +<i class="fa fa-search"></i> +</p> +</form> \ No newline at end of file diff --git a/src/static/movio/templates/Minimal-in-blue/skins/HomeImageSlider.html b/src/static/movio/templates/Minimal-in-blue/skins/HomeImageSlider.html new file mode 100644 index 0000000..11987bb --- /dev/null +++ b/src/static/movio/templates/Minimal-in-blue/skins/HomeImageSlider.html @@ -0,0 +1,26 @@ +<article class="slideshow big"> + <div class="slider single-item js-sliderhome" > + <div class="slide" tal:attributes="style php:Template::homeSliderImage(item)" tal:repeat="item Component"> + <div class="description"> + <h1><a tal:attributes="href item/pageId; title item/title" tal:content="item/title"></a></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <a class="link-continue" tal:attributes="href item/pageId" tal:content="php: __T('read more')"></a> + </div> + </div> + </div> +<script> +$(function() { + $('.js-sliderhome').slick({ + dots: true, + autoplay: true, + autoplaySpeed: Glizy.slideShowSpeed, + arrows:false, + infinite: true, + speed: 700, + pauseOnDotsHover: true, + slidesToShow: 1, + slidesToScroll: 1 + }); +}); +</script> +</article> \ No newline at end of file diff --git a/src/static/movio/templates/Movio/1col.php b/src/static/movio/templates/Movio/1col.php new file mode 100755 index 0000000..d8cae2e --- /dev/null +++ b/src/static/movio/templates/Movio/1col.php @@ -0,0 +1,131 @@ +<!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><?php print $docTitle?></title> + <meta name="description" content=""> + <meta name="viewport" content="width=device-width"> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> + <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.8.2.min.js"><\/script>')</script> + <script src="js/vendor/modernizr-2.6.2.min.js"></script> + <?php print $css?> + <link rel="stylesheet" type="text/css" href="../../../mediaelement/mediaelementplayer.css" charset="utf-8"> + <link rel="stylesheet" type="text/css" href="../../../js/slick/slick.css"> + <?php print $head?> + </head> + <body class="page"> + <!--[if lt IE 7]> + <p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p> + <![endif]--> + + <!-- outer --> + <div id="outer"> + <!-- metanavigation --> + <div id="topbar"> + <div class="contentWrapper clearfix"> + <nav class="langs"> + <?php print $languages; ?> + </nav> + <nav class="menu-top visible-tablet visible-desktop"> + <?php print $metanavigation; ?> + </nav> + <div class="menu-dropdown pull-right"> + <ul> + <li><a href="javascript:void(0)"><i class="icon fa fa-user"></i></a> + <?php print $userMenu; ?> + </li> + </ul> + </div> + <?php print $search; ?> + </div> + </div> + <!-- metanavigation --> + <div class="contentWrapper clearfix container-fluid"> + <!-- header --> + <header class="clearfix row-fluid"> + <div class="col-md-3 visible-tablet visible-desktop"> + <?php print $title3; ?> + </div> + <div class="<?php print ($title4 ? 'col-md-6' : 'col-md-9') ?>"> + <h1><?php print $title1; ?></h1> + <h2><?php print $title2; ?></h2> + </div> + <?php if ($title4) {?> + <div class="col-md-3 visible-tablet visible-desktop"> + <?php print $title4; ?> + </div> + <?php } ?> + </header> + <!-- header --> + + <!-- show-nav-for-iphone --> + <button type="button" class="show-nav-for-iphone col-md-12" data-toggle="collapse" data-target="#nav-collapse">MENU DI NAVIGAZIONE</button> + <!-- show-nav-for-iphone --> + + <!-- breadcrumb --> + <article class="main-content view-one-column col-md-12"> + <?php if ($breadcrumbs) { ?> + <nav class="breadcrumb"> + <?php print $breadcrumbs; ?> + </nav> + <?php } ?> + <?php if ($pageTitle) { ?> + <div class="box-title"> + <?php print $pageTitle; ?> + <a href="javascript:window.print()" class="print-ico"><i class="fa fa-print fa fa-grey"></i></a> + </div> + <?php } ?> + <div class="content-box row-fluid "> + <?php if ($navigation) { ?> + <div id="nav-collapse" class="collapse col-md-3"> + <nav class="menu-sx col-md-12"> + <?php print $navigation; ?> + </nav> + </div> + <?php } ?> + <?php print $content; ?> + </div> + <?php print $afterContent; ?> + <?php print $sharing; ?> + </article> + </div> + <!-- content --> + + </div> + <!-- outer --> + + <footer> + <div class="contentWrapper clearfix"> + <div class="logo-footer"> + <a href="http://www.movio.beniculturali.it" title="Movio"><img src="img/logo_movio.png" alt="Movio - Online Virtual Exhibition" title="Movio - Online Virtual Exhibition" width="109" height="44"></a> + <?php print $logoFooter; ?> + </div> + <?php if ($linkFooter) { ?> + <div class="box"> + <div id="nav-collapse-box1"> + <nav> + <?php print $linkFooter; ?> + </nav> + </div> + </div> + <?php } ?> + </div> + <div id="info-page" class="visible-desktop"> + <div class="contentWrapper container-fluid"> + <p class="pull-left"><?php print $copyright;?></p> + <p class="pull-right"><?php print $docUpdate;?></p> + </div> + </div> + </footer> + + <script src="js/bootstrap.min.js"></script> + <script src="js/main.js"></script> + <script src="../../js/movio.js"></script> + <script src="../../../mediaelement/mediaelement-and-player.js" type="text/javascript"></script> + <script src="../../../js/slick/slick.min.js"></script> + </body> +</html> \ No newline at end of file diff --git a/src/static/movio/templates/Movio/2cols.php b/src/static/movio/templates/Movio/2cols.php new file mode 100755 index 0000000..8b14536 --- /dev/null +++ b/src/static/movio/templates/Movio/2cols.php @@ -0,0 +1,158 @@ +<!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><?php print $docTitle?></title> + <meta name="description" content=""> + <meta name="viewport" content="width=device-width"> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> + <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.8.2.min.js"><\/script>')</script> + <script src="js/vendor/modernizr-2.6.2.min.js"></script> + <?php print $css?> + <link rel="stylesheet" type="text/css" href="../../../mediaelement/mediaelementplayer.css" charset="utf-8"> + <link rel="stylesheet" type="text/css" href="../../../js/slick/slick.css"> + <?php print $head?> + </head> + <body class="page"> + <!--[if lt IE 7]> + <p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p> + <![endif]--> + + <!-- outer --> + <div id="outer"> + <!-- metanavigation --> + <div id="topbar"> + <div class="contentWrapper clearfix"> + <nav class="langs"> + <?php print $languages; ?> + </nav> + <nav class="menu-top visible-tablet visible-desktop"> + <?php print $metanavigation; ?> + </nav> + + <div class="menu-dropdown pull-right"> + <ul> + <li><a href="javascript:void(0)"><i class="icon fa fa-user"></i></a> + <?php print $userMenu; ?> + </li> + </ul> + </div> + <?php print $search; ?> + </div> + </div> + <!-- metanavigation --> + <div class="contentWrapper clearfix container-fluid"> + <!-- header --> + <header class="clearfix row-fluid"> + <div class="col-md-3 visible-tablet visible-desktop"> + <?php print $title3; ?> + </div> + <div class="<?php print ($title4 ? 'col-md-6' : 'col-md-9') ?>"> + <h1><?php print $title1; ?></h1> + <h2><?php print $title2; ?></h2> + </div> + <?php if ($title4) {?> + <div class="col-md-3 visible-tablet visible-desktop"> + <?php print $title4; ?> + </div> + <?php } ?> + </header> + <!-- header --> + + <!-- show-nav-for-iphone --> + <button type="button" class="show-nav-for-iphone col-md-12" data-toggle="collapse" data-target="#nav-collapse">MENU DI NAVIGAZIONE</button> + <!-- show-nav-for-iphone --> + + <!-- content-box --> + <div class="content-box row-fluid"> + + <!-- aside sx --> + <aside class="sx col-md-3"> + + <!-- nav-collapse --> + <div id="nav-collapse" class="collapse col-md-12"> + + <!-- nax sx --> + <nav class="menu-sx"> + <?php print $leftSidebar; ?> + </nav> + <!-- nav sx --> + + </div> + <!-- nav-collapse --> + + <!-- show-nav-for-iphone --> + <button type="button" class="show-nav-for-iphone info-menu col-md-12" data-toggle="collapse" data-target="#nav-collapse-informazioni">INFORMAZIONI</button> + <!-- show-nav-for-iphone --> + + <!-- nav-collapse --> + <div id="nav-collapse-informazioni" class=""> + <?php print $leftSidebarAfter; ?> + <?php print $sharing; ?> + </div> + <!-- nav-collapse --> + + </aside> + <!-- aside sx --> + + <!-- article --> + <article class="main-content col-md-9"> + + <!-- breadcrumb --> + <nav class="breadcrumb"> + <?php print $breadcrumbs; ?> + </nav> + <!-- breadcrumb --> + <div class="box-title"> + <?php print $pageTitle; ?> + <a href="javascript:window.print()" class="print-ico"><i class="fa fa-print fa fa-grey"></i></a> + </div> + <?php print $content; ?> + <?php print $afterContent; ?> + </article> + <!-- article --> + + </div> + <!-- content-box --> + + </div> + <!-- content --> + + </div> + <!-- outer --> + + <footer> + <div class="contentWrapper clearfix"> + <div class="logo-footer"> + <a href="http://www.movio.beniculturali.it" title="Movio"><img src="img/logo_movio.png" alt="Movio - Online Virtual Exhibition" title="Movio - Online Virtual Exhibition" width="109" height="44"></a> + <?php print $logoFooter; ?> + </div> + <?php if ($linkFooter) { ?> + <div class="box"> + <div id="nav-collapse-box1"> + <nav> + <?php print $linkFooter; ?> + </nav> + </div> + </div> + <?php } ?> + </div> + <div id="info-page" class="visible-desktop"> + <div class="contentWrapper container-fluid"> + <p class="pull-left"><?php print $copyright;?></p> + <p class="pull-right"><?php print $docUpdate;?></p> + </div> + </div> + </footer> + + <script src="js/bootstrap.min.js"></script> + <script src="js/main.js"></script> + <script src="../../js/movio.js"></script> + <script src="../../../mediaelement/mediaelement-and-player.js" type="text/javascript"></script> + <script src="../../../js/slick/slick.min.js"></script> + </body> +</html> \ No newline at end of file diff --git a/src/static/movio/templates/Movio/3cols.php b/src/static/movio/templates/Movio/3cols.php new file mode 100644 index 0000000..f4d1536 --- /dev/null +++ b/src/static/movio/templates/Movio/3cols.php @@ -0,0 +1,163 @@ +<!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><?php print $docTitle?></title> + <meta name="description" content=""> + <meta name="viewport" content="width=device-width"> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> + <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.8.2.min.js"><\/script>')</script> + <script src="js/vendor/modernizr-2.6.2.min.js"></script> + <?php print $css?> + <link rel="stylesheet" type="text/css" href="../../../mediaelement/mediaelementplayer.css" charset="utf-8"> + <link rel="stylesheet" type="text/css" href="../../../js/slick/slick.css"> + <?php print $head?> + </head> + <body class="page"> + <!--[if lt IE 7]> + <p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p> + <![endif]--> + + <!-- outer --> + <div id="outer"> + <!-- metanavigation --> + <div id="topbar"> + <div class="contentWrapper clearfix"> + <nav class="langs"> + <?php print $languages; ?> + </nav> + <nav class="menu-top visible-tablet visible-desktop"> + <?php print $metanavigation; ?> + </nav> + <div class="menu-dropdown pull-right"> + <ul> + <li><a href="javascript:void(0)"><i class="icon fa fa-user"></i></a> + <?php print $userMenu; ?> + </li> + </ul> + </div> + <?php print $search; ?> + </div> + </div> + <!-- metanavigation --> + <div class="contentWrapper clearfix container-fluid"> + <!-- header --> + <header class="clearfix row-fluid"> + <div class="col-md-3 visible-tablet visible-desktop"> + <?php print $title3; ?> + </div> + <div class="<?php print ($title4 ? 'col-md-6' : 'col-md-9') ?>"> + <h1><?php print $title1; ?></h1> + <h2><?php print $title2; ?></h2> + </div> + <?php if ($title4) {?> + <div class="col-md-3 visible-tablet visible-desktop"> + <?php print $title4; ?> + </div> + <?php } ?> + </header> + <!-- header --> + + <!-- show-nav-for-iphone --> + <button type="button" class="show-nav-for-iphone col-md-12" data-toggle="collapse" data-target="#nav-collapse">MENU DI NAVIGAZIONE</button> + <!-- show-nav-for-iphone --> + + <!-- content-box --> + <div class="content-box row-fluid"> + + <!-- aside sx --> + <aside class="sx col-md-3"> + + <!-- nav-collapse --> + <div id="nav-collapse" class="collapse col-md-12"> + + <!-- nax sx --> + <nav class="menu-sx"> + <?php print $leftSidebar; ?> + </nav> + <!-- nav sx --> + + </div> + <!-- nav-collapse --> + + <!-- show-nav-for-iphone --> + <button type="button" class="show-nav-for-iphone info-menu col-md-12" data-toggle="collapse" data-target="#nav-collapse-informazioni">INFORMAZIONI</button> + <!-- show-nav-for-iphone --> + + <!-- nav-collapse --> + <div id="nav-collapse-informazioni" class=""> + <?php print $leftSidebarAfter; ?> + <?php print $sharing; ?> + </div> + <!-- nav-collapse --> + + </aside> + <!-- aside sx --> + + <!-- article --> + <article class="main-content col-md-9"> + + <!-- breadcrumb --> + <nav class="breadcrumb"> + <?php print $breadcrumbs; ?> + </nav> + <!-- breadcrumb --> + <div class="box-title"> + <?php print $pageTitle; ?> + <a href="javascript:window.print()" class="print-ico"><i class="fa fa-print fa fa-grey"></i></a> + </div> + <div class="row-fluid"> + <div class="col-md-8"> + <?php print $content; ?> + </div> + <aside class="dx col-md-4"> + <?php print $afterContent; ?> + </aside> + </div> + </article> + <!-- article --> + + </div> + <!-- content-box --> + + </div> + <!-- content --> + + </div> + <!-- outer --> + + <footer> + <div class="contentWrapper clearfix"> + <div class="logo-footer"> + <a href="http://www.movio.beniculturali.it" title="Movio"><img src="img/logo_movio.png" alt="Movio - Online Virtual Exhibition" title="Movio - Online Virtual Exhibition" width="109" height="44"></a> + <?php print $logoFooter; ?> + </div> + <?php if ($linkFooter) { ?> + <div class="box"> + <div id="nav-collapse-box1"> + <nav> + <?php print $linkFooter; ?> + </nav> + </div> + </div> + <?php } ?> + </div> + <div id="info-page" class="visible-desktop"> + <div class="contentWrapper container-fluid"> + <p class="pull-left"><?php print $copyright;?></p> + <p class="pull-right"><?php print $docUpdate;?></p> + </div> + </div> + </footer> + + <script src="js/bootstrap.min.js"></script> + <script src="js/main.js"></script> + <script src="../../js/movio.js"></script> + <script src="../../../mediaelement/mediaelement-and-player.js" type="text/javascript"></script> + <script src="../../../js/slick/slick.min.js"></script> + </body> +</html> \ No newline at end of file diff --git a/src/static/movio/templates/Movio/Template.php b/src/static/movio/templates/Movio/Template.php new file mode 100644 index 0000000..0c8fe96 --- /dev/null +++ b/src/static/movio/templates/Movio/Template.php @@ -0,0 +1,211 @@ +<?php +class Template extends GlizyObject +{ + function render($application, $view, $templateData) + { + $templateProxy = org_glizy_ObjectFactory::createObject('org.glizycms.template.models.proxy.TemplateProxy'); + // $templateProxy->invalidateCache(); + $cache = $templateProxy->getTemplateCache(); + + $cssFileName = __Paths::get('CACHE').md5($this->getClassName().'_'.$templateData->__id).'.css'; + $self = $this; + $templateData = $cache->get($cssFileName, array(), function() use ($self, $templateData, $view, $cssFileName) { + $self->updateTemplateData($templateData); + $self->compileCss($templateData, $cssFileName); + return $templateData; + }); + + $view->addOutputCode($templateData->css, 'css'); + $this->renderTemplateHeader($view, $templateData); + + if (!in_array($view->getAttribute('templateFileName'), array('1col.php', '2cols.php', '3cols.php', 'cover.php'))) { + $view->setAttribute('templateFileName', '2cols.php'); + } + } + + public function compileCss(&$templateData, $cssFileName) + { + glz_importLib('lessphp/lessc.inc.php'); + $less = new lessc; + $less->setImportDir(array(__DIR__.'/less/')); + $css = file_get_contents(__DIR__.'/less/styles.less'); + $css = $this->applyCssVariables($templateData, $less, $css); + $css = $this->applyFont($templateData, $less, $css); + $css = $less->compile($css); + + $css = str_replace( array('../img/', '../font/'), + array('../static/movio/templates/Movio/img/', '../static/movio/templates/Movio/font/'), + $css); + $css .= PHP_EOL.$templateData->customCss; + file_put_contents($cssFileName, $css); + $templateData->css = '<link rel="stylesheet" href="'.$cssFileName.'" type="text/css" media="screen" />'; + } + + public function updateTemplateData(&$templateData) + { + $elements = explode(',', 'c-body-background,c-text,c-text-heading,c-color-link,c-metanavigation-background,c-metanavigation-link,c-metanavigation-background-hover,c-slider-background,c-slider-text,c-sidebar-background,c-sidebar-background-hover,c-sidebar-link,c-sidebar-link-hover,c-box-border,c-box-background,c-box-header-background,c-box-header-link,c-box-text,c-box-image-border,c-icon-in-box,c-icon-in-box-background,c-color-border-button,c-color-background-button,c-color-arrow-button-slider,c-color-arrow-button-slider-hover,c-timeline-theme,c-footer-background,c-footer-border,c-footer-text,c-storyteller-background,c-storyteller-border,c-storyteller-item-background,c-storyteller-navigation-link,c-form-border,c-form-required,c-form-button-primary,c-form-button-gradient-1,c-form-button-primary-text,c-form-input-text,c-form-input-background,c-svg-path-stroke,c-svg-node-border,c-svg-main-node-background,c-svg-text-link,c-svg-text-node,c-svg-text-main-node,c-svg-node-background'); + $colors = explode(',', '#FFFFFF,#000000,#2F2F2F,#CC3522,#CC3522,#FFFFFF,#B82013,#CC3522,#FFFFFF,#F5F5F5,#CC3522,#000000,#FFFFFF,#C6C6C6,#FAFAFA,#F3F3F3,#000000,#000000,#C6C6C6,#FFFFFF,#A1A1A1,#D6D6D6,#FFFFFF,#A1A1A1,#CB3521,#CC3522,#363636,#5E5E5E,#FFFFFF,#E4E4E4,#D8D8D8,#F9F9F9,#7A7A7A,#E9E9E9,#E9E9E9,#B82013,#CACACA,#FFFFFF,#5D5D5D,#F9F9F9,#000000,#CFCED3,#D3D3D3,#CC3522,#000000,#000000,#FFFFFF'); + $numElements = count($elements); + + for ($i=0; $i<$numElements; $i++) { + if (!property_exists($templateData, $elements[$i])) { + $templateData->{$elements[$i]} = $colors[$i]; + } + } + } + + private function applyCssVariables(&$templateData, $less, $css) + { + $variables = array(); + foreach ($templateData as $k=>$v) { + if (strpos($k, 'c-')===0) { + if (strlen($v)!=7) { + $v = '#000000'; + } + $variables[$k] = $v; + } + } + $less->setVariables($variables); + + $css .= <<<EOD +@text: @c-text; +@text-heading: @c-text-heading; +@body-background: @c-body-background; +@color-link: @c-color-link; +@color-link-hover: darken(@c-color-link, 5); +@breadkcrumbs-link: @color-link-hover; +@breadkcrumbs-link-hover: @color-link-hover; + +@metanavigation-background: @c-metanavigation-background; +@metanavigation-background-hover: @c-metanavigation-background-hover; +@metanavigation-link: @c-metanavigation-link; +@metanavigation-link-hover: @c-metanavigation-link; + +@slider-background: @c-slider-background; +@slider-text: @c-slider-text; +@slider-read-more-background: darken(@c-slider-background, 5);; +@slider-bullet-background: @c-slider-text; +@slider-bullet-background-selected: darken(@c-slider-background, 5);; + +@sidebar-background: @c-sidebar-background; +@sidebar-background-hover: @c-sidebar-background-hover; +@sidebar-border: @c-box-border; +@sidebar-link: @c-sidebar-link; +@sidebar-link-hover: @c-sidebar-link-hover; +@sidebar-arrow: darken(@c-sidebar-link-hover, 37); +@sidebar-arrow-hover: @c-sidebar-link-hover; + +@sidebar-sub-background: lighten(@c-sidebar-background, 2); +@sidebar-sub-background-hover: @c-sidebar-background-hover; +@sidebar-sub-border: @c-box-border; +@sidebar-sub-link: @c-sidebar-link; +@sidebar-sub-link-hover: @c-sidebar-link-hover; +@sidebar-box-background: lighten(@c-sidebar-background, 2); + +@inner-nav-link: @text-heading; +@inner-nav-link-hover: @color-link; + +@box-border: @c-box-border; +@box-background: @c-box-background; +@box-header-background: @c-box-header-background; +@box-header-link: @c-box-header-link; +@box-image-border: @c-box-image-border; +@box-text: @c-box-text; +@box-relation-item-border: lighten(@c-box-image-border, 6); +@box-relation-item-background: @body-background; +@box-relation-item-link: @c-text; +@box-relation-item-link-hover: @c-color-link; + +@icon-in-page: lighten(@c-text, 70); +@icon-in-box: @c-icon-in-box; +@icon-in-box-background: @c-icon-in-box-background; + +@color-border-button: @c-color-border-button; +@color-background-button: @c-color-background-button; +@color-arrow-button-slider: @c-color-arrow-button-slider; +@color-arrow-button-slider-hover: @c-color-arrow-button-slider-hover; + +@timeline-theme: @c-timeline-theme; + +@footer-background: @c-footer-background; +@footer-border: @c-footer-border; +@footer-text: @c-footer-text; +@footer-text2: darken(@footer-text, 28); + +@storyteller-background: @c-storyteller-background; +@storyteller-icon: lighten(@c-text, 70); +@storyteller-grandient-1: lighten(@c-storyteller-background, 3); +@storyteller-grandient-2: lighten(@c-storyteller-background, 10); +@storyteller-border: @c-storyteller-border; +@storyteller-item-background: @c-storyteller-item-background; +@storyteller-comments-background: @c-storyteller-item-background; +@storyteller-link: @c-color-link; +@storyteller-navigation-link: @c-storyteller-navigation-link; +@storyteller-image-border: @c-box-image-border; +@storyteller-shadow: darken(@storyteller-background, 25); + +@form-border: @c-form-border; +@form-required: @c-form-required; +@form-button-primary: @c-form-button-primary; +@form-buttonPrimary-gradient-2:darken(@c-form-button-primary, 4); +@form-buttonPrimary-gradient-1:lighten(@c-form-button-primary, 24); +@form-button-gradient-1:@c-form-button-gradient-1; +@form-button-gradient-2:darken(@c-form-button-gradient-1, 15);; +@form-buttonPrimary-text:@c-form-button-primary-text; +@form-input-text:@c-form-input-text; +@form-input-background:@c-form-input-background; + +@svg-path-stroke:@c-svg-path-stroke; +@svg-main-node-background:@c-svg-main-node-background; +@svg-node-border:@c-svg-node-border; +@svg-text-link:@c-svg-text-link; +@svg-text-node:@c-svg-text-node; +@svg-text-main-node:@c-svg-text-main-node; +@svg-node-background:@c-svg-node-background; + +EOD; + + return $css; + } + + + private function applyFont(&$templateData, $less, $css) + { + $font1 = $templateData->font1 == 'default' ? 'Titillium Web' : $templateData->font1; + $font2 = $templateData->font2 == 'default' ? 'Open Sans' : $templateData->font2; + + $fonts = '@import url(http://fonts.googleapis.com/css?family='.str_replace(' ', '+', $font1).':300,600);'.PHP_EOL. + '@font-1: \''.$font1.'\', sans-serif;'.PHP_EOL. + '@import url(http://fonts.googleapis.com/css?family='.str_replace(' ', '+', $font2).':400,700,600);'.PHP_EOL. + '@font-2: \''.$font2.'\', sans-serif;'.PHP_EOL; + return $css.PHP_EOL.$fonts; + } + + private function renderTemplateHeader($view, $templateData) + { + $siteProp = unserialize(org_glizy_Registry::get(__Config::get('REGISTRY_SITE_PROP').$view->_application->getLanguage(), '')); + $view->addOutputCode($siteProp['title'], 'title1'); + $view->addOutputCode($siteProp['subtitle'], 'title2'); + + /* + $view->addOutputCode(str_replace('../getImage.php', 'getImage.php', $templateData->title1), 'title1'); + $view->addOutputCode(str_replace('../getImage.php', 'getImage.php', $templateData->title2), 'title2'); + */ + $view->addOutputCode(str_replace('../getImage.php', 'getImage.php', $templateData->title3), 'title3'); + $view->addOutputCode(str_replace('../getImage.php', 'getImage.php', $templateData->title4), 'title4'); + $templateData->footerLogo = @json_decode($templateData->footerLogo); + if ($templateData->footerLogo && $templateData->footerLogo->id) { + $image = org_glizy_helpers_Media::getImageById($templateData->footerLogo->id); + if ($templateData->footerLogoLink) { + $image = __Link::formatLink($templateData->footerLogoLink, $templateData->footerLogoTitle, $image); + } + $view->addOutputCode($image, 'logoFooter'); + } + + $view->addOutputCode(org_glizy_helpers_CSS::CSScode($templateData->customCss), 'head'); + } + + public static function homeSliderImage($item) { + return 'background:url('.$item->image['src'].') no-repeat 270px 0;'; + } +} \ No newline at end of file diff --git a/src/static/movio/templates/Movio/Template.xml b/src/static/movio/templates/Movio/Template.xml new file mode 100644 index 0000000..51c7e84 --- /dev/null +++ b/src/static/movio/templates/Movio/Template.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:EmptyComponent + xmlns:m="movio.views.components.*"> + <m:BoxesSidebar id="template:boxesSidebar" editableRegion="leftSidebarAfter" /> + <m:BoxesSidebar id="template:boxesSidebar-right" editableRegion="afterContent" /> + + <glz:ConfigValue key="movio.thumb.entityList.width" action="set" value="86" /> + <glz:ConfigValue key="movio.thumb.entityList.height" action="set" value="86" /> + <glz:ConfigValue key="movio.thumb.entityList.crop" action="set" value="true" /> + <glz:ConfigValue key="movio.thumb.homeSlider.width" action="set" value="600" /> + <glz:ConfigValue key="movio.thumb.homeSlider.height" action="set" value="290" /> + <glz:ConfigValue key="movio.thumb.homeSlider.crop" action="set" value="true" /> + +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Movio/TemplateAdmin.xml b/src/static/movio/templates/Movio/TemplateAdmin.xml new file mode 100644 index 0000000..a51f441 --- /dev/null +++ b/src/static/movio/templates/Movio/TemplateAdmin.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:EmptyComponent + xmlns:m="movio.views.components.*"> + <glz:List id="templateFileName" label="{i18n:Layout}"> + <glz:ListItem key="default" value="{i18n:Default}" /> + <glz:ListItem key="1col.php" value="{i18n:Full page}" /> + <glz:ListItem key="2cols.php" value="{i18n:Two columns}" /> + <glz:ListItem key="3cols.php" value="{i18n:Three columns}" /> + </glz:List> + + <m:BoxesSidebar id="boxesSidebar" label="{i18n:Boxes left}" /> + <m:BoxesSidebar id="boxesSidebar-right" label="{i18n:Boxes right (3 cols)}" /> +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Movio/TemplateAdminGlobal.xml b/src/static/movio/templates/Movio/TemplateAdminGlobal.xml new file mode 100644 index 0000000..1c27206 --- /dev/null +++ b/src/static/movio/templates/Movio/TemplateAdminGlobal.xml @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:EmptyComponent + xmlns:m="movio.views.components.*"> + + <!-- + <glz:Input id="title1" label="{i18n:Title}" /> + <glz:Input id="title2" label="{i18n:Subtitle}" /> + --> + <glz:LongText id="title3" label="{i18n:Left title}" adm:htmlEditor="true" /> + <glz:LongText id="title4" label="{i18n:Right title}" adm:htmlEditor="true" /> + + <glz:List id="font1" label="{i18n:Font primary}"> + <glz:ListItem key="default" value="{i18n:Default}" /> + <glz:ListItem key="Titillium Web" value="{i18n:Titillium Web}" /> + <glz:ListItem key="Open Sans" value="{i18n:Open Sans}" /> + <glz:ListItem key="Jacques Francois" value="{i18n:Jacques Francois}" /> + <glz:ListItem key="Cinzel" value="{i18n:Cinzel}" /> + <glz:ListItem key="Scada" value="{i18n:Scada}" /> + <glz:ListItem key="Quattrocento Sans" value="{i18n:Quattrocento Sans}" /> + </glz:List> + + <glz:List id="font2" label="{i18n:Font secondary}"> + <glz:ListItem key="default" value="{i18n:Default}" /> + <glz:ListItem key="Titillium Web" value="{i18n:Titillium Web}" /> + <glz:ListItem key="Open Sans" value="{i18n:Open Sans}" /> + <glz:ListItem key="Jacques Francois" value="{i18n:Jacques Francois}" /> + <glz:ListItem key="Cinzel" value="{i18n:Cinzel}" /> + <glz:ListItem key="Scada" value="{i18n:Scada}" /> + <glz:ListItem key="Quattrocento Sans" value="{i18n:Quattrocento Sans}" /> + </glz:List> + + <glz:Fieldset label="{i18n:Colors}"> + <glz:List label="{i18n:Preset}" data="type=valuesPreset;elements=c-body-background,c-text,c-text-heading,c-color-link,c-metanavigation-background,c-metanavigation-link,c-metanavigation-background-hover,c-slider-background,c-slider-text,c-sidebar-background,c-sidebar-background-hover,c-sidebar-link,c-sidebar-link-hover,c-box-border,c-box-background,c-box-header-background,c-box-header-link,c-box-text,c-box-image-border,c-icon-in-box,c-icon-in-box-background,c-color-border-button,c-color-background-button,c-color-arrow-button-slider,c-color-arrow-button-slider-hover,c-timeline-theme,c-footer-background,c-footer-border,c-footer-text,c-storyteller-background,c-storyteller-border,c-storyteller-item-background,c-storyteller-navigation-link,c-form-border,c-form-required,c-form-button-primary,c-form-button-gradient-1,c-form-button-primary-text,c-form-input-text,c-form-input-background,c-svg-path-stroke,c-svg-node-border,c-svg-main-node-background,c-svg-text-link,c-svg-text-node,c-svg-text-main-node,c-svg-node-background"> + <glz:ListItem value="-" key="" /> + <glz:ListItem value="{i18n:Preset 1}" key="0" options="#FFFFFF,#000000,#2F2F2F,#CC3522,#CC3522,#FFFFFF,#B82013,#CC3522,#FFFFFF,#F5F5F5,#CC3522,#000000,#FFFFFF,#C6C6C6,#FAFAFA,#F3F3F3,#000000,#000000,#C6C6C6,#FFFFFF,#A1A1A1,#D6D6D6,#FFFFFF,#A1A1A1,#CB3521,#CC3522,#363636,#5E5E5E,#FFFFFF,#E4E4E4,#D8D8D8,#F9F9F9,#7A7A7A,#E9E9E9,#E9E9E9,#B82013,#CACACA,#FFFFFF,#5D5D5D,#F9F9F9,#000000,#CFCED3,#D3D3D3,#CC3522,#000000,#000000,#FFFFFF" /> + </glz:List> + + <glz:Fieldset label="{i18n:General}"> + <glz:Input id="c-body-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-text-heading" label="{i18n:Heading}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-link" label="{i18n:Link}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-image-border" label="{i18n:Image border}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Top bar}"> + <glz:Input id="c-metanavigation-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-metanavigation-link" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-metanavigation-background-hover" label="{i18n:Hover/Selected}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Slider Home}"> + <glz:Input id="c-slider-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-slider-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Navigation}"> + <glz:Input id="c-sidebar-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-sidebar-background-hover" label="{i18n:Background Hover/Selected}" data="type=colorPicker" required="true" /> + <glz:Input id="c-sidebar-link" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-sidebar-link-hover" label="{i18n:Text Hover/Selected}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Box}"> + <glz:Input id="c-box-border" label="{i18n:Border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-header-background" label="{i18n:Background Header}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-header-link" label="{i18n:Title}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-icon-in-box" label="{i18n:Icon}" data="type=colorPicker" required="true" /> + <glz:Input id="c-icon-in-box-background" label="{i18n:Icon background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-border-button" label="{i18n:Collapsible button border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-background-button" label="{i18n:Collapsible button background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-arrow-button-slider" label="{i18n:Collapsible button icon}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-arrow-button-slider-hover" label="{i18n:Collapsible button icon hover}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Forms}"> + <glz:Input id="c-form-border" label="{i18n:Border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-required" label="{i18n:Border required}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-input-text" label="{i18n:Field text color}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-input-background" label="{i18n:Field background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-button-primary" label="{i18n:Primary button}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-button-gradient-1" label="{i18n:Secondary button}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-button-primary-text" label="{i18n:Button text}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Tools}"> + <glz:Input id="c-timeline-theme" label="{i18n:Timeline theme}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-background" label="{i18n:Storyteller background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-item-background" label="{i18n:Storyteller background items}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-border" label="{i18n:Storyteller border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-navigation-link" label="{i18n:Storyteller link}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Graph}"> + <glz:Input id="c-svg-path-stroke" label="{i18n:Path color}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-node-border" label="{i18n:node border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-main-node-background" label="{i18n:Main node}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-text-link" label="{i18n:Link}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-text-node" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-text-main-node" label="{i18n:Text main node}" data="type=colorPicker" required="true" /> + <glz:Input id="c-svg-node-background" label="{i18n:Node background}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Footer}"> + <glz:Input id="c-footer-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-footer-border" label="{i18n:Border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-footer-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + </glz:Fieldset> + + + <glz:Fieldset label="{i18n:Footer logo}"> + <glz:Image id="footerLogo" label="{i18n:Additional logo}" /> + <glz:Input id="footerLogoLink" label="{i18n:Logo link}" /> + <glz:Input id="footerLogoTitle" label="{i18n:Logo title}" /> + </glz:Fieldset> + + <glz:Input id="customCss" label="{i18n:Custom css}" size="90" type="multiline" rows="10" cols="70" /> +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Movio/cover.php b/src/static/movio/templates/Movio/cover.php new file mode 100644 index 0000000..2f9b45f --- /dev/null +++ b/src/static/movio/templates/Movio/cover.php @@ -0,0 +1,63 @@ +<!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><?php print $docTitle?></title> + <meta name="description" content=""> + <meta name="viewport" content="width=device-width"> + + <?php print $css?> + + <!-- JQUERY LIB --> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> + <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.8.2.min.js"><\/script>')</script> + <!-- JQUERY LIB --> + + <script src="js/vendor/modernizr-2.6.2.min.js"></script> + + <!-- FLEXSLIDER --> + <link rel="stylesheet" href="css/flexslider.css" type="text/css" media="screen" /> + <script defer src="js/jquery.flexslider.js"></script> + <!-- FLEXSLIDER --> + + <!-- fancybox --> + <link rel="stylesheet" type="text/css" href="fancybox/jquery.fancybox-1.3.4.css" media="screen" /> + <script type="text/javascript" src="fancybox/jquery.mousewheel-3.0.4.pack.js"></script> + <script type="text/javascript" src="fancybox/jquery.fancybox-1.3.4.pack.js"></script> + <!-- fancybox --> + + <link rel="stylesheet" type="text/css" href="../../../mediaelement/mediaelementplayer.css" charset="utf-8"> + <?php print $head?> + + </head> + <body class="page"> + <!--[if lt IE 7]> + <p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> or <a href="http://www.google.com/chromeframe/?redirect=true">activate Google Chrome Frame</a> to improve your experience.</p> + <![endif]--> + + <!-- outer --> + <div id="outer"> + + <div class="contentWrapper clearfix container-fluid"> + <article class="main-content col-md-12"> + + <div class="content-box row-fluid "> + <?php print $content; ?> + </div> + </article> + </div> + <!-- content --> + + </div> + <!-- outer --> + + <script src="js/plugins.js"></script> + <script src="js/bootstrap.min.js"></script> + <script src="js/main.js"></script> + <script src="../../../mediaelement/mediaelement-and-player.js" type="text/javascript"></script> + </body> +</html> diff --git a/src/static/movio/templates/Movio/font/font-awesome/FontAwesome.otf b/src/static/movio/templates/Movio/font/font-awesome/FontAwesome.otf new file mode 100644 index 0000000000000000000000000000000000000000..70125459f7d593b79cabc75bd60b91943aa65e93 GIT binary patch literal 61896 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.eot b/src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.eot new file mode 100755 index 0000000000000000000000000000000000000000..0662cb96bfb78cb2603df4bc9995314bd6806312 GIT binary patch literal 37405 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.svg b/src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.svg new file mode 100755 index 0000000..2edb4ec --- /dev/null +++ b/src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.svg @@ -0,0 +1,399 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata></metadata> +<defs> +<font id="fontawesomeregular" horiz-adv-x="1536" > +<font-face units-per-em="1792" ascent="1536" descent="-256" /> +<missing-glyph horiz-adv-x="448" /> +<glyph unicode=" " horiz-adv-x="448" /> +<glyph unicode="&#x09;" horiz-adv-x="448" /> +<glyph unicode="&#xa0;" horiz-adv-x="448" /> +<glyph unicode="&#xa8;" horiz-adv-x="1792" /> +<glyph unicode="&#xa9;" horiz-adv-x="1792" /> +<glyph unicode="&#xae;" horiz-adv-x="1792" /> +<glyph unicode="&#xb4;" horiz-adv-x="1792" /> +<glyph unicode="&#xc6;" horiz-adv-x="1792" /> +<glyph unicode="&#x2000;" horiz-adv-x="768" /> +<glyph unicode="&#x2001;" /> +<glyph unicode="&#x2002;" horiz-adv-x="768" /> +<glyph unicode="&#x2003;" /> +<glyph unicode="&#x2004;" horiz-adv-x="512" /> +<glyph unicode="&#x2005;" horiz-adv-x="384" /> +<glyph unicode="&#x2006;" horiz-adv-x="256" /> +<glyph unicode="&#x2007;" horiz-adv-x="256" /> +<glyph unicode="&#x2008;" horiz-adv-x="192" /> +<glyph unicode="&#x2009;" horiz-adv-x="307" /> +<glyph unicode="&#x200a;" horiz-adv-x="85" /> +<glyph unicode="&#x202f;" horiz-adv-x="307" /> +<glyph unicode="&#x205f;" horiz-adv-x="384" /> +<glyph unicode="&#x2122;" horiz-adv-x="1792" /> +<glyph unicode="&#x221e;" horiz-adv-x="1792" /> +<glyph unicode="&#x2260;" horiz-adv-x="1792" /> +<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" /> +<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" /> +<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" /> +<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" /> +<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" /> +<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" /> +<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" /> +<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" /> +<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" /> +<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " /> +<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" /> +<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" /> +<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" /> +<glyph unicode="&#xf016;" horiz-adv-x="1280" d="M128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280zM768 896h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376zM1280 864v-896q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h640q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88z " /> +<glyph unicode="&#xf017;" d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" /> +<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136 q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" /> +<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273 t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01b;" d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198 t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" /> +<glyph unicode="&#xf01d;" d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q14 0 25 -9 l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" /> +<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" /> +<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" /> +<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" /> +<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" /> +<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" /> +<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" /> +<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" /> +<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" /> +<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" /> +<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" /> +<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" /> +<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" /> +<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q73 -1 153.5 -2t119 -1.5t52.5 -0.5l29 2q-32 95 -92 241q-53 132 -92 211zM21 -128h-21l2 79q22 7 80 18q89 16 110 31q20 16 48 68l237 616l280 724h75h53l11 -21l205 -480q103 -242 124 -297q39 -102 96 -235q26 -58 65 -164q24 -67 65 -149 q22 -49 35 -57q22 -19 69 -23q47 -6 103 -27q6 -39 6 -57q0 -14 -1 -26q-80 0 -192 8q-93 8 -189 8q-79 0 -135 -2l-200 -11l-58 -2q0 45 4 78l131 28q56 13 68 23q12 12 12 27t-6 32l-47 114l-92 228l-450 2q-29 -65 -104 -274q-23 -64 -23 -84q0 -31 17 -43 q26 -21 103 -32q3 0 13.5 -2t30 -5t40.5 -6q1 -28 1 -58q0 -17 -2 -27q-66 0 -349 20l-48 -8q-81 -14 -167 -14z" /> +<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q76 -32 140 -32q131 0 216 41t122 113q38 70 38 181q0 114 -41 180q-58 94 -141 126q-80 32 -247 32q-74 0 -101 -10v-144l-1 -173l3 -270q0 -15 12 -44zM541 761q43 -7 109 -7q175 0 264 65t89 224q0 112 -85 187q-84 75 -255 75q-52 0 -130 -13q0 -44 2 -77 q7 -122 6 -279l-1 -98q0 -43 1 -77zM0 -128l2 94q45 9 68 12q77 12 123 31q17 27 21 51q9 66 9 194l-2 497q-5 256 -9 404q-1 87 -11 109q-1 4 -12 12q-18 12 -69 15q-30 2 -114 13l-4 83l260 6l380 13l45 1q5 0 14 0.5t14 0.5q1 0 21.5 -0.5t40.5 -0.5h74q88 0 191 -27 q43 -13 96 -39q57 -29 102 -76q44 -47 65 -104t21 -122q0 -70 -32 -128t-95 -105q-26 -20 -150 -77q177 -41 267 -146q92 -106 92 -236q0 -76 -29 -161q-21 -62 -71 -117q-66 -72 -140 -108q-73 -36 -203 -60q-82 -15 -198 -11l-197 4q-84 2 -298 -11q-33 -3 -272 -11z" /> +<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q4 1 77 20q76 19 116 39q29 37 41 101l27 139l56 268l12 64q8 44 17 84.5t16 67t12.5 46.5t9 30.5t3.5 11.5l29 157l16 63l22 135l8 50v38q-41 22 -144 28q-28 2 -38 4l19 103l317 -14q39 -2 73 -2q66 0 214 9q33 2 68 4.5t36 2.5q-2 -19 -6 -38 q-7 -29 -13 -51q-55 -19 -109 -31q-64 -16 -101 -31q-12 -31 -24 -88q-9 -44 -13 -82q-44 -199 -66 -306l-61 -311l-38 -158l-43 -235l-12 -45q-2 -7 1 -27q64 -15 119 -21q36 -5 66 -10q-1 -29 -7 -58q-7 -31 -9 -41q-18 0 -23 -1q-24 -2 -42 -2q-9 0 -28 3q-19 4 -145 17 l-198 2q-41 1 -174 -11q-74 -7 -98 -9z" /> +<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l215 -1h293l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -42.5 2t-103.5 -1t-111 -1 q-34 0 -67 -5q-10 -97 -8 -136l1 -152v-332l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-88 0 -233 -14q-48 -4 -70 -4q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q8 192 6 433l-5 428q-1 62 -0.5 118.5t0.5 102.5t-2 57t-6 15q-6 5 -14 6q-38 6 -148 6q-43 0 -100 -13.5t-73 -24.5q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1744 128q33 0 42 -18.5t-11 -44.5 l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80z" /> +<glyph unicode="&#xf035;" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l446 -1h318l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -58.5 2t-138.5 -1t-128 -1 q-94 0 -127 -5q-10 -97 -8 -136l1 -152v52l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-82 0 -233 -13q-45 -5 -70 -5q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q6 137 6 433l-5 44q0 265 -2 278q-2 11 -6 15q-6 5 -14 6q-38 6 -148 6q-50 0 -168.5 -14t-132.5 -24q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1505 113q26 -20 26 -49t-26 -49l-162 -126 q-26 -20 -44.5 -11t-18.5 42v80h-1024v-80q0 -33 -18.5 -42t-44.5 11l-162 126q-26 20 -26 49t26 49l162 126q26 20 44.5 11t18.5 -42v-80h1024v80q0 33 18.5 42t44.5 -11z" /> +<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03d;" horiz-adv-x="1792" d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5 q39 -17 39 -59z" /> +<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" /> +<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" /> +<glyph unicode="&#xf042;" d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" /> +<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" /> +<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" /> +<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" /> +<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" /> +<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" /> +<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" /> +<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" /> +<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" /> +<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" /> +<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" /> +<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" /> +<glyph unicode="&#xf053;" horiz-adv-x="1152" d="M742 -37l-652 651q-37 37 -37 90.5t37 90.5l652 651q37 37 90.5 37t90.5 -37l75 -75q37 -37 37 -90.5t-37 -90.5l-486 -486l486 -485q37 -38 37 -91t-37 -90l-75 -75q-37 -37 -90.5 -37t-90.5 37z" /> +<glyph unicode="&#xf054;" horiz-adv-x="1152" d="M1099 704q0 -52 -37 -91l-652 -651q-37 -37 -90 -37t-90 37l-76 75q-37 39 -37 91q0 53 37 90l486 486l-486 485q-37 39 -37 91q0 53 37 90l76 75q36 38 90 38t90 -38l652 -651q37 -37 37 -90z" /> +<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" /> +<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf059;" d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59 q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05a;" d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf05c;" d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23 l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05d;" d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198 t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05e;" d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61 t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" /> +<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" /> +<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" /> +<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" /> +<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" /> +<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" /> +<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" /> +<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" /> +<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" /> +<glyph unicode="&#xf06b;" d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5 t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" /> +<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" /> +<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" /> +<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " /> +<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" /> +<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9 q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" /> +<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" /> +<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" /> +<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf077;" horiz-adv-x="1664" d="M1611 320q0 -53 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-486 485l-486 -485q-36 -38 -90 -38t-90 38l-75 75q-38 36 -38 90q0 53 38 91l651 651q37 37 90 37q52 0 91 -37l650 -651q38 -38 38 -91z" /> +<glyph unicode="&#xf078;" horiz-adv-x="1664" d="M1611 832q0 -53 -37 -90l-651 -651q-38 -38 -91 -38q-54 0 -90 38l-651 651q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l486 -486l486 486q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" /> +<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " /> +<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf080;" horiz-adv-x="1920" d="M512 512v-384h-256v384h256zM896 1024v-896h-256v896h256zM1280 768v-640h-256v640h256zM1664 1152v-1024h-256v1024h256zM1792 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5z M1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf081;" d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4 q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5 t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf082;" d="M1307 618l23 219h-198v109q0 49 15.5 68.5t71.5 19.5h110v219h-175q-152 0 -218 -72t-66 -213v-131h-131v-219h131v-635h262v635h175zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960 q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" /> +<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" /> +<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" /> +<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" /> +<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" /> +<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" /> +<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" /> +<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" /> +<glyph unicode="&#xf08c;" d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5 q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" /> +<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf092;" d="M394 184q-8 -9 -20 3q-13 11 -4 19q8 9 20 -3q12 -11 4 -19zM352 245q9 -12 0 -19q-8 -6 -17 7t0 18q9 7 17 -6zM291 305q-5 -7 -13 -2q-10 5 -7 12q3 5 13 2q10 -5 7 -12zM322 271q-6 -7 -16 3q-9 11 -2 16q6 6 16 -3q9 -11 2 -16zM451 159q-4 -12 -19 -6q-17 4 -13 15 t19 7q16 -5 13 -16zM514 154q0 -11 -16 -11q-17 -2 -17 11q0 11 16 11q17 2 17 -11zM572 164q2 -10 -14 -14t-18 8t14 15q16 2 18 -9zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-224q-16 0 -24.5 1t-19.5 5t-16 14.5t-5 27.5v239q0 97 -52 142q57 6 102.5 18t94 39 t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103 q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -103t0.5 -68q0 -22 -11 -33.5t-22 -13t-33 -1.5 h-224q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92 t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" /> +<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" /> +<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" /> +<glyph unicode="&#xf096;" horiz-adv-x="1408" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" /> +<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf099;" horiz-adv-x="1664" d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41 q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" /> +<glyph unicode="&#xf09a;" horiz-adv-x="768" d="M511 980h257l-30 -284h-227v-824h-341v824h-170v284h170v171q0 182 86 275.5t283 93.5h227v-284h-142q-39 0 -62.5 -6.5t-34 -23.5t-13.5 -34.5t-3 -49.5v-142z" /> +<glyph unicode="&#xf09b;" d="M1536 640q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -39.5 7t-12.5 30v211q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5 q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23 q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -89t0.5 -54q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5 t316.5 -131.5t131.5 -316.5z" /> +<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" /> +<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" /> +<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" /> +<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" /> +<glyph unicode="&#xf0a2;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM183 128h1298q-164 181 -246.5 411.5t-82.5 484.5q0 256 -320 256t-320 -256q0 -254 -82.5 -484.5t-246.5 -411.5zM1664 128q0 -52 -38 -90t-90 -38 h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" /> +<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" /> +<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" /> +<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" /> +<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33 t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580 q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100 q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" /> +<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0ac;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11 q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 10.5t-9.5 10.5q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5 q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5 q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5 t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-5 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3 q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25 q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5 t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5 t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10t17 -20q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21 q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5 q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3 q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5 t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q7 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5 q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7 q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" /> +<glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" /> +<glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" /> +<glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf0b2;" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z " /> +<glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75 t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5 t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" /> +<glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15 t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207 q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" /> +<glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " /> +<glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" /> +<glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148 q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108 q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6 q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" /> +<glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" /> +<glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235 z" /> +<glyph unicode="&#xf0c7;" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0c8;" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf0c9;" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5 t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23 l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" /> +<glyph unicode="&#xf0cd;" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41 q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472 q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" /> +<glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192 q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192 q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113 z" /> +<glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" /> +<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" /> +<glyph unicode="&#xf0d4;" d="M678 -57q0 -38 -10 -71h-380q-95 0 -171.5 56.5t-103.5 147.5q24 45 69 77.5t100 49.5t107 24t107 7q32 0 49 -2q6 -4 30.5 -21t33 -23t31 -23t32 -25.5t27.5 -25.5t26.5 -29.5t21 -30.5t17.5 -34.5t9.5 -36t4.5 -40.5zM385 294q-234 -7 -385 -85v433q103 -118 273 -118 q32 0 70 5q-21 -61 -21 -86q0 -67 63 -149zM558 805q0 -100 -43.5 -160.5t-140.5 -60.5q-51 0 -97 26t-78 67.5t-56 93.5t-35.5 104t-11.5 99q0 96 51.5 165t144.5 69q66 0 119 -41t84 -104t47 -130t16 -128zM1536 896v-736q0 -119 -84.5 -203.5t-203.5 -84.5h-468 q39 73 39 157q0 66 -22 122.5t-55.5 93t-72 71t-72 59.5t-55.5 54.5t-22 59.5q0 36 23 68t56 61.5t65.5 64.5t55.5 93t23 131t-26.5 145.5t-75.5 118.5q-6 6 -14 11t-12.5 7.5t-10 9.5t-10.5 17h135l135 64h-437q-138 0 -244.5 -38.5t-182.5 -133.5q0 126 81 213t207 87h960 q119 0 203.5 -84.5t84.5 -203.5v-96h-256v256h-128v-256h-256v-128h256v-256h128v256h256z" /> +<glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M876 71q0 21 -4.5 40.5t-9.5 36t-17.5 34.5t-21 30.5t-26.5 29.5t-27.5 25.5t-32 25.5t-31 23t-33 23t-30.5 21q-17 2 -50 2q-54 0 -106 -7t-108 -25t-98 -46t-69 -75t-27 -107q0 -68 35.5 -121.5t93 -84t120.5 -45.5t127 -15q59 0 112.5 12.5t100.5 39t74.5 73.5 t27.5 110zM756 933q0 60 -16.5 127.5t-47 130.5t-84 104t-119.5 41q-93 0 -144 -69t-51 -165q0 -47 11.5 -99t35.5 -104t56 -93.5t78 -67.5t97 -26q97 0 140.5 60.5t43.5 160.5zM625 1408h437l-135 -79h-135q71 -45 110 -126t39 -169q0 -74 -23 -131.5t-56 -92.5t-66 -64.5 t-56 -61t-23 -67.5q0 -26 16.5 -51t43 -48t58.5 -48t64 -55.5t58.5 -66t43 -85t16.5 -106.5q0 -160 -140 -282q-152 -131 -420 -131q-59 0 -119.5 10t-122 33.5t-108.5 58t-77 89t-30 121.5q0 61 37 135q32 64 96 110.5t145 71t155 36t150 13.5q-64 83 -64 149q0 12 2 23.5 t5 19.5t8 21.5t7 21.5q-40 -5 -70 -5q-149 0 -255.5 98t-106.5 246q0 140 95 250.5t234 141.5q94 20 187 20zM1664 1152v-128h-256v-256h-128v256h-256v128h256v256h128v-256h256z" /> +<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf0da;" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" /> +<glyph unicode="&#xf0e1;" d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329 q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" /> +<glyph unicode="&#xf0e2;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" /> +<glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14 q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28 q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" /> +<glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5 t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29 q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" /> +<glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5 t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" /> +<glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5 t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129 q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" /> +<glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" /> +<glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68 z" /> +<glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69 q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47 q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5 t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" /> +<glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" /> +<glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" /> +<glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" /> +<glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68 t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252 t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" /> +<glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" /> +<glyph unicode="&#xf0f3;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1664 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5 q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" /> +<glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f6;" horiz-adv-x="1280" d="M1024 352v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1024 608v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280z M768 896h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376zM1280 864v-896q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h640q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5 t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320 v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152 q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96 q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q261 -58 287 -93z" /> +<glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" /> +<glyph unicode="&#xf0fd;" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf0fe;" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf100;" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" /> +<glyph unicode="&#xf101;" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf102;" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf103;" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf104;" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf105;" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf106;" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf107;" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf108;" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf109;" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" /> +<glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf10b;" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf10c;" d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103 t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" /> +<glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" /> +<glyph unicode="&#xf110;" horiz-adv-x="1568" d="M496 192q0 -60 -42.5 -102t-101.5 -42q-60 0 -102 42t-42 102t42 102t102 42q59 0 101.5 -42t42.5 -102zM928 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -66 -47 -113t-113 -47t-113 47t-47 113 t47 113t113 47t113 -47t47 -113zM1360 192q0 -46 -33 -79t-79 -33t-79 33t-33 79t33 79t79 33t79 -33t33 -79zM528 1088q0 -73 -51.5 -124.5t-124.5 -51.5t-124.5 51.5t-51.5 124.5t51.5 124.5t124.5 51.5t124.5 -51.5t51.5 -124.5zM992 1280q0 -80 -56 -136t-136 -56 t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1536 640q0 -40 -28 -68t-68 -28t-68 28t-28 68t28 68t68 28t68 -28t28 -68zM1328 1088q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5z" /> +<glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" /> +<glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" /> +<glyph unicode="&#xf114;" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf115;" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z " /> +<glyph unicode="&#xf116;" horiz-adv-x="1152" d="M896 608v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224h224q14 0 23 -9t9 -23zM1024 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 -28 t-28 -68v-704q0 -40 28 -68t68 -28h704q40 0 68 28t28 68zM1152 928v-704q0 -92 -65.5 -158t-158.5 -66h-704q-93 0 -158.5 66t-65.5 158v704q0 93 65.5 158.5t158.5 65.5h704q93 0 158.5 -65.5t65.5 -158.5z" /> +<glyph unicode="&#xf117;" horiz-adv-x="1152" d="M928 1152q93 0 158.5 -65.5t65.5 -158.5v-704q0 -92 -65.5 -158t-158.5 -66h-704q-93 0 -158.5 66t-65.5 158v704q0 93 65.5 158.5t158.5 65.5h704zM1024 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 -28t-28 -68v-704q0 -40 28 -68t68 -28h704q40 0 68 28t28 68z M864 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576z" /> +<glyph unicode="&#xf118;" d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5 t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf119;" d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204 t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf11a;" d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf11b;" horiz-adv-x="1920" d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150 t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" /> +<glyph unicode="&#xf11c;" horiz-adv-x="1920" d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16 h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16 h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96 q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896 h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="&#xf11d;" horiz-adv-x="1792" d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9 h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102 q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" /> +<glyph unicode="&#xf11e;" horiz-adv-x="1792" d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2 q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266 q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8 q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" /> +<glyph unicode="&#xf120;" horiz-adv-x="1664" d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9 t9 -23z" /> +<glyph unicode="&#xf121;" horiz-adv-x="1920" d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5 l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" /> +<glyph unicode="&#xf122;" horiz-adv-x="1792" d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1 q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" /> +<glyph unicode="&#xf123;" horiz-adv-x="1664" d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5 l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" /> +<glyph unicode="&#xf124;" horiz-adv-x="1408" d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" /> +<glyph unicode="&#xf125;" horiz-adv-x="1664" d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23 v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf126;" horiz-adv-x="1024" d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5 q-2 -287 -226 -414q-68 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497 q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" /> +<glyph unicode="&#xf127;" horiz-adv-x="1664" d="M439 265l-256 -256q-10 -9 -23 -9q-12 0 -23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320 q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18 l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9 t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" /> +<glyph unicode="&#xf128;" horiz-adv-x="1024" d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5 t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" /> +<glyph unicode="&#xf129;" horiz-adv-x="640" d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192 q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf12a;" horiz-adv-x="640" d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" /> +<glyph unicode="&#xf12b;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1534 846v-206h-514l-3 27 q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5t-65.5 -51.5t-30.5 -63h232v80 h126z" /> +<glyph unicode="&#xf12c;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1536 -50v-206h-514l-4 27 q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73h232v80h126z" /> +<glyph unicode="&#xf12d;" horiz-adv-x="1920" d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" /> +<glyph unicode="&#xf12e;" horiz-adv-x="1664" d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5 t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89 q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117 q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" /> +<glyph unicode="&#xf130;" horiz-adv-x="1152" d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5 t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" /> +<glyph unicode="&#xf131;" horiz-adv-x="1408" d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128 q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23 t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" /> +<glyph unicode="&#xf132;" horiz-adv-x="1280" d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150 t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf133;" horiz-adv-x="1664" d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf134;" horiz-adv-x="1408" d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800 q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113 q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" /> +<glyph unicode="&#xf135;" horiz-adv-x="1664" d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1 q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" /> +<glyph unicode="&#xf136;" horiz-adv-x="1792" d="M1708 881l-188 -881h-304l181 849q4 21 1 43q-4 20 -16 35q-10 14 -28 24q-18 9 -40 9h-197l-205 -960h-303l204 960h-304l-205 -960h-304l272 1280h1139q157 0 245 -118q86 -116 52 -281z" /> +<glyph unicode="&#xf137;" d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf138;" d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf139;" d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf13a;" d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf13b;" horiz-adv-x="1408" d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" /> +<glyph unicode="&#xf13c;" horiz-adv-x="1792" d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" /> +<glyph unicode="&#xf13d;" horiz-adv-x="1792" d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-13 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352 q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19 t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf13e;" horiz-adv-x="1152" d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181 v-320h736z" /> +<glyph unicode="&#xf140;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150 t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf141;" horiz-adv-x="1408" d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf142;" horiz-adv-x="384" d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf143;" d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 232 -177 396t-396 177q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128q13 0 23 10 t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf144;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56 q16 -8 32 -8q17 0 32 9z" /> +<glyph unicode="&#xf145;" horiz-adv-x="1792" d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136 t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" /> +<glyph unicode="&#xf146;" d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" /> +<glyph unicode="&#xf147;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5 t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf148;" horiz-adv-x="1024" d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" /> +<glyph unicode="&#xf149;" horiz-adv-x="1024" d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" /> +<glyph unicode="&#xf14a;" d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5 t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14b;" d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14c;" d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14d;" d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q10 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5 t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14e;" d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf150;" d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf151;" d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf152;" d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf153;" horiz-adv-x="1024" d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9 t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26 l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" /> +<glyph unicode="&#xf154;" horiz-adv-x="1024" d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7 q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" /> +<glyph unicode="&#xf155;" horiz-adv-x="1024" d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43 t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5 t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50 t53 -63.5t31.5 -76.5t13 -94z" /> +<glyph unicode="&#xf156;" horiz-adv-x="898" d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102 q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf157;" horiz-adv-x="1027" d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61 l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" /> +<glyph unicode="&#xf158;" horiz-adv-x="1664" d="M1664 352v-32q0 -132 -94 -226t-226 -94h-128q-132 0 -226 94t-94 226v480h-224q-2 -102 -14.5 -190.5t-30.5 -156t-48.5 -126.5t-57 -99.5t-67.5 -77.5t-69.5 -58.5t-74 -44t-69 -32t-65.5 -25.5q-4 -2 -32 -13q-8 -2 -12 -2q-22 0 -30 20l-71 178q-5 13 0 25t17 17 q7 3 20 7.5t18 6.5q31 12 46.5 18.5t44.5 20t45.5 26t42 32.5t40.5 42.5t34.5 53.5t30.5 68.5t22.5 83.5t17 103t6.5 123h-256q-14 0 -23 9t-9 23v160q0 14 9 23t23 9h1216q14 0 23 -9t9 -23v-160q0 -14 -9 -23t-23 -9h-224v-512q0 -26 19 -45t45 -19h128q26 0 45 19t19 45 v64q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1280 1376v-160q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v160q0 14 9 23t23 9h960q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf159;" horiz-adv-x="1792" d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23 t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28 q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf15a;" horiz-adv-x="1280" d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164 l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30 t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" /> +<glyph unicode="&#xf15b;" horiz-adv-x="1280" d="M1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544v-544q0 -40 28 -68t68 -28h544zM1277 896h-509v509q82 -15 132 -65l312 -312q50 -50 65 -132z" /> +<glyph unicode="&#xf15c;" horiz-adv-x="1280" d="M1024 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1024 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28 t-28 68v1344q0 40 28 68t68 28h544v-544q0 -40 28 -68t68 -28h544zM1277 896h-509v509q82 -15 132 -65l312 -312q50 -50 65 -132z" /> +<glyph unicode="&#xf15d;" horiz-adv-x="1664" d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23 v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162 l230 -662h70z" /> +<glyph unicode="&#xf15e;" horiz-adv-x="1664" d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150 v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248 v119h121z" /> +<glyph unicode="&#xf160;" horiz-adv-x="1792" d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832 q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf161;" horiz-adv-x="1792" d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192 q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf162;" d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23 zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5 t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" /> +<glyph unicode="&#xf163;" d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9 t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13 q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" /> +<glyph unicode="&#xf164;" horiz-adv-x="1664" d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76 q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5 t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" /> +<glyph unicode="&#xf165;" horiz-adv-x="1664" d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135 t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121 t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" /> +<glyph unicode="&#xf166;" d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 16 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15 q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38 q21 -28 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5 q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78l24 -69t23 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38q-51 0 -78 -38 q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf167;" d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73 q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51 q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99 q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-37 -51 -106 -51q-67 0 -105 51 q-28 38 -28 118v175q0 80 28 117q38 51 105 51q69 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" /> +<glyph unicode="&#xf168;" horiz-adv-x="1408" d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942 q25 45 64 45h241q22 0 31 -15z" /> +<glyph unicode="&#xf169;" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" /> +<glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" /> +<glyph unicode="&#xf16c;" horiz-adv-x="1408" d="M928 135v-151l-707 -1v151zM1169 481v-701l-1 -35v-1h-1132l-35 1h-1v736h121v-618h928v618h120zM241 393l704 -65l-13 -150l-705 65zM309 709l683 -183l-39 -146l-683 183zM472 1058l609 -360l-77 -130l-609 360zM832 1389l398 -585l-124 -85l-399 584zM1285 1536 l121 -697l-149 -26l-121 697z" /> +<glyph unicode="&#xf16d;" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139v1142q0 81 58 139 t139 58h1142q81 0 139 -58t58 -139z" /> +<glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" /> +<glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf171;" horiz-adv-x="1408" d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22 t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18 t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5 t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" /> +<glyph unicode="&#xf172;" d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5 t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf173;" horiz-adv-x="1024" d="M390 1408h219v-388h364v-241h-364v-394q0 -136 14 -172q13 -37 52 -60q50 -31 117 -31q117 0 232 76v-242q-102 -48 -178 -65q-77 -19 -173 -19q-105 0 -186 27q-78 25 -138 75q-58 51 -79 105q-22 54 -22 161v539h-170v217q91 30 155 84q64 55 103 132q39 78 54 196z " /> +<glyph unicode="&#xf174;" d="M1123 127v181q-88 -56 -174 -56q-51 0 -88 23q-29 17 -39 45q-11 30 -11 129v295h274v181h-274v291h-164q-11 -90 -40 -147t-78 -99q-48 -40 -116 -63v-163h127v-404q0 -78 17 -121q17 -42 59 -78q43 -37 104 -57q62 -20 140 -20q67 0 129 14q57 13 134 49zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf175;" horiz-adv-x="768" d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" /> +<glyph unicode="&#xf176;" horiz-adv-x="768" d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" /> +<glyph unicode="&#xf177;" horiz-adv-x="1792" d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf178;" horiz-adv-x="1792" d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" /> +<glyph unicode="&#xf179;" horiz-adv-x="1408" d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q112 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65 q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" /> +<glyph unicode="&#xf17a;" horiz-adv-x="1664" d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" /> +<glyph unicode="&#xf17b;" horiz-adv-x="1408" d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30 t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5 h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" /> +<glyph unicode="&#xf17c;" d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-7 -10 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7 q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15 q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5 t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19 q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63 q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18l-4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92 q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152 q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-14 -1 -7 -7l4 -2 q14 -4 18 -31q0 -3 8 2zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5t-30 -18.5 t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43q-19 4 -51 9.5 t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49t-14 -48 q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54q110 143 124 195 q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5t-40.5 -33.5t-61 -14 q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5t15.5 47.5q1 -31 8 -56.5 t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" /> +<glyph unicode="&#xf17d;" d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81 t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19 q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -6 6.5 -17.5t7.5 -16.5q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6 t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf17e;" d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5 t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5 q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80 q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" /> +<glyph unicode="&#xf180;" horiz-adv-x="1664" d="M1483 512l-587 -587q-52 -53 -127.5 -53t-128.5 53l-587 587q-53 53 -53 128t53 128l587 587q53 53 128 53t128 -53l265 -265l-398 -399l-188 188q-42 42 -99 42q-59 0 -100 -41l-120 -121q-42 -40 -42 -99q0 -58 42 -100l406 -408q30 -28 67 -37l6 -4h28q60 0 99 41 l619 619l2 -3q53 -53 53 -128t-53 -128zM1406 1138l120 -120q14 -15 14 -36t-14 -36l-730 -730q-17 -15 -37 -15v0q-4 0 -6 1q-18 2 -30 14l-407 408q-14 15 -14 36t14 35l121 120q13 15 35 15t36 -15l252 -252l574 575q15 15 36 15t36 -15z" /> +<glyph unicode="&#xf181;" d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408 q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf182;" horiz-adv-x="1280" d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43 q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" /> +<glyph unicode="&#xf183;" horiz-adv-x="1024" d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" /> +<glyph unicode="&#xf184;" d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf185;" horiz-adv-x="1792" d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4 l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94 q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" /> +<glyph unicode="&#xf186;" d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61 t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" /> +<glyph unicode="&#xf187;" horiz-adv-x="1792" d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536 q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf188;" horiz-adv-x="1664" d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207 q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19 t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" /> +<glyph unicode="&#xf189;" horiz-adv-x="1920" d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-78 -100 -90 -131q-17 -41 14 -81q17 -21 81 -82h1l1 -1l1 -1l2 -2q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58 t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6 q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q17 19 38 30q53 26 239 24 q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2 q39 5 64 -2.5t31 -16.5z" /> +<glyph unicode="&#xf18a;" horiz-adv-x="1792" d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12 q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422 q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178 q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" /> +<glyph unicode="&#xf18b;" horiz-adv-x="1920" d="M805 163q-122 -67 -261 -67q-141 0 -261 67q98 61 167 149t94 191q25 -103 94 -191t167 -149zM453 1176v-344q0 -179 -89.5 -326t-234.5 -217q-129 152 -129 351q0 200 129.5 352t323.5 184zM958 991q-128 -152 -128 -351q0 -201 128 -351q-145 70 -234.5 218t-89.5 328 v341q196 -33 324 -185zM1638 163q-122 -67 -261 -67q-141 0 -261 67q98 61 167 149t94 191q25 -103 94 -191t167 -149zM1286 1176v-344q0 -179 -91 -326t-237 -217v0q133 154 133 351q0 195 -133 351q129 151 328 185zM1920 640q0 -201 -129 -351q-145 70 -234.5 218 t-89.5 328v341q194 -32 323.5 -184t129.5 -352z" /> +<glyph unicode="&#xf18c;" horiz-adv-x="1792" /> +<glyph unicode="&#xf18d;" horiz-adv-x="1792" /> +<glyph unicode="&#xf18e;" horiz-adv-x="1792" /> +<glyph unicode="&#xf500;" horiz-adv-x="1792" /> +</font> +</defs></svg> \ No newline at end of file diff --git a/src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.ttf b/src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.ttf new file mode 100755 index 0000000000000000000000000000000000000000..d3659246915cacb0c9204271f1f9fc5f77049eac GIT binary patch literal 79076 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.woff b/src/static/movio/templates/Movio/font/font-awesome/fontawesome-webfont.woff new file mode 100755 index 0000000000000000000000000000000000000000..b9bd17e158d87fb1477f7ac3ddbb5a676f3c26d2 GIT binary patch literal 43572 zcmY(Jb8se4wD-d&+L#;LwzDxd*x0shZEV}NZQIrp+xA9pe($~i+^+gg_xbcWbE>9m zrn;t&tDKk^2q?&RD`y2k`0hYi5B|sgkNw{!CZ;6w?I7|^asQLCo&KD-h^W{%)BCmw zzC{Sy2m&Fe$iV!~{(js1-_nZ!^FT4Q*0=j+z271P0Rgi(Wvjh2)pz`6U^^fnAkhCS zBvUJQlW%qc0+L(<0*X55#~ku(W~^@n0+N>c?Zfmfb}+30VzY1f%_hI?|MHT;`$O%T zSv$FXvy1N>{U9I!jI|2{WGh?4Z@-M%?|VLifPf>}BQ>2_>$`pD%`W}lSVGWEFkBmb zYvXS=`W^dU{#ITv<8(V)M<)=FTt*NOm{$-Gq;BRZ$R1Z?gYWrr+V5Dve~MI)Z~gB7 z{}Y_#%b)okgG?y-f5(7;Ol|Sbxd9FJjP&$&zztvkNO}g}V<Ri@cv?Mta1dB5kam#& z=1sguIsN>S{DO)?hEo0f^5BJ7&{;(MUO5E?jpdmFzytbK0qntFzxZ*$3z%aKL=^IS zd!a$V6kt$5zT>Cjx}?D6k%EqGd=?2kN45tkCrk)_dHW;P)@dlLs$sQA;N3wGB^lqq zkQT8Eio`mpB=5nIsw2@JN+U0pw%KSQqgf61gF6O;ht#AJ<wFcLh*3KzEK!y{XDY4F zJ(Y=2)sGdiXZ;D8J{_NG#kun7yT@gKhGEA=+b!_N#x~o9#>?Er_TDh0ZRV_}7riYa zW;2(tlo%G-fVqAN5Z85s5CbJkM9z&SN0=L?qPGt~LPEh%WiKK%hAE_<f|=P!FJEKn zFd4B5O6%L)$rreY^3dj(smMIWHFZx*af`!r%RWx!>cgNRw|-FTIm7&@6#pkFa2B!_ z@Pgn=l~gQOT2I{2jk$;U4kc66uuzutbNpjf;xqgWu*d9V^Sv^lUtb`IZotki7%!#6 zB}Sha$Cfmnw+;39F(c+TBR^83W)St@+60I-2#CSZd}#Vy!tiy<&^>zUqGpT5@}dgu zixrF8ETDy|x3#6}$8&^r(}zw~Q?r03k>l(1{YKgtDQUj<*ELj{XO1`D%zdU~w&V06 zbW7I0TSp+G>`|-LDDoa2(FinJ<Aw`!r}hv0b$a^|&VPul<-RPXUz4br52dNcXLI}U zeaL4wt%VYlxN^qvL{NhZW%v@o++c)!K!whq4&81W9O)%;qv*CaVeB45oh?k%^r3oA zaS<hZFC&fz;mM&b(|V<b&IWk6%X9wtArn&lRisP8@pw8RoLd>=Mnnl0Hxe72bjLM3 zz7xD&GCg`S_MIH~JB}uvh9y|M{2O(RLzgz{9`xNPg-;AaYfGT-&p7e0c0v^5YB+bR zfHXM$l}oMIPmm65SrGnwdjnUKe8Ikbr+r4Zz|JQ>myjpWQ9CLI#6o8I%h45`4n-cH zhxp&o{?MREF**)xm0`%zAoba56D5GX+J9$tXeqc$(c7=Ul|~XKZk~;>&dD&`<NfwF z!RQDsQuWxXLP&8Clv_34T|0NXN|tE)`SE>R37eFaeR${wNpZxSDI-t9^H~at%iM(k z@Fc|HMql34N$o|1Ss!`&*W9NVwLeXvkP)!?M(nr~>WiM;_w}qanbyvrtr`ux>hlxZ zW0`5&tFE*wE%t^vYA5Sh2W@6MMc#CmEGCUD7oJo|bPgEG=-6QkCybQ&7Oxl612JJN zUQ8t{M;S!?F0F@GdHay*nz_a&j?!<*$M3ilJF(5M=2rURf89LYGXHQFzkg7f-qMpX z&n^{5J!tuk)tfo3k*z#On%SaVPxFj%3qMpkUZ=hRdo(bP^XE49l6||LzPjY!D|MbQ z?XSdIYY_^lF~pDQ$oEh|St}G6r-m1$LsZf2rM-aO6@8Zqn;JFC5vXV66-}O&Ji8w& zOZ1P<ZaoP-^ZN_<i<9+3+O|G#){b48_5A{Ridj4+T0gdJE#^(=+2_fGsGV`B9<Yf_ z`pXUt4chP&IfPe1@qq0G;!V!8by!cmNjKih)x~8QqFS?y;42m!4`w~{%f4T4oeDN4 zBO#6P&B#PJBi(+#36+uvNta0GZ?AJ{Xb2r#sIXd0{S7{Mk_tkqc_}*r(jYTBqP%Hr zH+=WU`3;|sAk%U+mtkuxXSzPQA1=D~mNjc6Y`2`R)E#j&=jmQnIG-yWU9FG43P*aT z?aAAVjWlZDEp7Ha+7?<HT7S2mxAL@wv@$qmrpgX!64EXOOt9b}Rm$x`iBnJKb~pae zGk717_AUQMPES5M;%#M`u}5TQuNzl@kDpVpp%$r@q&T5k!mXUv`a?huPO?8Ju|lNp zBY`V|zaMt_L=g*4fdA;ABEjrAC%?BOrmkJIITRB1M&Z$Ge$!(EdZ|AUnMag&2ELG$ zo{ce<_=4-`=w5LMDcYt0oGMrDE`fUHM6Nh|ch$i7ZDy=?)KAk^nd79&LHcIktJc@R zJMi3U5jH9-D=M~NhKXZL^)39hY@gp_+=2rlErEY$1>Mwsa!d}}V;n*`hzMGS8}qAY zreB;u8QD-w9V<qEq^)efeDmu_EeZ#gx1;)?a$cril?(CT&17tm9nLS_B{(-JtlK$| zd700>#*B}NcMi*tcb~JroNW>RUZ0ceD8Hs^lm319Tyh-PJQ%cL=D3MF!9uk`kBDls z$M(aJ%+~LhRoZ*K;-^?a%#BGc`&4|WFu?4cP%i;)6;6AGW)Y(vRi)-`e|q<X?yPaj z<?Ld72$qoL&rDfuB;U^MmO=4`<_5akE9&cjm1u}5!R6DDg!)HvjqDnJoR-}%F*_*8 zo_RIEN_tvYexXTdIOkYprdSHVSO{pmML=rMjCpseG(7nnBqvXMhtao?)5|cC5W@&s z$#5S|n(*qxkZRUF{s8X{V3>mq74YDbZ8tsVVI69C?kxO}fAf19NqOS+sy*}%&aHA^ zXg+Mg^?p5}n`p7NXokdTW+(7!O(j@m{_9KnWuERZ^Lyv(fg|@iKewsq)qf{mSEmg! z!LXW6_0vJ}#{USz@`m_Qy}odi-K?M8?43fzZm`bVFG9Ij6e>Pd_<7+;<|st*m8+yl z&$%AzKp@+*^ukW3oQdM#=2a)I4aRw(sNli)&>X4LHPT(=>}Lj|n4wnWrxGu18!sN3 zzn%9uCkcIK9CWq3<nUMHQmYm!Gi0Hge|~i6w&5R|*}h)LOu7(qdvsHzFH^oj$jd2W zi>O3U(TXZU!#^OqSF<!B2wg%5Yg5|_+Hs=cbyxH;YaSDg>>Z-jUs+4=pFd?<XxJ-G zfq_=FbPmhvUnxU29DLSQ)|nMp-mads$+uzGj6m9>^8(tsnc%RnkYzh)`hQt#!tZHn zBN`2IVVnA$vz8rg1J|`)3s+kvtlH`Fv?d9j-qs_L+<VQnja5}FDH&7YWF95;Ror#; zJm$4$Ve21*Q`6BX^c4f6RyOpm-O(XRGxct;J>d^EG`~)l@&A6mBogtW0CV&}G6kIl zb+PR|ta_F~b7RMF#MJ&Qf+<aF-kg2w<vk=cpt0y%HSv84XO%F{n;3Eqwn1)!j-IBJ zTxwA>WNb6{s~$R*dWjt-`1^`D6w(nMll~Yz3DNKyqnnf7VN!?6-L_Ga0P^o513Ave z$Lj%59=QXqq$=NKwhK3yFDab91kqm+wFyLm`cVoi&{9PotCu%>#r`j4$pU_yn0w`g zDG&W$S4?Vd5qX?{a2Ye`g7LxSM|}Y+fUmyf;R;wHK{^R!&G3_cXlRh0r9Go*6q2~H z%spSMzgQ`h&Vc&i<F_$a^X*2u?OZPqv9E9^Z!9~P+YPB?Ah!P>UOyUrV)j$f+G)5< z_QlmQds0MIN|VdCBM*;R0@D!MF%E>+yoK#iL!=*;uO2LutTe#nIo>FYTUy%(OMx52 zQ|E@J)BY|`AeKqRH4j<s?nM<+qdy-=-w#uY){MR7Xda%JjKFS^$desLubb4Tb3-UZ z{D5IYyVKu5VW8M$UW$%?!!9ys2EiP)ov?mhseXAt5$-|dSs_E$;87j;ZBbDxA2$+^ zOX9xj*BDxw>u>I?{cu9(gkC+V%hArjMOiEkKyEBfaR%IPG1q8l9QK&nVt`h12_1bY zXvr&q359!4Q)&ZeUr-;g1M3Q`q$t($v2P%_6i&q;6kZsAgp^$xj7D1?ocDsn2Xu9; z5FMgnGy0*}0(2a^HnaD5Pda8t;iFu1n}hCz_tQl#EjpGG#cba|i^G7jsH^r}Wn`*x zWnu2ODuJ6(_{cBb-|BMQKU(qf5af@k1v9(wudR58V_9ELWg7VT&Q08Y_U-=^4@h=2 z$<(Os+cg7_PW?sE)w<uO;=}w1*umOzb)@)27FX;_R#c{3<RHuKJt@{guUxc~4+d|g zzAXP6z8*JtnGZqBrxydKd_(+$3g{}$MqZ`Ig2fBjY<F`_fu73cc0*c9By7^~gjay< z;IcHdGh7bOBPotvh{p%xL~dTuJ#w0nH=UfDN+`X#9HmUBl#7`G&$T|o-&pqC-l*R^ z2G3Px!t#I}rO}5#;3c65695wqrgkzO@`r}>1t}&(brdH&N>Es3$<?stY*+3V=FN>% z-8s6K;EH-IiLm`P(?+Sqw){Ll|M72{>&1B7nwy(y6ABXrHxW3->4R&}c1c5PPA$!M zXV)dHwN~zNqC7WF9w+mlpST%R$z6=Nw9%`$E}o277KD9>+7AbHWU^IytffrxF=evK zH1971Dtt=7#L5fNFgJ!l5`7xMOu99}nKuNF+KKo-g3JkcVA&s`KzlTW47})I&8rXn zpRd4=af3A*HatfEUE)h|T`b|HD^TZkc<5c?l0&cCVUe9=a56O833XVeErU|!r%f3} zA&M7WpySxlxjnM-K8w5!ktSpyTu?!1ZKU;_g!>NDy1bz5I2_MVyF#C1d*4`)+WKwf zC+a~X9gqjAsmG>6M`rG{KdA&??d7rI`ODp}>}TIx{_^~%KBY?y+KYDtH`Eo>BVlXv z=HE3v5mKN)V~w`g)?>Mj2yYSoiKf#)QM6+hb<O+*mcs-nUoUaMPe7feMW%ngzLXCr z6e{EV1Jyg~>3`QVi0UK{6ig`!h++?DEP-)eUJ@2^SHpb6Nnx(OeYY+~C913Igw}B1 zubUInnT>)*e*M~Xn91eV-1}9W6KuJK%`I*3azzcK8C@wD4?8Z!#H5*|uq#3=JsvFo zs4QO9RgaTd73;!Mf_p6O7jmpdU+;!l$z5jEd=gx(<UV8Lfq_f<0>c2b3LCPx+Ubm< z^US@;P-cps!f2K=bqI(5TAm_;fbF`Q+ul>bnwXf4u6QoGoqc@gm$ufP|A21dN9`=C z8eaBsnrH$xMR=H75e!n#&)3x9P0q_%3knMe*!%o<CbO1RJqF8GO<YU34BHKi-1Rxl zvtmfMt}!F>=eHqn#973xOGqshe)z}ei<LhNB}kAil*4)x@3gCJ-4QDB2E;IR@UvCF z3ZG~$D}XiGl{uK*Ub|`=K=5qaw)Ur(U$6i|w)&inyO%B&A(|G*k=U7?e)@a$j4Q~~ zg`DN+&5l!A$CdsaECuY1W@gs?tq}oGHioOU`}`-<E?vQFR57Guqc;rv2=vvVfZ>6C z^(qV9h3GnOHGe^^^8Oq9_I`aNVajx_(i%Zn20@~k@pOK7^GyD@#I&gr4R@EKovcQL z(VXsIb+3DDyLRv&L*DGheWd7?(*vF#29?v=*VWcpD;g2k?Wt-bzc8OWY<Dy1j4stD zt=~AU`$?M6#;?p{w@e1t2RRFGkdU%m;&UO~$%e$QkTXBq)@hI0-SQWjj1I@is;5OZ zOzSoPISW2Ef{Zew@D7#_<(f8a)WC3AjMw`ZepvNOvMNr^$TyT~56z=FTmJOAr4AJ6 zkA|MSqQ>)OL+M2twLpz+k6K}<)s;7kx$`K4_{YpN<X5z#Q@%nNSCypuy|DGa6h1iF zj!sqWB<AS8MDL&l%9M980#3iEaLrqs29fOpH^x{`BynR$e7*1`8Khih31;SwVX9Lx z@7%Gg4%a$DzeL~X2(t^;#6YV96!@`!-(ka*c$xelr6qzd7Kq-2Po4=*c#GT7kn&EG zdEFliB`N#l@acMCz}i@yy#e`re9&5-ot^l^Ke-(0v0U38-r6d_;g~n->N5CTecW^Y zT8^2H@G0J==pK4H`A3Z}3PU0UYY_Qz_Y0I`<g=>(kZCGQqR4Q_iI*?df7gj$)(00= znzdecqR23v27^Q(>~MiG6I)^=B2DBcN0;1|N;!>pIZ%WTZS2<us<{^FE3yWtI|i;b zd@q9`D}4_BEA-{>x?jHFCjH~1F?;4+YrG|d(~e}#?&z-cEvQ5o<|s5p9d=x%imfjD zYxw=i_L=+?+>BCp<CVXQyy_2(M|kshVPYtmTp5h^3=6fAbh&%x3O+=;tfo(n`glIr z@L_JGNljV~vP^bF``_GM8$jv_MIf7GK){JqVvOw6lvF8qLt2BpYK_vwJt^96Cg<dq z(xj!P(BDhWSOBTy2`{%j&?YoL>la~doX|q%>JAH$h<F|6P7d4H)|00%Q8cQ8xyKI5 z75CQnqzd}blJnOGhE?WJki9$hf<xza?tV_z{mEYjN3q@LHhQ?*ytjU8hlJ<<RF)gW zD9xqQ$lF`Ib`&5=z6#G9zyWbR?JbUk^*Yn@J8rVeSizGb6|%7Q6wxfDi)=piX;GcT zq08De{QBXl@k8*XvYB1vBOm!=_)aG~<)LddlGPV;gzYo~X8$d4JU7)jQEiz!7=wyn zhOD;mg`?mB#5G6$9e$w$gQx~IzuZ`4L|csZEP4SchG-y4_;cWMc*C6MZ-J+*>AszO z37;b{Rur#zb&@fDcA(^vP;fkx^Mb&Fx9^g23~<8g7;4#%|A*<vV8QRvUMw(WebuCw zSr?yM9`Wc-$3TKS%7r>!?`YDcDf9j!j*79pSHpKBpA%>qDGUN2_xSwnOQ-vAe-Mie ze|AVX?f{l;T69jFW^}_KiKNh49MTxGmOw?n)i2^Ho~xd9G7@xDn04qb-%%3<YtmrU zi9#%Huw07JF_hP#V+;XavnoWFqKGD&y)@_G^}{c?#fK6ZhU{zE$p<ovbY2WOP0bRB ziRK(GCyir76BtjPDU&kmfMvz)Yv&h$yK6sup`2%dH`kY96%=%A1Hu(gbryNX1-oas z6;VxV(~jrby-jA5^HumyfO6~x45=zSz<_u`*eAjOfs_7&B<+47v!d^U9R}qZkrOSY zPb05lO}*HG$%bWQh&OV)Z;Dvfld{8jX=s5F+u!FRA71MZc9wK{2?g)lHei8hT`*2= z@M4t{lCpO!k|YwG`1EU?FdBS;Id=W6O|8>>dE8izwhTPG@xlAGqNL`ZmjzWEXt*!w zLRUZ)LZ5^PC>kSIf}b)NwB4iA9F<Ul<rwf@bDpI{&T{(kU-jpBJN)BSbT?Uqty<mv zt8&keHGdimy4HjF?x?<8hZW4GXR8Cz*Wi%m=V#60peNqiGGnKEF%nyqbBlj>Hyk@x z+WW{qOtMo|q%c5A8(z-Vf%I7odZrncCJT_7wpg596djb<Rdq06bvIg)0Fm5t515g* zNBa{<wsn$1&sSEwh{{kBF;KPmim!Wi;yS;)?AmEW(}7(i3`ExDjC1ZOK*<v6$~s?g z@%=|Q>}HtVc2^$cF9`K<69=Y-HA?AwrxDG`z!~EL&{(5AG|Nme<*uioVw@B$Pwvuk zn&b}j$u{$eg(w@h+~?xxR&nA3FPgqNr6rFTi{^D~6WIt~-;AdLsO@z64y$;|<rNOf zUv7Ouy|gJSLrfR@kQ-6BB_8$)o_#oX9?V^Z1Lq-t*waK}mk|)c$gH>`fL-YW?kuJs z|2cBA!VR7r#XMQ5<jrklG?xN!P3pv1kat&NpImQ&;rV1aFhi-vr%v3RZ-S-zt5vY; zLKO*4^P_&lsvv=k^vv=co*leS?J$U=B~TbPj~DGeQVivy5mJlT)>)gk_2jn6wZ#*< z)pYZW`3^vAASTE>$Y9g9Xk-6RS|N*fina^ap}pF9sy~ON(Mr8Zyt7(%PyuEY9ssfp ze(Gonsf@Gj;4!5ayb2*S*nk?+RAZUbS;8hyL*vqyD~)OYgchKD1I=$ZiqFwO64cX& z>EU8^15GU9Om6t*PPC+Y{I_^%L~`;u6!FUdOw}bS`KkCLlA$hWT{R8-HqkNmQ^Ija zVih$(2GrPD;^CyXX}wstmKY|4)n-^T9n1~Gqc}C-zGtz~zMM<#Hte+NkSkV1X!VEF z`;bN&=<TDzN=3*%NtCxmd|peap|CFqc8TAdLB8;{YI*SI>NZ7|-Px|w=N0D`OvljM z^~T|Z*2Xhvf>fLo3hPK3TEu8->-V<#D4|sW_czr}10(sO!xmNMR}8Q!LhSBUp(9O> z_BSLG!7G7T%f8{ik(LgR#)^@D+xVwn6xRGrZ-&jU!fyVkwq<xFH*x?D0u0~sZtxNf zELgrF;r<uHNfP3C@5l^l6Y6J)BGy(b=HruX8d?4M*|CN?p09*qrDNBHx5PyHOSmtY z(Og``3V9qRY$CHp4JG6cf?9m3N~)1H#Zeijn4(?r(ow+FRY{EEb7gx%!c(2oNbY@9 zDe1ItON?-1KqR>N5P7&bzYXTtZyybR`ec9lsTZd9(tDP)3kUEF0T-9#Hzo4Db5Jaf z-$y7Ij#-KwC!<#eHqUV+9g_Ob$gLylrp=_3EahuN<#sdshp8kT1OWl%C#AF2_0z)5 z4xrUZ(WFHI%y<&rMW9gi;m*<MBVDMg$D}>pZf{Te`fqi-2f;7~a0InJ5>BL7Wy#HG z7p%Ka27(jlY6{SMJ9VI_jK6O<4b$L);;l&M!EM9VIbq7iGzwu_|F9EvB-lt00YD}8 z2~8qM`I~1zL#aWGIY`0*>&rb&{Brcqln%Gg%>0tSrh9M91aVNd!}+S=`S7O-_icw5 zmzsG6F7nFI5M>@otj!uh28>AYJaK~wB1XPw<og96wTB0JvI`6#$9ck706aBt0lj&# zE;U`Q@-;FY6c7vFYaYcgW@m><hsB2xJ|f)NxRbA{m;N-)`HG$-RT8q6wb~kCcctS| zGPKRJ`(!CGddi`FU`w$rfA$QPskXBbIg=sPco&*9rji{WoE<G4xizMEL>bd42sJO> zxgyMox#;;`kAz_)Ae3C;YbmhXsM^>Bq?stfGu67_a4C!jd<~gi#3l>#WBVunS+;EP zY{<ia7G3!Gkn76V@6l;{1MC;Hd>&2y;>6{==V;-#=#<s1neVC1LFr$Wt`5-*teQ7X zh}hTisLzdtvJPhimLiEh4#CsQghSj}jT>j$kz0=F*4^Js6ZJ#l0ZF2B!P)5r>OB($ zxpK~@R^7IE2hJWm#C~GkK^qKbR@p=Q4-r|5tkw$RtnKI?30#B_(H1*~qER2Bech{f zC2opa7<Yh2#F1+67#VIiVbBiA>MV+dtD)W6{@noxB-d9me_rr+2WfK17rTmyhXIOE zpp^LvN^4gN&YlZ5kzmH-&-5#@rJkNgAIL)_iS$#3yxJl*U?R?NE|dx{54X5J_&d%% zBa%%keARe7)~-%FR|r?phgcf8h&xCcQgj?96g5NaCvM7G6B0sIXrC3E7Q?!0|6Cn1 zC=V$Za$xPU(Z#%pI_h78UP{)$AYa_P3cqoiR$^;3J4{ywhFCMEk}6-lIdiU9OAF00 ztu-<;?-Yg=@uZb+zr~~!<DT0Xi=o3YMCB+B5ldDJM158k*NAD#D>^cD3zBo}p6_AT z%X`|qD^V9RCt=GL_2cZIPilhe8vL|qL}a9)D=Zvv1WTcuKHiw;8c@?nlu^b|(xau7 zDod18Z|7p!QdP(OJ0>K52FcgDA!la+Yp)~{l$yYg#3WRh#HGBm8UztlEc>t5EO)Lq z?oB|)!`aJP*$ccpAW{FFo*IEwuz2Ef)aW&*f<H$i(-^J1@Gff4xO~l(_L!yO0J1<q zOLe#nd0)qrS?RR6QJU5_+(Ip1TBUr^#Ubkea>-R;s-f5njGX-~yg^O#De=XkDWQ=} zxy-#tr$Mk#PPwQlELhTVU=EKa`|;7@mfN0SX_}F^PpV^R`6Stp!Bd#1X7!596cZdH zMUM7G3&TmY&AvXOc^*dK>JK_aIi5WkJb1A+V|vX~SQ}G$Njg|~ihhgMjAWC<K4r1} zVdP=bL*2bf`w`vaACs=6gHxxIQ8=d)JH3;e-PyUg0fdax)bvrfNk5Vh#D<v8Tr8Ty zl-+~EyRPV4)rQ9MF$>mEWecL<GE4E1eM4{&eAURMsGlw5!!5=JB-Bl+D?Hu9Fz9u! z!`P%qWPu6X(Ta~Uep3LYDd?&ZZh#@$(;#Mfaga0vVqMKkF})-Db5?H&fA%TrHj?yS z46@<g;5@$)in!@UBBOglD+>lm%TV*sKSQP|DBI!LIyy0%C4$L<*T(i26{j=fEAHFG z*%)Jw2?up+>GN@koGuTJz)!5?4mNhAh`x+;1`M1~9jqY@38Ey*tA2&kN5oDT+gVp% z-e~>(6_Bo)gHm>R(t}y$;Em|mYL3JoTuz61jo@<O_VYrJKxg((idD|PSNi^DZDD&t zZ3>fP?zx9XYh~20MG76`Ra|ZG%I)F_%NqIKn&ff9v?~k!R~CxazkY66E5(lhB5UMs zHvq9~3keq|kPM#DwgYTuigIOV+)dNsc-`Di*|=by6pirs@3jX-NN(oib+^oI%s>s1 z5#%l->&JN&1+KC3r!ap<KCs5-!{-;RYo~q{4M=mlXxYU5A8%P|4K97xbrvNAFzLe7 zGA%|zIOT^ECiZYhj@hLp$rg}Vkdm4OaQU-1AT)`JJ6xHU$oZ%uvNX(R8)Pvxubx{+ zn-m$B!%mc$7T2~`*Ij=_n*;rK)#00Bb7ueThBNZK&I5&MeB}3eRhefh$|QsKs_?(6 z+vKsUTq<OrBb&)KQT_BQ<q`oI%2x@7KOV41+Q9<f1L<QD7!NX+^Xfq^W9jjtuF4VO z6R-s${cxj1Lsaw_D11lks0LrN!Y=Uw0@#Z!mFD=&gG7R!4IsHBk%`U_|F+~O&x3RO z0`_UlnRJUH@kdqW4ftt=U-m?uh_unXUWA%6>Ag5PnLy|x-mW6M9vScX-&HPTu?2|! z+9@7ZL-aP5HKc$IPxy(YF7lSpV2`zn{b8UFP4qGSldoXa>Y$xgc7TsbpyV~~2mZoY zI@`kB_q7)yDb$ZhF{5<5;?v6cFjfy7rl#!#l?oY66v}uuJ3qPmtSZkAx%T`ubnJeX zjflSW&UGYDG_6oi%X(cGvpS8#MRIJ^K2`?7_{tnNW>5S_f50g#Gd?&LOG~j4AFKNy z1WGk#IlgE60V{sNz-}f2NYF@N=9?>|(n{te^buinJ@6LM%(9I8e%mtUd5##p^#=W5 z!C=;7ijoDI3i-GwIy0~l#@d`mAYNWrQJ7N|*^|8d)9PXpGFWd)65SCgV&tuC6`T)l ztSXf{Iwbdr8b8KSf<NbK#V6wU5QHbS%x;kG_9gyBMS8YopUk}OPr2N&JyRA-=}q}V zm_cHmS}3|JnZg)EGGd(pJ)5a)I9j7>-KQHh-Uw>;0W*^esUalNxt!r8(g<*^40p~x zv~!W+sC1b>kw>M^hkC@fOsI_DcfN*7kFjW7w4VIIvIM&@GHm>3Z1Ze$@@;ZS?X;Kr zb|-IYk&Uul?fj}iQDcg^*PaB^1~Gr^cnN?|cBF>jHrh#A+=;R##DKeJs16@1*Acno zWEAU4J@-Z@|FrbIS$R-+QhDChmJG(<+c`Ksnt8KWUdqB~p@hH9P*F|<4UfG;oqhe~ zd_E?YAeyjAloP*<B`RLGHw}lm<QjV`GmAnrl09YMWFVpb^Y;2W#FLWTzpT~%*gRtk zrN;EfZw3Yda?BNgagcC(*U4l{4-IhTTETf&yYiDBt5?*Q>bl70@_ez1lF?38(g5>w z&+wE+sF#(GTzAsQ*Bl^yZTM5+HhwbqaPV?(duZa}NoFa!3^;XgL2f>Zc1hkQi6eBC z*0_fLhMixHs;&`(u2)qV3kxDY9)5O)z~n7oek`=4mI@V&!}Gdhlt=4bM(^)@%T34T zrz<_dH$7+(Bve*duTU-<puin&0T0<545e!zJtLdwq?~u^26)<AJ4UCuj502LN+XTf zi_tju;@W<#0>1s2Z+h085%<-mp*&eE_%(;=rw~5B6~e*vVi5UR_(ZI@DeHqWz%cys zcFi#IE8aYyM=h+3ACa<(IZHB%dxGavB+FMvhRh6Pue2Or2>3wP(Rr9q!%YVnF%g7F zVNV_Y$X1chskLmYu53??@9<tTqoJH~s2=e<=zdhxWK1u1a>x@cqsnU}=yKd1V>&?T z9wnTNYo4fOK)e4f{sLp|FsvBsF7smcak1Qa)=4TtT~oirQGugpes?#dNoY~`M!aeI zTIbxdFO8(<%F60i`(BHLH_R=u8obC*ahuoidW)sS`S^Zwy%et7+}WoKRfh_#(LAfk z+4=n_1cy7tc~5s>U;quCW+1V8xApn7D<FoCJ(Qtj`uoRJZN{d-Y%rX3pm@s0r~)3u z1}d5CF(lZMYUrPPG9?rhRo0^TI*2*-_W}T=h=@aXZr4)?Uu&nuhBJ;f)UVIrm_h9- zpk~dd!@-uO6;#(#b8_~-Ukww2KX|tr3P<E3E%|RRMAvG3FDstO5(8;6OC=uwmtMT+ z0>`5=SJ+yPY&c65Eq|Ssi;*weBIvD9Qw{(Q__|$sNwf||j4Z#=kEq5Tj0HT+To=vv zqry_-?cAbpo-P-y`$7{5EDC^_dxIGmnCnicI>RSu_E68{U|?N}*c}W!eN&v)W+#n5 z9U;|R*ZrK;H&;f^yLZDIJ9FtbU5~~^BbF&b?m%QJTy(yIWDaAaI1+`VS|RXU{l*(Z zQuVXlz+Anv80g3FAzauoxd$>O;T@eY{BdpE*M4+&DSY1GY_{jBKI4Sg26pVCw|2ZF zZaYt{yhnZVRcOBlRj)US-15=cXG}Qbya%i8a<s&4tamhPz0#HEzgN+;TzI?<^?YSb zT0Qt)VyA3hYjlaft#yuO05x~qNthY#0B((69s#Gf2op+xjnO5C%?+(9r@(hBn%ZJ+ zie?tEb@jb^16b-uX-(WSJ&nr5l^SBYKqVeSVK_Gh@rGLw3}oy1dZ#J!iwV?&UNwdt z^44GLwa&qN-=Au^j(b~6?P|GxI6W>yZ!!DuZZpEcbwk805H<j1D+(Nfd52HS0eb7s z_(b*z-}wZKubZc>KF(!Haa_bm`>Sf2SBDwDN3b_2#=5}q3KTW~dkd^%->O61xm;up zXzN`7zLnE$E6CaM4mWe<*nNLlqutE+ywvc}*0BHiKp#+o6jZuO^-PM->mXW=c2X4b z$JsQZBYx;1eM|wEM9YgA#$^%`W52r=trmEUs}0wVKO805G!JzVK#*aaAlYo8K4h?) z!<&44S%nyKUe;<S%&NhiK##^y=n>rNz5a{Nu?tm95BCNm*8-pf8fGmlHoK{VoYKk3 zO2=_?Q+qNxVdB>!3H+K1H=koRYDCGnJt+<Q>u(dr3)M-k=58>qd3lg901jzSsf^{; z+A7h6Ala*_r$oblT#N8C%>1F$swH)XT?pIl2K&NAaf_Irl{dD4Vh!e_de3O>yngY~ ze8U*`m`*Z!guF8ksH?w~__SZ{v<72e2ctnv=D?t2+|ip5lFJSz9J>Guyb<B}sei@m zeTNG_w+XySJwqri3k0X3<HUe@^;={rX3E)KO*vnO{s$-g;1R%;OqUX{Lz#>S`4N>z z3N1)({5uLS(kG5A?<cHsU%*J3A3Ac5@I$)3gfBwk36|E(9<&0Jx((D4QKDuLwSCZ? zwhITL`~o!@^V;9oAE)JTJC!2AH<Z0(R#nMPy#a&?mvPi(V;|Z9*}s_A1grzg7VuHY z3RH5Rfqhk3=L+C>-eu~}4ZkHzmz~wSV#&GsniwuEs$rU!Ii@ak9FNfNADGD@k{w~- zakA61wHK9U)P5AG2+%>UV1h7ccI_@-4W{Xu-YQ+ozajK=WD?FUtpgq9x7%rwt7L=K zj_ip%?&>_THV~*R!l7ZRDJ2K_XtO0oSnNFj;p!IAc~GT$*^^xrS#L3r9}H$ACX@Dy zFrCn_OsH*}n@XsRd^d}D*ZsX5pP)HMnoToiJ+Ga+6OL7YJ$rvWOsmc$tog0!Wzi_p zzfLE?Jzo0v$0G~xlEqvXE=-lBUh%u1s5?9!FXLk_Qq`aLzyTof<?gYwOk8s{deu}F zO*_zufz7S(G<jQUICj{pF!n3&=|WLXa2wGX!_b283K;^CERZtirL(SZX>Hugz$Rsp z;h_QN5+%ws^A}K=k|*bg2GyC{8MdQYft<cGZ;6OboQgIp+3>KqP7Afek}E8lMJ2(u z@r3E_QpQcOWaA}Mb}3GCA~9pSKvwBW`H(kzjj8;wXnoV-up<{|*nI2E1xiR7JJ(Av zW!d)Rfu4DQxRXHA*CT|&K`CZNFCNmrF$mtlA_bO9b3>JotHWN6+&x3ZZpy(N5?h6K zma+U^b=uET=MQPffxkYMSmFezdyM!5k3}g`dYPWTFdG8h^&=RZe`lK>Yn1U^aQTa* zyZp*-wv6@Ui2|0;sZ0}wG1IRN`ZfcmSRs$(n3G~~9x(ruFhj;m_|K7x$9=ua+ZI6# z%a?)4Xu|lcY^>LDIj7~8u4NMxBc$%Vh?2Cc;Lj0E)@t(M>$r1EG*2G%l4tdVdkFpr z*@%Wd)P#NIe=gMt*GXqTuSt4r2W~flz2DeD_{VO7z2EKPUSGky0nbrWr`Y7ro0Y;* zKC&rGmt~D8ON$^}Y~5b&G67FU6D9wmG5b#eYQgkGn6j4QVsJRRXUpBRLS=h|pBQW+ zjag$s-M@q(Yz8<cvH30IniWxSg_I2`Z9_;P!^Sr3euR?i+(v7k#Dmed!>qI@uhjJ0 zDms0rY)->!9WtwIPY_Z#dI{E4c$M(p0^HxdZwn!#Hvw|3A9R~f$yQ#YOCARB+;jvE zkzd}e*|dF|DF-7yO0ZVai>8^{Y~^Q=?)~!c(WufZaCZd~J$M8dPN!7C6+LQnH!RVZ z^V5f`WvPPiD&jU>p~Lg4yndn8DK@mBHS?H<UqobyqnV9s4q1*zOVerFUHVhXdyhQ= zRX*OD|2Bpm@grusthc5+yxE?8%-^1E)_K9ruZ~DM#M3s=bXUCteQTFjIk8$Ew3~`` zl3cSl=iJRX7UMs)RRU%^z?N@uFt0ur<CJChod^xvq9ZMP##@ospx2$}BdrPSDb}#$ z%#5<0gMz0cdc54Wx4H=Xx|ZOHG<Cbo#P*gtY_{JlZp9qXJ9V`)w2aq7_AHeYtCP;D z<YSc=e-+bCp-Y8udh$}P@d=(C2}9dBG*N+U{>7ayRSF$kTQl>H8DovY&u^9v@*0!f zJvmouK<wc9*QIr9LA9O3KV0<owt&Jvrus1*<&7q8cEQS6S2A~eHw(g7voHxZW*IbL zJ9Zq?@PpX9o=KB*bKqn<i0qY`dnz*0bQ~XF>WlesFYtnn>Bvd4Cy_;?-YJc)A_xG% z-{S4o0bJ~~@;sgLbxjyZg>JbKu6a#i=lB<4D&YPwhnW);y(_M}0eAf4wrY2WJVZ1u zxr*D6{OjQ6>2e}HWAU=6WtfW{@;0__GHUAg$3b2f13&i<yqWHolR1hesNfe2UM{>0 zG;_P5_U^my0#6N3Ow&=ndj~w%L>?V7j^bxT&!f`T@(c7ffkC~w5e`))<4Wk%NqI?t zKz6T8@bW<YNLec~x`2VPys|aJ6_;AK4p{T}?e^H@@lUkd5J2;fowa;{rp~1ossx@5 zs)?=5a>+K@Wi#f9tr8j8o8S!k6gu)ldiB#f&#4e}OR}<K*mTwng{(!rV#z6O_8ORk z_;+s;Q-xLGAK)q}6UKOqv3x@F=H1u)5hPU5d|5@IMhT=^M5K7hZ~Qj@;w6hwf3%5% zV9b++xU96Gp<58kTsoo;(L%XQoGaZ2S+lVpCWOEJShF+ClCPtGl#W>WJD?<K!JH27 zH*x4JdmdD^9}k4$z0_y0M-#VcSU<CHU4(t_kFpWkz`?u&^EkJ1i7b7dhem<V4wHw= z7zM*Vu4=ix{^V(+_GBEWGmIoKPQgl^n#A5UDnS~!LdH7x+p5{=Pei_imOz_N#Rx%z znMcPFEgfw7J%#73>3JleQq%G8(+tY?yCfZ4<bVvR;K`%K;Sp~;_|=YXl0w^6tE%<< zQXZMK+%;@W>nQr<L$yY;>f<t`0Sr-if7<fNvqoTWyZmEi9qPgoCrV=OuAUTzS#C&Z zqi#4|RAAlvd>sk_4N>cML6j|u$yEz15{*>ysLCZaD$4TmEzr4wy|cr&)_0eI=7o0w z^kR=5yCEI?fl%7`q{}y`Uq}hWQ%X|xLKShxPgvcyl~~)#xHe}|=!7upvcySVAv_Ye zI{=~dputf^!rR>_jDtT8|7u|%lU<2alZ9a|wHhG!yRv&~o&MA7Ith{q$-Y>-S?{+` zFjKVJ6{by0HrK<XG7ldRdQ+h9=O(YESQN)ryhJsyC--BFF2s4AhcpK_^KpMIgZ&?U zPu&oY+y!(oiM%Nj!x(!&0Ig3yW-Wsb%0;T~`sH8vIhN$W`~b(z?5Thje%`L4Isuux z)6ev-k5eGcGuz0~M*aDuBZ8wbk9T{e1xJ&wc2fb_s+OW?dE|6xTva~59<g#aiB5aW z$bu3@3bFE`cC=)Xf}(!X0+e6ym0o=ZbAHmU1q@Kj+?15iMk8VS&9QECU4@_lBH&3x z(MiKvYt$p%fQ=tl4(m)UU7+)D>`B7ttK5iq!>n9>-PAVP;<}az&co#>r%Uh6S~rlM z-zJmjq&*)Sa}6Z=3iyiGM;37jx_wH6ff~|B{(GpC1zQq|XV85s8HeH7dV}?CqyfM) zE#NhsmNJteK!E{lbZF`@w6l%kw}@IO=5zanyK!MZgBKZ`eBzS$id%4xyv{vl!IYC> zmZXNu_4Gbw5>l~3wzQiiY0IzaF7~k?|3lNAmpQI;JlSpura8CBYhoi0UbA|&vvhcE zzf!&NHJlD7_^6pz_$a}Bd%8!ybDb+F%j^?wqDE)KLJnd2(UbSHEkM%qe6J$K_bF{} zqVRG(r)W4oD<LfoKfw=vkAGgmzAbgakZj2<xC8A^Kf7rhh;Ca@1?htArbPB%vj#J1 zutbd!YImwD=*9e2VFd^uHM;0OMB*k4c(4!D^qiy+oBR><57io}riQw4dnNu>#CTNc zkf>0<U9kN_88OAj+b7%kz%1lwrtH@WN&GwTdFmcB0O7PDheq6cyK_?r`p+U4R}8-Y z7T#+0j`xCC^q+|9U*w=_THTpmQD?p+o1JCWVQQ2NJv~P`eA3c67?Lstd>>$1_dlUr zt*>ad0B?KKqmfXf#!IaP`z0(L4CK@`h}_h>daV%FAhtzElPJ6e`OK2yVf=+61>ml^ z$b(lmF@#m+RnjOSKhFk1FNJj9{T!)}NEDBGe+B!6MKG>g08?U9t2lVhcA{FZ%a377 z)=L&!k7-zOH^osC))=c-tkG0ykd<g9WnEG@$*+E^frqz+Td}a*iUn!p&|WRppp99} zmA7M&{+x$3Celr=rQMl`l)9rS?IoQUvB5Cs_ZZ?bp_ur+>jaC%s`4)}oFrLsJ}@*e z9Y&P*kuZkwCv?BDxQn8(7oefnBR?upuNf^k_46YkfS5F*je3*}63+piTTRsspj5rp zPgm@UWnM_gSLZZJwm){@a$15}J5hMYd-6<g^}Co|UTU)33Edc8K*PbGhuZ5IqUGSJ z;5DhGr?r3!ujV>?y=TH4Z-{DbNuZ^JKig*OcJGpg2Ztz>uHa%p&yb?+BQ6Jl?&IQ3 zSirmRvw`6dbF1l|m1zMDU)m(OGN(p!EUm{!lAH_6W<0dyveQz(yH4>q!sYCr9=bO) z&G9Z+>r=6#<dw^YK%q$H_y`4WePFc6*m;%5LJAFWk)ou<_X*Z-1-Pn2zLXQ>6Xc{& zl43l>i7HNd9jyt_t=}UQ($)iwyJrX>qRF=-&tT|adT{2Ge-`Ng4MS#(89b3<0Sji* z5rCj$^dSZ+v7f%45IEV`PxKuFSE-`@{+rW1c1F*ko4fJ~EGs#DC8v$6PG8F+?~|C* zjU^0KIT$=uRIX3|(xSv%J-2adxYrLI*2!4*+UUX!PSsgcu=j7=#Kz&iGQ=9j{`NGg zCwt{@kVoXx-WeoRrizT20gaO(VhDjUg9gN%2Bo_&U+C@DNCE4&D-9*T+0quCvV9Iu z&t0)_EG@kF746#XM?8MC>Z=!vg%d9W=h3Xt+zOVc!=*}AaBLg?5)Rt#@ac359VB1! zqG9EPS3M)Pu#HCgo76kKJaoA8g=^^2)SVaCv%k1Mb8YrI=j;d1uml85DcL1RS!eH* z60uWqvdB`h4wf)-uC|%Un^OF=pk){l8x(^pFFyoJx>w@$t7Q-1Ny#oza_7pTR>#bx zU_+<OuLx;P<Al~0dZ<s`9OrJJ&&MH~U#O4#$5u&iU0O0^^<x+bzI)n&nFb(=9C@ao zx{_nsk}1$~-<z3tZnEfM!OLd4GVSGkq<F0R6|wocE+*jo7-RC;jXHo~`?M&Ad92FN z_0`6w?VDbN(3;F3A4-T7wkfHT>SC$gE3kR2eI3Ttw|Z4|Yh*(EDd5}HZQnZ9VWQDh zLd5-{y3_v1beXolX8!n?LR+nVZtc~28n4^=5XIHdk<v_)q3XWkjvgX>D-nelnNpO? z9WZGCR@Ct`d3df%i1MeVL9-olNA89MH~%8c7D!FTzkFFCHon2miG!_9dtq(nmD<Tx zbH<vF$HpgU0!FSwBUACqbnc3a$kaVS99`QiF4tn>4*eZZD2Y`KQzsV}r?$$+DWS_r z$TP68kl}W=CcG@kHFMaTxTl5QID!o$t>xI?%hs!{Yt|08D8(7-G^{I{+S+(ovW8h~ z(g<F*ARG1m#+v8unv6E#oQHSr%60A&SyFv6SlA0JYcCy4%HPM4BGq2Qv#q;z&>xY@ z*3}a2AEHo3UAaD`w@L4mP;!~}0ABs<d004CUW5=?0qu3_>Nh)2TEouL*N5iRv%k9t z;_!{~iycX%<)qN1iXukA>NR56A@=|g6R&-vWb9qc;)VR}0!~wBpz+eh?o1oYZ`$|` z)&fcUTd$~^>55d~Le;&<95Ih1=Hz?i;+0i-6wq{QU(Bf+`_PY#d~SBH=2&|?lV80) z_9E-}2ETz?Gd-V<eP|!E=(LK(-+#n=M%uHnd2Ef|TkOpT(|#O7K654g$Ta%62Q=w0 zUM1{bhzr(;znb7Im4XLibx(WWzOm~uexGJNl-O(JPxGaX2E84{o<*N0$V=NAaSa{c zJO2?Jq0i)_%jZc=V2cwlsrD0cVD6&@UYixIV@FzlqWD$i3tr<k>&tm=v!CuDy+JhL znWiI<Q{XZ>$@1;`EgdE1O28xA^T@bMO1<ar@t`XgM-YHth;E<L>E2Q4BC>TC;@1u$ z@L1rvje++oga^giCd^m#ZT|%EMfS$`6KBTEw=s}JP-Pm`N=J2;ZG3D|q`$|rbGK|v zo?hdRomA%2S<bn|*QVpR>a*$PQhhD?7{Lnt&+qyhfv;z|ta~@pC{Acsg0C`qsllj* zTTC3&JZ{<7im_W4PfD=?NG9ivkhiZqRRs7bZz~WcO%u-$hD2wOQtNCXQ^Tak0bBV6 zUUZzZe>(D-_2R=awaAH13xGf85uv(@e30#FMhlDC8l!Ykvmb({QJP9rH5#;MP%pS( z^oVL#!`)2uoPd}}wZ;8R3nJkm{RpY4;zMV3^tyMtqAO~6?U-rO!gZE?SOo+^p{5Zk z6$5BYya*N+&xiJY`ZZZ4(+`;@`MtSp_X73<mzP2P(5u!5aswjzk}p}^ACtOEpSjxi z6~NGm(|tkzua5_o9tiCSRnM(!hY*YHzpwZxRb6FUr?neSrwEr#;%8db5|=f442!-? zV0A#AxYgSCyR?#~Kaz-vG@JHpb~0$5JLDUV?i4<T<Vx%VKN2*m&@ZgLt*yOhhjkE@ zY0wC+k@!FU{xQV!p3xwI)}0dves&rPC%2ezaAvm*ta*E||9hs7RG;?m>Aj{y2q|*2 z4x5}@`rbpIc6U47#vwGfTp2gI(WDs6{-UCJw`ZccqEqSJpMibooHU|QnF&BMbAzJb zhM<yjM+T?5q_tkD<R`j{&tw7aJ;r$FDQ8zN--a6^Ryaa*0~m?{cfdm+ogG<@sn^0H zNF`z!P79fkV|+sfSOfQ2de@4pcDIGNi6KD~TRMS6l-O%YQx2Q?HJj=SyHfW+Adegd zax2<^YJVd6-#?j!mx3V?p-yINrm!a<rkM{S^VXj2+RXUsE)+eJ{BI9CuMrU)qQ|EA zG)DxehN}U%)wFae*ltg4{ig6)6Ws7QbiB_-HxFwrZ+rK7A5?Dg;FY=y@p46g6Ji_* zz8^iHr*+3#vPso!OQ#-JOqZ!D@!;g43Fdojk;%8j(Ce!S;Y$<JSL!AvOQ#JfbvUO9 zK;HZrfC*eUe;59TxuJ`xk^M>XUjv(W7vRR9?FXlhd81?;Eso6tTN?#nj!n5OV@c1Z znF?5ow8WB<?}E&u%>F{`d!W^za6?-9a6Q}G2<B#CDvnJTo1VgOQJGgpWc4X)i!t$a z9L$qEI!2ol>aRBQ))D1<{E2tgvOzCe^QC0DbNskH3x6MBlyW=#p^+39G&n!AoyZ_I zZ?@!NQ8@5>Oh7<Hwztpg9LfmtKjbrh`#xl%!PaOF{Ex{ClnJI%H_Hv@Wo%{&1M?p( zkHa<Yi{L4$Ecn_i3pAQXF5BEwS(@FQE+$Ml6Ur>OQ1h6$S7~LAIL9-~YbIh#yDhJ; zWa`i1*;+<l+3wmQZRNLPd-V1{75++wM7Nx{bZbDmOax(3zFFYdprd)-N<BEl#&z&9 z`r+%Jcrcu_U~o@o|2RDsND8|LkOuGlfDDM^(vErz#2m{PvxF~|jajd~`GH$!kY{-M z3-+J0Y@yv#x-tVVoTgKGkw8_{<mY6=%H}QUFAf5fXsw&D0nHtUnSzx;&-MPO<WXD& z!z#xWH+1OYw|i3Eg*n_k_b}QScccM?p{`9wO_gHPc0fXzA1qBhx!b>REqWd7O=5)Q zi`SfX8C=ep{p>Zz7yo-i*Qxaef%tRv-D&z=dnCN_x}N?DV=rrfrjR>n>1m(}bOVp_ zTHZDqcj}tXrU~xbOf>WGYI3=3n@XJssL{hUfH~NIWTLi&8Rq$=wM;e(0v;ldNUo%d z^R+QY0Dyb`FoW%)JaC}&x8onlFEhx@wzFGFd+o#&na82kL!SMV*)J7ADB^f0#(sv& z+|~jpRout8aCGR63{n??{wuOF53{j9bP4_C^Jj&Nf9O?>7HrTcG9H%G3>~u><Ohq| zrYG|pv(z09Wl)dOt8&)vB@u}1<zejL`_c4p=JJxSO@uWwO9Cu@ecJt@1ATH!&-c?8 zlxB#>#xtV+TYq2ylB<i6ON9DBS|(jzjH|r#_>ch_vdoipu1~`~XOFg3lAe}eE{nf} z4lwtSF30QFI^q1c+n!iytrhO`5OzjtP(a<DQ5lvUO>0!a_9YURRK+2th$Z&oQ&v{% z%%?`qZtWP{)V+wcttQOW#9q{GRHhB1t%~wc{P6z(KtR90LPfikeUu?OUT^ZGo>wXZ z>%>-_$6D*0qA$f$wX2N{S4BuuSLk$kfi-KKO%kflIZ4l*Y*bEe*STY}JP8bNCq7Ic z%>=(DH52p?tRQ#vl<Yow<CGoI3sOAcl2dUhQ6_9Dl^bWq<Yc6Z<V-w~WKlBGKyD8` zA!w9@yPcI#GjsGzk?D`7?twJDwu^X}{5>AKo=n2SQb^vo6=)4%T4aV6$gn*RHC!io zWJ+UFLMzVLl2l|x)(i1wJ>EFIL`T{z5oV?+10?H_GYmta?eb)COOd_!mP*VOK#v@j zB8;Ds&FBWKI|5h{i;YmjEtKm*pLA!UpP<U>ag?C-WHV_gk!mHB*~{|MQIgzYdTH6i z#~E*n%1%;RxCdA$c$iQ@#Dne1rs7#omQ{|s9&Kk2Ao7(;V+Q?JGtrR^BW|9dS+O?u z%B0wYWFj<xjuCyw`3w_7Ph{vM@KQv!@?OetqtvM!#{^b^y09eyhVkJ*yYO$KCJ8@} z*d!u~Ala?)u!DGczJ@1e6G%oYQ4|S?jR4P!l0gPu!o!s}@ix068F^U*n~OK3@GXPI zFYrEIlw|^vDDWm#kd0nRjMj!ENjCF@H-cH_BR0_@7!_5t@<y{!<jppN0uH+YjH1E7 z`xUiLu9HMCDHdXth(*B~MbW^^K}D!>h=KsTVC7reB}ufCutBs+GImHNg3W5MO9#)8 zMS<{&QGyng@D{KGFU#0E!aFRM5VqWD76h|_cma6eYk44oM0_@il@J5w;uWilNOptK zBZ(3r7PE^N>kNw7A=><MR3)NGCZbQogf4@%!71{D2u30SAg=Ebc?*sc0i#4rW>p4y zMIM$dD!qI+3xqZvhY{o!$tH_Ltl?`#9(yJ##AJ{SK>yifMFFcra7(fPINU~A6h)(1 zmc#~LCcNMw4xV>f6gzJ=@(yD2IF7z_H?Q(e31p+4CyHQ_WI9y@+&0l{G)W@C#U%1J zqgAjFoI9ctftS@fBG~P4lA@6IJUBoxgKUr_gGxMrVBrC~1wo47&>L%b(Ig^xi;6-3 za9jz9k^q8T5{w2S8U@Ly@{(1Q9TtOKFt{Zm&@mD{wp!6(v{;NHSZ%!Ir4ws23pTL^ z$5Nq64o<AVh$G}hxT^)5!3t&@j+tzfF;Ecz=T&eCVy$50K_IdL2NZ|f=EEi!!77V( zqrgj&S>mlYlFROp0qocX6Zjnh&Y2ab5rPQ;%+q<k(E!9`l*EW6`Hi@l(LBV}Tq}rf zfydfpx7|aeI+tRIO0q>#2oAb{eGLn$0W3}vFF7SaG}I8j-WCEQ!j0?{3^lxwAQU46 zAg*Ayn6U*aZ!_>b5e&_CCFHOZ8&B<N3J8t7Q8HP;A=Wv0fk*J=MXS<?E{91r7>x$r zsTx5v2&&zPHJNxjF)IdxEK3AORWyJ}AQtQat~4NuB#zz?{Up|d$by-+)_~JYA&tih za9I&aL@2J6aOIkakr(XP8D8nIG&pK)9zm`%Ff9f53Ac1Dqnq4Rim{C48%vt8RBkkY zV9rDgI6KF_LE(}`w^#oRg^pU0&lOiwiQ}#DI60E|1bNNd_SWsXQqHXFrrGV<tKSjt zy~=2Fl<pP&h{<CYGFj&%n?3=zCFbsbLT4g{0;aI($jCN+{X!R4{Vh&i*0K&y*V#zD zgwi1>|4#7@*NJ|Cqo}`@7r0USQ7&pi|07vuWajztZ!}kCb5S!CZ%*Z*^tXug_f;at zc$6NwVs?%y{<3dGb%<9v8Z?zzn>)d&no2+ZBy!EdZ<^{gwdiAp<~Y>{Z^B>dn-XJo zDcQ_XImI^iosz0C2)WBPpd#)N`~JYh>qtVs9KZ>sZ>rF1Yx+_2p%Ym42i(R!7}8mG zFx0nE<nl#M3+n8XVcNA}90IBUlJDE78w1~1Z4+l9#~BG_6}ZQ~2xMd@P?^z`p~^XO z`Qt^p4J#W4CG_#28Ck5zYY)IVcVVZ?9}2oldq8{OE;>M^j{w~T=U{;9Gn*UfeH2Rr z=U^uG1+9WF&Mb2Af0#U9ATc2qHONJC(G;w1mV(wTs=6E^$LyOsxEb6`ZVtDSThF-S zlt8iT+=MJ5LNNK)t4rLt@>i^x2?r+M!vt<IFDa!U%O5#^|BCHbOZ`{Op4%r1<3D$; z^ex+e^ZsRhO6hagqq?0uesxKjln-rRvH$!>mWzFJXJ64TU9AfX5`@C#OX2M17H_Qn z)}nQaPh*Q6OcqaTD19Nj_|VejSBblBt&e$Inqe!8EbEKiC2beq<wD$C?t+rl5+sEK z0wddy6dN<Jl7X@TmU39OEKb9FGbL>aeV<8`bn#0{T$In^WiIha|I7Zy<^Ufwsd8td zt=4C5;6whG>Y5t;_xOu*{4e<%6ZQA_{V&%wO-#jKcltdmuefsMODor|UA^auRWGla z;D=lzmLB9A%)VM%W2dZ|(B0hV|Ia$#K|lF3I{bA9{RvD|*DyX&@%49C9$b0)f3CdZ zs?}@PV#(vZC7Y9!&s@ju{}3*?w9W|R=!dZMD@{27a{l#)ju&vdykjSUX|Fs8Fnht! z)<aF#e-`o&y^ee6zE?AT+bb~b$vb)uZSC(3{1oYp%W%zEn4WuxT6bqqm(?ZeOVTMV z^cV<1BJGGc+~Pkw=Wjip-#Wh&{+TPAx{CX9+S}T@<OkZjuKe0FuDk9Gz83B*332V1 zr>%r9HpJjgZAVPscAzB7D054>4cu1l3T{7l+nB9?5g3n=?Qsk_x0aSV!`YKekd?_a zhS|4c*wrq>wy98UY0@c!F{7KPm)O^i_#S4u2g{;9YV`yQp(W!V=1PEDW+v&;ou#$% zI`a%JgyVi*4CF0#hqbu$VuOG<@urpg?!I~TI+MI<#lC|p=NT<~_E?PbRvz59Vv{U3 zwVZz7?tLpa$(Yh`G5M<1VYlQ1BJV%Gp|xZAhI5xB^jGWhj@HDIb2sQOunvW+r}=oR zh<MVkhR6u+n8Vb(y;bn>L;2#rzCuhyKO}wHrLJhio<o#xZ=V1&+6Qk>uUfk5s)0Mw zs~RlE#fy!WhE?f124-KFIBiwxj=}aBAoRgrgPgNRqOMz-_a$dX>7zJ1xvx3O9%Oiy zDe5w``FJ~`Meu)uB$v~c?-()=L9h!xt&oGmxA1~~@1ma@4P2OuaY_0`iE;NXr4zEO zCE|8uk}`yh5K`$OQu;J!DpT=D!{r;G;t2f`1kg`GQ2qXSU3u*n&{Aa2??IQwECdj) zk^i;s6e_Cy5G;Lj0yAS7+BX}2q5Xn<Ui*di8R(+AJoIZ7z%>qy{!7T~KE~G;PV5t} z7O!SjnO$YADBXfaNua%?<p8BG9E|zh6Vi)UKe+3rb4UNV<F$t#yo{WwblWXT@sZQc z+j?+-H}tN^t?Dg4;|tfvYvF#S$8J`%^Lj5`v9_DcKlc;69z2&fT=waQez&9eh+?*P zE99)fLt8Hx82xAOs@#fRGQTEXAFR{P!?+#=?(bf^;!-SZ(>QrJsw+KT|F#E{fn(o| z8Pl(KB+D$XiMpWTB;OhZ`XL~W&*xo=_9vy?rr*HjakzOLZY^J>p^IV1*zFw8hQG$& z$UaJxx6V+YR&kXT?2mK0#RkGv-R7vHLsefV{j-1Q)OPWzuc?Kh@z>1yeH^>TDrwSu zTua;I?e0zGuCk{6=44KG#usF24?(|AOK@3=(UdjEoaI}>3AJ-mgr98XncWlWf8x8< zH*3f8lLS_~UuN0hF5TeoaK*4O|A&bo@b@aK$8=b2Ovm$|TmV=60Pflsa#!Paz*a$4 zUmbFyhh)=XDZ)Nrh3Ap#4l$;yerJ;CVVA*_nVU?XY#2P0PNpcfDana!(s9Z`xaOke zTl;3tm|5R)fzL1_s@mt+x5D6A$u6QDlG^(E+UjdtBd6D#HEZ#?^H$7<>%{-k$H8gU z2TJ?OHXw%Pg*R^%->#0S9<5c&HuSBXUhmHtI+eLiP9W*SYcDe|A-RX5&g808%QSCo z-K^QknJX7|tZdEJc4^<y$IR+f`OD8ar|FSKvm-WeopzyiO(kN&xbju{LTUPa6__9p z7}J$WGP;pgs=Z+Ys(iu@w#wxIAFBF-3d4Sw0tm&M(^*~W$6K<wMkT2vrZD^gll+74 z`n~P@Zv>%ZSKlRy$ts#xSv%5e_gp$}ZeQOo=5Lu5dmBC_H+kD*i<T{3cGacJZ<}c| zP`dFvTfinprnmIWUYzS6oZhxPO!8yj+{;C#pS}L6{B^218eeu*m$MFO%KJLk&z`k* z@!YvRu2z4|2`-VoWOH^#q_y4Y_BPth2CL=5_CP!~jf9uP4Krg=x2Mk6)je<3;`%DS z=sEP(NsYJZhG|)!I<m6YE$IW|ahJZvqxV+tajQOLHbBtwda`4mo1y7Fs%LEE^iN*k zhLea-v@h5mGw_zWuGGHp>J>W!odF<Sxh~ZLV3npvy4RkuWld*GyCdpw%QmFB)o{zX zR<i2Ffh&;KpPpDO*?5Cha@&0ICH>njI{3t{-Cf-tyQ5ZI?X-@4K3xnEvK9oHM;hOn zGa75Hms=9j8`__*UOGF}=68mo{?1v8KYiM!dsfe$>y7~7S1Y`Q#4U1-8BCJRCpVf@ z?WXTuG|)O{*34k2wXJ_(_p%3I@Y}V~V>guN#>sI?MP_57jsH8jhjhyg)qQtN@WcPG ze`0+n>pYh2=rJkcD);ypjhi~|qo=HPQ*xKd9*9)5tYTXb?x;AmF(+@GEcBEKstSXp z)n68+`*7WfPnGOKs7$}Gg<9G`!WW`tE1)I&qA@SsDS82>cngn1Y@7BfX?7kv=FB)> za5_bazK{KQ)22WGe{l8pzSq@-KmK>6km7?S2mcJq`-=?Ci&--?uk(ewS!7_7Hp=pK zeXqE&6hZ<e2je~DD)_&htKkN#ZrQ1AW=i5!)L0xYs}PUqA`t9}2$)XzAtKYmQ^QQm zOoeXpo{7I}KY{#%7UOq~qAm^(0|wO^GADRSlu}AI$0y7ot7<^P9R#Clc|q;18;<(~ zq-1pYd4k9y=C>5T#Joabl(TuQMjn6)OVA$xZ?t-C)V8Q0<7ul4V<EnRuE;-z!z`)T zL!cWGCGDw74l@?SQ+-+e5~B3=OC6=8-_A>ybVa?q<fV2K=<SX~Z{mJ>$+p?5ak^`3 z_m$6X+5P)FF8IcE>syu$1`NbZBuDb6M?P`nz_#usRzu92>F8NqdyYeRNh@3NT+aBk z!7~?zzmk}F;N3%){@~hKL)Yw|yXC>4IViVFURU?JPyFUHdq4Nin(oN1GaCMHbMFBk zM{)NL@649#dw09nPr6=IPnJ%1r>;|RZ*sS>v4w4Hxqv&iF*b*7FgDE?Fs233tAPYe zNu1=8Kte*O4?Jm*h$n=H5L(DXAXvA4XJ)VIBxCZt@BjaK!Mbg;voo`^Gr#$j@3*0Q z^SsIR($Wd*7K2Ov`nqfdD%5RSk=&oFoq#F_^OcjSoW7}YIov0PI8$e;=UG)X<~406 z{xV_L(`yG#>^`S@=5(EzQL~(};nfFjdf>p?He5MNtiFAoZMn_(48D!TB_K)g;)TA) z!%ZOkUvux+Ik~xi*X7--ZuhWizQ$-3I~E>&>+Z`Q{AfX&Z`%TQeb=Trlj^1AD{qyh zN2)ls#ERB6QED}oZ4?-n28ZfcT`IsSh^-lwT$Gg)*;pPqQWsA$3}HgWzWd>50((Z~ zm1Ts*(~E>~c)wcOzw8#L?VJk-5*{O0Z>$vqM!Q-i{o%u#S3m3tnLk=^UUW%voOSiN z-D^8M^cxRtmukW_J=1$?BHdk)SUqP@Y1jh?q^XDAns)adT>8@#4*I52%^~lm#kE~N z9x^_y&*-xUykRg!F#~+}BDUS$1CFoU**IrlpsxSW>^)bwGM?=ZO`hAmY4Z4nR#za| zI$`UP>m!_+<<-gQ%l16>(Dr`pAw+V{@lnY0MHy9#=HLxzj%bW1u^58iHYV!sfOKQl zWdXY!$7!#^kHhQ8br#RKUeaoq-az)r&bnwP;z;_#O%%gTM6Xw=?Z$vuYpmyt-uS@A zx$%ix_9R=^Eluq3wy*0xca?Qqa!K^O1^d8>0|zF~h;(;Hys>05=Dqru^gpdTcP(uT zdQx}aI4#L=YFOdA>8&4KwUk+(Yo&?ius2{w&7<`(kPkF1ZR=gv?y|?0(s#5S*faZ3 zf8D^qoW`B7b7t+`3#V+E(ApVrG(;NOC$4B7ym+6fZu|v3?NgHH)?4A6ZmreeRI<<C zc=bDOQ!anpYI*%C#*NUT7ONqvWJ2evu*PxFQUHm;z6eCE(16xkMtO9@VL)bY<EYsV zbG)WD-#EQWhjp%1)At<RGrdaQz^b)JPo?mf#H5aX7;^lJXk!!@^f=WI(g*v3CTZyX zs}El?W5y+i<&9JYDSU%Oe(7X^+bER9KVZ<>kJ9C$ZV1K#Dh5M|QW7JICPhN*M4v<U zMUWO7bGYPaNlnp7`Cgg-Tn;9{ASuHH2O*7d5YmA7k%+S6zkF|!N<oYvqRX=lXW<sG z)}!zsCRv=1nB$mE!6Z{uW*O|z3Sg3yS$-A{=gAd5lzr~VSe<f;ih7BkXb^K`j+Q$H zVSgqivKM4huwSMV&&vW#>eQf4^f3LWQY8=ySawY_GCrQOv{i+Yb{g5np^|3%eNjt{ z(T3zX=y7L#cOx>&-b+*2GM?q#(WTEV#3nm1LULi%Zm}{}7i@*ZFCZAl@Me^PXR09y zUI-8icb3vhHX_tCgS7{mCtef<AbQcn=7+(g=IZ5>r7M@HyQ<scRwTN_+pD|Oi=~Hs z9T(1-&ZfJT(JjO86Hk9fedwPns_N?N>#BDBF%0I<JRFryB^7n$0YM0q*C~=8+p2Ep zoH4MJyz?i}Sihdc5msjrH!QN-GWM+`)(+x}h4Ib>Lmlv%{Ul@)oGU#ImVwoC;p~;G z?_bGWCp|N3e&;;1MtTM<iNIuNs+zdE^O4u+>xRAbpFqRp<;y2eIq$sTcQP+RVa@jO zQCBqc8*m-?Y}~lRo^eg?Kab=BXe9Ci4($$vLl{aRiZzmWXq87+MTrRngAg(nj=K02 z>Al+@m40=B0w@ov^#;Y{H@6S`@X)MThkiJ){HX~Ci>wxV*8%Z{+d<hYbeZ&`^xi8M zU%y{%R~}M9^|Aq!{55pf#O^~yR*lQf-*E9OsEie-&D`JE-(p-W?+9RB9PH}iaPTmj zJ=ejI&}!D2?LrX_kNRv@uf{VZe1#2TeBK;h?cajy2p929q3YAr9=?KyX2!rM=`z}> zaR?4wMVT~ErczlnF4`4R8;oirXM#KrmW-7Y92+C)9za!N4c@w7EVw=x1lVd=4bZcA zXyQ;JgF1w6&{$L|qD9o9tTaxPsS;&whUhWqS)-GpQjL*x&uOX})g?^j@jztXYRqVh ztv*u=aoTx7SByshj)*6|FqmICP?93&EeH$>*(PRel);n*AY%&wjlB8te9qYrQJmkl z)L`nn^^nO>1DBI485w*CX474Djp+aS3cq*_M%)7H!L-k=1v1hQ%u+_*3HCT@d8b3# z%T8~beyE~vdfR4RPVo}iY?ITarBi<_FMkJcPvcCk{Y-i)H!jGyU=}?8QAmhIav_Gz zSHxw+{6O3gVhVs^7|LKIVi*Cko+b@Qcf5Yx-UUuu<k+t2=JD;n1}k2F9n31i5o7hX zQ9xp!f!o0c;C3c;)kg<6zBHwwfAOr&^&w7q)ki@1=obZWF|%<DY_Z2c_>o5n`WZAP zqOomdaV_$7Xbj=E@C}Fz;G3}+kZ4RVl3tPidB@uR^ZdTDn%In~w*d7WcVxbUF&Ivs z1*w5;`Bn%G*D|Sr@2#4Btf^_PNp!3Ef$#nLdmkM9=q#`er@lHnV#BT-ucPq+oTlhY z&=}^GZPc=HCLyx2;U*gxfJO;Ah(39Go1n?Orz>aFMkDirw3bl{I)VKqV>5tBqJw<| zT&-k8`d22~sa<x+mKo@Z^MOWhqnmlbZd9tJ`sJ{gr)1tpT`^h^dd<;N!ss#25u>($ zB+*AT5=XO0hYG5xLJnQ*mnfpG9`k5gBb1LxfMZ2J#OQ(*O~ql4>2xmj7)OoM(z$!_ z+4Qu=bW=e#Nu!niOlnb9F3P$8V-y}^yg}B$;w2@QGm~LYJ5X{+CNml5AWq>~1Dnf$ zIpkB2?C8|7*N%l6Lo-&+@OIE%QK!+?FKp@EQLQjD8l#|L%!=ymS8gYVf{`5V=xte8 zuhr;8P)nT#^L}(S&<)+^1sSTUrV6`7Kc6`{aO~Is7GWA@%xHkUnvhOZM<P?&)B(<D z<O1rpDaHGdh+5RK@EKsdvhRjJAA<0W<q$5%LMfBCIVmX{lAsc3ZRVBjOx{t7ByT<@ zynQ5r3$bj_NV3H?2`Pn{Br`<Q3)83$6sVTof>gl})l|WtJ+mIq1u1Oi0E57j$Ft2` zfYQ&)kas>Pn=r81NvB8iL4RJZB)l~Ss)AZV?6xFKUAC*@U`#Zn<M=WYv0PfCaiR-I zn6UR>9%lounn|D-d2_ix>}ww*O9u#tM2EP(5tplB#ni#^8x9;guwi_!x>B9ey{Ai| zZEtFIZEG7-XSdhtIwPjOrG2JIr>@p+uVdO;YgaG2{+S;=bNwQkXr&_!C^yfv#z~jV ztgW4S$)xjVYHBpMTz~y7XfyNt+cwot+tN@L4?3N}#&WAI(ooabSkn-(S<4&oxp-N_ zmTC2yZd>ulrmn6{kC5?S#>aJ#cpRd_FWAjw&P(D-VkpAS3>5<3Wr#K1*Mp)?tCfDD zQh_9)wd}{ljRXnv>p_A<+%F?tf__vB^iPe_VRpzQMzIv3HwS1*)b4rM${cPX;Zcf_ zSmWw~bu4G+!(@i+H`v@+O5le`#zUAmvmX;@E>pvtCI0G*uqFO>K(|g@w)SY{-Unbm zFMxhx0~;i4or9=a%d~G2`~2Rw6E5AGpysi|9Y@zr>u|q5x{P7s)Ggy(<b9N*S%ir* zmJvS&wZdKMqQZVd83%b>6O>-7<pqhfG3XbikIzuZ5j^n<Y9ZBMuy(O|KNdQHzET2u zAcGv>NKa1!bpZVJ=8)0CWH=ge911sL|5O)~cY2Y{;7mw%Y0(5*26`<m6E+TRoY-vN z4<_uluRZE%>TB{$8<<A6<68k>)XLt0mY_yTXI)%=Pt5zfcOE*lvv<$YEsOPyy)T(o zw)bt^*w?<&^iqd=V8GpxJi2yKc@_S+tI8K){Efm<?{=TM%iUNd>KAW0x`+O4*4ZT= z!!EbQ^n#?9K+7MaiSYz5sY;d(m6*iH7lGcTCoab+5Pg~a_HanDS-wIfiH3Yg$HZnC z;`-jVLk>=DZ1dxg0I&NbP@Z&q@xH&!sOB7@x9`QLnkS;xp=F1RWXE!|wC&D!-@S9c z>9>aoM29PYq&PvkkZ3lK2<RZ-f|$$f@NZ4~$;qqC%R5lhWO+$tn=@X`24%l7wgBOd z)=ts9n^+d-J(}|tlLiUWBr`ZnrDXRoNbO&eL?@XP2B6!&ghu<Pkh~>(g$)g-m+WV$ z{jw~XjhCw}iI)4;F>-YBtf6sd3x|{C!DLpR_mQ_tDhRxCM@OBsx`YpwOKt2+Cj0*N znSwgH_7t`Ds3Q69oyq-6FzO~&yxd8T8{8<RGHLW^Muqy32e%O%!t7xMjP_cpTb2M6 z`3PIN8<B2ek?~tb?z8!n{$gI(iOqzNpm}03L<5fMp~!hOG@RUzT@TrGCWStQ;V*E< zr#0x~fHG`tKXFbREZzSX;qriJ#HKy_Pln_eT{g$1S3%Wfv3W-ra$}{2-Tch%#VoF2 zFou5uCQ`}}yG#y=CbvI~=3FwrV~@-oYOVAOZ8@IRPstI)DeR-rR8|4{^QN%R^Lv>i zG=-;mDOIio&04iIFq|s#Pk50`?4}~j{Lyx^$EhDvuTp=aK1C9d9=Jg*Xdlg)9V<Cz zOOAtMaAbee_2B={?mt`l()!{zZp?X>j>2lfXr_6wtAG(s74}aT?bByCfBOGodU%HO zBg+g@r&73X1UQQ-W}Y9)*YqEwD_(Ri^N%r3{^S2(Lg^phShBBgz<{JfvOrek`iwP- z-|)>mL;ZpJ;{X0v^1tb&`Jt+)zuG~L<G>#q=~>kdqUO<<`cZFwMe={7cYoX7cN(v3 z(a0v_1%uqBqVlA&`Q`d1NTSgZbMGYoKkK7s=~2TsFewinf<32Fq+ii#xuE_1c_%V? zzqauC0CI;kgy)}Ro<kkmncJupBQ4DY-ZdwliRAU=87urb+6r_2Z8l_~t40{3L&Opt zm+jE`DVC_wq?bVIJG}B|3dmA2>Nk?UiCJI9>(A|Ce#~^vHch@8hxl_b=@^u)GFg=z zTCqaK&$Q~yaTyHUGb$gv3nSQ^le1D||J6Z966HpG^Fuk@3>hmwOx2@rak3mSde*9c zD=CkxhQ_F3Mwb3kM6zMhr_zH3>Cb~sg2AzC^T{^~g*ogIf<2Ed51bAt{IW=0O~;}} zzrr7mMbZD^SR&>}|0kkWbT-xsWxr++wX%%WqDTShU1@MADg9wQZvOtkWO6Xw@A0J4 z>6FLQpT@^T&>0VcNz8V^Isi<1(En&%#j8AEaLAMPC~Ya55^aaTphtyQc1cf*pT;s= zGV5!@p<YO=4Onb7dt(XGp5cTy;k7D^7`%IGj6oAaDs|_(Ne>wE&}mN+$CjL?VpFAL zI-P#^PLNEdQfbfd&<LJZ%(haXXf5&al%Y=uKH@0kAmXzqQ3cLim}6@#_O(pQwkS-y zk+VtR0YSnZ5A^p-{4h((^=<fL$10bUmdlowpCy+nSz0ogKsG6tZsZNHr4$FemYPog zgNY(3t`e_M^`Ky8%<}OvW1WOs)D3EfT8gOE;0?6XpjJ!U!9j3n%+tro9yx=4<Rsgr z?dq{l%Uo`#T>p_P7gg}%QROJtQMtxA3FqL4%lRHePav6sH&D68It{1GWhF-k!NF{a zBkHkF<8n=>u3@6goDuD%DsnQytS4ifWTI!Q^@!6Sk18sDKDcPi)0AAU<EUI)ircG% zon9F0Br4Y#t2@SNczpEBMJaH>#yE|~BGkX&7V;i(sdDVjh2DfZQa1I7enWpec4Lw8 z4fPE;C!goH?gVFg+a%BFK*vPsIdY!=#tQ@&oavq5JZn*&TMFg;mW@x>o}oFjc4b*^ ztdsFnNAn<<T=~^@V+V*8jUiZdID!WuGvx8e1nnMAW+=~z;Gv03F--iRr(<`!;H-8X z9z*!HzEHvSuE?iDPonej*f!E~;0Hx`b-1ip1kB2eQMREGjew>o7|c8Lb)Om(bqsm@ zsWet>4$6>JgY-s&VbEXzl#DJaqvO*31%<UZJclTs`_U|w_kCw%S;vZI_Pm@EJR5sN z7SrPXYzydUxv>iPd8>$WU`W;w591QhFOP6aWaI)6orqQTyg$>^A!&kEP)ctAUL#;n z)M+HuQKXLOH;tQM5R9AFC{eOzp>f(W854>$fvmr$r+Yk}VUmEszs2*9hA`=5*>O97 zY;4RkOW&9$!aZ_i6csKrSVWZj!?AEJvU9qZXf+D;>42>uN3NWwJ}age8an|^ZS0d$ zeH*dKp3G*+wMUyOhWa+rsWV)FNql-^A53FYKbiWDu0_JHoP3P))R^VwVbL-N$$Dg- zE~ZBM<^(h~s$d)YKnj=p3>TPmCRtiyKuUau^HdQAZJJV1M#`SIq<0Zbb5?1ZkB&UU zHc)b$i<JbQ&1-F&JGZSBva+50Z%g+tUAmvSuzN{&_mT`;ePs3OBQPPuvmGW3lE+AY z9o{i_?vA<AUt|fr8{f1v^9sJHn_h%(THR0LDuzEGtdrm}(tAhxd}w4J(Oj?ON)cDG zew#&|Zv;m!Fwqz;A`5nk-4NO8k^WO=W7H#}(eP4QuT^LbdLzsFJC<*{<+kOR7+0c1 zyk<lnIQ-?^F)(<)^k;?7p)#8EDnHkoIDc^4ytrG7<B>@+{DaY6r3<deW6o0KJFBM_ z;*p;Rz6fX}OnycCRv9(R7Y=3p12H8UEt(WO<M&0FaL%$N>%FmBoS460%HBS=-Hw0Y zE&1K&4qa4v>%>PV9;?3SP;&W^D`r19`-&sWlSA#H12_ES=#m+!2M%4i*4uHVGrIoX zbvN97<Nh`Gu8TUa1Ot6@dwb`O{JCVugJzA!{NRp-`=-|NeC^bIK>6w=(>J#HRh(Ga zv9fE|Yaib^d*RkqGw1p}vuCW@x?tAe$nVIC-$Hhr!(Yiaj<zxb6Iyy_k_GcICZ-)l z$}|MYwPYS15q?n0(j;?bZeuZ5W*A3*fkqjS54A7>_XY8wH&$9Ov`}RWY)-}HA{K9} zh5I6QDqXSIA^l#6G0BQ0b`TOyU4?a{G7cjyG@xn@v&|9dchyIFPNnnZMk~2={2YrO zp6jo6OE=jJ{u(z}XL)L{P?bkOYi#^I9WByLvGIk<EE%ki6whN!F_)XHP?raxJQsa2 zAE9`bIgU<|b!D=!#FTeax%YtEI<@cIOcJxk!t}ZOVE?GZcvspizm-h!3&H94jVybP z$*Ba7vQ&bhOJaTKLHvBV6tt(faDzn6O_bdXDQND&!~I1i0xuTgZ*mx!S^oGkDnK<7 z_9kLZ4iQ)y7aGqK9l!-j!5%3?1bTRAa6vR{3dN-I7Y2VN{VJ%mIqY>x`+)}!*p=fN zY?4~`E0TH2z|>Wbd@K!r{KzV_1<c2fyk9b+ftPpQc;il#0m`Ot#fm<M%}@tkEh0M0 zNcgr@g>2ANS26~UT{jDXca(h}u=fcbdj5^NDQykovbCzSJ8Vi^S1IxD)h%kTGvunJ zMA@LKLe>AaZW<EfQH?zwaz2^3Lx1}!r9zGjS*yd8Lkj(SHIWUZ;KaXG_^gbKHgaT2 z&$rVqF(tlk0R!dth5eii72<86lLDU>_!KY5kukYln9NotyOG{}GkxUkBk4D#H$lyt zbm~oz9(51iT}`T!^>%wxS}47lN`V^iAi%8i`n*mF&uf14CAU%&sX5d#Y8|zm+DEk3 z_fSugu?f`)eY&U~iK6{*(LPFp-W%FSwFsU$%~{W%X`e0LH|F<a_*fi+*$ku%{RZ?e zWf(G`f7v63G7KYOo9;Jc^4G}*jD48fN>ui^utnK!#5ep4i6~QJ|00;G7+Do;Bq=^C z`ptYc>XbCbL3RV=P4=HONYWW_oHC}f8zv8;@vl4<C$oA^3sptU$C7T&PfB4VaT^3f z0+g6jvsTkw6eV`LW%4K^3E~2ri!4MFW$K}WvpZKlxb*n@Uz|*ww<3`!t7+bG>H>c` z8G+0FsBf`pzgqG8n-@+fOHSC>vP$}5nO-m$JZ}GjYwn%A@uwR@(Th)7RBpE${0$B) z_S7dX%{;V8AGAAp3%$wTVm!r@G5>R83pVg?%dlaAWw!cxud8ffi%Ka5;ro7*xw<{n zkq|d(S%YB0F=Dy8v#1AGQ4Q1tYBT;0IfXecl3%nRj-jDag_^@mDrGgJdZCM`u4c>s zt7f5-CtiB_$w%M(4gJ@@-DDEkCS8LVan$&0ELMlO>cl$HR8_y@_(KP4y*HkE^ncY> z(3Uow|6D(K;sxbJKinWSJ-fAbh*QyJoJ}Ee8it|&*b-B5Cyh|?!^O(ytH3A!yN1Mi zIV9r|-Ae$+*p1S?SWKnnY&dx=WsI7s75HH?HPd+1svKJbCDj&1XyQIxd-?{&9Oh&4 z{AMI&Dn_X$EhZJ3(J}cP23)`};$s#Qt{F>HsfOdFs~D@cL#JcFHhBkLGiC)2j;+OG zykCETZZ<Mj9jlRdG6Q2*t`H~i1ImoCmw-73V}vV&@l6S^p^2xnU>^c@T`WmtMo&P? z0)liTFI~zj!_pQ}<aEC3SQ)1@akL#)-;{jou90cLZ6_ZBKc9e6c(Usl>=Zv<+Ki(j zrnlU@dv}x82$T+R_`ZoVb*D<wNne-!<hU&N!_&vPJ?s#rrYcY!YEj$MMk`B)RX`+I zzd^z$h1sOym`n<-W<=Hnn7aXxZtr&8*$O(^wBQTrrunSJYP3q7QYYG2*!j|p9-$We z^IcPUnfYDt&sqWYeBG#S1Kq>z?gzn&ZV;2cBWb-s?MEMJgI>%-<w+<o4OOMoJXw** z<20v;zcp1LG4T2@Fd&dIQrMlDl(B+UTb!A+#jh4jETuCz1-*i~=M?3Ktlt8Y&YB7} zOesXZGLKV@#uA7|lP1ELpaR|!sob0OF)0zvy$RI&unv?s0M)`dnH2gv&ZKf?p5eg} zRv&uKKT&^CslFseF_iT8=&!%XGDP<mS%<z<sZi>F4j&hC@q3Jn+l-kvrxtWjLW%!8 z_QR6-cgg`#9?C&zxpB^n$37$$v$5<6;2|r1`5$~%Uj8@Mz@gp)sW~-`XnEgQlikEu zCc36og^lFUMs8uAC7Vg)x4&_bU3&M@P<2Jec!zyaBUXB#Q*>itU(!3=MtiWTZD#gl zPWOTJpgiTELR1%ZF13c*h9r^fTh6L&Ehek%AWWQpLPY{2n-ACsV-z+tD&R<n1SYZp ziae^46(~YQywCux;0sxRqO4i0-OWD~Jad{->$Dn`3Q+j<4az)LLq$>3ER?~Lr0<!{ zp8}(Ew)2LvGU*e+Zw7sHGdF)KeVPSc0s=ZGJ(0y$0yE6;+M;YSpUYW;n@>|3TmFGS zb($i50gz3!C~$j-q#xXY0hPc^vtN)taRM2J35cJX(WB<Wr2-JL&`i=NpP5mS=3hi^ zkiKhPBU5rwMOofA;$iZb(2qWpVWJmq%dJ?8JO}WI#uuL@j{jL0aWbERgy6-_ylESf zXl&#Mw7J6*Yr>TYbfh=$ozdEGZhKd?f09nn>h9IC%0V!$@9w>`fh~7~4Ni(LZEbT} ztaI%~cTlXIbA#X6QdgBMx1VEB?pC{WK;1ELb53^w@i*<lJY~fwDKeFEZZb3D@0Ko| z;Zm{=J>*CxbM)nCCna+L$)I(4h!l{@8WuC@5VMLH=Hwu0NG(S{t~}RE$wNe1)=z}# zP&VGbID1za2;;*rC<8%k*$x8F5Wa|i7%oE+(gZvYk6IKfvFj)w#$XAW{TK<tkKv`f zv8YJ<V_pJ|5si03uh~zF!0aW?)lBXUg=OX-61NnM(U*O7r%g%IDz*MLNlLx&+(BTv z3YyUwT4}!;fZfmj8h)6OXr^(-IWrntE29zKvc?gdv*yAp>!&W9mY_d);DO;PmDX&s zef<FN1H*&wF(H*!rLB7JLFo(WxA1{ioMl3CZBJ*U!yBp(Yn)4h<z3rXG%amysc!T3 z$^DJRIN9`GRHq5wrcUgc>qLLcI(?Lp7<y!#`qp1~<@gmVr!Z%!((hhz)`HPB>R!{+ z(i`q0^#N$Tbtx-j5mG_y!*9WAEYbr)WbPtb9MG4cq$jv9^cwqcD%6spLY)S*PosSr z?Gp?}Cgz)3HcZu2`p}j^TUlTFHW@z$Wc)OOtd6mU%{~PWWn}PtTson0m*>tp;0ya= zMvR|=g<Bllo(pCt^i!CO$BebF7>7kBSwf3~MKdcW*Y*Z4^Z<*-cj-W+eXhUKzkb%- zi(ElhB-pp?s4A$^0SKWxNFQC+7mT3u7tQNik5bKTPkvAbSQgm)HMN%J`o8Mfi^0>g z@TE(_$HFWUHPo@@U~lc@%9)E6&#vyPZ?@Fd_-&AZ5CDcMxiwpo=9sJGX<1o}NfB<q zDEa;<g*i`PPaN<=6#g2Cii+}N_wg*?A+vzT!lb0%{f<CXW_1jJ`knMUtTG?~oM`7X zbyE83B=$e1lc{&4=WP3BN7MZ_F!3FEh>)>834+opiQ0ei<bH^Mv3D_&WwsE1-yS@h zqYU%KQ2{xMK!F;)sF0&75LOi9VOUH-AOqwB{rNaVg;^urd~$yx-hbZu=SX=+)o1sG z5*q1etJTaKWGh{qx#8sgRrkS}=da!%S0Dym(#@&;C&m6~wjz!ZRn_%MYILUqXMwjU z2VBF8@_ynn7nM);3qjwdXf*LGArQ^u)H6vbxqa#1(mg8<Zru|zXv?&Q*q*HiSM<mZ zLNEzar>^Uq@+|#ChMND-zDs6Lb|^Sb;g~%8l6?=&mj}W^41X3o#E-{AtJmlamUxSd zJ}!xv$_jVI8dx-$e2qT8g8GrB3j3J+<ZHrSnOfS7842YLI)fy(H1H6B6(Z9W?aw$x zOnNMiq#{g&^6xa#ZZwf|hmfo{t>9lD%tC$!BRJGc=JU#xI}yV;1=-IU$K~Z6#J%WZ zkU$AR*|VO$U#rwIw3O8Fr>PCs%ah&i6`t0O6WdLUvBIFU8nvw0)U~F`zI6Xm9z=Kz zNYf0ui<RGbzmztp6rdjpnpM^(whWW0iT130$hD!ab&6N%S7;k-YR}ZJ@j_J%u9erV z5nw-1sBql^r#+l($E_`5^EF|KmF5(zjP8V%7x_J0{zN>0jdg=WI0d$wzc*{M3Gz}( zq0(xSI(DA)-_l1k$E%V??U334cJ=q21akq)n;2P21*v~YH$B<cFI{d>4>2nI(oDcU z52%u&38Z*v+C1wA*NS<rr$-4dCk1G)7?%-~s`0*;_5zGk#XWjbdhG;*+C(h~mKR=@ zUjMc9+RM^wz`$&|W8r*y)9`ilEHhdd@M_g?l1>jNS?Z##MRr>};84Ltyb-Ocay$kc ziN+~5mC@I%5=H4{5EaE$coo+ois0vBBfO$SlX(rk3Zf`oqloWlkrTt;oDq9pem;71 zI7?PwRb`0*ik}Z(Mvs%TL)n6;^fD<3J)!jZxKy}kaxq^<>F^zAdp=0SbJ0FBJ%Xy_ z`OGy%wGj)I1f>lC<Q6C`Ecnf6jQ=s(fHc1<*AS)epmtQf<d;yYPX3rQLg@>G+s9~w zB#E6d;#Dk2pk9UHiu@uQjRi$-7<g$m$gDLCUtI@RT3&cw_qYYDWx(o&%q4oMiA|+4 zKg#@+e&q4YhwsH=S4$tR1S_ED1bFM~<#*pr`mgqMlKY=5zMxkHMX!QI`HJ3z7l`b; z(m#ja&P<pHD$BwB;QiiHlUkVPLZ>F7;q4{q3!nijZ@B9&Fb7orINMeRh0NzNujpHq z$DumFp;iiy!YFnDYtd4<Xwhko=DY%o9UzedGN#k=sI<zYWOV9tw@aI(MrqUbb5%T} zG@%i*-=b9NSN42ylPp}fOgQ@H(FrZ`!A)QEtkf%&7SPWN%==_)8XlAeElQ|5_qqoj zxb9pPlrNe@!^*|GP4EDb*6;Ccn}EGXCv5ZGLr!FNnszT<X%J0<{QVQT!9U8rh5cVq zr^zmKVlw+N<0%lld9sp0minz=QY1LhNy6>+94<M2x|F6y*s$bvJ&{%lD99lXXRvrE z1C{+dlO05cHwKn$>=!ssB1(Uv@_+O!h7kCn3}<{E=y(_359j7@t;y^;t2Kw{P>{%; zq6>Dxv-p~i@;y&ARgiW{V~^Rf_i0aVZ_J;(eG(Kf-$s?gc$VYha*Xu@3S|Jl9c#B3 zXGuXhsTj6e=Y54RnJKXi5&jH7WRDPxfB<IrAm=TNAYT~GfeB?7Yw)m6diDd}WYpdI zwgw2gl+FY$WmkRouhP4>@+!5U`!!hdx`JF#Yk<4hlT=1D@O=O#>3|7c7l7vNTXja0 z?pEOb>vvbNK&>Wc6|YP8{#qxfRrJfH{-p)GowI};g$(6{xQVPKMloo754)tfy&jLj zVAPLdRmj{dOc6j*6vSXA6%>^!^e*G4W86#ZuZS#%-ld8y%occ%mes&<)V7LnP68&{ zFRR6b77A^d=cVVt8n_k>$e5QVa}<r+YlS#{)$q39y5OFsje||QgF*T#bg&yA><Kb$ z((@UN!;9}~#HsOJjre|e-SE~Rx@mADO1CaZ9}1$I(82EDx)JRnuk}kqw#V@Ol^u-f z)R^ABvPxm3cP~AHJGO2Njlx-c1h7(am}q%u8Rf6w0GBG}mW4xk9lg{*sAuJr^xk5c zSu{?f6476?mr`ZeFTENRfb6mNyuU!ROn)s@q;U+JS*g?xsth2Rt`Lk4kQ6%5D|gcO z1+kV?FzM48m<k5nAZ4*gDG!;;kQ|JjLE+ve=JYjL*Go(*Y4j2aG48?ca_NeIQ%a*u zrL@C{9x0`H&7e-DVkwayzH5p{LivJ}I~0T|O`11}BV~a=kt_hh1zBL!XLua0%Fgb! z|B)33uuQb7_$_`6S7l`ZltxZ`t4Lo_{5}igK8HqjbM~ED71)WNz)O(!Q_)6{CA!j& z_9?vaSYuN^c!M`e?-+Hw5%`VLDd>@gGDCD~Nm<#kvc9q<aBu|k?W4yU`<uY`b@&!u zhi}Owp$DLEQyPN(OVAz1%F34XpXs}|V}InVmxqFL=h&nYKvp1(>E-Sr)B%|f<%WQk z!-7+*3zu~Jet;Gc;mUHHj<g&~C$dIZRa}xnIf6J=T$LMi%7Kq(Wfest9)_4GT0SZ* z5B)LdM=xd26|UI+(|zYPdDRc7^$N~H*Q|{^cy)zV>wuvV&GjTok4A!iY$6#9cP{I{ z`24mLf6~$_8(6-*v2L)+$ino9#wv{e5WQJ}auFK}Fajf*yg}Aea|A^hB#>$#B~i4e z$R%@>!zM_lQebB0zfMzVMg9(P>XcK%WhGN`fyW9Xe${62O5~3QHACr0QQAt(PQfar z#cokbTLmKyDm|9<i`CHtN}{-l=yUyUDd}{AwA=5`ct$wUmW*E|Ws--B>>zRWG8ro} zsS2ZDMYBY=2$I%qXD$=C$M5&MLE7n*l5Xku-@Z)5uUoeH#;xG2WlG}w{qnQ^P;CD! z>D+e}HKh@^ZRR7IjKt&)`jz4`5&4t;2P#uP8j;XaQxABB-$#Y>B6TQ{-;Gm*5giHL z#6-$s5ENMmM+N1q@-9|16O1jU6B`)m*Zj0r!!kP2=0q<*{7|~Pa~W=+Zb<jwLM`tB z=MAk|qET^lHEq!`jNW8-y7@gXHh?z`Dm86mosx~F!Ap81A=sdxk#>)J=~5x!E;Ab# zR;Sbc<xZ^`Q}}Q!%Q6tK?})lhI<a}2z;EV-HvnZt&)40FO|pPyXd0$AYPI}kN3d6` z)o;}3w;iMzbR&SQLXlmM)5EAeItyONBQ^Ol$_+OD;cz$1#YS9kygBDHV@{Jp52GgU z<poi9-ZEU%WncdIxua-_uv(?lsoARj+Ia(@o&?^#3ce%occT}1ope1;c@%ZAOGVv2 zUii}^f84FKt1s06sA9_kOQ-!t;P>f7>GBgY;5DEcPgC?8X#KEU=CaR=nAi)n69Zpa z$I0-`Sl>#ABT8(X%j=pj4|=v5S*B48twg`^i#rAWfKKe*)z@ohjr!FJgI)zU?F|NJ z?Q#YC8sp*G8Fk&25xepEJ4D?9UT9v|(<X36?JT99*U{EQ$AYS5JB(Gqsgb%^Q-5N7 z&;gd+@{Z$i+!~LoYHFi4^sEDF2sLnpLpgtDS%a_AYBmUdXH8{u>y*kvueqMW5aLg8 zK5vzQ6HG_+fL7CjzuY>%*HII8`bEKHtqXN@EzG{Nz382F<YaIjC@fjl=r9$|J6k96 z0!%0;hey4+Ried;tuuQC{z2=T4?h3`yjp4gnL#DJg0W6E?!U_-%_BOsJDUIFdR#P` ze1CtfGd_Y=gH@||;qX(Y?@6~B1VIZn{92{ER42}#E%4~VCQ)}ePK$Qi=LiJU5s4av zv!3$$vm_5$n3jBZlSPgOjJ}PQuOit;<7zb5&CG=kXX4=EM^UFBF`d98Z~s&Ju~MlP zek!VeBL>x#iXSV@KQ^jWO6eEBA${(Tz$b4}RlpR1U#%183H*Rggxv;%L68=N7T6XV z!M&n^H)eh)>IQgWo~T>R3)0g%5zRL4)BjEMYSRcBk2#Nwz$^2Z=>&qOLzVEBHg!It zw-7r#f;S*_a(`<7$suSDw8v&QFRrU%%9M;nIgwRs6%N+zZt+H4VT)A*PE*7Sg^X@P zM2;l}Z7DTkc<lFJMK~B*_1yy(&6-kOD;iL@Gks5IV`&xC>YVn9+K#D9Hg^j=@e3Wq z=+(p^hlk70bLRwV1n-rS(jrO9jz;neQT;`~XfatE<6^>V^+v;fd;%@7<P-AxlP0~9 z_R}(BIh`L)3S%vud*@zp#MYvq^U4ebw*A9dcTNQWZ1qcTd%#^+`6qxoXWTsto!Q`( zenW8M-?~>}yVIt)|MdsZR%3*Nui<Ju?!6XoE?C5>)rNx(_8hSKJcVtKO|cwYa4zdO zXi%%!#T#&v>wQn6mYWBv(bAm3%yN&WQmG7Drb}<319a+mD&;{9lsRUz!2$HktKk5V z<7KTiSg6-&ZPGC?V3U8fI=%E@HUVBcH=U-K4^TTssY#><Suo)a&nV3Pm@jPh8-3^# zO&|%&7!CQ2*x}LIkcdUi@hJLn(R5>k@ezR6h7JxNplJskba2dd!cE(@>J-r#TQ8k` zYhTr^!X)uU_l5?gfm7?IZFn>3y>)iQturqkXn);RGqG)9!%U^JCDdEr6{&ZL6YYVv zhRM}k3bxhPUDFy02z2V{X=O*Rnz(*KorO7l3Jg=H!81{C1ORvMy#Ne<3BMRtxLeQ5 z+!1IB*tHy#9s@M1H8^|`@Rc{}wW>J)q?gguqvWmbNRf@gD95gjh-60-f6$AOwU8*A z2id?}EaehCy8$#c(A4ly4nqT@YNbF%-ypr%Aj^SyY>;~FS#nm)`7=HH%y1xJ>{1Qp zmvDeD>|S_=qN1|;PE*`&4x{D=sBUUDYKJJMn(`~q1O{a6s@#%G9wEp|jK#!h@lJp# zF|fA`X2k$VU@_x_F%dIfg#C&r-ilF?dEmQ~w3u3v$$X}keu6zJq%_vvrO6P1-D7$) z&w@=_6(-@+3Lor%3F$gcui;hZuilV`rq=zVZmRU|g!k`$pBealoq;g{pZ1h12b^UP zO>94|>(_(A<$pZ~8U>Y#2K1J{EXsVM6f_XR?et}9*B(B+b}c-bSu5L%itF8o>m4lA zn>}N_K}pT%Z)}HeQSUoO)J{BOE99&FUt`r;8ZK0ixpY($sFBRJ9j!ZkS*$s{mTRUa zW8A&qH@xDJGXec?9>bxrtIT+cwGmi7kRp9LMGhpHxFbyt<S7N9-~O>`T|_1D`B`>l zeQU1%`a=CnYZ?58S6`xaIm<CKq5_g<?ACyTC3POr8ijW9<g2oItfl~)&)xu}&$F*& z`+N`f91ar40AlSwbDs~Ic$%<>BxKn&;m16eS?qiK0br1bc0imoFux7ky|A^hV{&i9 zgv@u&Q0Y$`O?}(OcSLMLSZ@f1=ALhW=2<msuQ+_cu6tcl^#cGZltRbs^sYa3uAQ=Z zT73Rkbxw3_zhHK~L8;iJV07CSSj(<Ef6b8}!n)0y!4nD_YtZV1mif<RHdCYOo*-V+ zg}Q(9I9F0V@td0CTh#rv;`;sU8ybSiR{qq(W7U4Rw3=*m%=XA(Z6>q2+a<ZTE<1UY z>Izwm%xF<q2sa(4z<Abx&_EMYGl6l$5VlZ8K{lH($sAN*l@t|nID<i_BQzLtNW?A- zJdO}En9$P^qfsALwInYOOfz=hzF_(;zatc|+Xm`;y@ErfQfSIdq9Zc7&Z}1eQ50xi z$pG_=&BW4!@`TQOpa=S$-&y0C*51_K9Naj58gx4y)c^z?@G^T4!p+GAUZE{m6|QMB z0c0tg)`@0!Lq(g*7MfP$<7_5=a}LXo;*un;&zZ%p%)h+SRe#W8CM#%Y#f~!s0veM^ zLzxyk+a$O>T4~J5NB$J1Gd0AT1lTk~`WvI<X+banmEK!7IpPpaWg3M_<q*8R^#eA0 zAms4xn!e!nZsWAT<;fORSZ_2&Xgb#tnZL+wK-%N+_JuPx^ClY?te76Mx!Nik+-A|# zRuirYwh7(^$;}W3?eH>35P)ij(+#JM-xzF04L8k$k^6J{4;8UJRa5P#HC9rWQdd*o zp}t4`l*laDgC1+vq8N@Yhy+3Oe~d+cS;Jp6tMWIpS-&Eb1dD}OGhsI6SclMnNStNM zf!}OGsT<>sm?H}Zb2NZPLUZW#5JcB3V5o=mGbFYv!hQlEYK~&!T;kt_Bqmwehrv#a z*>d=^<rt;(ySdzGFc{09?e5OJ&^KiU_-;=)=v8su0PrRY=u~Jc{obA)PoPq(I0b2~ zGuBvcHkGe(nlJa+I3Qh?OhU7$?ykO4`bhft%9<{<$)xV8J_thxtI>W&ch1ykY=+XK z@N1?3uerQF>NK03(fV@piJl$;0p7!DQ10N%Vx`bu?`SX#86NRPqaRF=7J&yQ?2)do zs4X*ufKU3|2K8=W+i;}OTvZtWAKz6`Wqw*!&Rc|vkhAr&R%a+w)-tUt>Hu1^hHkn& z8oj+SLw|QpO)IO{v#m7?jz2NCx()BQRnMhcLB-F0W?f=ko%rRBy)EUTP<ad4INQKx z=`U^rv;l+khoIoB1<H|nU-WgL@$xTdye#yO#ncLFH+7J@je4A{GBL6vde<xxdKw#o zQH()sjC#j-ExDH$L%kzLUS2TfCmp68L`S{Y1ZGU~p~D8ksI1^Tq>Esfb<`_7q=$eg zjdI7{8BsCU_vC(t`(AL29!kFywpuLKFqnPLIm0dMq!-t$1fE5UTuy-oi<H{PxHvej zGR7OK7cHtC7dNWF?8RtUi#+KJ_w<I#%ERL)p#=!c49=eqUv=;cTb|80o^4sAbD;g! zXW;u}f7r2V=SsdVShjW|c)Bb&z9&>x7U~%vECVwa#~LC!<zhe!P8SILM~?;6T6!aq z-lI#GW_|%ak*=sR(;l#1+F5T4wl95QvZE>fyUdz#iG*{GE~*ZUU$A;+Fd7ZcJdQRo zr&C4$^o{Z3-<XhD@Zr|hKF)0B`dT-Bg7+0BlLGBCytGOBJJ3%#w0f@euL+OOLU)Jy z9`D1M%$9VCj-V|H4oTO0p`{w^mi;a<5A#1M5hE-BPF@)&#D;KgA&fQ2=A0r2!~s4D z=c&JRhCVf$)ENNo(rQ%JPb(bsuQZy>XP{4`R$D%;vPs7U2<+j%Tj=uzX-dS0xgO9f z)az@(N`ra$9FV!iWYpKf3qAC;wFTY^JT{4hUl1e1VjU5-I+$tBiuDx<K+XUQAV={q zKw`Lcl)+|?+5N1bR48{puTm)u&$&f9p)mfyB}(U`Wwgojte{Y;q+xK2@(&{v+cbE` zr_maJ3#9vbUKgNeY5kcnl)Qela0YJ!_#cKVN8<ufG9Em^^PonWL_xqLld;Nu8FQn6 zLT|<(wl0Zs`@CL*-o!%+x}aWfSUd5L!+ZWXah-wJ!|XA=H+#HziV-ADf)L82LV{8a zl1J0)@9UbpQfap<S5EG_Z~e$aO2!N0((EB(Q^l;<ZuDt0W?&90VrV^&{w2&REm}-} zB0Vfw*c!=#*2>l!z<dC}g3K&1UlOFp*a(;{S*3@-0`OPqF-f4?rB|gtgHGwa_0k^z z{x7(`ACzGRJ?TB>x6+@b*8nelF8y8l2`H!cNI#K22jd8D0LAVhzIyt6Y5dsRmyH3V z!t4!WQctf@2NXe(MSnn{f(j566*N7VX{Vn8r*8Cvo%G=FZ(&-O>6{H831{a03Z6GT zb0;_fuDwLs1iN?MwDZ8t;AXHm)8j|w8Oj`mYZrDM?E-H+bL1KDsdQ{F7yvJ4o|y+H z{WUYu0iP?f-<Y#leiRx>utO}Sbw}fmKPwkddC9R5`YCJC5~b4A>;tCM+k0P-J}_P5 zcQCc~fb`yp)TJj*T$%!}SCl_iUO|2y+dAvip;=qE&SEZ_we>=HWoPf6w=MztbZ=*7 zhr{m&Pk#0I<6k`vZ@90lva;+xbkoO$<Xelr7d^o!85NtIk37vqix5gGxd($=FL~mU zOP+vFkWG$nO77Xi58`v#f5qP=M6&|sYZtw2R0X05?+CXk>X*`mFuqiZNwK8^Pz_F% zqCOmvUKxT<W~L8<`my4J``F9adyt%tqZ@lLTNSWyVI1cZM;}WBe@Ez(L7$I^B(VUC zq)+U`jHED;#3B%ms!+HSATh!PIFTb55<zsD!B;SUM<T#tKMcA~xh)nhFAD`GCpPdu zU*0*DW^P!r_~Q3WlWOXvcchQ2BT2!vB+>TX+nuo`^ObsCO<?}3FRYGCoSih;J)H0- zm>4p1h7*o?Y)!RySi1GABYLxrRX~;B>`>9=zNUa{_ern|RNmHR0Pw!fX&&S3*+xOz zYFxLurflc<#VMuo7`)i&S1If26>6WO%&$_EmnoJ0VZm{J&t%iMI@+i-`C|V5=MAbG zZ{&PU^s^60HdkYraZkv(QCnW=Y*aP8xa-kLj#`&XuZal31(9i{4#LwazbhpfMO)BX zm#~nB2xW9ULBh#NsJw{V2TQeBs7I2n*ccCm(LkjKgliHvEOCTnIfdNTE*hO@@ESlE zC2;l44pf8c@Z2fNh5OgiFi|_<x~EM&;hNhXstNU&brGNI=Wloe4NV$Wf0s0Hx0ZG2 z>+bm1lRlUJfXZ0C@wd|7_b&}qM;WChzyT#E=+-<5=o2=#n;8cxMp)Kvt&UhsYXob& zz57D#lAij7CiiU6Vs>z>$;2t_Cefxq0z0d)XJ|#(&a7R_X>V<s<&3NlyVk;A#4HJK zr&H_Go5s0%ul`klZ8Z5beWtR-I#b9DG@zkmd<WEwYz!9m4T}=WGgFp|(>#J*(;p+; zaNvqRpy~WZUKeiY*|ufXwCVk8X3c18F<Ty9oJ@wpY)ZQ1@6ttA27*@iw9m&GMW?+X z8jr7o&fmG>iRm-Oz?uujvQLQ-HZi}<>uHV}O$7?nQFh7|3+G3J<!TKOq)+bEl$Y0! z>%G)ytg3GBn9<YG3_dJw(o0V?S&e0`6(D>9_|Iu>uBx!!BdwoNT@?tLOuUX^N3{uk zIteoz@t376V=tlM7Y3blw_3-mr8{&=l_`sXh!#l(DWz6}ltC03;vju0=l4Ou44WoC zxUz3a9_BfbjopHod_HD_4lKpFgB3bP6i*Q+Yi1~904Q@QWytbx0a`)P8IorXsXvF) zZ<PT;6cjE&Nul7-$Y(6)Ne!}mU^JJ`<|*5bM<V=V=ASe!LP@FMKGYQ7;g!WzKn;}l zncsxkGen{hv)u{{$9^9TV_E4Izh|<-k~v;MjvH4dDzus`?56PC%To1==XbTwniV~E z(+!(8K00a5fUkD>s)^f|Ha5=mcO8=6Eq8Us<G~(!>Xat{jb`qy-MgRnc)UJzz<&PT zk;5*R&({@5_C%L%y5#4~#qCq4cE$w_chmZHm9&9ow8gx6G@8>jGOKmaNEoNGTljEh zKK|oU!`ra?6%;btmcm;2-<b<wEVF(1lilzp`oiJ&;T^I)2V?27dx$?|8It^_qcsOb zHN?rh#bmdvJiE!AT!!Z)fsXBXc}W)YVPeO_0g%`O9($X*v8w?N;8u_?B>RChSin0T ztJPxxCp{L6$2xqfs;zZ?TN^VoSv$3De%qn8>Z&#{C6a`XtxFBBNUfi!(CQSEmc6-b zl0v6dfTQ?&TUB)%Q*Ooi$p2n#tCD6{x3yJ+$Ew=I%&JK8&-m!i@^3N%Zv{6cUf8zn zg~UFcg46D=s@kvR6uQh!xx1=cThaWgL2dCb!V99Od_VzAAOPyYMDQuWIq_rKsRk<- zQlLtK5Ed;J93Iy@=r#~S0&@o)YQ)M45XNc=bP>y)WCjeyv+4^x_@mh%ftKUwG-oyW zBd8mrt04~aG~rQ9L4uU54Hk|Bm6EBK#&ZIVrwSnRu%Ou^B+nFRTEzh#Jl2q4@fQiR zR-D3uli>HD2b?VNlAB%797humn#$45B)%SJMr^EcJT*l-kbIBJW42fu6dYP=;u<mX z3>I!gq5wyRK2s-X#7jg!kCrFskrtdmLmapuE({=mDKvp+Qt)(GZU~$|ZUQ2R$4CKD zZZ2A3!g=BXVl5ZZeTDEvqV+<xPRO%nlt9cVvS}^&AvDPrwGeL9Y{uDkcCqkgjf!DK zb_t_b+my6)8^f?Ptx#}`kpU0_NY6_!NW4X2t_rB9_-)<=UQO7o2O5=G(CGm0vs)O( zqzUU=IVESY2g}qN0m&LhyT!0h0IEtm4SZ$JatKsLg_>hD3L^j}o6!V-MWqY_9joRo zYNw?x0jr!IR;6KSmDV&_RpYS7)c_dmRmPCd>$K<~<T#B&N0-fvTg+7!8o0`Jf_0`6 z0#0f6Fpy(dCJ<pO7}J9)1MPMxtN2Km(Q$w_sUtfsud!;h5IvGJ(^d$L(4r53o*9|D zXbq==w3?<hG`I(<j2x?CIY{$Wf=ct0T1)c^2zf@?#Oi3hO2yI;s3F5Bc_lFLFk!Ml zh0Pjtgp{FWWyVz@!K(JTYUYd6Of?e&(X#S;lVUPZZDZ9w0MPKQ=I0w-Hgn7q^{I3M z)Upil(X`KWncudu%UWGc3nul>alN$~1`T|IOQ8%}LZ%COEdv|-!d<bof#&fnk{wng z7U_`)qES1Yai8E6R6MkV1cOObH=R?_+CDipP80Tcy)+May~E&S&IcmkP*s4Q*628C zHc%Q_R;h--pr)1hbwlY^!KSx64drT|qM99dp~=*F_tpx?)LtA3x48u^=$P#aSj=5M zCG7&Bp%KvCc2TcjlB}!3tfG~B^eUQBG<O5g?AF(~A+1q?a?#=fRRKoNYpsBHuu7|5 z1E3LTRYn!hp_0&?n-Li#l`@Rp3V_xi>Q#&ivMj^V3c$BHw3-gLidNV=$Mu$T4>k*{ zls2=wv#d-6Y}ff(4`V%`(nl(2eQSNh)~hrqA*)g}8uXJwN-kpWv6cgItH-=%kwXZ2 zG<22G0ilWodecvp3YwwSoB}{Yf&s#i#;62<1AuYT>_?DOLOsywI7Y{EG-@`$eEp)< zZnap9CY`{DQ=A5cpenbZZj4@1na2)5n+|nrtx;oLpfQXK22@%`E%<zsy(X5{>8m)K z)}qn(@<tVBS8^Vn=4u+d!p0vpPVuR121_|+VqX>SHC@-Z@#p94sy2giXVsm(%eHS? z)B4(i`iT_~`huv@m7=zs4f1mn6Lxn^WWDu%JF1plqnR>M>yEmd8hrt;FGcZ`2g%kE zs)6dD=3}p)V2Ji(!#U<aqeEfFi)U!7Oy!J55;RPB*pLE`aKNXCvv_Vt2aFgB<GaXM z(g7M=j5R*O!@p`dgogNyd#?2BpZ#!uyV)cCQaTD2_BGsaXjdr62&;EoawzQq5&G>n zezBl(!;Qm#M-w`n`P^62X71ZE{^E&k`uFG~KxOKgx_i7`gep2PeL`<rtlFi%xMXb> zz;|-y=?ku%t~m;CsP8ye!C&(3qD8kY?d5fV{m-}V>-zlWPutv|zCZOZ^aTK1f3NuP zn~w4EHnZgW;Cn!8Pc~03i&b$})V*l5VqoEmW8q6?+pmLKiq|9&x(;B5;b;RP*Uhp> zLmaQ_#)}ZMOiG-yS#&^|7!3UdFp*wDR^MZEJ;ownY(3_taLdB!^#iW5DnWm^y0;=w z<EU%i_-KD`YC}(G%KWw?=U6;_UC~+fRSo40(f@g9@)aAp!Mb<v+&eIR@^#XwA8s)8 zWe)(055Vsl=EQ4k8k<64FgT3UZC;-(S({iCad&Q*+`hOi$OkOEsUjTp)Yf|1YM1N_ zPS|$%&UgC^8-57b>n2Yh*ef4Mr|?0(4HzQZx5@Y`IrI~&3QuJ@*aC|iM2VBF3C+92 zOjVB;0a^SLH$Xq^OPLdmH^(w3Vlg;1b~FZ5(&m#@&8?L?s;a<ISCA`f3&V9Vws!~5 zXF^630|l+LhUa(cYWQK;p|65e{$BJGlfINTovf<dS<%{3g_$XtO1O@W9fj>X^i}#y zNDrVE9Mf0vJM{Wt*r^|(e;~fh!BO6mXTfR3c3&bRgQ2WNG=DT0a(qop9xVDzGsK=c zOc5e^NGzqqUP|+YM4>!CBTKPE1W8l2@`P!>S+tl<C94Y5fy9`f&N9f6cx=?{xi}o` z{1GkxbM2R^kR#n48H{wN9U;}1wSO*;Rx}v^HF-5it)2`hgVew8`}_8N9}HDARfBo^ zrStWIBP4x>DV%{J<Ph}Ww*As0)lC)UHjrAkPD<J6etg3|xvUH>Ymj)yW`$e-8Mbnp z<#E!eroN_R_mXb%hxRx2!BpQyX^51DPD(O&U;pq%Qj*uCad=A~mI!Vk80_1)5xiU| zM^69c#Xj*JSVfRy+Ji`pvRDJfiXIj$H5kk5D(1J_0&T4UTl@UVNV(C#EG!vRJ_NtB zOzC$!kc3iEQRV{<cmEX2wPTD6HE2EYCVLw7qsdr@N=W3;AkfeOf@mngv1j2RiF;;= zt8Ora-72wMnFtcUT{eL~i6Ft!VTp6B)xxG1-}csrZ{4<7-hd5^L3&%K=cTuwQhU@- zNpJIdo%FVWVO38(rD7Qa2%w7~@RZ7@dI|*4MG(kdgqlJ&XcN=3{n9H2wVGS{l}`87 zQckTlfQEinZ`6MEmCk^!f(H4jRx4kXUO`t4y05;{X4iT@VlSlx)I+Ht9?S4h#zC2I zJP;&Ixr8S)9w4GIhS|W*yhQS5K8ZIyE&b}LfnT0p^~lG252Hykv{br$=yptdyX6HS z+)`r{yz>_y`TE9-F06F(ioc@T#Gg*z*Csvoo4p@DvTE1QUi!zyuYj`KZvoa{@8)1- zrF+J!TW<XNNK|n16*9&cm(JRZt4RbP{)EW~T&iUl6>pL(LbQOZioalV<!f?<!`xi= z%P@S@FhScOR!(q#0Skj*X?RW#a{X+Y>ZT@<=(uXM;Kd^$?gl)AO_II{tjp0sc7iN% zMJq6d@%P~-NIhAg9^l2n{ak;@G1T*#C<<}m=d3B&y?k6Mdj8~AUjK}#%qEJo@mDP} z<i>F^)F>XOryUm?L*nrvhcqFR`T<b?0G`trdSv_SVxuUEFR+G6j{}3WIm2Nc|Ek#_ z#7uwQJcuh6l5do=k$w-U%YX0#^nsr~O##JjW+HV3@wMaRwVO5ShDZW{XmQ7KAv7b> zNG7nF2$6@M!*z_%XkkSVY>=daXGZ+%q8kz&3_)}tODx=1&^pFMP+73H4q&|=T8khV z1X_b=-J;lSJ#MR<p*6aVNh~K^(|{Ht%Bs+5%9b>lTz$=5Hd<{H^+3Tef`7}zqnpmP z+138_1J|^1G^4Kqg4V*a2BoP{ZzzvfSCr`>C#cjc<Q1H~O(z)5vG320nVd+bM{+!8 z<duT2sw3D|#~?`@awawKgc~^etK|Eh*h+V0g}EISV&6HeKIF19tVydi&mUi>1gy<J zzFKeRSdnHbyLxOkb;Y%VfV;+EVL1`Wm<+8kH>@iwZ(CSj#sX!aWngkew@&L*L5rwy zK%ixfZf{HDqL8M;SLaqi#!<bvV_>IRPtySXgREX9a~MC&eaTLx)MV7Fqvla-s7uio znO_HEzGAYA7M<1{_9kl9U<3rv`VD`KiFhE0*1Bk9#4)b|I>d`W7j_K8hHv!gk_9Dn zfh>4u9IYwkg=CPNBd5Z6K`SrI;XT;AI>T%cdS`7_s&st0!sy~%Cu;v|!@5~@b+518 zunesX2c^?T{v`c@R}BJi<WC?7LQ@X^M9N6-OaJrM-m6j%fkjigY8j5#bKF(`8L6#> zEU(r!FX`Pn*Dflnt*Bt8g`Ku4hIQE5z`O;~u&N>MP?iNcIv!n6Hcsm<+x7XdZ-Sn8 zczxqN&f9cOmeuIoJgZr{sz2a+ZrQm@oaHCl`fr@TTR%P`Z?5gVZr?yh&-Q25Zvjl| zp(~~&ujjR>8^G4~&Mi7#gL+iU8n|rft|s(!REExe9eTR0lGV-Z&unozga+sAr+UZ7 z1kT-5$2q3v{CxWrDdrfZLZf9F6+$Csi#%qA(JI>oXrl=#Ff$~JMJ6<68ZBVt#d-`1 zh24C}MT!nyeAP8OmLIa)4@pm6e;J_R4^pY?pM0LKD4c)#$mN$`Mt5Cy{gXch^gTU2 z?N6*;{RI82^x%`y?<XAl#fxCvEysTG%cB!O#ZzFOceth`#jP*=?Dm@_buNKNdhP!K z7fY+P0C?JCU}RumU}k8(kY?%>&u{aUft#HH1kT>Gxd@~G|Nqax-oOUpaxgG~C;(^V z4C(*?0C?JCU}RumWB7NMfq}i@KM=4tFaSl60b>gQsZ$4Y0C?JkRJ~5bFbsB^q>+FM z78V#lh=GAy_!DDa05(P>!~-BC!~j#olkrgO@cCjlPVP=r`sCKJ9s9Fgm*|!7^bbVc zcSfXDIAAcc2f74M2C?rY<U^KxX8pULrF>-H!JP3sBd{*jXTS&aFKRQW4`qAk4uX8c z_d;#ff&F}rJ+YmW@A>W$hjm*)^E5Wz+#mmg<l?DFTW_p&pTXvC&WD~l<arIeZ>nt# zCW&*+h($k!G;{Z9xd}Dzd!gw?6)%}OGMAIBd1!br_mfM8htiX|ZYwp{P|nYt<w$Fx zDrR5hya|c+rS8!5eoy2Z^qtuFc9wwMD(^&xQF(82^wP^d(bNlXs`E{*ct5N5F6A8B znTe+UU^tD2vrzV`^e2@Z5o-aA=)oNWxh;VCTkr6x?ESop#|`hs);D{oablhm-oFvw z3-RrdW3QZud}5w}XZQyO?7Kl?!+zBL#Jht$UDt2nWk+{kbzMEDH>$_Ij`81qnciKw zFGz>^NOZKE6{6cfGP8+J7|<^<D9ry1IOG{Lb2WvuT8G?wFaKc25I%LE)oy!e_9>YE z5bV!IavzRk`u(+gnx8)a?q!Jp0C?JCU|<j<1IjT3Fic{&!sx_Uz_^Zyfysthg}I5v zgXJ8{FIF4YWvqYLLfDS5r?LOx2;rE-@qp8Va|P!=t{|=nT(`J&xM%UW@Ko@e;x*%q z;a$S#!ncB7jNgZUnLva<m%t-IEx}bnE<)RcD?}_rrigqH^%7ko<|lSQ+(<l4e3SS$ z2^EO|i5Zdtl6{gtq!OeiNL`a=lU9-rlP-~7BK=B6O2$W~OlFD92U!)_I@tqqT5?VD zO!67>d*uHqm?`8btWbEQsHRw^cuet+l7v!$(jH|s<r&J4R4h~us0yg2sVS)KQTwBw zpx&dtM?*`aNn@GD8%-t62+cKGJX%g#%e47)@^qf)R_Tf8S?NvE`=IZj-=Y7^z{OyV zVV&V4qa33L#zMwH#%D~VOzcedn0zy}Fr8z@U>0V!#$3sKlSP2V1IrrAQ&wVDNmd(d z_u28;<=9QLdte`Af5RciVV1)c$4yQWP8Cj%oEe;5oY%QTxx90o=2ql(#ofhylZTwg zI!`yxMV<#d?|J_5lJfHLYVexpwZ~h;JH~sRkC)F0UoGE#zCZjj{NDJx`JV`o2*?W9 z7w8hWDezs8QBYRUiD09UGhrNIlfr(5`-E47ABhl%h>2Jc@g>qBGAnXQ<i5xkQ3g?U zQG23UqRpZwMZb#)iz$iO5o;D(5&J04A+96tTYO6Vp#+sgw#1esjiijE3&}>w4auvL z|E1)l+N4fNy_Uw6R+4rnohN--`m>CPj0qWEGLtelWj@GK$V$jsl=UcEDBB`?Q}(MI zpPUIfmvS9)%W}`;{>yXAtH@iC_blHgzajrpfk;7I!HR-Ug;j-@ib9Ik6!R5#mFShM zD!EpwQ@Wx|scccXQu%@kxr!x~8dVn62GwQN7itu0(rPx<^3^)kmefhq9jN<N?^Rz? zKd=5o{ig=6hN6Za&Bt2OT3)pJwa#dL*JjjK)b^s?qP?d5S;v~ry3R*12mk<%9Yg>C z0C?JCU}RumY-f^W5MclTCLm@6LIws0FrNVc6$1eM0C?JMkjqZOKoo}m5xfwiD??m1 z#<*~SZH+Nu2P$4dgdjn;<x(L^A#J_jWB33rT=*cabm!71@HzZ@Iz=#KGH1T?&&+?$ z41g89A_bMs0I)e@R>(4oc@C>M(VW5t8k*DC!lUMSY~n@p0`I<SUZnfC<|VAFC(RkG zsb|g0*j8_vKaf>lnm=KxA6(!RWf-Vnhz>kb2?MSnsf-?4q6UlxEaW(o{Q@4S2F&_g zYn<1(!z~>6JX66r>U1ceh&;18wIf`iO0G#Z%f<NT(_rRvw<o6!?6L!!(<IxB7M0mf zRXTL&5qIu0y5eQ<<UnFqb`F>gG2%{-b-VKJ=uV52RCT%f6L;M44~5hnw5j%`-y3QU z)lmGJe8-=Q$2HVH8t@GzagAK2J3pkuz0^4-d2}C1Um^R<V}~QD?@ZmxNu^6tbD~2_ zek)Sj%+A=6C#o&cq~jj;8Et0cKm7%1;%L?Y0C?JMR|Rw=#}VCMJIlL*Gjq&r>!iEW zo%zhnOyhyxow=Qvo*R&~3ZoNq9EX{inVH#PW(J2jajJV}1uxN)x~h5_s;htfYE`JB ze;!<}TwnP=Ke$yj6{=K0mAfjpS8l7^S-A&Q7^tC+2AXK0jSjl#VFHttJ1X~9?#2|R zu>reaSL}w}u?P0VUf3J^U|;Nq{c!*uf&+074#puk6o=t(9DyTo6pqF*I2Om@c+6lU zW-*6N*o-Zh$5w2^2{;ia;bfeGQ*j!$<8+*XGjSHq#yL0_=iz)@fD3UEF2*Ie6qn(0 zT!AZb6|TlLxE9ypdfb2;aT9KaiCbX7h65J@eGK5i#|{h;AVdU-7&|Kyl?N(4BuJ4V z#{w3ygb|kUP&^C|$0P7aJPMD-WAIo!4v)tZa4VjOC*d~SjyrHC?!w);2T#Vmcna>r zQ}HxB9nZis@hm(W&%tx?JUkySzzgvrycjRROYt(i9IwDD@hZF;ufc2aI=milz#H)< zycuu7Tk$r$9q+(9@h-d@@4<WVKD-|vzz6Xmd>9|WNAWRy9G}1^@hN;7pTTGGIeZ>p zz!z~pzJxF1EBGqDhOgrr_$I!EZ{s`oF20BF;|KU5euN+6C-^CThM(gX_$7XYU*k9U zEgrz{@O%6Lf5e~gXZ!_!#ozFE`~&~QzwmGT2M<z(KtxqCs77^aP?K8JrVe$fM-wzj zQ#4H*XcyX*cB9>CkIF%`C+$Uh(>}B>?MM650rU_$kPf1Q=@2@U4x_{A2s)CEqNC{; zI+l*3<7tLA(k#u<CfZC}Xr8vxHadY$q?71mI)zT9(`Y-LPG``WbQYaW=g_%y9-U7Y z(1mmnT}+qIrF0oxPFK*CbQN7q*U+_e9bHd1(2aBx-ApFkLKfMT`^h1f1ode^9{IF` zh7?dp5lM<^Cnc0pMma51?rY?cKQps^M#<TknX%kh%GpxRm2y)lH<xltDd$VMwUpaR zxxJ9HXBTp_mS^!kwLxH|X)VlC->Ij<N*u2#q6HDiSkyeWGb7Ecq^%lLgmE@9@>C>7 z-w(oO=9z(&3<PCfL+O5+ksQ_&5y}P8Se7z0{ivy>%(JTO_v@)Yh^(OM$U!Yjtkg3+ z8Hy&aCQK{HjLZ*(kx0w!x^giJSW(^0u~E-sC2D?T%cV{nSR>Q%6DJV7XDqC&k%)dG zQm?68(F+FB85;e-8npQ^ZtTfOr0oS6<e@OxpH8W&4O*q1$Mv0wBVEz3EiJ2=H8A)u zHEbz|P1S@}GOWdkA7ypN3PoZWeHmr^J#g!OW(B^}$;47-dcq%gSzGIizMFY%{x*or zK=iY2p*kYUMA9jYL=Ep1`i?x!{Qk&LXX*Hn%j1f9rLM<L^esoIsF@4CD`X?~oh(m8 zJr<GU2kp>`P35ad>Xxe(<Os8$!u7LS>RE}XIiBDMsSE3+nTSo>a)ygm;`aI$hj45) z$BLnXUW+XT0RuzEjlN7&e^(D58+xVEsEHlI$-2DHLL!Tk_r``kLMsmP)KtJ|hkjJ5 zodQH!Z^)sRy`8z>knlWZwfv|ri)pEo2oa^8%zEXt0u?QuSZHnAipHvyByv&v(J55z zMYGWJxcsgWp+lr_#O|d2vM~F35OhmD4Xq%U5=%~Ch1QB&#=!40?1a_l97#k|j2LKq z8!e?cflNi0qZ0YiKo75RJR{L`tUyGrmDCd}a%I?XWEk=t*F$R%iL5=2S01m#QTfMk z&lZKqdVKUaR!cgZu-!hRP$b1>ozhS)OqPx>h$QoQ$LZ4cWa2L~e666xh&LTiEs`zz z8RN1DyaJhmy|%gq;!WN>k=3CX8Jx{&vvfJ_WnLcIDf_AdH(6TBU1hg4k$6_n?`U=@ zIHjT1Ws2wpel%oo7NKm!dFt`8dYnBXVcIa&XH6k~ROiiOZ`2w1yn|ifpkN2JO)X#? zaBx+=cQnL{jV8v)TbOM<pxCTDaC3atda-gnj}(V=7-F0>D!^_vNz<z5a#AoFICzm^ ziy-JYDy)4DY$n<sUt@`GttzxNw3f$3j|#|ifk<-|ksH?a=mjR%b>;E;NopD9aA}MB zV!}D^)iNs`rgdgiK1|C_e9?ETRJ0Xxi#(|f5}C(_ie-&4lDl<VSj-SrC(rmQV~&ay zYy9}Jky;C)t>R<a4AdbbP9}^e$^()CGe+VMMdtB>1Fw}cFD1OJU?1#2)EK<J!!(~e z!xmp7`@`uwv7+g)PYt9T@M%^!ptGi<#&;-2ZH~Ff^hukA%1K%%I*AKa$BOfYDLhJz zR3;2HZi+n78Yj=Vvgx8S#+t!?O9sq<@$Yg;vL)Yfr-ZW_*&Rb$R}|*>jPaTY=GG=- zJK?*xm=T%t+JSPyWLVfu<^{gzftb)CHpdmLTbKn>8>*C=q1)lPnI}^YzG$YopQ#&b zDp08%>kbzxA-KXwW@S|=bvaQ-uya4)6AYR>IaYP2Wre)E6*;0F3U}ydoxXC3ciAD> zb-{JOD`=`e(-+gO%xwjwNJU)ZZ(UD;zja-Vzjd}cS9^7SXU)Xsct(45Xu}ohkjq9r zuwo@NP_k|)ZFMf4jolL88gK2Lxy;I?3$?gsK5Z27VT!ReuKvNOT~YxDW@;@3Y8qNY zgUW7;rC4QQal3qhaWSrzhU`eK&#4tvL*X?B%yqHlHksx$E}H5sp+-(<MN<o-*==%+ zxq4ZFp<WCv?GO(OCRg~bBp@b}qFCtsH5_KKmYSl<<xr6gqtY;E=eKp%RF+Pfb4GId z`Z2>gw+oGjZJq1J`SP-goi7~01yn7l!Z@+2n)>18`66&9#)YQvW?GdflhMQ&%Kg;i zh$c*SLKU7R$7O;lt4%t7v}{<{QxeqLE=5plZB0;K76zLQCr#(-j7_G@cEPG8h?$wV zI_|=F_v6%0*A%4bmA-M&GR(P|xt4zVsrBpJ$^K5Pz8rM9E+}7jHUq&)uV7dx8nMN9 z{fyAGu2aIC+c?`UO1`cLoc5g7s<IUTSw#v%SB;*piae<f?6{hzZq<*H>W+9+b)r#q zm@HQ9%u&x|(OSvbDa}K+0!HjvHfN+cH@j`aN^iz=YUi0qcmLlmb*$dFTXXRAI!kkt zIXAaSHJiI5uBN$N9;7skCBEj?()j7IGDZcn;WAkGQO%UjFTF8&@f(ZnL1KmVKEG*) zN!4<hIyTO4oUr}O&Q<8kYhWe}l1?FX*JL1hqtz<aTVv<(+OG;%Q)}!Z#TWURD;LuS zr)eU6x5kN)FR`1xt!hg;9K~GJWS*oubG|Wt4lq<?z0b592tzfhfM<SOO>=d%TedXR wKR5n@sM`5}7KXJ&;oFk`aftYr2h7i^W==Jm{tIe%siXh^0003|xQtN%02oC%ivR!s literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/bg/bg-box-comment.png b/src/static/movio/templates/Movio/img/bg/bg-box-comment.png new file mode 100644 index 0000000000000000000000000000000000000000..307e234b4648d65d191a3595b13c748264262096 GIT binary patch literal 1126 zcmV-s1eyDZP)<h;3K|Lk000e1NJLTq001cf001fo1^@s6F7$F(00004b3#c}2nYxW zd<bNS00009a7bBm000W>000W>0fLJSS^xk57<5HgbVG7wVRUJ4ZXi@?ZDjy4G%YYT zEiy1MGnHI3LjV8(9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00X*7L_t(oh0R#OPU|oboEXc5rr?4KCk_b2ng9O@4txR!gv5cS4VJMi_Z_Ou+c<XG z(iS=rQW_j*GP^r#yZHS4TmnD{0YV6b5D-GZ5QGqe|KAl-N_g)frKH~y{O=gxy>CS` z#z2M;;GFBJ<GlxfBys+gd>ma9av#l~Pl3-JLV(a(7XV<4fpe}ikPqer_zU6)un=uT zBL1-WHvk9#&{`KHEhn0qIEN^Q2FIr6%tcNJfi}iO)LJ{JT<S~tJ-Vhj_*|)bF=CNI z2q@w~bzLt3pe#!$rIHiHImK0Ydwavn%gdlc#QA%5b%pEeYdkzW^xk8PLC;GlN4@uO z&LwjuCP;bdy~pe8YfF&qEdK4B>)e~oX88E{NGcpc=#%6`t+h#_L@uSuY&PqSCFe-_ ztCSMf+V;6rK4)FIs;V{>LI{JFG=v;6npX(1cFw`pp|vi&_psJ>h;pPnkLM#@6WREK zt+lHP&UCR(bq^5@A;1`uEQXxf1AtNrQpz4N-h%0Qs_Kn%GREcQW$UAq+_?~i5TKNT zbFP!mR9wzElw}DaMAnlzHd2zHwJwxWn9t`~k0X-adyGb-&O(8rp_FQ)!gDj%2sT!d zP*qhyYUB+0=H{kDgnO-0szXQ!0q;G85SUCR0Q%wHN=X8@r?}HdDRF;)kI7`xQHea4 zznJn{N{Q)oio3hJWC|ra&ZemAdMSi}QmU;?zHpFI;{E*{&(F_r&OvL9+uK__K0anw zQT$oDPIjD4K~-<9?YxApz4s`~vMm@+kO;)xDxL@UK~AQK0zlI=Em<NUrNnqV#>vSE zo}QjM3Z@p>Ikyl({5;$obzLt*2pEk<ZK3dxPp8vlIM=~@kEUt%LlOYKzP^^$T3lRQ z^!hnDLT*(xL~^H`j8RopQI;i|rdjPvqHt1i4S8$|JLhDID0v@Q4mb2|LQVLQPp*U3 zx{y-B7z1NWdw*L6342$PK#G!)@3K`sh>`^I(WYtIdp{w2FeM4Jxtq`D0J<A7!p2+L zLxL0~qB#>ETKONGB(PeKQZezixG8>xB+y-t#*5u`#r10>0pRTHtW|W~$sNbu+Tu1? zEEY>(WiPZ3N`ZR!uPRA6KR@prK*Ypi{0T{5MU?hFe3k!a)ty6CRYiR4!qIMj|A1Qu zsq;~8_y=u^+kiS#(=@$qbQDSwwARIVJZ|^(yfYmQNdP!KJ?-r4fj#bV_Kn42v7|!; s@BML-1pc2mODT_+<oEaYk`~VY05ZYgx%Y%9HUIzs07*qoM6N<$f`Z5U^Z)<= literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/bg/bg-box-link.png b/src/static/movio/templates/Movio/img/bg/bg-box-link.png new file mode 100644 index 0000000000000000000000000000000000000000..ac1ae4fdc82a0a47952417f64566e69db5fd6990 GIT binary patch literal 1263 zcmV<L1Q7d)P)<h;3K|Lk000e1NJLTq001cf001fo1^@s6F7$F(00004b3#c}2nYxW zd<bNS00009a7bBm000W>000W>0fLJSS^xk57<5HgbVG7wVRUJ4ZXi@?ZDjy4G%YYT zEiy1MGnHI3LjV8(9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00cuxL_t(oh0U13OEO&)haZQ_Fo>BYB8Y^9=AxZ%NVI6xU)@3^BBDizw6vg&>5!8S zgAC)vc^7_nnz89EYt-+zF|oP#;dkyi_nb++y}kLGrXi(do03u@gg{D(rfC3Znuf0H z2q6Rj`}_ObWDFp~e@iKGT^DU<XD78)y8oo0fJjuQ(<vIj&dyHCvMi*OYYY4Gy30Ue zCk?|0{!iES1tdT|pHJDg9kDz~#jU#xxC}0YU_PHC!VBf|`P67M^0V1&qJYbA0IutD zeSM8(S?Ib>v)QCnDt&k+;$#@qvaG}*Vd0Dr0^7D}x7%2jg<%-DuFK8M4gG%qgR4N) zNu^@37;#jEDhWA`L%ZF^aUAOPI`w)T*LAtPyyX7=9)N>`gJ9nvapIKE=TqbHI59XO zL=a-faX3Cc=Fgu$WHK3Yxf~Z47mUYay4`LhiG&cJLjn{Eg_LdEi6oJf62maCEQ?Gg zL#<Ye{GQEbNvG4;wjFs!)3kp>LUN7@A@DqpbUIC~R-@bP(rUE=*KTibky27Fmm|l^ z^SrMiVd3ac>!_3x$8my8y|}pG<>iH5uSX`6VLqSJZnx?8`;^ONn$2eLoJzEnZky3) z<g4p5d~V{vgb+B6!_CbNrfFgr2IuGJJUl!w7!0UXDhMIy^?J<bbIRp1XJ=>Vx*j|~ zolX}aUj<T?r_bC}PAkB6yNzj@WV2b0kB_;(zh^KQP%4#ZG#b3Vz5-CKRyjRAMc4Jn zdg*i;DdlQTDh-E2e}8}fgOdtyJRWm(b%pD?R4Nr3jRtpjcRW2k1%SC+ZgJi;Em+5O z-5|uu2*+_&b5f~TECyL0clUNW9c<gCQmN2vHWy_?)2LRf<nwv1uCDMrFXEi%d67Fi z4EiHT_?Y$K*2*+ZfJhRYoSblSa>C=|V{jEN_mJwl=Xt=Q(fD?Df2MF9RU2rUMmn8F z(=>X$UL;FZAwN1g!t=ZUQ2nl?99FgUSCH`DJ*h=ivmk`v?(UA~=VzwVDXmtEe!tJb z!2!)?^Fxxv-Py3{&J$~RRe4gInWoA0^)<F_qw6~J`JBVULmG`n&{QltxGYs;6Ya|T z{k~r)6oQRS)1=esFdmPCELWSWB>Ae|CJqTOnM{0L*D(y^L+HXVaWl<lkiR~Y%i7)D zO{tqA98T2*#esa)3MLK-?>CbwCGcJc!<FDWfNO(<MZup=r@?oX&0i%;oYn>ju(!7t z8Aaj-t+*qwthGYIBJ_^q1jSpyDbTnC+c+dF992DK*hQtdMkTC`K*I0l`i()t*Zt^c z+9)LaY_8upB*gcl|I$_<VYMlAYmo5$xqhpVko=pHwd(Ed&7aL?{%kh$ecum0N28Iy zbtjcn!B+}5ApaXkSb#3iOe?<}*o2m6rbK6)q%|B4{cJY-^EViq(quC6lYD`@HcciI Z|1X_!&wiSH30MFC002ovPDHLkV1i{TQ~m$| literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/bg/bg-box.png b/src/static/movio/templates/Movio/img/bg/bg-box.png new file mode 100644 index 0000000000000000000000000000000000000000..f54bbaf2212814e8b8021699fac05f6cf2d14d20 GIT binary patch literal 800 zcmV+*1K<3KP)<h;3K|Lk000e1NJLTq001cf001fo1^@s6F7$F(00004b3#c}2nYxW zd<bNS00009a7bBm000WZ000WZ0W>Kjs{jB19&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gH7+r$A4ux}000<tMObu0a%Ew3X>V>IRB3Hx05LQzFg7hRFflWgTr)!e z00MMLL_t(oh0U1Vj;b&eg};`D7!xr{CMLfByBROQpBQ4W&~w3QEr=s1$gG=j9BsbY zKdXBq4u^x0QlhnHN@=Z8N};tzN(q3Jk}wQWN+|%=>-Ch34$^<EwdQ)gA{UE=n3V3n zEEG`7YL;b4fW=}V(lkYDJzCnE=Qe@-NX}+6_qi|(D@cGij>Y+Wu7!L^HO~!#p!U8} z3S$faMNzo-%Ch7k)k%_=D2i$a456|t5keqD_v&&r+5AHs$0AMB!QiZ<l)V6LG=WD* zfX!wj&gb)}HQGf=se9wJDUM@tJRZNvRFhw`Pay$*etuj;r;s)FUm;=oh~|0z8WO6A zj_spOS>Jq_ZeL^jsIQ_ZT+{S|gu6YB9ZhTM^ZC50%f1JU<)c<*S-N|?bK|tB%}4Ej zKLjMy2adNO;j!!c+$PUtj6o?yp65U{XykeRcz5^JkavAi6wbt<YR+G8oUXE6Zx8)M zK@dEg@per%<=fMzpv`Q&)!ok&$FbP$c0(Ok(_oMQ+wE3lS;qBx?e#r>ENj!CkO0f& zQe;`yns(o&{I$VvmNpFz33tP{R-(18tV9Ust+sx<IKn89P#J!fW$yPd3<2EG&_|;| z0<2c6+7;T|5S3D$>UUH~s8WBqT*&jhwi#N`*=+XGwnm49Dx#OmrFPf*DR1*eUtfWQ z&*ssuLBjj<=vN`(y?ONOkkEgxp9B*6ZK0DvLifFXQb?G7ukWS9;b3mJo4MU?#u(#% zCP`u@kEE3~d@Fwd`7@AEf%;wV9`sKQ)>Lz6l2U%YEsmxAes7{ELTmkZApuUOlNs`n e_-HzvPUau0G^Ak#XRj6j0000<MNUMnLSTY$f^Js; literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/bg/bg-description.png b/src/static/movio/templates/Movio/img/bg/bg-description.png new file mode 100644 index 0000000000000000000000000000000000000000..fae27607a8a20104f6d3d5c489ff54bc755a5f05 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blmSQK*5Dp-y;YjHK@;M7UB8wRq zxP?HN@zUM8KR`jb64!{5;QX|b^2DN42FH~Aq*MjB%%art{G#k)1?ON>J;T-V9<PBa z#X%~ai&7IyGV}8kLNaqx87y=S%yo?n42>^OZp{QL;q`QJ4B?oWY+z<)$IQSqhcWH+ SnG|iH1cRrmpUXO@geCx@8!hqx literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/ico/alert-error.png b/src/static/movio/templates/Movio/img/ico/alert-error.png new file mode 100644 index 0000000000000000000000000000000000000000..b2e8b957f30efe4892854be097591f71b5a2ac54 GIT binary patch literal 1454 zcmV;f1yTBmP)<h;3K|Lk000e1NJLTq001li001Tk1^@s6zaM#L00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy5G%YYT zEiy1MGk$A`KmY&$9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00ja`L_t(oh0U35Xj5kt$A7o2owbcjHt}sR2ClR+Ww3n_>W49P6PbcIP`WP*?$b7u zGPZ#Oi`2a#qE+eYONZ5}owMuIy5ZU(tE*JBSU084;tR7)o3^n{ZeDDYd-fssiOG_* zd9!-p4+;02^Zatoea^j43mG;M$q|t^MC8>>=gz2!h($z>h{!#8WSt_i=Sj0gnF-sb zD93JI7yrL^!noyVrq;^IP@ZaFap3-4+*R8#90LGkzwjajWn0kl^4E*VZB5g@NOvJE z-2@`C6!=X%Zk!dLhG3QD6fVG0Ru13=7HOK+oz8k$=>(fr2H<OH!WgoHNQC@1uQS?q z9v~0cn(kt00gK26V1+Sc$JcxY5s4|!>3YQD23T))Wb%PUBnPv)o>TQ09(P>ez@Qy( z^BEOd_C$bzoj~!}&A;(o_#H8fapgUCiol>9V1<Z$GO55KG9R!4=tmF4t!%gqj~n-~ zgDQp9?9k)@6Rd8Y??MY>_ijg2GJl<wnKg~ftZBqz{TQB^8oK7Ya*@%lzW|EO9FHH^ z+%zl2<HmVpA0kFb(^juz+VWK)->D^UlDB+SgpaFkpSo-{JN0;hfh_>;UmG#pI$}sj zxkU?=&oWcw7A=hM8M}KMZ)-CI$6V4?P72uEEG2<~ew-(dU>HV(1W~R5QwS2}H&Xi@ zMsUonOm@sA3@joR%#Ai&TNQH>JmL)xB+4(KyU@=zD32|V1sJFTiXYzS#Cz$_*uZg! zWBEEy)Z!oL2PjEq%q0XYBCi9b0FFK1#GSQ?R#<8H`@PD`YIZO)z(6^G^URNo+HDwO z#FWG!79_5}`%){u>sKK-=BhFREFx=xm4;hq_;}5@PqSnzEQY~g<(JB{)a+z>z`#a; z2ghsh>#nFBA7@I0@kURHaE<oc7&-leaxYH{SVSs-62INX@Xz%VzAvOwVKEFGbq6ur zIt0hu+LVCJO|S-_f5%qD2u!H>Q)2wMfIfnwZodlHm=ZAN81r1ag8SN)aoZZYB_ss= zoT=c8PXe)y#$$~2+aNgRDv|;=pFX7kecQ_?Y^jpoc3!18VG6zNe8Ta4+e6QgHSxw= zyb5mu7(86fXkSml3pyI=7(84ZN-}u38b?E2!tw6T%Xm63!#HCu>JVxkd-ex(7u}^R z)Ml78n=)$-^Xq<5Uzcf`)*OC4R)wtqeS5#f?{Z-nlC*MPDkN{=YbnJ(wDn>?6e{kf z|HDO8*u2>{`?|a6-tcZp6`J>X1vB1W4S=t^i#r?NCy->9vhxcltUpI~fd$|LP16pj zYoQ8@$n%)h?cM!##7lRgdiJe%6s#AxICXvzvp@PQ={$bjiEZ~+3e6h+W5REVN??w& zwFSMSJ>iWKt|_zTs$4sO%>Ywo&rK<p<Lpm(Z*>7I4j*$_W_6bW>jS!zo?Y7#I#kAz z-qEh|ZU!0wMr}PQ=j+|IP30?7$Ehsy^jZlpP=APrz4ue9h!_U0j&}ME?pBLTANix1 zo}CqG<#RMOK=3$K381MlrgyY+>%;dZ+7Ag^c7cU}?#f7>qT18s&Y1_WEDKlyFw}H1 z<<`ZL-{s6$o}s3bihoHCFbt5LZwdYZ?<usrmy6ZMtD5;bcLE^ba^m^t#uEdJWzz~5 zkZqX`U;`Eb!Bd5Zw93<Kts?RYL_g_f08iULQ?6>7_CS644_Lf%-}b0WfdBvi07*qo IM6N<$f>2qYivR!s literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/ico/alert-ok.png b/src/static/movio/templates/Movio/img/ico/alert-ok.png new file mode 100644 index 0000000000000000000000000000000000000000..1028f985b374e276ccd6a3f1eed040ad1bcb77b6 GIT binary patch literal 1289 zcmV+k1@`)hP)<h;3K|Lk000e1NJLTq001HY001Be1^@s6caN&c00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy5G%YYT zEiy1MGk$A`KmY&$9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00do0L_t(og|(PlOk7nIhQB>bnW4z7+*2sUVB-W-l%_%r)&Oa(XiRLisnI5ltv-N> zB|d2%G--Wq2z{s+Vod5S#Rsq?3QFr#FvS!~M60PvrxFU~Higawn6rGCIb@ibGeZlk zWG8!{^PfH6ti9J+dmY6(n~3ZODuGhK4qQ-5bp_pDZv;PtM7GaGq(}!@R~Qi~5)qe( zNWZgNx+lMu-)4Jc-sjO_Tq1Hp2T|(?@-0w1>>lE>^Sh<%8{?8Gd7y%=3B~%QlfdzH z0TGcSK=ZujrG5Nk7Q`E-$%@aXD*XV!AHbugb$~Df4FFf}{J^~CMnns1W8NE#dmR8a zpwhh7AiycWHs*Ekw`<T)lo*#nmSqco1F)|th=|kxbpU<N@6kjv)Rv`G>s>prxYizN z02sJ)k;(Z{Ls7P+fPCvVfKlKbfHeaVk#~W;bBi+!&Gtt1#*Wn8dbb6bSThh2$spj3 zU#2_o_*{nChZ0NKv>^weS1EN|f0?b7M;d|LVb|~c;~Fv)#ha{@r#+_+TY~Sc8YGZQ z4tg~=KToxziO*15l2k#w$qH~@DfP*UKt!YzKq)m4gQWqWZ@Lrb!i1qH$(+Xa)Ea$w zD)fHX3r$37M5G7k2l_>%M?^{tU{3%Qx93ObcV56JKEw9ZrWf?b&IV^+-OM2q*8rUW zx4k0(WLh>?0GCDNX{FS!LE7!W`v4awTG3?D&>Nc*ig+;b5eN!bLl6<k$G_?5ojOnN zR0jZivR<b+xjX^r6Op4qYx@Dfm6>iFu0IVS0CuInq<34CQW4iL*du2E+fDahT$*fO zy4W%HDIV=EWvSHw%|T~}TCe8f(qtRHXd5)Sf=o*u1j5xwX9f_FCSb2~VUpI7rm&sg zHU1^HJPvAe4g)mf&zN+Le}&sOX9!_2B~X?5vOa7v6awZzwyXj;H_~W0@u1U=pz(ap z8vr(k>l%Yjd$hSJORdIY+6WQCH4Fs*dD3>nb&XNaaMXzhW`05wjmJ_dX&Y^hx+EzZ zGN{aWQ6GkdYpAJ!M+O1gnSbA7%;Sjl%!=%lykk6^R0jTVea%Rx?>UoFY7zJm;H|=s z*papyO?<0rTN1YE5QgCzYGweXRDFP~?%A9}6eQaCX5@6#<Q2{K<Q&qwhT$4&%g(HU zywM2cj(Ub^{jVwJz6rG_QlDX8UOo83b!RO7($XxWQtBM=B+#2{-O7=|4|zOwSHv@C zq-HT$sm(pCPZu>@LoF=VD5Y)&{>c~CxJ35nz0JP7I^yFjX!xSGo$0k$;}T&7;TjVp z2<TPdDBvzjtLDwZlVn>8&_s*avMmMFWFOQYj~T9EzZXjoC=EXYD%`%ibly6PeWGod zrZ}aX1Np~D@O$I5QmTHX0QX#O2I^IRt++TR*JrQF_1UZ9TAW)})85;x_gVV}ifVg= zqS_ufJm0ges`eF;H2j|#00xv&)Auuv4g&B$LpZhz*wdpE00000NkvXXu0mjf$zViH literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/ico/arrow-baloon-big.png b/src/static/movio/templates/Movio/img/ico/arrow-baloon-big.png new file mode 100644 index 0000000000000000000000000000000000000000..7348b99777331bbeb13f4e09145d57b41f1558ae GIT binary patch literal 599 zcmV-d0;v6oP)<h;3K|Lk000e1NJLTq000sI000mO1^@s68wM|200004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy4G%YYT zEiy1MGnHI3LjV8(9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00FB>L_t(Ijh&LQZlgdDhJV%vTCK=H7Gw&)231ni+!Lg^Yfwm=G|4Nt;3@JDDR=-X z1g3)$Su`#!Bt&z24fr?{pHKOv)k-@v-~KzZ8kW+=#Q<nomVE~R-}gTNC;-34U42sf z7lZ*=0nm%0cx{?SHBF<6qId<Mk1;mp{u8tUpod|2Q&pAfx=wXnr>d$_VHn=bU>8A? zn{NP&vMjf4+p1w0)G!RHZCh2A<raW3=6vdE>dOj%o+OE1*R|^V{sij#Ue$H2k|goZ zTxl4o=P>4ZUL>UiV}HVoF-R%ld0sSgb8<94&;YP3%N|VAd?cd9+ldIKX+CCI_HbT1 zU3nTe=R9&<_fj9>x-K~9(Y$8iD9`g}BD&+8Uj%W^K}2_Xo<E;E(g0|29N!8dwo=NA zkV#TX2qCs{9N#WLK@hxImIYncuYz=4hh<p^g5YfqLYk)cLWmdJwy#1a*|rTK#7ml{ z_rN%QB3g|5nx^kSL=gaJyWQ>w5xs9VoBxK))wV5;$Ky|C7{-(1IA4MQfa5qY4C6`L l@AqoGUVj+`0Efc?zX1VMievRbFK++<002ovPDHLkV1j6L@8tjh literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/ico/arrow-baloon.png b/src/static/movio/templates/Movio/img/ico/arrow-baloon.png new file mode 100644 index 0000000000000000000000000000000000000000..8bf5f098b4317b167bb4c1f6a5212b274d546970 GIT binary patch literal 381 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)8<3o<+3y6TSc;uILpXq-h9ji|$mcBZh%9Dc z;1&X5#!GkW{s09fN?apKoQqNuOEUBG6hbm{QyB~`bq$PkjSLKp|2Iuz0;-V%sR_<c zD=AMbN@Z|N$xljEaLX)8Ezd8?E>>_3Hq|p+E${IfsPdwxi(`n!#MVCBuI2y{xAVo^ zc?VtZxTeT%X1v|F@{*tY39X=;?FV8TuP#t9(^~YS>!5wyEE|rV#qp&-ceKBk2rXqu zln`<ijNW){(lSkkM*Z8{mcHKQ`@pubLqdV=#OFDwk>CEwGd6V8FmJD%r`eTM|L|>J z<NalsFMj`%5SS?c;LX)*rM58+F6SJKd@t|MI_M_OoE>|e=Wqc}hsUd{n{<9J-nJE} zoAIPY-;~r!o;{y9142cwMcu!9makz|TmyeH&pFG6%lG!TuUqvh<SW+)mL{8o<F9pv RYJi?&@O1TaS?83{1OQkbk#hh5 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/ico/arrow-button.png b/src/static/movio/templates/Movio/img/ico/arrow-button.png new file mode 100644 index 0000000000000000000000000000000000000000..585ff1d095a80e32acf271255d7bce1d8ad52fd3 GIT binary patch literal 579 zcmV-J0=)f+P)<h;3K|Lk000e1NJLTq001EX001Wl1^@s6fxRJe00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy5F)cAN zEiy1MGJYMjI{*Lx9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00EatL_t(oh3(kCF9Ts5$MN^mbZK?6D<*091B6s!Fff}eBrHr4vG_4)2qjU2A|#@c zTI`k%qDoW$K|>STo|rmuXJe=)jkMC|xpL3on|#Ob-7BB(b9c#!;nA@V{=N(#1<YNX z#|<&!45CscAm~O22Mx3Wt8PaL<r;DeXOjT%IlT@5bXW&EtV0uo9%n)e1UeuTlIRX} z@%U8W%`}^Wa0vmj-4o~{v^bBi#Vb8qt6f3}RJz08#(pGBXS-i%zPgnVmGXK#tSrpi zhA1ad4cQDWGZ^ewMl|gaot_*A;OZtVJ!?CO?~s|P3Fnfi)IeV^00+mX4bQlRa7o{& z5xC5C6_cnxlf2DvcoJ_2Y70?s<S-WJ`Zgm4P)5{B;wW}TDt#vnP)1abn3l!*_AdFN zp#)GyRFW_)i;YN>g7K^jP(}y=`JzF1XAje|YyrLy@<ZAC9Er;$*1J{rkV+!tuabSp z0gb&cehty=`bX%6_~|?FX9x{~&|)30I;<n%^g2qwl2hw=q5Su5HoCQDd;&NRSpg*~ RgmVA@002ovPDHLkV1l&`<wpPj literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/ico/eye-hover.png b/src/static/movio/templates/Movio/img/ico/eye-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..df913e44f5cc3b163c81f38e63818c81df1ea5ce GIT binary patch literal 463 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~g!3HGv?z=Y!NU;<<d4_NRK@CSr2awNM;1OBO zz`!j8!i<;h*8KqrN|d-plsFfqCYEI8=P86_=B6?jTIw1Y=^7ar8vk#a#spL&2T~K9 zpH@<ySd_}(n3A8As^FGclv<u&lwGXg9Bis*xLV%hH3I{qvZsq<h{nX+i-z7Yjv}lN z^2-w)1Gaf5f7Q}<ES%T4Kp||SsG~;!OLMDl(6Z0^OEw7~aS~uTsFliOmKbM{u-iak z30KFVLrohdB&k1qn(A-<eO~dqxy8{^D^4wHuFXkibiVV@<VeZIC)=eSS<Xq^>3QZy zPr2f<`So0HXH~FnkNndTd*%VF-2=(>h0#-w{;`)1N!{3@KjYljvjUexlXrjrF=hVu z2p&V*Evq&~oX<Z0?3saoTfRigjBBely?D6sS!MI#vU#_1>&%Xr9MX`Ub>QW~+kA$x z$)fv<lDYCXojfgY*=?Qtl_RxlT4(J0zt<^LjN7tZj?Lmws@a``?j@fVgexwy`#*o< zfsKW?CVvpkf1RG=n-rS5vDNmBbov+O=ZecFt9>``$_!}waSId+3=E#GelF{r5}E)v CG`ukY literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/ico/eye.png b/src/static/movio/templates/Movio/img/ico/eye.png new file mode 100644 index 0000000000000000000000000000000000000000..c3b3a7ae488a07c244db274641148f8a12dceaf6 GIT binary patch literal 449 zcmV;y0Y3hTP)<h;3K|Lk000e1NJLTq000mG000UI1^@s6y}sU@00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy4IV~_U zEiy1MGyj5?0ssI29&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z009+AL_t(2k!{hjOVx1{1@O;%f*>Ssb7^vN5)8p03dBj*5Q4&vpg6SD*w(+`)E0Cb z1VIp-8Vg(+#K6@lXbM6>5Cp-&Z}I&3&i1|coOAE@+@21qY785AfjL~_1fP@acKN-I zcm`jv&?Po}#b%P<{|fyf@lzZ(@i|^&5>t4GD=g!<s%GzOP*wBzh6k<wJjs4%ySLbG z&tG_y<ZrL4mfG46Tl2C_h99^{vRG9EoDF#%;!VFz9q)cN$u+K<p%I(`#`{SQ@C<)i zV*)Rm$>Ss|t-duRKE+~^qyJZ^s=1cK02laxy=J(E_ZVw~o+LTt{u!t7(QVqJ@Exy) r&)6Hqs;X72W7cg(Ke3bKQ<r-Kq5n?+plir100000NkvXXu0mjfEX=rr literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/ico/mov-top.png b/src/static/movio/templates/Movio/img/ico/mov-top.png new file mode 100644 index 0000000000000000000000000000000000000000..4c02f977d9de07c23e4f8861a467c24f49a2edcc GIT binary patch literal 975 zcmV;=12FuFP)<h;3K|Lk000e1NJLTq002<{001Qj0{{R34dV6F00003b3#c}2nYz< z;ZNWI004MUOjJdytE>C_`{m{3%*@Q^=jZS5@8jd+wY9a~-QBmhxA*t=|NsBFxw+}- z>ASnT*Vos*y}k4E^Ru(F>+9>`;o;TQ)xyHU|NsB7v9Z(B)A{-N?d|Q_+S>K?_3`oX zudlDbz`)Vb(Z<Hc-{0TQ&(GW2+pVpw#l^)4fn9?D000SaNLh0L01FZT01FZU(%pXi z0000ObVXQnLvm$dbZKvHAXI5>WdJcWEig7MGB7bSm0UAJ0000UbVXQnQ*UN;cVTj6 z06}DLVr3vkX>w(EZ*psMAVX6%E-|YgNb3Lq0-#AmK~zYIt(Fawn;;N|T?Utck{iTy zj9!v{WZM7#54#JPixK5+S|%Y;;Njg57b|G~Zxhv6KtcnLe{;7pdlZ!^i!{v`W<wF! zfDzTTv~%Eyp11{G7`=+hmxw&tYjt>bz&6o~N|uQYYBjWdQ?NRWNl}ThKm<TVtyB03 zt4BdZx37=3Ra)Ovr&aLfesfH`7Iqe-?{*wi*B$#}^3+VU8?#dSVSq)u74Etcn$aQ= z<z)*9WTa?s9kbM+RdrMzc2!;^YZNs!*`4{8ob^$!)veV6nmiPe(V{{jv;GEtR%E9& z(KM@UN##woHV$T~Mn)pmc@v<K$0PANmZ<g6{wDD7T|z!F=}t{BB1*Jl-e_?B{d_w8 zVVk=_sh>aI&Zjr`F!FVQkpyEuCQoKnvYHb~>zH@|Zkr_ouFN7Li_H23(%lnBnm>oI z1?1gG_bf{c8gWx(Xm2X!4;PD_Mu8?bMys*Uhx=>9i|kQ^$S@N9IBWkhF)bNA_97B7 zkf(puIElas8YA)oTO#*~Y1t(J6EPr#-K=V#(deuYNm}wFb$;s%D-*%^nZmKgkeAd? z8v!p9%_KfB;hBjSIAxDJcuxgVzi${}JmLfMLFCZSIkY4mhEQ&A-65Y{(d0Eza2nZM z84&HjO!ZB^l*V|$L3xt6AktU5^}7i8U+4S%eDE)ibDZfcuj@0!Ig6ZmDe0j)z+7-( z$s1kL(r1YA;X&bD&RLQBG6K$v{*iubtNSq0qpZzB;?rB%(rQynT7<YkL@ARuI6&~i z48Kd>NFj-!Saa4IKN<&p+CN4CY8xDdtJNzarcQd7g@#kXdAUrPGLiR|cDkBXFu=IU x$}}a1%~}1_q^++Plg_KrxVpCX**zJn{{lEiYOJ}h=(+#^002ovPDHLkV1kKf+Z6x+ literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/ico/pool.png b/src/static/movio/templates/Movio/img/ico/pool.png new file mode 100644 index 0000000000000000000000000000000000000000..fad7085f1808e2b3bebbf7bb2534fca2c5b39fcd GIT binary patch literal 4159 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/ico/search.png b/src/static/movio/templates/Movio/img/ico/search.png new file mode 100644 index 0000000000000000000000000000000000000000..21b3d0d8bc50ce42993f58b4ffb43981708be9ba GIT binary patch literal 342 zcmeAS@N?(olHy`uVBq!ia0vp^{6H+o!3HFmxV|j}QY^(zo*^7SP{WbZ0pxQQctjQh zDIpMMbUU_tH&9Tn#5JNMI6tkVJh3R1!7(L2DOJHOvnaJZzbLy{!8zDe&v3Q8$7`TU z36M(XqSVBa%=|oskj&gv1|tJqLnB=y14E<Cv;`GFHLE;b978O6k4_2{J*>dvS{%^8 zq7uRsG{Jy#Y7pnt0M5x9ELSw|p1)zK$%e1l@4F{|$a~P(!FA%msX+b&wnbl9M2_v+ z%`i7&tF{J{=kk4w^D0e`z2x4r<?O2452Cu?-ORC_@%3kfd~Td!#nE_CmnSP<+uR7R zK7M(oOLgPTbe~+~RU4Vod@W`#@Joz5kiwv>YwM7uwy=J|-%WN4)Y*TfA5bl3)|h^l dt3ydi|GjxbbB)J>M4+n~JYD@<);T3K0RVfSc#;4B literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/logo-footer.png b/src/static/movio/templates/Movio/img/logo-footer.png new file mode 100644 index 0000000000000000000000000000000000000000..41ccbf3aa441762af105af154051c41a6bdd9e54 GIT binary patch literal 4557 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/logo_fondazioneTelecom.png b/src/static/movio/templates/Movio/img/logo_fondazioneTelecom.png new file mode 100644 index 0000000000000000000000000000000000000000..4cb5e79a750b9a1fa39994a459df28cd0851dd4b GIT binary patch literal 5021 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/logo_movio.png b/src/static/movio/templates/Movio/img/logo_movio.png new file mode 100644 index 0000000000000000000000000000000000000000..f0dddb4349c2ff134643a00a5141404b05696661 GIT binary patch literal 2067 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/app.jpg b/src/static/movio/templates/Movio/img/various/app.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7ae1fd9d10ad7caa09cd55c3f452c304524660d2 GIT binary patch literal 15769 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%0AMguE>jHjxyB?L=mXi_iL``V8PSuG^fb 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 Q?7jmc-T|xanD1-<1N%AC)c^nh literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/cart.jpg b/src/static/movio/templates/Movio/img/various/cart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b245a4c724ab2a4ea88efb2b7c7812daf5c86890 GIT binary patch literal 26945 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 T{$s4ifz5&Oz}r*0hnfEeb#B%~ literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/figure.jpg b/src/static/movio/templates/Movio/img/various/figure.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5879818e0850ababc995e6d03bc23ab86d22af74 GIT binary patch literal 14615 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 L_Uz45miGS+l=ZXg literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/gallery.jpg b/src/static/movio/templates/Movio/img/various/gallery.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b21289d2ea687ca9552c7316f1cb56c874bed4e2 GIT binary patch literal 94553 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/header.jpg b/src/static/movio/templates/Movio/img/various/header.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3b6a34788cd0443a07d53c6fb8007abab45c7a18 GIT binary patch literal 165481 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 z%0A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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/image-page-y.jpg b/src/static/movio/templates/Movio/img/various/image-page-y.jpg new file mode 100644 index 0000000000000000000000000000000000000000..831769a4ecdb1a0398163d58821e9c35a4196bc4 GIT binary patch literal 32526 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/image-page.jpg b/src/static/movio/templates/Movio/img/various/image-page.jpg new file mode 100644 index 0000000000000000000000000000000000000000..22c1ece1e2b402b71e9f355e60e114a1bb6fd25e GIT binary patch literal 21452 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/image.jpg b/src/static/movio/templates/Movio/img/various/image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..621ab863149993714380daff933e7d757b8e0d70 GIT binary patch literal 27732 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/img-link.jpg b/src/static/movio/templates/Movio/img/various/img-link.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0c87d37c35f581d1fd37a69435a3d56feddb7555 GIT binary patch literal 5811 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%0AhC8)!o1)m9Dq_=A*l3NyufMW@FaD3<F2 zTNPv)g#zuaC2irsf?sLE!x=@3_Cw+-S-j69FgD)er8;=w+w=~*{-vEZfqLB@G`e}( zv+mg4&x&x=SlTx~A{5a=9jI3UwmjvqTy4UwJh_R=CK#|su&k39Z>%Frs@i^=sA(|M zc_pV#!tP-v_u-9kW42+ipk<K5N+Y=akReXfG6a2Rj}zLnObN|;Dh-vX(%K`)E(4Q? zz)5WNPt%f53O1kEZYD1PQ;7QA**`yVgTG$_>-oso>I4hdsdiwXe}gbu`tn0-;tNJ) zN1bn51TJbnxdPCmMWGk~pEr!{WbjK_9YP>xd=}-`%s!hndjQs6c{iw_*7)?1ORU{U zV#((vljq0soN0Di$yK>UAA=z5I7$##xWRH(O{SwWi}+BfrP1wD0*N9~P-qsa+>~ty zm3T0Mio!(F{l-$~uplzCHJUzbl-&(6wJZyH6~}SU_2RPX#-~g>C&`(Ab~;@<NRc1= z_T|ezyy8YLHoo?}rgyUpR+miaiqb*Vlof~}bBx=;mzCAvE-F68F^VdP3#dFyjfA9t z(VKx)J6{*o$*C$6HI$WSf(K2`ul3b$512xWuyYqG%;O~Vrm8t7)ROw!Hd*dv%bo*$ zo2_RK8ceAJA$PnCDmt!Ld|lV{?J&2zPPzZ#RtW8M(b(wVJDRO+WwfqnE7h29yPJOM z9)qXROYXu#cbTGzRpjVlCa7`>6w|8P--M{il=gr9PAh6&mc(hz)hVFQK5bnlPWDp2 z#LP0!+vxM*xmBIh1mROzz*jbRl?;Od&O-h6m=XD>DZbiS;8qre6}l@g`h%Vy`4r!V zFB|*B%vYs>X4CH=w8@h*<&J@!_WrH?IV$CHr87#eS+JSLA#h(at^=ous}SlPdkKNw zoyMI`=2M^I(YIfn%`z{kNRjppZQPM=yciTenQ-#u<Yb$tXJM(nu0CTD6$L}zTRI0= zfSEr0+LysM=slxbPM@>*yY8#up%2VWY^IN<4}RkCmqv@rM%DSsCFPWq45yH9l~+{I zp5zU=QLlsD&32Gs<nw8<o`>WDA3i0uF-K<^?rybo(y~cSNy~jGBQmIC!Fo%Pi^Y54 z9H8+NG#&6?Q_{%UH|rrKPQUOGJytK+p*QS;dcsZA#O*h6Z#87Q5#07aglN~%MXlYU z(HYV^lsX>v=YGi}%UQPjQiW<JTYC01Zz5zfw8TEg@SCUazC(c(zEY}r9lRhK=7q)# zP;Kg0-kUp}PONk?{8#&@G4s)(`B?+Jo?s<XkvaZ^)pzQF&Zlfk3(5vQ1vfIpb`Bso zWl~hC8=jTcO3Udm2rXPOB%~$m!k$w+-b8)x`1AV4AyaDUGJQsJ8M<QGe)r&Yot0mP zMd=X!ZbWz3NL|UBv?Hwg5Y97!^$$?ml&^wt=8w%*&b2}CTNn~hHHz#b=(7c+-dWY9 zwtwipoGm$hRIw^nOM|pYEHP_;3Oy-w+x(>gjxxFx?0a8Dm#K)O4QYG(Mkez~w9qOG zl~{VPLzW7F{~~|s-LMQ}%Ib-DeR9#=`ojEo!o;E3!xk)$a^S-OK_TT=&b^p+{%Zrt zyD#hHi8cg_N1QibBSnOTbEP9>%p*cSTa~v{<(KH?4AAfRsRaZn>t_hSAK*%>i)p6S zeg-_K=7`AOxdd9X;wdMZMQgl$f-U=94~*uomtb;;mXdmcE`?Bzyj{K^6vHu|<7t6^ zd~LaHc#o6^_1N@-7J{T0vOrC&@f<i&b}m}f7&g>>?_FJ(D<Cxix-PU(?Ts6XZR17r zyiqmgQXTpdkiqeUYx3#ST_<UULY%6rK1_S9aRZ+PX>Ry1J(v|$+KX|*Sh66G9!sp) zGCI^kO)x>+c~APTi6`h?2A*g!HGZ~t>sw?e!CpXu+D>fljCX<Bb=ia0l63AqR5O1j zsNBcu^4e5LA3q#N7n;kVQFCE|Xx$p4`pV@aHMxKcfET1X)A$eNEFaxK6<~r>lDncU z`~>8lh%9HAta9Y#qsvQ}>j3oW_gesk1+h?$aCE~@C)pD*UK}%;rS~c{O9Yz1*5q^G z`ysRLcHEx7OL%`ev}yLEnMiAK3b7RV)fZgiJ}d>5vbB_h3g%{R!4eb?s@mUCu@)qB z6E0qb$93vnY-1@)QSMp`)4XY8av6^QH1H8y)LF-$nL@5~*x2H6NRy(GO?-2rM}^89 zL&|z2hQg=se3}&+`{4mnqIzcXCaK7o^s>GiCOVSlOR=EvuidE?W;@7Zt%(f$ZUBOC z#hPAU54zkR`{#ST1Pm#@Rq-3u!FJY;eKx}M1znEGBS~B7j0)O+upnQtrV4PK9H(vm zT~Fnbwm8aeQ8}z45LhQ}=paRz7~Jg(n0{M4)BsnzM2C+RqcWI-+tSq8aNn3Z-KLc^ zE?QQ?1TYp~oUmJOG=R-(4d&%VF`sqq?{;$d_uRFvx6d>UkZ@)6BvAaUy$T_Ge5_(* ztV+!bp8KR4r<>I?B9pC@%hiAG#t*>+QpGFb`_~0Nu#;$gCJ#Er%bojLvl?W0U9B<_ zYnZi60*K6_>UnB*wya7)x5tvhJj~aN0sc|W<P#;4+Cu1KM_8qAc114PwhO3;SF22u zQIzFuN-n8OXJ93jDe+%!9Dc4&-C&^)hwrwXk(rI>W=V0~I+Yw;Qn8wWtn71&iK*-H zCHf^qs8DwSxBbx$DPjdMMjqQ~xUEt++b=A`tyIAjfh3;#<VW&UHQt90fg!>0N58sW z;*XlVWEQq(r4cQDtN3nN(p}dL)J9!scft2=xu@a>!gEwy*IU9z6$|Q<TKYP+;JS}a zAvH03pGuns;{{4?m^pnosQTJe<uLgD1WPB~<g4O$w^$P*`ZhY=l5al^_6%P4f)+HN zuKZE*4ts&2Qn7}7dPOnZLU4X}3dCoGc)^k0yt~;`h{U1lAA6cuYLycUL)Lyaq=F22 z)1Vyd39ZL2S2azRO#{AIf8`o4IWdmBdUnuxb7uu{y-9jcwJEoo#cA;1>Nd??rWzVw z#~P@WwZ!$jJcB<8TzeclXHHQ$&>6ix?Qm@@BV<Lji1&hdS`W&D9_?n8Ot3w3+cG={ z?5P<)z8<uFr?}YkO`IW91~oq-7L(B=Y%}<Dy0EQ>p`#zTVtTxV;VsvdGqi~jCqTUr zNCwZ9ENQEe(`y`71)c-m`Lpg@oDyQ<7K>()!&VYn+##FF>-RbLh%z2-HWn!F!mB@j zO#w&ty+_QAr+xm-We@zW*#~jP_n_cnqmpAL*5-aESWcxB<&b51`H>u-85y_5@^Wzj zLZfSv*A$l1Y5E1;S^gcyUDDJ=U!<;Ko&7#lZGKV!@HW?BtJ9>cRb&2?M>T+cKhV)M zeah>Tr9Rqq`XXnFfEGGTa{0G7R;q7a^7@{Q{qJ=T-`M?r+X)os%wQCqV_)MA{LmA( zH_yc=wM16!`@v~b*B~iE9v1Q|x4b=KM34|&-E8~jbBI&xL_&G$;~90FmlR``#-LwC z)5{y@s>cWlS@`U&a&GwSd<phya9sM%7vx6h4>XfYdzGd7NE<jgFC?`QfoTaL|4FAy zbsij<%(2MiEt#sKu#w&?bv%^WccQ08K<sZt8K;6LtM=5^6qEW5EbKkfFN%%TqhQuy zQ?uuQ4z<NQ$_GqAjoKwA$uD4@I{%{pyT}}>)!V3!G^c(CG~U`G;2(ZkQeI9=@uA80 znT?0s@nWhju~`c5#?8Gl7;@eYoBL(LqGDkPkF_S@0LCp$1exI=lD*Vhr;&@>?pdU@ zpg}HPi(-^LX%v-hd{n!k{RH>SS%#k2%jH^2iPo)UtCPXFNxOayns_K^7fXA~QoV8V z9JoyTMKoH?zDGgkZRyJqXe#J+KO$H;$y3xoUtaoquMO(OF1PmFMOiU~v+5c{|NDLP z*IW3#B0k%fc~tnP?qe7Zy6P6j{W}Mp&;&w+r1Ez^1xqos9ScOK4)-N0%ChQ@!^y#v z2bh?v|M#6$?dl(*%n#jjb9Jl#T7;Tl5l`*q-GA&eamV%{>&vgJXoo@$*O8@>SoB)= z!IZzAlK>JnHer-4e%Eqm*nLZ%l9cL72+Bu08b$4m6LO#bOg-c0+^2S5B31=L!G7Di z*CzV=Eo4w`v3crdC7*5ct*nHSqo%&RBWo6faj!{jA80VlYIY!;9gZs)Ik<#VKSS~P z*G6dOxy_Y^0-7T$K&mDW*|iFLSXj%*^3A&nl3Hv@o+hNZ=E2GjtUD*$EZaLQrbN_K zd2CcPJo=)$QdWel=W=BvD&LcvEG;w(eD3BS5)EKKqJOelYLp69v;};VieXg#f!xiw zGhGc(G|@uSY~4+3FaA#XaK`|au^awKHJ1PR;H9B7&O)78*b5sAb!gpz_T7dw2VB-o zu{xSGW%28&JfZ7ha4q~>vWVfMZ+aC}@-cjcBfjg20g4ODzBiZi;2yPwx021@oGG#- zi?<y3iQM45AjfL5{|`N6-E*`=rmKX@`(8a&<BIk{B*~zZLm;G1YybEK>Ydp(gUE>U zS)`GxE@~>4^aBfUDtMJQ92l*D93}JBgr+XH@$8K9cO%Yd9j}P|A=v-)`PmMN&DO#+ zn=bVPH=`(?VPR)v)>4mWl(L8mGw8L8Aobz1@8!B*+PYR&aGr&myy1(l><dKd>K8)& ziL#AQs?J*pm%)KS@5~8zd`;8%LMYjq(IcEinL6E^I81KQ`1_x@xM94-DTLAWwcYhv zfe$48gUZ<zTy?kP>m}$o7k!Q+H<<-Oo?LM>4u@ElSlW~oGF9`yvQ5x#WHu9VHto5q qHTsJc1@*^_9{y52?iL;99uWQ38hty@a?GcI%TyIV{(du^Py83bwxePI literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/img-not-disponible.jpg b/src/static/movio/templates/Movio/img/various/img-not-disponible.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6a7b56bace784c459708827489abdfa7bc3230fd GIT binary patch literal 1922 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/img-slider.jpg b/src/static/movio/templates/Movio/img/various/img-slider.jpg new file mode 100644 index 0000000000000000000000000000000000000000..33487b4d62e1031531705907aa45155e4908b768 GIT binary patch literal 76924 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%0Dx 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/map.jpg b/src/static/movio/templates/Movio/img/various/map.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6abfd927fe928fbb8e08d3951c7b8c6431fdd475 GIT binary patch literal 20322 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/mini-img-2.jpg b/src/static/movio/templates/Movio/img/various/mini-img-2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bc297efb4212ea27d47ac980cc58fe75621eb9c3 GIT binary patch literal 18629 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 KjdW@E!~Xz)24?jD literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/mini-img.jpg b/src/static/movio/templates/Movio/img/various/mini-img.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d65ed8bceede17408676838651f3011598da2fd9 GIT binary patch literal 3607 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/slide.jpg b/src/static/movio/templates/Movio/img/various/slide.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c6f2e18177485d2abc2b33974a8a5185156ca28a GIT binary patch literal 49477 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/img/various/visit.jpg b/src/static/movio/templates/Movio/img/various/visit.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5fc510f7a15e4aba41379f9038d5c98fea7d3302 GIT binary patch literal 22488 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Movio/js/bootstrap.min.js b/src/static/movio/templates/Movio/js/bootstrap.min.js new file mode 100755 index 0000000..b04a0e8 --- /dev/null +++ b/src/static/movio/templates/Movio/js/bootstrap.min.js @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.1.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.isLoading=!1};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",f.resetText||d.data("resetText",d[e]()),d[e](f[b]||this.options[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},b.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});return this.$element.trigger(j),j.isDefaultPrevented()?void 0:(this.sliding=!0,f&&this.pause(),this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")),f&&this.cycle(),this)};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);!e&&f.toggle&&"show"==c&&(c=!c),e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(b){a(d).remove(),a(e).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown",h),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=" li:not(.divider):visible a",i=f.find("[role=menu]"+h+", [role=listbox]"+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j<i.length-1&&j++,~j||(j=0),i.eq(j).focus()}}}};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.dropdown.Constructor=f,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu], [role=listbox]",f.prototype.keydown)}(jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show().scrollTop(0),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)}))},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=a.support.transition&&c;if(this.$backdrop=a('<div class="modal-backdrop '+c+'" />').appendTo(document.body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());c.is("a")&&b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this,d=this.tip();this.setContent(),this.options.animation&&d.addClass("fade");var e="function"==typeof this.options.placement?this.options.placement.call(this,d[0],this.$element[0]):this.options.placement,f=/\s?auto?\s?/i,g=f.test(e);g&&(e=e.replace(f,"")||"top"),d.detach().css({top:0,left:0,display:"block"}).addClass(e),this.options.container?d.appendTo(this.options.container):d.insertAfter(this.$element);var h=this.getPosition(),i=d[0].offsetWidth,j=d[0].offsetHeight;if(g){var k=this.$element.parent(),l=e,m=document.documentElement.scrollTop||document.body.scrollTop,n="body"==this.options.container?window.innerWidth:k.outerWidth(),o="body"==this.options.container?window.innerHeight:k.outerHeight(),p="body"==this.options.container?0:k.offset().left;e="bottom"==e&&h.top+h.height+j-m>o?"top":"top"==e&&h.top-m-j<0?"bottom":"right"==e&&h.right+i>n?"left":"left"==e&&h.left-i<p?"right":e,d.removeClass(l).addClass(e)}var q=this.getCalculatedOffset(e,h,i,j);this.applyPlacement(q,e),this.hoverState=null;var r=function(){c.$element.trigger("shown.bs."+c.type)};a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,r).emulateTransitionEnd(150):r()}},b.prototype.applyPlacement=function(b,c){var d,e=this.tip(),f=e[0].offsetWidth,g=e[0].offsetHeight,h=parseInt(e.css("margin-top"),10),i=parseInt(e.css("margin-left"),10);isNaN(h)&&(h=0),isNaN(i)&&(i=0),b.top=b.top+h,b.left=b.left+i,a.offset.setOffset(e[0],a.extend({using:function(a){e.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),e.addClass("in");var j=e[0].offsetWidth,k=e[0].offsetHeight;if("top"==c&&k!=g&&(d=!0,b.top=b.top+g-k),/bottom|top/.test(c)){var l=0;b.left<0&&(l=-2*b.left,b.left=0,e.offset(b),j=e[0].offsetWidth,k=e[0].offsetHeight),this.replaceArrow(l-f+j,j,"left")}else this.replaceArrow(k-g,k,"top");d&&e.offset(b)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach(),c.$element.trigger("hidden.bs."+c.type)}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.hoverState=null,this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(a(c).is("body")?window:c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);{var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})}},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(b.RESET).addClass("affix");var a=this.$window.scrollTop(),c=this.$element.offset();return this.pinnedOffset=c.top-a},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"top"==this.affixed&&(e.top+=d),"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(b.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:c-h-this.$element.height()}))}}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); \ No newline at end of file diff --git a/src/static/movio/templates/Movio/js/main.js b/src/static/movio/templates/Movio/js/main.js new file mode 100755 index 0000000..07d46a8 --- /dev/null +++ b/src/static/movio/templates/Movio/js/main.js @@ -0,0 +1,3 @@ +$(function() { + Movio.init(); +}); diff --git a/src/static/movio/templates/Movio/js/vendor/jquery-1.8.2.min.js b/src/static/movio/templates/Movio/js/vendor/jquery-1.8.2.min.js new file mode 100755 index 0000000..bc3fbc8 --- /dev/null +++ b/src/static/movio/templates/Movio/js/vendor/jquery-1.8.2.min.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call(" ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/src/static/movio/templates/Movio/js/vendor/modernizr-2.6.2.min.js b/src/static/movio/templates/Movio/js/vendor/modernizr-2.6.2.min.js new file mode 100755 index 0000000..f65d479 --- /dev/null +++ b/src/static/movio/templates/Movio/js/vendor/modernizr-2.6.2.min.js @@ -0,0 +1,4 @@ +/* Modernizr 2.6.2 (Custom Build) | MIT & BSD + * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load + */ +;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)u[c[d]]=c[d]in k;return u.list&&(u.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),u}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:e=k.value!=l)),t[a[d]]=!!e;return t}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.6.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n=" -webkit- -moz- -o- -ms- ".split(" "),o="Webkit Moz O ms",p=o.split(" "),q=o.toLowerCase().split(" "),r={svg:"http://www.w3.org/2000/svg"},s={},t={},u={},v=[],w=v.slice,x,y=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="<svg/>",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function p(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return r.shivMethods?n(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+l().join().replace(/\w+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(r,b.frag)}function q(a){a||(a=b);var c=m(a);return r.shivCSS&&!f&&!c.hasCSS&&(c.hasCSS=!!k(a,"article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}")),j||p(a,c),a}var c=a.html5||{},d=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,e=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,f,g="_html5shiv",h=0,i={},j;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))}; diff --git a/src/static/movio/templates/Movio/less/element.less b/src/static/movio/templates/Movio/less/element.less new file mode 100755 index 0000000..b2f1ac1 --- /dev/null +++ b/src/static/movio/templates/Movio/less/element.less @@ -0,0 +1,2264 @@ +/*** +nav +***/ + +nav.menu-sx { + border:1px @solid @sidebar-border; + background-color:@sidebar-background; + width:100%; + min-height:290px!important; + + + @media (max-width: 480px) { + height:auto!important; + min-height:100px!important; + border:0; + } + + z-index:1; + + ul { + padding:13px 0 18px 0; + margin:0; + + @media (max-width: 480px) { + padding:0 0 0 0; + } + + li { + list-style:none; + margin:0; + + a { + margin:0; + line-height:1.9em; + font-family: @font-1; + font-weight: 600; + color:@sidebar-link; + padding-left:30px; + border-bottom:1px @solid @sidebar-border; + display:block; + text-decoration:none; + text-transform:uppercase; + position:relative; + + &:after { + top:0; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + } + + &:after { + border-color:transparent; + border-top-color:@sidebar-arrow; + border-width: 5px; + left:0; + margin-top:10px; + margin-left: 12px; + } + + + &:hover, &.active , &.opening.active { + text-decoration:none; + background:@sidebar-background-hover; + &:after { + border-top-color:@sidebar-arrow-hover; + } + color:@sidebar-link-hover; + } + + } + + /* sub menu */ + + ul { + background-color:@sidebar-sub-background; + border-bottom:1px @solid @sidebar-sub-border; + margin-bottom:0; + padding-top:3px; + padding-bottom:3px; + padding-left:15px; + + li { + padding:0; + margin:0; + + ul { + border-bottom:0; + padding-bottom:0; + } + + a { + background:none; + margin-left:0; + font-size:11px; + border:0; + line-height:15px; + padding:1px 2px 1px 2px; + margin-right:30px; + margin-bottom:3px; + text-transform:uppercase; + + &:after { + border:0; + } + + &:hover, &.active { + background:none; + background-color:@sidebar-sub-background-hover; + text-decoration:none; + color:@sidebar-sub-link-hover; + } + + } + + + } + + } + + + } + + } + + } + +/*** +article.box +***/ + +article.box { + padding:0; + border:1px @solid @box-border; + background-color:@box-background; + position:relative; + /*min-height:58px;*/ + + @media (max-width: 480px) { + margin-bottom:15px; + } + + &.collapsible { + + border-bottom:0; + + h1 { + padding-left:40px; + } + + .container { + border-bottom:1px @solid @box-border; + } + } + + &.big { + + margin-bottom:12px; + clear:both; + + .container { + min-height:50px; + } + + } + + h1 { + font-size:14px; + font-family: @font-1; + font-weight: 600; + line-height:14px; + padding:13px 14px 12px 14px; + margin:0; + background-color:@box-header-background; + border-bottom:1px @solid @box-border; + color:@box-header-link; + + a {color:@box-header-link;text-decoration:none;} + + .ico { + display:block; + position:absolute; + width:25px; + height:30px; + top:0; + right:0; + margin-right:10px; + .border-radius-bottom-left-right(4px); + background:@icon-in-box-background; + + &.map { + background:@icon-in-box-background url(../img/ico/pool.png) 3px -153px no-repeat; + } + + &.arrow-dx { + background:@icon-in-box-background url(../img/ico/pool.png) 5px -204px no-repeat; + } + + &.ticket { + background:@icon-in-box-background url(../img/ico/pool.png) 3px -259px no-repeat; + } + + &.timeline { + background:@icon-in-box-background url(../img/ico/pool.png) 3px -315px no-repeat; + } + + &.info { + background:@icon-in-box-background url(../img/ico/pool.png) 4px -461px no-repeat; + } + + &.relations { + background:@icon-in-box-background url(../img/ico/pool.png) 2px -818px no-repeat; + } + + } + + } + + .show-content-box { + border:1px solid @color-border-button; + position:absolute; + width:21px; + height:21px; + display:block; + text-indent:-9999px; + cursor:pointer; + top:0; + margin-top:9px; + margin-left:10px; + background:@color-background-button; + .border-radius (4px); + + &:after { + top:50%; + margin-top:-2px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + } + + &:after { + border-color:transparent; + border-top-color:@color-arrow-button-slider; + border-width: 6px; + left: 50%; + margin-left: -6px; + } + + + &:hover { + + &:after { + border-top-color:@color-arrow-button-slider-hover; + } + + } + + &.collapsed { + + &:after { + top:50%; + margin-top:-10px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + } + + &:after { + border-color:transparent; + border-bottom-color:@color-arrow-button-slider; + border-width: 6px; + left: 50%; + margin-left: -6px; + } + + &:hover { + + &:after { + top:50%; + margin-top:-10px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + } + + &:after { + border-color:transparent; + border-bottom-color:@color-arrow-button-slider-hover; + border-width: 6px; + left: 50%; + margin-left: -6px; + } + + } + + } + + } + + .container { + padding:10px; + width:auto; + min-height:270px; + .glow(#F3F3F3); + min-height:260px; + + img { + max-width:100%; + } + + @media (max-width: 480px) { + min-height: inherit!important; + } + + } + + &.image { + + .container { + padding:0; + min-height: inherit; + + img { + margin:0; + border:0; + } + + } + + } + + p { + text-align:left!important; + } + + &.col-md-2 .container { + padding:10px 15px; + } + + a.link-to-reserv { + display:block; + .border-radius (4px); + color:@linkButton-link; + position:relative; + height:39px; + padding:14px 10px 11px 8px; + .button-gradient-black(); + background-color:#000; + text-decoration:none; + font-size:11px; + + &:hover, &:active { + text-decoration:none; + .button-gradient-black-reverse(); + } + + &:active { + .shadow-inset(@black); + } + + span { + display:block; + position:absolute; + right:0; + width:33px; + height:39px; + top:0; + background:url(../img/ico/arrow-button.png) no-repeat; + } + + } + + img { + margin-bottom:10px; + border:1px @solid @box-image-border; + } + + p { + margin:0; + color:@box-text; + + a { + color:@box-text; + text-decoration:none; + } + + } + + + dl { + font-size:11px; + margin-top:-10px; + + dt,dd { + float:left; + border-bottom:1px @solid @box-border; + margin:0; + padding:8px 0; + } + + dt { + clear:left; + width:25%; + } + + dd { + width:75%; + + @media (width: 1024px) { + font-size:9px; + } + + a { + color:@box-text; + } + + } + + + + } + + + +.item { + float:left; + border:1px solid @box-relation-item-border; + background:@box-relation-item-background; + .border-radius(2px); + margin-bottom:5px; + padding:8px; + min-height:58px; + padding-bottom:0; + padding-top:0; + padding-right:0; + + h2 { + line-height:1em; + padding:8px 8px 4px 0; + margin:0; + background: url(../img/ico/eye.png) 98% 10px no-repeat; + font-size:13px; + + &:hover { + background: url(../img/ico/eye-hover.png) 98% 10px no-repeat; + } + + a { + color:@box-relation-item-link; + text-decoration:none; + + &:hover { + color: @box-relation-item-link-hover; + text-decoration:none; + } + + } + + } + + figure { + + width:auto!important; + margin:0 0 -8px -8px!important; + padding: 0 15px 0 0 !important; + line-height:0; + font-size:0; + + img { + padding:0!important; + margin:0 0 0 0!important; + border:0!important; + line-height:0; + } + + } + + p { + font-size:13px; + line-height:1em; + margin-right:8px; + word-wrap:break-word; + } + + figure+h2, + figure+h2+p { + margin-left:56px; + } + + } + +} + +/*** +custom box +***/ + +/* relationImage */ +.relationImage { + + .js-gallery, .relations-img, .js-relationImage { + padding-left:32px; + + .slide { + border:1px solid @box-background; + text-align:left; + padding-right:0px; + box-shadow:none; + + img { + margin:0; + float:none; + padding:2px; + border:1px @solid @box-relation-item-border; + .border-radius (2px); + margin-right:5px; + } + + a { + margin-right:-2px; + display:inline-block; + position:relative; + + &:hover { + + .popup { + visibility:visible; + } + + } + + } + + } + + } + +} + +.js-gallery { + padding-left:32px; + img { + float:left; + padding:2px; + border:1px @solid @box-relation-item-border; + .border-radius (2px); + margin-right:5px; + } +} + +/* relationLink */ +.relationLink { + .item-list { + padding:0; + margin:0 -10px; + + li { + list-style:none; + padding-left:14px; + border-bottom:1px solid @box-relation-item-border; + + a { + text-decoration:none; + padding-left:28px; + padding-right:10px; + padding-bottom:5px; + margin-bottom:5px; + display:block; + color:@box-text; + background: url(../img/ico/eye.png) center left no-repeat; + + &:hover { + background: url(../img/ico/eye-hover.png) center left no-repeat; + } + + } + + &:last-child { + border:0; + + a { + padding-bottom:0; + margin-bottom:0; + } + + } + + + } + + } +} + +/* relationImageLink */ +.relationImageLink { + + .item { + h2 { + + } + } + + .col-md-4 { + width:30%; + float:left; + margin-left:1.2%; + + &.first-box { + margin-left:0; + } + + } + + } + +/*** +storyteller +***/ + +.storyteller { + .border-radius(10px); + background:@storyteller-background; + border:1px solid @storyteller-border; + padding-bottom:15px; + margin-bottom:20px; + .box-sizing(); + width:100%; + clear:both; + + #nav-bar { + min-height:40px; + .border-radius-top(10px); + background: #ececec; + background: -moz-linear-gradient(top, @storyteller-grandient-1 0%, @storyteller-grandient-2 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,@storyteller-grandient-1), color-stop(100%,@storyteller-grandient-2)); + background: -webkit-linear-gradient(top, @storyteller-grandient-1 0%,@storyteller-grandient-2 100%); + background: -o-linear-gradient(top, @storyteller-grandient-1 0%,@storyteller-grandient-2 100%); + background: -ms-linear-gradient(top, @storyteller-grandient-1 0%,@storyteller-grandient-2 100%); + background: linear-gradient(to bottom, @storyteller-grandient-1 0%,@storyteller-grandient-2 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='@storyteller-grandient-1', endColorstr='@storyteller-grandient-2',GradientType=0 ); + + ul { + .padding-margin-reset(); + margin-left:10px; + + + @media (max-width: 480px) { + margin-left:-1px; + margin-right:-1px; + margin-top:-1px; + } + + + li { + list-style:none; + display:inline; + padding:10px 10px; + height:40px; + float:left; + + @media (max-width: 480px) { + + display:block; + float:none; + + } + + &:hover, &.active { + + background-color: @storyteller-item-background; + + @media (max-width: 480px) { + background-color:transparent; + } + + a { + color:@text; + text-decoration:none; + border-bottom:4px solid @sidebar-background-hover; + } + + } + + border-left:1px solid @storyteller-border; + + a { + display:inline-block; + color:@storyteller-navigation-link; + text-decoration:none; + text-transform:uppercase; + } + + &:last-child { + + border-right:1px solid @storyteller-border; + + } + + } + + } + + } + + + .content-story { + + padding-top:20px; + .box-sizing(); + + .item-box { + background: @storyteller-item-background; + display:block; + width:95%; + margin:0 auto 35px auto; + padding:10px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + .box-shadow (0,0, 4px, @storyteller-shadow); + .border-radius(10px); + position:relative; + + &.small { + width:60%; + } + + &.link { + background:@storyteller-item-background url(../img/bg/bg-box-link.png) 99.8% 2px no-repeat; + .border-radius(6px); + } + + &.with-angle-icon { + background:@storyteller-item-background url(../img/bg/bg-box.png) 99.8% 2px no-repeat; + .border-radius(6px); + } + + .box-angle { + font-size:15px; + position:absolute; + right:0; + top:0; + margin:7px 5px 0 0; + + &.fa fa-link { + margin-right:8px; + margin-top:9px; + } + + } + + &.comment { + background:@storyteller-comments-background url(../img/bg/bg-box-comment.png) 99.8% 2px no-repeat; + .border-radius(6px); + + form { + margin-top:20px; + width:280px; + margin:0 auto; + + span { + width:100%; + display:block; + text-align:left; + } + + input[type="text"], textarea { + display:inline-block; + width:280px; + } + + textarea { + height:150px; + } + + + } + + } + + &.gallery { + background:@storyteller-item-background; + .border-radius(6px); + } + + .arrow-big { + background:url(../img/ico/arrow-baloon-big.png) 0 0 no-repeat; + width:18px; + height:16px; + display:block; + position:absolute; + top:0; + left:50%; + margin-left:-9px; + margin-top:-16px; + } + + iframe { width: 100%; margin: 0 0 30px 0; } + + .functions { + + h4 { + font-weight:bold; + } + + .from { + + color:@storyteller-link; + + span { + font-weight:bold; + color:@text; + } + + } + + .actions { + + border-top:1px solid @storyteller-border; + margin-top:4px; + padding-top:4px; + padding-bottom:8px; + + ul { + .padding-margin-reset(); + padding-top:8px; + + &.dx { + float:right; + + li a { + text-decoration:none; + } + + li i { + font-size:18px; + } + + } + + &.sx { + float:left; + } + + li { + list-style:none; + display:inline; + border-right:1px solid @storyteller-border; + padding:5px 10px; + + &:last-child { + border:0; + } + + .fa { + font-size:18px; + + &.fa-external-link { + float:left; + } + + &.fa-facebook-sign { + border:1px solid red; + } + + } + + i { + color:@storyteller-icon; + margin-right:5px; + } + + a { + display:inline-block; + text-decoration:none; + padding:0; + line-height:16px; + + &:hover { + text-decoration:underline; + } + + + + } + + } + + } + + } + + + } + + .archive-link { + text-align:center; + padding-top:5px; + } + + .tipe-box { + font-size:14px; + font-weight:lighter; + .padding-margin-reset(); + margin-bottom:12px; + + &.big { + font-size:20px; + } + + } + + .item-linked, .item-comment { + + figure { + margin:0 15px 0 0; + } + + padding:0; + + p { + .padding-margin-reset()!important; + } + + .title { + .padding-margin-reset(); + font-size:18px; + padding-bottom:6px; + font-weight:lighter; + + a { + color:@text; + text-decoration:none; + } + + } + + } + + .item-comment { + border-bottom:1px solid @storyteller-border; + padding-bottom:10px; + margin-bottom:10px; + + &:last-child { + border-bottom:0; + padding-bottom:0; + margin-bottom:0; + } + + } + + .ico.gallery { + background:url(../img/ico/pool.png) -1px -1159px no-repeat; + display:inline-block; + width:17px; + height:12px; + margin-left:5px; + } + + .story-gallery { + border-top:1px solid @storyteller-border; + padding-top:20px; + padding-bottom:20px; + padding-left:10px; + padding-right:10px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + + .mini-photo { + border:1px solid transparent; + padding-right:0px; + float:left; + width:82px; + height:82px; + position:relative; + margin-right:12px; + margin-bottom:12px; + + &:last-child { + margin-right:0; + } + + img { + width:82px; + height:82px; + margin:0; + float:none; + padding:2px; + margin-right:8px; + border:1px @solid @storyteller-image-border; + .border-radius (2px); + /*.glow(#F3F3F3); + .mini-shadow(@grey13); + */ + } + + &:last-child { + + &:hover { + + .popup { + + margin-left:-80px; + + .popup-arrow { + right:0; + left:auto; + margin-right:8px; + } + + } + + } + + } + + &:hover { + + .popup { + visibility:visible; + } + + } + + } + + } + + } + + } + + + ul.insights { + list-style: none; + margin: 0; + padding: 0; + + li { + float: left; + padding-right: 10px; + margin-right: 10px; + border-right: 1px solid @storyteller-border; + + &:last-child { + margin-right: 0; + padding-right: 0; + border: 0; + } + } + } +} + +/*** +nav-works +***/ + +.nav-works { + + ul { + .padding-margin-reset(); + + li { + list-style:none; + margin-bottom:10px; + + a { + font-family: @font-1; + font-weight: 600; + color:@sidebar-link; + padding-left:0; + text-transform:uppercase; + text-decoration:none; + padding-left:5px; + } + + /* sub-menu */ + + ul { + background-color:@sidebar-box-background; + margin-bottom:0; + padding-top:3px; + padding-bottom:3px; + + li { + padding:0; + margin:0; + border:0; + + a { + background:none; + margin-left:20px; + font-size:11px; + border:0; + line-height:15px; + padding:1px 2px 1px 2px; + margin-right:30px; + margin-bottom:3px; + text-transform:uppercase; + + &:hover, &.active { + background:none; + background-color:@sidebar-background-hover; + text-decoration:none; + color:@sidebar-link-hover; + } + + } + + + + } + + } + + + } + + } + +} + +/*** +gallery-slider +***/ + +#content-gallery-slider { + padding:5px; + border:1px @solid @box-border; + .border-radius (2px); + /*.glow(#F3F3F3);*/ + margin-bottom:40px; + + .flex-direction-nav { + + .flex-prev, .flex-next { + opacity:1; + top:auto; + bottom:0; + height:21px; + width:21px; + margin-bottom:-35px; + border:1px solid @color-border-button; + background:@body-background; + .border-radius (4px); + } + + .flex-prev { + left:0; + + &:after { + top:50%; + margin-top:-6px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + } + + &:after { + border-color:transparent; + border-right-color:@color-arrow-button-slider; + border-width: 6px; + right: 50%; + margin-right:-2px; + } + + + } + + .flex-next { + right:auto; + left:0; + margin-left:28px; + + &:after { + top:50%; + margin-top:-5px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + } + + &:after { + border-color:transparent; + border-left-color:@color-arrow-button-slider; + border-width: 6px; + left: 50%; + margin-left:-2px; + } + + } + + } + + .flex-control-nav { + text-align:right; + bottom:0; + margin-bottom:-30px; + + a { + font-size:0; + margin-left:4px; + box-shadow:none; + border:2px solid @sidebar-border; + background:none; + + &.flex-active { + border:2px solid @sidebar-background-hover; + } + + } + + } + +} + +/*** +my-form +***/ + +.my-form { + + margin-top:15px; + + .control-group { + border-bottom:1px solid @form-border; + padding-bottom:10px; + margin:0; + margin-bottom:10px; + + &:last-child { + border:0; + } + + } + + &.no-border-row { + + .control-group { + border-bottom:0; + } + + } + + &.all-in-row { + + .control-group, .controls, label { + border:0; + float:left; + margin:0; + width:auto; + + input[type="text"] { + margin-top:2px; + } + + input[type="submit"], + input[type="button"], + input[type="reset"], + button { + margin-top:0; + margin-right:5px; + } + + } + + .controls, label { + margin-right:15px; + } + + } + + input[type="submit"], + input[type="button"], + input[type="reset"], + button { + margin-top:15px; + margin-right:5px; + } + + input.input-large { + width:386px; + } + + input.input-small { + width:94px; + } + + select { + padding:0; + } + + select.select-large { + width:392px; + padding-top:2px; + padding-bottom:2px; + } + + select.select-medium { + width:203px; + } + + select.select-small { + width:94px; + } + + label { + width:150px; + text-transform:uppercase; + text-align:left; + float: left; + padding-top:5px; + &.large-label { + width:150px; + } + } + + textarea { + width:204px; + height:86px; + } + + .textarea-large { + width:386px; + } + + i { + color:@form-required; + } + + .controls { + margin-left:120px; + + &.with-button { + + &:after { + content:""; + clear:both; + display:block; + width:100%; + height:0px; + } + + input[type="text"] { + float:left; + margin-right:8px; + } + + input[type="submit"], + input[type="button"], + input[type="reset"], button { + margin-top:0; + margin-left:5px; + float:left; + } + + } + } + + @media (max-width: 765px) { + + .controls { + margin-left:0; + } + + } + + @media (max-width: 480px) { + + input.input-large { + width:296px; + } + + select.select-large { + width:296px; + } + + .textarea-large { + width:296px; + } + + } + + + &.login { + + border:1px @solid @box-border; + background-color:@box-background; + max-width:320px; + margin:15px auto; + display:block; + padding:15px; + .box-sizing(); + + .control-group { + border-bottom:0; + padding-bottom:0; + margin:0; + position:relative; + margin-bottom:10px; + + &:last-child { + border:0; + } + + p { + font-size:12px; + .padding-margin-reset(); + line-height:1.4em; + margin-top:-3px; + } + + } + + label { + display:none; + } + + .ico { + position:absolute; + width:20px; + height:26px; + background:#fff; + border:1px solid @form-border; + color:@form-border; + .box-sizing(); + .border-radius-left(4px); + + &.fa-user { + padding:5px 4px; + } + + &.fa-lock { + padding:5px 6px; + } + + } + + input[type="text"], + input[type="password"] { + width:100%; + padding-left:25px; + background:#fff; + .box-sizing(); + height:26px; + } + + .controls { + margin-left:0; + } + + input[type="submit"] { + margin-right:-4px; + margin-top:0; + } + + } + +} + +/* breadcrumb */ + +.breadcrumb { + + ul { + padding:0; + margin:0 0 8px 0; + + li { + list-style:none; + display:inline; + + a { + color: @breadkcrumbs-link; + text-decoration:none; + } + + &:hover { + color: @breadkcrumbs-link-hover; + } + + } + + } + +} + +/* box-title */ + +.box-title { + border-top:1px solid @box-border; + border-bottom:1px solid @box-border; + color:@text-heading; + position:relative; + padding:12px 0; + margin-bottom:10px; + + h1 { + font-size:30px; + font-family: @font-1; + font-weight: 600; + padding:0; + margin:0; + line-height:28px; + } + + h2 { + margin:0; + padding:0; + line-height:28px; + font-size:20px; + font-family: @font-1; + font-weight: 400; + } + + a.print { + width:20px; + height:20px; + position:absolute; + display:block; + bottom:15px; + right:0; + text-indent:-9999px; + background:url(../img/ico/pool.png) 1px -408px no-repeat; + } + + a.print-ico { + width:20px; + height:20px; + position:absolute; + display:block; + bottom:15px; + right:0; + text-decoration:none; + font-size:18px; + } + +} + +/* heading-row */ +.heading-row { + border-bottom:1px solid @box-border; + border-top:1px solid @box-border; + margin-bottom:25px; + padding-top:5px; + margin-top:35px; + + h2 { + .padding-margin-reset(); + } + +} + + +/* inner-menu */ + +nav.inner-menu { + margin-bottom:15px; + + ul { + margin:0; + padding:0; + + li { + list-style:none; + display:inline; + + a { + text-transform:uppercase; + color: @inner-nav-link; + font-size:12px; + display:inline-block; + margin-right:23px; + text-decoration:none; + + &:hover, &.active { + color: @inner-nav-link; + text-decoration:none; + border-bottom:4px solid @inner-nav-link-hover; + } + + } + + } + + } + +} + +/* results-content */ + +.results-content { + +.item { + + border-bottom:1px @solid @box-relation-item-border; + padding-bottom:15px; + margin-bottom:15px; + + figure { + width:135px!important; + max-height:135px; + float:left; + margin:0!important; + margin-right:15px!important; + + img { + padding:5px; + border:1px @solid @box-image-border; + /*.border-radius (2px); + .glow(#F3F3F3);*/ + float:left; + margin-bottom:8px + } + + } + + h1 { + font-size:16px; + padding:0; + margin:0; + line-height:1em; + margin-bottom:5px; + + a { + color:@color-link; + /*font-weight:lighter;*/ + text-decoration:none; + + &:hover { + text-decoration:underline; + } + + } + + } + + p { + font-size:14px; + line-height:18px; + padding:0; + margin:0; + } + + } + +} + +/* pagination */ + +.pagination { + + ul { + border:1px @solid @box-relation-item-border; + padding:0; + width:100%; + min-height:29px; + text-align:center; + background-color:@box-background; + + li { + display:inline; + padding-left:5px; + + a { + border:0; + background:none; + float:none; + color:@text; + display:inline-block; + padding-top:0; + margin-top:7px; + padding-bottom:0; + line-height:1em; + font-size:14px; + outline:none; + text-decoration:none; + padding-left:6px; + border-left:1px @solid @box-relation-item-border; + + &:hover { + text-decoration:underline; + } + + } + + &.active a { + text-decoration:underline; + } + + &:first-child > a { + border:0; + padding-left:17px; + background:url(../img/ico/pool.png) -6px -772px no-repeat; + } + + &:last-child > a { + padding-right:17px; + background:url(../img/ico/pool.png) 78px -727px no-repeat; + } + + } + + } + + } + +/*** +galleria-io +***/ +.wrapper-galleria-io { + padding:5px; + border:1px @solid @box-border; + .border-radius (2px); + /*.glow(#F3F3F3);*/ + margin-bottom:40px; + clear:both; + + &.gallery { + + .galleria-thumbnails-container { + border-top:1px solid @black; + } + + #galleria{height:499px} + + .galleria-info-description { + margin-top:3px!important; + } + + } + + + &.slider { + padding:0; + border:0; + /*.glow(#fff);*/ + } + + .content-galleria-io { + max-width:100%; + font-family: @font-1; + + &:hover { + + .galleria-info-description { + opacity:1; + filter: alpha(opacity=100); + } + + } + + .galleria-info { + margin-bottom:10px; + + } + + + .galleria-info-description { + opacity:0; + .transition(); + filter: alpha(opacity=0); + position:absolute; + margin:0 0 30px -15px; + bottom:0; + display:block; + width:100%; + background: url(../img/bg/bg-description.png) repeat; + padding:5px 15px 6px 15px; + padding-right:40px; + .box-sizing(); + border-top:1px solid #000; + border-right:1px solid #000; + width:430px; + } + + } + + .galleria-counter { + margin-bottom:10px; + margin-right:46px; + } + +#galleria.sfogliatore { + + .galleria-info { + position: absolute; + height:15px; + left:0px; + bottom:0; + margin-bottom:5px!important; + color: #bbb; + margin-right:40px; + } + + .galleria-info-description { + margin:0 0 16px -5px; + + } + + } + +#galleria.slider { + + .galleria-info-text { + top:auto; + bottom:0; + margin-bottom:-12px; + } + + } + +} + + +article.relationImageLink { + figure { + float: left; + } + img { + max-height: 56px; + max-width: 100%; + width: 100%; + float:left; + margin:0!important; + } +} + + +/* imageList */ + +.imageList { + clear:both; + width:100%; + padding-left:33px; + margin-bottom:20px !important; + + img { + width:auto!important; + padding:2px; + border:1px @solid @box-image-border; + .border-radius (2px); + /*.glow(#F3F3F3); + .mini-shadow(@grey13);*/ + } + +} + + +/* Timeline */ +.storyjs-embed.sized-embed { + border-radius: 0; +} + +.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content h3, .vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3 { + color: @timeline-theme !important; +} + +.vco-timeline .vco-navigation .timenav-background .timenav-line, +.vco-timeline .vco-navigation .timenav .content .marker.active .line, +.vco-timeline .vco-navigation .timenav .content .marker.active .dot { + background-color: @timeline-theme !important; +} + +.vco-timeline .vco-navigation .timenav .content .marker .line .event-line { + background: @timeline-theme !important; +} + +.vco-slider .slider-item .content .content-container .text .container p { + text-align: left; +} + +/* ImageHotspot */ + +.movio-hotspotContainer { + position: relative; + border:1px @solid @box-image-border; + .border-radius (2px); + padding: 3px; + display: inline-block; + width: 100%; + + .movio-imageHotspot-scale { + position: absolute; + left: 0; + top: 0; + } + + + .movio-hotspot, .movio-hotspot-circle { + border: 2px solid @white; + .box-shadow(0, 0, 2px, @black); + position: absolute; + z-index: 999; + cursor: pointer; + + &:hover { + border: 2px solid @color-link; + } + } + + .movio-hotspot-circle { + border-radius: 50%; + } + + img { + max-width: 100%; + height: auto; + } + + +} + +/* in-grid */ + +.results-content { + +.in-grid { + border:1px solid @box-relation-item-border; + background:@box-relation-item-background; + .border-radius(2px); + margin-bottom:8px; + padding:8px; + height:88px; + padding-bottom:0; + padding-top:0; + padding-right:0; + + .wrapper-link { + display: none; + } + + h2 { + line-height:1em; + padding:8px 8px 4px 0; + margin:0; + font-size:13px; + + a { + color:@black; + text-decoration:none; + + &:hover { + text-decoration:none; + } + + } + + } + + figure { + + width:auto!important; + margin:0 0 0 -8px!important; + padding: 0 15px 0 0 !important; + line-height:0; + font-size:0; + float:left; + height:auto!important; + + img { + padding:0!important; + margin:0 0 0 0!important; + border:0!important; + line-height:0; + } + + } + + p { + font-size:13px; + line-height:1em; + margin-right:8px; + text-align:left!important; + word-wrap:break-word; + } + + } +} + +/* superzoom */ +span.superzoom { + border-radius: 4px; + padding: 2px 8px 4px; + position: absolute; + width:60px; + color:@form-buttonPrimary-text; + background:@form-button-primary url(../img/ico/search.png) 3px 5px no-repeat; + text-align: right; + + &.small { + text-indent: 100%; + overflow: hidden; + width:22px; + color:@form-button-primary; + font-size:0; + padding: 0; + height:22px; + background:@form-button-primary url(../img/ico/search.png) center no-repeat; + } +} + +div.menu-dropdown { + ul, ul ul { + padding:0; + margin: 0; + } + ul li, ul ul li { + list-style-type: none; + display: inline-block; + } + ul li a, ul li ul li a { + text-decoration: none; + color: @metanavigation-link; + padding: 5px; + display:inline-block; + } + ul li ul li a { + width: 150px; + background: @metanavigation-background; + } + ul li ul li a:hover { + background: @metanavigation-background-hover; + color: @metanavigation-link-hover; + } + ul li { + position: relative; + } + ul li ul { + display:none; + position: absolute; + top: 20px; + left: -130px; + width: 150px; + z-index: 1000; + } + ul li:hover ul { + display:block; + } + + .icon { + font-size: 120%; + } +} + +/*Nuove modifiche CSS per la skin MapMarker.html*/ +div#map-popup-background { + margin-top: -9999px; + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + z-index: 2; +} +/** +/* attach +*/ +.attach { + padding: 10px; + border:1px @solid @box-border; + + .box-title { + font-size: 18px; + border-bottom: 0; + .pmr(); + padding-bottom: 10px; + color:@text; + } + + .container { + border:0; + background: none; + padding:0; + } + + ul { + .pmr(); + + li { + &.active { + a { + background:@bg-link-attach-hover; + color:@color-link-attach-hover; + + &:hover { + background:@bg-link-attach-hover; + color:@color-link-attach-hover; + } + + } + } + + a { + background:@bg-link-attach; + color:@color-link-attach; + + &:hover { + background:@bg-link-attach-hover; + color:@color-link-attach-hover; + } + + } + + } + + } + +} +/** +/* block-inner-aside +*/ +.block-inner-aside { + &.pull-right { + margin-left: 15px; + } + + figure.main-img.align-right { + margin-left: 0; + } +} + +body.page .block-inner-aside { + +h2, +h3, +h4, +h5, +h6 { + margin-top: 0; + padding-top: 0 !important; + } +} + +body.page .block-inner-aside figure.main-img.align-right { + margin-left: 0 !important; +} + +/** +/* new-properties +*/ +.new-properties { + border:1px @solid @box-border; + padding:10px; + background: @bg-dl; + + dd, dt { + float: left; + padding:5px 0; + border-top:1px @solid @box-border; + + &:first-child, &:nth-child(2) { + border-top:0; + } + + } + + dt { + clear: both; + width: 23%; + } + + dd { + width:77%; + } + +} +/** +/* tag-list +*/ +.tag-list, .insights { + .pmr(); + + li { + display: inline; + + a { + display: inline-block; + font-size: 12px; + color: @color-tag-attach; + background: @bg-tag-attach; + padding: 2px 5px; + .border-radius(4px); + margin-top: 2px; + text-decoration: none; + + &:hover { + text-decoration: none; + color: @color-tag-attach-hover; + background: @bg-tag-attach-hover; + } + + } + + } + +} +/** +/* block-my-pop-up +*/ +.block-my-pop-up { + position: absolute; + max-width: 490px; + background:@bg-block-my-pop-up; + z-index: 99; + border: 4px @solid @box-border; + + .arrow { + width: 0; + height: 0; + border-left:15px solid transparent; + border-right:15px solid transparent; + border-bottom:15px solid @box-border; + position: absolute; + } + + .block-title { + padding: 10px; + font-size:20px; + border-bottom: 1px @solid @box-border; + } + + .block-my-pop-up-container { + position: relative; + padding:10px; + padding-top: 0; + + &.no-padding { + padding:0; + margin-top: -15px; + } + + } + + .results-content { + position: relative; + } + + +} + +.google-maps img { + max-width: none !important; +} + +.sx article.box .container { + min-height: 0; +} diff --git a/src/static/movio/templates/Movio/less/font-awesome/bordered-pulled.less b/src/static/movio/templates/Movio/less/font-awesome/bordered-pulled.less new file mode 100644 index 0000000..9bb4d3a --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/bordered-pulled.less @@ -0,0 +1,16 @@ +// Bordered & Pulled +// ------------------------- + +.@{fa-css-prefix}-border { + padding: .2em .25em .15em; + border: @solid .08em @fa-border-color; + border-radius: .1em; +} + +.pull-right { float: right; } +.pull-left { float: left; } + +.@{fa-css-prefix} { + &.pull-left { margin-right: .3em; } + &.pull-right { margin-left: .3em; } +} diff --git a/src/static/movio/templates/Movio/less/font-awesome/core.less b/src/static/movio/templates/Movio/less/font-awesome/core.less new file mode 100644 index 0000000..6d223bc --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/core.less @@ -0,0 +1,12 @@ +// Base Class Definition +// ------------------------- + +.@{fa-css-prefix} { + display: inline-block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/src/static/movio/templates/Movio/less/font-awesome/fixed-width.less b/src/static/movio/templates/Movio/less/font-awesome/fixed-width.less new file mode 100644 index 0000000..110289f --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/fixed-width.less @@ -0,0 +1,6 @@ +// Fixed Width Icons +// ------------------------- +.@{fa-css-prefix}-fw { + width: (18em / 14); + text-align: center; +} diff --git a/src/static/movio/templates/Movio/less/font-awesome/font-awesome.less b/src/static/movio/templates/Movio/less/font-awesome/font-awesome.less new file mode 100644 index 0000000..96d2f22 --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/font-awesome.less @@ -0,0 +1,17 @@ +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ + +@import "variables"; +@import "mixins"; +@import "path"; +@import "core"; +@import "larger"; +@import "fixed-width"; +@import "list"; +@import "bordered-pulled"; +@import "spinning"; +@import "rotated-flipped"; +@import "stacked"; +@import "icons"; diff --git a/src/static/movio/templates/Movio/less/font-awesome/icons.less b/src/static/movio/templates/Movio/less/font-awesome/icons.less new file mode 100644 index 0000000..bf0f856 --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/icons.less @@ -0,0 +1,412 @@ +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ + +.@{fa-css-prefix}-glass:before { content: @fa-var-glass; } +.@{fa-css-prefix}-music:before { content: @fa-var-music; } +.@{fa-css-prefix}-search:before { content: @fa-var-search; } +.@{fa-css-prefix}-envelope-o:before { content: @fa-var-envelope-o; } +.@{fa-css-prefix}-heart:before { content: @fa-var-heart; } +.@{fa-css-prefix}-star:before { content: @fa-var-star; } +.@{fa-css-prefix}-star-o:before { content: @fa-var-star-o; } +.@{fa-css-prefix}-user:before { content: @fa-var-user; } +.@{fa-css-prefix}-film:before { content: @fa-var-film; } +.@{fa-css-prefix}-th-large:before { content: @fa-var-th-large; } +.@{fa-css-prefix}-th:before { content: @fa-var-th; } +.@{fa-css-prefix}-th-list:before { content: @fa-var-th-list; } +.@{fa-css-prefix}-check:before { content: @fa-var-check; } +.@{fa-css-prefix}-times:before { content: @fa-var-times; } +.@{fa-css-prefix}-search-plus:before { content: @fa-var-search-plus; } +.@{fa-css-prefix}-search-minus:before { content: @fa-var-search-minus; } +.@{fa-css-prefix}-power-off:before { content: @fa-var-power-off; } +.@{fa-css-prefix}-signal:before { content: @fa-var-signal; } +.@{fa-css-prefix}-gear:before, +.@{fa-css-prefix}-cog:before { content: @fa-var-cog; } +.@{fa-css-prefix}-trash-o:before { content: @fa-var-trash-o; } +.@{fa-css-prefix}-home:before { content: @fa-var-home; } +.@{fa-css-prefix}-file-o:before { content: @fa-var-file-o; } +.@{fa-css-prefix}-clock-o:before { content: @fa-var-clock-o; } +.@{fa-css-prefix}-road:before { content: @fa-var-road; } +.@{fa-css-prefix}-download:before { content: @fa-var-download; } +.@{fa-css-prefix}-arrow-circle-o-down:before { content: @fa-var-arrow-circle-o-down; } +.@{fa-css-prefix}-arrow-circle-o-up:before { content: @fa-var-arrow-circle-o-up; } +.@{fa-css-prefix}-inbox:before { content: @fa-var-inbox; } +.@{fa-css-prefix}-play-circle-o:before { content: @fa-var-play-circle-o; } +.@{fa-css-prefix}-rotate-right:before, +.@{fa-css-prefix}-repeat:before { content: @fa-var-repeat; } +.@{fa-css-prefix}-refresh:before { content: @fa-var-refresh; } +.@{fa-css-prefix}-list-alt:before { content: @fa-var-list-alt; } +.@{fa-css-prefix}-lock:before { content: @fa-var-lock; } +.@{fa-css-prefix}-flag:before { content: @fa-var-flag; } +.@{fa-css-prefix}-headphones:before { content: @fa-var-headphones; } +.@{fa-css-prefix}-volume-off:before { content: @fa-var-volume-off; } +.@{fa-css-prefix}-volume-down:before { content: @fa-var-volume-down; } +.@{fa-css-prefix}-volume-up:before { content: @fa-var-volume-up; } +.@{fa-css-prefix}-qrcode:before { content: @fa-var-qrcode; } +.@{fa-css-prefix}-barcode:before { content: @fa-var-barcode; } +.@{fa-css-prefix}-tag:before { content: @fa-var-tag; } +.@{fa-css-prefix}-tags:before { content: @fa-var-tags; } +.@{fa-css-prefix}-book:before { content: @fa-var-book; } +.@{fa-css-prefix}-bookmark:before { content: @fa-var-bookmark; } +.@{fa-css-prefix}-print:before { content: @fa-var-print; } +.@{fa-css-prefix}-camera:before { content: @fa-var-camera; } +.@{fa-css-prefix}-font:before { content: @fa-var-font; } +.@{fa-css-prefix}-bold:before { content: @fa-var-bold; } +.@{fa-css-prefix}-italic:before { content: @fa-var-italic; } +.@{fa-css-prefix}-text-height:before { content: @fa-var-text-height; } +.@{fa-css-prefix}-text-width:before { content: @fa-var-text-width; } +.@{fa-css-prefix}-align-left:before { content: @fa-var-align-left; } +.@{fa-css-prefix}-align-center:before { content: @fa-var-align-center; } +.@{fa-css-prefix}-align-right:before { content: @fa-var-align-right; } +.@{fa-css-prefix}-align-justify:before { content: @fa-var-align-justify; } +.@{fa-css-prefix}-list:before { content: @fa-var-list; } +.@{fa-css-prefix}-dedent:before, +.@{fa-css-prefix}-outdent:before { content: @fa-var-outdent; } +.@{fa-css-prefix}-indent:before { content: @fa-var-indent; } +.@{fa-css-prefix}-video-camera:before { content: @fa-var-video-camera; } +.@{fa-css-prefix}-picture-o:before { content: @fa-var-picture-o; } +.@{fa-css-prefix}-pencil:before { content: @fa-var-pencil; } +.@{fa-css-prefix}-map-marker:before { content: @fa-var-map-marker; } +.@{fa-css-prefix}-adjust:before { content: @fa-var-adjust; } +.@{fa-css-prefix}-tint:before { content: @fa-var-tint; } +.@{fa-css-prefix}-edit:before, +.@{fa-css-prefix}-pencil-square-o:before { content: @fa-var-pencil-square-o; } +.@{fa-css-prefix}-share-square-o:before { content: @fa-var-share-square-o; } +.@{fa-css-prefix}-check-square-o:before { content: @fa-var-check-square-o; } +.@{fa-css-prefix}-arrows:before { content: @fa-var-arrows; } +.@{fa-css-prefix}-step-backward:before { content: @fa-var-step-backward; } +.@{fa-css-prefix}-fast-backward:before { content: @fa-var-fast-backward; } +.@{fa-css-prefix}-backward:before { content: @fa-var-backward; } +.@{fa-css-prefix}-play:before { content: @fa-var-play; } +.@{fa-css-prefix}-pause:before { content: @fa-var-pause; } +.@{fa-css-prefix}-stop:before { content: @fa-var-stop; } +.@{fa-css-prefix}-forward:before { content: @fa-var-forward; } +.@{fa-css-prefix}-fast-forward:before { content: @fa-var-fast-forward; } +.@{fa-css-prefix}-step-forward:before { content: @fa-var-step-forward; } +.@{fa-css-prefix}-eject:before { content: @fa-var-eject; } +.@{fa-css-prefix}-chevron-left:before { content: @fa-var-chevron-left; } +.@{fa-css-prefix}-chevron-right:before { content: @fa-var-chevron-right; } +.@{fa-css-prefix}-plus-circle:before { content: @fa-var-plus-circle; } +.@{fa-css-prefix}-minus-circle:before { content: @fa-var-minus-circle; } +.@{fa-css-prefix}-times-circle:before { content: @fa-var-times-circle; } +.@{fa-css-prefix}-check-circle:before { content: @fa-var-check-circle; } +.@{fa-css-prefix}-question-circle:before { content: @fa-var-question-circle; } +.@{fa-css-prefix}-info-circle:before { content: @fa-var-info-circle; } +.@{fa-css-prefix}-crosshairs:before { content: @fa-var-crosshairs; } +.@{fa-css-prefix}-times-circle-o:before { content: @fa-var-times-circle-o; } +.@{fa-css-prefix}-check-circle-o:before { content: @fa-var-check-circle-o; } +.@{fa-css-prefix}-ban:before { content: @fa-var-ban; } +.@{fa-css-prefix}-arrow-left:before { content: @fa-var-arrow-left; } +.@{fa-css-prefix}-arrow-right:before { content: @fa-var-arrow-right; } +.@{fa-css-prefix}-arrow-up:before { content: @fa-var-arrow-up; } +.@{fa-css-prefix}-arrow-down:before { content: @fa-var-arrow-down; } +.@{fa-css-prefix}-mail-forward:before, +.@{fa-css-prefix}-share:before { content: @fa-var-share; } +.@{fa-css-prefix}-expand:before { content: @fa-var-expand; } +.@{fa-css-prefix}-compress:before { content: @fa-var-compress; } +.@{fa-css-prefix}-plus:before { content: @fa-var-plus; } +.@{fa-css-prefix}-minus:before { content: @fa-var-minus; } +.@{fa-css-prefix}-asterisk:before { content: @fa-var-asterisk; } +.@{fa-css-prefix}-exclamation-circle:before { content: @fa-var-exclamation-circle; } +.@{fa-css-prefix}-gift:before { content: @fa-var-gift; } +.@{fa-css-prefix}-leaf:before { content: @fa-var-leaf; } +.@{fa-css-prefix}-fire:before { content: @fa-var-fire; } +.@{fa-css-prefix}-eye:before { content: @fa-var-eye; } +.@{fa-css-prefix}-eye-slash:before { content: @fa-var-eye-slash; } +.@{fa-css-prefix}-warning:before, +.@{fa-css-prefix}-exclamation-triangle:before { content: @fa-var-exclamation-triangle; } +.@{fa-css-prefix}-plane:before { content: @fa-var-plane; } +.@{fa-css-prefix}-calendar:before { content: @fa-var-calendar; } +.@{fa-css-prefix}-random:before { content: @fa-var-random; } +.@{fa-css-prefix}-comment:before { content: @fa-var-comment; } +.@{fa-css-prefix}-magnet:before { content: @fa-var-magnet; } +.@{fa-css-prefix}-chevron-up:before { content: @fa-var-chevron-up; } +.@{fa-css-prefix}-chevron-down:before { content: @fa-var-chevron-down; } +.@{fa-css-prefix}-retweet:before { content: @fa-var-retweet; } +.@{fa-css-prefix}-shopping-cart:before { content: @fa-var-shopping-cart; } +.@{fa-css-prefix}-folder:before { content: @fa-var-folder; } +.@{fa-css-prefix}-folder-open:before { content: @fa-var-folder-open; } +.@{fa-css-prefix}-arrows-v:before { content: @fa-var-arrows-v; } +.@{fa-css-prefix}-arrows-h:before { content: @fa-var-arrows-h; } +.@{fa-css-prefix}-bar-chart-o:before { content: @fa-var-bar-chart-o; } +.@{fa-css-prefix}-twitter-square:before { content: @fa-var-twitter-square; } +.@{fa-css-prefix}-facebook-square:before { content: @fa-var-facebook-square; } +.@{fa-css-prefix}-camera-retro:before { content: @fa-var-camera-retro; } +.@{fa-css-prefix}-key:before { content: @fa-var-key; } +.@{fa-css-prefix}-gears:before, +.@{fa-css-prefix}-cogs:before { content: @fa-var-cogs; } +.@{fa-css-prefix}-comments:before { content: @fa-var-comments; } +.@{fa-css-prefix}-thumbs-o-up:before { content: @fa-var-thumbs-o-up; } +.@{fa-css-prefix}-thumbs-o-down:before { content: @fa-var-thumbs-o-down; } +.@{fa-css-prefix}-star-half:before { content: @fa-var-star-half; } +.@{fa-css-prefix}-heart-o:before { content: @fa-var-heart-o; } +.@{fa-css-prefix}-sign-out:before { content: @fa-var-sign-out; } +.@{fa-css-prefix}-linkedin-square:before { content: @fa-var-linkedin-square; } +.@{fa-css-prefix}-thumb-tack:before { content: @fa-var-thumb-tack; } +.@{fa-css-prefix}-external-link:before { content: @fa-var-external-link; } +.@{fa-css-prefix}-sign-in:before { content: @fa-var-sign-in; } +.@{fa-css-prefix}-trophy:before { content: @fa-var-trophy; } +.@{fa-css-prefix}-github-square:before { content: @fa-var-github-square; } +.@{fa-css-prefix}-upload:before { content: @fa-var-upload; } +.@{fa-css-prefix}-lemon-o:before { content: @fa-var-lemon-o; } +.@{fa-css-prefix}-phone:before { content: @fa-var-phone; } +.@{fa-css-prefix}-square-o:before { content: @fa-var-square-o; } +.@{fa-css-prefix}-bookmark-o:before { content: @fa-var-bookmark-o; } +.@{fa-css-prefix}-phone-square:before { content: @fa-var-phone-square; } +.@{fa-css-prefix}-twitter:before { content: @fa-var-twitter; } +.@{fa-css-prefix}-facebook:before { content: @fa-var-facebook; } +.@{fa-css-prefix}-github:before { content: @fa-var-github; } +.@{fa-css-prefix}-unlock:before { content: @fa-var-unlock; } +.@{fa-css-prefix}-credit-card:before { content: @fa-var-credit-card; } +.@{fa-css-prefix}-rss:before { content: @fa-var-rss; } +.@{fa-css-prefix}-hdd-o:before { content: @fa-var-hdd-o; } +.@{fa-css-prefix}-bullhorn:before { content: @fa-var-bullhorn; } +.@{fa-css-prefix}-bell:before { content: @fa-var-bell; } +.@{fa-css-prefix}-certificate:before { content: @fa-var-certificate; } +.@{fa-css-prefix}-hand-o-right:before { content: @fa-var-hand-o-right; } +.@{fa-css-prefix}-hand-o-left:before { content: @fa-var-hand-o-left; } +.@{fa-css-prefix}-hand-o-up:before { content: @fa-var-hand-o-up; } +.@{fa-css-prefix}-hand-o-down:before { content: @fa-var-hand-o-down; } +.@{fa-css-prefix}-arrow-circle-left:before { content: @fa-var-arrow-circle-left; } +.@{fa-css-prefix}-arrow-circle-right:before { content: @fa-var-arrow-circle-right; } +.@{fa-css-prefix}-arrow-circle-up:before { content: @fa-var-arrow-circle-up; } +.@{fa-css-prefix}-arrow-circle-down:before { content: @fa-var-arrow-circle-down; } +.@{fa-css-prefix}-globe:before { content: @fa-var-globe; } +.@{fa-css-prefix}-wrench:before { content: @fa-var-wrench; } +.@{fa-css-prefix}-tasks:before { content: @fa-var-tasks; } +.@{fa-css-prefix}-filter:before { content: @fa-var-filter; } +.@{fa-css-prefix}-briefcase:before { content: @fa-var-briefcase; } +.@{fa-css-prefix}-arrows-alt:before { content: @fa-var-arrows-alt; } +.@{fa-css-prefix}-group:before, +.@{fa-css-prefix}-users:before { content: @fa-var-users; } +.@{fa-css-prefix}-chain:before, +.@{fa-css-prefix}-link:before { content: @fa-var-link; } +.@{fa-css-prefix}-cloud:before { content: @fa-var-cloud; } +.@{fa-css-prefix}-flask:before { content: @fa-var-flask; } +.@{fa-css-prefix}-cut:before, +.@{fa-css-prefix}-scissors:before { content: @fa-var-scissors; } +.@{fa-css-prefix}-copy:before, +.@{fa-css-prefix}-files-o:before { content: @fa-var-files-o; } +.@{fa-css-prefix}-paperclip:before { content: @fa-var-paperclip; } +.@{fa-css-prefix}-save:before, +.@{fa-css-prefix}-floppy-o:before { content: @fa-var-floppy-o; } +.@{fa-css-prefix}-square:before { content: @fa-var-square; } +.@{fa-css-prefix}-bars:before { content: @fa-var-bars; } +.@{fa-css-prefix}-list-ul:before { content: @fa-var-list-ul; } +.@{fa-css-prefix}-list-ol:before { content: @fa-var-list-ol; } +.@{fa-css-prefix}-strikethrough:before { content: @fa-var-strikethrough; } +.@{fa-css-prefix}-underline:before { content: @fa-var-underline; } +.@{fa-css-prefix}-table:before { content: @fa-var-table; } +.@{fa-css-prefix}-magic:before { content: @fa-var-magic; } +.@{fa-css-prefix}-truck:before { content: @fa-var-truck; } +.@{fa-css-prefix}-pinterest:before { content: @fa-var-pinterest; } +.@{fa-css-prefix}-pinterest-square:before { content: @fa-var-pinterest-square; } +.@{fa-css-prefix}-google-plus-square:before { content: @fa-var-google-plus-square; } +.@{fa-css-prefix}-google-plus:before { content: @fa-var-google-plus; } +.@{fa-css-prefix}-money:before { content: @fa-var-money; } +.@{fa-css-prefix}-caret-down:before { content: @fa-var-caret-down; } +.@{fa-css-prefix}-caret-up:before { content: @fa-var-caret-up; } +.@{fa-css-prefix}-caret-left:before { content: @fa-var-caret-left; } +.@{fa-css-prefix}-caret-right:before { content: @fa-var-caret-right; } +.@{fa-css-prefix}-columns:before { content: @fa-var-columns; } +.@{fa-css-prefix}-unsorted:before, +.@{fa-css-prefix}-sort:before { content: @fa-var-sort; } +.@{fa-css-prefix}-sort-down:before, +.@{fa-css-prefix}-sort-asc:before { content: @fa-var-sort-asc; } +.@{fa-css-prefix}-sort-up:before, +.@{fa-css-prefix}-sort-desc:before { content: @fa-var-sort-desc; } +.@{fa-css-prefix}-envelope:before { content: @fa-var-envelope; } +.@{fa-css-prefix}-linkedin:before { content: @fa-var-linkedin; } +.@{fa-css-prefix}-rotate-left:before, +.@{fa-css-prefix}-undo:before { content: @fa-var-undo; } +.@{fa-css-prefix}-legal:before, +.@{fa-css-prefix}-gavel:before { content: @fa-var-gavel; } +.@{fa-css-prefix}-dashboard:before, +.@{fa-css-prefix}-tachometer:before { content: @fa-var-tachometer; } +.@{fa-css-prefix}-comment-o:before { content: @fa-var-comment-o; } +.@{fa-css-prefix}-comments-o:before { content: @fa-var-comments-o; } +.@{fa-css-prefix}-flash:before, +.@{fa-css-prefix}-bolt:before { content: @fa-var-bolt; } +.@{fa-css-prefix}-sitemap:before { content: @fa-var-sitemap; } +.@{fa-css-prefix}-umbrella:before { content: @fa-var-umbrella; } +.@{fa-css-prefix}-paste:before, +.@{fa-css-prefix}-clipboard:before { content: @fa-var-clipboard; } +.@{fa-css-prefix}-lightbulb-o:before { content: @fa-var-lightbulb-o; } +.@{fa-css-prefix}-exchange:before { content: @fa-var-exchange; } +.@{fa-css-prefix}-cloud-download:before { content: @fa-var-cloud-download; } +.@{fa-css-prefix}-cloud-upload:before { content: @fa-var-cloud-upload; } +.@{fa-css-prefix}-user-md:before { content: @fa-var-user-md; } +.@{fa-css-prefix}-stethoscope:before { content: @fa-var-stethoscope; } +.@{fa-css-prefix}-suitcase:before { content: @fa-var-suitcase; } +.@{fa-css-prefix}-bell-o:before { content: @fa-var-bell-o; } +.@{fa-css-prefix}-coffee:before { content: @fa-var-coffee; } +.@{fa-css-prefix}-cutlery:before { content: @fa-var-cutlery; } +.@{fa-css-prefix}-file-text-o:before { content: @fa-var-file-text-o; } +.@{fa-css-prefix}-building-o:before { content: @fa-var-building-o; } +.@{fa-css-prefix}-hospital-o:before { content: @fa-var-hospital-o; } +.@{fa-css-prefix}-ambulance:before { content: @fa-var-ambulance; } +.@{fa-css-prefix}-medkit:before { content: @fa-var-medkit; } +.@{fa-css-prefix}-fighter-jet:before { content: @fa-var-fighter-jet; } +.@{fa-css-prefix}-beer:before { content: @fa-var-beer; } +.@{fa-css-prefix}-h-square:before { content: @fa-var-h-square; } +.@{fa-css-prefix}-plus-square:before { content: @fa-var-plus-square; } +.@{fa-css-prefix}-angle-double-left:before { content: @fa-var-angle-double-left; } +.@{fa-css-prefix}-angle-double-right:before { content: @fa-var-angle-double-right; } +.@{fa-css-prefix}-angle-double-up:before { content: @fa-var-angle-double-up; } +.@{fa-css-prefix}-angle-double-down:before { content: @fa-var-angle-double-down; } +.@{fa-css-prefix}-angle-left:before { content: @fa-var-angle-left; } +.@{fa-css-prefix}-angle-right:before { content: @fa-var-angle-right; } +.@{fa-css-prefix}-angle-up:before { content: @fa-var-angle-up; } +.@{fa-css-prefix}-angle-down:before { content: @fa-var-angle-down; } +.@{fa-css-prefix}-desktop:before { content: @fa-var-desktop; } +.@{fa-css-prefix}-laptop:before { content: @fa-var-laptop; } +.@{fa-css-prefix}-tablet:before { content: @fa-var-tablet; } +.@{fa-css-prefix}-mobile-phone:before, +.@{fa-css-prefix}-mobile:before { content: @fa-var-mobile; } +.@{fa-css-prefix}-circle-o:before { content: @fa-var-circle-o; } +.@{fa-css-prefix}-quote-left:before { content: @fa-var-quote-left; } +.@{fa-css-prefix}-quote-right:before { content: @fa-var-quote-right; } +.@{fa-css-prefix}-spinner:before { content: @fa-var-spinner; } +.@{fa-css-prefix}-circle:before { content: @fa-var-circle; } +.@{fa-css-prefix}-mail-reply:before, +.@{fa-css-prefix}-reply:before { content: @fa-var-reply; } +.@{fa-css-prefix}-github-alt:before { content: @fa-var-github-alt; } +.@{fa-css-prefix}-folder-o:before { content: @fa-var-folder-o; } +.@{fa-css-prefix}-folder-open-o:before { content: @fa-var-folder-open-o; } +.@{fa-css-prefix}-smile-o:before { content: @fa-var-smile-o; } +.@{fa-css-prefix}-frown-o:before { content: @fa-var-frown-o; } +.@{fa-css-prefix}-meh-o:before { content: @fa-var-meh-o; } +.@{fa-css-prefix}-gamepad:before { content: @fa-var-gamepad; } +.@{fa-css-prefix}-keyboard-o:before { content: @fa-var-keyboard-o; } +.@{fa-css-prefix}-flag-o:before { content: @fa-var-flag-o; } +.@{fa-css-prefix}-flag-checkered:before { content: @fa-var-flag-checkered; } +.@{fa-css-prefix}-terminal:before { content: @fa-var-terminal; } +.@{fa-css-prefix}-code:before { content: @fa-var-code; } +.@{fa-css-prefix}-reply-all:before { content: @fa-var-reply-all; } +.@{fa-css-prefix}-mail-reply-all:before { content: @fa-var-mail-reply-all; } +.@{fa-css-prefix}-star-half-empty:before, +.@{fa-css-prefix}-star-half-full:before, +.@{fa-css-prefix}-star-half-o:before { content: @fa-var-star-half-o; } +.@{fa-css-prefix}-location-arrow:before { content: @fa-var-location-arrow; } +.@{fa-css-prefix}-crop:before { content: @fa-var-crop; } +.@{fa-css-prefix}-code-fork:before { content: @fa-var-code-fork; } +.@{fa-css-prefix}-unlink:before, +.@{fa-css-prefix}-chain-broken:before { content: @fa-var-chain-broken; } +.@{fa-css-prefix}-question:before { content: @fa-var-question; } +.@{fa-css-prefix}-info:before { content: @fa-var-info; } +.@{fa-css-prefix}-exclamation:before { content: @fa-var-exclamation; } +.@{fa-css-prefix}-superscript:before { content: @fa-var-superscript; } +.@{fa-css-prefix}-subscript:before { content: @fa-var-subscript; } +.@{fa-css-prefix}-eraser:before { content: @fa-var-eraser; } +.@{fa-css-prefix}-puzzle-piece:before { content: @fa-var-puzzle-piece; } +.@{fa-css-prefix}-microphone:before { content: @fa-var-microphone; } +.@{fa-css-prefix}-microphone-slash:before { content: @fa-var-microphone-slash; } +.@{fa-css-prefix}-shield:before { content: @fa-var-shield; } +.@{fa-css-prefix}-calendar-o:before { content: @fa-var-calendar-o; } +.@{fa-css-prefix}-fire-extinguisher:before { content: @fa-var-fire-extinguisher; } +.@{fa-css-prefix}-rocket:before { content: @fa-var-rocket; } +.@{fa-css-prefix}-maxcdn:before { content: @fa-var-maxcdn; } +.@{fa-css-prefix}-chevron-circle-left:before { content: @fa-var-chevron-circle-left; } +.@{fa-css-prefix}-chevron-circle-right:before { content: @fa-var-chevron-circle-right; } +.@{fa-css-prefix}-chevron-circle-up:before { content: @fa-var-chevron-circle-up; } +.@{fa-css-prefix}-chevron-circle-down:before { content: @fa-var-chevron-circle-down; } +.@{fa-css-prefix}-html5:before { content: @fa-var-html5; } +.@{fa-css-prefix}-css3:before { content: @fa-var-css3; } +.@{fa-css-prefix}-anchor:before { content: @fa-var-anchor; } +.@{fa-css-prefix}-unlock-alt:before { content: @fa-var-unlock-alt; } +.@{fa-css-prefix}-bullseye:before { content: @fa-var-bullseye; } +.@{fa-css-prefix}-ellipsis-h:before { content: @fa-var-ellipsis-h; } +.@{fa-css-prefix}-ellipsis-v:before { content: @fa-var-ellipsis-v; } +.@{fa-css-prefix}-rss-square:before { content: @fa-var-rss-square; } +.@{fa-css-prefix}-play-circle:before { content: @fa-var-play-circle; } +.@{fa-css-prefix}-ticket:before { content: @fa-var-ticket; } +.@{fa-css-prefix}-minus-square:before { content: @fa-var-minus-square; } +.@{fa-css-prefix}-minus-square-o:before { content: @fa-var-minus-square-o; } +.@{fa-css-prefix}-level-up:before { content: @fa-var-level-up; } +.@{fa-css-prefix}-level-down:before { content: @fa-var-level-down; } +.@{fa-css-prefix}-check-square:before { content: @fa-var-check-square; } +.@{fa-css-prefix}-pencil-square:before { content: @fa-var-pencil-square; } +.@{fa-css-prefix}-external-link-square:before { content: @fa-var-external-link-square; } +.@{fa-css-prefix}-share-square:before { content: @fa-var-share-square; } +.@{fa-css-prefix}-compass:before { content: @fa-var-compass; } +.@{fa-css-prefix}-toggle-down:before, +.@{fa-css-prefix}-caret-square-o-down:before { content: @fa-var-caret-square-o-down; } +.@{fa-css-prefix}-toggle-up:before, +.@{fa-css-prefix}-caret-square-o-up:before { content: @fa-var-caret-square-o-up; } +.@{fa-css-prefix}-toggle-right:before, +.@{fa-css-prefix}-caret-square-o-right:before { content: @fa-var-caret-square-o-right; } +.@{fa-css-prefix}-euro:before, +.@{fa-css-prefix}-eur:before { content: @fa-var-eur; } +.@{fa-css-prefix}-gbp:before { content: @fa-var-gbp; } +.@{fa-css-prefix}-dollar:before, +.@{fa-css-prefix}-usd:before { content: @fa-var-usd; } +.@{fa-css-prefix}-rupee:before, +.@{fa-css-prefix}-inr:before { content: @fa-var-inr; } +.@{fa-css-prefix}-cny:before, +.@{fa-css-prefix}-rmb:before, +.@{fa-css-prefix}-yen:before, +.@{fa-css-prefix}-jpy:before { content: @fa-var-jpy; } +.@{fa-css-prefix}-ruble:before, +.@{fa-css-prefix}-rouble:before, +.@{fa-css-prefix}-rub:before { content: @fa-var-rub; } +.@{fa-css-prefix}-won:before, +.@{fa-css-prefix}-krw:before { content: @fa-var-krw; } +.@{fa-css-prefix}-bitcoin:before, +.@{fa-css-prefix}-btc:before { content: @fa-var-btc; } +.@{fa-css-prefix}-file:before { content: @fa-var-file; } +.@{fa-css-prefix}-file-text:before { content: @fa-var-file-text; } +.@{fa-css-prefix}-sort-alpha-asc:before { content: @fa-var-sort-alpha-asc; } +.@{fa-css-prefix}-sort-alpha-desc:before { content: @fa-var-sort-alpha-desc; } +.@{fa-css-prefix}-sort-amount-asc:before { content: @fa-var-sort-amount-asc; } +.@{fa-css-prefix}-sort-amount-desc:before { content: @fa-var-sort-amount-desc; } +.@{fa-css-prefix}-sort-numeric-asc:before { content: @fa-var-sort-numeric-asc; } +.@{fa-css-prefix}-sort-numeric-desc:before { content: @fa-var-sort-numeric-desc; } +.@{fa-css-prefix}-thumbs-up:before { content: @fa-var-thumbs-up; } +.@{fa-css-prefix}-thumbs-down:before { content: @fa-var-thumbs-down; } +.@{fa-css-prefix}-youtube-square:before { content: @fa-var-youtube-square; } +.@{fa-css-prefix}-youtube:before { content: @fa-var-youtube; } +.@{fa-css-prefix}-xing:before { content: @fa-var-xing; } +.@{fa-css-prefix}-xing-square:before { content: @fa-var-xing-square; } +.@{fa-css-prefix}-youtube-play:before { content: @fa-var-youtube-play; } +.@{fa-css-prefix}-dropbox:before { content: @fa-var-dropbox; } +.@{fa-css-prefix}-stack-overflow:before { content: @fa-var-stack-overflow; } +.@{fa-css-prefix}-instagram:before { content: @fa-var-instagram; } +.@{fa-css-prefix}-flickr:before { content: @fa-var-flickr; } +.@{fa-css-prefix}-adn:before { content: @fa-var-adn; } +.@{fa-css-prefix}-bitbucket:before { content: @fa-var-bitbucket; } +.@{fa-css-prefix}-bitbucket-square:before { content: @fa-var-bitbucket-square; } +.@{fa-css-prefix}-tumblr:before { content: @fa-var-tumblr; } +.@{fa-css-prefix}-tumblr-square:before { content: @fa-var-tumblr-square; } +.@{fa-css-prefix}-long-arrow-down:before { content: @fa-var-long-arrow-down; } +.@{fa-css-prefix}-long-arrow-up:before { content: @fa-var-long-arrow-up; } +.@{fa-css-prefix}-long-arrow-left:before { content: @fa-var-long-arrow-left; } +.@{fa-css-prefix}-long-arrow-right:before { content: @fa-var-long-arrow-right; } +.@{fa-css-prefix}-apple:before { content: @fa-var-apple; } +.@{fa-css-prefix}-windows:before { content: @fa-var-windows; } +.@{fa-css-prefix}-android:before { content: @fa-var-android; } +.@{fa-css-prefix}-linux:before { content: @fa-var-linux; } +.@{fa-css-prefix}-dribbble:before { content: @fa-var-dribbble; } +.@{fa-css-prefix}-skype:before { content: @fa-var-skype; } +.@{fa-css-prefix}-foursquare:before { content: @fa-var-foursquare; } +.@{fa-css-prefix}-trello:before { content: @fa-var-trello; } +.@{fa-css-prefix}-female:before { content: @fa-var-female; } +.@{fa-css-prefix}-male:before { content: @fa-var-male; } +.@{fa-css-prefix}-gittip:before { content: @fa-var-gittip; } +.@{fa-css-prefix}-sun-o:before { content: @fa-var-sun-o; } +.@{fa-css-prefix}-moon-o:before { content: @fa-var-moon-o; } +.@{fa-css-prefix}-archive:before { content: @fa-var-archive; } +.@{fa-css-prefix}-bug:before { content: @fa-var-bug; } +.@{fa-css-prefix}-vk:before { content: @fa-var-vk; } +.@{fa-css-prefix}-weibo:before { content: @fa-var-weibo; } +.@{fa-css-prefix}-renren:before { content: @fa-var-renren; } +.@{fa-css-prefix}-pagelines:before { content: @fa-var-pagelines; } +.@{fa-css-prefix}-stack-exchange:before { content: @fa-var-stack-exchange; } +.@{fa-css-prefix}-arrow-circle-o-right:before { content: @fa-var-arrow-circle-o-right; } +.@{fa-css-prefix}-arrow-circle-o-left:before { content: @fa-var-arrow-circle-o-left; } +.@{fa-css-prefix}-toggle-left:before, +.@{fa-css-prefix}-caret-square-o-left:before { content: @fa-var-caret-square-o-left; } +.@{fa-css-prefix}-dot-circle-o:before { content: @fa-var-dot-circle-o; } +.@{fa-css-prefix}-wheelchair:before { content: @fa-var-wheelchair; } +.@{fa-css-prefix}-vimeo-square:before { content: @fa-var-vimeo-square; } +.@{fa-css-prefix}-turkish-lira:before, +.@{fa-css-prefix}-try:before { content: @fa-var-try; } +.@{fa-css-prefix}-plus-square-o:before { content: @fa-var-plus-square-o; } diff --git a/src/static/movio/templates/Movio/less/font-awesome/larger.less b/src/static/movio/templates/Movio/less/font-awesome/larger.less new file mode 100644 index 0000000..c9d6467 --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/larger.less @@ -0,0 +1,13 @@ +// Icon Sizes +// ------------------------- + +/* makes the font 33% larger relative to the icon container */ +.@{fa-css-prefix}-lg { + font-size: (4em / 3); + line-height: (3em / 4); + vertical-align: -15%; +} +.@{fa-css-prefix}-2x { font-size: 2em; } +.@{fa-css-prefix}-3x { font-size: 3em; } +.@{fa-css-prefix}-4x { font-size: 4em; } +.@{fa-css-prefix}-5x { font-size: 5em; } diff --git a/src/static/movio/templates/Movio/less/font-awesome/list.less b/src/static/movio/templates/Movio/less/font-awesome/list.less new file mode 100644 index 0000000..eed9340 --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/list.less @@ -0,0 +1,19 @@ +// List Icons +// ------------------------- + +.@{fa-css-prefix}-ul { + padding-left: 0; + margin-left: @fa-li-width; + list-style-type: none; + > li { position: relative; } +} +.@{fa-css-prefix}-li { + position: absolute; + left: -@fa-li-width; + width: @fa-li-width; + top: (2em / 14); + text-align: center; + &.@{fa-css-prefix}-lg { + left: -@fa-li-width + (4em / 14); + } +} diff --git a/src/static/movio/templates/Movio/less/font-awesome/mixins.less b/src/static/movio/templates/Movio/less/font-awesome/mixins.less new file mode 100644 index 0000000..19e5a64 --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/mixins.less @@ -0,0 +1,20 @@ +// Mixins +// -------------------------- + +.fa-icon-rotate(@degrees, @rotation) { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation); + -webkit-transform: rotate(@degrees); + -moz-transform: rotate(@degrees); + -ms-transform: rotate(@degrees); + -o-transform: rotate(@degrees); + transform: rotate(@degrees); +} + +.fa-icon-flip(@horiz, @vert, @rotation) { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1); + -webkit-transform: scale(@horiz, @vert); + -moz-transform: scale(@horiz, @vert); + -ms-transform: scale(@horiz, @vert); + -o-transform: scale(@horiz, @vert); + transform: scale(@horiz, @vert); +} diff --git a/src/static/movio/templates/Movio/less/font-awesome/path.less b/src/static/movio/templates/Movio/less/font-awesome/path.less new file mode 100644 index 0000000..c5a6912 --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/path.less @@ -0,0 +1,14 @@ +/* FONT PATH + * -------------------------- */ + +@font-face { + font-family: 'FontAwesome'; + src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); + src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), + url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), + url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), + url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); +// src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts + font-weight: normal; + font-style: normal; +} diff --git a/src/static/movio/templates/Movio/less/font-awesome/rotated-flipped.less b/src/static/movio/templates/Movio/less/font-awesome/rotated-flipped.less new file mode 100644 index 0000000..8fff3a6 --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/rotated-flipped.less @@ -0,0 +1,9 @@ +// Rotated & Flipped Icons +// ------------------------- + +.@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } +.@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } +.@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } + +.@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } +.@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } diff --git a/src/static/movio/templates/Movio/less/font-awesome/spinning.less b/src/static/movio/templates/Movio/less/font-awesome/spinning.less new file mode 100644 index 0000000..60828fe --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/spinning.less @@ -0,0 +1,30 @@ +// Spinning Icons +// -------------------------- + +.@{fa-css-prefix}-spin { + -webkit-animation: spin 2s infinite linear; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} + +@-moz-keyframes spin { + 0% { -moz-transform: rotate(0deg); } + 100% { -moz-transform: rotate(359deg); } +} +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(359deg); } +} +@-o-keyframes spin { + 0% { -o-transform: rotate(0deg); } + 100% { -o-transform: rotate(359deg); } +} +@-ms-keyframes spin { + 0% { -ms-transform: rotate(0deg); } + 100% { -ms-transform: rotate(359deg); } +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(359deg); } +} diff --git a/src/static/movio/templates/Movio/less/font-awesome/stacked.less b/src/static/movio/templates/Movio/less/font-awesome/stacked.less new file mode 100644 index 0000000..fc53fb0 --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/stacked.less @@ -0,0 +1,20 @@ +// Stacked Icons +// ------------------------- + +.@{fa-css-prefix}-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.@{fa-css-prefix}-stack-1x { line-height: inherit; } +.@{fa-css-prefix}-stack-2x { font-size: 2em; } +.@{fa-css-prefix}-inverse { color: @fa-inverse; } diff --git a/src/static/movio/templates/Movio/less/font-awesome/variables.less b/src/static/movio/templates/Movio/less/font-awesome/variables.less new file mode 100644 index 0000000..3ab7a75 --- /dev/null +++ b/src/static/movio/templates/Movio/less/font-awesome/variables.less @@ -0,0 +1,381 @@ +// Variables +// -------------------------- + +//@fa-font-path: "../font/font-awesome"; +@fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts"; // for referencing Bootstrap CDN font files directly +@fa-css-prefix: fa; +@fa-version: "4.0.3"; +@fa-border-color: #eee; +@fa-inverse: #fff; +@fa-li-width: (30em / 14); + +@fa-var-glass: "\f000"; +@fa-var-music: "\f001"; +@fa-var-search: "\f002"; +@fa-var-envelope-o: "\f003"; +@fa-var-heart: "\f004"; +@fa-var-star: "\f005"; +@fa-var-star-o: "\f006"; +@fa-var-user: "\f007"; +@fa-var-film: "\f008"; +@fa-var-th-large: "\f009"; +@fa-var-th: "\f00a"; +@fa-var-th-list: "\f00b"; +@fa-var-check: "\f00c"; +@fa-var-times: "\f00d"; +@fa-var-search-plus: "\f00e"; +@fa-var-search-minus: "\f010"; +@fa-var-power-off: "\f011"; +@fa-var-signal: "\f012"; +@fa-var-cog: "\f013"; +@fa-var-trash-o: "\f014"; +@fa-var-home: "\f015"; +@fa-var-file-o: "\f016"; +@fa-var-clock-o: "\f017"; +@fa-var-road: "\f018"; +@fa-var-download: "\f019"; +@fa-var-arrow-circle-o-down: "\f01a"; +@fa-var-arrow-circle-o-up: "\f01b"; +@fa-var-inbox: "\f01c"; +@fa-var-play-circle-o: "\f01d"; +@fa-var-repeat: "\f01e"; +@fa-var-refresh: "\f021"; +@fa-var-list-alt: "\f022"; +@fa-var-lock: "\f023"; +@fa-var-flag: "\f024"; +@fa-var-headphones: "\f025"; +@fa-var-volume-off: "\f026"; +@fa-var-volume-down: "\f027"; +@fa-var-volume-up: "\f028"; +@fa-var-qrcode: "\f029"; +@fa-var-barcode: "\f02a"; +@fa-var-tag: "\f02b"; +@fa-var-tags: "\f02c"; +@fa-var-book: "\f02d"; +@fa-var-bookmark: "\f02e"; +@fa-var-print: "\f02f"; +@fa-var-camera: "\f030"; +@fa-var-font: "\f031"; +@fa-var-bold: "\f032"; +@fa-var-italic: "\f033"; +@fa-var-text-height: "\f034"; +@fa-var-text-width: "\f035"; +@fa-var-align-left: "\f036"; +@fa-var-align-center: "\f037"; +@fa-var-align-right: "\f038"; +@fa-var-align-justify: "\f039"; +@fa-var-list: "\f03a"; +@fa-var-outdent: "\f03b"; +@fa-var-indent: "\f03c"; +@fa-var-video-camera: "\f03d"; +@fa-var-picture-o: "\f03e"; +@fa-var-pencil: "\f040"; +@fa-var-map-marker: "\f041"; +@fa-var-adjust: "\f042"; +@fa-var-tint: "\f043"; +@fa-var-pencil-square-o: "\f044"; +@fa-var-share-square-o: "\f045"; +@fa-var-check-square-o: "\f046"; +@fa-var-arrows: "\f047"; +@fa-var-step-backward: "\f048"; +@fa-var-fast-backward: "\f049"; +@fa-var-backward: "\f04a"; +@fa-var-play: "\f04b"; +@fa-var-pause: "\f04c"; +@fa-var-stop: "\f04d"; +@fa-var-forward: "\f04e"; +@fa-var-fast-forward: "\f050"; +@fa-var-step-forward: "\f051"; +@fa-var-eject: "\f052"; +@fa-var-chevron-left: "\f053"; +@fa-var-chevron-right: "\f054"; +@fa-var-plus-circle: "\f055"; +@fa-var-minus-circle: "\f056"; +@fa-var-times-circle: "\f057"; +@fa-var-check-circle: "\f058"; +@fa-var-question-circle: "\f059"; +@fa-var-info-circle: "\f05a"; +@fa-var-crosshairs: "\f05b"; +@fa-var-times-circle-o: "\f05c"; +@fa-var-check-circle-o: "\f05d"; +@fa-var-ban: "\f05e"; +@fa-var-arrow-left: "\f060"; +@fa-var-arrow-right: "\f061"; +@fa-var-arrow-up: "\f062"; +@fa-var-arrow-down: "\f063"; +@fa-var-share: "\f064"; +@fa-var-expand: "\f065"; +@fa-var-compress: "\f066"; +@fa-var-plus: "\f067"; +@fa-var-minus: "\f068"; +@fa-var-asterisk: "\f069"; +@fa-var-exclamation-circle: "\f06a"; +@fa-var-gift: "\f06b"; +@fa-var-leaf: "\f06c"; +@fa-var-fire: "\f06d"; +@fa-var-eye: "\f06e"; +@fa-var-eye-slash: "\f070"; +@fa-var-exclamation-triangle: "\f071"; +@fa-var-plane: "\f072"; +@fa-var-calendar: "\f073"; +@fa-var-random: "\f074"; +@fa-var-comment: "\f075"; +@fa-var-magnet: "\f076"; +@fa-var-chevron-up: "\f077"; +@fa-var-chevron-down: "\f078"; +@fa-var-retweet: "\f079"; +@fa-var-shopping-cart: "\f07a"; +@fa-var-folder: "\f07b"; +@fa-var-folder-open: "\f07c"; +@fa-var-arrows-v: "\f07d"; +@fa-var-arrows-h: "\f07e"; +@fa-var-bar-chart-o: "\f080"; +@fa-var-twitter-square: "\f081"; +@fa-var-facebook-square: "\f082"; +@fa-var-camera-retro: "\f083"; +@fa-var-key: "\f084"; +@fa-var-cogs: "\f085"; +@fa-var-comments: "\f086"; +@fa-var-thumbs-o-up: "\f087"; +@fa-var-thumbs-o-down: "\f088"; +@fa-var-star-half: "\f089"; +@fa-var-heart-o: "\f08a"; +@fa-var-sign-out: "\f08b"; +@fa-var-linkedin-square: "\f08c"; +@fa-var-thumb-tack: "\f08d"; +@fa-var-external-link: "\f08e"; +@fa-var-sign-in: "\f090"; +@fa-var-trophy: "\f091"; +@fa-var-github-square: "\f092"; +@fa-var-upload: "\f093"; +@fa-var-lemon-o: "\f094"; +@fa-var-phone: "\f095"; +@fa-var-square-o: "\f096"; +@fa-var-bookmark-o: "\f097"; +@fa-var-phone-square: "\f098"; +@fa-var-twitter: "\f099"; +@fa-var-facebook: "\f09a"; +@fa-var-github: "\f09b"; +@fa-var-unlock: "\f09c"; +@fa-var-credit-card: "\f09d"; +@fa-var-rss: "\f09e"; +@fa-var-hdd-o: "\f0a0"; +@fa-var-bullhorn: "\f0a1"; +@fa-var-bell: "\f0f3"; +@fa-var-certificate: "\f0a3"; +@fa-var-hand-o-right: "\f0a4"; +@fa-var-hand-o-left: "\f0a5"; +@fa-var-hand-o-up: "\f0a6"; +@fa-var-hand-o-down: "\f0a7"; +@fa-var-arrow-circle-left: "\f0a8"; +@fa-var-arrow-circle-right: "\f0a9"; +@fa-var-arrow-circle-up: "\f0aa"; +@fa-var-arrow-circle-down: "\f0ab"; +@fa-var-globe: "\f0ac"; +@fa-var-wrench: "\f0ad"; +@fa-var-tasks: "\f0ae"; +@fa-var-filter: "\f0b0"; +@fa-var-briefcase: "\f0b1"; +@fa-var-arrows-alt: "\f0b2"; +@fa-var-users: "\f0c0"; +@fa-var-link: "\f0c1"; +@fa-var-cloud: "\f0c2"; +@fa-var-flask: "\f0c3"; +@fa-var-scissors: "\f0c4"; +@fa-var-files-o: "\f0c5"; +@fa-var-paperclip: "\f0c6"; +@fa-var-floppy-o: "\f0c7"; +@fa-var-square: "\f0c8"; +@fa-var-bars: "\f0c9"; +@fa-var-list-ul: "\f0ca"; +@fa-var-list-ol: "\f0cb"; +@fa-var-strikethrough: "\f0cc"; +@fa-var-underline: "\f0cd"; +@fa-var-table: "\f0ce"; +@fa-var-magic: "\f0d0"; +@fa-var-truck: "\f0d1"; +@fa-var-pinterest: "\f0d2"; +@fa-var-pinterest-square: "\f0d3"; +@fa-var-google-plus-square: "\f0d4"; +@fa-var-google-plus: "\f0d5"; +@fa-var-money: "\f0d6"; +@fa-var-caret-down: "\f0d7"; +@fa-var-caret-up: "\f0d8"; +@fa-var-caret-left: "\f0d9"; +@fa-var-caret-right: "\f0da"; +@fa-var-columns: "\f0db"; +@fa-var-sort: "\f0dc"; +@fa-var-sort-asc: "\f0dd"; +@fa-var-sort-desc: "\f0de"; +@fa-var-envelope: "\f0e0"; +@fa-var-linkedin: "\f0e1"; +@fa-var-undo: "\f0e2"; +@fa-var-gavel: "\f0e3"; +@fa-var-tachometer: "\f0e4"; +@fa-var-comment-o: "\f0e5"; +@fa-var-comments-o: "\f0e6"; +@fa-var-bolt: "\f0e7"; +@fa-var-sitemap: "\f0e8"; +@fa-var-umbrella: "\f0e9"; +@fa-var-clipboard: "\f0ea"; +@fa-var-lightbulb-o: "\f0eb"; +@fa-var-exchange: "\f0ec"; +@fa-var-cloud-download: "\f0ed"; +@fa-var-cloud-upload: "\f0ee"; +@fa-var-user-md: "\f0f0"; +@fa-var-stethoscope: "\f0f1"; +@fa-var-suitcase: "\f0f2"; +@fa-var-bell-o: "\f0a2"; +@fa-var-coffee: "\f0f4"; +@fa-var-cutlery: "\f0f5"; +@fa-var-file-text-o: "\f0f6"; +@fa-var-building-o: "\f0f7"; +@fa-var-hospital-o: "\f0f8"; +@fa-var-ambulance: "\f0f9"; +@fa-var-medkit: "\f0fa"; +@fa-var-fighter-jet: "\f0fb"; +@fa-var-beer: "\f0fc"; +@fa-var-h-square: "\f0fd"; +@fa-var-plus-square: "\f0fe"; +@fa-var-angle-double-left: "\f100"; +@fa-var-angle-double-right: "\f101"; +@fa-var-angle-double-up: "\f102"; +@fa-var-angle-double-down: "\f103"; +@fa-var-angle-left: "\f104"; +@fa-var-angle-right: "\f105"; +@fa-var-angle-up: "\f106"; +@fa-var-angle-down: "\f107"; +@fa-var-desktop: "\f108"; +@fa-var-laptop: "\f109"; +@fa-var-tablet: "\f10a"; +@fa-var-mobile: "\f10b"; +@fa-var-circle-o: "\f10c"; +@fa-var-quote-left: "\f10d"; +@fa-var-quote-right: "\f10e"; +@fa-var-spinner: "\f110"; +@fa-var-circle: "\f111"; +@fa-var-reply: "\f112"; +@fa-var-github-alt: "\f113"; +@fa-var-folder-o: "\f114"; +@fa-var-folder-open-o: "\f115"; +@fa-var-smile-o: "\f118"; +@fa-var-frown-o: "\f119"; +@fa-var-meh-o: "\f11a"; +@fa-var-gamepad: "\f11b"; +@fa-var-keyboard-o: "\f11c"; +@fa-var-flag-o: "\f11d"; +@fa-var-flag-checkered: "\f11e"; +@fa-var-terminal: "\f120"; +@fa-var-code: "\f121"; +@fa-var-reply-all: "\f122"; +@fa-var-mail-reply-all: "\f122"; +@fa-var-star-half-o: "\f123"; +@fa-var-location-arrow: "\f124"; +@fa-var-crop: "\f125"; +@fa-var-code-fork: "\f126"; +@fa-var-chain-broken: "\f127"; +@fa-var-question: "\f128"; +@fa-var-info: "\f129"; +@fa-var-exclamation: "\f12a"; +@fa-var-superscript: "\f12b"; +@fa-var-subscript: "\f12c"; +@fa-var-eraser: "\f12d"; +@fa-var-puzzle-piece: "\f12e"; +@fa-var-microphone: "\f130"; +@fa-var-microphone-slash: "\f131"; +@fa-var-shield: "\f132"; +@fa-var-calendar-o: "\f133"; +@fa-var-fire-extinguisher: "\f134"; +@fa-var-rocket: "\f135"; +@fa-var-maxcdn: "\f136"; +@fa-var-chevron-circle-left: "\f137"; +@fa-var-chevron-circle-right: "\f138"; +@fa-var-chevron-circle-up: "\f139"; +@fa-var-chevron-circle-down: "\f13a"; +@fa-var-html5: "\f13b"; +@fa-var-css3: "\f13c"; +@fa-var-anchor: "\f13d"; +@fa-var-unlock-alt: "\f13e"; +@fa-var-bullseye: "\f140"; +@fa-var-ellipsis-h: "\f141"; +@fa-var-ellipsis-v: "\f142"; +@fa-var-rss-square: "\f143"; +@fa-var-play-circle: "\f144"; +@fa-var-ticket: "\f145"; +@fa-var-minus-square: "\f146"; +@fa-var-minus-square-o: "\f147"; +@fa-var-level-up: "\f148"; +@fa-var-level-down: "\f149"; +@fa-var-check-square: "\f14a"; +@fa-var-pencil-square: "\f14b"; +@fa-var-external-link-square: "\f14c"; +@fa-var-share-square: "\f14d"; +@fa-var-compass: "\f14e"; +@fa-var-caret-square-o-down: "\f150"; +@fa-var-caret-square-o-up: "\f151"; +@fa-var-caret-square-o-right: "\f152"; +@fa-var-eur: "\f153"; +@fa-var-gbp: "\f154"; +@fa-var-usd: "\f155"; +@fa-var-inr: "\f156"; +@fa-var-jpy: "\f157"; +@fa-var-rub: "\f158"; +@fa-var-krw: "\f159"; +@fa-var-btc: "\f15a"; +@fa-var-file: "\f15b"; +@fa-var-file-text: "\f15c"; +@fa-var-sort-alpha-asc: "\f15d"; +@fa-var-sort-alpha-desc: "\f15e"; +@fa-var-sort-amount-asc: "\f160"; +@fa-var-sort-amount-desc: "\f161"; +@fa-var-sort-numeric-asc: "\f162"; +@fa-var-sort-numeric-desc: "\f163"; +@fa-var-thumbs-up: "\f164"; +@fa-var-thumbs-down: "\f165"; +@fa-var-youtube-square: "\f166"; +@fa-var-youtube: "\f167"; +@fa-var-xing: "\f168"; +@fa-var-xing-square: "\f169"; +@fa-var-youtube-play: "\f16a"; +@fa-var-dropbox: "\f16b"; +@fa-var-stack-overflow: "\f16c"; +@fa-var-instagram: "\f16d"; +@fa-var-flickr: "\f16e"; +@fa-var-adn: "\f170"; +@fa-var-bitbucket: "\f171"; +@fa-var-bitbucket-square: "\f172"; +@fa-var-tumblr: "\f173"; +@fa-var-tumblr-square: "\f174"; +@fa-var-long-arrow-down: "\f175"; +@fa-var-long-arrow-up: "\f176"; +@fa-var-long-arrow-left: "\f177"; +@fa-var-long-arrow-right: "\f178"; +@fa-var-apple: "\f179"; +@fa-var-windows: "\f17a"; +@fa-var-android: "\f17b"; +@fa-var-linux: "\f17c"; +@fa-var-dribbble: "\f17d"; +@fa-var-skype: "\f17e"; +@fa-var-foursquare: "\f180"; +@fa-var-trello: "\f181"; +@fa-var-female: "\f182"; +@fa-var-male: "\f183"; +@fa-var-gittip: "\f184"; +@fa-var-sun-o: "\f185"; +@fa-var-moon-o: "\f186"; +@fa-var-archive: "\f187"; +@fa-var-bug: "\f188"; +@fa-var-vk: "\f189"; +@fa-var-weibo: "\f18a"; +@fa-var-renren: "\f18b"; +@fa-var-pagelines: "\f18c"; +@fa-var-stack-exchange: "\f18d"; +@fa-var-arrow-circle-o-right: "\f18e"; +@fa-var-arrow-circle-o-left: "\f190"; +@fa-var-caret-square-o-left: "\f191"; +@fa-var-dot-circle-o: "\f192"; +@fa-var-wheelchair: "\f193"; +@fa-var-vimeo-square: "\f194"; +@fa-var-try: "\f195"; +@fa-var-plus-square-o: "\f196"; + diff --git a/src/static/movio/templates/Movio/less/global.less b/src/static/movio/templates/Movio/less/global.less new file mode 100755 index 0000000..b3107cd --- /dev/null +++ b/src/static/movio/templates/Movio/less/global.less @@ -0,0 +1,701 @@ +html, body { + height:100%; + margin:0; + padding:0; + font-size:13px; + font-family: @font-1; + font-weight: 400; + padding:0; + background: @body-background; + color: @text; + overflow-x:hidden!important; + + + @-moz-document url-prefix() { + overflow-x:hidden!important; + + } + + @media screen and (-webkit-min-device-pixel-ratio:0) { + overflow-x:hidden!important; + } + + } + +a { + color:@color-link; + text-decoration:underline; + + &:hover { + color:@color-link-hover; + text-decoration:underline; + } + + } + +h1, h2, h3, h4, h5, h6 { + color: @text-heading; +} + +h1 { + font-size:365%; + line-height:1.4em; + } + +h2 { + font-size:205%; + line-height:1em; + margin-bottom:5px; + padding:0; + } + +h3 { + font-size:150%; + line-height:1em; + } + +h4 { + font-size:120%; + line-height:1em; + } + +h5 { + font-size:100%; + line-height:1em; + } + +ul, ol { + padding-left:20px; + } + +dt { + float: left; + font-weight:bold; + padding-right:10px; + } + +dd { + margin-left:0; + } + +dl { + + &.small { + + dt { + width: 70px; + } + + dd { + margin-left: 70px; + } + + } + + &.medium { + + dt { + width: 170px; + } + + dd { + margin-left: 170px; + } + + } + + &.large { + + dt { + width: 250px; + } + + dd { + margin-left: 250px; + } + + } + +} +.clearfix-left { + clear:left; + } + +.clearfix-right { + clear:right; + } + +.align-center { + text-align:center!important; + } + +.align-right { + text-align:right!important; + } + +.first-box { + margin-left:0!important; +} + +label { + font-weight:normal; +} + +input[type="text"] { + display: inline-block; + height: 30px; + padding:2px 6px; + margin:0; + font-size: 12px; + line-height: 20px; + color: @text; + .border-radius (0); + vertical-align: middle; + border: 0; +} + +select { + border:1px solid @form-border; + } + +.content-box { + + input[type="text"], + input[type="password"], + input[type="email"] { + .input-style(auto); + } + + input[type="submit"] { + .button-style(auto); + } + + input[type="reset"], input.reset { + .button-style-reset(auto); + } + + textarea { + background:@form-input-background; + color:@form-input-text; + width:auto; + padding:2px; + font-size:14px; + .border-radius(6px); + border:1px solid @form-border; + font-family: @font-1; + font-weight: 400; + } + +} + +.ico-box { + display:block; + position:absolute; + width:25px!important; + height:30px!important; + top:0; + right:0; + margin-right:10px; + .border-radius-bottom-left-right(4px); + background:@icon-in-box-background; + .box-sizing(); + color:@icon-in-box; + padding:8px 0 0 6px; + + &.fa-film { + padding-left:5px; + } + + } + +.fa-grey { + color:@icon-in-page; + } + +@media only screen +and (min-device-width : 480px) +and (max-device-width : 768px) { + + .box-title { + width:97%; + } + + .main-content { + + &.col-md-12 { + margin-right:10px!important; + } + + .col-md-8 { + width:97%; + float:none; + } + + .col-md-4 { + width:97%; + float:none; + margin-right:20px!important; + } + + } + + } + +.box-big-content { + padding-top:15px; + } + +/* pop-up hover img description */ + +.popup { + + display:block; + position:absolute; + z-index:9999; + color:@text; + text-align: center; + text-decoration: none; + visibility:hidden; + left:0; + top:0; + width:150px; + + &.more-text { + margin-top:-90px; + } + + @media (max-width: 480px) { + display:none; + } + + .popup-text { + border:2px solid @box-border; + background-color:@box-background; + .border-radius (4px); + padding: 8px; + position: absolute; + z-index:1; + top:0; + display:block; + .box-shadow(2px,2px,3px,#666); + } + + .popup-arrow { + position: absolute; + background:url(../img/ico/arrow-baloon.png) no-repeat; + width:12px; + height:13px; + bottom:0; + margin-bottom:-13px; + display:block; + z-index:2; + left:0; + margin-left:8px; + } + +} + +.item { + + p { + font-size:13px!important; + } +} + +/* tooltip */ + +.tooltip { + display: block; + font-size: 11px; + line-height: 1.4; + opacity: 0; + position: absolute; + visibility: visible; + z-index: 1030; +} +.tooltip.in { + opacity: 0.8; +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + background-color: #000000; + border-radius: 4px 4px 4px 4px; + color: #FFFFFF; + max-width: 200px; + padding: 8px; + text-align: center; + text-decoration: none; +} +.tooltip-arrow { + border-color: transparent; + border-style: solid; + height: 0; + position: absolute; + width: 0; +} +.tooltip.top .tooltip-arrow { + border-top-color: #000000; + border-width: 5px 5px 0; + bottom: 0; + left: 50%; + margin-left: -5px; +} +.tooltip.right .tooltip-arrow { + border-right-color: #000000; + border-width: 5px 5px 5px 0; + left: 0; + margin-top: -5px; + top: 50%; +} +.tooltip.left .tooltip-arrow { + border-left-color: #000000; + border-width: 5px 0 5px 5px; + margin-top: -5px; + right: 0; + top: 50%; +} +.tooltip.bottom .tooltip-arrow { + border-bottom-color: #000000; + border-width: 0 5px 5px; + left: 50%; + margin-left: -5px; + top: 0; +} + +.alert { + margin-bottom:15px; + .border-radius(15px); + padding:10px 15px 10px 60px; + + h4 { + .padding-margin-reset(); + } + + p { + .padding-margin-reset(); + } + + &.error { + + h4 { + font-size:18px; + color:@alert-error-text; + } + + background:@alert-error-background url(../img/ico/alert-error.png) 10px 10px no-repeat; + border:1px solid @alert-error-border; + } + + &.ok { + + h4 { + font-size:18px; + color:@green; + } + + background:@alert-ok-background url(../img/ico/alert-ok.png) 10px 10px no-repeat; + border:1px solid @alert-ok-border; + } + + + } + +/* show-nav-for-iphone */ + +.show-nav-for-iphone, +.show-footer-nav-for-iphone { + display:none!important; + } + +#nav-collapse.collapse.col-md-12, +#box-sidebar-collapse.collapse.col-md-12 { + float:none; + } + +#nav-collapse.collapse, +#nav-collapse, +#box-sidebar-collapse.collapse, +#nav-collapse-box1.collapse, +#nav-collapse-box2.collapse, +#nav-collapse-box3.collapse, +#nav-collapse-box4.collapse, +#nav-collapse-box5.collapse { + height:auto; +} + +@media (min-width: 765px) { +#nav-collapse.collapse, +#nav-collapse, +#box-sidebar-collapse.collapse, +#nav-collapse-box1.collapse, +#nav-collapse-box2.collapse, +#nav-collapse-box3.collapse, +#nav-collapse-box4.collapse, +#nav-collapse-box5.collapse { + display:block; +} +} + +@media (max-width: 767px) { + +#nav-collapse.collapse, +#box-sidebar-collapse.collapse, +#nav-collapse-box1.collapse, +#nav-collapse-box2.collapse, +#nav-collapse-box3.collapse, +#nav-collapse-box4.collapse, +#nav-collapse-box5.collapse { + /*height:0; + min-height:0; + display: run-in;*/ + } + + .show-nav-for-iphone { + visibility: visible; + line-height:25px; + font-family: @font-1; + font-weight: 600; + color:@text; + padding:0px; + padding-left:14px; + border:0; + font-size:13px; + width:100%; + border-top:1px @solid @box-border; + border-bottom:1px @solid @box-border; + border-left:1px @solid @box-border; + border-right:1px @solid @box-border; + display:block!important; + text-decoration:none; + background:@box-background url(../img/ico/pool.png) 98% -511px no-repeat; + text-align:left; + + &.info-menu { + border-top:0; + } + + &.collapsed { + background:@box-background url(../img/ico/pool.png) 98% -560px no-repeat; + } + } + + .show-footer-nav-for-iphone { + font-size:14px; + line-height:15px; + margin:0 0 0 0; + padding:0; + font-family: @font-1; + font-weight:lighter; + background:none; + border:0; + color:@white; + position:relative; + + &:after { + top:0; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + } + + &:after { + border-color:transparent; + border-left-color:#fff; + border-width: 5px; + left:0; + margin-top:4px; + margin-left:0; + } + + padding-left:12px!important; + width:100%; + padding-bottom:8px; + margin-bottom:4px; + text-align:left; + display:block!important; + } + + #box-sidebar-collapse.collapse { + margin-bottom:10px; + } + +} + +/* my custom width */ +.col-md-1, +.col-md-2, +.col-md-3, +.col-md-4, +.col-md-5, +.col-md-6, +.col-md-7, +.col-md-8, +.col-md-9, +.col-md-10, +.col-md-11, +.col-md-12 { + padding:0; +} + +@media (min-width: 765px) { +.col-md-3 { + .grid(12, 3, 2.5%); + float:left; + + &:last-child { + margin-right:0; + } + +} + +.col-md-4 { + .grid(12, 4, 2.5%); + float:left; + + &.first-box { + margin-left:0; + } + + &:last-child { + margin-right:0; + } + +} + +.col-md-6 { + .grid(12, 6, 2.5%); + float:left; + + &:last-child { + margin-right:0; + } + +} +.col-md-9 { + .grid(12, 9, 2.5%); + float:left; + + &:last-child { + margin-right:0; + } + +} + +.col-md-12 { + .grid(12, 12, 2.5%); + float:left; + + &:last-child { + margin-right:0; + } + +} + + + +} + +@media (max-width: 770px) { + .col-md-3, + .col-md-1, + .col-md-2, + .col-md-3, + .col-md-4, + .col-md-5, + .col-md-6, + .col-md-7, + .col-md-8, + .col-md-9, + .col-md-10, + .col-md-11, + .col-md-12 { + padding:0; + width:100%; + margin-right:0; + } +} + + +.downloadList { + padding-left: 0; + li { + list-style: none; + margin-bottom: 5px; + + a { + text-decoration: none; + + &:hover { + text-decoration: underline; + } + + } + + } +} + +/* CMS Class */ + +img { + border: 0; + + &.thumb, + &.left, + &.right, + &.center { + float:left; + margin: 0.5em; + padding:5px; + border:1px @solid @box-image-border; + .border-radius (2px); + } + + &.left { + margin-left: 0; + } + + &.right { + margin-right: 0; + clear:right; + float:right; + } + &.center { + clear:both; + float:none; + margin:auto; + display: block; + } + + &.noBorder { + border: 0; + padding: 0; + } +} + +a.no-undeline { + text-decoration: none; +} + +.col-padding-left, +.col-padding-right { + padding-right: 15px; +} + diff --git a/src/static/movio/templates/Movio/less/libs/bootstrap-social.less b/src/static/movio/templates/Movio/less/libs/bootstrap-social.less new file mode 100644 index 0000000..4424e99 --- /dev/null +++ b/src/static/movio/templates/Movio/less/libs/bootstrap-social.less @@ -0,0 +1,100 @@ +/* + * Social Buttons for Bootstrap + * + * Copyright 2013-2014 Panayiotis Lipiridis + * Licensed under the MIT License + * + * https://github.com/lipis/bootstrap-social + */ + +.btn-social{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.btn-social :first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)} +.btn-social.btn-lg{padding-left:61px}.btn-social.btn-lg :first-child{line-height:45px;width:45px;font-size:1.8em} +.btn-social.btn-sm{padding-left:38px}.btn-social.btn-sm :first-child{line-height:28px;width:28px;font-size:1.4em} +.btn-social.btn-xs{padding-left:30px}.btn-social.btn-xs :first-child{line-height:20px;width:20px;font-size:1.2em} +.btn-social-icon{position:relative;padding-left:44px;text-align:left;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;height:34px;width:34px;padding:0}.btn-social-icon :first-child{position:absolute;left:0;top:0;bottom:0;width:32px;line-height:34px;font-size:1.6em;text-align:center;border-right:1px solid rgba(0,0,0,0.2)} +.btn-social-icon.btn-lg{padding-left:61px}.btn-social-icon.btn-lg :first-child{line-height:45px;width:45px;font-size:1.8em} +.btn-social-icon.btn-sm{padding-left:38px}.btn-social-icon.btn-sm :first-child{line-height:28px;width:28px;font-size:1.4em} +.btn-social-icon.btn-xs{padding-left:30px}.btn-social-icon.btn-xs :first-child{line-height:20px;width:20px;font-size:1.2em} +.btn-social-icon :first-child{border:none;text-align:center;width:100% !important} +.btn-social-icon.btn-lg{height:45px;width:45px;padding-left:0;padding-right:0} +.btn-social-icon.btn-sm{height:30px;width:30px;padding-left:0;padding-right:0} +.btn-social-icon.btn-xs{height:22px;width:22px;padding-left:0;padding-right:0} +.btn-adn{color:#fff;background-color:#d87a68;border-color:rgba(0,0,0,0.2)}.btn-adn:hover,.btn-adn:focus,.btn-adn:active,.btn-adn.active,.open .dropdown-toggle.btn-adn{color:#fff;background-color:#d05d48;border-color:rgba(0,0,0,0.2)} +.btn-adn:active,.btn-adn.active,.open .dropdown-toggle.btn-adn{background-image:none} +.btn-adn.disabled,.btn-adn[disabled],fieldset[disabled] .btn-adn,.btn-adn.disabled:hover,.btn-adn[disabled]:hover,fieldset[disabled] .btn-adn:hover,.btn-adn.disabled:focus,.btn-adn[disabled]:focus,fieldset[disabled] .btn-adn:focus,.btn-adn.disabled:active,.btn-adn[disabled]:active,fieldset[disabled] .btn-adn:active,.btn-adn.disabled.active,.btn-adn[disabled].active,fieldset[disabled] .btn-adn.active{background-color:#d87a68;border-color:rgba(0,0,0,0.2)} +.btn-adn .badge{color:#d87a68;background-color:#fff} +.btn-bitbucket{color:#fff;background-color:#205081;border-color:rgba(0,0,0,0.2)}.btn-bitbucket:hover,.btn-bitbucket:focus,.btn-bitbucket:active,.btn-bitbucket.active,.open .dropdown-toggle.btn-bitbucket{color:#fff;background-color:#183c60;border-color:rgba(0,0,0,0.2)} +.btn-bitbucket:active,.btn-bitbucket.active,.open .dropdown-toggle.btn-bitbucket{background-image:none} +.btn-bitbucket.disabled,.btn-bitbucket[disabled],fieldset[disabled] .btn-bitbucket,.btn-bitbucket.disabled:hover,.btn-bitbucket[disabled]:hover,fieldset[disabled] .btn-bitbucket:hover,.btn-bitbucket.disabled:focus,.btn-bitbucket[disabled]:focus,fieldset[disabled] .btn-bitbucket:focus,.btn-bitbucket.disabled:active,.btn-bitbucket[disabled]:active,fieldset[disabled] .btn-bitbucket:active,.btn-bitbucket.disabled.active,.btn-bitbucket[disabled].active,fieldset[disabled] .btn-bitbucket.active{background-color:#205081;border-color:rgba(0,0,0,0.2)} +.btn-bitbucket .badge{color:#205081;background-color:#fff} +.btn-dropbox{color:#fff;background-color:#1087dd;border-color:rgba(0,0,0,0.2)}.btn-dropbox:hover,.btn-dropbox:focus,.btn-dropbox:active,.btn-dropbox.active,.open .dropdown-toggle.btn-dropbox{color:#fff;background-color:#0d70b7;border-color:rgba(0,0,0,0.2)} +.btn-dropbox:active,.btn-dropbox.active,.open .dropdown-toggle.btn-dropbox{background-image:none} +.btn-dropbox.disabled,.btn-dropbox[disabled],fieldset[disabled] .btn-dropbox,.btn-dropbox.disabled:hover,.btn-dropbox[disabled]:hover,fieldset[disabled] .btn-dropbox:hover,.btn-dropbox.disabled:focus,.btn-dropbox[disabled]:focus,fieldset[disabled] .btn-dropbox:focus,.btn-dropbox.disabled:active,.btn-dropbox[disabled]:active,fieldset[disabled] .btn-dropbox:active,.btn-dropbox.disabled.active,.btn-dropbox[disabled].active,fieldset[disabled] .btn-dropbox.active{background-color:#1087dd;border-color:rgba(0,0,0,0.2)} +.btn-dropbox .badge{color:#1087dd;background-color:#fff} +.btn-facebook{color:#fff;background-color:#3b5998;border-color:rgba(0,0,0,0.2)}.btn-facebook:hover,.btn-facebook:focus,.btn-facebook:active,.btn-facebook.active,.open .dropdown-toggle.btn-facebook{color:#fff;background-color:#30487b;border-color:rgba(0,0,0,0.2)} +.btn-facebook:active,.btn-facebook.active,.open .dropdown-toggle.btn-facebook{background-image:none} +.btn-facebook.disabled,.btn-facebook[disabled],fieldset[disabled] .btn-facebook,.btn-facebook.disabled:hover,.btn-facebook[disabled]:hover,fieldset[disabled] .btn-facebook:hover,.btn-facebook.disabled:focus,.btn-facebook[disabled]:focus,fieldset[disabled] .btn-facebook:focus,.btn-facebook.disabled:active,.btn-facebook[disabled]:active,fieldset[disabled] .btn-facebook:active,.btn-facebook.disabled.active,.btn-facebook[disabled].active,fieldset[disabled] .btn-facebook.active{background-color:#3b5998;border-color:rgba(0,0,0,0.2)} +.btn-facebook .badge{color:#3b5998;background-color:#fff} +.btn-flickr{color:#fff;background-color:#ff0084;border-color:rgba(0,0,0,0.2)}.btn-flickr:hover,.btn-flickr:focus,.btn-flickr:active,.btn-flickr.active,.open .dropdown-toggle.btn-flickr{color:#fff;background-color:#d6006f;border-color:rgba(0,0,0,0.2)} +.btn-flickr:active,.btn-flickr.active,.open .dropdown-toggle.btn-flickr{background-image:none} +.btn-flickr.disabled,.btn-flickr[disabled],fieldset[disabled] .btn-flickr,.btn-flickr.disabled:hover,.btn-flickr[disabled]:hover,fieldset[disabled] .btn-flickr:hover,.btn-flickr.disabled:focus,.btn-flickr[disabled]:focus,fieldset[disabled] .btn-flickr:focus,.btn-flickr.disabled:active,.btn-flickr[disabled]:active,fieldset[disabled] .btn-flickr:active,.btn-flickr.disabled.active,.btn-flickr[disabled].active,fieldset[disabled] .btn-flickr.active{background-color:#ff0084;border-color:rgba(0,0,0,0.2)} +.btn-flickr .badge{color:#ff0084;background-color:#fff} +.btn-foursquare{color:#fff;background-color:#0072b1;border-color:rgba(0,0,0,0.2)}.btn-foursquare:hover,.btn-foursquare:focus,.btn-foursquare:active,.btn-foursquare.active,.open .dropdown-toggle.btn-foursquare{color:#fff;background-color:#005888;border-color:rgba(0,0,0,0.2)} +.btn-foursquare:active,.btn-foursquare.active,.open .dropdown-toggle.btn-foursquare{background-image:none} +.btn-foursquare.disabled,.btn-foursquare[disabled],fieldset[disabled] .btn-foursquare,.btn-foursquare.disabled:hover,.btn-foursquare[disabled]:hover,fieldset[disabled] .btn-foursquare:hover,.btn-foursquare.disabled:focus,.btn-foursquare[disabled]:focus,fieldset[disabled] .btn-foursquare:focus,.btn-foursquare.disabled:active,.btn-foursquare[disabled]:active,fieldset[disabled] .btn-foursquare:active,.btn-foursquare.disabled.active,.btn-foursquare[disabled].active,fieldset[disabled] .btn-foursquare.active{background-color:#0072b1;border-color:rgba(0,0,0,0.2)} +.btn-foursquare .badge{color:#0072b1;background-color:#fff} +.btn-github{color:#fff;background-color:#444;border-color:rgba(0,0,0,0.2)}.btn-github:hover,.btn-github:focus,.btn-github:active,.btn-github.active,.open .dropdown-toggle.btn-github{color:#fff;background-color:#303030;border-color:rgba(0,0,0,0.2)} +.btn-github:active,.btn-github.active,.open .dropdown-toggle.btn-github{background-image:none} +.btn-github.disabled,.btn-github[disabled],fieldset[disabled] .btn-github,.btn-github.disabled:hover,.btn-github[disabled]:hover,fieldset[disabled] .btn-github:hover,.btn-github.disabled:focus,.btn-github[disabled]:focus,fieldset[disabled] .btn-github:focus,.btn-github.disabled:active,.btn-github[disabled]:active,fieldset[disabled] .btn-github:active,.btn-github.disabled.active,.btn-github[disabled].active,fieldset[disabled] .btn-github.active{background-color:#444;border-color:rgba(0,0,0,0.2)} +.btn-github .badge{color:#444;background-color:#fff} +.btn-google-plus{color:#fff;background-color:#dd4b39;border-color:rgba(0,0,0,0.2)}.btn-google-plus:hover,.btn-google-plus:focus,.btn-google-plus:active,.btn-google-plus.active,.open .dropdown-toggle.btn-google-plus{color:#fff;background-color:#ca3523;border-color:rgba(0,0,0,0.2)} +.btn-google-plus:active,.btn-google-plus.active,.open .dropdown-toggle.btn-google-plus{background-image:none} +.btn-google-plus.disabled,.btn-google-plus[disabled],fieldset[disabled] .btn-google-plus,.btn-google-plus.disabled:hover,.btn-google-plus[disabled]:hover,fieldset[disabled] .btn-google-plus:hover,.btn-google-plus.disabled:focus,.btn-google-plus[disabled]:focus,fieldset[disabled] .btn-google-plus:focus,.btn-google-plus.disabled:active,.btn-google-plus[disabled]:active,fieldset[disabled] .btn-google-plus:active,.btn-google-plus.disabled.active,.btn-google-plus[disabled].active,fieldset[disabled] .btn-google-plus.active{background-color:#dd4b39;border-color:rgba(0,0,0,0.2)} +.btn-google-plus .badge{color:#dd4b39;background-color:#fff} +.btn-instagram{color:#fff;background-color:#3f729b;border-color:rgba(0,0,0,0.2)}.btn-instagram:hover,.btn-instagram:focus,.btn-instagram:active,.btn-instagram.active,.open .dropdown-toggle.btn-instagram{color:#fff;background-color:#335d7e;border-color:rgba(0,0,0,0.2)} +.btn-instagram:active,.btn-instagram.active,.open .dropdown-toggle.btn-instagram{background-image:none} +.btn-instagram.disabled,.btn-instagram[disabled],fieldset[disabled] .btn-instagram,.btn-instagram.disabled:hover,.btn-instagram[disabled]:hover,fieldset[disabled] .btn-instagram:hover,.btn-instagram.disabled:focus,.btn-instagram[disabled]:focus,fieldset[disabled] .btn-instagram:focus,.btn-instagram.disabled:active,.btn-instagram[disabled]:active,fieldset[disabled] .btn-instagram:active,.btn-instagram.disabled.active,.btn-instagram[disabled].active,fieldset[disabled] .btn-instagram.active{background-color:#3f729b;border-color:rgba(0,0,0,0.2)} +.btn-instagram .badge{color:#3f729b;background-color:#fff} +.btn-linkedin{color:#fff;background-color:#007bb6;border-color:rgba(0,0,0,0.2)}.btn-linkedin:hover,.btn-linkedin:focus,.btn-linkedin:active,.btn-linkedin.active,.open .dropdown-toggle.btn-linkedin{color:#fff;background-color:#005f8d;border-color:rgba(0,0,0,0.2)} +.btn-linkedin:active,.btn-linkedin.active,.open .dropdown-toggle.btn-linkedin{background-image:none} +.btn-linkedin.disabled,.btn-linkedin[disabled],fieldset[disabled] .btn-linkedin,.btn-linkedin.disabled:hover,.btn-linkedin[disabled]:hover,fieldset[disabled] .btn-linkedin:hover,.btn-linkedin.disabled:focus,.btn-linkedin[disabled]:focus,fieldset[disabled] .btn-linkedin:focus,.btn-linkedin.disabled:active,.btn-linkedin[disabled]:active,fieldset[disabled] .btn-linkedin:active,.btn-linkedin.disabled.active,.btn-linkedin[disabled].active,fieldset[disabled] .btn-linkedin.active{background-color:#007bb6;border-color:rgba(0,0,0,0.2)} +.btn-linkedin .badge{color:#007bb6;background-color:#fff} +.btn-microsoft{color:#fff;background-color:#2672ec;border-color:rgba(0,0,0,0.2)}.btn-microsoft:hover,.btn-microsoft:focus,.btn-microsoft:active,.btn-microsoft.active,.open .dropdown-toggle.btn-microsoft{color:#fff;background-color:#135ed6;border-color:rgba(0,0,0,0.2)} +.btn-microsoft:active,.btn-microsoft.active,.open .dropdown-toggle.btn-microsoft{background-image:none} +.btn-microsoft.disabled,.btn-microsoft[disabled],fieldset[disabled] .btn-microsoft,.btn-microsoft.disabled:hover,.btn-microsoft[disabled]:hover,fieldset[disabled] .btn-microsoft:hover,.btn-microsoft.disabled:focus,.btn-microsoft[disabled]:focus,fieldset[disabled] .btn-microsoft:focus,.btn-microsoft.disabled:active,.btn-microsoft[disabled]:active,fieldset[disabled] .btn-microsoft:active,.btn-microsoft.disabled.active,.btn-microsoft[disabled].active,fieldset[disabled] .btn-microsoft.active{background-color:#2672ec;border-color:rgba(0,0,0,0.2)} +.btn-microsoft .badge{color:#2672ec;background-color:#fff} +.btn-openid{color:#fff;background-color:#f7931e;border-color:rgba(0,0,0,0.2)}.btn-openid:hover,.btn-openid:focus,.btn-openid:active,.btn-openid.active,.open .dropdown-toggle.btn-openid{color:#fff;background-color:#e47f08;border-color:rgba(0,0,0,0.2)} +.btn-openid:active,.btn-openid.active,.open .dropdown-toggle.btn-openid{background-image:none} +.btn-openid.disabled,.btn-openid[disabled],fieldset[disabled] .btn-openid,.btn-openid.disabled:hover,.btn-openid[disabled]:hover,fieldset[disabled] .btn-openid:hover,.btn-openid.disabled:focus,.btn-openid[disabled]:focus,fieldset[disabled] .btn-openid:focus,.btn-openid.disabled:active,.btn-openid[disabled]:active,fieldset[disabled] .btn-openid:active,.btn-openid.disabled.active,.btn-openid[disabled].active,fieldset[disabled] .btn-openid.active{background-color:#f7931e;border-color:rgba(0,0,0,0.2)} +.btn-openid .badge{color:#f7931e;background-color:#fff} +.btn-reddit{color:#000;background-color:#eff7ff;border-color:rgba(0,0,0,0.2)}.btn-reddit:hover,.btn-reddit:focus,.btn-reddit:active,.btn-reddit.active,.open .dropdown-toggle.btn-reddit{color:#000;background-color:#c6e3ff;border-color:rgba(0,0,0,0.2)} +.btn-reddit:active,.btn-reddit.active,.open .dropdown-toggle.btn-reddit{background-image:none} +.btn-reddit.disabled,.btn-reddit[disabled],fieldset[disabled] .btn-reddit,.btn-reddit.disabled:hover,.btn-reddit[disabled]:hover,fieldset[disabled] .btn-reddit:hover,.btn-reddit.disabled:focus,.btn-reddit[disabled]:focus,fieldset[disabled] .btn-reddit:focus,.btn-reddit.disabled:active,.btn-reddit[disabled]:active,fieldset[disabled] .btn-reddit:active,.btn-reddit.disabled.active,.btn-reddit[disabled].active,fieldset[disabled] .btn-reddit.active{background-color:#eff7ff;border-color:rgba(0,0,0,0.2)} +.btn-reddit .badge{color:#eff7ff;background-color:#000} +.btn-soundcloud{color:#fff;background-color:#f50;border-color:rgba(0,0,0,0.2)}.btn-soundcloud:hover,.btn-soundcloud:focus,.btn-soundcloud:active,.btn-soundcloud.active,.open .dropdown-toggle.btn-soundcloud{color:#fff;background-color:#d64700;border-color:rgba(0,0,0,0.2)} +.btn-soundcloud:active,.btn-soundcloud.active,.open .dropdown-toggle.btn-soundcloud{background-image:none} +.btn-soundcloud.disabled,.btn-soundcloud[disabled],fieldset[disabled] .btn-soundcloud,.btn-soundcloud.disabled:hover,.btn-soundcloud[disabled]:hover,fieldset[disabled] .btn-soundcloud:hover,.btn-soundcloud.disabled:focus,.btn-soundcloud[disabled]:focus,fieldset[disabled] .btn-soundcloud:focus,.btn-soundcloud.disabled:active,.btn-soundcloud[disabled]:active,fieldset[disabled] .btn-soundcloud:active,.btn-soundcloud.disabled.active,.btn-soundcloud[disabled].active,fieldset[disabled] .btn-soundcloud.active{background-color:#f50;border-color:rgba(0,0,0,0.2)} +.btn-soundcloud .badge{color:#f50;background-color:#fff} +.btn-tumblr{color:#fff;background-color:#2c4762;border-color:rgba(0,0,0,0.2)}.btn-tumblr:hover,.btn-tumblr:focus,.btn-tumblr:active,.btn-tumblr.active,.open .dropdown-toggle.btn-tumblr{color:#fff;background-color:#1f3346;border-color:rgba(0,0,0,0.2)} +.btn-tumblr:active,.btn-tumblr.active,.open .dropdown-toggle.btn-tumblr{background-image:none} +.btn-tumblr.disabled,.btn-tumblr[disabled],fieldset[disabled] .btn-tumblr,.btn-tumblr.disabled:hover,.btn-tumblr[disabled]:hover,fieldset[disabled] .btn-tumblr:hover,.btn-tumblr.disabled:focus,.btn-tumblr[disabled]:focus,fieldset[disabled] .btn-tumblr:focus,.btn-tumblr.disabled:active,.btn-tumblr[disabled]:active,fieldset[disabled] .btn-tumblr:active,.btn-tumblr.disabled.active,.btn-tumblr[disabled].active,fieldset[disabled] .btn-tumblr.active{background-color:#2c4762;border-color:rgba(0,0,0,0.2)} +.btn-tumblr .badge{color:#2c4762;background-color:#fff} +.btn-twitter{color:#fff;background-color:#55acee;border-color:rgba(0,0,0,0.2)}.btn-twitter:hover,.btn-twitter:focus,.btn-twitter:active,.btn-twitter.active,.open .dropdown-toggle.btn-twitter{color:#fff;background-color:#309aea;border-color:rgba(0,0,0,0.2)} +.btn-twitter:active,.btn-twitter.active,.open .dropdown-toggle.btn-twitter{background-image:none} +.btn-twitter.disabled,.btn-twitter[disabled],fieldset[disabled] .btn-twitter,.btn-twitter.disabled:hover,.btn-twitter[disabled]:hover,fieldset[disabled] .btn-twitter:hover,.btn-twitter.disabled:focus,.btn-twitter[disabled]:focus,fieldset[disabled] .btn-twitter:focus,.btn-twitter.disabled:active,.btn-twitter[disabled]:active,fieldset[disabled] .btn-twitter:active,.btn-twitter.disabled.active,.btn-twitter[disabled].active,fieldset[disabled] .btn-twitter.active{background-color:#55acee;border-color:rgba(0,0,0,0.2)} +.btn-twitter .badge{color:#55acee;background-color:#fff} +.btn-vimeo{color:#fff;background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)}.btn-vimeo:hover,.btn-vimeo:focus,.btn-vimeo:active,.btn-vimeo.active,.open .dropdown-toggle.btn-vimeo{color:#fff;background-color:#129cc9;border-color:rgba(0,0,0,0.2)} +.btn-vimeo:active,.btn-vimeo.active,.open .dropdown-toggle.btn-vimeo{background-image:none} +.btn-vimeo.disabled,.btn-vimeo[disabled],fieldset[disabled] .btn-vimeo,.btn-vimeo.disabled:hover,.btn-vimeo[disabled]:hover,fieldset[disabled] .btn-vimeo:hover,.btn-vimeo.disabled:focus,.btn-vimeo[disabled]:focus,fieldset[disabled] .btn-vimeo:focus,.btn-vimeo.disabled:active,.btn-vimeo[disabled]:active,fieldset[disabled] .btn-vimeo:active,.btn-vimeo.disabled.active,.btn-vimeo[disabled].active,fieldset[disabled] .btn-vimeo.active{background-color:#1ab7ea;border-color:rgba(0,0,0,0.2)} +.btn-vimeo .badge{color:#1ab7ea;background-color:#fff} +.btn-vk{color:#fff;background-color:#587ea3;border-color:rgba(0,0,0,0.2)}.btn-vk:hover,.btn-vk:focus,.btn-vk:active,.btn-vk.active,.open .dropdown-toggle.btn-vk{color:#fff;background-color:#4a6a89;border-color:rgba(0,0,0,0.2)} +.btn-vk:active,.btn-vk.active,.open .dropdown-toggle.btn-vk{background-image:none} +.btn-vk.disabled,.btn-vk[disabled],fieldset[disabled] .btn-vk,.btn-vk.disabled:hover,.btn-vk[disabled]:hover,fieldset[disabled] .btn-vk:hover,.btn-vk.disabled:focus,.btn-vk[disabled]:focus,fieldset[disabled] .btn-vk:focus,.btn-vk.disabled:active,.btn-vk[disabled]:active,fieldset[disabled] .btn-vk:active,.btn-vk.disabled.active,.btn-vk[disabled].active,fieldset[disabled] .btn-vk.active{background-color:#587ea3;border-color:rgba(0,0,0,0.2)} +.btn-vk .badge{color:#587ea3;background-color:#fff} +.btn-yahoo{color:#fff;background-color:#720e9e;border-color:rgba(0,0,0,0.2)}.btn-yahoo:hover,.btn-yahoo:focus,.btn-yahoo:active,.btn-yahoo.active,.open .dropdown-toggle.btn-yahoo{color:#fff;background-color:#570b79;border-color:rgba(0,0,0,0.2)} +.btn-yahoo:active,.btn-yahoo.active,.open .dropdown-toggle.btn-yahoo{background-image:none} +.btn-yahoo.disabled,.btn-yahoo[disabled],fieldset[disabled] .btn-yahoo,.btn-yahoo.disabled:hover,.btn-yahoo[disabled]:hover,fieldset[disabled] .btn-yahoo:hover,.btn-yahoo.disabled:focus,.btn-yahoo[disabled]:focus,fieldset[disabled] .btn-yahoo:focus,.btn-yahoo.disabled:active,.btn-yahoo[disabled]:active,fieldset[disabled] .btn-yahoo:active,.btn-yahoo.disabled.active,.btn-yahoo[disabled].active,fieldset[disabled] .btn-yahoo.active{background-color:#720e9e;border-color:rgba(0,0,0,0.2)} +.btn-yahoo .badge{color:#720e9e;background-color:#fff} +.btn-pinterest{color:#fff;background-color:#d94752;border-color:rgba(0,0,0,0.2)}.btn-pinterest:hover,.btn-pinterest:focus,.btn-pinterest:active,.btn-pinterest.active,.open .dropdown-toggle.btn-pinterest{color:#fff;background-color:#cb2027;border-color:rgba(0,0,0,0.2)} +.btn-pinterest:active,.btn-pinterest.active,.open .dropdown-toggle.btn-pinterest{background-image:none} +.btn-pinterest.disabled,.btn-pinterest[disabled],fieldset[disabled] .btn-pinterest,.btn-pinterest.disabled:hover,.btn-pinterest[disabled]:hover,fieldset[disabled] .btn-pinterest:hover,.btn-pinterest.disabled:focus,.btn-pinterest[disabled]:focus,fieldset[disabled] .btn-pinterest:focus,.btn-pinterest.disabled:active,.btn-pinterest[disabled]:active,fieldset[disabled] .btn-pinterest:active,.btn-pinterest.disabled.active,.btn-pinterest[disabled].active,fieldset[disabled] .btn-pinterest.active{background-color:#d94752;border-color:rgba(0,0,0,0.2)} diff --git a/src/static/movio/templates/Movio/less/libs/bootstrap.less b/src/static/movio/templates/Movio/less/libs/bootstrap.less new file mode 100755 index 0000000..b48afb5 --- /dev/null +++ b/src/static/movio/templates/Movio/less/libs/bootstrap.less @@ -0,0 +1,2820 @@ +/*! + * Bootstrap v3.1.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px @solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +@media print { + * { + text-shadow: none !important; + color: #000 !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) ")"; + } + 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; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .table td, + .table th { + background-color: #fff !important; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px @solid #000; + } + .table { + border-collapse: collapse !important; + } + .table-bordered th, + .table-bordered td { + border: 1px @solid #ddd !important; + } +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 62.5%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333333; + background-color: #ffffff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #428bca; + text-decoration: none; +} +a:hover, +a:focus { + color: #2a6496; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px @solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #999999; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 200; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +cite { + font-style: normal; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-muted { + color: #999999; +} +.text-primary { + color: #428bca; +} +a.text-primary:hover { + color: #3071a9; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #428bca; +} +a.bg-primary:hover { + background-color: #3071a9; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px @solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px @solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #999999; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px @solid #eeeeee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +blockquote:before, +blockquote:after { + content: ""; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + white-space: nowrap; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 3px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px @solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: 0%; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: 0%; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: 0%; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: 0%; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: 0%; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: 0%; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: 0%; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: 0%; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + max-width: 100%; + background-color: transparent; +} +th { + text-align: left; +} +.table { + width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px @solid #dddddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px @solid #dddddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.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 > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px @solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px @solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.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 col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +@media (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + overflow-x: scroll; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px @solid #dddddd; + -webkit-overflow-scrolling: touch; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px @solid #e5e5e5; +} +label { + display: inline-block; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + /* IE8-9 */ + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; + background-color: #ffffff; + background-image: none; + border: 1px @solid #cccccc; + border-radius: 4px; + -webkit-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-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #999999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999999; +} +.form-control::-webkit-input-placeholder { + color: #999999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; + opacity: 1; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +input[type="date"] { + line-height: 34px; +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + display: block; + min-height: 20px; + margin-top: 10px; + margin-bottom: 10px; + padding-left: 20px; +} +.radio label, +.checkbox label { + display: inline; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + float: left; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +.radio[disabled], +.radio-inline[disabled], +.checkbox[disabled], +.checkbox-inline[disabled], +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"], +fieldset[disabled] .radio, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.has-feedback .form-control-feedback { + position: absolute; + top: 25px; + right: 0; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} +.has-error .form-control-feedback { + color: #a94442; +} +.form-control-static { + margin-bottom: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + padding-left: 0; + vertical-align: middle; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .control-label, +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +.form-horizontal .form-control-static { + padding-top: 7px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + top: 0; + right: 15px; +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + cursor: pointer; + background-image: none; + border: 1px @solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + color: #333333; + background-color: #ebebeb; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default .badge { + color: #ffffff; + background-color: #333333; +} +.btn-primary { + color: #ffffff; + background-color: #428bca; + border-color: #357ebd; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #3276b1; + border-color: #285e8e; +} +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #428bca; + border-color: #357ebd; +} +.btn-primary .badge { + color: #428bca; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #47a447; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #39b3d7; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ed9c28; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #d2322d; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #ffffff; +} +.btn-link { + color: #428bca; + font-weight: normal; + cursor: pointer; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #2a6496; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #999999; + text-decoration: none; +} +.btn-lg { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.btn-sm { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; + padding-left: 0; + padding-right: 0; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + transition: height 0.35s ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px @solid; + border-right: 4px @solid transparent; + border-left: 4px @solid transparent; +} +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.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; + font-size: 14px; + background-color: #ffffff; + border: 1px @solid #cccccc; + border: 1px @solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #428bca; +} +.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; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #999999; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px @solid; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px @solid #cccccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.clearfix:before, +.clearfix:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.nav:before, +.nav:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.nav:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} + diff --git a/src/static/movio/templates/Movio/less/libs/mixin.less b/src/static/movio/templates/Movio/less/libs/mixin.less new file mode 100755 index 0000000..cba5b03 --- /dev/null +++ b/src/static/movio/templates/Movio/less/libs/mixin.less @@ -0,0 +1,237 @@ +.margin-reset() { +margin:0; +} + +.padding-reset() { +padding:0; +} + +.padding-margin-reset() { + .padding-reset(); + .margin-reset(); + } + +.pmr() { + .padding-reset(); + .margin-reset(); + } + +.box-sizing() { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + +/* define border radius */ + +.border-radius (@radius) { + border-radius: @radius; + -moz-border-radius: @radius; + -webkit-border-radius: @radius; +} + +.border-radius-top (@radius-top) { + border-top-left-radius: @radius-top; + border-top-right-radius: @radius-top; + -moz-border-radius-topright: @radius-top; + -moz-border-radius-topleft: @radius-top; + -webkit-border-top-right-radius: @radius-top; + -webkit-border-top-left-radius: @radius-top; +} + +.border-radius-bottom-left-right (@radius-bottom-left-right) { + -webkit-border-bottom-right-radius: @radius-bottom-left-right; + -webkit-border-bottom-left-radius: @radius-bottom-left-right; + -moz-border-radius-bottomright: @radius-bottom-left-right; + -moz-border-radius-bottomleft: @radius-bottom-left-right; + border-bottom-right-radius: @radius-bottom-left-right; + border-bottom-left-radius: @radius-bottom-left-right; +} + +.border-radius-left (@radius-left) { + -webkit-border-bottom-left-radius:@radius-left; + border-bottom-left-radius:@radius-left; + -webkit-border-top-left-radius:@radius-left; + border-top-left-radius:@radius-left; + -moz-border-radius-bottomleft:@radius-left; + -moz-border-radius-topleft:@radius-left; +} + +.border-radius-right (@radius-right) { + -webkit-border-top-right-radius:@radius-right; + border-top-right-radius:@radius-right; + -webkit-border-bottom-right-radius:@radius-right; + border-bottom-right-radius:@radius-right; + -moz-border-radius-topright:@radius-right; + -moz-border-radius-bottomright:@radius-right; +} + +.border-radius-all-no-right (@radius-all-no-right) { + -webkit-border-radius:@radius-all-no-right; + -webkit-border-bottom-right-radius: 0; + -moz-border-radius:@radius-all-no-right; + -moz-border-radius-bottomright: 0; + border-radius:@radius-all-no-right; + border-bottom-right-radius: 0; +} + +/* define transition */ + +.transition (@time:.4s) { + -moz-transition:all @time ease-in-out; + -webkit-transition:all @time ease-in-out; + -o-transition:all @time ease-in-out; + transition:all @time ease-in-out; + } + +/* define shadow */ + +.shadow-inset (@color) { +-moz-box-shadow:inset 0 0 10px @color; +-webkit-box-shadow:inset 0 0 10px @color; +box-shadow:inset 0 0 10px @color; +} + +.glow (@color) { +-moz-box-shadow: inset -1px 1px 1px @color; +-webkit-box-shadow: inset -1px 1px 1px @color; +box-shadow: inset -1px 1px 1px @color; +} + +.mini-shadow (@color) { +-moz-box-shadow: 2px 2px 2px 2px @color; +-webkit-box-shadow: 2px 2px 2px 2px @color; +box-shadow: -1px 1px 3px 1px @color; +} + +/* define shadow */ + +.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #999) { + box-shadow: @arguments; + -moz-box-shadow: @arguments; + -webkit-box-shadow: @arguments; +} + +/* text-shaodow */ +.text-shadow (@x: 0, @y: 0, @blur: 1px, @color: #000) { + text-shadow:@arguments; +} + +.button-gradient-black() { +background-image: linear-gradient(bottom, @linkButton-grandient-1 0%, @linkButton-grandient-2 67%); +background-image: -o-linear-gradient(bottom, @linkButton-grandient-1 0%, @linkButton-grandient-2 67%); +background-image: -moz-linear-gradient(bottom, @linkButton-grandient-1 0%, @linkButton-grandient-2 67%); +background-image: -webkit-linear-gradient(bottom, @linkButton-grandient-1 0%, @linkButton-grandient-2 67%); +background-image: -ms-linear-gradient(bottom, r@linkButton-grandient-1 0%, @linkButton-grandient-2 67%); + +background-image: -webkit-gradient( + linear, + left bottom, + left top, + color-stop(0, @linkButton-grandient-1), + color-stop(0.67,@linkButton-grandient-2) +); +} + +.button-gradient-black-reverse() { +background-image: linear-gradient(bottom, @linkButton-grandient-2 0%, @linkButton-grandient-1 67%); +background-image: -o-linear-gradient(bottom, @linkButton-grandient-2 0%, @linkButton-grandient-1 67%); +background-image: -moz-linear-gradient(bottom, @linkButton-grandient-2 0%, @linkButton-grandient-1 67%); +background-image: -webkit-linear-gradient(bottom, @linkButton-grandient-2 0%, @linkButton-grandient-1 67%); +background-image: -ms-linear-gradient(bottom, @linkButton-grandient-2 0%, @linkButton-grandient-1 67%); + +background-image: -webkit-gradient( + linear, + left bottom, + left top, + color-stop(0, @linkButton-grandient-2), + color-stop(0.67, @linkButton-grandient-1) +); +} + +.button-red { + display:block; + position:absolute; + display:block; + color:@form-buttonPrimary-text; + padding:2px 8px 4px 8px; + .border-radius (4px); + background:@form-button-primary url(../img/ico/pool.png) 50px -36px no-repeat; + + &:hover { + text-decoration:none; + } + +} + +.input-style (@width) { + background:@form-input-background; + box-shadow:0; + color:@form-input-text; + width:@width; + padding:2px; + font-size:14px; + .border-radius(6px); + border:1px solid @form-border; + font-family: @font-1; + font-weight: 400; + height:30px; + + &.required { + border:2px solid @form-required; + } + +} + + +.button-style (@with) { + width: @with; + border:0; + font-size:14px; + color:@form-buttonPrimary-text; + border:0; + padding:0 15px; + .border-radius(6px); + background: @form-buttonPrimary-gradient-1; + .text-shadow (0,0,1px,#999); + text-transform:uppercase; + font-family: @font-1; + font-weight: 400; + height:30px; + line-height:30px; + background: -moz-linear-gradient(top, @form-buttonPrimary-gradient-1 0%, @form-buttonPrimary-gradient-2 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,@form-buttonPrimary-gradient-1), color-stop(100%,@form-buttonPrimary-gradient-2)); + background: -webkit-linear-gradient(top, @form-buttonPrimary-gradient-1 0%,@form-buttonPrimary-gradient-2 100%); + background: -o-linear-gradient(top, @form-buttonPrimary-gradient-1 0%,@form-buttonPrimary-gradient-2 100%); + background: -ms-linear-gradient(top, @form-buttonPrimary-gradient-1 0%,@form-buttonPrimary-gradient-2 100%); + background: linear-gradient(to bottom, @form-buttonPrimary-gradient-1 0%,@form-buttonPrimary-gradient-2 100%); + + } + +.button-style-reset (@with) { + width: @with; + border:0; + font-size:14px; + color:@form-button-text; + border:0; + height:30px; + line-height:30px; + padding:0 15px; + .border-radius(6px); + background: @form-button-gradient-1; + .text-shadow (0,0,1px,#999); + text-transform:uppercase; + font-family: @font-1; + font-weight: 400; + background: -moz-linear-gradient(top, @form-button-gradient-1 0%, @form-button-gradient-2 100%); + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,@form-button-gradient-1), color-stop(100%,@form-button-gradient-2)); + background: -webkit-linear-gradient(top, @form-button-gradient-1 0%,@form-button-gradient-2 100%); + background: -o-linear-gradient(top, @form-button-gradient-1 0%,@form-button-gradient-2 100%); + background: -ms-linear-gradient(top, @form-button-gradient-1 0%,@form-button-gradient-2 100%); + background: linear-gradient(to bottom, @form-button-gradient-1 0%,@form-button-gradient-2 100%); + } + + .grid(@col, @span, @margin) { + width: ((100% - (@margin * (@col - 1))) / @col * @span) + (@margin * (@span - 1)); + margin-right: @margin; +} \ No newline at end of file diff --git a/src/static/movio/templates/Movio/less/mobile.less b/src/static/movio/templates/Movio/less/mobile.less new file mode 100755 index 0000000..37caa56 --- /dev/null +++ b/src/static/movio/templates/Movio/less/mobile.less @@ -0,0 +1,105 @@ +@media (max-width: 979px) { + + .visible-tablet, + .visible-desktop { + display:none; + } + +} + + +@media (max-width: 765px) { + +.box { + margin-bottom:15px; +} + +.show-nav-for-iphone { + padding-left:10px; + padding-right:10px; +} + +aside { + + &.sx { + .info-menu { + margin-top:10px; + border-top:1px solid #ccc; + } + } + +} + +.main-content { + padding-top:10px; +} + +footer { + padding-bottom:15px; +} + +footer .box { + min-height:inherit!important; + padding-left:15px!important; +} + +} + +@media (max-width: 650px) { + +.item.col-md-4 { + width:100%!important; +} + +} + +@media (max-width: 480px) { + +.main-content { + padding-top:20px!important; +} + +.contentWrapper { + padding:0; + } + +article.slideshow { + + .slide { + height:290px; + + .description { + width:100%; + min-height:inherit!important; + height:110px!important; + overflow:hidden; + } + + } + +} + +footer { + margin-top: 10px; + min-height:inherit!important; + height:auto; + + &:after { + content:""; + display:block; + width:100%; + clear:both; + height:1px; + } + +} + +} + +/* iPads (portrait) ----------- */ +@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : portrait) { +} + +/* iPads (landscape) ----------- */ +@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : landscape) { +} diff --git a/src/static/movio/templates/Movio/less/page.less b/src/static/movio/templates/Movio/less/page.less new file mode 100755 index 0000000..d54772d --- /dev/null +++ b/src/static/movio/templates/Movio/less/page.less @@ -0,0 +1,316 @@ +body.page { + + h3 { + padding-top:10px!important; + } + + aside { + + article.box { + margin-bottom:14px; + } + + } + + #box-sidebar-collapse { + + .box { + + .container { + min-height:inherit; + } + + } + + } + + /*** + aside sx + ***/ + + aside.sx { + + nav.menu-sx { + position:relative; + margin-bottom:14px; + height:auto!important; + } + + } + + /*** + aside dx + ***/ + + aside.dx { + + .show-content-box { + + &:after { + margin-left: -5px; + } + + &.collapsed { + + &:after { + margin-left: -5px; + } + + &:hover { + + + &:after { + margin-left: -5px; + } + + } + + } + + } + + padding-top:7px; + float:right; + margin-left:1%; + + @media (width: 1024px) { + + #gallery, .relations-img { + + .slides { + + padding-left:13px; + + } + + } + + } + + #gallery, .relations-img { + + .slides { + + li { + border:0; + + img { + margin-right:4px; + } + + &:nth-child(2n+0) { + + text-align:left; + padding-left:0px; + + img { + margin-left:4px; + } + + a:hover { + + .popup { + + margin-left:-80px; + + .popup-arrow { + right:0; + left:auto; + margin-right:8px; + } + + } + + } + + } + + + } + + + + } + + } + + @media (max-width: 767px) { + + .item { + width: 48.61878453038674%; + *width: 48.56559304102504%; + margin-right:1%; + } + + } + + .item.col-md-4 { + width:100%; + float:none; + margin-left:0; + } + + } + + /*** + main-content + ***/ + + article.main-content { + float:right; + + @media (max-width: 480px) { + padding:10px; + margin-top:-15px; + } + + &.view-one-column { + float:left; + margin:0; + width:100%; + + .content-box { + + } + + } + + p { + text-align:justify; + font-size:14px; + } + + /* figure */ + + img { + max-width:100%; + } + + figure.main-img { + padding:0; + position:relative; + padding:0 15px 10px 0; + margin: 0; + max-width:auto; + margin-bottom:15px; + + &.align-left { + float:left; + margin-right:20px; + } + + &.align-right { + float:right; + margin-left:20px; + padding-right:0; + + img { + float:right; + width:100%; + max-width:100%; + } + + .description { + float:right; + text-align:right; + clear:right; + padding-left:10px; + padding-right:0; + } + + a.button-red { + float:left!important; + + &.zoom { + background:@form-button-primary; + + &:before { + left:0; + top:0; + padding-top:3px; + margin-left:3px; + } + + } + + } + + } + + + + img { + padding:5px; + border:1px @solid @box-image-border; + .border-radius (2px); + float:left; + margin-bottom:8px; + width: 100%; + max-width:100%; + } + + .description { + font-size: 95%; + line-height: 1.2em; + padding:0; + margin:0; + position:relative; + bottom:0; + float:left; + clear:left; + width:auto; + padding-right:10px; + word-wrap:break-word; + strong {display:block;} + } + + a.button-red.zoom { + width:60px; + position:relative; + float:right; + text-decoration:none; + color:@form-buttonPrimary-text; + + &.zoom { + background:@form-button-primary; + + &:before { + font-family: 'FontAwesome'; + content:@fa-var-search; + display:block; + position:absolute; + right:0; + top:0; + margin:0; + width:20px; + height:100%; + text-align:left; + padding-top:3px; + margin-right:-3px; + } + + } + + &:hover { + color:@form-buttonPrimary-text; + } + + } + + } + + /* photogallery */ + + #photogallery { + border:1px solid @box-border; + background-color:@box-background; + .border-radius (2px); + width:815px; + padding:10px; + margin-top:30px; + margin-bottom:25px; + } + + } + +} diff --git a/src/static/movio/templates/Movio/less/slick.less b/src/static/movio/templates/Movio/less/slick.less new file mode 100755 index 0000000..c9bbeb5 --- /dev/null +++ b/src/static/movio/templates/Movio/less/slick.less @@ -0,0 +1,90 @@ +/* slick */ +#outer { + + .slider { + margin-bottom:0; + + + } + + /* dots */ + .slick-dots { + + li.slick-active { + + button { + background-color:@slider-bullet-background-selected; + border:1px solid @slider-bullet-background; + } + + } + + li button { + width:12px; + height:12px; + padding:0; + .border-radius(100px); + background-color:@slider-bullet-background; + border:1px solid @slider-bullet-background; + + &:hover { + background:#E3001B; + } + + &:before { + display:none; + } + + } + } + + /* Arrows */ + + .slick-prev:before, .slick-next:before { + font-family: 'FontAwesome'; + content:@fa-var-caret-left; + color:@color-arrow-button-slider; + opacity:1; + font-size:17px; + font-weight:lighter; + + } + + .slick-disabled { + display:none!important; + } + + .slick-next:before { + content:@fa-var-caret-right; + margin-right:-3px; + } + + .slick-prev, .slick-next { + width:20px; + height:40px; + padding-top:4px; + top:50%; + margin-top:-23px; + border:1px solid @color-border-button; + .border-radius(5px); + background:#fff; + + &:hover { + + &:before { + color:@color-arrow-button-slider-hover; + } + } + + + } + + .slick-prev { + left:0; + } + + .slick-next { + right:0; + } + +} \ No newline at end of file diff --git a/src/static/movio/templates/Movio/less/structure.less b/src/static/movio/templates/Movio/less/structure.less new file mode 100755 index 0000000..51f8986 --- /dev/null +++ b/src/static/movio/templates/Movio/less/structure.less @@ -0,0 +1,579 @@ +/** + * Struttura + */ + +body>#outer { + + height:auto; + min-height:90%; + width:100%; + color:@text; + padding:0; + .box-sizing(); + + .contentWrapper { + + .box-sizing(); + + @media (min-width: 979px) { + max-width:1180px; + padding:0 15px; + + } + margin:0 auto; + + + /* iPads (landscape) ----------- */ + @media only screen + and (min-device-width : 768px) + and (max-device-width : 1024px) + and (orientation : landscape) { + width:98%; + } + + /* iPads (portrait) ----------- */ + @media only screen + and (min-device-width : 768px) + and (max-device-width : 1024px) + and (orientation : portrait) { + width:97%; + } + + + } + + + } + +/*** +metanavigation +***/ + +#topbar { + background:@metanavigation-background; + height:34px; + + @media (min-width: 767px) { + + margin-bottom:20px; + + } + + .menu-dropdown { + padding-top:3px; + margin-left:10px; + } + + ul { + padding:0; + margin:0; + + li { + list-style:none; + display:inline; + } + + } + + a { + color: @metanavigation-link; + text-decoration:none; + } + + /* lang */ + + nav.langs { + float:left; + height:34px; + font-size:11px; + + ul { + + li { + float:left; + } + + a { + height:34px; + display:inline-block; + padding:9px 9px 0 9px; + font-family: @font-1; + font-weight: 600; + position:relative; + + &:hover, &.active { + color:@metanavigation-link-hover; + background:@metanavigation-background-hover; + text-decoration:none; + + &:after { + bottom:0; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + } + + &:after { + border-color:transparent; + border-bottom-color:#fff; + border-width: 5px; + left:50%; + margin-top:10px; + margin-left:-5px; + } + + } + + } + + } + + } + + /* menu-top */ + + nav.menu-top { + float:left; + font-size:11px; + padding-top:9px; + margin-left:20px; + + ul li { + border-right:1px @solid @metanavigation-link; + padding-right:13px; + + &.last { + border:0; + } + + a { + margin-left:10px; + font-family: @font-1; + font-weight: 600; + + &:hover { + text-decoration:none; + } + + } + + } + + } + + /* form ricerca */ + + form { + float:right; + margin-bottom:25px; + margin-top:3px; + + @media (max-width: 480px) { + margin-right:10px; + } + + label {display:none;} + + p { + pading:0; + margin:0; + + input { + width:290px; + margin-top:1px; + height:25px; + + @media (max-width: 480px) { + width:190px; + } + + @media (max-width: 768px) { + width:190px; + } + + &.button { + border:0; + width:16px; + height:16px; + margin-left:10px; + background: url(../img/ico/search.png) 0 0 no-repeat; + text-indent:-9999px; + float:right; + margin-top:5px; + } + + } + + } + + } + + } + +/*** +header +***/ + +header { + position:relative; + clear:both; + padding:0; + margin-bottom:15px; + + .col-md-3 { + margin-top:-5px; + line-height:19px; + } + + + p { + font-size:13px; + font-family: @font-1; + font-weight: 600; + text-align:right; + } + + h1 { + font-size:365%; + margin:0 0 7px 0; + padding:0; + line-height:35px; + font-family: @font-1; + font-weight: 600; + + @media (max-width: 480px) { + font-size:250%; + margin-left:10px; + } + + } + + h2 { + font-family: @font-2; + font-weight: 300; + margin:0; + font-size:205%; + + strong { + font-weight: 600; + } + + @media (max-width: 480px) { + font-size:110%; + margin-left:11px; + } + + } + + h3 { + font-family: @font-2; + font-weight: 600; + font-weight:normal; + margin-top:0; + line-height:26px; + font-size:125%; + } + + &.with-image { + background:url(../img/various/header.jpg) 0 0 no-repeat; + height:250px; + + @media (max-width: 480px) { + background:none; + height:auto; + } + + } + +} +/*** +content box +***/ + +.content-box { + min-height:290px; + float:left; + width:100%; + clear:right; + position:relative; + margin-bottom:14px; + + /* slideshow */ + + article.slideshow { + min-height:290px; + position:relative; + background-color:@slider-background; + z-index:2; + padding:0; + margin-right:0; + + .slick-dots { + text-align:right; + position:absolute; + bottom:0; + height:12px; + + li { + margin-right:0; + margin-left:0; + } + + } + + .slide { + background-position:top right!important; + } + + .description { + + float:left; + width: 270px; + .box-sizing(); + margin-left:0; + padding-left:15px; + min-height:290px; + position:relative; + + background-color:@slider-background; + + + h1 { + font-family: @font-1; + font-weight: 600; + font-size:18px; + margin:15px 15px 10px 0; + line-height:17px; + text-transform:uppercase; + + a { + color:@slider-text; + text-decoration:none; + } + + } + + p { + font-size:14px; + margin:0; + line-height:15px; + color:@slider-text; + } + + a.link-continue { + position:absolute; + display:block; + width:88%; + top:0; + padding:0 0 0 0; + text-indent:-9999px; + .box-sizing(); + line-height:20px; + margin-top:258px; + background:@color-link-hover; + + &:before { + font-family: 'FontAwesome'; + content:@fa-var-caret-right; + display:block; + color:@white; + font-size:20px; + text-indent:0; + float:right; + margin-right:5px; + font-weight:lighter!important; + } + + + @media (max-width: 480px) { + top:160px; + + width:95%; + } + + } + + } + + + } + + +} + +/*** +footer +***/ + +footer { + margin-top: 10px; + min-height:10%; + background-color:@footer-background; + color:@footer-text; + + .contentWrapper { + + padding-top:36px!important; + + @media (max-width: 480px) { + padding-top:10px!important; + } + + @media (min-width: 979px) { + padding:0; + min-width:980px; + max-width:1180px; + width:100%; + } + + margin:0 auto; + + + .logo-footer { + float:left; + margin-right:40px; + margin-left:60px; + padding-bottom: 10px; + + @media (max-width: 480px) { + margin-left:10px; + margin-right:0; + } + + @media (max-width: 1024px) { + margin-left:10px; + margin-right:10px; + width:150px; + } + + + + } + + .box { + float:left; + padding-left:20px; + border-left:1px solid @footer-border; + min-height:105px; + + @media (max-width: 767px) { + border:0; + display:block; + width:100%; + margin-bottom:0; + } + + padding-top:5px; + margin-bottom:25px; + margin-right:30px; + + h2 { + font-size:14px; + line-height:15px; + margin:0 0 6px 0; + padding:0; + color:@footer-text; + text-transform:uppercase; + + @media (max-width: 767px) { + display:none; + } + + } + + nav { + + ul { + padding:0 0 5px 2px; + margin:0; + + li { + list-style:none; + + a { + color:@footer-text; + position:relative; + + &:after { + top:0; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + } + + &:after { + border-color:transparent; + border-left-color:#fff; + border-width: 5px; + left:0; + margin-top:6px; + margin-left:0px; + } + + @media (max-width: 767px) { + background:none; + } + + padding-left:14px; + text-decoration:none; + } + + } + + } + + } + + + } + + + } + + #info-page { + border-top:1px solid @footer-border; + @media (max-width: 480px) { + display:none; + } + + .contentWrapper { + + padding-top:0px!important; + + @media (max-width: 480px) { + padding-top:0px!important; + } + + @media (min-width: 979px) { + padding:0; + min-width:980px; + max-width:1180px; + width:100%; + } + } + + .content {padding:0;} + + p { + padding:0; + margin:0; + font-size:11px; + color:@footer-text2; + padding-left:60px; + padding-top:5px; + padding-bottom:5px; + } + + } + + + + + } + diff --git a/src/static/movio/templates/Movio/less/styles.less b/src/static/movio/templates/Movio/less/styles.less new file mode 100755 index 0000000..3641c4f --- /dev/null +++ b/src/static/movio/templates/Movio/less/styles.less @@ -0,0 +1,192 @@ +/** + * Import libraries + */ + +@import "libs/mixin.less"; +@import "libs/bootstrap.less"; +@import "libs/bootstrap-social.less"; +/** + * Template files + */ +@import "global.less"; +@import "element.less"; +@import "page.less"; +@import "structure.less"; +@import "slick.less"; +@import "mobile.less"; +@import "svg.less"; + + +/* font-awesome */ +@import "font-awesome/font-awesome.less"; + +/*define lib colors */ +@white:#fff; +@black:#000; +@green:#7AB660; +@red1:#B82013; +@red2:#CC3522; +@red3:#CB3521; +@grey:#7E7E7E; +@grey2:#D8D8D8; +@grey3:#F5F5F5; +@grey4:#C6C6C6; +@grey5:#FAFAFA; +@grey6:#F3F3F3; +@grey7:#A1A1A1; +@grey8:#363636; +@grey9:#5E5E5E; +@grey10:#B6B6B6; +@grey11:#2F2F2F; +@grey12:#7A7A7A; +@grey13:#F9F9F9; +@grey14:#D7D7D7; +@grey15:#E9E9E9; +@grey16:#D6D6D6; + +@color1:#CCC; +@color2:#D8D8D8; +@color3:#F9F9F9; +@color4:#7A7A7A; +@color5:#C6C6C6; +@color6:#E4E4E4; +@color7:#F5F5F5; +@color8:#0099FF; +@color9:#545453; +@color10:#5E5E5D; +@color11:#333; +@color12:#CC0000; +@color-success:green; +@color-error:red; +@solid:solid; + + +/* define border type */ +@solid:solid; + +@font-1: 'Titillium Web', sans-serif; +@font-2: 'Open Sans', sans-serif; + +/* colori divisi per elementi */ +@text: @black; +@text-heading: @grey11; +@body-background: @white; +@color-link: @red2; +@color-link-hover: @red1; +@breadkcrumbs-link: @red1; +@breadkcrumbs-link-hover: @red1; + +@metanavigation-background:@red2; +@metanavigation-background-hover: @red1; +@metanavigation-link: @white; +@metanavigation-link-hover: @white; + +@slider-background: @red2; +@slider-text: @white; +@slider-read-more-background: @red1; +@slider-bullet-background: @white; +@slider-bullet-background-selected: @red1; + +@sidebar-background: @grey3; +@sidebar-background-hover: @red2; +@sidebar-border: @grey4; +@sidebar-link: @black; +@sidebar-link-hover: @white; +@sidebar-arrow:@grey7; +@sidebar-arrow-hover:@white; + +@sidebar-sub-background: @grey5; +@sidebar-sub-background-hover: @red2; +@sidebar-sub-border: @grey4; +@sidebar-sub-link: @black; +@sidebar-sub-link-hover: @white; +@sidebar-box-background: @grey5; + +@inner-nav-link: @text-heading; +@inner-nav-link-hover: @red2; + +@box-border: @grey4; +@box-background: @grey5; +@box-header-background: @grey6; +@box-header-link: @black; +@box-image-border: @grey4; +@box-text: @text; +@box-relation-item-border: @grey14; +@box-relation-item-background: @white; +@box-relation-item-link: @black; +@box-relation-item-link-hover: @red1; + +@icon-in-page:lighten(@text, 70); +@icon-in-box:@white; +@icon-in-box-background:@grey7; + +@color-border-button:@grey16; +@color-background-button:@white; +@color-arrow-button-slider:@grey7; +@color-arrow-button-slider-hover:@red3; + +@linkButton-link: @white; +@linkButton-grandient-1: rgb(76,76,76); +@linkButton-grandient-2: rgb(1,1,1); +@link-button-link: @white; + +@storyteller-background: #E4E4E4; //#E4E4E4 +@storyteller-border: darken(@storyteller-background, 5); //#D9D9D9 +@storyteller-shadow: darken(@storyteller-background, 25); +@storyteller-icon: lighten(@text, 70); +@storyteller-grandient-1: lighten(@storyteller-background, 3); //#ececec; +@storyteller-grandient-2: lighten(@storyteller-background, 10);; //#fdfdfd; +@storyteller-border: @grey2; +@storyteller-item-background: @grey13; +@storyteller-comments-background: @grey13; +@storyteller-link: @red2; +@storyteller-navigation-link: @grey12; +@storyteller-image-border: @grey4; +@storyteller-border: darken(@storyteller-background, 5); //#D9D9D9 + +@form-border: @grey15; +@form-required: @red1; +@form-button-primary: @red1; +@form-buttonPrimary-gradient-2:darken(@form-button-primary, 4); +@form-buttonPrimary-gradient-1:lighten(@form-button-primary, 24); +@form-buttonPrimary-text:@white; +@form-button-gradient-1:#CACACA; +@form-button-gradient-2:darken(@form-button-gradient-1, 15); +@form-button-text:@form-buttonPrimary-text; +@form-input-text:#5D5D5D; +@form-button: @color4; +@form-input-background:@grey13; + +@timeline-theme: @red2; + +@footer-background: @grey8; +@footer-border: @grey9; +@footer-text: @white; +@footer-text2: @grey10; + +@alert-error-background:#FFFED0; +@alert-ok-background:#E9FBE1; +@alert-error-text: @red3; +@alert-ok-border:#CFE0C2; +@alert-error-border:#FFCC00; + +@color-link-attach:@white; +@color-link-attach-hover:@white; +@bg-link-attach:@color1; +@bg-link-attach-hover:@color9; + +@color-tag-attach:@white; +@color-tag-attach-hover:#B82013; +@bg-tag-attach:#B82013; +@bg-tag-attach-hover:@color1; +@bg-dl:#fafafa; +@bg-block-my-pop-up:#fafafa; + +@svg-path-stroke:#000000; +@svg-main-node-background:#D3D3D3; +@svg-node-border:#CFCED3; +@svg-text-link:#CC3522; +@svg-text-link-hover:darken(@svg-text-link, 15); +@svg-text-node:#000000; +@svg-text-main-node:#000000; +@svg-node-background:#FFFFFF; diff --git a/src/static/movio/templates/Movio/less/svg.less b/src/static/movio/templates/Movio/less/svg.less new file mode 100644 index 0000000..b8649d5 --- /dev/null +++ b/src/static/movio/templates/Movio/less/svg.less @@ -0,0 +1,61 @@ +svg { + overflow: hidden; +} + +/* Stile testo delle entità */ +g.nodes tspan { + font-family: Helvetica, sans-serif; + font-size: 14px; + color: @svg-text-node; +} +/* Stile testo delle entità in HTML */ +g.nodes div { + white-space: nowrap; + padding: 2px 5px 2px 5px; + font-family: Helvetica, sans-serif; + font-size: 14px; + color: @svg-text-node; +} + +/* Stile testo delle entità principali */ +g.nodes tspan.main-node { + fill: @svg-text-main-node !important; +} +/* Stile testo delle entità principali in HTML */ +div.main-node { + padding: 2px 7px 2px 7px; + font-family: Helvetica, sans-serif; + font-size: 14px; + color: @svg-text-main-node !important; +} + +/* Stile testo delle relazioni */ +g.edgeLabels tspan { + +} +/* Stile riquadro delle entità */ +.node rect { + stroke: @svg-node-border; + stroke-width: 2px; + fill: @svg-node-background; +} +.node a { + color: @svg-text-link; + text-decoration: underline; +} +.node a:hover { + color: @svg-text-link-hover; +} +/* Stile riquadro delle entità principali */ +.node rect.main-node { + fill: @svg-main-node-background; +} +/* Stile delle frecce */ +.edgePath path { + stroke: @svg-path-stroke; + stroke-width: 1.5px; + fill: none; +} + + + diff --git a/src/static/movio/templates/Movio/preview.jpg b/src/static/movio/templates/Movio/preview.jpg new file mode 100644 index 0000000000000000000000000000000000000000..51b9940bfdc6122ea6f288817d74847a3f1b9380 GIT binary patch literal 23846 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%0DR;oW*Ca?8KeYg*WG! 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 Iyb*u@*;FQdUH||9 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/Template.php b/src/static/movio/templates/Skeleton/Template.php new file mode 100644 index 0000000..8410261 --- /dev/null +++ b/src/static/movio/templates/Skeleton/Template.php @@ -0,0 +1,45 @@ +<?php +class Template extends movio_views_AbstractLessTemplate +{ + function __construct() + { + $this->path = __DIR__; + $this->templateName = 'Skeleton'; + } + + protected function applyCssVariables(&$templateData, $less, $css) + { + return $css; + } + + + protected function applyFont(&$templateData, $css) + { + return $css; + } + + + protected function addLogoCss(&$templateData, $css) + { + return $css; + } + + protected function addCustomCss(&$templateData, $css) + { + return $css; + } + + public function fixTemplateData(&$templateData, &$newTemplateData) + { + } + + protected function fixTemplateName($view) + { + $view->setAttribute('templateFileName', 'page.php'); + } + + + public static function homeSliderImage($item) { + return 'background:url('.$item->image['src'].') no-repeat 0 0;'; + } +} \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/Template.xml b/src/static/movio/templates/Skeleton/Template.xml new file mode 100644 index 0000000..81c27f4 --- /dev/null +++ b/src/static/movio/templates/Skeleton/Template.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:EmptyComponent> + + <glz:ConfigValue key="movio.thumb.entityList.width" action="set" value="86" /> + <glz:ConfigValue key="movio.thumb.entityList.height" action="set" value="86" /> + <glz:ConfigValue key="movio.thumb.entityList.crop" action="set" value="true" /> + <glz:ConfigValue key="movio.thumb.homeSlider.width" action="set" value="600" /> + <glz:ConfigValue key="movio.thumb.homeSlider.height" action="set" value="290" /> + <glz:ConfigValue key="movio.thumb.homeSlider.crop" action="set" value="true" /> + + <glz:Modifier target="navigation" attribute="editableRegion" value="navigation" /> + <glz:Modifier target="navigation" attribute="cssClass" value="nav nav-pills nav-stacked" /> + <glz:Modifier target="navigation" attribute="nestedCssClass" value="true" /> + +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/TemplateAdmin.xml b/src/static/movio/templates/Skeleton/TemplateAdmin.xml new file mode 100644 index 0000000..c87a84c --- /dev/null +++ b/src/static/movio/templates/Skeleton/TemplateAdmin.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:EmptyComponent + xmlns:m="movio.views.components.*"> + +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/TemplateAdminGlobal.xml b/src/static/movio/templates/Skeleton/TemplateAdminGlobal.xml new file mode 100644 index 0000000..b097750 --- /dev/null +++ b/src/static/movio/templates/Skeleton/TemplateAdminGlobal.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:EmptyComponent + xmlns:m="movio.views.components.*"> + + <glz:Input id="customCss" label="{i18n:Custom css}" size="90" type="multiline" rows="10" cols="70" /> +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/css/styles.css b/src/static/movio/templates/Skeleton/css/styles.css new file mode 100644 index 0000000..51c1287 --- /dev/null +++ b/src/static/movio/templates/Skeleton/css/styles.css @@ -0,0 +1,11 @@ +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts/fontawesome-webfont.eot?v=4.0.3');src:url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'),url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'),url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'),url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857142858em;text-align:center}.fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}/*! + * Bootstrap v3.3.2 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! + * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=5956842e5639d629b2e6) + * Config saved to config.json and https://gist.github.com/5956842e5639d629b2e6 + *//*! normalize.css v3.0.2 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,*:before,*:after{background:transparent !important;color:#000 !important;-webkit-box-shadow:none !important;box-shadow:none !important;text-shadow:none !important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]: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}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff !important}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table td,.table th{background-color:#fff !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}kbd kbd{padding:0;font-size:100%;font-weight:bold;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.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>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-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-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type="date"],input[type="time"],input[type="datetime-local"],input[type="month"]{line-height:34px}input[type="date"].input-sm,input[type="time"].input-sm,input[type="datetime-local"].input-sm,input[type="month"].input-sm,.input-group-sm input[type="date"],.input-group-sm input[type="time"],.input-group-sm input[type="datetime-local"],.input-group-sm input[type="month"]{line-height:30px}input[type="date"].input-lg,input[type="time"].input-lg,input[type="datetime-local"].input-lg,input[type="month"].input-lg,.input-group-lg input[type="date"],.input-group-lg input[type="time"],.input-group-lg input[type="datetime-local"],.input-group-lg input[type="month"]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{position:absolute;margin-left:-20px;margin-top:4px \9}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"].disabled,input[type="checkbox"].disabled,fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"]{cursor:not-allowed}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-left:0;padding-right:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.form-group-sm .form-control{height:30px;line-height:30px}textarea.form-group-sm .form-control,select[multiple].form-group-sm .form-control{height:auto}.form-group-sm .form-control-static{height:30px;padding:5px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.form-group-lg .form-control{height:46px;line-height:46px}textarea.form-group-lg .form-control,select[multiple].form-group-lg .form-control{height:auto}.form-group-lg .form-control-static{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.333333px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px}}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default.focus,.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:hover,.btn-primary:focus,.btn-primary.focus,.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success.focus,.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info.focus,.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning.focus,.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger.focus,.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#337ab7;font-weight:normal;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none;visibility:hidden}.collapse.in{display:block;visibility:visible}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.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;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);-webkit-background-clip:padding-box;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#337ab7}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle="buttons"]>.btn input[type="radio"],[data-toggle="buttons"]>.btn-group>.btn input[type="radio"],[data-toggle="buttons"]>.btn input[type="checkbox"],[data-toggle="buttons"]>.btn-group>.btn input[type="checkbox"]{position:absolute;clip:rect(0, 0, 0, 0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none;visibility:hidden}.tab-content>.active{display:block;visibility:visible}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block !important;visibility:visible !important;height:auto !important;padding-bottom:0;overflow:visible !important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-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);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left !important}.navbar-right{float:right !important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-left:15px;padding-right:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.modal-open{overflow:hidden}.modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0, -25%);-ms-transform:translate(0, -25%);-o-transform:translate(0, -25%);transform:translate(0, -25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0, 0);-ms-transform:translate(0, 0);-o-transform:translate(0, 0);transform:translate(0, 0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);-webkit-background-clip:padding-box;background-clip:padding-box;outline:0}.modal-backdrop{position:absolute;top:0;right:0;left:0;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;visibility:visible;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-weight:normal;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;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-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-weight:normal;line-height:1.42857143;text-align:left;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.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{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,0.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,0.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important;visibility:hidden !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}}body{background-color:#fff;font-family:'Arial',sans-serif;font-size:14px;font-weight:normal}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}h1,h2,h3,h4,h5,h6{color:#000}a{color:#428bca}a:hover{color:#357ebd}dt{float:left;font-weight:bold;padding-right:10px}dd{margin-left:0}dl.small dt{width:70px}dl.small dd{margin-left:70px}dl.medium dt{width:170px}dl.medium dd{margin-left:170px}dl.large dt{width:250px}dl.large dd{margin-left:250px}.main-content h1{padding:0;margin:0}.main-content h2{padding:0;margin:0;margin-bottom:15px}.main-content .print-ico{float:right}.main-content p{line-height:1.6em;padding-bottom:15px}input[type="text"],input[type="password"],input[type="email"]{background:#fff;border:0;box-shadow:0;color:#000;width:100%;padding:2px;font-size:14px;border:1px solid #ccc;height:30px;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px}input[type="text"].required,input[type="password"].required,input[type="email"].required{border:2px solid #ccc}input[type="text"].input-large,input[type="password"].input-large,input[type="email"].input-large{width:450px}input[type="text"].input-small,input[type="password"].input-small,input[type="email"].input-small{width:160px}select{width:auto}select.select-large{width:450px}select.select-small{width:160px}select.select-medium{width:260px}input[type="submit"],button,input[type="button"],input[type="reset"]{background:#7a7a7a;width:auto;text-align:center;color:#fff;line-height:1em;height:30px;display:inline-block;padding:0 15px 0 15px;font-size:14px;line-height:30px;text-decoration:none;border:0}input[type="submit"]:hover,button:hover,input[type="button"]:hover,input[type="reset"]:hover{text-decoration:none}input[type="submit"]{background:#428bca;color:#fff}textarea{border:1px solid #ccc;width:100%;padding:4px;height:150px}textarea.textarea-large{width:450px}.clearfix-left{clear:left}.clearfix-right{clear:right}.align-center{text-align:center !important}.align-right{text-align:right !important}.first-box{margin-left:0 !important}.ico-box{display:block;position:absolute;width:30px !important;height:30px !important;top:0;right:0;margin-right:10px;background:#ccc;color:#fff;text-align:center;padding-top:7px;font-size:15px}.ico-box.icon-film{padding-left:5px}.icon-grey{color:#b3b3b3;font-size:20px}.link-go-to-read{color:#428bca !important;font-size:12px;display:inline-block;padding-top:5px}.link-go-to-read:hover{color:#357ebd !important}span.superzoom{background:#428bca;border-radius:4px;color:#fff;padding:2px 4px;position:absolute;text-align:center;width:60px;cursor:pointer}.container-fluid{padding:0}.content-box{min-height:290px;position:relative}.navbar-default .btn-default{border:1px solid #ccc;padding-top:5px}button.btn.navbar-toggle{border:1px solid #ae3433;float:none;position:relative;margin-left:10px;padding-top:8px;background:#ccc;color:#fff}.btn-default,input[type="submit"],button{background:#428bca;color:#fff}input[type="reset"]{background:#ccc !important}#outer{padding-bottom:25px;width:100%}#header{padding:15px 0;background:#eaeaea}#header h1,#header h2{padding:0;margin:0}.sx{float:left}.sx nav{margin:0}.sx #nav-collapse{padding:0;margin:0}#footer{width:100%;clear:both;background:#000}@media (max-width:979px){.relationImageLink .container{margin:0 !important;padding:0 !important;padding-top:10px !important}.relationImageLink .item{padding-top:15px;width:100% !important;margin-left:0 !important}.relationImageLink .item.last{margin-right:0 !important}.btn.add.pull-right{float:none !important;margin-top:10px;margin-bottom:10px}}@media (max-width:765px){figure.main-img{float:none !important;display:blockimportant;margin:0 auto 0 auto !important}.jq-menu ul li{display:block;float:none !important}.jq-menu ul li a{display:block;width:100%;float:none !important}.jqx-menu-dropdown .jqx-item .jqx-icon-arrow-right{display:none}}#topbar{font-size:14px;min-height:52px;padding-top:10px;padding-left:10px;padding-right:10px;background:#000}form.top-search{float:right}form.top-search p{padding:0;margin:0}form.top-search p label,form.top-search p input{display:inline-block;float:left}form.top-search p label{padding:4px 8px 0 0;color:#fff}form.top-search p input[type="text"]{width:180px;height:30px}.languages{float:left;margin-top:5px}.languages ul{padding:0;margin:0}.languages ul li{display:inline;padding:0 0 0 4px}.languages ul li:last-child{border-right:0}.languages ul li a{display:inline-block;margin-right:6px}.languages ul li a.active{text-decoration:underline}.metanavigation{margin-left:20px;float:left;margin-top:5px}.metanavigation ul{padding:0;margin:0}.metanavigation ul li{display:inline;padding:0 0 0 4px}.metanavigation ul li a{display:inline-block;margin-right:6px}.metanavigation ul li a.active{text-decoration:underline}.menu{border-bottom:1px solid #7a7a7a;padding:15px 0;position:relative;background:#ccc}.menu ul{margin-left:0;padding-left:15px}.menu ul li{margin-bottom:5px}.menu ul li.active a{background:#c4bdac !important}.menu ul li a{color:#428bca;font-size:16px}.menu ul li a:hover{color:#357ebd}.menu ul li a.active{color:#357ebd;text-decoration:underline}ul.nav-pills li.active a{background:#c4bdac !important}.jq-menu ul li{list-style:none}.jq-menu ul li a{min-height:40px;padding-top:8px;padding-left:8px;padding-right:8px;display:inline-block;text-decoration:none}.jq-menu ul li a:hover,.jq-menu ul li a.active{text-decoration:none}.jqx-menu-dropdown{background:#c4bdac;width:200px}.jqx-menu-dropdown ul{margin:0;padding:0}.jqx-menu-dropdown li{list-style:none}.jqx-menu-dropdown .jqx-item .jqx-icon-arrow-right{width:0 !important;height:0 !important;border-top:5px solid transparent !important;border-bottom:5px solid transparent !important;border-left:5px solid #ae3433 !important;margin-right:5px !important;margin-left:5px !important}.jqx-menu-dropdown a{color:#ae3433;display:block;padding-top:8px;padding-left:8px;padding-right:8px;text-decoration:none}.jqx-menu-dropdown a:hover{background:#d9d5ca !important}.breadcrumb{margin:15px 0;border-bottom:1px solid #ccc;padding-bottom:15px}.breadcrumb ul{padding:0;margin:0}.breadcrumb ul li{display:inline}.breadcrumb ul li a{color:#428bca}.breadcrumb ul li a:hover{color:#357ebd}.have-double-column .col-sm-3{background:rgba(204,204,204,0.2);border:1px solid #ccc}.have-double-column .col-sm-3 .row{padding:15px}.pagination{width:100%}.pagination ul{padding:0;width:100%;min-height:29px;text-align:center}.pagination ul li{display:inline}.pagination ul li a{border:0;background:none;float:none;color:#000;display:inline-block;padding-top:0;margin-top:7px;padding-bottom:0;line-height:1em;font-size:14px;outline:none;padding:0 5px 0 5px;border-left:1px solid #ccc}.pagination ul li a:hover{text-decoration:underline}.pagination ul li.active a{text-decoration:underline}.pagination ul li:first-child>a{border:0;padding-left:17px}.pagination ul li:last-child>a{padding-right:17px}.box-title{border-bottom:1px solid #ccc;padding-bottom:10px;margin-bottom:20px}.box{position:relative}.box h1{padding:0;margin:0;font-size:20px;line-height:2.5em}.box .container{padding:0;margin:0;position:relative;width:auto}.box img{margin-bottom:10px}.box p{word-break:break-strict}.box .show-content-box{border:1px solid #ccc;position:absolute;width:21px;height:21px;display:block;text-indent:-9999px;cursor:pointer;top:0;margin-top:9px;margin-left:10px;background:#fff}.box .show-content-box:after{top:50%;margin-top:-2px;content:" ";height:0;width:0;position:absolute;pointer-events:none;border:solid transparent;border-top-color:#000;border-width:6px;left:50%;margin-left:-6px}.box .show-content-box:hover:after{border-top-color:#428bca}.box .show-content-box.collapsed:after{top:50%;margin-top:-10px;content:" ";height:0;width:0;position:absolute;pointer-events:none;border:solid transparent;border-color:transparent;border-bottom-color:#000;border-width:6px;left:50%;margin-left:-6px}.box .show-content-box.collapsed:hover:after{border-bottom-color:#428bca}.slideshow{min-height:290px;position:relative;background-color:transparent;z-index:2;padding:0;overflow:hidden;margin-bottom:40px;padding-top:12px}.slideshow .slide{margin:0 0 0 0;padding:0;height:290px}@media (max-width:480px){.slideshow .slide{height:360px;background-position:bottom !important;background-size:320px}}.slideshow .slide img{width:70%;float:right;margin:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;height:290px !important}@media (max-width:480px){.slideshow .slide img{width:100% !important;float:none !important;height:auto !important}}.slideshow .slide .description{float:left;width:385px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;background:url(../img/bg/bg-description.png) repeat;margin-left:0;padding-left:15px;min-height:290px;margin-left:20px;padding-right:10px;position:relative;background-color:none}@media (max-width:480px){.slideshow .slide .description{min-height:200px !important;padding-left:10px;width:100% !important}}.slideshow .slide .description h1{font-family:'Arial',sans-serif;font-weight:600;font-size:45px;margin:45px 0 10px 0;line-height:1em;text-align:center;text-transform:uppercase}.slideshow .slide .description h1 a{color:#fff;text-decoration:none}.slideshow .slide .description p{font-size:18px;margin:0;text-align:center;line-height:1.3em;color:#fff}.slideshow .slide .description a.link-continue{display:block;margin-top:5px;position:absolute;top:0;left:0;width:100%;height:100%;text-indent:-9999px}.main-img{padding:0;position:relative;padding:0 15px 10px 0;margin:0;max-width:auto;margin-bottom:15px}.main-img img{padding:5px;border:1px solid #ccc;float:left;margin-bottom:8px}.main-img .description{font-size:95%;line-height:1.2em;padding:0;margin:0;position:relative;bottom:0;float:left;clear:left;width:auto;padding-right:10px;word-wrap:break-word}.main-img .description strong{display:block}.main-img.align-left{float:left;margin-right:20px;padding-right:0}.main-img.align-right{float:right;margin-left:20px;padding-right:0}.main-img.align-right img{float:right}.main-img.align-right .description{float:right;text-align:right;clear:right;padding-left:10px;padding-right:0}@media (max-width:480px){.main-img{margin:0 0 15px 0;width:288px}}.results-content .item{border-bottom:1px solid #ccc;padding-bottom:15px;margin-bottom:15px}.results-content .item.even{background:#ccc;padding:10px}.results-content .item.odd{background:#e6e6e6;padding:10px}.results-content .item figure{width:135px;height:135px;float:left;margin:0 15px 0 0}.results-content .item figure img{padding:5px;border:1px solid #ccc;float:left;margin-bottom:8px}.results-content .item h1,.results-content .item h2,.results-content .item h3,.results-content .item h4{font-size:16px;padding:0;margin:0;line-height:1em;margin-bottom:5px}.results-content .item h1 a,.results-content .item h2 a,.results-content .item h3 a,.results-content .item h4 a{text-decoration:none}.results-content .item h1 a:hover,.results-content .item h2 a:hover,.results-content .item h3 a:hover,.results-content .item h4 a:hover{text-decoration:underline}.results-content .item .sub-title{font-size:14px;margin-top:-5px}.results-content .item p{font-size:14px;line-height:18px;padding:0;margin:0}.relationImage h1{font-size:14px;font-family:'Arial',sans-serif;font-weight:600;line-height:14px;padding:13px 14px 12px 54px;margin:0;background-color:#fff;border-bottom:1px solid #ccc;color:#000}.relationImage h1 a{color:#000;text-decoration:none}.relationLink h1{font-size:14px;font-family:'Arial',sans-serif;font-weight:600;line-height:14px;padding:13px 14px 12px 54px;margin:0;background-color:#fff;border-bottom:1px solid #ccc;color:#000}.relationLink h1 a{color:#000;text-decoration:none}.relationLink .item-list{padding:0;margin:0 0}.relationLink .item-list li{list-style:none;padding-left:14px;border-bottom:1px solid #ccc}.relationLink .item-list li a{text-decoration:none;display:block;color:#000;line-height:30px;padding-left:20px;position:relative}.relationLink .item-list li a:before{display:block;position:absolute;width:15px;height:10px;top:0;left:0;margin:0 0 0 0;font-family:'FontAwesome';content:"\f06e";color:#000}.relationLink .item-list li a:hover:before{color:#428bca}.relationLink .item-list li:last-child{border:0}.relationLink .item-list li:last-child a{padding-bottom:0;margin-bottom:0}.relationImageLink .item{padding:10px;border-bottom:1px solid #ccc;min-height:100px}.relationImageLink .item h2{font-size:18px;padding:0;margin:0}.relationImageLink .item figure{float:left;margin-right:8px}.relationImageLink .item img{max-height:56px;max-width:100%;width:100%;float:left;margin:0}.relationImageLink h1{font-size:14px;font-family:'Arial',sans-serif;font-weight:600;line-height:14px;padding:13px 14px 12px 54px;margin:0;background-color:#fff;border-bottom:1px solid #ccc;color:#000}.relationImageLink h1 a{color:#000;text-decoration:none}.storyteller{background:#e4e4e4;border:1px solid #d8d8d8;padding-bottom:15px;margin-bottom:20px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;clear:both}.storyteller #nav-bar{min-height:40px;background:#ececec}.storyteller #nav-bar ul{padding:0;margin:0;margin-left:10px}@media (max-width:480px){.storyteller #nav-bar ul{margin-left:-1px;margin-right:-1px;margin-top:-1px}}.storyteller #nav-bar ul li{list-style:none;display:inline;padding:10px 10px;height:40px;float:left;border-left:1px solid #d8d8d8}@media (max-width:480px){.storyteller #nav-bar ul li{display:block;float:none}}.storyteller #nav-bar ul li:hover,.storyteller #nav-bar ul li.active{background-color:#f9f9f9}@media (max-width:480px){.storyteller #nav-bar ul li:hover,.storyteller #nav-bar ul li.active{background-color:transparent}}.storyteller #nav-bar ul li:hover a,.storyteller #nav-bar ul li.active a{color:#000;text-decoration:none;border-bottom:4px solid #428bca}.storyteller #nav-bar ul li a{display:inline-block;color:#7a7a7a;text-decoration:none;text-transform:uppercase}.storyteller #nav-bar ul li:last-child{border-right:1px solid #d8d8d8}.storyteller .content-story{padding-top:20px}.storyteller .content-story .item-box{position:relative;background:#f9f9f9;display:block;width:95%;margin:0 auto 35px auto;padding:10px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.storyteller .content-story .item-box h1{font-size:18px}.storyteller .content-story .item-box h2{font-size:16px}.storyteller .content-story .item-box h4{font-size:14px}.storyteller .content-story .item-box.with-angle-icon{background:#f9f9f9 url(../img/bg/bg-box.png) 99.8% 2px no-repeat}.storyteller .content-story .item-box .box-angle{font-size:15px;position:absolute;right:0;top:0;margin:7px 5px 0 0}.storyteller .content-story .item-box.comment{background:#f9f9f9}.storyteller .content-story .item-box.gallery{background:#f9f9f9}.storyteller .content-story .item-box .arrow-big{background:url(../img/ico/arrow-baloon-big.png) 0 0 no-repeat;width:18px;height:16px;display:block;position:absolute;top:0;left:50%;margin-left:-9px;margin-top:-16px}.storyteller .content-story .item-box iframe{width:100%;margin:0 0 30px 0}.storyteller .content-story .item-box .functions .from{color:#428bca}.storyteller .content-story .item-box .functions .from span{font-weight:bold;color:#000}.storyteller .content-story .item-box .functions .actions{border-top:1px solid #d8d8d8;margin-top:4px;padding-top:4px;padding-bottom:8px}.storyteller .content-story .item-box .functions .actions ul{padding:0;margin:0;padding-top:8px}.storyteller .content-story .item-box .functions .actions ul.dx{float:right}.storyteller .content-story .item-box .functions .actions ul.dx li a{text-decoration:none}.storyteller .content-story .item-box .functions .actions ul.dx li i{font-size:18px}.storyteller .content-story .item-box .functions .actions ul.sx{float:left}.storyteller .content-story .item-box .functions .actions ul li{list-style:none;display:inline;border-right:1px solid #d8d8d8;padding:5px 10px}.storyteller .content-story .item-box .functions .actions ul li:last-child{border:0}.storyteller .content-story .item-box .functions .actions ul li i{color:#b3b3b3;margin-right:5px}.storyteller .content-story .item-box .functions .actions ul li a{display:inline-block;text-decoration:none;padding:0;line-height:16px}.storyteller .content-story .item-box .functions .actions ul li a:hover{text-decoration:underline}.storyteller .content-story .item-box .archive-link{text-align:center;padding-top:5px}.storyteller .content-story .item-box .item-comment{border-bottom:1px solid #d8d8d8;padding-bottom:10px;margin-bottom:10px}.storyteller .content-story .item-box .item-comment:last-child{border-bottom:0;padding-bottom:0;margin-bottom:0}.storyteller .content-story .item-box .story-gallery{border-top:1px solid #d8d8d8;padding-top:20px;padding-bottom:20px;padding-left:10px;padding-right:10px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.storyteller .content-story .item-box .story-gallery .mini-photo{border:1px solid transparent;padding-right:0;float:left;width:82px;height:82px;position:relative;margin-right:12px;margin-bottom:12px}.storyteller .content-story .item-box .story-gallery .mini-photo:last-child{margin-right:0}.storyteller .content-story .item-box .story-gallery .mini-photo img{width:82px;height:82px;margin:0;float:none;padding:2px;margin-right:8px;border:1px solid #c6c6c6;border-radius:2px;-moz-border-radius:2px;-webkit-border-radius:2px}.storyteller .content-story .item-box .story-gallery .mini-photo:last-child:hover .popup{margin-left:-80px}.storyteller .content-story .item-box .story-gallery .mini-photo:last-child:hover .popup .popup-arrow{right:0;left:auto;margin-right:8px}.storyteller .content-story .item-box .story-gallery .mini-photo:hover .popup{visibility:visible}.storyteller ul.insights{list-style:none;margin:10px 0;padding:0}.storyteller ul.insights li{float:left;padding-right:10px;margin-right:10px;border-right:1px solid #d8d8d8}.storyteller ul.insights li:last-child{margin-right:0;padding-right:0;border:0}.wrapper-galleria-io{padding:5px;border:1px solid #ccc;margin-bottom:40px;clear:both}.wrapper-galleria-io .content-galleria-io{max-width:100%;font-family:'Arial',sans-serif}.wrapper-galleria-io .content-galleria-io:hover .galleria-info-description{opacity:1;filter:alpha(opacity=100)}.wrapper-galleria-io .content-galleria-io .galleria-info{margin-bottom:10px}.wrapper-galleria-io .content-galleria-io .galleria-info-description{opacity:0;filter:alpha(opacity=0);position:absolute;margin:0 0 31px -15px;bottom:0;display:block;width:100%;background:url(../img/bg/bg-description.png) repeat;padding:5px 15px;padding-right:40px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-top:1px solid #000;border-right:1px solid #000;width:430px}.wrapper-galleria-io .galleria-counter{margin-bottom:10px;margin-right:46px}.wrapper-galleria-io.slider{border:0}.wrapper-galleria-io #galleria.sfogliatore .galleria-info{position:absolute;height:15px;left:0;bottom:0;margin-bottom:5px !important;color:#bbb;margin-right:40px}.wrapper-galleria-io #galleria.sfogliatore .galleria-info-description{margin:0 0 16px -5px}.wrapper-galleria-io #galleria.slider .galleria-info-text{top:auto;bottom:0;margin-bottom:-12px}.imageList{margin:30px;clear:both}.storyjs-embed.sized-embed{border-radius:0}.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content h3,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3{color:#428bca !important}.vco-timeline .vco-navigation .timenav-background .timenav-line,.vco-timeline .vco-navigation .timenav .content .marker.active .line,.vco-timeline .vco-navigation .timenav .content .marker.active .dot{background-color:#428bca !important}.vco-timeline .vco-navigation .timenav .content .marker .line .event-line{background:#428bca !important}.movio-hotspotContainer{position:relative;border:1px solid #ccc;border-radius:2px;-moz-border-radius:2px;-webkit-border-radius:2px;padding:3px;display:inline-block;width:100%}.movio-hotspotContainer .movio-imageHotspot-scale{position:absolute;left:0;top:0}.movio-hotspotContainer .movio-hotspot,.movio-hotspotContainer .movio-hotspot-circle{border:2px solid #fff;box-shadow:0 0 2px #000;-moz-box-shadow:0 0 2px #000;-webkit-box-shadow:0 0 2px #000;position:absolute;z-index:999;cursor:pointer}.movio-hotspotContainer .movio-hotspot:hover,.movio-hotspotContainer .movio-hotspot-circle:hover{border:2px solid #428bca}.movio-hotspotContainer .movio-hotspot-circle{border-radius:50%}.movio-hotspotContainer img{max-width:100%;height:auto}.results-content-grid{padding:0}.results-content-grid .in-grid{border:4px solid #fff;margin-bottom:15px}.results-content-grid .in-grid .content-box{background:rgba(204,204,204,0.1);padding:15px;min-height:120px;border:1px solid #ccc}.results-content-grid .in-grid:hover .content-box{border:1px solid #000}.results-content-grid .in-grid p{line-height:1.2em;font-size:12px}.results-content-grid .in-grid h2{font-size:18px;border-bottom:0;padding:0;margin:0}.results-content-grid .in-grid figure{float:left;margin-right:8px}.results-content-grid .in-grid img{float:left;margin:0}img{max-width:100%;border:0}img.thumb,img.left,img.right,img.center{float:left;margin:.5em;padding:5px;border:1px solid #ccc}img.left{margin-left:0}img.right{margin-right:0;clear:right;float:right}img.center{clear:both;float:none;margin:auto;display:block}img.noBorder{border:0;padding:0}.my-form label.required:after,form label.required:after{content:" *"}.my-form input[type="text"],form input[type="text"],.my-form input[type="password"],form input[type="password"],.my-form input[type="email"],form input[type="email"]{width:100%}.my-form input[type="text"].input-large,form input[type="text"].input-large,.my-form input[type="password"].input-large,form input[type="password"].input-large,.my-form input[type="email"].input-large,form input[type="email"].input-large{width:100%}.my-form input[type="text"].input-small,form input[type="text"].input-small,.my-form input[type="password"].input-small,form input[type="password"].input-small,.my-form input[type="email"].input-small,form input[type="email"].input-small{width:50%}.my-form.no-border-row .control-group,form.no-border-row .control-group{border:0}.my-form .control-group,form .control-group{padding-bottom:10px}.my-form .control-group input[type="submit"],form .control-group input[type="submit"]{margin-right:5px}.my-form .controls,form .controls{margin-left:0}.my-form .controls.with-button input[type="submit"],form .controls.with-button input[type="submit"],.my-form .controls.with-button input[type="button"],form .controls.with-button input[type="button"],.my-form .controls.with-button input[type="reset"],form .controls.with-button input[type="reset"],.my-form .controls.with-button button,form .controls.with-button button{margin-top:0;margin-left:5px}.my-form.form-horizontal .control-group,form.form-horizontal .control-group{clear:both;margin-bottom:15px;padding-bottom:15px;border-bottom:1px solid #ccc}.my-form.form-horizontal .control-group label,form.form-horizontal .control-group label{display:inline-block;width:160px}.my-form.form-horizontal .control-group .controls,form.form-horizontal .control-group .controls{display:inline-block}.error{color:#f00}.ok{color:#008000}span.superzoom{border-radius:4px;padding:2px 8px 4px;position:absolute;width:60px;color:#fff;background:#428bca url(../img/ico/search.png) 10px 5px no-repeat;text-align:right}span.superzoom.small{text-indent:100%;overflow:hidden;width:22px;color:#428bca;font-size:0;padding:0;height:22px;background:#428bca url(../img/ico/search.png) center no-repeat}div.menu-dropdown ul,div.menu-dropdown ul ul{padding:0;margin:0}div.menu-dropdown ul li,div.menu-dropdown ul ul li{list-style-type:none;display:inline-block}div.menu-dropdown ul li a,div.menu-dropdown ul li ul li a{text-decoration:none;color:#fff;padding:5px;display:inline-block}div.menu-dropdown ul li ul li a{width:150px;background:#d8d8d8}div.menu-dropdown ul li ul li a:hover{background:#ccc;color:#fff}div.menu-dropdown ul li{position:relative}div.menu-dropdown ul li ul{display:none;position:absolute;top:20px;left:-130px;width:150px;z-index:1000}div.menu-dropdown ul li:hover ul{display:block}div.menu-dropdown .icon{font-size:120%}div#map-popup-background{margin-top:-9999px;position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);z-index:2}#footer .logo-footer{float:left;padding:15px 10px;border:0;width:20%;border-right:1px solid #ccc;min-height:140px}#footer #info-page{padding:0 10px;color:#fff;border-top:1px solid #ccc}#footer #info-page p{font-size:12px;padding-top:5px;line-height:1em}#footer .box{float:left;padding:15px 10px;border:0;width:20%;border-right:1px solid #ccc;min-height:140px}#footer .box h2{padding:0;margin:0;line-height:1em;font-size:16px;color:#fff}#footer .box ul{padding:0;margin:0;padding-top:10px}#footer .box ul li{list-style:none}#footer .box ul li a,#footer .box ul li a:hover,#footer .box ul li a:link{color:#428bca}.module-gloassary .glossary{margin:0;padding:0}.module-gloassary .glossary li{display:inline}.block-single-license{border:1px solid #ccc;padding:10px}.block-single-license .price{font-size:18px;display:block;margin-bottom:12px}.block-multiple-license{border:1px solid #ccc;padding:0;display:block;margin-top:15px}.block-multiple-license .row-fluid{padding:5px 15px}.block-multiple-license .odd{background:#e6e6e6}.block-multiple-license .even{background:#ccc}.block-multiple-license .price,.block-multiple-license .info-title{font-size:18px;display:inline-block}.block-multiple-license .sub-info-title{font-size:14px;display:block}.block-purchases{border:0;padding:0;display:block;margin-top:15px}.block-purchases .row-fluid{padding:10px 0;border-bottom:1px solid #ccc}.block-purchases .odd{background:transparent}.block-purchases .even{background:transparent}.block-purchases .price,.block-purchases .info-title{font-size:18px;display:inline-block}.block-purchases .sub-info-title{font-size:14px;display:block}.my-purchases .item{border:0}.my-cart .block-total{padding:0 15px}.my-cart .block-total .block-info,.my-cart .block-total .price{font-size:20px}.my-cart .block-total .block-action{text-align:right}.my-cart .block-total .block-action .price,.my-cart .block-total .block-action button{display:block;margin-bottom:8px}.top-cart.pull-right{margin-left:10px}.box-login .btn-group-vertical{padding:0;padding-bottom:15px}.box-login .btn-group-vertical a{text-align:left}.box-events ul{margin:0;padding:0}.box-events ul li{list-style:none;line-height:1em;margin-bottom:14px}.box-events ul li .date{font-size:13px;line-height:1em;margin:0;padding:0}.box-events ul li .title{line-height:1em;margin:0;padding:0}.post-nfo{font-size:13px;margin-top:-5px;margin-bottom:10px}.box .item.post h1{font-size:20px;border-bottom:0;text-transform:none}.attach{padding:10px;border:1px solid #ccc}.attach .box-title{font-size:18px;border-bottom:0;margin:0;padding:0;padding-bottom:10px;color:#000}.attach .container{border:0;background:none;padding:0}.attach ul{margin:0;padding:0}.attach ul li.active a{background:#428bca;color:#fff}.attach ul li.active a:hover{background:#428bca;color:#fff}.attach ul li a{background:#ccc;color:#fff}.attach ul li a:hover{background:#428bca;color:#fff}.new-properties{border:1px solid #ccc;padding:10px;background:#fafafa}.new-properties dd,.new-properties dt{float:left;padding:5px 0;border-top:1px solid #ccc}.new-properties dd:first-child,.new-properties dt:first-child,.new-properties dd:nth-child(2),.new-properties dt:nth-child(2){border-top:0}.new-properties dt{clear:both;width:23%}.new-properties dd{width:77%}.tag-list,.insights{margin:0;padding:0}.tag-list li,.insights li{display:inline}.tag-list li a,.insights li a{display:inline-block;font-size:12px;color:#fff;background:#428bca;padding:2px 5px;border-radius:4px;-moz-border-radius:4px;-webkit-border-radius:4px;margin-top:2px}.tag-list li a:hover,.insights li a:hover{text-decoration:none;color:#428bca;background:#ccc}.block-my-pop-up{position:absolute;max-width:490px;background:#fafafa;z-index:99;border:4px solid #ccc}.block-my-pop-up .arrow{width:0;height:0;border-left:15px solid transparent;border-right:15px solid transparent;border-bottom:15px solid #ccc;position:absolute}.block-my-pop-up .block-title{padding:10px;font-size:20px;border-bottom:1px solid #ccc}.block-my-pop-up .block-my-pop-up-container{position:relative;padding:10px;padding-top:0}.block-my-pop-up .block-my-pop-up-container.no-padding{padding:0;margin-top:-15px}.block-my-pop-up .results-content{position:relative}.slider{margin-bottom:0}.slick-dots li.slick-active button{background-color:#ccc;border:1px solid #000}.slick-dots li button{width:12px;height:12px;padding:0;border-radius:100px;-moz-border-radius:100px;-webkit-border-radius:100px;background-color:#000;border:1px solid #000}.slick-dots li button:hover{background:#e3001b}.slick-dots li button:before{display:none}.slick-prev:before,.slick-next:before{font-family:'FontAwesome';content:"\f0d9";color:#000;opacity:1;font-size:25px;font-weight:lighter}.slick-disabled{display:none !important}.slick-next:before{content:"\f0da";margin-right:-3px;color:#fff}.slick-prev,.slick-next{width:20px;height:40px;padding-top:4px;top:50%;margin-top:-23px;border:0;border-radius:0;-moz-border-radius:0;-webkit-border-radius:0;background:#428bca}.slick-prev:hover,.slick-next:hover{background:#428bca}.slick-prev:hover:before,.slick-next:hover:before{color:#fff}.slick-prev{left:0}.slick-next{right:0}.slideshow .slick-prev,.slideshow .slick-next{width:20px;height:40px;padding-top:4px;top:auto;bottom:0;margin-bottom:15px;border:0;border-radius:0;-moz-border-radius:0;-webkit-border-radius:0;background:none;background:rgba(135,40,39,0.8);border:1px solid #ca4b4a}.slideshow .slick-prev{margin-left:15px}.slideshow .slick-next{margin-left:40px;left:0}.slideshow .slick-prev:before,.slideshow .slick-next:before{font-family:'FontAwesome';content:"\f053";color:#000;opacity:1;font-weight:lighter;color:#fff;font-size:20px}.slideshow .slick-next:before{content:"\f054"} \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/disabled b/src/static/movio/templates/Skeleton/disabled new file mode 100644 index 0000000..e69de29 diff --git a/src/static/movio/templates/Skeleton/font/font-awesome/FontAwesome.otf b/src/static/movio/templates/Skeleton/font/font-awesome/FontAwesome.otf new file mode 100644 index 0000000000000000000000000000000000000000..8b0f54e47e1d356dcf1496942a50e228e0f1ee14 GIT binary patch literal 62856 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.eot b/src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.eot new file mode 100755 index 0000000000000000000000000000000000000000..7c79c6a6bc9a128a2a8eaffbe49a4338625fdbc2 GIT binary patch literal 38205 zcmZ^IWlSYp%;vqo1upLH?(XjH?(XhB4DRmk?(Q(SyX)W#I)m#B?7N%&@g<w>Nz<Mu zZF6#dJV{%@bO1m*4FG`n??3_mrvL#-K)`>Pg3A9y|F{1i{C~vS%_!vmy8pvq0i*!V z04IP4KosB&umrgOcXRyD0su$=wg0R&z!TsAFa@~%hfn~t{zKgUi?RJbIV1oM026@a zKV<`u{HH7cRsj2daa8}Gnk4^EMF2odUHbodF(eRY6Og71NK*#{I$+FQ#4RkN>Xu5t zDV|CZ0erHH%7mJ7f9C(hMgfc`(&`gnuuiqhEZtN@Gm6qm9jtBTu`bUstuVt`VE1U^ zQeRP-GNx@G1O+8HnNjpn78T|1$sHu=pO{n+?Hbd%?rXh*b{x)ZZ9Ey*heliTM$ph9 zeSOvxJI7sn2z_VOStQwpj}H7Y+@M&VY|#ngtbu=`HY)^$pT2Bh?F%Qz)A!hd^bxco z(ph?3k$*g}cpvrc9fcXhjj;5WPot~Co6>e-hv7*v=?ht4ZzfafOKSl*nvanjGNp%5 zq<K-(S9w#q8eMC7SiZgQp!0hpKY|?vxj)7Kct32D*$cDB?qOK!dRTPC_a&PoCm3o} zEhTj?;_sM$;BnBKbcE93L}8oghpwVL)kxDRs9hp`FXm%HAu&Y<<En<u(wG`T7*gc3 z3bO-Ofl-#Om5wI~Wp@;6e|2NinkKKyC^7MXpYJenk|Of)GF8zy^|2*s>VHEAb0A25 ztDEMbuMI$uR5*rQ;Ex2f;9~>x3rZo2m^kwR6UQRPZz@Czx8NQJM6qF(2xu!inpqCE zp&p-KF}@yM;D2@511uFKw|p7`rR5E%Q=P-zPeXA1Ktriy6is`S1oMudP6;lGGo*>+ z8#MeQ*S6fE;37Z&V&V2oyeT_l1gp@&a)ah*E|M@ELRv^E70jhArQEOCVR(XrnfK5q zp=6hd;d{^XAPeI<#-L-CBvNu5_(Jtd*&!2*tS%|-yzds5)A{0f(w};Y^KBe@AdynU zQL37Co!%Eq%0_)~bcR`#k94J}qgc4SSR@Ul!8_*tW{Z3Z>U6}ivNUHWn8P$)EbfkT z@k>R%?c7o_o;AP3>Pi=p)K`@mYLKBdm&H(%0ai{ls$|XAptE5F3tx6U{?(i@T>GA3 z^_!F+A*NF}bxUB`5ssZLyE(_w@^Dbsgs-6_CGq92Gx|oi!cA-HhDACy{4K)xs|&hF z>LTWj1(w}4LTGz@)0q87y$|wm>pEPvgpR{F10WY$v~2DYt@t>2Z4;zPN_He3aPb@z ziE0^tt>sf2&yu8qR?@PaDB@HEgBHaU>Zn<S{h`?tO>pXEB^D(;d~K@`H3P(?)J@Vn z@CfT^4qS#V(v@+Tim_UUz_Xd-$p=1fq8#h)@{UE|bVYBR`b>ehNCJ;D5bU7L26}ay zF9bjM0OWm1Ao>6*BK&HtwoOBWueI2fo{G7Y(GD|!_MzfV9ur=<&-+oRNRfybM70FE ziI3L556BV<%TDstB!_UPon6HAw*b{&kueNsC+=#&J+)243^;t8PopRU4eb)@)UjTC z%|J@gDtLqz=z5jdArpDBF8$;L=m(uEBXxr?n&v3{9kTU@&#yiW%YPB)RIU}%aSn`6 z$@EM;F;6}0Oe=&L&gfL&?rfC)Kx@IRPdd3jy;|W(cPJI&mJ)b22%#Jh)6+MBXi}{R zv^IAae*Q9Ff|}Y>L3KPUWC=0h^@i;U8!M>_c<Ctf%lPPQ?8s;lmh>S{w^1mL3n#)V zzLDJBVg}IArNIql9*}a_j5k%x5~ySF{kx7~rG&ilzkAtDE&P%=41?qbzUVW>mJ;wI zG5?8dPhnk<RiJ5WhQ7~j)Axx;T*A!?#mMh3lIdxm$-UKI1Q&`tWht=o!KG8FGz5%~ z6)ftU4i$K;R&dg@h6Vcz%E|Y^20#u-(GutyMUd;qb^W#Y4yRNgFQi1-m?RIJJb`Wm zwbB6gvTV1jJxGg~<s$h=lMW?>m~3cU8v`q<jnB6Z;i{9vUU*yJU|oY8q<~U72$Mji z=;jC(M5GPVlLHKJC}=P&CPhp~FGLt=*IVHpTJ!MNaJ;<<)KuoC6ludUf1quhK7QT{ zAdhm1g_>iyh&L1E1^VPh=!%X+Uo>1c96Q;$2#!T1Ajyyr?xG><e#&xjB8?6fv0;J? zh0eWUJSk4s^jcg*+!H~=QM5g3t;0o&=Xp(^D4dgft@(u%dEAgs4{2<vj?unqC+^Qx z=KO9$&yUNHhQQ;OJWa_GI5f)28#qao+JP`%=W02ePV^XJ=qdKNmgt9jH-ZRl=WadU zxihut=x$V1@^**5viUT4Or^<liS|InNiMm4aP6f5<0`XO+<w2~AKm*u5&=hhh3p(P zkT8JtN{eEOf21l=@J!<>dq*93%MpnA#<7B$B#7=HPXzf=n$eqoJt`+9|FBhvLb+Wa z4m8GHx>=pcMvH?ROyEX%6zNvTMAD1qZ;AsG_0HNgMRs*xMPr|7Ah1x>6n>WIU!Rbx zAYDQVirff^+o%FmVd0B_;=cS=Pb5fBM{XhmuA5{$CX^gd>K>tNd;Lue-*M39)i8u$ zvl<QDhw1)+FVB09(nz{kgh3#l1K#X6JAV6xY3lp}C~g8#D%AXHuULeAaQ&A_{8-0h zV_?}HH?F#<RyqQig-&c~X2;}O($C;WbVC7b29;?RkB_@S)~;BWrkSff+=p^^nHZP{ zOP%vDuPO_A?{}VY(p&`c&nq<>oM|Alu~~`DW*t3*x9MP(pP*a$yx_Za4IsuM$&kOP znIjBTyD&_q?33=(F8vwuz4}#@VC5b=BR^1qta#WB)w-2XWN|LD`9AlpS}&US6%rj_ zR<D^jDA~Euj)MaY{<JuP#N41|<@gS(1e}_J6<uLjdx4a7K{&jJbvq8la*<rUN0yB? zmQ6^K@>)6|i3w@-sbdLY*wIZzMyd+h(eZ#``O&@Bi9YU38yi!ozx7p}(2j2!@LD^z z=Hq^=#||B`(#WvR3+)d*sr80<P`SigM&%;uEQbfvanI&TCqp>BN|Ky6Jt`#Qjwg11 zG(HT7qi~b5*RMzyF*&HHxNqS2WkJBe>I_J0^)kQLmlNmelx<Z#$h^QBeuNa`rmCay z!@(~yY`!okH~mZD3K!$r0fR9H_3HimKn~Ye{w~_5F%@M|R+broDcW`h`Ha;Fgvuus z-AYb>f#>?%<hs~RZ&1N`-sJZt3p*K3^PP`<gs`R_fBolgn(a>GJIl_lQcfQhMcCHR zpjs9>tRLYo;~E98pm1*t7SyL+0x}c<r_t_Hu7RCDtp@!#D`ErxfR`(GvgFwz>VhI- z>CT#lG-N@6SO=jawi;8;(_?PT(9ie_1fvY;Jk<H9mdj`FZJcWUB953ZUIji1{U=q4 zsUnnqwD%lQZjd5zia!S+{862JP1VGU@Hw${;f)9gHhp<?vG$Q96j!P1XU#hed;|^x zj-x0-vh#ChJ7;R{6fD(6YRwkSwd4%0cyG_qbLG(3oT0~~x!RFv%b2sirn>2=I_w!E z!Y^R`3t#8*m?I|Ud>4es$FXWl2HUO$%~7*kxDsbkG4Q&Gd8^ez857WVF=K{GnKur# zV9TxY3P)fpjfiFra;dkVwPR>95jhb+kD|;*iA+l2Oqxik?B99KpfozgmzxwxSylWb zg)%DWt{5oQP7NgLljJDmH3}IPvoJ+PtxxycCnYT&69cDw>&}In&F09a^uTC0WeDa( zEL8Nxmcz5q4LfwxV%sU0hvQRh+z2C;vEp+E2B3SEF-f|#6-mSx*mK)c0$fDM7kPz8 z?`_-7=l0}C#Zht53SIt`Y4vfg!7WuL-bBA!&v`K(@{u2PXiuNAgvs0jjDCI?mYq<; z@mZQ{ZtFKytujvz#Oopf6!|7kA*r+I0ob}^W8~7^gRdfY+9S_F(zSHB!HwR(Y{(zI z-ibb7)VpopINsALOXkwt^<)cm?aV--LZ?;j*$ezC^n=3iBOB=!JGQ8>rYy~O6p6Wf zY~=*?XKaLp<&Qo6W<?pqb>*RX!e1xBb&9_ct3YV5z_iE#2JViml)_rvMZsp2wS_<v z$6a5%{p~(CG4!09RE#*O20N1zK`r<bFE+$zfOv8Bi|<b_HJ$jXM+tb*A}YJG_g8c# zKoNHUJJ^(}V>7iXxJvew%gf;mkQY%&1+`Gi*e*2*B>O@GO()_#LH6z(C{)jcjQ~2H z)FMk)q>Sp8;Wk^A>(}J1pqse|RN~jF+6{lt1bbson9)wiI+YmW7Np-sVNxH|T&AA! zBI7Xjs!)N);7)_r(h`BeuV_SgPbsHm*uRBUVktIpforWVBjVz-avd%1F&mvltBvF? zfNt|pMlEQ@*r7Zr@j1anSI{yWHPQ$!*)ikA<a+D|x2s%f{6$Ia2rHW8*HUa6fhb9Q z9ZaWw36m_&&HxG8%}!K>EYb7Vw$0#qFN1VR2OI)KF<Il{(Ej?KTyaLreT?RLAURjT z*1;#xf>A*m1z+qk`Qy*pW{`d{N@Nn-0){$edMYF#<XCws7`YI{gPxZ>Lln)aUBU%x zpbeNn0tProp-?4C-fLh&EA7jUs3uXR>mE(WMi;sRvb?M`LI&#S!`abZ>*?LAUzBEv z;)Sf?7eJk&T&RX^Zw74e7XPe{@Ple&hu)^v@rLAWVA)heayJ-&0YhI9ste5a#M@pF z()}*Gekga)6<b<5JO`GKjayLqY=;fPraPe*Uo&o}Q60RDQDujCGb|>xf{ah%_;p~T z+j{vjFu{}Ns1UWUeQeT)f!3d>d;a(X|5DX!wu&XZ9eRYc!uzZQ6r{8oI2ArhVA%G? zHyb=YT19dD63$<YK@<cPx>YpPa%n8ND7_Z+Jr5NQ>dEfM3VIVW%dBxo*UEF9g+=Z` z3D|>we0$`qMMT%+#&?bKsMuGo8^3qSNM2?u$wL0_nc8UkL68&{gP*<Ie4f<w7ba?` z;$LOCwn#a<eR-3k#gvR!X<KUdSCLw-yO&kKPlgQ%nE(Of-CGYendf0C4K3z7b{?pX zgT^9rGBZ~F<&PDZ?<_^i(->hNYc<tDkHvq<oCZOG5$&gBZazFTIaC5VWc7$a`v@La zwT8^dPU(X<-vKJAKA|MvPCf@Cu1V131{zd$2d^NM)y4Hes-V%~lP3al(k7a}Aw(a~ ztG<z;ygX;<WS+rO##>XSBRb%cB?pVTSk*kfIOciI=QQrZ1JZwiYyN9#?{qgO7Q!32 zgX+p(BAS0u%GTgED?@bG%^)gzHm;AuU5;tPf-`#gsCDOP-I(3&c+iFWwqT)~_?WRs z0IY9YJeXjU!Nm%OqKuR|k8Mk;_D%MBlM=Kp?lshdEZwvMKMFR{C5D4la_j_TyeaQ~ zdS<e-C1w!O4w%tLaZYE!+}~_YL`+w!?!?;ZHRQ#t2uh{Z3exah)PThLW?0LWA<AIJ z-c!W0q|z_-XVL|>vtTk@H$=sJHwFks8_|tO%{fojwPmtKj`Q1zQ>HauCfT53_ze)l zTG-M87<=x<rLe^zZZZTpeU-F^9xVEY<pbi?N7k?y1tq@5kY%d2zZoqL^BnUD8aY=G zKW8Z%BKl-SWL;O9?U{10`YE!(tSkyCXvVzw;P8r0Mh#-QXyoM0sGXsrILll9P>xy| zDdO)&IMC;(lZM18FVB?v=R|Rw@)!k9^%zF2N_oFCDrd~Y_ws}mz~dKX%-kV41cU}} zQ~qUWCv|=_P_%uplL?G&6J|d>Wk_c3gKFN@F)jA%#ii3cI4UcpfE7lu4V5L?>N`$! zk)h#WZ(15(Finwk1ceGKs3lJx3!EAjUatNdO{TJTR0f<Ij)O*deEL_~CG7njb9Srg z8$A)McUg7t)3VB5r*mh5;X=7O>@n1S1an1=2=8TU1Ml9{F^EsNZr(g5=z%U97>sgM zril2uR`W@#-Wt5t4Bn5Yz{|T;kcFdy!DE^@u598ty3OaS54s~Hb)tkY7zz6}Z_G@k z&5BO9g?I?$$5+Ud9=`SC0y?M!A2=yUZ(a`<OZIF@{^QAoDcXBGDTs*~%lm1JelY9M zg<Tvnn$4%M*PHH}FqLj;Yo;71)E@~XZaq)Ay%~e0zPsW<9VlzVii=94tsh|eCaE^% z&YHg*-zJCXgAVJDYT)#$oJNB{WbUuD2<4?-4GCfiS`V^BJ!NfLs7s|dr7KVkJKWsM z;X@<Xr2iPHj4B6ajp#UWJo7+7x%EbRcE(~2JYAfsO#Bg!o_03i8@4C@rIh-eYxtoc zroy^woRpERd<U=wZKh);j3zomibkCZsKg8(US09g8Hx2gYc)~xhu-GFWSihSP5nW< zCIL%%nmQcS>GKLJ<ou(vkSv~C;a%vQMKz4f3TK`-f=}1rpUCjXaQez>%Ec-W*#J(z zal~$;zmv0W6y8{yxu3p}rN~roYmS7RdYm}J=#D391J6{cb%T#4)$PQp>Q<taU8aq4 z^<x{J)@R@(&{L#l^P}qIdk$s7u^x^nMh}(vO9YArIeRXN8=+#e#wn#&E?F@*DZ0JA zn&Xk1VHScsg7-+(Vd8)oRQ_Vz^5c;)%*Fy|Ab+<5p5$=<8NMx(@VHA9b`UbkXoAU- z>8-uV-c7&nmY~uoMX$~7PY5dy=uY?@pM1GFC@wI|v|Qrw-=$Sf4{wk5&4_=sF>gnp z*P({nvArrS<B~o~hz3m~TZC`XAxEhId<NHep8GNyWc=W`UmImL$FsG=6=1+c_z4qF zieeIW#y7C<Y7nMhwD^+@ZgOzmySxv19aWAPneR$knw{i{o`lmo?Z>(l#^E8wXB^60 zjj8eIprA~2PY#gR{Q)B%m?ITG#X@32;je#;)B6g}9@Lo{@=*J&tl^#<OG4|hAf)%1 z*O?}k^Ap2tYT;mvP~MGOUEvSCnfVd|-DL0Pj1@=pcF~f-l%oPCq1&%Z$a;-k4($yw zC@lP7YAG`qnWwa^E62Z!r6Z6Q&G2wkf0$IFu1r!Ik);tvJr61`7kDG2WB>@&d70hV zqvdqNZSrNvD`pj@qo;n?u+SB3dYiht9J6DcMtae}KQt|F%fb$wYUmT-k7u?}UG8yl z)Fn}2q?zp*uBGX@u7bNWI76Nt7RMm)!sbX2Hz;8bW%E3gv$UWV_F%`6i4Cp7qpcfJ zDggycgt){-@q3Xf(|fbVc=5I>92_~)!?urM`!cFbfKnO~Et7=kL&!+Ci3&hjX#21i zKFjJr(e$x^2(e2@eFplc?uR%6Bo=N#WU7i-P3r}$20vvC5=maef9!lE`8^MhF~c2C zpe=9m1d%QT;koR$`WI=uIaOv;*&wjp4F`WIs*eFc#p^<+tI9=knDS`Y5Hk`w5F|r_ z4?}k75;f>g@CXGS58Xp^u#Y!M9~*|c8HAWY>=({SS*)Ox9&@4z<~uD-@;AQcA~6`) znp0N7D_`!W=)@bxJMyWUz#U*pQ{cN0!i%$t+J2M;9RU6#E3;dfkcw9t9*NT*lcI1S zbVTz`ZG|Ev(sHZt<?w^4V*O$bu@1dlZxS*WwqV-k%Occ7`{Du-!Z*)Y(dsv?J&-xR zTYgrj!Z`Cg6LT_mmD<mDr5Jm*zQaei(g}!mn`^Dg+;Cy7T5ZTfSx6Ow!O^^nQ?`9a zg?(zO(rSxi$Zk^TE0d2ar|)Q}MCWF~yH83-V?;hqswd)@DtZQghp&aO1%^Y`B%jfo z&5BJFAZc=Gf(@u27ii^^vGYHA58%KO$b~l#MGz1k;62rl{_EW#HS3hr_KN0cLtDjf zSR5lax(7A{gA;@9FIN#w2DWAiWRNOea0ci;ZlMY^z9K-Ha|)?t2yG`KbUT#E=_pfJ z>5`F5KoNfAh|<`q^eO8loN$OjJIl2#PXtQA)~wGv&f^-Al_TjJ58Pa+M5kmz-NhD0 z>XD-aM~}AOprfr!hqfU<!V6w(%iv1+s`BGs$att4p|OsAm#)fZA^Wso#@*;xrg&^V zCjSW7HRHzBm`gtaSk^;!Yu%inM}4^vMoe6Q;gd^F3MJmJ-Z#u`Cc$hGjwKVK;g?I; zYR$?*a$=Y$IFzQM86;b}$*QBxrV)iCNK=u9;u{&64foHY1UdqXXn|{*eTQi%-Voy? zkGQ%O)APT$7yFW5m=sJ25u|0Gsk5=?DdOi>w;f(eLw$1NUyo!L*Yc&h>8ZR3PcRsr zpYsNmhGRf-y508v%`$L8SaCUt#Le-|`Pk(FB`->6b$q*QiU>;5;ZO^-`(W`&3^SQ( zkqH=nN4>YBjf+!y{$c`$oM{CvIf05nmqxq36o*w@|2|2@sQgRAPEnrIYoiG6NcTuA zi20@ezU2fusTA{G1B8BuLkp+2=rSrPB@K@xP~VI_i<*3sk11&W&=Hk2t3r5-zDpV6 z#dQ?z6_e_cU_h5fCw*a;JR+eAljWPV_Vci#Oh=B8idNeaXLW~$1j{iF5rJu`*b1F% zh*c0OefvNb3TPm=QtqJnS&kg0IhUac=EH`4_JOdO2>dyQq`rdoW9z5}NrSU|aEVe@ z!0U9?EzH~X@v58!f-M3vXUndSwO;G6qI#e7_sY;FZ`~pD{4qHs6Dq@w0jvTvuB-~N z8+2+lf)Uo1oXzp{W-SR*n2#9tSW9am$`FVl_l@Qnkpcu$B>@qN%5&yQ1Sw+BnKemL zRfpwW%f=D?SAe7)%1{97X=s}IQA|YiL6S9K$N>{4hvtXo3ypJsGLwUJwmpXvvPb`i zPkFFE0I#<W?*W^jkr#9F&vESL^zo_}8u9bCc`8%v+Eb-p%h8U0k;Ix&h~x#^N)(nq z@DGA7X8x5>G&1qC%RlILTgZcE(q9+YC<%6We|>5Vf%t>CBZCH(2j~p;r3-+a*1_ko zbDXT3(;;8uXXy6+1Dk)LQsHjW_wQy>RZ=1Ndb*^$3dPZD;?iXgYVT4mXTRmuV@H@d z+u^8>gmn-Ztx&?PG9OW)by86jFo4ZHASsxOGZ=<np;Tm++Kbm{3bN!QQ;nTe3Q<Dn zc!Y#d#LrP!MVu!jST4A92lY_&atWKqitu$}qg(AVE|Q++?#Wn=NvLDzS4HHpYNeP2 z0XHqurD8@Z!M)Py=skb2sFu&>Hk?0FLtV$3cds2baN$3E4A#Cl31p{Ux18pUuLY!{ z4`cJ3-aWj(HRT`W2eeMg9XCNOM0LZ3*_F@?(ptb*MXl6wMq(2O8`(E*p^_64!N@mh zN}T6Iy|eL?DEPiQ3hfe{h(y80^dA*EwBR9&WeP}~^-1)Q!~NsxR;~NduFokawu-+X zBk?;o@e$fU1Ti{AzikyOdXzd22eX9kBS`pQkdEjn{K^EqmgG`{$d@+XqZ9O6SY_gu zVF`tjkVmDrsCq}^dc~hYd`tGM!y0j&M8QMw%5XSu{5J^=s>#z|3VD@{Gx!}uptysk zT-+YXFP4p2TEnMWl(`?Zi-2;tKPjKmJ|@->q=`h8(^8lcI;rt9Vh4rL1X0bU&<>to zQ6;sD%}9Rgx_URn9|V~;>{Y$#W1I~`l^ZP`I}3}K2ERDD$UwHe2|PEk(Z?gSX5)<+ zdUVERMQ8fU8wU?*Omoc^6-f@ZzMlOCCI4JZ6pFU7w%(&U3w2ffD{wNRM)kBsFp1D~ z$hptcdV!tgO9it8id@_=mRh|S1`n@*{P87e8yPYawPY3Ej4zfgPmjpJt2xkQ)}yWE z8!BwmbeSH$?$nPCXocC}BuHU>8G_#JzpON-o8dHDrRT}GC=zG4n-7RYj5gxvKZ=Te zS<sOMu$Nc{>On$?;)Y`Oh+*oP4+?!cN|V?jhT*7k+1UwXf3vmw<JiEW_1<x8-cZ|6 zjC6(YlO|urIsBeNHuv1GFCJ!|jH@{%?`=Df`}UykB8+yvF)@RQ(DJtr3_y`8qjVj& zc$;ngeUgT^&o+ZWf+I7&JPJauNy-=lcG}A}TAasPB|$<vGEH#CHQ3a8T~b(QbO0P{ z^(k2JQ|b0Mc10OAVW3tm$>_`8RK38Xw0v`a;iv1{x~`@aLM%hM*qtStGVzXCYf`q* z_(Exk=MfFjEUpAv%V>G@&>gR|FJndsyio<?BCW@RQz#Nw4d+4>uJU(}m+h$7w~k3( zW%y9pi}!Z98ob(Mvpx~OfountwA-jxjj<eTIy!_hBh#p|n)uWYUbn`M^2j$W(!S$O zQ+3Ap6K_97$U_j8+(N@v9yfE51>OYhbyE7{fri?p4n@6qdH^jr7&38fVczz`O5|rS zdy!`@=)KgM`o`*xTGX6Xu3ZvA3j2C&@tIF-vj3*NrQ~{bnX;X!<-Ae3z#`X$V(A?- zR>Eba34!GF`jUademjbn#TO<mNO45*cQY#JcTjreS_K8#p^6z5(fZZNswypVkL-|Z z_+SNGpPvF?^emYW(9Y@-RGsbuZ^x0$mQg!gl%!hQ&RTB$0JiN!;;h(3yUJP^j64)A z*@{8L5W_7$6vm7t)FOz$FfW#pa%ryX7n;r3PUbL3#cM8st@aUb@hBQV%>6DETFmI1 zzS4Ag!l8Mt{T_^WuF)6(;xNHm4}e?OJGCJrNUFcL`Kh&jmc&pBdHbLT;X{(%Yck+$ z9rj<FIV;ZJYffaaEr(<&J=4gQ`h2ZpIy>dgp4HO5J=y1e6o0fXPkuh0x`e&vK^jbN zLp|T>34R?^3!C<1=U?}@<A>-t=y2v*M`L27Wk8BFOxfx|1;Xni@||$FAh)b)?sBW> zzw>aD<;V80(-5HXqbXyvg-F(qA6|AbNFJ@SK<HDBggig^_X~=ztHE)$Rg^tv5wM)R z%G{{;-SUspyYF2nQ`^1qh7c@g{Z5iC50zOAkwT9+hjdWxJe!v|G(Y!$mN03c!>>r2 z1KK76v~3*m5M?RO@~rZr4@<>T$Pxjuw=^e(_#E?V8&W8b5hz8G9Og?S%wxe24~VR& z0*ZpRTVmJdRbj=qb<5uLm(abvLXYTU9@-jw)?ms&mfc8AE!QY0D)J>g-lmy@O#5rY z6WLsH{weaGczE8jONV{}7m$23_L)sEBHTLA?Zbb6s1(3*q~4x|K72BGM_9-U=s9<e z&|8HyKqN9C*l{gF5yT|N`C|4bqT+l$8=FC<u?(+RNSxlbr>sU39y!~V5p@k##Z1v$ zRm8R`n7%GrkuQ9-DMesZFZqp1B@nB$^Rq%jm}XzRNYPx9EK!;LbE>VkX}0H7VYmtx zJjuxDl_{Gm<0co4N93{5g1C}PR|$ebo?XxyrGGPoPNS1T35K!QkOYXJjNv~{hQ<}) zj=PwUzrPmNOe$M3S>%<Ypf7tIjA~ruj=pqPhnmdTSNmjgPqAds=j#{T(BlOgiL$WP zThz$Qxt90jc5t(Q%~%D^GQo1=fOVbMS~b9l(AlM)43Z(u(eT`8hzl5wT)xabz%3BJ zz7BKP5Pcj33i<_$zZ#UKA1PAsb!LzG%*oQ|BW)Gg&m-axo@EECt=BGg!MsrWv*`n_ z&A&swF<7`^3z0gn()9=NCfYB0B|6k6S#zY5P0NuLxy!wWplxLi^7?w?E1v|WoV`)k zZ`x`)wNxa+I{Q=IvGMTMMD*$(Q0dbs;@fl6f|8rqvMw<un-#c*fpn?YqV#qUl_Q~O z4VRl-x@@pgnTQfp8(kurMVfi_a{4+hM?CbaVnV^dEgp4A!|;${02E(755{D1a&8FE zJ}}P0nD~O5w1nqPD1dd!Jc$%CB0<@JDcqozMaC<J^G6iABh_OI$Vmcr6M-sPrl*|? zx`huGDB9F>bIQ{zQ?gB@@uBh3V44xG940Al0GE|aM6Jr(w5h1=03lZIFbBq;f<j|g zQTZ9PLxf}_mJkt2!_Vf)Kb{(3S(&$>Vp3GD+(ARJ!+=|3t4d~)LXIZ2?0`BfXcHj8 zbFHKWn9noh6O;9%f2%<CGtCMI1#i5DbqYhw<j>6a{o=6@ySg)Fj7Dl80<VG8&xgXO zUP5^xtU>r{ry(Q=;~OrOv@ysCr@<jCU6ga6`ttp=H=GKGh@m9FKd~sKVCav&LY@p7 z84*wC_=k^L?0+WT&<OK9ZR;qj533g(xSOCkS#3;Q{|cK{QBd*jF$iFK{>xCg4Q?h) z0>WslwOatjzul<rqtOjX8nQ8bnobzTc?o73&wyh2?~2U`R*VW3mp{kniPbiLLSL3? zj&spP;D7tRILM(ZV?S~#(9AgT<qi`AiB_7EOIu=tS)`C!fxx7KM~wQu2z~P`<L+p} zl4S}9g4%*-INm_Zh({wqPC`HZeOz;=*B1|u9<hWgeZkZ27FBd2T`r<gj1)d~yQ-?Q zJ`D8-bsdTt52?cszu|gkB6y!Dj-R5CbLoMe5oQl#1`;SfWhd8UH$9pHw;jP*UAer( z8Xp63qKkSCq9<)*z*)5CP+Y!FGOp*gEPCq^(zjAnABcyhb@Y@RL&tg_*2*BPuV_#H zk%uNwy(tH+GHsZLC;>yT&7q=aiqW`VEU)869Tu$`L`7jXD3k3&LeBAPXqa?S`Pd|7 z2qFA79}#)cd|QZvZPO?h+Y&M#*`{8bO5oYngy#14(vLt|k0Chlj3<Ff@BaOJuFpC~ zSpEjJ-IOm>L@1ZEP_ANPmHY|$Q<X*@sm6&Ul%?bRtsq30w6r`W4a~E@gxJMuQGtzJ zknvxY(X1fq7@VX4Qqt_a^ER-UMyTMi_J~@!;2bFq^50qCI8160o>XQ!wD`4GueT7t zb9DaP`^6<LdFn1Qd73hj6PX>}`7+hfI+Lt3byh=*|2RmW|5RYL%|k;X#f~6<qUPkA z#)$NRP_7j<Vk6?eLki87x$|FM{+V+6|Hce-{eC(1qf+!YuXf;qWB}&v;w!fXY>nsc z*CEiAl#o!);6?bZ&&7Cuw=)?`YsI9rCORFy;ceZau=(}DK+fzi?8WFD6_MBMG$ml= zMsh-4ss&nJ$hgT~NSX41@Jwctel6t^3f!aS7D~w?`X92Uy{}4vADR1Y?ObuRR)4U} z2pv1}O4qjvl5YamQNHtoGN&HSZ<PE5T%LHAg#9qQHskmp?p_0^++w5PSI@_sQQ-F} zS@;!lJEsaaRnRL`eit{5sMlHEL4A_9pML+$L@HFB8iy=^EMdR6jeaE8=Syj!4MieG zLS9(8|MfA|K8@lcRZ1>ttO^zz9Oa6hS-=n2);DK{SzE6Q+vde1;^FCjSC9$*dy_*- zJ%hTbBmFU~CdErX%Nyeb$#OsI&ESCeA;@k@I4(q&7^1U1`s(G-VP}*LfJS{r7`{#t z3<nwng*<KxUqpn(?uep56jy{@<$&zeGh9QO)}RQQP}|flnk(Qo`(Q`qKZ+rPL;-5< zqE-pIOXEO;jsa1jE$*0Bqv}LKDL;+BHsx^qD~L2|pa(PTSt&9PHB_AKLzSMMIlgF; zNaOby=}V5#q!QR6*dN`zkf2z1T1aNt{#mI5lnpe95Ym|pN<O%yNhb*c4G5!l_%)2_ zCzwae*i2%;D$<0q@){lD0{Z<Gt>XBp#<W3HvV=cFuz)OuDtgkTguhP<JZ(_AxR~Hz z;DFVe8v{ScS6)KL9w;mN^fZ{l^%W;Uj=Vyt=T2p|5kv7^1Ir1+ibO$I0-jaGV)+!p zHn#uPsPQZqqZ@)Y5#1p=wp%nhrXwJ6(`kBOU<IQ<=Z`l_&K;{|dfG6>j3T)<S^z>A zE{aoA15z}9lo-8(YRQ(SblP(l(>v_To=WdGwoOA(@uxpNPV2il0IpNJ2f3<ew^hL# z0`BlAYZb_l;yAGhKB75TGb+S&IFa%lbXXpfMLRonUMk5w+3AEBK@;Dd9P^lq1M_xX zY>e-`Bpo!h<qR<(n+6PsIl)m@eqUM4VKCr>L?RGM5E3eh8=8p>5^l_lXR9EPYY1}o z(k*0k1kU9Jyl--}Xw&XwA1P8^Q?cdv!cZY&l&Kq>B9GCGmdj4wHT^9dwMXYPap)$` zHcW`T%JL;fA%H>*c_mB?l#JLN?qHDW%PHjlUn{q>GpoUxp}-?hslNMUVKQVajYo`7 z>$&QaAbR9@gn)v*X_q1S^FTc3n^;^>(C45_gJ;x8ksNA!J8?Eww{X(y5t1#x)f`Qv z$afQ#`DUDiAP+HE#XzFQfSdoe-ssF`yXbms&A<F7^I<Fasp)sU2S7AA<`~DKJXavw z*tVwzZG&ggzuc^@k`;Q84`NoZ)In(Hd<AVJuxy3G0{&4=*dGySAz<*C9ap_Z7#zBA z69H*bshOxBGM)ifW~7!1j`hrtkUtZ{3V_oZ3BTx2FiYbFUUAIl%91qTfe12xWbZcl z#su>6+g4ZQu2BGnb5t5;(%?va?q$&kR<XdQIBhCKdz2o_1vD)tbkwiJV}+vWoOuJ7 zglRI47^lT7vn9$ug^sP^aS>J6O8P9QtkTz$f0HLozGu3sL1T)XQ$jv*TKZZcy0*t| zK_TQs!%2>%4P>HGk!Wh`(xKdSBv*e;=wI<HLM+O8x*ADZaoDAs@JgLU%U~(NZ7Voh zd?vBg09Uv;G;aFOrC@GQX2V*X;`YNrM9w<CG-spo${*0I6d?##JI>Yw7-Vd3f_575 z(1=MApsGiLJ4hjLR@<Lyn)~qPf)~mxM}i%(2Q%TGhCFX=Vme|<|DNZ^H7T4k0ZKiD zV8WV9y+9$m#ru|Nd0Fu`F67CaW&ZOZS2$w@pahqU+yz`&5|~`Gsnut+tr2m#mk3f( z_L8W4C_FPSA{+Kj6#nopV(8#=-l930>)szko>7!=Mo)iqa96vMJ&dRf?a3#D;$evQ z{_YY+Q+@rn5PCc^9*jnFAMTfUSH-g22#!1STP2Pao1A(Ln%MXc8bY?jv~j`xipY<b z*X)&Am5z10K)Jk{g;<8vGa#qd^q&>2wT{IOb13X&AJk-5nTR+wl5td2i1=+j94+tN z#ltppQ4jMkmI!9MfaNY_6h(w`qsE!^;@090RmQ!EZH8N8Qs0vKiosb!dcr~y0z;3Y zc?m2$yi;?v#SgG}?w`?N$lDPxJUGnrqzyF6ECSA6i<xS1%e?2d==Go=zQ?V_OGbe? zk|MY5IL#lyLcy%Z;mpF<Mq_?Hiuh?vxZqs&=M!<v5t3y5#<jhNU}M-=-|1I92d>HE zMmXjfI#M|SwM2gyozz_z3C})%JT?s!dVF)l`84z(f|d!j{UQ}Ap@rBDEw3W{Itg{I zNJZsRdQPFi!zloCuI^&>(+Blj{~CtNs_W>xFkZX125*_wJ98t$i=ehjc`5@(yd(2u zT?>W<o7}F=Z%K=7C%M7bgo-=p>>QqvI(U(%#Yz#1J9RBWcyAngI(;j%jXs@elcsgk zjas-ld1lL{O~fH~9q|_tC9}!DV<AXj*}$;&%vsp(7@m<wpC72y;<P7~4{#IxBF7J{ z4wbd;TJ;3V;f^6M6gpW~0?%#E`yl`WOHF6yUb!SF<C2mYhgrry76e7dNq>`;gM=*! z8ip;mpc5sz9uI7RwZ8;>dJ+ele$aWeoXuWdAdG)CWRFuFEcP@LxmdwxSkc?z&}UJ_ z08WXvLj!wjn}~#TCX9NPIc`2z*W@bg%&xvOIewG`y0STb1mq~gp%uS^6(Q2#as80L z|18VSW315517}JcsqYkA`{6di;aW;2wkA=R*}KLiI|h=(ZGMB;EvE)S-hI2->&k0% z9XqG;&yK?V5qPfiI~0EURzMh8%w+%yGtpQbwTJUzWxcJ04&k#-5q-L>x4-B58gbL6 z2xm7dvGamFUVE4Zr@ae^f-=YsOjlm-GtAO}f{z+x7G{VW%aDvWBS9C{t6kOzj6H0^ z8YEmZmqmb$bHtEg+s8(GP#b=%AwIf3^lBpJg*Iv)ludv@gk@!u2{OHFA6|f=Fq7aj zD+OB~lm_FIcUcWY;}m@2*m(lKDEH|8!o1JKb|~q19`#wLQ_GD~ON#)q2!G}Hvt*)$ zd9t^xsn0=5lknsVSWE<mxg_sNRtiaB5W>oU0229mEB7LcH>W7Vgsl%_@8?~uWwUD} z`XxhMRw~@(gYFi7+syt*GUAJxp0gKYG=_J&X?gwDFQyc*lF^iqR$g!<7wKhv-j6q& zzvr-n4l-w3hE0T=>}pxf__W3O<u7E8_)iCJ`{A}GLbHe2Da)ZBeWfj#kuuZY++(N6 z*7-XLTGVj5xk1m42GnY`IV90NiEOyQQ#3i{;nb<sV@+F|k$7HYWj4Ftp78Km$k$|f z5I*5m+h0+cM@l!OkXt<Wb=LvO?MF~B_{j4i_Gy?vnso-KAueS8pg5@~YJTX?5cIzp zGCJp0{uUbi;o!Fk_SEcBbILEWRm^JWaoOikF*2{+`UK81WsXbSNaX43{qNy-K5#f= zX0qxD3k$U-m+?vH(j?{9*?fI=0A8@_Pm!3ZGzJ7P5kR!+E@f>`L&E&t$3^wrU9$^^ zTq~O8NYqYbldSWw*?>enK`TBbRn4&WcxtJ4QS?lHx}AtuYG_I<kZ18O=nvt!eSc2N z{Z`l!V`;gtvbkx#d2*R4+JoKhHaI0P)m6Wjt8Sk3W=(3je3&mBlebci!iRbIr~Dzp ziv$PqrZ^8As*SsVz8~-A(e7wUQuFQJjm7=HaXlVeCWtDV4P*-`{=)fNWTEwZin<hi zHo%Jp6Ls0ADNI~B-M1u$)rwr}V{TCi|5d1&vM&E$NHjR~#Ht*cOy_pdJ&sXfnPv@C zF$t{nYCnGi@NoT!Ts&8yAD)ctZA52xzGYENcV<1K;+sBekleCCI1Z#*U#W_^(rZE= zVP@hZnl~3$-z3CnEur`6PCfRb0=m?cko9_kWPD=&{8o+u@q+)7Zr*IahHiYTATSHB zkCaOY3o<JDN=Y*#OG^sMvS$sGN#2g-8VvQcu<Rny^zqhy3yO4B_|zpCtst<W+J`Xz zOf_uwt}&f}y5$)EiCMK!Qf&vC_S-k<Z6w+zcf(|ZTY+-u^(QO7KrLGnG~UHwL)+32 zB}kgc=X^#=xJy&j>?@`rj4X*rCV_~hukuD?XojV7i&{J2ZIr-*=BAMJ&k0JU9NIq# zkz0mMp78F9fe^?!Lg>!&0Zv9yf1mgsQlc6Q2-;;B1cw%=UqR+R=4DvR@&Cl2mBVKp z^$`k`%+4)*RPDpZ+$`m!LPH4&7pOZJ^plAKLhYLIT;iCK$q`45h2sKPP+o4cvJ{4+ zpZ%hK0QCWZEa(A+(-JPhPI>g+A@NBZ4C1@Z-ovz)*y?$kP0pSY@G|23zIIL@AFT2F zs-71oJ&Y}5MHOWGq@sArAoRIn$v&m}RBSsfUX8-fT)OITeMh~nx83g&vx-Oqcgs|* z0bOZp(4vsA!q{KcO(H5w3TQmzrO>)0VYDJ+$~Uf)iS6H$2*$^fsf}xz&Yd&Y5X0HZ zjHgQtaD};It7$bx3Z?b+Fq}>o!)(VO$Jw!?$W@^;heX|Rh=zOW3}!StFr>yb+lI=g zJcd3Yp$`6a*px@(a0;3x=(&u1`w?jX71o9Wt9FhHFEp(_D{=3x62uA}6M*ayf6r`9 z{auu7q^{SrEDhaj2Rnth^rvap#Bh}zQhGPu7Cg6vIMx20KW7#nSo9ih-fDL||8rD| z?F30se51-f=q|`|T*15_ITLh-woarjY*hr4YRGl)<!)Rj-4Xw%i`cU=jExjfAna_v zc|5FSHj*ViM@>Q{BK8@AEZqf4Nti}!Cu+IxrT8t+nm2+GO*-^<AIqjhiI#b?557n* zJ@-%0r~-nUtMV#aFu8hW&;(oW^mMh1O3WBU@d8F4K(xcHpRY$G9M;n-UmofYA08Dc zqI1WQ<1_Sl>Y=+7-}W$WHpXp&=F_>|8~SXJ;k>(5GYwS}>~9;4YWl$R5|{36(|VO1 zwA-mm_p+urSKUi)o32KYVnVxTZ^R6m7W2CBzih2-%<qZWh2Pe5Hj#Tc#Ip;%+1RW+ z=Yc%98$8f8BEE=0)kbGXjbxc9E8r7t*9(*TeoO{d*62iJlhh||bB28I=nJuMeW^;; zq#0l03B-%y=*3pzrmO6Q=|tNcq<jw1QT|MU_FE=gJd>sCYD18CZgOx?(EU;#>TVzC z00(zo?At;%HQ60Bfd^w)H!PbA>p26=*O9x30bYiwULWM8Z1)w>k0~~hV*-x2hl`^5 zwvGQLmgWW69OCf}RVH|!GS^Kqj3uFc<ZWG6#ABft&v|e~42s$z?ouV-RU7)8MkMYx zk)ZyvEKZqT!b)2Zkun_iFZpNcwvk2FdUmQlG(?H)n&QKja8{1+%eYPnxNlbWaX=K3 zu^0{_o<=vpR_ROLW)B_99T?=ZsT`-dpF<JgP0+#1lxC57;q)%}zzWW1km%uwPC^OW zZ+lSpN0;G<L~w0X_+%nwi`1e@4%r$5v}Ke@rl#N--IlD6s*%ZS%AHFpbHkGT3>*8R z>e>_(uv`W0+l#JF-(pIhARC;Vf_Ng2GxaJ;u7u6$exj3mrNpQ&j8R5-_%w#@_dyFn zvfSFh;%61e<f`@#a+Pdi-3#SZVUPYP0J$VZkns#H&%|E|8MWxm=tsQ9)0u=S%9c@e ztPYtjXcFdvVSd?+(qp-VHuPS`pv)+2@rodag{Q_lLK_4Qm{LglY@7~W<b$>B05sSi z<V=)<o^KaAIU~hevZ&?ii=brF5oF9h<{(vxM8ttr$<h4$(hdl}Dy>`Yhwg!&_DQtF z@0MJfCj_nYMS;n0llhGVkt;VYD^)vdca2fi&Jxmb>Q(!TcrtN+d|{4d!pqNB58zvq zN6-gHE(cK#CVr}E+uMbADdD5Fx1CzLaF1G$h-i^8M~qM+U23HtrBU;fPGThCE3r#% zopji+n%!Bnw33WI6yuFBU6F8W<0iVBzZHiZWi_U8T>yt@>h4K-BC1D$QCEsYhW~<S z7^#?x!~wx{(&rs|%0{;oLx12O4-kWN!~oeP4xh7dPi*GTQ!E8cP?F&wAB3l@Up66s z@)i2Zn|?j1Oc=d?>%%K(pj127tbyQhk7Ay!gYzjdO6Jt%k64wTo!kNfR0(2(dmneO zNT(;<vB;wO;L^y`c8cl}@_1;yK|axk7&0f3Lipjp>B$nIq^p)NRYG&JB=)I$JLR%< zzmjY5$0?7q491IWEL@6lbW(tFH3cm-iZR96WL+7riuoI&%Wvc%f~Rk&UVc2OqyLh0 zt)zq%Ry*TI#p1L$g8ypa{k};(6X(P$bCI95$H>}a^Py)5qYzY!9`U4vuN1P2rcC?$ zlVNL5_VeCzjsC-y)gptp;v=bE95bAGZY=oqD|OdI`#wjEs&x1K_?Vh-aSb&0BW~pF zs_jI6Q42NGbW9u1-kcK!^Cb(GHYHzs2!5ZWm;*f(d>Rf96ldZ=5^gw|n50nHT?n#+ zm;B|@@%4;pV=36ej{7<&-t{k{6hYExI-_M{D1Igphg@gvS5->f7_GdMA|ZD`{{(7& znEZjFK$xuM77w{$+D~*8T*P3WT1s#b5Q4u3&1k}6%e}2$Kk#&_wV}x|e-b-#^-6Fz zYTo<SmDEwy=|lgC7CzTMD&k!lE3~OOss+*2I#mn^n&-svJ~5dDjMaU_qr^Ydmu!n! z+A&qX54ni@XJEOqx_sx-_f2?WA?Mkng&@N<8Qi|j)@i!ClTDX$00lELm`cR)>-I_g zT!2Be5zcJp=#oOI`tRcwDTDphmGbYOy+Sz4xg5n@({V^nWI{v3uHv~MNTwqAD3yoo zXuN)7AcX>t?kRET5$a=B0h5q9xBQG;s!LDHZ2bYy^Icm_ej+o+SP5`$Jv1f%z~3yf zP$(J&Gv_JQaf`vy|1lauI~cJY`u7{0h;ONdWBoh;0Zu|S9*(5HDdOq;z-DAQ83$ua z$3$3P{qZ%b;Tr8TR6eMpX;~)9WQyE7>E&uHhlxf)j?>=2#ILCvT8Y37<l1Mr37rVI z_@yn4WUwPXlC+>Yr(th(MYRWZ!h1J(B(s@f<Cl9J-{L?2?uPuaqm)xN?Y_ehIQ4Mx zTWf{6uK;Uu@DIDmyo!RsTp~I0M$!&!`a_V&f&hhd(aEq|b;k4<;_r{;la=R>bpan5 zN!;*SXL=%wfQf*u8edjrRe}VIxd)(`@`S8pv<^cB3GPr~O5j%vV+_XR*J?o$HB+kn z4Y9}N78Xe-Kgh_5F}hK3)kB?}_`hl5D_2M)#D<DgsnI>g!nVO|fcgZS;a%r)26Q2> z5s+VrrE-t79bfCeEzP8gG@&>rv>9OLf`*wCd+8eHPnwf^d1b6*BBP#@uy{NcJURbR zn?^PGElmeWUbqANIGDFOsRx{weXt5hSaGCZ5!UuYo_#03-SBZvVyOHi@C7fKc={u! zy4obhWSV$($=o?lSk|VBEosrdiomxzXx0$?t32;oPxD`smBja5{XM|GkytzG7HB+i zI+_xONpRW*Wd-t^I!(3t7vo7RQW9G!Ly6#|(XcAj8qJ;<kOcQ)-K6Xlj08#iub$3j zl}F_W)ILfd5n-H0os1zcLZ0rE3e6Se<Q}!5^t4#VmQfGUOskDMu$W%MH4FLpWcGOT zdIjl60tYD5ot9y>fwg=fURXgNm3T~Jf)b?{AxFghlwu)YxhxEJiZS)NI7FL&!Il2W z_|u~DS1!2t%?WR4WaN05$M-KE7P>R_b}bE5?Q~_J7SKG$*`2s}@rt`P6VF%tDnv(# zFb5Oy28(nbPf?AV@MPu!z;Cr6<IO3`ieDQoI+TsfF{46Bk)vhS{VUVQHnh&@8j8g^ zB%~&D5M57{2#+zBf>lx{K#EY5&jGQ`6&(#r#JWGyDOXM1CKL7XH!)0WSWHc&>o0D5 zS0bJEzjr@awn>pb_vpmH0}$;w3^y;<TU^GNY8FUo=I;v007B}#PM}4|Z6vaRvg;q- z++8Ni5)~e67*<%RU~2>zi#CF!#oTN1wYo5-P<ydo(lQVjA3x}Jgj|NYOhQgrd^1$P zo~r4el0Gl`-m0A(<eWfu|0b0(OB6+YJ{3u65AGb65GoYoawf+Jg!ljPx0yAh+o3(> zBKPi8elw+db`nlW#MhUR`Gybz1|<Mx8$ulF3uq;YrUx@-LUCGU$Z>~kx)*uH6Wzad z<Mmd>+4w^?sTHI3F<j-og*3=S(g{B%lf~B!cef2{ppo9DDr=;rrR5otbm`eRdy9p8 zosATx;qGuzl=<PQ$1yXKG9}qgytjA=#ME27vCUOhSS*$79M+GgX4-qtH=XB_u*~L& zG2Sr8ASc~6>OWV(vrBcNKzGJ*RG`C3rwb)b3H<RkIDl3NKp(()zC{?$6z%7c=mUn> zG2>8)%R{9^uPtgBJe49tAcmer5+`{{ckMtKLJJ}L`+>$>9w!FziW(a1tEOp!jk`8- ziUe|c5+g``wWAGqkR+FCJMleG!nIX)1Exf!WgJwMv=+^n(5_Xq)Sv@`bj(;%W)Gzc z@2ZB@YYM(l#Z<}C#p@me^!LN74(|KfT%uUcU|}+(B_v$!tp1Ij*ivQ!BtjAZ7^_ZW zOr<@(=633BJO%nWl+>z3PW^{!OSd>f(E@ozDI;uR>SxQS=K;IGAvIp9NAeyXR&TQA zszK87!&H|)M~H~41*VL%r0>+ZHg4H8u5s|WOK6Tf0x0}ee<|?ixzaq?qNg0;gBD_S zA(=kCH%5uabf_=}GKd!2$Hm|v=pM*BBGu$WN8UeUKFk(Gu)XRKFBbyA5bdb9su7m6 z&HoE9K+nHtmRW0-n>^F2HS2=1!7d-&=XPeK!D&joa2^FQ1^fOmsnrrI8pg#BK<b(D zT$M}$QWt==45C=%65<(v7ZFRHKym`OieO31!r0)t#1lWwb~iN*H-XHDmj)OIhcy<j zitj$q=rvQoJR+bsCr?iiR|B*jYG%!<vGZkadZv$}td2bJa+6@r-@Zu&a%ZR66jDPK z<_Oe@)5f*3*%_;%h+t8p$w%SPGZrp4P~-iaxMvq8)VwcyAl>6(W`PW8j-?^%>Y%1# zJ?EQ-4xVGt)JO^*IJ8ZpC%76145J*l%rM_c)PW==CPc^U<o?_+jE$xY!&JnwIx_w- z1=lqrE+Y|x&rjFJQ#9xK8zun&s(bh$K>nFSlp1Zig~W&`_FpnF1Xi-ZmVYk(M)eBG z?*xE7f!3hW&5<C3B?>p7p?Q*68}WEei<w?yL6dSX-byG(0{qysEnGOj{2mH)B_t`c z(g6ynFFY(!9DwNv_Wo=ER74EUFZ;3B_S$NyUA0H|!#12+ZRT__<|t~)VSSAiONqch zfT1&p9*r#X!`31Pw!;3{7YqsbZG{G<{IUi_$`>h55*V?c8|1V$59nxh+M6$Er*@mi zJXApP#GbfKPF`P$tQWePqVvkuTI#?in8t{3n!IC%v?}j4r2w!9kASC#R=ij+*9OHG z#-mmxq*0CxB=RJDD0w~`DJD0d)6Y1526{m8RLF~s$q&f?Eg3~%@3_}Mp{;>m*~d5x zoZNOGoqV<cmY2w1o?^AyA@~XewYA%=q>K!^*FDEN9}TgK*FJ@=_DSdb4rO|99j7}i zg2nv#36Zvh+*I&0=IS9z8w?l?ItCn>+5A{|YTrTa@BDjBwGKeFmbB<n#mL$H*O_Nt z+qkX(ezV#P%RZGmcDqcMVkI;$hv2STuFEFpD`BUPIi*{3;=6*3Bp53zX9$XRFp!O< z>{yd@O+>t25QCl;N0D7+GD{+rcr@YAL>3O#8Ao8#IgKqSs++?_8G5&SD8{oeu=_d^ zPQH8nD;}21YI&})RXV>w;%I=w<S*z153e0xPiRyiUEKLjc07Ih$P15vX_PHYsc%p_ z-d@)Q!VaBiC}3p%8ZzF@MzAK&Bn5E1?9rb_U0h%4h-y*#wRelq$V=EhKtnAe6IK_? zJ@YH5<{;IeRN8q(J6lQoeaF06RBNaj<5X*v>YD<|FyXHY^?LKFo-x=#7y?7wKIv3- z^qm1Qe@X)2nhgT%=@9hxADhYWm^{Tc@-FZ!qeoY1fk_A4>jqT()5WL8QpDkH*#t3V z^q6CIQ=9(-bT*R}(w0_YQ)=so&l84Kl+Z5n_IM4D?fNXDU3A8N-eIYMzQd4^ov#`b z=OMNrM+ovoct55A6Xn^vCn>bwjWsr@<T27o)~lfWkUwXIgY_MN${^8OKWO+B4mB)A ztbR-T0;##fK$H*MzYXhQj>k4zjGJVJ*ReuHoK9v2Q2k`mb`A}H-Rl?HqUD-6VE}d{ zKiY)If#boCCP?xG(~-F)BEZ^#M6w8VRAdwTF}}APoU|_`X>tS2)FX#}h+&5MjMjD_ zNb#H_>vxTmnK@S6zz3gUX{Kpb!u(?ki2ZQLB(z3*C~FZY%k+?>R6`9}a17CzKq3IY z6og`t1{o-1@G2<taLz%UTB@sx<U7v%edQ=616LUn0IB-!Gx)+?gzl5A<35Wd3IzNS zO4CuJhmJERZs|%ZAil{qp$hEP^S@CdQwyL{!CqE3pOM*yw16VrD4FmJ%yn`7cK|RW z*j9j*J?hk&FUFV=;AF{ps`*Duq&|Tfh8U@TB-B=2vVl<7ogV2nIS2t2$^ezfseoc` ziQ>?dYR}K$O(bYXbAjQ}KI5~Pqd(1cX102Xv!a@YQ0^N~#8EJ8PR60Z&V|tu8sG~O zUg01sgSE;D<dwvxgg*4}P|zlx`$94)IHRS3)%q8>Q>mer!Ua2@c@G^BO&6vD@JGmi z&U46(LZ0n^<Vd!oLNl8zOn0^WwsBnJmu3&B9q};jl}3QMEpx4xz)=U*K?*2G64oxy zh$&P#Uwd7Pcb|z9!W|6|PzO7=j-L)H5hPH-y{Z?7{@ak5Kn(`b59P=~as+Wb9{Fm_ z<Ss%J)@chAzMp6*pq1)l)Aj!RQibc{FIDwvj~CayZqHy~y>Cm*K{l&cM()za{B2i_ zza!H;u&@;2AN1^9oaU4d1gFo9wWGCeFu5eYJeffpbny^_WC#XJ0Az(?c(*5u!ww*2 z>4*TRoV`h4lCeIr_;@H>rQhFv7}IeGP#9+H$ufm90V#rx)8afQ7Sk}Jj=ZAuQdNny zrWg}qxG6*Hz%)puO@?vnTI;SMggHx7pQ*lXs<J}<7%Sm;4wO9U%wcD!HYO4bAM0fq z^y^alAxLrm1o4A;3i(j@M!~MzUBbyEQ?`=TH4huCgJ--y0SnhrbGswt{o_mWZa}my zNqemXiw9|6R^)9o8ye9Hgi%^w_0|`Lx}a%SqYnB12Ah14cvfEyjGAha9u4myW*Ws8 zro(_~|J$`jewf1mKl+|-aZmZY_cu&2$SX1S4<NuCzAaS(euD1-E@u!towQu-Hf1zb z^wL~pNap}XF6;;Nj9Ko?dnTxk9j;a$6K*DM{}!>2EJt0_EYo7q10Uj)2(Y7Mn$zM0 z2;K!2GTt_#I{tVG*R7UlY{@JXLCXhHjyR5jquHnq%~}aRseT#fK(n8n7gEsrC|t9Y zeQwgw{od@g)ecMG4f=c`u!$W98mz;RR17*_1`sMe<nplt<pF?FUJWesS{qn66xQ9! zg<H`Q^P16-1AojSSw>6pt1v<Qu|7zT;3m4GqINGb@<y)_sgH!iD~39-^s~Su4+3J; zfC%V;LQ)<HcsAds6jKB7s<x)Ut1>uof<`<Fy+=$>Rq6V{GN8pd>>HUc#MOtPD5%F% zRl!K!W7Fk2A||J}`DHS*>7KUI?Vov+c2P`yJ4_5MQ4$6eKwPqOdm<XZJO-4g0ob5C z$RD+o%hCAo?mjZ%bi+OL01i<GMo3~f=By-h;))4}@Mn6?dO^8@<tb_gPgE3+1QD>n zV5adY8IlxSSb6$&EFypH8%8qJNf`X8ODmSwVUgNf07D@1u`==`G1{lR)nCn*?Uaze z8ERJpU?O{DDgeEP3u+nP(dnk&8#Nh(@(X06EOCgvgMvge;pb%p$82x+-$;n}lc5hp zpG$z+hc#3mp?-|6fOKsTDN`FHP^?NB*PUqO*%1{BycWECs%9*x09AB^as<do{)J9h zKiV;jIxv7H*d$PK8t9$2C~{i@3GOqgT}`BkF<(I(Oj9UPhxSNelQ>8SPBrK=W2-Zg zeLhUvw{SegHUv^P*pRj|RI9YJEHbq?Ik3&E3*mcMp;4|kJ_Bkh?XXo*kz9jEw%|O> zAdP*cBGgJ0uz2SQmQ0E}jenNSVxtW1dv@lN9q4kNGh`W~&}NT9s@F#3veFQcWS1y` zA_lDmAZ+3-4aow?Kq??1S3;p;E5vHNBm@9?+>D8%mIOHPL?$WL5dLlAqP=Q83Q;yu z<mCb=(gHG=>S{b-J<hC$sO@$?L(^1b_y|n-Lo|~aZ|XjH(M)H<XvShi5CMtpQy58D z+-D}hG$|TjSs`W>7yI6|9OiA4X@erlLErB|?E4i*3?#}l>`N$<Fdz?;#EV)H*R`IQ zv5#U8g*O^^5U)3_|1waO;qg-5Bq8EytetnJ+{Yj{pTR{-vUe(!nz@Z)oC5h930fwK zV*rgF#6^)doQ;^~yJO;$Xy5v<1w?e<X59ow2L~sxYBggT5rff6Z?Ks+Dm*RD%&5@< zX@wyN&oleAvSR&#mLg%Q06?`!Po6)_uMh(Z5x-AF*j>&p8gV=Pvqr?ED=fjrWz>1E z6FUJJmx8-a{V8)|W_~tK!M1E{FWA%5<EZteZjGASz$kpUk_;rGvhm?v0W*U3NCYPg z*#}5VB%33nMt%T1>M5f8uw@Dd8EY07aYO(d)}rCQOWY65heABPXqQErYW-2fDnrkO ztE2rPTq!g!0x0Atth5e&kuT<(yv#_BF(!)`^SNmJ#{k`<*_prG*ZZNUVx-d-uMkDp zqEKQI!9SFjt0+Qtg)D(CiD&TKLOfrp4g}VXzzU~20OcdVBM3yKcE_5dW@g&?l+>7{ zIv^^qF0z7I(G0j-EA8yVXg&h}`xcAvUJz~!1AmeAS2x5(3a!zyC&<5RnWQK-hqOd_ zc&(bTi8g`G!B9S3vE>@j!HHKS)Cp5?@`OBIP{t;Eh`m;7d7&DDdR06-zI@Q&Zv-Q6 z{oV+P!PH+yFCt{2@6g%lc(b9)+5om{bif=Jxh)rOjZS!2`BEG>Gcw_ZNM5K%vaD<s zUu4$PMi^tzO^jRghQo?1r3D2xKt=p{dKA+r<}h_dh&7EqX-KJA$pb-ZlS!g<4m;CA zBD}t%XI0z&KaN(p4co453g~SPI_5p`I<UMqUXlX5PG_w1_<Pfle`R1D7+vRLdRKg% zEQ~7frk<nU3#f*DGryf>(tF!1aj%Rtq_uY^j?pqW2L}L|!!!mNkhB4gzT$Kjv@yA= zJwzG=JTL{22aiBJS5s73{;d*vfJdsGM)K*(8akWp3Y}5?>v&b<P*}umx*S<0A<#Q( zXRm3dADhW@Byik`=YvzIcZd&%*&R^gPZ8*wA|6nR1oNRLpx46Y_(T?jL263lmPpCX z8k@f$aPcl|*8EQ3_zICZnyEeiyUL{?w;%e>&zt{&0_g|ruU3^hPfd@fw*3_Ufn<pE zT!~R6q|)g4L{vaaJg8ony<)Pdf{m5w(nN{7_{8|Glg5s>MaL&{H+@!#6amQ70ET-< zu|Ypz1`Fs?6q8c@vmF*bieE)i2%3jEB6eIxnYLdXs1Ypzl<5;IWn&Y#J>jBb*0aw# zs58CR#-X+&j1K(EE-YHLf{8VZe`mqWH?1F!a9p_HrTLM<2Dz}*r<U1lQ{1*L1ri-H zbf5*r5ws{PB)Z~Ir=P(H(Pca`6egr+Ljq+Fo)Mxf=yt|44ESg9eR*y$U+1EpP!y<N z6se070AO0)5l-BM&SB3p_R|ZIwFV4A?AIwWC;6BZS~+L>q39~1`Q$QRL-C%0vP5VD zRJBqG!^prX8%vOQ8Rl>)Y*PKEMEU0X1_6a1L<0{AEQ-YAIDy89oQcuUb}=VR@rBu8 zxS^a4jNSU>db0Cx46A4zlb0|pv~5w4(c?Y5GGSaDXCX!{au9dzE*%e(k-{o;TUrAT z?EJxOx1|o@G_ipNNf%>syK^T4yFdxqVnuN^N4mazcURzTMGoA%!Qlgre8$qF+&32E zmkbg_VtL~+4@!v(%fsYHoQpl|MfFJc(u-m!lnD4mQvMeM{-EE5VUY#LUo|A1)_fqy z4e46XLQ%odYP%q#{E9P%MIfveEH?7bM{63%dxtUDP6Pti6c6&Ic?%n#Vdik-WhiVY zI1v_rMF!~t6aU1NDHo8)**-``MT3o*Cj=*f;-8UE;caqdzezL2pO{6hFHn3kOji;( z4EIkc;b@F){zhYj<jBSvP2r0k!{+^gs@ibt2SH#K577e#L{MGcDQ?f+&(D?PqQ55r znd{xO5KN%<0Rz%}SbB0eD4idDN_xUWX!h<E5c?|&gDj*ME01Dv2`C5*Es@G&L!kxz z13N3GEO7|=sPOzfFxLB;b&03RR5J|QqlgD_?`&-Pn_>uyu&-O=+d7{`fV5Vs^gS}r zSlnz8Ufy^}Z1`vtnigWm!4?Xime#mJM~<5aKp>h-1zL~HA9X?et-KMkR!ZBBSEup} z<0}P0xUD5UK^yKajIh)6%pnU3$6^cnUjs^(WJkRmGGqQn|94Rz9JC3vPHbpaH}2+m z;UNGc>@|w<H<To)8k};xRZ-QP7XgTP0o35wU;q)iU!`9H9wEW@MmDLzY<tM{7MRK5 zbWD580ntw5SZwa#<duwY-l8Id=5;o8f=E)+AVKLT(5RY#&nD29T@VKT2ZtTo$>GTc zn*CC)q?r!38f)2vsgP0}p({#+tte3(dAODUxSkY_Xp6WM(ycQ<rjAING+3hm1(A!I zBB~B3sgwh8wO7=@*my(}7-1=lBN;`Pv2~!3<eaqDcZDJI7ljSVh#d$*?}WO6jz13X z4&lLJ)8=a$v9rU_T-XGl3Wr2K(s3w99P`Oox{i=^vGX9+=J(J8^KB~OotPX9>lk>? zi90?Q2y`8f__Bj69I2m_C6sx+$`Ci73zahi4QQ#<F?D=VpYD{AZYW1B72nl2AtiL4 zItM=ApacS%E*g(@1dF5S>f7PvCCC--9`@nmIR8rm3^al&0+?ciPZVSfYtY_kBWwX) zp6!T*Elqhf2}~d$8UgO(P0b9H5-m$5i?4DAMEqWaKU51A8=pheK>-U2!brk25D-jZ zlt!DGCN4@pZHe4wRFY$vCjp@%m`2U*lR~5YgMq$kDT+Gx%+D)Pl*Kww`z8%2&`4$& z;gM`8E+{mJ79N7i?emDeL75VTddW}~l79wxVj=@)O1g*oiONH*B7l$$y;QYF{U(f> zbN(Gh22oA$&m}bHx+8Rjz-V4F>1U-sch#wX4$9!Kzf5y?qR6C`%nZ>}i}kNDb=8MW z&@a*la2TgL*_*dnu}`!`tjs3A4frq7=1b0>#>CJTQ;TuLj;|$=Zs#f^#Eso-jzS$n z_#5!N4U<;jYQLfw*}|AGJSzorKs?F-nS@Mo2Cgtjfd;|)WyyXl#t9AVro(Ji)cy#C zI*Tm3cyJh71DShm3fl-!FhCYgK3#Ij0GMny<3MrthIShbB%$A#=jA#HrY>sg)ScIG z>%2(!sh#7(gR&Kv>OZ1q8Sy~2k{-pOw?&-2w*&!cc>&HmLJI@LA&hvKQ3rw;t$`5v zDM*QOIQTChL~kTeu@e*oe=}fE4M$fJA?WR$j+b2PnAyXL(~V<Y2nJZN!AHAlvK&r( zu_F);h`tsK$5_xkBwusB`6zMNR-iTj1S2O@h`nF~fV$RO+zTa3aV!gQKf~k#uVQ5_ zD#GIpFzKd4GlLwt<IKH3rr@*{pclC|;IpMWQzgPCq&6xx6u@GR{vM(LTP`d(*jqT= zzAn!Wy$LTFinat|n5;n2*(s7y3N&-bApn0+s56KF7K{%`ZD^3M7?1~|E|=y4oB?yE z>fi`fRoplMeQJ8|Z48UpB~H_8y!d!9pe^6HHD1aUz1_pVYE?jJ+3wcV<JT0e|IDDd z1s*!lHXhzUGiIdCpRQ3b;P2#q(SR?=;`{S5YqdZCnRJ8L$G~^d{fsc2Ke!qlobmp6 zG#BO^hyHZnRL2s&io7rA%b$rh2*Dk%GxrsaZ%#QQ{|(@dAwLWYpBAF>#7-iw5}o<8 z&AS4Hqy}IF1q{@n(RIvtR6r~&ga8N*@PIlq++i^l|0TDP=;Hq&#3{UyzJ1OVA?6n0 z4QlwkniuXNq0ABZ=3(Ppe^{zWhR61~>Ga27j`Gh254B8-5?STtj!x0X&@q<+fDe)I zaFC3whx5$L`U8{1!ImV2V7Ukv0HLU&fWmrCtO=<Y13_4Tz{Nlz8grpwg`LZbZKgXQ zRLR88<_S1Nkh9M;+)YyVeRhP5k?5@PO;79u=m!VswCz$la{8ZM_sn>I2{4MEXZUW% z>9&DLp7LW-HLm7|q{-=nhk~AF6Uzu9Nc$}fQ7bZ)bmUmWU$Hcst&8(uYZeln08gBQ zNRYG0F+E}(L%f@lr$~e7laWe?ngZ6Ds&l|Oe4)ol>_v$V8oJi=6}sJ`EHD946S7pG zs{9ZZr*dt~6UahCj`Op3_JB<my%3e=5W8;RG!QOjMawkUri@7jE2r0^57QJlsG)jb zVM~o6ktNDh9ph@jL8%Qy4JghnhOl7-if~WiSwWQ0WdKVm)nVAwBxp+NXgwaF%b_pN zW9Vdz0Lf#MfO0ypi%XWNf+y_bo|jYeU)nbj_0Aqy?+RpyVUI8Zm~WFn7$ipo1Ysc^ z^GtSKIjE_q4)u9!T&J8E?{esUt((l6jt%<gLHtva_udQ3(hu-P#J}l_QTb@s+=z}= z6Dk}^SlI8<wk%(7b0bL23sHdK=1A87`m54jp!UUssUU{9T?6H{HDd)aze1_YGpR|* z8)DMTBOysOi|iGI07^PpX@;*yOEZQFpiy<K8jeT^h2U|+JU61T6b~8uhVx(X1B6W- z?2R*0H9?uG)y&LKgH#8UD(v1~s3;9ol+k?b`Z1mx@B}nep-)-de$rB%zMGd^53QD% z*+u!xO?oDn0)Fgu$UjKvo9~lpSBIF96gd1U<%BRn&5afvC9Kl(%S-Kv+U>wW-Q3Bx z|2mRHEuG2CBLVydoBRbJs&_OEv%Wc{5qVaKF18Lc)8n72VHMq4pd}P_Ao+qt<scBM z+s7p*WFwO4%YJpvV`gb&t{*_>Qk-mH7em4XOK1+uveEcxLlJ9YyE+iI{!6(Zpc#W~ z%a(LBj{H92-)(`>k@G)^M(jDoLS`@#rbmtnbE)AMo)UTE9rs6T`Fo>R8Tt4bv<Yuq z1&In{RL2}tG=v9z2hX@i0b=Y@2urs8l=lt7)J}we0wgf~`wQt3tHjy7@&aNcTT4U9 zzYED`oryILzHiwo_1N%aeTu3}Amh`Ivh-Xa=fxv>x`{1(3U}|7q1)xk?AJ;`EsNSj zoot2O!X5_KVP^7>_5!!0H|+N7rH!CY!%5`+ELrOV^?*o~@zJcQuwG06Z&tI-HhTsc z{HWxvNl%VcCoL?if#}y70(3J$`vO8uHU5v75-j7>4w`m>&<7C{nO$X@v(ftV+<guJ z60%aUZ43b5m0v1i(R0QOnk#ke_LW}}w}2TwvIP4oF*+V)WH|@C_P|M49?X=%OC)T{ z60o##5Z40`6X2K4wwhj51aZ}b&01jn!0gH{I=J@OT}^|nunN$KRtN&LB0O~`O@^4| zo|$p9{8U@q*35y=D0NanZ}1<!<5MU>O*RF)vL#5k^C_^Q%7jjvhR_`)>;Vm+FN|}p z)gymTb9zD5+%icdKC_YHs{l#h9$}Xif)Na9*4p^K@+qRX%9X%h#k+0}fpO6S!m_)2 zx#?$Kec=qO+g5YPdDNb+U4OQ6C0grZf2?JpM}Vk?5ugl9v4p9Tq<A-h<?!&(!>U(R zwehj_SZigl-5|e(BU4I7ot2wHR*M82NJvq#Hemw_Xa!TNSl3#@p-SQx!!Bh?;U2=7 z@7dSC57Ir9kjC3}RhAS{@d#5;1lAS-%N7?X#!ObJ0Q*{#tTKA}X@K(n=oZ40Z8w8j z-H`WFqR5_0%?P&?uV7fD7Ec!bHO2o|x_Vq&66q%du~yNeGg0!a>Cm6Um`808R+Vy0 zFcc69fue?5SA_LF0IxD)W+9-i;G^-Xx(;_@LU#@?kqaCzaFYoyp+cfr&4F^A(ku%? z6b?(lBjCjpw!f^kq;XMRRB{s&WiuQZ@C8d=aq;rB*j0$LOJL}5oV3T`iqZx-PFA*P zxGk`xy)Z(el4?S)0Ki~l*Ubb&k>#cW)6$Ia&5IF?khaEE(;Y?*!LU^}UtLKUw4t{* zc+q~-)bHIzLx@az>jYuL!j~kJaFKFvUR#Ptw#H8#MwEttL32Z4mJ-=K$}Y6L{*L7k zErl;};dP94!}>%8k|o{K%71cf!xyuL{1}bwW}&^qar3-BZKY%;;+f`ci;jQ$4CR^l z)Ya4}O@PFoWsHJW0C{#(t!RP_t`>p?-61{8QJO*~IGFe&CZ%I2zxRnz7+UWuaody- ze6`-on7{<}gW(jCawHQDlY<TX(0alng*D1=tXz?QPqZCWcBXrJ;L9TP{=8zUPP*}X zjCYWSVX$v7>K0-p<`#B58DL+Yl5)ZFcFHK=g5%Ihx58Q$b(o&9%6mCUc^N6v-aAsc ze7TH23DIau<v2IME&=*2C>58oINcMYJz$zY9a#lDJxq(}hYYA@{%ZE*XTH3u+jmi# z*(?MSVWH2l(OGhB7(Znaj)rjuOi=dh)PIZ^c9TOu0Qv^LFaWl;!T@^PSg={7;ipP- zuK66IeGU`|=NLR{fJD)xb|)=a$8Q!APZ)r&Pl{eK&4c3FoiAJ}IC^goa(@a&XJ$y* zBU3yIMiVK^+^WzU*d{~CS!Q>^d|;i%U>&AFX#fjR(mdSox5_4DWD2m!X!?Ik<U^ZT z@z)~hZeIE;qN59ggVy!xehxa8AfYoX6kMBV*(P;}uM+V|#oSp?qY*Y=>dWbo5U6=| zVPgD^i0w!^S(2L$NHLC>Y%%^q&e@Fk)Muh17!6Urj6@{4C=bT4U_BON11L58s4?PX zF>gdjJ+lvaLS<2FIbxZE+8HVvQCQu*xjBX<Y=wxp!|Ql#$tO=*rK@Tw3~&ad5+Lg0 zLsjJhHb8j#P>z&tUJk*c!DIxB28dyFa)SVJTL3D*E5qWqDE7Z`i`Zd*P#PzBqVkyZ z5q%lpV%R|9YCX->J21*3l(8x(<>|n|+n(5AL8=bd1Ry}5wzdQOPW?S;wSfddz=AO+ z!7U^Bjn3$aR_-W+pLpTYsJ*&TzW2{|A>&*in$F9@WI@OArgp_)KHSg<WnT~>33^s( z5~`f2W7b3(+uN`9F+<@5e(Z;3i8qzYNWT|_tjG`ta71e>%F+7AVNV<6Y1<Q-jPo?m zb}x*CN)F@06m~}n8cq=F-_>}AA&v=Qvs%_gNXx=;*d6MyF0m?T?Un#o31OYwfPZID zZzNh_l4ob41SEtA6oCx7@U6ZIRZ^n0mlJ+8srg`Hxk>aaN5?3Sa|R2;Fj)4moM}UZ zEINtcya{S%&jwoJHO-jj#smn)wjD|WBYNOQlC58nohb2jW;kgbrh(W-)7%G?UyuRK zq#$@)8N|iVL4v!PW4=H@SyOn2@C5{mEGbK_y07%OMkOEMw_}S1z9K~+0eY|#i8L&r z`O$RIAgy_)#!?I{oEbyMwk#>y%Ly`D_c7-lEIxv6s@cGjum~#fakjfVOI#U6$FnS# z9LblHni{IC@p|&viO{*&-8yhv3?c^*I5y;d!(m?ftBs~fM6gn*^zmpW!m?BIcZ98y zTqmBGxINDRj1|tUYb{rhbEx^-$3jOeD1p&73z1b@8nXhKR@@6Nk?lHQ;uBp!ZM%lR zX)|>lLL}?SKA$WH=y@juIcC&!NIHkhOSXnQF*6fAANb7#OM0<M0D`<OU2oucMTL5B zV0Ju`0sl*U=nlmqq8@wzaIL__#Qlg(`;t2ygjO02$AxAsr<j=%E~X8dY%!{(82{Q~ z4KEN5hy}i$3{#z>K-N#muPPZKP~#BHNVp!*5$Nou5LQxB$Zth)w9_gP8MVrYqkOc0 zkHJ$*X%k9xA2m3onQgoigKInz1YaP>Q0Z%VmU+=VfXd_X^0KA0ut4QcWJ^5hJ`6ua zuCpX!n_L+Hpv)nsrl<;kD+}s7la&>tnX#9|>Eg-?JD66St-s=I(J>+j%4L(%SpzF; zS>fk{L`;%*6VF<q?3HDeP1|@VB>rQ3Ob9LtAU*f7iP)Dxg*8$LpW0nngO&4DGN6Ga zz4D*cG5Y9&*aaW$)`_wl00W@7hzU=vjJ^jKrN|OdB_=|R$)IErcOzU3PXGzP91Hvi z1Hl^^bMsoP8b8*4*}h*`t?5K5o9(L2m_g(;hR6-;>4-nw1Y$essv5)r@mv=#!+mVN zy369O0e5E`5Do^y)Vq4weGDxy==KBE3$&<Yp63c59DRxoD26;sJn~2E!CdK+WJxH} z;>*InScmzgD^d?bg~3>CN7J|hGT#TVq6_H>LXckc$bjRTuVCLUusB6cyzAmf)Ai!_ z#NL7-QejN*Es8S0`o8uSvn&U&yki<KVe)*_ZyPPP&rDUkA~0+qbbk3+YQ)OOs&Pgb zB|-<qwL(hZAkxi$5Ci*}UKxKxxuc4;wMJojgSph`-2gR!beG5se_MBB4_ENOAxOUG z5}Z{&8H(S|AqkxEQ7&xm!{@8%t~w9iru>0>-hGK8%rLOTKyd0wIP}F1=VeljySB4p zAC4tj&8X^{G3FU9TSGOf;e}0Tv1%pb3~bca5GaMH!j^hyKw<k(fC3GyrK4hW6mftC zy-k&)C09_HM_yvK-Q9bzFjfnD3thozZ3b>v2<jxUK0h)j7*Wa%LW*^v|2=>Kkoa#D z;0KmE9^Cr~I>STVp^-DAxC0TX-;T}}5|Tj*&`S6NN=L#tauE?ESk}Y5B?#=6kBD_1 z?hI+lp^#}^Q@oV0SQ}71VqQ0ZWKiZx2cPjU$b?FL&64ep_D%dLZb(=#sQzpHc3_4q zOhFO*A~K*YaSpn7Q^k2$pduQ{R0s?AbcoR~WCYX27hsSq3kKuCmN9KIkwi;E^UrCo z6naP;$%&f&33H(+k6xX;W_o;%+j1sjpg`HqnUg@1&UA@RUDky%TBv-aSXR#SThC9Z zqE0FlL_fE&{ra&uWBs~jX6h&ozJ<s9hzgPfrB~?SmC_Pw7Y5H++C~7*WCYpjf<<=F z3o$mlx8tBMT@VF>OS-)u3kQ#;1c@bDs8CKdCQ!N)GOMNgPylAM5tB^Tg+x(7axuJy z94GC-zN&g^t1IzBVrkMB9GRjbPOmR0msE+i@AmGVDVox*h+UJysK8Q6=M6dl39=$S zs98&3*h(IP@Y3j|uAJ-d52&RW5E-^N#YWVn{i{27&cWY1_5isF1~i1p&!Ps62gUYd zyxX*Z73$wL|Fz8)_&gFPC#22_m*i9$rLK1YI6@mD*C{G-FlpZYw;i0twe}~AGSfQw z!C0U7L)gp|46XKQ2ep-=RAnwz&dX%Kk=HGRLSn&OW)TMJsy_rj{=1K*&{WXgo*Gc2 zn_nd;t5X*425l}ot30tixWqiA1b!O>c$yy8v)-dFG&L_|65kx4v;YrKVbDI5MHG^R z3el>MOrP7Pj_VrxAhHnyw9!6MCYp9Y1WKWQNh1Zq!Na3sjangyjt@GKro}*W!(I9< zGoj<@=PAKtkg`gB0Ul92Sa+2KJcXg)VL`sCP+QUac}1(GXjdOh0|Rh6EcQPvaEBBi z96an|jEZcYCz24@lz{N2E9Mw#5P;LjI&F=`q~&C7<<)zftjMP@-ieh?ELQcxyhY}# znQ;OSr;t7=q*m{7x~Y88brlsasSa|N%ZuqZnvZIfWvI|-gru{fY0`zn1&Uy9_%Flv zaahF3-!VeC_alhq|Hd7K$NqU#`$(ja5uK6goYrYc9T*cpY^LA_d#(g-s}_hO33!{W zu<;{BC^|VSP^6c|Mx%YvyHsRkzATp8cR(dvA_PUU;>Z~!pgDpzIf!)KvnNFQg2ht9 zM5x*Ff<Q-d$?uq*jiNvYi6qyyBs)Pd$-uRx@;!xpXS>z4G3I?7qoSRr`TivVfRJHd zoJFkEZXfR_Xa$IP;eqzNtvG}ta$SJG&5q4E9gjFE`b*4zE`c%F9HiNZg=JB9(&1{0 zWyr5e$4?g5fi3p+E_BhcYfTh#xGL@-T5T6GH2&F@G&x9)s}12;tzbIaBnvJ$ICaP& ze^nu_1xDfs08>W02FLy635_!IVp<Haql|tfLJVjC`F<+4mEgRhMI>;=mhx=QG(k_I zyz44f$^wBYtxB;?Q+L5tvdZh$lFC%@zB?seOIsPAd)7I%!%cw$0D5N!$csEp_%82T z7%1q7K9@w$*S3fTfD8*O_c9H!4uLR$?~8yH_N?EHi{OZ9Y6u7tNkB8xFye@Hy(f;E zy1z0c!an5ClOL9O*+xdH(g?FVCq4%2v4P>XWh({1DkWn~aTXvyP$$oZ`H1u^3@5_j z^`+Zb)|k^Jk!jyz6cunPNEhJ+e^=0dy~U?z$w;8q^|o69JE4ZgJ?kzX4v3@%!{UG6 zu8jx)Li+`<$4Jr70=lW!pVL;v42Vv@+hYx8p4PZTGK!^yK|7RV37)0~2@DJZdm(_Y zWJlV3VBKqk^aw#!Y6ZVl`Rw8zfFUKIMW*0MAmsXzCsH;$_L7IkIfemz5C8}r{r$5D zd{=>IW55BM`8323BGh@z_Wg;tF$51pm=?>I1e?->(hQ|5Q~@HSp6wiM@<L;bbu3qa ziRwv0ywVIGpsj6bDmwiwG_xaiMX8}qBZV3p7JuDi!^1h*#wBOwH{!$kEnmf<^@hhE zZuLiNvI*HrRFJLD$7^U*Fe#Xz6-*_Vw)=1m6rOS=F{MY6$e0d>!z_77*y4n>&`>+j z06x<cIH0v-4LX0rTOt5!29Z;7PNv?3tcic#=LI7DVMfr9{*<Sgu9c-RF~s=wp@^yf z1`l~{&$7e0sZhOeAI;gZ{<NJTpt=iY6{|FlC%`g|bzH04J+}LUv>sW@8mRfTozfzz zZ2VlioyxFOLUDBtNoW9stu=ZI4!wsq5=5lHqz<%jQa%WSQ`Dh2B7$2V*<%y{Bqxpr zSK58v<t3{%E6YGv#;`zcikbMPR-r$c8qCdcxHGb+3L~`Jq(MkOC5gM%xo%SwI-QF> zG`SZEQ=|FhA?yJWAsF#gP|xxo3%&nV;a#u9ktlmGOm__!Pz{@VFc|zlsp0ySPu9M? zeaA(C1_wjnsTOhtF-JbpXI+W;8kXGymUz#ppCbUharZ^hLiJ|XU6AwdX=E@`DCkYi z3=}IaC6LkaY~Mqf;N}WLQnyNY<~v!EXk*v|JTf7ph3gU?8Z$A`?Ib|sGDwT&^;jYf z@DX@RLt?)HeKs6-^j?MdWop25`Z*SF_ySTGf+sOT6k#+1Cdoz0C2SltLr1lF;7$^= z?_{OrkFfcWGFgmd(*g@hxl6Gk{Q-XpIj0_6N=__4;69cAsXC+(FRCEY!m+F99IQ-h z1HkwQFlgL2WujwMNFk-Q3r2G;=5^fQHnrRd1G`-$qwpTjGsy}kBbxZ1Dr*#^Ql3RQ ztw$2#r?j~|sOZDDgb;a??gQuu<beE0iV?Wg`d!4@4S>9g9|#=*5hMt?@;l<|9ZCj1 zEcQqS#+J4WAnm_GsU-apwifKKT0X_oO;%S{=_oixDKMnfR#Oy=sa^o1lAjj6pe#zD z(w>71(70IF1Ps95E?yfF;RSSxE~(cug}_ChZD73;>RsK;YhLDP99uish%65nL|wUk z?wifwh;p@{U>OP2<rjqQHC#$v_^1HhK!A~XSr`EDb+`%%`zF4GqhMwO0Fi3YNCxGI zvWj7_E<Q}cgMbt7NFg{sMj_zK<DPLa1Rt(%au1z)?z7i`GTP8kWkLykLZ(3oRy!Ft zyN2yU)@IS)1L2&aw=DtOL8Z`Ak+{uJ#*79x)?n=jIbKn$goAesX+d~xEl~fs<qFy) zaGg>NYG0V_h`krC&UzFK53YewW4tCLz~K}yAe7vj9t&o30)KecRGszp2)O(re$IL+ zTFc*{gB=R3l0c!5`xArP0!JG*7)Xp)xg(CFiId6ztZ9+lf*m;#X?Sd+9!5^XepPlm z*BBRwM;+;Lnu&1cW$STl2=-bVP+bv<z$_40QO!c9y;farU=xQ>O?VH`;75SKt@9gK zP=cW+lc`mCkoPc<y|k=v335_Vl~sg+D{ngd{HHQ22l=#-G6GTulxr6`1GVkIg}~{i zAX_2;K0cTGd<(0eUAbAZ2`f;pjO5)#buvcjxiWuWrg<Ma%4gv4q7-YOnq$pAvmK1( zuCk<3Na3BLm^=uT#-yA&#yPhIjV+lv0{M_ryqE@)1ovi0uL)_Z#(M*DzO{!in_R(< z8)cHjRO5z;$(GPpU9fS^4*-b~Q~}9kC+a}nej-IUlK>V_vszRmD@ex;T!wypI}$sw zSGkxS?#QQ--pnkXWY5NRFV5JZXxqG^`-*(f^#8A^j*cg=Q%EwvQ`n(iguOCU;vEN- zU@zIu0Stu`e<a%)4v!#{Qo`pI%HY7PhMwB7ZeVCXVF6^zEp1Yvp??{Dc+XsrbHcWP z2W`nZ?qwy8%n%X9vzlakxHV=5b{&x=DUH$t6s+W*HZbG^)uSdQl>?$pkytDqWx9in z*8g$Cq2g$-73Ta+OPoY!HRt5%7`zn?w&ua|(q`eHe*@sk&k`J?f3S72vLk}OA5cI5 zg*}x#yD71X0Gc@0j*;{@`>Ay{JS;HKi`ej<QbDwf9D77a%*T7xCf-RwAPGeLCvBt( z961OI38WH~!a;_GN>so$^(&<{_@iN#8Q2QNO{J1{d~yo_1Pt>@V3Of?LefzId^#%f zyI?dh=n-Xd$mZBb8^9jWI4Ic0Yprv6TnmL0!a^CP#1Dv;TJIV<lrmd@n(O?(O?<|L z!bP=&J3#Fh$vX1SA}6p>0?1yu8+3rAtP#o?tr>?)Kz|DPY8472R0<|)qKOh0N-uY? zS&<-XyFRE!FFIs42kXNOVLG+K5iKB<Il8u9aMx66k?VwvdgE~`-?Cq_-gZWies5|~ zgvRn0S|O^9QkXmVqUAG1U}lFE6JFRt;TpUltkIDTCX1&P^qfyuvDVR$LYwTZIMXef zaG8@uC0R)0Fq%zhBF6%*5g3r^J}%-&v0zx3G&%VC!1kJ_)>hV;cT%dqH%71kDgp)& zsgH%$$>utLqrN0_%%VK`;T9?hB)#ddsz`*2dmc9sm|w;-jCV@k;dgQ5m`sG9am$^N zZD7LSP||v>+9wG9AU6Z}%(dV<5jE4cLHkZ%)wx3X&AUmByS}`;)eFW@-42@?xiAs$ zUD#%yNQ&~RHEfPg1B)$?mBQw74TAIh`(0_S0jCS01)VNl+_Iwg<Udx@xdcEFSPhRN zyS#J&DIra8Lp9Y=U598{t3cmr8MA=4x2sRT)Wedn4P7`1FS_WE95s>HLH@%qQh~!1 z0m1J#M%#181prie;{Iw`tc<Bhg6wc55Q@nyvovA4Vl`BHL@z6=*^;SRvt*7*PI8KN zrn+A~WwKv(Q#R}3yjc>URn`FnB)u=|+MfosUgz+FYVBR`nS(3$e`9#cn0$fCW-{J- zKV70+l`gtvv@?pyCR?*Lt6s<wb&7q(mpDjyJC$T%M3gg?7gi>BYMFG-59y7P=SB=e znfRUiJj{hf^3dX+Nh}7xaD@Sn6Ca&T(u;o*fYu$urJ>lL!}}XwE0sQaf0?B>Lyt2} zVy#S4W}<1IVC(V+brX(#pBBmxQVOkZ=N~UORTS^?L5OVy4q>5yH34u8o5L4QqBNrX z!^UL!N5JFLNH!*Ei|~J=ECL)M_I!Sm2%9@WW|fvo&?u1v;jBW>IiM{R?6#etr_OVI zIQU&g6E1zW?kwuekEum?T%FjO7V1Q*h_LxLugHDNzqf$Q$Ae5xLa)JzWGHe{CZCQR zy1M;5&tk?0$|yGqfA>VKQl`K!O_QSX`$k4-0vCsQb9_!QwD9RjUu6!ie^~`!zxDX+ zf`<hgb;>K`#*U1MwJ(tgaiC~Ts6ug;b&hl+0412lNDn~fqdp!GdQ=2xB48v0l#V=e z-Zzy}H!z6qYkF0QIkQl*QW0Hwl;>%)y%oUdn#@N04uw9;0I2{h>Kksto%Gz=xnhgB z(YeZSjkYBO3BdYSv<0h};<Q^y=U3~nC6cmJoh25uF9Wl}dsG0$o1y28z5xpkq~(s| z?Jz)|Jkn6ORWGY}tttff)DDfuC5`h`7iulmQ1G{z{~jz-)hWpl)b~NK!7&u}$3l9E zYH)+ejr&T`l+miypaeqi5hH<58}p_}1~~;JCrRbQ7b#d{<vrrwy#PSV@GXiR$wOrx z$-Wsq)=`1D9c%srRXYG~kIQbEif(zT{h~}PGNffD;IRe}{);5q9F+~vak)#RN4JCm z=}~u}Z{tuhcnuDGDtg?vYcd|ZUQmiwI@|;T77$Sgs>;DWjja)bq&Nr`_1N|zs3hw- zBNC#^WvvX>*R>2&{Jngq>f=lOCRO2GkFp!K7B<Z_VV&iMLF$(npyjq<kfIZ!7?$F+ z*7p)nAABd*s2PJ@iti$^hL{0_!z>#3-DVb;Dqk;iwzE<{dn~!|EcjC445>}()P{b< zz^8$<1M&7iz-aM5WDn6INCyA~X0J`n1P*oSK4CzvaFP42tD@&CoV$h|wupoLVU1mn zM$rgRiW7j@v+q{ib}?Hy6%sR)N!DCD2d>M=Vw8qZwpj7u_l8XhK(`7YN%?hU<mofe zf>Ocx5z3~@%eZ%$4vBxE_@q%u#}-1&pb$uV$*w=4)7;V|ZE5$An?<J<`G@9hq_~$T zY&QJ5%H)hOnjwtK;=55XhQP@brs3-tzjmH5&`=X@Cy(D|A&<tq8#NYmwccoa6mH;> z{9I;)2{=%L3P7i6YKN9$XLEdik#MMHU1S`PDU>vzxV1ANl`#~+Z7z948>~;zO@QH~ zQz`Ok=3%}-%mDYofnd6^5xE}vgClw1%oVuSe(y4S6ro{UJSJtz&cq9*;l328SEN0J ziREB3u>~nC3&n$^XmHnHao*#Xk3C>C6drl7{t7X8TVMt$0>gh7W2y;UfzHci5^E{A zAjoDwhU<$3Nf$+sDx)#@<{^$4RrO=IWjOsz6tKiD`|7ptclbNuMTurBxGQk;8EI=7 zP{QGVgCKjDSi>VyS%65N60zB!ZF-~Khd}XW<;qT)1{FR!9p&*4P%4py_sRs4A)>S^ zE@m-VK<L$DKb9QM;Dw+eU&@06-5fcOW~D-Lh|P^YaUPML4xbgn!4%HKuha)P=sW-e zav1Z%pHyMoqQWHCuofRU{6y?NB8|ORV{BP7Q;<L&v@T71M}n5R4lXoE>Uc<Lgf0gl z*(qSDwsP&382J?0)U5SGP0%D&65JVRzU9=rZQVQ*;&(^_Xtf~PaF-v6i*l~;b8=9! z!f=OM!ysL;tZ^!|Z7@eI7PD;ex7cQU4w2VYjTz~Zwc6%`!p5x7FI1His%DEYecPH> z!OHht{0<^eb_VU1#JXr9c77(D7hEdo+{6e*O$7S@*M{{GU<sgc)7J2>MNIvWD$AqQ z&=#rOB=m@f09RTZ$vHXq+2f3{Tg&lO6GQca64!0=Aw5UE<sc1x^dq!}{S;+s&P}Mi zESENuVDJcs`r!VS!~YUC`=Q%Xl+wwj*C7?H0R|ar08t1FKY(YDxwIs?6@}W;IxcZ3 z6g3zUf1J<{1Z^&+RM8lUNdVD(?IB<|D=wErLDZ}bu3KMOxFVy`BoeJqgivo}g%YG3 z(zsaSH0}HT(4e$Lh^rApw4?_Fj@QVJRwM|CHX$ip>$l1pJSEU4%g$TpG9kKHIqV!5 zgeI`@2h{R>Z3Njj-G~4Lv*!?(VmAOFbH2j73`2+{U>f<1lxjT|;a-gfD<n}=N*#nI zJO9!Q*k(gOb3ux^7;#RZ>Pi=*#Pf9ldF&jevss!IsT^wf9EB1|385PE*HNG`qdf@G z1_m(bjwjzQW&azHfE|co3j-|^%=7{`4EHyFl}=C>HYA&4^3g?+i*I=b%s}}^8mB;l zh_!__{Zdy3=!|9@UW4(FrDYKrMZC?tZl~{q+CodO8-*y(hRh4hOK$GguBQ!f+tM?Z z`M3v{_ok4+;-Zr=Dzi1bPOQ39yGDpO^@@jVf$N6EX1)nkqCTNH#!vSt^@eyqAre-M z#C&S)u>XXeEKi}tDL~`T#6OgH#$g>>YhBZsNLr<9Zb0yh+-2C&Ar_5e3SJ_h#+$_= zmV<aRV4XVEho%TU87fI{^OC}ed0@c@u>4BVq4~PWPuncYsg;H|!n}|+cpyoIM774v zO^--5^f&-+{-;gsBT{H`)h7P&H7s@2!yT4Rk%lk|bb(1`V2F2t#L9DrR)aF&m)D{6 z*h~Y;W8X>Q8#;~v^rqD_q#p-Jx8Jb1!bs+VfewgnX`Rp0clH>+LJJEFLX&Z(9s?%% zQRO$<@Xc-+H6Ui1JKUym+-IFW&|OG!B#+gRl#z+)cx(k3OdM@aCyS$}OF$98TO?6_ z#;Mk^JQGrumPEUJ6Voflg1Q%H&UF7YFA3A78q?qTf2xXD*gn#OI_j0tEiU?!{O$}O zWj`g-VXyO9eZ8}k^C`V$c2(JQ={2~wt0nNC44eFvtO}(PC<YUo`{@tUnbKGCt`_iW zt2<b=?sX00l-ba3mjrYNkUKm(kM6Tge@DZ(6P<D=JeH*!Bdg&-H>Tm!q6}7$mWRE} zw!{JyaK*sQQc$>zr+Mk(A*dC%a}1f|g@+<F42`e!?n)WIYFCB_S8~m1BkrCceSPH- zD0x$OVf3YPk1Y%gn>12-H$_gG3_80Sk-6uWY=;5|z`tFl0=f;#mvlGQ?zli^lD$F? z4C6mPY;}ZO!ghjx((8e3Wq!ob4Yvh2R}FF`%K4=VT-FoBtPwG{hl2|uJp#RTG!5kW z+dn9ha<dhZ@|`Br1_hH%Fk$_0H@zqL?g&nGuy<w1h;+iFC6M(PJxxgZmUG`al`kf# zVPhl{rmSwX6l5N|Ze>S~>!qX0{xE@(jLur?H9`H5?dL0zIZT95I@J1-Z}>(q$Z-$R zgTrU<6Z)YW0)Efkr~;NL?7bK7rD#f~3iaa2oGV2|W;?|ByTi?Q;H6Cd((zGs?*{Q$ zqusfyzr098LnDxsBq(-oE~!X4oI|J+S_lteX$SyxV)05`L(MJShk!f)Sei_c$fz4y z{0hOQ7YeMa{Jn~oa2_EA+plYBfq@8;)`abAB-7HW7eP?IAoLL(fuVIJCMeTG?!4r$ zget<&RS@b5FuU`@EB3j}r(n-kLq%22p>bUgVaz?qKk9fOVu{EP-u}7yzJftMZiGg= zPDo7C9UVkE+XcDe_-clr*6u6RVmP3E0t<~wRJf#q-DHzwFhIG)Wx8n<Muc*GDzTzu z={&cU3sR#flVpBI9^VRALsBY{6vW4o6PriGW7RPgV91+?Vv%D~GYEx`_az?$*#FBs zE0REz6?8{xcRjpwaY9vZwKvF``DW(K0H5#I3{~iZ5mhR8ePFvLz~FB)!L|052MRd! z1{(}D?xlxe$>i@k30GP*DM|iyK_C#|&%$4$fe|X^3MP=RDL7}@U9SPeHP^N^^sb+1 zp9V2PcFt(@!BR_4!3Eksgk+W$yxv`LRVFeUHfV$v|Gz$m8G+0Y;KMtL7$C8sD&6A^ z8tt3^oyl$j9a`u{^a%e3wlpLpx}o~xJo6k3IAsLJ;0rFHy+=p7$G=cTy<>2ZLJ%Vw zh&s^MSO%6!AovQlBxTyI1!)bagEXAh#COP3Ga5GgI0E|EQKd9qYk8pG@EJMB5F#Ii z(?Zz7?-n5H1*R4AMOltZkSDu<`T+(YBfTzV(scN>_RL@AQ2z|k%$yh<oWWiFM65VR zIaoeTgs}<s5|1><9O^O%+V8H$p^x5B!&fqwM6W5HnQtZ%KgZtYJ;%-J0K`*@RNKb6 za)5XeBeyWXQX7bMpeB$(j!NVcJUvC$v^lklNjy;sn*rn15<yQ2xyxxr*bB&W7YJj$ zzp}F@O4MKoLHsXrYK~#p!^rnLAt?lq6uT9GM7T}KQ)!)mhg=M&YWwVtxHZO9i%J^g zcg~xJ8s3donqqZ?L9R=T5MUwe)T%?@PBfW9c0uygiSJXVPk$z?zCu!Xm;vT)ixt0P z2!2>LkysA=j$g(w$pEBSLVkBB%Y88T_Bl_`FrHJ77>&`7rX90BsbvmY4IU3Ik@&d# z%V0^5Ss$(ec@&20WsU~UsdY+9r8`n&L4}b7D_!|ZNIF?#uzG?vZ&9QH2taFUa;U!) zpOopLPK<+Q2gz_+$(3+r(Is<7@|e>CBxI;{!w8eo0cxTh{@wKG1UN$!2ns5)0UiL` zS^ZJ)5peyp?GBBBF*FkE7F|35xS~-n6BFO}dnnw4UWgx2sQ|l$#kyW0O)N#s;Uh*| zBq}TXPIUZqvNQ-;&gm}{CS;h{G9Rz~#K^@VmI~y?PW@S+Bsvi^Q1QsarV|4NkOenG z+EwQX+zdIWNy2FjLjxNE0_x~>##mpRZP38KfcC8+Dk+IlBLT!>3HlPDT^PRuv#vR5 z;W~d@MG}Ja(g*~_Y`}dqie{ADK#J>}C)kdxy%WoW_3lEWpJ9`<MUATg#`H_<K`xCZ zF(P@4d;vyJ0yCBQJ-v0b{T|8CJ#h7fsAT|6_(Pq#n{oSzO;il|>UK1P&|j*Pj2GCp zWO8?>j97(h8LiI1Fdak=rg+nF*6O7Q*-Lrtn}jy=mm??!+jXvgS}lbgqg!qHo(L5q zGnw$|<paYGI7c%<)hofdU!lmp*Dk{>r3yz`YrF|Ad6pj8!nvd{nc@)iIy2xJ3fg)d z;X;~y_gH9gr0i!OO-bO5xJUadI~D@^(*)GM85dI6=x`j^3T)idi0ST+0ZHy8e!Uew zAAn&6zXu95(GS12jO_}Eh>tLc_}5U3-GD4k6Y``J#UQCk{HX;)60)9Z53kunrzrXk z#FWflWssd;p@KC%(t9ig7xte~4F-jBIEQ>Q%xYxLyW(aav*v!r)YQuY6DY8U#_N@j z!q^OtWE{nwF}tm>Bko_+iRyxQ#u>ftBx#bmPU@1G*XHG4((<1qwqs3)v|2=Z<Q7R+ zG)-p$6;JR`xzL^n4IXqVy%+Vn6d#U+a!giGG(*z99z8l-FEz>93W^B>lK@N%1DWH4 zh-s>K6QbdX`{5=`X|U0dH8iO2L!8lTwZ5@G8<E>LRCq07R^VY0X_96LH$gDf*#fC7 z*>*NZ#d$6hNI@Vnr~2G<jGatj=0Ui4&h2O;M_94scw`GLYqw9mxoAvx<Rmxh1g;hC z2UJ7jZK6qzXdsC~_`Op5<EYWCD60jT@8vU6GPlCWwFus{=Sq|iB0;-%>oDt(H}Td9 z#W+(W!}<CVN)(B8B_SL857yG=;lbcIWRx3Z*2dh4Er7<B4UX|Vu7v``hCl?4hUM(c zU|g_t$Ik(SNw78I5<Zh^HzklQ9dm)3Bx0d4?Yp@3E5$!wHfCJ8aEq5agbt{-4Ng}< zbR4K8^tk6jOe7cb*G>0*A3t{vR__%C4|h><<(a9k0mV89;2~y0GLbaWqfqb&Wdz+2 z3KG|Q9N3(hLI)18PI36QP$0m+oB}7zoK=gi<sC4T=Jy`HJ|oX7fg-U2-5hW2=;pXa z<%A}Y7gQ<h82)@!(7*ZJ>pwZ35Mh;wUPl5W9?igb(VyT3ff#^g0x^$1zxXFf!HQkK zS{puhkV&Ig{Nc*%cR(7<XREFqJ%FsEUmj<UPDdQP_>`rnp9-8`s!kd}3fgASbXLHq zzATe?n}agP1<FI&Y-J3Qd16iF1%dF;jM@}6T?m2(5<XJfCLr{iT7pOL2KLYcTUi4( z))0H(Yb*h^fw%^V#FO<&5Mhc8gd<w!KL2iQQTET^-~Ka4dc0S#fHG!4&D;jUUZFh& zh~sx{127BH*btWF`dA;Tl5?KVw*yhf$hiR}@uMKNdB1#@VG7l4wY=0Z@ZOvf7A{b+ z#GP(Kvh~gw1$6vUHZLEGG58a5@gOp7)`B_;WTnuQ8uCO|va&2Ae=0TZ$!XS3G0dT+ zu@s91Gmb}e=QGpq;4T*+IP`-lA;SoW69XLCvWUfqxNB~AvcAt!snI7yJVfy#m3pXy z8uAEG*)q%6!|apt{%Cogq}IiuZOiRI9<MMcw1z_ofw73Ni->VU6Md0b$;cBXcE9cL zVR4aVL`QsTXbZup5SGk+Wr>#~gv45ic1M~gy+<O)JBvpni<d-jdU31qy28;VW9UtV zw{b}n9|Tp$Uo>@flV56X0T5vuO>3d#i*x44r;fBGWnXCgZ3w))l+TvRFz}E-@;kRK zoigNz#0I2Hp_bTx1F_l5jZz64O~lS1P(WMWYSqKy^>86z9$jj&NP;0v^krWlV2lDa zP)$LNhM)yw-Z@FZ&jhPn_K}kk7NtaQTMLI*fkKFk*aH0la&yH3TI*q9T~3T_;;Z1Y z+t*=2kKrg5fZVHPu=(nkezaBSUU)z>3|Fc`_?=El@VefO=oo!#-O*%@N=lG=0J@+x zqR5msA@8Z}2t#rRsTFu+X>W@II`HJr3KsRvHSa8Cte4vW%zrVOWb$(gIya=L&F$o8 zC!W)pomoa``&sOPNNy)jWAuZ?Rn%oh!j=Lkb>4hg*+KkM6IiJPh%is>)uF2#S2@}I zC)f9Fwm<%b41e=g!jkwC>*Hj*LPdKyL|oQ*K~DOA6erODf<bU_;4hyFy!Wu<eP;QI zwCm4<UDtwg2gEnyeL)zxMX00fdvf(%N$zV>?pG%!i`9Ev{G_4KG-z55hx3fZ+5}ux zFll&T+^*}r;D#@5E_TJGY{}FywEI5_<<ne;Mfd`exl~*1Z-|<iW+u5*yT(}iWOxYf zQ(Kalixd#UDbO~VAhhcoKcKgQTwEO~>gk-VGiT)19+e5*NrCbeBIB}VH$^_t0a~>~ zjTLN?6QB}6UB2u@JG%2%H!9(dsA_mf^+gn0)Jdgh;*=@P?aGNXsLTneKH&8AIwx8} zPiEIK;(Xd9%UyTw%bNqwQp9dR<RcU!NzN$+pr5C}%3+1@{T+urh!T`J0mxUOOs8Zb zT>@lAY=E=_w>b_JZYYy?BicG)gTXLb^MH(wyr(xVwiY5GrR^@E#4%k`@6b9;KCHZZ z%L?u_GUh+{HCeE#LOvoSNMb+~aAnpUfvf!mZfG}eWeau!ARQ1TjWEb8dkAp39Vj~U zv@iG5SJew&N^U1T(A+vFra=^5vu2PrEM!F6TUH}CoL6JJZcM2#mC?`?XOy`@g)wL5 zKteUGP|MIw*v4}(AQ()<BOR~Ip&%l8@sAow4eyL>W033j#<$fR)qHJ+JC5vlZwg>X zD_$6PGfZir)_HHmiaBCg4}{=Z6jOaWzLqhEi4eguCgSCnrqG0wgwkGg8&Y13uzZDN z#*>x?-GL|;`zd%;0YvDoArwX`WKaa#Rx8dVrbIP~RV6UPt-Cnt>|lp53j8Tr@fshj z@l7;VkOrIjJ`Gw^xsa&sS_)x;0c)Qi5k%+ds3yD$Bf#3c>MM?6fiA+19}qV*hiFgG zt0D4Fz=E)~Kg6+=(-{WUX(TkALind7oaCB#Yea=&TcAKDj@j5}@WE42@&fFrUg&=Y zymO9hZh!_3`Jm&_bFz{+Ym%+~jJE}KoP&fWh9{OYUVA&h0L%n|X^!?3kRZeNcv|ZN z?lr6BvY@e{w^7Zst)uFD>Kop?J#{8%t0xUE8)5DgL{V`|a-epGv(n-Pq*F|(>>0NK z>f%sQQiXmM7F7W&B(Rd8P8lYmaS23{uO+NYkda|K<dpb_Lm4>6kBPt}dP~TV`5-bc z2sk3(hh$&~q!HdAbcAFdkXRhNJgjhlc~JNf)FY_IE*O|*V9OD?15Jj2400KoH0WjV zp9Z28gk1q~1j!ICB)~&(kO2Y$H3-uWTpXk`NMvC7Ln4MJ40Ippe!-$cfQ2v#LKDm= z&`_YDK@);zg4PDO3WOC1Ens|rssL&N><9P?;5C3LK(zsD0=@?T2pj$Xj{m!S>;D7& z|L{IieNpqEupdodiF~W@|1tRQ@muAWsJ?#vX!z*%yTG4P{5E=f;iJZ<i(hoT3i#^! z2=bTa8_HKk&W*jaI#Tut>7(0Ajn@T#4z4zC7QD2%3Ff)Ocg-i0?QXz&0ASR~&F~(D z4+FO)zwl+Ru{)gF&e(R9ye*gahqMOOdS_{`p<cN(QPBfedLZSskrqK&yUDg~^6xgx z(X-9S{t{sS1&kK)6~HVFZ0)qwFX?Ae;+@G_50@=IDHp{U^pIW^gOVw@Ap>&TZbN3} zO4>MqZ5rdExMe&rj;N5jxiq|QdR&K4@n$r5YVhF7^ggha6Y%&gc<RI7c0-$9N_ufs zU$`$e_MVi-9+yi<#Yw=j>SaJ<gjCd4f!$5YifIsp@SrJ8iI9(HcR`~HNn(=N;NH7q z2$*)bw4qu}L{>zeSVDx4g+gLDYO6l@O(c_MRFWi<I49c#bmz=C3Wb>2fFL0*d2lr) z8n#&-XQxbsNQp1-1>ZE|25lV(ItxN336wT|AOUA~<$G#-Lm;EUflWQ2PaKt!V0)2@ zjJ^F|+4&{1156y1XVhq>2He_=DqEeIy1hpzgCD+R&<?(y&B=fXAlzJ3d;Y#WPG(e5 z^(Fceyy$Xz0HC`&q$CH{<v!G+>0^9)0J$9*>C2In3%|&ElmRjaUw6#F0}I9dQeSkV z^RzLX`Af@FJ2@Woj(}VlLHkjbhA`x+CcA>^#@fP__w;dyboTg56DwFGCb^;j5X8cR zLI{`Gb#h_5wKMp3fnJO4ppzx@>y2a(Io#{*0K_;QW;p`_@ys!fAt{OENE;VuFUsbC z40h0pe4(G)dKLkoLJvYaa^3p$CM(sf4-6kw&$s8>k>#d3MdQwty-GY+EW*B82yv!H z8Fn=-o&)#nl90Ts0VOSU&X&>=kMHhv<H#F@gW>bI0fY{<P6h>(po}wG&vZJ1Jm_MJ znZg=Dkqpd@MdosKGVTZb?tb%;6?47t(q~qaF@Efi<-zN6t1FL;l|p`+*eXW$PP8xU zwWe{O_Xtuc+^SR3q|qm4G$l~R@qD`i7bMI(4}Xz8p=K+^y_=BS%Lg9Q6@x9R42G{_ z3ujo$F#cfmIf!D-V!92kt)M)q0D%-tAve2&X~N~C(5xJOS!o9sX5A#7=E-d828}6u zEb|K&T5zgC<fA~S7W{_}Gw&nOUqLEixj-Ng1R)@a1ECHN;+q0)vXBM8X7V7=KSRl2 zKt@yo_J4h^yotoDDdjojg(RyNqFKEufR?RfY%FiH$R!SBKsmzUx05uPy<k+G05Q;t z0RN>oJb4p$9EH%f$C+G{LUH~tv){r`^C=p-iX<)ZyiuM4Ejlj;Qv_AJ(c<1^(u_O? z!9h&{iHbJXecG1W(?@=BXRrQfFq_r>Ns)O5dSc{+eKeE=LOWeoQOS>{1I3Ae^qV~& zMVyz(&kg>Lss1J>_F3JQ!_(JMF8oZMFC>f!8((o%fP?>WM~N{K#TOxx2Vhi)P6SnG z)VYfB8mattOu)u&z%DmUTfB(}1hry-W*%Yg>w+FF)KGK#rMv?{gx4!L8ZvRY&?8aA z;?n6XbgqHq_MOB=vo=uJ@dBJizk1;t-NhFZbHOU^dIl=QTGU~9L~Nxz!`v4c?YE}^ z4+HBd(|2gGF>P2X@V2WdAP`hl5OzNW-tpn--;vOvJ>heyF11A#Oo;gW?0Uow;-T@b z87P-<kq2mvwS*c{mqOL*ozPB|M5F?s1)W$3G7#|@y`&gov?&zvf}3RvDrE@=>Fkc% z<uTb1nFXtErfPAm-kJQ_E^KB51W1>~9spB&5E0V2-wEC_4B>(&?nod9X8@&nMmf`& zo$*$@gQu^K+>qXKi|&%C5CBQn7X`%)XlLO0#_N}~Ut#AR2aZTmd*lP))3~cX>ZY-5 z)zaJ>3=Mgmg{PR(r*IL{;-cKyzQcsI%^R(R*z=GO28L`>2+IhR<u)#=k3s>4ekE+4 zM+Gjxzqe4kWU~R-5>VMZT-3ZM(po&(PI(v(&1dv<hw9)mc$O05o$U%Iv&D(<TUH|; z8w;fZOT8SRDRwo`WP4lDc0yQ3ASz)g+_Bs#7C$lwGZt%HS%|?SnS|eV<?|LIZTF(v zA*|o&DWbBlSrJ1?4<ggpbPSzY3XjzJj>(86XaN;BvHm}^fU38+P=hf%-Z4PrXG}u{ z^{g=)0^+lVS>{0*NjXNV8&_q+Y)FC5rw3J)qxWAWsHWI1Q7czoL5fLjuNaLok>pJ0 zQivnSZfgD;R3V$T#E<_`Og=^fL87?6@mL~$cPHC8+zk`RkkHzqC2ee!6OOT25}?Au z8lo5|NxX-eBv?+_Jl(h9D~;e6g@3JwzU4b}rUS0Ft<p*|nY8hO`+?{K%jrJ_IBag7 z$rK0G?0og$UnjWEfbk|&EL1x6F?w=P`;@_V$j-_rSG+``f<ZYbPVFp`ne7h3m--Tx z)+G!kil$c7;m04|hz!J#nKY?ome&p^irpb2#Wy>baUHZZ$m{N<U4V|6GUp_jJ0taP zk6?!`u?*2ik%R-K%4{Rjc`HY3vMP?{fdY$I%s}raP3nVX740ei%K>tvL!ESZJHISL z#$q3276qW>>e0K9BC6Lm!PDcC*mJ>96;}jV-`)zxB`?jOs*Xw=t0)s{mG?QRw~8qt zfu=rKWTTDPq=!y;1b*tE3H@nBXu_aSH~}ou<m|N19~iAUU1B+rX>Mp}xlRsiQy|?8 z+=eFuOFpAznJ<i+6QW4$XG6*)Mn|0H#}g?-GUJ&tF%o5xO1y`MIS2NQFIOEc`I(3f z2l)=*43)y3kZ`{NpiJ0#G*-@MH_I?8iCsn3FPY~8-*Ppv@=`WOy`EK90Fl^_oq>a$ z9HP}Oq&hZZjUr$CB~(eAM!iJ*;=b?Yrx6h>^|H)MP==A9VPv1#j0hS{CaVQ1a0U*_ zOPt|Q3|tBH4>cTq2$K@~xI!3~L_nbiL8%UpJy?`vZOB>f8|q^o(U}ch?lcb}gFn9* z1|~O!l8`0`5O(Y2Oh~*GnI51ZmY26LDazLJ5qc&Ez{Mb8VGH2izKeuw*Z=?k00000 E0QL`y%>V!Z literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.svg b/src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.svg new file mode 100755 index 0000000..45fdf33 --- /dev/null +++ b/src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.svg @@ -0,0 +1,414 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata></metadata> +<defs> +<font id="fontawesomeregular" horiz-adv-x="1536" > +<font-face units-per-em="1792" ascent="1536" descent="-256" /> +<missing-glyph horiz-adv-x="448" /> +<glyph unicode=" " horiz-adv-x="448" /> +<glyph unicode="&#x09;" horiz-adv-x="448" /> +<glyph unicode="&#xa0;" horiz-adv-x="448" /> +<glyph unicode="&#xa8;" horiz-adv-x="1792" /> +<glyph unicode="&#xa9;" horiz-adv-x="1792" /> +<glyph unicode="&#xae;" horiz-adv-x="1792" /> +<glyph unicode="&#xb4;" horiz-adv-x="1792" /> +<glyph unicode="&#xc6;" horiz-adv-x="1792" /> +<glyph unicode="&#x2000;" horiz-adv-x="768" /> +<glyph unicode="&#x2001;" /> +<glyph unicode="&#x2002;" horiz-adv-x="768" /> +<glyph unicode="&#x2003;" /> +<glyph unicode="&#x2004;" horiz-adv-x="512" /> +<glyph unicode="&#x2005;" horiz-adv-x="384" /> +<glyph unicode="&#x2006;" horiz-adv-x="256" /> +<glyph unicode="&#x2007;" horiz-adv-x="256" /> +<glyph unicode="&#x2008;" horiz-adv-x="192" /> +<glyph unicode="&#x2009;" horiz-adv-x="307" /> +<glyph unicode="&#x200a;" horiz-adv-x="85" /> +<glyph unicode="&#x202f;" horiz-adv-x="307" /> +<glyph unicode="&#x205f;" horiz-adv-x="384" /> +<glyph unicode="&#x2122;" horiz-adv-x="1792" /> +<glyph unicode="&#x221e;" horiz-adv-x="1792" /> +<glyph unicode="&#x2260;" horiz-adv-x="1792" /> +<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" /> +<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" /> +<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" /> +<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" /> +<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" /> +<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" /> +<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" /> +<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" /> +<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" /> +<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " /> +<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" /> +<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" /> +<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" /> +<glyph unicode="&#xf016;" horiz-adv-x="1280" d="M128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280zM768 896h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376zM1280 864v-896q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h640q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88z " /> +<glyph unicode="&#xf017;" d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" /> +<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136 q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" /> +<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273 t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01b;" d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198 t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" /> +<glyph unicode="&#xf01d;" d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q14 0 25 -9 l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" /> +<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" /> +<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" /> +<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" /> +<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" /> +<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" /> +<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" /> +<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" /> +<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" /> +<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" /> +<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" /> +<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" /> +<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" /> +<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q73 -1 153.5 -2t119 -1.5t52.5 -0.5l29 2q-32 95 -92 241q-53 132 -92 211zM21 -128h-21l2 79q22 7 80 18q89 16 110 31q20 16 48 68l237 616l280 724h75h53l11 -21l205 -480q103 -242 124 -297q39 -102 96 -235q26 -58 65 -164q24 -67 65 -149 q22 -49 35 -57q22 -19 69 -23q47 -6 103 -27q6 -39 6 -57q0 -14 -1 -26q-80 0 -192 8q-93 8 -189 8q-79 0 -135 -2l-200 -11l-58 -2q0 45 4 78l131 28q56 13 68 23q12 12 12 27t-6 32l-47 114l-92 228l-450 2q-29 -65 -104 -274q-23 -64 -23 -84q0 -31 17 -43 q26 -21 103 -32q3 0 13.5 -2t30 -5t40.5 -6q1 -28 1 -58q0 -17 -2 -27q-66 0 -349 20l-48 -8q-81 -14 -167 -14z" /> +<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q76 -32 140 -32q131 0 216 41t122 113q38 70 38 181q0 114 -41 180q-58 94 -141 126q-80 32 -247 32q-74 0 -101 -10v-144l-1 -173l3 -270q0 -15 12 -44zM541 761q43 -7 109 -7q175 0 264 65t89 224q0 112 -85 187q-84 75 -255 75q-52 0 -130 -13q0 -44 2 -77 q7 -122 6 -279l-1 -98q0 -43 1 -77zM0 -128l2 94q45 9 68 12q77 12 123 31q17 27 21 51q9 66 9 194l-2 497q-5 256 -9 404q-1 87 -11 109q-1 4 -12 12q-18 12 -69 15q-30 2 -114 13l-4 83l260 6l380 13l45 1q5 0 14 0.5t14 0.5q1 0 21.5 -0.5t40.5 -0.5h74q88 0 191 -27 q43 -13 96 -39q57 -29 102 -76q44 -47 65 -104t21 -122q0 -70 -32 -128t-95 -105q-26 -20 -150 -77q177 -41 267 -146q92 -106 92 -236q0 -76 -29 -161q-21 -62 -71 -117q-66 -72 -140 -108q-73 -36 -203 -60q-82 -15 -198 -11l-197 4q-84 2 -298 -11q-33 -3 -272 -11z" /> +<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q4 1 77 20q76 19 116 39q29 37 41 101l27 139l56 268l12 64q8 44 17 84.5t16 67t12.5 46.5t9 30.5t3.5 11.5l29 157l16 63l22 135l8 50v38q-41 22 -144 28q-28 2 -38 4l19 103l317 -14q39 -2 73 -2q66 0 214 9q33 2 68 4.5t36 2.5q-2 -19 -6 -38 q-7 -29 -13 -51q-55 -19 -109 -31q-64 -16 -101 -31q-12 -31 -24 -88q-9 -44 -13 -82q-44 -199 -66 -306l-61 -311l-38 -158l-43 -235l-12 -45q-2 -7 1 -27q64 -15 119 -21q36 -5 66 -10q-1 -29 -7 -58q-7 -31 -9 -41q-18 0 -23 -1q-24 -2 -42 -2q-9 0 -28 3q-19 4 -145 17 l-198 2q-41 1 -174 -11q-74 -7 -98 -9z" /> +<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l215 -1h293l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -42.5 2t-103.5 -1t-111 -1 q-34 0 -67 -5q-10 -97 -8 -136l1 -152v-332l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-88 0 -233 -14q-48 -4 -70 -4q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q8 192 6 433l-5 428q-1 62 -0.5 118.5t0.5 102.5t-2 57t-6 15q-6 5 -14 6q-38 6 -148 6q-43 0 -100 -13.5t-73 -24.5q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1744 128q33 0 42 -18.5t-11 -44.5 l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80z" /> +<glyph unicode="&#xf035;" d="M81 1407l54 -27q20 -5 211 -5h130l19 3l115 1l446 -1h318l34 -2q14 -1 28 7t21 16l7 8l42 1q15 0 28 -1v-104.5t1 -131.5l1 -100l-1 -58q0 -32 -4 -51q-39 -15 -68 -18q-25 43 -54 128q-8 24 -15.5 62.5t-11.5 65.5t-6 29q-13 15 -27 19q-7 2 -58.5 2t-138.5 -1t-128 -1 q-94 0 -127 -5q-10 -97 -8 -136l1 -152v52l3 -359l-1 -147q-1 -46 11 -85q49 -25 89 -32q2 0 18 -5t44 -13t43 -12q30 -8 50 -18q5 -45 5 -50q0 -10 -3 -29q-14 -1 -34 -1q-110 0 -187 10q-72 8 -238 8q-82 0 -233 -13q-45 -5 -70 -5q-2 22 -2 26l-1 26v9q21 33 79 49 q139 38 159 50q9 21 12 56q6 137 6 433l-5 44q0 265 -2 278q-2 11 -6 15q-6 5 -14 6q-38 6 -148 6q-50 0 -168.5 -14t-132.5 -24q-13 -9 -22 -33t-22 -75t-24 -84q-6 -19 -19.5 -32t-20.5 -13q-44 27 -56 44v297v86zM1505 113q26 -20 26 -49t-26 -49l-162 -126 q-26 -20 -44.5 -11t-18.5 42v80h-1024v-80q0 -33 -18.5 -42t-44.5 11l-162 126q-26 20 -26 49t26 49l162 126q26 20 44.5 11t18.5 -42v-80h1024v80q0 33 18.5 42t44.5 -11z" /> +<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf03d;" horiz-adv-x="1792" d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5 q39 -17 39 -59z" /> +<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" /> +<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" /> +<glyph unicode="&#xf042;" d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" /> +<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" /> +<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" /> +<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" /> +<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" /> +<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" /> +<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" /> +<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" /> +<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" /> +<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" /> +<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" /> +<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" /> +<glyph unicode="&#xf053;" horiz-adv-x="1152" d="M742 -37l-652 651q-37 37 -37 90.5t37 90.5l652 651q37 37 90.5 37t90.5 -37l75 -75q37 -37 37 -90.5t-37 -90.5l-486 -486l486 -485q37 -38 37 -91t-37 -90l-75 -75q-37 -37 -90.5 -37t-90.5 37z" /> +<glyph unicode="&#xf054;" horiz-adv-x="1152" d="M1099 704q0 -52 -37 -91l-652 -651q-37 -37 -90 -37t-90 37l-76 75q-37 39 -37 91q0 53 37 90l486 486l-486 485q-37 39 -37 91q0 53 37 90l76 75q36 38 90 38t90 -38l652 -651q37 -37 37 -90z" /> +<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" /> +<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf059;" d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59 q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05a;" d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf05c;" d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23 l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05d;" d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198 t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf05e;" d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61 t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" /> +<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" /> +<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" /> +<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" /> +<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" /> +<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" /> +<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" /> +<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" /> +<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" /> +<glyph unicode="&#xf06b;" d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5 t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" /> +<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" /> +<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" /> +<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " /> +<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" /> +<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9 q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" /> +<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" /> +<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" /> +<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf077;" horiz-adv-x="1664" d="M1611 320q0 -53 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-486 485l-486 -485q-36 -38 -90 -38t-90 38l-75 75q-38 36 -38 90q0 53 38 91l651 651q37 37 90 37q52 0 91 -37l650 -651q38 -38 38 -91z" /> +<glyph unicode="&#xf078;" horiz-adv-x="1664" d="M1611 832q0 -53 -37 -90l-651 -651q-38 -38 -91 -38q-54 0 -90 38l-651 651q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l486 -486l486 486q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" /> +<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " /> +<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="&#xf080;" horiz-adv-x="1920" d="M512 512v-384h-256v384h256zM896 1024v-896h-256v896h256zM1280 768v-640h-256v640h256zM1664 1152v-1024h-256v1024h256zM1792 32v1216q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5z M1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf081;" d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4 q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5 t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf082;" d="M1307 618l23 219h-198v109q0 49 15.5 68.5t71.5 19.5h110v219h-175q-152 0 -218 -72t-66 -213v-131h-131v-219h131v-635h262v635h175zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960 q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" /> +<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" /> +<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" /> +<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" /> +<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" /> +<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" /> +<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" /> +<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" /> +<glyph unicode="&#xf08c;" d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5 q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" /> +<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf092;" d="M394 184q-8 -9 -20 3q-13 11 -4 19q8 9 20 -3q12 -11 4 -19zM352 245q9 -12 0 -19q-8 -6 -17 7t0 18q9 7 17 -6zM291 305q-5 -7 -13 -2q-10 5 -7 12q3 5 13 2q10 -5 7 -12zM322 271q-6 -7 -16 3q-9 11 -2 16q6 6 16 -3q9 -11 2 -16zM451 159q-4 -12 -19 -6q-17 4 -13 15 t19 7q16 -5 13 -16zM514 154q0 -11 -16 -11q-17 -2 -17 11q0 11 16 11q17 2 17 -11zM572 164q2 -10 -14 -14t-18 8t14 15q16 2 18 -9zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-224q-16 0 -24.5 1t-19.5 5t-16 14.5t-5 27.5v239q0 97 -52 142q57 6 102.5 18t94 39 t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103 q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -103t0.5 -68q0 -22 -11 -33.5t-22 -13t-33 -1.5 h-224q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92 t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" /> +<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" /> +<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" /> +<glyph unicode="&#xf096;" horiz-adv-x="1408" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" /> +<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf099;" horiz-adv-x="1664" d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41 q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" /> +<glyph unicode="&#xf09a;" horiz-adv-x="768" d="M511 980h257l-30 -284h-227v-824h-341v824h-170v284h170v171q0 182 86 275.5t283 93.5h227v-284h-142q-39 0 -62.5 -6.5t-34 -23.5t-13.5 -34.5t-3 -49.5v-142z" /> +<glyph unicode="&#xf09b;" d="M1536 640q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -39.5 7t-12.5 30v211q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5 q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23 q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -89t0.5 -54q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5 t316.5 -131.5t131.5 -316.5z" /> +<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" /> +<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" /> +<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" /> +<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" /> +<glyph unicode="&#xf0a2;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM183 128h1298q-164 181 -246.5 411.5t-82.5 484.5q0 256 -320 256t-320 -256q0 -254 -82.5 -484.5t-246.5 -411.5zM1664 128q0 -52 -38 -90t-90 -38 h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" /> +<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" /> +<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" /> +<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" /> +<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33 t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580 q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100 q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" /> +<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0ac;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11 q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 10.5t-9.5 10.5q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5 q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5 q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5 t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-5 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3 q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25 q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5 t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5 t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10t17 -20q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21 q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5 q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3 q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5 t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q7 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5 q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7 q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" /> +<glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" /> +<glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" /> +<glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf0b2;" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z " /> +<glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75 t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5 t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" /> +<glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15 t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207 q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" /> +<glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " /> +<glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" /> +<glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148 q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108 q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6 q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" /> +<glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" /> +<glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235 z" /> +<glyph unicode="&#xf0c7;" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0c8;" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf0c9;" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5 t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23 l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" /> +<glyph unicode="&#xf0cd;" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41 q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472 q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" /> +<glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192 q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192 q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113 z" /> +<glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" /> +<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" /> +<glyph unicode="&#xf0d4;" d="M678 -57q0 -38 -10 -71h-380q-95 0 -171.5 56.5t-103.5 147.5q24 45 69 77.5t100 49.5t107 24t107 7q32 0 49 -2q6 -4 30.5 -21t33 -23t31 -23t32 -25.5t27.5 -25.5t26.5 -29.5t21 -30.5t17.5 -34.5t9.5 -36t4.5 -40.5zM385 294q-234 -7 -385 -85v433q103 -118 273 -118 q32 0 70 5q-21 -61 -21 -86q0 -67 63 -149zM558 805q0 -100 -43.5 -160.5t-140.5 -60.5q-51 0 -97 26t-78 67.5t-56 93.5t-35.5 104t-11.5 99q0 96 51.5 165t144.5 69q66 0 119 -41t84 -104t47 -130t16 -128zM1536 896v-736q0 -119 -84.5 -203.5t-203.5 -84.5h-468 q39 73 39 157q0 66 -22 122.5t-55.5 93t-72 71t-72 59.5t-55.5 54.5t-22 59.5q0 36 23 68t56 61.5t65.5 64.5t55.5 93t23 131t-26.5 145.5t-75.5 118.5q-6 6 -14 11t-12.5 7.5t-10 9.5t-10.5 17h135l135 64h-437q-138 0 -244.5 -38.5t-182.5 -133.5q0 126 81 213t207 87h960 q119 0 203.5 -84.5t84.5 -203.5v-96h-256v256h-128v-256h-256v-128h256v-256h128v256h256z" /> +<glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M876 71q0 21 -4.5 40.5t-9.5 36t-17.5 34.5t-21 30.5t-26.5 29.5t-27.5 25.5t-32 25.5t-31 23t-33 23t-30.5 21q-17 2 -50 2q-54 0 -106 -7t-108 -25t-98 -46t-69 -75t-27 -107q0 -68 35.5 -121.5t93 -84t120.5 -45.5t127 -15q59 0 112.5 12.5t100.5 39t74.5 73.5 t27.5 110zM756 933q0 60 -16.5 127.5t-47 130.5t-84 104t-119.5 41q-93 0 -144 -69t-51 -165q0 -47 11.5 -99t35.5 -104t56 -93.5t78 -67.5t97 -26q97 0 140.5 60.5t43.5 160.5zM625 1408h437l-135 -79h-135q71 -45 110 -126t39 -169q0 -74 -23 -131.5t-56 -92.5t-66 -64.5 t-56 -61t-23 -67.5q0 -26 16.5 -51t43 -48t58.5 -48t64 -55.5t58.5 -66t43 -85t16.5 -106.5q0 -160 -140 -282q-152 -131 -420 -131q-59 0 -119.5 10t-122 33.5t-108.5 58t-77 89t-30 121.5q0 61 37 135q32 64 96 110.5t145 71t155 36t150 13.5q-64 83 -64 149q0 12 2 23.5 t5 19.5t8 21.5t7 21.5q-40 -5 -70 -5q-149 0 -255.5 98t-106.5 246q0 140 95 250.5t234 141.5q94 20 187 20zM1664 1152v-128h-256v-256h-128v256h-256v128h256v256h128v-256h256z" /> +<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf0da;" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" /> +<glyph unicode="&#xf0e1;" d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329 q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" /> +<glyph unicode="&#xf0e2;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" /> +<glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14 q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28 q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" /> +<glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5 t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29 q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" /> +<glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5 t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" /> +<glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5 t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129 q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" /> +<glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" /> +<glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68 z" /> +<glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69 q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" /> +<glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47 q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5 t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" /> +<glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" /> +<glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" /> +<glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" /> +<glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68 t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252 t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" /> +<glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" /> +<glyph unicode="&#xf0f3;" horiz-adv-x="1664" d="M848 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1664 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q190 161 287 397.5t97 498.5 q0 165 96 262t264 117q-8 18 -8 37q0 40 28 68t68 28t68 -28t28 -68q0 -19 -8 -37q168 -20 264 -117t96 -262q0 -262 97 -498.5t287 -397.5z" /> +<glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f6;" horiz-adv-x="1280" d="M1024 352v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM1024 608v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704q14 0 23 -9t9 -23zM128 0h1024v768h-416q-40 0 -68 28t-28 68v416h-512v-1280z M768 896h376q-10 29 -22 41l-313 313q-12 12 -41 22v-376zM1280 864v-896q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h640q40 0 88 -20t76 -48l312 -312q28 -28 48 -76t20 -88z" /> +<glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5 t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320 v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152 q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96 q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q261 -58 287 -93z" /> +<glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" /> +<glyph unicode="&#xf0fd;" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf0fe;" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf100;" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" /> +<glyph unicode="&#xf101;" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf102;" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf103;" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf104;" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf105;" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf106;" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="&#xf107;" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="&#xf108;" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf109;" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" /> +<glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" /> +<glyph unicode="&#xf10b;" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf10c;" d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103 t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" /> +<glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" /> +<glyph unicode="&#xf110;" horiz-adv-x="1568" d="M496 192q0 -60 -42.5 -102t-101.5 -42q-60 0 -102 42t-42 102t42 102t102 42q59 0 101.5 -42t42.5 -102zM928 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -66 -47 -113t-113 -47t-113 47t-47 113 t47 113t113 47t113 -47t47 -113zM1360 192q0 -46 -33 -79t-79 -33t-79 33t-33 79t33 79t79 33t79 -33t33 -79zM528 1088q0 -73 -51.5 -124.5t-124.5 -51.5t-124.5 51.5t-51.5 124.5t51.5 124.5t124.5 51.5t124.5 -51.5t51.5 -124.5zM992 1280q0 -80 -56 -136t-136 -56 t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1536 640q0 -40 -28 -68t-68 -28t-68 28t-28 68t28 68t68 28t68 -28t28 -68zM1328 1088q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5z" /> +<glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" /> +<glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" /> +<glyph unicode="&#xf114;" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" /> +<glyph unicode="&#xf115;" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z " /> +<glyph unicode="&#xf116;" horiz-adv-x="1792" /> +<glyph unicode="&#xf117;" horiz-adv-x="1792" /> +<glyph unicode="&#xf118;" d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5 t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf119;" d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204 t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf11a;" d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf11b;" horiz-adv-x="1920" d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150 t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" /> +<glyph unicode="&#xf11c;" horiz-adv-x="1920" d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16 h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16 h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96 q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896 h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="&#xf11d;" horiz-adv-x="1792" d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9 h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102 q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" /> +<glyph unicode="&#xf11e;" horiz-adv-x="1792" d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2 q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266 q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8 q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" /> +<glyph unicode="&#xf120;" horiz-adv-x="1664" d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9 t9 -23z" /> +<glyph unicode="&#xf121;" horiz-adv-x="1920" d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5 l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" /> +<glyph unicode="&#xf122;" horiz-adv-x="1792" d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1 q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" /> +<glyph unicode="&#xf123;" horiz-adv-x="1664" d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5 l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" /> +<glyph unicode="&#xf124;" horiz-adv-x="1408" d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" /> +<glyph unicode="&#xf125;" horiz-adv-x="1664" d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23 v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf126;" horiz-adv-x="1024" d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5 q-2 -287 -226 -414q-68 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497 q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" /> +<glyph unicode="&#xf127;" horiz-adv-x="1664" d="M439 265l-256 -256q-10 -9 -23 -9q-12 0 -23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320 q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18 l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9 t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" /> +<glyph unicode="&#xf128;" horiz-adv-x="1024" d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5 t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" /> +<glyph unicode="&#xf129;" horiz-adv-x="640" d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192 q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf12a;" horiz-adv-x="640" d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" /> +<glyph unicode="&#xf12b;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1534 846v-206h-514l-3 27 q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5t-65.5 -51.5t-30.5 -63h232v80 h126z" /> +<glyph unicode="&#xf12c;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1536 -50v-206h-514l-4 27 q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73h232v80h126z" /> +<glyph unicode="&#xf12d;" horiz-adv-x="1920" d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" /> +<glyph unicode="&#xf12e;" horiz-adv-x="1664" d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5 t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89 q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117 q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" /> +<glyph unicode="&#xf130;" horiz-adv-x="1152" d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5 t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" /> +<glyph unicode="&#xf131;" horiz-adv-x="1408" d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128 q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23 t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" /> +<glyph unicode="&#xf132;" horiz-adv-x="1280" d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150 t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf133;" horiz-adv-x="1664" d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" /> +<glyph unicode="&#xf134;" horiz-adv-x="1408" d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800 q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113 q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" /> +<glyph unicode="&#xf135;" horiz-adv-x="1664" d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1 q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" /> +<glyph unicode="&#xf136;" horiz-adv-x="1792" d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" /> +<glyph unicode="&#xf137;" d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf138;" d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf139;" d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf13a;" d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf13b;" horiz-adv-x="1408" d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" /> +<glyph unicode="&#xf13c;" horiz-adv-x="1792" d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" /> +<glyph unicode="&#xf13d;" horiz-adv-x="1792" d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-13 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352 q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19 t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf13e;" horiz-adv-x="1152" d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181 v-320h736z" /> +<glyph unicode="&#xf140;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150 t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf141;" horiz-adv-x="1408" d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf142;" horiz-adv-x="384" d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" /> +<glyph unicode="&#xf143;" d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 232 -177 396t-396 177q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128q13 0 23 10 t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf144;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56 q16 -8 32 -8q17 0 32 9z" /> +<glyph unicode="&#xf145;" horiz-adv-x="1792" d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136 t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" /> +<glyph unicode="&#xf146;" d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" /> +<glyph unicode="&#xf147;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5 t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf148;" horiz-adv-x="1024" d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" /> +<glyph unicode="&#xf149;" horiz-adv-x="1024" d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" /> +<glyph unicode="&#xf14a;" d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5 t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14b;" d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14c;" d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14d;" d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q10 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5 t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf14e;" d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf150;" d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf151;" d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf152;" d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf153;" horiz-adv-x="1024" d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9 t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26 l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" /> +<glyph unicode="&#xf154;" horiz-adv-x="1024" d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7 q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" /> +<glyph unicode="&#xf155;" horiz-adv-x="1024" d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43 t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5 t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50 t53 -63.5t31.5 -76.5t13 -94z" /> +<glyph unicode="&#xf156;" horiz-adv-x="898" d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102 q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf157;" horiz-adv-x="1027" d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61 l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" /> +<glyph unicode="&#xf158;" horiz-adv-x="1280" d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128 q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" /> +<glyph unicode="&#xf159;" horiz-adv-x="1792" d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23 t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28 q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf15a;" horiz-adv-x="1280" d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164 l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30 t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" /> +<glyph unicode="&#xf15b;" horiz-adv-x="1280" d="M1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h544v-544q0 -40 28 -68t68 -28h544zM1277 896h-509v509q82 -15 132 -65l312 -312q50 -50 65 -132z" /> +<glyph unicode="&#xf15c;" horiz-adv-x="1280" d="M1024 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1024 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1280 768v-800q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28 t-28 68v1344q0 40 28 68t68 28h544v-544q0 -40 28 -68t68 -28h544zM1277 896h-509v509q82 -15 132 -65l312 -312q50 -50 65 -132z" /> +<glyph unicode="&#xf15d;" horiz-adv-x="1664" d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23 v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162 l230 -662h70z" /> +<glyph unicode="&#xf15e;" horiz-adv-x="1664" d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150 v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248 v119h121z" /> +<glyph unicode="&#xf160;" horiz-adv-x="1792" d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832 q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf161;" horiz-adv-x="1792" d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192 q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf162;" d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23 zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5 t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" /> +<glyph unicode="&#xf163;" d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9 t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13 q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" /> +<glyph unicode="&#xf164;" horiz-adv-x="1664" d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76 q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5 t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" /> +<glyph unicode="&#xf165;" horiz-adv-x="1664" d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135 t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121 t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" /> +<glyph unicode="&#xf166;" d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 16 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15 q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38 q21 -28 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5 q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78l24 -69t23 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38q-51 0 -78 -38 q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf167;" d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73 q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51 q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99 q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-37 -51 -106 -51q-67 0 -105 51 q-28 38 -28 118v175q0 80 28 117q38 51 105 51q69 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" /> +<glyph unicode="&#xf168;" horiz-adv-x="1408" d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942 q25 45 64 45h241q22 0 31 -15z" /> +<glyph unicode="&#xf169;" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" /> +<glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" /> +<glyph unicode="&#xf16c;" horiz-adv-x="1408" d="M928 135v-151l-707 -1v151zM1169 481v-701l-1 -35v-1h-1132l-35 1h-1v736h121v-618h928v618h120zM241 393l704 -65l-13 -150l-705 65zM309 709l683 -183l-39 -146l-683 183zM472 1058l609 -360l-77 -130l-609 360zM832 1389l398 -585l-124 -85l-399 584zM1285 1536 l121 -697l-149 -26l-121 697z" /> +<glyph unicode="&#xf16d;" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139v1142q0 81 58 139 t139 58h1142q81 0 139 -58t58 -139z" /> +<glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" /> +<glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf171;" horiz-adv-x="1408" d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22 t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18 t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5 t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" /> +<glyph unicode="&#xf172;" d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5 t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf173;" horiz-adv-x="1024" d="M390 1408h219v-388h364v-241h-364v-394q0 -136 14 -172q13 -37 52 -60q50 -31 117 -31q117 0 232 76v-242q-102 -48 -178 -65q-77 -19 -173 -19q-105 0 -186 27q-78 25 -138 75q-58 51 -79 105q-22 54 -22 161v539h-170v217q91 30 155 84q64 55 103 132q39 78 54 196z " /> +<glyph unicode="&#xf174;" d="M1123 127v181q-88 -56 -174 -56q-51 0 -88 23q-29 17 -39 45q-11 30 -11 129v295h274v181h-274v291h-164q-11 -90 -40 -147t-78 -99q-48 -40 -116 -63v-163h127v-404q0 -78 17 -121q17 -42 59 -78q43 -37 104 -57q62 -20 140 -20q67 0 129 14q57 13 134 49zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf175;" horiz-adv-x="768" d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" /> +<glyph unicode="&#xf176;" horiz-adv-x="768" d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" /> +<glyph unicode="&#xf177;" horiz-adv-x="1792" d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf178;" horiz-adv-x="1792" d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" /> +<glyph unicode="&#xf179;" horiz-adv-x="1408" d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q112 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65 q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" /> +<glyph unicode="&#xf17a;" horiz-adv-x="1664" d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" /> +<glyph unicode="&#xf17b;" horiz-adv-x="1408" d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30 t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5 h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" /> +<glyph unicode="&#xf17c;" d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-7 -10 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7 q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15 q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5 t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19 q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63 q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18l-4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92 q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152 q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-14 -1 -7 -7l4 -2 q14 -4 18 -31q0 -3 8 2zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5t-30 -18.5 t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43q-19 4 -51 9.5 t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49t-14 -48 q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54q110 143 124 195 q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5t-40.5 -33.5t-61 -14 q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5t15.5 47.5q1 -31 8 -56.5 t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" /> +<glyph unicode="&#xf17d;" d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81 t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19 q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -6 6.5 -17.5t7.5 -16.5q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6 t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf17e;" d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5 t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5 q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80 q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" /> +<glyph unicode="&#xf180;" horiz-adv-x="1664" d="M1483 512l-587 -587q-52 -53 -127.5 -53t-128.5 53l-587 587q-53 53 -53 128t53 128l587 587q53 53 128 53t128 -53l265 -265l-398 -399l-188 188q-42 42 -99 42q-59 0 -100 -41l-120 -121q-42 -40 -42 -99q0 -58 42 -100l406 -408q30 -28 67 -37l6 -4h28q60 0 99 41 l619 619l2 -3q53 -53 53 -128t-53 -128zM1406 1138l120 -120q14 -15 14 -36t-14 -36l-730 -730q-17 -15 -37 -15v0q-4 0 -6 1q-18 2 -30 14l-407 408q-14 15 -14 36t14 35l121 120q13 15 35 15t36 -15l252 -252l574 575q15 15 36 15t36 -15z" /> +<glyph unicode="&#xf181;" d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408 q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf182;" horiz-adv-x="1280" d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43 q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" /> +<glyph unicode="&#xf183;" horiz-adv-x="1024" d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" /> +<glyph unicode="&#xf184;" d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf185;" horiz-adv-x="1792" d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4 l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94 q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" /> +<glyph unicode="&#xf186;" d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61 t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" /> +<glyph unicode="&#xf187;" horiz-adv-x="1792" d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536 q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" /> +<glyph unicode="&#xf188;" horiz-adv-x="1664" d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207 q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19 t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" /> +<glyph unicode="&#xf189;" horiz-adv-x="1920" d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-78 -100 -90 -131q-17 -41 14 -81q17 -21 81 -82h1l1 -1l1 -1l2 -2q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58 t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6 q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q17 19 38 30q53 26 239 24 q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2 q39 5 64 -2.5t31 -16.5z" /> +<glyph unicode="&#xf18a;" horiz-adv-x="1792" d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12 q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422 q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178 q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" /> +<glyph unicode="&#xf18b;" d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495 q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" /> +<glyph unicode="&#xf18c;" horiz-adv-x="1408" d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5 t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56 t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -5 1 -50.5t-1 -71.5q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5 t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5z" /> +<glyph unicode="&#xf18d;" horiz-adv-x="1280" d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z " /> +<glyph unicode="&#xf18e;" d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf190;" d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf191;" d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf192;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5 t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="&#xf193;" horiz-adv-x="1664" d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128 q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 16 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" /> +<glyph unicode="&#xf194;" d="M1254 899q16 85 -21 132q-52 65 -187 45q-17 -3 -41 -12.5t-57.5 -30.5t-64.5 -48.5t-59.5 -70t-44.5 -91.5q80 7 113.5 -16t26.5 -99q-5 -52 -52 -143q-43 -78 -71 -99q-44 -32 -87 14q-23 24 -37.5 64.5t-19 73t-10 84t-8.5 71.5q-23 129 -34 164q-12 37 -35.5 69 t-50.5 40q-57 16 -127 -25q-54 -32 -136.5 -106t-122.5 -102v-7q16 -8 25.5 -26t21.5 -20q21 -3 54.5 8.5t58 10.5t41.5 -30q11 -18 18.5 -38.5t15 -48t12.5 -40.5q17 -46 53 -187q36 -146 57 -197q42 -99 103 -125q43 -12 85 -1.5t76 31.5q131 77 250 237 q104 139 172.5 292.5t82.5 226.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf195;" horiz-adv-x="1152" d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160 q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" /> +<glyph unicode="&#xf196;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832 q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="&#xf197;" horiz-adv-x="1792" /> +<glyph unicode="&#xf198;" horiz-adv-x="1792" /> +<glyph unicode="&#xf199;" horiz-adv-x="1792" /> +<glyph unicode="&#xf19a;" horiz-adv-x="1792" /> +<glyph unicode="&#xf19b;" horiz-adv-x="1792" /> +<glyph unicode="&#xf19c;" horiz-adv-x="1792" /> +<glyph unicode="&#xf19d;" horiz-adv-x="1792" /> +<glyph unicode="&#xf19e;" horiz-adv-x="1792" /> +<glyph unicode="&#xf500;" horiz-adv-x="1792" /> +</font> +</defs></svg> \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.ttf b/src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.ttf new file mode 100755 index 0000000000000000000000000000000000000000..e89738de5eaf8fca33a2f2cdc5cb4929caa62b71 GIT binary patch literal 80652 zcmd4434B!5y$62Jx!dgfl1wJaOp=*N2qchXlCUL1*hxS(1pzUj2!bdoh~hR1qKGRh zwYF;1y3o}w_SLrdruJ!H7kRd|tG>S2R@?Wq7TP{rA#?eEf9K95lK|TG|33fEKg+%6 z+<Wf1XZfAq`R!L?k|epLtRzeQbLK2xcv17+D{$pq{72``nmvboTT&#6S&)yNwXC^i zKi?HZz8?Ah3%0J?_QNgTl##zplK2%H*Il^{*FBOX58-Utc*!*v-8gl_rzJ^IBv$s9 zO&iu-D8Etp8Hq*zhWqWCaKU-A{*J^dCn8_BY3uf@1Mj+Y<d;j5Ht&+lE?9S{bA47~ zwVy<tO<UJpy^X!gqY_L00OezsuG_j{>hTSaAdmL)uWh^R%I%Bq{=#vIHGE2vyyxxQ zu>PXwf4+35#HOMTl7@fkt@MNGkN*dqzrXxudarck;ms?=9TzfXbVcIGGxh+E^d!f> ztp1kWBdO@h9ZD<md(AVyQd%YQxODoTZP#3JrIe9k|BD8kL=g?$!AZ2F@I*}HFpii7 zjJtV{U4k5yib@JwjPqjDqGEJo(tvbG`n>cN>E)O$)*L%OUQ<(5(?2L3bseob+I4i% z(X~e}J$l2@yN*6`^z%o*bo9v4Umbn#sBz47tm;_Pv94o_j;%d*>9HG*-F57d|CLTs zlc>gL3N=cjYLt$8j>eB>jxIjhe{|c??9qFU4jg^<Xzu8%M+c7{JtiIV9E%;Bcr0^l z@v;76+m2<A-9t5={LRS=Po8)3+>^^s&K$J;*W3T~FTeWV|2+Pm&&ML33QxpS<_UX3 zo}ee-@q2t8ugBw&J>0`QlKZ6FaOd4a?i23g?ho95bN|)-zJuoA|NMsm7K+s}nqB%Y z{lQI|ivK_S=vvsKmRk#edAb%6i2hSQfN{*f8@=C#{(3MdvZPB=N8B5iy>ag#%Ndz% zd|;azJHAbmj*E8`hfQQA(J-EOQqrDKvr;880iAi{Eunx`8?Q;WwYSE-ESYZWVy*F( zDyBWrn7@r>BFSWAC`(6{$=}vkS07fh;rcptPAzWdrDR(Yf3n1{ZmbPgSS%G{s_+g8 z?`TBE8*uTOCf?S?TU)|jb#%6^y@R#4wuCfk)~1cCHg1}Q(}asx<VR<dRdUARsqa){ zCk9#;H3ox?i!Q_|#moPYpIUlB{!VqP4M?DqAOvm5q7AwfN9SoB;-8_bH7SNeU6Olz z?R7CF<O^aLLQ2;7z_`o!fa&ZCS?_CWuQLvP`Hj1c6NfLm>@ZVV6;lsib{$)h;3&X! zv#^nE>r1k8t{W+F*<s_v-EVx^IFt||c`~a52}luXy0lP|5?)PLbQf>LfUs0DkxY35 zA&hmqcN%Y!F$Y>O5DtZ_l&QR>OYUgz=wcmSb8^yNnjQ>PHkL5{@<?lD>qN#TZq2kl zV*Di$^E=g?)6Z1RVL6_0`tSSJtJ;*Bj-~)(fu@d{DcY;wYCkW#w&!@JXYJY^HP^E? zCQEfyNA@&MoHS`-<DMf`b$Q9@_bc_>XZ2cas^9s{_6MI-Cq)uIUm`L|ee%J^d;3q| zxwSnC)nU#t^(_m0Cn*@xCMAs)wp8(Omy8LeF_j-`^X2cc)%HzmHU_(Hx@>V>-Qvq` z>KZiO%HNyy@l}?(^Dn$><{N)&oS&(y%gk^5+Z+G+R{j~Y?$2TF2BjKgP>~<i(Yz&8 z908ymege~ugulHd>{l@+5#xb#STNuZ8r?=WCN#*;G43z#WbeP}pXPs)z27Nc6N(s* z7!KVTtaQBluA?%jx!7OW`ifw}I-h-~p~09u-%4wQ;KqEnm7v$k5_U|!oKTDHICC?U z%UO%D>hNJ>6>FK#cCl;NcSO4y&fF{>U=3aD2IJ-~<7dX|?|etL6`R@eA+4k~0<tmo z)lv#jRe+GTE|tc=g%(;Bb{;L3^t8v+?15{B4qkIW560T(Y?yBCS$50bTbA`$r*D|k z9t-M5?oH#xH{WDkyRY8A|LXLH9T%QIv%WFih`;)o=U=#EgZw-5{+p6yr!}S1d);_* zv(zn}C7mx_Cfz9AEj=oIL6X#TTe6YWXq7Awn#usyACYI?wxodi!ZKiE%Ab<|i1Hux zzOjpmWs?zs+0JlKq+}#75$cn1973*GP%U}VKzgLqN7adC_<>kR8WvKfSYMJobh>0d z!tvr{#Gs=xQsl%)QZ6lGj9fo`g<n4|-mQv7EH)y6Ba8D%*jnrbMRZe62orllG5=Bb zWvQ>tklOnC+PFB5q~+|H?r@3FXkQznBmY53W~ekX>W(B9tH3|SwvWJ~1XLheJ)N0I z(>o?V_Wu8Me(d|W)LC!j>N`8@S%!`yX`U_3<wxa4-y5C#u#%-UvY2=+9oWx@llhUP zJd!NAT9Q0{fs)EhN*&wm7`*U*J_~>UsHzz6Au-Z2`g~&4=#RcvTJE15t5HKCG3gq~ zrQNE0NeW>%!QQ27HO-7A+qxMxD=QAwOuIFjAAehPar8FhU^GezmgM(PUjEZ!aVvTo z+f4ar)c6Iz7iCcIr6=E0eaZm|+(=!(&9s`76^CY2-C-SFe<+|^nd%cY8^1JuY1YJ& zNEP13l7-rTiL2s0XS!=XLA99lj7d|~VsD&<y&3DO(LB^7r!(x$wBn`$ZR5}qs$|%R zz$ggHOTv;oE#;+1e&?Xy39@AnB*;i|6g}3PJ`+902TysDDtWtvNPBK`?-_`+(muJR zumt{c3@-Tl+Mmx+(>Yr5kF;8J`tNS3Nt<LfP}Wj|lqSlEYf21sY`V?Y(H;tiG~I>P z3km=mX{w2Vehi0vgtJWyPIUIJBgSuye>Z-6WY=Q{8ZWMnxyP;FvgG!|uO7aA$(Hrw z+_CD-;|@HQ&-QKV!ynInl1lD6!lIx2D(l%Ab2W~;IJV%Y*K9&@JhkbXpDu`9Jg(6d z+iJYP7vu#V=X4}m3WTqqe@p2FDIs8{2q`V01X>50LF_ODG-LDB`qKNS<Rzag=kkdI z%l>2O{^EnaD-4lj8PxQryhw9Ovnz(^<dW$U`_pleQ7KcP6)_*cd%AQf@@>f)Ef8uU z2*Uc*F(U!YNG;Z=rsJ1-f#sUgX(1$2M8Sf-$E7Al%LWLdqj<FySfU;DzgR}qEEMhl zX${VR$Z8kUL)BnM6zSk=2M@l+4|*KW`vbM}Y}Sf<LJrsM<C{HBz4BMCAd60FxYOo# z*>6bc7WX_~h3j9O9*_O&uJZbsHf!YGkkdK3@Lg87({WRsC>(L4Fb~li4zjJka)fxa zJ<+n#5wRuivR)E)-_{cKI=|)#Zn4_0Xty~X_TcLBmPr*n=oDp}nkFxCIBd?kyKP%a z3)^<KT3lw~iBS&G6o9!v%bNT6RB5KP5wJaG*1<N8f`YMmKltB374fZIjKwj!aZOhR zq~Sr6fGJ?7);LC;IH_ue0|)eoImLmUA)Ot{y4<pyk=?F*Kg&(jZN|54x_p_>)xWl9 z2=r7xK?qCFaWA6%eUW<(OS^n>tOSf)XGrI(<gX0%0p`64Wx)<B=hg?%kfFY1*X&p( ze@!&)=|o#w;%Ndm@Fo!q*hQ)=`NjGdT|>tU^jX@<LLC4!Ko@p~6u}yC*8rsgJ`Q@r z;9^0o8rhSexgtr%yLmVJuP%#Ic3Sd%`96okY3Z_X8~=~k%Gh7TVtU=idCZ8RaFz&N zHpmplerY86j0IM%^BMVnwJ>g7V5_k36_LmfzD;9cZ2Bt60U(mW+|v56fMdYE1^I$# zYn;WCDXavV<x=W046x2BlF?t^X-GWFuC_Uh?>H)nd^#bB7oM%}kFw5ay^Kq2z{plQ z*kp&z*ff+Sx=PK|ch*OZe~<Q??-pw_fc<B@2~qSebB6*qO~^*_G_jbAd8$~fUGi{X zQwRkh6Oe&OOpGunCV>qcIBxv>_<;k*S^aT##S!CCW3BP%kt1v!dz`J42aRDEB3Q^9 zD21}(34VTQ(IZF1Jhn)Zz6j{i3uu>ET5e**HtBLu3lZPM0<{ndq;MH6#$^pcf*PO; zMvz-W$VC(*%z=WTFr*hN%2>epb!UK;F`wfv4j+HNDW7rrSOAxeqqrVmK4(7D6k(59 z>H=&TuDEgKDHL&|2wN7Yv#`e^JgPA4Vt%KQQyd--xMIJPNp#^Pj`Q2Qlz>0#cjjo8 zb50~ryxS#YuAmFBly%H=0<sRNu7C@RXaA^~4u@L0Y4x#?PIL@Q0=>lx0*)XAQmQFc zVkB8gwmsEZe;gBw3IE}(Q$9K6HufsO;~U;;BjaoL8JTLYcN~)dnc$I_H0~)Ok20lF zEH*-E-`3fATPOE6R2mt-pXDkWQY<G}t4s;3lu31h1_0ewXxCKmr~*`iUPv`~0a&`2 zC#jUci_&j1zGW}78#%Yd63U5%gE9KSFw7h{a0=A$euu;OmetBK9)Exl+_;PZA8#pv zw8N)>&S}~TyokXyw@6buLX;*ub6eMzw9v-7(QKA+|L8-TdVjzepa!yjpUdH3-BzoS z^RN#-q^Xcm5ON2MJ89*!I0RmDT*l@V565YbFRc3xzln{*{*Zi<O=B{9EkErwoY=JU zS%&u~BgcWL%HOl4BXTB^w!K%*GqO!)M-2~m@Z94@6-^@hb=P!WUtUvFp8xsuk}+~i z6(k`cI$UhJU}HPlF*avd_R2skKj?;tI~I#q^Vo+jdj8}BpOLd#{0W{-_<epO_x%rB z^^9<#z(>$V6!2au+0Bx*H7*XCt+j>rd*JFSa16?@c(S!c!QKzj4ghXs#(BNfx8MKW zBJs8JwfVZoW#4CImaWG3K089H-N*b}ZU%&_l97od>r+*??<<gao6fg!>+P0u+n#%g zsAHWhdSusS8*aiP8m2FSuj{0_Xk|d>QoN=P1j~p30GtQ5S<zUrEQ$*o{0+J?Oy^8z zJ}EBR-V#!O$1=ty<GlmMAGh4($MTHO%Jc7=`;~Qje?P}Q4&dnYms9_672PXb{EpK< zgFVFj2UuXs&3KFrs@(XC@#RY|y2)==k!<tt>zQ}+72XTOe%Vit<I3&(%nMGPIoLvU z&7UMtB#qdqJSxeq3S3NaXJ`qf$55za^J6#!QNFmd5Me>(OY{CQQmf*S4a-!rCL=&B z(CJbN?hlE3G6w2QX%r&SuPF&0CF^DV!xjJeG^zaQE{<Hwx60z7p&Tk#7M2Qu#Tr+# zfEOL|K#9e{bwGq&x~mf}i2av1!4Q@+k*sp2$aKe;g>7S&Sbe7~<u)HYxY-!Y=Lper zp!?j{n8o<p*K(Z%mze?|;gvcBTn-~V5Yg>`Fyx7<ZsN5yrihr<Inm4@nOlWG6mQRn z!Oiq;?p1T;6+e4u`t@t}&(9f0y`D(2IymLs=eK<QhGa|ojpr?MMv|&DFL}a6<Ei{9 zIWOJYyCbibSGcy1ZySHWnvC$bV_{e2)l;VW$F+?k0K@tQzN4||r53t52>${c(L58e zQHg&n=5!keg~5Y?YTC|+Ni!3LPbVIMqgMshgqEEacs{gm<p`BJ_o|v%mCr(4{3YXO z&sNT=xoYmny_Ney&j+UM9b|2+kF^c%<+nd||D^b`EiuB~f}e54=1y~*zy5xvee#pW z@%z`G@0d1M+%*Z**p_ASN%ueXF;@1<u3fJfzc>38lO<&kG^fB@*scroW@{W9O-ROG z?Ki$`92a<4V+*lVm4Oqq!r4Ns(=2x7h2|P0c!?=lQP+gi*9Iv8O(X`OOKxkDF*?Ne zobDYgd-fcgJCZD`sVSrXWW;TobD9?$z6W<l)kH<GGFaX;tEn94ii8U46lx3L<mWMG zbJ4d6(tK&lKhh>_|Am$cJq`G6!Mus~mfQn}2SD_BIBt{9=O676JNwgjI2{$qRA*qp zvSkYbovCER>AZt|+W4^(V4Bja^`^ROZ@>N8x+WyW%^&~$qtIa-G4fN@WF!@+bhkh8 zwI|x$m4OtXf9h9_Hsi+CxKkHaoJx6QHS@3*=2;ynM>brCBC90_4WiIPkRH+w+RqOe zN(FF1EwlrzVyy;i(|-KN@y|g0(=VMF60C3?yj!}~TkDMnThnx%epwbjau%!?u^sde z<vNZhrF>S&;zAY~an5J+Sao@ENtSReJH*(HOgzJIJ)h-SLtH00GoIooB1?3c{;3Nd zItcmYsr^Vn(q;B#D)b#vYpu7{|Nr8@8$Yqw+Un|u@z>RLLv?kx_<Oj!8-F*5zqQ@n zhu5y9V%^<p_V`WejsMg?;UaTSe?WZ)X`M8_!!n8jMFb9_xDA0UVmTnk-p$HY2_u+l zODFQ_WEyh$fpj*>zn@U-bhFpUq!UIUk>Ec_WYcV*tuLL-w-b>i$yiSh=vxZ!f`sbB z-=>;v02>IL2n8amC4Bu+tzcQvxVok)_R|ElFq<CyJKBfdpwZE4JcO6=?<Lb_vt`K! zy6hUXdAW3<v>g}#JPB|&a9k?c0rhlyvZITWpoS78Q5&7WEiJ5reQ7B^2Lk}GYoL%= zdn%+7>()ZDog}I(uyQ4NZDW1N_=Eq-8ABTu-W@FqX$*TJcLcTYc#EuZIVuOoDNI+C zI>q0tFbn6dkY@2Z{egH2Qe!9oV8P;$@m}5B^M*cAVYl1Lu9iPh*=}Lub)G!&2gTvy z{mybFh(vw>iA|?mQEDd78@ej9V#}hL)08Hcr9!g@Ds0IuNn5?eUZd4*tFbnz&RR9H zBWbC%S^^P^BN0!PhnOZ?w=EdDYUgaXr(#ZZM1DO~>#m~xQcw#9Q43}gLkhU~n2-ZN zSIk-<ga{TkY!XyJTwwws_G{&ia4?=q#r@?IYmK?a+`48nAB4?;)!A8d{I4~gPD_kE zW2}r*UbP}GR6&Hxvts|1ftLc(GzdveWFq7~@ggXa3Q&lwO$v>+8nHbWxKE<L1*gY= zeTMKqP~S-y$7DnyST<>wL8t%nvp~o20mvgBjMit)x|{(&v217kK;Gm%Ge*DDkEd}3 zEcC!xm-842CmxLU*PoOw7i%S}X9dq3hdfu3$P5EU7$6d8bf|e|%Z9~Ok|{^`$n)Pj zbm+Z9@*t5+$Fp=CZ1rzQb1A*S-<sbzBKem4QSQ)teEz}BL!z9F<871X&Yg7Ii7Xj9 zn05?!IcTin_*tbTm?ar335g?FE$v_U^|PrAOd1IxM}8rWgebGN#?48;(b3-4%oEta zg%txt|3Y3_lh8H(lTXioY@w?%HZ7em5Ax8IbAy5CA6Qv$+WyMMU}|zCRn`!4hMJo@ zHMV%$dHrW~{`(YVcc;UlHLo$cDtp7;$U-@o3Nqefyftx&{6nLQamLR-u;+wvmTvdB zJ#Bmwe=TUl{?u{NEmJnnTsq0(SF~UX?5f4W?R-K!>a;nkyjT2|&-h^`Q0)lX6-|y- zd2IoUi~3Kv3m6l4zz+$=258kmIHE^D78r%v8a=4{12SEsE6Br81A-H=yVLljW!mAz zZ!?>~I$A&okdQ`<6<~_!8j=WO#3+Sdi03dcjeVKjpH3tjrYu|h^nwZ|^TwVpeCh1v zpJ`hJI}?`wEuRox*yL5LTveEj*?p~5%N0oAuA89xRMrq!uySK#dh&$v<1*cm>%O>Z zO=Ym9XTkiNmu`P)`A_5S*wT4(F1w;<Z7gQH=X1uN-24^&=0~^n_BzMMcRjqmacIL@ ztL*Ssl=WoUF(%!=BBWRxGPf_&oQ$ywXQZ;Z`HC5Hwl@bRH(b2==DxGLI_A~YmAMs# zJ275jT|-=lF<T%>K@(28nZKh;Nq5U>8jB7UBSrvR=yRd(vYP`*;+HPhnDTHj9A0I9 zUwx&cqSImVx$JtSCuC{Z7`6G?^i)mH{qZ@BE4tRvo=G?yR%Lu>da}{M<xEE%jFoim zQ_Fl-zyF4p8*W)}!`aO54<s`CnIkiPNxDAB9`3%iB^lB<-{|5PO~1b~<ac=7)sx33 zzq7^o?j!F^&;xEwRVyp2ZH&u`lQV~2To=dD$BU&~B*`Dfq;|7#JREB8<}KkUt7bY) zDX2RE05!m8x>n7+e%c4ZViB0LPC|dWSDQ?y(zK%Ro0605Cgn)Hvx}3u07gM+AOX_w zkpve4C?F}UF31K#B<oqy9{AUr{a5~sC2CwzT_5MB$x>34<&_q<g*#pP+}j#!;x<k) z6vw1`9_w^h1ytD;xOCyXr&iuOF~nJL%Km^=wr~{>Dw-vEY2y_hr!QjHD)jLV?bWz1 za6@1U{(bSqi%T==jTI_t<;-KTFcx_@ec_at-z_(uUAC~DyA{sWb*Tr9uNWV{uPIfo z+dPWJHbKSg*(@$4q(rQ7Ptp;r%^hQ(?YewTNKu(qVYg1aDDIC`cv-_aCwL<Acm#h5 zMJlF-3b<*nkezIj_6*N~`jK;x{=4SDoAQ|JcFYunNXZIuaU5$G6F~?LEF5^;_Hbbe z*bA)d40EvY^9^gyGzUvRHle&Y2b#*cn1Pl*xQ1syeNzm=(C{G8aQt0k-*%dzcd8>p zzmL_AXI7`3hCXU58T#XYKJA3l><d0=jO;{c@ys36w6GW}6ZxpT4tdrGU=5QI7;hy> zv2a47oQfj}bB~LhhNHNbrF#mFIgz3RyXYg5{~xv6G>w$e7}0LgC>2Lx6(n*T$N%eg zkF|yPsQl>hE*<UCvBq`L;(vIg|E{tAs5XwhKeo*y@KOpprRjfYls{A^I95wdZ6gu8 zsXb~5jm@79-b>4my+5|EWAjXcl7&d<GaNMBKQ8X68K?hvN$JsdN=ucd2Z!rrSDr38 z^ylHL%1D8dtEYcV=={gvinBl{5J5|N9;mR0F8W7D<CM|K`kgMTF$m>J%nBi$iu?x{ z2ftGj%|0QHinvmm9w{RalF0@=9;Ji-BYRfTUkOT$Q~OxZF_@NeWa$HlDaDXu`|weD z)=wQ25=a-Cs2=)9yU343sRq+51u4TSMuiR~ojH9{&~~Dal923rLE_K^7Wz~a8B{Ww z&TvSVQjk&kjID=u<}*7F9oorrI}fq@d=(C7iiA<)ysDqw_f+xDp`A~%1AY}62U7+I zJ_z)c4!@QvsR`EvAJpCg_ASjYkl>ra5eYsTFHVL_xFce_d3M{twrvB-w&Pir8Q|b# zJ`f$%GU(}jrPh{;hYD`X!%RLWin5sBd4h^L6+99<K~|AH3Ry@>f}e!kWQ(MMn=A)U zAjLaUdayOf+CarI@Hn7s!Q!KRUdVeHI03TS2(c}z-&vjISA}eP{?|H=yh?9p14B8Z zUwtR>l+piGU3)tDP6DO2WaWVnm9mAX)c1`3p&T3FgXzRmY~aac@_!&z5qz1Tv31DS zMoCm$z(-h9LclJY#vtrq+_>M<J+Iqs+!tr#*)wdsT(IGgw$2$k9#1CYvNmVyYizvn zT7l;y`dugKZo*q5RN<o(;nMx2$(HXQqw?-oGN$s6A3Ie?Y3c<eH75ljSCv>>s!2{I zYjl@PtYN67JwZBoGJlc58$jk$C5K^&5nz>}sIJr~dK83K0HP*H>|Qfg8m}$UE<g9u zsI{f7)e^n*+{?8kEL#_6jq#4K#}n>|H?nvgB=pa{W}siM-Fvh3iT%GguL@o^=lx>; z6V@Be^{V|1{nP+slcg?c9$ID2rj*27hB}ykG-wld0`d<OdkORb`4bT+iz(MJ;WXa? z`ReTtZtv$(%xgUEjd|JHC5Ltn0sar|lr!D!FdT7Aa{0m`G89?cBLl>&8Fzg@i{<-` zL1oPvV{i>@@g9t_epJ)h&vV1|<p1LZvzDEQ%5{$y)o7Y&aI&`N1}AFq@K>NQK~+4u zhQ-!IQ42X9(Y%r_0<wihX;lIH7Q_jy@kzoqAB-1S92D0TdPeL>IOI3=q_E|S>6$+z zRy|qvcj=_bArOavE}&+MU6f8b{gH*8Hf>w6cfM%E;}8D9$coiJU>v@3=L9)yQ9L$V zX!5vPJy<(+(Pg(kw|M|4BjRUSKd&|N#eVvo6>6kLDfaTGew(w*W3jR~j4bfQxZLi2 z#<O8Nn4Fr8{d+nmE$?5vY{rySNFW##X)E^qM$C1yuuvS0EDF;qSg}(kmM|ImFZL<o zw+hyprQIE#QJYf+dsjNAHm9ZqemC@^vYs+yX<6B&I5VB!iqoZKe68_fv5V$Z+W7EP z8kkC(Y+<kA*)sNd@j#jJ0Uo7FXet?G6Ih~{&zZ;x+XUiE$RI&vXk#TlF%B3m?y{tA ziWBEZTdtTi;vI>5K?ckHqy#+;<l#`$P?8R?ZU@mSl77%1(71}*l%zav!?vB0{GorW zynpoDM1QgZr;!g*yO4LG4{(MNG?pp$A~9Hdhx}uIB;wCcu_`0B_li}$((i~I&qN%4 z{<77UUnMvPLAmBv*)3-MLY@x~j?wj>;WeUAdxtjswo~89U-m~%dGnMrGy#Pjk^B_V zmR$w8Wcg{@LX#u<sVy`6X;JCTe)P*9Q7vQoX}%4!F;czg>vigl>K^jWfHYOmA7YJe zI{s=n9uKP%!+c%7${C2Lxk$i?R2{*T*jEHkO?G!Cg*J>MOpPj0FU6f+*dItV&g76V z1b)pJ&Z!wP(E#rzjwNY&55X=l5!R#o)VENrBjrccGxDs4XEAo+;jV=ttEC<Saie{j zK7odgzf41ifuZ5U&=G{7!wzIEcK)(RVB~Pq5#cY}ti$ye;pCM1={2ObC26c_U89}$ zjTR`$M9*<hEoXi^n(-73li6YZl+9Y&7%@)8H8Hv^V;eEt-_rMv?(divp|j*6D{1f$ z1Drtl={J#rpio)KJX2>~7{vmN(Hc`<9+{#fpHLj)Nd9eTcO~l4NgU1bOrQL!VpqQp zib+yUYF})TFh>{Clp6kaemgWrcO<qXdJ_pF!ro3Gu_eLxn+K6GB1T1WGm>VVJ5D~Q z^rB8sKjecYq+-~LVDp})?U-<z(wjiNn-hJB1bf?vBocjfm(<}cJlB@W@4zcanZ@2_ zZ_&9onZz}!dt?oezEZ*lhwUB|rnxg>e;_|57^a!dOlcUVjWQBca@2J(2{ZyU8X`l3 z!ZKqBCZ5TXguooG(a*5PF(lMTyU2d2(5_-@PHjVp@6l=BYJ$lrZz=76qtMm1H8T=; zL)Zn0K6KS|1i=Ogr#OaMVYNs06d3hV8d164|J-wa|0;h)gc6YoBu~A<c8?hm_Q;17 zFI2#eoN;Wz!mf;33vwLfrD!XFfyi>$=ZzS1s)}zl0NU8}YaCa@jC(V+kyrbM#<WPT ziTcoV<KkbVH@+wsnuEZ^)xHH|+8}fV1)MfTnghyttlwH2l$k;dOsxT7g`FCEGo-sk z&p7PE5R=!Hw319tbHc2WERipJYQ>+k?(iPn;jyOUHEk1n>nC<!EJ`%SV>MH%%UO0z z>j#QY`}pTq9$fm9GT()oV^&#NTRhnmitd<MN0s}h`+dPl%?qZF>5??kC*r}T6#G;# zT{4>ua-y&#TH0ZnA=XK;L!+!AC74DR4QTuOh2bC?SJFX#O5+DyJ}yy7B#fLm`Q*Eh zF_YgK+uo5i(hMI&X~g#gMiv-qQ}zODLySC{h&;4W7<AJP2R7oO4DJt?#dAVaNM)ep z9WIOKP>1rlt+aHv#vZ#wET>Bzi;ca&u1rSmPQ3G&xc}HYiM#26F&DUrAx`u3aCK}v z5XBiDFVsi4Yh=C%cTL3z2uCAvAX#<F^f;=<iWVr?jg=c{Ka<_#`~$X#ZQni|4%q07 z)2RF_C6=D27_zeOp8lcXO3FXXFmhC13bxwh*hEAvq4#RY7(@@wXta5sv5J=WFa7?D zaE9$8ju-iNeOQzEkMRtgh($^92t7;2-5+AMJv`>O!28fAe3N0efEC^aMGBB5Io|*; znm#!N-*Pp!BJbKaaM^bcoHJC;|9tC{V5ij>OsjqaADrKikrhxvC#!sg?|y7=-hJ+h z1K<B9|I_LNL-#+<x{a5OUkm4(DmH~xQVP=yTeviEPp=e12GCm@H}_T{Un3iFARA&! zbuzHlq#14b3`-=Fy=3-4dm-PCeKUzo(0Co&;|y5Cq<f8DV!y=Zi7k_iBW_P77bG{M z0GYCZeoL#l!ux3dC4Uy;DnK=mG!#}~Vxk0RsOA#+9jUg~6zXS*e5P&2j5eM#UdQ{B zZRsT6pWvBx6v38^7qCQc8gFMwyj|?dwe-F;=*3<&LtgtNSHb&)pMXh%4R8NK@C1ce zFKQy+uwRO*L`P5+-w(AlQ58J>A#I_y(psW-K8JT^i~i=~ohErf-5MqY3uB9yQZHd2 zvjZa~Xp3ZD8@!%alE$wWbO-JULWg8MMCtqzV+|Kq%teyO5p!I#pgnWsn^55C(m=2- zc&&s31%G#_6ye;};fuGT2`1lW5MwsD{u3X+e0^7~s(RfXhwgC8H>Mxw-yH;Z#wB>& z`%#L>5l40V**gX{bj;Fft?q!=8o^Fk`P6szvipb<L8($2AWSq6wFHPl(1k?%7ndJN za53-Z@MH3UUNG|zzWv!|eB~aztYCe659<TwxIzx2Dfbv(p|s7$`ltjM{jxtqMEPMO zU@DK|^M&m%J%I8N@c@dTIiS&;C+}4MtX>KFk7%?rwBt<e7M6pjX~-Gc%`>NM2*2;N z&8GHYeSp@@0(J;^#d;j(7lv2JFaTl1RM?0Z{hjqWI5G4KuZ97UVXzgE$y@i7tD=12 zT^#R{O<qd8tGEWudQW7iLIstGnnb;@pJfv9pu|U!*I*SKK3ptCHu&b6QZ>_6XaY>I zy0Q0#)#3Ig+TkVzzd}|0UQ<OR6WQ2gye}Z#c)w{Q@)b?YhNO9m*~~>?E8H^PXK&+) zOL6<-#w)_ZyY=IE<Wk&!=%L~r)=GDbSBCGD?rp@YK!OOXQCLu#-Z@026M<eNJY+xY zF>nDis^28kc{4fX92q8$_?LW8qXYst__)tzbG_lR*${^0d6!=uONX5J;|nf-!1;nR z;Aa={tq#p%(H!~vY;JI`5@f>Qp(NlYC%k*B$?74I_QJLiviuMzi+0vZL^FH<;r2qr zb8Cy~r-q?6ndySL5uA8v{a|qk(va@Lkaobx)kSmBI-~R3H$)mSll<qM^^KA1U#w@( zf}k>ep!x+h^|kYM?>=wK^lWze7D}<NxqM&gWUu9N#`w<iiVAtdW7VCDJMmZj7-|JY z)o(%?JUB8g-|nyPUijpb3vu!h4^+@)1QE@F<jb`+3Z#SRk+9t8Xs>H+0pF!brYsPI zmJ3$apq9uww+rYAb{>=fIg39EKmqTa$Y+f=ezOaUzARX=Hn5NBUybl&pvidW^`8#j zf4loY*wftDRarGI;N=!s?pn|l<<=D+dtqzGSHAqE2U50Fpe9w8>W+D2*iv0^=+<Bv zuvOVw|8<*~cK-T7<HfC)G^-0TeVI_CQgLZcy>?;y6u&ad)|$TZN008T^SNbfDq%}` z!`3x>whKNF>jv^OH>^@6@(ZNtFn2F#qXGiyrouwdsRDzCQ&kG-ltwgcC#6Ye_4l7O zX{N$f-LY>~hnee<&D?;{A<#kbFWPh7vU&4XxAtclYgoShrq8Y~URir{;R+2o=r<a7 zB?}+0xI}?@k||()Nyx=vDFk2_b72b1L5;Sy0LN*#57gVyj&oScKKRyjGY-x4w;sHO z-OFBM_vW9A2Cn~dv_87)oPc~u;0_~||C5orBM`WQ{Q@@Wzqo^E-rce3n&&Cd&GXl6 z+VSoyfBrL{Tp#`N^?_(KaLz8{N3&|*Hr`>Ow`ynAzQsbu|GY)=^OFN;>mcZ!a(H*m zl+Fg^cfe||twYm&W80aacA6VEAOpqB7ROtJ7c0s7{osYbwWA#Qx&XvrY1RQkn>Q|6 zu^xSSn(rIw1-q49Y^>Ql$>wwH@{GUx*vdfQ<LqVTJa=`w&8J4{s^YRI@yN}r%))Yk z)SQFHj$bW!ja_`rl}~q{|Aooly|X*Fh5Bh2{L+zb{!!=O%sURB>zRXUduRN7Uv*#g zJIv!<=W)Q7hue&a``>C|?@!n>rzW%HvoGxNz4y&8U%4&wC9oPacOKx=qXM4d1X0-a zKLRJoFe@FlDg}-OM<I<UcY&3h_BZU#0#<@?Rc*pMwdS}~Gu4}@l_l@AIny2kV)DD_ z!1l23J9N8UcNrZvr&E6Rc(%K{vZkhz%!RA#>VWU@qh6w3BEioP=-Z6|I)(Xwx=JWE z8X376kOPuHLlCBjbXbK#M(rP;>3eKI^=5U4BD*!?zm0rab@p3b+-*HPWarF=w8md# zvZ1(OFP3$A_{RtOa%z8DuJ5t@Jin`7W3rPC8Tl8zu6`@G4;|J$PRBYcOT#KDY=IYY z)~P-^(3c^pAjN6ISe|NoO%~*2b$ym}CFFl`({em9<_syfuqYSThlMu<e2ja=@*QLD zmH426;~Qr8;=?I$eOWjV4zhl@FXfDZv1vXiu4m~8<8+jSp}HtJ;>3e8!`ERRiZnEi zMP$Jc5#>1f%D2H?2YMl9o^VB!WU&lY2fq~-8<JRz<;*j#@)(Pe*3uZnap-fR2pSqg ziQ&r&Pe@d?ieo?NX8O%zpJeW@SkLMpxR?&uqDruyYf^|9Ae4xWOwgl(8wOL;q@~(B zs+3k58KQ=LCKEs!2y6vd!Y)Ba6duJ!0Lg|nT$(>LZDFXYwY7KrAnja($5jo!gQVAv zZSGvv*4NV0Hl<=}p$K_k7u^e~$VqA9qG{vGVoj9|GpDaO@9J4*9b+yQpHiyVJU5|Z zUPGl2lMK0_{?0-DonuVaUE!Lh>8bO+BJN{DguAA^vsj>NT6a^|)}B>YFFvO=E*>6r z#Vn3-!@43p4A3EwrXWbbnrJF;STdDPwkK&1R68gfLl?uQsp!&C<HEnp>3!KaK52%x zLXlNwgU_NqG1yR6Wq<g&yN<HHul|L7Qf@LnW&GkZmM_e7SvbNqC?3TvySODC?rfS@ ze=gGw-u#EpZupEjZ&)cR(VDHob2u0fR8es!15H#VBXU?VFYGR`(-o!oM2(D=>c3<> zX3R4ldkN$@#175VmNt!RS~{)S%u>K3auYXm6bxx3$8*{58ZSKe9P9b6C;_NVh7=`4 zj1ZpS7mXAxeT)VU<CvCqXuV3W&}bKUJmUGmSQa?gFdOFVB1XjI55dj}?v(9-a2WjM zTM!c`dx^us9q?kJ-Zbj9lfFR6iVIA!z;dL{6Rfdd--u}(Vc*_{AX;#4GMpReGT&e1 z+)NoYI5xp6Vb9JgSy%&rH8$gJHObQuzJWAtqUj`#27N)gHe$m~i8W*y0<FONU38IH zrz$xL)}M5EDt3aQjK!`iJQqp2Sq3r7;E|h*<aowo9ng8!ZRB8{2j^m3%jf8t-zn#c zPhia}HqEOA*Z>;<$pz<`P{_!7K{Odzd(O@dmU)eAILyQ)mUZN;_K`=7elaJYN3f@5 z0o&xm4S7;s!3skuoXKlZSF7N+rh`~5z!4z5Lq^vHGgzgBaffH2xbNL8e_x!wA1goc zF4NUA`9XrCAt{m!CHNPAAb?8pl)LSU&Xg}kl4;>vBA)4$bB0uwkay{oWj4=5GN+HY zT4yP82a---bts`HX)S^l&tfe=*Dw~&q57mqd3)BJ$gJ73XAQ%V53JcE59CE&&e7Ev zOi7D#x&rn1rEw<InEN!%CJdKR5eq^UfIvQN!|O=Yudk>!o^AX@&xu@3x|%IUO3Bou zjYC7ZwMV8KUr<@$#WB2mUUjXpy>)J+s=Ailfis&jaQ-}FyQX-RlE#p1N8&l`h0w^s z3I;#~@E~+6q+!6!1ZE`S0hI9^1dUi~rRrPC7Sy%MFWV?!S&23m>sRP;@c@1>ek`L) za?X4gy@N11KzEb|8DMM59fZF4v=xqMgG*iy(!bC+ybB$I|0c~<agV3yahNq&&W!pW z9Sv@*pDYLV<=K&c*bX>HOntC<j>J_XS1*?35_xct%NR#)2>jcL0W$O{82u=(lp6e? zog*^kiBbmb({!kWb>iqClK~k^rzE7yuv-UW0liA65afU0gi`Hefe?YFX3Q#|F?;%& z71yda{rarR)y?S(=U0ZDk>HkD+wYB(-T(P*|8~cQN#ME1!JI<aP06quksm3y)-Oyt zd#+tk>DRZfYw5gVIxFYBJ6sl}dnsEbubsQ|6Ni@jtP>a?dFs%p_WOl2qN7$|owN|! z*9Kd~SdZQT)Qa%S)t#4q;lVw-cQcLMU)m79`Sq=nQm@~0=kC|@xA1G(`=xKw#hgl* zQ;M5Zf%m1LH|Rnuh=VNQTG|Wv1D4Zq$&-v}o=}X^avb2Mmxclm0wsCC=jvJOi~2h2 zU4MeN@WI!H4pJ;rC0mG7IP@m@0cJI6=-)E=>$Gfd`nUw+AIL=0z5Gj2-`XCcGwM4n zB6Q8ri&<FccfCmuD{utNU3GgldqO;*(oxL$JncU8BS=2)XuX(i>H}FSVPY}CB5Ejv zaXMM@)1;GB5-8n=Z5~%(3RHAety1I+Ow9ZZ;}(;t8J*>CulHJ0HH~ur8_`AM>ZAE} z&mMl_l^0mcz!R_RW*79!O*OIgUZ+i4y!_nB^0P2eTRg78kB7zCki6?-HBIzz{kTO@ z{^;&ko)};)FTC=^;b)D9`{hOid-1NfX$zOG>Ou3xT61Hq9R(iuVqR{P4ofEr{i4`J zX8+JLki&&(BB>SFgMxPoupc%l5H({176Bmw+e1|JcZVy&$P|MW;T@=v#)?KR1tdf7 z5iyX!d4OI4)kqsC#jXs6fpg$82Xh>hhanckEC2k%a#lc*d=TNRu)UZ^BkQt$!XB*Y z)b;RAzuk6aqTcS%!(X@iSh%L)D&1+f-J{#OJYmO!HrH^`(A8A5rm?iB#X&_K)7)V@ zit_9O4qvOXi(C3!fk433XW_e)R-fa62b|tkMd|7++-Pmkl&h6iuk(R_w0t2X(@8<x z1At+h1u7p2<DTc?X;D_&Fma~M=FqEl>Z|;YOPb5vwvXF_=jxVQDy%lwqR{wc8S~nQ zi`uOYOVw5SDxd3;rcp&beW8gpVeZWj-r;dqlwV%1$aB{QIS;O#D=WxWxIMU08KxWX zXFm_O<~Hy-bT3@#mXH23PZ9hI94u(;gpfyhC>TbHz>(l4i5RCOXd=-A#qPzz)IoMs zX#{D)i$kl8(Tc4DtYYm_xT9|x-}u*aR$cc{U5jk@b1(y3m0<``=cx?ZuDk1-Y&N@r z&F0hYy3Q7?^whyIg8VK~EZ}IVd+54V=NQMnJEiI|R=@rFz2Tb<%KMG~d3T>@WxW*~ zE$kUJMVGO8CWDFkvUxw+x&PgL`||s){^7i``b03PG2B!%O_yCBrd#V*diE%*majRw zcVX|`pAOUW*dBHGD{dW$nuAqZ8*c;hN!AW?SRe(^QxY?xUtO@Nq}xbzV2RK&p??j5 zg)vAYBtAJAfh_^uOD<@n426vX=&3g4sYNZuK!2t`QkG~4btuX5@pTO;#658)Dx1R- z)gSM^CZ|@_`qBY+tT8*ungo^m**ojb>;J~J+e5}6AzbFG+c0HPSvc94YF)l}&ctUo zJ@^z=o#ffpg;Tyib^Y4NRkt*TXQ?f*bZwn4pVf4?#mnbE9jWrnUl41VT|V8**3_N5 zAYQj{W-zp2;r_=aG}iZ~c{bf!w!1f7e$Ae7i5a)=IPZc70T)D{0=WTC>ySVp{<Xl= zCPu?3&<2d*pfMp?uuB!RQ<VyXKSU%ZJf2LGPc9KvG*klnkX0&vM;Igk4JnBA;P8kJ z4_9N%9Z36XtJL)?vb%o_qpIf0gfkZNq#EkRmnW5uP(z|Dg7IYiEsL@bZhCfNZSCIW zt*M%NdzpXY)D3mUdt%IDq3zihF5Y&>=h!qkX`Q5q$w(Sf?HcBtUOu}ewqU-eDsuMH z`P^%9>smhRtE)}NTGUzL##^q6tX)6#`%@OSY<%#7^RAjTdqyI@e%U#}mW8|FM@ger zKYsip`_zRSLcy5}>*5QD#yj~rIinJv4{Ga_;K_1kY_Mc?@c2uo21hPkmlW@LGHOF` z2EqNqc^3&8lo8k~z@ng4Nsvk~SBM3zWgBPqui13<hIwVaE??Qa4Oeek(?7HE8+<mO z_024TLHo`SCtCjOlI!L-d0H3FjD|wdnG0JzP4ll?^2|5#ukz+^K10ExeWwc}U1%>h z!x;FPdMQJ^S_oq6k(tH>n->Zuuv2)IETkU9EDskmwQfAind(MFEHdGw=vaj;NmW=3 zD9EeX6nVg(A0(5?j9_hYq>796E3sh2X_~{s#+)*1d-4$Vz>U$)TVRehNQ$wT$zZb> z$oKqU!6sh7x(w<nL0X%RR&On^p4hQXO#@kG)ab40+K>$GARxE3WmM!9;#~glyWhRf z=4_uocQTtgkI(<zfvazu&wnS&zti2*#&2h@l~Q}V_*Z}0HfvT}>+IP>PqVuodSu6j zp8OqbPtsRA>0y3lDeXr%T2hFfx0Ag-^rJ*dz)XrFmqEaQC{I{~DVfF*aNsTQhr~2` zfq@1=-QkaeS2dQka<79`sC~vIk>tY{&|W6ON48z?Fdtx$yugekgQM|zFte2oZv}fR z8M*c)E}8Ku4e2FJHrhid6nHd6F&f4a;$;7UsUJ3WF4~t;IgmQ0+@VCLIbz++MFVKU zOv`OE7F-r{`)q!@soUgtJc}tLqe$LwLWm4XUKA`^F_X&0CoeTnMm#4}ob(*2I7Qnr z*AQ?@8FWLepi^MbI^3r=h?y|8?dSyX{5XV-2Wk_SLdxktkX?CbCpqH_m}R0TkQACQ zTe!CK5V3Hl14Y(K?i|CA%X22=T1>DOI5{hLa19!<`51X1SuCtXIv&umGX)X(9~(E> zMPN%7b~v;Ig>*`wWFX(Bg0PAJ1rRGZYxcbbC#A#6w@*q7?mV1bcIPXXk4q;jr_b!& z;d2dPN_O<loL-qskGuSpJC`9UTx@L*N5@#KzLVei_z(LRJ@bD54<E05=16w#J=@Px z+Z$>Ywze-=J)5S%m6^SIL3``Mnud1utnK&A&DMAJ3+X7-q!c3xG7xi*aY4gZg|#;U zlD0d6KQu&xfPH)lCh<t53fXYU8F#~hS}onyiWC*1Im0?=;^=S+KGE2sQb|zSuvcrs zxP-wZRmpIH7JeK}tQo7j3e1Z5m%Cwli1DL^G%R*tw_6-etHt4Hv05!Yt2M1!Y_e># zMKzmM$Nw(Hja|bt4Ik<7PT?^HU+Q@I(9S`RH)Ly@yn5Y?hO-hAqMK96^IksBlfI&I zeB!Kz%(~T+>#f0wJu|}osewSyqd9av)M&FgyXMWLU>u>)ps-vA^81?AVYlEv?a;M| zsy9O`tgEuxpxf*a>e_cWG&uRH9+>CbxooqP$z1*-p$%>cdjGg?f>zdk*6y>fIeYcx z*7~xtNW>nSV7+`bF5JAhy-ceE)!Nt)t5;;J%cZKe&Tu%{?1X!A@@6>{mf=i+7J$hW zemQ`-92UIWT<^sggT?b`xj_}laN0Xajsq+(EC7vz`6yV%LtjaB3nSX4G}_>2f)`9@ z()0_0>@y<Z;5ah&Bumee5(Q#oIfNf%xoUF@H;<6;L-}3^^F41KRJi^1#T@}**jNtM zg_$aV8m)W88#oCZItg({u%D6xITit+1bCg8Bq&;8(*>t+tR8S^w1lvy;s{*t>p<*Z z!AhBB#e+b$MC%EavRM|72^a$ze51?muvu(2#p+)anD+arjT>in?wiqn<D~LXS*UDX z`Q$ezKezFwpX|)uG4zS+zBl>TowzoCL#VuNe)gP2552f++V7_L`vOZA*tmjV1RfuM zdHnv0s_2ABcy%b@W7dh`vQYb^`TzaLo9YJ|!YjsChN|l({EP+mKWTj9M928b%FE`L ztqj*c)^OQRj(l~-)ai>R+BPf?uL|3|URy}3f0)Ju^h&{&0-9*xDD)l!VNz*Od!~r2 zAc7WKok`b`G?K;#ga)KBRru}%@sE_`<msVi1NPvCwQDL`Gu4Z&>lbE?Kb|$QR<5%9 z^w!Rn@)Z>>-B)W*#@uqHYx2y=Ha*Dt{%s$xaaCA-oh{P>uF7#r`Q$nNIhxGsD^`@Z zbhhd~dzD-}@hs-eE?jS2T%BpHShIFR&>nzSm4D9Ua%EhlD=@94(`T)4)$o1)*2jXn z4RyOJWp^xTuk}H0V&Z&ZGh*7_kKUV3ad1=mNBm6I{;KGCL)(lh755nOD;g+z9nnG| z_%dUzXhIeQQCmlt`9C!H3Pfb=>2uFzPdm;Sg+)4%WCzba+t{qG`tW!x0=@+<olV+e z@&N;eqX2D0dP9~{VnIMj6~v5)UJV{c3RmGv769boT@Qp9?GCEM<+<s!8V%WeQ#w7m z-w~28xVwWpHN9a{gDoJ-Ws!=o%|0>RG)q;Tx{ps|lRu?R^fi>%c_!Z%1ou-)@~{<l z)zTQPlmoUIJ-X)P9d}<Kha7(0*-+Q$wuPdqHlb+}z7P|<Z?dPZyumk7`;_sWY22qf zRdrTVTAo}=6%qWxmP=cXy`1#<LfiqByJB*rqz9+POVX22Sm@3}N>~s`kaj@M*sd*~ zc|Pm=#7~VMebzYkW^Ln}&tCjgbv)WQZrgpc7WFI|e+^sxvgPpJJNmcwCoVou*|dJP zD|)k$fA3$m-mBcsuV1Iy!(ZH?B<1mUEnC_9z?W^wy1j=l3QoSV+h(q<lUZ4UTquaP z#bt!sLdY#M{2ZB`@gO_NSk-Tg&wTpRpMB{!ccq$xn*5sa+o6A#5hL<5U;T#hTW3ve zjMnJMr^UQ3MLhvnh0uQfPi}A6J>dpO0e5|xWW4_Sit>MUpNdrc-gvzbj`s-9o-i(3 zh-e@`{^xg{i)3G!x{%#_;)kXw5uql5p9H;=K*rqNX>$hkD*_yn^TY^`A^bA6Y!YTt zNr<3?1&;Yq0#LRh_Kut@`VCMFpIm2sN%X_#DKrn>31BM7&fU;zk(9L&?>4<shTj#W z20%ZX1bq$45W8HcwF9JBEB>`XqHj#mxYMseX72QVfMY+CvMj4YY(63d$K}C6r~iZm zr{R7CjPhschv>WlUZ!s;A-eCdhc2igB2X}mSkFR=Hx+grh&itg-{Df-$UO(F4}8pY z*yY=}-&c8Sc^wZK-*~GWR#XvnfYn`o#jV`Q1HS0pkpy#m35K%Q|E#<=;ETwRPyg4~ zzwuM%5njB;OVL0uUj7!F9pZK6w^sVR&Regz+<4>hia?;Y{AX-8tNfCaCCcvxv*G;d zH@<GfX)H-ViWAWe)rh(TZlTzhqMi$GKOn3}xCN}0CNm6k2{tN;TB~@Pdzzbj82<71 zXsJW-i5BIP4=ZJ^p+C9G6y=NNNPAxLuIZ3n9c#QVdDuF7rto*P7<d^93ib!~Yp2)i z%->+-1e=*DZ{cgxJw56C<1GTW?}m&l3+@XpkAMc^tne=-T)-_ZhV9P<i;gCxy#s`V zpts{O0vg#Xsa{2cte_Wx-Hh{%9aDOgWI*#xYED)@`PnA;QdP({?=JDqLH1<^v%Rcw zm2o?}Mkc);eVc`?j{DbcNyTThPHm`~(o!)leABe6mS5h!wg*imn}(q}`Rm4y8jL?d zpC)(&N!WMTfq4+UQ-S+5uwD)E1S}41xhLigaFtdLX$s)%0M)Dy2%qG^h%X6Y4P;jy zpS;*J_3YTj`T3oy?^93avrnoC^dN(kWn|j=UU)J0j0N^?mS=J=J{voGs>d^bBb)df zd&OYjRSl!{xwbx9WPNRqv0pIl$rl4YKM`tvU*N?jjpK&U@4~YYG?}4ZFL)WawS!ov zV>8iVphW0QVb$qK7WU?`1EOkT4#=3#JceO3Nz4L0jpx<=+pBDj`fsKk)s+ojpJ;1v z=+%K+Z;g&?uuc4WLuIui{mpuZt?KqMr5Y-4y|uDobQzu<^B51&WA=uT%Ev`VSKVN9 zRPWzkWw(tgBjzP5U`U62VbfUIqcH3v7Z&r^l%|31DwRDJ<!Po|KZF4)6+N~<QcFHA zAXzbm*t`p(G!>G^e6Fgl>fE_-b#>Oyn_D$|ZY(zMg_o8bE=U|%FQD#Y7avmMLh5+S z;ZIF1h#X_KFf0mPWqd}hv%aReJ9+&RA$C=%;4v^cy{vKO^!?+5nI%igC+D-7OsT-J zFMaWYU6V~|<Ls%X*v#tpM%__)K}T?DSEhFFu36I{a1{D*F+Lr@60ko?KmsG^7ETk7 zwI#G%pg;*%0G8uKy@Wxg6JLjo9yTDfF+eC%;70_xjws2XVUy%)A~;@gge?HkvoM+g ziPIm8)y|k!U&$eco>%WGV}4&KXqkI1Ml7FeS%h$my{05mS+`>O%P+7^CfCxNHU_7D z>V+HcdX};2a$Grd@y8zA#I6cGaecD8xu)J(JA;?GDuQKU8;hlTvpieYGA=I58eftL zfx?a_!_#LrE=x}iEQCGouqd)DcJ|Ut#^h}%US_&?>g-S4q4r%A3Qq2N@ZyaRPMfuB zZ*8V)X|Q8~j6wAJtuTxz$ZCaLTfml590>}Y04bIZ=0?*A(Gs4;sEV<q#X`SgD-(ik z64?}Y)F!pS0e}f2*GwT$fT{?&b`XZ<D2$rww$_DXpn(G#vNY|~lhaK5#u4CHB}Ccs zv{INn6X2fncR=VcI1l4Ql2^4s?hjcuq^a0FAvzKA5?XUE#RMYWN_#nN>Ns{lz}7)I zUKmgCNKn-Y{fN*@f*3&#Fx4f~+S7`5KNv>hhBBGFn0Bjrx=C-EY>J<0&LQFw9C2Z; z+h@>Rw=cNn)-iJ}#LiP^^9&$yUIB0|${E16mgMKkI(fPn+WagNRIBt42h{>#W7x#L zXUb=)1r<aDPn?1d3Ku|KgQp^+FALBWAg59vMY2gYY=`~u|HC%}4#Ep?HQS6N5{KFQ z<e52aF3!X^9XR=G9)^DqN>F(eH4fq_Bn~G()R$7UO+pjUDyUV_C}0S(R&R}qCWhdj z*iq{Fr>dfEvoVHE$dBJIG?i^$&75PKwgE-a`a)wOBMn7qV~nHR2p?8xR|=aI+9euB zgEj2kDn80Es$I&dJs*A<bB%4)MUaMUrh&yco!XcDN41M4(M_Uc5R_Q=rbA~Sj4c$6 zWTWO1{+wbOh8sgZonngE=2P2sq1hOk<<r1`baG6?3hUE^Gdue^FT<5m{{u*6fZS=X z#~zO_taQPE0~UY**avA81W+)x#N{Tjno$@+KfOJfY8AJ1i1>mb+9Bwc25bkTT6!G6 zI{i~=sIyQluMMH@j&=yJLWm?QN@(Gv3(PW0)lik~NTC`Mc2Mj<Eu<5VNpeKggvKF< zy;)Qe?g)jGz$+-i@h}pQk#vOgc0#y#3=el;v(m#jQ`|z-N%k!v9ik{9Pl3!6n;uI+ zse?Yy-C7FVLQ)qx5@u>gRUPKNFc{hpe2KMGTN4M0Mq{Zl7$q%OlR~e$WNHmHn(mOr zq`1mLAp1Z?gwU>zwq!@BL%bYVkJ{M<qh;2X#sf4wXi-ZC91&{U=~28*oZ3kh0u+G3 zYfsS_(K#u%6Z?%EO@ge|A`}fQd72<Y!z?6Gz=hAUG94|UzMy4VIDkJs#*;*z#oZcL zp(FOVk~Ll)hQLAQ4m;Ce8*Q^`jJpwbQC2kzK7OiUbCvC~+hfzLvaT|BK(@5utTSg+ zkt4FI>zrw-0<E;7Tf>@KS02|i9RWBIV8)@#wQkj^SZ#jQC0iX<Rd%>7Hs<wMm{qk{ zWCX>m&?_{R*=<e^V{E4lZ&X!_tjBChnO9X5Cc`+pX(If7JiNxDx-=af(z)VxSv=Z- zb9GgLl-8=TMn8wGwg*PCI$FnNuhSVv%Y6<-aaed5ns6qU%ZR+G@rawK5^lj$vdsk% zBx19KU;)dy(-Dx>3X9F*Rozj&&d*i5&ee#Df(Wo$?NepMIka+wHwLXAQe{NflsU6% z+zxRIBNcg#jyPUWzB?3zI>jf3WSQxWnp;;nj0ekA89h^N+-}hkc@jTv9e!mluM)%; zbs2`+3Td=zg=AW-mUV>h3~{e4`<yn9?6AsS?hbhmAGufd%RcDjtsa@%6uYL=R3Q?h zTXk6Nh{TA+q{?oq3$Z^jcihhvS@&0P$kAa&Fb3TjFEKB(IhbzIG>e~y7{DULJWhZV z$Ix5LWYw+$yj2?_apDWI9Lg3Aky~NUU`60ftD;%`vgT5CuhW7!nL&*!G)8L3U9MWJ zPN!96_~?`tripbs6t`N2v9ytsgAXsTVuZqgyK?5XxR?W>H&xw=DACNOFwCnGP}Fk8 zDl>)a77Qqc+Z{m@tjwjW9;+g2nnROa7|F$VA<C==U9hvLSHYaQFpVshQkY|cEY~9z zwcV<zwVD>i$DUmD3=fPeSJa>)<86A-6XIG$z-Fn_bf<<dMR{d}mgF^x-@=?eyR7*% zMYWW1xzZhHR=|z!Q=k~IazHU4pb}w$oDQ_WFT3Ff#1+dpk1g)?a5oGvAo~Y2%2v(p zgzmb+C&SPLGpo96P!e#jUAI6BBKr`;O|>X~j}>pS<ICiba$9r+*2So*7G_7NTJ!)b zjd7c%4&7Y$al8k{oDOQO1=CEBCgTNIR$Nm7#pN1SuAN(D#e>eswiai#x7;04^a=|o zHdzXu3~D!k_twGB!iup-<%>wx!n(HuDjeATlAIHv<w2*?ci_}uSlBi(leFTW&YwdT z$D3hld?@uX{zka@ojXmZoGCYs$A_0*|CW0HwN|&+q`ld1Q9N;puysDP{$uQp)Xcq4 zn?j^`mA%G(XmE?XdM+$siKry;2HI!ZT2_Ekf;Ddf7I$QIC;mr>Y9Un}`;FJJc|{`9 z-^eP`5K?4)M{evN9gQ)Ivh+8UDT=wU1GBf!lmQtmso=k_g?xr&l!&KZ3_Az9*8E0P zi+U}-`{WnV=3tR(`03+Msx(gd1-|R#&qqX{Imr*3ZT1Iz{{}+=eG!d^m^rdjB)d}@ zhv6|Gg(Yc-5b`RBcykb*k*rxTX9aa6^#76}DUg)W_p?cD%^=e2hYDQ!00MXh&pi5I z3G44!t4i6tWW-GI$p8@?0~mrqGDd}bo&*j9YpI__JtHg*t=Pz5=w`NuBnsrA174Bj zAoLZJYFr@J5w>!s6rAJ=Rv~d9ei09fyQ*wF%r3YGod%I3J`{A1@v!mmJv2b1fr9qw z9(DmP_#+NSJ-UFHS>9?~!b9Q<S~+}7f+BLszd8MLRjDygQ9v&8>7|;*yG03lx9S&g z2w#aT#@!2P_+)8@v`ku!t_wS^w1>1bU}!)Hfrk-&9rN|-g4Jm8E7m9lmnE|A5eBz- zmKRF!C6901yL8)iTJP0UXZEPd=+9l-dKT}!ZSUe9Tj6upLuQ;j`J93^sT|+7bnnK; zm#956r(WHwU1u5#azNpdMQq);#&Du?f8KS5Ph+bs!p797E_@+7|LCG6*Qz`AS0=)Z z<Je|#lfaMs#qQCzLG~Vp*T%&d1!7si3Ri*4!_+p(WLgYw0TEiIa1&Hv;aW%0oJJ0} zOQyGkiDy!H7AXpoARHSYXCZ#LnyJr5Uxm47l^nDC_0D>CdBjmI$D>Co8tS9>Me{SF zN22wq%KM_xS1TIEmXdEg`@UsYU$gAUvXv{(*>&~uSC@~;;}eIdJtkK>BIWM-PTg-u z8g{M!Q4u*1<-bQFT5%wnLZOQ4(S`DF9$j`|+1dZG?CNXJS-BE5kIvG%z*@}$cU54F z1YAHpAOwLxqYCxS6bI_rHy=Hb1G>CxJ4eL7M;Mzrr+@RohMS&Y*+<`mW8<FJ+oNs- z1AO+bu7jI<yQ_W(-tkK4_MNCZj9EZ*cL8-BrbWF#gTmfkWpS2*AHFxJ{<U-V<`db? zvpd;ev3^V&4+!&(ca5X`-;JYz?8<X*yzyMQoZW5WXyfu(#xnM~>IA#nxI7`cA~EsZ zB0@lmq&3oJ>1t`ObO&yc#1>XDDv%tR-ePrQje|G`4N4jDr3v(wtYAU4(j_8a+ex)6 zsBQWJXkpTUEL70BNfOp!r)h1GK}%E41v~=NWkfweB~&y1@Dzf0!i*WUAl*T4m7fy) zIJ<<Mh{|eJ*6H!O@{2CDD4>bgFWYnPZRf1A>+6^9Ik0S&)wyez(>iO}fjvvt>uN*e z+57I@vuwSNl9o&Pmt0<tGh3y~(GzQ$T9&N2a6!sEH7#jrN-el>jd^0O{<!O`i0o29 zC;hCS4+3KjP<VTn5|R6}`M-S;;rh)@GGbg2sH^p4K=SSGQP`x33-3%XU$p$%zPr-P ztDV;Q^R3S6<>|Znre2adYkAvU3nxxuN)Ov@(KDXfy1?z@_Owo|qeFgb>z;9S;=l){ z*y{q8=7{V8S;YQ3#xogX$>sePsI@&x#K>jXgSX4rG_VN)f6=~Cji?X_Sb^Y+5+p(& z**FA(#%DgDj~0lyy%jMx5F64@n+QR#*h_{pn!x|00m={3mmnB@3WB`;XHCl*KVgm7 zVsZR8HqFSA$3K_q<)52L1s6=$eikcya{>>e4&!U}KQVs7KV$sF_!PdKH$ZOQ_!5p( z-#_#>C2QsYZA?;5?oqE(uOod2c`X6lOu?h+tR(WL2##<NAz4CCz&|DTX-6dICiS{U zcHDa5&|fcq<IzX1<mcI@dz`lX<7Zv8`9Pm+>0X*y-ktwOq^2@i&K`mRHNMSxQTG)~ zS5D`%FZ|e!M=q2tSAO!*UtOMm+~)91xAF5A9^8C!-_T#XmuHrC^Vwy|%2<VQ5$<)_ z*hAA-F1-Skt*1S_V3#9f?M{+ro8R_euzN!QRB(X9a{`T~xk-j#3s)2+n7*K6ec$L? zqxi^&l$Y?Cp@7Z!oo%Aq)WBsi+%l#K0VRjSFVol8kLPFumj~z*q-D{1B823uYm$wX z+X6)g`x6q)C?-iN(dPJvFfYSjC;ff2U(89dPi{=ma0g61w>C;m4gEiK{lgY8LcUti zW04jM6b(hIrcKn;^qA49KP*2w?p`q@oth;ycU&APof9cKu(wZ_q{VSE2U;^DnfkO8 z^gEzvik@S>!VV3&_^8$uHEv_CkBx|2&=Zm$#kK+UXsKrHxT!)MeX+E_t3pS}?h&W_ z01V*Fxs-o1_6i$`bd702pWL+W)xW~}Yns#ttbK`e9ngVTHA48BZqrkcKBOTT5g)LE zddeS+3!y6sBx`UN<Owz^NH_37t1+F2Gg-Q|ji^mcPr<5l?EO;);rgvhHup@PG`X_z z;)rEZo!>LVvzaYCzjYcn4r<LkJ<XNnO|@s2oj+y%g|n8<W;d$;V~&H*MXpZAv&I*< zFm4$)_qNUIyQOzZM{D`wH9adQR7NwFPTR}|ALHo<S6=B@z%!55`C6B^HI5ILS4^4O zI(gaLmSs&H<<pFBnFH$b`Q@uFxS-+jdWSdBccXEMasBX(G2=R-PjN%vv_as~f?=i! zwh8QEWZr`?0ocaK^}`K=k;29XOe8Lb<v39QBq7JIpnin+2+_^y4ibdXF9=I)mB3<2 zZIEpKJ`k3F?Ay`s#J#sLrDaFYWj4D@bu4$aq*v~`V%E%_o}bL#G$rva`-I*Qo|u@o zc>dyRuUK-&WPDEpeB(v#Dz{oYp|NY~{7mn{3C&AtI6|43)`Tu!rgp-*)z4*b^gHU3 zi?5yLs{l{=K<DbIQ&!HOIkPL!^#AboCV)|u=id0d=bYL1eKM0}CX<;7S;;a<$T}op z-@*=pAp$~JlwCvtM?g`uim14kXtl1WRdKncZQ81})mrsxS8Zc!{j9A^+iSIuIefq8 zJu}H9fO_x${y!yWo3p&@^FHhE$@QI5#o`;zudfPMjCHuZ#Ws`9VqQNsKN=|$3a3VO z<03_FPr%>Y(m8KR9{7|DU06X@Cnq#sM0b@sRo831Zd6+f((G}2m25mpZIv36j}4j( z;C=Nq(4g@E8s1cNzlZRAGc8BzL@rXqqENp@K`qic>gu|&5uIobG}rDcTrg*AenUPJ zniI{)VZ<z&@^H(d#k~s~O2^uZ>~5_UGPkp^bfra@_w(r&L)I^kP0?6IokinDX1=M@ z)?IMu{%zZvTRb*<j(UN^GMqkL9TJ2^46zfC@hu6xKF4yAIi~ru{K3wdO`*zMN2n;b zp>fKcvzFhupsB+hh9Y2r0a}cxS?e<~qsHpj78{-N{vTg3y<&XhxL~NFa@zFmU3ak= z$8(BK?8)>E+}_FeMa6wK6k17W0?SmC_w#zy5m3%ib+?Z?AKf<p+vlUdH_~?z(X@z& zR}xWkFXF7@k-x|z?i=~r$g?lIGy7X4?)H-)t4=_4?WcJ}8+P5$p*(yj4nY?>vaV(w zp81BXm$8}InMH{X2Tt9Q#)WV~9tcB^Q9}r~F;>KVq)G502hIW(@e-wgk>D(Q>Dw%_ z4rpg3juR(fH+a$EP-|#^;^pPb^Yih?c0T`nb2I+L->0vnzL`D{zssL}tB#(<qjmJG z<HZ~JbNS2VLH=Cx^QrFi6(K);fMF-4^Oh3-Z&UeHGlsQA4Bl5{9dZwau>g=riiT;) zg!eRU!GI}(9~hZd_ybdHN?I);B)R*${0d8c)2#ooUah#pv*|jgC1i?;<P<@YY(k8g zLKdeE;y#1pr};%^TL9_{N#&0!{_{}hsPMcw^=R*OT#@<*RaUPBibF=u67&c4nBL;W zY-R~vou@KTh?n^L!4sf<kk`_D*;Je<cnBc8(AksuJI+BcDKrEmnHwR9z=N29f`f)p zT0OpA5}OG{C*dZLCzysTaj$P!*W}cfyVkbs_<ry9KVG-y>C2XscFoAw0Y5=wuX+8! zTOPc6UCUI9E`nIW)&)5$?9!`pCL8-~ZqW&zJE`zHv2j;_dU*3oyBm9UUD?t5&7di$ z9SgmF%Q?6F=H9&zeY~(Gylrtob^GS|Q>x_diR+fIoqyr}UfFd6V#W~PpQ)V#l_OV1 zrE+u?HiR#!92sSaF_i|0kxP}%_v*{sYnqS!dE%u{ukAgy>zvYAGt6$upw`%{e{uiK z_wQfZOqKJ*t6Jv!miz3_&|^F<0i56^iwYl$HL%zp=iRkq%DA3OuV`O&XHadhl-a$` z)<uWky65r-{<g5WaNELys_~oVPOg%due@F19{HHe^qCiOO^s?b@itoUj<Hs_&wBHr z#?*3KGr9#ZJ*1rA^~x6%z!WU2G%Asu74{P`R#T6KL#uGDu-o%2o&YAd1KwEPx9qln z@0<&J>w|VpmA%|qWY00^<==gH%j$=MQTN{#o>#LpG1j~K-1fDtLGcZQDU`*^I%af~ zRkV+<h*xQBdZT*(etFt~x2E5-o4mhIsgkEK=91&0p-oH5$HQk)Dl`?^3v-G>F*a2@ zlYQqRbxTeMJGyd5?cCnp%ANyrc3+vF3T}UJ%DnbXQzle5<rgKICT=}+LxsiwHF9Fc zvfYn9xV?uwg!r4$JY3dL){9*D{;$AFp^DU2=t!cb-p+@AajSsTw2I3Dxg6JtAuViV z;P>cvfJ<pLA>L|~-hkLbp`M02S`iMdZr((3Y9evH-jHK2a+cexH1<$k@5Xs`leX+m zG_C8dzc|#guKnCq-m!_LHRmnd%Z}~eKWSz~dwWGFo=C()*WN1sSJRG5yPG4y<UKb{ zPe{;Z7w6yn*7vXJmeyxlX_7k@D#}6gm<lDqQq<7h+_|nLKPTQT-qpN+_nZSgmA$=l zYj+53v&!#TG<D0wrnVw~bwzc{q!r`(F4^m<oNz%$%hbfVRbF9kyUA+{=+w{ObnQC@ zuFU(X)s*()IvW+TF6P4jm84{z&K0UC3R)@x8w>{zv;s7K452_o-6#ymjR42ds~zQd zO>VwvMv0kpt|c>eAKpEqMA-=?YY(4H5>1klhd+e+88j^F*J8_(J*@xgu82z>c>mgi zJ7><^c~IHOCCE382V}k#6DO1O2<0{c@dE8)2}va;5xD{%KqYQX!La}`lbnF%ADgHj ziJioA_^}h-`?W;&__G)&BH_T{SuWh9Q5gs%We{KBH)F%N9|@h|b;`2|RZ>Vw{JSLg zku1(1266@hi||q9LsBC9Jv@Oj%8X|d%Ckd}LL8w%NboYlX#-DFI8UbVKzU54@E_;D zhhlYryANDzXem4qY@z)g-4lKA|3u1#3jm$a12@oYUO-Bo>;rm_)N?ZF90{R7ylX!& z%&A?V!5i7CkOoO49cm|D-r-`7YPR2IwZs|PkbeiC`^vs!*)O7YKpTqaJ6^`G=sWbg z(w>>V<GeX!LzT);2+6}zyT^+dWT8pmegTm>f;Usag$L2NAdyk>e<d0UC6N~P0x}|$ zjbm%~kDGK+4P!MIO&a$Qn>?;``4su8rH1jPEdaM?-ny33@rEVxLxrsu&Yhv|AHPg& z9DJYHG0|TY{nv_;%Brf$l1qOdV+&>-tdUP9w3T^94o6X5r8e=AujIzInZ4b-&mV`s z>v|kn!9StI2m_!bf}9+|C66>zplpx|-1d;e2Dce^nAQOgJ6C?1En}<a33FDi{`N}g zdij~z3)<$pjq)=PiP#ia0Vl0)d-yf+`oWO+2Ub00`SK}K&pU7MozzQ$W6kynHTgBE zU$N`ir(?$+432Fm_*1&=)BFOwR>3b&Xm=6RnxwxbjU<s)g|b3J3GoiYC2ayB5JJhL zQC;$?{NA09$UnP4%XC*8tTyeGH@EkG@4)QY2fo+4{HcjoXIVS;tYgj_?_{~Jin)N= zeecyvZrEqY(H+nWhGo6D{WUx_sr^8fRpavWHvnK4$}`ya{;K{p;bMg{__Ltiq$>sJ z2bM)xiPIW1M52SAL6mWNSXXFpUn^o4xZVu<Q(8aOF~Yv*QXJa;uaR{G7%Sf#Ej^{$ zZ7GK1Jrs|y=ZgWO-{ChG=gPggdc6l>Cizi=&29j$k6^K|rDwVoTENq9-OW^`q`_Mk ziAUB05TC4ur3~M)z+{5=*$h#<+vw5jNd;MK##fC2d>^)0$t~bB_}1ySqEu(Nb@wS% zDe4j<4i|g{pBtnLqKvj=^?@^BhQZD3nX|3}JO*M!$rlD|Vl-nx&D@dk7GyR)24Ycr zt%HL7$#a|o1Tmws`}}-Opt?ePesj0Y)ph#;m#s`#&VNZM;6p<CzH7eW44=3%?ED5H zZb8pI{nP6hzi*mgR8m?WVY~h1mVjU0qn^<`<3MrOjONW2{*&-B-)&Rw>z7adJ}>Vb zrg@rPa^0u$Q#7uLE}#KG7d*87!CQ#rbArv+Vr-M_UQ}m`5<)u04FQIM9T<feMx3uS zUGA0ddj0x63j@B2TQ4mgH=*Sfw&L~I+3YMFF}2lq8j#qh>`wLpyHiR6ePH9uQ>%NH z%x+sB)#$GI8*}{aC&S=kZu=Rq#U5p`haXO_54;X8(6*J?wHT^HZIpW9OAr~@mt!%2 z?-v&%<NUwwTHAA8xG=XYK6Bb_%y8FTsc#Yn!||^`YEU<RErf>aq-5_CtLEI=&@j*C zEHGGlpLpeo53c^(SHL!${Nk$-8!o;0b<hWPN+s@8C&`LLHfl_9(D!;LMc2b{<4juv zTv{;#+8}Oo7*p?=^CZN%NiWE2C7r|UQ2$i&+1O;HDS4P(3*QCtXD;8#OLGKuu1zdH zpBb$_ah%1GW7iqvs^u75ShM)tO7cjmEL|}KLIina8zl(7?~K=I{eeiCF(Rk4nz*qh z@z52m3f2U!-|mrBTw8s{Gel=AzrqLzjdqU!7!ur_9roDYpLrAAGwQ5%I(}82rT6zw zukCLb=1uy6!8J>@SXo)qOB5y&dB4_GD;iiR`>|T3&1A5NQAqrVQ@)sSb{in6v}%w; z7jq-#7E3Tdc9XZhb}Q_4Ggr<GwTdC9*=VX-)Yy4(sn#tS?GB^l)|PI+YCAu5*!k(j zosEmCOh8Oy<*HL`{`aqC=7IY{ETt+bE5VzD=TpafZ@smbc+2XUGpmJ8W7O<4R8&lD zHWX>>c1@9?d204?MTNm>RtwKC`&C^x{^@`qys=ymmJ?G-b`H=HsMU4Q76d3-LJjVW zIxTdX;t7_f^hki`aCW~UYB!&WDv{fN;CX;xo>YSL-vV^A7`~;j7@@Z_hA7}gqo3SX zS_{CKqI>#Skl#<6)CIVIehPgI*9FCdL1rhj73)C{h=jsd^1L-RAT2CK-*M#yaTOfm z7|o9*o#M+}+;Zuyf$tu9PhuGrhLKB1CBWmLsoP0v;(zeg!y$<df-vCpJJ;7zJ*rns z>zlA)|AGA*CUhFc7?S4q%t`D!ldH>{nx)E|oN{wpg{!N(%T>{4F3-uSl$x8$S1-Qd zneRVy!(tJQ;51iM<88s|wUc+wDleb4bMpDKjAh2#Zn)t#>}H*R$EK?3TdH&GB7s1p zHqYy;s4lCmEvv5ZdGl)NT3v4Smg!ZS?pX2grt#x9J<REUAIHb_^LQMt^5;qpZfE0= z{7PiIjRXy}4DT|<TEnGlo|4OaqR(kIndBcLt!09zwd_HPN(C(QL?0Df-J{@RvL4g| z{|vYfi7>H+b;BuyGJuxc)&V^oP%f#DKti~TMtPKgC4pFD#B*e<W0)}9&PT}%c@$3J znQiWBXc!0hiw7uiW)CIKTxJk5miTKgB1`<8Ol+F843_vk_X|D9W70#VmQgKa>+D0d zmYLq<_W3<;*XNsIpMUfq?DNxG3&=h{s*GqlCCwrrZ-#u7A#G!PfiXN=8R;`<g}V(| zh5eE;_M!25^tj(-0!Vfrm6r85<&Vx%NEDIFQ9O26t6HS$8MbyQZAZgZtcNO{gC3A6 z6)Syhy(d_Y0YEBt;taTjm6M|p=h0X#`KRVfLryP>8C;4U+A(-|$01{+vA5IHI1%=+ zN#k<%v5EU~)*cQb=qU)*9p6uAf}YQy>x3=CDEFsbTmS?JGPP^Rfde}_cOTxe#9G_= zvTJ1v@X5MbR=QqpE$HnnXiXemyEw0eW_d~8VnX2<KI`0GXc%8mTjI1X*>ZR{Y|=k^ z_gx^Wp)H8-Nv7KZy3Gv#29O=C-30*a7T9LF+N;{jO=9S|LL_<f1VPYg7GO;xu&?w2 zhEy#47cMMOtS?H9aQsQ*6o~74-$t%zgS|OSv1_4%<4kwFAVkOEX1hV-kG_2`T^ctD ztwX5c_?Kv1?v}S5dH3BT`&_?1$RRrNi@^6e<O{iG^N<54Mfn08rc?)i?b^pLUgKWg zil*VTI0=3zi5@3uHiCHrzcDq`w&^t#vJ-{Rl316=$hypfq#(tUx0u|=ktU_SK@~_U zxrYg=eM=L#C?TTqB#uQKp9Ig?$4TqJVE@v6YSlj8rmA$jTshQH+0k+|@;P-SdjDlH za$@2uL*u?G9FC83Z2~+k@$-eecX<UFia?SX25D)=c$xN0(<C=`B@$i#{!|N%%SqMR z!`j5VM-uy%66z)?UXF-k`!>qSR6kl;(qkM235Qb{pzL8ZmeAT*`^r`AXlt}529YAF z+Ld9%`5ev-@VGz>B;pL{SZRIgn4#VwAks<WctV14la%o=v=vqSI_TK(eUu18-JeQg zDhz%`179>^a!|@{42vGxvcA#B|L*5FHCR~1;J)KgV*D`=XsnQpsTdad4%C3J0>d`> z_^5LzOVcZRh_bly94Bdsmyao0#U;?(RDw(|86=v_@nBL?k<Wpwf(rj)gGv60DUVk5 zll?TDge3VWG{8rphd)i5e+(U^4vDxE-Xh676B`E)jo!f|J*7^NTZ;S=U)bSGn(mJ? z+07nP{Xq2#)gM%!fFrWPlc<~_Dww<wNVP!g8o_8$jkC`QcR%}l^!?OgU-tXx`$wPu zzkdF!zBjtQ)Z;t@CwCXhaBu0k;~_ND1T8=#HpIPUF2Lb+=vd4;&c1%O<NrVI7tT_K zk!5DdlS!%@2hM_a^du%6az$c0kg1sSpF>AO70kMp8vgmqkN&rAl+W~;;gX%WkpM{t z6oxFz4Vtu(UovN&QT<N!+5h`l@;@1+n21D*z@-k4*Bs6^5(@)V*(l~I1!oc*A$(bC zuyoUrVj>z^AeF@tnnmanF#=BS<dGv~_>QkLTEFh-I|W)NgR;SNlpclrJ6YvX4#}ro z8JjEt>IgbYUf%ypWArOV)ZmR$GDsvicrwYymDsPikM;C$2D+cN{J4C0`Vig~sy0CD zPa=&Gq1c(5VYeEJOF$on$;VWiVb7er`_g@g-c%evnlMf>y$L3pFTDz{!M6&xhQ(H~ zL#LhW(pcZ}%dkURbU#MKj|wc+w6!mT`{wQf1GHWZ9U=nU-=DEfCy5OBoi92Q{yxPj z!ylbSCTT(YW0N6ul<VA($;jdu`5t<uP(kJ#V%g{qOFNe71m4Dd^TAK>HJS5ogqcwV z&qu;1`#M$sT3jBNhR#q$*h`4}OLERe>Oa}vH_ZJ7agmWH#Tjbz@s~1%;Jz6CRNADJ z<dz4GnQ6o1Wrh_~jKj>P4aed&_&*k}kB9L;+<$O24wD4k!dQ)04Ok9slF9GNeFF*k zcN3`jd-@WIzW$zIFxlUq3<i7p>AZ)2nZP260oKFR2pdWS@jv7$i$2Ku27>)ToiFLr zVL!n7g18D^H`s_QCE(!_X<r)+^cO0I<qokG<ncx@6mfg3K2#s_YVAVulxkWWb|kRE zN8U{Y*+5Y24<;zK<dh28=o0<?{qG(@R*Ph^KR7tRc|&l9;IAm}0rJ#m=nq*hvMG@Q zeZuh(F@UqVDM%9(Eh;NJeoPY{mqtPY^~2tW>QmYc+LH;6!ad}E?8W~W<%dZ;YgV}w z70pnQU>H}Te$!+Ug;OTh=yJ*ZO4;Ze_?A*Ce12rfgapc>lxp+?LgUDS3E-h;i2syo zfQ>(fBvefQAu}V-4X9_*nJx-j4Ap=&lq(Qh_XZBC4F-8TyP6$1<K?6L27V(p$}QXF z?aFhfUB>VgutLrd|1(oA#XiXWc#waFCwugwTx5zJby1j0Wl}zOHNL>V#oj=<&U9Ir zp;UpYg2Gc)OR5OHfND1SGL>tF>KjsxG<QUMr4v%54VDh2y+&S?YQC!0=|WRuvNw?Y z4h3OZHK1a#i_UnNx7Q5SQIu<oQm$cpDhy_s?DRYv3-8>lizwGwt9yo45YUs<GTD8O zcA|ov;WE)8j4xpe??<xoX0kg&jNz?Sz%Y<#;G_q|(5pqXfP97_g1Ryq8^YY7cYf_b zaJJs&@0`KRQjJLcigNN<@bx;7U2wKOVX7Id9Pgw)p}MDM*4Jo!vHUE}sn9nbD`n;J zX&@n>5uCq*sF1eJyU4{vp=pSg<}f+wRamPUl?Nd;5Db!1!ygR>Qv+l)*1+a01Vzq) z4H7pY&LDTY$m|v~5gki&SF{`HD{w0+rGg%s>kBDg8leV&=0dE?2r4`R0t|wO%7%-) zti%HH!hso7SJ#3lyJ}b;eVV_u{bV0dMEU1W;`8dBJ_VAhPuys;^&!3%c5wj(QqXb5 zo?(Txb8v1C@i{$MrKng~W>CN+)&eaed0=?VSPyAcIK9<|i=B=sVc$lw6>0%9wFVp; zhOzZlajnsSq9Gon!iqm1;grbR1sH0i6Y(mZ_h<XMz?-0njpT^I2fxPgo>Zrx7FAIx zKogz))C7HOER;5|r;v@McKR|73-u}K?9=*taYis09OO4hv?aQgS$~Wuk4hD^Fk3zg zBKb8pHU^7;(+G>5c$55V%4^HB+n$!aSL(}3l>5EYz!30_^qNkwYgp5V*40*lgnaVh zrX`q`Iyxs+OnQMk^9`bEW0#!l+DImQEOLmbT6?&mc%W;e2<_1se-ILMd1IH*Po{pp zJRV*P=2yA>4A-g1r<dCzpqv@y1cVmOIt-0!l>5tX5LKs@cw-ks!NlZQevtZ8iP0sd z2R3${<vNvHm+sSk<l3`CU!Sq0kLQ|Zg$+l3E{YzjJL^6Zfswf{6D!F+o!`_vZ(ehg zpyteW>aX4Vy1VyD7q%~LZ(o`cRv%iu`jAi$73#)5;ULc-c`F~UgBQ=6ckw*=&zvI{ z+UcS0)T{JRySSJhTHV9rDh5B`Str@$eDqR%Sk@TjKBAdX$^AUDhnuMQZDv6HUQIs> z9-imOWiAm0BT^ef=^7_DM8bGSLu6JRm^5pGaB){%CR&jb*Jib=)#29Vn{K;f`2aaq zsgTQEMagr8pWYK^eczV<q%HL8?Jlc6tm&*jzi-?8x&jjgC-d8ALujw^1y>S11fQ40 zyr+3q1-(BgKde<143rp|{IZU{WcVUS5$vGq&lfQ#T16*}U9kOENMz39mMul^O=@w9 zXMnCUr)6GC4sC?nh7O-QaM76CCp|Lh*3yd(B$gk#a?S&Dt~|6nG0+m-f8!4iFP)jZ z|G-siL#<Z@YS!Po?#6p=+PCK3bv1#jSZ~+7&dzxwH#;wWz-=_TAGmnY-f86)OZl|D zO!teOGd4Dd^&01x)|KNgeeI(oa~5q~HEUitIA`XntqW)OQU49kBQK#_rl~AVqc5el z@CBvp(+H?aa4EH)wv?DQIXWrRfWUv_w{dtx;e*jxnmEnZZUfD?gW^xXz^ElkkG0qB zqD2UnE5x_+0%a8p4%6^#g&`(Qj?$WXl#5%uy&lbHai~j|_~qX^;;?}(&0$f;$!kbA zs^Bn^g&L5a2i4;$<lmGY>NwdyluQbeTz}m;9;<L}xU@jN*=Gxv6|i-lr~0UxN>v_a zP4NleYHgHnj!%HLpFbPix3sUSB1rAZ<x?)xxZpR5T%W20>cvf<6z56qP^efdl)#xu zoB=3Q*(!vfMX==yp!7p&amjz=!pP6$pG9;&e@>+?Xa58Hb97^?eX@a1bpc{I{;_GR z9{xxk{OI9T*fZ&)hu<HCYr%fL<EEQ-;01V1*NPQgejmKTe!=IxBA=&ZdW;@VzXs&F zTR!q?*1SD)-8>wU5K9H@_2e-@Q|G@?H=VC~Y`RvJIewpx>MGa&_v%)YQ)$aoOQ);M zK~)9)|FmvKcq<UP0<83?1`RT<@A~>xN=E%D$aIJ-PWt8Of3GHrQI8$_Zxuex*I}nb zQ_y<;H8dg_f2@oGsmP{+9WM-0Oz;+=YB2#th{KY!IH23eIusJ=A(!6CZ@$@o=<P%O zZ_2Rzz9}Z(Wc{Z-LyxcKl}dYPy(uq}-vow28GC?%{(vLJe_Rhjv^WfYxd}0ca}m?C zPPJXNmq+z{OZ6mb=5}Gd2b}^11`_?yG4gi}9pfJK8}30ZU`-ghKI)#Yyq^87>|<B} zhMon3kvWc2nVis$WN}lRI<cg!$A*7N+kg%K(r2&-4}w7ydu*wp-}!CBw~si@T$WYJ z+W?-W{H~(cZlw4BJE?^R=HEcUL*guK*+zcHr&-%n_K9*VXJ1O6q<2jD$;Mw`ll!O^ zpV}z4mQt_{@(+o$rS22caWP5w%ay1Wps&ar44QzY(++cRzQC~%z*&wk0j4c|naDqK z!RH>9SX3zi2Dz<fV*fzglMh}!r)}i}-ACX5?0EfoE9&cW%f?-N@`5n3gC;DFyf6l( zx<72t{`Qtd6LS+2H#V-4KU-#X*lfXq@WOB0J7wdKHb!eMIquOH6cn((3cX8$RrQyp z9^7P&<OD1paZ|X_e$qnYUHXT;k&M#YQtFsPEo}{3LixFi8udD7M0h{!a+kJ5TkD-0 zO=_D1BBN%g?rLxoCCJb_QMH-op+@VjbMh^Y;T;&O(4#rXy9*(WZcj}$encYy!}|YA zvxtdfFaP|>N8bFE_?N%l>~g9b%+<~ce_6Q9<MlgN9b4ygl~i4P^uepkLpPm#<bTvw zg0J6p{&PL-@fUO#eQ$%@@a)#|0RUj-YJ6I!#wbbR?;GQK&2hV+{oWGY^Cj%#|5-zl zE=i?Ha(zJ&#f6=wH1fDG6**nT1n1LBn8LLpqjfM+InqjCOgJne2$(R2bRMIXL<YZH z&TpZOGKR}f-Kd=_eFQx~5oN@Q5Z5=P00H6;X+;3IM5yNgT4?2&9nM%xVGVulG);>z zLB2-vnp(|fiEUF3gm0X&0#{Rw6ctli<HB_;Qs~5Ic-Ss^&1$1^km@~i<<hbwc<t{3 zd#8z0PvW)H6(USd00w%IDIF=Va5-A<z;p$f9C4Eyp8_k((Rmbh8*nu87N=8VE-a1b zYIN}b%n?d&PP}#Z$a~lw#~)-bP9)?QV$rc7NA3yoW{Sd?(Rj<QT@5BX)A`xK`zFmY zpB#0cd?NRUN2yN);P)N{Hq!v2K8sO@a<si@_o_u?y>@bZ+6Z}R!by{X$BH;XYP?Q0 z%<T6tCg0hff24`EHk;UI^34m>9<SXix5;hTdDIK!n}UvV_OEwcdAaU)krvz`beyO) zG_&@>mVyV^igp&4zbTtS5!2uPW{QN^f3fAkdhHbUlQCoDaZ|L!At>0wBtv-kXyx<{ zDq#o_#J^JL6;tm>CGEv(gC~&c_k;}&ms(}E1sqnb^sSSsu%HfmghZgM7*1DOrv-{# z@Wqrn8+@?<eiDw9u=N0cf`&bJ&A@s?HayaSpw=`CcmyGd>EO@np+h9kbjmR*lnZlV zx|o|fDkU=po58*jmI`t1zc5Pm`p*a8*QLU(zr|lq|L{Fx4;Jst>F0Vq?*7-{QJO4V ze&RlY<V)fuukeiC#F0ia&F~oHI|L~YEMgv5UsQyPd-dc2!ks>d_JJ){$I}-8h`}XJ zz7?KTMAq6eVW4w=a&B2IB-z@s^sa7Y{rKr6F*`r?@u#F``ED}b_S7!Uk>9;6T3XyX z!Jo6ZmIQTN5^IN#Wvd@pV3CsMS?P-zc^y^&l?72DQQ#b%3xuC-;6#Wf(Ns|s$R3xM zgjKF@sP+JIdx&9FlVXxjwHP6XL6b<{`}LH31qfeJB}^1^PfKnh1m;461t{xTui$cU z`qgUENDh6JJ#$KBFq@3<y;D*5^(ncR2C^c3)q(=>BR}DGf5Pm6IRO9z$saqyZq_v~ zb;~F6Cuy)C=D;=i@iZO~o9Py=%X&@fAIhuQEvHmQ-_Qq{{*;Q31q7O6NYrEnGY{}I zP<<B@CJ>wD4m;$J15AMqV$M(8_|yWS+rb=ZI3fAtPu(cef{XYA@^{>8lr&PRtXJMQ z;$sR;=)pu8#Jsce*fc&jGLr%NIHG9et4B&KK1CpxkSGZuo@g5<-VS7I7KDBuI2s?{ zu;zl;q_WtUdYoC^duBFOpW8CNG(6etFq!W)t98)jb=|XP4)bLm@ClRax|^B<9`C#y zdqKomKKI6Ops}(fk(YChO}ERCZ)S$p-dj*$E^iAor}HVd7Wuf)NKqzlW*UQCC2a@X znX`VTi%@cMy)U$CT(?F^y>Wo6!>DWhT;{-r;W9r?^+%;u{UnLdhRU!Un|zdk^uMQh zGC2{uL1l`GQDs?GWxqZ@m&NF7F_z0BWQ~om-~hdwHj*Z#qGOS^oNB3nx4uqQNVp*p zcbL!%!UTx~kPN37j)yp)Lrq<qfWRct2~#3>2u1*^(nB$b%4i0}UP{2)5HJ7Yhz~e| zdV}>2Sx&z2+||fGBe-!z)a6{u*sf<^5k5@GqEtKcoSC&vV`?fao;Ci++%*?oRW)tV z^m_4w`|lqt(VN^Z---KKnAsk9Pl^J2(^T@_1M+9`uZ8<x4dgl!YderGJ`}Br83Rir zdE>XQXy|TgENu>TDdSB|c?!insMEx+Qz!M=>m+{7I{hsrOXA2nb*;bfstGGrPL;l* zO22tEP|i-TQTv*X#?Ba32tYQFw=To{5ka|C5kfffkm`kx04$>*M;Lfwl63+3?s3g$ zR%6a!GTN9@McZsR7I7@%I7x6hQoL|l?x3n{Od<9X_OvdlPQA_j9eZ(t!OqdZ;ftVk z1HuX{K6%s*1&Z_Z<G2UR2Vibvg>gG!eh>l%1!R*qCLauNHpj)fdN*kd2|I)$%kYyX zxp>x?DdnA!3xmvKEWE6@qGeuqOnCk5c^BnJ@+%@;%MR-!dNYtRg@TB9cv)AZ0@p8^ z-?bih&1*?~P{{!P>I;{Zd&X6DmCjkho}NuV?Tp<TQ-jqo#K%QC%cqQ)wRp*#(ypp; zp7OG=PmqB930J;RkETm9E)LQ%;%l4+oJvZxro_1I#f>y86sa*x@#9eyQ3S4jR|V6@ zv<d|IDiHJl{pmNqA>YP~j)AFuBmainBzWc#9Gp@em%lhpKC@yX`HuXYZyzq=-##Ck z^iGl<Oe%Pkbj()Cs(r_g?}HQT@#7c?X81d9LHUfZ31BtH+B8%gJ?FX$V_GzNRv}NT zKn(oyFouK26@g1Sbsw{yPhl0(8u^yv`|9g@&RdUED7bK1eRf?4tZc&^q_iT|caA~6 zBz5EQeXH&hW}Ux!gHnOGkT2ho+;`mBQv*;q<yv-C&7HCVPx|Q<w8tB$h8HPxIPKG^ z!A$1944^d#lLcfe7Fb03rLAvLLQZV&{%e27imSKoj@wMRCR=>>)~i=^C{8Ux0@-M; zZ=3q8_;^aS;K98+=S=Zy0e9=4GH2)B2Nx)W5Z@ynNi~Fb5hi-*h4<C4uS3SeYNW?Q zwtXp^xx-XY*gUi-7Lya0e#4M8qH6e<5_X(OlGO>eFc<)tvcr|6r0Qou5{qQ8d=5+2 z@ywIl45h}lhm3YT$`&Rm&<hdmmIM#31$xquPdLiSMTH3XwvZc~-LRRc4jwCrt>-_J zT2LYdxsv!JgqV4XqJmVRc!P`IHUZC8loLkFDb<D>l*Mk>ieS^mNi8nPUTiaa?IyLe zVf>ng9GEC9tiobs{UU&jO=@L$_sIP=y_WR|4&y5C<68y?Xrzn5wGZZRsBD@V(uK9A zYM&uEZTtjBNg35GRA6)nJpc`+x)q%Ya(-J23;0mo0BH<nLDXnTxWJHxcrkQD<*%<R z!sJ!=apsiyZh2z%W`uOgNiA~eCCuvi^8b<lCTcADgxxe?u(3;fx{kAXOl@&V3YW@~ z|CVolva3hF!e$td^a=3aE|xQ&=@U*DOCnTr^X%_l=R|oxOCb}#uE-b+(M<rQD5ZS} ze<I2N8AJ2>z48-Jm~#US556Kl@rwLM+TJD&p8uVu<`Us#N-ZWDf}z1l;&b%JCe5BQ z<p=ay@Fi(q7Z(VQDgxMjNL3l^eUc45)!88J;x|?yZ2IS{#_3!|Qd}d#+Fx|m3RjNO zH{&*htk>YaTHHwY@tcKTjZ!L){yshpc9<YkDDy0#?2r7u@N;}lc^zKMYUH2uf`}7G zf1gT4MN^9TbKFM-`Ks?Df{A}03nBk>JyyjL^_O`4)3xF6Rw~IxHvm&wV02;G=mt1L zA7q*z-ZM%=j4Fdzep<bhP8hB9|A;pN+G#|G3ER)m2MHeUVJ9h;)njB4^iJ5Ru8BvS zK;a09>WH+~Hh68Nu+sCw^XA7qY^}srSEqJb<py;!nfiX}N8-ber9ONw9=}%pa3xzI z1dp+|PAtFY9@LMiOs5i>|56j*sRE-RI73=B-s^<h7;~!MmH##Pc531zHYSgKo4wz8 za&n{eT=e8*khhoR&zO;|yz%b4*<3b;1}u#in--iH=+JzeXEJ6ebf}VP5TAl2hy=7W zB_~{6M5|?ZY*5oIp_BA*imBU<=r!m+6t1VA6BTilODCBP=Wdrb$+hyP?dJkQT;~GC z?D6Py)|DNf-P})9roV9_oF6APDknF8*0Iv6(|K5r#UZ`Vm)^lXxzD2$^yglG|NYmW z3y^I7qswVqxn!41*w4B3ZxwEvNFI+9w-tViUr6n6?OL+Z=5#rf`Oo==Fxrnq1chUu z3L=QA785ru=zxDF{}L%k_9||5D-NbP1Al_2D;qY0actuR&qwwgRfE1R_oGRnbI8yH zMXu-EO2+=7vPFX$n<oexLHh4(W-A4fmwD3hO6)wDEB(33|B+!k(;3ZG!iNe3?|Fzw zqUVKqWG_&x1*zR%X{q8m6ev%iqvo<sCE6`Z7NjL~v={&AbCzr<hM|yeC<5b5$6_#Z zb@=zJBWg?Na`5dWANw5BadbHd7%(HFQn^N-XO|=E-9zPJ!)0K<9x6`OVOmeaZIW78 zw&G-I&FE<&$nX~BP97A+nNMlb>mpI1f&srlt6cX;4&{f_^EL{KTQGabEI<2!#br0& z{<e`h%t^Bgc!jIJ^B4Ku+bw#7!~6<c`ns0?U@)?R>{N{}bDL1%2W+yLx$vNa8Q;F$ zY<HP&X9a)x&MGxS##*|neO<oy6|=*j7k@t5Co(fuji{SyL`Dxz${{FFmK?|u!sx6I zPmmi`K?vF2ZFcKvnE+C^IHo#S!s&2EQpt!@r$=Abor-H-R{sn~PV(r|tA|$$S|}AY zFcQ`mYSXHk0<0rQ3<HH61cm0*^YZg-jj$F3nR2P54r2vFwi@x8!EKRsk=+d&`x<sd zBH}eT*+nP2BT}>ce2TDR=_#yd$PR<2u#_Hl2-gp8jo_iajks@JL_83|Lpa$LS%-EQ zURM=apCoJ8))mjyGyAJ5PO;=Ddj=0xMWry(BbASBzHTV7M5k*MzQT8ll#-PA85(+U zKO>yBk{Bhxh6277kg<dT{H*Y{GR%_1zH#?1anJBQ4`Q0pY!gqYFN5VBh~(Uj1eGQb zNsx6c0HE*WVaYt=2}f~1#bCL0I#ZwC#uEL-4m-3O$YakE0r9>FX-VN5+7Ha)NTh%z zJsvoJ(^Mut7~fFQXmf)1;`$n}3#3!8CvqI(ykcFDT)g^=ivn^#UJ6HJJ3a}Oma)&Q z2e6ydGI;mYpp5sjWI;3{B#r$R7nr@_ek1z><njzFHk3HWQ$5<eC>#~A#&dS8{69IH z<77A!S7pz%k8qE|is2sR=G&d(mD#gtnC@#p-Q9{O9P?_)@ti{<@b*L64dRl(5Q90% zmQzSyz;3#=wxNf;VX@2a*v%F@Fnr~cLQoz^4T#C5xw*IIcI7S=`mzhg9=Wx)r-A*4 znI5s2>5)`I2r|q~c|hn{iYIQ(&0X4)UDE7!${}B9ihD*^Yc)W>PIGP?pyPC!MIPgF zkb~r>K2#b)@EmjmOy=0AVc)|BfSo@k?;!5uEr<I6jxUsCmt?rVA{2v7tTP4zk<LO3 zmJ~&a5fh+&geN7PjqW`0Bh~|Y&<Dht?LXRkUPH)mzrhN~Z?SA`#RJzCn@oNoI-<Fr z#QmTIJ!DGhi?uE5x#axjV}CFqH3?h3y|%IsRurK>yNHUOp3{E;jFSTzNV1_Yn5p4& z0`ZS~7mi4)MZp>rSR<>%V3r%<X-<Z)^e5S@)E`eltth|49T87(r$k}dC>|3tGc9MB zRe2<3@d2ew8VnrgC`vK9m82aGuiWo!cgp=<hn)f;Z-u{Sf}AMHuXAM2iRXq3<U}BV zB;Mh0DmcRNGrM6<FB56MhKR&hm&sn7N*3E4UaS)BPL}X)JA0Yfx5D8ta*GE7a-u-~ z?bk08_eEAr;Q)~O$}%PB{rD7p>v!4q&yh_e+?~~wsDa#{`WsnE(@%)6X15aq-BXGG z1P{{#iUb?H75Qf1B@!F5K1DP6NSjz4ApJ?Zi+jjKs)oOumau=x7!uNWl|xcA=MyfJ z1k&vFh_8i3lTj_1oxT7%!1<wkPunu;+jc?hph7M0VCN02T8fM>VyWmcOOn-<6DY9k zeyN(hY111-pE@A>knZJWD>wunbO7?Mu`gfdC@RQxBVCNyZ2I#Nlbh1cAe9pG=rHv= zPV*+SbKF>mWwXWc22*+Qee)4A$s)ZHGRY)20y$u_KhkM3SvMN3+pb2+7&Tsi<W95( zP<srbJ=%!!D9rdsO+MGzaN{59t<@kU6_3XPg(PW%Amr1U9B~j$-U+~E^LfjtrprG6 z!E=WpBCJNPAcMN3r+j`dtD>fmf5E=#u-pSB!S(VDbmw6V`^%i>y%xtG9{&9<U5?>0 zBNO!M+@kL3zj9dinw|0$$M7JE%2c($ws`|G({h}^)HcL&lIJ3N0GUe0QlD{*ctD#~ z=uo=)Azc&Df2jMY8t`@`_ea2@X~Z{va>QZTZ+5m{+SQq(wp&+gZC1UoX-_0F`_lYK zS8ZLad}d|)n2H?x^LIJT`z?-f>pGep8oOz>&T27>-ul*sCCe_hmqeyjRK^>6>L<Xg zu<W*X{Ety<Jf<%zukqnq`;pJbD6H`77R<`6E*#@U%GhwAY|OZ(sbdbjmj9I5>99Pm zDGZg^G!EAxEAm%~j&PoLL8reg76>B^thX}SI(|{Q&-S3tTG0l)0f08+p+pVfzGL8m zl@5e<Ic=7y2|>xCSZHWvQ=~+X7XqWW$6<NE`{qOUvm%Q@=l-!xFTdIksE&>M?)J#@ zsc+a_<NosoDjM-M4$EIE?GHm5ELml79DK_4gnYZr;V`icujtK}nVk#fI4t;Klhb?! z-HXGPxg_&Jb10rddBLrRNL@~0<y1!C{iKh83c*<pSi3!5h_6o44I&zh0?3qMrr-ea z0q4>POCG_X7@)xfU?0B!rThb(&fxfw)9@>2#4twt1D*Q^c7t9g|KwME%>AAfDtlCg zO?6mSo1OC=mR_?{Xt&vH4tZg8p>L6$-Rrbj?5XcL&Ak@Ke5ZLeFgKnyJBgPeVG?x! z3=s}#iAJy#5C+1b;gSsv#vy7#ct+{z#2q{&=N?F=FlVq0sh8wO*uSZrWUbSDf5t35 zKvxD3P9JzlT>a8cIl=ChcmLN#qn+1q;bxS5o5ev21X3ZOY&sxZ+Tf9$r@9a$!x?tM zqzed3M6`u!Vqv-fpj+jFA|r}?#E4<OhqY{|w8QjJ%=8O%b<`)&b)@@-yqT1tq{WdS z%sw&=xO-c}^4mdn_ch^(?8wY}X5-3+ko>Dc0sQe>_iBAdeA;inen0j`yU_O<)%CH^ zb+o%+G4hbvuJ)_XVXM#6`gZ%Y%h?6zs{L2n3<mX*4Rp&5g-?QJ%m>`hn+()V%^pE? zUJ9Z#vQnsFzhFm`$sk5)>Q<jm=*8Az5PCVUjgR9xTVyqxeDbZV*Qabv010{^eFKK5 z3K6){2WZC{)ntwn<N<I#+@iGr(Jzd-!+-`YW%Urh>@`SZj^ntux;|dxuB*W&Uj*c; z1jKy+hgP?0=mbjxPFgk6^^TjjZ8d9aW^TP~&h1?#w>u^~Un<y8jU;yl^YjgGCPKH* zDZYKyCA}@L=a)@tUQ|6xr)!LMR*kQy%6Cr6DQd2sQaWC%ZYpdqYl;>*#N^Y{a}QrL zY5l}Xk96uJ8wA3^Gd1iGV+Eb}GB)_R@Y$fYpy|BST}2H=IVO!DKgvY4$>xV6#}}cR zkQZ418PsSDDCpjT3WZPSW81F8L=LNDAZox&6$#nN)DQoS40uBjA)|S+IH#I5REw&? z0a7jyHUp&%NwSo+T7Ico;nnziNv5izdGnQ6=2_~X5#K&L%mh1gsropzq756u!FR9= z&r(#BwGg(AU6@J+$SUosIha2+kPG5rEfyK1N=y4caIr`+TySX#rqMV<#4)8>z+A#W z3Aq`V3OC&tN798jCZ4v2_RboobpLlIn<!<Ul=>9FN96S&_mhSV0$e}$O%*#+&$3O( z^@rqcCdUUC3-$8#8mrNwcYpDQJTR^DpOw?(cPGAo&-+sEZ!2w*ixrwq=4SwzpkY(@ z&_p@W=eXi8=LmL(9yr<JmOn2}eXMgBVZ_@mUcPqi!Gmkp3Wrl`iENClcP-UBGF)$R zPAC0iS{%%(H$}{5*G&A<cK90gzH3D7oM&x?p=$r}OtqE=hpQ)Dc3Kk{z*lVt8Ao4h ziENU*H4ahNz;lb7wW>rZ!AqwXtkWGDMmso+J{Jbg+|^PrTVsF`kV;bD3E1L9PS6SK z=O?FB`~=&cGu3(+<evQl5Ad<%IP)R(`EdQM!}T9s%d@u!H=bs-hjUc>j6Ro8o8bz` z!85mp&^M~iBU)ovvl1Mt;N~+m1=~FI`&k=+k9qa0>ABuP-n|iW)_{5oT;titd<2d- zq<D$J@rmxN4}-vy@xP83DVh*aVk2t`Ifqc*6m|QerrOpioz)Xl-#kmDKlV3tZJW?q z;d8{Swn%i|`8L5lyKL>12QRqv-h8?Aeum_jj@CK-m;Rw`?bOZF>lU1;&h@R^FPKwh z(`h$pCG)n0-rVcYUvubtLgnVo>~XD6Z8Mo2jSHSjZ62EMLv^p`p3TE`|8hDvs(Q{Z zYmTo`_t&!P_v0^V2q|6plMkJ#_JgCVsjfL=d(iq$a(e>nJLy+}1E}=6;)pRCT^hpx z=}3_8jB=i7w1ksPdCp*OK_^260(ihys6vn#k<fMF-2+BJfOO~~1c^W-67Wa+pq+u* z1p)Ixe^lzLw~7^ZyEUe7Ok7bk-QIrZ!Wox_{n4TvUvE`s$l=%PwZ>eR(_b;AGGv7} zsMCQ|rV?|{+}uwu!8?V(P%s8AENCkWPH$;w85h|&VY*Nd@B>33;ukK@i3q~x#KMrH zIZ_fUYj!!^1=YpP`M&7%vO<l|W#Qw1+Cqi4ApZ#77Tm8TJ(fpH<`IvZOSwp?47U{y zEnFc$4&?2TX%cFWCJ{3Od7G)-TxV;DHT7)MO!=>p&LToB$@JDx<&+A))0Jz~>h*p{ zsI#iqms1q=hcBJ6@XmJo^r9;gjry3?Zm$r<OiQHxtiWIK_IRvi(ag;jmroNZo)Pus zHy2kIxSg)%vRFx^*%4Zp*enQ<9N}_!d9hM|pg@>DVPj+*8g6=!5aBbr96hWnUc}0@ zU}UUB?v-m*-&8%J`VmG+8~|rpH)ec2z|;!e@Bu>(fp8o+Yw@&kt|qOPw__l1gB@-m zwve<3bVV`ZK@Q*!tpGGZP*`<+ZCx$pUZUWRYF10m%F$4eBZWe}1``Gl`DmPhZP&&q z!!_PjgTheU9=B&G3ONGN;IRo1tB_@kU(5*d83z#YmOMKQ19{K3x2Im{nu;_89kEDA zuW3iZ9G8c+X-#9op^lDV(HN8Vq#&9C@!CAMD{oc6eMO;9!{o~o3Bm0&w3l9m)Pf&f zRW{z>asdYXY9V?xAi!NI^EuOM;xlzYZP+-Kh1_{nH37FfP*auXKGxB}p`|-CM!cPU zo~{1-%U#uo_IS9krsji*@?v)X#NF}@#pSuSC@Ylz;S;O{%(vlCt-EAQ5&P)w;u81M z`aFxrQ5+34UEUOkMspjdkFW7FliMgZ+*wm|XKhOS&fKylwbiO_DqDE;@p+}qblhAz z4-t;VKmM_Isdsh#PcPonm=}%aHS%4cnQfN;TwoJ?4C!nm4mg_Wvb9Bgb^tHw&sZyl z$Hx+2*X&YVt-3??7?;1XCQwL-8q8m9b)<%{ZS6IoGjvO)^WqpCaT-r`k$9L77=)ys z*0Jb$3^xc^)jU(LRukky1ksr^DuR53uo@AaPI;1QoSCslj0#aDFM#t;AEDyQF|Wtt zjj=iBoHN+CPJU_4N)}waI3LN2*<zikVr(5dst1;B>EgxZW9#6nJ!c8XTE&xrSVw0p zH!n6}G6WDI)wf`Q@C(0XQRA~I|FeyY&3+s=JtMr&j|cs$cC55iMsn9qVo&ErCUit| zbE6#-BDrkVl6ZB6S+|6VjzB&u`p*szEBAC(RCFHh?oR!LeJo#D;ueE!y}YB!7isB! zVT!+@?l-A5W9#b!bImn|q6rIE&x+L4L}neuE*=Qz#UH&fVZs{|Qwu-b+SH|SyER=+ z8$YIFt;?mwv1Eb4`|r#;^}y<R^1mlOHXBbzyB_PJm&}pP^{o+K4Lcy;5E4A4Y!~U` zmHfW{f>kVr-bJ2e(wx*gtKmvYJUy9Qw9K7Rwy-)z7lrwT&jZm<+%7|kvAf~R?ER$J zFaFGEOnu6_j0S_}lM<hN)FH5(*xx<k`3`w%MIohLz@)ZX%h^hsd+;2Vy3J*`mJ1gK z#p}p*C%s;gTu)_zhdzh|gidZ5a3dX!2Oq9y{0jWA`B`0zK^!4BZsJ%o(_c8c+g<Ri z19{1JJ&%Ocw&x0*V!hV>-F&BfKE!BO@L2~kRm+3yHr?;CCn&h(cM6Rr`>&b&ZHvWR zB+fR4Q!zmfg&{bzx0&#twyQ=?7e!A3T?F|u!>XuKEC?C1CGsNCItkQqK9(ux1_fEB zM>C=eRQa;1pfD7&SrO_EMZ93O+SX3`{owB3Pg-ZQScUYtxF>zSWU8GdTn<Mxm5e%& zdp>cvfBk*qr>xZF<mgsT8GqmUk*CD_Ccp#qs}G=couKyt@*dVpZsv|@<B;d^uimXU zL74tnen|GH%VZB^W$%q_0TdYvQ?uCu*&#owu3&Ryulyie$o?WfDm%m$`4{q^SeyLb zdii&_5exD99+nHAN<n^4`nCKg`88&d{~`Zf{vpc~cgsJN|G~yW1i>1t-VNG9xeqd> z31h`^tC8gy?uao;78$YwNh#t~;}0%gNDLlvA}f4fszrQ?oxCZ`c8Gn0zlMb_)iy_X zIF_3KGvT}$sUz$dyKbkvNoe13^N#(uuv^%YR7V))8Au%#)-D=<cszUKnM2R8Pvl$o zuwM4_)HCyi$$v>r@(a&FCd{mfiroyFVNeqCU<SJjRNHziGal#>>qrZxaLwe8j*-c2 zvKW<h^`l0hdd_}V^6fn@$RD`A5%x>vIYsh&NJw|=*kwufdU4*PdBuG5=+@aM56s@W zb+&ZT?5!6HSG9HSerqSQ_II|WF7}7R?8z@4d+dwHgd6Y69Wy5PK0Nf%@a<c(<_oRl z=vOw<zoaJPVUzI~P*NQ!BbeR3^YNWK9~U0yJ2lyCVXaki5)D2;Kc)X=&r1QTf*ap) zhSW8BR#P7u;a;ZtseGYO*Dc58cz3U0U?)fUb%}@MR|kYAQ#1M)Qaha<pWLOsT>UNR zBPar~gR&sOs~JlGRNP<&Drg>I4Z!qqf)guJgZm^$V{l<kcq;NhW+e8AwK1>}@TqfZ zI5q)N7(!7Fy*TBCs4qec5rDWWb=%^xyxeHfl==;p7niq96QvuMF1h4A*W|J)`5pPA z(u#y5e`$U5dvCYJmoCs*&1FRke(}QUib-=4uAHF8@du%Pz^$<z^Uqh8m4*i8+rKzu zb(_^%K_7Pe^<rLOLs9;&<Lpv4=8k3?6Ygu99<<MyV|SRE?CUm{<?fiUB&pNgDqIo> z>vfe?T0@~fH>}s@<?3|dL5KhRjw!COm7-neDvXDFp10|5x=B;mAU=D)?8~psweOAw zHk$Ir1ZwrwFJ1b`WPf>nzSUUah%Bs_?rJ3=KW(eiaVpvfS$_>tQrI=Yr`FZ;kZ&H& z?nDcseFe&#SqDznS&N*-AXHX{8<mEIvtlfY<OoVz=Zm;5kqqECjp6E=Q&h@IWAmo! z7VTRr3iag^uYcOr5i7gn!Ln$F+gwqY|Kb~=qUr{t+IqL#dyh%&w^rWu?<WiMt^4)% z(v82C|Guv~T3RFNJVhF&(>Tm)o@C-NUqOL1mKA4@P2u*^3Xf}z1KC*GFElOfs9NMI zn8O;~evR4%%~g)e>C?h+rPk)8L~SfbTDw+by1ij`pkjq{{955BaZi1yEnq6Ny2j>r zUi-5mb*-z=*yYMyVs=H{@K>uIo(1qqK*OnK!ta~bB+w~jw}tYXcuvlBy3>3vH4=Ey zI0h<sm@9vW<@_d#Iab}VZOf|ZGkVs{p4r^!_B^yCk%-0ANqOhr<%_N=ig*jA|6{D( z8OW)wsjFKj1b&lWS3hGWeRJ3@tzfGuTsM6K<^v!H5`T>-RHYmWQ#`sqq!o)6)I{>& zvV#bodyRQ{Rbx9ZgVDLPrFCXU>p1pdc9ULqtifx~&0oP{$5{BBapOvgz2B18&nzt| zinv@Bv!p()O~g|PA%&ra=mS+c-@<5>neds-EZ<`=TMY7DW}V(OphTiUNV3UE#6~7< zPNy_L%A1oxyoG!-R6<JKPw!0oe-I<W!{n4;JmwKnL+^3h%&eQ<&Q_Qur}Jcx-Xsk~ zZ457$lQz5(?@TaJs}fWEom^{!4U~Hz>14X(fEZd8m0(n%gaK$(28O?}+`?<X->G7v zra%2o(xH*{X-GQ+-3a(4O+OW3RH=l$XbM0wW>*0Xgm?1(R&PRkMtQ_wdRURv6D|}H zLZNWC#6NQh3%^5#2a~Lf1R8cAkS>pUQ*7Sl$*Ls_#<$F#U32TrH*VVa$mBJ>h2_gv zP1@dFTRST}{($^$UVd9$U8F;tHuZ6aq=Ibxu3gUugP}s4sQ>Zap@aGPg@xmb5*;<& zn|8h^UD7gbT3emNsJVIlx-p^+ZrekC@t6}L)^sD*a#&I$a7m!(d1Ws=lv+T4n&jX% za*+}oscqeeX#78^3xs%T`{2jBgqy_+2j3U&Lj8$mVTP%9<84;>|I`EfZ3(VdlQ)*e zC8hUjWpz{7JcRCpQAKx>o)Y3ES}GbRBTn2-L5k$14rhS60`eIGb;BT~6<T=~+AH=> z(CZC)*zusp6Z8(AENO09(A+G|N|aA)UeJ7?xwNF2O|3`>kFHA&u1Kz*q&1nflb5}@ zY_isD(z3(!dvi%?vy|th_bC5<(Oe?WDQ#{pWsjCLJ5#GF5`UtzKPlTpg>XB&x&DQ1 z+g_;OYu0K^`$|gonKW8+>gLQ-rA<v(UyW#sf1^osXp2HPfVx-_t74PbCun6bBpM8d zYOf}$MWtAjSW7K9V<;oUW)=m*+zO<1&~ymbAX4-rj+7NJ3i3`Tw4mY_4;+EwSQwFe zF^ud#F-lmE+p)spcP&E6qIF(`=in8bh4m8kr}TMPDqv4mJ{*fGD+QKS3c|3Eh9pX( z(;|534t$2L)YriTjmMOK8m!yyIxIX`%JE8kO(`h1gVxc~RMQInp339)c&oJ<h?-O* z01Kc>bur|yq$=ZoR~y3#^aB=%C-|g?SZg@Q<qK38Vi;)UC!S4ffn}UG1ihb{0JkEl zkQWed%NJqxz#FNIq~)TwQcY0yR-B{O^*E=Z)zMA-`?wd2DStCe@nBA<QPVG`Z{Z{P zYT*{69tnBXOC_rTad7e-lB5<ztyY5=aKtphtzmvWQtpaibM?$HHS7y53>jkuR%X<@ z9cDAL6y|s&$z_aLn>0F&Cnu6?Fgn0%*mFF#bq=N<lOwXi+(4ed^meU5BN?@J##}zT zi!qO07h`55q4XF6p2~WmBoI_1f1{{3xu)pL{5f?7#%wty_Gn=!;4uq=Mq|{P#oSqS z9(RdHWchh!hj$jTEo*e{poGL=YN@C~T`ajC(A&g<d|ip9A|{zNOmrD4F2177YcvV? zq{c0J1;H+OtVOJ2X6kOysL=~B?2AT`eM`{WHEO+DBZ!s~hu-*<!6aI=f&kC#2DMqV z!naNom_d-BD$_BWMW}aq1g*~-@ke#hWx4iMQHR%1m|wQQIo(w@si-D5@7{znQB>+v z8wwe`O_{;6z@G1O$AdM6db2|?!Rw<?6boIKhkYx@drM12hs&^IY-hPq0^xJyYmv<} z>blTkl7!l>*!cL`qHz;|PgS_0ez6rSh|v%T)D=1c4!uS2L>)Gl)6j5EaZ}5b_*i2s z7z&9NX0iHh0qK0^WExb3Sw*8+BhO(vz+CAJ0<#&A!3*6j$hSLu)|`MX&rql>Rgb;U z<!ZZUYq21eUs4fkE`UEl>zw=|k9&NfPDDn=>RKkY=Qt5#o>1o(yY-@Ow^c7n+Hp`{ zjVrL06$qkH&+?p}d{$B<SuG|nv-s6IuN6)tc4pGs^%f0EB5DdGrv$DPE;mSDXR<l1 zdPy(97e*rjgQ?kXGPV}zMQu*o*v>r71LGX4bUt@MTW&65WyYUx3QFGndTT|oXl<&h z@OA2JIzg@1*4nI-qdHARPKP&-IkyJgYZm(*k)Tm5vHJzMurRCZM>?dC77ef>3buNQ zIR=b&9X$JBuMUXnzX=+hU}a{rMl!3RY%qyTI`NVz$LsOHbJ!s{rv_|Vhd$4PVT?}7 z4dyV`Y{sxQ*^S<XM%&m(k=`U39EF8bLN2vvww7poCXdnDX|d}yIXX?yB5KNN$H(m7 zubo<`_t`vol;L|-U8n2%+Kn%sb7`rY<poNPbS~SzX-(5>3#%p-3qoN8jjnT=^3)N_ zy!wf|#!pg*s=_&_R*um)b&{!|CO=@rBA3B|OCqj32n|IAkV0BvQCJRnF)D`1a2|t} zON_>(5UtQ&B}FhO3CKiH9fhK}l|h|Rrv^!)6UiBk(Nmo60DB3(Id#ZLmVslFR3*y= z!B%(E?yJJqXFuH6;tt9`l@GH;UDY=pxHKA(9IG$hd7wYYD#W+n_{qXC8*Uo>I~H_d z)^lG>pS5?(gi9thTi+88F}<r}+O7#XPMBDWW=!mCj+f>ekhSkfwhUH8PiovV7G5{Q zcv!fxs`Xs0W#_w#7vIs{X)!bPFW<Uv{6B8_q`Bae_ow|?ynwMA?sY!&rhh_Rvs*6w z;0b2RNsOD48!yp#F}y@b3~J$}?AO2gYKG6@zKpG^Zmedt6(YRM5I78r0wrxlyeI^2 zN=wAiW++oSmh1}Hpr|z|UQ|gqg^NX$nwSTrfg=J}ghX_N*(Ti_Yg{y=sy9Ek#9=*H z+F4vw=C2&L@sXa+<c5yu)CJ9l&hZ4h#@EcQDyhz^uKBMAr(C(AovnNK$e!LAQ?8d! zes6=VD}BP$bi#g9J-4pRXY^^cHk;o*!xt*_CCcj;R}{2un9{POIbtdDSX{-inqYZ( zu(^Ec-pIsl2amklW!vyQroMj4jNU!UiF}eyhT1^l@<cQFoDL(DAZCizDlC;yhco1= z1H*?!#f5d3+iI)G6qg3&g{v&mZ@rv4R(nf4bu1niro|7(nO@#}ykuO{n2SqF*x~$$ zCbu~ztP|pUF1A=wQKWwn942{<#j?X(W*HP(t;oeX^ekQwmp_*`9WNQPqqwQDgfbpV zV}x~L{IJk+v9-jSidvaqVz*jLEEij?gF>5ig#LlYM~ue%Ondf@LQPFGVK5yDu$0Q2 zb7znQxJ7j64927rNwNc}vF(>s#NQ9nmR%<#>4e)$Ma%F_Q8X{-rJ?jv55WHd2r%5r z12-SHlLiy_Dj$+6Fo2wKcmi>grV=xaX3xaRkn=}P-k-`p*CR@(y`rz89kv+#=jDIO zt0`^(IO>$uEV+6LaGd0xz5lUy?|(3Of|RoP`{eVj4uD#JN~wVX`ssIA*&X}jhf5oZ z^L#A1Zk?R;i9PhdUZt#%EeDXvhP-OQp;FsG+jPb~%&us&O!*`gViywtd*pvO2IwY$ zEad@S8ZkkcNPwB&Gq{nL<TZIL?Zty~AHUuQC=K@W;c_JTymSNG5`OEg2>Ay?!>u?K z0@x^zw<wD)iE7pj<4R@mf)-y<b5oJ8Wx<#V7+j=9qln6f>^GjNJq3PnD8<FOh0I^j zGu3n58R$Y8Y;$iSNZ(3`@G2!a8HfOKw?;rpC_XGkSUw2#21gdRL#YGTN8&5%G33BM zs=@XZum~7Qw;jAFJRX4%)4$}7w?2I9jwQ;DZIEp8+h(gpe)}my(D0P}w#90e--e5+ z{;8+*YRSfm@FOdFN?)jd3eJI6Gb>8}C>V!dgSW-4>K^%3cxh?6zc8D>=+?lEi&gii zt#;EFUzlz9l~pUhnoP>C@~imOX8z&}6Yuk+`um7;aA1V0B1FrGlxaBCLsrTN&%nwv zuh$iE)|j9$$l(?zz{UBvuHk9<XHWJ1^c2Fd_8i0_8SR#@7`T(tscw0JIc_VnJ3<SV z96E8+MHh}KuxS5++SEPWe_ylw=&$wwB=FK7zx>ZjUS+v=-p0JI?9vEh#uUu_#g>~+ z9I9~?Sc);H6@9T{GcKjxfaf1qdWNb;YZ*q{kflTx>V&W=dj{i|6Dpd{8f=Ac^VmA3 z8cfh7Zsla(9)`ofOcqqZQ+=8q=mXl}o2J63FNMHMl#qr2kUKF=083Dr9;AS1f$I{% z{UM42@jEmeLKqZjFdYVYFzC_r0P&*ZH5i)f951R}iT34VlQrj0X|h<Kapn2|Eo}c; z;{X+C;HVSmq({Z+M}bZ1JUZZ)C#I6$WrptxNI(4W_SfOV?{vPPwv7oQ7xiE=5Q~{D zzkqXV-1Vo;eF#5fQRPA9HS%u-)fM0UE++UX_~mPNNt0Ap;snxyBD;BO3IuQf0)#uY zCW;ji+Dysof>Q;ul4_`q6(R&HjxqyI1yQva2L&u&tVUoq#0+?C@u`5(4><-(Yfw69 zM)MgY7ZOL19zyU&Ah&3Dd5`+W%rw~x><Qu%zEKT9L{|dX0bj!9%I_LC-X|J-PAk(& zk|Vrj(&0_#`f?26^}XL{)`*g|ggHzewc4h0)mm+Nb*06*W<lf78`OeDtI26LJM8ZG zf6R%y0^sSv$7}2souja%HPT!uffE-rE&~h3sx{&liT8u?l?7vp-7P4@-gDH}Xnu~Q zc9~4>1rsWDOzjI#D7EHj)J{<vGrq&;GZbIf$28xtdDI#wcuYw&x~tda<~1*>%2hL6 zQDg6v;&!vCP%n6#M!&#JYI{Mbv37CP*jiXwpcf>6>5|so9R@4RJNPH4t$K1FRh@cB z^SOE&^vy)|DiM*o23BxYWJnH%w1<X8Cqd|hG>eu-W1?9RFJA=tjV2?)$l)YI92>=@ zI&extAX4bUF`K-3Efl>9FbVRi<S(d$Oo^A`)#yoF!#nYj3XEb!EEm27_`|}PZjYmL z_EsGd3Fc|-`Ih`+<$v6;Zgyqm>uWbGgJjqzpE~ph`F9q5A7h99z#=R<_23WXl>EN@ zUvKTXCix&+Jav4zq_J2vnrnVpQC=>nEe6xLrJY;n<v4YvUKGr=sLfX*sr|lYHh*DF zOkZ8+*X0(qwmz~jcdV%(_tJk17EZKU{Gq}L!N48nfEr+B1s1ijdsR<S;d9H*T^h(c z*4%T`M2q*ML(1;D&g=K~wsvfPX8jf>B_F(UYT^cq3By2WYH8bIwg6<#(YQuf)_rLM zzK$}q^_cN>-x#%dR!?e6!0)II%z3JFLfoM#XsFcq0bns~ci0TAh!Z}(DhlC`L2#$6 z^$75%B*aC?NDN|WN2H^4!NV^+|L}ny7lwZ<-;sLd7+k!i__0?~PqL!>3%k1)esS>N z7wQ%{Fesn5;#bV~T{hvDsS^2vU#(zA2HBtUe<@>%LT5<2s7s)KK_nith{U35R8WUt z^#wh)2v8^h0aozV(XpD2)lf3UE7XwoB@09wkf>IyK^B_I8ah;85?s{XyP|tmv(3Iq zKJuCqDOQfM(p5#1yB95AFgLXMrTv@Ra^iliXHw^~ISUfynu(V!U(iw$@~8ol5SY|Z zYl+rOxuCg7t#QGo3AxBpS+{7}<()#TW#;^O)0^yeZ?(oZt!w+%>)3a?wzdRCOMZ^Q z@Sgl{=8xvEw~kvJI&<07-E%8l;hEFR_VzJR5bb#lQ@2dawL8Z&wY61QZI?{ZxF$^9 zxak|6Ia9jMSu}TI9efFv__f})cw>R!oq5@umV5{1k9gx%T5nTDRH%a8%nkqHzryxO zUf3=ko5Z;+3Z#Qt4r(|%{YBs^rZ6wkU$@L2Cl97RnY~5&<;jxF-<H|p%-LI5pnd*! z`Jc?ZeSSNecnVIwld-wBqhsFo?OD8L4!9+(oIJJ$6n~`h7199noFy<yN~RNcW|B%O zi8~+svLGqpx-;bOeE7?PrLx8?<@V%dC5jBUd6H&`f#>RMMf>bHYgs8rClzow^(gBx zJF|h|PmAb+)*4}pNHNOVC=;lXfmA;ArKJ^z>_wS4P_8E(F6L++el!mtsiJ<DT?yH; zyD0wj?15BbKlv}2(jix-=-`WABbExO6v(!j;d>otLDZL&koA%;!_`kmrnBt0xYObF z6~0_^F8Fe{st#1Z%ULpTX^wiV13><PD9R#UPK`v2bn=uyj3Ct0ur4@5ZbTm-Y(PA< zs!@LJyLZZ;-|_lG_Dc={?Pm8|+k`;lDIf?I+dq+ueG#!o&{-DLwRiV+M%exG8XNmb zvHd-E?ki9J{tl+U^B5~>-COsED**bl=N<p%B=QTr6Y_~ho4=;5yM4lWTKNyjWLSor zqwtlShi~HOKd{`9W`PvF^gq{wVx6I@Obf6VtZBq^fMwwSV?nB~JI$&my>E-u?zfMH z#mLsxp;cFw=9ZOu^Ylg$+P=!bxQTW572BL9cSn`o2x?(3Dsq>!l+G*MyS?}7kybl# z@BGT~F40+1Kfg*_F}-%lOn0!tH+%eQ=;k8-x3a5&v!lA|bME`x_p!T4^PK=oNJ9uA zY<82)hZHtp2}wvoNMlGs!ppq(?t5?Y=FLpzW50l~4IiaIDMri>u|-5gtcW!#(we3b z5h)_piY?-=h_PaeNU^rH@{7U$xihob1*|{c?wxz?x#ymH?z!ilduQg(On(+DsR!m| zvI_(*9-cGxqLsy^pFPrBnNyfPeaj>F;3XXkPmkZ5#$7r1XxxMtOO0s*NK6yS@RUxS zuD~B)p|oNm9PZ*i2d4-8^hPE%JqD)q@h59>`+i1p?5k&vf9;X>sozedb8W?$-;d*| z?Lg8{$DEn?c1jo>r=-G)lV3Y?{Hxf%Tv<oyT<6%#?A80mq4)R<^$-2jG{%qYi-9w< z@u>U><gq`)e8z3ydwf@-9m+>w@P&;TzoVqy6Tx>raPIfPeTpAie~;mO8eXHHKb*@F z(Eji_kp2JX6WSl5SDb#<6Wd`wVDH4?8{K-T<FX%Xc`T~%d-)3ou8-sQvE)@>QQ@m+ zLS?IRY3<B+um~GN{`;A+ut%d@M08(bOmjFb@SYGl83yM5!N6+7T&>i}F;_uj2pl75 zClU7|W<H2HZz2!+kxK95vgrwV40AyLK+4H^C_e(c71MB8=E*VB1CMVhhG~@TQFKvS z)iVL+a>+4OzMtv1JxRn2tGcyuK8(vLzQ~JZVj6V8c>NRG_K`5?Sq3f>$4Yj_BPe;0 z7vV-#dm`G2`Dwg^E;**HKnOnArk|1SS9vH0UMo}`A@3sBqv{&dc<rTR<9x<(9EHw^ zCQd6l=B4<7mSyC?`hhO{RXN6KXL-grj$?cRG%6j@CgZdg@{8nF^s%gQAEUk{+;1@r z*RA9PZURriuu8|Y9~F;j)0qb4Q!y>`Lmiz_>;X>^O){3BW5ywLa2(5ma&wXHpGX($ zhi!m^7}NR@xDJ($@#B0z19%aq<B%8&Wl+3;=Q1j93^78iBgVz`DIC({d8juo1DbIe z!Rr!)VscE|!U3{ff-s(D{v43UeXON909K(ZOvm-cb*p+}+9;0sAdltf2W=6!OQNy@ zatbcbZHwaltS5vr>P&F}J*hn4L0^o=C*TC|3luLdKOu1YfiG}g5-{g6jv|=T$m@&o zs6WABB9D)PS<Wad$Ga}IWI{`_JX{arRSa{0T=O{quL5|@S79t{XT*ChWa2ie@}TW! z8Kb;$nK_L*w{ncWNN`|URVULUMCJ11Wf>28mWAbI81ze`xF2P@cxGT8if&BNPG@*h z0G`uH#9Rl{f5dMF_LKd8|IXF6X-BkIXdOB96!v9amROKDoZOInIr(1dvee_L)9D@Q z=Q6d->Fkc|k?b378`_>|JA=0s-k*Cdza;-qVW2Qvc(K@5+*^FCeW3k`ju{=BJ09=c z)p>X4sVR%6d~xc))Tci-JZ;sq2d2F{ebe;EW^A2ta%RuW+RS4!e==*qtZlO%oZUJ5 zzS%#WvwzP0bG|h<J$L@xopb%UkIj8+-kf=x=MBz#Y~H))EI8-TIVaCueD2}%#CeVL zj-Pj?tFO!IdZO#p`3uh<JpcLgPtTt<-<f~>f`u16c)=+=7<uyJogc3)>{@ty;pq$a zUwH3@#}_SLba>I@i{8Fy{zbbkdUA1L@w&y2U);XLTJl}omYlY9&C(-F-@UZ|(z`Bw zvwNWX$z_L@o$4`r-sqj$yS?|N<#U!_zWn&|pR8E5;`4o4-_E`#SI%E~3|FDwSbg*A z7uU>KQ(p6>Pn@{C{c`j2qnE#N#r7*+?Kk@$>VIYJv30Z74X-<OrFP}Ol}`=q8F=Ta zqwC%EuUtKF^|1}-Zg^_r`i+lnJh}1pji)!w*|d4n*rta!9lvJUHG8jlYV)SeFKk)7 z<;0esZf$IR``Y!_zOZf9wgcNvTsLstvFqO1-n0F{_7^_cv*V?m*_}srzIXlR>xZv@ zZdd27y}O>+^`qVWyASMsVE2jL-`mr@=g^+xHzaT9yWz+U@9f>V*WdfhzP^3K`%dxS zjoWTKQJPmew15Bp*Y(5tv*pF*d&{p?u$ijzeD!Gc9oa3b^5t4ztyX)t-d{gff2*;z zaoi{vYm8CjE5_*qmmM$<9BCGs1I@>qZ<$NXhs<xZ7PfY^9%+5k5>~%;)OyWcVq5kz zj&L?RuN+)*@F_R#Hr%JZJ>Iu`;qUTa3AP3=4{jZNX=u~XH->kNR7dxYK012(rp-4U zx#{(r*W7H~{Kzc>x4eC5;i17pj~sgO(2s6C_twE%A0At9_=mS0xqaI0qqjeI$DBKE zyyM|Jr`=h-^NCMS{q(DMeetgEerEJDU%ESe_ujjoxckj}`tN!A-dXpKe)tcghwy(? z%*NR~|AfK-r}ZO*zoPaihB_s25e@f0dDt^d7-KyVEO38xLj)(Z`M5(G(%@848;;-< zo;rOvg3~DbYy@Y({nZH0YO`oGg4?udbR>fDjRtx=f?v?^{k91Hy4Fo^;=3ao@s`Uj z?OLoLC7uiK($;G>Vjs|ET;r=KtcPP4t|Kf(i1XLtYb8?iK;1&T9ifi5hMSs>uR*K_ zzpdI1a9E2g(rb{~0o+yi?$kEG+f^#8Wipqp5AfLut}f~@luTXt#?Vr&Tir?Sg8sT8 zP4E9A&o)RRAxkK^3%I6ub)jW8+Tv>sq`Pn~VWZ_EsKtQ%4b^TgQvnp$S_6$cp$w-( z4f(+9cpgYX2i)!^sC1NMyn#F2!2~WAN-<B?sE0PN9$jF%preVJ8~}$wCEL}2EN~xD za`}*R4X(Uiik5`+>yyeYRq|eslI3xVu+O@&LySvwp-*h^?!q6xN^co7xCY1NIQAkw zt5ddQ{N5kc_Jq*nBOOH=uh7?UeOS9syGOfQ`>e({SCV+pK8;;iS>B$5{h<ZIo*e4H z(^5yY&rv5{#4{DUKk!)#>{yyfvuHNWp}Ba?Hoq$WJnEwJX+GXsy@0RL(uK5$E~3SB zG2VrD2`>F!O5NDm)r0ff<@^)_zDTi(R?`~1$n7%v1a87zLH)EAbI_GEKv&Uv>;c<A z8)*|=Lz`&}ZKZ2z8(l}+@p{D_cuBxcY|h_ByJ-*IKznH)-AE<cPdb&ULRFGfqdGRe z8+3r0WKxSPvN5|I#8~}-RwS1^@+qJ}8lqtup;7E!zL{>JLv$;R(WmGz-A1?59dsvs zn(iWeewOZ`d+D=uAAOGQr(eMH1HVWQ&@a(Z?7V-FewiMkU!l*_7wBR7ReFSejUJ_6 zr^o0w@RG>i#8-oUi@r#|O;6JA&{Oog^d<T|I!3=we}FywPtzaKGxTNp3jHx1r?1ip z`WhY^`4f7U{*<1hKcnaA&*=sFI=x7LK`+r?(#!N$^bPuJe0cV6=oR`~`WAhgUZuaI z*XZx@z{Ypzb@~T-gZ`0D(Ld35>7VIM`WN~heV^W<f2FtS-{>9s0liEAPCumoz$YSp zOh2Ljq@U7%(R+mV4A6hm8G0Y{KXz*2T6R*TL|SA7UI!_1c(F-A6a}vMicaiznkqgf zritldhM1|%7qi4{F-Oc5^TauLrsF)(CC(S~#RX!4__$aoE)<KzMPjkISS-PoNZjBN z-C~*O5xru$SRwkvO0i0;7Hh=MiOa+%#O2}&(J$7Db>d1fAg&VY#nobi*eEuMYs6-; zMQjz<if!ULv0Z#p><~XMc8cr8F0ote5jTjvVxPECl*E3ai?a4jQ4v)kMNQO2L*T7+ z*c@Prmav2^9C1*%!V|s-#Gn`w!(v2?ikrmE;udj8+$zSzr^I1#o48%vp*@fZETg-7 zZ8yg~-Q97#EK2u8ac>kakKz?k+!w_wqj*&mua4riVcfGmj8~}mD%6vzo4V(vT7hR& z(w@}aN+T<+L225KOf``9lb)};IX;wR%kf8&fhXN$%`jV8zfm%Ew=RX>$S`bpzOb8V zSGMdynHjb1R>`okDz*bZVb^MD&!}6vnW)(Hl<(?ZBiXQ9G7E09q?>-yH(E03+IqE6 zwTCPd0Hd>UA{{u4OBq(#9?m<aK2oX}ZpD<S(~-KLab?YwUL(t*D2Aq8X(nr?UeBR1 zRi|NF(#s9nX3&x)$diviuAnV~11EjZt=LtWDMKBI6TV(gB6!KNZ8x)gXz6Y<<+z6B zrz?6(x_Yu^TR!s5YTEF1)2QTqIqa7j(x^B5oPvjps^7>VuWpr0S@R1aSdo@5-F%pE znY<Xn2LjJGY9mQ*OWv@mpbN`Iu%d0R=@rRZD-9Y|X=fax;s>rwJJPBcX0D|>C6-mX zX}!t}p<&1=tA?NQ8oDb}m4<|dxWkH`FP&0ZuQZ2rw_2>}P+^?P#z2ylo^o^;0Sv=- zGBw*}@`56d6N*!mNXY}T;ulcQplgRMFUASggf_<vyb>Emu4Pyem=BFep)+<<#l?ex zgi64KiQ5dTW{1VRiYuk%HEh2a6$`DR4Fy9eSJtf<)LqveQku+%ppqgR!hw?u0c8<N zMQle9$1_G{sTP=KA%eY@ZknBPxMJ!peO#<$-KhCVQ|dL05m#pA2n-Fq(Z)c<v^`mX zzAVG4E7?=frzNu$-IP{U$I4Z=s&*?=v0E+lce<t5E$QcCeFe_A9$7w^yFVnQUqsU# zhgnuIU<)-^p>)H_@==0C=!gU#l&)`}#wk&{VY|jC%vU$tVDY62?7}bjLxvB#3>D8t z#%8Zlh0x+lsNA&^O*xXpX!f#^$X?NJ1g)}H3LI8kN0ef5Io+llNkcbldF5R~pOWDY zg^MVfhSh{|hCQ5d0<VE)6)}>e3%3CeV>OivF|0HycN!!4x`7(Xp&f+YfvZWG@Ih8e zjrY7V@vx%yc<_eFoFY(#Gf{)Haa+?N=X3x!RB7g6Vi+{6;A+D4yhNi~&6Z&eP@a`6 zOVi9(SgkcE)|a^ky0H{mw*q;*XA~4TZ7ODkObLy%bk-uLPQoY#9g|RjGr176fe*LK zGCkyC%r{cL?lrwMJSue7R(1_ptLUE0vE_#2Bvp6qz=2z_nkg7$P)(Pm4iAy21U|ab z8Ob@iqwL3UlAb;&bKE<nG7Pl|i?dxAmk3N@oA4N}(Ug7z4C{@y06xkETL~G;rcA+j zjSAd+P-(WI8zB#dZ~Hi;)ZSUQ?K+(QxDUurK%~%zawG?xOTWY|#W-OQgERzKt@#jC zy27}DXSckhXS*;p98|H4f-rdEnT<^Zb3|xsNyu%(VCt~{DyF2ejXust=FF6Z*t9vp zKHi7D`Vzi13rly=_c}Zxd|nQ|y#c2gnB^?|0{Xcw+m(uy7(8_q!enTv8J<c@t!f@+ z{f6y9`7-MThR;2gWuxL6(-llqQeuX&;gxx&RMQDJp&S?{MoT@5!Vb?nZF&o}>sCdk zTe8|T{Ctf?LM;a*M3<Nc8cOfUT6axOsoDWLssuT4WMxjBgbD3$5(@S=Db2l-J6k>< zf~sIPgxRAi{!E&wO0S7&BW>yqN6JwALd!05yVPhbME0)iEq5@m{ZO=g2!{QP)>;-C z6Vj$I`<o-V$Q3{_ofBOk>#$>j8{~9O4m&(V0it)&fsUsZAStf}K~go$5LTik8<{$0 zcSo;g;pUWGWO*&Y#o861Tnp^FnuU%rd+8=dP*t`mfk0+<jQhLD0l}GslZ6`e$qKw! z8y6{Ix@@wufmJ3;Ju6q|C(JB)FTjYz@HHHmbx;l=kge)1IKk*B>&}oBi3yY$@+znO zEXWI;wAV1CS#6Ienoyc4JVlk@USUIl;WeO97tT)d#4}u}!a+r|w(<bVKqg^A1DS+k z2Q{&fa!?JwWv)n8Jg+wm+l0%^g<h2vsl2F%+3{nrcf;`vuXJ`onlg@yC#__ux4Rch z1}yzps5E9W$cxs-D+lHoxqOApni9)d_8B3dEEXbG!r81%xpig*&dYjo;grv5o`f;1 zd1ea@<gBH@beVc(LI!T4UUm|JS4|j}n>gT%B;25!Xu3m*vR~n4vTPe4vz^Khl}8|= z)6mNpk)__A)l<i@KHO<J@TE87!zgZ6F-9vNJY`af^TDonIUiOOMlhQOWf@LwQ6f2v zZf@g)LXXq1GBZ`!4HngK=~w{9&I@ZSr0cHUO4qQaZMq4)Y9(vSRxWEV8-5v%9o{(X z26#f#&HE}+s1DOcMQ0aN#R=)anV8FV)j1(I9O6S*=GsGE2E){~jcN)5BN&F5Mw#ap zuQ}piQnLfsI~ZV6z;XblVyA0x%ce~7fhTa^a1vg?UE9}};gcI<P$tSjT?{r;L((YQ zIB~G>4}z6F?W*k<4x#5}-16yR1L8T@442@X)z@CNu^v#TACdA`t||;-DUMaCk_l9+ qx{Kk=rVu5YQ9XR<<pcNCsug_b<HJfmtl|T2KhS9V(3iihY5xO1YPRzL literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.woff b/src/static/movio/templates/Skeleton/font/font-awesome/fontawesome-webfont.woff new file mode 100755 index 0000000000000000000000000000000000000000..8c1748aab7a790d510fb3f42a8a8971d96efa79d GIT binary patch literal 44432 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 VoBs<Y3))5i00001Qg^x6008Up2bBN- literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/img/bg/bg-box.png b/src/static/movio/templates/Skeleton/img/bg/bg-box.png new file mode 100644 index 0000000000000000000000000000000000000000..f54bbaf2212814e8b8021699fac05f6cf2d14d20 GIT binary patch literal 800 zcmV+*1K<3KP)<h;3K|Lk000e1NJLTq001cf001fo1^@s6F7$F(00004b3#c}2nYxW zd<bNS00009a7bBm000WZ000WZ0W>Kjs{jB19&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gH7+r$A4ux}000<tMObu0a%Ew3X>V>IRB3Hx05LQzFg7hRFflWgTr)!e z00MMLL_t(oh0U1Vj;b&eg};`D7!xr{CMLfByBROQpBQ4W&~w3QEr=s1$gG=j9BsbY zKdXBq4u^x0QlhnHN@=Z8N};tzN(q3Jk}wQWN+|%=>-Ch34$^<EwdQ)gA{UE=n3V3n zEEG`7YL;b4fW=}V(lkYDJzCnE=Qe@-NX}+6_qi|(D@cGij>Y+Wu7!L^HO~!#p!U8} z3S$faMNzo-%Ch7k)k%_=D2i$a456|t5keqD_v&&r+5AHs$0AMB!QiZ<l)V6LG=WD* zfX!wj&gb)}HQGf=se9wJDUM@tJRZNvRFhw`Pay$*etuj;r;s)FUm;=oh~|0z8WO6A zj_spOS>Jq_ZeL^jsIQ_ZT+{S|gu6YB9ZhTM^ZC50%f1JU<)c<*S-N|?bK|tB%}4Ej zKLjMy2adNO;j!!c+$PUtj6o?yp65U{XykeRcz5^JkavAi6wbt<YR+G8oUXE6Zx8)M zK@dEg@per%<=fMzpv`Q&)!ok&$FbP$c0(Ok(_oMQ+wE3lS;qBx?e#r>ENj!CkO0f& zQe;`yns(o&{I$VvmNpFz33tP{R-(18tV9Ust+sx<IKn89P#J!fW$yPd3<2EG&_|;| z0<2c6+7;T|5S3D$>UUH~s8WBqT*&jhwi#N`*=+XGwnm49Dx#OmrFPf*DR1*eUtfWQ z&*ssuLBjj<=vN`(y?ONOkkEgxp9B*6ZK0DvLifFXQb?G7ukWS9;b3mJo4MU?#u(#% zCP`u@kEE3~d@Fwd`7@AEf%;wV9`sKQ)>Lz6l2U%YEsmxAes7{ELTmkZApuUOlNs`n e_-HzvPUau0G^Ak#XRj6j0000<MNUMnLSTY$f^Js; literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/img/bg/bg-description.png b/src/static/movio/templates/Skeleton/img/bg/bg-description.png new file mode 100644 index 0000000000000000000000000000000000000000..fae27607a8a20104f6d3d5c489ff54bc755a5f05 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blmSQK*5Dp-y;YjHK@;M7UB8wRq zxP?HN@zUM8KR`jb64!{5;QX|b^2DN42FH~Aq*MjB%%art{G#k)1?ON>J;T-V9<PBa z#X%~ai&7IyGV}8kLNaqx87y=S%yo?n42>^OZp{QL;q`QJ4B?oWY+z<)$IQSqhcWH+ SnG|iH1cRrmpUXO@geCx@8!hqx literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/img/ico/alert-error.png b/src/static/movio/templates/Skeleton/img/ico/alert-error.png new file mode 100644 index 0000000000000000000000000000000000000000..b2e8b957f30efe4892854be097591f71b5a2ac54 GIT binary patch literal 1454 zcmV;f1yTBmP)<h;3K|Lk000e1NJLTq001li001Tk1^@s6zaM#L00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy5G%YYT zEiy1MGk$A`KmY&$9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00ja`L_t(oh0U35Xj5kt$A7o2owbcjHt}sR2ClR+Ww3n_>W49P6PbcIP`WP*?$b7u zGPZ#Oi`2a#qE+eYONZ5}owMuIy5ZU(tE*JBSU084;tR7)o3^n{ZeDDYd-fssiOG_* zd9!-p4+;02^Zatoea^j43mG;M$q|t^MC8>>=gz2!h($z>h{!#8WSt_i=Sj0gnF-sb zD93JI7yrL^!noyVrq;^IP@ZaFap3-4+*R8#90LGkzwjajWn0kl^4E*VZB5g@NOvJE z-2@`C6!=X%Zk!dLhG3QD6fVG0Ru13=7HOK+oz8k$=>(fr2H<OH!WgoHNQC@1uQS?q z9v~0cn(kt00gK26V1+Sc$JcxY5s4|!>3YQD23T))Wb%PUBnPv)o>TQ09(P>ez@Qy( z^BEOd_C$bzoj~!}&A;(o_#H8fapgUCiol>9V1<Z$GO55KG9R!4=tmF4t!%gqj~n-~ zgDQp9?9k)@6Rd8Y??MY>_ijg2GJl<wnKg~ftZBqz{TQB^8oK7Ya*@%lzW|EO9FHH^ z+%zl2<HmVpA0kFb(^juz+VWK)->D^UlDB+SgpaFkpSo-{JN0;hfh_>;UmG#pI$}sj zxkU?=&oWcw7A=hM8M}KMZ)-CI$6V4?P72uEEG2<~ew-(dU>HV(1W~R5QwS2}H&Xi@ zMsUonOm@sA3@joR%#Ai&TNQH>JmL)xB+4(KyU@=zD32|V1sJFTiXYzS#Cz$_*uZg! zWBEEy)Z!oL2PjEq%q0XYBCi9b0FFK1#GSQ?R#<8H`@PD`YIZO)z(6^G^URNo+HDwO z#FWG!79_5}`%){u>sKK-=BhFREFx=xm4;hq_;}5@PqSnzEQY~g<(JB{)a+z>z`#a; z2ghsh>#nFBA7@I0@kURHaE<oc7&-leaxYH{SVSs-62INX@Xz%VzAvOwVKEFGbq6ur zIt0hu+LVCJO|S-_f5%qD2u!H>Q)2wMfIfnwZodlHm=ZAN81r1ag8SN)aoZZYB_ss= zoT=c8PXe)y#$$~2+aNgRDv|;=pFX7kecQ_?Y^jpoc3!18VG6zNe8Ta4+e6QgHSxw= zyb5mu7(86fXkSml3pyI=7(84ZN-}u38b?E2!tw6T%Xm63!#HCu>JVxkd-ex(7u}^R z)Ml78n=)$-^Xq<5Uzcf`)*OC4R)wtqeS5#f?{Z-nlC*MPDkN{=YbnJ(wDn>?6e{kf z|HDO8*u2>{`?|a6-tcZp6`J>X1vB1W4S=t^i#r?NCy->9vhxcltUpI~fd$|LP16pj zYoQ8@$n%)h?cM!##7lRgdiJe%6s#AxICXvzvp@PQ={$bjiEZ~+3e6h+W5REVN??w& zwFSMSJ>iWKt|_zTs$4sO%>Ywo&rK<p<Lpm(Z*>7I4j*$_W_6bW>jS!zo?Y7#I#kAz z-qEh|ZU!0wMr}PQ=j+|IP30?7$Ehsy^jZlpP=APrz4ue9h!_U0j&}ME?pBLTANix1 zo}CqG<#RMOK=3$K381MlrgyY+>%;dZ+7Ag^c7cU}?#f7>qT18s&Y1_WEDKlyFw}H1 z<<`ZL-{s6$o}s3bihoHCFbt5LZwdYZ?<usrmy6ZMtD5;bcLE^ba^m^t#uEdJWzz~5 zkZqX`U;`Eb!Bd5Zw93<Kts?RYL_g_f08iULQ?6>7_CS644_Lf%-}b0WfdBvi07*qo IM6N<$f>2qYivR!s literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/img/ico/alert-ok.png b/src/static/movio/templates/Skeleton/img/ico/alert-ok.png new file mode 100644 index 0000000000000000000000000000000000000000..1028f985b374e276ccd6a3f1eed040ad1bcb77b6 GIT binary patch literal 1289 zcmV+k1@`)hP)<h;3K|Lk000e1NJLTq001HY001Be1^@s6caN&c00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy5G%YYT zEiy1MGk$A`KmY&$9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00do0L_t(og|(PlOk7nIhQB>bnW4z7+*2sUVB-W-l%_%r)&Oa(XiRLisnI5ltv-N> zB|d2%G--Wq2z{s+Vod5S#Rsq?3QFr#FvS!~M60PvrxFU~Higawn6rGCIb@ibGeZlk zWG8!{^PfH6ti9J+dmY6(n~3ZODuGhK4qQ-5bp_pDZv;PtM7GaGq(}!@R~Qi~5)qe( zNWZgNx+lMu-)4Jc-sjO_Tq1Hp2T|(?@-0w1>>lE>^Sh<%8{?8Gd7y%=3B~%QlfdzH z0TGcSK=ZujrG5Nk7Q`E-$%@aXD*XV!AHbugb$~Df4FFf}{J^~CMnns1W8NE#dmR8a zpwhh7AiycWHs*Ekw`<T)lo*#nmSqco1F)|th=|kxbpU<N@6kjv)Rv`G>s>prxYizN z02sJ)k;(Z{Ls7P+fPCvVfKlKbfHeaVk#~W;bBi+!&Gtt1#*Wn8dbb6bSThh2$spj3 zU#2_o_*{nChZ0NKv>^weS1EN|f0?b7M;d|LVb|~c;~Fv)#ha{@r#+_+TY~Sc8YGZQ z4tg~=KToxziO*15l2k#w$qH~@DfP*UKt!YzKq)m4gQWqWZ@Lrb!i1qH$(+Xa)Ea$w zD)fHX3r$37M5G7k2l_>%M?^{tU{3%Qx93ObcV56JKEw9ZrWf?b&IV^+-OM2q*8rUW zx4k0(WLh>?0GCDNX{FS!LE7!W`v4awTG3?D&>Nc*ig+;b5eN!bLl6<k$G_?5ojOnN zR0jZivR<b+xjX^r6Op4qYx@Dfm6>iFu0IVS0CuInq<34CQW4iL*du2E+fDahT$*fO zy4W%HDIV=EWvSHw%|T~}TCe8f(qtRHXd5)Sf=o*u1j5xwX9f_FCSb2~VUpI7rm&sg zHU1^HJPvAe4g)mf&zN+Le}&sOX9!_2B~X?5vOa7v6awZzwyXj;H_~W0@u1U=pz(ap z8vr(k>l%Yjd$hSJORdIY+6WQCH4Fs*dD3>nb&XNaaMXzhW`05wjmJ_dX&Y^hx+EzZ zGN{aWQ6GkdYpAJ!M+O1gnSbA7%;Sjl%!=%lykk6^R0jTVea%Rx?>UoFY7zJm;H|=s z*papyO?<0rTN1YE5QgCzYGweXRDFP~?%A9}6eQaCX5@6#<Q2{K<Q&qwhT$4&%g(HU zywM2cj(Ub^{jVwJz6rG_QlDX8UOo83b!RO7($XxWQtBM=B+#2{-O7=|4|zOwSHv@C zq-HT$sm(pCPZu>@LoF=VD5Y)&{>c~CxJ35nz0JP7I^yFjX!xSGo$0k$;}T&7;TjVp z2<TPdDBvzjtLDwZlVn>8&_s*avMmMFWFOQYj~T9EzZXjoC=EXYD%`%ibly6PeWGod zrZ}aX1Np~D@O$I5QmTHX0QX#O2I^IRt++TR*JrQF_1UZ9TAW)})85;x_gVV}ifVg= zqS_ufJm0ges`eF;H2j|#00xv&)Auuv4g&B$LpZhz*wdpE00000NkvXXu0mjf$zViH literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/img/ico/arrow-baloon-big.png b/src/static/movio/templates/Skeleton/img/ico/arrow-baloon-big.png new file mode 100644 index 0000000000000000000000000000000000000000..7348b99777331bbeb13f4e09145d57b41f1558ae GIT binary patch literal 599 zcmV-d0;v6oP)<h;3K|Lk000e1NJLTq000sI000mO1^@s68wM|200004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy4G%YYT zEiy1MGnHI3LjV8(9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00FB>L_t(Ijh&LQZlgdDhJV%vTCK=H7Gw&)231ni+!Lg^Yfwm=G|4Nt;3@JDDR=-X z1g3)$Su`#!Bt&z24fr?{pHKOv)k-@v-~KzZ8kW+=#Q<nomVE~R-}gTNC;-34U42sf z7lZ*=0nm%0cx{?SHBF<6qId<Mk1;mp{u8tUpod|2Q&pAfx=wXnr>d$_VHn=bU>8A? zn{NP&vMjf4+p1w0)G!RHZCh2A<raW3=6vdE>dOj%o+OE1*R|^V{sij#Ue$H2k|goZ zTxl4o=P>4ZUL>UiV}HVoF-R%ld0sSgb8<94&;YP3%N|VAd?cd9+ldIKX+CCI_HbT1 zU3nTe=R9&<_fj9>x-K~9(Y$8iD9`g}BD&+8Uj%W^K}2_Xo<E;E(g0|29N!8dwo=NA zkV#TX2qCs{9N#WLK@hxImIYncuYz=4hh<p^g5YfqLYk)cLWmdJwy#1a*|rTK#7ml{ z_rN%QB3g|5nx^kSL=gaJyWQ>w5xs9VoBxK))wV5;$Ky|C7{-(1IA4MQfa5qY4C6`L l@AqoGUVj+`0Efc?zX1VMievRbFK++<002ovPDHLkV1j6L@8tjh literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/img/ico/arrow-baloon.png b/src/static/movio/templates/Skeleton/img/ico/arrow-baloon.png new file mode 100644 index 0000000000000000000000000000000000000000..8bf5f098b4317b167bb4c1f6a5212b274d546970 GIT binary patch literal 381 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)8<3o<+3y6TSc;uILpXq-h9ji|$mcBZh%9Dc z;1&X5#!GkW{s09fN?apKoQqNuOEUBG6hbm{QyB~`bq$PkjSLKp|2Iuz0;-V%sR_<c zD=AMbN@Z|N$xljEaLX)8Ezd8?E>>_3Hq|p+E${IfsPdwxi(`n!#MVCBuI2y{xAVo^ zc?VtZxTeT%X1v|F@{*tY39X=;?FV8TuP#t9(^~YS>!5wyEE|rV#qp&-ceKBk2rXqu zln`<ijNW){(lSkkM*Z8{mcHKQ`@pubLqdV=#OFDwk>CEwGd6V8FmJD%r`eTM|L|>J z<NalsFMj`%5SS?c;LX)*rM58+F6SJKd@t|MI_M_OoE>|e=Wqc}hsUd{n{<9J-nJE} zoAIPY-;~r!o;{y9142cwMcu!9makz|TmyeH&pFG6%lG!TuUqvh<SW+)mL{8o<F9pv RYJi?&@O1TaS?83{1OQkbk#hh5 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/img/logo-footer.png b/src/static/movio/templates/Skeleton/img/logo-footer.png new file mode 100644 index 0000000000000000000000000000000000000000..41ccbf3aa441762af105af154051c41a6bdd9e54 GIT binary patch literal 4557 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/img/logo_movio.png b/src/static/movio/templates/Skeleton/img/logo_movio.png new file mode 100644 index 0000000000000000000000000000000000000000..f0dddb4349c2ff134643a00a5141404b05696661 GIT binary patch literal 2067 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/js/bootstrap.min.js b/src/static/movio/templates/Skeleton/js/bootstrap.min.js new file mode 100755 index 0000000..b04a0e8 --- /dev/null +++ b/src/static/movio/templates/Skeleton/js/bootstrap.min.js @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.1.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.isLoading=!1};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",f.resetText||d.data("resetText",d[e]()),d[e](f[b]||this.options[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},b.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});return this.$element.trigger(j),j.isDefaultPrevented()?void 0:(this.sliding=!0,f&&this.pause(),this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")),f&&this.cycle(),this)};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);!e&&f.toggle&&"show"==c&&(c=!c),e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(b){a(d).remove(),a(e).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown",h),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=" li:not(.divider):visible a",i=f.find("[role=menu]"+h+", [role=listbox]"+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j<i.length-1&&j++,~j||(j=0),i.eq(j).focus()}}}};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.dropdown.Constructor=f,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu], [role=listbox]",f.prototype.keydown)}(jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show().scrollTop(0),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)}))},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=a.support.transition&&c;if(this.$backdrop=a('<div class="modal-backdrop '+c+'" />').appendTo(document.body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());c.is("a")&&b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this,d=this.tip();this.setContent(),this.options.animation&&d.addClass("fade");var e="function"==typeof this.options.placement?this.options.placement.call(this,d[0],this.$element[0]):this.options.placement,f=/\s?auto?\s?/i,g=f.test(e);g&&(e=e.replace(f,"")||"top"),d.detach().css({top:0,left:0,display:"block"}).addClass(e),this.options.container?d.appendTo(this.options.container):d.insertAfter(this.$element);var h=this.getPosition(),i=d[0].offsetWidth,j=d[0].offsetHeight;if(g){var k=this.$element.parent(),l=e,m=document.documentElement.scrollTop||document.body.scrollTop,n="body"==this.options.container?window.innerWidth:k.outerWidth(),o="body"==this.options.container?window.innerHeight:k.outerHeight(),p="body"==this.options.container?0:k.offset().left;e="bottom"==e&&h.top+h.height+j-m>o?"top":"top"==e&&h.top-m-j<0?"bottom":"right"==e&&h.right+i>n?"left":"left"==e&&h.left-i<p?"right":e,d.removeClass(l).addClass(e)}var q=this.getCalculatedOffset(e,h,i,j);this.applyPlacement(q,e),this.hoverState=null;var r=function(){c.$element.trigger("shown.bs."+c.type)};a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,r).emulateTransitionEnd(150):r()}},b.prototype.applyPlacement=function(b,c){var d,e=this.tip(),f=e[0].offsetWidth,g=e[0].offsetHeight,h=parseInt(e.css("margin-top"),10),i=parseInt(e.css("margin-left"),10);isNaN(h)&&(h=0),isNaN(i)&&(i=0),b.top=b.top+h,b.left=b.left+i,a.offset.setOffset(e[0],a.extend({using:function(a){e.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),e.addClass("in");var j=e[0].offsetWidth,k=e[0].offsetHeight;if("top"==c&&k!=g&&(d=!0,b.top=b.top+g-k),/bottom|top/.test(c)){var l=0;b.left<0&&(l=-2*b.left,b.left=0,e.offset(b),j=e[0].offsetWidth,k=e[0].offsetHeight),this.replaceArrow(l-f+j,j,"left")}else this.replaceArrow(k-g,k,"top");d&&e.offset(b)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach(),c.$element.trigger("hidden.bs."+c.type)}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.hoverState=null,this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(a(c).is("body")?window:c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);{var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})}},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(b.RESET).addClass("affix");var a=this.$window.scrollTop(),c=this.$element.offset();return this.pinnedOffset=c.top-a},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"top"==this.affixed&&(e.top+=d),"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(b.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:c-h-this.$element.height()}))}}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/js/jquery-1.8.2.min.js b/src/static/movio/templates/Skeleton/js/jquery-1.8.2.min.js new file mode 100755 index 0000000..bc3fbc8 --- /dev/null +++ b/src/static/movio/templates/Skeleton/js/jquery-1.8.2.min.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d<e;d++)p.event.add(b,c,h[c][d])}g.data&&(g.data=p.extend({},g.data))}function bE(a,b){var c;if(b.nodeType!==1)return;b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?(b.parentNode&&(b.outerHTML=a.outerHTML),p.support.html5Clone&&a.innerHTML&&!p.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):c==="input"&&bv.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text),b.removeAttribute(p.expando)}function bF(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bG(a){bv.test(a.type)&&(a.defaultChecked=a.checked)}function bY(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=bW.length;while(e--){b=bW[e]+c;if(b in a)return b}return d}function bZ(a,b){return a=b||a,p.css(a,"display")==="none"||!p.contains(a.ownerDocument,a)}function b$(a,b){var c,d,e=[],f=0,g=a.length;for(;f<g;f++){c=a[f];if(!c.style)continue;e[f]=p._data(c,"olddisplay"),b?(!e[f]&&c.style.display==="none"&&(c.style.display=""),c.style.display===""&&bZ(c)&&(e[f]=p._data(c,"olddisplay",cc(c.nodeName)))):(d=bH(c,"display"),!e[f]&&d!=="none"&&p._data(c,"olddisplay",d))}for(f=0;f<g;f++){c=a[f];if(!c.style)continue;if(!b||c.style.display==="none"||c.style.display==="")c.style.display=b?e[f]||"":"none"}return a}function b_(a,b,c){var d=bP.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function ca(a,b,c,d){var e=c===(d?"border":"content")?4:b==="width"?1:0,f=0;for(;e<4;e+=2)c==="margin"&&(f+=p.css(a,c+bV[e],!0)),d?(c==="content"&&(f-=parseFloat(bH(a,"padding"+bV[e]))||0),c!=="margin"&&(f-=parseFloat(bH(a,"border"+bV[e]+"Width"))||0)):(f+=parseFloat(bH(a,"padding"+bV[e]))||0,c!=="padding"&&(f+=parseFloat(bH(a,"border"+bV[e]+"Width"))||0));return f}function cb(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=!0,f=p.support.boxSizing&&p.css(a,"boxSizing")==="border-box";if(d<=0||d==null){d=bH(a,b);if(d<0||d==null)d=a.style[b];if(bQ.test(d))return d;e=f&&(p.support.boxSizingReliable||d===a.style[b]),d=parseFloat(d)||0}return d+ca(a,b,c||(f?"border":"content"),e)+"px"}function cc(a){if(bS[a])return bS[a];var b=p("<"+a+">").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write("<!doctype html><html><body>"),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h<i;h++)d=g[h],f=/^\+/.test(d),f&&(d=d.substr(1)||"*"),e=a[d]=a[d]||[],e[f?"unshift":"push"](c)}}function cA(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h,i=a[f],j=0,k=i?i.length:0,l=a===cv;for(;j<k&&(l||!h);j++)h=i[j](c,d,e),typeof h=="string"&&(!l||g[h]?h=b:(c.dataTypes.unshift(h),h=cA(a,c,d,e,h,g)));return(l||!h)&&!g["*"]&&(h=cA(a,c,d,e,"*",g)),h}function cB(a,c){var d,e,f=p.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((f[d]?a:e||(e={}))[d]=c[d]);e&&p.extend(!0,a,e)}function cC(a,c,d){var e,f,g,h,i=a.contents,j=a.dataTypes,k=a.responseFields;for(f in k)f in d&&(c[k[f]]=d[f]);while(j[0]==="*")j.shift(),e===b&&(e=a.mimeType||c.getResponseHeader("content-type"));if(e)for(f in i)if(i[f]&&i[f].test(e)){j.unshift(f);break}if(j[0]in d)g=j[0];else{for(f in d){if(!j[0]||a.converters[f+" "+j[0]]){g=f;break}h||(h=f)}g=g||h}if(g)return g!==j[0]&&j.unshift(g),d[g]}function cD(a,b){var c,d,e,f,g=a.dataTypes.slice(),h=g[0],i={},j=0;a.dataFilter&&(b=a.dataFilter(b,a.dataType));if(g[1])for(c in a.converters)i[c.toLowerCase()]=a.converters[c];for(;e=g[++j];)if(e!=="*"){if(h!=="*"&&h!==e){c=i[h+" "+e]||i["* "+e];if(!c)for(d in i){f=d.split(" ");if(f[1]===e){c=i[h+" "+f[0]]||i["* "+f[0]];if(c){c===!0?c=i[d]:i[d]!==!0&&(e=f[0],g.splice(j--,0,e));break}}}if(c!==!0)if(c&&a["throws"])b=c(b);else try{b=c(b)}catch(k){return{state:"parsererror",error:c?k:"No conversion from "+h+" to "+e}}}h=e}return{state:"success",data:b}}function cL(){try{return new a.XMLHttpRequest}catch(b){}}function cM(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function cU(){return setTimeout(function(){cN=b},0),cN=p.now()}function cV(a,b){p.each(b,function(b,c){var d=(cT[b]||[]).concat(cT["*"]),e=0,f=d.length;for(;e<f;e++)if(d[e].call(a,b,c))return})}function cW(a,b,c){var d,e=0,f=0,g=cS.length,h=p.Deferred().always(function(){delete i.elem}),i=function(){var b=cN||cU(),c=Math.max(0,j.startTime+j.duration-b),d=1-(c/j.duration||0),e=0,f=j.tweens.length;for(;e<f;e++)j.tweens[e].run(d);return h.notifyWith(a,[j,d,c]),d<1&&f?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:p.extend({},b),opts:p.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:cN||cU(),duration:c.duration,tweens:[],createTween:function(b,c,d){var e=p.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(e),e},stop:function(b){var c=0,d=b?j.tweens.length:0;for(;c<d;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;cX(k,j.opts.specialEasing);for(;e<g;e++){d=cS[e].call(j,a,k,j.opts);if(d)return d}return cV(j,k),p.isFunction(j.opts.start)&&j.opts.start.call(a,j),p.fx.timer(p.extend(i,{anim:j,queue:j.opts.queue,elem:a})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}function cX(a,b){var c,d,e,f,g;for(c in a){d=p.camelCase(c),e=b[d],f=a[c],p.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=p.cssHooks[d];if(g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}}function cY(a,b,c){var d,e,f,g,h,i,j,k,l=this,m=a.style,n={},o=[],q=a.nodeType&&bZ(a);c.queue||(j=p._queueHooks(a,"fx"),j.unqueued==null&&(j.unqueued=0,k=j.empty.fire,j.empty.fire=function(){j.unqueued||k()}),j.unqueued++,l.always(function(){l.always(function(){j.unqueued--,p.queue(a,"fx").length||j.empty.fire()})})),a.nodeType===1&&("height"in b||"width"in b)&&(c.overflow=[m.overflow,m.overflowX,m.overflowY],p.css(a,"display")==="inline"&&p.css(a,"float")==="none"&&(!p.support.inlineBlockNeedsLayout||cc(a.nodeName)==="inline"?m.display="inline-block":m.zoom=1)),c.overflow&&(m.overflow="hidden",p.support.shrinkWrapBlocks||l.done(function(){m.overflow=c.overflow[0],m.overflowX=c.overflow[1],m.overflowY=c.overflow[2]}));for(d in b){f=b[d];if(cP.exec(f)){delete b[d];if(f===(q?"hide":"show"))continue;o.push(d)}}g=o.length;if(g){h=p._data(a,"fxshow")||p._data(a,"fxshow",{}),q?p(a).show():l.done(function(){p(a).hide()}),l.done(function(){var b;p.removeData(a,"fxshow",!0);for(b in n)p.style(a,b,n[b])});for(d=0;d<g;d++)e=o[d],i=l.createTween(e,q?h[e]:0),n[e]=h[e]||p.style(a,e),e in h||(h[e]=i.start,q&&(i.end=i.start,i.start=e==="width"||e==="height"?1:0))}}function cZ(a,b,c,d,e){return new cZ.prototype.init(a,b,c,d,e)}function c$(a,b){var c,d={height:a},e=0;b=b?1:0;for(;e<4;e+=2-b)c=bV[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function da(a){return p.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}var c,d,e=a.document,f=a.location,g=a.navigator,h=a.jQuery,i=a.$,j=Array.prototype.push,k=Array.prototype.slice,l=Array.prototype.indexOf,m=Object.prototype.toString,n=Object.prototype.hasOwnProperty,o=String.prototype.trim,p=function(a,b){return new p.fn.init(a,b,c)},q=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,r=/\S/,s=/\s+/,t=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,u=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i<j;i++)if((a=arguments[i])!=null)for(c in a){d=h[c],e=a[c];if(h===e)continue;k&&e&&(p.isPlainObject(e)||(f=p.isArray(e)))?(f?(f=!1,g=d&&p.isArray(d)?d:[]):g=d&&p.isPlainObject(d)?d:{},h[c]=p.extend(k,g,e)):e!==b&&(h[c]=e)}return h},p.extend({noConflict:function(b){return a.$===p&&(a.$=i),b&&a.jQuery===p&&(a.jQuery=h),p},isReady:!1,readyWait:1,holdReady:function(a){a?p.readyWait++:p.ready(!0)},ready:function(a){if(a===!0?--p.readyWait:p.isReady)return;if(!e.body)return setTimeout(p.ready,1);p.isReady=!0;if(a!==!0&&--p.readyWait>0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f<g;)if(c.apply(a[f++],d)===!1)break}else if(h){for(e in a)if(c.call(a[e],e,a[e])===!1)break}else for(;f<g;)if(c.call(a[f],f,a[f++])===!1)break;return a},trim:o&&!o.call(" ")?function(a){return a==null?"":o.call(a)}:function(a){return a==null?"":(a+"").replace(t,"")},makeArray:function(a,b){var c,d=b||[];return a!=null&&(c=p.type(a),a.length==null||c==="string"||c==="function"||c==="regexp"||p.isWindow(a)?j.call(d,a):p.merge(d,a)),d},inArray:function(a,b,c){var d;if(b){if(l)return l.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=c.length,e=a.length,f=0;if(typeof d=="number")for(;f<d;f++)a[e++]=c[f];else while(c[f]!==b)a[e++]=c[f++];return a.length=e,a},grep:function(a,b,c){var d,e=[],f=0,g=a.length;c=!!c;for(;f<g;f++)d=!!b(a[f],f),c!==d&&e.push(a[f]);return e},map:function(a,c,d){var e,f,g=[],h=0,i=a.length,j=a instanceof p||i!==b&&typeof i=="number"&&(i>0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h<i;h++)e=c(a[h],h,d),e!=null&&(g[g.length]=e);else for(f in a)e=c(a[f],f,d),e!=null&&(g[g.length]=e);return g.concat.apply([],g)},guid:1,proxy:function(a,c){var d,e,f;return typeof c=="string"&&(d=a[c],c=a,a=d),p.isFunction(a)?(e=k.call(arguments,2),f=function(){return a.apply(c,e.concat(k.call(arguments)))},f.guid=a.guid=a.guid||p.guid++,f):b},access:function(a,c,d,e,f,g,h){var i,j=d==null,k=0,l=a.length;if(d&&typeof d=="object"){for(k in d)p.access(a,c,k,d[k],1,g,e);f=1}else if(e!==b){i=h===b&&p.isFunction(e),j&&(i?(i=c,c=function(a,b,c){return i.call(p(a),c)}):(c.call(a,e),c=null));if(c)for(;k<l;k++)c(a[k],d,i?e.call(a[k],k,c(a[k],d)):e,h);f=1}return f?a:j?c.call(a):l?c(a[0],d):g},now:function(){return(new Date).getTime()}}),p.ready.promise=function(b){if(!d){d=p.Deferred();if(e.readyState==="complete")setTimeout(p.ready,1);else if(e.addEventListener)e.addEventListener("DOMContentLoaded",D,!1),a.addEventListener("load",p.ready,!1);else{e.attachEvent("onreadystatechange",D),a.attachEvent("onload",p.ready);var c=!1;try{c=a.frameElement==null&&e.documentElement}catch(f){}c&&c.doScroll&&function g(){if(!p.isReady){try{c.doScroll("left")}catch(a){return setTimeout(g,50)}p.ready()}}()}}return d.promise(b)},p.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){E["[object "+b+"]"]=b.toLowerCase()}),c=p(e);var F={};p.Callbacks=function(a){a=typeof a=="string"?F[a]||G(a):p.extend({},a);var c,d,e,f,g,h,i=[],j=!a.once&&[],k=function(b){c=a.memory&&b,d=!0,h=f||0,f=0,g=i.length,e=!0;for(;i&&h<g;h++)if(i[h].apply(b[0],b[1])===!1&&a.stopOnFalse){c=!1;break}e=!1,i&&(j?j.length&&k(j.shift()):c?i=[]:l.disable())},l={add:function(){if(i){var b=i.length;(function d(b){p.each(b,function(b,c){var e=p.type(c);e==="function"&&(!a.unique||!l.has(c))?i.push(c):c&&c.length&&e!=="string"&&d(c)})})(arguments),e?g=i.length:c&&(f=b,k(c))}return this},remove:function(){return i&&p.each(arguments,function(a,b){var c;while((c=p.inArray(b,i,c))>-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b<d;b++)c[b]&&p.isFunction(c[b].promise)?c[b].promise().done(g(b,j,c)).fail(f.reject).progress(g(b,i,h)):--e}return e||f.resolveWith(j,c),f.promise()}}),p.support=function(){var b,c,d,f,g,h,i,j,k,l,m,n=e.createElement("div");n.setAttribute("className","t"),n.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="<div></div>",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e<f;e++)delete d[b[e]];if(!(c?K:p.isEmptyObject)(d))return}}if(!c){delete h[i].data;if(!K(h[i]))return}g?p.cleanData([a],!0):p.support.deleteExpando||h!=h.window?delete h[i]:h[i]=null},_data:function(a,b,c){return p.data(a,b,c,!0)},acceptData:function(a){var b=a.nodeName&&p.noData[a.nodeName.toLowerCase()];return!b||b!==!0&&a.getAttribute("classid")===b}}),p.fn.extend({data:function(a,c){var d,e,f,g,h,i=this[0],j=0,k=null;if(a===b){if(this.length){k=p.data(i);if(i.nodeType===1&&!p._data(i,"parsedAttrs")){f=i.attributes;for(h=f.length;j<h;j++)g=f[j].name,g.indexOf("data-")||(g=p.camelCase(g.substring(5)),J(i,g,k[g]));p._data(i,"parsedAttrs",!0)}}return k}return typeof a=="object"?this.each(function(){p.data(this,a)}):(d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!",p.access(this,function(c){if(c===b)return k=this.triggerHandler("getData"+e,[d[0]]),k===b&&i&&(k=p.data(i,a),k=J(i,a,k)),k===b&&d[1]?this.data(d[0]):k;d[1]=c,this.each(function(){var b=p(this);b.triggerHandler("setData"+e,d),p.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length<d?p.queue(this[0],a):c===b?this:this.each(function(){var b=p.queue(this,a,c);p._queueHooks(this,a),a==="fx"&&b[0]!=="inprogress"&&p.dequeue(this,a)})},dequeue:function(a){return this.each(function(){p.dequeue(this,a)})},delay:function(a,b){return a=p.fx?p.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){var d,e=1,f=p.Deferred(),g=this,h=this.length,i=function(){--e||f.resolveWith(g,[g])};typeof a!="string"&&(c=a,a=b),a=a||"fx";while(h--)d=p._data(g[h],a+"queueHooks"),d&&d.empty&&(e++,d.empty.add(i));return i(),f.promise(c)}});var L,M,N,O=/[\t\r\n]/g,P=/\r/g,Q=/^(?:button|input)$/i,R=/^(?:button|input|object|select|textarea)$/i,S=/^a(?:rea|)$/i,T=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,U=p.support.getSetAttribute;p.fn.extend({attr:function(a,b){return p.access(this,p.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{f=" "+e.className+" ";for(g=0,h=b.length;g<h;g++)f.indexOf(" "+b[g]+" ")<0&&(f+=b[g]+" ");e.className=p.trim(f)}}}return this},removeClass:function(a){var c,d,e,f,g,h,i;if(p.isFunction(a))return this.each(function(b){p(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(s);for(h=0,i=this.length;h<i;h++){e=this[h];if(e.nodeType===1&&e.className){d=(" "+e.className+" ").replace(O," ");for(f=0,g=c.length;f<g;f++)while(d.indexOf(" "+c[f]+" ")>=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(O," ").indexOf(b)>=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c<d;c++){e=h[c];if(e.selected&&(p.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!p.nodeName(e.parentNode,"optgroup"))){b=p(e).val();if(i)return b;g.push(b)}}return i&&!g.length&&h.length?p(h[f]).val():g},set:function(a,b){var c=p.makeArray(b);return p(a).find("option").each(function(){this.selected=p.inArray(p(this).val(),c)>=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g<d.length;g++)e=d[g],e&&(c=p.propFix[e]||e,f=T.test(e),f||p.attr(a,e,""),a.removeAttribute(U?e:c),f&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(Q.test(a.nodeName)&&a.parentNode)p.error("type property can't be changed");else if(!p.support.radioValue&&b==="radio"&&p.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}},value:{get:function(a,b){return L&&p.nodeName(a,"button")?L.get(a,b):b in a?a.value:null},set:function(a,b,c){if(L&&p.nodeName(a,"button"))return L.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,f,g,h=a.nodeType;if(!a||h===3||h===8||h===2)return;return g=h!==1||!p.isXMLDoc(a),g&&(c=p.propFix[c]||c,f=p.propHooks[c]),d!==b?f&&"set"in f&&(e=f.set(a,d,c))!==b?e:a[c]=d:f&&"get"in f&&(e=f.get(a,c))!==null?e:a[c]},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):R.test(a.nodeName)||S.test(a.nodeName)&&a.href?0:b}}}}),M={get:function(a,c){var d,e=p.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;return b===!1?p.removeAttr(a,c):(d=p.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase())),c}},U||(N={name:!0,id:!0,coords:!0},L=p.valHooks.button={get:function(a,c){var d;return d=a.getAttributeNode(c),d&&(N[c]?d.value!=="":d.specified)?d.value:b},set:function(a,b,c){var d=a.getAttributeNode(c);return d||(d=e.createAttribute(c),a.setAttributeNode(d)),d.value=b+""}},p.each(["width","height"],function(a,b){p.attrHooks[b]=p.extend(p.attrHooks[b],{set:function(a,c){if(c==="")return a.setAttribute(b,"auto"),c}})}),p.attrHooks.contenteditable={get:L.get,set:function(a,b,c){b===""&&(b="false"),L.set(a,b,c)}}),p.support.hrefNormalized||p.each(["href","src","width","height"],function(a,c){p.attrHooks[c]=p.extend(p.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),p.support.style||(p.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=b+""}}),p.support.optSelected||(p.propHooks.selected=p.extend(p.propHooks.selected,{get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}})),p.support.enctype||(p.propFix.enctype="encoding"),p.support.checkOn||p.each(["radio","checkbox"],function(){p.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),p.each(["radio","checkbox"],function(){p.valHooks[this]=p.extend(p.valHooks[this],{set:function(a,b){if(p.isArray(b))return a.checked=p.inArray(p(a).val(),b)>=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j<c.length;j++){k=W.exec(c[j])||[],l=k[1],m=(k[2]||"").split(".").sort(),r=p.event.special[l]||{},l=(f?r.delegateType:r.bindType)||l,r=p.event.special[l]||{},n=p.extend({type:l,origType:k[1],data:e,handler:d,guid:d.guid,selector:f,needsContext:f&&p.expr.match.needsContext.test(f),namespace:m.join(".")},o),q=i[l];if(!q){q=i[l]=[],q.delegateCount=0;if(!r.setup||r.setup.call(a,e,m,h)===!1)a.addEventListener?a.addEventListener(l,h,!1):a.attachEvent&&a.attachEvent("on"+l,h)}r.add&&(r.add.call(a,n),n.handler.guid||(n.handler.guid=d.guid)),f?q.splice(q.delegateCount++,0,n):q.push(n),p.event.global[l]=!0}a=null},global:{},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,q,r=p.hasData(a)&&p._data(a);if(!r||!(m=r.events))return;b=p.trim(_(b||"")).split(" ");for(f=0;f<b.length;f++){g=W.exec(b[f])||[],h=i=g[1],j=g[2];if(!h){for(h in m)p.event.remove(a,h+b[f],c,d,!0);continue}n=p.event.special[h]||{},h=(d?n.delegateType:n.bindType)||h,o=m[h]||[],k=o.length,j=j?new RegExp("(^|\\.)"+j.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(l=0;l<o.length;l++)q=o[l],(e||i===q.origType)&&(!c||c.guid===q.guid)&&(!j||j.test(q.namespace))&&(!d||d===q.selector||d==="**"&&q.selector)&&(o.splice(l--,1),q.selector&&o.delegateCount--,n.remove&&n.remove.call(a,q));o.length===0&&k!==o.length&&((!n.teardown||n.teardown.call(a,j,r.handle)===!1)&&p.removeEvent(a,h,r.handle),delete m[h])}p.isEmptyObject(m)&&(delete r.handle,p.removeData(a,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,f,g){if(!f||f.nodeType!==3&&f.nodeType!==8){var h,i,j,k,l,m,n,o,q,r,s=c.type||c,t=[];if($.test(s+p.event.triggered))return;s.indexOf("!")>=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j<q.length&&!c.isPropagationStopped();j++)k=q[j][0],c.type=q[j][1],o=(p._data(k,"events")||{})[c.type]&&p._data(k,"handle"),o&&o.apply(k,d),o=m&&k[m],o&&p.acceptData(k)&&o.apply&&o.apply(k,d)===!1&&c.preventDefault();return c.type=s,!g&&!c.isDefaultPrevented()&&(!n._default||n._default.apply(f.ownerDocument,d)===!1)&&(s!=="click"||!p.nodeName(f,"a"))&&p.acceptData(f)&&m&&f[s]&&(s!=="focus"&&s!=="blur"||c.target.offsetWidth!==0)&&!p.isWindow(f)&&(l=f[m],l&&(f[m]=null),p.event.triggered=s,f[s](),p.event.triggered=b,l&&(f[m]=l)),c.result}return},dispatch:function(c){c=p.event.fix(c||a.event);var d,e,f,g,h,i,j,l,m,n,o=(p._data(this,"events")||{})[c.type]||[],q=o.delegateCount,r=k.call(arguments),s=!c.exclusive&&!c.namespace,t=p.event.special[c.type]||{},u=[];r[0]=c,c.delegateTarget=this;if(t.preDispatch&&t.preDispatch.call(this,c)===!1)return;if(q&&(!c.button||c.type!=="click"))for(f=c.target;f!=this;f=f.parentNode||this)if(f.disabled!==!0||c.type!=="click"){h={},j=[];for(d=0;d<q;d++)l=o[d],m=l.selector,h[m]===b&&(h[m]=l.needsContext?p(m,this).index(f)>=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d<u.length&&!c.isPropagationStopped();d++){i=u[d],c.currentTarget=i.elem;for(e=0;e<i.matches.length&&!c.isImmediatePropagationStopped();e++){l=i.matches[e];if(s||!c.namespace&&!l.namespace||c.namespace_re&&c.namespace_re.test(l.namespace))c.data=l.data,c.handleObj=l,g=((p.event.special[l.origType]||{}).handle||l.handler).apply(i.elem,r),g!==b&&(c.result=g,g===!1&&(c.preventDefault(),c.stopPropagation()))}}return t.postDispatch&&t.postDispatch.call(this,c),c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,c){var d,f,g,h=c.button,i=c.fromElement;return a.pageX==null&&c.clientX!=null&&(d=a.target.ownerDocument||e,f=d.documentElement,g=d.body,a.pageX=c.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=c.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?c.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0),a}},fix:function(a){if(a[p.expando])return a;var b,c,d=a,f=p.event.fixHooks[a.type]||{},g=f.props?this.props.concat(f.props):this.props;a=p.Event(d);for(b=g.length;b;)c=g[--b],a[c]=d[c];return a.target||(a.target=d.srcElement||e),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,f.filter?f.filter(a,d):a},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){p.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=p.extend(new p.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?p.event.trigger(e,null,b):p.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},p.event.handle=p.event.dispatch,p.removeEvent=e.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]=="undefined"&&(a[d]=null),a.detachEvent(d,c))},p.Event=function(a,b){if(this instanceof p.Event)a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?bb:ba):this.type=a,b&&p.extend(this,b),this.timeStamp=a&&a.timeStamp||p.now(),this[p.expando]=!0;else return new p.Event(a,b)},p.Event.prototype={preventDefault:function(){this.isDefaultPrevented=bb;var a=this.originalEvent;if(!a)return;a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=bb;var a=this.originalEvent;if(!a)return;a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=bb,this.stopPropagation()},isDefaultPrevented:ba,isPropagationStopped:ba,isImmediatePropagationStopped:ba},p.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){p.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj,g=f.selector;if(!e||e!==d&&!p.contains(d,e))a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b;return c}}}),p.support.submitBubbles||(p.event.special.submit={setup:function(){if(p.nodeName(this,"form"))return!1;p.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=p.nodeName(c,"input")||p.nodeName(c,"button")?c.form:b;d&&!p._data(d,"_submit_attached")&&(p.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),p._data(d,"_submit_attached",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&p.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(p.nodeName(this,"form"))return!1;p.event.remove(this,"._submit")}}),p.support.changeBubbles||(p.event.special.change={setup:function(){if(V.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")p.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),p.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),p.event.simulate("change",this,a,!0)});return!1}p.event.add(this,"beforeactivate._change",function(a){var b=a.target;V.test(b.nodeName)&&!p._data(b,"_change_attached")&&(p.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&p.event.simulate("change",this.parentNode,a,!0)}),p._data(b,"_change_attached",!0))})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){return p.event.remove(this,"._change"),!V.test(this.nodeName)}}),p.support.focusinBubbles||p.each({focus:"focusin",blur:"focusout"},function(a,b){var c=0,d=function(a){p.event.simulate(b,a.target,p.event.fix(a),!0)};p.event.special[b]={setup:function(){c++===0&&e.addEventListener(a,d,!0)},teardown:function(){--c===0&&e.removeEventListener(a,d,!0)}}}),p.fn.extend({on:function(a,c,d,e,f){var g,h;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(h in a)this.on(h,c,d,a[h],f);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=ba;else if(!e)return this;return f===1&&(g=e,e=function(a){return p().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=p.guid++)),this.each(function(){p.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){var e,f;if(a&&a.preventDefault&&a.handleObj)return e=a.handleObj,p(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler),this;if(typeof a=="object"){for(f in a)this.off(f,c,a[f]);return this}if(c===!1||typeof c=="function")d=c,c=b;return d===!1&&(d=ba),this.each(function(){p.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){return p(this.context).on(a,this.selector,b,c),this},die:function(a,b){return p(this.context).off(a,this.selector||"**",b),this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length===1?this.off(a,"**"):this.off(b,a||"**",c)},trigger:function(a,b){return this.each(function(){p.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return p.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||p.guid++,d=0,e=function(c){var e=(p._data(this,"lastToggle"+a.guid)||0)%d;return p._data(this,"lastToggle"+a.guid,e+1),c.preventDefault(),b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){p.fn[b]=function(a,c){return c==null&&(c=a,a=null),arguments.length>0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h<i;h++)if(f=a[h])if(!c||c(f,d,e))g.push(f),j&&b.push(h);return g}function bl(a,b,c,d,e,f){return d&&!d[o]&&(d=bl(d)),e&&!e[o]&&(e=bl(e,f)),z(function(f,g,h,i){if(f&&e)return;var j,k,l,m=[],n=[],o=g.length,p=f||bo(b||"*",h.nodeType?[h]:h,[],f),q=a&&(f||!b)?bk(p,m,a,h,i):p,r=c?e||(f?a:o||d)?[]:g:q;c&&c(q,r,h,i);if(d){l=bk(r,n),d(l,[],h,i),j=l.length;while(j--)if(k=l[j])r[n[j]]=!(q[n[j]]=k)}if(f){j=a&&r.length;while(j--)if(k=r[j])f[m[j]]=!(g[m[j]]=k)}else r=bk(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):w.apply(g,r)})}function bm(a){var b,c,d,f=a.length,g=e.relative[a[0].type],h=g||e.relative[" "],i=g?1:0,j=bi(function(a){return a===b},h,!0),k=bi(function(a){return y.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i<f;i++)if(c=e.relative[a[i].type])m=[bi(bj(m),c)];else{c=e.filter[a[i].type].apply(null,a[i].matches);if(c[o]){d=++i;for(;d<f;d++)if(e.relative[a[d].type])break;return bl(i>1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i<d&&bm(a.slice(i,d)),d<f&&bm(a=a.slice(d)),d<f&&a.join(""))}m.push(c)}return bj(m)}function bn(a,b){var d=b.length>0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e<f;e++)bc(a,b[e],c,d);return c}function bp(a,b,c,d,f){var g,h,j,k,l,m=bh(a),n=m.length;if(!d&&m.length===1){h=m[0]=m[0].slice(0);if(h.length>2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;b<c;b++)if(this[b]===a)return b;return-1},z=function(a,b){return a[o]=b==null||b,a},A=function(){var a={},b=[];return z(function(c,d){return b.push(c)>e.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="<select></select>";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="<a name='"+o+"'></a><div name='"+o+"'></div>",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d<b;d+=2)a.push(d);return a}),odd:bf(function(a,b,c){for(var d=1;d<b;d+=2)a.push(d);return a}),lt:bf(function(a,b,c){for(var d=c<0?c+b:c;--d>=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d<b;)a.push(d);return a})}},j=s.compareDocumentPosition?function(a,b){return a===b?(k=!0,0):(!a.compareDocumentPosition||!b.compareDocumentPosition?a.compareDocumentPosition:a.compareDocumentPosition(b)&4)?-1:1}:function(a,b){if(a===b)return k=!0,0;if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,h=b.parentNode,i=g;if(g===h)return bg(a,b);if(!g)return-1;if(!h)return 1;while(i)e.unshift(i),i=i.parentNode;i=h;while(i)f.unshift(i),i=i.parentNode;c=e.length,d=f.length;for(var j=0;j<c&&j<d;j++)if(e[j]!==f[j])return bg(e[j],f[j]);return j===c?bg(a,f[j],-1):bg(e[j],b,1)},[0,0].sort(j),m=!k,bc.uniqueSort=function(a){var b,c=1;k=m,a.sort(j);if(k)for(;b=a[c];c++)b===a[c-1]&&a.splice(c--,1);return a},bc.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},i=bc.compile=function(a,b){var c,d=[],e=[],f=D[o][a];if(!f){b||(b=bh(a)),c=b.length;while(c--)f=bm(b[c]),f[o]?d.push(f):e.push(f);f=D(a,bn(e,d))}return f},r.querySelectorAll&&function(){var a,b=bp,c=/'|\\/g,d=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,e=[":focus"],f=[":active",":focus"],h=s.matchesSelector||s.mozMatchesSelector||s.webkitMatchesSelector||s.oMatchesSelector||s.msMatchesSelector;X(function(a){a.innerHTML="<select><option selected=''></option></select>",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="<p test=''></p>",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="<input type='hidden'/>",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b<c;b++)if(p.contains(h[b],this))return!0});g=this.pushStack("","find",a);for(b=0,c=this.length;b<c;b++){d=g.length,p.find(a,this[b],g);if(b>0)for(e=d;e<g.length;e++)for(f=0;f<d;f++)if(g[f]===g[e]){g.splice(e--,1);break}}return g},has:function(a){var b,c=p(a,this),d=c.length;return this.filter(function(){for(b=0;b<d;b++)if(p.contains(this,c[b]))return!0})},not:function(a){return this.pushStack(bj(this,a,!1),"not",a)},filter:function(a){return this.pushStack(bj(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?bf.test(a)?p(a,this.context).index(this[0])>=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d<e;d++){c=this[d];while(c&&c.ownerDocument&&c!==b&&c.nodeType!==11){if(g?g.index(c)>-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/<tbody/i,br=/<|&#?\w+;/,bs=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,bu=new RegExp("<(?:"+bl+")[\\s/>]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,bz={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X<div>","</div>"]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(f){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){return bh(this[0])?this.length?this.pushStack(p(p.isFunction(a)?a():a),"replaceWith",a):this:p.isFunction(a)?this.each(function(b){var c=p(this),d=c.html();c.replaceWith(a.call(this,b,d))}):(typeof a!="string"&&(a=p(a).detach()),this.each(function(){var b=this.nextSibling,c=this.parentNode;p(this).remove(),b?p(b).before(a):p(c).append(a)}))},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){a=[].concat.apply([],a);var e,f,g,h,i=0,j=a[0],k=[],l=this.length;if(!p.support.checkClone&&l>1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i<l;i++)d.call(c&&p.nodeName(this[i],"table")?bC(this[i],"tbody"):this[i],i===h?g:p.clone(g,!0,!0))}g=f=null,k.length&&p.each(k,function(a,b){b.src?p.ajax?p.ajax({url:b.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):p.error("no ajax"):p.globalEval((b.text||b.textContent||b.innerHTML||"").replace(by,"")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),p.buildFragment=function(a,c,d){var f,g,h,i=a[0];return c=c||e,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,a.length===1&&typeof i=="string"&&i.length<512&&c===e&&i.charAt(0)==="<"&&!bt.test(i)&&(p.support.checkClone||!bw.test(i))&&(p.support.html5Clone||!bu.test(i))&&(g=!0,f=p.fragments[i],h=f!==b),f||(f=c.createDocumentFragment(),p.clean(a,c,f,d),g&&(p.fragments[i]=h&&f)),{fragment:f,cacheable:g}},p.fragments={},p.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){p.fn[a]=function(c){var d,e=0,f=[],g=p(c),h=g.length,i=this.length===1&&this[0].parentNode;if((i==null||i&&i.nodeType===11&&i.childNodes.length===1)&&h===1)return g[b](this[0]),this;for(;e<h;e++)d=(e>0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1></$2>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]==="<table>"&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("<div>").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d<e;d++)c=a[d],cT[c]=cT[c]||[],cT[c].unshift(b)},prefilter:function(a,b){b?cS.unshift(a):cS.push(a)}}),p.Tween=cZ,cZ.prototype={constructor:cZ,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(p.cssNumber[c]?"":"px")},cur:function(){var a=cZ.propHooks[this.prop];return a&&a.get?a.get(this):cZ.propHooks._default.get(this)},run:function(a){var b,c=cZ.propHooks[this.prop];return this.options.duration?this.pos=b=p.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):cZ.propHooks._default.set(this),this}},cZ.prototype.init.prototype=cZ.prototype,cZ.propHooks={_default:{get:function(a){var b;return a.elem[a.prop]==null||!!a.elem.style&&a.elem.style[a.prop]!=null?(b=p.css(a.elem,a.prop,!1,""),!b||b==="auto"?0:b):a.elem[a.prop]},set:function(a){p.fx.step[a.prop]?p.fx.step[a.prop](a):a.elem.style&&(a.elem.style[p.cssProps[a.prop]]!=null||p.cssHooks[a.prop])?p.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},cZ.propHooks.scrollTop=cZ.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},p.each(["toggle","show","hide"],function(a,b){var c=p.fn[b];p.fn[b]=function(d,e,f){return d==null||typeof d=="boolean"||!a&&p.isFunction(d)&&p.isFunction(e)?c.apply(this,arguments):this.animate(c$(b,!0),d,e,f)}}),p.fn.extend({fadeTo:function(a,b,c,d){return this.filter(bZ).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=p.isEmptyObject(a),f=p.speed(b,c,d),g=function(){var b=cW(this,p.extend({},a),f);e&&b.stop(!0)};return e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,c,d){var e=function(a){var b=a.stop;delete a.stop,b(d)};return typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,c=a!=null&&a+"queueHooks",f=p.timers,g=p._data(this);if(c)g[c]&&g[c].stop&&e(g[c]);else for(c in g)g[c]&&g[c].stop&&cR.test(c)&&e(g[c]);for(c=f.length;c--;)f[c].elem===this&&(a==null||f[c].queue===a)&&(f[c].anim.stop(d),b=!1,f.splice(c,1));(b||!d)&&p.dequeue(this,a)})}}),p.each({slideDown:c$("show"),slideUp:c$("hide"),slideToggle:c$("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){p.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),p.speed=function(a,b,c){var d=a&&typeof a=="object"?p.extend({},a):{complete:c||!c&&b||p.isFunction(a)&&a,duration:a,easing:c&&b||b&&!p.isFunction(b)&&b};d.duration=p.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in p.fx.speeds?p.fx.speeds[d.duration]:p.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";return d.old=d.complete,d.complete=function(){p.isFunction(d.old)&&d.old.call(this),d.queue&&p.dequeue(this,d.queue)},d},p.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},p.timers=[],p.fx=cZ.prototype.init,p.fx.tick=function(){var a,b=p.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||p.fx.stop()},p.fx.timer=function(a){a()&&p.timers.push(a)&&!cO&&(cO=setInterval(p.fx.tick,p.fx.interval))},p.fx.interval=13,p.fx.stop=function(){clearInterval(cO),cO=null},p.fx.speeds={slow:600,fast:200,_default:400},p.fx.step={},p.expr&&p.expr.filters&&(p.expr.filters.animated=function(a){return p.grep(p.timers,function(b){return a===b.elem}).length});var c_=/^(?:body|html)$/i;p.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){p.offset.setOffset(this,a,b)});var c,d,e,f,g,h,i,j={top:0,left:0},k=this[0],l=k&&k.ownerDocument;if(!l)return;return(d=l.body)===k?p.offset.bodyOffset(k):(c=l.documentElement,p.contains(c,k)?(typeof k.getBoundingClientRect!="undefined"&&(j=k.getBoundingClientRect()),e=da(l),f=c.clientTop||d.clientTop||0,g=c.clientLeft||d.clientLeft||0,h=e.pageYOffset||c.scrollTop,i=e.pageXOffset||c.scrollLeft,{top:j.top+h-f,left:j.left+i-g}):j)},p.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;return p.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(p.css(a,"marginTop"))||0,c+=parseFloat(p.css(a,"marginLeft"))||0),{top:b,left:c}},setOffset:function(a,b,c){var d=p.css(a,"position");d==="static"&&(a.style.position="relative");var e=p(a),f=e.offset(),g=p.css(a,"top"),h=p.css(a,"left"),i=(d==="absolute"||d==="fixed")&&p.inArray("auto",[g,h])>-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/js/main.js b/src/static/movio/templates/Skeleton/js/main.js new file mode 100755 index 0000000..ed9cd56 --- /dev/null +++ b/src/static/movio/templates/Skeleton/js/main.js @@ -0,0 +1,36 @@ +$(window).load(function() { + // TOOLTIP + $(function() { + $("[rel='tooltip']").tooltip(); + $('#element').tooltip('show') + }); + + + // VIDEO YOUTUBE LIQUID + // Find all YouTube videos + var $allVideos = $("iframe[src^='http://www.youtube.com']"), + // The element that is fluid width + $fluidEl = $(".item-box"); + // Figure out and save aspect ratio for each video + $allVideos.each(function() { + $(this) + .data('aspectRatio', this.height / this.width) + .removeAttr('height') + .removeAttr('width'); + }); + + // When the window is resized + // (You'll probably want to debounce this) + $(window).resize(function() { + var newWidth = $fluidEl.width(); + // Resize all videos according to their own aspect ratio + $allVideos.each(function() { + var $el = $(this); + $el + .width(newWidth) + .height(newWidth * $el.data('aspectRatio')); + + }); + // Kick off one resize to fix all videos on page load + }).resize(); +}); diff --git a/src/static/movio/templates/Skeleton/less/cms-component.less b/src/static/movio/templates/Skeleton/less/cms-component.less new file mode 100755 index 0000000..ff5b893 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/cms-component.less @@ -0,0 +1,1740 @@ +/** +* Top bar * +*/ +#topbar { + font-size:14px; + min-height:52px; + padding-top:10px; + padding-left:10px; + padding-right:10px; + background:@black; +} +/** + * Search form in top bar + */ +form.top-search { + float:right; + p { + .padding-margin-reset(); + label, input { + display:inline-block; + float:left; + } + label { + padding:4px 8px 0 0; + color:#fff; + } + input[type="text"] { + width:180px; + height: 30px + } + } +} +/** + * Language navigation + */ +.languages { + float:left; + margin-top:5px; + ul { + .padding-margin-reset(); + li { + display:inline; + padding:0 0 0 4px; + &:last-child { + border-right:0; + } + a { + display:inline-block; + margin-right:6px; + &.active { + text-decoration:underline; + } + } + } + } +} +/** + * Matanavigation + */ +.metanavigation { + margin-left:20px; + float:left; + margin-top:5px; + ul { + .padding-margin-reset(); + li { + display:inline; + padding:0 0 0 4px; + a { + display:inline-block; + margin-right:6px; + &.active { + text-decoration:underline; + } + } + } + } +} +/** + * Navigation menu + */ +.menu { + border-bottom:1px @solid @sidebar-border; + padding:15px 0; + position:relative; + background: @bg-menu; + ul { + margin-left:0; + padding-left:15px; + li { + margin-bottom:5px; + + &.active { + a { + background: @bg-sub-menu!important; + } + } + + a { + color: @sidebar-link; + font-size:16px; + &:hover { + color: @sidebar-link-hover; + } + &.active { + color: @sidebar-link-hover; + text-decoration:underline; + } + } + } + } +} +/* nav-pills */ +ul.nav-pills { + li { + &.active { + a { + background: @bg-sub-menu!important; + } + } + } +} +/* jq-menu */ +.jq-menu { + ul { + li { + list-style: none; + a { + min-height: 40px; + padding-top: 8px; + padding-left: 8px; + padding-right: 8px; + display: inline-block; + text-decoration: none; + + &:hover, &.active { + text-decoration: none; + } + + } + } + } + +} +.jqx-menu-dropdown { + background: @bg-sub-menu; + width:200px; + + ul { + .pmr(); + } + + li { + list-style: none; + } + + .jqx-item { + .jqx-icon-arrow-right { + width: 0!important; + height: 0!important; + border-top:5px solid transparent!important; + border-bottom:5px solid transparent!important; + border-left:5px solid @color-sub-menu-link!important; + margin-right:5px!important; + margin-left:5px!important; + } + } + + a { + color: @color-sub-menu-link; + display:block; + padding-top: 8px; + padding-left: 8px; + padding-right: 8px; + text-decoration: none; + + &:hover { + background:lighten(@bg-sub-menu,10%)!important; + } + + } +} +/** + * Breadcrumb + */ +.breadcrumb { + margin:15px 0; + border-bottom:1px @solid @box-border; + padding-bottom:15px; + ul { + .padding-margin-reset(); + li { + display:inline; + a { + color: @breadkcrumbs-link; + &:hover { + color: @breadkcrumbs-link-hover; + } + } + } + } +} +/** +* have-double-column +*/ +.have-double-column { + + .col-sm-3 { + background:@bg-column; + border:1px @solid @box-border; + .row { + padding: 15px; + } + } + + +} +/** + * Pagination + */ +.pagination { + width:100%; + + ul { + padding:0; + width:100%; + min-height:29px; + text-align:center; + text-align:center; + + li { + display:inline; + a { + border:0; + background:none; + float:none; + color:@text; + display:inline-block; + padding-top:0; + margin-top:7px; + padding-bottom:0; + line-height:1em; + font-size:14px; + outline:none; + padding:0 5px 0 5px; + border-left:1px @solid @box-border; + &:hover { + text-decoration:underline; + } + } + &.active a { + text-decoration:underline; + } + &:first-child > a { + border:0; + padding-left:17px; + } + &:last-child > a { + padding-right:17px; + } + } + } +} +/** + * Page title + */ + .box-title { + border-bottom:1px @solid @box-border; + padding-bottom:10px; + margin-bottom:20px; +} +/** + * Box with collapse button + */ + +.box { + position:relative; + + h1 { + .padding-margin-reset(); + font-size:20px; + line-height:2.5em; + } + + .container { + .padding-margin-reset(); + position:relative; + width:auto; + } + + img { + margin-bottom:10px; + } + + p { + word-break:break-strict; + } + + .show-content-box { + border:1px @solid @color-border-button; + position:absolute; + width:21px; + height:21px; + display:block; + text-indent:-9999px; + cursor:pointer; + top:0; + margin-top:9px; + margin-left:10px; + background:@color-background-button; + &:after { + top:50%; + margin-top:-2px; + content:" "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border: solid transparent; + border-top-color:@color-arrow-button-slider; + border-width: 6px; + left: 50%; + margin-left: -6px; + } + &:hover { + &:after { + border-top-color:@color-arrow-button-slider-hover; + } + } + &.collapsed { + &:after { + top:50%; + margin-top:-10px; + content:" "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border: solid transparent; + border-color:transparent; + border-bottom-color:@color-arrow-button-slider; + border-width: 6px; + left: 50%; + margin-left: -6px; + } + &:hover { + &:after { + border-bottom-color:@color-arrow-button-slider-hover; + } + } + } + } +} +/** + * Home slider + */ +.slideshow { + min-height:290px; + position:relative; + background-color:transparent; + z-index:2; + padding:0; + overflow:hidden; + margin-bottom:40px; + padding-top:12px; + + .slide { + margin:0 0 0 0; + padding:0; + height:290px; + @media (max-width: 480px) { + height:360px; + background-position:bottom!important; + background-size:320px; + } + img { + width:70%; + float:right; + margin:0; + .box-sizing(); + height:290px!important; + @media (max-width: 480px) { + width:100%!important; + float:none!important; + height:auto!important; + } + } + .description { + float:left; + width:385px; + .box-sizing(); + background:url(../img/bg/bg-description.png) repeat; + margin-left:0; + padding-left:15px; + min-height:290px; + margin-left:20px; + padding-right:10px; + position:relative; + @media (max-width: 480px) { + min-height:200px!important; + padding-left:10px; + width:100%!important; + } + background-color:none; + + h1 { + font-family: @font-1; + font-weight: 600; + font-size:45px; + margin:45px 0 10px 0; + line-height:1em; + text-align:center; + text-transform:uppercase; + a { + color:@slider-text; + text-decoration:none; + } + } + p { + font-size:18px; + margin:0; + text-align:center; + line-height:1.3em; + color:@slider-text; + } + a.link-continue { + display:block; + margin-top:5px; + position:absolute; + top:0; + left:0; + width:100%; + height:100%; + text-indent:-9999px; + } + + } + } + } + +/** + * Main image in entity detail + */ +.main-img { + padding:0; + position:relative; + padding:0 15px 10px 0; + margin: 0; + max-width:auto; + margin-bottom:15px; + + + img { + padding:5px; + border:1px @solid @box-image-border; + float:left; + margin-bottom:8px + } + .description { + font-size: 95%; + line-height: 1.2em; + padding:0; + margin:0; + position:relative; + bottom:0; + float:left; + clear:left; + width:auto; + padding-right:10px; + word-wrap:break-word; + + strong { + display:block; + } + } + + &.align-left { + float:left; + margin-right:20px; + padding-right:0; + } + + &.align-right { + float:right; + margin-left:20px; + padding-right:0; + img { + float:right; + } + .description { + float:right; + text-align:right; + clear:right; + padding-left:10px; + padding-right:0; + } + } + + @media (max-width: 480px) { + margin:0 0 15px 0; + width:288px; + } +} + +/** + * Search results + */ +.results-content { + .item { + border-bottom:1px @solid @box-relation-item-border; + padding-bottom:15px; + margin-bottom:15px; + + &.even { + background:@box-item-even-background; + padding: 10px; + } + + &.odd { + background:@box-item-odd-background; + padding: 10px; + } + + figure { + width:135px; + height:135px; + float:left; + margin: 0 15px 0 0; + + img { + padding:5px; + border:1px @solid @box-image-border; + float:left; + margin-bottom:8px + } + } + + h1, h2, h3, h4 { + font-size:16px; + padding:0; + margin:0; + line-height:1em; + margin-bottom:5px; + + a { + text-decoration:none; + &:hover { + text-decoration:underline; + } + } + } + + .sub-title { + font-size: 14px; + margin-top: -5px; + } + + p { + font-size:14px; + line-height:18px; + padding:0; + margin:0; + } + + } +} + +/** + * Entity relations image + */ +.relationImage { + h1 { + font-size:14px; + font-family: @font-1; + font-weight: 600; + line-height:14px; + padding:13px 14px 12px 54px; + margin:0; + background-color:@box-header-background; + border-bottom:1px @solid @box-border; + color:@box-header-link; + a { + color:@box-header-link; + text-decoration:none; + } + } + +} + + +/** + * Entity relations links + */ +.relationLink { + h1 { + font-size:14px; + font-family: @font-1; + font-weight: 600; + line-height:14px; + padding:13px 14px 12px 54px; + margin:0; + background-color:@box-header-background; + border-bottom:1px @solid @box-border; + color:@box-header-link; + a { + color:@box-header-link; + text-decoration:none; + } + } + .item-list { + padding:0; + margin:0 0; + li { + list-style:none; + padding-left:14px; + border-bottom:1px @solid @box-relation-item-border; + a { + text-decoration:none; + display:block; + color:@box-text; + line-height:30px; + padding-left:20px; + position:relative; + &:before { + display:block; + position:absolute; + width:15px; + height:10px; + top:0; + left:0; + margin:0 0 0 0; + font-family:'FontAwesome'; + content: @fa-var-eye; + color:@box-text; + } + &:hover { + &:before { + color:@color-arrow-button-slider-hover; + } + } + } + &:last-child { + border:0; + a { + padding-bottom:0; + margin-bottom:0; + } + } + } + } +} + +/** + * Entity relations image link + */ +.relationImageLink { + .item { + padding:10px; + border-bottom:1px @solid @box-relation-item-border; + min-height:100px; + h2 { + font-size:18px; + .padding-margin-reset(); + } + figure { + float: left; + margin-right:8px; + } + img { + max-height: 56px; + max-width: 100%; + width: 100%; + float:left; + margin:0; + } + } + h1 { + font-size:14px; + font-family: @font-1; + font-weight: 600; + line-height:14px; + padding:13px 14px 12px 54px; + margin:0; + background-color:@box-header-background; + border-bottom:1px @solid @box-border; + color:@box-header-link; + a { + color:@box-header-link; + text-decoration:none; + } + } +} + + +/** + * Storyteller + */ +.storyteller { + background:@storyteller-background; + border:1px @solid @storyteller-border; + padding-bottom:15px; + margin-bottom:20px; + .box-sizing(); + width:100%; + clear:both; + + #nav-bar { + min-height:40px; + background:#ececec; + ul { + .padding-margin-reset(); + margin-left:10px; + @media (max-width: 480px) { + margin-left:-1px; + margin-right:-1px; + margin-top:-1px; + } + li { + list-style:none; + display:inline; + padding:10px 10px; + height:40px; + float:left; + @media (max-width: 480px) { + display:block; + float:none; + } + &:hover, &.active { + background-color: @storyteller-item-background; + @media (max-width: 480px) { + background-color:transparent; + } + a { + color:@text; + text-decoration:none; + border-bottom:4px @solid @sidebar-background-hover; + } + } + border-left:1px @solid @storyteller-border; + a { + display:inline-block; + color:@storyteller-navigation-link; + text-decoration:none; + text-transform:uppercase; + } + &:last-child { + border-right:1px @solid @storyteller-border; + } + } + } + } + + .content-story { + padding-top:20px; + + .item-box { + position:relative; + background: @storyteller-item-background; + display:block; + width:95%; + margin:0 auto 35px auto; + padding:10px; + .box-sizing(); + + h1 { + font-size: 18px; + } + h2 { + font-size: 16px; + } + h4 { + font-size: 14px; + } + + &.with-angle-icon { + background:@storyteller-item-background url(../img/bg/bg-box.png) 99.8% 2px no-repeat; + } + + .box-angle { + font-size:15px; + position:absolute; + right:0; + top:0; + margin:7px 5px 0 0; + } + + &.comment { + background:@storyteller-comments-background; + form { + + } + } + &.gallery { + background:@storyteller-item-background; + } + .arrow-big { + background:url(../img/ico/arrow-baloon-big.png) 0 0 no-repeat; + width:18px; + height:16px; + display:block; + position:absolute; + top:0; + left:50%; + margin-left:-9px; + margin-top:-16px; + } + iframe { + width: 100%; + margin: 0 0 30px 0; + } + .functions { + .from { + color:@storyteller-link; + span { + font-weight:bold; + color:@text; + } + } + .actions { + border-top:1px @solid @storyteller-border; + margin-top:4px; + padding-top:4px; + padding-bottom:8px; + ul { + .padding-margin-reset(); + padding-top:8px; + &.dx { + float:right; + li a { + text-decoration:none; + } + li i { + font-size:18px; + } + } + &.sx { + float:left; + } + li { + list-style:none; + display:inline; + border-right:1px @solid @storyteller-border; + padding:5px 10px; + &:last-child { + border:0; + } + i { + color:@storyteller-icon; + margin-right:5px; + } + a { + display:inline-block; + text-decoration:none; + padding:0; + line-height:16px; + &:hover { + text-decoration:underline; + } + } + } + } + } + } + .archive-link { + text-align:center; + padding-top:5px; + } + + .item-comment { + border-bottom:1px @solid @storyteller-border; + padding-bottom:10px; + margin-bottom:10px; + &:last-child { + border-bottom:0; + padding-bottom:0; + margin-bottom:0; + } + } + + .story-gallery { + border-top:1px @solid @storyteller-border; + padding-top:20px; + padding-bottom:20px; + padding-left:10px; + padding-right:10px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + .mini-photo { + border:1px @solid transparent; + padding-right:0px; + float:left; + width:82px; + height:82px; + position:relative; + margin-right:12px; + margin-bottom:12px; + &:last-child { + margin-right:0; + } + img { + width:82px; + height:82px; + margin:0; + float:none; + padding:2px; + margin-right:8px; + border:1px @solid @storyteller-image-border; + .border-radius (2px); + } + &:last-child { + &:hover { + .popup { + margin-left:-80px; + .popup-arrow { + right:0; + left:auto; + margin-right:8px; + } + } + } + } + &:hover { + .popup { + visibility:visible; + } + } + } + } + } + } + ul.insights { + list-style: none; + margin: 10px 0; + padding: 0; + li { + float: left; + padding-right: 10px; + margin-right: 10px; + border-right: 1px @solid @storyteller-border; + &:last-child { + margin-right: 0; + padding-right: 0; + border: 0; + } + } + } +} + + +/** + * Gallery.io override + */ +.wrapper-galleria-io { + padding:5px; + border:1px @solid @box-border; + margin-bottom:40px; + clear:both; + + .content-galleria-io { + max-width:100%; + font-family: @font-1; + &:hover { + .galleria-info-description { + opacity:1; + filter: alpha(opacity=100); + } + } + .galleria-info { + margin-bottom:10px; + } + .galleria-info-description { + opacity:0; + filter: alpha(opacity=0); + position:absolute; + margin:0 0 31px -15px; + bottom:0; + display:block; + width:100%; + background: url(../img/bg/bg-description.png) repeat; + padding:5px 15px; + padding-right:40px; + .box-sizing(); + border-top:1px @solid #000; + border-right:1px @solid #000; + width:430px; + } + } + .galleria-counter { + margin-bottom:10px; + margin-right:46px; + } + + &.slider { + border: 0; + } + + #galleria.sfogliatore { + .galleria-info { + position: absolute; + height:15px; + left:0px; + bottom:0; + margin-bottom:5px!important; + color: #bbb; + margin-right:40px; + } + .galleria-info-description { + margin:0 0 16px -5px; + } + } + + #galleria.slider { + .galleria-info-text { + top:auto; + bottom:0; + margin-bottom:-12px; + } + } +} + + +/** + * Image list + */ +.imageList { + margin:30px; + clear:both; +} + + +/** + * Timeline + */ +.storyjs-embed.sized-embed { + border-radius: 0; +} + +.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content h3, .vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3 { + color: @timeline-theme !important; +} + +.vco-timeline .vco-navigation .timenav-background .timenav-line, +.vco-timeline .vco-navigation .timenav .content .marker.active .line, +.vco-timeline .vco-navigation .timenav .content .marker.active .dot { + background-color: @timeline-theme !important; +} + +.vco-timeline .vco-navigation .timenav .content .marker .line .event-line { + background: @timeline-theme !important; +} + +/* ImageHotspot */ + +.movio-hotspotContainer { + position: relative; + border:1px @solid @box-image-border; + .border-radius (2px); + padding: 3px; + display: inline-block; + width: 100%; + + .movio-imageHotspot-scale { + position: absolute; + left: 0; + top: 0; + } + + + .movio-hotspot, .movio-hotspot-circle { + border: 2px @solid @white; + .box-shadow(0, 0, 2px, @black); + position: absolute; + z-index: 999; + cursor: pointer; + + &:hover { + border: 2px @solid @color-link; + } + } + + .movio-hotspot-circle { + border-radius: 50%; + } + + img { + max-width: 100%; + height: auto; + } + + +} + +/** + * results-content in-grid + */ +.results-content-grid { + padding:0; + + .in-grid { + border:4px @solid @white; + margin-bottom:15px; + + .content-box { + background:fade(@box-border,10%); + padding: 15px; + min-height:120px; + border:1px @solid @box-border; + } + + &:hover { + .content-box { + border:1px @solid @box-header-link; + } + } + + p { + line-height: 1.2em; + font-size: 12px; + } + + h2 { + font-size:18px; + border-bottom: 0; + .padding-margin-reset(); + } + + figure { + float: left; + margin-right:8px; + } + + img { + float:left; + margin:0; + } + + } + + +} + +/** + * Image + */ +img { + max-width:100%; + border: 0; + &.thumb, &.left, &.right, &.center { + float:left; + margin: 0.5em; + padding:5px; + border:1px @solid @box-image-border; + } + &.left { + margin-left: 0; + } + &.right { + margin-right: 0; + clear:right; + float:right; + } + &.center { + clear:both; + float:none; + margin:auto; + display: block; + } + &.noBorder { + border: 0; + padding: 0; + } +} + +/** +/* myform +*/ +.my-form, form { + + label { + &.required { + &:after { + content:" *"; + } + } + } + + input[type="text"], input[type="password"], input[type="email"] { + width:100%; + + &.input-large { + width:100%; + } + &.input-small { + width:50%; + } + } + + + &.no-border-row { + .control-group { + border:0; + } + } + .control-group { + padding-bottom:10px; + + input[type="submit"] { + margin-right:5px; + } + + } + .controls { + margin-left:0; + &.with-button { + input[type="submit"], input[type="button"], input[type="reset"], button { + margin-top:0; + margin-left:5px; + } + } + } + + &.form-horizontal { + .control-group { + clear:both; + margin-bottom:15px; + padding-bottom:15px; + border-bottom:1px @solid @color1; + label { + display:inline-block; + width:160px; + } + .controls { + display:inline-block; + } + } + } +} +/** +/* alert error +*/ +.error { + color:@color-error; +} + +.ok { + color:@color-success; +} +/** +/* superzoom +*/ +span.superzoom { + border-radius: 4px; + padding: 2px 8px 4px; + position: absolute; + width:60px; + color:@form-buttonPrimary-text; + background:@form-button-primary url(../img/ico/search.png) 10px 5px no-repeat; + text-align: right; + + &.small { + text-indent: 100%; + overflow: hidden; + width:22px; + color:@form-button-primary; + font-size:0; + padding: 0; + height:22px; + background:@form-button-primary url(../img/ico/search.png) center no-repeat; + } +} + +div.menu-dropdown { + ul, ul ul { + padding:0; + margin: 0; + } + ul li, ul ul li { + list-style-type: none; + display: inline-block; + } + ul li a, ul li ul li a { + text-decoration: none; + color: @metanavigation-link; + padding: 5px; + display:inline-block; + } + ul li ul li a { + width: 150px; + background: @metanavigation-background; + } + ul li ul li a:hover { + background: @metanavigation-background-hover; + color: @metanavigation-link-hover; + } + ul li { + position: relative; + } + ul li ul { + display:none; + position: absolute; + top: 20px; + left: -130px; + width: 150px; + z-index: 1000; + } + ul li:hover ul { + display:block; + } + + .icon { + font-size: 120%; + } +} +/** +/* Nuove modifiche CSS per la skin MapMarker.html +*/ +div#map-popup-background { + margin-top: -9999px; + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + z-index: 2; +} +/** +/* footer component +*/ +#footer { + + .logo-footer { + float:left; + padding:15px 10px; + border:0; + width:20%; + border-right:1px @solid @footer-border; + min-height:140px; + } + + + #info-page { + padding:0 10px; + color:#fff; + border-top:1px @solid @footer-border; + + p { + font-size:12px; + padding-top:5px; + line-height:1em; + } + + } + + .box { + float:left; + padding:15px 10px; + border:0; + width:20%; + border-right:1px @solid @footer-border; + min-height:140px; + + h2 { + .padding-margin-reset(); + line-height:1em; + font-size:16px; + color: @footer-text; + } + + ul { + .padding-margin-reset(); + padding-top:10px; + + li { + list-style:none; + + a, a:hover, a:link { + color: @footer-text-link; + } + } + + } + + } + +} +/** +/* gloassary +*/ +.module-gloassary { + .glossary { + .pmr(); + + li { + display:inline; + } + + } +} +/** +/* block-single-license +*/ +.block-single-license { + border:1px @solid @box-border-cart; + padding:10px; + + .price { + font-size:18px; + display: block; + margin-bottom: 12px; + } + +} +/** +/* block-multiple-license +*/ +.block-multiple-license { + border:1px @solid @box-border-cart; + padding:0; + display:block; + margin-top:15px; + + .row-fluid { + padding:5px 15px; + } + + .odd { + background:@box-item-odd-background; + } + + .even { + background:@box-item-even-background; + } + + .price, .info-title { + font-size:18px; + display:inline-block; + } + + .sub-info-title { + font-size:14px; + display:block; + } + +} +/** +/* block-purchases +*/ +.block-purchases { + border:0; + padding:0; + display:block; + margin-top:15px; + + .row-fluid { + padding:10px 0; + border-bottom:1px @solid @box-border-cart; + } + + .odd { + background:transparent; + } + + .even { + background:transparent; + } + + .price, .info-title { + font-size:18px; + display:inline-block; + } + + .sub-info-title { + font-size:14px; + display:block; + } + +} +/** +/* my-purchases +*/ +.my-purchases { + .item { + border:0; + } +} +/** +/* my-cart +*/ +.my-cart { + + .block-total { + padding:0 15px; + + .block-info, .price { + font-size:20px; + } + + .block-action { + text-align: right; + + .price, button { + display:block; + margin-bottom: 8px; + } + + } + + } + +} + +/** +/* top-cart +*/ +.top-cart { + &.pull-right { + margin-left:10px; + } +} +/** +/* box-search +*/ +.box-search { + +} +/** +/* box-search, .box-login +*/ +.box-login { + .btn-group-vertical { + padding: 0; + padding-bottom: 15px; + + a { + text-align: left; + } + + } +} +/** +/* box-events +*/ +.box-events { + ul { + .pmr(); + + li { + list-style: none; + line-height:1em; + margin-bottom: 14px; + + .date { + font-size: 13px; + line-height: 1em; + .pmr(); + } + + .title { + line-height: 1em; + .pmr(); + } + + } + + } +} +/** +/* post-nfo +*/ +.post-nfo { + font-size:13px; + margin-top:-5px; + margin-bottom:10px; +} +.box { + .item.post { + h1 { + font-size:20px; + border-bottom: 0; + text-transform: none; + } + } +} +/** +/* attach +*/ +.attach { + padding: 10px; + border:1px @solid @box-border; + + .box-title { + font-size: 18px; + border-bottom: 0; + .pmr(); + padding-bottom: 10px; + color:@text; + } + + .container { + border:0; + background: none; + padding:0; + } + + ul { + .pmr(); + + li { + &.active { + a { + background:@bg-link-attach-hover; + color:@color-link-attach-hover; + + &:hover { + background:@bg-link-attach-hover; + color:@color-link-attach-hover; + } + + } + } + + a { + background:@bg-link-attach; + color:@color-link-attach; + + &:hover { + background:@bg-link-attach-hover; + color:@color-link-attach-hover; + } + + } + + } + + } + +} +/** +/* new-properties +*/ +.new-properties { + border:1px @solid @box-border; + padding:10px; + background: @bg-dl; + + dd, dt { + float: left; + padding:5px 0; + border-top:1px @solid @box-border; + + &:first-child, &:nth-child(2) { + border-top:0; + } + + } + + dt { + clear: both; + width: 23%; + } + + dd { + width:77%; + } + +} +/** +/* tag-list +*/ +.tag-list, .insights { + .pmr(); + + li { + display: inline; + + a { + display: inline-block; + font-size: 12px; + color: @color-tag-attach; + background: @bg-tag-attach; + padding: 2px 5px; + .border-radius(4px); + margin-top: 2px; + + &:hover { + text-decoration: none; + color: @color-tag-attach-hover; + background: @bg-tag-attach-hover; + } + + } + + } + +} +/** +/* block-my-pop-up +*/ +.block-my-pop-up { + position: absolute; + max-width: 490px; + background:@bg-block-my-pop-up; + z-index: 99; + border: 4px @solid @box-border; + + .arrow { + width: 0; + height: 0; + border-left:15px solid transparent; + border-right:15px solid transparent; + border-bottom:15px solid @box-border; + position: absolute; + } + + .block-title { + padding: 10px; + font-size:20px; + border-bottom: 1px @solid @box-border; + } + + .block-my-pop-up-container { + position: relative; + padding:10px; + padding-top: 0; + + &.no-padding { + padding:0; + margin-top: -15px; + } + + } + + .results-content { + position: relative; + } + + +} \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/less/cms-global.less b/src/static/movio/templates/Skeleton/less/cms-global.less new file mode 100755 index 0000000..504eddc --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/cms-global.less @@ -0,0 +1,240 @@ +body { + background-color:#fff; + font-family:@font-1; + font-size:14px; + font-weight:normal; +} + +* { + .box-sizing(); +} + +/** + * Typography + */ +h1, h2, h3, h4, h5, h6 { + color: @text-heading; +} +a { + color:@color-link; + + &:hover { + color:@color-link-hover; + } +} + +dt { + float: left; + font-weight:bold; + padding-right:10px; +} + +dd { + margin-left:0; +} + +dl { + &.small { + dt { + width: 70px; + } + dd { + margin-left: 70px; + } + } + &.medium { + dt { + width: 170px; + } + dd { + margin-left: 170px; + } + } + &.large { + dt { + width: 250px; + } + dd { + margin-left: 250px; + } + } +} + +.main-content { + h1 { + .padding-margin-reset(); + } + h2 { + .padding-margin-reset(); + margin-bottom:15px; + } + + .print-ico { + float:right; + } + + p { + line-height:1.6em; + padding-bottom:15px; + } +} +/** + * Form + */ +input[type="text"], input[type="password"], input[type="email"] { + .input-style(100%); + + &.input-large { + width:450px; + } + &.input-small { + width:160px; + } +} + +select { + width:auto; + &.select-large { + width:450px; + } + &.select-small { + width:160px; + } + &.select-medium { + width:260px; + } +} + +input[type="submit"], button, input[type="button"], input[type="reset"] { + .button-style(auto); +} + +input[type="submit"] { + background:@form-button-primary; + color:@form-button-primary-text; +} + +textarea { + border:1px @solid @color1; + width:100%; + padding:4px; + height:150px; + &.textarea-large { + width:450px; + } +} + +/** + * global selectors + */ +.clearfix-left { + clear:left; +} + +.clearfix-right { + clear:right; +} + +.align-center { + text-align:center!important; +} + +.align-right { + text-align:right!important; +} + +.first-box { + margin-left:0!important; +} + +.ico-box { + display:block; + position:absolute; + width:30px!important; + height:30px!important; + top:0; + right:0; + margin-right:10px; + background:@icon-in-box-background; + color:@icon-in-box; + text-align:center; + padding-top:7px; + font-size:15px; + &.icon-film { + padding-left:5px; + } +} + +.icon-grey { + color:@icon-in-page; + font-size:20px; +} + +.link-go-to-read { + color:@color-link!important; + font-size: 12px; + display: inline-block; + padding-top: 5px; + + &:hover { + color:@color-link-hover!important; + } + +} + +span.superzoom { + background: @form-button-primary; + border-radius: 4px; + color: @form-button-primary-text; + padding: 2px 4px; + position: absolute; + text-align: center; + width: 60px; + cursor: pointer; +} + +.container-fluid { + padding:0; +} + +.content-box { + min-height:290px; + position:relative; +} + +.navbar-default { + .btn-default { + border:1px solid @color-border-button; + padding-top:5px; + } +} + +button.btn.navbar-toggle { + border:1px solid @color9; + float: none; + position: relative; + margin-left:10px; + padding-top:8px; + background:@bg-menu; + color: @color-menu-link; +} + +.btn-default, input[type="submit"], button { +background:@form-button-primary; +color:@form-button-primary-text; +} + +input[type="reset"] { + background:@bg-button-reset!important; +} + + +a.no-undeline { + text-decoration: none; +} + +.col-padding-left, +.col-padding-right { + padding-right: 15px; +} + diff --git a/src/static/movio/templates/Skeleton/less/cms-layout.less b/src/static/movio/templates/Skeleton/less/cms-layout.less new file mode 100755 index 0000000..188ff43 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/cms-layout.less @@ -0,0 +1,33 @@ +#outer { + padding-bottom:25px; + width:100%; +} + +#header { + padding:15px 0; + background:#eaeaea; + + h1,h2 { + .padding-margin-reset(); + } +} + +.sx { + float:left; + + nav { + margin:0; + } + + #nav-collapse { + .padding-margin-reset(); + } +} + +#footer { + width:100%; + clear:both; + background:@footer-background; +} + + diff --git a/src/static/movio/templates/Skeleton/less/cms-mobile.less b/src/static/movio/templates/Skeleton/less/cms-mobile.less new file mode 100755 index 0000000..ddc4ff8 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/cms-mobile.less @@ -0,0 +1,76 @@ +@media (max-width: 979px) { + +.relationImageLink { + + .container {.pmr()!important;padding-top: 10px!important;} + + .item { + padding-top: 15px; + width:100%!important; + margin-left: 0!important; + + &.last { + margin-right:0!important; + } + } + + } + + .btn { + &.add { + &.pull-right { + float: none!important; + margin-top: 10px; + margin-bottom: 10px; + } + } + } + + .block-multiple-license { + + } + +} + +@media (max-width: 765px) { + figure.main-img { + float:none!important; + display:blockimportant; + margin:0 auto 0 auto!important; + } + /* jq-menu */ + .jq-menu { + + ul { + li { + display: block; + float: none!important; + + a { + display: block; + width: 100%; + float: none!important; + } + } + } + + } + .jqx-menu-dropdown { + + .jqx-item { + .jqx-icon-arrow-right { + display: none; + } + } + + } + +} + +/* iPads (portrait) ----------- */ +@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : portrait) { +} + +/* iPads (landscape) ----------- */ +@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : landscape) { +} diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/bordered-pulled.less b/src/static/movio/templates/Skeleton/less/font-awesome/bordered-pulled.less new file mode 100644 index 0000000..9bb4d3a --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/bordered-pulled.less @@ -0,0 +1,16 @@ +// Bordered & Pulled +// ------------------------- + +.@{fa-css-prefix}-border { + padding: .2em .25em .15em; + border: @solid .08em @fa-border-color; + border-radius: .1em; +} + +.pull-right { float: right; } +.pull-left { float: left; } + +.@{fa-css-prefix} { + &.pull-left { margin-right: .3em; } + &.pull-right { margin-left: .3em; } +} diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/core.less b/src/static/movio/templates/Skeleton/less/font-awesome/core.less new file mode 100644 index 0000000..6d223bc --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/core.less @@ -0,0 +1,12 @@ +// Base Class Definition +// ------------------------- + +.@{fa-css-prefix} { + display: inline-block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/fixed-width.less b/src/static/movio/templates/Skeleton/less/font-awesome/fixed-width.less new file mode 100644 index 0000000..110289f --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/fixed-width.less @@ -0,0 +1,6 @@ +// Fixed Width Icons +// ------------------------- +.@{fa-css-prefix}-fw { + width: (18em / 14); + text-align: center; +} diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/font-awesome.less b/src/static/movio/templates/Skeleton/less/font-awesome/font-awesome.less new file mode 100644 index 0000000..96d2f22 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/font-awesome.less @@ -0,0 +1,17 @@ +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ + +@import "variables"; +@import "mixins"; +@import "path"; +@import "core"; +@import "larger"; +@import "fixed-width"; +@import "list"; +@import "bordered-pulled"; +@import "spinning"; +@import "rotated-flipped"; +@import "stacked"; +@import "icons"; diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/icons.less b/src/static/movio/templates/Skeleton/less/font-awesome/icons.less new file mode 100644 index 0000000..bf0f856 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/icons.less @@ -0,0 +1,412 @@ +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ + +.@{fa-css-prefix}-glass:before { content: @fa-var-glass; } +.@{fa-css-prefix}-music:before { content: @fa-var-music; } +.@{fa-css-prefix}-search:before { content: @fa-var-search; } +.@{fa-css-prefix}-envelope-o:before { content: @fa-var-envelope-o; } +.@{fa-css-prefix}-heart:before { content: @fa-var-heart; } +.@{fa-css-prefix}-star:before { content: @fa-var-star; } +.@{fa-css-prefix}-star-o:before { content: @fa-var-star-o; } +.@{fa-css-prefix}-user:before { content: @fa-var-user; } +.@{fa-css-prefix}-film:before { content: @fa-var-film; } +.@{fa-css-prefix}-th-large:before { content: @fa-var-th-large; } +.@{fa-css-prefix}-th:before { content: @fa-var-th; } +.@{fa-css-prefix}-th-list:before { content: @fa-var-th-list; } +.@{fa-css-prefix}-check:before { content: @fa-var-check; } +.@{fa-css-prefix}-times:before { content: @fa-var-times; } +.@{fa-css-prefix}-search-plus:before { content: @fa-var-search-plus; } +.@{fa-css-prefix}-search-minus:before { content: @fa-var-search-minus; } +.@{fa-css-prefix}-power-off:before { content: @fa-var-power-off; } +.@{fa-css-prefix}-signal:before { content: @fa-var-signal; } +.@{fa-css-prefix}-gear:before, +.@{fa-css-prefix}-cog:before { content: @fa-var-cog; } +.@{fa-css-prefix}-trash-o:before { content: @fa-var-trash-o; } +.@{fa-css-prefix}-home:before { content: @fa-var-home; } +.@{fa-css-prefix}-file-o:before { content: @fa-var-file-o; } +.@{fa-css-prefix}-clock-o:before { content: @fa-var-clock-o; } +.@{fa-css-prefix}-road:before { content: @fa-var-road; } +.@{fa-css-prefix}-download:before { content: @fa-var-download; } +.@{fa-css-prefix}-arrow-circle-o-down:before { content: @fa-var-arrow-circle-o-down; } +.@{fa-css-prefix}-arrow-circle-o-up:before { content: @fa-var-arrow-circle-o-up; } +.@{fa-css-prefix}-inbox:before { content: @fa-var-inbox; } +.@{fa-css-prefix}-play-circle-o:before { content: @fa-var-play-circle-o; } +.@{fa-css-prefix}-rotate-right:before, +.@{fa-css-prefix}-repeat:before { content: @fa-var-repeat; } +.@{fa-css-prefix}-refresh:before { content: @fa-var-refresh; } +.@{fa-css-prefix}-list-alt:before { content: @fa-var-list-alt; } +.@{fa-css-prefix}-lock:before { content: @fa-var-lock; } +.@{fa-css-prefix}-flag:before { content: @fa-var-flag; } +.@{fa-css-prefix}-headphones:before { content: @fa-var-headphones; } +.@{fa-css-prefix}-volume-off:before { content: @fa-var-volume-off; } +.@{fa-css-prefix}-volume-down:before { content: @fa-var-volume-down; } +.@{fa-css-prefix}-volume-up:before { content: @fa-var-volume-up; } +.@{fa-css-prefix}-qrcode:before { content: @fa-var-qrcode; } +.@{fa-css-prefix}-barcode:before { content: @fa-var-barcode; } +.@{fa-css-prefix}-tag:before { content: @fa-var-tag; } +.@{fa-css-prefix}-tags:before { content: @fa-var-tags; } +.@{fa-css-prefix}-book:before { content: @fa-var-book; } +.@{fa-css-prefix}-bookmark:before { content: @fa-var-bookmark; } +.@{fa-css-prefix}-print:before { content: @fa-var-print; } +.@{fa-css-prefix}-camera:before { content: @fa-var-camera; } +.@{fa-css-prefix}-font:before { content: @fa-var-font; } +.@{fa-css-prefix}-bold:before { content: @fa-var-bold; } +.@{fa-css-prefix}-italic:before { content: @fa-var-italic; } +.@{fa-css-prefix}-text-height:before { content: @fa-var-text-height; } +.@{fa-css-prefix}-text-width:before { content: @fa-var-text-width; } +.@{fa-css-prefix}-align-left:before { content: @fa-var-align-left; } +.@{fa-css-prefix}-align-center:before { content: @fa-var-align-center; } +.@{fa-css-prefix}-align-right:before { content: @fa-var-align-right; } +.@{fa-css-prefix}-align-justify:before { content: @fa-var-align-justify; } +.@{fa-css-prefix}-list:before { content: @fa-var-list; } +.@{fa-css-prefix}-dedent:before, +.@{fa-css-prefix}-outdent:before { content: @fa-var-outdent; } +.@{fa-css-prefix}-indent:before { content: @fa-var-indent; } +.@{fa-css-prefix}-video-camera:before { content: @fa-var-video-camera; } +.@{fa-css-prefix}-picture-o:before { content: @fa-var-picture-o; } +.@{fa-css-prefix}-pencil:before { content: @fa-var-pencil; } +.@{fa-css-prefix}-map-marker:before { content: @fa-var-map-marker; } +.@{fa-css-prefix}-adjust:before { content: @fa-var-adjust; } +.@{fa-css-prefix}-tint:before { content: @fa-var-tint; } +.@{fa-css-prefix}-edit:before, +.@{fa-css-prefix}-pencil-square-o:before { content: @fa-var-pencil-square-o; } +.@{fa-css-prefix}-share-square-o:before { content: @fa-var-share-square-o; } +.@{fa-css-prefix}-check-square-o:before { content: @fa-var-check-square-o; } +.@{fa-css-prefix}-arrows:before { content: @fa-var-arrows; } +.@{fa-css-prefix}-step-backward:before { content: @fa-var-step-backward; } +.@{fa-css-prefix}-fast-backward:before { content: @fa-var-fast-backward; } +.@{fa-css-prefix}-backward:before { content: @fa-var-backward; } +.@{fa-css-prefix}-play:before { content: @fa-var-play; } +.@{fa-css-prefix}-pause:before { content: @fa-var-pause; } +.@{fa-css-prefix}-stop:before { content: @fa-var-stop; } +.@{fa-css-prefix}-forward:before { content: @fa-var-forward; } +.@{fa-css-prefix}-fast-forward:before { content: @fa-var-fast-forward; } +.@{fa-css-prefix}-step-forward:before { content: @fa-var-step-forward; } +.@{fa-css-prefix}-eject:before { content: @fa-var-eject; } +.@{fa-css-prefix}-chevron-left:before { content: @fa-var-chevron-left; } +.@{fa-css-prefix}-chevron-right:before { content: @fa-var-chevron-right; } +.@{fa-css-prefix}-plus-circle:before { content: @fa-var-plus-circle; } +.@{fa-css-prefix}-minus-circle:before { content: @fa-var-minus-circle; } +.@{fa-css-prefix}-times-circle:before { content: @fa-var-times-circle; } +.@{fa-css-prefix}-check-circle:before { content: @fa-var-check-circle; } +.@{fa-css-prefix}-question-circle:before { content: @fa-var-question-circle; } +.@{fa-css-prefix}-info-circle:before { content: @fa-var-info-circle; } +.@{fa-css-prefix}-crosshairs:before { content: @fa-var-crosshairs; } +.@{fa-css-prefix}-times-circle-o:before { content: @fa-var-times-circle-o; } +.@{fa-css-prefix}-check-circle-o:before { content: @fa-var-check-circle-o; } +.@{fa-css-prefix}-ban:before { content: @fa-var-ban; } +.@{fa-css-prefix}-arrow-left:before { content: @fa-var-arrow-left; } +.@{fa-css-prefix}-arrow-right:before { content: @fa-var-arrow-right; } +.@{fa-css-prefix}-arrow-up:before { content: @fa-var-arrow-up; } +.@{fa-css-prefix}-arrow-down:before { content: @fa-var-arrow-down; } +.@{fa-css-prefix}-mail-forward:before, +.@{fa-css-prefix}-share:before { content: @fa-var-share; } +.@{fa-css-prefix}-expand:before { content: @fa-var-expand; } +.@{fa-css-prefix}-compress:before { content: @fa-var-compress; } +.@{fa-css-prefix}-plus:before { content: @fa-var-plus; } +.@{fa-css-prefix}-minus:before { content: @fa-var-minus; } +.@{fa-css-prefix}-asterisk:before { content: @fa-var-asterisk; } +.@{fa-css-prefix}-exclamation-circle:before { content: @fa-var-exclamation-circle; } +.@{fa-css-prefix}-gift:before { content: @fa-var-gift; } +.@{fa-css-prefix}-leaf:before { content: @fa-var-leaf; } +.@{fa-css-prefix}-fire:before { content: @fa-var-fire; } +.@{fa-css-prefix}-eye:before { content: @fa-var-eye; } +.@{fa-css-prefix}-eye-slash:before { content: @fa-var-eye-slash; } +.@{fa-css-prefix}-warning:before, +.@{fa-css-prefix}-exclamation-triangle:before { content: @fa-var-exclamation-triangle; } +.@{fa-css-prefix}-plane:before { content: @fa-var-plane; } +.@{fa-css-prefix}-calendar:before { content: @fa-var-calendar; } +.@{fa-css-prefix}-random:before { content: @fa-var-random; } +.@{fa-css-prefix}-comment:before { content: @fa-var-comment; } +.@{fa-css-prefix}-magnet:before { content: @fa-var-magnet; } +.@{fa-css-prefix}-chevron-up:before { content: @fa-var-chevron-up; } +.@{fa-css-prefix}-chevron-down:before { content: @fa-var-chevron-down; } +.@{fa-css-prefix}-retweet:before { content: @fa-var-retweet; } +.@{fa-css-prefix}-shopping-cart:before { content: @fa-var-shopping-cart; } +.@{fa-css-prefix}-folder:before { content: @fa-var-folder; } +.@{fa-css-prefix}-folder-open:before { content: @fa-var-folder-open; } +.@{fa-css-prefix}-arrows-v:before { content: @fa-var-arrows-v; } +.@{fa-css-prefix}-arrows-h:before { content: @fa-var-arrows-h; } +.@{fa-css-prefix}-bar-chart-o:before { content: @fa-var-bar-chart-o; } +.@{fa-css-prefix}-twitter-square:before { content: @fa-var-twitter-square; } +.@{fa-css-prefix}-facebook-square:before { content: @fa-var-facebook-square; } +.@{fa-css-prefix}-camera-retro:before { content: @fa-var-camera-retro; } +.@{fa-css-prefix}-key:before { content: @fa-var-key; } +.@{fa-css-prefix}-gears:before, +.@{fa-css-prefix}-cogs:before { content: @fa-var-cogs; } +.@{fa-css-prefix}-comments:before { content: @fa-var-comments; } +.@{fa-css-prefix}-thumbs-o-up:before { content: @fa-var-thumbs-o-up; } +.@{fa-css-prefix}-thumbs-o-down:before { content: @fa-var-thumbs-o-down; } +.@{fa-css-prefix}-star-half:before { content: @fa-var-star-half; } +.@{fa-css-prefix}-heart-o:before { content: @fa-var-heart-o; } +.@{fa-css-prefix}-sign-out:before { content: @fa-var-sign-out; } +.@{fa-css-prefix}-linkedin-square:before { content: @fa-var-linkedin-square; } +.@{fa-css-prefix}-thumb-tack:before { content: @fa-var-thumb-tack; } +.@{fa-css-prefix}-external-link:before { content: @fa-var-external-link; } +.@{fa-css-prefix}-sign-in:before { content: @fa-var-sign-in; } +.@{fa-css-prefix}-trophy:before { content: @fa-var-trophy; } +.@{fa-css-prefix}-github-square:before { content: @fa-var-github-square; } +.@{fa-css-prefix}-upload:before { content: @fa-var-upload; } +.@{fa-css-prefix}-lemon-o:before { content: @fa-var-lemon-o; } +.@{fa-css-prefix}-phone:before { content: @fa-var-phone; } +.@{fa-css-prefix}-square-o:before { content: @fa-var-square-o; } +.@{fa-css-prefix}-bookmark-o:before { content: @fa-var-bookmark-o; } +.@{fa-css-prefix}-phone-square:before { content: @fa-var-phone-square; } +.@{fa-css-prefix}-twitter:before { content: @fa-var-twitter; } +.@{fa-css-prefix}-facebook:before { content: @fa-var-facebook; } +.@{fa-css-prefix}-github:before { content: @fa-var-github; } +.@{fa-css-prefix}-unlock:before { content: @fa-var-unlock; } +.@{fa-css-prefix}-credit-card:before { content: @fa-var-credit-card; } +.@{fa-css-prefix}-rss:before { content: @fa-var-rss; } +.@{fa-css-prefix}-hdd-o:before { content: @fa-var-hdd-o; } +.@{fa-css-prefix}-bullhorn:before { content: @fa-var-bullhorn; } +.@{fa-css-prefix}-bell:before { content: @fa-var-bell; } +.@{fa-css-prefix}-certificate:before { content: @fa-var-certificate; } +.@{fa-css-prefix}-hand-o-right:before { content: @fa-var-hand-o-right; } +.@{fa-css-prefix}-hand-o-left:before { content: @fa-var-hand-o-left; } +.@{fa-css-prefix}-hand-o-up:before { content: @fa-var-hand-o-up; } +.@{fa-css-prefix}-hand-o-down:before { content: @fa-var-hand-o-down; } +.@{fa-css-prefix}-arrow-circle-left:before { content: @fa-var-arrow-circle-left; } +.@{fa-css-prefix}-arrow-circle-right:before { content: @fa-var-arrow-circle-right; } +.@{fa-css-prefix}-arrow-circle-up:before { content: @fa-var-arrow-circle-up; } +.@{fa-css-prefix}-arrow-circle-down:before { content: @fa-var-arrow-circle-down; } +.@{fa-css-prefix}-globe:before { content: @fa-var-globe; } +.@{fa-css-prefix}-wrench:before { content: @fa-var-wrench; } +.@{fa-css-prefix}-tasks:before { content: @fa-var-tasks; } +.@{fa-css-prefix}-filter:before { content: @fa-var-filter; } +.@{fa-css-prefix}-briefcase:before { content: @fa-var-briefcase; } +.@{fa-css-prefix}-arrows-alt:before { content: @fa-var-arrows-alt; } +.@{fa-css-prefix}-group:before, +.@{fa-css-prefix}-users:before { content: @fa-var-users; } +.@{fa-css-prefix}-chain:before, +.@{fa-css-prefix}-link:before { content: @fa-var-link; } +.@{fa-css-prefix}-cloud:before { content: @fa-var-cloud; } +.@{fa-css-prefix}-flask:before { content: @fa-var-flask; } +.@{fa-css-prefix}-cut:before, +.@{fa-css-prefix}-scissors:before { content: @fa-var-scissors; } +.@{fa-css-prefix}-copy:before, +.@{fa-css-prefix}-files-o:before { content: @fa-var-files-o; } +.@{fa-css-prefix}-paperclip:before { content: @fa-var-paperclip; } +.@{fa-css-prefix}-save:before, +.@{fa-css-prefix}-floppy-o:before { content: @fa-var-floppy-o; } +.@{fa-css-prefix}-square:before { content: @fa-var-square; } +.@{fa-css-prefix}-bars:before { content: @fa-var-bars; } +.@{fa-css-prefix}-list-ul:before { content: @fa-var-list-ul; } +.@{fa-css-prefix}-list-ol:before { content: @fa-var-list-ol; } +.@{fa-css-prefix}-strikethrough:before { content: @fa-var-strikethrough; } +.@{fa-css-prefix}-underline:before { content: @fa-var-underline; } +.@{fa-css-prefix}-table:before { content: @fa-var-table; } +.@{fa-css-prefix}-magic:before { content: @fa-var-magic; } +.@{fa-css-prefix}-truck:before { content: @fa-var-truck; } +.@{fa-css-prefix}-pinterest:before { content: @fa-var-pinterest; } +.@{fa-css-prefix}-pinterest-square:before { content: @fa-var-pinterest-square; } +.@{fa-css-prefix}-google-plus-square:before { content: @fa-var-google-plus-square; } +.@{fa-css-prefix}-google-plus:before { content: @fa-var-google-plus; } +.@{fa-css-prefix}-money:before { content: @fa-var-money; } +.@{fa-css-prefix}-caret-down:before { content: @fa-var-caret-down; } +.@{fa-css-prefix}-caret-up:before { content: @fa-var-caret-up; } +.@{fa-css-prefix}-caret-left:before { content: @fa-var-caret-left; } +.@{fa-css-prefix}-caret-right:before { content: @fa-var-caret-right; } +.@{fa-css-prefix}-columns:before { content: @fa-var-columns; } +.@{fa-css-prefix}-unsorted:before, +.@{fa-css-prefix}-sort:before { content: @fa-var-sort; } +.@{fa-css-prefix}-sort-down:before, +.@{fa-css-prefix}-sort-asc:before { content: @fa-var-sort-asc; } +.@{fa-css-prefix}-sort-up:before, +.@{fa-css-prefix}-sort-desc:before { content: @fa-var-sort-desc; } +.@{fa-css-prefix}-envelope:before { content: @fa-var-envelope; } +.@{fa-css-prefix}-linkedin:before { content: @fa-var-linkedin; } +.@{fa-css-prefix}-rotate-left:before, +.@{fa-css-prefix}-undo:before { content: @fa-var-undo; } +.@{fa-css-prefix}-legal:before, +.@{fa-css-prefix}-gavel:before { content: @fa-var-gavel; } +.@{fa-css-prefix}-dashboard:before, +.@{fa-css-prefix}-tachometer:before { content: @fa-var-tachometer; } +.@{fa-css-prefix}-comment-o:before { content: @fa-var-comment-o; } +.@{fa-css-prefix}-comments-o:before { content: @fa-var-comments-o; } +.@{fa-css-prefix}-flash:before, +.@{fa-css-prefix}-bolt:before { content: @fa-var-bolt; } +.@{fa-css-prefix}-sitemap:before { content: @fa-var-sitemap; } +.@{fa-css-prefix}-umbrella:before { content: @fa-var-umbrella; } +.@{fa-css-prefix}-paste:before, +.@{fa-css-prefix}-clipboard:before { content: @fa-var-clipboard; } +.@{fa-css-prefix}-lightbulb-o:before { content: @fa-var-lightbulb-o; } +.@{fa-css-prefix}-exchange:before { content: @fa-var-exchange; } +.@{fa-css-prefix}-cloud-download:before { content: @fa-var-cloud-download; } +.@{fa-css-prefix}-cloud-upload:before { content: @fa-var-cloud-upload; } +.@{fa-css-prefix}-user-md:before { content: @fa-var-user-md; } +.@{fa-css-prefix}-stethoscope:before { content: @fa-var-stethoscope; } +.@{fa-css-prefix}-suitcase:before { content: @fa-var-suitcase; } +.@{fa-css-prefix}-bell-o:before { content: @fa-var-bell-o; } +.@{fa-css-prefix}-coffee:before { content: @fa-var-coffee; } +.@{fa-css-prefix}-cutlery:before { content: @fa-var-cutlery; } +.@{fa-css-prefix}-file-text-o:before { content: @fa-var-file-text-o; } +.@{fa-css-prefix}-building-o:before { content: @fa-var-building-o; } +.@{fa-css-prefix}-hospital-o:before { content: @fa-var-hospital-o; } +.@{fa-css-prefix}-ambulance:before { content: @fa-var-ambulance; } +.@{fa-css-prefix}-medkit:before { content: @fa-var-medkit; } +.@{fa-css-prefix}-fighter-jet:before { content: @fa-var-fighter-jet; } +.@{fa-css-prefix}-beer:before { content: @fa-var-beer; } +.@{fa-css-prefix}-h-square:before { content: @fa-var-h-square; } +.@{fa-css-prefix}-plus-square:before { content: @fa-var-plus-square; } +.@{fa-css-prefix}-angle-double-left:before { content: @fa-var-angle-double-left; } +.@{fa-css-prefix}-angle-double-right:before { content: @fa-var-angle-double-right; } +.@{fa-css-prefix}-angle-double-up:before { content: @fa-var-angle-double-up; } +.@{fa-css-prefix}-angle-double-down:before { content: @fa-var-angle-double-down; } +.@{fa-css-prefix}-angle-left:before { content: @fa-var-angle-left; } +.@{fa-css-prefix}-angle-right:before { content: @fa-var-angle-right; } +.@{fa-css-prefix}-angle-up:before { content: @fa-var-angle-up; } +.@{fa-css-prefix}-angle-down:before { content: @fa-var-angle-down; } +.@{fa-css-prefix}-desktop:before { content: @fa-var-desktop; } +.@{fa-css-prefix}-laptop:before { content: @fa-var-laptop; } +.@{fa-css-prefix}-tablet:before { content: @fa-var-tablet; } +.@{fa-css-prefix}-mobile-phone:before, +.@{fa-css-prefix}-mobile:before { content: @fa-var-mobile; } +.@{fa-css-prefix}-circle-o:before { content: @fa-var-circle-o; } +.@{fa-css-prefix}-quote-left:before { content: @fa-var-quote-left; } +.@{fa-css-prefix}-quote-right:before { content: @fa-var-quote-right; } +.@{fa-css-prefix}-spinner:before { content: @fa-var-spinner; } +.@{fa-css-prefix}-circle:before { content: @fa-var-circle; } +.@{fa-css-prefix}-mail-reply:before, +.@{fa-css-prefix}-reply:before { content: @fa-var-reply; } +.@{fa-css-prefix}-github-alt:before { content: @fa-var-github-alt; } +.@{fa-css-prefix}-folder-o:before { content: @fa-var-folder-o; } +.@{fa-css-prefix}-folder-open-o:before { content: @fa-var-folder-open-o; } +.@{fa-css-prefix}-smile-o:before { content: @fa-var-smile-o; } +.@{fa-css-prefix}-frown-o:before { content: @fa-var-frown-o; } +.@{fa-css-prefix}-meh-o:before { content: @fa-var-meh-o; } +.@{fa-css-prefix}-gamepad:before { content: @fa-var-gamepad; } +.@{fa-css-prefix}-keyboard-o:before { content: @fa-var-keyboard-o; } +.@{fa-css-prefix}-flag-o:before { content: @fa-var-flag-o; } +.@{fa-css-prefix}-flag-checkered:before { content: @fa-var-flag-checkered; } +.@{fa-css-prefix}-terminal:before { content: @fa-var-terminal; } +.@{fa-css-prefix}-code:before { content: @fa-var-code; } +.@{fa-css-prefix}-reply-all:before { content: @fa-var-reply-all; } +.@{fa-css-prefix}-mail-reply-all:before { content: @fa-var-mail-reply-all; } +.@{fa-css-prefix}-star-half-empty:before, +.@{fa-css-prefix}-star-half-full:before, +.@{fa-css-prefix}-star-half-o:before { content: @fa-var-star-half-o; } +.@{fa-css-prefix}-location-arrow:before { content: @fa-var-location-arrow; } +.@{fa-css-prefix}-crop:before { content: @fa-var-crop; } +.@{fa-css-prefix}-code-fork:before { content: @fa-var-code-fork; } +.@{fa-css-prefix}-unlink:before, +.@{fa-css-prefix}-chain-broken:before { content: @fa-var-chain-broken; } +.@{fa-css-prefix}-question:before { content: @fa-var-question; } +.@{fa-css-prefix}-info:before { content: @fa-var-info; } +.@{fa-css-prefix}-exclamation:before { content: @fa-var-exclamation; } +.@{fa-css-prefix}-superscript:before { content: @fa-var-superscript; } +.@{fa-css-prefix}-subscript:before { content: @fa-var-subscript; } +.@{fa-css-prefix}-eraser:before { content: @fa-var-eraser; } +.@{fa-css-prefix}-puzzle-piece:before { content: @fa-var-puzzle-piece; } +.@{fa-css-prefix}-microphone:before { content: @fa-var-microphone; } +.@{fa-css-prefix}-microphone-slash:before { content: @fa-var-microphone-slash; } +.@{fa-css-prefix}-shield:before { content: @fa-var-shield; } +.@{fa-css-prefix}-calendar-o:before { content: @fa-var-calendar-o; } +.@{fa-css-prefix}-fire-extinguisher:before { content: @fa-var-fire-extinguisher; } +.@{fa-css-prefix}-rocket:before { content: @fa-var-rocket; } +.@{fa-css-prefix}-maxcdn:before { content: @fa-var-maxcdn; } +.@{fa-css-prefix}-chevron-circle-left:before { content: @fa-var-chevron-circle-left; } +.@{fa-css-prefix}-chevron-circle-right:before { content: @fa-var-chevron-circle-right; } +.@{fa-css-prefix}-chevron-circle-up:before { content: @fa-var-chevron-circle-up; } +.@{fa-css-prefix}-chevron-circle-down:before { content: @fa-var-chevron-circle-down; } +.@{fa-css-prefix}-html5:before { content: @fa-var-html5; } +.@{fa-css-prefix}-css3:before { content: @fa-var-css3; } +.@{fa-css-prefix}-anchor:before { content: @fa-var-anchor; } +.@{fa-css-prefix}-unlock-alt:before { content: @fa-var-unlock-alt; } +.@{fa-css-prefix}-bullseye:before { content: @fa-var-bullseye; } +.@{fa-css-prefix}-ellipsis-h:before { content: @fa-var-ellipsis-h; } +.@{fa-css-prefix}-ellipsis-v:before { content: @fa-var-ellipsis-v; } +.@{fa-css-prefix}-rss-square:before { content: @fa-var-rss-square; } +.@{fa-css-prefix}-play-circle:before { content: @fa-var-play-circle; } +.@{fa-css-prefix}-ticket:before { content: @fa-var-ticket; } +.@{fa-css-prefix}-minus-square:before { content: @fa-var-minus-square; } +.@{fa-css-prefix}-minus-square-o:before { content: @fa-var-minus-square-o; } +.@{fa-css-prefix}-level-up:before { content: @fa-var-level-up; } +.@{fa-css-prefix}-level-down:before { content: @fa-var-level-down; } +.@{fa-css-prefix}-check-square:before { content: @fa-var-check-square; } +.@{fa-css-prefix}-pencil-square:before { content: @fa-var-pencil-square; } +.@{fa-css-prefix}-external-link-square:before { content: @fa-var-external-link-square; } +.@{fa-css-prefix}-share-square:before { content: @fa-var-share-square; } +.@{fa-css-prefix}-compass:before { content: @fa-var-compass; } +.@{fa-css-prefix}-toggle-down:before, +.@{fa-css-prefix}-caret-square-o-down:before { content: @fa-var-caret-square-o-down; } +.@{fa-css-prefix}-toggle-up:before, +.@{fa-css-prefix}-caret-square-o-up:before { content: @fa-var-caret-square-o-up; } +.@{fa-css-prefix}-toggle-right:before, +.@{fa-css-prefix}-caret-square-o-right:before { content: @fa-var-caret-square-o-right; } +.@{fa-css-prefix}-euro:before, +.@{fa-css-prefix}-eur:before { content: @fa-var-eur; } +.@{fa-css-prefix}-gbp:before { content: @fa-var-gbp; } +.@{fa-css-prefix}-dollar:before, +.@{fa-css-prefix}-usd:before { content: @fa-var-usd; } +.@{fa-css-prefix}-rupee:before, +.@{fa-css-prefix}-inr:before { content: @fa-var-inr; } +.@{fa-css-prefix}-cny:before, +.@{fa-css-prefix}-rmb:before, +.@{fa-css-prefix}-yen:before, +.@{fa-css-prefix}-jpy:before { content: @fa-var-jpy; } +.@{fa-css-prefix}-ruble:before, +.@{fa-css-prefix}-rouble:before, +.@{fa-css-prefix}-rub:before { content: @fa-var-rub; } +.@{fa-css-prefix}-won:before, +.@{fa-css-prefix}-krw:before { content: @fa-var-krw; } +.@{fa-css-prefix}-bitcoin:before, +.@{fa-css-prefix}-btc:before { content: @fa-var-btc; } +.@{fa-css-prefix}-file:before { content: @fa-var-file; } +.@{fa-css-prefix}-file-text:before { content: @fa-var-file-text; } +.@{fa-css-prefix}-sort-alpha-asc:before { content: @fa-var-sort-alpha-asc; } +.@{fa-css-prefix}-sort-alpha-desc:before { content: @fa-var-sort-alpha-desc; } +.@{fa-css-prefix}-sort-amount-asc:before { content: @fa-var-sort-amount-asc; } +.@{fa-css-prefix}-sort-amount-desc:before { content: @fa-var-sort-amount-desc; } +.@{fa-css-prefix}-sort-numeric-asc:before { content: @fa-var-sort-numeric-asc; } +.@{fa-css-prefix}-sort-numeric-desc:before { content: @fa-var-sort-numeric-desc; } +.@{fa-css-prefix}-thumbs-up:before { content: @fa-var-thumbs-up; } +.@{fa-css-prefix}-thumbs-down:before { content: @fa-var-thumbs-down; } +.@{fa-css-prefix}-youtube-square:before { content: @fa-var-youtube-square; } +.@{fa-css-prefix}-youtube:before { content: @fa-var-youtube; } +.@{fa-css-prefix}-xing:before { content: @fa-var-xing; } +.@{fa-css-prefix}-xing-square:before { content: @fa-var-xing-square; } +.@{fa-css-prefix}-youtube-play:before { content: @fa-var-youtube-play; } +.@{fa-css-prefix}-dropbox:before { content: @fa-var-dropbox; } +.@{fa-css-prefix}-stack-overflow:before { content: @fa-var-stack-overflow; } +.@{fa-css-prefix}-instagram:before { content: @fa-var-instagram; } +.@{fa-css-prefix}-flickr:before { content: @fa-var-flickr; } +.@{fa-css-prefix}-adn:before { content: @fa-var-adn; } +.@{fa-css-prefix}-bitbucket:before { content: @fa-var-bitbucket; } +.@{fa-css-prefix}-bitbucket-square:before { content: @fa-var-bitbucket-square; } +.@{fa-css-prefix}-tumblr:before { content: @fa-var-tumblr; } +.@{fa-css-prefix}-tumblr-square:before { content: @fa-var-tumblr-square; } +.@{fa-css-prefix}-long-arrow-down:before { content: @fa-var-long-arrow-down; } +.@{fa-css-prefix}-long-arrow-up:before { content: @fa-var-long-arrow-up; } +.@{fa-css-prefix}-long-arrow-left:before { content: @fa-var-long-arrow-left; } +.@{fa-css-prefix}-long-arrow-right:before { content: @fa-var-long-arrow-right; } +.@{fa-css-prefix}-apple:before { content: @fa-var-apple; } +.@{fa-css-prefix}-windows:before { content: @fa-var-windows; } +.@{fa-css-prefix}-android:before { content: @fa-var-android; } +.@{fa-css-prefix}-linux:before { content: @fa-var-linux; } +.@{fa-css-prefix}-dribbble:before { content: @fa-var-dribbble; } +.@{fa-css-prefix}-skype:before { content: @fa-var-skype; } +.@{fa-css-prefix}-foursquare:before { content: @fa-var-foursquare; } +.@{fa-css-prefix}-trello:before { content: @fa-var-trello; } +.@{fa-css-prefix}-female:before { content: @fa-var-female; } +.@{fa-css-prefix}-male:before { content: @fa-var-male; } +.@{fa-css-prefix}-gittip:before { content: @fa-var-gittip; } +.@{fa-css-prefix}-sun-o:before { content: @fa-var-sun-o; } +.@{fa-css-prefix}-moon-o:before { content: @fa-var-moon-o; } +.@{fa-css-prefix}-archive:before { content: @fa-var-archive; } +.@{fa-css-prefix}-bug:before { content: @fa-var-bug; } +.@{fa-css-prefix}-vk:before { content: @fa-var-vk; } +.@{fa-css-prefix}-weibo:before { content: @fa-var-weibo; } +.@{fa-css-prefix}-renren:before { content: @fa-var-renren; } +.@{fa-css-prefix}-pagelines:before { content: @fa-var-pagelines; } +.@{fa-css-prefix}-stack-exchange:before { content: @fa-var-stack-exchange; } +.@{fa-css-prefix}-arrow-circle-o-right:before { content: @fa-var-arrow-circle-o-right; } +.@{fa-css-prefix}-arrow-circle-o-left:before { content: @fa-var-arrow-circle-o-left; } +.@{fa-css-prefix}-toggle-left:before, +.@{fa-css-prefix}-caret-square-o-left:before { content: @fa-var-caret-square-o-left; } +.@{fa-css-prefix}-dot-circle-o:before { content: @fa-var-dot-circle-o; } +.@{fa-css-prefix}-wheelchair:before { content: @fa-var-wheelchair; } +.@{fa-css-prefix}-vimeo-square:before { content: @fa-var-vimeo-square; } +.@{fa-css-prefix}-turkish-lira:before, +.@{fa-css-prefix}-try:before { content: @fa-var-try; } +.@{fa-css-prefix}-plus-square-o:before { content: @fa-var-plus-square-o; } diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/larger.less b/src/static/movio/templates/Skeleton/less/font-awesome/larger.less new file mode 100644 index 0000000..c9d6467 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/larger.less @@ -0,0 +1,13 @@ +// Icon Sizes +// ------------------------- + +/* makes the font 33% larger relative to the icon container */ +.@{fa-css-prefix}-lg { + font-size: (4em / 3); + line-height: (3em / 4); + vertical-align: -15%; +} +.@{fa-css-prefix}-2x { font-size: 2em; } +.@{fa-css-prefix}-3x { font-size: 3em; } +.@{fa-css-prefix}-4x { font-size: 4em; } +.@{fa-css-prefix}-5x { font-size: 5em; } diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/list.less b/src/static/movio/templates/Skeleton/less/font-awesome/list.less new file mode 100644 index 0000000..eed9340 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/list.less @@ -0,0 +1,19 @@ +// List Icons +// ------------------------- + +.@{fa-css-prefix}-ul { + padding-left: 0; + margin-left: @fa-li-width; + list-style-type: none; + > li { position: relative; } +} +.@{fa-css-prefix}-li { + position: absolute; + left: -@fa-li-width; + width: @fa-li-width; + top: (2em / 14); + text-align: center; + &.@{fa-css-prefix}-lg { + left: -@fa-li-width + (4em / 14); + } +} diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/mixins.less b/src/static/movio/templates/Skeleton/less/font-awesome/mixins.less new file mode 100644 index 0000000..19e5a64 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/mixins.less @@ -0,0 +1,20 @@ +// Mixins +// -------------------------- + +.fa-icon-rotate(@degrees, @rotation) { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation); + -webkit-transform: rotate(@degrees); + -moz-transform: rotate(@degrees); + -ms-transform: rotate(@degrees); + -o-transform: rotate(@degrees); + transform: rotate(@degrees); +} + +.fa-icon-flip(@horiz, @vert, @rotation) { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1); + -webkit-transform: scale(@horiz, @vert); + -moz-transform: scale(@horiz, @vert); + -ms-transform: scale(@horiz, @vert); + -o-transform: scale(@horiz, @vert); + transform: scale(@horiz, @vert); +} diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/path.less b/src/static/movio/templates/Skeleton/less/font-awesome/path.less new file mode 100644 index 0000000..c5a6912 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/path.less @@ -0,0 +1,14 @@ +/* FONT PATH + * -------------------------- */ + +@font-face { + font-family: 'FontAwesome'; + src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); + src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), + url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), + url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), + url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); +// src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts + font-weight: normal; + font-style: normal; +} diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/rotated-flipped.less b/src/static/movio/templates/Skeleton/less/font-awesome/rotated-flipped.less new file mode 100644 index 0000000..8fff3a6 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/rotated-flipped.less @@ -0,0 +1,9 @@ +// Rotated & Flipped Icons +// ------------------------- + +.@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } +.@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } +.@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } + +.@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } +.@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/spinning.less b/src/static/movio/templates/Skeleton/less/font-awesome/spinning.less new file mode 100644 index 0000000..60828fe --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/spinning.less @@ -0,0 +1,30 @@ +// Spinning Icons +// -------------------------- + +.@{fa-css-prefix}-spin { + -webkit-animation: spin 2s infinite linear; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} + +@-moz-keyframes spin { + 0% { -moz-transform: rotate(0deg); } + 100% { -moz-transform: rotate(359deg); } +} +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(359deg); } +} +@-o-keyframes spin { + 0% { -o-transform: rotate(0deg); } + 100% { -o-transform: rotate(359deg); } +} +@-ms-keyframes spin { + 0% { -ms-transform: rotate(0deg); } + 100% { -ms-transform: rotate(359deg); } +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(359deg); } +} diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/stacked.less b/src/static/movio/templates/Skeleton/less/font-awesome/stacked.less new file mode 100644 index 0000000..fc53fb0 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/stacked.less @@ -0,0 +1,20 @@ +// Stacked Icons +// ------------------------- + +.@{fa-css-prefix}-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.@{fa-css-prefix}-stack-1x { line-height: inherit; } +.@{fa-css-prefix}-stack-2x { font-size: 2em; } +.@{fa-css-prefix}-inverse { color: @fa-inverse; } diff --git a/src/static/movio/templates/Skeleton/less/font-awesome/variables.less b/src/static/movio/templates/Skeleton/less/font-awesome/variables.less new file mode 100644 index 0000000..3ab7a75 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/font-awesome/variables.less @@ -0,0 +1,381 @@ +// Variables +// -------------------------- + +//@fa-font-path: "../font/font-awesome"; +@fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts"; // for referencing Bootstrap CDN font files directly +@fa-css-prefix: fa; +@fa-version: "4.0.3"; +@fa-border-color: #eee; +@fa-inverse: #fff; +@fa-li-width: (30em / 14); + +@fa-var-glass: "\f000"; +@fa-var-music: "\f001"; +@fa-var-search: "\f002"; +@fa-var-envelope-o: "\f003"; +@fa-var-heart: "\f004"; +@fa-var-star: "\f005"; +@fa-var-star-o: "\f006"; +@fa-var-user: "\f007"; +@fa-var-film: "\f008"; +@fa-var-th-large: "\f009"; +@fa-var-th: "\f00a"; +@fa-var-th-list: "\f00b"; +@fa-var-check: "\f00c"; +@fa-var-times: "\f00d"; +@fa-var-search-plus: "\f00e"; +@fa-var-search-minus: "\f010"; +@fa-var-power-off: "\f011"; +@fa-var-signal: "\f012"; +@fa-var-cog: "\f013"; +@fa-var-trash-o: "\f014"; +@fa-var-home: "\f015"; +@fa-var-file-o: "\f016"; +@fa-var-clock-o: "\f017"; +@fa-var-road: "\f018"; +@fa-var-download: "\f019"; +@fa-var-arrow-circle-o-down: "\f01a"; +@fa-var-arrow-circle-o-up: "\f01b"; +@fa-var-inbox: "\f01c"; +@fa-var-play-circle-o: "\f01d"; +@fa-var-repeat: "\f01e"; +@fa-var-refresh: "\f021"; +@fa-var-list-alt: "\f022"; +@fa-var-lock: "\f023"; +@fa-var-flag: "\f024"; +@fa-var-headphones: "\f025"; +@fa-var-volume-off: "\f026"; +@fa-var-volume-down: "\f027"; +@fa-var-volume-up: "\f028"; +@fa-var-qrcode: "\f029"; +@fa-var-barcode: "\f02a"; +@fa-var-tag: "\f02b"; +@fa-var-tags: "\f02c"; +@fa-var-book: "\f02d"; +@fa-var-bookmark: "\f02e"; +@fa-var-print: "\f02f"; +@fa-var-camera: "\f030"; +@fa-var-font: "\f031"; +@fa-var-bold: "\f032"; +@fa-var-italic: "\f033"; +@fa-var-text-height: "\f034"; +@fa-var-text-width: "\f035"; +@fa-var-align-left: "\f036"; +@fa-var-align-center: "\f037"; +@fa-var-align-right: "\f038"; +@fa-var-align-justify: "\f039"; +@fa-var-list: "\f03a"; +@fa-var-outdent: "\f03b"; +@fa-var-indent: "\f03c"; +@fa-var-video-camera: "\f03d"; +@fa-var-picture-o: "\f03e"; +@fa-var-pencil: "\f040"; +@fa-var-map-marker: "\f041"; +@fa-var-adjust: "\f042"; +@fa-var-tint: "\f043"; +@fa-var-pencil-square-o: "\f044"; +@fa-var-share-square-o: "\f045"; +@fa-var-check-square-o: "\f046"; +@fa-var-arrows: "\f047"; +@fa-var-step-backward: "\f048"; +@fa-var-fast-backward: "\f049"; +@fa-var-backward: "\f04a"; +@fa-var-play: "\f04b"; +@fa-var-pause: "\f04c"; +@fa-var-stop: "\f04d"; +@fa-var-forward: "\f04e"; +@fa-var-fast-forward: "\f050"; +@fa-var-step-forward: "\f051"; +@fa-var-eject: "\f052"; +@fa-var-chevron-left: "\f053"; +@fa-var-chevron-right: "\f054"; +@fa-var-plus-circle: "\f055"; +@fa-var-minus-circle: "\f056"; +@fa-var-times-circle: "\f057"; +@fa-var-check-circle: "\f058"; +@fa-var-question-circle: "\f059"; +@fa-var-info-circle: "\f05a"; +@fa-var-crosshairs: "\f05b"; +@fa-var-times-circle-o: "\f05c"; +@fa-var-check-circle-o: "\f05d"; +@fa-var-ban: "\f05e"; +@fa-var-arrow-left: "\f060"; +@fa-var-arrow-right: "\f061"; +@fa-var-arrow-up: "\f062"; +@fa-var-arrow-down: "\f063"; +@fa-var-share: "\f064"; +@fa-var-expand: "\f065"; +@fa-var-compress: "\f066"; +@fa-var-plus: "\f067"; +@fa-var-minus: "\f068"; +@fa-var-asterisk: "\f069"; +@fa-var-exclamation-circle: "\f06a"; +@fa-var-gift: "\f06b"; +@fa-var-leaf: "\f06c"; +@fa-var-fire: "\f06d"; +@fa-var-eye: "\f06e"; +@fa-var-eye-slash: "\f070"; +@fa-var-exclamation-triangle: "\f071"; +@fa-var-plane: "\f072"; +@fa-var-calendar: "\f073"; +@fa-var-random: "\f074"; +@fa-var-comment: "\f075"; +@fa-var-magnet: "\f076"; +@fa-var-chevron-up: "\f077"; +@fa-var-chevron-down: "\f078"; +@fa-var-retweet: "\f079"; +@fa-var-shopping-cart: "\f07a"; +@fa-var-folder: "\f07b"; +@fa-var-folder-open: "\f07c"; +@fa-var-arrows-v: "\f07d"; +@fa-var-arrows-h: "\f07e"; +@fa-var-bar-chart-o: "\f080"; +@fa-var-twitter-square: "\f081"; +@fa-var-facebook-square: "\f082"; +@fa-var-camera-retro: "\f083"; +@fa-var-key: "\f084"; +@fa-var-cogs: "\f085"; +@fa-var-comments: "\f086"; +@fa-var-thumbs-o-up: "\f087"; +@fa-var-thumbs-o-down: "\f088"; +@fa-var-star-half: "\f089"; +@fa-var-heart-o: "\f08a"; +@fa-var-sign-out: "\f08b"; +@fa-var-linkedin-square: "\f08c"; +@fa-var-thumb-tack: "\f08d"; +@fa-var-external-link: "\f08e"; +@fa-var-sign-in: "\f090"; +@fa-var-trophy: "\f091"; +@fa-var-github-square: "\f092"; +@fa-var-upload: "\f093"; +@fa-var-lemon-o: "\f094"; +@fa-var-phone: "\f095"; +@fa-var-square-o: "\f096"; +@fa-var-bookmark-o: "\f097"; +@fa-var-phone-square: "\f098"; +@fa-var-twitter: "\f099"; +@fa-var-facebook: "\f09a"; +@fa-var-github: "\f09b"; +@fa-var-unlock: "\f09c"; +@fa-var-credit-card: "\f09d"; +@fa-var-rss: "\f09e"; +@fa-var-hdd-o: "\f0a0"; +@fa-var-bullhorn: "\f0a1"; +@fa-var-bell: "\f0f3"; +@fa-var-certificate: "\f0a3"; +@fa-var-hand-o-right: "\f0a4"; +@fa-var-hand-o-left: "\f0a5"; +@fa-var-hand-o-up: "\f0a6"; +@fa-var-hand-o-down: "\f0a7"; +@fa-var-arrow-circle-left: "\f0a8"; +@fa-var-arrow-circle-right: "\f0a9"; +@fa-var-arrow-circle-up: "\f0aa"; +@fa-var-arrow-circle-down: "\f0ab"; +@fa-var-globe: "\f0ac"; +@fa-var-wrench: "\f0ad"; +@fa-var-tasks: "\f0ae"; +@fa-var-filter: "\f0b0"; +@fa-var-briefcase: "\f0b1"; +@fa-var-arrows-alt: "\f0b2"; +@fa-var-users: "\f0c0"; +@fa-var-link: "\f0c1"; +@fa-var-cloud: "\f0c2"; +@fa-var-flask: "\f0c3"; +@fa-var-scissors: "\f0c4"; +@fa-var-files-o: "\f0c5"; +@fa-var-paperclip: "\f0c6"; +@fa-var-floppy-o: "\f0c7"; +@fa-var-square: "\f0c8"; +@fa-var-bars: "\f0c9"; +@fa-var-list-ul: "\f0ca"; +@fa-var-list-ol: "\f0cb"; +@fa-var-strikethrough: "\f0cc"; +@fa-var-underline: "\f0cd"; +@fa-var-table: "\f0ce"; +@fa-var-magic: "\f0d0"; +@fa-var-truck: "\f0d1"; +@fa-var-pinterest: "\f0d2"; +@fa-var-pinterest-square: "\f0d3"; +@fa-var-google-plus-square: "\f0d4"; +@fa-var-google-plus: "\f0d5"; +@fa-var-money: "\f0d6"; +@fa-var-caret-down: "\f0d7"; +@fa-var-caret-up: "\f0d8"; +@fa-var-caret-left: "\f0d9"; +@fa-var-caret-right: "\f0da"; +@fa-var-columns: "\f0db"; +@fa-var-sort: "\f0dc"; +@fa-var-sort-asc: "\f0dd"; +@fa-var-sort-desc: "\f0de"; +@fa-var-envelope: "\f0e0"; +@fa-var-linkedin: "\f0e1"; +@fa-var-undo: "\f0e2"; +@fa-var-gavel: "\f0e3"; +@fa-var-tachometer: "\f0e4"; +@fa-var-comment-o: "\f0e5"; +@fa-var-comments-o: "\f0e6"; +@fa-var-bolt: "\f0e7"; +@fa-var-sitemap: "\f0e8"; +@fa-var-umbrella: "\f0e9"; +@fa-var-clipboard: "\f0ea"; +@fa-var-lightbulb-o: "\f0eb"; +@fa-var-exchange: "\f0ec"; +@fa-var-cloud-download: "\f0ed"; +@fa-var-cloud-upload: "\f0ee"; +@fa-var-user-md: "\f0f0"; +@fa-var-stethoscope: "\f0f1"; +@fa-var-suitcase: "\f0f2"; +@fa-var-bell-o: "\f0a2"; +@fa-var-coffee: "\f0f4"; +@fa-var-cutlery: "\f0f5"; +@fa-var-file-text-o: "\f0f6"; +@fa-var-building-o: "\f0f7"; +@fa-var-hospital-o: "\f0f8"; +@fa-var-ambulance: "\f0f9"; +@fa-var-medkit: "\f0fa"; +@fa-var-fighter-jet: "\f0fb"; +@fa-var-beer: "\f0fc"; +@fa-var-h-square: "\f0fd"; +@fa-var-plus-square: "\f0fe"; +@fa-var-angle-double-left: "\f100"; +@fa-var-angle-double-right: "\f101"; +@fa-var-angle-double-up: "\f102"; +@fa-var-angle-double-down: "\f103"; +@fa-var-angle-left: "\f104"; +@fa-var-angle-right: "\f105"; +@fa-var-angle-up: "\f106"; +@fa-var-angle-down: "\f107"; +@fa-var-desktop: "\f108"; +@fa-var-laptop: "\f109"; +@fa-var-tablet: "\f10a"; +@fa-var-mobile: "\f10b"; +@fa-var-circle-o: "\f10c"; +@fa-var-quote-left: "\f10d"; +@fa-var-quote-right: "\f10e"; +@fa-var-spinner: "\f110"; +@fa-var-circle: "\f111"; +@fa-var-reply: "\f112"; +@fa-var-github-alt: "\f113"; +@fa-var-folder-o: "\f114"; +@fa-var-folder-open-o: "\f115"; +@fa-var-smile-o: "\f118"; +@fa-var-frown-o: "\f119"; +@fa-var-meh-o: "\f11a"; +@fa-var-gamepad: "\f11b"; +@fa-var-keyboard-o: "\f11c"; +@fa-var-flag-o: "\f11d"; +@fa-var-flag-checkered: "\f11e"; +@fa-var-terminal: "\f120"; +@fa-var-code: "\f121"; +@fa-var-reply-all: "\f122"; +@fa-var-mail-reply-all: "\f122"; +@fa-var-star-half-o: "\f123"; +@fa-var-location-arrow: "\f124"; +@fa-var-crop: "\f125"; +@fa-var-code-fork: "\f126"; +@fa-var-chain-broken: "\f127"; +@fa-var-question: "\f128"; +@fa-var-info: "\f129"; +@fa-var-exclamation: "\f12a"; +@fa-var-superscript: "\f12b"; +@fa-var-subscript: "\f12c"; +@fa-var-eraser: "\f12d"; +@fa-var-puzzle-piece: "\f12e"; +@fa-var-microphone: "\f130"; +@fa-var-microphone-slash: "\f131"; +@fa-var-shield: "\f132"; +@fa-var-calendar-o: "\f133"; +@fa-var-fire-extinguisher: "\f134"; +@fa-var-rocket: "\f135"; +@fa-var-maxcdn: "\f136"; +@fa-var-chevron-circle-left: "\f137"; +@fa-var-chevron-circle-right: "\f138"; +@fa-var-chevron-circle-up: "\f139"; +@fa-var-chevron-circle-down: "\f13a"; +@fa-var-html5: "\f13b"; +@fa-var-css3: "\f13c"; +@fa-var-anchor: "\f13d"; +@fa-var-unlock-alt: "\f13e"; +@fa-var-bullseye: "\f140"; +@fa-var-ellipsis-h: "\f141"; +@fa-var-ellipsis-v: "\f142"; +@fa-var-rss-square: "\f143"; +@fa-var-play-circle: "\f144"; +@fa-var-ticket: "\f145"; +@fa-var-minus-square: "\f146"; +@fa-var-minus-square-o: "\f147"; +@fa-var-level-up: "\f148"; +@fa-var-level-down: "\f149"; +@fa-var-check-square: "\f14a"; +@fa-var-pencil-square: "\f14b"; +@fa-var-external-link-square: "\f14c"; +@fa-var-share-square: "\f14d"; +@fa-var-compass: "\f14e"; +@fa-var-caret-square-o-down: "\f150"; +@fa-var-caret-square-o-up: "\f151"; +@fa-var-caret-square-o-right: "\f152"; +@fa-var-eur: "\f153"; +@fa-var-gbp: "\f154"; +@fa-var-usd: "\f155"; +@fa-var-inr: "\f156"; +@fa-var-jpy: "\f157"; +@fa-var-rub: "\f158"; +@fa-var-krw: "\f159"; +@fa-var-btc: "\f15a"; +@fa-var-file: "\f15b"; +@fa-var-file-text: "\f15c"; +@fa-var-sort-alpha-asc: "\f15d"; +@fa-var-sort-alpha-desc: "\f15e"; +@fa-var-sort-amount-asc: "\f160"; +@fa-var-sort-amount-desc: "\f161"; +@fa-var-sort-numeric-asc: "\f162"; +@fa-var-sort-numeric-desc: "\f163"; +@fa-var-thumbs-up: "\f164"; +@fa-var-thumbs-down: "\f165"; +@fa-var-youtube-square: "\f166"; +@fa-var-youtube: "\f167"; +@fa-var-xing: "\f168"; +@fa-var-xing-square: "\f169"; +@fa-var-youtube-play: "\f16a"; +@fa-var-dropbox: "\f16b"; +@fa-var-stack-overflow: "\f16c"; +@fa-var-instagram: "\f16d"; +@fa-var-flickr: "\f16e"; +@fa-var-adn: "\f170"; +@fa-var-bitbucket: "\f171"; +@fa-var-bitbucket-square: "\f172"; +@fa-var-tumblr: "\f173"; +@fa-var-tumblr-square: "\f174"; +@fa-var-long-arrow-down: "\f175"; +@fa-var-long-arrow-up: "\f176"; +@fa-var-long-arrow-left: "\f177"; +@fa-var-long-arrow-right: "\f178"; +@fa-var-apple: "\f179"; +@fa-var-windows: "\f17a"; +@fa-var-android: "\f17b"; +@fa-var-linux: "\f17c"; +@fa-var-dribbble: "\f17d"; +@fa-var-skype: "\f17e"; +@fa-var-foursquare: "\f180"; +@fa-var-trello: "\f181"; +@fa-var-female: "\f182"; +@fa-var-male: "\f183"; +@fa-var-gittip: "\f184"; +@fa-var-sun-o: "\f185"; +@fa-var-moon-o: "\f186"; +@fa-var-archive: "\f187"; +@fa-var-bug: "\f188"; +@fa-var-vk: "\f189"; +@fa-var-weibo: "\f18a"; +@fa-var-renren: "\f18b"; +@fa-var-pagelines: "\f18c"; +@fa-var-stack-exchange: "\f18d"; +@fa-var-arrow-circle-o-right: "\f18e"; +@fa-var-arrow-circle-o-left: "\f190"; +@fa-var-caret-square-o-left: "\f191"; +@fa-var-dot-circle-o: "\f192"; +@fa-var-wheelchair: "\f193"; +@fa-var-vimeo-square: "\f194"; +@fa-var-try: "\f195"; +@fa-var-plus-square-o: "\f196"; + diff --git a/src/static/movio/templates/Skeleton/less/libs/bootstrap.less b/src/static/movio/templates/Skeleton/less/libs/bootstrap.less new file mode 100755 index 0000000..e50c73d --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/libs/bootstrap.less @@ -0,0 +1,6564 @@ +/*! + * Bootstrap v3.3.2 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! + * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=65cac9d8616e41fc0aab) + * Config saved to config.json and https://gist.github.com/65cac9d8616e41fc0aab + */ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + text-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]: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; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333333; + background-color: #ffffff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + background-color: #fcf8e3; + padding: .2em; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #dddddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #dddddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.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 > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + overflow-x: auto; + min-height: 0.01%; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #dddddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; + background-color: #ffffff; + background-image: none; + border: 1px solid #cccccc; + border-radius: 4px; + -webkit-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-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #999999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999999; +} +.form-control::-webkit-input-placeholder { + color: #999999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; + opacity: 1; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-left: 0; + padding-right: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.form-group-sm .form-control { + height: 30px; + line-height: 30px; +} +textarea.form-group-sm .form-control, +select[multiple].form-group-sm .form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.form-group-lg .form-control { + height: 46px; + line-height: 46px; +} +textarea.form-group-lg .form-control, +select[multiple].form-group-lg .form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 7px; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.333333px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333333; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default.focus, +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default .badge { + color: #ffffff; + background-color: #333333; +} +.btn-primary { + color: #ffffff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary.focus, +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success.focus, +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info.focus, +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning.focus, +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger.focus, +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #ffffff; +} +.btn-link { + color: #337ab7; + font-weight: normal; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; + visibility: hidden; +} +.collapse.in { + display: block; + visibility: visible; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + -o-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.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; + font-size: 14px; + text-align: left; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + -webkit-background-clip: padding-box; + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #337ab7; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #cccccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.nav > li.disabled > a { + color: #777777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777777; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eeeeee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #dddddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #dddddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555555; + background-color: #ffffff; + border: 1px solid #dddddd; + border-bottom-color: transparent; + cursor: default; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.tab-content > .tab-pane { + display: none; + visibility: hidden; +} +.tab-content > .active { + display: block; + visibility: visible; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + visibility: visible !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; + height: 50px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-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); + margin-top: 8px; + margin-bottom: 8px; +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777777; +} +.navbar-default .navbar-nav > li > a { + color: #777777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #dddddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #dddddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + background-color: #e7e7e7; + color: #555555; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777777; +} +.navbar-default .navbar-link:hover { + color: #333333; +} +.navbar-default .btn-link { + color: #777777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #cccccc; +} +.navbar-inverse { + background-color: #222222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + background-color: #080808; + color: #ffffff; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #ffffff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #ffffff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + content: "/\00a0"; + padding: 0 5px; + color: #cccccc; +} +.breadcrumb > .active { + color: #777777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + line-height: 1.42857143; + text-decoration: none; + color: #337ab7; + background-color: #ffffff; + border: 1px solid #dddddd; + margin-left: -1px; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + color: #23527c; + background-color: #eeeeee; + border-color: #dddddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #ffffff; + background-color: #337ab7; + border-color: #337ab7; + cursor: default; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777777; + background-color: #ffffff; + border-color: #dddddd; + cursor: not-allowed; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + list-style: none; + text-align: center; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.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: #777777; + background-color: #ffffff; + cursor: not-allowed; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #ffffff; + line-height: 1; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + background-color: #777777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #ffffff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding: 30px 15px; + margin-bottom: 30px; + color: inherit; + background-color: #eeeeee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding: 48px 0; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: border 0.2s ease-in-out; + -o-transition: border 0.2s ease-in-out; + transition: border 0.2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-left: auto; + margin-right: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; + color: #3c763d; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + background-color: #d9edf7; + border-color: #bce8f1; + color: #31708f; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + background-color: #fcf8e3; + border-color: #faebcc; + color: #8a6d3b; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + background-color: #f2dede; + border-color: #ebccd1; + color: #a94442; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-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; + line-height: 20px; + color: #ffffff; + text-align: center; + background-color: #337ab7; + -webkit-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-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + 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: -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; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + 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: -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-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + 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: -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-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + 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: -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-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + 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: -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); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + zoom: 1; + overflow: hidden; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + margin-bottom: 20px; + padding-left: 0; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #dddddd; +} +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item { + color: #555555; +} +a.list-group-item .list-group-item-heading { + color: #333333; +} +a.list-group-item:hover, +a.list-group-item:focus { + text-decoration: none; + color: #555555; + background-color: #f5f5f5; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #eeeeee; + color: #777777; + cursor: not-allowed; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #dddddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-left: 15px; + padding-right: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #dddddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #dddddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #dddddd; +} +.panel-default { + border-color: #dddddd; +} +.panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #dddddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #dddddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #dddddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #ffffff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #ffffff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; +} +.embed-responsive.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-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-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + 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.5; + filter: alpha(opacity=50); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + -webkit-background-clip: padding-box; + background-clip: padding-box; + outline: 0; +} +.modal-backdrop { + position: absolute; + top: 0; + right: 0; + left: 0; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; + min-height: 16.42857143px; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + visibility: visible; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-weight: normal; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + 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-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + right: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + background-color: #ffffff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + white-space: normal; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.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 { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; +} +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-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 { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -o-transition: -o-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000; + perspective: 1000; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + left: 0; + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + left: 0; + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + left: 0; + } +} +.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: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +.carousel-control:hover, +.carousel-control:focus { + outline: 0; + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + line-height: 1; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #ffffff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); +} +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #ffffff; +} +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} diff --git a/src/static/movio/templates/Skeleton/less/libs/cms-bootstrap.less b/src/static/movio/templates/Skeleton/less/libs/cms-bootstrap.less new file mode 100755 index 0000000..be59b1e --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/libs/cms-bootstrap.less @@ -0,0 +1,4806 @@ +/*! + * Bootstrap v3.3.2 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! + * Generated using the Bootstrap Customizer (http://getbootstrap.com/customize/?id=5956842e5639d629b2e6) + * Config saved to config.json and https://gist.github.com/5956842e5639d629b2e6 + */ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + text-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]: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; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333333; + background-color: #ffffff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.42857143; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + background-color: #fcf8e3; + padding: .2em; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #dddddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #dddddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.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 > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + overflow-x: auto; + min-height: 0.01%; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #dddddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; + background-color: #ffffff; + background-image: none; + border: 1px solid #cccccc; + border-radius: 4px; + -webkit-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-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #999999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999999; +} +.form-control::-webkit-input-placeholder { + color: #999999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; + opacity: 1; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-left: 0; + padding-right: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.form-group-sm .form-control { + height: 30px; + line-height: 30px; +} +textarea.form-group-sm .form-control, +select[multiple].form-group-sm .form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.form-group-lg .form-control { + height: 46px; + line-height: 46px; +} +textarea.form-group-lg .form-control, +select[multiple].form-group-lg .form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 7px; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.333333px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333333; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default.focus, +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default .badge { + color: #ffffff; + background-color: #333333; +} +.btn-primary { + color: #ffffff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary.focus, +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success.focus, +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info.focus, +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning.focus, +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger.focus, +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #ffffff; +} +.btn-link { + color: #337ab7; + font-weight: normal; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; + visibility: hidden; +} +.collapse.in { + display: block; + visibility: visible; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + -o-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.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; + font-size: 14px; + text-align: left; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + -webkit-background-clip: padding-box; + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #337ab7; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px solid; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-bottom-left-radius: 4px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #cccccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} +.nav > li.disabled > a { + color: #777777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777777; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eeeeee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #dddddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #dddddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555555; + background-color: #ffffff; + border: 1px solid #dddddd; + border-bottom-color: transparent; + cursor: default; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #dddddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #dddddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #ffffff; + } +} +.tab-content > .tab-pane { + display: none; + visibility: hidden; +} +.tab-content > .active { + display: block; + visibility: visible; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + visibility: visible !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; + height: 50px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-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); + margin-top: 8px; + margin-bottom: 8px; +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777777; +} +.navbar-default .navbar-nav > li > a { + color: #777777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #dddddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #dddddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + background-color: #e7e7e7; + color: #555555; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777777; +} +.navbar-default .navbar-link:hover { + color: #333333; +} +.navbar-default .btn-link { + color: #777777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #cccccc; +} +.navbar-inverse { + background-color: #222222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + background-color: #080808; + color: #ffffff; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #ffffff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #ffffff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444444; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #ffffff; + line-height: 1; + vertical-align: baseline; + white-space: nowrap; + text-align: center; + background-color: #777777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #ffffff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.panel { + margin-bottom: 20px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #dddddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-left: 15px; + padding-right: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #dddddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #dddddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #dddddd; +} +.panel-default { + border-color: #dddddd; +} +.panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #dddddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #dddddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #dddddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #ffffff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #ffffff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + -webkit-background-clip: padding-box; + background-clip: padding-box; + outline: 0; +} +.modal-backdrop { + position: absolute; + top: 0; + right: 0; + left: 0; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; + min-height: 16.42857143px; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + visibility: visible; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-weight: normal; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + 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-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + right: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + background-color: #ffffff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + white-space: normal; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.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 { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #ffffff; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #ffffff; +} +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #ffffff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #ffffff; + bottom: -10px; +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} diff --git a/src/static/movio/templates/Skeleton/less/libs/cms-mixin.less b/src/static/movio/templates/Skeleton/less/libs/cms-mixin.less new file mode 100755 index 0000000..8fae4b7 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/libs/cms-mixin.less @@ -0,0 +1,48 @@ +.input-style (@width) { + background:@form-input-background; + border:0; + box-shadow:0; + color:@form-input-text; + width:@width; + padding:2px; + font-size:14px; + border:1px @solid @form-border; + height: 30px; + .border-radius(5px); + &.required { + border:2px solid @form-required; + } +} +.button-style (@width) { + .button(auto, @form-button); + border:0; +} +.button(@width, @background:@form-button) { + background:@background; + width:@width; + text-align:center; + color:@form-button-text; + line-height:1em; + height:30px; + display:inline-block; + padding:0 15px 0 15px; + font-size:14px; + line-height:30px; + text-decoration:none; + &:hover { + text-decoration:none; + } +} +.icon-font() { + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.grid(@col, @span, @margin) { + width: ((100% - (@margin * (@col - 1))) / @col * @span) + (@margin * (@span - 1)); + margin-right: @margin; +} \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/less/libs/mixin.less b/src/static/movio/templates/Skeleton/less/libs/mixin.less new file mode 100755 index 0000000..286c127 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/libs/mixin.less @@ -0,0 +1,38 @@ +.padding-margin-reset() { + padding:0; + margin:0; +} +.pmr(){margin:0;padding:0;} +.box-sizing() { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.border-radius (@radius) { + border-radius: @radius; + -moz-border-radius: @radius; + -webkit-border-radius: @radius; +} +.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #999) { + box-shadow: @arguments; + -moz-box-shadow: @arguments; + -webkit-box-shadow: @arguments; +} +/* font awesome icon */ +/* http://fortawesome.github.io/Font-Awesome/icons/ */ +/* for icon code: font-awesome/variables.less */ +.icon-font-awesome() { + font-family: 'FontAwesome'; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -moz-font-feature-settings: normal; + -moz-font-language-override: normal; + -moz-osx-font-smoothing: grayscale; + font-size: inherit; + font-size-adjust: none; + font-stretch: normal; + font-style: normal; + font-variant: normal; + font-weight: normal; + text-rendering: auto; +} \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/less/slick.less b/src/static/movio/templates/Skeleton/less/slick.less new file mode 100755 index 0000000..3a65267 --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/slick.less @@ -0,0 +1,132 @@ +/* slick */ +.slider { + margin-bottom:0; + } + + /* dots */ + .slick-dots { + + li.slick-active { + + button { + background-color:@slider-bullet-background-selected; + border:1px solid @slider-bullet-background; + } + + } + + li button { + width:12px; + height:12px; + padding:0; + .border-radius(100px); + background-color:@slider-bullet-background; + border:1px solid @slider-bullet-background; + + &:hover { + background:#E3001B; + } + + &:before { + display:none; + } + + } + } + + /* Arrows */ + + .slick-prev:before, .slick-next:before { + font-family: 'FontAwesome'; + content:@fa-var-caret-left; + color:@color-arrow-button-slider; + opacity:1; + font-size:25px; + font-weight:lighter; + + } + + .slick-disabled { + display:none!important; + } + + .slick-next:before { + content:@fa-var-caret-right; + margin-right:-3px; + color:@form-buttonPrimary-text; + } + + .slick-prev, .slick-next { + width:20px; + height:40px; + padding-top:4px; + top:50%; + margin-top:-23px; + border:0; + .border-radius(0); + background:@form-button-primary; + + + &:hover { + background:@form-button-primary; + + &:before { + color:@form-buttonPrimary-text; + } + } + + + } + + .slick-prev { + left:0; + } + + .slick-next { + right:0; + } + + .slideshow { + + .slick-prev, .slick-next { + width:20px; + height:40px; + padding-top:4px; + top:auto; + bottom: 0; + margin-bottom:15px; + border:0; + .border-radius(0); + background:none; + background:fade(@bg-desc-slider,80%); + border:1px solid @border-slider; + } + + .slick-prev { + margin-left:15px; + } + + .slick-next { + margin-left:40px; + left:0; + + + } + + .slick-prev:before, .slick-next:before { + font-family: 'FontAwesome'; + content:"\f053"; + color:@color-arrow-button-slider; + opacity:1; + font-weight:lighter; + color:@slider-text; + font-size:20px; + + } + + .slick-next:before { + content:"\f054"; + } + + } + diff --git a/src/static/movio/templates/Skeleton/less/styles.less b/src/static/movio/templates/Skeleton/less/styles.less new file mode 100755 index 0000000..4d7b48c --- /dev/null +++ b/src/static/movio/templates/Skeleton/less/styles.less @@ -0,0 +1,189 @@ +/** + * Import GENERIC required libraries +*/ +@import "libs/mixin.less"; +@import "font-awesome/font-awesome.less"; + +/* OPTIONAL: all bootstrap component */ +/*@import "libs/bootstrap.less";*/ + +/* DEFAULT: custom bootstrap component */ +/** + * Import CMS libraries + * + * Bootstrap custom build: + * Print media styles + * Typography + * Code + * Grid system + * Tables + * Forms + * Buttons + * Responsive utilities + * Button groups + * Input groups + * Navs + * Navbar + * Badges + * Panels + * Component animations (for JS) + * Dropdowns + * Tooltips + * Popovers + * Modals +*/ +@import "libs/cms-bootstrap.less"; +@import "libs/cms-mixin.less"; +@import "cms-global.less"; +@import "cms-layout.less"; +@import "cms-mobile.less"; +@import "cms-component.less"; + + +/** + * Import extra libraries +*/ +@import "slick.less"; + +@font-1: 'Arial', sans-serif; + +/*define colors */ +@white:#fff; +@black:#000; +@color1:#CCC; +@color2:#D8D8D8; +@color3:#F9F9F9; +@color4:#7A7A7A; +@color5:#C6C6C6; +@color6:#E4E4E4; +@color7:#F5F5F5; +@color8:#428BCA; +@color-success:green; +@color-error:red; +@solid:solid; + +/* extra color */ +@color9:#AE3433; +@color10:#fff; +@color11:#C4BDAC; +@color12:#F8F6F0; +@color13:#F0F0F0; +@color14:#333; +@color15:#48AE46; +@color16:#fff; + +/*define theme colors */ +@text: @black; +@text-heading: @black; +@color-link: @color8; +@color-link-hover: darken(@color8, 5); +@breadkcrumbs-link: @color-link; +@breadkcrumbs-link-hover: @color-link-hover; +@metanavigation-background:@color2; +@metanavigation-background-hover: @color1; +@metanavigation-link: @white; +@metanavigation-link-hover: @white; + +@metanavigation-link: @white; +@metanavigation-link-hover: @white; + +@slider-background:@color1; +@slider-text:@white; +@slider-bullet-background: @black; +@slider-bullet-background-selected: @color1; + +@sidebar-background: @color7; +@sidebar-background-hover: @color8; +@sidebar-border: @color4; +@sidebar-link: @color-link; +@sidebar-link-hover: @color-link-hover; + +@icon-in-page:lighten(@text, 70); +@icon-in-box:@white; +@icon-in-box-background:@color1; + +@box-image-border:@color1; +@box-background:@white; +@box-header-background:@white; +@box-border:@color1; +@box-header-link:@black; +@box-relation-item-border:@color1; +@box-text:@black; +@box-relation-item-background: @white; +@box-item-even-background:@color1; +@box-item-odd-background:lighten(@color1,10%); +@box-relation-item-link: @black; +@box-relation-item-link-hover: @color1; +@box-border-cart:@color1; + +@color-border-button:@color1; +@color-arrow-button-slider:@black; +@color-arrow-button-slider-hover:@color8; +@color-border-button:@color1; +@color-background-button:@white; + +@storyteller-background: @color6; +@storyteller-border: darken(@storyteller-background, 5); +@storyteller-icon: lighten(@text, 70); +@storyteller-border: @color2; +@storyteller-item-background: @color3; +@storyteller-comments-background: @color3; +@storyteller-link: @color8; +@storyteller-navigation-link: @color4; +@storyteller-image-border: @color5; + +@form-border: @color1; +@form-required: @color1; +@form-button: @color4; +@form-button-text: @white; +@form-button-primary: @color8; +@form-buttonPrimary-text:@white; +@form-button-primary-text:@form-buttonPrimary-text; +@form-input-text:@text; +@form-input-background:@white; + +@timeline-theme: @color8; + +@footer-background: @black; +@footer-border: @color1; +@footer-text: @white; +@footer-text-link: @color-link; + +/**************************/ +/* possible custom for theme */ +/**************************/ +@max-width:1200px; + +/* color selector */ +@color-menu-link:@color10; +@color-menu-link-hover:@color9; +@color-sub-menu-link:@color9; +@color-block-box-title:lighten(@color9,10%); +@color-cart-button:@white; +@color-link-top-bar:@metanavigation-link; +@color-link-attach:@white; +@color-link-attach-hover:@white; +@bg-link-attach:@color1; +@bg-link-attach-hover:#428bca; +@color-tag-attach:@white; +@color-tag-attach-hover:@color8; +@bg-tag-attach:@color8; +@bg-tag-attach-hover:@color1; +@bg-dl:#fafafa; +@bg-block-my-pop-up:#fafafa; + +/* bg */ +@bg-body:@color16; +@bg-top-bar:@color9; +@bg-outer:@color10; +@bg-header:@color16; +@bg-menu:@color1; +@bg-sub-menu:@color11; +@bg-desc-slider:darken(@color9,10%); +@bg-module-main-search:@color12; +@bg-button-add:@color15; +@bg-button-reset:@color1; +@bg-column:fade(@color1,20%); + +/* border */ +@border-slider:lighten(@color9,10%); diff --git a/src/static/movio/templates/Skeleton/page.php b/src/static/movio/templates/Skeleton/page.php new file mode 100644 index 0000000..8b99383 --- /dev/null +++ b/src/static/movio/templates/Skeleton/page.php @@ -0,0 +1,124 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title><?php print $docTitle?></title> + <!-- JQUERY LIB --> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> + <script>window.jQuery || document.write('<script src="js/jquery-1.8.2.min.js"><\/script>')</script> + <!-- JQUERY LIB --> + + <?php print $css?> + <link rel="stylesheet" type="text/css" href="../../../mediaelement/mediaelementplayer.css" charset="utf-8"> + <link rel="stylesheet" type="text/css" href="../../../js/slick/slick.css"> + <?php print $head?> +</head> + +<body> + <!-- outer --> + <div id="outer"> + + <!-- topbar --> + <div id="topbar" class="clearfix"> + <nav class="languages"> + <?php print $languages; ?> + </nav> + <nav class="metanavigation visible-tablet visible-desktop"> + <?php print $metanavigation; ?> + </nav> + <div class="dropdown pull-right"> + <button aria-expanded="true" data-toggle="dropdown" id="dropdownMenu1" type="button" class="btn btn-default dropdown-toggle"> + <i class="icon fa fa-user"></i> + </button> + <?php print $userMenu; ?> +</div> + <?php print $search; ?> + </div> + <!-- topbar --> + + <!-- content --> + <div class="clearfix container-fluid"> + + <!-- header --> + <header id="header" class="row-fluid clearfix"> + <div class="col-md-12 visible-tablet visible-desktop"> + <h1><?php print $siteTitle; ?></h1> + </div> + </header> + <!-- header --> + + <!-- content-box --> + <div class="content-box row-fluid clearfix"> + <!-- aside sx --> + <aside class="sx col-md-3"> + <nav class="menu"> + <?php print $navigation; ?> + </nav> + <?php print $leftSidebar; ?> + <?php print $leftSidebarAfter; ?> + <?php print $sharing; ?> + </aside> + <!-- aside sx --> + + <!-- main-content --> + <div class="main-content col-md-9"> + <?php if ($breadcrumbs) { ?> + <nav class="breadcrumb"> + <?php print $breadcrumbs; ?> + </nav> + <?php } ?> + <?php if ($pageTitle) { ?> + <div class="box-title clearfix"> + <?php print $pageTitle; ?> + <a href="javascript:window.print()" class="print-ico"><i class="fa fa-print fa fa-grey"></i></a> + </div> + <?php } ?> + <?php print $content; ?> + <?php print $afterContent; ?> + </div> + <!-- article --> + </div> + <!-- content-box --> + </div> + <!-- content --> + </div> + <!-- outer --> + + <!-- footer --> + <footer id="footer"> + <div class="clearfix"> + <div class="logo-footer"> + <a href="http://www.movio.beniculturali.it" title="Movio - Online Virual Exhibition"> + <img src="img/logo_movio.png" alt="Movio - Online Virual Exhibition" title="Movio - Online Virual Exhibition" width="109" height="44"> + </a> + <?php print $logoFooter; ?> + </div> + + <!-- box --> + <div class="box"> + <?php print $linkFooter; ?> + </div> + <!-- box --> + </div> + + <!-- info-page --> + <div id="info-page" class="visible-desktop"> + <div class="container-fluid"> + <p class="pull-left"><?php print $copyright;?></p> + <p class="pull-right"><?php print $docUpdate;?></p> + </div> + </div> + <!-- info-page --> + </footer> + <!-- footer --> + + <script src="js/bootstrap.min.js"></script> + <script src="js/main.js"></script> + <script src="../../js/movio.js"></script> + <script src="../../../mediaelement/mediaelement-and-player.js" type="text/javascript"></script> + <script src="../../../js/slick/slick.min.js"></script> +</body> +</html> \ No newline at end of file diff --git a/src/static/movio/templates/Skeleton/preview.jpg b/src/static/movio/templates/Skeleton/preview.jpg new file mode 100644 index 0000000000000000000000000000000000000000..06236bf8dd90f54fcd8f15439211540977d6256a GIT binary patch literal 21552 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 O8KcD5^E2@GyMF;br7o2K literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Skeleton/skins/HomeImageSlider.html b/src/static/movio/templates/Skeleton/skins/HomeImageSlider.html new file mode 100644 index 0000000..d600e56 --- /dev/null +++ b/src/static/movio/templates/Skeleton/skins/HomeImageSlider.html @@ -0,0 +1,25 @@ +<div class="slideshow big"> + <div class="slider single-item js-sliderhome"> + <div class="slide" tal:attributes="style php:Template::homeSliderImage(item)" tal:repeat="item Component"> + <div class="description"> + <h1><a tal:attributes="href item/pageId" tal:content="item/title"></a></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <a class="link-continue" tal:attributes="href item/pageId" tal:content="php: __T('read more')"></a> + </div> + </div> + </div> +</div> +<script> +$(function() { + $('.js-sliderhome').slick({ + dots: false, + autoplay: true, + arrows:true, + infinite: true, + speed: 700, + pauseOnDotsHover: true, + slidesToShow: 1, + slidesToScroll: 1 + }); +}); +</script> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/Template.php b/src/static/movio/templates/Sliding-windows/Template.php new file mode 100644 index 0000000..afe0e22 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/Template.php @@ -0,0 +1,175 @@ +<?php +class Template extends movio_views_AbstractLessTemplate +{ + function __construct() + { + $this->path = __DIR__; + $this->templateName = 'Sliding-windows'; + } + + protected function applyCssVariables(&$templateData, $less, $css) + { + $variables = array(); + foreach ($templateData as $k=>$v) { + if (strpos($k, 'c-')===0) { + if (strlen($v)==0) { + $v = 'transparent'; + } + else if (strlen($v)!=7) { + $v = '#000000'; + } + $variables[$k] = $v; + } + } + $less->setVariables($variables); + + if ($templateData->{'c-body-background'}) + { + $css .= <<<EOD +body { + background: @c-body-background; +} +EOD; + } + + $css .= <<<EOD + +@box-header-background: @c-box-header-background; +@text: @c-text; +@text-heading: @c-text-heading; +@color-link: @c-color-link; +@color-link-hover: darken(@c-color-link, 5); +@breadkcrumbs-link: @c-breadkcrumbs-link; +@breadkcrumbs-link-hover: @color-link-hover; + +@slider-background: @c-slider-background; +@slider-text: @c-slider-text; +@slider-bullet-background: @c-slider-bullet-background; +@slider-bullet-background-selected: @c-slider-background-selected; + +@sidebar-background: @c-sidebar-background; +@sidebar-background-hover: @c-sidebar-background-hover; +@sidebar-border: @c-sidebar-border; +@sidebar-link: @c-color-link; +@sidebar-link-hover: @c-color-link-hover; + +@icon-in-page: lighten(@c-text, 70); +@icon-in-box: @c-icon-in-box; +@icon-in-box-background: @c-icon-in-box-background; + +@box-image-border: @c-box-border; +@box-background: @c-box-background; +@box-border: @c-box-border; +@box-header-link: @c-box-header-link; +@box-relation-item-border: @c-box-border; +@box-text: @c-box-text; + +@color-border-button: @c-color-border-button; +@color-arrow-button-slider: @c-color-arrow-button-slider; +@color-arrow-button-slider-hover: @c-color-arrow-button-slider-hover; +@color-background-button: @c-color-background-button; + +@storyteller-background: @c-storyteller-background; +@storyteller-border: darken(@c-storyteller-background, 5); +@storyteller-icon: lighten(@c-text, 70); +@storyteller-border: @c-storyteller-border; +@storyteller-item-background: @c-storyteller-item-background; +@storyteller-comments-background: @c-storyteller-item-background; +@storyteller-link: @c-storyteller-link; +@storyteller-navigation-link: @c-storyteller-navigation-link; +@storyteller-image-border: @c-storyteller-image-border; + +@form-border: @c-form-border; +@form-required: @c-form-border; +@form-button: @c-form-button; +@form-button-text: @c-form-button-text; +@form-button-primary: @c-form-button-primary; +@form-button-primary-text: @c-form-button-text; +@form-input-text: @c-text; +@form-input-background:@c-form-input-background; + +@timeline-theme: @c-timeline-theme; + +@footer-background: @c-footer-background; +@footer-border:@c-footer-border; +@footer-text: @c-footer-text; +@footer-text-link: @c-color-link; +@background-info-page: @c-background-info-page; + +@color-link-menu: @c-color-link-menu; +@border-color-link: @c-border-color-link; +@border-sub-title-page: @c-border-sub-title-page; +@border-input-header: @c-border-input-header; +@color-link-enity: @c-color-link-entity; +@button-zoom-img: @c-button-zoom-img; +@box-sub-menu-background: @c-box-sub-menu-background; +@background-main-content: @c-background-main-content; + +EOD; + + return $css; + } + + + protected function applyFont(&$templateData, $css) + { + $font1 = $templateData->font1 == 'default' ? 'PT Sans' : $templateData->font1; + $font2 = $templateData->font2 == 'default' ? 'PT Serif' : $templateData->font2; + + $fonts = '@import url(http://fonts.googleapis.com/css?family='.str_replace(' ', '+', $font1).');'.PHP_EOL. + '@font-1: \''.$font1.'\', sans-serif;'.PHP_EOL. + '@import url(http://fonts.googleapis.com/css?family='.str_replace(' ', '+', $font2).');'.PHP_EOL. + '@font-2: \''.$font2.'\', sans-serif;'.PHP_EOL; + return $css.PHP_EOL.$fonts; + } + + + protected function addLogoCss(&$templateData, $css) + { + $templateData->headerLogo = @json_decode($templateData->headerLogo); + if ($templateData->headerLogo) { + $image = org_glizycms_mediaArchive_MediaManager::getMediaById($templateData->headerLogo->id); + $fileName = $image->getFileName(); + + $templateData->customCss .= <<<EOD +header .site-logo { + background: url("../{$fileName}") no-repeat ; +} +EOD; + } + + return $css; + } + + protected function addCustomCss(&$templateData, $css) + { + $css .= PHP_EOL.$templateData->customCss; + return $css; + } + + protected function addCustomOutput(&$view, &$templateData) + { + } + + public function fixTemplateData(&$templateData, &$newTemplateData) + { + $templateData->footerLogo = @json_decode($templateData->footerLogo); + if ($templateData->footerLogo && $templateData->footerLogo->id) { + $image = org_glizy_helpers_Media::getImageById($templateData->footerLogo->id); + if ($templateData->footerLogoLink) { + $image = __Link::formatLink($templateData->footerLogoLink, $templateData->footerLogoTitle, $image); + } + $newTemplateData->footerLogo = $image; + } + } + + protected function fixTemplateName($view) + { + $view->setAttribute('templateFileName', 'page.php'); + } + + + public static function homeSliderImage($item) { + return 'background:url('.$item->image['src'].') no-repeat 0 0;'; + } +} \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/Template.xml b/src/static/movio/templates/Sliding-windows/Template.xml new file mode 100644 index 0000000..bcfb2bb --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/Template.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:EmptyComponent + xmlns:m="movio.views.components.*" + xmlns:ms="movio.modules.sharingButtons.views.components.*"> + + + + <glz:Modifier target="navigation" attribute="editableRegion" value="menu" /> + <glz:Modifier target="navigation" attribute="drawAllChilds" value="true" /> + <glz:Modifier target="navigation" attribute="selectParent" value="true" /> + <glz:Modifier target="navigation" attribute="selectLink" value="false" /> + <glz:Modifier target="navigation" attribute="showOnlyChilds" value="true" reprocess="true"/> + + + <glz:ConfigValue key="movio.thumb.entityList.width" action="set" value="172" /> + <glz:ConfigValue key="movio.thumb.entityList.height" action="set" value="232" /> + <glz:ConfigValue key="movio.thumb.entityList.crop" action="set" value="true" /> + <glz:ConfigValue key="movio.thumb.homeSlider.width" action="set" value="1200" /> + <glz:ConfigValue key="movio.thumb.homeSlider.height" action="set" value="1000" /> + <glz:ConfigValue key="movio.thumb.homeSlider.crop" action="set" value="true" /> + +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/TemplateAdmin.xml b/src/static/movio/templates/Sliding-windows/TemplateAdmin.xml new file mode 100644 index 0000000..c87a84c --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/TemplateAdmin.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:EmptyComponent + xmlns:m="movio.views.components.*"> + +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/TemplateAdminGlobal.xml b/src/static/movio/templates/Sliding-windows/TemplateAdminGlobal.xml new file mode 100644 index 0000000..d26bf26 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/TemplateAdminGlobal.xml @@ -0,0 +1,162 @@ +<?xml version="1.0" encoding="utf-8"?> +<glz:EmptyComponent + xmlns:m="movio.views.components.*"> + + <glz:Fieldset label="{i18n:Header logo}"> + <glz:Image id="headerLogo" label="{i18n:Logo}" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Footer logo}"> + <glz:Image id="footerLogo" label="{i18n:Additional logo}" /> + <glz:Input id="footerLogoLink" label="{i18n:Logo link}" /> + <glz:Input id="footerLogoTitle" label="{i18n:Logo title}" /> + </glz:Fieldset> + + <glz:List id="font1" label="{i18n:Font primary}"> + <glz:ListItem key="default" value="{i18n:Default}" /> + <glz:ListItem key="Alegreya" value="Alegreya" /> + <glz:ListItem key="Cinzel" value="Cinzel" /> + <glz:ListItem key="Inconsolata" value="Inconsolata" /> + <glz:ListItem key="Jacques Francois" value="Jacques Francois" /> + <glz:ListItem key="Karla" value="Karla" /> + <glz:ListItem key="Lato" value="Lato" /> + <glz:ListItem key="Lora" value="Lora" /> + <glz:ListItem key="Libre Baskerville" value="Libre Baskerville" /> + <glz:ListItem key="Merriweather" value="Merriweather" /> + <glz:ListItem key="Montserrat" value="Montserrat" /> + <glz:ListItem key="Muli" value="Muli" /> + <glz:ListItem key="Neuton" value="Neuton" /> + <glz:ListItem key="Open Sans" value="Open Sans" /> + <glz:ListItem key="Oswald" value="Oswald" /> + <glz:ListItem key="Playfair Display" value="Playfair Display" /> + <glz:ListItem key="PT Sans" value="PT Sans" /> + <glz:ListItem key="Quattrocento Sans" value="Quattrocento Sans" /> + <glz:ListItem key="Raleway" value="Raleway" /> + <glz:ListItem key="Roboto" value="Roboto" /> + <glz:ListItem key="Roboto Slab" value="Roboto Slab" /> + <glz:ListItem key="Scada" value="Scada" /> + <glz:ListItem key="Titillium Web" value="Titillium Web" /> + </glz:List> + <glz:List id="font2" label="{i18n:Font secondary}"> + <glz:ListItem key="default" value="{i18n:Default}" /> + <glz:ListItem key="Alegreya" value="Alegreya" /> + <glz:ListItem key="Cinzel" value="Cinzel" /> + <glz:ListItem key="Inconsolata" value="Inconsolata" /> + <glz:ListItem key="Jacques Francois" value="Jacques Francois" /> + <glz:ListItem key="Karla" value="Karla" /> + <glz:ListItem key="Lato" value="Lato" /> + <glz:ListItem key="Lora" value="Lora" /> + <glz:ListItem key="Libre Baskerville" value="Libre Baskerville" /> + <glz:ListItem key="Merriweather" value="Merriweather" /> + <glz:ListItem key="Montserrat" value="Montserrat" /> + <glz:ListItem key="Muli" value="Muli" /> + <glz:ListItem key="Neuton" value="Neuton" /> + <glz:ListItem key="Open Sans" value="Open Sans" /> + <glz:ListItem key="Oswald" value="Oswald" /> + <glz:ListItem key="Playfair Display" value="Playfair Display" /> + <glz:ListItem key="PT Sans" value="PT Sans" /> + <glz:ListItem key="Quattrocento Sans" value="Quattrocento Sans" /> + <glz:ListItem key="Raleway" value="Raleway" /> + <glz:ListItem key="Roboto" value="Roboto" /> + <glz:ListItem key="Roboto Slab" value="Roboto Slab" /> + <glz:ListItem key="Scada" value="Scada" /> + <glz:ListItem key="Titillium Web" value="Titillium Web" /> + </glz:List> + + <glz:Fieldset label="{i18n:Colors}"> + <glz:List label="{i18n:Preset}" data="type=valuesPreset;elements=c-body-background,c-box-header-background,c-text,c-text-heading,c-color-link,c-breadkcrumbs-link,c-metanavigation-link,c-metanavigation-link-hover,c-slider-background,c-slider-text,c-slider-bullet-background,c-slider-bullet-background-selected,c-sidebar-background,c-sidebar-background-hover,c-sidebar-border,c-icon-in-box,c-icon-in-box-background,c-box-border,c-box-background,c-box-header-link,c-box-text,c-color-border-button,c-color-arrow-button-slider,c-color-arrow-button-slider-hover,c-color-background-button,c-storyteller-background,c-storyteller-border,c-storyteller-item-background,c-storyteller-link,c-storyteller-navigation-link,c-storyteller-image-border,c-form-border,c-form-button,c-form-button-text,c-form-button-primary,c-form-input-background,c-timeline-theme,c-footer-background,c-footer-border,c-footer-text,c-background-info-page,c-color-link-menu,c-border-color-link,c-border-sub-title-page,c-border-input-header,c-color-link-entity,c-button-zoom-img,c-box-sub-menu-background,c-background-main-content"> + <glz:ListItem value="-" key="" /> + <glz:ListItem value="{i18n:Preset 1}" key="0" options="#FFFFFF,#303447,#000000,#000000,#076A72,#000000,#FFFFFF,#FFFFFF,#CCCCCC,#FFFFFF,#000000,#CCCCCC,#F5F5F5,#076A72,#7A7A7A,#FFFFFF,#CCCCCC,#CCCCCC,#FFFFFF,#FFFFFF,#000000,#CCCCCC,#000000,#076A72,#FFFFFF,#E4E4E4,#D8D8D8,#F9F9F9,#076A72,#7A7A7A,#C6C6C6,#CCCCCC,#7A7A7A,#FFFFFF,#076A72,#FFFFFF,#076A72,#303447,#52979D,#FFFFFF,#076A72,#FFFFFF,#CC0000,#CCCCCC,#838591,#000000,#CC0000,#222431,#FFFFFF" /> + </glz:List> + + <glz:Fieldset label="{i18n:General}"> + <glz:Input id="c-body-background" label="{i18n:Background}" data="type=colorPicker" required="false" /> + <glz:Input id="c-box-header-background" label="{i18n:Background header}" data="type=colorPicker" required=" + false" /> + <glz:Input id="c-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-text-heading" label="{i18n:Heading}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-link" label="{i18n:Link}" data="type=colorPicker" required="true" /> + <glz:Input id="c-breadkcrumbs-link" label="{i18n:Link bread krumbs}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Navigation}"> + <glz:Input id="c-metanavigation-link" label="{i18n:Metanavigation link}" data="type=colorPicker" required="true" /> + <glz:Input id="c-metanavigation-link-hover" label="{i18n:Metanavigation link hover}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Slider}"> + <glz:Input id="c-slider-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-slider-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-slider-bullet-background" label="{i18n:Bullet background}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Sidebar}"> + <glz:Input id="c-sidebar-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-sidebar-background-hover" label="{i18n:Background hover}" data="type=colorPicker" required="true" /> + <glz:Input id="c-sidebar-border" label="{i18n:Border}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Icon}"> + <glz:Input id="c-icon-in-box" label="{i18n:Box}" data="type=colorPicker" required="true" /> + <glz:Input id="c-icon-in-box-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Box}"> + <glz:Input id="c-box-border" label="{i18n:Border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-header-link" label="{i18n:Link header}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Button}"> + <glz:Input id="c-color-border-button" label="{i18n:Border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-arrow-button-slider" label="{i18n:Arrow}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-arrow-button-slider-hover" label="{i18n:Arrow hover}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-background-button" label="{i18n:Background}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Storyteller}"> + <glz:Input id="c-storyteller-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-border" label="{i18n:Border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-item-background" label="{i18n:Item background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-background-button" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-link" label="{i18n:Link}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-navigation-link" label="{i18n:Navigation link}" data="type=colorPicker" required="true" /> + <glz:Input id="c-storyteller-image-border" label="{i18n:Image border}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Form}"> + <glz:Input id="c-form-border" label="{i18n:Border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-button" label="{i18n:Button}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-button-text" label="{i18n:Button text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-button-primary" label="{i18n:Button primary}" data="type=colorPicker" required="true" /> + <glz:Input id="c-form-input-background" label="{i18n:Input background}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Timelime}"> + <glz:Input id="c-timeline-theme" label="{i18n:Timeline theme}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Footer}"> + <glz:Input id="c-footer-background" label="{i18n:Background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-footer-border" label="{i18n:Border}" data="type=colorPicker" required="true" /> + <glz:Input id="c-footer-text" label="{i18n:Text}" data="type=colorPicker" required="true" /> + <glz:Input id="c-background-info-page" label="{i18n:Background metanavigation}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + <glz:Fieldset label="{i18n:Custom}"> + <glz:Input id="c-color-link-menu" label="{i18n:Link menu}" data="type=colorPicker" required="true" /> + <glz:Input id="c-border-color-link" label="{i18n:Border link}" data="type=colorPicker" required="true" /> + <glz:Input id="c-border-sub-title-page" label="{i18n:Border subtitle}" data="type=colorPicker" required="true" /> + <glz:Input id="c-border-input-header" label="{i18n:Border input header}" data="type=colorPicker" required="true" /> + <glz:Input id="c-color-link-entity" label="{i18n:Entity link}" data="type=colorPicker" required="true" /> + <glz:Input id="c-button-zoom-img" label="{i18n:Zoom button}" data="type=colorPicker" required="true" /> + <glz:Input id="c-box-sub-menu-background" label="{i18n:Sub menu background}" data="type=colorPicker" required="true" /> + <glz:Input id="c-background-main-content" label="{i18n:Main content background}" data="type=colorPicker" required="true" /> + </glz:Fieldset> + + </glz:Fieldset> + + + <glz:Input id="customCss" label="{i18n:Custom css}" size="90" type="multiline" rows="10" cols="70" /> +</glz:EmptyComponent> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/css/ie.css b/src/static/movio/templates/Sliding-windows/css/ie.css new file mode 100644 index 0000000..4ea3856 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/css/ie.css @@ -0,0 +1 @@ +.wrapper-galleria-io .content-galleria-io .galleria-info-text .galleria-info-title {margin-bottom:0 / ;} \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/css/jquery.mCustomScrollbar.css b/src/static/movio/templates/Sliding-windows/css/jquery.mCustomScrollbar.css new file mode 100644 index 0000000..5893e05 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/css/jquery.mCustomScrollbar.css @@ -0,0 +1,474 @@ +/* basic scrollbar styling */ +/* vertical scrollbar */ +.mCSB_container{ + width:auto; + margin-right:30px; + overflow:hidden; +} +.mCSB_container.mCS_no_scrollbar{ + margin-right:0; +} +.mCS_disabled>.mCustomScrollBox>.mCSB_container.mCS_no_scrollbar, +.mCS_destroyed>.mCustomScrollBox>.mCSB_container.mCS_no_scrollbar{ + margin-right:30px; +} +.mCustomScrollBox>.mCSB_scrollTools{ + width:16px; + height:100%; + top:0; + right:0; +} +.mCSB_scrollTools .mCSB_draggerContainer{ + position:absolute; + top:0; + left:0; + bottom:0; + right:0; + height:auto; +} +.mCSB_scrollTools a+.mCSB_draggerContainer{ + margin:20px 0; +} +.mCSB_scrollTools .mCSB_draggerRail{ + width:2px; + height:100%; + margin:0 auto; + -webkit-border-radius:10px; + -moz-border-radius:10px; + border-radius:10px; +} +.mCSB_scrollTools .mCSB_dragger{ + cursor:pointer; + width:100%; + height:30px; +} +.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:4px; + height:100%; + margin:0 auto; + -webkit-border-radius:10px; + -moz-border-radius:10px; + border-radius:10px; + text-align:center; +} +.mCSB_scrollTools .mCSB_buttonUp, +.mCSB_scrollTools .mCSB_buttonDown{ + display:block; + position:relative; + height:20px; + overflow:hidden; + margin:0 auto; + cursor:pointer; +} +.mCSB_scrollTools .mCSB_buttonDown{ + top:100%; + margin-top:-40px; +} +/* horizontal scrollbar */ +.mCSB_horizontal>.mCSB_container{ + height:auto; + margin-right:0; + margin-bottom:30px; + overflow:hidden; +} +.mCSB_horizontal>.mCSB_container.mCS_no_scrollbar{ + margin-bottom:0; +} +.mCS_disabled>.mCSB_horizontal>.mCSB_container.mCS_no_scrollbar, +.mCS_destroyed>.mCSB_horizontal>.mCSB_container.mCS_no_scrollbar{ + margin-right:0; + margin-bottom:30px; +} +.mCSB_horizontal.mCustomScrollBox>.mCSB_scrollTools{ + width:100%; + height:16px; + top:auto; + right:auto; + bottom:0; + left:0; + overflow:hidden; +} +.mCSB_horizontal>.mCSB_scrollTools a+.mCSB_draggerContainer{ + margin:0 20px; +} +.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{ + width:100%; + height:2px; + margin:7px 0; + -webkit-border-radius:10px; + -moz-border-radius:10px; + border-radius:10px; +} +.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger{ + width:30px; + height:100%; +} +.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:100%; + height:4px; + margin:6px auto; + -webkit-border-radius:10px; + -moz-border-radius:10px; + border-radius:10px; +} +.mCSB_horizontal>.mCSB_scrollTools .mCSB_buttonLeft, +.mCSB_horizontal>.mCSB_scrollTools .mCSB_buttonRight{ + display:block; + position:relative; + width:20px; + height:100%; + overflow:hidden; + margin:0 auto; + cursor:pointer; + float:left; +} +.mCSB_horizontal>.mCSB_scrollTools .mCSB_buttonRight{ + margin-left:-40px; + float:right; +} +.mCustomScrollBox{ + -ms-touch-action:none; /*MSPointer events - direct all pointer events to js*/ +} + +/* default scrollbar colors and backgrounds (default theme) */ +.mCustomScrollBox>.mCSB_scrollTools{ + opacity:0.75; + filter:"alpha(opacity=75)"; -ms-filter:"alpha(opacity=75)"; /* old ie */ +} +.mCustomScrollBox:hover>.mCSB_scrollTools{ + opacity:1; + filter:"alpha(opacity=100)"; -ms-filter:"alpha(opacity=100)"; /* old ie */ +} +.mCSB_scrollTools .mCSB_draggerRail{ + background:#000; /* rgba fallback */ + background:rgba(0,0,0,0.4); + filter:"alpha(opacity=40)"; -ms-filter:"alpha(opacity=40)"; /* old ie */ +} +.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background:#fff; /* rgba fallback */ + background:rgba(255,255,255,0.75); + filter:"alpha(opacity=75)"; -ms-filter:"alpha(opacity=75)"; /* old ie */ +} +.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ + background:rgba(255,255,255,0.85); + filter:"alpha(opacity=85)"; -ms-filter:"alpha(opacity=85)"; /* old ie */ +} +.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, +.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background:rgba(255,255,255,0.9); + filter:"alpha(opacity=90)"; -ms-filter:"alpha(opacity=90)"; /* old ie */ +} +.mCSB_scrollTools .mCSB_buttonUp, +.mCSB_scrollTools .mCSB_buttonDown, +.mCSB_scrollTools .mCSB_buttonLeft, +.mCSB_scrollTools .mCSB_buttonRight{ + background-image:url(mCSB_buttons.png); + background-repeat:no-repeat; + opacity:0.4; + filter:"alpha(opacity=40)"; -ms-filter:"alpha(opacity=40)"; /* old ie */ +} +.mCSB_scrollTools .mCSB_buttonUp{ + background-position:0 0; + /* + sprites locations are 0 0/-16px 0/-32px 0/-48px 0 (light) and -80px 0/-96px 0/-112px 0/-128px 0 (dark) + */ +} +.mCSB_scrollTools .mCSB_buttonDown{ + background-position:0 -20px; + /* + sprites locations are 0 -20px/-16px -20px/-32px -20px/-48px -20px (light) and -80px -20px/-96px -20px/-112px -20px/-128px -20px (dark) + */ +} +.mCSB_scrollTools .mCSB_buttonLeft{ + background-position:0 -40px; + /* + sprites locations are 0 -40px/-20px -40px/-40px -40px/-60px -40px (light) and -80px -40px/-100px -40px/-120px -40px/-140px -40px (dark) + */ +} +.mCSB_scrollTools .mCSB_buttonRight{ + background-position:0 -56px; + /* + sprites locations are 0 -56px/-20px -56px/-40px -56px/-60px -56px (light) and -80px -56px/-100px -56px/-120px -56px/-140px -56px (dark) + */ +} +.mCSB_scrollTools .mCSB_buttonUp:hover, +.mCSB_scrollTools .mCSB_buttonDown:hover, +.mCSB_scrollTools .mCSB_buttonLeft:hover, +.mCSB_scrollTools .mCSB_buttonRight:hover{ + opacity:0.75; + filter:"alpha(opacity=75)"; -ms-filter:"alpha(opacity=75)"; /* old ie */ +} +.mCSB_scrollTools .mCSB_buttonUp:active, +.mCSB_scrollTools .mCSB_buttonDown:active, +.mCSB_scrollTools .mCSB_buttonLeft:active, +.mCSB_scrollTools .mCSB_buttonRight:active{ + opacity:0.9; + filter:"alpha(opacity=90)"; -ms-filter:"alpha(opacity=90)"; /* old ie */ +} + +/*scrollbar themes*/ +/*dark (dark colored scrollbar)*/ +.mCS-dark>.mCSB_scrollTools .mCSB_draggerRail{ + background:#000; /* rgba fallback */ + background:rgba(0,0,0,0.15); +} +.mCS-dark>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + background:#000; /* rgba fallback */ + background:rgba(0,0,0,0.75); +} +.mCS-dark>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ + background:rgba(0,0,0,0.85); +} +.mCS-dark>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, +.mCS-dark>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background:rgba(0,0,0,0.9); +} +.mCS-dark>.mCSB_scrollTools .mCSB_buttonUp{ + background-position:-80px 0; +} +.mCS-dark>.mCSB_scrollTools .mCSB_buttonDown{ + background-position:-80px -20px; +} +.mCS-dark>.mCSB_scrollTools .mCSB_buttonLeft{ + background-position:-80px -40px; +} +.mCS-dark>.mCSB_scrollTools .mCSB_buttonRight{ + background-position:-80px -56px; +} +/*light-2*/ +.mCS-light-2>.mCSB_scrollTools .mCSB_draggerRail{ + width:4px; + background:#fff; /* rgba fallback */ + background:rgba(255,255,255,0.1); + -webkit-border-radius:1px; + -moz-border-radius:1px; + border-radius:1px; +} +.mCS-light-2>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:4px; + background:#fff; /* rgba fallback */ + background:rgba(255,255,255,0.75); + -webkit-border-radius:1px; + -moz-border-radius:1px; + border-radius:1px; +} +.mCS-light-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{ + width:100%; + height:4px; + margin:6px 0; +} +.mCS-light-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:100%; + height:4px; + margin:6px auto; +} +.mCS-light-2>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ + background:rgba(255,255,255,0.85); +} +.mCS-light-2>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, +.mCS-light-2>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background:rgba(255,255,255,0.9); +} +.mCS-light-2>.mCSB_scrollTools .mCSB_buttonUp{ + background-position:-32px 0; +} +.mCS-light-2>.mCSB_scrollTools .mCSB_buttonDown{ + background-position:-32px -20px; +} +.mCS-light-2>.mCSB_scrollTools .mCSB_buttonLeft{ + background-position:-40px -40px; +} +.mCS-light-2>.mCSB_scrollTools .mCSB_buttonRight{ + background-position:-40px -56px; +} +/*dark-2*/ +.mCS-dark-2>.mCSB_scrollTools .mCSB_draggerRail{ + width:4px; + background:#000; /* rgba fallback */ + background:rgba(0,0,0,0.1); + -webkit-border-radius:1px; + -moz-border-radius:1px; + border-radius:1px; +} +.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:4px; + background:#000; /* rgba fallback */ + background:rgba(0,0,0,0.75); + -webkit-border-radius:1px; + -moz-border-radius:1px; + border-radius:1px; +} +.mCS-dark-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{ + width:100%; + height:4px; + margin:6px 0; +} +.mCS-dark-2.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:100%; + height:4px; + margin:6px auto; +} +.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ + background:rgba(0,0,0,0.85); +} +.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, +.mCS-dark-2>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background:rgba(0,0,0,0.9); +} +.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonUp{ + background-position:-112px 0; +} +.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonDown{ + background-position:-112px -20px; +} +.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonLeft{ + background-position:-120px -40px; +} +.mCS-dark-2>.mCSB_scrollTools .mCSB_buttonRight{ + background-position:-120px -56px; +} +/*light-thick*/ +.mCS-light-thick>.mCSB_scrollTools .mCSB_draggerRail{ + width:4px; + background:#fff; /* rgba fallback */ + background:rgba(255,255,255,0.1); + -webkit-border-radius:2px; + -moz-border-radius:2px; + border-radius:2px; +} +.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:6px; + background:#fff; /* rgba fallback */ + background:rgba(255,255,255,0.75); + -webkit-border-radius:2px; + -moz-border-radius:2px; + border-radius:2px; +} +.mCS-light-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{ + width:100%; + height:4px; + margin:6px 0; +} +.mCS-light-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:100%; + height:6px; + margin:5px auto; +} +.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ + background:rgba(255,255,255,0.85); +} +.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, +.mCS-light-thick>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background:rgba(255,255,255,0.9); +} +.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonUp{ + background-position:-16px 0; +} +.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonDown{ + background-position:-16px -20px; +} +.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonLeft{ + background-position:-20px -40px; +} +.mCS-light-thick>.mCSB_scrollTools .mCSB_buttonRight{ + background-position:-20px -56px; +} +/*dark-thick*/ +.mCS-dark-thick>.mCSB_scrollTools .mCSB_draggerRail{ + width:4px; + background:#000; /* rgba fallback */ + background:rgba(0,0,0,0.1); + -webkit-border-radius:2px; + -moz-border-radius:2px; + border-radius:2px; +} +.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:6px; + background:#000; /* rgba fallback */ + background:rgba(0,0,0,0.75); + -webkit-border-radius:2px; + -moz-border-radius:2px; + border-radius:2px; +} +.mCS-dark-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{ + width:100%; + height:4px; + margin:6px 0; +} +.mCS-dark-thick.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:100%; + height:6px; + margin:5px auto; +} +.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ + background:rgba(0,0,0,0.85); +} +.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, +.mCS-dark-thick>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background:rgba(0,0,0,0.9); +} +.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonUp{ + background-position:-96px 0; +} +.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonDown{ + background-position:-96px -20px; +} +.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonLeft{ + background-position:-100px -40px; +} +.mCS-dark-thick>.mCSB_scrollTools .mCSB_buttonRight{ + background-position:-100px -56px; +} +/*light-thin*/ +.mCS-light-thin>.mCSB_scrollTools .mCSB_draggerRail{ + background:#fff; /* rgba fallback */ + background:rgba(255,255,255,0.1); +} +.mCS-light-thin>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:2px; +} +.mCS-light-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{ + width:100%; +} +.mCS-light-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:100%; + height:2px; + margin:7px auto; +} +/*dark-thin*/ +.mCS-dark-thin>.mCSB_scrollTools .mCSB_draggerRail{ + background:#000; /* rgba fallback */ + background:rgba(0,0,0,0.15); +} +.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:2px; + background:#000; /* rgba fallback */ + background:rgba(0,0,0,0.75); +} +.mCS-dark-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_draggerRail{ + width:100%; +} +.mCS-dark-thin.mCSB_horizontal>.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar{ + width:100%; + height:2px; + margin:7px auto; +} +.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger:hover .mCSB_dragger_bar{ + background:rgba(0,0,0,0.85); +} +.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger:active .mCSB_dragger_bar, +.mCS-dark-thin>.mCSB_scrollTools .mCSB_dragger.mCSB_dragger_onDrag .mCSB_dragger_bar{ + background:rgba(0,0,0,0.9); +} +.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonUp{ + background-position:-80px 0; +} +.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonDown{ + background-position:-80px -20px; +} +.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonLeft{ + background-position:-80px -40px; +} +.mCS-dark-thin>.mCSB_scrollTools .mCSB_buttonRight{ + background-position:-80px -56px; +} \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/css/styles.css b/src/static/movio/templates/Sliding-windows/css/styles.css new file mode 100644 index 0000000..2d6f98e --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/css/styles.css @@ -0,0 +1,8 @@ +/*! + * Bootstrap v3.1.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none !important;color:#000 !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) ")"}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}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff !important}.navbar{display:none}.table td,.table th{background-color:#fff !important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important}.label{border:1px solid #000}.table{border-collapse:collapse !important}.table-bordered th,.table-bordered td{border:1px solid #ddd !important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.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>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.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 col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-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-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}input[type="date"]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.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;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.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;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*="col-"]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.nav:before,.nav:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.nav:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important;visibility:hidden !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}@media print{.hidden-print{display:none !important}}/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts/fontawesome-webfont.eot?v=4.0.3');src:url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'),url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'),url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'),url('//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857142858em;text-align:center}.fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}body{background-color:#fff;font-family:'PT Sans',sans-serif;font-size:15px;font-weight:normal;overflow:hidden}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}h1,h2,h3,h4,h5,h6{color:#333}a{color:#076a72}a:hover{color:#06545a}dt{float:left;font-weight:bold;padding-right:10px}dd{margin-left:0}dl.small dt{width:70px}dl.small dd{margin-left:70px}dl.medium dt{width:170px}dl.medium dd{margin-left:170px}dl.large dt{width:250px}dl.large dd{margin-left:250px}.main-content h1{padding:0;margin:0}.main-content h2{padding:0;margin:0;margin-bottom:15px}.main-content .print-ico{float:right}.main-content p{line-height:1.6em;padding-bottom:15px}img{max-width:100%;border:0}img.thumb,img.left,img.right,img.center{float:left;margin:.5em;padding:5px;border:1px solid #ccc}img.left{margin-left:0}img.right{margin-right:0;clear:right;float:right}img.center{clear:both;float:none;margin:auto;display:block}img.noBorder{border:0;padding:0}input[type="text"],input[type="password"],input[type="email"]{background:#fff;border:0;box-shadow:0;color:#333;width:100%;padding:2px;font-size:14px;border:1px solid #ccc;height:30px;border-radius:0;-moz-border-radius:0;-webkit-border-radius:0}input[type="text"].required,input[type="password"].required,input[type="email"].required{border:2px solid #ccc}input[type="text"].input-large,input[type="password"].input-large,input[type="email"].input-large{width:450px}input[type="text"].input-small,input[type="password"].input-small,input[type="email"].input-small{width:160px}label.required:after{content:" *"}select{width:auto}select.select-large{width:450px}select.select-small{width:160px}select.select-medium{width:260px}input[type="submit"],button,input[type="button"],input[type="reset"]{background:#7a7a7a;width:auto;text-align:center;color:#fff;line-height:1em;height:30px;display:inline-block;padding:0 15px 0 15px;font-size:14px;line-height:30px;text-decoration:none;border:0}input[type="submit"]:hover,button:hover,input[type="button"]:hover,input[type="reset"]:hover{text-decoration:none}input[type="submit"]{background:#076a72;color:#fff}textarea{border:1px solid #ccc;width:100%;padding:4px;height:150px}textarea.textarea-large{width:450px}.my-form.no-border-row .control-group{border:0}.my-form .control-group{padding-bottom:10px}.my-form .controls{margin-left:0}.my-form .controls.with-button input[type="submit"],.my-form .controls.with-button input[type="button"],.my-form .controls.with-button input[type="reset"],.my-form .controls.with-button button{margin-top:0;margin-left:5px}.my-form.form-horizontal .control-group{clear:both;margin-bottom:15px;padding-bottom:15px;border-bottom:1px solid #ccc}.my-form.form-horizontal .control-group label{display:inline-block;width:160px}.my-form.form-horizontal .control-group .controls{display:inline-block}.clearfix-left{clear:left}.clearfix-right{clear:right}.align-center{text-align:center !important}.align-right{text-align:right !important}.first-box{margin-left:0 !important}.error{color:#f00}.ok{color:#008000}.ico-box{display:block;position:absolute;width:30px !important;height:30px !important;top:0;right:0;margin-right:10px;background:#ccc;color:#fff;text-align:center;padding-top:7px;font-size:15px}.ico-box.icon-film{padding-left:5px}.icon-grey{color:#e5e5e5;font-size:20px}span.superzoom{background:#c00;color:#fff;padding:0 0;position:absolute;width:30px;height:30px;cursor:pointer;border-radius:0;-moz-border-radius:0;-webkit-border-radius:0;text-align:center;padding:2px 0 0 0;line-height:30px}.col-md-3,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{padding:0}#outer .mCustomScrollBox .mCSB_draggerContainer .mCSB_dragger_bar{background-color:#000;border-radius:0;-moz-border-radius:0;-webkit-border-radius:0;width:5px;margin-left:6px}#outer .mCustomScrollBox .mCSB_draggerContainer .mCSB_draggerRail{width:1px;background:#000}.container-fluid{padding:0}.content-box{min-height:290px;position:relative}.navbar-toggle,.show-nav-for-iphone,.show-footer-nav-for-iphone{display:none}#outer{width:100%;max-width:100%;margin:0 auto;position:relative}#topbar{font-size:14px;height:30px;padding-top:10px;padding-left:10px;padding-right:10px;background:#303447;position:relative;width:100%;max-width:380px;position:fixed;top:0;right:0;z-index:6}#topbar a{color:#fff}header{padding:0 0;background:#303447;border-bottom:1px solid #ccc;position:fixed;top:0;z-index:4;width:100%;height:73px;overflow:hidden}header .col-md-12{padding:0;margin:0;padding:5px}header h1,header h2{padding:0;margin:0}header .site-logo{background:url(../img/logo.png) 0 0 no-repeat;float:left;text-indent:-9999px;display:block;width:269px;height:62px}header .site-logo a{display:block}.main-content{padding-left:15px;padding-right:15px;position:absolute;top:0;margin:72px 0 90px 0;z-index:1;overflow:auto;overflow-x:hidden}footer{width:100%;max-width:100%;clear:both;position:fixed;bottom:0;z-index:4;height:90px;background:#303447}footer .box{float:left;padding:15px 15px;border:0;width:20%}footer .box p{font-size:12px;color:#fff}footer .box h2{padding:0;margin:0;line-height:1em;font-size:16px;color:#fff}footer .box ul{padding:0;margin:0;padding-top:10px}footer .box ul li{list-style:none}footer .box ul li a,footer .box ul li a:hover,footer .box ul li a:link{color:#076a72}footer .logo-footer{float:right;padding:0;border:0;margin-top:10px;margin-right:15px}footer #info-page{padding:0 10px;color:#fff;height:30px;background:#076a72}footer #info-page nav ul{padding:0;margin:0;padding-left:5px}footer #info-page nav ul li{display:inline}footer #info-page nav ul li a{color:#fff;text-transform:uppercase;display:inline-block;border-right:1px solid #52979d;float:left;padding-right:12px;margin:0 15px 0 0;padding-top:8px;font-size:11px;height:20px}footer #info-page p{font-size:11px;padding-top:0;line-height:30px;text-align:right}.sx{float:left}.sx nav{margin:0}.sx #nav-collapse{padding:0;margin:0}@media (min-width:979px){header .collapse,footer .collapse,.sx .collapse{display:block;height:auto !important}}.languages{text-transform:uppercase;position:absolute;top:0;right:0;margin-right:10px}.languages ul{padding:0;margin:0}.languages ul li{display:inline}.languages ul li a{font-size:12px;display:inline-block;margin:0;text-decoration:none;border-top:5px solid #303447;width:25px;padding-top:3px;text-align:center}.languages ul li a:hover,.languages ul li a.active{border-top:5px solid #c00}.metanavigation{margin-left:20px;float:left;margin-top:5px}.metanavigation ul{padding:0;margin:0}.metanavigation ul li{display:inline;padding:0 0 0 4px}.metanavigation ul li a{display:inline-block;margin-right:6px}.metanavigation ul li a.active{text-decoration:underline}.menu{padding:0 0;position:absolute;bottom:0;right:0;margin-bottom:5px}.menu ul{padding:0;margin:0;margin-right:-15px}.menu ul li{list-style:none;display:inline-block;float:left}.menu ul li.jqx-menu-item-top-selected a{color:#fff;text-decoration:none;border-bottom:5px solid #222431;background:#222431}.menu ul li a{color:#fff;font-size:12px;text-transform:uppercase;margin-right:25px;display:inline-block;padding:5px 8px 0 8px;line-height:1em;border-bottom:5px solid #303447}.menu ul li a:hover{color:#fff;text-decoration:none;border-bottom:5px solid #222431;background:#222431}.menu ul li a.active{color:#fff;text-decoration:none;border-bottom:5px solid #c00}.jqx-menu-dropdown{padding:0;margin:0;width:174px;background:#222431}.jqx-menu-dropdown .jqx-item .jqx-icon-arrow-right{width:0 !important;height:0 !important;border-top:5px solid transparent !important;border-bottom:5px solid transparent !important;border-left:5px solid #fff !important;margin-right:5px !important;margin-left:5px !important}.jqx-menu-dropdown a{color:#fff;line-height:1.2em;padding:8px 8px;border-bottom:1px solid #303447;display:block;font-size:12px;text-transform:uppercase}.jqx-menu-dropdown a:hover{background:#c00;text-decoration:none}.breadcrumb{margin:5px 0 15px 0;font-size:13px}.breadcrumb ul{padding:0;margin:0}.breadcrumb ul li{display:inline;font-style:italic}.breadcrumb ul li:first-child{font-style:normal}.breadcrumb ul li a{color:#333}.breadcrumb ul li a:hover{color:#06545a;text-decoration:none}.pagination{width:100%}.pagination ul{padding:0;width:100%;min-height:29px;text-align:center}.pagination ul li{display:inline}.pagination ul li a{border:0;background:none;float:none;color:#333;display:inline-block;padding-top:0;margin-top:7px;padding-bottom:0;line-height:1em;font-size:14px;outline:none;padding:0 5px 0 5px;border-left:1px solid #ccc}.pagination ul li a:hover{text-decoration:underline}.pagination ul li.active a{text-decoration:underline}.pagination ul li:first-child>a{border:0;padding-left:17px}.pagination ul li:last-child>a{padding-right:17px}form.top-search{position:absolute;top:0;right:0;margin:10px 80px 0 0}form.top-search p{padding:0;margin:0}form.top-search p label,form.top-search p input{display:inline-block;float:left}form.top-search p label{padding:4px 8px 0 0;color:#fff;display:none}form.top-search p input[type="text"]{width:290px;height:20px;border:1px solid #838591;background:transparent;color:#fff;font-size:12px}form.top-search p ::-webkit-input-placeholder{text-transform:uppercase;color:#fff}form.top-search p :-moz-placeholder{text-transform:uppercase;color:#fff}form.top-search p ::-moz-placeholder{text-transform:uppercase;color:#fff}form.top-search p :-ms-input-placeholder{text-transform:uppercase;color:#fff}form.top-search p input[type="submit"]{display:none}.box-title{padding-bottom:10px;margin-bottom:30px}.box-title h1,.box-title h2{padding:0;margin:0;font-family:'PT Serif',serif}.box-title h1{font-size:33px;padding-bottom:6px}.box-title h2{font-size:20px;font-style:italic;border-top:1px solid #ccc;padding-top:6px}.box{position:relative}.box h1{padding:0;margin:0;font-size:20px;line-height:2.5em}.box .container{padding:0;margin:0;position:relative;width:auto}.box img{margin-bottom:10px}.box p{word-break:break-strict}.box .show-content-box{position:absolute;width:21px;height:21px;display:block;text-indent:-9999px;cursor:pointer;top:0;margin-top:1px;margin-left:4px;border-radius:0;-moz-border-radius:0;-webkit-border-radius:0;box-shadow:none;background:#fff}.box .show-content-box:after{top:50%;margin-top:-2px;content:" ";height:0;width:0;position:absolute;pointer-events:none;border:solid transparent;border-top-color:#333;border-width:8px;left:50%;margin-left:-8px}.box .show-content-box:hover:after{border-top-color:#076a72}.box .show-content-box.collapsed:after{top:50%;margin-top:-10px;content:" ";height:0;width:0;position:absolute;pointer-events:none;border:solid transparent;border-color:transparent;border-bottom-color:#333;border-width:6px;left:50%;margin-left:-6px}.box .show-content-box.collapsed:hover:after{border-bottom-color:#076a72}.slideshow{height:100%;position:absolute;background-color:#ccc;z-index:2;width:100%;padding:0;margin:0;margin-left:-15px;margin-right:-15px}.slideshow .slide{background-size:cover !important;background-position:top center !important;position:relative}.slideshow .description{width:509px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin-left:0;height:212px;overflow:hidden;position:absolute;top:50%;left:50%;margin:-106px 0 0 -254px;background:url(../img/bg/bg-opacity.png) repeat;padding:20px}.slideshow .description h1{font-family:'PT Serif',serif;font-size:30px;font-style:italic;text-align:center;padding-bottom:20px}.slideshow .description h1 a{color:#fff;text-decoration:none}.slideshow .description p{font-family:'PT Serif',serif;color:#fff;line-height:1em;font-size:40px;display:block;margin:0 auto;width:357px;padding-top:20px;text-align:center;border-top:1px solid #fff}.slideshow .description a.link-continue{display:block;position:absolute;width:100%;height:100%;top:0;left:0;text-indent:-9999px}figure.main-img{padding:0;position:relative;padding:0 15px 10px 0;margin:0;max-width:auto;margin-bottom:15px}figure.main-img img{padding:5px;border:1px solid #ccc;float:left;margin-bottom:8px}figure.main-img .description{font-size:95%;line-height:1.2em;padding:0;margin:0;position:relative;bottom:0;float:left;clear:left;width:auto;padding-right:10px;word-wrap:break-word}figure.main-img .description strong{display:block}figure.main-img .superzoom{bottom:0;margin-left:6px;margin-bottom:41px;left:0;position:absolute}figure.main-img.align-left{float:left;margin-right:20px;padding-right:0}figure.main-img.align-right{float:right;margin-left:20px;padding-right:0}figure.main-img.align-right img{float:right}figure.main-img.align-right .description{float:right;text-align:right;clear:right;padding-left:10px;padding-right:0}@media (max-width:480px){figure.main-img{margin:0 0 15px 0;width:288px}}.results-content .slick-next{margin-right:-15px}.results-content .item{border-bottom:1px solid #ccc;padding-bottom:15px;margin-bottom:15px;text-align:center}.results-content .item figure{width:135px;height:135px;float:left;margin:0 15px 0 0}.results-content .item h1{font-size:18px;padding:0;margin:0;font-family:'PT Serif',serif;line-height:1em;margin-bottom:5px;text-align:left}.results-content .item h1 a{text-decoration:none}.results-content .item h1 a:hover{text-decoration:underline}.results-content .item p{font-size:14px;line-height:18px;padding:0;margin:0;text-align:left}.results-content .item.in-grid{border:1px solid #ccc;padding:15px;min-height:165px;margin-right:1.777777%;width:21.33333333%;min-height:360px;background:#fff}.results-content .item.in-grid.slide{width:auto;float:left;margin-right:20px}.results-content .item.in-grid.slide.fix-width{width:240px;margin-right:20px !important;margin-left:20px !important}.results-content .item.in-grid img{margin-bottom:15px;display:block;margin-left:auto;margin-right:auto}.results-content .item.in-grid h2{font-size:20px;line-height:1em;padding:0;margin:0;margin:0 0;padding:10px 0;border-top:1px solid #ccc;border-bottom:1px solid #ccc}.results-content .item.in-grid h2 a{color:#333}.results-content .item.in-grid figure{width:auto;height:auto;float:none;display:block;margin:0 auto}.results-content .item.in-grid figure img{float:none}.relationImage{box-shadow:0 0 4px #999;-moz-box-shadow:0 0 4px #999;-webkit-box-shadow:0 0 4px #999;border:1px solid #ccc;margin-bottom:10px;overflow:hidden}.relationImage .container{height:100px;padding-top:12px}.relationImage h1{font-size:14px;font-family:'PT Sans',sans-serif;padding:0;margin:0;height:24px;line-height:1em;border-bottom:1px solid #ccc;color:#333;padding-top:5px;padding-left:35px}.relationImage h1 a{color:#333;text-decoration:none}.relationImage .slider{padding-left:15px;padding-right:15px;height:auto;height:77px}.relationImage .slide{text-align:center;margin-right:10px;padding-bottom:0}.relationImage .slide img{display:block;margin:0 auto}.relationGeneral{box-shadow:0 0 4px #999;-moz-box-shadow:0 0 4px #999;-webkit-box-shadow:0 0 4px #999;border:1px solid #ccc;margin-bottom:10px;overflow:hidden}.relationGeneral .container{height:415px;padding-top:12px}.relationGeneral h1{font-size:14px;font-family:'PT Sans',sans-serif;padding:0;margin:0;height:24px;line-height:1em;border-bottom:1px solid #ccc;color:#333;padding-top:5px;padding-left:35px}.relationGeneral h1 a{color:#333;text-decoration:none}.relationGeneral .slider{padding-left:15px;padding-right:15px;height:auto;height:77px}.relationGeneral .slide{text-align:center;margin-right:10px;padding-bottom:0}.relationGeneral .slide img{display:block;margin:0 auto}.relationLink{box-shadow:0 0 4px #999;-moz-box-shadow:0 0 4px #999;-webkit-box-shadow:0 0 4px #999;border:1px solid #ccc;margin-bottom:10px}.relationLink h1{font-size:14px;font-family:'PT Sans',sans-serif;padding:0;margin:0;height:24px;line-height:1em;border-bottom:1px solid #ccc;color:#333;padding-top:5px;padding-left:35px}.relationLink h1 a{color:#333;text-decoration:none}.relationLink .item-list{padding:0 0 5px 0;margin:0 0}.relationLink .item-list li{list-style:none;padding-left:14px;border-bottom:1px solid #ccc}.relationLink .item-list li a{text-decoration:none;display:block;color:#333;line-height:1.2em;padding-left:20px;position:relative;font-size:14px;padding-top:5px;padding-bottom:5px}.relationLink .item-list li a:before{display:block;position:absolute;width:15px;height:10px;top:0;left:0;margin:5px 0 0 0;font-family:'FontAwesome';content:"\f06e";color:#076a72}.relationLink .item-list li a:hover:before{color:#076a72}.relationLink .item-list li:last-child{border:0}.relationLink .item-list li:last-child a{padding-bottom:0;margin-bottom:0}.relationImageLink{box-shadow:0 0 4px #999;-moz-box-shadow:0 0 4px #999;-webkit-box-shadow:0 0 4px #999;border:1px solid #ccc;margin-bottom:20px}.relationImageLink .container{height:160px;padding-top:12px}.relationImageLink h1{font-size:14px;font-family:'PT Sans',sans-serif;padding:0;margin:0;height:24px;line-height:1em;border-bottom:1px solid #ccc;color:#333;padding-top:5px;padding-left:35px}.relationImageLink h1 a{color:#333;text-decoration:none}.relationImageLink .slider{padding-left:20px;padding-right:15px}.relationImageLink .item{border:1px solid #ccc;padding:5px;margin-right:10px;overflow:hidden;height:135px}.relationImageLink .item img{margin-bottom:5px}.relationImageLink .item h2{color:#333;font-size:14px;line-height:1em !important;padding:0;margin:0;font-weight:600;padding-bottom:5px}.relationImageLink .item h2 a{color:#333}.relationImageLink .item p{line-height:1em;font-size:12px;padding:0;margin:0}.storyteller{background:#e4e4e4;border:1px solid #d8d8d8;padding-bottom:15px;margin-bottom:20px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;clear:both}.storyteller #nav-bar{min-height:40px;background:#ececec}.storyteller #nav-bar ul{padding:0;margin:0;margin-left:10px}@media (max-width:480px){.storyteller #nav-bar ul{margin-left:-1px;margin-right:-1px;margin-top:-1px}}.storyteller #nav-bar ul li{list-style:none;display:inline;padding:10px 10px;height:40px;float:left;border-left:1px solid #d8d8d8}@media (max-width:480px){.storyteller #nav-bar ul li{display:block;float:none}}.storyteller #nav-bar ul li:hover,.storyteller #nav-bar ul li.active{background-color:#f9f9f9}@media (max-width:480px){.storyteller #nav-bar ul li:hover,.storyteller #nav-bar ul li.active{background-color:transparent}}.storyteller #nav-bar ul li:hover a,.storyteller #nav-bar ul li.active a{color:#333;text-decoration:none;border-bottom:4px solid #076a72}.storyteller #nav-bar ul li a{display:inline-block;color:#7a7a7a;text-decoration:none;text-transform:uppercase}.storyteller #nav-bar ul li:last-child{border-right:1px solid #d8d8d8}.storyteller .content-story{padding-top:20px}.storyteller .item-box{position:relative;background:#f9f9f9;display:block;width:95%;margin:0 auto 35px auto;padding:10px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.storyteller .item-box h1{font-size:18px}.storyteller .item-box h2{font-size:16px}.storyteller .item-box h4{font-size:14px}.storyteller .item-box.with-angle-icon{background:#f9f9f9 url(../img/bg/bg-box.png) 99.8% 2px no-repeat}.storyteller .item-box .box-angle{font-size:15px;position:absolute;right:0;top:0;margin:7px 5px 0 0}.storyteller .item-box.comment{background:#f9f9f9}.storyteller .item-box.comment form{margin-top:20px;margin-left:auto;margin-right:auto;width:200px}.storyteller .item-box.comment form span{min-width:110px;text-align:right;display:inline-block;margin-right:10px}.storyteller .item-box.comment form input[type="text"],.storyteller .item-box.comment form textarea{display:inline-block;width:100%}.storyteller .item-box.gallery{background:#f9f9f9}.storyteller .item-box .arrow-big{background:url(../img/ico/arrow-baloon-big.png) 0 0 no-repeat;width:18px;height:16px;display:block;position:absolute;top:0;left:50%;margin-left:-9px;margin-top:-16px}.storyteller .item-box iframe{width:100%;margin:0 0 30px 0}.storyteller .item-box .functions .from{color:#076a72}.storyteller .item-box .functions .from span{font-weight:bold;color:#333}.storyteller .item-box .functions .actions{border-top:1px solid #d8d8d8;margin-top:4px;padding-top:4px;padding-bottom:8px}.storyteller .item-box .functions .actions ul{padding:0;margin:0;padding-top:8px}.storyteller .item-box .functions .actions ul.dx{float:right}.storyteller .item-box .functions .actions ul.dx li a{text-decoration:none}.storyteller .item-box .functions .actions ul.dx li i{font-size:18px}.storyteller .item-box .functions .actions ul.sx{float:left}.storyteller .item-box .functions .actions ul li{list-style:none;display:inline;border-right:1px solid #d8d8d8;padding:5px 10px}.storyteller .item-box .functions .actions ul li:last-child{border:0}.storyteller .item-box .functions .actions ul li i{color:#e5e5e5;margin-right:5px}.storyteller .item-box .functions .actions ul li a{display:inline-block;text-decoration:none;padding:0;line-height:16px}.storyteller .item-box .functions .actions ul li a:hover{text-decoration:underline}.storyteller .item-box .archive-link{text-align:center;padding-top:5px}.storyteller .item-box .item-comment{border-bottom:1px solid #d8d8d8;padding-bottom:10px;margin-bottom:10px}.storyteller .item-box .item-comment:last-child{border-bottom:0;padding-bottom:0;margin-bottom:0}.storyteller .item-box .story-gallery{border-top:1px solid #d8d8d8;padding-top:20px;padding-bottom:20px;padding-left:10px;padding-right:10px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.storyteller .item-box .story-gallery .mini-photo{border:1px solid transparent;padding-right:0;float:left;width:82px;height:82px;position:relative;margin-right:12px;margin-bottom:12px}.storyteller .item-box .story-gallery .mini-photo:last-child{margin-right:0}.storyteller .item-box .story-gallery .mini-photo img{margin:0;float:none;padding:2px;margin-right:8px;border:1px solid #c6c6c6;border-radius:0;-moz-border-radius:0;-webkit-border-radius:0}.storyteller .item-box .story-gallery .mini-photo:last-child:hover .popup{margin-left:-80px}.storyteller .item-box .story-gallery .mini-photo:last-child:hover .popup .popup-arrow{right:0;left:auto;margin-right:8px}.storyteller .item-box .story-gallery .mini-photo:hover .popup{visibility:visible}ul.insights{list-style:none;margin:10px 0;padding:0}ul.insights li{float:left;padding-right:10px;margin-right:10px;border-right:1px solid #d8d8d8}ul.insights li:last-child{margin-right:0;padding-right:0;border:0}.wrapper-galleria-io{padding:5px;border:1px solid #ccc;margin-bottom:40px;clear:both}.wrapper-galleria-io .content-galleria-io{max-width:100%;position:relative;font-family:'PT Sans',sans-serif}.wrapper-galleria-io .content-galleria-io:hover .galleria-info-description{opacity:1;filter:alpha(opacity=100)}.wrapper-galleria-io .content-galleria-io .galleria-info{margin-bottom:10px}.wrapper-galleria-io .content-galleria-io .galleria-info-description{opacity:0;filter:alpha(opacity=0);position:absolute;margin:0 0 31px -15px !important;bottom:0 !important;display:block;width:100%;background:url(../img/bg/bg-description.png) repeat;padding:5px 15px;padding-right:40px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-top:1px solid #000;border-right:1px solid #000;width:430px}.wrapper-galleria-io .galleria-counter{margin-bottom:10px;margin-right:46px}.wrapper-galleria-io.slider{border:0}.wrapper-galleria-io #galleria.sfogliatore .galleria-info{position:absolute;height:15px;left:0;bottom:0;margin-bottom:5px !important;color:#bbb;margin-right:40px}.wrapper-galleria-io #galleria.sfogliatore .galleria-info-description{margin:0 0 15px -5px !important}.wrapper-galleria-io #galleria.slider .galleria-info-text{top:auto;bottom:0;margin-bottom:-12px}.imageList{margin-bottom:30px !important;display:block;clear:both;padding-left:15px;padding-right:15px}.issue-slider{margin-bottom:20px !important;margin-left:-15px;margin-right:-15px}.issue-slider.storyteller{background:none;border:0;padding-bottom:0;margin-bottom:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:auto;clear:both}.item-slide{height:448px;overflow:hidden;padding:5px;margin-right:50px;opacity:.5;position:relative}.item-slide.story-slide{height:auto}.item-slide.story-slide .content-slide{height:auto !important}.item-slide.story-slide .content-slide .arrow-big{display:none}.item-slide.story-slide .content-slide .item-box{background:#f9f9f9;width:100%;margin:0 auto 0 auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.item-slide.story-slide .content-slide .item-box.comment{background:#f9f9f9}.item-slide.story-slide .content-slide .item-box.comment form{margin-top:0;margin:0 auto;width:300px !important}.item-slide.story-slide .content-slide .item-box.comment form span{min-width:inherit;text-align:left;display:inline-block;margin-right:0}.item-slide.story-slide .content-slide .item-box.comment form input[type="text"],.item-slide.story-slide .content-slide .item-box.comment form textarea{display:block;width:300px !important}.item-slide.story-slide .content-slide .item-box iframe{position:relative;-moz-transform:none;display:block;width:100%;height:100%;margin-bottom:0}.item-slide.slick-center{opacity:1}.item-slide .content-slide{height:100%;padding:5px;box-shadow:0 0 4px #999;-moz-box-shadow:0 0 4px #999;-webkit-box-shadow:0 0 4px #999}.item-slide.picture figure img{display:block;margin:0 auto;width:100%;max-width:100%}.item-slide.picture figcaption{font-size:14px;padding-top:2px;display:block;margin:0 auto;text-align:center}.item-slide.text .content-slide{padding:10px}.item-slide.link .content-slide{padding:0;box-shadow:0 0 4px transparent;-moz-box-shadow:0 0 4px transparent;-webkit-box-shadow:0 0 4px transparent}.quick-slider-nav{height:39px;margin-bottom:12px;text-align:center}.quick-slider-nav.text-link ul li{margin-right:9px;border-right:1px solid #ccc}.quick-slider-nav.text-link ul li:last-child{border-right:0;margin-right:0}.quick-slider-nav.text-link ul li a{font-size:15px;color:#333;margin-right:13px}.quick-slider-nav ul{padding:0;margin:0;text-align:center;border:1px solid #ccc;display:inline-block;padding:7px 5px 0 5px}.quick-slider-nav ul li{display:inline;height:39px}.quick-slider-nav ul li span.fa{display:inline-block;font-size:25px;height:32px;cursor:pointer;color:#333;padding-top:5px;opacity:.5;text-align:center}.quick-slider-nav ul li a{display:inline-block;margin-right:9px;cursor:pointer}.quick-slider-nav ul li a:hover,.quick-slider-nav ul li a.active{border-bottom:5px solid #c00;text-decoration:none}.quick-slider-nav ul li a:hover span,.quick-slider-nav ul li a.active span{opacity:1}.storyjs-embed.sized-embed{border-radius:0}.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content h3,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3{color:#076a72 !important}.vco-timeline .vco-navigation .timenav-background .timenav-line,.vco-timeline .vco-navigation .timenav .content .marker.active .line,.vco-timeline .vco-navigation .timenav .content .marker.active .dot{background-color:#076a72 !important}.vco-timeline .vco-navigation .timenav .content .marker .line .event-line{background:#076a72 !important}.box-gallery-description{display:block;margin-bottom:20px !important;padding-top:20px;position:relative}.box-gallery-description:before{content:"";display:block;width:50%;height:1px;top:0;left:50%;position:absolute;margin-left:-25%;background:#ccc}.box-gallery-description:after{content:"";display:block;width:50%;height:1px;bottom:0;left:50%;position:absolute;margin-left:-25%;background:#ccc}#outer .slider{margin-bottom:0}#outer .slider.storyteller .slick-dots{position:absolute;top:0;margin-top:-20px;height:20px}#outer .slider.entity-slider .slick-prev{left:0;margin-left:-20px}#outer .slider.js-relationImage .slick-prev,#outer .slider.js-relationImageLink .slick-prev,#outer .slider.js-imageList .slick-prev,#outer .slider.js-relationImage .slick-next,#outer .slider.js-relationImageLink .slick-next,#outer .slider.js-imageList .slick-next{width:9px;height:18px;padding:0;margin-top:30px;background:none;padding-top:5px;margin-left:5px;top:0}#outer .slider.js-relationImage .slick-next,#outer .slider.js-relationImageLink .slick-next,#outer .slider.js-imageList .slick-next{margin-left:0;margin-right:2px}#outer .slider.js-relationImage .slick-prev:before,#outer .slider.js-relationImageLink .slick-prev:before,#outer .slider.js-imageList .slick-prev:before,#outer .slider.js-relationImage .slick-next:before,#outer .slider.js-relationImageLink .slick-next:before,#outer .slider.js-imageList .slick-next:before{color:#076a72;font-family:'FontAwesome';content:"\f0d9";font-size:24px;line-height:0}#outer .slider.js-relationImage .slick-next:before,#outer .slider.js-relationImageLink .slick-next:before,#outer .slider.js-imageList .slick-next:before{content:"\f0da"}#outer .slider .js-relationImageLink .slick-prev,#outer .slider .js-relationImageLink .slick-next{margin-top:60px}#outer .slick-dots li.slick-active button{background:#c00}#outer .slick-dots li button{width:12px;height:12px;padding:0;border-radius:100px;-moz-border-radius:100px;-webkit-border-radius:100px;background:#076a72}#outer .slick-dots li button:hover{background:#c00}#outer .slick-dots li button:before{display:none}#outer .slick-prev:before,#outer .slick-next:before{font-family:'FontAwesome';content:"\f053";color:#fff;opacity:1;font-size:30px;font-weight:lighter}#outer .slick-disabled{display:none !important}#outer .slick-next:before{content:"\f054"}#outer .slick-prev,#outer .slick-next{width:40px;height:56px;padding-top:4px;top:50%;margin-top:-23px;background:url(../img/bg/bg-opacity.png) repeat}#outer .slick-prev{left:0}#outer .slick-next{right:0}@media (max-width:979px){.navbar-toggle,.show-nav-for-iphone,.show-footer-nav-for-iphone{display:block}.navbar-toggle{margin-left:15px}.show-nav-for-iphone{position:absolute;left:0;background:#076a72;margin-left:10px;top:0;margin-top:20px;z-index:9}header{min-height:73px;height:auto}.site-logo{background:url(../img/logo.png) 0 0 no-repeat;float:none;display:block;width:269px;height:62px;position:absolute;left:50%;top:0;margin-top:5px;margin-left:-134.5px}#topbar{display:none}.item-slide{height:auto}.storyteller .actions .sx,.storyteller .actions .dx{float:none !important}.storyteller .actions ul{text-align:center !important;padding-bottom:8px !important}.menu{padding:0 0;position:relative;bottom:0;right:0;margin-bottom:5px;margin-top:60px}.menu ul{padding:0;margin:0;margin-right:0}.menu ul li{list-style:none;display:block !important;float:none !important}.menu ul li.jqx-menu-item-top-selected a{background:none !important}.menu ul li a{color:#fff;font-size:14px;margin-right:0;padding:0 5px 0 5px;border-bottom:0 !important;margin-bottom:8px;border-left:3px solid #303447}.menu ul li a:hover{border-left:3px solid #c00;background:none !important}.menu ul li a.active{border-left:3px solid #c00}.jqx-menu-dropdown{display:none !important}.show-footer-nav-for-iphone{margin-top:10px}.collapse{display:none}.sx{width:100%;float:none}.main-content{width:100%;float:none}footer .box{float:none;width:100%;min-height:inherit;border-bottom:1px solid #ccc;border-right:0}footer .box:last-child{border-bottom:0}footer .logo-footer{float:none;width:100%;min-height:inherit;border-right:0;border-bottom:1px solid #ccc}#topbar{padding-bottom:8px}#topbar form{display:none}}@media (max-width:765px){body{overflow:auto;overflow-x:hidden;margin:0;background:#303447}#outer{margin:0}header{position:relative}footer{position:relative}.storyteller .actions{display:none}.item-slide{margin-right:10px}.item-slide .main-img.align-right img{float:none}.item-slide .main-img.align-left img{float:none}.item-slide.story-slide{height:auto !important}.item-slide.story-slide .content-slide{height:auto !important}.item-slide.story-slide .content-slide .arrow-big{display:none}.item-slide.story-slide .content-slide .item-box.comment{background:#f9f9f9}.item-slide.story-slide .content-slide .item-box.comment form{margin-top:0;margin:0 0;width:100% !important}.item-slide.story-slide .content-slide .item-box.comment form span{min-width:inherit;text-align:left;display:inline-block;margin-right:0}.item-slide.story-slide .content-slide .item-box.comment form input[type="text"],.item-slide.story-slide .content-slide .item-box.comment form textarea,.item-slide.story-slide .content-slide .item-box.comment form label{display:block;width:100% !important}.main-content{margin-top:0;position:relative;margin-bottom:0;height:auto !important;min-height:700px !important;overflow:hidden;background:#fff}.slideshow .slide{height:600px}figure.main-img{float:none !important;display:block !important;margin:0 auto 0 auto !important}figure.main-img .superzoom{display:none}.main-img{float:none !important;text-align:center !important;width:200px !important}.main-img.align-right{float:none !important}.main-img img{float:none !important}input[type="text"],input[type="password"],input[type="email"]{background:#fff;border:0;box-shadow:0;color:#333;width:100%;padding:2px;font-size:14px;border:1px solid #ccc;height:30px;border-radius:0;-moz-border-radius:0;-webkit-border-radius:0}input[type="text"].required,input[type="password"].required,input[type="email"].required{border:2px solid #ccc}input[type="text"].input-large,input[type="password"].input-large,input[type="email"].input-large{width:300px}input[type="text"].input-small,input[type="password"].input-small,input[type="email"].input-small{width:160px}.issue-slider .slick-prev{top:0 !important;margin-top:-60px !important}.issue-slider .slick-next{top:0 !important;margin-top:-60px !important}article.slideshow ul li{height:360px;background-position:bottom !important;background-size:320px}article.slideshow ul li img{width:100% !important;float:none !important;height:auto !important}article.slideshow ul li .description{min-height:200px !important;padding-left:10px;width:100% !important;background-color:#ccc}article.slideshow .flex-control-nav{top:330px}}@media only screen and (max-width:480px){input[type="text"],input[type="password"],input[type="email"]{background:#fff;border:0;box-shadow:0;color:#333;width:100%;padding:2px;font-size:14px;border:1px solid #ccc;height:30px;border-radius:0;-moz-border-radius:0;-webkit-border-radius:0}input[type="text"].required,input[type="password"].required,input[type="email"].required{border:2px solid #ccc}input[type="text"].input-large,input[type="password"].input-large,input[type="email"].input-large{width:280px}input[type="text"].input-small,input[type="password"].input-small,input[type="email"].input-small{width:160px}select{width:auto}select.select-large{width:280px}select.select-small{width:160px}select.select-medium{width:260px}textarea{border:1px solid #ccc;width:100%;padding:4px;height:150px}textarea.textarea-large{width:280px}footer .logo-footer{float:none;padding:0;border:0;margin-top:10px;margin-right:auto;margin-left:auto;text-align:center}footer p{text-align:center}footer #info-page{height:auto}footer #info-page nav{display:block}footer #info-page nav ul{padding-left:5px;text-align:center}footer #info-page nav ul li{display:inline}footer #info-page nav ul li a{display:inline-block;border-right:0;float:none;padding-right:0;margin:0 5px 0 0;padding-top:8px;height:auto}footer #info-page p{font-size:11px;padding-top:0;line-height:30px;text-align:center;display:block}#outer .item-slide .slider{margin-bottom:0;position:relative}#outer .item-slide .slider.js-relationImage .slick-prev,#outer .item-slide .slider.js-relationImageLink .slick-prev,#outer .item-slide .slider.js-imageList .slick-prev,#outer .item-slide .slider.js-relationImage .slick-next,#outer .item-slide .slider.js-relationImageLink .slick-next,#outer .item-slide .slider.js-imageList .slick-next{width:9px;height:18px;padding:0;margin-top:30px;background:none;padding-top:5px;margin-left:5px;top:0}#outer .item-slide .slider.js-relationImage.js-relationImageLink .slick-prev,#outer .item-slide .slider.js-relationImageLink.js-relationImageLink .slick-prev,#outer .item-slide .slider.js-imageList.js-relationImageLink .slick-prev,#outer .item-slide .slider.js-relationImage.js-relationImageLink .slick-next,#outer .item-slide .slider.js-relationImageLink.js-relationImageLink .slick-next,#outer .item-slide .slider.js-imageList.js-relationImageLink .slick-next{top:50% !important;margin-top:!important}#outer .item-slide .slider.js-relationImage.js-relationImageLink .slick-next,#outer .item-slide .slider.js-relationImageLink.js-relationImageLink .slick-next,#outer .item-slide .slider.js-imageList.js-relationImageLink .slick-next{margin-right:5px !important}.slideshow .description{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin-left:0;height:212px;overflow:hidden;position:absolute;top:50%;left:0;margin:-106px 0 0 0;padding:20px}.slideshow .description h1{font-family:'PT Serif',serif;font-size:30px;font-style:italic;text-align:center;padding-bottom:20px}.slideshow .description h1 a{color:#fff;text-decoration:none}.slideshow .description p{font-family:'PT Serif',serif;color:#fff;line-height:1em;font-size:20px;display:block;margin:0 auto;width:200px;padding-top:20px;text-align:center;border-top:1px solid #fff}} \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/img/bg/bg-box.png b/src/static/movio/templates/Sliding-windows/img/bg/bg-box.png new file mode 100644 index 0000000000000000000000000000000000000000..f54bbaf2212814e8b8021699fac05f6cf2d14d20 GIT binary patch literal 800 zcmV+*1K<3KP)<h;3K|Lk000e1NJLTq001cf001fo1^@s6F7$F(00004b3#c}2nYxW zd<bNS00009a7bBm000WZ000WZ0W>Kjs{jB19&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?o zcW-iQb09-gH7+r$A4ux}000<tMObu0a%Ew3X>V>IRB3Hx05LQzFg7hRFflWgTr)!e z00MMLL_t(oh0U1Vj;b&eg};`D7!xr{CMLfByBROQpBQ4W&~w3QEr=s1$gG=j9BsbY zKdXBq4u^x0QlhnHN@=Z8N};tzN(q3Jk}wQWN+|%=>-Ch34$^<EwdQ)gA{UE=n3V3n zEEG`7YL;b4fW=}V(lkYDJzCnE=Qe@-NX}+6_qi|(D@cGij>Y+Wu7!L^HO~!#p!U8} z3S$faMNzo-%Ch7k)k%_=D2i$a456|t5keqD_v&&r+5AHs$0AMB!QiZ<l)V6LG=WD* zfX!wj&gb)}HQGf=se9wJDUM@tJRZNvRFhw`Pay$*etuj;r;s)FUm;=oh~|0z8WO6A zj_spOS>Jq_ZeL^jsIQ_ZT+{S|gu6YB9ZhTM^ZC50%f1JU<)c<*S-N|?bK|tB%}4Ej zKLjMy2adNO;j!!c+$PUtj6o?yp65U{XykeRcz5^JkavAi6wbt<YR+G8oUXE6Zx8)M zK@dEg@per%<=fMzpv`Q&)!ok&$FbP$c0(Ok(_oMQ+wE3lS;qBx?e#r>ENj!CkO0f& zQe;`yns(o&{I$VvmNpFz33tP{R-(18tV9Ust+sx<IKn89P#J!fW$yPd3<2EG&_|;| z0<2c6+7;T|5S3D$>UUH~s8WBqT*&jhwi#N`*=+XGwnm49Dx#OmrFPf*DR1*eUtfWQ z&*ssuLBjj<=vN`(y?ONOkkEgxp9B*6ZK0DvLifFXQb?G7ukWS9;b3mJo4MU?#u(#% zCP`u@kEE3~d@Fwd`7@AEf%;wV9`sKQ)>Lz6l2U%YEsmxAes7{ELTmkZApuUOlNs`n e_-HzvPUau0G^Ak#XRj6j0000<MNUMnLSTY$f^Js; literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Sliding-windows/img/bg/bg-description.png b/src/static/movio/templates/Sliding-windows/img/bg/bg-description.png new file mode 100644 index 0000000000000000000000000000000000000000..fae27607a8a20104f6d3d5c489ff54bc755a5f05 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blmSQK*5Dp-y;YjHK@;M7UB8wRq zxP?HN@zUM8KR`jb64!{5;QX|b^2DN42FH~Aq*MjB%%art{G#k)1?ON>J;T-V9<PBa z#X%~ai&7IyGV}8kLNaqx87y=S%yo?n42>^OZp{QL;q`QJ4B?oWY+z<)$IQSqhcWH+ SnG|iH1cRrmpUXO@geCx@8!hqx literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Sliding-windows/img/bg/bg-opacity.png b/src/static/movio/templates/Sliding-windows/img/bg/bg-opacity.png new file mode 100644 index 0000000000000000000000000000000000000000..c3478675838f9044fcf47d06b0572b94620b8624 GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blmSQK*5Dp-y;YjHK@;M7UB8wRq zx;#Lb@grA(6Hrj1#5JPCxhOTUBr`uxAtW<5mBGkZ*T7QO$iUE~)Z);8pc*-ln&AAj zlJdl&R0hYC{G?O`x6Go{^8BLgVg=`5Q$54g@*b~&DtSF!978x}CI?(Kv1Ddo@?i82 SQ+Nn+5`(9!pUXO@geCx?b1km` literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Sliding-windows/img/ico/alert-error.png b/src/static/movio/templates/Sliding-windows/img/ico/alert-error.png new file mode 100644 index 0000000000000000000000000000000000000000..b2e8b957f30efe4892854be097591f71b5a2ac54 GIT binary patch literal 1454 zcmV;f1yTBmP)<h;3K|Lk000e1NJLTq001li001Tk1^@s6zaM#L00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy5G%YYT zEiy1MGk$A`KmY&$9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00ja`L_t(oh0U35Xj5kt$A7o2owbcjHt}sR2ClR+Ww3n_>W49P6PbcIP`WP*?$b7u zGPZ#Oi`2a#qE+eYONZ5}owMuIy5ZU(tE*JBSU084;tR7)o3^n{ZeDDYd-fssiOG_* zd9!-p4+;02^Zatoea^j43mG;M$q|t^MC8>>=gz2!h($z>h{!#8WSt_i=Sj0gnF-sb zD93JI7yrL^!noyVrq;^IP@ZaFap3-4+*R8#90LGkzwjajWn0kl^4E*VZB5g@NOvJE z-2@`C6!=X%Zk!dLhG3QD6fVG0Ru13=7HOK+oz8k$=>(fr2H<OH!WgoHNQC@1uQS?q z9v~0cn(kt00gK26V1+Sc$JcxY5s4|!>3YQD23T))Wb%PUBnPv)o>TQ09(P>ez@Qy( z^BEOd_C$bzoj~!}&A;(o_#H8fapgUCiol>9V1<Z$GO55KG9R!4=tmF4t!%gqj~n-~ zgDQp9?9k)@6Rd8Y??MY>_ijg2GJl<wnKg~ftZBqz{TQB^8oK7Ya*@%lzW|EO9FHH^ z+%zl2<HmVpA0kFb(^juz+VWK)->D^UlDB+SgpaFkpSo-{JN0;hfh_>;UmG#pI$}sj zxkU?=&oWcw7A=hM8M}KMZ)-CI$6V4?P72uEEG2<~ew-(dU>HV(1W~R5QwS2}H&Xi@ zMsUonOm@sA3@joR%#Ai&TNQH>JmL)xB+4(KyU@=zD32|V1sJFTiXYzS#Cz$_*uZg! zWBEEy)Z!oL2PjEq%q0XYBCi9b0FFK1#GSQ?R#<8H`@PD`YIZO)z(6^G^URNo+HDwO z#FWG!79_5}`%){u>sKK-=BhFREFx=xm4;hq_;}5@PqSnzEQY~g<(JB{)a+z>z`#a; z2ghsh>#nFBA7@I0@kURHaE<oc7&-leaxYH{SVSs-62INX@Xz%VzAvOwVKEFGbq6ur zIt0hu+LVCJO|S-_f5%qD2u!H>Q)2wMfIfnwZodlHm=ZAN81r1ag8SN)aoZZYB_ss= zoT=c8PXe)y#$$~2+aNgRDv|;=pFX7kecQ_?Y^jpoc3!18VG6zNe8Ta4+e6QgHSxw= zyb5mu7(86fXkSml3pyI=7(84ZN-}u38b?E2!tw6T%Xm63!#HCu>JVxkd-ex(7u}^R z)Ml78n=)$-^Xq<5Uzcf`)*OC4R)wtqeS5#f?{Z-nlC*MPDkN{=YbnJ(wDn>?6e{kf z|HDO8*u2>{`?|a6-tcZp6`J>X1vB1W4S=t^i#r?NCy->9vhxcltUpI~fd$|LP16pj zYoQ8@$n%)h?cM!##7lRgdiJe%6s#AxICXvzvp@PQ={$bjiEZ~+3e6h+W5REVN??w& zwFSMSJ>iWKt|_zTs$4sO%>Ywo&rK<p<Lpm(Z*>7I4j*$_W_6bW>jS!zo?Y7#I#kAz z-qEh|ZU!0wMr}PQ=j+|IP30?7$Ehsy^jZlpP=APrz4ue9h!_U0j&}ME?pBLTANix1 zo}CqG<#RMOK=3$K381MlrgyY+>%;dZ+7Ag^c7cU}?#f7>qT18s&Y1_WEDKlyFw}H1 z<<`ZL-{s6$o}s3bihoHCFbt5LZwdYZ?<usrmy6ZMtD5;bcLE^ba^m^t#uEdJWzz~5 zkZqX`U;`Eb!Bd5Zw93<Kts?RYL_g_f08iULQ?6>7_CS644_Lf%-}b0WfdBvi07*qo IM6N<$f>2qYivR!s literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Sliding-windows/img/ico/alert-ok.png b/src/static/movio/templates/Sliding-windows/img/ico/alert-ok.png new file mode 100644 index 0000000000000000000000000000000000000000..1028f985b374e276ccd6a3f1eed040ad1bcb77b6 GIT binary patch literal 1289 zcmV+k1@`)hP)<h;3K|Lk000e1NJLTq001HY001Be1^@s6caN&c00004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy5G%YYT zEiy1MGk$A`KmY&$9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00do0L_t(og|(PlOk7nIhQB>bnW4z7+*2sUVB-W-l%_%r)&Oa(XiRLisnI5ltv-N> zB|d2%G--Wq2z{s+Vod5S#Rsq?3QFr#FvS!~M60PvrxFU~Higawn6rGCIb@ibGeZlk zWG8!{^PfH6ti9J+dmY6(n~3ZODuGhK4qQ-5bp_pDZv;PtM7GaGq(}!@R~Qi~5)qe( zNWZgNx+lMu-)4Jc-sjO_Tq1Hp2T|(?@-0w1>>lE>^Sh<%8{?8Gd7y%=3B~%QlfdzH z0TGcSK=ZujrG5Nk7Q`E-$%@aXD*XV!AHbugb$~Df4FFf}{J^~CMnns1W8NE#dmR8a zpwhh7AiycWHs*Ekw`<T)lo*#nmSqco1F)|th=|kxbpU<N@6kjv)Rv`G>s>prxYizN z02sJ)k;(Z{Ls7P+fPCvVfKlKbfHeaVk#~W;bBi+!&Gtt1#*Wn8dbb6bSThh2$spj3 zU#2_o_*{nChZ0NKv>^weS1EN|f0?b7M;d|LVb|~c;~Fv)#ha{@r#+_+TY~Sc8YGZQ z4tg~=KToxziO*15l2k#w$qH~@DfP*UKt!YzKq)m4gQWqWZ@Lrb!i1qH$(+Xa)Ea$w zD)fHX3r$37M5G7k2l_>%M?^{tU{3%Qx93ObcV56JKEw9ZrWf?b&IV^+-OM2q*8rUW zx4k0(WLh>?0GCDNX{FS!LE7!W`v4awTG3?D&>Nc*ig+;b5eN!bLl6<k$G_?5ojOnN zR0jZivR<b+xjX^r6Op4qYx@Dfm6>iFu0IVS0CuInq<34CQW4iL*du2E+fDahT$*fO zy4W%HDIV=EWvSHw%|T~}TCe8f(qtRHXd5)Sf=o*u1j5xwX9f_FCSb2~VUpI7rm&sg zHU1^HJPvAe4g)mf&zN+Le}&sOX9!_2B~X?5vOa7v6awZzwyXj;H_~W0@u1U=pz(ap z8vr(k>l%Yjd$hSJORdIY+6WQCH4Fs*dD3>nb&XNaaMXzhW`05wjmJ_dX&Y^hx+EzZ zGN{aWQ6GkdYpAJ!M+O1gnSbA7%;Sjl%!=%lykk6^R0jTVea%Rx?>UoFY7zJm;H|=s z*papyO?<0rTN1YE5QgCzYGweXRDFP~?%A9}6eQaCX5@6#<Q2{K<Q&qwhT$4&%g(HU zywM2cj(Ub^{jVwJz6rG_QlDX8UOo83b!RO7($XxWQtBM=B+#2{-O7=|4|zOwSHv@C zq-HT$sm(pCPZu>@LoF=VD5Y)&{>c~CxJ35nz0JP7I^yFjX!xSGo$0k$;}T&7;TjVp z2<TPdDBvzjtLDwZlVn>8&_s*avMmMFWFOQYj~T9EzZXjoC=EXYD%`%ibly6PeWGod zrZ}aX1Np~D@O$I5QmTHX0QX#O2I^IRt++TR*JrQF_1UZ9TAW)})85;x_gVV}ifVg= zqS_ufJm0ges`eF;H2j|#00xv&)Auuv4g&B$LpZhz*wdpE00000NkvXXu0mjf$zViH literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Sliding-windows/img/ico/arrow-baloon-big.png b/src/static/movio/templates/Sliding-windows/img/ico/arrow-baloon-big.png new file mode 100644 index 0000000000000000000000000000000000000000..7348b99777331bbeb13f4e09145d57b41f1558ae GIT binary patch literal 599 zcmV-d0;v6oP)<h;3K|Lk000e1NJLTq000sI000mO1^@s68wM|200004b3#c}2nYxW zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|7<5HgbVG7wVRUJ4ZXi@?ZDjy4G%YYT zEiy1MGnHI3LjV8(9&|-mbW?9;ba!ELWdK2BZ(?O2Mrm?ocW-iQb09-gH7+r$A4ux} z00FB>L_t(Ijh&LQZlgdDhJV%vTCK=H7Gw&)231ni+!Lg^Yfwm=G|4Nt;3@JDDR=-X z1g3)$Su`#!Bt&z24fr?{pHKOv)k-@v-~KzZ8kW+=#Q<nomVE~R-}gTNC;-34U42sf z7lZ*=0nm%0cx{?SHBF<6qId<Mk1;mp{u8tUpod|2Q&pAfx=wXnr>d$_VHn=bU>8A? zn{NP&vMjf4+p1w0)G!RHZCh2A<raW3=6vdE>dOj%o+OE1*R|^V{sij#Ue$H2k|goZ zTxl4o=P>4ZUL>UiV}HVoF-R%ld0sSgb8<94&;YP3%N|VAd?cd9+ldIKX+CCI_HbT1 zU3nTe=R9&<_fj9>x-K~9(Y$8iD9`g}BD&+8Uj%W^K}2_Xo<E;E(g0|29N!8dwo=NA zkV#TX2qCs{9N#WLK@hxImIYncuYz=4hh<p^g5YfqLYk)cLWmdJwy#1a*|rTK#7ml{ z_rN%QB3g|5nx^kSL=gaJyWQ>w5xs9VoBxK))wV5;$Ky|C7{-(1IA4MQfa5qY4C6`L l@AqoGUVj+`0Efc?zX1VMievRbFK++<002ovPDHLkV1j6L@8tjh literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Sliding-windows/img/ico/arrow-baloon.png b/src/static/movio/templates/Sliding-windows/img/ico/arrow-baloon.png new file mode 100644 index 0000000000000000000000000000000000000000..8bf5f098b4317b167bb4c1f6a5212b274d546970 GIT binary patch literal 381 zcmeAS@N?(olHy`uVBq!ia0vp^JRmj)8<3o<+3y6TSc;uILpXq-h9ji|$mcBZh%9Dc z;1&X5#!GkW{s09fN?apKoQqNuOEUBG6hbm{QyB~`bq$PkjSLKp|2Iuz0;-V%sR_<c zD=AMbN@Z|N$xljEaLX)8Ezd8?E>>_3Hq|p+E${IfsPdwxi(`n!#MVCBuI2y{xAVo^ zc?VtZxTeT%X1v|F@{*tY39X=;?FV8TuP#t9(^~YS>!5wyEE|rV#qp&-ceKBk2rXqu zln`<ijNW){(lSkkM*Z8{mcHKQ`@pubLqdV=#OFDwk>CEwGd6V8FmJD%r`eTM|L|>J z<NalsFMj`%5SS?c;LX)*rM58+F6SJKd@t|MI_M_OoE>|e=Wqc}hsUd{n{<9J-nJE} zoAIPY-;~r!o;{y9142cwMcu!9makz|TmyeH&pFG6%lG!TuUqvh<SW+)mL{8o<F9pv RYJi?&@O1TaS?83{1OQkbk#hh5 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Sliding-windows/img/logo-footer.png b/src/static/movio/templates/Sliding-windows/img/logo-footer.png new file mode 100644 index 0000000000000000000000000000000000000000..9a5b1603986de62fbbf5b6cf00f17853e8fe0a46 GIT binary patch literal 4554 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Sliding-windows/img/logo.png b/src/static/movio/templates/Sliding-windows/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..3f02a3d762431e64c28743fdd7afa97b6d67cfcb GIT binary patch literal 1866 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 Yk}k_#<c>2bQG7FiuU7z!=>bpwFECAw4FCWD literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Sliding-windows/img/logo_movio.png b/src/static/movio/templates/Sliding-windows/img/logo_movio.png new file mode 100644 index 0000000000000000000000000000000000000000..f0dddb4349c2ff134643a00a5141404b05696661 GIT binary patch literal 2067 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Sliding-windows/js/bootstrap.min.js b/src/static/movio/templates/Sliding-windows/js/bootstrap.min.js new file mode 100755 index 0000000..b04a0e8 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/js/bootstrap.min.js @@ -0,0 +1,6 @@ +/*! + * Bootstrap v3.1.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.isLoading=!1};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",f.resetText||d.data("resetText",d[e]()),d[e](f[b]||this.options[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},b.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});return this.$element.trigger(j),j.isDefaultPrevented()?void 0:(this.sliding=!0,f&&this.pause(),this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid.bs.carousel",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid.bs.carousel")},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid.bs.carousel")),f&&this.cycle(),this)};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("collapse in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);!e&&f.toggle&&"show"==c&&(c=!c),e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(jQuery),+function(a){"use strict";function b(b){a(d).remove(),a(e).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown",h),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=" li:not(.divider):visible a",i=f.find("[role=menu]"+h+", [role=listbox]"+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j<i.length-1&&j++,~j||(j=0),i.eq(j).focus()}}}};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.dropdown.Constructor=f,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu], [role=listbox]",f.prototype.keydown)}(jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show().scrollTop(0),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)}))},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=a.support.transition&&c;if(this.$backdrop=a('<div class="modal-backdrop '+c+'" />').appendTo(document.body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());c.is("a")&&b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this,d=this.tip();this.setContent(),this.options.animation&&d.addClass("fade");var e="function"==typeof this.options.placement?this.options.placement.call(this,d[0],this.$element[0]):this.options.placement,f=/\s?auto?\s?/i,g=f.test(e);g&&(e=e.replace(f,"")||"top"),d.detach().css({top:0,left:0,display:"block"}).addClass(e),this.options.container?d.appendTo(this.options.container):d.insertAfter(this.$element);var h=this.getPosition(),i=d[0].offsetWidth,j=d[0].offsetHeight;if(g){var k=this.$element.parent(),l=e,m=document.documentElement.scrollTop||document.body.scrollTop,n="body"==this.options.container?window.innerWidth:k.outerWidth(),o="body"==this.options.container?window.innerHeight:k.outerHeight(),p="body"==this.options.container?0:k.offset().left;e="bottom"==e&&h.top+h.height+j-m>o?"top":"top"==e&&h.top-m-j<0?"bottom":"right"==e&&h.right+i>n?"left":"left"==e&&h.left-i<p?"right":e,d.removeClass(l).addClass(e)}var q=this.getCalculatedOffset(e,h,i,j);this.applyPlacement(q,e),this.hoverState=null;var r=function(){c.$element.trigger("shown.bs."+c.type)};a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,r).emulateTransitionEnd(150):r()}},b.prototype.applyPlacement=function(b,c){var d,e=this.tip(),f=e[0].offsetWidth,g=e[0].offsetHeight,h=parseInt(e.css("margin-top"),10),i=parseInt(e.css("margin-left"),10);isNaN(h)&&(h=0),isNaN(i)&&(i=0),b.top=b.top+h,b.left=b.left+i,a.offset.setOffset(e[0],a.extend({using:function(a){e.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),e.addClass("in");var j=e[0].offsetWidth,k=e[0].offsetHeight;if("top"==c&&k!=g&&(d=!0,b.top=b.top+g-k),/bottom|top/.test(c)){var l=0;b.left<0&&(l=-2*b.left,b.left=0,e.offset(b),j=e[0].offsetWidth,k=e[0].offsetHeight),this.replaceArrow(l-f+j,j,"left")}else this.replaceArrow(k-g,k,"top");d&&e.offset(b)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach(),c.$element.trigger("hidden.bs."+c.type)}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.hoverState=null,this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;(e||"destroy"!=c)&&(e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]())})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(a(c).is("body")?window:c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);{var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})}},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(b.RESET).addClass("affix");var a=this.$window.scrollTop(),c=this.$element.offset();return this.pinnedOffset=c.top-a},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"top"==this.affixed&&(e.top+=d),"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(b.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:c-h-this.$element.height()}))}}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(jQuery); \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/js/jquery-1.8.2.min.js b/src/static/movio/templates/Sliding-windows/js/jquery-1.8.2.min.js new file mode 100644 index 0000000..ab28a24 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/js/jquery-1.8.2.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="<select msallowclip=''><option selected=''></option></select>",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=lb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=mb(b);function pb(){}pb.prototype=d.filters=d.pseudos,d.setFilters=new pb,g=fb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fb.error(a):z(a,i).slice(0)};function qb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; +if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==cb()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===cb()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ab:bb):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:bb,isPropagationStopped:bb,isImmediatePropagationStopped:bb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ab,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ab,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ab,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=bb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,m(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=bb),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function db(a){var b=eb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var eb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fb=/ jQuery\d+="(?:null|\d+)"/g,gb=new RegExp("<(?:"+eb+")[\\s/>]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/<tbody/i,lb=/<|&#?\w+;/,mb=/<(?:script|style|link)/i,nb=/checked\s*(?:[^=]|=\s*.checked.)/i,ob=/^$|\/(?:java|ecma)script/i,pb=/^true\/(.*)/,qb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,rb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?"<table>"!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Cb[0].contentWindow||Cb[0].contentDocument).document,b.write(),b.close(),c=Eb(a,b),Cb.detach()),Db[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Gb=/^margin/,Hb=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ib,Jb,Kb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ib=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Hb.test(g)&&Gb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ib=function(a){return a.currentStyle},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Hb.test(g)&&!Kb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Lb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Mb=/alpha\([^)]*\)/i,Nb=/opacity\s*=\s*([^)]*)/,Ob=/^(none|table(?!-c[ea]).+)/,Pb=new RegExp("^("+S+")(.*)$","i"),Qb=new RegExp("^([+-])=("+S+")","i"),Rb={position:"absolute",visibility:"hidden",display:"block"},Sb={letterSpacing:"0",fontWeight:"400"},Tb=["Webkit","O","Moz","ms"];function Ub(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Tb.length;while(e--)if(b=Tb[e]+c,b in a)return b;return d}function Vb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fb(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wb(a,b,c){var d=Pb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Yb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ib(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Jb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Hb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xb(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Jb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ub(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ub(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Jb(a,b,d)),"normal"===f&&b in Sb&&(f=Sb[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Ob.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Rb,function(){return Yb(a,b,d)}):Yb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ib(a);return Wb(a,c,d?Xb(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Nb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Mb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Mb.test(f)?f.replace(Mb,e):f+" "+e)}}),m.cssHooks.marginRight=Lb(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Jb,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Gb.test(a)||(m.cssHooks[a+b].set=Wb)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ib(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Vb(this,!0)},hide:function(){return Vb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Zb(a,b,c,d,e){return new Zb.prototype.init(a,b,c,d,e)}m.Tween=Zb,Zb.prototype={constructor:Zb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px") +},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Zb.propHooks.scrollTop=Zb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Zb.prototype.init,m.fx.step={};var $b,_b,ac=/^(?:toggle|show|hide)$/,bc=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cc=/queueHooks$/,dc=[ic],ec={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bc.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bc.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fc(){return setTimeout(function(){$b=void 0}),$b=m.now()}function gc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hc(a,b,c){for(var d,e=(ec[b]||[]).concat(ec["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ic(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fb(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fb(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ac.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fb(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hc(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jc(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kc(a,b,c){var d,e,f=0,g=dc.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$b||fc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$b||fc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jc(k,j.opts.specialEasing);g>f;f++)if(d=dc[f].call(j,a,k,j.opts))return d;return m.map(k,hc,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kc,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],ec[c]=ec[c]||[],ec[c].unshift(b)},prefilter:function(a,b){b?dc.unshift(a):dc.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kc(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gc(b,!0),a,d,e)}}),m.each({slideDown:gc("show"),slideUp:gc("hide"),slideToggle:gc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($b=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$b=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_b||(_b=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_b),_b=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lc=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lc,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mc,nc,oc=m.expr.attrHandle,pc=/^(?:checked|selected)$/i,qc=k.getSetAttribute,rc=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nc:mc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rc&&qc||!pc.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qc?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nc={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rc&&qc||!pc.test(c)?a.setAttribute(!qc&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=oc[b]||m.find.attr;oc[b]=rc&&qc||!pc.test(b)?function(a,b,d){var e,f;return d||(f=oc[b],oc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,oc[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rc&&qc||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mc&&mc.set(a,b,c)}}),qc||(mc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},oc.id=oc.name=oc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mc.set},m.attrHooks.contenteditable={set:function(a,b,c){mc.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sc=/^(?:input|select|textarea|button|object)$/i,tc=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sc.test(a.nodeName)||tc.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var uc=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(uc," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vc=m.now(),wc=/\?/,xc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yc,zc,Ac=/#.*$/,Bc=/([?&])_=[^&]*/,Cc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Dc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Ec=/^(?:GET|HEAD)$/,Fc=/^\/\//,Gc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hc={},Ic={},Jc="*/".concat("*");try{zc=location.href}catch(Kc){zc=y.createElement("a"),zc.href="",zc=zc.href}yc=Gc.exec(zc.toLowerCase())||[];function Lc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mc(a,b,c,d){var e={},f=a===Ic;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nc(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Oc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zc,type:"GET",isLocal:Dc.test(yc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nc(Nc(a,m.ajaxSettings),b):Nc(m.ajaxSettings,a)},ajaxPrefilter:Lc(Hc),ajaxTransport:Lc(Ic),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zc)+"").replace(Ac,"").replace(Fc,yc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yc[1]&&c[2]===yc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yc[3]||("http:"===yc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mc(Hc,k,b,v),2===t)return v;h=k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Ec.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bc.test(e)?e.replace(Bc,"$1_="+vc++):e+(wc.test(e)?"&":"?")+"_="+vc++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mc(Ic,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Oc(k,v,c)),u=Pc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qc=/%20/g,Rc=/\[\]$/,Sc=/\r?\n/g,Tc=/^(?:submit|button|image|reset|file)$/i,Uc=/^(?:input|select|textarea|keygen)/i;function Vc(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rc.test(a)?d(a,e):Vc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vc(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vc(c,a[c],b,e);return d.join("&").replace(Qc,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Uc.test(this.nodeName)&&!Tc.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sc,"\r\n")}}):{name:b.name,value:c.replace(Sc,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zc()||$c()}:Zc;var Wc=0,Xc={},Yc=m.ajaxSettings.xhr();a.ActiveXObject&&m(a).on("unload",function(){for(var a in Xc)Xc[a](void 0,!0)}),k.cors=!!Yc&&"withCredentials"in Yc,Yc=k.ajax=!!Yc,Yc&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xc[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zc(){try{return new a.XMLHttpRequest}catch(b){}}function $c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _c=[],ad=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_c.pop()||m.expando+"_"+vc++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ad.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ad.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ad,"$1"+e):b.jsonp!==!1&&(b.url+=(wc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_c.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bd=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bd)return bd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cd=a.document.documentElement;function dd(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dd(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cd;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cd})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dd(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=Lb(k.pixelPosition,function(a,c){return c?(c=Jb(a,b),Hb.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ed=a.jQuery,fd=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fd),b&&a.jQuery===m&&(a.jQuery=ed),m},typeof b===K&&(a.jQuery=a.$=m),m}); diff --git a/src/static/movio/templates/Sliding-windows/js/jquery.mCustomScrollbar.concat.min.js b/src/static/movio/templates/Sliding-windows/js/jquery.mCustomScrollbar.concat.min.js new file mode 100755 index 0000000..8519e6a --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/js/jquery.mCustomScrollbar.concat.min.js @@ -0,0 +1,4 @@ +/*mousewheel*/ +(function(a){function d(b){var c=b||window.event,d=[].slice.call(arguments,1),e=0,f=!0,g=0,h=0;return b=a.event.fix(c),b.type="mousewheel",c.wheelDelta&&(e=c.wheelDelta/120),c.detail&&(e=-c.detail/3),h=e,c.axis!==undefined&&c.axis===c.HORIZONTAL_AXIS&&(h=0,g=-1*e),c.wheelDeltaY!==undefined&&(h=c.wheelDeltaY/120),c.wheelDeltaX!==undefined&&(g=-1*c.wheelDeltaX/120),d.unshift(b,e,g,h),(a.event.dispatch||a.event.handle).apply(this,d)}var b=["DOMMouseScroll","mousewheel"];if(a.event.fixHooks)for(var c=b.length;c;)a.event.fixHooks[b[--c]]=a.event.mouseHooks;a.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=b.length;a;)this.addEventListener(b[--a],d,!1);else this.onmousewheel=d},teardown:function(){if(this.removeEventListener)for(var a=b.length;a;)this.removeEventListener(b[--a],d,!1);else this.onmousewheel=null}},a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery); +/*custom scrollbar*/ +(function(c){var b={init:function(e){var f={set_width:false,set_height:false,horizontalScroll:false,scrollInertia:950,mouseWheel:true,mouseWheelPixels:"auto",autoDraggerLength:true,autoHideScrollbar:false,alwaysShowScrollbar:false,snapAmount:null,snapOffset:0,scrollButtons:{enable:false,scrollType:"continuous",scrollSpeed:"auto",scrollAmount:40},advanced:{updateOnBrowserResize:true,updateOnContentResize:false,autoExpandHorizontalScroll:false,autoScrollOnFocus:true,normalizeMouseWheelDelta:false},contentTouchScroll:true,callbacks:{onScrollStart:function(){},onScroll:function(){},onTotalScroll:function(){},onTotalScrollBack:function(){},onTotalScrollOffset:0,onTotalScrollBackOffset:0,whileScrolling:function(){}},theme:"light"},e=c.extend(true,f,e);return this.each(function(){var m=c(this);if(e.set_width){m.css("width",e.set_width)}if(e.set_height){m.css("height",e.set_height)}if(!c(document).data("mCustomScrollbar-index")){c(document).data("mCustomScrollbar-index","1")}else{var t=parseInt(c(document).data("mCustomScrollbar-index"));c(document).data("mCustomScrollbar-index",t+1)}m.wrapInner("<div class='mCustomScrollBox mCS-"+e.theme+"' id='mCSB_"+c(document).data("mCustomScrollbar-index")+"' style='position:relative; height:100%; overflow:hidden; max-width:100%;' />").addClass("mCustomScrollbar _mCS_"+c(document).data("mCustomScrollbar-index"));var g=m.children(".mCustomScrollBox");if(e.horizontalScroll){g.addClass("mCSB_horizontal").wrapInner("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />");var k=g.children(".mCSB_h_wrapper");k.wrapInner("<div class='mCSB_container' style='position:absolute; left:0;' />").children(".mCSB_container").css({width:k.children().outerWidth(),position:"relative"}).unwrap()}else{g.wrapInner("<div class='mCSB_container' style='position:relative; top:0;' />")}var o=g.children(".mCSB_container");if(c.support.touch){o.addClass("mCS_touch")}o.after("<div class='mCSB_scrollTools' style='position:absolute;'><div class='mCSB_draggerContainer'><div class='mCSB_dragger' style='position:absolute;' oncontextmenu='return false;'><div class='mCSB_dragger_bar' style='position:relative;'></div></div><div class='mCSB_draggerRail'></div></div></div>");var l=g.children(".mCSB_scrollTools"),h=l.children(".mCSB_draggerContainer"),q=h.children(".mCSB_dragger");if(e.horizontalScroll){q.data("minDraggerWidth",q.width())}else{q.data("minDraggerHeight",q.height())}if(e.scrollButtons.enable){if(e.horizontalScroll){l.prepend("<a class='mCSB_buttonLeft' oncontextmenu='return false;'></a>").append("<a class='mCSB_buttonRight' oncontextmenu='return false;'></a>")}else{l.prepend("<a class='mCSB_buttonUp' oncontextmenu='return false;'></a>").append("<a class='mCSB_buttonDown' oncontextmenu='return false;'></a>")}}g.bind("scroll",function(){if(!m.is(".mCS_disabled")){g.scrollTop(0).scrollLeft(0)}});m.data({mCS_Init:true,mCustomScrollbarIndex:c(document).data("mCustomScrollbar-index"),horizontalScroll:e.horizontalScroll,scrollInertia:e.scrollInertia,scrollEasing:"mcsEaseOut",mouseWheel:e.mouseWheel,mouseWheelPixels:e.mouseWheelPixels,autoDraggerLength:e.autoDraggerLength,autoHideScrollbar:e.autoHideScrollbar,alwaysShowScrollbar:e.alwaysShowScrollbar,snapAmount:e.snapAmount,snapOffset:e.snapOffset,scrollButtons_enable:e.scrollButtons.enable,scrollButtons_scrollType:e.scrollButtons.scrollType,scrollButtons_scrollSpeed:e.scrollButtons.scrollSpeed,scrollButtons_scrollAmount:e.scrollButtons.scrollAmount,autoExpandHorizontalScroll:e.advanced.autoExpandHorizontalScroll,autoScrollOnFocus:e.advanced.autoScrollOnFocus,normalizeMouseWheelDelta:e.advanced.normalizeMouseWheelDelta,contentTouchScroll:e.contentTouchScroll,onScrollStart_Callback:e.callbacks.onScrollStart,onScroll_Callback:e.callbacks.onScroll,onTotalScroll_Callback:e.callbacks.onTotalScroll,onTotalScrollBack_Callback:e.callbacks.onTotalScrollBack,onTotalScroll_Offset:e.callbacks.onTotalScrollOffset,onTotalScrollBack_Offset:e.callbacks.onTotalScrollBackOffset,whileScrolling_Callback:e.callbacks.whileScrolling,bindEvent_scrollbar_drag:false,bindEvent_content_touch:false,bindEvent_scrollbar_click:false,bindEvent_mousewheel:false,bindEvent_buttonsContinuous_y:false,bindEvent_buttonsContinuous_x:false,bindEvent_buttonsPixels_y:false,bindEvent_buttonsPixels_x:false,bindEvent_focusin:false,bindEvent_autoHideScrollbar:false,mCSB_buttonScrollRight:false,mCSB_buttonScrollLeft:false,mCSB_buttonScrollDown:false,mCSB_buttonScrollUp:false});if(e.horizontalScroll){if(m.css("max-width")!=="none"){if(!e.advanced.updateOnContentResize){e.advanced.updateOnContentResize=true}}}else{if(m.css("max-height")!=="none"){var s=false,r=parseInt(m.css("max-height"));if(m.css("max-height").indexOf("%")>=0){s=r,r=m.parent().height()*s/100}m.css("overflow","hidden");g.css("max-height",r)}}m.mCustomScrollbar("update");if(e.advanced.updateOnBrowserResize){var i,j=c(window).width(),u=c(window).height();c(window).bind("resize."+m.data("mCustomScrollbarIndex"),function(){if(i){clearTimeout(i)}i=setTimeout(function(){if(!m.is(".mCS_disabled")&&!m.is(".mCS_destroyed")){var w=c(window).width(),v=c(window).height();if(j!==w||u!==v){if(m.css("max-height")!=="none"&&s){g.css("max-height",m.parent().height()*s/100)}m.mCustomScrollbar("update");j=w;u=v}}},150)})}if(e.advanced.updateOnContentResize){var p;if(e.horizontalScroll){var n=o.outerWidth()}else{var n=o.outerHeight()}p=setInterval(function(){if(e.horizontalScroll){if(e.advanced.autoExpandHorizontalScroll){o.css({position:"absolute",width:"auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({width:o.outerWidth(),position:"relative"}).unwrap()}var v=o.outerWidth()}else{var v=o.outerHeight()}if(v!=n){m.mCustomScrollbar("update");n=v}},300)}})},update:function(){var n=c(this),k=n.children(".mCustomScrollBox"),q=k.children(".mCSB_container");q.removeClass("mCS_no_scrollbar");n.removeClass("mCS_disabled mCS_destroyed");k.scrollTop(0).scrollLeft(0);var y=k.children(".mCSB_scrollTools"),o=y.children(".mCSB_draggerContainer"),m=o.children(".mCSB_dragger");if(n.data("horizontalScroll")){var A=y.children(".mCSB_buttonLeft"),t=y.children(".mCSB_buttonRight"),f=k.width();if(n.data("autoExpandHorizontalScroll")){q.css({position:"absolute",width:"auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({width:q.outerWidth(),position:"relative"}).unwrap()}var z=q.outerWidth()}else{var w=y.children(".mCSB_buttonUp"),g=y.children(".mCSB_buttonDown"),r=k.height(),i=q.outerHeight()}if(i>r&&!n.data("horizontalScroll")){y.css("display","block");var s=o.height();if(n.data("autoDraggerLength")){var u=Math.round(r/i*s),l=m.data("minDraggerHeight");if(u<=l){m.css({height:l})}else{if(u>=s-10){var p=s-10;m.css({height:p})}else{m.css({height:u})}}m.children(".mCSB_dragger_bar").css({"line-height":m.height()+"px"})}var B=m.height(),x=(i-r)/(s-B);n.data("scrollAmount",x).mCustomScrollbar("scrolling",k,q,o,m,w,g,A,t);var D=Math.abs(q.position().top);n.mCustomScrollbar("scrollTo",D,{scrollInertia:0,trigger:"internal"})}else{if(z>f&&n.data("horizontalScroll")){y.css("display","block");var h=o.width();if(n.data("autoDraggerLength")){var j=Math.round(f/z*h),C=m.data("minDraggerWidth");if(j<=C){m.css({width:C})}else{if(j>=h-10){var e=h-10;m.css({width:e})}else{m.css({width:j})}}}var v=m.width(),x=(z-f)/(h-v);n.data("scrollAmount",x).mCustomScrollbar("scrolling",k,q,o,m,w,g,A,t);var D=Math.abs(q.position().left);n.mCustomScrollbar("scrollTo",D,{scrollInertia:0,trigger:"internal"})}else{k.unbind("mousewheel focusin");if(n.data("horizontalScroll")){m.add(q).css("left",0)}else{m.add(q).css("top",0)}if(n.data("alwaysShowScrollbar")){if(!n.data("horizontalScroll")){m.css({height:o.height()})}else{if(n.data("horizontalScroll")){m.css({width:o.width()})}}}else{y.css("display","none");q.addClass("mCS_no_scrollbar")}n.data({bindEvent_mousewheel:false,bindEvent_focusin:false})}}},scrolling:function(i,q,n,k,A,f,D,w){var l=c(this);if(!l.data("bindEvent_scrollbar_drag")){var o,p,C,z,e;if(c.support.pointer){C="pointerdown";z="pointermove";e="pointerup"}else{if(c.support.msPointer){C="MSPointerDown";z="MSPointerMove";e="MSPointerUp"}}if(c.support.pointer||c.support.msPointer){k.bind(C,function(K){K.preventDefault();l.data({on_drag:true});k.addClass("mCSB_dragger_onDrag");var J=c(this),M=J.offset(),I=K.originalEvent.pageX-M.left,L=K.originalEvent.pageY-M.top;if(I<J.width()&&I>0&&L<J.height()&&L>0){o=L;p=I}});c(document).bind(z+"."+l.data("mCustomScrollbarIndex"),function(K){K.preventDefault();if(l.data("on_drag")){var J=k,M=J.offset(),I=K.originalEvent.pageX-M.left,L=K.originalEvent.pageY-M.top;G(o,p,L,I)}}).bind(e+"."+l.data("mCustomScrollbarIndex"),function(x){l.data({on_drag:false});k.removeClass("mCSB_dragger_onDrag")})}else{k.bind("mousedown touchstart",function(K){K.preventDefault();K.stopImmediatePropagation();var J=c(this),N=J.offset(),I,M;if(K.type==="touchstart"){var L=K.originalEvent.touches[0]||K.originalEvent.changedTouches[0];I=L.pageX-N.left;M=L.pageY-N.top}else{l.data({on_drag:true});k.addClass("mCSB_dragger_onDrag");I=K.pageX-N.left;M=K.pageY-N.top}if(I<J.width()&&I>0&&M<J.height()&&M>0){o=M;p=I}}).bind("touchmove",function(K){K.preventDefault();K.stopImmediatePropagation();var N=K.originalEvent.touches[0]||K.originalEvent.changedTouches[0],J=c(this),M=J.offset(),I=N.pageX-M.left,L=N.pageY-M.top;G(o,p,L,I)});c(document).bind("mousemove."+l.data("mCustomScrollbarIndex"),function(K){if(l.data("on_drag")){var J=k,M=J.offset(),I=K.pageX-M.left,L=K.pageY-M.top;G(o,p,L,I)}}).bind("mouseup."+l.data("mCustomScrollbarIndex"),function(x){l.data({on_drag:false});k.removeClass("mCSB_dragger_onDrag")})}l.data({bindEvent_scrollbar_drag:true})}function G(J,K,L,I){if(l.data("horizontalScroll")){l.mCustomScrollbar("scrollTo",(k.position().left-(K))+I,{moveDragger:true,trigger:"internal"})}else{l.mCustomScrollbar("scrollTo",(k.position().top-(J))+L,{moveDragger:true,trigger:"internal"})}}if(c.support.touch&&l.data("contentTouchScroll")){if(!l.data("bindEvent_content_touch")){var m,E,s,t,v,F,H;q.bind("touchstart",function(x){x.stopImmediatePropagation();m=x.originalEvent.touches[0]||x.originalEvent.changedTouches[0];E=c(this);s=E.offset();v=m.pageX-s.left;t=m.pageY-s.top;F=t;H=v});q.bind("touchmove",function(x){x.preventDefault();x.stopImmediatePropagation();m=x.originalEvent.touches[0]||x.originalEvent.changedTouches[0];E=c(this).parent();s=E.offset();v=m.pageX-s.left;t=m.pageY-s.top;if(l.data("horizontalScroll")){l.mCustomScrollbar("scrollTo",H-v,{trigger:"internal"})}else{l.mCustomScrollbar("scrollTo",F-t,{trigger:"internal"})}})}}if(!l.data("bindEvent_scrollbar_click")){n.bind("click",function(I){var x=(I.pageY-n.offset().top)*l.data("scrollAmount"),y=c(I.target);if(l.data("horizontalScroll")){x=(I.pageX-n.offset().left)*l.data("scrollAmount")}if(y.hasClass("mCSB_draggerContainer")||y.hasClass("mCSB_draggerRail")){l.mCustomScrollbar("scrollTo",x,{trigger:"internal",scrollEasing:"draggerRailEase"})}});l.data({bindEvent_scrollbar_click:true})}if(l.data("mouseWheel")){if(!l.data("bindEvent_mousewheel")){i.bind("mousewheel",function(K,M){var J,I=l.data("mouseWheelPixels"),x=Math.abs(q.position().top),L=k.position().top,y=n.height()-k.height();if(l.data("normalizeMouseWheelDelta")){if(M<0){M=-1}else{M=1}}if(I==="auto"){I=100+Math.round(l.data("scrollAmount")/2)}if(l.data("horizontalScroll")){L=k.position().left;y=n.width()-k.width();x=Math.abs(q.position().left)}if((M>0&&L!==0)||(M<0&&L!==y)){K.preventDefault();K.stopImmediatePropagation()}J=x-(M*I);l.mCustomScrollbar("scrollTo",J,{trigger:"internal"})});l.data({bindEvent_mousewheel:true})}}if(l.data("scrollButtons_enable")){if(l.data("scrollButtons_scrollType")==="pixels"){if(l.data("horizontalScroll")){w.add(D).unbind("mousedown touchstart MSPointerDown pointerdown mouseup MSPointerUp pointerup mouseout MSPointerOut pointerout touchend",j,h);l.data({bindEvent_buttonsContinuous_x:false});if(!l.data("bindEvent_buttonsPixels_x")){w.bind("click",function(x){x.preventDefault();r(Math.abs(q.position().left)+l.data("scrollButtons_scrollAmount"))});D.bind("click",function(x){x.preventDefault();r(Math.abs(q.position().left)-l.data("scrollButtons_scrollAmount"))});l.data({bindEvent_buttonsPixels_x:true})}}else{f.add(A).unbind("mousedown touchstart MSPointerDown pointerdown mouseup MSPointerUp pointerup mouseout MSPointerOut pointerout touchend",j,h);l.data({bindEvent_buttonsContinuous_y:false});if(!l.data("bindEvent_buttonsPixels_y")){f.bind("click",function(x){x.preventDefault();r(Math.abs(q.position().top)+l.data("scrollButtons_scrollAmount"))});A.bind("click",function(x){x.preventDefault();r(Math.abs(q.position().top)-l.data("scrollButtons_scrollAmount"))});l.data({bindEvent_buttonsPixels_y:true})}}function r(x){if(!k.data("preventAction")){k.data("preventAction",true);l.mCustomScrollbar("scrollTo",x,{trigger:"internal"})}}}else{if(l.data("horizontalScroll")){w.add(D).unbind("click");l.data({bindEvent_buttonsPixels_x:false});if(!l.data("bindEvent_buttonsContinuous_x")){w.bind("mousedown touchstart MSPointerDown pointerdown",function(y){y.preventDefault();var x=B();l.data({mCSB_buttonScrollRight:setInterval(function(){l.mCustomScrollbar("scrollTo",Math.abs(q.position().left)+x,{trigger:"internal",scrollEasing:"easeOutCirc"})},17)})});var j=function(x){x.preventDefault();clearInterval(l.data("mCSB_buttonScrollRight"))};w.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout",j);D.bind("mousedown touchstart MSPointerDown pointerdown",function(y){y.preventDefault();var x=B();l.data({mCSB_buttonScrollLeft:setInterval(function(){l.mCustomScrollbar("scrollTo",Math.abs(q.position().left)-x,{trigger:"internal",scrollEasing:"easeOutCirc"})},17)})});var h=function(x){x.preventDefault();clearInterval(l.data("mCSB_buttonScrollLeft"))};D.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout",h);l.data({bindEvent_buttonsContinuous_x:true})}}else{f.add(A).unbind("click");l.data({bindEvent_buttonsPixels_y:false});if(!l.data("bindEvent_buttonsContinuous_y")){f.bind("mousedown touchstart MSPointerDown pointerdown",function(y){y.preventDefault();var x=B();l.data({mCSB_buttonScrollDown:setInterval(function(){l.mCustomScrollbar("scrollTo",Math.abs(q.position().top)+x,{trigger:"internal",scrollEasing:"easeOutCirc"})},17)})});var u=function(x){x.preventDefault();clearInterval(l.data("mCSB_buttonScrollDown"))};f.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout",u);A.bind("mousedown touchstart MSPointerDown pointerdown",function(y){y.preventDefault();var x=B();l.data({mCSB_buttonScrollUp:setInterval(function(){l.mCustomScrollbar("scrollTo",Math.abs(q.position().top)-x,{trigger:"internal",scrollEasing:"easeOutCirc"})},17)})});var g=function(x){x.preventDefault();clearInterval(l.data("mCSB_buttonScrollUp"))};A.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout",g);l.data({bindEvent_buttonsContinuous_y:true})}}function B(){var x=l.data("scrollButtons_scrollSpeed");if(l.data("scrollButtons_scrollSpeed")==="auto"){x=Math.round((l.data("scrollInertia")+100)/40)}return x}}}if(l.data("autoScrollOnFocus")){if(!l.data("bindEvent_focusin")){i.bind("focusin",function(){i.scrollTop(0).scrollLeft(0);var x=c(document.activeElement);if(x.is("input,textarea,select,button,a[tabindex],area,object")){var J=q.position().top,y=x.position().top,I=i.height()-x.outerHeight();if(l.data("horizontalScroll")){J=q.position().left;y=x.position().left;I=i.width()-x.outerWidth()}if(J+y<0||J+y>I){l.mCustomScrollbar("scrollTo",y,{trigger:"internal"})}}});l.data({bindEvent_focusin:true})}}if(l.data("autoHideScrollbar")&&!l.data("alwaysShowScrollbar")){if(!l.data("bindEvent_autoHideScrollbar")){i.bind("mouseenter",function(x){i.addClass("mCS-mouse-over");d.showScrollbar.call(i.children(".mCSB_scrollTools"))}).bind("mouseleave touchend",function(x){i.removeClass("mCS-mouse-over");if(x.type==="mouseleave"){d.hideScrollbar.call(i.children(".mCSB_scrollTools"))}});l.data({bindEvent_autoHideScrollbar:true})}}},scrollTo:function(e,f){var i=c(this),o={moveDragger:false,trigger:"external",callbacks:true,scrollInertia:i.data("scrollInertia"),scrollEasing:i.data("scrollEasing")},f=c.extend(o,f),p,g=i.children(".mCustomScrollBox"),k=g.children(".mCSB_container"),r=g.children(".mCSB_scrollTools"),j=r.children(".mCSB_draggerContainer"),h=j.children(".mCSB_dragger"),t=draggerSpeed=f.scrollInertia,q,s,m,l;if(!k.hasClass("mCS_no_scrollbar")){i.data({mCS_trigger:f.trigger});if(i.data("mCS_Init")){f.callbacks=false}if(e||e===0){if(typeof(e)==="number"){if(f.moveDragger){p=e;if(i.data("horizontalScroll")){e=h.position().left*i.data("scrollAmount")}else{e=h.position().top*i.data("scrollAmount")}draggerSpeed=0}else{p=e/i.data("scrollAmount")}}else{if(typeof(e)==="string"){var v;if(e==="top"){v=0}else{if(e==="bottom"&&!i.data("horizontalScroll")){v=k.outerHeight()-g.height()}else{if(e==="left"){v=0}else{if(e==="right"&&i.data("horizontalScroll")){v=k.outerWidth()-g.width()}else{if(e==="first"){v=i.find(".mCSB_container").find(":first")}else{if(e==="last"){v=i.find(".mCSB_container").find(":last")}else{v=i.find(e)}}}}}}if(v.length===1){if(i.data("horizontalScroll")){e=v.position().left}else{e=v.position().top}p=e/i.data("scrollAmount")}else{p=e=v}}}if(i.data("horizontalScroll")){if(i.data("onTotalScrollBack_Offset")){s=-i.data("onTotalScrollBack_Offset")}if(i.data("onTotalScroll_Offset")){l=g.width()-k.outerWidth()+i.data("onTotalScroll_Offset")}if(p<0){p=e=0;clearInterval(i.data("mCSB_buttonScrollLeft"));if(!s){q=true}}else{if(p>=j.width()-h.width()){p=j.width()-h.width();e=g.width()-k.outerWidth();clearInterval(i.data("mCSB_buttonScrollRight"));if(!l){m=true}}else{e=-e}}var n=i.data("snapAmount");if(n){e=Math.round(e/n)*n-i.data("snapOffset")}d.mTweenAxis.call(this,h[0],"left",Math.round(p),draggerSpeed,f.scrollEasing);d.mTweenAxis.call(this,k[0],"left",Math.round(e),t,f.scrollEasing,{onStart:function(){if(f.callbacks&&!i.data("mCS_tweenRunning")){u("onScrollStart")}if(i.data("autoHideScrollbar")&&!i.data("alwaysShowScrollbar")){d.showScrollbar.call(r)}},onUpdate:function(){if(f.callbacks){u("whileScrolling")}},onComplete:function(){if(f.callbacks){u("onScroll");if(q||(s&&k.position().left>=s)){u("onTotalScrollBack")}if(m||(l&&k.position().left<=l)){u("onTotalScroll")}}h.data("preventAction",false);i.data("mCS_tweenRunning",false);if(i.data("autoHideScrollbar")&&!i.data("alwaysShowScrollbar")){if(!g.hasClass("mCS-mouse-over")){d.hideScrollbar.call(r)}}}})}else{if(i.data("onTotalScrollBack_Offset")){s=-i.data("onTotalScrollBack_Offset")}if(i.data("onTotalScroll_Offset")){l=g.height()-k.outerHeight()+i.data("onTotalScroll_Offset")}if(p<0){p=e=0;clearInterval(i.data("mCSB_buttonScrollUp"));if(!s){q=true}}else{if(p>=j.height()-h.height()){p=j.height()-h.height();e=g.height()-k.outerHeight();clearInterval(i.data("mCSB_buttonScrollDown"));if(!l){m=true}}else{e=-e}}var n=i.data("snapAmount");if(n){e=Math.round(e/n)*n-i.data("snapOffset")}d.mTweenAxis.call(this,h[0],"top",Math.round(p),draggerSpeed,f.scrollEasing);d.mTweenAxis.call(this,k[0],"top",Math.round(e),t,f.scrollEasing,{onStart:function(){if(f.callbacks&&!i.data("mCS_tweenRunning")){u("onScrollStart")}if(i.data("autoHideScrollbar")&&!i.data("alwaysShowScrollbar")){d.showScrollbar.call(r)}},onUpdate:function(){if(f.callbacks){u("whileScrolling")}},onComplete:function(){if(f.callbacks){u("onScroll");if(q||(s&&k.position().top>=s)){u("onTotalScrollBack")}if(m||(l&&k.position().top<=l)){u("onTotalScroll")}}h.data("preventAction",false);i.data("mCS_tweenRunning",false);if(i.data("autoHideScrollbar")&&!i.data("alwaysShowScrollbar")){if(!g.hasClass("mCS-mouse-over")){d.hideScrollbar.call(r)}}}})}if(i.data("mCS_Init")){i.data({mCS_Init:false})}}}function u(w){if(i.data("mCustomScrollbarIndex")){this.mcs={top:k.position().top,left:k.position().left,draggerTop:h.position().top,draggerLeft:h.position().left,topPct:Math.round((100*Math.abs(k.position().top))/Math.abs(k.outerHeight()-g.height())),leftPct:Math.round((100*Math.abs(k.position().left))/Math.abs(k.outerWidth()-g.width()))};switch(w){case"onScrollStart":i.data("mCS_tweenRunning",true).data("onScrollStart_Callback").call(i,this.mcs);break;case"whileScrolling":i.data("whileScrolling_Callback").call(i,this.mcs);break;case"onScroll":i.data("onScroll_Callback").call(i,this.mcs);break;case"onTotalScrollBack":i.data("onTotalScrollBack_Callback").call(i,this.mcs);break;case"onTotalScroll":i.data("onTotalScroll_Callback").call(i,this.mcs);break}}}},stop:function(){var g=c(this),e=g.children().children(".mCSB_container"),f=g.children().children().children().children(".mCSB_dragger");d.mTweenAxisStop.call(this,e[0]);d.mTweenAxisStop.call(this,f[0])},disable:function(e){var j=c(this),f=j.children(".mCustomScrollBox"),h=f.children(".mCSB_container"),g=f.children(".mCSB_scrollTools"),i=g.children().children(".mCSB_dragger");f.unbind("mousewheel focusin mouseenter mouseleave touchend");h.unbind("touchstart touchmove");if(e){if(j.data("horizontalScroll")){i.add(h).css("left",0)}else{i.add(h).css("top",0)}}g.css("display","none");h.addClass("mCS_no_scrollbar");j.data({bindEvent_mousewheel:false,bindEvent_focusin:false,bindEvent_content_touch:false,bindEvent_autoHideScrollbar:false}).addClass("mCS_disabled")},destroy:function(){var e=c(this);e.removeClass("mCustomScrollbar _mCS_"+e.data("mCustomScrollbarIndex")).addClass("mCS_destroyed").children().children(".mCSB_container").unwrap().children().unwrap().siblings(".mCSB_scrollTools").remove();c(document).unbind("mousemove."+e.data("mCustomScrollbarIndex")+" mouseup."+e.data("mCustomScrollbarIndex")+" MSPointerMove."+e.data("mCustomScrollbarIndex")+" MSPointerUp."+e.data("mCustomScrollbarIndex"));c(window).unbind("resize."+e.data("mCustomScrollbarIndex"))}},d={showScrollbar:function(){this.stop().animate({opacity:1},"fast")},hideScrollbar:function(){this.stop().animate({opacity:0},"fast")},mTweenAxis:function(g,i,h,f,o,y){var y=y||{},v=y.onStart||function(){},p=y.onUpdate||function(){},w=y.onComplete||function(){};var n=t(),l,j=0,r=g.offsetTop,s=g.style;if(i==="left"){r=g.offsetLeft}var m=h-r;q();e();function t(){if(window.performance&&window.performance.now){return window.performance.now()}else{if(window.performance&&window.performance.webkitNow){return window.performance.webkitNow()}else{if(Date.now){return Date.now()}else{return new Date().getTime()}}}}function x(){if(!j){v.call()}j=t()-n;u();if(j>=g._time){g._time=(j>g._time)?j+l-(j-g._time):j+l-1;if(g._time<j+1){g._time=j+1}}if(g._time<f){g._id=_request(x)}else{w.call()}}function u(){if(f>0){g.currVal=k(g._time,r,m,f,o);s[i]=Math.round(g.currVal)+"px"}else{s[i]=h+"px"}p.call()}function e(){l=1000/60;g._time=j+l;_request=(!window.requestAnimationFrame)?function(z){u();return setTimeout(z,0.01)}:window.requestAnimationFrame;g._id=_request(x)}function q(){if(g._id==null){return}if(!window.requestAnimationFrame){clearTimeout(g._id)}else{window.cancelAnimationFrame(g._id)}g._id=null}function k(B,A,F,E,C){switch(C){case"linear":return F*B/E+A;break;case"easeOutQuad":B/=E;return -F*B*(B-2)+A;break;case"easeInOutQuad":B/=E/2;if(B<1){return F/2*B*B+A}B--;return -F/2*(B*(B-2)-1)+A;break;case"easeOutCubic":B/=E;B--;return F*(B*B*B+1)+A;break;case"easeOutQuart":B/=E;B--;return -F*(B*B*B*B-1)+A;break;case"easeOutQuint":B/=E;B--;return F*(B*B*B*B*B+1)+A;break;case"easeOutCirc":B/=E;B--;return F*Math.sqrt(1-B*B)+A;break;case"easeOutSine":return F*Math.sin(B/E*(Math.PI/2))+A;break;case"easeOutExpo":return F*(-Math.pow(2,-10*B/E)+1)+A;break;case"mcsEaseOut":var D=(B/=E)*B,z=D*B;return A+F*(0.499999999999997*z*D+-2.5*D*D+5.5*z+-6.5*D+4*B);break;case"draggerRailEase":B/=E/2;if(B<1){return F/2*B*B*B+A}B-=2;return F/2*(B*B*B+2)+A;break}}},mTweenAxisStop:function(e){if(e._id==null){return}if(!window.requestAnimationFrame){clearTimeout(e._id)}else{window.cancelAnimationFrame(e._id)}e._id=null},rafPolyfill:function(){var f=["ms","moz","webkit","o"],e=f.length;while(--e>-1&&!window.requestAnimationFrame){window.requestAnimationFrame=window[f[e]+"RequestAnimationFrame"];window.cancelAnimationFrame=window[f[e]+"CancelAnimationFrame"]||window[f[e]+"CancelRequestAnimationFrame"]}}};d.rafPolyfill.call();c.support.touch=!!("ontouchstart" in window);c.support.pointer=window.navigator.pointerEnabled;c.support.msPointer=window.navigator.msPointerEnabled;var a=("https:"==document.location.protocol)?"https:":"http:";c.event.special.mousewheel||document.write('<script src="'+a+'//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.0.6/jquery.mousewheel.min.js"><\/script>');c.fn.mCustomScrollbar=function(e){if(b[e]){return b[e].apply(this,Array.prototype.slice.call(arguments,1))}else{if(typeof e==="object"||!e){return b.init.apply(this,arguments)}else{c.error("Method "+e+" does not exist")}}}})(jQuery); \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/js/jquery.mCustomScrollbar.js b/src/static/movio/templates/Sliding-windows/js/jquery.mCustomScrollbar.js new file mode 100755 index 0000000..7e01da2 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/js/jquery.mCustomScrollbar.js @@ -0,0 +1,969 @@ +/* +== malihu jquery custom scrollbars plugin == +version: 2.8.3 +author: malihu (http://manos.malihu.gr) +plugin home: http://manos.malihu.gr/jquery-custom-content-scroller +*/ + +/* +Copyright 2010-2013 Manos Malihutsakis + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation, either version 3 of the License, or +any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see http://www.gnu.org/licenses/lgpl.html. +*/ +(function($){ + /*plugin script*/ + var methods={ + init:function(options){ + var defaults={ + set_width:false, /*optional element width: boolean, pixels, percentage*/ + set_height:false, /*optional element height: boolean, pixels, percentage*/ + horizontalScroll:false, /*scroll horizontally: boolean*/ + scrollInertia:950, /*scrolling inertia: integer (milliseconds)*/ + mouseWheel:true, /*mousewheel support: boolean*/ + mouseWheelPixels:"auto", /*mousewheel pixels amount: integer, "auto"*/ + autoDraggerLength:true, /*auto-adjust scrollbar dragger length: boolean*/ + autoHideScrollbar:false, /*auto-hide scrollbar when idle*/ + alwaysShowScrollbar:false, /*always show scrollbar even when there's nothing to scroll (disables autoHideScrollbar): boolean*/ + snapAmount:null, /* optional element always snaps to a multiple of this number in pixels */ + snapOffset:0, /* when snapping, snap with this number in pixels as an offset */ + scrollButtons:{ /*scroll buttons*/ + enable:false, /*scroll buttons support: boolean*/ + scrollType:"continuous", /*scroll buttons scrolling type: "continuous", "pixels"*/ + scrollSpeed:"auto", /*scroll buttons continuous scrolling speed: integer, "auto"*/ + scrollAmount:40 /*scroll buttons pixels scroll amount: integer (pixels)*/ + }, + advanced:{ + updateOnBrowserResize:true, /*update scrollbars on browser resize (for layouts based on percentages): boolean*/ + updateOnContentResize:false, /*auto-update scrollbars on content resize (for dynamic content): boolean*/ + autoExpandHorizontalScroll:false, /*auto-expand width for horizontal scrolling: boolean*/ + autoScrollOnFocus:true, /*auto-scroll on focused elements: boolean*/ + normalizeMouseWheelDelta:false /*normalize mouse-wheel delta (-1/1)*/ + }, + contentTouchScroll:true, /*scrolling by touch-swipe content: boolean*/ + callbacks:{ + onScrollStart:function(){}, /*user custom callback function on scroll start event*/ + onScroll:function(){}, /*user custom callback function on scroll event*/ + onTotalScroll:function(){}, /*user custom callback function on scroll end reached event*/ + onTotalScrollBack:function(){}, /*user custom callback function on scroll begin reached event*/ + onTotalScrollOffset:0, /*scroll end reached offset: integer (pixels)*/ + onTotalScrollBackOffset:0, /*scroll begin reached offset: integer (pixels)*/ + whileScrolling:function(){} /*user custom callback function on scrolling event*/ + }, + theme:"light" /*"light", "dark", "light-2", "dark-2", "light-thick", "dark-thick", "light-thin", "dark-thin"*/ + }, + options=$.extend(true,defaults,options); + return this.each(function(){ + var $this=$(this); + /*set element width/height, create markup for custom scrollbars, add classes*/ + if(options.set_width){ + $this.css("width",options.set_width); + } + if(options.set_height){ + $this.css("height",options.set_height); + } + if(!$(document).data("mCustomScrollbar-index")){ + $(document).data("mCustomScrollbar-index","1"); + }else{ + var mCustomScrollbarIndex=parseInt($(document).data("mCustomScrollbar-index")); + $(document).data("mCustomScrollbar-index",mCustomScrollbarIndex+1); + } + $this.wrapInner("<div class='mCustomScrollBox"+" mCS-"+options.theme+"' id='mCSB_"+$(document).data("mCustomScrollbar-index")+"' style='position:relative; height:100%; overflow:hidden; max-width:100%;' />").addClass("mCustomScrollbar _mCS_"+$(document).data("mCustomScrollbar-index")); + var mCustomScrollBox=$this.children(".mCustomScrollBox"); + if(options.horizontalScroll){ + mCustomScrollBox.addClass("mCSB_horizontal").wrapInner("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />"); + var mCSB_h_wrapper=mCustomScrollBox.children(".mCSB_h_wrapper"); + mCSB_h_wrapper.wrapInner("<div class='mCSB_container' style='position:absolute; left:0;' />").children(".mCSB_container").css({"width":mCSB_h_wrapper.children().outerWidth(),"position":"relative"}).unwrap(); + }else{ + mCustomScrollBox.wrapInner("<div class='mCSB_container' style='position:relative; top:0;' />"); + } + var mCSB_container=mCustomScrollBox.children(".mCSB_container"); + if($.support.touch){ + mCSB_container.addClass("mCS_touch"); + } + mCSB_container.after("<div class='mCSB_scrollTools' style='position:absolute;'><div class='mCSB_draggerContainer'><div class='mCSB_dragger' style='position:absolute;' oncontextmenu='return false;'><div class='mCSB_dragger_bar' style='position:relative;'></div></div><div class='mCSB_draggerRail'></div></div></div>"); + var mCSB_scrollTools=mCustomScrollBox.children(".mCSB_scrollTools"), + mCSB_draggerContainer=mCSB_scrollTools.children(".mCSB_draggerContainer"), + mCSB_dragger=mCSB_draggerContainer.children(".mCSB_dragger"); + if(options.horizontalScroll){ + mCSB_dragger.data("minDraggerWidth",mCSB_dragger.width()); + }else{ + mCSB_dragger.data("minDraggerHeight",mCSB_dragger.height()); + } + if(options.scrollButtons.enable){ + if(options.horizontalScroll){ + mCSB_scrollTools.prepend("<a class='mCSB_buttonLeft' oncontextmenu='return false;'></a>").append("<a class='mCSB_buttonRight' oncontextmenu='return false;'></a>"); + }else{ + mCSB_scrollTools.prepend("<a class='mCSB_buttonUp' oncontextmenu='return false;'></a>").append("<a class='mCSB_buttonDown' oncontextmenu='return false;'></a>"); + } + } + /*mCustomScrollBox scrollTop and scrollLeft is always 0 to prevent browser focus scrolling*/ + mCustomScrollBox.bind("scroll",function(){ + if(!$this.is(".mCS_disabled")){ /*native focus scrolling for disabled scrollbars*/ + mCustomScrollBox.scrollTop(0).scrollLeft(0); + } + }); + /*store options, global vars/states, intervals*/ + $this.data({ + /*init state*/ + "mCS_Init":true, + /*instance index*/ + "mCustomScrollbarIndex":$(document).data("mCustomScrollbar-index"), + /*option parameters*/ + "horizontalScroll":options.horizontalScroll, + "scrollInertia":options.scrollInertia, + "scrollEasing":"mcsEaseOut", + "mouseWheel":options.mouseWheel, + "mouseWheelPixels":options.mouseWheelPixels, + "autoDraggerLength":options.autoDraggerLength, + "autoHideScrollbar":options.autoHideScrollbar, + "alwaysShowScrollbar":options.alwaysShowScrollbar, + "snapAmount":options.snapAmount, + "snapOffset":options.snapOffset, + "scrollButtons_enable":options.scrollButtons.enable, + "scrollButtons_scrollType":options.scrollButtons.scrollType, + "scrollButtons_scrollSpeed":options.scrollButtons.scrollSpeed, + "scrollButtons_scrollAmount":options.scrollButtons.scrollAmount, + "autoExpandHorizontalScroll":options.advanced.autoExpandHorizontalScroll, + "autoScrollOnFocus":options.advanced.autoScrollOnFocus, + "normalizeMouseWheelDelta":options.advanced.normalizeMouseWheelDelta, + "contentTouchScroll":options.contentTouchScroll, + "onScrollStart_Callback":options.callbacks.onScrollStart, + "onScroll_Callback":options.callbacks.onScroll, + "onTotalScroll_Callback":options.callbacks.onTotalScroll, + "onTotalScrollBack_Callback":options.callbacks.onTotalScrollBack, + "onTotalScroll_Offset":options.callbacks.onTotalScrollOffset, + "onTotalScrollBack_Offset":options.callbacks.onTotalScrollBackOffset, + "whileScrolling_Callback":options.callbacks.whileScrolling, + /*events binding state*/ + "bindEvent_scrollbar_drag":false, + "bindEvent_content_touch":false, + "bindEvent_scrollbar_click":false, + "bindEvent_mousewheel":false, + "bindEvent_buttonsContinuous_y":false, + "bindEvent_buttonsContinuous_x":false, + "bindEvent_buttonsPixels_y":false, + "bindEvent_buttonsPixels_x":false, + "bindEvent_focusin":false, + "bindEvent_autoHideScrollbar":false, + /*buttons intervals*/ + "mCSB_buttonScrollRight":false, + "mCSB_buttonScrollLeft":false, + "mCSB_buttonScrollDown":false, + "mCSB_buttonScrollUp":false + }); + /*max-width/max-height*/ + if(options.horizontalScroll){ + if($this.css("max-width")!=="none"){ + if(!options.advanced.updateOnContentResize){ /*needs updateOnContentResize*/ + options.advanced.updateOnContentResize=true; + } + } + }else{ + if($this.css("max-height")!=="none"){ + var percentage=false,maxHeight=parseInt($this.css("max-height")); + if($this.css("max-height").indexOf("%")>=0){ + percentage=maxHeight, + maxHeight=$this.parent().height()*percentage/100; + } + $this.css("overflow","hidden"); + mCustomScrollBox.css("max-height",maxHeight); + } + } + $this.mCustomScrollbar("update"); + /*window resize fn (for layouts based on percentages)*/ + if(options.advanced.updateOnBrowserResize){ + var mCSB_resizeTimeout,currWinWidth=$(window).width(),currWinHeight=$(window).height(); + $(window).bind("resize."+$this.data("mCustomScrollbarIndex"),function(){ + if(mCSB_resizeTimeout){ + clearTimeout(mCSB_resizeTimeout); + } + mCSB_resizeTimeout=setTimeout(function(){ + if(!$this.is(".mCS_disabled") && !$this.is(".mCS_destroyed")){ + var winWidth=$(window).width(),winHeight=$(window).height(); + if(currWinWidth!==winWidth || currWinHeight!==winHeight){ /*ie8 fix*/ + if($this.css("max-height")!=="none" && percentage){ + mCustomScrollBox.css("max-height",$this.parent().height()*percentage/100); + } + $this.mCustomScrollbar("update"); + currWinWidth=winWidth; currWinHeight=winHeight; + } + } + },150); + }); + } + /*content resize fn (for dynamically generated content)*/ + if(options.advanced.updateOnContentResize){ + var mCSB_onContentResize; + if(options.horizontalScroll){ + var mCSB_containerOldSize=mCSB_container.outerWidth(); + }else{ + var mCSB_containerOldSize=mCSB_container.outerHeight(); + } + mCSB_onContentResize=setInterval(function(){ + if(options.horizontalScroll){ + if(options.advanced.autoExpandHorizontalScroll){ + mCSB_container.css({"position":"absolute","width":"auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({"width":mCSB_container.outerWidth(),"position":"relative"}).unwrap(); + } + var mCSB_containerNewSize=mCSB_container.outerWidth(); + }else{ + var mCSB_containerNewSize=mCSB_container.outerHeight(); + } + if(mCSB_containerNewSize!=mCSB_containerOldSize){ + $this.mCustomScrollbar("update"); + mCSB_containerOldSize=mCSB_containerNewSize; + } + },300); + } + }); + }, + update:function(){ + var $this=$(this), + mCustomScrollBox=$this.children(".mCustomScrollBox"), + mCSB_container=mCustomScrollBox.children(".mCSB_container"); + mCSB_container.removeClass("mCS_no_scrollbar"); + $this.removeClass("mCS_disabled mCS_destroyed"); + mCustomScrollBox.scrollTop(0).scrollLeft(0); /*reset scrollTop/scrollLeft to prevent browser focus scrolling*/ + var mCSB_scrollTools=mCustomScrollBox.children(".mCSB_scrollTools"), + mCSB_draggerContainer=mCSB_scrollTools.children(".mCSB_draggerContainer"), + mCSB_dragger=mCSB_draggerContainer.children(".mCSB_dragger"); + if($this.data("horizontalScroll")){ + var mCSB_buttonLeft=mCSB_scrollTools.children(".mCSB_buttonLeft"), + mCSB_buttonRight=mCSB_scrollTools.children(".mCSB_buttonRight"), + mCustomScrollBoxW=mCustomScrollBox.width(); + if($this.data("autoExpandHorizontalScroll")){ + mCSB_container.css({"position":"absolute","width":"auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({"width":mCSB_container.outerWidth(),"position":"relative"}).unwrap(); + } + var mCSB_containerW=mCSB_container.outerWidth(); + }else{ + var mCSB_buttonUp=mCSB_scrollTools.children(".mCSB_buttonUp"), + mCSB_buttonDown=mCSB_scrollTools.children(".mCSB_buttonDown"), + mCustomScrollBoxH=mCustomScrollBox.height(), + mCSB_containerH=mCSB_container.outerHeight(); + } + if(mCSB_containerH>mCustomScrollBoxH && !$this.data("horizontalScroll")){ /*content needs vertical scrolling*/ + mCSB_scrollTools.css("display","block"); + var mCSB_draggerContainerH=mCSB_draggerContainer.height(); + /*auto adjust scrollbar dragger length analogous to content*/ + if($this.data("autoDraggerLength")){ + var draggerH=Math.round(mCustomScrollBoxH/mCSB_containerH*mCSB_draggerContainerH), + minDraggerH=mCSB_dragger.data("minDraggerHeight"); + if(draggerH<=minDraggerH){ /*min dragger height*/ + mCSB_dragger.css({"height":minDraggerH}); + }else if(draggerH>=mCSB_draggerContainerH-10){ /*max dragger height*/ + var mCSB_draggerContainerMaxH=mCSB_draggerContainerH-10; + mCSB_dragger.css({"height":mCSB_draggerContainerMaxH}); + }else{ + mCSB_dragger.css({"height":draggerH}); + } + mCSB_dragger.children(".mCSB_dragger_bar").css({"line-height":mCSB_dragger.height()+"px"}); + } + var mCSB_draggerH=mCSB_dragger.height(), + /*calculate and store scroll amount, add scrolling*/ + scrollAmount=(mCSB_containerH-mCustomScrollBoxH)/(mCSB_draggerContainerH-mCSB_draggerH); + $this.data("scrollAmount",scrollAmount).mCustomScrollbar("scrolling",mCustomScrollBox,mCSB_container,mCSB_draggerContainer,mCSB_dragger,mCSB_buttonUp,mCSB_buttonDown,mCSB_buttonLeft,mCSB_buttonRight); + /*scroll*/ + var mCSB_containerP=Math.abs(mCSB_container.position().top); + $this.mCustomScrollbar("scrollTo",mCSB_containerP,{scrollInertia:0,trigger:"internal"}); + }else if(mCSB_containerW>mCustomScrollBoxW && $this.data("horizontalScroll")){ /*content needs horizontal scrolling*/ + mCSB_scrollTools.css("display","block"); + var mCSB_draggerContainerW=mCSB_draggerContainer.width(); + /*auto adjust scrollbar dragger length analogous to content*/ + if($this.data("autoDraggerLength")){ + var draggerW=Math.round(mCustomScrollBoxW/mCSB_containerW*mCSB_draggerContainerW), + minDraggerW=mCSB_dragger.data("minDraggerWidth"); + if(draggerW<=minDraggerW){ /*min dragger height*/ + mCSB_dragger.css({"width":minDraggerW}); + }else if(draggerW>=mCSB_draggerContainerW-10){ /*max dragger height*/ + var mCSB_draggerContainerMaxW=mCSB_draggerContainerW-10; + mCSB_dragger.css({"width":mCSB_draggerContainerMaxW}); + }else{ + mCSB_dragger.css({"width":draggerW}); + } + } + var mCSB_draggerW=mCSB_dragger.width(), + /*calculate and store scroll amount, add scrolling*/ + scrollAmount=(mCSB_containerW-mCustomScrollBoxW)/(mCSB_draggerContainerW-mCSB_draggerW); + $this.data("scrollAmount",scrollAmount).mCustomScrollbar("scrolling",mCustomScrollBox,mCSB_container,mCSB_draggerContainer,mCSB_dragger,mCSB_buttonUp,mCSB_buttonDown,mCSB_buttonLeft,mCSB_buttonRight); + /*scroll*/ + var mCSB_containerP=Math.abs(mCSB_container.position().left); + $this.mCustomScrollbar("scrollTo",mCSB_containerP,{scrollInertia:0,trigger:"internal"}); + }else{ /*content does not need scrolling*/ + /*unbind events, reset content position, hide scrollbars, remove classes*/ + mCustomScrollBox.unbind("mousewheel focusin"); + if($this.data("horizontalScroll")){ + mCSB_dragger.add(mCSB_container).css("left",0); + }else{ + mCSB_dragger.add(mCSB_container).css("top",0); + } + if ($this.data("alwaysShowScrollbar")) { + if(!$this.data("horizontalScroll")){ /*vertical scrolling*/ + mCSB_dragger.css({"height":mCSB_draggerContainer.height()}); + }else if($this.data("horizontalScroll")){ /*horizontal scrolling*/ + mCSB_dragger.css({"width":mCSB_draggerContainer.width()}); + } + } else { + mCSB_scrollTools.css("display","none"); + mCSB_container.addClass("mCS_no_scrollbar"); + } + $this.data({"bindEvent_mousewheel":false,"bindEvent_focusin":false}); + } + }, + scrolling:function(mCustomScrollBox,mCSB_container,mCSB_draggerContainer,mCSB_dragger,mCSB_buttonUp,mCSB_buttonDown,mCSB_buttonLeft,mCSB_buttonRight){ + var $this=$(this); + /*scrollbar drag scrolling*/ + if(!$this.data("bindEvent_scrollbar_drag")){ + var mCSB_draggerDragY,mCSB_draggerDragX, + mCSB_dragger_downEvent,mCSB_dragger_moveEvent,mCSB_dragger_upEvent; + if($.support.pointer){ /*pointer*/ + mCSB_dragger_downEvent="pointerdown"; + mCSB_dragger_moveEvent="pointermove"; + mCSB_dragger_upEvent="pointerup"; + }else if($.support.msPointer){ /*MSPointer*/ + mCSB_dragger_downEvent="MSPointerDown"; + mCSB_dragger_moveEvent="MSPointerMove"; + mCSB_dragger_upEvent="MSPointerUp"; + } + if($.support.pointer || $.support.msPointer){ /*pointer, MSPointer*/ + mCSB_dragger.bind(mCSB_dragger_downEvent,function(e){ + e.preventDefault(); + $this.data({"on_drag":true}); mCSB_dragger.addClass("mCSB_dragger_onDrag"); + var elem=$(this), + elemOffset=elem.offset(), + x=e.originalEvent.pageX-elemOffset.left, + y=e.originalEvent.pageY-elemOffset.top; + if(x<elem.width() && x>0 && y<elem.height() && y>0){ + mCSB_draggerDragY=y; + mCSB_draggerDragX=x; + } + }); + $(document).bind(mCSB_dragger_moveEvent+"."+$this.data("mCustomScrollbarIndex"),function(e){ + e.preventDefault(); + if($this.data("on_drag")){ + var elem=mCSB_dragger, + elemOffset=elem.offset(), + x=e.originalEvent.pageX-elemOffset.left, + y=e.originalEvent.pageY-elemOffset.top; + scrollbarDrag(mCSB_draggerDragY,mCSB_draggerDragX,y,x); + } + }).bind(mCSB_dragger_upEvent+"."+$this.data("mCustomScrollbarIndex"),function(e){ + $this.data({"on_drag":false}); mCSB_dragger.removeClass("mCSB_dragger_onDrag"); + }); + }else{ /*mouse/touch*/ + mCSB_dragger.bind("mousedown touchstart",function(e){ + e.preventDefault(); e.stopImmediatePropagation(); + var elem=$(this),elemOffset=elem.offset(),x,y; + if(e.type==="touchstart"){ + var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; + x=touch.pageX-elemOffset.left; y=touch.pageY-elemOffset.top; + }else{ + $this.data({"on_drag":true}); mCSB_dragger.addClass("mCSB_dragger_onDrag"); + x=e.pageX-elemOffset.left; y=e.pageY-elemOffset.top; + } + if(x<elem.width() && x>0 && y<elem.height() && y>0){ + mCSB_draggerDragY=y; mCSB_draggerDragX=x; + } + }).bind("touchmove",function(e){ + e.preventDefault(); e.stopImmediatePropagation(); + var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0], + elem=$(this), + elemOffset=elem.offset(), + x=touch.pageX-elemOffset.left, + y=touch.pageY-elemOffset.top; + scrollbarDrag(mCSB_draggerDragY,mCSB_draggerDragX,y,x); + }); + $(document).bind("mousemove."+$this.data("mCustomScrollbarIndex"),function(e){ + if($this.data("on_drag")){ + var elem=mCSB_dragger, + elemOffset=elem.offset(), + x=e.pageX-elemOffset.left, + y=e.pageY-elemOffset.top; + scrollbarDrag(mCSB_draggerDragY,mCSB_draggerDragX,y,x); + } + }).bind("mouseup."+$this.data("mCustomScrollbarIndex"),function(e){ + $this.data({"on_drag":false}); mCSB_dragger.removeClass("mCSB_dragger_onDrag"); + }); + } + $this.data({"bindEvent_scrollbar_drag":true}); + } + function scrollbarDrag(mCSB_draggerDragY,mCSB_draggerDragX,y,x){ + if($this.data("horizontalScroll")){ + $this.mCustomScrollbar("scrollTo",(mCSB_dragger.position().left-(mCSB_draggerDragX))+x,{moveDragger:true,trigger:"internal"}); + }else{ + $this.mCustomScrollbar("scrollTo",(mCSB_dragger.position().top-(mCSB_draggerDragY))+y,{moveDragger:true,trigger:"internal"}); + } + } + /*content touch-drag*/ + if($.support.touch && $this.data("contentTouchScroll")){ + if(!$this.data("bindEvent_content_touch")){ + var touch, + elem,elemOffset,y,x,mCSB_containerTouchY,mCSB_containerTouchX; + mCSB_container.bind("touchstart",function(e){ + e.stopImmediatePropagation(); + touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; + elem=$(this); + elemOffset=elem.offset(); + x=touch.pageX-elemOffset.left; + y=touch.pageY-elemOffset.top; + mCSB_containerTouchY=y; + mCSB_containerTouchX=x; + }); + mCSB_container.bind("touchmove",function(e){ + e.preventDefault(); e.stopImmediatePropagation(); + touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; + elem=$(this).parent(); + elemOffset=elem.offset(); + x=touch.pageX-elemOffset.left; + y=touch.pageY-elemOffset.top; + if($this.data("horizontalScroll")){ + $this.mCustomScrollbar("scrollTo",mCSB_containerTouchX-x,{trigger:"internal"}); + }else{ + $this.mCustomScrollbar("scrollTo",mCSB_containerTouchY-y,{trigger:"internal"}); + } + }); + } + } + /*dragger rail click scrolling*/ + if(!$this.data("bindEvent_scrollbar_click")){ + mCSB_draggerContainer.bind("click",function(e){ + var scrollToPos=(e.pageY-mCSB_draggerContainer.offset().top)*$this.data("scrollAmount"),target=$(e.target); + if($this.data("horizontalScroll")){ + scrollToPos=(e.pageX-mCSB_draggerContainer.offset().left)*$this.data("scrollAmount"); + } + if(target.hasClass("mCSB_draggerContainer") || target.hasClass("mCSB_draggerRail")){ + $this.mCustomScrollbar("scrollTo",scrollToPos,{trigger:"internal",scrollEasing:"draggerRailEase"}); + } + }); + $this.data({"bindEvent_scrollbar_click":true}); + } + /*mousewheel scrolling*/ + if($this.data("mouseWheel")){ + if(!$this.data("bindEvent_mousewheel")){ + mCustomScrollBox.bind("mousewheel",function(e,delta){ + var scrollTo,mouseWheelPixels=$this.data("mouseWheelPixels"),absPos=Math.abs(mCSB_container.position().top), + draggerPos=mCSB_dragger.position().top,limit=mCSB_draggerContainer.height()-mCSB_dragger.height(); + if($this.data("normalizeMouseWheelDelta")){ + if(delta<0){delta=-1;}else{delta=1;} + } + if(mouseWheelPixels==="auto"){ + mouseWheelPixels=100+Math.round($this.data("scrollAmount")/2); + } + if($this.data("horizontalScroll")){ + draggerPos=mCSB_dragger.position().left; + limit=mCSB_draggerContainer.width()-mCSB_dragger.width(); + absPos=Math.abs(mCSB_container.position().left); + } + if((delta>0 && draggerPos!==0) || (delta<0 && draggerPos!==limit)){e.preventDefault(); e.stopImmediatePropagation();} + scrollTo=absPos-(delta*mouseWheelPixels); + $this.mCustomScrollbar("scrollTo",scrollTo,{trigger:"internal"}); + }); + $this.data({"bindEvent_mousewheel":true}); + } + } + /*buttons scrolling*/ + if($this.data("scrollButtons_enable")){ + if($this.data("scrollButtons_scrollType")==="pixels"){ /*scroll by pixels*/ + if($this.data("horizontalScroll")){ + mCSB_buttonRight.add(mCSB_buttonLeft).unbind("mousedown touchstart MSPointerDown pointerdown mouseup MSPointerUp pointerup mouseout MSPointerOut pointerout touchend",mCSB_buttonRight_stop,mCSB_buttonLeft_stop); + $this.data({"bindEvent_buttonsContinuous_x":false}); + if(!$this.data("bindEvent_buttonsPixels_x")){ + /*scroll right*/ + mCSB_buttonRight.bind("click",function(e){ + e.preventDefault(); + PixelsScrollTo(Math.abs(mCSB_container.position().left)+$this.data("scrollButtons_scrollAmount")); + }); + /*scroll left*/ + mCSB_buttonLeft.bind("click",function(e){ + e.preventDefault(); + PixelsScrollTo(Math.abs(mCSB_container.position().left)-$this.data("scrollButtons_scrollAmount")); + }); + $this.data({"bindEvent_buttonsPixels_x":true}); + } + }else{ + mCSB_buttonDown.add(mCSB_buttonUp).unbind("mousedown touchstart MSPointerDown pointerdown mouseup MSPointerUp pointerup mouseout MSPointerOut pointerout touchend",mCSB_buttonRight_stop,mCSB_buttonLeft_stop); + $this.data({"bindEvent_buttonsContinuous_y":false}); + if(!$this.data("bindEvent_buttonsPixels_y")){ + /*scroll down*/ + mCSB_buttonDown.bind("click",function(e){ + e.preventDefault(); + PixelsScrollTo(Math.abs(mCSB_container.position().top)+$this.data("scrollButtons_scrollAmount")); + }); + /*scroll up*/ + mCSB_buttonUp.bind("click",function(e){ + e.preventDefault(); + PixelsScrollTo(Math.abs(mCSB_container.position().top)-$this.data("scrollButtons_scrollAmount")); + }); + $this.data({"bindEvent_buttonsPixels_y":true}); + } + } + function PixelsScrollTo(to){ + if(!mCSB_dragger.data("preventAction")){ + mCSB_dragger.data("preventAction",true); + $this.mCustomScrollbar("scrollTo",to,{trigger:"internal"}); + } + } + }else{ /*continuous scrolling*/ + if($this.data("horizontalScroll")){ + mCSB_buttonRight.add(mCSB_buttonLeft).unbind("click"); + $this.data({"bindEvent_buttonsPixels_x":false}); + if(!$this.data("bindEvent_buttonsContinuous_x")){ + /*scroll right*/ + mCSB_buttonRight.bind("mousedown touchstart MSPointerDown pointerdown",function(e){ + e.preventDefault(); + var scrollButtonsSpeed=ScrollButtonsSpeed(); + $this.data({"mCSB_buttonScrollRight":setInterval(function(){ + $this.mCustomScrollbar("scrollTo",Math.abs(mCSB_container.position().left)+scrollButtonsSpeed,{trigger:"internal",scrollEasing:"easeOutCirc"}); + },17)}); + }); + var mCSB_buttonRight_stop=function(e){ + e.preventDefault(); clearInterval($this.data("mCSB_buttonScrollRight")); + } + mCSB_buttonRight.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout",mCSB_buttonRight_stop); + /*scroll left*/ + mCSB_buttonLeft.bind("mousedown touchstart MSPointerDown pointerdown",function(e){ + e.preventDefault(); + var scrollButtonsSpeed=ScrollButtonsSpeed(); + $this.data({"mCSB_buttonScrollLeft":setInterval(function(){ + $this.mCustomScrollbar("scrollTo",Math.abs(mCSB_container.position().left)-scrollButtonsSpeed,{trigger:"internal",scrollEasing:"easeOutCirc"}); + },17)}); + }); + var mCSB_buttonLeft_stop=function(e){ + e.preventDefault(); clearInterval($this.data("mCSB_buttonScrollLeft")); + } + mCSB_buttonLeft.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout",mCSB_buttonLeft_stop); + $this.data({"bindEvent_buttonsContinuous_x":true}); + } + }else{ + mCSB_buttonDown.add(mCSB_buttonUp).unbind("click"); + $this.data({"bindEvent_buttonsPixels_y":false}); + if(!$this.data("bindEvent_buttonsContinuous_y")){ + /*scroll down*/ + mCSB_buttonDown.bind("mousedown touchstart MSPointerDown pointerdown",function(e){ + e.preventDefault(); + var scrollButtonsSpeed=ScrollButtonsSpeed(); + $this.data({"mCSB_buttonScrollDown":setInterval(function(){ + $this.mCustomScrollbar("scrollTo",Math.abs(mCSB_container.position().top)+scrollButtonsSpeed,{trigger:"internal",scrollEasing:"easeOutCirc"}); + },17)}); + }); + var mCSB_buttonDown_stop=function(e){ + e.preventDefault(); clearInterval($this.data("mCSB_buttonScrollDown")); + } + mCSB_buttonDown.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout",mCSB_buttonDown_stop); + /*scroll up*/ + mCSB_buttonUp.bind("mousedown touchstart MSPointerDown pointerdown",function(e){ + e.preventDefault(); + var scrollButtonsSpeed=ScrollButtonsSpeed(); + $this.data({"mCSB_buttonScrollUp":setInterval(function(){ + $this.mCustomScrollbar("scrollTo",Math.abs(mCSB_container.position().top)-scrollButtonsSpeed,{trigger:"internal",scrollEasing:"easeOutCirc"}); + },17)}); + }); + var mCSB_buttonUp_stop=function(e){ + e.preventDefault(); clearInterval($this.data("mCSB_buttonScrollUp")); + } + mCSB_buttonUp.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout",mCSB_buttonUp_stop); + $this.data({"bindEvent_buttonsContinuous_y":true}); + } + } + function ScrollButtonsSpeed(){ + var speed=$this.data("scrollButtons_scrollSpeed"); + if($this.data("scrollButtons_scrollSpeed")==="auto"){ + speed=Math.round(($this.data("scrollInertia")+100)/40); + } + return speed; + } + } + } + /*scrolling on element focus (e.g. via TAB key)*/ + if($this.data("autoScrollOnFocus")){ + if(!$this.data("bindEvent_focusin")){ + mCustomScrollBox.bind("focusin",function(){ + mCustomScrollBox.scrollTop(0).scrollLeft(0); + var focusedElem=$(document.activeElement); + if(focusedElem.is("input,textarea,select,button,a[tabindex],area,object")){ + var mCSB_containerPos=mCSB_container.position().top, + focusedElemPos=focusedElem.position().top, + visibleLimit=mCustomScrollBox.height()-focusedElem.outerHeight(); + if($this.data("horizontalScroll")){ + mCSB_containerPos=mCSB_container.position().left; + focusedElemPos=focusedElem.position().left; + visibleLimit=mCustomScrollBox.width()-focusedElem.outerWidth(); + } + if(mCSB_containerPos+focusedElemPos<0 || mCSB_containerPos+focusedElemPos>visibleLimit){ + $this.mCustomScrollbar("scrollTo",focusedElemPos,{trigger:"internal"}); + } + } + }); + $this.data({"bindEvent_focusin":true}); + } + } + /*auto-hide scrollbar*/ + if($this.data("autoHideScrollbar") && !$this.data("alwaysShowScrollbar")){ + if(!$this.data("bindEvent_autoHideScrollbar")){ + mCustomScrollBox.bind("mouseenter",function(e){ + mCustomScrollBox.addClass("mCS-mouse-over"); + functions.showScrollbar.call(mCustomScrollBox.children(".mCSB_scrollTools")); + }).bind("mouseleave touchend",function(e){ + mCustomScrollBox.removeClass("mCS-mouse-over"); + if(e.type==="mouseleave"){functions.hideScrollbar.call(mCustomScrollBox.children(".mCSB_scrollTools"));} + }); + $this.data({"bindEvent_autoHideScrollbar":true}); + } + } + }, + scrollTo:function(scrollTo,options){ + var $this=$(this), + defaults={ + moveDragger:false, + trigger:"external", + callbacks:true, + scrollInertia:$this.data("scrollInertia"), + scrollEasing:$this.data("scrollEasing") + }, + options=$.extend(defaults,options), + draggerScrollTo, + mCustomScrollBox=$this.children(".mCustomScrollBox"), + mCSB_container=mCustomScrollBox.children(".mCSB_container"), + mCSB_scrollTools=mCustomScrollBox.children(".mCSB_scrollTools"), + mCSB_draggerContainer=mCSB_scrollTools.children(".mCSB_draggerContainer"), + mCSB_dragger=mCSB_draggerContainer.children(".mCSB_dragger"), + contentSpeed=draggerSpeed=options.scrollInertia, + scrollBeginning,scrollBeginningOffset,totalScroll,totalScrollOffset; + if(!mCSB_container.hasClass("mCS_no_scrollbar")){ + $this.data({"mCS_trigger":options.trigger}); + if($this.data("mCS_Init")){options.callbacks=false;} + if(scrollTo || scrollTo===0){ + if(typeof(scrollTo)==="number"){ /*if integer, scroll by number of pixels*/ + if(options.moveDragger){ /*scroll dragger*/ + draggerScrollTo=scrollTo; + if($this.data("horizontalScroll")){ + scrollTo=mCSB_dragger.position().left*$this.data("scrollAmount"); + }else{ + scrollTo=mCSB_dragger.position().top*$this.data("scrollAmount"); + } + draggerSpeed=0; + }else{ /*scroll content by default*/ + draggerScrollTo=scrollTo/$this.data("scrollAmount"); + } + }else if(typeof(scrollTo)==="string"){ /*if string, scroll by element position*/ + var target; + if(scrollTo==="top"){ /*scroll to top*/ + target=0; + }else if(scrollTo==="bottom" && !$this.data("horizontalScroll")){ /*scroll to bottom*/ + target=mCSB_container.outerHeight()-mCustomScrollBox.height(); + }else if(scrollTo==="left"){ /*scroll to left*/ + target=0; + }else if(scrollTo==="right" && $this.data("horizontalScroll")){ /*scroll to right*/ + target=mCSB_container.outerWidth()-mCustomScrollBox.width(); + }else if(scrollTo==="first"){ /*scroll to first element position*/ + target=$this.find(".mCSB_container").find(":first"); + }else if(scrollTo==="last"){ /*scroll to last element position*/ + target=$this.find(".mCSB_container").find(":last"); + }else{ /*scroll to element position*/ + target=$this.find(scrollTo); + } + if(target.length===1){ /*if such unique element exists, scroll to it*/ + if($this.data("horizontalScroll")){ + scrollTo=target.position().left; + }else{ + scrollTo=target.position().top; + } + draggerScrollTo=scrollTo/$this.data("scrollAmount"); + }else{ + draggerScrollTo=scrollTo=target; + } + } + /*scroll to*/ + if($this.data("horizontalScroll")){ + if($this.data("onTotalScrollBack_Offset")){ /*scroll beginning offset*/ + scrollBeginningOffset=-$this.data("onTotalScrollBack_Offset"); + } + if($this.data("onTotalScroll_Offset")){ /*total scroll offset*/ + totalScrollOffset=mCustomScrollBox.width()-mCSB_container.outerWidth()+$this.data("onTotalScroll_Offset"); + } + if(draggerScrollTo<0){ /*scroll start position*/ + draggerScrollTo=scrollTo=0; clearInterval($this.data("mCSB_buttonScrollLeft")); + if(!scrollBeginningOffset){scrollBeginning=true;} + }else if(draggerScrollTo>=mCSB_draggerContainer.width()-mCSB_dragger.width()){ /*scroll end position*/ + draggerScrollTo=mCSB_draggerContainer.width()-mCSB_dragger.width(); + scrollTo=mCustomScrollBox.width()-mCSB_container.outerWidth(); clearInterval($this.data("mCSB_buttonScrollRight")); + if(!totalScrollOffset){totalScroll=true;} + }else{scrollTo=-scrollTo;} + var snapAmount = $this.data("snapAmount"); + if (snapAmount) { + scrollTo = Math.round(scrollTo / snapAmount) * snapAmount - $this.data("snapOffset"); + } + /*scrolling animation*/ + functions.mTweenAxis.call(this,mCSB_dragger[0],"left",Math.round(draggerScrollTo),draggerSpeed,options.scrollEasing); + functions.mTweenAxis.call(this,mCSB_container[0],"left",Math.round(scrollTo),contentSpeed,options.scrollEasing,{ + onStart:function(){ + if(options.callbacks && !$this.data("mCS_tweenRunning")){callbacks("onScrollStart");} + if($this.data("autoHideScrollbar") && !$this.data("alwaysShowScrollbar")){functions.showScrollbar.call(mCSB_scrollTools);} + }, + onUpdate:function(){ + if(options.callbacks){callbacks("whileScrolling");} + }, + onComplete:function(){ + if(options.callbacks){ + callbacks("onScroll"); + if(scrollBeginning || (scrollBeginningOffset && mCSB_container.position().left>=scrollBeginningOffset)){callbacks("onTotalScrollBack");} + if(totalScroll || (totalScrollOffset && mCSB_container.position().left<=totalScrollOffset)){callbacks("onTotalScroll");} + } + mCSB_dragger.data("preventAction",false); $this.data("mCS_tweenRunning",false); + if($this.data("autoHideScrollbar") && !$this.data("alwaysShowScrollbar")){if(!mCustomScrollBox.hasClass("mCS-mouse-over")){functions.hideScrollbar.call(mCSB_scrollTools);}} + } + }); + }else{ + if($this.data("onTotalScrollBack_Offset")){ /*scroll beginning offset*/ + scrollBeginningOffset=-$this.data("onTotalScrollBack_Offset"); + } + if($this.data("onTotalScroll_Offset")){ /*total scroll offset*/ + totalScrollOffset=mCustomScrollBox.height()-mCSB_container.outerHeight()+$this.data("onTotalScroll_Offset"); + } + if(draggerScrollTo<0){ /*scroll start position*/ + draggerScrollTo=scrollTo=0; clearInterval($this.data("mCSB_buttonScrollUp")); + if(!scrollBeginningOffset){scrollBeginning=true;} + }else if(draggerScrollTo>=mCSB_draggerContainer.height()-mCSB_dragger.height()){ /*scroll end position*/ + draggerScrollTo=mCSB_draggerContainer.height()-mCSB_dragger.height(); + scrollTo=mCustomScrollBox.height()-mCSB_container.outerHeight(); clearInterval($this.data("mCSB_buttonScrollDown")); + if(!totalScrollOffset){totalScroll=true;} + }else{scrollTo=-scrollTo;} + var snapAmount = $this.data("snapAmount"); + if (snapAmount) { + scrollTo = Math.round(scrollTo / snapAmount) * snapAmount - $this.data("snapOffset"); + } + /*scrolling animation*/ + functions.mTweenAxis.call(this,mCSB_dragger[0],"top",Math.round(draggerScrollTo),draggerSpeed,options.scrollEasing); + functions.mTweenAxis.call(this,mCSB_container[0],"top",Math.round(scrollTo),contentSpeed,options.scrollEasing,{ + onStart:function(){ + if(options.callbacks && !$this.data("mCS_tweenRunning")){callbacks("onScrollStart");} + if($this.data("autoHideScrollbar") && !$this.data("alwaysShowScrollbar")){functions.showScrollbar.call(mCSB_scrollTools);} + }, + onUpdate:function(){ + if(options.callbacks){callbacks("whileScrolling");} + }, + onComplete:function(){ + if(options.callbacks){ + callbacks("onScroll"); + if(scrollBeginning || (scrollBeginningOffset && mCSB_container.position().top>=scrollBeginningOffset)){callbacks("onTotalScrollBack");} + if(totalScroll || (totalScrollOffset && mCSB_container.position().top<=totalScrollOffset)){callbacks("onTotalScroll");} + } + mCSB_dragger.data("preventAction",false); $this.data("mCS_tweenRunning",false); + if($this.data("autoHideScrollbar") && !$this.data("alwaysShowScrollbar")){if(!mCustomScrollBox.hasClass("mCS-mouse-over")){functions.hideScrollbar.call(mCSB_scrollTools);}} + } + }); + } + if($this.data("mCS_Init")){$this.data({"mCS_Init":false});} + } + } + /*callbacks*/ + function callbacks(cb){ + if ($this.data("mCustomScrollbarIndex")) { + this.mcs = { + top: mCSB_container.position().top, left: mCSB_container.position().left, + draggerTop: mCSB_dragger.position().top, draggerLeft: mCSB_dragger.position().left, + topPct: Math.round((100 * Math.abs(mCSB_container.position().top)) / Math.abs(mCSB_container.outerHeight() - mCustomScrollBox.height())), + leftPct: Math.round((100 * Math.abs(mCSB_container.position().left)) / Math.abs(mCSB_container.outerWidth() - mCustomScrollBox.width())) + }; + switch (cb) { + /*start scrolling callback*/ + case "onScrollStart": + $this.data("mCS_tweenRunning", true).data("onScrollStart_Callback").call($this, this.mcs); + break; + case "whileScrolling": + $this.data("whileScrolling_Callback").call($this, this.mcs); + break; + case "onScroll": + $this.data("onScroll_Callback").call($this, this.mcs); + break; + case "onTotalScrollBack": + $this.data("onTotalScrollBack_Callback").call($this, this.mcs); + break; + case "onTotalScroll": + $this.data("onTotalScroll_Callback").call($this, this.mcs); + break; + } + } + } + }, + stop:function(){ + var $this=$(this), + mCSB_container=$this.children().children(".mCSB_container"), + mCSB_dragger=$this.children().children().children().children(".mCSB_dragger"); + functions.mTweenAxisStop.call(this,mCSB_container[0]); + functions.mTweenAxisStop.call(this,mCSB_dragger[0]); + }, + disable:function(resetScroll){ + var $this=$(this), + mCustomScrollBox=$this.children(".mCustomScrollBox"), + mCSB_container=mCustomScrollBox.children(".mCSB_container"), + mCSB_scrollTools=mCustomScrollBox.children(".mCSB_scrollTools"), + mCSB_dragger=mCSB_scrollTools.children().children(".mCSB_dragger"); + mCustomScrollBox.unbind("mousewheel focusin mouseenter mouseleave touchend"); + mCSB_container.unbind("touchstart touchmove") + if(resetScroll){ + if($this.data("horizontalScroll")){ + mCSB_dragger.add(mCSB_container).css("left",0); + }else{ + mCSB_dragger.add(mCSB_container).css("top",0); + } + } + mCSB_scrollTools.css("display","none"); + mCSB_container.addClass("mCS_no_scrollbar"); + $this.data({"bindEvent_mousewheel":false,"bindEvent_focusin":false,"bindEvent_content_touch":false,"bindEvent_autoHideScrollbar":false}).addClass("mCS_disabled"); + }, + destroy:function(){ + var $this=$(this); + $this.removeClass("mCustomScrollbar _mCS_"+$this.data("mCustomScrollbarIndex")).addClass("mCS_destroyed").children().children(".mCSB_container").unwrap().children().unwrap().siblings(".mCSB_scrollTools").remove(); + $(document).unbind("mousemove."+$this.data("mCustomScrollbarIndex")+" mouseup."+$this.data("mCustomScrollbarIndex")+" MSPointerMove."+$this.data("mCustomScrollbarIndex")+" MSPointerUp."+$this.data("mCustomScrollbarIndex")); + $(window).unbind("resize."+$this.data("mCustomScrollbarIndex")); + } + }, + functions={ + /*hide/show scrollbar*/ + showScrollbar:function(){ + this.stop().animate({opacity:1},"fast"); + }, + hideScrollbar:function(){ + this.stop().animate({opacity:0},"fast"); + }, + /*js animation tween*/ + mTweenAxis:function(el,prop,to,duration,easing,callbacks){ + var callbacks=callbacks || {}, + onStart=callbacks.onStart || function(){},onUpdate=callbacks.onUpdate || function(){},onComplete=callbacks.onComplete || function(){}; + var startTime=_getTime(),_delay,progress=0,from=el.offsetTop,elStyle=el.style; + if(prop==="left"){from=el.offsetLeft;} + var diff=to-from; + _cancelTween(); + _startTween(); + function _getTime(){ + if(window.performance && window.performance.now){ + return window.performance.now(); + }else{ + if(window.performance && window.performance.webkitNow){ + return window.performance.webkitNow(); + }else{ + if(Date.now){return Date.now();}else{return new Date().getTime();} + } + } + } + function _step(){ + if(!progress){onStart.call();} + progress=_getTime()-startTime; + _tween(); + if(progress>=el._time){ + el._time=(progress>el._time) ? progress+_delay-(progress- el._time) : progress+_delay-1; + if(el._time<progress+1){el._time=progress+1;} + } + if(el._time<duration){el._id=_request(_step);}else{onComplete.call();} + } + function _tween(){ + if(duration>0){ + el.currVal=_ease(el._time,from,diff,duration,easing); + elStyle[prop]=Math.round(el.currVal)+"px"; + }else{ + elStyle[prop]=to+"px"; + } + onUpdate.call(); + } + function _startTween(){ + _delay=1000/60; + el._time=progress+_delay; + _request=(!window.requestAnimationFrame) ? function(f){_tween(); return setTimeout(f,0.01);} : window.requestAnimationFrame; + el._id=_request(_step); + } + function _cancelTween(){ + if(el._id==null){return;} + if(!window.requestAnimationFrame){clearTimeout(el._id); + }else{window.cancelAnimationFrame(el._id);} + el._id=null; + } + function _ease(t,b,c,d,type){ + switch(type){ + case "linear": + return c*t/d + b; + break; + case "easeOutQuad": + t /= d; return -c * t*(t-2) + b; + break; + case "easeInOutQuad": + t /= d/2; + if (t < 1) return c/2*t*t + b; + t--; + return -c/2 * (t*(t-2) - 1) + b; + break; + case "easeOutCubic": + t /= d; t--; return c*(t*t*t + 1) + b; + break; + case "easeOutQuart": + t /= d; t--; return -c * (t*t*t*t - 1) + b; + break; + case "easeOutQuint": + t /= d; t--; return c*(t*t*t*t*t + 1) + b; + break; + case "easeOutCirc": + t /= d; t--; return c * Math.sqrt(1 - t*t) + b; + break; + case "easeOutSine": + return c * Math.sin(t/d * (Math.PI/2)) + b; + break; + case "easeOutExpo": + return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b; + break; + case "mcsEaseOut": + var ts=(t/=d)*t,tc=ts*t; + return b+c*(0.499999999999997*tc*ts + -2.5*ts*ts + 5.5*tc + -6.5*ts + 4*t); + break; + case "draggerRailEase": + t /= d/2; + if (t < 1) return c/2*t*t*t + b; + t -= 2; + return c/2*(t*t*t + 2) + b; + break; + } + } + }, + /*stop js animation tweens*/ + mTweenAxisStop:function(el){ + if(el._id==null){return;} + if(!window.requestAnimationFrame){clearTimeout(el._id); + }else{window.cancelAnimationFrame(el._id);} + el._id=null; + }, + /*detect requestAnimationFrame and polyfill*/ + rafPolyfill:function(){ + var pfx=["ms","moz","webkit","o"],i=pfx.length; + while(--i > -1 && !window.requestAnimationFrame){ + window.requestAnimationFrame=window[pfx[i]+"RequestAnimationFrame"]; + window.cancelAnimationFrame=window[pfx[i]+"CancelAnimationFrame"] || window[pfx[i]+"CancelRequestAnimationFrame"]; + } + } + } + /*detect features*/ + functions.rafPolyfill.call(); /*requestAnimationFrame*/ + $.support.touch=!!('ontouchstart' in window); /*touch*/ + $.support.pointer=window.navigator.pointerEnabled; /*pointer support*/ + $.support.msPointer=window.navigator.msPointerEnabled; /*MSPointer support*/ + /*plugin dependencies*/ + var _dlp=("https:"==document.location.protocol) ? "https:" : "http:"; + $.event.special.mousewheel || document.write('<script src="'+_dlp+'//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.0.6/jquery.mousewheel.min.js"><\/script>'); + /*plugin fn*/ + $.fn.mCustomScrollbar=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"); + } + }; +})(jQuery); \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/js/jqxcore.js b/src/static/movio/templates/Sliding-windows/js/jqxcore.js new file mode 100644 index 0000000..bb80d30 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/js/jqxcore.js @@ -0,0 +1,7 @@ +/* +jQWidgets v3.5.0 (2014-Sep-15) +Copyright (c) 2011-2014 jQWidgets. +License: http://jqwidgets.com/license/ +*/ + +var jqxBaseFramework=window.minQuery||window.jQuery;(function(a){a.jqx=a.jqx||{};a.jqx.define=function(b,c,d){b[c]=function(){if(this.baseType){this.base=new b[this.baseType]();this.base.defineInstance()}this.defineInstance()};b[c].prototype.defineInstance=function(){};b[c].prototype.base=null;b[c].prototype.baseType=undefined;if(d&&b[d]){b[c].prototype.baseType=d}};a.jqx.invoke=function(e,d){if(d.length==0){return}var f=typeof(d)==Array||d.length>0?d[0]:d;var c=typeof(d)==Array||d.length>1?Array.prototype.slice.call(d,1):a({}).toArray();while(e[f]==undefined&&e.base!=null){if(e[f]!=undefined&&a.isFunction(e[f])){return e[f].apply(e,c)}if(typeof f=="string"){var b=f.toLowerCase();if(e[b]!=undefined&&a.isFunction(e[b])){return e[b].apply(e,c)}}e=e.base}if(e[f]!=undefined&&a.isFunction(e[f])){return e[f].apply(e,c)}if(typeof f=="string"){var b=f.toLowerCase();if(e[b]!=undefined&&a.isFunction(e[b])){return e[b].apply(e,c)}}return};a.jqx.hasProperty=function(c,b){if(typeof(b)=="object"){for(var e in b){var d=c;while(d){if(d.hasOwnProperty(e)){return true}if(d.hasOwnProperty(e.toLowerCase())){return true}d=d.base}return false}}else{while(c){if(c.hasOwnProperty(b)){return true}if(c.hasOwnProperty(b.toLowerCase())){return true}c=c.base}}return false};a.jqx.hasFunction=function(e,d){if(d.length==0){return false}if(e==undefined){return false}var f=typeof(d)==Array||d.length>0?d[0]:d;var c=typeof(d)==Array||d.length>1?Array.prototype.slice.call(d,1):{};while(e[f]==undefined&&e.base!=null){if(e[f]&&a.isFunction(e[f])){return true}if(typeof f=="string"){var b=f.toLowerCase();if(e[b]&&a.isFunction(e[b])){return true}}e=e.base}if(e[f]&&a.isFunction(e[f])){return true}if(typeof f=="string"){var b=f.toLowerCase();if(e[b]&&a.isFunction(e[b])){return true}}return false};a.jqx.isPropertySetter=function(c,b){if(b.length==1&&typeof(b[0])=="object"){return true}if(b.length==2&&typeof(b[0])=="string"&&!a.jqx.hasFunction(c,b)){return true}return false};a.jqx.validatePropertySetter=function(f,d,b){if(!a.jqx.propertySetterValidation){return true}if(d.length==1&&typeof(d[0])=="object"){for(var e in d[0]){var g=f;while(!g.hasOwnProperty(e)&&g.base){g=g.base}if(!g||!g.hasOwnProperty(e)){if(!b){var c=g.hasOwnProperty(e.toString().toLowerCase());if(!c){throw"Invalid property: "+e}else{return true}}return false}}return true}if(d.length!=2){if(!b){throw"Invalid property: "+d.length>=0?d[0]:""}return false}while(!f.hasOwnProperty(d[0])&&f.base){f=f.base}if(!f||!f.hasOwnProperty(d[0])){if(!b){throw"Invalid property: "+d[0]}return false}return true};a.jqx.set=function(c,b){if(b.length==1&&typeof(b[0])=="object"){a.each(b[0],function(d,e){var f=c;while(!f.hasOwnProperty(d)&&f.base!=null){f=f.base}if(f.hasOwnProperty(d)){a.jqx.setvalueraiseevent(f,d,e)}else{if(f.hasOwnProperty(d.toLowerCase())){a.jqx.setvalueraiseevent(f,d.toLowerCase(),e)}else{if(a.jqx.propertySetterValidation){throw"jqxCore: invalid property '"+d+"'"}}}})}else{if(b.length==2){while(!c.hasOwnProperty(b[0])&&c.base){c=c.base}if(c.hasOwnProperty(b[0])){a.jqx.setvalueraiseevent(c,b[0],b[1])}else{if(c.hasOwnProperty(b[0].toLowerCase())){a.jqx.setvalueraiseevent(c,b[0].toLowerCase(),b[1])}else{if(a.jqx.propertySetterValidation){throw"jqxCore: invalid property '"+b[0]+"'"}}}}}};a.jqx.setvalueraiseevent=function(c,d,e){var b=c[d];c[d]=e;if(!c.isInitialized){return}if(c.propertyChangedHandler!=undefined){c.propertyChangedHandler(c,d,b,e)}if(c.propertyChangeMap!=undefined&&c.propertyChangeMap[d]!=undefined){c.propertyChangeMap[d](c,d,b,e)}};a.jqx.get=function(e,d){if(d==undefined||d==null){return undefined}if(e.propertyMap){var c=e.propertyMap(d);if(c!=null){return c}}if(e.hasOwnProperty(d)){return e[d]}if(e.hasOwnProperty(d.toLowerCase())){return e[d.toLowerCase()]}var b=undefined;if(typeof(d)==Array){if(d.length!=1){return undefined}b=d[0]}else{if(typeof(d)=="string"){b=d}}while(!e.hasOwnProperty(b)&&e.base){e=e.base}if(e){return e[b]}return undefined};a.jqx.serialize=function(e){var b="";if(a.isArray(e)){b="[";for(var d=0;d<e.length;d++){if(d>0){b+=", "}b+=a.jqx.serialize(e[d])}b+="]"}else{if(typeof(e)=="object"){b="{";var c=0;for(var d in e){if(c++>0){b+=", "}b+=d+": "+a.jqx.serialize(e[d])}b+="}"}else{b=e.toString()}}return b};a.jqx.propertySetterValidation=true;a.jqx.jqxWidgetProxy=function(g,c,b){var d=a(c);var f=a.data(c,g);if(f==undefined){return undefined}var e=f.instance;if(a.jqx.hasFunction(e,b)){return a.jqx.invoke(e,b)}if(a.jqx.isPropertySetter(e,b)){if(a.jqx.validatePropertySetter(e,b)){a.jqx.set(e,b);return undefined}}else{if(typeof(b)=="object"&&b.length==0){return}else{if(typeof(b)=="object"&&b.length==1&&a.jqx.hasProperty(e,b[0])){return a.jqx.get(e,b[0])}else{if(typeof(b)=="string"&&a.jqx.hasProperty(e,b[0])){return a.jqx.get(e,b)}}}}throw"jqxCore: Invalid parameter '"+a.jqx.serialize(b)+"' does not exist.";return undefined};a.jqx.applyWidget=function(c,d,k,l){var g=false;try{g=window.MSApp!=undefined}catch(f){}var m=a(c);if(!l){l=new a.jqx["_"+d]()}else{l.host=m;l.element=c}if(c.id==""){c.id=a.jqx.utilities.createId()}var j={host:m,element:c,instance:l};l.widgetName=d;a.data(c,d,j);a.data(c,"jqxWidget",j.instance);var h=new Array();var l=j.instance;while(l){l.isInitialized=false;h.push(l);l=l.base}h.reverse();h[0].theme=a.jqx.theme||"";a.jqx.jqxWidgetProxy(d,c,k);for(var b in h){l=h[b];if(b==0){l.host=m;l.element=c;l.WinJS=g}if(l!=undefined){if(l.definedInstance){l.definedInstance()}if(l.createInstance!=null){if(g){MSApp.execUnsafeLocalFunction(function(){l.createInstance(k)})}else{l.createInstance(k)}}}}for(var b in h){if(h[b]!=undefined){h[b].isInitialized=true}}if(g){MSApp.execUnsafeLocalFunction(function(){j.instance.refresh(true)})}else{j.instance.refresh(true)}};a.jqx.jqxWidget=function(b,d,j){var c=false;try{jqxArgs=Array.prototype.slice.call(j,0)}catch(h){jqxArgs=""}try{c=window.MSApp!=undefined}catch(h){}var g=b;var f="";if(d){f="_"+d}a.jqx.define(a.jqx,"_"+g,f);a.fn[g]=function(){var e=Array.prototype.slice.call(arguments,0);if(e.length==0||(e.length==1&&typeof(e[0])=="object")){if(this.length==0){if(this.selector){throw new Error("Invalid Selector - "+this.selector+"! Please, check whether the used ID or CSS Class name is correct.")}else{throw new Error("Invalid Selector! Please, check whether the used ID or CSS Class name is correct.")}}return this.each(function(){var n=a(this);var m=this;var o=a.data(m,g);if(o==null){a.jqx.applyWidget(m,g,e,undefined)}else{a.jqx.jqxWidgetProxy(g,this,e)}})}else{if(this.length==0){if(this.selector){throw new Error("Invalid Selector - "+this.selector+"! Please, check whether the used ID or CSS Class name is correct.")}else{throw new Error("Invalid Selector! Please, check whether the used ID or CSS Class name is correct.")}}var l=null;var k=0;this.each(function(){var m=a.jqx.jqxWidgetProxy(g,this,e);if(k==0){l=m;k++}else{if(k==1){var n=[];n.push(l);l=n}l.push(m)}})}return l};try{a.extend(a.jqx["_"+g].prototype,Array.prototype.slice.call(j,0)[0])}catch(h){}a.extend(a.jqx["_"+g].prototype,{toThemeProperty:function(e,k){return a.jqx.toThemeProperty(this,e,k)}});a.jqx["_"+g].prototype.refresh=function(){if(this.base){this.base.refresh(true)}};a.jqx["_"+g].prototype.createInstance=function(){};a.jqx["_"+g].prototype.applyTo=function(l,k){if(!(k instanceof Array)){var e=[];e.push(k);k=e}a.jqx.applyWidget(l,g,k,this)};a.jqx["_"+g].prototype.getInstance=function(){return this};a.jqx["_"+g].prototype.propertyChangeMap={};a.jqx["_"+g].prototype.addHandler=function(m,e,k,l){a.jqx.addHandler(m,e,k,l)};a.jqx["_"+g].prototype.removeHandler=function(l,e,k){a.jqx.removeHandler(l,e,k)}};a.jqx.toThemeProperty=function(c,d,h){if(c.theme==""){return d}var g=d.split(" ");var b="";for(var f=0;f<g.length;f++){if(f>0){b+=" "}var e=g[f];if(h!=null&&h){b+=e+"-"+c.theme}else{b+=e+" "+e+"-"+c.theme}}return b};a.jqx.addHandler=function(g,h,e,f){var c=h.split(" ");for(var b=0;b<c.length;b++){var d=c[b];if(window.addEventListener){switch(d){case"mousewheel":if(a.jqx.browser.mozilla){g[0].addEventListener("DOMMouseScroll",e,false)}else{g[0].addEventListener("mousewheel",e,false)}continue;case"mousemove":if(!f){g[0].addEventListener("mousemove",e,false);continue}break}}if(f==undefined||f==null){if(g.on){g.on(d,e)}else{g.bind(d,e)}}else{if(g.on){g.on(d,f,e)}else{g.bind(d,f,e)}}}};a.jqx.removeHandler=function(f,g,e){if(!g){return}var c=g.split(" ");for(var b=0;b<c.length;b++){var d=c[b];if(window.removeEventListener){switch(d){case"mousewheel":if(a.jqx.browser.mozilla){f[0].removeEventListener("DOMMouseScroll",e,false)}else{f[0].removeEventListener("mousewheel",e,false)}continue;case"mousemove":if(e){f[0].removeEventListener("mousemove",e,false);continue}break}}if(d==undefined){if(f.off){f.off()}else{f.unbind()}continue}if(e==undefined){if(f.off){f.off(d)}else{f.unbind(d)}}else{if(f.off){f.off(d,e)}else{f.unbind(d,e)}}}};a.jqx.theme=a.jqx.theme||"";a.jqx.resizeDelay=a.jqx.resizeDelay||10;a.jqx.ready=function(){a(window).trigger("jqxReady")};a.jqx.init=function(){a.each(arguments[0],function(b,c){if(b=="theme"){a.jqx.theme=c}if(b=="scrollBarSize"){a.jqx.utilities.scrollBarSize=c}if(b=="touchScrollBarSize"){a.jqx.utilities.touchScrollBarSize=c}if(b=="scrollBarButtonsVisibility"){a.jqx.utilities.scrollBarButtonsVisibility=c}})};a.jqx.utilities=a.jqx.utilities||{};a.extend(a.jqx.utilities,{scrollBarSize:15,touchScrollBarSize:10,scrollBarButtonsVisibility:"visible",createId:function(){var b=function(){return(((1+Math.random())*65536)|0).toString(16).substring(1)};return"jqxWidget"+b()+b()},setTheme:function(f,g,e){if(typeof e==="undefined"){return}var h=e[0].className.split(" "),b=[],j=[],d=e.children();for(var c=0;c<h.length;c+=1){if(h[c].indexOf(f)>=0){if(f.length>0){b.push(h[c]);j.push(h[c].replace(f,g))}else{j.push(h[c]+"-"+g)}}}this._removeOldClasses(b,e);this._addNewClasses(j,e);for(var c=0;c<d.length;c+=1){this.setTheme(f,g,a(d[c]))}},_removeOldClasses:function(d,c){for(var b=0;b<d.length;b+=1){c.removeClass(d[b])}},_addNewClasses:function(d,c){for(var b=0;b<d.length;b+=1){c.addClass(d[b])}},getOffset:function(b){var d=a.jqx.mobile.getLeftPos(b[0]);var c=a.jqx.mobile.getTopPos(b[0]);return{top:c,left:d}},resize:function(d,m,l,k){if(k===undefined){k=true}var g=-1;var f=this;var c=function(o){if(!f.hiddenWidgets){return -1}var p=-1;for(var n=0;n<f.hiddenWidgets.length;n++){if(o.id){if(f.hiddenWidgets[n].id==o.id){p=n;break}}else{if(f.hiddenWidgets[n].id==o[0].id){p=n;break}}}return p};if(this.resizeHandlers){for(var e=0;e<this.resizeHandlers.length;e++){if(d.id){if(this.resizeHandlers[e].id==d.id){g=e;break}}else{if(this.resizeHandlers[e].id==d[0].id){g=e;break}}}if(l===true){if(g!=-1){this.resizeHandlers.splice(g,1)}if(this.resizeHandlers.length==0){var j=a(window);if(j.off){j.off("resize.jqx");j.off("orientationchange.jqx");j.off("orientationchanged.jqx")}else{j.unbind("resize.jqx");j.unbind("orientationchange.jqx");j.unbind("orientationchanged.jqx")}this.resizeHandlers=null}var b=c(d);if(b!=-1&&this.hiddenWidgets){this.hiddenWidgets.splice(b,1)}return}}else{if(l===true){var b=c(d);if(b!=-1&&this.hiddenWidgets){this.hiddenWidgets.splice(b,1)}return}}var f=this;var h=function(p,w){if(!f.resizeHandlers){return}var x=function(B){var A=-1;var C=B.parentNode;while(C){A++;C=C.parentNode}return A};var o=function(D,B){if(!D.widget||!B.widget){return 0}var C=x(D.widget[0]);var A=x(B.widget[0]);try{if(C<A){return -1}if(C>A){return 1}}catch(E){var F=E}return 0};f.hiddenWidgets=new Array();f.resizeHandlers.sort(o);for(var t=0;t<f.resizeHandlers.length;t++){var z=f.resizeHandlers[t];var v=z.widget;var s=z.data;if(!s){continue}if(!s.jqxWidget){continue}var n=s.jqxWidget.width;var y=s.jqxWidget.height;if(s.jqxWidget.base){if(n==undefined){n=s.jqxWidget.base.width}if(y==undefined){y=s.jqxWidget.base.height}}if(n===undefined&&y===undefined){n=s.jqxWidget.element.style.width;y=s.jqxWidget.element.style.height}var u=false;if(n!=null&&n.toString().indexOf("%")!=-1){u=true}if(y!=null&&y.toString().indexOf("%")!=-1){u=true}if(a.jqx.isHidden(v)){if(c(v)===-1){if(u||p===true){if(z.data.nestedWidget!==true){f.hiddenWidgets.push(z)}}}}else{if(p===undefined||p!==true){if(u){z.callback(w);if(f.hiddenWidgets.indexOf(z)>=0){f.hiddenWidgets.splice(f.hiddenWidgets.indexOf(z),1)}}if(s.jqxWidget.element){var q=s.jqxWidget.element.className;if(q.indexOf("dropdownlist")>=0||q.indexOf("datetimeinput")>=0||q.indexOf("combobox")>=0||q.indexOf("menu")>=0){if(s.jqxWidget.isOpened){var r=s.jqxWidget.isOpened();if(r){s.jqxWidget.close()}}}}}}}if(f.hiddenWidgets.length>0){f.hiddenWidgets.sort(o);if(f.__resizeInterval){clearInterval(f.__resizeInterval)}f.__resizeInterval=setInterval(function(){var B=false;var D=new Array();for(var C=0;C<f.hiddenWidgets.length;C++){var A=f.hiddenWidgets[C];if(a.jqx.isHidden(A.widget)){B=true;D.push(A)}else{if(A.callback){A.callback(w)}}}f.hiddenWidgets=D;if(!B){clearInterval(f.__resizeInterval)}},100)}};if(!this.resizeHandlers){this.resizeHandlers=new Array();var j=a(window);if(j.on){this._resizeTimer=null;j.on("resize.jqx",function(n){if(f._resizeTimer!=undefined){clearTimeout(f._resizeTimer)}f._resizeTimer=setTimeout(function(){h(null,"resize")},a.jqx.resizeDelay)});j.on("orientationchange.jqx",function(n){h(null,"orientationchange")});j.on("orientationchanged.jqx",function(n){h(null,"orientationchange")})}else{j.bind("resize.jqx",function(n){h(null,"orientationchange")});j.bind("orientationchange.jqx",function(n){h(null,"orientationchange")});j.bind("orientationchanged.jqx",function(n){h(null,"orientationchange")})}}if(k){if(g===-1){this.resizeHandlers.push({id:d[0].id,widget:d,callback:m,data:d.data()})}}if(a.jqx.isHidden(d)&&k===true){h(true)}a.jqx.resize=function(){h(null,"resize")}},html:function(c,d){if(!a(c).on){return a(c).html(d)}try{return a.access(c,function(s){var f=c[0]||{},m=0,j=c.length;if(s===undefined){return f.nodeType===1?f.innerHTML.replace(rinlinejQuery,""):undefined}var r=/<(?:script|style|link)/i,n="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",h=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,p=/<([\w:]+)/,g=/<(?:script|object|embed|option|style)/i,k=new RegExp("<(?:"+n+")[\\s/>]","i"),q=/^\s+/,t={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};if(typeof s==="string"&&!r.test(s)&&(a.support.htmlSerialize||!k.test(s))&&(a.support.leadingWhitespace||!q.test(s))&&!t[(p.exec(s)||["",""])[1].toLowerCase()]){s=s.replace(h,"<$1></$2>");try{for(;m<j;m++){f=this[m]||{};if(f.nodeType===1){a.cleanData(f.getElementsByTagName("*"));f.innerHTML=s}}f=0}catch(o){}}if(f){c.empty().append(s)}},null,d,arguments.length)}catch(b){return a(c).html(d)}},hasTransform:function(d){var c="";c=d.css("transform");if(c==""||c=="none"){c=d.parents().css("transform");if(c==""||c=="none"){var b=a.jqx.utilities.getBrowser();if(b.browser=="msie"){c=d.css("-ms-transform");if(c==""||c=="none"){c=d.parents().css("-ms-transform")}}else{if(b.browser=="chrome"){c=d.css("-webkit-transform");if(c==""||c=="none"){c=d.parents().css("-webkit-transform")}}else{if(b.browser=="opera"){c=d.css("-o-transform");if(c==""||c=="none"){c=d.parents().css("-o-transform")}}else{if(b.browser=="mozilla"){c=d.css("-moz-transform");if(c==""||c=="none"){c=d.parents().css("-moz-transform")}}}}}}else{return c!=""&&c!="none"}}if(c==""||c=="none"){c=a(document.body).css("transform")}return c!=""&&c!="none"&&c!=null},getBrowser:function(){var c=navigator.userAgent.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(c)||/(webkit)[ \/]([\w.]+)/.exec(c)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(c)||/(msie) ([\w.]+)/.exec(c)||c.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(c)||[];var d={browser:b[1]||"",version:b[2]||"0"};if(c.indexOf("rv:11.0")>=0&&c.indexOf(".net4.0c")>=0){d.browser="msie";d.version="11";b[1]="msie"}d[b[1]]=b[1];return d}});a.jqx.browser=a.jqx.utilities.getBrowser();a.jqx.isHidden=function(d){try{var b=d[0].offsetWidth,e=d[0].offsetHeight;if(b===0||e===0){return true}else{return false}}catch(c){return false}};a.jqx.ariaEnabled=true;a.jqx.aria=function(c,e,d){if(!a.jqx.ariaEnabled){return}if(e==undefined){a.each(c.aria,function(g,h){var k=!c.base?c.host.attr(g):c.base.host.attr(g);if(k!=undefined&&!a.isFunction(k)){var j=k;switch(h.type){case"number":j=new Number(k);if(isNaN(j)){j=k}break;case"boolean":j=k=="true"?true:false;break;case"date":j=new Date(k);if(j=="Invalid Date"||isNaN(j)){j=k}break}c[h.name]=j}else{var k=c[h.name];if(a.isFunction(k)){k=c[h.name]()}if(k==undefined){k=""}try{!c.base?c.host.attr(g,k.toString()):c.base.host.attr(g,k.toString())}catch(f){}}})}else{try{if(c.host){if(!c.base){if(c.host){if(c.element.setAttribute){c.element.setAttribute(e,d.toString())}else{c.host.attr(e,d.toString())}}else{c.attr(e,d.toString())}}else{if(c.base.host){c.base.host.attr(e,d.toString())}else{c.attr(e,d.toString())}}}else{if(c.setAttribute){c.setAttribute(e,d.toString())}}}catch(b){}}};if(!Array.prototype.indexOf){Array.prototype.indexOf=function(c){var b=this.length;var d=Number(arguments[1])||0;d=(d<0)?Math.ceil(d):Math.floor(d);if(d<0){d+=b}for(;d<b;d++){if(d in this&&this[d]===c){return d}}return -1}}a.jqx.mobile=a.jqx.mobile||{};a.jqx.position=function(b){var e=parseInt(b.pageX);var d=parseInt(b.pageY);if(a.jqx.mobile.isTouchDevice()){var c=a.jqx.mobile.getTouches(b);var f=c[0];e=parseInt(f.pageX);d=parseInt(f.pageY)}return{left:e,top:d}};a.extend(a.jqx.mobile,{_touchListener:function(h,f){var b=function(j,l){var k=document.createEvent("MouseEvents");k.initMouseEvent(j,l.bubbles,l.cancelable,l.view,l.detail,l.screenX,l.screenY,l.clientX,l.clientY,l.ctrlKey,l.altKey,l.shiftKey,l.metaKey,l.button,l.relatedTarget);k._pageX=l.pageX;k._pageY=l.pageY;return k};var g={mousedown:"touchstart",mouseup:"touchend",mousemove:"touchmove"};var d=b(g[h.type],h);h.target.dispatchEvent(d);var c=h.target["on"+g[h.type]];if(typeof c==="function"){c(h)}},setMobileSimulator:function(c,e){if(this.isTouchDevice()){return}this.simulatetouches=true;if(e==false){this.simulatetouches=false}var d={mousedown:"touchstart",mouseup:"touchend",mousemove:"touchmove"};var b=this;if(window.addEventListener){var f=function(){for(var g in d){if(c.addEventListener){c.removeEventListener(g,b._touchListener);c.addEventListener(g,b._touchListener,false)}}};if(a.jqx.browser.msie){f()}else{f()}}},isTouchDevice:function(){if(this.touchDevice!=undefined){return this.touchDevice}var c="Browser CodeName: "+navigator.appCodeName+"";c+="Browser Name: "+navigator.appName+"";c+="Browser Version: "+navigator.appVersion+"";c+="Platform: "+navigator.platform+"";c+="User-agent header: "+navigator.userAgent+"";if(c.indexOf("Android")!=-1){return true}if(c.indexOf("IEMobile")!=-1){return true}if(c.indexOf("Windows Phone")!=-1){return true}if(c.indexOf("WPDesktop")!=-1){return true}if(c.indexOf("ZuneWP7")!=-1){return true}if(c.indexOf("BlackBerry")!=-1&&c.indexOf("Mobile Safari")!=-1){return true}if(c.indexOf("ipod")!=-1){return true}if(c.indexOf("nokia")!=-1||c.indexOf("Nokia")!=-1){return true}if(c.indexOf("Chrome/17")!=-1){return false}if(c.indexOf("CrOS")!=-1){return false}if(c.indexOf("Opera")!=-1&&c.indexOf("Mobi")==-1&&c.indexOf("Mini")==-1&&c.indexOf("Platform: Win")!=-1){return false}if(c.indexOf("Opera")!=-1&&c.indexOf("Mobi")!=-1&&c.indexOf("Opera Mobi")!=-1){return true}var d={ios:"i(?:Pad|Phone|Pod)(?:.*)CPU(?: iPhone)? OS ",android:"(Android |HTC_|Silk/)",blackberry:"BlackBerry(?:.*)Version/",rimTablet:"RIM Tablet OS ",webos:"(?:webOS|hpwOS)/",bada:"Bada/"};try{if(this.touchDevice!=undefined){return this.touchDevice}this.touchDevice=false;for(i in d){if(d.hasOwnProperty(i)){prefix=d[i];match=c.match(new RegExp("(?:"+prefix+")([^\\s;]+)"));if(match){if(i.toString()=="blackberry"){this.touchDevice=false;return false}this.touchDevice=true;return true}}}var f=navigator.userAgent;if(navigator.platform.toLowerCase().indexOf("win")!=-1){if(f.indexOf("Windows Phone")>=0||f.indexOf("WPDesktop")>=0||f.indexOf("IEMobile")>=0||f.indexOf("ZuneWP7")>=0){this.touchDevice=true;return true}else{if(f.indexOf("Touch")>=0){var b=("MSPointerDown" in window)||("pointerdown" in window);if(b){this.touchDevice=true;return true}if(f.indexOf("ARM")>=0){this.touchDevice=true;return true}this.touchDevice=false;return false}}}if(navigator.platform.toLowerCase().indexOf("win")!=-1){this.touchDevice=false;return false}if(("ontouchstart" in window)||window.DocumentTouch&&document instanceof DocumentTouch){this.touchDevice=true}return this.touchDevice}catch(g){this.touchDevice=false;return false}},getLeftPos:function(b){var c=b.offsetLeft;while((b=b.offsetParent)!=null){if(b.tagName!="HTML"){c+=b.offsetLeft;if(document.all){c+=b.clientLeft}}}return c},getTopPos:function(c){var e=c.offsetTop;var b=a(c).coord();while((c=c.offsetParent)!=null){if(c.tagName!="HTML"){e+=(c.offsetTop-c.scrollTop);if(document.all){e+=c.clientTop}}}var d=navigator.userAgent.toLowerCase();var f=(d.indexOf("windows phone")!=-1||d.indexOf("WPDesktop")!=-1||d.indexOf("ZuneWP7")!=-1||d.indexOf("msie 9")!=-1||d.indexOf("msie 11")!=-1||d.indexOf("msie 10")!=-1)&&d.indexOf("touch")!=-1;if(f){return b.top}if(this.isSafariMobileBrowser()){if(this.isSafari4MobileBrowser()&&this.isIPadSafariMobileBrowser()){return e}if(d.indexOf("version/7")!=-1){return b.top}e=e+a(window).scrollTop()}return e},isChromeMobileBrowser:function(){var c=navigator.userAgent.toLowerCase();var b=c.indexOf("android")!=-1;return b},isOperaMiniMobileBrowser:function(){var c=navigator.userAgent.toLowerCase();var b=c.indexOf("opera mini")!=-1||c.indexOf("opera mobi")!=-1;return b},isOperaMiniBrowser:function(){var c=navigator.userAgent.toLowerCase();var b=c.indexOf("opera mini")!=-1;return b},isNewSafariMobileBrowser:function(){var c=navigator.userAgent.toLowerCase();var b=c.indexOf("ipad")!=-1||c.indexOf("iphone")!=-1||c.indexOf("ipod")!=-1;b=b&&(c.indexOf("version/5")!=-1);return b},isSafari4MobileBrowser:function(){var c=navigator.userAgent.toLowerCase();var b=c.indexOf("ipad")!=-1||c.indexOf("iphone")!=-1||c.indexOf("ipod")!=-1;b=b&&(c.indexOf("version/4")!=-1);return b},isWindowsPhone:function(){var c=navigator.userAgent.toLowerCase();var b=(c.indexOf("windows phone")!=-1||c.indexOf("WPDesktop")!=-1||c.indexOf("ZuneWP7")!=-1||c.indexOf("msie 9")!=-1||c.indexOf("msie 11")!=-1||c.indexOf("msie 10")!=-1);return b},isSafariMobileBrowser:function(){var c=navigator.userAgent.toLowerCase();var b=c.indexOf("ipad")!=-1||c.indexOf("iphone")!=-1||c.indexOf("ipod")!=-1;return b},isIPadSafariMobileBrowser:function(){var c=navigator.userAgent.toLowerCase();var b=c.indexOf("ipad")!=-1;return b},isMobileBrowser:function(){var c=navigator.userAgent.toLowerCase();var b=c.indexOf("ipad")!=-1||c.indexOf("iphone")!=-1||c.indexOf("android")!=-1;return b},getTouches:function(b){if(b.originalEvent){if(b.originalEvent.touches&&b.originalEvent.touches.length){return b.originalEvent.touches}else{if(b.originalEvent.changedTouches&&b.originalEvent.changedTouches.length){return b.originalEvent.changedTouches}}}if(!b.touches){b.touches=new Array();b.touches[0]=b.originalEvent!=undefined?b.originalEvent:b;if(b.originalEvent!=undefined&&b.pageX){b.touches[0]=b}if(b.type=="mousemove"){b.touches[0]=b}}return b.touches},getTouchEventName:function(b){if(this.isWindowsPhone()){var c=navigator.userAgent.toLowerCase();if(c.indexOf("windows phone 8.1")!=-1){if(b.toLowerCase().indexOf("start")!=-1){return"pointerdown"}if(b.toLowerCase().indexOf("move")!=-1){return"pointermove"}if(b.toLowerCase().indexOf("end")!=-1){return"pointerup"}}if(b.toLowerCase().indexOf("start")!=-1){return"MSPointerDown"}if(b.toLowerCase().indexOf("move")!=-1){return"MSPointerMove"}if(b.toLowerCase().indexOf("end")!=-1){return"MSPointerUp"}}else{return b}},dispatchMouseEvent:function(b,f,d){if(this.simulatetouches){return}var c=document.createEvent("MouseEvent");c.initMouseEvent(b,true,true,f.view,1,f.screenX,f.screenY,f.clientX,f.clientY,false,false,false,false,0,null);if(d!=null){d.dispatchEvent(c)}},getRootNode:function(b){while(b.nodeType!==1){b=b.parentNode}return b},setTouchScroll:function(b,c){if(!this.enableScrolling){this.enableScrolling=[]}this.enableScrolling[c]=b},touchScroll:function(d,y,g,D,b,k){if(d==null){return}var B=this;var t=0;var j=0;var l=0;var u=0;var m=0;var n=0;if(!this.scrolling){this.scrolling=[]}this.scrolling[D]=false;var h=false;var q=a(d);var v=["select","input","textarea"];var c=0;var e=0;if(!this.enableScrolling){this.enableScrolling=[]}this.enableScrolling[D]=true;var D=D;var C=this.getTouchEventName("touchstart")+".touchScroll";var p=this.getTouchEventName("touchend")+".touchScroll";var A=this.getTouchEventName("touchmove")+".touchScroll";var c=function(E){if(!B.enableScrolling[D]){return true}if(a.inArray(E.target.tagName.toLowerCase(),v)!==-1){return}var F=B.getTouches(E);var G=F[0];if(F.length==1){B.dispatchMouseEvent("mousedown",G,B.getRootNode(G.target))}h=false;j=G.pageY;m=G.pageX;if(B.simulatetouches){if(G._pageY!=undefined){j=G._pageY;m=G._pageX}}B.scrolling[D]=true;t=0;u=0;return true};if(q.on){q.on(C,c)}else{q.bind(C,c)}var x=function(J){if(!B.enableScrolling[D]){return true}if(!B.scrolling[D]){return true}var L=B.getTouches(J);if(L.length>1){return true}var H=L[0].pageY;var I=L[0].pageX;if(B.simulatetouches){if(L[0]._pageY!=undefined){H=L[0]._pageY;I=L[0]._pageX}}var E=H-j;var F=I-m;e=H;touchHorizontalEnd=I;l=E-t;n=F-u;h=true;t=E;u=F;var G=b!=null?b[0].style.visibility!="hidden":true;var K=k!=null?k[0].style.visibility!="hidden":true;if(G||K){if((n!==0&&G)||(l!==0&&K)){g(-n*1,-l*1,F,E,J);J.preventDefault();J.stopPropagation();if(J.preventManipulation){J.preventManipulation()}return false}}};if(q.on){q.on(A,x)}else{q.bind(A,x)}if(this.simulatetouches){var o=a(window).on!=undefined||a(window).bind;var z=function(E){B.scrolling[D]=false};a(window).on!=undefined?a(document).on("mouseup.touchScroll",z):a(document).bind("mouseup.touchScroll",z);if(window.frameElement){if(window.top!=null){var r=function(E){B.scrolling[D]=false};if(window.top.document){a(window.top.document).on?a(window.top.document).on("mouseup",r):a(window.top.document).bind("mouseup",r)}}}var s=a(document).on!=undefined||a(document).bind;var w=function(E){if(!B.scrolling[D]){return true}B.scrolling[D]=false;var G=B.getTouches(E)[0],F=B.getRootNode(G.target);B.dispatchMouseEvent("mouseup",G,F);B.dispatchMouseEvent("click",G,F)};a(document).on!=undefined?a(document).on("touchend",w):a(document).bind("touchend",w)}var f=function(E){if(!B.enableScrolling[D]){return true}var G=B.getTouches(E)[0];if(!B.scrolling[D]){return true}B.scrolling[D]=false;if(h){B.dispatchMouseEvent("mouseup",G,F)}else{var G=B.getTouches(E)[0],F=B.getRootNode(G.target);B.dispatchMouseEvent("mouseup",G,F);B.dispatchMouseEvent("click",G,F);return true}};if(q.on){q.on("dragstart",function(E){E.preventDefault()});q.on("selectstart",function(E){E.preventDefault()})}q.on?q.on(p+" touchcancel.touchScroll",f):q.bind(p+" touchcancel.touchScroll",f)}});a.jqx.cookie=a.jqx.cookie||{};a.extend(a.jqx.cookie,{cookie:function(e,f,c){if(arguments.length>1&&String(f)!=="[object Object]"){c=a.extend({},c);if(f===null||f===undefined){c.expires=-1}if(typeof c.expires==="number"){var h=c.expires,d=c.expires=new Date();d.setDate(d.getDate()+h)}f=String(f);return(document.cookie=[encodeURIComponent(e),"=",c.raw?f:encodeURIComponent(f),c.expires?"; expires="+c.expires.toUTCString():"",c.path?"; path="+c.path:"",c.domain?"; domain="+c.domain:"",c.secure?"; secure":""].join(""))}c=f||{};var b,g=c.raw?function(j){return j}:decodeURIComponent;return(b=new RegExp("(?:^|; )"+encodeURIComponent(e)+"=([^;]*)").exec(document.cookie))?g(b[1]):null}});a.jqx.string=a.jqx.string||{};a.extend(a.jqx.string,{replace:function(f,d,e){if(d===e){return this}var b=f;var c=b.indexOf(d);while(c!=-1){b=b.replace(d,e);c=b.indexOf(d)}return b},contains:function(b,c){if(b==null||c==null){return false}return b.indexOf(c)!=-1},containsIgnoreCase:function(b,c){if(b==null||c==null){return false}return b.toUpperCase().indexOf(c.toUpperCase())!=-1},equals:function(b,c){if(b==null||c==null){return false}b=this.normalize(b);if(c.length==b.length){return b.slice(0,c.length)==c}return false},equalsIgnoreCase:function(b,c){if(b==null||c==null){return false}b=this.normalize(b);if(c.length==b.length){return b.toUpperCase().slice(0,c.length)==c.toUpperCase()}return false},startsWith:function(b,c){if(b==null||c==null){return false}return b.slice(0,c.length)==c},startsWithIgnoreCase:function(b,c){if(b==null||c==null){return false}return b.toUpperCase().slice(0,c.length)==c.toUpperCase()},normalize:function(b){if(b.charCodeAt(b.length-1)==65279){b=b.substring(0,b.length-1)}return b},endsWith:function(b,c){if(b==null||c==null){return false}b=this.normalize(b);return b.slice(-c.length)==c},endsWithIgnoreCase:function(b,c){if(b==null||c==null){return false}b=this.normalize(b);return b.toUpperCase().slice(-c.length)==c.toUpperCase()}});a.extend(a.easing,{easeOutBack:function(f,g,e,k,j,h){if(h==undefined){h=1.70158}return k*((g=g/j-1)*g*((h+1)*g+h)+1)+e},easeInQuad:function(f,g,e,j,h){return j*(g/=h)*g+e},easeInOutCirc:function(f,g,e,j,h){if((g/=h/2)<1){return -j/2*(Math.sqrt(1-g*g)-1)+e}return j/2*(Math.sqrt(1-(g-=2)*g)+1)+e},easeInOutSine:function(f,g,e,j,h){return -j/2*(Math.cos(Math.PI*g/h)-1)+e},easeInCubic:function(f,g,e,j,h){return j*(g/=h)*g*g+e},easeOutCubic:function(f,g,e,j,h){return j*((g=g/h-1)*g*g+1)+e},easeInOutCubic:function(f,g,e,j,h){if((g/=h/2)<1){return j/2*g*g*g+e}return j/2*((g-=2)*g*g+2)+e},easeInSine:function(f,g,e,j,h){return -j*Math.cos(g/h*(Math.PI/2))+j+e},easeOutSine:function(f,g,e,j,h){return j*Math.sin(g/h*(Math.PI/2))+e},easeInOutSine:function(f,g,e,j,h){return -j/2*(Math.cos(Math.PI*g/h)-1)+e}})})(jqxBaseFramework);(function(b){b.extend(b.event.special,{close:{noBubble:true},open:{noBubble:true},cellclick:{noBubble:true},rowclick:{noBubble:true},tabclick:{noBubble:true},selected:{noBubble:true},expanded:{noBubble:true},collapsed:{noBubble:true},valuechanged:{noBubble:true},expandedItem:{noBubble:true},collapsedItem:{noBubble:true},expandingItem:{noBubble:true},collapsingItem:{noBubble:true}});b.fn.extend({ischildof:function(f){var d=b(this).parents().get();for(var c=0;c<d.length;c++){if(typeof f!="string"){var e=d[c];if(f!==undefined){if(e==f[0]){return true}}}else{if(f!==undefined){if(b(d[c]).is(f)){return true}}}}return false}});b.fn.jqxProxy=function(){var e=b(this).data().jqxWidget;var c=Array.prototype.slice.call(arguments,0);var d=e.element;if(!d){d=e.base.element}return b.jqx.jqxWidgetProxy(e.widgetName,d,c)};var a=this.originalVal=b.fn.val;b.fn.val=function(d){if(typeof d=="undefined"){if(b(this).hasClass("jqx-widget")){var c=b(this).data().jqxWidget;if(c&&c.val){return c.val()}}return a.call(this)}else{if(b(this).hasClass("jqx-widget")){var c=b(this).data().jqxWidget;if(c&&c.val){if(arguments.length!=2){return c.val(d)}else{return c.val(d,arguments[1])}}}return a.call(this,d)}};b.fn.coord=function(o){var e,k,j={top:0,left:0},f=this[0],m=f&&f.ownerDocument;if(!m){return}e=m.documentElement;if(!b.contains(e,f)){return j}if(typeof f.getBoundingClientRect!==undefined){j=f.getBoundingClientRect()}var d=function(p){return b.isWindow(p)?p:p.nodeType===9?p.defaultView||p.parentWindow:false};k=d(m);var h=0;var c=0;var g=navigator.userAgent.toLowerCase();var n=g.indexOf("ipad")!=-1||g.indexOf("iphone")!=-1;if(n){h=2}if(true==o){if(b(document.body).css("position")!="static"){var l=b(document.body).coord();h=-l.left;c=-l.top}}return{top:c+j.top+(k.pageYOffset||e.scrollTop)-(e.clientTop||0),left:h+j.left+(k.pageXOffset||e.scrollLeft)-(e.clientLeft||0)}}})(jqxBaseFramework); \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/js/jqxmenu.js b/src/static/movio/templates/Sliding-windows/js/jqxmenu.js new file mode 100644 index 0000000..7185841 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/js/jqxmenu.js @@ -0,0 +1,7 @@ +/* +jQWidgets v3.5.0 (2014-Sep-15) +Copyright (c) 2011-2014 jQWidgets. +License: http://jqwidgets.com/license/ +*/ + +(function(a){a.jqx.jqxWidget("jqxMenu","",{});a.extend(a.jqx._jqxMenu.prototype,{defineInstance:function(){var b={items:new Array(),mode:"horizontal",width:null,height:null,minimizeWidth:"auto",easing:"easeInOutSine",animationShowDuration:200,animationHideDuration:200,autoCloseInterval:0,animationHideDelay:100,animationShowDelay:100,menuElements:new Array(),autoSizeMainItems:false,autoCloseOnClick:true,autoCloseOnMouseLeave:true,enableRoundedCorners:true,disabled:false,autoOpenPopup:true,enableHover:true,autoOpen:true,autoGenerate:true,clickToOpen:false,showTopLevelArrows:false,touchMode:"auto",source:null,popupZIndex:17000,rtl:false,title:"",events:["shown","closed","itemclick","initialized"]};a.extend(true,this,b)},createInstance:function(c){var b=this;this.host.attr("role","menubar");a.jqx.utilities.resize(this.host,function(){b.refresh()},false,this.mode!="popup");this.host.css("outline","none");if(this.source){if(this.source!=null){var d=this.loadItems(this.source);this.element.innerHTML=d}}this._tmpHTML=this.element.innerHTML;if(this.element.innerHTML.indexOf("UL")){var e=this.host.find("ul:first");if(e.length>0){this._createMenu(e[0])}}this.host.data("autoclose",{});this._render();this.setSize();if(a.jqx.browser.msie&&a.jqx.browser.version<8){this.host.attr("hideFocus",true)}},focus:function(){try{this.host.focus()}catch(b){}},loadItems:function(c,e){if(c==null){return}if(c.length==0){return""}var b=this;this.items=new Array();var d="<ul>";if(e){d='<ul style="width:'+e+';">'}a.map(c,function(f){if(f==undefined){return null}d+=b._parseItem(f)});d+="</ul>";return d},_parseItem:function(f){var c="";if(f==undefined){return null}var b=f.label;if(!f.label&&f.html){b=f.html}if(!b){b="Item"}if(typeof f==="string"){b=f}var e=false;if(f.selected!=undefined&&f.selected){e=true}var d=false;if(f.disabled!=undefined&&f.disabled){d=true}c+="<li";if(d){c+=' item-disabled="true" '}if(f.label&&!f.html){c+=' item-label="'+b+'" '}if(f.value!=null){c+=' item-value="'+f.value+'" '}if(f.id!=undefined){c+=' id="'+f.id+'" '}c+=">"+b;if(f.items){if(f.subMenuWidth){c+=this.loadItems(f.items,f.subMenuWidth)}else{c+=this.loadItems(f.items)}}c+="</li>";return c},setSize:function(){if(this.width!=null&&this.width.toString().indexOf("%")!=-1){this.host.width(this.width)}else{if(this.width!=null&&this.width.toString().indexOf("px")!=-1){this.host.width(this.width)}else{if(this.width!=undefined&&!isNaN(this.width)){this.host.width(this.width)}}}if(this.height!=null&&this.height.toString().indexOf("%")!=-1){this.host.height(this.height)}else{if(this.height!=null&&this.height.toString().indexOf("px")!=-1){this.host.height(this.height)}else{if(this.height!=undefined&&!isNaN(this.height)){this.host.height(this.height)}}}if(this.height===null){this.host.height("auto")}var g=this;if(this.minimizeWidth!=null&&this.mode!="popup"){var f=a(window).width();if(!a.jqx.response){var e=false;if(navigator.userAgent.match(/Windows|Linux|MacOS/)){var b=navigator.userAgent.indexOf("Windows Phone")>=0||navigator.userAgent.indexOf("WPDesktop")>=0||navigator.userAgent.indexOf("IEMobile")>=0||navigator.userAgent.indexOf("ZuneWP7")>=0;if(!b){e=true}}var c=this.minimizeWidth;if(e&&this.minimizeWidth=="auto"){return}}if(this.minimizeWidth=="auto"&&a.jqx.response){var d=new a.jqx.response();if(d.device.type=="Phone"||d.device.type=="Tablet"){if(!this.minimized){this.minimize()}}}else{if((f<c)&&!this.minimized){this.minimize()}else{if(this.minimized&&f>=c){this.restore()}}}}},minimize:function(){if(this.minimized){return}var e=this;this.host.addClass(this.toThemeProperty("jqx-menu-minimized"));this.minimized=true;this._tmpMode=this.mode;this.mode="simple";var h=this.host.closest("div.jqx-menu-wrapper");h.remove();a("#menuWrapper"+this.element.id).remove();a.each(this.items,function(){var l=this;var k=a(l.element);var j=a(l.subMenuElement);var m=j.closest("div.jqx-menu-popup");m.remove()});if(this.source){var d=this.loadItems(this.source);this.element.innerHTML=d;this._tmpHTML=this.element.innerHTML}this.element.innerHTML=this._tmpHTML;if(this.element.innerHTML.indexOf("UL")){var g=this.host.find("ul:first");if(g.length>0){this._createMenu(g[0])}}this._render();var c=this.host.find("ul:first");c.wrap('<div class="jqx-menu-wrapper" style="z-index:'+this.popupZIndex+'; padding: 0px; display: none; margin: 0px; height: auto; width: auto; position: absolute; top: 0; left: 0; display: block; visibility: visible;"></div>');var h=c.closest("div.jqx-menu-wrapper");h[0].id="menuWrapper"+this.element.id;h.detach();h.appendTo(a(document.body));h.addClass(this.toThemeProperty("jqx-widget"));h.addClass(this.toThemeProperty("jqx-menu"));h.addClass(this.toThemeProperty("jqx-menu-minimized"));h.addClass(this.toThemeProperty("jqx-widget-header"));c.children().hide();h.hide();h.find("ul").addClass(this.toThemeProperty("jqx-menu-ul-minimized"));this.minimizedItem=a("<div></div>");this.minimizedItem.addClass(this.toThemeProperty("jqx-item"));this.minimizedItem.addClass(this.toThemeProperty("jqx-menu-item-top"));this.minimizedItem.addClass(this.toThemeProperty("jqx-menu-minimized-button"));this.minimizedItem.prependTo(this.host);this.titleElement=a("<div>"+this.title+"</div>");this.titleElement.addClass(this.toThemeProperty("jqx-item"));this.titleElement.addClass(this.toThemeProperty("jqx-menu-title"));this.titleElement.prependTo(this.host);a("<div style='clear:both;'></div>").insertAfter(this.minimizedItem);e.minimizedHidden=true;var b=function(k){e.minimizedHidden=true;e.minimizedItem.show();var j=false;if(e.minimizedItem.css("float")=="right"){j=true}h.animate({left:!j?-h.outerWidth():e.host.coord().left+e.host.width()+h.width(),opacity:0},e.animationHideDuration,function(){h.find("ul:first").children().hide();h.hide()})};var f=function(l){if(e.minimizedHidden){h.find("ul:first").children().show();e.minimizedHidden=false;h.show();h.css("opacity",0);h.css("left",-h.outerWidth());var k=false;var j=h.width();if(e.minimizedItem.css("float")=="right"){h.css("left",e.host.coord().left+e.host.width()+j);k=true}h.css("top",e.host.coord().top+e.host.height());h.animate({left:!k?e.host.coord().left:e.host.coord().left+e.host.width()-j,opacity:0.95},e.animationShowDuration,function(){})}else{b(l)}e._raiseEvent("2",{item:e.minimizedItem[0],event:l});e.setSize()};this.addHandler(a(window),"orientationchange.jqxmenu"+this.element.id,function(j){setTimeout(function(){if(!e.minimizedHidden){var k=h.width();var l=false;var k=h.width();if(e.minimizedItem.css("float")=="right"){l=true}h.css("top",e.host.coord().top+e.host.height());h.css({left:!l?e.host.coord().left:e.host.coord().left+e.host.width()-k})}},25)});this.addHandler(this.minimizedItem,"click",function(j){f(j)})},restore:function(){if(!this.minimized){return}this.host.find("ul").removeClass(this.toThemeProperty("jqx-menu-ul-minimized"));this.host.removeClass(this.toThemeProperty("jqx-menu-minimized"));this.minimized=false;this.mode=this._tmpMode;if(this.minimizedItem){this.minimizedItem.remove()}var d=a("#menuWrapper"+this.element.id);d.remove();if(this.source){var b=this.loadItems(this.source);this.element.innerHTML=b;this._tmpHTML=b}this.element.innerHTML=this._tmpHTML;if(this.element.innerHTML.indexOf("UL")){var c=this.host.find("ul:first");if(c.length>0){this._createMenu(c[0])}}this.setSize();this._render()},isTouchDevice:function(){if(this._isTouchDevice!=undefined){return this._isTouchDevice}var b=a.jqx.mobile.isTouchDevice();if(this.touchMode==true){b=true}else{if(this.touchMode==false){b=false}}if(b){this.host.addClass(this.toThemeProperty("jqx-touch"));a(".jqx-menu-item").addClass(this.toThemeProperty("jqx-touch"))}this._isTouchDevice=b;return b},refresh:function(b){if(!b){this.setSize()}},resize:function(c,b){this.width=c;this.height=b;this.refresh()},_closeAll:function(f){var d=f!=null?f.data:this;var b=d.items;a.each(b,function(){var e=this;if(e.hasItems==true){if(e.isOpen){d._closeItem(d,e)}}});if(d.mode=="popup"){if(f!=null){var c=d._isRightClick(f);if(!c){d.close()}}}},closeItem:function(e){if(e==null){return false}var b=e;var c=document.getElementById(b);var d=this;a.each(d.items,function(){var f=this;if(f.isOpen==true&&f.element==c){d._closeItem(d,f);if(f.parentId){d.closeItem(f.parentId)}}});return true},openItem:function(e){if(e==null){return false}var b=e;var c=document.getElementById(b);var d=this;a.each(d.items,function(){var f=this;if(f.isOpen==false&&f.element==c){d._openItem(d,f);if(f.parentId){d.openItem(f.parentId)}}});return true},_getClosedSubMenuOffset:function(c){var b=a(c.subMenuElement);var f=-b.outerHeight();var e=-b.outerWidth();var d=c.level==0&&this.mode=="horizontal";if(d){e=0}else{f=0}switch(c.openVerticalDirection){case"up":case"center":f=b.outerHeight();break}switch(c.openHorizontalDirection){case this._getDir("left"):if(d){e=0}else{e=b.outerWidth()}break;case"center":if(d){e=0}else{e=b.outerWidth()}break}return{left:e,top:f}},_closeItem:function(m,p,g,c){if(m==null||p==null){return false}var k=a(p.subMenuElement);var b=p.level==0&&this.mode=="horizontal";var f=this._getClosedSubMenuOffset(p);var n=f.top;var e=f.left;var j=a(p.element);var l=k.closest("div.jqx-menu-popup");if(l!=null){var h=m.animationHideDelay;if(c==true){h=0}if(k.data("timer").show!=null){clearTimeout(k.data("timer").show);k.data("timer").show=null}var o=function(){p.isOpen=false;if(b){k.stop().animate({top:n},m.animationHideDuration,function(){a(p.element).removeClass(m.toThemeProperty("jqx-fill-state-pressed"));a(p.element).removeClass(m.toThemeProperty("jqx-menu-item-top-selected"));a(p.element).removeClass(m.toThemeProperty("jqx-rc-b-expanded"));l.removeClass(m.toThemeProperty("jqx-rc-t-expanded"));var q=a(p.arrow);if(q.length>0&&m.showTopLevelArrows){q.removeClass();if(p.openVerticalDirection=="down"){q.addClass(m.toThemeProperty("jqx-menu-item-arrow-down"));q.addClass(m.toThemeProperty("jqx-icon-arrow-down"))}else{q.addClass(m.toThemeProperty("jqx-menu-item-arrow-up"));q.addClass(m.toThemeProperty("jqx-icon-arrow-up"))}}a.jqx.aria(a(p.element),"aria-expanded",false);l.css({display:"none"});if(m.animationHideDuration==0){k.css({top:n})}m._raiseEvent("1",p)})}else{if(!a.jqx.browser.msie){}k.stop().animate({left:e},m.animationHideDuration,function(){if(m.animationHideDuration==0){k.css({left:e})}if(p.level>0){a(p.element).removeClass(m.toThemeProperty("jqx-fill-state-pressed"));a(p.element).removeClass(m.toThemeProperty("jqx-menu-item-selected"));var q=a(p.arrow);if(q.length>0){q.removeClass();if(p.openHorizontalDirection!="left"){q.addClass(m.toThemeProperty("jqx-menu-item-arrow-"+m._getDir("right")));q.addClass(m.toThemeProperty("jqx-icon-arrow-"+m._getDir("right")))}else{q.addClass(m.toThemeProperty("jqx-menu-item-arrow-"+m._getDir("left")));q.addClass(m.toThemeProperty("jqx-icon-arrow-"+m._getDir("left")))}}}else{a(p.element).removeClass(m.toThemeProperty("jqx-fill-state-pressed"));a(p.element).removeClass(m.toThemeProperty("jqx-menu-item-top-selected"));var q=a(p.arrow);if(q.length>0){q.removeClass();if(p.openHorizontalDirection!="left"){q.addClass(m.toThemeProperty("jqx-menu-item-arrow-top-"+m._getDir("right")));q.addClass(m.toThemeProperty("jqx-icon-arrow-"+m._getDir("right")))}else{q.addClass(m.toThemeProperty("jqx-menu-item-arrow-top-"+m._getDir("left")));q.addClass(m.toThemeProperty("jqx-icon-arrow-"+m._getDir("left")))}}}a.jqx.aria(a(p.element),"aria-expanded",false);l.css({display:"none"});m._raiseEvent("1",p)})}};if(h>0){k.data("timer").hide=setTimeout(function(){o()},h)}else{o()}if(g!=undefined&&g){var d=k.children();a.each(d,function(){if(m.menuElements[this.id]&&m.menuElements[this.id].isOpen){var q=a(m.menuElements[this.id].subMenuElement);m._closeItem(m,m.menuElements[this.id],true,true)}})}}},getSubItems:function(j,h){if(j==null){return false}var g=this;var c=new Array();if(h!=null){a.extend(c,h)}var d=j;var f=this.menuElements[d];var b=a(f.subMenuElement);var e=b.find(".jqx-menu-item");a.each(e,function(){c[this.id]=g.menuElements[this.id];var k=g.getSubItems(this.id,c);a.extend(c,k)});return c},disable:function(g,d){if(g==null){return}var c=g;var f=this;if(this.menuElements[c]){var e=this.menuElements[c];e.disabled=d;var b=a(e.element);e.element.disabled=d;a.each(b.children(),function(){this.disabled=d});if(d){b.addClass(f.toThemeProperty("jqx-menu-item-disabled"));b.addClass(f.toThemeProperty("jqx-fill-state-disabled"))}else{b.removeClass(f.toThemeProperty("jqx-menu-item-disabled"));b.removeClass(f.toThemeProperty("jqx-fill-state-disabled"))}}},_setItemProperty:function(g,c,f){if(g==null){return}var b=g;var e=this;if(this.menuElements[b]){var d=this.menuElements[b];if(d[c]){d[c]=f}}},setItemOpenDirection:function(d,c,e){if(d==null){return}var k=d;var g=this;var f=a.jqx.browser.msie&&a.jqx.browser.version<8;if(this.menuElements[k]){var j=this.menuElements[k];if(c!=null){j.openHorizontalDirection=c;if(j.hasItems&&j.level>0){var h=a(j.element);if(h!=undefined){var b=a(j.arrow);if(j.arrow==null){b=a('<span id="arrow'+h[0].id+'"></span>');if(!f){b.prependTo(h)}else{b.appendTo(h)}j.arrow=b[0]}b.removeClass();if(j.openHorizontalDirection=="left"){b.addClass(g.toThemeProperty("jqx-menu-item-arrow-"+g._getDir("left")));b.addClass(g.toThemeProperty("jqx-icon-arrow-"+g._getDir("left")))}else{b.addClass(g.toThemeProperty("jqx-menu-item-arrow-"+g._getDir("right")));b.addClass(g.toThemeProperty("jqx-icon-arrow-"+g._getDir("right")))}b.css("visibility","visible");if(!f){b.css("display","block");b.css("float","right")}else{b.css("display","inline-block");b.css("float","none")}}}}if(e!=null){j.openVerticalDirection=e;var b=a(j.arrow);var h=a(j.element);if(!g.showTopLevelArrows){return}if(h!=undefined){if(j.arrow==null){b=a('<span id="arrow'+h[0].id+'"></span>');if(!f){b.prependTo(h)}else{b.appendTo(h)}j.arrow=b[0]}b.removeClass();if(j.openVerticalDirection=="down"){b.addClass(g.toThemeProperty("jqx-menu-item-arrow-down"));b.addClass(g.toThemeProperty("jqx-icon-arrow-down"))}else{b.addClass(g.toThemeProperty("jqx-menu-item-arrow-up"));b.addClass(g.toThemeProperty("jqx-icon-arrow-up"))}b.css("visibility","visible");if(!f){b.css("display","block");b.css("float","right")}else{b.css("display","inline-block");b.css("float","none")}}}}},_getSiblings:function(c){var d=new Array();var b=0;for(i=0;i<this.items.length;i++){if(this.items[i]==c){continue}if(this.items[i].parentId==c.parentId&&this.items[i].hasItems){d[b++]=this.items[i]}}return d},_openItem:function(t,s,r){if(t==null||s==null){return false}if(s.isOpen){return false}if(s.disabled){return false}if(t.disabled){return false}var m=t.popupZIndex;if(r!=undefined){m=r}var e=t.animationHideDuration;t.animationHideDuration=0;t._closeItem(t,s,true,true);t.animationHideDuration=e;this.host.focus();var f=[5,5];var u=a(s.subMenuElement);if(u!=null){u.stop()}if(u.data("timer").hide!=null){clearTimeout(u.data("timer").hide)}var p=u.closest("div.jqx-menu-popup");var h=a(s.element);var j=s.level==0?this._getOffset(s.element):h.position();if(s.level>0&&this.hasTransform){var q=parseInt(h.coord().top)-parseInt(this._getOffset(s.element).top);j.top+=q}if(s.level==0&&this.mode=="popup"){j=h.coord()}var k=s.level==0&&this.mode=="horizontal";var b=k?j.left:this.menuElements[s.parentId]!=null&&this.menuElements[s.parentId].subMenuElement!=null?parseInt(a(a(this.menuElements[s.parentId].subMenuElement).closest("div.jqx-menu-popup")).outerWidth())-f[0]:parseInt(u.outerWidth());p.css({visibility:"visible",display:"block",left:b,top:k?j.top+h.outerHeight():j.top,zIndex:m});u.css("display","block");if(this.mode!="horizontal"&&s.level==0){var d=this._getOffset(this.element);p.css("left",-1+d.left+this.host.outerWidth());u.css("left",-u.outerWidth())}else{var c=this._getClosedSubMenuOffset(s);u.css("left",c.left);u.css("top",c.top)}p.css({height:parseInt(u.outerHeight())+parseInt(f[1])+"px"});var o=0;var g=0;switch(s.openVerticalDirection){case"up":if(k){u.css("top",u.outerHeight());o=f[1];var l=parseInt(u.parent().css("padding-bottom"));if(isNaN(l)){l=0}if(l>0){p.addClass(this.toThemeProperty("jqx-menu-popup-clear"))}u.css("top",u.outerHeight()-l);p.css({display:"block",top:j.top-p.outerHeight(),zIndex:m})}else{o=f[1];u.css("top",u.outerHeight());p.css({display:"block",top:j.top-p.outerHeight()+f[1]+h.outerHeight(),zIndex:m})}break;case"center":if(k){u.css("top",0);p.css({display:"block",top:j.top-p.outerHeight()/2+f[1],zIndex:m})}else{u.css("top",0);p.css({display:"block",top:j.top+h.outerHeight()/2-p.outerHeight()/2+f[1],zIndex:m})}break}switch(s.openHorizontalDirection){case this._getDir("left"):if(k){p.css({left:j.left-(p.outerWidth()-h.outerWidth()-f[0])})}else{g=0;u.css("left",p.outerWidth());p.css({left:j.left-(p.outerWidth())+2*s.level})}break;case"center":if(k){p.css({left:j.left-(p.outerWidth()/2-h.outerWidth()/2-f[0]/2)})}else{p.css({left:j.left-(p.outerWidth()/2-h.outerWidth()/2-f[0]/2)});u.css("left",p.outerWidth())}break}if(k){if(parseInt(u.css("top"))==o){s.isOpen=true;return}}else{if(parseInt(u.css("left"))==g){s.isOpen==true;return}}a.each(t._getSiblings(s),function(){t._closeItem(t,this,true,true)});var n=a.data(t.element,"animationHideDelay");t.animationHideDelay=n;if(this.autoCloseInterval>0){if(this.host.data("autoclose")!=null&&this.host.data("autoclose").close!=null){clearTimeout(this.host.data("autoclose").close)}if(this.host.data("autoclose")!=null){this.host.data("autoclose").close=setTimeout(function(){t._closeAll()},this.autoCloseInterval)}}u.data("timer").show=setTimeout(function(){if(p!=null){if(k){u.stop();u.css("left",g);if(!a.jqx.browser.msie){}h.addClass(t.toThemeProperty("jqx-fill-state-pressed"));h.addClass(t.toThemeProperty("jqx-menu-item-top-selected"));if(s.openVerticalDirection=="down"){a(s.element).addClass(t.toThemeProperty("jqx-rc-b-expanded"));p.addClass(t.toThemeProperty("jqx-rc-t-expanded"))}else{a(s.element).addClass(t.toThemeProperty("jqx-rc-t-expanded"));p.addClass(t.toThemeProperty("jqx-rc-b-expanded"))}var v=a(s.arrow);if(v.length>0&&t.showTopLevelArrows){v.removeClass();if(s.openVerticalDirection=="down"){v.addClass(t.toThemeProperty("jqx-menu-item-arrow-down-selected"));v.addClass(t.toThemeProperty("jqx-icon-arrow-down"))}else{v.addClass(t.toThemeProperty("jqx-menu-item-arrow-up-selected"));v.addClass(t.toThemeProperty("jqx-icon-arrow-up"))}}if(t.animationShowDuration==0){u.css({top:o});s.isOpen=true;t._raiseEvent("0",s);a.jqx.aria(a(s.element),"aria-expanded",true)}else{u.animate({top:o},t.animationShowDuration,t.easing,function(){s.isOpen=true;a.jqx.aria(a(s.element),"aria-expanded",true);t._raiseEvent("0",s)})}}else{u.stop();u.css("top",o);if(!a.jqx.browser.msie){}if(s.level>0){h.addClass(t.toThemeProperty("jqx-fill-state-pressed"));h.addClass(t.toThemeProperty("jqx-menu-item-selected"));var v=a(s.arrow);if(v.length>0){v.removeClass();if(s.openHorizontalDirection!="left"){v.addClass(t.toThemeProperty("jqx-menu-item-arrow-"+t._getDir("right")+"-selected"));v.addClass(t.toThemeProperty("jqx-icon-arrow-"+t._getDir("right")))}else{v.addClass(t.toThemeProperty("jqx-menu-item-arrow-"+t._getDir("left")+"-selected"));v.addClass(t.toThemeProperty("jqx-icon-arrow-"+t._getDir("left")))}}}else{h.addClass(t.toThemeProperty("jqx-fill-state-pressed"));h.addClass(t.toThemeProperty("jqx-menu-item-top-selected"));var v=a(s.arrow);if(v.length>0){v.removeClass();if(s.openHorizontalDirection!="left"){v.addClass(t.toThemeProperty("jqx-menu-item-arrow-"+t._getDir("right")+"-selected"));v.addClass(t.toThemeProperty("jqx-icon-arrow-"+t._getDir("right")))}else{v.addClass(t.toThemeProperty("jqx-menu-item-arrow-"+t._getDir("left")+"-selected"));v.addClass(t.toThemeProperty("jqx-icon-arrow-"+t._getDir("left")))}}}if(!a.jqx.browser.msie){}if(t.animationShowDuration==0){u.css({left:g});t._raiseEvent("0",s);s.isOpen=true;a.jqx.aria(a(s.element),"aria-expanded",true)}else{u.animate({left:g},t.animationShowDuration,t.easing,function(){t._raiseEvent("0",s);s.isOpen=true;a.jqx.aria(a(s.element),"aria-expanded",true)})}}}},this.animationShowDelay)},_getDir:function(b){switch(b){case"left":return !this.rtl?"left":"right";case"right":return this.rtl?"left":"right"}return"left"},_applyOrientation:function(j,d){var g=this;var f=0;this.host.removeClass(g.toThemeProperty("jqx-menu-horizontal"));this.host.removeClass(g.toThemeProperty("jqx-menu-vertical"));this.host.removeClass(g.toThemeProperty("jqx-menu"));this.host.removeClass(g.toThemeProperty("jqx-widget"));this.host.addClass(g.toThemeProperty("jqx-widget"));this.host.addClass(g.toThemeProperty("jqx-menu"));if(j!=undefined&&d!=undefined&&d=="popup"){if(this.host.parent().length>0&&this.host.parent().parent().length>0&&this.host.parent().parent()[0]==document.body){var h=a.data(document.body,"jqxMenuOldHost"+this.element.id);if(h!=null){var e=this.host.closest("div.jqx-menu-wrapper");e.remove();e.appendTo(h);this.host.css("display","block");this.host.css("visibility","visible");e.css("display","block");e.css("visibility","visible")}}}else{if(j==undefined&&d==undefined){a.data(document.body,"jqxMenuOldHost"+this.element.id,this.host.parent()[0])}}if(this.autoOpenPopup){if(this.mode=="popup"){this.addHandler(a(document),"contextmenu."+this.element.id,function(k){return false});this.addHandler(a(document),"mousedown.menu"+this.element.id,function(k){g._openContextMenu(k)})}else{this.removeHandler(a(document),"contextmenu."+this.element.id);this.removeHandler(a(document),"mousedown.menu"+this.element.id)}}else{this.removeHandler(a(document),"contextmenu."+this.element.id);this.removeHandler(a(document),"mousedown.menu"+this.element.id)}if(this.rtl){this.host.addClass(this.toThemeProperty("jqx-rtl"))}switch(this.mode){case"horizontal":this.host.addClass(g.toThemeProperty("jqx-widget-header"));this.host.addClass(g.toThemeProperty("jqx-menu-horizontal"));a.each(this.items,function(){var m=this;$element=a(m.element);var l=a(m.arrow);l.removeClass();if(m.hasItems&&m.level>0){var l=a('<span style="border: none; background-color: transparent;" id="arrow'+$element[0].id+'"></span>');l.prependTo($element);l.css("float",g._getDir("right"));l.addClass(g.toThemeProperty("jqx-menu-item-arrow-"+g._getDir("right")));l.addClass(g.toThemeProperty("jqx-icon-arrow-"+g._getDir("right")));m.arrow=l[0]}if(m.level==0){a(m.element).css("float",g._getDir("left"));if(!m.ignoretheme&&m.hasItems&&g.showTopLevelArrows){var l=a('<span style="border: none; background-color: transparent;" id="arrow'+$element[0].id+'"></span>');var k=a.jqx.browser.msie&&a.jqx.browser.version<8;if(m.arrow==null){if(!k){l.prependTo($element)}else{l.appendTo($element)}}else{l=a(m.arrow)}if(m.openVerticalDirection=="down"){l.addClass(g.toThemeProperty("jqx-menu-item-arrow-down"));l.addClass(g.toThemeProperty("jqx-icon-arrow-down"))}else{l.addClass(g.toThemeProperty("jqx-menu-item-arrow-up"));l.addClass(g.toThemeProperty("jqx-icon-arrow-up"))}l.css("visibility","visible");if(!k){l.css("display","block");l.css("float","right")}else{l.css("display","inline-block")}m.arrow=l[0]}else{if(!m.ignoretheme&&m.hasItems&&!g.showTopLevelArrows){if(m.arrow!=null){var l=a(m.arrow);l.remove();m.arrow=null}}}f=Math.max(f,$element.height())}});break;case"vertical":case"popup":case"simple":this.host.addClass(g.toThemeProperty("jqx-menu-vertical"));a.each(this.items,function(){var l=this;$element=a(l.element);if(l.hasItems&&!l.ignoretheme){if(l.arrow){a(l.arrow).remove()}if(g.mode=="simple"){return true}var k=a('<span style="border: none; background-color: transparent;" id="arrow'+$element[0].id+'"></span>');k.prependTo($element);k.css("float","right");if(l.level==0){k.addClass(g.toThemeProperty("jqx-menu-item-arrow-top-"+g._getDir("right")));k.addClass(g.toThemeProperty("jqx-icon-arrow-"+g._getDir("right")))}else{k.addClass(g.toThemeProperty("jqx-menu-item-arrow-"+g._getDir("right")));k.addClass(g.toThemeProperty("jqx-icon-arrow-"+g._getDir("right")))}l.arrow=k[0]}$element.css("float","none")});if(this.mode=="popup"){this.host.addClass(g.toThemeProperty("jqx-widget-content"));this.host.wrap('<div class="jqx-menu-wrapper" style="z-index:'+this.popupZIndex+'; border: none; background-color: transparent; padding: 0px; margin: 0px; position: absolute; top: 0; left: 0; display: block; visibility: visible;"></div>');var e=this.host.closest("div.jqx-menu-wrapper");this.host.addClass(g.toThemeProperty("jqx-popup"));e[0].id="menuWrapper"+this.element.id;e.appendTo(a(document.body))}else{this.host.addClass(g.toThemeProperty("jqx-widget-header"))}if(this.mode=="popup"){var b=this.host.height();this.host.css("position","absolute");this.host.css("top","0");this.host.css("left","0");if(this.mode!="simple"){this.host.height(b);this.host.css("display","none")}}break}var c=this.isTouchDevice();if(this.autoCloseOnClick){this.removeHandler(a(document),"mousedown.menu"+this.element.id,g._closeAfterClick);this.addHandler(a(document),"mousedown.menu"+this.element.id,g._closeAfterClick,g);if(c){this.removeHandler(a(document),a.jqx.mobile.getTouchEventName("touchstart")+".menu"+this.element.id,g._closeAfterClick,g);this.addHandler(a(document),a.jqx.mobile.getTouchEventName("touchstart")+".menu"+this.element.id,g._closeAfterClick,g)}}},_getBodyOffset:function(){var c=0;var b=0;if(a("body").css("border-top-width")!="0px"){c=parseInt(a("body").css("border-top-width"));if(isNaN(c)){c=0}}if(a("body").css("border-left-width")!="0px"){b=parseInt(a("body").css("border-left-width"));if(isNaN(b)){b=0}}return{left:b,top:c}},_getOffset:function(c){var e=a.jqx.mobile.isSafariMobileBrowser();var h=a(c).coord(true);var g=h.top;var f=h.left;if(a("body").css("border-top-width")!="0px"){g=parseInt(g)+this._getBodyOffset().top}if(a("body").css("border-left-width")!="0px"){f=parseInt(f)+this._getBodyOffset().left}var d=a.jqx.mobile.isWindowsPhone();if(this.hasTransform||(e!=null&&e)||d){var b={left:a.jqx.mobile.getLeftPos(c),top:a.jqx.mobile.getTopPos(c)};return b}else{return{left:f,top:g}}},_isRightClick:function(c){var b;if(!c){var c=window.event}if(c.which){b=(c.which==3)}else{if(c.button){b=(c.button==2)}}return b},_openContextMenu:function(d){var c=this;var b=c._isRightClick(d);if(b){c.open(parseInt(d.clientX)+5,parseInt(d.clientY)+5)}},close:function(){var c=this;var d=a.data(this.element,"contextMenuOpened"+this.element.id);if(d){var b=this.host;a.each(c.items,function(){var e=this;if(e.hasItems){c._closeItem(c,e)}});a.each(c.items,function(){var e=this;if(e.isOpen==true){$submenu=a(e.subMenuElement);var f=$submenu.closest("div.jqx-menu-popup");f.hide(this.animationHideDuration)}});this.host.hide(this.animationHideDuration);a.data(c.element,"contextMenuOpened"+this.element.id,false);c._raiseEvent("1",c)}},open:function(e,d){if(this.mode=="popup"){var c=0;if(this.host.css("display")=="block"){this.close();c=this.animationHideDuration}var b=this;if(e==undefined||e==null){e=0}if(d==undefined||d==null){d=0}setTimeout(function(){b.host.show(b.animationShowDuration);b.host.css("visibility","visible");a.data(b.element,"contextMenuOpened"+b.element.id,true);b._raiseEvent("0",b);b.host.css("z-index",9999);if(e!=undefined&&d!=undefined){b.host.css({left:e,top:d})}},c)}},_renderHover:function(c,e,b){var d=this;if(!e.ignoretheme){this.addHandler(c,"mouseenter",function(){if(!e.disabled&&!e.separator&&d.enableHover&&!d.disabled){if(e.level>0){c.addClass(d.toThemeProperty("jqx-fill-state-hover"));c.addClass(d.toThemeProperty("jqx-menu-item-hover"))}else{c.addClass(d.toThemeProperty("jqx-fill-state-hover"));c.addClass(d.toThemeProperty("jqx-menu-item-top-hover"))}}});this.addHandler(c,"mouseleave",function(){if(!e.disabled&&!e.separator&&d.enableHover&&!d.disabled){if(e.level>0){c.removeClass(d.toThemeProperty("jqx-fill-state-hover"));c.removeClass(d.toThemeProperty("jqx-menu-item-hover"))}else{c.removeClass(d.toThemeProperty("jqx-fill-state-hover"));c.removeClass(d.toThemeProperty("jqx-menu-item-top-hover"))}}})}},_closeAfterClick:function(c){var b=c!=null?c.data:this;var d=false;if(b.autoCloseOnClick){a.each(a(c.target).parents(),function(){if(this.className.indexOf){if(this.className.indexOf("jqx-menu")!=-1){d=true;return false}}});if(!d){c.data=b;b._closeAll(c)}}},_autoSizeHorizontalMenuItems:function(){var c=this;if(c.autoSizeMainItems&&this.mode=="horizontal"){var b=this.maxHeight;if(parseInt(b)>parseInt(this.host.height())){b=parseInt(this.host.height())}b=parseInt(this.host.height());a.each(this.items,function(){var m=this;$element=a(m.element);if(m.level==0&&b>0){var d=$element.children().length>0?parseInt($element.children().height()):$element.height();var g=c.host.find("ul:first");var h=parseInt(g.css("padding-top"));var n=parseInt(g.css("margin-top"));var k=b-2*(n+h);var j=parseInt(k)/2-d/2;var e=parseInt(j);var l=parseInt(j);$element.css("padding-top",e);$element.css("padding-bottom",l);if(parseInt($element.outerHeight())>k){var f=1;$element.css("padding-top",e-f);e=e-f}}})}a.each(this.items,function(){var f=this;$element=a(f.element);if(f.hasItems&&f.level>0){if(f.arrow){var e=a(f.arrow);var d=a(f.element).height();if(d>15){e.css("margin-top",(d-15)/2)}}}})},_render:function(f,g){if(this.disabled){this.host.addClass(this.toThemeProperty("jqx-fill-state-disabled"));this.host.addClass(this.toThemeProperty("jqx-menu-disabled"))}var j=this.popupZIndex;var d=[5,5];var h=this;a.data(h.element,"animationHideDelay",h.animationHideDelay);var e=this.isTouchDevice();var c=e&&(a.jqx.mobile.isWindowsPhone()||navigator.userAgent.indexOf("Touch")>=0);var k=false;if(navigator.platform.toLowerCase().indexOf("win")!=-1){if(navigator.userAgent.indexOf("Windows Phone")>=0||navigator.userAgent.indexOf("WPDesktop")>=0||navigator.userAgent.indexOf("IEMobile")>=0||navigator.userAgent.indexOf("ZuneWP7")>=0){this.touchDevice=true}else{if(navigator.userAgent.indexOf("Touch")>=0){var b=("MSPointerDown" in window);if(b||a.jqx.mobile.isWindowsPhone()||navigator.userAgent.indexOf("ARM")>=0){k=true;c=true;h.clickToOpen=true;h.autoCloseOnClick=false;h.enableHover=false}}}}a.data(document.body,"menuel",this);this.hasTransform=a.jqx.utilities.hasTransform(this.host);this._applyOrientation(f,g);if(h.enableRoundedCorners){this.host.addClass(h.toThemeProperty("jqx-rc-all"))}a.each(this.items,function(){var s=this;var o=a(s.element);o.attr("role","menuitem");if(h.enableRoundedCorners){o.addClass(h.toThemeProperty("jqx-rc-all"))}h.removeHandler(o,"click");h.addHandler(o,"click",function(x){if(s.disabled){return}if(h.disabled){return}h._raiseEvent("2",{item:s.element,event:x});if(!h.autoOpen){if(s.level>0){if(h.autoCloseOnClick&&!e&&!h.clickToOpen){x.data=h;h._closeAll(x)}}}else{if(h.autoCloseOnClick&&!e&&!h.clickToOpen){if(s.closeOnClick){x.data=h;h._closeAll(x)}}}if(e&&h.autoCloseOnClick){x.data=h;if(!s.hasItems){h._closeAll(x)}}if(x.target.tagName!="A"&&x.target.tagName!="a"){var v=s.anchor!=null?a(s.anchor):null;if(v!=null&&v.length>0){var u=v.attr("href");var w=v.attr("target");if(u!=null){if(w!=null){window.open(u,w)}else{window.location=u}}}}});h.removeHandler(o,"mouseenter");h.removeHandler(o,"mouseleave");if(!c&&h.mode!="simple"){h._renderHover(o,s,e)}if(s.subMenuElement!=null){var p=a(s.subMenuElement);if(h.mode=="simple"){p.show();return true}p.wrap('<div class="jqx-menu-popup '+h.toThemeProperty("jqx-menu-popup")+'" style="border: none; background-color: transparent; z-index:'+j+'; padding: 0px; margin: 0px; position: absolute; top: 0; left: 0; display: block; visibility: hidden;"><div style="background-color: transparent; border: none; position:absolute; overflow:hidden; left: 0; top: 0; right: 0; width: 100%; height: 100%;"></div></div>');p.css({overflow:"hidden",position:"absolute",left:0,display:"inherit",top:-p.outerHeight()});p.data("timer",{});if(s.level>0){p.css("left",-p.outerWidth())}else{if(h.mode=="horizontal"){p.css("left",0)}}j++;var r=a(s.subMenuElement).closest("div.jqx-menu-popup").css({width:parseInt(a(s.subMenuElement).outerWidth())+parseInt(d[0])+"px",height:parseInt(a(s.subMenuElement).outerHeight())+parseInt(d[1])+"px"});var t=o.closest("div.jqx-menu-popup");if(t.length>0){var l=p.css("margin-left");var n=p.css("margin-right");var m=p.css("padding-left");var q=p.css("padding-right");r.appendTo(t);p.css("margin-left",l);p.css("margin-right",n);p.css("padding-left",m);p.css("padding-right",q)}else{var l=p.css("margin-left");var n=p.css("margin-right");var m=p.css("padding-left");var q=p.css("padding-right");r.appendTo(a(document.body));p.css("margin-left",l);p.css("margin-right",n);p.css("padding-left",m);p.css("padding-right",q)}if(!h.clickToOpen){if(e||c){h.removeHandler(o,a.jqx.mobile.getTouchEventName("touchstart"));h.addHandler(o,a.jqx.mobile.getTouchEventName("touchstart"),function(u){clearTimeout(p.data("timer").hide);if(p!=null){p.stop()}if(s.level==0&&!s.isOpen&&h.mode!="popup"){u.data=h;h._closeAll(u)}if(!s.isOpen){h._openItem(h,s)}else{h._closeItem(h,s,true)}return false})}if(!c){h.addHandler(o,"mouseenter",function(){if(h.autoOpen||(s.level>0&&!h.autoOpen)){clearTimeout(p.data("timer").hide)}if(s.parentId&&s.parentId!=0){if(h.menuElements[s.parentId]){var u=h.menuElements[s.parentId].isOpen;if(!u){return}}}if(h.autoOpen||(s.level>0&&!h.autoOpen)){h._openItem(h,s)}return false});h.addHandler(o,"mousedown",function(){if(!h.autoOpen&&s.level==0){clearTimeout(p.data("timer").hide);if(p!=null){p.stop()}if(!s.isOpen){h._openItem(h,s)}else{h._closeItem(h,s,true)}}});h.addHandler(o,"mouseleave",function(v){if(h.autoCloseOnMouseLeave){clearTimeout(p.data("timer").hide);var y=a(s.subMenuElement);var u={left:parseInt(v.pageX),top:parseInt(v.pageY)};var x={left:parseInt(y.coord().left),top:parseInt(y.coord().top),width:parseInt(y.outerWidth()),height:parseInt(y.outerHeight())};var w=true;if(x.left-5<=u.left&&u.left<=x.left+x.width+5){if(x.top<=u.top&&u.top<=x.top+x.height){w=false}}if(w){h._closeItem(h,s,true)}}});h.removeHandler(r,"mouseenter");h.addHandler(r,"mouseenter",function(){clearTimeout(p.data("timer").hide)});h.removeHandler(r,"mouseleave");h.addHandler(r,"mouseleave",function(u){if(h.autoCloseOnMouseLeave){clearTimeout(p.data("timer").hide);clearTimeout(p.data("timer").show);if(p!=null){p.stop()}h._closeItem(h,s,true)}})}}else{h.removeHandler(o,"mousedown");h.addHandler(o,"mousedown",function(u){clearTimeout(p.data("timer").hide);if(p!=null){p.stop()}if(s.level==0&&!s.isOpen){u.data=h;h._closeAll(u)}if(!s.isOpen){h._openItem(h,s)}else{h._closeItem(h,s,true)}})}}});if(this.mode=="simple"){this._renderSimpleMode()}this._autoSizeHorizontalMenuItems();this._raiseEvent("3",this)},_renderSimpleMode:function(){this.host.show()},createID:function(){var b=Math.random()+"";b=b.replace(".","");b="99"+b;b=b/1;while(this.items[b]){b=Math.random()+"";b=b.replace(".","");b=b/1}return"menuItem"+b},_createMenu:function(c,f){if(c==null){return}if(f==undefined){f=true}if(f==null){f=true}var o=this;var t=a(c).find("li");var q=0;for(var j=0;j<t.length;j++){var m=t[j];var r=a(m);if(m.className.indexOf("jqx-menu")==-1&&this.autoGenerate==false){continue}var p=m.id;if(!p){p=this.createID()}if(f){m.id=p;this.items[q]=new a.jqx._jqxMenu.jqxMenuItem();this.menuElements[p]=this.items[q]}q+=1;var s=0;var v=this;var h=r.children();h.each(function(){if(!f){this.className="";if(v.autoGenerate){a(v.items[q-1].subMenuElement)[0].className="";if(!v.minimized){a(v.items[q-1].subMenuElement).addClass(v.toThemeProperty("jqx-widget-content"))}a(v.items[q-1].subMenuElement).addClass(v.toThemeProperty("jqx-menu-dropdown"));a(v.items[q-1].subMenuElement).addClass(v.toThemeProperty("jqx-popup"))}}if(this.className.indexOf("jqx-menu-dropdown")!=-1){if(f){v.items[q-1].subMenuElement=this}return false}else{if(v.autoGenerate&&(this.tagName=="ul"||this.tagName=="UL")){if(f){v.items[q-1].subMenuElement=this}this.className="";if(!v.minimized){a(this).addClass(v.toThemeProperty("jqx-widget-content"))}a(this).addClass(v.toThemeProperty("jqx-menu-dropdown"));a(this).addClass(v.toThemeProperty("jqx-popup"));a(this).attr("role","menu");if(v.rtl){a(this).addClass(v.toThemeProperty("jqx-rc-l"))}else{a(this).addClass(v.toThemeProperty("jqx-rc-r"))}a(this).addClass(v.toThemeProperty("jqx-rc-b"));return false}}});var u=r.parents();u.each(function(){if(this.className.indexOf("jqx-menu-item")!=-1){s=this.id;return false}else{if(v.autoGenerate&&(this.tagName=="li"||this.tagName=="LI")){s=this.id;return false}}});var e=false;var d=m.getAttribute("type");var b=m.getAttribute("ignoretheme")||m.getAttribute("data-ignoretheme");if(b){if(b=="true"||b==true){b=true}}else{b=false}if(!d){d=m.type}else{if(d=="separator"){var e=true}}if(!e){if(s){d="sub"}else{d="top"}}var g=this.items[q-1];if(f){g.id=p;g.parentId=s;g.type=d;g.separator=e;g.element=t[j];var l=r.children("a");g.disabled=m.getAttribute("item-disabled")=="true"?true:false;g.level=r.parents("li").length;g.anchor=l.length>0?l:null}g.ignoretheme=b;var n=this.menuElements[s];if(n!=null){if(n.ignoretheme){g.ignoretheme=n.ignoretheme;b=n.ignoretheme}}if(this.autoGenerate){if(d=="separator"){r.removeClass();r.addClass(this.toThemeProperty("jqx-menu-item-separator"));r.attr("role","separator")}else{if(!b){r[0].className="";if(this.rtl){r.addClass(this.toThemeProperty("jqx-rtl"))}if(g.level>0&&!v.minimized){r.addClass(this.toThemeProperty("jqx-item"));r.addClass(this.toThemeProperty("jqx-menu-item"))}else{r.addClass(this.toThemeProperty("jqx-item"));r.addClass(this.toThemeProperty("jqx-menu-item-top"))}}}}if(g.disabled){r.addClass(v.toThemeProperty("jqx-menu-item-disabled"));r.addClass(v.toThemeProperty("jqx-fill-state-disabled"))}if(f&&!b){g.hasItems=r.find("li").length>0;if(g.hasItems){if(g.element){a.jqx.aria(a(g.element),"aria-haspopup",true);if(!g.subMenuElement.id){g.subMenuElement.id=a.jqx.utilities.createId()}a.jqx.aria(a(g.element),"aria-owns",g.subMenuElement.id)}}}}},destroy:function(){a.jqx.utilities.resize(this.host,null,true);var d=this.host.closest("div.jqx-menu-wrapper");d.remove();a("#menuWrapper"+this.element.id).remove();var b=this;this.removeHandler(a(document),"mousedown.menu"+this.element.id,b._closeAfterClick);this.removeHandler(a(document),"mouseup.menu"+this.element.id,b._closeAfterClick);a.data(document.body,"jqxMenuOldHost"+this.element.id,null);if(this.isTouchDevice()){this.removeHandler(a(document),a.jqx.mobile.getTouchEventName("touchstart")+".menu"+this.element.id,this._closeAfterClick,this)}if(a(window).off){a(window).off("resize.menu"+b.element.id)}a.each(this.items,function(){var g=this;var f=a(g.element);b.removeHandler(f,"click");b.removeHandler(f,"selectstart");b.removeHandler(f,"mouseenter");b.removeHandler(f,"mouseleave");b.removeHandler(f,"mousedown");b.removeHandler(f,"mouseleave");var e=a(g.subMenuElement);var h=e.closest("div.jqx-menu-popup");h.remove();delete this.subMenuElement;delete this.element});a.data(document.body,"menuel",null);delete this.menuElements;this.items=new Array();delete this.items;var c=a.data(this.element,"jqxMenu");if(c){delete c.instance}this.host.removeClass();this.host.remove();delete this.host;delete this.element},_raiseEvent:function(f,c){if(c==undefined){c={owner:null}}var d=this.events[f];args=c;args.owner=this;var e=new a.Event(d);if(f=="2"){args=c.item;args.owner=this;a.extend(e,c.event);e.type="itemclick"}e.owner=this;e.args=args;var b=this.host.trigger(e);return b},propertyChangedHandler:function(b,d,g,f){if(this.isInitialized==undefined||this.isInitialized==false){return}if(d=="disabled"){if(b.disabled){b.host.addClass(b.toThemeProperty("jqx-fill-state-disabled"));b.host.addClass(b.toThemeProperty("jqx-menu-disabled"))}else{b.host.removeClass(b.toThemeProperty("jqx-fill-state-disabled"));b.host.removeClass(b.toThemeProperty("jqx-menu-disabled"))}}if(f==g){return}if(d=="touchMode"){this._isTouchDevice=null;b._render(f,g)}if(d=="source"){if(b.source!=null){var c=b.loadItems(b.source);b.element.innerHTML=c;var e=b.host.find("ul:first");if(e.length>0){b.refresh();b._createMenu(e[0]);b._render()}}}if(d=="autoCloseOnClick"){if(f==false){b.removeHandler(a(document),"mousedown.menu"+this.element.id,b._closeAll)}else{b.addHandler(a(document),"mousedown.menu"+this.element.id,b,b._closeAll)}}else{if(d=="mode"||d=="width"||d=="height"||d=="showTopLevelArrows"){b.refresh();if(d=="mode"){b._render(f,g)}else{b._applyOrientation()}}else{if(d=="theme"){a.jqx.utilities.setTheme(g,f,b.host)}}}}})})(jqxBaseFramework);(function(a){a.jqx._jqxMenu.jqxMenuItem=function(e,d,c){var b={id:e,parentId:d,parentItem:null,anchor:null,type:c,disabled:false,level:0,isOpen:false,hasItems:false,element:null,subMenuElement:null,arrow:null,openHorizontalDirection:"right",openVerticalDirection:"down",closeOnClick:true};return b}})(jqxBaseFramework); \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/js/main.js b/src/static/movio/templates/Sliding-windows/js/main.js new file mode 100755 index 0000000..af41f65 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/js/main.js @@ -0,0 +1,89 @@ +$(window).load(function() { + Movio.init(); + + $(".menu").jqxMenu({}); + + // TOOLTIP + $(function() { + $("[rel='tooltip']").tooltip(); + $('#element').tooltip('show') + }); + + /* SBLOCCA PER ATTIVARE */ + // scrollbar documentation http://manos.malihu.gr/jquery-custom-content-scroller/ + $(".overflow").mCustomScrollbar({ + scrollButtons:{ + enable:true + }, + mouseWheel: false, + advanced:{ + updateOnContentResize: true + } + }); + + // PLACEOLDER + //Assign to those input elements that have 'placeholder' attribute + if($.browser.msie){ + $('input[placeholder]').each(function(){ + + var input = $(this); + + $(input).val(input.attr('placeholder')); + + $(input).focus(function(){ + if (input.val() == input.attr('placeholder')) { + input.val(''); + } + }); + + $(input).blur(function(){ + if (input.val() == '' || input.val() == input.attr('placeholder')) { + input.val(input.attr('placeholder')); + } + }); + }); + }; + + // ADD HEIGHT MAIN CONTENT + var width1 = $(window).width(); + if(width1 >= 700) { + function resize() { + var h = $(window).height() - $('#header').height() - $('#footer').height(); + $('.main-content').height(h); + $('.slideshow .slide').height(h); + } + + $(window).resize(function () { + resize(); + }); + + resize(); + } + + // VIDEO YOUTUBE LIQUID + // Find all YouTube videos + var $allVideos = $("iframe[src^='http://www.youtube.com']"), + // The element that is fluid width + $fluidEl = $(".item-slide-height-full"); + // Figure out and save aspect ratio for each video + $allVideos.each(function() { + $(this) + .data('aspectRatio', this.width / (this.height)) + .removeAttr('height') + .removeAttr('width') + }); + + // When the window is resized + // (You'll probably want to debounce this) + $(window).resize(function() { + var newHeight = $fluidEl.height() -20; + // Resize all videos according to their own aspect ratio + $allVideos.each(function() { + var $el = $(this); + $el + .height(newHeight) + .width(newHeight * $el.data('aspectRatio')); + }); + // Kick off one resize to fix all videos on page load + }).resize(); +}); diff --git a/src/static/movio/templates/Sliding-windows/less/element.less b/src/static/movio/templates/Sliding-windows/less/element.less new file mode 100755 index 0000000..42bc8d3 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/element.less @@ -0,0 +1,1320 @@ +/** + * Search form in top bar + */ +form.top-search { + position:absolute; + top:0; + right:0; + margin:10px 80px 0 0; + + p { + .padding-margin-reset(); + label, input { + display:inline-block; + float:left; + } + label { + padding:4px 8px 0 0; + color:#fff; + display:none; + } + input[type="text"] { + width:290px; + height: 20px; + border:1px solid @border-input-header; + background:transparent; + color:@box-header-link; + font-size:12px; + + } + + ::-webkit-input-placeholder { + text-transform:uppercase; + color:@box-header-link; + } + + :-moz-placeholder { /* Firefox 18- */ + text-transform:uppercase; + color:@box-header-link; + } + + ::-moz-placeholder { /* Firefox 19+ */ + text-transform:uppercase; + color:@box-header-link; + } + + :-ms-input-placeholder { + text-transform:uppercase; + color:@box-header-link; + } + + input[type="submit"] { + display:none; + } + } +} + +/** + * Page title + */ + .box-title { + padding-bottom:10px; + margin-bottom:30px; + + h1, h2 { + .padding-margin-reset(); + font-family:@font-2; + } + + h1 { + font-size:33px; + padding-bottom:6px; + } + + h2 { + font-size:20px; + font-style:italic; + border-top:1px solid @border-sub-title-page; + padding-top:6px; + } + +} + +/** + * Box with collapse button + */ +.box { + position:relative; + + h1 { + .padding-margin-reset(); + font-size:20px; + line-height:2.5em; + } + + .container { + .padding-margin-reset(); + position:relative; + width:auto; + } + + img { + margin-bottom:10px; + } + + p { + word-break:break-strict; + } + + .show-content-box { + position:absolute; + width:21px; + height:21px; + display:block; + text-indent:-9999px; + cursor:pointer; + top:0; + margin-top:1px; + margin-left:4px; + .border-radius(0); + box-shadow:none; + background:@color-background-button; + + &:after { + top:50%; + margin-top:-2px; + content:" "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border: @solid transparent; + border-top-color:@color-arrow-button-slider; + border-width:8px; + left: 50%; + margin-left: -8px; + } + &:hover { + &:after { + border-top-color:@color-arrow-button-slider-hover; + } + } + &.collapsed { + &:after { + top:50%; + margin-top:-10px; + content:" "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border: @solid transparent; + border-color:transparent; + border-bottom-color:@color-arrow-button-slider; + border-width: 6px; + left: 50%; + margin-left: -6px; + } + &:hover { + &:after { + border-bottom-color:@color-arrow-button-slider-hover; + } + } + } + } +} + + +/** + * Home slider + */ +.slideshow { + height:100%; + position:absolute; + background-color:@slider-background; + z-index:2; + width:100%; + .padding-margin-reset(); + margin-left:-15px; + margin-right:-15px; + + .slide { + background-size:cover!important; + background-position:top center!important; + position:relative; + } + + .description { + width: 509px; + .box-sizing(); + margin-left:0; + height:212px; + overflow:hidden; + position:absolute; + top:50%; + left:50%; + margin:-106px 0 0 -254px; + background: url(../img/bg/bg-opacity.png) repeat; + padding:20px; + + h1 { + font-family: @font-2; + font-size:30px; + font-style:italic; + text-align:center; + padding-bottom:20px; + + a { + color:@slider-text; + text-decoration:none; + } + } + + p { + font-family: @font-2; + color:@slider-text; + line-height:1em; + font-size:40px; + display:block; + margin:0 auto; + width:357px; + padding-top:20px; + text-align:center; + border-top:1px solid @slider-text; + } + + a.link-continue { + display:block; + position:absolute; + width:100%; + height:100%; + top:0; + left:0; + text-indent:-9999px; + } + } +} + +/** + * Main image in entity detail + */ +figure.main-img { + padding:0; + position:relative; + padding:0 15px 10px 0; + margin: 0; + max-width:auto; + margin-bottom:15px; + + + img { + padding:5px; + border:1px @solid @box-image-border; + float:left; + margin-bottom:8px; + + } + .description { + font-size: 95%; + line-height: 1.2em; + padding:0; + margin:0; + position:relative; + bottom:0; + float:left; + clear:left; + width:auto; + padding-right:10px; + word-wrap:break-word; + + strong { + display:block; + } + } + + .superzoom { + bottom:0; + margin-left:6px; + margin-bottom:41px; + left:0; + position:absolute; + } + + &.align-left { + float:left; + margin-right:20px; + padding-right:0; + } + + &.align-right { + float:right; + margin-left:20px; + padding-right:0; + img { + float:right; + } + .description { + float:right; + text-align:right; + clear:right; + padding-left:10px; + padding-right:0; + } + } + + @media (max-width: 480px) { + margin:0 0 15px 0; + width:288px; + } +} + +/** + * Search results + */ +.results-content { + + .slick-next { + margin-right:-15px; + } + + .item { + border-bottom:1px @solid @box-relation-item-border; + padding-bottom:15px; + margin-bottom:15px; + text-align:center; + + figure { + width:135px; + height:135px; + float:left; + margin: 0 15px 0 0; + + img { + + } + } + + h1 { + font-size:18px; + padding:0; + margin:0; + font-family:@font-2; + line-height:1em; + margin-bottom:5px; + text-align:left; + + a { + text-decoration:none; + &:hover { + text-decoration:underline; + } + } + } + + p { + font-size:14px; + line-height:18px; + padding:0; + margin:0; + text-align:left; + } + + &.in-grid { + border:1px @solid @box-border; + padding:15px; + min-height:165px; + margin-right:1.777777%; + width:21.33333333%; + min-height:360px; + + &.slide { + width:auto; + float:left; + margin-right:20px; + + &.fix-width { + width:240px; + margin-right:20px!important; + margin-left:20px!important; + } + + } + + background:@box-background; + + img { + margin-bottom:15px; + display:block; + margin-left:auto; + margin-right:auto; + } + + h2 { + font-size:20px; + line-height:1em; + .padding-margin-reset(); + margin:0 0; + padding:10px 0; + border-top:1px @solid @box-border; + border-bottom:1px @solid @box-border; + + a { + color:@color-link-enity; + } + + } + + figure { + width:auto; + height:auto; + float:none; + display:block; + margin:0 auto; + + img { + float:none; + } + } + } + + } +} + +/** + * Entity relations image + */ +.relationImage { + .box-shadow (@x: 0, @y: 0, @blur:4px, @color: #999); + border:1px solid @box-border; + margin-bottom:10px; + overflow:hidden; + + .container { + height:100px; + padding-top:12px; + } + + h1 { + font-size:14px; + font-family: @font-1; + padding:0; + margin:0; + height:24px; + line-height:1em; + border-bottom:1px @solid @box-border; + color:@text; + padding-top:5px; + padding-left:35px; + a { + color:@text; + text-decoration:none; + } + } + + .slider { + padding-left:15px; + padding-right:15px; + height:auto; + height:77px; + } + + .slide { + text-align:center; + margin-right:10px; + padding-bottom:0; + + img { + display:block; + margin:0 auto; + } + + } +} + +/** + * Entity relations general + */ +.relationGeneral { + .box-shadow (@x: 0, @y: 0, @blur:4px, @color: #999); + border:1px solid @box-border; + margin-bottom:10px; + overflow:hidden; + + .container { + height:415px; + padding-top:12px; + } + + h1 { + font-size:14px; + font-family: @font-1; + padding:0; + margin:0; + height:24px; + line-height:1em; + border-bottom:1px @solid @box-border; + color:@text; + padding-top:5px; + padding-left:35px; + a { + color:@text; + text-decoration:none; + } + } + + .slider { + padding-left:15px; + padding-right:15px; + height:auto; + height:77px; + } + + .slide { + text-align:center; + margin-right:10px; + padding-bottom:0; + + img { + display:block; + margin:0 auto; + } + + } +} + +/** + * Entity relations links + */ +.relationLink { + .box-shadow (@x: 0, @y: 0, @blur:4px, @color: #999); + border:1px solid @box-border; + margin-bottom:10px; + + h1 { + font-size:14px; + font-family: @font-1; + padding:0; + margin:0; + height:24px; + line-height:1em; + border-bottom:1px @solid @box-border; + color:@text; + padding-top:5px; + padding-left:35px; + a { + color:@text; + text-decoration:none; + } + } + .item-list { + padding:0 0 5px 0; + margin:0 0; + li { + list-style:none; + padding-left:14px; + border-bottom:1px @solid @box-relation-item-border; + a { + text-decoration:none; + display:block; + color:@box-text; + line-height:1.2em; + padding-left:20px; + position:relative; + font-size:14px; + padding-top:5px; + padding-bottom:5px; + &:before { + display:block; + position:absolute; + width:15px; + height:10px; + top:0; + left:0; + margin:5px 0 0 0; + font-family:'FontAwesome'; + content: @fa-var-eye; + color:@color-arrow-button-slider-hover; + } + &:hover { + &:before { + color:@color-arrow-button-slider-hover; + } + } + } + &:last-child { + border:0; + a { + padding-bottom:0; + margin-bottom:0; + } + } + } + } +} + +/** + * Entity relations image link + */ +.relationImageLink { + .box-shadow (@x: 0, @y: 0, @blur:4px, @color: #999); + border:1px solid @box-border; + margin-bottom:20px; + + .container { + height:160px; + padding-top:12px; + } + + h1 { + font-size:14px; + font-family: @font-1; + padding:0; + margin:0; + height:24px; + line-height:1em; + border-bottom:1px @solid @box-border; + color:@text; + padding-top:5px; + padding-left:35px; + a { + color:@text; + text-decoration:none; + } + } + + .slider { + padding-left:20px; + padding-right:15px; + } + + .item { + border:1px solid @box-border; + padding:5px; + margin-right:10px; + overflow:hidden; + height:135px; + + img { + margin-bottom:5px; + } + + h2 { + color:@box-text; + font-size:14px; + line-height:1em!important; + .padding-margin-reset(); + font-weight:600; + padding-bottom:5px; + a { + color:@box-text; + } + } + + p { + line-height:1em; + font-size:12px; + .padding-margin-reset(); + } + + } + +} + + +/** + * Storyteller + */ +.storyteller { + background:@storyteller-background; + border:1px solid @storyteller-border; + padding-bottom:15px; + margin-bottom:20px; + .box-sizing(); + width:100%; + clear:both; + + #nav-bar { + min-height:40px; + background:#ececec; + ul { + .padding-margin-reset(); + margin-left:10px; + @media (max-width: 480px) { + margin-left:-1px; + margin-right:-1px; + margin-top:-1px; + } + li { + list-style:none; + display:inline; + padding:10px 10px; + height:40px; + float:left; + @media (max-width: 480px) { + display:block; + float:none; + } + &:hover, &.active { + background-color: @storyteller-item-background; + @media (max-width: 480px) { + background-color:transparent; + } + a { + color:@text; + text-decoration:none; + border-bottom:4px solid @sidebar-background-hover; + } + } + border-left:1px solid @storyteller-border; + a { + display:inline-block; + color:@storyteller-navigation-link; + text-decoration:none; + text-transform:uppercase; + } + &:last-child { + border-right:1px solid @storyteller-border; + } + } + } + } + + .content-story { + padding-top:20px; + } + + .item-box { + position:relative; + background: @storyteller-item-background; + display:block; + width:95%; + margin:0 auto 35px auto; + padding:10px; + .box-sizing(); + + h1 { + font-size: 18px; + } + h2 { + font-size: 16px; + } + h4 { + font-size: 14px; + } + + &.with-angle-icon { + background:@storyteller-item-background url(../img/bg/bg-box.png) 99.8% 2px no-repeat; + } + + .box-angle { + font-size:15px; + position:absolute; + right:0; + top:0; + margin:7px 5px 0 0; + } + + &.comment { + background:@storyteller-comments-background; + form { + margin-top:20px; + margin-left:auto; + margin-right:auto; + width:200px; + span { + min-width:110px; + text-align:right; + display:inline-block; + margin-right:10px; + } + input[type="text"], textarea { + display:inline-block; + width:100%; + } + } + } + &.gallery { + background:@storyteller-item-background; + } + .arrow-big { + background:url(../img/ico/arrow-baloon-big.png) 0 0 no-repeat; + width:18px; + height:16px; + display:block; + position:absolute; + top:0; + left:50%; + margin-left:-9px; + margin-top:-16px; + } + iframe { + width: 100%; + margin: 0 0 30px 0; + } + .functions { + .from { + color:@storyteller-link; + span { + font-weight:bold; + color:@text; + } + } + .actions { + border-top:1px solid @storyteller-border; + margin-top:4px; + padding-top:4px; + padding-bottom:8px; + ul { + .padding-margin-reset(); + padding-top:8px; + &.dx { + float:right; + li a { + text-decoration:none; + } + li i { + font-size:18px; + } + } + &.sx { + float:left; + } + li { + list-style:none; + display:inline; + border-right:1px solid @storyteller-border; + padding:5px 10px; + &:last-child { + border:0; + } + i { + color:@storyteller-icon; + margin-right:5px; + } + a { + display:inline-block; + text-decoration:none; + padding:0; + line-height:16px; + &:hover { + text-decoration:underline; + } + } + } + } + } + } + .archive-link { + text-align:center; + padding-top:5px; + } + + .item-comment { + border-bottom:1px solid @storyteller-border; + padding-bottom:10px; + margin-bottom:10px; + &:last-child { + border-bottom:0; + padding-bottom:0; + margin-bottom:0; + } + } + + .story-gallery { + border-top:1px solid @storyteller-border; + padding-top:20px; + padding-bottom:20px; + padding-left:10px; + padding-right:10px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + .mini-photo { + border:1px solid transparent; + padding-right:0px; + float:left; + width:82px; + height:82px; + position:relative; + margin-right:12px; + margin-bottom:12px; + &:last-child { + margin-right:0; + } + img { + margin:0; + float:none; + padding:2px; + margin-right:8px; + border:1px @solid @storyteller-image-border; + .border-radius (0); + } + &:last-child { + &:hover { + .popup { + margin-left:-80px; + .popup-arrow { + right:0; + left:auto; + margin-right:8px; + } + } + } + } + &:hover { + .popup { + visibility:visible; + } + } + } + } + } + } + ul.insights { + list-style: none; + margin: 10px 0; + padding: 0; + li { + float: left; + padding-right: 10px; + margin-right: 10px; + border-right: 1px solid @storyteller-border; + &:last-child { + margin-right: 0; + padding-right: 0; + border: 0; + } + } + +} + + +/** + * Gallery.io override + */ +.wrapper-galleria-io { + padding:5px; + border:1px @solid @box-border; + margin-bottom:40px; + clear:both; + + .content-galleria-io { + max-width:100%; + position:relative; + font-family: @font-1; + &:hover { + .galleria-info-description { + opacity:1; + filter: alpha(opacity=100); + } + } + .galleria-info { + margin-bottom:10px; + } + + .galleria-info-text { + .galleria-info-title { + + } + } + + + .galleria-info-description { + opacity:0; + filter: alpha(opacity=0); + position:absolute; + margin:0 0 31px -15px!important; + bottom:0!important; + display:block; + width:100%; + background: url(../img/bg/bg-description.png) repeat; + padding:5px 15px; + padding-right:40px; + .box-sizing(); + border-top:1px @solid #000; + border-right:1px @solid #000; + width:430px; + + } + } + .galleria-counter { + margin-bottom:10px; + margin-right:46px; + } + + &.slider { + border: 0; + } + + #galleria.sfogliatore { + + .galleria-info { + position: absolute; + height:15px; + left:0px; + bottom:0; + margin-bottom:5px!important; + color: #bbb; + margin-right:40px; + } + .galleria-info-description { + margin:0 0 15px -5px!important; + } + } + + #galleria.slider { + .galleria-info-text { + top:auto; + bottom:0; + margin-bottom:-12px; + } + } +} + + +/** + * Image list + */ +.imageList { + margin-bottom:30px!important; + display:block; + clear:both; + padding-left:15px; + padding-right:15px; +} + +.issue-slider { + margin-bottom:20px!important; + margin-left:-15px; + margin-right:-15px; + + &.storyteller { + background:none; + border:0; + padding-bottom:0; + margin-bottom:0; + .box-sizing(); + width:auto; + clear:both; + } + +} + +/* item-slide */ +.item-slide { + height:448px; + overflow:hidden; + padding:5px; + margin-right:50px; + opacity:.5; + position:relative; + + &.height-auto { + height:auto; + + .content-slide { + height:auto; + } + + } + + &.story-slide { + + .content-slide { + + .arrow-big { + display:none; + } + + .item-box { + background: @storyteller-item-background; + width:100%; + margin:0 auto 0 auto; + .box-sizing(); + + &.comment { + background:@storyteller-comments-background; + form { + margin-top:0; + margin:0 auto; + width:300px!important; + span { + min-width: inherit; + text-align:left; + display:inline-block; + margin-right:0; + } + input[type="text"], textarea { + display:block; + width:300px!important; + } + } + } + + iframe { + position:relative; + -moz-transform:none; + display:block; + width:100%; + height:100%; + margin-bottom:0; + } + + } + + + } + + } + + &.slick-center { + opacity:1; + } + + .content-slide { + height:100%; + padding:5px; + .box-shadow (@x: 0, @y: 0, @blur:4px, @color: #999); + } + + &.picture { + + figure img { + display:block; + margin:0 auto; + width:100%; + max-width:100%; + } + + figcaption { + font-size:14px; + padding-top:2px; + display:block; + margin:0 auto; + text-align:center; + } + + } + + &.text { + .content-slide { + padding:10px; + } + } + + &.link { + .content-slide { + padding:0; + .box-shadow (@x: 0, @y: 0, @blur:4px, @color:transparent); + } + } + +} + +/* quick-slider-nav */ +.quick-slider-nav { + height:39px; + margin-bottom:12px; + text-align:center; + + &.text-link { + + ul { + + li { + margin-right:9px; + border-right:1px solid @box-border; + + &:last-child { + border-right:0; + margin-right:0; + } + + a { + font-size:15px; + color:@text; + margin-right:13px; + } + } + + } + + } + + ul { + .padding-margin-reset(); + text-align:center; + border:1px solid @box-border; + display:inline-block; + padding:7px 5px 0 5px; + + li { + display: inline; + height:39px; + + span.fa { + display:inline-block; + font-size:25px; + height:32px; + cursor:pointer; + color:@text; + padding-top:5px; + opacity:.5; + text-align:center; + } + + a { + display:inline-block; + margin-right:9px; + cursor:pointer; + + &:hover, &.active { + border-bottom:5px solid @border-color-link; + span { + opacity:1; + } + text-decoration:none; + } + + } + + } + + } + +} + +/** + * Timeline + */ +.storyjs-embed.sized-embed { + border-radius: 0; +} + +.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content h3, .vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3 { + color: @timeline-theme !important; +} + +.vco-timeline .vco-navigation .timenav-background .timenav-line, +.vco-timeline .vco-navigation .timenav .content .marker.active .line, +.vco-timeline .vco-navigation .timenav .content .marker.active .dot { + background-color: @timeline-theme !important; +} + +.vco-timeline .vco-navigation .timenav .content .marker .line .event-line { + background: @timeline-theme !important; +} + +/* box-gallery-description */ +.box-gallery-description { + display:block; + margin-bottom:20px!important; + padding-top:20px; + position:relative; + + &:before { + content:""; + display:block; + width:50%; + height:1px; + top:0; + left:50%; + position:absolute; + margin-left:-25%; + background:@box-border; + } + + &:after { + content:""; + display:block; + width:50%; + height:1px; + bottom:0; + left:50%; + position:absolute; + margin-left:-25%; + background:@box-border; + } + +} + +/* ImageHotspot */ + +.movio-hotspotContainer { + position: relative; + border:1px @solid @box-image-border; + .border-radius (2px); + padding: 3px; + display: inline-block; + width: 100%; + + .movio-imageHotspot-scale { + position: absolute; + left: 0; + top: 0; + } + + + .movio-hotspot, .movio-hotspot-circle { + border: 2px solid @white; + .box-shadow(0, 0, 2px, @black); + position: absolute; + z-index: 999; + cursor: pointer; + + &:hover { + border: 2px solid @color-link; + } + } + + .movio-hotspot-circle { + border-radius: 50%; + } + + img { + max-width: 100%; + height: auto; + } + + +} diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/bordered-pulled.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/bordered-pulled.less new file mode 100644 index 0000000..9bb4d3a --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/bordered-pulled.less @@ -0,0 +1,16 @@ +// Bordered & Pulled +// ------------------------- + +.@{fa-css-prefix}-border { + padding: .2em .25em .15em; + border: @solid .08em @fa-border-color; + border-radius: .1em; +} + +.pull-right { float: right; } +.pull-left { float: left; } + +.@{fa-css-prefix} { + &.pull-left { margin-right: .3em; } + &.pull-right { margin-left: .3em; } +} diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/core.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/core.less new file mode 100644 index 0000000..6d223bc --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/core.less @@ -0,0 +1,12 @@ +// Base Class Definition +// ------------------------- + +.@{fa-css-prefix} { + display: inline-block; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/fixed-width.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/fixed-width.less new file mode 100644 index 0000000..110289f --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/fixed-width.less @@ -0,0 +1,6 @@ +// Fixed Width Icons +// ------------------------- +.@{fa-css-prefix}-fw { + width: (18em / 14); + text-align: center; +} diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/font-awesome.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/font-awesome.less new file mode 100644 index 0000000..96d2f22 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/font-awesome.less @@ -0,0 +1,17 @@ +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */ + +@import "variables"; +@import "mixins"; +@import "path"; +@import "core"; +@import "larger"; +@import "fixed-width"; +@import "list"; +@import "bordered-pulled"; +@import "spinning"; +@import "rotated-flipped"; +@import "stacked"; +@import "icons"; diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/icons.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/icons.less new file mode 100644 index 0000000..bf0f856 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/icons.less @@ -0,0 +1,412 @@ +/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen + readers do not read off random characters that represent icons */ + +.@{fa-css-prefix}-glass:before { content: @fa-var-glass; } +.@{fa-css-prefix}-music:before { content: @fa-var-music; } +.@{fa-css-prefix}-search:before { content: @fa-var-search; } +.@{fa-css-prefix}-envelope-o:before { content: @fa-var-envelope-o; } +.@{fa-css-prefix}-heart:before { content: @fa-var-heart; } +.@{fa-css-prefix}-star:before { content: @fa-var-star; } +.@{fa-css-prefix}-star-o:before { content: @fa-var-star-o; } +.@{fa-css-prefix}-user:before { content: @fa-var-user; } +.@{fa-css-prefix}-film:before { content: @fa-var-film; } +.@{fa-css-prefix}-th-large:before { content: @fa-var-th-large; } +.@{fa-css-prefix}-th:before { content: @fa-var-th; } +.@{fa-css-prefix}-th-list:before { content: @fa-var-th-list; } +.@{fa-css-prefix}-check:before { content: @fa-var-check; } +.@{fa-css-prefix}-times:before { content: @fa-var-times; } +.@{fa-css-prefix}-search-plus:before { content: @fa-var-search-plus; } +.@{fa-css-prefix}-search-minus:before { content: @fa-var-search-minus; } +.@{fa-css-prefix}-power-off:before { content: @fa-var-power-off; } +.@{fa-css-prefix}-signal:before { content: @fa-var-signal; } +.@{fa-css-prefix}-gear:before, +.@{fa-css-prefix}-cog:before { content: @fa-var-cog; } +.@{fa-css-prefix}-trash-o:before { content: @fa-var-trash-o; } +.@{fa-css-prefix}-home:before { content: @fa-var-home; } +.@{fa-css-prefix}-file-o:before { content: @fa-var-file-o; } +.@{fa-css-prefix}-clock-o:before { content: @fa-var-clock-o; } +.@{fa-css-prefix}-road:before { content: @fa-var-road; } +.@{fa-css-prefix}-download:before { content: @fa-var-download; } +.@{fa-css-prefix}-arrow-circle-o-down:before { content: @fa-var-arrow-circle-o-down; } +.@{fa-css-prefix}-arrow-circle-o-up:before { content: @fa-var-arrow-circle-o-up; } +.@{fa-css-prefix}-inbox:before { content: @fa-var-inbox; } +.@{fa-css-prefix}-play-circle-o:before { content: @fa-var-play-circle-o; } +.@{fa-css-prefix}-rotate-right:before, +.@{fa-css-prefix}-repeat:before { content: @fa-var-repeat; } +.@{fa-css-prefix}-refresh:before { content: @fa-var-refresh; } +.@{fa-css-prefix}-list-alt:before { content: @fa-var-list-alt; } +.@{fa-css-prefix}-lock:before { content: @fa-var-lock; } +.@{fa-css-prefix}-flag:before { content: @fa-var-flag; } +.@{fa-css-prefix}-headphones:before { content: @fa-var-headphones; } +.@{fa-css-prefix}-volume-off:before { content: @fa-var-volume-off; } +.@{fa-css-prefix}-volume-down:before { content: @fa-var-volume-down; } +.@{fa-css-prefix}-volume-up:before { content: @fa-var-volume-up; } +.@{fa-css-prefix}-qrcode:before { content: @fa-var-qrcode; } +.@{fa-css-prefix}-barcode:before { content: @fa-var-barcode; } +.@{fa-css-prefix}-tag:before { content: @fa-var-tag; } +.@{fa-css-prefix}-tags:before { content: @fa-var-tags; } +.@{fa-css-prefix}-book:before { content: @fa-var-book; } +.@{fa-css-prefix}-bookmark:before { content: @fa-var-bookmark; } +.@{fa-css-prefix}-print:before { content: @fa-var-print; } +.@{fa-css-prefix}-camera:before { content: @fa-var-camera; } +.@{fa-css-prefix}-font:before { content: @fa-var-font; } +.@{fa-css-prefix}-bold:before { content: @fa-var-bold; } +.@{fa-css-prefix}-italic:before { content: @fa-var-italic; } +.@{fa-css-prefix}-text-height:before { content: @fa-var-text-height; } +.@{fa-css-prefix}-text-width:before { content: @fa-var-text-width; } +.@{fa-css-prefix}-align-left:before { content: @fa-var-align-left; } +.@{fa-css-prefix}-align-center:before { content: @fa-var-align-center; } +.@{fa-css-prefix}-align-right:before { content: @fa-var-align-right; } +.@{fa-css-prefix}-align-justify:before { content: @fa-var-align-justify; } +.@{fa-css-prefix}-list:before { content: @fa-var-list; } +.@{fa-css-prefix}-dedent:before, +.@{fa-css-prefix}-outdent:before { content: @fa-var-outdent; } +.@{fa-css-prefix}-indent:before { content: @fa-var-indent; } +.@{fa-css-prefix}-video-camera:before { content: @fa-var-video-camera; } +.@{fa-css-prefix}-picture-o:before { content: @fa-var-picture-o; } +.@{fa-css-prefix}-pencil:before { content: @fa-var-pencil; } +.@{fa-css-prefix}-map-marker:before { content: @fa-var-map-marker; } +.@{fa-css-prefix}-adjust:before { content: @fa-var-adjust; } +.@{fa-css-prefix}-tint:before { content: @fa-var-tint; } +.@{fa-css-prefix}-edit:before, +.@{fa-css-prefix}-pencil-square-o:before { content: @fa-var-pencil-square-o; } +.@{fa-css-prefix}-share-square-o:before { content: @fa-var-share-square-o; } +.@{fa-css-prefix}-check-square-o:before { content: @fa-var-check-square-o; } +.@{fa-css-prefix}-arrows:before { content: @fa-var-arrows; } +.@{fa-css-prefix}-step-backward:before { content: @fa-var-step-backward; } +.@{fa-css-prefix}-fast-backward:before { content: @fa-var-fast-backward; } +.@{fa-css-prefix}-backward:before { content: @fa-var-backward; } +.@{fa-css-prefix}-play:before { content: @fa-var-play; } +.@{fa-css-prefix}-pause:before { content: @fa-var-pause; } +.@{fa-css-prefix}-stop:before { content: @fa-var-stop; } +.@{fa-css-prefix}-forward:before { content: @fa-var-forward; } +.@{fa-css-prefix}-fast-forward:before { content: @fa-var-fast-forward; } +.@{fa-css-prefix}-step-forward:before { content: @fa-var-step-forward; } +.@{fa-css-prefix}-eject:before { content: @fa-var-eject; } +.@{fa-css-prefix}-chevron-left:before { content: @fa-var-chevron-left; } +.@{fa-css-prefix}-chevron-right:before { content: @fa-var-chevron-right; } +.@{fa-css-prefix}-plus-circle:before { content: @fa-var-plus-circle; } +.@{fa-css-prefix}-minus-circle:before { content: @fa-var-minus-circle; } +.@{fa-css-prefix}-times-circle:before { content: @fa-var-times-circle; } +.@{fa-css-prefix}-check-circle:before { content: @fa-var-check-circle; } +.@{fa-css-prefix}-question-circle:before { content: @fa-var-question-circle; } +.@{fa-css-prefix}-info-circle:before { content: @fa-var-info-circle; } +.@{fa-css-prefix}-crosshairs:before { content: @fa-var-crosshairs; } +.@{fa-css-prefix}-times-circle-o:before { content: @fa-var-times-circle-o; } +.@{fa-css-prefix}-check-circle-o:before { content: @fa-var-check-circle-o; } +.@{fa-css-prefix}-ban:before { content: @fa-var-ban; } +.@{fa-css-prefix}-arrow-left:before { content: @fa-var-arrow-left; } +.@{fa-css-prefix}-arrow-right:before { content: @fa-var-arrow-right; } +.@{fa-css-prefix}-arrow-up:before { content: @fa-var-arrow-up; } +.@{fa-css-prefix}-arrow-down:before { content: @fa-var-arrow-down; } +.@{fa-css-prefix}-mail-forward:before, +.@{fa-css-prefix}-share:before { content: @fa-var-share; } +.@{fa-css-prefix}-expand:before { content: @fa-var-expand; } +.@{fa-css-prefix}-compress:before { content: @fa-var-compress; } +.@{fa-css-prefix}-plus:before { content: @fa-var-plus; } +.@{fa-css-prefix}-minus:before { content: @fa-var-minus; } +.@{fa-css-prefix}-asterisk:before { content: @fa-var-asterisk; } +.@{fa-css-prefix}-exclamation-circle:before { content: @fa-var-exclamation-circle; } +.@{fa-css-prefix}-gift:before { content: @fa-var-gift; } +.@{fa-css-prefix}-leaf:before { content: @fa-var-leaf; } +.@{fa-css-prefix}-fire:before { content: @fa-var-fire; } +.@{fa-css-prefix}-eye:before { content: @fa-var-eye; } +.@{fa-css-prefix}-eye-slash:before { content: @fa-var-eye-slash; } +.@{fa-css-prefix}-warning:before, +.@{fa-css-prefix}-exclamation-triangle:before { content: @fa-var-exclamation-triangle; } +.@{fa-css-prefix}-plane:before { content: @fa-var-plane; } +.@{fa-css-prefix}-calendar:before { content: @fa-var-calendar; } +.@{fa-css-prefix}-random:before { content: @fa-var-random; } +.@{fa-css-prefix}-comment:before { content: @fa-var-comment; } +.@{fa-css-prefix}-magnet:before { content: @fa-var-magnet; } +.@{fa-css-prefix}-chevron-up:before { content: @fa-var-chevron-up; } +.@{fa-css-prefix}-chevron-down:before { content: @fa-var-chevron-down; } +.@{fa-css-prefix}-retweet:before { content: @fa-var-retweet; } +.@{fa-css-prefix}-shopping-cart:before { content: @fa-var-shopping-cart; } +.@{fa-css-prefix}-folder:before { content: @fa-var-folder; } +.@{fa-css-prefix}-folder-open:before { content: @fa-var-folder-open; } +.@{fa-css-prefix}-arrows-v:before { content: @fa-var-arrows-v; } +.@{fa-css-prefix}-arrows-h:before { content: @fa-var-arrows-h; } +.@{fa-css-prefix}-bar-chart-o:before { content: @fa-var-bar-chart-o; } +.@{fa-css-prefix}-twitter-square:before { content: @fa-var-twitter-square; } +.@{fa-css-prefix}-facebook-square:before { content: @fa-var-facebook-square; } +.@{fa-css-prefix}-camera-retro:before { content: @fa-var-camera-retro; } +.@{fa-css-prefix}-key:before { content: @fa-var-key; } +.@{fa-css-prefix}-gears:before, +.@{fa-css-prefix}-cogs:before { content: @fa-var-cogs; } +.@{fa-css-prefix}-comments:before { content: @fa-var-comments; } +.@{fa-css-prefix}-thumbs-o-up:before { content: @fa-var-thumbs-o-up; } +.@{fa-css-prefix}-thumbs-o-down:before { content: @fa-var-thumbs-o-down; } +.@{fa-css-prefix}-star-half:before { content: @fa-var-star-half; } +.@{fa-css-prefix}-heart-o:before { content: @fa-var-heart-o; } +.@{fa-css-prefix}-sign-out:before { content: @fa-var-sign-out; } +.@{fa-css-prefix}-linkedin-square:before { content: @fa-var-linkedin-square; } +.@{fa-css-prefix}-thumb-tack:before { content: @fa-var-thumb-tack; } +.@{fa-css-prefix}-external-link:before { content: @fa-var-external-link; } +.@{fa-css-prefix}-sign-in:before { content: @fa-var-sign-in; } +.@{fa-css-prefix}-trophy:before { content: @fa-var-trophy; } +.@{fa-css-prefix}-github-square:before { content: @fa-var-github-square; } +.@{fa-css-prefix}-upload:before { content: @fa-var-upload; } +.@{fa-css-prefix}-lemon-o:before { content: @fa-var-lemon-o; } +.@{fa-css-prefix}-phone:before { content: @fa-var-phone; } +.@{fa-css-prefix}-square-o:before { content: @fa-var-square-o; } +.@{fa-css-prefix}-bookmark-o:before { content: @fa-var-bookmark-o; } +.@{fa-css-prefix}-phone-square:before { content: @fa-var-phone-square; } +.@{fa-css-prefix}-twitter:before { content: @fa-var-twitter; } +.@{fa-css-prefix}-facebook:before { content: @fa-var-facebook; } +.@{fa-css-prefix}-github:before { content: @fa-var-github; } +.@{fa-css-prefix}-unlock:before { content: @fa-var-unlock; } +.@{fa-css-prefix}-credit-card:before { content: @fa-var-credit-card; } +.@{fa-css-prefix}-rss:before { content: @fa-var-rss; } +.@{fa-css-prefix}-hdd-o:before { content: @fa-var-hdd-o; } +.@{fa-css-prefix}-bullhorn:before { content: @fa-var-bullhorn; } +.@{fa-css-prefix}-bell:before { content: @fa-var-bell; } +.@{fa-css-prefix}-certificate:before { content: @fa-var-certificate; } +.@{fa-css-prefix}-hand-o-right:before { content: @fa-var-hand-o-right; } +.@{fa-css-prefix}-hand-o-left:before { content: @fa-var-hand-o-left; } +.@{fa-css-prefix}-hand-o-up:before { content: @fa-var-hand-o-up; } +.@{fa-css-prefix}-hand-o-down:before { content: @fa-var-hand-o-down; } +.@{fa-css-prefix}-arrow-circle-left:before { content: @fa-var-arrow-circle-left; } +.@{fa-css-prefix}-arrow-circle-right:before { content: @fa-var-arrow-circle-right; } +.@{fa-css-prefix}-arrow-circle-up:before { content: @fa-var-arrow-circle-up; } +.@{fa-css-prefix}-arrow-circle-down:before { content: @fa-var-arrow-circle-down; } +.@{fa-css-prefix}-globe:before { content: @fa-var-globe; } +.@{fa-css-prefix}-wrench:before { content: @fa-var-wrench; } +.@{fa-css-prefix}-tasks:before { content: @fa-var-tasks; } +.@{fa-css-prefix}-filter:before { content: @fa-var-filter; } +.@{fa-css-prefix}-briefcase:before { content: @fa-var-briefcase; } +.@{fa-css-prefix}-arrows-alt:before { content: @fa-var-arrows-alt; } +.@{fa-css-prefix}-group:before, +.@{fa-css-prefix}-users:before { content: @fa-var-users; } +.@{fa-css-prefix}-chain:before, +.@{fa-css-prefix}-link:before { content: @fa-var-link; } +.@{fa-css-prefix}-cloud:before { content: @fa-var-cloud; } +.@{fa-css-prefix}-flask:before { content: @fa-var-flask; } +.@{fa-css-prefix}-cut:before, +.@{fa-css-prefix}-scissors:before { content: @fa-var-scissors; } +.@{fa-css-prefix}-copy:before, +.@{fa-css-prefix}-files-o:before { content: @fa-var-files-o; } +.@{fa-css-prefix}-paperclip:before { content: @fa-var-paperclip; } +.@{fa-css-prefix}-save:before, +.@{fa-css-prefix}-floppy-o:before { content: @fa-var-floppy-o; } +.@{fa-css-prefix}-square:before { content: @fa-var-square; } +.@{fa-css-prefix}-bars:before { content: @fa-var-bars; } +.@{fa-css-prefix}-list-ul:before { content: @fa-var-list-ul; } +.@{fa-css-prefix}-list-ol:before { content: @fa-var-list-ol; } +.@{fa-css-prefix}-strikethrough:before { content: @fa-var-strikethrough; } +.@{fa-css-prefix}-underline:before { content: @fa-var-underline; } +.@{fa-css-prefix}-table:before { content: @fa-var-table; } +.@{fa-css-prefix}-magic:before { content: @fa-var-magic; } +.@{fa-css-prefix}-truck:before { content: @fa-var-truck; } +.@{fa-css-prefix}-pinterest:before { content: @fa-var-pinterest; } +.@{fa-css-prefix}-pinterest-square:before { content: @fa-var-pinterest-square; } +.@{fa-css-prefix}-google-plus-square:before { content: @fa-var-google-plus-square; } +.@{fa-css-prefix}-google-plus:before { content: @fa-var-google-plus; } +.@{fa-css-prefix}-money:before { content: @fa-var-money; } +.@{fa-css-prefix}-caret-down:before { content: @fa-var-caret-down; } +.@{fa-css-prefix}-caret-up:before { content: @fa-var-caret-up; } +.@{fa-css-prefix}-caret-left:before { content: @fa-var-caret-left; } +.@{fa-css-prefix}-caret-right:before { content: @fa-var-caret-right; } +.@{fa-css-prefix}-columns:before { content: @fa-var-columns; } +.@{fa-css-prefix}-unsorted:before, +.@{fa-css-prefix}-sort:before { content: @fa-var-sort; } +.@{fa-css-prefix}-sort-down:before, +.@{fa-css-prefix}-sort-asc:before { content: @fa-var-sort-asc; } +.@{fa-css-prefix}-sort-up:before, +.@{fa-css-prefix}-sort-desc:before { content: @fa-var-sort-desc; } +.@{fa-css-prefix}-envelope:before { content: @fa-var-envelope; } +.@{fa-css-prefix}-linkedin:before { content: @fa-var-linkedin; } +.@{fa-css-prefix}-rotate-left:before, +.@{fa-css-prefix}-undo:before { content: @fa-var-undo; } +.@{fa-css-prefix}-legal:before, +.@{fa-css-prefix}-gavel:before { content: @fa-var-gavel; } +.@{fa-css-prefix}-dashboard:before, +.@{fa-css-prefix}-tachometer:before { content: @fa-var-tachometer; } +.@{fa-css-prefix}-comment-o:before { content: @fa-var-comment-o; } +.@{fa-css-prefix}-comments-o:before { content: @fa-var-comments-o; } +.@{fa-css-prefix}-flash:before, +.@{fa-css-prefix}-bolt:before { content: @fa-var-bolt; } +.@{fa-css-prefix}-sitemap:before { content: @fa-var-sitemap; } +.@{fa-css-prefix}-umbrella:before { content: @fa-var-umbrella; } +.@{fa-css-prefix}-paste:before, +.@{fa-css-prefix}-clipboard:before { content: @fa-var-clipboard; } +.@{fa-css-prefix}-lightbulb-o:before { content: @fa-var-lightbulb-o; } +.@{fa-css-prefix}-exchange:before { content: @fa-var-exchange; } +.@{fa-css-prefix}-cloud-download:before { content: @fa-var-cloud-download; } +.@{fa-css-prefix}-cloud-upload:before { content: @fa-var-cloud-upload; } +.@{fa-css-prefix}-user-md:before { content: @fa-var-user-md; } +.@{fa-css-prefix}-stethoscope:before { content: @fa-var-stethoscope; } +.@{fa-css-prefix}-suitcase:before { content: @fa-var-suitcase; } +.@{fa-css-prefix}-bell-o:before { content: @fa-var-bell-o; } +.@{fa-css-prefix}-coffee:before { content: @fa-var-coffee; } +.@{fa-css-prefix}-cutlery:before { content: @fa-var-cutlery; } +.@{fa-css-prefix}-file-text-o:before { content: @fa-var-file-text-o; } +.@{fa-css-prefix}-building-o:before { content: @fa-var-building-o; } +.@{fa-css-prefix}-hospital-o:before { content: @fa-var-hospital-o; } +.@{fa-css-prefix}-ambulance:before { content: @fa-var-ambulance; } +.@{fa-css-prefix}-medkit:before { content: @fa-var-medkit; } +.@{fa-css-prefix}-fighter-jet:before { content: @fa-var-fighter-jet; } +.@{fa-css-prefix}-beer:before { content: @fa-var-beer; } +.@{fa-css-prefix}-h-square:before { content: @fa-var-h-square; } +.@{fa-css-prefix}-plus-square:before { content: @fa-var-plus-square; } +.@{fa-css-prefix}-angle-double-left:before { content: @fa-var-angle-double-left; } +.@{fa-css-prefix}-angle-double-right:before { content: @fa-var-angle-double-right; } +.@{fa-css-prefix}-angle-double-up:before { content: @fa-var-angle-double-up; } +.@{fa-css-prefix}-angle-double-down:before { content: @fa-var-angle-double-down; } +.@{fa-css-prefix}-angle-left:before { content: @fa-var-angle-left; } +.@{fa-css-prefix}-angle-right:before { content: @fa-var-angle-right; } +.@{fa-css-prefix}-angle-up:before { content: @fa-var-angle-up; } +.@{fa-css-prefix}-angle-down:before { content: @fa-var-angle-down; } +.@{fa-css-prefix}-desktop:before { content: @fa-var-desktop; } +.@{fa-css-prefix}-laptop:before { content: @fa-var-laptop; } +.@{fa-css-prefix}-tablet:before { content: @fa-var-tablet; } +.@{fa-css-prefix}-mobile-phone:before, +.@{fa-css-prefix}-mobile:before { content: @fa-var-mobile; } +.@{fa-css-prefix}-circle-o:before { content: @fa-var-circle-o; } +.@{fa-css-prefix}-quote-left:before { content: @fa-var-quote-left; } +.@{fa-css-prefix}-quote-right:before { content: @fa-var-quote-right; } +.@{fa-css-prefix}-spinner:before { content: @fa-var-spinner; } +.@{fa-css-prefix}-circle:before { content: @fa-var-circle; } +.@{fa-css-prefix}-mail-reply:before, +.@{fa-css-prefix}-reply:before { content: @fa-var-reply; } +.@{fa-css-prefix}-github-alt:before { content: @fa-var-github-alt; } +.@{fa-css-prefix}-folder-o:before { content: @fa-var-folder-o; } +.@{fa-css-prefix}-folder-open-o:before { content: @fa-var-folder-open-o; } +.@{fa-css-prefix}-smile-o:before { content: @fa-var-smile-o; } +.@{fa-css-prefix}-frown-o:before { content: @fa-var-frown-o; } +.@{fa-css-prefix}-meh-o:before { content: @fa-var-meh-o; } +.@{fa-css-prefix}-gamepad:before { content: @fa-var-gamepad; } +.@{fa-css-prefix}-keyboard-o:before { content: @fa-var-keyboard-o; } +.@{fa-css-prefix}-flag-o:before { content: @fa-var-flag-o; } +.@{fa-css-prefix}-flag-checkered:before { content: @fa-var-flag-checkered; } +.@{fa-css-prefix}-terminal:before { content: @fa-var-terminal; } +.@{fa-css-prefix}-code:before { content: @fa-var-code; } +.@{fa-css-prefix}-reply-all:before { content: @fa-var-reply-all; } +.@{fa-css-prefix}-mail-reply-all:before { content: @fa-var-mail-reply-all; } +.@{fa-css-prefix}-star-half-empty:before, +.@{fa-css-prefix}-star-half-full:before, +.@{fa-css-prefix}-star-half-o:before { content: @fa-var-star-half-o; } +.@{fa-css-prefix}-location-arrow:before { content: @fa-var-location-arrow; } +.@{fa-css-prefix}-crop:before { content: @fa-var-crop; } +.@{fa-css-prefix}-code-fork:before { content: @fa-var-code-fork; } +.@{fa-css-prefix}-unlink:before, +.@{fa-css-prefix}-chain-broken:before { content: @fa-var-chain-broken; } +.@{fa-css-prefix}-question:before { content: @fa-var-question; } +.@{fa-css-prefix}-info:before { content: @fa-var-info; } +.@{fa-css-prefix}-exclamation:before { content: @fa-var-exclamation; } +.@{fa-css-prefix}-superscript:before { content: @fa-var-superscript; } +.@{fa-css-prefix}-subscript:before { content: @fa-var-subscript; } +.@{fa-css-prefix}-eraser:before { content: @fa-var-eraser; } +.@{fa-css-prefix}-puzzle-piece:before { content: @fa-var-puzzle-piece; } +.@{fa-css-prefix}-microphone:before { content: @fa-var-microphone; } +.@{fa-css-prefix}-microphone-slash:before { content: @fa-var-microphone-slash; } +.@{fa-css-prefix}-shield:before { content: @fa-var-shield; } +.@{fa-css-prefix}-calendar-o:before { content: @fa-var-calendar-o; } +.@{fa-css-prefix}-fire-extinguisher:before { content: @fa-var-fire-extinguisher; } +.@{fa-css-prefix}-rocket:before { content: @fa-var-rocket; } +.@{fa-css-prefix}-maxcdn:before { content: @fa-var-maxcdn; } +.@{fa-css-prefix}-chevron-circle-left:before { content: @fa-var-chevron-circle-left; } +.@{fa-css-prefix}-chevron-circle-right:before { content: @fa-var-chevron-circle-right; } +.@{fa-css-prefix}-chevron-circle-up:before { content: @fa-var-chevron-circle-up; } +.@{fa-css-prefix}-chevron-circle-down:before { content: @fa-var-chevron-circle-down; } +.@{fa-css-prefix}-html5:before { content: @fa-var-html5; } +.@{fa-css-prefix}-css3:before { content: @fa-var-css3; } +.@{fa-css-prefix}-anchor:before { content: @fa-var-anchor; } +.@{fa-css-prefix}-unlock-alt:before { content: @fa-var-unlock-alt; } +.@{fa-css-prefix}-bullseye:before { content: @fa-var-bullseye; } +.@{fa-css-prefix}-ellipsis-h:before { content: @fa-var-ellipsis-h; } +.@{fa-css-prefix}-ellipsis-v:before { content: @fa-var-ellipsis-v; } +.@{fa-css-prefix}-rss-square:before { content: @fa-var-rss-square; } +.@{fa-css-prefix}-play-circle:before { content: @fa-var-play-circle; } +.@{fa-css-prefix}-ticket:before { content: @fa-var-ticket; } +.@{fa-css-prefix}-minus-square:before { content: @fa-var-minus-square; } +.@{fa-css-prefix}-minus-square-o:before { content: @fa-var-minus-square-o; } +.@{fa-css-prefix}-level-up:before { content: @fa-var-level-up; } +.@{fa-css-prefix}-level-down:before { content: @fa-var-level-down; } +.@{fa-css-prefix}-check-square:before { content: @fa-var-check-square; } +.@{fa-css-prefix}-pencil-square:before { content: @fa-var-pencil-square; } +.@{fa-css-prefix}-external-link-square:before { content: @fa-var-external-link-square; } +.@{fa-css-prefix}-share-square:before { content: @fa-var-share-square; } +.@{fa-css-prefix}-compass:before { content: @fa-var-compass; } +.@{fa-css-prefix}-toggle-down:before, +.@{fa-css-prefix}-caret-square-o-down:before { content: @fa-var-caret-square-o-down; } +.@{fa-css-prefix}-toggle-up:before, +.@{fa-css-prefix}-caret-square-o-up:before { content: @fa-var-caret-square-o-up; } +.@{fa-css-prefix}-toggle-right:before, +.@{fa-css-prefix}-caret-square-o-right:before { content: @fa-var-caret-square-o-right; } +.@{fa-css-prefix}-euro:before, +.@{fa-css-prefix}-eur:before { content: @fa-var-eur; } +.@{fa-css-prefix}-gbp:before { content: @fa-var-gbp; } +.@{fa-css-prefix}-dollar:before, +.@{fa-css-prefix}-usd:before { content: @fa-var-usd; } +.@{fa-css-prefix}-rupee:before, +.@{fa-css-prefix}-inr:before { content: @fa-var-inr; } +.@{fa-css-prefix}-cny:before, +.@{fa-css-prefix}-rmb:before, +.@{fa-css-prefix}-yen:before, +.@{fa-css-prefix}-jpy:before { content: @fa-var-jpy; } +.@{fa-css-prefix}-ruble:before, +.@{fa-css-prefix}-rouble:before, +.@{fa-css-prefix}-rub:before { content: @fa-var-rub; } +.@{fa-css-prefix}-won:before, +.@{fa-css-prefix}-krw:before { content: @fa-var-krw; } +.@{fa-css-prefix}-bitcoin:before, +.@{fa-css-prefix}-btc:before { content: @fa-var-btc; } +.@{fa-css-prefix}-file:before { content: @fa-var-file; } +.@{fa-css-prefix}-file-text:before { content: @fa-var-file-text; } +.@{fa-css-prefix}-sort-alpha-asc:before { content: @fa-var-sort-alpha-asc; } +.@{fa-css-prefix}-sort-alpha-desc:before { content: @fa-var-sort-alpha-desc; } +.@{fa-css-prefix}-sort-amount-asc:before { content: @fa-var-sort-amount-asc; } +.@{fa-css-prefix}-sort-amount-desc:before { content: @fa-var-sort-amount-desc; } +.@{fa-css-prefix}-sort-numeric-asc:before { content: @fa-var-sort-numeric-asc; } +.@{fa-css-prefix}-sort-numeric-desc:before { content: @fa-var-sort-numeric-desc; } +.@{fa-css-prefix}-thumbs-up:before { content: @fa-var-thumbs-up; } +.@{fa-css-prefix}-thumbs-down:before { content: @fa-var-thumbs-down; } +.@{fa-css-prefix}-youtube-square:before { content: @fa-var-youtube-square; } +.@{fa-css-prefix}-youtube:before { content: @fa-var-youtube; } +.@{fa-css-prefix}-xing:before { content: @fa-var-xing; } +.@{fa-css-prefix}-xing-square:before { content: @fa-var-xing-square; } +.@{fa-css-prefix}-youtube-play:before { content: @fa-var-youtube-play; } +.@{fa-css-prefix}-dropbox:before { content: @fa-var-dropbox; } +.@{fa-css-prefix}-stack-overflow:before { content: @fa-var-stack-overflow; } +.@{fa-css-prefix}-instagram:before { content: @fa-var-instagram; } +.@{fa-css-prefix}-flickr:before { content: @fa-var-flickr; } +.@{fa-css-prefix}-adn:before { content: @fa-var-adn; } +.@{fa-css-prefix}-bitbucket:before { content: @fa-var-bitbucket; } +.@{fa-css-prefix}-bitbucket-square:before { content: @fa-var-bitbucket-square; } +.@{fa-css-prefix}-tumblr:before { content: @fa-var-tumblr; } +.@{fa-css-prefix}-tumblr-square:before { content: @fa-var-tumblr-square; } +.@{fa-css-prefix}-long-arrow-down:before { content: @fa-var-long-arrow-down; } +.@{fa-css-prefix}-long-arrow-up:before { content: @fa-var-long-arrow-up; } +.@{fa-css-prefix}-long-arrow-left:before { content: @fa-var-long-arrow-left; } +.@{fa-css-prefix}-long-arrow-right:before { content: @fa-var-long-arrow-right; } +.@{fa-css-prefix}-apple:before { content: @fa-var-apple; } +.@{fa-css-prefix}-windows:before { content: @fa-var-windows; } +.@{fa-css-prefix}-android:before { content: @fa-var-android; } +.@{fa-css-prefix}-linux:before { content: @fa-var-linux; } +.@{fa-css-prefix}-dribbble:before { content: @fa-var-dribbble; } +.@{fa-css-prefix}-skype:before { content: @fa-var-skype; } +.@{fa-css-prefix}-foursquare:before { content: @fa-var-foursquare; } +.@{fa-css-prefix}-trello:before { content: @fa-var-trello; } +.@{fa-css-prefix}-female:before { content: @fa-var-female; } +.@{fa-css-prefix}-male:before { content: @fa-var-male; } +.@{fa-css-prefix}-gittip:before { content: @fa-var-gittip; } +.@{fa-css-prefix}-sun-o:before { content: @fa-var-sun-o; } +.@{fa-css-prefix}-moon-o:before { content: @fa-var-moon-o; } +.@{fa-css-prefix}-archive:before { content: @fa-var-archive; } +.@{fa-css-prefix}-bug:before { content: @fa-var-bug; } +.@{fa-css-prefix}-vk:before { content: @fa-var-vk; } +.@{fa-css-prefix}-weibo:before { content: @fa-var-weibo; } +.@{fa-css-prefix}-renren:before { content: @fa-var-renren; } +.@{fa-css-prefix}-pagelines:before { content: @fa-var-pagelines; } +.@{fa-css-prefix}-stack-exchange:before { content: @fa-var-stack-exchange; } +.@{fa-css-prefix}-arrow-circle-o-right:before { content: @fa-var-arrow-circle-o-right; } +.@{fa-css-prefix}-arrow-circle-o-left:before { content: @fa-var-arrow-circle-o-left; } +.@{fa-css-prefix}-toggle-left:before, +.@{fa-css-prefix}-caret-square-o-left:before { content: @fa-var-caret-square-o-left; } +.@{fa-css-prefix}-dot-circle-o:before { content: @fa-var-dot-circle-o; } +.@{fa-css-prefix}-wheelchair:before { content: @fa-var-wheelchair; } +.@{fa-css-prefix}-vimeo-square:before { content: @fa-var-vimeo-square; } +.@{fa-css-prefix}-turkish-lira:before, +.@{fa-css-prefix}-try:before { content: @fa-var-try; } +.@{fa-css-prefix}-plus-square-o:before { content: @fa-var-plus-square-o; } diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/larger.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/larger.less new file mode 100644 index 0000000..c9d6467 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/larger.less @@ -0,0 +1,13 @@ +// Icon Sizes +// ------------------------- + +/* makes the font 33% larger relative to the icon container */ +.@{fa-css-prefix}-lg { + font-size: (4em / 3); + line-height: (3em / 4); + vertical-align: -15%; +} +.@{fa-css-prefix}-2x { font-size: 2em; } +.@{fa-css-prefix}-3x { font-size: 3em; } +.@{fa-css-prefix}-4x { font-size: 4em; } +.@{fa-css-prefix}-5x { font-size: 5em; } diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/list.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/list.less new file mode 100644 index 0000000..eed9340 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/list.less @@ -0,0 +1,19 @@ +// List Icons +// ------------------------- + +.@{fa-css-prefix}-ul { + padding-left: 0; + margin-left: @fa-li-width; + list-style-type: none; + > li { position: relative; } +} +.@{fa-css-prefix}-li { + position: absolute; + left: -@fa-li-width; + width: @fa-li-width; + top: (2em / 14); + text-align: center; + &.@{fa-css-prefix}-lg { + left: -@fa-li-width + (4em / 14); + } +} diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/mixins.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/mixins.less new file mode 100644 index 0000000..19e5a64 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/mixins.less @@ -0,0 +1,20 @@ +// Mixins +// -------------------------- + +.fa-icon-rotate(@degrees, @rotation) { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation); + -webkit-transform: rotate(@degrees); + -moz-transform: rotate(@degrees); + -ms-transform: rotate(@degrees); + -o-transform: rotate(@degrees); + transform: rotate(@degrees); +} + +.fa-icon-flip(@horiz, @vert, @rotation) { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1); + -webkit-transform: scale(@horiz, @vert); + -moz-transform: scale(@horiz, @vert); + -ms-transform: scale(@horiz, @vert); + -o-transform: scale(@horiz, @vert); + transform: scale(@horiz, @vert); +} diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/path.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/path.less new file mode 100644 index 0000000..c5a6912 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/path.less @@ -0,0 +1,14 @@ +/* FONT PATH + * -------------------------- */ + +@font-face { + font-family: 'FontAwesome'; + src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); + src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), + url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), + url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), + url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); +// src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts + font-weight: normal; + font-style: normal; +} diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/rotated-flipped.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/rotated-flipped.less new file mode 100644 index 0000000..8fff3a6 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/rotated-flipped.less @@ -0,0 +1,9 @@ +// Rotated & Flipped Icons +// ------------------------- + +.@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } +.@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } +.@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } + +.@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } +.@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/spinning.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/spinning.less new file mode 100644 index 0000000..60828fe --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/spinning.less @@ -0,0 +1,30 @@ +// Spinning Icons +// -------------------------- + +.@{fa-css-prefix}-spin { + -webkit-animation: spin 2s infinite linear; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} + +@-moz-keyframes spin { + 0% { -moz-transform: rotate(0deg); } + 100% { -moz-transform: rotate(359deg); } +} +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(359deg); } +} +@-o-keyframes spin { + 0% { -o-transform: rotate(0deg); } + 100% { -o-transform: rotate(359deg); } +} +@-ms-keyframes spin { + 0% { -ms-transform: rotate(0deg); } + 100% { -ms-transform: rotate(359deg); } +} +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(359deg); } +} diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/stacked.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/stacked.less new file mode 100644 index 0000000..fc53fb0 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/stacked.less @@ -0,0 +1,20 @@ +// Stacked Icons +// ------------------------- + +.@{fa-css-prefix}-stack { + position: relative; + display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.@{fa-css-prefix}-stack-1x { line-height: inherit; } +.@{fa-css-prefix}-stack-2x { font-size: 2em; } +.@{fa-css-prefix}-inverse { color: @fa-inverse; } diff --git a/src/static/movio/templates/Sliding-windows/less/font-awesome/variables.less b/src/static/movio/templates/Sliding-windows/less/font-awesome/variables.less new file mode 100644 index 0000000..3ab7a75 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/font-awesome/variables.less @@ -0,0 +1,381 @@ +// Variables +// -------------------------- + +//@fa-font-path: "../font/font-awesome"; +@fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.0.3/fonts"; // for referencing Bootstrap CDN font files directly +@fa-css-prefix: fa; +@fa-version: "4.0.3"; +@fa-border-color: #eee; +@fa-inverse: #fff; +@fa-li-width: (30em / 14); + +@fa-var-glass: "\f000"; +@fa-var-music: "\f001"; +@fa-var-search: "\f002"; +@fa-var-envelope-o: "\f003"; +@fa-var-heart: "\f004"; +@fa-var-star: "\f005"; +@fa-var-star-o: "\f006"; +@fa-var-user: "\f007"; +@fa-var-film: "\f008"; +@fa-var-th-large: "\f009"; +@fa-var-th: "\f00a"; +@fa-var-th-list: "\f00b"; +@fa-var-check: "\f00c"; +@fa-var-times: "\f00d"; +@fa-var-search-plus: "\f00e"; +@fa-var-search-minus: "\f010"; +@fa-var-power-off: "\f011"; +@fa-var-signal: "\f012"; +@fa-var-cog: "\f013"; +@fa-var-trash-o: "\f014"; +@fa-var-home: "\f015"; +@fa-var-file-o: "\f016"; +@fa-var-clock-o: "\f017"; +@fa-var-road: "\f018"; +@fa-var-download: "\f019"; +@fa-var-arrow-circle-o-down: "\f01a"; +@fa-var-arrow-circle-o-up: "\f01b"; +@fa-var-inbox: "\f01c"; +@fa-var-play-circle-o: "\f01d"; +@fa-var-repeat: "\f01e"; +@fa-var-refresh: "\f021"; +@fa-var-list-alt: "\f022"; +@fa-var-lock: "\f023"; +@fa-var-flag: "\f024"; +@fa-var-headphones: "\f025"; +@fa-var-volume-off: "\f026"; +@fa-var-volume-down: "\f027"; +@fa-var-volume-up: "\f028"; +@fa-var-qrcode: "\f029"; +@fa-var-barcode: "\f02a"; +@fa-var-tag: "\f02b"; +@fa-var-tags: "\f02c"; +@fa-var-book: "\f02d"; +@fa-var-bookmark: "\f02e"; +@fa-var-print: "\f02f"; +@fa-var-camera: "\f030"; +@fa-var-font: "\f031"; +@fa-var-bold: "\f032"; +@fa-var-italic: "\f033"; +@fa-var-text-height: "\f034"; +@fa-var-text-width: "\f035"; +@fa-var-align-left: "\f036"; +@fa-var-align-center: "\f037"; +@fa-var-align-right: "\f038"; +@fa-var-align-justify: "\f039"; +@fa-var-list: "\f03a"; +@fa-var-outdent: "\f03b"; +@fa-var-indent: "\f03c"; +@fa-var-video-camera: "\f03d"; +@fa-var-picture-o: "\f03e"; +@fa-var-pencil: "\f040"; +@fa-var-map-marker: "\f041"; +@fa-var-adjust: "\f042"; +@fa-var-tint: "\f043"; +@fa-var-pencil-square-o: "\f044"; +@fa-var-share-square-o: "\f045"; +@fa-var-check-square-o: "\f046"; +@fa-var-arrows: "\f047"; +@fa-var-step-backward: "\f048"; +@fa-var-fast-backward: "\f049"; +@fa-var-backward: "\f04a"; +@fa-var-play: "\f04b"; +@fa-var-pause: "\f04c"; +@fa-var-stop: "\f04d"; +@fa-var-forward: "\f04e"; +@fa-var-fast-forward: "\f050"; +@fa-var-step-forward: "\f051"; +@fa-var-eject: "\f052"; +@fa-var-chevron-left: "\f053"; +@fa-var-chevron-right: "\f054"; +@fa-var-plus-circle: "\f055"; +@fa-var-minus-circle: "\f056"; +@fa-var-times-circle: "\f057"; +@fa-var-check-circle: "\f058"; +@fa-var-question-circle: "\f059"; +@fa-var-info-circle: "\f05a"; +@fa-var-crosshairs: "\f05b"; +@fa-var-times-circle-o: "\f05c"; +@fa-var-check-circle-o: "\f05d"; +@fa-var-ban: "\f05e"; +@fa-var-arrow-left: "\f060"; +@fa-var-arrow-right: "\f061"; +@fa-var-arrow-up: "\f062"; +@fa-var-arrow-down: "\f063"; +@fa-var-share: "\f064"; +@fa-var-expand: "\f065"; +@fa-var-compress: "\f066"; +@fa-var-plus: "\f067"; +@fa-var-minus: "\f068"; +@fa-var-asterisk: "\f069"; +@fa-var-exclamation-circle: "\f06a"; +@fa-var-gift: "\f06b"; +@fa-var-leaf: "\f06c"; +@fa-var-fire: "\f06d"; +@fa-var-eye: "\f06e"; +@fa-var-eye-slash: "\f070"; +@fa-var-exclamation-triangle: "\f071"; +@fa-var-plane: "\f072"; +@fa-var-calendar: "\f073"; +@fa-var-random: "\f074"; +@fa-var-comment: "\f075"; +@fa-var-magnet: "\f076"; +@fa-var-chevron-up: "\f077"; +@fa-var-chevron-down: "\f078"; +@fa-var-retweet: "\f079"; +@fa-var-shopping-cart: "\f07a"; +@fa-var-folder: "\f07b"; +@fa-var-folder-open: "\f07c"; +@fa-var-arrows-v: "\f07d"; +@fa-var-arrows-h: "\f07e"; +@fa-var-bar-chart-o: "\f080"; +@fa-var-twitter-square: "\f081"; +@fa-var-facebook-square: "\f082"; +@fa-var-camera-retro: "\f083"; +@fa-var-key: "\f084"; +@fa-var-cogs: "\f085"; +@fa-var-comments: "\f086"; +@fa-var-thumbs-o-up: "\f087"; +@fa-var-thumbs-o-down: "\f088"; +@fa-var-star-half: "\f089"; +@fa-var-heart-o: "\f08a"; +@fa-var-sign-out: "\f08b"; +@fa-var-linkedin-square: "\f08c"; +@fa-var-thumb-tack: "\f08d"; +@fa-var-external-link: "\f08e"; +@fa-var-sign-in: "\f090"; +@fa-var-trophy: "\f091"; +@fa-var-github-square: "\f092"; +@fa-var-upload: "\f093"; +@fa-var-lemon-o: "\f094"; +@fa-var-phone: "\f095"; +@fa-var-square-o: "\f096"; +@fa-var-bookmark-o: "\f097"; +@fa-var-phone-square: "\f098"; +@fa-var-twitter: "\f099"; +@fa-var-facebook: "\f09a"; +@fa-var-github: "\f09b"; +@fa-var-unlock: "\f09c"; +@fa-var-credit-card: "\f09d"; +@fa-var-rss: "\f09e"; +@fa-var-hdd-o: "\f0a0"; +@fa-var-bullhorn: "\f0a1"; +@fa-var-bell: "\f0f3"; +@fa-var-certificate: "\f0a3"; +@fa-var-hand-o-right: "\f0a4"; +@fa-var-hand-o-left: "\f0a5"; +@fa-var-hand-o-up: "\f0a6"; +@fa-var-hand-o-down: "\f0a7"; +@fa-var-arrow-circle-left: "\f0a8"; +@fa-var-arrow-circle-right: "\f0a9"; +@fa-var-arrow-circle-up: "\f0aa"; +@fa-var-arrow-circle-down: "\f0ab"; +@fa-var-globe: "\f0ac"; +@fa-var-wrench: "\f0ad"; +@fa-var-tasks: "\f0ae"; +@fa-var-filter: "\f0b0"; +@fa-var-briefcase: "\f0b1"; +@fa-var-arrows-alt: "\f0b2"; +@fa-var-users: "\f0c0"; +@fa-var-link: "\f0c1"; +@fa-var-cloud: "\f0c2"; +@fa-var-flask: "\f0c3"; +@fa-var-scissors: "\f0c4"; +@fa-var-files-o: "\f0c5"; +@fa-var-paperclip: "\f0c6"; +@fa-var-floppy-o: "\f0c7"; +@fa-var-square: "\f0c8"; +@fa-var-bars: "\f0c9"; +@fa-var-list-ul: "\f0ca"; +@fa-var-list-ol: "\f0cb"; +@fa-var-strikethrough: "\f0cc"; +@fa-var-underline: "\f0cd"; +@fa-var-table: "\f0ce"; +@fa-var-magic: "\f0d0"; +@fa-var-truck: "\f0d1"; +@fa-var-pinterest: "\f0d2"; +@fa-var-pinterest-square: "\f0d3"; +@fa-var-google-plus-square: "\f0d4"; +@fa-var-google-plus: "\f0d5"; +@fa-var-money: "\f0d6"; +@fa-var-caret-down: "\f0d7"; +@fa-var-caret-up: "\f0d8"; +@fa-var-caret-left: "\f0d9"; +@fa-var-caret-right: "\f0da"; +@fa-var-columns: "\f0db"; +@fa-var-sort: "\f0dc"; +@fa-var-sort-asc: "\f0dd"; +@fa-var-sort-desc: "\f0de"; +@fa-var-envelope: "\f0e0"; +@fa-var-linkedin: "\f0e1"; +@fa-var-undo: "\f0e2"; +@fa-var-gavel: "\f0e3"; +@fa-var-tachometer: "\f0e4"; +@fa-var-comment-o: "\f0e5"; +@fa-var-comments-o: "\f0e6"; +@fa-var-bolt: "\f0e7"; +@fa-var-sitemap: "\f0e8"; +@fa-var-umbrella: "\f0e9"; +@fa-var-clipboard: "\f0ea"; +@fa-var-lightbulb-o: "\f0eb"; +@fa-var-exchange: "\f0ec"; +@fa-var-cloud-download: "\f0ed"; +@fa-var-cloud-upload: "\f0ee"; +@fa-var-user-md: "\f0f0"; +@fa-var-stethoscope: "\f0f1"; +@fa-var-suitcase: "\f0f2"; +@fa-var-bell-o: "\f0a2"; +@fa-var-coffee: "\f0f4"; +@fa-var-cutlery: "\f0f5"; +@fa-var-file-text-o: "\f0f6"; +@fa-var-building-o: "\f0f7"; +@fa-var-hospital-o: "\f0f8"; +@fa-var-ambulance: "\f0f9"; +@fa-var-medkit: "\f0fa"; +@fa-var-fighter-jet: "\f0fb"; +@fa-var-beer: "\f0fc"; +@fa-var-h-square: "\f0fd"; +@fa-var-plus-square: "\f0fe"; +@fa-var-angle-double-left: "\f100"; +@fa-var-angle-double-right: "\f101"; +@fa-var-angle-double-up: "\f102"; +@fa-var-angle-double-down: "\f103"; +@fa-var-angle-left: "\f104"; +@fa-var-angle-right: "\f105"; +@fa-var-angle-up: "\f106"; +@fa-var-angle-down: "\f107"; +@fa-var-desktop: "\f108"; +@fa-var-laptop: "\f109"; +@fa-var-tablet: "\f10a"; +@fa-var-mobile: "\f10b"; +@fa-var-circle-o: "\f10c"; +@fa-var-quote-left: "\f10d"; +@fa-var-quote-right: "\f10e"; +@fa-var-spinner: "\f110"; +@fa-var-circle: "\f111"; +@fa-var-reply: "\f112"; +@fa-var-github-alt: "\f113"; +@fa-var-folder-o: "\f114"; +@fa-var-folder-open-o: "\f115"; +@fa-var-smile-o: "\f118"; +@fa-var-frown-o: "\f119"; +@fa-var-meh-o: "\f11a"; +@fa-var-gamepad: "\f11b"; +@fa-var-keyboard-o: "\f11c"; +@fa-var-flag-o: "\f11d"; +@fa-var-flag-checkered: "\f11e"; +@fa-var-terminal: "\f120"; +@fa-var-code: "\f121"; +@fa-var-reply-all: "\f122"; +@fa-var-mail-reply-all: "\f122"; +@fa-var-star-half-o: "\f123"; +@fa-var-location-arrow: "\f124"; +@fa-var-crop: "\f125"; +@fa-var-code-fork: "\f126"; +@fa-var-chain-broken: "\f127"; +@fa-var-question: "\f128"; +@fa-var-info: "\f129"; +@fa-var-exclamation: "\f12a"; +@fa-var-superscript: "\f12b"; +@fa-var-subscript: "\f12c"; +@fa-var-eraser: "\f12d"; +@fa-var-puzzle-piece: "\f12e"; +@fa-var-microphone: "\f130"; +@fa-var-microphone-slash: "\f131"; +@fa-var-shield: "\f132"; +@fa-var-calendar-o: "\f133"; +@fa-var-fire-extinguisher: "\f134"; +@fa-var-rocket: "\f135"; +@fa-var-maxcdn: "\f136"; +@fa-var-chevron-circle-left: "\f137"; +@fa-var-chevron-circle-right: "\f138"; +@fa-var-chevron-circle-up: "\f139"; +@fa-var-chevron-circle-down: "\f13a"; +@fa-var-html5: "\f13b"; +@fa-var-css3: "\f13c"; +@fa-var-anchor: "\f13d"; +@fa-var-unlock-alt: "\f13e"; +@fa-var-bullseye: "\f140"; +@fa-var-ellipsis-h: "\f141"; +@fa-var-ellipsis-v: "\f142"; +@fa-var-rss-square: "\f143"; +@fa-var-play-circle: "\f144"; +@fa-var-ticket: "\f145"; +@fa-var-minus-square: "\f146"; +@fa-var-minus-square-o: "\f147"; +@fa-var-level-up: "\f148"; +@fa-var-level-down: "\f149"; +@fa-var-check-square: "\f14a"; +@fa-var-pencil-square: "\f14b"; +@fa-var-external-link-square: "\f14c"; +@fa-var-share-square: "\f14d"; +@fa-var-compass: "\f14e"; +@fa-var-caret-square-o-down: "\f150"; +@fa-var-caret-square-o-up: "\f151"; +@fa-var-caret-square-o-right: "\f152"; +@fa-var-eur: "\f153"; +@fa-var-gbp: "\f154"; +@fa-var-usd: "\f155"; +@fa-var-inr: "\f156"; +@fa-var-jpy: "\f157"; +@fa-var-rub: "\f158"; +@fa-var-krw: "\f159"; +@fa-var-btc: "\f15a"; +@fa-var-file: "\f15b"; +@fa-var-file-text: "\f15c"; +@fa-var-sort-alpha-asc: "\f15d"; +@fa-var-sort-alpha-desc: "\f15e"; +@fa-var-sort-amount-asc: "\f160"; +@fa-var-sort-amount-desc: "\f161"; +@fa-var-sort-numeric-asc: "\f162"; +@fa-var-sort-numeric-desc: "\f163"; +@fa-var-thumbs-up: "\f164"; +@fa-var-thumbs-down: "\f165"; +@fa-var-youtube-square: "\f166"; +@fa-var-youtube: "\f167"; +@fa-var-xing: "\f168"; +@fa-var-xing-square: "\f169"; +@fa-var-youtube-play: "\f16a"; +@fa-var-dropbox: "\f16b"; +@fa-var-stack-overflow: "\f16c"; +@fa-var-instagram: "\f16d"; +@fa-var-flickr: "\f16e"; +@fa-var-adn: "\f170"; +@fa-var-bitbucket: "\f171"; +@fa-var-bitbucket-square: "\f172"; +@fa-var-tumblr: "\f173"; +@fa-var-tumblr-square: "\f174"; +@fa-var-long-arrow-down: "\f175"; +@fa-var-long-arrow-up: "\f176"; +@fa-var-long-arrow-left: "\f177"; +@fa-var-long-arrow-right: "\f178"; +@fa-var-apple: "\f179"; +@fa-var-windows: "\f17a"; +@fa-var-android: "\f17b"; +@fa-var-linux: "\f17c"; +@fa-var-dribbble: "\f17d"; +@fa-var-skype: "\f17e"; +@fa-var-foursquare: "\f180"; +@fa-var-trello: "\f181"; +@fa-var-female: "\f182"; +@fa-var-male: "\f183"; +@fa-var-gittip: "\f184"; +@fa-var-sun-o: "\f185"; +@fa-var-moon-o: "\f186"; +@fa-var-archive: "\f187"; +@fa-var-bug: "\f188"; +@fa-var-vk: "\f189"; +@fa-var-weibo: "\f18a"; +@fa-var-renren: "\f18b"; +@fa-var-pagelines: "\f18c"; +@fa-var-stack-exchange: "\f18d"; +@fa-var-arrow-circle-o-right: "\f18e"; +@fa-var-arrow-circle-o-left: "\f190"; +@fa-var-caret-square-o-left: "\f191"; +@fa-var-dot-circle-o: "\f192"; +@fa-var-wheelchair: "\f193"; +@fa-var-vimeo-square: "\f194"; +@fa-var-try: "\f195"; +@fa-var-plus-square-o: "\f196"; + diff --git a/src/static/movio/templates/Sliding-windows/less/global.less b/src/static/movio/templates/Sliding-windows/less/global.less new file mode 100755 index 0000000..e0c50dd --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/global.less @@ -0,0 +1,338 @@ +body { + background-color:@background-main-content; + font-family:@font-1; + font-size:15px; + font-weight:normal; + overflow:hidden; +} +* { + .box-sizing(); +} + +/** + * Typography + */ +h1, h2, h3, h4, h5, h6 { + color: @text-heading; +} +a { + color:@color-link; + + &:hover { + color:@color-link-hover; + } +} + +dt { + float: left; + font-weight:bold; + padding-right:10px; +} + +dd { + margin-left:0; +} + +dl { + &.small { + dt { + width: 70px; + } + dd { + margin-left: 70px; + } + } + &.medium { + dt { + width: 170px; + } + dd { + margin-left: 170px; + } + } + &.large { + dt { + width: 250px; + } + dd { + margin-left: 250px; + } + } +} + +.main-content { + + h1 { + .padding-margin-reset(); + } + h2 { + .padding-margin-reset(); + margin-bottom:15px; + } + + .print-ico { + float:right; + } + + p { + line-height:1.6em; + padding-bottom:15px; + } +} + +/** + * Image + */ +img { + max-width:100%; + border: 0; + &.thumb, &.left, &.right, &.center { + float:left; + margin: 0.5em; + padding:5px; + border:1px @solid @box-image-border; + } + &.left { + margin-left: 0; + } + &.right { + margin-right: 0; + clear:right; + float:right; + } + &.center { + clear:both; + float:none; + margin:auto; + display: block; + } + &.noBorder { + border: 0; + padding: 0; + } +} + +/** + * Form + */ +input[type="text"], input[type="password"], input[type="email"] { + .input-style(100%); + + &.input-large { + width:450px; + } + &.input-small { + width:160px; + } +} + +label { + &.required { + &:after { + content:" *"; + } + } +} + +select { + width:auto; + &.select-large { + width:450px; + } + &.select-small { + width:160px; + } + &.select-medium { + width:260px; + } +} + +input[type="submit"], button, input[type="button"], input[type="reset"] { + .button-style(auto); +} + +input[type="submit"] { + background:@form-button-primary; + color:@form-button-primary-text; +} + +textarea { + border:1px @solid @color1; + width:100%; + padding:4px; + height:150px; + &.textarea-large { + width:450px; + } +} + +.my-form { + &.no-border-row { + .control-group { + border:0; + } + } + .control-group { + padding-bottom:10px; + } + .controls { + margin-left:0; + &.with-button { + input[type="submit"], input[type="button"], input[type="reset"], button { + margin-top:0; + margin-left:5px; + } + } + } + + &.form-horizontal { + .control-group { + clear:both; + margin-bottom:15px; + padding-bottom:15px; + border-bottom:1px @solid @color1; + label { + display:inline-block; + width:160px; + } + .controls { + display:inline-block; + } + } + } +} + +/** + * global selectors + */ +.clearfix-left { + clear:left; +} + +.clearfix-right { + clear:right; +} + +.align-center { + text-align:center!important; +} + +.align-right { + text-align:right!important; +} + +.first-box { + margin-left:0!important; +} + +.error { + color:@color-error; +} + +.ok { + color:@color-success; +} + +.ico-box { + display:block; + position:absolute; + width:30px!important; + height:30px!important; + top:0; + right:0; + margin-right:10px; + background:@icon-in-box-background; + color:@icon-in-box; + text-align:center; + padding-top:7px; + font-size:15px; + &.icon-film { + padding-left:5px; + } +} + +.icon-grey { + color:@icon-in-page; + font-size:20px; +} + + +span.superzoom { + background:@button-zoom-img; + color: @form-button-primary-text; + padding:0 0; + position: absolute; + text-align: center; + width:30px; + height:30px; + cursor: pointer; + .border-radius(0); + text-align:center; + padding:2px 0 0 0; + line-height:30px; +} + +.col-md-3, +.col-md-1, +.col-md-2, +.col-md-3, +.col-md-4, +.col-md-5, +.col-md-6, +.col-md-7, +.col-md-8, +.col-md-9, +.col-md-10, +.col-md-11, +.col-md-12 { + padding:0; + } + +/* define shadow */ + +.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #999) { + box-shadow: @arguments; + -moz-box-shadow: @arguments; + -webkit-box-shadow: @arguments; +} + + +/* mCustomScrollBox */ +#outer .mCustomScrollBox { + + .mCSB_buttonUp { + + } + + .mCSB_buttonDown { + + } + + .mCSB_draggerContainer { + + .mCSB_dragger_bar { + background-color:#000; + .border-radius(0); + width:5px; + margin-left:6px; + } + + .mCSB_draggerRail { + width:1px; + background:#000; + } + + } + +} + + +a.no-undeline { + text-decoration: none; +} + +.col-padding-left, +.col-padding-right { + padding-right: 15px; +} + diff --git a/src/static/movio/templates/Sliding-windows/less/libs/bootstrap.less b/src/static/movio/templates/Sliding-windows/less/libs/bootstrap.less new file mode 100755 index 0000000..b48afb5 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/libs/bootstrap.less @@ -0,0 +1,2820 @@ +/*! + * Bootstrap v3.1.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px @solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +@media print { + * { + text-shadow: none !important; + color: #000 !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) ")"; + } + 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; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .table td, + .table th { + background-color: #fff !important; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px @solid #000; + } + .table { + border-collapse: collapse !important; + } + .table-bordered th, + .table-bordered td { + border: 1px @solid #ddd !important; + } +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 62.5%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333333; + background-color: #ffffff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #428bca; + text-decoration: none; +} +a:hover, +a:focus { + color: #2a6496; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px @solid #eeeeee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #999999; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 200; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +cite { + font-style: normal; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-muted { + color: #999999; +} +.text-primary { + color: #428bca; +} +a.text-primary:hover { + color: #3071a9; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #428bca; +} +a.bg-primary:hover { + background-color: #3071a9; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px @solid #eeeeee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px @solid #eeeeee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #999999; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px @solid #eeeeee; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +blockquote:before, +blockquote:after { + content: ""; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + white-space: nowrap; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 3px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px @solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: 0%; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: 0%; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: 0%; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: 0%; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: 0%; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: 0%; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: 0%; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: 0%; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + max-width: 100%; + background-color: transparent; +} +th { + text-align: left; +} +.table { + width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px @solid #dddddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px @solid #dddddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.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 > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px @solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px @solid #dddddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.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 col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +@media (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + overflow-x: scroll; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px @solid #dddddd; + -webkit-overflow-scrolling: touch; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px @solid #e5e5e5; +} +label { + display: inline-block; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + /* IE8-9 */ + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555555; + background-color: #ffffff; + background-image: none; + border: 1px @solid #cccccc; + border-radius: 4px; + -webkit-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-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #999999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999999; +} +.form-control::-webkit-input-placeholder { + color: #999999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; + opacity: 1; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +input[type="date"] { + line-height: 34px; +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + display: block; + min-height: 20px; + margin-top: 10px; + margin-bottom: 10px; + padding-left: 20px; +} +.radio label, +.checkbox label { + display: inline; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + float: left; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +.radio[disabled], +.radio-inline[disabled], +.checkbox[disabled], +.checkbox-inline[disabled], +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"], +fieldset[disabled] .radio, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.has-feedback .form-control-feedback { + position: absolute; + top: 25px; + right: 0; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; +} +.has-error .form-control-feedback { + color: #a94442; +} +.form-control-static { + margin-bottom: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + padding-left: 0; + vertical-align: middle; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .control-label, +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +.form-horizontal .form-control-static { + padding-top: 7px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + top: 0; + right: 15px; +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + cursor: pointer; + background-image: none; + border: 1px @solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + pointer-events: none; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + color: #333333; + background-color: #ebebeb; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} +.btn-default .badge { + color: #ffffff; + background-color: #333333; +} +.btn-primary { + color: #ffffff; + background-color: #428bca; + border-color: #357ebd; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #3276b1; + border-color: #285e8e; +} +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #428bca; + border-color: #357ebd; +} +.btn-primary .badge { + color: #428bca; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #47a447; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #39b3d7; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ed9c28; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #d2322d; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #ffffff; +} +.btn-link { + color: #428bca; + font-weight: normal; + cursor: pointer; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #2a6496; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #999999; + text-decoration: none; +} +.btn-lg { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +.btn-sm { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; + padding-left: 0; + padding-right: 0; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + transition: height 0.35s ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px @solid; + border-right: 4px @solid transparent; + border-left: 4px @solid transparent; +} +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.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; + font-size: 14px; + background-color: #ffffff; + border: 1px @solid #cccccc; + border: 1px @solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #428bca; +} +.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; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #999999; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px @solid; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px @solid #cccccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.clearfix:before, +.clearfix:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.nav:before, +.nav:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.nav:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; + visibility: hidden !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} + diff --git a/src/static/movio/templates/Sliding-windows/less/libs/mixin.less b/src/static/movio/templates/Sliding-windows/less/libs/mixin.less new file mode 100755 index 0000000..79d7fc2 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/libs/mixin.less @@ -0,0 +1,85 @@ +.padding-margin-reset() { + padding:0; + margin:0; +} +.box-sizing() { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.input-style (@width) { + background:@form-input-background; + border:0; + box-shadow:0; + color:@form-input-text; + width:@width; + padding:2px; + font-size:14px; + border:1px @solid @form-border; + height: 30px; + .border-radius(0); + &.required { + border:2px solid @form-required; + } +} +.button-style (@width) { + .button(auto, @form-button); + border:0; +} +.button(@width, @background:@form-button) { + background:@background; + width:@width; + text-align:center; + color:@form-button-text; + line-height:1em; + height:30px; + display:inline-block; + padding:0 15px 0 15px; + font-size:14px; + line-height:30px; + text-decoration:none; + &:hover { + text-decoration:none; + } +} +.border-radius (@radius) { + border-radius: @radius; + -moz-border-radius: @radius; + -webkit-border-radius: @radius; +} + +.icon-font() { + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #999) { + box-shadow: @arguments; + -moz-box-shadow: @arguments; + -webkit-box-shadow: @arguments; +} + +.grid(@col, @span, @margin) { + width: ((100% - (@margin * (@col - 1))) / @col * @span) + (@margin * (@span - 1)); + margin-right: @margin; +} + +.icon-font-awesome() { + font-family: 'FontAwesome'; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -moz-font-feature-settings: normal; + -moz-font-language-override: normal; + -moz-osx-font-smoothing: grayscale; + font-size: inherit; + font-size-adjust: none; + font-stretch: normal; + font-style: normal; + font-variant: normal; + font-weight: normal; + text-rendering: auto; +} diff --git a/src/static/movio/templates/Sliding-windows/less/mobile.less b/src/static/movio/templates/Sliding-windows/less/mobile.less new file mode 100755 index 0000000..ad7a783 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/mobile.less @@ -0,0 +1,519 @@ +@media (max-width: 979px) { + .navbar-toggle, .show-nav-for-iphone, .show-footer-nav-for-iphone { + display:block; + } + .navbar-toggle { + margin-left:15px; + } + .show-nav-for-iphone { + position:absolute; + left:0; + background:@color-link; + margin-left:10px; + top:0; + margin-top:20px; + z-index:9; + } + + header { + min-height:73px; + height:auto; + } + + .site-logo { + background: url(../img/logo.png) 0 0 no-repeat; + float:none; + display:block; + width:269px; + height:62px; + position:absolute; + left:50%; + top:0; + margin-top:5px; + margin-left:-269px / 2; + } + + #topbar { + display:none; + } + + .item-slide { + height:auto; + } + + .storyteller { + .actions { + + .sx, .dx { + float:none!important; + } + + ul { + text-align:center!important; + padding-bottom:8px!important; + } + + } + } + + .menu { + padding:0 0; + position:relative; + bottom:0; + right:0; + margin-bottom:5px; + margin-top:60px; + + ul { + .padding-margin-reset(); + margin-right:0; + + li { + list-style:none; + display:block!important; + float:none!important; + + &.jqx-menu-item-top-selected { + a { + background:none!important; + } + } + + a { + color: @color-link-menu; + font-size:14px; + margin-right:0; + padding:0 5px 0 5px; + border-bottom:0!important; + margin-bottom:8px; + border-left:3px solid @box-header-background; + + &:hover { + border-left:3px solid @border-color-link; + background:none!important; + } + &.active { + border-left:3px solid @border-color-link; + } + } + } + } + } + + .jqx-menu-dropdown { + display:none!important; + } + + .show-footer-nav-for-iphone { + margin-top:10px; + } + .collapse { + display:none; + } + .sx { + width:100%; + float:none; + } + .main-content { + width:100%; + float:none; + } + footer { + .box { + float:none; + width:100%; + min-height:inherit; + border-bottom:1px @solid #ccc; + border-right:0; + &:last-child { + border-bottom:0; + } + } + .logo-footer { + float:none; + width:100%; + min-height:inherit; + border-right:0; + border-bottom:1px @solid #ccc; + } + } + #topbar { + padding-bottom:8px; + form { + display:none; + } + } +} + +@media (max-width: 765px) { + + body { + overflow:auto; + overflow-x:hidden; + margin:0; + background:@footer-background; + } + + #outer { + margin:0; + } + + header { + position:relative; + } + + footer { + position:relative; + } + + .storyteller { + .actions { + display:none; + } + } + + .item-slide { + margin-right:10px; + + .main-img { + &.align-right { + + img { + float:none; + } + + } + &.align-left { + + img { + float:none; + } + + } + } + + &.story-slide { + height:auto!important; + + .content-slide { + height:auto!important; + + .arrow-big { + display:none; + } + + .item-box { + + + &.comment { + background:@storyteller-comments-background; + form { + margin-top:0; + margin:0 0; + + width:100%!important; + + span { + min-width: inherit; + text-align:left; + display:inline-block; + margin-right:0; + } + input[type="text"], textarea, label { + display:block; + width:100%!important; + } + } + } + + } + + + } + + } + + } + + .main-content { + margin-top:0; + position:relative; + margin-bottom:0; + height:auto!important; + min-height:700px!important; + overflow: hidden; + background:@white; + } + + .slideshow .slide { + height:600px; + } + + figure.main-img { + float:none!important; + display:block!important; + margin:0 auto 0 auto!important; + + .superzoom { + display:none; + } + + } + + .main-img { + float:none!important; + text-align:center!important; + width:200px!important; + + &.align-right { + float:none!important; + } + + img { + float:none!important; + } + + } + + input[type="text"], input[type="password"], input[type="email"] { + .input-style(100%); + + &.input-large { + width:300px; + } + &.input-small { + width:160px; + } + } + + .issue-slider { + + .slick-prev { + top:0!important; + margin-top:-60px!important; + } + + .slick-next { + top:0!important; + margin-top:-60px!important; + } + } + + /* slideshow */ + article.slideshow { + ul { + li { + height:360px; + background-position:bottom!important; + background-size:320px; + img { + width:100%!important; + float:none!important; + height:auto!important; + } + .description { + min-height:200px!important; + padding-left:10px; + width:100%!important; + background-color:@slider-background; + } + } + } + .flex-control-nav { + top:330px; + } + } +} + +/* iPads (portrait) ----------- */ +@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : portrait) { +} + +/* iPads (landscape) ----------- */ +@media only screen and (min-device-width : 768px) and (max-device-width : 1024px) and (orientation : landscape) { +} + +/* iPhone (landscape) ----------- */ +@media only screen and (max-width : 480px) { + + input[type="text"], input[type="password"], input[type="email"] { + .input-style(100%); + + &.input-large { + width:280px; + } + &.input-small { + width:160px; + } + } + + select { + width:auto; + &.select-large { + width:280px; + } + &.select-small { + width:160px; + } + &.select-medium { + width:260px; + } +} +textarea { + border:1px @solid @color1; + width:100%; + padding:4px; + height:150px; + &.textarea-large { + width:280px; + } +} + + + + footer { + + .logo-footer { + float:none; + padding:0; + border:0; + margin-top:10px; + margin-right:auto; + margin-left:auto; + text-align:center; + } + + p { + text-align:center; + } + + #info-page { + height:auto; + + nav { + display:block; + + ul { + padding-left:5px; + text-align:center; + + li { + display:inline; + + a { + display:inline-block; + border-right:0; + float:none; + padding-right:0; + margin:0 5px 0 0; + padding-top:8px; + height:auto; + } + + } + + } + + } + + p { + font-size:11px; + padding-top:0; + line-height:30px; + text-align:center; + display:block; + } + + } + + } + + .item-slide { + + } + +#outer { + + .item-slide { + + .slider { + margin-bottom:0; + position:relative; + + &.js-relationImage, &.js-relationImageLink, &.js-imageList { + + .slick-prev, .slick-next { + width:9px; + height:18px; + padding:0; + margin-top:30px; + background:none; + padding-top:5px; + margin-left:5px; + top:0; + } + + &.js-relationImageLink { + + .slick-prev, .slick-next { + top:50%!important; + margin-top:!important; + } + + .slick-next { + margin-right:5px!important; + } + + } + + } + + } + + } + +} + + .slideshow { + + .description { + width:100%; + .box-sizing(); + margin-left:0; + height:212px; + overflow:hidden; + position:absolute; + top:50%; + left:0; + margin:-106px 0 0 0; + padding:20px; + + h1 { + font-family: @font-2; + font-size:30px; + font-style:italic; + text-align:center; + padding-bottom:20px; + + a { + color:@slider-text; + text-decoration:none; + } + } + + p { + font-family: @font-2; + color:@slider-text; + line-height:1em; + font-size:20px; + display:block; + margin:0 auto; + width:200px; + padding-top:20px; + text-align:center; + border-top:1px solid @slider-text; + } + + } + } +} diff --git a/src/static/movio/templates/Sliding-windows/less/navigation.less b/src/static/movio/templates/Sliding-windows/less/navigation.less new file mode 100644 index 0000000..2c3d3e2 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/navigation.less @@ -0,0 +1,225 @@ +/** + * Language navigation + */ +.languages { +text-transform:uppercase; +position:absolute; +top:0; +right:0; +margin-right:10px; + + ul { + .padding-margin-reset(); + + li { + display:inline; + + a { + font-size:12px; + display:inline-block; + margin:0; + text-decoration:none; + border-top:5px solid @box-header-background; + width:25px; + padding-top:3px; + text-align:center; + + &:hover, &.active { + border-top:5px solid @border-color-link; + } + + } + + } + + } + +} + +/** + * Matanavigation + */ +.metanavigation { + margin-left:20px; + float:left; + margin-top:5px; + ul { + .padding-margin-reset(); + li { + display:inline; + padding:0 0 0 4px; + a { + display:inline-block; + margin-right:6px; + &.active { + text-decoration:underline; + } + } + } + } +} + +/** + * Navigation menu + */ +.menu { + padding:0 0; + position:absolute; + bottom:0; + right:0; + margin-bottom:5px; + + ul { + .padding-margin-reset(); + margin-right:-15px; + + li { + list-style:none; + display:inline-block; + float:left; + + &.jqx-menu-item-top-selected { + a { + color: @color-link-menu; + text-decoration:none; + border-bottom:5px solid @box-sub-menu-background; + background:@box-sub-menu-background; + } + } + + + a { + color: @color-link-menu; + font-size:12px; + text-transform:uppercase; + margin-right:25px; + display:inline-block; + padding:5px 8px 0 8px; + line-height:1em; + border-bottom:5px solid @box-header-background; + + &:hover { + color: @color-link-menu; + text-decoration:none; + border-bottom:5px solid @box-sub-menu-background; + background:@box-sub-menu-background; + } + &.active { + color: @color-link-menu; + text-decoration:none; + border-bottom:5px solid @border-color-link; + } + } + } + } +} + +.jqx-menu-dropdown { + .padding-margin-reset(); + width:174px; + background:@box-sub-menu-background; + + .jqx-item { + .jqx-icon-arrow-right { + width: 0!important; + height: 0!important; + border-top:5px solid transparent!important; + border-bottom:5px solid transparent!important; + border-left:5px solid @color-link-menu!important; + margin-right:5px!important; + margin-left:5px!important; + } + } + + a { + color: @color-link-menu; + line-height:1.2em; + padding:8px 8px; + border-bottom:1px solid @box-header-background; + display:block; + font-size:12px; + text-transform:uppercase; + + &:hover { + background:@border-color-link; + text-decoration:none; + } + + } + +} + +/** + * Breadcrumb + */ +.breadcrumb { + margin:5px 0 15px 0; + font-size:13px; + + ul { + .padding-margin-reset(); + li { + display:inline; + font-style:italic; + + &:first-child { + font-style:normal; + } + + a { + color: @breadkcrumbs-link; + &:hover { + color: @breadkcrumbs-link-hover; + text-decoration:none; + } + } + } + } +} + +/** + * Pagination + */ +.pagination { + width:100%; + + ul { + padding:0; + width:100%; + min-height:29px; + text-align:center; + text-align:center; + + li { + display:inline; + a { + border:0; + background:none; + float:none; + color:@text; + display:inline-block; + padding-top:0; + margin-top:7px; + padding-bottom:0; + line-height:1em; + font-size:14px; + outline:none; + padding:0 5px 0 5px; + border-left:1px @solid @box-border; + &:hover { + text-decoration:underline; + } + } + &.active a { + text-decoration:underline; + } + &:first-child > a { + border:0; + padding-left:17px; + } + &:last-child > a { + padding-right:17px; + } + } + } +} \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/less/slick.less b/src/static/movio/templates/Sliding-windows/less/slick.less new file mode 100755 index 0000000..d127b56 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/slick.less @@ -0,0 +1,136 @@ +/* slick */ +#outer { + + .slider { + margin-bottom:0; + + &.storyteller { + + .slick-dots { + position:absolute; + top:0; + margin-top:-20px; + height:20px; + } + + } + + &.entity-slider { + .slick-prev { + left:0; + margin-left:-20px; + } + } + + &.js-relationImage, &.js-relationImageLink, &.js-imageList { + + .slick-prev, .slick-next { + width:9px; + height:18px; + padding:0; + margin-top:30px; + background:none; + padding-top:5px; + margin-left:5px; + top:0; + } + + .slick-next { + margin-left:0; + margin-right:2px; + } + + .slick-prev:before, .slick-next:before { + color:@color-arrow-button-slider-hover; + font-family: 'FontAwesome'; + content:@fa-var-caret-left; + font-size:24px; + line-height:0; + } + + .slick-next:before { + content:@fa-var-caret-right; + } + + } + + .js-relationImageLink { + + .slick-prev, .slick-next { + margin-top:60px; + } + + } + + } + + /* dots */ + .slick-dots { + + li.slick-active { + + button { + background:@border-color-link; + } + + } + + li button { + width:12px; + height:12px; + padding:0; + .border-radius(100px); + background:@color-link; + + &:hover { + background:@border-color-link; + } + + &:before { + display:none; + } + + } + } + + /* Arrows */ + + .slick-prev:before, .slick-next:before { + font-family: 'FontAwesome'; + content:@fa-var-chevron-left; + color:@white; + opacity:1; + font-size:30px; + font-weight:lighter; + } + + .slick-disabled { + display:none!important; + } + + .slick-next:before { + content:@fa-var-chevron-right; + } + + .slick-prev, .slick-next { + width:40px; + height:56px; + padding-top:4px; + top:50%; + margin-top:-23px; + background:url(../img/bg/bg-opacity.png) repeat; + + + + } + + .slick-prev { + left:0; + + } + + .slick-next { + right:0; + } + +} \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/less/structure.less b/src/static/movio/templates/Sliding-windows/less/structure.less new file mode 100755 index 0000000..2a87b87 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/structure.less @@ -0,0 +1,208 @@ +.container-fluid { + padding:0; +} + +.content-box { + min-height:290px; + position:relative; +} + +.navbar-toggle, .show-nav-for-iphone, .show-footer-nav-for-iphone { + display:none; +} + +#outer { + width:100%; + max-width:100%; + margin:0 auto; + position:relative; +} + +#topbar { + font-size:14px; + height:30px; + padding-top:10px; + padding-left:10px; + padding-right:10px; + background:@box-header-background; + position:relative; + width:100%; + max-width:380px; + position:fixed; + top:0; + right:0; + z-index:6; + + a { + color:@box-header-link; + } + + +} + +header { + padding:0 0; + background:@box-header-background; + border-bottom:1px solid @box-border; + position:fixed; + top:0; + z-index:4; + width:100%; + height:73px; + overflow:hidden; + + .col-md-12 { + .padding-margin-reset(); + padding:5px; + } + + h1,h2 { + .padding-margin-reset(); + } + + .site-logo { + background: url(../img/logo.png) 0 0 no-repeat; + float:left; + text-indent:-9999px; + display:block; + width:269px; + height:62px; + + a { + display:block; + } + + } +} + +.main-content { + padding-left:15px; + padding-right:15px; + position:absolute; + top:0; + margin:72px 0 90px 0; + z-index:1; + overflow:auto; + overflow-x:hidden; +} + +footer { + width:100%; + max-width:100%; + clear:both; + position:fixed; + bottom:0; + z-index:4; + height:90px; + background:@footer-background; + + .box { + float:left; + padding:15px 15px; + border:0; + width:20%; + + p { + font-size:12px; + color: @footer-text; + } + + h2 { + .padding-margin-reset(); + line-height:1em; + font-size:16px; + color: @footer-text; + } + + ul { + .padding-margin-reset(); + padding-top:10px; + + li { + list-style:none; + + a, a:hover, a:link { + color: @footer-text-link; + } + } + + } + + } + + .logo-footer { + float:right; + padding:0; + border:0; + margin-top:10px; + margin-right:15px; + } + + + #info-page { + padding:0 10px; + color:#fff; + height:30px; + background:@background-info-page; + + nav { + + ul { + .padding-margin-reset(); + padding-left:5px; + + li { + display:inline; + + a { + color:@white; + text-transform:uppercase; + display:inline-block; + border-right:1px solid @footer-border; + float:left; + padding-right:12px; + margin:0 15px 0 0; + padding-top:8px; + font-size:11px; + height:20px; + } + + } + + } + + } + + p { + font-size:11px; + padding-top:0; + line-height:30px; + text-align:right; + } + + } +} + +.sx { + float:left; + + nav { + margin:0; + } + + #nav-collapse { + .padding-margin-reset(); + } +} + + +@media (min-width: 979px) { + header, footer, .sx { + .collapse { + display:block; + height:auto!important; + } + } +} + + diff --git a/src/static/movio/templates/Sliding-windows/less/styles.less b/src/static/movio/templates/Sliding-windows/less/styles.less new file mode 100755 index 0000000..f2d7e79 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/styles.less @@ -0,0 +1,146 @@ +/** + * Import libraries + * + * Bootstrap custom build: + * Print media styles + * Typography + * Code + * Grid system + * Tables + * Forms + * Buttons + * Input groups + * Badges + * Component animations (for JS) + * Dropdowns + * Basic utilities + * Responsive utilities +*/ +@import "libs/bootstrap.less"; +@import "libs/mixin.less"; +@import "font-awesome/font-awesome.less"; + +/** + * Import theme parts +*/ +@import "global.less"; +@import "structure.less"; +@import "navigation.less"; +@import "element.less"; +@import "slick.less"; +@import "mobile.less"; +@import "svg.less"; + +@font-1: 'PT Sans', sans-serif; +@font-2: 'PT Serif', serif; + +/*define colors */ +@white:#fff; +@black:#333; +@color1:#CCC; +@color2:#D8D8D8; +@color3:#F9F9F9; +@color4:#7A7A7A; +@color5:#C6C6C6; +@color6:#E4E4E4; +@color7:#F5F5F5; +@color8:#428BCA; +@color-success:green; +@color-error:red; +@solid:solid; + +/* custom color */ + +@color9:#303447; +@color10:#838591; +@color11:#CC0000; +@color12:#076A72; +@color13:#52979D; +@color14:#CC0000; +@color15:#222431; + +/*define theme colors */ +@text: @black; +@text-heading: @black; +@color-link: @color12; +@color-link-hover: darken(@color12, 5); +@breadkcrumbs-link: @black; +@breadkcrumbs-link-hover: @color-link-hover; + +@metanavigation-link: @white; +@metanavigation-link-hover: @white; + +@slider-background:@color1; +@slider-text:@white; +@slider-bullet-background: @black; +@slider-bullet-background-selected: @color1; + +@sidebar-background: @color7; +@sidebar-background-hover: @color12; +@sidebar-border: @color4; +@sidebar-link: @color-link; +@sidebar-link-hover: @color-link-hover; + +@icon-in-page:lighten(@text, 70); +@icon-in-box:@white; +@icon-in-box-background:@color1; + +@box-image-border:@color1; +@box-background:@white; +@box-header-background:@color9; +@box-border:@color1; +@box-header-link:@white; +@box-relation-item-border:@color1; +@box-text:@black; + +@color-border-button:@color1; +@color-arrow-button-slider:@black; +@color-arrow-button-slider-hover:@color12; +@color-border-button:@color1; +@color-background-button:@white; + +@storyteller-background: @color6; +@storyteller-border: darken(@storyteller-background, 5); +@storyteller-icon: lighten(@text, 70); +@storyteller-border: @color2; +@storyteller-item-background: @color3; +@storyteller-comments-background: @color3; +@storyteller-link: @color12; +@storyteller-navigation-link: @color4; +@storyteller-image-border: @color5; + +@form-border: @color1; +@form-required: @color1; +@form-button: @color4; +@form-button-text: @white; +@form-button-primary: @color12; +@form-button-primary-text:@white; +@form-input-text:@text; +@form-input-background:@white; + +@timeline-theme: @color12; + +@footer-background:@color9; +@footer-border:@color13; +@footer-text: @white; +@footer-text-link: @color-link; + +/* custom rule */ +@color-link-menu: @white; +@border-color-link:@color11; +@background-info-page:@color12; +@border-sub-title-page:@color1; +@border-input-header:@color10; +@color-link-enity:@black; +@button-zoom-img:@color14; +@box-sub-menu-background:@color15; +@background-main-content:@white; + +@svg-path-stroke:#000000; +@svg-main-node-background:#D3D3D3; +@svg-node-border:#CFCED3; +@svg-text-link:#CC3522; +@svg-text-link-hover:darken(@svg-text-link, 15); +@svg-text-node:#000000; +@svg-text-main-node:#000000; +@svg-node-background:#FFFFFF; diff --git a/src/static/movio/templates/Sliding-windows/less/svg.less b/src/static/movio/templates/Sliding-windows/less/svg.less new file mode 100644 index 0000000..b8649d5 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/less/svg.less @@ -0,0 +1,61 @@ +svg { + overflow: hidden; +} + +/* Stile testo delle entità */ +g.nodes tspan { + font-family: Helvetica, sans-serif; + font-size: 14px; + color: @svg-text-node; +} +/* Stile testo delle entità in HTML */ +g.nodes div { + white-space: nowrap; + padding: 2px 5px 2px 5px; + font-family: Helvetica, sans-serif; + font-size: 14px; + color: @svg-text-node; +} + +/* Stile testo delle entità principali */ +g.nodes tspan.main-node { + fill: @svg-text-main-node !important; +} +/* Stile testo delle entità principali in HTML */ +div.main-node { + padding: 2px 7px 2px 7px; + font-family: Helvetica, sans-serif; + font-size: 14px; + color: @svg-text-main-node !important; +} + +/* Stile testo delle relazioni */ +g.edgeLabels tspan { + +} +/* Stile riquadro delle entità */ +.node rect { + stroke: @svg-node-border; + stroke-width: 2px; + fill: @svg-node-background; +} +.node a { + color: @svg-text-link; + text-decoration: underline; +} +.node a:hover { + color: @svg-text-link-hover; +} +/* Stile riquadro delle entità principali */ +.node rect.main-node { + fill: @svg-main-node-background; +} +/* Stile delle frecce */ +.edgePath path { + stroke: @svg-path-stroke; + stroke-width: 1.5px; + fill: none; +} + + + diff --git a/src/static/movio/templates/Sliding-windows/page.php b/src/static/movio/templates/Sliding-windows/page.php new file mode 100644 index 0000000..10542ca --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/page.php @@ -0,0 +1,122 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title><?php print $docTitle?></title> + <script src="//code.jquery.com/jquery-1.11.0.min.js"></script> + <script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script> + <script src="js/jqxcore.js"></script> + <script src="js/jqxmenu.js"></script> + <link href="css/jquery.mCustomScrollbar.css" rel="stylesheet" type="text/css" /> + <script src="js/jquery.mCustomScrollbar.concat.min.js"></script> + <?php print $css?> + <link rel="stylesheet" type="text/css" href="../../../mediaelement/mediaelementplayer.css" charset="utf-8"> + <link rel="stylesheet" type="text/css" href="../../../js/slick/slick.css"> + <!--[if lte IE 9]> + <link rel="stylesheet" href="css/ie.css" /> + <![endif]--> + <?php print $head?> +</head> + +<body> + <!-- outer --> + <div id="outer"> + + <!-- topbar --> + <div id="topbar" class="clearfix"> + <nav class="languages"> + <?php print $languages; ?> + </nav> + <?php print $search; ?> + </div> + <!-- topbar --> + + <!-- content --> + <div class="clearfix container-fluid"> + + <!-- header --> + <header id="header" class="row-fluid clearfix"> + <div class="col-md-12 visible-tablet visible-desktop"> + <h1 class="site-logo"><a href="<?php print GLZ_HOST; ?>" class="site-logo"><?php print $siteTitle; ?></a></h1> + <button type="button" class="show-nav-for-iphone" data-toggle="collapse" data-target="#nav-collapse">MENU</button> + <div id="nav-collapse" class="collapse col-md-12"> + <nav class="menu"> + <?php print $menu; ?> + </nav> + </div> + </div> + </header> + <!-- header --> + + <!-- content-box --> + <div class="content-box row-fluid clearfix"> + <!-- article --> + <article class="main-content col-md-12"> + <?php if ($breadcrumbs) { ?> + <nav class="breadcrumb"> + <?php print $breadcrumbs; ?> + </nav> + <?php } ?> + <?php if ($pageTitle) { ?> + <div class="box-title clearfix"> + <?php print $pageTitle; ?> + </div> + <?php } ?> + <?php if ($content) { ?> + <div class="clearfix"> + <?php print $content; ?> + </div> + <?php } ?> + <?php if ($afterContent) { ?> + <div class="clearfix"> + <?php print $afterContent; ?> + </div> + <?php } ?> + </article> + <!-- article --> + </div> + <!-- content-box --> + </div> + <!-- content --> + </div> + <!-- outer --> + + <!-- footer --> + <footer id="footer"> + <div id="info-page" class="visible-desktop"> + <div class="container-fluid"> + <nav> + <?php print $metanavigation; ?> + </nav> + <p><?php print $docUpdate;?></p> + </div> + </div> + + <div class="clearfix"> + <div class="logo-footer"> + <?php print $logoFooter; ?> + <a href="http://www.movio.beniculturali.it" title="Movio - Online Virtual Exhibition"> + <img src="img/logo_movio.png" alt="Movio - Online Virtual Exhibition" title="Movio - Online Virtual Exhibition" width="80" > + </a> + </div> + + <div class="box"> + <?php print $sharing; ?> + <?php print $copyright; ?> + </div> + </div> + </footer> + <!-- footer --> + + <script src="js/bootstrap.min.js"></script> + <script src="js/main.js"></script> + <script src="../../js/movio.js"></script> + <script src="../../../mediaelement/mediaelement-and-player.js" type="text/javascript"></script> + <script src="../../../js/slick/slick.min.js"></script> + + <?php print $tail; ?> +</body> +</html> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/pageTypes/Home.xml b/src/static/movio/templates/Sliding-windows/pageTypes/Home.xml new file mode 100644 index 0000000..f9ba3fb --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/pageTypes/Home.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="iso-8859-1"?> +<glz:Page id="Page" + xmlns:glz="http://www.glizy.org/dtd/1.0/" + xmlns:cms="org.glizycms.views.components.*" + xmlns:m="movio.views.components.*" + templateType="php" + templateFileName="1col.php" + defaultEditableRegion="content" + addCoreJS="true"> + <glz:Import src="Common.xml" /> + + <glz:Modifier target="pageTitle" attribute="visible" value="false" /> + <glz:Modifier target="breadcrumbs" attribute="visible" value="false" /> + + <glz:Repeater id="slider" label="{i18n:Image slider}" adm:collapsable="true" skin="HomeImageSlider.html"> + <glz:Input id="title" label="{i18n:Title}" size="50" required="false" /> + <glz:LongText id="text" label="{i18n:Text}" adm:rows="20" adm:cols="75" adm:htmlEditor="true" /> + <glz:Image id="image" label="{i18n:Image}" width="{config:movio.thumb.homeSlider.width}" height="{config:movio.thumb.homeSlider.height}" crop="{config:movio.thumb.homeSlider.crop}" /> + <cms:PagePicker id="pageId" label="{i18n:Linked page}" required="false" /> + </glz:Repeater> +</glz:Page> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/preview.jpg b/src/static/movio/templates/Sliding-windows/preview.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3c5c8dbcfe78332e7cb282e50a9c91ef90c16fa7 GIT binary patch literal 15548 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 literal 0 HcmV?d00001 diff --git a/src/static/movio/templates/Sliding-windows/skins/BoxList.html b/src/static/movio/templates/Sliding-windows/skins/BoxList.html new file mode 100644 index 0000000..9f2d3a2 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/skins/BoxList.html @@ -0,0 +1,21 @@ +<span tal:omit-tag="" tal:repeat="item Component"> + <div class="content-box row-fluid "> + <span tal:omit-tag="" tal:repeat="subitem item"> + <span tal:omit-tag=""> + <article class="box col-md-3"> + <a tal:condition="subitem/image/__html__" tal:attributes="href subitem/pageId; title subitem/title" tal:content="structure subitem/image/__html__"></a> + <h1><a tal:attributes="href subitem/pageId; title subitem/title" tal:content="subitem/title"></a></h1> + <div class="container" tal:condition="php: subitem.type == 'imageText'"> + <span tal:omit-tag="" tal:content="structure subitem/text" /> + </div> + <div class="wrapper-link"> + <a tal:attributes="href subitem/pageId; title subitem/title"> + <span tal:condition="php: subitem.type == 'imageLink'" tal:omit-tag="" tal:content="subitem/linkTitle" /> + <i class="fa fa-arrow-right"></i> + </a> + </div> + </article> + </span> + </span> + </div> +</span> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/skins/Entity_entry.html b/src/static/movio/templates/Sliding-windows/skins/Entity_entry.html new file mode 100644 index 0000000..bdd6182 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/skins/Entity_entry.html @@ -0,0 +1,208 @@ +<div class="clearfix"> + <div class="quick-slider-nav"> + <ul></ul> + </div> + <script> + $(function(){ + + var setMenuActive = function() { + var currentSlide = $('.issue-slider').getSlick().currentSlide; + $(".quick-slider-nav li").each(function(){ + $el = $(this).find('a').first(); + if($el.attr('data') == currentSlide) { + $el.addClass('active'); + } else { + $el.removeClass('active'); + } + }); + } + + var setSlide = function(initialSlide) { + $('.issue-slider').unslick(); + $('.issue-slider').slick({ + dots: false, + refresh: true, + centerPadding: '170px', + centerMode: true, + infinite: false, + speed: 700, + slidesToShow: 1, + slidesToScroll: 1, + onAfterChange: setMenuActive, + responsive: [{ + breakpoint: 480, + settings: { + centerPadding: '10px' + } + }] + }); + } + + var resize = function() { + var h = $(window).height() - $('#header').height() - $('#footer').height() -2*($('div.quick-slider-nav').height() + $('div.box-title').height() + $('div.breadcrumb').height()); + $('.item-slide-height-full').height(h); + } + + $( document ).on('click', '.quick-slider-nav a', function(e){ + e.preventDefault(); + $(this).parent().parent().find('a.active').first().removeClass('active'); + $(this).addClass('active'); + $('.issue-slider').slickGoTo(parseFloat($(this).attr('data'))); + }); + $( document ).on('click', '.slick-next, .slick-prev', function(e){ + setMenuActive(); + }); + + $(document).on('ready', function(){ + var html =''; + $('div .item-slide').each(function(index, el){ + active = index == 0 ? ' class="active" ' : ' '; + // <![CDATA[ + html += '<li><a' + active +'data="' + index + '"><span class="fa fa-' + $(this).attr("data")+ '"></span></a></li>'; + // ]]> + }); + $('div.quick-slider-nav ul').append(html); + + var width1 = $(window).width(); + if(width1 >= 700) { + $(window).resize(function () { + resize(); + }); + resize(); + } + + setSlide(); + + $('.js-relationImage').slick({ + dots: false, + infinite: false, + speed: 700, + slidesToShow: 6, + slidesToScroll: 1, + responsive: [{ + breakpoint: 1024, + settings: { + slidesToShow: 3, + slidesToScroll: 1, + infinite: true, + dots: false + } + }, { + breakpoint: 600, + settings: { + slidesToShow: 2, + slidesToScroll: 1 + } + }, { + breakpoint: 480, + settings: { + slidesToShow: 1, + slidesToScroll: 1 + } + }] + }); + }); + }); + </script> + + <div class="slider issue-slider clearfix"> + + <span tal:omit-tag="" tal:repeat="attribute Component/attributes/figure" > + <div class="item-slide item-slide-height-full slide clearfix" data="picture-o" tal:condition="php: Component[attribute['name']]['mediaId']" > + <div class="overflow content-slide"> + <figure> + <span tal:omit-tag="" tal:content="structure php:Component[attribute['name']]['__html__']" /> + <figcaption class="description" tal:content="structure php:Component[attribute['name']]['title']" /> + </figure> + </div> + </div> + </span> + + <div class="item-slide item-slide-height-full text slide clearfix" data ="file-text"> + <div class="overflow content-slide" > + <span tal:omit-tag="" tal:condition="php: count(Component['attributes'].properties)"> + <span tal:omit-tag="" tal:repeat="attribute Component/attributes/properties"> + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'property'"> + <span tal:omit-tag="" tal:condition="php: Component[attribute['name']] != ''"> + <dt tal:condition="php: attribute['label']" tal:content="php: attribute['label']"></dt> + <dd tal:content="structure php:Component[attribute['name']]"></dd> + </span> + </span> + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'date'"> + <span tal:omit-tag="" tal:condition="php: Component[attribute['name']] != ''"> + <dt tal:condition="php: attribute['label']" tal:content="php: attribute['label']"></dt> + <dd tal:content="php:glz_defaultDate2locale( __T('GLZ_DATE_FORMAT'), Component[attribute['name']])"></dd> + </span> + </span> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'thesaurus'"> + <span tal:omit-tag="" tal:condition="php: count(Component[attribute['name']])"> + <dt tal:condition="php: attribute['label']" tal:content="php: attribute['label']"></dt> + <dd><span tal:omit-tag="" tal:repeat="item php:Component[attribute['name']]"><a tal:attributes="href item/url; title item/title" tal:content="structure item/title"></a> </span></dd> + </span> + </span> + </span> + </span> + <span tal:omit-tag="" tal:condition="php: count(Component['attributes'].body)"> + <span tal:omit-tag="" tal:repeat="attribute Component/attributes/body"> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'longtext'"> + <span tal:omit-tag="" tal:condition="php: !glz_empty(Component[attribute['name']])"> + <h3 tal:condition="php: attribute['label']" tal:content="php: attribute['label']" /> + <span tal:omit-tag="" tal:content="structure php:Component[attribute['name']]" /> + </span> + </span> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'imagelist'"> + <span tal:omit-tag="" tal:condition="php: count(Component[attribute['name']]['content'])"> + <h3 tal:condition="php: attribute['label']" tal:content="php: attribute['label']" /> + <div class="slider js-relationImage imageList clearfix js-imageList"> + <div class="slide" tal:repeat="item php:Component[attribute['name']]['content']" tal:content="structure item/__html__" /> + </div> + </span> + </span> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'media'"> + <span tal:omit-tag="" tal:condition="php: Component[attribute['name']]['__html__'] != ''"> + <h3 tal:condition="php: attribute['label']" tal:content="php: attribute['label']" /> + <span tal:omit-tag="" tal:content="structure php:Component[attribute['name']]['__html__']" /> + </span> + </span> + + <span tal:omit-tag="" tal:condition="php: attribute['type'] == 'medialist'"> + <span tal:omit-tag="" tal:condition="php: count(Component[attribute['name']]['content'])"> + <h3 tal:condition="php: attribute['label']" tal:content="php: attribute['label']" /> + <ul class="downloadList"> + <li tal:repeat="item php:Component[attribute['name']]['content']" tal:content="structure item/__html__" /> + </ul> + </span> + </span> + </span> + </span> + </div> + </div> + + <div class="item-slide item-slide-height-full link slide clearfix" data="link" tal:condition="php: property_exists(Component['relations'], 'europeanaRelatedContents') or property_exists(Component['relations'], 'relations') or property_exists(Component['relations'], 'referenceRelations')" > + <div class="overflow content-slide slider js-relationImage imageList clearfix js-imageList" > + <article class="box collapsible big"> + <span tal:condition="php: property_exists(Component['relations'], 'europeanaRelatedContents')" tal:content="structure Component/relations/europeanaRelatedContents" /> + <span tal:condition="php: property_exists(Component['relations'], 'relations')" tal:content="structure Component/relations/relations" /> + <span tal:condition="php: property_exists(Component['relations'], 'referenceRelations')" tal:content="structure Component/relations/referenceRelations" /> + </article> + </div> + </div> + + <div class="item-slide item-slide-height-full link slide clearfix" data="film" tal:condition="php: property_exists(Component['relations'], 'photogallery')" > + <div class="overflow content-slide" > + <article tal:condition="php: property_exists(Component['relations'], 'photogallery')" tal:content="structure Component/relations/photogallery" /> + </div> + </div> + + <div class="item-slide item-slide-height-full link slide clearfix" data="sitemap" tal:condition="php: property_exists(Component['relations'], 'relationsGraph')" > + <div class="overflow content-slide" > + <article class="box relationGeneral collapsible big" tal:content="structure Component/relations/relationsGraph" /> + </div> + </div> + + </div> +</div> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/skins/Entity_list.html b/src/static/movio/templates/Sliding-windows/skins/Entity_list.html new file mode 100644 index 0000000..a9d6f2d --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/skins/Entity_list.html @@ -0,0 +1,56 @@ +<section class="results-content" tal:condition="php: !is_null(Component.records)"> + <h3 tal:condition="Component/title" tal:content="structure Component/title"/> + <span tal:omit-tag="" tal:condition="php: Component.records.count() > 0"> + + <span tal:omit-tag="" tal:condition="php: Component.params.visualization == 'listAndIcons' OR Component.params.visualization == 'icons'" tal:content="structure php: ('<div class=\'row-fluid clearfix\'><div class=\'slider entity-slider js-entity-slider\'>')" /> + + <span tal:omit-tag="" tal:repeat="item Component/records" tal:attributes="class item/__cssClass__"> + + <span tal:omit-tag="" tal:condition="php: Component.params.visualization == 'list'"> + <article class="item clearfix"> + <h1><a href="" tal:attributes="href item/__url__; title item/title" tal:content="item/title"></a></h1> + </article> + </span> + + <span tal:omit-tag="" tal:condition="php: Component.params.visualization == 'listWithDescription'"> + <article class="item clearfix"> + <h1><a href="" tal:attributes="href item/__url__; title item/title" tal:content="item/title"></a></h1> + <span tal:omit-tag="" tal:condition="php: Component.params.attributes.description && item.keyInDataExists(Component.params.attributes.description)" tal:content="structure php: item->{Component.params.attributes.description}" /> + </article> + </span> + + <span tal:omit-tag="" tal:condition="php: Component.params.visualization == 'listAndIcons' OR Component.params.visualization == 'icons'"> + <div class="item slide in-grid clearfix"> + <figure> + <a href="" tal:attributes="href item/__url__; title item/title" tal:content="structure item/__image"></a> + </figure> + <h2><a tal:attributes="href item/__url__; title item/title" tal:content="item/title"></a></h2> + </div> + </span> + + </span> + + <span tal:omit-tag="" tal:condition="php: Component.params.visualization == 'listAndIcons' OR Component.params.visualization == 'icons'" tal:content="structure php: ('</div></div>')" /> + </span> + <span tal:omit-tag="" tal:condition="php: Component.records.count() == 0"> + <p tal:content="php:__Tp('MW_NO_RECORD_FOUND')"></p> + </span> + +<script> +$(document).ready(function() { + $('.js-entity-slider').slick({ + dots: false, + infinite: false, + speed: 700, + slidesToShow: 4, + slidesToScroll: 1, + responsive: [{ + breakpoint: 480, + settings: { + slidesToShow:1 + } + }] + }); +}); +</script> +</section> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/skins/Entity_relationImage.html b/src/static/movio/templates/Sliding-windows/skins/Entity_relationImage.html new file mode 100644 index 0000000..71787bf --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/skins/Entity_relationImage.html @@ -0,0 +1,27 @@ +<article class="box collapsible big relationImage" tal:condition="php: Component"> + <h1><span tal:omit-tag="" tal:content="structure Component/relation" /> <i class="ico-box fa fa-link"></i></h1> + <button data-toggle="collapse" class="show-content-box" type="button" tal:attributes="data-target php: '#' . Component['id']"></button> + <div tal:attributes="id Component/id"> + <div class="container"> + <div class="slider js-relationImage clearfix"> + <div class="slide" tal:repeat="item Component/content"> + <a tal:condition="exists:item/__image" tal:attributes="href item/url; title item/title" tal:content="structure item/__image/__html__"> + <span class="popup" > + <span class="popup-text" tal:content="item/title"> + <span class="popup-arrow"></span> + </span> + </span> + </a> + </div> + </div> + </div> + </div> + <script> + $(function() { + var targetId = '#<span tal:omit-tag="" tal:content="Component/id"/>'; + Movio.initImageSlider(targetId+' .js-relationImage'); + }); + </script> +</article> + + diff --git a/src/static/movio/templates/Sliding-windows/skins/Entity_relationImageLink.html b/src/static/movio/templates/Sliding-windows/skins/Entity_relationImageLink.html new file mode 100644 index 0000000..7b935b0 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/skins/Entity_relationImageLink.html @@ -0,0 +1,16 @@ +<article class="box collapsible big relationImageLink" tal:condition="php: Component"> + <h1><span tal:omit-tag="" tal:content="structure Component/relation" /> <i class="ico-box fa fa-link"></i></h1> + <button data-toggle="collapse" class="show-content-box" type="button" tal:attributes="data-target php: '#' . Component['id']"></button> + <div tal:attributes="id Component/id"> + <div class="container"> + <span tal:omit-tag="" tal:repeat="item Component/content"> + <span tal:omit-tag="" tal:condition="php: (repeat.item.index % 3) == 0" tal:content="structure php: ('<div class=\'row-fluid\'>')" /> + <div class="item col-md-4" > + <figure tal:condition= "exists:item/__image"><a tal:attributes="href item/url; title item/title" tal:content="structure item/__image/__html__"></a></figure> + <h2><a tal:attributes="href item/url; title item/title" tal:content="structure item/title"></a></h2> + </div> + <span tal:omit-tag="" tal:condition="php: (repeat.item.index % 3) == 2 || repeat.item.end" tal:content="structure php:('</div>') " /> + </span> + </div> + </div> +</article> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/skins/Entity_relationLink.html b/src/static/movio/templates/Sliding-windows/skins/Entity_relationLink.html new file mode 100644 index 0000000..ce0838c --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/skins/Entity_relationLink.html @@ -0,0 +1,13 @@ +<article class="box collapsible big relationLink" tal:condition="php: Component"> + <h1><span tal:omit-tag="" tal:content="structure Component/relation" /> <i class="ico-box fa fa-link"></i></h1> + <button data-toggle="collapse" class="show-content-box" type="button" tal:attributes="data-target php: '#' . Component['id']"></button> + <div tal:attributes="id Component/id"> + <div class="container"> + <div class="row-fluid"> + <ul class="item-list"> + <li tal:repeat="item Component/content"><a tal:attributes="href item/url; title item/title" tal:content="structure item/title"></a></li> + </ul> + </div> + </div> + </div> +</article> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/skins/EuropeanaRelatedContents.html b/src/static/movio/templates/Sliding-windows/skins/EuropeanaRelatedContents.html new file mode 100644 index 0000000..37f0d23 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/skins/EuropeanaRelatedContents.html @@ -0,0 +1,46 @@ +<span tal:omit-tag="" tal:condition="php: Component['ajax']"> + <span tal:omit-tag="" tal:condition="php: !Component['error']" class="wrapper-box-summary no-padding clearfix"> + <div class="slider js-europeanaRelated clearfix"> + <div class="slide" tal:repeat="item Component/records"> + <a target="_blank" tal:attributes="href item/url; title item/title"> + <img tal:attributes="src item/image; title item/title" width="50" height="46" /> + <span class="popup" > + <span class="popup-text">Nascita di diversi stati in Europa + <span class="popup-arrow"></span> + </span> + </span> + </a> + </div> + </div> + </span> + <span tal:omit-tag="" tal:condition="php: Component['error']" class="wrapper-box-summary no-padding clearfix"> + <h1 tal:content="structure Component/error" /> + </span> +</span> + +<span tal:omit-tag="" tal:condition="php: !Component['ajax'] "> + <article class="box collapsible big relationImage" tal:condition="php: Component"> + <h1><span tal:omit-tag="" tal:content="structure Component/label" /></h1> + <button data-toggle="collapse" class="show-content-box" type="button" tal:attributes="data-target php: '#' . Component['id']"></button> + <div tal:attributes="id Component/id"> + <div class="container"> + <div style="text-align: center"> + <img src="static/movio/assets/img/loader_white.gif" style="border: 0; margin: 20px" /> + </div> + </div> + </div> + </article> + <script> +$(function() { + var targetId = '#<span tal:omit-tag="" tal:content="Component/id" />'; + jQuery.ajax({ + url: '<span tal:omit-tag="" tal:content="structure Component/ajaxUrl" />', + dataType: 'json', + success: function( data ) { + $(targetId+' div.container').html(data.content); + Movio.initImageSlider(targetId+' .js-europeanaRelated'); + } + }); +}); + </script> +</span> diff --git a/src/static/movio/templates/Sliding-windows/skins/HomeImageSlider.html b/src/static/movio/templates/Sliding-windows/skins/HomeImageSlider.html new file mode 100644 index 0000000..8983aa9 --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/skins/HomeImageSlider.html @@ -0,0 +1,25 @@ +<article class="slideshow big"> + <div class="slider single-item js-sliderhome" > + <div class="slide" tal:attributes="style php:Template::homeSliderImage(item)" tal:repeat="item Component"> + <div class="description"> + <h1><a tal:attributes="href item/pageId; title item/title" tal:content="item/title"></a></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <a class="link-continue" tal:attributes="href item/pageId" tal:content="php: __T('read more')"></a> + </div> + </div> + </div> +<script> +$(function() { + $('.js-sliderhome').slick({ + dots: false, + autoplay: true, + autoplaySpeed: Glizy.slideShowSpeed, + arrows:true, + infinite: true, + speed: 700, + slidesToShow: 1, + slidesToScroll: 1 + }); +}); +</script> +</article> \ No newline at end of file diff --git a/src/static/movio/templates/Sliding-windows/skins/Storyteller.html b/src/static/movio/templates/Sliding-windows/skins/Storyteller.html new file mode 100644 index 0000000..840ec6d --- /dev/null +++ b/src/static/movio/templates/Sliding-windows/skins/Storyteller.html @@ -0,0 +1,358 @@ +<div class="clearfix margin-left: auto;"> + <script src="static/galleria/galleria-1.4.2.min.js"></script> + <script> + var galleries = []; + + var setSlick = function() { + $('.issue-slider').unslick(); + $('.issue-slider').slick({ + dots: true, + centerPadding: '170px', + centerMode: true, + infinite: false, + speed: 700, + slidesToShow: 1, + slidesToScroll: 1, + responsive: [{ + breakpoint: 480, + settings: { + centerPadding: '10px' + } + }] + }); + $(".issue-slider").css("margin-top", "10px"); + } + + var resize =function() { + var h = $(window).height() - $('#header').height() - $('#footer').height() -2*($('div.quick-slider-nav').height() + $('div.box-title').height() + $('div.box-title').parent().find('p').first().height() + $('div.breadcrumb').height() + $('.slick-dots').height() + 10); + $('.item-slide-height-full').height(h); + } + + function galleriaio_loadNext() { + if (galleries.length) { + var callback = galleries.shift(); + callback(); + } + } + + $(function(){ + $(".js-storytellerNav a").each(function(index, el){ + var el = $(el); + var cssClass = el.attr("class"); + if (cssClass && $("div."+cssClass).length==0) { + el.parent().hide(); + } + }); + + $(".js-storytellerNav a").click(function(e){ + e.preventDefault(); + var el = $(this); + el.parent().siblings().removeClass("active"); + el.parent().addClass("active"); + var cssClass = el.attr("class"); + if (cssClass) { + $("div."+cssClass).show(); + $("div.item-slide:not(."+cssClass+")").addClass("js-itemHidden").hide(); + } else { + $("div.js-itemHidden").show(); + } + $("div.content-slide > article.js-formComment").slideUp(300); + }) + + $("a.js-writeComment").click(function(e){ + e.preventDefault(); + $(this).closest("article.item-box").next().slideDown(300); + }); + + $(".js-formCommentCancel").click(function(e){ + e.preventDefault(); + $(this).closest("article.item-box").slideUp(300); + }); + + $(".js-formComment form").submit(function(){ + var form = $(this); + if (!form.find("input#authorName").val()) { + alert("Insert the name"); + return false; + } + if (!form.find("input#authorEmail").val()) { + alert("Insert the email"); + return false; + } + if (!form.find("textarea#text").val()) { + alert("Insert the comment text"); + return false; + } + + }); + + $("a.js-commentsMoreLink").click(function(e){ + e.preventDefault(); + $(this).parent().parent().find(".js-commentsMore").slideDown(300); + $(this).hide(); + }); + + jQuery('video,audio').mediaelementplayer(); + galleriaio_loadNext(); + }); + + $(document).on('ready', function() { + setSlick(); + var width1 = $(window).width(); + if(width1 >= 700) { + $(window).resize(function () { + resize(); + }); + resize(); + } + }); + + </script> + <div class="slider issue-slider storyteller clearfix" > + <span tal:omit-tag="" tal:repeat="item Component"> + <a tal:attributes="name item/hash"></a> + <div class="item-slide item-slide-height-full slide story-slide clearfix" tal:condition="php:item.type=='text'"> + <div class="overflow content-slide"> + <article class="item-box" > + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item with-angle-icon"> + <div class="clearfix"> + <figure class="main-img align-right" tal:condition="item/image" tal:content="structure php:org_glizy_helpers_Media::getResizedImageById(item.image, false, 320, 320)"> + </figure> + <div tal:condition="item/audio" style="float:right; margin: 30px 0 0 15px;"> + <audio controls="" tal:attributes="src php:org_glizy_helpers_Media::getFileUrlById(item.audio, true)" /> + </div> + <div tal:condition="item/video" style="float:right; margin: 0 15px 0 0;"> + <video width="300" height="200" controls="" tal:attributes="src php:org_glizy_helpers_Media::getFileUrlById(item.video, true)" /> + </div> + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <h2 class="tipe-box" tal:condition="item/subtitle" tal:content="item/subtitle"></h2> + <span tal:omit-tag="" tal:content="structure item/text" /> + </div> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from ''" /> + </div> + </article> + <span tal:omit-tag="" metal:use-macro="formComments" tal:define="item item" /> + <span tal:omit-tag="" metal:use-macro="comments" tal:define="item item" /> + </div> + </div> + + <div class="item-slide item-slide-height-full slide story-slide clearfix" tal:condition="php:item.type=='youtube'"> + <div class="overflow content-slide"> + <article class="item-box"> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item" > + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <iframe width="640" height="360" frameborder="0" allowfullscreen="" tal:attributes="src item/url"></iframe> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from 'Youtube'" /> + </div> + </article> + <span tal:omit-tag="" metal:use-macro="formComments" tal:define="item item" /> + <span tal:omit-tag="" metal:use-macro="comments" tal:define="item item" /> + </div> + </div> + + <div class="item-slide item-slide-height-full slide story-slide clearfix" tal:condition="php:item.type=='vimeo'"> + <div class="overflow content-slide"> + <article class="item-box "> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <iframe width="640" height="360" frameborder="0" allowfullscreen="" tal:attributes="src item/url"></iframe> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from 'Vimeo'" /> + </div> + </article> + <span tal:omit-tag="" metal:use-macro="formComments" tal:define="item item" /> + <span tal:omit-tag="" metal:use-macro="comments" tal:define="item item" /> + </div> + </div> + + <div class="item-slide item-slide-height-full slide story-slide clearfix" tal:condition="php:item.type=='video'"> + <div class="overflow content-slide"> + <article class="item-box link "> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <div class="clearfix"> + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <video controls="" width="100%" style="max-width: 100%" tal:attributes="src php:org_glizy_helpers_Media::getFileUrlById(item.video, true)" /> + </div> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from ''" /> + </div> + </article> + <span tal:omit-tag="" metal:use-macro="formComments" tal:define="item item" /> + <span tal:omit-tag="" metal:use-macro="comments" tal:define="item item" /> + </div> + </div> + + <div class="item-slide item-slide-height-full slide story-slide clearfix" tal:condition="php:item.type=='audio'"> + <div class="overflow content-slide"> + <article class="item-box link "> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <div class="clearfix"> + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <audio controls="" width="100%" tal:attributes="src php:org_glizy_helpers_Media::getFileUrlById(item.audio, true)" /> + </div> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from ''" /> + </div> + </article> + <span tal:omit-tag="" metal:use-macro="formComments" tal:define="item item" /> + <span tal:omit-tag="" metal:use-macro="comments" tal:define="item item" /> + </div> + </div> + + <div class="item-slide item-slide-height-full slide story-slide clearfix" tal:condition="php:item.type=='image'"> + <div class="overflow content-slide"> + <article class="item-box link"> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <article class="item-linked"> + <div class="clearfix"> + <h1 class="title" tal:condition="item/title" tal:content="item/title"></h1> + <span tal:omit-tag="" tal:content="structure item/text" /> + <figure tal:condition="item/image" style="max-width:100%" tal:content="structure php:org_glizy_helpers_Media::getImageById(item.image)"> + </figure> + </div> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from ''" /> + </article> + </div> + </article> + <span tal:omit-tag="" metal:use-macro="formComments" tal:define="item item" /> + <span tal:omit-tag="" metal:use-macro="comments" tal:define="item item" /> + </div> + </div> + + <div class="item-slide item-slide-height-full slide story-slide clearfix" tal:condition="php:item.type=='photogallery'"> + <div class="overflow content-slide"> + <article class="item-box gallery "> + <span tal:condition="item/showArrow" class="arrow-big"></span> + <div class="content-box-item"> + <h4 class="tipe-box big"><span tal:omit-tag="" tal:content="item/title"/><i class="ico gallery"></i></h4> + <span tal:omit-tag="" tal:content="structure item/text" /> + <div tal:attributes="class php: 'wrapper-galleria-io ' . item.galleryType" tal:condition="php: item.gallery AND item.gallery.count()"> + <div class="content-galleria-io" > + <div tal:attributes="id php: 'galleria' . item.hash" style="height: 500px"></div> + <script> + galleries.push(function(){ + var data = []; + <span tal:omit-tag="" tal:repeat="subitem item/gallery"> + data.push({ "title": "<span tal:omit-tag="" tal:content="structure php: glz_stringToJs(subitem.media_title)" />", + "description": "<span tal:omit-tag="" tal:content="structure php: glz_stringToJs(subitem.media_description, true)" />", + "thumb": "<span tal:omit-tag="" tal:content="php:org_glizy_helpers_Media::getResizedImageUrlById(subitem.media_id, false, __Config::get('THUMB_WIDTH'), __Config::get('THUMB_HEIGHT'), true)" />", + "image": "<span tal:omit-tag="" tal:content="php:org_glizy_helpers_Media::getUrlById(subitem.media_id)" />" + }); + </span> + Galleria.loadTheme('static/galleria/themes/movio/galleria.<span tal:omit-tag="" tal:content="item/galleryType" />.js'); + Galleria.run('<span tal:omit-tag="" tal:content="php: '#galleria' . item.hash" />', { + dataSource: data, imageCrop: <span tal:omit-tag="" tal:content="item/galleryImageCrop" />, imagePan: <span tal:omit-tag="" tal:content="item/galleryImagePan" />, imagePosition: '<span tal:omit-tag="" tal:content="item/galleryImagePosition" />' + }); + + Galleria.ready(function() { + galleriaio_loadNext(); + }); + }); + </script> + </div> + </div> + <span tal:omit-tag="" tal:content="structure item/textAfter" /> + <span tal:omit-tag="" metal:use-macro="functions" tal:define="item item; from ''" /> + </div> + </article> + <span tal:omit-tag="" metal:use-macro="formComments" tal:define="item item" /> + <span tal:omit-tag="" metal:use-macro="comments" tal:define="item item" /> + </div> + </div> + </span> + </div> +</div> + +<div class="functions" metal:define-macro="functions"> + <span tal:omit-tag="" tal:condition="php:count(item.documents)"> + <h4 tal:content="php: __T('Insights')"></h4> + <ul class="insights clearfix" tal:condition="item/documents" > + <span tal:omit-tag="" tal:repeat="subItem item/documents"> + <li tal:condition="subItem/documentUrl"><a tal:attributes="href subItem/documentUrl" tal:content="subItem/text"></a></li> + </span> + </ul> + </span> + <div class="from" tal:condition="from"><span>FROM:</span> <span tal:omit-tag="" tal:content="from" /></div> + <div class="actions clearfix"> + <ul class="sx" tal:condition="item/commentsEnabled"> + <li tal:condition="item/externalLink"><a tal:attributes="href item/externalLink" target="_blank"><i class="fa fa-external-link"></i></a></li> + <li tal:condition="item/numComments"><i class="fa fa-comment"></i><a tal:attributes="href php: '#comments_' . item.hash"> <span tal:omit-tag="" tal:content="item/numComments" /> comments</a></li> + <li><i class="fa fa-pencil"></i><a class="js-writeComment" href="" tal:content="php: __T('Write comment')"></a></li> + </ul> + + <ul class="dx"> + <li><a tal:attributes="href item/urlPermalink">permalink</a></li> + <li><a target="_blank" tal:attributes="href item/urlFacebook"><i class="fa fa-facebook"></i></a></li> + <li><a target="_blank" tal:attributes="href item/urlTwitter"><i class="fa fa-twitter"></i> </a></li> + </ul> + + </div> +</div> + +<article class="item-box comment js-comments with-angle-icon" metal:define-macro="comments" tal:condition="item/numComments"> + <a tal:attributes="name php: 'comments_' . item.hash"></a> + <span class="arrow-big"></span> + + <div class="content-box-item"> + <h4 class="tipe-box">Comments</h4> + <span tal:omit-tag="" tal:repeat="subItem item/comments"> + <article class="item-comment" tal:condition="php: repeat.subItem.number == 1"> + <h2 class="title" tal:content="subItem/authorName"></h2> + <div tal:content="structure subItem/text"></div> + </article> + </span> + <span tal:condition="php: item.comments.count() > 1"> + <div class="archive-link"> + <a href="" class="js-commentsMoreLink">show more comments</a> + </div> + <div style="display:none;" class="js-commentsMore"> + <span tal:omit-tag="" tal:repeat="subItem item/comments"> + <article class="item-comment" tal:condition="php: repeat.subItem.number > 1"> + <h2 class="title" tal:content="subItem/authorName"></h2> + <div tal:content="structure subItem/text"></div> + </article> + </span> + </div> + </span> + </div> +</article> + +<article class="item-box comment js-formComment" style="display: none" metal:define-macro="formComments"> + <span class="arrow-big"></span> + + <form action="" method="POST"> + <input type="hidden" name="hash" tal:attributes="value item/hash"/> + <input type="hidden" name="action" value="PostComment"/> + <p><label><span>Name</span> + <input type="text" value="" id="authorName" name="authorName"/> + </label> + </p> + <p> + <label><span>Email</span> + <input type="text" value="" id="authorEmail" name="authorEmail"/> + </label> + </p> + <p> + <label><span>Comment text</span> + <textarea name="text" id="text"></textarea> + </label> + </p> + <p class="align-center"> + <input type="submit" value="Post"/> + <input type="reset" value="Cancel" class="js-formCommentCancel"/> + </p> + </form> +</article> diff --git a/src/static/org_glizy/assets/js/Glizy.js b/src/static/org_glizy/assets/js/Glizy.js new file mode 100644 index 0000000..54ce264 --- /dev/null +++ b/src/static/org_glizy/assets/js/Glizy.js @@ -0,0 +1,295 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +var tinyMCE = undefined; +var Glizy = new Object(); +Glizy = { + Onload: new Array(), + Onunload: new Array(), + Onbeforeunload: new Array(), + windowsList: new Array(), + slideShowSpeed: 20, + + start : function() + { + var oldonload = window.onload; + var oldunonload = window.onunload; + var onbeforeunload = window.onbeforeunload; + + window.onload = function () + { + if (typeof oldonload == 'function') + { + oldonload(); + } + for (var i=0;i<Glizy.Onload.length;i++) + { + eval(Glizy.Onload[i]); + } + } + + window.onunload = function () + { + if (typeof oldunonload == 'function') + { + oldunonload(); + } + for (var i=0;i<Glizy.Onunload.length;i++) + { + eval(Glizy.Onunload[i]); + } + } + + window.onbeforeunload = function () + { + if (typeof oldunonload == 'function') + { + onbeforeunload(); + } + for (var i=0;i<Glizy.Onbeforeunload.length;i++) + { + eval(Glizy.Onbeforeunload[i]); + } + } + }, + + addEvent: function (theType, theEvent) + { + if (theType=="onload") + Glizy.Onload.push(theEvent); + else if (theType=="onunload") + Glizy.Onunload.push(theEvent); + else if (theType=="onbeforeunload") + Glizy.Onbeforeunload.push(theEvent); + }, + + hideMessage: function(box) + { + if (!box) box = 'message-box' + var el = typeof( box ) == "string" ? Glizy.$(box) : box; + if (el.innerHTML!='') + { + el.innerHTML = ''; + } + }, + + showWarningMessage: function(text, messages, box) + { + if (!box) box = 'message-box' + var html = ''; + if (messages.length) + { + html = '<div class="message error">'; + html += '<p><strong>'+GlizyLocale.WARNING+'</strong> '+text+'</p>'; + html += '<ul><li>'+messages.join('</li><li>')+'</li></ul></div>'; + } + var el = typeof( box ) == "string" ? Glizy.$(box) : box; + if (el) + { + el.innerHTML = html; + if (document.documentElement && document.documentElement.scrollTop) + document.documentElement.scrollTop = 0; + else if (document.body) + document.body.scrollTop = 0; + } + }, + + showSuccessMessage: function(messages) + { + box = 'message-box' + html = '<div class="message success">'; + html += '<p><strong>'+GlizyLocale.SUCCESS+'</strong> '+messages+'</p>'; + html += '</div>'; + var el = Glizy.$(box); + if (el) + { + el.innerHTML = html; + if (document.documentElement && document.documentElement.scrollTop) + document.documentElement.scrollTop = 0; + else if (document.body) + document.body.scrollTop = 0; + } + }, + + validateForm: function(elValue, elName, elType, message) + { + elValue = unescape(elValue); + var resultState = true; + switch (elType) { + case 'date': + resultState = elValue!=''; + break; + case 'text': + case 'longtext': + case 'editableSelect': + //var regExp = new RegExp("([a-zA-Z\ ]{3,})"); + //resultState = regExp.test(elValue); + resultState = elValue!=''; + break; + case 'select': + case 'multipleselect': + resultState = elValue!=''; + break; + case 'colorPicker': + var regExp = new RegExp("^(#){1}([a-fA-F0-9]){6}$"); + resultState = regExp.test(elValue); + break; + } + //alert("validateForm "+elName+" "+(!resultState ? (!message ? message : elName) : '')) + return !resultState ? (!message ? message : elName) : ''; + }, + + tableruler: function() + { + if (document.getElementById && document.createTextNode) + { + var tables=document.getElementsByTagName("table"); + for (var i=0;i<tables.length;i++) + { + if(tables[i].className=="list") + { + var trs=tables[i].getElementsByTagName("tr"); + for(var j=0;j<trs.length;j++) + { + if(trs[j].parentNode.nodeName=="TBODY" && trs[j].parentNode.nodeName!="TFOOT" && trs[j].className!="labels") + { + trs[j].oldClass = trs[j].className; + trs[j].resetClass =function(){this.className=this.oldClass;return false} + trs[j].onmouseover=function(){ + var nodes = this.parentNode.childNodes; + for ( var i=0; i < nodes.length; i++ ) + { + if ( nodes[i] != this && nodes[i].resetClass ) nodes[i].resetClass(); + } + this.className="ruled";return false + } + trs[j].onmouseout=function(){this.resetClass()} + } + } + } + } + } + }, + + tablerulerReset: function( element ) + { + if (document.getElementById && document.createTextNode) + { + var nodes = element.parentNode.childNodes; + for ( var i=0; i < nodes.length; i++ ) + { + nodes[i].className = i % 2? "odd" : "even"; + } + Glizy.tableruler(); + } + }, + + selectAllCheckbox: function(el, name) + { + var actionFrm = el.form; + var checks = actionFrm.elements[name]; + if ( !el.checked ) + { + el.checked = false; + } + //el.checked = !el.checked; + var checkValue = el.checked; + if (checks.length!=undefined) + { + for (counter = 0; counter < checks.length; counter++) + checks[counter].checked = checkValue; + } + else + checks.checked = checkValue; + }, + + + + openWindow: function(url,wnd_name,wnd_props) + { + var w = window.open(url,wnd_name,wnd_props); + Glizy.windowsList.push(w); + return w; + }, + + closeWindows: function() + { + for(var i=0; i<Glizy.windowsList.length; i++) + { + Glizy.windowsList[i].close(); + } + Glizy.windowsList = new Array(); + }, + + previewImage: function(id) + { + Glizy.closeWindows(); + Glizy.openWindow("imagePreview.php?id="+id,"preview","width=100,height=100,menubar=false,alwaysRaised=true,copyhistory=false,resize=false"); + }, + + externalLinks: function() + { + // from SitePoint article + // http://www.sitepoint.com/article/standards-compliant-world + if (!document.getElementsByTagName) return; + var anchors = document.getElementsByTagName("a"); + for (var i=0; i<anchors.length; i++) { + var anchor = anchors[i]; + if (anchor.getAttribute("href") && anchor.getAttribute("rel") == "external") anchor.target = "_blank"; + } + }, + zoomViewer: null, + openZoom: function( id ) + { + var zoomContainer = document.getElementById('zoomContainer'); + if ( Glizy.zoomViewer == null ) + { + SeadragonConfig.imgPath = "static/"; + Glizy.zoomViewer = new Seadragon.Viewer("zoomContainer"); + Glizy.zoomViewer.setFullPage( true ); + Glizy.zoomViewer.onFullPage = function() + { + Glizy.zoomViewer.close(); + zoomContainer.style.display = "none"; + } + } + var url = "zoom.php?id="+id; + Seadragon.Utils.makeAjaxRequest(url, function(xhr) { + zoomContainer.style.display = "block"; + Glizy.zoomViewer.setFullPage( true ); + Glizy.zoomViewer.openDzi("cache/zoom_"+id+".xml"); + }); + + }, + + $: function() { + var elements = new Array(); + + for (var i = 0; i < arguments.length; i++) { + var element = arguments[i]; + if (typeof element == 'string') + element = document.getElementById(element); + + if (arguments.length == 1) + return element; + + elements.push(element); + } + + return elements; + } + +}; + +Glizy.tinyMCE_plugins = ''; +Glizy.tinyMCE_pluginsNames = ''; + +var GlizyLocale = new Object(); +Glizy.start(); +Glizy.addEvent('onload', 'Glizy.tableruler()'); +Glizy.addEvent('onload', 'Glizy.externalLinks()'); diff --git a/src/static/org_glizy/assets/js/Glizy_tiny_mce.js b/src/static/org_glizy/assets/js/Glizy_tiny_mce.js new file mode 100644 index 0000000..847189d --- /dev/null +++ b/src/static/org_glizy/assets/js/Glizy_tiny_mce.js @@ -0,0 +1,301 @@ +/* SVN FILE: $Id$ */ + +/** + * TinyMCE configuration file. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2006 Daniele Ugoletti <daniele@ugoletti.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + * + * @copyright Copyright (c) 2005, 2006 Daniele Ugoletti + * @link http://www.glizy.org Glizy Project + * @license http://www.gnu.org/copyleft/lesser.html GNU LESSER GENERAL PUBLIC LICENSE + * @package glizy + * @subpackage javascript + * @author Daniele Ugoletti <daniele@ugoletti.com> + * @category javascript + * @since Glizy v 0.01 + * @version $Rev$ + * @modifiedby $LastChangedBy$ + * @lastmodified $Date$ + */ + +if ( Glizy.tinyMCE_btn3 != "" && Glizy.tinyMCE_pluginsNames != "" ) +{ + Glizy.tinyMCE_btn3 = Glizy.tinyMCE_btn3 != "" ? Glizy.tinyMCE_btn3 + "," + Glizy.tinyMCE_pluginsNames : Glizy.tinyMCE_pluginsNames; +} + +Glizy.tinyMCE_options = { + theme : "advanced", + mode : "exact", + elements : "", + language: GlizyLocale.LANGUAGE, + dialog_type: "modal", + paste_remove_spans: true, + paste_remove_styles: true, + paste_strip_class_attributes: "all", + remove_linebreaks: true, + remove_script_host: false, + tab_focus : ':prev,:next', + + content_css : "../admin/MW/templates/assets/css/tinyMCE.css", + + plugins : Glizy.tinyMCE_plugins, + theme_advanced_buttons1 : Glizy.tinyMCE_btn1, + theme_advanced_buttons2 : Glizy.tinyMCE_btn2, + theme_advanced_buttons3 : Glizy.tinyMCE_btn3, + theme_advanced_resize_horizontal : false, + theme_advanced_resizing : true, + theme_advanced_toolbar_location : "top", + theme_advanced_toolbar_align : "left", + theme_advanced_path_location : "bottom", + + inline_styles : true, + verify_html : true, + extended_valid_elements : "a[name|href|title|style|class|rel|rev|tabindex|accesskey]", + valid_elements : "" ++"a[accesskey|charset|class|coords|dir<ltr?rtl|href|hreflang|id|lang|name" + +"|onblur|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|rel|rev" + +"|shape<circle?default?poly?rect|style|tabindex|title|target|type]," ++"abbr[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"acronym[class|dir<ltr?rtl|id|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"address[class|align|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"area[accesskey|alt|class|coords|dir<ltr?rtl|href|id|lang|nohref<nohref" + +"|onblur|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup" + +"|shape<circle?default?poly?rect|style|tabindex|title|target]," ++"bdo[class|dir<ltr?rtl|id|lang|style|title]," ++"big[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"blockquote[cite|class|dir<ltr?rtl|id|lang|onclick|ondblclick" + +"|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout" + +"|onmouseover|onmouseup|style|title]," ++"br[class|clear<all?left?none?right|id|style|title]," ++"button[accesskey|class|dir<ltr?rtl|disabled<disabled|id|lang|name|onblur" + +"|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|style|tabindex|title|type" + +"|value]," ++"caption[align<bottom?left?right?top|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"cite[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"col[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl|id" + +"|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|span|style|title" + +"|valign<baseline?bottom?middle?top|width]," ++"colgroup[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl" + +"|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|span|style|title" + +"|valign<baseline?bottom?middle?top|width]," ++"dd[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title]," ++"del[cite|class|datetime|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"dfn[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"dir[class|compact<compact|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"div[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"dl[class|compact<compact|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"dt[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title]," ++"em/i[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"embed[width|height|name|flashvars|src|bgcolor|align|play|loop|quality|allowscriptaccess|allowfullscreen|type|pluginspage]," ++"fieldset[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"font[class|color|dir<ltr?rtl|face|id|lang|size|style|title]," ++"form[accept|accept-charset|action|class|dir<ltr?rtl|enctype|id|lang" + +"|method<get?post|name|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onreset|onsubmit" + +"|style|title|target]," ++"frame[class|frameborder|id|longdesc|marginheight|marginwidth|name" + +"|noresize<noresize|scrolling<auto?no?yes|src|style|title]," ++"frameset[class|cols|id|onload|onunload|rows|style|title]," ++"h1[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"h2[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"h3[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"h4[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"h5[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"h6[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"head[dir<ltr?rtl|lang|profile]," ++"hr[align<center?left?right|class|dir<ltr?rtl|id|lang|noshade<noshade|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|size|style|title|width]," ++"html[dir<ltr?rtl|lang|version]," ++"iframe[align<bottom?left?middle?right?top|class|frameborder|height|id" + +"|longdesc|marginheight|marginwidth|name|scrolling<auto?no?yes|src|style" + +"|title|width]," ++"img[align<bottom?left?middle?right?top|alt|border|class|dir<ltr?rtl|height" + +"|hspace|id|ismap<ismap|lang|longdesc|name|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|src|style|title|usemap|vspace|width]," ++"input[accept|accesskey|align<bottom?left?middle?right?top|alt" + +"|checked<checked|class|dir<ltr?rtl|disabled<disabled|id|ismap<ismap|lang" + +"|maxlength|name|onblur|onclick|ondblclick|onfocus|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onselect" + +"|readonly<readonly|size|src|style|tabindex|title" + +"|type<button?checkbox?file?hidden?image?password?radio?reset?submit?text" + +"|usemap|value]," ++"ins[cite|class|datetime|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"isindex[class|dir<ltr?rtl|id|lang|prompt|style|title]," ++"kbd[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"label[accesskey|class|dir<ltr?rtl|for|id|lang|onblur|onclick|ondblclick" + +"|onfocus|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout" + +"|onmouseover|onmouseup|style|title]," ++"legend[align<bottom?left?right?top|accesskey|class|dir<ltr?rtl|id|lang" + +"|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"li[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title|type" + +"|value]," ++"link[charset|class|dir<ltr?rtl|href|hreflang|id|lang|media|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|rel|rev|style|title|target|type]," ++"map[class|dir<ltr?rtl|id|lang|name|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"menu[class|compact<compact|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"meta[content|dir<ltr?rtl|http-equiv|lang|name|scheme]," ++"noframes[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"noscript[class|dir<ltr?rtl|id|lang|style|title]," ++"object[align<bottom?left?middle?right?top|archive|border|class|classid" + +"|codebase|codetype|data|declare|dir<ltr?rtl|height|hspace|id|lang|name" + +"|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|standby|style|tabindex|title|type|usemap" + +"|vspace|width]," ++"ol[class|compact<compact|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|start|style|title|type]," ++"optgroup[class|dir<ltr?rtl|disabled<disabled|id|label|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"option[class|dir<ltr?rtl|disabled<disabled|id|label|lang|onclick|ondblclick" + +"|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout" + +"|onmouseover|onmouseup|selected<selected|style|title|value]," ++"p[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|style|title]," ++"param[id|name|type|value|valuetype<DATA?OBJECT?REF]," ++"pre/listing/plaintext/xmp[align|class|dir<ltr?rtl|id|lang|onclick|ondblclick" + +"|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout" + +"|onmouseover|onmouseup|style|title|width]," ++"q[cite|class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"s[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title]," ++"samp[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"script[charset|defer|language|src|type]," ++"select[class|dir<ltr?rtl|disabled<disabled|id|lang|multiple<multiple|name" + +"|onblur|onchange|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|size|style" + +"|tabindex|title]," ++"small[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"span[align<center?justify?left?right|class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"strike[class|class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title]," ++"strong/b[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"style[dir<ltr?rtl|lang|media|title|type]," ++"sub[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"sup[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]," ++"table[align<center?left?right|bgcolor|border|cellpadding|cellspacing|class" + +"|dir<ltr?rtl|frame|height|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|rules" + +"|style|summary|title|width]," ++"tbody[align<center?char?justify?left?right|char|class|charoff|dir<ltr?rtl|id" + +"|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|style|title" + +"|valign<baseline?bottom?middle?top]," ++"td[abbr|align<center?char?justify?left?right|axis|bgcolor|char|charoff|class" + +"|colspan|dir<ltr?rtl|headers|height|id|lang|nowrap<nowrap|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|rowspan|scope<col?colgroup?row?rowgroup" + +"|style|title|valign<baseline?bottom?middle?top|width]," ++"textarea[accesskey|class|cols|dir<ltr?rtl|disabled<disabled|id|lang|name" + +"|onblur|onclick|ondblclick|onfocus|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|onselect" + +"|readonly<readonly|rows|style|tabindex|title]," ++"tfoot[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl|id" + +"|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|style|title" + +"|valign<baseline?bottom?middle?top]," ++"th[abbr|align<center?char?justify?left?right|axis|bgcolor|char|charoff|class" + +"|colspan|dir<ltr?rtl|headers|height|id|lang|nowrap<nowrap|onclick" + +"|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown|onmousemove" + +"|onmouseout|onmouseover|onmouseup|rowspan|scope<col?colgroup?row?rowgroup" + +"|style|title|valign<baseline?bottom?middle?top|width]," ++"thead[align<center?char?justify?left?right|char|charoff|class|dir<ltr?rtl|id" + +"|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup|onmousedown" + +"|onmousemove|onmouseout|onmouseover|onmouseup|style|title" + +"|valign<baseline?bottom?middle?top]," ++"title[dir<ltr?rtl|lang]," ++"tr[abbr|align<center?char?justify?left?right|bgcolor|char|charoff|class" + +"|rowspan|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title|valign<baseline?bottom?middle?top]," ++"tt[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title]," ++"u[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress|onkeyup" + +"|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style|title]," ++"ul[class|compact<compact|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown" + +"|onkeypress|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover" + +"|onmouseup|style|title|type]," ++"var[class|dir<ltr?rtl|id|lang|onclick|ondblclick|onkeydown|onkeypress" + +"|onkeyup|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|style" + +"|title]" + }; \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/locale/de.js b/src/static/org_glizy/assets/js/locale/de.js new file mode 100644 index 0000000..0ef4855 --- /dev/null +++ b/src/static/org_glizy/assets/js/locale/de.js @@ -0,0 +1,33 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +var GlizyLocale = new Object(); +GlizyLocale = { + LANGUAGE: 'en', + WARNING: 'Achtung', + REQUIREDFIELDS: 'Diese Felder sind notwendig:', + SUCCESS: '', + SUCCESSMSG: 'Gespeichert!', + DATE_FORMAT: '%Y-%m-%d', + DATETIME_FORMAT: '%Y-%m-%d %H:%M:00', + NOVALIDFIELD: 'Die Eingabe im Feld "%s" ist nicht gültig.', + FIRSTNAME: 'First Name', + LASTNAME: 'Last Name', + EMAIL: 'email', + PASSWORD: 'password', + PRIVACY: 'Permission to use personal data is required.' +}; + +var SeadragonConfig = {}; +SeadragonConfig.Loading = "Loading..."; +SeadragonConfig.Home = "Fit Image"; +SeadragonConfig.FullPage = "Exit"; +SeadragonConfig.ZoomIn = "Zoom In"; +SeadragonConfig.ZoomOut = "Zoom Out"; + +var pageTexts = {ins: 'Einfügen', add: 'Neuen Eintrag einfügen', addFirst: 'Neuen Eintrag am Anfang einfügen', addLast: 'Neuen Eintrag am Ende einfügen', addBefore: 'Neuen Eintrag vor diesem einfügen', moveUp: 'Nach oben verschieben', moveDn: 'Nach unten verschieben', edit: 'Bearbeiten', del: 'Löschen', confirmDel: 'Wollen Sie diesen Eintrag wirklich löschen?', newImg: 'Wählen Sie ein Bild aus', newMedia: 'Wählen Sie ein Medien-Datei aus ', color: 'Wählen Sie eine Farbe aus', cancel: 'Abbrechen', ok: 'OK', save: 'Speichern', confirmSave: 'Änderungen speichern?', noSave: 'keine Änderungen vorhanden', searchOn: 'Suche in', goSearch: 'Suche starten', selItems: 'Suchergebnis', noResult: 'Kein Suchergebnis', include: 'Hinzufügen', reset: 'Neue Suche', preview: 'Vorschau' }; \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/locale/en.js b/src/static/org_glizy/assets/js/locale/en.js new file mode 100644 index 0000000..bbe7ad1 --- /dev/null +++ b/src/static/org_glizy/assets/js/locale/en.js @@ -0,0 +1,34 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +var GlizyLocale = new Object(); +GlizyLocale = { + LANGUAGE: 'en', + WARNING: 'Warning', + REQUIREDFIELDS: 'These fields are required:', + SUCCESS: '', + SUCCESSMSG: 'Saved!', + DATE_FORMAT: '%Y-%m-%d', + DATETIME_FORMAT: '%Y-%m-%d %H:%M:00', + NOVALIDFIELD: 'The field "%s" is not valid.', + FIRSTNAME: 'First Name', + LASTNAME: 'Last Name', + EMAIL: 'email', + PASSWORD: 'password', + PRIVACY: 'Permission to use personal data is required.' +}; + +var SeadragonConfig = {}; +SeadragonConfig.Loading = "Loading..."; +SeadragonConfig.Home = "Fit Image"; +SeadragonConfig.FullPage = "Exit"; +SeadragonConfig.ZoomIn = "Zoom In"; +SeadragonConfig.ZoomOut = "Zoom Out"; + +var pageTexts = {ins: 'Insert', add: 'Add new record', addFirst: 'Add new record before the first one', addLast: 'Add new record after the last one', addBefore: 'Add new record before this one', moveUp: 'Move up', moveDn: 'Move down', edit: 'Modify', del: 'Delete', confirmDel: 'Are you sure to delete this record?', newImg: 'Pick up an image', newMedia: 'Pick up a media file ', color: 'Pick up a color', cancel: 'Cancel', ok: 'OK', save: 'Save', confirmSave: 'Save updates?', noSave: 'Nothing to save!', searchOn: 'Search in', goSearch: 'Start search', selItems: 'selected items', noResult: 'no search result', include: 'Add', reset: 'Restart', preview: 'Preview' }; + diff --git a/src/static/org_glizy/assets/js/locale/fr.js b/src/static/org_glizy/assets/js/locale/fr.js new file mode 100644 index 0000000..073d7e1 --- /dev/null +++ b/src/static/org_glizy/assets/js/locale/fr.js @@ -0,0 +1,33 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +var GlizyLocale = new Object(); +GlizyLocale = { + LANGUAGE: 'en', + WARNING: 'Attention', + REQUIREDFIELDS: 'Ces champs sont indispensable:', + SUCCESS: '', + SUCCESSMSG: 'Sauvegardé!', + DATE_FORMAT: '%Y-%m-%d', + DATETIME_FORMAT: '%Y-%m-%d %H:%M:00', + NOVALIDFIELD: 'Le champs "%s" n\'est pas valide', + FIRSTNAME: 'First Name', + LASTNAME: 'Last Name', + EMAIL: 'email', + PASSWORD: 'password', + PRIVACY: 'Permission to use personal data is required.' +}; + +var SeadragonConfig = {}; +SeadragonConfig.Loading = "Loading..."; +SeadragonConfig.Home = "Fit Image"; +SeadragonConfig.FullPage = "Exit"; +SeadragonConfig.ZoomIn = "Zoom In"; +SeadragonConfig.ZoomOut = "Zoom Out"; + +var pageTexts = {ins: 'Insérer', add: 'Ajouter un nouvel enregistrement', addFirst: 'Ajouter un nouvel enregistrement avant le premier', addLast: 'Ajouter un nouvel enregistrement avant le dernier', addBefore: 'Ajouter un nouvel enregistrement avant celui-ci', moveUp: 'Déplacer vers le haut', moveDn: 'Déplacer vers le bas', edit: 'Modifier', del: 'Supprimer', confirmDel: 'Etes-vous sur de vouloir supprimer cet enregistrement?', newImg: 'Choisir une image', newMedia: 'Choisir un fichier média', color: 'Choisir une couleur', cancel: 'Annuler', ok: 'OK', save: 'Sauvegarder', confirmSave: 'Sauvergarder les mises à jour?', noSave: 'Rien à sauvegarder!', searchOn: 'Rechercher dans', goSearch: 'Commencer la recherche', selItems: 'articles sélectionnés', noResult: 'Aucun résultat', include: 'Ajouter', reset: 'Recommencer', preview: 'Aperçu' }; \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/locale/it.js b/src/static/org_glizy/assets/js/locale/it.js new file mode 100644 index 0000000..97df6cc --- /dev/null +++ b/src/static/org_glizy/assets/js/locale/it.js @@ -0,0 +1,34 @@ +/** + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2011 Daniele Ugoletti <daniele.ugoletti@glizy.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + */ + +var GlizyLocale = new Object(); +GlizyLocale = { + LANGUAGE: 'it', + WARNING: 'Attenzione', + REQUIREDFIELDS: 'I seguenti campi sono richiesti', + SUCCESS: '', + SUCCESSMSG: 'Salvataggio avvenuto', + DATE_FORMAT: '%d/%m/%Y', + DATETIME_FORMAT: '%d/%m/%Y %H:%M:00', + NOVALIDFIELD: 'Il campo "%s" non e\' valido.', + FIRSTNAME: 'Nome', + LASTNAME: 'Cognome', + EMAIL: 'email', + PASSWORD: 'password', + PRIVACY: 'E\' necessario acconsentire al trattamento dei dati personali.' +}; + +var SeadragonConfig = {}; +SeadragonConfig.Loading = "Caricamento..."; +SeadragonConfig.Home = "Visualizza tutta l'immagine"; +SeadragonConfig.FullPage = "Esci"; +SeadragonConfig.ZoomIn = "Ingrandisci"; +SeadragonConfig.ZoomOut = "Riduci"; + + +var pageTexts = {ins: 'Inserisci', add: 'Aggiungi nuovo record', addFirst: 'Aggiungi nuovo record all\'inizio', addLast: 'Aggiungi nuovo record alla fine', addBefore: 'Aggiungi un record prima di questo', moveUp: 'Sposta in alto', moveDn: 'Sposta in basso', edit: 'Modifica', del: 'Rimuovi', confirmDel: 'Siete sicuri di voler cancellare il record selezionato ?', newImg: 'scegli una nuova immagine', newMedia: 'scegli un nuovo media', color: 'scegli un colore', cancel: 'Annulla', ok: 'OK', save: 'Salva', confirmSave: 'vuoi salvare le modifiche?', noSave: 'niente da salvare!', searchOn: 'Cerca in', goSearch: 'Esegui ricerca', selItems: 'item selezionati', noResult: 'nessun risultato coerente con i criteri di ricerca', include: 'Inserisci', reset: 'ricomincia', preview: 'anteprima' }; diff --git a/src/static/org_glizy/assets/js/tiny_mce/langs/de.js b/src/static/org_glizy/assets/js/tiny_mce/langs/de.js new file mode 100644 index 0000000..1494406 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/langs/de.js @@ -0,0 +1 @@ +tinyMCE.addI18n({de:{common:{"more_colors":"Weitere Farben","invalid_data":"Fehler: Sie haben ung\u00fcltige Werte eingegeben (rot markiert).","popup_blocked":"Leider hat Ihr Popup-Blocker ein Fenster unterbunden, das f\u00fcr den Betrieb dieses Programms n\u00f6tig ist. Bitte deaktivieren Sie den Popup-Blocker f\u00fcr diese Seite.","clipboard_no_support":"Wird derzeit in Ihrem Browser nicht unterst\u00fctzt. Bitte benutzen Sie stattdessen die Tastenk\u00fcrzel.","clipboard_msg":"Kopieren, Ausschneiden und Einf\u00fcgen sind im Mozilla Firefox nicht m\u00f6glich.\nM\u00f6chten Sie mehr \u00fcber dieses Problem erfahren?","not_set":"- unbestimmt -","class_name":"CSS-Klasse",browse:"Durchsuchen",close:"Schlie\u00dfen",cancel:"Abbrechen",update:"Aktualisieren",insert:"Einf\u00fcgen",apply:"\u00dcbernehmen","edit_confirm":"M\u00f6chten Sie diesen Text jetzt bearbeiten?","invalid_data_number":"{#field} muss eine Zahl sein","invalid_data_min":"{#field} muss eine Zahl gr\u00f6\u00dfer als {#min} sein","invalid_data_size":"{#field} muss eine Zahl oder ein Prozentwert sein",value:"(Wert)"},contextmenu:{full:"Blocksatz",right:"Rechtsb\u00fcndig",center:"Zentriert",left:"Linksb\u00fcndig",align:"Ausrichtung"},insertdatetime:{"day_short":"So,Mo,Di,Mi,Do,Fr,Sa,So","day_long":"Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag,Sonntag","months_short":"Jan,Feb,M\u00e4r,Apr,Mai,Juni,Juli,Aug,Sept,Okt,Nov,Dez","months_long":"Januar,Februar,M\u00e4rz,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember","inserttime_desc":"Zeit einf\u00fcgen","insertdate_desc":"Datum einf\u00fcgen","time_fmt":"%H:%M:%S","date_fmt":"%d.%m.%Y"},print:{"print_desc":"Drucken"},preview:{"preview_desc":"Vorschau"},directionality:{"rtl_desc":"Schrift von rechts nach links","ltr_desc":"Schrift von links nach rechts"},layer:{content:"Neue Ebene...","absolute_desc":"Absolute Positionierung","backward_desc":"Nach hinten legen","forward_desc":"Nach vorne holen","insertlayer_desc":"Neue Ebene einf\u00fcgen"},save:{"save_desc":"Speichern","cancel_desc":"Alle \u00c4nderungen verwerfen"},nonbreaking:{"nonbreaking_desc":"Gesch\u00fctztes Leerzeichen einf\u00fcgen"},iespell:{download:"ieSpell konnte nicht gefunden werden. Wollen Sie es installieren?","iespell_desc":"Rechtschreibpr\u00fcfung"},advhr:{"advhr_desc":"Trennlinie","delta_height":"","delta_width":""},emotions:{"emotions_desc":"Smilies","delta_height":"","delta_width":""},searchreplace:{"replace_desc":"Suchen/Ersetzen","search_desc":"Suchen","delta_width":"","delta_height":""},advimage:{"image_desc":"Bild einf\u00fcgen/ver\u00e4ndern","delta_width":"","delta_height":""},advlink:{"link_desc":"Link einf\u00fcgen/ver\u00e4ndern","delta_height":"","delta_width":""},xhtmlxtras:{"attribs_desc":"Attribute einf\u00fcgen/bearbeiten","ins_desc":"Eingef\u00fcgter Text","del_desc":"Entfernter Text","acronym_desc":"Akronym","abbr_desc":"Abk\u00fcrzung","cite_desc":"Quellenangabe","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"CSS-Styles bearbeiten","delta_height":"","delta_width":""},paste:{"plaintext_mode":"Einf\u00fcgemodus ist nun \"Nur Text\". Erneut klicken stellt den Normalmodus wieder her.","plaintext_mode_sticky":"Einf\u00fcgemodus ist nun \"Nur Text\". Erneut klicken (oder das Einf\u00fcgen aus der Zwischenablage) stellt den Normalmodus wieder her.","selectall_desc":"Alles ausw\u00e4hlen","paste_word_desc":"Mit Formatierungen (aus Word) einf\u00fcgen","paste_text_desc":"Als einfachen Text einf\u00fcgen"},"paste_dlg":{"word_title":"Dr\u00fccken Sie auf Ihrer Tastatur Strg+V, um den Text einzuf\u00fcgen.","text_linebreaks":"Zeilenumbr\u00fcche beibehalten","text_title":"Dr\u00fccken Sie auf Ihrer Tastatur Strg+V, um den Text einzuf\u00fcgen."},table:{"cellprops_delta_width":"150",cell:"Zelle",col:"Spalte",row:"Zeile",del:"Tabelle l\u00f6schen","copy_row_desc":"Zeile kopieren","cut_row_desc":"Zeile ausschneiden","paste_row_after_desc":"Zeile unterhalb aus der Zwischenablage einf\u00fcgen","paste_row_before_desc":"Zeile oberhalb aus der Zwischenablage einf\u00fcgen","props_desc":"Eigenschaften der Tabelle","cell_desc":"Eigenschaften der Zelle","row_desc":"Eigenschaften der Zeile","merge_cells_desc":"Zellen verbinden","split_cells_desc":"Verbundene Zellen trennen","delete_col_desc":"Spalte l\u00f6schen","col_after_desc":"Spalte rechts einf\u00fcgen","col_before_desc":"Spalte links einf\u00fcgen","delete_row_desc":"Zeile l\u00f6schen","row_after_desc":"Zeile unterhalb einf\u00fcgen","row_before_desc":"Zeile oberhalb einf\u00fcgen",desc:"Tabelle erstellen/bearbeiten","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"Wenn Sie den Inhalt wiederherstellen, gehen die aktuellen Daten im Editor verloren.\n\nSind sie sicher, dass Sie den Inhalt wiederherstellen m\u00f6chten?","restore_content":"Automatisch gespeicherten Inhalt wiederherstellen.","unload_msg":"Ihre \u00c4nderungen werden verloren gehen, wenn Sie die Seite verlassen."},fullscreen:{desc:"Vollbildschirm"},media:{edit:"Multimediaeinbettung bearbeiten",desc:"Multimedia einbetten/bearbeiten","delta_height":"","delta_width":""},fullpage:{desc:"Dokument-Eigenschaften","delta_width":"","delta_height":""},template:{desc:"Inhalt aus Vorlage einf\u00fcgen"},visualchars:{desc:"Sichtbarkeit der Steuerzeichen an/aus"},spellchecker:{desc:"Rechtschreibpr\u00fcfung an/aus",menu:"Einstellungen der Rechtschreibpr\u00fcfung","ignore_word":"Wort ignorieren","ignore_words":"Alle ignorieren",langs:"Sprachen",wait:"Bitte warten...",sug:"Vorschl\u00e4ge","no_sug":"Keine Vorschl\u00e4ge","no_mpell":"Keine Rechtschreibfehler gefunden.","learn_word":"Zum W\u00f6rterbuch hinzuf\u00fcgen"},pagebreak:{desc:"Seitenumbruch einf\u00fcgen"},advlist:{types:"Typen",def:"Standard","lower_alpha":"a. b. c.","lower_greek":"1. 2. 3.","lower_roman":"i. ii. iii.","upper_alpha":"A. B. C.","upper_roman":"I. II. III.",circle:"Kreis",disc:"Punkt",square:"Quadrat"},colors:{"333300":"Dunkeloliv","993300":"Orange","000000":"Schwarz","003300":"Dunkelgr\u00fcn","003366":"Dunkles himmelblau","000080":"Marineblau","333399":"Indigoblau","333333":"Sehr dunkelgrau","800000":"Kastanienbraun",FF6600:"Orange","808000":"Oliv","008000":"Gr\u00fcn","008080":"Blaugr\u00fcn","0000FF":"Blau","666699":"Graublau","808080":"Grau",FF0000:"Rot",FF9900:"Bernsteinfarben","99CC00":"Gelbgr\u00fcn","339966":"Meergr\u00fcn","33CCCC":"T\u00fcrkis","3366FF":"K\u00f6nigsblau","800080":"Violett","999999":"Mittelgrau",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Gelb","00FF00":"Hellgr\u00fcn","00FFFF":"Aquamarinblau","00CCFF":"Himmelblau","993366":"Braun",C0C0C0:"Silber",FF99CC:"Rosa",FFCC99:"Pfirsichfarben",FFFF99:"Hellgelb",CCFFCC:"Blassgr\u00fcn",CCFFFF:"Blasst\u00fcrkis","99CCFF":"Helles himmelblau",CC99FF:"Pflaumenblau",FFFFFF:"Wei\u00df"},aria:{"rich_text_area":"Rich Text Bereich"},wordcount:{words:"W\u00f6rter: "}}}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/langs/en.js b/src/static/org_glizy/assets/js/tiny_mce/langs/en.js new file mode 100644 index 0000000..16d7a93 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/langs/en.js @@ -0,0 +1 @@ +tinyMCE.addI18n({en:{common:{"more_colors":"More Colors...","invalid_data":"Error: Invalid values entered, these are marked in red.","popup_blocked":"Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.","clipboard_no_support":"Currently not supported by your browser, use keyboard shortcuts instead.","clipboard_msg":"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?","not_set":"-- Not Set --","class_name":"Class",browse:"Browse",close:"Close",cancel:"Cancel",update:"Update",insert:"Insert",apply:"Apply","edit_confirm":"Do you want to use the WYSIWYG mode for this textarea?","invalid_data_number":"{#field} must be a number","invalid_data_min":"{#field} must be a number greater than {#min}","invalid_data_size":"{#field} must be a number or percentage",value:"(value)"},contextmenu:{full:"Full",right:"Right",center:"Center",left:"Left",align:"Alignment"},insertdatetime:{"day_short":"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun","day_long":"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday","months_short":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","months_long":"January,February,March,April,May,June,July,August,September,October,November,December","inserttime_desc":"Insert Time","insertdate_desc":"Insert Date","time_fmt":"%H:%M:%S","date_fmt":"%Y-%m-%d"},print:{"print_desc":"Print"},preview:{"preview_desc":"Preview"},directionality:{"rtl_desc":"Direction Right to Left","ltr_desc":"Direction Left to Right"},layer:{content:"New layer...","absolute_desc":"Toggle Absolute Positioning","backward_desc":"Move Backward","forward_desc":"Move Forward","insertlayer_desc":"Insert New Layer"},save:{"save_desc":"Save","cancel_desc":"Cancel All Changes"},nonbreaking:{"nonbreaking_desc":"Insert Non-Breaking Space Character"},iespell:{download:"ieSpell not detected. Do you want to install it now?","iespell_desc":"Check Spelling"},advhr:{"delta_height":"","delta_width":"","advhr_desc":"Insert Horizontal Line"},emotions:{"delta_height":"","delta_width":"","emotions_desc":"Emotions"},searchreplace:{"replace_desc":"Find/Replace","delta_width":"","delta_height":"","search_desc":"Find"},advimage:{"delta_width":"","image_desc":"Insert/Edit Image","delta_height":""},advlink:{"delta_height":"","delta_width":"","link_desc":"Insert/Edit Link"},xhtmlxtras:{"attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":"","attribs_desc":"Insert/Edit Attributes","ins_desc":"Insertion","del_desc":"Deletion","acronym_desc":"Acronym","abbr_desc":"Abbreviation","cite_desc":"Citation"},style:{"delta_height":"","delta_width":"",desc:"Edit CSS Style"},paste:{"plaintext_mode":"Paste is now in plain text mode. Click again to toggle back to regular paste mode.","plaintext_mode_sticky":"Paste is now in plain text mode. Click again to toggle back to regular paste mode. After you paste something you will be returned to regular paste mode.","selectall_desc":"Select All","paste_word_desc":"Paste from Word","paste_text_desc":"Paste as Plain Text"},"paste_dlg":{"word_title":"Use Ctrl+V on your keyboard to paste the text into the window.","text_linebreaks":"Keep Linebreaks","text_title":"Use Ctrl+V on your keyboard to paste the text into the window."},table:{"merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":"",cell:"Cell",col:"Column",row:"Row",del:"Delete Table","copy_row_desc":"Copy Table Row","cut_row_desc":"Cut Table Row","paste_row_after_desc":"Paste Table Row After","paste_row_before_desc":"Paste Table Row Before","props_desc":"Table Properties","cell_desc":"Table Cell Properties","row_desc":"Table Row Properties","merge_cells_desc":"Merge Table Cells","split_cells_desc":"Split Merged Table Cells","delete_col_desc":"Delete Column","col_after_desc":"Insert Column After","col_before_desc":"Insert Column Before","delete_row_desc":"Delete Row","row_after_desc":"Insert Row After","row_before_desc":"Insert Row Before",desc:"Insert/Edit Table"},autosave:{"warning_message":"If you restore the saved content, you will lose all the content that is currently in the editor.\n\nAre you sure you want to restore the saved content?","restore_content":"Restore auto-saved content.","unload_msg":"The changes you made will be lost if you navigate away from this page."},fullscreen:{desc:"Toggle Full Screen Mode"},media:{"delta_height":"","delta_width":"",edit:"Edit Embedded Media",desc:"Insert/Edit Embedded Media"},fullpage:{desc:"Document Properties","delta_width":"","delta_height":""},template:{desc:"Insert Predefined Template Content"},visualchars:{desc:"Show/Hide Visual Control Characters"},spellchecker:{desc:"Toggle Spell Checker",menu:"Spell Checker Settings","ignore_word":"Ignore Word","ignore_words":"Ignore All",langs:"Languages",wait:"Please wait...",sug:"Suggestions","no_sug":"No Suggestions","no_mpell":"No misspellings found.","learn_word":"Learn word"},pagebreak:{desc:"Insert Page Break for Printing"},advlist:{types:"Types",def:"Default","lower_alpha":"Lower Alpha","lower_greek":"Lower Greek","lower_roman":"Lower Roman","upper_alpha":"Upper Alpha","upper_roman":"Upper Roman",circle:"Circle",disc:"Disc",square:"Square"},colors:{"333300":"Dark olive","993300":"Burnt orange","000000":"Black","003300":"Dark green","003366":"Dark azure","000080":"Navy Blue","333399":"Indigo","333333":"Very dark gray","800000":"Maroon",FF6600:"Orange","808000":"Olive","008000":"Green","008080":"Teal","0000FF":"Blue","666699":"Grayish blue","808080":"Gray",FF0000:"Red",FF9900:"Amber","99CC00":"Yellow green","339966":"Sea green","33CCCC":"Turquoise","3366FF":"Royal blue","800080":"Purple","999999":"Medium gray",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Yellow","00FF00":"Lime","00FFFF":"Aqua","00CCFF":"Sky blue","993366":"Brown",C0C0C0:"Silver",FF99CC:"Pink",FFCC99:"Peach",FFFF99:"Light yellow",CCFFCC:"Pale green",CCFFFF:"Pale cyan","99CCFF":"Light sky blue",CC99FF:"Plum",FFFFFF:"White"},aria:{"rich_text_area":"Rich Text Area"},wordcount:{words:"Words:"}}}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/langs/fr.js b/src/static/org_glizy/assets/js/tiny_mce/langs/fr.js new file mode 100644 index 0000000..7042832 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/langs/fr.js @@ -0,0 +1 @@ +tinyMCE.addI18n({fr:{common:{"more_colors":"Plus de couleurs","invalid_data":"Erreur : saisie de valeurs incorrectes. Elles sont mises en \u00e9vidence en rouge.","popup_blocked":"D\u00e9sol\u00e9, nous avons d\u00e9tect\u00e9 que votre bloqueur de popup a bloqu\u00e9 une fen\u00eatre dont l\'application a besoin. Vous devez d\u00e9sactiver votre bloqueur de popup pour pouvoir utiliser cet outil.","clipboard_no_support":"Actuellement non support\u00e9 par votre navigateur.\n Veuillez utiliser les raccourcis clavier \u00e0 la place.","clipboard_msg":"Les fonctions Copier/Couper/Coller ne sont pas valables sur Mozilla et Firefox.\nSouhaitez-vous avoir plus d\'informations sur ce sujet ?","not_set":"-- non d\u00e9fini --","class_name":"Classe",browse:"parcourir",close:"Fermer",cancel:"Annuler",update:"Mettre \u00e0 jour",insert:"Ins\u00e9rer",apply:"Appliquer","edit_confirm":"Souhaitez-vous utiliser le mode WYSIWYG pour cette zone de texte ?","invalid_data_number":"{#field} doit \u00eatre un nombre","invalid_data_min":"{#field} doit \u00eatre un nombre plus grand que {#min}","invalid_data_size":"{#field} doit \u00eatre un nombre ou un pourcentage",value:"(value)"},contextmenu:{full:"Justifi\u00e9",right:"Droite",center:"Centr\u00e9",left:"Gauche",align:"Alignement"},insertdatetime:{"day_short":"Dim,Lun,Mar,Mer,Jeu,Ven,Sam,Dim","day_long":"Dimanche,Lundi,Mardi,Mercredi,Jeudi,Vendredi,Samedi,Dimanche","months_short":"Jan,F\u00e9v,Mar,Avr,Mai,Juin,Juil,Ao\u00fbt,Sep,Oct,Nov,D\u00e9c","months_long":"Janvier,F\u00e9vrier,Mars,Avril,Mai,Juin,Juillet,Ao\u00fbt,Septembre,Octobre,Novembre,D\u00e9cembre","inserttime_desc":"Ins\u00e9rer l\'heure","insertdate_desc":"Ins\u00e9rer la date","time_fmt":"%H:%M:%S","date_fmt":"%d-%m-%Y"},print:{"print_desc":"Imprimer"},preview:{"preview_desc":"Pr\u00e9visualiser"},directionality:{"rtl_desc":"\u00c9criture de droite \u00e0 gauche","ltr_desc":"\u00c9criture de gauche \u00e0 droite"},layer:{content:"Nouvelle couche\u2026","absolute_desc":"Activer le positionnement absolu","backward_desc":"D\u00e9placer vers l\'arri\u00e8re","forward_desc":"D\u00e9placer vers l\'avant","insertlayer_desc":"Ins\u00e9rer une nouvelle couche"},save:{"save_desc":"Enregistrer","cancel_desc":"Annuler toutes les modifications"},nonbreaking:{"nonbreaking_desc":"Ins\u00e9rer une espace ins\u00e9cable"},iespell:{download:"ieSpell n\'est pas install\u00e9. Souhaitez-vous l\'installer maintenant ?","iespell_desc":"Lancer le v\u00e9rificateur d\'orthographe"},advhr:{"delta_height":"Ecart de hauteur","delta_width":"Ecart de largeur","advhr_desc":"Ins\u00e9rer un trait horizontal"},emotions:{"emotions_desc":"\u00c9motic\u00f4nes","delta_height":"","delta_width":""},searchreplace:{"replace_desc":"Rechercher / remplacer","search_desc":"Rechercher","delta_width":"","delta_height":""},advimage:{"image_desc":"Ins\u00e9rer / \u00e9diter une image","delta_width":"","delta_height":""},advlink:{"link_desc":"Ins\u00e9rer / \u00e9diter un lien","delta_height":"","delta_width":""},xhtmlxtras:{"attribs_desc":"Ins\u00e9rer / \u00e9diter les attributs","ins_desc":"Ins\u00e9r\u00e9","del_desc":"Barr\u00e9","acronym_desc":"Acronyme","abbr_desc":"Abr\u00e9viation","cite_desc":"Citation","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"\u00c9diter la feuille de style (CSS)","delta_height":"","delta_width":""},paste:{"plaintext_mode":"Le collage est actuellement en mode texte non format\u00e9. Cliquez \u00e0 nouveau pour revenir en mode de collage ordinaire.","plaintext_mode_sticky":"Le collage est actuellement en mode texte non format\u00e9. Cliquez \u00e0 nouveau pour revenir en mode de collage ordinaire. Apr\u00e8s avoir coll\u00e9 quelque chose, vous retournerez en mode de collage ordinaire.","selectall_desc":"Tout s\u00e9lectionner","paste_word_desc":"Coller un texte cr\u00e9\u00e9 sous Word","paste_text_desc":"Coller comme texte brut"},"paste_dlg":{"word_title":"Utilisez CTRL+V sur votre clavier pour coller le texte dans la fen\u00eatre.","text_linebreaks":"Conserver les retours \u00e0 la ligne","text_title":"Utilisez CTRL+V sur votre clavier pour coller le texte dans la fen\u00eatre."},table:{cell:"Cellule",col:"Colonne",row:"Ligne",del:"Effacer le tableau","copy_row_desc":"Copier la ligne","cut_row_desc":"Couper la ligne","paste_row_after_desc":"Coller la ligne apr\u00e8s","paste_row_before_desc":"Coller la ligne avant","props_desc":"Propri\u00e9t\u00e9s du tableau","cell_desc":"Propri\u00e9t\u00e9s de la cellule","row_desc":"Propri\u00e9t\u00e9s de la ligne","merge_cells_desc":"Fusionner les cellules","split_cells_desc":"Scinder les cellules fusionn\u00e9es","delete_col_desc":"Effacer la colonne","col_after_desc":"Ins\u00e9rer une colonne apr\u00e8s","col_before_desc":"Ins\u00e9rer une colonne avant","delete_row_desc":"Effacer la ligne","row_after_desc":"Ins\u00e9rer une ligne apr\u00e8s","row_before_desc":"Ins\u00e9rer une ligne avant",desc:"Ins\u00e9rer un nouveau tableau","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"Si vous restaurez le contenu sauv\u00e9, vous perdrez le contenu qui est actuellement dans l\'\u00e9diteur.\n\n\u00cates-vous s\u00fbr de vouloir restaurer le contenu sauv\u00e9 ?","restore_content":"Restaurer le contenu auto-sauvegard\u00e9.","unload_msg":"Les modifications apport\u00e9es seront perdues si vous quittez cette page."},fullscreen:{desc:"Passer en mode plein \u00e9cran"},media:{edit:"\u00c9diter un m\u00e9dia incorpor\u00e9",desc:"Ins\u00e9rer / \u00e9diter un m\u00e9dia incorpor\u00e9","delta_height":"","delta_width":""},fullpage:{desc:"Propri\u00e9t\u00e9s du document","delta_width":"","delta_height":""},template:{desc:"Ins\u00e9rer un mod\u00e8le pr\u00e9d\u00e9fini."},visualchars:{desc:"Activer les caract\u00e8res de mise en page."},spellchecker:{desc:"Activer le v\u00e9rificateur d\'orthographe",menu:"Param\u00e8tres du v\u00e9rificateur d\'orthographe","ignore_word":"Ignorer le mot","ignore_words":"Tout ignorer",langs:"Langues",wait:"Veuillez patienter\u2026",sug:"Suggestions","no_sug":"Aucune suggestion","no_mpell":"Aucune erreur trouv\u00e9e.","learn_word":"Apprendre le mot"},pagebreak:{desc:"Ins\u00e9rer un saut de page."},advlist:{types:"Types",def:"D\u00e9faut","lower_alpha":"Alpha minuscule","lower_greek":"Grec minuscule","lower_roman":"Romain minuscule","upper_alpha":"Alpha majuscule","upper_roman":"Romain majuscule",circle:"Cercle",disc:"Disque",square:"Carr\u00e9"},colors:{"333300":"Dark olive","993300":"Burnt orange","000000":"Black","003300":"Dark green","003366":"Dark azure","000080":"Navy Blue","333399":"Indigo","333333":"Very dark gray","800000":"Maroon",FF6600:"Orange","808000":"Olive","008000":"Green","008080":"Teal","0000FF":"Blue","666699":"Grayish blue","808080":"Gray",FF0000:"Red",FF9900:"Amber","99CC00":"Yellow green","339966":"Sea green","33CCCC":"Turquoise","3366FF":"Royal blue","800080":"Purple","999999":"Medium gray",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Yellow","00FF00":"Lime","00FFFF":"Aqua","00CCFF":"Sky blue","993366":"Brown",C0C0C0:"Silver",FF99CC:"Pink",FFCC99:"Peach",FFFF99:"Light yellow",CCFFCC:"Pale green",CCFFFF:"Pale cyan","99CCFF":"Light sky blue",CC99FF:"Plum",FFFFFF:"White"},aria:{"rich_text_area":"Texte riche"},wordcount:{words:"Mots:"}}}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/langs/it.js b/src/static/org_glizy/assets/js/tiny_mce/langs/it.js new file mode 100644 index 0000000..59acac9 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/langs/it.js @@ -0,0 +1 @@ +tinyMCE.addI18n({it:{common:{"more_colors":"Colori aggiuntivi","invalid_data":"Errore: valori inseriti non validi, sono marcati in rosso.","popup_blocked":"Spiacente, ma il blocco popup ha disabilitato una finestra che fornisce funzionalit\u00e0 dell\'applicazione. Si deve disabilitare il blocco popup per questo sito per poter utlizzare appieno questo strumento.","clipboard_no_support":"Attualmente non supportato dal browser in uso, usare le scorciatoie da tastiera.","clipboard_msg":"Copia/Taglia/Incolla non \u00e8 disponibile in Mozilla e Firefox.\nSi desidera avere maggiori informazioni su questo problema?","not_set":"-- Non impostato --","class_name":"Classe",browse:"Sfoglia",close:"Chiudi",cancel:"Annulla",update:"Aggiorna",insert:"Inserisci",apply:"Applica","edit_confirm":"Usare la modalit\u00e0 WYSIWYG per questa textarea?","invalid_data_number":"{#field} deve essere un numero","invalid_data_min":"{#field} deve essere un numero maggiore di {#min}","invalid_data_size":"{#field} deve essere un numero o una percentuale",value:"(value)"},contextmenu:{full:"Giustifica",right:"Allinea a destra",center:"Centra",left:"Allinea a sinistra",align:"Allineamento"},insertdatetime:{"day_short":"Dom,Lun,Mar,Mer,Gio,Ven,Sab,Dom","day_long":"Domenica,Luned\u00ec,Marted\u00ec,Mercoled\u00ec,Gioved\u00ec,Venerd\u00ec,Sabato,Domenica","months_short":"Gen,Feb,Mar,Apr,Mag,Giu,Lug,Ago,Set,Ott,Nov,Dic","months_long":"Gennaio,Febbraio,Marzo,Aprile,Maggio,Giugno,Luglio,Agosto,Settembre,Ottobre,Novembre,Dicembre","inserttime_desc":"Inserisci ora","insertdate_desc":"Inserisci data","time_fmt":"%H:%M:%S","date_fmt":"%Y-%m-%d"},print:{"print_desc":"Stampa"},preview:{"preview_desc":"Anteprima"},directionality:{"rtl_desc":"Direzione da destra a sinistra","ltr_desc":"Direzione da sinistra a destra"},layer:{content:"Nuovo layer...","absolute_desc":"Attiva/Disattiva posizionamento assoluto","backward_desc":"Porta in sfondo","forward_desc":"Porta in rilievo","insertlayer_desc":"Inserisci nuovo layer"},save:{"save_desc":"Salva","cancel_desc":"Cancella tutte le modifiche"},nonbreaking:{"nonbreaking_desc":"Inserisci uno spazio"},iespell:{download:"ieSpell non rilevato. Installarlo ora?","iespell_desc":"Esegui controllo ortografico"},advhr:{"advhr_desc":"Riga orizzontale","delta_height":"","delta_width":""},emotions:{"emotions_desc":"Faccine","delta_height":"","delta_width":""},searchreplace:{"replace_desc":"Trova/Sostituisci","search_desc":"Trova","delta_width":"","delta_height":""},advimage:{"image_desc":"Inserisci/modifica immagine","delta_width":"","delta_height":""},advlink:{"link_desc":"Inserisci/modifica collegamento","delta_height":"","delta_width":""},xhtmlxtras:{"attribs_desc":"Inserisci/modifica attributi","ins_desc":"Inserimento","del_desc":"Cancellamento","acronym_desc":"Acronimo","abbr_desc":"Abbreviazione","cite_desc":"Citazione","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"Modifica stile CSS","delta_height":"","delta_width":""},paste:{"plaintext_mode":"Incolla adesso e in modalit\u00e0 testo. Clicca nuovamente per tornare alla modalit\u00e0 normale.","plaintext_mode_sticky":"Incolla adesso e in modalit\u00e0 testo. Clicca nuovamente per tornare alla modalit\u00e0 normale. Dopo che avrai incollato qualcosa tornerai alla modalit\u00e0 normale","selectall_desc":"Seleziona tutto","paste_word_desc":"Incolla da Word","paste_text_desc":"Incolla come testo semplice"},"paste_dlg":{"word_title":"Premere CTRL+V sulla tastiera per incollare il testo nella finestra.","text_linebreaks":"Mantieni interruzioni di riga","text_title":"Premere CTRL+V sulla tastiera per incollare il testo nella finestra."},table:{cell:"Cella",col:"Colonna",row:"Riga",del:"Elimina tabella","copy_row_desc":"Copia riga","cut_row_desc":"Taglia riga","paste_row_after_desc":"Incolla riga dopo","paste_row_before_desc":"Incolla riga prima","props_desc":"Propriet\u00e0 tabella","cell_desc":"Propriet\u00e0 cella","row_desc":"Propriet\u00e0 riga","merge_cells_desc":"Unisci celle","split_cells_desc":"Separa celle","delete_col_desc":"Elimina colonna","col_after_desc":"Inserisci colonna dopo","col_before_desc":"Inserisci colonna prima","delete_row_desc":"Elimina riga","row_after_desc":"Inserisci riga dopo","row_before_desc":"Inserisci riga prima",desc:"Inserisci una nuova tabella","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"Se ripristini i dati salvati automaticamente perderai i dati attuali dell\'editor\n\nSei sicuro di voler ripristinare i dati?.","restore_content":"Ripristina i dati salvati automaticamente","unload_msg":"I cambiamenti effettuati saranno persi se si abbandona la pagina corrente."},fullscreen:{desc:"Attiva/disattiva modalit\u00e0 a tutto schermo"},media:{edit:"Modifica file multimediale",desc:"Inserisci/modifica file multimediale","delta_height":"","delta_width":""},fullpage:{desc:"Propriet\u00e0 Documento","delta_width":"","delta_height":""},template:{desc:"Inserisci contenuto da modello predefinito"},visualchars:{desc:"Attiva/disattiva caratteri di controllo visuale."},spellchecker:{desc:"Attiva/disattiva controllo ortografico",menu:"Impostazioni controllo ortografico","ignore_word":"Ignora parola","ignore_words":"Ignora tutto",langs:"Lingue",wait:"Attendere prego...",sug:"Suggerimenti","no_sug":"Nessun suggerimento","no_mpell":"Nessun errore rilevato.","learn_word":"Learn word"},pagebreak:{desc:"Inserisci intterruzione di pagina."},advlist:{types:"Tipi",def:"Default","lower_alpha":"Minuscolo alfanumerico","lower_greek":"Minuscolo lettera greca","lower_roman":"Minuscolo lettere romane","upper_alpha":"Maiuscolo alfanumerico","upper_roman":"Maiuscolo lettere romane",circle:"Cerchio",disc:"Punto",square:"Quadrato"},colors:{"333300":"Dark olive","993300":"Burnt orange","000000":"Black","003300":"Dark green","003366":"Dark azure","000080":"Navy Blue","333399":"Indigo","333333":"Very dark gray","800000":"Maroon",FF6600:"Orange","808000":"Olive","008000":"Green","008080":"Teal","0000FF":"Blue","666699":"Grayish blue","808080":"Gray",FF0000:"Red",FF9900:"Amber","99CC00":"Yellow green","339966":"Sea green","33CCCC":"Turquoise","3366FF":"Royal blue","800080":"Purple","999999":"Medium gray",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Yellow","00FF00":"Lime","00FFFF":"Aqua","00CCFF":"Sky blue","993366":"Brown",C0C0C0:"Silver",FF99CC:"Pink",FFCC99:"Peach",FFFF99:"Light yellow",CCFFCC:"Pale green",CCFFFF:"Pale cyan","99CCFF":"Light sky blue",CC99FF:"Plum",FFFFFF:"White"},aria:{"rich_text_area":"Area testo formattato"},wordcount:{words:"Parole:"}}}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/license.txt b/src/static/org_glizy/assets/js/tiny_mce/license.txt new file mode 100644 index 0000000..60d6d4c --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/license.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/css/GLZ_image.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/css/GLZ_image.css new file mode 100644 index 0000000..5a404f2 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/css/GLZ_image.css @@ -0,0 +1,72 @@ +/* CSS file for advimage plugin popup */ + +.mceImageList { + width: 280px; +} + +.mceActionPanel { + margin-top: 7px; +} + +.alignPreview { + border: 1px solid black; + width: 150px; + height: 100px; + overflow: hidden; + padding: 5px; +} + +.checkbox { + border: 0px; +} + +.panel_wrapper div.current { + height: 305px; +} + +#align, #classlist { + width: 120px; +} + +#width, #height { + vertical-align: middle; + width: 40px; + text-align: center; +} + +#vspace, #hspace, #border { + vertical-align: middle; + width: 30px; + text-align: center; +} + +#cssClass { + width: 140px; + margin-right: 5px; +} + +input { + width: 100%; +} + +#id, #dir, #lang, #usemap, #longdesc { + width: 200px; +} + +#general_panel { + width: 370px; +} + +#picker { + width: 100%; + height: 450px; +} + + +.multifieldset { + margin-bottom: 4px; +} + +body { + margin: 6px; +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/editor_plugin.js new file mode 100644 index 0000000..9ec5947 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/editor_plugin.js @@ -0,0 +1,67 @@ +/** + * TinyMCE Image plugin, based on TinyMCE-advimage plugin by Moxiecode Systems AB. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2006 Daniele Ugoletti <daniele@ugoletti.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + * + * @copyright Copyright (c) 2005, 2006 Daniele Ugoletti + * @link http://www.glizy.org Glizy Project + * @license http://www.gnu.org/copyleft/lesser.html GNU LESSER GENERAL PUBLIC LICENSE + * @package glizy + * @subpackage javascript + * @author Daniele Ugoletti <daniele@ugoletti.com>, Giorgio Braga <giorgio@justattributes.com> + * @category javascript + * @since Glizy v 0.01 + * @version $Rev: 81 $ + * @modifiedby $LastChangedBy: ugoletti $ + * @lastmodified $Date: 2007-01-14 08:59:55 +0100 (dom, 14 gen 2007) $ + */ + + +(function() { + tinymce.PluginManager.requireLangPack('GLZ_image'); + + tinymce.create('tinymce.plugins.GlizyImagePlugin', { + init : function(ed, url) { + this.editor = ed; + + // Register commands + ed.addCommand('mceGlzImage', function() { + // Internal image object like a flash placeholder + if (ed.dom.getAttrib(ed.selection.getNode(), 'class', '').indexOf('mceItem') != -1) + return; + + ed.windowManager.open({ + file : url + '/image.htm', + width : 950 + parseInt(ed.getLang('GLZ_image.delta_width', 0)), + height : 530 + parseInt(ed.getLang('GLZ_image.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('image', { + title : 'advimage.image_desc', + cmd : 'mceGlzImage' + }); + }, + + getInfo : function() { + return { + longname : 'Glizy Image (based on TinyMCE-advimage plugin by Moxiecode Systems AB)', + author : 'Daniele Ugoletti', + authorurl : 'http://www.glizy.org', + infourl : 'http://www.glizy.org', + version : '1.2.0' + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('GLZ_image', tinymce.plugins.GlizyImagePlugin); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/image.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/image.htm new file mode 100644 index 0000000..ae73cca --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/image.htm @@ -0,0 +1,114 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#GLZ_image.window_title}</title> + <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script> + <script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script> + <script language="javascript" type="text/javascript" src="jscripts/functions.js"></script> + <link href="css/GLZ_image.css" rel="stylesheet" type="text/css" /> +</head> +<body id="GLZ_image" style="display: none"> + <form onsubmit="insertAction();return false;" action="#"> + <input type="hidden" id="src" name="src" value = ""/> + <input type="hidden" id="imgid" value = ""/> + <input type="hidden" id="orw" value = ""/> + <input type="hidden" id="orh" value = ""/> + <table style="background-color:#FFFFFF;border:1px solid #919B9C;" width="100%"> + <tr> + <td style="padding-left:4px;" valign="top"> + <table border="0" cellpadding="0" cellspacing="0" width="100%" height="334"> + <tr><td valign="top"> + <fieldset> + <legend>{#GLZ_image.general}</legend> + <table border="0" cellpadding="2" cellspacing="0"> + <tr> + <td rowspan="5" width="100" align="center" valign="middle"><img src="images/sample.gif" alt="{#GLZ_image.sample_image}" id="thumbnail" width="100" height="100"/></td> + <td width="100%"><label id="altlabel" for="alt">{#GLZ_image.alt}</label></td> + <tr> + <tr><td><input id="alt" name="alt" type="text" value="" /></td></tr> + <tr><td><label id="titlelabel" for="title">{#GLZ_image.title}</label></td></tr> + <tr><td><input id="title" name="title" type="text" value="" /></td></tr> + </table> + </fieldset> + </td></tr> + <tr><td valign="bottom"> + <fieldset> + <legend>{#GLZ_image.tab_appearance}</legend> + <table border="0" cellpadding="2" cellspacing="0"> + <tr> + <td><label id="alignlabel" for="align">{#GLZ_image.align}</label></td> + <td><select id="align" name="align" onchange="changeAppearance();"> + <option value="">{#GLZ_image.align_default}</option> + <option value="left">{#GLZ_image.align_left}</option> + <option value="right">{#GLZ_image.align_right}</option> + </select> + </td> + <td rowspan="6" valign="top"> + <div class="alignPreview"> + <img id="alignSampleImg" src="images/sample.gif" alt="{#GLZ_image.example_img}" /> + Lorem ipsum, Dolor sit amet, consectetuer adipiscing loreum ipsum edipiscing elit, sed diam + nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.Loreum ipsum + edipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam + erat volutpat. + </div> + </td> + </tr> + <tr> + <td><label id="widthlabel" for="width">{#GLZ_image.dimensions}</label></td> + <td nowrap="nowrap"> + <input name="width" type="text" id="width" value="" size="5" maxlength="5" onchange="changeHeight();" /> x + <input name="height" type="text" id="height" value="" size="5" maxlength="5" onchange="changeWidth();" /> px + </td> + </tr> + <tr> + <td width="1%"><label id="vspacelabel" for="vspace">{#GLZ_image.vspace}</label></td> + <td><input name="vspace" type="text" id="vspace" value="" size="3" maxlength="3" onchange="changeAppearance();updateStyle();" /> + </td> + </tr> + <tr> + <td><label id="hspacelabel" for="hspace">{#GLZ_image.hspace}</label></td> + <td><input name="hspace" type="text" id="hspace" value="" size="3" maxlength="3" onchange="changeAppearance();updateStyle();" /></td> + </tr> + <tr> + <td><label id="borderlabel" for="border">{#GLZ_image.border}</label></td> + <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="changeAppearance();updateStyle();" /></td> + </tr> + <tr> + <td><label id="classlabel" for="classlist">{#class_name}</label></td> + <td colspan="2"><input name="cssclass" type="text" id="cssclass" value="" onchange="changeAppearance();updateStyle();"/><select id="cssClassList" onchange="changeCssClass(this);"> + <option value="">-</option> + <option value="left">{#GLZ_image.css_left}</option> + <option value="right">{#GLZ_image.css_right}</option> + <option value="center">{#GLZ_image.css_center}</option> + <option value="left noBorder">{#GLZ_image.css_left_noborder}</option> + <option value="right noBorder">{#GLZ_image.css_right_noborder}</option> + <option value="center noBorder">{#GLZ_image.css_center_noborder}</option> + </select></td> + </tr> + <tr> + <td><label id="stylelabel" for="style">{#GLZ_image.style}</label></td> + <td colspan="2"><input id="style" name="style" type="text" value="" onchange="styleUpdated();" /></td> + </tr> + </table> + </fieldset> + </td></tr> + </table> + </td> + <td style="padding:4px;width:100%;"> + <fieldset> + <iframe id="picker" frameborder="0"></iframe> + </fieldset> + </td> + </tr> + </table> + <div class="mceActionPanel"> + <div style="float: left"> + <input type="button" id="insert" name="insert" value="{#insert}" onclick="insertAction();" /> + </div> + <div style="float: right"> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="cancelAction();" /> + </div> + </div> + </form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/images/sample.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/images/sample.gif new file mode 100644 index 0000000000000000000000000000000000000000..53bf6890b507741c10910c9e2217ad8247b98e8d GIT binary patch literal 1624 zcmV-e2B-N)Nk%w1VJ!eH0OkMy|NsB}{r&v>{Q3F$`1ttq^YifV@ayaA>FMd_=H}w! z;^5%m-rnBb-QC>W+}qpR+S=OL+1c3G*w@$B*4Eb4)YQ|{)zHw=&d$%x&CScp%gV~i z$;rvc$jHXV#>B+L!^6YE!otD9!N9=4zrVk|y}i7=yt})*y1Kf#xw*Hux3;#nwY9ah zw6wFcv$C?Xv9YnRu&}SMudc4Ht*x!BtgNf6tE#H1si~={sjjD|r>3T+rKP2$q@<&x zqobp!qN1Xqp`oFnrJ$goprE6lpP!zdp`M<eot>SWoSd7Ro12@UnwpxLnw^=MnV6WE zmzS58mX?*3mz9;3mX?*2l$4W`lai8@l9G~<k&%*;k&uv(kdTs(kB^X$kB*L!j*gFx zj*g9ujf{+pi;Ihjii(MeiHL}ZhlhuThK7ZOg@lBJgM)*Df`Wj6fPQ{{eSLj=e0+L( zdU$wvcXxPpc6M}hbaHZXaBy&KZEb03X=P<)Vq#)hSy=!800000A^8LZ6afDKEC2ui z04)G5000O7fD?j)goT3;h=_uTjE0VnkP{A*lY*3#5s{jX5SyN#jwMP^N>eg|M^H&l zLpBo?51@vfgB2q_TVh*dNP<;cR$Wg!vYsMHR!qvvOis>GNH`<Kgo-dQEG#%tOgP>+ zJ3B|t<U=>qgANiBSy@x>Q#;x7+DuU7&rwlf#S04)VZvA$XoUy8Y&f7)SqP<}Lw@L# zA(@Cohl`6CZyedUu^BlmK|DG5$Kl2f8z@uCc)^k-3m7$G!njf7$;XhOW>^`rV#UFh zEN#eG;bP?tCs>{+)q)ceg9$aDAaTZ{MGK5rU8ty$qz8){MT#gHGX{#XEJHLonBXFa zj+#9GE&^pq!`qG`K5iiC!gq}sRY|1yD8?j++_^oR0g+)NNtZN`)08!0q=}AA4HhIo zFaa9NYu8%97=oos5f?O`lwre~4VfoIei+FyK|urxj@C(-q(sS(!$5uL3j&jg7&XY% zlr17;3GGL;2K8>CB87G97;W(2VZ((D<H*m1X-8g4T1RUqv|C6cLxvIXN1Vu-5xkl* zPo|)0%|_0X3I7<PM0jf8P(cMAfS_OrF2vxVRV}12LlR*iM}|FUw9$qdZP)=tBtZnx zLk})^AcA!ykbnYxMezW|7|5CN&KYY&<^~fWRG>+3Hz;L;bylfhf(kFNV8at)h;hdM z85WX(#*<HWA=N}r00GG;a<~x$Q5TsILJBdkz{44EtWjfRXr^I?6H&Aw2OM^+aitP) zw9&%}DyYyx2_bA1gAZl6p+=f%uIWS?Zn!ar8PzP(n-X1AQG^bZ>Hq@@BYePt3t_l{ zCL3|YVWydA0Fz{rTl65n00)c^)^<fWanch@Zoz~PFJO?s0Uclg2byo_k%t>-jJn1c zRVXtA6mkUMEDLU|v7{JK&_IJ2ciiCy7BOT1fdUBh8b=yrbYaCAchCU_7?H`b1`}4q zLB|_mI2!;7W4QCq6F1O+MW||6AwmKafUrReUA&QotxQZI8D$G)AuSVV@X<&A9v;~H zKnWjo&;bljq=29aCeV-t5GBYkL=Q}q(S~FLd2t39MyRmC%_GFHkPc7CfIt8P*emqV z0YK2j9A+kmW^!tn(ZmG+L=6DZR99W}8p9?Utr=#t@rE2=zxf3QQ(JBJ&<{Z2>8EUP zeX1B)2w_3gXV)D-0Tt+=#@cV-0f!PU#MglZ3m6b}0e08zK^x<mF$W)Qkg&keQkPA2 z&_YW+Gyzd_0EZlEJ|4vZ_6|__;fb4VK(FD+!N(S<5ACrA8q7|+?H+h=vj;3Z!3G*~ z?BSsbv={I3@h6-R!t%_Q;QaH@NAJAHKoA>;9(u?Tga{%?&nNTXhcEuM_#J>yL>p*a zuZJ2p<PO64@XH|o{Pfp9zYbWu96TR(SYfTTFsR=OZV-j=G2?&;R0bBHga$b1fe(9_ zLm4KhiUTI$f*8D@LpI1khg3lfY;Z#v7D5I&*uf5X$b%l@WCe$0@P$cGiVSB+!zW-N z4KK?=Z>liCGSp!Ye8>YFq@)ZOW-uT~OrjFQK!)UyVGFt7ni<?shdN}*45u<8293qV WE}n@{k&&Vq!n33@nsG^i002Ao7W&ix literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/jscripts/functions.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/jscripts/functions.js new file mode 100644 index 0000000..556777e --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/jscripts/functions.js @@ -0,0 +1,310 @@ +/** + * TinyMCE Image plugin, based on TinyMCE-advimage plugin by Moxiecode Systems AB. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2006 Daniele Ugoletti <daniele@ugoletti.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + * + * @copyright Copyright (c) 2005, 2006 Daniele Ugoletti + * @link http://www.glizy.org Glizy Project + * @license http://www.gnu.org/copyleft/lesser.html GNU LESSER GENERAL PUBLIC LICENSE + * @package glizy + * @subpackage javascript + * @author Daniele Ugoletti <daniele@ugoletti.com>, Giorgio Braga <giorgio@justattributes.com> + * @category javascript + * @since Glizy v 0.01 + * @version $Rev: 328 $ + * @modifiedby $LastChangedBy: ugoletti $ + * @lastmodified $Date: 2011-01-24 17:46:02 +0100 (lun, 24 gen 2011) $ + */ + + +function convertURL(url, node, on_save) { + return url; +} +function trimSize(size) { + return size.replace(/([0-9\.]+)px|(%|in|cm|mm|em|ex|pt|pc)/, '$1$2'); +} + +function init() { + var f = document.forms[0], formObj = f.elements, ed = tinyMCEPopup.editor, dom = ed.dom, elm = ed.selection.getNode(); + document.getElementById("picker").src = parent.Glizy.tinyMCE_options.image_picker; + + tinyMCEPopup.resizeToInnerSize(); + if (elm.nodeName == 'IMG') { + var src = dom.getAttrib(elm, 'src'); + src = convertURL(src, elm, true); + // Setup form data + var style = dom.getAttrib(elm, 'style'); + var search = src.split("?")[1]; + var els = search.split("&"); + formObj.imgid.value = els[0].split("=")[1]; + var tn = formObj.src.value = src; + formObj.alt.value = dom.getAttrib(elm, 'alt'); + formObj.title.value = dom.getAttrib(elm, 'title'); + var border = dom.getStyle(elm, 'border' ); + if (border!='') + { + formObj.border.value = trimSize(border.split(' ')[0]); + } + else + { + formObj.border.value = ''; + } + + var margin = getStyle(elm, 'margin'); + if (margin!='') + { + margin = margin.split(' '); + formObj.vspace.value = trimSize(margin[0]); + formObj.hspace.value = trimSize(margin[margin.length > 1 ? 1 : 0]); + } + else + { + formObj.vspace.value = ''; + formObj.hspace.value = ''; + } + + formObj.cssclass.value = dom.getAttrib(elm, 'class'); + var w = formObj.orw.value = formObj.width.value = trimSize(dom.getStyle(elm, 'width')); + var h = formObj.orh.value = formObj.height.value = trimSize(dom.getStyle(elm, 'height')); + formObj.style.value = style; ///dom.serializeStyle(style); + with (f.thumbnail) { + if (w>h) { + width = 100; + height = h/w*100; + } + else { + height = 100; + width = w/h*100; + } + src = tn.indexOf('http://')>-1 ? tn : parent.Glizy.tinyMCE_options.glizy_admin_path+tn; + } + + selectByValue(f, 'align', dom.getStyle(elm, 'float')); + + updateStyle(); + changeAppearance(); + } + + // // Check action + // if (elm != null && elm.nodeName == "IMG") + // action = "update"; + // + // formObj.insert.value = tinyMCE.getLang('lang_' + action, 'Insert', true); + // + // if (action == "update") { + // + // } +} + +function update(imgid,url,t,tn,w,h) { + var formObj = document.forms[0]; + formObj.imgid.value = imgid; + with (formObj) { + title.value = t; + alt.value = ""; + width.value = orw.value = w; + height.value = orh.value = h; + with (thumbnail) { + if (w/h > 1) { + width = 100; + height = h/w*100; + } + else { + height = 100; + width = w/h*100; + } + src = tn; + } + } + updateStyle(); +} + +function setAttrib(elm, attrib, value) { + var ed = tinyMCEPopup.editor, dom = ed.dom; + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib]; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + if (value != "") { + dom.setAttrib(elm, attrib, value); + } else + elm.removeAttribute(attrib); +} + +function makeAttrib(attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib]; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + if (value == "") + return ""; + return ' ' + attrib + '="' + value + '"'; +} + +function insertAction() { + var ed = tinyMCEPopup.editor, dom = ed.dom; + var formObj = document.forms[0]; + tinyMCEPopup.restoreSelection(); + + // Fixes crash in Safari + if (tinymce.isWebKit) + ed.getWin().focus(); + + if (formObj.imgid.value) { + var src = parent.Glizy.tinyMCE_options.image_resizer+"?id="+formObj.imgid.value+"&w="+formObj.width.value+"&h="+formObj.height.value; + formObj.alt.value = formObj.alt.value || formObj.title.value; + var src = convertURL(src, tinyMCE.imgElement); + + var args + var elm = ed.selection.getNode(); + if (elm && elm.nodeName == 'IMG') { + setAttrib(elm, 'src', src); + setAttrib(elm, 'alt'); + setAttrib(elm, 'title'); + setAttrib(elm, 'style'); + setAttrib(elm, 'class', formObj.cssclass.value); + } else { + var html = "<img"; + + html += makeAttrib('src', src); + html += makeAttrib('alt'); + html += makeAttrib('title'); + html += makeAttrib('style'); + html += makeAttrib('class', formObj.cssclass.value); + html += " />"; + + ed.execCommand("mceInsertContent", false, html, {skip_undo : 1}); + ed.undoManager.add(); + } + } + + tinyMCEPopup.editor.execCommand('mceRepaint'); + tinyMCEPopup.editor.focus(); + tinyMCEPopup.close(); +} + +function cancelAction() { + tinyMCEPopup.close(); +} + +function changeAppearance() { + var formObj = document.forms[0]; + var img = document.getElementById('alignSampleImg'); + + if (img) { + img.align = formObj.align.value; + img.border = formObj.border.value; + img.hspace = formObj.hspace.value; + img.vspace = formObj.vspace.value; + updateStyle(); + } +} + +function changeCssClass(elm) { + if (elm.selectedIndex !=0) + { + var formObj = document.forms[0]; + formObj.cssclass.value = elm.value; + elm.selectedIndex = 0; + } +} + +function updateStyle() { + var ed = tinyMCEPopup.editor, dom = ed.dom; + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + if (ed.settings.inline_styles) { + st['width'] = formObj.width.value == '' ? '' : formObj.width.value + "px"; + st['height'] = formObj.height.value == '' ? '' : formObj.height.value + "px"; + st['border'] = formObj.border.value == '' ? '' : formObj.border.value + "px solid"; + if (formObj.vspace.value != '' || formObj.hspace.value != '') + { + st['margin'] = formObj.vspace.value == '' ? '0' : formObj.vspace.value + "px" + st['margin'] += formObj.hspace.value == '' ? ' 0' : ' '+formObj.hspace.value + "px"; + st['margin'] += formObj.vspace.value == '' ? ' 0' : ' '+formObj.vspace.value + "px" + st['margin'] += formObj.hspace.value == '' ? ' 0' : ' '+formObj.hspace.value + "px"; + } + else + { + delete st['margin']; + } + + } else { + st['width'] = st['height'] = st['border'] = null; + + if (st['margin-top'] == st['margin-bottom']) + st['margin-top'] = st['margin-bottom'] = null; + + if (st['margin-left'] == st['margin-right']) + st['margin-left'] = st['margin-right'] = null; + } + + st['float'] = formObj.align.value == '' ? '' : formObj.align.value; + + formObj.style.value = dom.serializeStyle(st); +} + +function styleUpdated() { + var ed = tinyMCEPopup.editor, dom = ed.dom; + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + if (st['width']) + formObj.width.value = st['width'].replace('px', ''); + + if (st['height']) + formObj.height.value = st['height'].replace('px', ''); + + if (st['margin-top'] && st['margin-top'] == st['margin-bottom']) + formObj.vspace.value = st['margin-top'].replace('px', ''); + + if (st['margin-left'] && st['margin-left'] == st['margin-right']) + formObj.hspace.value = st['margin-left'].replace('px', ''); + + if (st['border-width']) + formObj.border.value = st['border-width'].replace('px', ''); +} + +function changeHeight() { + var formObj = document.forms[0]; + + var temp = (formObj.width.value / formObj.orw.value) * formObj.orh.value; + formObj.height.value = temp.toFixed(0); + updateStyle(); +} + +function changeWidth() { + var formObj = document.forms[0]; + + var temp = (formObj.height.value / formObj.orh.value) * formObj.orw.value; + formObj.width.value = temp.toFixed(0); + updateStyle(); +} + +function getSelectValue(form_obj, field_name) { + var elm = form_obj.elements[field_name]; + + if (elm == null || elm.options == null) + return ""; + + return elm.options[elm.selectedIndex].value; +} + +tinyMCEPopup.onInit.add(init, null); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/langs/en.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/langs/en.js new file mode 100644 index 0000000..814c03f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/langs/en.js @@ -0,0 +1,56 @@ +// UK lang variables + +tinyMCE.addI18n('en.GLZ_image',{ + window_title:"Insert/Edit Image", + tab_appearance : 'Appearance', + general : 'General', + title : 'Title', + style : 'Style', + example_img : 'Appearance&nbsp;preview&nbsp;image', + sample_image : 'image placeholder', + css_left : 'Left aligned', + css_right : 'Right aligned', + css_center : 'Center aligned', + css_left_noborder : 'Left aligned, no border', + css_right_noborder : 'Right aligned, no border', + css_center_noborder : 'Center aligned, no border', + align_default:"-- Default --", + "image_list":"Image List", + "align_right":"Right", + "align_left":"Left", + "align_textbottom":"Text Bottom", + "align_texttop":"Text Top", + "align_bottom":"Bottom", + "align_middle":"Middle", + "align_top":"Top", + "align_baseline":"Baseline", + align:"Alignment", + hspace:"Horizontal Space", + vspace:"Vertical Space", + dimensions:"Dimensions", + border:"Border",list:"Image List", + alt:"Image Description", + src:"Image URL", + "missing_alt":"Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.", + misc:"Miscellaneous", + mouseout:"For Mouse Out", + mouseover:"For Mouse Over", + "alt_image":"Alternative Image", + "swap_image":"Swap Image", + map:"Image Map", + id:"ID", + rtl:"Right to Left", + ltr:"Left to Right", + classes:"Classes", + "long_desc":"Long Description Link", + langcode:"Language Code", + langdir:"Language Direction", + "constrain_proportions":"Constrain Proportions", + preview:"Preview", + "tab_advanced":"Advanced", + "tab_appearance":"Appearance", + "tab_general":"General", + width:"Width", + height:"Height" +}); + diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/langs/it.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/langs/it.js new file mode 100644 index 0000000..d028846 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_image/langs/it.js @@ -0,0 +1,57 @@ +// IT lang variables + +tinyMCE.addI18n('it.GLZ_image',{ + window_title:"Inserisci/modifica immagine", + tab_appearance : 'Aspetto', + general : 'Propriet&agrave&nbsp;generali', + style : 'Stile', + title : 'Titolo', + example_img : 'Immagine&nbsp;esemplificativa', + sample_image : 'Immagine&nbsp;esemplificativa', + css_left : 'Allineato a sinistra', + css_right : 'Allineato a destra', + css_center : 'Allineato al centro', + css_left_noborder : 'Allineato a sinistra, senza bordo', + css_right_noborder : 'Allineato a destra, senza bordo', + css_center_noborder : 'Allineato al centro, senza bordo', + align_default:"-- Non impostato --", + "image_list":"Lista immagini", + "align_right":"A destra", + "align_left":"A sinistra", + "align_textbottom":"In basso al testo", + "align_texttop":"In alto al testo", + "align_bottom":"In basso", + "align_middle":"In mezzo", + "align_top":"In alto", + "align_baseline":"Alla base", + align:"Allineamento", + hspace:"Spaziatura orizzontale", + vspace:"Spaziatura verticale", + dimensions:"Dimensioni", + border:"Bordo", + list:"Lista immagini", + alt:"Descrizione immagine", + src:"URL immagine", + "missing_alt":"Sicuro di continuare senza includere una descrizione dell\'immagine? Senza di essa l\'immagine pu\u00f2 non essere accessibile ad alcuni utenti con disabilit\u00e0, o per coloro che usano un browser testuale oppure che hanno disabilitato la visualizzazione delle immagini nel loro browser.", + misc:"Impostazioni varie", + mouseout:"quando mouse fuori", + mouseover:"quando mouse sopra", + "alt_image":"Immagine alternativa", + "swap_image":"Sostituisci immagine", + map:"Immagine come mappa", + id:"Id", + rtl:"Destra verso sinistra", + ltr:"Sinistra verso destra", + classes:"Classe", + style:"Stile", + "long_desc":"Descrizione del collegamento", + langcode:"codice lingua", + langdir:"Direzione testo", + "constrain_proportions":"Mantieni proporzioni", + preview:"Anteprima", + "tab_advanced":"Avanzate", + "tab_appearance":"Aspetto", + "tab_general":"Generale", + width:"Larghezza", + height:"Altezza" +}); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/css/GLZ_link.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/css/GLZ_link.css new file mode 100644 index 0000000..68da316 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/css/GLZ_link.css @@ -0,0 +1,41 @@ +/* CSS file for advimage plugin popup */ + +.mceActionPanel { + margin-top: 7px; +} + +.panel_wrapper { + border-top: 1px solid #919B9C; + width: 380px; +} + +#linkType, #linkUrl, #internalLink, #title, #target, #id, #style, #classlist, #rel, #rev, #tabindex, #accesskey, #cssclass { + width: 100%; +} + +#preview { + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 10px; + cursor: pointer; +} + +.multifieldset { + margin-bottom: 4px; +} + +#picker { + width: 100%; + height: 100%; +} + +#pickerPanel { + background-color: #FFF; + position: absolute; + left: 414px; + top: 8px; + width: 470px; + height: 466px; + display: none; + padding: 4px; + border: 1px solid #919B9C; +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/editor_plugin.js new file mode 100644 index 0000000..5f52601 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/editor_plugin.js @@ -0,0 +1,77 @@ +/* SVN FILE: $Id: editor_plugin.js 162 2007-03-30 22:57:05Z ugoletti $ */ +/** + * TinyMCE Image plugin, based on TinyMCE-advlink plugin by Moxiecode Systems AB. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2006 Daniele Ugoletti <daniele@ugoletti.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + * + * @copyright Copyright (c) 2005, 2006 Daniele Ugoletti + * @link http://www.glizy.org Glizy Project + * @license http://www.gnu.org/copyleft/lesser.html GNU LESSER GENERAL PUBLIC LICENSE + * @package glizy + * @subpackage javascript + * @author Daniele Ugoletti <daniele@ugoletti.com>, Giorgio Braga <giorgio@justattributes.com> + * @category javascript + * @since Glizy v 0.01 + * @version $Rev: 162 $ + * @modifiedby $LastChangedBy: ugoletti $ + * @lastmodified $Date: 2007-03-31 00:57:05 +0200 (sab, 31 mar 2007) $ + */ + + +(function() { + tinymce.PluginManager.requireLangPack('GLZ_link'); + + tinymce.create('tinymce.plugins.GlizyLinkPlugin', { + init : function(ed, url) { + this.editor = ed; + + // Register commands + ed.addCommand('mceGlzLink', function() { + var se = ed.selection; + + // No selection and not in link + if (se.isCollapsed() && !ed.dom.getParent(se.getNode(), 'A')) + return; + + ed.windowManager.open({ + file : url + '/link.htm', + width : 420 + parseInt(ed.getLang('GLZ_link.delta_width', 0)), + height : 530 + parseInt(ed.getLang('GLZ_link.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('link', { + title : 'advlink.link_desc', + cmd : 'mceGlzLink' + }); + + ed.addShortcut('ctrl+k', 'advlink.link_desc', 'mceGLZ_link'); + + ed.onNodeChange.add(function(ed, cm, n, co) { + cm.setDisabled('link', co && n.nodeName != 'A'); + cm.setActive('link', n.nodeName == 'A' && !n.name); + }); + }, + + getInfo : function() { + return { + longname : 'Glizy link (based on TinyMCE-advlink plugin by Moxiecode Systems AB)', + author : 'Daniele Ugoletti', + authorurl : 'http://www.glizy.org', + infourl : 'http://www.glizy.org', + version : '1.2.0' + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('GLZ_link', tinymce.plugins.GlizyLinkPlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/jscripts/functions.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/jscripts/functions.js new file mode 100644 index 0000000..ccc31a4 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/jscripts/functions.js @@ -0,0 +1,347 @@ +/* SVN FILE: $Id: functions.js 298 2008-10-21 23:21:58Z ugoletti $ */ + +/** + * TinyMCE Image plugin, based on TinyMCE-advlink plugin by Moxiecode Systems AB. + * + * This file is part of the GLIZY framework. + * Copyright (c) 2005-2006 Daniele Ugoletti <daniele@ugoletti.com> + * + * For the full copyright and license information, please view the COPYRIGHT.txt + * file that was distributed with this source code. + * + * @copyright Copyright (c) 2005, 2006 Daniele Ugoletti + * @link http://www.glizy.org Glizy Project + * @license http://www.gnu.org/copyleft/lesser.html GNU LESSER GENERAL PUBLIC LICENSE + * @package glizy + * @subpackage javascript + * @author Daniele Ugoletti <daniele@ugoletti.com> + * @category javascript + * @since Glizy v 0.01 + * @version $Rev: 298 $ + * @modifiedby $LastChangedBy: ugoletti $ + * @lastmodified $Date: 2008-10-22 01:21:58 +0200 (mer, 22 ott 2008) $ + */ + + +/* Functions for the advlink plugin popup */ + +var currentSize = {w: 420, h: 530 }; + +function renderInternalLinks() { + var intLinks = parent.Glizy.tinyMCE_options.internal_links; + var aSel = ['<select id="internalLink" style="width: 100%" disabled="disabled">']; + aSel.push('<option value="">---</option>'); + for (var i=0;i<intLinks.length;i++) { + aSel.push('<option value="internal:'+intLinks[i][1]+'">'+intLinks[i][0]+'</option>'); + } + aSel.push('</select>'); + + var intLinks = parent.Glizy.tinyMCE_options.glossary_links; + aSel.push( '<select id="glossaryLinks" style="width: 100%; display: none;">' ); + aSel.push('<option value="">---</option>'); + for (var i=0;i<intLinks.length;i++) { + aSel.push('<option value="glossary:'+intLinks[i]+'">'+intLinks[i]+'</option>'); + } + aSel.push('</select>'); + document.write(aSel.join("")); +} + + + +function setLinkType(type) { + var wSize; + if (type=="1") + { + document.getElementById("protocol").disabled = "disabled"; + document.getElementById("linkUrl").disabled = "disabled"; + document.getElementById("preview").disabled = "disabled"; + document.getElementById("internalLink").disabled = ""; + document.getElementById("glossaryLinks").style.display = "none"; + document.getElementById("pickerPanel").style.display = "none"; + wSize = {w: 420, h: 530 } + } + else if (type=="2") + { + document.getElementById("protocol").disabled = ""; + document.getElementById("linkUrl").disabled = ""; + document.getElementById("preview").disabled = ""; + document.getElementById("internalLink").disabled = "disabled"; + document.getElementById("glossaryLinks").style.display = "none"; + document.getElementById("pickerPanel").style.display = "none"; + wSize = {w: 420, h: 530 } + } + else if (type=="3") + { + if (document.getElementById("picker").src=='') document.getElementById("picker").src = parent.Glizy.tinyMCE_options.media_picker; + document.getElementById("pickerPanel").style.display = "block"; + document.getElementById("linkUrl").disabled = "disabled"; + document.getElementById("internalLink").disabled = "disabled"; + document.getElementById("glossaryLinks").style.display = "none"; + document.getElementById("protocol").disabled = "disabled"; + wSize = {w: 900, h: 530 } + } + else if (type=="4") + { + document.getElementById("protocol").disabled = "disabled"; + document.getElementById("linkUrl").disabled = ""; + document.getElementById("preview").disabled = "disabled"; + document.getElementById("internalLink").disabled = "disabled"; + document.getElementById("glossaryLinks").style.display = "none"; + document.getElementById("pickerPanel").style.display = "none"; + wSize = {w: 420, h: 530 } + } + else if (type=="5") + { + document.getElementById("protocol").disabled = "disabled"; + document.getElementById("linkUrl").disabled = "disabled"; + document.getElementById("preview").disabled = "disabled"; + document.getElementById("internalLink").style.display = "none"; + document.getElementById("glossaryLinks").style.display = "inline"; + document.getElementById("pickerPanel").style.display = "none"; + wSize = {w: 420, h: 530 } + resizeMe(wSize.w, wSize.h); + } + else if (type=="6") + { + document.getElementById("protocol").disabled = "disabled"; + document.getElementById("linkUrl").disabled = ""; + document.getElementById("preview").disabled = "disabled"; + document.getElementById("internalLink").disabled = "disabled"; + document.getElementById("glossaryLinks").style.display = "none"; + document.getElementById("pickerPanel").style.display = "none"; + wSize = {w: 420, h: 530 } + } + + resizeMe( wSize ); +} + +function resizeMe( newSize ) { + var winID = tinyMCEPopup.id; + var wm = tinyMCEPopup.editor.windowManager; + + wm.resizeBy(newSize.w - currentSize.w, newSize.h - currentSize.h, winID); + var left = parseInt( tinymce.DOM.getStyle( winID, 'left' ).replace( 'px', '' ) ); + tinymce.DOM.setStyle( winID, 'left', ( left - (newSize.w - currentSize.w) / 2 ) + 'px' ); + currentSize = newSize; +} + +function previewLink() { + var url = document.getElementById("protocol").value+document.getElementById("linkUrl").value; + if (url) try {window.open(url,"urlTest","")} catch(err) {}; +} + +function init() { + tinyMCEPopup.resizeToInnerSize(); + var formObj = document.forms[0]; + var inst = tinyMCEPopup.editor; + var elm = inst.selection.getNode(); //inst.getFocusElement(); + var action = "insert"; + + elm = inst.dom.getParent(elm, "A"); + if (elm != null && elm.nodeName == "A") + action = "update"; + + formObj.insert.value = tinyMCEPopup.getLang(action, 'Insert', true); + + if (action == "update") { + var href = inst.dom.getAttrib(elm, 'href'); + href = convertURL(href, elm, true); + + // Setup form data + var linkType = 0; + var protocol = 'http://'; + if (href.indexOf("internal:")==0) + { + linkType = 1; + setFormValue('linkUrl', ''); + } + else if (href.indexOf("media:")==0) + { + linkType = 3; + var mediaInfo = href.split(':'); + setFormValue('linkUrl', mediaInfo[2]); + setFormValue('mediaId', mediaInfo[1]); + setFormValue('mediaTitle', mediaInfo[2]); + } + else if (href.indexOf("#")==0) + { + linkType = 4; + setFormValue('linkUrl', href); + } + else if (href.indexOf("glossary:")==0) + { + linkType = 5; + setFormValue('linkUrl', ''); + setFormValue('glossaryLinks', href ); + } + else + { + var regExp = new RegExp("(http://|https://|ftp://|mailto:)(.*)", "gi"); + linkType = href.match( regExp ) ? 2 : 6 ; + if ( linkType == 2 ) + { + protocol = href.replace(regExp, "$1"); + setFormValue('linkUrl', href.replace(protocol,"")); + } + else + { + setFormValue('linkUrl', href ); + } + } + + setFormValue('linkType', String(linkType)); + setLinkType(String(linkType)); + setFormValue('protocol', protocol); + setFormValue('internalLink', linkType==1 ? href:""); + setFormValue('title', inst.dom.getAttrib(elm, 'title')); + setFormValue('id', inst.dom.getAttrib(elm, 'id')); + setFormValue('style', inst.dom.getAttrib(elm, 'style')); + setFormValue('cssclass', inst.dom.getAttrib(elm, 'class')); + setFormValue('dir', inst.dom.getAttrib(elm, 'dir')); + setFormValue('hreflang', inst.dom.getAttrib(elm, 'hreflang')); + setFormValue('lang', inst.dom.getAttrib(elm, 'lang')); + setFormValue('charset', inst.dom.getAttrib(elm, 'charset')); + document.forms[0].elements['relExternal'].checked = tinymce.DOM.getAttrib(elm, 'rel') == "external"; + setFormValue('tabindex', inst.dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : "")); + setFormValue('accesskey', inst.dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : "")); + } + + + window.focus(); +} + +function setFormValue(name, value) { + document.forms[0].elements[name].value = value; +} + + + +function convertURL(url, node, on_save) { + return url; + //return eval("tinyMCEPopup.windowOpener." + tinyMCE.settings['urlconverter_callback'] + "(url, node, on_save);"); +} + +function setAttrib(elm, attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib.toLowerCase()]; + var dom = tinyMCEPopup.editor.dom; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + // Clean up the style + if (attrib == 'style') + value = dom.serializeStyle(dom.parseStyle(value), 'a'); + + dom.setAttrib(elm, attrib, value); +} + +function insertAction() { + var inst = tinyMCEPopup.editor; + var elm, elementArray, i; + + elm = inst.selection.getNode(); + elm = inst.dom.getParent(elm, "A"); + + tinyMCEPopup.execCommand("mceBeginUndoLevel"); + + // Create new anchor elements + if (elm == null) { + inst.getDoc().execCommand("unlink", false, null); + tinyMCEPopup.execCommand("CreateLink", false, "#mce_temp_url#", {skip_undo : 1}); + + elementArray = tinymce.grep(inst.dom.select("a"), function(n) {return inst.dom.getAttrib(n, 'href') == '#mce_temp_url#';}); + for (i=0; i<elementArray.length; i++) + setAllAttribs(elm = elementArray[i]); + } else + setAllAttribs(elm); + + // Don't move caret if selection was image + if (elm.childNodes.length != 1 || elm.firstChild.nodeName != 'IMG') { + inst.focus(); + inst.selection.select(elm); + inst.selection.collapse(0); + tinyMCEPopup.storeSelection(); + } + + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); +} + + + +function setAllAttribs(elm) { + var formObj = document.forms[0]; + var linkUrlObj = document.getElementById("linkUrl"); + var href; + switch (formObj.linkType.value) { + case "1": + href = formObj.internalLink.value; + break; + case "2": + href = formObj.protocol.value+linkUrlObj.value; + break; + case "3": + href = 'media:'+formObj.mediaId.value+":"+formObj.mediaTitle.value; + break; + case "4": + href = (linkUrlObj.value.indexOf('#')!=0 ? '#' : '')+linkUrlObj.value; + break; + case "5": + href = formObj.glossaryLinks.value; + break; + case "6": + href = linkUrlObj.value; + } + if (href) { + href = convertURL(href, elm); + setAttrib(elm, 'href', href); + setAttrib(elm, 'title'); + setAttrib(elm, 'id'); + setAttrib(elm, 'style'); + setAttrib(elm, 'class', formObj.cssclass.value); + setAttrib(elm, 'rel', formObj.elements['relExternal'].checked ? "external" : "" ); + setAttrib(elm, 'charset'); + setAttrib(elm, 'hreflang'); + setAttrib(elm, 'dir'); + setAttrib(elm, 'lang'); + setAttrib(elm, 'tabindex'); + setAttrib(elm, 'accesskey'); + + // Refresh in old MSIE + if (tinyMCE.isMSIE5) + elm.outerHTML = elm.outerHTML; + } + else { + setAttrib(elm, 'href', null); + } +} + + +function getSelectValue(form_obj, field_name) { + var elm = form_obj.elements[field_name]; + + if (elm == null || elm.options == null) + return ""; + + return elm.options[elm.selectedIndex].value; +} + + +function update(i,t) { + var linkUrlObj = document.getElementById("linkUrl"); + var formObj = document.forms[0]; + with (formObj) { + mediaId.value = i; + mediaTitle.value = t; + title.value = t; + } + linkUrlObj.value = t; +} + + +tinyMCEPopup.onInit.add(init); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/langs/en.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/langs/en.js new file mode 100644 index 0000000..625b762 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/langs/en.js @@ -0,0 +1,34 @@ +// UK lang variables + +tinyMCE.addI18n('en.GLZ_link',{ + window_title:"Insert/edit link", + general_legend: 'General properties', + link_type: 'Link type', + internal_link: 'Internal link', + relative_link: 'Relative link', + external_link: 'External link', + media_link: 'Media link', + glossary_link: 'Link to glossary', + link_url: 'Link URL', + title: 'Title', + advanced_legend: 'Advanced properties', + id: 'Id', + style: 'Style', + classes: 'Class', + target_name : 'Target name', + langdir : 'Language direction', + target_langcode : 'Target language', + langcode : 'Language code', + encoding : 'Target character encoding', + mime : 'Target MIME type', + rel : 'Relationship page to target', + rev : 'Relationship target to page', + tabindex : 'Tabindex', + accesskey : 'Accesskey', + ltr : 'Left to right', + rtl : 'Right to left', + not_set: '-- Not set --', + preview: 'Preview', + anchor: 'Anchor', + open_external : 'Open in a new page' +}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/langs/it.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/langs/it.js new file mode 100644 index 0000000..01e3654 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/langs/it.js @@ -0,0 +1,34 @@ +// IT lang variables + +tinyMCE.addI18n('it.GLZ_link',{ + window_title:"Inserisci/modifica link", + general_legend: 'Propriet&agrave generali', + link_type: 'Tipo di link', + internal_link: 'Link interno', + relative_link: 'Link relativo', + external_link: 'Link esterno', + media_link: 'Link media', + glossary_link: 'Link a glossario', + link_url: 'Link URL', + title: 'Titolo', + advanced_legend: 'Propriet&agrave avanzate', + id : 'Id', + style: 'Stile', + classes : 'Classe', + target_name : 'Nome della destinazione', + langdir : 'Direzione del testo', + target_langcode : 'Codifica lingua destinazione', + langcode : 'Codifica lingua', + encoding : 'Codifica caratteri destinazione', + mime : 'Tipo MIME destinazione', + rel : 'Relazione pagina-destinazione', + rev : 'Relazione destinazione-pagina', + tabindex : 'Indice TAB', + accesskey : 'Tasto di accesso', + ltr : 'Da sinistra a destra', + rtl : 'Da destra a sinistra', + not_set: '-- Non impostato --', + preview: 'Anteprima', + anchor: 'Ancora', + open_external : 'Apri in una nuova pagina' +}); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/link.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/link.htm new file mode 100644 index 0000000..cb7b24f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/GLZ_link/link.htm @@ -0,0 +1,111 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#GLZ_link.window_title}</title> + <script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script> + <script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script> + <script language="javascript" type="text/javascript" src="jscripts/functions.js"></script> + <link href="css/GLZ_link.css" rel="stylesheet" type="text/css" /> +</head> +<body id="GLZ_link" onloada="init();" style="display: none"> + <form onsubmit="insertAction();return false;" action="#"> + <input type="hidden" name="mediaId" value="" /> + <input type="hidden" name="mediaTitle" value="" /> + <div class="panel_wrapper" style="width: 380px;"> + <fieldset class="multifieldset"> + <legend>{#GLZ_link.general_legend}</legend> + <table border="0" cellpadding="4" cellspacing="0" width="100%"> + <tr> + <td nowrap="nowrap"><label id="linkTypeLabel" for="linkType">{#GLZ_link.link_type}</label></td> + <td colspan="3" width="100%"><select id="linkType" style="width:100%" onchange="setLinkType(this.value)"><option>---</option><option value="1">{#GLZ_link.internal_link}</option><option value="6">{#GLZ_link.relative_link}</option><option value="2">{#GLZ_link.external_link}</option><option value="3">{#GLZ_link.media_link}</option><option value="5">{#GLZ_link.glossary_link}</option><option value="4">{#GLZ_link.anchor}</option></select></td> + </tr> + <tr> + <td nowrap="nowrap"><label id="linkUrlLabel" for="linkUrl">{#GLZ_link.link_url}</label></td> + <td width="1%"><select id="protocol"><option selected="selected" value="http://">http://</option><option value="https://">https://</option><option value="ftp://">ftp://</option><option value="mailto:">mailto:</option></select></td> + <td><input id="linkUrl" name="linkUrl" style="width:100%" type="text" value="" disabled="disabled" class="ja={suggest:{src:'../../../../../../../admin/ajax.php?pageId=AjaxCatalog&ajaxTarget=glossary',key:'t'}}"/></td> + <td width="1%"><input type="button" id="preview" value="{#GLZ_link.preview}" disabled="disabled" onclick="previewLink()"/></td> + </tr> + <tr> + <td nowrap><label id="internalLinkLabel" for="internalLink">{#GLZ_link.internal_link}</label></td> + <td colspan="3"><script type="text/javascript">renderInternalLinks();</script></td> + </tr> + <tr> + <td nowrap="nowrap"><label id="titleLabel" for="title">{#GLZ_link.title}</label></td> + <td colspan="3"><input id="title" type="text" value="" /></td> + </tr> + <tr> + <td nowrap><label id="relLabel" for="rel">{#GLZ_link.open_external}</label></td> + <td> + <input type="checkbox" id="relExternal" name="nameExternal" value="1" /> + </td> + </tr> + </table> + </fieldset> + <fieldset> + <legend>{#GLZ_link.advanced_legend}</legend> + <table border="0" cellpadding="4" cellspacing="0" width="100%"> + <tr> + <td class="column1"><label id="idlabel" for="id">{#GLZ_link.id}</label></td> + <td><input id="id" name="id" type="text" value="" /></td> + </tr> + <tr> + <td nowrap="nowrap"><label id="styleLabel" for="style">{#GLZ_link.style}</label></td> + <td width="100%"><input id="style" type="text" value="" /></td> + </tr> + <tr id="classRow"> + <td nowrap="nowrap"><label id="classesLabel" for="classlist">{#GLZ_link.classes}</label></td> + <td><input id="cssclass" name="cssclass" type="text" value="" /></td> + </tr> + <tr> + <td class="column1"><label id="dirlabel" for="dir">{#GLZ_link.langdir}</label></td> + <td> + <select id="dir" name="dir"> + <option value="">{#GLZ_link.not_set}</option> + <option value="ltr">{#GLZ_link.ltr}</option> + <option value="rtl">{#GLZ_link.rtl}</option> + </select> + </td> + </tr> + + <tr> + <td><label id="hreflanglabel" for="hreflang">{#GLZ_link.target_langcode}</label></td> + <td><input type="text" id="hreflang" name="hreflang" value="" /></td> + </tr> + + <tr> + <td class="column1"><label id="langlabel" for="lang">{#GLZ_link.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" /> + </td> + </tr> + + <tr> + <td><label id="charsetlabel" for="charset">{#GLZ_link.encoding}</label></td> + <td><input type="text" id="charset" name="charset" value="" /></td> + </tr> + + <tr> + <td nowrap="nowrap"><label id="tabindexLabel" for="tabindex">{#GLZ_link.tabindex}</label></td> + <td><input id="tabindex" type="text" value="" /></td> + </tr> + <tr> + <td nowrap="nowrap"><label id="accesskeyLabel" for="accesskey">{#GLZ_link.accesskey}</label></td> + <td><input id="accesskey" type="text" value="" /></td> + </tr> + </table> + </fieldset> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" onclick="insertAction();" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + + <div id="pickerPanel"> + <iframe id="picker" frameborder="0"></iframe> + </div> + </form> +</body> +</html> + + diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/css/advhr.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/css/advhr.css new file mode 100644 index 0000000..0e22834 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/css/advhr.css @@ -0,0 +1,5 @@ +input.radio {border:1px none #000; background:transparent; vertical-align:middle;} +.panel_wrapper div.current {height:80px;} +#width {width:50px; vertical-align:middle;} +#width2 {width:50px; vertical-align:middle;} +#size {width:100px;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/editor_plugin.js new file mode 100644 index 0000000..4d3b062 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.AdvancedHRPlugin",{init:function(a,b){a.addCommand("mceAdvancedHr",function(){a.windowManager.open({file:b+"/rule.htm",width:250+parseInt(a.getLang("advhr.delta_width",0)),height:160+parseInt(a.getLang("advhr.delta_height",0)),inline:1},{plugin_url:b})});a.addButton("advhr",{title:"advhr.advhr_desc",cmd:"mceAdvancedHr"});a.onNodeChange.add(function(d,c,e){c.setActive("advhr",e.nodeName=="HR")});a.onClick.add(function(c,d){d=d.target;if(d.nodeName==="HR"){c.selection.select(d)}})},getInfo:function(){return{longname:"Advanced HR",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("advhr",tinymce.plugins.AdvancedHRPlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/editor_plugin_src.js new file mode 100644 index 0000000..0c652d3 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/editor_plugin_src.js @@ -0,0 +1,57 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.AdvancedHRPlugin', { + init : function(ed, url) { + // Register commands + ed.addCommand('mceAdvancedHr', function() { + ed.windowManager.open({ + file : url + '/rule.htm', + width : 250 + parseInt(ed.getLang('advhr.delta_width', 0)), + height : 160 + parseInt(ed.getLang('advhr.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('advhr', { + title : 'advhr.advhr_desc', + cmd : 'mceAdvancedHr' + }); + + ed.onNodeChange.add(function(ed, cm, n) { + cm.setActive('advhr', n.nodeName == 'HR'); + }); + + ed.onClick.add(function(ed, e) { + e = e.target; + + if (e.nodeName === 'HR') + ed.selection.select(e); + }); + }, + + getInfo : function() { + return { + longname : 'Advanced HR', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('advhr', tinymce.plugins.AdvancedHRPlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/js/rule.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/js/rule.js new file mode 100644 index 0000000..b6cbd66 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/js/rule.js @@ -0,0 +1,43 @@ +var AdvHRDialog = { + init : function(ed) { + var dom = ed.dom, f = document.forms[0], n = ed.selection.getNode(), w; + + w = dom.getAttrib(n, 'width'); + f.width.value = w ? parseInt(w) : (dom.getStyle('width') || ''); + f.size.value = dom.getAttrib(n, 'size') || parseInt(dom.getStyle('height')) || ''; + f.noshade.checked = !!dom.getAttrib(n, 'noshade') || !!dom.getStyle('border-width'); + selectByValue(f, 'width2', w.indexOf('%') != -1 ? '%' : 'px'); + }, + + update : function() { + var ed = tinyMCEPopup.editor, h, f = document.forms[0], st = ''; + + h = '<hr'; + + if (f.size.value) { + h += ' size="' + f.size.value + '"'; + st += ' height:' + f.size.value + 'px;'; + } + + if (f.width.value) { + h += ' width="' + f.width.value + (f.width2.value == '%' ? '%' : '') + '"'; + st += ' width:' + f.width.value + (f.width2.value == '%' ? '%' : 'px') + ';'; + } + + if (f.noshade.checked) { + h += ' noshade="noshade"'; + st += ' border-width: 1px; border-style: solid; border-color: #CCCCCC; color: #ffffff;'; + } + + if (ed.settings.inline_styles) + h += ' style="' + tinymce.trim(st) + '"'; + + h += ' />'; + + ed.execCommand("mceInsertContent", false, h); + tinyMCEPopup.close(); + } +}; + +tinyMCEPopup.requireLangPack(); +tinyMCEPopup.onInit.add(AdvHRDialog.init, AdvHRDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/de_dlg.js new file mode 100644 index 0000000..7c5143e --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.advhr_dlg',{size:"H\u00f6he",noshade:"Kein Schatten",width:"Breite",normal:"Normal",widthunits:"Einheiten"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/en_dlg.js new file mode 100644 index 0000000..0c3bf15 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.advhr_dlg',{size:"Height",noshade:"No Shadow",width:"Width",normal:"Normal",widthunits:"Units"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/fr_dlg.js new file mode 100644 index 0000000..b4fcd2a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.advhr_dlg',{size:"Hauteur",noshade:"Pas d\'ombre",width:"Largeur",normal:"Normal",widthunits:"Units"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/it_dlg.js new file mode 100644 index 0000000..f013f11 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.advhr_dlg',{size:"Altezza",noshade:"Senza ombreggiatura",width:"Larghezza",normal:"Normal",widthunits:"Units"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/rule.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/rule.htm new file mode 100644 index 0000000..843e1f8 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advhr/rule.htm @@ -0,0 +1,58 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advhr.advhr_desc}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/rule.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <link href="css/advhr.css" rel="stylesheet" type="text/css" /> +</head> +<body role="application"> +<form onsubmit="AdvHRDialog.update();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advhr.advhr_desc}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr role="group" aria-labelledby="width_label"> + <td><label id="width_label" for="width">{#advhr_dlg.width}</label></td> + <td class="nowrap"> + <input id="width" name="width" type="text" value="" class="mceFocus" /> + <span style="display:none;" id="width_unit_label">{#advhr_dlg.widthunits}</span> + <select name="width2" id="width2" aria-labelledby="width_unit_label"> + <option value="">px</option> + <option value="%">%</option> + </select> + </td> + </tr> + <tr> + <td><label for="size">{#advhr_dlg.size}</label></td> + <td><select id="size" name="size"> + <option value="">{#advhr_dlg.normal}</option> + <option value="1">1</option> + <option value="2">2</option> + <option value="3">3</option> + <option value="4">4</option> + <option value="5">5</option> + </select></td> + </tr> + <tr> + <td><label for="noshade">{#advhr_dlg.noshade}</label></td> + <td><input type="checkbox" name="noshade" id="noshade" class="radio" /></td> + </tr> + </table> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/css/advimage.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/css/advimage.css new file mode 100644 index 0000000..0a6251a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/css/advimage.css @@ -0,0 +1,13 @@ +#src_list, #over_list, #out_list {width:280px;} +.mceActionPanel {margin-top:7px;} +.alignPreview {border:1px solid #000; width:140px; height:140px; overflow:hidden; padding:5px;} +.checkbox {border:0;} +.panel_wrapper div.current {height:305px;} +#prev {margin:0; border:1px solid #000; width:428px; height:150px; overflow:auto;} +#align, #classlist {width:150px;} +#width, #height {vertical-align:middle; width:50px; text-align:center;} +#vspace, #hspace, #border {vertical-align:middle; width:30px; text-align:center;} +#class_list {width:180px;} +input {width: 280px;} +#constrain, #onmousemovecheck {width:auto;} +#id, #dir, #lang, #usemap, #longdesc {width:200px;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/editor_plugin.js new file mode 100644 index 0000000..d613a61 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.AdvancedImagePlugin",{init:function(a,b){a.addCommand("mceAdvImage",function(){if(a.dom.getAttrib(a.selection.getNode(),"class","").indexOf("mceItem")!=-1){return}a.windowManager.open({file:b+"/image.htm",width:480+parseInt(a.getLang("advimage.delta_width",0)),height:385+parseInt(a.getLang("advimage.delta_height",0)),inline:1},{plugin_url:b})});a.addButton("image",{title:"advimage.image_desc",cmd:"mceAdvImage"})},getInfo:function(){return{longname:"Advanced image",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("advimage",tinymce.plugins.AdvancedImagePlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/editor_plugin_src.js new file mode 100644 index 0000000..d2678cb --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/editor_plugin_src.js @@ -0,0 +1,50 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.AdvancedImagePlugin', { + init : function(ed, url) { + // Register commands + ed.addCommand('mceAdvImage', function() { + // Internal image object like a flash placeholder + if (ed.dom.getAttrib(ed.selection.getNode(), 'class', '').indexOf('mceItem') != -1) + return; + + ed.windowManager.open({ + file : url + '/image.htm', + width : 480 + parseInt(ed.getLang('advimage.delta_width', 0)), + height : 385 + parseInt(ed.getLang('advimage.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('image', { + title : 'advimage.image_desc', + cmd : 'mceAdvImage' + }); + }, + + getInfo : function() { + return { + longname : 'Advanced image', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('advimage', tinymce.plugins.AdvancedImagePlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/image.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/image.htm new file mode 100644 index 0000000..ed16b3d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/image.htm @@ -0,0 +1,235 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advimage_dlg.dialog_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/image.js"></script> + <link href="css/advimage.css" rel="stylesheet" type="text/css" /> +</head> +<body id="advimage" style="display: none" role="application" aria-labelledby="app_title"> + <span id="app_title" style="display:none">{#advimage_dlg.dialog_title}</span> + <form onsubmit="ImageDialog.insert();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advimage_dlg.tab_general}</a></span></li> + <li id="appearance_tab" aria-controls="appearance_panel"><span><a href="javascript:mcTabs.displayTab('appearance_tab','appearance_panel');" onmousedown="return false;">{#advimage_dlg.tab_appearance}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#advimage_dlg.tab_advanced}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#advimage_dlg.general}</legend> + + <table role="presentation" class="properties"> + <tr> + <td class="column1"><label id="srclabel" for="src">{#advimage_dlg.src}</label></td> + <td colspan="2"><table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input name="src" type="text" id="src" value="" class="mceFocus" onchange="ImageDialog.showPreviewImage(this.value);" aria-required="true" /></td> + <td id="srcbrowsercontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td><label for="src_list">{#advimage_dlg.image_list}</label></td> + <td><select id="src_list" name="src_list" onchange="document.getElementById('src').value=this.options[this.selectedIndex].value;document.getElementById('alt').value=this.options[this.selectedIndex].text;document.getElementById('title').value=this.options[this.selectedIndex].text;ImageDialog.showPreviewImage(this.options[this.selectedIndex].value);"><option value=""></option></select></td> + </tr> + <tr> + <td class="column1"><label id="altlabel" for="alt">{#advimage_dlg.alt}</label></td> + <td colspan="2"><input id="alt" name="alt" type="text" value="" /></td> + </tr> + <tr> + <td class="column1"><label id="titlelabel" for="title">{#advimage_dlg.title}</label></td> + <td colspan="2"><input id="title" name="title" type="text" value="" /></td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#advimage_dlg.preview}</legend> + <div id="prev"></div> + </fieldset> + </div> + + <div id="appearance_panel" class="panel"> + <fieldset> + <legend>{#advimage_dlg.tab_appearance}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label id="alignlabel" for="align">{#advimage_dlg.align}</label></td> + <td><select id="align" name="align" onchange="ImageDialog.updateStyle('align');ImageDialog.changeAppearance();"> + <option value="">{#not_set}</option> + <option value="baseline">{#advimage_dlg.align_baseline}</option> + <option value="top">{#advimage_dlg.align_top}</option> + <option value="middle">{#advimage_dlg.align_middle}</option> + <option value="bottom">{#advimage_dlg.align_bottom}</option> + <option value="text-top">{#advimage_dlg.align_texttop}</option> + <option value="text-bottom">{#advimage_dlg.align_textbottom}</option> + <option value="left">{#advimage_dlg.align_left}</option> + <option value="right">{#advimage_dlg.align_right}</option> + </select> + </td> + <td rowspan="6" valign="top"> + <div class="alignPreview"> + <img id="alignSampleImg" src="img/sample.gif" alt="{#advimage_dlg.example_img}" /> + Lorem ipsum, Dolor sit amet, consectetuer adipiscing loreum ipsum edipiscing elit, sed diam + nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.Loreum ipsum + edipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam + erat volutpat. + </div> + </td> + </tr> + + <tr role="group" aria-labelledby="widthlabel"> + <td class="column1"><label id="widthlabel" for="width">{#advimage_dlg.dimensions}</label></td> + <td class="nowrap"> + <span style="display:none" id="width_voiceLabel">{#advimage_dlg.width}</span> + <input name="width" type="text" id="width" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeHeight();" aria-labelledby="width_voiceLabel" /> x + <span style="display:none" id="height_voiceLabel">{#advimage_dlg.height}</span> + <input name="height" type="text" id="height" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeWidth();" aria-labelledby="height_voiceLabel" /> px + </td> + </tr> + + <tr> + <td>&nbsp;</td> + <td><table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="constrain" type="checkbox" name="constrain" class="checkbox" /></td> + <td><label id="constrainlabel" for="constrain">{#advimage_dlg.constrain_proportions}</label></td> + </tr> + </table></td> + </tr> + + <tr> + <td class="column1"><label id="vspacelabel" for="vspace">{#advimage_dlg.vspace}</label></td> + <td><input name="vspace" type="text" id="vspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" /> + </td> + </tr> + + <tr> + <td class="column1"><label id="hspacelabel" for="hspace">{#advimage_dlg.hspace}</label></td> + <td><input name="hspace" type="text" id="hspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" /></td> + </tr> + + <tr> + <td class="column1"><label id="borderlabel" for="border">{#advimage_dlg.border}</label></td> + <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" /></td> + </tr> + + <tr> + <td><label for="class_list">{#class_name}</label></td> + <td colspan="2"><select id="class_list" name="class_list" class="mceEditableSelect"><option value=""></option></select></td> + </tr> + + <tr> + <td class="column1"><label id="stylelabel" for="style">{#advimage_dlg.style}</label></td> + <td colspan="2"><input id="style" name="style" type="text" value="" onchange="ImageDialog.changeAppearance();" /></td> + </tr> + + <!-- <tr> + <td class="column1"><label id="classeslabel" for="classes">{#advimage_dlg.classes}</label></td> + <td colspan="2"><input id="classes" name="classes" type="text" value="" onchange="selectByValue(this.form,'classlist',this.value,true);" /></td> + </tr> --> + </table> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#advimage_dlg.swap_image}</legend> + + <input type="checkbox" id="onmousemovecheck" name="onmousemovecheck" class="checkbox" onclick="ImageDialog.setSwapImage(this.checked);" aria-controls="onmouseoversrc onmouseoutsrc" /> + <label id="onmousemovechecklabel" for="onmousemovecheck">{#advimage_dlg.alt_image}</label> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0" width="100%"> + <tr> + <td class="column1"><label id="onmouseoversrclabel" for="onmouseoversrc">{#advimage_dlg.mouseover}</label></td> + <td><table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="onmouseoversrc" name="onmouseoversrc" type="text" value="" /></td> + <td id="onmouseoversrccontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td><label for="over_list">{#advimage_dlg.image_list}</label></td> + <td><select id="over_list" name="over_list" onchange="document.getElementById('onmouseoversrc').value=this.options[this.selectedIndex].value;"><option value=""></option></select></td> + </tr> + <tr> + <td class="column1"><label id="onmouseoutsrclabel" for="onmouseoutsrc">{#advimage_dlg.mouseout}</label></td> + <td class="column2"><table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="onmouseoutsrc" name="onmouseoutsrc" type="text" value="" /></td> + <td id="onmouseoutsrccontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td><label for="out_list">{#advimage_dlg.image_list}</label></td> + <td><select id="out_list" name="out_list" onchange="document.getElementById('onmouseoutsrc').value=this.options[this.selectedIndex].value;"><option value=""></option></select></td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#advimage_dlg.misc}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label id="idlabel" for="id">{#advimage_dlg.id}</label></td> + <td><input id="id" name="id" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label id="dirlabel" for="dir">{#advimage_dlg.langdir}</label></td> + <td> + <select id="dir" name="dir" onchange="ImageDialog.changeAppearance();"> + <option value="">{#not_set}</option> + <option value="ltr">{#advimage_dlg.ltr}</option> + <option value="rtl">{#advimage_dlg.rtl}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label id="langlabel" for="lang">{#advimage_dlg.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" /> + </td> + </tr> + + <tr> + <td class="column1"><label id="usemaplabel" for="usemap">{#advimage_dlg.map}</label></td> + <td> + <input id="usemap" name="usemap" type="text" value="" /> + </td> + </tr> + + <tr> + <td class="column1"><label id="longdesclabel" for="longdesc">{#advimage_dlg.long_desc}</label></td> + <td><table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="longdesc" name="longdesc" type="text" value="" /></td> + <td id="longdesccontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/img/sample.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/img/sample.gif new file mode 100644 index 0000000000000000000000000000000000000000..53bf6890b507741c10910c9e2217ad8247b98e8d GIT binary patch literal 1624 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 WE}n@{k&&Vq!n33@nsG^i002Ao7W&ix literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/js/image.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/js/image.js new file mode 100644 index 0000000..546b69c --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/js/image.js @@ -0,0 +1,462 @@ +var ImageDialog = { + preInit : function() { + var url; + + tinyMCEPopup.requireLangPack(); + + if (url = tinyMCEPopup.getParam("external_image_list_url")) + document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>'); + }, + + init : function(ed) { + var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, dom = ed.dom, n = ed.selection.getNode(), fl = tinyMCEPopup.getParam('external_image_list', 'tinyMCEImageList'); + + tinyMCEPopup.resizeToInnerSize(); + this.fillClassList('class_list'); + this.fillFileList('src_list', fl); + this.fillFileList('over_list', fl); + this.fillFileList('out_list', fl); + TinyMCE_EditableSelects.init(); + + if (n.nodeName == 'IMG') { + nl.src.value = dom.getAttrib(n, 'src'); + nl.width.value = dom.getAttrib(n, 'width'); + nl.height.value = dom.getAttrib(n, 'height'); + nl.alt.value = dom.getAttrib(n, 'alt'); + nl.title.value = dom.getAttrib(n, 'title'); + nl.vspace.value = this.getAttrib(n, 'vspace'); + nl.hspace.value = this.getAttrib(n, 'hspace'); + nl.border.value = this.getAttrib(n, 'border'); + selectByValue(f, 'align', this.getAttrib(n, 'align')); + selectByValue(f, 'class_list', dom.getAttrib(n, 'class'), true, true); + nl.style.value = dom.getAttrib(n, 'style'); + nl.id.value = dom.getAttrib(n, 'id'); + nl.dir.value = dom.getAttrib(n, 'dir'); + nl.lang.value = dom.getAttrib(n, 'lang'); + nl.usemap.value = dom.getAttrib(n, 'usemap'); + nl.longdesc.value = dom.getAttrib(n, 'longdesc'); + nl.insert.value = ed.getLang('update'); + + if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseover'))) + nl.onmouseoversrc.value = dom.getAttrib(n, 'onmouseover').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1'); + + if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseout'))) + nl.onmouseoutsrc.value = dom.getAttrib(n, 'onmouseout').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1'); + + if (ed.settings.inline_styles) { + // Move attribs to styles + if (dom.getAttrib(n, 'align')) + this.updateStyle('align'); + + if (dom.getAttrib(n, 'hspace')) + this.updateStyle('hspace'); + + if (dom.getAttrib(n, 'border')) + this.updateStyle('border'); + + if (dom.getAttrib(n, 'vspace')) + this.updateStyle('vspace'); + } + } + + // Setup browse button + document.getElementById('srcbrowsercontainer').innerHTML = getBrowserHTML('srcbrowser','src','image','theme_advanced_image'); + if (isVisible('srcbrowser')) + document.getElementById('src').style.width = '260px'; + + // Setup browse button + document.getElementById('onmouseoversrccontainer').innerHTML = getBrowserHTML('overbrowser','onmouseoversrc','image','theme_advanced_image'); + if (isVisible('overbrowser')) + document.getElementById('onmouseoversrc').style.width = '260px'; + + // Setup browse button + document.getElementById('onmouseoutsrccontainer').innerHTML = getBrowserHTML('outbrowser','onmouseoutsrc','image','theme_advanced_image'); + if (isVisible('outbrowser')) + document.getElementById('onmouseoutsrc').style.width = '260px'; + + // If option enabled default contrain proportions to checked + if (ed.getParam("advimage_constrain_proportions", true)) + f.constrain.checked = true; + + // Check swap image if valid data + if (nl.onmouseoversrc.value || nl.onmouseoutsrc.value) + this.setSwapImage(true); + else + this.setSwapImage(false); + + this.changeAppearance(); + this.showPreviewImage(nl.src.value, 1); + }, + + insert : function(file, title) { + var ed = tinyMCEPopup.editor, t = this, f = document.forms[0]; + + if (f.src.value === '') { + if (ed.selection.getNode().nodeName == 'IMG') { + ed.dom.remove(ed.selection.getNode()); + ed.execCommand('mceRepaint'); + } + + tinyMCEPopup.close(); + return; + } + + if (tinyMCEPopup.getParam("accessibility_warnings", 1)) { + if (!f.alt.value) { + tinyMCEPopup.confirm(tinyMCEPopup.getLang('advimage_dlg.missing_alt'), function(s) { + if (s) + t.insertAndClose(); + }); + + return; + } + } + + t.insertAndClose(); + }, + + insertAndClose : function() { + var ed = tinyMCEPopup.editor, f = document.forms[0], nl = f.elements, v, args = {}, el; + + tinyMCEPopup.restoreSelection(); + + // Fixes crash in Safari + if (tinymce.isWebKit) + ed.getWin().focus(); + + if (!ed.settings.inline_styles) { + args = { + vspace : nl.vspace.value, + hspace : nl.hspace.value, + border : nl.border.value, + align : getSelectValue(f, 'align') + }; + } else { + // Remove deprecated values + args = { + vspace : '', + hspace : '', + border : '', + align : '' + }; + } + + tinymce.extend(args, { + src : nl.src.value.replace(/ /g, '%20'), + width : nl.width.value, + height : nl.height.value, + alt : nl.alt.value, + title : nl.title.value, + 'class' : getSelectValue(f, 'class_list'), + style : nl.style.value, + id : nl.id.value, + dir : nl.dir.value, + lang : nl.lang.value, + usemap : nl.usemap.value, + longdesc : nl.longdesc.value + }); + + args.onmouseover = args.onmouseout = ''; + + if (f.onmousemovecheck.checked) { + if (nl.onmouseoversrc.value) + args.onmouseover = "this.src='" + nl.onmouseoversrc.value + "';"; + + if (nl.onmouseoutsrc.value) + args.onmouseout = "this.src='" + nl.onmouseoutsrc.value + "';"; + } + + el = ed.selection.getNode(); + + if (el && el.nodeName == 'IMG') { + ed.dom.setAttribs(el, args); + } else { + tinymce.each(args, function(value, name) { + if (value === "") { + delete args[name]; + } + }); + + ed.execCommand('mceInsertContent', false, tinyMCEPopup.editor.dom.createHTML('img', args), {skip_undo : 1}); + ed.undoManager.add(); + } + + tinyMCEPopup.editor.execCommand('mceRepaint'); + tinyMCEPopup.editor.focus(); + tinyMCEPopup.close(); + }, + + getAttrib : function(e, at) { + var ed = tinyMCEPopup.editor, dom = ed.dom, v, v2; + + if (ed.settings.inline_styles) { + switch (at) { + case 'align': + if (v = dom.getStyle(e, 'float')) + return v; + + if (v = dom.getStyle(e, 'vertical-align')) + return v; + + break; + + case 'hspace': + v = dom.getStyle(e, 'margin-left') + v2 = dom.getStyle(e, 'margin-right'); + + if (v && v == v2) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + + case 'vspace': + v = dom.getStyle(e, 'margin-top') + v2 = dom.getStyle(e, 'margin-bottom'); + if (v && v == v2) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + + case 'border': + v = 0; + + tinymce.each(['top', 'right', 'bottom', 'left'], function(sv) { + sv = dom.getStyle(e, 'border-' + sv + '-width'); + + // False or not the same as prev + if (!sv || (sv != v && v !== 0)) { + v = 0; + return false; + } + + if (sv) + v = sv; + }); + + if (v) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + } + } + + if (v = dom.getAttrib(e, at)) + return v; + + return ''; + }, + + setSwapImage : function(st) { + var f = document.forms[0]; + + f.onmousemovecheck.checked = st; + setBrowserDisabled('overbrowser', !st); + setBrowserDisabled('outbrowser', !st); + + if (f.over_list) + f.over_list.disabled = !st; + + if (f.out_list) + f.out_list.disabled = !st; + + f.onmouseoversrc.disabled = !st; + f.onmouseoutsrc.disabled = !st; + }, + + fillClassList : function(id) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl; + + if (v = tinyMCEPopup.getParam('theme_advanced_styles')) { + cl = []; + + tinymce.each(v.split(';'), function(v) { + var p = v.split('='); + + cl.push({'title' : p[0], 'class' : p[1]}); + }); + } else + cl = tinyMCEPopup.editor.dom.getClasses(); + + if (cl.length > 0) { + lst.options.length = 0; + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), ''); + + tinymce.each(cl, function(o) { + lst.options[lst.options.length] = new Option(o.title || o['class'], o['class']); + }); + } else + dom.remove(dom.getParent(id, 'tr')); + }, + + fillFileList : function(id, l) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl; + + l = typeof(l) === 'function' ? l() : window[l]; + lst.options.length = 0; + + if (l && l.length > 0) { + lst.options[lst.options.length] = new Option('', ''); + + tinymce.each(l, function(o) { + lst.options[lst.options.length] = new Option(o[0], o[1]); + }); + } else + dom.remove(dom.getParent(id, 'tr')); + }, + + resetImageData : function() { + var f = document.forms[0]; + + f.elements.width.value = f.elements.height.value = ''; + }, + + updateImageData : function(img, st) { + var f = document.forms[0]; + + if (!st) { + f.elements.width.value = img.width; + f.elements.height.value = img.height; + } + + this.preloadImg = img; + }, + + changeAppearance : function() { + var ed = tinyMCEPopup.editor, f = document.forms[0], img = document.getElementById('alignSampleImg'); + + if (img) { + if (ed.getParam('inline_styles')) { + ed.dom.setAttrib(img, 'style', f.style.value); + } else { + img.align = f.align.value; + img.border = f.border.value; + img.hspace = f.hspace.value; + img.vspace = f.vspace.value; + } + } + }, + + changeHeight : function() { + var f = document.forms[0], tp, t = this; + + if (!f.constrain.checked || !t.preloadImg) { + return; + } + + if (f.width.value == "" || f.height.value == "") + return; + + tp = (parseInt(f.width.value) / parseInt(t.preloadImg.width)) * t.preloadImg.height; + f.height.value = tp.toFixed(0); + }, + + changeWidth : function() { + var f = document.forms[0], tp, t = this; + + if (!f.constrain.checked || !t.preloadImg) { + return; + } + + if (f.width.value == "" || f.height.value == "") + return; + + tp = (parseInt(f.height.value) / parseInt(t.preloadImg.height)) * t.preloadImg.width; + f.width.value = tp.toFixed(0); + }, + + updateStyle : function(ty) { + var dom = tinyMCEPopup.dom, b, bStyle, bColor, v, isIE = tinymce.isIE, f = document.forms[0], img = dom.create('img', {style : dom.get('style').value}); + + if (tinyMCEPopup.editor.settings.inline_styles) { + // Handle align + if (ty == 'align') { + dom.setStyle(img, 'float', ''); + dom.setStyle(img, 'vertical-align', ''); + + v = getSelectValue(f, 'align'); + if (v) { + if (v == 'left' || v == 'right') + dom.setStyle(img, 'float', v); + else + img.style.verticalAlign = v; + } + } + + // Handle border + if (ty == 'border') { + b = img.style.border ? img.style.border.split(' ') : []; + bStyle = dom.getStyle(img, 'border-style'); + bColor = dom.getStyle(img, 'border-color'); + + dom.setStyle(img, 'border', ''); + + v = f.border.value; + if (v || v == '0') { + if (v == '0') + img.style.border = isIE ? '0' : '0 none none'; + else { + if (b.length == 3 && b[isIE ? 2 : 1]) + bStyle = b[isIE ? 2 : 1]; + else if (!bStyle || bStyle == 'none') + bStyle = 'solid'; + if (b.length == 3 && b[isIE ? 0 : 2]) + bColor = b[isIE ? 0 : 2]; + else if (!bColor || bColor == 'none') + bColor = 'black'; + img.style.border = v + 'px ' + bStyle + ' ' + bColor; + } + } + } + + // Handle hspace + if (ty == 'hspace') { + dom.setStyle(img, 'marginLeft', ''); + dom.setStyle(img, 'marginRight', ''); + + v = f.hspace.value; + if (v) { + img.style.marginLeft = v + 'px'; + img.style.marginRight = v + 'px'; + } + } + + // Handle vspace + if (ty == 'vspace') { + dom.setStyle(img, 'marginTop', ''); + dom.setStyle(img, 'marginBottom', ''); + + v = f.vspace.value; + if (v) { + img.style.marginTop = v + 'px'; + img.style.marginBottom = v + 'px'; + } + } + + // Merge + dom.get('style').value = dom.serializeStyle(dom.parseStyle(img.style.cssText), 'img'); + } + }, + + changeMouseMove : function() { + }, + + showPreviewImage : function(u, st) { + if (!u) { + tinyMCEPopup.dom.setHTML('prev', ''); + return; + } + + if (!st && tinyMCEPopup.getParam("advimage_update_dimensions_onchange", true)) + this.resetImageData(); + + u = tinyMCEPopup.editor.documentBaseURI.toAbsolute(u); + + if (!st) + tinyMCEPopup.dom.setHTML('prev', '<img id="previewImg" src="' + u + '" border="0" onload="ImageDialog.updateImageData(this);" onerror="ImageDialog.resetImageData();" />'); + else + tinyMCEPopup.dom.setHTML('prev', '<img id="previewImg" src="' + u + '" border="0" onload="ImageDialog.updateImageData(this, 1);" />'); + } +}; + +ImageDialog.preInit(); +tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/de_dlg.js new file mode 100644 index 0000000..fc0f6d1 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.advimage_dlg',{"image_list":"Bilderliste","align_right":"Rechts","align_left":"Links","align_textbottom":"Unten im Text","align_texttop":"Oben im Text","align_bottom":"Unten","align_middle":"Mittig","align_top":"Oben","align_baseline":"Zeile",align:"Ausrichtung",hspace:"Horizontaler Abstand",vspace:"Vertikaler Abstand",dimensions:"Ausma\u00dfe",border:"Rahmen",list:"Bilderliste",alt:"Beschreibung",src:"Adresse","dialog_title":"Bild einf\u00fcgen/ver\u00e4ndern","missing_alt":"Wollen Sie wirklich keine Beschreibung eingeben? Bestimmte Benutzer mit k\u00f6rperlichen Einschr\u00e4nkungen k\u00f6nnen so nicht darauf zugreifen, ebenso solche, die einen Textbrowser benutzen oder die Anzeige von Bildern deaktiviert haben.","example_img":"Vorschau auf das Aussehen",misc:"Verschiedenes",mouseout:"bei keinem Mauskontakt",mouseover:"bei Mauskontakt","alt_image":"Alternatives Bild","swap_image":"Bild austauschen",map:"Image-Map",id:"ID",rtl:"Rechts nach links",ltr:"Links nach rechts",classes:"Klassen",style:"Format","long_desc":"Ausf\u00fchrliche Beschreibung",langcode:"Sprachcode",langdir:"Schriftrichtung","constrain_proportions":"Seitenverh\u00e4ltnis beibehalten",preview:"Vorschau",title:"Titel",general:"Allgemein","tab_advanced":"Erweitert","tab_appearance":"Aussehen","tab_general":"Allgemein",width:"Breite",height:"H\u00f6he"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/en_dlg.js new file mode 100644 index 0000000..5f122e2 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.advimage_dlg',{"image_list":"Image List","align_right":"Right","align_left":"Left","align_textbottom":"Text Bottom","align_texttop":"Text Top","align_bottom":"Bottom","align_middle":"Middle","align_top":"Top","align_baseline":"Baseline",align:"Alignment",hspace:"Horizontal Space",vspace:"Vertical Space",dimensions:"Dimensions",border:"Border",list:"Image List",alt:"Image Description",src:"Image URL","dialog_title":"Insert/Edit Image","missing_alt":"Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.","example_img":"Appearance Preview Image",misc:"Miscellaneous",mouseout:"For Mouse Out",mouseover:"For Mouse Over","alt_image":"Alternative Image","swap_image":"Swap Image",map:"Image Map",id:"ID",rtl:"Right to Left",ltr:"Left to Right",classes:"Classes",style:"Style","long_desc":"Long Description Link",langcode:"Language Code",langdir:"Language Direction","constrain_proportions":"Constrain Proportions",preview:"Preview",title:"Title",general:"General","tab_advanced":"Advanced","tab_appearance":"Appearance","tab_general":"General",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/fr_dlg.js new file mode 100644 index 0000000..ecf3d95 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.advimage_dlg',{"image_list":"Liste d\'images","align_right":"Droite (flottant)","align_left":"Gauche (flottant)","align_textbottom":"Texte en bas","align_texttop":"Texte en haut","align_bottom":"En bas","align_middle":"Au milieu","align_top":"En haut","align_baseline":"Normal",align:"Alignement",hspace:"Espacement horizontal",vspace:"Espacement vertical",dimensions:"Dimensions",border:"Bordure",list:"Liste d\'images",alt:"Description de l\'image",src:"URL de l\'image","dialog_title":"Ins\u00e9rer / \u00e9diter une image","missing_alt":"\u00cates-vous s\u00fbr de vouloir continuer sans d\u00e9finir de description pour l\'image ? Sans elle, l\'image peut ne pas \u00eatre accessible \u00e0 certains utilisateurs handicap\u00e9s, ceux utilisant un navigateur texte ou ceux qui naviguent sans affichage des images.","example_img":"Apparence de l\'image",misc:"Divers",mouseout:"\u00e0 la sortie de la souris",mouseover:"au survol de la souris","alt_image":"Image alternative","swap_image":"Image de remplacement",map:"Image cliquable",id:"Id",rtl:"De droite \u00e0 gauche",ltr:"De gauche \u00e0 droite",classes:"Classes",style:"Style","long_desc":"Description longue du lien",langcode:"Code de la langue",langdir:"Sens de lecture","constrain_proportions":"Conserver les proportions",preview:"Pr\u00e9visualisation",title:"Titre",general:"G\u00e9n\u00e9ral","tab_advanced":"Avanc\u00e9","tab_appearance":"Apparence","tab_general":"G\u00e9n\u00e9ral",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/it_dlg.js new file mode 100644 index 0000000..684369d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advimage/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.advimage_dlg',{"image_list":"Lista immagini","align_right":"A destra","align_left":"A sinistra","align_textbottom":"In basso al testo","align_texttop":"In alto al testo","align_bottom":"In basso","align_middle":"In mezzo","align_top":"In alto","align_baseline":"Alla base",align:"Allineamento",hspace:"Spaziatura orizzontale",vspace:"Spaziatura verticale",dimensions:"Dimensioni",border:"Bordo",list:"Lista immagini",alt:"Descrizione immagine",src:"URL immagine","dialog_title":"Inserisci/modifica immagine","missing_alt":"Sicuro di continuare senza includere una descrizione dell\'immagine? Senza di essa l\'immagine pu\u00f2 non essere accessibile ad alcuni utenti con disabilit\u00e0, o per coloro che usano un browser testuale oppure che hanno disabilitato la visualizzazione delle immagini nel loro browser.","example_img":"Anteprima aspetto immagine",misc:"Impostazioni varie",mouseout:"quando mouse fuori",mouseover:"quando mouse sopra","alt_image":"Immagine alternativa","swap_image":"Sostituisci immagine",map:"Immagine come mappa",id:"Id",rtl:"Destra verso sinistraa",ltr:"Sinistra verso destra",classes:"Classe",style:"Stile","long_desc":"Descrizione del collegamento",langcode:"codice lingua",langdir:"Direzione testo","constrain_proportions":"Mantieni proporzioni",preview:"Anteprima",title:"Titolo",general:"Generale","tab_advanced":"Avanzate","tab_appearance":"Aspetto","tab_general":"Generale",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/css/advlink.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/css/advlink.css new file mode 100644 index 0000000..1436431 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/css/advlink.css @@ -0,0 +1,8 @@ +.mceLinkList, .mceAnchorList, #targetlist {width:280px;} +.mceActionPanel {margin-top:7px;} +.panel_wrapper div.current {height:320px;} +#classlist, #title, #href {width:280px;} +#popupurl, #popupname {width:200px;} +#popupwidth, #popupheight, #popupleft, #popuptop {width:30px;vertical-align:middle;text-align:center;} +#id, #style, #classes, #target, #dir, #hreflang, #lang, #charset, #type, #rel, #rev, #tabindex, #accesskey {width:200px;} +#events_panel input {width:200px;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/editor_plugin.js new file mode 100644 index 0000000..983fe5a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.AdvancedLinkPlugin",{init:function(a,b){this.editor=a;a.addCommand("mceAdvLink",function(){var c=a.selection;if(c.isCollapsed()&&!a.dom.getParent(c.getNode(),"A")){return}a.windowManager.open({file:b+"/link.htm",width:480+parseInt(a.getLang("advlink.delta_width",0)),height:400+parseInt(a.getLang("advlink.delta_height",0)),inline:1},{plugin_url:b})});a.addButton("link",{title:"advlink.link_desc",cmd:"mceAdvLink"});a.addShortcut("ctrl+k","advlink.advlink_desc","mceAdvLink");a.onNodeChange.add(function(d,c,f,e){c.setDisabled("link",e&&f.nodeName!="A");c.setActive("link",f.nodeName=="A"&&!f.name)})},getInfo:function(){return{longname:"Advanced link",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("advlink",tinymce.plugins.AdvancedLinkPlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/editor_plugin_src.js new file mode 100644 index 0000000..14e46a7 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/editor_plugin_src.js @@ -0,0 +1,61 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.AdvancedLinkPlugin', { + init : function(ed, url) { + this.editor = ed; + + // Register commands + ed.addCommand('mceAdvLink', function() { + var se = ed.selection; + + // No selection and not in link + if (se.isCollapsed() && !ed.dom.getParent(se.getNode(), 'A')) + return; + + ed.windowManager.open({ + file : url + '/link.htm', + width : 480 + parseInt(ed.getLang('advlink.delta_width', 0)), + height : 400 + parseInt(ed.getLang('advlink.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('link', { + title : 'advlink.link_desc', + cmd : 'mceAdvLink' + }); + + ed.addShortcut('ctrl+k', 'advlink.advlink_desc', 'mceAdvLink'); + + ed.onNodeChange.add(function(ed, cm, n, co) { + cm.setDisabled('link', co && n.nodeName != 'A'); + cm.setActive('link', n.nodeName == 'A' && !n.name); + }); + }, + + getInfo : function() { + return { + longname : 'Advanced link', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('advlink', tinymce.plugins.AdvancedLinkPlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/js/advlink.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/js/advlink.js new file mode 100644 index 0000000..837c937 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/js/advlink.js @@ -0,0 +1,532 @@ +/* Functions for the advlink plugin popup */ + +tinyMCEPopup.requireLangPack(); + +var templates = { + "window.open" : "window.open('${url}','${target}','${options}')" +}; + +function preinit() { + var url; + + if (url = tinyMCEPopup.getParam("external_link_list_url")) + document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>'); +} + +function changeClass() { + var f = document.forms[0]; + + f.classes.value = getSelectValue(f, 'classlist'); +} + +function init() { + tinyMCEPopup.resizeToInnerSize(); + + var formObj = document.forms[0]; + var inst = tinyMCEPopup.editor; + var elm = inst.selection.getNode(); + var action = "insert"; + var html; + + document.getElementById('hrefbrowsercontainer').innerHTML = getBrowserHTML('hrefbrowser','href','file','advlink'); + document.getElementById('popupurlbrowsercontainer').innerHTML = getBrowserHTML('popupurlbrowser','popupurl','file','advlink'); + document.getElementById('targetlistcontainer').innerHTML = getTargetListHTML('targetlist','target'); + + // Link list + html = getLinkListHTML('linklisthref','href'); + if (html == "") + document.getElementById("linklisthrefrow").style.display = 'none'; + else + document.getElementById("linklisthrefcontainer").innerHTML = html; + + // Anchor list + html = getAnchorListHTML('anchorlist','href'); + if (html == "") + document.getElementById("anchorlistrow").style.display = 'none'; + else + document.getElementById("anchorlistcontainer").innerHTML = html; + + // Resize some elements + if (isVisible('hrefbrowser')) + document.getElementById('href').style.width = '260px'; + + if (isVisible('popupurlbrowser')) + document.getElementById('popupurl').style.width = '180px'; + + elm = inst.dom.getParent(elm, "A"); + if (elm != null && elm.nodeName == "A") + action = "update"; + + formObj.insert.value = tinyMCEPopup.getLang(action, 'Insert', true); + + setPopupControlsDisabled(true); + + if (action == "update") { + var href = inst.dom.getAttrib(elm, 'href'); + var onclick = inst.dom.getAttrib(elm, 'onclick'); + + // Setup form data + setFormValue('href', href); + setFormValue('title', inst.dom.getAttrib(elm, 'title')); + setFormValue('id', inst.dom.getAttrib(elm, 'id')); + setFormValue('style', inst.dom.getAttrib(elm, "style")); + setFormValue('rel', inst.dom.getAttrib(elm, 'rel')); + setFormValue('rev', inst.dom.getAttrib(elm, 'rev')); + setFormValue('charset', inst.dom.getAttrib(elm, 'charset')); + setFormValue('hreflang', inst.dom.getAttrib(elm, 'hreflang')); + setFormValue('dir', inst.dom.getAttrib(elm, 'dir')); + setFormValue('lang', inst.dom.getAttrib(elm, 'lang')); + setFormValue('tabindex', inst.dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : "")); + setFormValue('accesskey', inst.dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : "")); + setFormValue('type', inst.dom.getAttrib(elm, 'type')); + setFormValue('onfocus', inst.dom.getAttrib(elm, 'onfocus')); + setFormValue('onblur', inst.dom.getAttrib(elm, 'onblur')); + setFormValue('onclick', onclick); + setFormValue('ondblclick', inst.dom.getAttrib(elm, 'ondblclick')); + setFormValue('onmousedown', inst.dom.getAttrib(elm, 'onmousedown')); + setFormValue('onmouseup', inst.dom.getAttrib(elm, 'onmouseup')); + setFormValue('onmouseover', inst.dom.getAttrib(elm, 'onmouseover')); + setFormValue('onmousemove', inst.dom.getAttrib(elm, 'onmousemove')); + setFormValue('onmouseout', inst.dom.getAttrib(elm, 'onmouseout')); + setFormValue('onkeypress', inst.dom.getAttrib(elm, 'onkeypress')); + setFormValue('onkeydown', inst.dom.getAttrib(elm, 'onkeydown')); + setFormValue('onkeyup', inst.dom.getAttrib(elm, 'onkeyup')); + setFormValue('target', inst.dom.getAttrib(elm, 'target')); + setFormValue('classes', inst.dom.getAttrib(elm, 'class')); + + // Parse onclick data + if (onclick != null && onclick.indexOf('window.open') != -1) + parseWindowOpen(onclick); + else + parseFunction(onclick); + + // Select by the values + selectByValue(formObj, 'dir', inst.dom.getAttrib(elm, 'dir')); + selectByValue(formObj, 'rel', inst.dom.getAttrib(elm, 'rel')); + selectByValue(formObj, 'rev', inst.dom.getAttrib(elm, 'rev')); + selectByValue(formObj, 'linklisthref', href); + + if (href.charAt(0) == '#') + selectByValue(formObj, 'anchorlist', href); + + addClassesToList('classlist', 'advlink_styles'); + + selectByValue(formObj, 'classlist', inst.dom.getAttrib(elm, 'class'), true); + selectByValue(formObj, 'targetlist', inst.dom.getAttrib(elm, 'target'), true); + } else + addClassesToList('classlist', 'advlink_styles'); +} + +function checkPrefix(n) { + if (n.value && Validator.isEmail(n) && !/^\s*mailto:/i.test(n.value) && confirm(tinyMCEPopup.getLang('advlink_dlg.is_email'))) + n.value = 'mailto:' + n.value; + + if (/^\s*www\./i.test(n.value) && confirm(tinyMCEPopup.getLang('advlink_dlg.is_external'))) + n.value = 'http://' + n.value; +} + +function setFormValue(name, value) { + document.forms[0].elements[name].value = value; +} + +function parseWindowOpen(onclick) { + var formObj = document.forms[0]; + + // Preprocess center code + if (onclick.indexOf('return false;') != -1) { + formObj.popupreturn.checked = true; + onclick = onclick.replace('return false;', ''); + } else + formObj.popupreturn.checked = false; + + var onClickData = parseLink(onclick); + + if (onClickData != null) { + formObj.ispopup.checked = true; + setPopupControlsDisabled(false); + + var onClickWindowOptions = parseOptions(onClickData['options']); + var url = onClickData['url']; + + formObj.popupname.value = onClickData['target']; + formObj.popupurl.value = url; + formObj.popupwidth.value = getOption(onClickWindowOptions, 'width'); + formObj.popupheight.value = getOption(onClickWindowOptions, 'height'); + + formObj.popupleft.value = getOption(onClickWindowOptions, 'left'); + formObj.popuptop.value = getOption(onClickWindowOptions, 'top'); + + if (formObj.popupleft.value.indexOf('screen') != -1) + formObj.popupleft.value = "c"; + + if (formObj.popuptop.value.indexOf('screen') != -1) + formObj.popuptop.value = "c"; + + formObj.popuplocation.checked = getOption(onClickWindowOptions, 'location') == "yes"; + formObj.popupscrollbars.checked = getOption(onClickWindowOptions, 'scrollbars') == "yes"; + formObj.popupmenubar.checked = getOption(onClickWindowOptions, 'menubar') == "yes"; + formObj.popupresizable.checked = getOption(onClickWindowOptions, 'resizable') == "yes"; + formObj.popuptoolbar.checked = getOption(onClickWindowOptions, 'toolbar') == "yes"; + formObj.popupstatus.checked = getOption(onClickWindowOptions, 'status') == "yes"; + formObj.popupdependent.checked = getOption(onClickWindowOptions, 'dependent') == "yes"; + + buildOnClick(); + } +} + +function parseFunction(onclick) { + var formObj = document.forms[0]; + var onClickData = parseLink(onclick); + + // TODO: Add stuff here +} + +function getOption(opts, name) { + return typeof(opts[name]) == "undefined" ? "" : opts[name]; +} + +function setPopupControlsDisabled(state) { + var formObj = document.forms[0]; + + formObj.popupname.disabled = state; + formObj.popupurl.disabled = state; + formObj.popupwidth.disabled = state; + formObj.popupheight.disabled = state; + formObj.popupleft.disabled = state; + formObj.popuptop.disabled = state; + formObj.popuplocation.disabled = state; + formObj.popupscrollbars.disabled = state; + formObj.popupmenubar.disabled = state; + formObj.popupresizable.disabled = state; + formObj.popuptoolbar.disabled = state; + formObj.popupstatus.disabled = state; + formObj.popupreturn.disabled = state; + formObj.popupdependent.disabled = state; + + setBrowserDisabled('popupurlbrowser', state); +} + +function parseLink(link) { + link = link.replace(new RegExp('&#39;', 'g'), "'"); + + var fnName = link.replace(new RegExp("\\s*([A-Za-z0-9\.]*)\\s*\\(.*", "gi"), "$1"); + + // Is function name a template function + var template = templates[fnName]; + if (template) { + // Build regexp + var variableNames = template.match(new RegExp("'?\\$\\{[A-Za-z0-9\.]*\\}'?", "gi")); + var regExp = "\\s*[A-Za-z0-9\.]*\\s*\\("; + var replaceStr = ""; + for (var i=0; i<variableNames.length; i++) { + // Is string value + if (variableNames[i].indexOf("'${") != -1) + regExp += "'(.*)'"; + else // Number value + regExp += "([0-9]*)"; + + replaceStr += "$" + (i+1); + + // Cleanup variable name + variableNames[i] = variableNames[i].replace(new RegExp("[^A-Za-z0-9]", "gi"), ""); + + if (i != variableNames.length-1) { + regExp += "\\s*,\\s*"; + replaceStr += "<delim>"; + } else + regExp += ".*"; + } + + regExp += "\\);?"; + + // Build variable array + var variables = []; + variables["_function"] = fnName; + var variableValues = link.replace(new RegExp(regExp, "gi"), replaceStr).split('<delim>'); + for (var i=0; i<variableNames.length; i++) + variables[variableNames[i]] = variableValues[i]; + + return variables; + } + + return null; +} + +function parseOptions(opts) { + if (opts == null || opts == "") + return []; + + // Cleanup the options + opts = opts.toLowerCase(); + opts = opts.replace(/;/g, ","); + opts = opts.replace(/[^0-9a-z=,]/g, ""); + + var optionChunks = opts.split(','); + var options = []; + + for (var i=0; i<optionChunks.length; i++) { + var parts = optionChunks[i].split('='); + + if (parts.length == 2) + options[parts[0]] = parts[1]; + } + + return options; +} + +function buildOnClick() { + var formObj = document.forms[0]; + + if (!formObj.ispopup.checked) { + formObj.onclick.value = ""; + return; + } + + var onclick = "window.open('"; + var url = formObj.popupurl.value; + + onclick += url + "','"; + onclick += formObj.popupname.value + "','"; + + if (formObj.popuplocation.checked) + onclick += "location=yes,"; + + if (formObj.popupscrollbars.checked) + onclick += "scrollbars=yes,"; + + if (formObj.popupmenubar.checked) + onclick += "menubar=yes,"; + + if (formObj.popupresizable.checked) + onclick += "resizable=yes,"; + + if (formObj.popuptoolbar.checked) + onclick += "toolbar=yes,"; + + if (formObj.popupstatus.checked) + onclick += "status=yes,"; + + if (formObj.popupdependent.checked) + onclick += "dependent=yes,"; + + if (formObj.popupwidth.value != "") + onclick += "width=" + formObj.popupwidth.value + ","; + + if (formObj.popupheight.value != "") + onclick += "height=" + formObj.popupheight.value + ","; + + if (formObj.popupleft.value != "") { + if (formObj.popupleft.value != "c") + onclick += "left=" + formObj.popupleft.value + ","; + else + onclick += "left='+(screen.availWidth/2-" + (formObj.popupwidth.value/2) + ")+',"; + } + + if (formObj.popuptop.value != "") { + if (formObj.popuptop.value != "c") + onclick += "top=" + formObj.popuptop.value + ","; + else + onclick += "top='+(screen.availHeight/2-" + (formObj.popupheight.value/2) + ")+',"; + } + + if (onclick.charAt(onclick.length-1) == ',') + onclick = onclick.substring(0, onclick.length-1); + + onclick += "');"; + + if (formObj.popupreturn.checked) + onclick += "return false;"; + + // tinyMCE.debug(onclick); + + formObj.onclick.value = onclick; + + if (formObj.href.value == "") + formObj.href.value = url; +} + +function setAttrib(elm, attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib.toLowerCase()]; + var dom = tinyMCEPopup.editor.dom; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + // Clean up the style + if (attrib == 'style') + value = dom.serializeStyle(dom.parseStyle(value), 'a'); + + dom.setAttrib(elm, attrib, value); +} + +function getAnchorListHTML(id, target) { + var ed = tinyMCEPopup.editor, nodes = ed.dom.select('a'), name, i, len, html = ""; + + for (i=0, len=nodes.length; i<len; i++) { + if ((name = ed.dom.getAttrib(nodes[i], "name")) != "") + html += '<option value="#' + name + '">' + name + '</option>'; + } + + if (html == "") + return ""; + + html = '<select id="' + id + '" name="' + id + '" class="mceAnchorList"' + + ' onchange="this.form.' + target + '.value=this.options[this.selectedIndex].value"' + + '>' + + '<option value="">---</option>' + + html + + '</select>'; + + return html; +} + +function insertAction() { + var inst = tinyMCEPopup.editor; + var elm, elementArray, i; + + elm = inst.selection.getNode(); + checkPrefix(document.forms[0].href); + + elm = inst.dom.getParent(elm, "A"); + + // Remove element if there is no href + if (!document.forms[0].href.value) { + i = inst.selection.getBookmark(); + inst.dom.remove(elm, 1); + inst.selection.moveToBookmark(i); + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); + return; + } + + // Create new anchor elements + if (elm == null) { + inst.getDoc().execCommand("unlink", false, null); + tinyMCEPopup.execCommand("mceInsertLink", false, "#mce_temp_url#", {skip_undo : 1}); + + elementArray = tinymce.grep(inst.dom.select("a"), function(n) {return inst.dom.getAttrib(n, 'href') == '#mce_temp_url#';}); + for (i=0; i<elementArray.length; i++) + setAllAttribs(elm = elementArray[i]); + } else + setAllAttribs(elm); + + // Don't move caret if selection was image + if (elm.childNodes.length != 1 || elm.firstChild.nodeName != 'IMG') { + inst.focus(); + inst.selection.select(elm); + inst.selection.collapse(0); + tinyMCEPopup.storeSelection(); + } + + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); +} + +function setAllAttribs(elm) { + var formObj = document.forms[0]; + var href = formObj.href.value.replace(/ /g, '%20'); + var target = getSelectValue(formObj, 'targetlist'); + + setAttrib(elm, 'href', href); + setAttrib(elm, 'title'); + setAttrib(elm, 'target', target == '_self' ? '' : target); + setAttrib(elm, 'id'); + setAttrib(elm, 'style'); + setAttrib(elm, 'class', getSelectValue(formObj, 'classlist')); + setAttrib(elm, 'rel'); + setAttrib(elm, 'rev'); + setAttrib(elm, 'charset'); + setAttrib(elm, 'hreflang'); + setAttrib(elm, 'dir'); + setAttrib(elm, 'lang'); + setAttrib(elm, 'tabindex'); + setAttrib(elm, 'accesskey'); + setAttrib(elm, 'type'); + setAttrib(elm, 'onfocus'); + setAttrib(elm, 'onblur'); + setAttrib(elm, 'onclick'); + setAttrib(elm, 'ondblclick'); + setAttrib(elm, 'onmousedown'); + setAttrib(elm, 'onmouseup'); + setAttrib(elm, 'onmouseover'); + setAttrib(elm, 'onmousemove'); + setAttrib(elm, 'onmouseout'); + setAttrib(elm, 'onkeypress'); + setAttrib(elm, 'onkeydown'); + setAttrib(elm, 'onkeyup'); + + // Refresh in old MSIE + if (tinyMCE.isMSIE5) + elm.outerHTML = elm.outerHTML; +} + +function getSelectValue(form_obj, field_name) { + var elm = form_obj.elements[field_name]; + + if (!elm || elm.options == null || elm.selectedIndex == -1) + return ""; + + return elm.options[elm.selectedIndex].value; +} + +function getLinkListHTML(elm_id, target_form_element, onchange_func) { + if (typeof(tinyMCELinkList) == "undefined" || tinyMCELinkList.length == 0) + return ""; + + var html = ""; + + html += '<select id="' + elm_id + '" name="' + elm_id + '"'; + html += ' class="mceLinkList" onfoc2us="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value='; + html += 'this.options[this.selectedIndex].value;'; + + if (typeof(onchange_func) != "undefined") + html += onchange_func + '(\'' + target_form_element + '\',this.options[this.selectedIndex].text,this.options[this.selectedIndex].value);'; + + html += '"><option value="">---</option>'; + + for (var i=0; i<tinyMCELinkList.length; i++) + html += '<option value="' + tinyMCELinkList[i][1] + '">' + tinyMCELinkList[i][0] + '</option>'; + + html += '</select>'; + + return html; + + // tinyMCE.debug('-- image list start --', html, '-- image list end --'); +} + +function getTargetListHTML(elm_id, target_form_element) { + var targets = tinyMCEPopup.getParam('theme_advanced_link_targets', '').split(';'); + var html = ''; + + html += '<select id="' + elm_id + '" name="' + elm_id + '" onf2ocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value='; + html += 'this.options[this.selectedIndex].value;">'; + html += '<option value="_self">' + tinyMCEPopup.getLang('advlink_dlg.target_same') + '</option>'; + html += '<option value="_blank">' + tinyMCEPopup.getLang('advlink_dlg.target_blank') + ' (_blank)</option>'; + html += '<option value="_parent">' + tinyMCEPopup.getLang('advlink_dlg.target_parent') + ' (_parent)</option>'; + html += '<option value="_top">' + tinyMCEPopup.getLang('advlink_dlg.target_top') + ' (_top)</option>'; + + for (var i=0; i<targets.length; i++) { + var key, value; + + if (targets[i] == "") + continue; + + key = targets[i].split('=')[0]; + value = targets[i].split('=')[1]; + + html += '<option value="' + key + '">' + value + ' (' + key + ')</option>'; + } + + html += '</select>'; + + return html; +} + +// While loading +preinit(); +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/de_dlg.js new file mode 100644 index 0000000..bb0d3e3 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.advlink_dlg',{"target_name":"Name der Zielseite",classes:"Klassen",style:"Format",id:"ID","popup_position":"Position (X/Y)",langdir:"Schriftrichtung","popup_size":"Gr\u00f6\u00dfe","popup_dependent":"Vom Elternfenster abh\u00e4ngig <br /> (nur Mozilla/Firefox) ","popup_resizable":"Vergr\u00f6\u00dfern des Fenster zulassen","popup_location":"Adressleiste anzeigen","popup_menubar":"Browsermen\u00fc anzeigen","popup_toolbar":"Werkzeugleisten anzeigen","popup_statusbar":"Statusleiste anzeigen","popup_scrollbars":"Scrollbalken anzeigen","popup_return":"Link trotz Popup folgen","popup_name":"Name des Fensters","popup_url":"Popup-Adresse",popup:"JavaScript-Popup","target_blank":"In neuem Fenster \u00f6ffnen","target_top":"Im obersten Frame \u00f6ffnen (sprengt das Frameset)","target_parent":"Im \u00fcbergeordneten Fenster/Frame \u00f6ffnen","target_same":"Im selben Fenster/Frame \u00f6ffnen","anchor_names":"Anker","popup_opts":"Optionen","advanced_props":"Erweiterte Eigenschaften","event_props":"Ereignisse","popup_props":"Popup-Eigenschaften","general_props":"Allemeine Eigenschaften","advanced_tab":"Erweitert","events_tab":"Ereignisse","popup_tab":"Popup","general_tab":"Allgemein",list:"Linkliste","is_external":"Diese Adresse scheint ein externer Link zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"http://\" voranstellen?","is_email":"Diese Adresse scheint eine E-Mail-Adresse zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"mailto:\" voranstellen?",titlefield:"Titel",target:"Fenster",url:"Adresse",title:"Link einf\u00fcgen/bearbeiten","link_list":"Linkliste",rtl:"Rechts nach links",ltr:"Links nach rechts",accesskey:"Tastenk\u00fcrzel",tabindex:"Tabindex",rev:"Beziehung des Linkziels zur Seite",rel:"Beziehung der Seite zum Linkziel",mime:"MIME-Type der Zielseite",encoding:"Zeichenkodierung der Zielseite",langcode:"Sprachcode","target_langcode":"Sprache der Zielseite",width:"Breite",height:"H\u00f6he"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/en_dlg.js new file mode 100644 index 0000000..3169a56 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.advlink_dlg',{"target_name":"Target Name",classes:"Classes",style:"Style",id:"ID","popup_position":"Position (X/Y)",langdir:"Language Direction","popup_size":"Size","popup_dependent":"Dependent (Mozilla/Firefox Only)","popup_resizable":"Make Window Resizable","popup_location":"Show Location Bar","popup_menubar":"Show Menu Bar","popup_toolbar":"Show Toolbars","popup_statusbar":"Show Status Bar","popup_scrollbars":"Show Scrollbars","popup_return":"Insert \'return false\'","popup_name":"Window Name","popup_url":"Popup URL",popup:"JavaScript Popup","target_blank":"Open in New Window","target_top":"Open in Top Frame (Replaces All Frames)","target_parent":"Open in Parent Window/Frame","target_same":"Open in This Window/Frame","anchor_names":"Anchors","popup_opts":"Options","advanced_props":"Advanced Properties","event_props":"Events","popup_props":"Popup Properties","general_props":"General Properties","advanced_tab":"Advanced","events_tab":"Events","popup_tab":"Popup","general_tab":"General",list:"Link List","is_external":"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?","is_email":"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",titlefield:"Title",target:"Target",url:"Link URL",title:"Insert/Edit Link","link_list":"Link List",rtl:"Right to Left",ltr:"Left to Right",accesskey:"AccessKey",tabindex:"TabIndex",rev:"Relationship Target to Page",rel:"Relationship Page to Target",mime:"Target MIME Type",encoding:"Target Character Encoding",langcode:"Language Code","target_langcode":"Target Language",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/fr_dlg.js new file mode 100644 index 0000000..f22e960 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.advlink_dlg',{"target_name":"Nom de la cible",classes:"Classes",style:"Style",id:"Id","popup_position":"Position (X/Y)",langdir:"Sens de lecture","popup_size":"Taille","popup_dependent":"D\u00e9pendante (seulement sous Mozilla/Firefox)","popup_resizable":"Autoriser le redimensionnement de la fen\u00eatre","popup_location":"Afficher la barre d\'adresse","popup_menubar":"Afficher la barre de menu","popup_toolbar":"Afficher la barre d\'outils","popup_statusbar":"Afficher la barre d\'\u00e9tat","popup_scrollbars":"Afficher les ascenseurs","popup_return":"Ins\u00e9rer \'return false\'","popup_name":"Nom de la fen\u00eatre","popup_url":"URL de la popup",popup:"Popup Javascript","target_blank":"Ouvrir dans une nouvelle fen\u00eatre","target_top":"Ouvrir dans le cadre principal (remplace tous les cadres)","target_parent":"Ouvrir dans la fen\u00eatre / le cadre parent","target_same":"Ouvrir dans cette fen\u00eatre / dans ce cadre","anchor_names":"Ancres","popup_opts":"Options","advanced_props":"Propri\u00e9t\u00e9s avanc\u00e9es","event_props":"\u00c9v\u00e8nements","popup_props":"Propri\u00e9t\u00e9s de la popup","general_props":"Propri\u00e9t\u00e9s g\u00e9n\u00e9rales","advanced_tab":"Avanc\u00e9","events_tab":"\u00c9v\u00e8nements","popup_tab":"Popup","general_tab":"G\u00e9n\u00e9ral",list:"Liste de liens","is_external":"L\'URL que vous avez saisie semble \u00eatre une adresse web externe. Souhaitez-vous ajouter le pr\u00e9fixe \u00ab http:// \u00bb ?","is_email":"L\'URL que vous avez saisie semble \u00eatre une adresse e-mail, souhaitez-vous ajouter le pr\u00e9fixe \u00ab mailto: \u00bb ?",titlefield:"Titre",target:"Cible",url:"URL du lien",title:"Ins\u00e9rer / \u00e9diter un lien","link_list":"Liste des liens",rtl:"Droite \u00e0 gauche",ltr:"Gauche \u00e0 droite",accesskey:"Touche d\'acc\u00e8s rapide",tabindex:"Tabindex",rev:"Relation de la cible \u00e0 la page",rel:"Relation de la page \u00e0 la cible",mime:"Type MIME de la cible",encoding:"Encodage de la cible",langcode:"Code de la langue","target_langcode":"Langue de la cible",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/it_dlg.js new file mode 100644 index 0000000..1a59f88 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.advlink_dlg',{"target_name":"Nome target",classes:"Classe",style:"Stile",id:"Id","popup_position":"Posizione (X/Y)",langdir:"Direzione del testo","popup_size":"Dimensioni","popup_dependent":"Dipendente (Solo in Mozilla/Firefox)","popup_resizable":"Rendi la finestra ridimensionabile","popup_location":"Mostra barra navigazione","popup_menubar":"Mostra barra menu","popup_toolbar":"Mostra barre strumenti","popup_statusbar":"Mostra barra di stato","popup_scrollbars":"Mostra barre di scorrimento","popup_return":"Inserisci \'return false\'","popup_name":"Nome finestra","popup_url":"URL Popup",popup:"Popup Javascript","target_blank":"Apri in una nuova finestra","target_top":"Apri nella cornice superiore (sostituisce tutte le cornici)","target_parent":"Apri nella finestra / cornice genitore","target_same":"Apri in questa finestra / cornice","anchor_names":"Ancore","popup_opts":"Opzioni","advanced_props":"Propriet\u00e0 avanzate","event_props":"Eventi","popup_props":"Propriet\u00e0 popup","general_props":"Propriet\u00e0 generali","advanced_tab":"Avanzate","events_tab":"Eventi","popup_tab":"Popup","general_tab":"Generale",list:"Lista collegamenti","is_external":"L\'URL inserito sembra essere un link esterno. Aggiungere il necessario prefisso http:// ?","is_email":"L\'URL inserito sembra essere un indirizzo email. Aggiungere il necessario prefisso mailto: ?",titlefield:"Titolo",target:"Target",url:"URL collegamento",title:"Inserisci/modifica link","link_list":"Lista collegamenti",rtl:"Destra verso sinistra",ltr:"Sinistra verso destra",accesskey:"Carattere di accesso",tabindex:"Indice tabulazione",rev:"Relazione da target a pagina",rel:"Relazione da pagina a target",mime:"Tipo MIME del target",encoding:"Codifica carattere del target",langcode:"Lingua","target_langcode":"Lingua del target",width:"Width",height:"Height"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/link.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/link.htm new file mode 100644 index 0000000..8ab7c2a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlink/link.htm @@ -0,0 +1,338 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advlink_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="js/advlink.js"></script> + <link href="css/advlink.css" rel="stylesheet" type="text/css" /> +</head> +<body id="advlink" style="display: none" role="application" onload="javascript:mcTabs.displayTab('general_tab','general_panel', true);" aria-labelledby="app_label"> + <span class="mceVoiceLabel" id="app_label" style="display:none;">{#advlink_dlg.title}</span> + <form onsubmit="insertAction();return false;" action="#"> + <div class="tabs" role="presentation"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel" ><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advlink_dlg.general_tab}</a></span></li> + <li id="popup_tab" aria-controls="popup_panel" ><span><a href="javascript:mcTabs.displayTab('popup_tab','popup_panel');" onmousedown="return false;">{#advlink_dlg.popup_tab}</a></span></li> + <li id="events_tab" aria-controls="events_panel"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#advlink_dlg.events_tab}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#advlink_dlg.advanced_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper" role="presentation"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#advlink_dlg.general_props}</legend> + + <table border="0" cellpadding="4" cellspacing="0" role="presentation"> + <tr> + <td class="nowrap"><label id="hreflabel" for="href">{#advlink_dlg.url}</label></td> + <td><table border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="href" name="href" type="text" class="mceFocus" value="" onchange="selectByValue(this.form,'linklisthref',this.value);" aria-required="true" /></td> + <td id="hrefbrowsercontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr id="linklisthrefrow"> + <td class="column1"><label for="linklisthref">{#advlink_dlg.list}</label></td> + <td colspan="2" id="linklisthrefcontainer"><select id="linklisthref"><option value=""></option></select></td> + </tr> + <tr id="anchorlistrow"> + <td class="column1"><label for="anchorlist">{#advlink_dlg.anchor_names}</label></td> + <td colspan="2" id="anchorlistcontainer"><select id="anchorlist"><option value=""></option></select></td> + </tr> + <tr> + <td><label id="targetlistlabel" for="targetlist">{#advlink_dlg.target}</label></td> + <td id="targetlistcontainer"><select id="targetlist"><option value=""></option></select></td> + </tr> + <tr> + <td class="nowrap"><label id="titlelabel" for="title">{#advlink_dlg.titlefield}</label></td> + <td><input id="title" name="title" type="text" value="" /></td> + </tr> + <tr> + <td><label id="classlabel" for="classlist">{#class_name}</label></td> + <td> + <select id="classlist" name="classlist" onchange="changeClass();"> + <option value="" selected="selected">{#not_set}</option> + </select> + </td> + </tr> + </table> + </fieldset> + </div> + + <div id="popup_panel" class="panel"> + <fieldset> + <legend>{#advlink_dlg.popup_props}</legend> + + <input type="checkbox" id="ispopup" name="ispopup" class="radio" onclick="setPopupControlsDisabled(!this.checked);buildOnClick();" /> + <label id="ispopuplabel" for="ispopup">{#advlink_dlg.popup}</label> + + <table border="0" cellpadding="0" cellspacing="4" role="presentation" > + <tr> + <td class="nowrap"><label for="popupurl">{#advlink_dlg.popup_url}</label>&nbsp;</td> + <td> + <table border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" name="popupurl" id="popupurl" value="" onchange="buildOnClick();" /></td> + <td id="popupurlbrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + <tr> + <td class="nowrap"><label for="popupname">{#advlink_dlg.popup_name}</label>&nbsp;</td> + <td><input type="text" name="popupname" id="popupname" value="" onchange="buildOnClick();" /></td> + </tr> + <tr role="group" aria-labelledby="popup_size_label"> + <td class="nowrap"><label id="popup_size_label">{#advlink_dlg.popup_size}</label>&nbsp;</td> + <td class="nowrap"> + <span style="display:none" id="width_voiceLabel">{#advlink_dlg.width}</span> + <input type="text" id="popupwidth" name="popupwidth" value="" onchange="buildOnClick();" aria-labelledby="width_voiceLabel" /> x + <span style="display:none" id="height_voiceLabel">{#advlink_dlg.height}</span> + <input type="text" id="popupheight" name="popupheight" value="" onchange="buildOnClick();" aria-labelledby="height_voiceLabel" /> px + </td> + </tr> + <tr role="group" aria-labelledby="popup_position_label center_hint"> + <td class="nowrap" id="labelleft"><label id="popup_position_label">{#advlink_dlg.popup_position}</label>&nbsp;</td> + <td class="nowrap"> + <span style="display:none" id="x_voiceLabel">X</span> + <input type="text" id="popupleft" name="popupleft" value="" onchange="buildOnClick();" aria-labelledby="x_voiceLabel" /> / + <span style="display:none" id="y_voiceLabel">Y</span> + <input type="text" id="popuptop" name="popuptop" value="" onchange="buildOnClick();" aria-labelledby="y_voiceLabel" /> <span id="center_hint">(c /c = center)</span> + </td> + </tr> + </table> + + <fieldset> + <legend>{#advlink_dlg.popup_opts}</legend> + + <table border="0" cellpadding="0" cellspacing="4" role="presentation" > + <tr> + <td><input type="checkbox" id="popuplocation" name="popuplocation" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popuplocationlabel" for="popuplocation">{#advlink_dlg.popup_location}</label></td> + <td><input type="checkbox" id="popupscrollbars" name="popupscrollbars" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popupscrollbarslabel" for="popupscrollbars">{#advlink_dlg.popup_scrollbars}</label></td> + </tr> + <tr> + <td><input type="checkbox" id="popupmenubar" name="popupmenubar" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popupmenubarlabel" for="popupmenubar">{#advlink_dlg.popup_menubar}</label></td> + <td><input type="checkbox" id="popupresizable" name="popupresizable" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popupresizablelabel" for="popupresizable">{#advlink_dlg.popup_resizable}</label></td> + </tr> + <tr> + <td><input type="checkbox" id="popuptoolbar" name="popuptoolbar" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popuptoolbarlabel" for="popuptoolbar">{#advlink_dlg.popup_toolbar}</label></td> + <td><input type="checkbox" id="popupdependent" name="popupdependent" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popupdependentlabel" for="popupdependent">{#advlink_dlg.popup_dependent}</label></td> + </tr> + <tr> + <td><input type="checkbox" id="popupstatus" name="popupstatus" class="checkbox" onchange="buildOnClick();" /></td> + <td class="nowrap"><label id="popupstatuslabel" for="popupstatus">{#advlink_dlg.popup_statusbar}</label></td> + <td><input type="checkbox" id="popupreturn" name="popupreturn" class="checkbox" onchange="buildOnClick();" checked="checked" /></td> + <td class="nowrap"><label id="popupreturnlabel" for="popupreturn">{#advlink_dlg.popup_return}</label></td> + </tr> + </table> + </fieldset> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#advlink_dlg.advanced_props}</legend> + + <table border="0" cellpadding="0" cellspacing="4" role="presentation" > + <tr> + <td class="column1"><label id="idlabel" for="id">{#advlink_dlg.id}</label></td> + <td><input id="id" name="id" type="text" value="" /></td> + </tr> + + <tr> + <td><label id="stylelabel" for="style">{#advlink_dlg.style}</label></td> + <td><input type="text" id="style" name="style" value="" /></td> + </tr> + + <tr> + <td><label id="classeslabel" for="classes">{#advlink_dlg.classes}</label></td> + <td><input type="text" id="classes" name="classes" value="" onchange="selectByValue(this.form,'classlist',this.value,true);" /></td> + </tr> + + <tr> + <td><label id="targetlabel" for="target">{#advlink_dlg.target_name}</label></td> + <td><input type="text" id="target" name="target" value="" onchange="selectByValue(this.form,'targetlist',this.value,true);" /></td> + </tr> + + <tr> + <td class="column1"><label id="dirlabel" for="dir">{#advlink_dlg.langdir}</label></td> + <td> + <select id="dir" name="dir"> + <option value="">{#not_set}</option> + <option value="ltr">{#advlink_dlg.ltr}</option> + <option value="rtl">{#advlink_dlg.rtl}</option> + </select> + </td> + </tr> + + <tr> + <td><label id="hreflanglabel" for="hreflang">{#advlink_dlg.target_langcode}</label></td> + <td><input type="text" id="hreflang" name="hreflang" value="" /></td> + </tr> + + <tr> + <td class="column1"><label id="langlabel" for="lang">{#advlink_dlg.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" /> + </td> + </tr> + + <tr> + <td><label id="charsetlabel" for="charset">{#advlink_dlg.encoding}</label></td> + <td><input type="text" id="charset" name="charset" value="" /></td> + </tr> + + <tr> + <td><label id="typelabel" for="type">{#advlink_dlg.mime}</label></td> + <td><input type="text" id="type" name="type" value="" /></td> + </tr> + + <tr> + <td><label id="rellabel" for="rel">{#advlink_dlg.rel}</label></td> + <td><select id="rel" name="rel"> + <option value="">{#not_set}</option> + <option value="lightbox">Lightbox</option> + <option value="alternate">Alternate</option> + <option value="designates">Designates</option> + <option value="stylesheet">Stylesheet</option> + <option value="start">Start</option> + <option value="next">Next</option> + <option value="prev">Prev</option> + <option value="contents">Contents</option> + <option value="index">Index</option> + <option value="glossary">Glossary</option> + <option value="copyright">Copyright</option> + <option value="chapter">Chapter</option> + <option value="subsection">Subsection</option> + <option value="appendix">Appendix</option> + <option value="help">Help</option> + <option value="bookmark">Bookmark</option> + <option value="nofollow">No Follow</option> + <option value="tag">Tag</option> + </select> + </td> + </tr> + + <tr> + <td><label id="revlabel" for="rev">{#advlink_dlg.rev}</label></td> + <td><select id="rev" name="rev"> + <option value="">{#not_set}</option> + <option value="alternate">Alternate</option> + <option value="designates">Designates</option> + <option value="stylesheet">Stylesheet</option> + <option value="start">Start</option> + <option value="next">Next</option> + <option value="prev">Prev</option> + <option value="contents">Contents</option> + <option value="index">Index</option> + <option value="glossary">Glossary</option> + <option value="copyright">Copyright</option> + <option value="chapter">Chapter</option> + <option value="subsection">Subsection</option> + <option value="appendix">Appendix</option> + <option value="help">Help</option> + <option value="bookmark">Bookmark</option> + </select> + </td> + </tr> + + <tr> + <td><label id="tabindexlabel" for="tabindex">{#advlink_dlg.tabindex}</label></td> + <td><input type="text" id="tabindex" name="tabindex" value="" /></td> + </tr> + + <tr> + <td><label id="accesskeylabel" for="accesskey">{#advlink_dlg.accesskey}</label></td> + <td><input type="text" id="accesskey" name="accesskey" value="" /></td> + </tr> + </table> + </fieldset> + </div> + + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#advlink_dlg.event_props}</legend> + + <table border="0" cellpadding="0" cellspacing="4" role="presentation" > + <tr> + <td class="column1"><label for="onfocus">onfocus</label></td> + <td><input id="onfocus" name="onfocus" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onblur">onblur</label></td> + <td><input id="onblur" name="onblur" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onclick">onclick</label></td> + <td><input id="onclick" name="onclick" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="ondblclick">ondblclick</label></td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onmousedown">onmousedown</label></td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onmouseup">onmouseup</label></td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onmouseover">onmouseover</label></td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onmousemove">onmousemove</label></td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onmouseout">onmouseout</label></td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onkeypress">onkeypress</label></td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onkeydown">onkeydown</label></td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" /></td> + </tr> + + <tr> + <td class="column1"><label for="onkeyup">onkeyup</label></td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advlist/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlist/editor_plugin.js new file mode 100644 index 0000000..57ecce6 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlist/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.each;tinymce.create("tinymce.plugins.AdvListPlugin",{init:function(b,c){var d=this;d.editor=b;function e(g){var f=[];a(g.split(/,/),function(h){f.push({title:"advlist."+(h=="default"?"def":h.replace(/-/g,"_")),styles:{listStyleType:h=="default"?"":h}})});return f}d.numlist=b.getParam("advlist_number_styles")||e("default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman");d.bullist=b.getParam("advlist_bullet_styles")||e("default,circle,disc,square");if(tinymce.isIE&&/MSIE [2-7]/.test(navigator.userAgent)){d.isIE7=true}},createControl:function(d,b){var f=this,e,i,g=f.editor;if(d=="numlist"||d=="bullist"){if(f[d][0].title=="advlist.def"){i=f[d][0]}function c(j,l){var k=true;a(l.styles,function(n,m){if(g.dom.getStyle(j,m)!=n){k=false;return false}});return k}function h(){var k,l=g.dom,j=g.selection;k=l.getParent(j.getNode(),"ol,ul");if(!k||k.nodeName==(d=="bullist"?"OL":"UL")||c(k,i)){g.execCommand(d=="bullist"?"InsertUnorderedList":"InsertOrderedList")}if(i){k=l.getParent(j.getNode(),"ol,ul");if(k){l.setStyles(k,i.styles);k.removeAttribute("data-mce-style")}}g.focus()}e=b.createSplitButton(d,{title:"advanced."+d+"_desc","class":"mce_"+d,onclick:function(){h()}});e.onRenderMenu.add(function(j,k){k.onHideMenu.add(function(){if(f.bookmark){g.selection.moveToBookmark(f.bookmark);f.bookmark=0}});k.onShowMenu.add(function(){var n=g.dom,m=n.getParent(g.selection.getNode(),"ol,ul"),l;if(m||i){l=f[d];a(k.items,function(o){var p=true;o.setSelected(0);if(m&&!o.isDisabled()){a(l,function(q){if(q.id==o.id){if(!c(m,q)){p=false;return false}}});if(p){o.setSelected(1)}}});if(!m){k.items[i.id].setSelected(1)}}g.focus();if(tinymce.isIE){f.bookmark=g.selection.getBookmark(1)}});k.add({id:g.dom.uniqueId(),title:"advlist.types","class":"mceMenuItemTitle",titleItem:true}).setDisabled(1);a(f[d],function(l){if(f.isIE7&&l.styles.listStyleType=="lower-greek"){return}l.id=g.dom.uniqueId();k.add({id:l.id,title:l.title,onclick:function(){i=l;h()}})})});return e}},getInfo:function(){return{longname:"Advanced lists",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlist",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("advlist",tinymce.plugins.AdvListPlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/advlist/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlist/editor_plugin_src.js new file mode 100644 index 0000000..a8f046b --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/advlist/editor_plugin_src.js @@ -0,0 +1,176 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var each = tinymce.each; + + tinymce.create('tinymce.plugins.AdvListPlugin', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + function buildFormats(str) { + var formats = []; + + each(str.split(/,/), function(type) { + formats.push({ + title : 'advlist.' + (type == 'default' ? 'def' : type.replace(/-/g, '_')), + styles : { + listStyleType : type == 'default' ? '' : type + } + }); + }); + + return formats; + }; + + // Setup number formats from config or default + t.numlist = ed.getParam("advlist_number_styles") || buildFormats("default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman"); + t.bullist = ed.getParam("advlist_bullet_styles") || buildFormats("default,circle,disc,square"); + + if (tinymce.isIE && /MSIE [2-7]/.test(navigator.userAgent)) + t.isIE7 = true; + }, + + createControl: function(name, cm) { + var t = this, btn, format, editor = t.editor; + + if (name == 'numlist' || name == 'bullist') { + // Default to first item if it's a default item + if (t[name][0].title == 'advlist.def') + format = t[name][0]; + + function hasFormat(node, format) { + var state = true; + + each(format.styles, function(value, name) { + // Format doesn't match + if (editor.dom.getStyle(node, name) != value) { + state = false; + return false; + } + }); + + return state; + }; + + function applyListFormat() { + var list, dom = editor.dom, sel = editor.selection; + + // Check for existing list element + list = dom.getParent(sel.getNode(), 'ol,ul'); + + // Switch/add list type if needed + if (!list || list.nodeName == (name == 'bullist' ? 'OL' : 'UL') || hasFormat(list, format)) + editor.execCommand(name == 'bullist' ? 'InsertUnorderedList' : 'InsertOrderedList'); + + // Append styles to new list element + if (format) { + list = dom.getParent(sel.getNode(), 'ol,ul'); + if (list) { + dom.setStyles(list, format.styles); + list.removeAttribute('data-mce-style'); + } + } + + editor.focus(); + }; + + btn = cm.createSplitButton(name, { + title : 'advanced.' + name + '_desc', + 'class' : 'mce_' + name, + onclick : function() { + applyListFormat(); + } + }); + + btn.onRenderMenu.add(function(btn, menu) { + menu.onHideMenu.add(function() { + if (t.bookmark) { + editor.selection.moveToBookmark(t.bookmark); + t.bookmark = 0; + } + }); + + menu.onShowMenu.add(function() { + var dom = editor.dom, list = dom.getParent(editor.selection.getNode(), 'ol,ul'), fmtList; + + if (list || format) { + fmtList = t[name]; + + // Unselect existing items + each(menu.items, function(item) { + var state = true; + + item.setSelected(0); + + if (list && !item.isDisabled()) { + each(fmtList, function(fmt) { + if (fmt.id == item.id) { + if (!hasFormat(list, fmt)) { + state = false; + return false; + } + } + }); + + if (state) + item.setSelected(1); + } + }); + + // Select the current format + if (!list) + menu.items[format.id].setSelected(1); + } + + editor.focus(); + + // IE looses it's selection so store it away and restore it later + if (tinymce.isIE) { + t.bookmark = editor.selection.getBookmark(1); + } + }); + + menu.add({id : editor.dom.uniqueId(), title : 'advlist.types', 'class' : 'mceMenuItemTitle', titleItem: true}).setDisabled(1); + + each(t[name], function(item) { + // IE<8 doesn't support lower-greek, skip it + if (t.isIE7 && item.styles.listStyleType == 'lower-greek') + return; + + item.id = editor.dom.uniqueId(); + + menu.add({id : item.id, title : item.title, onclick : function() { + format = item; + applyListFormat(); + }}); + }); + }); + + return btn; + } + }, + + getInfo : function() { + return { + longname : 'Advanced lists', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlist', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('advlist', tinymce.plugins.AdvListPlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/autolink/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/autolink/editor_plugin.js new file mode 100644 index 0000000..fd293dc --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/autolink/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.AutolinkPlugin",{init:function(a,b){var c=this;if(tinyMCE.isIE){return}a.onKeyDown.add(function(d,f){if(f.keyCode==13){return c.handleEnter(d)}});a.onKeyPress.add(function(d,f){if(f.which==41){return c.handleEclipse(d)}});a.onKeyUp.add(function(d,f){if(f.keyCode==32){return c.handleSpacebar(d)}})},handleEclipse:function(a){this.parseCurrentLine(a,-1,"(",true)},handleSpacebar:function(a){this.parseCurrentLine(a,0,"",true)},handleEnter:function(a){this.parseCurrentLine(a,-1,"",false)},parseCurrentLine:function(i,d,b,g){var a,f,c,n,k,m,h,e,j;a=i.selection.getRng().cloneRange();if(a.startOffset<5){e=a.endContainer.previousSibling;if(e==null){if(a.endContainer.firstChild==null||a.endContainer.firstChild.nextSibling==null){return}e=a.endContainer.firstChild.nextSibling}j=e.length;a.setStart(e,j);a.setEnd(e,j);if(a.endOffset<5){return}f=a.endOffset;n=e}else{n=a.endContainer;if(n.nodeType!=3&&n.firstChild){while(n.nodeType!=3&&n.firstChild){n=n.firstChild}a.setStart(n,0);a.setEnd(n,n.nodeValue.length)}if(a.endOffset==1){f=2}else{f=a.endOffset-1-d}}c=f;do{a.setStart(n,f-2);a.setEnd(n,f-1);f-=1}while(a.toString()!=" "&&a.toString()!=""&&a.toString().charCodeAt(0)!=160&&(f-2)>=0&&a.toString()!=b);if(a.toString()==b||a.toString().charCodeAt(0)==160){a.setStart(n,f);a.setEnd(n,c);f+=1}else{if(a.startOffset==0){a.setStart(n,0);a.setEnd(n,c)}else{a.setStart(n,f);a.setEnd(n,c)}}m=a.toString();h=m.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)(.+)$/i);if(h){if(h[1]=="www."){h[1]="http://www."}k=i.selection.getBookmark();i.selection.setRng(a);tinyMCE.execCommand("createlink",false,h[1]+h[2]);i.selection.moveToBookmark(k);if(tinyMCE.isWebKit){i.selection.collapse(false);var l=Math.min(n.length,c+1);a.setStart(n,l);a.setEnd(n,l);i.selection.setRng(a)}}},getInfo:function(){return{longname:"Autolink",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autolink",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("autolink",tinymce.plugins.AutolinkPlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/autolink/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/autolink/editor_plugin_src.js new file mode 100644 index 0000000..604da8b --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/autolink/editor_plugin_src.js @@ -0,0 +1,172 @@ +/** + * editor_plugin_src.js + * + * Copyright 2011, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.AutolinkPlugin', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + + init : function(ed, url) { + var t = this; + + // Internet Explorer has built-in automatic linking + if (tinyMCE.isIE) + return; + + // Add a key down handler + ed.onKeyDown.add(function(ed, e) { + if (e.keyCode == 13) + return t.handleEnter(ed); + }); + + ed.onKeyPress.add(function(ed, e) { + if (e.which == 41) + return t.handleEclipse(ed); + }); + + // Add a key up handler + ed.onKeyUp.add(function(ed, e) { + if (e.keyCode == 32) + return t.handleSpacebar(ed); + }); + }, + + handleEclipse : function(ed) { + this.parseCurrentLine(ed, -1, '(', true); + }, + + handleSpacebar : function(ed) { + this.parseCurrentLine(ed, 0, '', true); + }, + + handleEnter : function(ed) { + this.parseCurrentLine(ed, -1, '', false); + }, + + parseCurrentLine : function(ed, end_offset, delimiter, goback) { + var r, end, start, endContainer, bookmark, text, matches, prev, len; + + // We need at least five characters to form a URL, + // hence, at minimum, five characters from the beginning of the line. + r = ed.selection.getRng().cloneRange(); + if (r.startOffset < 5) { + // During testing, the caret is placed inbetween two text nodes. + // The previous text node contains the URL. + prev = r.endContainer.previousSibling; + if (prev == null) { + if (r.endContainer.firstChild == null || r.endContainer.firstChild.nextSibling == null) + return; + + prev = r.endContainer.firstChild.nextSibling; + } + len = prev.length; + r.setStart(prev, len); + r.setEnd(prev, len); + + if (r.endOffset < 5) + return; + + end = r.endOffset; + endContainer = prev; + } else { + endContainer = r.endContainer; + + // Get a text node + if (endContainer.nodeType != 3 && endContainer.firstChild) { + while (endContainer.nodeType != 3 && endContainer.firstChild) + endContainer = endContainer.firstChild; + + r.setStart(endContainer, 0); + r.setEnd(endContainer, endContainer.nodeValue.length); + } + + if (r.endOffset == 1) + end = 2; + else + end = r.endOffset - 1 - end_offset; + } + + start = end; + + do + { + // Move the selection one character backwards. + r.setStart(endContainer, end - 2); + r.setEnd(endContainer, end - 1); + end -= 1; + + // Loop until one of the following is found: a blank space, &nbsp;, delimeter, (end-2) >= 0 + } while (r.toString() != ' ' && r.toString() != '' && r.toString().charCodeAt(0) != 160 && (end -2) >= 0 && r.toString() != delimiter); + + if (r.toString() == delimiter || r.toString().charCodeAt(0) == 160) { + r.setStart(endContainer, end); + r.setEnd(endContainer, start); + end += 1; + } else if (r.startOffset == 0) { + r.setStart(endContainer, 0); + r.setEnd(endContainer, start); + } + else { + r.setStart(endContainer, end); + r.setEnd(endContainer, start); + } + + text = r.toString(); + matches = text.match(/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.)(.+)$/i); + + if (matches) { + if (matches[1] == 'www.') { + matches[1] = 'http://www.'; + } + + bookmark = ed.selection.getBookmark(); + + ed.selection.setRng(r); + tinyMCE.execCommand('createlink',false, matches[1] + matches[2]); + ed.selection.moveToBookmark(bookmark); + + // TODO: Determine if this is still needed. + if (tinyMCE.isWebKit) { + // move the caret to its original position + ed.selection.collapse(false); + var max = Math.min(endContainer.length, start + 1); + r.setStart(endContainer, max); + r.setEnd(endContainer, max); + ed.selection.setRng(r); + } + } + }, + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Autolink', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autolink', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('autolink', tinymce.plugins.AutolinkPlugin); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/autoresize/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/autoresize/editor_plugin.js new file mode 100644 index 0000000..6c4ff0d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/autoresize/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.AutoResizePlugin",{init:function(a,c){var d=this,e=0;if(a.getParam("fullscreen_is_enabled")){return}function b(){var i=a.getDoc(),f=i.body,k=i.documentElement,h=tinymce.DOM,j=d.autoresize_min_height,g;g=tinymce.isIE?f.scrollHeight:i.body.offsetHeight;if(g>d.autoresize_min_height){j=g}if(d.autoresize_max_height&&g>d.autoresize_max_height){j=d.autoresize_max_height;a.getBody().style.overflowY="auto"}else{a.getBody().style.overflowY="hidden"}if(j!==e){h.setStyle(h.get(a.id+"_ifr"),"height",j+"px");e=j}if(d.throbbing){a.setProgressState(false);a.setProgressState(true)}}d.editor=a;d.autoresize_min_height=parseInt(a.getParam("autoresize_min_height",a.getElement().offsetHeight));d.autoresize_max_height=parseInt(a.getParam("autoresize_max_height",0));a.onInit.add(function(f){f.dom.setStyle(f.getBody(),"paddingBottom",f.getParam("autoresize_bottom_margin",50)+"px")});a.onChange.add(b);a.onSetContent.add(b);a.onPaste.add(b);a.onKeyUp.add(b);a.onPostRender.add(b);if(a.getParam("autoresize_on_init",true)){a.onInit.add(function(g,f){g.setProgressState(true);d.throbbing=true;g.getBody().style.overflowY="hidden"});a.onLoadContent.add(function(g,f){b();setTimeout(function(){b();g.setProgressState(false);d.throbbing=false},1250)})}a.addCommand("mceAutoResize",b)},getInfo:function(){return{longname:"Auto Resize",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autoresize",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("autoresize",tinymce.plugins.AutoResizePlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/autoresize/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/autoresize/editor_plugin_src.js new file mode 100644 index 0000000..7d11341 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/autoresize/editor_plugin_src.js @@ -0,0 +1,137 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + /** + * Auto Resize + * + * This plugin automatically resizes the content area to fit its content height. + * It will retain a minimum height, which is the height of the content area when + * it's initialized. + */ + tinymce.create('tinymce.plugins.AutoResizePlugin', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed, url) { + var t = this, oldSize = 0; + + if (ed.getParam('fullscreen_is_enabled')) + return; + + /** + * This method gets executed each time the editor needs to resize. + */ + function resize() { + var d = ed.getDoc(), b = d.body, de = d.documentElement, DOM = tinymce.DOM, resizeHeight = t.autoresize_min_height, myHeight; + + // Get height differently depending on the browser used + myHeight = tinymce.isIE ? b.scrollHeight : d.body.offsetHeight; + + // Don't make it smaller than the minimum height + if (myHeight > t.autoresize_min_height) + resizeHeight = myHeight; + + // If a maximum height has been defined don't exceed this height + if (t.autoresize_max_height && myHeight > t.autoresize_max_height) { + resizeHeight = t.autoresize_max_height; + ed.getBody().style.overflowY = "auto"; + } else + ed.getBody().style.overflowY = "hidden"; + + // Resize content element + if (resizeHeight !== oldSize) { + DOM.setStyle(DOM.get(ed.id + '_ifr'), 'height', resizeHeight + 'px'); + oldSize = resizeHeight; + } + + // if we're throbbing, we'll re-throb to match the new size + if (t.throbbing) { + ed.setProgressState(false); + ed.setProgressState(true); + } + }; + + t.editor = ed; + + // Define minimum height + t.autoresize_min_height = parseInt( ed.getParam('autoresize_min_height', ed.getElement().offsetHeight) ); + + // Define maximum height + t.autoresize_max_height = parseInt( ed.getParam('autoresize_max_height', 0) ); + + // Add padding at the bottom for better UX + ed.onInit.add(function(ed){ + ed.dom.setStyle(ed.getBody(), 'paddingBottom', ed.getParam('autoresize_bottom_margin', 50) + 'px'); + }); + + // Add appropriate listeners for resizing content area + ed.onChange.add(resize); + ed.onSetContent.add(resize); + ed.onPaste.add(resize); + ed.onKeyUp.add(resize); + ed.onPostRender.add(resize); + + if (ed.getParam('autoresize_on_init', true)) { + // Things to do when the editor is ready + ed.onInit.add(function(ed, l) { + // Show throbber until content area is resized properly + ed.setProgressState(true); + t.throbbing = true; + + // Hide scrollbars + ed.getBody().style.overflowY = "hidden"; + }); + + ed.onLoadContent.add(function(ed, l) { + resize(); + + // Because the content area resizes when its content CSS loads, + // and we can't easily add a listener to its onload event, + // we'll just trigger a resize after a short loading period + setTimeout(function() { + resize(); + + // Disable throbber + ed.setProgressState(false); + t.throbbing = false; + }, 1250); + }); + } + + // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample'); + ed.addCommand('mceAutoResize', resize); + }, + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Auto Resize', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autoresize', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('autoresize', tinymce.plugins.AutoResizePlugin); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/editor_plugin.js new file mode 100644 index 0000000..f7d0576 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/editor_plugin.js @@ -0,0 +1 @@ +(function(e){var c="autosave",g="restoredraft",b=true,f,d,a=e.util.Dispatcher;e.create("tinymce.plugins.AutoSave",{init:function(i,j){var h=this,l=i.settings;h.editor=i;function k(n){var m={s:1000,m:60000};n=/^(\d+)([ms]?)$/.exec(""+n);return(n[2]?m[n[2]]:1)*parseInt(n)}e.each({ask_before_unload:b,interval:"30s",retention:"20m",minlength:50},function(n,m){m=c+"_"+m;if(l[m]===f){l[m]=n}});l.autosave_interval=k(l.autosave_interval);l.autosave_retention=k(l.autosave_retention);i.addButton(g,{title:c+".restore_content",onclick:function(){if(i.getContent({draft:true}).replace(/\s|&nbsp;|<\/?p[^>]*>|<br[^>]*>/gi,"").length>0){i.windowManager.confirm(c+".warning_message",function(m){if(m){h.restoreDraft()}})}else{h.restoreDraft()}}});i.onNodeChange.add(function(){var m=i.controlManager;if(m.get(g)){m.setDisabled(g,!h.hasDraft())}});i.onInit.add(function(){if(i.controlManager.get(g)){h.setupStorage(i);setInterval(function(){h.storeDraft();i.nodeChanged()},l.autosave_interval)}});h.onStoreDraft=new a(h);h.onRestoreDraft=new a(h);h.onRemoveDraft=new a(h);if(!d){window.onbeforeunload=e.plugins.AutoSave._beforeUnloadHandler;d=b}},getInfo:function(){return{longname:"Auto save",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave",version:e.majorVersion+"."+e.minorVersion}},getExpDate:function(){return new Date(new Date().getTime()+this.editor.settings.autosave_retention).toUTCString()},setupStorage:function(i){var h=this,k=c+"_test",j="OK";h.key=c+i.id;e.each([function(){if(localStorage){localStorage.setItem(k,j);if(localStorage.getItem(k)===j){localStorage.removeItem(k);return localStorage}}},function(){if(sessionStorage){sessionStorage.setItem(k,j);if(sessionStorage.getItem(k)===j){sessionStorage.removeItem(k);return sessionStorage}}},function(){if(e.isIE){i.getElement().style.behavior="url('#default#userData')";return{autoExpires:b,setItem:function(l,n){var m=i.getElement();m.setAttribute(l,n);m.expires=h.getExpDate();try{m.save("TinyMCE")}catch(o){}},getItem:function(l){var m=i.getElement();try{m.load("TinyMCE");return m.getAttribute(l)}catch(n){return null}},removeItem:function(l){i.getElement().removeAttribute(l)}}}},],function(l){try{h.storage=l();if(h.storage){return false}}catch(m){}})},storeDraft:function(){var i=this,l=i.storage,j=i.editor,h,k;if(l){if(!l.getItem(i.key)&&!j.isDirty()){return}k=j.getContent({draft:true});if(k.length>j.settings.autosave_minlength){h=i.getExpDate();if(!i.storage.autoExpires){i.storage.setItem(i.key+"_expires",h)}i.storage.setItem(i.key,k);i.onStoreDraft.dispatch(i,{expires:h,content:k})}}},restoreDraft:function(){var h=this,j=h.storage,i;if(j){i=j.getItem(h.key);if(i){h.editor.setContent(i);h.onRestoreDraft.dispatch(h,{content:i})}}},hasDraft:function(){var h=this,k=h.storage,i,j;if(k){j=!!k.getItem(h.key);if(j){if(!h.storage.autoExpires){i=new Date(k.getItem(h.key+"_expires"));if(new Date().getTime()<i.getTime()){return b}h.removeDraft()}else{return b}}}return false},removeDraft:function(){var h=this,k=h.storage,i=h.key,j;if(k){j=k.getItem(i);k.removeItem(i);k.removeItem(i+"_expires");if(j){h.onRemoveDraft.dispatch(h,{content:j})}}},"static":{_beforeUnloadHandler:function(h){var i;e.each(tinyMCE.editors,function(j){if(j.plugins.autosave){j.plugins.autosave.storeDraft()}if(j.getParam("fullscreen_is_enabled")){return}if(!i&&j.isDirty()&&j.getParam("autosave_ask_before_unload")){i=j.getLang("autosave.unload_msg")}});return i}}});e.PluginManager.add("autosave",e.plugins.AutoSave)})(tinymce); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/editor_plugin_src.js new file mode 100644 index 0000000..8311483 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/editor_plugin_src.js @@ -0,0 +1,431 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + * + * Adds auto-save capability to the TinyMCE text editor to rescue content + * inadvertently lost. This plugin was originally developed by Speednet + * and that project can be found here: http://code.google.com/p/tinyautosave/ + * + * TECHNOLOGY DISCUSSION: + * + * The plugin attempts to use the most advanced features available in the current browser to save + * as much content as possible. There are a total of four different methods used to autosave the + * content. In order of preference, they are: + * + * 1. localStorage - A new feature of HTML 5, localStorage can store megabytes of data per domain + * on the client computer. Data stored in the localStorage area has no expiration date, so we must + * manage expiring the data ourselves. localStorage is fully supported by IE8, and it is supposed + * to be working in Firefox 3 and Safari 3.2, but in reality is is flaky in those browsers. As + * HTML 5 gets wider support, the AutoSave plugin will use it automatically. In Windows Vista/7, + * localStorage is stored in the following folder: + * C:\Users\[username]\AppData\Local\Microsoft\Internet Explorer\DOMStore\[tempFolder] + * + * 2. sessionStorage - A new feature of HTML 5, sessionStorage works similarly to localStorage, + * except it is designed to expire after a certain amount of time. Because the specification + * around expiration date/time is very loosely-described, it is preferrable to use locaStorage and + * manage the expiration ourselves. sessionStorage has similar storage characteristics to + * localStorage, although it seems to have better support by Firefox 3 at the moment. (That will + * certainly change as Firefox continues getting better at HTML 5 adoption.) + * + * 3. UserData - A very under-exploited feature of Microsoft Internet Explorer, UserData is a + * way to store up to 128K of data per "document", or up to 1MB of data per domain, on the client + * computer. The feature is available for IE 5+, which makes it available for every version of IE + * supported by TinyMCE. The content is persistent across browser restarts and expires on the + * date/time specified, just like a cookie. However, the data is not cleared when the user clears + * cookies on the browser, which makes it well-suited for rescuing autosaved content. UserData, + * like other Microsoft IE browser technologies, is implemented as a behavior attached to a + * specific DOM object, so in this case we attach the behavior to the same DOM element that the + * TinyMCE editor instance is attached to. + */ + +(function(tinymce) { + // Setup constants to help the compressor to reduce script size + var PLUGIN_NAME = 'autosave', + RESTORE_DRAFT = 'restoredraft', + TRUE = true, + undefined, + unloadHandlerAdded, + Dispatcher = tinymce.util.Dispatcher; + + /** + * This plugin adds auto-save capability to the TinyMCE text editor to rescue content + * inadvertently lost. By using localStorage. + * + * @class tinymce.plugins.AutoSave + */ + tinymce.create('tinymce.plugins.AutoSave', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @method init + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed, url) { + var self = this, settings = ed.settings; + + self.editor = ed; + + // Parses the specified time string into a milisecond number 10m, 10s etc. + function parseTime(time) { + var multipels = { + s : 1000, + m : 60000 + }; + + time = /^(\d+)([ms]?)$/.exec('' + time); + + return (time[2] ? multipels[time[2]] : 1) * parseInt(time); + }; + + // Default config + tinymce.each({ + ask_before_unload : TRUE, + interval : '30s', + retention : '20m', + minlength : 50 + }, function(value, key) { + key = PLUGIN_NAME + '_' + key; + + if (settings[key] === undefined) + settings[key] = value; + }); + + // Parse times + settings.autosave_interval = parseTime(settings.autosave_interval); + settings.autosave_retention = parseTime(settings.autosave_retention); + + // Register restore button + ed.addButton(RESTORE_DRAFT, { + title : PLUGIN_NAME + ".restore_content", + onclick : function() { + if (ed.getContent({draft: true}).replace(/\s|&nbsp;|<\/?p[^>]*>|<br[^>]*>/gi, "").length > 0) { + // Show confirm dialog if the editor isn't empty + ed.windowManager.confirm( + PLUGIN_NAME + ".warning_message", + function(ok) { + if (ok) + self.restoreDraft(); + } + ); + } else + self.restoreDraft(); + } + }); + + // Enable/disable restoredraft button depending on if there is a draft stored or not + ed.onNodeChange.add(function() { + var controlManager = ed.controlManager; + + if (controlManager.get(RESTORE_DRAFT)) + controlManager.setDisabled(RESTORE_DRAFT, !self.hasDraft()); + }); + + ed.onInit.add(function() { + // Check if the user added the restore button, then setup auto storage logic + if (ed.controlManager.get(RESTORE_DRAFT)) { + // Setup storage engine + self.setupStorage(ed); + + // Auto save contents each interval time + setInterval(function() { + self.storeDraft(); + ed.nodeChanged(); + }, settings.autosave_interval); + } + }); + + /** + * This event gets fired when a draft is stored to local storage. + * + * @event onStoreDraft + * @param {tinymce.plugins.AutoSave} sender Plugin instance sending the event. + * @param {Object} draft Draft object containing the HTML contents of the editor. + */ + self.onStoreDraft = new Dispatcher(self); + + /** + * This event gets fired when a draft is restored from local storage. + * + * @event onStoreDraft + * @param {tinymce.plugins.AutoSave} sender Plugin instance sending the event. + * @param {Object} draft Draft object containing the HTML contents of the editor. + */ + self.onRestoreDraft = new Dispatcher(self); + + /** + * This event gets fired when a draft removed/expired. + * + * @event onRemoveDraft + * @param {tinymce.plugins.AutoSave} sender Plugin instance sending the event. + * @param {Object} draft Draft object containing the HTML contents of the editor. + */ + self.onRemoveDraft = new Dispatcher(self); + + // Add ask before unload dialog only add one unload handler + if (!unloadHandlerAdded) { + window.onbeforeunload = tinymce.plugins.AutoSave._beforeUnloadHandler; + unloadHandlerAdded = TRUE; + } + }, + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @method getInfo + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Auto save', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + /** + * Returns an expiration date UTC string. + * + * @method getExpDate + * @return {String} Expiration date UTC string. + */ + getExpDate : function() { + return new Date( + new Date().getTime() + this.editor.settings.autosave_retention + ).toUTCString(); + }, + + /** + * This method will setup the storage engine. If the browser has support for it. + * + * @method setupStorage + */ + setupStorage : function(ed) { + var self = this, testKey = PLUGIN_NAME + '_test', testVal = "OK"; + + self.key = PLUGIN_NAME + ed.id; + + // Loop though each storage engine type until we find one that works + tinymce.each([ + function() { + // Try HTML5 Local Storage + if (localStorage) { + localStorage.setItem(testKey, testVal); + + if (localStorage.getItem(testKey) === testVal) { + localStorage.removeItem(testKey); + + return localStorage; + } + } + }, + + function() { + // Try HTML5 Session Storage + if (sessionStorage) { + sessionStorage.setItem(testKey, testVal); + + if (sessionStorage.getItem(testKey) === testVal) { + sessionStorage.removeItem(testKey); + + return sessionStorage; + } + } + }, + + function() { + // Try IE userData + if (tinymce.isIE) { + ed.getElement().style.behavior = "url('#default#userData')"; + + // Fake localStorage on old IE + return { + autoExpires : TRUE, + + setItem : function(key, value) { + var userDataElement = ed.getElement(); + + userDataElement.setAttribute(key, value); + userDataElement.expires = self.getExpDate(); + + try { + userDataElement.save("TinyMCE"); + } catch (e) { + // Ignore, saving might fail if "Userdata Persistence" is disabled in IE + } + }, + + getItem : function(key) { + var userDataElement = ed.getElement(); + + try { + userDataElement.load("TinyMCE"); + return userDataElement.getAttribute(key); + } catch (e) { + // Ignore, loading might fail if "Userdata Persistence" is disabled in IE + return null; + } + }, + + removeItem : function(key) { + ed.getElement().removeAttribute(key); + } + }; + } + }, + ], function(setup) { + // Try executing each function to find a suitable storage engine + try { + self.storage = setup(); + + if (self.storage) + return false; + } catch (e) { + // Ignore + } + }); + }, + + /** + * This method will store the current contents in the the storage engine. + * + * @method storeDraft + */ + storeDraft : function() { + var self = this, storage = self.storage, editor = self.editor, expires, content; + + // Is the contents dirty + if (storage) { + // If there is no existing key and the contents hasn't been changed since + // it's original value then there is no point in saving a draft + if (!storage.getItem(self.key) && !editor.isDirty()) + return; + + // Store contents if the contents if longer than the minlength of characters + content = editor.getContent({draft: true}); + if (content.length > editor.settings.autosave_minlength) { + expires = self.getExpDate(); + + // Store expiration date if needed IE userData has auto expire built in + if (!self.storage.autoExpires) + self.storage.setItem(self.key + "_expires", expires); + + self.storage.setItem(self.key, content); + self.onStoreDraft.dispatch(self, { + expires : expires, + content : content + }); + } + } + }, + + /** + * This method will restore the contents from the storage engine back to the editor. + * + * @method restoreDraft + */ + restoreDraft : function() { + var self = this, storage = self.storage, content; + + if (storage) { + content = storage.getItem(self.key); + + if (content) { + self.editor.setContent(content); + self.onRestoreDraft.dispatch(self, { + content : content + }); + } + } + }, + + /** + * This method will return true/false if there is a local storage draft available. + * + * @method hasDraft + * @return {boolean} true/false state if there is a local draft. + */ + hasDraft : function() { + var self = this, storage = self.storage, expDate, exists; + + if (storage) { + // Does the item exist at all + exists = !!storage.getItem(self.key); + if (exists) { + // Storage needs autoexpire + if (!self.storage.autoExpires) { + expDate = new Date(storage.getItem(self.key + "_expires")); + + // Contents hasn't expired + if (new Date().getTime() < expDate.getTime()) + return TRUE; + + // Remove it if it has + self.removeDraft(); + } else + return TRUE; + } + } + + return false; + }, + + /** + * Removes the currently stored draft. + * + * @method removeDraft + */ + removeDraft : function() { + var self = this, storage = self.storage, key = self.key, content; + + if (storage) { + // Get current contents and remove the existing draft + content = storage.getItem(key); + storage.removeItem(key); + storage.removeItem(key + "_expires"); + + // Dispatch remove event if we had any contents + if (content) { + self.onRemoveDraft.dispatch(self, { + content : content + }); + } + } + }, + + "static" : { + // Internal unload handler will be called before the page is unloaded + _beforeUnloadHandler : function(e) { + var msg; + + tinymce.each(tinyMCE.editors, function(ed) { + // Store a draft for each editor instance + if (ed.plugins.autosave) + ed.plugins.autosave.storeDraft(); + + // Never ask in fullscreen mode + if (ed.getParam("fullscreen_is_enabled")) + return; + + // Setup a return message if the editor is dirty + if (!msg && ed.isDirty() && ed.getParam("autosave_ask_before_unload")) + msg = ed.getLang("autosave.unload_msg"); + }); + + return msg; + } + } + }); + + tinymce.PluginManager.add('autosave', tinymce.plugins.AutoSave); +})(tinymce); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/langs/en.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/langs/en.js new file mode 100644 index 0000000..fce6bd3 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/autosave/langs/en.js @@ -0,0 +1,4 @@ +tinyMCE.addI18n('en.autosave',{ +restore_content: "Restore auto-saved content", +warning_message: "If you restore the saved content, you will lose all the content that is currently in the editor.\n\nAre you sure you want to restore the saved content?" +}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/bbcode/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/bbcode/editor_plugin.js new file mode 100644 index 0000000..8f8821f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/bbcode/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.BBCodePlugin",{init:function(a,b){var d=this,c=a.getParam("bbcode_dialect","punbb").toLowerCase();a.onBeforeSetContent.add(function(e,f){f.content=d["_"+c+"_bbcode2html"](f.content)});a.onPostProcess.add(function(e,f){if(f.set){f.content=d["_"+c+"_bbcode2html"](f.content)}if(f.get){f.content=d["_"+c+"_html2bbcode"](f.content)}})},getInfo:function(){return{longname:"BBCode Plugin",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_punbb_html2bbcode:function(a){a=tinymce.trim(a);function b(c,d){a=a.replace(c,d)}b(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");b(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");b(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");b(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");b(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");b(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]");b(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]");b(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]");b(/<font>(.*?)<\/font>/gi,"$1");b(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]");b(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]");b(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]");b(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]");b(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]");b(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]");b(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]");b(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]");b(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]");b(/<\/(strong|b)>/gi,"[/b]");b(/<(strong|b)>/gi,"[b]");b(/<\/(em|i)>/gi,"[/i]");b(/<(em|i)>/gi,"[i]");b(/<\/u>/gi,"[/u]");b(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]");b(/<u>/gi,"[u]");b(/<blockquote[^>]*>/gi,"[quote]");b(/<\/blockquote>/gi,"[/quote]");b(/<br \/>/gi,"\n");b(/<br\/>/gi,"\n");b(/<br>/gi,"\n");b(/<p>/gi,"");b(/<\/p>/gi,"\n");b(/&nbsp;|\u00a0/gi," ");b(/&quot;/gi,'"');b(/&lt;/gi,"<");b(/&gt;/gi,">");b(/&amp;/gi,"&");return a},_punbb_bbcode2html:function(a){a=tinymce.trim(a);function b(c,d){a=a.replace(c,d)}b(/\n/gi,"<br />");b(/\[b\]/gi,"<strong>");b(/\[\/b\]/gi,"</strong>");b(/\[i\]/gi,"<em>");b(/\[\/i\]/gi,"</em>");b(/\[u\]/gi,"<u>");b(/\[\/u\]/gi,"</u>");b(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'<a href="$1">$2</a>');b(/\[url\](.*?)\[\/url\]/gi,'<a href="$1">$1</a>');b(/\[img\](.*?)\[\/img\]/gi,'<img src="$1" />');b(/\[color=(.*?)\](.*?)\[\/color\]/gi,'<font color="$1">$2</font>');b(/\[code\](.*?)\[\/code\]/gi,'<span class="codeStyle">$1</span>&nbsp;');b(/\[quote.*?\](.*?)\[\/quote\]/gi,'<span class="quoteStyle">$1</span>&nbsp;');return a}});tinymce.PluginManager.add("bbcode",tinymce.plugins.BBCodePlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/bbcode/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/bbcode/editor_plugin_src.js new file mode 100644 index 0000000..4e7eb33 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/bbcode/editor_plugin_src.js @@ -0,0 +1,120 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.BBCodePlugin', { + init : function(ed, url) { + var t = this, dialect = ed.getParam('bbcode_dialect', 'punbb').toLowerCase(); + + ed.onBeforeSetContent.add(function(ed, o) { + o.content = t['_' + dialect + '_bbcode2html'](o.content); + }); + + ed.onPostProcess.add(function(ed, o) { + if (o.set) + o.content = t['_' + dialect + '_bbcode2html'](o.content); + + if (o.get) + o.content = t['_' + dialect + '_html2bbcode'](o.content); + }); + }, + + getInfo : function() { + return { + longname : 'BBCode Plugin', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + // HTML -> BBCode in PunBB dialect + _punbb_html2bbcode : function(s) { + s = tinymce.trim(s); + + function rep(re, str) { + s = s.replace(re, str); + }; + + // example: <strong> to [b] + rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]"); + rep(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"); + rep(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"); + rep(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"); + rep(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"); + rep(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]"); + rep(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]"); + rep(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]"); + rep(/<font>(.*?)<\/font>/gi,"$1"); + rep(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]"); + rep(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]"); + rep(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]"); + rep(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"); + rep(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"); + rep(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"); + rep(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"); + rep(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"); + rep(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"); + rep(/<\/(strong|b)>/gi,"[/b]"); + rep(/<(strong|b)>/gi,"[b]"); + rep(/<\/(em|i)>/gi,"[/i]"); + rep(/<(em|i)>/gi,"[i]"); + rep(/<\/u>/gi,"[/u]"); + rep(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]"); + rep(/<u>/gi,"[u]"); + rep(/<blockquote[^>]*>/gi,"[quote]"); + rep(/<\/blockquote>/gi,"[/quote]"); + rep(/<br \/>/gi,"\n"); + rep(/<br\/>/gi,"\n"); + rep(/<br>/gi,"\n"); + rep(/<p>/gi,""); + rep(/<\/p>/gi,"\n"); + rep(/&nbsp;|\u00a0/gi," "); + rep(/&quot;/gi,"\""); + rep(/&lt;/gi,"<"); + rep(/&gt;/gi,">"); + rep(/&amp;/gi,"&"); + + return s; + }, + + // BBCode -> HTML from PunBB dialect + _punbb_bbcode2html : function(s) { + s = tinymce.trim(s); + + function rep(re, str) { + s = s.replace(re, str); + }; + + // example: [b] to <strong> + rep(/\n/gi,"<br />"); + rep(/\[b\]/gi,"<strong>"); + rep(/\[\/b\]/gi,"</strong>"); + rep(/\[i\]/gi,"<em>"); + rep(/\[\/i\]/gi,"</em>"); + rep(/\[u\]/gi,"<u>"); + rep(/\[\/u\]/gi,"</u>"); + rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>"); + rep(/\[url\](.*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>"); + rep(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />"); + rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"<font color=\"$1\">$2</font>"); + rep(/\[code\](.*?)\[\/code\]/gi,"<span class=\"codeStyle\">$1</span>&nbsp;"); + rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"<span class=\"quoteStyle\">$1</span>&nbsp;"); + + return s; + } + }); + + // Register plugin + tinymce.PluginManager.add('bbcode', tinymce.plugins.BBCodePlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/contextmenu/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/contextmenu/editor_plugin.js new file mode 100644 index 0000000..af7ae54 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/contextmenu/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.dom.Event,c=tinymce.each,b=tinymce.DOM;tinymce.create("tinymce.plugins.ContextMenu",{init:function(e){var h=this,f,d,i;h.editor=e;d=e.settings.contextmenu_never_use_native;h.onContextMenu=new tinymce.util.Dispatcher(this);f=e.onContextMenu.add(function(j,k){if((i!==0?i:k.ctrlKey)&&!d){return}a.cancel(k);if(k.target.nodeName=="IMG"){j.selection.select(k.target)}h._getMenu(j).showMenu(k.clientX||k.pageX,k.clientY||k.pageY);a.add(j.getDoc(),"click",function(l){g(j,l)});j.nodeChanged()});e.onRemove.add(function(){if(h._menu){h._menu.removeAll()}});function g(j,k){i=0;if(k&&k.button==2){i=k.ctrlKey;return}if(h._menu){h._menu.removeAll();h._menu.destroy();a.remove(j.getDoc(),"click",g)}}e.onMouseDown.add(g);e.onKeyDown.add(g);e.onKeyDown.add(function(j,k){if(k.shiftKey&&!k.ctrlKey&&!k.altKey&&k.keyCode===121){a.cancel(k);f(j,k)}})},getInfo:function(){return{longname:"Contextmenu",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/contextmenu",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_getMenu:function(e){var g=this,d=g._menu,j=e.selection,f=j.isCollapsed(),h=j.getNode()||e.getBody(),i,k;if(d){d.removeAll();d.destroy()}k=b.getPos(e.getContentAreaContainer());d=e.controlManager.createDropMenu("contextmenu",{offset_x:k.x+e.getParam("contextmenu_offset_x",0),offset_y:k.y+e.getParam("contextmenu_offset_y",0),constrain:1,keyboard_focus:true});g._menu=d;d.add({title:"advanced.cut_desc",icon:"cut",cmd:"Cut"}).setDisabled(f);d.add({title:"advanced.copy_desc",icon:"copy",cmd:"Copy"}).setDisabled(f);d.add({title:"advanced.paste_desc",icon:"paste",cmd:"Paste"});if((h.nodeName=="A"&&!e.dom.getAttrib(h,"name"))||!f){d.addSeparator();d.add({title:"advanced.link_desc",icon:"link",cmd:e.plugins.advlink?"mceAdvLink":"mceLink",ui:true});d.add({title:"advanced.unlink_desc",icon:"unlink",cmd:"UnLink"})}d.addSeparator();d.add({title:"advanced.image_desc",icon:"image",cmd:e.plugins.advimage?"mceAdvImage":"mceImage",ui:true});d.addSeparator();i=d.addMenu({title:"contextmenu.align"});i.add({title:"contextmenu.left",icon:"justifyleft",cmd:"JustifyLeft"});i.add({title:"contextmenu.center",icon:"justifycenter",cmd:"JustifyCenter"});i.add({title:"contextmenu.right",icon:"justifyright",cmd:"JustifyRight"});i.add({title:"contextmenu.full",icon:"justifyfull",cmd:"JustifyFull"});g.onContextMenu.dispatch(g,d,h,f);return d}});tinymce.PluginManager.add("contextmenu",tinymce.plugins.ContextMenu)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/contextmenu/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/contextmenu/editor_plugin_src.js new file mode 100644 index 0000000..956fbea --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/contextmenu/editor_plugin_src.js @@ -0,0 +1,160 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var Event = tinymce.dom.Event, each = tinymce.each, DOM = tinymce.DOM; + + /** + * This plugin a context menu to TinyMCE editor instances. + * + * @class tinymce.plugins.ContextMenu + */ + tinymce.create('tinymce.plugins.ContextMenu', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @method init + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed) { + var t = this, showMenu, contextmenuNeverUseNative, realCtrlKey; + + t.editor = ed; + + contextmenuNeverUseNative = ed.settings.contextmenu_never_use_native; + + /** + * This event gets fired when the context menu is shown. + * + * @event onContextMenu + * @param {tinymce.plugins.ContextMenu} sender Plugin instance sending the event. + * @param {tinymce.ui.DropMenu} menu Drop down menu to fill with more items if needed. + */ + t.onContextMenu = new tinymce.util.Dispatcher(this); + + showMenu = ed.onContextMenu.add(function(ed, e) { + // Block TinyMCE menu on ctrlKey and work around Safari issue + if ((realCtrlKey !== 0 ? realCtrlKey : e.ctrlKey) && !contextmenuNeverUseNative) + return; + + Event.cancel(e); + + // Select the image if it's clicked. WebKit would other wise expand the selection + if (e.target.nodeName == 'IMG') + ed.selection.select(e.target); + + t._getMenu(ed).showMenu(e.clientX || e.pageX, e.clientY || e.pageY); + Event.add(ed.getDoc(), 'click', function(e) { + hide(ed, e); + }); + + ed.nodeChanged(); + }); + + ed.onRemove.add(function() { + if (t._menu) + t._menu.removeAll(); + }); + + function hide(ed, e) { + realCtrlKey = 0; + + // Since the contextmenu event moves + // the selection we need to store it away + if (e && e.button == 2) { + realCtrlKey = e.ctrlKey; + return; + } + + if (t._menu) { + t._menu.removeAll(); + t._menu.destroy(); + Event.remove(ed.getDoc(), 'click', hide); + } + }; + + ed.onMouseDown.add(hide); + ed.onKeyDown.add(hide); + ed.onKeyDown.add(function(ed, e) { + if (e.shiftKey && !e.ctrlKey && !e.altKey && e.keyCode === 121) { + Event.cancel(e); + showMenu(ed, e); + } + }); + }, + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @method getInfo + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Contextmenu', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/contextmenu', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + _getMenu : function(ed) { + var t = this, m = t._menu, se = ed.selection, col = se.isCollapsed(), el = se.getNode() || ed.getBody(), am, p; + + if (m) { + m.removeAll(); + m.destroy(); + } + + p = DOM.getPos(ed.getContentAreaContainer()); + + m = ed.controlManager.createDropMenu('contextmenu', { + offset_x : p.x + ed.getParam('contextmenu_offset_x', 0), + offset_y : p.y + ed.getParam('contextmenu_offset_y', 0), + constrain : 1, + keyboard_focus: true + }); + + t._menu = m; + + m.add({title : 'advanced.cut_desc', icon : 'cut', cmd : 'Cut'}).setDisabled(col); + m.add({title : 'advanced.copy_desc', icon : 'copy', cmd : 'Copy'}).setDisabled(col); + m.add({title : 'advanced.paste_desc', icon : 'paste', cmd : 'Paste'}); + + if ((el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) || !col) { + m.addSeparator(); + m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true}); + m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'}); + } + + m.addSeparator(); + m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true}); + + m.addSeparator(); + am = m.addMenu({title : 'contextmenu.align'}); + am.add({title : 'contextmenu.left', icon : 'justifyleft', cmd : 'JustifyLeft'}); + am.add({title : 'contextmenu.center', icon : 'justifycenter', cmd : 'JustifyCenter'}); + am.add({title : 'contextmenu.right', icon : 'justifyright', cmd : 'JustifyRight'}); + am.add({title : 'contextmenu.full', icon : 'justifyfull', cmd : 'JustifyFull'}); + + t.onContextMenu.dispatch(t, m, el, col); + + return m; + } + }); + + // Register plugin + tinymce.PluginManager.add('contextmenu', tinymce.plugins.ContextMenu); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/directionality/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/directionality/editor_plugin.js new file mode 100644 index 0000000..bce8e73 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/directionality/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.Directionality",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceDirectionLTR",function(){var d=a.dom.getParent(a.selection.getNode(),a.dom.isBlock);if(d){if(a.dom.getAttrib(d,"dir")!="ltr"){a.dom.setAttrib(d,"dir","ltr")}else{a.dom.setAttrib(d,"dir","")}}a.nodeChanged()});a.addCommand("mceDirectionRTL",function(){var d=a.dom.getParent(a.selection.getNode(),a.dom.isBlock);if(d){if(a.dom.getAttrib(d,"dir")!="rtl"){a.dom.setAttrib(d,"dir","rtl")}else{a.dom.setAttrib(d,"dir","")}}a.nodeChanged()});a.addButton("ltr",{title:"directionality.ltr_desc",cmd:"mceDirectionLTR"});a.addButton("rtl",{title:"directionality.rtl_desc",cmd:"mceDirectionRTL"});a.onNodeChange.add(c._nodeChange,c)},getInfo:function(){return{longname:"Directionality",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_nodeChange:function(b,a,e){var d=b.dom,c;e=d.getParent(e,d.isBlock);if(!e){a.setDisabled("ltr",1);a.setDisabled("rtl",1);return}c=d.getAttrib(e,"dir");a.setActive("ltr",c=="ltr");a.setDisabled("ltr",0);a.setActive("rtl",c=="rtl");a.setDisabled("rtl",0)}});tinymce.PluginManager.add("directionality",tinymce.plugins.Directionality)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/directionality/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/directionality/editor_plugin_src.js new file mode 100644 index 0000000..4444959 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/directionality/editor_plugin_src.js @@ -0,0 +1,82 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.Directionality', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + ed.addCommand('mceDirectionLTR', function() { + var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock); + + if (e) { + if (ed.dom.getAttrib(e, "dir") != "ltr") + ed.dom.setAttrib(e, "dir", "ltr"); + else + ed.dom.setAttrib(e, "dir", ""); + } + + ed.nodeChanged(); + }); + + ed.addCommand('mceDirectionRTL', function() { + var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock); + + if (e) { + if (ed.dom.getAttrib(e, "dir") != "rtl") + ed.dom.setAttrib(e, "dir", "rtl"); + else + ed.dom.setAttrib(e, "dir", ""); + } + + ed.nodeChanged(); + }); + + ed.addButton('ltr', {title : 'directionality.ltr_desc', cmd : 'mceDirectionLTR'}); + ed.addButton('rtl', {title : 'directionality.rtl_desc', cmd : 'mceDirectionRTL'}); + + ed.onNodeChange.add(t._nodeChange, t); + }, + + getInfo : function() { + return { + longname : 'Directionality', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + _nodeChange : function(ed, cm, n) { + var dom = ed.dom, dir; + + n = dom.getParent(n, dom.isBlock); + if (!n) { + cm.setDisabled('ltr', 1); + cm.setDisabled('rtl', 1); + return; + } + + dir = dom.getAttrib(n, 'dir'); + cm.setActive('ltr', dir == "ltr"); + cm.setDisabled('ltr', 0); + cm.setActive('rtl', dir == "rtl"); + cm.setDisabled('rtl', 0); + } + }); + + // Register plugin + tinymce.PluginManager.add('directionality', tinymce.plugins.Directionality); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/editor_plugin.js new file mode 100644 index 0000000..dbdd8ff --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/editor_plugin.js @@ -0,0 +1 @@ +(function(a){a.create("tinymce.plugins.EmotionsPlugin",{init:function(b,c){b.addCommand("mceEmotion",function(){b.windowManager.open({file:c+"/emotions.htm",width:250+parseInt(b.getLang("emotions.delta_width",0)),height:160+parseInt(b.getLang("emotions.delta_height",0)),inline:1},{plugin_url:c})});b.addButton("emotions",{title:"emotions.emotions_desc",cmd:"mceEmotion"})},getInfo:function(){return{longname:"Emotions",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/emotions",version:a.majorVersion+"."+a.minorVersion}}});a.PluginManager.add("emotions",a.plugins.EmotionsPlugin)})(tinymce); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/editor_plugin_src.js new file mode 100644 index 0000000..71d5416 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/editor_plugin_src.js @@ -0,0 +1,43 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function(tinymce) { + tinymce.create('tinymce.plugins.EmotionsPlugin', { + init : function(ed, url) { + // Register commands + ed.addCommand('mceEmotion', function() { + ed.windowManager.open({ + file : url + '/emotions.htm', + width : 250 + parseInt(ed.getLang('emotions.delta_width', 0)), + height : 160 + parseInt(ed.getLang('emotions.delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('emotions', {title : 'emotions.emotions_desc', cmd : 'mceEmotion'}); + }, + + getInfo : function() { + return { + longname : 'Emotions', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/emotions', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('emotions', tinymce.plugins.EmotionsPlugin); +})(tinymce); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/emotions.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/emotions.htm new file mode 100644 index 0000000..2c91002 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/emotions.htm @@ -0,0 +1,41 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#emotions_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/emotions.js"></script> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#emotions_dlg.title}</span> +<div align="center"> + <div class="title">{#emotions_dlg.title}:<br /><br /></div> + + <table role="presentation" border="0" cellspacing="0" cellpadding="4"> + <tr> + <td><a href="javascript:EmotionsDialog.insert('smiley-cool.gif','emotions_dlg.cool');"><img src="img/smiley-cool.gif" width="18" height="18" border="0" alt="{#emotions_dlg.cool}" title="{#emotions_dlg.cool}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-cry.gif','emotions_dlg.cry');"><img src="img/smiley-cry.gif" width="18" height="18" border="0" alt="{#emotions_dlg.cry}" title="{#emotions_dlg.cry}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-embarassed.gif','emotions_dlg.embarassed');"><img src="img/smiley-embarassed.gif" width="18" height="18" border="0" alt="{#emotions_dlg.embarassed}" title="{#emotions_dlg.embarassed}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-foot-in-mouth.gif','emotions_dlg.foot_in_mouth');"><img src="img/smiley-foot-in-mouth.gif" width="18" height="18" border="0" alt="{#emotions_dlg.foot_in_mouth}" title="{#emotions_dlg.foot_in_mouth}" /></a></td> + </tr> + <tr> + <td><a href="javascript:EmotionsDialog.insert('smiley-frown.gif','emotions_dlg.frown');"><img src="img/smiley-frown.gif" width="18" height="18" border="0" alt="{#emotions_dlg.frown}" title="{#emotions_dlg.frown}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-innocent.gif','emotions_dlg.innocent');"><img src="img/smiley-innocent.gif" width="18" height="18" border="0" alt="{#emotions_dlg.innocent}" title="{#emotions_dlg.innocent}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-kiss.gif','emotions_dlg.kiss');"><img src="img/smiley-kiss.gif" width="18" height="18" border="0" alt="{#emotions_dlg.kiss}" title="{#emotions_dlg.kiss}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-laughing.gif','emotions_dlg.laughing');"><img src="img/smiley-laughing.gif" width="18" height="18" border="0" alt="{#emotions_dlg.laughing}" title="{#emotions_dlg.laughing}" /></a></td> + </tr> + <tr> + <td><a href="javascript:EmotionsDialog.insert('smiley-money-mouth.gif','emotions_dlg.money_mouth');"><img src="img/smiley-money-mouth.gif" width="18" height="18" border="0" alt="{#emotions_dlg.money_mouth}" title="{#emotions_dlg.money_mouth}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-sealed.gif','emotions_dlg.sealed');"><img src="img/smiley-sealed.gif" width="18" height="18" border="0" alt="{#emotions_dlg.sealed}" title="{#emotions_dlg.sealed}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-smile.gif','emotions_dlg.smile');"><img src="img/smiley-smile.gif" width="18" height="18" border="0" alt="{#emotions_dlg.smile}" title="{#emotions_dlg.smile}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-surprised.gif','emotions_dlg.surprised');"><img src="img/smiley-surprised.gif" width="18" height="18" border="0" alt="{#emotions_dlg.surprised}" title="{#emotions_dlg.surprised}" /></a></td> + </tr> + <tr> + <td><a href="javascript:EmotionsDialog.insert('smiley-tongue-out.gif','emotions_dlg.tongue_out');"><img src="img/smiley-tongue-out.gif" width="18" height="18" border="0" alt="{#emotions_dlg.tongue-out}" title="{#emotions_dlg.tongue_out}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-undecided.gif','emotions_dlg.undecided');"><img src="img/smiley-undecided.gif" width="18" height="18" border="0" alt="{#emotions_dlg.undecided}" title="{#emotions_dlg.undecided}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-wink.gif','emotions_dlg.wink');"><img src="img/smiley-wink.gif" width="18" height="18" border="0" alt="{#emotions_dlg.wink}" title="{#emotions_dlg.wink}" /></a></td> + <td><a href="javascript:EmotionsDialog.insert('smiley-yell.gif','emotions_dlg.yell');"><img src="img/smiley-yell.gif" width="18" height="18" border="0" alt="{#emotions_dlg.yell}" title="{#emotions_dlg.yell}" /></a></td> + </tr> + </table> +</div> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-cool.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-cool.gif new file mode 100644 index 0000000000000000000000000000000000000000..ba90cc36fb0415d0273d1cd206bff63fd9c91fde GIT binary patch literal 354 zcmV-o0iFIwNk%w1VG;lm0Mr!#3ke00dJfFY%i+lrhK7V(RutUQJhPY;?(XfrsZKgL z7WLQ^zPO&zzav{)SL^9nBOw~z(=orMEH5uC-P_gr`uhCnASMa|$-iRw?m_(dUwU8) zq>Kx}s1_F$4FCWDA^8LW0018VEC2ui01^Na000Hw;3tYzX_jM3Qpv$_M?zI9i5=0S zX-{-uv=l<p*=3HIT}Of#RazKBq;Z@YZV4Iz0#Fnb06?MO>3%&P0s%m9Ox_a(m_c|u z01g3U0`Wll5)poVdma=N8y<3f0Sf~hXmTC}2oxMW4FdxUj+z4<0}lrX2nP=qkDRIt z9Ge*(qzMrj3jrIOjvI{`5eWzt3`G_T8yChG8w(a19SkK12@M(+799Zr9n=~PzBCmA z5)BU-)YKUd4H5!D9|!^o9kWIe9SH(WDHRk92}DZ?3})2$P@$55g90f0N)ZA8JID5J Aw*UYD literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-cry.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-cry.gif new file mode 100644 index 0000000000000000000000000000000000000000..74d897a4f6d22e814e2b054e98b8a75fb464b4be GIT binary patch literal 329 zcmV-P0k-}}Nk%w1VG;lm0Mr-&E)xPSit@9T3%;vR+|V+?t0A(pllJjXrMl7n=_A_a za^B+Su$LjvyC3@TIQZNZa##w=!k(SO^P#bO*w(eU#;{U83XFCU_V)J5wrb+;g2vkN z#>U24qVoOvY5)KLA^8LW0018VEC2ui01^Na000HX;3tY$X_jM3QUfCh%s^o(nF++< zc?Th6v=oL>*by8K!mhvwelUXuuW&&U9iGO3hM@>Njw{l^#0q9mWpcefdI;O$;efnY zkd~@r-o$*74FCWI1%d((4+jDz0va0>69^fI6%`W{8w!gU1pyL>prH>E0R<%k6Aq%H z4ij+^9TEwM5P}eh2@)L<B?|!!2MHGf4Gk9;2?q@U3tR{Vzzzx13409%2tlM00|hxd bJp}{XBh3p2-Gt%><~6+>@EpxfA0YrcPNsSu literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-embarassed.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-embarassed.gif new file mode 100644 index 0000000000000000000000000000000000000000..963a96b8a7593b1d8bcbab073abe5ee4e539dbf6 GIT binary patch literal 331 zcmV-R0kr-{Nk%w1VG;lm0MrryDh>j~yq&6%75dW~z^P39(NxsGDE{UkxtkIEq(S-a zRKlwv+S=Lr?>hbYY~sQ?c3T&ZcN_Nh_E<O%#>U3s(>Io6B&>WW`@bsw**)Ocy1bht z{*G6|uwwqUQ2+n{A^8LW0018VEC2ui01^Na000HZ;3tYwX_jM3YQ!c88=*-m*&&bO zILd=`w3KAC;8hxpif*w9ek6oqV-Z0L77fROK$B<?js^^gTnMs=8C02!K#=aEqQaFR z6pBm+GC@uzdU#EC4h0?_7ZwKt5f%vv7zzj_2!<RSkOKo436}{4lS7u67@C}(1%m_+ z1&^hgn~wz#bpZ=`7y=Uj023D&843#lB@6@x3J1!|$_fSq3|$Nh$PLU5&I{2a5)2&+ dN;`849os?-0Z|L<1OetM#T4=s(M}&B06V4ic~SrX literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-foot-in-mouth.gif new file mode 100644 index 0000000000000000000000000000000000000000..c7cf1011dad0e7500e29a278b0d395b253871109 GIT binary patch literal 342 zcmV-c0jd5+Nk%w1VG;lm0Q4UKxtkou#>SR@5BAv-%C>6y>>#+D4e#&nz^qMDItlpp zTG728+|V&?R13PIEBW(C`uh6d*t-1sZ^XQv;oDD}iYLOV7uVO;{`xl4#4tJ{0;h@! z>)kdc3IhA?Hvj+tA^8La0018VEC2ui01^Na06+!P;3tYuX_ljS7!u|-O)<bjtr*7$ zT@&J176)Q-futaag{0!(c%F`mWPvb3CKkn_!{urOiG{*4F_H*|3`HWLWDErJ2gy*p z5_gw^Q9S?@9yNjn4F(zs0}lW>I}TzP1q%xT4HOFwMJaO;2ml)!00<FsBL_bU2o)S0 z6$oPvIh!mG92pr;wj2)<2BUro4=xFK7{e|P3X3Z(kb=%N4>$)141pU08x3594IX?4 o5YuAA8yXz~76K1c;3^jg77WP185Rf^u}23N0sR5^q(T4yJ1sVN5dZ)H literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-frown.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-frown.gif new file mode 100644 index 0000000000000000000000000000000000000000..716f55e161bfebb1c3d34f0b0f40c177fc82c30b GIT binary patch literal 340 zcmV-a0jvH;Nk%w1VG;lm0MroxK_>;q#>Sw62=mns-On=0wransPVevT^YK{Dy(0YY zH)vE6x0?;Wqb>gZas1^OT0si>`ugD5y87}*#H$s=yq(wA*8cf7{`y+(+9J7|9QfT7 z`ROHiU=Y&6FaQ7mA^8LW0018VEC2ui01^Na000Hi;3tYvX_jM3N`@u~nju9hSuh^r zIEcp-wA7(NL0~2d#RP+(G!CPPA>o*KJjv_CkucCA5=K?AfF#RG2V*8BU@jL304|4P z2;PGRF@bj$et;Jf2pR_mVsIA<85|n}kQ*Bq42Ovqj*yy>6P0=h3X&9Z01y<C4-<w5 z1_YrDr5zn|3>yk~2N4w%7#RW^55W%`0vQ+-6(y_*2pqz~90*;x9}yM}%$UI(7t#$D mK_3Se1{4HKM+6iG7EmeH6$V631{L5n)#CyC0qx-*Apkoyg?w!Q literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-innocent.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-innocent.gif new file mode 100644 index 0000000000000000000000000000000000000000..334d49e0e60f2997c9ba24071764f95d9e08a5cc GIT binary patch literal 336 zcmV-W0k8f?Nk%w1VG;lm0MrryI4TI-%dP0m5~*<p%dw5l&RW5fRqyTWvyTq>+Y`T~ z7Rth){q{I_X%*S48uRZ|(b3V&wIKTX`u+WJzo<^$#wuY;3W|Cf{O29IkTAcaE&lpe z+P*^H)-tknA^-pYA^8LW0018VEC2ui01^Na000He;3tYwX_n)75QgVvNQ`6#5gcMm zEEG~blgXokptKAJgCU?%JT?yo<M~i%4gt?6Fz6~Am9UtD7-RyH0HP3SJKk^yXMmPa zIvd6X(CBm;d>s!R6cPtcQWh2siHlNI2L}ifQhgX02^InZ2?-ktkqVRyZJY^Trk|lv zovp437?1~d46O)?2(1i+2NDYk8<+_Kil!K!3njA^!I#dL8x<729}*B65mC=m5gHH@ iDi9P3f*VjB3KS4HDb_qqRul{0DI<mu`1#Z$Apkp|ihYg% literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-kiss.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-kiss.gif new file mode 100644 index 0000000000000000000000000000000000000000..4efd549ed31c44b1faac17ed34bb67abeb42baf8 GIT binary patch literal 338 zcmV-Y0j>T=Nk%w1VG;lm0Mrx!QauaC#>Vb6G=_5=^YB^9wrc376Sb5I-qJGf@9vZ# z5WlKU(!eVB+7tfnDXp0zyB`?BZ5IChalob*`uh6d*t+@dKGHcU+L|83yq*5~IoH?L zy`?Gp<{bX|SpWb4A^8LW0018VEC2ui01^Na000Hg;3tYyX_jM3R?Bl7&r(q;SsVx< zNd$5fv{ZsKA$SlL3&KN~a1tZRf*~1Ltk<iAv7k{Z2Z`pvc_hgXjpQ(sE;$1LK%<cl zILB_HNUzT|aeYk*31NL24jm1Pj2;JshKLOYi<FIzdjt-Z3NH$l9TpRW3rGzS3J|Ig z3K0!T3keh%6CNEM5fB0b7ZJA}6B#85Qy!Zb7Z(@}4jx>x9~2uL3<QX`4jKdu92-F& k2^$L&NFE+a6AK$qDbg7WL{1AC-ZjzT0r>&z-yb0WJDRY082|tP literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-laughing.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-laughing.gif new file mode 100644 index 0000000000000000000000000000000000000000..82c5b182e61d32bd394acae551eff180f1eebd26 GIT binary patch literal 343 zcmV-d0jT~*Nk%w1VG;lm0Q4UK!lp8=s;1-69HWK?p_PpF=Pd8<?!T%|a$ZRD@LAHn zAH%B}$j8NMQxe3yo%Yxe`tnEM*t)ly6Z-o4{{3<N_BV)iTG-Xox}Pq}wrbweGI?VY z)x$ATJq`Z*S^xk5A^8La0018VEC2ui01^Na06+!Q;3tYxX_ljCNL1w(@FNIM?McQs zUCse43&6o~nWQEM1qH(4xS9}(;$WOO79K(4!YDB=4TWdnFp@G7PJ%*7a3mS?2dVM6 zI-PsI;?Yo72@41ogoT6%7!Wvf7XS(g6$={!3l#|p07WTt5eE_j0}=-jaw7&93ke<& ztPmc77&)9Q5ETu3w-r$mq=2;*8x1bOE)WSgD-;DBG&Rl-3j&G;1_v6p1PlQe7Xb_e p!hQx5)nWo01l-^P9#i8g7Y7R(uB#dg2N$wO23!pP`bvcW06U9bekA|^ literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-money-mouth.gif new file mode 100644 index 0000000000000000000000000000000000000000..ca2451e102722e12e131ae53ea76989acbf191e2 GIT binary patch literal 321 zcmV-H0lxl6Nk%w1VG;lm0Mrx!DHsO6wwjoX9Kxs~!mLsE+7oVAHu>~Ygtcnp*fHAL z**;z>w3iC}`fmL6IkKB1N;3zEa}&zKpsu1;_V)HocR5-{J~BcYvE`YXhBnc@CfU=! za(E<?eig#P!T<mOA^8LW0018VEC2ui01^Na000HP;3tYyX_jM3Zp6bd53x}yNif>c zG>66zv=rqr;2j)}gKqE$ekcSD?}0=<bQ<7u!)Q1n00<H+ZZKxh#32EQBphsaG65Va zkpjTmkyjs@6kSLVZ3P8{5rzj0C4zW{h8>WLB?AWp85)qAL<a*U1aAfwq@|<=aCH)v z4*(Si6|WTl0-h2j3Q-&j3$U*X6&G0wG!zO07rYn<2p9_&0t3V&#uK|3*v<n4(?SXX Tyx|K0-72^q=pMvQA0YrcF~)Li literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-sealed.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-sealed.gif new file mode 100644 index 0000000000000000000000000000000000000000..fe66220c24b4da4526818a5d68f75a06d9985a29 GIT binary patch literal 323 zcmV-J0lfZ4Nk%w1VG;lm0Q4UKz^WI%xS#gj6sL~~h=_>d+P=4)6X4oXy{bw2>K^d$ z@6ERvva+(4ib~41YUkTEn1&#?rzrOHT>1I=Y*h`+%*@WtPUPg|!@EEI_d5LgZ>^Og z-qyBKJqy*wF8}}lA^8La0018VEC2ui01^Na06+!6;3tYxX_lj?7+U61R3gAaEg8x< zT>%mSfCwURnWQF&g=Q0ZxH1ulW`QtH0>O!5%iT_X0VBy_@EkOngU8?ye~=H!t21{= z9@Uj3a_UbE88~kh5Eq7rh!7QSBn1c?0|Off1&k^`5*QE<4-gm<K{;<6EEx|T9xkX( z8U`F%268SPbQ!cyH(M+Z5eAXJzYDnv2)q*nU0VcScnUiRg#;DT)C3n02t_Ik4G<9+ V78V#$4Gf}33K!HB7tSdm06S^%c-8;_ literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-smile.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-smile.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd27edfaaa29a70a8c4563c0eab9f18c74d374fd GIT binary patch literal 344 zcmV-e0jK^)Nk%w1VG;lm0Q4UKd0-C4#>SR<4C>Dj%C>6W(lWoQPVevT^YB^Fy&h6M z4YZgH{O~qtR1(Ci8T;lQ`uh6d*t-7xar*K{#Jrulo-Wtd*44u?{`oh#n;gQXGXDEo z_}UUC3IeK%0ssI2A^8La0018VEC2ui01^Na06+!R;3tYuX_ljSEE482&%+G^XK%|f zLKbCc4u{4-u|QG~LqamSTo?@JM3OKZAr!|Z2IzP@fY`=CIg$vA3qm46TowfLCt29I z6pDKuvnf~)83+sm9yW#?9s>^(89F=~2?!W44-6Ox2^vNza}fp^9v&G65pp936%Gg+ z6HpTy2o4oGoh+>l3Q)KVQwybl2oo*<4a3D469|nfEii|MH4`}p1_cZp0ssj%2>=2d q41Na?)CpS;4gvxWVpZcR76uLludD?Q1{SnP2NnVU0rZ&)0RTIit8@_n literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-surprised.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-surprised.gif new file mode 100644 index 0000000000000000000000000000000000000000..0cc9bb71cca4cdeafbb248ce7e07c3708c1cbd64 GIT binary patch literal 338 zcmV-Y0j>T=Nk%w1VG;lm0Q4UK`{WwN#>SnDDC*4*{OcpiwransPVevTQacIr@mkQp zCf(06s)_=>r7UYx48o@u`uh6d*t-7rH~ji<`P&oj;5Wp)o!8ga`SV6TA_BIW5#ZWV z{`*)c3<AWsL;wH)A^8La0018VEC2ui01^Na06+!L;3tYuX_ljSXp`hR4gtVa&1uI7 zU6#>2kA}f=futY?#YE7kxGD|7L}4&OEDw$hkm+~<00QS>F_H?J#bz?uEHnl42f5(9 z5O)`6Q9V2o5;YVLUK)Y`7!Nr+4GMq?85s%^2?`BGDRU798Vn2?1`%>22R{iO0u>bk z9tlA?nk*O<3zHJH6&Mp5qALj)E(mxM!Y&vII4dm@1Ov{`f*8pL3xPEVUI>D>1_uxa kNm?`6VH{N6Di;P13m6<67z+;u7qCYM7XkVK^`jvGJD~P?KL7v# literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-tongue-out.gif new file mode 100644 index 0000000000000000000000000000000000000000..2075dc16058f1f17912167675ce5cfb9986fc71d GIT binary patch literal 328 zcmV-O0k{4~Nk%w1VG;lm0Mrx!CJF+^#>SU@3-{U*rx+Q^wrc$ABfqLn@9*x?z8(4X zSW-O=@){bmmI~g|GQXoP);c<FSP}d3M*jVA`uh6d*t))=8CnMdwl62dyq*2^H`mwJ z)x$CM;3E1`Q~&?~A^8LW0018VEC2ui01^Na000HW;3tYyX_jM3R)^Iz)=^O^Su~t7 zO$yf(v=riDQ79xxiP7>vj3|f1M8e@{G*!tYaiCEujj1NGxRN#6#tiCETo+{x{Hkzt z5k-kPvcD=V2nb<UR~-feh=~dffrA={iID>mjCgL6k{uF&2nP-t0s;w<385Nx2oxDb z9T5Pp7qJl?3Kkh9oe2sCr5F$p7zPSlsUH*@54w*83=9Or4;w)r2pcU95(FL|1Th;< aDaRQH4;Tal7#Y$v#?=Au0pHUfApkpvZg^t= literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-undecided.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-undecided.gif new file mode 100644 index 0000000000000000000000000000000000000000..bef7e257303f8243c89787e7a7f9955dd1f112e2 GIT binary patch literal 337 zcmV-X0j~Z>Nk%w1VG;lm0MroxDi#99#>R?y8~4}{%C>6#>?OadPVevTr-=vi@LATn z4rERY-qJF+n+?CCE&B3D{{3<K`ugD5x<W4p!>Shh?>WT0o%`b%*Voqm`dL;(4F35y zc485^n;g!+Bme*aA^8LW0018VEC2ui01^Na000Hf;3tYvX_jM3N=AnuogqakNi<9X zK?&0kwA8^tNn{?C$|IAYI1ZzT!2>}iuMddFK#NEkRl!7%6brJAnUs;)XcnA}TNBSP zxQ9;SvEfwYeSaGd2^|LqU~(QF1qBxr3Ii7x84ZVt8wCTKoSYAqc?p`G2onnpk`IOl z1`HLGj}riN2p1K12N4z&8IBDc6tEWs859;JtRB6>lf+xO9}yT19toMv8wnl`7(pKg j7zPv!OGgY81{hE&(iR3pP6ig;HPPS!_yOwPA0Yrc)=Yf3 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-wink.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-wink.gif new file mode 100644 index 0000000000000000000000000000000000000000..0631c7616ec8624ddeee02b633326f697ee72f80 GIT binary patch literal 350 zcmV-k0ipg!Nk%w1VG;lm0Q4UK(ZVUl#>Sn03F^-g-qAA3wransPV?|t@9*x%vmQ`7 z4E*pcw3rOOq%3t@4*K#({N^40{c-yG`rz2Q!KfI-yq*61HrBop*VoqW<}&{JS@_x# zwwfF$4Fdh~IsgCwA^8La0018VEC2ui01^Na06+!X;3tYwX_ljiFp=e23$zWxW@`*G zN?2ty6iUNT!AMdPLn89<I6VNsBa$#2B^8PW0&#S{9S2uKsT@fK2H_Bi90-iU`I97Q z0E%zIqENUr1Xc(f2MYrXHi;Vy0}u}!Iy?;k2OcpH3myjm4Mr(+69yat0vrYtb0Y{q z2O3Qt4;lwTI-o2K1Rfax9u5ky5e%q<2M-n*2^lU94lWM|kSi@QiitH3IS2;18v+g& wHWv;88y<lO650S7F$tszn0E%~Di{V71hK9J6b2ZzNDyEMKrq0+R3QKWI|*@ij{pDw literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-yell.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/img/smiley-yell.gif new file mode 100644 index 0000000000000000000000000000000000000000..648e6e879123fe49beebbc1f3635141864a79a9c GIT binary patch literal 336 zcmV-W0k8f?Nk%w1VG;lm0MrryG8O{K#>IbS7WCB_mWF$+hzY-{PWkp(?(Xf;zbH~P z3jOdj?W+^YwrakfE8fyG&5jTBz!3WS`fgM_;MltQ+c}4GO8)(E`S3`@yq&d~5!ct& z)v79NObo)O7XSbNA^8LW0018VEC2ui01^Na000He;3tYwX_jM3QifI(nn6h_*=Wyk zUB{y}v=qYOIUF#R3dZPhAVv~H;(|<CF_(maCZTAu39B_R)y$%~g`mSpayo)VZ;Q|z z7ZnA-;Q%Nq3riXZbr%Z>a2yN_5FH&J0|$eJ3kw4gj1Y?v5d#>LMV12^6BYy$1)ZKA zga!|m2?POz0R)f>4+aPl8KD{gz`+G_9vLMFQU?RU!8uyH9}*i52|cC+7S0YEK_3Vk i1|APfM-Ltb8&4_H83sg61{vHn(cc000qNZzApkp<uzFPh literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/js/emotions.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/js/emotions.js new file mode 100644 index 0000000..c549367 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/js/emotions.js @@ -0,0 +1,22 @@ +tinyMCEPopup.requireLangPack(); + +var EmotionsDialog = { + init : function(ed) { + tinyMCEPopup.resizeToInnerSize(); + }, + + insert : function(file, title) { + var ed = tinyMCEPopup.editor, dom = ed.dom; + + tinyMCEPopup.execCommand('mceInsertContent', false, dom.createHTML('img', { + src : tinyMCEPopup.getWindowArg('plugin_url') + '/img/' + file, + alt : ed.getLang(title), + title : ed.getLang(title), + border : 0 + })); + + tinyMCEPopup.close(); + } +}; + +tinyMCEPopup.onInit.add(EmotionsDialog.init, EmotionsDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/de_dlg.js new file mode 100644 index 0000000..9ef427c --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.emotions_dlg',{cry:"Weinend",cool:"Cool",desc:"Smilies",title:"Smiley einf\u00fcgen",yell:"Br\u00fcllend",wink:"Zwinkernd",undecided:"Unentschlossen","tongue_out":"Zunge raus",surprised:"\u00dcberrascht",smile:"L\u00e4chelnd",sealed:"Verschlossen","money_mouth":"Geld",laughing:"Lachend",kiss:"K\u00fcssend",innocent:"Unschuldig",frown:"Stirnrunzelnd","foot_in_mouth":"Reingefallen",embarassed:"Verlegen",usage:"Navigation mit linken und rechten Pfeilen."}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/en_dlg.js new file mode 100644 index 0000000..f5aafc3 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.emotions_dlg',{cry:"Cry",cool:"Cool",desc:"Emotions",title:"Insert Emotion",yell:"Yell",wink:"Wink",undecided:"Undecided","tongue_out":"Tongue Out",surprised:"Surprised",smile:"Smile",sealed:"Sealed","money_mouth":"Money Mouth",laughing:"Laughing",kiss:"Kiss",innocent:"Innocent",frown:"Frown","foot_in_mouth":"Foot in Mouth",embarassed:"Embarassed",usage:"Use left and right arrows to navigate."}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/fr_dlg.js new file mode 100644 index 0000000..b312b0d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.emotions_dlg',{cry:"En pleurs",cool:"Cool",desc:"\u00c9motic\u00f4nes",title:"Ins\u00e9rer une \u00e9motic\u00f4ne",yell:"Criant",wink:"Clin d\'\u0153il",undecided:"Incertain","tongue_out":"Langue tir\u00e9e",surprised:"Surpris",smile:"Sourire",sealed:"Bouche cousue","money_mouth":"Avare",laughing:"Rigolant",kiss:"Bisou",innocent:"Innocent",frown:"D\u00e9\u00e7u","foot_in_mouth":"Pied de nez",embarassed:"Embarrass\u00e9"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/it_dlg.js new file mode 100644 index 0000000..64c8e5a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/emotions/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.emotions_dlg',{cry:"Piango",cool:"Fico",desc:"Faccina",title:"Inserisci faccina",yell:"Arrabbiato",wink:"Occhiolino",undecided:"Indeciso","tongue_out":"Linguaccia",surprised:"Sorpreso",smile:"Sorridente",sealed:"Bocca sigillata","money_mouth":"Bocca danarosa",laughing:"Risatona",kiss:"Bacio",innocent:"Santarellino",frown:"Triste","foot_in_mouth":"Piede in bocca",embarassed:"Imbarazzato"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/example/dialog.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/dialog.htm new file mode 100644 index 0000000..50b2b34 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/dialog.htm @@ -0,0 +1,22 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#example_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/dialog.js"></script> +</head> +<body> + +<form onsubmit="ExampleDialog.insert();return false;" action="#"> + <p>Here is a example dialog.</p> + <p>Selected text: <input id="someval" name="someval" type="text" class="text" /></p> + <p>Custom arg: <input id="somearg" name="somearg" type="text" class="text" /></p> + + <div class="mceActionPanel"> + <input type="button" id="insert" name="insert" value="{#insert}" onclick="ExampleDialog.insert();" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> + +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/example/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/editor_plugin.js new file mode 100644 index 0000000..ec1f81e --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.PluginManager.requireLangPack("example");tinymce.create("tinymce.plugins.ExamplePlugin",{init:function(a,b){a.addCommand("mceExample",function(){a.windowManager.open({file:b+"/dialog.htm",width:320+parseInt(a.getLang("example.delta_width",0)),height:120+parseInt(a.getLang("example.delta_height",0)),inline:1},{plugin_url:b,some_custom_arg:"custom arg"})});a.addButton("example",{title:"example.desc",cmd:"mceExample",image:b+"/img/example.gif"});a.onNodeChange.add(function(d,c,e){c.setActive("example",e.nodeName=="IMG")})},createControl:function(b,a){return null},getInfo:function(){return{longname:"Example plugin",author:"Some author",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example",version:"1.0"}}});tinymce.PluginManager.add("example",tinymce.plugins.ExamplePlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/example/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/editor_plugin_src.js new file mode 100644 index 0000000..9a0e7da --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/editor_plugin_src.js @@ -0,0 +1,84 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + // Load plugin specific language pack + tinymce.PluginManager.requireLangPack('example'); + + tinymce.create('tinymce.plugins.ExamplePlugin', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed, url) { + // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample'); + ed.addCommand('mceExample', function() { + ed.windowManager.open({ + file : url + '/dialog.htm', + width : 320 + parseInt(ed.getLang('example.delta_width', 0)), + height : 120 + parseInt(ed.getLang('example.delta_height', 0)), + inline : 1 + }, { + plugin_url : url, // Plugin absolute URL + some_custom_arg : 'custom arg' // Custom argument + }); + }); + + // Register example button + ed.addButton('example', { + title : 'example.desc', + cmd : 'mceExample', + image : url + '/img/example.gif' + }); + + // Add a node change handler, selects the button in the UI when a image is selected + ed.onNodeChange.add(function(ed, cm, n) { + cm.setActive('example', n.nodeName == 'IMG'); + }); + }, + + /** + * Creates control instances based in the incomming name. This method is normally not + * needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons + * but you sometimes need to create more complex controls like listboxes, split buttons etc then this + * method can be used to create those. + * + * @param {String} n Name of the control to create. + * @param {tinymce.ControlManager} cm Control manager to use inorder to create new control. + * @return {tinymce.ui.Control} New control instance or null if no control was created. + */ + createControl : function(n, cm) { + return null; + }, + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Example plugin', + author : 'Some author', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example', + version : "1.0" + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('example', tinymce.plugins.ExamplePlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/example/img/example.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/img/example.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ab5da4461113d2af579898528246fdbe52ecd00 GIT binary patch literal 87 zcmZ?wbhEHb6k!lyn83&Y1dNP~ia%L^OhyJB5FaGNz@*pGzw+SQ`#f{}FJ-?!v#V)e mtsGNfpJeCKSAiOz**>0`XR2{OVa>-G_df0vaY<rium%9X5FI1{ literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/example/js/dialog.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/js/dialog.js new file mode 100644 index 0000000..fa83411 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/js/dialog.js @@ -0,0 +1,19 @@ +tinyMCEPopup.requireLangPack(); + +var ExampleDialog = { + init : function() { + var f = document.forms[0]; + + // Get the selected contents as text and place it in the input + f.someval.value = tinyMCEPopup.editor.selection.getContent({format : 'text'}); + f.somearg.value = tinyMCEPopup.getWindowArg('some_custom_arg'); + }, + + insert : function() { + // Insert the contents from the input into the document + tinyMCEPopup.editor.execCommand('mceInsertContent', false, document.forms[0].someval.value); + tinyMCEPopup.close(); + } +}; + +tinyMCEPopup.onInit.add(ExampleDialog.init, ExampleDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/example/langs/en.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/langs/en.js new file mode 100644 index 0000000..e0784f8 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/langs/en.js @@ -0,0 +1,3 @@ +tinyMCE.addI18n('en.example',{ + desc : 'This is just a template button' +}); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/example/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/langs/en_dlg.js new file mode 100644 index 0000000..ebcf948 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/example/langs/en_dlg.js @@ -0,0 +1,3 @@ +tinyMCE.addI18n('en.example_dlg',{ + title : 'This is just a example title' +}); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/example_dependency/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/example_dependency/editor_plugin.js new file mode 100644 index 0000000..0a4551d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/example_dependency/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.ExampleDependencyPlugin",{init:function(a,b){},getInfo:function(){return{longname:"Example Dependency plugin",author:"Some author",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example_dependency",version:"1.0"}}});tinymce.PluginManager.add("example_dependency",tinymce.plugins.ExampleDependencyPlugin,["example"])})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/example_dependency/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/example_dependency/editor_plugin_src.js new file mode 100644 index 0000000..e1c55e4 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/example_dependency/editor_plugin_src.js @@ -0,0 +1,50 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + + tinymce.create('tinymce.plugins.ExampleDependencyPlugin', { + /** + * Initializes the plugin, this will be executed after the plugin has been created. + * This call is done before the editor instance has finished it's initialization so use the onInit event + * of the editor instance to intercept that event. + * + * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. + * @param {string} url Absolute URL to where the plugin is located. + */ + init : function(ed, url) { + }, + + + /** + * Returns information about the plugin as a name/value array. + * The current keys are longname, author, authorurl, infourl and version. + * + * @return {Object} Name/value array containing information about the plugin. + */ + getInfo : function() { + return { + longname : 'Example Dependency plugin', + author : 'Some author', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example_dependency', + version : "1.0" + }; + } + }); + + /** + * Register the plugin, specifying the list of the plugins that this plugin depends on. They are specified in a list, with the list loaded in order. + * plugins in this list will be initialised when this plugin is initialized. (before the init method is called). + * plugins in a depends list should typically be specified using the short name). If neccesary this can be done + * with an object which has the url to the plugin and the shortname. + */ + tinymce.PluginManager.add('example_dependency', tinymce.plugins.ExampleDependencyPlugin, ['example']); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/css/fullpage.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/css/fullpage.css new file mode 100644 index 0000000..2675cec --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/css/fullpage.css @@ -0,0 +1,143 @@ +/* Hide the advanced tab */ +#advanced_tab { + display: none; +} + +#metatitle, #metakeywords, #metadescription, #metaauthor, #metacopyright { + width: 280px; +} + +#doctype, #docencoding { + width: 200px; +} + +#langcode { + width: 30px; +} + +#bgimage { + width: 220px; +} + +#fontface { + width: 240px; +} + +#leftmargin, #rightmargin, #topmargin, #bottommargin { + width: 50px; +} + +.panel_wrapper div.current { + height: 400px; +} + +#stylesheet, #style { + width: 240px; +} + +#doctypes { + width: 200px; +} + +/* Head list classes */ + +.headlistwrapper { + width: 100%; +} + +.selected { + border: 1px solid #0A246A; + background-color: #B6BDD2; +} + +.toolbar { + width: 100%; +} + +#headlist { + width: 100%; + margin-top: 3px; + font-size: 11px; +} + +#info, #title_element, #meta_element, #script_element, #style_element, #base_element, #link_element, #comment_element, #unknown_element { + display: none; +} + +#addmenu { + position: absolute; + border: 1px solid gray; + display: none; + z-index: 100; + background-color: white; +} + +#addmenu a { + display: block; + width: 100%; + line-height: 20px; + text-decoration: none; + background-color: white; +} + +#addmenu a:hover { + background-color: #B6BDD2; + color: black; +} + +#addmenu span { + padding-left: 10px; + padding-right: 10px; +} + +#updateElementPanel { + display: none; +} + +#script_element .panel_wrapper div.current { + height: 108px; +} + +#style_element .panel_wrapper div.current { + height: 108px; +} + +#link_element .panel_wrapper div.current { + height: 140px; +} + +#element_script_value { + width: 100%; + height: 100px; +} + +#element_comment_value { + width: 100%; + height: 120px; +} + +#element_style_value { + width: 100%; + height: 100px; +} + +#element_title, #element_script_src, #element_meta_name, #element_meta_content, #element_base_href, #element_link_href, #element_link_title { + width: 250px; +} + +.updateElementButton { + margin-top: 3px; +} + +/* MSIE specific styles */ + +* html .addbutton, * html .removebutton, * html .moveupbutton, * html .movedownbutton { + width: 22px; + height: 22px; +} + +textarea { + height: 55px; +} + +.panel_wrapper div.current {height:420px;} \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/editor_plugin.js new file mode 100644 index 0000000..dcf7602 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/editor_plugin.js @@ -0,0 +1 @@ +(function(){var b=tinymce.each,a=tinymce.html.Node;tinymce.create("tinymce.plugins.FullPagePlugin",{init:function(c,d){var e=this;e.editor=c;c.addCommand("mceFullPageProperties",function(){c.windowManager.open({file:d+"/fullpage.htm",width:430+parseInt(c.getLang("fullpage.delta_width",0)),height:495+parseInt(c.getLang("fullpage.delta_height",0)),inline:1},{plugin_url:d,data:e._htmlToData()})});c.addButton("fullpage",{title:"fullpage.desc",cmd:"mceFullPageProperties"});c.onBeforeSetContent.add(e._setContent,e);c.onGetContent.add(e._getContent,e)},getInfo:function(){return{longname:"Fullpage",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_htmlToData:function(){var f=this._parseHeader(),h={},c,i,g,e=this.editor;function d(l,j){var k=l.attr(j);return k||""}h.fontface=e.getParam("fullpage_default_fontface","");h.fontsize=e.getParam("fullpage_default_fontsize","");i=f.firstChild;if(i.type==7){h.xml_pi=true;g=/encoding="([^"]+)"/.exec(i.value);if(g){h.docencoding=g[1]}}i=f.getAll("#doctype")[0];if(i){h.doctype="<!DOCTYPE"+i.value+">"}i=f.getAll("title")[0];if(i&&i.firstChild){h.metatitle=i.firstChild.value}b(f.getAll("meta"),function(m){var k=m.attr("name"),j=m.attr("http-equiv"),l;if(k){h["meta"+k.toLowerCase()]=m.attr("content")}else{if(j=="Content-Type"){l=/charset\s*=\s*(.*)\s*/gi.exec(m.attr("content"));if(l){h.docencoding=l[1]}}}});i=f.getAll("html")[0];if(i){h.langcode=d(i,"lang")||d(i,"xml:lang")}i=f.getAll("link")[0];if(i&&i.attr("rel")=="stylesheet"){h.stylesheet=i.attr("href")}i=f.getAll("body")[0];if(i){h.langdir=d(i,"dir");h.style=d(i,"style");h.visited_color=d(i,"vlink");h.link_color=d(i,"link");h.active_color=d(i,"alink")}return h},_dataToHtml:function(g){var f,d,h,j,k,e=this.editor.dom;function c(n,l,m){n.attr(l,m?m:undefined)}function i(l){if(d.firstChild){d.insert(l,d.firstChild)}else{d.append(l)}}f=this._parseHeader();d=f.getAll("head")[0];if(!d){j=f.getAll("html")[0];d=new a("head",1);if(j.firstChild){j.insert(d,j.firstChild,true)}else{j.append(d)}}j=f.firstChild;if(g.xml_pi){k='version="1.0"';if(g.docencoding){k+=' encoding="'+g.docencoding+'"'}if(j.type!=7){j=new a("xml",7);f.insert(j,f.firstChild,true)}j.value=k}else{if(j&&j.type==7){j.remove()}}j=f.getAll("#doctype")[0];if(g.doctype){if(!j){j=new a("#doctype",10);if(g.xml_pi){f.insert(j,f.firstChild)}else{i(j)}}j.value=g.doctype.substring(9,g.doctype.length-1)}else{if(j){j.remove()}}j=f.getAll("title")[0];if(g.metatitle){if(!j){j=new a("title",1);j.append(new a("#text",3)).value=g.metatitle;i(j)}}if(g.docencoding){j=null;b(f.getAll("meta"),function(l){if(l.attr("http-equiv")=="Content-Type"){j=l}});if(!j){j=new a("meta",1);j.attr("http-equiv","Content-Type");j.shortEnded=true;i(j)}j.attr("content","text/html; charset="+g.docencoding)}b("keywords,description,author,copyright,robots".split(","),function(m){var l=f.getAll("meta"),n,p,o=g["meta"+m];for(n=0;n<l.length;n++){p=l[n];if(p.attr("name")==m){if(o){p.attr("content",o)}else{p.remove()}return}}if(o){j=new a("meta",1);j.attr("name",m);j.attr("content",o);j.shortEnded=true;i(j)}});j=f.getAll("link")[0];if(j&&j.attr("rel")=="stylesheet"){if(g.stylesheet){j.attr("href",g.stylesheet)}else{j.remove()}}else{if(g.stylesheet){j=new a("link",1);j.attr({rel:"stylesheet",text:"text/css",href:g.stylesheet});j.shortEnded=true;i(j)}}j=f.getAll("body")[0];if(j){c(j,"dir",g.langdir);c(j,"style",g.style);c(j,"vlink",g.visited_color);c(j,"link",g.link_color);c(j,"alink",g.active_color);e.setAttribs(this.editor.getBody(),{style:g.style,dir:g.dir,vLink:g.visited_color,link:g.link_color,aLink:g.active_color})}j=f.getAll("html")[0];if(j){c(j,"lang",g.langcode);c(j,"xml:lang",g.langcode)}h=new tinymce.html.Serializer({validate:false,indent:true,apply_source_formatting:true,indent_before:"head,html,body,meta,title,script,link,style",indent_after:"head,html,body,meta,title,script,link,style"}).serialize(f);this.head=h.substring(0,h.indexOf("</body>"))},_parseHeader:function(){return new tinymce.html.DomParser({validate:false,root_name:"#document"}).parse(this.head)},_setContent:function(g,d){var m=this,i,c,h=d.content,f,l="",e=m.editor.dom,j;function k(n){return n.replace(/<\/?[A-Z]+/g,function(o){return o.toLowerCase()})}if(d.format=="raw"&&m.head){return}if(d.source_view&&g.getParam("fullpage_hide_in_source_view")){return}h=h.replace(/<(\/?)BODY/gi,"<$1body");i=h.indexOf("<body");if(i!=-1){i=h.indexOf(">",i);m.head=k(h.substring(0,i+1));c=h.indexOf("</body",i);if(c==-1){c=h.length}d.content=h.substring(i+1,c);m.foot=k(h.substring(c))}else{m.head=this._getDefaultHeader();m.foot="\n</body>\n</html>"}f=m._parseHeader();b(f.getAll("style"),function(n){if(n.firstChild){l+=n.firstChild.value}});j=f.getAll("body")[0];if(j){e.setAttribs(m.editor.getBody(),{style:j.attr("style")||"",dir:j.attr("dir")||"",vLink:j.attr("vlink")||"",link:j.attr("link")||"",aLink:j.attr("alink")||""})}e.remove("fullpage_styles");if(l){e.add(m.editor.getDoc().getElementsByTagName("head")[0],"style",{id:"fullpage_styles"},l);j=e.get("fullpage_styles");if(j.styleSheet){j.styleSheet.cssText=l}}},_getDefaultHeader:function(){var f="",c=this.editor,e,d="";if(c.getParam("fullpage_default_xml_pi")){f+='<?xml version="1.0" encoding="'+c.getParam("fullpage_default_encoding","ISO-8859-1")+'" ?>\n'}f+=c.getParam("fullpage_default_doctype",'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">');f+="\n<html>\n<head>\n";if(e=c.getParam("fullpage_default_title")){f+="<title>"+e+"</title>\n"}if(e=c.getParam("fullpage_default_encoding")){f+='<meta http-equiv="Content-Type" content="text/html; charset='+e+'" />\n'}if(e=c.getParam("fullpage_default_font_family")){d+="font-family: "+e+";"}if(e=c.getParam("fullpage_default_font_size")){d+="font-size: "+e+";"}if(e=c.getParam("fullpage_default_text_color")){d+="color: "+e+";"}f+="</head>\n<body"+(d?' style="'+d+'"':"")+">\n";return f},_getContent:function(d,e){var c=this;if(!e.source_view||!d.getParam("fullpage_hide_in_source_view")){e.content=tinymce.trim(c.head)+"\n"+tinymce.trim(e.content)+"\n"+tinymce.trim(c.foot)}}});tinymce.PluginManager.add("fullpage",tinymce.plugins.FullPagePlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/editor_plugin_src.js new file mode 100644 index 0000000..23de7c5 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/editor_plugin_src.js @@ -0,0 +1,405 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var each = tinymce.each, Node = tinymce.html.Node; + + tinymce.create('tinymce.plugins.FullPagePlugin', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceFullPageProperties', function() { + ed.windowManager.open({ + file : url + '/fullpage.htm', + width : 430 + parseInt(ed.getLang('fullpage.delta_width', 0)), + height : 495 + parseInt(ed.getLang('fullpage.delta_height', 0)), + inline : 1 + }, { + plugin_url : url, + data : t._htmlToData() + }); + }); + + // Register buttons + ed.addButton('fullpage', {title : 'fullpage.desc', cmd : 'mceFullPageProperties'}); + + ed.onBeforeSetContent.add(t._setContent, t); + ed.onGetContent.add(t._getContent, t); + }, + + getInfo : function() { + return { + longname : 'Fullpage', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private plugin internal methods + + _htmlToData : function() { + var headerFragment = this._parseHeader(), data = {}, nodes, elm, matches, editor = this.editor; + + function getAttr(elm, name) { + var value = elm.attr(name); + + return value || ''; + }; + + // Default some values + data.fontface = editor.getParam("fullpage_default_fontface", ""); + data.fontsize = editor.getParam("fullpage_default_fontsize", ""); + + // Parse XML PI + elm = headerFragment.firstChild; + if (elm.type == 7) { + data.xml_pi = true; + matches = /encoding="([^"]+)"/.exec(elm.value); + if (matches) + data.docencoding = matches[1]; + } + + // Parse doctype + elm = headerFragment.getAll('#doctype')[0]; + if (elm) + data.doctype = '<!DOCTYPE' + elm.value + ">"; + + // Parse title element + elm = headerFragment.getAll('title')[0]; + if (elm && elm.firstChild) { + data.metatitle = elm.firstChild.value; + } + + // Parse meta elements + each(headerFragment.getAll('meta'), function(meta) { + var name = meta.attr('name'), httpEquiv = meta.attr('http-equiv'), matches; + + if (name) + data['meta' + name.toLowerCase()] = meta.attr('content'); + else if (httpEquiv == "Content-Type") { + matches = /charset\s*=\s*(.*)\s*/gi.exec(meta.attr('content')); + + if (matches) + data.docencoding = matches[1]; + } + }); + + // Parse html attribs + elm = headerFragment.getAll('html')[0]; + if (elm) + data.langcode = getAttr(elm, 'lang') || getAttr(elm, 'xml:lang'); + + // Parse stylesheet + elm = headerFragment.getAll('link')[0]; + if (elm && elm.attr('rel') == 'stylesheet') + data.stylesheet = elm.attr('href'); + + // Parse body parts + elm = headerFragment.getAll('body')[0]; + if (elm) { + data.langdir = getAttr(elm, 'dir'); + data.style = getAttr(elm, 'style'); + data.visited_color = getAttr(elm, 'vlink'); + data.link_color = getAttr(elm, 'link'); + data.active_color = getAttr(elm, 'alink'); + } + + return data; + }, + + _dataToHtml : function(data) { + var headerFragment, headElement, html, elm, value, dom = this.editor.dom; + + function setAttr(elm, name, value) { + elm.attr(name, value ? value : undefined); + }; + + function addHeadNode(node) { + if (headElement.firstChild) + headElement.insert(node, headElement.firstChild); + else + headElement.append(node); + }; + + headerFragment = this._parseHeader(); + headElement = headerFragment.getAll('head')[0]; + if (!headElement) { + elm = headerFragment.getAll('html')[0]; + headElement = new Node('head', 1); + + if (elm.firstChild) + elm.insert(headElement, elm.firstChild, true); + else + elm.append(headElement); + } + + // Add/update/remove XML-PI + elm = headerFragment.firstChild; + if (data.xml_pi) { + value = 'version="1.0"'; + + if (data.docencoding) + value += ' encoding="' + data.docencoding + '"'; + + if (elm.type != 7) { + elm = new Node('xml', 7); + headerFragment.insert(elm, headerFragment.firstChild, true); + } + + elm.value = value; + } else if (elm && elm.type == 7) + elm.remove(); + + // Add/update/remove doctype + elm = headerFragment.getAll('#doctype')[0]; + if (data.doctype) { + if (!elm) { + elm = new Node('#doctype', 10); + + if (data.xml_pi) + headerFragment.insert(elm, headerFragment.firstChild); + else + addHeadNode(elm); + } + + elm.value = data.doctype.substring(9, data.doctype.length - 1); + } else if (elm) + elm.remove(); + + // Add/update/remove title + elm = headerFragment.getAll('title')[0]; + if (data.metatitle) { + if (!elm) { + elm = new Node('title', 1); + elm.append(new Node('#text', 3)).value = data.metatitle; + addHeadNode(elm); + } + } + + // Add meta encoding + if (data.docencoding) { + elm = null; + each(headerFragment.getAll('meta'), function(meta) { + if (meta.attr('http-equiv') == 'Content-Type') + elm = meta; + }); + + if (!elm) { + elm = new Node('meta', 1); + elm.attr('http-equiv', 'Content-Type'); + elm.shortEnded = true; + addHeadNode(elm); + } + + elm.attr('content', 'text/html; charset=' + data.docencoding); + } + + // Add/update/remove meta + each('keywords,description,author,copyright,robots'.split(','), function(name) { + var nodes = headerFragment.getAll('meta'), i, meta, value = data['meta' + name]; + + for (i = 0; i < nodes.length; i++) { + meta = nodes[i]; + + if (meta.attr('name') == name) { + if (value) + meta.attr('content', value); + else + meta.remove(); + + return; + } + } + + if (value) { + elm = new Node('meta', 1); + elm.attr('name', name); + elm.attr('content', value); + elm.shortEnded = true; + + addHeadNode(elm); + } + }); + + // Add/update/delete link + elm = headerFragment.getAll('link')[0]; + if (elm && elm.attr('rel') == 'stylesheet') { + if (data.stylesheet) + elm.attr('href', data.stylesheet); + else + elm.remove(); + } else if (data.stylesheet) { + elm = new Node('link', 1); + elm.attr({ + rel : 'stylesheet', + text : 'text/css', + href : data.stylesheet + }); + elm.shortEnded = true; + + addHeadNode(elm); + } + + // Update body attributes + elm = headerFragment.getAll('body')[0]; + if (elm) { + setAttr(elm, 'dir', data.langdir); + setAttr(elm, 'style', data.style); + setAttr(elm, 'vlink', data.visited_color); + setAttr(elm, 'link', data.link_color); + setAttr(elm, 'alink', data.active_color); + + // Update iframe body as well + dom.setAttribs(this.editor.getBody(), { + style : data.style, + dir : data.dir, + vLink : data.visited_color, + link : data.link_color, + aLink : data.active_color + }); + } + + // Set html attributes + elm = headerFragment.getAll('html')[0]; + if (elm) { + setAttr(elm, 'lang', data.langcode); + setAttr(elm, 'xml:lang', data.langcode); + } + + // Serialize header fragment and crop away body part + html = new tinymce.html.Serializer({ + validate: false, + indent: true, + apply_source_formatting : true, + indent_before: 'head,html,body,meta,title,script,link,style', + indent_after: 'head,html,body,meta,title,script,link,style' + }).serialize(headerFragment); + + this.head = html.substring(0, html.indexOf('</body>')); + }, + + _parseHeader : function() { + // Parse the contents with a DOM parser + return new tinymce.html.DomParser({ + validate: false, + root_name: '#document' + }).parse(this.head); + }, + + _setContent : function(ed, o) { + var self = this, startPos, endPos, content = o.content, headerFragment, styles = '', dom = self.editor.dom, elm; + + function low(s) { + return s.replace(/<\/?[A-Z]+/g, function(a) { + return a.toLowerCase(); + }) + }; + + // Ignore raw updated if we already have a head, this will fix issues with undo/redo keeping the head/foot separate + if (o.format == 'raw' && self.head) + return; + + if (o.source_view && ed.getParam('fullpage_hide_in_source_view')) + return; + + // Parse out head, body and footer + content = content.replace(/<(\/?)BODY/gi, '<$1body'); + startPos = content.indexOf('<body'); + + if (startPos != -1) { + startPos = content.indexOf('>', startPos); + self.head = low(content.substring(0, startPos + 1)); + + endPos = content.indexOf('</body', startPos); + if (endPos == -1) + endPos = content.length; + + o.content = content.substring(startPos + 1, endPos); + self.foot = low(content.substring(endPos)); + } else { + self.head = this._getDefaultHeader(); + self.foot = '\n</body>\n</html>'; + } + + // Parse header and update iframe + headerFragment = self._parseHeader(); + each(headerFragment.getAll('style'), function(node) { + if (node.firstChild) + styles += node.firstChild.value; + }); + + elm = headerFragment.getAll('body')[0]; + if (elm) { + dom.setAttribs(self.editor.getBody(), { + style : elm.attr('style') || '', + dir : elm.attr('dir') || '', + vLink : elm.attr('vlink') || '', + link : elm.attr('link') || '', + aLink : elm.attr('alink') || '' + }); + } + + dom.remove('fullpage_styles'); + + if (styles) { + dom.add(self.editor.getDoc().getElementsByTagName('head')[0], 'style', {id : 'fullpage_styles'}, styles); + + // Needed for IE 6/7 + elm = dom.get('fullpage_styles'); + if (elm.styleSheet) + elm.styleSheet.cssText = styles; + } + }, + + _getDefaultHeader : function() { + var header = '', editor = this.editor, value, styles = ''; + + if (editor.getParam('fullpage_default_xml_pi')) + header += '<?xml version="1.0" encoding="' + editor.getParam('fullpage_default_encoding', 'ISO-8859-1') + '" ?>\n'; + + header += editor.getParam('fullpage_default_doctype', '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'); + header += '\n<html>\n<head>\n'; + + if (value = editor.getParam('fullpage_default_title')) + header += '<title>' + value + '</title>\n'; + + if (value = editor.getParam('fullpage_default_encoding')) + header += '<meta http-equiv="Content-Type" content="text/html; charset=' + value + '" />\n'; + + if (value = editor.getParam('fullpage_default_font_family')) + styles += 'font-family: ' + value + ';'; + + if (value = editor.getParam('fullpage_default_font_size')) + styles += 'font-size: ' + value + ';'; + + if (value = editor.getParam('fullpage_default_text_color')) + styles += 'color: ' + value + ';'; + + header += '</head>\n<body' + (styles ? ' style="' + styles + '"' : '') + '>\n'; + + return header; + }, + + _getContent : function(ed, o) { + var self = this; + + if (!o.source_view || !ed.getParam('fullpage_hide_in_source_view')) + o.content = tinymce.trim(self.head) + '\n' + tinymce.trim(o.content) + '\n' + tinymce.trim(self.foot); + } + }); + + // Register plugin + tinymce.PluginManager.add('fullpage', tinymce.plugins.FullPagePlugin); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/fullpage.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/fullpage.htm new file mode 100644 index 0000000..14ab865 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/fullpage.htm @@ -0,0 +1,259 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#fullpage_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="js/fullpage.js"></script> + <link href="css/fullpage.css" rel="stylesheet" type="text/css" /> +</head> +<body id="fullpage" style="display: none"> +<form onsubmit="FullPageDialog.update();return false;" name="fullpage" action="#"> + <div class="tabs"> + <ul> + <li id="meta_tab" class="current"><span><a href="javascript:mcTabs.displayTab('meta_tab','meta_panel');" onmousedown="return false;">{#fullpage_dlg.meta_tab}</a></span></li> + <li id="appearance_tab"><span><a href="javascript:mcTabs.displayTab('appearance_tab','appearance_panel');" onmousedown="return false;">{#fullpage_dlg.appearance_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="meta_panel" class="panel current"> + <fieldset> + <legend>{#fullpage_dlg.meta_props}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="nowrap"><label for="metatitle">{#fullpage_dlg.meta_title}</label>&nbsp;</td> + <td><input type="text" id="metatitle" name="metatitle" value="" class="mceFocus" /></td> + </tr> + <tr> + <td class="nowrap"><label for="metakeywords">{#fullpage_dlg.meta_keywords}</label>&nbsp;</td> + <td><textarea id="metakeywords" name="metakeywords" rows="4"></textarea></td> + </tr> + <tr> + <td class="nowrap"><label for="metadescription">{#fullpage_dlg.meta_description}</label>&nbsp;</td> + <td><textarea id="metadescription" name="metadescription" rows="4"></textarea></td> + </tr> + <tr> + <td class="nowrap"><label for="metaauthor">{#fullpage_dlg.author}</label>&nbsp;</td> + <td><input type="text" id="metaauthor" name="metaauthor" value="" /></td> + </tr> + <tr> + <td class="nowrap"><label for="metacopyright">{#fullpage_dlg.copyright}</label>&nbsp;</td> + <td><input type="text" id="metacopyright" name="metacopyright" value="" /></td> + </tr> + <tr> + <td class="nowrap"><label for="metarobots">{#fullpage_dlg.meta_robots}</label>&nbsp;</td> + <td> + <select id="metarobots" name="metarobots"> + <option value="">{#not_set}</option> + <option value="index,follow">{#fullpage_dlg.meta_index_follow}</option> + <option value="index,nofollow">{#fullpage_dlg.meta_index_nofollow}</option> + <option value="noindex,follow">{#fullpage_dlg.meta_noindex_follow}</option> + <option value="noindex,nofollow">{#fullpage_dlg.meta_noindex_nofollow}</option> + </select> + </td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#fullpage_dlg.langprops}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="docencoding">{#fullpage_dlg.encoding}</label></td> + <td> + <select id="docencoding" name="docencoding"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="nowrap"><label for="doctype">{#fullpage_dlg.doctypes}</label>&nbsp;</td> + <td> + <select id="doctype" name="doctype"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="nowrap"><label for="langcode">{#fullpage_dlg.langcode}</label>&nbsp;</td> + <td><input type="text" id="langcode" name="langcode" value="" /></td> + </tr> + <tr> + <td class="column1"><label for="langdir">{#fullpage_dlg.langdir}</label></td> + <td> + <select id="langdir" name="langdir"> + <option value="">{#not_set}</option> + <option value="ltr">{#fullpage_dlg.ltr}</option> + <option value="rtl">{#fullpage_dlg.rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="nowrap"><label for="xml_pi">{#fullpage_dlg.xml_pi}</label>&nbsp;</td> + <td><input type="checkbox" id="xml_pi" name="xml_pi" class="checkbox" /></td> + </tr> + </table> + </fieldset> + </div> + + <div id="appearance_panel" class="panel"> + <fieldset> + <legend>{#fullpage_dlg.appearance_textprops}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="fontface">{#fullpage_dlg.fontface}</label></td> + <td> + <select id="fontface" name="fontface" onchange="FullPageDialog.changedStyleProp();"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="fontsize">{#fullpage_dlg.fontsize}</label></td> + <td> + <select id="fontsize" name="fontsize" onchange="FullPageDialog.changedStyleProp();"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="textcolor">{#fullpage_dlg.textcolor}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="textcolor" name="textcolor" type="text" value="" size="9" onchange="updateColor('textcolor_pick','textcolor');FullPageDialog.changedStyleProp();" /></td> + <td id="textcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#fullpage_dlg.appearance_bgprops}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="bgimage">{#fullpage_dlg.bgimage}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgimage" name="bgimage" type="text" value="" onchange="FullPageDialog.changedStyleProp();" /></td> + <td id="bgimage_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + <tr> + <td class="column1"><label for="bgcolor">{#fullpage_dlg.bgcolor}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');FullPageDialog.changedStyleProp();" /></td> + <td id="bgcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#fullpage_dlg.appearance_marginprops}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="leftmargin">{#fullpage_dlg.left_margin}</label></td> + <td><input id="leftmargin" name="leftmargin" type="text" value="" onchange="FullPageDialog.changedStyleProp();" /></td> + <td class="column1"><label for="rightmargin">{#fullpage_dlg.right_margin}</label></td> + <td><input id="rightmargin" name="rightmargin" type="text" value="" onchange="FullPageDialog.changedStyleProp();" /></td> + </tr> + <tr> + <td class="column1"><label for="topmargin">{#fullpage_dlg.top_margin}</label></td> + <td><input id="topmargin" name="topmargin" type="text" value="" onchange="FullPageDialog.changedStyleProp();" /></td> + <td class="column1"><label for="bottommargin">{#fullpage_dlg.bottom_margin}</label></td> + <td><input id="bottommargin" name="bottommargin" type="text" value="" onchange="FullPageDialog.changedStyleProp();" /></td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#fullpage_dlg.appearance_linkprops}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="link_color">{#fullpage_dlg.link_color}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="link_color" name="link_color" type="text" value="" size="9" onchange="updateColor('link_color_pick','link_color');FullPageDialog.changedStyleProp();" /></td> + <td id="link_color_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + + <td class="column1"><label for="visited_color">{#fullpage_dlg.visited_color}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="visited_color" name="visited_color" type="text" value="" size="9" onchange="updateColor('visited_color_pick','visited_color');FullPageDialog.changedStyleProp();" /></td> + <td id="visited_color_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td class="column1"><label for="active_color">{#fullpage_dlg.active_color}</label></td> + <td> + <table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="active_color" name="active_color" type="text" value="" size="9" onchange="updateColor('active_color_pick','active_color');FullPageDialog.changedStyleProp();" /></td> + <td id="active_color_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + + <td>&nbsp;</td> + <td>&nbsp;</td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#fullpage_dlg.appearance_style}</legend> + + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="column1"><label for="stylesheet">{#fullpage_dlg.stylesheet}</label></td> + <td><table border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="stylesheet" name="stylesheet" type="text" value="" /></td> + <td id="stylesheet_browsercontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td class="column1"><label for="style">{#fullpage_dlg.style}</label></td> + <td><input id="style" name="style" type="text" value="" onchange="FullPageDialog.changedStyle();" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="update" value="{#update}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/js/fullpage.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/js/fullpage.js new file mode 100644 index 0000000..3f672ad --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/js/fullpage.js @@ -0,0 +1,232 @@ +/** + * fullpage.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinyMCEPopup.requireLangPack(); + + var defaultDocTypes = + 'XHTML 1.0 Transitional=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">,' + + 'XHTML 1.0 Frameset=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">,' + + 'XHTML 1.0 Strict=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">,' + + 'XHTML 1.1=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">,' + + 'HTML 4.01 Transitional=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">,' + + 'HTML 4.01 Strict=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">,' + + 'HTML 4.01 Frameset=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'; + + var defaultEncodings = + 'Western european (iso-8859-1)=iso-8859-1,' + + 'Central European (iso-8859-2)=iso-8859-2,' + + 'Unicode (UTF-8)=utf-8,' + + 'Chinese traditional (Big5)=big5,' + + 'Cyrillic (iso-8859-5)=iso-8859-5,' + + 'Japanese (iso-2022-jp)=iso-2022-jp,' + + 'Greek (iso-8859-7)=iso-8859-7,' + + 'Korean (iso-2022-kr)=iso-2022-kr,' + + 'ASCII (us-ascii)=us-ascii'; + + var defaultFontNames = 'Arial=arial,helvetica,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,times new roman,times,serif;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times,serif;Verdana=verdana,arial,helvetica,sans-serif;Impact=impact;WingDings=wingdings'; + var defaultFontSizes = '10px,11px,12px,13px,14px,15px,16px'; + + function setVal(id, value) { + var elm = document.getElementById(id); + + if (elm) { + value = value || ''; + + if (elm.nodeName == "SELECT") + selectByValue(document.forms[0], id, value); + else if (elm.type == "checkbox") + elm.checked = !!value; + else + elm.value = value; + } + }; + + function getVal(id) { + var elm = document.getElementById(id); + + if (elm.nodeName == "SELECT") + return elm.options[elm.selectedIndex].value; + + if (elm.type == "checkbox") + return elm.checked; + + return elm.value; + }; + + window.FullPageDialog = { + changedStyle : function() { + var val, styles = tinyMCEPopup.editor.dom.parseStyle(getVal('style')); + + setVal('fontface', styles['font-face']); + setVal('fontsize', styles['font-size']); + setVal('textcolor', styles['color']); + + if (val = styles['background-image']) + setVal('bgimage', val.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1")); + else + setVal('bgimage', ''); + + setVal('bgcolor', styles['background-color']); + + // Reset margin form elements + setVal('topmargin', ''); + setVal('rightmargin', ''); + setVal('bottommargin', ''); + setVal('leftmargin', ''); + + // Expand margin + if (val = styles['margin']) { + val = val.split(' '); + styles['margin-top'] = val[0] || ''; + styles['margin-right'] = val[1] || val[0] || ''; + styles['margin-bottom'] = val[2] || val[0] || ''; + styles['margin-left'] = val[3] || val[0] || ''; + } + + if (val = styles['margin-top']) + setVal('topmargin', val.replace(/px/, '')); + + if (val = styles['margin-right']) + setVal('rightmargin', val.replace(/px/, '')); + + if (val = styles['margin-bottom']) + setVal('bottommargin', val.replace(/px/, '')); + + if (val = styles['margin-left']) + setVal('leftmargin', val.replace(/px/, '')); + + updateColor('bgcolor_pick', 'bgcolor'); + updateColor('textcolor_pick', 'textcolor'); + }, + + changedStyleProp : function() { + var val, dom = tinyMCEPopup.editor.dom, styles = dom.parseStyle(getVal('style')); + + styles['font-face'] = getVal('fontface'); + styles['font-size'] = getVal('fontsize'); + styles['color'] = getVal('textcolor'); + styles['background-color'] = getVal('bgcolor'); + + if (val = getVal('bgimage')) + styles['background-image'] = "url('" + val + "')"; + else + styles['background-image'] = ''; + + delete styles['margin']; + + if (val = getVal('topmargin')) + styles['margin-top'] = val + "px"; + else + styles['margin-top'] = ''; + + if (val = getVal('rightmargin')) + styles['margin-right'] = val + "px"; + else + styles['margin-right'] = ''; + + if (val = getVal('bottommargin')) + styles['margin-bottom'] = val + "px"; + else + styles['margin-bottom'] = ''; + + if (val = getVal('leftmargin')) + styles['margin-left'] = val + "px"; + else + styles['margin-left'] = ''; + + // Serialize, parse and reserialize this will compress redundant styles + setVal('style', dom.serializeStyle(dom.parseStyle(dom.serializeStyle(styles)))); + this.changedStyle(); + }, + + update : function() { + var data = {}; + + tinymce.each(tinyMCEPopup.dom.select('select,input,textarea'), function(node) { + data[node.id] = getVal(node.id); + }); + + tinyMCEPopup.editor.plugins.fullpage._dataToHtml(data); + tinyMCEPopup.close(); + } + }; + + function init() { + var form = document.forms[0], i, item, list, editor = tinyMCEPopup.editor; + + // Setup doctype select box + list = editor.getParam("fullpage_doctypes", defaultDocTypes).split(','); + for (i = 0; i < list.length; i++) { + item = list[i].split('='); + + if (item.length > 1) + addSelectValue(form, 'doctype', item[0], item[1]); + } + + // Setup fonts select box + list = editor.getParam("fullpage_fonts", defaultFontNames).split(';'); + for (i = 0; i < list.length; i++) { + item = list[i].split('='); + + if (item.length > 1) + addSelectValue(form, 'fontface', item[0], item[1]); + } + + // Setup fontsize select box + list = editor.getParam("fullpage_fontsizes", defaultFontSizes).split(','); + for (i = 0; i < list.length; i++) + addSelectValue(form, 'fontsize', list[i], list[i]); + + // Setup encodings select box + list = editor.getParam("fullpage_encodings", defaultEncodings).split(','); + for (i = 0; i < list.length; i++) { + item = list[i].split('='); + + if (item.length > 1) + addSelectValue(form, 'docencoding', item[0], item[1]); + } + + // Setup color pickers + document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor'); + document.getElementById('link_color_pickcontainer').innerHTML = getColorPickerHTML('link_color_pick','link_color'); + document.getElementById('visited_color_pickcontainer').innerHTML = getColorPickerHTML('visited_color_pick','visited_color'); + document.getElementById('active_color_pickcontainer').innerHTML = getColorPickerHTML('active_color_pick','active_color'); + document.getElementById('textcolor_pickcontainer').innerHTML = getColorPickerHTML('textcolor_pick','textcolor'); + document.getElementById('stylesheet_browsercontainer').innerHTML = getBrowserHTML('stylesheetbrowser','stylesheet','file','fullpage'); + document.getElementById('bgimage_pickcontainer').innerHTML = getBrowserHTML('bgimage_browser','bgimage','image','fullpage'); + + // Resize some elements + if (isVisible('stylesheetbrowser')) + document.getElementById('stylesheet').style.width = '220px'; + + if (isVisible('link_href_browser')) + document.getElementById('element_link_href').style.width = '230px'; + + if (isVisible('bgimage_browser')) + document.getElementById('bgimage').style.width = '210px'; + + // Update form + tinymce.each(tinyMCEPopup.getWindowArg('data'), function(value, key) { + setVal(key, value); + }); + + FullPageDialog.changedStyle(); + + // Update colors + updateColor('textcolor_pick', 'textcolor'); + updateColor('bgcolor_pick', 'bgcolor'); + updateColor('visited_color_pick', 'visited_color'); + updateColor('active_color_pick', 'active_color'); + updateColor('link_color_pick', 'link_color'); + }; + + tinyMCEPopup.onInit.add(init); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/de_dlg.js new file mode 100644 index 0000000..ecdff9e --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.fullpage_dlg',{title:"Dokument-Eigenschaften","meta_tab":"Allgemein","appearance_tab":"Aussehen","advanced_tab":"Erweitert","meta_props":"Meta-Information",langprops:"Sprache und Codierung","meta_title":"Titel","meta_keywords":"Keywords","meta_description":"Beschreibung","meta_robots":"Robots",doctypes:"DocType",langcode:"Sprachcode",langdir:"Sprachrichtung",ltr:"Links nach Rechts",rtl:"Rechts nach Links","xml_pi":"XML Deklaration",encoding:"Zeichencodierung","appearance_bgprops":"Hintergrund-Eigenschaften","appearance_marginprops":"Abst\u00e4nde des Body","appearance_linkprops":"Linkfarben","appearance_textprops":"Text-Eigenschaften",bgcolor:"Hintergrundfarbe",bgimage:"Hintergrundbild","left_margin":"Linker Abstand","right_margin":"Rechter Abstand","top_margin":"Oberer Abstand","bottom_margin":"Unterer Abstand","text_color":"Textfarbe","font_size":"Schriftgr\u00f6\u00dfe","font_face":"Schriftart","link_color":"Linkfarbe","hover_color":"Hover-Farbe","visited_color":"Visited-Farbe","active_color":"Active-Farbe",textcolor:"Farbe",fontsize:"Schriftgr\u00f6\u00dfe",fontface:"Schriftart","meta_index_follow":"Indizieren und den Links folgen","meta_index_nofollow":"Indizieren, aber den Links nicht folgen","meta_noindex_follow":"Nicht indizieren, aber den Links folgen","meta_noindex_nofollow":"Nicht indizieren und auch nicht den Links folgen","appearance_style":"CSS-Stylesheet und Stileigenschaften",stylesheet:"CSS-Stylesheet",style:"CSS-Stil",author:"Autor",copyright:"Copyright",add:"Neues Element hinzuf\u00fcgen",remove:"Ausgew\u00e4hltes Element entfernen",moveup:"Ausgew\u00e4hltes Element nach oben bewegen",movedown:"Ausgew\u00e4hltes Element nach unten bewegen","head_elements":"\u00dcberschriftenelemente",info:"Information","add_title":"Titel-Element","add_meta":"Meta-Element","add_script":"Script-Element","add_style":"Style-Element","add_link":"Link-Element","add_base":"Base-Element","add_comment":"HTML-Kommentar","title_element":"Titel-Element","script_element":"Script-Element","style_element":"Style-Element","base_element":"Base-Element","link_element":"Link-Element","meta_element":"Meta_Element","comment_element":"Kommentar",src:"Src",language:"Sprache",href:"Href",target:"Ziel",type:"Typ",charset:"Zeichensatz",defer:"Defer",media:"Media",properties:"Eigenschaften",name:"Name",value:"Wert",content:"Inhalt",rel:"Rel",rev:"Rev",hreflang:"Href lang","general_props":"Allgemein","advanced_props":"Erweitert"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/en_dlg.js new file mode 100644 index 0000000..516edc7 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.fullpage_dlg',{title:"Document Properties","meta_tab":"General","appearance_tab":"Appearance","advanced_tab":"Advanced","meta_props":"Meta Information",langprops:"Language and Encoding","meta_title":"Title","meta_keywords":"Keywords","meta_description":"Description","meta_robots":"Robots",doctypes:"Doctype",langcode:"Language Code",langdir:"Language Direction",ltr:"Left to Right",rtl:"Right to Left","xml_pi":"XML Declaration",encoding:"Character Encoding","appearance_bgprops":"Background Properties","appearance_marginprops":"Body Margins","appearance_linkprops":"Link Colors","appearance_textprops":"Text Properties",bgcolor:"Background Color",bgimage:"Background Image","left_margin":"Left Margin","right_margin":"Right Margin","top_margin":"Top Margin","bottom_margin":"Bottom Margin","text_color":"Text Color","font_size":"Font Size","font_face":"Font Face","link_color":"Link Color","hover_color":"Hover Color","visited_color":"Visited Color","active_color":"Active Color",textcolor:"Color",fontsize:"Font Size",fontface:"Font Family","meta_index_follow":"Index and Follow the Links","meta_index_nofollow":"Index and Don\'t Follow the Links","meta_noindex_follow":"Do Not Index but Follow the Links","meta_noindex_nofollow":"Do Not Index and Don\'t Follow the Links","appearance_style":"Stylesheet and Style Properties",stylesheet:"Stylesheet",style:"Style",author:"Author",copyright:"Copyright",add:"Add New Element",remove:"Remove Selected Element",moveup:"Move Selected Element Up",movedown:"Move Selected Element Down","head_elements":"Head Elements",info:"Information","add_title":"Title Element","add_meta":"Meta Element","add_script":"Script Element","add_style":"Style Element","add_link":"Link Element","add_base":"Base Element","add_comment":"Comment Node","title_element":"Title Element","script_element":"Script Element","style_element":"Style Element","base_element":"Base Element","link_element":"Link Element","meta_element":"Meta Element","comment_element":"Comment",src:"Source",language:"Language",href:"HREF",target:"Target",type:"Type",charset:"Charset",defer:"Defer",media:"Media",properties:"Properties",name:"Name",value:"Value",content:"Content",rel:"Rel",rev:"Rev",hreflang:"HREF Lang","general_props":"General","advanced_props":"Advanced"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/fr_dlg.js new file mode 100644 index 0000000..c2ddc65 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.fullpage_dlg',{title:"Propri\u00e9t\u00e9s du document","meta_tab":"G\u00e9n\u00e9ral","appearance_tab":"Apparence","advanced_tab":"Avanc\u00e9","meta_props":"Metadonn\u00e9es",langprops:"Langue et encodage","meta_title":"Titre","meta_keywords":"Mots-cl\u00e9s","meta_description":"Description","meta_robots":"Robots",doctypes:"Doctype",langcode:"Code de la langue",langdir:"Sens de lecture",ltr:"De gauche \u00e0 droite",rtl:"De droite \u00e0 gauche","xml_pi":"D\u00e9claration XML",encoding:"Encodage des caract\u00e8res","appearance_bgprops":"Propri\u00e9t\u00e9s du fond","appearance_marginprops":"Marge du corps de la page","appearance_linkprops":"Couleurs des liens","appearance_textprops":"Propri\u00e9t\u00e9s du texte",bgcolor:"Couleur de fond",bgimage:"Image de fond","left_margin":"Marge de gauche","right_margin":"Marge de droite","top_margin":"Marge du haut","bottom_margin":"Marge du bas","text_color":"Couleur du texte","font_size":"Taille de la police","font_face":"Nom de la police","link_color":"Couleur des liens","hover_color":"Couleur au survol","visited_color":"Couleur des liens visit\u00e9s","active_color":"Couleur du lien actif",textcolor:"Couleur",fontsize:"Taille de police",fontface:"Nom de la police","meta_index_follow":"Indexer et suivre les liens","meta_index_nofollow":"Indexer et ne pas suivre les liens","meta_noindex_follow":"Ne pas indexer et suivre les liens","meta_noindex_nofollow":"Ne pas indexer et ne pas suivre les liens","appearance_style":"Propri\u00e9t\u00e9s de la feuille de style et du style",stylesheet:"Feuille de style",style:"Style",author:"Auteur",copyright:"Copyright",add:"Ajouter un nouvel \u00e9l\u00e9ment",remove:"Retirer l\'\u00e9l\u00e9ment s\u00e9lectionn\u00e9",moveup:"D\u00e9placer l\'\u00e9l\u00e9ment s\u00e9lectionn\u00e9 vers le haut",movedown:"D\u00e9placer l\'\u00e9l\u00e9ment s\u00e9lectionn\u00e9 vers le bas","head_elements":"\u00c9l\u00e9ments d\'en-t\u00eate",info:"Information","add_title":"\u00c9l\u00e9ment de titre","add_meta":"\u00c9l\u00e9ment Meta","add_script":"\u00c9l\u00e9ment de script","add_style":"\u00c9l\u00e9ment de style","add_link":"\u00c9l\u00e9ment de lien","add_base":"\u00c9l\u00e9ment de base","add_comment":"Commentaire","title_element":"\u00c9l\u00e9ment de titre","script_element":"\u00c9l\u00e9ment de script","style_element":"\u00c9l\u00e9ment de style","base_element":"\u00c9l\u00e9ment de base","link_element":"\u00c9l\u00e9ment de lien","meta_element":"\u00c9l\u00e9ment Meta","comment_element":"Commentaire",src:"Source",language:"Langue",href:"Href",target:"Cible",type:"Type",charset:"Charset",defer:"D\u00e9f\u00e9rer",media:"M\u00e9dia",properties:"Propri\u00e9t\u00e9s",name:"Nom",value:"Valeur",content:"Contenu",rel:"Rel",rev:"Rev",hreflang:"langue Href","general_props":"G\u00e9n\u00e9ral","advanced_props":"Avanc\u00e9"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/it_dlg.js new file mode 100644 index 0000000..d5445e8 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullpage/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.fullpage_dlg',{title:"Propriet\u00e0 Documento","meta_tab":"Generale","appearance_tab":"Aspetto","advanced_tab":"Avanzate","meta_props":"Informazioni Metatag",langprops:"Lingua e codifica","meta_title":"Titolo","meta_keywords":"Parole chiave","meta_description":"Descrizione","meta_robots":"Robots",doctypes:"Doctype",langcode:"Codice lingua",langdir:"Direzione testo",ltr:"Sinistra verso destra",rtl:"Destra verso sinistra","xml_pi":"Dichiarazione XML",encoding:"Codifica carattere","appearance_bgprops":"Propriet\u00e0 sfondo","appearance_marginprops":"Margini body","appearance_linkprops":"Colori collegamenti","appearance_textprops":"Propriet\u00e0 testo",bgcolor:"Colore sfondo",bgimage:"Immagine sfondo","left_margin":"Margine sinistro","right_margin":"Margine destro","top_margin":"Margine superiore","bottom_margin":"Margine inferiore","text_color":"Colore testo","font_size":"Dimensione carattere","font_face":"Tipo carattere","link_color":"Colore collegamento","hover_color":"Colore \\\'Hover\\\'","visited_color":"Colore \\\'Visited\\\'","active_color":"Colore \\\'Active\\\'",textcolor:"Colore",fontsize:"Dimensione carattere",fontface:"Famiglia carattere","meta_index_follow":"Indicizzare e seguire collegamenti","meta_index_nofollow":"Indicizzare e non segure collegamenti","meta_noindex_follow":"Non indicizzare ma seguire collegamenti","meta_noindex_nofollow":"Non indicizzare e non seguire collegamenti","appearance_style":"Propriet\u00e0 stili e fogli di stile",stylesheet:"Fogli di stile",style:"Stile",author:"Autore",copyright:"Copyright",add:"Aggiungi nuovo elemento",remove:"Rimuovi elemento selezionato",moveup:"Sposta elemento selezionato in alto",movedown:"Sposta elemento selezionato in basso","head_elements":"Elementi Head",info:"Informazioni","add_title":"Elemento Titolo","add_meta":"Elemento Meta","add_script":"Elemento Script","add_style":"Elemento Style","add_link":"Elemento Link","add_base":"Elemento Base","add_comment":"Nodo Commento","title_element":"Elemento Titolo","script_element":"Elemento Script","style_element":"Elemento Style","base_element":"Elemento Base","link_element":"Elemento Link","meta_element":"Elemento Meta","comment_element":"Commento",src:"Sorgente",language:"Linguaggio",href:"Href",target:"Target",type:"Tipo",charset:"Set caratteri",defer:"Defer",media:"Media",properties:"Propriet\u00e0",name:"Nome",value:"Valore",content:"Contenuto",rel:"Rel",rev:"Rev",hreflang:"Href lang","general_props":"Generale","advanced_props":"Avanzate"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/editor_plugin.js new file mode 100644 index 0000000..a6456f8 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.DOM;tinymce.create("tinymce.plugins.FullScreenPlugin",{init:function(d,e){var f=this,g={},c,b;f.editor=d;d.addCommand("mceFullScreen",function(){var i,j=a.doc.documentElement;if(d.getParam("fullscreen_is_enabled")){if(d.getParam("fullscreen_new_window")){closeFullscreen()}else{a.win.setTimeout(function(){tinymce.dom.Event.remove(a.win,"resize",f.resizeFunc);tinyMCE.get(d.getParam("fullscreen_editor_id")).setContent(d.getContent());tinyMCE.remove(d);a.remove("mce_fullscreen_container");j.style.overflow=d.getParam("fullscreen_html_overflow");a.setStyle(a.doc.body,"overflow",d.getParam("fullscreen_overflow"));a.win.scrollTo(d.getParam("fullscreen_scrollx"),d.getParam("fullscreen_scrolly"));tinyMCE.settings=tinyMCE.oldSettings},10)}return}if(d.getParam("fullscreen_new_window")){i=a.win.open(e+"/fullscreen.htm","mceFullScreenPopup","fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=yes,left=0,top=0,width="+screen.availWidth+",height="+screen.availHeight);try{i.resizeTo(screen.availWidth,screen.availHeight)}catch(h){}}else{tinyMCE.oldSettings=tinyMCE.settings;g.fullscreen_overflow=a.getStyle(a.doc.body,"overflow",1)||"auto";g.fullscreen_html_overflow=a.getStyle(j,"overflow",1);c=a.getViewPort();g.fullscreen_scrollx=c.x;g.fullscreen_scrolly=c.y;if(tinymce.isOpera&&g.fullscreen_overflow=="visible"){g.fullscreen_overflow="auto"}if(tinymce.isIE&&g.fullscreen_overflow=="scroll"){g.fullscreen_overflow="auto"}if(tinymce.isIE&&(g.fullscreen_html_overflow=="visible"||g.fullscreen_html_overflow=="scroll")){g.fullscreen_html_overflow="auto"}if(g.fullscreen_overflow=="0px"){g.fullscreen_overflow=""}a.setStyle(a.doc.body,"overflow","hidden");j.style.overflow="hidden";c=a.getViewPort();a.win.scrollTo(0,0);if(tinymce.isIE){c.h-=1}if(tinymce.isIE6){b="absolute;top:"+c.y}else{b="fixed;top:0"}n=a.add(a.doc.body,"div",{id:"mce_fullscreen_container",style:"position:"+b+";left:0;width:"+c.w+"px;height:"+c.h+"px;z-index:200000;"});a.add(n,"div",{id:"mce_fullscreen"});tinymce.each(d.settings,function(k,l){g[l]=k});g.id="mce_fullscreen";g.width=n.clientWidth;g.height=n.clientHeight-15;g.fullscreen_is_enabled=true;g.fullscreen_editor_id=d.id;g.theme_advanced_resizing=false;g.save_onsavecallback=function(){d.setContent(tinyMCE.get(g.id).getContent());d.execCommand("mceSave")};tinymce.each(d.getParam("fullscreen_settings"),function(m,l){g[l]=m});if(g.theme_advanced_toolbar_location==="external"){g.theme_advanced_toolbar_location="top"}f.fullscreenEditor=new tinymce.Editor("mce_fullscreen",g);f.fullscreenEditor.onInit.add(function(){f.fullscreenEditor.setContent(d.getContent());f.fullscreenEditor.focus()});f.fullscreenEditor.render();f.fullscreenElement=new tinymce.dom.Element("mce_fullscreen_container");f.fullscreenElement.update();f.resizeFunc=tinymce.dom.Event.add(a.win,"resize",function(){var o=tinymce.DOM.getViewPort(),l=f.fullscreenEditor,k,m;k=l.dom.getSize(l.getContainer().firstChild);m=l.dom.getSize(l.getContainer().getElementsByTagName("iframe")[0]);l.theme.resizeTo(o.w-k.w+m.w,o.h-k.h+m.h)})}});d.addButton("fullscreen",{title:"fullscreen.desc",cmd:"mceFullScreen"});d.onNodeChange.add(function(i,h){h.setActive("fullscreen",i.getParam("fullscreen_is_enabled"))})},getInfo:function(){return{longname:"Fullscreen",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("fullscreen",tinymce.plugins.FullScreenPlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/editor_plugin_src.js new file mode 100644 index 0000000..afa4f9b --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/editor_plugin_src.js @@ -0,0 +1,159 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var DOM = tinymce.DOM; + + tinymce.create('tinymce.plugins.FullScreenPlugin', { + init : function(ed, url) { + var t = this, s = {}, vp, posCss; + + t.editor = ed; + + // Register commands + ed.addCommand('mceFullScreen', function() { + var win, de = DOM.doc.documentElement; + + if (ed.getParam('fullscreen_is_enabled')) { + if (ed.getParam('fullscreen_new_window')) + closeFullscreen(); // Call to close in new window + else { + DOM.win.setTimeout(function() { + tinymce.dom.Event.remove(DOM.win, 'resize', t.resizeFunc); + tinyMCE.get(ed.getParam('fullscreen_editor_id')).setContent(ed.getContent()); + tinyMCE.remove(ed); + DOM.remove('mce_fullscreen_container'); + de.style.overflow = ed.getParam('fullscreen_html_overflow'); + DOM.setStyle(DOM.doc.body, 'overflow', ed.getParam('fullscreen_overflow')); + DOM.win.scrollTo(ed.getParam('fullscreen_scrollx'), ed.getParam('fullscreen_scrolly')); + tinyMCE.settings = tinyMCE.oldSettings; // Restore old settings + }, 10); + } + + return; + } + + if (ed.getParam('fullscreen_new_window')) { + win = DOM.win.open(url + "/fullscreen.htm", "mceFullScreenPopup", "fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=yes,left=0,top=0,width=" + screen.availWidth + ",height=" + screen.availHeight); + try { + win.resizeTo(screen.availWidth, screen.availHeight); + } catch (e) { + // Ignore + } + } else { + tinyMCE.oldSettings = tinyMCE.settings; // Store old settings + s.fullscreen_overflow = DOM.getStyle(DOM.doc.body, 'overflow', 1) || 'auto'; + s.fullscreen_html_overflow = DOM.getStyle(de, 'overflow', 1); + vp = DOM.getViewPort(); + s.fullscreen_scrollx = vp.x; + s.fullscreen_scrolly = vp.y; + + // Fixes an Opera bug where the scrollbars doesn't reappear + if (tinymce.isOpera && s.fullscreen_overflow == 'visible') + s.fullscreen_overflow = 'auto'; + + // Fixes an IE bug where horizontal scrollbars would appear + if (tinymce.isIE && s.fullscreen_overflow == 'scroll') + s.fullscreen_overflow = 'auto'; + + // Fixes an IE bug where the scrollbars doesn't reappear + if (tinymce.isIE && (s.fullscreen_html_overflow == 'visible' || s.fullscreen_html_overflow == 'scroll')) + s.fullscreen_html_overflow = 'auto'; + + if (s.fullscreen_overflow == '0px') + s.fullscreen_overflow = ''; + + DOM.setStyle(DOM.doc.body, 'overflow', 'hidden'); + de.style.overflow = 'hidden'; //Fix for IE6/7 + vp = DOM.getViewPort(); + DOM.win.scrollTo(0, 0); + + if (tinymce.isIE) + vp.h -= 1; + + // Use fixed position if it exists + if (tinymce.isIE6) + posCss = 'absolute;top:' + vp.y; + else + posCss = 'fixed;top:0'; + + n = DOM.add(DOM.doc.body, 'div', { + id : 'mce_fullscreen_container', + style : 'position:' + posCss + ';left:0;width:' + vp.w + 'px;height:' + vp.h + 'px;z-index:200000;'}); + DOM.add(n, 'div', {id : 'mce_fullscreen'}); + + tinymce.each(ed.settings, function(v, n) { + s[n] = v; + }); + + s.id = 'mce_fullscreen'; + s.width = n.clientWidth; + s.height = n.clientHeight - 15; + s.fullscreen_is_enabled = true; + s.fullscreen_editor_id = ed.id; + s.theme_advanced_resizing = false; + s.save_onsavecallback = function() { + ed.setContent(tinyMCE.get(s.id).getContent()); + ed.execCommand('mceSave'); + }; + + tinymce.each(ed.getParam('fullscreen_settings'), function(v, k) { + s[k] = v; + }); + + if (s.theme_advanced_toolbar_location === 'external') + s.theme_advanced_toolbar_location = 'top'; + + t.fullscreenEditor = new tinymce.Editor('mce_fullscreen', s); + t.fullscreenEditor.onInit.add(function() { + t.fullscreenEditor.setContent(ed.getContent()); + t.fullscreenEditor.focus(); + }); + + t.fullscreenEditor.render(); + + t.fullscreenElement = new tinymce.dom.Element('mce_fullscreen_container'); + t.fullscreenElement.update(); + //document.body.overflow = 'hidden'; + + t.resizeFunc = tinymce.dom.Event.add(DOM.win, 'resize', function() { + var vp = tinymce.DOM.getViewPort(), fed = t.fullscreenEditor, outerSize, innerSize; + + // Get outer/inner size to get a delta size that can be used to calc the new iframe size + outerSize = fed.dom.getSize(fed.getContainer().firstChild); + innerSize = fed.dom.getSize(fed.getContainer().getElementsByTagName('iframe')[0]); + + fed.theme.resizeTo(vp.w - outerSize.w + innerSize.w, vp.h - outerSize.h + innerSize.h); + }); + } + }); + + // Register buttons + ed.addButton('fullscreen', {title : 'fullscreen.desc', cmd : 'mceFullScreen'}); + + ed.onNodeChange.add(function(ed, cm) { + cm.setActive('fullscreen', ed.getParam('fullscreen_is_enabled')); + }); + }, + + getInfo : function() { + return { + longname : 'Fullscreen', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('fullscreen', tinymce.plugins.FullScreenPlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/fullscreen.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/fullscreen.htm new file mode 100644 index 0000000..ffe528e --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/fullscreen/fullscreen.htm @@ -0,0 +1,110 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title></title> + <meta http-equiv="X-UA-Compatible" content="IE=edge" /> + <script type="text/javascript" src="../../tiny_mce.js"></script> + <script type="text/javascript"> + function patchCallback(settings, key) { + if (settings[key]) + settings[key] = "window.opener." + settings[key]; + } + + var settings = {}, paSe = window.opener.tinyMCE.activeEditor.settings, oeID = window.opener.tinyMCE.activeEditor.id; + + // Clone array + for (var n in paSe) + settings[n] = paSe[n]; + + // Override options for fullscreen + for (var n in paSe.fullscreen_settings) + settings[n] = paSe.fullscreen_settings[n]; + + // Patch callbacks, make them point to window.opener + patchCallback(settings, 'urlconverter_callback'); + patchCallback(settings, 'insertlink_callback'); + patchCallback(settings, 'insertimage_callback'); + patchCallback(settings, 'setupcontent_callback'); + patchCallback(settings, 'save_callback'); + patchCallback(settings, 'onchange_callback'); + patchCallback(settings, 'init_instance_callback'); + patchCallback(settings, 'file_browser_callback'); + patchCallback(settings, 'cleanup_callback'); + patchCallback(settings, 'execcommand_callback'); + patchCallback(settings, 'oninit'); + + // Set options + delete settings.id; + settings['mode'] = 'exact'; + settings['elements'] = 'fullscreenarea'; + settings['add_unload_trigger'] = false; + settings['ask'] = false; + settings['document_base_url'] = window.opener.tinyMCE.activeEditor.documentBaseURI.getURI(); + settings['fullscreen_is_enabled'] = true; + settings['fullscreen_editor_id'] = oeID; + settings['theme_advanced_resizing'] = false; + settings['strict_loading_mode'] = true; + + settings.save_onsavecallback = function() { + window.opener.tinyMCE.get(oeID).setContent(tinyMCE.get('fullscreenarea').getContent({format : 'raw'}), {format : 'raw'}); + window.opener.tinyMCE.get(oeID).execCommand('mceSave'); + window.close(); + }; + + function unloadHandler(e) { + moveContent(); + } + + function moveContent() { + window.opener.tinyMCE.get(oeID).setContent(tinyMCE.activeEditor.getContent()); + } + + function closeFullscreen() { + moveContent(); + window.close(); + } + + function doParentSubmit() { + moveContent(); + + if (window.opener.tinyMCE.selectedInstance.formElement.form) + window.opener.tinyMCE.selectedInstance.formElement.form.submit(); + + window.close(); + + return false; + } + + function render() { + var e = document.getElementById('fullscreenarea'), vp, ed, ow, oh, dom = tinymce.DOM; + + e.value = window.opener.tinyMCE.get(oeID).getContent(); + + vp = dom.getViewPort(); + settings.width = vp.w; + settings.height = vp.h - 15; + + tinymce.dom.Event.add(window, 'resize', function() { + var vp = dom.getViewPort(); + + tinyMCE.activeEditor.theme.resizeTo(vp.w, vp.h); + }); + + tinyMCE.init(settings); + } + + // Add onunload + tinymce.dom.Event.add(window, "beforeunload", unloadHandler); + </script> +</head> +<body style="margin:0;overflow:hidden;width:100%;height:100%" scrolling="no" scroll="no"> +<form onsubmit="doParentSubmit();"> +<textarea id="fullscreenarea" style="width:100%; height:100%"></textarea> +</form> + +<script type="text/javascript"> + render(); +</script> + +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/iespell/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/iespell/editor_plugin.js new file mode 100644 index 0000000..e9cba10 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/iespell/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.IESpell",{init:function(a,b){var c=this,d;if(!tinymce.isIE){return}c.editor=a;a.addCommand("mceIESpell",function(){try{d=new ActiveXObject("ieSpell.ieSpellExtension");d.CheckDocumentNode(a.getDoc().documentElement)}catch(f){if(f.number==-2146827859){a.windowManager.confirm(a.getLang("iespell.download"),function(e){if(e){window.open("http://www.iespell.com/download.php","ieSpellDownload","")}})}else{a.windowManager.alert("Error Loading ieSpell: Exception "+f.number)}}});a.addButton("iespell",{title:"iespell.iespell_desc",cmd:"mceIESpell"})},getInfo:function(){return{longname:"IESpell (IE Only)",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/iespell",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("iespell",tinymce.plugins.IESpell)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/iespell/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/iespell/editor_plugin_src.js new file mode 100644 index 0000000..1b2bb98 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/iespell/editor_plugin_src.js @@ -0,0 +1,54 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.IESpell', { + init : function(ed, url) { + var t = this, sp; + + if (!tinymce.isIE) + return; + + t.editor = ed; + + // Register commands + ed.addCommand('mceIESpell', function() { + try { + sp = new ActiveXObject("ieSpell.ieSpellExtension"); + sp.CheckDocumentNode(ed.getDoc().documentElement); + } catch (e) { + if (e.number == -2146827859) { + ed.windowManager.confirm(ed.getLang("iespell.download"), function(s) { + if (s) + window.open('http://www.iespell.com/download.php', 'ieSpellDownload', ''); + }); + } else + ed.windowManager.alert("Error Loading ieSpell: Exception " + e.number); + } + }); + + // Register buttons + ed.addButton('iespell', {title : 'iespell.iespell_desc', cmd : 'mceIESpell'}); + }, + + getInfo : function() { + return { + longname : 'IESpell (IE Only)', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/iespell', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('iespell', tinymce.plugins.IESpell); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/editor_plugin.js new file mode 100644 index 0000000..8bb96f9 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/editor_plugin.js @@ -0,0 +1 @@ +(function(){var d=tinymce.DOM,b=tinymce.dom.Element,a=tinymce.dom.Event,e=tinymce.each,c=tinymce.is;tinymce.create("tinymce.plugins.InlinePopups",{init:function(f,g){f.onBeforeRenderUI.add(function(){f.windowManager=new tinymce.InlineWindowManager(f);d.loadCSS(g+"/skins/"+(f.settings.inlinepopups_skin||"clearlooks2")+"/window.css")})},getInfo:function(){return{longname:"InlinePopups",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.create("tinymce.InlineWindowManager:tinymce.WindowManager",{InlineWindowManager:function(f){var g=this;g.parent(f);g.zIndex=300000;g.count=0;g.windows={}},open:function(s,j){var z=this,i,k="",r=z.editor,g=0,v=0,h,m,o,q,l,x,y,n;s=s||{};j=j||{};if(!s.inline){return z.parent(s,j)}n=z._frontWindow();if(n&&d.get(n.id+"_ifr")){n.focussedElement=d.get(n.id+"_ifr").contentWindow.document.activeElement}if(!s.type){z.bookmark=r.selection.getBookmark(1)}i=d.uniqueId();h=d.getViewPort();s.width=parseInt(s.width||320);s.height=parseInt(s.height||240)+(tinymce.isIE?8:0);s.min_width=parseInt(s.min_width||150);s.min_height=parseInt(s.min_height||100);s.max_width=parseInt(s.max_width||2000);s.max_height=parseInt(s.max_height||2000);s.left=s.left||Math.round(Math.max(h.x,h.x+(h.w/2)-(s.width/2)));s.top=s.top||Math.round(Math.max(h.y,h.y+(h.h/2)-(s.height/2)));s.movable=s.resizable=true;j.mce_width=s.width;j.mce_height=s.height;j.mce_inline=true;j.mce_window_id=i;j.mce_auto_focus=s.auto_focus;z.features=s;z.params=j;z.onOpen.dispatch(z,s,j);if(s.type){k+=" mceModal";if(s.type){k+=" mce"+s.type.substring(0,1).toUpperCase()+s.type.substring(1)}s.resizable=false}if(s.statusbar){k+=" mceStatusbar"}if(s.resizable){k+=" mceResizable"}if(s.minimizable){k+=" mceMinimizable"}if(s.maximizable){k+=" mceMaximizable"}if(s.movable){k+=" mceMovable"}z._addAll(d.doc.body,["div",{id:i,role:"dialog","aria-labelledby":s.type?i+"_content":i+"_title","class":(r.settings.inlinepopups_skin||"clearlooks2")+(tinymce.isIE&&window.getSelection?" ie9":""),style:"width:100px;height:100px"},["div",{id:i+"_wrapper","class":"mceWrapper"+k},["div",{id:i+"_top","class":"mceTop"},["div",{"class":"mceLeft"}],["div",{"class":"mceCenter"}],["div",{"class":"mceRight"}],["span",{id:i+"_title"},s.title||""]],["div",{id:i+"_middle","class":"mceMiddle"},["div",{id:i+"_left","class":"mceLeft",tabindex:"0"}],["span",{id:i+"_content"}],["div",{id:i+"_right","class":"mceRight",tabindex:"0"}]],["div",{id:i+"_bottom","class":"mceBottom"},["div",{"class":"mceLeft"}],["div",{"class":"mceCenter"}],["div",{"class":"mceRight"}],["span",{id:i+"_status"},"Content"]],["a",{"class":"mceMove",tabindex:"-1",href:"javascript:;"}],["a",{"class":"mceMin",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{"class":"mceMax",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{"class":"mceMed",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{"class":"mceClose",tabindex:"-1",href:"javascript:;",onmousedown:"return false;"}],["a",{id:i+"_resize_n","class":"mceResize mceResizeN",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_s","class":"mceResize mceResizeS",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_w","class":"mceResize mceResizeW",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_e","class":"mceResize mceResizeE",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_nw","class":"mceResize mceResizeNW",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_ne","class":"mceResize mceResizeNE",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_sw","class":"mceResize mceResizeSW",tabindex:"-1",href:"javascript:;"}],["a",{id:i+"_resize_se","class":"mceResize mceResizeSE",tabindex:"-1",href:"javascript:;"}]]]);d.setStyles(i,{top:-10000,left:-10000});if(tinymce.isGecko){d.setStyle(i,"overflow","auto")}if(!s.type){g+=d.get(i+"_left").clientWidth;g+=d.get(i+"_right").clientWidth;v+=d.get(i+"_top").clientHeight;v+=d.get(i+"_bottom").clientHeight}d.setStyles(i,{top:s.top,left:s.left,width:s.width+g,height:s.height+v});y=s.url||s.file;if(y){if(tinymce.relaxedDomain){y+=(y.indexOf("?")==-1?"?":"&")+"mce_rdomain="+tinymce.relaxedDomain}y=tinymce._addVer(y)}if(!s.type){d.add(i+"_content","iframe",{id:i+"_ifr",src:'javascript:""',frameBorder:0,style:"border:0;width:10px;height:10px"});d.setStyles(i+"_ifr",{width:s.width,height:s.height});d.setAttrib(i+"_ifr","src",y)}else{d.add(i+"_wrapper","a",{id:i+"_ok","class":"mceButton mceOk",href:"javascript:;",onmousedown:"return false;"},"Ok");if(s.type=="confirm"){d.add(i+"_wrapper","a",{"class":"mceButton mceCancel",href:"javascript:;",onmousedown:"return false;"},"Cancel")}d.add(i+"_middle","div",{"class":"mceIcon"});d.setHTML(i+"_content",s.content.replace("\n","<br />"));a.add(i,"keyup",function(f){var p=27;if(f.keyCode===p){s.button_func(false);return a.cancel(f)}});a.add(i,"keydown",function(f){var t,p=9;if(f.keyCode===p){t=d.select("a.mceCancel",i+"_wrapper")[0];if(t&&t!==f.target){t.focus()}else{d.get(i+"_ok").focus()}return a.cancel(f)}})}o=a.add(i,"mousedown",function(t){var u=t.target,f,p;f=z.windows[i];z.focus(i);if(u.nodeName=="A"||u.nodeName=="a"){if(u.className=="mceClose"){z.close(null,i);return a.cancel(t)}else{if(u.className=="mceMax"){f.oldPos=f.element.getXY();f.oldSize=f.element.getSize();p=d.getViewPort();p.w-=2;p.h-=2;f.element.moveTo(p.x,p.y);f.element.resizeTo(p.w,p.h);d.setStyles(i+"_ifr",{width:p.w-f.deltaWidth,height:p.h-f.deltaHeight});d.addClass(i+"_wrapper","mceMaximized")}else{if(u.className=="mceMed"){f.element.moveTo(f.oldPos.x,f.oldPos.y);f.element.resizeTo(f.oldSize.w,f.oldSize.h);f.iframeElement.resizeTo(f.oldSize.w-f.deltaWidth,f.oldSize.h-f.deltaHeight);d.removeClass(i+"_wrapper","mceMaximized")}else{if(u.className=="mceMove"){return z._startDrag(i,t,u.className)}else{if(d.hasClass(u,"mceResize")){return z._startDrag(i,t,u.className.substring(13))}}}}}}});q=a.add(i,"click",function(f){var p=f.target;z.focus(i);if(p.nodeName=="A"||p.nodeName=="a"){switch(p.className){case"mceClose":z.close(null,i);return a.cancel(f);case"mceButton mceOk":case"mceButton mceCancel":s.button_func(p.className=="mceButton mceOk");return a.cancel(f)}}});a.add([i+"_left",i+"_right"],"focus",function(p){var t=d.get(i+"_ifr");if(t){var f=t.contentWindow.document.body;var u=d.select(":input:enabled,*[tabindex=0]",f);if(p.target.id===(i+"_left")){u[u.length-1].focus()}else{u[0].focus()}}else{d.get(i+"_ok").focus()}});x=z.windows[i]={id:i,mousedown_func:o,click_func:q,element:new b(i,{blocker:1,container:r.getContainer()}),iframeElement:new b(i+"_ifr"),features:s,deltaWidth:g,deltaHeight:v};x.iframeElement.on("focus",function(){z.focus(i)});if(z.count==0&&z.editor.getParam("dialog_type","modal")=="modal"){d.add(d.doc.body,"div",{id:"mceModalBlocker","class":(z.editor.settings.inlinepopups_skin||"clearlooks2")+"_modalBlocker",style:{zIndex:z.zIndex-1}});d.show("mceModalBlocker");d.setAttrib(d.doc.body,"aria-hidden","true")}else{d.setStyle("mceModalBlocker","z-index",z.zIndex-1)}if(tinymce.isIE6||/Firefox\/2\./.test(navigator.userAgent)||(tinymce.isIE&&!d.boxModel)){d.setStyles("mceModalBlocker",{position:"absolute",left:h.x,top:h.y,width:h.w-2,height:h.h-2})}d.setAttrib(i,"aria-hidden","false");z.focus(i);z._fixIELayout(i,1);if(d.get(i+"_ok")){d.get(i+"_ok").focus()}z.count++;return x},focus:function(h){var g=this,f;if(f=g.windows[h]){f.zIndex=this.zIndex++;f.element.setStyle("zIndex",f.zIndex);f.element.update();h=h+"_wrapper";d.removeClass(g.lastId,"mceFocus");d.addClass(h,"mceFocus");g.lastId=h;if(f.focussedElement){f.focussedElement.focus()}else{if(d.get(h+"_ok")){d.get(f.id+"_ok").focus()}else{if(d.get(f.id+"_ifr")){d.get(f.id+"_ifr").focus()}}}}},_addAll:function(k,h){var g,l,f=this,j=tinymce.DOM;if(c(h,"string")){k.appendChild(j.doc.createTextNode(h))}else{if(h.length){k=k.appendChild(j.create(h[0],h[1]));for(g=2;g<h.length;g++){f._addAll(k,h[g])}}}},_startDrag:function(v,G,E){var o=this,u,z,C=d.doc,f,l=o.windows[v],h=l.element,y=h.getXY(),x,q,F,g,A,s,r,j,i,m,k,n,B;g={x:0,y:0};A=d.getViewPort();A.w-=2;A.h-=2;j=G.screenX;i=G.screenY;m=k=n=B=0;u=a.add(C,"mouseup",function(p){a.remove(C,"mouseup",u);a.remove(C,"mousemove",z);if(f){f.remove()}h.moveBy(m,k);h.resizeBy(n,B);q=h.getSize();d.setStyles(v+"_ifr",{width:q.w-l.deltaWidth,height:q.h-l.deltaHeight});o._fixIELayout(v,1);return a.cancel(p)});if(E!="Move"){D()}function D(){if(f){return}o._fixIELayout(v,0);d.add(C.body,"div",{id:"mceEventBlocker","class":"mceEventBlocker "+(o.editor.settings.inlinepopups_skin||"clearlooks2"),style:{zIndex:o.zIndex+1}});if(tinymce.isIE6||(tinymce.isIE&&!d.boxModel)){d.setStyles("mceEventBlocker",{position:"absolute",left:A.x,top:A.y,width:A.w-2,height:A.h-2})}f=new b("mceEventBlocker");f.update();x=h.getXY();q=h.getSize();s=g.x+x.x-A.x;r=g.y+x.y-A.y;d.add(f.get(),"div",{id:"mcePlaceHolder","class":"mcePlaceHolder",style:{left:s,top:r,width:q.w,height:q.h}});F=new b("mcePlaceHolder")}z=a.add(C,"mousemove",function(w){var p,H,t;D();p=w.screenX-j;H=w.screenY-i;switch(E){case"ResizeW":m=p;n=0-p;break;case"ResizeE":n=p;break;case"ResizeN":case"ResizeNW":case"ResizeNE":if(E=="ResizeNW"){m=p;n=0-p}else{if(E=="ResizeNE"){n=p}}k=H;B=0-H;break;case"ResizeS":case"ResizeSW":case"ResizeSE":if(E=="ResizeSW"){m=p;n=0-p}else{if(E=="ResizeSE"){n=p}}B=H;break;case"mceMove":m=p;k=H;break}if(n<(t=l.features.min_width-q.w)){if(m!==0){m+=n-t}n=t}if(B<(t=l.features.min_height-q.h)){if(k!==0){k+=B-t}B=t}n=Math.min(n,l.features.max_width-q.w);B=Math.min(B,l.features.max_height-q.h);m=Math.max(m,A.x-(s+A.x));k=Math.max(k,A.y-(r+A.y));m=Math.min(m,(A.w+A.x)-(s+q.w+A.x));k=Math.min(k,(A.h+A.y)-(r+q.h+A.y));if(m+k!==0){if(s+m<0){m=0}if(r+k<0){k=0}F.moveTo(s+m,r+k)}if(n+B!==0){F.resizeTo(q.w+n,q.h+B)}return a.cancel(w)});return a.cancel(G)},resizeBy:function(g,h,i){var f=this.windows[i];if(f){f.element.resizeBy(g,h);f.iframeElement.resizeBy(g,h)}},close:function(i,k){var g=this,f,j=d.doc,h,k;k=g._findId(k||i);if(!g.windows[k]){g.parent(i);return}g.count--;if(g.count==0){d.remove("mceModalBlocker");d.setAttrib(d.doc.body,"aria-hidden","false");g.editor.focus()}if(f=g.windows[k]){g.onClose.dispatch(g);a.remove(j,"mousedown",f.mousedownFunc);a.remove(j,"click",f.clickFunc);a.clear(k);a.clear(k+"_ifr");d.setAttrib(k+"_ifr","src",'javascript:""');f.element.remove();delete g.windows[k];h=g._frontWindow();if(h){g.focus(h.id)}}},_frontWindow:function(){var g,f=0;e(this.windows,function(h){if(h.zIndex>f){g=h;f=h.zIndex}});return g},setTitle:function(f,g){var h;f=this._findId(f);if(h=d.get(f+"_title")){h.innerHTML=d.encode(g)}},alert:function(g,f,j){var i=this,h;h=i.open({title:i,type:"alert",button_func:function(k){if(f){f.call(k||i,k)}i.close(null,h.id)},content:d.encode(i.editor.getLang(g,g)),inline:1,width:400,height:130})},confirm:function(g,f,j){var i=this,h;h=i.open({title:i,type:"confirm",button_func:function(k){if(f){f.call(k||i,k)}i.close(null,h.id)},content:d.encode(i.editor.getLang(g,g)),inline:1,width:400,height:130})},_findId:function(f){var g=this;if(typeof(f)=="string"){return f}e(g.windows,function(h){var i=d.get(h.id+"_ifr");if(i&&f==i.contentWindow){f=h.id;return false}});return f},_fixIELayout:function(i,h){var f,g;if(!tinymce.isIE6){return}e(["n","s","w","e","nw","ne","sw","se"],function(j){var k=d.get(i+"_resize_"+j);d.setStyles(k,{width:h?k.clientWidth:"",height:h?k.clientHeight:"",cursor:d.getStyle(k,"cursor",1)});d.setStyle(i+"_bottom","bottom","-1px");k=0});if(f=this.windows[i]){f.element.hide();f.element.show();e(d.select("div,a",i),function(k,j){if(k.currentStyle.backgroundImage!="none"){g=new Image();g.src=k.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/,"$1")}});d.get(i).style.filter=""}}});tinymce.PluginManager.add("inlinepopups",tinymce.plugins.InlinePopups)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/editor_plugin_src.js new file mode 100644 index 0000000..67123ca --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/editor_plugin_src.js @@ -0,0 +1,699 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var DOM = tinymce.DOM, Element = tinymce.dom.Element, Event = tinymce.dom.Event, each = tinymce.each, is = tinymce.is; + + tinymce.create('tinymce.plugins.InlinePopups', { + init : function(ed, url) { + // Replace window manager + ed.onBeforeRenderUI.add(function() { + ed.windowManager = new tinymce.InlineWindowManager(ed); + DOM.loadCSS(url + '/skins/' + (ed.settings.inlinepopups_skin || 'clearlooks2') + "/window.css"); + }); + }, + + getInfo : function() { + return { + longname : 'InlinePopups', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + tinymce.create('tinymce.InlineWindowManager:tinymce.WindowManager', { + InlineWindowManager : function(ed) { + var t = this; + + t.parent(ed); + t.zIndex = 300000; + t.count = 0; + t.windows = {}; + }, + + open : function(f, p) { + var t = this, id, opt = '', ed = t.editor, dw = 0, dh = 0, vp, po, mdf, clf, we, w, u, parentWindow; + + f = f || {}; + p = p || {}; + + // Run native windows + if (!f.inline) + return t.parent(f, p); + + parentWindow = t._frontWindow(); + if (parentWindow && DOM.get(parentWindow.id + '_ifr')) { + parentWindow.focussedElement = DOM.get(parentWindow.id + '_ifr').contentWindow.document.activeElement; + } + + // Only store selection if the type is a normal window + if (!f.type) + t.bookmark = ed.selection.getBookmark(1); + + id = DOM.uniqueId(); + vp = DOM.getViewPort(); + f.width = parseInt(f.width || 320); + f.height = parseInt(f.height || 240) + (tinymce.isIE ? 8 : 0); + f.min_width = parseInt(f.min_width || 150); + f.min_height = parseInt(f.min_height || 100); + f.max_width = parseInt(f.max_width || 2000); + f.max_height = parseInt(f.max_height || 2000); + f.left = f.left || Math.round(Math.max(vp.x, vp.x + (vp.w / 2.0) - (f.width / 2.0))); + f.top = f.top || Math.round(Math.max(vp.y, vp.y + (vp.h / 2.0) - (f.height / 2.0))); + f.movable = f.resizable = true; + p.mce_width = f.width; + p.mce_height = f.height; + p.mce_inline = true; + p.mce_window_id = id; + p.mce_auto_focus = f.auto_focus; + + // Transpose +// po = DOM.getPos(ed.getContainer()); +// f.left -= po.x; +// f.top -= po.y; + + t.features = f; + t.params = p; + t.onOpen.dispatch(t, f, p); + + if (f.type) { + opt += ' mceModal'; + + if (f.type) + opt += ' mce' + f.type.substring(0, 1).toUpperCase() + f.type.substring(1); + + f.resizable = false; + } + + if (f.statusbar) + opt += ' mceStatusbar'; + + if (f.resizable) + opt += ' mceResizable'; + + if (f.minimizable) + opt += ' mceMinimizable'; + + if (f.maximizable) + opt += ' mceMaximizable'; + + if (f.movable) + opt += ' mceMovable'; + + // Create DOM objects + t._addAll(DOM.doc.body, + ['div', {id : id, role : 'dialog', 'aria-labelledby': f.type ? id + '_content' : id + '_title', 'class' : (ed.settings.inlinepopups_skin || 'clearlooks2') + (tinymce.isIE && window.getSelection ? ' ie9' : ''), style : 'width:100px;height:100px'}, + ['div', {id : id + '_wrapper', 'class' : 'mceWrapper' + opt}, + ['div', {id : id + '_top', 'class' : 'mceTop'}, + ['div', {'class' : 'mceLeft'}], + ['div', {'class' : 'mceCenter'}], + ['div', {'class' : 'mceRight'}], + ['span', {id : id + '_title'}, f.title || ''] + ], + + ['div', {id : id + '_middle', 'class' : 'mceMiddle'}, + ['div', {id : id + '_left', 'class' : 'mceLeft', tabindex : '0'}], + ['span', {id : id + '_content'}], + ['div', {id : id + '_right', 'class' : 'mceRight', tabindex : '0'}] + ], + + ['div', {id : id + '_bottom', 'class' : 'mceBottom'}, + ['div', {'class' : 'mceLeft'}], + ['div', {'class' : 'mceCenter'}], + ['div', {'class' : 'mceRight'}], + ['span', {id : id + '_status'}, 'Content'] + ], + + ['a', {'class' : 'mceMove', tabindex : '-1', href : 'javascript:;'}], + ['a', {'class' : 'mceMin', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], + ['a', {'class' : 'mceMax', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], + ['a', {'class' : 'mceMed', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], + ['a', {'class' : 'mceClose', tabindex : '-1', href : 'javascript:;', onmousedown : 'return false;'}], + ['a', {id : id + '_resize_n', 'class' : 'mceResize mceResizeN', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_s', 'class' : 'mceResize mceResizeS', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_w', 'class' : 'mceResize mceResizeW', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_e', 'class' : 'mceResize mceResizeE', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_nw', 'class' : 'mceResize mceResizeNW', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_ne', 'class' : 'mceResize mceResizeNE', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_sw', 'class' : 'mceResize mceResizeSW', tabindex : '-1', href : 'javascript:;'}], + ['a', {id : id + '_resize_se', 'class' : 'mceResize mceResizeSE', tabindex : '-1', href : 'javascript:;'}] + ] + ] + ); + + DOM.setStyles(id, {top : -10000, left : -10000}); + + // Fix gecko rendering bug, where the editors iframe messed with window contents + if (tinymce.isGecko) + DOM.setStyle(id, 'overflow', 'auto'); + + // Measure borders + if (!f.type) { + dw += DOM.get(id + '_left').clientWidth; + dw += DOM.get(id + '_right').clientWidth; + dh += DOM.get(id + '_top').clientHeight; + dh += DOM.get(id + '_bottom').clientHeight; + } + + // Resize window + DOM.setStyles(id, {top : f.top, left : f.left, width : f.width + dw, height : f.height + dh}); + + u = f.url || f.file; + if (u) { + if (tinymce.relaxedDomain) + u += (u.indexOf('?') == -1 ? '?' : '&') + 'mce_rdomain=' + tinymce.relaxedDomain; + + u = tinymce._addVer(u); + } + + if (!f.type) { + DOM.add(id + '_content', 'iframe', {id : id + '_ifr', src : 'javascript:""', frameBorder : 0, style : 'border:0;width:10px;height:10px'}); + DOM.setStyles(id + '_ifr', {width : f.width, height : f.height}); + DOM.setAttrib(id + '_ifr', 'src', u); + } else { + DOM.add(id + '_wrapper', 'a', {id : id + '_ok', 'class' : 'mceButton mceOk', href : 'javascript:;', onmousedown : 'return false;'}, 'Ok'); + + if (f.type == 'confirm') + DOM.add(id + '_wrapper', 'a', {'class' : 'mceButton mceCancel', href : 'javascript:;', onmousedown : 'return false;'}, 'Cancel'); + + DOM.add(id + '_middle', 'div', {'class' : 'mceIcon'}); + DOM.setHTML(id + '_content', f.content.replace('\n', '<br />')); + + Event.add(id, 'keyup', function(evt) { + var VK_ESCAPE = 27; + if (evt.keyCode === VK_ESCAPE) { + f.button_func(false); + return Event.cancel(evt); + } + }); + + Event.add(id, 'keydown', function(evt) { + var cancelButton, VK_TAB = 9; + if (evt.keyCode === VK_TAB) { + cancelButton = DOM.select('a.mceCancel', id + '_wrapper')[0]; + if (cancelButton && cancelButton !== evt.target) { + cancelButton.focus(); + } else { + DOM.get(id + '_ok').focus(); + } + return Event.cancel(evt); + } + }); + } + + // Register events + mdf = Event.add(id, 'mousedown', function(e) { + var n = e.target, w, vp; + + w = t.windows[id]; + t.focus(id); + + if (n.nodeName == 'A' || n.nodeName == 'a') { + if (n.className == 'mceClose') { + t.close(null, id); + return Event.cancel(e); + } else if (n.className == 'mceMax') { + w.oldPos = w.element.getXY(); + w.oldSize = w.element.getSize(); + + vp = DOM.getViewPort(); + + // Reduce viewport size to avoid scrollbars + vp.w -= 2; + vp.h -= 2; + + w.element.moveTo(vp.x, vp.y); + w.element.resizeTo(vp.w, vp.h); + DOM.setStyles(id + '_ifr', {width : vp.w - w.deltaWidth, height : vp.h - w.deltaHeight}); + DOM.addClass(id + '_wrapper', 'mceMaximized'); + } else if (n.className == 'mceMed') { + // Reset to old size + w.element.moveTo(w.oldPos.x, w.oldPos.y); + w.element.resizeTo(w.oldSize.w, w.oldSize.h); + w.iframeElement.resizeTo(w.oldSize.w - w.deltaWidth, w.oldSize.h - w.deltaHeight); + + DOM.removeClass(id + '_wrapper', 'mceMaximized'); + } else if (n.className == 'mceMove') + return t._startDrag(id, e, n.className); + else if (DOM.hasClass(n, 'mceResize')) + return t._startDrag(id, e, n.className.substring(13)); + } + }); + + clf = Event.add(id, 'click', function(e) { + var n = e.target; + + t.focus(id); + + if (n.nodeName == 'A' || n.nodeName == 'a') { + switch (n.className) { + case 'mceClose': + t.close(null, id); + return Event.cancel(e); + + case 'mceButton mceOk': + case 'mceButton mceCancel': + f.button_func(n.className == 'mceButton mceOk'); + return Event.cancel(e); + } + } + }); + + // Make sure the tab order loops within the dialog. + Event.add([id + '_left', id + '_right'], 'focus', function(evt) { + var iframe = DOM.get(id + '_ifr'); + if (iframe) { + var body = iframe.contentWindow.document.body; + var focusable = DOM.select(':input:enabled,*[tabindex=0]', body); + if (evt.target.id === (id + '_left')) { + focusable[focusable.length - 1].focus(); + } else { + focusable[0].focus(); + } + } else { + DOM.get(id + '_ok').focus(); + } + }); + + // Add window + w = t.windows[id] = { + id : id, + mousedown_func : mdf, + click_func : clf, + element : new Element(id, {blocker : 1, container : ed.getContainer()}), + iframeElement : new Element(id + '_ifr'), + features : f, + deltaWidth : dw, + deltaHeight : dh + }; + + w.iframeElement.on('focus', function() { + t.focus(id); + }); + + // Setup blocker + if (t.count == 0 && t.editor.getParam('dialog_type', 'modal') == 'modal') { + DOM.add(DOM.doc.body, 'div', { + id : 'mceModalBlocker', + 'class' : (t.editor.settings.inlinepopups_skin || 'clearlooks2') + '_modalBlocker', + style : {zIndex : t.zIndex - 1} + }); + + DOM.show('mceModalBlocker'); // Reduces flicker in IE + DOM.setAttrib(DOM.doc.body, 'aria-hidden', 'true'); + } else + DOM.setStyle('mceModalBlocker', 'z-index', t.zIndex - 1); + + if (tinymce.isIE6 || /Firefox\/2\./.test(navigator.userAgent) || (tinymce.isIE && !DOM.boxModel)) + DOM.setStyles('mceModalBlocker', {position : 'absolute', left : vp.x, top : vp.y, width : vp.w - 2, height : vp.h - 2}); + + DOM.setAttrib(id, 'aria-hidden', 'false'); + t.focus(id); + t._fixIELayout(id, 1); + + // Focus ok button + if (DOM.get(id + '_ok')) + DOM.get(id + '_ok').focus(); + t.count++; + + return w; + }, + + focus : function(id) { + var t = this, w; + + if (w = t.windows[id]) { + w.zIndex = this.zIndex++; + w.element.setStyle('zIndex', w.zIndex); + w.element.update(); + + id = id + '_wrapper'; + DOM.removeClass(t.lastId, 'mceFocus'); + DOM.addClass(id, 'mceFocus'); + t.lastId = id; + + if (w.focussedElement) { + w.focussedElement.focus(); + } else if (DOM.get(id + '_ok')) { + DOM.get(w.id + '_ok').focus(); + } else if (DOM.get(w.id + '_ifr')) { + DOM.get(w.id + '_ifr').focus(); + } + } + }, + + _addAll : function(te, ne) { + var i, n, t = this, dom = tinymce.DOM; + + if (is(ne, 'string')) + te.appendChild(dom.doc.createTextNode(ne)); + else if (ne.length) { + te = te.appendChild(dom.create(ne[0], ne[1])); + + for (i=2; i<ne.length; i++) + t._addAll(te, ne[i]); + } + }, + + _startDrag : function(id, se, ac) { + var t = this, mu, mm, d = DOM.doc, eb, w = t.windows[id], we = w.element, sp = we.getXY(), p, sz, ph, cp, vp, sx, sy, sex, sey, dx, dy, dw, dh; + + // Get positons and sizes +// cp = DOM.getPos(t.editor.getContainer()); + cp = {x : 0, y : 0}; + vp = DOM.getViewPort(); + + // Reduce viewport size to avoid scrollbars while dragging + vp.w -= 2; + vp.h -= 2; + + sex = se.screenX; + sey = se.screenY; + dx = dy = dw = dh = 0; + + // Handle mouse up + mu = Event.add(d, 'mouseup', function(e) { + Event.remove(d, 'mouseup', mu); + Event.remove(d, 'mousemove', mm); + + if (eb) + eb.remove(); + + we.moveBy(dx, dy); + we.resizeBy(dw, dh); + sz = we.getSize(); + DOM.setStyles(id + '_ifr', {width : sz.w - w.deltaWidth, height : sz.h - w.deltaHeight}); + t._fixIELayout(id, 1); + + return Event.cancel(e); + }); + + if (ac != 'Move') + startMove(); + + function startMove() { + if (eb) + return; + + t._fixIELayout(id, 0); + + // Setup event blocker + DOM.add(d.body, 'div', { + id : 'mceEventBlocker', + 'class' : 'mceEventBlocker ' + (t.editor.settings.inlinepopups_skin || 'clearlooks2'), + style : {zIndex : t.zIndex + 1} + }); + + if (tinymce.isIE6 || (tinymce.isIE && !DOM.boxModel)) + DOM.setStyles('mceEventBlocker', {position : 'absolute', left : vp.x, top : vp.y, width : vp.w - 2, height : vp.h - 2}); + + eb = new Element('mceEventBlocker'); + eb.update(); + + // Setup placeholder + p = we.getXY(); + sz = we.getSize(); + sx = cp.x + p.x - vp.x; + sy = cp.y + p.y - vp.y; + DOM.add(eb.get(), 'div', {id : 'mcePlaceHolder', 'class' : 'mcePlaceHolder', style : {left : sx, top : sy, width : sz.w, height : sz.h}}); + ph = new Element('mcePlaceHolder'); + }; + + // Handle mouse move/drag + mm = Event.add(d, 'mousemove', function(e) { + var x, y, v; + + startMove(); + + x = e.screenX - sex; + y = e.screenY - sey; + + switch (ac) { + case 'ResizeW': + dx = x; + dw = 0 - x; + break; + + case 'ResizeE': + dw = x; + break; + + case 'ResizeN': + case 'ResizeNW': + case 'ResizeNE': + if (ac == "ResizeNW") { + dx = x; + dw = 0 - x; + } else if (ac == "ResizeNE") + dw = x; + + dy = y; + dh = 0 - y; + break; + + case 'ResizeS': + case 'ResizeSW': + case 'ResizeSE': + if (ac == "ResizeSW") { + dx = x; + dw = 0 - x; + } else if (ac == "ResizeSE") + dw = x; + + dh = y; + break; + + case 'mceMove': + dx = x; + dy = y; + break; + } + + // Boundary check + if (dw < (v = w.features.min_width - sz.w)) { + if (dx !== 0) + dx += dw - v; + + dw = v; + } + + if (dh < (v = w.features.min_height - sz.h)) { + if (dy !== 0) + dy += dh - v; + + dh = v; + } + + dw = Math.min(dw, w.features.max_width - sz.w); + dh = Math.min(dh, w.features.max_height - sz.h); + dx = Math.max(dx, vp.x - (sx + vp.x)); + dy = Math.max(dy, vp.y - (sy + vp.y)); + dx = Math.min(dx, (vp.w + vp.x) - (sx + sz.w + vp.x)); + dy = Math.min(dy, (vp.h + vp.y) - (sy + sz.h + vp.y)); + + // Move if needed + if (dx + dy !== 0) { + if (sx + dx < 0) + dx = 0; + + if (sy + dy < 0) + dy = 0; + + ph.moveTo(sx + dx, sy + dy); + } + + // Resize if needed + if (dw + dh !== 0) + ph.resizeTo(sz.w + dw, sz.h + dh); + + return Event.cancel(e); + }); + + return Event.cancel(se); + }, + + resizeBy : function(dw, dh, id) { + var w = this.windows[id]; + + if (w) { + w.element.resizeBy(dw, dh); + w.iframeElement.resizeBy(dw, dh); + } + }, + + close : function(win, id) { + var t = this, w, d = DOM.doc, fw, id; + + id = t._findId(id || win); + + // Probably not inline + if (!t.windows[id]) { + t.parent(win); + return; + } + + t.count--; + + if (t.count == 0) { + DOM.remove('mceModalBlocker'); + DOM.setAttrib(DOM.doc.body, 'aria-hidden', 'false'); + t.editor.focus(); + } + + if (w = t.windows[id]) { + t.onClose.dispatch(t); + Event.remove(d, 'mousedown', w.mousedownFunc); + Event.remove(d, 'click', w.clickFunc); + Event.clear(id); + Event.clear(id + '_ifr'); + + DOM.setAttrib(id + '_ifr', 'src', 'javascript:""'); // Prevent leak + w.element.remove(); + delete t.windows[id]; + + fw = t._frontWindow(); + + if (fw) + t.focus(fw.id); + } + }, + + // Find front most window + _frontWindow : function() { + var fw, ix = 0; + // Find front most window and focus that + each (this.windows, function(w) { + if (w.zIndex > ix) { + fw = w; + ix = w.zIndex; + } + }); + return fw; + }, + + setTitle : function(w, ti) { + var e; + + w = this._findId(w); + + if (e = DOM.get(w + '_title')) + e.innerHTML = DOM.encode(ti); + }, + + alert : function(txt, cb, s) { + var t = this, w; + + w = t.open({ + title : t, + type : 'alert', + button_func : function(s) { + if (cb) + cb.call(s || t, s); + + t.close(null, w.id); + }, + content : DOM.encode(t.editor.getLang(txt, txt)), + inline : 1, + width : 400, + height : 130 + }); + }, + + confirm : function(txt, cb, s) { + var t = this, w; + + w = t.open({ + title : t, + type : 'confirm', + button_func : function(s) { + if (cb) + cb.call(s || t, s); + + t.close(null, w.id); + }, + content : DOM.encode(t.editor.getLang(txt, txt)), + inline : 1, + width : 400, + height : 130 + }); + }, + + // Internal functions + + _findId : function(w) { + var t = this; + + if (typeof(w) == 'string') + return w; + + each(t.windows, function(wo) { + var ifr = DOM.get(wo.id + '_ifr'); + + if (ifr && w == ifr.contentWindow) { + w = wo.id; + return false; + } + }); + + return w; + }, + + _fixIELayout : function(id, s) { + var w, img; + + if (!tinymce.isIE6) + return; + + // Fixes the bug where hover flickers and does odd things in IE6 + each(['n','s','w','e','nw','ne','sw','se'], function(v) { + var e = DOM.get(id + '_resize_' + v); + + DOM.setStyles(e, { + width : s ? e.clientWidth : '', + height : s ? e.clientHeight : '', + cursor : DOM.getStyle(e, 'cursor', 1) + }); + + DOM.setStyle(id + "_bottom", 'bottom', '-1px'); + + e = 0; + }); + + // Fixes graphics glitch + if (w = this.windows[id]) { + // Fixes rendering bug after resize + w.element.hide(); + w.element.show(); + + // Forced a repaint of the window + //DOM.get(id).style.filter = ''; + + // IE has a bug where images used in CSS won't get loaded + // sometimes when the cache in the browser is disabled + // This fix tries to solve it by loading the images using the image object + each(DOM.select('div,a', id), function(e, i) { + if (e.currentStyle.backgroundImage != 'none') { + img = new Image(); + img.src = e.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/, '$1'); + } + }); + + DOM.get(id).style.filter = ''; + } + } + }); + + // Register plugin + tinymce.PluginManager.add('inlinepopups', tinymce.plugins.InlinePopups); +})(); + diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif new file mode 100644 index 0000000000000000000000000000000000000000..219139857ead162c6c83fa92e4a36eb978359b70 GIT binary patch literal 810 zcmV+_1J(RTNk%v~VITk?0QP$T|NsBgZf>Is3*B5?sT&&Hqoc$;Jkrt6&k+&QHa5gV zL)l77I5;@fLqpYMWV<abwUm?7QBkxrGu*<$+j)7$S6A9;Y1?*oyK8FB&&|;q8Uq6Z z%mM<tJUq<=1mJ9J-(q5{BqZT=b=gHl*N%?Q4i4J1w6jf2;c#%QD=X6^B;RFa%}Yzp z2ng9yQp1dkrxq5d6co*~vAevw&lVQfJw4b#LAqpQ*4EV8&dt-y$<jJH(kUsW5)!XE zI<Kdt&l(!iN=n~qYTH*=+fY!kC@7*564*OC#m2;^otw#{p&J_;(7(MUB_+qm#;Ty7 z)i5y3V`IHZN!8NO&$_wHv9Hj;zSfwSz<++opPsm0UDu+bp8^8hRaMU{EZU5W)p>c- z$;Z;u(cpZ1*{!X#QBc56PRYv1%goBm&CA4*kj9vnyFx<e!NJmBU(r85yc`_bZEdF@ zAmh5a-++MIVq($7!@-4wp8x>N007q4)xCFi000000000000000EC2ui03ZM$000O7 zfO>+1goTEOh>41ejE#<kdjbL&kBn<EaTYNzm5Oo!HY08@Q=Nx*5-1!VC`Egwg$FPc zDl{}a76Ll3gL`Zsc_ddHAQCscdSN|u8eRYZ2^zUfyjo^md0Wq997G)_uuL&@C2!Bq zK?u23rY98(946-g6CO4SKAlwrV=WQ$&)l@A(<4hIA5o69nDA`FhI1vLC<uYWk&+N1 zJUBS#@Z1FtLkMtclp+8W1oJwc1EPWjDMo4}2;l%G<->Ddx`lYP=u<6#D$nuIz(SWI zEFA^}1Gr=fzyf({6gh@S$E;fb0W@inbw`OH0<0jyAcaV_tY`tu;Q-}9nL~DuW|c$B zfB{+;EgA@rVMxoncy#S%&Cx=|gM5Uj%<`AEF#ro5b_h^H$lZ~%j?uQsqv1gcLINnz z$V0lc>C>q5v`E0^fS@#T44@D}8^s49D{>FmJ;a6Y1;88FsF47UkqoaP7{SB5x%21H on;U^3X3&`#Kb|Dn&b_<$?>}ZBkL3i3`Sa-0r$^%&nWI1eJN~S2!T<mO literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif new file mode 100644 index 0000000000000000000000000000000000000000..f957e49a3dda34867982d54bdbbf46e5b6c11298 GIT binary patch literal 272 zcmZ?wbh9u|3}BFB_{_m@?Z&m_<m7ADuRePG@c#XKPoF(yU|{(F|Np7eCx8r0paT*D z>1AL!8o=VbdauRnv)25R3VTvA=Vh!~_a@6HSLb|**VT%3)4#v_zecXW!-k{V<F4V! zIl8k0rmt{V8@2w%nzGYx%kuASsPH-0bo#}XSygen@8347vD?r1?#G_G^Y4HEZ>Z-e zYiw<6@2F~4>g?_7FYjibFlA~}%e0v@C(W8Wb<Vtny^~m$E?d50<*L<d)~;K-Wc{Yi zTehy)xNYaI-8**g+rPp5z~Ljy_cEV2dFu3;v**rVxOnFHrK{Jj-(YSQzIpfF{S*3% Pa!;N<doHdZ$Y2csQd^57 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif new file mode 100644 index 0000000000000000000000000000000000000000..6baf64ad321ab3d35330f2aaae7504aa519644bd GIT binary patch literal 1195 zcmV;c1XTM+Nk%w1VRQg60K^&qo}rxY@9u7Ug;85$H#j%{|NpDH#%p|xwZqR~a)67K zo_>*_&)DBrWN@OfznH1FT4{BUps!wTd|YdJ0002^_xJYp^u)%)d3$)z&B_1&{{R30 z000000000000000A^8LW000^QEC2ui0CWH_000I5phk>jX`ZJhqHH^=Zk(=iEn-2g z?|i>wBOI?nEE<hGAVKJBHkC}LRHw8|uQ|)eIy`!bJS~BXm5Ryb<~eQN_P*b+o2{PH zd+R&iu7i8!V@(u;go93bJ%&1pK8SicjyXhygMT}bi<FFefj)#epLLy&kbIIAnwF)b zJer$;XswiOtfZKeMii=9ri+P(y*q_dViy3%$j7b}$;}rd#?8tZ8I;n<&jiuZ%+1}` z+1uBJ*U91K%jE#)<J1(@)#~ir^yTy1*7DHkuKL>ih2q)UH?AHyg7~@-@+VH6!(;c_ zxnl@0-@$+5z5y6S@uA0c2rFuI7V_gjj3zt(raakjrMZ$WvB8W9atTdoP;NHMsS_E` zo&bQ*s1XAOQ5i;$x=5;&g^B@Cqe`7hmFm-~ShGUCs<o?Bu3o)rfXbk(*|TWVo|US$ zty>0c-^w)`cdp#12=eOP%eQY|sD1+r)(d#BVZMbAD~4*IvE#>(BS&T|xw7TPlrL+3 zoO$zRs18Dl9!<J*Y0#!qs}7CYbb;5fU$1UmTDEB0si8jD&AYen-@kPOe-Qii@ZQ3K z7l(cPLGs_si5ou-HG=i)*t2WbUVVFn<=(M(-@g2H_z2_47e9}Fz=HSi<IA5vA1eL# z1>)zw58wX%{rd5@fPehOCg6KeHK5@Cf($n3po0lM*gyda7AK*C5k5#^gBwbip@gwr zxFA#zlxU)f<rQ$^iV%><Vu>n3pyG@#n&{$-F`k&?i#Os}T#YskFu{;S5}9I=NKOD% zl13IcK><t>xnz`3B3WgWQ!)wLkXuHn<Ny+cDW;eyj%lU@P@Q>Z0c5HvW}0r6=_Z<B z#>pm`ce)8x0(|!A=bwNAx@Vw%7Dp(bgC44=paU%GsGm?BAnBx(R%)rGkzT6lrjlmL z>8F%>3M!~kDPZcUsHUnas#2}$>Z=O03hS(=%1Z03TZN@7Sh{A#Yp+%P3hY!W2w?27 z$R?|-vc)dz?6bx;3+=SXN=q&OwHg>}*IdYMD_6JPx&>~yY8|WCxyGKWSi0&O#%{ZU z8SB}+^3J<iz4l&)Z@!foyV}2{`3vyC4hZa8d8-**TLGitW}30hMf@AY!!0K<#mbe} z9LCU17u|5ivL`ZjA$tcNdnK!PvUe$~3>(S<94K>q#ugahfi?d(AAt1bTp(;R8!O__ z4hjuog&|&Ow1y6L_~6nY!bY^QK&A*J1XR};BaJ(<m^F?pcD>@)KE`%6)&h8Wq?g93 z?c|kAwoPS{a3?9ZmalP{H`@ZtDW{vp&e>*|d8!$>oy!S+xSFqx+4!8sJ}P<SiyC?; z<&rOodFGc3FzV;Vem-g_=%Rm0dg+@Udn>KTu0Ct)uD=R<?5jq5?d{gy{%r2LFUx!H J$!ZV+06W;kU)}%! literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif new file mode 100644 index 0000000000000000000000000000000000000000..20acbbf7aec8a3fccbffbbb894f973241a045732 GIT binary patch literal 907 zcmV;619bdHNk%v~VITk?0QPwR_mwyIk1Co}49|EKqh~0+ri!6j6Z*7U`lU1e^XU7^ zod5p+om&^t%*Cs9J)E4I)z#6vZX5cfOQfZw_J9bzzPy@aE7*uE$H2Mzs7<(K4$*}x z?4CLJokRMqQrd$ZlS~7knw0jXHTSe!o0*mDqeS+82K9OY`oWCJ%E<SVGxdH6#m2<> znI-zTdit_%`kX1XwzT=HMfsK@_J<qznmqP{6RobS&d<&GkQ=;e5vr@I!NS1#uvD?K zu=a@`xw*Li`}gaYEc&1=_lObsp+(MuEv0u!+?7DFgH-pHIK#xkyS%!zjA6^n%AsE! z($2`PeM!&I&ehh`{`c{}z`oGY&-j-*v$V3Xv9Gtdw(F`?#KptR!nLccs?dfq`Kw{c z!@HGxUzUAg-HIdp*R%V$UiqnAsh^Usu&>>ZF~`Wpm{14%#gX`?RrPxW_?tKTt2vcW z2>QE!xVg8it*iEY1oe3U*4Nd~$-n>r00000000000000000000EC2ui03ZM$000O7 zfOvv~gm?`F4o?Cg0#6PF4TX}EcwG(x5lCAjW+Pij5dscfl$1#VUuGE{0IjYW2VVk7 z5T%0+1Q8<=O0K@HMI#Xek);g`Mh92F%&$fa#ghcdz0KAc8w9nIO}f?A*AY#Uc?QbO z3RLO});$J!g;5v0=nMAj%^ep}gir!z-+rO6w*Un=4+5YJDiFZ~I2Q!xfRmu3z#s=| zihz4T@CCRUY8(uDQlbX9GX%kWEb(N}zkt6a5bW@S#*YBZWC(Bx@FPJRcY+3`q2d)A zmpx#*`mrL2J)uzF{Ai_fBnOke0ssw~U_pYYQE6~!DagSGIIXnWiQ2(U2e47_$%qtG zKtl_-P`Bc}lcVA-0SHd)Rj{DU-aA7Q5{fb)$6lukR^TP_fghoAf$`3v(q`|FciePj zJ`5Lzj&afk40%I3YKsBdC>>Kxp>@z91EARoLqLOw8Eg0E5TStp1}jr0SxLdA!VxyA zTM#iJc<2lS0|XplvLpqLZT(nO0fGgM1vVN!2oVuSgpdy!*jPa0LraD3QY1MMPyWV) z5M!Jt2O|PlAVvri?2tta_j#uua~06xgMa@$K*EI<Cg{b2+^zAQa{KWRVGI-2vBQZQ hrh$chRdC^;Ef7e-+!7*2$i$8J@xX!;$Vn0i06V<1vibl3 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif new file mode 100644 index 0000000000000000000000000000000000000000..d5de1cc236c9e44b2bcce92b4444f9cc7c43c551 GIT binary patch literal 909 zcmd6k{WFts0KlK`HhVEz-VP%)t%%6w2P$qT_Vhz_x6{iH74Ayc4<%REb(eY?v$8WW z4khQU($$h#iW<+#%Or2nwaUu~d&TU9y;A)beg1;a=RRq0YFvEgF31;JgQ3skzaR)o z*dHe!>EGPkB#}sYrS(hdInBZpyW+|1vW7c?#%0ZK)9R8@uU$7A%*K`47Ku)&&@N8% zYK4`}Z?(#q)nzsJ;d4P#TS@)v!Eck-?^kOUr>&MXooZI6QXu6`cgvfGK6NyRP`l0I zbUL24e{$GuZ=Tk)b;~w3oNZk)lVQ14(q~xFwmqvbt?JB%Wl>kZ(_t4$`g=#dTP<eG zn(;&5sLi_G*)#n1;}>!FfZc90uIhs65nZyc!gn8KV?V^`fOK%epx0W~O)FaE->(0k z?N*!%1i?_`Kh=Lv7=%p(X0u)L3pj<K5DsTDu^52khZi$LF^n|#8g~#+t*1VAPh&Jt z;{m^<RKPEL31U3oc!EfBC%N4-2H@XEzTiJ-<?~>dSo+ZClpSM3^jOZ=j+CO8eJz!t zq0G`~;ye*V;nnyBVl=9W>Jj!cd0-F0N&tsQ8zkEnF;O24JZ?^&qO;nwIHcqN+QW<Y z!shUY;r5QKURM^_MoCT#JKn?|aHR#S!g55(9t8oJk|Q1pDd&+dMvtOi*kLjSW9mV% zI}>1R89rxky}AI}=gmx4Tw`N1SlNC{7h0s;mS9Zt)}#|SIi=REJiRqNljiTH@k0@h zx>r*jSI^6*BI>TpNc;poVS4>2-YcJQ#?7&Nd)eix@@huXX@A74D!h?VgENw#pGCd% zsxdBiJjhjk58aQsL`ifN^D`QSq1}1pNdyf@Mne4A*(&$hR50t$mZ#==bMuuaZyc{W z3OccYpqV9ab*SFuDkp>y%A>aq7N>y#HQJSeP+30Wl?>dA3F_dI^EEnyd3A<t%9c`4 zqTn1Y2B`}nW^oi5L^4~?0~8S_=;VDx<1r|~+k2GZV$M;70My493y4x_QDBV>IUAW9 QatMOy3rC81I1F^)55?|uDF6Tf literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif new file mode 100644 index 0000000000000000000000000000000000000000..c2a2ad454db194e428a7b9da40f62d5376a17428 GIT binary patch literal 769 zcmb7?=`WiB0LI^D)(HC`v6*aD4AW#LGRb0Oi$t<fW)_L~Kx~mM4a>H~CP=nb%N%8n zy02ceuewTUUDeW|RaMp*TlLV6R$o=rQOY{@AME+?`}QQiCwU%4Jq)?`{5B8=ECT1T z+wH!7{<!M4+^W_x3X9mvt_8U*Jv?fkfX)#zho;^a)qkj<V5?d`5osSQsRa$~gqAMJ z;>zji$)-UA>D9({)xO1SJGLHK54Mat(}s4_unMiKjB85EHng*~!Ddt+?(c5uHG4ZI zsc>jP#5Y6w6Wj5!Y<hs+bU!o%27{ex{L}eAcpo{y03Z+uIIo>=0^oK*&D+R;Yh@ze z7vfi;q<Qcix+@`mxieE@%Hh|uvSI=oWth?&>FW{owiOfGqcB@XkwUZ0j?Km4{qjE- z6c!Z|O1!?5l~+^}tE#<g>*^aCo0?lZ$rLKBwT;dI+nLO(UEMvb-ad9elEWPw8Xg(t zx$y<#6T+{PQ@$ecjAT|iC%dxnP5yoH$I`OLFU5*drPiz>bidcu^@a^2v}rP3-`?4^ z?Cl>M-Z(n8ot*x$0~Z|;ku35!-qAHSQN*GM3tW8AN#VWJNrHQD+6qXfO_zB^6eFVU z<cf)?cxIBg&kt7{lseNC#imOygk%_3#B7GlPJ-i{Jkb5%0xi-Rl|0kmE@#Bi&~@km z=3+-8JFQeO(6Q9>OjzupAb0*`W8}<a38zcJed8@^j^=hNN3twNrKHx3=VLE8BVz_x ztHMH8|4hMPuWq{BC%Pqu+_xsF3r<(fW@Gg-as&bSc({K<4n7S|lnxI-ORQ80JbZ*> zQVeE5Djt<<RtxaXp0SAh9i51HD`jqU$fBR8MUx&V^Y)=-cDj0w7e+8^gapqgW1~l| z26;z{Y>a0+Owme6r2OGio7DoTWqkhGKj0`0*1-*<$#uL5YH*kC8Z>wpCvYO~asp;G r-~A;>$wp)vkltB=c_?k6Zw*FUgrbAm;sB08O9+}m=}H3OFd*zN8L+JA literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif new file mode 100644 index 0000000000000000000000000000000000000000..0b4cc3682a1c62b3583d83ad83b84fce14461ec3 GIT binary patch literal 84 zcmZ?wbh9u|<YM4s_{6~Q{`GSP28ON6=G?h*=KufyKsE&EfGCg}2WCYL24P2Ujb{oI gR`0dgdh|+Jsp#~nk2Ra-N!C4)I;{2Ajg!F|0C)f#UH||9 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css new file mode 100644 index 0000000..a50d4fc --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css @@ -0,0 +1,90 @@ +/* Clearlooks 2 */ + +/* Reset */ +.clearlooks2, .clearlooks2 div, .clearlooks2 span, .clearlooks2 a {vertical-align:baseline; text-align:left; position:absolute; border:0; padding:0; margin:0; background:transparent; font-family:Arial,Verdana; font-size:11px; color:#000; text-decoration:none; font-weight:normal; width:auto; height:auto; overflow:hidden; display:block} + +/* General */ +.clearlooks2 {position:absolute; direction:ltr} +.clearlooks2 .mceWrapper {position:static} +.mceEventBlocker {position:fixed; left:0; top:0; background:url(img/horizontal.gif) no-repeat 0 -75px; width:100%; height:100%} +.clearlooks2 .mcePlaceHolder {border:1px solid #000; background:#888; top:0; left:0; opacity:0.5; -ms-filter:'alpha(opacity=50)'; filter:alpha(opacity=50)} +.clearlooks2_modalBlocker {position:fixed; left:0; top:0; width:100%; height:100%; background:#FFF; opacity:0.6; -ms-filter:'alpha(opacity=60)'; filter:alpha(opacity=60); display:none} + +/* Top */ +.clearlooks2 .mceTop, .clearlooks2 .mceTop div {top:0; width:100%; height:23px} +.clearlooks2 .mceTop .mceLeft {width:6px; background:url(img/corners.gif)} +.clearlooks2 .mceTop .mceCenter {right:6px; width:100%; height:23px; background:url(img/horizontal.gif) 12px 0; clip:rect(auto auto auto 12px)} +.clearlooks2 .mceTop .mceRight {right:0; width:6px; height:23px; background:url(img/corners.gif) -12px 0} +.clearlooks2 .mceTop span {width:100%; text-align:center; vertical-align:middle; line-height:23px; font-weight:bold} +.clearlooks2 .mceFocus .mceTop .mceLeft {background:url(img/corners.gif) -6px 0} +.clearlooks2 .mceFocus .mceTop .mceCenter {background:url(img/horizontal.gif) 0 -23px} +.clearlooks2 .mceFocus .mceTop .mceRight {background:url(img/corners.gif) -18px 0} +.clearlooks2 .mceFocus .mceTop span {color:#FFF} + +/* Middle */ +.clearlooks2 .mceMiddle, .clearlooks2 .mceMiddle div {top:0} +.clearlooks2 .mceMiddle {width:100%; height:100%; clip:rect(23px auto auto auto)} +.clearlooks2 .mceMiddle .mceLeft {left:0; width:5px; height:100%; background:url(img/vertical.gif) -5px 0} +.clearlooks2 .mceMiddle span {top:23px; left:5px; width:100%; height:100%; background:#FFF} +.clearlooks2 .mceMiddle .mceRight {right:0; width:5px; height:100%; background:url(img/vertical.gif)} + +/* Bottom */ +.clearlooks2 .mceBottom, .clearlooks2 .mceBottom div {height:6px} +.clearlooks2 .mceBottom {left:0; bottom:0; width:100%} +.clearlooks2 .mceBottom div {top:0} +.clearlooks2 .mceBottom .mceLeft {left:0; width:5px; background:url(img/corners.gif) -34px -6px} +.clearlooks2 .mceBottom .mceCenter {left:5px; width:100%; background:url(img/horizontal.gif) 0 -46px} +.clearlooks2 .mceBottom .mceRight {right:0; width:5px; background: url(img/corners.gif) -34px 0} +.clearlooks2 .mceBottom span {display:none} +.clearlooks2 .mceStatusbar .mceBottom, .clearlooks2 .mceStatusbar .mceBottom div {height:23px} +.clearlooks2 .mceStatusbar .mceBottom .mceLeft {background:url(img/corners.gif) -29px 0} +.clearlooks2 .mceStatusbar .mceBottom .mceCenter {background:url(img/horizontal.gif) 0 -52px} +.clearlooks2 .mceStatusbar .mceBottom .mceRight {background:url(img/corners.gif) -24px 0} +.clearlooks2 .mceStatusbar .mceBottom span {display:block; left:7px; font-family:Arial, Verdana; font-size:11px; line-height:23px} + +/* Actions */ +.clearlooks2 a {width:29px; height:16px; top:3px;} +.clearlooks2 .mceClose {right:6px; background:url(img/buttons.gif) -87px 0} +.clearlooks2 .mceMin {display:none; right:68px; background:url(img/buttons.gif) 0 0} +.clearlooks2 .mceMed {display:none; right:37px; background:url(img/buttons.gif) -29px 0} +.clearlooks2 .mceMax {display:none; right:37px; background:url(img/buttons.gif) -58px 0} +.clearlooks2 .mceMove {display:none;width:100%;cursor:move;background:url(img/corners.gif) no-repeat -100px -100px} +.clearlooks2 .mceMovable .mceMove {display:block} +.clearlooks2 .mceFocus .mceClose {right:6px; background:url(img/buttons.gif) -87px -16px} +.clearlooks2 .mceFocus .mceMin {right:68px; background:url(img/buttons.gif) 0 -16px} +.clearlooks2 .mceFocus .mceMed {right:37px; background:url(img/buttons.gif) -29px -16px} +.clearlooks2 .mceFocus .mceMax {right:37px; background:url(img/buttons.gif) -58px -16px} +.clearlooks2 .mceFocus .mceClose:hover {right:6px; background:url(img/buttons.gif) -87px -32px} +.clearlooks2 .mceFocus .mceClose:hover {right:6px; background:url(img/buttons.gif) -87px -32px} +.clearlooks2 .mceFocus .mceMin:hover {right:68px; background:url(img/buttons.gif) 0 -32px} +.clearlooks2 .mceFocus .mceMed:hover {right:37px; background:url(img/buttons.gif) -29px -32px} +.clearlooks2 .mceFocus .mceMax:hover {right:37px; background:url(img/buttons.gif) -58px -32px} + +/* Resize */ +.clearlooks2 .mceResize {top:auto; left:auto; display:none; width:5px; height:5px; background:url(img/horizontal.gif) no-repeat 0 -75px} +.clearlooks2 .mceResizable .mceResize {display:block} +.clearlooks2 .mceResizable .mceMin, .clearlooks2 .mceMax {display:none} +.clearlooks2 .mceMinimizable .mceMin {display:block} +.clearlooks2 .mceMaximizable .mceMax {display:block} +.clearlooks2 .mceMaximized .mceMed {display:block} +.clearlooks2 .mceMaximized .mceMax {display:none} +.clearlooks2 a.mceResizeN {top:0; left:0; width:100%; cursor:n-resize} +.clearlooks2 a.mceResizeNW {top:0; left:0; cursor:nw-resize} +.clearlooks2 a.mceResizeNE {top:0; right:0; cursor:ne-resize} +.clearlooks2 a.mceResizeW {top:0; left:0; height:100%; cursor:w-resize;} +.clearlooks2 a.mceResizeE {top:0; right:0; height:100%; cursor:e-resize} +.clearlooks2 a.mceResizeS {bottom:0; left:0; width:100%; cursor:s-resize} +.clearlooks2 a.mceResizeSW {bottom:0; left:0; cursor:sw-resize} +.clearlooks2 a.mceResizeSE {bottom:0; right:0; cursor:se-resize} + +/* Alert/Confirm */ +.clearlooks2 .mceButton {font-weight:bold; bottom:10px; width:80px; height:30px; background:url(img/button.gif); line-height:30px; vertical-align:middle; text-align:center; outline:0} +.clearlooks2 .mceMiddle .mceIcon {left:15px; top:35px; width:32px; height:32px} +.clearlooks2 .mceAlert .mceMiddle span, .clearlooks2 .mceConfirm .mceMiddle span {background:transparent;left:60px; top:35px; width:320px; height:50px; font-weight:bold; overflow:auto; white-space:normal} +.clearlooks2 a:hover {font-weight:bold;} +.clearlooks2 .mceAlert .mceMiddle, .clearlooks2 .mceConfirm .mceMiddle {background:#D6D7D5} +.clearlooks2 .mceAlert .mceOk {left:50%; top:auto; margin-left: -40px} +.clearlooks2 .mceAlert .mceIcon {background:url(img/alert.gif)} +.clearlooks2 .mceConfirm .mceOk {left:50%; top:auto; margin-left: -90px} +.clearlooks2 .mceConfirm .mceCancel {left:50%; top:auto} +.clearlooks2 .mceConfirm .mceIcon {background:url(img/confirm.gif)} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/template.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/template.htm new file mode 100644 index 0000000..f9ec642 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/inlinepopups/template.htm @@ -0,0 +1,387 @@ +<!-- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> --> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Template for dialogs</title> +<link rel="stylesheet" type="text/css" href="skins/clearlooks2/window.css" /> +</head> +<body> + +<div class="mceEditor"> + <div class="clearlooks2" style="width:400px; height:100px; left:10px;"> + <div class="mceWrapper"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Blured</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:420px;"> + <div class="mceWrapper mceMovable mceFocus"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Focused</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:120px;"> + <div class="mceWrapper mceMovable mceFocus mceStatusbar"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:120px;"> + <div class="mceWrapper mceMovable mceFocus mceStatusbar mceResizable"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar, Resizable</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:230px;"> + <div class="mceWrapper mceMovable mceFocus mceResizable mceMaximizable"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Resizable, Maximizable</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:230px;"> + <div class="mceWrapper mceMovable mceStatusbar mceResizable mceMaximizable"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Blurred, Maximizable, Statusbar, Resizable</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:10px; top:340px;"> + <div class="mceWrapper mceMovable mceFocus mceResizable mceMaximized mceMinimizable mceMaximizable"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Maximized, Maximizable, Minimizable</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:100px; left:420px; top:340px;"> + <div class="mceWrapper mceMovable mceStatusbar mceResizable mceMaximized mceMinimizable mceMaximizable"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Blured</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span>Content</span> + <div class="mceRight"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Statusbar text.</span> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceMin" href="#"></a> + <a class="mceMax" href="#"></a> + <a class="mceMed" href="#"></a> + <a class="mceClose" href="#"></a> + <a class="mceResize mceResizeN" href="#"></a> + <a class="mceResize mceResizeS" href="#"></a> + <a class="mceResize mceResizeW" href="#"></a> + <a class="mceResize mceResizeE" href="#"></a> + <a class="mceResize mceResizeNW" href="#"></a> + <a class="mceResize mceResizeNE" href="#"></a> + <a class="mceResize mceResizeSW" href="#"></a> + <a class="mceResize mceResizeSE" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:130px; left:10px; top:450px;"> + <div class="mceWrapper mceMovable mceFocus mceModal mceAlert"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Alert</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span> + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + </span> + <div class="mceRight"></div> + <div class="mceIcon"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceButton mceOk" href="#">Ok</a> + <a class="mceClose" href="#"></a> + </div> + </div> + + <div class="clearlooks2" style="width:400px; height:130px; left:420px; top:450px;"> + <div class="mceWrapper mceMovable mceFocus mceModal mceConfirm"> + <div class="mceTop"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + <span>Confirm</span> + </div> + + <div class="mceMiddle"> + <div class="mceLeft"></div> + <span> + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + This is a very long error message. This is a very long error message. + </span> + <div class="mceRight"></div> + <div class="mceIcon"></div> + </div> + + <div class="mceBottom"> + <div class="mceLeft"></div> + <div class="mceCenter"></div> + <div class="mceRight"></div> + </div> + + <a class="mceMove" href="#"></a> + <a class="mceButton mceOk" href="#">Ok</a> + <a class="mceButton mceCancel" href="#">Cancel</a> + <a class="mceClose" href="#"></a> + </div> + </div> +</div> + +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/insertdatetime/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/insertdatetime/editor_plugin.js new file mode 100644 index 0000000..938ce6b --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/insertdatetime/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.InsertDateTime",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceInsertDate",function(){var d=c._getDateTime(new Date(),a.getParam("plugin_insertdate_dateFormat",a.getLang("insertdatetime.date_fmt")));a.execCommand("mceInsertContent",false,d)});a.addCommand("mceInsertTime",function(){var d=c._getDateTime(new Date(),a.getParam("plugin_insertdate_timeFormat",a.getLang("insertdatetime.time_fmt")));a.execCommand("mceInsertContent",false,d)});a.addButton("insertdate",{title:"insertdatetime.insertdate_desc",cmd:"mceInsertDate"});a.addButton("inserttime",{title:"insertdatetime.inserttime_desc",cmd:"mceInsertTime"})},getInfo:function(){return{longname:"Insert date/time",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/insertdatetime",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_getDateTime:function(e,a){var c=this.editor;function b(g,d){g=""+g;if(g.length<d){for(var f=0;f<(d-g.length);f++){g="0"+g}}return g}a=a.replace("%D","%m/%d/%y");a=a.replace("%r","%I:%M:%S %p");a=a.replace("%Y",""+e.getFullYear());a=a.replace("%y",""+e.getYear());a=a.replace("%m",b(e.getMonth()+1,2));a=a.replace("%d",b(e.getDate(),2));a=a.replace("%H",""+b(e.getHours(),2));a=a.replace("%M",""+b(e.getMinutes(),2));a=a.replace("%S",""+b(e.getSeconds(),2));a=a.replace("%I",""+((e.getHours()+11)%12+1));a=a.replace("%p",""+(e.getHours()<12?"AM":"PM"));a=a.replace("%B",""+c.getLang("insertdatetime.months_long").split(",")[e.getMonth()]);a=a.replace("%b",""+c.getLang("insertdatetime.months_short").split(",")[e.getMonth()]);a=a.replace("%A",""+c.getLang("insertdatetime.day_long").split(",")[e.getDay()]);a=a.replace("%a",""+c.getLang("insertdatetime.day_short").split(",")[e.getDay()]);a=a.replace("%%","%");return a}});tinymce.PluginManager.add("insertdatetime",tinymce.plugins.InsertDateTime)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/insertdatetime/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/insertdatetime/editor_plugin_src.js new file mode 100644 index 0000000..181c791 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/insertdatetime/editor_plugin_src.js @@ -0,0 +1,83 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.InsertDateTime', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + ed.addCommand('mceInsertDate', function() { + var str = t._getDateTime(new Date(), ed.getParam("plugin_insertdate_dateFormat", ed.getLang('insertdatetime.date_fmt'))); + + ed.execCommand('mceInsertContent', false, str); + }); + + ed.addCommand('mceInsertTime', function() { + var str = t._getDateTime(new Date(), ed.getParam("plugin_insertdate_timeFormat", ed.getLang('insertdatetime.time_fmt'))); + + ed.execCommand('mceInsertContent', false, str); + }); + + ed.addButton('insertdate', {title : 'insertdatetime.insertdate_desc', cmd : 'mceInsertDate'}); + ed.addButton('inserttime', {title : 'insertdatetime.inserttime_desc', cmd : 'mceInsertTime'}); + }, + + getInfo : function() { + return { + longname : 'Insert date/time', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/insertdatetime', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + _getDateTime : function(d, fmt) { + var ed = this.editor; + + function addZeros(value, len) { + value = "" + value; + + if (value.length < len) { + for (var i=0; i<(len-value.length); i++) + value = "0" + value; + } + + return value; + }; + + fmt = fmt.replace("%D", "%m/%d/%y"); + fmt = fmt.replace("%r", "%I:%M:%S %p"); + fmt = fmt.replace("%Y", "" + d.getFullYear()); + fmt = fmt.replace("%y", "" + d.getYear()); + fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2)); + fmt = fmt.replace("%d", addZeros(d.getDate(), 2)); + fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2)); + fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2)); + fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2)); + fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1)); + fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM")); + fmt = fmt.replace("%B", "" + ed.getLang("insertdatetime.months_long").split(',')[d.getMonth()]); + fmt = fmt.replace("%b", "" + ed.getLang("insertdatetime.months_short").split(',')[d.getMonth()]); + fmt = fmt.replace("%A", "" + ed.getLang("insertdatetime.day_long").split(',')[d.getDay()]); + fmt = fmt.replace("%a", "" + ed.getLang("insertdatetime.day_short").split(',')[d.getDay()]); + fmt = fmt.replace("%%", "%"); + + return fmt; + } + }); + + // Register plugin + tinymce.PluginManager.add('insertdatetime', tinymce.plugins.InsertDateTime); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/layer/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/layer/editor_plugin.js new file mode 100644 index 0000000..ca3857a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/layer/editor_plugin.js @@ -0,0 +1 @@ +(function(){function a(b){do{if(b.className&&b.className.indexOf("mceItemLayer")!=-1){return b}}while(b=b.parentNode)}tinymce.create("tinymce.plugins.Layer",{init:function(b,c){var d=this;d.editor=b;b.addCommand("mceInsertLayer",d._insertLayer,d);b.addCommand("mceMoveForward",function(){d._move(1)});b.addCommand("mceMoveBackward",function(){d._move(-1)});b.addCommand("mceMakeAbsolute",function(){d._toggleAbsolute()});b.addButton("moveforward",{title:"layer.forward_desc",cmd:"mceMoveForward"});b.addButton("movebackward",{title:"layer.backward_desc",cmd:"mceMoveBackward"});b.addButton("absolute",{title:"layer.absolute_desc",cmd:"mceMakeAbsolute"});b.addButton("insertlayer",{title:"layer.insertlayer_desc",cmd:"mceInsertLayer"});b.onInit.add(function(){var e=b.dom;if(tinymce.isIE){b.getDoc().execCommand("2D-Position",false,true)}});b.onMouseUp.add(function(f,h){var g=a(h.target);if(g){f.dom.setAttrib(g,"data-mce-style","")}});b.onMouseDown.add(function(f,j){var h=j.target,i=f.getDoc(),g;if(tinymce.isGecko){if(a(h)){if(i.designMode!=="on"){i.designMode="on";h=i.body;g=h.parentNode;g.removeChild(h);g.appendChild(h)}}else{if(i.designMode=="on"){i.designMode="off"}}}});b.onNodeChange.add(d._nodeChange,d);b.onVisualAid.add(d._visualAid,d)},getInfo:function(){return{longname:"Layer",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_nodeChange:function(c,b,f){var d,e;d=this._getParentLayer(f);e=c.dom.getParent(f,"DIV,P,IMG");if(!e){b.setDisabled("absolute",1);b.setDisabled("moveforward",1);b.setDisabled("movebackward",1)}else{b.setDisabled("absolute",0);b.setDisabled("moveforward",!d);b.setDisabled("movebackward",!d);b.setActive("absolute",d&&d.style.position.toLowerCase()=="absolute")}},_visualAid:function(b,d,c){var f=b.dom;tinymce.each(f.select("div,p",d),function(g){if(/^(absolute|relative|fixed)$/i.test(g.style.position)){if(c){f.addClass(g,"mceItemVisualAid")}else{f.removeClass(g,"mceItemVisualAid")}f.addClass(g,"mceItemLayer")}})},_move:function(j){var c=this.editor,g,h=[],f=this._getParentLayer(c.selection.getNode()),e=-1,k=-1,b;b=[];tinymce.walk(c.getBody(),function(d){if(d.nodeType==1&&/^(absolute|relative|static)$/i.test(d.style.position)){b.push(d)}},"childNodes");for(g=0;g<b.length;g++){h[g]=b[g].style.zIndex?parseInt(b[g].style.zIndex):0;if(e<0&&b[g]==f){e=g}}if(j<0){for(g=0;g<h.length;g++){if(h[g]<h[e]){k=g;break}}if(k>-1){b[e].style.zIndex=h[k];b[k].style.zIndex=h[e]}else{if(h[e]>0){b[e].style.zIndex=h[e]-1}}}else{for(g=0;g<h.length;g++){if(h[g]>h[e]){k=g;break}}if(k>-1){b[e].style.zIndex=h[k];b[k].style.zIndex=h[e]}else{b[e].style.zIndex=h[e]+1}}c.execCommand("mceRepaint")},_getParentLayer:function(b){return this.editor.dom.getParent(b,function(c){return c.nodeType==1&&/^(absolute|relative|static)$/i.test(c.style.position)})},_insertLayer:function(){var c=this.editor,e=c.dom,d=e.getPos(e.getParent(c.selection.getNode(),"*")),b=c.getBody();c.dom.add(b,"div",{style:{position:"absolute",left:d.x,top:(d.y>20?d.y:20),width:100,height:100},"class":"mceItemVisualAid mceItemLayer"},c.selection.getContent()||c.getLang("layer.content"));if(tinymce.isIE){e.setHTML(b,b.innerHTML)}},_toggleAbsolute:function(){var b=this.editor,c=this._getParentLayer(b.selection.getNode());if(!c){c=b.dom.getParent(b.selection.getNode(),"DIV,P,IMG")}if(c){if(c.style.position.toLowerCase()=="absolute"){b.dom.setStyles(c,{position:"",left:"",top:"",width:"",height:""});b.dom.removeClass(c,"mceItemVisualAid");b.dom.removeClass(c,"mceItemLayer")}else{if(c.style.left==""){c.style.left=20+"px"}if(c.style.top==""){c.style.top=20+"px"}if(c.style.width==""){c.style.width=c.width?(c.width+"px"):"100px"}if(c.style.height==""){c.style.height=c.height?(c.height+"px"):"100px"}c.style.position="absolute";b.dom.setAttrib(c,"data-mce-style","");b.addVisual(b.getBody())}b.execCommand("mceRepaint");b.nodeChanged()}}});tinymce.PluginManager.add("layer",tinymce.plugins.Layer)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/layer/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/layer/editor_plugin_src.js new file mode 100644 index 0000000..daed280 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/layer/editor_plugin_src.js @@ -0,0 +1,262 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + function findParentLayer(node) { + do { + if (node.className && node.className.indexOf('mceItemLayer') != -1) { + return node; + } + } while (node = node.parentNode); + }; + + tinymce.create('tinymce.plugins.Layer', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceInsertLayer', t._insertLayer, t); + + ed.addCommand('mceMoveForward', function() { + t._move(1); + }); + + ed.addCommand('mceMoveBackward', function() { + t._move(-1); + }); + + ed.addCommand('mceMakeAbsolute', function() { + t._toggleAbsolute(); + }); + + // Register buttons + ed.addButton('moveforward', {title : 'layer.forward_desc', cmd : 'mceMoveForward'}); + ed.addButton('movebackward', {title : 'layer.backward_desc', cmd : 'mceMoveBackward'}); + ed.addButton('absolute', {title : 'layer.absolute_desc', cmd : 'mceMakeAbsolute'}); + ed.addButton('insertlayer', {title : 'layer.insertlayer_desc', cmd : 'mceInsertLayer'}); + + ed.onInit.add(function() { + var dom = ed.dom; + + if (tinymce.isIE) + ed.getDoc().execCommand('2D-Position', false, true); + }); + + // Remove serialized styles when selecting a layer since it might be changed by a drag operation + ed.onMouseUp.add(function(ed, e) { + var layer = findParentLayer(e.target); + + if (layer) { + ed.dom.setAttrib(layer, 'data-mce-style', ''); + } + }); + + // Fixes edit focus issues with layers on Gecko + // This will enable designMode while inside a layer and disable it when outside + ed.onMouseDown.add(function(ed, e) { + var node = e.target, doc = ed.getDoc(), parent; + + if (tinymce.isGecko) { + if (findParentLayer(node)) { + if (doc.designMode !== 'on') { + doc.designMode = 'on'; + + // Repaint caret + node = doc.body; + parent = node.parentNode; + parent.removeChild(node); + parent.appendChild(node); + } + } else if (doc.designMode == 'on') { + doc.designMode = 'off'; + } + } + }); + + ed.onNodeChange.add(t._nodeChange, t); + ed.onVisualAid.add(t._visualAid, t); + }, + + getInfo : function() { + return { + longname : 'Layer', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + _nodeChange : function(ed, cm, n) { + var le, p; + + le = this._getParentLayer(n); + p = ed.dom.getParent(n, 'DIV,P,IMG'); + + if (!p) { + cm.setDisabled('absolute', 1); + cm.setDisabled('moveforward', 1); + cm.setDisabled('movebackward', 1); + } else { + cm.setDisabled('absolute', 0); + cm.setDisabled('moveforward', !le); + cm.setDisabled('movebackward', !le); + cm.setActive('absolute', le && le.style.position.toLowerCase() == "absolute"); + } + }, + + // Private methods + + _visualAid : function(ed, e, s) { + var dom = ed.dom; + + tinymce.each(dom.select('div,p', e), function(e) { + if (/^(absolute|relative|fixed)$/i.test(e.style.position)) { + if (s) + dom.addClass(e, 'mceItemVisualAid'); + else + dom.removeClass(e, 'mceItemVisualAid'); + + dom.addClass(e, 'mceItemLayer'); + } + }); + }, + + _move : function(d) { + var ed = this.editor, i, z = [], le = this._getParentLayer(ed.selection.getNode()), ci = -1, fi = -1, nl; + + nl = []; + tinymce.walk(ed.getBody(), function(n) { + if (n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position)) + nl.push(n); + }, 'childNodes'); + + // Find z-indexes + for (i=0; i<nl.length; i++) { + z[i] = nl[i].style.zIndex ? parseInt(nl[i].style.zIndex) : 0; + + if (ci < 0 && nl[i] == le) + ci = i; + } + + if (d < 0) { + // Move back + + // Try find a lower one + for (i=0; i<z.length; i++) { + if (z[i] < z[ci]) { + fi = i; + break; + } + } + + if (fi > -1) { + nl[ci].style.zIndex = z[fi]; + nl[fi].style.zIndex = z[ci]; + } else { + if (z[ci] > 0) + nl[ci].style.zIndex = z[ci] - 1; + } + } else { + // Move forward + + // Try find a higher one + for (i=0; i<z.length; i++) { + if (z[i] > z[ci]) { + fi = i; + break; + } + } + + if (fi > -1) { + nl[ci].style.zIndex = z[fi]; + nl[fi].style.zIndex = z[ci]; + } else + nl[ci].style.zIndex = z[ci] + 1; + } + + ed.execCommand('mceRepaint'); + }, + + _getParentLayer : function(n) { + return this.editor.dom.getParent(n, function(n) { + return n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position); + }); + }, + + _insertLayer : function() { + var ed = this.editor, dom = ed.dom, p = dom.getPos(dom.getParent(ed.selection.getNode(), '*')), body = ed.getBody(); + + ed.dom.add(body, 'div', { + style : { + position : 'absolute', + left : p.x, + top : (p.y > 20 ? p.y : 20), + width : 100, + height : 100 + }, + 'class' : 'mceItemVisualAid mceItemLayer' + }, ed.selection.getContent() || ed.getLang('layer.content')); + + // Workaround for IE where it messes up the JS engine if you insert a layer on IE 6,7 + if (tinymce.isIE) + dom.setHTML(body, body.innerHTML); + }, + + _toggleAbsolute : function() { + var ed = this.editor, le = this._getParentLayer(ed.selection.getNode()); + + if (!le) + le = ed.dom.getParent(ed.selection.getNode(), 'DIV,P,IMG'); + + if (le) { + if (le.style.position.toLowerCase() == "absolute") { + ed.dom.setStyles(le, { + position : '', + left : '', + top : '', + width : '', + height : '' + }); + + ed.dom.removeClass(le, 'mceItemVisualAid'); + ed.dom.removeClass(le, 'mceItemLayer'); + } else { + if (le.style.left == "") + le.style.left = 20 + 'px'; + + if (le.style.top == "") + le.style.top = 20 + 'px'; + + if (le.style.width == "") + le.style.width = le.width ? (le.width + 'px') : '100px'; + + if (le.style.height == "") + le.style.height = le.height ? (le.height + 'px') : '100px'; + + le.style.position = "absolute"; + + ed.dom.setAttrib(le, 'data-mce-style', ''); + ed.addVisual(ed.getBody()); + } + + ed.execCommand('mceRepaint'); + ed.nodeChanged(); + } + } + }); + + // Register plugin + tinymce.PluginManager.add('layer', tinymce.plugins.Layer); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/legacyoutput/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/legacyoutput/editor_plugin.js new file mode 100644 index 0000000..b3a4ce3 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/legacyoutput/editor_plugin.js @@ -0,0 +1 @@ +(function(a){a.onAddEditor.addToTop(function(c,b){b.settings.inline_styles=false});a.create("tinymce.plugins.LegacyOutput",{init:function(b){b.onInit.add(function(){var c="p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img",e=a.explode(b.settings.font_size_style_values),d=b.schema;b.formatter.register({alignleft:{selector:c,attributes:{align:"left"}},aligncenter:{selector:c,attributes:{align:"center"}},alignright:{selector:c,attributes:{align:"right"}},alignfull:{selector:c,attributes:{align:"justify"}},bold:[{inline:"b",remove:"all"},{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}}],italic:[{inline:"i",remove:"all"},{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}}],underline:[{inline:"u",remove:"all"},{inline:"span",styles:{textDecoration:"underline"},exact:true}],strikethrough:[{inline:"strike",remove:"all"},{inline:"span",styles:{textDecoration:"line-through"},exact:true}],fontname:{inline:"font",attributes:{face:"%value"}},fontsize:{inline:"font",attributes:{size:function(f){return a.inArray(e,f.value)+1}}},forecolor:{inline:"font",styles:{color:"%value"}},hilitecolor:{inline:"font",styles:{backgroundColor:"%value"}}});a.each("b,i,u,strike".split(","),function(f){d.addValidElements(f+"[*]")});if(!d.getElementRule("font")){d.addValidElements("font[face|size|color|style]")}a.each(c.split(","),function(f){var h=d.getElementRule(f),g;if(h){if(!h.attributes.align){h.attributes.align={};h.attributesOrder.push("align")}}});b.onNodeChange.add(function(g,k){var j,f,h,i;f=g.dom.getParent(g.selection.getNode(),"font");if(f){h=f.face;i=f.size}if(j=k.get("fontselect")){j.select(function(l){return l==h})}if(j=k.get("fontsizeselect")){j.select(function(m){var l=a.inArray(e,m.fontSize);return l+1==i})}})})},getInfo:function(){return{longname:"LegacyOutput",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/legacyoutput",version:a.majorVersion+"."+a.minorVersion}}});a.PluginManager.add("legacyoutput",a.plugins.LegacyOutput)})(tinymce); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/legacyoutput/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/legacyoutput/editor_plugin_src.js new file mode 100644 index 0000000..e627ec7 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/legacyoutput/editor_plugin_src.js @@ -0,0 +1,139 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + * + * This plugin will force TinyMCE to produce deprecated legacy output such as font elements, u elements, align + * attributes and so forth. There are a few cases where these old items might be needed for example in email applications or with Flash + * + * However you should NOT use this plugin if you are building some system that produces web contents such as a CMS. All these elements are + * not apart of the newer specifications for HTML and XHTML. + */ + +(function(tinymce) { + // Override inline_styles setting to force TinyMCE to produce deprecated contents + tinymce.onAddEditor.addToTop(function(tinymce, editor) { + editor.settings.inline_styles = false; + }); + + // Create the legacy ouput plugin + tinymce.create('tinymce.plugins.LegacyOutput', { + init : function(editor) { + editor.onInit.add(function() { + var alignElements = 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table,img', + fontSizes = tinymce.explode(editor.settings.font_size_style_values), + schema = editor.schema; + + // Override some internal formats to produce legacy elements and attributes + editor.formatter.register({ + // Change alignment formats to use the deprecated align attribute + alignleft : {selector : alignElements, attributes : {align : 'left'}}, + aligncenter : {selector : alignElements, attributes : {align : 'center'}}, + alignright : {selector : alignElements, attributes : {align : 'right'}}, + alignfull : {selector : alignElements, attributes : {align : 'justify'}}, + + // Change the basic formatting elements to use deprecated element types + bold : [ + {inline : 'b', remove : 'all'}, + {inline : 'strong', remove : 'all'}, + {inline : 'span', styles : {fontWeight : 'bold'}} + ], + italic : [ + {inline : 'i', remove : 'all'}, + {inline : 'em', remove : 'all'}, + {inline : 'span', styles : {fontStyle : 'italic'}} + ], + underline : [ + {inline : 'u', remove : 'all'}, + {inline : 'span', styles : {textDecoration : 'underline'}, exact : true} + ], + strikethrough : [ + {inline : 'strike', remove : 'all'}, + {inline : 'span', styles : {textDecoration: 'line-through'}, exact : true} + ], + + // Change font size and font family to use the deprecated font element + fontname : {inline : 'font', attributes : {face : '%value'}}, + fontsize : { + inline : 'font', + attributes : { + size : function(vars) { + return tinymce.inArray(fontSizes, vars.value) + 1; + } + } + }, + + // Setup font elements for colors as well + forecolor : {inline : 'font', styles : {color : '%value'}}, + hilitecolor : {inline : 'font', styles : {backgroundColor : '%value'}} + }); + + // Check that deprecated elements are allowed if not add them + tinymce.each('b,i,u,strike'.split(','), function(name) { + schema.addValidElements(name + '[*]'); + }); + + // Add font element if it's missing + if (!schema.getElementRule("font")) + schema.addValidElements("font[face|size|color|style]"); + + // Add the missing and depreacted align attribute for the serialization engine + tinymce.each(alignElements.split(','), function(name) { + var rule = schema.getElementRule(name), found; + + if (rule) { + if (!rule.attributes.align) { + rule.attributes.align = {}; + rule.attributesOrder.push('align'); + } + } + }); + + // Listen for the onNodeChange event so that we can do special logic for the font size and font name drop boxes + editor.onNodeChange.add(function(editor, control_manager) { + var control, fontElm, fontName, fontSize; + + // Find font element get it's name and size + fontElm = editor.dom.getParent(editor.selection.getNode(), 'font'); + if (fontElm) { + fontName = fontElm.face; + fontSize = fontElm.size; + } + + // Select/unselect the font name in droplist + if (control = control_manager.get('fontselect')) { + control.select(function(value) { + return value == fontName; + }); + } + + // Select/unselect the font size in droplist + if (control = control_manager.get('fontsizeselect')) { + control.select(function(value) { + var index = tinymce.inArray(fontSizes, value.fontSize); + + return index + 1 == fontSize; + }); + } + }); + }); + }, + + getInfo : function() { + return { + longname : 'LegacyOutput', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/legacyoutput', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('legacyoutput', tinymce.plugins.LegacyOutput); +})(tinymce); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/lists/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/lists/editor_plugin.js new file mode 100644 index 0000000..67308f0 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/lists/editor_plugin.js @@ -0,0 +1 @@ +(function(){var e=tinymce.each,r=tinymce.dom.Event,g;function p(t,s){while(t&&(t.nodeType===8||(t.nodeType===3&&/^[ \t\n\r]*$/.test(t.nodeValue)))){t=s(t)}return t}function b(s){return p(s,function(t){return t.previousSibling})}function i(s){return p(s,function(t){return t.nextSibling})}function d(s,u,t){return s.dom.getParent(u,function(v){return tinymce.inArray(t,v)!==-1})}function n(s){return s&&(s.tagName==="OL"||s.tagName==="UL")}function c(u,v){var t,w,s;t=b(u.lastChild);while(n(t)){w=t;t=b(w.previousSibling)}if(w){s=v.create("li",{style:"list-style-type: none;"});v.split(u,w);v.insertAfter(s,w);s.appendChild(w);s.appendChild(w);u=s.previousSibling}return u}function m(t,s,u){t=a(t,s,u);return o(t,s,u)}function a(u,s,v){var t=b(u.previousSibling);if(t){return h(t,u,s?t:false,v)}else{return u}}function o(u,t,v){var s=i(u.nextSibling);if(s){return h(u,s,t?s:false,v)}else{return u}}function h(u,s,t,v){if(l(u,s,!!t,v)){return f(u,s,t)}else{if(u&&u.tagName==="LI"&&n(s)){u.appendChild(s)}}return s}function l(u,t,s,v){if(!u||!t){return false}else{if(u.tagName==="LI"&&t.tagName==="LI"){return t.style.listStyleType==="none"||j(t)}else{if(n(u)){return(u.tagName===t.tagName&&(s||u.style.listStyleType===t.style.listStyleType))||q(t)}else{if(v&&u.tagName==="P"&&t.tagName==="P"){return true}else{return false}}}}}function q(t){var s=i(t.firstChild),u=b(t.lastChild);return s&&u&&n(t)&&s===u&&(n(s)||s.style.listStyleType==="none"||j(s))}function j(u){var t=i(u.firstChild),s=b(u.lastChild);return t&&s&&t===s&&n(t)}function f(w,v,s){var u=b(w.lastChild),t=i(v.firstChild);if(w.tagName==="P"){w.appendChild(w.ownerDocument.createElement("br"))}while(v.firstChild){w.appendChild(v.firstChild)}if(s){w.style.listStyleType=s.style.listStyleType}v.parentNode.removeChild(v);h(u,t,false);return w}function k(t,u){var s;if(!u.is(t,"li,ol,ul")){s=u.getParent(t,"li");if(s){t=s}}return t}tinymce.create("tinymce.plugins.Lists",{init:function(A,y){var w=0;var t=1;var H=2;var J=3;var z=J;function C(M){return M.keyCode===9&&(A.queryCommandState("InsertUnorderedList")||A.queryCommandState("InsertOrderedList"))}function x(){var M=B();var O=M.parentNode.parentNode;var N=M.parentNode.lastChild===M;return N&&!u(O)&&K(M)}function u(M){if(n(M)){return M.parentNode&&M.parentNode.tagName==="LI"}else{return M.tagName==="LI"}}function D(){return A.selection.isCollapsed()&&K(B())}function B(){var M=A.selection.getStart();return((M.tagName=="BR"||M.tagName=="")&&M.parentNode.tagName=="LI")?M.parentNode:M}function K(M){var N=M.childNodes.length;if(M.tagName==="LI"){return N==0?true:N==1&&(M.firstChild.tagName==""||F(M)||G(M))}return false}function F(M){return tinymce.isWebKit&&M.firstChild.nodeName=="BR"}function G(M){var N=tinymce.grep(M.parentNode.childNodes,function(Q){return Q.nodeName=="LI"});var O=M==N[N.length-1];var P=M.firstChild;return tinymce.isIE9&&O&&(P.nodeValue==String.fromCharCode(160)||P.nodeValue==String.fromCharCode(32))}function L(M){return M.keyCode===13}function I(M){if(C(M)){return w}else{if(L(M)&&x()){return H}else{if(L(M)&&D()){return t}else{return J}}}}function s(M,N){if(z==w||z==t){return r.cancel(N)}}function v(P,R){var U;if(!tinymce.isGecko){return}var N=P.selection.getStart();if(R.keyCode!=8||N.tagName!=="IMG"){return}function O(Y){var Z=Y.firstChild;var X=null;do{if(!Z){break}if(Z.tagName==="LI"){X=Z}}while(Z=Z.nextSibling);return X}function W(Y,X){while(Y.childNodes.length>0){X.appendChild(Y.childNodes[0])}}U=N.parentNode.previousSibling;if(!U){return}var S;if(U.tagName==="UL"||U.tagName==="OL"){S=U}else{if(U.previousSibling&&(U.previousSibling.tagName==="UL"||U.previousSibling.tagName==="OL")){S=U.previousSibling}else{return}}var V=O(S);var M=P.dom.createRng();M.setStart(V,1);M.setEnd(V,1);P.selection.setRng(M);P.selection.collapse(true);var Q=P.selection.getBookmark();var T=N.parentNode.cloneNode(true);if(T.tagName==="P"||T.tagName==="DIV"){W(T,V)}else{V.appendChild(T)}N.parentNode.parentNode.removeChild(N.parentNode);P.selection.moveToBookmark(Q)}function E(M){var N=A.dom.getParent(M,"ol,ul");if(N!=null){var O=N.lastChild;O.appendChild(A.getDoc().createElement(""));A.selection.setCursorLocation(O,0)}}this.ed=A;A.addCommand("Indent",this.indent,this);A.addCommand("Outdent",this.outdent,this);A.addCommand("InsertUnorderedList",function(){this.applyList("UL","OL")},this);A.addCommand("InsertOrderedList",function(){this.applyList("OL","UL")},this);A.onInit.add(function(){A.editorCommands.addCommands({outdent:function(){var N=A.selection,O=A.dom;function M(P){P=O.getParent(P,O.isBlock);return P&&(parseInt(A.dom.getStyle(P,"margin-left")||0,10)+parseInt(A.dom.getStyle(P,"padding-left")||0,10))>0}return M(N.getStart())||M(N.getEnd())||A.queryCommandState("InsertOrderedList")||A.queryCommandState("InsertUnorderedList")}},"state")});A.onKeyUp.add(function(N,O){if(z==w){N.execCommand(O.shiftKey?"Outdent":"Indent",true,null);z=J;return r.cancel(O)}else{if(z==t){var M=B();var Q=N.settings.list_outdent_on_enter===true||O.shiftKey;N.execCommand(Q?"Outdent":"Indent",true,null);if(tinymce.isIE){E(M)}return r.cancel(O)}else{if(z==H){if(tinymce.isIE8){var P=N.getDoc().createTextNode("\uFEFF");N.selection.getNode().appendChild(P)}else{if(tinymce.isIE9){N.execCommand("Outdent");return r.cancel(O)}}}}}});A.onKeyDown.add(function(M,N){z=I(N)});A.onKeyDown.add(s);A.onKeyDown.add(v);A.onKeyPress.add(s)},applyList:function(y,v){var C=this,z=C.ed,I=z.dom,s=[],H=false,u=false,w=false,B,G=z.selection.getSelectedBlocks();function E(t){if(t&&t.tagName==="BR"){I.remove(t)}}function F(M){var N=I.create(y),t;function L(O){if(O.style.marginLeft||O.style.paddingLeft){C.adjustPaddingFunction(false)(O)}}if(M.tagName==="LI"){}else{if(M.tagName==="P"||M.tagName==="DIV"||M.tagName==="BODY"){K(M,function(P,O,Q){J(P,O,M.tagName==="BODY"?null:P.parentNode);t=P.parentNode;L(t);E(O)});if(M.tagName==="P"||G.length>1){I.split(t.parentNode.parentNode,t.parentNode)}m(t.parentNode,true);return}else{t=I.create("li");I.insertAfter(t,M);t.appendChild(M);L(M);M=t}}I.insertAfter(N,M);N.appendChild(M);m(N,true);s.push(M)}function J(Q,L,O){var t,P=Q,N,M;while(!I.isBlock(Q.parentNode)&&Q.parentNode!==I.getRoot()){Q=I.split(Q.parentNode,Q.previousSibling);Q=Q.nextSibling;P=Q}if(O){t=O.cloneNode(true);Q.parentNode.insertBefore(t,Q);while(t.firstChild){I.remove(t.firstChild)}t=I.rename(t,"li")}else{t=I.create("li");Q.parentNode.insertBefore(t,Q)}while(P&&P!=L){N=P.nextSibling;t.appendChild(P);P=N}if(t.childNodes.length===0){t.innerHTML='<br _mce_bogus="1" />'}F(t)}function K(Q,T){var N,R,O=3,L=1,t="br,ul,ol,p,div,h1,h2,h3,h4,h5,h6,table,blockquote,address,pre,form,center,dl";function P(X,U){var V=I.createRng(),W;g.keep=true;z.selection.moveToBookmark(g);g.keep=false;W=z.selection.getRng(true);if(!U){U=X.parentNode.lastChild}V.setStartBefore(X);V.setEndAfter(U);return !(V.compareBoundaryPoints(O,W)>0||V.compareBoundaryPoints(L,W)<=0)}function S(U){if(U.nextSibling){return U.nextSibling}if(!I.isBlock(U.parentNode)&&U.parentNode!==I.getRoot()){return S(U.parentNode)}}N=Q.firstChild;var M=false;e(I.select(t,Q),function(V){var U;if(V.hasAttribute&&V.hasAttribute("_mce_bogus")){return true}if(P(N,V)){I.addClass(V,"_mce_tagged_br");N=S(V)}});M=(N&&P(N,undefined));N=Q.firstChild;e(I.select(t,Q),function(V){var U=S(V);if(V.hasAttribute&&V.hasAttribute("_mce_bogus")){return true}if(I.hasClass(V,"_mce_tagged_br")){T(N,V,R);R=null}else{R=V}N=U});if(M){T(N,undefined,R)}}function D(t){K(t,function(M,L,N){J(M,L);E(L);E(N)})}function A(t){if(tinymce.inArray(s,t)!==-1){return}if(t.parentNode.tagName===v){I.split(t.parentNode,t);F(t);o(t.parentNode,false)}s.push(t)}function x(M){var O,N,L,t;if(tinymce.inArray(s,M)!==-1){return}M=c(M,I);while(I.is(M.parentNode,"ol,ul,li")){I.split(M.parentNode,M)}s.push(M);M=I.rename(M,"p");L=m(M,false,z.settings.force_br_newlines);if(L===M){O=M.firstChild;while(O){if(I.isBlock(O)){O=I.split(O.parentNode,O);t=true;N=O.nextSibling&&O.nextSibling.firstChild}else{N=O.nextSibling;if(t&&O.tagName==="BR"){I.remove(O)}t=false}O=N}}}e(G,function(t){t=k(t,I);if(t.tagName===v||(t.tagName==="LI"&&t.parentNode.tagName===v)){u=true}else{if(t.tagName===y||(t.tagName==="LI"&&t.parentNode.tagName===y)){H=true}else{w=true}}});if(w||u||G.length===0){B={LI:A,H1:F,H2:F,H3:F,H4:F,H5:F,H6:F,P:F,BODY:F,DIV:G.length>1?F:D,defaultAction:D}}else{B={defaultAction:x}}this.process(B)},indent:function(){var u=this.ed,w=u.dom,x=[];function s(z){var y=w.create("li",{style:"list-style-type: none;"});w.insertAfter(y,z);return y}function t(B){var y=s(B),D=w.getParent(B,"ol,ul"),C=D.tagName,E=w.getStyle(D,"list-style-type"),A={},z;if(E!==""){A.style="list-style-type: "+E+";"}z=w.create(C,A);y.appendChild(z);return z}function v(z){if(!d(u,z,x)){z=c(z,w);var y=t(z);y.appendChild(z);m(y.parentNode,false);m(y,false);x.push(z)}}this.process({LI:v,defaultAction:this.adjustPaddingFunction(true)})},outdent:function(){var v=this,u=v.ed,w=u.dom,s=[];function x(t){var z,y,A;if(!d(u,t,s)){if(w.getStyle(t,"margin-left")!==""||w.getStyle(t,"padding-left")!==""){return v.adjustPaddingFunction(false)(t)}A=w.getStyle(t,"text-align",true);if(A==="center"||A==="right"){w.setStyle(t,"text-align","left");return}t=c(t,w);z=t.parentNode;y=t.parentNode.parentNode;if(y.tagName==="P"){w.split(y,t.parentNode)}else{w.split(z,t);if(y.tagName==="LI"){w.split(y,t)}else{if(!w.is(y,"ol,ul")){w.rename(t,"p")}}}s.push(t)}}this.process({LI:x,defaultAction:this.adjustPaddingFunction(false)});e(s,m)},process:function(y){var D=this,w=D.ed.selection,z=D.ed.dom,C,u;function x(s){z.removeClass(s,"_mce_act_on");if(!s||s.nodeType!==1){return}s=k(s,z);var t=y[s.tagName];if(!t){t=y.defaultAction}t(s)}function v(s){D.splitSafeEach(s.childNodes,x)}function B(s,t){return t>=0&&s.hasChildNodes()&&t<s.childNodes.length&&s.childNodes[t].tagName==="BR"}C=w.getSelectedBlocks();if(C.length===0){C=[z.getRoot()]}u=w.getRng(true);if(!u.collapsed){if(B(u.endContainer,u.endOffset-1)){u.setEnd(u.endContainer,u.endOffset-1);w.setRng(u)}if(B(u.startContainer,u.startOffset)){u.setStart(u.startContainer,u.startOffset+1);w.setRng(u)}}if(tinymce.isIE8){var E=D.ed.selection.getNode();if(E.tagName==="LI"&&!(E.parentNode.lastChild===E)){var A=D.ed.getDoc().createTextNode("\uFEFF");E.appendChild(A)}}g=w.getBookmark();y.OL=y.UL=v;D.splitSafeEach(C,x);w.moveToBookmark(g);g=null;D.ed.execCommand("mceRepaint")},splitSafeEach:function(t,s){if(tinymce.isGecko&&(/Firefox\/[12]\.[0-9]/.test(navigator.userAgent)||/Firefox\/3\.[0-4]/.test(navigator.userAgent))){this.classBasedEach(t,s)}else{e(t,s)}},classBasedEach:function(v,u){var w=this.ed.dom,s,t;e(v,function(x){w.addClass(x,"_mce_act_on")});s=w.select("._mce_act_on");while(s.length>0){t=s.shift();w.removeClass(t,"_mce_act_on");u(t);s=w.select("._mce_act_on")}},adjustPaddingFunction:function(u){var s,v,t=this.ed;s=t.settings.indentation;v=/[a-z%]+/i.exec(s);s=parseInt(s,10);return function(w){var y,x;y=parseInt(t.dom.getStyle(w,"margin-left")||0,10)+parseInt(t.dom.getStyle(w,"padding-left")||0,10);if(u){x=y+s}else{x=y-s}t.dom.setStyle(w,"padding-left","");t.dom.setStyle(w,"margin-left",x>0?x+v:"")}},getInfo:function(){return{longname:"Lists",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/lists",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("lists",tinymce.plugins.Lists)}()); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/lists/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/lists/editor_plugin_src.js new file mode 100644 index 0000000..1db29f7 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/lists/editor_plugin_src.js @@ -0,0 +1,781 @@ +/** + * editor_plugin_src.js + * + * Copyright 2011, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var each = tinymce.each, Event = tinymce.dom.Event, bookmark; + + // Skips text nodes that only contain whitespace since they aren't semantically important. + function skipWhitespaceNodes(e, next) { + while (e && (e.nodeType === 8 || (e.nodeType === 3 && /^[ \t\n\r]*$/.test(e.nodeValue)))) { + e = next(e); + } + return e; + } + + function skipWhitespaceNodesBackwards(e) { + return skipWhitespaceNodes(e, function(e) { + return e.previousSibling; + }); + } + + function skipWhitespaceNodesForwards(e) { + return skipWhitespaceNodes(e, function(e) { + return e.nextSibling; + }); + } + + function hasParentInList(ed, e, list) { + return ed.dom.getParent(e, function(p) { + return tinymce.inArray(list, p) !== -1; + }); + } + + function isList(e) { + return e && (e.tagName === 'OL' || e.tagName === 'UL'); + } + + function splitNestedLists(element, dom) { + var tmp, nested, wrapItem; + tmp = skipWhitespaceNodesBackwards(element.lastChild); + while (isList(tmp)) { + nested = tmp; + tmp = skipWhitespaceNodesBackwards(nested.previousSibling); + } + if (nested) { + wrapItem = dom.create('li', { style: 'list-style-type: none;'}); + dom.split(element, nested); + dom.insertAfter(wrapItem, nested); + wrapItem.appendChild(nested); + wrapItem.appendChild(nested); + element = wrapItem.previousSibling; + } + return element; + } + + function attemptMergeWithAdjacent(e, allowDifferentListStyles, mergeParagraphs) { + e = attemptMergeWithPrevious(e, allowDifferentListStyles, mergeParagraphs); + return attemptMergeWithNext(e, allowDifferentListStyles, mergeParagraphs); + } + + function attemptMergeWithPrevious(e, allowDifferentListStyles, mergeParagraphs) { + var prev = skipWhitespaceNodesBackwards(e.previousSibling); + if (prev) { + return attemptMerge(prev, e, allowDifferentListStyles ? prev : false, mergeParagraphs); + } else { + return e; + } + } + + function attemptMergeWithNext(e, allowDifferentListStyles, mergeParagraphs) { + var next = skipWhitespaceNodesForwards(e.nextSibling); + if (next) { + return attemptMerge(e, next, allowDifferentListStyles ? next : false, mergeParagraphs); + } else { + return e; + } + } + + function attemptMerge(e1, e2, differentStylesMasterElement, mergeParagraphs) { + if (canMerge(e1, e2, !!differentStylesMasterElement, mergeParagraphs)) { + return merge(e1, e2, differentStylesMasterElement); + } else if (e1 && e1.tagName === 'LI' && isList(e2)) { + // Fix invalidly nested lists. + e1.appendChild(e2); + } + return e2; + } + + function canMerge(e1, e2, allowDifferentListStyles, mergeParagraphs) { + if (!e1 || !e2) { + return false; + } else if (e1.tagName === 'LI' && e2.tagName === 'LI') { + return e2.style.listStyleType === 'none' || containsOnlyAList(e2); + } else if (isList(e1)) { + return (e1.tagName === e2.tagName && (allowDifferentListStyles || e1.style.listStyleType === e2.style.listStyleType)) || isListForIndent(e2); + } else if (mergeParagraphs && e1.tagName === 'P' && e2.tagName === 'P') { + return true; + } else { + return false; + } + } + + function isListForIndent(e) { + var firstLI = skipWhitespaceNodesForwards(e.firstChild), lastLI = skipWhitespaceNodesBackwards(e.lastChild); + return firstLI && lastLI && isList(e) && firstLI === lastLI && (isList(firstLI) || firstLI.style.listStyleType === 'none' || containsOnlyAList(firstLI)); + } + + function containsOnlyAList(e) { + var firstChild = skipWhitespaceNodesForwards(e.firstChild), lastChild = skipWhitespaceNodesBackwards(e.lastChild); + return firstChild && lastChild && firstChild === lastChild && isList(firstChild); + } + + function merge(e1, e2, masterElement) { + var lastOriginal = skipWhitespaceNodesBackwards(e1.lastChild), firstNew = skipWhitespaceNodesForwards(e2.firstChild); + if (e1.tagName === 'P') { + e1.appendChild(e1.ownerDocument.createElement('br')); + } + while (e2.firstChild) { + e1.appendChild(e2.firstChild); + } + if (masterElement) { + e1.style.listStyleType = masterElement.style.listStyleType; + } + e2.parentNode.removeChild(e2); + attemptMerge(lastOriginal, firstNew, false); + return e1; + } + + function findItemToOperateOn(e, dom) { + var item; + if (!dom.is(e, 'li,ol,ul')) { + item = dom.getParent(e, 'li'); + if (item) { + e = item; + } + } + return e; + } + + tinymce.create('tinymce.plugins.Lists', { + init: function(ed, url) { + var LIST_TABBING = 0; + var LIST_EMPTY_ITEM = 1; + var LIST_ESCAPE = 2; + var LIST_UNKNOWN = 3; + var state = LIST_UNKNOWN; + + function isTabInList(e) { + return e.keyCode === 9 && (ed.queryCommandState('InsertUnorderedList') || ed.queryCommandState('InsertOrderedList')); + } + + function isOnLastListItem() { + var li = getLi(); + var grandParent = li.parentNode.parentNode; + var isLastItem = li.parentNode.lastChild === li; + return isLastItem && !isNestedList(grandParent) && isEmptyListItem(li); + } + + function isNestedList(grandParent) { + if (isList(grandParent)) { + return grandParent.parentNode && grandParent.parentNode.tagName === 'LI'; + } else { + return grandParent.tagName === 'LI'; + } + } + + function isInEmptyListItem() { + return ed.selection.isCollapsed() && isEmptyListItem(getLi()); + } + + function getLi() { + var n = ed.selection.getStart(); + // Get start will return BR if the LI only contains a BR or an empty element as we use these to fix caret position + return ((n.tagName == 'BR' || n.tagName == '') && n.parentNode.tagName == 'LI') ? n.parentNode : n; + } + + function isEmptyListItem(li) { + var numChildren = li.childNodes.length; + if (li.tagName === 'LI') { + return numChildren == 0 ? true : numChildren == 1 && (li.firstChild.tagName == '' || isEmptyWebKitLi(li) || isEmptyIE9Li(li)); + } + return false; + } + + function isEmptyWebKitLi(li) { + // Check for empty LI or a LI with just a child that is a BR since Gecko and WebKit uses BR elements to place the caret + return tinymce.isWebKit && li.firstChild.nodeName == 'BR'; + } + + function isEmptyIE9Li(li) { + // only consider this to be last item if there is no list item content or that content is nbsp or space since IE9 creates these + var lis = tinymce.grep(li.parentNode.childNodes, function(n) {return n.nodeName == 'LI'}); + var isLastLi = li == lis[lis.length - 1]; + var child = li.firstChild; + return tinymce.isIE9 && isLastLi && (child.nodeValue == String.fromCharCode(160) || child.nodeValue == String.fromCharCode(32)); + } + + function isEnter(e) { + return e.keyCode === 13; + } + + function getListKeyState(e) { + if (isTabInList(e)) { + return LIST_TABBING; + } else if (isEnter(e) && isOnLastListItem()) { + return LIST_ESCAPE; + } else if (isEnter(e) && isInEmptyListItem()) { + return LIST_EMPTY_ITEM; + } else { + return LIST_UNKNOWN; + } + } + + function cancelEnterAndTab(_, e) { + if (state == LIST_TABBING || state == LIST_EMPTY_ITEM) { + return Event.cancel(e); + } + } + + function imageJoiningListItem(ed, e) { + var prevSibling; + + if (!tinymce.isGecko) + return; + + var n = ed.selection.getStart(); + if (e.keyCode != 8 || n.tagName !== 'IMG') + return; + + function lastLI(node) { + var child = node.firstChild; + var li = null; + do { + if (!child) + break; + + if (child.tagName === 'LI') + li = child; + } while (child = child.nextSibling); + + return li; + } + + function addChildren(parentNode, destination) { + while (parentNode.childNodes.length > 0) + destination.appendChild(parentNode.childNodes[0]); + } + + // Check if there is a previous sibling + prevSibling = n.parentNode.previousSibling; + if (!prevSibling) + return; + + var ul; + if (prevSibling.tagName === 'UL' || prevSibling.tagName === 'OL') + ul = prevSibling; + else if (prevSibling.previousSibling && (prevSibling.previousSibling.tagName === 'UL' || prevSibling.previousSibling.tagName === 'OL')) + ul = prevSibling.previousSibling; + else + return; + + var li = lastLI(ul); + + // move the caret to the end of the list item + var rng = ed.dom.createRng(); + rng.setStart(li, 1); + rng.setEnd(li, 1); + ed.selection.setRng(rng); + ed.selection.collapse(true); + + // save a bookmark at the end of the list item + var bookmark = ed.selection.getBookmark(); + + // copy the image an its text to the list item + var clone = n.parentNode.cloneNode(true); + if (clone.tagName === 'P' || clone.tagName === 'DIV') + addChildren(clone, li); + else + li.appendChild(clone); + + // remove the old copy of the image + n.parentNode.parentNode.removeChild(n.parentNode); + + // move the caret where we saved the bookmark + ed.selection.moveToBookmark(bookmark); + } + + // fix the cursor position to ensure it is correct in IE + function setCursorPositionToOriginalLi(li) { + var list = ed.dom.getParent(li, 'ol,ul'); + if (list != null) { + var lastLi = list.lastChild; + lastLi.appendChild(ed.getDoc().createElement('')); + ed.selection.setCursorLocation(lastLi, 0); + } + } + + this.ed = ed; + ed.addCommand('Indent', this.indent, this); + ed.addCommand('Outdent', this.outdent, this); + ed.addCommand('InsertUnorderedList', function() { + this.applyList('UL', 'OL'); + }, this); + ed.addCommand('InsertOrderedList', function() { + this.applyList('OL', 'UL'); + }, this); + + ed.onInit.add(function() { + ed.editorCommands.addCommands({ + 'outdent': function() { + var sel = ed.selection, dom = ed.dom; + + function hasStyleIndent(n) { + n = dom.getParent(n, dom.isBlock); + return n && (parseInt(ed.dom.getStyle(n, 'margin-left') || 0, 10) + parseInt(ed.dom.getStyle(n, 'padding-left') || 0, 10)) > 0; + } + + return hasStyleIndent(sel.getStart()) || hasStyleIndent(sel.getEnd()) || ed.queryCommandState('InsertOrderedList') || ed.queryCommandState('InsertUnorderedList'); + } + }, 'state'); + }); + + ed.onKeyUp.add(function(ed, e) { + if (state == LIST_TABBING) { + ed.execCommand(e.shiftKey ? 'Outdent' : 'Indent', true, null); + state = LIST_UNKNOWN; + return Event.cancel(e); + } else if (state == LIST_EMPTY_ITEM) { + var li = getLi(); + var shouldOutdent = ed.settings.list_outdent_on_enter === true || e.shiftKey; + ed.execCommand(shouldOutdent ? 'Outdent' : 'Indent', true, null); + if (tinymce.isIE) { + setCursorPositionToOriginalLi(li); + } + return Event.cancel(e); + } else if (state == LIST_ESCAPE) { + if (tinymce.isIE8) { + // append a zero sized nbsp so that caret is positioned correctly in IE8 after escaping and applying formatting. + // if there is no text then applying formatting for e.g a H1 to the P tag immediately following list after + // escaping from it will cause the caret to be positioned on the last li instead of staying the in P tag. + var n = ed.getDoc().createTextNode('\uFEFF'); + ed.selection.getNode().appendChild(n); + } else if (tinymce.isIE9) { + // IE9 does not escape the list so we use outdent to do this and cancel the default behaviour + ed.execCommand('Outdent'); + return Event.cancel(e); + } + } + }); + ed.onKeyDown.add(function(_, e) { state = getListKeyState(e); }); + ed.onKeyDown.add(cancelEnterAndTab); + ed.onKeyDown.add(imageJoiningListItem); + ed.onKeyPress.add(cancelEnterAndTab); + }, + + applyList: function(targetListType, oppositeListType) { + var t = this, ed = t.ed, dom = ed.dom, applied = [], hasSameType = false, hasOppositeType = false, hasNonList = false, actions, + selectedBlocks = ed.selection.getSelectedBlocks(); + + function cleanupBr(e) { + if (e && e.tagName === 'BR') { + dom.remove(e); + } + } + + function makeList(element) { + var list = dom.create(targetListType), li; + + function adjustIndentForNewList(element) { + // If there's a margin-left, outdent one level to account for the extra list margin. + if (element.style.marginLeft || element.style.paddingLeft) { + t.adjustPaddingFunction(false)(element); + } + } + + if (element.tagName === 'LI') { + // No change required. + } else if (element.tagName === 'P' || element.tagName === 'DIV' || element.tagName === 'BODY') { + processBrs(element, function(startSection, br, previousBR) { + doWrapList(startSection, br, element.tagName === 'BODY' ? null : startSection.parentNode); + li = startSection.parentNode; + adjustIndentForNewList(li); + cleanupBr(br); + }); + if (element.tagName === 'P' || selectedBlocks.length > 1) { + dom.split(li.parentNode.parentNode, li.parentNode); + } + attemptMergeWithAdjacent(li.parentNode, true); + return; + } else { + // Put the list around the element. + li = dom.create('li'); + dom.insertAfter(li, element); + li.appendChild(element); + adjustIndentForNewList(element); + element = li; + } + dom.insertAfter(list, element); + list.appendChild(element); + attemptMergeWithAdjacent(list, true); + applied.push(element); + } + + function doWrapList(start, end, template) { + var li, n = start, tmp, i; + while (!dom.isBlock(start.parentNode) && start.parentNode !== dom.getRoot()) { + start = dom.split(start.parentNode, start.previousSibling); + start = start.nextSibling; + n = start; + } + if (template) { + li = template.cloneNode(true); + start.parentNode.insertBefore(li, start); + while (li.firstChild) dom.remove(li.firstChild); + li = dom.rename(li, 'li'); + } else { + li = dom.create('li'); + start.parentNode.insertBefore(li, start); + } + while (n && n != end) { + tmp = n.nextSibling; + li.appendChild(n); + n = tmp; + } + if (li.childNodes.length === 0) { + li.innerHTML = '<br _mce_bogus="1" />'; + } + makeList(li); + } + + function processBrs(element, callback) { + var startSection, previousBR, END_TO_START = 3, START_TO_END = 1, + breakElements = 'br,ul,ol,p,div,h1,h2,h3,h4,h5,h6,table,blockquote,address,pre,form,center,dl'; + + function isAnyPartSelected(start, end) { + var r = dom.createRng(), sel; + bookmark.keep = true; + ed.selection.moveToBookmark(bookmark); + bookmark.keep = false; + sel = ed.selection.getRng(true); + if (!end) { + end = start.parentNode.lastChild; + } + r.setStartBefore(start); + r.setEndAfter(end); + return !(r.compareBoundaryPoints(END_TO_START, sel) > 0 || r.compareBoundaryPoints(START_TO_END, sel) <= 0); + } + + function nextLeaf(br) { + if (br.nextSibling) + return br.nextSibling; + if (!dom.isBlock(br.parentNode) && br.parentNode !== dom.getRoot()) + return nextLeaf(br.parentNode); + } + + // Split on BRs within the range and process those. + startSection = element.firstChild; + // First mark the BRs that have any part of the previous section selected. + var trailingContentSelected = false; + each(dom.select(breakElements, element), function(br) { + var b; + if (br.hasAttribute && br.hasAttribute('_mce_bogus')) { + return true; // Skip the bogus Brs that are put in to appease Firefox and Safari. + } + if (isAnyPartSelected(startSection, br)) { + dom.addClass(br, '_mce_tagged_br'); + startSection = nextLeaf(br); + } + }); + trailingContentSelected = (startSection && isAnyPartSelected(startSection, undefined)); + startSection = element.firstChild; + each(dom.select(breakElements, element), function(br) { + // Got a section from start to br. + var tmp = nextLeaf(br); + if (br.hasAttribute && br.hasAttribute('_mce_bogus')) { + return true; // Skip the bogus Brs that are put in to appease Firefox and Safari. + } + if (dom.hasClass(br, '_mce_tagged_br')) { + callback(startSection, br, previousBR); + previousBR = null; + } else { + previousBR = br; + } + startSection = tmp; + }); + if (trailingContentSelected) { + callback(startSection, undefined, previousBR); + } + } + + function wrapList(element) { + processBrs(element, function(startSection, br, previousBR) { + // Need to indent this part + doWrapList(startSection, br); + cleanupBr(br); + cleanupBr(previousBR); + }); + } + + function changeList(element) { + if (tinymce.inArray(applied, element) !== -1) { + return; + } + if (element.parentNode.tagName === oppositeListType) { + dom.split(element.parentNode, element); + makeList(element); + attemptMergeWithNext(element.parentNode, false); + } + applied.push(element); + } + + function convertListItemToParagraph(element) { + var child, nextChild, mergedElement, splitLast; + if (tinymce.inArray(applied, element) !== -1) { + return; + } + element = splitNestedLists(element, dom); + while (dom.is(element.parentNode, 'ol,ul,li')) { + dom.split(element.parentNode, element); + } + // Push the original element we have from the selection, not the renamed one. + applied.push(element); + element = dom.rename(element, 'p'); + mergedElement = attemptMergeWithAdjacent(element, false, ed.settings.force_br_newlines); + if (mergedElement === element) { + // Now split out any block elements that can't be contained within a P. + // Manually iterate to ensure we handle modifications correctly (doesn't work with tinymce.each) + child = element.firstChild; + while (child) { + if (dom.isBlock(child)) { + child = dom.split(child.parentNode, child); + splitLast = true; + nextChild = child.nextSibling && child.nextSibling.firstChild; + } else { + nextChild = child.nextSibling; + if (splitLast && child.tagName === 'BR') { + dom.remove(child); + } + splitLast = false; + } + child = nextChild; + } + } + } + + each(selectedBlocks, function(e) { + e = findItemToOperateOn(e, dom); + if (e.tagName === oppositeListType || (e.tagName === 'LI' && e.parentNode.tagName === oppositeListType)) { + hasOppositeType = true; + } else if (e.tagName === targetListType || (e.tagName === 'LI' && e.parentNode.tagName === targetListType)) { + hasSameType = true; + } else { + hasNonList = true; + } + }); + + if (hasNonList || hasOppositeType || selectedBlocks.length === 0) { + actions = { + 'LI': changeList, + 'H1': makeList, + 'H2': makeList, + 'H3': makeList, + 'H4': makeList, + 'H5': makeList, + 'H6': makeList, + 'P': makeList, + 'BODY': makeList, + 'DIV': selectedBlocks.length > 1 ? makeList : wrapList, + defaultAction: wrapList + }; + } else { + actions = { + defaultAction: convertListItemToParagraph + }; + } + this.process(actions); + }, + + indent: function() { + var ed = this.ed, dom = ed.dom, indented = []; + + function createWrapItem(element) { + var wrapItem = dom.create('li', { style: 'list-style-type: none;'}); + dom.insertAfter(wrapItem, element); + return wrapItem; + } + + function createWrapList(element) { + var wrapItem = createWrapItem(element), + list = dom.getParent(element, 'ol,ul'), + listType = list.tagName, + listStyle = dom.getStyle(list, 'list-style-type'), + attrs = {}, + wrapList; + if (listStyle !== '') { + attrs.style = 'list-style-type: ' + listStyle + ';'; + } + wrapList = dom.create(listType, attrs); + wrapItem.appendChild(wrapList); + return wrapList; + } + + function indentLI(element) { + if (!hasParentInList(ed, element, indented)) { + element = splitNestedLists(element, dom); + var wrapList = createWrapList(element); + wrapList.appendChild(element); + attemptMergeWithAdjacent(wrapList.parentNode, false); + attemptMergeWithAdjacent(wrapList, false); + indented.push(element); + } + } + + this.process({ + 'LI': indentLI, + defaultAction: this.adjustPaddingFunction(true) + }); + + }, + + outdent: function() { + var t = this, ed = t.ed, dom = ed.dom, outdented = []; + + function outdentLI(element) { + var listElement, targetParent, align; + if (!hasParentInList(ed, element, outdented)) { + if (dom.getStyle(element, 'margin-left') !== '' || dom.getStyle(element, 'padding-left') !== '') { + return t.adjustPaddingFunction(false)(element); + } + align = dom.getStyle(element, 'text-align', true); + if (align === 'center' || align === 'right') { + dom.setStyle(element, 'text-align', 'left'); + return; + } + element = splitNestedLists(element, dom); + listElement = element.parentNode; + targetParent = element.parentNode.parentNode; + if (targetParent.tagName === 'P') { + dom.split(targetParent, element.parentNode); + } else { + dom.split(listElement, element); + if (targetParent.tagName === 'LI') { + // Nested list, need to split the LI and go back out to the OL/UL element. + dom.split(targetParent, element); + } else if (!dom.is(targetParent, 'ol,ul')) { + dom.rename(element, 'p'); + } + } + outdented.push(element); + } + } + + this.process({ + 'LI': outdentLI, + defaultAction: this.adjustPaddingFunction(false) + }); + + each(outdented, attemptMergeWithAdjacent); + }, + + process: function(actions) { + var t = this, sel = t.ed.selection, dom = t.ed.dom, selectedBlocks, r; + + function processElement(element) { + dom.removeClass(element, '_mce_act_on'); + if (!element || element.nodeType !== 1) { + return; + } + element = findItemToOperateOn(element, dom); + var action = actions[element.tagName]; + if (!action) { + action = actions.defaultAction; + } + action(element); + } + + function recurse(element) { + t.splitSafeEach(element.childNodes, processElement); + } + + function brAtEdgeOfSelection(container, offset) { + return offset >= 0 && container.hasChildNodes() && offset < container.childNodes.length && + container.childNodes[offset].tagName === 'BR'; + } + + selectedBlocks = sel.getSelectedBlocks(); + if (selectedBlocks.length === 0) { + selectedBlocks = [ dom.getRoot() ]; + } + + r = sel.getRng(true); + if (!r.collapsed) { + if (brAtEdgeOfSelection(r.endContainer, r.endOffset - 1)) { + r.setEnd(r.endContainer, r.endOffset - 1); + sel.setRng(r); + } + if (brAtEdgeOfSelection(r.startContainer, r.startOffset)) { + r.setStart(r.startContainer, r.startOffset + 1); + sel.setRng(r); + } + } + + + if (tinymce.isIE8) { + // append a zero sized nbsp so that caret is restored correctly using bookmark + var s = t.ed.selection.getNode(); + if (s.tagName === 'LI' && !(s.parentNode.lastChild === s)) { + var i = t.ed.getDoc().createTextNode('\uFEFF'); + s.appendChild(i); + } + } + + bookmark = sel.getBookmark(); + actions.OL = actions.UL = recurse; + t.splitSafeEach(selectedBlocks, processElement); + sel.moveToBookmark(bookmark); + bookmark = null; + // Avoids table or image handles being left behind in Firefox. + t.ed.execCommand('mceRepaint'); + }, + + splitSafeEach: function(elements, f) { + if (tinymce.isGecko && (/Firefox\/[12]\.[0-9]/.test(navigator.userAgent) || + /Firefox\/3\.[0-4]/.test(navigator.userAgent))) { + this.classBasedEach(elements, f); + } else { + each(elements, f); + } + }, + + classBasedEach: function(elements, f) { + var dom = this.ed.dom, nodes, element; + // Mark nodes + each(elements, function(element) { + dom.addClass(element, '_mce_act_on'); + }); + nodes = dom.select('._mce_act_on'); + while (nodes.length > 0) { + element = nodes.shift(); + dom.removeClass(element, '_mce_act_on'); + f(element); + nodes = dom.select('._mce_act_on'); + } + }, + + adjustPaddingFunction: function(isIndent) { + var indentAmount, indentUnits, ed = this.ed; + indentAmount = ed.settings.indentation; + indentUnits = /[a-z%]+/i.exec(indentAmount); + indentAmount = parseInt(indentAmount, 10); + return function(element) { + var currentIndent, newIndentAmount; + currentIndent = parseInt(ed.dom.getStyle(element, 'margin-left') || 0, 10) + parseInt(ed.dom.getStyle(element, 'padding-left') || 0, 10); + if (isIndent) { + newIndentAmount = currentIndent + indentAmount; + } else { + newIndentAmount = currentIndent - indentAmount; + } + ed.dom.setStyle(element, 'padding-left', ''); + ed.dom.setStyle(element, 'margin-left', newIndentAmount > 0 ? newIndentAmount + indentUnits : ''); + }; + }, + + getInfo: function() { + return { + longname : 'Lists', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/lists', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + tinymce.PluginManager.add("lists", tinymce.plugins.Lists); +}()); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/media/css/media.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/css/media.css new file mode 100644 index 0000000..0c45c7f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/css/media.css @@ -0,0 +1,17 @@ +#id, #name, #hspace, #vspace, #class_name, #align { width: 100px } +#hspace, #vspace { width: 50px } +#flash_quality, #flash_align, #flash_scale, #flash_salign, #flash_wmode { width: 100px } +#flash_base, #flash_flashvars, #html5_altsource1, #html5_altsource2, #html5_poster { width: 240px } +#width, #height { width: 40px } +#src, #media_type { width: 250px } +#class { width: 120px } +#prev { margin: 0; border: 1px solid black; width: 380px; height: 260px; overflow: auto } +.panel_wrapper div.current { height: 420px; overflow: auto } +#flash_options, #shockwave_options, #qt_options, #wmp_options, #rmp_options { display: none } +.mceAddSelectValue { background-color: #DDDDDD } +#qt_starttime, #qt_endtime, #qt_fov, #qt_href, #qt_moveid, #qt_moviename, #qt_node, #qt_pan, #qt_qtsrc, #qt_qtsrcchokespeed, #qt_target, #qt_tilt, #qt_urlsubstituten, #qt_volume { width: 70px } +#wmp_balance, #wmp_baseurl, #wmp_captioningid, #wmp_currentmarker, #wmp_currentposition, #wmp_defaultframe, #wmp_playcount, #wmp_rate, #wmp_uimode, #wmp_volume { width: 70px } +#rmp_console, #rmp_numloop, #rmp_controls, #rmp_scriptcallbacks { width: 70px } +#shockwave_swvolume, #shockwave_swframe, #shockwave_swurl, #shockwave_swstretchvalign, #shockwave_swstretchhalign, #shockwave_swstretchstyle { width: 90px } +#qt_qtsrc { width: 200px } +iframe {border: 1px solid gray} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/media/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/editor_plugin.js new file mode 100644 index 0000000..37b4320 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/editor_plugin.js @@ -0,0 +1 @@ +(function(){var d=tinymce.explode("id,name,width,height,style,align,class,hspace,vspace,bgcolor,type"),h=tinymce.makeMap(d.join(",")),b=tinymce.html.Node,f,a,g=tinymce.util.JSON,e;f=[["Flash","d27cdb6e-ae6d-11cf-96b8-444553540000","application/x-shockwave-flash","http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"],["ShockWave","166b1bca-3f9c-11cf-8075-444553540000","application/x-director","http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0"],["WindowsMedia","6bf52a52-394a-11d3-b153-00c04f79faa6,22d6f312-b0f6-11d0-94ab-0080c74c7e95,05589fa1-c356-11ce-bf01-00aa0055595a","application/x-mplayer2","http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701"],["QuickTime","02bf25d5-8c17-4b23-bc80-d3488abddc6b","video/quicktime","http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0"],["RealMedia","cfcdaa03-8be4-11cf-b84b-0020afbbccfa","audio/x-pn-realaudio-plugin","http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"],["Java","8ad9c840-044e-11d1-b3e9-00805f499d93","application/x-java-applet","http://java.sun.com/products/plugin/autodl/jinstall-1_5_0-windows-i586.cab#Version=1,5,0,0"],["Silverlight","dfeaf541-f3e1-4c24-acac-99c30715084a","application/x-silverlight-2"],["Iframe"],["Video"],["EmbeddedAudio"],["Audio"]];function c(m){var l,j,k;if(m&&!m.splice){j=[];for(k=0;true;k++){if(m[k]){j[k]=m[k]}else{break}}return j}return m}tinymce.create("tinymce.plugins.MediaPlugin",{init:function(n,j){var r=this,l={},m,p,q,k;function o(i){return i&&i.nodeName==="IMG"&&n.dom.hasClass(i,"mceItemMedia")}r.editor=n;r.url=j;a="";for(m=0;m<f.length;m++){k=f[m][0];q={name:k,clsids:tinymce.explode(f[m][1]||""),mimes:tinymce.explode(f[m][2]||""),codebase:f[m][3]};for(p=0;p<q.clsids.length;p++){l["clsid:"+q.clsids[p]]=q}for(p=0;p<q.mimes.length;p++){l[q.mimes[p]]=q}l["mceItem"+k]=q;l[k.toLowerCase()]=q;a+=(a?"|":"")+k}tinymce.each(n.getParam("media_types","video=mp4,m4v,ogv,webm;silverlight=xap;flash=swf,flv;shockwave=dcr;quicktime=mov,qt,mpg,mpeg;shockwave=dcr;windowsmedia=avi,wmv,wm,asf,asx,wmx,wvx;realmedia=rm,ra,ram;java=jar;audio=mp3,ogg").split(";"),function(v){var s,u,t;v=v.split(/=/);u=tinymce.explode(v[1].toLowerCase());for(s=0;s<u.length;s++){t=l[v[0].toLowerCase()];if(t){l[u[s]]=t}}});a=new RegExp("write("+a+")\\(([^)]+)\\)");r.lookup=l;n.onPreInit.add(function(){n.schema.addValidElements("object[id|style|width|height|classid|codebase|*],param[name|value],embed[id|style|width|height|type|src|*],video[*],audio[*],source[*]");n.parser.addNodeFilter("object,embed,video,audio,script,iframe",function(s){var t=s.length;while(t--){r.objectToImg(s[t])}});n.serializer.addNodeFilter("img",function(s,u,t){var v=s.length,w;while(v--){w=s[v];if((w.attr("class")||"").indexOf("mceItemMedia")!==-1){r.imgToObject(w,t)}}})});n.onInit.add(function(){if(n.theme&&n.theme.onResolveName){n.theme.onResolveName.add(function(i,s){if(s.name==="img"&&n.dom.hasClass(s.node,"mceItemMedia")){s.name="media"}})}if(n&&n.plugins.contextmenu){n.plugins.contextmenu.onContextMenu.add(function(s,t,i){if(i.nodeName==="IMG"&&i.className.indexOf("mceItemMedia")!==-1){t.add({title:"media.edit",icon:"media",cmd:"mceMedia"})}})}});n.addCommand("mceMedia",function(){var s,i;i=n.selection.getNode();if(o(i)){s=n.dom.getAttrib(i,"data-mce-json");if(s){s=g.parse(s);tinymce.each(d,function(t){var u=n.dom.getAttrib(i,t);if(u){s[t]=u}});s.type=r.getType(i.className).name.toLowerCase()}}if(!s){s={type:"flash",video:{sources:[]},params:{}}}n.windowManager.open({file:j+"/media.htm",width:430+parseInt(n.getLang("media.delta_width",0)),height:500+parseInt(n.getLang("media.delta_height",0)),inline:1},{plugin_url:j,data:s})});n.addButton("media",{title:"media.desc",cmd:"mceMedia"});n.onNodeChange.add(function(s,i,t){i.setActive("media",o(t))})},convertUrl:function(k,n){var j=this,m=j.editor,l=m.settings,o=l.url_converter,i=l.url_converter_scope||j;if(!k){return k}if(n){return m.documentBaseURI.toAbsolute(k)}return o.call(i,k,"src","object")},getInfo:function(){return{longname:"Media",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media",version:tinymce.majorVersion+"."+tinymce.minorVersion}},dataToImg:function(m,k){var r=this,o=r.editor,p=o.documentBaseURI,j,q,n,l;m.params.src=r.convertUrl(m.params.src,k);q=m.video.attrs;if(q){q.src=r.convertUrl(q.src,k)}if(q){q.poster=r.convertUrl(q.poster,k)}j=c(m.video.sources);if(j){for(l=0;l<j.length;l++){j[l].src=r.convertUrl(j[l].src,k)}}n=r.editor.dom.create("img",{id:m.id,style:m.style,align:m.align,hspace:m.hspace,vspace:m.vspace,src:r.editor.theme.url+"/img/trans.gif","class":"mceItemMedia mceItem"+r.getType(m.type).name,"data-mce-json":g.serialize(m,"'")});n.width=m.width||(m.type=="audio"?"300":"320");n.height=m.height||(m.type=="audio"?"32":"240");return n},dataToHtml:function(i,j){return this.editor.serializer.serialize(this.dataToImg(i,j),{forced_root_block:"",force_absolute:j})},htmlToData:function(k){var j,i,l;l={type:"flash",video:{sources:[]},params:{}};j=this.editor.parser.parse(k);i=j.getAll("img")[0];if(i){l=g.parse(i.attr("data-mce-json"));l.type=this.getType(i.attr("class")).name.toLowerCase();tinymce.each(d,function(m){var n=i.attr(m);if(n){l[m]=n}})}return l},getType:function(m){var k,j,l;j=tinymce.explode(m," ");for(k=0;k<j.length;k++){l=this.lookup[j[k]];if(l){return l}}},imgToObject:function(z,o){var u=this,p=u.editor,C,H,j,t,I,y,G,w,k,E,s,q,A,D,m,x,l,B,F;function r(i,n){var M,L,N,K,J;J=p.getParam("flash_video_player_url",u.convertUrl(u.url+"/moxieplayer.swf"));if(J){M=p.documentBaseURI;G.params.src=J;if(p.getParam("flash_video_player_absvideourl",true)){i=M.toAbsolute(i||"",true);n=M.toAbsolute(n||"",true)}N="";L=p.getParam("flash_video_player_flashvars",{url:"$url",poster:"$poster"});tinymce.each(L,function(P,O){P=P.replace(/\$url/,i||"");P=P.replace(/\$poster/,n||"");if(P.length>0){N+=(N?"&":"")+O+"="+escape(P)}});if(N.length){G.params.flashvars=N}K=p.getParam("flash_video_player_params",{allowfullscreen:true,allowscriptaccess:true});tinymce.each(K,function(P,O){G.params[O]=""+P})}}G=z.attr("data-mce-json");if(!G){return}G=g.parse(G);q=this.getType(z.attr("class"));B=z.attr("data-mce-style");if(!B){B=z.attr("style");if(B){B=p.dom.serializeStyle(p.dom.parseStyle(B,"img"))}}if(q.name==="Iframe"){x=new b("iframe",1);tinymce.each(d,function(i){var n=z.attr(i);if(i=="class"&&n){n=n.replace(/mceItem.+ ?/g,"")}if(n&&n.length>0){x.attr(i,n)}});for(I in G.params){x.attr(I,G.params[I])}x.attr({style:B,src:G.params.src});z.replace(x);return}if(this.editor.settings.media_use_script){x=new b("script",1).attr("type","text/javascript");y=new b("#text",3);y.value="write"+q.name+"("+g.serialize(tinymce.extend(G.params,{width:z.attr("width"),height:z.attr("height")}))+");";x.append(y);z.replace(x);return}if(q.name==="Video"&&G.video.sources[0]){C=new b("video",1).attr(tinymce.extend({id:z.attr("id"),width:z.attr("width"),height:z.attr("height"),style:B},G.video.attrs));if(G.video.attrs){l=G.video.attrs.poster}k=G.video.sources=c(G.video.sources);for(A=0;A<k.length;A++){if(/\.mp4$/.test(k[A].src)){m=k[A].src}}if(!k[0].type){C.attr("src",k[0].src);k.splice(0,1)}for(A=0;A<k.length;A++){w=new b("source",1).attr(k[A]);w.shortEnded=true;C.append(w)}if(m){r(m,l);q=u.getType("flash")}else{G.params.src=""}}if(q.name==="Audio"&&G.video.sources[0]){F=new b("audio",1).attr(tinymce.extend({id:z.attr("id"),width:z.attr("width"),height:z.attr("height"),style:B},G.video.attrs));if(G.video.attrs){l=G.video.attrs.poster}k=G.video.sources=c(G.video.sources);if(!k[0].type){F.attr("src",k[0].src);k.splice(0,1)}for(A=0;A<k.length;A++){w=new b("source",1).attr(k[A]);w.shortEnded=true;F.append(w)}G.params.src=""}if(q.name==="EmbeddedAudio"){j=new b("embed",1);j.shortEnded=true;j.attr({id:z.attr("id"),width:z.attr("width"),height:z.attr("height"),style:B,type:z.attr("type")});for(I in G.params){j.attr(I,G.params[I])}tinymce.each(d,function(i){if(G[i]&&i!="type"){j.attr(i,G[i])}});G.params.src=""}if(G.params.src){if(/\.flv$/i.test(G.params.src)){r(G.params.src,"")}if(o&&o.force_absolute){G.params.src=p.documentBaseURI.toAbsolute(G.params.src)}H=new b("object",1).attr({id:z.attr("id"),width:z.attr("width"),height:z.attr("height"),style:B});tinymce.each(d,function(i){var n=G[i];if(i=="class"&&n){n=n.replace(/mceItem.+ ?/g,"")}if(n&&i!="type"){H.attr(i,n)}});for(I in G.params){s=new b("param",1);s.shortEnded=true;y=G.params[I];if(I==="src"&&q.name==="WindowsMedia"){I="url"}s.attr({name:I,value:y});H.append(s)}if(this.editor.getParam("media_strict",true)){H.attr({data:G.params.src,type:q.mimes[0]})}else{H.attr({classid:"clsid:"+q.clsids[0],codebase:q.codebase});j=new b("embed",1);j.shortEnded=true;j.attr({id:z.attr("id"),width:z.attr("width"),height:z.attr("height"),style:B,type:q.mimes[0]});for(I in G.params){j.attr(I,G.params[I])}tinymce.each(d,function(i){if(G[i]&&i!="type"){j.attr(i,G[i])}});H.append(j)}if(G.object_html){y=new b("#text",3);y.raw=true;y.value=G.object_html;H.append(y)}if(C){C.append(H)}}if(C){if(G.video_html){y=new b("#text",3);y.raw=true;y.value=G.video_html;C.append(y)}}if(F){if(G.video_html){y=new b("#text",3);y.raw=true;y.value=G.video_html;F.append(y)}}var v=C||F||H||j;if(v){z.replace(v)}else{z.remove()}},objectToImg:function(C){var L,k,F,s,M,N,y,A,x,G,E,t,q,I,B,l,K,o,H=this.lookup,m,z,v=this.editor.settings.url_converter,n=this.editor.settings.url_converter_scope,w,r,D,j;function u(i){return new tinymce.html.Serializer({inner:true,validate:false}).serialize(i)}function J(O,i){return H[(O.attr(i)||"").toLowerCase()]}function p(O){var i=O.replace(/^.*\.([^.]+)$/,"$1");return H[i.toLowerCase()||""]}if(!C.parent){return}if(C.name==="script"){if(C.firstChild){m=a.exec(C.firstChild.value)}if(!m){return}o=m[1];K={video:{},params:g.parse(m[2])};A=K.params.width;x=K.params.height}K=K||{video:{},params:{}};M=new b("img",1);M.attr({src:this.editor.theme.url+"/img/trans.gif"});N=C.name;if(N==="video"||N=="audio"){F=C;L=C.getAll("object")[0];k=C.getAll("embed")[0];A=F.attr("width");x=F.attr("height");y=F.attr("id");K.video={attrs:{},sources:[]};z=K.video.attrs;for(N in F.attributes.map){z[N]=F.attributes.map[N]}B=C.attr("src");if(B){K.video.sources.push({src:v.call(n,B,"src",C.name)})}l=F.getAll("source");for(E=0;E<l.length;E++){B=l[E].remove();K.video.sources.push({src:v.call(n,B.attr("src"),"src","source"),type:B.attr("type"),media:B.attr("media")})}if(z.poster){z.poster=v.call(n,z.poster,"poster",C.name)}}if(C.name==="object"){L=C;k=C.getAll("embed")[0]}if(C.name==="embed"){k=C}if(C.name==="iframe"){s=C;o="Iframe"}if(L){A=A||L.attr("width");x=x||L.attr("height");G=G||L.attr("style");y=y||L.attr("id");w=w||L.attr("hspace");r=r||L.attr("vspace");D=D||L.attr("align");j=j||L.attr("bgcolor");K.name=L.attr("name");I=L.getAll("param");for(E=0;E<I.length;E++){q=I[E];N=q.remove().attr("name");if(!h[N]){K.params[N]=q.attr("value")}}K.params.src=K.params.src||L.attr("data")}if(k){A=A||k.attr("width");x=x||k.attr("height");G=G||k.attr("style");y=y||k.attr("id");w=w||k.attr("hspace");r=r||k.attr("vspace");D=D||k.attr("align");j=j||k.attr("bgcolor");for(N in k.attributes.map){if(!h[N]&&!K.params[N]){K.params[N]=k.attributes.map[N]}}}if(s){A=s.attr("width");x=s.attr("height");G=G||s.attr("style");y=s.attr("id");w=s.attr("hspace");r=s.attr("vspace");D=s.attr("align");j=s.attr("bgcolor");tinymce.each(d,function(i){M.attr(i,s.attr(i))});for(N in s.attributes.map){if(!h[N]&&!K.params[N]){K.params[N]=s.attributes.map[N]}}}if(K.params.movie){K.params.src=K.params.src||K.params.movie;delete K.params.movie}if(K.params.src){K.params.src=v.call(n,K.params.src,"src","object")}if(F){if(C.name==="video"){o=H.video.name}else{if(C.name==="audio"){o=H.audio.name}}}if(L&&!o){o=(J(L,"clsid")||J(L,"classid")||J(L,"type")||{}).name}if(k&&!o){o=(J(k,"type")||p(K.params.src)||{}).name}if(k&&o=="EmbeddedAudio"){K.params.type=k.attr("type")}C.replace(M);if(k){k.remove()}if(L){t=u(L.remove());if(t){K.object_html=t}}if(F){t=u(F.remove());if(t){K.video_html=t}}K.hspace=w;K.vspace=r;K.align=D;K.bgcolor=j;M.attr({id:y,"class":"mceItemMedia mceItem"+(o||"Flash"),style:G,width:A||(C.name=="audio"?"300":"320"),height:x||(C.name=="audio"?"32":"240"),hspace:w,vspace:r,align:D,bgcolor:j,"data-mce-json":g.serialize(K,"'")})}});tinymce.PluginManager.add("media",tinymce.plugins.MediaPlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/media/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/editor_plugin_src.js new file mode 100644 index 0000000..ea79db1 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/editor_plugin_src.js @@ -0,0 +1,890 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var rootAttributes = tinymce.explode('id,name,width,height,style,align,class,hspace,vspace,bgcolor,type'), excludedAttrs = tinymce.makeMap(rootAttributes.join(',')), Node = tinymce.html.Node, + mediaTypes, scriptRegExp, JSON = tinymce.util.JSON, mimeTypes; + + // Media types supported by this plugin + mediaTypes = [ + // Type, clsid:s, mime types, codebase + ["Flash", "d27cdb6e-ae6d-11cf-96b8-444553540000", "application/x-shockwave-flash", "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"], + ["ShockWave", "166b1bca-3f9c-11cf-8075-444553540000", "application/x-director", "http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0"], + ["WindowsMedia", "6bf52a52-394a-11d3-b153-00c04f79faa6,22d6f312-b0f6-11d0-94ab-0080c74c7e95,05589fa1-c356-11ce-bf01-00aa0055595a", "application/x-mplayer2", "http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701"], + ["QuickTime", "02bf25d5-8c17-4b23-bc80-d3488abddc6b", "video/quicktime", "http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0"], + ["RealMedia", "cfcdaa03-8be4-11cf-b84b-0020afbbccfa", "audio/x-pn-realaudio-plugin", "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"], + ["Java", "8ad9c840-044e-11d1-b3e9-00805f499d93", "application/x-java-applet", "http://java.sun.com/products/plugin/autodl/jinstall-1_5_0-windows-i586.cab#Version=1,5,0,0"], + ["Silverlight", "dfeaf541-f3e1-4c24-acac-99c30715084a", "application/x-silverlight-2"], + ["Iframe"], + ["Video"], + ["EmbeddedAudio"], + ["Audio"] + ]; + + function toArray(obj) { + var undef, out, i; + + if (obj && !obj.splice) { + out = []; + + for (i = 0; true; i++) { + if (obj[i]) + out[i] = obj[i]; + else + break; + } + + return out; + } + + return obj; + }; + + tinymce.create('tinymce.plugins.MediaPlugin', { + init : function(ed, url) { + var self = this, lookup = {}, i, y, item, name; + + function isMediaImg(node) { + return node && node.nodeName === 'IMG' && ed.dom.hasClass(node, 'mceItemMedia'); + }; + + self.editor = ed; + self.url = url; + + // Parse media types into a lookup table + scriptRegExp = ''; + for (i = 0; i < mediaTypes.length; i++) { + name = mediaTypes[i][0]; + + item = { + name : name, + clsids : tinymce.explode(mediaTypes[i][1] || ''), + mimes : tinymce.explode(mediaTypes[i][2] || ''), + codebase : mediaTypes[i][3] + }; + + for (y = 0; y < item.clsids.length; y++) + lookup['clsid:' + item.clsids[y]] = item; + + for (y = 0; y < item.mimes.length; y++) + lookup[item.mimes[y]] = item; + + lookup['mceItem' + name] = item; + lookup[name.toLowerCase()] = item; + + scriptRegExp += (scriptRegExp ? '|' : '') + name; + } + + // Handle the media_types setting + tinymce.each(ed.getParam("media_types", + "video=mp4,m4v,ogv,webm;" + + "silverlight=xap;" + + "flash=swf,flv;" + + "shockwave=dcr;" + + "quicktime=mov,qt,mpg,mpeg;" + + "shockwave=dcr;" + + "windowsmedia=avi,wmv,wm,asf,asx,wmx,wvx;" + + "realmedia=rm,ra,ram;" + + "java=jar;" + + "audio=mp3,ogg" + ).split(';'), function(item) { + var i, extensions, type; + + item = item.split(/=/); + extensions = tinymce.explode(item[1].toLowerCase()); + for (i = 0; i < extensions.length; i++) { + type = lookup[item[0].toLowerCase()]; + + if (type) + lookup[extensions[i]] = type; + } + }); + + scriptRegExp = new RegExp('write(' + scriptRegExp + ')\\(([^)]+)\\)'); + self.lookup = lookup; + + ed.onPreInit.add(function() { + // Allow video elements + ed.schema.addValidElements('object[id|style|width|height|classid|codebase|*],param[name|value],embed[id|style|width|height|type|src|*],video[*],audio[*],source[*]'); + + // Convert video elements to image placeholder + ed.parser.addNodeFilter('object,embed,video,audio,script,iframe', function(nodes) { + var i = nodes.length; + + while (i--) + self.objectToImg(nodes[i]); + }); + + // Convert image placeholders to video elements + ed.serializer.addNodeFilter('img', function(nodes, name, args) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + if ((node.attr('class') || '').indexOf('mceItemMedia') !== -1) + self.imgToObject(node, args); + } + }); + }); + + ed.onInit.add(function() { + // Display "media" instead of "img" in element path + if (ed.theme && ed.theme.onResolveName) { + ed.theme.onResolveName.add(function(theme, path_object) { + if (path_object.name === 'img' && ed.dom.hasClass(path_object.node, 'mceItemMedia')) + path_object.name = 'media'; + }); + } + + // Add contect menu if it's loaded + if (ed && ed.plugins.contextmenu) { + ed.plugins.contextmenu.onContextMenu.add(function(plugin, menu, element) { + if (element.nodeName === 'IMG' && element.className.indexOf('mceItemMedia') !== -1) + menu.add({title : 'media.edit', icon : 'media', cmd : 'mceMedia'}); + }); + } + }); + + // Register commands + ed.addCommand('mceMedia', function() { + var data, img; + + img = ed.selection.getNode(); + if (isMediaImg(img)) { + data = ed.dom.getAttrib(img, 'data-mce-json'); + if (data) { + data = JSON.parse(data); + + // Add some extra properties to the data object + tinymce.each(rootAttributes, function(name) { + var value = ed.dom.getAttrib(img, name); + + if (value) + data[name] = value; + }); + + data.type = self.getType(img.className).name.toLowerCase(); + } + } + + if (!data) { + data = { + type : 'flash', + video: {sources:[]}, + params: {} + }; + } + + ed.windowManager.open({ + file : url + '/media.htm', + width : 430 + parseInt(ed.getLang('media.delta_width', 0)), + height : 500 + parseInt(ed.getLang('media.delta_height', 0)), + inline : 1 + }, { + plugin_url : url, + data : data + }); + }); + + // Register buttons + ed.addButton('media', {title : 'media.desc', cmd : 'mceMedia'}); + + // Update media selection status + ed.onNodeChange.add(function(ed, cm, node) { + cm.setActive('media', isMediaImg(node)); + }); + }, + + convertUrl : function(url, force_absolute) { + var self = this, editor = self.editor, settings = editor.settings, + urlConverter = settings.url_converter, + urlConverterScope = settings.url_converter_scope || self; + + if (!url) + return url; + + if (force_absolute) + return editor.documentBaseURI.toAbsolute(url); + + return urlConverter.call(urlConverterScope, url, 'src', 'object'); + }, + + getInfo : function() { + return { + longname : 'Media', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + /** + * Converts the JSON data object to an img node. + */ + dataToImg : function(data, force_absolute) { + var self = this, editor = self.editor, baseUri = editor.documentBaseURI, sources, attrs, img, i; + + data.params.src = self.convertUrl(data.params.src, force_absolute); + + attrs = data.video.attrs; + if (attrs) + attrs.src = self.convertUrl(attrs.src, force_absolute); + + if (attrs) + attrs.poster = self.convertUrl(attrs.poster, force_absolute); + + sources = toArray(data.video.sources); + if (sources) { + for (i = 0; i < sources.length; i++) + sources[i].src = self.convertUrl(sources[i].src, force_absolute); + } + + img = self.editor.dom.create('img', { + id : data.id, + style : data.style, + align : data.align, + hspace : data.hspace, + vspace : data.vspace, + src : self.editor.theme.url + '/img/trans.gif', + 'class' : 'mceItemMedia mceItem' + self.getType(data.type).name, + 'data-mce-json' : JSON.serialize(data, "'") + }); + + img.width = data.width || (data.type == 'audio' ? "300" : "320"); + img.height = data.height || (data.type == 'audio' ? "32" : "240"); + + return img; + }, + + /** + * Converts the JSON data object to a HTML string. + */ + dataToHtml : function(data, force_absolute) { + return this.editor.serializer.serialize(this.dataToImg(data, force_absolute), {forced_root_block : '', force_absolute : force_absolute}); + }, + + /** + * Converts the JSON data object to a HTML string. + */ + htmlToData : function(html) { + var fragment, img, data; + + data = { + type : 'flash', + video: {sources:[]}, + params: {} + }; + + fragment = this.editor.parser.parse(html); + img = fragment.getAll('img')[0]; + + if (img) { + data = JSON.parse(img.attr('data-mce-json')); + data.type = this.getType(img.attr('class')).name.toLowerCase(); + + // Add some extra properties to the data object + tinymce.each(rootAttributes, function(name) { + var value = img.attr(name); + + if (value) + data[name] = value; + }); + } + + return data; + }, + + /** + * Get type item by extension, class, clsid or mime type. + * + * @method getType + * @param {String} value Value to get type item by. + * @return {Object} Type item object or undefined. + */ + getType : function(value) { + var i, values, typeItem; + + // Find type by checking the classes + values = tinymce.explode(value, ' '); + for (i = 0; i < values.length; i++) { + typeItem = this.lookup[values[i]]; + + if (typeItem) + return typeItem; + } + }, + + /** + * Converts a tinymce.html.Node image element to video/object/embed. + */ + imgToObject : function(node, args) { + var self = this, editor = self.editor, video, object, embed, iframe, name, value, data, + source, sources, params, param, typeItem, i, item, mp4Source, replacement, + posterSrc, style, audio; + + // Adds the flash player + function addPlayer(video_src, poster_src) { + var baseUri, flashVars, flashVarsOutput, params, flashPlayer; + + flashPlayer = editor.getParam('flash_video_player_url', self.convertUrl(self.url + '/moxieplayer.swf')); + if (flashPlayer) { + baseUri = editor.documentBaseURI; + data.params.src = flashPlayer; + + // Convert the movie url to absolute urls + if (editor.getParam('flash_video_player_absvideourl', true)) { + video_src = baseUri.toAbsolute(video_src || '', true); + poster_src = baseUri.toAbsolute(poster_src || '', true); + } + + // Generate flash vars + flashVarsOutput = ''; + flashVars = editor.getParam('flash_video_player_flashvars', {url : '$url', poster : '$poster'}); + tinymce.each(flashVars, function(value, name) { + // Replace $url and $poster variables in flashvars value + value = value.replace(/\$url/, video_src || ''); + value = value.replace(/\$poster/, poster_src || ''); + + if (value.length > 0) + flashVarsOutput += (flashVarsOutput ? '&' : '') + name + '=' + escape(value); + }); + + if (flashVarsOutput.length) + data.params.flashvars = flashVarsOutput; + + params = editor.getParam('flash_video_player_params', { + allowfullscreen: true, + allowscriptaccess: true + }); + + tinymce.each(params, function(value, name) { + data.params[name] = "" + value; + }); + } + }; + + data = node.attr('data-mce-json'); + if (!data) + return; + + data = JSON.parse(data); + typeItem = this.getType(node.attr('class')); + + style = node.attr('data-mce-style') + if (!style) { + style = node.attr('style'); + + if (style) + style = editor.dom.serializeStyle(editor.dom.parseStyle(style, 'img')); + } + + // Handle iframe + if (typeItem.name === 'Iframe') { + replacement = new Node('iframe', 1); + + tinymce.each(rootAttributes, function(name) { + var value = node.attr(name); + + if (name == 'class' && value) + value = value.replace(/mceItem.+ ?/g, ''); + + if (value && value.length > 0) + replacement.attr(name, value); + }); + + for (name in data.params) + replacement.attr(name, data.params[name]); + + replacement.attr({ + style: style, + src: data.params.src + }); + + node.replace(replacement); + + return; + } + + // Handle scripts + if (this.editor.settings.media_use_script) { + replacement = new Node('script', 1).attr('type', 'text/javascript'); + + value = new Node('#text', 3); + value.value = 'write' + typeItem.name + '(' + JSON.serialize(tinymce.extend(data.params, { + width: node.attr('width'), + height: node.attr('height') + })) + ');'; + + replacement.append(value); + node.replace(replacement); + + return; + } + + // Add HTML5 video element + if (typeItem.name === 'Video' && data.video.sources[0]) { + // Create new object element + video = new Node('video', 1).attr(tinymce.extend({ + id : node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style + }, data.video.attrs)); + + // Get poster source and use that for flash fallback + if (data.video.attrs) + posterSrc = data.video.attrs.poster; + + sources = data.video.sources = toArray(data.video.sources); + for (i = 0; i < sources.length; i++) { + if (/\.mp4$/.test(sources[i].src)) + mp4Source = sources[i].src; + } + + if (!sources[0].type) { + video.attr('src', sources[0].src); + sources.splice(0, 1); + } + + for (i = 0; i < sources.length; i++) { + source = new Node('source', 1).attr(sources[i]); + source.shortEnded = true; + video.append(source); + } + + // Create flash fallback for video if we have a mp4 source + if (mp4Source) { + addPlayer(mp4Source, posterSrc); + typeItem = self.getType('flash'); + } else + data.params.src = ''; + } + + // Add HTML5 audio element + if (typeItem.name === 'Audio' && data.video.sources[0]) { + // Create new object element + audio = new Node('audio', 1).attr(tinymce.extend({ + id : node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style + }, data.video.attrs)); + + // Get poster source and use that for flash fallback + if (data.video.attrs) + posterSrc = data.video.attrs.poster; + + sources = data.video.sources = toArray(data.video.sources); + if (!sources[0].type) { + audio.attr('src', sources[0].src); + sources.splice(0, 1); + } + + for (i = 0; i < sources.length; i++) { + source = new Node('source', 1).attr(sources[i]); + source.shortEnded = true; + audio.append(source); + } + + data.params.src = ''; + } + + if (typeItem.name === 'EmbeddedAudio') { + embed = new Node('embed', 1); + embed.shortEnded = true; + embed.attr({ + id: node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style, + type: node.attr('type') + }); + + for (name in data.params) + embed.attr(name, data.params[name]); + + tinymce.each(rootAttributes, function(name) { + if (data[name] && name != 'type') + embed.attr(name, data[name]); + }); + + data.params.src = ''; + } + + // Do we have a params src then we can generate object + if (data.params.src) { + // Is flv movie add player for it + if (/\.flv$/i.test(data.params.src)) + addPlayer(data.params.src, ''); + + if (args && args.force_absolute) + data.params.src = editor.documentBaseURI.toAbsolute(data.params.src); + + // Create new object element + object = new Node('object', 1).attr({ + id : node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style + }); + + tinymce.each(rootAttributes, function(name) { + var value = data[name]; + + if (name == 'class' && value) + value = value.replace(/mceItem.+ ?/g, ''); + + if (value && name != 'type') + object.attr(name, value); + }); + + // Add params + for (name in data.params) { + param = new Node('param', 1); + param.shortEnded = true; + value = data.params[name]; + + // Windows media needs to use url instead of src for the media URL + if (name === 'src' && typeItem.name === 'WindowsMedia') + name = 'url'; + + param.attr({name: name, value: value}); + object.append(param); + } + + // Setup add type and classid if strict is disabled + if (this.editor.getParam('media_strict', true)) { + object.attr({ + data: data.params.src, + type: typeItem.mimes[0] + }); + } else { + object.attr({ + classid: "clsid:" + typeItem.clsids[0], + codebase: typeItem.codebase + }); + + embed = new Node('embed', 1); + embed.shortEnded = true; + embed.attr({ + id: node.attr('id'), + width: node.attr('width'), + height: node.attr('height'), + style : style, + type: typeItem.mimes[0] + }); + + for (name in data.params) + embed.attr(name, data.params[name]); + + tinymce.each(rootAttributes, function(name) { + if (data[name] && name != 'type') + embed.attr(name, data[name]); + }); + + object.append(embed); + } + + // Insert raw HTML + if (data.object_html) { + value = new Node('#text', 3); + value.raw = true; + value.value = data.object_html; + object.append(value); + } + + // Append object to video element if it exists + if (video) + video.append(object); + } + + if (video) { + // Insert raw HTML + if (data.video_html) { + value = new Node('#text', 3); + value.raw = true; + value.value = data.video_html; + video.append(value); + } + } + + if (audio) { + // Insert raw HTML + if (data.video_html) { + value = new Node('#text', 3); + value.raw = true; + value.value = data.video_html; + audio.append(value); + } + } + + var n = video || audio || object || embed; + if (n) + node.replace(n); + else + node.remove(); + }, + + /** + * Converts a tinymce.html.Node video/object/embed to an img element. + * + * The video/object/embed will be converted into an image placeholder with a JSON data attribute like this: + * <img class="mceItemMedia mceItemFlash" width="100" height="100" data-mce-json="{..}" /> + * + * The JSON structure will be like this: + * {'params':{'flashvars':'something','quality':'high','src':'someurl'}, 'video':{'sources':[{src: 'someurl', type: 'video/mp4'}]}} + */ + objectToImg : function(node) { + var object, embed, video, iframe, img, name, id, width, height, style, i, html, + param, params, source, sources, data, type, lookup = this.lookup, + matches, attrs, urlConverter = this.editor.settings.url_converter, + urlConverterScope = this.editor.settings.url_converter_scope, + hspace, vspace, align, bgcolor; + + function getInnerHTML(node) { + return new tinymce.html.Serializer({ + inner: true, + validate: false + }).serialize(node); + }; + + function lookupAttribute(o, attr) { + return lookup[(o.attr(attr) || '').toLowerCase()]; + } + + function lookupExtension(src) { + var ext = src.replace(/^.*\.([^.]+)$/, '$1'); + return lookup[ext.toLowerCase() || '']; + } + + // If node isn't in document + if (!node.parent) + return; + + // Handle media scripts + if (node.name === 'script') { + if (node.firstChild) + matches = scriptRegExp.exec(node.firstChild.value); + + if (!matches) + return; + + type = matches[1]; + data = {video : {}, params : JSON.parse(matches[2])}; + width = data.params.width; + height = data.params.height; + } + + // Setup data objects + data = data || { + video : {}, + params : {} + }; + + // Setup new image object + img = new Node('img', 1); + img.attr({ + src : this.editor.theme.url + '/img/trans.gif' + }); + + // Video element + name = node.name; + if (name === 'video' || name == 'audio') { + video = node; + object = node.getAll('object')[0]; + embed = node.getAll('embed')[0]; + width = video.attr('width'); + height = video.attr('height'); + id = video.attr('id'); + data.video = {attrs : {}, sources : []}; + + // Get all video attributes + attrs = data.video.attrs; + for (name in video.attributes.map) + attrs[name] = video.attributes.map[name]; + + source = node.attr('src'); + if (source) + data.video.sources.push({src : urlConverter.call(urlConverterScope, source, 'src', node.name)}); + + // Get all sources + sources = video.getAll("source"); + for (i = 0; i < sources.length; i++) { + source = sources[i].remove(); + + data.video.sources.push({ + src: urlConverter.call(urlConverterScope, source.attr('src'), 'src', 'source'), + type: source.attr('type'), + media: source.attr('media') + }); + } + + // Convert the poster URL + if (attrs.poster) + attrs.poster = urlConverter.call(urlConverterScope, attrs.poster, 'poster', node.name); + } + + // Object element + if (node.name === 'object') { + object = node; + embed = node.getAll('embed')[0]; + } + + // Embed element + if (node.name === 'embed') + embed = node; + + // Iframe element + if (node.name === 'iframe') { + iframe = node; + type = 'Iframe'; + } + + if (object) { + // Get width/height + width = width || object.attr('width'); + height = height || object.attr('height'); + style = style || object.attr('style'); + id = id || object.attr('id'); + hspace = hspace || object.attr('hspace'); + vspace = vspace || object.attr('vspace'); + align = align || object.attr('align'); + bgcolor = bgcolor || object.attr('bgcolor'); + data.name = object.attr('name'); + + // Get all object params + params = object.getAll("param"); + for (i = 0; i < params.length; i++) { + param = params[i]; + name = param.remove().attr('name'); + + if (!excludedAttrs[name]) + data.params[name] = param.attr('value'); + } + + data.params.src = data.params.src || object.attr('data'); + } + + if (embed) { + // Get width/height + width = width || embed.attr('width'); + height = height || embed.attr('height'); + style = style || embed.attr('style'); + id = id || embed.attr('id'); + hspace = hspace || embed.attr('hspace'); + vspace = vspace || embed.attr('vspace'); + align = align || embed.attr('align'); + bgcolor = bgcolor || embed.attr('bgcolor'); + + // Get all embed attributes + for (name in embed.attributes.map) { + if (!excludedAttrs[name] && !data.params[name]) + data.params[name] = embed.attributes.map[name]; + } + } + + if (iframe) { + // Get width/height + width = iframe.attr('width'); + height = iframe.attr('height'); + style = style || iframe.attr('style'); + id = iframe.attr('id'); + hspace = iframe.attr('hspace'); + vspace = iframe.attr('vspace'); + align = iframe.attr('align'); + bgcolor = iframe.attr('bgcolor'); + + tinymce.each(rootAttributes, function(name) { + img.attr(name, iframe.attr(name)); + }); + + // Get all iframe attributes + for (name in iframe.attributes.map) { + if (!excludedAttrs[name] && !data.params[name]) + data.params[name] = iframe.attributes.map[name]; + } + } + + // Use src not movie + if (data.params.movie) { + data.params.src = data.params.src || data.params.movie; + delete data.params.movie; + } + + // Convert the URL to relative/absolute depending on configuration + if (data.params.src) + data.params.src = urlConverter.call(urlConverterScope, data.params.src, 'src', 'object'); + + if (video) { + if (node.name === 'video') + type = lookup.video.name; + else if (node.name === 'audio') + type = lookup.audio.name; + } + + if (object && !type) + type = (lookupAttribute(object, 'clsid') || lookupAttribute(object, 'classid') || lookupAttribute(object, 'type') || {}).name; + + if (embed && !type) + type = (lookupAttribute(embed, 'type') || lookupExtension(data.params.src) || {}).name; + + // for embedded audio we preserve the original specified type + if (embed && type == 'EmbeddedAudio') { + data.params.type = embed.attr('type'); + } + + // Replace the video/object/embed element with a placeholder image containing the data + node.replace(img); + + // Remove embed + if (embed) + embed.remove(); + + // Serialize the inner HTML of the object element + if (object) { + html = getInnerHTML(object.remove()); + + if (html) + data.object_html = html; + } + + // Serialize the inner HTML of the video element + if (video) { + html = getInnerHTML(video.remove()); + + if (html) + data.video_html = html; + } + + data.hspace = hspace; + data.vspace = vspace; + data.align = align; + data.bgcolor = bgcolor; + + // Set width/height of placeholder + img.attr({ + id : id, + 'class' : 'mceItemMedia mceItem' + (type || 'Flash'), + style : style, + width : width || (node.name == 'audio' ? "300" : "320"), + height : height || (node.name == 'audio' ? "32" : "240"), + hspace : hspace, + vspace : vspace, + align : align, + bgcolor : bgcolor, + "data-mce-json" : JSON.serialize(data, "'") + }); + } + }); + + // Register plugin + tinymce.PluginManager.add('media', tinymce.plugins.MediaPlugin); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/media/js/embed.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/js/embed.js new file mode 100644 index 0000000..f8dc810 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/js/embed.js @@ -0,0 +1,73 @@ +/** + * This script contains embed functions for common plugins. This scripts are complety free to use for any purpose. + */ + +function writeFlash(p) { + writeEmbed( + 'D27CDB6E-AE6D-11cf-96B8-444553540000', + 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0', + 'application/x-shockwave-flash', + p + ); +} + +function writeShockWave(p) { + writeEmbed( + '166B1BCA-3F9C-11CF-8075-444553540000', + 'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0', + 'application/x-director', + p + ); +} + +function writeQuickTime(p) { + writeEmbed( + '02BF25D5-8C17-4B23-BC80-D3488ABDDC6B', + 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0', + 'video/quicktime', + p + ); +} + +function writeRealMedia(p) { + writeEmbed( + 'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA', + 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0', + 'audio/x-pn-realaudio-plugin', + p + ); +} + +function writeWindowsMedia(p) { + p.url = p.src; + writeEmbed( + '6BF52A52-394A-11D3-B153-00C04F79FAA6', + 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701', + 'application/x-mplayer2', + p + ); +} + +function writeEmbed(cls, cb, mt, p) { + var h = '', n; + + h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"'; + h += typeof(p.id) != "undefined" ? 'id="' + p.id + '"' : ''; + h += typeof(p.name) != "undefined" ? 'name="' + p.name + '"' : ''; + h += typeof(p.width) != "undefined" ? 'width="' + p.width + '"' : ''; + h += typeof(p.height) != "undefined" ? 'height="' + p.height + '"' : ''; + h += typeof(p.align) != "undefined" ? 'align="' + p.align + '"' : ''; + h += '>'; + + for (n in p) + h += '<param name="' + n + '" value="' + p[n] + '">'; + + h += '<embed type="' + mt + '"'; + + for (n in p) + h += n + '="' + p[n] + '" '; + + h += '></embed></object>'; + + document.write(h); +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/media/js/media.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/js/media.js new file mode 100644 index 0000000..c4ec453 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/js/media.js @@ -0,0 +1,453 @@ +(function() { + var url; + + if (url = tinyMCEPopup.getParam("media_external_list_url")) + document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>'); + + function get(id) { + return document.getElementById(id); + } + + function clone(obj) { + var i, len, copy, attr; + + if (null == obj || "object" != typeof obj) + return obj; + + // Handle Array + if ('length' in obj) { + copy = []; + + for (i = 0, len = obj.length; i < len; ++i) { + copy[i] = clone(obj[i]); + } + + return copy; + } + + // Handle Object + copy = {}; + for (attr in obj) { + if (obj.hasOwnProperty(attr)) + copy[attr] = clone(obj[attr]); + } + + return copy; + } + + function getVal(id) { + var elm = get(id); + + if (elm.nodeName == "SELECT") + return elm.options[elm.selectedIndex].value; + + if (elm.type == "checkbox") + return elm.checked; + + return elm.value; + } + + function setVal(id, value, name) { + if (typeof(value) != 'undefined') { + var elm = get(id); + + if (elm.nodeName == "SELECT") + selectByValue(document.forms[0], id, value); + else if (elm.type == "checkbox") { + if (typeof(value) == 'string') { + value = value.toLowerCase(); + value = (!name && value === 'true') || (name && value === name.toLowerCase()); + } + elm.checked = !!value; + } else + elm.value = value; + } + } + + window.Media = { + init : function() { + var html, editor; + + this.editor = editor = tinyMCEPopup.editor; + + // Setup file browsers and color pickers + get('filebrowsercontainer').innerHTML = getBrowserHTML('filebrowser','src','media','media'); + get('qtsrcfilebrowsercontainer').innerHTML = getBrowserHTML('qtsrcfilebrowser','quicktime_qtsrc','media','media'); + get('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor'); + get('video_altsource1_filebrowser').innerHTML = getBrowserHTML('video_filebrowser_altsource1','video_altsource1','media','media'); + get('video_altsource2_filebrowser').innerHTML = getBrowserHTML('video_filebrowser_altsource2','video_altsource2','media','media'); + get('audio_altsource1_filebrowser').innerHTML = getBrowserHTML('audio_filebrowser_altsource1','audio_altsource1','media','media'); + get('audio_altsource2_filebrowser').innerHTML = getBrowserHTML('audio_filebrowser_altsource2','audio_altsource2','media','media'); + get('video_poster_filebrowser').innerHTML = getBrowserHTML('filebrowser_poster','video_poster','media','image'); + + html = this.getMediaListHTML('medialist', 'src', 'media', 'media'); + if (html == "") + get("linklistrow").style.display = 'none'; + else + get("linklistcontainer").innerHTML = html; + + if (isVisible('filebrowser')) + get('src').style.width = '230px'; + + if (isVisible('video_filebrowser_altsource1')) + get('video_altsource1').style.width = '220px'; + + if (isVisible('video_filebrowser_altsource2')) + get('video_altsource2').style.width = '220px'; + + if (isVisible('audio_filebrowser_altsource1')) + get('audio_altsource1').style.width = '220px'; + + if (isVisible('audio_filebrowser_altsource2')) + get('audio_altsource2').style.width = '220px'; + + if (isVisible('filebrowser_poster')) + get('video_poster').style.width = '220px'; + + editor.dom.setOuterHTML(get('media_type'), this.getMediaTypeHTML(editor)); + + this.data = clone(tinyMCEPopup.getWindowArg('data')); + this.dataToForm(); + this.preview(); + + updateColor('bgcolor_pick', 'bgcolor'); + }, + + insert : function() { + var editor = tinyMCEPopup.editor; + + this.formToData(); + editor.execCommand('mceRepaint'); + tinyMCEPopup.restoreSelection(); + editor.selection.setNode(editor.plugins.media.dataToImg(this.data)); + tinyMCEPopup.close(); + }, + + preview : function() { + get('prev').innerHTML = this.editor.plugins.media.dataToHtml(this.data, true); + }, + + moveStates : function(to_form, field) { + var data = this.data, editor = this.editor, + mediaPlugin = editor.plugins.media, ext, src, typeInfo, defaultStates, src; + + defaultStates = { + // QuickTime + quicktime_autoplay : true, + quicktime_controller : true, + + // Flash + flash_play : true, + flash_loop : true, + flash_menu : true, + + // WindowsMedia + windowsmedia_autostart : true, + windowsmedia_enablecontextmenu : true, + windowsmedia_invokeurls : true, + + // RealMedia + realmedia_autogotourl : true, + realmedia_imagestatus : true + }; + + function parseQueryParams(str) { + var out = {}; + + if (str) { + tinymce.each(str.split('&'), function(item) { + var parts = item.split('='); + + out[unescape(parts[0])] = unescape(parts[1]); + }); + } + + return out; + }; + + function setOptions(type, names) { + var i, name, formItemName, value, list; + + if (type == data.type || type == 'global') { + names = tinymce.explode(names); + for (i = 0; i < names.length; i++) { + name = names[i]; + formItemName = type == 'global' ? name : type + '_' + name; + + if (type == 'global') + list = data; + else if (type == 'video' || type == 'audio') { + list = data.video.attrs; + + if (!list && !to_form) + data.video.attrs = list = {}; + } else + list = data.params; + + if (list) { + if (to_form) { + setVal(formItemName, list[name], type == 'video' || type == 'audio' ? name : ''); + } else { + delete list[name]; + + value = getVal(formItemName); + if ((type == 'video' || type == 'audio') && value === true) + value = name; + + if (defaultStates[formItemName]) { + if (value !== defaultStates[formItemName]) { + value = "" + value; + list[name] = value; + } + } else if (value) { + value = "" + value; + list[name] = value; + } + } + } + } + } + } + + if (!to_form) { + data.type = get('media_type').options[get('media_type').selectedIndex].value; + data.width = getVal('width'); + data.height = getVal('height'); + + // Switch type based on extension + src = getVal('src'); + if (field == 'src') { + ext = src.replace(/^.*\.([^.]+)$/, '$1'); + if (typeInfo = mediaPlugin.getType(ext)) + data.type = typeInfo.name.toLowerCase(); + + setVal('media_type', data.type); + } + + if (data.type == "video" || data.type == "audio") { + if (!data.video.sources) + data.video.sources = []; + + data.video.sources[0] = {src: getVal('src')}; + } + } + + // Hide all fieldsets and show the one active + get('video_options').style.display = 'none'; + get('audio_options').style.display = 'none'; + get('flash_options').style.display = 'none'; + get('quicktime_options').style.display = 'none'; + get('shockwave_options').style.display = 'none'; + get('windowsmedia_options').style.display = 'none'; + get('realmedia_options').style.display = 'none'; + get('embeddedaudio_options').style.display = 'none'; + + if (get(data.type + '_options')) + get(data.type + '_options').style.display = 'block'; + + setVal('media_type', data.type); + + setOptions('flash', 'play,loop,menu,swliveconnect,quality,scale,salign,wmode,base,flashvars'); + setOptions('quicktime', 'loop,autoplay,cache,controller,correction,enablejavascript,kioskmode,autohref,playeveryframe,targetcache,scale,starttime,endtime,target,qtsrcchokespeed,volume,qtsrc'); + setOptions('shockwave', 'sound,progress,autostart,swliveconnect,swvolume,swstretchstyle,swstretchhalign,swstretchvalign'); + setOptions('windowsmedia', 'autostart,enabled,enablecontextmenu,fullscreen,invokeurls,mute,stretchtofit,windowlessvideo,balance,baseurl,captioningid,currentmarker,currentposition,defaultframe,playcount,rate,uimode,volume'); + setOptions('realmedia', 'autostart,loop,autogotourl,center,imagestatus,maintainaspect,nojava,prefetch,shuffle,console,controls,numloop,scriptcallbacks'); + setOptions('video', 'poster,autoplay,loop,muted,preload,controls'); + setOptions('audio', 'autoplay,loop,preload,controls'); + setOptions('embeddedaudio', 'autoplay,loop,controls'); + setOptions('global', 'id,name,vspace,hspace,bgcolor,align,width,height'); + + if (to_form) { + if (data.type == 'video') { + if (data.video.sources[0]) + setVal('src', data.video.sources[0].src); + + src = data.video.sources[1]; + if (src) + setVal('video_altsource1', src.src); + + src = data.video.sources[2]; + if (src) + setVal('video_altsource2', src.src); + } else if (data.type == 'audio') { + if (data.video.sources[0]) + setVal('src', data.video.sources[0].src); + + src = data.video.sources[1]; + if (src) + setVal('audio_altsource1', src.src); + + src = data.video.sources[2]; + if (src) + setVal('audio_altsource2', src.src); + } else { + // Check flash vars + if (data.type == 'flash') { + tinymce.each(editor.getParam('flash_video_player_flashvars', {url : '$url', poster : '$poster'}), function(value, name) { + if (value == '$url') + data.params.src = parseQueryParams(data.params.flashvars)[name] || data.params.src || ''; + }); + } + + setVal('src', data.params.src); + } + } else { + src = getVal("src"); + + // YouTube *NEW* + if (src.match(/youtu.be\/[a-z1-9.-_]+/)) { + data.width = 425; + data.height = 350; + data.params.frameborder = '0'; + data.type = 'iframe'; + src = 'http://www.youtube.com/embed/' + src.match(/youtu.be\/([a-z1-9.-_]+)/)[1]; + setVal('src', src); + setVal('media_type', data.type); + } + + // YouTube + if (src.match(/youtube.com(.+)v=([^&]+)/)) { + data.width = 425; + data.height = 350; + data.params.frameborder = '0'; + data.type = 'iframe'; + src = 'http://www.youtube.com/embed/' + src.match(/v=([^&]+)/)[1]; + setVal('src', src); + setVal('media_type', data.type); + } + + // Google video + if (src.match(/video.google.com(.+)docid=([^&]+)/)) { + data.width = 425; + data.height = 326; + data.type = 'flash'; + src = 'http://video.google.com/googleplayer.swf?docId=' + src.match(/docid=([^&]+)/)[1] + '&hl=en'; + setVal('src', src); + setVal('media_type', data.type); + } + + if (data.type == 'video') { + if (!data.video.sources) + data.video.sources = []; + + data.video.sources[0] = {src : src}; + + src = getVal("video_altsource1"); + if (src) + data.video.sources[1] = {src : src}; + + src = getVal("video_altsource2"); + if (src) + data.video.sources[2] = {src : src}; + } else if (data.type == 'audio') { + if (!data.video.sources) + data.video.sources = []; + + data.video.sources[0] = {src : src}; + + src = getVal("audio_altsource1"); + if (src) + data.video.sources[1] = {src : src}; + + src = getVal("audio_altsource2"); + if (src) + data.video.sources[2] = {src : src}; + } else + data.params.src = src; + + // Set default size + setVal('width', data.width || (data.type == 'audio' ? 300 : 320)); + setVal('height', data.height || (data.type == 'audio' ? 32 : 240)); + } + }, + + dataToForm : function() { + this.moveStates(true); + }, + + formToData : function(field) { + if (field == "width" || field == "height") + this.changeSize(field); + + if (field == 'source') { + this.moveStates(false, field); + setVal('source', this.editor.plugins.media.dataToHtml(this.data)); + this.panel = 'source'; + } else { + if (this.panel == 'source') { + this.data = clone(this.editor.plugins.media.htmlToData(getVal('source'))); + this.dataToForm(); + this.panel = ''; + } + + this.moveStates(false, field); + this.preview(); + } + }, + + beforeResize : function() { + this.width = parseInt(getVal('width') || (this.data.type == 'audio' ? "300" : "320"), 10); + this.height = parseInt(getVal('height') || (this.data.type == 'audio' ? "32" : "240"), 10); + }, + + changeSize : function(type) { + var width, height, scale, size; + + if (get('constrain').checked) { + width = parseInt(getVal('width') || (this.data.type == 'audio' ? "300" : "320"), 10); + height = parseInt(getVal('height') || (this.data.type == 'audio' ? "32" : "240"), 10); + + if (type == 'width') { + this.height = Math.round((width / this.width) * height); + setVal('height', this.height); + } else { + this.width = Math.round((height / this.height) * width); + setVal('width', this.width); + } + } + }, + + getMediaListHTML : function() { + if (typeof(tinyMCEMediaList) != "undefined" && tinyMCEMediaList.length > 0) { + var html = ""; + + html += '<select id="linklist" name="linklist" style="width: 250px" onchange="this.form.src.value=this.options[this.selectedIndex].value;Media.formToData(\'src\');">'; + html += '<option value="">---</option>'; + + for (var i=0; i<tinyMCEMediaList.length; i++) + html += '<option value="' + tinyMCEMediaList[i][1] + '">' + tinyMCEMediaList[i][0] + '</option>'; + + html += '</select>'; + + return html; + } + + return ""; + }, + + getMediaTypeHTML : function(editor) { + var html = ""; + html += '<select id="media_type" name="media_type" onchange="Media.formToData(\'type\');">'; + html += '<option value="video">HTML5 Video</option>'; + html += '<option value="audio">HTML5 Audio</option>'; + html += '<option value="flash">Flash</option>'; + html += '<option value="quicktime">QuickTime</option>'; + html += '<option value="shockwave">Shockwave</option>'; + html += '<option value="windowsmedia">Windows Media</option>'; + html += '<option value="realmedia">Real Media</option>'; + html += '<option value="iframe">Iframe</option>'; + + if (editor.getParam('media_embedded_audio', false)) { + html += '<option value="embeddedaudio">Embedded Audio</option>'; + } + + html += '</select>'; + return html; + } + }; + + tinyMCEPopup.requireLangPack(); + tinyMCEPopup.onInit.add(function() { + Media.init(); + }); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/de_dlg.js new file mode 100644 index 0000000..614b11b --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.media_dlg',{list:"Liste",file:"Datei/URL",advanced:"Erweitert",general:"Allgemein",title:"Multimedia-Inhalte einf\u00fcgen/bearbeiten","align_top_left":"Oben Links","align_center":"Zentriert","align_left":"Links","align_bottom":"Unten","align_right":"Rechts","align_top":"Oben","qt_stream_warn":"In den Erweiterten Einstellungen sollten im Feld \'QT Src\' gestreamte RTSP Resourcen hinzugef\u00fcgt werden.\nZus\u00e4tzlich sollten Sie dort auch eine nicht-gestreamte Resource angeben.",qtsrc:"Angabe zu QT Src",progress:"Fortschritt",sound:"Ton",swstretchvalign:"Stretch V-Ausrichtung",swstretchhalign:"Stretch H-Ausrichtung",swstretchstyle:"Stretch-Art",scriptcallbacks:"Script callbacks","align_top_right":"Oben Rechts",uimode:"UI Modus",rate:"Rate",playcount:"Z\u00e4hler",defaultframe:"Frame-Voreinstellung",currentposition:"Aktuelle Position",currentmarker:"Aktueller Marker",captioningid:"Captioning id",baseurl:"Base URL",balance:"Balance",windowlessvideo:"Fensterloses Video",stretchtofit:"Anzeigefl\u00e4che an verf\u00fcgbaren Platz anpassen",mute:"Stumm",invokeurls:"Invoke URLs",fullscreen:"Vollbild",enabled:"Aktiviert",autostart:"Autostart",volume:"Lautst\u00e4rke",target:"Ziel",qtsrcchokespeed:"Choke speed",href:"Href",endtime:"Endzeitpunkt",starttime:"Startzeitpunkt",enablejavascript:"JavaScript aktivieren",correction:"Ohne Korrektur",targetcache:"Ziel zwischenspeichern",playeveryframe:"Jeden Frame abspielen",kioskmode:"Kioskmodus",controller:"Controller",menu:"Men\u00fc anzeigen",loop:"Wiederholung",play:"Automatisches Abspielen",hspace:"Horizontaler Abstand",vspace:"Vertikaler Abstand","class_name":"CSS-Klasse",name:"Name",id:"Id",type:"Typ",size:"Abmessungen",preview:"Vorschau","constrain_proportions":"Proportionen erhalten",controls:"Steuerung",numloop:"Anzahl Wiederholungen",console:"Konsole",cache:"Zwischenspeicher",autohref:"AutoHREF",liveconnect:"SWLiveConnect",flashvars:"Flashvariablen",base:"Base",bgcolor:"Hintergrund",wmode:"WMode",salign:"S-Ausrichtung",align:"Ausrichtung",scale:"Skalierung",quality:"Qualit\u00e4t",shuffle:"Zuf\u00e4llige Wiedergabe",prefetch:"Prefetch",nojava:"Kein Java",maintainaspect:"Bildverh\u00e4ltnis beibehalten",imagestatus:"Bildstatus",center:"Zentriert",autogotourl:"Auto goto URL","shockwave_options":"Shockwave-Optionen","rmp_options":"Optionen f\u00fcr Real Media Player","wmp_options":"Optionen f\u00fcr Windows Media Player","qt_options":"Quicktime-Optionen","flash_options":"Flash-Optionen",hidden:"Versteckt","align_bottom_left":"Unten Links","align_bottom_right":"Unten Rechts","embedded_audio_options":"Integrierte Audio Optionen","html5_video_options":"HTML5 Video Optionen",altsource1:"Alternative Quelle 1",altsource2:"Alternative Quelle 2",preload:"Preload",poster:"Poster",source:"Quelle","html5_audio_options":"Audio Optionen","preload_none":"Nicht vorladen","preload_metadata":"Video Metadaten vorladen","preload_auto":"Benutzer Browser entscheidet automatisch"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/en_dlg.js new file mode 100644 index 0000000..11b24a1 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.media_dlg',{list:"List",file:"File/URL",advanced:"Advanced",general:"General",title:"Insert/Edit Embedded Media","align_top_left":"Top Left","align_center":"Center","align_left":"Left","align_bottom":"Bottom","align_right":"Right","align_top":"Top","qt_stream_warn":"Streamed RTSP resources should be added to the QT Source field under the Advanced tab.\nYou should also add a non-streamed version to the Source field.",qtsrc:"QT Source",progress:"Progress",sound:"Sound",swstretchvalign:"Stretch V-Align",swstretchhalign:"Stretch H-Align",swstretchstyle:"Stretch Style",scriptcallbacks:"Script Callbacks","align_top_right":"Top Right",uimode:"UI Mode",rate:"Rate",playcount:"Play Count",defaultframe:"Default Frame",currentposition:"Current Position",currentmarker:"Current Marker",captioningid:"Captioning ID",baseurl:"Base URL",balance:"Balance",windowlessvideo:"Windowless Video",stretchtofit:"Stretch to Fit",mute:"Mute",invokeurls:"Invoke URLs",fullscreen:"Full Screen",enabled:"Enabled",autostart:"Auto Start",volume:"Volume",target:"Target",qtsrcchokespeed:"Choke Speed",href:"HREF",endtime:"End Time",starttime:"Start Time",enablejavascript:"Enable JavaScript",correction:"No Correction",targetcache:"Target Cache",playeveryframe:"Play Every Frame",kioskmode:"Kiosk Mode",controller:"Controller",menu:"Show Menu",loop:"Loop",play:"Auto Play",hspace:"H-Space",vspace:"V-Space","class_name":"Class",name:"Name",id:"ID",type:"Type",size:"Dimensions",preview:"Preview","constrain_proportions":"Constrain Proportions",controls:"Controls",numloop:"Num Loops",console:"Console",cache:"Cache",autohref:"Auto HREF",liveconnect:"SWLiveConnect",flashvars:"Flash Vars",base:"Base",bgcolor:"Background",wmode:"WMode",salign:"SAlign",align:"Align",scale:"Scale",quality:"Quality",shuffle:"Shuffle",prefetch:"Prefetch",nojava:"No Java",maintainaspect:"Maintain Aspect",imagestatus:"Image Status",center:"Center",autogotourl:"Auto Goto URL","shockwave_options":"Shockwave Options","rmp_options":"Real Media Player Options","wmp_options":"Windows Media Player Options","qt_options":"QuickTime Options","flash_options":"Flash Options",hidden:"Hidden","align_bottom_left":"Bottom Left","align_bottom_right":"Bottom Right","embedded_audio_options":"Embedded Audio Options","html5_video_options":"HTML5 Video Options",altsource1:"Alternative source 1",altsource2:"Alternative source 2",preload:"Preload",poster:"Poster",source:"Source","html5_audio_options":"Audio Options","preload_none":"Don\'t Preload","preload_metadata":"Preload video metadata","preload_auto":"Let user\'s browser decide"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/fr_dlg.js new file mode 100644 index 0000000..6273c59 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.media_dlg',{list:"Liste",file:"Fichier / URL",advanced:"Avanc\u00e9",general:"G\u00e9n\u00e9ral",title:"Ins\u00e9rer / \u00e9diter un fichier m\u00e9dia","align_top_left":"En haut \u00e0 gauche","align_center":"Centr\u00e9","align_left":"Gauche","align_bottom":"Bas","align_right":"Droite","align_top":"Haut","qt_stream_warn":"Les ressources rtsp en streaming doivent \u00eatre ajout\u00e9es au champ \u00ab Source QT \u00bb dans l\'onglet avanc\u00e9.\nVous devriez aussi ajouter une version n\'\u00e9tant pas en streaming au champ \u00ab source QT \u00bb.",qtsrc:"Source QT",progress:"Progression",sound:"Son",swstretchvalign:"Stretch vertical",swstretchhalign:"Stretch horizontal",swstretchstyle:"Stretch style",scriptcallbacks:"Callback de script","align_top_right":"En haut \u00e0 droite",uimode:"Mode UI",rate:"Taux",playcount:"Compteur",defaultframe:"Image par d\u00e9faut",currentposition:"Position actuelle",currentmarker:"Marqueur actuel",captioningid:"ID sous-titrage",baseurl:"Adresse de base",balance:"Balance",windowlessvideo:"Vid\u00e9o sans fen\u00eatre",stretchtofit:"\u00c9tendre pour adapter la taille",mute:"Muet",invokeurls:"Invoquer URLs",fullscreen:"Plein \u00e9cran",enabled:"Activ\u00e9",autostart:"Lire automatiquement",volume:"Volume",target:"Cible",qtsrcchokespeed:"D\u00e9bit maximum",href:"Href",endtime:"Fin",starttime:"D\u00e9but",enablejavascript:"Activer le JavaScript",correction:"Pas de correction",targetcache:"Cache cible",playeveryframe:"Jouer toutes les images",kioskmode:"Mode kiosque",controller:"Contr\u00f4leur",menu:"Afficher le menu",loop:"Lire en boucle",play:"Lecture automatique",hspace:"Espacement horizontal",vspace:"Espacement vertical","class_name":"Classe",name:"Nom",id:"Id",type:"Type",size:"Dimensions",preview:"Pr\u00e9visualisation","constrain_proportions":"Conserver les proportions",controls:"Contr\u00f4les",numloop:"Nombre de tours",console:"Console",cache:"Cache",autohref:"AutoHREF",liveconnect:"SWLiveConnect",flashvars:"Variables flash",base:"Base",bgcolor:"Fond",wmode:"WMode",salign:"SAlign",align:"Alignement",scale:"\u00c9chelle",quality:"Qualit\u00e9",shuffle:"Al\u00e9atoire",prefetch:"Pr\u00e9chargement",nojava:"Pas java",maintainaspect:"Maintenir l\'aspect",imagestatus:"Statut de l\'image",center:"Centrer",autogotourl:"Aller automatiquement \u00e0 l\'URL","shockwave_options":"Options Shockwave","rmp_options":"Options Real media player","wmp_options":"Windows media player options","qt_options":"Options Quicktime","flash_options":"Options Flash",hidden:"Cach\u00e9","align_bottom_left":"En bas \u00e0 gauche","align_bottom_right":"En bas \u00e0 droite","html5_video_options":"Options Vid\u00e9o HTML 5",altsource1:"Source alternative 1",altsource2:"Source alternative 2",preload:"Pr\u00e9chargement",poster:"Poster",source:"Source","html5_audio_options":"Audio Options","preload_none":"Don\'t Preload","preload_metadata":"Preload video metadata","preload_auto":"Let user\'s browser decide"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/it_dlg.js new file mode 100644 index 0000000..23b5240 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.media_dlg',{list:"Lista",file:"File/URL",advanced:"Avanzate",general:"Generale",title:"Inserisci/modifica file multimediale","align_top_left":"Alto a sinistra","align_center":"Centro","align_left":"Sinistra","align_bottom":"Basso","align_right":"Destra","align_top":"Alto","qt_stream_warn":"Le risorse rstp \'streamed\' devono essere aggiunte al campo Sorgente QT nella tabella Avanzate.\nSi dovrebbe inserire anche una versione non \'streamed\' al campo Sorgente..",qtsrc:"Sorgente QT",progress:"Avanzamento",sound:"Suono",swstretchvalign:"Tratto V-Allineamento",swstretchhalign:"Tratto H-Allineamento",swstretchstyle:"Stile Tratto",scriptcallbacks:"Script richiamato","align_top_right":"Alto a destra",uimode:"Modalit\u00e0 Interfaccia Utente",rate:"Qualit\u00e0",playcount:"Conteggio esecuzione",defaultframe:"Frame predefinito",currentposition:"Posizione corrente",currentmarker:"Indicatore corrente",captioningid:"Didascalia dell\'Id",baseurl:"URL base",balance:"Bilanciamento",windowlessvideo:"Video senza finestra",stretchtofit:"Adatta dimensioni",mute:"Muto",invokeurls:"Invoca URLs",fullscreen:"Tutto schermo",enabled:"Abilitato",autostart:"Avvio automatico",volume:"Volume",target:"Target",qtsrcchokespeed:"Velocit\u00e0 cursore",href:"Href",endtime:"Ora fine",starttime:"Ora inizio",enablejavascript:"Abilita JavaScript",correction:"Nessuna correzione",targetcache:"Cache del target",playeveryframe:"Esegui ogni frame",kioskmode:"Modalit\u00e0 Kiosk",controller:"Controller",menu:"Mostra menu",loop:"Riproduzione ciclica",play:"Esecuzione automatica",hspace:"H-Spazio",vspace:"V-Spazio","class_name":"Classe",name:"Nome",id:"Id",type:"Tipo",size:"Dimensioni",preview:"Anteprima","constrain_proportions":"Mantieni proporzioni",controls:"Controlli",numloop:"Numero cicli",console:"Console",cache:"Cache",autohref:"AutoHREF",liveconnect:"SWLiveConnect",flashvars:"Flashvars",base:"Base",bgcolor:"Sfondo",wmode:"WMode",salign:"SAlign",align:"Allineamento",scale:"Scala",quality:"Qualit\u00e0",shuffle:"Shuffle",prefetch:"Precaricamento",nojava:"No java",maintainaspect:"Mantieni aspetto",imagestatus:"Stato immagine",center:"Centra",autogotourl:"Vai a URL automatico","shockwave_options":"Opzioni Shockwave","rmp_options":"Opzioni Real media player","wmp_options":"Opzioni Windows media player","qt_options":"Opzioni Quicktime","flash_options":"Opzioni Flash",hidden:"Nascosto","align_bottom_left":"Basso a sinistra","align_bottom_right":"Basso a destra","html5_video_options":"Opzioni Video HTML5",altsource1:"Sorgente alternativa 1",altsource2:"Sorgente alternativa 2",preload:"Precarica",poster:"Poster",source:"Sorgente","html5_audio_options":"Audio Options","preload_none":"Don\'t Preload","preload_metadata":"Preload video metadata","preload_auto":"Let user\'s browser decide"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/media/media.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/media.htm new file mode 100644 index 0000000..957d83a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/media.htm @@ -0,0 +1,922 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#media_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/media.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <link href="css/media.css" rel="stylesheet" type="text/css" /> +</head> +<body style="display: none" role="application"> +<form onsubmit="Media.insert();return false;" action="#"> + <div class="tabs" role="presentation"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');Media.formToData();" onmousedown="return false;">{#media_dlg.general}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');Media.formToData();" onmousedown="return false;">{#media_dlg.advanced}</a></span></li> + <li id="source_tab" aria-controls="source_panel"><span><a href="javascript:mcTabs.displayTab('source_tab','source_panel');Media.formToData('source');" onmousedown="return false;">{#media_dlg.source}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#media_dlg.general}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td><label for="media_type">{#media_dlg.type}</label></td> + <td> + <select id="media_type"></select> + </td> + </tr> + <tr> + <td><label for="src">{#media_dlg.file}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="src" name="src" type="text" value="" class="mceFocus" onchange="Media.formToData();" /></td> + <td id="filebrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + <tr id="linklistrow"> + <td><label for="linklist">{#media_dlg.list}</label></td> + <td id="linklistcontainer"><select id="linklist"><option value=""></option></select></td> + </tr> + <tr> + <td><label for="width">{#media_dlg.size}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="text" id="width" name="width" value="" class="size" onchange="Media.formToData('width');" onfocus="Media.beforeResize();" /> x <input type="text" id="height" name="height" value="" class="size" onfocus="Media.beforeResize();" onchange="Media.formToData('height');" /></td> + <td>&nbsp;&nbsp;<input id="constrain" type="checkbox" name="constrain" class="checkbox" checked="checked" /></td> + <td><label id="constrainlabel" for="constrain">{#media_dlg.constrain_proportions}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset> + <legend>{#media_dlg.preview}</legend> + <div id="prev"></div> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#media_dlg.advanced}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0" width="100%"> + <tr> + <td><label for="id">{#media_dlg.id}</label></td> + <td><input type="text" id="id" name="id" onchange="Media.formToData();" /></td> + <td><label for="name">{#media_dlg.name}</label></td> + <td><input type="text" id="name" name="name" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="align">{#media_dlg.align}</label></td> + <td> + <select id="align" name="align" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="top">{#media_dlg.align_top}</option> + <option value="right">{#media_dlg.align_right}</option> + <option value="bottom">{#media_dlg.align_bottom}</option> + <option value="left">{#media_dlg.align_left}</option> + </select> + </td> + + <td><label for="bgcolor">{#media_dlg.bgcolor}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');Media.formToData();" /></td> + <td id="bgcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="vspace">{#media_dlg.vspace}</label></td> + <td><input type="text" id="vspace" name="vspace" class="number" onchange="Media.formToData();" /></td> + <td><label for="hspace">{#media_dlg.hspace}</label></td> + <td><input type="text" id="hspace" name="hspace" class="number" onchange="Media.formToData();" /></td> + </tr> + </table> + </fieldset> + + <fieldset id="video_options"> + <legend>{#media_dlg.html5_video_options}</legend> + + <table role="presentation"> + <tr> + <td><label for="video_altsource1">{#media_dlg.altsource1}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="video_altsource1" name="video_altsource1" onchange="Media.formToData();" style="width: 240px" /></td> + <td id="video_altsource1_filebrowser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="video_altsource2">{#media_dlg.altsource2}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="video_altsource2" name="video_altsource2" onchange="Media.formToData();" style="width: 240px" /></td> + <td id="video_altsource2_filebrowser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="video_poster">{#media_dlg.poster}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="video_poster" name="video_poster" onchange="Media.formToData();" style="width: 240px" /></td> + <td id="video_poster_filebrowser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="video_preload">{#media_dlg.preload}</label></td> + <td> + <select id="video_preload" name="video_preload" onchange="Media.formToData();"> + <option value="none">{#media_dlg.preload_none}</option> + <option value="metadata">{#media_dlg.preload_metadata}</option> + <option value="auto">{#media_dlg.preload_auto}</option> + </select> + </td> + </tr> + </table> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="video_autoplay" name="video_autoplay" onchange="Media.formToData();" /></td> + <td><label for="video_autoplay">{#media_dlg.play}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="video_muted" name="video_muted" onchange="Media.formToData();" /></td> + <td><label for="video_muted">{#media_dlg.mute}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="video_loop" name="video_loop" onchange="Media.formToData();" /></td> + <td><label for="video_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="video_controls" name="video_controls" onchange="Media.formToData();" /></td> + <td><label for="video_controls">{#media_dlg.controls}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset id="embeddedaudio_options"> + <legend>{#media_dlg.embedded_audio_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="embeddedaudio_autoplay" name="audio_autoplay" onchange="Media.formToData();" /></td> + <td><label for="audio_autoplay">{#media_dlg.play}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="embeddedaudio_loop" name="audio_loop" onchange="Media.formToData();" /></td> + <td><label for="audio_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="embeddedaudio_controls" name="audio_controls" onchange="Media.formToData();" /></td> + <td><label for="audio_controls">{#media_dlg.controls}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset id="audio_options"> + <legend>{#media_dlg.html5_audio_options}</legend> + + <table role="presentation"> + <tr> + <td><label for="audio_altsource1">{#media_dlg.altsource1}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="audio_altsource1" name="audio_altsource1" onchange="Media.formToData();" style="width: 240px" /></td> + <td id="audio_altsource1_filebrowser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="audio_altsource2">{#media_dlg.altsource2}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="audio_altsource2" name="audio_altsource2" onchange="Media.formToData();" style="width: 240px" /></td> + <td id="audio_altsource2_filebrowser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="audio_preload">{#media_dlg.preload}</label></td> + <td> + <select id="audio_preload" name="audio_preload" onchange="Media.formToData();"> + <option value="none">{#media_dlg.preload_none}</option> + <option value="metadata">{#media_dlg.preload_metadata}</option> + <option value="auto">{#media_dlg.preload_auto}</option> + </select> + </td> + </tr> + </table> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="audio_autoplay" name="audio_autoplay" onchange="Media.formToData();" /></td> + <td><label for="audio_autoplay">{#media_dlg.play}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="audio_loop" name="audio_loop" onchange="Media.formToData();" /></td> + <td><label for="audio_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="audio_controls" name="audio_controls" onchange="Media.formToData();" /></td> + <td><label for="audio_controls">{#media_dlg.controls}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset id="flash_options"> + <legend>{#media_dlg.flash_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td><label for="flash_quality">{#media_dlg.quality}</label></td> + <td> + <select id="flash_quality" name="flash_quality" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="high">high</option> + <option value="low">low</option> + <option value="autolow">autolow</option> + <option value="autohigh">autohigh</option> + <option value="best">best</option> + </select> + </td> + + <td><label for="flash_scale">{#media_dlg.scale}</label></td> + <td> + <select id="flash_scale" name="flash_scale" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="showall">showall</option> + <option value="noborder">noborder</option> + <option value="exactfit">exactfit</option> + <option value="noscale">noscale</option> + </select> + </td> + </tr> + + <tr> + <td><label for="flash_wmode">{#media_dlg.wmode}</label></td> + <td> + <select id="flash_wmode" name="flash_wmode" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="window">window</option> + <option value="opaque">opaque</option> + <option value="transparent">transparent</option> + </select> + </td> + + <td><label for="flash_salign">{#media_dlg.salign}</label></td> + <td> + <select id="flash_salign" name="flash_salign" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="l">{#media_dlg.align_left}</option> + <option value="t">{#media_dlg.align_top}</option> + <option value="r">{#media_dlg.align_right}</option> + <option value="b">{#media_dlg.align_bottom}</option> + <option value="tl">{#media_dlg.align_top_left}</option> + <option value="tr">{#media_dlg.align_top_right}</option> + <option value="bl">{#media_dlg.align_bottom_left}</option> + <option value="br">{#media_dlg.align_bottom_right}</option> + </select> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="flash_play" name="flash_play" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="flash_play">{#media_dlg.play}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="flash_loop" name="flash_loop" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="flash_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="flash_menu" name="flash_menu" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="flash_menu">{#media_dlg.menu}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="flash_swliveconnect" name="flash_swliveconnect" onchange="Media.formToData();" /></td> + <td><label for="flash_swliveconnect">{#media_dlg.liveconnect}</label></td> + </tr> + </table> + </td> + </tr> + </table> + + <table role="presentation"> + <tr> + <td><label for="flash_base">{#media_dlg.base}</label></td> + <td><input type="text" id="flash_base" name="flash_base" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="flash_flashvars">{#media_dlg.flashvars}</label></td> + <td><input type="text" id="flash_flashvars" name="flash_flashvars" onchange="Media.formToData();" /></td> + </tr> + </table> + </fieldset> + + <fieldset id="quicktime_options"> + <legend>{#media_dlg.qt_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_loop" name="quicktime_loop" onchange="Media.formToData();" /></td> + <td><label for="quicktime_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_autoplay" name="quicktime_autoplay" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="quicktime_autoplay">{#media_dlg.play}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_cache" name="quicktime_cache" onchange="Media.formToData();" /></td> + <td><label for="quicktime_cache">{#media_dlg.cache}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_controller" name="quicktime_controller" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="quicktime_controller">{#media_dlg.controller}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_correction" name="quicktime_correction" onchange="Media.formToData();" /></td> + <td><label for="quicktime_correction">{#media_dlg.correction}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_enablejavascript" name="quicktime_enablejavascript" onchange="Media.formToData();" /></td> + <td><label for="quicktime_enablejavascript">{#media_dlg.enablejavascript}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_kioskmode" name="quicktime_kioskmode" onchange="Media.formToData();" /></td> + <td><label for="quicktime_kioskmode">{#media_dlg.kioskmode}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_autohref" name="quicktime_autohref" onchange="Media.formToData();" /></td> + <td><label for="quicktime_autohref">{#media_dlg.autohref}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_playeveryframe" name="quicktime_playeveryframe" onchange="Media.formToData();" /></td> + <td><label for="quicktime_playeveryframe">{#media_dlg.playeveryframe}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="quicktime_targetcache" name="quicktime_targetcache" onchange="Media.formToData();" /></td> + <td><label for="quicktime_targetcache">{#media_dlg.targetcache}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="quicktime_scale">{#media_dlg.scale}</label></td> + <td><select id="quicktime_scale" name="quicktime_scale" class="mceEditableSelect" onchange="Media.formToData();"> + <option value="">{#not_set}</option> + <option value="tofit">tofit</option> + <option value="aspect">aspect</option> + </select> + </td> + + <td colspan="2">&nbsp;</td> + </tr> + + <tr> + <td><label for="quicktime_starttime">{#media_dlg.starttime}</label></td> + <td><input type="text" id="quicktime_starttime" name="quicktime_starttime" onchange="Media.formToData();" /></td> + + <td><label for="quicktime_endtime">{#media_dlg.endtime}</label></td> + <td><input type="text" id="quicktime_endtime" name="quicktime_endtime" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="quicktime_target">{#media_dlg.target}</label></td> + <td><input type="text" id="quicktime_target" name="quicktime_target" onchange="Media.formToData();" /></td> + + <td><label for="quicktime_href">{#media_dlg.href}</label></td> + <td><input type="text" id="quicktime_href" name="quicktime_href" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="quicktime_qtsrcchokespeed">{#media_dlg.qtsrcchokespeed}</label></td> + <td><input type="text" id="quicktime_qtsrcchokespeed" name="quicktime_qtsrcchokespeed" onchange="Media.formToData();" /></td> + + <td><label for="quicktime_volume">{#media_dlg.volume}</label></td> + <td><input type="text" id="quicktime_volume" name="quicktime_volume" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="quicktime_qtsrc">{#media_dlg.qtsrc}</label></td> + <td colspan="4"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="quicktime_qtsrc" name="quicktime_qtsrc" onchange="Media.formToData();" /></td> + <td id="qtsrcfilebrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + + <fieldset id="windowsmedia_options"> + <legend>{#media_dlg.wmp_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_autostart" name="windowsmedia_autostart" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_autostart">{#media_dlg.autostart}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_enabled" name="windowsmedia_enabled" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_enabled">{#media_dlg.enabled}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_enablecontextmenu" name="windowsmedia_enablecontextmenu" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_enablecontextmenu">{#media_dlg.menu}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_fullscreen" name="windowsmedia_fullscreen" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_fullscreen">{#media_dlg.fullscreen}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_invokeurls" name="windowsmedia_invokeurls" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_invokeurls">{#media_dlg.invokeurls}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_mute" name="windowsmedia_mute" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_mute">{#media_dlg.mute}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_stretchtofit" name="windowsmedia_stretchtofit" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_stretchtofit">{#media_dlg.stretchtofit}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="windowsmedia_windowlessvideo" name="windowsmedia_windowlessvideo" onchange="Media.formToData();" /></td> + <td><label for="windowsmedia_windowlessvideo">{#media_dlg.windowlessvideo}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="windowsmedia_balance">{#media_dlg.balance}</label></td> + <td><input type="text" id="windowsmedia_balance" name="windowsmedia_balance" onchange="Media.formToData();" /></td> + + <td><label for="windowsmedia_baseurl">{#media_dlg.baseurl}</label></td> + <td><input type="text" id="windowsmedia_baseurl" name="windowsmedia_baseurl" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="windowsmedia_captioningid">{#media_dlg.captioningid}</label></td> + <td><input type="text" id="windowsmedia_captioningid" name="windowsmedia_captioningid" onchange="Media.formToData();" /></td> + + <td><label for="windowsmedia_currentmarker">{#media_dlg.currentmarker}</label></td> + <td><input type="text" id="windowsmedia_currentmarker" name="windowsmedia_currentmarker" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="windowsmedia_currentposition">{#media_dlg.currentposition}</label></td> + <td><input type="text" id="windowsmedia_currentposition" name="windowsmedia_currentposition" onchange="Media.formToData();" /></td> + + <td><label for="windowsmedia_defaultframe">{#media_dlg.defaultframe}</label></td> + <td><input type="text" id="windowsmedia_defaultframe" name="windowsmedia_defaultframe" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="windowsmedia_playcount">{#media_dlg.playcount}</label></td> + <td><input type="text" id="windowsmedia_playcount" name="windowsmedia_playcount" onchange="Media.formToData();" /></td> + + <td><label for="windowsmedia_rate">{#media_dlg.rate}</label></td> + <td><input type="text" id="windowsmedia_rate" name="windowsmedia_rate" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="windowsmedia_uimode">{#media_dlg.uimode}</label></td> + <td><input type="text" id="windowsmedia_uimode" name="windowsmedia_uimode" onchange="Media.formToData();" /></td> + + <td><label for="windowsmedia_volume">{#media_dlg.volume}</label></td> + <td><input type="text" id="windowsmedia_volume" name="windowsmedia_volume" onchange="Media.formToData();" /></td> + </tr> + + </table> + </fieldset> + + <fieldset id="realmedia_options"> + <legend>{#media_dlg.rmp_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_autostart" name="realmedia_autostart" onchange="Media.formToData();" /></td> + <td><label for="realmedia_autostart">{#media_dlg.autostart}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_loop" name="realmedia_loop" onchange="Media.formToData();" /></td> + <td><label for="realmedia_loop">{#media_dlg.loop}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_autogotourl" name="realmedia_autogotourl" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="realmedia_autogotourl">{#media_dlg.autogotourl}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_center" name="realmedia_center" onchange="Media.formToData();" /></td> + <td><label for="realmedia_center">{#media_dlg.center}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_imagestatus" name="realmedia_imagestatus" checked="checked" onchange="Media.formToData();" /></td> + <td><label for="realmedia_imagestatus">{#media_dlg.imagestatus}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_maintainaspect" name="realmedia_maintainaspect" onchange="Media.formToData();" /></td> + <td><label for="realmedia_maintainaspect">{#media_dlg.maintainaspect}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_nojava" name="realmedia_nojava" onchange="Media.formToData();" /></td> + <td><label for="realmedia_nojava">{#media_dlg.nojava}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_prefetch" name="realmedia_prefetch" onchange="Media.formToData();" /></td> + <td><label for="realmedia_prefetch">{#media_dlg.prefetch}</label></td> + </tr> + </table> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="realmedia_shuffle" name="realmedia_shuffle" onchange="Media.formToData();" /></td> + <td><label for="realmedia_shuffle">{#media_dlg.shuffle}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + &nbsp; + </td> + </tr> + + <tr> + <td><label for="realmedia_console">{#media_dlg.console}</label></td> + <td><input type="text" id="realmedia_console" name="realmedia_console" onchange="Media.formToData();" /></td> + + <td><label for="realmedia_controls">{#media_dlg.controls}</label></td> + <td><input type="text" id="realmedia_controls" name="realmedia_controls" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="realmedia_numloop">{#media_dlg.numloop}</label></td> + <td><input type="text" id="realmedia_numloop" name="realmedia_numloop" onchange="Media.formToData();" /></td> + + <td><label for="realmedia_scriptcallbacks">{#media_dlg.scriptcallbacks}</label></td> + <td><input type="text" id="realmedia_scriptcallbacks" name="realmedia_scriptcallbacks" onchange="Media.formToData();" /></td> + </tr> + </table> + </fieldset> + + <fieldset id="shockwave_options"> + <legend>{#media_dlg.shockwave_options}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td><label for="shockwave_swstretchstyle">{#media_dlg.swstretchstyle}</label></td> + <td> + <select id="shockwave_swstretchstyle" name="shockwave_swstretchstyle" onchange="Media.formToData();"> + <option value="none">{#not_set}</option> + <option value="meet">Meet</option> + <option value="fill">Fill</option> + <option value="stage">Stage</option> + </select> + </td> + + <td><label for="shockwave_swvolume">{#media_dlg.volume}</label></td> + <td><input type="text" id="shockwave_swvolume" name="shockwave_swvolume" onchange="Media.formToData();" /></td> + </tr> + + <tr> + <td><label for="shockwave_swstretchhalign">{#media_dlg.swstretchhalign}</label></td> + <td> + <select id="shockwave_swstretchhalign" name="shockwave_swstretchhalign" onchange="Media.formToData();"> + <option value="none">{#not_set}</option> + <option value="left">{#media_dlg.align_left}</option> + <option value="center">{#media_dlg.align_center}</option> + <option value="right">{#media_dlg.align_right}</option> + </select> + </td> + + <td><label for="shockwave_swstretchvalign">{#media_dlg.swstretchvalign}</label></td> + <td> + <select id="shockwave_swstretchvalign" name="shockwave_swstretchvalign" onchange="Media.formToData();"> + <option value="none">{#not_set}</option> + <option value="meet">Meet</option> + <option value="fill">Fill</option> + <option value="stage">Stage</option> + </select> + </td> + </tr> + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="shockwave_autostart" name="shockwave_autostart" onchange="Media.formToData();" checked="checked" /></td> + <td><label for="shockwave_autostart">{#media_dlg.autostart}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="shockwave_sound" name="shockwave_sound" onchange="Media.formToData();" checked="checked" /></td> + <td><label for="shockwave_sound">{#media_dlg.sound}</label></td> + </tr> + </table> + </td> + </tr> + + + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="shockwave_swliveconnect" name="shockwave_swliveconnect" onchange="Media.formToData();" /></td> + <td><label for="shockwave_swliveconnect">{#media_dlg.liveconnect}</label></td> + </tr> + </table> + </td> + + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input type="checkbox" class="checkbox" id="shockwave_progress" name="shockwave_progress" onchange="Media.formToData();" checked="checked" /></td> + <td><label for="shockwave_progress">{#media_dlg.progress}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + </div> + + <div id="source_panel" class="panel"> + <fieldset> + <legend>{#media_dlg.source}</legend> + <textarea id="source" style="width: 99%; height: 390px"></textarea> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/media/moxieplayer.swf b/src/static/org_glizy/assets/js/tiny_mce/plugins/media/moxieplayer.swf new file mode 100644 index 0000000000000000000000000000000000000000..2a040358df0d1f8eb784d2ec0919626198d6eb47 GIT binary patch literal 33931 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 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/nonbreaking/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/nonbreaking/editor_plugin.js new file mode 100644 index 0000000..687f548 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/nonbreaking/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.Nonbreaking",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceNonBreaking",function(){a.execCommand("mceInsertContent",false,(a.plugins.visualchars&&a.plugins.visualchars.state)?'<span data-mce-bogus="1" class="mceItemHidden mceItemNbsp">&nbsp;</span>':"&nbsp;")});a.addButton("nonbreaking",{title:"nonbreaking.nonbreaking_desc",cmd:"mceNonBreaking"});if(a.getParam("nonbreaking_force_tab")){a.onKeyDown.add(function(d,f){if(f.keyCode==9){f.preventDefault();d.execCommand("mceNonBreaking");d.execCommand("mceNonBreaking");d.execCommand("mceNonBreaking")}})}},getInfo:function(){return{longname:"Nonbreaking space",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("nonbreaking",tinymce.plugins.Nonbreaking)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js new file mode 100644 index 0000000..d492fbe --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/nonbreaking/editor_plugin_src.js @@ -0,0 +1,54 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.Nonbreaking', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceNonBreaking', function() { + ed.execCommand('mceInsertContent', false, (ed.plugins.visualchars && ed.plugins.visualchars.state) ? '<span data-mce-bogus="1" class="mceItemHidden mceItemNbsp">&nbsp;</span>' : '&nbsp;'); + }); + + // Register buttons + ed.addButton('nonbreaking', {title : 'nonbreaking.nonbreaking_desc', cmd : 'mceNonBreaking'}); + + if (ed.getParam('nonbreaking_force_tab')) { + ed.onKeyDown.add(function(ed, e) { + if (e.keyCode == 9) { + e.preventDefault(); + + ed.execCommand('mceNonBreaking'); + ed.execCommand('mceNonBreaking'); + ed.execCommand('mceNonBreaking'); + } + }); + } + }, + + getInfo : function() { + return { + longname : 'Nonbreaking space', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + + // Private methods + }); + + // Register plugin + tinymce.PluginManager.add('nonbreaking', tinymce.plugins.Nonbreaking); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/noneditable/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/noneditable/editor_plugin.js new file mode 100644 index 0000000..2d60138 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/noneditable/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.dom.Event;tinymce.create("tinymce.plugins.NonEditablePlugin",{init:function(d,e){var f=this,c,b,g;f.editor=d;c=d.getParam("noneditable_editable_class","mceEditable");b=d.getParam("noneditable_noneditable_class","mceNonEditable");d.onNodeChange.addToTop(function(i,h,l){var k,j;k=i.dom.getParent(i.selection.getStart(),function(m){return i.dom.hasClass(m,b)});j=i.dom.getParent(i.selection.getEnd(),function(m){return i.dom.hasClass(m,b)});if(k||j){g=1;f._setDisabled(1);return false}else{if(g==1){f._setDisabled(0);g=0}}})},getInfo:function(){return{longname:"Non editable elements",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_block:function(c,d){var b=d.keyCode;if((b>32&&b<41)||(b>111&&b<124)){return}return a.cancel(d)},_setDisabled:function(d){var c=this,b=c.editor;tinymce.each(b.controlManager.controls,function(e){e.setDisabled(d)});if(d!==c.disabled){if(d){b.onKeyDown.addToTop(c._block);b.onKeyPress.addToTop(c._block);b.onKeyUp.addToTop(c._block);b.onPaste.addToTop(c._block);b.onContextMenu.addToTop(c._block)}else{b.onKeyDown.remove(c._block);b.onKeyPress.remove(c._block);b.onKeyUp.remove(c._block);b.onPaste.remove(c._block);b.onContextMenu.remove(c._block)}c.disabled=d}}});tinymce.PluginManager.add("noneditable",tinymce.plugins.NonEditablePlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/noneditable/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/noneditable/editor_plugin_src.js new file mode 100644 index 0000000..916dce2 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/noneditable/editor_plugin_src.js @@ -0,0 +1,95 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var Event = tinymce.dom.Event; + + tinymce.create('tinymce.plugins.NonEditablePlugin', { + init : function(ed, url) { + var t = this, editClass, nonEditClass, state; + + t.editor = ed; + editClass = ed.getParam("noneditable_editable_class", "mceEditable"); + nonEditClass = ed.getParam("noneditable_noneditable_class", "mceNonEditable"); + + ed.onNodeChange.addToTop(function(ed, cm, n) { + var sc, ec; + + // Block if start or end is inside a non editable element + sc = ed.dom.getParent(ed.selection.getStart(), function(n) { + return ed.dom.hasClass(n, nonEditClass); + }); + + ec = ed.dom.getParent(ed.selection.getEnd(), function(n) { + return ed.dom.hasClass(n, nonEditClass); + }); + + // Block or unblock + if (sc || ec) { + state = 1; + t._setDisabled(1); + return false; + } else if (state == 1) { + t._setDisabled(0); + state = 0; + } + }); + }, + + getInfo : function() { + return { + longname : 'Non editable elements', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + _block : function(ed, e) { + var k = e.keyCode; + + // Don't block arrow keys, pg up/down, and F1-F12 + if ((k > 32 && k < 41) || (k > 111 && k < 124)) + return; + + return Event.cancel(e); + }, + + _setDisabled : function(s) { + var t = this, ed = t.editor; + + tinymce.each(ed.controlManager.controls, function(c) { + c.setDisabled(s); + }); + + if (s !== t.disabled) { + if (s) { + ed.onKeyDown.addToTop(t._block); + ed.onKeyPress.addToTop(t._block); + ed.onKeyUp.addToTop(t._block); + ed.onPaste.addToTop(t._block); + ed.onContextMenu.addToTop(t._block); + } else { + ed.onKeyDown.remove(t._block); + ed.onKeyPress.remove(t._block); + ed.onKeyUp.remove(t._block); + ed.onPaste.remove(t._block); + ed.onContextMenu.remove(t._block); + } + + t.disabled = s; + } + } + }); + + // Register plugin + tinymce.PluginManager.add('noneditable', tinymce.plugins.NonEditablePlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/pagebreak/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/pagebreak/editor_plugin.js new file mode 100644 index 0000000..35085e8 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/pagebreak/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.PageBreakPlugin",{init:function(b,d){var f='<img src="'+b.theme.url+'/img/trans.gif" class="mcePageBreak mceItemNoResize" />',a="mcePageBreak",c=b.getParam("pagebreak_separator","<!-- pagebreak -->"),e;e=new RegExp(c.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(g){return"\\"+g}),"g");b.addCommand("mcePageBreak",function(){b.execCommand("mceInsertContent",0,f)});b.addButton("pagebreak",{title:"pagebreak.desc",cmd:a});b.onInit.add(function(){if(b.theme.onResolveName){b.theme.onResolveName.add(function(g,h){if(h.node.nodeName=="IMG"&&b.dom.hasClass(h.node,a)){h.name="pagebreak"}})}});b.onClick.add(function(g,h){h=h.target;if(h.nodeName==="IMG"&&g.dom.hasClass(h,a)){g.selection.select(h)}});b.onNodeChange.add(function(h,g,i){g.setActive("pagebreak",i.nodeName==="IMG"&&h.dom.hasClass(i,a))});b.onBeforeSetContent.add(function(g,h){h.content=h.content.replace(e,f)});b.onPostProcess.add(function(g,h){if(h.get){h.content=h.content.replace(/<img[^>]+>/g,function(i){if(i.indexOf('class="mcePageBreak')!==-1){i=c}return i})}})},getInfo:function(){return{longname:"PageBreak",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/pagebreak",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("pagebreak",tinymce.plugins.PageBreakPlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/pagebreak/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/pagebreak/editor_plugin_src.js new file mode 100644 index 0000000..a094c19 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/pagebreak/editor_plugin_src.js @@ -0,0 +1,74 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.PageBreakPlugin', { + init : function(ed, url) { + var pb = '<img src="' + ed.theme.url + '/img/trans.gif" class="mcePageBreak mceItemNoResize" />', cls = 'mcePageBreak', sep = ed.getParam('pagebreak_separator', '<!-- pagebreak -->'), pbRE; + + pbRE = new RegExp(sep.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g, function(a) {return '\\' + a;}), 'g'); + + // Register commands + ed.addCommand('mcePageBreak', function() { + ed.execCommand('mceInsertContent', 0, pb); + }); + + // Register buttons + ed.addButton('pagebreak', {title : 'pagebreak.desc', cmd : cls}); + + ed.onInit.add(function() { + if (ed.theme.onResolveName) { + ed.theme.onResolveName.add(function(th, o) { + if (o.node.nodeName == 'IMG' && ed.dom.hasClass(o.node, cls)) + o.name = 'pagebreak'; + }); + } + }); + + ed.onClick.add(function(ed, e) { + e = e.target; + + if (e.nodeName === 'IMG' && ed.dom.hasClass(e, cls)) + ed.selection.select(e); + }); + + ed.onNodeChange.add(function(ed, cm, n) { + cm.setActive('pagebreak', n.nodeName === 'IMG' && ed.dom.hasClass(n, cls)); + }); + + ed.onBeforeSetContent.add(function(ed, o) { + o.content = o.content.replace(pbRE, pb); + }); + + ed.onPostProcess.add(function(ed, o) { + if (o.get) + o.content = o.content.replace(/<img[^>]+>/g, function(im) { + if (im.indexOf('class="mcePageBreak') !== -1) + im = sep; + + return im; + }); + }); + }, + + getInfo : function() { + return { + longname : 'PageBreak', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/pagebreak', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('pagebreak', tinymce.plugins.PageBreakPlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/editor_plugin.js new file mode 100644 index 0000000..e47a5c6 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/editor_plugin.js @@ -0,0 +1 @@ +(function(){var c=tinymce.each,a={paste_auto_cleanup_on_paste:true,paste_enable_default_filters:true,paste_block_drop:false,paste_retain_style_properties:"none",paste_strip_class_attributes:"mso",paste_remove_spans:false,paste_remove_styles:false,paste_remove_styles_if_webkit:true,paste_convert_middot_lists:true,paste_convert_headers_to_strong:false,paste_dialog_width:"450",paste_dialog_height:"400",paste_text_use_dialog:false,paste_text_sticky:false,paste_text_sticky_default:false,paste_text_notifyalways:false,paste_text_linebreaktype:"combined",paste_text_replacements:[[/\u2026/g,"..."],[/[\x93\x94\u201c\u201d]/g,'"'],[/[\x60\x91\x92\u2018\u2019]/g,"'"]]};function b(d,e){return d.getParam(e,a[e])}tinymce.create("tinymce.plugins.PastePlugin",{init:function(d,e){var f=this;f.editor=d;f.url=e;f.onPreProcess=new tinymce.util.Dispatcher(f);f.onPostProcess=new tinymce.util.Dispatcher(f);f.onPreProcess.add(f._preProcess);f.onPostProcess.add(f._postProcess);f.onPreProcess.add(function(i,j){d.execCallback("paste_preprocess",i,j)});f.onPostProcess.add(function(i,j){d.execCallback("paste_postprocess",i,j)});d.onKeyDown.addToTop(function(i,j){if(((tinymce.isMac?j.metaKey:j.ctrlKey)&&j.keyCode==86)||(j.shiftKey&&j.keyCode==45)){return false}});d.pasteAsPlainText=b(d,"paste_text_sticky_default");function h(l,j){var k=d.dom,i;f.onPreProcess.dispatch(f,l);l.node=k.create("div",0,l.content);if(tinymce.isGecko){i=d.selection.getRng(true);if(i.startContainer==i.endContainer&&i.startContainer.nodeType==3){if(l.node.childNodes.length===1&&/^(p|h[1-6]|pre)$/i.test(l.node.firstChild.nodeName)&&l.content.indexOf("__MCE_ITEM__")===-1){k.remove(l.node.firstChild,true)}}}f.onPostProcess.dispatch(f,l);l.content=d.serializer.serialize(l.node,{getInner:1,forced_root_block:""});if((!j)&&(d.pasteAsPlainText)){f._insertPlainText(l.content);if(!b(d,"paste_text_sticky")){d.pasteAsPlainText=false;d.controlManager.setActive("pastetext",false)}}else{f._insert(l.content)}}d.addCommand("mceInsertClipboardContent",function(i,j){h(j,true)});if(!b(d,"paste_text_use_dialog")){d.addCommand("mcePasteText",function(j,i){var k=tinymce.util.Cookie;d.pasteAsPlainText=!d.pasteAsPlainText;d.controlManager.setActive("pastetext",d.pasteAsPlainText);if((d.pasteAsPlainText)&&(!k.get("tinymcePasteText"))){if(b(d,"paste_text_sticky")){d.windowManager.alert(d.translate("paste.plaintext_mode_sticky"))}else{d.windowManager.alert(d.translate("paste.plaintext_mode"))}if(!b(d,"paste_text_notifyalways")){k.set("tinymcePasteText","1",new Date(new Date().getFullYear()+1,12,31))}}})}d.addButton("pastetext",{title:"paste.paste_text_desc",cmd:"mcePasteText"});d.addButton("selectall",{title:"paste.selectall_desc",cmd:"selectall"});function g(s){var l,p,j,t,k=d.selection,o=d.dom,q=d.getBody(),i,r;if(s.clipboardData||o.doc.dataTransfer){r=(s.clipboardData||o.doc.dataTransfer).getData("Text");if(d.pasteAsPlainText){s.preventDefault();h({content:o.encode(r).replace(/\r?\n/g,"<br />")});return}}if(o.get("_mcePaste")){return}l=o.add(q,"div",{id:"_mcePaste","class":"mcePaste","data-mce-bogus":"1"},"\uFEFF\uFEFF");if(q!=d.getDoc().body){i=o.getPos(d.selection.getStart(),q).y}else{i=q.scrollTop+o.getViewPort(d.getWin()).y}o.setStyles(l,{position:"absolute",left:tinymce.isGecko?-40:0,top:i-25,width:1,height:1,overflow:"hidden"});if(tinymce.isIE){t=k.getRng();j=o.doc.body.createTextRange();j.moveToElementText(l);j.execCommand("Paste");o.remove(l);if(l.innerHTML==="\uFEFF\uFEFF"){d.execCommand("mcePasteWord");s.preventDefault();return}k.setRng(t);k.setContent("");setTimeout(function(){h({content:l.innerHTML})},0);return tinymce.dom.Event.cancel(s)}else{function m(n){n.preventDefault()}o.bind(d.getDoc(),"mousedown",m);o.bind(d.getDoc(),"keydown",m);p=d.selection.getRng();l=l.firstChild;j=d.getDoc().createRange();j.setStart(l,0);j.setEnd(l,2);k.setRng(j);window.setTimeout(function(){var u="",n;if(!o.select("div.mcePaste > div.mcePaste").length){n=o.select("div.mcePaste");c(n,function(w){var v=w.firstChild;if(v&&v.nodeName=="DIV"&&v.style.marginTop&&v.style.backgroundColor){o.remove(v,1)}c(o.select("span.Apple-style-span",w),function(x){o.remove(x,1)});c(o.select("br[data-mce-bogus]",w),function(x){o.remove(x)});if(w.parentNode.className!="mcePaste"){u+=w.innerHTML}})}else{u="<p>"+o.encode(r).replace(/\r?\n\r?\n/g,"</p><p>").replace(/\r?\n/g,"<br />")+"</p>"}c(o.select("div.mcePaste"),function(v){o.remove(v)});if(p){k.setRng(p)}h({content:u});o.unbind(d.getDoc(),"mousedown",m);o.unbind(d.getDoc(),"keydown",m)},0)}}if(b(d,"paste_auto_cleanup_on_paste")){if(tinymce.isOpera||/Firefox\/2/.test(navigator.userAgent)){d.onKeyDown.addToTop(function(i,j){if(((tinymce.isMac?j.metaKey:j.ctrlKey)&&j.keyCode==86)||(j.shiftKey&&j.keyCode==45)){g(j)}})}else{d.onPaste.addToTop(function(i,j){return g(j)})}}d.onInit.add(function(){d.controlManager.setActive("pastetext",d.pasteAsPlainText);if(b(d,"paste_block_drop")){d.dom.bind(d.getBody(),["dragend","dragover","draggesture","dragdrop","drop","drag"],function(i){i.preventDefault();i.stopPropagation();return false})}});f._legacySupport()},getInfo:function(){return{longname:"Paste text/word",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_preProcess:function(g,e){var k=this.editor,j=e.content,p=tinymce.grep,n=tinymce.explode,f=tinymce.trim,l,i;function d(h){c(h,function(o){if(o.constructor==RegExp){j=j.replace(o,"")}else{j=j.replace(o[0],o[1])}})}if(k.settings.paste_enable_default_filters==false){return}if(tinymce.isIE&&document.documentMode>=9){d([[/(?:<br>&nbsp;[\s\r\n]+|<br>)*(<\/?(h[1-6r]|p|div|address|pre|form|table|tbody|thead|tfoot|th|tr|td|li|ol|ul|caption|blockquote|center|dl|dt|dd|dir|fieldset)[^>]*>)(?:<br>&nbsp;[\s\r\n]+|<br>)*/g,"$1"]]);d([[/<br><br>/g,"<BR><BR>"],[/<br>/g," "],[/<BR><BR>/g,"<br>"]])}if(/class="?Mso|style="[^"]*\bmso-|w:WordDocument/i.test(j)||e.wordContent){e.wordContent=true;d([/^\s*(&nbsp;)+/gi,/(&nbsp;|<br[^>]*>)+\s*$/gi]);if(b(k,"paste_convert_headers_to_strong")){j=j.replace(/<p [^>]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi,"<p><strong>$1</strong></p>")}if(b(k,"paste_convert_middot_lists")){d([[/<!--\[if !supportLists\]-->/gi,"$&__MCE_ITEM__"],[/(<span[^>]+(?:mso-list:|:\s*symbol)[^>]+>)/gi,"$1__MCE_ITEM__"],[/(<p[^>]+(?:MsoListParagraph)[^>]+>)/gi,"$1__MCE_ITEM__"]])}d([/<!--[\s\S]+?-->/gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/&nbsp;/gi,"\u00a0"]]);do{l=j.length;j=j.replace(/(<[a-z][^>]*\s)(?:id|name|language|type|on\w+|\w+:\w+)=(?:"[^"]*"|\w+)\s?/gi,"$1")}while(l!=j.length);if(b(k,"paste_retain_style_properties").replace(/^none$/i,"").length==0){j=j.replace(/<\/?span[^>]*>/gi,"")}else{d([[/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi,function(o,h){return(h.length>0)?h.replace(/./," ").slice(Math.floor(h.length/2)).split("").join("\u00a0"):""}],[/(<[a-z][^>]*)\sstyle="([^"]*)"/gi,function(t,h,r){var u=[],o=0,q=n(f(r).replace(/&quot;/gi,"'"),";");c(q,function(s){var w,y,z=n(s,":");function x(A){return A+((A!=="0")&&(/\d$/.test(A)))?"px":""}if(z.length==2){w=z[0].toLowerCase();y=z[1].toLowerCase();switch(w){case"mso-padding-alt":case"mso-padding-top-alt":case"mso-padding-right-alt":case"mso-padding-bottom-alt":case"mso-padding-left-alt":case"mso-margin-alt":case"mso-margin-top-alt":case"mso-margin-right-alt":case"mso-margin-bottom-alt":case"mso-margin-left-alt":case"mso-table-layout-alt":case"mso-height":case"mso-width":case"mso-vertical-align-alt":u[o++]=w.replace(/^mso-|-alt$/g,"")+":"+x(y);return;case"horiz-align":u[o++]="text-align:"+y;return;case"vert-align":u[o++]="vertical-align:"+y;return;case"font-color":case"mso-foreground":u[o++]="color:"+y;return;case"mso-background":case"mso-highlight":u[o++]="background:"+y;return;case"mso-default-height":u[o++]="min-height:"+x(y);return;case"mso-default-width":u[o++]="min-width:"+x(y);return;case"mso-padding-between-alt":u[o++]="border-collapse:separate;border-spacing:"+x(y);return;case"text-line-through":if((y=="single")||(y=="double")){u[o++]="text-decoration:line-through"}return;case"mso-zero-height":if(y=="yes"){u[o++]="display:none"}return}if(/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?!align|decor|indent|trans)|top-bar|version|vnd|word-break)/.test(w)){return}u[o++]=w+":"+z[1]}});if(o>0){return h+' style="'+u.join(";")+'"'}else{return h}}]])}}if(b(k,"paste_convert_headers_to_strong")){d([[/<h[1-6][^>]*>/gi,"<p><strong>"],[/<\/h[1-6][^>]*>/gi,"</strong></p>"]])}d([[/Version:[\d.]+\nStartHTML:\d+\nEndHTML:\d+\nStartFragment:\d+\nEndFragment:\d+/gi,""]]);i=b(k,"paste_strip_class_attributes");if(i!=="none"){function m(q,o){if(i==="all"){return""}var h=p(n(o.replace(/^(["'])(.*)\1$/,"$2")," "),function(r){return(/^(?!mso)/i.test(r))});return h.length?' class="'+h.join(" ")+'"':""}j=j.replace(/ class="([^"]+)"/gi,m);j=j.replace(/ class=([\-\w]+)/gi,m)}if(b(k,"paste_remove_spans")){j=j.replace(/<\/?span[^>]*>/gi,"")}e.content=j},_postProcess:function(g,i){var f=this,e=f.editor,h=e.dom,d;if(e.settings.paste_enable_default_filters==false){return}if(i.wordContent){c(h.select("a",i.node),function(j){if(!j.href||j.href.indexOf("#_Toc")!=-1){h.remove(j,1)}});if(b(e,"paste_convert_middot_lists")){f._convertLists(g,i)}d=b(e,"paste_retain_style_properties");if((tinymce.is(d,"string"))&&(d!=="all")&&(d!=="*")){d=tinymce.explode(d.replace(/^none$/i,""));c(h.select("*",i.node),function(m){var n={},k=0,l,o,j;if(d){for(l=0;l<d.length;l++){o=d[l];j=h.getStyle(m,o);if(j){n[o]=j;k++}}}h.setAttrib(m,"style","");if(d&&k>0){h.setStyles(m,n)}else{if(m.nodeName=="SPAN"&&!m.className){h.remove(m,true)}}})}}if(b(e,"paste_remove_styles")||(b(e,"paste_remove_styles_if_webkit")&&tinymce.isWebKit)){c(h.select("*[style]",i.node),function(j){j.removeAttribute("style");j.removeAttribute("data-mce-style")})}else{if(tinymce.isWebKit){c(h.select("*",i.node),function(j){j.removeAttribute("data-mce-style")})}}},_convertLists:function(g,e){var i=g.editor.dom,h,l,d=-1,f,m=[],k,j;c(i.select("p",e.node),function(t){var q,u="",s,r,n,o;for(q=t.firstChild;q&&q.nodeType==3;q=q.nextSibling){u+=q.nodeValue}u=t.innerHTML.replace(/<\/?\w+[^>]*>/gi,"").replace(/&nbsp;/g,"\u00a0");if(/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*\u00a0*/.test(u)){s="ul"}if(/^__MCE_ITEM__\s*\w+\.\s*\u00a0+/.test(u)){s="ol"}if(s){f=parseFloat(t.style.marginLeft||0);if(f>d){m.push(f)}if(!h||s!=k){h=i.create(s);i.insertAfter(h,t)}else{if(f>d){h=l.appendChild(i.create(s))}else{if(f<d){n=tinymce.inArray(m,f);o=i.getParents(h.parentNode,s);h=o[o.length-1-n]||h}}}c(i.select("span",t),function(v){var p=v.innerHTML.replace(/<\/?\w+[^>]*>/gi,"");if(s=="ul"&&/^__MCE_ITEM__[\u2022\u00b7\u00a7\u00d8o\u25CF]/.test(p)){i.remove(v)}else{if(/^__MCE_ITEM__[\s\S]*\w+\.(&nbsp;|\u00a0)*\s*/.test(p)){i.remove(v)}}});r=t.innerHTML;if(s=="ul"){r=t.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*(&nbsp;|\u00a0)+\s*/,"")}else{r=t.innerHTML.replace(/__MCE_ITEM__/g,"").replace(/^\s*\w+\.(&nbsp;|\u00a0)+\s*/,"")}l=h.appendChild(i.create("li",0,r));i.remove(t);d=f;k=s}else{h=d=0}});j=e.node.innerHTML;if(j.indexOf("__MCE_ITEM__")!=-1){e.node.innerHTML=j.replace(/__MCE_ITEM__/g,"")}},_insert:function(f,d){var e=this.editor,g=e.selection.getRng();if(!e.selection.isCollapsed()&&g.startContainer!=g.endContainer){e.getDoc().execCommand("Delete",false,null)}e.execCommand("mceInsertContent",false,f,{skip_undo:d})},_insertPlainText:function(g){var d=this.editor,e=b(d,"paste_text_linebreaktype"),i=b(d,"paste_text_replacements"),f=tinymce.is;function h(j){c(j,function(k){if(k.constructor==RegExp){g=g.replace(k,"")}else{g=g.replace(k[0],k[1])}})}if((typeof(g)==="string")&&(g.length>0)){if(/<(?:p|br|h[1-6]|ul|ol|dl|table|t[rdh]|div|blockquote|fieldset|pre|address|center)[^>]*>/i.test(g)){h([/[\n\r]+/g])}else{h([/\r+/g])}h([[/<\/(?:p|h[1-6]|ul|ol|dl|table|div|blockquote|fieldset|pre|address|center)>/gi,"\n\n"],[/<br[^>]*>|<\/tr>/gi,"\n"],[/<\/t[dh]>\s*<t[dh][^>]*>/gi,"\t"],/<[a-z!\/?][^>]*>/gi,[/&nbsp;/gi," "],[/(?:(?!\n)\s)*(\n+)(?:(?!\n)\s)*/gi,"$1"],[/\n{3,}/g,"\n\n"]]);g=d.dom.decode(tinymce.html.Entities.encodeRaw(g));if(f(i,"array")){h(i)}else{if(f(i,"string")){h(new RegExp(i,"gi"))}}if(e=="none"){h([[/\n+/g," "]])}else{if(e=="br"){h([[/\n/g,"<br />"]])}else{if(e=="p"){h([[/\n+/g,"</p><p>"],[/^(.*<\/p>)(<p>)$/,"<p>$1"]])}else{h([[/\n\n/g,"</p><p>"],[/^(.*<\/p>)(<p>)$/,"<p>$1"],[/\n/g,"<br />"]])}}}d.execCommand("mceInsertContent",false,g)}},_legacySupport:function(){var e=this,d=e.editor;d.addCommand("mcePasteWord",function(){d.windowManager.open({file:e.url+"/pasteword.htm",width:parseInt(b(d,"paste_dialog_width")),height:parseInt(b(d,"paste_dialog_height")),inline:1})});if(b(d,"paste_text_use_dialog")){d.addCommand("mcePasteText",function(){d.windowManager.open({file:e.url+"/pastetext.htm",width:parseInt(b(d,"paste_dialog_width")),height:parseInt(b(d,"paste_dialog_height")),inline:1})})}d.addButton("pasteword",{title:"paste.paste_word_desc",cmd:"mcePasteWord"})}});tinymce.PluginManager.add("paste",tinymce.plugins.PastePlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/editor_plugin_src.js new file mode 100644 index 0000000..73fe7fe --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/editor_plugin_src.js @@ -0,0 +1,871 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var each = tinymce.each, + defs = { + paste_auto_cleanup_on_paste : true, + paste_enable_default_filters : true, + paste_block_drop : false, + paste_retain_style_properties : "none", + paste_strip_class_attributes : "mso", + paste_remove_spans : false, + paste_remove_styles : false, + paste_remove_styles_if_webkit : true, + paste_convert_middot_lists : true, + paste_convert_headers_to_strong : false, + paste_dialog_width : "450", + paste_dialog_height : "400", + paste_text_use_dialog : false, + paste_text_sticky : false, + paste_text_sticky_default : false, + paste_text_notifyalways : false, + paste_text_linebreaktype : "combined", + paste_text_replacements : [ + [/\u2026/g, "..."], + [/[\x93\x94\u201c\u201d]/g, '"'], + [/[\x60\x91\x92\u2018\u2019]/g, "'"] + ] + }; + + function getParam(ed, name) { + return ed.getParam(name, defs[name]); + } + + tinymce.create('tinymce.plugins.PastePlugin', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + t.url = url; + + // Setup plugin events + t.onPreProcess = new tinymce.util.Dispatcher(t); + t.onPostProcess = new tinymce.util.Dispatcher(t); + + // Register default handlers + t.onPreProcess.add(t._preProcess); + t.onPostProcess.add(t._postProcess); + + // Register optional preprocess handler + t.onPreProcess.add(function(pl, o) { + ed.execCallback('paste_preprocess', pl, o); + }); + + // Register optional postprocess + t.onPostProcess.add(function(pl, o) { + ed.execCallback('paste_postprocess', pl, o); + }); + + ed.onKeyDown.addToTop(function(ed, e) { + // Block ctrl+v from adding an undo level since the default logic in tinymce.Editor will add that + if (((tinymce.isMac ? e.metaKey : e.ctrlKey) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45)) + return false; // Stop other listeners + }); + + // Initialize plain text flag + ed.pasteAsPlainText = getParam(ed, 'paste_text_sticky_default'); + + // This function executes the process handlers and inserts the contents + // force_rich overrides plain text mode set by user, important for pasting with execCommand + function process(o, force_rich) { + var dom = ed.dom, rng; + + // Execute pre process handlers + t.onPreProcess.dispatch(t, o); + + // Create DOM structure + o.node = dom.create('div', 0, o.content); + + // If pasting inside the same element and the contents is only one block + // remove the block and keep the text since Firefox will copy parts of pre and h1-h6 as a pre element + if (tinymce.isGecko) { + rng = ed.selection.getRng(true); + if (rng.startContainer == rng.endContainer && rng.startContainer.nodeType == 3) { + // Is only one block node and it doesn't contain word stuff + if (o.node.childNodes.length === 1 && /^(p|h[1-6]|pre)$/i.test(o.node.firstChild.nodeName) && o.content.indexOf('__MCE_ITEM__') === -1) + dom.remove(o.node.firstChild, true); + } + } + + // Execute post process handlers + t.onPostProcess.dispatch(t, o); + + // Serialize content + o.content = ed.serializer.serialize(o.node, {getInner : 1, forced_root_block : ''}); + + // Plain text option active? + if ((!force_rich) && (ed.pasteAsPlainText)) { + t._insertPlainText(o.content); + + if (!getParam(ed, "paste_text_sticky")) { + ed.pasteAsPlainText = false; + ed.controlManager.setActive("pastetext", false); + } + } else { + t._insert(o.content); + } + } + + // Add command for external usage + ed.addCommand('mceInsertClipboardContent', function(u, o) { + process(o, true); + }); + + if (!getParam(ed, "paste_text_use_dialog")) { + ed.addCommand('mcePasteText', function(u, v) { + var cookie = tinymce.util.Cookie; + + ed.pasteAsPlainText = !ed.pasteAsPlainText; + ed.controlManager.setActive('pastetext', ed.pasteAsPlainText); + + if ((ed.pasteAsPlainText) && (!cookie.get("tinymcePasteText"))) { + if (getParam(ed, "paste_text_sticky")) { + ed.windowManager.alert(ed.translate('paste.plaintext_mode_sticky')); + } else { + ed.windowManager.alert(ed.translate('paste.plaintext_mode')); + } + + if (!getParam(ed, "paste_text_notifyalways")) { + cookie.set("tinymcePasteText", "1", new Date(new Date().getFullYear() + 1, 12, 31)) + } + } + }); + } + + ed.addButton('pastetext', {title: 'paste.paste_text_desc', cmd: 'mcePasteText'}); + ed.addButton('selectall', {title: 'paste.selectall_desc', cmd: 'selectall'}); + + // This function grabs the contents from the clipboard by adding a + // hidden div and placing the caret inside it and after the browser paste + // is done it grabs that contents and processes that + function grabContent(e) { + var n, or, rng, oldRng, sel = ed.selection, dom = ed.dom, body = ed.getBody(), posY, textContent; + + // Check if browser supports direct plaintext access + if (e.clipboardData || dom.doc.dataTransfer) { + textContent = (e.clipboardData || dom.doc.dataTransfer).getData('Text'); + + if (ed.pasteAsPlainText) { + e.preventDefault(); + process({content : dom.encode(textContent).replace(/\r?\n/g, '<br />')}); + return; + } + } + + if (dom.get('_mcePaste')) + return; + + // Create container to paste into + n = dom.add(body, 'div', {id : '_mcePaste', 'class' : 'mcePaste', 'data-mce-bogus' : '1'}, '\uFEFF\uFEFF'); + + // If contentEditable mode we need to find out the position of the closest element + if (body != ed.getDoc().body) + posY = dom.getPos(ed.selection.getStart(), body).y; + else + posY = body.scrollTop + dom.getViewPort(ed.getWin()).y; + + // Styles needs to be applied after the element is added to the document since WebKit will otherwise remove all styles + // If also needs to be in view on IE or the paste would fail + dom.setStyles(n, { + position : 'absolute', + left : tinymce.isGecko ? -40 : 0, // Need to move it out of site on Gecko since it will othewise display a ghost resize rect for the div + top : posY - 25, + width : 1, + height : 1, + overflow : 'hidden' + }); + + if (tinymce.isIE) { + // Store away the old range + oldRng = sel.getRng(); + + // Select the container + rng = dom.doc.body.createTextRange(); + rng.moveToElementText(n); + rng.execCommand('Paste'); + + // Remove container + dom.remove(n); + + // Check if the contents was changed, if it wasn't then clipboard extraction failed probably due + // to IE security settings so we pass the junk though better than nothing right + if (n.innerHTML === '\uFEFF\uFEFF') { + ed.execCommand('mcePasteWord'); + e.preventDefault(); + return; + } + + // Restore the old range and clear the contents before pasting + sel.setRng(oldRng); + sel.setContent(''); + + // For some odd reason we need to detach the the mceInsertContent call from the paste event + // It's like IE has a reference to the parent element that you paste in and the selection gets messed up + // when it tries to restore the selection + setTimeout(function() { + // Process contents + process({content : n.innerHTML}); + }, 0); + + // Block the real paste event + return tinymce.dom.Event.cancel(e); + } else { + function block(e) { + e.preventDefault(); + }; + + // Block mousedown and click to prevent selection change + dom.bind(ed.getDoc(), 'mousedown', block); + dom.bind(ed.getDoc(), 'keydown', block); + + or = ed.selection.getRng(); + + // Move select contents inside DIV + n = n.firstChild; + rng = ed.getDoc().createRange(); + rng.setStart(n, 0); + rng.setEnd(n, 2); + sel.setRng(rng); + + // Wait a while and grab the pasted contents + window.setTimeout(function() { + var h = '', nl; + + // Paste divs duplicated in paste divs seems to happen when you paste plain text so lets first look for that broken behavior in WebKit + if (!dom.select('div.mcePaste > div.mcePaste').length) { + nl = dom.select('div.mcePaste'); + + // WebKit will split the div into multiple ones so this will loop through then all and join them to get the whole HTML string + each(nl, function(n) { + var child = n.firstChild; + + // WebKit inserts a DIV container with lots of odd styles + if (child && child.nodeName == 'DIV' && child.style.marginTop && child.style.backgroundColor) { + dom.remove(child, 1); + } + + // Remove apply style spans + each(dom.select('span.Apple-style-span', n), function(n) { + dom.remove(n, 1); + }); + + // Remove bogus br elements + each(dom.select('br[data-mce-bogus]', n), function(n) { + dom.remove(n); + }); + + // WebKit will make a copy of the DIV for each line of plain text pasted and insert them into the DIV + if (n.parentNode.className != 'mcePaste') + h += n.innerHTML; + }); + } else { + // Found WebKit weirdness so force the content into paragraphs this seems to happen when you paste plain text from Nodepad etc + // So this logic will replace double enter with paragraphs and single enter with br so it kind of looks the same + h = '<p>' + dom.encode(textContent).replace(/\r?\n\r?\n/g, '</p><p>').replace(/\r?\n/g, '<br />') + '</p>'; + } + + // Remove the nodes + each(dom.select('div.mcePaste'), function(n) { + dom.remove(n); + }); + + // Restore the old selection + if (or) + sel.setRng(or); + + process({content : h}); + + // Unblock events ones we got the contents + dom.unbind(ed.getDoc(), 'mousedown', block); + dom.unbind(ed.getDoc(), 'keydown', block); + }, 0); + } + } + + // Check if we should use the new auto process method + if (getParam(ed, "paste_auto_cleanup_on_paste")) { + // Is it's Opera or older FF use key handler + if (tinymce.isOpera || /Firefox\/2/.test(navigator.userAgent)) { + ed.onKeyDown.addToTop(function(ed, e) { + if (((tinymce.isMac ? e.metaKey : e.ctrlKey) && e.keyCode == 86) || (e.shiftKey && e.keyCode == 45)) + grabContent(e); + }); + } else { + // Grab contents on paste event on Gecko and WebKit + ed.onPaste.addToTop(function(ed, e) { + return grabContent(e); + }); + } + } + + ed.onInit.add(function() { + ed.controlManager.setActive("pastetext", ed.pasteAsPlainText); + + // Block all drag/drop events + if (getParam(ed, "paste_block_drop")) { + ed.dom.bind(ed.getBody(), ['dragend', 'dragover', 'draggesture', 'dragdrop', 'drop', 'drag'], function(e) { + e.preventDefault(); + e.stopPropagation(); + + return false; + }); + } + }); + + // Add legacy support + t._legacySupport(); + }, + + getInfo : function() { + return { + longname : 'Paste text/word', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + _preProcess : function(pl, o) { + var ed = this.editor, + h = o.content, + grep = tinymce.grep, + explode = tinymce.explode, + trim = tinymce.trim, + len, stripClass; + + //console.log('Before preprocess:' + o.content); + + function process(items) { + each(items, function(v) { + // Remove or replace + if (v.constructor == RegExp) + h = h.replace(v, ''); + else + h = h.replace(v[0], v[1]); + }); + } + + if (ed.settings.paste_enable_default_filters == false) { + return; + } + + // IE9 adds BRs before/after block elements when contents is pasted from word or for example another browser + if (tinymce.isIE && document.documentMode >= 9) { + // IE9 adds BRs before/after block elements when contents is pasted from word or for example another browser + process([[/(?:<br>&nbsp;[\s\r\n]+|<br>)*(<\/?(h[1-6r]|p|div|address|pre|form|table|tbody|thead|tfoot|th|tr|td|li|ol|ul|caption|blockquote|center|dl|dt|dd|dir|fieldset)[^>]*>)(?:<br>&nbsp;[\s\r\n]+|<br>)*/g, '$1']]); + + // IE9 also adds an extra BR element for each soft-linefeed and it also adds a BR for each word wrap break + process([ + [/<br><br>/g, '<BR><BR>'], // Replace multiple BR elements with uppercase BR to keep them intact + [/<br>/g, ' '], // Replace single br elements with space since they are word wrap BR:s + [/<BR><BR>/g, '<br>'] // Replace back the double brs but into a single BR + ]); + } + + // Detect Word content and process it more aggressive + if (/class="?Mso|style="[^"]*\bmso-|w:WordDocument/i.test(h) || o.wordContent) { + o.wordContent = true; // Mark the pasted contents as word specific content + //console.log('Word contents detected.'); + + // Process away some basic content + process([ + /^\s*(&nbsp;)+/gi, // &nbsp; entities at the start of contents + /(&nbsp;|<br[^>]*>)+\s*$/gi // &nbsp; entities at the end of contents + ]); + + if (getParam(ed, "paste_convert_headers_to_strong")) { + h = h.replace(/<p [^>]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "<p><strong>$1</strong></p>"); + } + + if (getParam(ed, "paste_convert_middot_lists")) { + process([ + [/<!--\[if !supportLists\]-->/gi, '$&__MCE_ITEM__'], // Convert supportLists to a list item marker + [/(<span[^>]+(?:mso-list:|:\s*symbol)[^>]+>)/gi, '$1__MCE_ITEM__'], // Convert mso-list and symbol spans to item markers + [/(<p[^>]+(?:MsoListParagraph)[^>]+>)/gi, '$1__MCE_ITEM__'] // Convert mso-list and symbol paragraphs to item markers (FF) + ]); + } + + process([ + // Word comments like conditional comments etc + /<!--[\s\S]+?-->/gi, + + // Remove comments, scripts (e.g., msoShowComment), XML tag, VML content, MS Office namespaced tags, and a few other tags + /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi, + + // Convert <s> into <strike> for line-though + [/<(\/?)s>/gi, "<$1strike>"], + + // Replace nsbp entites to char since it's easier to handle + [/&nbsp;/gi, "\u00a0"] + ]); + + // Remove bad attributes, with or without quotes, ensuring that attribute text is really inside a tag. + // If JavaScript had a RegExp look-behind, we could have integrated this with the last process() array and got rid of the loop. But alas, it does not, so we cannot. + do { + len = h.length; + h = h.replace(/(<[a-z][^>]*\s)(?:id|name|language|type|on\w+|\w+:\w+)=(?:"[^"]*"|\w+)\s?/gi, "$1"); + } while (len != h.length); + + // Remove all spans if no styles is to be retained + if (getParam(ed, "paste_retain_style_properties").replace(/^none$/i, "").length == 0) { + h = h.replace(/<\/?span[^>]*>/gi, ""); + } else { + // We're keeping styles, so at least clean them up. + // CSS Reference: http://msdn.microsoft.com/en-us/library/aa155477.aspx + + process([ + // Convert <span style="mso-spacerun:yes">___</span> to string of alternating breaking/non-breaking spaces of same length + [/<span\s+style\s*=\s*"\s*mso-spacerun\s*:\s*yes\s*;?\s*"\s*>([\s\u00a0]*)<\/span>/gi, + function(str, spaces) { + return (spaces.length > 0)? spaces.replace(/./, " ").slice(Math.floor(spaces.length/2)).split("").join("\u00a0") : ""; + } + ], + + // Examine all styles: delete junk, transform some, and keep the rest + [/(<[a-z][^>]*)\sstyle="([^"]*)"/gi, + function(str, tag, style) { + var n = [], + i = 0, + s = explode(trim(style).replace(/&quot;/gi, "'"), ";"); + + // Examine each style definition within the tag's style attribute + each(s, function(v) { + var name, value, + parts = explode(v, ":"); + + function ensureUnits(v) { + return v + ((v !== "0") && (/\d$/.test(v)))? "px" : ""; + } + + if (parts.length == 2) { + name = parts[0].toLowerCase(); + value = parts[1].toLowerCase(); + + // Translate certain MS Office styles into their CSS equivalents + switch (name) { + case "mso-padding-alt": + case "mso-padding-top-alt": + case "mso-padding-right-alt": + case "mso-padding-bottom-alt": + case "mso-padding-left-alt": + case "mso-margin-alt": + case "mso-margin-top-alt": + case "mso-margin-right-alt": + case "mso-margin-bottom-alt": + case "mso-margin-left-alt": + case "mso-table-layout-alt": + case "mso-height": + case "mso-width": + case "mso-vertical-align-alt": + n[i++] = name.replace(/^mso-|-alt$/g, "") + ":" + ensureUnits(value); + return; + + case "horiz-align": + n[i++] = "text-align:" + value; + return; + + case "vert-align": + n[i++] = "vertical-align:" + value; + return; + + case "font-color": + case "mso-foreground": + n[i++] = "color:" + value; + return; + + case "mso-background": + case "mso-highlight": + n[i++] = "background:" + value; + return; + + case "mso-default-height": + n[i++] = "min-height:" + ensureUnits(value); + return; + + case "mso-default-width": + n[i++] = "min-width:" + ensureUnits(value); + return; + + case "mso-padding-between-alt": + n[i++] = "border-collapse:separate;border-spacing:" + ensureUnits(value); + return; + + case "text-line-through": + if ((value == "single") || (value == "double")) { + n[i++] = "text-decoration:line-through"; + } + return; + + case "mso-zero-height": + if (value == "yes") { + n[i++] = "display:none"; + } + return; + } + + // Eliminate all MS Office style definitions that have no CSS equivalent by examining the first characters in the name + if (/^(mso|column|font-emph|lang|layout|line-break|list-image|nav|panose|punct|row|ruby|sep|size|src|tab-|table-border|text-(?!align|decor|indent|trans)|top-bar|version|vnd|word-break)/.test(name)) { + return; + } + + // If it reached this point, it must be a valid CSS style + n[i++] = name + ":" + parts[1]; // Lower-case name, but keep value case + } + }); + + // If style attribute contained any valid styles the re-write it; otherwise delete style attribute. + if (i > 0) { + return tag + ' style="' + n.join(';') + '"'; + } else { + return tag; + } + } + ] + ]); + } + } + + // Replace headers with <strong> + if (getParam(ed, "paste_convert_headers_to_strong")) { + process([ + [/<h[1-6][^>]*>/gi, "<p><strong>"], + [/<\/h[1-6][^>]*>/gi, "</strong></p>"] + ]); + } + + process([ + // Copy paste from Java like Open Office will produce this junk on FF + [/Version:[\d.]+\nStartHTML:\d+\nEndHTML:\d+\nStartFragment:\d+\nEndFragment:\d+/gi, ''] + ]); + + // Class attribute options are: leave all as-is ("none"), remove all ("all"), or remove only those starting with mso ("mso"). + // Note:- paste_strip_class_attributes: "none", verify_css_classes: true is also a good variation. + stripClass = getParam(ed, "paste_strip_class_attributes"); + + if (stripClass !== "none") { + function removeClasses(match, g1) { + if (stripClass === "all") + return ''; + + var cls = grep(explode(g1.replace(/^(["'])(.*)\1$/, "$2"), " "), + function(v) { + return (/^(?!mso)/i.test(v)); + } + ); + + return cls.length ? ' class="' + cls.join(" ") + '"' : ''; + }; + + h = h.replace(/ class="([^"]+)"/gi, removeClasses); + h = h.replace(/ class=([\-\w]+)/gi, removeClasses); + } + + // Remove spans option + if (getParam(ed, "paste_remove_spans")) { + h = h.replace(/<\/?span[^>]*>/gi, ""); + } + + //console.log('After preprocess:' + h); + + o.content = h; + }, + + /** + * Various post process items. + */ + _postProcess : function(pl, o) { + var t = this, ed = t.editor, dom = ed.dom, styleProps; + + if (ed.settings.paste_enable_default_filters == false) { + return; + } + + if (o.wordContent) { + // Remove named anchors or TOC links + each(dom.select('a', o.node), function(a) { + if (!a.href || a.href.indexOf('#_Toc') != -1) + dom.remove(a, 1); + }); + + if (getParam(ed, "paste_convert_middot_lists")) { + t._convertLists(pl, o); + } + + // Process styles + styleProps = getParam(ed, "paste_retain_style_properties"); // retained properties + + // Process only if a string was specified and not equal to "all" or "*" + if ((tinymce.is(styleProps, "string")) && (styleProps !== "all") && (styleProps !== "*")) { + styleProps = tinymce.explode(styleProps.replace(/^none$/i, "")); + + // Retains some style properties + each(dom.select('*', o.node), function(el) { + var newStyle = {}, npc = 0, i, sp, sv; + + // Store a subset of the existing styles + if (styleProps) { + for (i = 0; i < styleProps.length; i++) { + sp = styleProps[i]; + sv = dom.getStyle(el, sp); + + if (sv) { + newStyle[sp] = sv; + npc++; + } + } + } + + // Remove all of the existing styles + dom.setAttrib(el, 'style', ''); + + if (styleProps && npc > 0) + dom.setStyles(el, newStyle); // Add back the stored subset of styles + else // Remove empty span tags that do not have class attributes + if (el.nodeName == 'SPAN' && !el.className) + dom.remove(el, true); + }); + } + } + + // Remove all style information or only specifically on WebKit to avoid the style bug on that browser + if (getParam(ed, "paste_remove_styles") || (getParam(ed, "paste_remove_styles_if_webkit") && tinymce.isWebKit)) { + each(dom.select('*[style]', o.node), function(el) { + el.removeAttribute('style'); + el.removeAttribute('data-mce-style'); + }); + } else { + if (tinymce.isWebKit) { + // We need to compress the styles on WebKit since if you paste <img border="0" /> it will become <img border="0" style="... lots of junk ..." /> + // Removing the mce_style that contains the real value will force the Serializer engine to compress the styles + each(dom.select('*', o.node), function(el) { + el.removeAttribute('data-mce-style'); + }); + } + } + }, + + /** + * Converts the most common bullet and number formats in Office into a real semantic UL/LI list. + */ + _convertLists : function(pl, o) { + var dom = pl.editor.dom, listElm, li, lastMargin = -1, margin, levels = [], lastType, html; + + // Convert middot lists into real semantic lists + each(dom.select('p', o.node), function(p) { + var sib, val = '', type, html, idx, parents; + + // Get text node value at beginning of paragraph + for (sib = p.firstChild; sib && sib.nodeType == 3; sib = sib.nextSibling) + val += sib.nodeValue; + + val = p.innerHTML.replace(/<\/?\w+[^>]*>/gi, '').replace(/&nbsp;/g, '\u00a0'); + + // Detect unordered lists look for bullets + if (/^(__MCE_ITEM__)+[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*\u00a0*/.test(val)) + type = 'ul'; + + // Detect ordered lists 1., a. or ixv. + if (/^__MCE_ITEM__\s*\w+\.\s*\u00a0+/.test(val)) + type = 'ol'; + + // Check if node value matches the list pattern: o&nbsp;&nbsp; + if (type) { + margin = parseFloat(p.style.marginLeft || 0); + + if (margin > lastMargin) + levels.push(margin); + + if (!listElm || type != lastType) { + listElm = dom.create(type); + dom.insertAfter(listElm, p); + } else { + // Nested list element + if (margin > lastMargin) { + listElm = li.appendChild(dom.create(type)); + } else if (margin < lastMargin) { + // Find parent level based on margin value + idx = tinymce.inArray(levels, margin); + parents = dom.getParents(listElm.parentNode, type); + listElm = parents[parents.length - 1 - idx] || listElm; + } + } + + // Remove middot or number spans if they exists + each(dom.select('span', p), function(span) { + var html = span.innerHTML.replace(/<\/?\w+[^>]*>/gi, ''); + + // Remove span with the middot or the number + if (type == 'ul' && /^__MCE_ITEM__[\u2022\u00b7\u00a7\u00d8o\u25CF]/.test(html)) + dom.remove(span); + else if (/^__MCE_ITEM__[\s\S]*\w+\.(&nbsp;|\u00a0)*\s*/.test(html)) + dom.remove(span); + }); + + html = p.innerHTML; + + // Remove middot/list items + if (type == 'ul') + html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^[\u2022\u00b7\u00a7\u00d8o\u25CF]\s*(&nbsp;|\u00a0)+\s*/, ''); + else + html = p.innerHTML.replace(/__MCE_ITEM__/g, '').replace(/^\s*\w+\.(&nbsp;|\u00a0)+\s*/, ''); + + // Create li and add paragraph data into the new li + li = listElm.appendChild(dom.create('li', 0, html)); + dom.remove(p); + + lastMargin = margin; + lastType = type; + } else + listElm = lastMargin = 0; // End list element + }); + + // Remove any left over makers + html = o.node.innerHTML; + if (html.indexOf('__MCE_ITEM__') != -1) + o.node.innerHTML = html.replace(/__MCE_ITEM__/g, ''); + }, + + /** + * Inserts the specified contents at the caret position. + */ + _insert : function(h, skip_undo) { + var ed = this.editor, r = ed.selection.getRng(); + + // First delete the contents seems to work better on WebKit when the selection spans multiple list items or multiple table cells. + if (!ed.selection.isCollapsed() && r.startContainer != r.endContainer) + ed.getDoc().execCommand('Delete', false, null); + + ed.execCommand('mceInsertContent', false, h, {skip_undo : skip_undo}); + }, + + /** + * Instead of the old plain text method which tried to re-create a paste operation, the + * new approach adds a plain text mode toggle switch that changes the behavior of paste. + * This function is passed the same input that the regular paste plugin produces. + * It performs additional scrubbing and produces (and inserts) the plain text. + * This approach leverages all of the great existing functionality in the paste + * plugin, and requires minimal changes to add the new functionality. + * Speednet - June 2009 + */ + _insertPlainText : function(content) { + var ed = this.editor, + linebr = getParam(ed, "paste_text_linebreaktype"), + rl = getParam(ed, "paste_text_replacements"), + is = tinymce.is; + + function process(items) { + each(items, function(v) { + if (v.constructor == RegExp) + content = content.replace(v, ""); + else + content = content.replace(v[0], v[1]); + }); + }; + + if ((typeof(content) === "string") && (content.length > 0)) { + // If HTML content with line-breaking tags, then remove all cr/lf chars because only tags will break a line + if (/<(?:p|br|h[1-6]|ul|ol|dl|table|t[rdh]|div|blockquote|fieldset|pre|address|center)[^>]*>/i.test(content)) { + process([ + /[\n\r]+/g + ]); + } else { + // Otherwise just get rid of carriage returns (only need linefeeds) + process([ + /\r+/g + ]); + } + + process([ + [/<\/(?:p|h[1-6]|ul|ol|dl|table|div|blockquote|fieldset|pre|address|center)>/gi, "\n\n"], // Block tags get a blank line after them + [/<br[^>]*>|<\/tr>/gi, "\n"], // Single linebreak for <br /> tags and table rows + [/<\/t[dh]>\s*<t[dh][^>]*>/gi, "\t"], // Table cells get tabs betweem them + /<[a-z!\/?][^>]*>/gi, // Delete all remaining tags + [/&nbsp;/gi, " "], // Convert non-break spaces to regular spaces (remember, *plain text*) + [/(?:(?!\n)\s)*(\n+)(?:(?!\n)\s)*/gi, "$1"],// Cool little RegExp deletes whitespace around linebreak chars. + [/\n{3,}/g, "\n\n"] // Max. 2 consecutive linebreaks + ]); + + content = ed.dom.decode(tinymce.html.Entities.encodeRaw(content)); + + // Perform default or custom replacements + if (is(rl, "array")) { + process(rl); + } else if (is(rl, "string")) { + process(new RegExp(rl, "gi")); + } + + // Treat paragraphs as specified in the config + if (linebr == "none") { + // Convert all line breaks to space + process([ + [/\n+/g, " "] + ]); + } else if (linebr == "br") { + // Convert all line breaks to <br /> + process([ + [/\n/g, "<br />"] + ]); + } else if (linebr == "p") { + // Convert all line breaks to <p>...</p> + process([ + [/\n+/g, "</p><p>"], + [/^(.*<\/p>)(<p>)$/, '<p>$1'] + ]); + } else { + // defaults to "combined" + // Convert single line breaks to <br /> and double line breaks to <p>...</p> + process([ + [/\n\n/g, "</p><p>"], + [/^(.*<\/p>)(<p>)$/, '<p>$1'], + [/\n/g, "<br />"] + ]); + } + + ed.execCommand('mceInsertContent', false, content); + } + }, + + /** + * This method will open the old style paste dialogs. Some users might want the old behavior but still use the new cleanup engine. + */ + _legacySupport : function() { + var t = this, ed = t.editor; + + // Register command(s) for backwards compatibility + ed.addCommand("mcePasteWord", function() { + ed.windowManager.open({ + file: t.url + "/pasteword.htm", + width: parseInt(getParam(ed, "paste_dialog_width")), + height: parseInt(getParam(ed, "paste_dialog_height")), + inline: 1 + }); + }); + + if (getParam(ed, "paste_text_use_dialog")) { + ed.addCommand("mcePasteText", function() { + ed.windowManager.open({ + file : t.url + "/pastetext.htm", + width: parseInt(getParam(ed, "paste_dialog_width")), + height: parseInt(getParam(ed, "paste_dialog_height")), + inline : 1 + }); + }); + } + + // Register button for backwards compatibility + ed.addButton("pasteword", {title : "paste.paste_word_desc", cmd : "mcePasteWord"}); + } + }); + + // Register plugin + tinymce.PluginManager.add("paste", tinymce.plugins.PastePlugin); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/js/pastetext.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/js/pastetext.js new file mode 100644 index 0000000..c524f9e --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/js/pastetext.js @@ -0,0 +1,36 @@ +tinyMCEPopup.requireLangPack(); + +var PasteTextDialog = { + init : function() { + this.resize(); + }, + + insert : function() { + var h = tinyMCEPopup.dom.encode(document.getElementById('content').value), lines; + + // Convert linebreaks into paragraphs + if (document.getElementById('linebreaks').checked) { + lines = h.split(/\r?\n/); + if (lines.length > 1) { + h = ''; + tinymce.each(lines, function(row) { + h += '<p>' + row + '</p>'; + }); + } + } + + tinyMCEPopup.editor.execCommand('mceInsertClipboardContent', false, {content : h}); + tinyMCEPopup.close(); + }, + + resize : function() { + var vp = tinyMCEPopup.dom.getViewPort(window), el; + + el = document.getElementById('content'); + + el.style.width = (vp.w - 20) + 'px'; + el.style.height = (vp.h - 90) + 'px'; + } +}; + +tinyMCEPopup.onInit.add(PasteTextDialog.init, PasteTextDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/js/pasteword.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/js/pasteword.js new file mode 100644 index 0000000..a52731c --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/js/pasteword.js @@ -0,0 +1,51 @@ +tinyMCEPopup.requireLangPack(); + +var PasteWordDialog = { + init : function() { + var ed = tinyMCEPopup.editor, el = document.getElementById('iframecontainer'), ifr, doc, css, cssHTML = ''; + + // Create iframe + el.innerHTML = '<iframe id="iframe" src="javascript:\'\';" frameBorder="0" style="border: 1px solid gray"></iframe>'; + ifr = document.getElementById('iframe'); + doc = ifr.contentWindow.document; + + // Force absolute CSS urls + css = [ed.baseURI.toAbsolute("themes/" + ed.settings.theme + "/skins/" + ed.settings.skin + "/content.css")]; + css = css.concat(tinymce.explode(ed.settings.content_css) || []); + tinymce.each(css, function(u) { + cssHTML += '<link href="' + ed.documentBaseURI.toAbsolute('' + u) + '" rel="stylesheet" type="text/css" />'; + }); + + // Write content into iframe + doc.open(); + doc.write('<html><head>' + cssHTML + '</head><body class="mceContentBody" spellcheck="false"></body></html>'); + doc.close(); + + doc.designMode = 'on'; + this.resize(); + + window.setTimeout(function() { + ifr.contentWindow.focus(); + }, 10); + }, + + insert : function() { + var h = document.getElementById('iframe').contentWindow.document.body.innerHTML; + + tinyMCEPopup.editor.execCommand('mceInsertClipboardContent', false, {content : h, wordContent : true}); + tinyMCEPopup.close(); + }, + + resize : function() { + var vp = tinyMCEPopup.dom.getViewPort(window), el; + + el = document.getElementById('iframe'); + + if (el) { + el.style.width = (vp.w - 20) + 'px'; + el.style.height = (vp.h - 90) + 'px'; + } + } +}; + +tinyMCEPopup.onInit.add(PasteWordDialog.init, PasteWordDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/de_dlg.js new file mode 100644 index 0000000..84b9bc6 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.paste_dlg',{"word_title":"Dr\u00fccken Sie auf Ihrer Tastatur Strg+V, um den Text einzuf\u00fcgen.","text_linebreaks":"Zeilenumbr\u00fcche beibehalten","text_title":"Dr\u00fccken Sie auf Ihrer Tastatur Strg+V, um den Text einzuf\u00fcgen."}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/en_dlg.js new file mode 100644 index 0000000..bc74daf --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.paste_dlg',{"word_title":"Use Ctrl+V on your keyboard to paste the text into the window.","text_linebreaks":"Keep Linebreaks","text_title":"Use Ctrl+V on your keyboard to paste the text into the window."}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/fr_dlg.js new file mode 100644 index 0000000..acc5d63 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.paste_dlg',{"word_title":"Utilisez CTRL+V sur votre clavier pour coller le texte dans la fen\u00eatre.","text_linebreaks":"Conserver les retours \u00e0 la ligne","text_title":"Utilisez CTRL+V sur votre clavier pour coller le texte dans la fen\u00eatre."}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/it_dlg.js new file mode 100644 index 0000000..f1b8dc7 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.paste_dlg',{"word_title":"Premere CTRL+V sulla tastiera per incollare il testo nella finestra.","text_linebreaks":"Mantieni interruzioni di riga","text_title":"Premere CTRL+V sulla tastiera per incollare il testo nella finestra."}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/pastetext.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/pastetext.htm new file mode 100644 index 0000000..b655945 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/pastetext.htm @@ -0,0 +1,27 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#paste.paste_text_desc}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/pastetext.js"></script> +</head> +<body onresize="PasteTextDialog.resize();" style="display:none; overflow:hidden;"> + <form name="source" onsubmit="return PasteTextDialog.insert();" action="#"> + <div style="float: left" class="title">{#paste.paste_text_desc}</div> + + <div style="float: right"> + <input type="checkbox" name="linebreaks" id="linebreaks" class="wordWrapCode" checked="checked" /><label for="linebreaks">{#paste_dlg.text_linebreaks}</label> + </div> + + <br style="clear: both" /> + + <div>{#paste_dlg.text_title}</div> + + <textarea id="content" name="content" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,mono; font-size: 12px;" dir="ltr" wrap="soft" class="mceFocus"></textarea> + + <div class="mceActionPanel"> + <input type="submit" name="insert" value="{#insert}" id="insert" /> + <input type="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" /> + </div> + </form> +</body> +</html> \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/pasteword.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/pasteword.htm new file mode 100644 index 0000000..0f6bb41 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/paste/pasteword.htm @@ -0,0 +1,21 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#paste.paste_word_desc}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/pasteword.js"></script> +</head> +<body onresize="PasteWordDialog.resize();" style="display:none; overflow:hidden;"> + <form name="source" onsubmit="return PasteWordDialog.insert();" action="#"> + <div class="title">{#paste.paste_word_desc}</div> + + <div>{#paste_dlg.word_title}</div> + + <div id="iframecontainer"></div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/editor_plugin.js new file mode 100644 index 0000000..507909c --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.Preview",{init:function(a,b){var d=this,c=tinymce.explode(a.settings.content_css);d.editor=a;tinymce.each(c,function(f,e){c[e]=a.documentBaseURI.toAbsolute(f)});a.addCommand("mcePreview",function(){a.windowManager.open({file:a.getParam("plugin_preview_pageurl",b+"/preview.html"),width:parseInt(a.getParam("plugin_preview_width","550")),height:parseInt(a.getParam("plugin_preview_height","600")),resizable:"yes",scrollbars:"yes",popup_css:c?c.join(","):a.baseURI.toAbsolute("themes/"+a.settings.theme+"/skins/"+a.settings.skin+"/content.css"),inline:a.getParam("plugin_preview_inline",1)},{base:a.documentBaseURI.getURI()})});a.addButton("preview",{title:"preview.preview_desc",cmd:"mcePreview"})},getInfo:function(){return{longname:"Preview",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/preview",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("preview",tinymce.plugins.Preview)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/editor_plugin_src.js new file mode 100644 index 0000000..80f00f0 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/editor_plugin_src.js @@ -0,0 +1,53 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.Preview', { + init : function(ed, url) { + var t = this, css = tinymce.explode(ed.settings.content_css); + + t.editor = ed; + + // Force absolute CSS urls + tinymce.each(css, function(u, k) { + css[k] = ed.documentBaseURI.toAbsolute(u); + }); + + ed.addCommand('mcePreview', function() { + ed.windowManager.open({ + file : ed.getParam("plugin_preview_pageurl", url + "/preview.html"), + width : parseInt(ed.getParam("plugin_preview_width", "550")), + height : parseInt(ed.getParam("plugin_preview_height", "600")), + resizable : "yes", + scrollbars : "yes", + popup_css : css ? css.join(',') : ed.baseURI.toAbsolute("themes/" + ed.settings.theme + "/skins/" + ed.settings.skin + "/content.css"), + inline : ed.getParam("plugin_preview_inline", 1) + }, { + base : ed.documentBaseURI.getURI() + }); + }); + + ed.addButton('preview', {title : 'preview.preview_desc', cmd : 'mcePreview'}); + }, + + getInfo : function() { + return { + longname : 'Preview', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/preview', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('preview', tinymce.plugins.Preview); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/example.html b/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/example.html new file mode 100644 index 0000000..b2c3d90 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/example.html @@ -0,0 +1,28 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<script language="javascript" src="../../tiny_mce_popup.js"></script> +<script type="text/javascript" src="jscripts/embed.js"></script> +<script type="text/javascript"> +tinyMCEPopup.onInit.add(function(ed) { + var dom = tinyMCEPopup.dom; + + // Load editor content_css + tinymce.each(ed.settings.content_css.split(','), function(u) { + dom.loadCSS(ed.documentBaseURI.toAbsolute(u)); + }); + + // Place contents inside div container + dom.setHTML('content', ed.getContent()); +}); +</script> +<title>Example of a custom preview page</title> +</head> +<body> + +Editor contents: <br /> +<div id="content"> +<!-- Gets filled with editor contents --> +</div> + +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/jscripts/embed.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/jscripts/embed.js new file mode 100644 index 0000000..f8dc810 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/jscripts/embed.js @@ -0,0 +1,73 @@ +/** + * This script contains embed functions for common plugins. This scripts are complety free to use for any purpose. + */ + +function writeFlash(p) { + writeEmbed( + 'D27CDB6E-AE6D-11cf-96B8-444553540000', + 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0', + 'application/x-shockwave-flash', + p + ); +} + +function writeShockWave(p) { + writeEmbed( + '166B1BCA-3F9C-11CF-8075-444553540000', + 'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0', + 'application/x-director', + p + ); +} + +function writeQuickTime(p) { + writeEmbed( + '02BF25D5-8C17-4B23-BC80-D3488ABDDC6B', + 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0', + 'video/quicktime', + p + ); +} + +function writeRealMedia(p) { + writeEmbed( + 'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA', + 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0', + 'audio/x-pn-realaudio-plugin', + p + ); +} + +function writeWindowsMedia(p) { + p.url = p.src; + writeEmbed( + '6BF52A52-394A-11D3-B153-00C04F79FAA6', + 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701', + 'application/x-mplayer2', + p + ); +} + +function writeEmbed(cls, cb, mt, p) { + var h = '', n; + + h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"'; + h += typeof(p.id) != "undefined" ? 'id="' + p.id + '"' : ''; + h += typeof(p.name) != "undefined" ? 'name="' + p.name + '"' : ''; + h += typeof(p.width) != "undefined" ? 'width="' + p.width + '"' : ''; + h += typeof(p.height) != "undefined" ? 'height="' + p.height + '"' : ''; + h += typeof(p.align) != "undefined" ? 'align="' + p.align + '"' : ''; + h += '>'; + + for (n in p) + h += '<param name="' + n + '" value="' + p[n] + '">'; + + h += '<embed type="' + mt + '"'; + + for (n in p) + h += n + '="' + p[n] + '" '; + + h += '></embed></object>'; + + document.write(h); +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/preview.html b/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/preview.html new file mode 100644 index 0000000..67e7b14 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/preview/preview.html @@ -0,0 +1,17 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<script type="text/javascript" src="../../tiny_mce_popup.js"></script> +<script type="text/javascript" src="jscripts/embed.js"></script> +<script type="text/javascript"><!-- +document.write('<base href="' + tinyMCEPopup.getWindowArg("base") + '">'); +// --> +</script> +<title>{#preview.preview_desc}</title> +</head> +<body id="content"> +<script type="text/javascript"> + document.write(tinyMCEPopup.editor.getContent()); +</script> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/print/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/print/editor_plugin.js new file mode 100644 index 0000000..b5b3a55 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/print/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.Print",{init:function(a,b){a.addCommand("mcePrint",function(){a.getWin().print()});a.addButton("print",{title:"print.print_desc",cmd:"mcePrint"})},getInfo:function(){return{longname:"Print",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/print",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("print",tinymce.plugins.Print)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/print/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/print/editor_plugin_src.js new file mode 100644 index 0000000..3933fe6 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/print/editor_plugin_src.js @@ -0,0 +1,34 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.Print', { + init : function(ed, url) { + ed.addCommand('mcePrint', function() { + ed.getWin().print(); + }); + + ed.addButton('print', {title : 'print.print_desc', cmd : 'mcePrint'}); + }, + + getInfo : function() { + return { + longname : 'Print', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/print', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('print', tinymce.plugins.Print); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/save/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/save/editor_plugin.js new file mode 100644 index 0000000..8e93996 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/save/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.Save",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceSave",c._save,c);a.addCommand("mceCancel",c._cancel,c);a.addButton("save",{title:"save.save_desc",cmd:"mceSave"});a.addButton("cancel",{title:"save.cancel_desc",cmd:"mceCancel"});a.onNodeChange.add(c._nodeChange,c);a.addShortcut("ctrl+s",a.getLang("save.save_desc"),"mceSave")},getInfo:function(){return{longname:"Save",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/save",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_nodeChange:function(b,a,c){var b=this.editor;if(b.getParam("save_enablewhendirty")){a.setDisabled("save",!b.isDirty());a.setDisabled("cancel",!b.isDirty())}},_save:function(){var c=this.editor,a,e,d,b;a=tinymce.DOM.get(c.id).form||tinymce.DOM.getParent(c.id,"form");if(c.getParam("save_enablewhendirty")&&!c.isDirty()){return}tinyMCE.triggerSave();if(e=c.getParam("save_onsavecallback")){if(c.execCallback("save_onsavecallback",c)){c.startContent=tinymce.trim(c.getContent({format:"raw"}));c.nodeChanged()}return}if(a){c.isNotDirty=true;if(a.onsubmit==null||a.onsubmit()!=false){a.submit()}c.nodeChanged()}else{c.windowManager.alert("Error: No form element found.")}},_cancel:function(){var a=this.editor,c,b=tinymce.trim(a.startContent);if(c=a.getParam("save_oncancelcallback")){a.execCallback("save_oncancelcallback",a);return}a.setContent(b);a.undoManager.clear();a.nodeChanged()}});tinymce.PluginManager.add("save",tinymce.plugins.Save)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/save/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/save/editor_plugin_src.js new file mode 100644 index 0000000..f5a3de8 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/save/editor_plugin_src.js @@ -0,0 +1,101 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.Save', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceSave', t._save, t); + ed.addCommand('mceCancel', t._cancel, t); + + // Register buttons + ed.addButton('save', {title : 'save.save_desc', cmd : 'mceSave'}); + ed.addButton('cancel', {title : 'save.cancel_desc', cmd : 'mceCancel'}); + + ed.onNodeChange.add(t._nodeChange, t); + ed.addShortcut('ctrl+s', ed.getLang('save.save_desc'), 'mceSave'); + }, + + getInfo : function() { + return { + longname : 'Save', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/save', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + _nodeChange : function(ed, cm, n) { + var ed = this.editor; + + if (ed.getParam('save_enablewhendirty')) { + cm.setDisabled('save', !ed.isDirty()); + cm.setDisabled('cancel', !ed.isDirty()); + } + }, + + // Private methods + + _save : function() { + var ed = this.editor, formObj, os, i, elementId; + + formObj = tinymce.DOM.get(ed.id).form || tinymce.DOM.getParent(ed.id, 'form'); + + if (ed.getParam("save_enablewhendirty") && !ed.isDirty()) + return; + + tinyMCE.triggerSave(); + + // Use callback instead + if (os = ed.getParam("save_onsavecallback")) { + if (ed.execCallback('save_onsavecallback', ed)) { + ed.startContent = tinymce.trim(ed.getContent({format : 'raw'})); + ed.nodeChanged(); + } + + return; + } + + if (formObj) { + ed.isNotDirty = true; + + if (formObj.onsubmit == null || formObj.onsubmit() != false) + formObj.submit(); + + ed.nodeChanged(); + } else + ed.windowManager.alert("Error: No form element found."); + }, + + _cancel : function() { + var ed = this.editor, os, h = tinymce.trim(ed.startContent); + + // Use callback instead + if (os = ed.getParam("save_oncancelcallback")) { + ed.execCallback('save_oncancelcallback', ed); + return; + } + + ed.setContent(h); + ed.undoManager.clear(); + ed.nodeChanged(); + } + }); + + // Register plugin + tinymce.PluginManager.add('save', tinymce.plugins.Save); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/css/searchreplace.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/css/searchreplace.css new file mode 100644 index 0000000..ecdf58c --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/css/searchreplace.css @@ -0,0 +1,6 @@ +.panel_wrapper {height:85px;} +.panel_wrapper div.current {height:85px;} + +/* IE */ +* html .panel_wrapper {height:100px;} +* html .panel_wrapper div.current {height:100px;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/editor_plugin.js new file mode 100644 index 0000000..165bc12 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.SearchReplacePlugin",{init:function(a,c){function b(d){window.focus();a.windowManager.open({file:c+"/searchreplace.htm",width:420+parseInt(a.getLang("searchreplace.delta_width",0)),height:170+parseInt(a.getLang("searchreplace.delta_height",0)),inline:1,auto_focus:0},{mode:d,search_string:a.selection.getContent({format:"text"}),plugin_url:c})}a.addCommand("mceSearch",function(){b("search")});a.addCommand("mceReplace",function(){b("replace")});a.addButton("search",{title:"searchreplace.search_desc",cmd:"mceSearch"});a.addButton("replace",{title:"searchreplace.replace_desc",cmd:"mceReplace"});a.addShortcut("ctrl+f","searchreplace.search_desc","mceSearch")},getInfo:function(){return{longname:"Search/Replace",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("searchreplace",tinymce.plugins.SearchReplacePlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js new file mode 100644 index 0000000..4c87e8f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/editor_plugin_src.js @@ -0,0 +1,61 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.SearchReplacePlugin', { + init : function(ed, url) { + function open(m) { + // Keep IE from writing out the f/r character to the editor + // instance while initializing a new dialog. See: #3131190 + window.focus(); + + ed.windowManager.open({ + file : url + '/searchreplace.htm', + width : 420 + parseInt(ed.getLang('searchreplace.delta_width', 0)), + height : 170 + parseInt(ed.getLang('searchreplace.delta_height', 0)), + inline : 1, + auto_focus : 0 + }, { + mode : m, + search_string : ed.selection.getContent({format : 'text'}), + plugin_url : url + }); + }; + + // Register commands + ed.addCommand('mceSearch', function() { + open('search'); + }); + + ed.addCommand('mceReplace', function() { + open('replace'); + }); + + // Register buttons + ed.addButton('search', {title : 'searchreplace.search_desc', cmd : 'mceSearch'}); + ed.addButton('replace', {title : 'searchreplace.replace_desc', cmd : 'mceReplace'}); + + ed.addShortcut('ctrl+f', 'searchreplace.search_desc', 'mceSearch'); + }, + + getInfo : function() { + return { + longname : 'Search/Replace', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('searchreplace', tinymce.plugins.SearchReplacePlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/js/searchreplace.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/js/searchreplace.js new file mode 100644 index 0000000..80284b9 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/js/searchreplace.js @@ -0,0 +1,142 @@ +tinyMCEPopup.requireLangPack(); + +var SearchReplaceDialog = { + init : function(ed) { + var t = this, f = document.forms[0], m = tinyMCEPopup.getWindowArg("mode"); + + t.switchMode(m); + + f[m + '_panel_searchstring'].value = tinyMCEPopup.getWindowArg("search_string"); + + // Focus input field + f[m + '_panel_searchstring'].focus(); + + mcTabs.onChange.add(function(tab_id, panel_id) { + t.switchMode(tab_id.substring(0, tab_id.indexOf('_'))); + }); + }, + + switchMode : function(m) { + var f, lm = this.lastMode; + + if (lm != m) { + f = document.forms[0]; + + if (lm) { + f[m + '_panel_searchstring'].value = f[lm + '_panel_searchstring'].value; + f[m + '_panel_backwardsu'].checked = f[lm + '_panel_backwardsu'].checked; + f[m + '_panel_backwardsd'].checked = f[lm + '_panel_backwardsd'].checked; + f[m + '_panel_casesensitivebox'].checked = f[lm + '_panel_casesensitivebox'].checked; + } + + mcTabs.displayTab(m + '_tab', m + '_panel'); + document.getElementById("replaceBtn").style.display = (m == "replace") ? "inline" : "none"; + document.getElementById("replaceAllBtn").style.display = (m == "replace") ? "inline" : "none"; + this.lastMode = m; + } + }, + + searchNext : function(a) { + var ed = tinyMCEPopup.editor, se = ed.selection, r = se.getRng(), f, m = this.lastMode, s, b, fl = 0, w = ed.getWin(), wm = ed.windowManager, fo = 0; + + // Get input + f = document.forms[0]; + s = f[m + '_panel_searchstring'].value; + b = f[m + '_panel_backwardsu'].checked; + ca = f[m + '_panel_casesensitivebox'].checked; + rs = f['replace_panel_replacestring'].value; + + if (tinymce.isIE) { + r = ed.getDoc().selection.createRange(); + } + + if (s == '') + return; + + function fix() { + // Correct Firefox graphics glitches + // TODO: Verify if this is actually needed any more, maybe it was for very old FF versions? + r = se.getRng().cloneRange(); + ed.getDoc().execCommand('SelectAll', false, null); + se.setRng(r); + }; + + function replace() { + ed.selection.setContent(rs); // Needs to be duplicated due to selection bug in IE + }; + + // IE flags + if (ca) + fl = fl | 4; + + switch (a) { + case 'all': + // Move caret to beginning of text + ed.execCommand('SelectAll'); + ed.selection.collapse(true); + + if (tinymce.isIE) { + ed.focus(); + r = ed.getDoc().selection.createRange(); + + while (r.findText(s, b ? -1 : 1, fl)) { + r.scrollIntoView(); + r.select(); + replace(); + fo = 1; + + if (b) { + r.moveEnd("character", -(rs.length)); // Otherwise will loop forever + } + } + + tinyMCEPopup.storeSelection(); + } else { + while (w.find(s, ca, b, false, false, false, false)) { + replace(); + fo = 1; + } + } + + if (fo) + tinyMCEPopup.alert(ed.getLang('searchreplace_dlg.allreplaced')); + else + tinyMCEPopup.alert(ed.getLang('searchreplace_dlg.notfound')); + + return; + + case 'current': + if (!ed.selection.isCollapsed()) + replace(); + + break; + } + + se.collapse(b); + r = se.getRng(); + + // Whats the point + if (!s) + return; + + if (tinymce.isIE) { + ed.focus(); + r = ed.getDoc().selection.createRange(); + + if (r.findText(s, b ? -1 : 1, fl)) { + r.scrollIntoView(); + r.select(); + } else + tinyMCEPopup.alert(ed.getLang('searchreplace_dlg.notfound')); + + tinyMCEPopup.storeSelection(); + } else { + if (!w.find(s, ca, b, false, false, false, false)) + tinyMCEPopup.alert(ed.getLang('searchreplace_dlg.notfound')); + else + fix(); + } + } +}; + +tinyMCEPopup.onInit.add(SearchReplaceDialog.init, SearchReplaceDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/de_dlg.js new file mode 100644 index 0000000..7c40acd --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.searchreplace_dlg',{findwhat:"Zu suchender Text",replacewith:"Ersetzen durch",direction:"Suchrichtung",up:"Aufw\u00e4rts",down:"Abw\u00e4rts",mcase:"Gro\u00df-/Kleinschreibung beachten",findnext:"Weitersuchen",allreplaced:"Alle Vorkommen der Zeichenkette wurden ersetzt.","searchnext_desc":"Weitersuchen",notfound:"Die Suche ist am Ende angelangt. Die Zeichenkette konnte nicht gefunden werden.","search_title":"Suchen","replace_title":"Suchen/Ersetzen",replaceall:"Alle ersetzen",replace:"Ersetzen"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/en_dlg.js new file mode 100644 index 0000000..8a65900 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.searchreplace_dlg',{findwhat:"Find What",replacewith:"Replace with",direction:"Direction",up:"Up",down:"Down",mcase:"Match Case",findnext:"Find Next",allreplaced:"All occurrences of the search string were replaced.","searchnext_desc":"Find Again",notfound:"The search has been completed. The search string could not be found.","search_title":"Find","replace_title":"Find/Replace",replaceall:"Replace All",replace:"Replace"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/fr_dlg.js new file mode 100644 index 0000000..707b5c2 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.searchreplace_dlg',{findwhat:"Rechercher ceci",replacewith:"Remplacer par",direction:"Direction",up:"Vers le haut",down:"Vers le bas",mcase:"Sensible \u00e0 la casse",findnext:"Rechercher le suivant",allreplaced:"Toutes les occurrences de la cha\u00eene recherch\u00e9e ont \u00e9t\u00e9 remplac\u00e9es.","searchnext_desc":"Suivant",notfound:"La recherche est termin\u00e9e. La cha\u00eene recherch\u00e9e n\'a pas \u00e9t\u00e9 trouv\u00e9e.","search_title":"Rechercher","replace_title":"Rechercher / remplacer",replaceall:"Tout remplacer",replace:"Remplacer"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/it_dlg.js new file mode 100644 index 0000000..da34e5d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.searchreplace_dlg',{findwhat:"Trova:",replacewith:"Sostituisci con:",direction:"Direzione",up:"Avanti",down:"Indietro",mcase:"Maiuscole/minuscole",findnext:"Trova succ.",allreplaced:"Tutte le occorrenze del criterio di ricerca sono state sostituite.","searchnext_desc":"Trova successivo",notfound:"Ricerca completata. Nessun risultato trovato.","search_title":"Trova","replace_title":"Trova/Sostituisci",replaceall:"Sost. tutto",replace:"Sostituisci"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/searchreplace.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/searchreplace.htm new file mode 100644 index 0000000..5a22d8a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/searchreplace/searchreplace.htm @@ -0,0 +1,100 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#searchreplace_dlg.replace_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="js/searchreplace.js"></script> + <link rel="stylesheet" type="text/css" href="css/searchreplace.css" /> +</head> +<body style="display:none;" role="application" aria-labelledby="app_title"> +<span id="app_title" style="display:none">{#searchreplace_dlg.replace_title}</span> +<form onsubmit="SearchReplaceDialog.searchNext('none');return false;" action="#"> + <div class="tabs"> + <ul> + <li id="search_tab" aria-controls="search_panel"><span><a href="javascript:SearchReplaceDialog.switchMode('search');" onmousedown="return false;">{#searchreplace.search_desc}</a></span></li> + <li id="replace_tab" aria-controls="replace_panel"><span><a href="javascript:SearchReplaceDialog.switchMode('replace');" onmousedown="return false;">{#searchreplace_dlg.replace}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="search_panel" class="panel"> + <table role="presentation" border="0" cellspacing="0" cellpadding="2"> + <tr> + <td><label for="search_panel_searchstring">{#searchreplace_dlg.findwhat}</label></td> + <td><input type="text" id="search_panel_searchstring" name="search_panel_searchstring" style="width: 200px" aria-required="true" /></td> + </tr> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0" class="direction"> + <tr role="group" aria-labelledby="search_panel_backwards_label"> + <td><label id="search_panel_backwards_label">{#searchreplace_dlg.direction}</label></td> + <td><input id="search_panel_backwardsu" name="search_panel_backwards" class="radio" type="radio" /></td> + <td><label for="search_panel_backwardsu">{#searchreplace_dlg.up}</label></td> + <td><input id="search_panel_backwardsd" name="search_panel_backwards" class="radio" type="radio" checked="checked" /></td> + <td><label for="search_panel_backwardsd">{#searchreplace_dlg.down}</label></td> + </tr> + </table> + </td> + </tr> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="search_panel_casesensitivebox" name="search_panel_casesensitivebox" class="checkbox" type="checkbox" /></td> + <td><label for="search_panel_casesensitivebox">{#searchreplace_dlg.mcase}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </div> + + <div id="replace_panel" class="panel"> + <table role="presentation" border="0" cellspacing="0" cellpadding="2"> + <tr> + <td><label for="replace_panel_searchstring">{#searchreplace_dlg.findwhat}</label></td> + <td><input type="text" id="replace_panel_searchstring" name="replace_panel_searchstring" style="width: 200px" aria-required="true" /></td> + </tr> + <tr> + <td><label for="replace_panel_replacestring">{#searchreplace_dlg.replacewith}</label></td> + <td><input type="text" id="replace_panel_replacestring" name="replace_panel_replacestring" style="width: 200px" aria-required="true" /></td> + </tr> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0" class="direction"> + <tr role="group" aria-labelledby="replace_panel_dir_label"> + <td><label id="replace_panel_dir_label">{#searchreplace_dlg.direction}</label></td> + <td><input id="replace_panel_backwardsu" name="replace_panel_backwards" class="radio" type="radio" /></td> + <td><label for="replace_panel_backwardsu">{#searchreplace_dlg.up}</label></td> + <td><input id="replace_panel_backwardsd" name="replace_panel_backwards" class="radio" type="radio" checked="checked" /></td> + <td><label for="replace_panel_backwardsd">{#searchreplace_dlg.down}</label></td> + </tr> + </table> + </td> + </tr> + <tr> + <td colspan="2"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="replace_panel_casesensitivebox" name="replace_panel_casesensitivebox" class="checkbox" type="checkbox" /></td> + <td><label for="replace_panel_casesensitivebox">{#searchreplace_dlg.mcase}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </div> + + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#searchreplace_dlg.findnext}" /> + <input type="button" class="button" id="replaceBtn" name="replaceBtn" value="{#searchreplace_dlg.replace}" onclick="SearchReplaceDialog.searchNext('current');" /> + <input type="button" class="button" id="replaceAllBtn" name="replaceAllBtn" value="{#searchreplace_dlg.replaceall}" onclick="SearchReplaceDialog.searchNext('all');" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/css/content.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/css/content.css new file mode 100644 index 0000000..24efa02 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/css/content.css @@ -0,0 +1 @@ +.mceItemHiddenSpellWord {background:url(../img/wline.gif) repeat-x bottom left; cursor:default;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/editor_plugin.js new file mode 100644 index 0000000..71fbb68 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.util.JSONRequest,c=tinymce.each,b=tinymce.DOM;tinymce.create("tinymce.plugins.SpellcheckerPlugin",{getInfo:function(){return{longname:"Spellchecker",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker",version:tinymce.majorVersion+"."+tinymce.minorVersion}},init:function(e,f){var g=this,d;g.url=f;g.editor=e;g.rpcUrl=e.getParam("spellchecker_rpc_url","{backend}");if(g.rpcUrl=="{backend}"){if(tinymce.isIE){return}g.hasSupport=true;e.onContextMenu.addToTop(function(h,i){if(g.active){return false}})}e.addCommand("mceSpellCheck",function(){if(g.rpcUrl=="{backend}"){g.editor.getBody().spellcheck=g.active=!g.active;return}if(!g.active){e.setProgressState(1);g._sendRPC("checkWords",[g.selectedLang,g._getWords()],function(h){if(h.length>0){g.active=1;g._markWords(h);e.setProgressState(0);e.nodeChanged()}else{e.setProgressState(0);if(e.getParam("spellchecker_report_no_misspellings",true)){e.windowManager.alert("spellchecker.no_mpell")}}})}else{g._done()}});if(e.settings.content_css!==false){e.contentCSS.push(f+"/css/content.css")}e.onClick.add(g._showMenu,g);e.onContextMenu.add(g._showMenu,g);e.onBeforeGetContent.add(function(){if(g.active){g._removeWords()}});e.onNodeChange.add(function(i,h){h.setActive("spellchecker",g.active)});e.onSetContent.add(function(){g._done()});e.onBeforeGetContent.add(function(){g._done()});e.onBeforeExecCommand.add(function(h,i){if(i=="mceFullScreen"){g._done()}});g.languages={};c(e.getParam("spellchecker_languages","+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv","hash"),function(i,h){if(h.indexOf("+")===0){h=h.substring(1);g.selectedLang=i}g.languages[h]=i})},createControl:function(h,d){var f=this,g,e=f.editor;if(h=="spellchecker"){if(f.rpcUrl=="{backend}"){if(f.hasSupport){g=d.createButton(h,{title:"spellchecker.desc",cmd:"mceSpellCheck",scope:f})}return g}g=d.createSplitButton(h,{title:"spellchecker.desc",cmd:"mceSpellCheck",scope:f});g.onRenderMenu.add(function(j,i){i.add({title:"spellchecker.langs","class":"mceMenuItemTitle"}).setDisabled(1);c(f.languages,function(n,m){var p={icon:1},l;p.onclick=function(){if(n==f.selectedLang){return}l.setSelected(1);f.selectedItem.setSelected(0);f.selectedItem=l;f.selectedLang=n};p.title=m;l=i.add(p);l.setSelected(n==f.selectedLang);if(n==f.selectedLang){f.selectedItem=l}})});return g}},_walk:function(i,g){var h=this.editor.getDoc(),e;if(h.createTreeWalker){e=h.createTreeWalker(i,NodeFilter.SHOW_TEXT,null,false);while((i=e.nextNode())!=null){g.call(this,i)}}else{tinymce.walk(i,g,"childNodes")}},_getSeparators:function(){var e="",d,f=this.editor.getParam("spellchecker_word_separator_chars",'\\s!"#$%&()*+,-./:;<=>?@[]^_{|}§©«®±¶·¸»¼½¾¿×÷¤\u201d\u201c');for(d=0;d<f.length;d++){e+="\\"+f.charAt(d)}return e},_getWords:function(){var e=this.editor,g=[],d="",f={},h=[];this._walk(e.getBody(),function(i){if(i.nodeType==3){d+=i.nodeValue+" "}});if(e.getParam("spellchecker_word_pattern")){h=d.match("("+e.getParam("spellchecker_word_pattern")+")","gi")}else{d=d.replace(new RegExp("([0-9]|["+this._getSeparators()+"])","g")," ");d=tinymce.trim(d.replace(/(\s+)/g," "));h=d.split(" ")}c(h,function(i){if(!f[i]){g.push(i);f[i]=1}});return g},_removeWords:function(e){var f=this.editor,h=f.dom,g=f.selection,d=g.getBookmark();c(h.select("span").reverse(),function(i){if(i&&(h.hasClass(i,"mceItemHiddenSpellWord")||h.hasClass(i,"mceItemHidden"))){if(!e||h.decode(i.innerHTML)==e){h.remove(i,1)}}});g.moveToBookmark(d)},_markWords:function(l){var g=this.editor,f=g.dom,j=g.getDoc(),h=g.selection,i=h.getBookmark(),d=[],k=l.join("|"),m=this._getSeparators(),e=new RegExp("(^|["+m+"])("+k+")(?=["+m+"]|$)","g");this._walk(g.getBody(),function(o){if(o.nodeType==3){d.push(o)}});c(d,function(t){var r,q,o,s,p=t.nodeValue;if(e.test(p)){p=f.encode(p);q=f.create("span",{"class":"mceItemHidden"});if(tinymce.isIE){p=p.replace(e,"$1<mcespell>$2</mcespell>");while((s=p.indexOf("<mcespell>"))!=-1){o=p.substring(0,s);if(o.length){r=j.createTextNode(f.decode(o));q.appendChild(r)}p=p.substring(s+10);s=p.indexOf("</mcespell>");o=p.substring(0,s);p=p.substring(s+11);q.appendChild(f.create("span",{"class":"mceItemHiddenSpellWord"},o))}if(p.length){r=j.createTextNode(f.decode(p));q.appendChild(r)}}else{q.innerHTML=p.replace(e,'$1<span class="mceItemHiddenSpellWord">$2</span>')}f.replace(q,t)}});h.moveToBookmark(i)},_showMenu:function(h,j){var i=this,h=i.editor,d=i._menu,l,k=h.dom,g=k.getViewPort(h.getWin()),f=j.target;j=0;if(!d){d=h.controlManager.createDropMenu("spellcheckermenu",{"class":"mceNoIcons"});i._menu=d}if(k.hasClass(f,"mceItemHiddenSpellWord")){d.removeAll();d.add({title:"spellchecker.wait","class":"mceMenuItemTitle"}).setDisabled(1);i._sendRPC("getSuggestions",[i.selectedLang,k.decode(f.innerHTML)],function(m){var e;d.removeAll();if(m.length>0){d.add({title:"spellchecker.sug","class":"mceMenuItemTitle"}).setDisabled(1);c(m,function(n){d.add({title:n,onclick:function(){k.replace(h.getDoc().createTextNode(n),f);i._checkDone()}})});d.addSeparator()}else{d.add({title:"spellchecker.no_sug","class":"mceMenuItemTitle"}).setDisabled(1)}if(h.getParam("show_ignore_words",true)){e=i.editor.getParam("spellchecker_enable_ignore_rpc","");d.add({title:"spellchecker.ignore_word",onclick:function(){var n=f.innerHTML;k.remove(f,1);i._checkDone();if(e){h.setProgressState(1);i._sendRPC("ignoreWord",[i.selectedLang,n],function(o){h.setProgressState(0)})}}});d.add({title:"spellchecker.ignore_words",onclick:function(){var n=f.innerHTML;i._removeWords(k.decode(n));i._checkDone();if(e){h.setProgressState(1);i._sendRPC("ignoreWords",[i.selectedLang,n],function(o){h.setProgressState(0)})}}})}if(i.editor.getParam("spellchecker_enable_learn_rpc")){d.add({title:"spellchecker.learn_word",onclick:function(){var n=f.innerHTML;k.remove(f,1);i._checkDone();h.setProgressState(1);i._sendRPC("learnWord",[i.selectedLang,n],function(o){h.setProgressState(0)})}})}d.update()});l=b.getPos(h.getContentAreaContainer());d.settings.offset_x=l.x;d.settings.offset_y=l.y;h.selection.select(f);l=k.getPos(f);d.showMenu(l.x,l.y+f.offsetHeight-g.y);return tinymce.dom.Event.cancel(j)}else{d.hideMenu()}},_checkDone:function(){var e=this,d=e.editor,g=d.dom,f;c(g.select("span"),function(h){if(h&&g.hasClass(h,"mceItemHiddenSpellWord")){f=true;return false}});if(!f){e._done()}},_done:function(){var d=this,e=d.active;if(d.active){d.active=0;d._removeWords();if(d._menu){d._menu.hideMenu()}if(e){d.editor.nodeChanged()}}},_sendRPC:function(e,g,d){var f=this;a.sendRPC({url:f.rpcUrl,method:e,params:g,success:d,error:function(i,h){f.editor.setProgressState(0);f.editor.windowManager.alert(i.errstr||("Error response: "+h.responseText))}})}});tinymce.PluginManager.add("spellchecker",tinymce.plugins.SpellcheckerPlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/editor_plugin_src.js new file mode 100644 index 0000000..fb32af4 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/editor_plugin_src.js @@ -0,0 +1,436 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var JSONRequest = tinymce.util.JSONRequest, each = tinymce.each, DOM = tinymce.DOM; + + tinymce.create('tinymce.plugins.SpellcheckerPlugin', { + getInfo : function() { + return { + longname : 'Spellchecker', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + init : function(ed, url) { + var t = this, cm; + + t.url = url; + t.editor = ed; + t.rpcUrl = ed.getParam("spellchecker_rpc_url", "{backend}"); + + if (t.rpcUrl == '{backend}') { + // Sniff if the browser supports native spellchecking (Don't know of a better way) + if (tinymce.isIE) + return; + + t.hasSupport = true; + + // Disable the context menu when spellchecking is active + ed.onContextMenu.addToTop(function(ed, e) { + if (t.active) + return false; + }); + } + + // Register commands + ed.addCommand('mceSpellCheck', function() { + if (t.rpcUrl == '{backend}') { + // Enable/disable native spellchecker + t.editor.getBody().spellcheck = t.active = !t.active; + return; + } + + if (!t.active) { + ed.setProgressState(1); + t._sendRPC('checkWords', [t.selectedLang, t._getWords()], function(r) { + if (r.length > 0) { + t.active = 1; + t._markWords(r); + ed.setProgressState(0); + ed.nodeChanged(); + } else { + ed.setProgressState(0); + + if (ed.getParam('spellchecker_report_no_misspellings', true)) + ed.windowManager.alert('spellchecker.no_mpell'); + } + }); + } else + t._done(); + }); + + if (ed.settings.content_css !== false) + ed.contentCSS.push(url + '/css/content.css'); + + ed.onClick.add(t._showMenu, t); + ed.onContextMenu.add(t._showMenu, t); + ed.onBeforeGetContent.add(function() { + if (t.active) + t._removeWords(); + }); + + ed.onNodeChange.add(function(ed, cm) { + cm.setActive('spellchecker', t.active); + }); + + ed.onSetContent.add(function() { + t._done(); + }); + + ed.onBeforeGetContent.add(function() { + t._done(); + }); + + ed.onBeforeExecCommand.add(function(ed, cmd) { + if (cmd == 'mceFullScreen') + t._done(); + }); + + // Find selected language + t.languages = {}; + each(ed.getParam('spellchecker_languages', '+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv', 'hash'), function(v, k) { + if (k.indexOf('+') === 0) { + k = k.substring(1); + t.selectedLang = v; + } + + t.languages[k] = v; + }); + }, + + createControl : function(n, cm) { + var t = this, c, ed = t.editor; + + if (n == 'spellchecker') { + // Use basic button if we use the native spellchecker + if (t.rpcUrl == '{backend}') { + // Create simple toggle button if we have native support + if (t.hasSupport) + c = cm.createButton(n, {title : 'spellchecker.desc', cmd : 'mceSpellCheck', scope : t}); + + return c; + } + + c = cm.createSplitButton(n, {title : 'spellchecker.desc', cmd : 'mceSpellCheck', scope : t}); + + c.onRenderMenu.add(function(c, m) { + m.add({title : 'spellchecker.langs', 'class' : 'mceMenuItemTitle'}).setDisabled(1); + each(t.languages, function(v, k) { + var o = {icon : 1}, mi; + + o.onclick = function() { + if (v == t.selectedLang) { + return; + } + mi.setSelected(1); + t.selectedItem.setSelected(0); + t.selectedItem = mi; + t.selectedLang = v; + }; + + o.title = k; + mi = m.add(o); + mi.setSelected(v == t.selectedLang); + + if (v == t.selectedLang) + t.selectedItem = mi; + }) + }); + + return c; + } + }, + + // Internal functions + + _walk : function(n, f) { + var d = this.editor.getDoc(), w; + + if (d.createTreeWalker) { + w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false); + + while ((n = w.nextNode()) != null) + f.call(this, n); + } else + tinymce.walk(n, f, 'childNodes'); + }, + + _getSeparators : function() { + var re = '', i, str = this.editor.getParam('spellchecker_word_separator_chars', '\\s!"#$%&()*+,-./:;<=>?@[\]^_{|}§©«®±¶·¸»¼½¾¿×÷¤\u201d\u201c'); + + // Build word separator regexp + for (i=0; i<str.length; i++) + re += '\\' + str.charAt(i); + + return re; + }, + + _getWords : function() { + var ed = this.editor, wl = [], tx = '', lo = {}, rawWords = []; + + // Get area text + this._walk(ed.getBody(), function(n) { + if (n.nodeType == 3) + tx += n.nodeValue + ' '; + }); + + // split the text up into individual words + if (ed.getParam('spellchecker_word_pattern')) { + // look for words that match the pattern + rawWords = tx.match('(' + ed.getParam('spellchecker_word_pattern') + ')', 'gi'); + } else { + // Split words by separator + tx = tx.replace(new RegExp('([0-9]|[' + this._getSeparators() + '])', 'g'), ' '); + tx = tinymce.trim(tx.replace(/(\s+)/g, ' ')); + rawWords = tx.split(' '); + } + + // Build word array and remove duplicates + each(rawWords, function(v) { + if (!lo[v]) { + wl.push(v); + lo[v] = 1; + } + }); + + return wl; + }, + + _removeWords : function(w) { + var ed = this.editor, dom = ed.dom, se = ed.selection, b = se.getBookmark(); + + each(dom.select('span').reverse(), function(n) { + if (n && (dom.hasClass(n, 'mceItemHiddenSpellWord') || dom.hasClass(n, 'mceItemHidden'))) { + if (!w || dom.decode(n.innerHTML) == w) + dom.remove(n, 1); + } + }); + + se.moveToBookmark(b); + }, + + _markWords : function(wl) { + var ed = this.editor, dom = ed.dom, doc = ed.getDoc(), se = ed.selection, b = se.getBookmark(), nl = [], + w = wl.join('|'), re = this._getSeparators(), rx = new RegExp('(^|[' + re + '])(' + w + ')(?=[' + re + ']|$)', 'g'); + + // Collect all text nodes + this._walk(ed.getBody(), function(n) { + if (n.nodeType == 3) { + nl.push(n); + } + }); + + // Wrap incorrect words in spans + each(nl, function(n) { + var node, elem, txt, pos, v = n.nodeValue; + + if (rx.test(v)) { + // Encode the content + v = dom.encode(v); + // Create container element + elem = dom.create('span', {'class' : 'mceItemHidden'}); + + // Following code fixes IE issues by creating text nodes + // using DOM methods instead of innerHTML. + // Bug #3124: <PRE> elements content is broken after spellchecking. + // Bug #1408: Preceding whitespace characters are removed + // @TODO: I'm not sure that both are still issues on IE9. + if (tinymce.isIE) { + // Enclose mispelled words with temporal tag + v = v.replace(rx, '$1<mcespell>$2</mcespell>'); + // Loop over the content finding mispelled words + while ((pos = v.indexOf('<mcespell>')) != -1) { + // Add text node for the content before the word + txt = v.substring(0, pos); + if (txt.length) { + node = doc.createTextNode(dom.decode(txt)); + elem.appendChild(node); + } + v = v.substring(pos+10); + pos = v.indexOf('</mcespell>'); + txt = v.substring(0, pos); + v = v.substring(pos+11); + // Add span element for the word + elem.appendChild(dom.create('span', {'class' : 'mceItemHiddenSpellWord'}, txt)); + } + // Add text node for the rest of the content + if (v.length) { + node = doc.createTextNode(dom.decode(v)); + elem.appendChild(node); + } + } else { + // Other browsers preserve whitespace characters on innerHTML usage + elem.innerHTML = v.replace(rx, '$1<span class="mceItemHiddenSpellWord">$2</span>'); + } + + // Finally, replace the node with the container + dom.replace(elem, n); + } + }); + + se.moveToBookmark(b); + }, + + _showMenu : function(ed, e) { + var t = this, ed = t.editor, m = t._menu, p1, dom = ed.dom, vp = dom.getViewPort(ed.getWin()), wordSpan = e.target; + + e = 0; // Fixes IE memory leak + + if (!m) { + m = ed.controlManager.createDropMenu('spellcheckermenu', {'class' : 'mceNoIcons'}); + t._menu = m; + } + + if (dom.hasClass(wordSpan, 'mceItemHiddenSpellWord')) { + m.removeAll(); + m.add({title : 'spellchecker.wait', 'class' : 'mceMenuItemTitle'}).setDisabled(1); + + t._sendRPC('getSuggestions', [t.selectedLang, dom.decode(wordSpan.innerHTML)], function(r) { + var ignoreRpc; + + m.removeAll(); + + if (r.length > 0) { + m.add({title : 'spellchecker.sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1); + each(r, function(v) { + m.add({title : v, onclick : function() { + dom.replace(ed.getDoc().createTextNode(v), wordSpan); + t._checkDone(); + }}); + }); + + m.addSeparator(); + } else + m.add({title : 'spellchecker.no_sug', 'class' : 'mceMenuItemTitle'}).setDisabled(1); + + if (ed.getParam('show_ignore_words', true)) { + ignoreRpc = t.editor.getParam("spellchecker_enable_ignore_rpc", ''); + m.add({ + title : 'spellchecker.ignore_word', + onclick : function() { + var word = wordSpan.innerHTML; + + dom.remove(wordSpan, 1); + t._checkDone(); + + // tell the server if we need to + if (ignoreRpc) { + ed.setProgressState(1); + t._sendRPC('ignoreWord', [t.selectedLang, word], function(r) { + ed.setProgressState(0); + }); + } + } + }); + + m.add({ + title : 'spellchecker.ignore_words', + onclick : function() { + var word = wordSpan.innerHTML; + + t._removeWords(dom.decode(word)); + t._checkDone(); + + // tell the server if we need to + if (ignoreRpc) { + ed.setProgressState(1); + t._sendRPC('ignoreWords', [t.selectedLang, word], function(r) { + ed.setProgressState(0); + }); + } + } + }); + } + + if (t.editor.getParam("spellchecker_enable_learn_rpc")) { + m.add({ + title : 'spellchecker.learn_word', + onclick : function() { + var word = wordSpan.innerHTML; + + dom.remove(wordSpan, 1); + t._checkDone(); + + ed.setProgressState(1); + t._sendRPC('learnWord', [t.selectedLang, word], function(r) { + ed.setProgressState(0); + }); + } + }); + } + + m.update(); + }); + + p1 = DOM.getPos(ed.getContentAreaContainer()); + m.settings.offset_x = p1.x; + m.settings.offset_y = p1.y; + + ed.selection.select(wordSpan); + p1 = dom.getPos(wordSpan); + m.showMenu(p1.x, p1.y + wordSpan.offsetHeight - vp.y); + + return tinymce.dom.Event.cancel(e); + } else + m.hideMenu(); + }, + + _checkDone : function() { + var t = this, ed = t.editor, dom = ed.dom, o; + + each(dom.select('span'), function(n) { + if (n && dom.hasClass(n, 'mceItemHiddenSpellWord')) { + o = true; + return false; + } + }); + + if (!o) + t._done(); + }, + + _done : function() { + var t = this, la = t.active; + + if (t.active) { + t.active = 0; + t._removeWords(); + + if (t._menu) + t._menu.hideMenu(); + + if (la) + t.editor.nodeChanged(); + } + }, + + _sendRPC : function(m, p, cb) { + var t = this; + + JSONRequest.sendRPC({ + url : t.rpcUrl, + method : m, + params : p, + success : cb, + error : function(e, x) { + t.editor.setProgressState(0); + t.editor.windowManager.alert(e.errstr || ('Error response: ' + x.responseText)); + } + }); + } + }); + + // Register plugin + tinymce.PluginManager.add('spellchecker', tinymce.plugins.SpellcheckerPlugin); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/img/wline.gif b/src/static/org_glizy/assets/js/tiny_mce/plugins/spellchecker/img/wline.gif new file mode 100644 index 0000000000000000000000000000000000000000..7d0a4dbca03cc13177a359a5f175dda819fdf464 GIT binary patch literal 46 ycmZ?wbhEHbWMN=tXkcXcqowu#|9{1wEQ|~cj0`#qKmd|qU}ANVOOs?}um%7FLkRf* literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/style/css/props.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/css/props.css new file mode 100644 index 0000000..eb1f264 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/css/props.css @@ -0,0 +1,13 @@ +#text_font {width:250px;} +#text_size {width:70px;} +.mceAddSelectValue {background:#DDD;} +select, #block_text_indent, #box_width, #box_height, #box_padding_top, #box_padding_right, #box_padding_bottom, #box_padding_left {width:70px;} +#box_margin_top, #box_margin_right, #box_margin_bottom, #box_margin_left, #positioning_width, #positioning_height, #positioning_zindex {width:70px;} +#positioning_placement_top, #positioning_placement_right, #positioning_placement_bottom, #positioning_placement_left {width:70px;} +#positioning_clip_top, #positioning_clip_right, #positioning_clip_bottom, #positioning_clip_left {width:70px;} +.panel_wrapper div.current {padding-top:10px;height:230px;} +.delim {border-left:1px solid gray;} +.tdelim {border-bottom:1px solid gray;} +#block_display {width:145px;} +#list_type {width:115px;} +.disabled {background:#EEE;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/style/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/editor_plugin.js new file mode 100644 index 0000000..cab2153 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.StylePlugin",{init:function(a,b){a.addCommand("mceStyleProps",function(){a.windowManager.open({file:b+"/props.htm",width:480+parseInt(a.getLang("style.delta_width",0)),height:320+parseInt(a.getLang("style.delta_height",0)),inline:1},{plugin_url:b,style_text:a.selection.getNode().style.cssText})});a.addCommand("mceSetElementStyle",function(d,c){if(e=a.selection.getNode()){a.dom.setAttrib(e,"style",c);a.execCommand("mceRepaint")}});a.onNodeChange.add(function(d,c,f){c.setDisabled("styleprops",f.nodeName==="BODY")});a.addButton("styleprops",{title:"style.desc",cmd:"mceStyleProps"})},getInfo:function(){return{longname:"Style",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/style",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("style",tinymce.plugins.StylePlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/style/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/editor_plugin_src.js new file mode 100644 index 0000000..5f7755f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/editor_plugin_src.js @@ -0,0 +1,55 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.StylePlugin', { + init : function(ed, url) { + // Register commands + ed.addCommand('mceStyleProps', function() { + ed.windowManager.open({ + file : url + '/props.htm', + width : 480 + parseInt(ed.getLang('style.delta_width', 0)), + height : 320 + parseInt(ed.getLang('style.delta_height', 0)), + inline : 1 + }, { + plugin_url : url, + style_text : ed.selection.getNode().style.cssText + }); + }); + + ed.addCommand('mceSetElementStyle', function(ui, v) { + if (e = ed.selection.getNode()) { + ed.dom.setAttrib(e, 'style', v); + ed.execCommand('mceRepaint'); + } + }); + + ed.onNodeChange.add(function(ed, cm, n) { + cm.setDisabled('styleprops', n.nodeName === 'BODY'); + }); + + // Register buttons + ed.addButton('styleprops', {title : 'style.desc', cmd : 'mceStyleProps'}); + }, + + getInfo : function() { + return { + longname : 'Style', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/style', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('style', tinymce.plugins.StylePlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/style/js/props.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/js/props.js new file mode 100644 index 0000000..6800a9a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/js/props.js @@ -0,0 +1,635 @@ +tinyMCEPopup.requireLangPack(); + +var defaultFonts = "" + + "Arial, Helvetica, sans-serif=Arial, Helvetica, sans-serif;" + + "Times New Roman, Times, serif=Times New Roman, Times, serif;" + + "Courier New, Courier, mono=Courier New, Courier, mono;" + + "Times New Roman, Times, serif=Times New Roman, Times, serif;" + + "Georgia, Times New Roman, Times, serif=Georgia, Times New Roman, Times, serif;" + + "Verdana, Arial, Helvetica, sans-serif=Verdana, Arial, Helvetica, sans-serif;" + + "Geneva, Arial, Helvetica, sans-serif=Geneva, Arial, Helvetica, sans-serif"; + +var defaultSizes = "9;10;12;14;16;18;24;xx-small;x-small;small;medium;large;x-large;xx-large;smaller;larger"; +var defaultMeasurement = "+pixels=px;points=pt;inches=in;centimetres=cm;millimetres=mm;picas=pc;ems=em;exs=ex;%"; +var defaultSpacingMeasurement = "pixels=px;points=pt;inches=in;centimetres=cm;millimetres=mm;picas=pc;+ems=em;exs=ex;%"; +var defaultIndentMeasurement = "pixels=px;+points=pt;inches=in;centimetres=cm;millimetres=mm;picas=pc;ems=em;exs=ex;%"; +var defaultWeight = "normal;bold;bolder;lighter;100;200;300;400;500;600;700;800;900"; +var defaultTextStyle = "normal;italic;oblique"; +var defaultVariant = "normal;small-caps"; +var defaultLineHeight = "normal"; +var defaultAttachment = "fixed;scroll"; +var defaultRepeat = "no-repeat;repeat;repeat-x;repeat-y"; +var defaultPosH = "left;center;right"; +var defaultPosV = "top;center;bottom"; +var defaultVAlign = "baseline;sub;super;top;text-top;middle;bottom;text-bottom"; +var defaultDisplay = "inline;block;list-item;run-in;compact;marker;table;inline-table;table-row-group;table-header-group;table-footer-group;table-row;table-column-group;table-column;table-cell;table-caption;none"; +var defaultBorderStyle = "none;solid;dashed;dotted;double;groove;ridge;inset;outset"; +var defaultBorderWidth = "thin;medium;thick"; +var defaultListType = "disc;circle;square;decimal;lower-roman;upper-roman;lower-alpha;upper-alpha;none"; + +function init() { + var ce = document.getElementById('container'), h; + + ce.style.cssText = tinyMCEPopup.getWindowArg('style_text'); + + h = getBrowserHTML('background_image_browser','background_image','image','advimage'); + document.getElementById("background_image_browser").innerHTML = h; + + document.getElementById('text_color_pickcontainer').innerHTML = getColorPickerHTML('text_color_pick','text_color'); + document.getElementById('background_color_pickcontainer').innerHTML = getColorPickerHTML('background_color_pick','background_color'); + document.getElementById('border_color_top_pickcontainer').innerHTML = getColorPickerHTML('border_color_top_pick','border_color_top'); + document.getElementById('border_color_right_pickcontainer').innerHTML = getColorPickerHTML('border_color_right_pick','border_color_right'); + document.getElementById('border_color_bottom_pickcontainer').innerHTML = getColorPickerHTML('border_color_bottom_pick','border_color_bottom'); + document.getElementById('border_color_left_pickcontainer').innerHTML = getColorPickerHTML('border_color_left_pick','border_color_left'); + + fillSelect(0, 'text_font', 'style_font', defaultFonts, ';', true); + fillSelect(0, 'text_size', 'style_font_size', defaultSizes, ';', true); + fillSelect(0, 'text_size_measurement', 'style_font_size_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'text_case', 'style_text_case', "capitalize;uppercase;lowercase", ';', true); + fillSelect(0, 'text_weight', 'style_font_weight', defaultWeight, ';', true); + fillSelect(0, 'text_style', 'style_font_style', defaultTextStyle, ';', true); + fillSelect(0, 'text_variant', 'style_font_variant', defaultVariant, ';', true); + fillSelect(0, 'text_lineheight', 'style_font_line_height', defaultLineHeight, ';', true); + fillSelect(0, 'text_lineheight_measurement', 'style_font_line_height_measurement', defaultMeasurement, ';', true); + + fillSelect(0, 'background_attachment', 'style_background_attachment', defaultAttachment, ';', true); + fillSelect(0, 'background_repeat', 'style_background_repeat', defaultRepeat, ';', true); + + fillSelect(0, 'background_hpos_measurement', 'style_background_hpos_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'background_vpos_measurement', 'style_background_vpos_measurement', defaultMeasurement, ';', true); + + fillSelect(0, 'background_hpos', 'style_background_hpos', defaultPosH, ';', true); + fillSelect(0, 'background_vpos', 'style_background_vpos', defaultPosV, ';', true); + + fillSelect(0, 'block_wordspacing', 'style_wordspacing', 'normal', ';', true); + fillSelect(0, 'block_wordspacing_measurement', 'style_wordspacing_measurement', defaultSpacingMeasurement, ';', true); + fillSelect(0, 'block_letterspacing', 'style_letterspacing', 'normal', ';', true); + fillSelect(0, 'block_letterspacing_measurement', 'style_letterspacing_measurement', defaultSpacingMeasurement, ';', true); + fillSelect(0, 'block_vertical_alignment', 'style_vertical_alignment', defaultVAlign, ';', true); + fillSelect(0, 'block_text_align', 'style_text_align', "left;right;center;justify", ';', true); + fillSelect(0, 'block_whitespace', 'style_whitespace', "normal;pre;nowrap", ';', true); + fillSelect(0, 'block_display', 'style_display', defaultDisplay, ';', true); + fillSelect(0, 'block_text_indent_measurement', 'style_text_indent_measurement', defaultIndentMeasurement, ';', true); + + fillSelect(0, 'box_width_measurement', 'style_box_width_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_height_measurement', 'style_box_height_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_float', 'style_float', 'left;right;none', ';', true); + fillSelect(0, 'box_clear', 'style_clear', 'left;right;both;none', ';', true); + fillSelect(0, 'box_padding_left_measurement', 'style_padding_left_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_padding_top_measurement', 'style_padding_top_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_padding_bottom_measurement', 'style_padding_bottom_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_padding_right_measurement', 'style_padding_right_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_margin_left_measurement', 'style_margin_left_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_margin_top_measurement', 'style_margin_top_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_margin_bottom_measurement', 'style_margin_bottom_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'box_margin_right_measurement', 'style_margin_right_measurement', defaultMeasurement, ';', true); + + fillSelect(0, 'border_style_top', 'style_border_style_top', defaultBorderStyle, ';', true); + fillSelect(0, 'border_style_right', 'style_border_style_right', defaultBorderStyle, ';', true); + fillSelect(0, 'border_style_bottom', 'style_border_style_bottom', defaultBorderStyle, ';', true); + fillSelect(0, 'border_style_left', 'style_border_style_left', defaultBorderStyle, ';', true); + + fillSelect(0, 'border_width_top', 'style_border_width_top', defaultBorderWidth, ';', true); + fillSelect(0, 'border_width_right', 'style_border_width_right', defaultBorderWidth, ';', true); + fillSelect(0, 'border_width_bottom', 'style_border_width_bottom', defaultBorderWidth, ';', true); + fillSelect(0, 'border_width_left', 'style_border_width_left', defaultBorderWidth, ';', true); + + fillSelect(0, 'border_width_top_measurement', 'style_border_width_top_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'border_width_right_measurement', 'style_border_width_right_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'border_width_bottom_measurement', 'style_border_width_bottom_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'border_width_left_measurement', 'style_border_width_left_measurement', defaultMeasurement, ';', true); + + fillSelect(0, 'list_type', 'style_list_type', defaultListType, ';', true); + fillSelect(0, 'list_position', 'style_list_position', "inside;outside", ';', true); + + fillSelect(0, 'positioning_type', 'style_positioning_type', "absolute;relative;static", ';', true); + fillSelect(0, 'positioning_visibility', 'style_positioning_visibility', "inherit;visible;hidden", ';', true); + + fillSelect(0, 'positioning_width_measurement', 'style_positioning_width_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_height_measurement', 'style_positioning_height_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_overflow', 'style_positioning_overflow', "visible;hidden;scroll;auto", ';', true); + + fillSelect(0, 'positioning_placement_top_measurement', 'style_positioning_placement_top_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_placement_right_measurement', 'style_positioning_placement_right_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_placement_bottom_measurement', 'style_positioning_placement_bottom_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_placement_left_measurement', 'style_positioning_placement_left_measurement', defaultMeasurement, ';', true); + + fillSelect(0, 'positioning_clip_top_measurement', 'style_positioning_clip_top_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_clip_right_measurement', 'style_positioning_clip_right_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_clip_bottom_measurement', 'style_positioning_clip_bottom_measurement', defaultMeasurement, ';', true); + fillSelect(0, 'positioning_clip_left_measurement', 'style_positioning_clip_left_measurement', defaultMeasurement, ';', true); + + TinyMCE_EditableSelects.init(); + setupFormData(); + showDisabledControls(); +} + +function setupFormData() { + var ce = document.getElementById('container'), f = document.forms[0], s, b, i; + + // Setup text fields + + selectByValue(f, 'text_font', ce.style.fontFamily, true, true); + selectByValue(f, 'text_size', getNum(ce.style.fontSize), true, true); + selectByValue(f, 'text_size_measurement', getMeasurement(ce.style.fontSize)); + selectByValue(f, 'text_weight', ce.style.fontWeight, true, true); + selectByValue(f, 'text_style', ce.style.fontStyle, true, true); + selectByValue(f, 'text_lineheight', getNum(ce.style.lineHeight), true, true); + selectByValue(f, 'text_lineheight_measurement', getMeasurement(ce.style.lineHeight)); + selectByValue(f, 'text_case', ce.style.textTransform, true, true); + selectByValue(f, 'text_variant', ce.style.fontVariant, true, true); + f.text_color.value = tinyMCEPopup.editor.dom.toHex(ce.style.color); + updateColor('text_color_pick', 'text_color'); + f.text_underline.checked = inStr(ce.style.textDecoration, 'underline'); + f.text_overline.checked = inStr(ce.style.textDecoration, 'overline'); + f.text_linethrough.checked = inStr(ce.style.textDecoration, 'line-through'); + f.text_blink.checked = inStr(ce.style.textDecoration, 'blink'); + + // Setup background fields + + f.background_color.value = tinyMCEPopup.editor.dom.toHex(ce.style.backgroundColor); + updateColor('background_color_pick', 'background_color'); + f.background_image.value = ce.style.backgroundImage.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1"); + selectByValue(f, 'background_repeat', ce.style.backgroundRepeat, true, true); + selectByValue(f, 'background_attachment', ce.style.backgroundAttachment, true, true); + selectByValue(f, 'background_hpos', getNum(getVal(ce.style.backgroundPosition, 0)), true, true); + selectByValue(f, 'background_hpos_measurement', getMeasurement(getVal(ce.style.backgroundPosition, 0))); + selectByValue(f, 'background_vpos', getNum(getVal(ce.style.backgroundPosition, 1)), true, true); + selectByValue(f, 'background_vpos_measurement', getMeasurement(getVal(ce.style.backgroundPosition, 1))); + + // Setup block fields + + selectByValue(f, 'block_wordspacing', getNum(ce.style.wordSpacing), true, true); + selectByValue(f, 'block_wordspacing_measurement', getMeasurement(ce.style.wordSpacing)); + selectByValue(f, 'block_letterspacing', getNum(ce.style.letterSpacing), true, true); + selectByValue(f, 'block_letterspacing_measurement', getMeasurement(ce.style.letterSpacing)); + selectByValue(f, 'block_vertical_alignment', ce.style.verticalAlign, true, true); + selectByValue(f, 'block_text_align', ce.style.textAlign, true, true); + f.block_text_indent.value = getNum(ce.style.textIndent); + selectByValue(f, 'block_text_indent_measurement', getMeasurement(ce.style.textIndent)); + selectByValue(f, 'block_whitespace', ce.style.whiteSpace, true, true); + selectByValue(f, 'block_display', ce.style.display, true, true); + + // Setup box fields + + f.box_width.value = getNum(ce.style.width); + selectByValue(f, 'box_width_measurement', getMeasurement(ce.style.width)); + + f.box_height.value = getNum(ce.style.height); + selectByValue(f, 'box_height_measurement', getMeasurement(ce.style.height)); + selectByValue(f, 'box_float', ce.style.cssFloat || ce.style.styleFloat, true, true); + + selectByValue(f, 'box_clear', ce.style.clear, true, true); + + setupBox(f, ce, 'box_padding', 'padding', ''); + setupBox(f, ce, 'box_margin', 'margin', ''); + + // Setup border fields + + setupBox(f, ce, 'border_style', 'border', 'Style'); + setupBox(f, ce, 'border_width', 'border', 'Width'); + setupBox(f, ce, 'border_color', 'border', 'Color'); + + updateColor('border_color_top_pick', 'border_color_top'); + updateColor('border_color_right_pick', 'border_color_right'); + updateColor('border_color_bottom_pick', 'border_color_bottom'); + updateColor('border_color_left_pick', 'border_color_left'); + + f.elements.border_color_top.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_top.value); + f.elements.border_color_right.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_right.value); + f.elements.border_color_bottom.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_bottom.value); + f.elements.border_color_left.value = tinyMCEPopup.editor.dom.toHex(f.elements.border_color_left.value); + + // Setup list fields + + selectByValue(f, 'list_type', ce.style.listStyleType, true, true); + selectByValue(f, 'list_position', ce.style.listStylePosition, true, true); + f.list_bullet_image.value = ce.style.listStyleImage.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1"); + + // Setup box fields + + selectByValue(f, 'positioning_type', ce.style.position, true, true); + selectByValue(f, 'positioning_visibility', ce.style.visibility, true, true); + selectByValue(f, 'positioning_overflow', ce.style.overflow, true, true); + f.positioning_zindex.value = ce.style.zIndex ? ce.style.zIndex : ""; + + f.positioning_width.value = getNum(ce.style.width); + selectByValue(f, 'positioning_width_measurement', getMeasurement(ce.style.width)); + + f.positioning_height.value = getNum(ce.style.height); + selectByValue(f, 'positioning_height_measurement', getMeasurement(ce.style.height)); + + setupBox(f, ce, 'positioning_placement', '', '', ['top', 'right', 'bottom', 'left']); + + s = ce.style.clip.replace(new RegExp("rect\\('?([^']*)'?\\)", 'gi'), "$1"); + s = s.replace(/,/g, ' '); + + if (!hasEqualValues([getVal(s, 0), getVal(s, 1), getVal(s, 2), getVal(s, 3)])) { + f.positioning_clip_top.value = getNum(getVal(s, 0)); + selectByValue(f, 'positioning_clip_top_measurement', getMeasurement(getVal(s, 0))); + f.positioning_clip_right.value = getNum(getVal(s, 1)); + selectByValue(f, 'positioning_clip_right_measurement', getMeasurement(getVal(s, 1))); + f.positioning_clip_bottom.value = getNum(getVal(s, 2)); + selectByValue(f, 'positioning_clip_bottom_measurement', getMeasurement(getVal(s, 2))); + f.positioning_clip_left.value = getNum(getVal(s, 3)); + selectByValue(f, 'positioning_clip_left_measurement', getMeasurement(getVal(s, 3))); + } else { + f.positioning_clip_top.value = getNum(getVal(s, 0)); + selectByValue(f, 'positioning_clip_top_measurement', getMeasurement(getVal(s, 0))); + f.positioning_clip_right.value = f.positioning_clip_bottom.value = f.positioning_clip_left.value; + } + +// setupBox(f, ce, '', 'border', 'Color'); +} + +function getMeasurement(s) { + return s.replace(/^([0-9.]+)(.*)$/, "$2"); +} + +function getNum(s) { + if (new RegExp('^(?:[0-9.]+)(?:[a-z%]+)$', 'gi').test(s)) + return s.replace(/[^0-9.]/g, ''); + + return s; +} + +function inStr(s, n) { + return new RegExp(n, 'gi').test(s); +} + +function getVal(s, i) { + var a = s.split(' '); + + if (a.length > 1) + return a[i]; + + return ""; +} + +function setValue(f, n, v) { + if (f.elements[n].type == "text") + f.elements[n].value = v; + else + selectByValue(f, n, v, true, true); +} + +function setupBox(f, ce, fp, pr, sf, b) { + if (typeof(b) == "undefined") + b = ['Top', 'Right', 'Bottom', 'Left']; + + if (isSame(ce, pr, sf, b)) { + f.elements[fp + "_same"].checked = true; + + setValue(f, fp + "_top", getNum(ce.style[pr + b[0] + sf])); + f.elements[fp + "_top"].disabled = false; + + f.elements[fp + "_right"].value = ""; + f.elements[fp + "_right"].disabled = true; + f.elements[fp + "_bottom"].value = ""; + f.elements[fp + "_bottom"].disabled = true; + f.elements[fp + "_left"].value = ""; + f.elements[fp + "_left"].disabled = true; + + if (f.elements[fp + "_top_measurement"]) { + selectByValue(f, fp + '_top_measurement', getMeasurement(ce.style[pr + b[0] + sf])); + f.elements[fp + "_left_measurement"].disabled = true; + f.elements[fp + "_bottom_measurement"].disabled = true; + f.elements[fp + "_right_measurement"].disabled = true; + } + } else { + f.elements[fp + "_same"].checked = false; + + setValue(f, fp + "_top", getNum(ce.style[pr + b[0] + sf])); + f.elements[fp + "_top"].disabled = false; + + setValue(f, fp + "_right", getNum(ce.style[pr + b[1] + sf])); + f.elements[fp + "_right"].disabled = false; + + setValue(f, fp + "_bottom", getNum(ce.style[pr + b[2] + sf])); + f.elements[fp + "_bottom"].disabled = false; + + setValue(f, fp + "_left", getNum(ce.style[pr + b[3] + sf])); + f.elements[fp + "_left"].disabled = false; + + if (f.elements[fp + "_top_measurement"]) { + selectByValue(f, fp + '_top_measurement', getMeasurement(ce.style[pr + b[0] + sf])); + selectByValue(f, fp + '_right_measurement', getMeasurement(ce.style[pr + b[1] + sf])); + selectByValue(f, fp + '_bottom_measurement', getMeasurement(ce.style[pr + b[2] + sf])); + selectByValue(f, fp + '_left_measurement', getMeasurement(ce.style[pr + b[3] + sf])); + f.elements[fp + "_left_measurement"].disabled = false; + f.elements[fp + "_bottom_measurement"].disabled = false; + f.elements[fp + "_right_measurement"].disabled = false; + } + } +} + +function isSame(e, pr, sf, b) { + var a = [], i, x; + + if (typeof(b) == "undefined") + b = ['Top', 'Right', 'Bottom', 'Left']; + + if (typeof(sf) == "undefined" || sf == null) + sf = ""; + + a[0] = e.style[pr + b[0] + sf]; + a[1] = e.style[pr + b[1] + sf]; + a[2] = e.style[pr + b[2] + sf]; + a[3] = e.style[pr + b[3] + sf]; + + for (i=0; i<a.length; i++) { + if (a[i] == null) + return false; + + for (x=0; x<a.length; x++) { + if (a[x] != a[i]) + return false; + } + } + + return true; +}; + +function hasEqualValues(a) { + var i, x; + + for (i=0; i<a.length; i++) { + if (a[i] == null) + return false; + + for (x=0; x<a.length; x++) { + if (a[x] != a[i]) + return false; + } + } + + return true; +} + +function applyAction() { + var ce = document.getElementById('container'), ed = tinyMCEPopup.editor; + + generateCSS(); + + tinyMCEPopup.restoreSelection(); + ed.dom.setAttrib(ed.selection.getSelectedBlocks(), 'style', tinyMCEPopup.editor.dom.serializeStyle(tinyMCEPopup.editor.dom.parseStyle(ce.style.cssText))); +} + +function updateAction() { + applyAction(); + tinyMCEPopup.close(); +} + +function generateCSS() { + var ce = document.getElementById('container'), f = document.forms[0], num = new RegExp('[0-9]+', 'g'), s, t; + + ce.style.cssText = ""; + + // Build text styles + ce.style.fontFamily = f.text_font.value; + ce.style.fontSize = f.text_size.value + (isNum(f.text_size.value) ? (f.text_size_measurement.value || 'px') : ""); + ce.style.fontStyle = f.text_style.value; + ce.style.lineHeight = f.text_lineheight.value + (isNum(f.text_lineheight.value) ? f.text_lineheight_measurement.value : ""); + ce.style.textTransform = f.text_case.value; + ce.style.fontWeight = f.text_weight.value; + ce.style.fontVariant = f.text_variant.value; + ce.style.color = f.text_color.value; + + s = ""; + s += f.text_underline.checked ? " underline" : ""; + s += f.text_overline.checked ? " overline" : ""; + s += f.text_linethrough.checked ? " line-through" : ""; + s += f.text_blink.checked ? " blink" : ""; + s = s.length > 0 ? s.substring(1) : s; + + if (f.text_none.checked) + s = "none"; + + ce.style.textDecoration = s; + + // Build background styles + + ce.style.backgroundColor = f.background_color.value; + ce.style.backgroundImage = f.background_image.value != "" ? "url(" + f.background_image.value + ")" : ""; + ce.style.backgroundRepeat = f.background_repeat.value; + ce.style.backgroundAttachment = f.background_attachment.value; + + if (f.background_hpos.value != "") { + s = ""; + s += f.background_hpos.value + (isNum(f.background_hpos.value) ? f.background_hpos_measurement.value : "") + " "; + s += f.background_vpos.value + (isNum(f.background_vpos.value) ? f.background_vpos_measurement.value : ""); + ce.style.backgroundPosition = s; + } + + // Build block styles + + ce.style.wordSpacing = f.block_wordspacing.value + (isNum(f.block_wordspacing.value) ? f.block_wordspacing_measurement.value : ""); + ce.style.letterSpacing = f.block_letterspacing.value + (isNum(f.block_letterspacing.value) ? f.block_letterspacing_measurement.value : ""); + ce.style.verticalAlign = f.block_vertical_alignment.value; + ce.style.textAlign = f.block_text_align.value; + ce.style.textIndent = f.block_text_indent.value + (isNum(f.block_text_indent.value) ? f.block_text_indent_measurement.value : ""); + ce.style.whiteSpace = f.block_whitespace.value; + ce.style.display = f.block_display.value; + + // Build box styles + + ce.style.width = f.box_width.value + (isNum(f.box_width.value) ? f.box_width_measurement.value : ""); + ce.style.height = f.box_height.value + (isNum(f.box_height.value) ? f.box_height_measurement.value : ""); + ce.style.styleFloat = f.box_float.value; + ce.style.cssFloat = f.box_float.value; + + ce.style.clear = f.box_clear.value; + + if (!f.box_padding_same.checked) { + ce.style.paddingTop = f.box_padding_top.value + (isNum(f.box_padding_top.value) ? f.box_padding_top_measurement.value : ""); + ce.style.paddingRight = f.box_padding_right.value + (isNum(f.box_padding_right.value) ? f.box_padding_right_measurement.value : ""); + ce.style.paddingBottom = f.box_padding_bottom.value + (isNum(f.box_padding_bottom.value) ? f.box_padding_bottom_measurement.value : ""); + ce.style.paddingLeft = f.box_padding_left.value + (isNum(f.box_padding_left.value) ? f.box_padding_left_measurement.value : ""); + } else + ce.style.padding = f.box_padding_top.value + (isNum(f.box_padding_top.value) ? f.box_padding_top_measurement.value : ""); + + if (!f.box_margin_same.checked) { + ce.style.marginTop = f.box_margin_top.value + (isNum(f.box_margin_top.value) ? f.box_margin_top_measurement.value : ""); + ce.style.marginRight = f.box_margin_right.value + (isNum(f.box_margin_right.value) ? f.box_margin_right_measurement.value : ""); + ce.style.marginBottom = f.box_margin_bottom.value + (isNum(f.box_margin_bottom.value) ? f.box_margin_bottom_measurement.value : ""); + ce.style.marginLeft = f.box_margin_left.value + (isNum(f.box_margin_left.value) ? f.box_margin_left_measurement.value : ""); + } else + ce.style.margin = f.box_margin_top.value + (isNum(f.box_margin_top.value) ? f.box_margin_top_measurement.value : ""); + + // Build border styles + + if (!f.border_style_same.checked) { + ce.style.borderTopStyle = f.border_style_top.value; + ce.style.borderRightStyle = f.border_style_right.value; + ce.style.borderBottomStyle = f.border_style_bottom.value; + ce.style.borderLeftStyle = f.border_style_left.value; + } else + ce.style.borderStyle = f.border_style_top.value; + + if (!f.border_width_same.checked) { + ce.style.borderTopWidth = f.border_width_top.value + (isNum(f.border_width_top.value) ? f.border_width_top_measurement.value : ""); + ce.style.borderRightWidth = f.border_width_right.value + (isNum(f.border_width_right.value) ? f.border_width_right_measurement.value : ""); + ce.style.borderBottomWidth = f.border_width_bottom.value + (isNum(f.border_width_bottom.value) ? f.border_width_bottom_measurement.value : ""); + ce.style.borderLeftWidth = f.border_width_left.value + (isNum(f.border_width_left.value) ? f.border_width_left_measurement.value : ""); + } else + ce.style.borderWidth = f.border_width_top.value + (isNum(f.border_width_top.value) ? f.border_width_top_measurement.value : ""); + + if (!f.border_color_same.checked) { + ce.style.borderTopColor = f.border_color_top.value; + ce.style.borderRightColor = f.border_color_right.value; + ce.style.borderBottomColor = f.border_color_bottom.value; + ce.style.borderLeftColor = f.border_color_left.value; + } else + ce.style.borderColor = f.border_color_top.value; + + // Build list styles + + ce.style.listStyleType = f.list_type.value; + ce.style.listStylePosition = f.list_position.value; + ce.style.listStyleImage = f.list_bullet_image.value != "" ? "url(" + f.list_bullet_image.value + ")" : ""; + + // Build positioning styles + + ce.style.position = f.positioning_type.value; + ce.style.visibility = f.positioning_visibility.value; + + if (ce.style.width == "") + ce.style.width = f.positioning_width.value + (isNum(f.positioning_width.value) ? f.positioning_width_measurement.value : ""); + + if (ce.style.height == "") + ce.style.height = f.positioning_height.value + (isNum(f.positioning_height.value) ? f.positioning_height_measurement.value : ""); + + ce.style.zIndex = f.positioning_zindex.value; + ce.style.overflow = f.positioning_overflow.value; + + if (!f.positioning_placement_same.checked) { + ce.style.top = f.positioning_placement_top.value + (isNum(f.positioning_placement_top.value) ? f.positioning_placement_top_measurement.value : ""); + ce.style.right = f.positioning_placement_right.value + (isNum(f.positioning_placement_right.value) ? f.positioning_placement_right_measurement.value : ""); + ce.style.bottom = f.positioning_placement_bottom.value + (isNum(f.positioning_placement_bottom.value) ? f.positioning_placement_bottom_measurement.value : ""); + ce.style.left = f.positioning_placement_left.value + (isNum(f.positioning_placement_left.value) ? f.positioning_placement_left_measurement.value : ""); + } else { + s = f.positioning_placement_top.value + (isNum(f.positioning_placement_top.value) ? f.positioning_placement_top_measurement.value : ""); + ce.style.top = s; + ce.style.right = s; + ce.style.bottom = s; + ce.style.left = s; + } + + if (!f.positioning_clip_same.checked) { + s = "rect("; + s += (isNum(f.positioning_clip_top.value) ? f.positioning_clip_top.value + f.positioning_clip_top_measurement.value : "auto") + " "; + s += (isNum(f.positioning_clip_right.value) ? f.positioning_clip_right.value + f.positioning_clip_right_measurement.value : "auto") + " "; + s += (isNum(f.positioning_clip_bottom.value) ? f.positioning_clip_bottom.value + f.positioning_clip_bottom_measurement.value : "auto") + " "; + s += (isNum(f.positioning_clip_left.value) ? f.positioning_clip_left.value + f.positioning_clip_left_measurement.value : "auto"); + s += ")"; + + if (s != "rect(auto auto auto auto)") + ce.style.clip = s; + } else { + s = "rect("; + t = isNum(f.positioning_clip_top.value) ? f.positioning_clip_top.value + f.positioning_clip_top_measurement.value : "auto"; + s += t + " "; + s += t + " "; + s += t + " "; + s += t + ")"; + + if (s != "rect(auto auto auto auto)") + ce.style.clip = s; + } + + ce.style.cssText = ce.style.cssText; +} + +function isNum(s) { + return new RegExp('[0-9]+', 'g').test(s); +} + +function showDisabledControls() { + var f = document.forms, i, a; + + for (i=0; i<f.length; i++) { + for (a=0; a<f[i].elements.length; a++) { + if (f[i].elements[a].disabled) + tinyMCEPopup.editor.dom.addClass(f[i].elements[a], "disabled"); + else + tinyMCEPopup.editor.dom.removeClass(f[i].elements[a], "disabled"); + } + } +} + +function fillSelect(f, s, param, dval, sep, em) { + var i, ar, p, se; + + f = document.forms[f]; + sep = typeof(sep) == "undefined" ? ";" : sep; + + if (em) + addSelectValue(f, s, "", ""); + + ar = tinyMCEPopup.getParam(param, dval).split(sep); + for (i=0; i<ar.length; i++) { + se = false; + + if (ar[i].charAt(0) == '+') { + ar[i] = ar[i].substring(1); + se = true; + } + + p = ar[i].split('='); + + if (p.length > 1) { + addSelectValue(f, s, p[0], p[1]); + + if (se) + selectByValue(f, s, p[1]); + } else { + addSelectValue(f, s, p[0], p[0]); + + if (se) + selectByValue(f, s, p[0]); + } + } +} + +function toggleSame(ce, pre) { + var el = document.forms[0].elements, i; + + if (ce.checked) { + el[pre + "_top"].disabled = false; + el[pre + "_right"].disabled = true; + el[pre + "_bottom"].disabled = true; + el[pre + "_left"].disabled = true; + + if (el[pre + "_top_measurement"]) { + el[pre + "_top_measurement"].disabled = false; + el[pre + "_right_measurement"].disabled = true; + el[pre + "_bottom_measurement"].disabled = true; + el[pre + "_left_measurement"].disabled = true; + } + } else { + el[pre + "_top"].disabled = false; + el[pre + "_right"].disabled = false; + el[pre + "_bottom"].disabled = false; + el[pre + "_left"].disabled = false; + + if (el[pre + "_top_measurement"]) { + el[pre + "_top_measurement"].disabled = false; + el[pre + "_right_measurement"].disabled = false; + el[pre + "_bottom_measurement"].disabled = false; + el[pre + "_left_measurement"].disabled = false; + } + } + + showDisabledControls(); +} + +function synch(fr, to) { + var f = document.forms[0]; + + f.elements[to].value = f.elements[fr].value; + + if (f.elements[fr + "_measurement"]) + selectByValue(f, to + "_measurement", f.elements[fr + "_measurement"].value); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/de_dlg.js new file mode 100644 index 0000000..ad04664 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.style_dlg',{"text_lineheight":"Zeilenh\u00f6he","text_variant":"Variante","text_style":"Stil","text_weight":"Dicke","text_size":"Gr\u00f6\u00dfe","text_font":"Schriftart","text_props":"Text","positioning_tab":"Positionierung","list_tab":"Liste","border_tab":"Rahmen","box_tab":"Box","block_tab":"Block","background_tab":"Hintergrund","text_tab":"Text",apply:"\u00dcbernehmen",title:"CSS-Styles bearbeiten",clip:"Ausschnitt",placement:"Platzierung",overflow:"Verhalten bei \u00dcbergr\u00f6\u00dfe",zindex:"Z-Wert",visibility:"Sichtbar","positioning_type":"Art der Positionierung",position:"Positionierung","bullet_image":"Listenpunkt-Grafik","list_type":"Listenpunkt-Art",color:"Textfarbe",height:"H\u00f6he",width:"Breite",style:"Format",margin:"\u00c4u\u00dferer Abstand",left:"Links",bottom:"Unten",right:"Rechts",top:"Oben",same:"Alle gleich",padding:"Innerer Abstand","box_clear":"Umflie\u00dfung verhindern","box_float":"Umflie\u00dfung","box_height":"H\u00f6he","box_width":"Breite","block_display":"Umbruchverhalten","block_whitespace":"Automatischer Umbruch","block_text_indent":"Einr\u00fcckung","block_text_align":"Ausrichtung","block_vertical_alignment":"Vertikale Ausrichtung","block_letterspacing":"Buchstabenabstand","block_wordspacing":"Wortabstand","background_vpos":"Position Y","background_hpos":"Position X","background_attachment":"Wasserzeicheneffekt","background_repeat":"Wiederholung","background_image":"Hintergrundbild","background_color":"Hintergrundfarbe","text_none":"keine","text_blink":"blinkend","text_case":"Schreibung","text_striketrough":"durchgestrichen","text_underline":"unterstrichen","text_overline":"\u00fcberstrichen","text_decoration":"Gestaltung","text_color":"Farbe",text:"Text",background:"Hintergrund",block:"Block",box:"Box",border:"Rahmen",list:"Liste"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/en_dlg.js new file mode 100644 index 0000000..9a1d4a2 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.style_dlg',{"text_lineheight":"Line Height","text_variant":"Variant","text_style":"Style","text_weight":"Weight","text_size":"Size","text_font":"Font","text_props":"Text","positioning_tab":"Positioning","list_tab":"List","border_tab":"Border","box_tab":"Box","block_tab":"Block","background_tab":"Background","text_tab":"Text",apply:"Apply",title:"Edit CSS Style",clip:"Clip",placement:"Placement",overflow:"Overflow",zindex:"Z-index",visibility:"Visibility","positioning_type":"Type",position:"Position","bullet_image":"Bullet Image","list_type":"Type",color:"Color",height:"Height",width:"Width",style:"Style",margin:"Margin",left:"Left",bottom:"Bottom",right:"Right",top:"Top",same:"Same for All",padding:"Padding","box_clear":"Clear","box_float":"Float","box_height":"Height","box_width":"Width","block_display":"Display","block_whitespace":"Whitespace","block_text_indent":"Text Indent","block_text_align":"Text Align","block_vertical_alignment":"Vertical Alignment","block_letterspacing":"Letter Spacing","block_wordspacing":"Word Spacing","background_vpos":"Vertical Position","background_hpos":"Horizontal Position","background_attachment":"Attachment","background_repeat":"Repeat","background_image":"Background Image","background_color":"Background Color","text_none":"None","text_blink":"Blink","text_case":"Case","text_striketrough":"Strikethrough","text_underline":"Underline","text_overline":"Overline","text_decoration":"Decoration","text_color":"Color",text:"Text",background:"Background",block:"Block",box:"Box",border:"Border",list:"List"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/fr_dlg.js new file mode 100644 index 0000000..8ab5e6c --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.style_dlg',{"text_lineheight":"Hauteur de ligne","text_variant":"Variante","text_style":"Style","text_weight":"Gras","text_size":"Taille","text_font":"Police","text_props":"Texte","positioning_tab":"Positionnement","list_tab":"Liste","border_tab":"Bordure","box_tab":"Bo\u00eete","block_tab":"Bloc","background_tab":"Fond","text_tab":"Texte",apply:"Appliquer",title:"\u00c9diter la feuille de style",clip:"Clip",placement:"Placement",overflow:"D\u00e9bordement",zindex:"Z-index",visibility:"Visibilit\u00e9","positioning_type":"Type",position:"Position","bullet_image":"Image de puce","list_type":"Type",color:"Couleur",height:"Hauteur",width:"Largeur",style:"Style",margin:"Marge",left:"Gauche",bottom:"Bas",right:"Droit",top:"Haut",same:"Identique pour tous",padding:"Espacement","box_clear":"Vider","box_float":"Flottant","box_height":"Hauteur","box_width":"Largeur","block_display":"Affichage","block_whitespace":"Fin de ligne","block_text_indent":"Indentation du texte","block_text_align":"Alignement du texte","block_vertical_alignment":"Alignement vertical","block_letterspacing":"Espacement des lettres","block_wordspacing":"Espacement des mots ","background_vpos":"Position verticale","background_hpos":"Position horizontale","background_attachment":"Attachement","background_repeat":"R\u00e9p\u00e9ter","background_image":"Image de fond","background_color":"Couleur de fond","text_none":"aucun","text_blink":"clignotant","text_case":"Casse","text_striketrough":"barr\u00e9","text_underline":"soulign\u00e9","text_overline":"ligne au-dessus","text_decoration":"D\u00e9coration","text_color":"Couleur",text:"Text",background:"Background",block:"Block",box:"Box",border:"Border",list:"List"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/it_dlg.js new file mode 100644 index 0000000..3ffc088 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.style_dlg',{"text_lineheight":"Altezza linea","text_variant":"Variante","text_style":"Stile","text_weight":"Spessore","text_size":"Dimensione","text_font":"Carattere","text_props":"Testo","positioning_tab":"Posizionamento","list_tab":"Liste","border_tab":"Bordi","box_tab":"Contenitore","block_tab":"Blocco","background_tab":"Sfondo","text_tab":"Testo",apply:"Applica",title:"Modifica stile CSS",clip:"Clip",placement:"Piazzamento",overflow:"Overflow",zindex:"Z-index",visibility:"Visibilit\u00e0","positioning_type":"Tipo",position:"Posizione","bullet_image":"Immagine Punto","list_type":"Tipo",color:"Colore",height:"Altezza",width:"Larghezza",style:"Stile",margin:"Margine",left:"Sinistro",bottom:"Inferiore",right:"Destro",top:"Superiore",same:"Uguale per tutti",padding:"Spazio dal bordo","box_clear":"Pulito","box_float":"Fluttuante","box_height":"Altezza","box_width":"Larghezza","block_display":"Visualizzazione","block_whitespace":"Whitespace","block_text_indent":"Indentazione testo","block_text_align":"Allineamento testo","block_vertical_alignment":"Allineamento verticale","block_letterspacing":"Spaziatura caratteri","block_wordspacing":"Spaziatura parole","background_vpos":"Posizione verticale","background_hpos":"Posizione orizzontale","background_attachment":"Allegato","background_repeat":"Repetizione","background_image":"Immagine sfondo","background_color":"Colore sfondo","text_none":"nessuna","text_blink":"lampeggiante","text_case":"Tipo","text_striketrough":"barrato","text_underline":"sottolineato","text_overline":"sopralineato","text_decoration":"Decorazione","text_color":"Colore",text:"Text",background:"Background",block:"Block",box:"Box",border:"Border",list:"List"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/style/props.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/props.htm new file mode 100644 index 0000000..76ab68d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/style/props.htm @@ -0,0 +1,840 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#style_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="js/props.js"></script> + <link href="css/props.css" rel="stylesheet" type="text/css" /> +</head> + +<body id="styleprops" style="display: none" role="application" aria-labelledby="app_title"> +<span id="app_title" style="display:none">{#style_dlg.title}</span> +<form onsubmit="updateAction();return false;" action="#"> +<div class="tabs"> + <ul> + <li id="text_tab" class="current" aria-controls="text_panel"><span><a href="javascript:mcTabs.displayTab('text_tab','text_panel');" onMouseDown="return false;">{#style_dlg.text_tab}</a></span></li> + <li id="background_tab" aria-controls="background_panel"><span><a href="javascript:mcTabs.displayTab('background_tab','background_panel');" onMouseDown="return false;">{#style_dlg.background_tab}</a></span></li> + <li id="block_tab" aria-controls="block_panel"><span><a href="javascript:mcTabs.displayTab('block_tab','block_panel');" onMouseDown="return false;">{#style_dlg.block_tab}</a></span></li> + <li id="box_tab" aria-controls="box_panel"><span><a href="javascript:mcTabs.displayTab('box_tab','box_panel');" onMouseDown="return false;">{#style_dlg.box_tab}</a></span></li> + <li id="border_tab" aria-controls="border_panel"><span><a href="javascript:mcTabs.displayTab('border_tab','border_panel');" onMouseDown="return false;">{#style_dlg.border_tab}</a></span></li> + <li id="list_tab" aria-controls="list_panel"><span><a href="javascript:mcTabs.displayTab('list_tab','list_panel');" onMouseDown="return false;">{#style_dlg.list_tab}</a></span></li> + <li id="positioning_tab" aria-controls="positioning_panel"><span><a href="javascript:mcTabs.displayTab('positioning_tab','positioning_panel');" onMouseDown="return false;">{#style_dlg.positioning_tab}</a></span></li> + </ul> +</div> + +<div class="panel_wrapper"> +<div id="text_panel" class="panel current"> + <fieldset> + <legend>{#style_dlg.text}</legend> + <table role="presentation" border="0" width="100%"> + <tr> + <td><label for="text_font">{#style_dlg.text_font}</label></td> + <td colspan="3"> + <select id="text_font" name="text_font" class="mceEditableSelect mceFocus"></select> + </td> + </tr> + <tr> + <td><label for="text_size">{#style_dlg.text_size}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="text_size" name="text_size" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + <label id="text_size_measurement_label" for="text_size_measurement" style="display: none; visibility: hidden;">Text Size Measurement Unit</label> + <select id="text_size_measurement" name="text_size_measurement" aria-labelledby="text_size_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td><label for="text_weight">{#style_dlg.text_weight}</label></td> + <td> + <select id="text_weight" name="text_weight"></select> + </td> + </tr> + <tr> + <td><label for="text_style">{#style_dlg.text_style}</label></td> + <td> + <select id="text_style" name="text_style" class="mceEditableSelect"></select> + </td> + <td><label for="text_variant">{#style_dlg.text_variant}</label></td> + <td> + <select id="text_variant" name="text_variant"></select> + </td> + </tr> + <tr> + <td><label for="text_lineheight">{#style_dlg.text_lineheight}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td> + <select id="text_lineheight" name="text_lineheight" class="mceEditableSelect"></select> + </td> + <td>&nbsp;</td> + <td> + <label id="text_lineheight_measurement_label" for="text_lineheight_measurement" style="display: none; visibility: hidden;">Line Height Measurement Unit</label> + <select id="text_lineheight_measurement" name="text_lineheight_measurement" aria-labelledby="text_lineheight_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td><label for="text_case">{#style_dlg.text_case}</label></td> + <td> + <select id="text_case" name="text_case"></select> + </td> + </tr> + <tr> + <td><label for="text_color">{#style_dlg.text_color}</label></td> + <td colspan="2"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="text_color" name="text_color" type="text" value="" size="9" onChange="updateColor('text_color_pick','text_color');" /></td> + <td id="text_color_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + <tr> + <td valign="top" style="vertical-align: top; padding-top: 3px;">{#style_dlg.text_decoration}</td> + <td colspan="2"> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="text_underline" name="text_underline" class="checkbox" type="checkbox" /></td> + <td><label for="text_underline">{#style_dlg.text_underline}</label></td> + </tr> + <tr> + <td><input id="text_overline" name="text_overline" class="checkbox" type="checkbox" /></td> + <td><label for="text_overline">{#style_dlg.text_overline}</label></td> + </tr> + <tr> + <td><input id="text_linethrough" name="text_linethrough" class="checkbox" type="checkbox" /></td> + <td><label for="text_linethrough">{#style_dlg.text_striketrough}</label></td> + </tr> + <tr> + <td><input id="text_blink" name="text_blink" class="checkbox" type="checkbox" /></td> + <td><label for="text_blink">{#style_dlg.text_blink}</label></td> + </tr> + <tr> + <td><input id="text_none" name="text_none" class="checkbox" type="checkbox" /></td> + <td><label for="text_none">{#style_dlg.text_none}</label></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> + +<div id="background_panel" class="panel"> + <fieldset> + <legend>{#style_dlg.background}</legend> + <table role="presentation" border="0"> + <tr> + <td><label for="background_color">{#style_dlg.background_color}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="background_color" name="background_color" type="text" value="" size="9" onChange="updateColor('background_color_pick','background_color');" /></td> + <td id="background_color_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="background_image">{#style_dlg.background_image}</label></td> + <td><table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="background_image" name="background_image" type="text" /></td> + <td id="background_image_browser">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="background_repeat">{#style_dlg.background_repeat}</label></td> + <td><select id="background_repeat" name="background_repeat" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="background_attachment">{#style_dlg.background_attachment}</label></td> + <td><select id="background_attachment" name="background_attachment" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="background_hpos">{#style_dlg.background_hpos}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="background_hpos" name="background_hpos" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + <label id="background_hpos_measurement_label" for="background_hpos_measurement" style="display: none; visibility: hidden;">Horizontal position measurement unit</label> + <select id="background_hpos_measurement" name="background_hpos_measurement" aria-labelledby="background_hpos_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="background_vpos">{#style_dlg.background_vpos}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="background_vpos" name="background_vpos" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + + <label id="background_vpos_measurement_label" for="background_vpos_measurement" style="display: none; visibility: hidden;">Vertical position measurement unit</label> + <select id="background_vpos_measurement" name="background_vpos_measurement" aria-labelledby="background_vpos_measurement_label">></select></td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> + +<div id="block_panel" class="panel"> + <fieldset> + <legend>{#style_dlg.block}</legend> + <table role="presentation" border="0"> + <tr> + <td><label for="block_wordspacing">{#style_dlg.block_wordspacing}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="block_wordspacing" name="block_wordspacing" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + <label id="block_wordspacing_measurement_label" for="block_wordspacing_measurement" style="display: none; visibility: hidden;">Word spacing measurement unit</label> + <select id="block_wordspacing_measurement" name="block_wordspacing_measurement" aria-labelledby="block_wordspacing_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="block_letterspacing">{#style_dlg.block_letterspacing}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="block_letterspacing" name="block_letterspacing" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + <label id="block_letterspacing_measurement_label" for="block_letterspacing_measurement" style="display: none; visibility: hidden;">Letter spacing measurement unit</label> + <select id="block_letterspacing_measurement" name="block_letterspacing_measurement" aria-labelledby="block_letterspacing_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="block_vertical_alignment">{#style_dlg.block_vertical_alignment}</label></td> + <td><select id="block_vertical_alignment" name="block_vertical_alignment" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="block_text_align">{#style_dlg.block_text_align}</label></td> + <td><select id="block_text_align" name="block_text_align" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="block_text_indent">{#style_dlg.block_text_indent}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="block_text_indent" name="block_text_indent" /></td> + <td>&nbsp;</td> + <td> + <label id="block_text_indent_measurement_label" for="block_text_indent_measurement" style="display: none; visibility: hidden;">Text Indent Measurement Unit</label> + + <select id="block_text_indent_measurement" name="block_text_indent_measurement" aria-labelledby="block_text_indent_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + + <tr> + <td><label for="block_whitespace">{#style_dlg.block_whitespace}</label></td> + <td><select id="block_whitespace" name="block_whitespace" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="block_display">{#style_dlg.block_display}</label></td> + <td><select id="block_display" name="block_display" class="mceEditableSelect"></select></td> + </tr> + </table> + </fieldset> +</div> + +<div id="box_panel" class="panel"> + <fieldset> + <legend>{#style_dlg.box}</legend> + <table role="presentation" border="0"> + <tr> + <td><label for="box_width">{#style_dlg.box_width}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_width" name="box_width" class="mceEditableSelect" onChange="synch('box_width','positioning_width');" /></td> + <td>&nbsp;</td> + <td> + <label id="box_width_measurement_label" for="box_width_measurement" style="display: none; visibility: hidden;">Box Width Measurement Unit</label> + <select id="box_width_measurement" name="box_width_measurement" aria-labelledby="box_width_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td>&nbsp;&nbsp;&nbsp;<label for="box_float">{#style_dlg.box_float}</label></td> + <td><select id="box_float" name="box_float" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="box_height">{#style_dlg.box_height}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_height" name="box_height" class="mceEditableSelect" onChange="synch('box_height','positioning_height');" /></td> + <td>&nbsp;</td> + <td> + <label id="box_height_measurement_label" for="box_height_measurement" style="display: none; visibility: hidden;">Box Height Measurement Unit</label> + <select id="box_height_measurement" name="box_height_measurement" aria-labelledby="box_height_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td>&nbsp;&nbsp;&nbsp;<label for="box_clear">{#style_dlg.box_clear}</label></td> + <td><select id="box_clear" name="box_clear" class="mceEditableSelect"></select></td> + </tr> + </table> + </fieldset> + +<div style="float: left; width: 49%"> + <fieldset> + <legend>{#style_dlg.padding}</legend> + + <table role="presentation" border="0"> + <tr> + <td>&nbsp;</td> + <td><input type="checkbox" id="box_padding_same" name="box_padding_same" class="checkbox" checked="checked" onClick="toggleSame(this,'box_padding');" /> <label for="box_padding_same">{#style_dlg.same}</label></td> + </tr> + <tr> + <td><label for="box_padding_top">{#style_dlg.top}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_padding_top" name="box_padding_top" class="mceEditableSelect" /></td> + <td>&nbsp;</td> + <td> + <label id="box_padding_top_measurement_label" for="box_padding_top_measurement" style="display: none; visibility: hidden;">Padding Top Measurement Unit</label> + <select id="box_padding_top_measurement" name="box_padding_top_measurement" aria-labelledby="box_padding_top_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_padding_right">{#style_dlg.right}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_padding_right" name="box_padding_right" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_padding_right_measurement_label" for="box_padding_right_measurement" style="display: none; visibility: hidden;">Padding Right Measurement Unit</label> + <select id="box_padding_right_measurement" name="box_padding_right_measurement" disabled="disabled" aria-labelledby="box_padding_right_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_padding_bottom">{#style_dlg.bottom}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_padding_bottom" name="box_padding_bottom" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_padding_bottom_measurement_label" for="box_padding_bottom_measurement" style="display: none; visibility: hidden;">Padding Bottom Measurement Unit</label> + <select id="box_padding_bottom_measurement" name="box_padding_bottom_measurement" disabled="disabled" aria-labelledby="box_padding_bottom_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_padding_left">{#style_dlg.left}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_padding_left" name="box_padding_left" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_padding_left_measurement_label" for="box_padding_left_measurement" style="display: none; visibility: hidden;">Padding Left Measurement Unit</label> + <select id="box_padding_left_measurement" name="box_padding_left_measurement" disabled="disabled" aria-labelledby="box_padding_left_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> + +<div style="float: right; width: 49%"> + <fieldset> + <legend>{#style_dlg.margin}</legend> + + <table role="presentation" border="0"> + <tr> + <td>&nbsp;</td> + <td><input type="checkbox" id="box_margin_same" name="box_margin_same" class="checkbox" checked="checked" onClick="toggleSame(this,'box_margin');" /> <label for="box_margin_same">{#style_dlg.same}</label></td> + </tr> + <tr> + <td><label for="box_margin_top">{#style_dlg.top}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_margin_top" name="box_margin_top" class="mceEditableSelect" /></td> + <td>&nbsp;</td> + <td> + <label id="box_margin_top_measurement_label" for="box_margin_top_measurement" style="display: none; visibility: hidden;">Margin Top Measurement Unit</label> + <select id="box_margin_top_measurement" name="box_margin_top_measurement" aria-labelledby="box_margin_top_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_margin_right">{#style_dlg.right}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_margin_right" name="box_margin_right" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_margin_right_measurement_label" for="box_margin_right_measurement" style="display: none; visibility: hidden;">Margin Right Measurement Unit</label> + <select id="box_margin_right_measurement" name="box_margin_right_measurement" disabled="disabled" aria-labelledby="box_margin_right_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_margin_bottom">{#style_dlg.bottom}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_margin_bottom" name="box_margin_bottom" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_margin_bottom_measurement_label" for="box_margin_bottom_measurement" style="display: none; visibility: hidden;">Margin Bottom Measurement Unit</label> + <select id="box_margin_bottom_measurement" name="box_margin_bottom_measurement" disabled="disabled" aria-labelledby="box_margin_bottom_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td><label for="box_margin_left">{#style_dlg.left}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="box_margin_left" name="box_margin_left" class="mceEditableSelect" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="box_margin_left_measurement_label" for="box_margin_left_measurement" style="display: none; visibility: hidden;">Margin Left Measurement Unit</label> + <select id="box_margin_left_measurement" name="box_margin_left_measurement" disabled="disabled" aria-labelledby="box_margin_left_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> +<br style="clear: both" /> +</div> + +<div id="border_panel" class="panel"> + <fieldset> + <legend>{#style_dlg.border}</legend> + <table role="presentation" border="0" cellspacing="0" cellpadding="0" width="100%"> + <tr> + <td class="tdelim">&nbsp;</td> + <td class="tdelim delim">&nbsp;</td> + <td class="tdelim">{#style_dlg.style}</td> + <td class="tdelim delim">&nbsp;</td> + <td class="tdelim">{#style_dlg.width}</td> + <td class="tdelim delim">&nbsp;</td> + <td class="tdelim">{#style_dlg.color}</td> + </tr> + + <tr> + <td>&nbsp;</td> + <td class="delim">&nbsp;</td> + <td><input type="checkbox" id="border_style_same" name="border_style_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_style');" /> <label for="border_style_same">{#style_dlg.same}</label></td> + <td class="delim">&nbsp;</td> + <td><input type="checkbox" id="border_width_same" name="border_width_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_width');" /> <label for="border_width_same">{#style_dlg.same}</label></td> + <td class="delim">&nbsp;</td> + <td><input type="checkbox" id="border_color_same" name="border_color_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_color');" /> <label for="border_color_same">{#style_dlg.same}</label></td> + </tr> + + <tr> + <td>{#style_dlg.top}</td> + <td class="delim">&nbsp;</td> + <td><select id="border_style_top" name="border_style_top" class="mceEditableSelect"></select></td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="border_width_top" name="border_width_top" class="mceEditableSelect"></select></td> + <td>&nbsp;</td> + <td> + <label id="border_width_top_measurement_label" for="border_width_top_measurement" style="display: none; visibility: hidden;">Width top Measurement Unit</label> + <select id="border_width_top_measurement" name="border_width_top_measurement" aria-labelledby="border_width_top_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="border_color_top" name="border_color_top" type="text" value="" size="9" onChange="updateColor('border_color_top_pick','border_color_top');" /></td> + <td id="border_color_top_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td>{#style_dlg.right}</td> + <td class="delim">&nbsp;</td> + <td><select id="border_style_right" name="border_style_right" class="mceEditableSelect" disabled="disabled"></select></td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="border_width_right" name="border_width_right" class="mceEditableSelect" disabled="disabled"></select></td> + <td>&nbsp;</td> + <td> + <label id="border_width_right_measurement_label" for="border_width_right_measurement" style="display: none; visibility: hidden;">Width Right Measurement Unit</label> + <select id="border_width_right_measurement" name="border_width_right_measurement" disabled="disabled" aria-labelledby="border_width_right_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="border_color_right" name="border_color_right" type="text" value="" size="9" onChange="updateColor('border_color_right_pick','border_color_right');" disabled="disabled" /></td> + <td id="border_color_right_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td>{#style_dlg.bottom}</td> + <td class="delim">&nbsp;</td> + <td><select id="border_style_bottom" name="border_style_bottom" class="mceEditableSelect" disabled="disabled"></select></td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="border_width_bottom" name="border_width_bottom" class="mceEditableSelect" disabled="disabled"></select></td> + <td>&nbsp;</td> + <td> + <label id="border_width_bottom_measurement_label" for="border_width_bottom_measurement" style="display: none; visibility: hidden;">Width Bottom Measurement Unit</label> + <select id="border_width_bottom_measurement" name="border_width_bottom_measurement" disabled="disabled" aria-labelledby="border_width_bottom_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="border_color_bottom" name="border_color_bottom" type="text" value="" size="9" onChange="updateColor('border_color_bottom_pick','border_color_bottom');" disabled="disabled" /></td> + <td id="border_color_bottom_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td>{#style_dlg.left}</td> + <td class="delim">&nbsp;</td> + <td><select id="border_style_left" name="border_style_left" class="mceEditableSelect" disabled="disabled"></select></td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><select id="border_width_left" name="border_width_left" class="mceEditableSelect" disabled="disabled"></select></td> + <td>&nbsp;</td> + <td> + <label id="border_width_left_measurement_label" for="border_width_left_measurement" style="display: none; visibility: hidden;">Width Left Measurement Unit</label> + <select id="border_width_left_measurement" name="border_width_left_measurement" disabled="disabled" aria-labelledby="border_width_left_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td class="delim">&nbsp;</td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="border_color_left" name="border_color_left" type="text" value="" size="9" onChange="updateColor('border_color_left_pick','border_color_left');" disabled="disabled" /></td> + <td id="border_color_left_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> + +<div id="list_panel" class="panel"> +<fieldset> + <legend>{#style_dlg.list}</legend> + <table role="presentation" border="0"> + <tr> + <td><label for="list_type">{#style_dlg.list_type}</label></td> + <td><select id="list_type" name="list_type" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="list_bullet_image">{#style_dlg.bullet_image}</label></td> + <td><input id="list_bullet_image" name="list_bullet_image" type="text" /></td> + </tr> + + <tr> + <td><label for="list_position">{#style_dlg.position}</label></td> + <td><select id="list_position" name="list_position" class="mceEditableSelect"></select></td> + </tr> + </table> +</fieldset> +</div> + +<div id="positioning_panel" class="panel"> +<fieldset> + <legend>{#style_dlg.position}</legend> +<table role="presentation" border="0"> + <tr> + <td><label for="positioning_type">{#style_dlg.positioning_type}</label></td> + <td><select id="positioning_type" name="positioning_type" class="mceEditableSelect"></select></td> + <td>&nbsp;&nbsp;&nbsp;<label for="positioning_visibility">{#style_dlg.visibility}</label></td> + <td><select id="positioning_visibility" name="positioning_visibility" class="mceEditableSelect"></select></td> + </tr> + + <tr> + <td><label for="positioning_width">{#style_dlg.width}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_width" name="positioning_width" onChange="synch('positioning_width','box_width');" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_width_measurement_label" for="positioning_width_measurement" style="display: none; visibility: hidden;">Positioning width Measurement Unit</label> + <select id="positioning_width_measurement" name="positioning_width_measurement" aria-labelledby="positioning_width_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td>&nbsp;&nbsp;&nbsp;<label for="positioning_zindex">{#style_dlg.zindex}</label></td> + <td><input type="text" id="positioning_zindex" name="positioning_zindex" /></td> + </tr> + + <tr> + <td><label for="positioning_height">{#style_dlg.height}</label></td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_height" name="positioning_height" onChange="synch('positioning_height','box_height');" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_height_measurement_label" for="positioning_height_measurement" style="display: none; visibility: hidden;">Positioning Height Measurement Unit</label> + <select id="positioning_height_measurement" name="positioning_height_measurement" aria-labelledby="positioning_height_measurement_label"></select> + </td> + </tr> + </table> + </td> + <td>&nbsp;&nbsp;&nbsp;<label for="positioning_overflow">{#style_dlg.overflow}</label></td> + <td><select id="positioning_overflow" name="positioning_overflow" class="mceEditableSelect"></select></td> + </tr> +</table> +</fieldset> + +<div style="float: left; width: 49%"> + <fieldset> + <legend>{#style_dlg.placement}</legend> + + <table role="presentation" border="0"> + <tr> + <td>&nbsp;</td> + <td><input type="checkbox" id="positioning_placement_same" name="positioning_placement_same" class="checkbox" checked="checked" onClick="toggleSame(this,'positioning_placement');" /> <label for="positioning_placement_same">{#style_dlg.same}</label></td> + </tr> + <tr> + <td>{#style_dlg.top}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_placement_top" name="positioning_placement_top" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_placement_top_measurement_label" for="positioning_placement_top_measurement" style="display: none; visibility: hidden;">Placement Top Measurement Unit</label> + <select id="positioning_placement_top_measurement" name="positioning_placement_top_measurement" aria-labelledby="positioning_placement_top_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.right}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_placement_right" name="positioning_placement_right" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_placement_right_measurement_label" for="positioning_placement_right_measurement" style="display: none; visibility: hidden;">Placement Right Measurement Unit</label> + <select id="positioning_placement_right_measurement" name="positioning_placement_right_measurement" disabled="disabled" aria-labelledby="positioning_placement_right_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.bottom}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_placement_bottom" name="positioning_placement_bottom" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_placement_bottom_measurement_label" for="positioning_placement_bottom_measurement" style="display: none; visibility: hidden;">Placement Bottom Measurement Unit</label> + <select id="positioning_placement_bottom_measurement" name="positioning_placement_bottom_measurement" disabled="disabled" aria-labelledby="positioning_placement_bottom_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.left}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_placement_left" name="positioning_placement_left" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_placement_left_measurement_label" for="positioning_placement_left_measurement" style="display: none; visibility: hidden;">Placement Left Measurement Unit</label> + <select id="positioning_placement_left_measurement" name="positioning_placement_left_measurement" disabled="disabled" aria-labelledby="positioning_placement_left_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> + +<div style="float: right; width: 49%"> + <fieldset> + <legend>{#style_dlg.clip}</legend> + + <table role="presentation" border="0"> + <tr> + <td>&nbsp;</td> + <td><input type="checkbox" id="positioning_clip_same" name="positioning_clip_same" class="checkbox" checked="checked" onClick="toggleSame(this,'positioning_clip');" /> <label for="positioning_clip_same">{#style_dlg.same}</label></td> + </tr> + <tr> + <td>{#style_dlg.top}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_clip_top" name="positioning_clip_top" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_clip_top_measurement_label" for="positioning_clip_top_measurement" style="display: none; visibility: hidden;">Clip Top Measurement Unit</label> + <select id="positioning_clip_top_measurement" name="positioning_clip_top_measurement" aria-labelledby="positioning_clip_top_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.right}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_clip_right" name="positioning_clip_right" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_clip_right_measurement_label" for="positioning_clip_right_measurement" style="display: none; visibility: hidden;">Clip Right Measurement Unit</label> + <select id="positioning_clip_right_measurement" name="positioning_clip_right_measurement" disabled="disabled" aria-labelledby="positioning_clip_right_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.bottom}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_clip_bottom" name="positioning_clip_bottom" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_clip_bottom_measurement_label" for="positioning_clip_bottom_measurement" style="display: none; visibility: hidden;">Clip Bottom Measurement Unit</label> + <select id="positioning_clip_bottom_measurement" name="positioning_clip_bottom_measurement" disabled="disabled" aria-labelledby="positioning_clip_bottom_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + <tr> + <td>{#style_dlg.left}</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input type="text" id="positioning_clip_left" name="positioning_clip_left" disabled="disabled" /></td> + <td>&nbsp;</td> + <td> + <label id="positioning_clip_left_measurement_label" for="positioning_clip_left_measurement" style="display: none; visibility: hidden;">Clip Left Measurement Unit</label> + <select id="positioning_clip_left_measurement" name="positioning_clip_left_measurement" disabled="disabled" aria-labelledby="positioning_clip_left_measurement_label"></select> + </td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> +</div> +<br style="clear: both" /> +</div> +</div> + +<div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" class="button" id="apply" name="apply" value="{#style_dlg.apply}" onClick="applyAction();" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onClick="tinyMCEPopup.close();" /> +</div> +</form> + +<div style="display: none"> + <div id="container"></div> +</div> + +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/tabfocus/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/tabfocus/editor_plugin.js new file mode 100644 index 0000000..42a82d1 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/tabfocus/editor_plugin.js @@ -0,0 +1 @@ +(function(){var c=tinymce.DOM,a=tinymce.dom.Event,d=tinymce.each,b=tinymce.explode;tinymce.create("tinymce.plugins.TabFocusPlugin",{init:function(f,g){function e(i,j){if(j.keyCode===9){return a.cancel(j)}}function h(l,p){var j,m,o,n,k;function q(t){n=c.select(":input:enabled,*[tabindex]");function s(v){return v.nodeName==="BODY"||(v.type!="hidden"&&!(v.style.display=="none")&&!(v.style.visibility=="hidden")&&s(v.parentNode))}function i(v){return v.attributes.tabIndex.specified||v.nodeName=="INPUT"||v.nodeName=="TEXTAREA"}function u(){return tinymce.isIE6||tinymce.isIE7}function r(v){return((!u()||i(v)))&&v.getAttribute("tabindex")!="-1"&&s(v)}d(n,function(w,v){if(w.id==l.id){j=v;return false}});if(t>0){for(m=j+1;m<n.length;m++){if(r(n[m])){return n[m]}}}else{for(m=j-1;m>=0;m--){if(r(n[m])){return n[m]}}}return null}if(p.keyCode===9){k=b(l.getParam("tab_focus",l.getParam("tabfocus_elements",":prev,:next")));if(k.length==1){k[1]=k[0];k[0]=":prev"}if(p.shiftKey){if(k[0]==":prev"){n=q(-1)}else{n=c.get(k[0])}}else{if(k[1]==":next"){n=q(1)}else{n=c.get(k[1])}}if(n){if(n.id&&(l=tinymce.get(n.id||n.name))){l.focus()}else{window.setTimeout(function(){if(!tinymce.isWebKit){window.focus()}n.focus()},10)}return a.cancel(p)}}}f.onKeyUp.add(e);if(tinymce.isGecko){f.onKeyPress.add(h);f.onKeyDown.add(e)}else{f.onKeyDown.add(h)}},getInfo:function(){return{longname:"Tabfocus",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/tabfocus",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("tabfocus",tinymce.plugins.TabFocusPlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/tabfocus/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/tabfocus/editor_plugin_src.js new file mode 100644 index 0000000..a1579c8 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/tabfocus/editor_plugin_src.js @@ -0,0 +1,122 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, explode = tinymce.explode; + + tinymce.create('tinymce.plugins.TabFocusPlugin', { + init : function(ed, url) { + function tabCancel(ed, e) { + if (e.keyCode === 9) + return Event.cancel(e); + } + + function tabHandler(ed, e) { + var x, i, f, el, v; + + function find(d) { + el = DOM.select(':input:enabled,*[tabindex]'); + + function canSelectRecursive(e) { + return e.nodeName==="BODY" || (e.type != 'hidden' && + !(e.style.display == "none") && + !(e.style.visibility == "hidden") && canSelectRecursive(e.parentNode)); + } + function canSelectInOldIe(el) { + return el.attributes["tabIndex"].specified || el.nodeName == "INPUT" || el.nodeName == "TEXTAREA"; + } + function isOldIe() { + return tinymce.isIE6 || tinymce.isIE7; + } + function canSelect(el) { + return ((!isOldIe() || canSelectInOldIe(el))) && el.getAttribute("tabindex") != '-1' && canSelectRecursive(el); + } + + each(el, function(e, i) { + if (e.id == ed.id) { + x = i; + return false; + } + }); + if (d > 0) { + for (i = x + 1; i < el.length; i++) { + if (canSelect(el[i])) + return el[i]; + } + } else { + for (i = x - 1; i >= 0; i--) { + if (canSelect(el[i])) + return el[i]; + } + } + + return null; + } + + if (e.keyCode === 9) { + v = explode(ed.getParam('tab_focus', ed.getParam('tabfocus_elements', ':prev,:next'))); + + if (v.length == 1) { + v[1] = v[0]; + v[0] = ':prev'; + } + + // Find element to focus + if (e.shiftKey) { + if (v[0] == ':prev') + el = find(-1); + else + el = DOM.get(v[0]); + } else { + if (v[1] == ':next') + el = find(1); + else + el = DOM.get(v[1]); + } + + if (el) { + if (el.id && (ed = tinymce.get(el.id || el.name))) + ed.focus(); + else + window.setTimeout(function() { + if (!tinymce.isWebKit) + window.focus(); + el.focus(); + }, 10); + + return Event.cancel(e); + } + } + } + + ed.onKeyUp.add(tabCancel); + + if (tinymce.isGecko) { + ed.onKeyPress.add(tabHandler); + ed.onKeyDown.add(tabCancel); + } else + ed.onKeyDown.add(tabHandler); + + }, + + getInfo : function() { + return { + longname : 'Tabfocus', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/tabfocus', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('tabfocus', tinymce.plugins.TabFocusPlugin); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/cell.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/cell.htm new file mode 100644 index 0000000..a72a8d6 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/cell.htm @@ -0,0 +1,180 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#table_dlg.cell_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/cell.js"></script> + <link href="css/cell.css" rel="stylesheet" type="text/css" /> +</head> +<body id="tablecell" style="display: none" role="application"> + <form onsubmit="updateAction();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#table_dlg.general_props}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td><label for="align">{#table_dlg.align}</label></td> + <td> + <select id="align" name="align" class="mceFocus"> + <option value="">{#not_set}</option> + <option value="center">{#table_dlg.align_middle}</option> + <option value="left">{#table_dlg.align_left}</option> + <option value="right">{#table_dlg.align_right}</option> + </select> + </td> + + <td><label for="celltype">{#table_dlg.cell_type}</label></td> + <td> + <select id="celltype" name="celltype"> + <option value="td">{#table_dlg.td}</option> + <option value="th">{#table_dlg.th}</option> + </select> + </td> + </tr> + + <tr> + <td><label for="valign">{#table_dlg.valign}</label></td> + <td> + <select id="valign" name="valign"> + <option value="">{#not_set}</option> + <option value="top">{#table_dlg.align_top}</option> + <option value="middle">{#table_dlg.align_middle}</option> + <option value="bottom">{#table_dlg.align_bottom}</option> + </select> + </td> + + <td><label for="scope">{#table_dlg.scope}</label></td> + <td> + <select id="scope" name="scope"> + <option value="">{#not_set}</option> + <option value="col">{#table.col}</option> + <option value="row">{#table.row}</option> + <option value="rowgroup">{#table_dlg.rowgroup}</option> + <option value="colgroup">{#table_dlg.colgroup}</option> + </select> + </td> + + </tr> + + <tr> + <td><label for="width">{#table_dlg.width}</label></td> + <td><input id="width" name="width" type="text" value="" size="7" maxlength="7" onchange="changedSize();" class="size" /></td> + + <td><label for="height">{#table_dlg.height}</label></td> + <td><input id="height" name="height" type="text" value="" size="7" maxlength="7" onchange="changedSize();" class="size" /></td> + </tr> + + <tr id="styleSelectRow"> + <td><label for="class">{#class_name}</label></td> + <td colspan="3"> + <select id="class" name="class" class="mceEditableSelect"> + <option value="" selected="selected">{#not_set}</option> + </select> + </td> + </tr> + </table> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#table_dlg.advanced_props}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="column1"><label for="id">{#table_dlg.id}</label></td> + <td><input id="id" name="id" type="text" value="" style="width: 200px" /></td> + </tr> + + <tr> + <td><label for="style">{#table_dlg.style}</label></td> + <td><input type="text" id="style" name="style" value="" style="width: 200px;" onchange="changedStyle();" /></td> + </tr> + + <tr> + <td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> + <td> + <select id="dir" name="dir" style="width: 200px"> + <option value="">{#not_set}</option> + <option value="ltr">{#table_dlg.ltr}</option> + <option value="rtl">{#table_dlg.rtl}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="lang">{#table_dlg.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" style="width: 200px" /> + </td> + </tr> + + <tr> + <td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="backgroundimage" name="backgroundimage" type="text" value="" style="width: 200px" onchange="changedBackgroundImage();" /></td> + <td id="backgroundimagebrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr role="group" aria-labelledby="bordercolor_label"> + <td class="column1"><label id="bordercolor_label" for="bordercolor">{#table_dlg.bordercolor}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bordercolor" name="bordercolor" type="text" value="" size="9" onchange="updateColor('bordercolor_pick','bordercolor');changedColor();" /></td> + <td id="bordercolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr role="group" aria-labelledby="bgcolor_label"> + <td class="column1"><label id="bgcolor_label" for="bgcolor">{#table_dlg.bgcolor}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');changedColor();" /></td> + <td id="bgcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <div> + <select id="action" name="action"> + <option value="cell">{#table_dlg.cell_cell}</option> + <option value="row">{#table_dlg.cell_row}</option> + <option value="col">{#table_dlg.cell_col}</option> + <option value="all">{#table_dlg.cell_all}</option> + </select> + </div> + + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/cell.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/cell.css new file mode 100644 index 0000000..a067ecd --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/cell.css @@ -0,0 +1,17 @@ +/* CSS file for cell dialog in the table plugin */ + +.panel_wrapper div.current { + height: 200px; +} + +.advfield { + width: 200px; +} + +#action { + margin-bottom: 3px; +} + +#class { + width: 150px; +} \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/row.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/row.css new file mode 100644 index 0000000..1f7755d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/row.css @@ -0,0 +1,25 @@ +/* CSS file for row dialog in the table plugin */ + +.panel_wrapper div.current { + height: 200px; +} + +.advfield { + width: 200px; +} + +#action { + margin-bottom: 3px; +} + +#rowtype,#align,#valign,#class,#height { + width: 150px; +} + +#height { + width: 50px; +} + +.col2 { + padding-left: 20px; +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/table.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/table.css new file mode 100644 index 0000000..d11c3f6 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/css/table.css @@ -0,0 +1,13 @@ +/* CSS file for table dialog in the table plugin */ + +.panel_wrapper div.current { + height: 245px; +} + +.advfield { + width: 200px; +} + +#class { + width: 150px; +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/editor_plugin.js new file mode 100644 index 0000000..94e3c21 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/editor_plugin.js @@ -0,0 +1 @@ +(function(d){var e=d.each;function c(g,h){var j=h.ownerDocument,f=j.createRange(),k;f.setStartBefore(h);f.setEnd(g.endContainer,g.endOffset);k=j.createElement("body");k.appendChild(f.cloneContents());return k.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length==0}function a(g,f){return parseInt(g.getAttribute(f)||1)}function b(H,G,K){var g,L,D,o;t();o=G.getParent(K.getStart(),"th,td");if(o){L=F(o);D=I();o=z(L.x,L.y)}function A(N,M){N=N.cloneNode(M);N.removeAttribute("id");return N}function t(){var M=0;g=[];e(["thead","tbody","tfoot"],function(N){var O=G.select("> "+N+" tr",H);e(O,function(P,Q){Q+=M;e(G.select("> td, > th",P),function(W,R){var S,T,U,V;if(g[Q]){while(g[Q][R]){R++}}U=a(W,"rowspan");V=a(W,"colspan");for(T=Q;T<Q+U;T++){if(!g[T]){g[T]=[]}for(S=R;S<R+V;S++){g[T][S]={part:N,real:T==Q&&S==R,elm:W,rowspan:U,colspan:V}}}})});M+=O.length})}function z(M,O){var N;N=g[O];if(N){return N[M]}}function s(O,M,N){if(O){N=parseInt(N);if(N===1){O.removeAttribute(M,1)}else{O.setAttribute(M,N,1)}}}function j(M){return M&&(G.hasClass(M.elm,"mceSelected")||M==o)}function k(){var M=[];e(H.rows,function(N){e(N.cells,function(O){if(G.hasClass(O,"mceSelected")||O==o.elm){M.push(N);return false}})});return M}function r(){var M=G.createRng();M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H)}function f(M){var N;d.walk(M,function(P){var O;if(P.nodeType==3){e(G.getParents(P.parentNode,null,M).reverse(),function(Q){Q=A(Q,false);if(!N){N=O=Q}else{if(O){O.appendChild(Q)}}O=Q});if(O){O.innerHTML=d.isIE?"&nbsp;":'<br data-mce-bogus="1" />'}return false}},"childNodes");M=A(M,false);s(M,"rowSpan",1);s(M,"colSpan",1);if(N){M.appendChild(N)}else{if(!d.isIE){M.innerHTML='<br data-mce-bogus="1" />'}}return M}function q(){var M=G.createRng();e(G.select("tr",H),function(N){if(N.cells.length==0){G.remove(N)}});if(G.select("tr",H).length==0){M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H);return}e(G.select("thead,tbody,tfoot",H),function(N){if(N.rows.length==0){G.remove(N)}});t();row=g[Math.min(g.length-1,L.y)];if(row){K.select(row[Math.min(row.length-1,L.x)].elm,true);K.collapse(true)}}function u(S,Q,U,R){var P,N,M,O,T;P=g[Q][S].elm.parentNode;for(M=1;M<=U;M++){P=G.getNext(P,"tr");if(P){for(N=S;N>=0;N--){T=g[Q+M][N].elm;if(T.parentNode==P){for(O=1;O<=R;O++){G.insertAfter(f(T),T)}break}}if(N==-1){for(O=1;O<=R;O++){P.insertBefore(f(P.cells[0]),P.cells[0])}}}}}function C(){e(g,function(M,N){e(M,function(P,O){var S,R,T,Q;if(j(P)){P=P.elm;S=a(P,"colspan");R=a(P,"rowspan");if(S>1||R>1){s(P,"rowSpan",1);s(P,"colSpan",1);for(Q=0;Q<S-1;Q++){G.insertAfter(f(P),P)}u(O,N,R-1,S)}}})})}function p(V,S,Y){var P,O,X,W,U,R,T,M,V,N,Q;if(V){pos=F(V);P=pos.x;O=pos.y;X=P+(S-1);W=O+(Y-1)}else{P=L.x;O=L.y;X=D.x;W=D.y}T=z(P,O);M=z(X,W);if(T&&M&&T.part==M.part){C();t();T=z(P,O).elm;s(T,"colSpan",(X-P)+1);s(T,"rowSpan",(W-O)+1);for(R=O;R<=W;R++){for(U=P;U<=X;U++){if(!g[R]||!g[R][U]){continue}V=g[R][U].elm;if(V!=T){N=d.grep(V.childNodes);e(N,function(Z){T.appendChild(Z)});if(N.length){N=d.grep(T.childNodes);Q=0;e(N,function(Z){if(Z.nodeName=="BR"&&G.getAttrib(Z,"data-mce-bogus")&&Q++<N.length-1){T.removeChild(Z)}})}G.remove(V)}}}q()}}function l(Q){var M,S,P,R,T,U,N,V,O;e(g,function(W,X){e(W,function(Z,Y){if(j(Z)){Z=Z.elm;T=Z.parentNode;U=A(T,false);M=X;if(Q){return false}}});if(Q){return !M}});for(R=0;R<g[0].length;R++){if(!g[M][R]){continue}S=g[M][R].elm;if(S!=P){if(!Q){O=a(S,"rowspan");if(O>1){s(S,"rowSpan",O+1);continue}}else{if(M>0&&g[M-1][R]){V=g[M-1][R].elm;O=a(V,"rowSpan");if(O>1){s(V,"rowSpan",O+1);continue}}}N=f(S);s(N,"colSpan",S.colSpan);U.appendChild(N);P=S}}if(U.hasChildNodes()){if(!Q){G.insertAfter(U,T)}else{T.parentNode.insertBefore(U,T)}}}function h(N){var O,M;e(g,function(P,Q){e(P,function(S,R){if(j(S)){O=R;if(N){return false}}});if(N){return !O}});e(g,function(S,T){var P,Q,R;if(!S[O]){return}P=S[O].elm;if(P!=M){R=a(P,"colspan");Q=a(P,"rowspan");if(R==1){if(!N){G.insertAfter(f(P),P);u(O,T,Q-1,R)}else{P.parentNode.insertBefore(f(P),P);u(O,T,Q-1,R)}}else{s(P,"colSpan",P.colSpan+1)}M=P}})}function n(){var M=[];e(g,function(N,O){e(N,function(Q,P){if(j(Q)&&d.inArray(M,P)===-1){e(g,function(T){var R=T[P].elm,S;S=a(R,"colSpan");if(S>1){s(R,"colSpan",S-1)}else{G.remove(R)}});M.push(P)}})});q()}function m(){var N;function M(Q){var P,R,O;P=G.getNext(Q,"tr");e(Q.cells,function(S){var T=a(S,"rowSpan");if(T>1){s(S,"rowSpan",T-1);R=F(S);u(R.x,R.y,1,1)}});R=F(Q.cells[0]);e(g[R.y],function(S){var T;S=S.elm;if(S!=O){T=a(S,"rowSpan");if(T<=1){G.remove(S)}else{s(S,"rowSpan",T-1)}O=S}})}N=k();e(N.reverse(),function(O){M(O)});q()}function E(){var M=k();G.remove(M);q();return M}function J(){var M=k();e(M,function(O,N){M[N]=A(O,true)});return M}function B(O,N){var P=k(),M=P[N?0:P.length-1],Q=M.cells.length;e(g,function(S){var R;Q=0;e(S,function(U,T){if(U.real){Q+=U.colspan}if(U.elm.parentNode==M){R=1}});if(R){return false}});if(!N){O.reverse()}e(O,function(T){var S=T.cells.length,R;for(i=0;i<S;i++){R=T.cells[i];s(R,"colSpan",1);s(R,"rowSpan",1)}for(i=S;i<Q;i++){T.appendChild(f(T.cells[S-1]))}for(i=Q;i<S;i++){G.remove(T.cells[i])}if(N){M.parentNode.insertBefore(T,M)}else{G.insertAfter(T,M)}})}function F(M){var N;e(g,function(O,P){e(O,function(R,Q){if(R.elm==M){N={x:Q,y:P};return false}});return !N});return N}function w(M){L=F(M)}function I(){var O,N,M;N=M=0;e(g,function(P,Q){e(P,function(S,R){var U,T;if(j(S)){S=g[Q][R];if(R>N){N=R}if(Q>M){M=Q}if(S.real){U=S.colspan-1;T=S.rowspan-1;if(U){if(R+U>N){N=R+U}}if(T){if(Q+T>M){M=Q+T}}}}})});return{x:N,y:M}}function v(S){var P,O,U,T,N,M,Q,R;D=F(S);if(L&&D){P=Math.min(L.x,D.x);O=Math.min(L.y,D.y);U=Math.max(L.x,D.x);T=Math.max(L.y,D.y);N=U;M=T;for(y=O;y<=M;y++){S=g[y][P];if(!S.real){if(P-(S.colspan-1)<P){P-=S.colspan-1}}}for(x=P;x<=N;x++){S=g[O][x];if(!S.real){if(O-(S.rowspan-1)<O){O-=S.rowspan-1}}}for(y=O;y<=T;y++){for(x=P;x<=U;x++){S=g[y][x];if(S.real){Q=S.colspan-1;R=S.rowspan-1;if(Q){if(x+Q>N){N=x+Q}}if(R){if(y+R>M){M=y+R}}}}}G.removeClass(G.select("td.mceSelected,th.mceSelected"),"mceSelected");for(y=O;y<=M;y++){for(x=P;x<=N;x++){if(g[y][x]){G.addClass(g[y][x].elm,"mceSelected")}}}}}d.extend(this,{deleteTable:r,split:C,merge:p,insertRow:l,insertCol:h,deleteCols:n,deleteRows:m,cutRows:E,copyRows:J,pasteRows:B,getPos:F,setStartCell:w,setEndCell:v})}d.create("tinymce.plugins.TablePlugin",{init:function(g,h){var f,m,j=true;function l(p){var o=g.selection,n=g.dom.getParent(p||o.getNode(),"table");if(n){return new b(n,g.dom,o)}}function k(){g.getBody().style.webkitUserSelect="";if(j){g.dom.removeClass(g.dom.select("td.mceSelected,th.mceSelected"),"mceSelected");j=false}}e([["table","table.desc","mceInsertTable",true],["delete_table","table.del","mceTableDelete"],["delete_col","table.delete_col_desc","mceTableDeleteCol"],["delete_row","table.delete_row_desc","mceTableDeleteRow"],["col_after","table.col_after_desc","mceTableInsertColAfter"],["col_before","table.col_before_desc","mceTableInsertColBefore"],["row_after","table.row_after_desc","mceTableInsertRowAfter"],["row_before","table.row_before_desc","mceTableInsertRowBefore"],["row_props","table.row_desc","mceTableRowProps",true],["cell_props","table.cell_desc","mceTableCellProps",true],["split_cells","table.split_cells_desc","mceTableSplitCells",true],["merge_cells","table.merge_cells_desc","mceTableMergeCells",true]],function(n){g.addButton(n[0],{title:n[1],cmd:n[2],ui:n[3]})});if(!d.isIE){g.onClick.add(function(n,o){o=o.target;if(o.nodeName==="TABLE"){n.selection.select(o);n.nodeChanged()}})}g.onPreProcess.add(function(o,p){var n,q,r,t=o.dom,s;n=t.select("table",p.node);q=n.length;while(q--){r=n[q];t.setAttrib(r,"data-mce-style","");if((s=t.getAttrib(r,"width"))){t.setStyle(r,"width",s);t.setAttrib(r,"width","")}if((s=t.getAttrib(r,"height"))){t.setStyle(r,"height",s);t.setAttrib(r,"height","")}}});g.onNodeChange.add(function(q,o,s){var r;s=q.selection.getStart();r=q.dom.getParent(s,"td,th,caption");o.setActive("table",s.nodeName==="TABLE"||!!r);if(r&&r.nodeName==="CAPTION"){r=0}o.setDisabled("delete_table",!r);o.setDisabled("delete_col",!r);o.setDisabled("delete_table",!r);o.setDisabled("delete_row",!r);o.setDisabled("col_after",!r);o.setDisabled("col_before",!r);o.setDisabled("row_after",!r);o.setDisabled("row_before",!r);o.setDisabled("row_props",!r);o.setDisabled("cell_props",!r);o.setDisabled("split_cells",!r);o.setDisabled("merge_cells",!r)});g.onInit.add(function(r){var p,t,q=r.dom,u;f=r.windowManager;r.onMouseDown.add(function(w,z){if(z.button!=2){k();t=q.getParent(z.target,"td,th");p=q.getParent(t,"table")}});q.bind(r.getDoc(),"mouseover",function(C){var A,z,B=C.target;if(t&&(u||B!=t)&&(B.nodeName=="TD"||B.nodeName=="TH")){z=q.getParent(B,"table");if(z==p){if(!u){u=l(z);u.setStartCell(t);r.getBody().style.webkitUserSelect="none"}u.setEndCell(B);j=true}A=r.selection.getSel();try{if(A.removeAllRanges){A.removeAllRanges()}else{A.empty()}}catch(w){}C.preventDefault()}});r.onMouseUp.add(function(F,G){var z,B=F.selection,H,I=B.getSel(),w,C,A,E;if(t){if(u){F.getBody().style.webkitUserSelect=""}function D(J,L){var K=new d.dom.TreeWalker(J,J);do{if(J.nodeType==3&&d.trim(J.nodeValue).length!=0){if(L){z.setStart(J,0)}else{z.setEnd(J,J.nodeValue.length)}return}if(J.nodeName=="BR"){if(L){z.setStartBefore(J)}else{z.setEndBefore(J)}return}}while(J=(L?K.next():K.prev()))}H=q.select("td.mceSelected,th.mceSelected");if(H.length>0){z=q.createRng();C=H[0];E=H[H.length-1];z.setStartBefore(C);z.setEndAfter(C);D(C,1);w=new d.dom.TreeWalker(C,q.getParent(H[0],"table"));do{if(C.nodeName=="TD"||C.nodeName=="TH"){if(!q.hasClass(C,"mceSelected")){break}A=C}}while(C=w.next());D(A);B.setRng(z)}F.nodeChanged();t=u=p=null}});r.onKeyUp.add(function(w,z){k()});r.onKeyDown.add(function(w,z){n(w)});r.onMouseDown.add(function(w,z){if(z.button!=2){n(w)}});function o(D,z,A,F){var B=3,G=D.dom.getParent(z.startContainer,"TABLE"),C,w,E;if(G){C=G.parentNode}w=z.startContainer.nodeType==B&&z.startOffset==0&&z.endOffset==0&&F&&(A.nodeName=="TR"||A==C);E=(A.nodeName=="TD"||A.nodeName=="TH")&&!F;return w||E}function n(A){if(!d.isWebKit){return}var z=A.selection.getRng();var C=A.selection.getNode();var B=A.dom.getParent(z.startContainer,"TD");if(!o(A,z,C,B)){return}if(!B){B=C}var w=B.lastChild;while(w.lastChild){w=w.lastChild}z.setEnd(w,w.nodeValue.length);A.selection.setRng(z)}r.plugins.table.fixTableCellSelection=n;if(r&&r.plugins.contextmenu){r.plugins.contextmenu.onContextMenu.add(function(A,w,C){var D,B=r.selection,z=B.getNode()||r.getBody();if(r.dom.getParent(C,"td")||r.dom.getParent(C,"th")||r.dom.select("td.mceSelected,th.mceSelected").length){w.removeAll();if(z.nodeName=="A"&&!r.dom.getAttrib(z,"name")){w.add({title:"advanced.link_desc",icon:"link",cmd:r.plugins.advlink?"mceAdvLink":"mceLink",ui:true});w.add({title:"advanced.unlink_desc",icon:"unlink",cmd:"UnLink"});w.addSeparator()}if(z.nodeName=="IMG"&&z.className.indexOf("mceItem")==-1){w.add({title:"advanced.image_desc",icon:"image",cmd:r.plugins.advimage?"mceAdvImage":"mceImage",ui:true});w.addSeparator()}w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable",value:{action:"insert"}});w.add({title:"table.props_desc",icon:"table_props",cmd:"mceInsertTable"});w.add({title:"table.del",icon:"delete_table",cmd:"mceTableDelete"});w.addSeparator();D=w.addMenu({title:"table.cell"});D.add({title:"table.cell_desc",icon:"cell_props",cmd:"mceTableCellProps"});D.add({title:"table.split_cells_desc",icon:"split_cells",cmd:"mceTableSplitCells"});D.add({title:"table.merge_cells_desc",icon:"merge_cells",cmd:"mceTableMergeCells"});D=w.addMenu({title:"table.row"});D.add({title:"table.row_desc",icon:"row_props",cmd:"mceTableRowProps"});D.add({title:"table.row_before_desc",icon:"row_before",cmd:"mceTableInsertRowBefore"});D.add({title:"table.row_after_desc",icon:"row_after",cmd:"mceTableInsertRowAfter"});D.add({title:"table.delete_row_desc",icon:"delete_row",cmd:"mceTableDeleteRow"});D.addSeparator();D.add({title:"table.cut_row_desc",icon:"cut",cmd:"mceTableCutRow"});D.add({title:"table.copy_row_desc",icon:"copy",cmd:"mceTableCopyRow"});D.add({title:"table.paste_row_before_desc",icon:"paste",cmd:"mceTablePasteRowBefore"}).setDisabled(!m);D.add({title:"table.paste_row_after_desc",icon:"paste",cmd:"mceTablePasteRowAfter"}).setDisabled(!m);D=w.addMenu({title:"table.col"});D.add({title:"table.col_before_desc",icon:"col_before",cmd:"mceTableInsertColBefore"});D.add({title:"table.col_after_desc",icon:"col_after",cmd:"mceTableInsertColAfter"});D.add({title:"table.delete_col_desc",icon:"delete_col",cmd:"mceTableDeleteCol"})}else{w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable"})}})}if(d.isWebKit){function v(B,M){function F(Q){B.selection.setCursorLocation(Q,0)}function H(R,Q){return R.keyCode==z?Q.previousSibling:Q.nextSibling}function G(R,S){var Q=H(R,S);return Q!==null&&Q.tagName==="TR"?Q:null}function C(Q,R){return Q.dom.getParent(R,"table")}function O(Q){var R=C(B,Q);return H(M,R)}function A(Q){return Q.keyCode==z||Q.keyCode==I}function D(Q){var S=Q.selection.getNode();var R=Q.dom.getParent(S,"tr");return R!==null}function N(R){var Q=0;var S=R;while(S.previousSibling){S=S.previousSibling;Q=Q+a(S,"colspan")}return Q}function E(S,Q){var T=0;var R=0;e(S.children,function(U,V){T=T+a(U,"colspan");R=V;if(T>Q){return false}});return R}function w(S,T,V){var U=N(S.dom.getParent(T,"td,th"));var R=E(V,U);var Q=V.childNodes[R];F(Q)}function L(R,T){var Q=O(R);if(Q!==null){F(Q);return d.dom.Event.cancel(T)}else{var S=T.keyCode==z?R.firstChild:R.lastChild;F(S);return true}}var z=38;var I=40;if(A(M)&&D(B)){var J=B.selection.getNode();var P=B.dom.getParent(J,"tr");var K=G(M,P);if(K==null){return L(P,M)}else{w(B,J,K);d.dom.Event.cancel(M);return true}}}r.onKeyDown.add(v)}if(!d.isIE){function s(){var w;for(w=r.getBody().lastChild;w&&w.nodeType==3&&!w.nodeValue.length;w=w.previousSibling){}if(w&&w.nodeName=="TABLE"){r.dom.add(r.getBody(),"p",null,'<br mce_bogus="1" />')}}if(d.isGecko){r.onKeyDown.add(function(z,B){var w,A,C=z.dom;if(B.keyCode==37||B.keyCode==38){w=z.selection.getRng();A=C.getParent(w.startContainer,"table");if(A&&z.getBody().firstChild==A){if(c(w,A)){w=C.createRng();w.setStartBefore(A);w.setEndBefore(A);z.selection.setRng(w);B.preventDefault()}}}})}r.onKeyUp.add(s);r.onSetContent.add(s);r.onVisualAid.add(s);r.onPreProcess.add(function(w,A){var z=A.node.lastChild;if(z&&z.childNodes.length==1&&z.firstChild.nodeName=="BR"){w.dom.remove(z)}});s();r.startContent=r.getContent({format:"raw"})}});e({mceTableSplitCells:function(n){n.split()},mceTableMergeCells:function(o){var p,q,n;n=g.dom.getParent(g.selection.getNode(),"th,td");if(n){p=n.rowSpan;q=n.colSpan}if(!g.dom.select("td.mceSelected,th.mceSelected").length){f.open({url:h+"/merge_cells.htm",width:240+parseInt(g.getLang("table.merge_cells_delta_width",0)),height:110+parseInt(g.getLang("table.merge_cells_delta_height",0)),inline:1},{rows:p,cols:q,onaction:function(r){o.merge(n,r.cols,r.rows)},plugin_url:h})}else{o.merge()}},mceTableInsertRowBefore:function(n){n.insertRow(true)},mceTableInsertRowAfter:function(n){n.insertRow()},mceTableInsertColBefore:function(n){n.insertCol(true)},mceTableInsertColAfter:function(n){n.insertCol()},mceTableDeleteCol:function(n){n.deleteCols()},mceTableDeleteRow:function(n){n.deleteRows()},mceTableCutRow:function(n){m=n.cutRows()},mceTableCopyRow:function(n){m=n.copyRows()},mceTablePasteRowBefore:function(n){n.pasteRows(m,true)},mceTablePasteRowAfter:function(n){n.pasteRows(m)},mceTableDelete:function(n){n.deleteTable()}},function(o,n){g.addCommand(n,function(){var p=l();if(p){o(p);g.execCommand("mceRepaint");k()}})});e({mceInsertTable:function(n){f.open({url:h+"/table.htm",width:400+parseInt(g.getLang("table.table_delta_width",0)),height:320+parseInt(g.getLang("table.table_delta_height",0)),inline:1},{plugin_url:h,action:n?n.action:0})},mceTableRowProps:function(){f.open({url:h+"/row.htm",width:400+parseInt(g.getLang("table.rowprops_delta_width",0)),height:295+parseInt(g.getLang("table.rowprops_delta_height",0)),inline:1},{plugin_url:h})},mceTableCellProps:function(){f.open({url:h+"/cell.htm",width:400+parseInt(g.getLang("table.cellprops_delta_width",0)),height:295+parseInt(g.getLang("table.cellprops_delta_height",0)),inline:1},{plugin_url:h})}},function(o,n){g.addCommand(n,function(p,q){o(q)})})}});d.PluginManager.add("table",d.plugins.TablePlugin)})(tinymce); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/editor_plugin_src.js new file mode 100644 index 0000000..ccfe808 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/editor_plugin_src.js @@ -0,0 +1,1364 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function(tinymce) { + var each = tinymce.each; + + // Checks if the selection/caret is at the start of the specified block element + function isAtStart(rng, par) { + var doc = par.ownerDocument, rng2 = doc.createRange(), elm; + + rng2.setStartBefore(par); + rng2.setEnd(rng.endContainer, rng.endOffset); + + elm = doc.createElement('body'); + elm.appendChild(rng2.cloneContents()); + + // Check for text characters of other elements that should be treated as content + return elm.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi, '-').replace(/<[^>]+>/g, '').length == 0; + }; + + function getSpanVal(td, name) { + return parseInt(td.getAttribute(name) || 1); + } + + /** + * Table Grid class. + */ + function TableGrid(table, dom, selection) { + var grid, startPos, endPos, selectedCell; + + buildGrid(); + selectedCell = dom.getParent(selection.getStart(), 'th,td'); + if (selectedCell) { + startPos = getPos(selectedCell); + endPos = findEndPos(); + selectedCell = getCell(startPos.x, startPos.y); + } + + function cloneNode(node, children) { + node = node.cloneNode(children); + node.removeAttribute('id'); + + return node; + } + + function buildGrid() { + var startY = 0; + + grid = []; + + each(['thead', 'tbody', 'tfoot'], function(part) { + var rows = dom.select('> ' + part + ' tr', table); + + each(rows, function(tr, y) { + y += startY; + + each(dom.select('> td, > th', tr), function(td, x) { + var x2, y2, rowspan, colspan; + + // Skip over existing cells produced by rowspan + if (grid[y]) { + while (grid[y][x]) + x++; + } + + // Get col/rowspan from cell + rowspan = getSpanVal(td, 'rowspan'); + colspan = getSpanVal(td, 'colspan'); + + // Fill out rowspan/colspan right and down + for (y2 = y; y2 < y + rowspan; y2++) { + if (!grid[y2]) + grid[y2] = []; + + for (x2 = x; x2 < x + colspan; x2++) { + grid[y2][x2] = { + part : part, + real : y2 == y && x2 == x, + elm : td, + rowspan : rowspan, + colspan : colspan + }; + } + } + }); + }); + + startY += rows.length; + }); + }; + + function getCell(x, y) { + var row; + + row = grid[y]; + if (row) + return row[x]; + }; + + function setSpanVal(td, name, val) { + if (td) { + val = parseInt(val); + + if (val === 1) + td.removeAttribute(name, 1); + else + td.setAttribute(name, val, 1); + } + } + + function isCellSelected(cell) { + return cell && (dom.hasClass(cell.elm, 'mceSelected') || cell == selectedCell); + }; + + function getSelectedRows() { + var rows = []; + + each(table.rows, function(row) { + each(row.cells, function(cell) { + if (dom.hasClass(cell, 'mceSelected') || cell == selectedCell.elm) { + rows.push(row); + return false; + } + }); + }); + + return rows; + }; + + function deleteTable() { + var rng = dom.createRng(); + + rng.setStartAfter(table); + rng.setEndAfter(table); + + selection.setRng(rng); + + dom.remove(table); + }; + + function cloneCell(cell) { + var formatNode; + + // Clone formats + tinymce.walk(cell, function(node) { + var curNode; + + if (node.nodeType == 3) { + each(dom.getParents(node.parentNode, null, cell).reverse(), function(node) { + node = cloneNode(node, false); + + if (!formatNode) + formatNode = curNode = node; + else if (curNode) + curNode.appendChild(node); + + curNode = node; + }); + + // Add something to the inner node + if (curNode) + curNode.innerHTML = tinymce.isIE ? '&nbsp;' : '<br data-mce-bogus="1" />'; + + return false; + } + }, 'childNodes'); + + cell = cloneNode(cell, false); + setSpanVal(cell, 'rowSpan', 1); + setSpanVal(cell, 'colSpan', 1); + + if (formatNode) { + cell.appendChild(formatNode); + } else { + if (!tinymce.isIE) + cell.innerHTML = '<br data-mce-bogus="1" />'; + } + + return cell; + }; + + function cleanup() { + var rng = dom.createRng(); + + // Empty rows + each(dom.select('tr', table), function(tr) { + if (tr.cells.length == 0) + dom.remove(tr); + }); + + // Empty table + if (dom.select('tr', table).length == 0) { + rng.setStartAfter(table); + rng.setEndAfter(table); + selection.setRng(rng); + dom.remove(table); + return; + } + + // Empty header/body/footer + each(dom.select('thead,tbody,tfoot', table), function(part) { + if (part.rows.length == 0) + dom.remove(part); + }); + + // Restore selection to start position if it still exists + buildGrid(); + + // Restore the selection to the closest table position + row = grid[Math.min(grid.length - 1, startPos.y)]; + if (row) { + selection.select(row[Math.min(row.length - 1, startPos.x)].elm, true); + selection.collapse(true); + } + }; + + function fillLeftDown(x, y, rows, cols) { + var tr, x2, r, c, cell; + + tr = grid[y][x].elm.parentNode; + for (r = 1; r <= rows; r++) { + tr = dom.getNext(tr, 'tr'); + + if (tr) { + // Loop left to find real cell + for (x2 = x; x2 >= 0; x2--) { + cell = grid[y + r][x2].elm; + + if (cell.parentNode == tr) { + // Append clones after + for (c = 1; c <= cols; c++) + dom.insertAfter(cloneCell(cell), cell); + + break; + } + } + + if (x2 == -1) { + // Insert nodes before first cell + for (c = 1; c <= cols; c++) + tr.insertBefore(cloneCell(tr.cells[0]), tr.cells[0]); + } + } + } + }; + + function split() { + each(grid, function(row, y) { + each(row, function(cell, x) { + var colSpan, rowSpan, newCell, i; + + if (isCellSelected(cell)) { + cell = cell.elm; + colSpan = getSpanVal(cell, 'colspan'); + rowSpan = getSpanVal(cell, 'rowspan'); + + if (colSpan > 1 || rowSpan > 1) { + setSpanVal(cell, 'rowSpan', 1); + setSpanVal(cell, 'colSpan', 1); + + // Insert cells right + for (i = 0; i < colSpan - 1; i++) + dom.insertAfter(cloneCell(cell), cell); + + fillLeftDown(x, y, rowSpan - 1, colSpan); + } + } + }); + }); + }; + + function merge(cell, cols, rows) { + var startX, startY, endX, endY, x, y, startCell, endCell, cell, children, count; + + // Use specified cell and cols/rows + if (cell) { + pos = getPos(cell); + startX = pos.x; + startY = pos.y; + endX = startX + (cols - 1); + endY = startY + (rows - 1); + } else { + // Use selection + startX = startPos.x; + startY = startPos.y; + endX = endPos.x; + endY = endPos.y; + } + + // Find start/end cells + startCell = getCell(startX, startY); + endCell = getCell(endX, endY); + + // Check if the cells exists and if they are of the same part for example tbody = tbody + if (startCell && endCell && startCell.part == endCell.part) { + // Split and rebuild grid + split(); + buildGrid(); + + // Set row/col span to start cell + startCell = getCell(startX, startY).elm; + setSpanVal(startCell, 'colSpan', (endX - startX) + 1); + setSpanVal(startCell, 'rowSpan', (endY - startY) + 1); + + // Remove other cells and add it's contents to the start cell + for (y = startY; y <= endY; y++) { + for (x = startX; x <= endX; x++) { + if (!grid[y] || !grid[y][x]) + continue; + + cell = grid[y][x].elm; + + if (cell != startCell) { + // Move children to startCell + children = tinymce.grep(cell.childNodes); + each(children, function(node) { + startCell.appendChild(node); + }); + + // Remove bogus nodes if there is children in the target cell + if (children.length) { + children = tinymce.grep(startCell.childNodes); + count = 0; + each(children, function(node) { + if (node.nodeName == 'BR' && dom.getAttrib(node, 'data-mce-bogus') && count++ < children.length - 1) + startCell.removeChild(node); + }); + } + + // Remove cell + dom.remove(cell); + } + } + } + + // Remove empty rows etc and restore caret location + cleanup(); + } + }; + + function insertRow(before) { + var posY, cell, lastCell, x, rowElm, newRow, newCell, otherCell, rowSpan; + + // Find first/last row + each(grid, function(row, y) { + each(row, function(cell, x) { + if (isCellSelected(cell)) { + cell = cell.elm; + rowElm = cell.parentNode; + newRow = cloneNode(rowElm, false); + posY = y; + + if (before) + return false; + } + }); + + if (before) + return !posY; + }); + + for (x = 0; x < grid[0].length; x++) { + // Cell not found could be because of an invalid table structure + if (!grid[posY][x]) + continue; + + cell = grid[posY][x].elm; + + if (cell != lastCell) { + if (!before) { + rowSpan = getSpanVal(cell, 'rowspan'); + if (rowSpan > 1) { + setSpanVal(cell, 'rowSpan', rowSpan + 1); + continue; + } + } else { + // Check if cell above can be expanded + if (posY > 0 && grid[posY - 1][x]) { + otherCell = grid[posY - 1][x].elm; + rowSpan = getSpanVal(otherCell, 'rowSpan'); + if (rowSpan > 1) { + setSpanVal(otherCell, 'rowSpan', rowSpan + 1); + continue; + } + } + } + + // Insert new cell into new row + newCell = cloneCell(cell); + setSpanVal(newCell, 'colSpan', cell.colSpan); + + newRow.appendChild(newCell); + + lastCell = cell; + } + } + + if (newRow.hasChildNodes()) { + if (!before) + dom.insertAfter(newRow, rowElm); + else + rowElm.parentNode.insertBefore(newRow, rowElm); + } + }; + + function insertCol(before) { + var posX, lastCell; + + // Find first/last column + each(grid, function(row, y) { + each(row, function(cell, x) { + if (isCellSelected(cell)) { + posX = x; + + if (before) + return false; + } + }); + + if (before) + return !posX; + }); + + each(grid, function(row, y) { + var cell, rowSpan, colSpan; + + if (!row[posX]) + return; + + cell = row[posX].elm; + if (cell != lastCell) { + colSpan = getSpanVal(cell, 'colspan'); + rowSpan = getSpanVal(cell, 'rowspan'); + + if (colSpan == 1) { + if (!before) { + dom.insertAfter(cloneCell(cell), cell); + fillLeftDown(posX, y, rowSpan - 1, colSpan); + } else { + cell.parentNode.insertBefore(cloneCell(cell), cell); + fillLeftDown(posX, y, rowSpan - 1, colSpan); + } + } else + setSpanVal(cell, 'colSpan', cell.colSpan + 1); + + lastCell = cell; + } + }); + }; + + function deleteCols() { + var cols = []; + + // Get selected column indexes + each(grid, function(row, y) { + each(row, function(cell, x) { + if (isCellSelected(cell) && tinymce.inArray(cols, x) === -1) { + each(grid, function(row) { + var cell = row[x].elm, colSpan; + + colSpan = getSpanVal(cell, 'colSpan'); + + if (colSpan > 1) + setSpanVal(cell, 'colSpan', colSpan - 1); + else + dom.remove(cell); + }); + + cols.push(x); + } + }); + }); + + cleanup(); + }; + + function deleteRows() { + var rows; + + function deleteRow(tr) { + var nextTr, pos, lastCell; + + nextTr = dom.getNext(tr, 'tr'); + + // Move down row spanned cells + each(tr.cells, function(cell) { + var rowSpan = getSpanVal(cell, 'rowSpan'); + + if (rowSpan > 1) { + setSpanVal(cell, 'rowSpan', rowSpan - 1); + pos = getPos(cell); + fillLeftDown(pos.x, pos.y, 1, 1); + } + }); + + // Delete cells + pos = getPos(tr.cells[0]); + each(grid[pos.y], function(cell) { + var rowSpan; + + cell = cell.elm; + + if (cell != lastCell) { + rowSpan = getSpanVal(cell, 'rowSpan'); + + if (rowSpan <= 1) + dom.remove(cell); + else + setSpanVal(cell, 'rowSpan', rowSpan - 1); + + lastCell = cell; + } + }); + }; + + // Get selected rows and move selection out of scope + rows = getSelectedRows(); + + // Delete all selected rows + each(rows.reverse(), function(tr) { + deleteRow(tr); + }); + + cleanup(); + }; + + function cutRows() { + var rows = getSelectedRows(); + + dom.remove(rows); + cleanup(); + + return rows; + }; + + function copyRows() { + var rows = getSelectedRows(); + + each(rows, function(row, i) { + rows[i] = cloneNode(row, true); + }); + + return rows; + }; + + function pasteRows(rows, before) { + var selectedRows = getSelectedRows(), + targetRow = selectedRows[before ? 0 : selectedRows.length - 1], + targetCellCount = targetRow.cells.length; + + // Calc target cell count + each(grid, function(row) { + var match; + + targetCellCount = 0; + each(row, function(cell, x) { + if (cell.real) + targetCellCount += cell.colspan; + + if (cell.elm.parentNode == targetRow) + match = 1; + }); + + if (match) + return false; + }); + + if (!before) + rows.reverse(); + + each(rows, function(row) { + var cellCount = row.cells.length, cell; + + // Remove col/rowspans + for (i = 0; i < cellCount; i++) { + cell = row.cells[i]; + setSpanVal(cell, 'colSpan', 1); + setSpanVal(cell, 'rowSpan', 1); + } + + // Needs more cells + for (i = cellCount; i < targetCellCount; i++) + row.appendChild(cloneCell(row.cells[cellCount - 1])); + + // Needs less cells + for (i = targetCellCount; i < cellCount; i++) + dom.remove(row.cells[i]); + + // Add before/after + if (before) + targetRow.parentNode.insertBefore(row, targetRow); + else + dom.insertAfter(row, targetRow); + }); + }; + + function getPos(target) { + var pos; + + each(grid, function(row, y) { + each(row, function(cell, x) { + if (cell.elm == target) { + pos = {x : x, y : y}; + return false; + } + }); + + return !pos; + }); + + return pos; + }; + + function setStartCell(cell) { + startPos = getPos(cell); + }; + + function findEndPos() { + var pos, maxX, maxY; + + maxX = maxY = 0; + + each(grid, function(row, y) { + each(row, function(cell, x) { + var colSpan, rowSpan; + + if (isCellSelected(cell)) { + cell = grid[y][x]; + + if (x > maxX) + maxX = x; + + if (y > maxY) + maxY = y; + + if (cell.real) { + colSpan = cell.colspan - 1; + rowSpan = cell.rowspan - 1; + + if (colSpan) { + if (x + colSpan > maxX) + maxX = x + colSpan; + } + + if (rowSpan) { + if (y + rowSpan > maxY) + maxY = y + rowSpan; + } + } + } + }); + }); + + return {x : maxX, y : maxY}; + }; + + function setEndCell(cell) { + var startX, startY, endX, endY, maxX, maxY, colSpan, rowSpan; + + endPos = getPos(cell); + + if (startPos && endPos) { + // Get start/end positions + startX = Math.min(startPos.x, endPos.x); + startY = Math.min(startPos.y, endPos.y); + endX = Math.max(startPos.x, endPos.x); + endY = Math.max(startPos.y, endPos.y); + + // Expand end positon to include spans + maxX = endX; + maxY = endY; + + // Expand startX + for (y = startY; y <= maxY; y++) { + cell = grid[y][startX]; + + if (!cell.real) { + if (startX - (cell.colspan - 1) < startX) + startX -= cell.colspan - 1; + } + } + + // Expand startY + for (x = startX; x <= maxX; x++) { + cell = grid[startY][x]; + + if (!cell.real) { + if (startY - (cell.rowspan - 1) < startY) + startY -= cell.rowspan - 1; + } + } + + // Find max X, Y + for (y = startY; y <= endY; y++) { + for (x = startX; x <= endX; x++) { + cell = grid[y][x]; + + if (cell.real) { + colSpan = cell.colspan - 1; + rowSpan = cell.rowspan - 1; + + if (colSpan) { + if (x + colSpan > maxX) + maxX = x + colSpan; + } + + if (rowSpan) { + if (y + rowSpan > maxY) + maxY = y + rowSpan; + } + } + } + } + + // Remove current selection + dom.removeClass(dom.select('td.mceSelected,th.mceSelected'), 'mceSelected'); + + // Add new selection + for (y = startY; y <= maxY; y++) { + for (x = startX; x <= maxX; x++) { + if (grid[y][x]) + dom.addClass(grid[y][x].elm, 'mceSelected'); + } + } + } + }; + + // Expose to public + tinymce.extend(this, { + deleteTable : deleteTable, + split : split, + merge : merge, + insertRow : insertRow, + insertCol : insertCol, + deleteCols : deleteCols, + deleteRows : deleteRows, + cutRows : cutRows, + copyRows : copyRows, + pasteRows : pasteRows, + getPos : getPos, + setStartCell : setStartCell, + setEndCell : setEndCell + }); + }; + + tinymce.create('tinymce.plugins.TablePlugin', { + init : function(ed, url) { + var winMan, clipboardRows, hasCellSelection = true; // Might be selected cells on reload + + function createTableGrid(node) { + var selection = ed.selection, tblElm = ed.dom.getParent(node || selection.getNode(), 'table'); + + if (tblElm) + return new TableGrid(tblElm, ed.dom, selection); + }; + + function cleanup() { + // Restore selection possibilities + ed.getBody().style.webkitUserSelect = ''; + + if (hasCellSelection) { + ed.dom.removeClass(ed.dom.select('td.mceSelected,th.mceSelected'), 'mceSelected'); + hasCellSelection = false; + } + }; + + // Register buttons + each([ + ['table', 'table.desc', 'mceInsertTable', true], + ['delete_table', 'table.del', 'mceTableDelete'], + ['delete_col', 'table.delete_col_desc', 'mceTableDeleteCol'], + ['delete_row', 'table.delete_row_desc', 'mceTableDeleteRow'], + ['col_after', 'table.col_after_desc', 'mceTableInsertColAfter'], + ['col_before', 'table.col_before_desc', 'mceTableInsertColBefore'], + ['row_after', 'table.row_after_desc', 'mceTableInsertRowAfter'], + ['row_before', 'table.row_before_desc', 'mceTableInsertRowBefore'], + ['row_props', 'table.row_desc', 'mceTableRowProps', true], + ['cell_props', 'table.cell_desc', 'mceTableCellProps', true], + ['split_cells', 'table.split_cells_desc', 'mceTableSplitCells', true], + ['merge_cells', 'table.merge_cells_desc', 'mceTableMergeCells', true] + ], function(c) { + ed.addButton(c[0], {title : c[1], cmd : c[2], ui : c[3]}); + }); + + // Select whole table is a table border is clicked + if (!tinymce.isIE) { + ed.onClick.add(function(ed, e) { + e = e.target; + + if (e.nodeName === 'TABLE') { + ed.selection.select(e); + ed.nodeChanged(); + } + }); + } + + ed.onPreProcess.add(function(ed, args) { + var nodes, i, node, dom = ed.dom, value; + + nodes = dom.select('table', args.node); + i = nodes.length; + while (i--) { + node = nodes[i]; + dom.setAttrib(node, 'data-mce-style', ''); + + if ((value = dom.getAttrib(node, 'width'))) { + dom.setStyle(node, 'width', value); + dom.setAttrib(node, 'width', ''); + } + + if ((value = dom.getAttrib(node, 'height'))) { + dom.setStyle(node, 'height', value); + dom.setAttrib(node, 'height', ''); + } + } + }); + + // Handle node change updates + ed.onNodeChange.add(function(ed, cm, n) { + var p; + + n = ed.selection.getStart(); + p = ed.dom.getParent(n, 'td,th,caption'); + cm.setActive('table', n.nodeName === 'TABLE' || !!p); + + // Disable table tools if we are in caption + if (p && p.nodeName === 'CAPTION') + p = 0; + + cm.setDisabled('delete_table', !p); + cm.setDisabled('delete_col', !p); + cm.setDisabled('delete_table', !p); + cm.setDisabled('delete_row', !p); + cm.setDisabled('col_after', !p); + cm.setDisabled('col_before', !p); + cm.setDisabled('row_after', !p); + cm.setDisabled('row_before', !p); + cm.setDisabled('row_props', !p); + cm.setDisabled('cell_props', !p); + cm.setDisabled('split_cells', !p); + cm.setDisabled('merge_cells', !p); + }); + + ed.onInit.add(function(ed) { + var startTable, startCell, dom = ed.dom, tableGrid; + + winMan = ed.windowManager; + + // Add cell selection logic + ed.onMouseDown.add(function(ed, e) { + if (e.button != 2) { + cleanup(); + + startCell = dom.getParent(e.target, 'td,th'); + startTable = dom.getParent(startCell, 'table'); + } + }); + + dom.bind(ed.getDoc(), 'mouseover', function(e) { + var sel, table, target = e.target; + + if (startCell && (tableGrid || target != startCell) && (target.nodeName == 'TD' || target.nodeName == 'TH')) { + table = dom.getParent(target, 'table'); + if (table == startTable) { + if (!tableGrid) { + tableGrid = createTableGrid(table); + tableGrid.setStartCell(startCell); + + ed.getBody().style.webkitUserSelect = 'none'; + } + + tableGrid.setEndCell(target); + hasCellSelection = true; + } + + // Remove current selection + sel = ed.selection.getSel(); + + try { + if (sel.removeAllRanges) + sel.removeAllRanges(); + else + sel.empty(); + } catch (ex) { + // IE9 might throw errors here + } + + e.preventDefault(); + } + }); + + ed.onMouseUp.add(function(ed, e) { + var rng, sel = ed.selection, selectedCells, nativeSel = sel.getSel(), walker, node, lastNode, endNode; + + // Move selection to startCell + if (startCell) { + if (tableGrid) + ed.getBody().style.webkitUserSelect = ''; + + function setPoint(node, start) { + var walker = new tinymce.dom.TreeWalker(node, node); + + do { + // Text node + if (node.nodeType == 3 && tinymce.trim(node.nodeValue).length != 0) { + if (start) + rng.setStart(node, 0); + else + rng.setEnd(node, node.nodeValue.length); + + return; + } + + // BR element + if (node.nodeName == 'BR') { + if (start) + rng.setStartBefore(node); + else + rng.setEndBefore(node); + + return; + } + } while (node = (start ? walker.next() : walker.prev())); + } + + // Try to expand text selection as much as we can only Gecko supports cell selection + selectedCells = dom.select('td.mceSelected,th.mceSelected'); + if (selectedCells.length > 0) { + rng = dom.createRng(); + node = selectedCells[0]; + endNode = selectedCells[selectedCells.length - 1]; + rng.setStartBefore(node); + rng.setEndAfter(node); + + setPoint(node, 1); + walker = new tinymce.dom.TreeWalker(node, dom.getParent(selectedCells[0], 'table')); + + do { + if (node.nodeName == 'TD' || node.nodeName == 'TH') { + if (!dom.hasClass(node, 'mceSelected')) + break; + + lastNode = node; + } + } while (node = walker.next()); + + setPoint(lastNode); + + sel.setRng(rng); + } + + ed.nodeChanged(); + startCell = tableGrid = startTable = null; + } + }); + + ed.onKeyUp.add(function(ed, e) { + cleanup(); + }); + + ed.onKeyDown.add(function (ed, e) { + fixTableCellSelection(ed); + }); + + ed.onMouseDown.add(function (ed, e) { + if (e.button != 2) { + fixTableCellSelection(ed); + } + }); + function tableCellSelected(ed, rng, n, currentCell) { + // The decision of when a table cell is selected is somewhat involved. The fact that this code is + // required is actually a pointer to the root cause of this bug. A cell is selected when the start + // and end offsets are 0, the start container is a text, and the selection node is either a TR (most cases) + // or the parent of the table (in the case of the selection containing the last cell of a table). + var TEXT_NODE = 3, table = ed.dom.getParent(rng.startContainer, 'TABLE'), + tableParent, allOfCellSelected, tableCellSelection; + if (table) + tableParent = table.parentNode; + allOfCellSelected =rng.startContainer.nodeType == TEXT_NODE && + rng.startOffset == 0 && + rng.endOffset == 0 && + currentCell && + (n.nodeName=="TR" || n==tableParent); + tableCellSelection = (n.nodeName=="TD"||n.nodeName=="TH")&& !currentCell; + return allOfCellSelected || tableCellSelection; + // return false; + } + + // this nasty hack is here to work around some WebKit selection bugs. + function fixTableCellSelection(ed) { + if (!tinymce.isWebKit) + return; + + var rng = ed.selection.getRng(); + var n = ed.selection.getNode(); + var currentCell = ed.dom.getParent(rng.startContainer, 'TD'); + + if (!tableCellSelected(ed, rng, n, currentCell)) + return; + if (!currentCell) { + currentCell=n; + } + + // Get the very last node inside the table cell + var end = currentCell.lastChild; + while (end.lastChild) + end = end.lastChild; + + // Select the entire table cell. Nothing outside of the table cell should be selected. + rng.setEnd(end, end.nodeValue.length); + ed.selection.setRng(rng); + } + ed.plugins.table.fixTableCellSelection=fixTableCellSelection; + + // Add context menu + if (ed && ed.plugins.contextmenu) { + ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) { + var sm, se = ed.selection, el = se.getNode() || ed.getBody(); + + if (ed.dom.getParent(e, 'td') || ed.dom.getParent(e, 'th') || ed.dom.select('td.mceSelected,th.mceSelected').length) { + m.removeAll(); + + if (el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) { + m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true}); + m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'}); + m.addSeparator(); + } + + if (el.nodeName == 'IMG' && el.className.indexOf('mceItem') == -1) { + m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true}); + m.addSeparator(); + } + + m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', value : {action : 'insert'}}); + m.add({title : 'table.props_desc', icon : 'table_props', cmd : 'mceInsertTable'}); + m.add({title : 'table.del', icon : 'delete_table', cmd : 'mceTableDelete'}); + m.addSeparator(); + + // Cell menu + sm = m.addMenu({title : 'table.cell'}); + sm.add({title : 'table.cell_desc', icon : 'cell_props', cmd : 'mceTableCellProps'}); + sm.add({title : 'table.split_cells_desc', icon : 'split_cells', cmd : 'mceTableSplitCells'}); + sm.add({title : 'table.merge_cells_desc', icon : 'merge_cells', cmd : 'mceTableMergeCells'}); + + // Row menu + sm = m.addMenu({title : 'table.row'}); + sm.add({title : 'table.row_desc', icon : 'row_props', cmd : 'mceTableRowProps'}); + sm.add({title : 'table.row_before_desc', icon : 'row_before', cmd : 'mceTableInsertRowBefore'}); + sm.add({title : 'table.row_after_desc', icon : 'row_after', cmd : 'mceTableInsertRowAfter'}); + sm.add({title : 'table.delete_row_desc', icon : 'delete_row', cmd : 'mceTableDeleteRow'}); + sm.addSeparator(); + sm.add({title : 'table.cut_row_desc', icon : 'cut', cmd : 'mceTableCutRow'}); + sm.add({title : 'table.copy_row_desc', icon : 'copy', cmd : 'mceTableCopyRow'}); + sm.add({title : 'table.paste_row_before_desc', icon : 'paste', cmd : 'mceTablePasteRowBefore'}).setDisabled(!clipboardRows); + sm.add({title : 'table.paste_row_after_desc', icon : 'paste', cmd : 'mceTablePasteRowAfter'}).setDisabled(!clipboardRows); + + // Column menu + sm = m.addMenu({title : 'table.col'}); + sm.add({title : 'table.col_before_desc', icon : 'col_before', cmd : 'mceTableInsertColBefore'}); + sm.add({title : 'table.col_after_desc', icon : 'col_after', cmd : 'mceTableInsertColAfter'}); + sm.add({title : 'table.delete_col_desc', icon : 'delete_col', cmd : 'mceTableDeleteCol'}); + } else + m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable'}); + }); + } + + // Fix to allow navigating up and down in a table in WebKit browsers. + if (tinymce.isWebKit) { + function moveSelection(ed, e) { + + function moveCursorToStartOfElement(n) { + ed.selection.setCursorLocation(n, 0); + } + + function getSibling(event, element) { + return event.keyCode == UP_ARROW ? element.previousSibling : element.nextSibling; + } + + function getNextRow(e, row) { + var sibling = getSibling(e, row); + return sibling !== null && sibling.tagName === 'TR' ? sibling : null; + } + + function getTable(ed, currentRow) { + return ed.dom.getParent(currentRow, 'table'); + } + + function getTableSibling(currentRow) { + var table = getTable(ed, currentRow); + return getSibling(e, table); + } + + function isVerticalMovement(event) { + return event.keyCode == UP_ARROW || event.keyCode == DOWN_ARROW; + } + + function isInTable(ed) { + var node = ed.selection.getNode(); + var currentRow = ed.dom.getParent(node, 'tr'); + return currentRow !== null; + } + + function columnIndex(column) { + var colIndex = 0; + var c = column; + while (c.previousSibling) { + c = c.previousSibling; + colIndex = colIndex + getSpanVal(c, "colspan"); + } + return colIndex; + } + + function findColumn(rowElement, columnIndex) { + var c = 0; + var r = 0; + each(rowElement.children, function(cell, i) { + c = c + getSpanVal(cell, "colspan"); + r = i; + if (c > columnIndex) + return false; + }); + return r; + } + + function moveCursorToRow(ed, node, row) { + var srcColumnIndex = columnIndex(ed.dom.getParent(node, 'td,th')); + var tgtColumnIndex = findColumn(row, srcColumnIndex) + var tgtNode = row.childNodes[tgtColumnIndex]; + moveCursorToStartOfElement(tgtNode); + } + + function escapeTable(currentRow, e) { + var tableSiblingElement = getTableSibling(currentRow); + if (tableSiblingElement !== null) { + moveCursorToStartOfElement(tableSiblingElement); + return tinymce.dom.Event.cancel(e); + } else { + var element = e.keyCode == UP_ARROW ? currentRow.firstChild : currentRow.lastChild; + // rely on default behaviour to escape table after we are in the last cell of the last row + moveCursorToStartOfElement(element); + return true; + } + } + + var UP_ARROW = 38; + var DOWN_ARROW = 40; + + if (isVerticalMovement(e) && isInTable(ed)) { + var node = ed.selection.getNode(); + var currentRow = ed.dom.getParent(node, 'tr'); + var nextRow = getNextRow(e, currentRow); + + // If we're at the first or last row in the table, we should move the caret outside of the table + if (nextRow == null) { + return escapeTable(currentRow, e); + } else { + moveCursorToRow(ed, node, nextRow); + tinymce.dom.Event.cancel(e); + return true; + } + } + } + + ed.onKeyDown.add(moveSelection); + } + + // Fixes an issue on Gecko where it's impossible to place the caret behind a table + // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled + if (!tinymce.isIE) { + function fixTableCaretPos() { + var last; + + // Skip empty text nodes form the end + for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling) ; + + if (last && last.nodeName == 'TABLE') + ed.dom.add(ed.getBody(), 'p', null, '<br mce_bogus="1" />'); + }; + + // Fixes an bug where it's impossible to place the caret before a table in Gecko + // this fix solves it by detecting when the caret is at the beginning of such a table + // and then manually moves the caret infront of the table + if (tinymce.isGecko) { + ed.onKeyDown.add(function(ed, e) { + var rng, table, dom = ed.dom; + + // On gecko it's not possible to place the caret before a table + if (e.keyCode == 37 || e.keyCode == 38) { + rng = ed.selection.getRng(); + table = dom.getParent(rng.startContainer, 'table'); + + if (table && ed.getBody().firstChild == table) { + if (isAtStart(rng, table)) { + rng = dom.createRng(); + + rng.setStartBefore(table); + rng.setEndBefore(table); + + ed.selection.setRng(rng); + + e.preventDefault(); + } + } + } + }); + } + + ed.onKeyUp.add(fixTableCaretPos); + ed.onSetContent.add(fixTableCaretPos); + ed.onVisualAid.add(fixTableCaretPos); + + ed.onPreProcess.add(function(ed, o) { + var last = o.node.lastChild; + + if (last && last.childNodes.length == 1 && last.firstChild.nodeName == 'BR') + ed.dom.remove(last); + }); + + fixTableCaretPos(); + ed.startContent = ed.getContent({format : 'raw'}); + } + }); + + // Register action commands + each({ + mceTableSplitCells : function(grid) { + grid.split(); + }, + + mceTableMergeCells : function(grid) { + var rowSpan, colSpan, cell; + + cell = ed.dom.getParent(ed.selection.getNode(), 'th,td'); + if (cell) { + rowSpan = cell.rowSpan; + colSpan = cell.colSpan; + } + + if (!ed.dom.select('td.mceSelected,th.mceSelected').length) { + winMan.open({ + url : url + '/merge_cells.htm', + width : 240 + parseInt(ed.getLang('table.merge_cells_delta_width', 0)), + height : 110 + parseInt(ed.getLang('table.merge_cells_delta_height', 0)), + inline : 1 + }, { + rows : rowSpan, + cols : colSpan, + onaction : function(data) { + grid.merge(cell, data.cols, data.rows); + }, + plugin_url : url + }); + } else + grid.merge(); + }, + + mceTableInsertRowBefore : function(grid) { + grid.insertRow(true); + }, + + mceTableInsertRowAfter : function(grid) { + grid.insertRow(); + }, + + mceTableInsertColBefore : function(grid) { + grid.insertCol(true); + }, + + mceTableInsertColAfter : function(grid) { + grid.insertCol(); + }, + + mceTableDeleteCol : function(grid) { + grid.deleteCols(); + }, + + mceTableDeleteRow : function(grid) { + grid.deleteRows(); + }, + + mceTableCutRow : function(grid) { + clipboardRows = grid.cutRows(); + }, + + mceTableCopyRow : function(grid) { + clipboardRows = grid.copyRows(); + }, + + mceTablePasteRowBefore : function(grid) { + grid.pasteRows(clipboardRows, true); + }, + + mceTablePasteRowAfter : function(grid) { + grid.pasteRows(clipboardRows); + }, + + mceTableDelete : function(grid) { + grid.deleteTable(); + } + }, function(func, name) { + ed.addCommand(name, function() { + var grid = createTableGrid(); + + if (grid) { + func(grid); + ed.execCommand('mceRepaint'); + cleanup(); + } + }); + }); + + // Register dialog commands + each({ + mceInsertTable : function(val) { + winMan.open({ + url : url + '/table.htm', + width : 400 + parseInt(ed.getLang('table.table_delta_width', 0)), + height : 320 + parseInt(ed.getLang('table.table_delta_height', 0)), + inline : 1 + }, { + plugin_url : url, + action : val ? val.action : 0 + }); + }, + + mceTableRowProps : function() { + winMan.open({ + url : url + '/row.htm', + width : 400 + parseInt(ed.getLang('table.rowprops_delta_width', 0)), + height : 295 + parseInt(ed.getLang('table.rowprops_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }, + + mceTableCellProps : function() { + winMan.open({ + url : url + '/cell.htm', + width : 400 + parseInt(ed.getLang('table.cellprops_delta_width', 0)), + height : 295 + parseInt(ed.getLang('table.cellprops_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + } + }, function(func, name) { + ed.addCommand(name, function(ui, val) { + func(val); + }); + }); + } + }); + + // Register plugin + tinymce.PluginManager.add('table', tinymce.plugins.TablePlugin); +})(tinymce); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/cell.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/cell.js new file mode 100644 index 0000000..d6f3290 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/cell.js @@ -0,0 +1,319 @@ +tinyMCEPopup.requireLangPack(); + +var ed; + +function init() { + ed = tinyMCEPopup.editor; + tinyMCEPopup.resizeToInnerSize(); + + document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table'); + document.getElementById('bordercolor_pickcontainer').innerHTML = getColorPickerHTML('bordercolor_pick','bordercolor'); + document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor') + + var inst = ed; + var tdElm = ed.dom.getParent(ed.selection.getStart(), "td,th"); + var formObj = document.forms[0]; + var st = ed.dom.parseStyle(ed.dom.getAttrib(tdElm, "style")); + + // Get table cell data + var celltype = tdElm.nodeName.toLowerCase(); + var align = ed.dom.getAttrib(tdElm, 'align'); + var valign = ed.dom.getAttrib(tdElm, 'valign'); + var width = trimSize(getStyle(tdElm, 'width', 'width')); + var height = trimSize(getStyle(tdElm, 'height', 'height')); + var bordercolor = convertRGBToHex(getStyle(tdElm, 'bordercolor', 'borderLeftColor')); + var bgcolor = convertRGBToHex(getStyle(tdElm, 'bgcolor', 'backgroundColor')); + var className = ed.dom.getAttrib(tdElm, 'class'); + var backgroundimage = getStyle(tdElm, 'background', 'backgroundImage').replace(new RegExp("url\\(['\"]?([^'\"]*)['\"]?\\)", 'gi'), "$1"); + var id = ed.dom.getAttrib(tdElm, 'id'); + var lang = ed.dom.getAttrib(tdElm, 'lang'); + var dir = ed.dom.getAttrib(tdElm, 'dir'); + var scope = ed.dom.getAttrib(tdElm, 'scope'); + + // Setup form + addClassesToList('class', 'table_cell_styles'); + TinyMCE_EditableSelects.init(); + + if (!ed.dom.hasClass(tdElm, 'mceSelected')) { + formObj.bordercolor.value = bordercolor; + formObj.bgcolor.value = bgcolor; + formObj.backgroundimage.value = backgroundimage; + formObj.width.value = width; + formObj.height.value = height; + formObj.id.value = id; + formObj.lang.value = lang; + formObj.style.value = ed.dom.serializeStyle(st); + selectByValue(formObj, 'align', align); + selectByValue(formObj, 'valign', valign); + selectByValue(formObj, 'class', className, true, true); + selectByValue(formObj, 'celltype', celltype); + selectByValue(formObj, 'dir', dir); + selectByValue(formObj, 'scope', scope); + + // Resize some elements + if (isVisible('backgroundimagebrowser')) + document.getElementById('backgroundimage').style.width = '180px'; + + updateColor('bordercolor_pick', 'bordercolor'); + updateColor('bgcolor_pick', 'bgcolor'); + } else + tinyMCEPopup.dom.hide('action'); +} + +function updateAction() { + var el, inst = ed, tdElm, trElm, tableElm, formObj = document.forms[0]; + + if (!AutoValidator.validate(formObj)) { + tinyMCEPopup.alert(AutoValidator.getErrorMessages(formObj).join('. ') + '.'); + return false; + } + + tinyMCEPopup.restoreSelection(); + el = ed.selection.getStart(); + tdElm = ed.dom.getParent(el, "td,th"); + trElm = ed.dom.getParent(el, "tr"); + tableElm = ed.dom.getParent(el, "table"); + + // Cell is selected + if (ed.dom.hasClass(tdElm, 'mceSelected')) { + // Update all selected sells + tinymce.each(ed.dom.select('td.mceSelected,th.mceSelected'), function(td) { + updateCell(td); + }); + + ed.addVisual(); + ed.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); + return; + } + + switch (getSelectValue(formObj, 'action')) { + case "cell": + var celltype = getSelectValue(formObj, 'celltype'); + var scope = getSelectValue(formObj, 'scope'); + + function doUpdate(s) { + if (s) { + updateCell(tdElm); + + ed.addVisual(); + ed.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); + } + }; + + if (ed.getParam("accessibility_warnings", 1)) { + if (celltype == "th" && scope == "") + tinyMCEPopup.confirm(ed.getLang('table_dlg.missing_scope', '', true), doUpdate); + else + doUpdate(1); + + return; + } + + updateCell(tdElm); + break; + + case "row": + var cell = trElm.firstChild; + + if (cell.nodeName != "TD" && cell.nodeName != "TH") + cell = nextCell(cell); + + do { + cell = updateCell(cell, true); + } while ((cell = nextCell(cell)) != null); + + break; + + case "col": + var curr, col = 0, cell = trElm.firstChild, rows = tableElm.getElementsByTagName("tr"); + + if (cell.nodeName != "TD" && cell.nodeName != "TH") + cell = nextCell(cell); + + do { + if (cell == tdElm) + break; + col += cell.getAttribute("colspan"); + } while ((cell = nextCell(cell)) != null); + + for (var i=0; i<rows.length; i++) { + cell = rows[i].firstChild; + + if (cell.nodeName != "TD" && cell.nodeName != "TH") + cell = nextCell(cell); + + curr = 0; + do { + if (curr == col) { + cell = updateCell(cell, true); + break; + } + curr += cell.getAttribute("colspan"); + } while ((cell = nextCell(cell)) != null); + } + + break; + + case "all": + var rows = tableElm.getElementsByTagName("tr"); + + for (var i=0; i<rows.length; i++) { + var cell = rows[i].firstChild; + + if (cell.nodeName != "TD" && cell.nodeName != "TH") + cell = nextCell(cell); + + do { + cell = updateCell(cell, true); + } while ((cell = nextCell(cell)) != null); + } + + break; + } + + ed.addVisual(); + ed.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); +} + +function nextCell(elm) { + while ((elm = elm.nextSibling) != null) { + if (elm.nodeName == "TD" || elm.nodeName == "TH") + return elm; + } + + return null; +} + +function updateCell(td, skip_id) { + var inst = ed; + var formObj = document.forms[0]; + var curCellType = td.nodeName.toLowerCase(); + var celltype = getSelectValue(formObj, 'celltype'); + var doc = inst.getDoc(); + var dom = ed.dom; + + if (!skip_id) + dom.setAttrib(td, 'id', formObj.id.value); + + dom.setAttrib(td, 'align', formObj.align.value); + dom.setAttrib(td, 'vAlign', formObj.valign.value); + dom.setAttrib(td, 'lang', formObj.lang.value); + dom.setAttrib(td, 'dir', getSelectValue(formObj, 'dir')); + dom.setAttrib(td, 'style', ed.dom.serializeStyle(ed.dom.parseStyle(formObj.style.value))); + dom.setAttrib(td, 'scope', formObj.scope.value); + dom.setAttrib(td, 'class', getSelectValue(formObj, 'class')); + + // Clear deprecated attributes + ed.dom.setAttrib(td, 'width', ''); + ed.dom.setAttrib(td, 'height', ''); + ed.dom.setAttrib(td, 'bgColor', ''); + ed.dom.setAttrib(td, 'borderColor', ''); + ed.dom.setAttrib(td, 'background', ''); + + // Set styles + td.style.width = getCSSSize(formObj.width.value); + td.style.height = getCSSSize(formObj.height.value); + if (formObj.bordercolor.value != "") { + td.style.borderColor = formObj.bordercolor.value; + td.style.borderStyle = td.style.borderStyle == "" ? "solid" : td.style.borderStyle; + td.style.borderWidth = td.style.borderWidth == "" ? "1px" : td.style.borderWidth; + } else + td.style.borderColor = ''; + + td.style.backgroundColor = formObj.bgcolor.value; + + if (formObj.backgroundimage.value != "") + td.style.backgroundImage = "url('" + formObj.backgroundimage.value + "')"; + else + td.style.backgroundImage = ''; + + if (curCellType != celltype) { + // changing to a different node type + var newCell = doc.createElement(celltype); + + for (var c=0; c<td.childNodes.length; c++) + newCell.appendChild(td.childNodes[c].cloneNode(1)); + + for (var a=0; a<td.attributes.length; a++) + ed.dom.setAttrib(newCell, td.attributes[a].name, ed.dom.getAttrib(td, td.attributes[a].name)); + + td.parentNode.replaceChild(newCell, td); + td = newCell; + } + + dom.setAttrib(td, 'style', dom.serializeStyle(dom.parseStyle(td.style.cssText))); + + return td; +} + +function changedBackgroundImage() { + var formObj = document.forms[0]; + var st = ed.dom.parseStyle(formObj.style.value); + + st['background-image'] = "url('" + formObj.backgroundimage.value + "')"; + + formObj.style.value = ed.dom.serializeStyle(st); +} + +function changedSize() { + var formObj = document.forms[0]; + var st = ed.dom.parseStyle(formObj.style.value); + + var width = formObj.width.value; + if (width != "") + st['width'] = getCSSSize(width); + else + st['width'] = ""; + + var height = formObj.height.value; + if (height != "") + st['height'] = getCSSSize(height); + else + st['height'] = ""; + + formObj.style.value = ed.dom.serializeStyle(st); +} + +function changedColor() { + var formObj = document.forms[0]; + var st = ed.dom.parseStyle(formObj.style.value); + + st['background-color'] = formObj.bgcolor.value; + st['border-color'] = formObj.bordercolor.value; + + formObj.style.value = ed.dom.serializeStyle(st); +} + +function changedStyle() { + var formObj = document.forms[0]; + var st = ed.dom.parseStyle(formObj.style.value); + + if (st['background-image']) + formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1"); + else + formObj.backgroundimage.value = ''; + + if (st['width']) + formObj.width.value = trimSize(st['width']); + + if (st['height']) + formObj.height.value = trimSize(st['height']); + + if (st['background-color']) { + formObj.bgcolor.value = st['background-color']; + updateColor('bgcolor_pick','bgcolor'); + } + + if (st['border-color']) { + formObj.bordercolor.value = st['border-color']; + updateColor('bordercolor_pick','bordercolor'); + } +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/merge_cells.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/merge_cells.js new file mode 100644 index 0000000..7ee4bf0 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/merge_cells.js @@ -0,0 +1,27 @@ +tinyMCEPopup.requireLangPack(); + +var MergeCellsDialog = { + init : function() { + var f = document.forms[0]; + + f.numcols.value = tinyMCEPopup.getWindowArg('cols', 1); + f.numrows.value = tinyMCEPopup.getWindowArg('rows', 1); + }, + + merge : function() { + var func, f = document.forms[0]; + + tinyMCEPopup.restoreSelection(); + + func = tinyMCEPopup.getWindowArg('onaction'); + + func({ + cols : f.numcols.value, + rows : f.numrows.value + }); + + tinyMCEPopup.close(); + } +}; + +tinyMCEPopup.onInit.add(MergeCellsDialog.init, MergeCellsDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/row.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/row.js new file mode 100644 index 0000000..a13d695 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/row.js @@ -0,0 +1,237 @@ +tinyMCEPopup.requireLangPack(); + +function init() { + tinyMCEPopup.resizeToInnerSize(); + + document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table'); + document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor'); + + var inst = tinyMCEPopup.editor; + var dom = inst.dom; + var trElm = dom.getParent(inst.selection.getStart(), "tr"); + var formObj = document.forms[0]; + var st = dom.parseStyle(dom.getAttrib(trElm, "style")); + + // Get table row data + var rowtype = trElm.parentNode.nodeName.toLowerCase(); + var align = dom.getAttrib(trElm, 'align'); + var valign = dom.getAttrib(trElm, 'valign'); + var height = trimSize(getStyle(trElm, 'height', 'height')); + var className = dom.getAttrib(trElm, 'class'); + var bgcolor = convertRGBToHex(getStyle(trElm, 'bgcolor', 'backgroundColor')); + var backgroundimage = getStyle(trElm, 'background', 'backgroundImage').replace(new RegExp("url\\(['\"]?([^'\"]*)['\"]?\\)", 'gi'), "$1"); + var id = dom.getAttrib(trElm, 'id'); + var lang = dom.getAttrib(trElm, 'lang'); + var dir = dom.getAttrib(trElm, 'dir'); + + selectByValue(formObj, 'rowtype', rowtype); + + // Any cells selected + if (dom.select('td.mceSelected,th.mceSelected', trElm).length == 0) { + // Setup form + addClassesToList('class', 'table_row_styles'); + TinyMCE_EditableSelects.init(); + + formObj.bgcolor.value = bgcolor; + formObj.backgroundimage.value = backgroundimage; + formObj.height.value = height; + formObj.id.value = id; + formObj.lang.value = lang; + formObj.style.value = dom.serializeStyle(st); + selectByValue(formObj, 'align', align); + selectByValue(formObj, 'valign', valign); + selectByValue(formObj, 'class', className, true, true); + selectByValue(formObj, 'dir', dir); + + // Resize some elements + if (isVisible('backgroundimagebrowser')) + document.getElementById('backgroundimage').style.width = '180px'; + + updateColor('bgcolor_pick', 'bgcolor'); + } else + tinyMCEPopup.dom.hide('action'); +} + +function updateAction() { + var inst = tinyMCEPopup.editor, dom = inst.dom, trElm, tableElm, formObj = document.forms[0]; + var action = getSelectValue(formObj, 'action'); + + if (!AutoValidator.validate(formObj)) { + tinyMCEPopup.alert(AutoValidator.getErrorMessages(formObj).join('. ') + '.'); + return false; + } + + tinyMCEPopup.restoreSelection(); + trElm = dom.getParent(inst.selection.getStart(), "tr"); + tableElm = dom.getParent(inst.selection.getStart(), "table"); + + // Update all selected rows + if (dom.select('td.mceSelected,th.mceSelected', trElm).length > 0) { + tinymce.each(tableElm.rows, function(tr) { + var i; + + for (i = 0; i < tr.cells.length; i++) { + if (dom.hasClass(tr.cells[i], 'mceSelected')) { + updateRow(tr, true); + return; + } + } + }); + + inst.addVisual(); + inst.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); + return; + } + + switch (action) { + case "row": + updateRow(trElm); + break; + + case "all": + var rows = tableElm.getElementsByTagName("tr"); + + for (var i=0; i<rows.length; i++) + updateRow(rows[i], true); + + break; + + case "odd": + case "even": + var rows = tableElm.getElementsByTagName("tr"); + + for (var i=0; i<rows.length; i++) { + if ((i % 2 == 0 && action == "odd") || (i % 2 != 0 && action == "even")) + updateRow(rows[i], true, true); + } + + break; + } + + inst.addVisual(); + inst.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); +} + +function updateRow(tr_elm, skip_id, skip_parent) { + var inst = tinyMCEPopup.editor; + var formObj = document.forms[0]; + var dom = inst.dom; + var curRowType = tr_elm.parentNode.nodeName.toLowerCase(); + var rowtype = getSelectValue(formObj, 'rowtype'); + var doc = inst.getDoc(); + + // Update row element + if (!skip_id) + dom.setAttrib(tr_elm, 'id', formObj.id.value); + + dom.setAttrib(tr_elm, 'align', getSelectValue(formObj, 'align')); + dom.setAttrib(tr_elm, 'vAlign', getSelectValue(formObj, 'valign')); + dom.setAttrib(tr_elm, 'lang', formObj.lang.value); + dom.setAttrib(tr_elm, 'dir', getSelectValue(formObj, 'dir')); + dom.setAttrib(tr_elm, 'style', dom.serializeStyle(dom.parseStyle(formObj.style.value))); + dom.setAttrib(tr_elm, 'class', getSelectValue(formObj, 'class')); + + // Clear deprecated attributes + dom.setAttrib(tr_elm, 'background', ''); + dom.setAttrib(tr_elm, 'bgColor', ''); + dom.setAttrib(tr_elm, 'height', ''); + + // Set styles + tr_elm.style.height = getCSSSize(formObj.height.value); + tr_elm.style.backgroundColor = formObj.bgcolor.value; + + if (formObj.backgroundimage.value != "") + tr_elm.style.backgroundImage = "url('" + formObj.backgroundimage.value + "')"; + else + tr_elm.style.backgroundImage = ''; + + // Setup new rowtype + if (curRowType != rowtype && !skip_parent) { + // first, clone the node we are working on + var newRow = tr_elm.cloneNode(1); + + // next, find the parent of its new destination (creating it if necessary) + var theTable = dom.getParent(tr_elm, "table"); + var dest = rowtype; + var newParent = null; + for (var i = 0; i < theTable.childNodes.length; i++) { + if (theTable.childNodes[i].nodeName.toLowerCase() == dest) + newParent = theTable.childNodes[i]; + } + + if (newParent == null) { + newParent = doc.createElement(dest); + + if (theTable.firstChild.nodeName == 'CAPTION') + inst.dom.insertAfter(newParent, theTable.firstChild); + else + theTable.insertBefore(newParent, theTable.firstChild); + } + + // append the row to the new parent + newParent.appendChild(newRow); + + // remove the original + tr_elm.parentNode.removeChild(tr_elm); + + // set tr_elm to the new node + tr_elm = newRow; + } + + dom.setAttrib(tr_elm, 'style', dom.serializeStyle(dom.parseStyle(tr_elm.style.cssText))); +} + +function changedBackgroundImage() { + var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom; + var st = dom.parseStyle(formObj.style.value); + + st['background-image'] = "url('" + formObj.backgroundimage.value + "')"; + + formObj.style.value = dom.serializeStyle(st); +} + +function changedStyle() { + var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom; + var st = dom.parseStyle(formObj.style.value); + + if (st['background-image']) + formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1"); + else + formObj.backgroundimage.value = ''; + + if (st['height']) + formObj.height.value = trimSize(st['height']); + + if (st['background-color']) { + formObj.bgcolor.value = st['background-color']; + updateColor('bgcolor_pick','bgcolor'); + } +} + +function changedSize() { + var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom; + var st = dom.parseStyle(formObj.style.value); + + var height = formObj.height.value; + if (height != "") + st['height'] = getCSSSize(height); + else + st['height'] = ""; + + formObj.style.value = dom.serializeStyle(st); +} + +function changedColor() { + var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom; + var st = dom.parseStyle(formObj.style.value); + + st['background-color'] = formObj.bgcolor.value; + + formObj.style.value = dom.serializeStyle(st); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/table.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/table.js new file mode 100644 index 0000000..520d857 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/js/table.js @@ -0,0 +1,450 @@ +tinyMCEPopup.requireLangPack(); + +var action, orgTableWidth, orgTableHeight, dom = tinyMCEPopup.editor.dom; + +function insertTable() { + var formObj = document.forms[0]; + var inst = tinyMCEPopup.editor, dom = inst.dom; + var cols = 2, rows = 2, border = 0, cellpadding = -1, cellspacing = -1, align, width, height, className, caption, frame, rules; + var html = '', capEl, elm; + var cellLimit, rowLimit, colLimit; + + tinyMCEPopup.restoreSelection(); + + if (!AutoValidator.validate(formObj)) { + tinyMCEPopup.alert(AutoValidator.getErrorMessages(formObj).join('. ') + '.'); + return false; + } + + elm = dom.getParent(inst.selection.getNode(), 'table'); + + // Get form data + cols = formObj.elements['cols'].value; + rows = formObj.elements['rows'].value; + border = formObj.elements['border'].value != "" ? formObj.elements['border'].value : 0; + cellpadding = formObj.elements['cellpadding'].value != "" ? formObj.elements['cellpadding'].value : ""; + cellspacing = formObj.elements['cellspacing'].value != "" ? formObj.elements['cellspacing'].value : ""; + align = getSelectValue(formObj, "align"); + frame = getSelectValue(formObj, "tframe"); + rules = getSelectValue(formObj, "rules"); + width = formObj.elements['width'].value; + height = formObj.elements['height'].value; + bordercolor = formObj.elements['bordercolor'].value; + bgcolor = formObj.elements['bgcolor'].value; + className = getSelectValue(formObj, "class"); + id = formObj.elements['id'].value; + summary = formObj.elements['summary'].value; + style = formObj.elements['style'].value; + dir = formObj.elements['dir'].value; + lang = formObj.elements['lang'].value; + background = formObj.elements['backgroundimage'].value; + caption = formObj.elements['caption'].checked; + + cellLimit = tinyMCEPopup.getParam('table_cell_limit', false); + rowLimit = tinyMCEPopup.getParam('table_row_limit', false); + colLimit = tinyMCEPopup.getParam('table_col_limit', false); + + // Validate table size + if (colLimit && cols > colLimit) { + tinyMCEPopup.alert(inst.getLang('table_dlg.col_limit').replace(/\{\$cols\}/g, colLimit)); + return false; + } else if (rowLimit && rows > rowLimit) { + tinyMCEPopup.alert(inst.getLang('table_dlg.row_limit').replace(/\{\$rows\}/g, rowLimit)); + return false; + } else if (cellLimit && cols * rows > cellLimit) { + tinyMCEPopup.alert(inst.getLang('table_dlg.cell_limit').replace(/\{\$cells\}/g, cellLimit)); + return false; + } + + // Update table + if (action == "update") { + dom.setAttrib(elm, 'cellPadding', cellpadding, true); + dom.setAttrib(elm, 'cellSpacing', cellspacing, true); + dom.setAttrib(elm, 'border', border); + dom.setAttrib(elm, 'align', align); + dom.setAttrib(elm, 'frame', frame); + dom.setAttrib(elm, 'rules', rules); + dom.setAttrib(elm, 'class', className); + dom.setAttrib(elm, 'style', style); + dom.setAttrib(elm, 'id', id); + dom.setAttrib(elm, 'summary', summary); + dom.setAttrib(elm, 'dir', dir); + dom.setAttrib(elm, 'lang', lang); + + capEl = inst.dom.select('caption', elm)[0]; + + if (capEl && !caption) + capEl.parentNode.removeChild(capEl); + + if (!capEl && caption) { + capEl = elm.ownerDocument.createElement('caption'); + + if (!tinymce.isIE) + capEl.innerHTML = '<br data-mce-bogus="1"/>'; + + elm.insertBefore(capEl, elm.firstChild); + } + + if (width && inst.settings.inline_styles) { + dom.setStyle(elm, 'width', width); + dom.setAttrib(elm, 'width', ''); + } else { + dom.setAttrib(elm, 'width', width, true); + dom.setStyle(elm, 'width', ''); + } + + // Remove these since they are not valid XHTML + dom.setAttrib(elm, 'borderColor', ''); + dom.setAttrib(elm, 'bgColor', ''); + dom.setAttrib(elm, 'background', ''); + + if (height && inst.settings.inline_styles) { + dom.setStyle(elm, 'height', height); + dom.setAttrib(elm, 'height', ''); + } else { + dom.setAttrib(elm, 'height', height, true); + dom.setStyle(elm, 'height', ''); + } + + if (background != '') + elm.style.backgroundImage = "url('" + background + "')"; + else + elm.style.backgroundImage = ''; + +/* if (tinyMCEPopup.getParam("inline_styles")) { + if (width != '') + elm.style.width = getCSSSize(width); + }*/ + + if (bordercolor != "") { + elm.style.borderColor = bordercolor; + elm.style.borderStyle = elm.style.borderStyle == "" ? "solid" : elm.style.borderStyle; + elm.style.borderWidth = border == "" ? "1px" : border; + } else + elm.style.borderColor = ''; + + elm.style.backgroundColor = bgcolor; + elm.style.height = getCSSSize(height); + + inst.addVisual(); + + // Fix for stange MSIE align bug + //elm.outerHTML = elm.outerHTML; + + inst.nodeChanged(); + inst.execCommand('mceEndUndoLevel'); + + // Repaint if dimensions changed + if (formObj.width.value != orgTableWidth || formObj.height.value != orgTableHeight) + inst.execCommand('mceRepaint'); + + tinyMCEPopup.close(); + return true; + } + + // Create new table + html += '<table'; + + html += makeAttrib('id', id); + html += makeAttrib('border', border); + html += makeAttrib('cellpadding', cellpadding); + html += makeAttrib('cellspacing', cellspacing); + html += makeAttrib('data-mce-new', '1'); + + if (width && inst.settings.inline_styles) { + if (style) + style += '; '; + + // Force px + if (/^[0-9\.]+$/.test(width)) + width += 'px'; + + style += 'width: ' + width; + } else + html += makeAttrib('width', width); + +/* if (height) { + if (style) + style += '; '; + + style += 'height: ' + height; + }*/ + + //html += makeAttrib('height', height); + //html += makeAttrib('bordercolor', bordercolor); + //html += makeAttrib('bgcolor', bgcolor); + html += makeAttrib('align', align); + html += makeAttrib('frame', frame); + html += makeAttrib('rules', rules); + html += makeAttrib('class', className); + html += makeAttrib('style', style); + html += makeAttrib('summary', summary); + html += makeAttrib('dir', dir); + html += makeAttrib('lang', lang); + html += '>'; + + if (caption) { + if (!tinymce.isIE) + html += '<caption><br data-mce-bogus="1"/></caption>'; + else + html += '<caption></caption>'; + } + + for (var y=0; y<rows; y++) { + html += "<tr>"; + + for (var x=0; x<cols; x++) { + if (!tinymce.isIE) + html += '<td><br data-mce-bogus="1"/></td>'; + else + html += '<td></td>'; + } + + html += "</tr>"; + } + + html += "</table>"; + + // Move table + if (inst.settings.fix_table_elements) { + var patt = ''; + + inst.focus(); + inst.selection.setContent('<br class="_mce_marker" />'); + + tinymce.each('h1,h2,h3,h4,h5,h6,p'.split(','), function(n) { + if (patt) + patt += ','; + + patt += n + ' ._mce_marker'; + }); + + tinymce.each(inst.dom.select(patt), function(n) { + inst.dom.split(inst.dom.getParent(n, 'h1,h2,h3,h4,h5,h6,p'), n); + }); + + dom.setOuterHTML(dom.select('br._mce_marker')[0], html); + } else + inst.execCommand('mceInsertContent', false, html); + + tinymce.each(dom.select('table[data-mce-new]'), function(node) { + var td = dom.select('td', node); + + try { + // IE9 might fail to do this selection + inst.selection.select(td[0], true); + inst.selection.collapse(); + } catch (ex) { + // Ignore + } + + dom.setAttrib(node, 'data-mce-new', ''); + }); + + inst.addVisual(); + inst.execCommand('mceEndUndoLevel'); + + tinyMCEPopup.close(); +} + +function makeAttrib(attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib]; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + if (value == "") + return ""; + + // XML encode it + value = value.replace(/&/g, '&amp;'); + value = value.replace(/\"/g, '&quot;'); + value = value.replace(/</g, '&lt;'); + value = value.replace(/>/g, '&gt;'); + + return ' ' + attrib + '="' + value + '"'; +} + +function init() { + tinyMCEPopup.resizeToInnerSize(); + + document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table'); + document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table'); + document.getElementById('bordercolor_pickcontainer').innerHTML = getColorPickerHTML('bordercolor_pick','bordercolor'); + document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor'); + + var cols = 2, rows = 2, border = tinyMCEPopup.getParam('table_default_border', '0'), cellpadding = tinyMCEPopup.getParam('table_default_cellpadding', ''), cellspacing = tinyMCEPopup.getParam('table_default_cellspacing', ''); + var align = "", width = "", height = "", bordercolor = "", bgcolor = "", className = ""; + var id = "", summary = "", style = "", dir = "", lang = "", background = "", bgcolor = "", bordercolor = "", rules = "", frame = ""; + var inst = tinyMCEPopup.editor, dom = inst.dom; + var formObj = document.forms[0]; + var elm = dom.getParent(inst.selection.getNode(), "table"); + + action = tinyMCEPopup.getWindowArg('action'); + + if (!action) + action = elm ? "update" : "insert"; + + if (elm && action != "insert") { + var rowsAr = elm.rows; + var cols = 0; + for (var i=0; i<rowsAr.length; i++) + if (rowsAr[i].cells.length > cols) + cols = rowsAr[i].cells.length; + + cols = cols; + rows = rowsAr.length; + + st = dom.parseStyle(dom.getAttrib(elm, "style")); + border = trimSize(getStyle(elm, 'border', 'borderWidth')); + cellpadding = dom.getAttrib(elm, 'cellpadding', ""); + cellspacing = dom.getAttrib(elm, 'cellspacing', ""); + width = trimSize(getStyle(elm, 'width', 'width')); + height = trimSize(getStyle(elm, 'height', 'height')); + bordercolor = convertRGBToHex(getStyle(elm, 'bordercolor', 'borderLeftColor')); + bgcolor = convertRGBToHex(getStyle(elm, 'bgcolor', 'backgroundColor')); + align = dom.getAttrib(elm, 'align', align); + frame = dom.getAttrib(elm, 'frame'); + rules = dom.getAttrib(elm, 'rules'); + className = tinymce.trim(dom.getAttrib(elm, 'class').replace(/mceItem.+/g, '')); + id = dom.getAttrib(elm, 'id'); + summary = dom.getAttrib(elm, 'summary'); + style = dom.serializeStyle(st); + dir = dom.getAttrib(elm, 'dir'); + lang = dom.getAttrib(elm, 'lang'); + background = getStyle(elm, 'background', 'backgroundImage').replace(new RegExp("url\\(['\"]?([^'\"]*)['\"]?\\)", 'gi'), "$1"); + formObj.caption.checked = elm.getElementsByTagName('caption').length > 0; + + orgTableWidth = width; + orgTableHeight = height; + + action = "update"; + formObj.insert.value = inst.getLang('update'); + } + + addClassesToList('class', "table_styles"); + TinyMCE_EditableSelects.init(); + + // Update form + selectByValue(formObj, 'align', align); + selectByValue(formObj, 'tframe', frame); + selectByValue(formObj, 'rules', rules); + selectByValue(formObj, 'class', className, true, true); + formObj.cols.value = cols; + formObj.rows.value = rows; + formObj.border.value = border; + formObj.cellpadding.value = cellpadding; + formObj.cellspacing.value = cellspacing; + formObj.width.value = width; + formObj.height.value = height; + formObj.bordercolor.value = bordercolor; + formObj.bgcolor.value = bgcolor; + formObj.id.value = id; + formObj.summary.value = summary; + formObj.style.value = style; + formObj.dir.value = dir; + formObj.lang.value = lang; + formObj.backgroundimage.value = background; + + updateColor('bordercolor_pick', 'bordercolor'); + updateColor('bgcolor_pick', 'bgcolor'); + + // Resize some elements + if (isVisible('backgroundimagebrowser')) + document.getElementById('backgroundimage').style.width = '180px'; + + // Disable some fields in update mode + if (action == "update") { + formObj.cols.disabled = true; + formObj.rows.disabled = true; + } +} + +function changedSize() { + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + +/* var width = formObj.width.value; + if (width != "") + st['width'] = tinyMCEPopup.getParam("inline_styles") ? getCSSSize(width) : ""; + else + st['width'] = "";*/ + + var height = formObj.height.value; + if (height != "") + st['height'] = getCSSSize(height); + else + st['height'] = ""; + + formObj.style.value = dom.serializeStyle(st); +} + +function changedBackgroundImage() { + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + st['background-image'] = "url('" + formObj.backgroundimage.value + "')"; + + formObj.style.value = dom.serializeStyle(st); +} + +function changedBorder() { + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + // Update border width if the element has a color + if (formObj.border.value != "" && formObj.bordercolor.value != "") + st['border-width'] = formObj.border.value + "px"; + + formObj.style.value = dom.serializeStyle(st); +} + +function changedColor() { + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + st['background-color'] = formObj.bgcolor.value; + + if (formObj.bordercolor.value != "") { + st['border-color'] = formObj.bordercolor.value; + + // Add border-width if it's missing + if (!st['border-width']) + st['border-width'] = formObj.border.value == "" ? "1px" : formObj.border.value + "px"; + } + + formObj.style.value = dom.serializeStyle(st); +} + +function changedStyle() { + var formObj = document.forms[0]; + var st = dom.parseStyle(formObj.style.value); + + if (st['background-image']) + formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\(['\"]?([^'\"]*)['\"]?\\)", 'gi'), "$1"); + else + formObj.backgroundimage.value = ''; + + if (st['width']) + formObj.width.value = trimSize(st['width']); + + if (st['height']) + formObj.height.value = trimSize(st['height']); + + if (st['background-color']) { + formObj.bgcolor.value = st['background-color']; + updateColor('bgcolor_pick','bgcolor'); + } + + if (st['border-color']) { + formObj.bordercolor.value = st['border-color']; + updateColor('bordercolor_pick','bordercolor'); + } +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/de_dlg.js new file mode 100644 index 0000000..5a64ebd --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.table_dlg',{"rules_border":"alle 4 Seiten (Border)","rules_box":"alle 4 Seiten (Box)","rules_vsides":"links und rechts","rules_rhs":"nur rechts","rules_lhs":"nur links","rules_hsides":"oben und unten","rules_below":"nur unten","rules_above":"nur oben","rules_void":"keins",rules:"Gitter","frame_all":"zwischen allen Zellen","frame_cols":"zwischen Spalten","frame_rows":"zwischen Zeilen","frame_groups":"zwischen Gruppen","frame_none":"keine",frame:"Rahmen",caption:"Beschriftung der Tabelle","missing_scope":"Wollen Sie wirklich keine Beziehung f\u00fcr diese \u00dcberschrift angeben? Benutzer mit k\u00f6rperlichen Einschr\u00e4nkungen k\u00f6nnten Schwierigkeiten haben, den Inhalt der Tabelle zu verstehen.","cell_limit":"Sie haben die maximale Zellenzahl von {$cells} \u00fcberschritten.","row_limit":"Sie haben die maximale Zeilenzahl von {$rows} \u00fcberschritten.","col_limit":"Sie haben die maximale Spaltenzahl von {$cols} \u00fcberschritten.",colgroup:"Horizontal gruppieren",rowgroup:"Vertikal gruppieren",scope:"Bezug",tfoot:"Tabellenfu\u00df",tbody:"Tabelleninhalt",thead:"Tabellenkopf","row_all":"Alle Zeilen ver\u00e4ndern","row_even":"Gerade Zeilen ver\u00e4ndern","row_odd":"Ungerade Zeilen ver\u00e4ndern","row_row":"Diese Zeile ver\u00e4ndern","cell_all":"Alle Zellen der Tabelle ver\u00e4ndern","cell_row":"Alle Zellen in dieser Zeile ver\u00e4ndern","cell_cell":"Diese Zelle ver\u00e4ndern",th:"\u00dcberschrift",td:"Textzelle",summary:"Zusammenfassung",bgimage:"Hintergrundbild",rtl:"Rechts nach links",ltr:"Links nach rechts",mime:"MIME-Type des Inhalts",langcode:"Sprachcode",langdir:"Schriftrichtung",style:"Format",id:"ID","merge_cells_title":"Zellen vereinen",bgcolor:"Hintergrundfarbe",bordercolor:"Rahmenfarbe","align_bottom":"Unten","align_top":"Oben",valign:"Vertikale Ausrichtung","cell_type":"Zellentyp","cell_title":"Eigenschaften der Zelle","row_title":"Eigenschaften der Zeile","align_middle":"Mittig","align_right":"Rechts","align_left":"Links","align_default":"Standard",align:"Ausrichtung",border:"Rahmen",cellpadding:"Abstand innerhalb der Zellen",cellspacing:"Zellenabstand",rows:"Zeilen",cols:"Spalten",height:"H\u00f6he",width:"Breite",title:"Tabelle einf\u00fcgen/bearbeiten",rowtype:"Gruppierung","advanced_props":"Erweiterte Einstellungen","general_props":"Allgemeine Einstellungen","advanced_tab":"Erweitert","general_tab":"Allgemein","cell_col":"Alle Zellen in dieser Spalte aktualisieren"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/en_dlg.js new file mode 100644 index 0000000..463e09e --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.table_dlg',{"rules_border":"border","rules_box":"box","rules_vsides":"vsides","rules_rhs":"rhs","rules_lhs":"lhs","rules_hsides":"hsides","rules_below":"below","rules_above":"above","rules_void":"void",rules:"Rules","frame_all":"all","frame_cols":"cols","frame_rows":"rows","frame_groups":"groups","frame_none":"none",frame:"Frame",caption:"Table Caption","missing_scope":"Are you sure you want to continue without specifying a scope for this table header cell. Without it, it may be difficult for some users with disabilities to understand the content or data displayed of the table.","cell_limit":"You\'ve exceeded the maximum number of cells of {$cells}.","row_limit":"You\'ve exceeded the maximum number of rows of {$rows}.","col_limit":"You\'ve exceeded the maximum number of columns of {$cols}.",colgroup:"Col Group",rowgroup:"Row Group",scope:"Scope",tfoot:"Footer",tbody:"Body",thead:"Header","row_all":"Update All Rows in Table","row_even":"Update Even Rows in Table","row_odd":"Update Odd Rows in Table","row_row":"Update Current Row","cell_all":"Update All Cells in Table","cell_row":"Update All Cells in Row","cell_cell":"Update Current Cell",th:"Header",td:"Data",summary:"Summary",bgimage:"Background Image",rtl:"Right to Left",ltr:"Left to Right",mime:"Target MIME Type",langcode:"Language Code",langdir:"Language Direction",style:"Style",id:"ID","merge_cells_title":"Merge Table Cells",bgcolor:"Background Color",bordercolor:"Border Color","align_bottom":"Bottom","align_top":"Top",valign:"Vertical Alignment","cell_type":"Cell Type","cell_title":"Table Cell Properties","row_title":"Table Row Properties","align_middle":"Center","align_right":"Right","align_left":"Left","align_default":"Default",align:"Alignment",border:"Border",cellpadding:"Cell Padding",cellspacing:"Cell Spacing",rows:"Rows",cols:"Columns",height:"Height",width:"Width",title:"Insert/Edit Table",rowtype:"Row Type","advanced_props":"Advanced Properties","general_props":"General Properties","advanced_tab":"Advanced","general_tab":"General","cell_col":"Update all cells in column"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/fr_dlg.js new file mode 100644 index 0000000..9f9488a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.table_dlg',{"rules_border":"bordure","rules_box":"bo\u00eete","rules_vsides":"verticales","rules_rhs":"\u00e0 droite","rules_lhs":"\u00e0 gauche","rules_hsides":"horizontales","rules_below":"au-dessous","rules_above":"au-dessus","rules_void":"aucune",rules:"R\u00e8gles","frame_all":"tous","frame_cols":"colonnes","frame_rows":"lignes","frame_groups":"groupe","frame_none":"aucun",frame:"Cadre",caption:"Afficher la l\u00e9gende du tableau","missing_scope":"\u00cates-vous s\u00fbr de vouloir continuer sans sp\u00e9cifier de port\u00e9e pour cette cellule de titre ? Sans port\u00e9e, cela peut \u00eatre difficile pour certains utilisateurs de comprendre le contenu ou les donn\u00e9es affich\u00e9es dans le tableau.","cell_limit":"Vous avez d\u00e9pass\u00e9 le nombre maximum de cellules ({$cells}).","row_limit":"Vous avez d\u00e9pass\u00e9 le nombre maximum de lignes ({$rows}).","col_limit":"Vous avez d\u00e9pass\u00e9 le nombre maximum de colonnes ({$cols}).",colgroup:"Groupe de colonnes",rowgroup:"Groupe de lignes",scope:"Port\u00e9e",tfoot:"Pied de tableau",tbody:"Corps de tableau",thead:"En-t\u00eates de tableau","row_all":"Mettre \u00e0 jour toutes les lignes du tableau","row_even":"Mettre \u00e0 jour les lignes paires","row_odd":"Mettre \u00e0 jour les lignes impaires","row_row":"Mettre \u00e0 jour la ligne courante","cell_all":"Mettre \u00e0 jour toutes les cellules du tableau","cell_row":"Mettre \u00e0 jour toutes les cellules de la ligne","cell_cell":"Mettre \u00e0 jour la cellule courante",th:"Titre",td:"Donn\u00e9es",summary:"R\u00e9sum\u00e9",bgimage:"Image de fond",rtl:"de droite \u00e0 gauche",ltr:"De gauche \u00e0 droite",mime:"Type MIME de la cible",langcode:"Code de la langue",langdir:"Sens de lecture",style:"Style",id:"Id","merge_cells_title":"Fusionner les cellules",bgcolor:"Couleur du fond",bordercolor:"Couleur de la bordure","align_bottom":"Bas","align_top":"Haut",valign:"Alignement vertical","cell_type":"Type de cellule","cell_title":"Propri\u00e9t\u00e9s de la cellule","row_title":"Propri\u00e9t\u00e9s de la ligne","align_middle":"Centr\u00e9","align_right":"Droite","align_left":"Gauche","align_default":"Par d\u00e9faut",align:"Alignement",border:"Bordure",cellpadding:"Espacement dans les cellules",cellspacing:"Espacement entre les cellules",rows:"Lignes",cols:"Colonnes",height:"Hauteur",width:"Largeur",title:"Ins\u00e9rer / modifier un tableau",rowtype:"Type de ligne","advanced_props":"Propri\u00e9t\u00e9s avanc\u00e9es","general_props":"Propri\u00e9t\u00e9s g\u00e9n\u00e9rales","advanced_tab":"Avanc\u00e9","general_tab":"G\u00e9n\u00e9ral","cell_col":"Mettre \u00e0 jour toutes les cellules de la colonne"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/it_dlg.js new file mode 100644 index 0000000..2a847ed --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.table_dlg',{"rules_border":"bordo","rules_box":"box","rules_vsides":"lato vert.","rules_rhs":"rhs","rules_lhs":"lhs","rules_hsides":"lato orizz.","rules_below":"sotto","rules_above":"sopra","rules_void":"vuoto",rules:"Regole","frame_all":"tutte","frame_cols":"colonne","frame_rows":"righe","frame_groups":"gruppi","frame_none":"nessuna",frame:"Cornice",caption:"Didascalia tabella","missing_scope":"Sicuro di proseguire senza aver specificato uno scope per l\'intestazione di questa tabella? Senza di esso, potrebbe essere difficoltoso per alcuni utenti con disabilit\u00e0 capire il contenuto o i dati mostrati nella tabella.","cell_limit":"Superato il numero massimo di celle di {$cells}.","row_limit":"Superato il numero massimo di righe di {$rows}.","col_limit":"Superato il numero massimo di colonne di {$cols}.",colgroup:"Gruppo colonna",rowgroup:"Gruppo riga",scope:"Scope",tfoot:"Pedice tabella",tbody:"Corpo tabella",thead:"Intestazione tabella","row_all":"Update tutte le righe della tabella","row_even":"Aggiorna righe pari della tabella","row_odd":"Aggiorna righe dispari della tabella","row_row":"Aggiorna riga corrente","cell_all":"Aggiorna tutte le celle della tabella","cell_row":"Aggiorna tutte le celle della riga","cell_cell":"Aggiorna cella corrente",th:"Intestazione",td:"Data",summary:"Sommario",bgimage:"Immagine sfondo",rtl:"Destra verso sinistra",ltr:"Sinistra verso destra",mime:"Tipo MIME del target",langcode:"Lingua",langdir:"Direzione testo",style:"Stile",id:"Id","merge_cells_title":"Unisci celle",bgcolor:"Colore sfondo",bordercolor:"Colore bordo","align_bottom":"In basso","align_top":"In alto",valign:"Allineamento verticale","cell_type":"Tipo cella","cell_title":"Propriet\u00e0 cella","row_title":"Propriet\u00e0 riga","align_middle":"Centra","align_right":"A destra","align_left":"A sinistra","align_default":"Predefinito",align:"Allineamento",border:"Bordo",cellpadding:"Padding celle",cellspacing:"Spaziatura celle",rows:"Righe",cols:"Colonne",height:"Altezza",width:"Larghezza",title:"Inserisci/Modifica tabella",rowtype:"Riga in una parte di tabella","advanced_props":"Propriet\u00e0 avanzate","general_props":"Propriet\u00e0 generali","advanced_tab":"Avanzate","general_tab":"Generale","cell_col":"Aggiorna tutte le celle della colonna"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/merge_cells.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/merge_cells.htm new file mode 100644 index 0000000..d231090 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/merge_cells.htm @@ -0,0 +1,32 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#table_dlg.merge_cells_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="js/merge_cells.js"></script> +</head> +<body style="margin: 8px" role="application"> +<form onsubmit="MergeCellsDialog.merge();return false;" action="#"> + <fieldset> + <legend>{#table_dlg.merge_cells_title}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="3" width="100%"> + <tr> + <td><label for="numcols">{#table_dlg.cols}</label>:</td> + <td align="right"><input type="text" id="numcols" name="numcols" value="" class="number min1 mceFocus" style="width: 30px" aria-required="true" /></td> + </tr> + <tr> + <td><label for="numrows">{#table_dlg.rows}</label>:</td> + <td align="right"><input type="text" id="numrows" name="numrows" value="" class="number min1" style="width: 30px" aria-required="true" /></td> + </tr> + </table> + </fieldset> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/row.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/row.htm new file mode 100644 index 0000000..1885401 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/row.htm @@ -0,0 +1,158 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#table_dlg.row_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/row.js"></script> + <link href="css/row.css" rel="stylesheet" type="text/css" /> +</head> +<body id="tablerow" style="display: none" role="application"> + <form onsubmit="updateAction();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#table_dlg.general_props}</legend> + + <table role="presentation" border="0" cellpadding="4" cellspacing="0"> + <tr> + <td><label for="rowtype">{#table_dlg.rowtype}</label></td> + <td class="col2"> + <select id="rowtype" name="rowtype" class="mceFocus"> + <option value="thead">{#table_dlg.thead}</option> + <option value="tbody">{#table_dlg.tbody}</option> + <option value="tfoot">{#table_dlg.tfoot}</option> + </select> + </td> + </tr> + + <tr> + <td><label for="align">{#table_dlg.align}</label></td> + <td class="col2"> + <select id="align" name="align"> + <option value="">{#not_set}</option> + <option value="center">{#table_dlg.align_middle}</option> + <option value="left">{#table_dlg.align_left}</option> + <option value="right">{#table_dlg.align_right}</option> + </select> + </td> + </tr> + + <tr> + <td><label for="valign">{#table_dlg.valign}</label></td> + <td class="col2"> + <select id="valign" name="valign"> + <option value="">{#not_set}</option> + <option value="top">{#table_dlg.align_top}</option> + <option value="middle">{#table_dlg.align_middle}</option> + <option value="bottom">{#table_dlg.align_bottom}</option> + </select> + </td> + </tr> + + <tr id="styleSelectRow"> + <td><label for="class">{#class_name}</label></td> + <td class="col2"> + <select id="class" name="class" class="mceEditableSelect"> + <option value="" selected="selected">{#not_set}</option> + </select> + </td> + </tr> + + <tr> + <td><label for="height">{#table_dlg.height}</label></td> + <td class="col2"><input name="height" type="text" id="height" value="" size="7" maxlength="7" onchange="changedSize();" class="size" /></td> + </tr> + </table> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#table_dlg.advanced_props}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="column1"><label for="id">{#table_dlg.id}</label></td> + <td><input id="id" name="id" type="text" value="" style="width: 200px" /></td> + </tr> + + <tr> + <td><label for="style">{#table_dlg.style}</label></td> + <td><input type="text" id="style" name="style" value="" style="width: 200px;" onchange="changedStyle();" /></td> + </tr> + + <tr> + <td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> + <td> + <select id="dir" name="dir" style="width: 200px"> + <option value="">{#not_set}</option> + <option value="ltr">{#table_dlg.ltr}</option> + <option value="rtl">{#table_dlg.rtl}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="lang">{#table_dlg.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" style="width: 200px" /> + </td> + </tr> + + <tr> + <td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="backgroundimage" name="backgroundimage" type="text" value="" style="width: 200px" onchange="changedBackgroundImage();" /></td> + <td id="backgroundimagebrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td class="column1"><label for="bgcolor" id="bgcolor_label">{#table_dlg.bgcolor}</label></td> + <td> + <span role="group" aria-labelledby="bgcolor_label"> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');changedColor();" /></td> + <td id="bgcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </span> + </td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <div> + <select id="action" name="action"> + <option value="row">{#table_dlg.row_row}</option> + <option value="odd">{#table_dlg.row_odd}</option> + <option value="even">{#table_dlg.row_even}</option> + <option value="all">{#table_dlg.row_all}</option> + </select> + </div> + + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/table/table.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/table.htm new file mode 100644 index 0000000..09d3700 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/table/table.htm @@ -0,0 +1,188 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#table_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/table.js"></script> + <link href="css/table.css" rel="stylesheet" type="text/css" /> +</head> +<body id="table" style="display: none" role="application" aria-labelledby="app_title"> + <span style="display:none;" id="app_title">{#table_dlg.title}</span> + <form onsubmit="insertTable();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" aria-controls="general_panel" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li> + <li id="advanced_tab" aria-controls="advanced_panel"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#table_dlg.general_props}</legend> + <table role="presentation" border="0" cellpadding="4" cellspacing="0" width="100%"> + <tr> + <td><label id="colslabel" for="cols">{#table_dlg.cols}</label></td> + <td><input id="cols" name="cols" type="text" value="" size="3" maxlength="3" class="required number min1 mceFocus" aria-required="true" /></td> + <td><label id="rowslabel" for="rows">{#table_dlg.rows}</label></td> + <td><input id="rows" name="rows" type="text" value="" size="3" maxlength="3" class="required number min1" aria-required="true" /></td> + </tr> + <tr> + <td><label id="cellpaddinglabel" for="cellpadding">{#table_dlg.cellpadding}</label></td> + <td><input id="cellpadding" name="cellpadding" type="text" value="" size="3" maxlength="3" class="number" /></td> + <td><label id="cellspacinglabel" for="cellspacing">{#table_dlg.cellspacing}</label></td> + <td><input id="cellspacing" name="cellspacing" type="text" value="" size="3" maxlength="3" class="number" /></td> + </tr> + <tr> + <td><label id="alignlabel" for="align">{#table_dlg.align}</label></td> + <td><select id="align" name="align"> + <option value="">{#not_set}</option> + <option value="center">{#table_dlg.align_middle}</option> + <option value="left">{#table_dlg.align_left}</option> + <option value="right">{#table_dlg.align_right}</option> + </select></td> + <td><label id="borderlabel" for="border">{#table_dlg.border}</label></td> + <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="changedBorder();" class="number" /></td> + </tr> + <tr id="width_row"> + <td><label id="widthlabel" for="width">{#table_dlg.width}</label></td> + <td><input name="width" type="text" id="width" value="" size="7" maxlength="7" onchange="changedSize();" class="size" /></td> + <td><label id="heightlabel" for="height">{#table_dlg.height}</label></td> + <td><input name="height" type="text" id="height" value="" size="7" maxlength="7" onchange="changedSize();" class="size" /></td> + </tr> + <tr id="styleSelectRow" > + <td><label id="classlabel" for="class">{#class_name}</label></td> + <td colspan="3" > + <select id="class" name="class" class="mceEditableSelect"> + <option value="" selected="selected">{#not_set}</option> + </select></td> + </tr> + <tr> + <td class="column1" ><label for="caption">{#table_dlg.caption}</label></td> + <td><input id="caption" name="caption" type="checkbox" class="checkbox" value="true" /></td> + </tr> + </table> + </fieldset> + </div> + + <div id="advanced_panel" class="panel"> + <fieldset> + <legend>{#table_dlg.advanced_props}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="column1"><label for="id">{#table_dlg.id}</label></td> + <td><input id="id" name="id" type="text" value="" class="advfield" /></td> + </tr> + + <tr> + <td class="column1"><label for="summary">{#table_dlg.summary}</label></td> + <td><input id="summary" name="summary" type="text" value="" class="advfield" /></td> + </tr> + + <tr> + <td><label for="style">{#table_dlg.style}</label></td> + <td><input type="text" id="style" name="style" value="" class="advfield" onchange="changedStyle();" /></td> + </tr> + + <tr> + <td class="column1"><label id="langlabel" for="lang">{#table_dlg.langcode}</label></td> + <td> + <input id="lang" name="lang" type="text" value="" class="advfield" /> + </td> + </tr> + + <tr> + <td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> + <td> + <table role="presentation" aria-labelledby="backgroundimage_label" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="backgroundimage" name="backgroundimage" type="text" value="" class="advfield" onchange="changedBackgroundImage();" /></td> + <td id="backgroundimagebrowsercontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr> + <td class="column1"><label for="tframe">{#table_dlg.frame}</label></td> + <td> + <select id="tframe" name="tframe" class="advfield"> + <option value="">{#not_set}</option> + <option value="void">{#table_dlg.rules_void}</option> + <option value="above">{#table_dlg.rules_above}</option> + <option value="below">{#table_dlg.rules_below}</option> + <option value="hsides">{#table_dlg.rules_hsides}</option> + <option value="lhs">{#table_dlg.rules_lhs}</option> + <option value="rhs">{#table_dlg.rules_rhs}</option> + <option value="vsides">{#table_dlg.rules_vsides}</option> + <option value="box">{#table_dlg.rules_box}</option> + <option value="border">{#table_dlg.rules_border}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="rules">{#table_dlg.rules}</label></td> + <td> + <select id="rules" name="rules" class="advfield"> + <option value="">{#not_set}</option> + <option value="none">{#table_dlg.frame_none}</option> + <option value="groups">{#table_dlg.frame_groups}</option> + <option value="rows">{#table_dlg.frame_rows}</option> + <option value="cols">{#table_dlg.frame_cols}</option> + <option value="all">{#table_dlg.frame_all}</option> + </select> + </td> + </tr> + + <tr> + <td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> + <td> + <select id="dir" name="dir" class="advfield"> + <option value="">{#not_set}</option> + <option value="ltr">{#table_dlg.ltr}</option> + <option value="rtl">{#table_dlg.rtl}</option> + </select> + </td> + </tr> + + <tr role="group" aria-labelledby="bordercolor_label"> + <td class="column1"><label id="bordercolor_label" for="bordercolor">{#table_dlg.bordercolor}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bordercolor" name="bordercolor" type="text" value="" size="9" onchange="updateColor('bordercolor_pick','bordercolor');changedColor();" /></td> + <td id="bordercolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + + <tr role="group" aria-labelledby="bgcolor_label"> + <td class="column1"><label id="bgcolor_label" for="bgcolor">{#table_dlg.bgcolor}</label></td> + <td> + <table role="presentation" border="0" cellpadding="0" cellspacing="0"> + <tr> + <td><input id="bgcolor" name="bgcolor" type="text" value="" size="9" onchange="updateColor('bgcolor_pick','bgcolor');changedColor();" /></td> + <td id="bgcolor_pickcontainer">&nbsp;</td> + </tr> + </table> + </td> + </tr> + </table> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/template/blank.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/blank.htm new file mode 100644 index 0000000..ecde53f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/blank.htm @@ -0,0 +1,12 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>blank_page</title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <script type="text/javascript"> + parent.TemplateDialog.loadCSSFiles(document); + </script> +</head> +<body id="mceTemplatePreview" class="mceContentBody"> + +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/template/css/template.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/css/template.css new file mode 100644 index 0000000..2d23a49 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/css/template.css @@ -0,0 +1,23 @@ +#frmbody { + padding: 10px; + background-color: #FFF; + border: 1px solid #CCC; +} + +.frmRow { + margin-bottom: 10px; +} + +#templatesrc { + border: none; + width: 320px; + height: 240px; +} + +.title { + padding-bottom: 5px; +} + +.mceActionPanel { + padding-top: 5px; +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/template/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/editor_plugin.js new file mode 100644 index 0000000..ebe3c27 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/editor_plugin.js @@ -0,0 +1 @@ +(function(){var a=tinymce.each;tinymce.create("tinymce.plugins.TemplatePlugin",{init:function(b,c){var d=this;d.editor=b;b.addCommand("mceTemplate",function(e){b.windowManager.open({file:c+"/template.htm",width:b.getParam("template_popup_width",750),height:b.getParam("template_popup_height",600),inline:1},{plugin_url:c})});b.addCommand("mceInsertTemplate",d._insertTemplate,d);b.addButton("template",{title:"template.desc",cmd:"mceTemplate"});b.onPreProcess.add(function(e,g){var f=e.dom;a(f.select("div",g.node),function(h){if(f.hasClass(h,"mceTmpl")){a(f.select("*",h),function(i){if(f.hasClass(i,e.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))){i.innerHTML=d._getDateTime(new Date(),e.getParam("template_mdate_format",e.getLang("template.mdate_format")))}});d._replaceVals(h)}})})},getInfo:function(){return{longname:"Template plugin",author:"Moxiecode Systems AB",authorurl:"http://www.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/template",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_insertTemplate:function(i,j){var k=this,g=k.editor,f,c,d=g.dom,b=g.selection.getContent();f=j.content;a(k.editor.getParam("template_replace_values"),function(l,h){if(typeof(l)!="function"){f=f.replace(new RegExp("\\{\\$"+h+"\\}","g"),l)}});c=d.create("div",null,f);n=d.select(".mceTmpl",c);if(n&&n.length>0){c=d.create("div",null);c.appendChild(n[0].cloneNode(true))}function e(l,h){return new RegExp("\\b"+h+"\\b","g").test(l.className)}a(d.select("*",c),function(h){if(e(h,g.getParam("template_cdate_classes","cdate").replace(/\s+/g,"|"))){h.innerHTML=k._getDateTime(new Date(),g.getParam("template_cdate_format",g.getLang("template.cdate_format")))}if(e(h,g.getParam("template_mdate_classes","mdate").replace(/\s+/g,"|"))){h.innerHTML=k._getDateTime(new Date(),g.getParam("template_mdate_format",g.getLang("template.mdate_format")))}if(e(h,g.getParam("template_selected_content_classes","selcontent").replace(/\s+/g,"|"))){h.innerHTML=b}});k._replaceVals(c);g.execCommand("mceInsertContent",false,c.innerHTML);g.addVisual()},_replaceVals:function(c){var d=this.editor.dom,b=this.editor.getParam("template_replace_values");a(d.select("*",c),function(f){a(b,function(g,e){if(d.hasClass(f,e)){if(typeof(b[e])=="function"){b[e](f)}}})})},_getDateTime:function(e,b){if(!b){return""}function c(g,d){var f;g=""+g;if(g.length<d){for(f=0;f<(d-g.length);f++){g="0"+g}}return g}b=b.replace("%D","%m/%d/%y");b=b.replace("%r","%I:%M:%S %p");b=b.replace("%Y",""+e.getFullYear());b=b.replace("%y",""+e.getYear());b=b.replace("%m",c(e.getMonth()+1,2));b=b.replace("%d",c(e.getDate(),2));b=b.replace("%H",""+c(e.getHours(),2));b=b.replace("%M",""+c(e.getMinutes(),2));b=b.replace("%S",""+c(e.getSeconds(),2));b=b.replace("%I",""+((e.getHours()+11)%12+1));b=b.replace("%p",""+(e.getHours()<12?"AM":"PM"));b=b.replace("%B",""+this.editor.getLang("template_months_long").split(",")[e.getMonth()]);b=b.replace("%b",""+this.editor.getLang("template_months_short").split(",")[e.getMonth()]);b=b.replace("%A",""+this.editor.getLang("template_day_long").split(",")[e.getDay()]);b=b.replace("%a",""+this.editor.getLang("template_day_short").split(",")[e.getDay()]);b=b.replace("%%","%");return b}});tinymce.PluginManager.add("template",tinymce.plugins.TemplatePlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/template/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/editor_plugin_src.js new file mode 100644 index 0000000..9cac269 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/editor_plugin_src.js @@ -0,0 +1,159 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var each = tinymce.each; + + tinymce.create('tinymce.plugins.TemplatePlugin', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceTemplate', function(ui) { + ed.windowManager.open({ + file : url + '/template.htm', + width : ed.getParam('template_popup_width', 750), + height : ed.getParam('template_popup_height', 600), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceInsertTemplate', t._insertTemplate, t); + + // Register buttons + ed.addButton('template', {title : 'template.desc', cmd : 'mceTemplate'}); + + ed.onPreProcess.add(function(ed, o) { + var dom = ed.dom; + + each(dom.select('div', o.node), function(e) { + if (dom.hasClass(e, 'mceTmpl')) { + each(dom.select('*', e), function(e) { + if (dom.hasClass(e, ed.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|'))) + e.innerHTML = t._getDateTime(new Date(), ed.getParam("template_mdate_format", ed.getLang("template.mdate_format"))); + }); + + t._replaceVals(e); + } + }); + }); + }, + + getInfo : function() { + return { + longname : 'Template plugin', + author : 'Moxiecode Systems AB', + authorurl : 'http://www.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/template', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + _insertTemplate : function(ui, v) { + var t = this, ed = t.editor, h, el, dom = ed.dom, sel = ed.selection.getContent(); + + h = v.content; + + each(t.editor.getParam('template_replace_values'), function(v, k) { + if (typeof(v) != 'function') + h = h.replace(new RegExp('\\{\\$' + k + '\\}', 'g'), v); + }); + + el = dom.create('div', null, h); + + // Find template element within div + n = dom.select('.mceTmpl', el); + if (n && n.length > 0) { + el = dom.create('div', null); + el.appendChild(n[0].cloneNode(true)); + } + + function hasClass(n, c) { + return new RegExp('\\b' + c + '\\b', 'g').test(n.className); + }; + + each(dom.select('*', el), function(n) { + // Replace cdate + if (hasClass(n, ed.getParam('template_cdate_classes', 'cdate').replace(/\s+/g, '|'))) + n.innerHTML = t._getDateTime(new Date(), ed.getParam("template_cdate_format", ed.getLang("template.cdate_format"))); + + // Replace mdate + if (hasClass(n, ed.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|'))) + n.innerHTML = t._getDateTime(new Date(), ed.getParam("template_mdate_format", ed.getLang("template.mdate_format"))); + + // Replace selection + if (hasClass(n, ed.getParam('template_selected_content_classes', 'selcontent').replace(/\s+/g, '|'))) + n.innerHTML = sel; + }); + + t._replaceVals(el); + + ed.execCommand('mceInsertContent', false, el.innerHTML); + ed.addVisual(); + }, + + _replaceVals : function(e) { + var dom = this.editor.dom, vl = this.editor.getParam('template_replace_values'); + + each(dom.select('*', e), function(e) { + each(vl, function(v, k) { + if (dom.hasClass(e, k)) { + if (typeof(vl[k]) == 'function') + vl[k](e); + } + }); + }); + }, + + _getDateTime : function(d, fmt) { + if (!fmt) + return ""; + + function addZeros(value, len) { + var i; + + value = "" + value; + + if (value.length < len) { + for (i=0; i<(len-value.length); i++) + value = "0" + value; + } + + return value; + } + + fmt = fmt.replace("%D", "%m/%d/%y"); + fmt = fmt.replace("%r", "%I:%M:%S %p"); + fmt = fmt.replace("%Y", "" + d.getFullYear()); + fmt = fmt.replace("%y", "" + d.getYear()); + fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2)); + fmt = fmt.replace("%d", addZeros(d.getDate(), 2)); + fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2)); + fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2)); + fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2)); + fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1)); + fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM")); + fmt = fmt.replace("%B", "" + this.editor.getLang("template_months_long").split(',')[d.getMonth()]); + fmt = fmt.replace("%b", "" + this.editor.getLang("template_months_short").split(',')[d.getMonth()]); + fmt = fmt.replace("%A", "" + this.editor.getLang("template_day_long").split(',')[d.getDay()]); + fmt = fmt.replace("%a", "" + this.editor.getLang("template_day_short").split(',')[d.getDay()]); + fmt = fmt.replace("%%", "%"); + + return fmt; + } + }); + + // Register plugin + tinymce.PluginManager.add('template', tinymce.plugins.TemplatePlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/template/js/template.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/js/template.js new file mode 100644 index 0000000..bc3045d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/js/template.js @@ -0,0 +1,106 @@ +tinyMCEPopup.requireLangPack(); + +var TemplateDialog = { + preInit : function() { + var url = tinyMCEPopup.getParam("template_external_list_url"); + + if (url != null) + document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></sc'+'ript>'); + }, + + init : function() { + var ed = tinyMCEPopup.editor, tsrc, sel, x, u; + + tsrc = ed.getParam("template_templates", false); + sel = document.getElementById('tpath'); + + // Setup external template list + if (!tsrc && typeof(tinyMCETemplateList) != 'undefined') { + for (x=0, tsrc = []; x<tinyMCETemplateList.length; x++) + tsrc.push({title : tinyMCETemplateList[x][0], src : tinyMCETemplateList[x][1], description : tinyMCETemplateList[x][2]}); + } + + for (x=0; x<tsrc.length; x++) + sel.options[sel.options.length] = new Option(tsrc[x].title, tinyMCEPopup.editor.documentBaseURI.toAbsolute(tsrc[x].src)); + + this.resize(); + this.tsrc = tsrc; + }, + + resize : function() { + var w, h, e; + + if (!self.innerWidth) { + w = document.body.clientWidth - 50; + h = document.body.clientHeight - 160; + } else { + w = self.innerWidth - 50; + h = self.innerHeight - 170; + } + + e = document.getElementById('templatesrc'); + + if (e) { + e.style.height = Math.abs(h) + 'px'; + e.style.width = Math.abs(w - 5) + 'px'; + } + }, + + loadCSSFiles : function(d) { + var ed = tinyMCEPopup.editor; + + tinymce.each(ed.getParam("content_css", '').split(','), function(u) { + d.write('<link href="' + ed.documentBaseURI.toAbsolute(u) + '" rel="stylesheet" type="text/css" />'); + }); + }, + + selectTemplate : function(u, ti) { + var d = window.frames['templatesrc'].document, x, tsrc = this.tsrc; + + if (!u) + return; + + d.body.innerHTML = this.templateHTML = this.getFileContents(u); + + for (x=0; x<tsrc.length; x++) { + if (tsrc[x].title == ti) + document.getElementById('tmpldesc').innerHTML = tsrc[x].description || ''; + } + }, + + insert : function() { + tinyMCEPopup.execCommand('mceInsertTemplate', false, { + content : this.templateHTML, + selection : tinyMCEPopup.editor.selection.getContent() + }); + + tinyMCEPopup.close(); + }, + + getFileContents : function(u) { + var x, d, t = 'text/plain'; + + function g(s) { + x = 0; + + try { + x = new ActiveXObject(s); + } catch (s) { + } + + return x; + }; + + x = window.ActiveXObject ? g('Msxml2.XMLHTTP') || g('Microsoft.XMLHTTP') : new XMLHttpRequest(); + + // Synchronous AJAX load file + x.overrideMimeType && x.overrideMimeType(t); + x.open("GET", u, false); + x.send(null); + + return x.responseText; + } +}; + +TemplateDialog.preInit(); +tinyMCEPopup.onInit.add(TemplateDialog.init, TemplateDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/de_dlg.js new file mode 100644 index 0000000..04c9fa1 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.template_dlg',{title:"Vorlagen",label:"Vorlage","desc_label":"Beschreibung",desc:"Inhalt aus Vorlage einf\u00fcgen",select:"Vorlage ausw\u00e4hlen",preview:"Vorschau",warning:"Warnung: Eine Vorlage mit einer anderen zu aktualisieren kann zu einem Datenverlust f\u00fchren!","mdate_format":"%Y-%m-%d %H:%M:%S","cdate_format":"%Y-%m-%d %H:%M:%S","months_long":"Januar,Februar,M\u00e4rz,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember","months_short":"Jan,Feb,M\u00e4r,Apr,Mai,Juni,Juli,Aug,Sept,Okt,Nov,Dez","day_long":"Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag,Sonntag","day_short":"So,Mo,Di,Mi,Do,Fr,Sa,So"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/en_dlg.js new file mode 100644 index 0000000..83e599d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.template_dlg',{title:"Templates",label:"Template","desc_label":"Description",desc:"Insert Predefined Template Content",select:"Select a Template",preview:"Preview",warning:"Warning: Updating a template with a different one may cause data loss.","mdate_format":"%Y-%m-%d %H:%M:%S","cdate_format":"%Y-%m-%d %H:%M:%S","months_long":"January,February,March,April,May,June,July,August,September,October,November,December","months_short":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","day_long":"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday","day_short":"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/fr_dlg.js new file mode 100644 index 0000000..a9ee124 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.template_dlg',{title:"Mod\u00e8les",label:"Mod\u00e8le","desc_label":"Description",desc:"Ins\u00e9rer un mod\u00e8le pr\u00e9d\u00e9fini",select:"Choisir un mod\u00e8le",preview:"Pr\u00e9visualisation",warning:"Attention : Mettre \u00e0 jour un mod\u00e8le pour un autre peut entra\u00eener une perte de donn\u00e9es !","mdate_format":"%d/%m/%Y %H:%M:%S","cdate_format":"%d/%m/%Y %H:%M:%S","months_long":"Janvier,F\u00e9vrier,Mars,Avril,Mai,Juin,Juillet,Ao\u00fbt,Septembre,Octobre,Novembre,D\u00e9cembre","months_short":"Jan,F\u00e9v,Mar,Avr,Mai,Juin,Juil,Ao\u00fbt,Sep,Oct,Nov,D\u00e9c","day_long":"Dimanche,Lundi,Mardi,Mercredi,Jeudi,Vendredi,Samedi,Dimanche","day_short":"Dim,Lun,Mar,Mer,Jeu,Ven,Sam,Dim"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/it_dlg.js new file mode 100644 index 0000000..78abd1f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.template_dlg',{title:"Modelli",label:"Modello","desc_label":"Descrizione",desc:"Inserisci contenuto da modello predefinito",select:"Seleziona un modello",preview:"Anteprima",warning:"Attenzione: Aggiornare un modello con un altro differente pu\u00f2 causare perdite di dati.","mdate_format":"%Y-%m-%d %H:%M:%S","cdate_format":"%Y-%m-%d %H:%M:%S","months_long":"Gennaio,Febbraio,Marzo,Aprile,Maggio,Giugno,Luglio,Agosto,Settembre,Ottobre,Novembre,Dicembre","months_short":"Gen,Feb,Mar,Apr,Mag,Giu,Lug,Ago,Set,Ott,Nov,Dic","day_long":"Domenica,Luned\u00ec,Marted\u00ec,Mercoled\u00ec,Gioved\u00ec,Venerd\u00ec,Sabato,Domenica","day_short":"Dom,Lun,Mar,Mer,Gio,Ven,Sab,Dom"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/template/template.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/template.htm new file mode 100644 index 0000000..b2182e6 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/template/template.htm @@ -0,0 +1,31 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#template_dlg.title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/template.js"></script> + <link href="css/template.css" rel="stylesheet" type="text/css" /> +</head> +<body onresize="TemplateDialog.resize();"> + <form onsubmit="TemplateDialog.insert();return false;"> + <div id="frmbody"> + <div class="title">{#template_dlg.desc}</div> + <div class="frmRow"><label for="tpath" title="{#template_dlg.select}">{#template_dlg.label}:</label> + <select id="tpath" name="tpath" onchange="TemplateDialog.selectTemplate(this.options[this.selectedIndex].value, this.options[this.selectedIndex].text);" class="mceFocus"> + <option value="">{#template_dlg.select}...</option> + </select> + <span id="warning"></span></div> + <div class="frmRow"><label for="tdesc">{#template_dlg.desc_label}:</label> + <span id="tmpldesc"></span></div> + <fieldset> + <legend>{#template_dlg.preview}</legend> + <iframe id="templatesrc" name="templatesrc" src="blank.htm" width="690" height="400" frameborder="0"></iframe> + </fieldset> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> + </form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/visualchars/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/visualchars/editor_plugin.js new file mode 100644 index 0000000..1a148e8 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/visualchars/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.VisualChars",{init:function(a,b){var c=this;c.editor=a;a.addCommand("mceVisualChars",c._toggleVisualChars,c);a.addButton("visualchars",{title:"visualchars.desc",cmd:"mceVisualChars"});a.onBeforeGetContent.add(function(d,e){if(c.state&&e.format!="raw"&&!e.draft){c.state=true;c._toggleVisualChars(false)}})},getInfo:function(){return{longname:"Visual characters",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/visualchars",version:tinymce.majorVersion+"."+tinymce.minorVersion}},_toggleVisualChars:function(m){var p=this,k=p.editor,a,g,j,n=k.getDoc(),o=k.getBody(),l,q=k.selection,e,c,f;p.state=!p.state;k.controlManager.setActive("visualchars",p.state);if(m){f=q.getBookmark()}if(p.state){a=[];tinymce.walk(o,function(b){if(b.nodeType==3&&b.nodeValue&&b.nodeValue.indexOf("\u00a0")!=-1){a.push(b)}},"childNodes");for(g=0;g<a.length;g++){l=a[g].nodeValue;l=l.replace(/(\u00a0)/g,'<span data-mce-bogus="1" class="mceItemHidden mceItemNbsp">$1</span>');c=k.dom.create("div",null,l);while(node=c.lastChild){k.dom.insertAfter(node,a[g])}k.dom.remove(a[g])}}else{a=k.dom.select("span.mceItemNbsp",o);for(g=a.length-1;g>=0;g--){k.dom.remove(a[g],1)}}q.moveToBookmark(f)}});tinymce.PluginManager.add("visualchars",tinymce.plugins.VisualChars)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/visualchars/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/visualchars/editor_plugin_src.js new file mode 100644 index 0000000..df98590 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/visualchars/editor_plugin_src.js @@ -0,0 +1,83 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.VisualChars', { + init : function(ed, url) { + var t = this; + + t.editor = ed; + + // Register commands + ed.addCommand('mceVisualChars', t._toggleVisualChars, t); + + // Register buttons + ed.addButton('visualchars', {title : 'visualchars.desc', cmd : 'mceVisualChars'}); + + ed.onBeforeGetContent.add(function(ed, o) { + if (t.state && o.format != 'raw' && !o.draft) { + t.state = true; + t._toggleVisualChars(false); + } + }); + }, + + getInfo : function() { + return { + longname : 'Visual characters', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/visualchars', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + }, + + // Private methods + + _toggleVisualChars : function(bookmark) { + var t = this, ed = t.editor, nl, i, h, d = ed.getDoc(), b = ed.getBody(), nv, s = ed.selection, bo, div, bm; + + t.state = !t.state; + ed.controlManager.setActive('visualchars', t.state); + + if (bookmark) + bm = s.getBookmark(); + + if (t.state) { + nl = []; + tinymce.walk(b, function(n) { + if (n.nodeType == 3 && n.nodeValue && n.nodeValue.indexOf('\u00a0') != -1) + nl.push(n); + }, 'childNodes'); + + for (i = 0; i < nl.length; i++) { + nv = nl[i].nodeValue; + nv = nv.replace(/(\u00a0)/g, '<span data-mce-bogus="1" class="mceItemHidden mceItemNbsp">$1</span>'); + + div = ed.dom.create('div', null, nv); + while (node = div.lastChild) + ed.dom.insertAfter(node, nl[i]); + + ed.dom.remove(nl[i]); + } + } else { + nl = ed.dom.select('span.mceItemNbsp', b); + + for (i = nl.length - 1; i >= 0; i--) + ed.dom.remove(nl[i], 1); + } + + s.moveToBookmark(bm); + } + }); + + // Register plugin + tinymce.PluginManager.add('visualchars', tinymce.plugins.VisualChars); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/wordcount/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/wordcount/editor_plugin.js new file mode 100644 index 0000000..a752ad3 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/wordcount/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.WordCount",{block:0,id:null,countre:null,cleanre:null,init:function(a,b){var c=this,d=0;c.countre=a.getParam("wordcount_countregex",/[\w\u2019\'-]+/g);c.cleanre=a.getParam("wordcount_cleanregex",/[0-9.(),;:!?%#$?\'\"_+=\\\/-]*/g);c.id=a.id+"-word-count";a.onPostRender.add(function(f,e){var g,h;h=f.getParam("wordcount_target_id");if(!h){g=tinymce.DOM.get(f.id+"_path_row");if(g){tinymce.DOM.add(g.parentNode,"div",{style:"float: right"},f.getLang("wordcount.words","Words: ")+'<span id="'+c.id+'">0</span>')}}else{tinymce.DOM.add(h,"span",{},'<span id="'+c.id+'">0</span>')}});a.onInit.add(function(e){e.selection.onSetContent.add(function(){c._count(e)});c._count(e)});a.onSetContent.add(function(e){c._count(e)});a.onKeyUp.add(function(f,g){if(g.keyCode==d){return}if(13==g.keyCode||8==d||46==d){c._count(f)}d=g.keyCode})},_getCount:function(c){var a=0;var b=c.getContent({format:"raw"});if(b){b=b.replace(/\.\.\./g," ");b=b.replace(/<.[^<>]*?>/g," ").replace(/&nbsp;|&#160;/gi," ");b=b.replace(/(\w+)(&.+?;)+(\w+)/,"$1$3").replace(/&.+?;/g," ");b=b.replace(this.cleanre,"");var d=b.match(this.countre);if(d){a=d.length}}return a},_count:function(a){var b=this;if(b.block){return}b.block=1;setTimeout(function(){if(!a.destroyed){var c=b._getCount(a);tinymce.DOM.setHTML(b.id,c.toString());setTimeout(function(){b.block=0},2000)}},1)},getInfo:function(){return{longname:"Word Count plugin",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/wordcount",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("wordcount",tinymce.plugins.WordCount)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/wordcount/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/wordcount/editor_plugin_src.js new file mode 100644 index 0000000..e94743b --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/wordcount/editor_plugin_src.js @@ -0,0 +1,114 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.WordCount', { + block : 0, + id : null, + countre : null, + cleanre : null, + + init : function(ed, url) { + var t = this, last = 0; + + t.countre = ed.getParam('wordcount_countregex', /[\w\u2019\'-]+/g); // u2019 == &rsquo; + t.cleanre = ed.getParam('wordcount_cleanregex', /[0-9.(),;:!?%#$?\'\"_+=\\\/-]*/g); + t.id = ed.id + '-word-count'; + + ed.onPostRender.add(function(ed, cm) { + var row, id; + + // Add it to the specified id or the theme advanced path + id = ed.getParam('wordcount_target_id'); + if (!id) { + row = tinymce.DOM.get(ed.id + '_path_row'); + + if (row) + tinymce.DOM.add(row.parentNode, 'div', {'style': 'float: right'}, ed.getLang('wordcount.words', 'Words: ') + '<span id="' + t.id + '">0</span>'); + } else { + tinymce.DOM.add(id, 'span', {}, '<span id="' + t.id + '">0</span>'); + } + }); + + ed.onInit.add(function(ed) { + ed.selection.onSetContent.add(function() { + t._count(ed); + }); + + t._count(ed); + }); + + ed.onSetContent.add(function(ed) { + t._count(ed); + }); + + ed.onKeyUp.add(function(ed, e) { + if (e.keyCode == last) + return; + + if (13 == e.keyCode || 8 == last || 46 == last) + t._count(ed); + + last = e.keyCode; + }); + }, + + _getCount : function(ed) { + var tc = 0; + var tx = ed.getContent({ format: 'raw' }); + + if (tx) { + tx = tx.replace(/\.\.\./g, ' '); // convert ellipses to spaces + tx = tx.replace(/<.[^<>]*?>/g, ' ').replace(/&nbsp;|&#160;/gi, ' '); // remove html tags and space chars + + // deal with html entities + tx = tx.replace(/(\w+)(&.+?;)+(\w+)/, "$1$3").replace(/&.+?;/g, ' '); + tx = tx.replace(this.cleanre, ''); // remove numbers and punctuation + + var wordArray = tx.match(this.countre); + if (wordArray) { + tc = wordArray.length; + } + } + + return tc; + }, + + _count : function(ed) { + var t = this; + + // Keep multiple calls from happening at the same time + if (t.block) + return; + + t.block = 1; + + setTimeout(function() { + if (!ed.destroyed) { + var tc = t._getCount(ed); + tinymce.DOM.setHTML(t.id, tc.toString()); + setTimeout(function() {t.block = 0;}, 2000); + } + }, 1); + }, + + getInfo: function() { + return { + longname : 'Word Count plugin', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/wordcount', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + tinymce.PluginManager.add('wordcount', tinymce.plugins.WordCount); +})(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/abbr.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/abbr.htm new file mode 100644 index 0000000..30a894f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/abbr.htm @@ -0,0 +1,142 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.title_abbr_element}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/element_common.js"></script> + <script type="text/javascript" src="js/abbr.js"></script> + <link rel="stylesheet" type="text/css" href="css/popup.css" /> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_abbr_element}</span> +<form onsubmit="insertAbbr();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li> + <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> --> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> + <td> + <select id="class" name="class" class="field mceEditableSelect"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir" class="field"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" class="field" /> + </td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeAbbr();" style="display: none;" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/acronym.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/acronym.htm new file mode 100644 index 0000000..c109345 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/acronym.htm @@ -0,0 +1,142 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.title_acronym_element}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/element_common.js"></script> + <script type="text/javascript" src="js/acronym.js"></script> + <link rel="stylesheet" type="text/css" href="css/popup.css" /> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_acronym_element}</span> +<form onsubmit="insertAcronym();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li> + <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> --> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> + <td> + <select id="class" name="class" class="field mceEditableSelect"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir" class="field"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" class="field" /> + </td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeAcronym();" style="display: none;" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/attributes.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/attributes.htm new file mode 100644 index 0000000..e8d606a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/attributes.htm @@ -0,0 +1,149 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.attribs_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="js/attributes.js"></script> + <link rel="stylesheet" type="text/css" href="css/attributes.css" /> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.attribs_title}</span> +<form onsubmit="insertAction();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.attribute_attrib_tab}</a></span></li> + <li id="events_tab" aria-controls="events_panel"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.attribute_events_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.attribute_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="mceFocus" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" /></td> + </tr> + <tr> + <td><label id="classlabel" for="classlist">{#class_name}</label></td> + <td> + <select id="classlist" name="classlist" class="mceEditableSelect"> + <option value="" selected="selected">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" /> + </td> + </tr> + <tr> + <td><label id="tabindexlabel" for="tabindex">{#xhtmlxtras_dlg.attribute_label_tabindex}</label></td> + <td><input type="text" id="tabindex" name="tabindex" value="" /></td> + </tr> + + <tr> + <td><label id="accesskeylabel" for="accesskey">{#xhtmlxtras_dlg.attribute_label_accesskey}</label></td> + <td><input type="text" id="accesskey" name="accesskey" value="" /></td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.attribute_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/cite.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/cite.htm new file mode 100644 index 0000000..0ac6bdb --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/cite.htm @@ -0,0 +1,142 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.title_cite_element}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/element_common.js"></script> + <script type="text/javascript" src="js/cite.js"></script> + <link rel="stylesheet" type="text/css" href="css/popup.css" /> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_cite_element}</span> +<form onsubmit="insertCite();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li> + <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> --> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="field mceFocus" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> + <td> + <select id="class" name="class" class="field mceEditableSelect"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir" class="field"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" class="field" /> + </td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeCite();" style="display: none;" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/css/attributes.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/css/attributes.css new file mode 100644 index 0000000..9a6a235 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/css/attributes.css @@ -0,0 +1,11 @@ +.panel_wrapper div.current { + height: 290px; +} + +#id, #style, #title, #dir, #hreflang, #lang, #classlist, #tabindex, #accesskey { + width: 200px; +} + +#events_panel input { + width: 200px; +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/css/popup.css b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/css/popup.css new file mode 100644 index 0000000..e67114d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/css/popup.css @@ -0,0 +1,9 @@ +input.field, select.field {width:200px;} +input.picker {width:179px; margin-left: 5px;} +input.disabled {border-color:#F2F2F2;} +img.picker {vertical-align:text-bottom; cursor:pointer;} +h1 {padding: 0 0 5px 0;} +.panel_wrapper div.current {height:160px;} +#xhtmlxtrasdel .panel_wrapper div.current, #xhtmlxtrasins .panel_wrapper div.current {height: 230px;} +a.browse span {display:block; width:20px; height:20px; background:url('../../../themes/advanced/img/icons.gif') -140px -20px;} +#datetime {width:180px;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/del.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/del.htm new file mode 100644 index 0000000..5f66751 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/del.htm @@ -0,0 +1,162 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.title_del_element}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/element_common.js"></script> + <script type="text/javascript" src="js/del.js"></script> + <link rel="stylesheet" type="text/css" href="css/popup.css" /> +</head> +<body id="xhtmlxtrasins" style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_del_element}</span> +<form onsubmit="insertDel();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li> + <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> --> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_general_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="datetimelabel" for="datetime">{#xhtmlxtras_dlg.attribute_label_datetime}</label>:</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="datetime" name="datetime" type="text" value="" maxlength="19" class="field mceFocus" /></td> + <td><a href="javascript:insertDateTime('datetime');" onmousedown="return false;" class="browse" role="button" aria-labelledby="datetimelabel"><span class="datetime" title="{#xhtmlxtras_dlg.insert_date}"></span></a></td> + </tr> + </table> + </td> + </tr> + <tr> + <td class="label"><label id="citelabel" for="cite">{#xhtmlxtras_dlg.attribute_label_cite}</label>:</td> + <td><input id="cite" name="cite" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> + <td> + <select id="class" name="class" class="field mceEditableSelect"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir" class="field"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" class="field" /> + </td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeDel();" style="display: none;" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/editor_plugin.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/editor_plugin.js new file mode 100644 index 0000000..9b98a51 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/editor_plugin.js @@ -0,0 +1 @@ +(function(){tinymce.create("tinymce.plugins.XHTMLXtrasPlugin",{init:function(a,b){a.addCommand("mceCite",function(){a.windowManager.open({file:b+"/cite.htm",width:350+parseInt(a.getLang("xhtmlxtras.cite_delta_width",0)),height:250+parseInt(a.getLang("xhtmlxtras.cite_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceAcronym",function(){a.windowManager.open({file:b+"/acronym.htm",width:350+parseInt(a.getLang("xhtmlxtras.acronym_delta_width",0)),height:250+parseInt(a.getLang("xhtmlxtras.acronym_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceAbbr",function(){a.windowManager.open({file:b+"/abbr.htm",width:350+parseInt(a.getLang("xhtmlxtras.abbr_delta_width",0)),height:250+parseInt(a.getLang("xhtmlxtras.abbr_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceDel",function(){a.windowManager.open({file:b+"/del.htm",width:340+parseInt(a.getLang("xhtmlxtras.del_delta_width",0)),height:310+parseInt(a.getLang("xhtmlxtras.del_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceIns",function(){a.windowManager.open({file:b+"/ins.htm",width:340+parseInt(a.getLang("xhtmlxtras.ins_delta_width",0)),height:310+parseInt(a.getLang("xhtmlxtras.ins_delta_height",0)),inline:1},{plugin_url:b})});a.addCommand("mceAttributes",function(){a.windowManager.open({file:b+"/attributes.htm",width:380+parseInt(a.getLang("xhtmlxtras.attr_delta_width",0)),height:370+parseInt(a.getLang("xhtmlxtras.attr_delta_height",0)),inline:1},{plugin_url:b})});a.addButton("cite",{title:"xhtmlxtras.cite_desc",cmd:"mceCite"});a.addButton("acronym",{title:"xhtmlxtras.acronym_desc",cmd:"mceAcronym"});a.addButton("abbr",{title:"xhtmlxtras.abbr_desc",cmd:"mceAbbr"});a.addButton("del",{title:"xhtmlxtras.del_desc",cmd:"mceDel"});a.addButton("ins",{title:"xhtmlxtras.ins_desc",cmd:"mceIns"});a.addButton("attribs",{title:"xhtmlxtras.attribs_desc",cmd:"mceAttributes"});a.onNodeChange.add(function(d,c,f,e){f=d.dom.getParent(f,"CITE,ACRONYM,ABBR,DEL,INS");c.setDisabled("cite",e);c.setDisabled("acronym",e);c.setDisabled("abbr",e);c.setDisabled("del",e);c.setDisabled("ins",e);c.setDisabled("attribs",f&&f.nodeName=="BODY");c.setActive("cite",0);c.setActive("acronym",0);c.setActive("abbr",0);c.setActive("del",0);c.setActive("ins",0);if(f){do{c.setDisabled(f.nodeName.toLowerCase(),0);c.setActive(f.nodeName.toLowerCase(),1)}while(f=f.parentNode)}});a.onPreInit.add(function(){a.dom.create("abbr")})},getInfo:function(){return{longname:"XHTML Xtras Plugin",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.PluginManager.add("xhtmlxtras",tinymce.plugins.XHTMLXtrasPlugin)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js new file mode 100644 index 0000000..f240572 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/editor_plugin_src.js @@ -0,0 +1,132 @@ +/** + * editor_plugin_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + tinymce.create('tinymce.plugins.XHTMLXtrasPlugin', { + init : function(ed, url) { + // Register commands + ed.addCommand('mceCite', function() { + ed.windowManager.open({ + file : url + '/cite.htm', + width : 350 + parseInt(ed.getLang('xhtmlxtras.cite_delta_width', 0)), + height : 250 + parseInt(ed.getLang('xhtmlxtras.cite_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceAcronym', function() { + ed.windowManager.open({ + file : url + '/acronym.htm', + width : 350 + parseInt(ed.getLang('xhtmlxtras.acronym_delta_width', 0)), + height : 250 + parseInt(ed.getLang('xhtmlxtras.acronym_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceAbbr', function() { + ed.windowManager.open({ + file : url + '/abbr.htm', + width : 350 + parseInt(ed.getLang('xhtmlxtras.abbr_delta_width', 0)), + height : 250 + parseInt(ed.getLang('xhtmlxtras.abbr_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceDel', function() { + ed.windowManager.open({ + file : url + '/del.htm', + width : 340 + parseInt(ed.getLang('xhtmlxtras.del_delta_width', 0)), + height : 310 + parseInt(ed.getLang('xhtmlxtras.del_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceIns', function() { + ed.windowManager.open({ + file : url + '/ins.htm', + width : 340 + parseInt(ed.getLang('xhtmlxtras.ins_delta_width', 0)), + height : 310 + parseInt(ed.getLang('xhtmlxtras.ins_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + ed.addCommand('mceAttributes', function() { + ed.windowManager.open({ + file : url + '/attributes.htm', + width : 380 + parseInt(ed.getLang('xhtmlxtras.attr_delta_width', 0)), + height : 370 + parseInt(ed.getLang('xhtmlxtras.attr_delta_height', 0)), + inline : 1 + }, { + plugin_url : url + }); + }); + + // Register buttons + ed.addButton('cite', {title : 'xhtmlxtras.cite_desc', cmd : 'mceCite'}); + ed.addButton('acronym', {title : 'xhtmlxtras.acronym_desc', cmd : 'mceAcronym'}); + ed.addButton('abbr', {title : 'xhtmlxtras.abbr_desc', cmd : 'mceAbbr'}); + ed.addButton('del', {title : 'xhtmlxtras.del_desc', cmd : 'mceDel'}); + ed.addButton('ins', {title : 'xhtmlxtras.ins_desc', cmd : 'mceIns'}); + ed.addButton('attribs', {title : 'xhtmlxtras.attribs_desc', cmd : 'mceAttributes'}); + + ed.onNodeChange.add(function(ed, cm, n, co) { + n = ed.dom.getParent(n, 'CITE,ACRONYM,ABBR,DEL,INS'); + + cm.setDisabled('cite', co); + cm.setDisabled('acronym', co); + cm.setDisabled('abbr', co); + cm.setDisabled('del', co); + cm.setDisabled('ins', co); + cm.setDisabled('attribs', n && n.nodeName == 'BODY'); + cm.setActive('cite', 0); + cm.setActive('acronym', 0); + cm.setActive('abbr', 0); + cm.setActive('del', 0); + cm.setActive('ins', 0); + + // Activate all + if (n) { + do { + cm.setDisabled(n.nodeName.toLowerCase(), 0); + cm.setActive(n.nodeName.toLowerCase(), 1); + } while (n = n.parentNode); + } + }); + + ed.onPreInit.add(function() { + // Fixed IE issue where it can't handle these elements correctly + ed.dom.create('abbr'); + }); + }, + + getInfo : function() { + return { + longname : 'XHTML Xtras Plugin', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras', + version : tinymce.majorVersion + "." + tinymce.minorVersion + }; + } + }); + + // Register plugin + tinymce.PluginManager.add('xhtmlxtras', tinymce.plugins.XHTMLXtrasPlugin); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/ins.htm b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/ins.htm new file mode 100644 index 0000000..d001ac7 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/ins.htm @@ -0,0 +1,162 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#xhtmlxtras_dlg.title_ins_element}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/editable_selects.js"></script> + <script type="text/javascript" src="js/element_common.js"></script> + <script type="text/javascript" src="js/ins.js"></script> + <link rel="stylesheet" type="text/css" href="css/popup.css" /> +</head> +<body id="xhtmlxtrasins" style="display: none" role="application" aria-labelledby="app_title"> +<span style="display:none;" id="app_title">{#xhtmlxtras_dlg.title_ins_element}</span> +<form onsubmit="insertIns();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li> + <!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> --> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_general_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="datetimelabel" for="datetime">{#xhtmlxtras_dlg.attribute_label_datetime}</label>:</td> + <td> + <table role="presentation" border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="datetime" name="datetime" type="text" value="" maxlength="19" class="field mceFocus" /></td> + <td ><a href="javascript:insertDateTime('datetime');" onmousedown="return false;" class="browse" role="button" aria-labelledby="datetimelabel"><span class="datetime" title="{#xhtmlxtras_dlg.insert_date}"></span></a></td> + </tr> + </table> + </td> + </tr> + <tr > + <td class="label"><label id="citelabel" for="cite">{#xhtmlxtras_dlg.attribute_label_cite}</label>:</td> + <td><input id="cite" name="cite" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend> + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> + <td><input id="title" name="title" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> + <td><input id="id" name="id" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> + <td> + <select id="class" name="class" class="field mceEditableSelect"> + <option value="">{#not_set}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="stylelabel" for="style">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> + <td><input id="style" name="style" type="text" value="" class="field" /></td> + </tr> + <tr> + <td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> + <td> + <select id="dir" name="dir" class="field"> + <option value="">{#not_set}</option> + <option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> + <option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> + </select> + </td> + </tr> + <tr> + <td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> + <td> + <input id="lang" name="lang" type="text" value="" class="field" /> + </td> + </tr> + </table> + </fieldset> + </div> + <div id="events_panel" class="panel"> + <fieldset> + <legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend> + + <table role="presentation" border="0" cellpadding="0" cellspacing="4"> + <tr> + <td class="label"><label for="onfocus">onfocus</label>:</td> + <td><input id="onfocus" name="onfocus" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onblur">onblur</label>:</td> + <td><input id="onblur" name="onblur" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onclick">onclick</label>:</td> + <td><input id="onclick" name="onclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="ondblclick">ondblclick</label>:</td> + <td><input id="ondblclick" name="ondblclick" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousedown">onmousedown</label>:</td> + <td><input id="onmousedown" name="onmousedown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseup">onmouseup</label>:</td> + <td><input id="onmouseup" name="onmouseup" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseover">onmouseover</label>:</td> + <td><input id="onmouseover" name="onmouseover" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmousemove">onmousemove</label>:</td> + <td><input id="onmousemove" name="onmousemove" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onmouseout">onmouseout</label>:</td> + <td><input id="onmouseout" name="onmouseout" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeypress">onkeypress</label>:</td> + <td><input id="onkeypress" name="onkeypress" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeydown">onkeydown</label>:</td> + <td><input id="onkeydown" name="onkeydown" type="text" value="" class="field" /></td> + </tr> + + <tr> + <td class="label"><label for="onkeyup">onkeyup</label>:</td> + <td><input id="onkeyup" name="onkeyup" type="text" value="" class="field" /></td> + </tr> + </table> + </fieldset> + </div> + </div> + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeIns();" style="display: none;" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/abbr.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/abbr.js new file mode 100644 index 0000000..4b51a25 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/abbr.js @@ -0,0 +1,28 @@ +/** + * abbr.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + SXE.initElementDialog('abbr'); + if (SXE.currentAction == "update") { + SXE.showRemoveButton(); + } +} + +function insertAbbr() { + SXE.insertElement('abbr'); + tinyMCEPopup.close(); +} + +function removeAbbr() { + SXE.removeElement('abbr'); + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/acronym.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/acronym.js new file mode 100644 index 0000000..6ec2f88 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/acronym.js @@ -0,0 +1,28 @@ +/** + * acronym.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + SXE.initElementDialog('acronym'); + if (SXE.currentAction == "update") { + SXE.showRemoveButton(); + } +} + +function insertAcronym() { + SXE.insertElement('acronym'); + tinyMCEPopup.close(); +} + +function removeAcronym() { + SXE.removeElement('acronym'); + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/attributes.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/attributes.js new file mode 100644 index 0000000..9c99995 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/attributes.js @@ -0,0 +1,111 @@ +/** + * attributes.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + tinyMCEPopup.resizeToInnerSize(); + var inst = tinyMCEPopup.editor; + var dom = inst.dom; + var elm = inst.selection.getNode(); + var f = document.forms[0]; + var onclick = dom.getAttrib(elm, 'onclick'); + + setFormValue('title', dom.getAttrib(elm, 'title')); + setFormValue('id', dom.getAttrib(elm, 'id')); + setFormValue('style', dom.getAttrib(elm, "style")); + setFormValue('dir', dom.getAttrib(elm, 'dir')); + setFormValue('lang', dom.getAttrib(elm, 'lang')); + setFormValue('tabindex', dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : "")); + setFormValue('accesskey', dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : "")); + setFormValue('onfocus', dom.getAttrib(elm, 'onfocus')); + setFormValue('onblur', dom.getAttrib(elm, 'onblur')); + setFormValue('onclick', onclick); + setFormValue('ondblclick', dom.getAttrib(elm, 'ondblclick')); + setFormValue('onmousedown', dom.getAttrib(elm, 'onmousedown')); + setFormValue('onmouseup', dom.getAttrib(elm, 'onmouseup')); + setFormValue('onmouseover', dom.getAttrib(elm, 'onmouseover')); + setFormValue('onmousemove', dom.getAttrib(elm, 'onmousemove')); + setFormValue('onmouseout', dom.getAttrib(elm, 'onmouseout')); + setFormValue('onkeypress', dom.getAttrib(elm, 'onkeypress')); + setFormValue('onkeydown', dom.getAttrib(elm, 'onkeydown')); + setFormValue('onkeyup', dom.getAttrib(elm, 'onkeyup')); + className = dom.getAttrib(elm, 'class'); + + addClassesToList('classlist', 'advlink_styles'); + selectByValue(f, 'classlist', className, true); + + TinyMCE_EditableSelects.init(); +} + +function setFormValue(name, value) { + if(value && document.forms[0].elements[name]){ + document.forms[0].elements[name].value = value; + } +} + +function insertAction() { + var inst = tinyMCEPopup.editor; + var elm = inst.selection.getNode(); + + setAllAttribs(elm); + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); +} + +function setAttrib(elm, attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib.toLowerCase()]; + var inst = tinyMCEPopup.editor; + var dom = inst.dom; + + if (typeof(value) == "undefined" || value == null) { + value = ""; + + if (valueElm) + value = valueElm.value; + } + + dom.setAttrib(elm, attrib.toLowerCase(), value); +} + +function setAllAttribs(elm) { + var f = document.forms[0]; + + setAttrib(elm, 'title'); + setAttrib(elm, 'id'); + setAttrib(elm, 'style'); + setAttrib(elm, 'class', getSelectValue(f, 'classlist')); + setAttrib(elm, 'dir'); + setAttrib(elm, 'lang'); + setAttrib(elm, 'tabindex'); + setAttrib(elm, 'accesskey'); + setAttrib(elm, 'onfocus'); + setAttrib(elm, 'onblur'); + setAttrib(elm, 'onclick'); + setAttrib(elm, 'ondblclick'); + setAttrib(elm, 'onmousedown'); + setAttrib(elm, 'onmouseup'); + setAttrib(elm, 'onmouseover'); + setAttrib(elm, 'onmousemove'); + setAttrib(elm, 'onmouseout'); + setAttrib(elm, 'onkeypress'); + setAttrib(elm, 'onkeydown'); + setAttrib(elm, 'onkeyup'); + + // Refresh in old MSIE +// if (tinyMCE.isMSIE5) +// elm.outerHTML = elm.outerHTML; +} + +function insertAttribute() { + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); +tinyMCEPopup.requireLangPack(); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/cite.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/cite.js new file mode 100644 index 0000000..009b715 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/cite.js @@ -0,0 +1,28 @@ +/** + * cite.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + SXE.initElementDialog('cite'); + if (SXE.currentAction == "update") { + SXE.showRemoveButton(); + } +} + +function insertCite() { + SXE.insertElement('cite'); + tinyMCEPopup.close(); +} + +function removeCite() { + SXE.removeElement('cite'); + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/del.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/del.js new file mode 100644 index 0000000..1f957dc --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/del.js @@ -0,0 +1,53 @@ +/** + * del.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + SXE.initElementDialog('del'); + if (SXE.currentAction == "update") { + setFormValue('datetime', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'datetime')); + setFormValue('cite', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'cite')); + SXE.showRemoveButton(); + } +} + +function setElementAttribs(elm) { + setAllCommonAttribs(elm); + setAttrib(elm, 'datetime'); + setAttrib(elm, 'cite'); + elm.removeAttribute('data-mce-new'); +} + +function insertDel() { + var elm = tinyMCEPopup.editor.dom.getParent(SXE.focusElement, 'DEL'); + + if (elm == null) { + var s = SXE.inst.selection.getContent(); + if(s.length > 0) { + insertInlineElement('del'); + var elementArray = SXE.inst.dom.select('del[data-mce-new]'); + for (var i=0; i<elementArray.length; i++) { + var elm = elementArray[i]; + setElementAttribs(elm); + } + } + } else { + setElementAttribs(elm); + } + tinyMCEPopup.editor.nodeChanged(); + tinyMCEPopup.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); +} + +function removeDel() { + SXE.removeElement('del'); + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/element_common.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/element_common.js new file mode 100644 index 0000000..4e5d9c3 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/element_common.js @@ -0,0 +1,229 @@ +/** + * element_common.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +tinyMCEPopup.requireLangPack(); + +function initCommonAttributes(elm) { + var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom; + + // Setup form data for common element attributes + setFormValue('title', dom.getAttrib(elm, 'title')); + setFormValue('id', dom.getAttrib(elm, 'id')); + selectByValue(formObj, 'class', dom.getAttrib(elm, 'class'), true); + setFormValue('style', dom.getAttrib(elm, 'style')); + selectByValue(formObj, 'dir', dom.getAttrib(elm, 'dir')); + setFormValue('lang', dom.getAttrib(elm, 'lang')); + setFormValue('onfocus', dom.getAttrib(elm, 'onfocus')); + setFormValue('onblur', dom.getAttrib(elm, 'onblur')); + setFormValue('onclick', dom.getAttrib(elm, 'onclick')); + setFormValue('ondblclick', dom.getAttrib(elm, 'ondblclick')); + setFormValue('onmousedown', dom.getAttrib(elm, 'onmousedown')); + setFormValue('onmouseup', dom.getAttrib(elm, 'onmouseup')); + setFormValue('onmouseover', dom.getAttrib(elm, 'onmouseover')); + setFormValue('onmousemove', dom.getAttrib(elm, 'onmousemove')); + setFormValue('onmouseout', dom.getAttrib(elm, 'onmouseout')); + setFormValue('onkeypress', dom.getAttrib(elm, 'onkeypress')); + setFormValue('onkeydown', dom.getAttrib(elm, 'onkeydown')); + setFormValue('onkeyup', dom.getAttrib(elm, 'onkeyup')); +} + +function setFormValue(name, value) { + if(document.forms[0].elements[name]) document.forms[0].elements[name].value = value; +} + +function insertDateTime(id) { + document.getElementById(id).value = getDateTime(new Date(), "%Y-%m-%dT%H:%M:%S"); +} + +function getDateTime(d, fmt) { + fmt = fmt.replace("%D", "%m/%d/%y"); + fmt = fmt.replace("%r", "%I:%M:%S %p"); + fmt = fmt.replace("%Y", "" + d.getFullYear()); + fmt = fmt.replace("%y", "" + d.getYear()); + fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2)); + fmt = fmt.replace("%d", addZeros(d.getDate(), 2)); + fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2)); + fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2)); + fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2)); + fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1)); + fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM")); + fmt = fmt.replace("%%", "%"); + + return fmt; +} + +function addZeros(value, len) { + var i; + + value = "" + value; + + if (value.length < len) { + for (i=0; i<(len-value.length); i++) + value = "0" + value; + } + + return value; +} + +function selectByValue(form_obj, field_name, value, add_custom, ignore_case) { + if (!form_obj || !form_obj.elements[field_name]) + return; + + var sel = form_obj.elements[field_name]; + + var found = false; + for (var i=0; i<sel.options.length; i++) { + var option = sel.options[i]; + + if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) { + option.selected = true; + found = true; + } else + option.selected = false; + } + + if (!found && add_custom && value != '') { + var option = new Option('Value: ' + value, value); + option.selected = true; + sel.options[sel.options.length] = option; + } + + return found; +} + +function setAttrib(elm, attrib, value) { + var formObj = document.forms[0]; + var valueElm = formObj.elements[attrib.toLowerCase()]; + tinyMCEPopup.editor.dom.setAttrib(elm, attrib, value || valueElm.value); +} + +function setAllCommonAttribs(elm) { + setAttrib(elm, 'title'); + setAttrib(elm, 'id'); + setAttrib(elm, 'class'); + setAttrib(elm, 'style'); + setAttrib(elm, 'dir'); + setAttrib(elm, 'lang'); + /*setAttrib(elm, 'onfocus'); + setAttrib(elm, 'onblur'); + setAttrib(elm, 'onclick'); + setAttrib(elm, 'ondblclick'); + setAttrib(elm, 'onmousedown'); + setAttrib(elm, 'onmouseup'); + setAttrib(elm, 'onmouseover'); + setAttrib(elm, 'onmousemove'); + setAttrib(elm, 'onmouseout'); + setAttrib(elm, 'onkeypress'); + setAttrib(elm, 'onkeydown'); + setAttrib(elm, 'onkeyup');*/ +} + +SXE = { + currentAction : "insert", + inst : tinyMCEPopup.editor, + updateElement : null +} + +SXE.focusElement = SXE.inst.selection.getNode(); + +SXE.initElementDialog = function(element_name) { + addClassesToList('class', 'xhtmlxtras_styles'); + TinyMCE_EditableSelects.init(); + + element_name = element_name.toLowerCase(); + var elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase()); + if (elm != null && elm.nodeName.toUpperCase() == element_name.toUpperCase()) { + SXE.currentAction = "update"; + } + + if (SXE.currentAction == "update") { + initCommonAttributes(elm); + SXE.updateElement = elm; + } + + document.forms[0].insert.value = tinyMCEPopup.getLang(SXE.currentAction, 'Insert', true); +} + +SXE.insertElement = function(element_name) { + var elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase()), h, tagName; + + if (elm == null) { + var s = SXE.inst.selection.getContent(); + if(s.length > 0) { + tagName = element_name; + + insertInlineElement(element_name); + var elementArray = tinymce.grep(SXE.inst.dom.select(element_name)); + for (var i=0; i<elementArray.length; i++) { + var elm = elementArray[i]; + + if (SXE.inst.dom.getAttrib(elm, 'data-mce-new')) { + elm.id = ''; + elm.setAttribute('id', ''); + elm.removeAttribute('id'); + elm.removeAttribute('data-mce-new'); + + setAllCommonAttribs(elm); + } + } + } + } else { + setAllCommonAttribs(elm); + } + SXE.inst.nodeChanged(); + tinyMCEPopup.execCommand('mceEndUndoLevel'); +} + +SXE.removeElement = function(element_name){ + element_name = element_name.toLowerCase(); + elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase()); + if(elm && elm.nodeName.toUpperCase() == element_name.toUpperCase()){ + tinyMCE.execCommand('mceRemoveNode', false, elm); + SXE.inst.nodeChanged(); + tinyMCEPopup.execCommand('mceEndUndoLevel'); + } +} + +SXE.showRemoveButton = function() { + document.getElementById("remove").style.display = ''; +} + +SXE.containsClass = function(elm,cl) { + return (elm.className.indexOf(cl) > -1) ? true : false; +} + +SXE.removeClass = function(elm,cl) { + if(elm.className == null || elm.className == "" || !SXE.containsClass(elm,cl)) { + return true; + } + var classNames = elm.className.split(" "); + var newClassNames = ""; + for (var x = 0, cnl = classNames.length; x < cnl; x++) { + if (classNames[x] != cl) { + newClassNames += (classNames[x] + " "); + } + } + elm.className = newClassNames.substring(0,newClassNames.length-1); //removes extra space at the end +} + +SXE.addClass = function(elm,cl) { + if(!SXE.containsClass(elm,cl)) elm.className ? elm.className += " " + cl : elm.className = cl; + return true; +} + +function insertInlineElement(en) { + var ed = tinyMCEPopup.editor, dom = ed.dom; + + ed.getDoc().execCommand('FontName', false, 'mceinline'); + tinymce.each(dom.select('span,font'), function(n) { + if (n.style.fontFamily == 'mceinline' || n.face == 'mceinline') + dom.replace(dom.create(en, {'data-mce-new' : 1}), n, 1); + }); +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/ins.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/ins.js new file mode 100644 index 0000000..c4addfb --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/js/ins.js @@ -0,0 +1,53 @@ +/** + * ins.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function init() { + SXE.initElementDialog('ins'); + if (SXE.currentAction == "update") { + setFormValue('datetime', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'datetime')); + setFormValue('cite', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'cite')); + SXE.showRemoveButton(); + } +} + +function setElementAttribs(elm) { + setAllCommonAttribs(elm); + setAttrib(elm, 'datetime'); + setAttrib(elm, 'cite'); + elm.removeAttribute('data-mce-new'); +} + +function insertIns() { + var elm = tinyMCEPopup.editor.dom.getParent(SXE.focusElement, 'INS'); + + if (elm == null) { + var s = SXE.inst.selection.getContent(); + if(s.length > 0) { + insertInlineElement('ins'); + var elementArray = SXE.inst.dom.select('ins[data-mce-new]'); + for (var i=0; i<elementArray.length; i++) { + var elm = elementArray[i]; + setElementAttribs(elm); + } + } + } else { + setElementAttribs(elm); + } + tinyMCEPopup.editor.nodeChanged(); + tinyMCEPopup.execCommand('mceEndUndoLevel'); + tinyMCEPopup.close(); +} + +function removeIns() { + SXE.removeElement('ins'); + tinyMCEPopup.close(); +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/de_dlg.js new file mode 100644 index 0000000..4994355 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.xhtmlxtras_dlg',{"attribs_title":"Attribute einf\u00fcgen/bearbeiten","option_rtl":"Rechts nach links","option_ltr":"Links nach rechts","insert_date":"Aktuelle Zeit/Datum einf\u00fcgen",remove:"Entfernen","title_cite_element":"Quellenangabe","title_abbr_element":"Abk\u00fcrzung","title_acronym_element":"Akronym","title_del_element":"Entfernter Text","title_ins_element":"Eingef\u00fcgter Text","fieldset_events_tab":"Ereignisse","fieldset_attrib_tab":"Attribute","fieldset_general_tab":"Allgemeine Einstellungen","events_tab":"Ereignisse","attrib_tab":"Attribute","general_tab":"Allgemein","attribute_attrib_tab":"Attribute","attribute_events_tab":"Ereignisse","attribute_label_accesskey":"Tastenk\u00fcrzel","attribute_label_tabindex":"Tabindex","attribute_label_langcode":"Sprache","attribute_option_rtl":"Rechts nach links","attribute_option_ltr":"Links nach rechts","attribute_label_langdir":"Schriftrichtung","attribute_label_datetime":"Zeit/Datum","attribute_label_cite":"Quellenangabe","attribute_label_style":"Format","attribute_label_class":"Klasse","attribute_label_id":"ID","attribute_label_title":"Titel"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js new file mode 100644 index 0000000..c4569f8 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.xhtmlxtras_dlg',{"attribs_title":"Insert/Edit Attributes","option_rtl":"Right to Left","option_ltr":"Left to Right","insert_date":"Insert Current Date/Time",remove:"Remove","title_cite_element":"Citation Element","title_abbr_element":"Abbreviation Element","title_acronym_element":"Acronym Element","title_del_element":"Deletion Element","title_ins_element":"Insertion Element","fieldset_events_tab":"Element Events","fieldset_attrib_tab":"Element Attributes","fieldset_general_tab":"General Settings","events_tab":"Events","attrib_tab":"Attributes","general_tab":"General","attribute_attrib_tab":"Attributes","attribute_events_tab":"Events","attribute_label_accesskey":"AccessKey","attribute_label_tabindex":"TabIndex","attribute_label_langcode":"Language","attribute_option_rtl":"Right to Left","attribute_option_ltr":"Left to Right","attribute_label_langdir":"Text Direction","attribute_label_datetime":"Date/Time","attribute_label_cite":"Cite","attribute_label_style":"Style","attribute_label_class":"Class","attribute_label_id":"ID","attribute_label_title":"Title"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/fr_dlg.js new file mode 100644 index 0000000..4ae5a3b --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.xhtmlxtras_dlg',{"attribs_title":"Ins\u00e9rer / \u00e9diter les attributs","option_rtl":"De droite \u00e0 gauche","option_ltr":"De gauche \u00e0 droite","insert_date":"Ins\u00e9rer la date et l\'heure actuelles",remove:"Enlever","title_cite_element":"Citation","title_abbr_element":"Abr\u00e9viation","title_acronym_element":"Acronyme","title_del_element":"Suppression","title_ins_element":"Insertion","fieldset_events_tab":"\u00c9v\u00e9nements","fieldset_attrib_tab":"Attributs","fieldset_general_tab":"Param\u00e8tres g\u00e9n\u00e9raux","events_tab":"\u00c9v\u00e9nements","attrib_tab":"Attributs","general_tab":"G\u00e9n\u00e9ral","attribute_attrib_tab":"Attributs","attribute_events_tab":"\u00c9v\u00e8nements","attribute_label_accesskey":"Accesskey","attribute_label_tabindex":"TabIndex","attribute_label_langcode":"Langue","attribute_option_rtl":"De droite \u00e0 gauche","attribute_option_ltr":"De gauche \u00e0 droite","attribute_label_langdir":"Sens de lecture","attribute_label_datetime":"Date / heure","attribute_label_cite":"Citation","attribute_label_style":"Style","attribute_label_class":"Classe","attribute_label_id":"ID","attribute_label_title":"Titre"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/it_dlg.js new file mode 100644 index 0000000..726be22 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/plugins/xhtmlxtras/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.xhtmlxtras_dlg',{"attribs_title":"Inserisci/modifica attributi","option_rtl":"Destra verso sinistra","option_ltr":"Sinistra verso destra","insert_date":"Inserisci data/ora corrente",remove:"Rimuovi","title_cite_element":"Citazione elemento","title_abbr_element":"Abbreviazione elemento","title_acronym_element":"Acronimo elemento","title_del_element":"Cancellazione elemento","title_ins_element":"Inserimento elemento","fieldset_events_tab":"Eventi elemento","fieldset_attrib_tab":"Attributi elemento","fieldset_general_tab":"Impostazioni Generali","events_tab":"Eventi","attrib_tab":"Attributi","general_tab":"Generale","attribute_attrib_tab":"Attributi","attribute_events_tab":"Eventi","attribute_label_accesskey":"Tasto di accesso","attribute_label_tabindex":"Indice tabulazione","attribute_label_langcode":"Lingua","attribute_option_rtl":"Destra verso sinistra","attribute_option_ltr":"Sinistra verso destra","attribute_label_langdir":"Direzione del testo","attribute_label_datetime":"Date/Time","attribute_label_cite":"Citazione","attribute_label_style":"Style","attribute_label_class":"Classe","attribute_label_id":"ID","attribute_label_title":"Titolo"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/about.htm b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/about.htm new file mode 100644 index 0000000..7a97cb7 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/about.htm @@ -0,0 +1,52 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.about_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="js/about.js"></script> +</head> +<body id="about" style="display: none"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current" aria-controls="general_panel"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.about_general}</a></span></li> + <li id="help_tab" style="display:none" aria-hidden="true" aria-controls="help_panel"><span><a href="javascript:mcTabs.displayTab('help_tab','help_panel');" onmousedown="return false;">{#advanced_dlg.about_help}</a></span></li> + <li id="plugins_tab" aria-controls="plugins_panel"><span><a href="javascript:mcTabs.displayTab('plugins_tab','plugins_panel');" onmousedown="return false;">{#advanced_dlg.about_plugins}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <h3>{#advanced_dlg.about_title}</h3> + <p>Version: <span id="version"></span> (<span id="date"></span>)</p> + <p>TinyMCE is a platform independent web based Javascript HTML WYSIWYG editor control released as Open Source under <a href="../../license.txt" target="_blank">LGPL</a> + by Moxiecode Systems AB. It has the ability to convert HTML TEXTAREA fields or other HTML elements to editor instances.</p> + <p>Copyright &copy; 2003-2008, <a href="http://www.moxiecode.com" target="_blank">Moxiecode Systems AB</a>, All rights reserved.</p> + <p>For more information about this software visit the <a href="http://tinymce.moxiecode.com" target="_blank">TinyMCE website</a>.</p> + + <div id="buttoncontainer"> + <a href="http://www.moxiecode.com" target="_blank"><img src="http://tinymce.moxiecode.com/images/gotmoxie.png" alt="Got Moxie?" border="0" /></a> + </div> + </div> + + <div id="plugins_panel" class="panel"> + <div id="pluginscontainer"> + <h3>{#advanced_dlg.about_loaded}</h3> + + <div id="plugintablecontainer"> + </div> + + <p>&nbsp;</p> + </div> + </div> + + <div id="help_panel" class="panel noscroll" style="overflow: visible;"> + <div id="iframecontainer"></div> + </div> + </div> + + <div class="mceActionPanel"> + <input type="button" id="cancel" name="cancel" value="{#close}" onclick="tinyMCEPopup.close();" /> + </div> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/anchor.htm b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/anchor.htm new file mode 100644 index 0000000..75c93b7 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/anchor.htm @@ -0,0 +1,26 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.anchor_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/anchor.js"></script> +</head> +<body style="display: none" role="application" aria-labelledby="app_title"> +<form onsubmit="AnchorDialog.update();return false;" action="#"> + <table border="0" cellpadding="4" cellspacing="0" role="presentation"> + <tr> + <td colspan="2" class="title" id="app_title">{#advanced_dlg.anchor_title}</td> + </tr> + <tr> + <td class="nowrap"><label for="anchorName">{#advanced_dlg.anchor_name}:</label></td> + <td><input name="anchorName" type="text" class="mceFocus" id="anchorName" value="" style="width: 200px" aria-required="true" /></td> + </tr> + </table> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#update}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/charmap.htm b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/charmap.htm new file mode 100644 index 0000000..2c3b3f2 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/charmap.htm @@ -0,0 +1,51 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.charmap_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/charmap.js"></script> +</head> +<body id="charmap" style="display:none"> +<table align="center" border="0" cellspacing="0" cellpadding="2" role="presentation"> + <tr> + <td colspan="2" class="title" ><label for="charmapView" id="charmap_label">{#advanced_dlg.charmap_title}</label></td> + </tr> + <tr> + <td id="charmapView" rowspan="2" align="left" valign="top"> + <!-- Chars will be rendered here --> + </td> + <td width="100" align="center" valign="top"> + <table border="0" cellpadding="0" cellspacing="0" width="100" style="height:100px" role="presentation"> + <tr> + <td id="codeV">&nbsp;</td> + </tr> + <tr> + <td id="codeN">&nbsp;</td> + </tr> + </table> + </td> + </tr> + <tr> + <td valign="bottom" style="padding-bottom: 3px;"> + <table width="100" align="center" border="0" cellpadding="2" cellspacing="0" role="presentation"> + <tr> + <td align="center" style="border-left: 1px solid #666699; border-top: 1px solid #666699; border-right: 1px solid #666699;"><label for="codeA">HTML-Code</label></td> + </tr> + <tr> + <td style="font-size: 16px; font-weight: bold; border-left: 1px solid #666699; border-bottom: 1px solid #666699; border-right: 1px solid #666699;" id="codeA" align="center">&nbsp;</td> + </tr> + <tr> + <td style="font-size: 1px;">&nbsp;</td> + </tr> + <tr> + <td align="center" style="border-left: 1px solid #666699; border-top: 1px solid #666699; border-right: 1px solid #666699;"><label for="codeB">NUM-Code</label></td> + </tr> + <tr> + <td style="font-size: 16px; font-weight: bold; border-left: 1px solid #666699; border-bottom: 1px solid #666699; border-right: 1px solid #666699;" id="codeB" align="center">&nbsp;</td> + </tr> + </table> + </td> + </tr> +</table> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/color_picker.htm b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/color_picker.htm new file mode 100644 index 0000000..ad1bb0f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/color_picker.htm @@ -0,0 +1,74 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.colorpicker_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="js/color_picker.js"></script> +</head> +<body id="colorpicker" style="display: none" role="application" aria-labelledby="app_label"> + <span class="mceVoiceLabel" id="app_label" style="display:none;">{#advanced_dlg.colorpicker_title}</span> +<form onsubmit="insertAction();return false" action="#"> + <div class="tabs"> + <ul> + <li id="picker_tab" aria-controls="picker_panel" class="current"><span><a href="javascript:mcTabs.displayTab('picker_tab','picker_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_picker_tab}</a></span></li> + <li id="rgb_tab" aria-controls="rgb_panel"><span><a href="javascript:;" onclick="mcTabs.displayTab('rgb_tab','rgb_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_palette_tab}</a></span></li> + <li id="named_tab" aria-controls="named_panel"><span><a href="javascript:;" onclick="javascript:mcTabs.displayTab('named_tab','named_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_named_tab}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="picker_panel" class="panel current"> + <fieldset> + <legend>{#advanced_dlg.colorpicker_picker_title}</legend> + <div id="picker"> + <img id="colors" src="img/colorpicker.jpg" onclick="computeColor(event)" onmousedown="isMouseDown = true;return false;" onmouseup="isMouseDown = false;" onmousemove="if (isMouseDown && isMouseOver) computeColor(event); return false;" onmouseover="isMouseOver=true;" onmouseout="isMouseOver=false;" alt="" /> + + <div id="light"> + <!-- Will be filled with divs --> + </div> + + <br style="clear: both" /> + </div> + </fieldset> + </div> + + <div id="rgb_panel" class="panel"> + <fieldset> + <legend id="webcolors_title">{#advanced_dlg.colorpicker_palette_title}</legend> + <div id="webcolors"> + <!-- Gets filled with web safe colors--> + </div> + + <br style="clear: both" /> + </fieldset> + </div> + + <div id="named_panel" class="panel"> + <fieldset id="named_picker_label"> + <legend id="named_title">{#advanced_dlg.colorpicker_named_title}</legend> + <div id="namedcolors" role="listbox" tabindex="0" aria-labelledby="named_picker_label"> + <!-- Gets filled with named colors--> + </div> + + <br style="clear: both" /> + + <div id="colornamecontainer"> + {#advanced_dlg.colorpicker_name} <span id="colorname"></span> + </div> + </fieldset> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#apply}" /> + + <div id="preview"></div> + + <div id="previewblock"> + <label for="color">{#advanced_dlg.colorpicker_color}</label> <input id="color" type="text" size="8" class="text mceFocus" aria-required="true" /> + </div> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/editor_template.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/editor_template.js new file mode 100644 index 0000000..7f30c18 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/editor_template.js @@ -0,0 +1 @@ +(function(e){var d=e.DOM,b=e.dom.Event,h=e.extend,f=e.each,a=e.util.Cookie,g,c=e.explode;e.ThemeManager.requireLangPack("advanced");e.create("tinymce.themes.AdvancedTheme",{sizes:[8,10,12,14,18,24,36],controls:{bold:["bold_desc","Bold"],italic:["italic_desc","Italic"],underline:["underline_desc","Underline"],strikethrough:["striketrough_desc","Strikethrough"],justifyleft:["justifyleft_desc","JustifyLeft"],justifycenter:["justifycenter_desc","JustifyCenter"],justifyright:["justifyright_desc","JustifyRight"],justifyfull:["justifyfull_desc","JustifyFull"],bullist:["bullist_desc","InsertUnorderedList"],numlist:["numlist_desc","InsertOrderedList"],outdent:["outdent_desc","Outdent"],indent:["indent_desc","Indent"],cut:["cut_desc","Cut"],copy:["copy_desc","Copy"],paste:["paste_desc","Paste"],undo:["undo_desc","Undo"],redo:["redo_desc","Redo"],link:["link_desc","mceLink"],unlink:["unlink_desc","unlink"],image:["image_desc","mceImage"],cleanup:["cleanup_desc","mceCleanup"],help:["help_desc","mceHelp"],code:["code_desc","mceCodeEditor"],hr:["hr_desc","InsertHorizontalRule"],removeformat:["removeformat_desc","RemoveFormat"],sub:["sub_desc","subscript"],sup:["sup_desc","superscript"],forecolor:["forecolor_desc","ForeColor"],forecolorpicker:["forecolor_desc","mceForeColor"],backcolor:["backcolor_desc","HiliteColor"],backcolorpicker:["backcolor_desc","mceBackColor"],charmap:["charmap_desc","mceCharMap"],visualaid:["visualaid_desc","mceToggleVisualAid"],anchor:["anchor_desc","mceInsertAnchor"],newdocument:["newdocument_desc","mceNewDocument"],blockquote:["blockquote_desc","mceBlockQuote"]},stateControls:["bold","italic","underline","strikethrough","bullist","numlist","justifyleft","justifycenter","justifyright","justifyfull","sub","sup","blockquote"],init:function(j,k){var l=this,m,i,n;l.editor=j;l.url=k;l.onResolveName=new e.util.Dispatcher(this);j.forcedHighContrastMode=j.settings.detect_highcontrast&&l._isHighContrast();j.settings.skin=j.forcedHighContrastMode?"highcontrast":j.settings.skin;l.settings=m=h({theme_advanced_path:true,theme_advanced_toolbar_location:"bottom",theme_advanced_buttons1:"bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",theme_advanced_buttons2:"bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",theme_advanced_buttons3:"hr,removeformat,visualaid,|,sub,sup,|,charmap",theme_advanced_blockformats:"p,address,pre,h1,h2,h3,h4,h5,h6",theme_advanced_toolbar_align:"center",theme_advanced_fonts:"Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",theme_advanced_more_colors:1,theme_advanced_row_height:23,theme_advanced_resize_horizontal:1,theme_advanced_resizing_use_cookie:1,theme_advanced_font_sizes:"1,2,3,4,5,6,7",theme_advanced_font_selector:"span",theme_advanced_show_current_color:0,readonly:j.settings.readonly},j.settings);if(!m.font_size_style_values){m.font_size_style_values="8pt,10pt,12pt,14pt,18pt,24pt,36pt"}if(e.is(m.theme_advanced_font_sizes,"string")){m.font_size_style_values=e.explode(m.font_size_style_values);m.font_size_classes=e.explode(m.font_size_classes||"");n={};j.settings.theme_advanced_font_sizes=m.theme_advanced_font_sizes;f(j.getParam("theme_advanced_font_sizes","","hash"),function(q,p){var o;if(p==q&&q>=1&&q<=7){p=q+" ("+l.sizes[q-1]+"pt)";o=m.font_size_classes[q-1];q=m.font_size_style_values[q-1]||(l.sizes[q-1]+"pt")}if(/^\s*\./.test(q)){o=q.replace(/\./g,"")}n[p]=o?{"class":o}:{fontSize:q}});m.theme_advanced_font_sizes=n}if((i=m.theme_advanced_path_location)&&i!="none"){m.theme_advanced_statusbar_location=m.theme_advanced_path_location}if(m.theme_advanced_statusbar_location=="none"){m.theme_advanced_statusbar_location=0}if(j.settings.content_css!==false){j.contentCSS.push(j.baseURI.toAbsolute(k+"/skins/"+j.settings.skin+"/content.css"))}j.onInit.add(function(){if(!j.settings.readonly){j.onNodeChange.add(l._nodeChanged,l);j.onKeyUp.add(l._updateUndoStatus,l);j.onMouseUp.add(l._updateUndoStatus,l);j.dom.bind(j.dom.getRoot(),"dragend",function(){l._updateUndoStatus(j)})}});j.onSetProgressState.add(function(q,o,r){var s,t=q.id,p;if(o){l.progressTimer=setTimeout(function(){s=q.getContainer();s=s.insertBefore(d.create("DIV",{style:"position:relative"}),s.firstChild);p=d.get(q.id+"_tbl");d.add(s,"div",{id:t+"_blocker","class":"mceBlocker",style:{width:p.clientWidth+2,height:p.clientHeight+2}});d.add(s,"div",{id:t+"_progress","class":"mceProgress",style:{left:p.clientWidth/2,top:p.clientHeight/2}})},r||0)}else{d.remove(t+"_blocker");d.remove(t+"_progress");clearTimeout(l.progressTimer)}});d.loadCSS(m.editor_css?j.documentBaseURI.toAbsolute(m.editor_css):k+"/skins/"+j.settings.skin+"/ui.css");if(m.skin_variant){d.loadCSS(k+"/skins/"+j.settings.skin+"/ui_"+m.skin_variant+".css")}},_isHighContrast:function(){var i,j=d.add(d.getRoot(),"div",{style:"background-color: rgb(171,239,86);"});i=(d.getStyle(j,"background-color",true)+"").toLowerCase().replace(/ /g,"");d.remove(j);return i!="rgb(171,239,86)"&&i!="#abef56"},createControl:function(l,i){var j,k;if(k=i.createControl(l)){return k}switch(l){case"styleselect":return this._createStyleSelect();case"formatselect":return this._createBlockFormats();case"fontselect":return this._createFontSelect();case"fontsizeselect":return this._createFontSizeSelect();case"forecolor":return this._createForeColorMenu();case"backcolor":return this._createBackColorMenu()}if((j=this.controls[l])){return i.createButton(l,{title:"advanced."+j[0],cmd:j[1],ui:j[2],value:j[3]})}},execCommand:function(k,j,l){var i=this["_"+k];if(i){i.call(this,j,l);return true}return false},_importClasses:function(k){var i=this.editor,j=i.controlManager.get("styleselect");if(j.getLength()==0){f(i.dom.getClasses(),function(n,l){var m="style_"+l;i.formatter.register(m,{inline:"span",attributes:{"class":n["class"]},selector:"*"});j.add(n["class"],m)})}},_createStyleSelect:function(m){var k=this,i=k.editor,j=i.controlManager,l;l=j.createListBox("styleselect",{title:"advanced.style_select",onselect:function(o){var p,n=[];f(l.items,function(q){n.push(q.value)});i.focus();i.undoManager.add();p=i.formatter.matchAll(n);if(!o||p[0]==o){if(p[0]){i.formatter.remove(p[0])}}else{i.formatter.apply(o)}i.undoManager.add();i.nodeChanged();return false}});i.onInit.add(function(){var o=0,n=i.getParam("style_formats");if(n){f(n,function(p){var q,r=0;f(p,function(){r++});if(r>1){q=p.name=p.name||"style_"+(o++);i.formatter.register(q,p);l.add(p.title,q)}else{l.add(p.title)}})}else{f(i.getParam("theme_advanced_styles","","hash"),function(r,q){var p;if(r){p="style_"+(o++);i.formatter.register(p,{inline:"span",classes:r,selector:"*"});l.add(k.editor.translate(q),p)}})}});if(l.getLength()==0){l.onPostRender.add(function(o,p){if(!l.NativeListBox){b.add(p.id+"_text","focus",k._importClasses,k);b.add(p.id+"_text","mousedown",k._importClasses,k);b.add(p.id+"_open","focus",k._importClasses,k);b.add(p.id+"_open","mousedown",k._importClasses,k)}else{b.add(p.id,"focus",k._importClasses,k)}})}return l},_createFontSelect:function(){var k,j=this,i=j.editor;k=i.controlManager.createListBox("fontselect",{title:"advanced.fontdefault",onselect:function(l){var m=k.items[k.selectedIndex];if(!l&&m){i.execCommand("FontName",false,m.value);return}i.execCommand("FontName",false,l);k.select(function(n){return l==n});if(m&&m.value==l){k.select(null)}return false}});if(k){f(i.getParam("theme_advanced_fonts",j.settings.theme_advanced_fonts,"hash"),function(m,l){k.add(i.translate(l),m,{style:m.indexOf("dings")==-1?"font-family:"+m:""})})}return k},_createFontSizeSelect:function(){var m=this,k=m.editor,n,l=0,j=[];n=k.controlManager.createListBox("fontsizeselect",{title:"advanced.font_size",onselect:function(i){var o=n.items[n.selectedIndex];if(!i&&o){o=o.value;if(o["class"]){k.formatter.toggle("fontsize_class",{value:o["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,o.fontSize)}return}if(i["class"]){k.focus();k.undoManager.add();k.formatter.toggle("fontsize_class",{value:i["class"]});k.undoManager.add();k.nodeChanged()}else{k.execCommand("FontSize",false,i.fontSize)}n.select(function(p){return i==p});if(o&&(o.value.fontSize==i.fontSize||o.value["class"]==i["class"])){n.select(null)}return false}});if(n){f(m.settings.theme_advanced_font_sizes,function(o,i){var p=o.fontSize;if(p>=1&&p<=7){p=m.sizes[parseInt(p)-1]+"pt"}n.add(i,o,{style:"font-size:"+p,"class":"mceFontSize"+(l++)+(" "+(o["class"]||""))})})}return n},_createBlockFormats:function(){var k,i={p:"advanced.paragraph",address:"advanced.address",pre:"advanced.pre",h1:"advanced.h1",h2:"advanced.h2",h3:"advanced.h3",h4:"advanced.h4",h5:"advanced.h5",h6:"advanced.h6",div:"advanced.div",blockquote:"advanced.blockquote",code:"advanced.code",dt:"advanced.dt",dd:"advanced.dd",samp:"advanced.samp"},j=this;k=j.editor.controlManager.createListBox("formatselect",{title:"advanced.block",onselect:function(l){j.editor.execCommand("FormatBlock",false,l);return false}});if(k){f(j.editor.getParam("theme_advanced_blockformats",j.settings.theme_advanced_blockformats,"hash"),function(m,l){k.add(j.editor.translate(l!=m?l:i[m]),m,{"class":"mce_formatPreview mce_"+m})})}return k},_createForeColorMenu:function(){var m,j=this,k=j.settings,l={},i;if(k.theme_advanced_more_colors){l.more_colors_func=function(){j._mceColorPicker(0,{color:m.value,func:function(n){m.setColor(n)}})}}if(i=k.theme_advanced_text_colors){l.colors=i}if(k.theme_advanced_default_foreground_color){l.default_color=k.theme_advanced_default_foreground_color}l.title="advanced.forecolor_desc";l.cmd="ForeColor";l.scope=this;m=j.editor.controlManager.createColorSplitButton("forecolor",l);return m},_createBackColorMenu:function(){var m,j=this,k=j.settings,l={},i;if(k.theme_advanced_more_colors){l.more_colors_func=function(){j._mceColorPicker(0,{color:m.value,func:function(n){m.setColor(n)}})}}if(i=k.theme_advanced_background_colors){l.colors=i}if(k.theme_advanced_default_background_color){l.default_color=k.theme_advanced_default_background_color}l.title="advanced.backcolor_desc";l.cmd="HiliteColor";l.scope=this;m=j.editor.controlManager.createColorSplitButton("backcolor",l);return m},renderUI:function(k){var m,l,q,v=this,r=v.editor,w=v.settings,u,j,i;if(r.settings){r.settings.aria_label=w.aria_label+r.getLang("advanced.help_shortcut")}m=j=d.create("span",{role:"application","aria-labelledby":r.id+"_voice",id:r.id+"_parent","class":"mceEditor "+r.settings.skin+"Skin"+(w.skin_variant?" "+r.settings.skin+"Skin"+v._ufirst(w.skin_variant):"")});d.add(m,"span",{"class":"mceVoiceLabel",style:"display:none;",id:r.id+"_voice"},w.aria_label);if(!d.boxModel){m=d.add(m,"div",{"class":"mceOldBoxModel"})}m=u=d.add(m,"table",{role:"presentation",id:r.id+"_tbl","class":"mceLayout",cellSpacing:0,cellPadding:0});m=q=d.add(m,"tbody");switch((w.theme_advanced_layout_manager||"").toLowerCase()){case"rowlayout":l=v._rowLayout(w,q,k);break;case"customlayout":l=r.execCallback("theme_advanced_custom_layout",w,q,k,j);break;default:l=v._simpleLayout(w,q,k,j)}m=k.targetNode;i=u.rows;d.addClass(i[0],"mceFirst");d.addClass(i[i.length-1],"mceLast");f(d.select("tr",q),function(o){d.addClass(o.firstChild,"mceFirst");d.addClass(o.childNodes[o.childNodes.length-1],"mceLast")});if(d.get(w.theme_advanced_toolbar_container)){d.get(w.theme_advanced_toolbar_container).appendChild(j)}else{d.insertAfter(j,m)}b.add(r.id+"_path_row","click",function(n){n=n.target;if(n.nodeName=="A"){v._sel(n.className.replace(/^.*mcePath_([0-9]+).*$/,"$1"));return b.cancel(n)}});if(!r.getParam("accessibility_focus")){b.add(d.add(j,"a",{href:"#"},"<!-- IE -->"),"focus",function(){tinyMCE.get(r.id).focus()})}if(w.theme_advanced_toolbar_location=="external"){k.deltaHeight=0}v.deltaHeight=k.deltaHeight;k.targetNode=null;r.onKeyDown.add(function(p,n){var s=121,o=122;if(n.altKey){if(n.keyCode===s){window.focus();v.toolbarGroup.focus();return b.cancel(n)}else{if(n.keyCode===o){d.get(p.id+"_path_row").focus();return b.cancel(n)}}}});r.addShortcut("alt+0","","mceShortcuts",v);return{iframeContainer:l,editorContainer:r.id+"_parent",sizeContainer:u,deltaHeight:k.deltaHeight}},getInfo:function(){return{longname:"Advanced theme",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",version:e.majorVersion+"."+e.minorVersion}},resizeBy:function(i,j){var k=d.get(this.editor.id+"_ifr");this.resizeTo(k.clientWidth+i,k.clientHeight+j)},resizeTo:function(i,m,k){var j=this.editor,l=this.settings,n=d.get(j.id+"_tbl"),o=d.get(j.id+"_ifr");i=Math.max(l.theme_advanced_resizing_min_width||100,i);m=Math.max(l.theme_advanced_resizing_min_height||100,m);i=Math.min(l.theme_advanced_resizing_max_width||65535,i);m=Math.min(l.theme_advanced_resizing_max_height||65535,m);d.setStyle(n,"height","");d.setStyle(o,"height",m);if(l.theme_advanced_resize_horizontal){d.setStyle(n,"width","");d.setStyle(o,"width",i);if(i<n.clientWidth){i=n.clientWidth;d.setStyle(o,"width",n.clientWidth)}}if(k&&l.theme_advanced_resizing_use_cookie){a.setHash("TinyMCE_"+j.id+"_size",{cw:i,ch:m})}},destroy:function(){var i=this.editor.id;b.clear(i+"_resize");b.clear(i+"_path_row");b.clear(i+"_external_close")},_simpleLayout:function(y,r,k,i){var x=this,u=x.editor,v=y.theme_advanced_toolbar_location,m=y.theme_advanced_statusbar_location,l,j,q,w;if(y.readonly){l=d.add(r,"tr");l=j=d.add(l,"td",{"class":"mceIframeContainer"});return j}if(v=="top"){x._addToolbars(r,k)}if(v=="external"){l=w=d.create("div",{style:"position:relative"});l=d.add(l,"div",{id:u.id+"_external","class":"mceExternalToolbar"});d.add(l,"a",{id:u.id+"_external_close",href:"javascript:;","class":"mceExternalClose"});l=d.add(l,"table",{id:u.id+"_tblext",cellSpacing:0,cellPadding:0});q=d.add(l,"tbody");if(i.firstChild.className=="mceOldBoxModel"){i.firstChild.appendChild(w)}else{i.insertBefore(w,i.firstChild)}x._addToolbars(q,k);u.onMouseUp.add(function(){var o=d.get(u.id+"_external");d.show(o);d.hide(g);var n=b.add(u.id+"_external_close","click",function(){d.hide(u.id+"_external");b.remove(u.id+"_external_close","click",n)});d.show(o);d.setStyle(o,"top",0-d.getRect(u.id+"_tblext").h-1);d.hide(o);d.show(o);o.style.filter="";g=u.id+"_external";o=null})}if(m=="top"){x._addStatusBar(r,k)}if(!y.theme_advanced_toolbar_container){l=d.add(r,"tr");l=j=d.add(l,"td",{"class":"mceIframeContainer"})}if(v=="bottom"){x._addToolbars(r,k)}if(m=="bottom"){x._addStatusBar(r,k)}return j},_rowLayout:function(w,m,k){var v=this,p=v.editor,u,x,i=p.controlManager,l,j,r,q;u=w.theme_advanced_containers_default_class||"";x=w.theme_advanced_containers_default_align||"center";f(c(w.theme_advanced_containers||""),function(s,o){var n=w["theme_advanced_container_"+s]||"";switch(s.toLowerCase()){case"mceeditor":l=d.add(m,"tr");l=j=d.add(l,"td",{"class":"mceIframeContainer"});break;case"mceelementpath":v._addStatusBar(m,k);break;default:q=(w["theme_advanced_container_"+s+"_align"]||x).toLowerCase();q="mce"+v._ufirst(q);l=d.add(d.add(m,"tr"),"td",{"class":"mceToolbar "+(w["theme_advanced_container_"+s+"_class"]||u)+" "+q||x});r=i.createToolbar("toolbar"+o);v._addControls(n,r);d.setHTML(l,r.renderHTML());k.deltaHeight-=w.theme_advanced_row_height}});return j},_addControls:function(j,i){var k=this,l=k.settings,m,n=k.editor.controlManager;if(l.theme_advanced_disable&&!k._disabled){m={};f(c(l.theme_advanced_disable),function(o){m[o]=1});k._disabled=m}else{m=k._disabled}f(c(j),function(p){var o;if(m&&m[p]){return}if(p=="tablecontrols"){f(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"],function(q){q=k.createControl(q,n);if(q){i.add(q)}});return}o=k.createControl(p,n);if(o){i.add(o)}})},_addToolbars:function(x,k){var A=this,p,m,r=A.editor,B=A.settings,z,j=r.controlManager,u,l,q=[],y,w;w=j.createToolbarGroup("toolbargroup",{name:r.getLang("advanced.toolbar"),tab_focus_toolbar:r.getParam("theme_advanced_tab_focus_toolbar")});A.toolbarGroup=w;y=B.theme_advanced_toolbar_align.toLowerCase();y="mce"+A._ufirst(y);l=d.add(d.add(x,"tr",{role:"presentation"}),"td",{"class":"mceToolbar "+y,role:"presentation"});for(p=1;(z=B["theme_advanced_buttons"+p]);p++){m=j.createToolbar("toolbar"+p,{"class":"mceToolbarRow"+p});if(B["theme_advanced_buttons"+p+"_add"]){z+=","+B["theme_advanced_buttons"+p+"_add"]}if(B["theme_advanced_buttons"+p+"_add_before"]){z=B["theme_advanced_buttons"+p+"_add_before"]+","+z}A._addControls(z,m);w.add(m);k.deltaHeight-=B.theme_advanced_row_height}q.push(w.renderHTML());q.push(d.createHTML("a",{href:"#",accesskey:"z",title:r.getLang("advanced.toolbar_focus"),onfocus:"tinyMCE.getInstanceById('"+r.id+"').focus();"},"<!-- IE -->"));d.setHTML(l,q.join(""))},_addStatusBar:function(m,j){var k,v=this,p=v.editor,w=v.settings,i,q,u,l;k=d.add(m,"tr");k=l=d.add(k,"td",{"class":"mceStatusbar"});k=d.add(k,"div",{id:p.id+"_path_row",role:"group","aria-labelledby":p.id+"_path_voice"});if(w.theme_advanced_path){d.add(k,"span",{id:p.id+"_path_voice"},p.translate("advanced.path"));d.add(k,"span",{},": ")}else{d.add(k,"span",{},"&#160;")}if(w.theme_advanced_resizing){d.add(l,"a",{id:p.id+"_resize",href:"javascript:;",onclick:"return false;","class":"mceResize",tabIndex:"-1"});if(w.theme_advanced_resizing_use_cookie){p.onPostRender.add(function(){var n=a.getHash("TinyMCE_"+p.id+"_size"),r=d.get(p.id+"_tbl");if(!n){return}v.resizeTo(n.cw,n.ch)})}p.onPostRender.add(function(){b.add(p.id+"_resize","click",function(n){n.preventDefault()});b.add(p.id+"_resize","mousedown",function(D){var t,r,s,o,C,z,A,F,n,E,x;function y(G){G.preventDefault();n=A+(G.screenX-C);E=F+(G.screenY-z);v.resizeTo(n,E)}function B(G){b.remove(d.doc,"mousemove",t);b.remove(p.getDoc(),"mousemove",r);b.remove(d.doc,"mouseup",s);b.remove(p.getDoc(),"mouseup",o);n=A+(G.screenX-C);E=F+(G.screenY-z);v.resizeTo(n,E,true)}D.preventDefault();C=D.screenX;z=D.screenY;x=d.get(v.editor.id+"_ifr");A=n=x.clientWidth;F=E=x.clientHeight;t=b.add(d.doc,"mousemove",y);r=b.add(p.getDoc(),"mousemove",y);s=b.add(d.doc,"mouseup",B);o=b.add(p.getDoc(),"mouseup",B)})})}j.deltaHeight-=21;k=m=null},_updateUndoStatus:function(j){var i=j.controlManager,k=j.undoManager;i.setDisabled("undo",!k.hasUndo()&&!k.typing);i.setDisabled("redo",!k.hasRedo())},_nodeChanged:function(m,r,D,q,E){var y=this,C,F=0,x,G,z=y.settings,w,k,u,B,l,j,i;e.each(y.stateControls,function(n){r.setActive(n,m.queryCommandState(y.controls[n][1]))});function o(p){var s,n=E.parents,t=p;if(typeof(p)=="string"){t=function(v){return v.nodeName==p}}for(s=0;s<n.length;s++){if(t(n[s])){return n[s]}}}r.setActive("visualaid",m.hasVisual);y._updateUndoStatus(m);r.setDisabled("outdent",!m.queryCommandState("Outdent"));C=o("A");if(G=r.get("link")){if(!C||!C.name){G.setDisabled(!C&&q);G.setActive(!!C)}}if(G=r.get("unlink")){G.setDisabled(!C&&q);G.setActive(!!C&&!C.name)}if(G=r.get("anchor")){G.setActive(!q&&!!C&&C.name)}C=o("IMG");if(G=r.get("image")){G.setActive(!q&&!!C&&D.className.indexOf("mceItem")==-1)}if(G=r.get("styleselect")){y._importClasses();j=[];f(G.items,function(n){j.push(n.value)});i=m.formatter.matchAll(j);G.select(i[0])}if(G=r.get("formatselect")){C=o(d.isBlock);if(C){G.select(C.nodeName.toLowerCase())}}o(function(p){if(p.nodeName==="SPAN"){if(!w&&p.className){w=p.className}}if(m.dom.is(p,z.theme_advanced_font_selector)){if(!k&&p.style.fontSize){k=p.style.fontSize}if(!u&&p.style.fontFamily){u=p.style.fontFamily.replace(/[\"\']+/g,"").replace(/^([^,]+).*/,"$1").toLowerCase()}if(!B&&p.style.color){B=p.style.color}if(!l&&p.style.backgroundColor){l=p.style.backgroundColor}}return false});if(G=r.get("fontselect")){G.select(function(n){return n.replace(/^([^,]+).*/,"$1").toLowerCase()==u})}if(G=r.get("fontsizeselect")){if(z.theme_advanced_runtime_fontsize&&!k&&!w){k=m.dom.getStyle(D,"fontSize",true)}G.select(function(n){if(n.fontSize&&n.fontSize===k){return true}if(n["class"]&&n["class"]===w){return true}})}if(z.theme_advanced_show_current_color){function A(p,n){if(G=r.get(p)){if(!n){n=G.settings.default_color}if(n!==G.value){G.displayColor(n)}}}A("forecolor",B);A("backcolor",l)}if(z.theme_advanced_show_current_color){function A(p,n){if(G=r.get(p)){if(!n){n=G.settings.default_color}if(n!==G.value){G.displayColor(n)}}}A("forecolor",B);A("backcolor",l)}if(z.theme_advanced_path&&z.theme_advanced_statusbar_location){C=d.get(m.id+"_path")||d.add(m.id+"_path_row","span",{id:m.id+"_path"});if(y.statusKeyboardNavigation){y.statusKeyboardNavigation.destroy();y.statusKeyboardNavigation=null}d.setHTML(C,"");o(function(H){var p=H.nodeName.toLowerCase(),s,v,t="";if(H.nodeType!=1||p==="br"||H.getAttribute("data-mce-bogus")||d.hasClass(H,"mceItemHidden")||d.hasClass(H,"mceItemRemoved")){return}if(e.isIE&&H.scopeName!=="HTML"){p=H.scopeName+":"+p}p=p.replace(/mce\:/g,"");switch(p){case"b":p="strong";break;case"i":p="em";break;case"img":if(x=d.getAttrib(H,"src")){t+="src: "+x+" "}break;case"a":if(x=d.getAttrib(H,"name")){t+="name: "+x+" ";p+="#"+x}if(x=d.getAttrib(H,"href")){t+="href: "+x+" "}break;case"font":if(x=d.getAttrib(H,"face")){t+="font: "+x+" "}if(x=d.getAttrib(H,"size")){t+="size: "+x+" "}if(x=d.getAttrib(H,"color")){t+="color: "+x+" "}break;case"span":if(x=d.getAttrib(H,"style")){t+="style: "+x+" "}break}if(x=d.getAttrib(H,"id")){t+="id: "+x+" "}if(x=H.className){x=x.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g,"");if(x){t+="class: "+x+" ";if(d.isBlock(H)||p=="img"||p=="span"){p+="."+x}}}p=p.replace(/(html:)/g,"");p={name:p,node:H,title:t};y.onResolveName.dispatch(y,p);t=p.title;p=p.name;v=d.create("a",{href:"javascript:;",role:"button",onmousedown:"return false;",title:t,"class":"mcePath_"+(F++)},p);if(C.hasChildNodes()){C.insertBefore(d.create("span",{"aria-hidden":"true"},"\u00a0\u00bb "),C.firstChild);C.insertBefore(v,C.firstChild)}else{C.appendChild(v)}},m.getBody());if(d.select("a",C).length>0){y.statusKeyboardNavigation=new e.ui.KeyboardNavigation({root:m.id+"_path_row",items:d.select("a",C),excludeFromTabOrder:true,onCancel:function(){m.focus()}},d)}}},_sel:function(i){this.editor.execCommand("mceSelectNodeDepth",false,i)},_mceInsertAnchor:function(k,j){var i=this.editor;i.windowManager.open({url:this.url+"/anchor.htm",width:320+parseInt(i.getLang("advanced.anchor_delta_width",0)),height:90+parseInt(i.getLang("advanced.anchor_delta_height",0)),inline:true},{theme_url:this.url})},_mceCharMap:function(){var i=this.editor;i.windowManager.open({url:this.url+"/charmap.htm",width:550+parseInt(i.getLang("advanced.charmap_delta_width",0)),height:250+parseInt(i.getLang("advanced.charmap_delta_height",0)),inline:true},{theme_url:this.url})},_mceHelp:function(){var i=this.editor;i.windowManager.open({url:this.url+"/about.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceShortcuts:function(){var i=this.editor;i.windowManager.open({url:this.url+"/shortcuts.htm",width:480,height:380,inline:true},{theme_url:this.url})},_mceColorPicker:function(k,j){var i=this.editor;j=j||{};i.windowManager.open({url:this.url+"/color_picker.htm",width:375+parseInt(i.getLang("advanced.colorpicker_delta_width",0)),height:250+parseInt(i.getLang("advanced.colorpicker_delta_height",0)),close_previous:false,inline:true},{input_color:j.color,func:j.func,theme_url:this.url})},_mceCodeEditor:function(j,k){var i=this.editor;i.windowManager.open({url:this.url+"/source_editor.htm",width:parseInt(i.getParam("theme_advanced_source_editor_width",720)),height:parseInt(i.getParam("theme_advanced_source_editor_height",580)),inline:true,resizable:true,maximizable:true},{theme_url:this.url})},_mceImage:function(j,k){var i=this.editor;if(i.dom.getAttrib(i.selection.getNode(),"class").indexOf("mceItem")!=-1){return}i.windowManager.open({url:this.url+"/image.htm",width:355+parseInt(i.getLang("advanced.image_delta_width",0)),height:275+parseInt(i.getLang("advanced.image_delta_height",0)),inline:true},{theme_url:this.url})},_mceLink:function(j,k){var i=this.editor;i.windowManager.open({url:this.url+"/link.htm",width:310+parseInt(i.getLang("advanced.link_delta_width",0)),height:200+parseInt(i.getLang("advanced.link_delta_height",0)),inline:true},{theme_url:this.url})},_mceNewDocument:function(){var i=this.editor;i.windowManager.confirm("advanced.newdocument",function(j){if(j){i.execCommand("mceSetContent",false,"")}})},_mceForeColor:function(){var i=this;this._mceColorPicker(0,{color:i.fgColor,func:function(j){i.fgColor=j;i.editor.execCommand("ForeColor",false,j)}})},_mceBackColor:function(){var i=this;this._mceColorPicker(0,{color:i.bgColor,func:function(j){i.bgColor=j;i.editor.execCommand("HiliteColor",false,j)}})},_ufirst:function(i){return i.substring(0,1).toUpperCase()+i.substring(1)}});e.ThemeManager.add("advanced",e.themes.AdvancedTheme)}(tinymce)); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/editor_template_src.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/editor_template_src.js new file mode 100644 index 0000000..bee26e1 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/editor_template_src.js @@ -0,0 +1,1358 @@ +/** + * editor_template_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, each = tinymce.each, Cookie = tinymce.util.Cookie, lastExtID, explode = tinymce.explode; + + // Tell it to load theme specific language pack(s) + tinymce.ThemeManager.requireLangPack('advanced'); + + tinymce.create('tinymce.themes.AdvancedTheme', { + sizes : [8, 10, 12, 14, 18, 24, 36], + + // Control name lookup, format: title, command + controls : { + bold : ['bold_desc', 'Bold'], + italic : ['italic_desc', 'Italic'], + underline : ['underline_desc', 'Underline'], + strikethrough : ['striketrough_desc', 'Strikethrough'], + justifyleft : ['justifyleft_desc', 'JustifyLeft'], + justifycenter : ['justifycenter_desc', 'JustifyCenter'], + justifyright : ['justifyright_desc', 'JustifyRight'], + justifyfull : ['justifyfull_desc', 'JustifyFull'], + bullist : ['bullist_desc', 'InsertUnorderedList'], + numlist : ['numlist_desc', 'InsertOrderedList'], + outdent : ['outdent_desc', 'Outdent'], + indent : ['indent_desc', 'Indent'], + cut : ['cut_desc', 'Cut'], + copy : ['copy_desc', 'Copy'], + paste : ['paste_desc', 'Paste'], + undo : ['undo_desc', 'Undo'], + redo : ['redo_desc', 'Redo'], + link : ['link_desc', 'mceLink'], + unlink : ['unlink_desc', 'unlink'], + image : ['image_desc', 'mceImage'], + cleanup : ['cleanup_desc', 'mceCleanup'], + help : ['help_desc', 'mceHelp'], + code : ['code_desc', 'mceCodeEditor'], + hr : ['hr_desc', 'InsertHorizontalRule'], + removeformat : ['removeformat_desc', 'RemoveFormat'], + sub : ['sub_desc', 'subscript'], + sup : ['sup_desc', 'superscript'], + forecolor : ['forecolor_desc', 'ForeColor'], + forecolorpicker : ['forecolor_desc', 'mceForeColor'], + backcolor : ['backcolor_desc', 'HiliteColor'], + backcolorpicker : ['backcolor_desc', 'mceBackColor'], + charmap : ['charmap_desc', 'mceCharMap'], + visualaid : ['visualaid_desc', 'mceToggleVisualAid'], + anchor : ['anchor_desc', 'mceInsertAnchor'], + newdocument : ['newdocument_desc', 'mceNewDocument'], + blockquote : ['blockquote_desc', 'mceBlockQuote'] + }, + + stateControls : ['bold', 'italic', 'underline', 'strikethrough', 'bullist', 'numlist', 'justifyleft', 'justifycenter', 'justifyright', 'justifyfull', 'sub', 'sup', 'blockquote'], + + init : function(ed, url) { + var t = this, s, v, o; + + t.editor = ed; + t.url = url; + t.onResolveName = new tinymce.util.Dispatcher(this); + + ed.forcedHighContrastMode = ed.settings.detect_highcontrast && t._isHighContrast(); + ed.settings.skin = ed.forcedHighContrastMode ? 'highcontrast' : ed.settings.skin; + + // Default settings + t.settings = s = extend({ + theme_advanced_path : true, + theme_advanced_toolbar_location : 'bottom', + theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect", + theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code", + theme_advanced_buttons3 : "hr,removeformat,visualaid,|,sub,sup,|,charmap", + theme_advanced_blockformats : "p,address,pre,h1,h2,h3,h4,h5,h6", + theme_advanced_toolbar_align : "center", + theme_advanced_fonts : "Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats", + theme_advanced_more_colors : 1, + theme_advanced_row_height : 23, + theme_advanced_resize_horizontal : 1, + theme_advanced_resizing_use_cookie : 1, + theme_advanced_font_sizes : "1,2,3,4,5,6,7", + theme_advanced_font_selector : "span", + theme_advanced_show_current_color: 0, + readonly : ed.settings.readonly + }, ed.settings); + + // Setup default font_size_style_values + if (!s.font_size_style_values) + s.font_size_style_values = "8pt,10pt,12pt,14pt,18pt,24pt,36pt"; + + if (tinymce.is(s.theme_advanced_font_sizes, 'string')) { + s.font_size_style_values = tinymce.explode(s.font_size_style_values); + s.font_size_classes = tinymce.explode(s.font_size_classes || ''); + + // Parse string value + o = {}; + ed.settings.theme_advanced_font_sizes = s.theme_advanced_font_sizes; + each(ed.getParam('theme_advanced_font_sizes', '', 'hash'), function(v, k) { + var cl; + + if (k == v && v >= 1 && v <= 7) { + k = v + ' (' + t.sizes[v - 1] + 'pt)'; + cl = s.font_size_classes[v - 1]; + v = s.font_size_style_values[v - 1] || (t.sizes[v - 1] + 'pt'); + } + + if (/^\s*\./.test(v)) + cl = v.replace(/\./g, ''); + + o[k] = cl ? {'class' : cl} : {fontSize : v}; + }); + + s.theme_advanced_font_sizes = o; + } + + if ((v = s.theme_advanced_path_location) && v != 'none') + s.theme_advanced_statusbar_location = s.theme_advanced_path_location; + + if (s.theme_advanced_statusbar_location == 'none') + s.theme_advanced_statusbar_location = 0; + + if (ed.settings.content_css !== false) + ed.contentCSS.push(ed.baseURI.toAbsolute(url + "/skins/" + ed.settings.skin + "/content.css")); + + // Init editor + ed.onInit.add(function() { + if (!ed.settings.readonly) { + ed.onNodeChange.add(t._nodeChanged, t); + ed.onKeyUp.add(t._updateUndoStatus, t); + ed.onMouseUp.add(t._updateUndoStatus, t); + ed.dom.bind(ed.dom.getRoot(), 'dragend', function() { + t._updateUndoStatus(ed); + }); + } + }); + + ed.onSetProgressState.add(function(ed, b, ti) { + var co, id = ed.id, tb; + + if (b) { + t.progressTimer = setTimeout(function() { + co = ed.getContainer(); + co = co.insertBefore(DOM.create('DIV', {style : 'position:relative'}), co.firstChild); + tb = DOM.get(ed.id + '_tbl'); + + DOM.add(co, 'div', {id : id + '_blocker', 'class' : 'mceBlocker', style : {width : tb.clientWidth + 2, height : tb.clientHeight + 2}}); + DOM.add(co, 'div', {id : id + '_progress', 'class' : 'mceProgress', style : {left : tb.clientWidth / 2, top : tb.clientHeight / 2}}); + }, ti || 0); + } else { + DOM.remove(id + '_blocker'); + DOM.remove(id + '_progress'); + clearTimeout(t.progressTimer); + } + }); + + DOM.loadCSS(s.editor_css ? ed.documentBaseURI.toAbsolute(s.editor_css) : url + "/skins/" + ed.settings.skin + "/ui.css"); + + if (s.skin_variant) + DOM.loadCSS(url + "/skins/" + ed.settings.skin + "/ui_" + s.skin_variant + ".css"); + }, + + _isHighContrast : function() { + var actualColor, div = DOM.add(DOM.getRoot(), 'div', {'style': 'background-color: rgb(171,239,86);'}); + + actualColor = (DOM.getStyle(div, 'background-color', true) + '').toLowerCase().replace(/ /g, ''); + DOM.remove(div); + + return actualColor != 'rgb(171,239,86)' && actualColor != '#abef56'; + }, + + createControl : function(n, cf) { + var cd, c; + + if (c = cf.createControl(n)) + return c; + + switch (n) { + case "styleselect": + return this._createStyleSelect(); + + case "formatselect": + return this._createBlockFormats(); + + case "fontselect": + return this._createFontSelect(); + + case "fontsizeselect": + return this._createFontSizeSelect(); + + case "forecolor": + return this._createForeColorMenu(); + + case "backcolor": + return this._createBackColorMenu(); + } + + if ((cd = this.controls[n])) + return cf.createButton(n, {title : "advanced." + cd[0], cmd : cd[1], ui : cd[2], value : cd[3]}); + }, + + execCommand : function(cmd, ui, val) { + var f = this['_' + cmd]; + + if (f) { + f.call(this, ui, val); + return true; + } + + return false; + }, + + _importClasses : function(e) { + var ed = this.editor, ctrl = ed.controlManager.get('styleselect'); + + if (ctrl.getLength() == 0) { + each(ed.dom.getClasses(), function(o, idx) { + var name = 'style_' + idx; + + ed.formatter.register(name, { + inline : 'span', + attributes : {'class' : o['class']}, + selector : '*' + }); + + ctrl.add(o['class'], name); + }); + } + }, + + _createStyleSelect : function(n) { + var t = this, ed = t.editor, ctrlMan = ed.controlManager, ctrl; + + // Setup style select box + ctrl = ctrlMan.createListBox('styleselect', { + title : 'advanced.style_select', + onselect : function(name) { + var matches, formatNames = []; + + each(ctrl.items, function(item) { + formatNames.push(item.value); + }); + + ed.focus(); + ed.undoManager.add(); + + // Toggle off the current format + matches = ed.formatter.matchAll(formatNames); + if (!name || matches[0] == name) { + if (matches[0]) + ed.formatter.remove(matches[0]); + } else + ed.formatter.apply(name); + + ed.undoManager.add(); + ed.nodeChanged(); + + return false; // No auto select + } + }); + + // Handle specified format + ed.onInit.add(function() { + var counter = 0, formats = ed.getParam('style_formats'); + + if (formats) { + each(formats, function(fmt) { + var name, keys = 0; + + each(fmt, function() {keys++;}); + + if (keys > 1) { + name = fmt.name = fmt.name || 'style_' + (counter++); + ed.formatter.register(name, fmt); + ctrl.add(fmt.title, name); + } else + ctrl.add(fmt.title); + }); + } else { + each(ed.getParam('theme_advanced_styles', '', 'hash'), function(val, key) { + var name; + + if (val) { + name = 'style_' + (counter++); + + ed.formatter.register(name, { + inline : 'span', + classes : val, + selector : '*' + }); + + ctrl.add(t.editor.translate(key), name); + } + }); + } + }); + + // Auto import classes if the ctrl box is empty + if (ctrl.getLength() == 0) { + ctrl.onPostRender.add(function(ed, n) { + if (!ctrl.NativeListBox) { + Event.add(n.id + '_text', 'focus', t._importClasses, t); + Event.add(n.id + '_text', 'mousedown', t._importClasses, t); + Event.add(n.id + '_open', 'focus', t._importClasses, t); + Event.add(n.id + '_open', 'mousedown', t._importClasses, t); + } else + Event.add(n.id, 'focus', t._importClasses, t); + }); + } + + return ctrl; + }, + + _createFontSelect : function() { + var c, t = this, ed = t.editor; + + c = ed.controlManager.createListBox('fontselect', { + title : 'advanced.fontdefault', + onselect : function(v) { + var cur = c.items[c.selectedIndex]; + + if (!v && cur) { + ed.execCommand('FontName', false, cur.value); + return; + } + + ed.execCommand('FontName', false, v); + + // Fake selection, execCommand will fire a nodeChange and update the selection + c.select(function(sv) { + return v == sv; + }); + + if (cur && cur.value == v) { + c.select(null); + } + + return false; // No auto select + } + }); + + if (c) { + each(ed.getParam('theme_advanced_fonts', t.settings.theme_advanced_fonts, 'hash'), function(v, k) { + c.add(ed.translate(k), v, {style : v.indexOf('dings') == -1 ? 'font-family:' + v : ''}); + }); + } + + return c; + }, + + _createFontSizeSelect : function() { + var t = this, ed = t.editor, c, i = 0, cl = []; + + c = ed.controlManager.createListBox('fontsizeselect', {title : 'advanced.font_size', onselect : function(v) { + var cur = c.items[c.selectedIndex]; + + if (!v && cur) { + cur = cur.value; + + if (cur['class']) { + ed.formatter.toggle('fontsize_class', {value : cur['class']}); + ed.undoManager.add(); + ed.nodeChanged(); + } else { + ed.execCommand('FontSize', false, cur.fontSize); + } + + return; + } + + if (v['class']) { + ed.focus(); + ed.undoManager.add(); + ed.formatter.toggle('fontsize_class', {value : v['class']}); + ed.undoManager.add(); + ed.nodeChanged(); + } else + ed.execCommand('FontSize', false, v.fontSize); + + // Fake selection, execCommand will fire a nodeChange and update the selection + c.select(function(sv) { + return v == sv; + }); + + if (cur && (cur.value.fontSize == v.fontSize || cur.value['class'] == v['class'])) { + c.select(null); + } + + return false; // No auto select + }}); + + if (c) { + each(t.settings.theme_advanced_font_sizes, function(v, k) { + var fz = v.fontSize; + + if (fz >= 1 && fz <= 7) + fz = t.sizes[parseInt(fz) - 1] + 'pt'; + + c.add(k, v, {'style' : 'font-size:' + fz, 'class' : 'mceFontSize' + (i++) + (' ' + (v['class'] || ''))}); + }); + } + + return c; + }, + + _createBlockFormats : function() { + var c, fmts = { + p : 'advanced.paragraph', + address : 'advanced.address', + pre : 'advanced.pre', + h1 : 'advanced.h1', + h2 : 'advanced.h2', + h3 : 'advanced.h3', + h4 : 'advanced.h4', + h5 : 'advanced.h5', + h6 : 'advanced.h6', + div : 'advanced.div', + blockquote : 'advanced.blockquote', + code : 'advanced.code', + dt : 'advanced.dt', + dd : 'advanced.dd', + samp : 'advanced.samp' + }, t = this; + + c = t.editor.controlManager.createListBox('formatselect', {title : 'advanced.block', onselect : function(v) { + t.editor.execCommand('FormatBlock', false, v); + return false; + }}); + + if (c) { + each(t.editor.getParam('theme_advanced_blockformats', t.settings.theme_advanced_blockformats, 'hash'), function(v, k) { + c.add(t.editor.translate(k != v ? k : fmts[v]), v, {'class' : 'mce_formatPreview mce_' + v}); + }); + } + + return c; + }, + + _createForeColorMenu : function() { + var c, t = this, s = t.settings, o = {}, v; + + if (s.theme_advanced_more_colors) { + o.more_colors_func = function() { + t._mceColorPicker(0, { + color : c.value, + func : function(co) { + c.setColor(co); + } + }); + }; + } + + if (v = s.theme_advanced_text_colors) + o.colors = v; + + if (s.theme_advanced_default_foreground_color) + o.default_color = s.theme_advanced_default_foreground_color; + + o.title = 'advanced.forecolor_desc'; + o.cmd = 'ForeColor'; + o.scope = this; + + c = t.editor.controlManager.createColorSplitButton('forecolor', o); + + return c; + }, + + _createBackColorMenu : function() { + var c, t = this, s = t.settings, o = {}, v; + + if (s.theme_advanced_more_colors) { + o.more_colors_func = function() { + t._mceColorPicker(0, { + color : c.value, + func : function(co) { + c.setColor(co); + } + }); + }; + } + + if (v = s.theme_advanced_background_colors) + o.colors = v; + + if (s.theme_advanced_default_background_color) + o.default_color = s.theme_advanced_default_background_color; + + o.title = 'advanced.backcolor_desc'; + o.cmd = 'HiliteColor'; + o.scope = this; + + c = t.editor.controlManager.createColorSplitButton('backcolor', o); + + return c; + }, + + renderUI : function(o) { + var n, ic, tb, t = this, ed = t.editor, s = t.settings, sc, p, nl; + + if (ed.settings) { + ed.settings.aria_label = s.aria_label + ed.getLang('advanced.help_shortcut'); + } + + // TODO: ACC Should have an aria-describedby attribute which is user-configurable to describe what this field is actually for. + // Maybe actually inherit it from the original textara? + n = p = DOM.create('span', {role : 'application', 'aria-labelledby' : ed.id + '_voice', id : ed.id + '_parent', 'class' : 'mceEditor ' + ed.settings.skin + 'Skin' + (s.skin_variant ? ' ' + ed.settings.skin + 'Skin' + t._ufirst(s.skin_variant) : '')}); + DOM.add(n, 'span', {'class': 'mceVoiceLabel', 'style': 'display:none;', id: ed.id + '_voice'}, s.aria_label); + + if (!DOM.boxModel) + n = DOM.add(n, 'div', {'class' : 'mceOldBoxModel'}); + + n = sc = DOM.add(n, 'table', {role : "presentation", id : ed.id + '_tbl', 'class' : 'mceLayout', cellSpacing : 0, cellPadding : 0}); + n = tb = DOM.add(n, 'tbody'); + + switch ((s.theme_advanced_layout_manager || '').toLowerCase()) { + case "rowlayout": + ic = t._rowLayout(s, tb, o); + break; + + case "customlayout": + ic = ed.execCallback("theme_advanced_custom_layout", s, tb, o, p); + break; + + default: + ic = t._simpleLayout(s, tb, o, p); + } + + n = o.targetNode; + + // Add classes to first and last TRs + nl = sc.rows; + DOM.addClass(nl[0], 'mceFirst'); + DOM.addClass(nl[nl.length - 1], 'mceLast'); + + // Add classes to first and last TDs + each(DOM.select('tr', tb), function(n) { + DOM.addClass(n.firstChild, 'mceFirst'); + DOM.addClass(n.childNodes[n.childNodes.length - 1], 'mceLast'); + }); + + if (DOM.get(s.theme_advanced_toolbar_container)) + DOM.get(s.theme_advanced_toolbar_container).appendChild(p); + else + DOM.insertAfter(p, n); + + Event.add(ed.id + '_path_row', 'click', function(e) { + e = e.target; + + if (e.nodeName == 'A') { + t._sel(e.className.replace(/^.*mcePath_([0-9]+).*$/, '$1')); + + return Event.cancel(e); + } + }); +/* + if (DOM.get(ed.id + '_path_row')) { + Event.add(ed.id + '_tbl', 'mouseover', function(e) { + var re; + + e = e.target; + + if (e.nodeName == 'SPAN' && DOM.hasClass(e.parentNode, 'mceButton')) { + re = DOM.get(ed.id + '_path_row'); + t.lastPath = re.innerHTML; + DOM.setHTML(re, e.parentNode.title); + } + }); + + Event.add(ed.id + '_tbl', 'mouseout', function(e) { + if (t.lastPath) { + DOM.setHTML(ed.id + '_path_row', t.lastPath); + t.lastPath = 0; + } + }); + } +*/ + + if (!ed.getParam('accessibility_focus')) + Event.add(DOM.add(p, 'a', {href : '#'}, '<!-- IE -->'), 'focus', function() {tinyMCE.get(ed.id).focus();}); + + if (s.theme_advanced_toolbar_location == 'external') + o.deltaHeight = 0; + + t.deltaHeight = o.deltaHeight; + o.targetNode = null; + + ed.onKeyDown.add(function(ed, evt) { + var DOM_VK_F10 = 121, DOM_VK_F11 = 122; + + if (evt.altKey) { + if (evt.keyCode === DOM_VK_F10) { + window.focus(); + t.toolbarGroup.focus(); + return Event.cancel(evt); + } else if (evt.keyCode === DOM_VK_F11) { + DOM.get(ed.id + '_path_row').focus(); + return Event.cancel(evt); + } + } + }); + + // alt+0 is the UK recommended shortcut for accessing the list of access controls. + ed.addShortcut('alt+0', '', 'mceShortcuts', t); + + return { + iframeContainer : ic, + editorContainer : ed.id + '_parent', + sizeContainer : sc, + deltaHeight : o.deltaHeight + }; + }, + + getInfo : function() { + return { + longname : 'Advanced theme', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + version : tinymce.majorVersion + "." + tinymce.minorVersion + } + }, + + resizeBy : function(dw, dh) { + var e = DOM.get(this.editor.id + '_ifr'); + + this.resizeTo(e.clientWidth + dw, e.clientHeight + dh); + }, + + resizeTo : function(w, h, store) { + var ed = this.editor, s = this.settings, e = DOM.get(ed.id + '_tbl'), ifr = DOM.get(ed.id + '_ifr'); + + // Boundery fix box + w = Math.max(s.theme_advanced_resizing_min_width || 100, w); + h = Math.max(s.theme_advanced_resizing_min_height || 100, h); + w = Math.min(s.theme_advanced_resizing_max_width || 0xFFFF, w); + h = Math.min(s.theme_advanced_resizing_max_height || 0xFFFF, h); + + // Resize iframe and container + DOM.setStyle(e, 'height', ''); + DOM.setStyle(ifr, 'height', h); + + if (s.theme_advanced_resize_horizontal) { + DOM.setStyle(e, 'width', ''); + DOM.setStyle(ifr, 'width', w); + + // Make sure that the size is never smaller than the over all ui + if (w < e.clientWidth) { + w = e.clientWidth; + DOM.setStyle(ifr, 'width', e.clientWidth); + } + } + + // Store away the size + if (store && s.theme_advanced_resizing_use_cookie) { + Cookie.setHash("TinyMCE_" + ed.id + "_size", { + cw : w, + ch : h + }); + } + }, + + destroy : function() { + var id = this.editor.id; + + Event.clear(id + '_resize'); + Event.clear(id + '_path_row'); + Event.clear(id + '_external_close'); + }, + + // Internal functions + + _simpleLayout : function(s, tb, o, p) { + var t = this, ed = t.editor, lo = s.theme_advanced_toolbar_location, sl = s.theme_advanced_statusbar_location, n, ic, etb, c; + + if (s.readonly) { + n = DOM.add(tb, 'tr'); + n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'}); + return ic; + } + + // Create toolbar container at top + if (lo == 'top') + t._addToolbars(tb, o); + + // Create external toolbar + if (lo == 'external') { + n = c = DOM.create('div', {style : 'position:relative'}); + n = DOM.add(n, 'div', {id : ed.id + '_external', 'class' : 'mceExternalToolbar'}); + DOM.add(n, 'a', {id : ed.id + '_external_close', href : 'javascript:;', 'class' : 'mceExternalClose'}); + n = DOM.add(n, 'table', {id : ed.id + '_tblext', cellSpacing : 0, cellPadding : 0}); + etb = DOM.add(n, 'tbody'); + + if (p.firstChild.className == 'mceOldBoxModel') + p.firstChild.appendChild(c); + else + p.insertBefore(c, p.firstChild); + + t._addToolbars(etb, o); + + ed.onMouseUp.add(function() { + var e = DOM.get(ed.id + '_external'); + DOM.show(e); + + DOM.hide(lastExtID); + + var f = Event.add(ed.id + '_external_close', 'click', function() { + DOM.hide(ed.id + '_external'); + Event.remove(ed.id + '_external_close', 'click', f); + }); + + DOM.show(e); + DOM.setStyle(e, 'top', 0 - DOM.getRect(ed.id + '_tblext').h - 1); + + // Fixes IE rendering bug + DOM.hide(e); + DOM.show(e); + e.style.filter = ''; + + lastExtID = ed.id + '_external'; + + e = null; + }); + } + + if (sl == 'top') + t._addStatusBar(tb, o); + + // Create iframe container + if (!s.theme_advanced_toolbar_container) { + n = DOM.add(tb, 'tr'); + n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'}); + } + + // Create toolbar container at bottom + if (lo == 'bottom') + t._addToolbars(tb, o); + + if (sl == 'bottom') + t._addStatusBar(tb, o); + + return ic; + }, + + _rowLayout : function(s, tb, o) { + var t = this, ed = t.editor, dc, da, cf = ed.controlManager, n, ic, to, a; + + dc = s.theme_advanced_containers_default_class || ''; + da = s.theme_advanced_containers_default_align || 'center'; + + each(explode(s.theme_advanced_containers || ''), function(c, i) { + var v = s['theme_advanced_container_' + c] || ''; + + switch (c.toLowerCase()) { + case 'mceeditor': + n = DOM.add(tb, 'tr'); + n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'}); + break; + + case 'mceelementpath': + t._addStatusBar(tb, o); + break; + + default: + a = (s['theme_advanced_container_' + c + '_align'] || da).toLowerCase(); + a = 'mce' + t._ufirst(a); + + n = DOM.add(DOM.add(tb, 'tr'), 'td', { + 'class' : 'mceToolbar ' + (s['theme_advanced_container_' + c + '_class'] || dc) + ' ' + a || da + }); + + to = cf.createToolbar("toolbar" + i); + t._addControls(v, to); + DOM.setHTML(n, to.renderHTML()); + o.deltaHeight -= s.theme_advanced_row_height; + } + }); + + return ic; + }, + + _addControls : function(v, tb) { + var t = this, s = t.settings, di, cf = t.editor.controlManager; + + if (s.theme_advanced_disable && !t._disabled) { + di = {}; + + each(explode(s.theme_advanced_disable), function(v) { + di[v] = 1; + }); + + t._disabled = di; + } else + di = t._disabled; + + each(explode(v), function(n) { + var c; + + if (di && di[n]) + return; + + // Compatiblity with 2.x + if (n == 'tablecontrols') { + each(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"], function(n) { + n = t.createControl(n, cf); + + if (n) + tb.add(n); + }); + + return; + } + + c = t.createControl(n, cf); + + if (c) + tb.add(c); + }); + }, + + _addToolbars : function(c, o) { + var t = this, i, tb, ed = t.editor, s = t.settings, v, cf = ed.controlManager, di, n, h = [], a, toolbarGroup; + + toolbarGroup = cf.createToolbarGroup('toolbargroup', { + 'name': ed.getLang('advanced.toolbar'), + 'tab_focus_toolbar':ed.getParam('theme_advanced_tab_focus_toolbar') + }); + + t.toolbarGroup = toolbarGroup; + + a = s.theme_advanced_toolbar_align.toLowerCase(); + a = 'mce' + t._ufirst(a); + + n = DOM.add(DOM.add(c, 'tr', {role: 'presentation'}), 'td', {'class' : 'mceToolbar ' + a, "role":"presentation"}); + + // Create toolbar and add the controls + for (i=1; (v = s['theme_advanced_buttons' + i]); i++) { + tb = cf.createToolbar("toolbar" + i, {'class' : 'mceToolbarRow' + i}); + + if (s['theme_advanced_buttons' + i + '_add']) + v += ',' + s['theme_advanced_buttons' + i + '_add']; + + if (s['theme_advanced_buttons' + i + '_add_before']) + v = s['theme_advanced_buttons' + i + '_add_before'] + ',' + v; + + t._addControls(v, tb); + toolbarGroup.add(tb); + + o.deltaHeight -= s.theme_advanced_row_height; + } + h.push(toolbarGroup.renderHTML()); + h.push(DOM.createHTML('a', {href : '#', accesskey : 'z', title : ed.getLang("advanced.toolbar_focus"), onfocus : 'tinyMCE.getInstanceById(\'' + ed.id + '\').focus();'}, '<!-- IE -->')); + DOM.setHTML(n, h.join('')); + }, + + _addStatusBar : function(tb, o) { + var n, t = this, ed = t.editor, s = t.settings, r, mf, me, td; + + n = DOM.add(tb, 'tr'); + n = td = DOM.add(n, 'td', {'class' : 'mceStatusbar'}); + n = DOM.add(n, 'div', {id : ed.id + '_path_row', 'role': 'group', 'aria-labelledby': ed.id + '_path_voice'}); + if (s.theme_advanced_path) { + DOM.add(n, 'span', {id: ed.id + '_path_voice'}, ed.translate('advanced.path')); + DOM.add(n, 'span', {}, ': '); + } else { + DOM.add(n, 'span', {}, '&#160;'); + } + + + if (s.theme_advanced_resizing) { + DOM.add(td, 'a', {id : ed.id + '_resize', href : 'javascript:;', onclick : "return false;", 'class' : 'mceResize', tabIndex:"-1"}); + + if (s.theme_advanced_resizing_use_cookie) { + ed.onPostRender.add(function() { + var o = Cookie.getHash("TinyMCE_" + ed.id + "_size"), c = DOM.get(ed.id + '_tbl'); + + if (!o) + return; + + t.resizeTo(o.cw, o.ch); + }); + } + + ed.onPostRender.add(function() { + Event.add(ed.id + '_resize', 'click', function(e) { + e.preventDefault(); + }); + + Event.add(ed.id + '_resize', 'mousedown', function(e) { + var mouseMoveHandler1, mouseMoveHandler2, + mouseUpHandler1, mouseUpHandler2, + startX, startY, startWidth, startHeight, width, height, ifrElm; + + function resizeOnMove(e) { + e.preventDefault(); + + width = startWidth + (e.screenX - startX); + height = startHeight + (e.screenY - startY); + + t.resizeTo(width, height); + }; + + function endResize(e) { + // Stop listening + Event.remove(DOM.doc, 'mousemove', mouseMoveHandler1); + Event.remove(ed.getDoc(), 'mousemove', mouseMoveHandler2); + Event.remove(DOM.doc, 'mouseup', mouseUpHandler1); + Event.remove(ed.getDoc(), 'mouseup', mouseUpHandler2); + + width = startWidth + (e.screenX - startX); + height = startHeight + (e.screenY - startY); + t.resizeTo(width, height, true); + }; + + e.preventDefault(); + + // Get the current rect size + startX = e.screenX; + startY = e.screenY; + ifrElm = DOM.get(t.editor.id + '_ifr'); + startWidth = width = ifrElm.clientWidth; + startHeight = height = ifrElm.clientHeight; + + // Register envent handlers + mouseMoveHandler1 = Event.add(DOM.doc, 'mousemove', resizeOnMove); + mouseMoveHandler2 = Event.add(ed.getDoc(), 'mousemove', resizeOnMove); + mouseUpHandler1 = Event.add(DOM.doc, 'mouseup', endResize); + mouseUpHandler2 = Event.add(ed.getDoc(), 'mouseup', endResize); + }); + }); + } + + o.deltaHeight -= 21; + n = tb = null; + }, + + _updateUndoStatus : function(ed) { + var cm = ed.controlManager, um = ed.undoManager; + + cm.setDisabled('undo', !um.hasUndo() && !um.typing); + cm.setDisabled('redo', !um.hasRedo()); + }, + + _nodeChanged : function(ed, cm, n, co, ob) { + var t = this, p, de = 0, v, c, s = t.settings, cl, fz, fn, fc, bc, formatNames, matches; + + tinymce.each(t.stateControls, function(c) { + cm.setActive(c, ed.queryCommandState(t.controls[c][1])); + }); + + function getParent(name) { + var i, parents = ob.parents, func = name; + + if (typeof(name) == 'string') { + func = function(node) { + return node.nodeName == name; + }; + } + + for (i = 0; i < parents.length; i++) { + if (func(parents[i])) + return parents[i]; + } + }; + + cm.setActive('visualaid', ed.hasVisual); + t._updateUndoStatus(ed); + cm.setDisabled('outdent', !ed.queryCommandState('Outdent')); + + p = getParent('A'); + if (c = cm.get('link')) { + if (!p || !p.name) { + c.setDisabled(!p && co); + c.setActive(!!p); + } + } + + if (c = cm.get('unlink')) { + c.setDisabled(!p && co); + c.setActive(!!p && !p.name); + } + + if (c = cm.get('anchor')) { + c.setActive(!co && !!p && p.name); + } + + p = getParent('IMG'); + if (c = cm.get('image')) + c.setActive(!co && !!p && n.className.indexOf('mceItem') == -1); + + if (c = cm.get('styleselect')) { + t._importClasses(); + + formatNames = []; + each(c.items, function(item) { + formatNames.push(item.value); + }); + + matches = ed.formatter.matchAll(formatNames); + c.select(matches[0]); + } + + if (c = cm.get('formatselect')) { + p = getParent(DOM.isBlock); + + if (p) + c.select(p.nodeName.toLowerCase()); + } + + // Find out current fontSize, fontFamily and fontClass + getParent(function(n) { + if (n.nodeName === 'SPAN') { + if (!cl && n.className) + cl = n.className; + } + + if (ed.dom.is(n, s.theme_advanced_font_selector)) { + if (!fz && n.style.fontSize) + fz = n.style.fontSize; + + if (!fn && n.style.fontFamily) + fn = n.style.fontFamily.replace(/[\"\']+/g, '').replace(/^([^,]+).*/, '$1').toLowerCase(); + + if (!fc && n.style.color) + fc = n.style.color; + + if (!bc && n.style.backgroundColor) + bc = n.style.backgroundColor; + } + + return false; + }); + + if (c = cm.get('fontselect')) { + c.select(function(v) { + return v.replace(/^([^,]+).*/, '$1').toLowerCase() == fn; + }); + } + + // Select font size + if (c = cm.get('fontsizeselect')) { + // Use computed style + if (s.theme_advanced_runtime_fontsize && !fz && !cl) + fz = ed.dom.getStyle(n, 'fontSize', true); + + c.select(function(v) { + if (v.fontSize && v.fontSize === fz) + return true; + + if (v['class'] && v['class'] === cl) + return true; + }); + } + + if (s.theme_advanced_show_current_color) { + function updateColor(controlId, color) { + if (c = cm.get(controlId)) { + if (!color) + color = c.settings.default_color; + if (color !== c.value) { + c.displayColor(color); + } + } + } + updateColor('forecolor', fc); + updateColor('backcolor', bc); + } + + if (s.theme_advanced_show_current_color) { + function updateColor(controlId, color) { + if (c = cm.get(controlId)) { + if (!color) + color = c.settings.default_color; + if (color !== c.value) { + c.displayColor(color); + } + } + }; + + updateColor('forecolor', fc); + updateColor('backcolor', bc); + } + + if (s.theme_advanced_path && s.theme_advanced_statusbar_location) { + p = DOM.get(ed.id + '_path') || DOM.add(ed.id + '_path_row', 'span', {id : ed.id + '_path'}); + + if (t.statusKeyboardNavigation) { + t.statusKeyboardNavigation.destroy(); + t.statusKeyboardNavigation = null; + } + + DOM.setHTML(p, ''); + + getParent(function(n) { + var na = n.nodeName.toLowerCase(), u, pi, ti = ''; + + // Ignore non element and bogus/hidden elements + if (n.nodeType != 1 || na === 'br' || n.getAttribute('data-mce-bogus') || DOM.hasClass(n, 'mceItemHidden') || DOM.hasClass(n, 'mceItemRemoved')) + return; + + // Handle prefix + if (tinymce.isIE && n.scopeName !== 'HTML') + na = n.scopeName + ':' + na; + + // Remove internal prefix + na = na.replace(/mce\:/g, ''); + + // Handle node name + switch (na) { + case 'b': + na = 'strong'; + break; + + case 'i': + na = 'em'; + break; + + case 'img': + if (v = DOM.getAttrib(n, 'src')) + ti += 'src: ' + v + ' '; + + break; + + case 'a': + if (v = DOM.getAttrib(n, 'name')) { + ti += 'name: ' + v + ' '; + na += '#' + v; + } + + if (v = DOM.getAttrib(n, 'href')) + ti += 'href: ' + v + ' '; + + break; + + case 'font': + if (v = DOM.getAttrib(n, 'face')) + ti += 'font: ' + v + ' '; + + if (v = DOM.getAttrib(n, 'size')) + ti += 'size: ' + v + ' '; + + if (v = DOM.getAttrib(n, 'color')) + ti += 'color: ' + v + ' '; + + break; + + case 'span': + if (v = DOM.getAttrib(n, 'style')) + ti += 'style: ' + v + ' '; + + break; + } + + if (v = DOM.getAttrib(n, 'id')) + ti += 'id: ' + v + ' '; + + if (v = n.className) { + v = v.replace(/\b\s*(webkit|mce|Apple-)\w+\s*\b/g, '') + + if (v) { + ti += 'class: ' + v + ' '; + + if (DOM.isBlock(n) || na == 'img' || na == 'span') + na += '.' + v; + } + } + + na = na.replace(/(html:)/g, ''); + na = {name : na, node : n, title : ti}; + t.onResolveName.dispatch(t, na); + ti = na.title; + na = na.name; + + //u = "javascript:tinymce.EditorManager.get('" + ed.id + "').theme._sel('" + (de++) + "');"; + pi = DOM.create('a', {'href' : "javascript:;", role: 'button', onmousedown : "return false;", title : ti, 'class' : 'mcePath_' + (de++)}, na); + + if (p.hasChildNodes()) { + p.insertBefore(DOM.create('span', {'aria-hidden': 'true'}, '\u00a0\u00bb '), p.firstChild); + p.insertBefore(pi, p.firstChild); + } else + p.appendChild(pi); + }, ed.getBody()); + + if (DOM.select('a', p).length > 0) { + t.statusKeyboardNavigation = new tinymce.ui.KeyboardNavigation({ + root: ed.id + "_path_row", + items: DOM.select('a', p), + excludeFromTabOrder: true, + onCancel: function() { + ed.focus(); + } + }, DOM); + } + } + }, + + // Commands gets called by execCommand + + _sel : function(v) { + this.editor.execCommand('mceSelectNodeDepth', false, v); + }, + + _mceInsertAnchor : function(ui, v) { + var ed = this.editor; + + ed.windowManager.open({ + url : this.url + '/anchor.htm', + width : 320 + parseInt(ed.getLang('advanced.anchor_delta_width', 0)), + height : 90 + parseInt(ed.getLang('advanced.anchor_delta_height', 0)), + inline : true + }, { + theme_url : this.url + }); + }, + + _mceCharMap : function() { + var ed = this.editor; + + ed.windowManager.open({ + url : this.url + '/charmap.htm', + width : 550 + parseInt(ed.getLang('advanced.charmap_delta_width', 0)), + height : 250 + parseInt(ed.getLang('advanced.charmap_delta_height', 0)), + inline : true + }, { + theme_url : this.url + }); + }, + + _mceHelp : function() { + var ed = this.editor; + + ed.windowManager.open({ + url : this.url + '/about.htm', + width : 480, + height : 380, + inline : true + }, { + theme_url : this.url + }); + }, + + _mceShortcuts : function() { + var ed = this.editor; + ed.windowManager.open({ + url: this.url + '/shortcuts.htm', + width: 480, + height: 380, + inline: true + }, { + theme_url: this.url + }); + }, + + _mceColorPicker : function(u, v) { + var ed = this.editor; + + v = v || {}; + + ed.windowManager.open({ + url : this.url + '/color_picker.htm', + width : 375 + parseInt(ed.getLang('advanced.colorpicker_delta_width', 0)), + height : 250 + parseInt(ed.getLang('advanced.colorpicker_delta_height', 0)), + close_previous : false, + inline : true + }, { + input_color : v.color, + func : v.func, + theme_url : this.url + }); + }, + + _mceCodeEditor : function(ui, val) { + var ed = this.editor; + + ed.windowManager.open({ + url : this.url + '/source_editor.htm', + width : parseInt(ed.getParam("theme_advanced_source_editor_width", 720)), + height : parseInt(ed.getParam("theme_advanced_source_editor_height", 580)), + inline : true, + resizable : true, + maximizable : true + }, { + theme_url : this.url + }); + }, + + _mceImage : function(ui, val) { + var ed = this.editor; + + // Internal image object like a flash placeholder + if (ed.dom.getAttrib(ed.selection.getNode(), 'class').indexOf('mceItem') != -1) + return; + + ed.windowManager.open({ + url : this.url + '/image.htm', + width : 355 + parseInt(ed.getLang('advanced.image_delta_width', 0)), + height : 275 + parseInt(ed.getLang('advanced.image_delta_height', 0)), + inline : true + }, { + theme_url : this.url + }); + }, + + _mceLink : function(ui, val) { + var ed = this.editor; + + ed.windowManager.open({ + url : this.url + '/link.htm', + width : 310 + parseInt(ed.getLang('advanced.link_delta_width', 0)), + height : 200 + parseInt(ed.getLang('advanced.link_delta_height', 0)), + inline : true + }, { + theme_url : this.url + }); + }, + + _mceNewDocument : function() { + var ed = this.editor; + + ed.windowManager.confirm('advanced.newdocument', function(s) { + if (s) + ed.execCommand('mceSetContent', false, ''); + }); + }, + + _mceForeColor : function() { + var t = this; + + this._mceColorPicker(0, { + color: t.fgColor, + func : function(co) { + t.fgColor = co; + t.editor.execCommand('ForeColor', false, co); + } + }); + }, + + _mceBackColor : function() { + var t = this; + + this._mceColorPicker(0, { + color: t.bgColor, + func : function(co) { + t.bgColor = co; + t.editor.execCommand('HiliteColor', false, co); + } + }); + }, + + _ufirst : function(s) { + return s.substring(0, 1).toUpperCase() + s.substring(1); + } + }); + + tinymce.ThemeManager.add('advanced', tinymce.themes.AdvancedTheme); +}(tinymce)); diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/image.htm b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/image.htm new file mode 100644 index 0000000..b8ba729 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/image.htm @@ -0,0 +1,80 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.image_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="js/image.js"></script> +</head> +<body id="image" style="display: none"> +<form onsubmit="ImageDialog.update();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.image_title}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="nowrap"><label for="src">{#advanced_dlg.image_src}</label></td> + <td><table border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="src" name="src" type="text" class="mceFocus" value="" style="width: 200px" onchange="ImageDialog.getImageData();" /></td> + <td id="srcbrowsercontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td><label for="image_list">{#advanced_dlg.image_list}</label></td> + <td><select id="image_list" name="image_list" onchange="document.getElementById('src').value=this.options[this.selectedIndex].value;document.getElementById('alt').value=this.options[this.selectedIndex].text;"></select></td> + </tr> + <tr> + <td class="nowrap"><label for="alt">{#advanced_dlg.image_alt}</label></td> + <td><input id="alt" name="alt" type="text" value="" style="width: 200px" /></td> + </tr> + <tr> + <td class="nowrap"><label for="align">{#advanced_dlg.image_align}</label></td> + <td><select id="align" name="align" onchange="ImageDialog.updateStyle();"> + <option value="">{#not_set}</option> + <option value="baseline">{#advanced_dlg.image_align_baseline}</option> + <option value="top">{#advanced_dlg.image_align_top}</option> + <option value="middle">{#advanced_dlg.image_align_middle}</option> + <option value="bottom">{#advanced_dlg.image_align_bottom}</option> + <option value="text-top">{#advanced_dlg.image_align_texttop}</option> + <option value="text-bottom">{#advanced_dlg.image_align_textbottom}</option> + <option value="left">{#advanced_dlg.image_align_left}</option> + <option value="right">{#advanced_dlg.image_align_right}</option> + </select></td> + </tr> + <tr> + <td class="nowrap"><label for="width">{#advanced_dlg.image_dimensions}</label></td> + <td><input id="width" name="width" type="text" value="" size="3" maxlength="5" /> + x + <input id="height" name="height" type="text" value="" size="3" maxlength="5" /></td> + </tr> + <tr> + <td class="nowrap"><label for="border">{#advanced_dlg.image_border}</label></td> + <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td> + </tr> + <tr> + <td class="nowrap"><label for="vspace">{#advanced_dlg.image_vspace}</label></td> + <td><input id="vspace" name="vspace" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td> + </tr> + <tr> + <td class="nowrap"><label for="hspace">{#advanced_dlg.image_hspace}</label></td> + <td><input id="hspace" name="hspace" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td> + </tr> + </table> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/colorpicker.jpg b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/colorpicker.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b1a377aba7784d3a0a0fabb4d22b8114cde25ace GIT binary patch literal 2584 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 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/flash.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/flash.gif new file mode 100644 index 0000000000000000000000000000000000000000..dec3f7c7028df98657860529461af29b8793601c GIT binary patch literal 239 zcmV<L01*F2Nk%w1VH5xq0P_z3YJHAwilWKS*;Z<L?e6iex5E`&f8F2Yf{&g3{rv|x zTAiq{x5Lr`C`yW(uK)l5A^8La000jFEC2ui02BZe06+ws@X1N5eMlUVdNW3$9SmZT z&ejo!!yFgE0ODZ_#R4!yB?`cXLQ!DZ4u!(yLC_5bfJHCn&~OrjA?P4*OeFwKCm|dv zi~>M~p;I&fgwbZVtlRJPxC7uw?yFxEX;uVr4IeWCJ^(5m4hjYVM>G^+2V)FnXE$mS p86yHh03AmHCKD}bWutOkFce4&0zF5CG_Myp4hRT+ig>^g06S0cRV@Gj literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/icons.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/icons.gif new file mode 100644 index 0000000000000000000000000000000000000000..641a9e3d314f4ea051692a2274aeb281456f5df9 GIT binary patch literal 11790 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 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/iframe.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/iframe.gif new file mode 100644 index 0000000000000000000000000000000000000000..410c7ad084db698e9f35e3230233aa4040682566 GIT binary patch literal 600 zcmZ?wbhEHb6krfwcoxm@|NsB$<##6SeDUYszh8g<{{H*-%a7k_-3KZc-T3+YPwBiX zzyAIE^Y`z!U%$Wp{QdX;|FQ*Fw;jIy{pasbUw?o3{yVB>Q_sR<KmYuB{`zY~^~S1Y zciw#Z@#p{luRnhO{QLLE-@o7g{7Got_4nVux1YbidjG9*@y-0{XY!|=4lZ6<Jm+Fq z+1kX`-QR!z2`*lB@A;>gx-G9iegFLZcfrha#d9w;%sU=Zx~6K$tw~$%z4`#O^Y@3Z zKV#~)MpSKh@#b63l#}6=>yq2|{`&JLqwny)|NnC)o%r$l&-Y)yKYjo8?#quSuRaGB zt_&<%`RV)bl#YEr{`~p)?RU|v^Y1_Z`u*?Ux8J`*N>>+5JlMAOZr+qr@y$D{mfVhO z+zt#7208-8pDc_F4ABfaAUi>E!oa?@A-bu#r8Qd6oKeb*Lx9UTz)0QBL@+vxY38ii zvqGa87c5+~h&?)zVa3W-D;=U$88}^qMBJ^ERU|z17!;#97+4%Rd1XcXJq#>t8KR;E z7<gD&#C7=C421)w8LXqZ7?@cv%J~Uh^ATncjn;g?{P2>zr5i6BgH5y=gAD)sAQlGB zh8au?j!n~E(Pks?@!j1fR&j<cH=I(Yx`udfix4PUaFR<$Un}Lu!X_>*RWY8GF(-=x H6d0@lT&58X literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/pagebreak.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/pagebreak.gif new file mode 100644 index 0000000000000000000000000000000000000000..acdf4085f3068c4c0a1d6855f4b80dae8bac3068 GIT binary patch literal 325 zcmV-L0lNN2Nk%w1VPpUd0J9GO`>v<{=;ru;boX6P{`2zsmyZ3>&HK5t_;hIbi-G;z z+4`cI{KdfcXj}GCLjV8&A^8LW000jFEC2ui0Av6R000E?@X1N5y*TU5yZ>M)j$|1M z4Ouvb$pHu>IW8BZq|n;U0s@T!VM5~w1_+1X!EiVl!&PITYdjT!ffYfpt{jAfv%qvh zA63WUHSlr7LkeyaV4(pM0f50(II?RD4RtMg4-E+tFhdAy5{3c=0}3Bg9Y8`B2To20 zR%SO62L%9}0H+dzoKB$+2TOwzUrwi{XiBM^4V#>63q3!LsU3u93zH8CdwqY%62;1g z0g8ze$k93lWExp`CUe|K4qOWk17ZeJ0|5pDP6+}};{>bI@lOWj=kf}r2sHp7w9-Ie XK%9UG6W(*AX-vY05F<*&5CH%?Gwy&_ literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/quicktime.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/quicktime.gif new file mode 100644 index 0000000000000000000000000000000000000000..8f10e7aa6b6ab40ee69a1a41a961c092168d6fda GIT binary patch literal 301 zcmV+|0n+|QNk%w1VGsZi0Q4UK+~)L6v+~s9^fsC5ZpZP=*zu3F=Jxpf8k_5u%JNv6 z=md-84VLU4w)kSE=yI&-yw>b=v+SqE?+kq47pC+YrR?bJ^yu>Zyvpn;hTp*6^mM!O zu+8!}sO$`q<p2NwA^8La0018VEC2ui01yBW06+z*;3tYl0b#{4ii5Xs;uR2=_;^fo zWDC-1qryV~Stvvritq6-7#;xx!V|!VI2kE}qGSvd0+C|D*aRJj0HEVCNTwOcN@Vch z03!gQ!RL1p348;2Pa6>%8%`=C5EEn#1d#z95FHtK5(^#(cp^e+Y!d=4FCrFbY9A3U z4-O0-4kHJPJ2(jk13n5879s!!3Q`V>8VwW`9my3H#|R8ZD+fdx0E-+693cQZ;!k;* literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/realmedia.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/realmedia.gif new file mode 100644 index 0000000000000000000000000000000000000000..fdfe0b9ac05869ae845fdd828eaad97cc0c69dbc GIT binary patch literal 439 zcmV;o0Z9HwNk%w1VI=?(0K^{vQcz8xz}f&njBB06v9GQ`Jv%NdDHCI&z`wqZw$(Lw zuFTBL!Pe#<92tv>h)9OE1Xh}vnVEHSaeb-GByg#tqM_B*)YRkdSdqTu<Kq($4eIgt z07{c)W@Z2Y0RR90A^8LW0018VEC2ui03`qt000I5;3tmX6%3D}JVU~ea4d`4L_vbU z?R!oQuNiDZ90d+Lh@ur}CQvxRV<Qx03Jr;9kQ`iu8)s06@OUDh#O^TuSUR0br;y1w z00jxcDls$+9Rwc|9vTZ9NC#ge4rUr200@t8W`Y171r7xs4H=gP8w@)SF#sAG4s`|| z1`!brkZu*Tn+6N39Ur0`7(=T7A`7Pl003~V4I0GBk&kGI90yb*k{%9LupJo$4h|NN zbOg?g8W|#L917Eeg?l0d$&Vfq8<!de2B!p<1q2IQYbH?1u;3qw4G1a_F!zptg$xJ| zEkIx)q7e!?4qyntfXKQ4DFjvllRyE792_7taG3BR07ec2){PXxV8R0m2M#27utPzc hnLsyCNWv1RQ6oJU9W}ZE0)zxhqYhA@G%AS@06S<cl~n)$ literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/shockwave.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/shockwave.gif new file mode 100644 index 0000000000000000000000000000000000000000..9314d044709c9845876e08003cf94526fd69177f GIT binary patch literal 384 zcmZ?wbhEHb6lD-#_^Qe9?Af#b->&}n`s(k;lb>H+`#+Q6|3c{>OLTv23;utm>DSfy zuOD3adm!iUuGar)4FAhzel5=UwZ7*6(K(+k@BP_g{o}}@k7u_2k7W2iGwlom!+#Z( z|Hj5w_4MwTo8QaHxm#EFYX1DUOO|}vvgQBb!_ST${rmj+`+Fep|C$j4HGtwz7FGrZ zO$Hs1VIV&_u+2R%#bJV$RKJIcL*N7vss0Y-EsB{gGlSJaTr>sRLKbLj5HMTpyK;)l zJcfpaMYltBZdEK6Kht6+BPy*VtthFMtIoqFC=#Tu$e^eaDXCC7U0vOYOJjNk(;P<O z+?*WGIXu2>!V<jVVxdx#m$@=9ujFJ8P~>agC#fQ*?7otVO)-#9rK#nB%ry4`E_DHQ Wm01j~^6E13^D1O7+^=wCum%9s<%z=p literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/trans.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/trans.gif new file mode 100644 index 0000000000000000000000000000000000000000..388486517fa8da13ebd150e8f65d5096c3e10c3a GIT binary patch literal 43 ncmZ?wbhEHbWMp7un7{x9ia%KxMSyG_5FaGNz{KRj$Y2csb)f_x literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/video.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/video.gif new file mode 100644 index 0000000000000000000000000000000000000000..3570104077a3b3585f11403c8d4c3fc9351f35d2 GIT binary patch literal 597 zcmZ?wbhEHb6krfwc$UTx9v<%P?Ok48Ze?YanwpxCkzrwBk(ZYzB_&l;Q<IsQ8F##3 z&6+hjyS!_6-?m?OIypHx=Cr@-5&wj}H`bh97ZVd>w!gmM(Ep^QBwbzIoSdAh>*2n> zz9l6k0Xw#(?);y5^ls9w|LObxXI*si^YfcEYu3*P8J(S-PEJlaNB-yTd}C^Ax@_69 zzP`Ryt5)S5`=P3;TDk9SbaeFk_3NiTjGA~aFd-pf@}tlxQ>GLb7jM|Gp`oFHlaq7F zk|nvhxjsHV=g+oST3Rl6T(N1>rn0iK*Ed>3MMVn>3vF#}<Kp6$Jg%90KfnCM|DvP+ z<KyEe-;F<iW5)F9(>**q!otE>Sy|^jDoRUBoBANRc=wyaJ<nc0nc3Rf>ged$+}u3x zK}ld>puWET<a=QO0RcuvMvEU*R8>{||NozXdO-0f3nK$V8iNkVNKl+Guy1NeYie$3 zZB}=&Zex!RYq8YfVwgNdMpdFkN|rU!Fha}0m66q>CDxczOhH^pM9qvxw1p`;Rftzu zQJ&9}g>iErlc2ORw;aC_=l*6UJ=st%r*ISVV2jgDT<)w>rX<Tawy@hu>HGL<21Kdo z#<Z}gv#eUPE{L72Mbyr3`_A1O_6G!-4lo?pkaV1FiiAT30~@pViHb_0Wo%3wHXM={ aHZHoY!s6T`pfu63XCY5W0tXihgEasdRMD9L literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/windowsmedia.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/img/windowsmedia.gif new file mode 100644 index 0000000000000000000000000000000000000000..ab50f2d887a0843b116ef598e5a005e5601d18d0 GIT binary patch literal 415 zcmV;Q0bu?|Nk%w1VGjTg0M$PL`E^qkEu+z?1&N?x_*pRg{rx~kg!#|I<>uyug^O^t z0hZGrt*x!>$1C!zn`W5@`ts6_uMW)2%<0NUEKIo?SIPPE=}U0}7Z(?JcX!y=*;bF< zCWz-=h7+2ao9)(dOHM;+X=xs9)%!~xc&ICMZdRYdUQ2$^@9y(6X3NCIz{cM7f^Z=Q z1_tQ95kgl8b%R%OiYTIo7LSdE^<g{S%f{2(!x(nqRGjHZr0IW^!yX<Ufq!q~!#RbG zsQ>@}A^8LW002J#EC2ui01p5U000KOz@O0K01zUifeIyT9%!RzMDgehG|mwLz+Eh; z7Z~<O+d66*jm@O!TxJNz2;i`UR0tHx^tgZ+0CP1KAR!ql1qdV^FA0GF8iXJ_Eg=Xd zF)utP961Ptlsgg#A3Xw_HykS#I~WWS1r`&g89Eg=I4CoS1qB}yE;0!k6cr*HE4>iE zrX?OfJ^>XeDJK)xJuWOB3_l1N0Ra>g4Gk^=ED0V6LI?>4;Q|6OB{LplLMRLg8U5-E J?0y6R06W6!pgRBn literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/about.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/about.js new file mode 100644 index 0000000..5b35845 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/about.js @@ -0,0 +1,73 @@ +tinyMCEPopup.requireLangPack(); + +function init() { + var ed, tcont; + + tinyMCEPopup.resizeToInnerSize(); + ed = tinyMCEPopup.editor; + + // Give FF some time + window.setTimeout(insertHelpIFrame, 10); + + tcont = document.getElementById('plugintablecontainer'); + document.getElementById('plugins_tab').style.display = 'none'; + + var html = ""; + html += '<table id="plugintable">'; + html += '<thead>'; + html += '<tr>'; + html += '<td>' + ed.getLang('advanced_dlg.about_plugin') + '</td>'; + html += '<td>' + ed.getLang('advanced_dlg.about_author') + '</td>'; + html += '<td>' + ed.getLang('advanced_dlg.about_version') + '</td>'; + html += '</tr>'; + html += '</thead>'; + html += '<tbody>'; + + tinymce.each(ed.plugins, function(p, n) { + var info; + + if (!p.getInfo) + return; + + html += '<tr>'; + + info = p.getInfo(); + + if (info.infourl != null && info.infourl != '') + html += '<td width="50%" title="' + n + '"><a href="' + info.infourl + '" target="_blank">' + info.longname + '</a></td>'; + else + html += '<td width="50%" title="' + n + '">' + info.longname + '</td>'; + + if (info.authorurl != null && info.authorurl != '') + html += '<td width="35%"><a href="' + info.authorurl + '" target="_blank">' + info.author + '</a></td>'; + else + html += '<td width="35%">' + info.author + '</td>'; + + html += '<td width="15%">' + info.version + '</td>'; + html += '</tr>'; + + document.getElementById('plugins_tab').style.display = ''; + + }); + + html += '</tbody>'; + html += '</table>'; + + tcont.innerHTML = html; + + tinyMCEPopup.dom.get('version').innerHTML = tinymce.majorVersion + "." + tinymce.minorVersion; + tinyMCEPopup.dom.get('date').innerHTML = tinymce.releaseDate; +} + +function insertHelpIFrame() { + var html; + + if (tinyMCEPopup.getParam('docs_url')) { + html = '<iframe width="100%" height="300" src="' + tinyMCEPopup.editor.baseURI.toAbsolute(tinyMCEPopup.getParam('docs_url')) + '"></iframe>'; + document.getElementById('iframecontainer').innerHTML = html; + document.getElementById('help_tab').style.display = 'block'; + document.getElementById('help_tab').setAttribute("aria-hidden", "false"); + } +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/anchor.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/anchor.js new file mode 100644 index 0000000..04f41e0 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/anchor.js @@ -0,0 +1,43 @@ +tinyMCEPopup.requireLangPack(); + +var AnchorDialog = { + init : function(ed) { + var action, elm, f = document.forms[0]; + + this.editor = ed; + elm = ed.dom.getParent(ed.selection.getNode(), 'A'); + v = ed.dom.getAttrib(elm, 'name'); + + if (v) { + this.action = 'update'; + f.anchorName.value = v; + } + + f.insert.value = ed.getLang(elm ? 'update' : 'insert'); + }, + + update : function() { + var ed = this.editor, elm, name = document.forms[0].anchorName.value; + + if (!name || !/^[a-z][a-z0-9\-\_:\.]*$/i.test(name)) { + tinyMCEPopup.alert('advanced_dlg.anchor_invalid'); + return; + } + + tinyMCEPopup.restoreSelection(); + + if (this.action != 'update') + ed.selection.collapse(1); + + elm = ed.dom.getParent(ed.selection.getNode(), 'A'); + if (elm) { + elm.setAttribute('name', name); + elm.name = name; + } else + ed.execCommand('mceInsertContent', 0, ed.dom.createHTML('a', {name : name, 'class' : 'mceItemAnchor'}, '')); + + tinyMCEPopup.close(); + } +}; + +tinyMCEPopup.onInit.add(AnchorDialog.init, AnchorDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/charmap.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/charmap.js new file mode 100644 index 0000000..1cead6d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/charmap.js @@ -0,0 +1,355 @@ +/** + * charmap.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +tinyMCEPopup.requireLangPack(); + +var charmap = [ + ['&nbsp;', '&#160;', true, 'no-break space'], + ['&amp;', '&#38;', true, 'ampersand'], + ['&quot;', '&#34;', true, 'quotation mark'], +// finance + ['&cent;', '&#162;', true, 'cent sign'], + ['&euro;', '&#8364;', true, 'euro sign'], + ['&pound;', '&#163;', true, 'pound sign'], + ['&yen;', '&#165;', true, 'yen sign'], +// signs + ['&copy;', '&#169;', true, 'copyright sign'], + ['&reg;', '&#174;', true, 'registered sign'], + ['&trade;', '&#8482;', true, 'trade mark sign'], + ['&permil;', '&#8240;', true, 'per mille sign'], + ['&micro;', '&#181;', true, 'micro sign'], + ['&middot;', '&#183;', true, 'middle dot'], + ['&bull;', '&#8226;', true, 'bullet'], + ['&hellip;', '&#8230;', true, 'three dot leader'], + ['&prime;', '&#8242;', true, 'minutes / feet'], + ['&Prime;', '&#8243;', true, 'seconds / inches'], + ['&sect;', '&#167;', true, 'section sign'], + ['&para;', '&#182;', true, 'paragraph sign'], + ['&szlig;', '&#223;', true, 'sharp s / ess-zed'], +// quotations + ['&lsaquo;', '&#8249;', true, 'single left-pointing angle quotation mark'], + ['&rsaquo;', '&#8250;', true, 'single right-pointing angle quotation mark'], + ['&laquo;', '&#171;', true, 'left pointing guillemet'], + ['&raquo;', '&#187;', true, 'right pointing guillemet'], + ['&lsquo;', '&#8216;', true, 'left single quotation mark'], + ['&rsquo;', '&#8217;', true, 'right single quotation mark'], + ['&ldquo;', '&#8220;', true, 'left double quotation mark'], + ['&rdquo;', '&#8221;', true, 'right double quotation mark'], + ['&sbquo;', '&#8218;', true, 'single low-9 quotation mark'], + ['&bdquo;', '&#8222;', true, 'double low-9 quotation mark'], + ['&lt;', '&#60;', true, 'less-than sign'], + ['&gt;', '&#62;', true, 'greater-than sign'], + ['&le;', '&#8804;', true, 'less-than or equal to'], + ['&ge;', '&#8805;', true, 'greater-than or equal to'], + ['&ndash;', '&#8211;', true, 'en dash'], + ['&mdash;', '&#8212;', true, 'em dash'], + ['&macr;', '&#175;', true, 'macron'], + ['&oline;', '&#8254;', true, 'overline'], + ['&curren;', '&#164;', true, 'currency sign'], + ['&brvbar;', '&#166;', true, 'broken bar'], + ['&uml;', '&#168;', true, 'diaeresis'], + ['&iexcl;', '&#161;', true, 'inverted exclamation mark'], + ['&iquest;', '&#191;', true, 'turned question mark'], + ['&circ;', '&#710;', true, 'circumflex accent'], + ['&tilde;', '&#732;', true, 'small tilde'], + ['&deg;', '&#176;', true, 'degree sign'], + ['&minus;', '&#8722;', true, 'minus sign'], + ['&plusmn;', '&#177;', true, 'plus-minus sign'], + ['&divide;', '&#247;', true, 'division sign'], + ['&frasl;', '&#8260;', true, 'fraction slash'], + ['&times;', '&#215;', true, 'multiplication sign'], + ['&sup1;', '&#185;', true, 'superscript one'], + ['&sup2;', '&#178;', true, 'superscript two'], + ['&sup3;', '&#179;', true, 'superscript three'], + ['&frac14;', '&#188;', true, 'fraction one quarter'], + ['&frac12;', '&#189;', true, 'fraction one half'], + ['&frac34;', '&#190;', true, 'fraction three quarters'], +// math / logical + ['&fnof;', '&#402;', true, 'function / florin'], + ['&int;', '&#8747;', true, 'integral'], + ['&sum;', '&#8721;', true, 'n-ary sumation'], + ['&infin;', '&#8734;', true, 'infinity'], + ['&radic;', '&#8730;', true, 'square root'], + ['&sim;', '&#8764;', false,'similar to'], + ['&cong;', '&#8773;', false,'approximately equal to'], + ['&asymp;', '&#8776;', true, 'almost equal to'], + ['&ne;', '&#8800;', true, 'not equal to'], + ['&equiv;', '&#8801;', true, 'identical to'], + ['&isin;', '&#8712;', false,'element of'], + ['&notin;', '&#8713;', false,'not an element of'], + ['&ni;', '&#8715;', false,'contains as member'], + ['&prod;', '&#8719;', true, 'n-ary product'], + ['&and;', '&#8743;', false,'logical and'], + ['&or;', '&#8744;', false,'logical or'], + ['&not;', '&#172;', true, 'not sign'], + ['&cap;', '&#8745;', true, 'intersection'], + ['&cup;', '&#8746;', false,'union'], + ['&part;', '&#8706;', true, 'partial differential'], + ['&forall;', '&#8704;', false,'for all'], + ['&exist;', '&#8707;', false,'there exists'], + ['&empty;', '&#8709;', false,'diameter'], + ['&nabla;', '&#8711;', false,'backward difference'], + ['&lowast;', '&#8727;', false,'asterisk operator'], + ['&prop;', '&#8733;', false,'proportional to'], + ['&ang;', '&#8736;', false,'angle'], +// undefined + ['&acute;', '&#180;', true, 'acute accent'], + ['&cedil;', '&#184;', true, 'cedilla'], + ['&ordf;', '&#170;', true, 'feminine ordinal indicator'], + ['&ordm;', '&#186;', true, 'masculine ordinal indicator'], + ['&dagger;', '&#8224;', true, 'dagger'], + ['&Dagger;', '&#8225;', true, 'double dagger'], +// alphabetical special chars + ['&Agrave;', '&#192;', true, 'A - grave'], + ['&Aacute;', '&#193;', true, 'A - acute'], + ['&Acirc;', '&#194;', true, 'A - circumflex'], + ['&Atilde;', '&#195;', true, 'A - tilde'], + ['&Auml;', '&#196;', true, 'A - diaeresis'], + ['&Aring;', '&#197;', true, 'A - ring above'], + ['&AElig;', '&#198;', true, 'ligature AE'], + ['&Ccedil;', '&#199;', true, 'C - cedilla'], + ['&Egrave;', '&#200;', true, 'E - grave'], + ['&Eacute;', '&#201;', true, 'E - acute'], + ['&Ecirc;', '&#202;', true, 'E - circumflex'], + ['&Euml;', '&#203;', true, 'E - diaeresis'], + ['&Igrave;', '&#204;', true, 'I - grave'], + ['&Iacute;', '&#205;', true, 'I - acute'], + ['&Icirc;', '&#206;', true, 'I - circumflex'], + ['&Iuml;', '&#207;', true, 'I - diaeresis'], + ['&ETH;', '&#208;', true, 'ETH'], + ['&Ntilde;', '&#209;', true, 'N - tilde'], + ['&Ograve;', '&#210;', true, 'O - grave'], + ['&Oacute;', '&#211;', true, 'O - acute'], + ['&Ocirc;', '&#212;', true, 'O - circumflex'], + ['&Otilde;', '&#213;', true, 'O - tilde'], + ['&Ouml;', '&#214;', true, 'O - diaeresis'], + ['&Oslash;', '&#216;', true, 'O - slash'], + ['&OElig;', '&#338;', true, 'ligature OE'], + ['&Scaron;', '&#352;', true, 'S - caron'], + ['&Ugrave;', '&#217;', true, 'U - grave'], + ['&Uacute;', '&#218;', true, 'U - acute'], + ['&Ucirc;', '&#219;', true, 'U - circumflex'], + ['&Uuml;', '&#220;', true, 'U - diaeresis'], + ['&Yacute;', '&#221;', true, 'Y - acute'], + ['&Yuml;', '&#376;', true, 'Y - diaeresis'], + ['&THORN;', '&#222;', true, 'THORN'], + ['&agrave;', '&#224;', true, 'a - grave'], + ['&aacute;', '&#225;', true, 'a - acute'], + ['&acirc;', '&#226;', true, 'a - circumflex'], + ['&atilde;', '&#227;', true, 'a - tilde'], + ['&auml;', '&#228;', true, 'a - diaeresis'], + ['&aring;', '&#229;', true, 'a - ring above'], + ['&aelig;', '&#230;', true, 'ligature ae'], + ['&ccedil;', '&#231;', true, 'c - cedilla'], + ['&egrave;', '&#232;', true, 'e - grave'], + ['&eacute;', '&#233;', true, 'e - acute'], + ['&ecirc;', '&#234;', true, 'e - circumflex'], + ['&euml;', '&#235;', true, 'e - diaeresis'], + ['&igrave;', '&#236;', true, 'i - grave'], + ['&iacute;', '&#237;', true, 'i - acute'], + ['&icirc;', '&#238;', true, 'i - circumflex'], + ['&iuml;', '&#239;', true, 'i - diaeresis'], + ['&eth;', '&#240;', true, 'eth'], + ['&ntilde;', '&#241;', true, 'n - tilde'], + ['&ograve;', '&#242;', true, 'o - grave'], + ['&oacute;', '&#243;', true, 'o - acute'], + ['&ocirc;', '&#244;', true, 'o - circumflex'], + ['&otilde;', '&#245;', true, 'o - tilde'], + ['&ouml;', '&#246;', true, 'o - diaeresis'], + ['&oslash;', '&#248;', true, 'o slash'], + ['&oelig;', '&#339;', true, 'ligature oe'], + ['&scaron;', '&#353;', true, 's - caron'], + ['&ugrave;', '&#249;', true, 'u - grave'], + ['&uacute;', '&#250;', true, 'u - acute'], + ['&ucirc;', '&#251;', true, 'u - circumflex'], + ['&uuml;', '&#252;', true, 'u - diaeresis'], + ['&yacute;', '&#253;', true, 'y - acute'], + ['&thorn;', '&#254;', true, 'thorn'], + ['&yuml;', '&#255;', true, 'y - diaeresis'], + ['&Alpha;', '&#913;', true, 'Alpha'], + ['&Beta;', '&#914;', true, 'Beta'], + ['&Gamma;', '&#915;', true, 'Gamma'], + ['&Delta;', '&#916;', true, 'Delta'], + ['&Epsilon;', '&#917;', true, 'Epsilon'], + ['&Zeta;', '&#918;', true, 'Zeta'], + ['&Eta;', '&#919;', true, 'Eta'], + ['&Theta;', '&#920;', true, 'Theta'], + ['&Iota;', '&#921;', true, 'Iota'], + ['&Kappa;', '&#922;', true, 'Kappa'], + ['&Lambda;', '&#923;', true, 'Lambda'], + ['&Mu;', '&#924;', true, 'Mu'], + ['&Nu;', '&#925;', true, 'Nu'], + ['&Xi;', '&#926;', true, 'Xi'], + ['&Omicron;', '&#927;', true, 'Omicron'], + ['&Pi;', '&#928;', true, 'Pi'], + ['&Rho;', '&#929;', true, 'Rho'], + ['&Sigma;', '&#931;', true, 'Sigma'], + ['&Tau;', '&#932;', true, 'Tau'], + ['&Upsilon;', '&#933;', true, 'Upsilon'], + ['&Phi;', '&#934;', true, 'Phi'], + ['&Chi;', '&#935;', true, 'Chi'], + ['&Psi;', '&#936;', true, 'Psi'], + ['&Omega;', '&#937;', true, 'Omega'], + ['&alpha;', '&#945;', true, 'alpha'], + ['&beta;', '&#946;', true, 'beta'], + ['&gamma;', '&#947;', true, 'gamma'], + ['&delta;', '&#948;', true, 'delta'], + ['&epsilon;', '&#949;', true, 'epsilon'], + ['&zeta;', '&#950;', true, 'zeta'], + ['&eta;', '&#951;', true, 'eta'], + ['&theta;', '&#952;', true, 'theta'], + ['&iota;', '&#953;', true, 'iota'], + ['&kappa;', '&#954;', true, 'kappa'], + ['&lambda;', '&#955;', true, 'lambda'], + ['&mu;', '&#956;', true, 'mu'], + ['&nu;', '&#957;', true, 'nu'], + ['&xi;', '&#958;', true, 'xi'], + ['&omicron;', '&#959;', true, 'omicron'], + ['&pi;', '&#960;', true, 'pi'], + ['&rho;', '&#961;', true, 'rho'], + ['&sigmaf;', '&#962;', true, 'final sigma'], + ['&sigma;', '&#963;', true, 'sigma'], + ['&tau;', '&#964;', true, 'tau'], + ['&upsilon;', '&#965;', true, 'upsilon'], + ['&phi;', '&#966;', true, 'phi'], + ['&chi;', '&#967;', true, 'chi'], + ['&psi;', '&#968;', true, 'psi'], + ['&omega;', '&#969;', true, 'omega'], +// symbols + ['&alefsym;', '&#8501;', false,'alef symbol'], + ['&piv;', '&#982;', false,'pi symbol'], + ['&real;', '&#8476;', false,'real part symbol'], + ['&thetasym;','&#977;', false,'theta symbol'], + ['&upsih;', '&#978;', false,'upsilon - hook symbol'], + ['&weierp;', '&#8472;', false,'Weierstrass p'], + ['&image;', '&#8465;', false,'imaginary part'], +// arrows + ['&larr;', '&#8592;', true, 'leftwards arrow'], + ['&uarr;', '&#8593;', true, 'upwards arrow'], + ['&rarr;', '&#8594;', true, 'rightwards arrow'], + ['&darr;', '&#8595;', true, 'downwards arrow'], + ['&harr;', '&#8596;', true, 'left right arrow'], + ['&crarr;', '&#8629;', false,'carriage return'], + ['&lArr;', '&#8656;', false,'leftwards double arrow'], + ['&uArr;', '&#8657;', false,'upwards double arrow'], + ['&rArr;', '&#8658;', false,'rightwards double arrow'], + ['&dArr;', '&#8659;', false,'downwards double arrow'], + ['&hArr;', '&#8660;', false,'left right double arrow'], + ['&there4;', '&#8756;', false,'therefore'], + ['&sub;', '&#8834;', false,'subset of'], + ['&sup;', '&#8835;', false,'superset of'], + ['&nsub;', '&#8836;', false,'not a subset of'], + ['&sube;', '&#8838;', false,'subset of or equal to'], + ['&supe;', '&#8839;', false,'superset of or equal to'], + ['&oplus;', '&#8853;', false,'circled plus'], + ['&otimes;', '&#8855;', false,'circled times'], + ['&perp;', '&#8869;', false,'perpendicular'], + ['&sdot;', '&#8901;', false,'dot operator'], + ['&lceil;', '&#8968;', false,'left ceiling'], + ['&rceil;', '&#8969;', false,'right ceiling'], + ['&lfloor;', '&#8970;', false,'left floor'], + ['&rfloor;', '&#8971;', false,'right floor'], + ['&lang;', '&#9001;', false,'left-pointing angle bracket'], + ['&rang;', '&#9002;', false,'right-pointing angle bracket'], + ['&loz;', '&#9674;', true, 'lozenge'], + ['&spades;', '&#9824;', true, 'black spade suit'], + ['&clubs;', '&#9827;', true, 'black club suit'], + ['&hearts;', '&#9829;', true, 'black heart suit'], + ['&diams;', '&#9830;', true, 'black diamond suit'], + ['&ensp;', '&#8194;', false,'en space'], + ['&emsp;', '&#8195;', false,'em space'], + ['&thinsp;', '&#8201;', false,'thin space'], + ['&zwnj;', '&#8204;', false,'zero width non-joiner'], + ['&zwj;', '&#8205;', false,'zero width joiner'], + ['&lrm;', '&#8206;', false,'left-to-right mark'], + ['&rlm;', '&#8207;', false,'right-to-left mark'], + ['&shy;', '&#173;', false,'soft hyphen'] +]; + +tinyMCEPopup.onInit.add(function() { + tinyMCEPopup.dom.setHTML('charmapView', renderCharMapHTML()); + addKeyboardNavigation(); +}); + +function addKeyboardNavigation(){ + var tableElm, cells, settings; + + cells = tinyMCEPopup.dom.select(".charmaplink", "charmapgroup"); + + settings ={ + root: "charmapgroup", + items: cells + }; + + tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', settings, tinyMCEPopup.dom); +} + +function renderCharMapHTML() { + var charsPerRow = 20, tdWidth=20, tdHeight=20, i; + var html = '<div id="charmapgroup" aria-labelledby="charmap_label" tabindex="0" role="listbox">'+ + '<table role="presentation" border="0" cellspacing="1" cellpadding="0" width="' + (tdWidth*charsPerRow) + + '"><tr height="' + tdHeight + '">'; + var cols=-1; + + for (i=0; i<charmap.length; i++) { + var previewCharFn; + + if (charmap[i][2]==true) { + cols++; + previewCharFn = 'previewChar(\'' + charmap[i][1].substring(1,charmap[i][1].length) + '\',\'' + charmap[i][0].substring(1,charmap[i][0].length) + '\',\'' + charmap[i][3] + '\');'; + html += '' + + '<td class="charmap">' + + '<a class="charmaplink" role="button" onmouseover="'+previewCharFn+'" onfocus="'+previewCharFn+'" href="javascript:void(0)" onclick="insertChar(\'' + charmap[i][1].substring(2,charmap[i][1].length-1) + '\');" onclick="return false;" onmousedown="return false;" title="' + charmap[i][3] + '">' + + charmap[i][1] + + '</a></td>'; + if ((cols+1) % charsPerRow == 0) + html += '</tr><tr height="' + tdHeight + '">'; + } + } + + if (cols % charsPerRow > 0) { + var padd = charsPerRow - (cols % charsPerRow); + for (var i=0; i<padd-1; i++) + html += '<td width="' + tdWidth + '" height="' + tdHeight + '" class="charmap">&nbsp;</td>'; + } + + html += '</tr></table></div>'; + html = html.replace(/<tr height="20"><\/tr>/g, ''); + + return html; +} + +function insertChar(chr) { + tinyMCEPopup.execCommand('mceInsertContent', false, '&#' + chr + ';'); + + // Refocus in window + if (tinyMCEPopup.isWindow) + window.focus(); + + tinyMCEPopup.editor.focus(); + tinyMCEPopup.close(); +} + +function previewChar(codeA, codeB, codeN) { + var elmA = document.getElementById('codeA'); + var elmB = document.getElementById('codeB'); + var elmV = document.getElementById('codeV'); + var elmN = document.getElementById('codeN'); + + if (codeA=='#160;') { + elmV.innerHTML = '__'; + } else { + elmV.innerHTML = '&' + codeA; + } + + elmB.innerHTML = '&amp;' + codeA; + elmA.innerHTML = '&amp;' + codeB; + elmN.innerHTML = codeN; +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/color_picker.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/color_picker.js new file mode 100644 index 0000000..7decac5 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/color_picker.js @@ -0,0 +1,329 @@ +tinyMCEPopup.requireLangPack(); + +var detail = 50, strhex = "0123456789ABCDEF", i, isMouseDown = false, isMouseOver = false; + +var colors = [ + "#000000","#000033","#000066","#000099","#0000cc","#0000ff","#330000","#330033", + "#330066","#330099","#3300cc","#3300ff","#660000","#660033","#660066","#660099", + "#6600cc","#6600ff","#990000","#990033","#990066","#990099","#9900cc","#9900ff", + "#cc0000","#cc0033","#cc0066","#cc0099","#cc00cc","#cc00ff","#ff0000","#ff0033", + "#ff0066","#ff0099","#ff00cc","#ff00ff","#003300","#003333","#003366","#003399", + "#0033cc","#0033ff","#333300","#333333","#333366","#333399","#3333cc","#3333ff", + "#663300","#663333","#663366","#663399","#6633cc","#6633ff","#993300","#993333", + "#993366","#993399","#9933cc","#9933ff","#cc3300","#cc3333","#cc3366","#cc3399", + "#cc33cc","#cc33ff","#ff3300","#ff3333","#ff3366","#ff3399","#ff33cc","#ff33ff", + "#006600","#006633","#006666","#006699","#0066cc","#0066ff","#336600","#336633", + "#336666","#336699","#3366cc","#3366ff","#666600","#666633","#666666","#666699", + "#6666cc","#6666ff","#996600","#996633","#996666","#996699","#9966cc","#9966ff", + "#cc6600","#cc6633","#cc6666","#cc6699","#cc66cc","#cc66ff","#ff6600","#ff6633", + "#ff6666","#ff6699","#ff66cc","#ff66ff","#009900","#009933","#009966","#009999", + "#0099cc","#0099ff","#339900","#339933","#339966","#339999","#3399cc","#3399ff", + "#669900","#669933","#669966","#669999","#6699cc","#6699ff","#999900","#999933", + "#999966","#999999","#9999cc","#9999ff","#cc9900","#cc9933","#cc9966","#cc9999", + "#cc99cc","#cc99ff","#ff9900","#ff9933","#ff9966","#ff9999","#ff99cc","#ff99ff", + "#00cc00","#00cc33","#00cc66","#00cc99","#00cccc","#00ccff","#33cc00","#33cc33", + "#33cc66","#33cc99","#33cccc","#33ccff","#66cc00","#66cc33","#66cc66","#66cc99", + "#66cccc","#66ccff","#99cc00","#99cc33","#99cc66","#99cc99","#99cccc","#99ccff", + "#cccc00","#cccc33","#cccc66","#cccc99","#cccccc","#ccccff","#ffcc00","#ffcc33", + "#ffcc66","#ffcc99","#ffcccc","#ffccff","#00ff00","#00ff33","#00ff66","#00ff99", + "#00ffcc","#00ffff","#33ff00","#33ff33","#33ff66","#33ff99","#33ffcc","#33ffff", + "#66ff00","#66ff33","#66ff66","#66ff99","#66ffcc","#66ffff","#99ff00","#99ff33", + "#99ff66","#99ff99","#99ffcc","#99ffff","#ccff00","#ccff33","#ccff66","#ccff99", + "#ccffcc","#ccffff","#ffff00","#ffff33","#ffff66","#ffff99","#ffffcc","#ffffff" +]; + +var named = { + '#F0F8FF':'Alice Blue','#FAEBD7':'Antique White','#00FFFF':'Aqua','#7FFFD4':'Aquamarine','#F0FFFF':'Azure','#F5F5DC':'Beige', + '#FFE4C4':'Bisque','#000000':'Black','#FFEBCD':'Blanched Almond','#0000FF':'Blue','#8A2BE2':'Blue Violet','#A52A2A':'Brown', + '#DEB887':'Burly Wood','#5F9EA0':'Cadet Blue','#7FFF00':'Chartreuse','#D2691E':'Chocolate','#FF7F50':'Coral','#6495ED':'Cornflower Blue', + '#FFF8DC':'Cornsilk','#DC143C':'Crimson','#00FFFF':'Cyan','#00008B':'Dark Blue','#008B8B':'Dark Cyan','#B8860B':'Dark Golden Rod', + '#A9A9A9':'Dark Gray','#A9A9A9':'Dark Grey','#006400':'Dark Green','#BDB76B':'Dark Khaki','#8B008B':'Dark Magenta','#556B2F':'Dark Olive Green', + '#FF8C00':'Darkorange','#9932CC':'Dark Orchid','#8B0000':'Dark Red','#E9967A':'Dark Salmon','#8FBC8F':'Dark Sea Green','#483D8B':'Dark Slate Blue', + '#2F4F4F':'Dark Slate Gray','#2F4F4F':'Dark Slate Grey','#00CED1':'Dark Turquoise','#9400D3':'Dark Violet','#FF1493':'Deep Pink','#00BFFF':'Deep Sky Blue', + '#696969':'Dim Gray','#696969':'Dim Grey','#1E90FF':'Dodger Blue','#B22222':'Fire Brick','#FFFAF0':'Floral White','#228B22':'Forest Green', + '#FF00FF':'Fuchsia','#DCDCDC':'Gainsboro','#F8F8FF':'Ghost White','#FFD700':'Gold','#DAA520':'Golden Rod','#808080':'Gray','#808080':'Grey', + '#008000':'Green','#ADFF2F':'Green Yellow','#F0FFF0':'Honey Dew','#FF69B4':'Hot Pink','#CD5C5C':'Indian Red','#4B0082':'Indigo','#FFFFF0':'Ivory', + '#F0E68C':'Khaki','#E6E6FA':'Lavender','#FFF0F5':'Lavender Blush','#7CFC00':'Lawn Green','#FFFACD':'Lemon Chiffon','#ADD8E6':'Light Blue', + '#F08080':'Light Coral','#E0FFFF':'Light Cyan','#FAFAD2':'Light Golden Rod Yellow','#D3D3D3':'Light Gray','#D3D3D3':'Light Grey','#90EE90':'Light Green', + '#FFB6C1':'Light Pink','#FFA07A':'Light Salmon','#20B2AA':'Light Sea Green','#87CEFA':'Light Sky Blue','#778899':'Light Slate Gray','#778899':'Light Slate Grey', + '#B0C4DE':'Light Steel Blue','#FFFFE0':'Light Yellow','#00FF00':'Lime','#32CD32':'Lime Green','#FAF0E6':'Linen','#FF00FF':'Magenta','#800000':'Maroon', + '#66CDAA':'Medium Aqua Marine','#0000CD':'Medium Blue','#BA55D3':'Medium Orchid','#9370D8':'Medium Purple','#3CB371':'Medium Sea Green','#7B68EE':'Medium Slate Blue', + '#00FA9A':'Medium Spring Green','#48D1CC':'Medium Turquoise','#C71585':'Medium Violet Red','#191970':'Midnight Blue','#F5FFFA':'Mint Cream','#FFE4E1':'Misty Rose','#FFE4B5':'Moccasin', + '#FFDEAD':'Navajo White','#000080':'Navy','#FDF5E6':'Old Lace','#808000':'Olive','#6B8E23':'Olive Drab','#FFA500':'Orange','#FF4500':'Orange Red','#DA70D6':'Orchid', + '#EEE8AA':'Pale Golden Rod','#98FB98':'Pale Green','#AFEEEE':'Pale Turquoise','#D87093':'Pale Violet Red','#FFEFD5':'Papaya Whip','#FFDAB9':'Peach Puff', + '#CD853F':'Peru','#FFC0CB':'Pink','#DDA0DD':'Plum','#B0E0E6':'Powder Blue','#800080':'Purple','#FF0000':'Red','#BC8F8F':'Rosy Brown','#4169E1':'Royal Blue', + '#8B4513':'Saddle Brown','#FA8072':'Salmon','#F4A460':'Sandy Brown','#2E8B57':'Sea Green','#FFF5EE':'Sea Shell','#A0522D':'Sienna','#C0C0C0':'Silver', + '#87CEEB':'Sky Blue','#6A5ACD':'Slate Blue','#708090':'Slate Gray','#708090':'Slate Grey','#FFFAFA':'Snow','#00FF7F':'Spring Green', + '#4682B4':'Steel Blue','#D2B48C':'Tan','#008080':'Teal','#D8BFD8':'Thistle','#FF6347':'Tomato','#40E0D0':'Turquoise','#EE82EE':'Violet', + '#F5DEB3':'Wheat','#FFFFFF':'White','#F5F5F5':'White Smoke','#FFFF00':'Yellow','#9ACD32':'Yellow Green' +}; + +var namedLookup = {}; + +function init() { + var inputColor = convertRGBToHex(tinyMCEPopup.getWindowArg('input_color')), key, value; + + tinyMCEPopup.resizeToInnerSize(); + + generatePicker(); + generateWebColors(); + generateNamedColors(); + + if (inputColor) { + changeFinalColor(inputColor); + + col = convertHexToRGB(inputColor); + + if (col) + updateLight(col.r, col.g, col.b); + } + + for (key in named) { + value = named[key]; + namedLookup[value.replace(/\s+/, '').toLowerCase()] = key.replace(/#/, '').toLowerCase(); + } +} + +function toHexColor(color) { + var matches, red, green, blue, toInt = parseInt; + + function hex(value) { + value = parseInt(value).toString(16); + + return value.length > 1 ? value : '0' + value; // Padd with leading zero + }; + + color = color.replace(/[\s#]+/g, '').toLowerCase(); + color = namedLookup[color] || color; + matches = /^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)|([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})|([a-f0-9])([a-f0-9])([a-f0-9])$/.exec(color); + + if (matches) { + if (matches[1]) { + red = toInt(matches[1]); + green = toInt(matches[2]); + blue = toInt(matches[3]); + } else if (matches[4]) { + red = toInt(matches[4], 16); + green = toInt(matches[5], 16); + blue = toInt(matches[6], 16); + } else if (matches[7]) { + red = toInt(matches[7] + matches[7], 16); + green = toInt(matches[8] + matches[8], 16); + blue = toInt(matches[9] + matches[9], 16); + } + + return '#' + hex(red) + hex(green) + hex(blue); + } + + return ''; +} + +function insertAction() { + var color = document.getElementById("color").value, f = tinyMCEPopup.getWindowArg('func'); + + tinyMCEPopup.restoreSelection(); + + if (f) + f(toHexColor(color)); + + tinyMCEPopup.close(); +} + +function showColor(color, name) { + if (name) + document.getElementById("colorname").innerHTML = name; + + document.getElementById("preview").style.backgroundColor = color; + document.getElementById("color").value = color.toUpperCase(); +} + +function convertRGBToHex(col) { + var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi"); + + if (!col) + return col; + + var rgb = col.replace(re, "$1,$2,$3").split(','); + if (rgb.length == 3) { + r = parseInt(rgb[0]).toString(16); + g = parseInt(rgb[1]).toString(16); + b = parseInt(rgb[2]).toString(16); + + r = r.length == 1 ? '0' + r : r; + g = g.length == 1 ? '0' + g : g; + b = b.length == 1 ? '0' + b : b; + + return "#" + r + g + b; + } + + return col; +} + +function convertHexToRGB(col) { + if (col.indexOf('#') != -1) { + col = col.replace(new RegExp('[^0-9A-F]', 'gi'), ''); + + r = parseInt(col.substring(0, 2), 16); + g = parseInt(col.substring(2, 4), 16); + b = parseInt(col.substring(4, 6), 16); + + return {r : r, g : g, b : b}; + } + + return null; +} + +function generatePicker() { + var el = document.getElementById('light'), h = '', i; + + for (i = 0; i < detail; i++){ + h += '<div id="gs'+i+'" style="background-color:#000000; width:15px; height:3px; border-style:none; border-width:0px;"' + + ' onclick="changeFinalColor(this.style.backgroundColor)"' + + ' onmousedown="isMouseDown = true; return false;"' + + ' onmouseup="isMouseDown = false;"' + + ' onmousemove="if (isMouseDown && isMouseOver) changeFinalColor(this.style.backgroundColor); return false;"' + + ' onmouseover="isMouseOver = true;"' + + ' onmouseout="isMouseOver = false;"' + + '></div>'; + } + + el.innerHTML = h; +} + +function generateWebColors() { + var el = document.getElementById('webcolors'), h = '', i; + + if (el.className == 'generated') + return; + + // TODO: VoiceOver doesn't seem to support legend as a label referenced by labelledby. + h += '<div role="listbox" aria-labelledby="webcolors_title" tabindex="0"><table role="presentation" border="0" cellspacing="1" cellpadding="0">' + + '<tr>'; + + for (i=0; i<colors.length; i++) { + h += '<td bgcolor="' + colors[i] + '" width="10" height="10">' + + '<a href="javascript:insertAction();" role="option" tabindex="-1" aria-labelledby="web_colors_' + i + '" onfocus="showColor(\'' + colors[i] + '\');" onmouseover="showColor(\'' + colors[i] + '\');" style="display:block;width:10px;height:10px;overflow:hidden;">'; + if (tinyMCEPopup.editor.forcedHighContrastMode) { + h += '<canvas class="mceColorSwatch" height="10" width="10" data-color="' + colors[i] + '"></canvas>'; + } + h += '<span class="mceVoiceLabel" style="display:none;" id="web_colors_' + i + '">' + colors[i].toUpperCase() + '</span>'; + h += '</a></td>'; + if ((i+1) % 18 == 0) + h += '</tr><tr>'; + } + + h += '</table></div>'; + + el.innerHTML = h; + el.className = 'generated'; + + paintCanvas(el); + enableKeyboardNavigation(el.firstChild); +} + +function paintCanvas(el) { + tinyMCEPopup.getWin().tinymce.each(tinyMCEPopup.dom.select('canvas.mceColorSwatch', el), function(canvas) { + var context; + if (canvas.getContext && (context = canvas.getContext("2d"))) { + context.fillStyle = canvas.getAttribute('data-color'); + context.fillRect(0, 0, 10, 10); + } + }); +} +function generateNamedColors() { + var el = document.getElementById('namedcolors'), h = '', n, v, i = 0; + + if (el.className == 'generated') + return; + + for (n in named) { + v = named[n]; + h += '<a href="javascript:insertAction();" role="option" tabindex="-1" aria-labelledby="named_colors_' + i + '" onfocus="showColor(\'' + n + '\',\'' + v + '\');" onmouseover="showColor(\'' + n + '\',\'' + v + '\');" style="background-color: ' + n + '">'; + if (tinyMCEPopup.editor.forcedHighContrastMode) { + h += '<canvas class="mceColorSwatch" height="10" width="10" data-color="' + colors[i] + '"></canvas>'; + } + h += '<span class="mceVoiceLabel" style="display:none;" id="named_colors_' + i + '">' + v + '</span>'; + h += '</a>'; + i++; + } + + el.innerHTML = h; + el.className = 'generated'; + + paintCanvas(el); + enableKeyboardNavigation(el); +} + +function enableKeyboardNavigation(el) { + tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', { + root: el, + items: tinyMCEPopup.dom.select('a', el) + }, tinyMCEPopup.dom); +} + +function dechex(n) { + return strhex.charAt(Math.floor(n / 16)) + strhex.charAt(n % 16); +} + +function computeColor(e) { + var x, y, partWidth, partDetail, imHeight, r, g, b, coef, i, finalCoef, finalR, finalG, finalB; + + x = e.offsetX ? e.offsetX : (e.target ? e.clientX - e.target.x : 0); + y = e.offsetY ? e.offsetY : (e.target ? e.clientY - e.target.y : 0); + + partWidth = document.getElementById('colors').width / 6; + partDetail = detail / 2; + imHeight = document.getElementById('colors').height; + + r = (x >= 0)*(x < partWidth)*255 + (x >= partWidth)*(x < 2*partWidth)*(2*255 - x * 255 / partWidth) + (x >= 4*partWidth)*(x < 5*partWidth)*(-4*255 + x * 255 / partWidth) + (x >= 5*partWidth)*(x < 6*partWidth)*255; + g = (x >= 0)*(x < partWidth)*(x * 255 / partWidth) + (x >= partWidth)*(x < 3*partWidth)*255 + (x >= 3*partWidth)*(x < 4*partWidth)*(4*255 - x * 255 / partWidth); + b = (x >= 2*partWidth)*(x < 3*partWidth)*(-2*255 + x * 255 / partWidth) + (x >= 3*partWidth)*(x < 5*partWidth)*255 + (x >= 5*partWidth)*(x < 6*partWidth)*(6*255 - x * 255 / partWidth); + + coef = (imHeight - y) / imHeight; + r = 128 + (r - 128) * coef; + g = 128 + (g - 128) * coef; + b = 128 + (b - 128) * coef; + + changeFinalColor('#' + dechex(r) + dechex(g) + dechex(b)); + updateLight(r, g, b); +} + +function updateLight(r, g, b) { + var i, partDetail = detail / 2, finalCoef, finalR, finalG, finalB, color; + + for (i=0; i<detail; i++) { + if ((i>=0) && (i<partDetail)) { + finalCoef = i / partDetail; + finalR = dechex(255 - (255 - r) * finalCoef); + finalG = dechex(255 - (255 - g) * finalCoef); + finalB = dechex(255 - (255 - b) * finalCoef); + } else { + finalCoef = 2 - i / partDetail; + finalR = dechex(r * finalCoef); + finalG = dechex(g * finalCoef); + finalB = dechex(b * finalCoef); + } + + color = finalR + finalG + finalB; + + setCol('gs' + i, '#'+color); + } +} + +function changeFinalColor(color) { + if (color.indexOf('#') == -1) + color = convertRGBToHex(color); + + setCol('preview', color); + document.getElementById('color').value = color; +} + +function setCol(e, c) { + try { + document.getElementById(e).style.backgroundColor = c; + } catch (ex) { + // Ignore IE warning + } +} + +tinyMCEPopup.onInit.add(init); diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/image.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/image.js new file mode 100644 index 0000000..6c2489a --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/image.js @@ -0,0 +1,251 @@ +var ImageDialog = { + preInit : function() { + var url; + + tinyMCEPopup.requireLangPack(); + + if (url = tinyMCEPopup.getParam("external_image_list_url")) + document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>'); + }, + + init : function() { + var f = document.forms[0], ed = tinyMCEPopup.editor; + + // Setup browse button + document.getElementById('srcbrowsercontainer').innerHTML = getBrowserHTML('srcbrowser','src','image','theme_advanced_image'); + if (isVisible('srcbrowser')) + document.getElementById('src').style.width = '180px'; + + e = ed.selection.getNode(); + + this.fillFileList('image_list', tinyMCEPopup.getParam('external_image_list', 'tinyMCEImageList')); + + if (e.nodeName == 'IMG') { + f.src.value = ed.dom.getAttrib(e, 'src'); + f.alt.value = ed.dom.getAttrib(e, 'alt'); + f.border.value = this.getAttrib(e, 'border'); + f.vspace.value = this.getAttrib(e, 'vspace'); + f.hspace.value = this.getAttrib(e, 'hspace'); + f.width.value = ed.dom.getAttrib(e, 'width'); + f.height.value = ed.dom.getAttrib(e, 'height'); + f.insert.value = ed.getLang('update'); + this.styleVal = ed.dom.getAttrib(e, 'style'); + selectByValue(f, 'image_list', f.src.value); + selectByValue(f, 'align', this.getAttrib(e, 'align')); + this.updateStyle(); + } + }, + + fillFileList : function(id, l) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl; + + l = typeof(l) === 'function' ? l() : window[l]; + + if (l && l.length > 0) { + lst.options[lst.options.length] = new Option('', ''); + + tinymce.each(l, function(o) { + lst.options[lst.options.length] = new Option(o[0], o[1]); + }); + } else + dom.remove(dom.getParent(id, 'tr')); + }, + + update : function() { + var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, args = {}, el; + + tinyMCEPopup.restoreSelection(); + + if (f.src.value === '') { + if (ed.selection.getNode().nodeName == 'IMG') { + ed.dom.remove(ed.selection.getNode()); + ed.execCommand('mceRepaint'); + } + + tinyMCEPopup.close(); + return; + } + + if (!ed.settings.inline_styles) { + args = tinymce.extend(args, { + vspace : nl.vspace.value, + hspace : nl.hspace.value, + border : nl.border.value, + align : getSelectValue(f, 'align') + }); + } else + args.style = this.styleVal; + + tinymce.extend(args, { + src : f.src.value.replace(/ /g, '%20'), + alt : f.alt.value, + width : f.width.value, + height : f.height.value + }); + + el = ed.selection.getNode(); + + if (el && el.nodeName == 'IMG') { + ed.dom.setAttribs(el, args); + tinyMCEPopup.editor.execCommand('mceRepaint'); + tinyMCEPopup.editor.focus(); + } else { + tinymce.each(args, function(value, name) { + if (value === "") { + delete args[name]; + } + }); + + ed.execCommand('mceInsertContent', false, tinyMCEPopup.editor.dom.createHTML('img', args), {skip_undo : 1}); + ed.undoManager.add(); + } + + tinyMCEPopup.close(); + }, + + updateStyle : function() { + var dom = tinyMCEPopup.dom, st, v, f = document.forms[0]; + + if (tinyMCEPopup.editor.settings.inline_styles) { + st = tinyMCEPopup.dom.parseStyle(this.styleVal); + + // Handle align + v = getSelectValue(f, 'align'); + if (v) { + if (v == 'left' || v == 'right') { + st['float'] = v; + delete st['vertical-align']; + } else { + st['vertical-align'] = v; + delete st['float']; + } + } else { + delete st['float']; + delete st['vertical-align']; + } + + // Handle border + v = f.border.value; + if (v || v == '0') { + if (v == '0') + st['border'] = '0'; + else + st['border'] = v + 'px solid black'; + } else + delete st['border']; + + // Handle hspace + v = f.hspace.value; + if (v) { + delete st['margin']; + st['margin-left'] = v + 'px'; + st['margin-right'] = v + 'px'; + } else { + delete st['margin-left']; + delete st['margin-right']; + } + + // Handle vspace + v = f.vspace.value; + if (v) { + delete st['margin']; + st['margin-top'] = v + 'px'; + st['margin-bottom'] = v + 'px'; + } else { + delete st['margin-top']; + delete st['margin-bottom']; + } + + // Merge + st = tinyMCEPopup.dom.parseStyle(dom.serializeStyle(st), 'img'); + this.styleVal = dom.serializeStyle(st, 'img'); + } + }, + + getAttrib : function(e, at) { + var ed = tinyMCEPopup.editor, dom = ed.dom, v, v2; + + if (ed.settings.inline_styles) { + switch (at) { + case 'align': + if (v = dom.getStyle(e, 'float')) + return v; + + if (v = dom.getStyle(e, 'vertical-align')) + return v; + + break; + + case 'hspace': + v = dom.getStyle(e, 'margin-left') + v2 = dom.getStyle(e, 'margin-right'); + if (v && v == v2) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + + case 'vspace': + v = dom.getStyle(e, 'margin-top') + v2 = dom.getStyle(e, 'margin-bottom'); + if (v && v == v2) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + + case 'border': + v = 0; + + tinymce.each(['top', 'right', 'bottom', 'left'], function(sv) { + sv = dom.getStyle(e, 'border-' + sv + '-width'); + + // False or not the same as prev + if (!sv || (sv != v && v !== 0)) { + v = 0; + return false; + } + + if (sv) + v = sv; + }); + + if (v) + return parseInt(v.replace(/[^0-9]/g, '')); + + break; + } + } + + if (v = dom.getAttrib(e, at)) + return v; + + return ''; + }, + + resetImageData : function() { + var f = document.forms[0]; + + f.width.value = f.height.value = ""; + }, + + updateImageData : function() { + var f = document.forms[0], t = ImageDialog; + + if (f.width.value == "") + f.width.value = t.preloadImg.width; + + if (f.height.value == "") + f.height.value = t.preloadImg.height; + }, + + getImageData : function() { + var f = document.forms[0]; + + this.preloadImg = new Image(); + this.preloadImg.onload = this.updateImageData; + this.preloadImg.onerror = this.resetImageData; + this.preloadImg.src = tinyMCEPopup.editor.documentBaseURI.toAbsolute(f.src.value); + } +}; + +ImageDialog.preInit(); +tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/link.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/link.js new file mode 100644 index 0000000..53ff409 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/link.js @@ -0,0 +1,153 @@ +tinyMCEPopup.requireLangPack(); + +var LinkDialog = { + preInit : function() { + var url; + + if (url = tinyMCEPopup.getParam("external_link_list_url")) + document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>'); + }, + + init : function() { + var f = document.forms[0], ed = tinyMCEPopup.editor; + + // Setup browse button + document.getElementById('hrefbrowsercontainer').innerHTML = getBrowserHTML('hrefbrowser', 'href', 'file', 'theme_advanced_link'); + if (isVisible('hrefbrowser')) + document.getElementById('href').style.width = '180px'; + + this.fillClassList('class_list'); + this.fillFileList('link_list', 'tinyMCELinkList'); + this.fillTargetList('target_list'); + + if (e = ed.dom.getParent(ed.selection.getNode(), 'A')) { + f.href.value = ed.dom.getAttrib(e, 'href'); + f.linktitle.value = ed.dom.getAttrib(e, 'title'); + f.insert.value = ed.getLang('update'); + selectByValue(f, 'link_list', f.href.value); + selectByValue(f, 'target_list', ed.dom.getAttrib(e, 'target')); + selectByValue(f, 'class_list', ed.dom.getAttrib(e, 'class')); + } + }, + + update : function() { + var f = document.forms[0], ed = tinyMCEPopup.editor, e, b, href = f.href.value.replace(/ /g, '%20'); + + tinyMCEPopup.restoreSelection(); + e = ed.dom.getParent(ed.selection.getNode(), 'A'); + + // Remove element if there is no href + if (!f.href.value) { + if (e) { + b = ed.selection.getBookmark(); + ed.dom.remove(e, 1); + ed.selection.moveToBookmark(b); + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); + return; + } + } + + // Create new anchor elements + if (e == null) { + ed.getDoc().execCommand("unlink", false, null); + tinyMCEPopup.execCommand("mceInsertLink", false, "#mce_temp_url#", {skip_undo : 1}); + + tinymce.each(ed.dom.select("a"), function(n) { + if (ed.dom.getAttrib(n, 'href') == '#mce_temp_url#') { + e = n; + + ed.dom.setAttribs(e, { + href : href, + title : f.linktitle.value, + target : f.target_list ? getSelectValue(f, "target_list") : null, + 'class' : f.class_list ? getSelectValue(f, "class_list") : null + }); + } + }); + } else { + ed.dom.setAttribs(e, { + href : href, + title : f.linktitle.value, + target : f.target_list ? getSelectValue(f, "target_list") : null, + 'class' : f.class_list ? getSelectValue(f, "class_list") : null + }); + } + + // Don't move caret if selection was image + if (e.childNodes.length != 1 || e.firstChild.nodeName != 'IMG') { + ed.focus(); + ed.selection.select(e); + ed.selection.collapse(0); + tinyMCEPopup.storeSelection(); + } + + tinyMCEPopup.execCommand("mceEndUndoLevel"); + tinyMCEPopup.close(); + }, + + checkPrefix : function(n) { + if (n.value && Validator.isEmail(n) && !/^\s*mailto:/i.test(n.value) && confirm(tinyMCEPopup.getLang('advanced_dlg.link_is_email'))) + n.value = 'mailto:' + n.value; + + if (/^\s*www\./i.test(n.value) && confirm(tinyMCEPopup.getLang('advanced_dlg.link_is_external'))) + n.value = 'http://' + n.value; + }, + + fillFileList : function(id, l) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl; + + l = window[l]; + + if (l && l.length > 0) { + lst.options[lst.options.length] = new Option('', ''); + + tinymce.each(l, function(o) { + lst.options[lst.options.length] = new Option(o[0], o[1]); + }); + } else + dom.remove(dom.getParent(id, 'tr')); + }, + + fillClassList : function(id) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl; + + if (v = tinyMCEPopup.getParam('theme_advanced_styles')) { + cl = []; + + tinymce.each(v.split(';'), function(v) { + var p = v.split('='); + + cl.push({'title' : p[0], 'class' : p[1]}); + }); + } else + cl = tinyMCEPopup.editor.dom.getClasses(); + + if (cl.length > 0) { + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), ''); + + tinymce.each(cl, function(o) { + lst.options[lst.options.length] = new Option(o.title || o['class'], o['class']); + }); + } else + dom.remove(dom.getParent(id, 'tr')); + }, + + fillTargetList : function(id) { + var dom = tinyMCEPopup.dom, lst = dom.get(id), v; + + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), ''); + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('advanced_dlg.link_target_same'), '_self'); + lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('advanced_dlg.link_target_blank'), '_blank'); + + if (v = tinyMCEPopup.getParam('theme_advanced_link_targets')) { + tinymce.each(v.split(','), function(v) { + v = v.split('='); + lst.options[lst.options.length] = new Option(v[0], v[1]); + }); + } + } +}; + +LinkDialog.preInit(); +tinyMCEPopup.onInit.add(LinkDialog.init, LinkDialog); diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/source_editor.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/source_editor.js new file mode 100644 index 0000000..84546ad --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/js/source_editor.js @@ -0,0 +1,56 @@ +tinyMCEPopup.requireLangPack(); +tinyMCEPopup.onInit.add(onLoadInit); + +function saveContent() { + tinyMCEPopup.editor.setContent(document.getElementById('htmlSource').value, {source_view : true}); + tinyMCEPopup.close(); +} + +function onLoadInit() { + tinyMCEPopup.resizeToInnerSize(); + + // Remove Gecko spellchecking + if (tinymce.isGecko) + document.body.spellcheck = tinyMCEPopup.editor.getParam("gecko_spellcheck"); + + document.getElementById('htmlSource').value = tinyMCEPopup.editor.getContent({source_view : true}); + + if (tinyMCEPopup.editor.getParam("theme_advanced_source_editor_wrap", true)) { + setWrap('soft'); + document.getElementById('wraped').checked = true; + } + + resizeInputs(); +} + +function setWrap(val) { + var v, n, s = document.getElementById('htmlSource'); + + s.wrap = val; + + if (!tinymce.isIE) { + v = s.value; + n = s.cloneNode(false); + n.setAttribute("wrap", val); + s.parentNode.replaceChild(n, s); + n.value = v; + } +} + +function toggleWordWrap(elm) { + if (elm.checked) + setWrap('soft'); + else + setWrap('off'); +} + +function resizeInputs() { + var vp = tinyMCEPopup.dom.getViewPort(window), el; + + el = document.getElementById('htmlSource'); + + if (el) { + el.style.width = (vp.w - 20) + 'px'; + el.style.height = (vp.h - 65) + 'px'; + } +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/de.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/de.js new file mode 100644 index 0000000..034195c --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/de.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.advanced',{"underline_desc":"Unterstrichen (Strg+U)","italic_desc":"Kursiv (Strg+I)","bold_desc":"Fett (Strg+B)",dd:"Definitionsbeschreibung",dt:"Definitionsbegriff",samp:"Beispiel",code:"Code",blockquote:"Zitatblock",h6:"\u00dcberschrift 6",h5:"\u00dcberschrift 5",h4:"\u00dcberschrift 4",h3:"\u00dcberschrift 3",h2:"\u00dcberschrift 2",h1:"\u00dcberschrift 1",pre:"Rohdaten",address:"Adresse",div:"Zusammenh\u00e4ngender Bereich",paragraph:"Absatz",block:"Vorlage",fontdefault:"Schriftart","font_size":"Schriftgr\u00f6\u00dfe","style_select":"Format","anchor_delta_width":"13","more_colors":"Weitere Farben","toolbar_focus":"Zur Werkzeugleiste springen: Alt+Q; Zum Editor springen: Alt-Z; Zum Elementpfad springen: Alt-X",newdocument:"Wollen Sie wirklich den ganzen Inhalt l\u00f6schen?",path:"Pfad","clipboard_msg":"Kopieren, Ausschneiden und Einf\u00fcgen sind im Mozilla Firefox nicht m\u00f6glich.\nWollen Sie mehr \u00fcber dieses Problem erfahren?","blockquote_desc":"Zitatblock","help_desc":"Hilfe","newdocument_desc":"Neues Dokument","image_props_desc":"Bildeigenschaften","paste_desc":"Einf\u00fcgen","copy_desc":"Kopieren","cut_desc":"Ausschneiden","anchor_desc":"Anker einf\u00fcgen/ver\u00e4ndern","visualaid_desc":"Hilfslinien und unsichtbare Elemente ein-/ausblenden","charmap_desc":"Sonderzeichen einf\u00fcgen","backcolor_desc":"Hintergrundfarbe","forecolor_desc":"Textfarbe","custom1_desc":"Benutzerdefinierte Beschreibung","removeformat_desc":"Formatierungen zur\u00fccksetzen","hr_desc":"Trennlinie einf\u00fcgen","sup_desc":"Hochgestellt","sub_desc":"Tiefgestellt","code_desc":"HTML-Quellcode bearbeiten","cleanup_desc":"Quellcode aufr\u00e4umen","image_desc":"Bild einf\u00fcgen/ver\u00e4ndern","unlink_desc":"Link entfernen","link_desc":"Link einf\u00fcgen/ver\u00e4ndern","redo_desc":"Wiederholen (Strg+Y)","undo_desc":"R\u00fcckg\u00e4ngig (Strg+Z)","indent_desc":"Einr\u00fccken","outdent_desc":"Ausr\u00fccken","numlist_desc":"Sortierte Liste","bullist_desc":"Unsortierte Liste","justifyfull_desc":"Blocksatz","justifyright_desc":"Rechtsb\u00fcndig","justifycenter_desc":"Zentriert","justifyleft_desc":"Linksb\u00fcndig","striketrough_desc":"Durchgestrichen","help_shortcut":"Dr\u00fccken Sie ALT-F10 f\u00fcr die Toolbar. Dr\u00fccken Sie ALT-0 f\u00fcr Hilfe","rich_text_area":"Rich Text Feld","shortcuts_desc":"Eingabehilfe",toolbar:"Toolbar","anchor_delta_height":"","charmap_delta_height":"","charmap_delta_width":"","colorpicker_delta_height":"","colorpicker_delta_width":"","link_delta_height":"","link_delta_width":"","image_delta_height":"","image_delta_width":""}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/de_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/de_dlg.js new file mode 100644 index 0000000..b823694 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/de_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.advanced_dlg',{"link_list":"Linkliste","link_is_external":"Diese Adresse scheint ein externer Link zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"http://\" voranstellen?","link_is_email":"Diese Adresse scheint eine E-Mail-Adresse zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"mailto:\" voranstellen?","link_titlefield":"Titel","link_target_blank":"Neues Fenster \u00f6ffnen","link_target_same":"Im selben Fenster \u00f6ffnen","link_target":"Fenster","link_url":"Adresse","link_title":"Link einf\u00fcgen/ver\u00e4ndern","image_align_right":"Rechts","image_align_left":"Links","image_align_textbottom":"Unten im Text","image_align_texttop":"Oben im Text","image_align_bottom":"Unten","image_align_middle":"Mittig","image_align_top":"Oben","image_align_baseline":"Zeile","image_align":"Ausrichtung","image_hspace":"Horizontaler Abstand","image_vspace":"Vertikaler Abstand","image_dimensions":"Abmessungen","image_alt":"Alternativtext","image_list":"Bilderliste","image_border":"Rahmen","image_src":"Adresse","image_title":"Bild einf\u00fcgen/ver\u00e4ndern","charmap_title":"Sonderzeichen","colorpicker_name":"Name:","colorpicker_color":"Farbe:","colorpicker_named_title":"Benannte Farben","colorpicker_named_tab":"Benannte Farben","colorpicker_palette_title":"Farbpalette","colorpicker_palette_tab":"Palette","colorpicker_picker_title":"Farbwahl","colorpicker_picker_tab":"Farbwahl","colorpicker_title":"Farbe","code_wordwrap":"Automatischer Zeilenumbruch","code_title":"HTML-Quellcode bearbeiten","anchor_name":"Name des Ankers","anchor_title":"Anker einf\u00fcgen/ver\u00e4ndern","about_loaded":"Geladene Plugins","about_version":"Version","about_author":"Urheber","about_plugin":"Plugin","about_plugins":"Plugins","about_license":"Lizenzbedingungen","about_help":"Hilfe","about_general":"\u00dcber","about_title":"\u00dcber TinyMCE","charmap_usage":"Navigation mit linken und rechten Pfeilen.","anchor_invalid":"Bitte geben Sie einen g\u00fcltigen Namen f\u00fcr den Anker ein!","accessibility_help":"Eingabehilfe","accessibility_usage_title":"Allgemeine Verwendung"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/en.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/en.js new file mode 100644 index 0000000..6e58481 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/en.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.advanced',{"underline_desc":"Underline (Ctrl+U)","italic_desc":"Italic (Ctrl+I)","bold_desc":"Bold (Ctrl+B)",dd:"Definition Description",dt:"Definition Term ",samp:"Code Sample",code:"Code",blockquote:"Block Quote",h6:"Heading 6",h5:"Heading 5",h4:"Heading 4",h3:"Heading 3",h2:"Heading 2",h1:"Heading 1",pre:"Preformatted",address:"Address",div:"DIV",paragraph:"Paragraph",block:"Format",fontdefault:"Font Family","font_size":"Font Size","style_select":"Styles","anchor_delta_height":"","anchor_delta_width":"","charmap_delta_height":"","charmap_delta_width":"","colorpicker_delta_height":"","colorpicker_delta_width":"","link_delta_height":"","link_delta_width":"","image_delta_height":"","image_delta_width":"","more_colors":"More Colors...","toolbar_focus":"Jump to tool buttons - Alt+Q, Jump to editor - Alt-Z, Jump to element path - Alt-X",newdocument:"Are you sure you want clear all contents?",path:"Path","clipboard_msg":"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?","blockquote_desc":"Block Quote","help_desc":"Help","newdocument_desc":"New Document","image_props_desc":"Image Properties","paste_desc":"Paste (Ctrl+V)","copy_desc":"Copy (Ctrl+C)","cut_desc":"Cut (Ctrl+X)","anchor_desc":"Insert/Edit Anchor","visualaid_desc":"show/Hide Guidelines/Invisible Elements","charmap_desc":"Insert Special Character","backcolor_desc":"Select Background Color","forecolor_desc":"Select Text Color","custom1_desc":"Your Custom Description Here","removeformat_desc":"Remove Formatting","hr_desc":"Insert Horizontal Line","sup_desc":"Superscript","sub_desc":"Subscript","code_desc":"Edit HTML Source","cleanup_desc":"Cleanup Messy Code","image_desc":"Insert/Edit Image","unlink_desc":"Unlink","link_desc":"Insert/Edit Link","redo_desc":"Redo (Ctrl+Y)","undo_desc":"Undo (Ctrl+Z)","indent_desc":"Increase Indent","outdent_desc":"Decrease Indent","numlist_desc":"Insert/Remove Numbered List","bullist_desc":"Insert/Remove Bulleted List","justifyfull_desc":"Align Full","justifyright_desc":"Align Right","justifycenter_desc":"Align Center","justifyleft_desc":"Align Left","striketrough_desc":"Strikethrough","help_shortcut":"Press ALT-F10 for toolbar. Press ALT-0 for help","rich_text_area":"Rich Text Area","shortcuts_desc":"Accessability Help",toolbar:"Toolbar"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/en_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/en_dlg.js new file mode 100644 index 0000000..5e786e3 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/en_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.advanced_dlg',{"link_list":"Link List","link_is_external":"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?","link_is_email":"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?","link_titlefield":"Title","link_target_blank":"Open Link in a New Window","link_target_same":"Open Link in the Same Window","link_target":"Target","link_url":"Link URL","link_title":"Insert/Edit Link","image_align_right":"Right","image_align_left":"Left","image_align_textbottom":"Text Bottom","image_align_texttop":"Text Top","image_align_bottom":"Bottom","image_align_middle":"Middle","image_align_top":"Top","image_align_baseline":"Baseline","image_align":"Alignment","image_hspace":"Horizontal Space","image_vspace":"Vertical Space","image_dimensions":"Dimensions","image_alt":"Image Description","image_list":"Image List","image_border":"Border","image_src":"Image URL","image_title":"Insert/Edit Image","charmap_title":"Select Special Character","colorpicker_name":"Name:","colorpicker_color":"Color:","colorpicker_named_title":"Named Colors","colorpicker_named_tab":"Named","colorpicker_palette_title":"Palette Colors","colorpicker_palette_tab":"Palette","colorpicker_picker_title":"Color Picker","colorpicker_picker_tab":"Picker","colorpicker_title":"Select a Color","code_wordwrap":"Word Wrap","code_title":"HTML Source Editor","anchor_name":"Anchor Name","anchor_title":"Insert/Edit Anchor","about_loaded":"Loaded Plugins","about_version":"Version","about_author":"Author","about_plugin":"Plugin","about_plugins":"Plugins","about_license":"License","about_help":"Help","about_general":"About","about_title":"About TinyMCE","charmap_usage":"Use left and right arrows to navigate.","anchor_invalid":"Please specify a valid anchor name.","accessibility_help":"Accessibility Help","accessibility_usage_title":"General Usage"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/fr.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/fr.js new file mode 100644 index 0000000..1e91abb --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/fr.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.advanced',{"underline_desc":"Soulign\u00e9 (Ctrl+U)","italic_desc":"Italique (Ctrl+I)","bold_desc":"Gras (Ctrl+B)",dd:"D\u00e9finition du terme",dt:"Terme \u00e0 d\u00e9finir",samp:"Exemple de code",code:"Code",blockquote:"Bloc de citation",h6:"Titre 6",h5:"Titre 5",h4:"Titre 4",h3:"Titre 3",h2:"Titre 2",h1:"Titre 1",pre:"Pr\u00e9format\u00e9",address:"Adresse",div:"Div",paragraph:"Paragraphe",block:"Format",fontdefault:"Police","font_size":"Taille police","style_select":"Styles","more_colors":"Plus de couleurs","toolbar_focus":"Atteindre les boutons de l\'\u00e9diteur - Alt+Q, Aller \u00e0 l\'\u00e9diteur - Alt-Z, Aller au chemin de l\'\u00e9l\u00e9ment - Alt-X",newdocument:"\u00cates-vous s\u00fbr de vouloir effacer l\'int\u00e9gralit\u00e9 du document ?",path:"Chemin","clipboard_msg":"Les fonctions Copier/Couper/Coller ne sont pas valables sur Mozilla et Firefox.\nSouhaitez-vous avoir plus d\'informations sur ce sujet ?","blockquote_desc":"Citation","help_desc":"Aide","newdocument_desc":"Nouveau document","image_props_desc":"Propri\u00e9t\u00e9s de l\'image","paste_desc":"Coller","copy_desc":"Copier","cut_desc":"Couper","anchor_desc":"Ins\u00e9rer / \u00e9diter une ancre","visualaid_desc":"Activer / d\u00e9sactiver les guides et les \u00e9l\u00e9ments invisibles","charmap_desc":"Ins\u00e9rer des caract\u00e8res sp\u00e9ciaux","backcolor_desc":"Choisir la couleur de surlignage","forecolor_desc":"Choisir la couleur du texte","custom1_desc":"Votre description personnalis\u00e9e ici","removeformat_desc":"Supprimer le formatage","hr_desc":"Ins\u00e9rer un trait horizontal","sup_desc":"Exposant","sub_desc":"Indice","code_desc":"\u00c9diter le code source HTML","cleanup_desc":"Nettoyer le code","image_desc":"Ins\u00e9rer / \u00e9diter l\'image","unlink_desc":"Supprimer le lien","link_desc":"Ins\u00e9rer / \u00e9diter le lien","redo_desc":"R\u00e9tablir (Ctrl+Y)","undo_desc":"Annuler (Ctrl+Z)","indent_desc":"Indenter","outdent_desc":"Retirer l\'indentation","numlist_desc":"Liste num\u00e9rot\u00e9e","bullist_desc":"Liste \u00e0 puces","justifyfull_desc":"Justifi\u00e9","justifyright_desc":"Align\u00e9 \u00e0 droite","justifycenter_desc":"Centr\u00e9","justifyleft_desc":"Align\u00e9 \u00e0 gauche","striketrough_desc":"Barr\u00e9","help_shortcut":"Faites ALT-F10 pour acc\u00e9der \u00e0 la barre d\'outils. Faites ALT-0 pour acc\u00e9der \u00e0 l\'aide","rich_text_area":"Zone de texte enrichi","shortcuts_desc":"Aides \u00e0 l\'accessibilit\u00e9",toolbar:"Barre d\'outils","anchor_delta_height":"","anchor_delta_width":"","charmap_delta_height":"","charmap_delta_width":"","colorpicker_delta_height":"","colorpicker_delta_width":"","link_delta_height":"","link_delta_width":"","image_delta_height":"","image_delta_width":""}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/fr_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/fr_dlg.js new file mode 100644 index 0000000..2976296 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/fr_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.advanced_dlg',{"link_list":"Liste de liens","link_is_external":"L\'URL que vous avez saisie semble \u00eatre une adresse web externe. Souhaitez-vous ajouter le pr\u00e9fixe \u00ab http:// \u00bb ?","link_is_email":"L\'URL que vous avez saisie semble \u00eatre une adresse e-mail, souhaitez-vous ajouter le pr\u00e9fixe \u00ab mailto: \u00bb ?","link_titlefield":"Titre","link_target_blank":"Ouvrir dans une nouvelle fen\u00eatre","link_target_same":"Ouvrir dans la m\u00eame fen\u00eatre","link_target":"Cible","link_url":"URL du lien","link_title":"Ins\u00e9rer / \u00e9diter un lien","image_align_right":"Droite (flottant)","image_align_left":"Gauche (flottant)","image_align_textbottom":"Texte en bas","image_align_texttop":"Texte en haut","image_align_bottom":"En bas","image_align_middle":"Au milieu","image_align_top":"En haut","image_align_baseline":"Normal","image_align":"Alignement","image_hspace":"Espacement horizontal","image_vspace":"Espacement vertical","image_dimensions":"Dimensions","image_alt":"Description de l\'image","image_list":"Liste d\'images","image_border":"Bordure","image_src":"URL de l\'image","image_title":"Ins\u00e9rer / \u00e9diter une image","charmap_title":"Choisir le caract\u00e8re \u00e0 ins\u00e9rer","colorpicker_name":"Nom :","colorpicker_color":"Couleur :","colorpicker_named_title":"Couleurs nomm\u00e9es","colorpicker_named_tab":"Noms","colorpicker_palette_title":"Couleurs de la palette","colorpicker_palette_tab":"Palette","colorpicker_picker_title":"Nuancier","colorpicker_picker_tab":"Nuancier","colorpicker_title":"Choisir une couleur","code_wordwrap":"Retour \u00e0 la ligne","code_title":"\u00c9diteur de source HTML","anchor_name":"Nom de l\'ancre","anchor_title":"Ins\u00e9rer / \u00e9diter une ancre","about_loaded":"Plugins charg\u00e9s","about_version":"Version","about_author":"Auteur","about_plugin":"Plugin","about_plugins":"Plugins","about_license":"Licence","about_help":"Aide","about_general":"\u00c0 propos","about_title":"\u00c0 propos de TinyMCE","anchor_invalid":"Veuillez sp\u00e9cifier un nom d\'ancre valide.","accessibility_help":"Accessibility Help","accessibility_usage_title":"General Usage"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/it.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/it.js new file mode 100644 index 0000000..af84c79 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/it.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.advanced',{"underline_desc":"Sottolineato (Ctrl+U)","italic_desc":"Corsivo (Ctrl+I)","bold_desc":"Grassetto (Ctrl+B)",dd:"Descrizione definizione",dt:"Termine definizione",samp:"Esempio codice",code:"Codice",blockquote:"Testo quotato",h6:"Intestazione 6",h5:"Intestazione 5",h4:"Intestazione 4",h3:"Intestazione 3",h2:"Intestazione 2",h1:"Intestazione 1",pre:"Preformattato",address:"Indirizzo",div:"Div",paragraph:"Paragrafo",block:"Formato",fontdefault:"Famiglia carattere","font_size":"Grandezza carattere","style_select":"Stili","anchor_delta_height":"anchor_delta_height","anchor_delta_width":"anchor_delta_width","charmap_delta_height":"charmap_delta_height","charmap_delta_width":"charmap_delta_width","colorpicker_delta_height":"colorpicker_delta_height","colorpicker_delta_width":"colorpicker_delta_width","link_delta_height":"link_delta_height","link_delta_width":"link_delta_width","image_delta_height":"image_delta_height","image_delta_width":"image_delta_width","more_colors":"Colori aggiuntivi","toolbar_focus":"Vai ai pulsanti strumento - Alt+Q, Vai all\'editor - Alt-Z, Vai al percorso dell\'elemento - Alt-X",newdocument:"Sei sicuro di voler cancellare tutti i contenuti?",path:"Percorso","clipboard_msg":"Copia/Taglia/Incolla non \u00e8 disponibile in Mozilla e Firefox..\nSi desidera avere maggiori informazioni su questo problema?","blockquote_desc":"Testo quotato","help_desc":"Aiuto","newdocument_desc":"Nuovo documento","image_props_desc":"Propriet\u00e0 immagine","paste_desc":"Incolla","copy_desc":"Copia","cut_desc":"Taglia","anchor_desc":"Inserisci/modifica ancora","visualaid_desc":"Mostra/nascondi linee guida/elementi invisibili","charmap_desc":"Inserisci carattere speciale","backcolor_desc":"Seleziona colore sfondo","forecolor_desc":"Seleziona colore testo","custom1_desc":"La tua descrizione personalizzata qui","removeformat_desc":"Rimuovi formattazione","hr_desc":"Inserisci riga orizzontale","sup_desc":"Apice","sub_desc":"Pedice","code_desc":"Modifica sorgente HTML","cleanup_desc":"Pulisci codice disordinato","image_desc":"Inserisci/modifica immagine","unlink_desc":"Togli collegamento","link_desc":"Inserisci/modifica collegamento","redo_desc":"Ripristina (Ctrl+Y)","undo_desc":"Annulla (Ctrl+Z)","indent_desc":"Sposta verso interno","outdent_desc":"Sposta verso esterno","numlist_desc":"Lista ordinata","bullist_desc":"Lista non ordinata","justifyfull_desc":"Giustifica","justifyright_desc":"Allinea a destra","justifycenter_desc":"Centra","justifyleft_desc":"Allinea a sinistra","striketrough_desc":"Barrato","help_shortcut":"Premi ALT-F10 Per la barra degli strumenti. Premi ALT-0 per l\'aiuto","rich_text_area":"Rich Text Area","shortcuts_desc":"Aiuto accessibilit\u00e0",toolbar:"Barra degli strumenti"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/it_dlg.js b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/it_dlg.js new file mode 100644 index 0000000..10918c2 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/langs/it_dlg.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.advanced_dlg',{"link_list":"Lista link","link_is_external":"L\'URL inserito sembra essere un link esterno. Aggiungere il necessario prefisso http:// ?","link_is_email":"L\'URL inserito sembra essere un indirizzo email. Aggiungere il necessario prefisso mailto: ?","link_titlefield":"Titolo","link_target_blank":"Apri link in una nuova finestra","link_target_same":"Apri link nella stessa finestra","link_target":"Target","link_url":"URL link","link_title":"Inserisci/modifica collegamento","image_align_right":"A destra","image_align_left":"A sinistra","image_align_textbottom":"In basso al testo","image_align_texttop":"In alto al testo","image_align_bottom":"In basso","image_align_middle":"In mezzo","image_align_top":"In alto","image_align_baseline":"Alla base","image_align":"Allineamentot","image_hspace":"Spaziatura orizz.","image_vspace":"Spaziatura vert.","image_dimensions":"Dimensioni","image_alt":"Descrizione","image_list":"Lista immagini","image_border":"Bordo","image_src":"URL immagine","image_title":"Inserisci/modifica immagine","charmap_title":"Seleziona carattere speciale","colorpicker_name":"Nome:","colorpicker_color":"Colore:","colorpicker_named_title":"Colori per nome","colorpicker_named_tab":"Per nome","colorpicker_palette_title":"Tavolozza dei colori","colorpicker_palette_tab":"Tavolozza","colorpicker_picker_title":"Selettore colori","colorpicker_picker_tab":"Selettore","colorpicker_title":"Seleziona un colore","code_wordwrap":"A capo automatico","code_title":"Editor sorgente HTML","anchor_name":"Nome ancora","anchor_title":"Inserisci/modifica ancora","about_loaded":"Plugin caricati","about_version":"Versione","about_author":"Autore","about_plugin":"Plugin","about_plugins":"Plugins","about_license":"Licenza","about_help":"Aiuto","about_general":"Informazioni","about_title":"Informazioni su TinyMCE","anchor_invalid":"Specificare un nome di ancora valido.","accessibility_help":"Accessibility Help","accessibility_usage_title":"General Usage"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/link.htm b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/link.htm new file mode 100644 index 0000000..5d9dea9 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/link.htm @@ -0,0 +1,57 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.link_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="../../utils/mctabs.js"></script> + <script type="text/javascript" src="../../utils/form_utils.js"></script> + <script type="text/javascript" src="../../utils/validate.js"></script> + <script type="text/javascript" src="js/link.js"></script> +</head> +<body id="link" style="display: none"> +<form onsubmit="LinkDialog.update();return false;" action="#"> + <div class="tabs"> + <ul> + <li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.link_title}</a></span></li> + </ul> + </div> + + <div class="panel_wrapper"> + <div id="general_panel" class="panel current"> + <table border="0" cellpadding="4" cellspacing="0"> + <tr> + <td class="nowrap"><label for="href">{#advanced_dlg.link_url}</label></td> + <td><table border="0" cellspacing="0" cellpadding="0"> + <tr> + <td><input id="href" name="href" type="text" class="mceFocus" value="" style="width: 200px" onchange="LinkDialog.checkPrefix(this);" /></td> + <td id="hrefbrowsercontainer">&nbsp;</td> + </tr> + </table></td> + </tr> + <tr> + <td><label for="link_list">{#advanced_dlg.link_list}</label></td> + <td><select id="link_list" name="link_list" onchange="document.getElementById('href').value=this.options[this.selectedIndex].value;"></select></td> + </tr> + <tr> + <td><label id="targetlistlabel" for="targetlist">{#advanced_dlg.link_target}</label></td> + <td><select id="target_list" name="target_list"></select></td> + </tr> + <tr> + <td class="nowrap"><label for="linktitle">{#advanced_dlg.link_titlefield}</label></td> + <td><input id="linktitle" name="linktitle" type="text" value="" style="width: 200px" /></td> + </tr> + <tr> + <td><label for="class_list">{#class_name}</label></td> + <td><select id="class_list" name="class_list"></select></td> + </tr> + </table> + </div> + </div> + + <div class="mceActionPanel"> + <input type="submit" id="insert" name="insert" value="{#insert}" /> + <input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" /> + </div> +</form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/shortcuts.htm b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/shortcuts.htm new file mode 100644 index 0000000..20ec2f5 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/shortcuts.htm @@ -0,0 +1,47 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>{#advanced_dlg.accessibility_help}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript">tinyMCEPopup.requireLangPack();</script> + </head> + <body id="content"> + <h1>{#advanced_dlg.accessibility_usage_title}</h1> + <h2>Toolbars</h2> + <p>Press ALT-F10 to move focus to the toolbars. Navigate through the buttons using the arrow keys. + Press enter to activate a button and return focus to the editor. + Press escape to return focus to the editor without performing any actions.</p> + + <h2>Status Bar</h2> + <p>To access the editor status bar, press ALT-F11. Use the left and right arrow keys to navigate between elements in the path. + Press enter or space to select an element. Press escape to return focus to the editor without changing the selection.</p> + + <h2>Context Menu</h2> + <p>Press shift-F10 to activate the context menu. Use the up and down arrow keys to move between menu items. To open sub-menus press the right arrow key. + To close submenus press the left arrow key. Press escape to close the context menu.</p> + + <h1>Keyboard Shortcuts</h1> + <table> + <thead> + <tr> + <th>Keystroke</th> + <th>Function</th> + </tr> + </thead> + <tbody> + <tr> + <td>Control-B</td><td>Bold</td> + </tr> + <tr> + <td>Control-I</td><td>Italic</td> + </tr> + <tr> + <td>Control-Z</td><td>Undo</td> + </tr> + <tr> + <td>Control-Y</td><td>Redo</td> + </tr> + </tbody> + </table> + </body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/content.css b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/content.css new file mode 100644 index 0000000..2fd94a1 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/content.css @@ -0,0 +1,50 @@ +body, td, pre {color:#000; font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px; margin:8px;} +body {background:#FFF;} +body.mceForceColors {background:#FFF; color:#000;} +body.mceBrowserDefaults {background:transparent; color:inherit; font-size:inherit; font-family:inherit;} +h1 {font-size: 2em} +h2 {font-size: 1.5em} +h3 {font-size: 1.17em} +h4 {font-size: 1em} +h5 {font-size: .83em} +h6 {font-size: .75em} +.mceItemTable, .mceItemTable td, .mceItemTable th, .mceItemTable caption, .mceItemVisualAid {border: 1px dashed #BBB;} +a.mceItemAnchor {display:inline-block; -webkit-user-select:all; -webkit-user-modify:read-only; -moz-user-select:all; -moz-user-modify:read-only; width:11px !important; height:11px !important; background:url(img/items.gif) no-repeat center center} +span.mceItemNbsp {background: #DDD} +td.mceSelected, th.mceSelected {background-color:#3399ff !important} +img {border:0;} +table, img, hr, .mceItemAnchor {cursor:default} +table td, table th {cursor:text} +ins {border-bottom:1px solid green; text-decoration: none; color:green} +del {color:red; text-decoration:line-through} +cite {border-bottom:1px dashed blue} +acronym {border-bottom:1px dotted #CCC; cursor:help} +abbr {border-bottom:1px dashed #CCC; cursor:help} + +/* IE */ +* html body { +scrollbar-3dlight-color:#F0F0EE; +scrollbar-arrow-color:#676662; +scrollbar-base-color:#F0F0EE; +scrollbar-darkshadow-color:#DDD; +scrollbar-face-color:#E0E0DD; +scrollbar-highlight-color:#F0F0EE; +scrollbar-shadow-color:#F0F0EE; +scrollbar-track-color:#F5F5F5; +} + +img:-moz-broken {-moz-force-broken-image-icon:1; width:24px; height:24px} +font[face=mceinline] {font-family:inherit !important} +*[contentEditable]:focus {outline:0} + +.mceItemMedia {border:1px dotted #cc0000; background-position:center; background-repeat:no-repeat; background-color:#ffffcc} +.mceItemShockWave {background-image:url(../../img/shockwave.gif)} +.mceItemFlash {background-image:url(../../img/flash.gif)} +.mceItemQuickTime {background-image:url(../../img/quicktime.gif)} +.mceItemWindowsMedia {background-image:url(../../img/windowsmedia.gif)} +.mceItemRealMedia {background-image:url(../../img/realmedia.gif)} +.mceItemVideo {background-image:url(../../img/video.gif)} +.mceItemAudio {background-image:url(../../img/video.gif)} +.mceItemEmbeddedAudio {background-image:url(../../img/video.gif)} +.mceItemIframe {background-image:url(../../img/iframe.gif)} +.mcePageBreak {display:block;border:0;width:100%;height:12px;border-top:1px dotted #ccc;margin-top:15px;background:#fff url(../../img/pagebreak.gif) no-repeat center top;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/dialog.css b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/dialog.css new file mode 100644 index 0000000..f012226 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/dialog.css @@ -0,0 +1,117 @@ +/* Generic */ +body { +font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px; +scrollbar-3dlight-color:#F0F0EE; +scrollbar-arrow-color:#676662; +scrollbar-base-color:#F0F0EE; +scrollbar-darkshadow-color:#DDDDDD; +scrollbar-face-color:#E0E0DD; +scrollbar-highlight-color:#F0F0EE; +scrollbar-shadow-color:#F0F0EE; +scrollbar-track-color:#F5F5F5; +background:#F0F0EE; +padding:0; +margin:8px 8px 0 8px; +} + +html {background:#F0F0EE;} +td {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +textarea {resize:none;outline:none;} +a:link, a:visited {color:black;} +a:hover {color:#2B6FB6;} +.nowrap {white-space: nowrap} + +/* Forms */ +fieldset {margin:0; padding:4px; border:1px solid #919B9C; font-family:Verdana, Arial; font-size:10px;} +legend {color:#2B6FB6; font-weight:bold;} +label.msg {display:none;} +label.invalid {color:#EE0000; display:inline;} +input.invalid {border:1px solid #EE0000;} +input {background:#FFF; border:1px solid #CCC;} +input, select, textarea {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +input, select, textarea {border:1px solid #808080;} +input.radio {border:1px none #000000; background:transparent; vertical-align:middle;} +input.checkbox {border:1px none #000000; background:transparent; vertical-align:middle;} +.input_noborder {border:0;} + +/* Buttons */ +#insert, #cancel, input.button, .updateButton { +border:0; margin:0; padding:0; +font-weight:bold; +width:94px; height:26px; +background:url(img/buttons.png) 0 -26px; +cursor:pointer; +padding-bottom:2px; +float:left; +} + +#insert {background:url(img/buttons.png) 0 -52px} +#cancel {background:url(img/buttons.png) 0 0; float:right} + +/* Browse */ +a.pickcolor, a.browse {text-decoration:none} +a.browse span {display:block; width:20px; height:18px; background:url(../../img/icons.gif) -860px 0; border:1px solid #FFF; margin-left:1px;} +.mceOldBoxModel a.browse span {width:22px; height:20px;} +a.browse:hover span {border:1px solid #0A246A; background-color:#B2BBD0;} +a.browse span.disabled {border:1px solid white; opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +a.browse:hover span.disabled {border:1px solid white; background-color:transparent;} +a.pickcolor span {display:block; width:20px; height:16px; background:url(../../img/icons.gif) -840px 0; margin-left:2px;} +.mceOldBoxModel a.pickcolor span {width:21px; height:17px;} +a.pickcolor:hover span {background-color:#B2BBD0;} +a.pickcolor:hover span.disabled {} + +/* Charmap */ +table.charmap {border:1px solid #AAA; text-align:center} +td.charmap, #charmap a {width:18px; height:18px; color:#000; border:1px solid #AAA; text-align:center; font-size:12px; vertical-align:middle; line-height: 18px;} +#charmap a {display:block; color:#000; text-decoration:none; border:0} +#charmap a:hover {background:#CCC;color:#2B6FB6} +#charmap #codeN {font-size:10px; font-family:Arial,Helvetica,sans-serif; text-align:center} +#charmap #codeV {font-size:40px; height:80px; border:1px solid #AAA; text-align:center} + +/* Source */ +.wordWrapCode {vertical-align:middle; border:1px none #000000; background:transparent;} +.mceActionPanel {margin-top:5px;} + +/* Tabs classes */ +.tabs {width:100%; height:18px; line-height:normal; background:url(img/tabs.gif) repeat-x 0 -72px;} +.tabs ul {margin:0; padding:0; list-style:none;} +.tabs li {float:left; background:url(img/tabs.gif) no-repeat 0 0; margin:0 2px 0 0; padding:0 0 0 10px; line-height:17px; height:18px; display:block;} +.tabs li.current {background:url(img/tabs.gif) no-repeat 0 -18px; margin-right:2px;} +.tabs span {float:left; display:block; background:url(img/tabs.gif) no-repeat right -36px; padding:0px 10px 0 0;} +.tabs .current span {background:url(img/tabs.gif) no-repeat right -54px;} +.tabs a {text-decoration:none; font-family:Verdana, Arial; font-size:10px;} +.tabs a:link, .tabs a:visited, .tabs a:hover {color:black;} + +/* Panels */ +.panel_wrapper div.panel {display:none;} +.panel_wrapper div.current {display:block; width:100%; height:300px; overflow:visible;} +.panel_wrapper {border:1px solid #919B9C; border-top:0px; padding:10px; padding-top:5px; clear:both; background:white;} + +/* Columns */ +.column {float:left;} +.properties {width:100%;} +.properties .column1 {} +.properties .column2 {text-align:left;} + +/* Titles */ +h1, h2, h3, h4 {color:#2B6FB6; margin:0; padding:0; padding-top:5px;} +h3 {font-size:14px;} +.title {font-size:12px; font-weight:bold; color:#2B6FB6;} + +/* Dialog specific */ +#link .panel_wrapper, #link div.current {height:125px;} +#image .panel_wrapper, #image div.current {height:200px;} +#plugintable thead {font-weight:bold; background:#DDD;} +#plugintable, #about #plugintable td {border:1px solid #919B9C;} +#plugintable {width:96%; margin-top:10px;} +#pluginscontainer {height:290px; overflow:auto;} +#colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;} +#colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;} +#colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;} +#colorpicker #light div {overflow:hidden;} +#colorpicker #previewblock {float:right; padding-left:10px; height:20px;} +#colorpicker .panel_wrapper div.current {height:175px;} +#colorpicker #namedcolors {width:150px;} +#colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;} +#colorpicker #colornamecontainer {margin-top:5px;} +#colorpicker #picker_panel fieldset {margin:auto;width:325px;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/buttons.png b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/buttons.png new file mode 100644 index 0000000000000000000000000000000000000000..1e53560e0aa7bb1b9a0373fc2f330acab7d1d51f GIT binary patch literal 3133 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 XtZb~ra4Vor00000NkvXXu0mjf(5kL( literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/items.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/items.gif new file mode 100644 index 0000000000000000000000000000000000000000..d2f93671ca3090b277e16a67b1aa6cfb6ac4915f GIT binary patch literal 64 zcmZ?wbhEHb<YwSz_`t*f1poh^QT)lm%D}+HpabHAWE_~pU3$vJPT#)OT-dba%GH`< P{}UIOOiKDG%3uuu9X}L~ literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif new file mode 100644 index 0000000000000000000000000000000000000000..85e31dfb2d0454de352d87fe95f7003f22c87992 GIT binary patch literal 68 zcmZ?wbhEHb6k!lyXkcUjg8%>jEB<5wG8q|kKzxu41Cw-5|H{*E`4`XOxxoD9Y}F^Z SLTQbO*E^TJI;F+RU=09Vu@yA{ literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/menu_check.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/menu_check.gif new file mode 100644 index 0000000000000000000000000000000000000000..adfdddccd7cac62a17d68873fa53c248bff8351a GIT binary patch literal 70 zcmZ?wbhEHb6k!lyXkcUjg8%>jEB<5wG8q|kKzxu41Cwk||H{*E`4`XG(j;}D)%x|1 U%)82UlRJ8EoZ9xTT7<zG0H3rM{r~^~ literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/progress.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/progress.gif new file mode 100644 index 0000000000000000000000000000000000000000..5bb90fd6a49107a321c35b9cee4a7b810314b51f GIT binary patch literal 1787 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 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/tabs.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/img/tabs.gif new file mode 100644 index 0000000000000000000000000000000000000000..06812cb4109b0b236b9659c570458842e39c6416 GIT binary patch literal 1322 zcmV+_1=adTNk%w1VJrb!0QEKi{QUg<{QfdZVv?e=w#3bmr?lkh?BnU|?eX)Wv%9Ie zzvJoa`uqFH(aq4-(D3l;^z`rZ^X~HU?eX#K@bK&Q_VV@h@$~fY^YicW^6v5R?e_Nb z_4V@m`}z3z_V)Jl{r&v>{QLU)`S|$v@$cX6?dI$1<L~b1?Ca(6@aypJ>gD3v=j7e% z=;7w$-Rb7w=;hz@@$UBY^8Wt*`uh6+|Nj60000000000000000000000000000000 z00000A^8La001@sEC2ui04xDo06+%+K$1gIC>oE*q;kn@I-k&}bV{vSuh^_MTj5x~ z;IMd1E}PHjw0g~MyWjA*d`_1aD382;&+q&HfPsR8goTEOh>41ejE#<s1p$(il$Dm3 zl{K21oSmMZprN9pq@|{(sHv)}tgWu4k(jcxnXk6DxVgH!yuGeAz`?@9#Kp$P$jQpf z%+1cv(9zP<)Ya26Dh1Zt+}+;a;Njxq$|x+_<mu|`?CtLB0|V&q^!4`l_~erF`ThR? z00RmfNU)&6g9sBUT)3?O4G|C{N}NcsqQ#3CGiuz(v7^V2AVZ2ANwOr#0udreSjn=b z%a<@?%A85Frp=o;bL!m5v!~DhpFn*Uh)1-j(W6L{DqYI7sne%Wqe`7hwW`&tShL2W z#TApUuVBN99ZR+q!?S49woA}}gxa@o<5pAgf}h;Gc=HBpvBIw2zktu~3rx6h!oh|U zD_+dFvEyV44$PQLxw7TUm@{kM%(=7Y&!9t#9!<Km>C>oB7x?gDgX`C@W6PdRySDAy zxO3~?&AYen-@t<lA0E8Gg$o#xD__pMx%21Hqf4Joy}I@5*t2Wj&b_;L?gds(7*D>u z`Sa-0t6$H)z5Dm@<IA5<zrOwZ`0X=rAfUhh{{RLk;D7`cXyAbeCaB<o3^wTCgAhh2 zVT4<CW#J@cWvJnX9Cn!hN`)6%=;4SYmS|!xAcn}*i7dA0;)|Z7sN#$?)@b96IOeG1 zjy(2=<6}Su3C;`)C?MpKNKTVN3w|Z(<dejd07H{dR_P=PE>LOZmO%>O00UfxnIvLj zmiZW&W~QkanrgNg7@Ka!Dd(JY)@kRRc;=aq0|XcV<DY;ADkv!hfB*sjAtb8kqKr1` z=%bKED(R$@R%+>`m}aW!rkr-_>81sY;K8V*mTKy$sHUpws;su^>Z`EED(kGY)@tjm zxZYZTYZdhB>#x8DE9|hu7HjOW$R?}ovdlK??6c5DD=oAId~w{h*k-Hkw%m5>?YH2D zEAF`DmTT_0=%%ax?z-w0009Ik#VhZ;^ww+dz4+#<@4o!@>+in+2Q2Ww1Q$$j0U2bV z!NLqT?C`@7M=bHg6jyBV#TaL-@x~l??D5ASdtAVH6qIc8$tb6+^2#i??DESn$1L;A zG}mnN%{b?*GtOJ|?DNk+2QBo_L>Daue_181^wLZ>?ex=7N9~l1I}U2~)mXDawT@YL z?e*83Y@H+6WS1?d*f^T4_Sz?+eIwg&$E~5;Hp*@H-M-LWBi?-X{fgc`1}^yEgcol3 z;X3N6_(2E|;K1UL57dDST1Ia9J29Y8`Q@Cev*hNThaS!eb%|~|J5qvv`s&nRsXFVh zKVw2)vDa=#`|SV?;3e+7Ljz~;z#H>>@Wcl*eDTB|k38_oFVB1P&fgAw^tDe<{q@*q gul@Gickli8;D;~%_~eUY^!ezgum1Y%w;u!mJFYAXt^fc4 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/ui.css b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/ui.css new file mode 100644 index 0000000..2b7c2a5 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/default/ui.css @@ -0,0 +1,214 @@ +/* Reset */ +.defaultSkin table, .defaultSkin tbody, .defaultSkin a, .defaultSkin img, .defaultSkin tr, .defaultSkin div, .defaultSkin td, .defaultSkin iframe, .defaultSkin span, .defaultSkin *, .defaultSkin .mceText {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000; vertical-align:baseline; width:auto; border-collapse:separate; text-align:left} +.defaultSkin a:hover, .defaultSkin a:link, .defaultSkin a:visited, .defaultSkin a:active {text-decoration:none; font-weight:normal; cursor:default; color:#000} +.defaultSkin table td {vertical-align:middle} + +/* Containers */ +.defaultSkin table {direction:ltr;background:transparent} +.defaultSkin iframe {display:block;} +.defaultSkin .mceToolbar {height:26px} +.defaultSkin .mceLeft {text-align:left} +.defaultSkin .mceRight {text-align:right} + +/* External */ +.defaultSkin .mceExternalToolbar {position:absolute; border:1px solid #CCC; border-bottom:0; display:none;} +.defaultSkin .mceExternalToolbar td.mceToolbar {padding-right:13px;} +.defaultSkin .mceExternalClose {position:absolute; top:3px; right:3px; width:7px; height:7px; background:url(../../img/icons.gif) -820px 0} + +/* Layout */ +.defaultSkin table.mceLayout {border:0; border-left:1px solid #CCC; border-right:1px solid #CCC} +.defaultSkin table.mceLayout tr.mceFirst td {border-top:1px solid #CCC} +.defaultSkin table.mceLayout tr.mceLast td {border-bottom:1px solid #CCC} +.defaultSkin table.mceToolbar, .defaultSkin tr.mceFirst .mceToolbar tr td, .defaultSkin tr.mceLast .mceToolbar tr td {border:0; margin:0; padding:0;} +.defaultSkin td.mceToolbar {background:#F0F0EE; padding-top:1px; vertical-align:top} +.defaultSkin .mceIframeContainer {border-top:1px solid #CCC; border-bottom:1px solid #CCC} +.defaultSkin .mceStatusbar {background:#F0F0EE; font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:9pt; line-height:16px; overflow:visible; color:#000; display:block; height:20px} +.defaultSkin .mceStatusbar div {float:left; margin:2px} +.defaultSkin .mceStatusbar a.mceResize {display:block; float:right; background:url(../../img/icons.gif) -800px 0; width:20px; height:20px; cursor:se-resize; outline:0} +.defaultSkin .mceStatusbar a:hover {text-decoration:underline} +.defaultSkin table.mceToolbar {margin-left:3px} +.defaultSkin span.mceIcon, .defaultSkin img.mceIcon {display:block; width:20px; height:20px} +.defaultSkin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px} +.defaultSkin td.mceCenter {text-align:center;} +.defaultSkin td.mceCenter table {margin:0 auto; text-align:left;} +.defaultSkin td.mceRight table {margin:0 0 0 auto;} + +/* Button */ +.defaultSkin .mceButton {display:block; border:1px solid #F0F0EE; width:20px; height:20px; margin-right:1px} +.defaultSkin a.mceButtonEnabled:hover {border:1px solid #0A246A; background-color:#B2BBD0} +.defaultSkin a.mceButtonActive, .defaultSkin a.mceButtonSelected {border:1px solid #0A246A; background-color:#C2CBE0} +.defaultSkin .mceButtonDisabled .mceIcon {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +.defaultSkin .mceButtonLabeled {width:auto} +.defaultSkin .mceButtonLabeled span.mceIcon {float:left} +.defaultSkin span.mceButtonLabel {display:block; font-size:10px; padding:4px 6px 0 22px; font-family:Tahoma,Verdana,Arial,Helvetica} +.defaultSkin .mceButtonDisabled .mceButtonLabel {color:#888} + +/* Separator */ +.defaultSkin .mceSeparator {display:block; background:url(../../img/icons.gif) -180px 0; width:2px; height:20px; margin:2px 2px 0 4px} + +/* ListBox */ +.defaultSkin .mceListBox, .defaultSkin .mceListBox a {display:block} +.defaultSkin .mceListBox .mceText {padding-left:4px; width:70px; text-align:left; border:1px solid #CCC; border-right:0; background:#FFF; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; height:20px; line-height:20px; overflow:hidden} +.defaultSkin .mceListBox .mceOpen {width:9px; height:20px; background:url(../../img/icons.gif) -741px 0; margin-right:2px; border:1px solid #CCC;} +.defaultSkin table.mceListBoxEnabled:hover .mceText, .defaultSkin .mceListBoxHover .mceText, .defaultSkin .mceListBoxSelected .mceText {border:1px solid #A2ABC0; border-right:0; background:#FFF} +.defaultSkin table.mceListBoxEnabled:hover .mceOpen, .defaultSkin .mceListBoxHover .mceOpen, .defaultSkin .mceListBoxSelected .mceOpen {background-color:#FFF; border:1px solid #A2ABC0} +.defaultSkin .mceListBoxDisabled a.mceText {color:gray; background-color:transparent;} +.defaultSkin .mceListBoxMenu {overflow:auto; overflow-x:hidden} +.defaultSkin .mceOldBoxModel .mceListBox .mceText {height:22px} +.defaultSkin .mceOldBoxModel .mceListBox .mceOpen {width:11px; height:22px;} +.defaultSkin select.mceNativeListBox {font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:7pt; background:#F0F0EE; border:1px solid gray; margin-right:2px;} + +/* SplitButton */ +.defaultSkin .mceSplitButton {width:32px; height:20px; direction:ltr} +.defaultSkin .mceSplitButton a, .defaultSkin .mceSplitButton span {height:20px; display:block} +.defaultSkin .mceSplitButton a.mceAction {width:20px; border:1px solid #F0F0EE; border-right:0;} +.defaultSkin .mceSplitButton span.mceAction {width:20px; background-image:url(../../img/icons.gif);} +.defaultSkin .mceSplitButton a.mceOpen {width:9px; background:url(../../img/icons.gif) -741px 0; border:1px solid #F0F0EE;} +.defaultSkin .mceSplitButton span.mceOpen {display:none} +.defaultSkin table.mceSplitButtonEnabled:hover a.mceAction, .defaultSkin .mceSplitButtonHover a.mceAction, .defaultSkin .mceSplitButtonSelected a.mceAction {border:1px solid #0A246A; border-right:0; background-color:#B2BBD0} +.defaultSkin table.mceSplitButtonEnabled:hover a.mceOpen, .defaultSkin .mceSplitButtonHover a.mceOpen, .defaultSkin .mceSplitButtonSelected a.mceOpen {background-color:#B2BBD0; border:1px solid #0A246A;} +.defaultSkin .mceSplitButtonDisabled .mceAction, .defaultSkin .mceSplitButtonDisabled a.mceOpen {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +.defaultSkin .mceSplitButtonActive a.mceAction {border:1px solid #0A246A; background-color:#C2CBE0} +.defaultSkin .mceSplitButtonActive a.mceOpen {border-left:0;} + +/* ColorSplitButton */ +.defaultSkin div.mceColorSplitMenu table {background:#FFF; border:1px solid gray} +.defaultSkin .mceColorSplitMenu td {padding:2px} +.defaultSkin .mceColorSplitMenu a {display:block; width:9px; height:9px; overflow:hidden; border:1px solid #808080} +.defaultSkin .mceColorSplitMenu td.mceMoreColors {padding:1px 3px 1px 1px} +.defaultSkin .mceColorSplitMenu a.mceMoreColors {width:100%; height:auto; text-align:center; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; line-height:20px; border:1px solid #FFF} +.defaultSkin .mceColorSplitMenu a.mceMoreColors:hover {border:1px solid #0A246A; background-color:#B6BDD2} +.defaultSkin a.mceMoreColors:hover {border:1px solid #0A246A} +.defaultSkin .mceColorPreview {margin-left:2px; width:16px; height:4px; overflow:hidden; background:#9a9b9a} +.defaultSkin .mce_forecolor span.mceAction, .defaultSkin .mce_backcolor span.mceAction {overflow:hidden; height:16px} + +/* Menu */ +.defaultSkin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #D4D0C8} +.defaultSkin .mceNoIcons span.mceIcon {width:0;} +.defaultSkin .mceNoIcons a .mceText {padding-left:10px} +.defaultSkin .mceMenu table {background:#FFF} +.defaultSkin .mceMenu a, .defaultSkin .mceMenu span, .defaultSkin .mceMenu {display:block} +.defaultSkin .mceMenu td {height:20px} +.defaultSkin .mceMenu a {position:relative;padding:3px 0 4px 0} +.defaultSkin .mceMenu .mceText {position:relative; display:block; font-family:Tahoma,Verdana,Arial,Helvetica; color:#000; cursor:default; margin:0; padding:0 25px 0 25px; display:block} +.defaultSkin .mceMenu span.mceText, .defaultSkin .mceMenu .mcePreview {font-size:11px} +.defaultSkin .mceMenu pre.mceText {font-family:Monospace} +.defaultSkin .mceMenu .mceIcon {position:absolute; top:0; left:0; width:22px;} +.defaultSkin .mceMenu .mceMenuItemEnabled a:hover, .defaultSkin .mceMenu .mceMenuItemActive {background-color:#dbecf3} +.defaultSkin td.mceMenuItemSeparator {background:#DDD; height:1px} +.defaultSkin .mceMenuItemTitle a {border:0; background:#EEE; border-bottom:1px solid #DDD} +.defaultSkin .mceMenuItemTitle span.mceText {color:#000; font-weight:bold; padding-left:4px} +.defaultSkin .mceMenuItemDisabled .mceText {color:#888} +.defaultSkin .mceMenuItemSelected .mceIcon {background:url(img/menu_check.gif)} +.defaultSkin .mceNoIcons .mceMenuItemSelected a {background:url(img/menu_arrow.gif) no-repeat -6px center} +.defaultSkin .mceMenu span.mceMenuLine {display:none} +.defaultSkin .mceMenuItemSub a {background:url(img/menu_arrow.gif) no-repeat top right;} +.defaultSkin .mceMenuItem td, .defaultSkin .mceMenuItem th {line-height: normal} + +/* Progress,Resize */ +.defaultSkin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=50)'; filter:alpha(opacity=50); background:#FFF} +.defaultSkin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px} + +/* Formats */ +.defaultSkin .mce_formatPreview a {font-size:10px} +.defaultSkin .mce_p span.mceText {} +.defaultSkin .mce_address span.mceText {font-style:italic} +.defaultSkin .mce_pre span.mceText {font-family:monospace} +.defaultSkin .mce_h1 span.mceText {font-weight:bolder; font-size: 2em} +.defaultSkin .mce_h2 span.mceText {font-weight:bolder; font-size: 1.5em} +.defaultSkin .mce_h3 span.mceText {font-weight:bolder; font-size: 1.17em} +.defaultSkin .mce_h4 span.mceText {font-weight:bolder; font-size: 1em} +.defaultSkin .mce_h5 span.mceText {font-weight:bolder; font-size: .83em} +.defaultSkin .mce_h6 span.mceText {font-weight:bolder; font-size: .75em} + +/* Theme */ +.defaultSkin span.mce_bold {background-position:0 0} +.defaultSkin span.mce_italic {background-position:-60px 0} +.defaultSkin span.mce_underline {background-position:-140px 0} +.defaultSkin span.mce_strikethrough {background-position:-120px 0} +.defaultSkin span.mce_undo {background-position:-160px 0} +.defaultSkin span.mce_redo {background-position:-100px 0} +.defaultSkin span.mce_cleanup {background-position:-40px 0} +.defaultSkin span.mce_bullist {background-position:-20px 0} +.defaultSkin span.mce_numlist {background-position:-80px 0} +.defaultSkin span.mce_justifyleft {background-position:-460px 0} +.defaultSkin span.mce_justifyright {background-position:-480px 0} +.defaultSkin span.mce_justifycenter {background-position:-420px 0} +.defaultSkin span.mce_justifyfull {background-position:-440px 0} +.defaultSkin span.mce_anchor {background-position:-200px 0} +.defaultSkin span.mce_indent {background-position:-400px 0} +.defaultSkin span.mce_outdent {background-position:-540px 0} +.defaultSkin span.mce_link {background-position:-500px 0} +.defaultSkin span.mce_unlink {background-position:-640px 0} +.defaultSkin span.mce_sub {background-position:-600px 0} +.defaultSkin span.mce_sup {background-position:-620px 0} +.defaultSkin span.mce_removeformat {background-position:-580px 0} +.defaultSkin span.mce_newdocument {background-position:-520px 0} +.defaultSkin span.mce_image {background-position:-380px 0} +.defaultSkin span.mce_help {background-position:-340px 0} +.defaultSkin span.mce_code {background-position:-260px 0} +.defaultSkin span.mce_hr {background-position:-360px 0} +.defaultSkin span.mce_visualaid {background-position:-660px 0} +.defaultSkin span.mce_charmap {background-position:-240px 0} +.defaultSkin span.mce_paste {background-position:-560px 0} +.defaultSkin span.mce_copy {background-position:-700px 0} +.defaultSkin span.mce_cut {background-position:-680px 0} +.defaultSkin span.mce_blockquote {background-position:-220px 0} +.defaultSkin .mce_forecolor span.mceAction {background-position:-720px 0} +.defaultSkin .mce_backcolor span.mceAction {background-position:-760px 0} +.defaultSkin span.mce_forecolorpicker {background-position:-720px 0} +.defaultSkin span.mce_backcolorpicker {background-position:-760px 0} + +/* Plugins */ +.defaultSkin span.mce_advhr {background-position:-0px -20px} +.defaultSkin span.mce_ltr {background-position:-20px -20px} +.defaultSkin span.mce_rtl {background-position:-40px -20px} +.defaultSkin span.mce_emotions {background-position:-60px -20px} +.defaultSkin span.mce_fullpage {background-position:-80px -20px} +.defaultSkin span.mce_fullscreen {background-position:-100px -20px} +.defaultSkin span.mce_iespell {background-position:-120px -20px} +.defaultSkin span.mce_insertdate {background-position:-140px -20px} +.defaultSkin span.mce_inserttime {background-position:-160px -20px} +.defaultSkin span.mce_absolute {background-position:-180px -20px} +.defaultSkin span.mce_backward {background-position:-200px -20px} +.defaultSkin span.mce_forward {background-position:-220px -20px} +.defaultSkin span.mce_insert_layer {background-position:-240px -20px} +.defaultSkin span.mce_insertlayer {background-position:-260px -20px} +.defaultSkin span.mce_movebackward {background-position:-280px -20px} +.defaultSkin span.mce_moveforward {background-position:-300px -20px} +.defaultSkin span.mce_media {background-position:-320px -20px} +.defaultSkin span.mce_nonbreaking {background-position:-340px -20px} +.defaultSkin span.mce_pastetext {background-position:-360px -20px} +.defaultSkin span.mce_pasteword {background-position:-380px -20px} +.defaultSkin span.mce_selectall {background-position:-400px -20px} +.defaultSkin span.mce_preview {background-position:-420px -20px} +.defaultSkin span.mce_print {background-position:-440px -20px} +.defaultSkin span.mce_cancel {background-position:-460px -20px} +.defaultSkin span.mce_save {background-position:-480px -20px} +.defaultSkin span.mce_replace {background-position:-500px -20px} +.defaultSkin span.mce_search {background-position:-520px -20px} +.defaultSkin span.mce_styleprops {background-position:-560px -20px} +.defaultSkin span.mce_table {background-position:-580px -20px} +.defaultSkin span.mce_cell_props {background-position:-600px -20px} +.defaultSkin span.mce_delete_table {background-position:-620px -20px} +.defaultSkin span.mce_delete_col {background-position:-640px -20px} +.defaultSkin span.mce_delete_row {background-position:-660px -20px} +.defaultSkin span.mce_col_after {background-position:-680px -20px} +.defaultSkin span.mce_col_before {background-position:-700px -20px} +.defaultSkin span.mce_row_after {background-position:-720px -20px} +.defaultSkin span.mce_row_before {background-position:-740px -20px} +.defaultSkin span.mce_merge_cells {background-position:-760px -20px} +.defaultSkin span.mce_table_props {background-position:-980px -20px} +.defaultSkin span.mce_row_props {background-position:-780px -20px} +.defaultSkin span.mce_split_cells {background-position:-800px -20px} +.defaultSkin span.mce_template {background-position:-820px -20px} +.defaultSkin span.mce_visualchars {background-position:-840px -20px} +.defaultSkin span.mce_abbr {background-position:-860px -20px} +.defaultSkin span.mce_acronym {background-position:-880px -20px} +.defaultSkin span.mce_attribs {background-position:-900px -20px} +.defaultSkin span.mce_cite {background-position:-920px -20px} +.defaultSkin span.mce_del {background-position:-940px -20px} +.defaultSkin span.mce_ins {background-position:-960px -20px} +.defaultSkin span.mce_pagebreak {background-position:0 -40px} +.defaultSkin span.mce_restoredraft {background-position:-20px -40px} +.defaultSkin span.mce_spellchecker {background-position:-540px -20px} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/content.css b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/content.css new file mode 100644 index 0000000..cbce6c6 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/content.css @@ -0,0 +1,24 @@ +body, td, pre { margin:8px;} +body.mceForceColors {background:#FFF; color:#000;} +h1 {font-size: 2em} +h2 {font-size: 1.5em} +h3 {font-size: 1.17em} +h4 {font-size: 1em} +h5 {font-size: .83em} +h6 {font-size: .75em} +.mceItemTable, .mceItemTable td, .mceItemTable th, .mceItemTable caption, .mceItemVisualAid {border: 1px dashed #BBB;} +a.mceItemAnchor {display:inline-block; width:11px !important; height:11px !important; background:url(../default/img/items.gif) no-repeat 0 0;} +span.mceItemNbsp {background: #DDD} +td.mceSelected, th.mceSelected {background-color:#3399ff !important} +img {border:0;} +table, img, hr, .mceItemAnchor {cursor:default} +table td, table th {cursor:text} +ins {border-bottom:1px solid green; text-decoration: none; color:green} +del {color:red; text-decoration:line-through} +cite {border-bottom:1px dashed blue} +acronym {border-bottom:1px dotted #CCC; cursor:help} +abbr {border-bottom:1px dashed #CCC; cursor:help} + +img:-moz-broken {-moz-force-broken-image-icon:1; width:24px; height:24px} +font[face=mceinline] {font-family:inherit !important} +*[contentEditable]:focus {outline:0} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/dialog.css b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/dialog.css new file mode 100644 index 0000000..b2ed097 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/dialog.css @@ -0,0 +1,105 @@ +/* Generic */ +body { +font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px; +background:#F0F0EE; +color: black; +padding:0; +margin:8px 8px 0 8px; +} + +html {background:#F0F0EE; color:#000;} +td {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +textarea {resize:none;outline:none;} +a:link, a:visited {color:black;background-color:transparent;} +a:hover {color:#2B6FB6;background-color:transparent;} +.nowrap {white-space: nowrap} + +/* Forms */ +fieldset {margin:0; padding:4px; border:1px solid #919B9C; font-family:Verdana, Arial; font-size:10px;} +legend {color:#2B6FB6; font-weight:bold;} +label.msg {display:none;} +label.invalid {color:#EE0000; display:inline;background-color:transparent;} +input.invalid {border:1px solid #EE0000;background-color:transparent;} +input {background:#FFF; border:1px solid #CCC;color:black;} +input, select, textarea {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +input, select, textarea {border:1px solid #808080;} +input.radio {border:1px none #000000; background:transparent; vertical-align:middle;} +input.checkbox {border:1px none #000000; background:transparent; vertical-align:middle;} +.input_noborder {border:0;} + +/* Buttons */ +#insert, #cancel, input.button, .updateButton { +font-weight:bold; +width:94px; height:23px; +cursor:pointer; +padding-bottom:2px; +float:left; +} + +#cancel {float:right} + +/* Browse */ +a.pickcolor, a.browse {text-decoration:none} +a.browse span {display:block; width:20px; height:18px; background:url(../../img/icons.gif) -860px 0; border:1px solid #FFF; margin-left:1px;} +.mceOldBoxModel a.browse span {width:22px; height:20px;} +a.browse:hover span {border:1px solid #0A246A; background-color:#B2BBD0;} +a.browse span.disabled {border:1px solid white; opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +a.browse:hover span.disabled {border:1px solid white; background-color:transparent;} +a.pickcolor span {display:block; width:20px; height:16px; background:url(../../img/icons.gif) -840px 0; margin-left:2px;} +.mceOldBoxModel a.pickcolor span {width:21px; height:17px;} +a.pickcolor:hover span {background-color:#B2BBD0;} +a.pickcolor:hover span.disabled {} + +/* Charmap */ +table.charmap {border:1px solid #AAA; text-align:center} +td.charmap, #charmap a {width:18px; height:18px; color:#000; border:1px solid #AAA; text-align:center; font-size:12px; vertical-align:middle; line-height: 18px;} +#charmap a {display:block; color:#000; text-decoration:none; border:0} +#charmap a:hover {background:#CCC;color:#2B6FB6} +#charmap #codeN {font-size:10px; font-family:Arial,Helvetica,sans-serif; text-align:center} +#charmap #codeV {font-size:40px; height:80px; border:1px solid #AAA; text-align:center} + +/* Source */ +.wordWrapCode {vertical-align:middle; border:1px none #000000; background:transparent;} +.mceActionPanel {margin-top:5px;} + +/* Tabs classes */ +.tabs {width:100%; height:18px; line-height:normal;} +.tabs ul {margin:0; padding:0; list-style:none;} +.tabs li {float:left; border: 1px solid black; border-bottom:0; margin:0 2px 0 0; padding:0 0 0 10px; line-height:17px; height:18px; display:block; cursor:pointer;} +.tabs li.current {font-weight: bold; margin-right:2px;} +.tabs span {float:left; display:block; padding:0px 10px 0 0;} +.tabs a {text-decoration:none; font-family:Verdana, Arial; font-size:10px;} +.tabs a:link, .tabs a:visited, .tabs a:hover {color:black;} + +/* Panels */ +.panel_wrapper div.panel {display:none;} +.panel_wrapper div.current {display:block; width:100%; height:300px; overflow:visible;} +.panel_wrapper {border:1px solid #919B9C; padding:10px; padding-top:5px; clear:both; background:white;} + +/* Columns */ +.column {float:left;} +.properties {width:100%;} +.properties .column1 {} +.properties .column2 {text-align:left;} + +/* Titles */ +h1, h2, h3, h4 {color:#2B6FB6; margin:0; padding:0; padding-top:5px;} +h3 {font-size:14px;} +.title {font-size:12px; font-weight:bold; color:#2B6FB6;} + +/* Dialog specific */ +#link .panel_wrapper, #link div.current {height:125px;} +#image .panel_wrapper, #image div.current {height:200px;} +#plugintable thead {font-weight:bold; background:#DDD;} +#plugintable, #about #plugintable td {border:1px solid #919B9C;} +#plugintable {width:96%; margin-top:10px;} +#pluginscontainer {height:290px; overflow:auto;} +#colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;} +#colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;} +#colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;} +#colorpicker #light div {overflow:hidden;} +#colorpicker #previewblock {float:right; padding-left:10px; height:20px;} +#colorpicker .panel_wrapper div.current {height:175px;} +#colorpicker #namedcolors {width:150px;} +#colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;} +#colorpicker #colornamecontainer {margin-top:5px;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/ui.css b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/ui.css new file mode 100644 index 0000000..a2cfcc3 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/highcontrast/ui.css @@ -0,0 +1,102 @@ +/* Reset */ +.highcontrastSkin table, .highcontrastSkin tbody, .highcontrastSkin a, .highcontrastSkin img, .highcontrastSkin tr, .highcontrastSkin div, .highcontrastSkin td, .highcontrastSkin iframe, .highcontrastSkin span, .highcontrastSkin *, .highcontrastSkin .mceText {border:0; margin:0; padding:0; vertical-align:baseline; border-collapse:separate;} +.highcontrastSkin a:hover, .highcontrastSkin a:link, .highcontrastSkin a:visited, .highcontrastSkin a:active {text-decoration:none; font-weight:normal; cursor:default;} +.highcontrastSkin table td {vertical-align:middle} + +.highcontrastSkin .mceIconOnly {display: block !important;} + +/* External */ +.highcontrastSkin .mceExternalToolbar {position:absolute; border:1px solid; border-bottom:0; display:none; background-color: white;} +.highcontrastSkin .mceExternalToolbar td.mceToolbar {padding-right:13px;} +.highcontrastSkin .mceExternalClose {position:absolute; top:3px; right:3px; width:7px; height:7px;} + +/* Layout */ +.highcontrastSkin table.mceLayout {border: 1px solid;} +.highcontrastSkin .mceIframeContainer {border-top:1px solid; border-bottom:1px solid} +.highcontrastSkin .mceStatusbar a:hover {text-decoration:underline} +.highcontrastSkin .mceStatusbar {display:block; line-height:1.5em; overflow:visible;} +.highcontrastSkin .mceStatusbar div {float:left} +.highcontrastSkin .mceStatusbar a.mceResize {display:block; float:right; width:20px; height:20px; cursor:se-resize; outline:0} + +.highcontrastSkin .mceToolbar td { display: inline-block; float: left;} +.highcontrastSkin .mceToolbar tr { display: block;} +.highcontrastSkin .mceToolbar table { display: block; } + +/* Button */ + +.highcontrastSkin .mceButton { display:block; margin: 2px; padding: 5px 10px;border: 1px solid; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; -ms-border-radius: 3px; height: 2em;} +.highcontrastSkin .mceButton .mceVoiceLabel { height: 100%; vertical-align: center; line-height: 2em} +.highcontrastSkin .mceButtonDisabled .mceVoiceLabel { opacity:0.6; -ms-filter:'alpha(opacity=60)'; filter:alpha(opacity=60);} +.highcontrastSkin .mceButtonActive, .highcontrastSkin .mceButton:focus, .highcontrastSkin .mceButton:active { border: 5px solid; padding: 1px 6px;-webkit-focus-ring-color:none;outline:none;} + +/* Separator */ +.highcontrastSkin .mceSeparator {display:block; width:16px; height:26px;} + +/* ListBox */ +.highcontrastSkin .mceListBox { display: block; margin:2px;-webkit-focus-ring-color:none;outline:none;} +.highcontrastSkin .mceListBox .mceText {padding: 5px 6px; line-height: 2em; width: 15ex; overflow: hidden;} +.highcontrastSkin .mceListBoxDisabled .mceText { opacity:0.6; -ms-filter:'alpha(opacity=60)'; filter:alpha(opacity=60);} +.highcontrastSkin .mceListBox a.mceText { padding: 5px 10px; display: block; height: 2em; line-height: 2em; border: 1px solid; border-right: 0; border-radius: 3px 0px 0px 3px; -moz-border-radius: 3px 0px 0px 3px; -webkit-border-radius: 3px 0px 0px 3px; -ms-border-radius: 3px 0px 0px 3px;} +.highcontrastSkin .mceListBox a.mceOpen { padding: 5px 4px; display: block; height: 2em; line-height: 2em; border: 1px solid; border-left: 0; border-radius: 0px 3px 3px 0px; -moz-border-radius: 0px 3px 3px 0px; -webkit-border-radius: 0px 3px 3px 0px; -ms-border-radius: 0px 3px 3px 0px;} +.highcontrastSkin .mceListBox:focus a.mceText, .highcontrastSkin .mceListBox:active a.mceText { border-width: 5px; padding: 1px 10px 1px 6px;} +.highcontrastSkin .mceListBox:focus a.mceOpen, .highcontrastSkin .mceListBox:active a.mceOpen { border-width: 5px; padding: 1px 0px 1px 4px;} + +.highcontrastSkin .mceListBoxMenu {overflow-y:auto} + +/* SplitButton */ +.highcontrastSkin .mceSplitButtonDisabled .mceAction {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} + +.highcontrastSkin .mceSplitButton { border-collapse: collapse; margin: 2px; height: 2em; line-height: 2em;-webkit-focus-ring-color:none;outline:none;} +.highcontrastSkin .mceSplitButton td { display: table-cell; float: none; margin: 0; padding: 0; height: 2em;} +.highcontrastSkin .mceSplitButton tr { display: table-row; } +.highcontrastSkin table.mceSplitButton { display: table; } +.highcontrastSkin .mceSplitButton a.mceAction { padding: 5px 10px; display: block; height: 2em; line-height: 2em; overflow: hidden; border: 1px solid; border-right: 0; border-radius: 3px 0px 0px 3px; -moz-border-radius: 3px 0px 0px 3px; -webkit-border-radius: 3px 0px 0px 3px; -ms-border-radius: 3px 0px 0px 3px;} +.highcontrastSkin .mceSplitButton a.mceOpen { padding: 5px 4px; display: block; height: 2em; line-height: 2em; border: 1px solid; border-radius: 0px 3px 3px 0px; -moz-border-radius: 0px 3px 3px 0px; -webkit-border-radius: 0px 3px 3px 0px; -ms-border-radius: 0px 3px 3px 0px;} +.highcontrastSkin .mceSplitButton .mceVoiceLabel { height: 2em; vertical-align: center; line-height: 2em; } +.highcontrastSkin .mceSplitButton:focus a.mceAction, .highcontrastSkin .mceSplitButton:active a.mceAction { border-width: 5px; border-right-width: 1px; padding: 1px 10px 1px 6px;-webkit-focus-ring-color:none;outline:none;} +.highcontrastSkin .mceSplitButton:focus a.mceOpen, .highcontrastSkin .mceSplitButton:active a.mceOpen { border-width: 5px; border-left-width: 1px; padding: 1px 0px 1px 4px;-webkit-focus-ring-color:none;outline:none;} + +/* Menu */ +.highcontrastSkin .mceNoIcons span.mceIcon {width:0;} +.highcontrastSkin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid; } +.highcontrastSkin .mceMenu table {background:white; color: black} +.highcontrastSkin .mceNoIcons a .mceText {padding-left:10px} +.highcontrastSkin .mceMenu a, .highcontrastSkin .mceMenu span, .highcontrastSkin .mceMenu {display:block;background:white; color: black} +.highcontrastSkin .mceMenu td {height:2em} +.highcontrastSkin .mceMenu a {position:relative;padding:3px 0 4px 0; display: block;} +.highcontrastSkin .mceMenu .mceText {position:relative; display:block; cursor:default; margin:0; padding:0 25px 0 25px;} +.highcontrastSkin .mceMenu pre.mceText {font-family:Monospace} +.highcontrastSkin .mceMenu .mceIcon {position:absolute; top:0; left:0; width:26px;} +.highcontrastSkin td.mceMenuItemSeparator {border-top:1px solid; height:1px} +.highcontrastSkin .mceMenuItemTitle a {border:0; border-bottom:1px solid} +.highcontrastSkin .mceMenuItemTitle span.mceText {font-weight:bold; padding-left:4px} +.highcontrastSkin .mceNoIcons .mceMenuItemSelected span.mceText:before {content: "\2713\A0";} +.highcontrastSkin .mceMenu span.mceMenuLine {display:none} +.highcontrastSkin .mceMenuItemSub a .mceText:after {content: "\A0\25B8"} +.highcontrastSkin .mceMenuItem td, .highcontrastSkin .mceMenuItem th {line-height: normal} + +/* ColorSplitButton */ +.highcontrastSkin div.mceColorSplitMenu table {background:#FFF; border:1px solid; color: #000} +.highcontrastSkin .mceColorSplitMenu td {padding:2px} +.highcontrastSkin .mceColorSplitMenu a {display:block; width:16px; height:16px; overflow:hidden; color:#000; margin: 0; padding: 0;} +.highcontrastSkin .mceColorSplitMenu td.mceMoreColors {padding:1px 3px 1px 1px} +.highcontrastSkin .mceColorSplitMenu a.mceMoreColors {width:100%; height:auto; text-align:center; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; line-height:20px; border:1px solid #FFF} +.highcontrastSkin .mceColorSplitMenu a.mceMoreColors:hover {border:1px solid; background-color:#B6BDD2} +.highcontrastSkin a.mceMoreColors:hover {border:1px solid #0A246A; color: #000;} +.highcontrastSkin .mceColorPreview {display:none;} +.highcontrastSkin .mce_forecolor span.mceAction, .highcontrastSkin .mce_backcolor span.mceAction {height:17px;overflow:hidden} + +/* Progress,Resize */ +.highcontrastSkin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=50); background:#FFF} +.highcontrastSkin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(../default/img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px} + +/* Formats */ +.highcontrastSkin .mce_p span.mceText {} +.highcontrastSkin .mce_address span.mceText {font-style:italic} +.highcontrastSkin .mce_pre span.mceText {font-family:monospace} +.highcontrastSkin .mce_h1 span.mceText {font-weight:bolder; font-size: 2em} +.highcontrastSkin .mce_h2 span.mceText {font-weight:bolder; font-size: 1.5em} +.highcontrastSkin .mce_h3 span.mceText {font-weight:bolder; font-size: 1.17em} +.highcontrastSkin .mce_h4 span.mceText {font-weight:bolder; font-size: 1em} +.highcontrastSkin .mce_h5 span.mceText {font-weight:bolder; font-size: .83em} +.highcontrastSkin .mce_h6 span.mceText {font-weight:bolder; font-size: .75em} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/content.css b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/content.css new file mode 100644 index 0000000..a1a8f9b --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/content.css @@ -0,0 +1,48 @@ +body, td, pre {color:#000; font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px; margin:8px;} +body {background:#FFF;} +body.mceForceColors {background:#FFF; color:#000;} +h1 {font-size: 2em} +h2 {font-size: 1.5em} +h3 {font-size: 1.17em} +h4 {font-size: 1em} +h5 {font-size: .83em} +h6 {font-size: .75em} +.mceItemTable, .mceItemTable td, .mceItemTable th, .mceItemTable caption, .mceItemVisualAid {border: 1px dashed #BBB;} +a.mceItemAnchor {display:inline-block; width:11px !important; height:11px !important; background:url(../default/img/items.gif) no-repeat 0 0;} +span.mceItemNbsp {background: #DDD} +td.mceSelected, th.mceSelected {background-color:#3399ff !important} +img {border:0;} +table, img, hr, .mceItemAnchor {cursor:default} +table td, table th {cursor:text} +ins {border-bottom:1px solid green; text-decoration: none; color:green} +del {color:red; text-decoration:line-through} +cite {border-bottom:1px dashed blue} +acronym {border-bottom:1px dotted #CCC; cursor:help} +abbr {border-bottom:1px dashed #CCC; cursor:help} + +/* IE */ +* html body { +scrollbar-3dlight-color:#F0F0EE; +scrollbar-arrow-color:#676662; +scrollbar-base-color:#F0F0EE; +scrollbar-darkshadow-color:#DDD; +scrollbar-face-color:#E0E0DD; +scrollbar-highlight-color:#F0F0EE; +scrollbar-shadow-color:#F0F0EE; +scrollbar-track-color:#F5F5F5; +} + +img:-moz-broken {-moz-force-broken-image-icon:1; width:24px; height:24px} +font[face=mceinline] {font-family:inherit !important} +*[contentEditable]:focus {outline:0} + +.mceItemMedia {border:1px dotted #cc0000; background-position:center; background-repeat:no-repeat; background-color:#ffffcc} +.mceItemShockWave {background-image:url(../../img/shockwave.gif)} +.mceItemFlash {background-image:url(../../img/flash.gif)} +.mceItemQuickTime {background-image:url(../../img/quicktime.gif)} +.mceItemWindowsMedia {background-image:url(../../img/windowsmedia.gif)} +.mceItemRealMedia {background-image:url(../../img/realmedia.gif)} +.mceItemVideo {background-image:url(../../img/video.gif)} +.mceItemAudio {background-image:url(../../img/video.gif)} +.mceItemIframe {background-image:url(../../img/iframe.gif)} +.mcePageBreak {display:block;border:0;width:100%;height:12px;border-top:1px dotted #ccc;margin-top:15px;background:#fff url(../../img/pagebreak.gif) no-repeat center top;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/dialog.css b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/dialog.css new file mode 100644 index 0000000..ec08772 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/dialog.css @@ -0,0 +1,117 @@ +/* Generic */ +body { +font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px; +scrollbar-3dlight-color:#F0F0EE; +scrollbar-arrow-color:#676662; +scrollbar-base-color:#F0F0EE; +scrollbar-darkshadow-color:#DDDDDD; +scrollbar-face-color:#E0E0DD; +scrollbar-highlight-color:#F0F0EE; +scrollbar-shadow-color:#F0F0EE; +scrollbar-track-color:#F5F5F5; +background:#F0F0EE; +padding:0; +margin:8px 8px 0 8px; +} + +html {background:#F0F0EE;} +td {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +textarea {resize:none;outline:none;} +a:link, a:visited {color:black;} +a:hover {color:#2B6FB6;} +.nowrap {white-space: nowrap} + +/* Forms */ +fieldset {margin:0; padding:4px; border:1px solid #919B9C; font-family:Verdana, Arial; font-size:10px;} +legend {color:#2B6FB6; font-weight:bold;} +label.msg {display:none;} +label.invalid {color:#EE0000; display:inline;} +input.invalid {border:1px solid #EE0000;} +input {background:#FFF; border:1px solid #CCC;} +input, select, textarea {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} +input, select, textarea {border:1px solid #808080;} +input.radio {border:1px none #000000; background:transparent; vertical-align:middle;} +input.checkbox {border:1px none #000000; background:transparent; vertical-align:middle;} +.input_noborder {border:0;} + +/* Buttons */ +#insert, #cancel, input.button, .updateButton { +border:0; margin:0; padding:0; +font-weight:bold; +width:94px; height:26px; +background:url(../default/img/buttons.png) 0 -26px; +cursor:pointer; +padding-bottom:2px; +float:left; +} + +#insert {background:url(../default/img/buttons.png) 0 -52px} +#cancel {background:url(../default/img/buttons.png) 0 0; float:right} + +/* Browse */ +a.pickcolor, a.browse {text-decoration:none} +a.browse span {display:block; width:20px; height:18px; background:url(../../img/icons.gif) -860px 0; border:1px solid #FFF; margin-left:1px;} +.mceOldBoxModel a.browse span {width:22px; height:20px;} +a.browse:hover span {border:1px solid #0A246A; background-color:#B2BBD0;} +a.browse span.disabled {border:1px solid white; opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +a.browse:hover span.disabled {border:1px solid white; background-color:transparent;} +a.pickcolor span {display:block; width:20px; height:16px; background:url(../../img/icons.gif) -840px 0; margin-left:2px;} +.mceOldBoxModel a.pickcolor span {width:21px; height:17px;} +a.pickcolor:hover span {background-color:#B2BBD0;} +a.pickcolor:hover span.disabled {} + +/* Charmap */ +table.charmap {border:1px solid #AAA; text-align:center} +td.charmap, #charmap a {width:18px; height:18px; color:#000; border:1px solid #AAA; text-align:center; font-size:12px; vertical-align:middle; line-height: 18px;} +#charmap a {display:block; color:#000; text-decoration:none; border:0} +#charmap a:hover {background:#CCC;color:#2B6FB6} +#charmap #codeN {font-size:10px; font-family:Arial,Helvetica,sans-serif; text-align:center} +#charmap #codeV {font-size:40px; height:80px; border:1px solid #AAA; text-align:center} + +/* Source */ +.wordWrapCode {vertical-align:middle; border:1px none #000000; background:transparent;} +.mceActionPanel {margin-top:5px;} + +/* Tabs classes */ +.tabs {width:100%; height:18px; line-height:normal; background:url(../default/img/tabs.gif) repeat-x 0 -72px;} +.tabs ul {margin:0; padding:0; list-style:none;} +.tabs li {float:left; background:url(../default/img/tabs.gif) no-repeat 0 0; margin:0 2px 0 0; padding:0 0 0 10px; line-height:17px; height:18px; display:block;} +.tabs li.current {background:url(../default/img/tabs.gif) no-repeat 0 -18px; margin-right:2px;} +.tabs span {float:left; display:block; background:url(../default/img/tabs.gif) no-repeat right -36px; padding:0px 10px 0 0;} +.tabs .current span {background:url(../default/img/tabs.gif) no-repeat right -54px;} +.tabs a {text-decoration:none; font-family:Verdana, Arial; font-size:10px;} +.tabs a:link, .tabs a:visited, .tabs a:hover {color:black;} + +/* Panels */ +.panel_wrapper div.panel {display:none;} +.panel_wrapper div.current {display:block; width:100%; height:300px; overflow:visible;} +.panel_wrapper {border:1px solid #919B9C; border-top:0px; padding:10px; padding-top:5px; clear:both; background:white;} + +/* Columns */ +.column {float:left;} +.properties {width:100%;} +.properties .column1 {} +.properties .column2 {text-align:left;} + +/* Titles */ +h1, h2, h3, h4 {color:#2B6FB6; margin:0; padding:0; padding-top:5px;} +h3 {font-size:14px;} +.title {font-size:12px; font-weight:bold; color:#2B6FB6;} + +/* Dialog specific */ +#link .panel_wrapper, #link div.current {height:125px;} +#image .panel_wrapper, #image div.current {height:200px;} +#plugintable thead {font-weight:bold; background:#DDD;} +#plugintable, #about #plugintable td {border:1px solid #919B9C;} +#plugintable {width:96%; margin-top:10px;} +#pluginscontainer {height:290px; overflow:auto;} +#colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;} +#colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;} +#colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;} +#colorpicker #light div {overflow:hidden;} +#colorpicker #previewblock {float:right; padding-left:10px; height:20px;} +#colorpicker .panel_wrapper div.current {height:175px;} +#colorpicker #namedcolors {width:150px;} +#colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;} +#colorpicker #colornamecontainer {margin-top:5px;} +#colorpicker #picker_panel fieldset {margin:auto;width:325px;} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..13a5cb03097c004f7b37658654a9250748cf073c GIT binary patch literal 2766 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 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png new file mode 100644 index 0000000000000000000000000000000000000000..7fc57f2bc2d63a3ad6fbf98b663f336539f011ec GIT binary patch literal 651 zcmV;60(AX}P)<h;3K|Lk000e1NJLTq003A3002S=0{{R3<ObpU00009a7bBm000XU z000XU0RWnu7ytkO%uq~JMF0Q*ySuvp002`{Q*w5EkCBv-nWUJXshgs#pQf*(sj{Z5 zwW+VTt+TtZw!XBv!MD7`yTHb~z{kA7$iBnLzr@SI#>~UV&BV#i#>&vh%+bls)637) z|EoX$u}%N7Q2(@4|Fu{Dw_E?XUjMpc|GQ=Xy=niyZU4b?|HF3w#e4t9fd9#a|I3O0 z&5r-ub^qLY|J{H8--Q3*iT~k_|KpSY<e2~Eo&V>d|L3Cr=%)YbtN-h;|LwH@@45f* zzW?&W|MbWI_00eO|F&Wq@&Et;0(4SNQveU<EYPU{00CD?L_t(o!|j!^Y63wJhUf0E z38<tH3j+ZS_yTH?=eNik1Wc9ICSB6xJa_MOcK7_3U3YV-=7U6-aX#c{;V+*cqpGS# z)W_`cR3EBAdssG*xmwL{#Aa_#*EW3U5ueoR6e*^61M#6ptS_5bv3<seA{KGB_)7!C zJWmx*)&D6F^E^3<2~A)W*LixzV^79od2S+371wH2$BJJK#E17(Q-Q^M8&gd)2#lgJ zdwcwBv(!JJ6+b{~%}o>qL%#keZfRNo2=jQw7k!se7X^9V1j4iLUp68Z@t=r4G(h~O zNf#5nT>kpvo%+~iMX{n4jABdM%#4?wj5qS!L>wXh2IPsmmi~l5Z*gRt`Huw!S{nag zygxXo!EY-rAUF!s;uNGb)obDTa;U{!asI0iv51EeU)nfId<Wdd14Pla@emnr<W-3H lf5f2{cf>~s{&Jwj9nO>J@7?&+<Hi60002ovPDHLkV1hmPRc!zO literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png new file mode 100644 index 0000000000000000000000000000000000000000..c0dcc6cac2003f7405fff3ea5df7bcf276243596 GIT binary patch literal 2084 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 O0000<MNUMnLSTX~QySp_ literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui.css b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui.css new file mode 100644 index 0000000..0916c34 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui.css @@ -0,0 +1,217 @@ +/* Reset */ +.o2k7Skin table, .o2k7Skin tbody, .o2k7Skin a, .o2k7Skin img, .o2k7Skin tr, .o2k7Skin div, .o2k7Skin td, .o2k7Skin iframe, .o2k7Skin span, .o2k7Skin *, .o2k7Skin .mceText {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000; vertical-align:baseline; width:auto; border-collapse:separate; text-align:left} +.o2k7Skin a:hover, .o2k7Skin a:link, .o2k7Skin a:visited, .o2k7Skin a:active {text-decoration:none; font-weight:normal; cursor:default; color:#000} +.o2k7Skin table td {vertical-align:middle} + +/* Containers */ +.o2k7Skin table {background:transparent} +.o2k7Skin iframe {display:block;} +.o2k7Skin .mceToolbar {height:26px} + +/* External */ +.o2k7Skin .mceExternalToolbar {position:absolute; border:1px solid #ABC6DD; border-bottom:0; display:none} +.o2k7Skin .mceExternalToolbar td.mceToolbar {padding-right:13px;} +.o2k7Skin .mceExternalClose {position:absolute; top:3px; right:3px; width:7px; height:7px; background:url(../../img/icons.gif) -820px 0} + +/* Layout */ +.o2k7Skin table.mceLayout {border:0; border-left:1px solid #ABC6DD; border-right:1px solid #ABC6DD} +.o2k7Skin table.mceLayout tr.mceFirst td {border-top:1px solid #ABC6DD} +.o2k7Skin table.mceLayout tr.mceLast td {border-bottom:1px solid #ABC6DD} +.o2k7Skin table.mceToolbar, .o2k7Skin tr.mceFirst .mceToolbar tr td, .o2k7Skin tr.mceLast .mceToolbar tr td {border:0; margin:0; padding:0} +.o2k7Skin .mceIframeContainer {border-top:1px solid #ABC6DD; border-bottom:1px solid #ABC6DD} +.o2k7Skin td.mceToolbar{background:#E5EFFD} +.o2k7Skin .mceStatusbar {background:#E5EFFD; display:block; font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:9pt; line-height:16px; overflow:visible; color:#000; height:20px} +.o2k7Skin .mceStatusbar div {float:left; padding:2px} +.o2k7Skin .mceStatusbar a.mceResize {display:block; float:right; background:url(../../img/icons.gif) -800px 0; width:20px; height:20px; cursor:se-resize; outline:0} +.o2k7Skin .mceStatusbar a:hover {text-decoration:underline} +.o2k7Skin table.mceToolbar {margin-left:3px} +.o2k7Skin .mceToolbar .mceToolbarStart span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px; margin-left:3px;} +.o2k7Skin .mceToolbar td.mceFirst span {margin:0} +.o2k7Skin .mceToolbar .mceToolbarEnd span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px} +.o2k7Skin .mceToolbar .mceToolbarEndListBox span, .o2k7Skin .mceToolbar .mceToolbarStartListBox span {display:none} +.o2k7Skin span.mceIcon, .o2k7Skin img.mceIcon {display:block; width:20px; height:20px} +.o2k7Skin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px} +.o2k7Skin td.mceCenter {text-align:center;} +.o2k7Skin td.mceCenter table {margin:0 auto; text-align:left;} +.o2k7Skin td.mceRight table {margin:0 0 0 auto;} + +/* Button */ +.o2k7Skin .mceButton {display:block; background:url(img/button_bg.png); width:22px; height:22px} +.o2k7Skin a.mceButton span, .o2k7Skin a.mceButton img {margin-left:1px} +.o2k7Skin .mceOldBoxModel a.mceButton span, .o2k7Skin .mceOldBoxModel a.mceButton img {margin:0 0 0 1px} +.o2k7Skin a.mceButtonEnabled:hover {background-color:#B2BBD0; background-position:0 -22px} +.o2k7Skin a.mceButtonActive, .o2k7Skin a.mceButtonSelected {background-position:0 -44px} +.o2k7Skin .mceButtonDisabled .mceIcon {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +.o2k7Skin .mceButtonLabeled {width:auto} +.o2k7Skin .mceButtonLabeled span.mceIcon {float:left} +.o2k7Skin span.mceButtonLabel {display:block; font-size:10px; padding:4px 6px 0 22px; font-family:Tahoma,Verdana,Arial,Helvetica} +.o2k7Skin .mceButtonDisabled .mceButtonLabel {color:#888} + +/* Separator */ +.o2k7Skin .mceSeparator {display:block; background:url(img/button_bg.png) -22px 0; width:5px; height:22px} + +/* ListBox */ +.o2k7Skin .mceListBox {padding-left: 3px} +.o2k7Skin .mceListBox, .o2k7Skin .mceListBox a {display:block} +.o2k7Skin .mceListBox .mceText {padding-left:4px; text-align:left; width:70px; border:1px solid #b3c7e1; border-right:0; background:#eaf2fb; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; height:20px; line-height:20px; overflow:hidden} +.o2k7Skin .mceListBox .mceOpen {width:14px; height:22px; background:url(img/button_bg.png) -66px 0} +.o2k7Skin table.mceListBoxEnabled:hover .mceText, .o2k7Skin .mceListBoxHover .mceText, .o2k7Skin .mceListBoxSelected .mceText {background:#FFF} +.o2k7Skin table.mceListBoxEnabled:hover .mceOpen, .o2k7Skin .mceListBoxHover .mceOpen, .o2k7Skin .mceListBoxSelected .mceOpen {background-position:-66px -22px} +.o2k7Skin .mceListBoxDisabled .mceText {color:gray} +.o2k7Skin .mceListBoxMenu {overflow:auto; overflow-x:hidden; margin-left:3px} +.o2k7Skin .mceOldBoxModel .mceListBox .mceText {height:22px} +.o2k7Skin select.mceListBox {font-family:Tahoma,Verdana,Arial,Helvetica; font-size:12px; border:1px solid #b3c7e1; background:#FFF;} + +/* SplitButton */ +.o2k7Skin .mceSplitButton, .o2k7Skin .mceSplitButton a, .o2k7Skin .mceSplitButton span {display:block; height:22px; direction:ltr} +.o2k7Skin .mceSplitButton {background:url(img/button_bg.png)} +.o2k7Skin .mceSplitButton a.mceAction {width:22px} +.o2k7Skin .mceSplitButton span.mceAction {width:22px; background-image:url(../../img/icons.gif)} +.o2k7Skin .mceSplitButton a.mceOpen {width:10px; background:url(img/button_bg.png) -44px 0} +.o2k7Skin .mceSplitButton span.mceOpen {display:none} +.o2k7Skin table.mceSplitButtonEnabled:hover a.mceAction, .o2k7Skin .mceSplitButtonHover a.mceAction, .o2k7Skin .mceSplitButtonSelected {background:url(img/button_bg.png) 0 -22px} +.o2k7Skin table.mceSplitButtonEnabled:hover a.mceOpen, .o2k7Skin .mceSplitButtonHover a.mceOpen, .o2k7Skin .mceSplitButtonSelected a.mceOpen {background-position:-44px -44px} +.o2k7Skin .mceSplitButtonDisabled .mceAction {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} +.o2k7Skin .mceSplitButtonActive {background-position:0 -44px} + +/* ColorSplitButton */ +.o2k7Skin div.mceColorSplitMenu table {background:#FFF; border:1px solid gray} +.o2k7Skin .mceColorSplitMenu td {padding:2px} +.o2k7Skin .mceColorSplitMenu a {display:block; width:9px; height:9px; overflow:hidden; border:1px solid #808080} +.o2k7Skin .mceColorSplitMenu td.mceMoreColors {padding:1px 3px 1px 1px} +.o2k7Skin .mceColorSplitMenu a.mceMoreColors {width:100%; height:auto; text-align:center; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; line-height:20px; border:1px solid #FFF} +.o2k7Skin .mceColorSplitMenu a.mceMoreColors:hover {border:1px solid #0A246A; background-color:#B6BDD2} +.o2k7Skin a.mceMoreColors:hover {border:1px solid #0A246A} +.o2k7Skin .mceColorPreview {margin-left:2px; width:16px; height:4px; overflow:hidden; background:#9a9b9a;overflow:hidden} +.o2k7Skin .mce_forecolor span.mceAction, .o2k7Skin .mce_backcolor span.mceAction {height:15px;overflow:hidden} + +/* Menu */ +.o2k7Skin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #ABC6DD} +.o2k7Skin .mceNoIcons span.mceIcon {width:0;} +.o2k7Skin .mceNoIcons a .mceText {padding-left:10px} +.o2k7Skin .mceMenu table {background:#FFF} +.o2k7Skin .mceMenu a, .o2k7Skin .mceMenu span, .o2k7Skin .mceMenu {display:block} +.o2k7Skin .mceMenu td {height:20px} +.o2k7Skin .mceMenu a {position:relative;padding:3px 0 4px 0} +.o2k7Skin .mceMenu .mceText {position:relative; display:block; font-family:Tahoma,Verdana,Arial,Helvetica; color:#000; cursor:default; margin:0; padding:0 25px 0 25px; display:block} +.o2k7Skin .mceMenu span.mceText, .o2k7Skin .mceMenu .mcePreview {font-size:11px} +.o2k7Skin .mceMenu pre.mceText {font-family:Monospace} +.o2k7Skin .mceMenu .mceIcon {position:absolute; top:0; left:0; width:22px;} +.o2k7Skin .mceMenu .mceMenuItemEnabled a:hover, .o2k7Skin .mceMenu .mceMenuItemActive {background-color:#dbecf3} +.o2k7Skin td.mceMenuItemSeparator {background:#DDD; height:1px} +.o2k7Skin .mceMenuItemTitle a {border:0; background:#E5EFFD; border-bottom:1px solid #ABC6DD} +.o2k7Skin .mceMenuItemTitle span.mceText {color:#000; font-weight:bold; padding-left:4px} +.o2k7Skin .mceMenuItemDisabled .mceText {color:#888} +.o2k7Skin .mceMenuItemSelected .mceIcon {background:url(../default/img/menu_check.gif)} +.o2k7Skin .mceNoIcons .mceMenuItemSelected a {background:url(../default/img/menu_arrow.gif) no-repeat -6px center} +.o2k7Skin .mceMenu span.mceMenuLine {display:none} +.o2k7Skin .mceMenuItemSub a {background:url(../default/img/menu_arrow.gif) no-repeat top right;} +.o2k7Skin .mceMenuItem td, .o2k7Skin .mceMenuItem th {line-height: normal} + +/* Progress,Resize */ +.o2k7Skin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=50); background:#FFF} +.o2k7Skin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(../default/img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px} + +/* Formats */ +.o2k7Skin .mce_formatPreview a {font-size:10px} +.o2k7Skin .mce_p span.mceText {} +.o2k7Skin .mce_address span.mceText {font-style:italic} +.o2k7Skin .mce_pre span.mceText {font-family:monospace} +.o2k7Skin .mce_h1 span.mceText {font-weight:bolder; font-size: 2em} +.o2k7Skin .mce_h2 span.mceText {font-weight:bolder; font-size: 1.5em} +.o2k7Skin .mce_h3 span.mceText {font-weight:bolder; font-size: 1.17em} +.o2k7Skin .mce_h4 span.mceText {font-weight:bolder; font-size: 1em} +.o2k7Skin .mce_h5 span.mceText {font-weight:bolder; font-size: .83em} +.o2k7Skin .mce_h6 span.mceText {font-weight:bolder; font-size: .75em} + +/* Theme */ +.o2k7Skin span.mce_bold {background-position:0 0} +.o2k7Skin span.mce_italic {background-position:-60px 0} +.o2k7Skin span.mce_underline {background-position:-140px 0} +.o2k7Skin span.mce_strikethrough {background-position:-120px 0} +.o2k7Skin span.mce_undo {background-position:-160px 0} +.o2k7Skin span.mce_redo {background-position:-100px 0} +.o2k7Skin span.mce_cleanup {background-position:-40px 0} +.o2k7Skin span.mce_bullist {background-position:-20px 0} +.o2k7Skin span.mce_numlist {background-position:-80px 0} +.o2k7Skin span.mce_justifyleft {background-position:-460px 0} +.o2k7Skin span.mce_justifyright {background-position:-480px 0} +.o2k7Skin span.mce_justifycenter {background-position:-420px 0} +.o2k7Skin span.mce_justifyfull {background-position:-440px 0} +.o2k7Skin span.mce_anchor {background-position:-200px 0} +.o2k7Skin span.mce_indent {background-position:-400px 0} +.o2k7Skin span.mce_outdent {background-position:-540px 0} +.o2k7Skin span.mce_link {background-position:-500px 0} +.o2k7Skin span.mce_unlink {background-position:-640px 0} +.o2k7Skin span.mce_sub {background-position:-600px 0} +.o2k7Skin span.mce_sup {background-position:-620px 0} +.o2k7Skin span.mce_removeformat {background-position:-580px 0} +.o2k7Skin span.mce_newdocument {background-position:-520px 0} +.o2k7Skin span.mce_image {background-position:-380px 0} +.o2k7Skin span.mce_help {background-position:-340px 0} +.o2k7Skin span.mce_code {background-position:-260px 0} +.o2k7Skin span.mce_hr {background-position:-360px 0} +.o2k7Skin span.mce_visualaid {background-position:-660px 0} +.o2k7Skin span.mce_charmap {background-position:-240px 0} +.o2k7Skin span.mce_paste {background-position:-560px 0} +.o2k7Skin span.mce_copy {background-position:-700px 0} +.o2k7Skin span.mce_cut {background-position:-680px 0} +.o2k7Skin span.mce_blockquote {background-position:-220px 0} +.o2k7Skin .mce_forecolor span.mceAction {background-position:-720px 0} +.o2k7Skin .mce_backcolor span.mceAction {background-position:-760px 0} +.o2k7Skin span.mce_forecolorpicker {background-position:-720px 0} +.o2k7Skin span.mce_backcolorpicker {background-position:-760px 0} + +/* Plugins */ +.o2k7Skin span.mce_advhr {background-position:-0px -20px} +.o2k7Skin span.mce_ltr {background-position:-20px -20px} +.o2k7Skin span.mce_rtl {background-position:-40px -20px} +.o2k7Skin span.mce_emotions {background-position:-60px -20px} +.o2k7Skin span.mce_fullpage {background-position:-80px -20px} +.o2k7Skin span.mce_fullscreen {background-position:-100px -20px} +.o2k7Skin span.mce_iespell {background-position:-120px -20px} +.o2k7Skin span.mce_insertdate {background-position:-140px -20px} +.o2k7Skin span.mce_inserttime {background-position:-160px -20px} +.o2k7Skin span.mce_absolute {background-position:-180px -20px} +.o2k7Skin span.mce_backward {background-position:-200px -20px} +.o2k7Skin span.mce_forward {background-position:-220px -20px} +.o2k7Skin span.mce_insert_layer {background-position:-240px -20px} +.o2k7Skin span.mce_insertlayer {background-position:-260px -20px} +.o2k7Skin span.mce_movebackward {background-position:-280px -20px} +.o2k7Skin span.mce_moveforward {background-position:-300px -20px} +.o2k7Skin span.mce_media {background-position:-320px -20px} +.o2k7Skin span.mce_nonbreaking {background-position:-340px -20px} +.o2k7Skin span.mce_pastetext {background-position:-360px -20px} +.o2k7Skin span.mce_pasteword {background-position:-380px -20px} +.o2k7Skin span.mce_selectall {background-position:-400px -20px} +.o2k7Skin span.mce_preview {background-position:-420px -20px} +.o2k7Skin span.mce_print {background-position:-440px -20px} +.o2k7Skin span.mce_cancel {background-position:-460px -20px} +.o2k7Skin span.mce_save {background-position:-480px -20px} +.o2k7Skin span.mce_replace {background-position:-500px -20px} +.o2k7Skin span.mce_search {background-position:-520px -20px} +.o2k7Skin span.mce_styleprops {background-position:-560px -20px} +.o2k7Skin span.mce_table {background-position:-580px -20px} +.o2k7Skin span.mce_cell_props {background-position:-600px -20px} +.o2k7Skin span.mce_delete_table {background-position:-620px -20px} +.o2k7Skin span.mce_delete_col {background-position:-640px -20px} +.o2k7Skin span.mce_delete_row {background-position:-660px -20px} +.o2k7Skin span.mce_col_after {background-position:-680px -20px} +.o2k7Skin span.mce_col_before {background-position:-700px -20px} +.o2k7Skin span.mce_row_after {background-position:-720px -20px} +.o2k7Skin span.mce_row_before {background-position:-740px -20px} +.o2k7Skin span.mce_merge_cells {background-position:-760px -20px} +.o2k7Skin span.mce_table_props {background-position:-980px -20px} +.o2k7Skin span.mce_row_props {background-position:-780px -20px} +.o2k7Skin span.mce_split_cells {background-position:-800px -20px} +.o2k7Skin span.mce_template {background-position:-820px -20px} +.o2k7Skin span.mce_visualchars {background-position:-840px -20px} +.o2k7Skin span.mce_abbr {background-position:-860px -20px} +.o2k7Skin span.mce_acronym {background-position:-880px -20px} +.o2k7Skin span.mce_attribs {background-position:-900px -20px} +.o2k7Skin span.mce_cite {background-position:-920px -20px} +.o2k7Skin span.mce_del {background-position:-940px -20px} +.o2k7Skin span.mce_ins {background-position:-960px -20px} +.o2k7Skin span.mce_pagebreak {background-position:0 -40px} +.o2k7Skin span.mce_restoredraft {background-position:-20px -40px} +.o2k7Skin span.mce_spellchecker {background-position:-540px -20px} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui_black.css b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui_black.css new file mode 100644 index 0000000..50c9b76 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui_black.css @@ -0,0 +1,8 @@ +/* Black */ +.o2k7SkinBlack .mceToolbar .mceToolbarStart span, .o2k7SkinBlack .mceToolbar .mceToolbarEnd span, .o2k7SkinBlack .mceButton, .o2k7SkinBlack .mceSplitButton, .o2k7SkinBlack .mceSeparator, .o2k7SkinBlack .mceSplitButton a.mceOpen, .o2k7SkinBlack .mceListBox a.mceOpen {background-image:url(img/button_bg_black.png)} +.o2k7SkinBlack td.mceToolbar, .o2k7SkinBlack td.mceStatusbar, .o2k7SkinBlack .mceMenuItemTitle a, .o2k7SkinBlack .mceMenuItemTitle span.mceText, .o2k7SkinBlack .mceStatusbar div, .o2k7SkinBlack .mceStatusbar span, .o2k7SkinBlack .mceStatusbar a {background:#535353; color:#FFF} +.o2k7SkinBlack table.mceListBoxEnabled .mceText, o2k7SkinBlack .mceListBox .mceText {background:#FFF; border:1px solid #CBCFD4; border-bottom-color:#989FA9; border-right:0} +.o2k7SkinBlack table.mceListBoxEnabled:hover .mceText, .o2k7SkinBlack .mceListBoxHover .mceText, .o2k7SkinBlack .mceListBoxSelected .mceText {background:#FFF; border:1px solid #FFBD69; border-right:0} +.o2k7SkinBlack .mceExternalToolbar, .o2k7SkinBlack .mceListBox .mceText, .o2k7SkinBlack div.mceMenu, .o2k7SkinBlack table.mceLayout, .o2k7SkinBlack .mceMenuItemTitle a, .o2k7SkinBlack table.mceLayout tr.mceFirst td, .o2k7SkinBlack table.mceLayout, .o2k7SkinBlack .mceMenuItemTitle a, .o2k7SkinBlack table.mceLayout tr.mceLast td, .o2k7SkinBlack .mceIframeContainer {border-color: #535353;} +.o2k7SkinBlack table.mceSplitButtonEnabled:hover a.mceAction, .o2k7SkinBlack .mceSplitButtonHover a.mceAction, .o2k7SkinBlack .mceSplitButtonSelected {background-image:url(img/button_bg_black.png)} +.o2k7SkinBlack .mceMenu .mceMenuItemEnabled a:hover, .o2k7SkinBlack .mceMenu .mceMenuItemActive {background-color:#FFE7A1} \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css new file mode 100644 index 0000000..960a8e4 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css @@ -0,0 +1,5 @@ +/* Silver */ +.o2k7SkinSilver .mceToolbar .mceToolbarStart span, .o2k7SkinSilver .mceButton, .o2k7SkinSilver .mceSplitButton, .o2k7SkinSilver .mceSeparator, .o2k7SkinSilver .mceSplitButton a.mceOpen, .o2k7SkinSilver .mceListBox a.mceOpen {background-image:url(img/button_bg_silver.png)} +.o2k7SkinSilver td.mceToolbar, .o2k7SkinSilver td.mceStatusbar, .o2k7SkinSilver .mceMenuItemTitle a {background:#eee} +.o2k7SkinSilver .mceListBox .mceText {background:#FFF} +.o2k7SkinSilver .mceExternalToolbar, .o2k7SkinSilver .mceListBox .mceText, .o2k7SkinSilver div.mceMenu, .o2k7SkinSilver table.mceLayout, .o2k7SkinSilver .mceMenuItemTitle a, .o2k7SkinSilver table.mceLayout tr.mceFirst td, .o2k7SkinSilver table.mceLayout, .o2k7SkinSilver .mceMenuItemTitle a, .o2k7SkinSilver table.mceLayout tr.mceLast td, .o2k7SkinSilver .mceIframeContainer {border-color: #bbb} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/source_editor.htm b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/source_editor.htm new file mode 100644 index 0000000..3c6d658 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/advanced/source_editor.htm @@ -0,0 +1,25 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>{#advanced_dlg.code_title}</title> + <script type="text/javascript" src="../../tiny_mce_popup.js"></script> + <script type="text/javascript" src="js/source_editor.js"></script> +</head> +<body onresize="resizeInputs();" style="display:none; overflow:hidden;"> + <form name="source" onsubmit="saveContent();return false;" action="#"> + <div style="float: left" class="title"><label for="htmlSource">{#advanced_dlg.code_title}</label></div> + + <div id="wrapline" style="float: right"> + <input type="checkbox" name="wraped" id="wraped" onclick="toggleWordWrap(this);" class="wordWrapCode" /><label for="wraped">{#advanced_dlg.code_wordwrap}</label> + </div> + + <br style="clear: both" /> + + <textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,monospace; font-size: 12px;" dir="ltr" wrap="off" class="mceFocus"></textarea> + + <div class="mceActionPanel"> + <input type="submit" role="button" name="insert" value="{#update}" id="insert" /> + <input type="button" role="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" /> + </div> + </form> +</body> +</html> diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/editor_template.js b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/editor_template.js new file mode 100644 index 0000000..4b3209c --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/editor_template.js @@ -0,0 +1 @@ +(function(){var a=tinymce.DOM;tinymce.ThemeManager.requireLangPack("simple");tinymce.create("tinymce.themes.SimpleTheme",{init:function(c,d){var e=this,b=["Bold","Italic","Underline","Strikethrough","InsertUnorderedList","InsertOrderedList"],f=c.settings;e.editor=c;c.contentCSS.push(d+"/skins/"+f.skin+"/content.css");c.onInit.add(function(){c.onNodeChange.add(function(h,g){tinymce.each(b,function(i){g.get(i.toLowerCase()).setActive(h.queryCommandState(i))})})});a.loadCSS((f.editor_css?c.documentBaseURI.toAbsolute(f.editor_css):"")||d+"/skins/"+f.skin+"/ui.css")},renderUI:function(h){var e=this,i=h.targetNode,b,c,d=e.editor,f=d.controlManager,g;i=a.insertAfter(a.create("span",{id:d.id+"_container","class":"mceEditor "+d.settings.skin+"SimpleSkin"}),i);i=g=a.add(i,"table",{cellPadding:0,cellSpacing:0,"class":"mceLayout"});i=c=a.add(i,"tbody");i=a.add(c,"tr");i=b=a.add(a.add(i,"td"),"div",{"class":"mceIframeContainer"});i=a.add(a.add(c,"tr",{"class":"last"}),"td",{"class":"mceToolbar mceLast",align:"center"});c=e.toolbar=f.createToolbar("tools1");c.add(f.createButton("bold",{title:"simple.bold_desc",cmd:"Bold"}));c.add(f.createButton("italic",{title:"simple.italic_desc",cmd:"Italic"}));c.add(f.createButton("underline",{title:"simple.underline_desc",cmd:"Underline"}));c.add(f.createButton("strikethrough",{title:"simple.striketrough_desc",cmd:"Strikethrough"}));c.add(f.createSeparator());c.add(f.createButton("undo",{title:"simple.undo_desc",cmd:"Undo"}));c.add(f.createButton("redo",{title:"simple.redo_desc",cmd:"Redo"}));c.add(f.createSeparator());c.add(f.createButton("cleanup",{title:"simple.cleanup_desc",cmd:"mceCleanup"}));c.add(f.createSeparator());c.add(f.createButton("insertunorderedlist",{title:"simple.bullist_desc",cmd:"InsertUnorderedList"}));c.add(f.createButton("insertorderedlist",{title:"simple.numlist_desc",cmd:"InsertOrderedList"}));c.renderTo(i);return{iframeContainer:b,editorContainer:d.id+"_container",sizeContainer:g,deltaHeight:-20}},getInfo:function(){return{longname:"Simple theme",author:"Moxiecode Systems AB",authorurl:"http://tinymce.moxiecode.com",version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.ThemeManager.add("simple",tinymce.themes.SimpleTheme)})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/editor_template_src.js b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/editor_template_src.js new file mode 100644 index 0000000..01ce87c --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/editor_template_src.js @@ -0,0 +1,84 @@ +/** + * editor_template_src.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +(function() { + var DOM = tinymce.DOM; + + // Tell it to load theme specific language pack(s) + tinymce.ThemeManager.requireLangPack('simple'); + + tinymce.create('tinymce.themes.SimpleTheme', { + init : function(ed, url) { + var t = this, states = ['Bold', 'Italic', 'Underline', 'Strikethrough', 'InsertUnorderedList', 'InsertOrderedList'], s = ed.settings; + + t.editor = ed; + ed.contentCSS.push(url + "/skins/" + s.skin + "/content.css"); + + ed.onInit.add(function() { + ed.onNodeChange.add(function(ed, cm) { + tinymce.each(states, function(c) { + cm.get(c.toLowerCase()).setActive(ed.queryCommandState(c)); + }); + }); + }); + + DOM.loadCSS((s.editor_css ? ed.documentBaseURI.toAbsolute(s.editor_css) : '') || url + "/skins/" + s.skin + "/ui.css"); + }, + + renderUI : function(o) { + var t = this, n = o.targetNode, ic, tb, ed = t.editor, cf = ed.controlManager, sc; + + n = DOM.insertAfter(DOM.create('span', {id : ed.id + '_container', 'class' : 'mceEditor ' + ed.settings.skin + 'SimpleSkin'}), n); + n = sc = DOM.add(n, 'table', {cellPadding : 0, cellSpacing : 0, 'class' : 'mceLayout'}); + n = tb = DOM.add(n, 'tbody'); + + // Create iframe container + n = DOM.add(tb, 'tr'); + n = ic = DOM.add(DOM.add(n, 'td'), 'div', {'class' : 'mceIframeContainer'}); + + // Create toolbar container + n = DOM.add(DOM.add(tb, 'tr', {'class' : 'last'}), 'td', {'class' : 'mceToolbar mceLast', align : 'center'}); + + // Create toolbar + tb = t.toolbar = cf.createToolbar("tools1"); + tb.add(cf.createButton('bold', {title : 'simple.bold_desc', cmd : 'Bold'})); + tb.add(cf.createButton('italic', {title : 'simple.italic_desc', cmd : 'Italic'})); + tb.add(cf.createButton('underline', {title : 'simple.underline_desc', cmd : 'Underline'})); + tb.add(cf.createButton('strikethrough', {title : 'simple.striketrough_desc', cmd : 'Strikethrough'})); + tb.add(cf.createSeparator()); + tb.add(cf.createButton('undo', {title : 'simple.undo_desc', cmd : 'Undo'})); + tb.add(cf.createButton('redo', {title : 'simple.redo_desc', cmd : 'Redo'})); + tb.add(cf.createSeparator()); + tb.add(cf.createButton('cleanup', {title : 'simple.cleanup_desc', cmd : 'mceCleanup'})); + tb.add(cf.createSeparator()); + tb.add(cf.createButton('insertunorderedlist', {title : 'simple.bullist_desc', cmd : 'InsertUnorderedList'})); + tb.add(cf.createButton('insertorderedlist', {title : 'simple.numlist_desc', cmd : 'InsertOrderedList'})); + tb.renderTo(n); + + return { + iframeContainer : ic, + editorContainer : ed.id + '_container', + sizeContainer : sc, + deltaHeight : -20 + }; + }, + + getInfo : function() { + return { + longname : 'Simple theme', + author : 'Moxiecode Systems AB', + authorurl : 'http://tinymce.moxiecode.com', + version : tinymce.majorVersion + "." + tinymce.minorVersion + } + } + }); + + tinymce.ThemeManager.add('simple', tinymce.themes.SimpleTheme); +})(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/img/icons.gif b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/img/icons.gif new file mode 100644 index 0000000000000000000000000000000000000000..6fcbcb5dedf16a5fa1d15c2aa127bceb612f1e71 GIT binary patch literal 806 zcmZ?wbhEHbJi#Es@KuxH{{08bHy>kQU|4+kcV*u?6Yu2z|Nk2X_I-c9E~4fBsnb_x z&7Ngzq1inB@Woqi-rnfiGF7y<BJ%goW0A3G&CP97J93+rew?^?=aC%~&u<9q>w9zM z^p;~=3MY4TT)2AY!iC=7fBwej_wPS(UDm1P!}|}9?`#au+qhx#R?Fl=KuakHia%Lc z85lGfbU;Rd{N%v)|G<<24;`ug6HAIt=2*?Yu%d)ZG@><(acbwmDSj%f4MMZ#%vkt3 z%+g~)i<pR3VyF7n8#Z$JA<O@`mzEZZI~9w$$|__BGb*!0O9%_{aQAqM=SM3kP4|vm z(BRE1&gaoJFMyGSaitRjFE7_TKF--n%yZZ6cH(2+zszk#Ph`ZR>8kP^LLB_(WJHBo z)4eilyozQ8a&qqSt%<6xpa0;xA7k;M?mchbzI*>+`RnL~M?L!{MDwZt;o_B2<MUBS zf8W6@vUbsfBIEWxz1)=!e>F2$0=pQSpQ!u@RcUGT{(44KaY91N#ws_nDH9G%Qf=ZF z5o_THWH`G~`GwyilS^z$ZvV~I`dh4Lx_8c>?R@8gr-07UIgFjp0y#A&c{B)cE>2kS zL5I1;i$zoEA)6qV`HGJvVWE!{8MZ6ST|PC}d%K<xbI{vYcTaC$e}8|&bH2siMjBT& z{xP(Dc#_6(b?bhX$PZ!_9Bz&>i<?4}%fuUm8II^=2wdP1))w7xa^j`QZxmxvJKt#D zxH;qT)&eDCABP7k(~{;)Toy6)>d7{KiD{l18xziSGKuWtj9AkWy-*`}#c~0`Lrjq> z-;O-o=3A#@&dst%_SasuJq0xZW;OwR3vM!diY%Es?;J~Pp}LYununP(i|XxU>#u=* zSvNC^0?cJ=S?=UK4&2DdcCO^BsHxjWc4vR-Z64x&8r#>V9!<LDaqw)tCXZP-hw94E x+X50U2O7f@HcobM>JMd4O!Z*d@mNrgX=jUy;0|T>ZntHjDU$=-I8y`|tN~Y<KXd>9 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/de.js b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/de.js new file mode 100644 index 0000000..59bf788 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/de.js @@ -0,0 +1 @@ +tinyMCE.addI18n('de.simple',{"cleanup_desc":"Quellcode aufr\u00e4umen","redo_desc":"Wiederholen (Strg+Y)","undo_desc":"R\u00fcckg\u00e4ngig (Strg+Z)","numlist_desc":"Nummerierung","bullist_desc":"Aufz\u00e4hlung","striketrough_desc":"Durchgestrichen","underline_desc":"Unterstrichen (Strg+U)","italic_desc":"Kursiv (Strg+I)","bold_desc":"Fett (Strg+B)"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/en.js b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/en.js new file mode 100644 index 0000000..088ed0f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/en.js @@ -0,0 +1 @@ +tinyMCE.addI18n('en.simple',{"cleanup_desc":"Cleanup Messy Code","redo_desc":"Redo (Ctrl+Y)","undo_desc":"Undo (Ctrl+Z)","numlist_desc":"Insert/Remove Numbered List","bullist_desc":"Insert/Remove Bulleted List","striketrough_desc":"Strikethrough","underline_desc":"Underline (Ctrl+U)","italic_desc":"Italic (Ctrl+I)","bold_desc":"Bold (Ctrl+B)"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/fr.js b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/fr.js new file mode 100644 index 0000000..ebe964e --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/fr.js @@ -0,0 +1 @@ +tinyMCE.addI18n('fr.simple',{"cleanup_desc":"Nettoyer le code","redo_desc":"R\u00e9tablir (Ctrl+Y)","undo_desc":"Annuler (Ctrl+Z)","numlist_desc":"Liste num\u00e9rot\u00e9e","bullist_desc":"Liste \u00e0 puces","striketrough_desc":"Barr\u00e9","underline_desc":"Soulign\u00e9 (Ctrl+U)","italic_desc":"Italique (Ctrl+I)","bold_desc":"Gras (Ctrl+B)"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/it.js b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/it.js new file mode 100644 index 0000000..e0c45ed --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/langs/it.js @@ -0,0 +1 @@ +tinyMCE.addI18n('it.simple',{"cleanup_desc":"Pulisci codice disordinato","redo_desc":"Ripristina (Ctrl+Y)","undo_desc":"Annulla (Ctrl+Z)","numlist_desc":"Lista ordinata","bullist_desc":"Lista non ordinata","striketrough_desc":"Barrato","underline_desc":"Sottolineato (Ctrl+U)","italic_desc":"Corsivo (Ctrl+I)","bold_desc":"Grassetto (Ctrl+B)"}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/default/content.css b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/default/content.css new file mode 100644 index 0000000..2506c80 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/default/content.css @@ -0,0 +1,25 @@ +body, td, pre { + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 10px; +} + +body { + background-color: #FFFFFF; +} + +.mceVisualAid { + border: 1px dashed #BBBBBB; +} + +/* MSIE specific */ + +* html body { + scrollbar-3dlight-color: #F0F0EE; + scrollbar-arrow-color: #676662; + scrollbar-base-color: #F0F0EE; + scrollbar-darkshadow-color: #DDDDDD; + scrollbar-face-color: #E0E0DD; + scrollbar-highlight-color: #F0F0EE; + scrollbar-shadow-color: #F0F0EE; + scrollbar-track-color: #F5F5F5; +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/default/ui.css b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/default/ui.css new file mode 100644 index 0000000..076fe84 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/default/ui.css @@ -0,0 +1,32 @@ +/* Reset */ +.defaultSimpleSkin table, .defaultSimpleSkin tbody, .defaultSimpleSkin a, .defaultSimpleSkin img, .defaultSimpleSkin tr, .defaultSimpleSkin div, .defaultSimpleSkin td, .defaultSimpleSkin iframe, .defaultSimpleSkin span, .defaultSimpleSkin * {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000} + +/* Containers */ +.defaultSimpleSkin {position:relative} +.defaultSimpleSkin table.mceLayout {background:#F0F0EE; border:1px solid #CCC;} +.defaultSimpleSkin iframe {display:block; background:#FFF; border-bottom:1px solid #CCC;} +.defaultSimpleSkin .mceToolbar {height:24px;} + +/* Layout */ +.defaultSimpleSkin span.mceIcon, .defaultSimpleSkin img.mceIcon {display:block; width:20px; height:20px} +.defaultSimpleSkin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px} + +/* Button */ +.defaultSimpleSkin .mceButton {display:block; border:1px solid #F0F0EE; width:20px; height:20px} +.defaultSimpleSkin a.mceButtonEnabled:hover {border:1px solid #0A246A; background-color:#B2BBD0} +.defaultSimpleSkin a.mceButtonActive {border:1px solid #0A246A; background-color:#C2CBE0} +.defaultSimpleSkin .mceButtonDisabled span {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} + +/* Separator */ +.defaultSimpleSkin .mceSeparator {display:block; background:url(../../img/icons.gif) -180px 0; width:2px; height:20px; margin:0 2px 0 4px} + +/* Theme */ +.defaultSimpleSkin span.mce_bold {background-position:0 0} +.defaultSimpleSkin span.mce_italic {background-position:-60px 0} +.defaultSimpleSkin span.mce_underline {background-position:-140px 0} +.defaultSimpleSkin span.mce_strikethrough {background-position:-120px 0} +.defaultSimpleSkin span.mce_undo {background-position:-160px 0} +.defaultSimpleSkin span.mce_redo {background-position:-100px 0} +.defaultSimpleSkin span.mce_cleanup {background-position:-40px 0} +.defaultSimpleSkin span.mce_insertunorderedlist {background-position:-20px 0} +.defaultSimpleSkin span.mce_insertorderedlist {background-position:-80px 0} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/o2k7/content.css b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/o2k7/content.css new file mode 100644 index 0000000..595809f --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/o2k7/content.css @@ -0,0 +1,17 @@ +body, td, pre {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;} + +body {background: #FFF;} +.mceVisualAid {border: 1px dashed #BBB;} + +/* IE */ + +* html body { +scrollbar-3dlight-color: #F0F0EE; +scrollbar-arrow-color: #676662; +scrollbar-base-color: #F0F0EE; +scrollbar-darkshadow-color: #DDDDDD; +scrollbar-face-color: #E0E0DD; +scrollbar-highlight-color: #F0F0EE; +scrollbar-shadow-color: #F0F0EE; +scrollbar-track-color: #F5F5F5; +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/o2k7/img/button_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..527e3495a653e57d76bf7e55316793d17dda497a GIT binary patch literal 5102 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 VmjT$ODWe$zObpERYjs_s{s;8{A&me4 literal 0 HcmV?d00001 diff --git a/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/o2k7/ui.css b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/o2k7/ui.css new file mode 100644 index 0000000..cf6c35d --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/themes/simple/skins/o2k7/ui.css @@ -0,0 +1,35 @@ +/* Reset */ +.o2k7SimpleSkin table, .o2k7SimpleSkin tbody, .o2k7SimpleSkin a, .o2k7SimpleSkin img, .o2k7SimpleSkin tr, .o2k7SimpleSkin div, .o2k7SimpleSkin td, .o2k7SimpleSkin iframe, .o2k7SimpleSkin span, .o2k7SimpleSkin * {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000} + +/* Containers */ +.o2k7SimpleSkin {position:relative} +.o2k7SimpleSkin table.mceLayout {background:#E5EFFD; border:1px solid #ABC6DD;} +.o2k7SimpleSkin iframe {display:block; background:#FFF; border-bottom:1px solid #ABC6DD;} +.o2k7SimpleSkin .mceToolbar {height:26px;} + +/* Layout */ +.o2k7SimpleSkin .mceToolbar .mceToolbarStart span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px; } +.o2k7SimpleSkin .mceToolbar .mceToolbarEnd span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px} +.o2k7SimpleSkin span.mceIcon, .o2k7SimpleSkin img.mceIcon {display:block; width:20px; height:20px} +.o2k7SimpleSkin .mceIcon {background:url(../../img/icons.gif) no-repeat 20px 20px} + +/* Button */ +.o2k7SimpleSkin .mceButton {display:block; background:url(img/button_bg.png); width:22px; height:22px} +.o2k7SimpleSkin a.mceButton span, .o2k7SimpleSkin a.mceButton img {margin:1px 0 0 1px} +.o2k7SimpleSkin a.mceButtonEnabled:hover {background-color:#B2BBD0; background-position:0 -22px} +.o2k7SimpleSkin a.mceButtonActive {background-position:0 -44px} +.o2k7SimpleSkin .mceButtonDisabled span {opacity:0.3; -ms-filter:'alpha(opacity=30)'; filter:alpha(opacity=30)} + +/* Separator */ +.o2k7SimpleSkin .mceSeparator {display:block; background:url(img/button_bg.png) -22px 0; width:5px; height:22px} + +/* Theme */ +.o2k7SimpleSkin span.mce_bold {background-position:0 0} +.o2k7SimpleSkin span.mce_italic {background-position:-60px 0} +.o2k7SimpleSkin span.mce_underline {background-position:-140px 0} +.o2k7SimpleSkin span.mce_strikethrough {background-position:-120px 0} +.o2k7SimpleSkin span.mce_undo {background-position:-160px 0} +.o2k7SimpleSkin span.mce_redo {background-position:-100px 0} +.o2k7SimpleSkin span.mce_cleanup {background-position:-40px 0} +.o2k7SimpleSkin span.mce_insertunorderedlist {background-position:-20px 0} +.o2k7SimpleSkin span.mce_insertorderedlist {background-position:-80px 0} diff --git a/src/static/org_glizy/assets/js/tiny_mce/tiny_mce.js b/src/static/org_glizy/assets/js/tiny_mce/tiny_mce.js new file mode 100644 index 0000000..e1c0acf --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/tiny_mce.js @@ -0,0 +1 @@ +(function(d){var a=/^\s*|\s*$/g,e,c="B".replace(/A(.)|B/,"$1")==="$1";var b={majorVersion:"3",minorVersion:"4.6",releaseDate:"2011-09-29",_init:function(){var s=this,q=document,o=navigator,g=o.userAgent,m,f,l,k,j,r;s.isOpera=d.opera&&opera.buildNumber;s.isWebKit=/WebKit/.test(g);s.isIE=!s.isWebKit&&!s.isOpera&&(/MSIE/gi).test(g)&&(/Explorer/gi).test(o.appName);s.isIE6=s.isIE&&/MSIE [56]/.test(g);s.isIE7=s.isIE&&/MSIE [7]/.test(g);s.isIE8=s.isIE&&/MSIE [8]/.test(g);s.isIE9=s.isIE&&/MSIE [9]/.test(g);s.isGecko=!s.isWebKit&&/Gecko/.test(g);s.isMac=g.indexOf("Mac")!=-1;s.isAir=/adobeair/i.test(g);s.isIDevice=/(iPad|iPhone)/.test(g);s.isIOS5=s.isIDevice&&g.match(/AppleWebKit\/(\d*)/)[1]>=534;if(d.tinyMCEPreInit){s.suffix=tinyMCEPreInit.suffix;s.baseURL=tinyMCEPreInit.base;s.query=tinyMCEPreInit.query;return}s.suffix="";f=q.getElementsByTagName("base");for(m=0;m<f.length;m++){if(r=f[m].href){if(/^https?:\/\/[^\/]+$/.test(r)){r+="/"}k=r?r.match(/.*\//)[0]:""}}function h(i){if(i.src&&/tiny_mce(|_gzip|_jquery|_prototype|_full)(_dev|_src)?.js/.test(i.src)){if(/_(src|dev)\.js/g.test(i.src)){s.suffix="_src"}if((j=i.src.indexOf("?"))!=-1){s.query=i.src.substring(j+1)}s.baseURL=i.src.substring(0,i.src.lastIndexOf("/"));if(k&&s.baseURL.indexOf("://")==-1&&s.baseURL.indexOf("/")!==0){s.baseURL=k+s.baseURL}return s.baseURL}return null}f=q.getElementsByTagName("script");for(m=0;m<f.length;m++){if(h(f[m])){return}}l=q.getElementsByTagName("head")[0];if(l){f=l.getElementsByTagName("script");for(m=0;m<f.length;m++){if(h(f[m])){return}}}return},is:function(g,f){if(!f){return g!==e}if(f=="array"&&(g.hasOwnProperty&&g instanceof Array)){return true}return typeof(g)==f},makeMap:function(f,j,h){var g;f=f||[];j=j||",";if(typeof(f)=="string"){f=f.split(j)}h=h||{};g=f.length;while(g--){h[f[g]]={}}return h},each:function(i,f,h){var j,g;if(!i){return 0}h=h||i;if(i.length!==e){for(j=0,g=i.length;j<g;j++){if(f.call(h,i[j],j,i)===false){return 0}}}else{for(j in i){if(i.hasOwnProperty(j)){if(f.call(h,i[j],j,i)===false){return 0}}}}return 1},map:function(g,h){var i=[];b.each(g,function(f){i.push(h(f))});return i},grep:function(g,h){var i=[];b.each(g,function(f){if(!h||h(f)){i.push(f)}});return i},inArray:function(g,h){var j,f;if(g){for(j=0,f=g.length;j<f;j++){if(g[j]===h){return j}}}return -1},extend:function(k,j){var h,g,f=arguments;for(h=1,g=f.length;h<g;h++){j=f[h];b.each(j,function(i,l){if(i!==e){k[l]=i}})}return k},trim:function(f){return(f?""+f:"").replace(a,"")},create:function(o,f,j){var n=this,g,i,k,l,h,m=0;o=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(o);k=o[3].match(/(^|\.)(\w+)$/i)[2];i=n.createNS(o[3].replace(/\.\w+$/,""),j);if(i[k]){return}if(o[2]=="static"){i[k]=f;if(this.onCreate){this.onCreate(o[2],o[3],i[k])}return}if(!f[k]){f[k]=function(){};m=1}i[k]=f[k];n.extend(i[k].prototype,f);if(o[5]){g=n.resolve(o[5]).prototype;l=o[5].match(/\.(\w+)$/i)[1];h=i[k];if(m){i[k]=function(){return g[l].apply(this,arguments)}}else{i[k]=function(){this.parent=g[l];return h.apply(this,arguments)}}i[k].prototype[k]=i[k];n.each(g,function(p,q){i[k].prototype[q]=g[q]});n.each(f,function(p,q){if(g[q]){i[k].prototype[q]=function(){this.parent=g[q];return p.apply(this,arguments)}}else{if(q!=k){i[k].prototype[q]=p}}})}n.each(f["static"],function(p,q){i[k][q]=p});if(this.onCreate){this.onCreate(o[2],o[3],i[k].prototype)}},walk:function(i,h,j,g){g=g||this;if(i){if(j){i=i[j]}b.each(i,function(k,f){if(h.call(g,k,f,j)===false){return false}b.walk(k,h,j,g)})}},createNS:function(j,h){var g,f;h=h||d;j=j.split(".");for(g=0;g<j.length;g++){f=j[g];if(!h[f]){h[f]={}}h=h[f]}return h},resolve:function(j,h){var g,f;h=h||d;j=j.split(".");for(g=0,f=j.length;g<f;g++){h=h[j[g]];if(!h){break}}return h},addUnload:function(j,i){var h=this;j={func:j,scope:i||this};if(!h.unloads){function g(){var f=h.unloads,l,m;if(f){for(m in f){l=f[m];if(l&&l.func){l.func.call(l.scope,1)}}if(d.detachEvent){d.detachEvent("onbeforeunload",k);d.detachEvent("onunload",g)}else{if(d.removeEventListener){d.removeEventListener("unload",g,false)}}h.unloads=l=f=w=g=0;if(d.CollectGarbage){CollectGarbage()}}}function k(){var l=document;if(l.readyState=="interactive"){function f(){l.detachEvent("onstop",f);if(g){g()}l=0}if(l){l.attachEvent("onstop",f)}d.setTimeout(function(){if(l){l.detachEvent("onstop",f)}},0)}}if(d.attachEvent){d.attachEvent("onunload",g);d.attachEvent("onbeforeunload",k)}else{if(d.addEventListener){d.addEventListener("unload",g,false)}}h.unloads=[j]}else{h.unloads.push(j)}return j},removeUnload:function(i){var g=this.unloads,h=null;b.each(g,function(j,f){if(j&&j.func==i){g.splice(f,1);h=i;return false}});return h},explode:function(f,g){return f?b.map(f.split(g||","),b.trim):f},_addVer:function(g){var f;if(!this.query){return g}f=(g.indexOf("?")==-1?"?":"&")+this.query;if(g.indexOf("#")==-1){return g+f}return g.replace("#",f+"#")},_replace:function(h,f,g){if(c){return g.replace(h,function(){var l=f,j=arguments,k;for(k=0;k<j.length-2;k++){if(j[k]===e){l=l.replace(new RegExp("\\$"+k,"g"),"")}else{l=l.replace(new RegExp("\\$"+k,"g"),j[k])}}return l})}return g.replace(h,f)}};b._init();d.tinymce=d.tinyMCE=b})(window);tinymce.create("tinymce.util.Dispatcher",{scope:null,listeners:null,Dispatcher:function(a){this.scope=a||this;this.listeners=[]},add:function(a,b){this.listeners.push({cb:a,scope:b||this.scope});return a},addToTop:function(a,b){this.listeners.unshift({cb:a,scope:b||this.scope});return a},remove:function(a){var b=this.listeners,c=null;tinymce.each(b,function(e,d){if(a==e.cb){c=a;b.splice(d,1);return false}});return c},dispatch:function(){var f,d=arguments,e,b=this.listeners,g;for(e=0;e<b.length;e++){g=b[e];f=g.cb.apply(g.scope,d);if(f===false){break}}return f}});(function(){var a=tinymce.each;tinymce.create("tinymce.util.URI",{URI:function(e,g){var f=this,i,d,c,h;e=tinymce.trim(e);g=f.settings=g||{};if(/^([\w\-]+):([^\/]{2})/i.test(e)||/^\s*#/.test(e)){f.source=e;return}if(e.indexOf("/")===0&&e.indexOf("//")!==0){e=(g.base_uri?g.base_uri.protocol||"http":"http")+"://mce_host"+e}if(!/^[\w-]*:?\/\//.test(e)){h=g.base_uri?g.base_uri.path:new tinymce.util.URI(location.href).directory;e=((g.base_uri&&g.base_uri.protocol)||"http")+"://mce_host"+f.toAbsPath(h,e)}e=e.replace(/@@/g,"(mce_at)");e=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(e);a(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(b,j){var k=e[j];if(k){k=k.replace(/\(mce_at\)/g,"@@")}f[b]=k});if(c=g.base_uri){if(!f.protocol){f.protocol=c.protocol}if(!f.userInfo){f.userInfo=c.userInfo}if(!f.port&&f.host=="mce_host"){f.port=c.port}if(!f.host||f.host=="mce_host"){f.host=c.host}f.source=""}},setPath:function(c){var b=this;c=/^(.*?)\/?(\w+)?$/.exec(c);b.path=c[0];b.directory=c[1];b.file=c[2];b.source="";b.getURI()},toRelative:function(b){var c=this,d;if(b==="./"){return b}b=new tinymce.util.URI(b,{base_uri:c});if((b.host!="mce_host"&&c.host!=b.host&&b.host)||c.port!=b.port||c.protocol!=b.protocol){return b.getURI()}d=c.toRelPath(c.path,b.path);if(b.query){d+="?"+b.query}if(b.anchor){d+="#"+b.anchor}return d},toAbsolute:function(b,c){var b=new tinymce.util.URI(b,{base_uri:this});return b.getURI(this.host==b.host&&this.protocol==b.protocol?c:0)},toRelPath:function(g,h){var c,f=0,d="",e,b;g=g.substring(0,g.lastIndexOf("/"));g=g.split("/");c=h.split("/");if(g.length>=c.length){for(e=0,b=g.length;e<b;e++){if(e>=c.length||g[e]!=c[e]){f=e+1;break}}}if(g.length<c.length){for(e=0,b=c.length;e<b;e++){if(e>=g.length||g[e]!=c[e]){f=e+1;break}}}if(f==1){return h}for(e=0,b=g.length-(f-1);e<b;e++){d+="../"}for(e=f-1,b=c.length;e<b;e++){if(e!=f-1){d+="/"+c[e]}else{d+=c[e]}}return d},toAbsPath:function(e,f){var c,b=0,h=[],d,g;d=/\/$/.test(f)?"/":"";e=e.split("/");f=f.split("/");a(e,function(i){if(i){h.push(i)}});e=h;for(c=f.length-1,h=[];c>=0;c--){if(f[c].length==0||f[c]=="."){continue}if(f[c]==".."){b++;continue}if(b>0){b--;continue}h.push(f[c])}c=e.length-b;if(c<=0){g=h.reverse().join("/")}else{g=e.slice(0,c).join("/")+"/"+h.reverse().join("/")}if(g.indexOf("/")!==0){g="/"+g}if(d&&g.lastIndexOf("/")!==g.length-1){g+=d}return g},getURI:function(d){var c,b=this;if(!b.source||d){c="";if(!d){if(b.protocol){c+=b.protocol+"://"}if(b.userInfo){c+=b.userInfo+"@"}if(b.host){c+=b.host}if(b.port){c+=":"+b.port}}if(b.path){c+=b.path}if(b.query){c+="?"+b.query}if(b.anchor){c+="#"+b.anchor}b.source=c}return b.source}})})();(function(){var a=tinymce.each;tinymce.create("static tinymce.util.Cookie",{getHash:function(d){var b=this.get(d),c;if(b){a(b.split("&"),function(e){e=e.split("=");c=c||{};c[unescape(e[0])]=unescape(e[1])})}return c},setHash:function(j,b,g,f,i,c){var h="";a(b,function(e,d){h+=(!h?"":"&")+escape(d)+"="+escape(e)});this.set(j,h,g,f,i,c)},get:function(i){var h=document.cookie,g,f=i+"=",d;if(!h){return}d=h.indexOf("; "+f);if(d==-1){d=h.indexOf(f);if(d!=0){return null}}else{d+=2}g=h.indexOf(";",d);if(g==-1){g=h.length}return unescape(h.substring(d+f.length,g))},set:function(i,b,g,f,h,c){document.cookie=i+"="+escape(b)+((g)?"; expires="+g.toGMTString():"")+((f)?"; path="+escape(f):"")+((h)?"; domain="+h:"")+((c)?"; secure":"")},remove:function(e,b){var c=new Date();c.setTime(c.getTime()-1000);this.set(e,"",c,b,c)}})})();(function(){function serialize(o,quote){var i,v,t;quote=quote||'"';if(o==null){return"null"}t=typeof o;if(t=="string"){v="\bb\tt\nn\ff\rr\"\"''\\\\";return quote+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(a,b){if(quote==='"'&&a==="'"){return a}i=v.indexOf(b);if(i+1){return"\\"+v.charAt(i+1)}a=b.charCodeAt().toString(16);return"\\u"+"0000".substring(a.length)+a})+quote}if(t=="object"){if(o.hasOwnProperty&&o instanceof Array){for(i=0,v="[";i<o.length;i++){v+=(i>0?",":"")+serialize(o[i],quote)}return v+"]"}v="{";for(i in o){v+=typeof o[i]!="function"?(v.length>1?","+quote:quote)+i+quote+":"+serialize(o[i],quote):""}return v+"}"}return""+o}tinymce.util.JSON={serialize:serialize,parse:function(s){try{return eval("("+s+")")}catch(ex){}}}})();tinymce.create("static tinymce.util.XHR",{send:function(g){var a,e,b=window,h=0;g.scope=g.scope||this;g.success_scope=g.success_scope||g.scope;g.error_scope=g.error_scope||g.scope;g.async=g.async===false?false:true;g.data=g.data||"";function d(i){a=0;try{a=new ActiveXObject(i)}catch(c){}return a}a=b.XMLHttpRequest?new XMLHttpRequest():d("Microsoft.XMLHTTP")||d("Msxml2.XMLHTTP");if(a){if(a.overrideMimeType){a.overrideMimeType(g.content_type)}a.open(g.type||(g.data?"POST":"GET"),g.url,g.async);if(g.content_type){a.setRequestHeader("Content-Type",g.content_type)}a.setRequestHeader("X-Requested-With","XMLHttpRequest");a.send(g.data);function f(){if(!g.async||a.readyState==4||h++>10000){if(g.success&&h<10000&&a.status==200){g.success.call(g.success_scope,""+a.responseText,a,g)}else{if(g.error){g.error.call(g.error_scope,h>10000?"TIMED_OUT":"GENERAL",a,g)}}a=null}else{b.setTimeout(f,10)}}if(!g.async){return f()}e=b.setTimeout(f,10)}}});(function(){var c=tinymce.extend,b=tinymce.util.JSON,a=tinymce.util.XHR;tinymce.create("tinymce.util.JSONRequest",{JSONRequest:function(d){this.settings=c({},d);this.count=0},send:function(f){var e=f.error,d=f.success;f=c(this.settings,f);f.success=function(h,g){h=b.parse(h);if(typeof(h)=="undefined"){h={error:"JSON Parse error."}}if(h.error){e.call(f.error_scope||f.scope,h.error,g)}else{d.call(f.success_scope||f.scope,h.result)}};f.error=function(h,g){if(e){e.call(f.error_scope||f.scope,h,g)}};f.data=b.serialize({id:f.id||"c"+(this.count++),method:f.method,params:f.params});f.content_type="application/json";a.send(f)},"static":{sendRPC:function(d){return new tinymce.util.JSONRequest().send(d)}}})}());(function(a){a.VK={DELETE:46,BACKSPACE:8}})(tinymce);(function(i){var g=i.VK,h=g.BACKSPACE,f=g.DELETE;function b(j){var l=j.dom,k=j.selection;j.onKeyDown.add(function(n,r){var m,s,p,q,o;o=r.keyCode==f;if(o||r.keyCode==h){r.preventDefault();m=k.getRng();s=l.getParent(m.startContainer,l.isBlock);if(o){s=l.getNext(s,l.isBlock)}if(s){p=s.firstChild;while(p.nodeType==3&&p.nodeValue.length==0){p=p.nextSibling}if(p&&p.nodeName==="SPAN"){q=p.cloneNode(false)}}n.getDoc().execCommand(o?"ForwardDelete":"Delete",false,null);s=l.getParent(m.startContainer,l.isBlock);i.each(l.select("span.Apple-style-span,font.Apple-style-span",s),function(t){var u=k.getBookmark();if(q){l.replace(q.cloneNode(false),t,true)}else{l.remove(t,true)}k.moveToBookmark(u)})}})}function c(j){j.onKeyUp.add(function(k,m){var l=m.keyCode;if(l==f||l==h){if(k.dom.isEmpty(k.getBody())){k.setContent("",{format:"raw"});k.nodeChanged();return}}})}function a(j){j.dom.bind(j.getDoc(),"focusin",function(){j.selection.setRng(j.selection.getRng())})}function e(j){if(!Range.prototype.getClientRects){j.onMouseDown.add(function(l,m){if(m.target.nodeName==="HTML"){var k=l.getBody();k.blur();setTimeout(function(){k.focus()},0)}})}}function d(j){j.onClick.add(function(k,l){l=l.target;if(/^(IMG|HR)$/.test(l.nodeName)){k.selection.getSel().setBaseAndExtent(l,0,l,1)}if(l.nodeName=="A"&&k.dom.hasClass(l,"mceItemAnchor")){k.selection.select(l)}k.nodeChanged()})}i.create("tinymce.util.Quirks",{Quirks:function(j){if(i.isWebKit){b(j);c(j);a(j);d(j)}if(i.isIE){c(j)}if(i.isGecko){e(j)}}})})(tinymce);(function(j){var a,g,d,k=/[&<>\"\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,b=/[<>&\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,f=/[<>&\"\']/g,c=/&(#x|#)?([\w]+);/g,i={128:"\u20AC",130:"\u201A",131:"\u0192",132:"\u201E",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02C6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017D",145:"\u2018",146:"\u2019",147:"\u201C",148:"\u201D",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02DC",153:"\u2122",154:"\u0161",155:"\u203A",156:"\u0153",158:"\u017E",159:"\u0178"};g={'"':"&quot;","'":"&#39;","<":"&lt;",">":"&gt;","&":"&amp;"};d={"&lt;":"<","&gt;":">","&amp;":"&","&quot;":'"',"&apos;":"'"};function h(l){var m;m=document.createElement("div");m.innerHTML=l;return m.textContent||m.innerText||l}function e(m,p){var n,o,l,q={};if(m){m=m.split(",");p=p||10;for(n=0;n<m.length;n+=2){o=String.fromCharCode(parseInt(m[n],p));if(!g[o]){l="&"+m[n+1]+";";q[o]=l;q[l]=o}}return q}}a=e("50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,t9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro",32);j.html=j.html||{};j.html.Entities={encodeRaw:function(m,l){return m.replace(l?k:b,function(n){return g[n]||n})},encodeAllRaw:function(l){return(""+l).replace(f,function(m){return g[m]||m})},encodeNumeric:function(m,l){return m.replace(l?k:b,function(n){if(n.length>1){return"&#"+(((n.charCodeAt(0)-55296)*1024)+(n.charCodeAt(1)-56320)+65536)+";"}return g[n]||"&#"+n.charCodeAt(0)+";"})},encodeNamed:function(n,l,m){m=m||a;return n.replace(l?k:b,function(o){return g[o]||m[o]||o})},getEncodeFunc:function(l,o){var p=j.html.Entities;o=e(o)||a;function m(r,q){return r.replace(q?k:b,function(s){return g[s]||o[s]||"&#"+s.charCodeAt(0)+";"||s})}function n(r,q){return p.encodeNamed(r,q,o)}l=j.makeMap(l.replace(/\+/g,","));if(l.named&&l.numeric){return m}if(l.named){if(o){return n}return p.encodeNamed}if(l.numeric){return p.encodeNumeric}return p.encodeRaw},decode:function(l){return l.replace(c,function(n,m,o){if(m){o=parseInt(o,m.length===2?16:10);if(o>65535){o-=65536;return String.fromCharCode(55296+(o>>10),56320+(o&1023))}else{return i[o]||String.fromCharCode(o)}}return d[n]||a[n]||h(n)})}}})(tinymce);tinymce.html.Styles=function(d,f){var k=/rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,h=/(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,b=/\s*([^:]+):\s*([^;]+);?/g,l=/\s+$/,m=/rgb/,e,g,a={},j;d=d||{};j="\\\" \\' \\; \\: ; : \uFEFF".split(" ");for(g=0;g<j.length;g++){a[j[g]]="\uFEFF"+g;a["\uFEFF"+g]=j[g]}function c(n,q,p,i){function o(r){r=parseInt(r).toString(16);return r.length>1?r:"0"+r}return"#"+o(q)+o(p)+o(i)}return{toHex:function(i){return i.replace(k,c)},parse:function(r){var y={},p,n,v,q,u=d.url_converter,x=d.url_converter_scope||this;function o(C,F){var E,B,A,D;E=y[C+"-top"+F];if(!E){return}B=y[C+"-right"+F];if(E!=B){return}A=y[C+"-bottom"+F];if(B!=A){return}D=y[C+"-left"+F];if(A!=D){return}y[C+F]=D;delete y[C+"-top"+F];delete y[C+"-right"+F];delete y[C+"-bottom"+F];delete y[C+"-left"+F]}function t(B){var C=y[B],A;if(!C||C.indexOf(" ")<0){return}C=C.split(" ");A=C.length;while(A--){if(C[A]!==C[0]){return false}}y[B]=C[0];return true}function z(C,B,A,D){if(!t(B)){return}if(!t(A)){return}if(!t(D)){return}y[C]=y[B]+" "+y[A]+" "+y[D];delete y[B];delete y[A];delete y[D]}function s(A){q=true;return a[A]}function i(B,A){if(q){B=B.replace(/\uFEFF[0-9]/g,function(C){return a[C]})}if(!A){B=B.replace(/\\([\'\";:])/g,"$1")}return B}if(r){r=r.replace(/\\[\"\';:\uFEFF]/g,s).replace(/\"[^\"]+\"|\'[^\']+\'/g,function(A){return A.replace(/[;:]/g,s)});while(p=b.exec(r)){n=p[1].replace(l,"").toLowerCase();v=p[2].replace(l,"");if(n&&v.length>0){if(n==="font-weight"&&v==="700"){v="bold"}else{if(n==="color"||n==="background-color"){v=v.toLowerCase()}}v=v.replace(k,c);v=v.replace(h,function(B,A,E,D,F,C){F=F||C;if(F){F=i(F);return"'"+F.replace(/\'/g,"\\'")+"'"}A=i(A||E||D);if(u){A=u.call(x,A,"style")}return"url('"+A.replace(/\'/g,"\\'")+"')"});y[n]=q?i(v,true):v}b.lastIndex=p.index+p[0].length}o("border","");o("border","-width");o("border","-color");o("border","-style");o("padding","");o("margin","");z("border","border-width","border-style","border-color");if(y.border==="medium none"){delete y.border}}return y},serialize:function(p,r){var o="",n,q;function i(t){var x,u,s,v;x=f.styles[t];if(x){for(u=0,s=x.length;u<s;u++){t=x[u];v=p[t];if(v!==e&&v.length>0){o+=(o.length>0?" ":"")+t+": "+v+";"}}}}if(r&&f&&f.styles){i("*");i(r)}else{for(n in p){q=p[n];if(q!==e&&q.length>0){o+=(o.length>0?" ":"")+n+": "+q+";"}}}return o}}};(function(m){var h={},j,l,g,f,c={},b,e,d=m.makeMap,k=m.each;function i(o,n){return o.split(n||",")}function a(r,q){var o,p={};function n(s){return s.replace(/[A-Z]+/g,function(t){return n(r[t])})}for(o in r){if(r.hasOwnProperty(o)){r[o]=n(r[o])}}n(q).replace(/#/g,"#text").replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g,function(v,t,s,u){s=i(s,"|");p[t]={attributes:d(s),attributesOrder:s,children:d(u,"|",{"#comment":{}})}});return p}l="h1,h2,h3,h4,h5,h6,hr,p,div,address,pre,form,table,tbody,thead,tfoot,th,tr,td,li,ol,ul,caption,blockquote,center,dl,dt,dd,dir,fieldset,noscript,menu,isindex,samp,header,footer,article,section,hgroup";l=d(l,",",d(l.toUpperCase()));h=a({Z:"H|K|N|O|P",Y:"X|form|R|Q",ZG:"E|span|width|align|char|charoff|valign",X:"p|T|div|U|W|isindex|fieldset|table",ZF:"E|align|char|charoff|valign",W:"pre|hr|blockquote|address|center|noframes",ZE:"abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height",ZD:"[E][S]",U:"ul|ol|dl|menu|dir",ZC:"p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q",T:"h1|h2|h3|h4|h5|h6",ZB:"X|S|Q",S:"R|P",ZA:"a|G|J|M|O|P",R:"a|H|K|N|O",Q:"noscript|P",P:"ins|del|script",O:"input|select|textarea|label|button",N:"M|L",M:"em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym",L:"sub|sup",K:"J|I",J:"tt|i|b|u|s|strike",I:"big|small|font|basefont",H:"G|F",G:"br|span|bdo",F:"object|applet|img|map|iframe",E:"A|B|C",D:"accesskey|tabindex|onfocus|onblur",C:"onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup",B:"lang|xml:lang|dir",A:"id|class|style|title"},"script[id|charset|type|language|src|defer|xml:space][]style[B|id|type|media|title|xml:space][]object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]param[id|name|value|valuetype|type][]p[E|align][#|S]a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]br[A|clear][]span[E][#|S]bdo[A|C|B][#|S]applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]h1[E|align][#|S]img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]map[B|C|A|name][X|form|Q|area]h2[E|align][#|S]iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]h3[E|align][#|S]tt[E][#|S]i[E][#|S]b[E][#|S]u[E][#|S]s[E][#|S]strike[E][#|S]big[E][#|S]small[E][#|S]font[A|B|size|color|face][#|S]basefont[id|size|color|face][]em[E][#|S]strong[E][#|S]dfn[E][#|S]code[E][#|S]q[E|cite][#|S]samp[E][#|S]kbd[E][#|S]var[E][#|S]cite[E][#|S]abbr[E][#|S]acronym[E][#|S]sub[E][#|S]sup[E][#|S]input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]optgroup[E|disabled|label][option]option[E|selected|disabled|label|value][]textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]label[E|for|accesskey|onfocus|onblur][#|S]button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]h4[E|align][#|S]ins[E|cite|datetime][#|Y]h5[E|align][#|S]del[E|cite|datetime][#|Y]h6[E|align][#|S]div[E|align][#|Y]ul[E|type|compact][li]li[E|type|value][#|Y]ol[E|type|compact|start][li]dl[E|compact][dt|dd]dt[E][#|S]dd[E][#|Y]menu[E|compact][li]dir[E|compact][li]pre[E|width|xml:space][#|ZA]hr[E|align|noshade|size|width][]blockquote[E|cite][#|Y]address[E][#|S|p]center[E][#|Y]noframes[E][#|Y]isindex[A|B|prompt][]fieldset[E][#|legend|Y]legend[E|accesskey|align][#|S]table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]caption[E|align][#|S]col[ZG][]colgroup[ZG][col]thead[ZF][tr]tr[ZF|bgcolor][th|td]th[E|ZE][#|Y]form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]noscript[E][#|Y]td[E|ZE][#|Y]tfoot[ZF][tr]tbody[ZF][tr]area[E|D|shape|coords|href|nohref|alt|target][]base[id|href|target][]body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]");j=d("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected,autoplay,loop,controls");g=d("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,source");f=m.extend(d("td,th,iframe,video,audio,object"),g);b=d("pre,script,style,textarea");e=d("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");m.html.Schema=function(r){var A=this,n={},o={},y=[],q,p;r=r||{};if(r.verify_html===false){r.valid_elements="*[*]"}if(r.valid_styles){q={};k(r.valid_styles,function(C,B){q[B]=m.explode(C)})}p=r.whitespace_elements?d(r.whitespace_elements):b;function z(B){return new RegExp("^"+B.replace(/([?+*])/g,".$1")+"$")}function t(I){var H,D,W,S,X,C,F,R,U,N,V,Z,L,G,T,B,P,E,Y,aa,M,Q,K=/^([#+-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,O=/^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,J=/[*?+]/;if(I){I=i(I);if(n["@"]){P=n["@"].attributes;E=n["@"].attributesOrder}for(H=0,D=I.length;H<D;H++){C=K.exec(I[H]);if(C){T=C[1];N=C[2];B=C[3];U=C[4];L={};G=[];F={attributes:L,attributesOrder:G};if(T==="#"){F.paddEmpty=true}if(T==="-"){F.removeEmpty=true}if(P){for(aa in P){L[aa]=P[aa]}G.push.apply(G,E)}if(U){U=i(U,"|");for(W=0,S=U.length;W<S;W++){C=O.exec(U[W]);if(C){R={};Z=C[1];V=C[2].replace(/::/g,":");T=C[3];Q=C[4];if(Z==="!"){F.attributesRequired=F.attributesRequired||[];F.attributesRequired.push(V);R.required=true}if(Z==="-"){delete L[V];G.splice(m.inArray(G,V),1);continue}if(T){if(T==="="){F.attributesDefault=F.attributesDefault||[];F.attributesDefault.push({name:V,value:Q});R.defaultValue=Q}if(T===":"){F.attributesForced=F.attributesForced||[];F.attributesForced.push({name:V,value:Q});R.forcedValue=Q}if(T==="<"){R.validValues=d(Q,"?")}}if(J.test(V)){F.attributePatterns=F.attributePatterns||[];R.pattern=z(V);F.attributePatterns.push(R)}else{if(!L[V]){G.push(V)}L[V]=R}}}}if(!P&&N=="@"){P=L;E=G}if(B){F.outputName=N;n[B]=F}if(J.test(N)){F.pattern=z(N);y.push(F)}else{n[N]=F}}}}}function v(B){n={};y=[];t(B);k(h,function(D,C){o[C]=D.children})}function s(C){var B=/^(~)?(.+)$/;if(C){k(i(C),function(G){var E=B.exec(G),F=E[1]==="~",H=F?"span":"div",D=E[2];o[D]=o[H];c[D]=H;if(!F){l[D]={}}k(o,function(I,J){if(I[H]){I[D]=I[H]}})})}}function u(C){var B=/^([+\-]?)(\w+)\[([^\]]+)\]$/;if(C){k(i(C),function(G){var F=B.exec(G),D,E;if(F){E=F[1];if(E){D=o[F[2]]}else{D=o[F[2]]={"#comment":{}}}D=o[F[2]];k(i(F[3],"|"),function(H){if(E==="-"){delete D[H]}else{D[H]={}}})}})}}function x(B){var D=n[B],C;if(D){return D}C=y.length;while(C--){D=y[C];if(D.pattern.test(B)){return D}}}if(!r.valid_elements){k(h,function(C,B){n[B]={attributes:C.attributes,attributesOrder:C.attributesOrder};o[B]=C.children});k(i("strong/b,em/i"),function(B){B=i(B,"/");n[B[1]].outputName=B[0]});n.img.attributesDefault=[{name:"alt",value:""}];k(i("ol,ul,sub,sup,blockquote,span,font,a,table,tbody,tr"),function(B){n[B].removeEmpty=true});k(i("p,h1,h2,h3,h4,h5,h6,th,td,pre,div,address,caption"),function(B){n[B].paddEmpty=true})}else{v(r.valid_elements)}s(r.custom_elements);u(r.valid_children);t(r.extended_valid_elements);u("+ol[ul|ol],+ul[ul|ol]");if(!x("span")){t("span[!data-mce-type|*]")}if(r.invalid_elements){m.each(m.explode(r.invalid_elements),function(B){if(n[B]){delete n[B]}})}A.children=o;A.styles=q;A.getBoolAttrs=function(){return j};A.getBlockElements=function(){return l};A.getShortEndedElements=function(){return g};A.getSelfClosingElements=function(){return e};A.getNonEmptyElements=function(){return f};A.getWhiteSpaceElements=function(){return p};A.isValidChild=function(B,D){var C=o[B];return !!(C&&C[D])};A.getElementRule=x;A.getCustomElements=function(){return c};A.addValidElements=t;A.setValidElements=v;A.addCustomElements=s;A.addValidChildren=u};m.html.Schema.boolAttrMap=j;m.html.Schema.blockElementsMap=l})(tinymce);(function(a){a.html.SaxParser=function(c,e){var b=this,d=function(){};c=c||{};b.schema=e=e||new a.html.Schema();if(c.fix_self_closing!==false){c.fix_self_closing=true}a.each("comment cdata text start end pi doctype".split(" "),function(f){if(f){b[f]=c[f]||d}});b.parse=function(D){var n=this,g,F=0,H,A,z=[],M,P,B,q,y,r,L,G,N,u,m,k,s,Q,o,O,E,R,K,f,I,l,C,J,h,v=0,j=a.html.Entities.decode,x,p;function t(S){var U,T;U=z.length;while(U--){if(z[U].name===S){break}}if(U>=0){for(T=z.length-1;T>=U;T--){S=z[T];if(S.valid){n.end(S.name)}}z.length=U}}l=new RegExp("<(?:(?:!--([\\w\\W]*?)-->)|(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|(?:!DOCTYPE([\\w\\W]*?)>)|(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|(?:\\/([^>]+)>)|(?:([^\\s\\/<>]+)\\s*((?:[^\"'>]+(?:(?:\"[^\"]*\")|(?:'[^']*')|[^>]*))*)>))","g");C=/([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;J={script:/<\/script[^>]*>/gi,style:/<\/style[^>]*>/gi,noscript:/<\/noscript[^>]*>/gi};L=e.getShortEndedElements();I=e.getSelfClosingElements();G=e.getBoolAttrs();u=c.validate;r=c.remove_internals;x=c.fix_self_closing;p=a.isIE;o=/^:/;while(g=l.exec(D)){if(F<g.index){n.text(j(D.substr(F,g.index-F)))}if(H=g[6]){H=H.toLowerCase();if(p&&o.test(H)){H=H.substr(1)}t(H)}else{if(H=g[7]){H=H.toLowerCase();if(p&&o.test(H)){H=H.substr(1)}N=H in L;if(x&&I[H]&&z.length>0&&z[z.length-1].name===H){t(H)}if(!u||(m=e.getElementRule(H))){k=true;if(u){O=m.attributes;E=m.attributePatterns}if(Q=g[8]){y=Q.indexOf("data-mce-type")!==-1;if(y&&r){k=false}M=[];M.map={};Q.replace(C,function(T,S,X,W,V){var Y,U;S=S.toLowerCase();X=S in G?S:j(X||W||V||"");if(u&&!y&&S.indexOf("data-")!==0){Y=O[S];if(!Y&&E){U=E.length;while(U--){Y=E[U];if(Y.pattern.test(S)){break}}if(U===-1){Y=null}}if(!Y){return}if(Y.validValues&&!(X in Y.validValues)){return}}M.map[S]=X;M.push({name:S,value:X})})}else{M=[];M.map={}}if(u&&!y){R=m.attributesRequired;K=m.attributesDefault;f=m.attributesForced;if(f){P=f.length;while(P--){s=f[P];q=s.name;h=s.value;if(h==="{$uid}"){h="mce_"+v++}M.map[q]=h;M.push({name:q,value:h})}}if(K){P=K.length;while(P--){s=K[P];q=s.name;if(!(q in M.map)){h=s.value;if(h==="{$uid}"){h="mce_"+v++}M.map[q]=h;M.push({name:q,value:h})}}}if(R){P=R.length;while(P--){if(R[P] in M.map){break}}if(P===-1){k=false}}if(M.map["data-mce-bogus"]){k=false}}if(k){n.start(H,M,N)}}else{k=false}if(A=J[H]){A.lastIndex=F=g.index+g[0].length;if(g=A.exec(D)){if(k){B=D.substr(F,g.index-F)}F=g.index+g[0].length}else{B=D.substr(F);F=D.length}if(k&&B.length>0){n.text(B,true)}if(k){n.end(H)}l.lastIndex=F;continue}if(!N){if(!Q||Q.indexOf("/")!=Q.length-1){z.push({name:H,valid:k})}else{if(k){n.end(H)}}}}else{if(H=g[1]){n.comment(H)}else{if(H=g[2]){n.cdata(H)}else{if(H=g[3]){n.doctype(H)}else{if(H=g[4]){n.pi(H,g[5])}}}}}}F=g.index+g[0].length}if(F<D.length){n.text(j(D.substr(F)))}for(P=z.length-1;P>=0;P--){H=z[P];if(H.valid){n.end(H.name)}}}}})(tinymce);(function(d){var c=/^[ \t\r\n]*$/,e={"#text":3,"#comment":8,"#cdata":4,"#pi":7,"#doctype":10,"#document-fragment":11};function a(k,l,j){var i,h,f=j?"lastChild":"firstChild",g=j?"prev":"next";if(k[f]){return k[f]}if(k!==l){i=k[g];if(i){return i}for(h=k.parent;h&&h!==l;h=h.parent){i=h[g];if(i){return i}}}}function b(f,g){this.name=f;this.type=g;if(g===1){this.attributes=[];this.attributes.map={}}}d.extend(b.prototype,{replace:function(g){var f=this;if(g.parent){g.remove()}f.insert(g,f);f.remove();return f},attr:function(h,l){var f=this,g,j,k;if(typeof h!=="string"){for(j in h){f.attr(j,h[j])}return f}if(g=f.attributes){if(l!==k){if(l===null){if(h in g.map){delete g.map[h];j=g.length;while(j--){if(g[j].name===h){g=g.splice(j,1);return f}}}return f}if(h in g.map){j=g.length;while(j--){if(g[j].name===h){g[j].value=l;break}}}else{g.push({name:h,value:l})}g.map[h]=l;return f}else{return g.map[h]}}},clone:function(){var g=this,n=new b(g.name,g.type),h,f,m,j,k;if(m=g.attributes){k=[];k.map={};for(h=0,f=m.length;h<f;h++){j=m[h];if(j.name!=="id"){k[k.length]={name:j.name,value:j.value};k.map[j.name]=j.value}}n.attributes=k}n.value=g.value;n.shortEnded=g.shortEnded;return n},wrap:function(g){var f=this;f.parent.insert(g,f);g.append(f);return f},unwrap:function(){var f=this,h,g;for(h=f.firstChild;h;){g=h.next;f.insert(h,f,true);h=g}f.remove()},remove:function(){var f=this,h=f.parent,g=f.next,i=f.prev;if(h){if(h.firstChild===f){h.firstChild=g;if(g){g.prev=null}}else{i.next=g}if(h.lastChild===f){h.lastChild=i;if(i){i.next=null}}else{g.prev=i}f.parent=f.next=f.prev=null}return f},append:function(h){var f=this,g;if(h.parent){h.remove()}g=f.lastChild;if(g){g.next=h;h.prev=g;f.lastChild=h}else{f.lastChild=f.firstChild=h}h.parent=f;return h},insert:function(h,f,i){var g;if(h.parent){h.remove()}g=f.parent||this;if(i){if(f===g.firstChild){g.firstChild=h}else{f.prev.next=h}h.prev=f.prev;h.next=f;f.prev=h}else{if(f===g.lastChild){g.lastChild=h}else{f.next.prev=h}h.next=f.next;h.prev=f;f.next=h}h.parent=g;return h},getAll:function(g){var f=this,h,i=[];for(h=f.firstChild;h;h=a(h,f)){if(h.name===g){i.push(h)}}return i},empty:function(){var g=this,f,h,j;if(g.firstChild){f=[];for(j=g.firstChild;j;j=a(j,g)){f.push(j)}h=f.length;while(h--){j=f[h];j.parent=j.firstChild=j.lastChild=j.next=j.prev=null}}g.firstChild=g.lastChild=null;return g},isEmpty:function(k){var f=this,j=f.firstChild,h,g;if(j){do{if(j.type===1){if(j.attributes.map["data-mce-bogus"]){continue}if(k[j.name]){return false}h=j.attributes.length;while(h--){g=j.attributes[h].name;if(g==="name"||g.indexOf("data-")===0){return false}}}if((j.type===3&&!c.test(j.value))){return false}}while(j=a(j,f))}return true},walk:function(f){return a(this,null,f)}});d.extend(b,{create:function(g,f){var i,h;i=new b(g,e[g]||1);if(f){for(h in f){i.attr(h,f[h])}}return i}});d.html.Node=b})(tinymce);(function(b){var a=b.html.Node;b.html.DomParser=function(g,h){var f=this,e={},d=[],i={},c={};g=g||{};g.validate="validate" in g?g.validate:true;g.root_name=g.root_name||"body";f.schema=h=h||new b.html.Schema();function j(m){var o,p,x,v,z,n,q,l,t,u,k,s,y,r;s=b.makeMap("tr,td,th,tbody,thead,tfoot,table");k=h.getNonEmptyElements();for(o=0;o<m.length;o++){p=m[o];if(!p.parent){continue}v=[p];for(x=p.parent;x&&!h.isValidChild(x.name,p.name)&&!s[x.name];x=x.parent){v.push(x)}if(x&&v.length>1){v.reverse();z=n=f.filterNode(v[0].clone());for(t=0;t<v.length-1;t++){if(h.isValidChild(n.name,v[t].name)){q=f.filterNode(v[t].clone());n.append(q)}else{q=n}for(l=v[t].firstChild;l&&l!=v[t+1];){r=l.next;q.append(l);l=r}n=q}if(!z.isEmpty(k)){x.insert(z,v[0],true);x.insert(p,z)}else{x.insert(p,v[0],true)}x=v[0];if(x.isEmpty(k)||x.firstChild===x.lastChild&&x.firstChild.name==="br"){x.empty().remove()}}else{if(p.parent){if(p.name==="li"){y=p.prev;if(y&&(y.name==="ul"||y.name==="ul")){y.append(p);continue}y=p.next;if(y&&(y.name==="ul"||y.name==="ul")){y.insert(p,y.firstChild,true);continue}p.wrap(f.filterNode(new a("ul",1)));continue}if(h.isValidChild(p.parent.name,"div")&&h.isValidChild("div",p.name)){p.wrap(f.filterNode(new a("div",1)))}else{if(p.name==="style"||p.name==="script"){p.empty().remove()}else{p.unwrap()}}}}}}f.filterNode=function(m){var l,k,n;if(k in e){n=i[k];if(n){n.push(m)}else{i[k]=[m]}}l=d.length;while(l--){k=d[l].name;if(k in m.attributes.map){n=c[k];if(n){n.push(m)}else{c[k]=[m]}}}return m};f.addNodeFilter=function(k,l){b.each(b.explode(k),function(m){var n=e[m];if(!n){e[m]=n=[]}n.push(l)})};f.addAttributeFilter=function(k,l){b.each(b.explode(k),function(m){var n;for(n=0;n<d.length;n++){if(d[n].name===m){d[n].callbacks.push(l);return}}d.push({name:m,callbacks:[l]})})};f.parse=function(v,m){var n,H,A,z,C,B,x,r,E,K,y,o,D,J=[],t,k,s,p,u,q;m=m||{};i={};c={};o=b.extend(b.makeMap("script,style,head,html,body,title,meta,param"),h.getBlockElements());u=h.getNonEmptyElements();p=h.children;y=g.validate;q="forced_root_block" in m?m.forced_root_block:g.forced_root_block;s=h.getWhiteSpaceElements();D=/^[ \t\r\n]+/;t=/[ \t\r\n]+$/;k=/[ \t\r\n]+/g;function F(){var L=H.firstChild,l,M;while(L){l=L.next;if(L.type==3||(L.type==1&&L.name!=="p"&&!o[L.name]&&!L.attr("data-mce-type"))){if(!M){M=I(q,1);H.insert(M,L);M.append(L)}else{M.append(L)}}else{M=null}L=l}}function I(l,L){var M=new a(l,L),N;if(l in e){N=i[l];if(N){N.push(M)}else{i[l]=[M]}}return M}function G(M){var N,l,L;for(N=M.prev;N&&N.type===3;){l=N.value.replace(t,"");if(l.length>0){N.value=l;N=N.prev}else{L=N.prev;N.remove();N=L}}}n=new b.html.SaxParser({validate:y,fix_self_closing:!y,cdata:function(l){A.append(I("#cdata",4)).value=l},text:function(M,l){var L;if(!s[A.name]){M=M.replace(k," ");if(A.lastChild&&o[A.lastChild.name]){M=M.replace(D,"")}}if(M.length!==0){L=I("#text",3);L.raw=!!l;A.append(L).value=M}},comment:function(l){A.append(I("#comment",8)).value=l},pi:function(l,L){A.append(I(l,7)).value=L;G(A)},doctype:function(L){var l;l=A.append(I("#doctype",10));l.value=L;G(A)},start:function(l,T,M){var R,O,N,L,P,U,S,Q;N=y?h.getElementRule(l):{};if(N){R=I(N.outputName||l,1);R.attributes=T;R.shortEnded=M;A.append(R);Q=p[A.name];if(Q&&p[R.name]&&!Q[R.name]){J.push(R)}O=d.length;while(O--){P=d[O].name;if(P in T.map){E=c[P];if(E){E.push(R)}else{c[P]=[R]}}}if(o[l]){G(R)}if(!M){A=R}}},end:function(l){var P,M,O,L,N;M=y?h.getElementRule(l):{};if(M){if(o[l]){if(!s[A.name]){for(P=A.firstChild;P&&P.type===3;){O=P.value.replace(D,"");if(O.length>0){P.value=O;P=P.next}else{L=P.next;P.remove();P=L}}for(P=A.lastChild;P&&P.type===3;){O=P.value.replace(t,"");if(O.length>0){P.value=O;P=P.prev}else{L=P.prev;P.remove();P=L}}}P=A.prev;if(P&&P.type===3){O=P.value.replace(D,"");if(O.length>0){P.value=O}else{P.remove()}}}if(M.removeEmpty||M.paddEmpty){if(A.isEmpty(u)){if(M.paddEmpty){A.empty().append(new a("#text","3")).value="\u00a0"}else{if(!A.attributes.map.name){N=A.parent;A.empty().remove();A=N;return}}}}A=A.parent}}},h);H=A=new a(m.context||g.root_name,11);n.parse(v);if(y&&J.length){if(!m.context){j(J)}else{m.invalid=true}}if(q&&H.name=="body"){F()}if(!m.invalid){for(K in i){E=e[K];z=i[K];x=z.length;while(x--){if(!z[x].parent){z.splice(x,1)}}for(C=0,B=E.length;C<B;C++){E[C](z,K,m)}}for(C=0,B=d.length;C<B;C++){E=d[C];if(E.name in c){z=c[E.name];x=z.length;while(x--){if(!z[x].parent){z.splice(x,1)}}for(x=0,r=E.callbacks.length;x<r;x++){E.callbacks[x](z,E.name,m)}}}}return H};if(g.remove_trailing_brs){f.addNodeFilter("br",function(n,m){var r,q=n.length,o,u=h.getBlockElements(),k=h.getNonEmptyElements(),s,p,t;u.body=1;for(r=0;r<q;r++){o=n[r];s=o.parent;if(u[o.parent.name]&&o===s.lastChild){p=o.prev;while(p){t=p.name;if(t!=="span"||p.attr("data-mce-type")!=="bookmark"){if(t!=="br"){break}if(t==="br"){o=null;break}}p=p.prev}if(o){o.remove();if(s.isEmpty(k)){elementRule=h.getElementRule(s.name);if(elementRule){if(elementRule.removeEmpty){s.remove()}else{if(elementRule.paddEmpty){s.empty().append(new b.html.Node("#text",3)).value="\u00a0"}}}}}}}})}}})(tinymce);tinymce.html.Writer=function(e){var c=[],a,b,d,f,g;e=e||{};a=e.indent;b=tinymce.makeMap(e.indent_before||"");d=tinymce.makeMap(e.indent_after||"");f=tinymce.html.Entities.getEncodeFunc(e.entity_encoding||"raw",e.entities);g=e.element_format=="html";return{start:function(m,k,p){var n,j,h,o;if(a&&b[m]&&c.length>0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}c.push("<",m);if(k){for(n=0,j=k.length;n<j;n++){h=k[n];c.push(" ",h.name,'="',f(h.value,true),'"')}}if(!p||g){c[c.length]=">"}else{c[c.length]=" />"}if(p&&a&&d[m]&&c.length>0){o=c[c.length-1];if(o.length>0&&o!=="\n"){c.push("\n")}}},end:function(h){var i;c.push("</",h,">");if(a&&d[h]&&c.length>0){i=c[c.length-1];if(i.length>0&&i!=="\n"){c.push("\n")}}},text:function(i,h){if(i.length>0){c[c.length]=h?i:f(i)}},cdata:function(h){c.push("<![CDATA[",h,"]]>")},comment:function(h){c.push("<!--",h,"-->")},pi:function(h,i){if(i){c.push("<?",h," ",i,"?>")}else{c.push("<?",h,"?>")}if(a){c.push("\n")}},doctype:function(h){c.push("<!DOCTYPE",h,">",a?"\n":"")},reset:function(){c.length=0},getContent:function(){return c.join("").replace(/\n$/,"")}}};(function(a){a.html.Serializer=function(c,d){var b=this,e=new a.html.Writer(c);c=c||{};c.validate="validate" in c?c.validate:true;b.schema=d=d||new a.html.Schema();b.writer=e;b.serialize=function(h){var g,i;i=c.validate;g={3:function(k,j){e.text(k.value,k.raw)},8:function(j){e.comment(j.value)},7:function(j){e.pi(j.name,j.value)},10:function(j){e.doctype(j.value)},4:function(j){e.cdata(j.value)},11:function(j){if((j=j.firstChild)){do{f(j)}while(j=j.next)}}};e.reset();function f(k){var t=g[k.type],j,o,s,r,p,u,n,m,q;if(!t){j=k.name;o=k.shortEnded;s=k.attributes;if(i&&s&&s.length>1){u=[];u.map={};q=d.getElementRule(k.name);for(n=0,m=q.attributesOrder.length;n<m;n++){r=q.attributesOrder[n];if(r in s.map){p=s.map[r];u.map[r]=p;u.push({name:r,value:p})}}for(n=0,m=s.length;n<m;n++){r=s[n].name;if(!(r in u.map)){p=s.map[r];u.map[r]=p;u.push({name:r,value:p})}}s=u}e.start(k.name,s,o);if(!o){if((k=k.firstChild)){do{f(k)}while(k=k.next)}e.end(j)}}else{t(k)}}if(h.type==1&&!c.inner){f(h)}else{g[11](h)}return e.getContent()}}})(tinymce);(function(h){var f=h.each,e=h.is,d=h.isWebKit,b=h.isIE,c=h.html.Entities,a=/^([a-z0-9],?)+$/i,g=h.html.Schema.blockElementsMap,i=/^[ \t\r\n]*$/;h.create("tinymce.dom.DOMUtils",{doc:null,root:null,files:null,pixelStyles:/^(top|left|bottom|right|width|height|borderWidth)$/,props:{"for":"htmlFor","class":"className",className:"className",checked:"checked",disabled:"disabled",maxlength:"maxLength",readonly:"readOnly",selected:"selected",value:"value",id:"id",name:"name",type:"type"},DOMUtils:function(o,m){var l=this,j,k;l.doc=o;l.win=window;l.files={};l.cssFlicker=false;l.counter=0;l.stdMode=!h.isIE||o.documentMode>=8;l.boxModel=!h.isIE||o.compatMode=="CSS1Compat"||l.stdMode;l.hasOuterHTML="outerHTML" in o.createElement("a");l.settings=m=h.extend({keep_values:false,hex_colors:1},m);l.schema=m.schema;l.styles=new h.html.Styles({url_converter:m.url_converter,url_converter_scope:m.url_converter_scope},m.schema);if(h.isIE6){try{o.execCommand("BackgroundImageCache",false,true)}catch(n){l.cssFlicker=true}}if(b&&m.schema){("abbr article aside audio canvas details figcaption figure footer header hgroup mark menu meter nav output progress section summary time video").replace(/\w+/g,function(p){o.createElement(p)});for(k in m.schema.getCustomElements()){o.createElement(k)}}h.addUnload(l.destroy,l)},getRoot:function(){var j=this,k=j.settings;return(k&&j.get(k.root_element))||j.doc.body},getViewPort:function(k){var l,j;k=!k?this.win:k;l=k.document;j=this.boxModel?l.documentElement:l.body;return{x:k.pageXOffset||j.scrollLeft,y:k.pageYOffset||j.scrollTop,w:k.innerWidth||j.clientWidth,h:k.innerHeight||j.clientHeight}},getRect:function(m){var l,j=this,k;m=j.get(m);l=j.getPos(m);k=j.getSize(m);return{x:l.x,y:l.y,w:k.w,h:k.h}},getSize:function(m){var k=this,j,l;m=k.get(m);j=k.getStyle(m,"width");l=k.getStyle(m,"height");if(j.indexOf("px")===-1){j=0}if(l.indexOf("px")===-1){l=0}return{w:parseInt(j)||m.offsetWidth||m.clientWidth,h:parseInt(l)||m.offsetHeight||m.clientHeight}},getParent:function(l,k,j){return this.getParents(l,k,j,false)},getParents:function(u,p,l,s){var k=this,j,m=k.settings,q=[];u=k.get(u);s=s===undefined;if(m.strict_root){l=l||k.getRoot()}if(e(p,"string")){j=p;if(p==="*"){p=function(o){return o.nodeType==1}}else{p=function(o){return k.is(o,j)}}}while(u){if(u==l||!u.nodeType||u.nodeType===9){break}if(!p||p(u)){if(s){q.push(u)}else{return u}}u=u.parentNode}return s?q:null},get:function(j){var k;if(j&&this.doc&&typeof(j)=="string"){k=j;j=this.doc.getElementById(j);if(j&&j.id!==k){return this.doc.getElementsByName(k)[1]}}return j},getNext:function(k,j){return this._findSib(k,j,"nextSibling")},getPrev:function(k,j){return this._findSib(k,j,"previousSibling")},select:function(l,k){var j=this;return h.dom.Sizzle(l,j.get(k)||j.get(j.settings.root_element)||j.doc,[])},is:function(l,j){var k;if(l.length===undefined){if(j==="*"){return l.nodeType==1}if(a.test(j)){j=j.toLowerCase().split(/,/);l=l.nodeName.toLowerCase();for(k=j.length-1;k>=0;k--){if(j[k]==l){return true}}return false}}return h.dom.Sizzle.matches(j,l.nodeType?[l]:l).length>0},add:function(m,q,j,l,o){var k=this;return this.run(m,function(s){var r,n;r=e(q,"string")?k.doc.createElement(q):q;k.setAttribs(r,j);if(l){if(l.nodeType){r.appendChild(l)}else{k.setHTML(r,l)}}return !o?s.appendChild(r):r})},create:function(l,j,k){return this.add(this.doc.createElement(l),l,j,k,1)},createHTML:function(r,j,p){var q="",m=this,l;q+="<"+r;for(l in j){if(j.hasOwnProperty(l)){q+=" "+l+'="'+m.encode(j[l])+'"'}}if(typeof(p)!="undefined"){return q+">"+p+"</"+r+">"}return q+" />"},remove:function(j,k){return this.run(j,function(m){var n,l=m.parentNode;if(!l){return null}if(k){while(n=m.firstChild){if(!h.isIE||n.nodeType!==3||n.nodeValue){l.insertBefore(n,m)}else{m.removeChild(n)}}}return l.removeChild(m)})},setStyle:function(m,j,k){var l=this;return l.run(m,function(p){var o,n;o=p.style;j=j.replace(/-(\D)/g,function(r,q){return q.toUpperCase()});if(l.pixelStyles.test(j)&&(h.is(k,"number")||/^[\-0-9\.]+$/.test(k))){k+="px"}switch(j){case"opacity":if(b){o.filter=k===""?"":"alpha(opacity="+(k*100)+")";if(!m.currentStyle||!m.currentStyle.hasLayout){o.display="inline-block"}}o[j]=o["-moz-opacity"]=o["-khtml-opacity"]=k||"";break;case"float":b?o.styleFloat=k:o.cssFloat=k;break;default:o[j]=k||""}if(l.settings.update_styles){l.setAttrib(p,"data-mce-style")}})},getStyle:function(m,j,l){m=this.get(m);if(!m){return}if(this.doc.defaultView&&l){j=j.replace(/[A-Z]/g,function(n){return"-"+n});try{return this.doc.defaultView.getComputedStyle(m,null).getPropertyValue(j)}catch(k){return null}}j=j.replace(/-(\D)/g,function(o,n){return n.toUpperCase()});if(j=="float"){j=b?"styleFloat":"cssFloat"}if(m.currentStyle&&l){return m.currentStyle[j]}return m.style?m.style[j]:undefined},setStyles:function(m,n){var k=this,l=k.settings,j;j=l.update_styles;l.update_styles=0;f(n,function(o,p){k.setStyle(m,p,o)});l.update_styles=j;if(l.update_styles){k.setAttrib(m,l.cssText)}},removeAllAttribs:function(j){return this.run(j,function(m){var l,k=m.attributes;for(l=k.length-1;l>=0;l--){m.removeAttributeNode(k.item(l))}})},setAttrib:function(l,m,j){var k=this;if(!l||!m){return}if(k.settings.strict){m=m.toLowerCase()}return this.run(l,function(o){var n=k.settings;switch(m){case"style":if(!e(j,"string")){f(j,function(p,q){k.setStyle(o,q,p)});return}if(n.keep_values){if(j&&!k._isRes(j)){o.setAttribute("data-mce-style",j,2)}else{o.removeAttribute("data-mce-style",2)}}o.style.cssText=j;break;case"class":o.className=j||"";break;case"src":case"href":if(n.keep_values){if(n.url_converter){j=n.url_converter.call(n.url_converter_scope||k,j,m,o)}k.setAttrib(o,"data-mce-"+m,j,2)}break;case"shape":o.setAttribute("data-mce-style",j);break}if(e(j)&&j!==null&&j.length!==0){o.setAttribute(m,""+j,2)}else{o.removeAttribute(m,2)}})},setAttribs:function(k,l){var j=this;return this.run(k,function(m){f(l,function(o,p){j.setAttrib(m,p,o)})})},getAttrib:function(o,p,l){var j,k=this,m;o=k.get(o);if(!o||o.nodeType!==1){return l===m?false:l}if(!e(l)){l=""}if(/^(src|href|style|coords|shape)$/.test(p)){j=o.getAttribute("data-mce-"+p);if(j){return j}}if(b&&k.props[p]){j=o[k.props[p]];j=j&&j.nodeValue?j.nodeValue:j}if(!j){j=o.getAttribute(p,2)}if(/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(p)){if(o[k.props[p]]===true&&j===""){return p}return j?p:""}if(o.nodeName==="FORM"&&o.getAttributeNode(p)){return o.getAttributeNode(p).nodeValue}if(p==="style"){j=j||o.style.cssText;if(j){j=k.serializeStyle(k.parseStyle(j),o.nodeName);if(k.settings.keep_values&&!k._isRes(j)){o.setAttribute("data-mce-style",j)}}}if(d&&p==="class"&&j){j=j.replace(/(apple|webkit)\-[a-z\-]+/gi,"")}if(b){switch(p){case"rowspan":case"colspan":if(j===1){j=""}break;case"size":if(j==="+0"||j===20||j===0){j=""}break;case"width":case"height":case"vspace":case"checked":case"disabled":case"readonly":if(j===0){j=""}break;case"hspace":if(j===-1){j=""}break;case"maxlength":case"tabindex":if(j===32768||j===2147483647||j==="32768"){j=""}break;case"multiple":case"compact":case"noshade":case"nowrap":if(j===65535){return p}return l;case"shape":j=j.toLowerCase();break;default:if(p.indexOf("on")===0&&j){j=h._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/,"$1",""+j)}}}return(j!==m&&j!==null&&j!=="")?""+j:l},getPos:function(s,m){var k=this,j=0,q=0,o,p=k.doc,l;s=k.get(s);m=m||p.body;if(s){if(s.getBoundingClientRect){s=s.getBoundingClientRect();o=k.boxModel?p.documentElement:p.body;j=s.left+(p.documentElement.scrollLeft||p.body.scrollLeft)-o.clientTop;q=s.top+(p.documentElement.scrollTop||p.body.scrollTop)-o.clientLeft;return{x:j,y:q}}l=s;while(l&&l!=m&&l.nodeType){j+=l.offsetLeft||0;q+=l.offsetTop||0;l=l.offsetParent}l=s.parentNode;while(l&&l!=m&&l.nodeType){j-=l.scrollLeft||0;q-=l.scrollTop||0;l=l.parentNode}}return{x:j,y:q}},parseStyle:function(j){return this.styles.parse(j)},serializeStyle:function(k,j){return this.styles.serialize(k,j)},loadCSS:function(j){var l=this,m=l.doc,k;if(!j){j=""}k=l.select("head")[0];f(j.split(","),function(n){var o;if(l.files[n]){return}l.files[n]=true;o=l.create("link",{rel:"stylesheet",href:h._addVer(n)});if(b&&m.documentMode&&m.recalc){o.onload=function(){if(m.recalc){m.recalc()}o.onload=null}}k.appendChild(o)})},addClass:function(j,k){return this.run(j,function(l){var m;if(!k){return 0}if(this.hasClass(l,k)){return l.className}m=this.removeClass(l,k);return l.className=(m!=""?(m+" "):"")+k})},removeClass:function(l,m){var j=this,k;return j.run(l,function(o){var n;if(j.hasClass(o,m)){if(!k){k=new RegExp("(^|\\s+)"+m+"(\\s+|$)","g")}n=o.className.replace(k," ");n=h.trim(n!=" "?n:"");o.className=n;if(!n){o.removeAttribute("class");o.removeAttribute("className")}return n}return o.className})},hasClass:function(k,j){k=this.get(k);if(!k||!j){return false}return(" "+k.className+" ").indexOf(" "+j+" ")!==-1},show:function(j){return this.setStyle(j,"display","block")},hide:function(j){return this.setStyle(j,"display","none")},isHidden:function(j){j=this.get(j);return !j||j.style.display=="none"||this.getStyle(j,"display")=="none"},uniqueId:function(j){return(!j?"mce_":j)+(this.counter++)},setHTML:function(l,k){var j=this;return j.run(l,function(n){if(b){while(n.firstChild){n.removeChild(n.firstChild)}try{n.innerHTML="<br />"+k;n.removeChild(n.firstChild)}catch(m){n=j.create("div");n.innerHTML="<br />"+k;f(n.childNodes,function(p,o){if(o){n.appendChild(p)}})}}else{n.innerHTML=k}return k})},getOuterHTML:function(l){var k,j=this;l=j.get(l);if(!l){return null}if(l.nodeType===1&&j.hasOuterHTML){return l.outerHTML}k=(l.ownerDocument||j.doc).createElement("body");k.appendChild(l.cloneNode(true));return k.innerHTML},setOuterHTML:function(m,k,n){var j=this;function l(p,o,r){var s,q;q=r.createElement("body");q.innerHTML=o;s=q.lastChild;while(s){j.insertAfter(s.cloneNode(true),p);s=s.previousSibling}j.remove(p)}return this.run(m,function(p){p=j.get(p);if(p.nodeType==1){n=n||p.ownerDocument||j.doc;if(b){try{if(b&&p.nodeType==1){p.outerHTML=k}else{l(p,k,n)}}catch(o){l(p,k,n)}}else{l(p,k,n)}}})},decode:c.decode,encode:c.encodeAllRaw,insertAfter:function(j,k){k=this.get(k);return this.run(j,function(m){var l,n;l=k.parentNode;n=k.nextSibling;if(n){l.insertBefore(m,n)}else{l.appendChild(m)}return m})},isBlock:function(k){var j=k.nodeType;if(j){return !!(j===1&&g[k.nodeName])}return !!g[k]},replace:function(p,m,j){var l=this;if(e(m,"array")){p=p.cloneNode(true)}return l.run(m,function(k){if(j){f(h.grep(k.childNodes),function(n){p.appendChild(n)})}return k.parentNode.replaceChild(p,k)})},rename:function(m,j){var l=this,k;if(m.nodeName!=j.toUpperCase()){k=l.create(j);f(l.getAttribs(m),function(n){l.setAttrib(k,n.nodeName,l.getAttrib(m,n.nodeName))});l.replace(k,m,1)}return k||m},findCommonAncestor:function(l,j){var m=l,k;while(m){k=j;while(k&&m!=k){k=k.parentNode}if(m==k){break}m=m.parentNode}if(!m&&l.ownerDocument){return l.ownerDocument.documentElement}return m},toHex:function(j){var l=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(j);function k(m){m=parseInt(m).toString(16);return m.length>1?m:"0"+m}if(l){j="#"+k(l[1])+k(l[2])+k(l[3]);return j}return j},getClasses:function(){var n=this,j=[],m,o={},p=n.settings.class_filter,l;if(n.classes){return n.classes}function q(r){f(r.imports,function(s){q(s)});f(r.cssRules||r.rules,function(s){switch(s.type||1){case 1:if(s.selectorText){f(s.selectorText.split(","),function(t){t=t.replace(/^\s*|\s*$|^\s\./g,"");if(/\.mce/.test(t)||!/\.[\w\-]+$/.test(t)){return}l=t;t=h._replace(/.*\.([a-z0-9_\-]+).*/i,"$1",t);if(p&&!(t=p(t,l))){return}if(!o[t]){j.push({"class":t});o[t]=1}})}break;case 3:q(s.styleSheet);break}})}try{f(n.doc.styleSheets,q)}catch(k){}if(j.length>0){n.classes=j}return j},run:function(m,l,k){var j=this,n;if(j.doc&&typeof(m)==="string"){m=j.get(m)}if(!m){return false}k=k||this;if(!m.nodeType&&(m.length||m.length===0)){n=[];f(m,function(p,o){if(p){if(typeof(p)=="string"){p=j.doc.getElementById(p)}n.push(l.call(k,p,o))}});return n}return l.call(k,m)},getAttribs:function(k){var j;k=this.get(k);if(!k){return[]}if(b){j=[];if(k.nodeName=="OBJECT"){return k.attributes}if(k.nodeName==="OPTION"&&this.getAttrib(k,"selected")){j.push({specified:1,nodeName:"selected"})}k.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi,"").replace(/[\w:\-]+/gi,function(l){j.push({specified:1,nodeName:l})});return j}return k.attributes},isEmpty:function(m,k){var r=this,o,n,q,j,l,p;m=m.firstChild;if(m){j=new h.dom.TreeWalker(m);k=k||r.schema?r.schema.getNonEmptyElements():null;do{q=m.nodeType;if(q===1){if(m.getAttribute("data-mce-bogus")){continue}l=m.nodeName.toLowerCase();if(k&&k[l]){p=m.parentNode;if(l==="br"&&r.isBlock(p)&&p.firstChild===m&&p.lastChild===m){continue}return false}n=r.getAttribs(m);o=m.attributes.length;while(o--){l=m.attributes[o].nodeName;if(l==="name"||l==="data-mce-bookmark"){return false}}}if((q===3&&!i.test(m.nodeValue))){return false}}while(m=j.next())}return true},destroy:function(k){var j=this;if(j.events){j.events.destroy()}j.win=j.doc=j.root=j.events=null;if(!k){h.removeUnload(j.destroy)}},createRng:function(){var j=this.doc;return j.createRange?j.createRange():new h.dom.Range(this)},nodeIndex:function(n,o){var j=0,l,m,k;if(n){for(l=n.nodeType,n=n.previousSibling,m=n;n;n=n.previousSibling){k=n.nodeType;if(o&&k==3){if(k==l||!n.nodeValue.length){continue}}j++;l=k}}return j},split:function(n,m,q){var s=this,j=s.createRng(),o,l,p;function k(v){var t,r=v.childNodes,u=v.nodeType;if(u==1&&v.getAttribute("data-mce-type")=="bookmark"){return}for(t=r.length-1;t>=0;t--){k(r[t])}if(u!=9){if(u==3&&v.nodeValue.length>0){if(!s.isBlock(v.parentNode)||h.trim(v.nodeValue).length>0){return}}else{if(u==1){r=v.childNodes;if(r.length==1&&r[0]&&r[0].nodeType==1&&r[0].getAttribute("data-mce-type")=="bookmark"){v.parentNode.insertBefore(r[0],v)}if(r.length||/^(br|hr|input|img)$/i.test(v.nodeName)){return}}}s.remove(v)}return v}if(n&&m){j.setStart(n.parentNode,s.nodeIndex(n));j.setEnd(m.parentNode,s.nodeIndex(m));o=j.extractContents();j=s.createRng();j.setStart(m.parentNode,s.nodeIndex(m)+1);j.setEnd(n.parentNode,s.nodeIndex(n)+1);l=j.extractContents();p=n.parentNode;p.insertBefore(k(o),n);if(q){p.replaceChild(q,m)}else{p.insertBefore(m,n)}p.insertBefore(k(l),n);s.remove(n);return q||m}},bind:function(n,j,m,l){var k=this;if(!k.events){k.events=new h.dom.EventUtils()}return k.events.add(n,j,m,l||this)},unbind:function(m,j,l){var k=this;if(!k.events){k.events=new h.dom.EventUtils()}return k.events.remove(m,j,l)},_findSib:function(m,j,k){var l=this,n=j;if(m){if(e(n,"string")){n=function(o){return l.is(o,j)}}for(m=m[k];m;m=m[k]){if(n(m)){return m}}}return null},_isRes:function(j){return/^(top|left|bottom|right|width|height)/i.test(j)||/;\s*(top|left|bottom|right|width|height)/i.test(j)}});h.DOM=new h.dom.DOMUtils(document,{process_html:0})})(tinymce);(function(a){function b(c){var N=this,e=c.doc,S=0,E=1,j=2,D=true,R=false,U="startOffset",h="startContainer",P="endContainer",z="endOffset",k=tinymce.extend,n=c.nodeIndex;k(N,{startContainer:e,startOffset:0,endContainer:e,endOffset:0,collapsed:D,commonAncestorContainer:e,START_TO_START:0,START_TO_END:1,END_TO_END:2,END_TO_START:3,setStart:q,setEnd:s,setStartBefore:g,setStartAfter:I,setEndBefore:J,setEndAfter:u,collapse:A,selectNode:x,selectNodeContents:F,compareBoundaryPoints:v,deleteContents:p,extractContents:H,cloneContents:d,insertNode:C,surroundContents:M,cloneRange:K});function q(V,t){B(D,V,t)}function s(V,t){B(R,V,t)}function g(t){q(t.parentNode,n(t))}function I(t){q(t.parentNode,n(t)+1)}function J(t){s(t.parentNode,n(t))}function u(t){s(t.parentNode,n(t)+1)}function A(t){if(t){N[P]=N[h];N[z]=N[U]}else{N[h]=N[P];N[U]=N[z]}N.collapsed=D}function x(t){g(t);u(t)}function F(t){q(t,0);s(t,t.nodeType===1?t.childNodes.length:t.nodeValue.length)}function v(Y,t){var ab=N[h],W=N[U],aa=N[P],V=N[z],Z=t.startContainer,ad=t.startOffset,X=t.endContainer,ac=t.endOffset;if(Y===0){return G(ab,W,Z,ad)}if(Y===1){return G(aa,V,Z,ad)}if(Y===2){return G(aa,V,X,ac)}if(Y===3){return G(ab,W,X,ac)}}function p(){m(j)}function H(){return m(S)}function d(){return m(E)}function C(Y){var V=this[h],t=this[U],X,W;if((V.nodeType===3||V.nodeType===4)&&V.nodeValue){if(!t){V.parentNode.insertBefore(Y,V)}else{if(t>=V.nodeValue.length){c.insertAfter(Y,V)}else{X=V.splitText(t);V.parentNode.insertBefore(Y,X)}}}else{if(V.childNodes.length>0){W=V.childNodes[t]}if(W){V.insertBefore(Y,W)}else{V.appendChild(Y)}}}function M(V){var t=N.extractContents();N.insertNode(V);V.appendChild(t);N.selectNode(V)}function K(){return k(new b(c),{startContainer:N[h],startOffset:N[U],endContainer:N[P],endOffset:N[z],collapsed:N.collapsed,commonAncestorContainer:N.commonAncestorContainer})}function O(t,V){var W;if(t.nodeType==3){return t}if(V<0){return t}W=t.firstChild;while(W&&V>0){--V;W=W.nextSibling}if(W){return W}return t}function l(){return(N[h]==N[P]&&N[U]==N[z])}function G(X,Z,V,Y){var aa,W,t,ab,ad,ac;if(X==V){if(Z==Y){return 0}if(Z<Y){return -1}return 1}aa=V;while(aa&&aa.parentNode!=X){aa=aa.parentNode}if(aa){W=0;t=X.firstChild;while(t!=aa&&W<Z){W++;t=t.nextSibling}if(Z<=W){return -1}return 1}aa=X;while(aa&&aa.parentNode!=V){aa=aa.parentNode}if(aa){W=0;t=V.firstChild;while(t!=aa&&W<Y){W++;t=t.nextSibling}if(W<Y){return -1}return 1}ab=c.findCommonAncestor(X,V);ad=X;while(ad&&ad.parentNode!=ab){ad=ad.parentNode}if(!ad){ad=ab}ac=V;while(ac&&ac.parentNode!=ab){ac=ac.parentNode}if(!ac){ac=ab}if(ad==ac){return 0}t=ab.firstChild;while(t){if(t==ad){return -1}if(t==ac){return 1}t=t.nextSibling}}function B(V,Y,X){var t,W;if(V){N[h]=Y;N[U]=X}else{N[P]=Y;N[z]=X}t=N[P];while(t.parentNode){t=t.parentNode}W=N[h];while(W.parentNode){W=W.parentNode}if(W==t){if(G(N[h],N[U],N[P],N[z])>0){N.collapse(V)}}else{N.collapse(V)}N.collapsed=l();N.commonAncestorContainer=c.findCommonAncestor(N[h],N[P])}function m(ab){var aa,X=0,ad=0,V,Z,W,Y,t,ac;if(N[h]==N[P]){return f(ab)}for(aa=N[P],V=aa.parentNode;V;aa=V,V=V.parentNode){if(V==N[h]){return r(aa,ab)}++X}for(aa=N[h],V=aa.parentNode;V;aa=V,V=V.parentNode){if(V==N[P]){return T(aa,ab)}++ad}Z=ad-X;W=N[h];while(Z>0){W=W.parentNode;Z--}Y=N[P];while(Z<0){Y=Y.parentNode;Z++}for(t=W.parentNode,ac=Y.parentNode;t!=ac;t=t.parentNode,ac=ac.parentNode){W=t;Y=ac}return o(W,Y,ab)}function f(Z){var ab,Y,X,aa,t,W,V;if(Z!=j){ab=e.createDocumentFragment()}if(N[U]==N[z]){return ab}if(N[h].nodeType==3){Y=N[h].nodeValue;X=Y.substring(N[U],N[z]);if(Z!=E){N[h].deleteData(N[U],N[z]-N[U]);N.collapse(D)}if(Z==j){return}ab.appendChild(e.createTextNode(X));return ab}aa=O(N[h],N[U]);t=N[z]-N[U];while(t>0){W=aa.nextSibling;V=y(aa,Z);if(ab){ab.appendChild(V)}--t;aa=W}if(Z!=E){N.collapse(D)}return ab}function r(ab,Y){var aa,Z,V,t,X,W;if(Y!=j){aa=e.createDocumentFragment()}Z=i(ab,Y);if(aa){aa.appendChild(Z)}V=n(ab);t=V-N[U];if(t<=0){if(Y!=E){N.setEndBefore(ab);N.collapse(R)}return aa}Z=ab.previousSibling;while(t>0){X=Z.previousSibling;W=y(Z,Y);if(aa){aa.insertBefore(W,aa.firstChild)}--t;Z=X}if(Y!=E){N.setEndBefore(ab);N.collapse(R)}return aa}function T(Z,Y){var ab,V,aa,t,X,W;if(Y!=j){ab=e.createDocumentFragment()}aa=Q(Z,Y);if(ab){ab.appendChild(aa)}V=n(Z);++V;t=N[z]-V;aa=Z.nextSibling;while(t>0){X=aa.nextSibling;W=y(aa,Y);if(ab){ab.appendChild(W)}--t;aa=X}if(Y!=E){N.setStartAfter(Z);N.collapse(D)}return ab}function o(Z,t,ac){var W,ae,Y,aa,ab,V,ad,X;if(ac!=j){ae=e.createDocumentFragment()}W=Q(Z,ac);if(ae){ae.appendChild(W)}Y=Z.parentNode;aa=n(Z);ab=n(t);++aa;V=ab-aa;ad=Z.nextSibling;while(V>0){X=ad.nextSibling;W=y(ad,ac);if(ae){ae.appendChild(W)}ad=X;--V}W=i(t,ac);if(ae){ae.appendChild(W)}if(ac!=E){N.setStartAfter(Z);N.collapse(D)}return ae}function i(aa,ab){var W=O(N[P],N[z]-1),ac,Z,Y,t,V,X=W!=N[P];if(W==aa){return L(W,X,R,ab)}ac=W.parentNode;Z=L(ac,R,R,ab);while(ac){while(W){Y=W.previousSibling;t=L(W,X,R,ab);if(ab!=j){Z.insertBefore(t,Z.firstChild)}X=D;W=Y}if(ac==aa){return Z}W=ac.previousSibling;ac=ac.parentNode;V=L(ac,R,R,ab);if(ab!=j){V.appendChild(Z)}Z=V}}function Q(aa,ab){var X=O(N[h],N[U]),Y=X!=N[h],ac,Z,W,t,V;if(X==aa){return L(X,Y,D,ab)}ac=X.parentNode;Z=L(ac,R,D,ab);while(ac){while(X){W=X.nextSibling;t=L(X,Y,D,ab);if(ab!=j){Z.appendChild(t)}Y=D;X=W}if(ac==aa){return Z}X=ac.nextSibling;ac=ac.parentNode;V=L(ac,R,D,ab);if(ab!=j){V.appendChild(Z)}Z=V}}function L(t,Y,ab,ac){var X,W,Z,V,aa;if(Y){return y(t,ac)}if(t.nodeType==3){X=t.nodeValue;if(ab){V=N[U];W=X.substring(V);Z=X.substring(0,V)}else{V=N[z];W=X.substring(0,V);Z=X.substring(V)}if(ac!=E){t.nodeValue=Z}if(ac==j){return}aa=t.cloneNode(R);aa.nodeValue=W;return aa}if(ac==j){return}return t.cloneNode(R)}function y(V,t){if(t!=j){return t==E?V.cloneNode(D):V}V.parentNode.removeChild(V)}}a.Range=b})(tinymce.dom);(function(){function a(d){var b=this,h=d.dom,c=true,f=false;function e(i,j){var k,t=0,q,n,m,l,o,r,p=-1,s;k=i.duplicate();k.collapse(j);s=k.parentElement();if(s.ownerDocument!==d.dom.doc){return}while(s.contentEditable==="false"){s=s.parentNode}if(!s.hasChildNodes()){return{node:s,inside:1}}m=s.children;q=m.length-1;while(t<=q){r=Math.floor((t+q)/2);l=m[r];k.moveToElementText(l);p=k.compareEndPoints(j?"StartToStart":"EndToEnd",i);if(p>0){q=r-1}else{if(p<0){t=r+1}else{return{node:l}}}}if(p<0){if(!l){k.moveToElementText(s);k.collapse(true);l=s;n=true}else{k.collapse(false)}k.setEndPoint(j?"EndToStart":"EndToEnd",i);if(k.compareEndPoints(j?"StartToStart":"StartToEnd",i)>0){k=i.duplicate();k.collapse(j);o=-1;while(s==k.parentElement()){if(k.move("character",-1)==0){break}o++}}o=o||k.text.replace("\r\n"," ").length}else{k.collapse(true);k.setEndPoint(j?"StartToStart":"StartToEnd",i);o=k.text.replace("\r\n"," ").length}return{node:l,position:p,offset:o,inside:n}}function g(){var i=d.getRng(),r=h.createRng(),l,k,p,q,m,j;l=i.item?i.item(0):i.parentElement();if(l.ownerDocument!=h.doc){return r}k=d.isCollapsed();if(i.item){r.setStart(l.parentNode,h.nodeIndex(l));r.setEnd(r.startContainer,r.startOffset+1);return r}function o(A){var u=e(i,A),s,y,z=0,x,v,t;s=u.node;y=u.offset;if(u.inside&&!s.hasChildNodes()){r[A?"setStart":"setEnd"](s,0);return}if(y===v){r[A?"setStartBefore":"setEndAfter"](s);return}if(u.position<0){x=u.inside?s.firstChild:s.nextSibling;if(!x){r[A?"setStartAfter":"setEndAfter"](s);return}if(!y){if(x.nodeType==3){r[A?"setStart":"setEnd"](x,0)}else{r[A?"setStartBefore":"setEndBefore"](x)}return}while(x){t=x.nodeValue;z+=t.length;if(z>=y){s=x;z-=y;z=t.length-z;break}x=x.nextSibling}}else{x=s.previousSibling;if(!x){return r[A?"setStartBefore":"setEndBefore"](s)}if(!y){if(s.nodeType==3){r[A?"setStart":"setEnd"](x,s.nodeValue.length)}else{r[A?"setStartAfter":"setEndAfter"](x)}return}while(x){z+=x.nodeValue.length;if(z>=y){s=x;z-=y;break}x=x.previousSibling}}r[A?"setStart":"setEnd"](s,z)}try{o(true);if(!k){o()}}catch(n){if(n.number==-2147024809){m=b.getBookmark(2);p=i.duplicate();p.collapse(true);l=p.parentElement();if(!k){p=i.duplicate();p.collapse(false);q=p.parentElement();q.innerHTML=q.innerHTML}l.innerHTML=l.innerHTML;b.moveToBookmark(m);i=d.getRng();o(true);if(!k){o()}}else{throw n}}return r}this.getBookmark=function(m){var j=d.getRng(),o,i,l={};function n(u){var u,t,p,s,r,q=[];t=u.parentNode;p=h.getRoot().parentNode;while(t!=p){s=t.children;r=s.length;while(r--){if(u===s[r]){q.push(r);break}}u=t;t=t.parentNode}return q}function k(q){var p;p=e(j,q);if(p){return{position:p.position,offset:p.offset,indexes:n(p.node),inside:p.inside}}}if(m===2){if(!j.item){l.start=k(true);if(!d.isCollapsed()){l.end=k()}}else{l.start={ctrl:true,indexes:n(j.item(0))}}}return l};this.moveToBookmark=function(k){var j,i=h.doc.body;function m(o){var r,q,n,p;r=h.getRoot();for(q=o.length-1;q>=0;q--){p=r.children;n=o[q];if(n<=p.length-1){r=p[n]}}return r}function l(r){var n=k[r?"start":"end"],q,p,o;if(n){q=n.position>0;p=i.createTextRange();p.moveToElementText(m(n.indexes));offset=n.offset;if(offset!==o){p.collapse(n.inside||q);p.moveStart("character",q?-offset:offset)}else{p.collapse(r)}j.setEndPoint(r?"StartToStart":"EndToStart",p);if(r){j.collapse(true)}}}if(k.start){if(k.start.ctrl){j=i.createControlRange();j.addElement(m(k.start.indexes));j.select()}else{j=i.createTextRange();l(true);l();j.select()}}};this.addRange=function(i){var n,l,k,p,s,q,r=d.dom.doc,m=r.body;function j(z){var u,y,t,x,v;t=h.create("a");u=z?k:s;y=z?p:q;x=n.duplicate();if(u==r||u==r.documentElement){u=m;y=0}if(u.nodeType==3){u.parentNode.insertBefore(t,u);x.moveToElementText(t);x.moveStart("character",y);h.remove(t);n.setEndPoint(z?"StartToStart":"EndToEnd",x)}else{v=u.childNodes;if(v.length){if(y>=v.length){h.insertAfter(t,v[v.length-1])}else{u.insertBefore(t,v[y])}x.moveToElementText(t)}else{t=r.createTextNode("\uFEFF");u.appendChild(t);x.moveToElementText(t.parentNode);x.collapse(c)}n.setEndPoint(z?"StartToStart":"EndToEnd",x);h.remove(t)}}k=i.startContainer;p=i.startOffset;s=i.endContainer;q=i.endOffset;n=m.createTextRange();if(k==s&&k.nodeType==1&&p==q-1){if(p==q-1){try{l=m.createControlRange();l.addElement(k.childNodes[p]);l.select();return}catch(o){}}}j(true);j();n.select()};this.getRangeAt=g}tinymce.dom.TridentSelection=a})();(function(){var p=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,j=0,d=Object.prototype.toString,o=false,i=true;[0,0].sort(function(){i=false;return 0});var b=function(v,e,z,A){z=z||[];e=e||document;var C=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!v||typeof v!=="string"){return z}var x=[],s,E,H,r,u=true,t=b.isXML(e),B=v,D,G,F,y;do{p.exec("");s=p.exec(B);if(s){B=s[3];x.push(s[1]);if(s[2]){r=s[3];break}}}while(s);if(x.length>1&&k.exec(v)){if(x.length===2&&f.relative[x[0]]){E=h(x[0]+x[1],e)}else{E=f.relative[x[0]]?[e]:b(x.shift(),e);while(x.length){v=x.shift();if(f.relative[v]){v+=x.shift()}E=h(v,E)}}}else{if(!A&&x.length>1&&e.nodeType===9&&!t&&f.match.ID.test(x[0])&&!f.match.ID.test(x[x.length-1])){D=b.find(x.shift(),e,t);e=D.expr?b.filter(D.expr,D.set)[0]:D.set[0]}if(e){D=A?{expr:x.pop(),set:a(A)}:b.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&e.parentNode?e.parentNode:e,t);E=D.expr?b.filter(D.expr,D.set):D.set;if(x.length>0){H=a(E)}else{u=false}while(x.length){G=x.pop();F=G;if(!f.relative[G]){G=""}else{F=x.pop()}if(F==null){F=e}f.relative[G](H,F,t)}}else{H=x=[]}}if(!H){H=E}if(!H){b.error(G||v)}if(d.call(H)==="[object Array]"){if(!u){z.push.apply(z,H)}else{if(e&&e.nodeType===1){for(y=0;H[y]!=null;y++){if(H[y]&&(H[y]===true||H[y].nodeType===1&&b.contains(e,H[y]))){z.push(E[y])}}}else{for(y=0;H[y]!=null;y++){if(H[y]&&H[y].nodeType===1){z.push(E[y])}}}}}else{a(H,z)}if(r){b(r,C,z,A);b.uniqueSort(z)}return z};b.uniqueSort=function(r){if(c){o=i;r.sort(c);if(o){for(var e=1;e<r.length;e++){if(r[e]===r[e-1]){r.splice(e--,1)}}}}return r};b.matches=function(e,r){return b(e,null,null,r)};b.find=function(y,e,z){var x;if(!y){return[]}for(var t=0,s=f.order.length;t<s;t++){var v=f.order[t],u;if((u=f.leftMatch[v].exec(y))){var r=u[1];u.splice(1,1);if(r.substr(r.length-1)!=="\\"){u[1]=(u[1]||"").replace(/\\/g,"");x=f.find[v](u,e,z);if(x!=null){y=y.replace(f.match[v],"");break}}}}if(!x){x=e.getElementsByTagName("*")}return{set:x,expr:y}};b.filter=function(C,B,F,u){var s=C,H=[],z=B,x,e,y=B&&B[0]&&b.isXML(B[0]);while(C&&B.length){for(var A in f.filter){if((x=f.leftMatch[A].exec(C))!=null&&x[2]){var r=f.filter[A],G,E,t=x[1];e=false;x.splice(1,1);if(t.substr(t.length-1)==="\\"){continue}if(z===H){H=[]}if(f.preFilter[A]){x=f.preFilter[A](x,z,F,H,u,y);if(!x){e=G=true}else{if(x===true){continue}}}if(x){for(var v=0;(E=z[v])!=null;v++){if(E){G=r(E,x,v,z);var D=u^!!G;if(F&&G!=null){if(D){e=true}else{z[v]=false}}else{if(D){H.push(E);e=true}}}}}if(G!==undefined){if(!F){z=H}C=C.replace(f.match[A],"");if(!e){return[]}break}}}if(C===s){if(e==null){b.error(C)}else{break}}s=C}return z};b.error=function(e){throw"Syntax error, unrecognized expression: "+e};var f=b.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(e){return e.getAttribute("href")}},relative:{"+":function(x,r){var t=typeof r==="string",v=t&&!/\W/.test(r),y=t&&!v;if(v){r=r.toLowerCase()}for(var s=0,e=x.length,u;s<e;s++){if((u=x[s])){while((u=u.previousSibling)&&u.nodeType!==1){}x[s]=y||u&&u.nodeName.toLowerCase()===r?u||false:u===r}}if(y){b.filter(r,x,true)}},">":function(x,r){var u=typeof r==="string",v,s=0,e=x.length;if(u&&!/\W/.test(r)){r=r.toLowerCase();for(;s<e;s++){v=x[s];if(v){var t=v.parentNode;x[s]=t.nodeName.toLowerCase()===r?t:false}}}else{for(;s<e;s++){v=x[s];if(v){x[s]=u?v.parentNode:v.parentNode===r}}if(u){b.filter(r,x,true)}}},"":function(t,r,v){var s=j++,e=q,u;if(typeof r==="string"&&!/\W/.test(r)){r=r.toLowerCase();u=r;e=n}e("parentNode",r,s,t,u,v)},"~":function(t,r,v){var s=j++,e=q,u;if(typeof r==="string"&&!/\W/.test(r)){r=r.toLowerCase();u=r;e=n}e("previousSibling",r,s,t,u,v)}},find:{ID:function(r,s,t){if(typeof s.getElementById!=="undefined"&&!t){var e=s.getElementById(r[1]);return e?[e]:[]}},NAME:function(s,v){if(typeof v.getElementsByName!=="undefined"){var r=[],u=v.getElementsByName(s[1]);for(var t=0,e=u.length;t<e;t++){if(u[t].getAttribute("name")===s[1]){r.push(u[t])}}return r.length===0?null:r}},TAG:function(e,r){return r.getElementsByTagName(e[1])}},preFilter:{CLASS:function(t,r,s,e,x,y){t=" "+t[1].replace(/\\/g,"")+" ";if(y){return t}for(var u=0,v;(v=r[u])!=null;u++){if(v){if(x^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(t)>=0)){if(!s){e.push(v)}}else{if(s){r[u]=false}}}}return false},ID:function(e){return e[1].replace(/\\/g,"")},TAG:function(r,e){return r[1].toLowerCase()},CHILD:function(e){if(e[1]==="nth"){var r=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(r[1]+(r[2]||1))-0;e[3]=r[3]-0}e[0]=j++;return e},ATTR:function(u,r,s,e,v,x){var t=u[1].replace(/\\/g,"");if(!x&&f.attrMap[t]){u[1]=f.attrMap[t]}if(u[2]==="~="){u[4]=" "+u[4]+" "}return u},PSEUDO:function(u,r,s,e,v){if(u[1]==="not"){if((p.exec(u[3])||"").length>1||/^\w/.test(u[3])){u[3]=b(u[3],null,null,r)}else{var t=b.filter(u[3],r,s,true^v);if(!s){e.push.apply(e,t)}return false}}else{if(f.match.POS.test(u[0])||f.match.CHILD.test(u[0])){return true}}return u},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){e.parentNode.selectedIndex;return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(s,r,e){return !!b(e[3],s).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(e){return"text"===e.type},radio:function(e){return"radio"===e.type},checkbox:function(e){return"checkbox"===e.type},file:function(e){return"file"===e.type},password:function(e){return"password"===e.type},submit:function(e){return"submit"===e.type},image:function(e){return"image"===e.type},reset:function(e){return"reset"===e.type},button:function(e){return"button"===e.type||e.nodeName.toLowerCase()==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)}},setFilters:{first:function(r,e){return e===0},last:function(s,r,e,t){return r===t.length-1},even:function(r,e){return e%2===0},odd:function(r,e){return e%2===1},lt:function(s,r,e){return r<e[3]-0},gt:function(s,r,e){return r>e[3]-0},nth:function(s,r,e){return e[3]-0===r},eq:function(s,r,e){return e[3]-0===r}},filter:{PSEUDO:function(s,y,x,z){var e=y[1],r=f.filters[e];if(r){return r(s,x,y,z)}else{if(e==="contains"){return(s.textContent||s.innerText||b.getText([s])||"").indexOf(y[3])>=0}else{if(e==="not"){var t=y[3];for(var v=0,u=t.length;v<u;v++){if(t[v]===s){return false}}return true}else{b.error("Syntax error, unrecognized expression: "+e)}}}},CHILD:function(e,t){var x=t[1],r=e;switch(x){case"only":case"first":while((r=r.previousSibling)){if(r.nodeType===1){return false}}if(x==="first"){return true}r=e;case"last":while((r=r.nextSibling)){if(r.nodeType===1){return false}}return true;case"nth":var s=t[2],A=t[3];if(s===1&&A===0){return true}var v=t[0],z=e.parentNode;if(z&&(z.sizcache!==v||!e.nodeIndex)){var u=0;for(r=z.firstChild;r;r=r.nextSibling){if(r.nodeType===1){r.nodeIndex=++u}}z.sizcache=v}var y=e.nodeIndex-A;if(s===0){return y===0}else{return(y%s===0&&y/s>=0)}}},ID:function(r,e){return r.nodeType===1&&r.getAttribute("id")===e},TAG:function(r,e){return(e==="*"&&r.nodeType===1)||r.nodeName.toLowerCase()===e},CLASS:function(r,e){return(" "+(r.className||r.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(v,t){var s=t[1],e=f.attrHandle[s]?f.attrHandle[s](v):v[s]!=null?v[s]:v.getAttribute(s),x=e+"",u=t[2],r=t[4];return e==null?u==="!=":u==="="?x===r:u==="*="?x.indexOf(r)>=0:u==="~="?(" "+x+" ").indexOf(r)>=0:!r?x&&e!==false:u==="!="?x!==r:u==="^="?x.indexOf(r)===0:u==="$="?x.substr(x.length-r.length)===r:u==="|="?x===r||x.substr(0,r.length+1)===r+"-":false},POS:function(u,r,s,v){var e=r[2],t=f.setFilters[e];if(t){return t(u,s,r,v)}}}};var k=f.match.POS,g=function(r,e){return"\\"+(e-0+1)};for(var m in f.match){f.match[m]=new RegExp(f.match[m].source+(/(?![^\[]*\])(?![^\(]*\))/.source));f.leftMatch[m]=new RegExp(/(^(?:.|\r|\n)*?)/.source+f.match[m].source.replace(/\\(\d+)/g,g))}var a=function(r,e){r=Array.prototype.slice.call(r,0);if(e){e.push.apply(e,r);return e}return r};try{Array.prototype.slice.call(document.documentElement.childNodes,0)[0].nodeType}catch(l){a=function(u,t){var r=t||[],s=0;if(d.call(u)==="[object Array]"){Array.prototype.push.apply(r,u)}else{if(typeof u.length==="number"){for(var e=u.length;s<e;s++){r.push(u[s])}}else{for(;u[s];s++){r.push(u[s])}}}return r}}var c;if(document.documentElement.compareDocumentPosition){c=function(r,e){if(!r.compareDocumentPosition||!e.compareDocumentPosition){if(r==e){o=true}return r.compareDocumentPosition?-1:1}var s=r.compareDocumentPosition(e)&4?-1:r===e?0:1;if(s===0){o=true}return s}}else{if("sourceIndex" in document.documentElement){c=function(r,e){if(!r.sourceIndex||!e.sourceIndex){if(r==e){o=true}return r.sourceIndex?-1:1}var s=r.sourceIndex-e.sourceIndex;if(s===0){o=true}return s}}else{if(document.createRange){c=function(t,r){if(!t.ownerDocument||!r.ownerDocument){if(t==r){o=true}return t.ownerDocument?-1:1}var s=t.ownerDocument.createRange(),e=r.ownerDocument.createRange();s.setStart(t,0);s.setEnd(t,0);e.setStart(r,0);e.setEnd(r,0);var u=s.compareBoundaryPoints(Range.START_TO_END,e);if(u===0){o=true}return u}}}}b.getText=function(e){var r="",t;for(var s=0;e[s];s++){t=e[s];if(t.nodeType===3||t.nodeType===4){r+=t.nodeValue}else{if(t.nodeType!==8){r+=b.getText(t.childNodes)}}}return r};(function(){var r=document.createElement("div"),s="script"+(new Date()).getTime();r.innerHTML="<a name='"+s+"'/>";var e=document.documentElement;e.insertBefore(r,e.firstChild);if(document.getElementById(s)){f.find.ID=function(u,v,x){if(typeof v.getElementById!=="undefined"&&!x){var t=v.getElementById(u[1]);return t?t.id===u[1]||typeof t.getAttributeNode!=="undefined"&&t.getAttributeNode("id").nodeValue===u[1]?[t]:undefined:[]}};f.filter.ID=function(v,t){var u=typeof v.getAttributeNode!=="undefined"&&v.getAttributeNode("id");return v.nodeType===1&&u&&u.nodeValue===t}}e.removeChild(r);e=r=null})();(function(){var e=document.createElement("div");e.appendChild(document.createComment(""));if(e.getElementsByTagName("*").length>0){f.find.TAG=function(r,v){var u=v.getElementsByTagName(r[1]);if(r[1]==="*"){var t=[];for(var s=0;u[s];s++){if(u[s].nodeType===1){t.push(u[s])}}u=t}return u}}e.innerHTML="<a href='#'></a>";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){f.attrHandle.href=function(r){return r.getAttribute("href",2)}}e=null})();if(document.querySelectorAll){(function(){var e=b,s=document.createElement("div");s.innerHTML="<p class='TEST'></p>";if(s.querySelectorAll&&s.querySelectorAll(".TEST").length===0){return}b=function(x,v,t,u){v=v||document;if(!u&&v.nodeType===9&&!b.isXML(v)){try{return a(v.querySelectorAll(x),t)}catch(y){}}return e(x,v,t,u)};for(var r in e){b[r]=e[r]}s=null})()}(function(){var e=document.createElement("div");e.innerHTML="<div class='test e'></div><div class='test'></div>";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}f.order.splice(1,0,"CLASS");f.find.CLASS=function(r,s,t){if(typeof s.getElementsByClassName!=="undefined"&&!t){return s.getElementsByClassName(r[1])}};e=null})();function n(r,x,v,A,y,z){for(var t=0,s=A.length;t<s;t++){var e=A[t];if(e){e=e[r];var u=false;while(e){if(e.sizcache===v){u=A[e.sizset];break}if(e.nodeType===1&&!z){e.sizcache=v;e.sizset=t}if(e.nodeName.toLowerCase()===x){u=e;break}e=e[r]}A[t]=u}}}function q(r,x,v,A,y,z){for(var t=0,s=A.length;t<s;t++){var e=A[t];if(e){e=e[r];var u=false;while(e){if(e.sizcache===v){u=A[e.sizset];break}if(e.nodeType===1){if(!z){e.sizcache=v;e.sizset=t}if(typeof x!=="string"){if(e===x){u=true;break}}else{if(b.filter(x,[e]).length>0){u=e;break}}}e=e[r]}A[t]=u}}}b.contains=document.compareDocumentPosition?function(r,e){return !!(r.compareDocumentPosition(e)&16)}:function(r,e){return r!==e&&(r.contains?r.contains(e):true)};b.isXML=function(e){var r=(e?e.ownerDocument||e:0).documentElement;return r?r.nodeName!=="HTML":false};var h=function(e,y){var t=[],u="",v,s=y.nodeType?[y]:y;while((v=f.match.PSEUDO.exec(e))){u+=v[0];e=e.replace(f.match.PSEUDO,"")}e=f.relative[e]?e+"*":e;for(var x=0,r=s.length;x<r;x++){b(e,s[x],t)}return b.filter(u,t)};window.tinymce.dom.Sizzle=b})();(function(d){var f=d.each,c=d.DOM,b=d.isIE,e=d.isWebKit,a;d.create("tinymce.dom.EventUtils",{EventUtils:function(){this.inits=[];this.events=[]},add:function(m,p,l,j){var g,h=this,i=h.events,k;if(p instanceof Array){k=[];f(p,function(o){k.push(h.add(m,o,l,j))});return k}if(m&&m.hasOwnProperty&&m instanceof Array){k=[];f(m,function(n){n=c.get(n);k.push(h.add(n,p,l,j))});return k}m=c.get(m);if(!m){return}g=function(n){if(h.disabled){return}n=n||window.event;if(n&&b){if(!n.target){n.target=n.srcElement}d.extend(n,h._stoppers)}if(!j){return l(n)}return l.call(j,n)};if(p=="unload"){d.unloads.unshift({func:g});return g}if(p=="init"){if(h.domLoaded){g()}else{h.inits.push(g)}return g}i.push({obj:m,name:p,func:l,cfunc:g,scope:j});h._add(m,p,g);return l},remove:function(l,m,k){var h=this,g=h.events,i=false,j;if(l&&l.hasOwnProperty&&l instanceof Array){j=[];f(l,function(n){n=c.get(n);j.push(h.remove(n,m,k))});return j}l=c.get(l);f(g,function(o,n){if(o.obj==l&&o.name==m&&(!k||(o.func==k||o.cfunc==k))){g.splice(n,1);h._remove(l,m,o.cfunc);i=true;return false}});return i},clear:function(l){var j=this,g=j.events,h,k;if(l){l=c.get(l);for(h=g.length-1;h>=0;h--){k=g[h];if(k.obj===l){j._remove(k.obj,k.name,k.cfunc);k.obj=k.cfunc=null;g.splice(h,1)}}}},cancel:function(g){if(!g){return false}this.stop(g);return this.prevent(g)},stop:function(g){if(g.stopPropagation){g.stopPropagation()}else{g.cancelBubble=true}return false},prevent:function(g){if(g.preventDefault){g.preventDefault()}else{g.returnValue=false}return false},destroy:function(){var g=this;f(g.events,function(j,h){g._remove(j.obj,j.name,j.cfunc);j.obj=j.cfunc=null});g.events=[];g=null},_add:function(h,i,g){if(h.attachEvent){h.attachEvent("on"+i,g)}else{if(h.addEventListener){h.addEventListener(i,g,false)}else{h["on"+i]=g}}},_remove:function(i,j,h){if(i){try{if(i.detachEvent){i.detachEvent("on"+j,h)}else{if(i.removeEventListener){i.removeEventListener(j,h,false)}else{i["on"+j]=null}}}catch(g){}}},_pageInit:function(h){var g=this;if(g.domLoaded){return}g.domLoaded=true;f(g.inits,function(i){i()});g.inits=[]},_wait:function(i){var g=this,h=i.document;if(i.tinyMCE_GZ&&tinyMCE_GZ.loaded){g.domLoaded=1;return}if(h.attachEvent){h.attachEvent("onreadystatechange",function(){if(h.readyState==="complete"){h.detachEvent("onreadystatechange",arguments.callee);g._pageInit(i)}});if(h.documentElement.doScroll&&i==i.top){(function(){if(g.domLoaded){return}try{h.documentElement.doScroll("left")}catch(j){setTimeout(arguments.callee,0);return}g._pageInit(i)})()}}else{if(h.addEventListener){g._add(i,"DOMContentLoaded",function(){g._pageInit(i)})}}g._add(i,"load",function(){g._pageInit(i)})},_stoppers:{preventDefault:function(){this.returnValue=false},stopPropagation:function(){this.cancelBubble=true}}});a=d.dom.Event=new d.dom.EventUtils();a._wait(window);d.addUnload(function(){a.destroy()})})(tinymce);(function(a){a.dom.Element=function(f,d){var b=this,e,c;b.settings=d=d||{};b.id=f;b.dom=e=d.dom||a.DOM;if(!a.isIE){c=e.get(b.id)}a.each(("getPos,getRect,getParent,add,setStyle,getStyle,setStyles,setAttrib,setAttribs,getAttrib,addClass,removeClass,hasClass,getOuterHTML,setOuterHTML,remove,show,hide,isHidden,setHTML,get").split(/,/),function(g){b[g]=function(){var h=[f],j;for(j=0;j<arguments.length;j++){h.push(arguments[j])}h=e[g].apply(e,h);b.update(g);return h}});a.extend(b,{on:function(i,h,g){return a.dom.Event.add(b.id,i,h,g)},getXY:function(){return{x:parseInt(b.getStyle("left")),y:parseInt(b.getStyle("top"))}},getSize:function(){var g=e.get(b.id);return{w:parseInt(b.getStyle("width")||g.clientWidth),h:parseInt(b.getStyle("height")||g.clientHeight)}},moveTo:function(g,h){b.setStyles({left:g,top:h})},moveBy:function(g,i){var h=b.getXY();b.moveTo(h.x+g,h.y+i)},resizeTo:function(g,i){b.setStyles({width:g,height:i})},resizeBy:function(g,j){var i=b.getSize();b.resizeTo(i.w+g,i.h+j)},update:function(h){var g;if(a.isIE6&&d.blocker){h=h||"";if(h.indexOf("get")===0||h.indexOf("has")===0||h.indexOf("is")===0){return}if(h=="remove"){e.remove(b.blocker);return}if(!b.blocker){b.blocker=e.uniqueId();g=e.add(d.container||e.getRoot(),"iframe",{id:b.blocker,style:"position:absolute;",frameBorder:0,src:'javascript:""'});e.setStyle(g,"opacity",0)}else{g=e.get(b.blocker)}e.setStyles(g,{left:b.getStyle("left",1),top:b.getStyle("top",1),width:b.getStyle("width",1),height:b.getStyle("height",1),display:b.getStyle("display",1),zIndex:parseInt(b.getStyle("zIndex",1)||0)-1})}}})}})(tinymce);(function(c){function e(f){return f.replace(/[\n\r]+/g,"")}var b=c.is,a=c.isIE,d=c.each;c.create("tinymce.dom.Selection",{Selection:function(i,h,g){var f=this;f.dom=i;f.win=h;f.serializer=g;d(["onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent"],function(j){f[j]=new c.util.Dispatcher(f)});if(!f.win.getSelection){f.tridentSel=new c.dom.TridentSelection(f)}if(c.isIE&&i.boxModel){this._fixIESelection()}c.addUnload(f.destroy,f)},setCursorLocation:function(h,i){var f=this;var g=f.dom.createRng();g.setStart(h,i);g.setEnd(h,i);f.setRng(g);f.collapse(false)},getContent:function(g){var f=this,h=f.getRng(),l=f.dom.create("body"),j=f.getSel(),i,k,m;g=g||{};i=k="";g.get=true;g.format=g.format||"html";g.forced_root_block="";f.onBeforeGetContent.dispatch(f,g);if(g.format=="text"){return f.isCollapsed()?"":(h.text||(j.toString?j.toString():""))}if(h.cloneContents){m=h.cloneContents();if(m){l.appendChild(m)}}else{if(b(h.item)||b(h.htmlText)){l.innerHTML="<br>"+(h.item?h.item(0).outerHTML:h.htmlText);l.removeChild(l.firstChild)}else{l.innerHTML=h.toString()}}if(/^\s/.test(l.innerHTML)){i=" "}if(/\s+$/.test(l.innerHTML)){k=" "}g.getInner=true;g.content=f.isCollapsed()?"":i+f.serializer.serialize(l,g)+k;f.onGetContent.dispatch(f,g);return g.content},setContent:function(g,i){var n=this,f=n.getRng(),j,k=n.win.document,m,l;i=i||{format:"html"};i.set=true;g=i.content=g;if(!i.no_events){n.onBeforeSetContent.dispatch(n,i)}g=i.content;if(f.insertNode){g+='<span id="__caret">_</span>';if(f.startContainer==k&&f.endContainer==k){k.body.innerHTML=g}else{f.deleteContents();if(k.body.childNodes.length==0){k.body.innerHTML=g}else{if(f.createContextualFragment){f.insertNode(f.createContextualFragment(g))}else{m=k.createDocumentFragment();l=k.createElement("div");m.appendChild(l);l.outerHTML=g;f.insertNode(m)}}}j=n.dom.get("__caret");f=k.createRange();f.setStartBefore(j);f.setEndBefore(j);n.setRng(f);n.dom.remove("__caret");try{n.setRng(f)}catch(h){}}else{if(f.item){k.execCommand("Delete",false,null);f=n.getRng()}if(/^\s+/.test(g)){f.pasteHTML('<span id="__mce_tmp">_</span>'+g);n.dom.remove("__mce_tmp")}else{f.pasteHTML(g)}}if(!i.no_events){n.onSetContent.dispatch(n,i)}},getStart:function(){var g=this.getRng(),h,f,j,i;if(g.duplicate||g.item){if(g.item){return g.item(0)}j=g.duplicate();j.collapse(1);h=j.parentElement();f=i=g.parentElement();while(i=i.parentNode){if(i==h){h=f;break}}return h}else{h=g.startContainer;if(h.nodeType==1&&h.hasChildNodes()){h=h.childNodes[Math.min(h.childNodes.length-1,g.startOffset)]}if(h&&h.nodeType==3){return h.parentNode}return h}},getEnd:function(){var g=this,h=g.getRng(),i,f;if(h.duplicate||h.item){if(h.item){return h.item(0)}h=h.duplicate();h.collapse(0);i=h.parentElement();if(i&&i.nodeName=="BODY"){return i.lastChild||i}return i}else{i=h.endContainer;f=h.endOffset;if(i.nodeType==1&&i.hasChildNodes()){i=i.childNodes[f>0?f-1:f]}if(i&&i.nodeType==3){return i.parentNode}return i}},getBookmark:function(r,s){var v=this,m=v.dom,g,j,i,n,h,o,p,l="\uFEFF",u;function f(x,y){var t=0;d(m.select(x),function(A,z){if(A==y){t=z}});return t}if(r==2){function k(){var x=v.getRng(true),t=m.getRoot(),y={};function z(C,H){var B=C[H?"startContainer":"endContainer"],G=C[H?"startOffset":"endOffset"],A=[],D,F,E=0;if(B.nodeType==3){if(s){for(D=B.previousSibling;D&&D.nodeType==3;D=D.previousSibling){G+=D.nodeValue.length}}A.push(G)}else{F=B.childNodes;if(G>=F.length&&F.length){E=1;G=Math.max(0,F.length-1)}A.push(v.dom.nodeIndex(F[G],s)+E)}for(;B&&B!=t;B=B.parentNode){A.push(v.dom.nodeIndex(B,s))}return A}y.start=z(x,true);if(!v.isCollapsed()){y.end=z(x)}return y}if(v.tridentSel){return v.tridentSel.getBookmark(r)}return k()}if(r){return{rng:v.getRng()}}g=v.getRng();i=m.uniqueId();n=tinyMCE.activeEditor.selection.isCollapsed();u="overflow:hidden;line-height:0px";if(g.duplicate||g.item){if(!g.item){j=g.duplicate();try{g.collapse();g.pasteHTML('<span data-mce-type="bookmark" id="'+i+'_start" style="'+u+'">'+l+"</span>");if(!n){j.collapse(false);g.moveToElementText(j.parentElement());if(g.compareEndPoints("StartToEnd",j)==0){j.move("character",-1)}j.pasteHTML('<span data-mce-type="bookmark" id="'+i+'_end" style="'+u+'">'+l+"</span>")}}catch(q){return null}}else{o=g.item(0);h=o.nodeName;return{name:h,index:f(h,o)}}}else{o=v.getNode();h=o.nodeName;if(h=="IMG"){return{name:h,index:f(h,o)}}j=g.cloneRange();if(!n){j.collapse(false);j.insertNode(m.create("span",{"data-mce-type":"bookmark",id:i+"_end",style:u},l))}g.collapse(true);g.insertNode(m.create("span",{"data-mce-type":"bookmark",id:i+"_start",style:u},l))}v.moveToBookmark({id:i,keep:1});return{id:i}},moveToBookmark:function(n){var r=this,l=r.dom,i,h,f,q,j,s,o,p;if(n){if(n.start){f=l.createRng();q=l.getRoot();function g(z){var t=n[z?"start":"end"],v,x,y,u;if(t){y=t[0];for(x=q,v=t.length-1;v>=1;v--){u=x.childNodes;if(t[v]>u.length-1){return}x=u[t[v]]}if(x.nodeType===3){y=Math.min(t[0],x.nodeValue.length)}if(x.nodeType===1){y=Math.min(t[0],x.childNodes.length)}if(z){f.setStart(x,y)}else{f.setEnd(x,y)}}return true}if(r.tridentSel){return r.tridentSel.moveToBookmark(n)}if(g(true)&&g()){r.setRng(f)}}else{if(n.id){function k(A){var u=l.get(n.id+"_"+A),z,t,x,y,v=n.keep;if(u){z=u.parentNode;if(A=="start"){if(!v){t=l.nodeIndex(u)}else{z=u.firstChild;t=1}j=s=z;o=p=t}else{if(!v){t=l.nodeIndex(u)}else{z=u.firstChild;t=1}s=z;p=t}if(!v){y=u.previousSibling;x=u.nextSibling;d(c.grep(u.childNodes),function(B){if(B.nodeType==3){B.nodeValue=B.nodeValue.replace(/\uFEFF/g,"")}});while(u=l.get(n.id+"_"+A)){l.remove(u,1)}if(y&&x&&y.nodeType==x.nodeType&&y.nodeType==3&&!c.isOpera){t=y.nodeValue.length;y.appendData(x.nodeValue);l.remove(x);if(A=="start"){j=s=y;o=p=t}else{s=y;p=t}}}}}function m(t){if(l.isBlock(t)&&!t.innerHTML){t.innerHTML=!a?'<br data-mce-bogus="1" />':" "}return t}k("start");k("end");if(j){f=l.createRng();f.setStart(m(j),o);f.setEnd(m(s),p);r.setRng(f)}}else{if(n.name){r.select(l.select(n.name)[n.index])}else{if(n.rng){r.setRng(n.rng)}}}}}},select:function(k,j){var i=this,l=i.dom,g=l.createRng(),f;if(k){f=l.nodeIndex(k);g.setStart(k.parentNode,f);g.setEnd(k.parentNode,f+1);if(j){function h(m,o){var n=new c.dom.TreeWalker(m,m);do{if(m.nodeType==3&&c.trim(m.nodeValue).length!=0){if(o){g.setStart(m,0)}else{g.setEnd(m,m.nodeValue.length)}return}if(m.nodeName=="BR"){if(o){g.setStartBefore(m)}else{g.setEndBefore(m)}return}}while(m=(o?n.next():n.prev()))}h(k,1);h(k)}i.setRng(g)}return k},isCollapsed:function(){var f=this,h=f.getRng(),g=f.getSel();if(!h||h.item){return false}if(h.compareEndPoints){return h.compareEndPoints("StartToEnd",h)===0}return !g||h.collapsed},collapse:function(f){var h=this,g=h.getRng(),i;if(g.item){i=g.item(0);g=h.win.document.body.createTextRange();g.moveToElementText(i)}g.collapse(!!f);h.setRng(g)},getSel:function(){var g=this,f=this.win;return f.getSelection?f.getSelection():f.document.selection},getRng:function(l){var g=this,h,i,k,j=g.win.document;if(l&&g.tridentSel){return g.tridentSel.getRangeAt(0)}try{if(h=g.getSel()){i=h.rangeCount>0?h.getRangeAt(0):(h.createRange?h.createRange():j.createRange())}}catch(f){}if(c.isIE&&i&&i.setStart&&j.selection.createRange().item){k=j.selection.createRange().item(0);i=j.createRange();i.setStartBefore(k);i.setEndAfter(k)}if(!i){i=j.createRange?j.createRange():j.body.createTextRange()}if(g.selectedRange&&g.explicitRange){if(i.compareBoundaryPoints(i.START_TO_START,g.selectedRange)===0&&i.compareBoundaryPoints(i.END_TO_END,g.selectedRange)===0){i=g.explicitRange}else{g.selectedRange=null;g.explicitRange=null}}return i},setRng:function(i){var h,g=this;if(!g.tridentSel){h=g.getSel();if(h){g.explicitRange=i;try{h.removeAllRanges()}catch(f){}h.addRange(i);g.selectedRange=h.getRangeAt(0)}}else{if(i.cloneRange){g.tridentSel.addRange(i);return}try{i.select()}catch(f){}}},setNode:function(g){var f=this;f.setContent(f.dom.getOuterHTML(g));return g},getNode:function(){var h=this,g=h.getRng(),i=h.getSel(),l,k=g.startContainer,f=g.endContainer;if(!g){return h.dom.getRoot()}if(g.setStart){l=g.commonAncestorContainer;if(!g.collapsed){if(g.startContainer==g.endContainer){if(g.endOffset-g.startOffset<2){if(g.startContainer.hasChildNodes()){l=g.startContainer.childNodes[g.startOffset]}}}if(k.nodeType===3&&f.nodeType===3){function j(p,m){var o=p;while(p&&p.nodeType===3&&p.length===0){p=m?p.nextSibling:p.previousSibling}return p||o}if(k.length===g.startOffset){k=j(k.nextSibling,true)}else{k=k.parentNode}if(g.endOffset===0){f=j(f.previousSibling,false)}else{f=f.parentNode}if(k&&k===f){return k}}}if(l&&l.nodeType==3){return l.parentNode}return l}return g.item?g.item(0):g.parentElement()},getSelectedBlocks:function(g,f){var i=this,j=i.dom,m,h,l,k=[];m=j.getParent(g||i.getStart(),j.isBlock);h=j.getParent(f||i.getEnd(),j.isBlock);if(m){k.push(m)}if(m&&h&&m!=h){l=m;while((l=l.nextSibling)&&l!=h){if(j.isBlock(l)){k.push(l)}}}if(h&&m!=h){k.push(h)}return k},normalize:function(){var g=this,f,i;if(c.isIE){return}function h(p){var k,o,n,m=g.dom,j=m.getRoot(),l;k=f[(p?"start":"end")+"Container"];o=f[(p?"start":"end")+"Offset"];if(k.nodeType===9){k=k.body;o=0}if(k===j){if(k.hasChildNodes()){k=k.childNodes[Math.min(!p&&o>0?o-1:o,k.childNodes.length-1)];o=0;if(k.hasChildNodes()){l=k;n=new c.dom.TreeWalker(k,j);do{if(l.nodeType===3){o=p?0:l.nodeValue.length-1;k=l;break}if(l.nodeName==="BR"){o=m.nodeIndex(l);k=l.parentNode;break}}while(l=(p?n.next():n.prev()));i=true}}}if(i){f["set"+(p?"Start":"End")](k,o)}}f=g.getRng();h(true);if(f.collapsed){h()}if(i){g.setRng(f)}},destroy:function(g){var f=this;f.win=null;if(!g){c.removeUnload(f.destroy)}},_fixIESelection:function(){var g=this.dom,m=g.doc,h=m.body,j,n,f;m.documentElement.unselectable=true;function i(o,r){var p=h.createTextRange();try{p.moveToPoint(o,r)}catch(q){p=null}return p}function l(p){var o;if(p.button){o=i(p.x,p.y);if(o){if(o.compareEndPoints("StartToStart",n)>0){o.setEndPoint("StartToStart",n)}else{o.setEndPoint("EndToEnd",n)}o.select()}}else{k()}}function k(){var o=m.selection.createRange();if(n&&!o.item&&o.compareEndPoints("StartToEnd",o)===0){n.select()}g.unbind(m,"mouseup",k);g.unbind(m,"mousemove",l);n=j=0}g.bind(m,["mousedown","contextmenu"],function(o){if(o.target.nodeName==="HTML"){if(j){k()}f=m.documentElement;if(f.scrollHeight>f.clientHeight){return}j=1;n=i(o.x,o.y);if(n){g.bind(m,"mouseup",k);g.bind(m,"mousemove",l);g.win.focus();n.select()}}})}})})(tinymce);(function(a){a.dom.Serializer=function(e,i,f){var h,b,d=a.isIE,g=a.each,c;if(!e.apply_source_formatting){e.indent=false}e.remove_trailing_brs=true;i=i||a.DOM;f=f||new a.html.Schema(e);e.entity_encoding=e.entity_encoding||"named";h=new a.util.Dispatcher(self);b=new a.util.Dispatcher(self);c=new a.html.DomParser(e,f);c.addAttributeFilter("src,href,style",function(k,j){var o=k.length,l,q,n="data-mce-"+j,p=e.url_converter,r=e.url_converter_scope,m;while(o--){l=k[o];q=l.attributes.map[n];if(q!==m){l.attr(j,q.length>0?q:null);l.attr(n,null)}else{q=l.attributes.map[j];if(j==="style"){q=i.serializeStyle(i.parseStyle(q),l.name)}else{if(p){q=p.call(r,q,j,l.name)}}l.attr(j,q.length>0?q:null)}}});c.addAttributeFilter("class",function(j,k){var l=j.length,m,n;while(l--){m=j[l];n=m.attr("class").replace(/\s*mce(Item\w+|Selected)\s*/g,"");m.attr("class",n.length>0?n:null)}});c.addAttributeFilter("data-mce-type",function(j,l,k){var m=j.length,n;while(m--){n=j[m];if(n.attributes.map["data-mce-type"]==="bookmark"&&!k.cleanup){n.remove()}}});c.addNodeFilter("script,style",function(k,l){var m=k.length,n,o;function j(p){return p.replace(/(<!--\[CDATA\[|\]\]-->)/g,"\n").replace(/^[\r\n]*|[\r\n]*$/g,"").replace(/^\s*(\/\/\s*<!--|\/\/\s*<!\[CDATA\[|<!--|<!\[CDATA\[)[\r\n]*/g,"").replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->|\]\]-->)\s*$/g,"")}while(m--){n=k[m];o=n.firstChild?n.firstChild.value:"";if(l==="script"){n.attr("type",(n.attr("type")||"text/javascript").replace(/^mce\-/,""));if(o.length>0){n.firstChild.value="// <![CDATA[\n"+j(o)+"\n// ]]>"}}else{if(o.length>0){n.firstChild.value="<!--\n"+j(o)+"\n-->"}}}});c.addNodeFilter("#comment",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.value.indexOf("[CDATA[")===0){m.name="#cdata";m.type=4;m.value=m.value.replace(/^\[CDATA\[|\]\]$/g,"")}else{if(m.value.indexOf("mce:protected ")===0){m.name="#text";m.type=3;m.raw=true;m.value=unescape(m.value).substr(14)}}}});c.addNodeFilter("xml:namespace,input",function(j,k){var l=j.length,m;while(l--){m=j[l];if(m.type===7){m.remove()}else{if(m.type===1){if(k==="input"&&!("type" in m.attributes.map)){m.attr("type","text")}}}}});if(e.fix_list_elements){c.addNodeFilter("ul,ol",function(k,l){var m=k.length,n,j;while(m--){n=k[m];j=n.parent;if(j.name==="ul"||j.name==="ol"){if(n.prev&&n.prev.name==="li"){n.prev.append(n)}}}})}c.addAttributeFilter("data-mce-src,data-mce-href,data-mce-style",function(j,k){var l=j.length;while(l--){j[l].attr(k,null)}});return{schema:f,addNodeFilter:c.addNodeFilter,addAttributeFilter:c.addAttributeFilter,onPreProcess:h,onPostProcess:b,serialize:function(o,m){var l,p,k,j,n;if(d&&i.select("script,style,select,map").length>0){n=o.innerHTML;o=o.cloneNode(false);i.setHTML(o,n)}else{o=o.cloneNode(true)}l=o.ownerDocument.implementation;if(l.createHTMLDocument){p=l.createHTMLDocument("");g(o.nodeName=="BODY"?o.childNodes:[o],function(q){p.body.appendChild(p.importNode(q,true))});if(o.nodeName!="BODY"){o=p.body.firstChild}else{o=p.body}k=i.doc;i.doc=p}m=m||{};m.format=m.format||"html";if(!m.no_events){m.node=o;h.dispatch(self,m)}j=new a.html.Serializer(e,f);m.content=j.serialize(c.parse(m.getInner?o.innerHTML:a.trim(i.getOuterHTML(o),m),m));if(!m.cleanup){m.content=m.content.replace(/\uFEFF/g,"")}if(!m.no_events){b.dispatch(self,m)}if(k){i.doc=k}m.node=null;return m.content},addRules:function(j){f.addValidElements(j)},setRules:function(j){f.setValidElements(j)}}}})(tinymce);(function(a){a.dom.ScriptLoader=function(h){var c=0,k=1,i=2,l={},j=[],f={},d=[],g=0,e;function b(m,v){var x=this,q=a.DOM,s,o,r,n;function p(){q.remove(n);if(s){s.onreadystatechange=s.onload=s=null}v()}function u(){if(typeof(console)!=="undefined"&&console.log){console.log("Failed to load: "+m)}}n=q.uniqueId();if(a.isIE6){o=new a.util.URI(m);r=location;if(o.host==r.hostname&&o.port==r.port&&(o.protocol+":")==r.protocol&&o.protocol.toLowerCase()!="file"){a.util.XHR.send({url:a._addVer(o.getURI()),success:function(y){var t=q.create("script",{type:"text/javascript"});t.text=y;document.getElementsByTagName("head")[0].appendChild(t);q.remove(t);p()},error:u});return}}s=q.create("script",{id:n,type:"text/javascript",src:a._addVer(m)});if(!a.isIE){s.onload=p}s.onerror=u;if(!a.isOpera){s.onreadystatechange=function(){var t=s.readyState;if(t=="complete"||t=="loaded"){p()}}}(document.getElementsByTagName("head")[0]||document.body).appendChild(s)}this.isDone=function(m){return l[m]==i};this.markDone=function(m){l[m]=i};this.add=this.load=function(m,q,n){var o,p=l[m];if(p==e){j.push(m);l[m]=c}if(q){if(!f[m]){f[m]=[]}f[m].push({func:q,scope:n||this})}};this.loadQueue=function(n,m){this.loadScripts(j,n,m)};this.loadScripts=function(m,q,p){var o;function n(r){a.each(f[r],function(s){s.func.call(s.scope)});f[r]=e}d.push({func:q,scope:p||this});o=function(){var r=a.grep(m);m.length=0;a.each(r,function(s){if(l[s]==i){n(s);return}if(l[s]!=k){l[s]=k;g++;b(s,function(){l[s]=i;g--;n(s);o()})}});if(!g){a.each(d,function(s){s.func.call(s.scope)});d.length=0}};o()}};a.ScriptLoader=new a.dom.ScriptLoader()})(tinymce);tinymce.dom.TreeWalker=function(a,c){var b=a;function d(i,f,e,j){var h,g;if(i){if(!j&&i[f]){return i[f]}if(i!=c){h=i[e];if(h){return h}for(g=i.parentNode;g&&g!=c;g=g.parentNode){h=g[e];if(h){return h}}}}}this.current=function(){return b};this.next=function(e){return(b=d(b,"firstChild","nextSibling",e))};this.prev=function(e){return(b=d(b,"lastChild","previousSibling",e))}};(function(a){a.dom.RangeUtils=function(c){var b="\uFEFF";this.walk=function(d,r){var h=d.startContainer,k=d.startOffset,s=d.endContainer,l=d.endOffset,i,f,n,g,q,p,e;e=c.select("td.mceSelected,th.mceSelected");if(e.length>0){a.each(e,function(t){r([t])});return}function o(v,u,t){var x=[];for(;v&&v!=t;v=v[u]){x.push(v)}return x}function m(u,t){do{if(u.parentNode==t){return u}u=u.parentNode}while(u)}function j(v,u,x){var t=x?"nextSibling":"previousSibling";for(g=v,q=g.parentNode;g&&g!=u;g=q){q=g.parentNode;p=o(g==v?g:g[t],t);if(p.length){if(!x){p.reverse()}r(p)}}}if(h.nodeType==1&&h.hasChildNodes()){h=h.childNodes[k]}if(s.nodeType==1&&s.hasChildNodes()){s=s.childNodes[Math.min(l-1,s.childNodes.length-1)]}i=c.findCommonAncestor(h,s);if(h==s){return r([h])}for(g=h;g;g=g.parentNode){if(g==s){return j(h,i,true)}if(g==i){break}}for(g=s;g;g=g.parentNode){if(g==h){return j(s,i)}if(g==i){break}}f=m(h,i)||h;n=m(s,i)||s;j(h,f,true);p=o(f==h?f:f.nextSibling,"nextSibling",n==s?n.nextSibling:n);if(p.length){r(p)}j(s,n)}};a.dom.RangeUtils.compareRanges=function(c,b){if(c&&b){if(c.item||c.duplicate){if(c.item&&b.item&&c.item(0)===b.item(0)){return true}if(c.isEqual&&b.isEqual&&b.isEqual(c)){return true}}else{return c.startContainer==b.startContainer&&c.startOffset==b.startOffset}}return false}})(tinymce);(function(b){var a=b.dom.Event,c=b.each;b.create("tinymce.ui.KeyboardNavigation",{KeyboardNavigation:function(e,f){var p=this,m=e.root,l=e.items,n=e.enableUpDown,i=e.enableLeftRight||!e.enableUpDown,k=e.excludeFromTabOrder,j,h,o,d,g;f=f||b.DOM;j=function(q){g=q.target.id};h=function(q){f.setAttrib(q.target.id,"tabindex","-1")};d=function(q){var r=f.get(g);f.setAttrib(r,"tabindex","0");r.focus()};p.focus=function(){f.get(g).focus()};p.destroy=function(){c(l,function(q){f.unbind(f.get(q.id),"focus",j);f.unbind(f.get(q.id),"blur",h)});f.unbind(f.get(m),"focus",d);f.unbind(f.get(m),"keydown",o);l=f=m=p.focus=j=h=o=d=null;p.destroy=function(){}};p.moveFocus=function(u,r){var q=-1,t=p.controls,s;if(!g){return}c(l,function(x,v){if(x.id===g){q=v;return false}});q+=u;if(q<0){q=l.length-1}else{if(q>=l.length){q=0}}s=l[q];f.setAttrib(g,"tabindex","-1");f.setAttrib(s.id,"tabindex","0");f.get(s.id).focus();if(e.actOnFocus){e.onAction(s.id)}if(r){a.cancel(r)}};o=function(y){var u=37,t=39,x=38,z=40,q=27,s=14,r=13,v=32;switch(y.keyCode){case u:if(i){p.moveFocus(-1)}break;case t:if(i){p.moveFocus(1)}break;case x:if(n){p.moveFocus(-1)}break;case z:if(n){p.moveFocus(1)}break;case q:if(e.onCancel){e.onCancel();a.cancel(y)}break;case s:case r:case v:if(e.onAction){e.onAction(g);a.cancel(y)}break}};c(l,function(s,q){var r;if(!s.id){s.id=f.uniqueId("_mce_item_")}if(k){f.bind(s.id,"blur",h);r="-1"}else{r=(q===0?"0":"-1")}f.setAttrib(s.id,"tabindex",r);f.bind(f.get(s.id),"focus",j)});if(l[0]){g=l[0].id}f.setAttrib(m,"tabindex","-1");f.bind(f.get(m),"focus",d);f.bind(f.get(m),"keydown",o)}})})(tinymce);(function(c){var b=c.DOM,a=c.is;c.create("tinymce.ui.Control",{Control:function(f,e,d){this.id=f;this.settings=e=e||{};this.rendered=false;this.onRender=new c.util.Dispatcher(this);this.classPrefix="";this.scope=e.scope||this;this.disabled=0;this.active=0;this.editor=d},setAriaProperty:function(f,e){var d=b.get(this.id+"_aria")||b.get(this.id);if(d){b.setAttrib(d,"aria-"+f,!!e)}},focus:function(){b.get(this.id).focus()},setDisabled:function(d){if(d!=this.disabled){this.setAriaProperty("disabled",d);this.setState("Disabled",d);this.setState("Enabled",!d);this.disabled=d}},isDisabled:function(){return this.disabled},setActive:function(d){if(d!=this.active){this.setState("Active",d);this.active=d;this.setAriaProperty("pressed",d)}},isActive:function(){return this.active},setState:function(f,d){var e=b.get(this.id);f=this.classPrefix+f;if(d){b.addClass(e,f)}else{b.removeClass(e,f)}},isRendered:function(){return this.rendered},renderHTML:function(){},renderTo:function(d){b.setHTML(d,this.renderHTML())},postRender:function(){var e=this,d;if(a(e.disabled)){d=e.disabled;e.disabled=-1;e.setDisabled(d)}if(a(e.active)){d=e.active;e.active=-1;e.setActive(d)}},remove:function(){b.remove(this.id);this.destroy()},destroy:function(){c.dom.Event.clear(this.id)}})})(tinymce);tinymce.create("tinymce.ui.Container:tinymce.ui.Control",{Container:function(c,b,a){this.parent(c,b,a);this.controls=[];this.lookup={}},add:function(a){this.lookup[a.id]=a;this.controls.push(a);return a},get:function(a){return this.lookup[a]}});tinymce.create("tinymce.ui.Separator:tinymce.ui.Control",{Separator:function(b,a){this.parent(b,a);this.classPrefix="mceSeparator";this.setDisabled(true)},renderHTML:function(){return tinymce.DOM.createHTML("span",{"class":this.classPrefix,role:"separator","aria-orientation":"vertical",tabindex:"-1"})}});(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.MenuItem:tinymce.ui.Control",{MenuItem:function(g,f){this.parent(g,f);this.classPrefix="mceMenuItem"},setSelected:function(f){this.setState("Selected",f);this.setAriaProperty("checked",!!f);this.selected=f},isSelected:function(){return this.selected},postRender:function(){var f=this;f.parent();if(c(f.selected)){f.setSelected(f.selected)}}})})(tinymce);(function(d){var c=d.is,b=d.DOM,e=d.each,a=d.walk;d.create("tinymce.ui.Menu:tinymce.ui.MenuItem",{Menu:function(h,g){var f=this;f.parent(h,g);f.items={};f.collapsed=false;f.menuCount=0;f.onAddItem=new d.util.Dispatcher(this)},expand:function(g){var f=this;if(g){a(f,function(h){if(h.expand){h.expand()}},"items",f)}f.collapsed=false},collapse:function(g){var f=this;if(g){a(f,function(h){if(h.collapse){h.collapse()}},"items",f)}f.collapsed=true},isCollapsed:function(){return this.collapsed},add:function(f){if(!f.settings){f=new d.ui.MenuItem(f.id||b.uniqueId(),f)}this.onAddItem.dispatch(this,f);return this.items[f.id]=f},addSeparator:function(){return this.add({separator:true})},addMenu:function(f){if(!f.collapse){f=this.createMenu(f)}this.menuCount++;return this.add(f)},hasMenus:function(){return this.menuCount!==0},remove:function(f){delete this.items[f.id]},removeAll:function(){var f=this;a(f,function(g){if(g.removeAll){g.removeAll()}else{g.remove()}g.destroy()},"items",f);f.items={}},createMenu:function(g){var f=new d.ui.Menu(g.id||b.uniqueId(),g);f.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return f}})})(tinymce);(function(e){var d=e.is,c=e.DOM,f=e.each,a=e.dom.Event,b=e.dom.Element;e.create("tinymce.ui.DropMenu:tinymce.ui.Menu",{DropMenu:function(h,g){g=g||{};g.container=g.container||c.doc.body;g.offset_x=g.offset_x||0;g.offset_y=g.offset_y||0;g.vp_offset_x=g.vp_offset_x||0;g.vp_offset_y=g.vp_offset_y||0;if(d(g.icons)&&!g.icons){g["class"]+=" mceNoIcons"}this.parent(h,g);this.onShowMenu=new e.util.Dispatcher(this);this.onHideMenu=new e.util.Dispatcher(this);this.classPrefix="mceMenu"},createMenu:function(j){var h=this,i=h.settings,g;j.container=j.container||i.container;j.parent=h;j.constrain=j.constrain||i.constrain;j["class"]=j["class"]||i["class"];j.vp_offset_x=j.vp_offset_x||i.vp_offset_x;j.vp_offset_y=j.vp_offset_y||i.vp_offset_y;j.keyboard_focus=i.keyboard_focus;g=new e.ui.DropMenu(j.id||c.uniqueId(),j);g.onAddItem.add(h.onAddItem.dispatch,h.onAddItem);return g},focus:function(){var g=this;if(g.keyboardNav){g.keyboardNav.focus()}},update:function(){var i=this,j=i.settings,g=c.get("menu_"+i.id+"_tbl"),l=c.get("menu_"+i.id+"_co"),h,k;h=j.max_width?Math.min(g.clientWidth,j.max_width):g.clientWidth;k=j.max_height?Math.min(g.clientHeight,j.max_height):g.clientHeight;if(!c.boxModel){i.element.setStyles({width:h+2,height:k+2})}else{i.element.setStyles({width:h,height:k})}if(j.max_width){c.setStyle(l,"width",h)}if(j.max_height){c.setStyle(l,"height",k);if(g.clientHeight<j.max_height){c.setStyle(l,"overflow","hidden")}}},showMenu:function(p,n,r){var z=this,A=z.settings,o,g=c.getViewPort(),u,l,v,q,i=2,k,j,m=z.classPrefix;z.collapse(1);if(z.isMenuVisible){return}if(!z.rendered){o=c.add(z.settings.container,z.renderNode());f(z.items,function(h){h.postRender()});z.element=new b("menu_"+z.id,{blocker:1,container:A.container})}else{o=c.get("menu_"+z.id)}if(!e.isOpera){c.setStyles(o,{left:-65535,top:-65535})}c.show(o);z.update();p+=A.offset_x||0;n+=A.offset_y||0;g.w-=4;g.h-=4;if(A.constrain){u=o.clientWidth-i;l=o.clientHeight-i;v=g.x+g.w;q=g.y+g.h;if((p+A.vp_offset_x+u)>v){p=r?r-u:Math.max(0,(v-A.vp_offset_x)-u)}if((n+A.vp_offset_y+l)>q){n=Math.max(0,(q-A.vp_offset_y)-l)}}c.setStyles(o,{left:p,top:n});z.element.update();z.isMenuVisible=1;z.mouseClickFunc=a.add(o,"click",function(s){var h;s=s.target;if(s&&(s=c.getParent(s,"tr"))&&!c.hasClass(s,m+"ItemSub")){h=z.items[s.id];if(h.isDisabled()){return}k=z;while(k){if(k.hideMenu){k.hideMenu()}k=k.settings.parent}if(h.settings.onclick){h.settings.onclick(s)}return a.cancel(s)}});if(z.hasMenus()){z.mouseOverFunc=a.add(o,"mouseover",function(x){var h,t,s;x=x.target;if(x&&(x=c.getParent(x,"tr"))){h=z.items[x.id];if(z.lastMenu){z.lastMenu.collapse(1)}if(h.isDisabled()){return}if(x&&c.hasClass(x,m+"ItemSub")){t=c.getRect(x);h.showMenu((t.x+t.w-i),t.y-i,t.x);z.lastMenu=h;c.addClass(c.get(h.id).firstChild,m+"ItemActive")}}})}a.add(o,"keydown",z._keyHandler,z);z.onShowMenu.dispatch(z);if(A.keyboard_focus){z._setupKeyboardNav()}},hideMenu:function(j){var g=this,i=c.get("menu_"+g.id),h;if(!g.isMenuVisible){return}if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(i,"mouseover",g.mouseOverFunc);a.remove(i,"click",g.mouseClickFunc);a.remove(i,"keydown",g._keyHandler);c.hide(i);g.isMenuVisible=0;if(!j){g.collapse(1)}if(g.element){g.element.hide()}if(h=c.get(g.id)){c.removeClass(h.firstChild,g.classPrefix+"ItemActive")}g.onHideMenu.dispatch(g)},add:function(i){var g=this,h;i=g.parent(i);if(g.isRendered&&(h=c.get("menu_"+g.id))){g._add(c.select("tbody",h)[0],i)}return i},collapse:function(g){this.parent(g);this.hideMenu(1)},remove:function(g){c.remove(g.id);this.destroy();return this.parent(g)},destroy:function(){var g=this,h=c.get("menu_"+g.id);if(g.keyboardNav){g.keyboardNav.destroy()}a.remove(h,"mouseover",g.mouseOverFunc);a.remove(c.select("a",h),"focus",g.mouseOverFunc);a.remove(h,"click",g.mouseClickFunc);a.remove(h,"keydown",g._keyHandler);if(g.element){g.element.remove()}c.remove(h)},renderNode:function(){var i=this,j=i.settings,l,h,k,g;g=c.create("div",{role:"listbox",id:"menu_"+i.id,"class":j["class"],style:"position:absolute;left:0;top:0;z-index:200000;outline:0"});if(i.settings.parent){c.setAttrib(g,"aria-parent","menu_"+i.settings.parent.id)}k=c.add(g,"div",{role:"presentation",id:"menu_"+i.id+"_co","class":i.classPrefix+(j["class"]?" "+j["class"]:"")});i.element=new b("menu_"+i.id,{blocker:1,container:j.container});if(j.menu_line){c.add(k,"span",{"class":i.classPrefix+"Line"})}l=c.add(k,"table",{role:"presentation",id:"menu_"+i.id+"_tbl",border:0,cellPadding:0,cellSpacing:0});h=c.add(l,"tbody");f(i.items,function(m){i._add(h,m)});i.rendered=true;return g},_setupKeyboardNav:function(){var i,h,g=this;i=c.select("#menu_"+g.id)[0];h=c.select("a[role=option]","menu_"+g.id);h.splice(0,0,i);g.keyboardNav=new e.ui.KeyboardNavigation({root:"menu_"+g.id,items:h,onCancel:function(){g.hideMenu()},enableUpDown:true});i.focus()},_keyHandler:function(g){var h=this,i;switch(g.keyCode){case 37:if(h.settings.parent){h.hideMenu();h.settings.parent.focus();a.cancel(g)}break;case 39:if(h.mouseOverFunc){h.mouseOverFunc(g)}break}},_add:function(j,h){var i,q=h.settings,p,l,k,m=this.classPrefix,g;if(q.separator){l=c.add(j,"tr",{id:h.id,"class":m+"ItemSeparator"});c.add(l,"td",{"class":m+"ItemSeparator"});if(i=l.previousSibling){c.addClass(i,"mceLast")}return}i=l=c.add(j,"tr",{id:h.id,"class":m+"Item "+m+"ItemEnabled"});i=k=c.add(i,q.titleItem?"th":"td");i=p=c.add(i,"a",{id:h.id+"_aria",role:q.titleItem?"presentation":"option",href:"javascript:;",onclick:"return false;",onmousedown:"return false;"});if(q.parent){c.setAttrib(p,"aria-haspopup","true");c.setAttrib(p,"aria-owns","menu_"+h.id)}c.addClass(k,q["class"]);g=c.add(i,"span",{"class":"mceIcon"+(q.icon?" mce_"+q.icon:"")});if(q.icon_src){c.add(g,"img",{src:q.icon_src})}i=c.add(i,q.element||"span",{"class":"mceText",title:h.settings.title},h.settings.title);if(h.settings.style){c.setAttrib(i,"style",h.settings.style)}if(j.childNodes.length==1){c.addClass(l,"mceFirst")}if((i=l.previousSibling)&&c.hasClass(i,m+"ItemSeparator")){c.addClass(l,"mceFirst")}if(h.collapse){c.addClass(l,m+"ItemSub")}if(i=l.previousSibling){c.removeClass(i,"mceLast")}c.addClass(l,"mceLast")}})})(tinymce);(function(b){var a=b.DOM;b.create("tinymce.ui.Button:tinymce.ui.Control",{Button:function(e,d,c){this.parent(e,d,c);this.classPrefix="mceButton"},renderHTML:function(){var f=this.classPrefix,e=this.settings,d,c;c=a.encode(e.label||"");d='<a role="button" id="'+this.id+'" href="javascript:;" class="'+f+" "+f+"Enabled "+e["class"]+(c?" "+f+"Labeled":"")+'" onmousedown="return false;" onclick="return false;" aria-labelledby="'+this.id+'_voice" title="'+a.encode(e.title)+'">';if(e.image&&!(this.editor&&this.editor.forcedHighContrastMode)){d+='<img class="mceIcon" src="'+e.image+'" alt="'+a.encode(e.title)+'" />'+c}else{d+='<span class="mceIcon '+e["class"]+'"></span>'+(c?'<span class="'+f+'Label">'+c+"</span>":"")}d+='<span class="mceVoiceLabel mceIconOnly" style="display: none;" id="'+this.id+'_voice">'+e.title+"</span>";d+="</a>";return d},postRender:function(){var c=this,d=c.settings;b.dom.Event.add(c.id,"click",function(f){if(!c.isDisabled()){return d.onclick.call(d.scope,f)}})}})})(tinymce);(function(d){var c=d.DOM,b=d.dom.Event,e=d.each,a=d.util.Dispatcher;d.create("tinymce.ui.ListBox:tinymce.ui.Control",{ListBox:function(i,h,f){var g=this;g.parent(i,h,f);g.items=[];g.onChange=new a(g);g.onPostRender=new a(g);g.onAdd=new a(g);g.onRenderMenu=new d.util.Dispatcher(this);g.classPrefix="mceListBox"},select:function(h){var g=this,j,i;if(h==undefined){return g.selectByIndex(-1)}if(h&&h.call){i=h}else{i=function(f){return f==h}}if(h!=g.selectedValue){e(g.items,function(k,f){if(i(k.value)){j=1;g.selectByIndex(f);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(f){var h=this,i,j,g;if(f!=h.selectedIndex){i=c.get(h.id+"_text");g=c.get(h.id+"_voiceDesc");j=h.items[f];if(j){h.selectedValue=j.value;h.selectedIndex=f;c.setHTML(i,c.encode(j.title));c.setHTML(g,h.settings.title+" - "+j.title);c.removeClass(i,"mceTitle");c.setAttrib(h.id,"aria-valuenow",j.title)}else{c.setHTML(i,c.encode(h.settings.title));c.setHTML(g,c.encode(h.settings.title));c.addClass(i,"mceTitle");h.selectedValue=h.selectedIndex=null;c.setAttrib(h.id,"aria-valuenow",h.settings.title)}i=0}},add:function(i,f,h){var g=this;h=h||{};h=d.extend(h,{title:i,value:f});g.items.push(h);g.onAdd.dispatch(g,h)},getLength:function(){return this.items.length},renderHTML:function(){var i="",f=this,g=f.settings,j=f.classPrefix;i='<span role="listbox" aria-haspopup="true" aria-labelledby="'+f.id+'_voiceDesc" aria-describedby="'+f.id+'_voiceDesc"><table role="presentation" tabindex="0" id="'+f.id+'" cellpadding="0" cellspacing="0" class="'+j+" "+j+"Enabled"+(g["class"]?(" "+g["class"]):"")+'"><tbody><tr>';i+="<td>"+c.createHTML("span",{id:f.id+"_voiceDesc","class":"voiceLabel",style:"display:none;"},f.settings.title);i+=c.createHTML("a",{id:f.id+"_text",tabindex:-1,href:"javascript:;","class":"mceText",onclick:"return false;",onmousedown:"return false;"},c.encode(f.settings.title))+"</td>";i+="<td>"+c.createHTML("a",{id:f.id+"_open",tabindex:-1,href:"javascript:;","class":"mceOpen",onclick:"return false;",onmousedown:"return false;"},'<span><span style="display:none;" class="mceIconOnly" aria-hidden="true">\u25BC</span></span>')+"</td>";i+="</tr></tbody></table></span>";return i},showMenu:function(){var g=this,i,h=c.get(this.id),f;if(g.isDisabled()||g.items.length==0){return}if(g.menu&&g.menu.isMenuVisible){return g.hideMenu()}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}i=c.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.keyboard_focus=!d.isOpera;if(g.oldID){f.items[g.oldID].setSelected(0)}e(g.items,function(j){if(j.value===g.selectedValue){f.items[j.id].setSelected(1);g.oldID=j.id}});f.showMenu(0,h.clientHeight);b.add(c.doc,"mousedown",g.hideMenu,g);c.addClass(g.id,g.classPrefix+"Selected")},hideMenu:function(g){var f=this;if(f.menu&&f.menu.isMenuVisible){c.removeClass(f.id,f.classPrefix+"Selected");if(g&&g.type=="mousedown"&&(g.target.id==f.id+"_text"||g.target.id==f.id+"_open")){return}if(!g||!c.getParent(g.target,".mceMenu")){c.removeClass(f.id,f.classPrefix+"Selected");b.remove(c.doc,"mousedown",f.hideMenu,f);f.menu.hideMenu()}}},renderMenu:function(){var g=this,f;f=g.settings.control_manager.createDropMenu(g.id+"_menu",{menu_line:1,"class":g.classPrefix+"Menu mceNoIcons",max_width:150,max_height:150});f.onHideMenu.add(function(){g.hideMenu();g.focus()});f.add({title:g.settings.title,"class":"mceMenuItemTitle",onclick:function(){if(g.settings.onselect("")!==false){g.select("")}}});e(g.items,function(h){if(h.value===undefined){f.add({title:h.title,role:"option","class":"mceMenuItemTitle",onclick:function(){if(g.settings.onselect("")!==false){g.select("")}}})}else{h.id=c.uniqueId();h.role="option";h.onclick=function(){if(g.settings.onselect(h.value)!==false){g.select(h.value)}};f.add(h)}});g.onRenderMenu.dispatch(g,f);g.menu=f},postRender:function(){var f=this,g=f.classPrefix;b.add(f.id,"click",f.showMenu,f);b.add(f.id,"keydown",function(h){if(h.keyCode==32){f.showMenu(h);b.cancel(h)}});b.add(f.id,"focus",function(){if(!f._focused){f.keyDownHandler=b.add(f.id,"keydown",function(h){if(h.keyCode==40){f.showMenu();b.cancel(h)}});f.keyPressHandler=b.add(f.id,"keypress",function(i){var h;if(i.keyCode==13){h=f.selectedValue;f.selectedValue=null;b.cancel(i);f.settings.onselect(h)}})}f._focused=1});b.add(f.id,"blur",function(){b.remove(f.id,"keydown",f.keyDownHandler);b.remove(f.id,"keypress",f.keyPressHandler);f._focused=0});if(d.isIE6||!c.boxModel){b.add(f.id,"mouseover",function(){if(!c.hasClass(f.id,g+"Disabled")){c.addClass(f.id,g+"Hover")}});b.add(f.id,"mouseout",function(){if(!c.hasClass(f.id,g+"Disabled")){c.removeClass(f.id,g+"Hover")}})}f.onPostRender.dispatch(f,c.get(f.id))},destroy:function(){this.parent();b.clear(this.id+"_text");b.clear(this.id+"_open")}})})(tinymce);(function(d){var c=d.DOM,b=d.dom.Event,e=d.each,a=d.util.Dispatcher;d.create("tinymce.ui.NativeListBox:tinymce.ui.ListBox",{NativeListBox:function(g,f){this.parent(g,f);this.classPrefix="mceNativeListBox"},setDisabled:function(f){c.get(this.id).disabled=f;this.setAriaProperty("disabled",f)},isDisabled:function(){return c.get(this.id).disabled},select:function(h){var g=this,j,i;if(h==undefined){return g.selectByIndex(-1)}if(h&&h.call){i=h}else{i=function(f){return f==h}}if(h!=g.selectedValue){e(g.items,function(k,f){if(i(k.value)){j=1;g.selectByIndex(f);return false}});if(!j){g.selectByIndex(-1)}}},selectByIndex:function(f){c.get(this.id).selectedIndex=f+1;this.selectedValue=this.items[f]?this.items[f].value:null},add:function(j,g,f){var i,h=this;f=f||{};f.value=g;if(h.isRendered()){c.add(c.get(this.id),"option",f,j)}i={title:j,value:g,attribs:f};h.items.push(i);h.onAdd.dispatch(h,i)},getLength:function(){return this.items.length},renderHTML:function(){var g,f=this;g=c.createHTML("option",{value:""},"-- "+f.settings.title+" --");e(f.items,function(h){g+=c.createHTML("option",{value:h.value},h.title)});g=c.createHTML("select",{id:f.id,"class":"mceNativeListBox","aria-labelledby":f.id+"_aria"},g);g+=c.createHTML("span",{id:f.id+"_aria",style:"display: none"},f.settings.title);return g},postRender:function(){var g=this,h,i=true;g.rendered=true;function f(k){var j=g.items[k.target.selectedIndex-1];if(j&&(j=j.value)){g.onChange.dispatch(g,j);if(g.settings.onselect){g.settings.onselect(j)}}}b.add(g.id,"change",f);b.add(g.id,"keydown",function(k){var j;b.remove(g.id,"change",h);i=false;j=b.add(g.id,"blur",function(){if(i){return}i=true;b.add(g.id,"change",f);b.remove(g.id,"blur",j)});if(d.isWebKit&&(k.keyCode==37||k.keyCode==39)){return b.prevent(k)}if(k.keyCode==13||k.keyCode==32){f(k);return b.cancel(k)}});g.onPostRender.dispatch(g,c.get(g.id))}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.MenuButton:tinymce.ui.Button",{MenuButton:function(g,f,e){this.parent(g,f,e);this.onRenderMenu=new c.util.Dispatcher(this);f.menu_container=f.menu_container||b.doc.body},showMenu:function(){var g=this,j,i,h=b.get(g.id),f;if(g.isDisabled()){return}if(!g.isMenuRendered){g.renderMenu();g.isMenuRendered=true}if(g.isMenuVisible){return g.hideMenu()}j=b.getPos(g.settings.menu_container);i=b.getPos(h);f=g.menu;f.settings.offset_x=i.x;f.settings.offset_y=i.y;f.settings.vp_offset_x=i.x;f.settings.vp_offset_y=i.y;f.settings.keyboard_focus=g._focused;f.showMenu(0,h.clientHeight);a.add(b.doc,"mousedown",g.hideMenu,g);g.setState("Selected",1);g.isMenuVisible=1},renderMenu:function(){var f=this,e;e=f.settings.control_manager.createDropMenu(f.id+"_menu",{menu_line:1,"class":this.classPrefix+"Menu",icons:f.settings.icons});e.onHideMenu.add(function(){f.hideMenu();f.focus()});f.onRenderMenu.dispatch(f,e);f.menu=e},hideMenu:function(g){var f=this;if(g&&g.type=="mousedown"&&b.getParent(g.target,function(h){return h.id===f.id||h.id===f.id+"_open"})){return}if(!g||!b.getParent(g.target,".mceMenu")){f.setState("Selected",0);a.remove(b.doc,"mousedown",f.hideMenu,f);if(f.menu){f.menu.hideMenu()}}f.isMenuVisible=0},postRender:function(){var e=this,f=e.settings;a.add(e.id,"click",function(){if(!e.isDisabled()){if(f.onclick){f.onclick(e.value)}e.showMenu()}})}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each;c.create("tinymce.ui.SplitButton:tinymce.ui.MenuButton",{SplitButton:function(g,f,e){this.parent(g,f,e);this.classPrefix="mceSplitButton"},renderHTML:function(){var i,f=this,g=f.settings,e;i="<tbody><tr>";if(g.image){e=b.createHTML("img ",{src:g.image,role:"presentation","class":"mceAction "+g["class"]})}else{e=b.createHTML("span",{"class":"mceAction "+g["class"]},"")}e+=b.createHTML("span",{"class":"mceVoiceLabel mceIconOnly",id:f.id+"_voice",style:"display:none;"},g.title);i+="<td >"+b.createHTML("a",{role:"button",id:f.id+"_action",tabindex:"-1",href:"javascript:;","class":"mceAction "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"</td>";e=b.createHTML("span",{"class":"mceOpen "+g["class"]},'<span style="display:none;" class="mceIconOnly" aria-hidden="true">\u25BC</span>');i+="<td >"+b.createHTML("a",{role:"button",id:f.id+"_open",tabindex:"-1",href:"javascript:;","class":"mceOpen "+g["class"],onclick:"return false;",onmousedown:"return false;",title:g.title},e)+"</td>";i+="</tr></tbody>";i=b.createHTML("table",{role:"presentation","class":"mceSplitButton mceSplitButtonEnabled "+g["class"],cellpadding:"0",cellspacing:"0",title:g.title},i);return b.createHTML("div",{id:f.id,role:"button",tabindex:"0","aria-labelledby":f.id+"_voice","aria-haspopup":"true"},i)},postRender:function(){var e=this,g=e.settings,f;if(g.onclick){f=function(h){if(!e.isDisabled()){g.onclick(e.value);a.cancel(h)}};a.add(e.id+"_action","click",f);a.add(e.id,["click","keydown"],function(h){var k=32,m=14,i=13,j=38,l=40;if((h.keyCode===32||h.keyCode===13||h.keyCode===14)&&!h.altKey&&!h.ctrlKey&&!h.metaKey){f();a.cancel(h)}else{if(h.type==="click"||h.keyCode===l){e.showMenu();a.cancel(h)}}})}a.add(e.id+"_open","click",function(h){e.showMenu();a.cancel(h)});a.add([e.id,e.id+"_open"],"focus",function(){e._focused=1});a.add([e.id,e.id+"_open"],"blur",function(){e._focused=0});if(c.isIE6||!b.boxModel){a.add(e.id,"mouseover",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.addClass(e.id,"mceSplitButtonHover")}});a.add(e.id,"mouseout",function(){if(!b.hasClass(e.id,"mceSplitButtonDisabled")){b.removeClass(e.id,"mceSplitButtonHover")}})}},destroy:function(){this.parent();a.clear(this.id+"_action");a.clear(this.id+"_open");a.clear(this.id)}})})(tinymce);(function(d){var c=d.DOM,a=d.dom.Event,b=d.is,e=d.each;d.create("tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton",{ColorSplitButton:function(i,h,f){var g=this;g.parent(i,h,f);g.settings=h=d.extend({colors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",grid_width:8,default_color:"#888888"},g.settings);g.onShowMenu=new d.util.Dispatcher(g);g.onHideMenu=new d.util.Dispatcher(g);g.value=h.default_color},showMenu:function(){var f=this,g,j,i,h;if(f.isDisabled()){return}if(!f.isMenuRendered){f.renderMenu();f.isMenuRendered=true}if(f.isMenuVisible){return f.hideMenu()}i=c.get(f.id);c.show(f.id+"_menu");c.addClass(i,"mceSplitButtonSelected");h=c.getPos(i);c.setStyles(f.id+"_menu",{left:h.x,top:h.y+i.clientHeight,zIndex:200000});i=0;a.add(c.doc,"mousedown",f.hideMenu,f);f.onShowMenu.dispatch(f);if(f._focused){f._keyHandler=a.add(f.id+"_menu","keydown",function(k){if(k.keyCode==27){f.hideMenu()}});c.select("a",f.id+"_menu")[0].focus()}f.isMenuVisible=1},hideMenu:function(g){var f=this;if(f.isMenuVisible){if(g&&g.type=="mousedown"&&c.getParent(g.target,function(h){return h.id===f.id+"_open"})){return}if(!g||!c.getParent(g.target,".mceSplitButtonMenu")){c.removeClass(f.id,"mceSplitButtonSelected");a.remove(c.doc,"mousedown",f.hideMenu,f);a.remove(f.id+"_menu","keydown",f._keyHandler);c.hide(f.id+"_menu")}f.isMenuVisible=0;f.onHideMenu.dispatch()}},renderMenu:function(){var p=this,h,k=0,q=p.settings,g,j,l,o,f;o=c.add(q.menu_container,"div",{role:"listbox",id:p.id+"_menu","class":q.menu_class+" "+q["class"],style:"position:absolute;left:0;top:-1000px;"});h=c.add(o,"div",{"class":q["class"]+" mceSplitButtonMenu"});c.add(h,"span",{"class":"mceMenuLine"});g=c.add(h,"table",{role:"presentation","class":"mceColorSplitMenu"});j=c.add(g,"tbody");k=0;e(b(q.colors,"array")?q.colors:q.colors.split(","),function(i){i=i.replace(/^#/,"");if(!k--){l=c.add(j,"tr");k=q.grid_width-1}g=c.add(l,"td");g=c.add(g,"a",{role:"option",href:"javascript:;",style:{backgroundColor:"#"+i},title:p.editor.getLang("colors."+i,i),"data-mce-color":"#"+i});if(p.editor.forcedHighContrastMode){g=c.add(g,"canvas",{width:16,height:16,"aria-hidden":"true"});if(g.getContext&&(f=g.getContext("2d"))){f.fillStyle="#"+i;f.fillRect(0,0,16,16)}else{c.remove(g)}}});if(q.more_colors_func){g=c.add(j,"tr");g=c.add(g,"td",{colspan:q.grid_width,"class":"mceMoreColors"});g=c.add(g,"a",{role:"option",id:p.id+"_more",href:"javascript:;",onclick:"return false;","class":"mceMoreColors"},q.more_colors_title);a.add(g,"click",function(i){q.more_colors_func.call(q.more_colors_scope||this);return a.cancel(i)})}c.addClass(h,"mceColorSplitMenu");new d.ui.KeyboardNavigation({root:p.id+"_menu",items:c.select("a",p.id+"_menu"),onCancel:function(){p.hideMenu();p.focus()}});a.add(p.id+"_menu","mousedown",function(i){return a.cancel(i)});a.add(p.id+"_menu","click",function(i){var m;i=c.getParent(i.target,"a",j);if(i&&i.nodeName.toLowerCase()=="a"&&(m=i.getAttribute("data-mce-color"))){p.setColor(m)}return a.cancel(i)});return o},setColor:function(f){this.displayColor(f);this.hideMenu();this.settings.onselect(f)},displayColor:function(g){var f=this;c.setStyle(f.id+"_preview","backgroundColor",g);f.value=g},postRender:function(){var f=this,g=f.id;f.parent();c.add(g+"_action","div",{id:g+"_preview","class":"mceColorPreview"});c.setStyle(f.id+"_preview","backgroundColor",f.value)},destroy:function(){this.parent();a.clear(this.id+"_menu");a.clear(this.id+"_more");c.remove(this.id+"_menu")}})})(tinymce);(function(b){var d=b.DOM,c=b.each,a=b.dom.Event;b.create("tinymce.ui.ToolbarGroup:tinymce.ui.Container",{renderHTML:function(){var f=this,i=[],e=f.controls,j=b.each,g=f.settings;i.push('<div id="'+f.id+'" role="group" aria-labelledby="'+f.id+'_voice">');i.push("<span role='application'>");i.push('<span id="'+f.id+'_voice" class="mceVoiceLabel" style="display:none;">'+d.encode(g.name)+"</span>");j(e,function(h){i.push(h.renderHTML())});i.push("</span>");i.push("</div>");return i.join("")},focus:function(){var e=this;d.get(e.id).focus()},postRender:function(){var f=this,e=[];c(f.controls,function(g){c(g.controls,function(h){if(h.id){e.push(h)}})});f.keyNav=new b.ui.KeyboardNavigation({root:f.id,items:e,onCancel:function(){if(b.isWebKit){d.get(f.editor.id+"_ifr").focus()}f.editor.focus()},excludeFromTabOrder:!f.settings.tab_focus_toolbar})},destroy:function(){var e=this;e.parent();e.keyNav.destroy();a.clear(e.id)}})})(tinymce);(function(a){var c=a.DOM,b=a.each;a.create("tinymce.ui.Toolbar:tinymce.ui.Container",{renderHTML:function(){var m=this,f="",j,k,n=m.settings,e,d,g,l;l=m.controls;for(e=0;e<l.length;e++){k=l[e];d=l[e-1];g=l[e+1];if(e===0){j="mceToolbarStart";if(k.Button){j+=" mceToolbarStartButton"}else{if(k.SplitButton){j+=" mceToolbarStartSplitButton"}else{if(k.ListBox){j+=" mceToolbarStartListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,"<!-- IE -->"))}if(d&&k.ListBox){if(d.Button||d.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarEnd"},c.createHTML("span",null,"<!-- IE -->"))}}if(c.stdMode){f+='<td style="position: relative">'+k.renderHTML()+"</td>"}else{f+="<td>"+k.renderHTML()+"</td>"}if(g&&k.ListBox){if(g.Button||g.SplitButton){f+=c.createHTML("td",{"class":"mceToolbarStart"},c.createHTML("span",null,"<!-- IE -->"))}}}j="mceToolbarEnd";if(k.Button){j+=" mceToolbarEndButton"}else{if(k.SplitButton){j+=" mceToolbarEndSplitButton"}else{if(k.ListBox){j+=" mceToolbarEndListBox"}}}f+=c.createHTML("td",{"class":j},c.createHTML("span",null,"<!-- IE -->"));return c.createHTML("table",{id:m.id,"class":"mceToolbar"+(n["class"]?" "+n["class"]:""),cellpadding:"0",cellspacing:"0",align:m.settings.align||"",role:"presentation",tabindex:"-1"},"<tbody><tr>"+f+"</tr></tbody>")}})})(tinymce);(function(b){var a=b.util.Dispatcher,c=b.each;b.create("tinymce.AddOnManager",{AddOnManager:function(){var d=this;d.items=[];d.urls={};d.lookup={};d.onAdd=new a(d)},get:function(d){if(this.lookup[d]){return this.lookup[d].instance}else{return undefined}},dependencies:function(e){var d;if(this.lookup[e]){d=this.lookup[e].dependencies}return d||[]},requireLangPack:function(e){var d=b.settings;if(d&&d.language&&d.language_load!==false){b.ScriptLoader.add(this.urls[e]+"/langs/"+d.language+".js")}},add:function(f,e,d){this.items.push(e);this.lookup[f]={instance:e,dependencies:d};this.onAdd.dispatch(this,f,e);return e},createUrl:function(d,e){if(typeof e==="object"){return e}else{return{prefix:d.prefix,resource:e,suffix:d.suffix}}},addComponents:function(f,d){var e=this.urls[f];b.each(d,function(g){b.ScriptLoader.add(e+"/"+g)})},load:function(j,f,d,h){var g=this,e=f;function i(){var k=g.dependencies(j);b.each(k,function(m){var l=g.createUrl(f,m);g.load(l.resource,l,undefined,undefined)});if(d){if(h){d.call(h)}else{d.call(b.ScriptLoader)}}}if(g.urls[j]){return}if(typeof f==="object"){e=f.prefix+f.resource+f.suffix}if(e.indexOf("/")!=0&&e.indexOf("://")==-1){e=b.baseURL+"/"+e}g.urls[j]=e.substring(0,e.lastIndexOf("/"));if(g.lookup[j]){i()}else{b.ScriptLoader.add(e,i,h)}}});b.PluginManager=new b.AddOnManager();b.ThemeManager=new b.AddOnManager()}(tinymce));(function(j){var g=j.each,d=j.extend,k=j.DOM,i=j.dom.Event,f=j.ThemeManager,b=j.PluginManager,e=j.explode,h=j.util.Dispatcher,a,c=0;j.documentBaseURL=window.location.href.replace(/[\?#].*$/,"").replace(/[\/\\][^\/]+$/,"");if(!/[\/\\]$/.test(j.documentBaseURL)){j.documentBaseURL+="/"}j.baseURL=new j.util.URI(j.documentBaseURL).toAbsolute(j.baseURL);j.baseURI=new j.util.URI(j.baseURL);j.onBeforeUnload=new h(j);i.add(window,"beforeunload",function(l){j.onBeforeUnload.dispatch(j,l)});j.onAddEditor=new h(j);j.onRemoveEditor=new h(j);j.EditorManager=d(j,{editors:[],i18n:{},activeEditor:null,init:function(q){var n=this,p,l=j.ScriptLoader,u,o=[],m;function r(x,y,t){var v=x[y];if(!v){return}if(j.is(v,"string")){t=v.replace(/\.\w+$/,"");t=t?j.resolve(t):0;v=j.resolve(v)}return v.apply(t||this,Array.prototype.slice.call(arguments,2))}q=d({theme:"simple",language:"en"},q);n.settings=q;i.add(document,"init",function(){var s,v;r(q,"onpageload");switch(q.mode){case"exact":s=q.elements||"";if(s.length>0){g(e(s),function(x){if(k.get(x)){m=new j.Editor(x,q);o.push(m);m.render(1)}else{g(document.forms,function(y){g(y.elements,function(z){if(z.name===x){x="mce_editor_"+c++;k.setAttrib(z,"id",x);m=new j.Editor(x,q);o.push(m);m.render(1)}})})}})}break;case"textareas":case"specific_textareas":function t(y,x){return x.constructor===RegExp?x.test(y.className):k.hasClass(y,x)}g(k.select("textarea"),function(x){if(q.editor_deselector&&t(x,q.editor_deselector)){return}if(!q.editor_selector||t(x,q.editor_selector)){u=k.get(x.name);if(!x.id&&!u){x.id=x.name}if(!x.id||n.get(x.id)){x.id=k.uniqueId()}m=new j.Editor(x.id,q);o.push(m);m.render(1)}});break}if(q.oninit){s=v=0;g(o,function(x){v++;if(!x.initialized){x.onInit.add(function(){s++;if(s==v){r(q,"oninit")}})}else{s++}if(s==v){r(q,"oninit")}})}})},get:function(l){if(l===a){return this.editors}return this.editors[l]},getInstanceById:function(l){return this.get(l)},add:function(m){var l=this,n=l.editors;n[m.id]=m;n.push(m);l._setActive(m);l.onAddEditor.dispatch(l,m);return m},remove:function(n){var m=this,l,o=m.editors;if(!o[n.id]){return null}delete o[n.id];for(l=0;l<o.length;l++){if(o[l]==n){o.splice(l,1);break}}if(m.activeEditor==n){m._setActive(o[0])}n.destroy();m.onRemoveEditor.dispatch(m,n);return n},execCommand:function(r,p,o){var q=this,n=q.get(o),l;switch(r){case"mceFocus":n.focus();return true;case"mceAddEditor":case"mceAddControl":if(!q.get(o)){new j.Editor(o,q.settings).render()}return true;case"mceAddFrameControl":l=o.window;l.tinyMCE=tinyMCE;l.tinymce=j;j.DOM.doc=l.document;j.DOM.win=l;n=new j.Editor(o.element_id,o);n.render();if(j.isIE){function m(){n.destroy();l.detachEvent("onunload",m);l=l.tinyMCE=l.tinymce=null}l.attachEvent("onunload",m)}o.page_window=null;return true;case"mceRemoveEditor":case"mceRemoveControl":if(n){n.remove()}return true;case"mceToggleEditor":if(!n){q.execCommand("mceAddControl",0,o);return true}if(n.isHidden()){n.show()}else{n.hide()}return true}if(q.activeEditor){return q.activeEditor.execCommand(r,p,o)}return false},execInstanceCommand:function(p,o,n,m){var l=this.get(p);if(l){return l.execCommand(o,n,m)}return false},triggerSave:function(){g(this.editors,function(l){l.save()})},addI18n:function(n,q){var l,m=this.i18n;if(!j.is(n,"string")){g(n,function(r,p){g(r,function(t,s){g(t,function(v,u){if(s==="common"){m[p+"."+u]=v}else{m[p+"."+s+"."+u]=v}})})})}else{g(q,function(r,p){m[n+"."+p]=r})}},_setActive:function(l){this.selectedInstance=this.activeEditor=l}})})(tinymce);(function(m){var n=m.DOM,j=m.dom.Event,f=m.extend,k=m.util.Dispatcher,i=m.each,a=m.isGecko,b=m.isIE,e=m.isWebKit,d=m.is,h=m.ThemeManager,c=m.PluginManager,o=m.inArray,l=m.grep,g=m.explode;m.create("tinymce.Editor",{Editor:function(r,q){var p=this;p.id=p.editorId=r;p.execCommands={};p.queryStateCommands={};p.queryValueCommands={};p.isNotDirty=false;p.plugins={};i(["onPreInit","onBeforeRenderUI","onPostRender","onInit","onRemove","onActivate","onDeactivate","onClick","onEvent","onMouseUp","onMouseDown","onDblClick","onKeyDown","onKeyUp","onKeyPress","onContextMenu","onSubmit","onReset","onPaste","onPreProcess","onPostProcess","onBeforeSetContent","onBeforeGetContent","onSetContent","onGetContent","onLoadContent","onSaveContent","onNodeChange","onChange","onBeforeExecCommand","onExecCommand","onUndo","onRedo","onVisualAid","onSetProgressState"],function(s){p[s]=new k(p)});p.settings=q=f({id:r,language:"en",docs_language:"en",theme:"simple",skin:"default",delta_width:0,delta_height:0,popup_css:"",plugins:"",document_base_url:m.documentBaseURL,add_form_submit_trigger:1,submit_patch:1,add_unload_trigger:1,convert_urls:1,relative_urls:1,remove_script_host:1,table_inline_editing:0,object_resizing:1,cleanup:1,accessibility_focus:1,custom_shortcuts:1,custom_undo_redo_keyboard_shortcuts:1,custom_undo_redo_restore_selection:1,custom_undo_redo:1,doctype:m.isIE6?'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">':"<!DOCTYPE>",visual_table_class:"mceItemTable",visual:1,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",apply_source_formatting:1,directionality:"ltr",forced_root_block:"p",hidden_input:1,padd_empty_editor:1,render_ui:1,init_theme:1,force_p_newlines:1,indentation:"30px",keep_styles:1,fix_table_elements:1,inline_styles:1,convert_fonts_to_spans:true,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr",validate:true,entity_encoding:"named",url_converter:p.convertURL,url_converter_scope:p,ie7_compat:true},q);p.documentBaseURI=new m.util.URI(q.document_base_url||m.documentBaseURL,{base_uri:tinyMCE.baseURI});p.baseURI=m.baseURI;p.contentCSS=[];p.execCallback("setup",p)},render:function(r){var u=this,v=u.settings,x=u.id,p=m.ScriptLoader;if(!j.domLoaded){j.add(document,"init",function(){u.render()});return}tinyMCE.settings=v;if(!u.getElement()){return}if(m.isIDevice&&!m.isIOS5){return}if(!/TEXTAREA|INPUT/i.test(u.getElement().nodeName)&&v.hidden_input&&n.getParent(x,"form")){n.insertAfter(n.create("input",{type:"hidden",name:x}),x)}if(m.WindowManager){u.windowManager=new m.WindowManager(u)}if(v.encoding=="xml"){u.onGetContent.add(function(s,t){if(t.save){t.content=n.encode(t.content)}})}if(v.add_form_submit_trigger){u.onSubmit.addToTop(function(){if(u.initialized){u.save();u.isNotDirty=1}})}if(v.add_unload_trigger){u._beforeUnload=tinyMCE.onBeforeUnload.add(function(){if(u.initialized&&!u.destroyed&&!u.isHidden()){u.save({format:"raw",no_events:true})}})}m.addUnload(u.destroy,u);if(v.submit_patch){u.onBeforeRenderUI.add(function(){var s=u.getElement().form;if(!s){return}if(s._mceOldSubmit){return}if(!s.submit.nodeType&&!s.submit.length){u.formElement=s;s._mceOldSubmit=s.submit;s.submit=function(){m.triggerSave();u.isNotDirty=1;return u.formElement._mceOldSubmit(u.formElement)}}s=null})}function q(){if(v.language&&v.language_load!==false){p.add(m.baseURL+"/langs/"+v.language+".js")}if(v.theme&&v.theme.charAt(0)!="-"&&!h.urls[v.theme]){h.load(v.theme,"themes/"+v.theme+"/editor_template"+m.suffix+".js")}i(g(v.plugins),function(t){if(t&&!c.urls[t]){if(t.charAt(0)=="-"){t=t.substr(1,t.length);var s=c.dependencies(t);i(s,function(z){var y={prefix:"plugins/",resource:z,suffix:"/editor_plugin"+m.suffix+".js"};var z=c.createUrl(y,z);c.load(z.resource,z)})}else{if(t=="safari"){return}c.load(t,{prefix:"plugins/",resource:t,suffix:"/editor_plugin"+m.suffix+".js"})}}});p.loadQueue(function(){if(!u.removed){u.init()}})}q()},init:function(){var r,H=this,I=H.settings,E,A,D=H.getElement(),q,p,F,y,C,G,z,v=[];m.add(H);I.aria_label=I.aria_label||n.getAttrib(D,"aria-label",H.getLang("aria.rich_text_area"));if(I.theme){I.theme=I.theme.replace(/-/,"");q=h.get(I.theme);H.theme=new q();if(H.theme.init&&I.init_theme){H.theme.init(H,h.urls[I.theme]||m.documentBaseURL.replace(/\/$/,""))}}function B(J){var K=c.get(J),t=c.urls[J]||m.documentBaseURL.replace(/\/$/,""),s;if(K&&m.inArray(v,J)===-1){i(c.dependencies(J),function(u){B(u)});s=new K(H,t);H.plugins[J]=s;if(s.init){s.init(H,t);v.push(J)}}}i(g(I.plugins.replace(/\-/g,"")),B);if(I.popup_css!==false){if(I.popup_css){I.popup_css=H.documentBaseURI.toAbsolute(I.popup_css)}else{I.popup_css=H.baseURI.toAbsolute("themes/"+I.theme+"/skins/"+I.skin+"/dialog.css")}}if(I.popup_css_add){I.popup_css+=","+H.documentBaseURI.toAbsolute(I.popup_css_add)}H.controlManager=new m.ControlManager(H);if(I.custom_undo_redo){H.onBeforeExecCommand.add(function(t,J,u,K,s){if(J!="Undo"&&J!="Redo"&&J!="mceRepaint"&&(!s||!s.skip_undo)){H.undoManager.beforeChange()}});H.onExecCommand.add(function(t,J,u,K,s){if(J!="Undo"&&J!="Redo"&&J!="mceRepaint"&&(!s||!s.skip_undo)){H.undoManager.add()}})}H.onExecCommand.add(function(s,t){if(!/^(FontName|FontSize)$/.test(t)){H.nodeChanged()}});if(a){function x(s,t){if(!t||!t.initial){H.execCommand("mceRepaint")}}H.onUndo.add(x);H.onRedo.add(x);H.onSetContent.add(x)}H.onBeforeRenderUI.dispatch(H,H.controlManager);if(I.render_ui){E=I.width||D.style.width||D.offsetWidth;A=I.height||D.style.height||D.offsetHeight;H.orgDisplay=D.style.display;G=/^[0-9\.]+(|px)$/i;if(G.test(""+E)){E=Math.max(parseInt(E)+(q.deltaWidth||0),100)}if(G.test(""+A)){A=Math.max(parseInt(A)+(q.deltaHeight||0),100)}q=H.theme.renderUI({targetNode:D,width:E,height:A,deltaWidth:I.delta_width,deltaHeight:I.delta_height});H.editorContainer=q.editorContainer}if(document.domain&&location.hostname!=document.domain){m.relaxedDomain=document.domain}n.setStyles(q.sizeContainer||q.editorContainer,{width:E,height:A});if(I.content_css){m.each(g(I.content_css),function(s){H.contentCSS.push(H.documentBaseURI.toAbsolute(s))})}A=(q.iframeHeight||A)+(typeof(A)=="number"?(q.deltaHeight||0):"");if(A<100){A=100}H.iframeHTML=I.doctype+'<html><head xmlns="http://www.w3.org/1999/xhtml">';if(I.document_base_url!=m.documentBaseURL){H.iframeHTML+='<base href="'+H.documentBaseURI.getURI()+'" />'}if(I.ie7_compat){H.iframeHTML+='<meta http-equiv="X-UA-Compatible" content="IE=7" />'}else{H.iframeHTML+='<meta http-equiv="X-UA-Compatible" content="IE=edge" />'}H.iframeHTML+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';for(z=0;z<H.contentCSS.length;z++){H.iframeHTML+='<link type="text/css" rel="stylesheet" href="'+H.contentCSS[z]+'" />'}y=I.body_id||"tinymce";if(y.indexOf("=")!=-1){y=H.getParam("body_id","","hash");y=y[H.id]||y}C=I.body_class||"";if(C.indexOf("=")!=-1){C=H.getParam("body_class","","hash");C=C[H.id]||""}H.iframeHTML+='</head><body id="'+y+'" class="mceContentBody '+C+'"><br></body></html>';if(m.relaxedDomain&&(b||(m.isOpera&&parseFloat(opera.version())<11))){F='javascript:(function(){document.open();document.domain="'+document.domain+'";var ed = window.parent.tinyMCE.get("'+H.id+'");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()'}r=n.add(q.iframeContainer,"iframe",{id:H.id+"_ifr",src:F||'javascript:""',frameBorder:"0",allowTransparency:"true",title:I.aria_label,style:{width:"100%",height:A,display:"block"}});H.contentAreaContainer=q.iframeContainer;n.get(q.editorContainer).style.display=H.orgDisplay;n.get(H.id).style.display="none";n.setAttrib(H.id,"aria-hidden",true);if(!m.relaxedDomain||!F){H.setupIframe()}D=r=q=null},setupIframe:function(){var q=this,v=q.settings,x=n.get(q.id),y=q.getDoc(),u,p;if(!b||!m.relaxedDomain){y.open();y.write(q.iframeHTML);y.close();if(m.relaxedDomain){y.domain=m.relaxedDomain}}p=q.getBody();p.disabled=true;if(!v.readonly){p.contentEditable=true}p.disabled=false;q.schema=new m.html.Schema(v);q.dom=new m.dom.DOMUtils(q.getDoc(),{keep_values:true,url_converter:q.convertURL,url_converter_scope:q,hex_colors:v.force_hex_style_colors,class_filter:v.class_filter,update_styles:1,fix_ie_paragraphs:1,schema:q.schema});q.parser=new m.html.DomParser(v,q.schema);if(!q.settings.allow_html_in_named_anchor){q.parser.addAttributeFilter("name",function(s,t){var A=s.length,C,z,B,D;while(A--){D=s[A];if(D.name==="a"&&D.firstChild){B=D.parent;C=D.lastChild;do{z=C.prev;B.insert(C,D);C=z}while(C)}}})}q.parser.addAttributeFilter("src,href,style",function(s,t){var z=s.length,B,D=q.dom,C,A;while(z--){B=s[z];C=B.attr(t);A="data-mce-"+t;if(!B.attributes.map[A]){if(t==="style"){B.attr(A,D.serializeStyle(D.parseStyle(C),B.name))}else{B.attr(A,q.convertURL(C,t,B.name))}}}});q.parser.addNodeFilter("script",function(s,t){var z=s.length;while(z--){s[z].attr("type","mce-text/javascript")}});q.parser.addNodeFilter("#cdata",function(s,t){var z=s.length,A;while(z--){A=s[z];A.type=8;A.name="#comment";A.value="[CDATA["+A.value+"]]"}});q.parser.addNodeFilter("p,h1,h2,h3,h4,h5,h6,div",function(t,z){var A=t.length,B,s=q.schema.getNonEmptyElements();while(A--){B=t[A];if(B.isEmpty(s)){B.empty().append(new m.html.Node("br",1)).shortEnded=true}}});q.serializer=new m.dom.Serializer(v,q.dom,q.schema);q.selection=new m.dom.Selection(q.dom,q.getWin(),q.serializer);q.formatter=new m.Formatter(this);q.formatter.register({alignleft:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"left"}},{selector:"img,table",collapsed:false,styles:{"float":"left"}}],aligncenter:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"center"}},{selector:"img",collapsed:false,styles:{display:"block",marginLeft:"auto",marginRight:"auto"}},{selector:"table",collapsed:false,styles:{marginLeft:"auto",marginRight:"auto"}}],alignright:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"right"}},{selector:"img,table",collapsed:false,styles:{"float":"right"}}],alignfull:[{selector:"p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li",styles:{textAlign:"justify"}}],bold:[{inline:"strong",remove:"all"},{inline:"span",styles:{fontWeight:"bold"}},{inline:"b",remove:"all"}],italic:[{inline:"em",remove:"all"},{inline:"span",styles:{fontStyle:"italic"}},{inline:"i",remove:"all"}],underline:[{inline:"span",styles:{textDecoration:"underline"},exact:true},{inline:"u",remove:"all"}],strikethrough:[{inline:"span",styles:{textDecoration:"line-through"},exact:true},{inline:"strike",remove:"all"}],forecolor:{inline:"span",styles:{color:"%value"},wrap_links:false},hilitecolor:{inline:"span",styles:{backgroundColor:"%value"},wrap_links:false},fontname:{inline:"span",styles:{fontFamily:"%value"}},fontsize:{inline:"span",styles:{fontSize:"%value"}},fontsize_class:{inline:"span",attributes:{"class":"%value"}},blockquote:{block:"blockquote",wrapper:1,remove:"all"},subscript:{inline:"sub"},superscript:{inline:"sup"},link:{inline:"a",selector:"a",remove:"all",split:true,deep:true,onmatch:function(s){return true},onformat:function(z,s,t){i(t,function(B,A){q.dom.setAttrib(z,A,B)})}},removeformat:[{selector:"b,strong,em,i,font,u,strike",remove:"all",split:true,expand:false,block_expand:true,deep:true},{selector:"span",attributes:["style","class"],remove:"empty",split:true,expand:false,deep:true},{selector:"*",attributes:["style","class"],split:false,expand:false,deep:true}]});i("p h1 h2 h3 h4 h5 h6 div address pre div code dt dd samp".split(/\s/),function(s){q.formatter.register(s,{block:s,remove:"all"})});q.formatter.register(q.settings.formats);q.undoManager=new m.UndoManager(q);q.undoManager.onAdd.add(function(t,s){if(t.hasUndo()){return q.onChange.dispatch(q,s,t)}});q.undoManager.onUndo.add(function(t,s){return q.onUndo.dispatch(q,s,t)});q.undoManager.onRedo.add(function(t,s){return q.onRedo.dispatch(q,s,t)});q.forceBlocks=new m.ForceBlocks(q,{forced_root_block:v.forced_root_block});q.editorCommands=new m.EditorCommands(q);q.serializer.onPreProcess.add(function(s,t){return q.onPreProcess.dispatch(q,t,s)});q.serializer.onPostProcess.add(function(s,t){return q.onPostProcess.dispatch(q,t,s)});q.onPreInit.dispatch(q);if(!v.gecko_spellcheck){q.getBody().spellcheck=0}if(!v.readonly){q._addEvents()}q.controlManager.onPostRender.dispatch(q,q.controlManager);q.onPostRender.dispatch(q);q.quirks=new m.util.Quirks(this);if(v.directionality){q.getBody().dir=v.directionality}if(v.nowrap){q.getBody().style.whiteSpace="nowrap"}if(v.handle_node_change_callback){q.onNodeChange.add(function(t,s,z){q.execCallback("handle_node_change_callback",q.id,z,-1,-1,true,q.selection.isCollapsed())})}if(v.save_callback){q.onSaveContent.add(function(s,z){var t=q.execCallback("save_callback",q.id,z.content,q.getBody());if(t){z.content=t}})}if(v.onchange_callback){q.onChange.add(function(t,s){q.execCallback("onchange_callback",q,s)})}if(v.protect){q.onBeforeSetContent.add(function(s,t){if(v.protect){i(v.protect,function(z){t.content=t.content.replace(z,function(A){return"<!--mce:protected "+escape(A)+"-->"})})}})}if(v.convert_newlines_to_brs){q.onBeforeSetContent.add(function(s,t){if(t.initial){t.content=t.content.replace(/\r?\n/g,"<br />")}})}if(v.preformatted){q.onPostProcess.add(function(s,t){t.content=t.content.replace(/^\s*<pre.*?>/,"");t.content=t.content.replace(/<\/pre>\s*$/,"");if(t.set){t.content='<pre class="mceItemHidden">'+t.content+"</pre>"}})}if(v.verify_css_classes){q.serializer.attribValueFilter=function(B,z){var A,t;if(B=="class"){if(!q.classesRE){t=q.dom.getClasses();if(t.length>0){A="";i(t,function(s){A+=(A?"|":"")+s["class"]});q.classesRE=new RegExp("("+A+")","gi")}}return !q.classesRE||/(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(z)||q.classesRE.test(z)?z:""}return z}}if(v.cleanup_callback){q.onBeforeSetContent.add(function(s,t){t.content=q.execCallback("cleanup_callback","insert_to_editor",t.content,t)});q.onPreProcess.add(function(s,t){if(t.set){q.execCallback("cleanup_callback","insert_to_editor_dom",t.node,t)}if(t.get){q.execCallback("cleanup_callback","get_from_editor_dom",t.node,t)}});q.onPostProcess.add(function(s,t){if(t.set){t.content=q.execCallback("cleanup_callback","insert_to_editor",t.content,t)}if(t.get){t.content=q.execCallback("cleanup_callback","get_from_editor",t.content,t)}})}if(v.save_callback){q.onGetContent.add(function(s,t){if(t.save){t.content=q.execCallback("save_callback",q.id,t.content,q.getBody())}})}if(v.handle_event_callback){q.onEvent.add(function(s,t,z){if(q.execCallback("handle_event_callback",t,s,z)===false){j.cancel(t)}})}q.onSetContent.add(function(){q.addVisual(q.getBody())});if(v.padd_empty_editor){q.onPostProcess.add(function(s,t){t.content=t.content.replace(/^(<p[^>]*>(&nbsp;|&#160;|\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/,"")})}if(a){function r(s,t){i(s.dom.select("a"),function(A){var z=A.parentNode;if(s.dom.isBlock(z)&&z.lastChild===A){s.dom.add(z,"br",{"data-mce-bogus":1})}})}q.onExecCommand.add(function(s,t){if(t==="CreateLink"){r(s)}});q.onSetContent.add(q.selection.onSetContent.add(r))}q.load({initial:true,format:"html"});q.startContent=q.getContent({format:"raw"});q.undoManager.add();q.initialized=true;q.onInit.dispatch(q);q.execCallback("setupcontent_callback",q.id,q.getBody(),q.getDoc());q.execCallback("init_instance_callback",q);q.focus(true);q.nodeChanged({initial:1});i(q.contentCSS,function(s){q.dom.loadCSS(s)});if(v.auto_focus){setTimeout(function(){var s=m.get(v.auto_focus);s.selection.select(s.getBody(),1);s.selection.collapse(1);s.getBody().focus();s.getWin().focus()},100)}x=null},focus:function(u){var y,q=this,s=q.selection,x=q.settings.content_editable,r,p,v=q.getDoc();if(!u){r=s.getRng();if(r.item){p=r.item(0)}q._refreshContentEditable();s.normalize();if(!x){q.getWin().focus()}if(m.isGecko){q.getBody().focus()}if(p&&p.ownerDocument==v){r=v.body.createControlRange();r.addElement(p);r.select()}}if(m.activeEditor!=q){if((y=m.activeEditor)!=null){y.onDeactivate.dispatch(y,q)}q.onActivate.dispatch(q,y)}m._setActive(q)},execCallback:function(u){var p=this,r=p.settings[u],q;if(!r){return}if(p.callbackLookup&&(q=p.callbackLookup[u])){r=q.func;q=q.scope}if(d(r,"string")){q=r.replace(/\.\w+$/,"");q=q?m.resolve(q):0;r=m.resolve(r);p.callbackLookup=p.callbackLookup||{};p.callbackLookup[u]={func:r,scope:q}}return r.apply(q||p,Array.prototype.slice.call(arguments,1))},translate:function(p){var r=this.settings.language||"en",q=m.i18n;if(!p){return""}return q[r+"."+p]||p.replace(/{\#([^}]+)\}/g,function(t,s){return q[r+"."+s]||"{#"+s+"}"})},getLang:function(q,p){return m.i18n[(this.settings.language||"en")+"."+q]||(d(p)?p:"{#"+q+"}")},getParam:function(u,r,p){var s=m.trim,q=d(this.settings[u])?this.settings[u]:r,t;if(p==="hash"){t={};if(d(q,"string")){i(q.indexOf("=")>0?q.split(/[;,](?![^=;,]*(?:[;,]|$))/):q.split(","),function(x){x=x.split("=");if(x.length>1){t[s(x[0])]=s(x[1])}else{t[s(x[0])]=s(x)}})}else{t=q}return t}return q},nodeChanged:function(r){var p=this,q=p.selection,u=q.getStart()||p.getBody();if(p.initialized){r=r||{};u=b&&u.ownerDocument!=p.getDoc()?p.getBody():u;r.parents=[];p.dom.getParent(u,function(s){if(s.nodeName=="BODY"){return true}r.parents.push(s)});p.onNodeChange.dispatch(p,r?r.controlManager||p.controlManager:p.controlManager,u,q.isCollapsed(),r)}},addButton:function(r,q){var p=this;p.buttons=p.buttons||{};p.buttons[r]=q},addCommand:function(p,r,q){this.execCommands[p]={func:r,scope:q||this}},addQueryStateHandler:function(p,r,q){this.queryStateCommands[p]={func:r,scope:q||this}},addQueryValueHandler:function(p,r,q){this.queryValueCommands[p]={func:r,scope:q||this}},addShortcut:function(r,u,p,s){var q=this,v;if(!q.settings.custom_shortcuts){return false}q.shortcuts=q.shortcuts||{};if(d(p,"string")){v=p;p=function(){q.execCommand(v,false,null)}}if(d(p,"object")){v=p;p=function(){q.execCommand(v[0],v[1],v[2])}}i(g(r),function(t){var x={func:p,scope:s||this,desc:u,alt:false,ctrl:false,shift:false};i(g(t,"+"),function(y){switch(y){case"alt":case"ctrl":case"shift":x[y]=true;break;default:x.charCode=y.charCodeAt(0);x.keyCode=y.toUpperCase().charCodeAt(0)}});q.shortcuts[(x.ctrl?"ctrl":"")+","+(x.alt?"alt":"")+","+(x.shift?"shift":"")+","+x.keyCode]=x});return true},execCommand:function(x,v,z,p){var r=this,u=0,y,q;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(x)&&(!p||!p.skip_focus)){r.focus()}y={};r.onBeforeExecCommand.dispatch(r,x,v,z,y);if(y.terminate){return false}if(r.execCallback("execcommand_callback",r.id,r.selection.getNode(),x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);return true}if(y=r.execCommands[x]){q=y.func.call(y.scope,v,z);if(q!==true){r.onExecCommand.dispatch(r,x,v,z,p);return q}}i(r.plugins,function(s){if(s.execCommand&&s.execCommand(x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);u=1;return false}});if(u){return true}if(r.theme&&r.theme.execCommand&&r.theme.execCommand(x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);return true}if(r.editorCommands.execCommand(x,v,z)){r.onExecCommand.dispatch(r,x,v,z,p);return true}r.getDoc().execCommand(x,v,z);r.onExecCommand.dispatch(r,x,v,z,p)},queryCommandState:function(u){var q=this,v,r;if(q._isHidden()){return}if(v=q.queryStateCommands[u]){r=v.func.call(v.scope);if(r!==true){return r}}v=q.editorCommands.queryCommandState(u);if(v!==-1){return v}try{return this.getDoc().queryCommandState(u)}catch(p){}},queryCommandValue:function(v){var q=this,u,r;if(q._isHidden()){return}if(u=q.queryValueCommands[v]){r=u.func.call(u.scope);if(r!==true){return r}}u=q.editorCommands.queryCommandValue(v);if(d(u)){return u}try{return this.getDoc().queryCommandValue(v)}catch(p){}},show:function(){var p=this;n.show(p.getContainer());n.hide(p.id);p.load()},hide:function(){var p=this,q=p.getDoc();if(b&&q){q.execCommand("SelectAll")}p.save();n.hide(p.getContainer());n.setStyle(p.id,"display",p.orgDisplay)},isHidden:function(){return !n.isHidden(this.id)},setProgressState:function(p,q,r){this.onSetProgressState.dispatch(this,p,q,r);return p},load:function(s){var p=this,r=p.getElement(),q;if(r){s=s||{};s.load=true;q=p.setContent(d(r.value)?r.value:r.innerHTML,s);s.element=r;if(!s.no_events){p.onLoadContent.dispatch(p,s)}s.element=r=null;return q}},save:function(u){var p=this,s=p.getElement(),q,r;if(!s||!p.initialized){return}u=u||{};u.save=true;if(!u.no_events){p.undoManager.typing=false;p.undoManager.add()}u.element=s;q=u.content=p.getContent(u);if(!u.no_events){p.onSaveContent.dispatch(p,u)}q=u.content;if(!/TEXTAREA|INPUT/i.test(s.nodeName)){s.innerHTML=q;if(r=n.getParent(p.id,"form")){i(r.elements,function(t){if(t.name==p.id){t.value=q;return false}})}}else{s.value=q}u.element=s=null;return q},setContent:function(u,s){var r=this,q,p=r.getBody(),t;s=s||{};s.format=s.format||"html";s.set=true;s.content=u;if(!s.no_events){r.onBeforeSetContent.dispatch(r,s)}u=s.content;if(!m.isIE&&(u.length===0||/^\s+$/.test(u))){t=r.settings.forced_root_block;if(t){u="<"+t+'><br data-mce-bogus="1"></'+t+">"}else{u='<br data-mce-bogus="1">'}p.innerHTML=u;r.selection.select(p,true);r.selection.collapse(true);return}if(s.format!=="raw"){u=new m.html.Serializer({},r.schema).serialize(r.parser.parse(u))}s.content=m.trim(u);r.dom.setHTML(p,s.content);if(!s.no_events){r.onSetContent.dispatch(r,s)}r.selection.normalize();return s.content},getContent:function(q){var p=this,r;q=q||{};q.format=q.format||"html";q.get=true;if(!q.no_events){p.onBeforeGetContent.dispatch(p,q)}if(q.format=="raw"){r=p.getBody().innerHTML}else{r=p.serializer.serialize(p.getBody(),q)}q.content=m.trim(r);if(!q.no_events){p.onGetContent.dispatch(p,q)}return q.content},isDirty:function(){var p=this;return m.trim(p.startContent)!=m.trim(p.getContent({format:"raw",no_events:1}))&&!p.isNotDirty},getContainer:function(){var p=this;if(!p.container){p.container=n.get(p.editorContainer||p.id+"_parent")}return p.container},getContentAreaContainer:function(){return this.contentAreaContainer},getElement:function(){return n.get(this.settings.content_element||this.id)},getWin:function(){var p=this,q;if(!p.contentWindow){q=n.get(p.id+"_ifr");if(q){p.contentWindow=q.contentWindow}}return p.contentWindow},getDoc:function(){var q=this,p;if(!q.contentDocument){p=q.getWin();if(p){q.contentDocument=p.document}}return q.contentDocument},getBody:function(){return this.bodyElement||this.getDoc().body},convertURL:function(p,x,v){var q=this,r=q.settings;if(r.urlconverter_callback){return q.execCallback("urlconverter_callback",p,v,true,x)}if(!r.convert_urls||(v&&v.nodeName=="LINK")||p.indexOf("file:")===0){return p}if(r.relative_urls){return q.documentBaseURI.toRelative(p)}p=q.documentBaseURI.toAbsolute(p,r.remove_script_host);return p},addVisual:function(r){var p=this,q=p.settings;r=r||p.getBody();if(!d(p.hasVisual)){p.hasVisual=q.visual}i(p.dom.select("table,a",r),function(t){var s;switch(t.nodeName){case"TABLE":s=p.dom.getAttrib(t,"border");if(!s||s=="0"){if(p.hasVisual){p.dom.addClass(t,q.visual_table_class)}else{p.dom.removeClass(t,q.visual_table_class)}}return;case"A":s=p.dom.getAttrib(t,"name");if(s){if(p.hasVisual){p.dom.addClass(t,"mceItemAnchor")}else{p.dom.removeClass(t,"mceItemAnchor")}}return}});p.onVisualAid.dispatch(p,r,p.hasVisual)},remove:function(){var p=this,q=p.getContainer();p.removed=1;p.hide();p.execCallback("remove_instance_callback",p);p.onRemove.dispatch(p);p.onExecCommand.listeners=[];m.remove(p);n.remove(q)},destroy:function(q){var p=this;if(p.destroyed){return}if(!q){m.removeUnload(p.destroy);tinyMCE.onBeforeUnload.remove(p._beforeUnload);if(p.theme&&p.theme.destroy){p.theme.destroy()}p.controlManager.destroy();p.selection.destroy();p.dom.destroy();if(!p.settings.content_editable){j.clear(p.getWin());j.clear(p.getDoc())}j.clear(p.getBody());j.clear(p.formElement)}if(p.formElement){p.formElement.submit=p.formElement._mceOldSubmit;p.formElement._mceOldSubmit=null}p.contentAreaContainer=p.formElement=p.container=p.settings.content_element=p.bodyElement=p.contentDocument=p.contentWindow=null;if(p.selection){p.selection=p.selection.win=p.selection.dom=p.selection.dom.doc=null}p.destroyed=1},_addEvents:function(){var B=this,r,C=B.settings,q=B.dom,x={mouseup:"onMouseUp",mousedown:"onMouseDown",click:"onClick",keyup:"onKeyUp",keydown:"onKeyDown",keypress:"onKeyPress",submit:"onSubmit",reset:"onReset",contextmenu:"onContextMenu",dblclick:"onDblClick",paste:"onPaste"};function p(t,D){var s=t.type;if(B.removed){return}if(B.onEvent.dispatch(B,t,D)!==false){B[x[t.fakeType||t.type]].dispatch(B,t,D)}}i(x,function(t,s){switch(s){case"contextmenu":q.bind(B.getDoc(),s,p);break;case"paste":q.bind(B.getBody(),s,function(D){p(D)});break;case"submit":case"reset":q.bind(B.getElement().form||n.getParent(B.id,"form"),s,p);break;default:q.bind(C.content_editable?B.getBody():B.getDoc(),s,p)}});q.bind(C.content_editable?B.getBody():(a?B.getDoc():B.getWin()),"focus",function(s){B.focus(true)});if(m.isGecko){q.bind(B.getDoc(),"DOMNodeInserted",function(t){var s;t=t.target;if(t.nodeType===1&&t.nodeName==="IMG"&&(s=t.getAttribute("data-mce-src"))){t.src=B.documentBaseURI.toAbsolute(s)}})}if(a){function u(){var E=this,G=E.getDoc(),F=E.settings;if(a&&!F.readonly){E._refreshContentEditable();try{G.execCommand("styleWithCSS",0,false)}catch(D){if(!E._isHidden()){try{G.execCommand("useCSS",0,true)}catch(D){}}}if(!F.table_inline_editing){try{G.execCommand("enableInlineTableEditing",false,false)}catch(D){}}if(!F.object_resizing){try{G.execCommand("enableObjectResizing",false,false)}catch(D){}}}}B.onBeforeExecCommand.add(u);B.onMouseDown.add(u)}B.onMouseUp.add(B.nodeChanged);B.onKeyUp.add(function(s,t){var D=t.keyCode;if((D>=33&&D<=36)||(D>=37&&D<=40)||D==13||D==45||D==46||D==8||(m.isMac&&(D==91||D==93))||t.ctrlKey){B.nodeChanged()}});B.onKeyDown.add(function(t,D){if(D.keyCode!=8){return}var F=t.selection.getRng().startContainer;var E=t.selection.getRng().startOffset;while(F&&F.nodeType&&F.nodeType!=1&&F.parentNode){F=F.parentNode}if(F&&F.parentNode&&F.parentNode.tagName==="BLOCKQUOTE"&&F.parentNode.firstChild==F&&E==0){t.formatter.toggle("blockquote",null,F.parentNode);var s=t.selection.getRng();s.setStart(F,0);s.setEnd(F,0);t.selection.setRng(s);t.selection.collapse(false)}});B.onReset.add(function(){B.setContent(B.startContent,{format:"raw"})});if(C.custom_shortcuts){if(C.custom_undo_redo_keyboard_shortcuts){B.addShortcut("ctrl+z",B.getLang("undo_desc"),"Undo");B.addShortcut("ctrl+y",B.getLang("redo_desc"),"Redo")}B.addShortcut("ctrl+b",B.getLang("bold_desc"),"Bold");B.addShortcut("ctrl+i",B.getLang("italic_desc"),"Italic");B.addShortcut("ctrl+u",B.getLang("underline_desc"),"Underline");for(r=1;r<=6;r++){B.addShortcut("ctrl+"+r,"",["FormatBlock",false,"h"+r])}B.addShortcut("ctrl+7","",["FormatBlock",false,"p"]);B.addShortcut("ctrl+8","",["FormatBlock",false,"div"]);B.addShortcut("ctrl+9","",["FormatBlock",false,"address"]);function v(t){var s=null;if(!t.altKey&&!t.ctrlKey&&!t.metaKey){return s}i(B.shortcuts,function(D){if(m.isMac&&D.ctrl!=t.metaKey){return}else{if(!m.isMac&&D.ctrl!=t.ctrlKey){return}}if(D.alt!=t.altKey){return}if(D.shift!=t.shiftKey){return}if(t.keyCode==D.keyCode||(t.charCode&&t.charCode==D.charCode)){s=D;return false}});return s}B.onKeyUp.add(function(s,t){var D=v(t);if(D){return j.cancel(t)}});B.onKeyPress.add(function(s,t){var D=v(t);if(D){return j.cancel(t)}});B.onKeyDown.add(function(s,t){var D=v(t);if(D){D.func.call(D.scope);return j.cancel(t)}})}if(m.isIE){q.bind(B.getDoc(),"controlselect",function(D){var t=B.resizeInfo,s;D=D.target;if(D.nodeName!=="IMG"){return}if(t){q.unbind(t.node,t.ev,t.cb)}if(!q.hasClass(D,"mceItemNoResize")){ev="resizeend";s=q.bind(D,ev,function(F){var E;F=F.target;if(E=q.getStyle(F,"width")){q.setAttrib(F,"width",E.replace(/[^0-9%]+/g,""));q.setStyle(F,"width","")}if(E=q.getStyle(F,"height")){q.setAttrib(F,"height",E.replace(/[^0-9%]+/g,""));q.setStyle(F,"height","")}})}else{ev="resizestart";s=q.bind(D,"resizestart",j.cancel,j)}t=B.resizeInfo={node:D,ev:ev,cb:s}})}if(m.isOpera){B.onClick.add(function(s,t){j.prevent(t)})}if(C.custom_undo_redo){function y(){B.undoManager.typing=false;B.undoManager.add()}q.bind(B.getDoc(),"focusout",function(s){if(!B.removed&&B.undoManager.typing){y()}});B.dom.bind(B.dom.getRoot(),"dragend",function(s){y()});B.onKeyUp.add(function(s,D){var t=D.keyCode;if((t>=33&&t<=36)||(t>=37&&t<=40)||t==13||t==45||D.ctrlKey){y()}});B.onKeyDown.add(function(s,E){var D=E.keyCode,t;if(D==8){t=B.getDoc().selection;if(t&&t.createRange&&t.createRange().item){B.undoManager.beforeChange();s.dom.remove(t.createRange().item(0));y();return j.cancel(E)}}if((D>=33&&D<=36)||(D>=37&&D<=40)||D==13||D==45){if(m.isIE&&D==13){B.undoManager.beforeChange()}if(B.undoManager.typing){y()}return}if((D<16||D>20)&&D!=224&&D!=91&&!B.undoManager.typing){B.undoManager.beforeChange();B.undoManager.typing=true;B.undoManager.add()}});B.onMouseDown.add(function(){if(B.undoManager.typing){y()}})}if(m.isWebKit){q.bind(B.getDoc(),"selectionchange",function(){if(B.selectionTimer){clearTimeout(B.selectionTimer);B.selectionTimer=0}B.selectionTimer=window.setTimeout(function(){B.nodeChanged()},50)})}if(m.isGecko){function A(){var s=B.dom.getAttribs(B.selection.getStart().cloneNode(false));return function(){var t=B.selection.getStart();if(t!==B.getBody()){B.dom.removeAllAttribs(t);i(s,function(D){t.setAttributeNode(D.cloneNode(true))})}}}function z(){var t=B.selection;return !t.isCollapsed()&&t.getStart()!=t.getEnd()}B.onKeyPress.add(function(s,D){var t;if((D.keyCode==8||D.keyCode==46)&&z()){t=A();B.getDoc().execCommand("delete",false,null);t();return j.cancel(D)}});B.dom.bind(B.getDoc(),"cut",function(t){var s;if(z()){s=A();B.onKeyUp.addToTop(j.cancel,j);setTimeout(function(){s();B.onKeyUp.remove(j.cancel,j)},0)}})}},_refreshContentEditable:function(){var q=this,p,r;if(q._isHidden()){p=q.getBody();r=p.parentNode;r.removeChild(p);r.appendChild(p);p.focus()}},_isHidden:function(){var p;if(!a){return 0}p=this.selection.getSel();return(!p||!p.rangeCount||p.rangeCount==0)}})})(tinymce);(function(c){var d=c.each,e,a=true,b=false;c.EditorCommands=function(n){var m=n.dom,p=n.selection,j={state:{},exec:{},value:{}},k=n.settings,q=n.formatter,o;function r(z,y,x){var v;z=z.toLowerCase();if(v=j.exec[z]){v(z,y,x);return a}return b}function l(x){var v;x=x.toLowerCase();if(v=j.state[x]){return v(x)}return -1}function h(x){var v;x=x.toLowerCase();if(v=j.value[x]){return v(x)}return b}function u(v,x){x=x||"exec";d(v,function(z,y){d(y.toLowerCase().split(","),function(A){j[x][A]=z})})}c.extend(this,{execCommand:r,queryCommandState:l,queryCommandValue:h,addCommands:u});function f(y,x,v){if(x===e){x=b}if(v===e){v=null}return n.getDoc().execCommand(y,x,v)}function t(v){return q.match(v)}function s(v,x){q.toggle(v,x?{value:x}:e)}function i(v){o=p.getBookmark(v)}function g(){p.moveToBookmark(o)}u({"mceResetDesignMode,mceBeginUndoLevel":function(){},"mceEndUndoLevel,mceAddUndoLevel":function(){n.undoManager.add()},"Cut,Copy,Paste":function(z){var y=n.getDoc(),v;try{f(z)}catch(x){v=a}if(v||!y.queryCommandSupported(z)){if(c.isGecko){n.windowManager.confirm(n.getLang("clipboard_msg"),function(A){if(A){open("http://www.mozilla.org/editor/midasdemo/securityprefs.html","_blank")}})}else{n.windowManager.alert(n.getLang("clipboard_no_support"))}}},unlink:function(v){if(p.isCollapsed()){p.select(p.getNode())}f(v);p.collapse(b)},"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){var x=v.substring(7);d("left,center,right,full".split(","),function(y){if(x!=y){q.remove("align"+y)}});s("align"+x);r("mceRepaint")},"InsertUnorderedList,InsertOrderedList":function(y){var v,x;f(y);v=m.getParent(p.getNode(),"ol,ul");if(v){x=v.parentNode;if(/^(H[1-6]|P|ADDRESS|PRE)$/.test(x.nodeName)){i();m.split(x,v);g()}}},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){s(v)},"ForeColor,HiliteColor,FontName":function(y,x,v){s(y,v)},FontSize:function(z,y,x){var v,A;if(x>=1&&x<=7){A=c.explode(k.font_size_style_values);v=c.explode(k.font_size_classes);if(v){x=v[x-1]||x}else{x=A[x-1]||x}}s(z,x)},RemoveFormat:function(v){q.remove(v)},mceBlockQuote:function(v){s("blockquote")},FormatBlock:function(y,x,v){return s(v||"p")},mceCleanup:function(){var v=p.getBookmark();n.setContent(n.getContent({cleanup:a}),{cleanup:a});p.moveToBookmark(v)},mceRemoveNode:function(z,y,x){var v=x||p.getNode();if(v!=n.getBody()){i();n.dom.remove(v,a);g()}},mceSelectNodeDepth:function(z,y,x){var v=0;m.getParent(p.getNode(),function(A){if(A.nodeType==1&&v++==x){p.select(A);return b}},n.getBody())},mceSelectNode:function(y,x,v){p.select(v)},mceInsertContent:function(B,I,K){var y,J,E,z,F,G,D,C,L,x,A,M,v,H;y=n.parser;J=new c.html.Serializer({},n.schema);v='<span id="mce_marker" data-mce-type="bookmark">\uFEFF</span>';G={content:K,format:"html"};p.onBeforeSetContent.dispatch(p,G);K=G.content;if(K.indexOf("{$caret}")==-1){K+="{$caret}"}K=K.replace(/\{\$caret\}/,v);if(!p.isCollapsed()){n.getDoc().execCommand("Delete",false,null)}E=p.getNode();G={context:E.nodeName.toLowerCase()};F=y.parse(K,G);A=F.lastChild;if(A.attr("id")=="mce_marker"){D=A;for(A=A.prev;A;A=A.walk(true)){if(A.type==3||!m.isBlock(A.name)){A.parent.insert(D,A,A.name==="br");break}}}if(!G.invalid){K=J.serialize(F);A=E.firstChild;M=E.lastChild;if(!A||(A===M&&A.nodeName==="BR")){m.setHTML(E,K)}else{p.setContent(K)}}else{p.setContent(v);E=n.selection.getNode();z=n.getBody();if(E.nodeType==9){E=A=z}else{A=E}while(A!==z){E=A;A=A.parentNode}K=E==z?z.innerHTML:m.getOuterHTML(E);K=J.serialize(y.parse(K.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i,function(){return J.serialize(F)})));if(E==z){m.setHTML(z,K)}else{m.setOuterHTML(E,K)}}D=m.get("mce_marker");C=m.getRect(D);L=m.getViewPort(n.getWin());if((C.y+C.h>L.y+L.h||C.y<L.y)||(C.x>L.x+L.w||C.x<L.x)){H=c.isIE?n.getDoc().documentElement:n.getBody();H.scrollLeft=C.x;H.scrollTop=C.y-L.h+25}x=m.createRng();A=D.previousSibling;if(A&&A.nodeType==3){x.setStart(A,A.nodeValue.length)}else{x.setStartBefore(D);x.setEndBefore(D)}m.remove(D);p.setRng(x);p.onSetContent.dispatch(p,G);n.addVisual()},mceInsertRawHTML:function(y,x,v){p.setContent("tiny_mce_marker");n.setContent(n.getContent().replace(/tiny_mce_marker/g,function(){return v}))},mceSetContent:function(y,x,v){n.setContent(v)},"Indent,Outdent":function(z){var x,v,y;x=k.indentation;v=/[a-z%]+$/i.exec(x);x=parseInt(x);if(!l("InsertUnorderedList")&&!l("InsertOrderedList")){d(p.getSelectedBlocks(),function(A){if(z=="outdent"){y=Math.max(0,parseInt(A.style.paddingLeft||0)-x);m.setStyle(A,"paddingLeft",y?y+v:"")}else{m.setStyle(A,"paddingLeft",(parseInt(A.style.paddingLeft||0)+x)+v)}})}else{f(z)}},mceRepaint:function(){var x;if(c.isGecko){try{i(a);if(p.getSel()){p.getSel().selectAllChildren(n.getBody())}p.collapse(a);g()}catch(v){}}},mceToggleFormat:function(y,x,v){q.toggle(v)},InsertHorizontalRule:function(){n.execCommand("mceInsertContent",false,"<hr />")},mceToggleVisualAid:function(){n.hasVisual=!n.hasVisual;n.addVisual()},mceReplaceContent:function(y,x,v){n.execCommand("mceInsertContent",false,v.replace(/\{\$selection\}/g,p.getContent({format:"text"})))},mceInsertLink:function(z,y,x){var v;if(typeof(x)=="string"){x={href:x}}v=m.getParent(p.getNode(),"a");x.href=x.href.replace(" ","%20");if(!v||!x.href){q.remove("link")}if(x.href){q.apply("link",x,v)}},selectAll:function(){var x=m.getRoot(),v=m.createRng();v.setStart(x,0);v.setEnd(x,x.childNodes.length);n.selection.setRng(v)}});u({"JustifyLeft,JustifyCenter,JustifyRight,JustifyFull":function(v){return t("align"+v.substring(7))},"Bold,Italic,Underline,Strikethrough,Superscript,Subscript":function(v){return t(v)},mceBlockQuote:function(){return t("blockquote")},Outdent:function(){var v;if(k.inline_styles){if((v=m.getParent(p.getStart(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}if((v=m.getParent(p.getEnd(),m.isBlock))&&parseInt(v.style.paddingLeft)>0){return a}}return l("InsertUnorderedList")||l("InsertOrderedList")||(!k.inline_styles&&!!m.getParent(p.getNode(),"BLOCKQUOTE"))},"InsertUnorderedList,InsertOrderedList":function(v){return m.getParent(p.getNode(),v=="insertunorderedlist"?"UL":"OL")}},"state");u({"FontSize,FontName":function(y){var x=0,v;if(v=m.getParent(p.getNode(),"span")){if(y=="fontsize"){x=v.style.fontSize}else{x=v.style.fontFamily.replace(/, /g,",").replace(/[\'\"]/g,"").toLowerCase()}}return x}},"value");if(k.custom_undo_redo){u({Undo:function(){n.undoManager.undo()},Redo:function(){n.undoManager.redo()}})}}})(tinymce);(function(b){var a=b.util.Dispatcher;b.UndoManager=function(f){var d,e=0,h=[],c;function g(){return b.trim(f.getContent({format:"raw",no_events:1}))}return d={typing:false,onAdd:new a(d),onUndo:new a(d),onRedo:new a(d),beforeChange:function(){c=f.selection.getBookmark(2,true)},add:function(m){var j,k=f.settings,l;m=m||{};m.content=g();l=h[e];if(l&&l.content==m.content){return null}if(h[e]){h[e].beforeBookmark=c}if(k.custom_undo_redo_levels){if(h.length>k.custom_undo_redo_levels){for(j=0;j<h.length-1;j++){h[j]=h[j+1]}h.length--;e=h.length}}m.bookmark=f.selection.getBookmark(2,true);if(e<h.length-1){h.length=e+1}h.push(m);e=h.length-1;d.onAdd.dispatch(d,m);f.isNotDirty=0;return m},undo:function(){var k,j;if(d.typing){d.add();d.typing=false}if(e>0){k=h[--e];f.setContent(k.content,{format:"raw"});f.selection.moveToBookmark(k.beforeBookmark);d.onUndo.dispatch(d,k)}return k},redo:function(){var i;if(e<h.length-1){i=h[++e];f.setContent(i.content,{format:"raw"});f.selection.moveToBookmark(i.bookmark);d.onRedo.dispatch(d,i)}return i},clear:function(){h=[];e=0;d.typing=false},hasUndo:function(){return e>0||this.typing},hasRedo:function(){return e<h.length-1&&!this.typing}}}})(tinymce);(function(l){var j=l.dom.Event,c=l.isIE,a=l.isGecko,b=l.isOpera,i=l.each,h=l.extend,d=true,g=false;function k(o){var p,n,m;do{if(/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(o.nodeName)){if(p){n=o.cloneNode(false);n.appendChild(p);p=n}else{p=m=o.cloneNode(false)}p.removeAttribute("id")}}while(o=o.parentNode);if(p){return{wrapper:p,inner:m}}}function f(n,o){var m=o.ownerDocument.createRange();m.setStart(n.endContainer,n.endOffset);m.setEndAfter(o);return m.cloneContents().textContent.length==0}function e(o,q,m){var n,p;if(q.isEmpty(m)){n=q.getParent(m,"ul,ol");if(!q.getParent(n.parentNode,"ul,ol")){q.split(n,m);p=q.create("p",0,'<br data-mce-bogus="1" />');q.replace(p,m);o.select(p,1)}return g}return d}l.create("tinymce.ForceBlocks",{ForceBlocks:function(m){var n=this,o=m.settings,p;n.editor=m;n.dom=m.dom;p=(o.forced_root_block||"p").toLowerCase();o.element=p.toUpperCase();m.onPreInit.add(n.setup,n)},setup:function(){var n=this,m=n.editor,p=m.settings,u=m.dom,o=m.selection,q=m.schema.getBlockElements();if(p.forced_root_block){function v(){var y=o.getStart(),t=m.getBody(),s,z,D,F,E,x,A,B=-16777215;if(!y||y.nodeType!==1){return}while(y!=t){if(q[y.nodeName]){return}y=y.parentNode}s=o.getRng();if(s.setStart){z=s.startContainer;D=s.startOffset;F=s.endContainer;E=s.endOffset}else{if(s.item){s=m.getDoc().body.createTextRange();s.moveToElementText(s.item(0))}tmpRng=s.duplicate();tmpRng.collapse(true);D=tmpRng.move("character",B)*-1;if(!tmpRng.collapsed){tmpRng=s.duplicate();tmpRng.collapse(false);E=(tmpRng.move("character",B)*-1)-D}}for(y=t.firstChild;y;y){if(y.nodeType===3||(y.nodeType==1&&!q[y.nodeName])){if(!x){x=u.create(p.forced_root_block);y.parentNode.insertBefore(x,y)}A=y;y=y.nextSibling;x.appendChild(A)}else{x=null;y=y.nextSibling}}if(s.setStart){s.setStart(z,D);s.setEnd(F,E);o.setRng(s)}else{try{s=m.getDoc().body.createTextRange();s.moveToElementText(t);s.collapse(true);s.moveStart("character",D);if(E>0){s.moveEnd("character",E)}s.select()}catch(C){}}m.nodeChanged()}m.onKeyUp.add(v);m.onClick.add(v)}if(p.force_br_newlines){if(c){m.onKeyPress.add(function(s,t){var x;if(t.keyCode==13&&o.getNode().nodeName!="LI"){o.setContent('<br id="__" /> ',{format:"raw"});x=u.get("__");x.removeAttribute("id");o.select(x);o.collapse();return j.cancel(t)}})}}if(p.force_p_newlines){if(!c){m.onKeyPress.add(function(s,t){if(t.keyCode==13&&!t.shiftKey&&!n.insertPara(t)){j.cancel(t)}})}else{l.addUnload(function(){n._previousFormats=0});m.onKeyPress.add(function(s,t){n._previousFormats=0;if(t.keyCode==13&&!t.shiftKey&&s.selection.isCollapsed()&&p.keep_styles){n._previousFormats=k(s.selection.getStart())}});m.onKeyUp.add(function(t,y){if(y.keyCode==13&&!y.shiftKey){var x=t.selection.getStart(),s=n._previousFormats;if(!x.hasChildNodes()&&s){x=u.getParent(x,u.isBlock);if(x&&x.nodeName!="LI"){x.innerHTML="";if(n._previousFormats){x.appendChild(s.wrapper);s.inner.innerHTML="\uFEFF"}else{x.innerHTML="\uFEFF"}o.select(x,1);o.collapse(true);t.getDoc().execCommand("Delete",false,null);n._previousFormats=0}}}})}if(a){m.onKeyDown.add(function(s,t){if((t.keyCode==8||t.keyCode==46)&&!t.shiftKey){n.backspaceDelete(t,t.keyCode==8)}})}}if(l.isWebKit){function r(t){var s=o.getRng(),x,A=u.create("div",null," "),z,y=u.getViewPort(t.getWin()).h;s.insertNode(x=u.create("br"));s.setStartAfter(x);s.setEndAfter(x);o.setRng(s);if(o.getSel().focusNode==x.previousSibling){o.select(u.insertAfter(u.doc.createTextNode("\u00a0"),x));o.collapse(d)}u.insertAfter(A,x);z=u.getPos(A).y;u.remove(A);if(z>y){t.getWin().scrollTo(0,z)}}m.onKeyPress.add(function(s,t){if(t.keyCode==13&&(t.shiftKey||(p.force_br_newlines&&!u.getParent(o.getNode(),"h1,h2,h3,h4,h5,h6,ol,ul")))){r(s);j.cancel(t)}})}if(c){if(p.element!="P"){m.onKeyPress.add(function(s,t){n.lastElm=o.getNode().nodeName});m.onKeyUp.add(function(t,x){var z,y=o.getNode(),s=t.getBody();if(s.childNodes.length===1&&y.nodeName=="P"){y=u.rename(y,p.element);o.select(y);o.collapse();t.nodeChanged()}else{if(x.keyCode==13&&!x.shiftKey&&n.lastElm!="P"){z=u.getParent(y,"p");if(z){u.rename(z,p.element);t.nodeChanged()}}}})}}},getParentBlock:function(o){var m=this.dom;return m.getParent(o,m.isBlock)},insertPara:function(Q){var E=this,v=E.editor,M=v.dom,R=v.getDoc(),V=v.settings,F=v.selection.getSel(),G=F.getRangeAt(0),U=R.body;var J,K,H,O,N,q,o,u,z,m,C,T,p,x,I,L=M.getViewPort(v.getWin()),B,D,A;v.undoManager.beforeChange();J=R.createRange();J.setStart(F.anchorNode,F.anchorOffset);J.collapse(d);K=R.createRange();K.setStart(F.focusNode,F.focusOffset);K.collapse(d);H=J.compareBoundaryPoints(J.START_TO_END,K)<0;O=H?F.anchorNode:F.focusNode;N=H?F.anchorOffset:F.focusOffset;q=H?F.focusNode:F.anchorNode;o=H?F.focusOffset:F.anchorOffset;if(O===q&&/^(TD|TH)$/.test(O.nodeName)){if(O.firstChild.nodeName=="BR"){M.remove(O.firstChild)}if(O.childNodes.length==0){v.dom.add(O,V.element,null,"<br />");T=v.dom.add(O,V.element,null,"<br />")}else{I=O.innerHTML;O.innerHTML="";v.dom.add(O,V.element,null,I);T=v.dom.add(O,V.element,null,"<br />")}G=R.createRange();G.selectNodeContents(T);G.collapse(1);v.selection.setRng(G);return g}if(O==U&&q==U&&U.firstChild&&v.dom.isBlock(U.firstChild)){O=q=O.firstChild;N=o=0;J=R.createRange();J.setStart(O,0);K=R.createRange();K.setStart(q,0)}if(!R.body.hasChildNodes()){R.body.appendChild(M.create("br"))}O=O.nodeName=="HTML"?R.body:O;O=O.nodeName=="BODY"?O.firstChild:O;q=q.nodeName=="HTML"?R.body:q;q=q.nodeName=="BODY"?q.firstChild:q;u=E.getParentBlock(O);z=E.getParentBlock(q);m=u?u.nodeName:V.element;if(I=E.dom.getParent(u,"li,pre")){if(I.nodeName=="LI"){return e(v.selection,E.dom,I)}return d}if(u&&(u.nodeName=="CAPTION"||/absolute|relative|fixed/gi.test(M.getStyle(u,"position",1)))){m=V.element;u=null}if(z&&(z.nodeName=="CAPTION"||/absolute|relative|fixed/gi.test(M.getStyle(u,"position",1)))){m=V.element;z=null}if(/(TD|TABLE|TH|CAPTION)/.test(m)||(u&&m=="DIV"&&/left|right/gi.test(M.getStyle(u,"float",1)))){m=V.element;u=z=null}C=(u&&u.nodeName==m)?u.cloneNode(0):v.dom.create(m);T=(z&&z.nodeName==m)?z.cloneNode(0):v.dom.create(m);T.removeAttribute("id");if(/^(H[1-6])$/.test(m)&&f(G,u)){T=v.dom.create(V.element)}I=p=O;do{if(I==U||I.nodeType==9||E.dom.isBlock(I)||/(TD|TABLE|TH|CAPTION)/.test(I.nodeName)){break}p=I}while((I=I.previousSibling?I.previousSibling:I.parentNode));I=x=q;do{if(I==U||I.nodeType==9||E.dom.isBlock(I)||/(TD|TABLE|TH|CAPTION)/.test(I.nodeName)){break}x=I}while((I=I.nextSibling?I.nextSibling:I.parentNode));if(p.nodeName==m){J.setStart(p,0)}else{J.setStartBefore(p)}J.setEnd(O,N);C.appendChild(J.cloneContents()||R.createTextNode(""));try{K.setEndAfter(x)}catch(P){}K.setStart(q,o);T.appendChild(K.cloneContents()||R.createTextNode(""));G=R.createRange();if(!p.previousSibling&&p.parentNode.nodeName==m){G.setStartBefore(p.parentNode)}else{if(J.startContainer.nodeName==m&&J.startOffset==0){G.setStartBefore(J.startContainer)}else{G.setStart(J.startContainer,J.startOffset)}}if(!x.nextSibling&&x.parentNode.nodeName==m){G.setEndAfter(x.parentNode)}else{G.setEnd(K.endContainer,K.endOffset)}G.deleteContents();if(b){v.getWin().scrollTo(0,L.y)}if(C.firstChild&&C.firstChild.nodeName==m){C.innerHTML=C.firstChild.innerHTML}if(T.firstChild&&T.firstChild.nodeName==m){T.innerHTML=T.firstChild.innerHTML}function S(y,s){var r=[],X,W,t;y.innerHTML="";if(V.keep_styles){W=s;do{if(/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(W.nodeName)){X=W.cloneNode(g);M.setAttrib(X,"id","");r.push(X)}}while(W=W.parentNode)}if(r.length>0){for(t=r.length-1,X=y;t>=0;t--){X=X.appendChild(r[t])}r[0].innerHTML=b?"\u00a0":"<br />";return r[0]}else{y.innerHTML=b?"\u00a0":"<br />"}}if(M.isEmpty(C)){S(C,O)}if(M.isEmpty(T)){A=S(T,q)}if(b&&parseFloat(opera.version())<9.5){G.insertNode(C);G.insertNode(T)}else{G.insertNode(T);G.insertNode(C)}T.normalize();C.normalize();v.selection.select(T,true);v.selection.collapse(true);B=v.dom.getPos(T).y;if(B<L.y||B+25>L.y+L.h){v.getWin().scrollTo(0,B<L.y?B:B-L.h+25)}v.undoManager.add();return g},backspaceDelete:function(u,B){var C=this,s=C.editor,y=s.getBody(),q=s.dom,p,v=s.selection,o=v.getRng(),x=o.startContainer,p,z,A,m;if(!B&&o.collapsed&&x.nodeType==1&&o.startOffset==x.childNodes.length){m=new l.dom.TreeWalker(x.lastChild,x);for(p=x.lastChild;p;p=m.prev()){if(p.nodeType==3){o.setStart(p,p.nodeValue.length);o.collapse(true);v.setRng(o);return}}}if(x&&s.dom.isBlock(x)&&!/^(TD|TH)$/.test(x.nodeName)&&B){if(x.childNodes.length==0||(x.childNodes.length==1&&x.firstChild.nodeName=="BR")){p=x;while((p=p.previousSibling)&&!s.dom.isBlock(p)){}if(p){if(x!=y.firstChild){z=s.dom.doc.createTreeWalker(p,NodeFilter.SHOW_TEXT,null,g);while(A=z.nextNode()){p=A}o=s.getDoc().createRange();o.setStart(p,p.nodeValue?p.nodeValue.length:0);o.setEnd(p,p.nodeValue?p.nodeValue.length:0);v.setRng(o);s.dom.remove(x)}return j.cancel(u)}}}}})})(tinymce);(function(c){var b=c.DOM,a=c.dom.Event,d=c.each,e=c.extend;c.create("tinymce.ControlManager",{ControlManager:function(f,j){var h=this,g;j=j||{};h.editor=f;h.controls={};h.onAdd=new c.util.Dispatcher(h);h.onPostRender=new c.util.Dispatcher(h);h.prefix=j.prefix||f.id+"_";h._cls={};h.onPostRender.add(function(){d(h.controls,function(i){i.postRender()})})},get:function(f){return this.controls[this.prefix+f]||this.controls[f]},setActive:function(h,f){var g=null;if(g=this.get(h)){g.setActive(f)}return g},setDisabled:function(h,f){var g=null;if(g=this.get(h)){g.setDisabled(f)}return g},add:function(g){var f=this;if(g){f.controls[g.id]=g;f.onAdd.dispatch(g,f)}return g},createControl:function(i){var h,g=this,f=g.editor;d(f.plugins,function(j){if(j.createControl){h=j.createControl(i,g);if(h){return false}}});switch(i){case"|":case"separator":return g.createSeparator()}if(!h&&f.buttons&&(h=f.buttons[i])){return g.createButton(i,h)}return g.add(h)},createDropMenu:function(f,n,h){var m=this,i=m.editor,j,g,k,l;n=e({"class":"mceDropDown",constrain:i.settings.constrain_menus},n);n["class"]=n["class"]+" "+i.getParam("skin")+"Skin";if(k=i.getParam("skin_variant")){n["class"]+=" "+i.getParam("skin")+"Skin"+k.substring(0,1).toUpperCase()+k.substring(1)}f=m.prefix+f;l=h||m._cls.dropmenu||c.ui.DropMenu;j=m.controls[f]=new l(f,n);j.onAddItem.add(function(r,q){var p=q.settings;p.title=i.getLang(p.title,p.title);if(!p.onclick){p.onclick=function(o){if(p.cmd){i.execCommand(p.cmd,p.ui||false,p.value)}}}});i.onRemove.add(function(){j.destroy()});if(c.isIE){j.onShowMenu.add(function(){i.focus();g=i.selection.getBookmark(1)});j.onHideMenu.add(function(){if(g){i.selection.moveToBookmark(g);g=0}})}return m.add(j)},createListBox:function(f,n,h){var l=this,j=l.editor,i,k,m;if(l.get(f)){return null}n.title=j.translate(n.title);n.scope=n.scope||j;if(!n.onselect){n.onselect=function(o){j.execCommand(n.cmd,n.ui||false,o||n.value)}}n=e({title:n.title,"class":"mce_"+f,scope:n.scope,control_manager:l},n);f=l.prefix+f;function g(o){return o.settings.use_accessible_selects&&!c.isGecko}if(j.settings.use_native_selects||g(j)){k=new c.ui.NativeListBox(f,n)}else{m=h||l._cls.listbox||c.ui.ListBox;k=new m(f,n,j)}l.controls[f]=k;if(c.isWebKit){k.onPostRender.add(function(p,o){a.add(o,"mousedown",function(){j.bookmark=j.selection.getBookmark(1)});a.add(o,"focus",function(){j.selection.moveToBookmark(j.bookmark);j.bookmark=null})})}if(k.hideMenu){j.onMouseDown.add(k.hideMenu,k)}return l.add(k)},createButton:function(m,i,l){var h=this,g=h.editor,j,k,f;if(h.get(m)){return null}i.title=g.translate(i.title);i.label=g.translate(i.label);i.scope=i.scope||g;if(!i.onclick&&!i.menu_button){i.onclick=function(){g.execCommand(i.cmd,i.ui||false,i.value)}}i=e({title:i.title,"class":"mce_"+m,unavailable_prefix:g.getLang("unavailable",""),scope:i.scope,control_manager:h},i);m=h.prefix+m;if(i.menu_button){f=l||h._cls.menubutton||c.ui.MenuButton;k=new f(m,i,g);g.onMouseDown.add(k.hideMenu,k)}else{f=h._cls.button||c.ui.Button;k=new f(m,i,g)}return h.add(k)},createMenuButton:function(h,f,g){f=f||{};f.menu_button=1;return this.createButton(h,f,g)},createSplitButton:function(m,i,l){var h=this,g=h.editor,j,k,f;if(h.get(m)){return null}i.title=g.translate(i.title);i.scope=i.scope||g;if(!i.onclick){i.onclick=function(n){g.execCommand(i.cmd,i.ui||false,n||i.value)}}if(!i.onselect){i.onselect=function(n){g.execCommand(i.cmd,i.ui||false,n||i.value)}}i=e({title:i.title,"class":"mce_"+m,scope:i.scope,control_manager:h},i);m=h.prefix+m;f=l||h._cls.splitbutton||c.ui.SplitButton;k=h.add(new f(m,i,g));g.onMouseDown.add(k.hideMenu,k);return k},createColorSplitButton:function(f,n,h){var l=this,j=l.editor,i,k,m,g;if(l.get(f)){return null}n.title=j.translate(n.title);n.scope=n.scope||j;if(!n.onclick){n.onclick=function(o){if(c.isIE){g=j.selection.getBookmark(1)}j.execCommand(n.cmd,n.ui||false,o||n.value)}}if(!n.onselect){n.onselect=function(o){j.execCommand(n.cmd,n.ui||false,o||n.value)}}n=e({title:n.title,"class":"mce_"+f,menu_class:j.getParam("skin")+"Skin",scope:n.scope,more_colors_title:j.getLang("more_colors")},n);f=l.prefix+f;m=h||l._cls.colorsplitbutton||c.ui.ColorSplitButton;k=new m(f,n,j);j.onMouseDown.add(k.hideMenu,k);j.onRemove.add(function(){k.destroy()});if(c.isIE){k.onShowMenu.add(function(){j.focus();g=j.selection.getBookmark(1)});k.onHideMenu.add(function(){if(g){j.selection.moveToBookmark(g);g=0}})}return l.add(k)},createToolbar:function(k,h,j){var i,g=this,f;k=g.prefix+k;f=j||g._cls.toolbar||c.ui.Toolbar;i=new f(k,h,g.editor);if(g.get(k)){return null}return g.add(i)},createToolbarGroup:function(k,h,j){var i,g=this,f;k=g.prefix+k;f=j||this._cls.toolbarGroup||c.ui.ToolbarGroup;i=new f(k,h,g.editor);if(g.get(k)){return null}return g.add(i)},createSeparator:function(g){var f=g||this._cls.separator||c.ui.Separator;return new f()},setControlType:function(g,f){return this._cls[g.toLowerCase()]=f},destroy:function(){d(this.controls,function(f){f.destroy()});this.controls=null}})})(tinymce);(function(d){var a=d.util.Dispatcher,e=d.each,c=d.isIE,b=d.isOpera;d.create("tinymce.WindowManager",{WindowManager:function(f){var g=this;g.editor=f;g.onOpen=new a(g);g.onClose=new a(g);g.params={};g.features={}},open:function(z,h){var v=this,k="",n,m,i=v.editor.settings.dialog_type=="modal",q,o,j,g=d.DOM.getViewPort(),r;z=z||{};h=h||{};o=b?g.w:screen.width;j=b?g.h:screen.height;z.name=z.name||"mc_"+new Date().getTime();z.width=parseInt(z.width||320);z.height=parseInt(z.height||240);z.resizable=true;z.left=z.left||parseInt(o/2)-(z.width/2);z.top=z.top||parseInt(j/2)-(z.height/2);h.inline=false;h.mce_width=z.width;h.mce_height=z.height;h.mce_auto_focus=z.auto_focus;if(i){if(c){z.center=true;z.help=false;z.dialogWidth=z.width+"px";z.dialogHeight=z.height+"px";z.scroll=z.scrollbars||false}}e(z,function(p,f){if(d.is(p,"boolean")){p=p?"yes":"no"}if(!/^(name|url)$/.test(f)){if(c&&i){k+=(k?";":"")+f+":"+p}else{k+=(k?",":"")+f+"="+p}}});v.features=z;v.params=h;v.onOpen.dispatch(v,z,h);r=z.url||z.file;r=d._addVer(r);try{if(c&&i){q=1;window.showModalDialog(r,window,k)}else{q=window.open(r,z.name,k)}}catch(l){}if(!q){alert(v.editor.getLang("popup_blocked"))}},close:function(f){f.close();this.onClose.dispatch(this)},createInstance:function(i,h,g,m,l,k){var j=d.resolve(i);return new j(h,g,m,l,k)},confirm:function(h,f,i,g){g=g||window;f.call(i||this,g.confirm(this._decode(this.editor.getLang(h,h))))},alert:function(h,f,j,g){var i=this;g=g||window;g.alert(i._decode(i.editor.getLang(h,h)));if(f){f.call(j||i)}},resizeBy:function(f,g,h){h.resizeBy(f,g)},_decode:function(f){return d.DOM.decode(f).replace(/\\n/g,"\n")}})}(tinymce));(function(a){a.Formatter=function(V){var M={},O=a.each,c=V.dom,q=V.selection,t=a.dom.TreeWalker,K=new a.dom.RangeUtils(c),d=V.schema.isValidChild,F=c.isBlock,l=V.settings.forced_root_block,s=c.nodeIndex,E="\uFEFF",e=/^(src|href|style)$/,S=false,B=true,p,P={apply:[],remove:[]};function z(W){return W instanceof Array}function m(X,W){return c.getParents(X,W,c.getRoot())}function b(W){return W.nodeType===1&&(W.face==="mceinline"||W.style.fontFamily==="mceinline")}function R(W){return W?M[W]:M}function k(W,X){if(W){if(typeof(W)!=="string"){O(W,function(Z,Y){k(Y,Z)})}else{X=X.length?X:[X];O(X,function(Y){if(Y.deep===p){Y.deep=!Y.selector}if(Y.split===p){Y.split=!Y.selector||Y.inline}if(Y.remove===p&&Y.selector&&!Y.inline){Y.remove="none"}if(Y.selector&&Y.inline){Y.mixed=true;Y.block_expand=true}if(typeof(Y.classes)==="string"){Y.classes=Y.classes.split(/\s+/)}});M[W]=X}}}var i=function(X){var W;V.dom.getParent(X,function(Y){W=V.dom.getStyle(Y,"text-decoration");return W&&W!=="none"});return W};var I=function(W){var X;if(W.nodeType===1&&W.parentNode&&W.parentNode.nodeType===1){X=i(W.parentNode);if(V.dom.getStyle(W,"color")&&X){V.dom.setStyle(W,"text-decoration",X)}else{if(V.dom.getStyle(W,"textdecoration")===X){V.dom.setStyle(W,"text-decoration",null)}}}};function T(Z,ah,ac){var ad=R(Z),ai=ad[0],ag,X,af,ae=q.isCollapsed();function aa(am){var al=am.startContainer,ap=am.startOffset,ao,an;if(al.nodeType==1||al.nodeValue===""){al=al.nodeType==1?al.childNodes[ap]:al;if(al){ao=new t(al,al.parentNode);for(an=ao.current();an;an=ao.next()){if(an.nodeType==3&&!f(an)){am.setStart(an,0);break}}}}return am}function W(am,al){al=al||ai;if(am){if(al.onformat){al.onformat(am,al,ah,ac)}O(al.styles,function(ao,an){c.setStyle(am,an,r(ao,ah))});O(al.attributes,function(ao,an){c.setAttrib(am,an,r(ao,ah))});O(al.classes,function(an){an=r(an,ah);if(!c.hasClass(am,an)){c.addClass(am,an)}})}}function ab(){function an(au,ar){var at=new t(ar);for(ac=at.current();ac;ac=at.prev()){if(ac.childNodes.length>1||ac==au){return ac}}}var am=V.selection.getRng();var aq=am.startContainer;var al=am.endContainer;if(aq!=al&&am.endOffset==0){var ap=an(aq,al);var ao=ap.nodeType==3?ap.length:ap.childNodes.length;am.setEnd(ap,ao)}return am}function Y(ao,au,ar,aq,am){var al=[],an=-1,at,aw=-1,ap=-1,av;O(ao.childNodes,function(ay,ax){if(ay.nodeName==="UL"||ay.nodeName==="OL"){an=ax;at=ay;return false}});O(ao.childNodes,function(ay,ax){if(ay.nodeName==="SPAN"&&c.getAttrib(ay,"data-mce-type")=="bookmark"){if(ay.id==au.id+"_start"){aw=ax}else{if(ay.id==au.id+"_end"){ap=ax}}}});if(an<=0||(aw<an&&ap>an)){O(a.grep(ao.childNodes),am);return 0}else{av=ar.cloneNode(S);O(a.grep(ao.childNodes),function(ay,ax){if((aw<an&&ax<an)||(aw>an&&ax>an)){al.push(ay);ay.parentNode.removeChild(ay)}});if(aw<an){ao.insertBefore(av,at)}else{if(aw>an){ao.insertBefore(av,at.nextSibling)}}aq.push(av);O(al,function(ax){av.appendChild(ax)});return av}}function aj(am,ao){var al=[],ap,an;ap=ai.inline||ai.block;an=c.create(ap);W(an);K.walk(am,function(aq){var ar;function at(au){var ax=au.nodeName.toLowerCase(),aw=au.parentNode.nodeName.toLowerCase(),av;if(g(ax,"br")){ar=0;if(ai.block){c.remove(au)}return}if(ai.wrapper&&x(au,Z,ah)){ar=0;return}if(ai.block&&!ai.wrapper&&G(ax)){au=c.rename(au,ap);W(au);al.push(au);ar=0;return}if(ai.selector){O(ad,function(ay){if("collapsed" in ay&&ay.collapsed!==ae){return}if(c.is(au,ay.selector)&&!b(au)){W(au,ay);av=true}});if(!ai.inline||av){ar=0;return}}if(d(ap,ax)&&d(aw,ap)&&!(au.nodeType===3&&au.nodeValue.length===1&&au.nodeValue.charCodeAt(0)===65279)){if(!ar){ar=an.cloneNode(S);au.parentNode.insertBefore(ar,au);al.push(ar)}ar.appendChild(au)}else{if(ax=="li"&&ao){ar=Y(au,ao,an,al,at)}else{ar=0;O(a.grep(au.childNodes),at);ar=0}}}O(aq,at)});if(ai.wrap_links===false){O(al,function(aq){function ar(aw){var av,au,at;if(aw.nodeName==="A"){au=an.cloneNode(S);al.push(au);at=a.grep(aw.childNodes);for(av=0;av<at.length;av++){au.appendChild(at[av])}aw.appendChild(au)}O(a.grep(aw.childNodes),ar)}ar(aq)})}O(al,function(at){var aq;function au(aw){var av=0;O(aw.childNodes,function(ax){if(!f(ax)&&!H(ax)){av++}});return av}function ar(av){var ax,aw;O(av.childNodes,function(ay){if(ay.nodeType==1&&!H(ay)&&!b(ay)){ax=ay;return S}});if(ax&&h(ax,ai)){aw=ax.cloneNode(S);W(aw);c.replace(aw,av,B);c.remove(ax,1)}return aw||av}aq=au(at);if((al.length>1||!F(at))&&aq===0){c.remove(at,1);return}if(ai.inline||ai.wrapper){if(!ai.exact&&aq===1){at=ar(at)}O(ad,function(av){O(c.select(av.inline,at),function(ax){var aw;if(av.wrap_links===false){aw=ax.parentNode;do{if(aw.nodeName==="A"){return}}while(aw=aw.parentNode)}U(av,ah,ax,av.exact?ax:null)})});if(x(at.parentNode,Z,ah)){c.remove(at,1);at=0;return B}if(ai.merge_with_parents){c.getParent(at.parentNode,function(av){if(x(av,Z,ah)){c.remove(at,1);at=0;return B}})}if(at&&ai.merge_siblings!==false){at=u(C(at),at);at=u(at,C(at,B))}}})}if(ai){if(ac){X=c.createRng();X.setStartBefore(ac);X.setEndAfter(ac);aj(o(X,ad))}else{if(!ae||!ai.inline||c.select("td.mceSelected,th.mceSelected").length){var ak=V.selection.getNode();V.selection.setRng(ab());ag=q.getBookmark();aj(o(q.getRng(B),ad),ag);if(ai.styles&&(ai.styles.color||ai.styles.textDecoration)){a.walk(ak,I,"childNodes");I(ak)}q.moveToBookmark(ag);q.setRng(aa(q.getRng(B)));V.nodeChanged()}else{Q("apply",Z,ah)}}}}function A(Y,ah,ab){var ac=R(Y),aj=ac[0],ag,af,X;function aa(am){var al=am.startContainer,ar=am.startOffset,aq,ap,an,ao;if(al.nodeType==3&&ar>=al.nodeValue.length-1){al=al.parentNode;ar=s(al)+1}if(al.nodeType==1){an=al.childNodes;al=an[Math.min(ar,an.length-1)];aq=new t(al);if(ar>an.length-1){aq.next()}for(ap=aq.current();ap;ap=aq.next()){if(ap.nodeType==3&&!f(ap)){ao=c.create("a",null,E);ap.parentNode.insertBefore(ao,ap);am.setStart(ap,0);q.setRng(am);c.remove(ao);return}}}}function Z(ao){var an,am,al;an=a.grep(ao.childNodes);for(am=0,al=ac.length;am<al;am++){if(U(ac[am],ah,ao,ao)){break}}if(aj.deep){for(am=0,al=an.length;am<al;am++){Z(an[am])}}}function ad(al){var am;O(m(al.parentNode).reverse(),function(an){var ao;if(!am&&an.id!="_start"&&an.id!="_end"){ao=x(an,Y,ah);if(ao&&ao.split!==false){am=an}}});return am}function W(ao,al,aq,au){var av,at,ar,an,ap,am;if(ao){am=ao.parentNode;for(av=al.parentNode;av&&av!=am;av=av.parentNode){at=av.cloneNode(S);for(ap=0;ap<ac.length;ap++){if(U(ac[ap],ah,at,at)){at=0;break}}if(at){if(ar){at.appendChild(ar)}if(!an){an=at}ar=at}}if(au&&(!aj.mixed||!F(ao))){al=c.split(ao,al)}if(ar){aq.parentNode.insertBefore(ar,aq);an.appendChild(aq)}}return al}function ai(al){return W(ad(al),al,al,true)}function ae(an){var am=c.get(an?"_start":"_end"),al=am[an?"firstChild":"lastChild"];if(H(al)){al=al[an?"firstChild":"lastChild"]}c.remove(am,true);return al}function ak(al){var am,an;al=o(al,ac,B);if(aj.split){am=J(al,B);an=J(al);if(am!=an){am=N(am,"span",{id:"_start","data-mce-type":"bookmark"});an=N(an,"span",{id:"_end","data-mce-type":"bookmark"});ai(am);ai(an);am=ae(B);an=ae()}else{am=an=ai(am)}al.startContainer=am.parentNode;al.startOffset=s(am);al.endContainer=an.parentNode;al.endOffset=s(an)+1}K.walk(al,function(ao){O(ao,function(ap){Z(ap);if(ap.nodeType===1&&V.dom.getStyle(ap,"text-decoration")==="underline"&&ap.parentNode&&i(ap.parentNode)==="underline"){U({deep:false,exact:true,inline:"span",styles:{textDecoration:"underline"}},null,ap)}})})}if(ab){X=c.createRng();X.setStartBefore(ab);X.setEndAfter(ab);ak(X);return}if(!q.isCollapsed()||!aj.inline||c.select("td.mceSelected,th.mceSelected").length){ag=q.getBookmark();ak(q.getRng(B));q.moveToBookmark(ag);if(aj.inline&&j(Y,ah,q.getStart())){aa(q.getRng(true))}V.nodeChanged()}else{Q("remove",Y,ah)}}function D(X,Z,Y){var W=R(X);if(j(X,Z,Y)&&(!("toggle" in W[0])||W[0]["toggle"])){A(X,Z,Y)}else{T(X,Z,Y)}}function x(X,W,ac,aa){var Y=R(W),ad,ab,Z;function ae(ai,ak,al){var ah,aj,af=ak[al],ag;if(ak.onmatch){return ak.onmatch(ai,ak,al)}if(af){if(af.length===p){for(ah in af){if(af.hasOwnProperty(ah)){if(al==="attributes"){aj=c.getAttrib(ai,ah)}else{aj=L(ai,ah)}if(aa&&!aj&&!ak.exact){return}if((!aa||ak.exact)&&!g(aj,r(af[ah],ac))){return}}}}else{for(ag=0;ag<af.length;ag++){if(al==="attributes"?c.getAttrib(ai,af[ag]):L(ai,af[ag])){return ak}}}}return ak}if(Y&&X){for(ab=0;ab<Y.length;ab++){ad=Y[ab];if(h(X,ad)&&ae(X,ad,"attributes")&&ae(X,ad,"styles")){if(Z=ad.classes){for(ab=0;ab<Z.length;ab++){if(!c.hasClass(X,Z[ab])){return}}}return ad}}}}function j(Y,ab,aa){var X,Z;function W(ac){ac=c.getParent(ac,function(ad){return !!x(ad,Y,ab,true)});return x(ac,Y,ab)}if(aa){return W(aa)}if(q.isCollapsed()){for(Z=P.apply.length-1;Z>=0;Z--){if(P.apply[Z].name==Y){return true}}for(Z=P.remove.length-1;Z>=0;Z--){if(P.remove[Z].name==Y){return false}}return W(q.getNode())}aa=q.getNode();if(W(aa)){return B}X=q.getStart();if(X!=aa){if(W(X)){return B}}return S}function v(ad,ac){var aa,ab=[],Z={},Y,X,W;if(q.isCollapsed()){for(X=0;X<ad.length;X++){for(Y=P.remove.length-1;Y>=0;Y--){W=ad[X];if(P.remove[Y].name==W){Z[W]=true;break}}}for(Y=P.apply.length-1;Y>=0;Y--){for(X=0;X<ad.length;X++){W=ad[X];if(!Z[W]&&P.apply[Y].name==W){Z[W]=true;ab.push(W)}}}}aa=q.getStart();c.getParent(aa,function(ag){var af,ae;for(af=0;af<ad.length;af++){ae=ad[af];if(!Z[ae]&&x(ag,ae,ac)){Z[ae]=true;ab.push(ae)}}});return ab}function y(aa){var ac=R(aa),Z,Y,ab,X,W;if(ac){Z=q.getStart();Y=m(Z);for(X=ac.length-1;X>=0;X--){W=ac[X].selector;if(!W){return B}for(ab=Y.length-1;ab>=0;ab--){if(c.is(Y[ab],W)){return B}}}}return S}a.extend(this,{get:R,register:k,apply:T,remove:A,toggle:D,match:j,matchAll:v,matchNode:x,canApply:y});function h(W,X){if(g(W,X.inline)){return B}if(g(W,X.block)){return B}if(X.selector){return c.is(W,X.selector)}}function g(X,W){X=X||"";W=W||"";X=""+(X.nodeName||X);W=""+(W.nodeName||W);return X.toLowerCase()==W.toLowerCase()}function L(X,W){var Y=c.getStyle(X,W);if(W=="color"||W=="backgroundColor"){Y=c.toHex(Y)}if(W=="fontWeight"&&Y==700){Y="bold"}return""+Y}function r(W,X){if(typeof(W)!="string"){W=W(X)}else{if(X){W=W.replace(/%(\w+)/g,function(Z,Y){return X[Y]||Z})}}return W}function f(W){return W&&W.nodeType===3&&/^([\s\r\n]+|)$/.test(W.nodeValue)}function N(Y,X,W){var Z=c.create(X,W);Y.parentNode.insertBefore(Z,Y);Z.appendChild(Y);return Z}function o(W,ag,Z){var Y=W.startContainer,ad=W.startOffset,aj=W.endContainer,ae=W.endOffset,ai,af,ac;function ah(am,an,ak,al){var ao,ap;al=al||c.getRoot();for(;;){ao=am.parentNode;if(ao==al||(!ag[0].block_expand&&F(ao))){return am}for(ai=ao[an];ai&&ai!=am;ai=ai[ak]){if(ai.nodeType==1&&!H(ai)){return am}if(ai.nodeType==3&&!f(ai)){return am}}am=am.parentNode}return am}function ab(ak,al){if(al===p){al=ak.nodeType===3?ak.length:ak.childNodes.length}while(ak&&ak.hasChildNodes()){ak=ak.childNodes[al];if(ak){al=ak.nodeType===3?ak.length:ak.childNodes.length}}return{node:ak,offset:al}}if(Y.nodeType==1&&Y.hasChildNodes()){af=Y.childNodes.length-1;Y=Y.childNodes[ad>af?af:ad];if(Y.nodeType==3){ad=0}}if(aj.nodeType==1&&aj.hasChildNodes()){af=aj.childNodes.length-1;aj=aj.childNodes[ae>af?af:ae-1];if(aj.nodeType==3){ae=aj.nodeValue.length}}if(H(Y.parentNode)){Y=Y.parentNode}if(H(Y)){Y=Y.nextSibling||Y}if(H(aj.parentNode)){ae=c.nodeIndex(aj);aj=aj.parentNode}if(H(aj)&&aj.previousSibling){aj=aj.previousSibling;ae=aj.length}if(ag[0].inline){ac=ab(aj,ae);if(ac.node){while(ac.node&&ac.offset===0&&ac.node.previousSibling){ac=ab(ac.node.previousSibling)}if(ac.node&&ac.offset>0&&ac.node.nodeType===3&&ac.node.nodeValue.charAt(ac.offset-1)===" "){if(ac.offset>1){aj=ac.node;aj.splitText(ac.offset-1)}else{if(ac.node.previousSibling){aj=ac.node.previousSibling}}}}}if(ag[0].inline||ag[0].block_expand){Y=ah(Y,"firstChild","nextSibling");aj=ah(aj,"lastChild","previousSibling")}if(ag[0].selector&&ag[0].expand!==S&&!ag[0].inline){function aa(al,ak){var am,an,ap,ao;if(al.nodeType==3&&al.nodeValue.length==0&&al[ak]){al=al[ak]}am=m(al);for(an=0;an<am.length;an++){for(ap=0;ap<ag.length;ap++){ao=ag[ap];if("collapsed" in ao&&ao.collapsed!==W.collapsed){continue}if(c.is(am[an],ao.selector)){return am[an]}}}return al}Y=aa(Y,"previousSibling");aj=aa(aj,"nextSibling")}if(ag[0].block||ag[0].selector){function X(al,ak,an){var am;if(!ag[0].wrapper){am=c.getParent(al,ag[0].block)}if(!am){am=c.getParent(al.nodeType==3?al.parentNode:al,F)}if(am&&ag[0].wrapper){am=m(am,"ul,ol").reverse()[0]||am}if(!am){am=al;while(am[ak]&&!F(am[ak])){am=am[ak];if(g(am,"br")){break}}}return am||al}Y=X(Y,"previousSibling");aj=X(aj,"nextSibling");if(ag[0].block){if(!F(Y)){Y=ah(Y,"firstChild","nextSibling")}if(!F(aj)){aj=ah(aj,"lastChild","previousSibling")}}}if(Y.nodeType==1){ad=s(Y);Y=Y.parentNode}if(aj.nodeType==1){ae=s(aj)+1;aj=aj.parentNode}return{startContainer:Y,startOffset:ad,endContainer:aj,endOffset:ae}}function U(ac,ab,Z,W){var Y,X,aa;if(!h(Z,ac)){return S}if(ac.remove!="all"){O(ac.styles,function(ae,ad){ae=r(ae,ab);if(typeof(ad)==="number"){ad=ae;W=0}if(!W||g(L(W,ad),ae)){c.setStyle(Z,ad,"")}aa=1});if(aa&&c.getAttrib(Z,"style")==""){Z.removeAttribute("style");Z.removeAttribute("data-mce-style")}O(ac.attributes,function(af,ad){var ae;af=r(af,ab);if(typeof(ad)==="number"){ad=af;W=0}if(!W||g(c.getAttrib(W,ad),af)){if(ad=="class"){af=c.getAttrib(Z,ad);if(af){ae="";O(af.split(/\s+/),function(ag){if(/mce\w+/.test(ag)){ae+=(ae?" ":"")+ag}});if(ae){c.setAttrib(Z,ad,ae);return}}}if(ad=="class"){Z.removeAttribute("className")}if(e.test(ad)){Z.removeAttribute("data-mce-"+ad)}Z.removeAttribute(ad)}});O(ac.classes,function(ad){ad=r(ad,ab);if(!W||c.hasClass(W,ad)){c.removeClass(Z,ad)}});X=c.getAttribs(Z);for(Y=0;Y<X.length;Y++){if(X[Y].nodeName.indexOf("_")!==0){return S}}}if(ac.remove!="none"){n(Z,ac);return B}}function n(Y,Z){var W=Y.parentNode,X;if(Z.block){if(!l){function aa(ac,ab,ad){ac=C(ac,ab,ad);return !ac||(ac.nodeName=="BR"||F(ac))}if(F(Y)&&!F(W)){if(!aa(Y,S)&&!aa(Y.firstChild,B,1)){Y.insertBefore(c.create("br"),Y.firstChild)}if(!aa(Y,B)&&!aa(Y.lastChild,S,1)){Y.appendChild(c.create("br"))}}}else{if(W==c.getRoot()){if(!Z.list_block||!g(Y,Z.list_block)){O(a.grep(Y.childNodes),function(ab){if(d(l,ab.nodeName.toLowerCase())){if(!X){X=N(ab,l)}else{X.appendChild(ab)}}else{X=0}})}}}}if(Z.selector&&Z.inline&&!g(Z.inline,Y)){return}c.remove(Y,1)}function C(X,W,Y){if(X){W=W?"nextSibling":"previousSibling";for(X=Y?X:X[W];X;X=X[W]){if(X.nodeType==1||!f(X)){return X}}}}function H(W){return W&&W.nodeType==1&&W.getAttribute("data-mce-type")=="bookmark"}function u(aa,Z){var W,Y,X;function ac(af,ae){if(af.nodeName!=ae.nodeName){return S}function ad(ah){var ai={};O(c.getAttribs(ah),function(aj){var ak=aj.nodeName.toLowerCase();if(ak.indexOf("_")!==0&&ak!=="style"){ai[ak]=c.getAttrib(ah,ak)}});return ai}function ag(ak,aj){var ai,ah;for(ah in ak){if(ak.hasOwnProperty(ah)){ai=aj[ah];if(ai===p){return S}if(ak[ah]!=ai){return S}delete aj[ah]}}for(ah in aj){if(aj.hasOwnProperty(ah)){return S}}return B}if(!ag(ad(af),ad(ae))){return S}if(!ag(c.parseStyle(c.getAttrib(af,"style")),c.parseStyle(c.getAttrib(ae,"style")))){return S}return B}if(aa&&Z){function ab(ae,ad){for(Y=ae;Y;Y=Y[ad]){if(Y.nodeType==3&&Y.nodeValue.length!==0){return ae}if(Y.nodeType==1&&!H(Y)){return Y}}return ae}aa=ab(aa,"previousSibling");Z=ab(Z,"nextSibling");if(ac(aa,Z)){for(Y=aa.nextSibling;Y&&Y!=Z;){X=Y;Y=Y.nextSibling;aa.appendChild(X)}c.remove(Z);O(a.grep(Z.childNodes),function(ad){aa.appendChild(ad)});return aa}}return Z}function G(W){return/^(h[1-6]|p|div|pre|address|dl|dt|dd)$/.test(W)}function J(X,aa){var W,Z,Y;W=X[aa?"startContainer":"endContainer"];Z=X[aa?"startOffset":"endOffset"];if(W.nodeType==1){Y=W.childNodes.length-1;if(!aa&&Z){Z--}W=W.childNodes[Z>Y?Y:Z]}return W}function Q(ad,Y,ac){var aa,X=P[ad],ae=P[ad=="apply"?"remove":"apply"];function af(){return P.apply.length||P.remove.length}function ab(){P.apply=[];P.remove=[]}function ag(ah){O(P.apply.reverse(),function(ai){T(ai.name,ai.vars,ah);if(ai.name==="forecolor"&&ai.vars.value){I(ah.parentNode)}});O(P.remove.reverse(),function(ai){A(ai.name,ai.vars,ah)});c.remove(ah,1);ab()}for(aa=X.length-1;aa>=0;aa--){if(X[aa].name==Y){return}}X.push({name:Y,vars:ac});for(aa=ae.length-1;aa>=0;aa--){if(ae[aa].name==Y){ae.splice(aa,1)}}if(af()){V.getDoc().execCommand("FontName",false,"mceinline");P.lastRng=q.getRng();O(c.select("font,span"),function(ai){var ah;if(b(ai)){ah=q.getBookmark();ag(ai);q.moveToBookmark(ah);V.nodeChanged()}});if(!P.isListening&&af()){P.isListening=true;function W(ai,aj){var ah=c.createRng();ag(ai);ah.setStart(aj,aj.nodeValue.length);ah.setEnd(aj,aj.nodeValue.length);q.setRng(ah);V.nodeChanged()}var Z=false;O("onKeyDown,onKeyUp,onKeyPress,onMouseUp".split(","),function(ah){V[ah].addToTop(function(ai,al){if(al.keyCode==13&&!al.shiftKey){Z=true;return}if(af()&&!a.dom.RangeUtils.compareRanges(P.lastRng,q.getRng())){var aj=false;O(c.select("font,span"),function(ao){var ap,an;if(b(ao)){aj=true;ap=ao.firstChild;while(ap&&ap.nodeType!=3){ap=ap.firstChild}if(ap){W(ao,ap)}else{c.remove(ao)}}});if(Z&&!aj){var ak=q.getNode();var am=ak;while(am&&am.nodeType!=3){am=am.firstChild}if(am){ak=am.parentNode;while(!F(ak)){ak=ak.parentNode}W(ak,am)}}if(al.type=="keyup"||al.type=="mouseup"){ab();Z=false}}})})}}}}})(tinymce);tinymce.onAddEditor.add(function(e,a){var d,h,g,c=a.settings;if(c.inline_styles){h=e.explode(c.font_size_style_values);function b(j,i){e.each(i,function(l,k){if(l){g.setStyle(j,k,l)}});g.rename(j,"span")}d={font:function(j,i){b(i,{backgroundColor:i.style.backgroundColor,color:i.color,fontFamily:i.face,fontSize:h[parseInt(i.size)-1]})},u:function(j,i){b(i,{textDecoration:"underline"})},strike:function(j,i){b(i,{textDecoration:"line-through"})}};function f(i,j){g=i.dom;if(c.convert_fonts_to_spans){e.each(g.select("font,u,strike",j.node),function(k){d[k.nodeName.toLowerCase()](a.dom,k)})}}a.onPreProcess.add(f);a.onSetContent.add(f);a.onInit.add(function(){a.selection.onSetContent.add(f)})}}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/tiny_mce_popup.js b/src/static/org_glizy/assets/js/tiny_mce/tiny_mce_popup.js new file mode 100644 index 0000000..f859d24 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/tiny_mce_popup.js @@ -0,0 +1,5 @@ + +// Uncomment and change this document.domain value if you are loading the script cross subdomains +// document.domain = 'moxiecode.com'; + +var tinymce=null,tinyMCEPopup,tinyMCE;tinyMCEPopup={init:function(){var b=this,a,c;a=b.getWin();tinymce=a.tinymce;tinyMCE=a.tinyMCE;b.editor=tinymce.EditorManager.activeEditor;b.params=b.editor.windowManager.params;b.features=b.editor.windowManager.features;b.dom=b.editor.windowManager.createInstance("tinymce.dom.DOMUtils",document);if(b.features.popup_css!==false){b.dom.loadCSS(b.features.popup_css||b.editor.settings.popup_css)}b.listeners=[];b.onInit={add:function(e,d){b.listeners.push({func:e,scope:d})}};b.isWindow=!b.getWindowArg("mce_inline");b.id=b.getWindowArg("mce_window_id");b.editor.windowManager.onOpen.dispatch(b.editor.windowManager,window)},getWin:function(){return(!window.frameElement&&window.dialogArguments)||opener||parent||top},getWindowArg:function(c,b){var a=this.params[c];return tinymce.is(a)?a:b},getParam:function(b,a){return this.editor.getParam(b,a)},getLang:function(b,a){return this.editor.getLang(b,a)},execCommand:function(d,c,e,b){b=b||{};b.skip_focus=1;this.restoreSelection();return this.editor.execCommand(d,c,e,b)},resizeToInnerSize:function(){var a=this;setTimeout(function(){var b=a.dom.getViewPort(window);a.editor.windowManager.resizeBy(a.getWindowArg("mce_width")-b.w,a.getWindowArg("mce_height")-b.h,a.id||window)},10)},executeOnLoad:function(s){this.onInit.add(function(){eval(s)})},storeSelection:function(){this.editor.windowManager.bookmark=tinyMCEPopup.editor.selection.getBookmark(1)},restoreSelection:function(){var a=tinyMCEPopup;if(!a.isWindow&&tinymce.isIE){a.editor.selection.moveToBookmark(a.editor.windowManager.bookmark)}},requireLangPack:function(){var b=this,a=b.getWindowArg("plugin_url")||b.getWindowArg("theme_url");if(a&&b.editor.settings.language&&b.features.translate_i18n!==false&&b.editor.settings.language_load!==false){a+="/langs/"+b.editor.settings.language+"_dlg.js";if(!tinymce.ScriptLoader.isDone(a)){document.write('<script type="text/javascript" src="'+tinymce._addVer(a)+'"><\/script>');tinymce.ScriptLoader.markDone(a)}}},pickColor:function(b,a){this.execCommand("mceColorPicker",true,{color:document.getElementById(a).value,func:function(e){document.getElementById(a).value=e;try{document.getElementById(a).onchange()}catch(d){}}})},openBrowser:function(a,c,b){tinyMCEPopup.restoreSelection();this.editor.execCallback("file_browser_callback",a,document.getElementById(a).value,c,window)},confirm:function(b,a,c){this.editor.windowManager.confirm(b,a,c,window)},alert:function(b,a,c){this.editor.windowManager.alert(b,a,c,window)},close:function(){var a=this;function b(){a.editor.windowManager.close(window);tinymce=tinyMCE=a.editor=a.params=a.dom=a.dom.doc=null}if(tinymce.isOpera){a.getWin().setTimeout(b,0)}else{b()}},_restoreSelection:function(){var a=window.event.srcElement;if(a.nodeName=="INPUT"&&(a.type=="submit"||a.type=="button")){tinyMCEPopup.restoreSelection()}},_onDOMLoaded:function(){var b=tinyMCEPopup,d=document.title,e,c,a;if(b.domLoaded){return}b.domLoaded=1;if(b.features.translate_i18n!==false){c=document.body.innerHTML;if(tinymce.isIE){c=c.replace(/ (value|title|alt)=([^"][^\s>]+)/gi,' $1="$2"')}document.dir=b.editor.getParam("directionality","");if((a=b.editor.translate(c))&&a!=c){document.body.innerHTML=a}if((a=b.editor.translate(d))&&a!=d){document.title=d=a}}if(!b.editor.getParam("browser_preferred_colors",false)||!b.isWindow){b.dom.addClass(document.body,"forceColors")}document.body.style.display="";if(tinymce.isIE){document.attachEvent("onmouseup",tinyMCEPopup._restoreSelection);b.dom.add(b.dom.select("head")[0],"base",{target:"_self"})}b.restoreSelection();b.resizeToInnerSize();if(!b.isWindow){b.editor.windowManager.setTitle(window,d)}else{window.focus()}if(!tinymce.isIE&&!b.isWindow){tinymce.dom.Event._add(document,"focus",function(){b.editor.windowManager.focus(b.id)})}tinymce.each(b.dom.select("select"),function(f){f.onkeydown=tinyMCEPopup._accessHandler});tinymce.each(b.listeners,function(f){f.func.call(f.scope,b.editor)});if(b.getWindowArg("mce_auto_focus",true)){window.focus();tinymce.each(document.forms,function(g){tinymce.each(g.elements,function(f){if(b.dom.hasClass(f,"mceFocus")&&!f.disabled){f.focus();return false}})})}document.onkeyup=tinyMCEPopup._closeWinKeyHandler},_accessHandler:function(a){a=a||window.event;if(a.keyCode==13||a.keyCode==32){a=a.target||a.srcElement;if(a.onchange){a.onchange()}return tinymce.dom.Event.cancel(a)}},_closeWinKeyHandler:function(a){a=a||window.event;if(a.keyCode==27){tinyMCEPopup.close()}},_wait:function(){if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);tinyMCEPopup._onDOMLoaded()}});if(document.documentElement.doScroll&&window==window.top){(function(){if(tinyMCEPopup.domLoaded){return}try{document.documentElement.doScroll("left")}catch(a){setTimeout(arguments.callee,0);return}tinyMCEPopup._onDOMLoaded()})()}document.attachEvent("onload",tinyMCEPopup._onDOMLoaded)}else{if(document.addEventListener){window.addEventListener("DOMContentLoaded",tinyMCEPopup._onDOMLoaded,false);window.addEventListener("load",tinyMCEPopup._onDOMLoaded,false)}}}};tinyMCEPopup.init();tinyMCEPopup._wait(); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/tiny_mce_src.js b/src/static/org_glizy/assets/js/tiny_mce/tiny_mce_src.js new file mode 100644 index 0000000..358de47 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/tiny_mce_src.js @@ -0,0 +1,16479 @@ +(function(win) { + var whiteSpaceRe = /^\s*|\s*$/g, + undefined, isRegExpBroken = 'B'.replace(/A(.)|B/, '$1') === '$1'; + + var tinymce = { + majorVersion : '3', + + minorVersion : '4.6', + + releaseDate : '2011-09-29', + + _init : function() { + var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v; + + t.isOpera = win.opera && opera.buildNumber; + + t.isWebKit = /WebKit/.test(ua); + + t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName); + + t.isIE6 = t.isIE && /MSIE [56]/.test(ua); + + t.isIE7 = t.isIE && /MSIE [7]/.test(ua); + + t.isIE8 = t.isIE && /MSIE [8]/.test(ua); + + t.isIE9 = t.isIE && /MSIE [9]/.test(ua); + + t.isGecko = !t.isWebKit && /Gecko/.test(ua); + + t.isMac = ua.indexOf('Mac') != -1; + + t.isAir = /adobeair/i.test(ua); + + t.isIDevice = /(iPad|iPhone)/.test(ua); + + t.isIOS5 = t.isIDevice && ua.match(/AppleWebKit\/(\d*)/)[1]>=534; + + // TinyMCE .NET webcontrol might be setting the values for TinyMCE + if (win.tinyMCEPreInit) { + t.suffix = tinyMCEPreInit.suffix; + t.baseURL = tinyMCEPreInit.base; + t.query = tinyMCEPreInit.query; + return; + } + + // Get suffix and base + t.suffix = ''; + + // If base element found, add that infront of baseURL + nl = d.getElementsByTagName('base'); + for (i=0; i<nl.length; i++) { + if (v = nl[i].href) { + // Host only value like http://site.com or http://site.com:8008 + if (/^https?:\/\/[^\/]+$/.test(v)) + v += '/'; + + base = v ? v.match(/.*\//)[0] : ''; // Get only directory + } + } + + function getBase(n) { + if (n.src && /tiny_mce(|_gzip|_jquery|_prototype|_full)(_dev|_src)?.js/.test(n.src)) { + if (/_(src|dev)\.js/g.test(n.src)) + t.suffix = '_src'; + + if ((p = n.src.indexOf('?')) != -1) + t.query = n.src.substring(p + 1); + + t.baseURL = n.src.substring(0, n.src.lastIndexOf('/')); + + // If path to script is relative and a base href was found add that one infront + // the src property will always be an absolute one on non IE browsers and IE 8 + // so this logic will basically only be executed on older IE versions + if (base && t.baseURL.indexOf('://') == -1 && t.baseURL.indexOf('/') !== 0) + t.baseURL = base + t.baseURL; + + return t.baseURL; + } + + return null; + }; + + // Check document + nl = d.getElementsByTagName('script'); + for (i=0; i<nl.length; i++) { + if (getBase(nl[i])) + return; + } + + // Check head + n = d.getElementsByTagName('head')[0]; + if (n) { + nl = n.getElementsByTagName('script'); + for (i=0; i<nl.length; i++) { + if (getBase(nl[i])) + return; + } + } + + return; + }, + + is : function(o, t) { + if (!t) + return o !== undefined; + + if (t == 'array' && (o.hasOwnProperty && o instanceof Array)) + return true; + + return typeof(o) == t; + }, + + makeMap : function(items, delim, map) { + var i; + + items = items || []; + delim = delim || ','; + + if (typeof(items) == "string") + items = items.split(delim); + + map = map || {}; + + i = items.length; + while (i--) + map[items[i]] = {}; + + return map; + }, + + each : function(o, cb, s) { + var n, l; + + if (!o) + return 0; + + s = s || o; + + if (o.length !== undefined) { + // Indexed arrays, needed for Safari + for (n=0, l = o.length; n < l; n++) { + if (cb.call(s, o[n], n, o) === false) + return 0; + } + } else { + // Hashtables + for (n in o) { + if (o.hasOwnProperty(n)) { + if (cb.call(s, o[n], n, o) === false) + return 0; + } + } + } + + return 1; + }, + + + map : function(a, f) { + var o = []; + + tinymce.each(a, function(v) { + o.push(f(v)); + }); + + return o; + }, + + grep : function(a, f) { + var o = []; + + tinymce.each(a, function(v) { + if (!f || f(v)) + o.push(v); + }); + + return o; + }, + + inArray : function(a, v) { + var i, l; + + if (a) { + for (i = 0, l = a.length; i < l; i++) { + if (a[i] === v) + return i; + } + } + + return -1; + }, + + extend : function(o, e) { + var i, l, a = arguments; + + for (i = 1, l = a.length; i < l; i++) { + e = a[i]; + + tinymce.each(e, function(v, n) { + if (v !== undefined) + o[n] = v; + }); + } + + return o; + }, + + + trim : function(s) { + return (s ? '' + s : '').replace(whiteSpaceRe, ''); + }, + + create : function(s, p, root) { + var t = this, sp, ns, cn, scn, c, de = 0; + + // Parse : <prefix> <class>:<super class> + s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s); + cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name + + // Create namespace for new class + ns = t.createNS(s[3].replace(/\.\w+$/, ''), root); + + // Class already exists + if (ns[cn]) + return; + + // Make pure static class + if (s[2] == 'static') { + ns[cn] = p; + + if (this.onCreate) + this.onCreate(s[2], s[3], ns[cn]); + + return; + } + + // Create default constructor + if (!p[cn]) { + p[cn] = function() {}; + de = 1; + } + + // Add constructor and methods + ns[cn] = p[cn]; + t.extend(ns[cn].prototype, p); + + // Extend + if (s[5]) { + sp = t.resolve(s[5]).prototype; + scn = s[5].match(/\.(\w+)$/i)[1]; // Class name + + // Extend constructor + c = ns[cn]; + if (de) { + // Add passthrough constructor + ns[cn] = function() { + return sp[scn].apply(this, arguments); + }; + } else { + // Add inherit constructor + ns[cn] = function() { + this.parent = sp[scn]; + return c.apply(this, arguments); + }; + } + ns[cn].prototype[cn] = ns[cn]; + + // Add super methods + t.each(sp, function(f, n) { + ns[cn].prototype[n] = sp[n]; + }); + + // Add overridden methods + t.each(p, function(f, n) { + // Extend methods if needed + if (sp[n]) { + ns[cn].prototype[n] = function() { + this.parent = sp[n]; + return f.apply(this, arguments); + }; + } else { + if (n != cn) + ns[cn].prototype[n] = f; + } + }); + } + + // Add static methods + t.each(p['static'], function(f, n) { + ns[cn][n] = f; + }); + + if (this.onCreate) + this.onCreate(s[2], s[3], ns[cn].prototype); + }, + + walk : function(o, f, n, s) { + s = s || this; + + if (o) { + if (n) + o = o[n]; + + tinymce.each(o, function(o, i) { + if (f.call(s, o, i, n) === false) + return false; + + tinymce.walk(o, f, n, s); + }); + } + }, + + createNS : function(n, o) { + var i, v; + + o = o || win; + + n = n.split('.'); + for (i=0; i<n.length; i++) { + v = n[i]; + + if (!o[v]) + o[v] = {}; + + o = o[v]; + } + + return o; + }, + + resolve : function(n, o) { + var i, l; + + o = o || win; + + n = n.split('.'); + for (i = 0, l = n.length; i < l; i++) { + o = o[n[i]]; + + if (!o) + break; + } + + return o; + }, + + addUnload : function(f, s) { + var t = this; + + f = {func : f, scope : s || this}; + + if (!t.unloads) { + function unload() { + var li = t.unloads, o, n; + + if (li) { + // Call unload handlers + for (n in li) { + o = li[n]; + + if (o && o.func) + o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy + } + + // Detach unload function + if (win.detachEvent) { + win.detachEvent('onbeforeunload', fakeUnload); + win.detachEvent('onunload', unload); + } else if (win.removeEventListener) + win.removeEventListener('unload', unload, false); + + // Destroy references + t.unloads = o = li = w = unload = 0; + + // Run garbarge collector on IE + if (win.CollectGarbage) + CollectGarbage(); + } + }; + + function fakeUnload() { + var d = document; + + // Is there things still loading, then do some magic + if (d.readyState == 'interactive') { + function stop() { + // Prevent memory leak + d.detachEvent('onstop', stop); + + // Call unload handler + if (unload) + unload(); + + d = 0; + }; + + // Fire unload when the currently loading page is stopped + if (d) + d.attachEvent('onstop', stop); + + // Remove onstop listener after a while to prevent the unload function + // to execute if the user presses cancel in an onbeforeunload + // confirm dialog and then presses the browser stop button + win.setTimeout(function() { + if (d) + d.detachEvent('onstop', stop); + }, 0); + } + }; + + // Attach unload handler + if (win.attachEvent) { + win.attachEvent('onunload', unload); + win.attachEvent('onbeforeunload', fakeUnload); + } else if (win.addEventListener) + win.addEventListener('unload', unload, false); + + // Setup initial unload handler array + t.unloads = [f]; + } else + t.unloads.push(f); + + return f; + }, + + removeUnload : function(f) { + var u = this.unloads, r = null; + + tinymce.each(u, function(o, i) { + if (o && o.func == f) { + u.splice(i, 1); + r = f; + return false; + } + }); + + return r; + }, + + explode : function(s, d) { + return s ? tinymce.map(s.split(d || ','), tinymce.trim) : s; + }, + + _addVer : function(u) { + var v; + + if (!this.query) + return u; + + v = (u.indexOf('?') == -1 ? '?' : '&') + this.query; + + if (u.indexOf('#') == -1) + return u + v; + + return u.replace('#', v + '#'); + }, + + // Fix function for IE 9 where regexps isn't working correctly + // Todo: remove me once MS fixes the bug + _replace : function(find, replace, str) { + // On IE9 we have to fake $x replacement + if (isRegExpBroken) { + return str.replace(find, function() { + var val = replace, args = arguments, i; + + for (i = 0; i < args.length - 2; i++) { + if (args[i] === undefined) { + val = val.replace(new RegExp('\\$' + i, 'g'), ''); + } else { + val = val.replace(new RegExp('\\$' + i, 'g'), args[i]); + } + } + + return val; + }); + } + + return str.replace(find, replace); + } + + }; + + // Initialize the API + tinymce._init(); + + // Expose tinymce namespace to the global namespace (window) + win.tinymce = win.tinyMCE = tinymce; + + // Describe the different namespaces + + })(window); + + + +tinymce.create('tinymce.util.Dispatcher', { + scope : null, + listeners : null, + + Dispatcher : function(s) { + this.scope = s || this; + this.listeners = []; + }, + + add : function(cb, s) { + this.listeners.push({cb : cb, scope : s || this.scope}); + + return cb; + }, + + addToTop : function(cb, s) { + this.listeners.unshift({cb : cb, scope : s || this.scope}); + + return cb; + }, + + remove : function(cb) { + var l = this.listeners, o = null; + + tinymce.each(l, function(c, i) { + if (cb == c.cb) { + o = cb; + l.splice(i, 1); + return false; + } + }); + + return o; + }, + + dispatch : function() { + var s, a = arguments, i, li = this.listeners, c; + + // Needs to be a real loop since the listener count might change while looping + // And this is also more efficient + for (i = 0; i<li.length; i++) { + c = li[i]; + s = c.cb.apply(c.scope, a); + + if (s === false) + break; + } + + return s; + } + + }); + +(function() { + var each = tinymce.each; + + tinymce.create('tinymce.util.URI', { + URI : function(u, s) { + var t = this, o, a, b, base_url; + + // Trim whitespace + u = tinymce.trim(u); + + // Default settings + s = t.settings = s || {}; + + // Strange app protocol that isn't http/https or local anchor + // For example: mailto,skype,tel etc. + if (/^([\w\-]+):([^\/]{2})/i.test(u) || /^\s*#/.test(u)) { + t.source = u; + return; + } + + // Absolute path with no host, fake host and protocol + if (u.indexOf('/') === 0 && u.indexOf('//') !== 0) + u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u; + + // Relative path http:// or protocol relative //path + if (!/^[\w-]*:?\/\//.test(u)) { + base_url = s.base_uri ? s.base_uri.path : new tinymce.util.URI(location.href).directory; + u = ((s.base_uri && s.base_uri.protocol) || 'http') + '://mce_host' + t.toAbsPath(base_url, u); + } + + // Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri) + u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something + u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u); + each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) { + var s = u[i]; + + // Zope 3 workaround, they use @@something + if (s) + s = s.replace(/\(mce_at\)/g, '@@'); + + t[v] = s; + }); + + if (b = s.base_uri) { + if (!t.protocol) + t.protocol = b.protocol; + + if (!t.userInfo) + t.userInfo = b.userInfo; + + if (!t.port && t.host == 'mce_host') + t.port = b.port; + + if (!t.host || t.host == 'mce_host') + t.host = b.host; + + t.source = ''; + } + + //t.path = t.path || '/'; + }, + + setPath : function(p) { + var t = this; + + p = /^(.*?)\/?(\w+)?$/.exec(p); + + // Update path parts + t.path = p[0]; + t.directory = p[1]; + t.file = p[2]; + + // Rebuild source + t.source = ''; + t.getURI(); + }, + + toRelative : function(u) { + var t = this, o; + + if (u === "./") + return u; + + u = new tinymce.util.URI(u, {base_uri : t}); + + // Not on same domain/port or protocol + if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol) + return u.getURI(); + + o = t.toRelPath(t.path, u.path); + + // Add query + if (u.query) + o += '?' + u.query; + + // Add anchor + if (u.anchor) + o += '#' + u.anchor; + + return o; + }, + + toAbsolute : function(u, nh) { + var u = new tinymce.util.URI(u, {base_uri : this}); + + return u.getURI(this.host == u.host && this.protocol == u.protocol ? nh : 0); + }, + + toRelPath : function(base, path) { + var items, bp = 0, out = '', i, l; + + // Split the paths + base = base.substring(0, base.lastIndexOf('/')); + base = base.split('/'); + items = path.split('/'); + + if (base.length >= items.length) { + for (i = 0, l = base.length; i < l; i++) { + if (i >= items.length || base[i] != items[i]) { + bp = i + 1; + break; + } + } + } + + if (base.length < items.length) { + for (i = 0, l = items.length; i < l; i++) { + if (i >= base.length || base[i] != items[i]) { + bp = i + 1; + break; + } + } + } + + if (bp == 1) + return path; + + for (i = 0, l = base.length - (bp - 1); i < l; i++) + out += "../"; + + for (i = bp - 1, l = items.length; i < l; i++) { + if (i != bp - 1) + out += "/" + items[i]; + else + out += items[i]; + } + + return out; + }, + + toAbsPath : function(base, path) { + var i, nb = 0, o = [], tr, outPath; + + // Split paths + tr = /\/$/.test(path) ? '/' : ''; + base = base.split('/'); + path = path.split('/'); + + // Remove empty chunks + each(base, function(k) { + if (k) + o.push(k); + }); + + base = o; + + // Merge relURLParts chunks + for (i = path.length - 1, o = []; i >= 0; i--) { + // Ignore empty or . + if (path[i].length == 0 || path[i] == ".") + continue; + + // Is parent + if (path[i] == '..') { + nb++; + continue; + } + + // Move up + if (nb > 0) { + nb--; + continue; + } + + o.push(path[i]); + } + + i = base.length - nb; + + // If /a/b/c or / + if (i <= 0) + outPath = o.reverse().join('/'); + else + outPath = base.slice(0, i).join('/') + '/' + o.reverse().join('/'); + + // Add front / if it's needed + if (outPath.indexOf('/') !== 0) + outPath = '/' + outPath; + + // Add traling / if it's needed + if (tr && outPath.lastIndexOf('/') !== outPath.length - 1) + outPath += tr; + + return outPath; + }, + + getURI : function(nh) { + var s, t = this; + + // Rebuild source + if (!t.source || nh) { + s = ''; + + if (!nh) { + if (t.protocol) + s += t.protocol + '://'; + + if (t.userInfo) + s += t.userInfo + '@'; + + if (t.host) + s += t.host; + + if (t.port) + s += ':' + t.port; + } + + if (t.path) + s += t.path; + + if (t.query) + s += '?' + t.query; + + if (t.anchor) + s += '#' + t.anchor; + + t.source = s; + } + + return t.source; + } + }); +})(); + +(function() { + var each = tinymce.each; + + tinymce.create('static tinymce.util.Cookie', { + getHash : function(n) { + var v = this.get(n), h; + + if (v) { + each(v.split('&'), function(v) { + v = v.split('='); + h = h || {}; + h[unescape(v[0])] = unescape(v[1]); + }); + } + + return h; + }, + + setHash : function(n, v, e, p, d, s) { + var o = ''; + + each(v, function(v, k) { + o += (!o ? '' : '&') + escape(k) + '=' + escape(v); + }); + + this.set(n, o, e, p, d, s); + }, + + get : function(n) { + var c = document.cookie, e, p = n + "=", b; + + // Strict mode + if (!c) + return; + + b = c.indexOf("; " + p); + + if (b == -1) { + b = c.indexOf(p); + + if (b != 0) + return null; + } else + b += 2; + + e = c.indexOf(";", b); + + if (e == -1) + e = c.length; + + return unescape(c.substring(b + p.length, e)); + }, + + set : function(n, v, e, p, d, s) { + document.cookie = n + "=" + escape(v) + + ((e) ? "; expires=" + e.toGMTString() : "") + + ((p) ? "; path=" + escape(p) : "") + + ((d) ? "; domain=" + d : "") + + ((s) ? "; secure" : ""); + }, + + remove : function(n, p) { + var d = new Date(); + + d.setTime(d.getTime() - 1000); + + this.set(n, '', d, p, d); + } + }); +})(); + +(function() { + function serialize(o, quote) { + var i, v, t; + + quote = quote || '"'; + + if (o == null) + return 'null'; + + t = typeof o; + + if (t == 'string') { + v = '\bb\tt\nn\ff\rr\""\'\'\\\\'; + + return quote + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g, function(a, b) { + // Make sure single quotes never get encoded inside double quotes for JSON compatibility + if (quote === '"' && a === "'") + return a; + + i = v.indexOf(b); + + if (i + 1) + return '\\' + v.charAt(i + 1); + + a = b.charCodeAt().toString(16); + + return '\\u' + '0000'.substring(a.length) + a; + }) + quote; + } + + if (t == 'object') { + if (o.hasOwnProperty && o instanceof Array) { + for (i=0, v = '['; i<o.length; i++) + v += (i > 0 ? ',' : '') + serialize(o[i], quote); + + return v + ']'; + } + + v = '{'; + + for (i in o) + v += typeof o[i] != 'function' ? (v.length > 1 ? ',' + quote : quote) + i + quote +':' + serialize(o[i], quote) : ''; + + return v + '}'; + } + + return '' + o; + }; + + tinymce.util.JSON = { + serialize: serialize, + + parse: function(s) { + try { + return eval('(' + s + ')'); + } catch (ex) { + // Ignore + } + } + + }; +})(); +tinymce.create('static tinymce.util.XHR', { + send : function(o) { + var x, t, w = window, c = 0; + + // Default settings + o.scope = o.scope || this; + o.success_scope = o.success_scope || o.scope; + o.error_scope = o.error_scope || o.scope; + o.async = o.async === false ? false : true; + o.data = o.data || ''; + + function get(s) { + x = 0; + + try { + x = new ActiveXObject(s); + } catch (ex) { + } + + return x; + }; + + x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP'); + + if (x) { + if (x.overrideMimeType) + x.overrideMimeType(o.content_type); + + x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async); + + if (o.content_type) + x.setRequestHeader('Content-Type', o.content_type); + + x.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + + x.send(o.data); + + function ready() { + if (!o.async || x.readyState == 4 || c++ > 10000) { + if (o.success && c < 10000 && x.status == 200) + o.success.call(o.success_scope, '' + x.responseText, x, o); + else if (o.error) + o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o); + + x = null; + } else + w.setTimeout(ready, 10); + }; + + // Syncronous request + if (!o.async) + return ready(); + + // Wait for response, onReadyStateChange can not be used since it leaks memory in IE + t = w.setTimeout(ready, 10); + } + } +}); + +(function() { + var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR; + + tinymce.create('tinymce.util.JSONRequest', { + JSONRequest : function(s) { + this.settings = extend({ + }, s); + this.count = 0; + }, + + send : function(o) { + var ecb = o.error, scb = o.success; + + o = extend(this.settings, o); + + o.success = function(c, x) { + c = JSON.parse(c); + + if (typeof(c) == 'undefined') { + c = { + error : 'JSON Parse error.' + }; + } + + if (c.error) + ecb.call(o.error_scope || o.scope, c.error, x); + else + scb.call(o.success_scope || o.scope, c.result); + }; + + o.error = function(ty, x) { + if (ecb) + ecb.call(o.error_scope || o.scope, ty, x); + }; + + o.data = JSON.serialize({ + id : o.id || 'c' + (this.count++), + method : o.method, + params : o.params + }); + + // JSON content type for Ruby on rails. Bug: #1883287 + o.content_type = 'application/json'; + + XHR.send(o); + }, + + 'static' : { + sendRPC : function(o) { + return new tinymce.util.JSONRequest().send(o); + } + } + }); +}()); +(function(tinymce){ + tinymce.VK = { + DELETE:46, + BACKSPACE:8 + + } + +})(tinymce); + +(function(tinymce) { + var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE; + + function cleanupStylesWhenDeleting(ed) { + var dom = ed.dom, selection = ed.selection; + + ed.onKeyDown.add(function(ed, e) { + var rng, blockElm, node, clonedSpan, isDelete; + + isDelete = e.keyCode == DELETE; + if (isDelete || e.keyCode == BACKSPACE) { + e.preventDefault(); + rng = selection.getRng(); + + // Find root block + blockElm = dom.getParent(rng.startContainer, dom.isBlock); + + // On delete clone the root span of the next block element + if (isDelete) + blockElm = dom.getNext(blockElm, dom.isBlock); + + // Locate root span element and clone it since it would otherwise get merged by the "apple-style-span" on delete/backspace + if (blockElm) { + node = blockElm.firstChild; + + // Ignore empty text nodes + while (node.nodeType == 3 && node.nodeValue.length == 0) + node = node.nextSibling; + + if (node && node.nodeName === 'SPAN') { + clonedSpan = node.cloneNode(false); + } + } + + // Do the backspace/delete actiopn + ed.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null); + + // Find all odd apple-style-spans + blockElm = dom.getParent(rng.startContainer, dom.isBlock); + tinymce.each(dom.select('span.Apple-style-span,font.Apple-style-span', blockElm), function(span) { + var bm = selection.getBookmark(); + + if (clonedSpan) { + dom.replace(clonedSpan.cloneNode(false), span, true); + } else { + dom.remove(span, true); + } + + // Restore the selection + selection.moveToBookmark(bm); + }); + } + }); + }; + + function emptyEditorWhenDeleting(ed) { + ed.onKeyUp.add(function(ed, e) { + var keyCode = e.keyCode; + + if (keyCode == DELETE || keyCode == BACKSPACE) { + if (ed.dom.isEmpty(ed.getBody())) { + ed.setContent('', {format : 'raw'}); + ed.nodeChanged(); + return; + } + } + }); + }; + + function inputMethodFocus(ed) { + ed.dom.bind(ed.getDoc(), 'focusin', function() { + ed.selection.setRng(ed.selection.getRng()); + }); + }; + + function focusBody(ed) { + // Fix for a focus bug in FF 3.x where the body element + // wouldn't get proper focus if the user clicked on the HTML element + if (!Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4 + ed.onMouseDown.add(function(ed, e) { + if (e.target.nodeName === "HTML") { + var body = ed.getBody(); + + // Blur the body it's focused but not correctly focused + body.blur(); + + // Refocus the body after a little while + setTimeout(function() { + body.focus(); + }, 0); + } + }); + } + }; + + function selectControlElements(ed) { + ed.onClick.add(function(ed, e) { + e = e.target; + + // Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250 + // WebKit can't even do simple things like selecting an image + // Needs tobe the setBaseAndExtend or it will fail to select floated images + if (/^(IMG|HR)$/.test(e.nodeName)) + ed.selection.getSel().setBaseAndExtent(e, 0, e, 1); + + if (e.nodeName == 'A' && ed.dom.hasClass(e, 'mceItemAnchor')) + ed.selection.select(e); + + ed.nodeChanged(); + }); + }; + + tinymce.create('tinymce.util.Quirks', { + Quirks: function(ed) { + // WebKit + if (tinymce.isWebKit) { + cleanupStylesWhenDeleting(ed); + emptyEditorWhenDeleting(ed); + inputMethodFocus(ed); + selectControlElements(ed); + } + + // IE + if (tinymce.isIE) { + emptyEditorWhenDeleting(ed); + } + + // Gecko + if (tinymce.isGecko) { + focusBody(ed); + } + } + }); +})(tinymce); +(function(tinymce) { + var namedEntities, baseEntities, reverseEntities, + attrsCharsRegExp = /[&<>\"\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + textCharsRegExp = /[<>&\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, + rawCharsRegExp = /[<>&\"\']/g, + entityRegExp = /&(#x|#)?([\w]+);/g, + asciiMap = { + 128 : "\u20AC", 130 : "\u201A", 131 : "\u0192", 132 : "\u201E", 133 : "\u2026", 134 : "\u2020", + 135 : "\u2021", 136 : "\u02C6", 137 : "\u2030", 138 : "\u0160", 139 : "\u2039", 140 : "\u0152", + 142 : "\u017D", 145 : "\u2018", 146 : "\u2019", 147 : "\u201C", 148 : "\u201D", 149 : "\u2022", + 150 : "\u2013", 151 : "\u2014", 152 : "\u02DC", 153 : "\u2122", 154 : "\u0161", 155 : "\u203A", + 156 : "\u0153", 158 : "\u017E", 159 : "\u0178" + }; + + // Raw entities + baseEntities = { + '\"' : '&quot;', // Needs to be escaped since the YUI compressor would otherwise break the code + "'" : '&#39;', + '<' : '&lt;', + '>' : '&gt;', + '&' : '&amp;' + }; + + // Reverse lookup table for raw entities + reverseEntities = { + '&lt;' : '<', + '&gt;' : '>', + '&amp;' : '&', + '&quot;' : '"', + '&apos;' : "'" + }; + + // Decodes text by using the browser + function nativeDecode(text) { + var elm; + + elm = document.createElement("div"); + elm.innerHTML = text; + + return elm.textContent || elm.innerText || text; + }; + + // Build a two way lookup table for the entities + function buildEntitiesLookup(items, radix) { + var i, chr, entity, lookup = {}; + + if (items) { + items = items.split(','); + radix = radix || 10; + + // Build entities lookup table + for (i = 0; i < items.length; i += 2) { + chr = String.fromCharCode(parseInt(items[i], radix)); + + // Only add non base entities + if (!baseEntities[chr]) { + entity = '&' + items[i + 1] + ';'; + lookup[chr] = entity; + lookup[entity] = chr; + } + } + + return lookup; + } + }; + + // Unpack entities lookup where the numbers are in radix 32 to reduce the size + namedEntities = buildEntitiesLookup( + '50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' + + '5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' + + '5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' + + '5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' + + '68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' + + '6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' + + '6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' + + '75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' + + '7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' + + '7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' + + 'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' + + 'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' + + 't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' + + 'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' + + 'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' + + '81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' + + '8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' + + '8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' + + '8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' + + '8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' + + 'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' + + 'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' + + 'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' + + '80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' + + '811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro' + , 32); + + tinymce.html = tinymce.html || {}; + + tinymce.html.Entities = { + encodeRaw : function(text, attr) { + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + return baseEntities[chr] || chr; + }); + }, + + encodeAllRaw : function(text) { + return ('' + text).replace(rawCharsRegExp, function(chr) { + return baseEntities[chr] || chr; + }); + }, + + encodeNumeric : function(text, attr) { + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + // Multi byte sequence convert it to a single entity + if (chr.length > 1) + return '&#' + (((chr.charCodeAt(0) - 0xD800) * 0x400) + (chr.charCodeAt(1) - 0xDC00) + 0x10000) + ';'; + + return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';'; + }); + }, + + encodeNamed : function(text, attr, entities) { + entities = entities || namedEntities; + + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + return baseEntities[chr] || entities[chr] || chr; + }); + }, + + getEncodeFunc : function(name, entities) { + var Entities = tinymce.html.Entities; + + entities = buildEntitiesLookup(entities) || namedEntities; + + function encodeNamedAndNumeric(text, attr) { + return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) { + return baseEntities[chr] || entities[chr] || '&#' + chr.charCodeAt(0) + ';' || chr; + }); + }; + + function encodeCustomNamed(text, attr) { + return Entities.encodeNamed(text, attr, entities); + }; + + // Replace + with , to be compatible with previous TinyMCE versions + name = tinymce.makeMap(name.replace(/\+/g, ',')); + + // Named and numeric encoder + if (name.named && name.numeric) + return encodeNamedAndNumeric; + + // Named encoder + if (name.named) { + // Custom names + if (entities) + return encodeCustomNamed; + + return Entities.encodeNamed; + } + + // Numeric + if (name.numeric) + return Entities.encodeNumeric; + + // Raw encoder + return Entities.encodeRaw; + }, + + decode : function(text) { + return text.replace(entityRegExp, function(all, numeric, value) { + if (numeric) { + value = parseInt(value, numeric.length === 2 ? 16 : 10); + + // Support upper UTF + if (value > 0xFFFF) { + value -= 0x10000; + + return String.fromCharCode(0xD800 + (value >> 10), 0xDC00 + (value & 0x3FF)); + } else + return asciiMap[value] || String.fromCharCode(value); + } + + return reverseEntities[all] || namedEntities[all] || nativeDecode(all); + }); + } + }; +})(tinymce); + +tinymce.html.Styles = function(settings, schema) { + var rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi, + urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi, + styleRegExp = /\s*([^:]+):\s*([^;]+);?/g, + trimRightRegExp = /\s+$/, + urlColorRegExp = /rgb/, + undef, i, encodingLookup = {}, encodingItems; + + settings = settings || {}; + + encodingItems = '\\" \\\' \\; \\: ; : \uFEFF'.split(' '); + for (i = 0; i < encodingItems.length; i++) { + encodingLookup[encodingItems[i]] = '\uFEFF' + i; + encodingLookup['\uFEFF' + i] = encodingItems[i]; + } + + function toHex(match, r, g, b) { + function hex(val) { + val = parseInt(val).toString(16); + + return val.length > 1 ? val : '0' + val; // 0 -> 00 + }; + + return '#' + hex(r) + hex(g) + hex(b); + }; + + return { + toHex : function(color) { + return color.replace(rgbRegExp, toHex); + }, + + parse : function(css) { + var styles = {}, matches, name, value, isEncoded, urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope || this; + + function compress(prefix, suffix) { + var top, right, bottom, left; + + // Get values and check it it needs compressing + top = styles[prefix + '-top' + suffix]; + if (!top) + return; + + right = styles[prefix + '-right' + suffix]; + if (top != right) + return; + + bottom = styles[prefix + '-bottom' + suffix]; + if (right != bottom) + return; + + left = styles[prefix + '-left' + suffix]; + if (bottom != left) + return; + + // Compress + styles[prefix + suffix] = left; + delete styles[prefix + '-top' + suffix]; + delete styles[prefix + '-right' + suffix]; + delete styles[prefix + '-bottom' + suffix]; + delete styles[prefix + '-left' + suffix]; + }; + + function canCompress(key) { + var value = styles[key], i; + + if (!value || value.indexOf(' ') < 0) + return; + + value = value.split(' '); + i = value.length; + while (i--) { + if (value[i] !== value[0]) + return false; + } + + styles[key] = value[0]; + + return true; + }; + + function compress2(target, a, b, c) { + if (!canCompress(a)) + return; + + if (!canCompress(b)) + return; + + if (!canCompress(c)) + return; + + // Compress + styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c]; + delete styles[a]; + delete styles[b]; + delete styles[c]; + }; + + // Encodes the specified string by replacing all \" \' ; : with _<num> + function encode(str) { + isEncoded = true; + + return encodingLookup[str]; + }; + + // Decodes the specified string by replacing all _<num> with it's original value \" \' etc + // It will also decode the \" \' if keep_slashes is set to fale or omitted + function decode(str, keep_slashes) { + if (isEncoded) { + str = str.replace(/\uFEFF[0-9]/g, function(str) { + return encodingLookup[str]; + }); + } + + if (!keep_slashes) + str = str.replace(/\\([\'\";:])/g, "$1"); + + return str; + } + + if (css) { + // Encode \" \' % and ; and : inside strings so they don't interfere with the style parsing + css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, function(str) { + return str.replace(/[;:]/g, encode); + }); + + // Parse styles + while (matches = styleRegExp.exec(css)) { + name = matches[1].replace(trimRightRegExp, '').toLowerCase(); + value = matches[2].replace(trimRightRegExp, ''); + + if (name && value.length > 0) { + // Opera will produce 700 instead of bold in their style values + if (name === 'font-weight' && value === '700') + value = 'bold'; + else if (name === 'color' || name === 'background-color') // Lowercase colors like RED + value = value.toLowerCase(); + + // Convert RGB colors to HEX + value = value.replace(rgbRegExp, toHex); + + // Convert URLs and force them into url('value') format + value = value.replace(urlOrStrRegExp, function(match, url, url2, url3, str, str2) { + str = str || str2; + + if (str) { + str = decode(str); + + // Force strings into single quote format + return "'" + str.replace(/\'/g, "\\'") + "'"; + } + + url = decode(url || url2 || url3); + + // Convert the URL to relative/absolute depending on config + if (urlConverter) + url = urlConverter.call(urlConverterScope, url, 'style'); + + // Output new URL format + return "url('" + url.replace(/\'/g, "\\'") + "')"; + }); + + styles[name] = isEncoded ? decode(value, true) : value; + } + + styleRegExp.lastIndex = matches.index + matches[0].length; + } + + // Compress the styles to reduce it's size for example IE will expand styles + compress("border", ""); + compress("border", "-width"); + compress("border", "-color"); + compress("border", "-style"); + compress("padding", ""); + compress("margin", ""); + compress2('border', 'border-width', 'border-style', 'border-color'); + + // Remove pointless border, IE produces these + if (styles.border === 'medium none') + delete styles.border; + } + + return styles; + }, + + serialize : function(styles, element_name) { + var css = '', name, value; + + function serializeStyles(name) { + var styleList, i, l, value; + + styleList = schema.styles[name]; + if (styleList) { + for (i = 0, l = styleList.length; i < l; i++) { + name = styleList[i]; + value = styles[name]; + + if (value !== undef && value.length > 0) + css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; + } + } + }; + + // Serialize styles according to schema + if (element_name && schema && schema.styles) { + // Serialize global styles and element specific styles + serializeStyles('*'); + serializeStyles(element_name); + } else { + // Output the styles in the order they are inside the object + for (name in styles) { + value = styles[name]; + + if (value !== undef && value.length > 0) + css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';'; + } + } + + return css; + } + }; +}; + +(function(tinymce) { + var transitional = {}, boolAttrMap, blockElementsMap, shortEndedElementsMap, nonEmptyElementsMap, customElementsMap = {}, + defaultWhiteSpaceElementsMap, selfClosingElementsMap, makeMap = tinymce.makeMap, each = tinymce.each; + + function split(str, delim) { + return str.split(delim || ','); + }; + + function unpack(lookup, data) { + var key, elements = {}; + + function replace(value) { + return value.replace(/[A-Z]+/g, function(key) { + return replace(lookup[key]); + }); + }; + + // Unpack lookup + for (key in lookup) { + if (lookup.hasOwnProperty(key)) + lookup[key] = replace(lookup[key]); + } + + // Unpack and parse data into object map + replace(data).replace(/#/g, '#text').replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g, function(str, name, attributes, children) { + attributes = split(attributes, '|'); + + elements[name] = { + attributes : makeMap(attributes), + attributesOrder : attributes, + children : makeMap(children, '|', {'#comment' : {}}) + } + }); + + return elements; + }; + + // Build a lookup table for block elements both lowercase and uppercase + blockElementsMap = 'h1,h2,h3,h4,h5,h6,hr,p,div,address,pre,form,table,tbody,thead,tfoot,' + + 'th,tr,td,li,ol,ul,caption,blockquote,center,dl,dt,dd,dir,fieldset,' + + 'noscript,menu,isindex,samp,header,footer,article,section,hgroup'; + blockElementsMap = makeMap(blockElementsMap, ',', makeMap(blockElementsMap.toUpperCase())); + + // This is the XHTML 1.0 transitional elements with it's attributes and children packed to reduce it's size + transitional = unpack({ + Z : 'H|K|N|O|P', + Y : 'X|form|R|Q', + ZG : 'E|span|width|align|char|charoff|valign', + X : 'p|T|div|U|W|isindex|fieldset|table', + ZF : 'E|align|char|charoff|valign', + W : 'pre|hr|blockquote|address|center|noframes', + ZE : 'abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height', + ZD : '[E][S]', + U : 'ul|ol|dl|menu|dir', + ZC : 'p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q', + T : 'h1|h2|h3|h4|h5|h6', + ZB : 'X|S|Q', + S : 'R|P', + ZA : 'a|G|J|M|O|P', + R : 'a|H|K|N|O', + Q : 'noscript|P', + P : 'ins|del|script', + O : 'input|select|textarea|label|button', + N : 'M|L', + M : 'em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym', + L : 'sub|sup', + K : 'J|I', + J : 'tt|i|b|u|s|strike', + I : 'big|small|font|basefont', + H : 'G|F', + G : 'br|span|bdo', + F : 'object|applet|img|map|iframe', + E : 'A|B|C', + D : 'accesskey|tabindex|onfocus|onblur', + C : 'onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup', + B : 'lang|xml:lang|dir', + A : 'id|class|style|title' + }, 'script[id|charset|type|language|src|defer|xml:space][]' + + 'style[B|id|type|media|title|xml:space][]' + + 'object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]' + + 'param[id|name|value|valuetype|type][]' + + 'p[E|align][#|S]' + + 'a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]' + + 'br[A|clear][]' + + 'span[E][#|S]' + + 'bdo[A|C|B][#|S]' + + 'applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]' + + 'h1[E|align][#|S]' + + 'img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]' + + 'map[B|C|A|name][X|form|Q|area]' + + 'h2[E|align][#|S]' + + 'iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]' + + 'h3[E|align][#|S]' + + 'tt[E][#|S]' + + 'i[E][#|S]' + + 'b[E][#|S]' + + 'u[E][#|S]' + + 's[E][#|S]' + + 'strike[E][#|S]' + + 'big[E][#|S]' + + 'small[E][#|S]' + + 'font[A|B|size|color|face][#|S]' + + 'basefont[id|size|color|face][]' + + 'em[E][#|S]' + + 'strong[E][#|S]' + + 'dfn[E][#|S]' + + 'code[E][#|S]' + + 'q[E|cite][#|S]' + + 'samp[E][#|S]' + + 'kbd[E][#|S]' + + 'var[E][#|S]' + + 'cite[E][#|S]' + + 'abbr[E][#|S]' + + 'acronym[E][#|S]' + + 'sub[E][#|S]' + + 'sup[E][#|S]' + + 'input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]' + + 'select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]' + + 'optgroup[E|disabled|label][option]' + + 'option[E|selected|disabled|label|value][]' + + 'textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]' + + 'label[E|for|accesskey|onfocus|onblur][#|S]' + + 'button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]' + + 'h4[E|align][#|S]' + + 'ins[E|cite|datetime][#|Y]' + + 'h5[E|align][#|S]' + + 'del[E|cite|datetime][#|Y]' + + 'h6[E|align][#|S]' + + 'div[E|align][#|Y]' + + 'ul[E|type|compact][li]' + + 'li[E|type|value][#|Y]' + + 'ol[E|type|compact|start][li]' + + 'dl[E|compact][dt|dd]' + + 'dt[E][#|S]' + + 'dd[E][#|Y]' + + 'menu[E|compact][li]' + + 'dir[E|compact][li]' + + 'pre[E|width|xml:space][#|ZA]' + + 'hr[E|align|noshade|size|width][]' + + 'blockquote[E|cite][#|Y]' + + 'address[E][#|S|p]' + + 'center[E][#|Y]' + + 'noframes[E][#|Y]' + + 'isindex[A|B|prompt][]' + + 'fieldset[E][#|legend|Y]' + + 'legend[E|accesskey|align][#|S]' + + 'table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]' + + 'caption[E|align][#|S]' + + 'col[ZG][]' + + 'colgroup[ZG][col]' + + 'thead[ZF][tr]' + + 'tr[ZF|bgcolor][th|td]' + + 'th[E|ZE][#|Y]' + + 'form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]' + + 'noscript[E][#|Y]' + + 'td[E|ZE][#|Y]' + + 'tfoot[ZF][tr]' + + 'tbody[ZF][tr]' + + 'area[E|D|shape|coords|href|nohref|alt|target][]' + + 'base[id|href|target][]' + + 'body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]' + ); + + boolAttrMap = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected,autoplay,loop,controls'); + shortEndedElementsMap = makeMap('area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,source'); + nonEmptyElementsMap = tinymce.extend(makeMap('td,th,iframe,video,audio,object'), shortEndedElementsMap); + defaultWhiteSpaceElementsMap = makeMap('pre,script,style,textarea'); + selfClosingElementsMap = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'); + + tinymce.html.Schema = function(settings) { + var self = this, elements = {}, children = {}, patternElements = [], validStyles, whiteSpaceElementsMap; + + settings = settings || {}; + + // Allow all elements and attributes if verify_html is set to false + if (settings.verify_html === false) + settings.valid_elements = '*[*]'; + + // Build styles list + if (settings.valid_styles) { + validStyles = {}; + + // Convert styles into a rule list + each(settings.valid_styles, function(value, key) { + validStyles[key] = tinymce.explode(value); + }); + } + + whiteSpaceElementsMap = settings.whitespace_elements ? makeMap(settings.whitespace_elements) : defaultWhiteSpaceElementsMap; + + // Converts a wildcard expression string to a regexp for example *a will become /.*a/. + function patternToRegExp(str) { + return new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$'); + }; + + // Parses the specified valid_elements string and adds to the current rules + // This function is a bit hard to read since it's heavily optimized for speed + function addValidElements(valid_elements) { + var ei, el, ai, al, yl, matches, element, attr, attrData, elementName, attrName, attrType, attributes, attributesOrder, + prefix, outputName, globalAttributes, globalAttributesOrder, transElement, key, childKey, value, + elementRuleRegExp = /^([#+-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/, + attrRuleRegExp = /^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/, + hasPatternsRegExp = /[*?+]/; + + if (valid_elements) { + // Split valid elements into an array with rules + valid_elements = split(valid_elements); + + if (elements['@']) { + globalAttributes = elements['@'].attributes; + globalAttributesOrder = elements['@'].attributesOrder; + } + + // Loop all rules + for (ei = 0, el = valid_elements.length; ei < el; ei++) { + // Parse element rule + matches = elementRuleRegExp.exec(valid_elements[ei]); + if (matches) { + // Setup local names for matches + prefix = matches[1]; + elementName = matches[2]; + outputName = matches[3]; + attrData = matches[4]; + + // Create new attributes and attributesOrder + attributes = {}; + attributesOrder = []; + + // Create the new element + element = { + attributes : attributes, + attributesOrder : attributesOrder + }; + + // Padd empty elements prefix + if (prefix === '#') + element.paddEmpty = true; + + // Remove empty elements prefix + if (prefix === '-') + element.removeEmpty = true; + + // Copy attributes from global rule into current rule + if (globalAttributes) { + for (key in globalAttributes) + attributes[key] = globalAttributes[key]; + + attributesOrder.push.apply(attributesOrder, globalAttributesOrder); + } + + // Attributes defined + if (attrData) { + attrData = split(attrData, '|'); + for (ai = 0, al = attrData.length; ai < al; ai++) { + matches = attrRuleRegExp.exec(attrData[ai]); + if (matches) { + attr = {}; + attrType = matches[1]; + attrName = matches[2].replace(/::/g, ':'); + prefix = matches[3]; + value = matches[4]; + + // Required + if (attrType === '!') { + element.attributesRequired = element.attributesRequired || []; + element.attributesRequired.push(attrName); + attr.required = true; + } + + // Denied from global + if (attrType === '-') { + delete attributes[attrName]; + attributesOrder.splice(tinymce.inArray(attributesOrder, attrName), 1); + continue; + } + + // Default value + if (prefix) { + // Default value + if (prefix === '=') { + element.attributesDefault = element.attributesDefault || []; + element.attributesDefault.push({name: attrName, value: value}); + attr.defaultValue = value; + } + + // Forced value + if (prefix === ':') { + element.attributesForced = element.attributesForced || []; + element.attributesForced.push({name: attrName, value: value}); + attr.forcedValue = value; + } + + // Required values + if (prefix === '<') + attr.validValues = makeMap(value, '?'); + } + + // Check for attribute patterns + if (hasPatternsRegExp.test(attrName)) { + element.attributePatterns = element.attributePatterns || []; + attr.pattern = patternToRegExp(attrName); + element.attributePatterns.push(attr); + } else { + // Add attribute to order list if it doesn't already exist + if (!attributes[attrName]) + attributesOrder.push(attrName); + + attributes[attrName] = attr; + } + } + } + } + + // Global rule, store away these for later usage + if (!globalAttributes && elementName == '@') { + globalAttributes = attributes; + globalAttributesOrder = attributesOrder; + } + + // Handle substitute elements such as b/strong + if (outputName) { + element.outputName = elementName; + elements[outputName] = element; + } + + // Add pattern or exact element + if (hasPatternsRegExp.test(elementName)) { + element.pattern = patternToRegExp(elementName); + patternElements.push(element); + } else + elements[elementName] = element; + } + } + } + }; + + function setValidElements(valid_elements) { + elements = {}; + patternElements = []; + + addValidElements(valid_elements); + + each(transitional, function(element, name) { + children[name] = element.children; + }); + }; + + // Adds custom non HTML elements to the schema + function addCustomElements(custom_elements) { + var customElementRegExp = /^(~)?(.+)$/; + + if (custom_elements) { + each(split(custom_elements), function(rule) { + var matches = customElementRegExp.exec(rule), + inline = matches[1] === '~', + cloneName = inline ? 'span' : 'div', + name = matches[2]; + + children[name] = children[cloneName]; + customElementsMap[name] = cloneName; + + // If it's not marked as inline then add it to valid block elements + if (!inline) + blockElementsMap[name] = {}; + + // Add custom elements at span/div positions + each(children, function(element, child) { + if (element[cloneName]) + element[name] = element[cloneName]; + }); + }); + } + }; + + // Adds valid children to the schema object + function addValidChildren(valid_children) { + var childRuleRegExp = /^([+\-]?)(\w+)\[([^\]]+)\]$/; + + if (valid_children) { + each(split(valid_children), function(rule) { + var matches = childRuleRegExp.exec(rule), parent, prefix; + + if (matches) { + prefix = matches[1]; + + // Add/remove items from default + if (prefix) + parent = children[matches[2]]; + else + parent = children[matches[2]] = {'#comment' : {}}; + + parent = children[matches[2]]; + + each(split(matches[3], '|'), function(child) { + if (prefix === '-') + delete parent[child]; + else + parent[child] = {}; + }); + } + }); + } + }; + + function getElementRule(name) { + var element = elements[name], i; + + // Exact match found + if (element) + return element; + + // No exact match then try the patterns + i = patternElements.length; + while (i--) { + element = patternElements[i]; + + if (element.pattern.test(name)) + return element; + } + }; + + if (!settings.valid_elements) { + // No valid elements defined then clone the elements from the transitional spec + each(transitional, function(element, name) { + elements[name] = { + attributes : element.attributes, + attributesOrder : element.attributesOrder + }; + + children[name] = element.children; + }); + + // Switch these + each(split('strong/b,em/i'), function(item) { + item = split(item, '/'); + elements[item[1]].outputName = item[0]; + }); + + // Add default alt attribute for images + elements.img.attributesDefault = [{name: 'alt', value: ''}]; + + // Remove these if they are empty by default + each(split('ol,ul,sub,sup,blockquote,span,font,a,table,tbody,tr'), function(name) { + elements[name].removeEmpty = true; + }); + + // Padd these by default + each(split('p,h1,h2,h3,h4,h5,h6,th,td,pre,div,address,caption'), function(name) { + elements[name].paddEmpty = true; + }); + } else + setValidElements(settings.valid_elements); + + addCustomElements(settings.custom_elements); + addValidChildren(settings.valid_children); + addValidElements(settings.extended_valid_elements); + + // Todo: Remove this when we fix list handling to be valid + addValidChildren('+ol[ul|ol],+ul[ul|ol]'); + + // If the user didn't allow span only allow internal spans + if (!getElementRule('span')) + addValidElements('span[!data-mce-type|*]'); + + // Delete invalid elements + if (settings.invalid_elements) { + tinymce.each(tinymce.explode(settings.invalid_elements), function(item) { + if (elements[item]) + delete elements[item]; + }); + } + + self.children = children; + + self.styles = validStyles; + + self.getBoolAttrs = function() { + return boolAttrMap; + }; + + self.getBlockElements = function() { + return blockElementsMap; + }; + + self.getShortEndedElements = function() { + return shortEndedElementsMap; + }; + + self.getSelfClosingElements = function() { + return selfClosingElementsMap; + }; + + self.getNonEmptyElements = function() { + return nonEmptyElementsMap; + }; + + self.getWhiteSpaceElements = function() { + return whiteSpaceElementsMap; + }; + + self.isValidChild = function(name, child) { + var parent = children[name]; + + return !!(parent && parent[child]); + }; + + self.getElementRule = getElementRule; + + self.getCustomElements = function() { + return customElementsMap; + }; + + self.addValidElements = addValidElements; + + self.setValidElements = setValidElements; + + self.addCustomElements = addCustomElements; + + self.addValidChildren = addValidChildren; + }; + + // Expose boolMap and blockElementMap as static properties for usage in DOMUtils + tinymce.html.Schema.boolAttrMap = boolAttrMap; + tinymce.html.Schema.blockElementsMap = blockElementsMap; +})(tinymce); + +(function(tinymce) { + tinymce.html.SaxParser = function(settings, schema) { + var self = this, noop = function() {}; + + settings = settings || {}; + self.schema = schema = schema || new tinymce.html.Schema(); + + if (settings.fix_self_closing !== false) + settings.fix_self_closing = true; + + // Add handler functions from settings and setup default handlers + tinymce.each('comment cdata text start end pi doctype'.split(' '), function(name) { + if (name) + self[name] = settings[name] || noop; + }); + + self.parse = function(html) { + var self = this, matches, index = 0, value, endRegExp, stack = [], attrList, i, text, name, isInternalElement, removeInternalElements, + shortEndedElements, fillAttrsMap, isShortEnded, validate, elementRule, isValidElement, attr, attribsValue, invalidPrefixRegExp, + validAttributesMap, validAttributePatterns, attributesRequired, attributesDefault, attributesForced, selfClosing, + tokenRegExp, attrRegExp, specialElements, attrValue, idCount = 0, decode = tinymce.html.Entities.decode, fixSelfClosing, isIE; + + function processEndTag(name) { + var pos, i; + + // Find position of parent of the same type + pos = stack.length; + while (pos--) { + if (stack[pos].name === name) + break; + } + + // Found parent + if (pos >= 0) { + // Close all the open elements + for (i = stack.length - 1; i >= pos; i--) { + name = stack[i]; + + if (name.valid) + self.end(name.name); + } + + // Remove the open elements from the stack + stack.length = pos; + } + }; + + // Precompile RegExps and map objects + tokenRegExp = new RegExp('<(?:' + + '(?:!--([\\w\\W]*?)-->)|' + // Comment + '(?:!\\[CDATA\\[([\\w\\W]*?)\\]\\]>)|' + // CDATA + '(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE + '(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI + '(?:\\/([^>]+)>)|' + // End element + '(?:([^\\s\\/<>]+)\\s*((?:[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*)>)' + // Start element + ')', 'g'); + + attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g; + specialElements = { + 'script' : /<\/script[^>]*>/gi, + 'style' : /<\/style[^>]*>/gi, + 'noscript' : /<\/noscript[^>]*>/gi + }; + + // Setup lookup tables for empty elements and boolean attributes + shortEndedElements = schema.getShortEndedElements(); + selfClosing = schema.getSelfClosingElements(); + fillAttrsMap = schema.getBoolAttrs(); + validate = settings.validate; + removeInternalElements = settings.remove_internals; + fixSelfClosing = settings.fix_self_closing; + isIE = tinymce.isIE; + invalidPrefixRegExp = /^:/; + + while (matches = tokenRegExp.exec(html)) { + // Text + if (index < matches.index) + self.text(decode(html.substr(index, matches.index - index))); + + if (value = matches[6]) { // End element + value = value.toLowerCase(); + + // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements + if (isIE && invalidPrefixRegExp.test(value)) + value = value.substr(1); + + processEndTag(value); + } else if (value = matches[7]) { // Start element + value = value.toLowerCase(); + + // IE will add a ":" in front of elements it doesn't understand like custom elements or HTML5 elements + if (isIE && invalidPrefixRegExp.test(value)) + value = value.substr(1); + + isShortEnded = value in shortEndedElements; + + // Is self closing tag for example an <li> after an open <li> + if (fixSelfClosing && selfClosing[value] && stack.length > 0 && stack[stack.length - 1].name === value) + processEndTag(value); + + // Validate element + if (!validate || (elementRule = schema.getElementRule(value))) { + isValidElement = true; + + // Grab attributes map and patters when validation is enabled + if (validate) { + validAttributesMap = elementRule.attributes; + validAttributePatterns = elementRule.attributePatterns; + } + + // Parse attributes + if (attribsValue = matches[8]) { + isInternalElement = attribsValue.indexOf('data-mce-type') !== -1; // Check if the element is an internal element + + // If the element has internal attributes then remove it if we are told to do so + if (isInternalElement && removeInternalElements) + isValidElement = false; + + attrList = []; + attrList.map = {}; + + attribsValue.replace(attrRegExp, function(match, name, value, val2, val3) { + var attrRule, i; + + name = name.toLowerCase(); + value = name in fillAttrsMap ? name : decode(value || val2 || val3 || ''); // Handle boolean attribute than value attribute + + // Validate name and value + if (validate && !isInternalElement && name.indexOf('data-') !== 0) { + attrRule = validAttributesMap[name]; + + // Find rule by pattern matching + if (!attrRule && validAttributePatterns) { + i = validAttributePatterns.length; + while (i--) { + attrRule = validAttributePatterns[i]; + if (attrRule.pattern.test(name)) + break; + } + + // No rule matched + if (i === -1) + attrRule = null; + } + + // No attribute rule found + if (!attrRule) + return; + + // Validate value + if (attrRule.validValues && !(value in attrRule.validValues)) + return; + } + + // Add attribute to list and map + attrList.map[name] = value; + attrList.push({ + name: name, + value: value + }); + }); + } else { + attrList = []; + attrList.map = {}; + } + + // Process attributes if validation is enabled + if (validate && !isInternalElement) { + attributesRequired = elementRule.attributesRequired; + attributesDefault = elementRule.attributesDefault; + attributesForced = elementRule.attributesForced; + + // Handle forced attributes + if (attributesForced) { + i = attributesForced.length; + while (i--) { + attr = attributesForced[i]; + name = attr.name; + attrValue = attr.value; + + if (attrValue === '{$uid}') + attrValue = 'mce_' + idCount++; + + attrList.map[name] = attrValue; + attrList.push({name: name, value: attrValue}); + } + } + + // Handle default attributes + if (attributesDefault) { + i = attributesDefault.length; + while (i--) { + attr = attributesDefault[i]; + name = attr.name; + + if (!(name in attrList.map)) { + attrValue = attr.value; + + if (attrValue === '{$uid}') + attrValue = 'mce_' + idCount++; + + attrList.map[name] = attrValue; + attrList.push({name: name, value: attrValue}); + } + } + } + + // Handle required attributes + if (attributesRequired) { + i = attributesRequired.length; + while (i--) { + if (attributesRequired[i] in attrList.map) + break; + } + + // None of the required attributes where found + if (i === -1) + isValidElement = false; + } + + // Invalidate element if it's marked as bogus + if (attrList.map['data-mce-bogus']) + isValidElement = false; + } + + if (isValidElement) + self.start(value, attrList, isShortEnded); + } else + isValidElement = false; + + // Treat script, noscript and style a bit different since they may include code that looks like elements + if (endRegExp = specialElements[value]) { + endRegExp.lastIndex = index = matches.index + matches[0].length; + + if (matches = endRegExp.exec(html)) { + if (isValidElement) + text = html.substr(index, matches.index - index); + + index = matches.index + matches[0].length; + } else { + text = html.substr(index); + index = html.length; + } + + if (isValidElement && text.length > 0) + self.text(text, true); + + if (isValidElement) + self.end(value); + + tokenRegExp.lastIndex = index; + continue; + } + + // Push value on to stack + if (!isShortEnded) { + if (!attribsValue || attribsValue.indexOf('/') != attribsValue.length - 1) + stack.push({name: value, valid: isValidElement}); + else if (isValidElement) + self.end(value); + } + } else if (value = matches[1]) { // Comment + self.comment(value); + } else if (value = matches[2]) { // CDATA + self.cdata(value); + } else if (value = matches[3]) { // DOCTYPE + self.doctype(value); + } else if (value = matches[4]) { // PI + self.pi(value, matches[5]); + } + + index = matches.index + matches[0].length; + } + + // Text + if (index < html.length) + self.text(decode(html.substr(index))); + + // Close any open elements + for (i = stack.length - 1; i >= 0; i--) { + value = stack[i]; + + if (value.valid) + self.end(value.name); + } + }; + } +})(tinymce); + +(function(tinymce) { + var whiteSpaceRegExp = /^[ \t\r\n]*$/, typeLookup = { + '#text' : 3, + '#comment' : 8, + '#cdata' : 4, + '#pi' : 7, + '#doctype' : 10, + '#document-fragment' : 11 + }; + + // Walks the tree left/right + function walk(node, root_node, prev) { + var sibling, parent, startName = prev ? 'lastChild' : 'firstChild', siblingName = prev ? 'prev' : 'next'; + + // Walk into nodes if it has a start + if (node[startName]) + return node[startName]; + + // Return the sibling if it has one + if (node !== root_node) { + sibling = node[siblingName]; + + if (sibling) + return sibling; + + // Walk up the parents to look for siblings + for (parent = node.parent; parent && parent !== root_node; parent = parent.parent) { + sibling = parent[siblingName]; + + if (sibling) + return sibling; + } + } + }; + + function Node(name, type) { + this.name = name; + this.type = type; + + if (type === 1) { + this.attributes = []; + this.attributes.map = {}; + } + } + + tinymce.extend(Node.prototype, { + replace : function(node) { + var self = this; + + if (node.parent) + node.remove(); + + self.insert(node, self); + self.remove(); + + return self; + }, + + attr : function(name, value) { + var self = this, attrs, i, undef; + + if (typeof name !== "string") { + for (i in name) + self.attr(i, name[i]); + + return self; + } + + if (attrs = self.attributes) { + if (value !== undef) { + // Remove attribute + if (value === null) { + if (name in attrs.map) { + delete attrs.map[name]; + + i = attrs.length; + while (i--) { + if (attrs[i].name === name) { + attrs = attrs.splice(i, 1); + return self; + } + } + } + + return self; + } + + // Set attribute + if (name in attrs.map) { + // Set attribute + i = attrs.length; + while (i--) { + if (attrs[i].name === name) { + attrs[i].value = value; + break; + } + } + } else + attrs.push({name: name, value: value}); + + attrs.map[name] = value; + + return self; + } else { + return attrs.map[name]; + } + } + }, + + clone : function() { + var self = this, clone = new Node(self.name, self.type), i, l, selfAttrs, selfAttr, cloneAttrs; + + // Clone element attributes + if (selfAttrs = self.attributes) { + cloneAttrs = []; + cloneAttrs.map = {}; + + for (i = 0, l = selfAttrs.length; i < l; i++) { + selfAttr = selfAttrs[i]; + + // Clone everything except id + if (selfAttr.name !== 'id') { + cloneAttrs[cloneAttrs.length] = {name: selfAttr.name, value: selfAttr.value}; + cloneAttrs.map[selfAttr.name] = selfAttr.value; + } + } + + clone.attributes = cloneAttrs; + } + + clone.value = self.value; + clone.shortEnded = self.shortEnded; + + return clone; + }, + + wrap : function(wrapper) { + var self = this; + + self.parent.insert(wrapper, self); + wrapper.append(self); + + return self; + }, + + unwrap : function() { + var self = this, node, next; + + for (node = self.firstChild; node; ) { + next = node.next; + self.insert(node, self, true); + node = next; + } + + self.remove(); + }, + + remove : function() { + var self = this, parent = self.parent, next = self.next, prev = self.prev; + + if (parent) { + if (parent.firstChild === self) { + parent.firstChild = next; + + if (next) + next.prev = null; + } else { + prev.next = next; + } + + if (parent.lastChild === self) { + parent.lastChild = prev; + + if (prev) + prev.next = null; + } else { + next.prev = prev; + } + + self.parent = self.next = self.prev = null; + } + + return self; + }, + + append : function(node) { + var self = this, last; + + if (node.parent) + node.remove(); + + last = self.lastChild; + if (last) { + last.next = node; + node.prev = last; + self.lastChild = node; + } else + self.lastChild = self.firstChild = node; + + node.parent = self; + + return node; + }, + + insert : function(node, ref_node, before) { + var parent; + + if (node.parent) + node.remove(); + + parent = ref_node.parent || this; + + if (before) { + if (ref_node === parent.firstChild) + parent.firstChild = node; + else + ref_node.prev.next = node; + + node.prev = ref_node.prev; + node.next = ref_node; + ref_node.prev = node; + } else { + if (ref_node === parent.lastChild) + parent.lastChild = node; + else + ref_node.next.prev = node; + + node.next = ref_node.next; + node.prev = ref_node; + ref_node.next = node; + } + + node.parent = parent; + + return node; + }, + + getAll : function(name) { + var self = this, node, collection = []; + + for (node = self.firstChild; node; node = walk(node, self)) { + if (node.name === name) + collection.push(node); + } + + return collection; + }, + + empty : function() { + var self = this, nodes, i, node; + + // Remove all children + if (self.firstChild) { + nodes = []; + + // Collect the children + for (node = self.firstChild; node; node = walk(node, self)) + nodes.push(node); + + // Remove the children + i = nodes.length; + while (i--) { + node = nodes[i]; + node.parent = node.firstChild = node.lastChild = node.next = node.prev = null; + } + } + + self.firstChild = self.lastChild = null; + + return self; + }, + + isEmpty : function(elements) { + var self = this, node = self.firstChild, i, name; + + if (node) { + do { + if (node.type === 1) { + // Ignore bogus elements + if (node.attributes.map['data-mce-bogus']) + continue; + + // Keep empty elements like <img /> + if (elements[node.name]) + return false; + + // Keep elements with data attributes or name attribute like <a name="1"></a> + i = node.attributes.length; + while (i--) { + name = node.attributes[i].name; + if (name === "name" || name.indexOf('data-') === 0) + return false; + } + } + + // Keep non whitespace text nodes + if ((node.type === 3 && !whiteSpaceRegExp.test(node.value))) + return false; + } while (node = walk(node, self)); + } + + return true; + }, + + walk : function(prev) { + return walk(this, null, prev); + } + }); + + tinymce.extend(Node, { + create : function(name, attrs) { + var node, attrName; + + // Create node + node = new Node(name, typeLookup[name] || 1); + + // Add attributes if needed + if (attrs) { + for (attrName in attrs) + node.attr(attrName, attrs[attrName]); + } + + return node; + } + }); + + tinymce.html.Node = Node; +})(tinymce); + +(function(tinymce) { + var Node = tinymce.html.Node; + + tinymce.html.DomParser = function(settings, schema) { + var self = this, nodeFilters = {}, attributeFilters = [], matchedNodes = {}, matchedAttributes = {}; + + settings = settings || {}; + settings.validate = "validate" in settings ? settings.validate : true; + settings.root_name = settings.root_name || 'body'; + self.schema = schema = schema || new tinymce.html.Schema(); + + function fixInvalidChildren(nodes) { + var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i, + childClone, nonEmptyElements, nonSplitableElements, sibling, nextNode; + + nonSplitableElements = tinymce.makeMap('tr,td,th,tbody,thead,tfoot,table'); + nonEmptyElements = schema.getNonEmptyElements(); + + for (ni = 0; ni < nodes.length; ni++) { + node = nodes[ni]; + + // Already removed + if (!node.parent) + continue; + + // Get list of all parent nodes until we find a valid parent to stick the child into + parents = [node]; + for (parent = node.parent; parent && !schema.isValidChild(parent.name, node.name) && !nonSplitableElements[parent.name]; parent = parent.parent) + parents.push(parent); + + // Found a suitable parent + if (parent && parents.length > 1) { + // Reverse the array since it makes looping easier + parents.reverse(); + + // Clone the related parent and insert that after the moved node + newParent = currentNode = self.filterNode(parents[0].clone()); + + // Start cloning and moving children on the left side of the target node + for (i = 0; i < parents.length - 1; i++) { + if (schema.isValidChild(currentNode.name, parents[i].name)) { + tempNode = self.filterNode(parents[i].clone()); + currentNode.append(tempNode); + } else + tempNode = currentNode; + + for (childNode = parents[i].firstChild; childNode && childNode != parents[i + 1]; ) { + nextNode = childNode.next; + tempNode.append(childNode); + childNode = nextNode; + } + + currentNode = tempNode; + } + + if (!newParent.isEmpty(nonEmptyElements)) { + parent.insert(newParent, parents[0], true); + parent.insert(node, newParent); + } else { + parent.insert(node, parents[0], true); + } + + // Check if the element is empty by looking through it's contents and special treatment for <p><br /></p> + parent = parents[0]; + if (parent.isEmpty(nonEmptyElements) || parent.firstChild === parent.lastChild && parent.firstChild.name === 'br') { + parent.empty().remove(); + } + } else if (node.parent) { + // If it's an LI try to find a UL/OL for it or wrap it + if (node.name === 'li') { + sibling = node.prev; + if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) { + sibling.append(node); + continue; + } + + sibling = node.next; + if (sibling && (sibling.name === 'ul' || sibling.name === 'ul')) { + sibling.insert(node, sibling.firstChild, true); + continue; + } + + node.wrap(self.filterNode(new Node('ul', 1))); + continue; + } + + // Try wrapping the element in a DIV + if (schema.isValidChild(node.parent.name, 'div') && schema.isValidChild('div', node.name)) { + node.wrap(self.filterNode(new Node('div', 1))); + } else { + // We failed wrapping it, then remove or unwrap it + if (node.name === 'style' || node.name === 'script') + node.empty().remove(); + else + node.unwrap(); + } + } + } + }; + + self.filterNode = function(node) { + var i, name, list; + + // Run element filters + if (name in nodeFilters) { + list = matchedNodes[name]; + + if (list) + list.push(node); + else + matchedNodes[name] = [node]; + } + + // Run attribute filters + i = attributeFilters.length; + while (i--) { + name = attributeFilters[i].name; + + if (name in node.attributes.map) { + list = matchedAttributes[name]; + + if (list) + list.push(node); + else + matchedAttributes[name] = [node]; + } + } + + return node; + }; + + self.addNodeFilter = function(name, callback) { + tinymce.each(tinymce.explode(name), function(name) { + var list = nodeFilters[name]; + + if (!list) + nodeFilters[name] = list = []; + + list.push(callback); + }); + }; + + self.addAttributeFilter = function(name, callback) { + tinymce.each(tinymce.explode(name), function(name) { + var i; + + for (i = 0; i < attributeFilters.length; i++) { + if (attributeFilters[i].name === name) { + attributeFilters[i].callbacks.push(callback); + return; + } + } + + attributeFilters.push({name: name, callbacks: [callback]}); + }); + }; + + self.parse = function(html, args) { + var parser, rootNode, node, nodes, i, l, fi, fl, list, name, validate, + blockElements, startWhiteSpaceRegExp, invalidChildren = [], + endWhiteSpaceRegExp, allWhiteSpaceRegExp, whiteSpaceElements, children, nonEmptyElements, rootBlockName; + + args = args || {}; + matchedNodes = {}; + matchedAttributes = {}; + blockElements = tinymce.extend(tinymce.makeMap('script,style,head,html,body,title,meta,param'), schema.getBlockElements()); + nonEmptyElements = schema.getNonEmptyElements(); + children = schema.children; + validate = settings.validate; + rootBlockName = "forced_root_block" in args ? args.forced_root_block : settings.forced_root_block; + + whiteSpaceElements = schema.getWhiteSpaceElements(); + startWhiteSpaceRegExp = /^[ \t\r\n]+/; + endWhiteSpaceRegExp = /[ \t\r\n]+$/; + allWhiteSpaceRegExp = /[ \t\r\n]+/g; + + function addRootBlocks() { + var node = rootNode.firstChild, next, rootBlockNode; + + while (node) { + next = node.next; + + if (node.type == 3 || (node.type == 1 && node.name !== 'p' && !blockElements[node.name] && !node.attr('data-mce-type'))) { + if (!rootBlockNode) { + // Create a new root block element + rootBlockNode = createNode(rootBlockName, 1); + rootNode.insert(rootBlockNode, node); + rootBlockNode.append(node); + } else + rootBlockNode.append(node); + } else { + rootBlockNode = null; + } + + node = next; + }; + }; + + function createNode(name, type) { + var node = new Node(name, type), list; + + if (name in nodeFilters) { + list = matchedNodes[name]; + + if (list) + list.push(node); + else + matchedNodes[name] = [node]; + } + + return node; + }; + + function removeWhitespaceBefore(node) { + var textNode, textVal, sibling; + + for (textNode = node.prev; textNode && textNode.type === 3; ) { + textVal = textNode.value.replace(endWhiteSpaceRegExp, ''); + + if (textVal.length > 0) { + textNode.value = textVal; + textNode = textNode.prev; + } else { + sibling = textNode.prev; + textNode.remove(); + textNode = sibling; + } + } + }; + + parser = new tinymce.html.SaxParser({ + validate : validate, + fix_self_closing : !validate, // Let the DOM parser handle <li> in <li> or <p> in <p> for better results + + cdata: function(text) { + node.append(createNode('#cdata', 4)).value = text; + }, + + text: function(text, raw) { + var textNode; + + // Trim all redundant whitespace on non white space elements + if (!whiteSpaceElements[node.name]) { + text = text.replace(allWhiteSpaceRegExp, ' '); + + if (node.lastChild && blockElements[node.lastChild.name]) + text = text.replace(startWhiteSpaceRegExp, ''); + } + + // Do we need to create the node + if (text.length !== 0) { + textNode = createNode('#text', 3); + textNode.raw = !!raw; + node.append(textNode).value = text; + } + }, + + comment: function(text) { + node.append(createNode('#comment', 8)).value = text; + }, + + pi: function(name, text) { + node.append(createNode(name, 7)).value = text; + removeWhitespaceBefore(node); + }, + + doctype: function(text) { + var newNode; + + newNode = node.append(createNode('#doctype', 10)); + newNode.value = text; + removeWhitespaceBefore(node); + }, + + start: function(name, attrs, empty) { + var newNode, attrFiltersLen, elementRule, textNode, attrName, text, sibling, parent; + + elementRule = validate ? schema.getElementRule(name) : {}; + if (elementRule) { + newNode = createNode(elementRule.outputName || name, 1); + newNode.attributes = attrs; + newNode.shortEnded = empty; + + node.append(newNode); + + // Check if node is valid child of the parent node is the child is + // unknown we don't collect it since it's probably a custom element + parent = children[node.name]; + if (parent && children[newNode.name] && !parent[newNode.name]) + invalidChildren.push(newNode); + + attrFiltersLen = attributeFilters.length; + while (attrFiltersLen--) { + attrName = attributeFilters[attrFiltersLen].name; + + if (attrName in attrs.map) { + list = matchedAttributes[attrName]; + + if (list) + list.push(newNode); + else + matchedAttributes[attrName] = [newNode]; + } + } + + // Trim whitespace before block + if (blockElements[name]) + removeWhitespaceBefore(newNode); + + // Change current node if the element wasn't empty i.e not <br /> or <img /> + if (!empty) + node = newNode; + } + }, + + end: function(name) { + var textNode, elementRule, text, sibling, tempNode; + + elementRule = validate ? schema.getElementRule(name) : {}; + if (elementRule) { + if (blockElements[name]) { + if (!whiteSpaceElements[node.name]) { + // Trim whitespace at beginning of block + for (textNode = node.firstChild; textNode && textNode.type === 3; ) { + text = textNode.value.replace(startWhiteSpaceRegExp, ''); + + if (text.length > 0) { + textNode.value = text; + textNode = textNode.next; + } else { + sibling = textNode.next; + textNode.remove(); + textNode = sibling; + } + } + + // Trim whitespace at end of block + for (textNode = node.lastChild; textNode && textNode.type === 3; ) { + text = textNode.value.replace(endWhiteSpaceRegExp, ''); + + if (text.length > 0) { + textNode.value = text; + textNode = textNode.prev; + } else { + sibling = textNode.prev; + textNode.remove(); + textNode = sibling; + } + } + } + + // Trim start white space + textNode = node.prev; + if (textNode && textNode.type === 3) { + text = textNode.value.replace(startWhiteSpaceRegExp, ''); + + if (text.length > 0) + textNode.value = text; + else + textNode.remove(); + } + } + + // Handle empty nodes + if (elementRule.removeEmpty || elementRule.paddEmpty) { + if (node.isEmpty(nonEmptyElements)) { + if (elementRule.paddEmpty) + node.empty().append(new Node('#text', '3')).value = '\u00a0'; + else { + // Leave nodes that have a name like <a name="name"> + if (!node.attributes.map.name) { + tempNode = node.parent; + node.empty().remove(); + node = tempNode; + return; + } + } + } + } + + node = node.parent; + } + } + }, schema); + + rootNode = node = new Node(args.context || settings.root_name, 11); + + parser.parse(html); + + // Fix invalid children or report invalid children in a contextual parsing + if (validate && invalidChildren.length) { + if (!args.context) + fixInvalidChildren(invalidChildren); + else + args.invalid = true; + } + + // Wrap nodes in the root into block elements if the root is body + if (rootBlockName && rootNode.name == 'body') + addRootBlocks(); + + // Run filters only when the contents is valid + if (!args.invalid) { + // Run node filters + for (name in matchedNodes) { + list = nodeFilters[name]; + nodes = matchedNodes[name]; + + // Remove already removed children + fi = nodes.length; + while (fi--) { + if (!nodes[fi].parent) + nodes.splice(fi, 1); + } + + for (i = 0, l = list.length; i < l; i++) + list[i](nodes, name, args); + } + + // Run attribute filters + for (i = 0, l = attributeFilters.length; i < l; i++) { + list = attributeFilters[i]; + + if (list.name in matchedAttributes) { + nodes = matchedAttributes[list.name]; + + // Remove already removed children + fi = nodes.length; + while (fi--) { + if (!nodes[fi].parent) + nodes.splice(fi, 1); + } + + for (fi = 0, fl = list.callbacks.length; fi < fl; fi++) + list.callbacks[fi](nodes, list.name, args); + } + } + } + + return rootNode; + }; + + // Remove <br> at end of block elements Gecko and WebKit injects BR elements to + // make it possible to place the caret inside empty blocks. This logic tries to remove + // these elements and keep br elements that where intended to be there intact + if (settings.remove_trailing_brs) { + self.addNodeFilter('br', function(nodes, name) { + var i, l = nodes.length, node, blockElements = schema.getBlockElements(), + nonEmptyElements = schema.getNonEmptyElements(), parent, prev, prevName; + + // Remove brs from body element as well + blockElements.body = 1; + + // Must loop forwards since it will otherwise remove all brs in <p>a<br><br><br></p> + for (i = 0; i < l; i++) { + node = nodes[i]; + parent = node.parent; + + if (blockElements[node.parent.name] && node === parent.lastChild) { + // Loop all nodes to the right of the current node and check for other BR elements + // excluding bookmarks since they are invisible + prev = node.prev; + while (prev) { + prevName = prev.name; + + // Ignore bookmarks + if (prevName !== "span" || prev.attr('data-mce-type') !== 'bookmark') { + // Found a non BR element + if (prevName !== "br") + break; + + // Found another br it's a <br><br> structure then don't remove anything + if (prevName === 'br') { + node = null; + break; + } + } + + prev = prev.prev; + } + + if (node) { + node.remove(); + + // Is the parent to be considered empty after we removed the BR + if (parent.isEmpty(nonEmptyElements)) { + elementRule = schema.getElementRule(parent.name); + + // Remove or padd the element depending on schema rule + if (elementRule) { + if (elementRule.removeEmpty) + parent.remove(); + else if (elementRule.paddEmpty) + parent.empty().append(new tinymce.html.Node('#text', 3)).value = '\u00a0'; + } + } + } + } + } + }); + } + } +})(tinymce); + +tinymce.html.Writer = function(settings) { + var html = [], indent, indentBefore, indentAfter, encode, htmlOutput; + + settings = settings || {}; + indent = settings.indent; + indentBefore = tinymce.makeMap(settings.indent_before || ''); + indentAfter = tinymce.makeMap(settings.indent_after || ''); + encode = tinymce.html.Entities.getEncodeFunc(settings.entity_encoding || 'raw', settings.entities); + htmlOutput = settings.element_format == "html"; + + return { + start: function(name, attrs, empty) { + var i, l, attr, value; + + if (indent && indentBefore[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + } + + html.push('<', name); + + if (attrs) { + for (i = 0, l = attrs.length; i < l; i++) { + attr = attrs[i]; + html.push(' ', attr.name, '="', encode(attr.value, true), '"'); + } + } + + if (!empty || htmlOutput) + html[html.length] = '>'; + else + html[html.length] = ' />'; + + if (empty && indent && indentAfter[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + } + }, + + end: function(name) { + var value; + + /*if (indent && indentBefore[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + }*/ + + html.push('</', name, '>'); + + if (indent && indentAfter[name] && html.length > 0) { + value = html[html.length - 1]; + + if (value.length > 0 && value !== '\n') + html.push('\n'); + } + }, + + text: function(text, raw) { + if (text.length > 0) + html[html.length] = raw ? text : encode(text); + }, + + cdata: function(text) { + html.push('<![CDATA[', text, ']]>'); + }, + + comment: function(text) { + html.push('<!--', text, '-->'); + }, + + pi: function(name, text) { + if (text) + html.push('<?', name, ' ', text, '?>'); + else + html.push('<?', name, '?>'); + + if (indent) + html.push('\n'); + }, + + doctype: function(text) { + html.push('<!DOCTYPE', text, '>', indent ? '\n' : ''); + }, + + reset: function() { + html.length = 0; + }, + + getContent: function() { + return html.join('').replace(/\n$/, ''); + } + }; +}; + +(function(tinymce) { + tinymce.html.Serializer = function(settings, schema) { + var self = this, writer = new tinymce.html.Writer(settings); + + settings = settings || {}; + settings.validate = "validate" in settings ? settings.validate : true; + + self.schema = schema = schema || new tinymce.html.Schema(); + self.writer = writer; + + self.serialize = function(node) { + var handlers, validate; + + validate = settings.validate; + + handlers = { + // #text + 3: function(node, raw) { + writer.text(node.value, node.raw); + }, + + // #comment + 8: function(node) { + writer.comment(node.value); + }, + + // Processing instruction + 7: function(node) { + writer.pi(node.name, node.value); + }, + + // Doctype + 10: function(node) { + writer.doctype(node.value); + }, + + // CDATA + 4: function(node) { + writer.cdata(node.value); + }, + + // Document fragment + 11: function(node) { + if ((node = node.firstChild)) { + do { + walk(node); + } while (node = node.next); + } + } + }; + + writer.reset(); + + function walk(node) { + var handler = handlers[node.type], name, isEmpty, attrs, attrName, attrValue, sortedAttrs, i, l, elementRule; + + if (!handler) { + name = node.name; + isEmpty = node.shortEnded; + attrs = node.attributes; + + // Sort attributes + if (validate && attrs && attrs.length > 1) { + sortedAttrs = []; + sortedAttrs.map = {}; + + elementRule = schema.getElementRule(node.name); + for (i = 0, l = elementRule.attributesOrder.length; i < l; i++) { + attrName = elementRule.attributesOrder[i]; + + if (attrName in attrs.map) { + attrValue = attrs.map[attrName]; + sortedAttrs.map[attrName] = attrValue; + sortedAttrs.push({name: attrName, value: attrValue}); + } + } + + for (i = 0, l = attrs.length; i < l; i++) { + attrName = attrs[i].name; + + if (!(attrName in sortedAttrs.map)) { + attrValue = attrs.map[attrName]; + sortedAttrs.map[attrName] = attrValue; + sortedAttrs.push({name: attrName, value: attrValue}); + } + } + + attrs = sortedAttrs; + } + + writer.start(node.name, attrs, isEmpty); + + if (!isEmpty) { + if ((node = node.firstChild)) { + do { + walk(node); + } while (node = node.next); + } + + writer.end(name); + } + } else + handler(node); + } + + // Serialize element and treat all non elements as fragments + if (node.type == 1 && !settings.inner) + walk(node); + else + handlers[11](node); + + return writer.getContent(); + }; + } +})(tinymce); + +(function(tinymce) { + // Shorten names + var each = tinymce.each, + is = tinymce.is, + isWebKit = tinymce.isWebKit, + isIE = tinymce.isIE, + Entities = tinymce.html.Entities, + simpleSelectorRe = /^([a-z0-9],?)+$/i, + blockElementsMap = tinymce.html.Schema.blockElementsMap, + whiteSpaceRegExp = /^[ \t\r\n]*$/; + + tinymce.create('tinymce.dom.DOMUtils', { + doc : null, + root : null, + files : null, + pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/, + props : { + "for" : "htmlFor", + "class" : "className", + className : "className", + checked : "checked", + disabled : "disabled", + maxlength : "maxLength", + readonly : "readOnly", + selected : "selected", + value : "value", + id : "id", + name : "name", + type : "type" + }, + + DOMUtils : function(d, s) { + var t = this, globalStyle, name; + + t.doc = d; + t.win = window; + t.files = {}; + t.cssFlicker = false; + t.counter = 0; + t.stdMode = !tinymce.isIE || d.documentMode >= 8; + t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat" || t.stdMode; + t.hasOuterHTML = "outerHTML" in d.createElement("a"); + + t.settings = s = tinymce.extend({ + keep_values : false, + hex_colors : 1 + }, s); + + t.schema = s.schema; + t.styles = new tinymce.html.Styles({ + url_converter : s.url_converter, + url_converter_scope : s.url_converter_scope + }, s.schema); + + // Fix IE6SP2 flicker and check it failed for pre SP2 + if (tinymce.isIE6) { + try { + d.execCommand('BackgroundImageCache', false, true); + } catch (e) { + t.cssFlicker = true; + } + } + + if (isIE && s.schema) { + // Add missing HTML 4/5 elements to IE + ('abbr article aside audio canvas ' + + 'details figcaption figure footer ' + + 'header hgroup mark menu meter nav ' + + 'output progress section summary ' + + 'time video').replace(/\w+/g, function(name) { + d.createElement(name); + }); + + // Create all custom elements + for (name in s.schema.getCustomElements()) { + d.createElement(name); + } + } + + tinymce.addUnload(t.destroy, t); + }, + + getRoot : function() { + var t = this, s = t.settings; + + return (s && t.get(s.root_element)) || t.doc.body; + }, + + getViewPort : function(w) { + var d, b; + + w = !w ? this.win : w; + d = w.document; + b = this.boxModel ? d.documentElement : d.body; + + // Returns viewport size excluding scrollbars + return { + x : w.pageXOffset || b.scrollLeft, + y : w.pageYOffset || b.scrollTop, + w : w.innerWidth || b.clientWidth, + h : w.innerHeight || b.clientHeight + }; + }, + + getRect : function(e) { + var p, t = this, sr; + + e = t.get(e); + p = t.getPos(e); + sr = t.getSize(e); + + return { + x : p.x, + y : p.y, + w : sr.w, + h : sr.h + }; + }, + + getSize : function(e) { + var t = this, w, h; + + e = t.get(e); + w = t.getStyle(e, 'width'); + h = t.getStyle(e, 'height'); + + // Non pixel value, then force offset/clientWidth + if (w.indexOf('px') === -1) + w = 0; + + // Non pixel value, then force offset/clientWidth + if (h.indexOf('px') === -1) + h = 0; + + return { + w : parseInt(w) || e.offsetWidth || e.clientWidth, + h : parseInt(h) || e.offsetHeight || e.clientHeight + }; + }, + + getParent : function(n, f, r) { + return this.getParents(n, f, r, false); + }, + + getParents : function(n, f, r, c) { + var t = this, na, se = t.settings, o = []; + + n = t.get(n); + c = c === undefined; + + if (se.strict_root) + r = r || t.getRoot(); + + // Wrap node name as func + if (is(f, 'string')) { + na = f; + + if (f === '*') { + f = function(n) {return n.nodeType == 1;}; + } else { + f = function(n) { + return t.is(n, na); + }; + } + } + + while (n) { + if (n == r || !n.nodeType || n.nodeType === 9) + break; + + if (!f || f(n)) { + if (c) + o.push(n); + else + return n; + } + + n = n.parentNode; + } + + return c ? o : null; + }, + + get : function(e) { + var n; + + if (e && this.doc && typeof(e) == 'string') { + n = e; + e = this.doc.getElementById(e); + + // IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick + if (e && e.id !== n) + return this.doc.getElementsByName(n)[1]; + } + + return e; + }, + + getNext : function(node, selector) { + return this._findSib(node, selector, 'nextSibling'); + }, + + getPrev : function(node, selector) { + return this._findSib(node, selector, 'previousSibling'); + }, + + + select : function(pa, s) { + var t = this; + + return tinymce.dom.Sizzle(pa, t.get(s) || t.get(t.settings.root_element) || t.doc, []); + }, + + is : function(n, selector) { + var i; + + // If it isn't an array then try to do some simple selectors instead of Sizzle for to boost performance + if (n.length === undefined) { + // Simple all selector + if (selector === '*') + return n.nodeType == 1; + + // Simple selector just elements + if (simpleSelectorRe.test(selector)) { + selector = selector.toLowerCase().split(/,/); + n = n.nodeName.toLowerCase(); + + for (i = selector.length - 1; i >= 0; i--) { + if (selector[i] == n) + return true; + } + + return false; + } + } + + return tinymce.dom.Sizzle.matches(selector, n.nodeType ? [n] : n).length > 0; + }, + + + add : function(p, n, a, h, c) { + var t = this; + + return this.run(p, function(p) { + var e, k; + + e = is(n, 'string') ? t.doc.createElement(n) : n; + t.setAttribs(e, a); + + if (h) { + if (h.nodeType) + e.appendChild(h); + else + t.setHTML(e, h); + } + + return !c ? p.appendChild(e) : e; + }); + }, + + create : function(n, a, h) { + return this.add(this.doc.createElement(n), n, a, h, 1); + }, + + createHTML : function(n, a, h) { + var o = '', t = this, k; + + o += '<' + n; + + for (k in a) { + if (a.hasOwnProperty(k)) + o += ' ' + k + '="' + t.encode(a[k]) + '"'; + } + + // A call to tinymce.is doesn't work for some odd reason on IE9 possible bug inside their JS runtime + if (typeof(h) != "undefined") + return o + '>' + h + '</' + n + '>'; + + return o + ' />'; + }, + + remove : function(node, keep_children) { + return this.run(node, function(node) { + var child, parent = node.parentNode; + + if (!parent) + return null; + + if (keep_children) { + while (child = node.firstChild) { + // IE 8 will crash if you don't remove completely empty text nodes + if (!tinymce.isIE || child.nodeType !== 3 || child.nodeValue) + parent.insertBefore(child, node); + else + node.removeChild(child); + } + } + + return parent.removeChild(node); + }); + }, + + setStyle : function(n, na, v) { + var t = this; + + return t.run(n, function(e) { + var s, i; + + s = e.style; + + // Camelcase it, if needed + na = na.replace(/-(\D)/g, function(a, b){ + return b.toUpperCase(); + }); + + // Default px suffix on these + if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v))) + v += 'px'; + + switch (na) { + case 'opacity': + // IE specific opacity + if (isIE) { + s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")"; + + if (!n.currentStyle || !n.currentStyle.hasLayout) + s.display = 'inline-block'; + } + + // Fix for older browsers + s[na] = s['-moz-opacity'] = s['-khtml-opacity'] = v || ''; + break; + + case 'float': + isIE ? s.styleFloat = v : s.cssFloat = v; + break; + + default: + s[na] = v || ''; + } + + // Force update of the style data + if (t.settings.update_styles) + t.setAttrib(e, 'data-mce-style'); + }); + }, + + getStyle : function(n, na, c) { + n = this.get(n); + + if (!n) + return; + + // Gecko + if (this.doc.defaultView && c) { + // Remove camelcase + na = na.replace(/[A-Z]/g, function(a){ + return '-' + a; + }); + + try { + return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na); + } catch (ex) { + // Old safari might fail + return null; + } + } + + // Camelcase it, if needed + na = na.replace(/-(\D)/g, function(a, b){ + return b.toUpperCase(); + }); + + if (na == 'float') + na = isIE ? 'styleFloat' : 'cssFloat'; + + // IE & Opera + if (n.currentStyle && c) + return n.currentStyle[na]; + + return n.style ? n.style[na] : undefined; + }, + + setStyles : function(e, o) { + var t = this, s = t.settings, ol; + + ol = s.update_styles; + s.update_styles = 0; + + each(o, function(v, n) { + t.setStyle(e, n, v); + }); + + // Update style info + s.update_styles = ol; + if (s.update_styles) + t.setAttrib(e, s.cssText); + }, + + removeAllAttribs: function(e) { + return this.run(e, function(e) { + var i, attrs = e.attributes; + for (i = attrs.length - 1; i >= 0; i--) { + e.removeAttributeNode(attrs.item(i)); + } + }); + }, + + setAttrib : function(e, n, v) { + var t = this; + + // Whats the point + if (!e || !n) + return; + + // Strict XML mode + if (t.settings.strict) + n = n.toLowerCase(); + + return this.run(e, function(e) { + var s = t.settings; + + switch (n) { + case "style": + if (!is(v, 'string')) { + each(v, function(v, n) { + t.setStyle(e, n, v); + }); + + return; + } + + // No mce_style for elements with these since they might get resized by the user + if (s.keep_values) { + if (v && !t._isRes(v)) + e.setAttribute('data-mce-style', v, 2); + else + e.removeAttribute('data-mce-style', 2); + } + + e.style.cssText = v; + break; + + case "class": + e.className = v || ''; // Fix IE null bug + break; + + case "src": + case "href": + if (s.keep_values) { + if (s.url_converter) + v = s.url_converter.call(s.url_converter_scope || t, v, n, e); + + t.setAttrib(e, 'data-mce-' + n, v, 2); + } + + break; + + case "shape": + e.setAttribute('data-mce-style', v); + break; + } + + if (is(v) && v !== null && v.length !== 0) + e.setAttribute(n, '' + v, 2); + else + e.removeAttribute(n, 2); + }); + }, + + setAttribs : function(e, o) { + var t = this; + + return this.run(e, function(e) { + each(o, function(v, n) { + t.setAttrib(e, n, v); + }); + }); + }, + + getAttrib : function(e, n, dv) { + var v, t = this, undef; + + e = t.get(e); + + if (!e || e.nodeType !== 1) + return dv === undef ? false : dv; + + if (!is(dv)) + dv = ''; + + // Try the mce variant for these + if (/^(src|href|style|coords|shape)$/.test(n)) { + v = e.getAttribute("data-mce-" + n); + + if (v) + return v; + } + + if (isIE && t.props[n]) { + v = e[t.props[n]]; + v = v && v.nodeValue ? v.nodeValue : v; + } + + if (!v) + v = e.getAttribute(n, 2); + + // Check boolean attribs + if (/^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noshade|nowrap|readonly|selected)$/.test(n)) { + if (e[t.props[n]] === true && v === '') + return n; + + return v ? n : ''; + } + + // Inner input elements will override attributes on form elements + if (e.nodeName === "FORM" && e.getAttributeNode(n)) + return e.getAttributeNode(n).nodeValue; + + if (n === 'style') { + v = v || e.style.cssText; + + if (v) { + v = t.serializeStyle(t.parseStyle(v), e.nodeName); + + if (t.settings.keep_values && !t._isRes(v)) + e.setAttribute('data-mce-style', v); + } + } + + // Remove Apple and WebKit stuff + if (isWebKit && n === "class" && v) + v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, ''); + + // Handle IE issues + if (isIE) { + switch (n) { + case 'rowspan': + case 'colspan': + // IE returns 1 as default value + if (v === 1) + v = ''; + + break; + + case 'size': + // IE returns +0 as default value for size + if (v === '+0' || v === 20 || v === 0) + v = ''; + + break; + + case 'width': + case 'height': + case 'vspace': + case 'checked': + case 'disabled': + case 'readonly': + if (v === 0) + v = ''; + + break; + + case 'hspace': + // IE returns -1 as default value + if (v === -1) + v = ''; + + break; + + case 'maxlength': + case 'tabindex': + // IE returns default value + if (v === 32768 || v === 2147483647 || v === '32768') + v = ''; + + break; + + case 'multiple': + case 'compact': + case 'noshade': + case 'nowrap': + if (v === 65535) + return n; + + return dv; + + case 'shape': + v = v.toLowerCase(); + break; + + default: + // IE has odd anonymous function for event attributes + if (n.indexOf('on') === 0 && v) + v = tinymce._replace(/^function\s+\w+\(\)\s+\{\s+(.*)\s+\}$/, '$1', '' + v); + } + } + + return (v !== undef && v !== null && v !== '') ? '' + v : dv; + }, + + getPos : function(n, ro) { + var t = this, x = 0, y = 0, e, d = t.doc, r; + + n = t.get(n); + ro = ro || d.body; + + if (n) { + // Use getBoundingClientRect if it exists since it's faster than looping offset nodes + if (n.getBoundingClientRect) { + n = n.getBoundingClientRect(); + e = t.boxModel ? d.documentElement : d.body; + + // Add scroll offsets from documentElement or body since IE with the wrong box model will use d.body and so do WebKit + // Also remove the body/documentelement clientTop/clientLeft on IE 6, 7 since they offset the position + x = n.left + (d.documentElement.scrollLeft || d.body.scrollLeft) - e.clientTop; + y = n.top + (d.documentElement.scrollTop || d.body.scrollTop) - e.clientLeft; + + return {x : x, y : y}; + } + + r = n; + while (r && r != ro && r.nodeType) { + x += r.offsetLeft || 0; + y += r.offsetTop || 0; + r = r.offsetParent; + } + + r = n.parentNode; + while (r && r != ro && r.nodeType) { + x -= r.scrollLeft || 0; + y -= r.scrollTop || 0; + r = r.parentNode; + } + } + + return {x : x, y : y}; + }, + + parseStyle : function(st) { + return this.styles.parse(st); + }, + + serializeStyle : function(o, name) { + return this.styles.serialize(o, name); + }, + + loadCSS : function(u) { + var t = this, d = t.doc, head; + + if (!u) + u = ''; + + head = t.select('head')[0]; + + each(u.split(','), function(u) { + var link; + + if (t.files[u]) + return; + + t.files[u] = true; + link = t.create('link', {rel : 'stylesheet', href : tinymce._addVer(u)}); + + // IE 8 has a bug where dynamically loading stylesheets would produce a 1 item remaining bug + // This fix seems to resolve that issue by realcing the document ones a stylesheet finishes loading + // It's ugly but it seems to work fine. + if (isIE && d.documentMode && d.recalc) { + link.onload = function() { + if (d.recalc) + d.recalc(); + + link.onload = null; + }; + } + + head.appendChild(link); + }); + }, + + addClass : function(e, c) { + return this.run(e, function(e) { + var o; + + if (!c) + return 0; + + if (this.hasClass(e, c)) + return e.className; + + o = this.removeClass(e, c); + + return e.className = (o != '' ? (o + ' ') : '') + c; + }); + }, + + removeClass : function(e, c) { + var t = this, re; + + return t.run(e, function(e) { + var v; + + if (t.hasClass(e, c)) { + if (!re) + re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g"); + + v = e.className.replace(re, ' '); + v = tinymce.trim(v != ' ' ? v : ''); + + e.className = v; + + // Empty class attr + if (!v) { + e.removeAttribute('class'); + e.removeAttribute('className'); + } + + return v; + } + + return e.className; + }); + }, + + hasClass : function(n, c) { + n = this.get(n); + + if (!n || !c) + return false; + + return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1; + }, + + show : function(e) { + return this.setStyle(e, 'display', 'block'); + }, + + hide : function(e) { + return this.setStyle(e, 'display', 'none'); + }, + + isHidden : function(e) { + e = this.get(e); + + return !e || e.style.display == 'none' || this.getStyle(e, 'display') == 'none'; + }, + + uniqueId : function(p) { + return (!p ? 'mce_' : p) + (this.counter++); + }, + + setHTML : function(element, html) { + var self = this; + + return self.run(element, function(element) { + if (isIE) { + // Remove all child nodes, IE keeps empty text nodes in DOM + while (element.firstChild) + element.removeChild(element.firstChild); + + try { + // IE will remove comments from the beginning + // unless you padd the contents with something + element.innerHTML = '<br />' + html; + element.removeChild(element.firstChild); + } catch (ex) { + // IE sometimes produces an unknown runtime error on innerHTML if it's an block element within a block element for example a div inside a p + // This seems to fix this problem + + // Create new div with HTML contents and a BR infront to keep comments + element = self.create('div'); + element.innerHTML = '<br />' + html; + + // Add all children from div to target + each (element.childNodes, function(node, i) { + // Skip br element + if (i) + element.appendChild(node); + }); + } + } else + element.innerHTML = html; + + return html; + }); + }, + + getOuterHTML : function(elm) { + var doc, self = this; + + elm = self.get(elm); + + if (!elm) + return null; + + if (elm.nodeType === 1 && self.hasOuterHTML) + return elm.outerHTML; + + doc = (elm.ownerDocument || self.doc).createElement("body"); + doc.appendChild(elm.cloneNode(true)); + + return doc.innerHTML; + }, + + setOuterHTML : function(e, h, d) { + var t = this; + + function setHTML(e, h, d) { + var n, tp; + + tp = d.createElement("body"); + tp.innerHTML = h; + + n = tp.lastChild; + while (n) { + t.insertAfter(n.cloneNode(true), e); + n = n.previousSibling; + } + + t.remove(e); + }; + + return this.run(e, function(e) { + e = t.get(e); + + // Only set HTML on elements + if (e.nodeType == 1) { + d = d || e.ownerDocument || t.doc; + + if (isIE) { + try { + // Try outerHTML for IE it sometimes produces an unknown runtime error + if (isIE && e.nodeType == 1) + e.outerHTML = h; + else + setHTML(e, h, d); + } catch (ex) { + // Fix for unknown runtime error + setHTML(e, h, d); + } + } else + setHTML(e, h, d); + } + }); + }, + + decode : Entities.decode, + + encode : Entities.encodeAllRaw, + + insertAfter : function(node, reference_node) { + reference_node = this.get(reference_node); + + return this.run(node, function(node) { + var parent, nextSibling; + + parent = reference_node.parentNode; + nextSibling = reference_node.nextSibling; + + if (nextSibling) + parent.insertBefore(node, nextSibling); + else + parent.appendChild(node); + + return node; + }); + }, + + isBlock : function(node) { + var type = node.nodeType; + + // If it's a node then check the type and use the nodeName + if (type) + return !!(type === 1 && blockElementsMap[node.nodeName]); + + return !!blockElementsMap[node]; + }, + + replace : function(n, o, k) { + var t = this; + + if (is(o, 'array')) + n = n.cloneNode(true); + + return t.run(o, function(o) { + if (k) { + each(tinymce.grep(o.childNodes), function(c) { + n.appendChild(c); + }); + } + + return o.parentNode.replaceChild(n, o); + }); + }, + + rename : function(elm, name) { + var t = this, newElm; + + if (elm.nodeName != name.toUpperCase()) { + // Rename block element + newElm = t.create(name); + + // Copy attribs to new block + each(t.getAttribs(elm), function(attr_node) { + t.setAttrib(newElm, attr_node.nodeName, t.getAttrib(elm, attr_node.nodeName)); + }); + + // Replace block + t.replace(newElm, elm, 1); + } + + return newElm || elm; + }, + + findCommonAncestor : function(a, b) { + var ps = a, pe; + + while (ps) { + pe = b; + + while (pe && ps != pe) + pe = pe.parentNode; + + if (ps == pe) + break; + + ps = ps.parentNode; + } + + if (!ps && a.ownerDocument) + return a.ownerDocument.documentElement; + + return ps; + }, + + toHex : function(s) { + var c = /^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s); + + function hex(s) { + s = parseInt(s).toString(16); + + return s.length > 1 ? s : '0' + s; // 0 -> 00 + }; + + if (c) { + s = '#' + hex(c[1]) + hex(c[2]) + hex(c[3]); + + return s; + } + + return s; + }, + + getClasses : function() { + var t = this, cl = [], i, lo = {}, f = t.settings.class_filter, ov; + + if (t.classes) + return t.classes; + + function addClasses(s) { + // IE style imports + each(s.imports, function(r) { + addClasses(r); + }); + + each(s.cssRules || s.rules, function(r) { + // Real type or fake it on IE + switch (r.type || 1) { + // Rule + case 1: + if (r.selectorText) { + each(r.selectorText.split(','), function(v) { + v = v.replace(/^\s*|\s*$|^\s\./g, ""); + + // Is internal or it doesn't contain a class + if (/\.mce/.test(v) || !/\.[\w\-]+$/.test(v)) + return; + + // Remove everything but class name + ov = v; + v = tinymce._replace(/.*\.([a-z0-9_\-]+).*/i, '$1', v); + + // Filter classes + if (f && !(v = f(v, ov))) + return; + + if (!lo[v]) { + cl.push({'class' : v}); + lo[v] = 1; + } + }); + } + break; + + // Import + case 3: + addClasses(r.styleSheet); + break; + } + }); + }; + + try { + each(t.doc.styleSheets, addClasses); + } catch (ex) { + // Ignore + } + + if (cl.length > 0) + t.classes = cl; + + return cl; + }, + + run : function(e, f, s) { + var t = this, o; + + if (t.doc && typeof(e) === 'string') + e = t.get(e); + + if (!e) + return false; + + s = s || this; + if (!e.nodeType && (e.length || e.length === 0)) { + o = []; + + each(e, function(e, i) { + if (e) { + if (typeof(e) == 'string') + e = t.doc.getElementById(e); + + o.push(f.call(s, e, i)); + } + }); + + return o; + } + + return f.call(s, e); + }, + + getAttribs : function(n) { + var o; + + n = this.get(n); + + if (!n) + return []; + + if (isIE) { + o = []; + + // Object will throw exception in IE + if (n.nodeName == 'OBJECT') + return n.attributes; + + // IE doesn't keep the selected attribute if you clone option elements + if (n.nodeName === 'OPTION' && this.getAttrib(n, 'selected')) + o.push({specified : 1, nodeName : 'selected'}); + + // It's crazy that this is faster in IE but it's because it returns all attributes all the time + n.cloneNode(false).outerHTML.replace(/<\/?[\w:\-]+ ?|=[\"][^\"]+\"|=\'[^\']+\'|=[\w\-]+|>/gi, '').replace(/[\w:\-]+/gi, function(a) { + o.push({specified : 1, nodeName : a}); + }); + + return o; + } + + return n.attributes; + }, + + isEmpty : function(node, elements) { + var self = this, i, attributes, type, walker, name, parentNode; + + node = node.firstChild; + if (node) { + walker = new tinymce.dom.TreeWalker(node); + elements = elements || self.schema ? self.schema.getNonEmptyElements() : null; + + do { + type = node.nodeType; + + if (type === 1) { + // Ignore bogus elements + if (node.getAttribute('data-mce-bogus')) + continue; + + // Keep empty elements like <img /> + name = node.nodeName.toLowerCase(); + if (elements && elements[name]) { + // Ignore single BR elements in blocks like <p><br /></p> + parentNode = node.parentNode; + if (name === 'br' && self.isBlock(parentNode) && parentNode.firstChild === node && parentNode.lastChild === node) { + continue; + } + + return false; + } + + // Keep elements with data-bookmark attributes or name attribute like <a name="1"></a> + attributes = self.getAttribs(node); + i = node.attributes.length; + while (i--) { + name = node.attributes[i].nodeName; + if (name === "name" || name === 'data-mce-bookmark') + return false; + } + } + + // Keep non whitespace text nodes + if ((type === 3 && !whiteSpaceRegExp.test(node.nodeValue))) + return false; + } while (node = walker.next()); + } + + return true; + }, + + destroy : function(s) { + var t = this; + + if (t.events) + t.events.destroy(); + + t.win = t.doc = t.root = t.events = null; + + // Manual destroy then remove unload handler + if (!s) + tinymce.removeUnload(t.destroy); + }, + + createRng : function() { + var d = this.doc; + + return d.createRange ? d.createRange() : new tinymce.dom.Range(this); + }, + + nodeIndex : function(node, normalized) { + var idx = 0, lastNodeType, lastNode, nodeType; + + if (node) { + for (lastNodeType = node.nodeType, node = node.previousSibling, lastNode = node; node; node = node.previousSibling) { + nodeType = node.nodeType; + + // Normalize text nodes + if (normalized && nodeType == 3) { + if (nodeType == lastNodeType || !node.nodeValue.length) + continue; + } + idx++; + lastNodeType = nodeType; + } + } + + return idx; + }, + + split : function(pe, e, re) { + var t = this, r = t.createRng(), bef, aft, pa; + + // W3C valid browsers tend to leave empty nodes to the left/right side of the contents, this makes sense + // but we don't want that in our code since it serves no purpose for the end user + // For example if this is chopped: + // <p>text 1<span><b>CHOP</b></span>text 2</p> + // would produce: + // <p>text 1<span></span></p><b>CHOP</b><p><span></span>text 2</p> + // this function will then trim of empty edges and produce: + // <p>text 1</p><b>CHOP</b><p>text 2</p> + function trim(node) { + var i, children = node.childNodes, type = node.nodeType; + + if (type == 1 && node.getAttribute('data-mce-type') == 'bookmark') + return; + + for (i = children.length - 1; i >= 0; i--) + trim(children[i]); + + if (type != 9) { + // Keep non whitespace text nodes + if (type == 3 && node.nodeValue.length > 0) { + // If parent element isn't a block or there isn't any useful contents for example "<p> </p>" + if (!t.isBlock(node.parentNode) || tinymce.trim(node.nodeValue).length > 0) + return; + } else if (type == 1) { + // If the only child is a bookmark then move it up + children = node.childNodes; + if (children.length == 1 && children[0] && children[0].nodeType == 1 && children[0].getAttribute('data-mce-type') == 'bookmark') + node.parentNode.insertBefore(children[0], node); + + // Keep non empty elements or img, hr etc + if (children.length || /^(br|hr|input|img)$/i.test(node.nodeName)) + return; + } + + t.remove(node); + } + + return node; + }; + + if (pe && e) { + // Get before chunk + r.setStart(pe.parentNode, t.nodeIndex(pe)); + r.setEnd(e.parentNode, t.nodeIndex(e)); + bef = r.extractContents(); + + // Get after chunk + r = t.createRng(); + r.setStart(e.parentNode, t.nodeIndex(e) + 1); + r.setEnd(pe.parentNode, t.nodeIndex(pe) + 1); + aft = r.extractContents(); + + // Insert before chunk + pa = pe.parentNode; + pa.insertBefore(trim(bef), pe); + + // Insert middle chunk + if (re) + pa.replaceChild(re, e); + else + pa.insertBefore(e, pe); + + // Insert after chunk + pa.insertBefore(trim(aft), pe); + t.remove(pe); + + return re || e; + } + }, + + bind : function(target, name, func, scope) { + var t = this; + + if (!t.events) + t.events = new tinymce.dom.EventUtils(); + + return t.events.add(target, name, func, scope || this); + }, + + unbind : function(target, name, func) { + var t = this; + + if (!t.events) + t.events = new tinymce.dom.EventUtils(); + + return t.events.remove(target, name, func); + }, + + + _findSib : function(node, selector, name) { + var t = this, f = selector; + + if (node) { + // If expression make a function of it using is + if (is(f, 'string')) { + f = function(node) { + return t.is(node, selector); + }; + } + + // Loop all siblings + for (node = node[name]; node; node = node[name]) { + if (f(node)) + return node; + } + } + + return null; + }, + + _isRes : function(c) { + // Is live resizble element + return /^(top|left|bottom|right|width|height)/i.test(c) || /;\s*(top|left|bottom|right|width|height)/i.test(c); + } + + /* + walk : function(n, f, s) { + var d = this.doc, w; + + if (d.createTreeWalker) { + w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false); + + while ((n = w.nextNode()) != null) + f.call(s || this, n); + } else + tinymce.walk(n, f, 'childNodes', s); + } + */ + + /* + toRGB : function(s) { + var c = /^\s*?#([0-9A-F]{2})([0-9A-F]{1,2})([0-9A-F]{2})?\s*?$/.exec(s); + + if (c) { + // #FFF -> #FFFFFF + if (!is(c[3])) + c[3] = c[2] = c[1]; + + return "rgb(" + parseInt(c[1], 16) + "," + parseInt(c[2], 16) + "," + parseInt(c[3], 16) + ")"; + } + + return s; + } + */ + }); + + tinymce.DOM = new tinymce.dom.DOMUtils(document, {process_html : 0}); +})(tinymce); + +(function(ns) { + // Range constructor + function Range(dom) { + var t = this, + doc = dom.doc, + EXTRACT = 0, + CLONE = 1, + DELETE = 2, + TRUE = true, + FALSE = false, + START_OFFSET = 'startOffset', + START_CONTAINER = 'startContainer', + END_CONTAINER = 'endContainer', + END_OFFSET = 'endOffset', + extend = tinymce.extend, + nodeIndex = dom.nodeIndex; + + extend(t, { + // Inital states + startContainer : doc, + startOffset : 0, + endContainer : doc, + endOffset : 0, + collapsed : TRUE, + commonAncestorContainer : doc, + + // Range constants + START_TO_START : 0, + START_TO_END : 1, + END_TO_END : 2, + END_TO_START : 3, + + // Public methods + setStart : setStart, + setEnd : setEnd, + setStartBefore : setStartBefore, + setStartAfter : setStartAfter, + setEndBefore : setEndBefore, + setEndAfter : setEndAfter, + collapse : collapse, + selectNode : selectNode, + selectNodeContents : selectNodeContents, + compareBoundaryPoints : compareBoundaryPoints, + deleteContents : deleteContents, + extractContents : extractContents, + cloneContents : cloneContents, + insertNode : insertNode, + surroundContents : surroundContents, + cloneRange : cloneRange + }); + + function setStart(n, o) { + _setEndPoint(TRUE, n, o); + }; + + function setEnd(n, o) { + _setEndPoint(FALSE, n, o); + }; + + function setStartBefore(n) { + setStart(n.parentNode, nodeIndex(n)); + }; + + function setStartAfter(n) { + setStart(n.parentNode, nodeIndex(n) + 1); + }; + + function setEndBefore(n) { + setEnd(n.parentNode, nodeIndex(n)); + }; + + function setEndAfter(n) { + setEnd(n.parentNode, nodeIndex(n) + 1); + }; + + function collapse(ts) { + if (ts) { + t[END_CONTAINER] = t[START_CONTAINER]; + t[END_OFFSET] = t[START_OFFSET]; + } else { + t[START_CONTAINER] = t[END_CONTAINER]; + t[START_OFFSET] = t[END_OFFSET]; + } + + t.collapsed = TRUE; + }; + + function selectNode(n) { + setStartBefore(n); + setEndAfter(n); + }; + + function selectNodeContents(n) { + setStart(n, 0); + setEnd(n, n.nodeType === 1 ? n.childNodes.length : n.nodeValue.length); + }; + + function compareBoundaryPoints(h, r) { + var sc = t[START_CONTAINER], so = t[START_OFFSET], ec = t[END_CONTAINER], eo = t[END_OFFSET], + rsc = r.startContainer, rso = r.startOffset, rec = r.endContainer, reo = r.endOffset; + + // Check START_TO_START + if (h === 0) + return _compareBoundaryPoints(sc, so, rsc, rso); + + // Check START_TO_END + if (h === 1) + return _compareBoundaryPoints(ec, eo, rsc, rso); + + // Check END_TO_END + if (h === 2) + return _compareBoundaryPoints(ec, eo, rec, reo); + + // Check END_TO_START + if (h === 3) + return _compareBoundaryPoints(sc, so, rec, reo); + }; + + function deleteContents() { + _traverse(DELETE); + }; + + function extractContents() { + return _traverse(EXTRACT); + }; + + function cloneContents() { + return _traverse(CLONE); + }; + + function insertNode(n) { + var startContainer = this[START_CONTAINER], + startOffset = this[START_OFFSET], nn, o; + + // Node is TEXT_NODE or CDATA + if ((startContainer.nodeType === 3 || startContainer.nodeType === 4) && startContainer.nodeValue) { + if (!startOffset) { + // At the start of text + startContainer.parentNode.insertBefore(n, startContainer); + } else if (startOffset >= startContainer.nodeValue.length) { + // At the end of text + dom.insertAfter(n, startContainer); + } else { + // Middle, need to split + nn = startContainer.splitText(startOffset); + startContainer.parentNode.insertBefore(n, nn); + } + } else { + // Insert element node + if (startContainer.childNodes.length > 0) + o = startContainer.childNodes[startOffset]; + + if (o) + startContainer.insertBefore(n, o); + else + startContainer.appendChild(n); + } + }; + + function surroundContents(n) { + var f = t.extractContents(); + + t.insertNode(n); + n.appendChild(f); + t.selectNode(n); + }; + + function cloneRange() { + return extend(new Range(dom), { + startContainer : t[START_CONTAINER], + startOffset : t[START_OFFSET], + endContainer : t[END_CONTAINER], + endOffset : t[END_OFFSET], + collapsed : t.collapsed, + commonAncestorContainer : t.commonAncestorContainer + }); + }; + + // Private methods + + function _getSelectedNode(container, offset) { + var child; + + if (container.nodeType == 3 /* TEXT_NODE */) + return container; + + if (offset < 0) + return container; + + child = container.firstChild; + while (child && offset > 0) { + --offset; + child = child.nextSibling; + } + + if (child) + return child; + + return container; + }; + + function _isCollapsed() { + return (t[START_CONTAINER] == t[END_CONTAINER] && t[START_OFFSET] == t[END_OFFSET]); + }; + + function _compareBoundaryPoints(containerA, offsetA, containerB, offsetB) { + var c, offsetC, n, cmnRoot, childA, childB; + + // In the first case the boundary-points have the same container. A is before B + // if its offset is less than the offset of B, A is equal to B if its offset is + // equal to the offset of B, and A is after B if its offset is greater than the + // offset of B. + if (containerA == containerB) { + if (offsetA == offsetB) + return 0; // equal + + if (offsetA < offsetB) + return -1; // before + + return 1; // after + } + + // In the second case a child node C of the container of A is an ancestor + // container of B. In this case, A is before B if the offset of A is less than or + // equal to the index of the child node C and A is after B otherwise. + c = containerB; + while (c && c.parentNode != containerA) + c = c.parentNode; + + if (c) { + offsetC = 0; + n = containerA.firstChild; + + while (n != c && offsetC < offsetA) { + offsetC++; + n = n.nextSibling; + } + + if (offsetA <= offsetC) + return -1; // before + + return 1; // after + } + + // In the third case a child node C of the container of B is an ancestor container + // of A. In this case, A is before B if the index of the child node C is less than + // the offset of B and A is after B otherwise. + c = containerA; + while (c && c.parentNode != containerB) { + c = c.parentNode; + } + + if (c) { + offsetC = 0; + n = containerB.firstChild; + + while (n != c && offsetC < offsetB) { + offsetC++; + n = n.nextSibling; + } + + if (offsetC < offsetB) + return -1; // before + + return 1; // after + } + + // In the fourth case, none of three other cases hold: the containers of A and B + // are siblings or descendants of sibling nodes. In this case, A is before B if + // the container of A is before the container of B in a pre-order traversal of the + // Ranges' context tree and A is after B otherwise. + cmnRoot = dom.findCommonAncestor(containerA, containerB); + childA = containerA; + + while (childA && childA.parentNode != cmnRoot) + childA = childA.parentNode; + + if (!childA) + childA = cmnRoot; + + childB = containerB; + while (childB && childB.parentNode != cmnRoot) + childB = childB.parentNode; + + if (!childB) + childB = cmnRoot; + + if (childA == childB) + return 0; // equal + + n = cmnRoot.firstChild; + while (n) { + if (n == childA) + return -1; // before + + if (n == childB) + return 1; // after + + n = n.nextSibling; + } + }; + + function _setEndPoint(st, n, o) { + var ec, sc; + + if (st) { + t[START_CONTAINER] = n; + t[START_OFFSET] = o; + } else { + t[END_CONTAINER] = n; + t[END_OFFSET] = o; + } + + // If one boundary-point of a Range is set to have a root container + // other than the current one for the Range, the Range is collapsed to + // the new position. This enforces the restriction that both boundary- + // points of a Range must have the same root container. + ec = t[END_CONTAINER]; + while (ec.parentNode) + ec = ec.parentNode; + + sc = t[START_CONTAINER]; + while (sc.parentNode) + sc = sc.parentNode; + + if (sc == ec) { + // The start position of a Range is guaranteed to never be after the + // end position. To enforce this restriction, if the start is set to + // be at a position after the end, the Range is collapsed to that + // position. + if (_compareBoundaryPoints(t[START_CONTAINER], t[START_OFFSET], t[END_CONTAINER], t[END_OFFSET]) > 0) + t.collapse(st); + } else + t.collapse(st); + + t.collapsed = _isCollapsed(); + t.commonAncestorContainer = dom.findCommonAncestor(t[START_CONTAINER], t[END_CONTAINER]); + }; + + function _traverse(how) { + var c, endContainerDepth = 0, startContainerDepth = 0, p, depthDiff, startNode, endNode, sp, ep; + + if (t[START_CONTAINER] == t[END_CONTAINER]) + return _traverseSameContainer(how); + + for (c = t[END_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) { + if (p == t[START_CONTAINER]) + return _traverseCommonStartContainer(c, how); + + ++endContainerDepth; + } + + for (c = t[START_CONTAINER], p = c.parentNode; p; c = p, p = p.parentNode) { + if (p == t[END_CONTAINER]) + return _traverseCommonEndContainer(c, how); + + ++startContainerDepth; + } + + depthDiff = startContainerDepth - endContainerDepth; + + startNode = t[START_CONTAINER]; + while (depthDiff > 0) { + startNode = startNode.parentNode; + depthDiff--; + } + + endNode = t[END_CONTAINER]; + while (depthDiff < 0) { + endNode = endNode.parentNode; + depthDiff++; + } + + // ascend the ancestor hierarchy until we have a common parent. + for (sp = startNode.parentNode, ep = endNode.parentNode; sp != ep; sp = sp.parentNode, ep = ep.parentNode) { + startNode = sp; + endNode = ep; + } + + return _traverseCommonAncestors(startNode, endNode, how); + }; + + function _traverseSameContainer(how) { + var frag, s, sub, n, cnt, sibling, xferNode; + + if (how != DELETE) + frag = doc.createDocumentFragment(); + + // If selection is empty, just return the fragment + if (t[START_OFFSET] == t[END_OFFSET]) + return frag; + + // Text node needs special case handling + if (t[START_CONTAINER].nodeType == 3 /* TEXT_NODE */) { + // get the substring + s = t[START_CONTAINER].nodeValue; + sub = s.substring(t[START_OFFSET], t[END_OFFSET]); + + // set the original text node to its new value + if (how != CLONE) { + t[START_CONTAINER].deleteData(t[START_OFFSET], t[END_OFFSET] - t[START_OFFSET]); + + // Nothing is partially selected, so collapse to start point + t.collapse(TRUE); + } + + if (how == DELETE) + return; + + frag.appendChild(doc.createTextNode(sub)); + return frag; + } + + // Copy nodes between the start/end offsets. + n = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]); + cnt = t[END_OFFSET] - t[START_OFFSET]; + + while (cnt > 0) { + sibling = n.nextSibling; + xferNode = _traverseFullySelected(n, how); + + if (frag) + frag.appendChild( xferNode ); + + --cnt; + n = sibling; + } + + // Nothing is partially selected, so collapse to start point + if (how != CLONE) + t.collapse(TRUE); + + return frag; + }; + + function _traverseCommonStartContainer(endAncestor, how) { + var frag, n, endIdx, cnt, sibling, xferNode; + + if (how != DELETE) + frag = doc.createDocumentFragment(); + + n = _traverseRightBoundary(endAncestor, how); + + if (frag) + frag.appendChild(n); + + endIdx = nodeIndex(endAncestor); + cnt = endIdx - t[START_OFFSET]; + + if (cnt <= 0) { + // Collapse to just before the endAncestor, which + // is partially selected. + if (how != CLONE) { + t.setEndBefore(endAncestor); + t.collapse(FALSE); + } + + return frag; + } + + n = endAncestor.previousSibling; + while (cnt > 0) { + sibling = n.previousSibling; + xferNode = _traverseFullySelected(n, how); + + if (frag) + frag.insertBefore(xferNode, frag.firstChild); + + --cnt; + n = sibling; + } + + // Collapse to just before the endAncestor, which + // is partially selected. + if (how != CLONE) { + t.setEndBefore(endAncestor); + t.collapse(FALSE); + } + + return frag; + }; + + function _traverseCommonEndContainer(startAncestor, how) { + var frag, startIdx, n, cnt, sibling, xferNode; + + if (how != DELETE) + frag = doc.createDocumentFragment(); + + n = _traverseLeftBoundary(startAncestor, how); + if (frag) + frag.appendChild(n); + + startIdx = nodeIndex(startAncestor); + ++startIdx; // Because we already traversed it + + cnt = t[END_OFFSET] - startIdx; + n = startAncestor.nextSibling; + while (cnt > 0) { + sibling = n.nextSibling; + xferNode = _traverseFullySelected(n, how); + + if (frag) + frag.appendChild(xferNode); + + --cnt; + n = sibling; + } + + if (how != CLONE) { + t.setStartAfter(startAncestor); + t.collapse(TRUE); + } + + return frag; + }; + + function _traverseCommonAncestors(startAncestor, endAncestor, how) { + var n, frag, commonParent, startOffset, endOffset, cnt, sibling, nextSibling; + + if (how != DELETE) + frag = doc.createDocumentFragment(); + + n = _traverseLeftBoundary(startAncestor, how); + if (frag) + frag.appendChild(n); + + commonParent = startAncestor.parentNode; + startOffset = nodeIndex(startAncestor); + endOffset = nodeIndex(endAncestor); + ++startOffset; + + cnt = endOffset - startOffset; + sibling = startAncestor.nextSibling; + + while (cnt > 0) { + nextSibling = sibling.nextSibling; + n = _traverseFullySelected(sibling, how); + + if (frag) + frag.appendChild(n); + + sibling = nextSibling; + --cnt; + } + + n = _traverseRightBoundary(endAncestor, how); + + if (frag) + frag.appendChild(n); + + if (how != CLONE) { + t.setStartAfter(startAncestor); + t.collapse(TRUE); + } + + return frag; + }; + + function _traverseRightBoundary(root, how) { + var next = _getSelectedNode(t[END_CONTAINER], t[END_OFFSET] - 1), parent, clonedParent, prevSibling, clonedChild, clonedGrandParent, isFullySelected = next != t[END_CONTAINER]; + + if (next == root) + return _traverseNode(next, isFullySelected, FALSE, how); + + parent = next.parentNode; + clonedParent = _traverseNode(parent, FALSE, FALSE, how); + + while (parent) { + while (next) { + prevSibling = next.previousSibling; + clonedChild = _traverseNode(next, isFullySelected, FALSE, how); + + if (how != DELETE) + clonedParent.insertBefore(clonedChild, clonedParent.firstChild); + + isFullySelected = TRUE; + next = prevSibling; + } + + if (parent == root) + return clonedParent; + + next = parent.previousSibling; + parent = parent.parentNode; + + clonedGrandParent = _traverseNode(parent, FALSE, FALSE, how); + + if (how != DELETE) + clonedGrandParent.appendChild(clonedParent); + + clonedParent = clonedGrandParent; + } + }; + + function _traverseLeftBoundary(root, how) { + var next = _getSelectedNode(t[START_CONTAINER], t[START_OFFSET]), isFullySelected = next != t[START_CONTAINER], parent, clonedParent, nextSibling, clonedChild, clonedGrandParent; + + if (next == root) + return _traverseNode(next, isFullySelected, TRUE, how); + + parent = next.parentNode; + clonedParent = _traverseNode(parent, FALSE, TRUE, how); + + while (parent) { + while (next) { + nextSibling = next.nextSibling; + clonedChild = _traverseNode(next, isFullySelected, TRUE, how); + + if (how != DELETE) + clonedParent.appendChild(clonedChild); + + isFullySelected = TRUE; + next = nextSibling; + } + + if (parent == root) + return clonedParent; + + next = parent.nextSibling; + parent = parent.parentNode; + + clonedGrandParent = _traverseNode(parent, FALSE, TRUE, how); + + if (how != DELETE) + clonedGrandParent.appendChild(clonedParent); + + clonedParent = clonedGrandParent; + } + }; + + function _traverseNode(n, isFullySelected, isLeft, how) { + var txtValue, newNodeValue, oldNodeValue, offset, newNode; + + if (isFullySelected) + return _traverseFullySelected(n, how); + + if (n.nodeType == 3 /* TEXT_NODE */) { + txtValue = n.nodeValue; + + if (isLeft) { + offset = t[START_OFFSET]; + newNodeValue = txtValue.substring(offset); + oldNodeValue = txtValue.substring(0, offset); + } else { + offset = t[END_OFFSET]; + newNodeValue = txtValue.substring(0, offset); + oldNodeValue = txtValue.substring(offset); + } + + if (how != CLONE) + n.nodeValue = oldNodeValue; + + if (how == DELETE) + return; + + newNode = n.cloneNode(FALSE); + newNode.nodeValue = newNodeValue; + + return newNode; + } + + if (how == DELETE) + return; + + return n.cloneNode(FALSE); + }; + + function _traverseFullySelected(n, how) { + if (how != DELETE) + return how == CLONE ? n.cloneNode(TRUE) : n; + + n.parentNode.removeChild(n); + }; + }; + + ns.Range = Range; +})(tinymce.dom); + +(function() { + function Selection(selection) { + var self = this, dom = selection.dom, TRUE = true, FALSE = false; + + function getPosition(rng, start) { + var checkRng, startIndex = 0, endIndex, inside, + children, child, offset, index, position = -1, parent; + + // Setup test range, collapse it and get the parent + checkRng = rng.duplicate(); + checkRng.collapse(start); + parent = checkRng.parentElement(); + + // Check if the selection is within the right document + if (parent.ownerDocument !== selection.dom.doc) + return; + + // IE will report non editable elements as it's parent so look for an editable one + while (parent.contentEditable === "false") { + parent = parent.parentNode; + } + + // If parent doesn't have any children then return that we are inside the element + if (!parent.hasChildNodes()) { + return {node : parent, inside : 1}; + } + + // Setup node list and endIndex + children = parent.children; + endIndex = children.length - 1; + + // Perform a binary search for the position + while (startIndex <= endIndex) { + index = Math.floor((startIndex + endIndex) / 2); + + // Move selection to node and compare the ranges + child = children[index]; + checkRng.moveToElementText(child); + position = checkRng.compareEndPoints(start ? 'StartToStart' : 'EndToEnd', rng); + + // Before/after or an exact match + if (position > 0) { + endIndex = index - 1; + } else if (position < 0) { + startIndex = index + 1; + } else { + return {node : child}; + } + } + + // Check if child position is before or we didn't find a position + if (position < 0) { + // No element child was found use the parent element and the offset inside that + if (!child) { + checkRng.moveToElementText(parent); + checkRng.collapse(true); + child = parent; + inside = true; + } else + checkRng.collapse(false); + + checkRng.setEndPoint(start ? 'EndToStart' : 'EndToEnd', rng); + + // Fix for edge case: <div style="width: 100px; height:100px;"><table>..</table>ab|c</div> + if (checkRng.compareEndPoints(start ? 'StartToStart' : 'StartToEnd', rng) > 0) { + checkRng = rng.duplicate(); + checkRng.collapse(start); + + offset = -1; + while (parent == checkRng.parentElement()) { + if (checkRng.move('character', -1) == 0) + break; + + offset++; + } + } + + offset = offset || checkRng.text.replace('\r\n', ' ').length; + } else { + // Child position is after the selection endpoint + checkRng.collapse(true); + checkRng.setEndPoint(start ? 'StartToStart' : 'StartToEnd', rng); + + // Get the length of the text to find where the endpoint is relative to it's container + offset = checkRng.text.replace('\r\n', ' ').length; + } + + return {node : child, position : position, offset : offset, inside : inside}; + }; + + // Returns a W3C DOM compatible range object by using the IE Range API + function getRange() { + var ieRange = selection.getRng(), domRange = dom.createRng(), element, collapsed, tmpRange, element2, bookmark, fail; + + // If selection is outside the current document just return an empty range + element = ieRange.item ? ieRange.item(0) : ieRange.parentElement(); + if (element.ownerDocument != dom.doc) + return domRange; + + collapsed = selection.isCollapsed(); + + // Handle control selection + if (ieRange.item) { + domRange.setStart(element.parentNode, dom.nodeIndex(element)); + domRange.setEnd(domRange.startContainer, domRange.startOffset + 1); + + return domRange; + } + + function findEndPoint(start) { + var endPoint = getPosition(ieRange, start), container, offset, textNodeOffset = 0, sibling, undef, nodeValue; + + container = endPoint.node; + offset = endPoint.offset; + + if (endPoint.inside && !container.hasChildNodes()) { + domRange[start ? 'setStart' : 'setEnd'](container, 0); + return; + } + + if (offset === undef) { + domRange[start ? 'setStartBefore' : 'setEndAfter'](container); + return; + } + + if (endPoint.position < 0) { + sibling = endPoint.inside ? container.firstChild : container.nextSibling; + + if (!sibling) { + domRange[start ? 'setStartAfter' : 'setEndAfter'](container); + return; + } + + if (!offset) { + if (sibling.nodeType == 3) + domRange[start ? 'setStart' : 'setEnd'](sibling, 0); + else + domRange[start ? 'setStartBefore' : 'setEndBefore'](sibling); + + return; + } + + // Find the text node and offset + while (sibling) { + nodeValue = sibling.nodeValue; + textNodeOffset += nodeValue.length; + + // We are at or passed the position we where looking for + if (textNodeOffset >= offset) { + container = sibling; + textNodeOffset -= offset; + textNodeOffset = nodeValue.length - textNodeOffset; + break; + } + + sibling = sibling.nextSibling; + } + } else { + // Find the text node and offset + sibling = container.previousSibling; + + if (!sibling) + return domRange[start ? 'setStartBefore' : 'setEndBefore'](container); + + // If there isn't any text to loop then use the first position + if (!offset) { + if (container.nodeType == 3) + domRange[start ? 'setStart' : 'setEnd'](sibling, container.nodeValue.length); + else + domRange[start ? 'setStartAfter' : 'setEndAfter'](sibling); + + return; + } + + while (sibling) { + textNodeOffset += sibling.nodeValue.length; + + // We are at or passed the position we where looking for + if (textNodeOffset >= offset) { + container = sibling; + textNodeOffset -= offset; + break; + } + + sibling = sibling.previousSibling; + } + } + + domRange[start ? 'setStart' : 'setEnd'](container, textNodeOffset); + }; + + try { + // Find start point + findEndPoint(true); + + // Find end point if needed + if (!collapsed) + findEndPoint(); + } catch (ex) { + // IE has a nasty bug where text nodes might throw "invalid argument" when you + // access the nodeValue or other properties of text nodes. This seems to happend when + // text nodes are split into two nodes by a delete/backspace call. So lets detect it and try to fix it. + if (ex.number == -2147024809) { + // Get the current selection + bookmark = self.getBookmark(2); + + // Get start element + tmpRange = ieRange.duplicate(); + tmpRange.collapse(true); + element = tmpRange.parentElement(); + + // Get end element + if (!collapsed) { + tmpRange = ieRange.duplicate(); + tmpRange.collapse(false); + element2 = tmpRange.parentElement(); + element2.innerHTML = element2.innerHTML; + } + + // Remove the broken elements + element.innerHTML = element.innerHTML; + + // Restore the selection + self.moveToBookmark(bookmark); + + // Since the range has moved we need to re-get it + ieRange = selection.getRng(); + + // Find start point + findEndPoint(true); + + // Find end point if needed + if (!collapsed) + findEndPoint(); + } else + throw ex; // Throw other errors + } + + return domRange; + }; + + this.getBookmark = function(type) { + var rng = selection.getRng(), start, end, bookmark = {}; + + function getIndexes(node) { + var node, parent, root, children, i, indexes = []; + + parent = node.parentNode; + root = dom.getRoot().parentNode; + + while (parent != root) { + children = parent.children; + + i = children.length; + while (i--) { + if (node === children[i]) { + indexes.push(i); + break; + } + } + + node = parent; + parent = parent.parentNode; + } + + return indexes; + }; + + function getBookmarkEndPoint(start) { + var position; + + position = getPosition(rng, start); + if (position) { + return { + position : position.position, + offset : position.offset, + indexes : getIndexes(position.node), + inside : position.inside + }; + } + }; + + // Non ubstructive bookmark + if (type === 2) { + // Handle text selection + if (!rng.item) { + bookmark.start = getBookmarkEndPoint(true); + + if (!selection.isCollapsed()) + bookmark.end = getBookmarkEndPoint(); + } else + bookmark.start = {ctrl : true, indexes : getIndexes(rng.item(0))}; + } + + return bookmark; + }; + + this.moveToBookmark = function(bookmark) { + var rng, body = dom.doc.body; + + function resolveIndexes(indexes) { + var node, i, idx, children; + + node = dom.getRoot(); + for (i = indexes.length - 1; i >= 0; i--) { + children = node.children; + idx = indexes[i]; + + if (idx <= children.length - 1) { + node = children[idx]; + } + } + + return node; + }; + + function setBookmarkEndPoint(start) { + var endPoint = bookmark[start ? 'start' : 'end'], moveLeft, moveRng, undef; + + if (endPoint) { + moveLeft = endPoint.position > 0; + + moveRng = body.createTextRange(); + moveRng.moveToElementText(resolveIndexes(endPoint.indexes)); + + offset = endPoint.offset; + if (offset !== undef) { + moveRng.collapse(endPoint.inside || moveLeft); + moveRng.moveStart('character', moveLeft ? -offset : offset); + } else + moveRng.collapse(start); + + rng.setEndPoint(start ? 'StartToStart' : 'EndToStart', moveRng); + + if (start) + rng.collapse(true); + } + }; + + if (bookmark.start) { + if (bookmark.start.ctrl) { + rng = body.createControlRange(); + rng.addElement(resolveIndexes(bookmark.start.indexes)); + rng.select(); + } else { + rng = body.createTextRange(); + setBookmarkEndPoint(true); + setBookmarkEndPoint(); + rng.select(); + } + } + }; + + this.addRange = function(rng) { + var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, doc = selection.dom.doc, body = doc.body; + + function setEndPoint(start) { + var container, offset, marker, tmpRng, nodes; + + marker = dom.create('a'); + container = start ? startContainer : endContainer; + offset = start ? startOffset : endOffset; + tmpRng = ieRng.duplicate(); + + if (container == doc || container == doc.documentElement) { + container = body; + offset = 0; + } + + if (container.nodeType == 3) { + container.parentNode.insertBefore(marker, container); + tmpRng.moveToElementText(marker); + tmpRng.moveStart('character', offset); + dom.remove(marker); + ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng); + } else { + nodes = container.childNodes; + + if (nodes.length) { + if (offset >= nodes.length) { + dom.insertAfter(marker, nodes[nodes.length - 1]); + } else { + container.insertBefore(marker, nodes[offset]); + } + + tmpRng.moveToElementText(marker); + } else { + // Empty node selection for example <div>|</div> + marker = doc.createTextNode('\uFEFF'); + container.appendChild(marker); + tmpRng.moveToElementText(marker.parentNode); + tmpRng.collapse(TRUE); + } + + ieRng.setEndPoint(start ? 'StartToStart' : 'EndToEnd', tmpRng); + dom.remove(marker); + } + } + + // Setup some shorter versions + startContainer = rng.startContainer; + startOffset = rng.startOffset; + endContainer = rng.endContainer; + endOffset = rng.endOffset; + ieRng = body.createTextRange(); + + // If single element selection then try making a control selection out of it + if (startContainer == endContainer && startContainer.nodeType == 1 && startOffset == endOffset - 1) { + if (startOffset == endOffset - 1) { + try { + ctrlRng = body.createControlRange(); + ctrlRng.addElement(startContainer.childNodes[startOffset]); + ctrlRng.select(); + return; + } catch (ex) { + // Ignore + } + } + } + + // Set start/end point of selection + setEndPoint(true); + setEndPoint(); + + // Select the new range and scroll it into view + ieRng.select(); + }; + + // Expose range method + this.getRangeAt = getRange; + }; + + // Expose the selection object + tinymce.dom.TridentSelection = Selection; +})(); + + +/* + * Sizzle CSS Selector Engine - v1.0 + * Copyright 2009, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function(){ + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function(selector, context, results, seed) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var parts = [], m, set, checkSet, extra, prune = true, contextXML = Sizzle.isXML(context), + soFar = selector, ret, cur, pop, i; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec(""); + m = chunker.exec(soFar); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray(set); + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function(results){ + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort(sortOrder); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[i-1] ) { + results.splice(i--, 1); + } + } + } + } + + return results; +}; + +Sizzle.matches = function(expr, set){ + return Sizzle(expr, null, null, set); +}; + +Sizzle.find = function(expr, context, isXML){ + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var type = Expr.order[i], match; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice(1,1); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace(/\\/g, ""); + set = Expr.find[ type ]( match, context, isXML ); + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = context.getElementsByTagName("*"); + } + + return {set: set, expr: expr}; +}; + +Sizzle.filter = function(expr, set, inplace, not){ + var old = expr, result = [], curLoop = set, match, anyFound, + isXMLFilter = set && set[0] && Sizzle.isXML(set[0]); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var filter = Expr.filter[ type ], found, item, left = match[1]; + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + } else { + curLoop[i] = false; + } + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+\-]*)\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + leftMatch: {}, + attrMap: { + "class": "className", + "for": "htmlFor" + }, + attrHandle: { + href: function(elem){ + return elem.getAttribute("href"); + } + }, + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !/\W/.test(part), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + ">": function(checkSet, part){ + var isPartStr = typeof part === "string", + elem, i = 0, l = checkSet.length; + + if ( isPartStr && !/\W/.test(part) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + "": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck, nodeCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML); + }, + "~": function(checkSet, part, isXML){ + var doneName = done++, checkFn = dirCheck, nodeCheck; + + if ( typeof part === "string" && !/\W/.test(part) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML); + } + }, + find: { + ID: function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? [m] : []; + } + }, + NAME: function(match, context){ + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], results = context.getElementsByName(match[1]); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + TAG: function(match, context){ + return context.getElementsByTagName(match[1]); + } + }, + preFilter: { + CLASS: function(match, curLoop, inplace, result, not, isXML){ + match = " " + match[1].replace(/\\/g, "") + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + ID: function(match){ + return match[1].replace(/\\/g, ""); + }, + TAG: function(match, curLoop){ + return match[1].toLowerCase(); + }, + CHILD: function(match){ + if ( match[1] === "nth" ) { + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + ATTR: function(match, curLoop, inplace, result, not, isXML){ + var name = match[1].replace(/\\/g, ""); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + PSEUDO: function(match, curLoop, inplace, result, not){ + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + if ( !inplace ) { + result.push.apply( result, ret ); + } + return false; + } + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + POS: function(match){ + match.unshift( true ); + return match; + } + }, + filters: { + enabled: function(elem){ + return elem.disabled === false && elem.type !== "hidden"; + }, + disabled: function(elem){ + return elem.disabled === true; + }, + checked: function(elem){ + return elem.checked === true; + }, + selected: function(elem){ + // Accessing this property makes selected-by-default + // options in Safari work properly + elem.parentNode.selectedIndex; + return elem.selected === true; + }, + parent: function(elem){ + return !!elem.firstChild; + }, + empty: function(elem){ + return !elem.firstChild; + }, + has: function(elem, i, match){ + return !!Sizzle( match[3], elem ).length; + }, + header: function(elem){ + return (/h\d/i).test( elem.nodeName ); + }, + text: function(elem){ + return "text" === elem.type; + }, + radio: function(elem){ + return "radio" === elem.type; + }, + checkbox: function(elem){ + return "checkbox" === elem.type; + }, + file: function(elem){ + return "file" === elem.type; + }, + password: function(elem){ + return "password" === elem.type; + }, + submit: function(elem){ + return "submit" === elem.type; + }, + image: function(elem){ + return "image" === elem.type; + }, + reset: function(elem){ + return "reset" === elem.type; + }, + button: function(elem){ + return "button" === elem.type || elem.nodeName.toLowerCase() === "button"; + }, + input: function(elem){ + return (/input|select|textarea|button/i).test(elem.nodeName); + } + }, + setFilters: { + first: function(elem, i){ + return i === 0; + }, + last: function(elem, i, match, array){ + return i === array.length - 1; + }, + even: function(elem, i){ + return i % 2 === 0; + }, + odd: function(elem, i){ + return i % 2 === 1; + }, + lt: function(elem, i, match){ + return i < match[3] - 0; + }, + gt: function(elem, i, match){ + return i > match[3] - 0; + }, + nth: function(elem, i, match){ + return match[3] - 0 === i; + }, + eq: function(elem, i, match){ + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function(elem, match, i, array){ + var name = match[1], filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + } else { + Sizzle.error( "Syntax error, unrecognized expression: " + name ); + } + }, + CHILD: function(elem, match){ + var type = match[1], node = elem; + switch (type) { + case 'only': + case 'first': + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + if ( type === "first" ) { + return true; + } + node = elem; + case 'last': + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + return true; + case 'nth': + var first = match[2], last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + if ( first === 0 ) { + return diff === 0; + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + ID: function(elem, match){ + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + TAG: function(elem, match){ + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + CLASS: function(elem, match){ + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + ATTR: function(elem, match){ + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + POS: function(elem, match, i, array){ + var name = match[2], filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function(array, results) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch(e){ + makeArray = function(array, results) { + var ret = results || [], i = 0; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.compareDocumentPosition ? -1 : 1; + } + + var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( "sourceIndex" in document.documentElement ) { + sortOrder = function( a, b ) { + if ( !a.sourceIndex || !b.sourceIndex ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.sourceIndex ? -1 : 1; + } + + var ret = a.sourceIndex - b.sourceIndex; + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} else if ( document.createRange ) { + sortOrder = function( a, b ) { + if ( !a.ownerDocument || !b.ownerDocument ) { + if ( a == b ) { + hasDuplicate = true; + } + return a.ownerDocument ? -1 : 1; + } + + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + if ( ret === 0 ) { + hasDuplicate = true; + } + return ret; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(); + form.innerHTML = "<a name='" + id + "'/>"; + + // Inject it into the root element, check its status, and remove it quickly + var root = document.documentElement; + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function(match, context, isXML){ + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; + } + }; + + Expr.filter.ID = function(elem, match){ + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + root = form = null; // release memory in IE +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function(match, context){ + var results = context.getElementsByTagName(match[1]); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = "<a href='#'></a>"; + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + Expr.attrHandle.href = function(elem){ + return elem.getAttribute("href", 2); + }; + } + + div = null; // release memory in IE +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, div = document.createElement("div"); + div.innerHTML = "<p class='TEST'></p>"; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function(query, context, extra, seed){ + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && context.nodeType === 9 && !Sizzle.isXML(context) ) { + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(e){} + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + div = null; // release memory in IE + })(); +} + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "<div class='test e'></div><div class='test'></div>"; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function(match, context, isXML) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + div = null; // release memory in IE +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + if ( elem ) { + elem = elem[dir]; + var match = false; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +Sizzle.contains = document.compareDocumentPosition ? function(a, b){ + return !!(a.compareDocumentPosition(b) & 16); +} : function(a, b){ + return a !== b && (a.contains ? a.contains(b) : true); +}; + +Sizzle.isXML = function(elem){ + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function(selector, context){ + var tmpSet = [], later = "", match, + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE + +window.tinymce.dom.Sizzle = Sizzle; + +})(); + + +(function(tinymce) { + // Shorten names + var each = tinymce.each, DOM = tinymce.DOM, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, Event; + + tinymce.create('tinymce.dom.EventUtils', { + EventUtils : function() { + this.inits = []; + this.events = []; + }, + + add : function(o, n, f, s) { + var cb, t = this, el = t.events, r; + + if (n instanceof Array) { + r = []; + + each(n, function(n) { + r.push(t.add(o, n, f, s)); + }); + + return r; + } + + // Handle array + if (o && o.hasOwnProperty && o instanceof Array) { + r = []; + + each(o, function(o) { + o = DOM.get(o); + r.push(t.add(o, n, f, s)); + }); + + return r; + } + + o = DOM.get(o); + + if (!o) + return; + + // Setup event callback + cb = function(e) { + // Is all events disabled + if (t.disabled) + return; + + e = e || window.event; + + // Patch in target, preventDefault and stopPropagation in IE it's W3C valid + if (e && isIE) { + if (!e.target) + e.target = e.srcElement; + + // Patch in preventDefault, stopPropagation methods for W3C compatibility + tinymce.extend(e, t._stoppers); + } + + if (!s) + return f(e); + + return f.call(s, e); + }; + + if (n == 'unload') { + tinymce.unloads.unshift({func : cb}); + return cb; + } + + if (n == 'init') { + if (t.domLoaded) + cb(); + else + t.inits.push(cb); + + return cb; + } + + // Store away listener reference + el.push({ + obj : o, + name : n, + func : f, + cfunc : cb, + scope : s + }); + + t._add(o, n, cb); + + return f; + }, + + remove : function(o, n, f) { + var t = this, a = t.events, s = false, r; + + // Handle array + if (o && o.hasOwnProperty && o instanceof Array) { + r = []; + + each(o, function(o) { + o = DOM.get(o); + r.push(t.remove(o, n, f)); + }); + + return r; + } + + o = DOM.get(o); + + each(a, function(e, i) { + if (e.obj == o && e.name == n && (!f || (e.func == f || e.cfunc == f))) { + a.splice(i, 1); + t._remove(o, n, e.cfunc); + s = true; + return false; + } + }); + + return s; + }, + + clear : function(o) { + var t = this, a = t.events, i, e; + + if (o) { + o = DOM.get(o); + + for (i = a.length - 1; i >= 0; i--) { + e = a[i]; + + if (e.obj === o) { + t._remove(e.obj, e.name, e.cfunc); + e.obj = e.cfunc = null; + a.splice(i, 1); + } + } + } + }, + + cancel : function(e) { + if (!e) + return false; + + this.stop(e); + + return this.prevent(e); + }, + + stop : function(e) { + if (e.stopPropagation) + e.stopPropagation(); + else + e.cancelBubble = true; + + return false; + }, + + prevent : function(e) { + if (e.preventDefault) + e.preventDefault(); + else + e.returnValue = false; + + return false; + }, + + destroy : function() { + var t = this; + + each(t.events, function(e, i) { + t._remove(e.obj, e.name, e.cfunc); + e.obj = e.cfunc = null; + }); + + t.events = []; + t = null; + }, + + _add : function(o, n, f) { + if (o.attachEvent) + o.attachEvent('on' + n, f); + else if (o.addEventListener) + o.addEventListener(n, f, false); + else + o['on' + n] = f; + }, + + _remove : function(o, n, f) { + if (o) { + try { + if (o.detachEvent) + o.detachEvent('on' + n, f); + else if (o.removeEventListener) + o.removeEventListener(n, f, false); + else + o['on' + n] = null; + } catch (ex) { + // Might fail with permission denined on IE so we just ignore that + } + } + }, + + _pageInit : function(win) { + var t = this; + + // Keep it from running more than once + if (t.domLoaded) + return; + + t.domLoaded = true; + + each(t.inits, function(c) { + c(); + }); + + t.inits = []; + }, + + _wait : function(win) { + var t = this, doc = win.document; + + // No need since the document is already loaded + if (win.tinyMCE_GZ && tinyMCE_GZ.loaded) { + t.domLoaded = 1; + return; + } + + // Use IE method + if (doc.attachEvent) { + doc.attachEvent("onreadystatechange", function() { + if (doc.readyState === "complete") { + doc.detachEvent("onreadystatechange", arguments.callee); + t._pageInit(win); + } + }); + + if (doc.documentElement.doScroll && win == win.top) { + (function() { + if (t.domLoaded) + return; + + try { + // If IE is used, use the trick by Diego Perini licensed under MIT by request to the author. + // http://javascript.nwbox.com/IEContentLoaded/ + doc.documentElement.doScroll("left"); + } catch (ex) { + setTimeout(arguments.callee, 0); + return; + } + + t._pageInit(win); + })(); + } + } else if (doc.addEventListener) { + t._add(win, 'DOMContentLoaded', function() { + t._pageInit(win); + }); + } + + t._add(win, 'load', function() { + t._pageInit(win); + }); + }, + + _stoppers : { + preventDefault : function() { + this.returnValue = false; + }, + + stopPropagation : function() { + this.cancelBubble = true; + } + } + }); + + Event = tinymce.dom.Event = new tinymce.dom.EventUtils(); + + // Dispatch DOM content loaded event for IE and Safari + Event._wait(window); + + tinymce.addUnload(function() { + Event.destroy(); + }); +})(tinymce); + +(function(tinymce) { + tinymce.dom.Element = function(id, settings) { + var t = this, dom, el; + + t.settings = settings = settings || {}; + t.id = id; + t.dom = dom = settings.dom || tinymce.DOM; + + // Only IE leaks DOM references, this is a lot faster + if (!tinymce.isIE) + el = dom.get(t.id); + + tinymce.each( + ('getPos,getRect,getParent,add,setStyle,getStyle,setStyles,' + + 'setAttrib,setAttribs,getAttrib,addClass,removeClass,' + + 'hasClass,getOuterHTML,setOuterHTML,remove,show,hide,' + + 'isHidden,setHTML,get').split(/,/) + , function(k) { + t[k] = function() { + var a = [id], i; + + for (i = 0; i < arguments.length; i++) + a.push(arguments[i]); + + a = dom[k].apply(dom, a); + t.update(k); + + return a; + }; + }); + + tinymce.extend(t, { + on : function(n, f, s) { + return tinymce.dom.Event.add(t.id, n, f, s); + }, + + getXY : function() { + return { + x : parseInt(t.getStyle('left')), + y : parseInt(t.getStyle('top')) + }; + }, + + getSize : function() { + var n = dom.get(t.id); + + return { + w : parseInt(t.getStyle('width') || n.clientWidth), + h : parseInt(t.getStyle('height') || n.clientHeight) + }; + }, + + moveTo : function(x, y) { + t.setStyles({left : x, top : y}); + }, + + moveBy : function(x, y) { + var p = t.getXY(); + + t.moveTo(p.x + x, p.y + y); + }, + + resizeTo : function(w, h) { + t.setStyles({width : w, height : h}); + }, + + resizeBy : function(w, h) { + var s = t.getSize(); + + t.resizeTo(s.w + w, s.h + h); + }, + + update : function(k) { + var b; + + if (tinymce.isIE6 && settings.blocker) { + k = k || ''; + + // Ignore getters + if (k.indexOf('get') === 0 || k.indexOf('has') === 0 || k.indexOf('is') === 0) + return; + + // Remove blocker on remove + if (k == 'remove') { + dom.remove(t.blocker); + return; + } + + if (!t.blocker) { + t.blocker = dom.uniqueId(); + b = dom.add(settings.container || dom.getRoot(), 'iframe', {id : t.blocker, style : 'position:absolute;', frameBorder : 0, src : 'javascript:""'}); + dom.setStyle(b, 'opacity', 0); + } else + b = dom.get(t.blocker); + + dom.setStyles(b, { + left : t.getStyle('left', 1), + top : t.getStyle('top', 1), + width : t.getStyle('width', 1), + height : t.getStyle('height', 1), + display : t.getStyle('display', 1), + zIndex : parseInt(t.getStyle('zIndex', 1) || 0) - 1 + }); + } + } + }); + }; +})(tinymce); + +(function(tinymce) { + function trimNl(s) { + return s.replace(/[\n\r]+/g, ''); + }; + + // Shorten names + var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each; + + tinymce.create('tinymce.dom.Selection', { + Selection : function(dom, win, serializer) { + var t = this; + + t.dom = dom; + t.win = win; + t.serializer = serializer; + + // Add events + each([ + 'onBeforeSetContent', + + 'onBeforeGetContent', + + 'onSetContent', + + 'onGetContent' + ], function(e) { + t[e] = new tinymce.util.Dispatcher(t); + }); + + // No W3C Range support + if (!t.win.getSelection) + t.tridentSel = new tinymce.dom.TridentSelection(t); + + if (tinymce.isIE && dom.boxModel) + this._fixIESelection(); + + // Prevent leaks + tinymce.addUnload(t.destroy, t); + }, + + setCursorLocation: function(node, offset) { + var t = this; var r = t.dom.createRng(); + r.setStart(node, offset); + r.setEnd(node, offset); + t.setRng(r); + t.collapse(false); + }, + getContent : function(s) { + var t = this, r = t.getRng(), e = t.dom.create("body"), se = t.getSel(), wb, wa, n; + + s = s || {}; + wb = wa = ''; + s.get = true; + s.format = s.format || 'html'; + s.forced_root_block = ''; + t.onBeforeGetContent.dispatch(t, s); + + if (s.format == 'text') + return t.isCollapsed() ? '' : (r.text || (se.toString ? se.toString() : '')); + + if (r.cloneContents) { + n = r.cloneContents(); + + if (n) + e.appendChild(n); + } else if (is(r.item) || is(r.htmlText)) { + // IE will produce invalid markup if elements are present that + // it doesn't understand like custom elements or HTML5 elements. + // Adding a BR in front of the contents and then remoiving it seems to fix it though. + e.innerHTML = '<br>' + (r.item ? r.item(0).outerHTML : r.htmlText); + e.removeChild(e.firstChild); + } else + e.innerHTML = r.toString(); + + // Keep whitespace before and after + if (/^\s/.test(e.innerHTML)) + wb = ' '; + + if (/\s+$/.test(e.innerHTML)) + wa = ' '; + + s.getInner = true; + + s.content = t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa; + t.onGetContent.dispatch(t, s); + + return s.content; + }, + + setContent : function(content, args) { + var self = this, rng = self.getRng(), caretNode, doc = self.win.document, frag, temp; + + args = args || {format : 'html'}; + args.set = true; + content = args.content = content; + + // Dispatch before set content event + if (!args.no_events) + self.onBeforeSetContent.dispatch(self, args); + + content = args.content; + + if (rng.insertNode) { + // Make caret marker since insertNode places the caret in the beginning of text after insert + content += '<span id="__caret">_</span>'; + + // Delete and insert new node + if (rng.startContainer == doc && rng.endContainer == doc) { + // WebKit will fail if the body is empty since the range is then invalid and it can't insert contents + doc.body.innerHTML = content; + } else { + rng.deleteContents(); + + if (doc.body.childNodes.length == 0) { + doc.body.innerHTML = content; + } else { + // createContextualFragment doesn't exists in IE 9 DOMRanges + if (rng.createContextualFragment) { + rng.insertNode(rng.createContextualFragment(content)); + } else { + // Fake createContextualFragment call in IE 9 + frag = doc.createDocumentFragment(); + temp = doc.createElement('div'); + + frag.appendChild(temp); + temp.outerHTML = content; + + rng.insertNode(frag); + } + } + } + + // Move to caret marker + caretNode = self.dom.get('__caret'); + + // Make sure we wrap it compleatly, Opera fails with a simple select call + rng = doc.createRange(); + rng.setStartBefore(caretNode); + rng.setEndBefore(caretNode); + self.setRng(rng); + + // Remove the caret position + self.dom.remove('__caret'); + + try { + self.setRng(rng); + } catch (ex) { + // Might fail on Opera for some odd reason + } + } else { + if (rng.item) { + // Delete content and get caret text selection + doc.execCommand('Delete', false, null); + rng = self.getRng(); + } + + // Explorer removes spaces from the beginning of pasted contents + if (/^\s+/.test(content)) { + rng.pasteHTML('<span id="__mce_tmp">_</span>' + content); + self.dom.remove('__mce_tmp'); + } else + rng.pasteHTML(content); + } + + // Dispatch set content event + if (!args.no_events) + self.onSetContent.dispatch(self, args); + }, + + getStart : function() { + var rng = this.getRng(), startElement, parentElement, checkRng, node; + + if (rng.duplicate || rng.item) { + // Control selection, return first item + if (rng.item) + return rng.item(0); + + // Get start element + checkRng = rng.duplicate(); + checkRng.collapse(1); + startElement = checkRng.parentElement(); + + // Check if range parent is inside the start element, then return the inner parent element + // This will fix issues when a single element is selected, IE would otherwise return the wrong start element + parentElement = node = rng.parentElement(); + while (node = node.parentNode) { + if (node == startElement) { + startElement = parentElement; + break; + } + } + + return startElement; + } else { + startElement = rng.startContainer; + + if (startElement.nodeType == 1 && startElement.hasChildNodes()) + startElement = startElement.childNodes[Math.min(startElement.childNodes.length - 1, rng.startOffset)]; + + if (startElement && startElement.nodeType == 3) + return startElement.parentNode; + + return startElement; + } + }, + + getEnd : function() { + var t = this, r = t.getRng(), e, eo; + + if (r.duplicate || r.item) { + if (r.item) + return r.item(0); + + r = r.duplicate(); + r.collapse(0); + e = r.parentElement(); + + if (e && e.nodeName == 'BODY') + return e.lastChild || e; + + return e; + } else { + e = r.endContainer; + eo = r.endOffset; + + if (e.nodeType == 1 && e.hasChildNodes()) + e = e.childNodes[eo > 0 ? eo - 1 : eo]; + + if (e && e.nodeType == 3) + return e.parentNode; + + return e; + } + }, + + getBookmark : function(type, normalized) { + var t = this, dom = t.dom, rng, rng2, id, collapsed, name, element, index, chr = '\uFEFF', styles; + + function findIndex(name, element) { + var index = 0; + + each(dom.select(name), function(node, i) { + if (node == element) + index = i; + }); + + return index; + }; + + if (type == 2) { + function getLocation() { + var rng = t.getRng(true), root = dom.getRoot(), bookmark = {}; + + function getPoint(rng, start) { + var container = rng[start ? 'startContainer' : 'endContainer'], + offset = rng[start ? 'startOffset' : 'endOffset'], point = [], node, childNodes, after = 0; + + if (container.nodeType == 3) { + if (normalized) { + for (node = container.previousSibling; node && node.nodeType == 3; node = node.previousSibling) + offset += node.nodeValue.length; + } + + point.push(offset); + } else { + childNodes = container.childNodes; + + if (offset >= childNodes.length && childNodes.length) { + after = 1; + offset = Math.max(0, childNodes.length - 1); + } + + point.push(t.dom.nodeIndex(childNodes[offset], normalized) + after); + } + + for (; container && container != root; container = container.parentNode) + point.push(t.dom.nodeIndex(container, normalized)); + + return point; + }; + + bookmark.start = getPoint(rng, true); + + if (!t.isCollapsed()) + bookmark.end = getPoint(rng); + + return bookmark; + }; + + if (t.tridentSel) + return t.tridentSel.getBookmark(type); + + return getLocation(); + } + + // Handle simple range + if (type) + return {rng : t.getRng()}; + + rng = t.getRng(); + id = dom.uniqueId(); + collapsed = tinyMCE.activeEditor.selection.isCollapsed(); + styles = 'overflow:hidden;line-height:0px'; + + // Explorer method + if (rng.duplicate || rng.item) { + // Text selection + if (!rng.item) { + rng2 = rng.duplicate(); + + try { + // Insert start marker + rng.collapse(); + rng.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_start" style="' + styles + '">' + chr + '</span>'); + + // Insert end marker + if (!collapsed) { + rng2.collapse(false); + + // Detect the empty space after block elements in IE and move the end back one character <p></p>] becomes <p>]</p> + rng.moveToElementText(rng2.parentElement()); + if (rng.compareEndPoints('StartToEnd', rng2) == 0) + rng2.move('character', -1); + + rng2.pasteHTML('<span data-mce-type="bookmark" id="' + id + '_end" style="' + styles + '">' + chr + '</span>'); + } + } catch (ex) { + // IE might throw unspecified error so lets ignore it + return null; + } + } else { + // Control selection + element = rng.item(0); + name = element.nodeName; + + return {name : name, index : findIndex(name, element)}; + } + } else { + element = t.getNode(); + name = element.nodeName; + if (name == 'IMG') + return {name : name, index : findIndex(name, element)}; + + // W3C method + rng2 = rng.cloneRange(); + + // Insert end marker + if (!collapsed) { + rng2.collapse(false); + rng2.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_end', style : styles}, chr)); + } + + rng.collapse(true); + rng.insertNode(dom.create('span', {'data-mce-type' : "bookmark", id : id + '_start', style : styles}, chr)); + } + + t.moveToBookmark({id : id, keep : 1}); + + return {id : id}; + }, + + moveToBookmark : function(bookmark) { + var t = this, dom = t.dom, marker1, marker2, rng, root, startContainer, endContainer, startOffset, endOffset; + + if (bookmark) { + if (bookmark.start) { + rng = dom.createRng(); + root = dom.getRoot(); + + function setEndPoint(start) { + var point = bookmark[start ? 'start' : 'end'], i, node, offset, children; + + if (point) { + offset = point[0]; + + // Find container node + for (node = root, i = point.length - 1; i >= 1; i--) { + children = node.childNodes; + + if (point[i] > children.length - 1) + return; + + node = children[point[i]]; + } + + // Move text offset to best suitable location + if (node.nodeType === 3) + offset = Math.min(point[0], node.nodeValue.length); + + // Move element offset to best suitable location + if (node.nodeType === 1) + offset = Math.min(point[0], node.childNodes.length); + + // Set offset within container node + if (start) + rng.setStart(node, offset); + else + rng.setEnd(node, offset); + } + + return true; + }; + + if (t.tridentSel) + return t.tridentSel.moveToBookmark(bookmark); + + if (setEndPoint(true) && setEndPoint()) { + t.setRng(rng); + } + } else if (bookmark.id) { + function restoreEndPoint(suffix) { + var marker = dom.get(bookmark.id + '_' + suffix), node, idx, next, prev, keep = bookmark.keep; + + if (marker) { + node = marker.parentNode; + + if (suffix == 'start') { + if (!keep) { + idx = dom.nodeIndex(marker); + } else { + node = marker.firstChild; + idx = 1; + } + + startContainer = endContainer = node; + startOffset = endOffset = idx; + } else { + if (!keep) { + idx = dom.nodeIndex(marker); + } else { + node = marker.firstChild; + idx = 1; + } + + endContainer = node; + endOffset = idx; + } + + if (!keep) { + prev = marker.previousSibling; + next = marker.nextSibling; + + // Remove all marker text nodes + each(tinymce.grep(marker.childNodes), function(node) { + if (node.nodeType == 3) + node.nodeValue = node.nodeValue.replace(/\uFEFF/g, ''); + }); + + // Remove marker but keep children if for example contents where inserted into the marker + // Also remove duplicated instances of the marker for example by a split operation or by WebKit auto split on paste feature + while (marker = dom.get(bookmark.id + '_' + suffix)) + dom.remove(marker, 1); + + // If siblings are text nodes then merge them unless it's Opera since it some how removes the node + // and we are sniffing since adding a lot of detection code for a browser with 3% of the market isn't worth the effort. Sorry, Opera but it's just a fact + if (prev && next && prev.nodeType == next.nodeType && prev.nodeType == 3 && !tinymce.isOpera) { + idx = prev.nodeValue.length; + prev.appendData(next.nodeValue); + dom.remove(next); + + if (suffix == 'start') { + startContainer = endContainer = prev; + startOffset = endOffset = idx; + } else { + endContainer = prev; + endOffset = idx; + } + } + } + } + }; + + function addBogus(node) { + // Adds a bogus BR element for empty block elements or just a space on IE since it renders BR elements incorrectly + if (dom.isBlock(node) && !node.innerHTML) + node.innerHTML = !isIE ? '<br data-mce-bogus="1" />' : ' '; + + return node; + }; + + // Restore start/end points + restoreEndPoint('start'); + restoreEndPoint('end'); + + if (startContainer) { + rng = dom.createRng(); + rng.setStart(addBogus(startContainer), startOffset); + rng.setEnd(addBogus(endContainer), endOffset); + t.setRng(rng); + } + } else if (bookmark.name) { + t.select(dom.select(bookmark.name)[bookmark.index]); + } else if (bookmark.rng) + t.setRng(bookmark.rng); + } + }, + + select : function(node, content) { + var t = this, dom = t.dom, rng = dom.createRng(), idx; + + if (node) { + idx = dom.nodeIndex(node); + rng.setStart(node.parentNode, idx); + rng.setEnd(node.parentNode, idx + 1); + + // Find first/last text node or BR element + if (content) { + function setPoint(node, start) { + var walker = new tinymce.dom.TreeWalker(node, node); + + do { + // Text node + if (node.nodeType == 3 && tinymce.trim(node.nodeValue).length != 0) { + if (start) + rng.setStart(node, 0); + else + rng.setEnd(node, node.nodeValue.length); + + return; + } + + // BR element + if (node.nodeName == 'BR') { + if (start) + rng.setStartBefore(node); + else + rng.setEndBefore(node); + + return; + } + } while (node = (start ? walker.next() : walker.prev())); + }; + + setPoint(node, 1); + setPoint(node); + } + + t.setRng(rng); + } + + return node; + }, + + isCollapsed : function() { + var t = this, r = t.getRng(), s = t.getSel(); + + if (!r || r.item) + return false; + + if (r.compareEndPoints) + return r.compareEndPoints('StartToEnd', r) === 0; + + return !s || r.collapsed; + }, + + collapse : function(to_start) { + var self = this, rng = self.getRng(), node; + + // Control range on IE + if (rng.item) { + node = rng.item(0); + rng = self.win.document.body.createTextRange(); + rng.moveToElementText(node); + } + + rng.collapse(!!to_start); + self.setRng(rng); + }, + + getSel : function() { + var t = this, w = this.win; + + return w.getSelection ? w.getSelection() : w.document.selection; + }, + + getRng : function(w3c) { + var t = this, s, r, elm, doc = t.win.document; + + // Found tridentSel object then we need to use that one + if (w3c && t.tridentSel) + return t.tridentSel.getRangeAt(0); + + try { + if (s = t.getSel()) + r = s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : doc.createRange()); + } catch (ex) { + // IE throws unspecified error here if TinyMCE is placed in a frame/iframe + } + + // We have W3C ranges and it's IE then fake control selection since IE9 doesn't handle that correctly yet + if (tinymce.isIE && r && r.setStart && doc.selection.createRange().item) { + elm = doc.selection.createRange().item(0); + r = doc.createRange(); + r.setStartBefore(elm); + r.setEndAfter(elm); + } + + // No range found then create an empty one + // This can occur when the editor is placed in a hidden container element on Gecko + // Or on IE when there was an exception + if (!r) + r = doc.createRange ? doc.createRange() : doc.body.createTextRange(); + + if (t.selectedRange && t.explicitRange) { + if (r.compareBoundaryPoints(r.START_TO_START, t.selectedRange) === 0 && r.compareBoundaryPoints(r.END_TO_END, t.selectedRange) === 0) { + // Safari, Opera and Chrome only ever select text which causes the range to change. + // This lets us use the originally set range if the selection hasn't been changed by the user. + r = t.explicitRange; + } else { + t.selectedRange = null; + t.explicitRange = null; + } + } + + return r; + }, + + setRng : function(r) { + var s, t = this; + + if (!t.tridentSel) { + s = t.getSel(); + + if (s) { + t.explicitRange = r; + + try { + s.removeAllRanges(); + } catch (ex) { + // IE9 might throw errors here don't know why + } + + s.addRange(r); + t.selectedRange = s.getRangeAt(0); + } + } else { + // Is W3C Range + if (r.cloneRange) { + t.tridentSel.addRange(r); + return; + } + + // Is IE specific range + try { + r.select(); + } catch (ex) { + // Needed for some odd IE bug #1843306 + } + } + }, + + setNode : function(n) { + var t = this; + + t.setContent(t.dom.getOuterHTML(n)); + + return n; + }, + + getNode : function() { + var t = this, rng = t.getRng(), sel = t.getSel(), elm, start = rng.startContainer, end = rng.endContainer; + + // Range maybe lost after the editor is made visible again + if (!rng) + return t.dom.getRoot(); + + if (rng.setStart) { + elm = rng.commonAncestorContainer; + + // Handle selection a image or other control like element such as anchors + if (!rng.collapsed) { + if (rng.startContainer == rng.endContainer) { + if (rng.endOffset - rng.startOffset < 2) { + if (rng.startContainer.hasChildNodes()) + elm = rng.startContainer.childNodes[rng.startOffset]; + } + } + + // If the anchor node is a element instead of a text node then return this element + //if (tinymce.isWebKit && sel.anchorNode && sel.anchorNode.nodeType == 1) + // return sel.anchorNode.childNodes[sel.anchorOffset]; + + // Handle cases where the selection is immediately wrapped around a node and return that node instead of it's parent. + // This happens when you double click an underlined word in FireFox. + if (start.nodeType === 3 && end.nodeType === 3) { + function skipEmptyTextNodes(n, forwards) { + var orig = n; + while (n && n.nodeType === 3 && n.length === 0) { + n = forwards ? n.nextSibling : n.previousSibling; + } + return n || orig; + } + if (start.length === rng.startOffset) { + start = skipEmptyTextNodes(start.nextSibling, true); + } else { + start = start.parentNode; + } + if (rng.endOffset === 0) { + end = skipEmptyTextNodes(end.previousSibling, false); + } else { + end = end.parentNode; + } + + if (start && start === end) + return start; + } + } + + if (elm && elm.nodeType == 3) + return elm.parentNode; + + return elm; + } + + return rng.item ? rng.item(0) : rng.parentElement(); + }, + + getSelectedBlocks : function(st, en) { + var t = this, dom = t.dom, sb, eb, n, bl = []; + + sb = dom.getParent(st || t.getStart(), dom.isBlock); + eb = dom.getParent(en || t.getEnd(), dom.isBlock); + + if (sb) + bl.push(sb); + + if (sb && eb && sb != eb) { + n = sb; + + while ((n = n.nextSibling) && n != eb) { + if (dom.isBlock(n)) + bl.push(n); + } + } + + if (eb && sb != eb) + bl.push(eb); + + return bl; + }, + + normalize : function() { + var self = this, rng, normalized; + + // Normalize only on non IE browsers for now + if (tinymce.isIE) + return; + + function normalizeEndPoint(start) { + var container, offset, walker, dom = self.dom, body = dom.getRoot(), node; + + container = rng[(start ? 'start' : 'end') + 'Container']; + offset = rng[(start ? 'start' : 'end') + 'Offset']; + + // If the container is a document move it to the body element + if (container.nodeType === 9) { + container = container.body; + offset = 0; + } + + // If the container is body try move it into the closest text node or position + // TODO: Add more logic here to handle element selection cases + if (container === body) { + // Resolve the index + if (container.hasChildNodes()) { + container = container.childNodes[Math.min(!start && offset > 0 ? offset - 1 : offset, container.childNodes.length - 1)]; + offset = 0; + + // Don't walk into elements that doesn't have any child nodes like a IMG + if (container.hasChildNodes()) { + // Walk the DOM to find a text node to place the caret at or a BR + node = container; + walker = new tinymce.dom.TreeWalker(container, body); + do { + // Found a text node use that position + if (node.nodeType === 3) { + offset = start ? 0 : node.nodeValue.length - 1; + container = node; + break; + } + + // Found a BR element that we can place the caret before + if (node.nodeName === 'BR') { + offset = dom.nodeIndex(node); + container = node.parentNode; + break; + } + } while (node = (start ? walker.next() : walker.prev())); + + normalized = true; + } + } + } + + // Set endpoint if it was normalized + if (normalized) + rng['set' + (start ? 'Start' : 'End')](container, offset); + }; + + rng = self.getRng(); + + // Normalize the end points + normalizeEndPoint(true); + + if (rng.collapsed) + normalizeEndPoint(); + + // Set the selection if it was normalized + if (normalized) { + //console.log(self.dom.dumpRng(rng)); + self.setRng(rng); + } + }, + + destroy : function(s) { + var t = this; + + t.win = null; + + // Manual destroy then remove unload handler + if (!s) + tinymce.removeUnload(t.destroy); + }, + + // IE has an issue where you can't select/move the caret by clicking outside the body if the document is in standards mode + _fixIESelection : function() { + var dom = this.dom, doc = dom.doc, body = doc.body, started, startRng, htmlElm; + + // Make HTML element unselectable since we are going to handle selection by hand + doc.documentElement.unselectable = true; + + // Return range from point or null if it failed + function rngFromPoint(x, y) { + var rng = body.createTextRange(); + + try { + rng.moveToPoint(x, y); + } catch (ex) { + // IE sometimes throws and exception, so lets just ignore it + rng = null; + } + + return rng; + }; + + // Fires while the selection is changing + function selectionChange(e) { + var pointRng; + + // Check if the button is down or not + if (e.button) { + // Create range from mouse position + pointRng = rngFromPoint(e.x, e.y); + + if (pointRng) { + // Check if pointRange is before/after selection then change the endPoint + if (pointRng.compareEndPoints('StartToStart', startRng) > 0) + pointRng.setEndPoint('StartToStart', startRng); + else + pointRng.setEndPoint('EndToEnd', startRng); + + pointRng.select(); + } + } else + endSelection(); + } + + // Removes listeners + function endSelection() { + var rng = doc.selection.createRange(); + + // If the range is collapsed then use the last start range + if (startRng && !rng.item && rng.compareEndPoints('StartToEnd', rng) === 0) + startRng.select(); + + dom.unbind(doc, 'mouseup', endSelection); + dom.unbind(doc, 'mousemove', selectionChange); + startRng = started = 0; + }; + + // Detect when user selects outside BODY + dom.bind(doc, ['mousedown', 'contextmenu'], function(e) { + if (e.target.nodeName === 'HTML') { + if (started) + endSelection(); + + // Detect vertical scrollbar, since IE will fire a mousedown on the scrollbar and have target set as HTML + htmlElm = doc.documentElement; + if (htmlElm.scrollHeight > htmlElm.clientHeight) + return; + + started = 1; + // Setup start position + startRng = rngFromPoint(e.x, e.y); + if (startRng) { + // Listen for selection change events + dom.bind(doc, 'mouseup', endSelection); + dom.bind(doc, 'mousemove', selectionChange); + + dom.win.focus(); + startRng.select(); + } + } + }); + } + }); +})(tinymce); + +(function(tinymce) { + tinymce.dom.Serializer = function(settings, dom, schema) { + var onPreProcess, onPostProcess, isIE = tinymce.isIE, each = tinymce.each, htmlParser; + + // Support the old apply_source_formatting option + if (!settings.apply_source_formatting) + settings.indent = false; + + settings.remove_trailing_brs = true; + + // Default DOM and Schema if they are undefined + dom = dom || tinymce.DOM; + schema = schema || new tinymce.html.Schema(settings); + settings.entity_encoding = settings.entity_encoding || 'named'; + + onPreProcess = new tinymce.util.Dispatcher(self); + + onPostProcess = new tinymce.util.Dispatcher(self); + + htmlParser = new tinymce.html.DomParser(settings, schema); + + // Convert move data-mce-src, data-mce-href and data-mce-style into nodes or process them if needed + htmlParser.addAttributeFilter('src,href,style', function(nodes, name) { + var i = nodes.length, node, value, internalName = 'data-mce-' + name, urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope, undef; + + while (i--) { + node = nodes[i]; + + value = node.attributes.map[internalName]; + if (value !== undef) { + // Set external name to internal value and remove internal + node.attr(name, value.length > 0 ? value : null); + node.attr(internalName, null); + } else { + // No internal attribute found then convert the value we have in the DOM + value = node.attributes.map[name]; + + if (name === "style") + value = dom.serializeStyle(dom.parseStyle(value), node.name); + else if (urlConverter) + value = urlConverter.call(urlConverterScope, value, name, node.name); + + node.attr(name, value.length > 0 ? value : null); + } + } + }); + + // Remove internal classes mceItem<..> + htmlParser.addAttributeFilter('class', function(nodes, name) { + var i = nodes.length, node, value; + + while (i--) { + node = nodes[i]; + value = node.attr('class').replace(/\s*mce(Item\w+|Selected)\s*/g, ''); + node.attr('class', value.length > 0 ? value : null); + } + }); + + // Remove bookmark elements + htmlParser.addAttributeFilter('data-mce-type', function(nodes, name, args) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + + if (node.attributes.map['data-mce-type'] === 'bookmark' && !args.cleanup) + node.remove(); + } + }); + + // Force script into CDATA sections and remove the mce- prefix also add comments around styles + htmlParser.addNodeFilter('script,style', function(nodes, name) { + var i = nodes.length, node, value; + + function trim(value) { + return value.replace(/(<!--\[CDATA\[|\]\]-->)/g, '\n') + .replace(/^[\r\n]*|[\r\n]*$/g, '') + .replace(/^\s*(\/\/\s*<!--|\/\/\s*<!\[CDATA\[|<!--|<!\[CDATA\[)[\r\n]*/g, '') + .replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->|\]\]-->)\s*$/g, ''); + }; + + while (i--) { + node = nodes[i]; + value = node.firstChild ? node.firstChild.value : ''; + + if (name === "script") { + // Remove mce- prefix from script elements + node.attr('type', (node.attr('type') || 'text/javascript').replace(/^mce\-/, '')); + + if (value.length > 0) + node.firstChild.value = '// <![CDATA[\n' + trim(value) + '\n// ]]>'; + } else { + if (value.length > 0) + node.firstChild.value = '<!--\n' + trim(value) + '\n-->'; + } + } + }); + + // Convert comments to cdata and handle protected comments + htmlParser.addNodeFilter('#comment', function(nodes, name) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + + if (node.value.indexOf('[CDATA[') === 0) { + node.name = '#cdata'; + node.type = 4; + node.value = node.value.replace(/^\[CDATA\[|\]\]$/g, ''); + } else if (node.value.indexOf('mce:protected ') === 0) { + node.name = "#text"; + node.type = 3; + node.raw = true; + node.value = unescape(node.value).substr(14); + } + } + }); + + htmlParser.addNodeFilter('xml:namespace,input', function(nodes, name) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + if (node.type === 7) + node.remove(); + else if (node.type === 1) { + if (name === "input" && !("type" in node.attributes.map)) + node.attr('type', 'text'); + } + } + }); + + // Fix list elements, TODO: Replace this later + if (settings.fix_list_elements) { + htmlParser.addNodeFilter('ul,ol', function(nodes, name) { + var i = nodes.length, node, parentNode; + + while (i--) { + node = nodes[i]; + parentNode = node.parent; + + if (parentNode.name === 'ul' || parentNode.name === 'ol') { + if (node.prev && node.prev.name === 'li') { + node.prev.append(node); + } + } + } + }); + } + + // Remove internal data attributes + htmlParser.addAttributeFilter('data-mce-src,data-mce-href,data-mce-style', function(nodes, name) { + var i = nodes.length; + + while (i--) { + nodes[i].attr(name, null); + } + }); + + // Return public methods + return { + schema : schema, + + addNodeFilter : htmlParser.addNodeFilter, + + addAttributeFilter : htmlParser.addAttributeFilter, + + onPreProcess : onPreProcess, + + onPostProcess : onPostProcess, + + serialize : function(node, args) { + var impl, doc, oldDoc, htmlSerializer, content; + + // Explorer won't clone contents of script and style and the + // selected index of select elements are cleared on a clone operation. + if (isIE && dom.select('script,style,select,map').length > 0) { + content = node.innerHTML; + node = node.cloneNode(false); + dom.setHTML(node, content); + } else + node = node.cloneNode(true); + + // Nodes needs to be attached to something in WebKit/Opera + // Older builds of Opera crashes if you attach the node to an document created dynamically + // and since we can't feature detect a crash we need to sniff the acutal build number + // This fix will make DOM ranges and make Sizzle happy! + impl = node.ownerDocument.implementation; + if (impl.createHTMLDocument) { + // Create an empty HTML document + doc = impl.createHTMLDocument(""); + + // Add the element or it's children if it's a body element to the new document + each(node.nodeName == 'BODY' ? node.childNodes : [node], function(node) { + doc.body.appendChild(doc.importNode(node, true)); + }); + + // Grab first child or body element for serialization + if (node.nodeName != 'BODY') + node = doc.body.firstChild; + else + node = doc.body; + + // set the new document in DOMUtils so createElement etc works + oldDoc = dom.doc; + dom.doc = doc; + } + + args = args || {}; + args.format = args.format || 'html'; + + // Pre process + if (!args.no_events) { + args.node = node; + onPreProcess.dispatch(self, args); + } + + // Setup serializer + htmlSerializer = new tinymce.html.Serializer(settings, schema); + + // Parse and serialize HTML + args.content = htmlSerializer.serialize( + htmlParser.parse(args.getInner ? node.innerHTML : tinymce.trim(dom.getOuterHTML(node), args), args) + ); + + // Replace all BOM characters for now until we can find a better solution + if (!args.cleanup) + args.content = args.content.replace(/\uFEFF/g, ''); + + // Post process + if (!args.no_events) + onPostProcess.dispatch(self, args); + + // Restore the old document if it was changed + if (oldDoc) + dom.doc = oldDoc; + + args.node = null; + + return args.content; + }, + + addRules : function(rules) { + schema.addValidElements(rules); + }, + + setRules : function(rules) { + schema.setValidElements(rules); + } + }; + }; +})(tinymce); +(function(tinymce) { + tinymce.dom.ScriptLoader = function(settings) { + var QUEUED = 0, + LOADING = 1, + LOADED = 2, + states = {}, + queue = [], + scriptLoadedCallbacks = {}, + queueLoadedCallbacks = [], + loading = 0, + undefined; + + function loadScript(url, callback) { + var t = this, dom = tinymce.DOM, elm, uri, loc, id; + + // Execute callback when script is loaded + function done() { + dom.remove(id); + + if (elm) + elm.onreadystatechange = elm.onload = elm = null; + + callback(); + }; + + function error() { + // Report the error so it's easier for people to spot loading errors + if (typeof(console) !== "undefined" && console.log) + console.log("Failed to load: " + url); + + // We can't mark it as done if there is a load error since + // A) We don't want to produce 404 errors on the server and + // B) the onerror event won't fire on all browsers. + // done(); + }; + + id = dom.uniqueId(); + + if (tinymce.isIE6) { + uri = new tinymce.util.URI(url); + loc = location; + + // If script is from same domain and we + // use IE 6 then use XHR since it's more reliable + if (uri.host == loc.hostname && uri.port == loc.port && (uri.protocol + ':') == loc.protocol && uri.protocol.toLowerCase() != 'file') { + tinymce.util.XHR.send({ + url : tinymce._addVer(uri.getURI()), + success : function(content) { + // Create new temp script element + var script = dom.create('script', { + type : 'text/javascript' + }); + + // Evaluate script in global scope + script.text = content; + document.getElementsByTagName('head')[0].appendChild(script); + dom.remove(script); + + done(); + }, + + error : error + }); + + return; + } + } + + // Create new script element + elm = dom.create('script', { + id : id, + type : 'text/javascript', + src : tinymce._addVer(url) + }); + + // Add onload listener for non IE browsers since IE9 + // fires onload event before the script is parsed and executed + if (!tinymce.isIE) + elm.onload = done; + + // Add onerror event will get fired on some browsers but not all of them + elm.onerror = error; + + // Opera 9.60 doesn't seem to fire the onreadystate event at correctly + if (!tinymce.isOpera) { + elm.onreadystatechange = function() { + var state = elm.readyState; + + // Loaded state is passed on IE 6 however there + // are known issues with this method but we can't use + // XHR in a cross domain loading + if (state == 'complete' || state == 'loaded') + done(); + }; + } + + // Most browsers support this feature so we report errors + // for those at least to help users track their missing plugins etc + // todo: Removed since it produced error if the document is unloaded by navigating away, re-add it as an option + /*elm.onerror = function() { + alert('Failed to load: ' + url); + };*/ + + // Add script to document + (document.getElementsByTagName('head')[0] || document.body).appendChild(elm); + }; + + this.isDone = function(url) { + return states[url] == LOADED; + }; + + this.markDone = function(url) { + states[url] = LOADED; + }; + + this.add = this.load = function(url, callback, scope) { + var item, state = states[url]; + + // Add url to load queue + if (state == undefined) { + queue.push(url); + states[url] = QUEUED; + } + + if (callback) { + // Store away callback for later execution + if (!scriptLoadedCallbacks[url]) + scriptLoadedCallbacks[url] = []; + + scriptLoadedCallbacks[url].push({ + func : callback, + scope : scope || this + }); + } + }; + + this.loadQueue = function(callback, scope) { + this.loadScripts(queue, callback, scope); + }; + + this.loadScripts = function(scripts, callback, scope) { + var loadScripts; + + function execScriptLoadedCallbacks(url) { + // Execute URL callback functions + tinymce.each(scriptLoadedCallbacks[url], function(callback) { + callback.func.call(callback.scope); + }); + + scriptLoadedCallbacks[url] = undefined; + }; + + queueLoadedCallbacks.push({ + func : callback, + scope : scope || this + }); + + loadScripts = function() { + var loadingScripts = tinymce.grep(scripts); + + // Current scripts has been handled + scripts.length = 0; + + // Load scripts that needs to be loaded + tinymce.each(loadingScripts, function(url) { + // Script is already loaded then execute script callbacks directly + if (states[url] == LOADED) { + execScriptLoadedCallbacks(url); + return; + } + + // Is script not loading then start loading it + if (states[url] != LOADING) { + states[url] = LOADING; + loading++; + + loadScript(url, function() { + states[url] = LOADED; + loading--; + + execScriptLoadedCallbacks(url); + + // Load more scripts if they where added by the recently loaded script + loadScripts(); + }); + } + }); + + // No scripts are currently loading then execute all pending queue loaded callbacks + if (!loading) { + tinymce.each(queueLoadedCallbacks, function(callback) { + callback.func.call(callback.scope); + }); + + queueLoadedCallbacks.length = 0; + } + }; + + loadScripts(); + }; + }; + + // Global script loader + tinymce.ScriptLoader = new tinymce.dom.ScriptLoader(); +})(tinymce); + +tinymce.dom.TreeWalker = function(start_node, root_node) { + var node = start_node; + + function findSibling(node, start_name, sibling_name, shallow) { + var sibling, parent; + + if (node) { + // Walk into nodes if it has a start + if (!shallow && node[start_name]) + return node[start_name]; + + // Return the sibling if it has one + if (node != root_node) { + sibling = node[sibling_name]; + if (sibling) + return sibling; + + // Walk up the parents to look for siblings + for (parent = node.parentNode; parent && parent != root_node; parent = parent.parentNode) { + sibling = parent[sibling_name]; + if (sibling) + return sibling; + } + } + } + }; + + this.current = function() { + return node; + }; + + this.next = function(shallow) { + return (node = findSibling(node, 'firstChild', 'nextSibling', shallow)); + }; + + this.prev = function(shallow) { + return (node = findSibling(node, 'lastChild', 'previousSibling', shallow)); + }; +}; + +(function(tinymce) { + tinymce.dom.RangeUtils = function(dom) { + var INVISIBLE_CHAR = '\uFEFF'; + + this.walk = function(rng, callback) { + var startContainer = rng.startContainer, + startOffset = rng.startOffset, + endContainer = rng.endContainer, + endOffset = rng.endOffset, + ancestor, startPoint, + endPoint, node, parent, siblings, nodes; + + // Handle table cell selection the table plugin enables + // you to fake select table cells and perform formatting actions on them + nodes = dom.select('td.mceSelected,th.mceSelected'); + if (nodes.length > 0) { + tinymce.each(nodes, function(node) { + callback([node]); + }); + + return; + } + + function collectSiblings(node, name, end_node) { + var siblings = []; + + for (; node && node != end_node; node = node[name]) + siblings.push(node); + + return siblings; + }; + + function findEndPoint(node, root) { + do { + if (node.parentNode == root) + return node; + + node = node.parentNode; + } while(node); + }; + + function walkBoundary(start_node, end_node, next) { + var siblingName = next ? 'nextSibling' : 'previousSibling'; + + for (node = start_node, parent = node.parentNode; node && node != end_node; node = parent) { + parent = node.parentNode; + siblings = collectSiblings(node == start_node ? node : node[siblingName], siblingName); + + if (siblings.length) { + if (!next) + siblings.reverse(); + + callback(siblings); + } + } + }; + + // If index based start position then resolve it + if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) + startContainer = startContainer.childNodes[startOffset]; + + // If index based end position then resolve it + if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) + endContainer = endContainer.childNodes[Math.min(endOffset - 1, endContainer.childNodes.length - 1)]; + + // Find common ancestor and end points + ancestor = dom.findCommonAncestor(startContainer, endContainer); + + // Same container + if (startContainer == endContainer) + return callback([startContainer]); + + // Process left side + for (node = startContainer; node; node = node.parentNode) { + if (node == endContainer) + return walkBoundary(startContainer, ancestor, true); + + if (node == ancestor) + break; + } + + // Process right side + for (node = endContainer; node; node = node.parentNode) { + if (node == startContainer) + return walkBoundary(endContainer, ancestor); + + if (node == ancestor) + break; + } + + // Find start/end point + startPoint = findEndPoint(startContainer, ancestor) || startContainer; + endPoint = findEndPoint(endContainer, ancestor) || endContainer; + + // Walk left leaf + walkBoundary(startContainer, startPoint, true); + + // Walk the middle from start to end point + siblings = collectSiblings( + startPoint == startContainer ? startPoint : startPoint.nextSibling, + 'nextSibling', + endPoint == endContainer ? endPoint.nextSibling : endPoint + ); + + if (siblings.length) + callback(siblings); + + // Walk right leaf + walkBoundary(endContainer, endPoint); + }; + + /* this.split = function(rng) { + var startContainer = rng.startContainer, + startOffset = rng.startOffset, + endContainer = rng.endContainer, + endOffset = rng.endOffset; + + function splitText(node, offset) { + if (offset == node.nodeValue.length) + node.appendData(INVISIBLE_CHAR); + + node = node.splitText(offset); + + if (node.nodeValue === INVISIBLE_CHAR) + node.nodeValue = ''; + + return node; + }; + + // Handle single text node + if (startContainer == endContainer) { + if (startContainer.nodeType == 3) { + if (startOffset != 0) + startContainer = endContainer = splitText(startContainer, startOffset); + + if (endOffset - startOffset != startContainer.nodeValue.length) + splitText(startContainer, endOffset - startOffset); + } + } else { + // Split startContainer text node if needed + if (startContainer.nodeType == 3 && startOffset != 0) { + startContainer = splitText(startContainer, startOffset); + startOffset = 0; + } + + // Split endContainer text node if needed + if (endContainer.nodeType == 3 && endOffset != endContainer.nodeValue.length) { + endContainer = splitText(endContainer, endOffset).previousSibling; + endOffset = endContainer.nodeValue.length; + } + } + + return { + startContainer : startContainer, + startOffset : startOffset, + endContainer : endContainer, + endOffset : endOffset + }; + }; +*/ + }; + + tinymce.dom.RangeUtils.compareRanges = function(rng1, rng2) { + if (rng1 && rng2) { + // Compare native IE ranges + if (rng1.item || rng1.duplicate) { + // Both are control ranges and the selected element matches + if (rng1.item && rng2.item && rng1.item(0) === rng2.item(0)) + return true; + + // Both are text ranges and the range matches + if (rng1.isEqual && rng2.isEqual && rng2.isEqual(rng1)) + return true; + } else { + // Compare w3c ranges + return rng1.startContainer == rng2.startContainer && rng1.startOffset == rng2.startOffset; + } + } + + return false; + }; +})(tinymce); + +(function(tinymce) { + var Event = tinymce.dom.Event, each = tinymce.each; + + tinymce.create('tinymce.ui.KeyboardNavigation', { + KeyboardNavigation: function(settings, dom) { + var t = this, root = settings.root, items = settings.items, + enableUpDown = settings.enableUpDown, enableLeftRight = settings.enableLeftRight || !settings.enableUpDown, + excludeFromTabOrder = settings.excludeFromTabOrder, + itemFocussed, itemBlurred, rootKeydown, rootFocussed, focussedId; + + dom = dom || tinymce.DOM; + + itemFocussed = function(evt) { + focussedId = evt.target.id; + }; + + itemBlurred = function(evt) { + dom.setAttrib(evt.target.id, 'tabindex', '-1'); + }; + + rootFocussed = function(evt) { + var item = dom.get(focussedId); + dom.setAttrib(item, 'tabindex', '0'); + item.focus(); + }; + + t.focus = function() { + dom.get(focussedId).focus(); + }; + + t.destroy = function() { + each(items, function(item) { + dom.unbind(dom.get(item.id), 'focus', itemFocussed); + dom.unbind(dom.get(item.id), 'blur', itemBlurred); + }); + + dom.unbind(dom.get(root), 'focus', rootFocussed); + dom.unbind(dom.get(root), 'keydown', rootKeydown); + + items = dom = root = t.focus = itemFocussed = itemBlurred = rootKeydown = rootFocussed = null; + t.destroy = function() {}; + }; + + t.moveFocus = function(dir, evt) { + var idx = -1, controls = t.controls, newFocus; + + if (!focussedId) + return; + + each(items, function(item, index) { + if (item.id === focussedId) { + idx = index; + return false; + } + }); + + idx += dir; + if (idx < 0) { + idx = items.length - 1; + } else if (idx >= items.length) { + idx = 0; + } + + newFocus = items[idx]; + dom.setAttrib(focussedId, 'tabindex', '-1'); + dom.setAttrib(newFocus.id, 'tabindex', '0'); + dom.get(newFocus.id).focus(); + + if (settings.actOnFocus) { + settings.onAction(newFocus.id); + } + + if (evt) + Event.cancel(evt); + }; + + rootKeydown = function(evt) { + var DOM_VK_LEFT = 37, DOM_VK_RIGHT = 39, DOM_VK_UP = 38, DOM_VK_DOWN = 40, DOM_VK_ESCAPE = 27, DOM_VK_ENTER = 14, DOM_VK_RETURN = 13, DOM_VK_SPACE = 32; + + switch (evt.keyCode) { + case DOM_VK_LEFT: + if (enableLeftRight) t.moveFocus(-1); + break; + + case DOM_VK_RIGHT: + if (enableLeftRight) t.moveFocus(1); + break; + + case DOM_VK_UP: + if (enableUpDown) t.moveFocus(-1); + break; + + case DOM_VK_DOWN: + if (enableUpDown) t.moveFocus(1); + break; + + case DOM_VK_ESCAPE: + if (settings.onCancel) { + settings.onCancel(); + Event.cancel(evt); + } + break; + + case DOM_VK_ENTER: + case DOM_VK_RETURN: + case DOM_VK_SPACE: + if (settings.onAction) { + settings.onAction(focussedId); + Event.cancel(evt); + } + break; + } + }; + + // Set up state and listeners for each item. + each(items, function(item, idx) { + var tabindex; + + if (!item.id) { + item.id = dom.uniqueId('_mce_item_'); + } + + if (excludeFromTabOrder) { + dom.bind(item.id, 'blur', itemBlurred); + tabindex = '-1'; + } else { + tabindex = (idx === 0 ? '0' : '-1'); + } + + dom.setAttrib(item.id, 'tabindex', tabindex); + dom.bind(dom.get(item.id), 'focus', itemFocussed); + }); + + // Setup initial state for root element. + if (items[0]){ + focussedId = items[0].id; + } + + dom.setAttrib(root, 'tabindex', '-1'); + + // Setup listeners for root element. + dom.bind(dom.get(root), 'focus', rootFocussed); + dom.bind(dom.get(root), 'keydown', rootKeydown); + } + }); +})(tinymce); + +(function(tinymce) { + // Shorten class names + var DOM = tinymce.DOM, is = tinymce.is; + + tinymce.create('tinymce.ui.Control', { + Control : function(id, s, editor) { + this.id = id; + this.settings = s = s || {}; + this.rendered = false; + this.onRender = new tinymce.util.Dispatcher(this); + this.classPrefix = ''; + this.scope = s.scope || this; + this.disabled = 0; + this.active = 0; + this.editor = editor; + }, + + setAriaProperty : function(property, value) { + var element = DOM.get(this.id + '_aria') || DOM.get(this.id); + if (element) { + DOM.setAttrib(element, 'aria-' + property, !!value); + } + }, + + focus : function() { + DOM.get(this.id).focus(); + }, + + setDisabled : function(s) { + if (s != this.disabled) { + this.setAriaProperty('disabled', s); + + this.setState('Disabled', s); + this.setState('Enabled', !s); + this.disabled = s; + } + }, + + isDisabled : function() { + return this.disabled; + }, + + setActive : function(s) { + if (s != this.active) { + this.setState('Active', s); + this.active = s; + this.setAriaProperty('pressed', s); + } + }, + + isActive : function() { + return this.active; + }, + + setState : function(c, s) { + var n = DOM.get(this.id); + + c = this.classPrefix + c; + + if (s) + DOM.addClass(n, c); + else + DOM.removeClass(n, c); + }, + + isRendered : function() { + return this.rendered; + }, + + renderHTML : function() { + }, + + renderTo : function(n) { + DOM.setHTML(n, this.renderHTML()); + }, + + postRender : function() { + var t = this, b; + + // Set pending states + if (is(t.disabled)) { + b = t.disabled; + t.disabled = -1; + t.setDisabled(b); + } + + if (is(t.active)) { + b = t.active; + t.active = -1; + t.setActive(b); + } + }, + + remove : function() { + DOM.remove(this.id); + this.destroy(); + }, + + destroy : function() { + tinymce.dom.Event.clear(this.id); + } + }); +})(tinymce); +tinymce.create('tinymce.ui.Container:tinymce.ui.Control', { + Container : function(id, s, editor) { + this.parent(id, s, editor); + + this.controls = []; + + this.lookup = {}; + }, + + add : function(c) { + this.lookup[c.id] = c; + this.controls.push(c); + + return c; + }, + + get : function(n) { + return this.lookup[n]; + } +}); + + +tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', { + Separator : function(id, s) { + this.parent(id, s); + this.classPrefix = 'mceSeparator'; + this.setDisabled(true); + }, + + renderHTML : function() { + return tinymce.DOM.createHTML('span', {'class' : this.classPrefix, role : 'separator', 'aria-orientation' : 'vertical', tabindex : '-1'}); + } +}); + +(function(tinymce) { + var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk; + + tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', { + MenuItem : function(id, s) { + this.parent(id, s); + this.classPrefix = 'mceMenuItem'; + }, + + setSelected : function(s) { + this.setState('Selected', s); + this.setAriaProperty('checked', !!s); + this.selected = s; + }, + + isSelected : function() { + return this.selected; + }, + + postRender : function() { + var t = this; + + t.parent(); + + // Set pending state + if (is(t.selected)) + t.setSelected(t.selected); + } + }); +})(tinymce); + +(function(tinymce) { + var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk; + + tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', { + Menu : function(id, s) { + var t = this; + + t.parent(id, s); + t.items = {}; + t.collapsed = false; + t.menuCount = 0; + t.onAddItem = new tinymce.util.Dispatcher(this); + }, + + expand : function(d) { + var t = this; + + if (d) { + walk(t, function(o) { + if (o.expand) + o.expand(); + }, 'items', t); + } + + t.collapsed = false; + }, + + collapse : function(d) { + var t = this; + + if (d) { + walk(t, function(o) { + if (o.collapse) + o.collapse(); + }, 'items', t); + } + + t.collapsed = true; + }, + + isCollapsed : function() { + return this.collapsed; + }, + + add : function(o) { + if (!o.settings) + o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o); + + this.onAddItem.dispatch(this, o); + + return this.items[o.id] = o; + }, + + addSeparator : function() { + return this.add({separator : true}); + }, + + addMenu : function(o) { + if (!o.collapse) + o = this.createMenu(o); + + this.menuCount++; + + return this.add(o); + }, + + hasMenus : function() { + return this.menuCount !== 0; + }, + + remove : function(o) { + delete this.items[o.id]; + }, + + removeAll : function() { + var t = this; + + walk(t, function(o) { + if (o.removeAll) + o.removeAll(); + else + o.remove(); + + o.destroy(); + }, 'items', t); + + t.items = {}; + }, + + createMenu : function(o) { + var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o); + + m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem); + + return m; + } + }); +})(tinymce); +(function(tinymce) { + var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element; + + tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', { + DropMenu : function(id, s) { + s = s || {}; + s.container = s.container || DOM.doc.body; + s.offset_x = s.offset_x || 0; + s.offset_y = s.offset_y || 0; + s.vp_offset_x = s.vp_offset_x || 0; + s.vp_offset_y = s.vp_offset_y || 0; + + if (is(s.icons) && !s.icons) + s['class'] += ' mceNoIcons'; + + this.parent(id, s); + this.onShowMenu = new tinymce.util.Dispatcher(this); + this.onHideMenu = new tinymce.util.Dispatcher(this); + this.classPrefix = 'mceMenu'; + }, + + createMenu : function(s) { + var t = this, cs = t.settings, m; + + s.container = s.container || cs.container; + s.parent = t; + s.constrain = s.constrain || cs.constrain; + s['class'] = s['class'] || cs['class']; + s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x; + s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y; + s.keyboard_focus = cs.keyboard_focus; + m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s); + + m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem); + + return m; + }, + + focus : function() { + var t = this; + if (t.keyboardNav) { + t.keyboardNav.focus(); + } + }, + + update : function() { + var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th; + + tw = s.max_width ? Math.min(tb.clientWidth, s.max_width) : tb.clientWidth; + th = s.max_height ? Math.min(tb.clientHeight, s.max_height) : tb.clientHeight; + + if (!DOM.boxModel) + t.element.setStyles({width : tw + 2, height : th + 2}); + else + t.element.setStyles({width : tw, height : th}); + + if (s.max_width) + DOM.setStyle(co, 'width', tw); + + if (s.max_height) { + DOM.setStyle(co, 'height', th); + + if (tb.clientHeight < s.max_height) + DOM.setStyle(co, 'overflow', 'hidden'); + } + }, + + showMenu : function(x, y, px) { + var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb, cp = t.classPrefix; + + t.collapse(1); + + if (t.isMenuVisible) + return; + + if (!t.rendered) { + co = DOM.add(t.settings.container, t.renderNode()); + + each(t.items, function(o) { + o.postRender(); + }); + + t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container}); + } else + co = DOM.get('menu_' + t.id); + + // Move layer out of sight unless it's Opera since it scrolls to top of page due to an bug + if (!tinymce.isOpera) + DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF}); + + DOM.show(co); + t.update(); + + x += s.offset_x || 0; + y += s.offset_y || 0; + vp.w -= 4; + vp.h -= 4; + + // Move inside viewport if not submenu + if (s.constrain) { + w = co.clientWidth - ot; + h = co.clientHeight - ot; + mx = vp.x + vp.w; + my = vp.y + vp.h; + + if ((x + s.vp_offset_x + w) > mx) + x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w); + + if ((y + s.vp_offset_y + h) > my) + y = Math.max(0, (my - s.vp_offset_y) - h); + } + + DOM.setStyles(co, {left : x , top : y}); + t.element.update(); + + t.isMenuVisible = 1; + t.mouseClickFunc = Event.add(co, 'click', function(e) { + var m; + + e = e.target; + + if (e && (e = DOM.getParent(e, 'tr')) && !DOM.hasClass(e, cp + 'ItemSub')) { + m = t.items[e.id]; + + if (m.isDisabled()) + return; + + dm = t; + + while (dm) { + if (dm.hideMenu) + dm.hideMenu(); + + dm = dm.settings.parent; + } + + if (m.settings.onclick) + m.settings.onclick(e); + + return Event.cancel(e); // Cancel to fix onbeforeunload problem + } + }); + + if (t.hasMenus()) { + t.mouseOverFunc = Event.add(co, 'mouseover', function(e) { + var m, r, mi; + + e = e.target; + if (e && (e = DOM.getParent(e, 'tr'))) { + m = t.items[e.id]; + + if (t.lastMenu) + t.lastMenu.collapse(1); + + if (m.isDisabled()) + return; + + if (e && DOM.hasClass(e, cp + 'ItemSub')) { + //p = DOM.getPos(s.container); + r = DOM.getRect(e); + m.showMenu((r.x + r.w - ot), r.y - ot, r.x); + t.lastMenu = m; + DOM.addClass(DOM.get(m.id).firstChild, cp + 'ItemActive'); + } + } + }); + } + + Event.add(co, 'keydown', t._keyHandler, t); + + t.onShowMenu.dispatch(t); + + if (s.keyboard_focus) { + t._setupKeyboardNav(); + } + }, + + hideMenu : function(c) { + var t = this, co = DOM.get('menu_' + t.id), e; + + if (!t.isMenuVisible) + return; + + if (t.keyboardNav) t.keyboardNav.destroy(); + Event.remove(co, 'mouseover', t.mouseOverFunc); + Event.remove(co, 'click', t.mouseClickFunc); + Event.remove(co, 'keydown', t._keyHandler); + DOM.hide(co); + t.isMenuVisible = 0; + + if (!c) + t.collapse(1); + + if (t.element) + t.element.hide(); + + if (e = DOM.get(t.id)) + DOM.removeClass(e.firstChild, t.classPrefix + 'ItemActive'); + + t.onHideMenu.dispatch(t); + }, + + add : function(o) { + var t = this, co; + + o = t.parent(o); + + if (t.isRendered && (co = DOM.get('menu_' + t.id))) + t._add(DOM.select('tbody', co)[0], o); + + return o; + }, + + collapse : function(d) { + this.parent(d); + this.hideMenu(1); + }, + + remove : function(o) { + DOM.remove(o.id); + this.destroy(); + + return this.parent(o); + }, + + destroy : function() { + var t = this, co = DOM.get('menu_' + t.id); + + if (t.keyboardNav) t.keyboardNav.destroy(); + Event.remove(co, 'mouseover', t.mouseOverFunc); + Event.remove(DOM.select('a', co), 'focus', t.mouseOverFunc); + Event.remove(co, 'click', t.mouseClickFunc); + Event.remove(co, 'keydown', t._keyHandler); + + if (t.element) + t.element.remove(); + + DOM.remove(co); + }, + + renderNode : function() { + var t = this, s = t.settings, n, tb, co, w; + + w = DOM.create('div', {role: 'listbox', id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:200000;outline:0'}); + if (t.settings.parent) { + DOM.setAttrib(w, 'aria-parent', 'menu_' + t.settings.parent.id); + } + co = DOM.add(w, 'div', {role: 'presentation', id : 'menu_' + t.id + '_co', 'class' : t.classPrefix + (s['class'] ? ' ' + s['class'] : '')}); + t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container}); + + if (s.menu_line) + DOM.add(co, 'span', {'class' : t.classPrefix + 'Line'}); + +// n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'}); + n = DOM.add(co, 'table', {role: 'presentation', id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0}); + tb = DOM.add(n, 'tbody'); + + each(t.items, function(o) { + t._add(tb, o); + }); + + t.rendered = true; + + return w; + }, + + // Internal functions + _setupKeyboardNav : function(){ + var contextMenu, menuItems, t=this; + contextMenu = DOM.select('#menu_' + t.id)[0]; + menuItems = DOM.select('a[role=option]', 'menu_' + t.id); + menuItems.splice(0,0,contextMenu); + t.keyboardNav = new tinymce.ui.KeyboardNavigation({ + root: 'menu_' + t.id, + items: menuItems, + onCancel: function() { + t.hideMenu(); + }, + enableUpDown: true + }); + contextMenu.focus(); + }, + + _keyHandler : function(evt) { + var t = this, e; + switch (evt.keyCode) { + case 37: // Left + if (t.settings.parent) { + t.hideMenu(); + t.settings.parent.focus(); + Event.cancel(evt); + } + break; + case 39: // Right + if (t.mouseOverFunc) + t.mouseOverFunc(evt); + break; + } + }, + + _add : function(tb, o) { + var n, s = o.settings, a, ro, it, cp = this.classPrefix, ic; + + if (s.separator) { + ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'ItemSeparator'}); + DOM.add(ro, 'td', {'class' : cp + 'ItemSeparator'}); + + if (n = ro.previousSibling) + DOM.addClass(n, 'mceLast'); + + return; + } + + n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'Item ' + cp + 'ItemEnabled'}); + n = it = DOM.add(n, s.titleItem ? 'th' : 'td'); + n = a = DOM.add(n, 'a', {id: o.id + '_aria', role: s.titleItem ? 'presentation' : 'option', href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'}); + + if (s.parent) { + DOM.setAttrib(a, 'aria-haspopup', 'true'); + DOM.setAttrib(a, 'aria-owns', 'menu_' + o.id); + } + + DOM.addClass(it, s['class']); +// n = DOM.add(n, 'span', {'class' : 'item'}); + + ic = DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')}); + + if (s.icon_src) + DOM.add(ic, 'img', {src : s.icon_src}); + + n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title); + + if (o.settings.style) + DOM.setAttrib(n, 'style', o.settings.style); + + if (tb.childNodes.length == 1) + DOM.addClass(ro, 'mceFirst'); + + if ((n = ro.previousSibling) && DOM.hasClass(n, cp + 'ItemSeparator')) + DOM.addClass(ro, 'mceFirst'); + + if (o.collapse) + DOM.addClass(ro, cp + 'ItemSub'); + + if (n = ro.previousSibling) + DOM.removeClass(n, 'mceLast'); + + DOM.addClass(ro, 'mceLast'); + } + }); +})(tinymce); +(function(tinymce) { + var DOM = tinymce.DOM; + + tinymce.create('tinymce.ui.Button:tinymce.ui.Control', { + Button : function(id, s, ed) { + this.parent(id, s, ed); + this.classPrefix = 'mceButton'; + }, + + renderHTML : function() { + var cp = this.classPrefix, s = this.settings, h, l; + + l = DOM.encode(s.label || ''); + h = '<a role="button" id="' + this.id + '" href="javascript:;" class="' + cp + ' ' + cp + 'Enabled ' + s['class'] + (l ? ' ' + cp + 'Labeled' : '') +'" onmousedown="return false;" onclick="return false;" aria-labelledby="' + this.id + '_voice" title="' + DOM.encode(s.title) + '">'; + if (s.image && !(this.editor &&this.editor.forcedHighContrastMode) ) + h += '<img class="mceIcon" src="' + s.image + '" alt="' + DOM.encode(s.title) + '" />' + l; + else + h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : ''); + + h += '<span class="mceVoiceLabel mceIconOnly" style="display: none;" id="' + this.id + '_voice">' + s.title + '</span>'; + h += '</a>'; + return h; + }, + + postRender : function() { + var t = this, s = t.settings; + + tinymce.dom.Event.add(t.id, 'click', function(e) { + if (!t.isDisabled()) + return s.onclick.call(s.scope, e); + }); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher; + + tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', { + ListBox : function(id, s, ed) { + var t = this; + + t.parent(id, s, ed); + + t.items = []; + + t.onChange = new Dispatcher(t); + + t.onPostRender = new Dispatcher(t); + + t.onAdd = new Dispatcher(t); + + t.onRenderMenu = new tinymce.util.Dispatcher(this); + + t.classPrefix = 'mceListBox'; + }, + + select : function(va) { + var t = this, fv, f; + + if (va == undefined) + return t.selectByIndex(-1); + + // Is string or number make function selector + if (va && va.call) + f = va; + else { + f = function(v) { + return v == va; + }; + } + + // Do we need to do something? + if (va != t.selectedValue) { + // Find item + each(t.items, function(o, i) { + if (f(o.value)) { + fv = 1; + t.selectByIndex(i); + return false; + } + }); + + if (!fv) + t.selectByIndex(-1); + } + }, + + selectByIndex : function(idx) { + var t = this, e, o, label; + + if (idx != t.selectedIndex) { + e = DOM.get(t.id + '_text'); + label = DOM.get(t.id + '_voiceDesc'); + o = t.items[idx]; + + if (o) { + t.selectedValue = o.value; + t.selectedIndex = idx; + DOM.setHTML(e, DOM.encode(o.title)); + DOM.setHTML(label, t.settings.title + " - " + o.title); + DOM.removeClass(e, 'mceTitle'); + DOM.setAttrib(t.id, 'aria-valuenow', o.title); + } else { + DOM.setHTML(e, DOM.encode(t.settings.title)); + DOM.setHTML(label, DOM.encode(t.settings.title)); + DOM.addClass(e, 'mceTitle'); + t.selectedValue = t.selectedIndex = null; + DOM.setAttrib(t.id, 'aria-valuenow', t.settings.title); + } + e = 0; + } + }, + + add : function(n, v, o) { + var t = this; + + o = o || {}; + o = tinymce.extend(o, { + title : n, + value : v + }); + + t.items.push(o); + t.onAdd.dispatch(t, o); + }, + + getLength : function() { + return this.items.length; + }, + + renderHTML : function() { + var h = '', t = this, s = t.settings, cp = t.classPrefix; + + h = '<span role="listbox" aria-haspopup="true" aria-labelledby="' + t.id +'_voiceDesc" aria-describedby="' + t.id + '_voiceDesc"><table role="presentation" tabindex="0" id="' + t.id + '" cellpadding="0" cellspacing="0" class="' + cp + ' ' + cp + 'Enabled' + (s['class'] ? (' ' + s['class']) : '') + '"><tbody><tr>'; + h += '<td>' + DOM.createHTML('span', {id: t.id + '_voiceDesc', 'class': 'voiceLabel', style:'display:none;'}, t.settings.title); + h += DOM.createHTML('a', {id : t.id + '_text', tabindex : -1, href : 'javascript:;', 'class' : 'mceText', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + '</td>'; + h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', tabindex : -1, href : 'javascript:;', 'class' : 'mceOpen', onclick : "return false;", onmousedown : 'return false;'}, '<span><span style="display:none;" class="mceIconOnly" aria-hidden="true">\u25BC</span></span>') + '</td>'; + h += '</tr></tbody></table></span>'; + + return h; + }, + + showMenu : function() { + var t = this, p2, e = DOM.get(this.id), m; + + if (t.isDisabled() || t.items.length == 0) + return; + + if (t.menu && t.menu.isMenuVisible) + return t.hideMenu(); + + if (!t.isMenuRendered) { + t.renderMenu(); + t.isMenuRendered = true; + } + + p2 = DOM.getPos(e); + + m = t.menu; + m.settings.offset_x = p2.x; + m.settings.offset_y = p2.y; + m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus + + // Select in menu + if (t.oldID) + m.items[t.oldID].setSelected(0); + + each(t.items, function(o) { + if (o.value === t.selectedValue) { + m.items[o.id].setSelected(1); + t.oldID = o.id; + } + }); + + m.showMenu(0, e.clientHeight); + + Event.add(DOM.doc, 'mousedown', t.hideMenu, t); + DOM.addClass(t.id, t.classPrefix + 'Selected'); + + //DOM.get(t.id + '_text').focus(); + }, + + hideMenu : function(e) { + var t = this; + + if (t.menu && t.menu.isMenuVisible) { + DOM.removeClass(t.id, t.classPrefix + 'Selected'); + + // Prevent double toogles by canceling the mouse click event to the button + if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open')) + return; + + if (!e || !DOM.getParent(e.target, '.mceMenu')) { + DOM.removeClass(t.id, t.classPrefix + 'Selected'); + Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); + t.menu.hideMenu(); + } + } + }, + + renderMenu : function() { + var t = this, m; + + m = t.settings.control_manager.createDropMenu(t.id + '_menu', { + menu_line : 1, + 'class' : t.classPrefix + 'Menu mceNoIcons', + max_width : 150, + max_height : 150 + }); + + m.onHideMenu.add(function() { + t.hideMenu(); + t.focus(); + }); + + m.add({ + title : t.settings.title, + 'class' : 'mceMenuItemTitle', + onclick : function() { + if (t.settings.onselect('') !== false) + t.select(''); // Must be runned after + } + }); + + each(t.items, function(o) { + // No value then treat it as a title + if (o.value === undefined) { + m.add({ + title : o.title, + role : "option", + 'class' : 'mceMenuItemTitle', + onclick : function() { + if (t.settings.onselect('') !== false) + t.select(''); // Must be runned after + } + }); + } else { + o.id = DOM.uniqueId(); + o.role= "option"; + o.onclick = function() { + if (t.settings.onselect(o.value) !== false) + t.select(o.value); // Must be runned after + }; + + m.add(o); + } + }); + + t.onRenderMenu.dispatch(t, m); + t.menu = m; + }, + + postRender : function() { + var t = this, cp = t.classPrefix; + + Event.add(t.id, 'click', t.showMenu, t); + Event.add(t.id, 'keydown', function(evt) { + if (evt.keyCode == 32) { // Space + t.showMenu(evt); + Event.cancel(evt); + } + }); + Event.add(t.id, 'focus', function() { + if (!t._focused) { + t.keyDownHandler = Event.add(t.id, 'keydown', function(e) { + if (e.keyCode == 40) { + t.showMenu(); + Event.cancel(e); + } + }); + t.keyPressHandler = Event.add(t.id, 'keypress', function(e) { + var v; + if (e.keyCode == 13) { + // Fake select on enter + v = t.selectedValue; + t.selectedValue = null; // Needs to be null to fake change + Event.cancel(e); + t.settings.onselect(v); + } + }); + } + + t._focused = 1; + }); + Event.add(t.id, 'blur', function() { + Event.remove(t.id, 'keydown', t.keyDownHandler); + Event.remove(t.id, 'keypress', t.keyPressHandler); + t._focused = 0; + }); + + // Old IE doesn't have hover on all elements + if (tinymce.isIE6 || !DOM.boxModel) { + Event.add(t.id, 'mouseover', function() { + if (!DOM.hasClass(t.id, cp + 'Disabled')) + DOM.addClass(t.id, cp + 'Hover'); + }); + + Event.add(t.id, 'mouseout', function() { + if (!DOM.hasClass(t.id, cp + 'Disabled')) + DOM.removeClass(t.id, cp + 'Hover'); + }); + } + + t.onPostRender.dispatch(t, DOM.get(t.id)); + }, + + destroy : function() { + this.parent(); + + Event.clear(this.id + '_text'); + Event.clear(this.id + '_open'); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher; + + tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', { + NativeListBox : function(id, s) { + this.parent(id, s); + this.classPrefix = 'mceNativeListBox'; + }, + + setDisabled : function(s) { + DOM.get(this.id).disabled = s; + this.setAriaProperty('disabled', s); + }, + + isDisabled : function() { + return DOM.get(this.id).disabled; + }, + + select : function(va) { + var t = this, fv, f; + + if (va == undefined) + return t.selectByIndex(-1); + + // Is string or number make function selector + if (va && va.call) + f = va; + else { + f = function(v) { + return v == va; + }; + } + + // Do we need to do something? + if (va != t.selectedValue) { + // Find item + each(t.items, function(o, i) { + if (f(o.value)) { + fv = 1; + t.selectByIndex(i); + return false; + } + }); + + if (!fv) + t.selectByIndex(-1); + } + }, + + selectByIndex : function(idx) { + DOM.get(this.id).selectedIndex = idx + 1; + this.selectedValue = this.items[idx] ? this.items[idx].value : null; + }, + + add : function(n, v, a) { + var o, t = this; + + a = a || {}; + a.value = v; + + if (t.isRendered()) + DOM.add(DOM.get(this.id), 'option', a, n); + + o = { + title : n, + value : v, + attribs : a + }; + + t.items.push(o); + t.onAdd.dispatch(t, o); + }, + + getLength : function() { + return this.items.length; + }, + + renderHTML : function() { + var h, t = this; + + h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --'); + + each(t.items, function(it) { + h += DOM.createHTML('option', {value : it.value}, it.title); + }); + + h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox', 'aria-labelledby': t.id + '_aria'}, h); + h += DOM.createHTML('span', {id : t.id + '_aria', 'style': 'display: none'}, t.settings.title); + return h; + }, + + postRender : function() { + var t = this, ch, changeListenerAdded = true; + + t.rendered = true; + + function onChange(e) { + var v = t.items[e.target.selectedIndex - 1]; + + if (v && (v = v.value)) { + t.onChange.dispatch(t, v); + + if (t.settings.onselect) + t.settings.onselect(v); + } + }; + + Event.add(t.id, 'change', onChange); + + // Accessibility keyhandler + Event.add(t.id, 'keydown', function(e) { + var bf; + + Event.remove(t.id, 'change', ch); + changeListenerAdded = false; + + bf = Event.add(t.id, 'blur', function() { + if (changeListenerAdded) return; + changeListenerAdded = true; + Event.add(t.id, 'change', onChange); + Event.remove(t.id, 'blur', bf); + }); + + //prevent default left and right keys on chrome - so that the keyboard navigation is used. + if (tinymce.isWebKit && (e.keyCode==37 ||e.keyCode==39)) { + return Event.prevent(e); + } + + if (e.keyCode == 13 || e.keyCode == 32) { + onChange(e); + return Event.cancel(e); + } + }); + + t.onPostRender.dispatch(t, DOM.get(t.id)); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each; + + tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', { + MenuButton : function(id, s, ed) { + this.parent(id, s, ed); + + this.onRenderMenu = new tinymce.util.Dispatcher(this); + + s.menu_container = s.menu_container || DOM.doc.body; + }, + + showMenu : function() { + var t = this, p1, p2, e = DOM.get(t.id), m; + + if (t.isDisabled()) + return; + + if (!t.isMenuRendered) { + t.renderMenu(); + t.isMenuRendered = true; + } + + if (t.isMenuVisible) + return t.hideMenu(); + + p1 = DOM.getPos(t.settings.menu_container); + p2 = DOM.getPos(e); + + m = t.menu; + m.settings.offset_x = p2.x; + m.settings.offset_y = p2.y; + m.settings.vp_offset_x = p2.x; + m.settings.vp_offset_y = p2.y; + m.settings.keyboard_focus = t._focused; + m.showMenu(0, e.clientHeight); + + Event.add(DOM.doc, 'mousedown', t.hideMenu, t); + t.setState('Selected', 1); + + t.isMenuVisible = 1; + }, + + renderMenu : function() { + var t = this, m; + + m = t.settings.control_manager.createDropMenu(t.id + '_menu', { + menu_line : 1, + 'class' : this.classPrefix + 'Menu', + icons : t.settings.icons + }); + + m.onHideMenu.add(function() { + t.hideMenu(); + t.focus(); + }); + + t.onRenderMenu.dispatch(t, m); + t.menu = m; + }, + + hideMenu : function(e) { + var t = this; + + // Prevent double toogles by canceling the mouse click event to the button + if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';})) + return; + + if (!e || !DOM.getParent(e.target, '.mceMenu')) { + t.setState('Selected', 0); + Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); + if (t.menu) + t.menu.hideMenu(); + } + + t.isMenuVisible = 0; + }, + + postRender : function() { + var t = this, s = t.settings; + + Event.add(t.id, 'click', function() { + if (!t.isDisabled()) { + if (s.onclick) + s.onclick(t.value); + + t.showMenu(); + } + }); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each; + + tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', { + SplitButton : function(id, s, ed) { + this.parent(id, s, ed); + this.classPrefix = 'mceSplitButton'; + }, + + renderHTML : function() { + var h, t = this, s = t.settings, h1; + + h = '<tbody><tr>'; + + if (s.image) + h1 = DOM.createHTML('img ', {src : s.image, role: 'presentation', 'class' : 'mceAction ' + s['class']}); + else + h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, ''); + + h1 += DOM.createHTML('span', {'class': 'mceVoiceLabel mceIconOnly', id: t.id + '_voice', style: 'display:none;'}, s.title); + h += '<td >' + DOM.createHTML('a', {role: 'button', id : t.id + '_action', tabindex: '-1', href : 'javascript:;', 'class' : 'mceAction ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>'; + + h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']}, '<span style="display:none;" class="mceIconOnly" aria-hidden="true">\u25BC</span>'); + h += '<td >' + DOM.createHTML('a', {role: 'button', id : t.id + '_open', tabindex: '-1', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>'; + + h += '</tr></tbody>'; + h = DOM.createHTML('table', { role: 'presentation', 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', title : s.title}, h); + return DOM.createHTML('div', {id : t.id, role: 'button', tabindex: '0', 'aria-labelledby': t.id + '_voice', 'aria-haspopup': 'true'}, h); + }, + + postRender : function() { + var t = this, s = t.settings, activate; + + if (s.onclick) { + activate = function(evt) { + if (!t.isDisabled()) { + s.onclick(t.value); + Event.cancel(evt); + } + }; + Event.add(t.id + '_action', 'click', activate); + Event.add(t.id, ['click', 'keydown'], function(evt) { + var DOM_VK_SPACE = 32, DOM_VK_ENTER = 14, DOM_VK_RETURN = 13, DOM_VK_UP = 38, DOM_VK_DOWN = 40; + if ((evt.keyCode === 32 || evt.keyCode === 13 || evt.keyCode === 14) && !evt.altKey && !evt.ctrlKey && !evt.metaKey) { + activate(); + Event.cancel(evt); + } else if (evt.type === 'click' || evt.keyCode === DOM_VK_DOWN) { + t.showMenu(); + Event.cancel(evt); + } + }); + } + + Event.add(t.id + '_open', 'click', function (evt) { + t.showMenu(); + Event.cancel(evt); + }); + Event.add([t.id, t.id + '_open'], 'focus', function() {t._focused = 1;}); + Event.add([t.id, t.id + '_open'], 'blur', function() {t._focused = 0;}); + + // Old IE doesn't have hover on all elements + if (tinymce.isIE6 || !DOM.boxModel) { + Event.add(t.id, 'mouseover', function() { + if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled')) + DOM.addClass(t.id, 'mceSplitButtonHover'); + }); + + Event.add(t.id, 'mouseout', function() { + if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled')) + DOM.removeClass(t.id, 'mceSplitButtonHover'); + }); + } + }, + + destroy : function() { + this.parent(); + + Event.clear(this.id + '_action'); + Event.clear(this.id + '_open'); + Event.clear(this.id); + } + }); +})(tinymce); + +(function(tinymce) { + var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each; + + tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', { + ColorSplitButton : function(id, s, ed) { + var t = this; + + t.parent(id, s, ed); + + t.settings = s = tinymce.extend({ + colors : '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF', + grid_width : 8, + default_color : '#888888' + }, t.settings); + + t.onShowMenu = new tinymce.util.Dispatcher(t); + + t.onHideMenu = new tinymce.util.Dispatcher(t); + + t.value = s.default_color; + }, + + showMenu : function() { + var t = this, r, p, e, p2; + + if (t.isDisabled()) + return; + + if (!t.isMenuRendered) { + t.renderMenu(); + t.isMenuRendered = true; + } + + if (t.isMenuVisible) + return t.hideMenu(); + + e = DOM.get(t.id); + DOM.show(t.id + '_menu'); + DOM.addClass(e, 'mceSplitButtonSelected'); + p2 = DOM.getPos(e); + DOM.setStyles(t.id + '_menu', { + left : p2.x, + top : p2.y + e.clientHeight, + zIndex : 200000 + }); + e = 0; + + Event.add(DOM.doc, 'mousedown', t.hideMenu, t); + t.onShowMenu.dispatch(t); + + if (t._focused) { + t._keyHandler = Event.add(t.id + '_menu', 'keydown', function(e) { + if (e.keyCode == 27) + t.hideMenu(); + }); + + DOM.select('a', t.id + '_menu')[0].focus(); // Select first link + } + + t.isMenuVisible = 1; + }, + + hideMenu : function(e) { + var t = this; + + if (t.isMenuVisible) { + // Prevent double toogles by canceling the mouse click event to the button + if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';})) + return; + + if (!e || !DOM.getParent(e.target, '.mceSplitButtonMenu')) { + DOM.removeClass(t.id, 'mceSplitButtonSelected'); + Event.remove(DOM.doc, 'mousedown', t.hideMenu, t); + Event.remove(t.id + '_menu', 'keydown', t._keyHandler); + DOM.hide(t.id + '_menu'); + } + + t.isMenuVisible = 0; + t.onHideMenu.dispatch(); + } + }, + + renderMenu : function() { + var t = this, m, i = 0, s = t.settings, n, tb, tr, w, context; + + w = DOM.add(s.menu_container, 'div', {role: 'listbox', id : t.id + '_menu', 'class' : s['menu_class'] + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'}); + m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'}); + DOM.add(m, 'span', {'class' : 'mceMenuLine'}); + + n = DOM.add(m, 'table', {role: 'presentation', 'class' : 'mceColorSplitMenu'}); + tb = DOM.add(n, 'tbody'); + + // Generate color grid + i = 0; + each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) { + c = c.replace(/^#/, ''); + + if (!i--) { + tr = DOM.add(tb, 'tr'); + i = s.grid_width - 1; + } + + n = DOM.add(tr, 'td'); + n = DOM.add(n, 'a', { + role : 'option', + href : 'javascript:;', + style : { + backgroundColor : '#' + c + }, + 'title': t.editor.getLang('colors.' + c, c), + 'data-mce-color' : '#' + c + }); + + if (t.editor.forcedHighContrastMode) { + n = DOM.add(n, 'canvas', { width: 16, height: 16, 'aria-hidden': 'true' }); + if (n.getContext && (context = n.getContext("2d"))) { + context.fillStyle = '#' + c; + context.fillRect(0, 0, 16, 16); + } else { + // No point leaving a canvas element around if it's not supported for drawing on anyway. + DOM.remove(n); + } + } + }); + + if (s.more_colors_func) { + n = DOM.add(tb, 'tr'); + n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'}); + n = DOM.add(n, 'a', {role: 'option', id : t.id + '_more', href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title); + + Event.add(n, 'click', function(e) { + s.more_colors_func.call(s.more_colors_scope || this); + return Event.cancel(e); // Cancel to fix onbeforeunload problem + }); + } + + DOM.addClass(m, 'mceColorSplitMenu'); + + new tinymce.ui.KeyboardNavigation({ + root: t.id + '_menu', + items: DOM.select('a', t.id + '_menu'), + onCancel: function() { + t.hideMenu(); + t.focus(); + } + }); + + // Prevent IE from scrolling and hindering click to occur #4019 + Event.add(t.id + '_menu', 'mousedown', function(e) {return Event.cancel(e);}); + + Event.add(t.id + '_menu', 'click', function(e) { + var c; + + e = DOM.getParent(e.target, 'a', tb); + + if (e && e.nodeName.toLowerCase() == 'a' && (c = e.getAttribute('data-mce-color'))) + t.setColor(c); + + return Event.cancel(e); // Prevent IE auto save warning + }); + + return w; + }, + + setColor : function(c) { + this.displayColor(c); + this.hideMenu(); + this.settings.onselect(c); + }, + + displayColor : function(c) { + var t = this; + + DOM.setStyle(t.id + '_preview', 'backgroundColor', c); + + t.value = c; + }, + + postRender : function() { + var t = this, id = t.id; + + t.parent(); + DOM.add(id + '_action', 'div', {id : id + '_preview', 'class' : 'mceColorPreview'}); + DOM.setStyle(t.id + '_preview', 'backgroundColor', t.value); + }, + + destroy : function() { + this.parent(); + + Event.clear(this.id + '_menu'); + Event.clear(this.id + '_more'); + DOM.remove(this.id + '_menu'); + } + }); +})(tinymce); + +(function(tinymce) { +// Shorten class names +var dom = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event; +tinymce.create('tinymce.ui.ToolbarGroup:tinymce.ui.Container', { + renderHTML : function() { + var t = this, h = [], controls = t.controls, each = tinymce.each, settings = t.settings; + + h.push('<div id="' + t.id + '" role="group" aria-labelledby="' + t.id + '_voice">'); + //TODO: ACC test this out - adding a role = application for getting the landmarks working well. + h.push("<span role='application'>"); + h.push('<span id="' + t.id + '_voice" class="mceVoiceLabel" style="display:none;">' + dom.encode(settings.name) + '</span>'); + each(controls, function(toolbar) { + h.push(toolbar.renderHTML()); + }); + h.push("</span>"); + h.push('</div>'); + + return h.join(''); + }, + + focus : function() { + var t = this; + dom.get(t.id).focus(); + }, + + postRender : function() { + var t = this, items = []; + + each(t.controls, function(toolbar) { + each (toolbar.controls, function(control) { + if (control.id) { + items.push(control); + } + }); + }); + + t.keyNav = new tinymce.ui.KeyboardNavigation({ + root: t.id, + items: items, + onCancel: function() { + //Move focus if webkit so that navigation back will read the item. + if (tinymce.isWebKit) { + dom.get(t.editor.id+"_ifr").focus(); + } + t.editor.focus(); + }, + excludeFromTabOrder: !t.settings.tab_focus_toolbar + }); + }, + + destroy : function() { + var self = this; + + self.parent(); + self.keyNav.destroy(); + Event.clear(self.id); + } +}); +})(tinymce); + +(function(tinymce) { +// Shorten class names +var dom = tinymce.DOM, each = tinymce.each; +tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', { + renderHTML : function() { + var t = this, h = '', c, co, s = t.settings, i, pr, nx, cl; + + cl = t.controls; + for (i=0; i<cl.length; i++) { + // Get current control, prev control, next control and if the control is a list box or not + co = cl[i]; + pr = cl[i - 1]; + nx = cl[i + 1]; + + // Add toolbar start + if (i === 0) { + c = 'mceToolbarStart'; + + if (co.Button) + c += ' mceToolbarStartButton'; + else if (co.SplitButton) + c += ' mceToolbarStartSplitButton'; + else if (co.ListBox) + c += ' mceToolbarStartListBox'; + + h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->')); + } + + // Add toolbar end before list box and after the previous button + // This is to fix the o2k7 editor skins + if (pr && co.ListBox) { + if (pr.Button || pr.SplitButton) + h += dom.createHTML('td', {'class' : 'mceToolbarEnd'}, dom.createHTML('span', null, '<!-- IE -->')); + } + + // Render control HTML + + // IE 8 quick fix, needed to propertly generate a hit area for anchors + if (dom.stdMode) + h += '<td style="position: relative">' + co.renderHTML() + '</td>'; + else + h += '<td>' + co.renderHTML() + '</td>'; + + // Add toolbar start after list box and before the next button + // This is to fix the o2k7 editor skins + if (nx && co.ListBox) { + if (nx.Button || nx.SplitButton) + h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '<!-- IE -->')); + } + } + + c = 'mceToolbarEnd'; + + if (co.Button) + c += ' mceToolbarEndButton'; + else if (co.SplitButton) + c += ' mceToolbarEndSplitButton'; + else if (co.ListBox) + c += ' mceToolbarEndListBox'; + + h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->')); + + return dom.createHTML('table', {id : t.id, 'class' : 'mceToolbar' + (s['class'] ? ' ' + s['class'] : ''), cellpadding : '0', cellspacing : '0', align : t.settings.align || '', role: 'presentation', tabindex: '-1'}, '<tbody><tr>' + h + '</tr></tbody>'); + } +}); +})(tinymce); + +(function(tinymce) { + var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each; + + tinymce.create('tinymce.AddOnManager', { + AddOnManager : function() { + var self = this; + + self.items = []; + self.urls = {}; + self.lookup = {}; + self.onAdd = new Dispatcher(self); + }, + + get : function(n) { + if (this.lookup[n]) { + return this.lookup[n].instance; + } else { + return undefined; + } + }, + + dependencies : function(n) { + var result; + if (this.lookup[n]) { + result = this.lookup[n].dependencies; + } + return result || []; + }, + + requireLangPack : function(n) { + var s = tinymce.settings; + + if (s && s.language && s.language_load !== false) + tinymce.ScriptLoader.add(this.urls[n] + '/langs/' + s.language + '.js'); + }, + + add : function(id, o, dependencies) { + this.items.push(o); + this.lookup[id] = {instance:o, dependencies:dependencies}; + this.onAdd.dispatch(this, id, o); + + return o; + }, + createUrl: function(baseUrl, dep) { + if (typeof dep === "object") { + return dep + } else { + return {prefix: baseUrl.prefix, resource: dep, suffix: baseUrl.suffix}; + } + }, + + addComponents: function(pluginName, scripts) { + var pluginUrl = this.urls[pluginName]; + tinymce.each(scripts, function(script){ + tinymce.ScriptLoader.add(pluginUrl+"/"+script); + }); + }, + + load : function(n, u, cb, s) { + var t = this, url = u; + + function loadDependencies() { + var dependencies = t.dependencies(n); + tinymce.each(dependencies, function(dep) { + var newUrl = t.createUrl(u, dep); + t.load(newUrl.resource, newUrl, undefined, undefined); + }); + if (cb) { + if (s) { + cb.call(s); + } else { + cb.call(tinymce.ScriptLoader); + } + } + } + + if (t.urls[n]) + return; + if (typeof u === "object") + url = u.prefix + u.resource + u.suffix; + + if (url.indexOf('/') != 0 && url.indexOf('://') == -1) + url = tinymce.baseURL + '/' + url; + + t.urls[n] = url.substring(0, url.lastIndexOf('/')); + + if (t.lookup[n]) { + loadDependencies(); + } else { + tinymce.ScriptLoader.add(url, loadDependencies, s); + } + } + }); + + // Create plugin and theme managers + tinymce.PluginManager = new tinymce.AddOnManager(); + tinymce.ThemeManager = new tinymce.AddOnManager(); +}(tinymce)); + +(function(tinymce) { + // Shorten names + var each = tinymce.each, extend = tinymce.extend, + DOM = tinymce.DOM, Event = tinymce.dom.Event, + ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, + explode = tinymce.explode, + Dispatcher = tinymce.util.Dispatcher, undefined, instanceCounter = 0; + + // Setup some URLs where the editor API is located and where the document is + tinymce.documentBaseURL = window.location.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, ''); + if (!/[\/\\]$/.test(tinymce.documentBaseURL)) + tinymce.documentBaseURL += '/'; + + tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL); + + tinymce.baseURI = new tinymce.util.URI(tinymce.baseURL); + + // Add before unload listener + // This was required since IE was leaking memory if you added and removed beforeunload listeners + // with attachEvent/detatchEvent so this only adds one listener and instances can the attach to the onBeforeUnload event + tinymce.onBeforeUnload = new Dispatcher(tinymce); + + // Must be on window or IE will leak if the editor is placed in frame or iframe + Event.add(window, 'beforeunload', function(e) { + tinymce.onBeforeUnload.dispatch(tinymce, e); + }); + + tinymce.onAddEditor = new Dispatcher(tinymce); + + tinymce.onRemoveEditor = new Dispatcher(tinymce); + + tinymce.EditorManager = extend(tinymce, { + editors : [], + + i18n : {}, + + activeEditor : null, + + init : function(s) { + var t = this, pl, sl = tinymce.ScriptLoader, e, el = [], ed; + + function execCallback(se, n, s) { + var f = se[n]; + + if (!f) + return; + + if (tinymce.is(f, 'string')) { + s = f.replace(/\.\w+$/, ''); + s = s ? tinymce.resolve(s) : 0; + f = tinymce.resolve(f); + } + + return f.apply(s || this, Array.prototype.slice.call(arguments, 2)); + }; + + s = extend({ + theme : "simple", + language : "en" + }, s); + + t.settings = s; + + // Legacy call + Event.add(document, 'init', function() { + var l, co; + + execCallback(s, 'onpageload'); + + switch (s.mode) { + case "exact": + l = s.elements || ''; + + if(l.length > 0) { + each(explode(l), function(v) { + if (DOM.get(v)) { + ed = new tinymce.Editor(v, s); + el.push(ed); + ed.render(1); + } else { + each(document.forms, function(f) { + each(f.elements, function(e) { + if (e.name === v) { + v = 'mce_editor_' + instanceCounter++; + DOM.setAttrib(e, 'id', v); + + ed = new tinymce.Editor(v, s); + el.push(ed); + ed.render(1); + } + }); + }); + } + }); + } + break; + + case "textareas": + case "specific_textareas": + function hasClass(n, c) { + return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c); + }; + + each(DOM.select('textarea'), function(v) { + if (s.editor_deselector && hasClass(v, s.editor_deselector)) + return; + + if (!s.editor_selector || hasClass(v, s.editor_selector)) { + // Can we use the name + e = DOM.get(v.name); + if (!v.id && !e) + v.id = v.name; + + // Generate unique name if missing or already exists + if (!v.id || t.get(v.id)) + v.id = DOM.uniqueId(); + + ed = new tinymce.Editor(v.id, s); + el.push(ed); + ed.render(1); + } + }); + break; + } + + // Call onInit when all editors are initialized + if (s.oninit) { + l = co = 0; + + each(el, function(ed) { + co++; + + if (!ed.initialized) { + // Wait for it + ed.onInit.add(function() { + l++; + + // All done + if (l == co) + execCallback(s, 'oninit'); + }); + } else + l++; + + // All done + if (l == co) + execCallback(s, 'oninit'); + }); + } + }); + }, + + get : function(id) { + if (id === undefined) + return this.editors; + + return this.editors[id]; + }, + + getInstanceById : function(id) { + return this.get(id); + }, + + add : function(editor) { + var self = this, editors = self.editors; + + // Add named and index editor instance + editors[editor.id] = editor; + editors.push(editor); + + self._setActive(editor); + self.onAddEditor.dispatch(self, editor); + + + return editor; + }, + + remove : function(editor) { + var t = this, i, editors = t.editors; + + // Not in the collection + if (!editors[editor.id]) + return null; + + delete editors[editor.id]; + + for (i = 0; i < editors.length; i++) { + if (editors[i] == editor) { + editors.splice(i, 1); + break; + } + } + + // Select another editor since the active one was removed + if (t.activeEditor == editor) + t._setActive(editors[0]); + + editor.destroy(); + t.onRemoveEditor.dispatch(t, editor); + + return editor; + }, + + execCommand : function(c, u, v) { + var t = this, ed = t.get(v), w; + + // Manager commands + switch (c) { + case "mceFocus": + ed.focus(); + return true; + + case "mceAddEditor": + case "mceAddControl": + if (!t.get(v)) + new tinymce.Editor(v, t.settings).render(); + + return true; + + case "mceAddFrameControl": + w = v.window; + + // Add tinyMCE global instance and tinymce namespace to specified window + w.tinyMCE = tinyMCE; + w.tinymce = tinymce; + + tinymce.DOM.doc = w.document; + tinymce.DOM.win = w; + + ed = new tinymce.Editor(v.element_id, v); + ed.render(); + + // Fix IE memory leaks + if (tinymce.isIE) { + function clr() { + ed.destroy(); + w.detachEvent('onunload', clr); + w = w.tinyMCE = w.tinymce = null; // IE leak + }; + + w.attachEvent('onunload', clr); + } + + v.page_window = null; + + return true; + + case "mceRemoveEditor": + case "mceRemoveControl": + if (ed) + ed.remove(); + + return true; + + case 'mceToggleEditor': + if (!ed) { + t.execCommand('mceAddControl', 0, v); + return true; + } + + if (ed.isHidden()) + ed.show(); + else + ed.hide(); + + return true; + } + + // Run command on active editor + if (t.activeEditor) + return t.activeEditor.execCommand(c, u, v); + + return false; + }, + + execInstanceCommand : function(id, c, u, v) { + var ed = this.get(id); + + if (ed) + return ed.execCommand(c, u, v); + + return false; + }, + + triggerSave : function() { + each(this.editors, function(e) { + e.save(); + }); + }, + + addI18n : function(p, o) { + var lo, i18n = this.i18n; + + if (!tinymce.is(p, 'string')) { + each(p, function(o, lc) { + each(o, function(o, g) { + each(o, function(o, k) { + if (g === 'common') + i18n[lc + '.' + k] = o; + else + i18n[lc + '.' + g + '.' + k] = o; + }); + }); + }); + } else { + each(o, function(o, k) { + i18n[p + '.' + k] = o; + }); + } + }, + + // Private methods + + _setActive : function(editor) { + this.selectedInstance = this.activeEditor = editor; + } + }); +})(tinymce); + +(function(tinymce) { + // Shorten these names + var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, + Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isGecko = tinymce.isGecko, + isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, is = tinymce.is, + ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, + inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode; + + tinymce.create('tinymce.Editor', { + Editor : function(id, s) { + var t = this; + + t.id = t.editorId = id; + + t.execCommands = {}; + t.queryStateCommands = {}; + t.queryValueCommands = {}; + + t.isNotDirty = false; + + t.plugins = {}; + + // Add events to the editor + each([ + 'onPreInit', + + 'onBeforeRenderUI', + + 'onPostRender', + + 'onInit', + + 'onRemove', + + 'onActivate', + + 'onDeactivate', + + 'onClick', + + 'onEvent', + + 'onMouseUp', + + 'onMouseDown', + + 'onDblClick', + + 'onKeyDown', + + 'onKeyUp', + + 'onKeyPress', + + 'onContextMenu', + + 'onSubmit', + + 'onReset', + + 'onPaste', + + 'onPreProcess', + + 'onPostProcess', + + 'onBeforeSetContent', + + 'onBeforeGetContent', + + 'onSetContent', + + 'onGetContent', + + 'onLoadContent', + + 'onSaveContent', + + 'onNodeChange', + + 'onChange', + + 'onBeforeExecCommand', + + 'onExecCommand', + + 'onUndo', + + 'onRedo', + + 'onVisualAid', + + 'onSetProgressState' + ], function(e) { + t[e] = new Dispatcher(t); + }); + + t.settings = s = extend({ + id : id, + language : 'en', + docs_language : 'en', + theme : 'simple', + skin : 'default', + delta_width : 0, + delta_height : 0, + popup_css : '', + plugins : '', + document_base_url : tinymce.documentBaseURL, + add_form_submit_trigger : 1, + submit_patch : 1, + add_unload_trigger : 1, + convert_urls : 1, + relative_urls : 1, + remove_script_host : 1, + table_inline_editing : 0, + object_resizing : 1, + cleanup : 1, + accessibility_focus : 1, + custom_shortcuts : 1, + custom_undo_redo_keyboard_shortcuts : 1, + custom_undo_redo_restore_selection : 1, + custom_undo_redo : 1, + doctype : tinymce.isIE6 ? '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">' : '<!DOCTYPE>', // Use old doctype on IE 6 to avoid horizontal scroll + visual_table_class : 'mceItemTable', + visual : 1, + font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large', + apply_source_formatting : 1, + directionality : 'ltr', + forced_root_block : 'p', + hidden_input : 1, + padd_empty_editor : 1, + render_ui : 1, + init_theme : 1, + force_p_newlines : 1, + indentation : '30px', + keep_styles : 1, + fix_table_elements : 1, + inline_styles : 1, + convert_fonts_to_spans : true, + indent : 'simple', + indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr', + indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr', + validate : true, + entity_encoding : 'named', + url_converter : t.convertURL, + url_converter_scope : t, + ie7_compat : true + }, s); + + t.documentBaseURI = new tinymce.util.URI(s.document_base_url || tinymce.documentBaseURL, { + base_uri : tinyMCE.baseURI + }); + + t.baseURI = tinymce.baseURI; + + t.contentCSS = []; + + // Call setup + t.execCallback('setup', t); + }, + + render : function(nst) { + var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader; + + // Page is not loaded yet, wait for it + if (!Event.domLoaded) { + Event.add(document, 'init', function() { + t.render(); + }); + return; + } + + tinyMCE.settings = s; + + // Element not found, then skip initialization + if (!t.getElement()) + return; + + // Is a iPad/iPhone and not on iOS5, then skip initialization. We need to sniff + // here since the browser says it has contentEditable support but there is no visible + // caret We will remove this check ones Apple implements full contentEditable support + if (tinymce.isIDevice && !tinymce.isIOS5) + return; + + // Add hidden input for non input elements inside form elements + if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form')) + DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id); + + if (tinymce.WindowManager) + t.windowManager = new tinymce.WindowManager(t); + + if (s.encoding == 'xml') { + t.onGetContent.add(function(ed, o) { + if (o.save) + o.content = DOM.encode(o.content); + }); + } + + if (s.add_form_submit_trigger) { + t.onSubmit.addToTop(function() { + if (t.initialized) { + t.save(); + t.isNotDirty = 1; + } + }); + } + + if (s.add_unload_trigger) { + t._beforeUnload = tinyMCE.onBeforeUnload.add(function() { + if (t.initialized && !t.destroyed && !t.isHidden()) + t.save({format : 'raw', no_events : true}); + }); + } + + tinymce.addUnload(t.destroy, t); + + if (s.submit_patch) { + t.onBeforeRenderUI.add(function() { + var n = t.getElement().form; + + if (!n) + return; + + // Already patched + if (n._mceOldSubmit) + return; + + // Check page uses id="submit" or name="submit" for it's submit button + if (!n.submit.nodeType && !n.submit.length) { + t.formElement = n; + n._mceOldSubmit = n.submit; + n.submit = function() { + // Save all instances + tinymce.triggerSave(); + t.isNotDirty = 1; + + return t.formElement._mceOldSubmit(t.formElement); + }; + } + + n = null; + }); + } + + // Load scripts + function loadScripts() { + if (s.language && s.language_load !== false) + sl.add(tinymce.baseURL + '/langs/' + s.language + '.js'); + + if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme]) + ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js'); + + each(explode(s.plugins), function(p) { + if (p &&!PluginManager.urls[p]) { + if (p.charAt(0) == '-') { + p = p.substr(1, p.length); + var dependencies = PluginManager.dependencies(p); + each(dependencies, function(dep) { + var defaultSettings = {prefix:'plugins/', resource: dep, suffix:'/editor_plugin' + tinymce.suffix + '.js'}; + var dep = PluginManager.createUrl(defaultSettings, dep); + PluginManager.load(dep.resource, dep); + + }); + } else { + // Skip safari plugin, since it is removed as of 3.3b1 + if (p == 'safari') { + return; + } + PluginManager.load(p, {prefix:'plugins/', resource: p, suffix:'/editor_plugin' + tinymce.suffix + '.js'}); + } + } + }); + + // Init when que is loaded + sl.loadQueue(function() { + if (!t.removed) + t.init(); + }); + }; + + loadScripts(); + }, + + init : function() { + var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti, u, bi, bc, re, i, initializedPlugins = []; + + tinymce.add(t); + + s.aria_label = s.aria_label || DOM.getAttrib(e, 'aria-label', t.getLang('aria.rich_text_area')); + + if (s.theme) { + s.theme = s.theme.replace(/-/, ''); + o = ThemeManager.get(s.theme); + t.theme = new o(); + + if (t.theme.init && s.init_theme) + t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, '')); + } + function initPlugin(p) { + var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po; + if (c && tinymce.inArray(initializedPlugins,p) === -1) { + each(PluginManager.dependencies(p), function(dep){ + initPlugin(dep); + }); + po = new c(t, u); + + t.plugins[p] = po; + + if (po.init) { + po.init(t, u); + initializedPlugins.push(p); + } + } + } + + // Create all plugins + each(explode(s.plugins.replace(/\-/g, '')), initPlugin); + + // Setup popup CSS path(s) + if (s.popup_css !== false) { + if (s.popup_css) + s.popup_css = t.documentBaseURI.toAbsolute(s.popup_css); + else + s.popup_css = t.baseURI.toAbsolute("themes/" + s.theme + "/skins/" + s.skin + "/dialog.css"); + } + + if (s.popup_css_add) + s.popup_css += ',' + t.documentBaseURI.toAbsolute(s.popup_css_add); + + t.controlManager = new tinymce.ControlManager(t); + + if (s.custom_undo_redo) { + t.onBeforeExecCommand.add(function(ed, cmd, ui, val, a) { + if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!a || !a.skip_undo)) + t.undoManager.beforeChange(); + }); + + t.onExecCommand.add(function(ed, cmd, ui, val, a) { + if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!a || !a.skip_undo)) + t.undoManager.add(); + }); + } + + t.onExecCommand.add(function(ed, c) { + // Don't refresh the select lists until caret move + if (!/^(FontName|FontSize)$/.test(c)) + t.nodeChanged(); + }); + + // Remove ghost selections on images and tables in Gecko + if (isGecko) { + function repaint(a, o) { + if (!o || !o.initial) + t.execCommand('mceRepaint'); + }; + + t.onUndo.add(repaint); + t.onRedo.add(repaint); + t.onSetContent.add(repaint); + } + + // Enables users to override the control factory + t.onBeforeRenderUI.dispatch(t, t.controlManager); + + // Measure box + if (s.render_ui) { + w = s.width || e.style.width || e.offsetWidth; + h = s.height || e.style.height || e.offsetHeight; + t.orgDisplay = e.style.display; + re = /^[0-9\.]+(|px)$/i; + + if (re.test('' + w)) + w = Math.max(parseInt(w) + (o.deltaWidth || 0), 100); + + if (re.test('' + h)) + h = Math.max(parseInt(h) + (o.deltaHeight || 0), 100); + + // Render UI + o = t.theme.renderUI({ + targetNode : e, + width : w, + height : h, + deltaWidth : s.delta_width, + deltaHeight : s.delta_height + }); + + t.editorContainer = o.editorContainer; + } + + + // User specified a document.domain value + if (document.domain && location.hostname != document.domain) + tinymce.relaxedDomain = document.domain; + + // Resize editor + DOM.setStyles(o.sizeContainer || o.editorContainer, { + width : w, + height : h + }); + + // Load specified content CSS last + if (s.content_css) { + tinymce.each(explode(s.content_css), function(u) { + t.contentCSS.push(t.documentBaseURI.toAbsolute(u)); + }); + } + + h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : ''); + if (h < 100) + h = 100; + + t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml">'; + + // We only need to override paths if we have to + // IE has a bug where it remove site absolute urls to relative ones if this is specified + if (s.document_base_url != tinymce.documentBaseURL) + t.iframeHTML += '<base href="' + t.documentBaseURI.getURI() + '" />'; + + // IE8 doesn't support carets behind images setting ie7_compat would force IE8+ to run in IE7 compat mode. + if (s.ie7_compat) + t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=7" />'; + else + t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=edge" />'; + + t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />'; + + // Load the CSS by injecting them into the HTML this will reduce "flicker" + for (i = 0; i < t.contentCSS.length; i++) { + t.iframeHTML += '<link type="text/css" rel="stylesheet" href="' + t.contentCSS[i] + '" />'; + } + + bi = s.body_id || 'tinymce'; + if (bi.indexOf('=') != -1) { + bi = t.getParam('body_id', '', 'hash'); + bi = bi[t.id] || bi; + } + + bc = s.body_class || ''; + if (bc.indexOf('=') != -1) { + bc = t.getParam('body_class', '', 'hash'); + bc = bc[t.id] || ''; + } + + t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '"><br></body></html>'; + + // Domain relaxing enabled, then set document domain + if (tinymce.relaxedDomain && (isIE || (tinymce.isOpera && parseFloat(opera.version()) < 11))) { + // We need to write the contents here in IE since multiple writes messes up refresh button and back button + u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";var ed = window.parent.tinyMCE.get("' + t.id + '");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()'; + } + + // Create iframe + // TODO: ACC add the appropriate description on this. + n = DOM.add(o.iframeContainer, 'iframe', { + id : t.id + "_ifr", + src : u || 'javascript:""', // Workaround for HTTPS warning in IE6/7 + frameBorder : '0', + allowTransparency : "true", + title : s.aria_label, + style : { + width : '100%', + height : h, + display : 'block' // Important for Gecko to render the iframe correctly + } + }); + + t.contentAreaContainer = o.iframeContainer; + DOM.get(o.editorContainer).style.display = t.orgDisplay; + DOM.get(t.id).style.display = 'none'; + DOM.setAttrib(t.id, 'aria-hidden', true); + + if (!tinymce.relaxedDomain || !u) + t.setupIframe(); + + e = n = o = null; // Cleanup + }, + + setupIframe : function() { + var t = this, s = t.settings, e = DOM.get(t.id), d = t.getDoc(), h, b; + + // Setup iframe body + if (!isIE || !tinymce.relaxedDomain) { + d.open(); + d.write(t.iframeHTML); + d.close(); + + if (tinymce.relaxedDomain) + d.domain = tinymce.relaxedDomain; + } + + // It will not steal focus while setting contentEditable + b = t.getBody(); + b.disabled = true; + + if (!s.readonly) + b.contentEditable = true; + + b.disabled = false; + + t.schema = new tinymce.html.Schema(s); + + t.dom = new tinymce.dom.DOMUtils(t.getDoc(), { + keep_values : true, + url_converter : t.convertURL, + url_converter_scope : t, + hex_colors : s.force_hex_style_colors, + class_filter : s.class_filter, + update_styles : 1, + fix_ie_paragraphs : 1, + schema : t.schema + }); + + t.parser = new tinymce.html.DomParser(s, t.schema); + + // Force anchor names closed, unless the setting "allow_html_in_named_anchor" is explicitly included. + if (!t.settings.allow_html_in_named_anchor) { + t.parser.addAttributeFilter('name', function(nodes, name) { + var i = nodes.length, sibling, prevSibling, parent, node; + + while (i--) { + node = nodes[i]; + if (node.name === 'a' && node.firstChild) { + parent = node.parent; + + // Move children after current node + sibling = node.lastChild; + do { + prevSibling = sibling.prev; + parent.insert(sibling, node); + sibling = prevSibling; + } while (sibling); + } + } + }); + } + + // Convert src and href into data-mce-src, data-mce-href and data-mce-style + t.parser.addAttributeFilter('src,href,style', function(nodes, name) { + var i = nodes.length, node, dom = t.dom, value, internalName; + + while (i--) { + node = nodes[i]; + value = node.attr(name); + internalName = 'data-mce-' + name; + + // Add internal attribute if we need to we don't on a refresh of the document + if (!node.attributes.map[internalName]) { + if (name === "style") + node.attr(internalName, dom.serializeStyle(dom.parseStyle(value), node.name)); + else + node.attr(internalName, t.convertURL(value, name, node.name)); + } + } + }); + + // Keep scripts from executing + t.parser.addNodeFilter('script', function(nodes, name) { + var i = nodes.length; + + while (i--) + nodes[i].attr('type', 'mce-text/javascript'); + }); + + t.parser.addNodeFilter('#cdata', function(nodes, name) { + var i = nodes.length, node; + + while (i--) { + node = nodes[i]; + node.type = 8; + node.name = '#comment'; + node.value = '[CDATA[' + node.value + ']]'; + } + }); + + t.parser.addNodeFilter('p,h1,h2,h3,h4,h5,h6,div', function(nodes, name) { + var i = nodes.length, node, nonEmptyElements = t.schema.getNonEmptyElements(); + + while (i--) { + node = nodes[i]; + + if (node.isEmpty(nonEmptyElements)) + node.empty().append(new tinymce.html.Node('br', 1)).shortEnded = true; + } + }); + + t.serializer = new tinymce.dom.Serializer(s, t.dom, t.schema); + + t.selection = new tinymce.dom.Selection(t.dom, t.getWin(), t.serializer); + + t.formatter = new tinymce.Formatter(this); + + // Register default formats + t.formatter.register({ + alignleft : [ + {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'left'}}, + {selector : 'img,table', collapsed : false, styles : {'float' : 'left'}} + ], + + aligncenter : [ + {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'center'}}, + {selector : 'img', collapsed : false, styles : {display : 'block', marginLeft : 'auto', marginRight : 'auto'}}, + {selector : 'table', collapsed : false, styles : {marginLeft : 'auto', marginRight : 'auto'}} + ], + + alignright : [ + {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'right'}}, + {selector : 'img,table', collapsed : false, styles : {'float' : 'right'}} + ], + + alignfull : [ + {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'justify'}} + ], + + bold : [ + {inline : 'strong', remove : 'all'}, + {inline : 'span', styles : {fontWeight : 'bold'}}, + {inline : 'b', remove : 'all'} + ], + + italic : [ + {inline : 'em', remove : 'all'}, + {inline : 'span', styles : {fontStyle : 'italic'}}, + {inline : 'i', remove : 'all'} + ], + + underline : [ + {inline : 'span', styles : {textDecoration : 'underline'}, exact : true}, + {inline : 'u', remove : 'all'} + ], + + strikethrough : [ + {inline : 'span', styles : {textDecoration : 'line-through'}, exact : true}, + {inline : 'strike', remove : 'all'} + ], + + forecolor : {inline : 'span', styles : {color : '%value'}, wrap_links : false}, + hilitecolor : {inline : 'span', styles : {backgroundColor : '%value'}, wrap_links : false}, + fontname : {inline : 'span', styles : {fontFamily : '%value'}}, + fontsize : {inline : 'span', styles : {fontSize : '%value'}}, + fontsize_class : {inline : 'span', attributes : {'class' : '%value'}}, + blockquote : {block : 'blockquote', wrapper : 1, remove : 'all'}, + subscript : {inline : 'sub'}, + superscript : {inline : 'sup'}, + + link : {inline : 'a', selector : 'a', remove : 'all', split : true, deep : true, + onmatch : function(node) { + return true; + }, + + onformat : function(elm, fmt, vars) { + each(vars, function(value, key) { + t.dom.setAttrib(elm, key, value); + }); + } + }, + + removeformat : [ + {selector : 'b,strong,em,i,font,u,strike', remove : 'all', split : true, expand : false, block_expand : true, deep : true}, + {selector : 'span', attributes : ['style', 'class'], remove : 'empty', split : true, expand : false, deep : true}, + {selector : '*', attributes : ['style', 'class'], split : false, expand : false, deep : true} + ] + }); + + // Register default block formats + each('p h1 h2 h3 h4 h5 h6 div address pre div code dt dd samp'.split(/\s/), function(name) { + t.formatter.register(name, {block : name, remove : 'all'}); + }); + + // Register user defined formats + t.formatter.register(t.settings.formats); + + t.undoManager = new tinymce.UndoManager(t); + + // Pass through + t.undoManager.onAdd.add(function(um, l) { + if (um.hasUndo()) + return t.onChange.dispatch(t, l, um); + }); + + t.undoManager.onUndo.add(function(um, l) { + return t.onUndo.dispatch(t, l, um); + }); + + t.undoManager.onRedo.add(function(um, l) { + return t.onRedo.dispatch(t, l, um); + }); + + t.forceBlocks = new tinymce.ForceBlocks(t, { + forced_root_block : s.forced_root_block + }); + + t.editorCommands = new tinymce.EditorCommands(t); + + // Pass through + t.serializer.onPreProcess.add(function(se, o) { + return t.onPreProcess.dispatch(t, o, se); + }); + + t.serializer.onPostProcess.add(function(se, o) { + return t.onPostProcess.dispatch(t, o, se); + }); + + t.onPreInit.dispatch(t); + + if (!s.gecko_spellcheck) + t.getBody().spellcheck = 0; + + if (!s.readonly) + t._addEvents(); + + t.controlManager.onPostRender.dispatch(t, t.controlManager); + t.onPostRender.dispatch(t); + + t.quirks = new tinymce.util.Quirks(this); + + if (s.directionality) + t.getBody().dir = s.directionality; + + if (s.nowrap) + t.getBody().style.whiteSpace = "nowrap"; + + if (s.handle_node_change_callback) { + t.onNodeChange.add(function(ed, cm, n) { + t.execCallback('handle_node_change_callback', t.id, n, -1, -1, true, t.selection.isCollapsed()); + }); + } + + if (s.save_callback) { + t.onSaveContent.add(function(ed, o) { + var h = t.execCallback('save_callback', t.id, o.content, t.getBody()); + + if (h) + o.content = h; + }); + } + + if (s.onchange_callback) { + t.onChange.add(function(ed, l) { + t.execCallback('onchange_callback', t, l); + }); + } + + if (s.protect) { + t.onBeforeSetContent.add(function(ed, o) { + if (s.protect) { + each(s.protect, function(pattern) { + o.content = o.content.replace(pattern, function(str) { + return '<!--mce:protected ' + escape(str) + '-->'; + }); + }); + } + }); + } + + if (s.convert_newlines_to_brs) { + t.onBeforeSetContent.add(function(ed, o) { + if (o.initial) + o.content = o.content.replace(/\r?\n/g, '<br />'); + }); + } + + if (s.preformatted) { + t.onPostProcess.add(function(ed, o) { + o.content = o.content.replace(/^\s*<pre.*?>/, ''); + o.content = o.content.replace(/<\/pre>\s*$/, ''); + + if (o.set) + o.content = '<pre class="mceItemHidden">' + o.content + '</pre>'; + }); + } + + if (s.verify_css_classes) { + t.serializer.attribValueFilter = function(n, v) { + var s, cl; + + if (n == 'class') { + // Build regexp for classes + if (!t.classesRE) { + cl = t.dom.getClasses(); + + if (cl.length > 0) { + s = ''; + + each (cl, function(o) { + s += (s ? '|' : '') + o['class']; + }); + + t.classesRE = new RegExp('(' + s + ')', 'gi'); + } + } + + return !t.classesRE || /(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(v) || t.classesRE.test(v) ? v : ''; + } + + return v; + }; + } + + if (s.cleanup_callback) { + t.onBeforeSetContent.add(function(ed, o) { + o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o); + }); + + t.onPreProcess.add(function(ed, o) { + if (o.set) + t.execCallback('cleanup_callback', 'insert_to_editor_dom', o.node, o); + + if (o.get) + t.execCallback('cleanup_callback', 'get_from_editor_dom', o.node, o); + }); + + t.onPostProcess.add(function(ed, o) { + if (o.set) + o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o); + + if (o.get) + o.content = t.execCallback('cleanup_callback', 'get_from_editor', o.content, o); + }); + } + + if (s.save_callback) { + t.onGetContent.add(function(ed, o) { + if (o.save) + o.content = t.execCallback('save_callback', t.id, o.content, t.getBody()); + }); + } + + if (s.handle_event_callback) { + t.onEvent.add(function(ed, e, o) { + if (t.execCallback('handle_event_callback', e, ed, o) === false) + Event.cancel(e); + }); + } + + // Add visual aids when new contents is added + t.onSetContent.add(function() { + t.addVisual(t.getBody()); + }); + + // Remove empty contents + if (s.padd_empty_editor) { + t.onPostProcess.add(function(ed, o) { + o.content = o.content.replace(/^(<p[^>]*>(&nbsp;|&#160;|\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, ''); + }); + } + + if (isGecko) { + // Fix gecko link bug, when a link is placed at the end of block elements there is + // no way to move the caret behind the link. This fix adds a bogus br element after the link + function fixLinks(ed, o) { + each(ed.dom.select('a'), function(n) { + var pn = n.parentNode; + + if (ed.dom.isBlock(pn) && pn.lastChild === n) + ed.dom.add(pn, 'br', {'data-mce-bogus' : 1}); + }); + }; + + t.onExecCommand.add(function(ed, cmd) { + if (cmd === 'CreateLink') + fixLinks(ed); + }); + + t.onSetContent.add(t.selection.onSetContent.add(fixLinks)); + } + + t.load({initial : true, format : 'html'}); + t.startContent = t.getContent({format : 'raw'}); + t.undoManager.add(); + t.initialized = true; + + t.onInit.dispatch(t); + t.execCallback('setupcontent_callback', t.id, t.getBody(), t.getDoc()); + t.execCallback('init_instance_callback', t); + t.focus(true); + t.nodeChanged({initial : 1}); + + // Load specified content CSS last + each(t.contentCSS, function(u) { + t.dom.loadCSS(u); + }); + + // Handle auto focus + if (s.auto_focus) { + setTimeout(function () { + var ed = tinymce.get(s.auto_focus); + + ed.selection.select(ed.getBody(), 1); + ed.selection.collapse(1); + ed.getBody().focus(); + ed.getWin().focus(); + }, 100); + } + + e = null; + }, + + + focus : function(sf) { + var oed, t = this, selection = t.selection, ce = t.settings.content_editable, ieRng, controlElm, doc = t.getDoc(); + + if (!sf) { + // Get selected control element + ieRng = selection.getRng(); + if (ieRng.item) { + controlElm = ieRng.item(0); + } + + t._refreshContentEditable(); + selection.normalize(); + + // Is not content editable + if (!ce) + t.getWin().focus(); + + // Focus the body as well since it's contentEditable + if (tinymce.isGecko) { + t.getBody().focus(); + } + + // Restore selected control element + // This is needed when for example an image is selected within a + // layer a call to focus will then remove the control selection + if (controlElm && controlElm.ownerDocument == doc) { + ieRng = doc.body.createControlRange(); + ieRng.addElement(controlElm); + ieRng.select(); + } + + } + + if (tinymce.activeEditor != t) { + if ((oed = tinymce.activeEditor) != null) + oed.onDeactivate.dispatch(oed, t); + + t.onActivate.dispatch(t, oed); + } + + tinymce._setActive(t); + }, + + execCallback : function(n) { + var t = this, f = t.settings[n], s; + + if (!f) + return; + + // Look through lookup + if (t.callbackLookup && (s = t.callbackLookup[n])) { + f = s.func; + s = s.scope; + } + + if (is(f, 'string')) { + s = f.replace(/\.\w+$/, ''); + s = s ? tinymce.resolve(s) : 0; + f = tinymce.resolve(f); + t.callbackLookup = t.callbackLookup || {}; + t.callbackLookup[n] = {func : f, scope : s}; + } + + return f.apply(s || t, Array.prototype.slice.call(arguments, 1)); + }, + + translate : function(s) { + var c = this.settings.language || 'en', i18n = tinymce.i18n; + + if (!s) + return ''; + + return i18n[c + '.' + s] || s.replace(/{\#([^}]+)\}/g, function(a, b) { + return i18n[c + '.' + b] || '{#' + b + '}'; + }); + }, + + getLang : function(n, dv) { + return tinymce.i18n[(this.settings.language || 'en') + '.' + n] || (is(dv) ? dv : '{#' + n + '}'); + }, + + getParam : function(n, dv, ty) { + var tr = tinymce.trim, v = is(this.settings[n]) ? this.settings[n] : dv, o; + + if (ty === 'hash') { + o = {}; + + if (is(v, 'string')) { + each(v.indexOf('=') > 0 ? v.split(/[;,](?![^=;,]*(?:[;,]|$))/) : v.split(','), function(v) { + v = v.split('='); + + if (v.length > 1) + o[tr(v[0])] = tr(v[1]); + else + o[tr(v[0])] = tr(v); + }); + } else + o = v; + + return o; + } + + return v; + }, + + nodeChanged : function(o) { + var t = this, s = t.selection, n = s.getStart() || t.getBody(); + + // Fix for bug #1896577 it seems that this can not be fired while the editor is loading + if (t.initialized) { + o = o || {}; + n = isIE && n.ownerDocument != t.getDoc() ? t.getBody() : n; // Fix for IE initial state + + // Get parents and add them to object + o.parents = []; + t.dom.getParent(n, function(node) { + if (node.nodeName == 'BODY') + return true; + + o.parents.push(node); + }); + + t.onNodeChange.dispatch( + t, + o ? o.controlManager || t.controlManager : t.controlManager, + n, + s.isCollapsed(), + o + ); + } + }, + + addButton : function(n, s) { + var t = this; + + t.buttons = t.buttons || {}; + t.buttons[n] = s; + }, + + addCommand : function(name, callback, scope) { + this.execCommands[name] = {func : callback, scope : scope || this}; + }, + + addQueryStateHandler : function(name, callback, scope) { + this.queryStateCommands[name] = {func : callback, scope : scope || this}; + }, + + addQueryValueHandler : function(name, callback, scope) { + this.queryValueCommands[name] = {func : callback, scope : scope || this}; + }, + + addShortcut : function(pa, desc, cmd_func, sc) { + var t = this, c; + + if (!t.settings.custom_shortcuts) + return false; + + t.shortcuts = t.shortcuts || {}; + + if (is(cmd_func, 'string')) { + c = cmd_func; + + cmd_func = function() { + t.execCommand(c, false, null); + }; + } + + if (is(cmd_func, 'object')) { + c = cmd_func; + + cmd_func = function() { + t.execCommand(c[0], c[1], c[2]); + }; + } + + each(explode(pa), function(pa) { + var o = { + func : cmd_func, + scope : sc || this, + desc : desc, + alt : false, + ctrl : false, + shift : false + }; + + each(explode(pa, '+'), function(v) { + switch (v) { + case 'alt': + case 'ctrl': + case 'shift': + o[v] = true; + break; + + default: + o.charCode = v.charCodeAt(0); + o.keyCode = v.toUpperCase().charCodeAt(0); + } + }); + + t.shortcuts[(o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode] = o; + }); + + return true; + }, + + execCommand : function(cmd, ui, val, a) { + var t = this, s = 0, o, st; + + if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus)) + t.focus(); + + o = {}; + t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o); + if (o.terminate) + return false; + + // Command callback + if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return true; + } + + // Registred commands + if (o = t.execCommands[cmd]) { + st = o.func.call(o.scope, ui, val); + + // Fall through on true + if (st !== true) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return st; + } + } + + // Plugin commands + each(t.plugins, function(p) { + if (p.execCommand && p.execCommand(cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + s = 1; + return false; + } + }); + + if (s) + return true; + + // Theme commands + if (t.theme && t.theme.execCommand && t.theme.execCommand(cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return true; + } + + // Editor commands + if (t.editorCommands.execCommand(cmd, ui, val)) { + t.onExecCommand.dispatch(t, cmd, ui, val, a); + return true; + } + + // Browser commands + t.getDoc().execCommand(cmd, ui, val); + t.onExecCommand.dispatch(t, cmd, ui, val, a); + }, + + queryCommandState : function(cmd) { + var t = this, o, s; + + // Is hidden then return undefined + if (t._isHidden()) + return; + + // Registred commands + if (o = t.queryStateCommands[cmd]) { + s = o.func.call(o.scope); + + // Fall though on true + if (s !== true) + return s; + } + + // Registred commands + o = t.editorCommands.queryCommandState(cmd); + if (o !== -1) + return o; + + // Browser commands + try { + return this.getDoc().queryCommandState(cmd); + } catch (ex) { + // Fails sometimes see bug: 1896577 + } + }, + + queryCommandValue : function(c) { + var t = this, o, s; + + // Is hidden then return undefined + if (t._isHidden()) + return; + + // Registred commands + if (o = t.queryValueCommands[c]) { + s = o.func.call(o.scope); + + // Fall though on true + if (s !== true) + return s; + } + + // Registred commands + o = t.editorCommands.queryCommandValue(c); + if (is(o)) + return o; + + // Browser commands + try { + return this.getDoc().queryCommandValue(c); + } catch (ex) { + // Fails sometimes see bug: 1896577 + } + }, + + show : function() { + var t = this; + + DOM.show(t.getContainer()); + DOM.hide(t.id); + t.load(); + }, + + hide : function() { + var t = this, d = t.getDoc(); + + // Fixed bug where IE has a blinking cursor left from the editor + if (isIE && d) + d.execCommand('SelectAll'); + + // We must save before we hide so Safari doesn't crash + t.save(); + DOM.hide(t.getContainer()); + DOM.setStyle(t.id, 'display', t.orgDisplay); + }, + + isHidden : function() { + return !DOM.isHidden(this.id); + }, + + setProgressState : function(b, ti, o) { + this.onSetProgressState.dispatch(this, b, ti, o); + + return b; + }, + + load : function(o) { + var t = this, e = t.getElement(), h; + + if (e) { + o = o || {}; + o.load = true; + + // Double encode existing entities in the value + h = t.setContent(is(e.value) ? e.value : e.innerHTML, o); + o.element = e; + + if (!o.no_events) + t.onLoadContent.dispatch(t, o); + + o.element = e = null; + + return h; + } + }, + + save : function(o) { + var t = this, e = t.getElement(), h, f; + + if (!e || !t.initialized) + return; + + o = o || {}; + o.save = true; + + // Add undo level will trigger onchange event + if (!o.no_events) { + t.undoManager.typing = false; + t.undoManager.add(); + } + + o.element = e; + h = o.content = t.getContent(o); + + if (!o.no_events) + t.onSaveContent.dispatch(t, o); + + h = o.content; + + if (!/TEXTAREA|INPUT/i.test(e.nodeName)) { + e.innerHTML = h; + + // Update hidden form element + if (f = DOM.getParent(t.id, 'form')) { + each(f.elements, function(e) { + if (e.name == t.id) { + e.value = h; + return false; + } + }); + } + } else + e.value = h; + + o.element = e = null; + + return h; + }, + + setContent : function(content, args) { + var self = this, rootNode, body = self.getBody(), forcedRootBlockName; + + // Setup args object + args = args || {}; + args.format = args.format || 'html'; + args.set = true; + args.content = content; + + // Do preprocessing + if (!args.no_events) + self.onBeforeSetContent.dispatch(self, args); + + content = args.content; + + // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content + // It will also be impossible to place the caret in the editor unless there is a BR element present + if (!tinymce.isIE && (content.length === 0 || /^\s+$/.test(content))) { + forcedRootBlockName = self.settings.forced_root_block; + if (forcedRootBlockName) + content = '<' + forcedRootBlockName + '><br data-mce-bogus="1"></' + forcedRootBlockName + '>'; + else + content = '<br data-mce-bogus="1">'; + + body.innerHTML = content; + self.selection.select(body, true); + self.selection.collapse(true); + return; + } + + // Parse and serialize the html + if (args.format !== 'raw') { + content = new tinymce.html.Serializer({}, self.schema).serialize( + self.parser.parse(content) + ); + } + + // Set the new cleaned contents to the editor + args.content = tinymce.trim(content); + self.dom.setHTML(body, args.content); + + // Do post processing + if (!args.no_events) + self.onSetContent.dispatch(self, args); + + self.selection.normalize(); + + return args.content; + }, + + getContent : function(args) { + var self = this, content; + + // Setup args object + args = args || {}; + args.format = args.format || 'html'; + args.get = true; + + // Do preprocessing + if (!args.no_events) + self.onBeforeGetContent.dispatch(self, args); + + // Get raw contents or by default the cleaned contents + if (args.format == 'raw') + content = self.getBody().innerHTML; + else + content = self.serializer.serialize(self.getBody(), args); + + args.content = tinymce.trim(content); + + // Do post processing + if (!args.no_events) + self.onGetContent.dispatch(self, args); + + return args.content; + }, + + isDirty : function() { + var self = this; + + return tinymce.trim(self.startContent) != tinymce.trim(self.getContent({format : 'raw', no_events : 1})) && !self.isNotDirty; + }, + + getContainer : function() { + var t = this; + + if (!t.container) + t.container = DOM.get(t.editorContainer || t.id + '_parent'); + + return t.container; + }, + + getContentAreaContainer : function() { + return this.contentAreaContainer; + }, + + getElement : function() { + return DOM.get(this.settings.content_element || this.id); + }, + + getWin : function() { + var t = this, e; + + if (!t.contentWindow) { + e = DOM.get(t.id + "_ifr"); + + if (e) + t.contentWindow = e.contentWindow; + } + + return t.contentWindow; + }, + + getDoc : function() { + var t = this, w; + + if (!t.contentDocument) { + w = t.getWin(); + + if (w) + t.contentDocument = w.document; + } + + return t.contentDocument; + }, + + getBody : function() { + return this.bodyElement || this.getDoc().body; + }, + + convertURL : function(u, n, e) { + var t = this, s = t.settings; + + // Use callback instead + if (s.urlconverter_callback) + return t.execCallback('urlconverter_callback', u, e, true, n); + + // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs + if (!s.convert_urls || (e && e.nodeName == 'LINK') || u.indexOf('file:') === 0) + return u; + + // Convert to relative + if (s.relative_urls) + return t.documentBaseURI.toRelative(u); + + // Convert to absolute + u = t.documentBaseURI.toAbsolute(u, s.remove_script_host); + + return u; + }, + + addVisual : function(e) { + var t = this, s = t.settings; + + e = e || t.getBody(); + + if (!is(t.hasVisual)) + t.hasVisual = s.visual; + + each(t.dom.select('table,a', e), function(e) { + var v; + + switch (e.nodeName) { + case 'TABLE': + v = t.dom.getAttrib(e, 'border'); + + if (!v || v == '0') { + if (t.hasVisual) + t.dom.addClass(e, s.visual_table_class); + else + t.dom.removeClass(e, s.visual_table_class); + } + + return; + + case 'A': + v = t.dom.getAttrib(e, 'name'); + + if (v) { + if (t.hasVisual) + t.dom.addClass(e, 'mceItemAnchor'); + else + t.dom.removeClass(e, 'mceItemAnchor'); + } + + return; + } + }); + + t.onVisualAid.dispatch(t, e, t.hasVisual); + }, + + remove : function() { + var t = this, e = t.getContainer(); + + t.removed = 1; // Cancels post remove event execution + t.hide(); + + t.execCallback('remove_instance_callback', t); + t.onRemove.dispatch(t); + + // Clear all execCommand listeners this is required to avoid errors if the editor was removed inside another command + t.onExecCommand.listeners = []; + + tinymce.remove(t); + DOM.remove(e); + }, + + destroy : function(s) { + var t = this; + + // One time is enough + if (t.destroyed) + return; + + if (!s) { + tinymce.removeUnload(t.destroy); + tinyMCE.onBeforeUnload.remove(t._beforeUnload); + + // Manual destroy + if (t.theme && t.theme.destroy) + t.theme.destroy(); + + // Destroy controls, selection and dom + t.controlManager.destroy(); + t.selection.destroy(); + t.dom.destroy(); + + // Remove all events + + // Don't clear the window or document if content editable + // is enabled since other instances might still be present + if (!t.settings.content_editable) { + Event.clear(t.getWin()); + Event.clear(t.getDoc()); + } + + Event.clear(t.getBody()); + Event.clear(t.formElement); + } + + if (t.formElement) { + t.formElement.submit = t.formElement._mceOldSubmit; + t.formElement._mceOldSubmit = null; + } + + t.contentAreaContainer = t.formElement = t.container = t.settings.content_element = t.bodyElement = t.contentDocument = t.contentWindow = null; + + if (t.selection) + t.selection = t.selection.win = t.selection.dom = t.selection.dom.doc = null; + + t.destroyed = 1; + }, + + // Internal functions + + _addEvents : function() { + // 'focus', 'blur', 'dblclick', 'beforedeactivate', submit, reset + var t = this, i, s = t.settings, dom = t.dom, lo = { + mouseup : 'onMouseUp', + mousedown : 'onMouseDown', + click : 'onClick', + keyup : 'onKeyUp', + keydown : 'onKeyDown', + keypress : 'onKeyPress', + submit : 'onSubmit', + reset : 'onReset', + contextmenu : 'onContextMenu', + dblclick : 'onDblClick', + paste : 'onPaste' // Doesn't work in all browsers yet + }; + + function eventHandler(e, o) { + var ty = e.type; + + // Don't fire events when it's removed + if (t.removed) + return; + + // Generic event handler + if (t.onEvent.dispatch(t, e, o) !== false) { + // Specific event handler + t[lo[e.fakeType || e.type]].dispatch(t, e, o); + } + }; + + // Add DOM events + each(lo, function(v, k) { + switch (k) { + case 'contextmenu': + dom.bind(t.getDoc(), k, eventHandler); + break; + + case 'paste': + dom.bind(t.getBody(), k, function(e) { + eventHandler(e); + }); + break; + + case 'submit': + case 'reset': + dom.bind(t.getElement().form || DOM.getParent(t.id, 'form'), k, eventHandler); + break; + + default: + dom.bind(s.content_editable ? t.getBody() : t.getDoc(), k, eventHandler); + } + }); + + dom.bind(s.content_editable ? t.getBody() : (isGecko ? t.getDoc() : t.getWin()), 'focus', function(e) { + t.focus(true); + }); + + + // Fixes bug where a specified document_base_uri could result in broken images + // This will also fix drag drop of images in Gecko + if (tinymce.isGecko) { + dom.bind(t.getDoc(), 'DOMNodeInserted', function(e) { + var v; + + e = e.target; + + if (e.nodeType === 1 && e.nodeName === 'IMG' && (v = e.getAttribute('data-mce-src'))) + e.src = t.documentBaseURI.toAbsolute(v); + }); + } + + // Set various midas options in Gecko + if (isGecko) { + function setOpts() { + var t = this, d = t.getDoc(), s = t.settings; + + if (isGecko && !s.readonly) { + t._refreshContentEditable(); + + try { + // Try new Gecko method + d.execCommand("styleWithCSS", 0, false); + } catch (ex) { + // Use old method + if (!t._isHidden()) + try {d.execCommand("useCSS", 0, true);} catch (ex) {} + } + + if (!s.table_inline_editing) + try {d.execCommand('enableInlineTableEditing', false, false);} catch (ex) {} + + if (!s.object_resizing) + try {d.execCommand('enableObjectResizing', false, false);} catch (ex) {} + } + }; + + t.onBeforeExecCommand.add(setOpts); + t.onMouseDown.add(setOpts); + } + + // Add node change handlers + t.onMouseUp.add(t.nodeChanged); + //t.onClick.add(t.nodeChanged); + t.onKeyUp.add(function(ed, e) { + var c = e.keyCode; + + if ((c >= 33 && c <= 36) || (c >= 37 && c <= 40) || c == 13 || c == 45 || c == 46 || c == 8 || (tinymce.isMac && (c == 91 || c == 93)) || e.ctrlKey) + t.nodeChanged(); + }); + + + // Add block quote deletion handler + t.onKeyDown.add(function(ed, e) { + // Was the BACKSPACE key pressed? + if (e.keyCode != 8) + return; + + var n = ed.selection.getRng().startContainer; + var offset = ed.selection.getRng().startOffset; + + while (n && n.nodeType && n.nodeType != 1 && n.parentNode) + n = n.parentNode; + + // Is the cursor at the beginning of a blockquote? + if (n && n.parentNode && n.parentNode.tagName === 'BLOCKQUOTE' && n.parentNode.firstChild == n && offset == 0) { + // Remove the blockquote + ed.formatter.toggle('blockquote', null, n.parentNode); + + // Move the caret to the beginning of n + var rng = ed.selection.getRng(); + rng.setStart(n, 0); + rng.setEnd(n, 0); + ed.selection.setRng(rng); + ed.selection.collapse(false); + } + }); + + + + // Add reset handler + t.onReset.add(function() { + t.setContent(t.startContent, {format : 'raw'}); + }); + + // Add shortcuts + if (s.custom_shortcuts) { + if (s.custom_undo_redo_keyboard_shortcuts) { + t.addShortcut('ctrl+z', t.getLang('undo_desc'), 'Undo'); + t.addShortcut('ctrl+y', t.getLang('redo_desc'), 'Redo'); + } + + // Add default shortcuts for gecko + t.addShortcut('ctrl+b', t.getLang('bold_desc'), 'Bold'); + t.addShortcut('ctrl+i', t.getLang('italic_desc'), 'Italic'); + t.addShortcut('ctrl+u', t.getLang('underline_desc'), 'Underline'); + + // BlockFormat shortcuts keys + for (i=1; i<=6; i++) + t.addShortcut('ctrl+' + i, '', ['FormatBlock', false, 'h' + i]); + + t.addShortcut('ctrl+7', '', ['FormatBlock', false, 'p']); + t.addShortcut('ctrl+8', '', ['FormatBlock', false, 'div']); + t.addShortcut('ctrl+9', '', ['FormatBlock', false, 'address']); + + function find(e) { + var v = null; + + if (!e.altKey && !e.ctrlKey && !e.metaKey) + return v; + + each(t.shortcuts, function(o) { + if (tinymce.isMac && o.ctrl != e.metaKey) + return; + else if (!tinymce.isMac && o.ctrl != e.ctrlKey) + return; + + if (o.alt != e.altKey) + return; + + if (o.shift != e.shiftKey) + return; + + if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) { + v = o; + return false; + } + }); + + return v; + }; + + t.onKeyUp.add(function(ed, e) { + var o = find(e); + + if (o) + return Event.cancel(e); + }); + + t.onKeyPress.add(function(ed, e) { + var o = find(e); + + if (o) + return Event.cancel(e); + }); + + t.onKeyDown.add(function(ed, e) { + var o = find(e); + + if (o) { + o.func.call(o.scope); + return Event.cancel(e); + } + }); + } + + if (tinymce.isIE) { + // Fix so resize will only update the width and height attributes not the styles of an image + // It will also block mceItemNoResize items + dom.bind(t.getDoc(), 'controlselect', function(e) { + var re = t.resizeInfo, cb; + + e = e.target; + + // Don't do this action for non image elements + if (e.nodeName !== 'IMG') + return; + + if (re) + dom.unbind(re.node, re.ev, re.cb); + + if (!dom.hasClass(e, 'mceItemNoResize')) { + ev = 'resizeend'; + cb = dom.bind(e, ev, function(e) { + var v; + + e = e.target; + + if (v = dom.getStyle(e, 'width')) { + dom.setAttrib(e, 'width', v.replace(/[^0-9%]+/g, '')); + dom.setStyle(e, 'width', ''); + } + + if (v = dom.getStyle(e, 'height')) { + dom.setAttrib(e, 'height', v.replace(/[^0-9%]+/g, '')); + dom.setStyle(e, 'height', ''); + } + }); + } else { + ev = 'resizestart'; + cb = dom.bind(e, 'resizestart', Event.cancel, Event); + } + + re = t.resizeInfo = { + node : e, + ev : ev, + cb : cb + }; + }); + } + + if (tinymce.isOpera) { + t.onClick.add(function(ed, e) { + Event.prevent(e); + }); + } + + // Add custom undo/redo handlers + if (s.custom_undo_redo) { + function addUndo() { + t.undoManager.typing = false; + t.undoManager.add(); + }; + + dom.bind(t.getDoc(), 'focusout', function(e) { + if (!t.removed && t.undoManager.typing) + addUndo(); + }); + + // Add undo level when contents is drag/dropped within the editor + t.dom.bind(t.dom.getRoot(), 'dragend', function(e) { + addUndo(); + }); + + t.onKeyUp.add(function(ed, e) { + var keyCode = e.keyCode; + + if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 13 || keyCode == 45 || e.ctrlKey) + addUndo(); + }); + + t.onKeyDown.add(function(ed, e) { + var keyCode = e.keyCode, sel; + + if (keyCode == 8) { + sel = t.getDoc().selection; + + // Fix IE control + backspace browser bug + if (sel && sel.createRange && sel.createRange().item) { + t.undoManager.beforeChange(); + ed.dom.remove(sel.createRange().item(0)); + addUndo(); + + return Event.cancel(e); + } + } + + // Is caracter positon keys left,right,up,down,home,end,pgdown,pgup,enter + if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 13 || keyCode == 45) { + // Add position before enter key is pressed, used by IE since it still uses the default browser behavior + // Todo: Remove this once we normalize enter behavior on IE + if (tinymce.isIE && keyCode == 13) + t.undoManager.beforeChange(); + + if (t.undoManager.typing) + addUndo(); + + return; + } + + // If key isn't shift,ctrl,alt,capslock,metakey + if ((keyCode < 16 || keyCode > 20) && keyCode != 224 && keyCode != 91 && !t.undoManager.typing) { + t.undoManager.beforeChange(); + t.undoManager.typing = true; + t.undoManager.add(); + } + }); + + t.onMouseDown.add(function() { + if (t.undoManager.typing) + addUndo(); + }); + } + + // Fire a nodeChanged when the selection is changed on WebKit this fixes selection issues on iOS5 + // It only fires the nodeChange event every 50ms since it would other wise update the UI when you type and it hogs the CPU + if (tinymce.isWebKit) { + dom.bind(t.getDoc(), 'selectionchange', function() { + if (t.selectionTimer) { + clearTimeout(t.selectionTimer); + t.selectionTimer = 0; + } + + t.selectionTimer = window.setTimeout(function() { + t.nodeChanged(); + }, 50); + }); + } + + // Bug fix for FireFox keeping styles from end of selection instead of start. + if (tinymce.isGecko) { + function getAttributeApplyFunction() { + var template = t.dom.getAttribs(t.selection.getStart().cloneNode(false)); + + return function() { + var target = t.selection.getStart(); + + if (target !== t.getBody()) { + t.dom.removeAllAttribs(target); + + each(template, function(attr) { + target.setAttributeNode(attr.cloneNode(true)); + }); + } + }; + } + + function isSelectionAcrossElements() { + var s = t.selection; + + return !s.isCollapsed() && s.getStart() != s.getEnd(); + } + + t.onKeyPress.add(function(ed, e) { + var applyAttributes; + + if ((e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) { + applyAttributes = getAttributeApplyFunction(); + t.getDoc().execCommand('delete', false, null); + applyAttributes(); + + return Event.cancel(e); + } + }); + + t.dom.bind(t.getDoc(), 'cut', function(e) { + var applyAttributes; + + if (isSelectionAcrossElements()) { + applyAttributes = getAttributeApplyFunction(); + t.onKeyUp.addToTop(Event.cancel, Event); + + setTimeout(function() { + applyAttributes(); + t.onKeyUp.remove(Event.cancel, Event); + }, 0); + } + }); + } + }, + + _refreshContentEditable : function() { + var self = this, body, parent; + + // Check if the editor was hidden and the re-initalize contentEditable mode by removing and adding the body again + if (self._isHidden()) { + body = self.getBody(); + parent = body.parentNode; + + parent.removeChild(body); + parent.appendChild(body); + + body.focus(); + } + }, + + _isHidden : function() { + var s; + + if (!isGecko) + return 0; + + // Weird, wheres that cursor selection? + s = this.selection.getSel(); + return (!s || !s.rangeCount || s.rangeCount == 0); + } + }); +})(tinymce); + +(function(tinymce) { + // Added for compression purposes + var each = tinymce.each, undefined, TRUE = true, FALSE = false; + + tinymce.EditorCommands = function(editor) { + var dom = editor.dom, + selection = editor.selection, + commands = {state: {}, exec : {}, value : {}}, + settings = editor.settings, + formatter = editor.formatter, + bookmark; + + function execCommand(command, ui, value) { + var func; + + command = command.toLowerCase(); + if (func = commands.exec[command]) { + func(command, ui, value); + return TRUE; + } + + return FALSE; + }; + + function queryCommandState(command) { + var func; + + command = command.toLowerCase(); + if (func = commands.state[command]) + return func(command); + + return -1; + }; + + function queryCommandValue(command) { + var func; + + command = command.toLowerCase(); + if (func = commands.value[command]) + return func(command); + + return FALSE; + }; + + function addCommands(command_list, type) { + type = type || 'exec'; + + each(command_list, function(callback, command) { + each(command.toLowerCase().split(','), function(command) { + commands[type][command] = callback; + }); + }); + }; + + // Expose public methods + tinymce.extend(this, { + execCommand : execCommand, + queryCommandState : queryCommandState, + queryCommandValue : queryCommandValue, + addCommands : addCommands + }); + + // Private methods + + function execNativeCommand(command, ui, value) { + if (ui === undefined) + ui = FALSE; + + if (value === undefined) + value = null; + + return editor.getDoc().execCommand(command, ui, value); + }; + + function isFormatMatch(name) { + return formatter.match(name); + }; + + function toggleFormat(name, value) { + formatter.toggle(name, value ? {value : value} : undefined); + }; + + function storeSelection(type) { + bookmark = selection.getBookmark(type); + }; + + function restoreSelection() { + selection.moveToBookmark(bookmark); + }; + + // Add execCommand overrides + addCommands({ + // Ignore these, added for compatibility + 'mceResetDesignMode,mceBeginUndoLevel' : function() {}, + + // Add undo manager logic + 'mceEndUndoLevel,mceAddUndoLevel' : function() { + editor.undoManager.add(); + }, + + 'Cut,Copy,Paste' : function(command) { + var doc = editor.getDoc(), failed; + + // Try executing the native command + try { + execNativeCommand(command); + } catch (ex) { + // Command failed + failed = TRUE; + } + + // Present alert message about clipboard access not being available + if (failed || !doc.queryCommandSupported(command)) { + if (tinymce.isGecko) { + editor.windowManager.confirm(editor.getLang('clipboard_msg'), function(state) { + if (state) + open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', '_blank'); + }); + } else + editor.windowManager.alert(editor.getLang('clipboard_no_support')); + } + }, + + // Override unlink command + unlink : function(command) { + if (selection.isCollapsed()) + selection.select(selection.getNode()); + + execNativeCommand(command); + selection.collapse(FALSE); + }, + + // Override justify commands to use the text formatter engine + 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) { + var align = command.substring(7); + + // Remove all other alignments first + each('left,center,right,full'.split(','), function(name) { + if (align != name) + formatter.remove('align' + name); + }); + + toggleFormat('align' + align); + execCommand('mceRepaint'); + }, + + // Override list commands to fix WebKit bug + 'InsertUnorderedList,InsertOrderedList' : function(command) { + var listElm, listParent; + + execNativeCommand(command); + + // WebKit produces lists within block elements so we need to split them + // we will replace the native list creation logic to custom logic later on + // TODO: Remove this when the list creation logic is removed + listElm = dom.getParent(selection.getNode(), 'ol,ul'); + if (listElm) { + listParent = listElm.parentNode; + + // If list is within a text block then split that block + if (/^(H[1-6]|P|ADDRESS|PRE)$/.test(listParent.nodeName)) { + storeSelection(); + dom.split(listParent, listElm); + restoreSelection(); + } + } + }, + + // Override commands to use the text formatter engine + 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript' : function(command) { + toggleFormat(command); + }, + + // Override commands to use the text formatter engine + 'ForeColor,HiliteColor,FontName' : function(command, ui, value) { + toggleFormat(command, value); + }, + + FontSize : function(command, ui, value) { + var fontClasses, fontSizes; + + // Convert font size 1-7 to styles + if (value >= 1 && value <= 7) { + fontSizes = tinymce.explode(settings.font_size_style_values); + fontClasses = tinymce.explode(settings.font_size_classes); + + if (fontClasses) + value = fontClasses[value - 1] || value; + else + value = fontSizes[value - 1] || value; + } + + toggleFormat(command, value); + }, + + RemoveFormat : function(command) { + formatter.remove(command); + }, + + mceBlockQuote : function(command) { + toggleFormat('blockquote'); + }, + + FormatBlock : function(command, ui, value) { + return toggleFormat(value || 'p'); + }, + + mceCleanup : function() { + var bookmark = selection.getBookmark(); + + editor.setContent(editor.getContent({cleanup : TRUE}), {cleanup : TRUE}); + + selection.moveToBookmark(bookmark); + }, + + mceRemoveNode : function(command, ui, value) { + var node = value || selection.getNode(); + + // Make sure that the body node isn't removed + if (node != editor.getBody()) { + storeSelection(); + editor.dom.remove(node, TRUE); + restoreSelection(); + } + }, + + mceSelectNodeDepth : function(command, ui, value) { + var counter = 0; + + dom.getParent(selection.getNode(), function(node) { + if (node.nodeType == 1 && counter++ == value) { + selection.select(node); + return FALSE; + } + }, editor.getBody()); + }, + + mceSelectNode : function(command, ui, value) { + selection.select(value); + }, + + mceInsertContent : function(command, ui, value) { + var parser, serializer, parentNode, rootNode, fragment, args, + marker, nodeRect, viewPortRect, rng, node, node2, bookmarkHtml, viewportBodyElement; + + // Setup parser and serializer + parser = editor.parser; + serializer = new tinymce.html.Serializer({}, editor.schema); + bookmarkHtml = '<span id="mce_marker" data-mce-type="bookmark">\uFEFF</span>'; + + // Run beforeSetContent handlers on the HTML to be inserted + args = {content: value, format: 'html'}; + selection.onBeforeSetContent.dispatch(selection, args); + value = args.content; + + // Add caret at end of contents if it's missing + if (value.indexOf('{$caret}') == -1) + value += '{$caret}'; + + // Replace the caret marker with a span bookmark element + value = value.replace(/\{\$caret\}/, bookmarkHtml); + + // Insert node maker where we will insert the new HTML and get it's parent + if (!selection.isCollapsed()) + editor.getDoc().execCommand('Delete', false, null); + + parentNode = selection.getNode(); + + // Parse the fragment within the context of the parent node + args = {context : parentNode.nodeName.toLowerCase()}; + fragment = parser.parse(value, args); + + // Move the caret to a more suitable location + node = fragment.lastChild; + if (node.attr('id') == 'mce_marker') { + marker = node; + + for (node = node.prev; node; node = node.walk(true)) { + if (node.type == 3 || !dom.isBlock(node.name)) { + node.parent.insert(marker, node, node.name === 'br'); + break; + } + } + } + + // If parser says valid we can insert the contents into that parent + if (!args.invalid) { + value = serializer.serialize(fragment); + + // Check if parent is empty or only has one BR element then set the innerHTML of that parent + node = parentNode.firstChild; + node2 = parentNode.lastChild; + if (!node || (node === node2 && node.nodeName === 'BR')) + dom.setHTML(parentNode, value); + else + selection.setContent(value); + } else { + // If the fragment was invalid within that context then we need + // to parse and process the parent it's inserted into + + // Insert bookmark node and get the parent + selection.setContent(bookmarkHtml); + parentNode = editor.selection.getNode(); + rootNode = editor.getBody(); + + // Opera will return the document node when selection is in root + if (parentNode.nodeType == 9) + parentNode = node = rootNode; + else + node = parentNode; + + // Find the ancestor just before the root element + while (node !== rootNode) { + parentNode = node; + node = node.parentNode; + } + + // Get the outer/inner HTML depending on if we are in the root and parser and serialize that + value = parentNode == rootNode ? rootNode.innerHTML : dom.getOuterHTML(parentNode); + value = serializer.serialize( + parser.parse( + // Need to replace by using a function since $ in the contents would otherwise be a problem + value.replace(/<span (id="mce_marker"|id=mce_marker).+?<\/span>/i, function() { + return serializer.serialize(fragment); + }) + ) + ); + + // Set the inner/outer HTML depending on if we are in the root or not + if (parentNode == rootNode) + dom.setHTML(rootNode, value); + else + dom.setOuterHTML(parentNode, value); + } + + marker = dom.get('mce_marker'); + + // Scroll range into view scrollIntoView on element can't be used since it will scroll the main view port as well + nodeRect = dom.getRect(marker); + viewPortRect = dom.getViewPort(editor.getWin()); + + // Check if node is out side the viewport if it is then scroll to it + if ((nodeRect.y + nodeRect.h > viewPortRect.y + viewPortRect.h || nodeRect.y < viewPortRect.y) || + (nodeRect.x > viewPortRect.x + viewPortRect.w || nodeRect.x < viewPortRect.x)) { + viewportBodyElement = tinymce.isIE ? editor.getDoc().documentElement : editor.getBody(); + viewportBodyElement.scrollLeft = nodeRect.x; + viewportBodyElement.scrollTop = nodeRect.y - viewPortRect.h + 25; + } + + // Move selection before marker and remove it + rng = dom.createRng(); + + // If previous sibling is a text node set the selection to the end of that node + node = marker.previousSibling; + if (node && node.nodeType == 3) { + rng.setStart(node, node.nodeValue.length); + } else { + // If the previous sibling isn't a text node or doesn't exist set the selection before the marker node + rng.setStartBefore(marker); + rng.setEndBefore(marker); + } + + // Remove the marker node and set the new range + dom.remove(marker); + selection.setRng(rng); + + // Dispatch after event and add any visual elements needed + selection.onSetContent.dispatch(selection, args); + editor.addVisual(); + }, + + mceInsertRawHTML : function(command, ui, value) { + selection.setContent('tiny_mce_marker'); + editor.setContent(editor.getContent().replace(/tiny_mce_marker/g, function() { return value })); + }, + + mceSetContent : function(command, ui, value) { + editor.setContent(value); + }, + + 'Indent,Outdent' : function(command) { + var intentValue, indentUnit, value; + + // Setup indent level + intentValue = settings.indentation; + indentUnit = /[a-z%]+$/i.exec(intentValue); + intentValue = parseInt(intentValue); + + if (!queryCommandState('InsertUnorderedList') && !queryCommandState('InsertOrderedList')) { + each(selection.getSelectedBlocks(), function(element) { + if (command == 'outdent') { + value = Math.max(0, parseInt(element.style.paddingLeft || 0) - intentValue); + dom.setStyle(element, 'paddingLeft', value ? value + indentUnit : ''); + } else + dom.setStyle(element, 'paddingLeft', (parseInt(element.style.paddingLeft || 0) + intentValue) + indentUnit); + }); + } else + execNativeCommand(command); + }, + + mceRepaint : function() { + var bookmark; + + if (tinymce.isGecko) { + try { + storeSelection(TRUE); + + if (selection.getSel()) + selection.getSel().selectAllChildren(editor.getBody()); + + selection.collapse(TRUE); + restoreSelection(); + } catch (ex) { + // Ignore + } + } + }, + + mceToggleFormat : function(command, ui, value) { + formatter.toggle(value); + }, + + InsertHorizontalRule : function() { + editor.execCommand('mceInsertContent', false, '<hr />'); + }, + + mceToggleVisualAid : function() { + editor.hasVisual = !editor.hasVisual; + editor.addVisual(); + }, + + mceReplaceContent : function(command, ui, value) { + editor.execCommand('mceInsertContent', false, value.replace(/\{\$selection\}/g, selection.getContent({format : 'text'}))); + }, + + mceInsertLink : function(command, ui, value) { + var anchor; + + if (typeof(value) == 'string') + value = {href : value}; + + anchor = dom.getParent(selection.getNode(), 'a'); + + // Spaces are never valid in URLs and it's a very common mistake for people to make so we fix it here. + value.href = value.href.replace(' ', '%20'); + + // Remove existing links if there could be child links or that the href isn't specified + if (!anchor || !value.href) { + formatter.remove('link'); + } + + // Apply new link to selection + if (value.href) { + formatter.apply('link', value, anchor); + } + }, + + selectAll : function() { + var root = dom.getRoot(), rng = dom.createRng(); + + rng.setStart(root, 0); + rng.setEnd(root, root.childNodes.length); + + editor.selection.setRng(rng); + } + }); + + // Add queryCommandState overrides + addCommands({ + // Override justify commands + 'JustifyLeft,JustifyCenter,JustifyRight,JustifyFull' : function(command) { + return isFormatMatch('align' + command.substring(7)); + }, + + 'Bold,Italic,Underline,Strikethrough,Superscript,Subscript' : function(command) { + return isFormatMatch(command); + }, + + mceBlockQuote : function() { + return isFormatMatch('blockquote'); + }, + + Outdent : function() { + var node; + + if (settings.inline_styles) { + if ((node = dom.getParent(selection.getStart(), dom.isBlock)) && parseInt(node.style.paddingLeft) > 0) + return TRUE; + + if ((node = dom.getParent(selection.getEnd(), dom.isBlock)) && parseInt(node.style.paddingLeft) > 0) + return TRUE; + } + + return queryCommandState('InsertUnorderedList') || queryCommandState('InsertOrderedList') || (!settings.inline_styles && !!dom.getParent(selection.getNode(), 'BLOCKQUOTE')); + }, + + 'InsertUnorderedList,InsertOrderedList' : function(command) { + return dom.getParent(selection.getNode(), command == 'insertunorderedlist' ? 'UL' : 'OL'); + } + }, 'state'); + + // Add queryCommandValue overrides + addCommands({ + 'FontSize,FontName' : function(command) { + var value = 0, parent; + + if (parent = dom.getParent(selection.getNode(), 'span')) { + if (command == 'fontsize') + value = parent.style.fontSize; + else + value = parent.style.fontFamily.replace(/, /g, ',').replace(/[\'\"]/g, '').toLowerCase(); + } + + return value; + } + }, 'value'); + + // Add undo manager logic + if (settings.custom_undo_redo) { + addCommands({ + Undo : function() { + editor.undoManager.undo(); + }, + + Redo : function() { + editor.undoManager.redo(); + } + }); + } + }; +})(tinymce); + +(function(tinymce) { + var Dispatcher = tinymce.util.Dispatcher; + + tinymce.UndoManager = function(editor) { + var self, index = 0, data = [], beforeBookmark; + + function getContent() { + return tinymce.trim(editor.getContent({format : 'raw', no_events : 1})); + }; + + return self = { + typing : false, + + onAdd : new Dispatcher(self), + + onUndo : new Dispatcher(self), + + onRedo : new Dispatcher(self), + + beforeChange : function() { + beforeBookmark = editor.selection.getBookmark(2, true); + }, + + add : function(level) { + var i, settings = editor.settings, lastLevel; + + level = level || {}; + level.content = getContent(); + + // Add undo level if needed + lastLevel = data[index]; + if (lastLevel && lastLevel.content == level.content) + return null; + + // Set before bookmark on previous level + if (data[index]) + data[index].beforeBookmark = beforeBookmark; + + // Time to compress + if (settings.custom_undo_redo_levels) { + if (data.length > settings.custom_undo_redo_levels) { + for (i = 0; i < data.length - 1; i++) + data[i] = data[i + 1]; + + data.length--; + index = data.length; + } + } + + // Get a non intrusive normalized bookmark + level.bookmark = editor.selection.getBookmark(2, true); + + // Crop array if needed + if (index < data.length - 1) + data.length = index + 1; + + data.push(level); + index = data.length - 1; + + self.onAdd.dispatch(self, level); + editor.isNotDirty = 0; + + return level; + }, + + undo : function() { + var level, i; + + if (self.typing) { + self.add(); + self.typing = false; + } + + if (index > 0) { + level = data[--index]; + + editor.setContent(level.content, {format : 'raw'}); + editor.selection.moveToBookmark(level.beforeBookmark); + + self.onUndo.dispatch(self, level); + } + + return level; + }, + + redo : function() { + var level; + + if (index < data.length - 1) { + level = data[++index]; + + editor.setContent(level.content, {format : 'raw'}); + editor.selection.moveToBookmark(level.bookmark); + + self.onRedo.dispatch(self, level); + } + + return level; + }, + + clear : function() { + data = []; + index = 0; + self.typing = false; + }, + + hasUndo : function() { + return index > 0 || this.typing; + }, + + hasRedo : function() { + return index < data.length - 1 && !this.typing; + } + }; + }; +})(tinymce); + +(function(tinymce) { + // Shorten names + var Event = tinymce.dom.Event, + isIE = tinymce.isIE, + isGecko = tinymce.isGecko, + isOpera = tinymce.isOpera, + each = tinymce.each, + extend = tinymce.extend, + TRUE = true, + FALSE = false; + + function cloneFormats(node) { + var clone, temp, inner; + + do { + if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) { + if (clone) { + temp = node.cloneNode(false); + temp.appendChild(clone); + clone = temp; + } else { + clone = inner = node.cloneNode(false); + } + + clone.removeAttribute('id'); + } + } while (node = node.parentNode); + + if (clone) + return {wrapper : clone, inner : inner}; + }; + + // Checks if the selection/caret is at the end of the specified block element + function isAtEnd(rng, par) { + var rng2 = par.ownerDocument.createRange(); + + rng2.setStart(rng.endContainer, rng.endOffset); + rng2.setEndAfter(par); + + // Get number of characters to the right of the cursor if it's zero then we are at the end and need to merge the next block element + return rng2.cloneContents().textContent.length == 0; + }; + + function splitList(selection, dom, li) { + var listBlock, block; + + if (dom.isEmpty(li)) { + listBlock = dom.getParent(li, 'ul,ol'); + + if (!dom.getParent(listBlock.parentNode, 'ul,ol')) { + dom.split(listBlock, li); + block = dom.create('p', 0, '<br data-mce-bogus="1" />'); + dom.replace(block, li); + selection.select(block, 1); + } + + return FALSE; + } + + return TRUE; + }; + + tinymce.create('tinymce.ForceBlocks', { + ForceBlocks : function(ed) { + var t = this, s = ed.settings, elm; + + t.editor = ed; + t.dom = ed.dom; + elm = (s.forced_root_block || 'p').toLowerCase(); + s.element = elm.toUpperCase(); + + ed.onPreInit.add(t.setup, t); + }, + + setup : function() { + var t = this, ed = t.editor, s = ed.settings, dom = ed.dom, selection = ed.selection, blockElements = ed.schema.getBlockElements(); + + // Force root blocks + if (s.forced_root_block) { + function addRootBlocks() { + var node = selection.getStart(), rootNode = ed.getBody(), rng, startContainer, startOffset, endContainer, endOffset, rootBlockNode, tempNode, offset = -0xFFFFFF; + + if (!node || node.nodeType !== 1) + return; + + // Check if node is wrapped in block + while (node != rootNode) { + if (blockElements[node.nodeName]) + return; + + node = node.parentNode; + } + + // Get current selection + rng = selection.getRng(); + if (rng.setStart) { + startContainer = rng.startContainer; + startOffset = rng.startOffset; + endContainer = rng.endContainer; + endOffset = rng.endOffset; + } else { + // Force control range into text range + if (rng.item) { + rng = ed.getDoc().body.createTextRange(); + rng.moveToElementText(rng.item(0)); + } + + tmpRng = rng.duplicate(); + tmpRng.collapse(true); + startOffset = tmpRng.move('character', offset) * -1; + + if (!tmpRng.collapsed) { + tmpRng = rng.duplicate(); + tmpRng.collapse(false); + endOffset = (tmpRng.move('character', offset) * -1) - startOffset; + } + } + + // Wrap non block elements and text nodes + for (node = rootNode.firstChild; node; node) { + if (node.nodeType === 3 || (node.nodeType == 1 && !blockElements[node.nodeName])) { + if (!rootBlockNode) { + rootBlockNode = dom.create(s.forced_root_block); + node.parentNode.insertBefore(rootBlockNode, node); + } + + tempNode = node; + node = node.nextSibling; + rootBlockNode.appendChild(tempNode); + } else { + rootBlockNode = null; + node = node.nextSibling; + } + } + + if (rng.setStart) { + rng.setStart(startContainer, startOffset); + rng.setEnd(endContainer, endOffset); + selection.setRng(rng); + } else { + try { + rng = ed.getDoc().body.createTextRange(); + rng.moveToElementText(rootNode); + rng.collapse(true); + rng.moveStart('character', startOffset); + + if (endOffset > 0) + rng.moveEnd('character', endOffset); + + rng.select(); + } catch (ex) { + // Ignore + } + } + + ed.nodeChanged(); + }; + + ed.onKeyUp.add(addRootBlocks); + ed.onClick.add(addRootBlocks); + } + + if (s.force_br_newlines) { + // Force IE to produce BRs on enter + if (isIE) { + ed.onKeyPress.add(function(ed, e) { + var n; + + if (e.keyCode == 13 && selection.getNode().nodeName != 'LI') { + selection.setContent('<br id="__" /> ', {format : 'raw'}); + n = dom.get('__'); + n.removeAttribute('id'); + selection.select(n); + selection.collapse(); + return Event.cancel(e); + } + }); + } + } + + if (s.force_p_newlines) { + if (!isIE) { + ed.onKeyPress.add(function(ed, e) { + if (e.keyCode == 13 && !e.shiftKey && !t.insertPara(e)) + Event.cancel(e); + }); + } else { + // Ungly hack to for IE to preserve the formatting when you press + // enter at the end of a block element with formatted contents + // This logic overrides the browsers default logic with + // custom logic that enables us to control the output + tinymce.addUnload(function() { + t._previousFormats = 0; // Fix IE leak + }); + + ed.onKeyPress.add(function(ed, e) { + t._previousFormats = 0; + + // Clone the current formats, this will later be applied to the new block contents + if (e.keyCode == 13 && !e.shiftKey && ed.selection.isCollapsed() && s.keep_styles) + t._previousFormats = cloneFormats(ed.selection.getStart()); + }); + + ed.onKeyUp.add(function(ed, e) { + // Let IE break the element and the wrap the new caret location in the previous formats + if (e.keyCode == 13 && !e.shiftKey) { + var parent = ed.selection.getStart(), fmt = t._previousFormats; + + // Parent is an empty block + if (!parent.hasChildNodes() && fmt) { + parent = dom.getParent(parent, dom.isBlock); + + if (parent && parent.nodeName != 'LI') { + parent.innerHTML = ''; + + if (t._previousFormats) { + parent.appendChild(fmt.wrapper); + fmt.inner.innerHTML = '\uFEFF'; + } else + parent.innerHTML = '\uFEFF'; + + selection.select(parent, 1); + selection.collapse(true); + ed.getDoc().execCommand('Delete', false, null); + t._previousFormats = 0; + } + } + } + }); + } + + if (isGecko) { + ed.onKeyDown.add(function(ed, e) { + if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) + t.backspaceDelete(e, e.keyCode == 8); + }); + } + } + + // Workaround for missing shift+enter support, http://bugs.webkit.org/show_bug.cgi?id=16973 + if (tinymce.isWebKit) { + function insertBr(ed) { + var rng = selection.getRng(), br, div = dom.create('div', null, ' '), divYPos, vpHeight = dom.getViewPort(ed.getWin()).h; + + // Insert BR element + rng.insertNode(br = dom.create('br')); + + // Place caret after BR + rng.setStartAfter(br); + rng.setEndAfter(br); + selection.setRng(rng); + + // Could not place caret after BR then insert an nbsp entity and move the caret + if (selection.getSel().focusNode == br.previousSibling) { + selection.select(dom.insertAfter(dom.doc.createTextNode('\u00a0'), br)); + selection.collapse(TRUE); + } + + // Create a temporary DIV after the BR and get the position as it + // seems like getPos() returns 0 for text nodes and BR elements. + dom.insertAfter(div, br); + divYPos = dom.getPos(div).y; + dom.remove(div); + + // Scroll to new position, scrollIntoView can't be used due to bug: http://bugs.webkit.org/show_bug.cgi?id=16117 + if (divYPos > vpHeight) // It is not necessary to scroll if the DIV is inside the view port. + ed.getWin().scrollTo(0, divYPos); + }; + + ed.onKeyPress.add(function(ed, e) { + if (e.keyCode == 13 && (e.shiftKey || (s.force_br_newlines && !dom.getParent(selection.getNode(), 'h1,h2,h3,h4,h5,h6,ol,ul')))) { + insertBr(ed); + Event.cancel(e); + } + }); + } + + // IE specific fixes + if (isIE) { + // Replaces IE:s auto generated paragraphs with the specified element name + if (s.element != 'P') { + ed.onKeyPress.add(function(ed, e) { + t.lastElm = selection.getNode().nodeName; + }); + + ed.onKeyUp.add(function(ed, e) { + var bl, n = selection.getNode(), b = ed.getBody(); + + if (b.childNodes.length === 1 && n.nodeName == 'P') { + n = dom.rename(n, s.element); + selection.select(n); + selection.collapse(); + ed.nodeChanged(); + } else if (e.keyCode == 13 && !e.shiftKey && t.lastElm != 'P') { + bl = dom.getParent(n, 'p'); + + if (bl) { + dom.rename(bl, s.element); + ed.nodeChanged(); + } + } + }); + } + } + }, + + getParentBlock : function(n) { + var d = this.dom; + + return d.getParent(n, d.isBlock); + }, + + insertPara : function(e) { + var t = this, ed = t.editor, dom = ed.dom, d = ed.getDoc(), se = ed.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body; + var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n, vp = dom.getViewPort(ed.getWin()), y, ch, car; + + ed.undoManager.beforeChange(); + + // If root blocks are forced then use Operas default behavior since it's really good +// Removed due to bug: #1853816 +// if (se.forced_root_block && isOpera) +// return TRUE; + + // Setup before range + rb = d.createRange(); + + // If is before the first block element and in body, then move it into first block element + rb.setStart(s.anchorNode, s.anchorOffset); + rb.collapse(TRUE); + + // Setup after range + ra = d.createRange(); + + // If is before the first block element and in body, then move it into first block element + ra.setStart(s.focusNode, s.focusOffset); + ra.collapse(TRUE); + + // Setup start/end points + dir = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0; + sn = dir ? s.anchorNode : s.focusNode; + so = dir ? s.anchorOffset : s.focusOffset; + en = dir ? s.focusNode : s.anchorNode; + eo = dir ? s.focusOffset : s.anchorOffset; + + // If selection is in empty table cell + if (sn === en && /^(TD|TH)$/.test(sn.nodeName)) { + if (sn.firstChild.nodeName == 'BR') + dom.remove(sn.firstChild); // Remove BR + + // Create two new block elements + if (sn.childNodes.length == 0) { + ed.dom.add(sn, se.element, null, '<br />'); + aft = ed.dom.add(sn, se.element, null, '<br />'); + } else { + n = sn.innerHTML; + sn.innerHTML = ''; + ed.dom.add(sn, se.element, null, n); + aft = ed.dom.add(sn, se.element, null, '<br />'); + } + + // Move caret into the last one + r = d.createRange(); + r.selectNodeContents(aft); + r.collapse(1); + ed.selection.setRng(r); + + return FALSE; + } + + // If the caret is in an invalid location in FF we need to move it into the first block + if (sn == b && en == b && b.firstChild && ed.dom.isBlock(b.firstChild)) { + sn = en = sn.firstChild; + so = eo = 0; + rb = d.createRange(); + rb.setStart(sn, 0); + ra = d.createRange(); + ra.setStart(en, 0); + } + + // If the body is totally empty add a BR element this might happen on webkit + if (!d.body.hasChildNodes()) { + d.body.appendChild(dom.create('br')); + } + + // Never use body as start or end node + sn = sn.nodeName == "HTML" ? d.body : sn; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes + sn = sn.nodeName == "BODY" ? sn.firstChild : sn; + en = en.nodeName == "HTML" ? d.body : en; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes + en = en.nodeName == "BODY" ? en.firstChild : en; + + // Get start and end blocks + sb = t.getParentBlock(sn); + eb = t.getParentBlock(en); + bn = sb ? sb.nodeName : se.element; // Get block name to create + + // Return inside list use default browser behavior + if (n = t.dom.getParent(sb, 'li,pre')) { + if (n.nodeName == 'LI') + return splitList(ed.selection, t.dom, n); + + return TRUE; + } + + // If caption or absolute layers then always generate new blocks within + if (sb && (sb.nodeName == 'CAPTION' || /absolute|relative|fixed/gi.test(dom.getStyle(sb, 'position', 1)))) { + bn = se.element; + sb = null; + } + + // If caption or absolute layers then always generate new blocks within + if (eb && (eb.nodeName == 'CAPTION' || /absolute|relative|fixed/gi.test(dom.getStyle(sb, 'position', 1)))) { + bn = se.element; + eb = null; + } + + // Use P instead + if (/(TD|TABLE|TH|CAPTION)/.test(bn) || (sb && bn == "DIV" && /left|right/gi.test(dom.getStyle(sb, 'float', 1)))) { + bn = se.element; + sb = eb = null; + } + + // Setup new before and after blocks + bef = (sb && sb.nodeName == bn) ? sb.cloneNode(0) : ed.dom.create(bn); + aft = (eb && eb.nodeName == bn) ? eb.cloneNode(0) : ed.dom.create(bn); + + // Remove id from after clone + aft.removeAttribute('id'); + + // Is header and cursor is at the end, then force paragraph under + if (/^(H[1-6])$/.test(bn) && isAtEnd(r, sb)) + aft = ed.dom.create(se.element); + + // Find start chop node + n = sc = sn; + do { + if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName)) + break; + + sc = n; + } while ((n = n.previousSibling ? n.previousSibling : n.parentNode)); + + // Find end chop node + n = ec = en; + do { + if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName)) + break; + + ec = n; + } while ((n = n.nextSibling ? n.nextSibling : n.parentNode)); + + // Place first chop part into before block element + if (sc.nodeName == bn) + rb.setStart(sc, 0); + else + rb.setStartBefore(sc); + + rb.setEnd(sn, so); + bef.appendChild(rb.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari + + // Place secnd chop part within new block element + try { + ra.setEndAfter(ec); + } catch(ex) { + //console.debug(s.focusNode, s.focusOffset); + } + + ra.setStart(en, eo); + aft.appendChild(ra.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari + + // Create range around everything + r = d.createRange(); + if (!sc.previousSibling && sc.parentNode.nodeName == bn) { + r.setStartBefore(sc.parentNode); + } else { + if (rb.startContainer.nodeName == bn && rb.startOffset == 0) + r.setStartBefore(rb.startContainer); + else + r.setStart(rb.startContainer, rb.startOffset); + } + + if (!ec.nextSibling && ec.parentNode.nodeName == bn) + r.setEndAfter(ec.parentNode); + else + r.setEnd(ra.endContainer, ra.endOffset); + + // Delete and replace it with new block elements + r.deleteContents(); + + if (isOpera) + ed.getWin().scrollTo(0, vp.y); + + // Never wrap blocks in blocks + if (bef.firstChild && bef.firstChild.nodeName == bn) + bef.innerHTML = bef.firstChild.innerHTML; + + if (aft.firstChild && aft.firstChild.nodeName == bn) + aft.innerHTML = aft.firstChild.innerHTML; + + function appendStyles(e, en) { + var nl = [], nn, n, i; + + e.innerHTML = ''; + + // Make clones of style elements + if (se.keep_styles) { + n = en; + do { + // We only want style specific elements + if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(n.nodeName)) { + nn = n.cloneNode(FALSE); + dom.setAttrib(nn, 'id', ''); // Remove ID since it needs to be unique + nl.push(nn); + } + } while (n = n.parentNode); + } + + // Append style elements to aft + if (nl.length > 0) { + for (i = nl.length - 1, nn = e; i >= 0; i--) + nn = nn.appendChild(nl[i]); + + // Padd most inner style element + nl[0].innerHTML = isOpera ? '\u00a0' : '<br />'; // Extra space for Opera so that the caret can move there + return nl[0]; // Move caret to most inner element + } else + e.innerHTML = isOpera ? '\u00a0' : '<br />'; // Extra space for Opera so that the caret can move there + }; + + // Padd empty blocks + if (dom.isEmpty(bef)) + appendStyles(bef, sn); + + // Fill empty afterblook with current style + if (dom.isEmpty(aft)) + car = appendStyles(aft, en); + + // Opera needs this one backwards for older versions + if (isOpera && parseFloat(opera.version()) < 9.5) { + r.insertNode(bef); + r.insertNode(aft); + } else { + r.insertNode(aft); + r.insertNode(bef); + } + + // Normalize + aft.normalize(); + bef.normalize(); + + // Move cursor and scroll into view + ed.selection.select(aft, true); + ed.selection.collapse(true); + + // scrollIntoView seems to scroll the parent window in most browsers now including FF 3.0b4 so it's time to stop using it and do it our selfs + y = ed.dom.getPos(aft).y; + //ch = aft.clientHeight; + + // Is element within viewport + if (y < vp.y || y + 25 > vp.y + vp.h) { + ed.getWin().scrollTo(0, y < vp.y ? y : y - vp.h + 25); // Needs to be hardcoded to roughly one line of text if a huge text block is broken into two blocks + + /*console.debug( + 'Element: y=' + y + ', h=' + ch + ', ' + + 'Viewport: y=' + vp.y + ", h=" + vp.h + ', bottom=' + (vp.y + vp.h) + );*/ + } + + ed.undoManager.add(); + + return FALSE; + }, + + backspaceDelete : function(e, bs) { + var t = this, ed = t.editor, b = ed.getBody(), dom = ed.dom, n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn, walker; + + // Delete when caret is behind a element doesn't work correctly on Gecko see #3011651 + if (!bs && r.collapsed && sc.nodeType == 1 && r.startOffset == sc.childNodes.length) { + walker = new tinymce.dom.TreeWalker(sc.lastChild, sc); + + // Walk the dom backwards until we find a text node + for (n = sc.lastChild; n; n = walker.prev()) { + if (n.nodeType == 3) { + r.setStart(n, n.nodeValue.length); + r.collapse(true); + se.setRng(r); + return; + } + } + } + + // The caret sometimes gets stuck in Gecko if you delete empty paragraphs + // This workaround removes the element by hand and moves the caret to the previous element + if (sc && ed.dom.isBlock(sc) && !/^(TD|TH)$/.test(sc.nodeName) && bs) { + if (sc.childNodes.length == 0 || (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR')) { + // Find previous block element + n = sc; + while ((n = n.previousSibling) && !ed.dom.isBlock(n)) ; + + if (n) { + if (sc != b.firstChild) { + // Find last text node + w = ed.dom.doc.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, FALSE); + while (tn = w.nextNode()) + n = tn; + + // Place caret at the end of last text node + r = ed.getDoc().createRange(); + r.setStart(n, n.nodeValue ? n.nodeValue.length : 0); + r.setEnd(n, n.nodeValue ? n.nodeValue.length : 0); + se.setRng(r); + + // Remove the target container + ed.dom.remove(sc); + } + + return Event.cancel(e); + } + } + } + } + }); +})(tinymce); + +(function(tinymce) { + // Shorten names + var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, extend = tinymce.extend; + + tinymce.create('tinymce.ControlManager', { + ControlManager : function(ed, s) { + var t = this, i; + + s = s || {}; + t.editor = ed; + t.controls = {}; + t.onAdd = new tinymce.util.Dispatcher(t); + t.onPostRender = new tinymce.util.Dispatcher(t); + t.prefix = s.prefix || ed.id + '_'; + t._cls = {}; + + t.onPostRender.add(function() { + each(t.controls, function(c) { + c.postRender(); + }); + }); + }, + + get : function(id) { + return this.controls[this.prefix + id] || this.controls[id]; + }, + + setActive : function(id, s) { + var c = null; + + if (c = this.get(id)) + c.setActive(s); + + return c; + }, + + setDisabled : function(id, s) { + var c = null; + + if (c = this.get(id)) + c.setDisabled(s); + + return c; + }, + + add : function(c) { + var t = this; + + if (c) { + t.controls[c.id] = c; + t.onAdd.dispatch(c, t); + } + + return c; + }, + + createControl : function(n) { + var c, t = this, ed = t.editor; + + each(ed.plugins, function(p) { + if (p.createControl) { + c = p.createControl(n, t); + + if (c) + return false; + } + }); + + switch (n) { + case "|": + case "separator": + return t.createSeparator(); + } + + if (!c && ed.buttons && (c = ed.buttons[n])) + return t.createButton(n, c); + + return t.add(c); + }, + + createDropMenu : function(id, s, cc) { + var t = this, ed = t.editor, c, bm, v, cls; + + s = extend({ + 'class' : 'mceDropDown', + constrain : ed.settings.constrain_menus + }, s); + + s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin'; + if (v = ed.getParam('skin_variant')) + s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1); + + id = t.prefix + id; + cls = cc || t._cls.dropmenu || tinymce.ui.DropMenu; + c = t.controls[id] = new cls(id, s); + c.onAddItem.add(function(c, o) { + var s = o.settings; + + s.title = ed.getLang(s.title, s.title); + + if (!s.onclick) { + s.onclick = function(v) { + if (s.cmd) + ed.execCommand(s.cmd, s.ui || false, s.value); + }; + } + }); + + ed.onRemove.add(function() { + c.destroy(); + }); + + // Fix for bug #1897785, #1898007 + if (tinymce.isIE) { + c.onShowMenu.add(function() { + // IE 8 needs focus in order to store away a range with the current collapsed caret location + ed.focus(); + + bm = ed.selection.getBookmark(1); + }); + + c.onHideMenu.add(function() { + if (bm) { + ed.selection.moveToBookmark(bm); + bm = 0; + } + }); + } + + return t.add(c); + }, + + createListBox : function(id, s, cc) { + var t = this, ed = t.editor, cmd, c, cls; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.scope = s.scope || ed; + + if (!s.onselect) { + s.onselect = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + scope : s.scope, + control_manager : t + }, s); + + id = t.prefix + id; + + + function useNativeListForAccessibility(ed) { + return ed.settings.use_accessible_selects && !tinymce.isGecko + } + + if (ed.settings.use_native_selects || useNativeListForAccessibility(ed)) + c = new tinymce.ui.NativeListBox(id, s); + else { + cls = cc || t._cls.listbox || tinymce.ui.ListBox; + c = new cls(id, s, ed); + } + + t.controls[id] = c; + + // Fix focus problem in Safari + if (tinymce.isWebKit) { + c.onPostRender.add(function(c, n) { + // Store bookmark on mousedown + Event.add(n, 'mousedown', function() { + ed.bookmark = ed.selection.getBookmark(1); + }); + + // Restore on focus, since it might be lost + Event.add(n, 'focus', function() { + ed.selection.moveToBookmark(ed.bookmark); + ed.bookmark = null; + }); + }); + } + + if (c.hideMenu) + ed.onMouseDown.add(c.hideMenu, c); + + return t.add(c); + }, + + createButton : function(id, s, cc) { + var t = this, ed = t.editor, o, c, cls; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.label = ed.translate(s.label); + s.scope = s.scope || ed; + + if (!s.onclick && !s.menu_button) { + s.onclick = function() { + ed.execCommand(s.cmd, s.ui || false, s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + unavailable_prefix : ed.getLang('unavailable', ''), + scope : s.scope, + control_manager : t + }, s); + + id = t.prefix + id; + + if (s.menu_button) { + cls = cc || t._cls.menubutton || tinymce.ui.MenuButton; + c = new cls(id, s, ed); + ed.onMouseDown.add(c.hideMenu, c); + } else { + cls = t._cls.button || tinymce.ui.Button; + c = new cls(id, s, ed); + } + + return t.add(c); + }, + + createMenuButton : function(id, s, cc) { + s = s || {}; + s.menu_button = 1; + + return this.createButton(id, s, cc); + }, + + createSplitButton : function(id, s, cc) { + var t = this, ed = t.editor, cmd, c, cls; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.scope = s.scope || ed; + + if (!s.onclick) { + s.onclick = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + if (!s.onselect) { + s.onselect = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + scope : s.scope, + control_manager : t + }, s); + + id = t.prefix + id; + cls = cc || t._cls.splitbutton || tinymce.ui.SplitButton; + c = t.add(new cls(id, s, ed)); + ed.onMouseDown.add(c.hideMenu, c); + + return c; + }, + + createColorSplitButton : function(id, s, cc) { + var t = this, ed = t.editor, cmd, c, cls, bm; + + if (t.get(id)) + return null; + + s.title = ed.translate(s.title); + s.scope = s.scope || ed; + + if (!s.onclick) { + s.onclick = function(v) { + if (tinymce.isIE) + bm = ed.selection.getBookmark(1); + + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + if (!s.onselect) { + s.onselect = function(v) { + ed.execCommand(s.cmd, s.ui || false, v || s.value); + }; + } + + s = extend({ + title : s.title, + 'class' : 'mce_' + id, + 'menu_class' : ed.getParam('skin') + 'Skin', + scope : s.scope, + more_colors_title : ed.getLang('more_colors') + }, s); + + id = t.prefix + id; + cls = cc || t._cls.colorsplitbutton || tinymce.ui.ColorSplitButton; + c = new cls(id, s, ed); + ed.onMouseDown.add(c.hideMenu, c); + + // Remove the menu element when the editor is removed + ed.onRemove.add(function() { + c.destroy(); + }); + + // Fix for bug #1897785, #1898007 + if (tinymce.isIE) { + c.onShowMenu.add(function() { + // IE 8 needs focus in order to store away a range with the current collapsed caret location + ed.focus(); + bm = ed.selection.getBookmark(1); + }); + + c.onHideMenu.add(function() { + if (bm) { + ed.selection.moveToBookmark(bm); + bm = 0; + } + }); + } + + return t.add(c); + }, + + createToolbar : function(id, s, cc) { + var c, t = this, cls; + + id = t.prefix + id; + cls = cc || t._cls.toolbar || tinymce.ui.Toolbar; + c = new cls(id, s, t.editor); + + if (t.get(id)) + return null; + + return t.add(c); + }, + + createToolbarGroup : function(id, s, cc) { + var c, t = this, cls; + id = t.prefix + id; + cls = cc || this._cls.toolbarGroup || tinymce.ui.ToolbarGroup; + c = new cls(id, s, t.editor); + + if (t.get(id)) + return null; + + return t.add(c); + }, + + createSeparator : function(cc) { + var cls = cc || this._cls.separator || tinymce.ui.Separator; + + return new cls(); + }, + + setControlType : function(n, c) { + return this._cls[n.toLowerCase()] = c; + }, + + destroy : function() { + each(this.controls, function(c) { + c.destroy(); + }); + + this.controls = null; + } + }); +})(tinymce); + +(function(tinymce) { + var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isIE = tinymce.isIE, isOpera = tinymce.isOpera; + + tinymce.create('tinymce.WindowManager', { + WindowManager : function(ed) { + var t = this; + + t.editor = ed; + t.onOpen = new Dispatcher(t); + t.onClose = new Dispatcher(t); + t.params = {}; + t.features = {}; + }, + + open : function(s, p) { + var t = this, f = '', x, y, mo = t.editor.settings.dialog_type == 'modal', w, sw, sh, vp = tinymce.DOM.getViewPort(), u; + + // Default some options + s = s || {}; + p = p || {}; + sw = isOpera ? vp.w : screen.width; // Opera uses windows inside the Opera window + sh = isOpera ? vp.h : screen.height; + s.name = s.name || 'mc_' + new Date().getTime(); + s.width = parseInt(s.width || 320); + s.height = parseInt(s.height || 240); + s.resizable = true; + s.left = s.left || parseInt(sw / 2.0) - (s.width / 2.0); + s.top = s.top || parseInt(sh / 2.0) - (s.height / 2.0); + p.inline = false; + p.mce_width = s.width; + p.mce_height = s.height; + p.mce_auto_focus = s.auto_focus; + + if (mo) { + if (isIE) { + s.center = true; + s.help = false; + s.dialogWidth = s.width + 'px'; + s.dialogHeight = s.height + 'px'; + s.scroll = s.scrollbars || false; + } + } + + // Build features string + each(s, function(v, k) { + if (tinymce.is(v, 'boolean')) + v = v ? 'yes' : 'no'; + + if (!/^(name|url)$/.test(k)) { + if (isIE && mo) + f += (f ? ';' : '') + k + ':' + v; + else + f += (f ? ',' : '') + k + '=' + v; + } + }); + + t.features = s; + t.params = p; + t.onOpen.dispatch(t, s, p); + + u = s.url || s.file; + u = tinymce._addVer(u); + + try { + if (isIE && mo) { + w = 1; + window.showModalDialog(u, window, f); + } else + w = window.open(u, s.name, f); + } catch (ex) { + // Ignore + } + + if (!w) + alert(t.editor.getLang('popup_blocked')); + }, + + close : function(w) { + w.close(); + this.onClose.dispatch(this); + }, + + createInstance : function(cl, a, b, c, d, e) { + var f = tinymce.resolve(cl); + + return new f(a, b, c, d, e); + }, + + confirm : function(t, cb, s, w) { + w = w || window; + + cb.call(s || this, w.confirm(this._decode(this.editor.getLang(t, t)))); + }, + + alert : function(tx, cb, s, w) { + var t = this; + + w = w || window; + w.alert(t._decode(t.editor.getLang(tx, tx))); + + if (cb) + cb.call(s || t); + }, + + resizeBy : function(dw, dh, win) { + win.resizeBy(dw, dh); + }, + + // Internal functions + + _decode : function(s) { + return tinymce.DOM.decode(s).replace(/\\n/g, '\n'); + } + }); +}(tinymce)); +(function(tinymce) { + tinymce.Formatter = function(ed) { + var formats = {}, + each = tinymce.each, + dom = ed.dom, + selection = ed.selection, + TreeWalker = tinymce.dom.TreeWalker, + rangeUtils = new tinymce.dom.RangeUtils(dom), + isValid = ed.schema.isValidChild, + isBlock = dom.isBlock, + forcedRootBlock = ed.settings.forced_root_block, + nodeIndex = dom.nodeIndex, + INVISIBLE_CHAR = '\uFEFF', + MCE_ATTR_RE = /^(src|href|style)$/, + FALSE = false, + TRUE = true, + undefined, + pendingFormats = {apply : [], remove : []}; + + function isArray(obj) { + return obj instanceof Array; + }; + + function getParents(node, selector) { + return dom.getParents(node, selector, dom.getRoot()); + }; + + function isCaretNode(node) { + return node.nodeType === 1 && (node.face === 'mceinline' || node.style.fontFamily === 'mceinline'); + }; + + // Public functions + + function get(name) { + return name ? formats[name] : formats; + }; + + function register(name, format) { + if (name) { + if (typeof(name) !== 'string') { + each(name, function(format, name) { + register(name, format); + }); + } else { + // Force format into array and add it to internal collection + format = format.length ? format : [format]; + + each(format, function(format) { + // Set deep to false by default on selector formats this to avoid removing + // alignment on images inside paragraphs when alignment is changed on paragraphs + if (format.deep === undefined) + format.deep = !format.selector; + + // Default to true + if (format.split === undefined) + format.split = !format.selector || format.inline; + + // Default to true + if (format.remove === undefined && format.selector && !format.inline) + format.remove = 'none'; + + // Mark format as a mixed format inline + block level + if (format.selector && format.inline) { + format.mixed = true; + format.block_expand = true; + } + + // Split classes if needed + if (typeof(format.classes) === 'string') + format.classes = format.classes.split(/\s+/); + }); + + formats[name] = format; + } + } + }; + + var getTextDecoration = function(node) { + var decoration; + + ed.dom.getParent(node, function(n) { + decoration = ed.dom.getStyle(n, 'text-decoration'); + return decoration && decoration !== 'none'; + }); + + return decoration; + }; + + var processUnderlineAndColor = function(node) { + var textDecoration; + if (node.nodeType === 1 && node.parentNode && node.parentNode.nodeType === 1) { + textDecoration = getTextDecoration(node.parentNode); + if (ed.dom.getStyle(node, 'color') && textDecoration) { + ed.dom.setStyle(node, 'text-decoration', textDecoration); + } else if (ed.dom.getStyle(node, 'textdecoration') === textDecoration) { + ed.dom.setStyle(node, 'text-decoration', null); + } + } + }; + + function apply(name, vars, node) { + var formatList = get(name), format = formatList[0], bookmark, rng, i, isCollapsed = selection.isCollapsed(); + + function moveStart(rng) { + var container = rng.startContainer, + offset = rng.startOffset, + walker, node; + + // Move startContainer/startOffset in to a suitable node + if (container.nodeType == 1 || container.nodeValue === "") { + container = container.nodeType == 1 ? container.childNodes[offset] : container; + + // Might fail if the offset is behind the last element in it's container + if (container) { + walker = new TreeWalker(container, container.parentNode); + for (node = walker.current(); node; node = walker.next()) { + if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { + rng.setStart(node, 0); + break; + } + } + } + } + + return rng; + }; + + function setElementFormat(elm, fmt) { + fmt = fmt || format; + + if (elm) { + if (fmt.onformat) { + fmt.onformat(elm, fmt, vars, node); + } + + each(fmt.styles, function(value, name) { + dom.setStyle(elm, name, replaceVars(value, vars)); + }); + + each(fmt.attributes, function(value, name) { + dom.setAttrib(elm, name, replaceVars(value, vars)); + }); + + each(fmt.classes, function(value) { + value = replaceVars(value, vars); + + if (!dom.hasClass(elm, value)) + dom.addClass(elm, value); + }); + } + }; + function adjustSelectionToVisibleSelection() { + function findSelectionEnd(start, end) { + var walker = new TreeWalker(end); + for (node = walker.current(); node; node = walker.prev()) { + if (node.childNodes.length > 1 || node == start) { + return node; + } + } + }; + + // Adjust selection so that a end container with a end offset of zero is not included in the selection + // as this isn't visible to the user. + var rng = ed.selection.getRng(); + var start = rng.startContainer; + var end = rng.endContainer; + + if (start != end && rng.endOffset == 0) { + var newEnd = findSelectionEnd(start, end); + var endOffset = newEnd.nodeType == 3 ? newEnd.length : newEnd.childNodes.length; + + rng.setEnd(newEnd, endOffset); + } + + return rng; + } + + function applyStyleToList(node, bookmark, wrapElm, newWrappers, process){ + var nodes = [], listIndex = -1, list, startIndex = -1, endIndex = -1, currentWrapElm; + + // find the index of the first child list. + each(node.childNodes, function(n, index) { + if (n.nodeName === "UL" || n.nodeName === "OL") { + listIndex = index; + list = n; + return false; + } + }); + + // get the index of the bookmarks + each(node.childNodes, function(n, index) { + if (n.nodeName === "SPAN" && dom.getAttrib(n, "data-mce-type") == "bookmark") { + if (n.id == bookmark.id + "_start") { + startIndex = index; + } else if (n.id == bookmark.id + "_end") { + endIndex = index; + } + } + }); + + // if the selection spans across an embedded list, or there isn't an embedded list - handle processing normally + if (listIndex <= 0 || (startIndex < listIndex && endIndex > listIndex)) { + each(tinymce.grep(node.childNodes), process); + return 0; + } else { + currentWrapElm = wrapElm.cloneNode(FALSE); + + // create a list of the nodes on the same side of the list as the selection + each(tinymce.grep(node.childNodes), function(n, index) { + if ((startIndex < listIndex && index < listIndex) || (startIndex > listIndex && index > listIndex)) { + nodes.push(n); + n.parentNode.removeChild(n); + } + }); + + // insert the wrapping element either before or after the list. + if (startIndex < listIndex) { + node.insertBefore(currentWrapElm, list); + } else if (startIndex > listIndex) { + node.insertBefore(currentWrapElm, list.nextSibling); + } + + // add the new nodes to the list. + newWrappers.push(currentWrapElm); + + each(nodes, function(node) { + currentWrapElm.appendChild(node); + }); + + return currentWrapElm; + } + }; + + function applyRngStyle(rng, bookmark) { + var newWrappers = [], wrapName, wrapElm; + + // Setup wrapper element + wrapName = format.inline || format.block; + wrapElm = dom.create(wrapName); + setElementFormat(wrapElm); + + rangeUtils.walk(rng, function(nodes) { + var currentWrapElm; + + function process(node) { + var nodeName = node.nodeName.toLowerCase(), parentName = node.parentNode.nodeName.toLowerCase(), found; + + // Stop wrapping on br elements + if (isEq(nodeName, 'br')) { + currentWrapElm = 0; + + // Remove any br elements when we wrap things + if (format.block) + dom.remove(node); + + return; + } + + // If node is wrapper type + if (format.wrapper && matchNode(node, name, vars)) { + currentWrapElm = 0; + return; + } + + // Can we rename the block + if (format.block && !format.wrapper && isTextBlock(nodeName)) { + node = dom.rename(node, wrapName); + setElementFormat(node); + newWrappers.push(node); + currentWrapElm = 0; + return; + } + + // Handle selector patterns + if (format.selector) { + // Look for matching formats + each(formatList, function(format) { + // Check collapsed state if it exists + if ('collapsed' in format && format.collapsed !== isCollapsed) { + return; + } + + if (dom.is(node, format.selector) && !isCaretNode(node)) { + setElementFormat(node, format); + found = true; + } + }); + + // Continue processing if a selector match wasn't found and a inline element is defined + if (!format.inline || found) { + currentWrapElm = 0; + return; + } + } + + // Is it valid to wrap this item + if (isValid(wrapName, nodeName) && isValid(parentName, wrapName) && + !(node.nodeType === 3 && node.nodeValue.length === 1 && node.nodeValue.charCodeAt(0) === 65279)) { + // Start wrapping + if (!currentWrapElm) { + // Wrap the node + currentWrapElm = wrapElm.cloneNode(FALSE); + node.parentNode.insertBefore(currentWrapElm, node); + newWrappers.push(currentWrapElm); + } + + currentWrapElm.appendChild(node); + } else if (nodeName == 'li' && bookmark) { + // Start wrapping - if we are in a list node and have a bookmark, then we will always begin by wrapping in a new element. + currentWrapElm = applyStyleToList(node, bookmark, wrapElm, newWrappers, process); + } else { + // Start a new wrapper for possible children + currentWrapElm = 0; + + each(tinymce.grep(node.childNodes), process); + + // End the last wrapper + currentWrapElm = 0; + } + }; + + // Process siblings from range + each(nodes, process); + }); + + // Wrap links inside as well, for example color inside a link when the wrapper is around the link + if (format.wrap_links === false) { + each(newWrappers, function(node) { + function process(node) { + var i, currentWrapElm, children; + + if (node.nodeName === 'A') { + currentWrapElm = wrapElm.cloneNode(FALSE); + newWrappers.push(currentWrapElm); + + children = tinymce.grep(node.childNodes); + for (i = 0; i < children.length; i++) + currentWrapElm.appendChild(children[i]); + + node.appendChild(currentWrapElm); + } + + each(tinymce.grep(node.childNodes), process); + }; + + process(node); + }); + } + + // Cleanup + each(newWrappers, function(node) { + var childCount; + + function getChildCount(node) { + var count = 0; + + each(node.childNodes, function(node) { + if (!isWhiteSpaceNode(node) && !isBookmarkNode(node)) + count++; + }); + + return count; + }; + + function mergeStyles(node) { + var child, clone; + + each(node.childNodes, function(node) { + if (node.nodeType == 1 && !isBookmarkNode(node) && !isCaretNode(node)) { + child = node; + return FALSE; // break loop + } + }); + + // If child was found and of the same type as the current node + if (child && matchName(child, format)) { + clone = child.cloneNode(FALSE); + setElementFormat(clone); + + dom.replace(clone, node, TRUE); + dom.remove(child, 1); + } + + return clone || node; + }; + + childCount = getChildCount(node); + + // Remove empty nodes but only if there is multiple wrappers and they are not block + // elements so never remove single <h1></h1> since that would remove the currrent empty block element where the caret is at + if ((newWrappers.length > 1 || !isBlock(node)) && childCount === 0) { + dom.remove(node, 1); + return; + } + + if (format.inline || format.wrapper) { + // Merges the current node with it's children of similar type to reduce the number of elements + if (!format.exact && childCount === 1) + node = mergeStyles(node); + + // Remove/merge children + each(formatList, function(format) { + // Merge all children of similar type will move styles from child to parent + // this: <span style="color:red"><b><span style="color:red; font-size:10px">text</span></b></span> + // will become: <span style="color:red"><b><span style="font-size:10px">text</span></b></span> + each(dom.select(format.inline, node), function(child) { + var parent; + + // When wrap_links is set to false we don't want + // to remove the format on children within links + if (format.wrap_links === false) { + parent = child.parentNode; + + do { + if (parent.nodeName === 'A') + return; + } while (parent = parent.parentNode); + } + + removeFormat(format, vars, child, format.exact ? child : null); + }); + }); + + // Remove child if direct parent is of same type + if (matchNode(node.parentNode, name, vars)) { + dom.remove(node, 1); + node = 0; + return TRUE; + } + + // Look for parent with similar style format + if (format.merge_with_parents) { + dom.getParent(node.parentNode, function(parent) { + if (matchNode(parent, name, vars)) { + dom.remove(node, 1); + node = 0; + return TRUE; + } + }); + } + + // Merge next and previous siblings if they are similar <b>text</b><b>text</b> becomes <b>texttext</b> + if (node && format.merge_siblings !== false) { + node = mergeSiblings(getNonWhiteSpaceSibling(node), node); + node = mergeSiblings(node, getNonWhiteSpaceSibling(node, TRUE)); + } + } + }); + }; + + if (format) { + if (node) { + rng = dom.createRng(); + + rng.setStartBefore(node); + rng.setEndAfter(node); + + applyRngStyle(expandRng(rng, formatList)); + } else { + if (!isCollapsed || !format.inline || dom.select('td.mceSelected,th.mceSelected').length) { + // Obtain selection node before selection is unselected by applyRngStyle() + var curSelNode = ed.selection.getNode(); + + // Apply formatting to selection + ed.selection.setRng(adjustSelectionToVisibleSelection()); + bookmark = selection.getBookmark(); + applyRngStyle(expandRng(selection.getRng(TRUE), formatList), bookmark); + + // Colored nodes should be underlined so that the color of the underline matches the text color. + if (format.styles && (format.styles.color || format.styles.textDecoration)) { + tinymce.walk(curSelNode, processUnderlineAndColor, 'childNodes'); + processUnderlineAndColor(curSelNode); + } + + selection.moveToBookmark(bookmark); + selection.setRng(moveStart(selection.getRng(TRUE))); + ed.nodeChanged(); + } else + performCaretAction('apply', name, vars); + } + } + }; + + function remove(name, vars, node) { + var formatList = get(name), format = formatList[0], bookmark, i, rng; + function moveStart(rng) { + var container = rng.startContainer, + offset = rng.startOffset, + walker, node, nodes, tmpNode; + + // Convert text node into index if possible + if (container.nodeType == 3 && offset >= container.nodeValue.length - 1) { + container = container.parentNode; + offset = nodeIndex(container) + 1; + } + + // Move startContainer/startOffset in to a suitable node + if (container.nodeType == 1) { + nodes = container.childNodes; + container = nodes[Math.min(offset, nodes.length - 1)]; + walker = new TreeWalker(container); + + // If offset is at end of the parent node walk to the next one + if (offset > nodes.length - 1) + walker.next(); + + for (node = walker.current(); node; node = walker.next()) { + if (node.nodeType == 3 && !isWhiteSpaceNode(node)) { + // IE has a "neat" feature where it moves the start node into the closest element + // we can avoid this by inserting an element before it and then remove it after we set the selection + tmpNode = dom.create('a', null, INVISIBLE_CHAR); + node.parentNode.insertBefore(tmpNode, node); + + // Set selection and remove tmpNode + rng.setStart(node, 0); + selection.setRng(rng); + dom.remove(tmpNode); + + return; + } + } + } + }; + + // Merges the styles for each node + function process(node) { + var children, i, l; + + // Grab the children first since the nodelist might be changed + children = tinymce.grep(node.childNodes); + + // Process current node + for (i = 0, l = formatList.length; i < l; i++) { + if (removeFormat(formatList[i], vars, node, node)) + break; + } + + // Process the children + if (format.deep) { + for (i = 0, l = children.length; i < l; i++) + process(children[i]); + } + }; + + function findFormatRoot(container) { + var formatRoot; + + // Find format root + each(getParents(container.parentNode).reverse(), function(parent) { + var format; + + // Find format root element + if (!formatRoot && parent.id != '_start' && parent.id != '_end') { + // Is the node matching the format we are looking for + format = matchNode(parent, name, vars); + if (format && format.split !== false) + formatRoot = parent; + } + }); + + return formatRoot; + }; + + function wrapAndSplit(format_root, container, target, split) { + var parent, clone, lastClone, firstClone, i, formatRootParent; + + // Format root found then clone formats and split it + if (format_root) { + formatRootParent = format_root.parentNode; + + for (parent = container.parentNode; parent && parent != formatRootParent; parent = parent.parentNode) { + clone = parent.cloneNode(FALSE); + + for (i = 0; i < formatList.length; i++) { + if (removeFormat(formatList[i], vars, clone, clone)) { + clone = 0; + break; + } + } + + // Build wrapper node + if (clone) { + if (lastClone) + clone.appendChild(lastClone); + + if (!firstClone) + firstClone = clone; + + lastClone = clone; + } + } + + // Never split block elements if the format is mixed + if (split && (!format.mixed || !isBlock(format_root))) + container = dom.split(format_root, container); + + // Wrap container in cloned formats + if (lastClone) { + target.parentNode.insertBefore(lastClone, target); + firstClone.appendChild(target); + } + } + + return container; + }; + + function splitToFormatRoot(container) { + return wrapAndSplit(findFormatRoot(container), container, container, true); + }; + + function unwrap(start) { + var node = dom.get(start ? '_start' : '_end'), + out = node[start ? 'firstChild' : 'lastChild']; + + // If the end is placed within the start the result will be removed + // So this checks if the out node is a bookmark node if it is it + // checks for another more suitable node + if (isBookmarkNode(out)) + out = out[start ? 'firstChild' : 'lastChild']; + + dom.remove(node, true); + + return out; + }; + + function removeRngStyle(rng) { + var startContainer, endContainer; + + rng = expandRng(rng, formatList, TRUE); + + if (format.split) { + startContainer = getContainer(rng, TRUE); + endContainer = getContainer(rng); + + if (startContainer != endContainer) { + // Wrap start/end nodes in span element since these might be cloned/moved + startContainer = wrap(startContainer, 'span', {id : '_start', 'data-mce-type' : 'bookmark'}); + endContainer = wrap(endContainer, 'span', {id : '_end', 'data-mce-type' : 'bookmark'}); + + // Split start/end + splitToFormatRoot(startContainer); + splitToFormatRoot(endContainer); + + // Unwrap start/end to get real elements again + startContainer = unwrap(TRUE); + endContainer = unwrap(); + } else + startContainer = endContainer = splitToFormatRoot(startContainer); + + // Update range positions since they might have changed after the split operations + rng.startContainer = startContainer.parentNode; + rng.startOffset = nodeIndex(startContainer); + rng.endContainer = endContainer.parentNode; + rng.endOffset = nodeIndex(endContainer) + 1; + } + + // Remove items between start/end + rangeUtils.walk(rng, function(nodes) { + each(nodes, function(node) { + process(node); + + // Remove parent span if it only contains text-decoration: underline, yet a parent node is also underlined. + if (node.nodeType === 1 && ed.dom.getStyle(node, 'text-decoration') === 'underline' && node.parentNode && getTextDecoration(node.parentNode) === 'underline') { + removeFormat({'deep': false, 'exact': true, 'inline': 'span', 'styles': {'textDecoration' : 'underline'}}, null, node); + } + }); + }); + }; + + // Handle node + if (node) { + rng = dom.createRng(); + rng.setStartBefore(node); + rng.setEndAfter(node); + removeRngStyle(rng); + return; + } + + if (!selection.isCollapsed() || !format.inline || dom.select('td.mceSelected,th.mceSelected').length) { + bookmark = selection.getBookmark(); + removeRngStyle(selection.getRng(TRUE)); + selection.moveToBookmark(bookmark); + + // Check if start element still has formatting then we are at: "<b>text|</b>text" and need to move the start into the next text node + if (format.inline && match(name, vars, selection.getStart())) { + moveStart(selection.getRng(true)); + } + + ed.nodeChanged(); + } else + performCaretAction('remove', name, vars); + }; + + function toggle(name, vars, node) { + var fmt = get(name); + + if (match(name, vars, node) && (!('toggle' in fmt[0]) || fmt[0]['toggle'])) + remove(name, vars, node); + else + apply(name, vars, node); + }; + + function matchNode(node, name, vars, similar) { + var formatList = get(name), format, i, classes; + + function matchItems(node, format, item_name) { + var key, value, items = format[item_name], i; + + // Custom match + if (format.onmatch) { + return format.onmatch(node, format, item_name); + } + + // Check all items + if (items) { + // Non indexed object + if (items.length === undefined) { + for (key in items) { + if (items.hasOwnProperty(key)) { + if (item_name === 'attributes') + value = dom.getAttrib(node, key); + else + value = getStyle(node, key); + + if (similar && !value && !format.exact) + return; + + if ((!similar || format.exact) && !isEq(value, replaceVars(items[key], vars))) + return; + } + } + } else { + // Only one match needed for indexed arrays + for (i = 0; i < items.length; i++) { + if (item_name === 'attributes' ? dom.getAttrib(node, items[i]) : getStyle(node, items[i])) + return format; + } + } + } + + return format; + }; + + if (formatList && node) { + // Check each format in list + for (i = 0; i < formatList.length; i++) { + format = formatList[i]; + + // Name name, attributes, styles and classes + if (matchName(node, format) && matchItems(node, format, 'attributes') && matchItems(node, format, 'styles')) { + // Match classes + if (classes = format.classes) { + for (i = 0; i < classes.length; i++) { + if (!dom.hasClass(node, classes[i])) + return; + } + } + + return format; + } + } + } + }; + + function match(name, vars, node) { + var startNode, i; + + function matchParents(node) { + // Find first node with similar format settings + node = dom.getParent(node, function(node) { + return !!matchNode(node, name, vars, true); + }); + + // Do an exact check on the similar format element + return matchNode(node, name, vars); + }; + + // Check specified node + if (node) + return matchParents(node); + + // Check pending formats + if (selection.isCollapsed()) { + for (i = pendingFormats.apply.length - 1; i >= 0; i--) { + if (pendingFormats.apply[i].name == name) + return true; + } + + for (i = pendingFormats.remove.length - 1; i >= 0; i--) { + if (pendingFormats.remove[i].name == name) + return false; + } + + return matchParents(selection.getNode()); + } + + // Check selected node + node = selection.getNode(); + if (matchParents(node)) + return TRUE; + + // Check start node if it's different + startNode = selection.getStart(); + if (startNode != node) { + if (matchParents(startNode)) + return TRUE; + } + + return FALSE; + }; + + function matchAll(names, vars) { + var startElement, matchedFormatNames = [], checkedMap = {}, i, ni, name; + + // If the selection is collapsed then check pending formats + if (selection.isCollapsed()) { + for (ni = 0; ni < names.length; ni++) { + // If the name is to be removed, then stop it from being added + for (i = pendingFormats.remove.length - 1; i >= 0; i--) { + name = names[ni]; + + if (pendingFormats.remove[i].name == name) { + checkedMap[name] = true; + break; + } + } + } + + // If the format is to be applied + for (i = pendingFormats.apply.length - 1; i >= 0; i--) { + for (ni = 0; ni < names.length; ni++) { + name = names[ni]; + + if (!checkedMap[name] && pendingFormats.apply[i].name == name) { + checkedMap[name] = true; + matchedFormatNames.push(name); + } + } + } + } + + // Check start of selection for formats + startElement = selection.getStart(); + dom.getParent(startElement, function(node) { + var i, name; + + for (i = 0; i < names.length; i++) { + name = names[i]; + + if (!checkedMap[name] && matchNode(node, name, vars)) { + checkedMap[name] = true; + matchedFormatNames.push(name); + } + } + }); + + return matchedFormatNames; + }; + + function canApply(name) { + var formatList = get(name), startNode, parents, i, x, selector; + + if (formatList) { + startNode = selection.getStart(); + parents = getParents(startNode); + + for (x = formatList.length - 1; x >= 0; x--) { + selector = formatList[x].selector; + + // Format is not selector based, then always return TRUE + if (!selector) + return TRUE; + + for (i = parents.length - 1; i >= 0; i--) { + if (dom.is(parents[i], selector)) + return TRUE; + } + } + } + + return FALSE; + }; + + // Expose to public + tinymce.extend(this, { + get : get, + register : register, + apply : apply, + remove : remove, + toggle : toggle, + match : match, + matchAll : matchAll, + matchNode : matchNode, + canApply : canApply + }); + + // Private functions + + function matchName(node, format) { + // Check for inline match + if (isEq(node, format.inline)) + return TRUE; + + // Check for block match + if (isEq(node, format.block)) + return TRUE; + + // Check for selector match + if (format.selector) + return dom.is(node, format.selector); + }; + + function isEq(str1, str2) { + str1 = str1 || ''; + str2 = str2 || ''; + + str1 = '' + (str1.nodeName || str1); + str2 = '' + (str2.nodeName || str2); + + return str1.toLowerCase() == str2.toLowerCase(); + }; + + function getStyle(node, name) { + var styleVal = dom.getStyle(node, name); + + // Force the format to hex + if (name == 'color' || name == 'backgroundColor') + styleVal = dom.toHex(styleVal); + + // Opera will return bold as 700 + if (name == 'fontWeight' && styleVal == 700) + styleVal = 'bold'; + + return '' + styleVal; + }; + + function replaceVars(value, vars) { + if (typeof(value) != "string") + value = value(vars); + else if (vars) { + value = value.replace(/%(\w+)/g, function(str, name) { + return vars[name] || str; + }); + } + + return value; + }; + + function isWhiteSpaceNode(node) { + return node && node.nodeType === 3 && /^([\s\r\n]+|)$/.test(node.nodeValue); + }; + + function wrap(node, name, attrs) { + var wrapper = dom.create(name, attrs); + + node.parentNode.insertBefore(wrapper, node); + wrapper.appendChild(node); + + return wrapper; + }; + + function expandRng(rng, format, remove) { + var startContainer = rng.startContainer, + startOffset = rng.startOffset, + endContainer = rng.endContainer, + endOffset = rng.endOffset, sibling, lastIdx, leaf; + + // This function walks up the tree if there is no siblings before/after the node + function findParentContainer(container, child_name, sibling_name, root) { + var parent, child; + + root = root || dom.getRoot(); + + for (;;) { + // Check if we can move up are we at root level or body level + parent = container.parentNode; + + // Stop expanding on block elements or root depending on format + if (parent == root || (!format[0].block_expand && isBlock(parent))) + return container; + + for (sibling = parent[child_name]; sibling && sibling != container; sibling = sibling[sibling_name]) { + if (sibling.nodeType == 1 && !isBookmarkNode(sibling)) + return container; + + if (sibling.nodeType == 3 && !isWhiteSpaceNode(sibling)) + return container; + } + + container = container.parentNode; + } + + return container; + }; + + // This function walks down the tree to find the leaf at the selection. + // The offset is also returned as if node initially a leaf, the offset may be in the middle of the text node. + function findLeaf(node, offset) { + if (offset === undefined) + offset = node.nodeType === 3 ? node.length : node.childNodes.length; + while (node && node.hasChildNodes()) { + node = node.childNodes[offset]; + if (node) + offset = node.nodeType === 3 ? node.length : node.childNodes.length; + } + return { node: node, offset: offset }; + } + + // If index based start position then resolve it + if (startContainer.nodeType == 1 && startContainer.hasChildNodes()) { + lastIdx = startContainer.childNodes.length - 1; + startContainer = startContainer.childNodes[startOffset > lastIdx ? lastIdx : startOffset]; + + if (startContainer.nodeType == 3) + startOffset = 0; + } + + // If index based end position then resolve it + if (endContainer.nodeType == 1 && endContainer.hasChildNodes()) { + lastIdx = endContainer.childNodes.length - 1; + endContainer = endContainer.childNodes[endOffset > lastIdx ? lastIdx : endOffset - 1]; + + if (endContainer.nodeType == 3) + endOffset = endContainer.nodeValue.length; + } + + // Exclude bookmark nodes if possible + if (isBookmarkNode(startContainer.parentNode)) + startContainer = startContainer.parentNode; + + if (isBookmarkNode(startContainer)) + startContainer = startContainer.nextSibling || startContainer; + + if (isBookmarkNode(endContainer.parentNode)) { + endOffset = dom.nodeIndex(endContainer); + endContainer = endContainer.parentNode; + } + + if (isBookmarkNode(endContainer) && endContainer.previousSibling) { + endContainer = endContainer.previousSibling; + endOffset = endContainer.length; + } + + if (format[0].inline) { + // Avoid applying formatting to a trailing space. + leaf = findLeaf(endContainer, endOffset); + if (leaf.node) { + while (leaf.node && leaf.offset === 0 && leaf.node.previousSibling) + leaf = findLeaf(leaf.node.previousSibling); + + if (leaf.node && leaf.offset > 0 && leaf.node.nodeType === 3 && + leaf.node.nodeValue.charAt(leaf.offset - 1) === ' ') { + + if (leaf.offset > 1) { + endContainer = leaf.node; + endContainer.splitText(leaf.offset - 1); + } else if (leaf.node.previousSibling) { + endContainer = leaf.node.previousSibling; + } + } + } + } + + // Move start/end point up the tree if the leaves are sharp and if we are in different containers + // Example * becomes !: !<p><b><i>*text</i><i>text*</i></b></p>! + // This will reduce the number of wrapper elements that needs to be created + // Move start point up the tree + if (format[0].inline || format[0].block_expand) { + startContainer = findParentContainer(startContainer, 'firstChild', 'nextSibling'); + endContainer = findParentContainer(endContainer, 'lastChild', 'previousSibling'); + } + + // Expand start/end container to matching selector + if (format[0].selector && format[0].expand !== FALSE && !format[0].inline) { + function findSelectorEndPoint(container, sibling_name) { + var parents, i, y, curFormat; + + if (container.nodeType == 3 && container.nodeValue.length == 0 && container[sibling_name]) + container = container[sibling_name]; + + parents = getParents(container); + for (i = 0; i < parents.length; i++) { + for (y = 0; y < format.length; y++) { + curFormat = format[y]; + + // If collapsed state is set then skip formats that doesn't match that + if ("collapsed" in curFormat && curFormat.collapsed !== rng.collapsed) + continue; + + if (dom.is(parents[i], curFormat.selector)) + return parents[i]; + } + } + + return container; + }; + + // Find new startContainer/endContainer if there is better one + startContainer = findSelectorEndPoint(startContainer, 'previousSibling'); + endContainer = findSelectorEndPoint(endContainer, 'nextSibling'); + } + + // Expand start/end container to matching block element or text node + if (format[0].block || format[0].selector) { + function findBlockEndPoint(container, sibling_name, sibling_name2) { + var node; + + // Expand to block of similar type + if (!format[0].wrapper) + node = dom.getParent(container, format[0].block); + + // Expand to first wrappable block element or any block element + if (!node) + node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, isBlock); + + // Exclude inner lists from wrapping + if (node && format[0].wrapper) + node = getParents(node, 'ul,ol').reverse()[0] || node; + + // Didn't find a block element look for first/last wrappable element + if (!node) { + node = container; + + while (node[sibling_name] && !isBlock(node[sibling_name])) { + node = node[sibling_name]; + + // Break on BR but include it will be removed later on + // we can't remove it now since we need to check if it can be wrapped + if (isEq(node, 'br')) + break; + } + } + + return node || container; + }; + + // Find new startContainer/endContainer if there is better one + startContainer = findBlockEndPoint(startContainer, 'previousSibling'); + endContainer = findBlockEndPoint(endContainer, 'nextSibling'); + + // Non block element then try to expand up the leaf + if (format[0].block) { + if (!isBlock(startContainer)) + startContainer = findParentContainer(startContainer, 'firstChild', 'nextSibling'); + + if (!isBlock(endContainer)) + endContainer = findParentContainer(endContainer, 'lastChild', 'previousSibling'); + } + } + + // Setup index for startContainer + if (startContainer.nodeType == 1) { + startOffset = nodeIndex(startContainer); + startContainer = startContainer.parentNode; + } + + // Setup index for endContainer + if (endContainer.nodeType == 1) { + endOffset = nodeIndex(endContainer) + 1; + endContainer = endContainer.parentNode; + } + + // Return new range like object + return { + startContainer : startContainer, + startOffset : startOffset, + endContainer : endContainer, + endOffset : endOffset + }; + } + + function removeFormat(format, vars, node, compare_node) { + var i, attrs, stylesModified; + + // Check if node matches format + if (!matchName(node, format)) + return FALSE; + + // Should we compare with format attribs and styles + if (format.remove != 'all') { + // Remove styles + each(format.styles, function(value, name) { + value = replaceVars(value, vars); + + // Indexed array + if (typeof(name) === 'number') { + name = value; + compare_node = 0; + } + + if (!compare_node || isEq(getStyle(compare_node, name), value)) + dom.setStyle(node, name, ''); + + stylesModified = 1; + }); + + // Remove style attribute if it's empty + if (stylesModified && dom.getAttrib(node, 'style') == '') { + node.removeAttribute('style'); + node.removeAttribute('data-mce-style'); + } + + // Remove attributes + each(format.attributes, function(value, name) { + var valueOut; + + value = replaceVars(value, vars); + + // Indexed array + if (typeof(name) === 'number') { + name = value; + compare_node = 0; + } + + if (!compare_node || isEq(dom.getAttrib(compare_node, name), value)) { + // Keep internal classes + if (name == 'class') { + value = dom.getAttrib(node, name); + if (value) { + // Build new class value where everything is removed except the internal prefixed classes + valueOut = ''; + each(value.split(/\s+/), function(cls) { + if (/mce\w+/.test(cls)) + valueOut += (valueOut ? ' ' : '') + cls; + }); + + // We got some internal classes left + if (valueOut) { + dom.setAttrib(node, name, valueOut); + return; + } + } + } + + // IE6 has a bug where the attribute doesn't get removed correctly + if (name == "class") + node.removeAttribute('className'); + + // Remove mce prefixed attributes + if (MCE_ATTR_RE.test(name)) + node.removeAttribute('data-mce-' + name); + + node.removeAttribute(name); + } + }); + + // Remove classes + each(format.classes, function(value) { + value = replaceVars(value, vars); + + if (!compare_node || dom.hasClass(compare_node, value)) + dom.removeClass(node, value); + }); + + // Check for non internal attributes + attrs = dom.getAttribs(node); + for (i = 0; i < attrs.length; i++) { + if (attrs[i].nodeName.indexOf('_') !== 0) + return FALSE; + } + } + + // Remove the inline child if it's empty for example <b> or <span> + if (format.remove != 'none') { + removeNode(node, format); + return TRUE; + } + }; + + function removeNode(node, format) { + var parentNode = node.parentNode, rootBlockElm; + + if (format.block) { + if (!forcedRootBlock) { + function find(node, next, inc) { + node = getNonWhiteSpaceSibling(node, next, inc); + + return !node || (node.nodeName == 'BR' || isBlock(node)); + }; + + // Append BR elements if needed before we remove the block + if (isBlock(node) && !isBlock(parentNode)) { + if (!find(node, FALSE) && !find(node.firstChild, TRUE, 1)) + node.insertBefore(dom.create('br'), node.firstChild); + + if (!find(node, TRUE) && !find(node.lastChild, FALSE, 1)) + node.appendChild(dom.create('br')); + } + } else { + // Wrap the block in a forcedRootBlock if we are at the root of document + if (parentNode == dom.getRoot()) { + if (!format.list_block || !isEq(node, format.list_block)) { + each(tinymce.grep(node.childNodes), function(node) { + if (isValid(forcedRootBlock, node.nodeName.toLowerCase())) { + if (!rootBlockElm) + rootBlockElm = wrap(node, forcedRootBlock); + else + rootBlockElm.appendChild(node); + } else + rootBlockElm = 0; + }); + } + } + } + } + + // Never remove nodes that isn't the specified inline element if a selector is specified too + if (format.selector && format.inline && !isEq(format.inline, node)) + return; + + dom.remove(node, 1); + }; + + function getNonWhiteSpaceSibling(node, next, inc) { + if (node) { + next = next ? 'nextSibling' : 'previousSibling'; + + for (node = inc ? node : node[next]; node; node = node[next]) { + if (node.nodeType == 1 || !isWhiteSpaceNode(node)) + return node; + } + } + }; + + function isBookmarkNode(node) { + return node && node.nodeType == 1 && node.getAttribute('data-mce-type') == 'bookmark'; + }; + + function mergeSiblings(prev, next) { + var marker, sibling, tmpSibling; + + function compareElements(node1, node2) { + // Not the same name + if (node1.nodeName != node2.nodeName) + return FALSE; + + function getAttribs(node) { + var attribs = {}; + + each(dom.getAttribs(node), function(attr) { + var name = attr.nodeName.toLowerCase(); + + // Don't compare internal attributes or style + if (name.indexOf('_') !== 0 && name !== 'style') + attribs[name] = dom.getAttrib(node, name); + }); + + return attribs; + }; + + function compareObjects(obj1, obj2) { + var value, name; + + for (name in obj1) { + // Obj1 has item obj2 doesn't have + if (obj1.hasOwnProperty(name)) { + value = obj2[name]; + + // Obj2 doesn't have obj1 item + if (value === undefined) + return FALSE; + + // Obj2 item has a different value + if (obj1[name] != value) + return FALSE; + + // Delete similar value + delete obj2[name]; + } + } + + // Check if obj 2 has something obj 1 doesn't have + for (name in obj2) { + // Obj2 has item obj1 doesn't have + if (obj2.hasOwnProperty(name)) + return FALSE; + } + + return TRUE; + }; + + // Attribs are not the same + if (!compareObjects(getAttribs(node1), getAttribs(node2))) + return FALSE; + + // Styles are not the same + if (!compareObjects(dom.parseStyle(dom.getAttrib(node1, 'style')), dom.parseStyle(dom.getAttrib(node2, 'style')))) + return FALSE; + + return TRUE; + }; + + // Check if next/prev exists and that they are elements + if (prev && next) { + function findElementSibling(node, sibling_name) { + for (sibling = node; sibling; sibling = sibling[sibling_name]) { + if (sibling.nodeType == 3 && sibling.nodeValue.length !== 0) + return node; + + if (sibling.nodeType == 1 && !isBookmarkNode(sibling)) + return sibling; + } + + return node; + }; + + // If previous sibling is empty then jump over it + prev = findElementSibling(prev, 'previousSibling'); + next = findElementSibling(next, 'nextSibling'); + + // Compare next and previous nodes + if (compareElements(prev, next)) { + // Append nodes between + for (sibling = prev.nextSibling; sibling && sibling != next;) { + tmpSibling = sibling; + sibling = sibling.nextSibling; + prev.appendChild(tmpSibling); + } + + // Remove next node + dom.remove(next); + + // Move children into prev node + each(tinymce.grep(next.childNodes), function(node) { + prev.appendChild(node); + }); + + return prev; + } + } + + return next; + }; + + function isTextBlock(name) { + return /^(h[1-6]|p|div|pre|address|dl|dt|dd)$/.test(name); + }; + + function getContainer(rng, start) { + var container, offset, lastIdx; + + container = rng[start ? 'startContainer' : 'endContainer']; + offset = rng[start ? 'startOffset' : 'endOffset']; + + if (container.nodeType == 1) { + lastIdx = container.childNodes.length - 1; + + if (!start && offset) + offset--; + + container = container.childNodes[offset > lastIdx ? lastIdx : offset]; + } + + return container; + }; + + function performCaretAction(type, name, vars) { + var i, currentPendingFormats = pendingFormats[type], + otherPendingFormats = pendingFormats[type == 'apply' ? 'remove' : 'apply']; + + function hasPending() { + return pendingFormats.apply.length || pendingFormats.remove.length; + }; + + function resetPending() { + pendingFormats.apply = []; + pendingFormats.remove = []; + }; + + function perform(caret_node) { + // Apply pending formats + each(pendingFormats.apply.reverse(), function(item) { + apply(item.name, item.vars, caret_node); + + // Colored nodes should be underlined so that the color of the underline matches the text color. + if (item.name === 'forecolor' && item.vars.value) + processUnderlineAndColor(caret_node.parentNode); + }); + + // Remove pending formats + each(pendingFormats.remove.reverse(), function(item) { + remove(item.name, item.vars, caret_node); + }); + + dom.remove(caret_node, 1); + resetPending(); + }; + + // Check if it already exists then ignore it + for (i = currentPendingFormats.length - 1; i >= 0; i--) { + if (currentPendingFormats[i].name == name) + return; + } + + currentPendingFormats.push({name : name, vars : vars}); + + // Check if it's in the other type, then remove it + for (i = otherPendingFormats.length - 1; i >= 0; i--) { + if (otherPendingFormats[i].name == name) + otherPendingFormats.splice(i, 1); + } + + // Pending apply or remove formats + if (hasPending()) { + ed.getDoc().execCommand('FontName', false, 'mceinline'); + pendingFormats.lastRng = selection.getRng(); + + // IE will convert the current word + each(dom.select('font,span'), function(node) { + var bookmark; + + if (isCaretNode(node)) { + bookmark = selection.getBookmark(); + perform(node); + selection.moveToBookmark(bookmark); + ed.nodeChanged(); + } + }); + + // Only register listeners once if we need to + if (!pendingFormats.isListening && hasPending()) { + pendingFormats.isListening = true; + function performPendingFormat(node, textNode) { + var rng = dom.createRng(); + perform(node); + + rng.setStart(textNode, textNode.nodeValue.length); + rng.setEnd(textNode, textNode.nodeValue.length); + selection.setRng(rng); + ed.nodeChanged(); + } + var enterKeyPressed = false; + + each('onKeyDown,onKeyUp,onKeyPress,onMouseUp'.split(','), function(event) { + ed[event].addToTop(function(ed, e) { + if (e.keyCode==13 && !e.shiftKey) { + enterKeyPressed = true; + return; + } + // Do we have pending formats and is the selection moved has moved + if (hasPending() && !tinymce.dom.RangeUtils.compareRanges(pendingFormats.lastRng, selection.getRng())) { + var foundCaret = false; + each(dom.select('font,span'), function(node) { + var textNode, rng; + + // Look for marker + if (isCaretNode(node)) { + foundCaret = true; + textNode = node.firstChild; + + // Find the first text node within node + while (textNode && textNode.nodeType != 3) + textNode = textNode.firstChild; + + if (textNode) + performPendingFormat(node, textNode); + else + dom.remove(node); + } + }); + + // no caret - so we are + if (enterKeyPressed && !foundCaret) { + var node = selection.getNode(); + var textNode = node; + + // Find the first text node within node + while (textNode && textNode.nodeType != 3) + textNode = textNode.firstChild; + if (textNode) { + node=textNode.parentNode; + while (!isBlock(node)){ + node=node.parentNode; + } + performPendingFormat(node, textNode); + } + } + + // Always unbind and clear pending styles on keyup + if (e.type == 'keyup' || e.type == 'mouseup') { + resetPending(); + enterKeyPressed=false; + } + } + }); + }); + } + } + }; + }; +})(tinymce); + +tinymce.onAddEditor.add(function(tinymce, ed) { + var filters, fontSizes, dom, settings = ed.settings; + + if (settings.inline_styles) { + fontSizes = tinymce.explode(settings.font_size_style_values); + + function replaceWithSpan(node, styles) { + tinymce.each(styles, function(value, name) { + if (value) + dom.setStyle(node, name, value); + }); + + dom.rename(node, 'span'); + }; + + filters = { + font : function(dom, node) { + replaceWithSpan(node, { + backgroundColor : node.style.backgroundColor, + color : node.color, + fontFamily : node.face, + fontSize : fontSizes[parseInt(node.size) - 1] + }); + }, + + u : function(dom, node) { + replaceWithSpan(node, { + textDecoration : 'underline' + }); + }, + + strike : function(dom, node) { + replaceWithSpan(node, { + textDecoration : 'line-through' + }); + } + }; + + function convert(editor, params) { + dom = editor.dom; + + if (settings.convert_fonts_to_spans) { + tinymce.each(dom.select('font,u,strike', params.node), function(node) { + filters[node.nodeName.toLowerCase()](ed.dom, node); + }); + } + }; + + ed.onPreProcess.add(convert); + ed.onSetContent.add(convert); + + ed.onInit.add(function() { + ed.selection.onSetContent.add(convert); + }); + } +}); + diff --git a/src/static/org_glizy/assets/js/tiny_mce/utils/editable_selects.js b/src/static/org_glizy/assets/js/tiny_mce/utils/editable_selects.js new file mode 100644 index 0000000..4b920f3 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/utils/editable_selects.js @@ -0,0 +1,70 @@ +/** + * editable_selects.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +var TinyMCE_EditableSelects = { + editSelectElm : null, + + init : function() { + var nl = document.getElementsByTagName("select"), i, d = document, o; + + for (i=0; i<nl.length; i++) { + if (nl[i].className.indexOf('mceEditableSelect') != -1) { + o = new Option(tinyMCEPopup.editor.translate('value'), '__mce_add_custom__'); + + o.className = 'mceAddSelectValue'; + + nl[i].options[nl[i].options.length] = o; + nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect; + } + } + }, + + onChangeEditableSelect : function(e) { + var d = document, ne, se = window.event ? window.event.srcElement : e.target; + + if (se.options[se.selectedIndex].value == '__mce_add_custom__') { + ne = d.createElement("input"); + ne.id = se.id + "_custom"; + ne.name = se.name + "_custom"; + ne.type = "text"; + + ne.style.width = se.offsetWidth + 'px'; + se.parentNode.insertBefore(ne, se); + se.style.display = 'none'; + ne.focus(); + ne.onblur = TinyMCE_EditableSelects.onBlurEditableSelectInput; + ne.onkeydown = TinyMCE_EditableSelects.onKeyDown; + TinyMCE_EditableSelects.editSelectElm = se; + } + }, + + onBlurEditableSelectInput : function() { + var se = TinyMCE_EditableSelects.editSelectElm; + + if (se) { + if (se.previousSibling.value != '') { + addSelectValue(document.forms[0], se.id, se.previousSibling.value, se.previousSibling.value); + selectByValue(document.forms[0], se.id, se.previousSibling.value); + } else + selectByValue(document.forms[0], se.id, ''); + + se.style.display = 'inline'; + se.parentNode.removeChild(se.previousSibling); + TinyMCE_EditableSelects.editSelectElm = null; + } + }, + + onKeyDown : function(e) { + e = e || window.event; + + if (e.keyCode == 13) + TinyMCE_EditableSelects.onBlurEditableSelectInput(); + } +}; diff --git a/src/static/org_glizy/assets/js/tiny_mce/utils/form_utils.js b/src/static/org_glizy/assets/js/tiny_mce/utils/form_utils.js new file mode 100644 index 0000000..59da013 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/utils/form_utils.js @@ -0,0 +1,210 @@ +/** + * form_utils.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +var themeBaseURL = tinyMCEPopup.editor.baseURI.toAbsolute('themes/' + tinyMCEPopup.getParam("theme")); + +function getColorPickerHTML(id, target_form_element) { + var h = "", dom = tinyMCEPopup.dom; + + if (label = dom.select('label[for=' + target_form_element + ']')[0]) { + label.id = label.id || dom.uniqueId(); + } + + h += '<a role="button" aria-labelledby="' + id + '_label" id="' + id + '_link" href="javascript:;" onclick="tinyMCEPopup.pickColor(event,\'' + target_form_element +'\');" onmousedown="return false;" class="pickcolor">'; + h += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '">&nbsp;<span id="' + id + '_label" class="mceVoiceLabel mceIconOnly" style="display:none;">' + tinyMCEPopup.getLang('browse') + '</span></span></a>'; + + return h; +} + +function updateColor(img_id, form_element_id) { + document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value; +} + +function setBrowserDisabled(id, state) { + var img = document.getElementById(id); + var lnk = document.getElementById(id + "_link"); + + if (lnk) { + if (state) { + lnk.setAttribute("realhref", lnk.getAttribute("href")); + lnk.removeAttribute("href"); + tinyMCEPopup.dom.addClass(img, 'disabled'); + } else { + if (lnk.getAttribute("realhref")) + lnk.setAttribute("href", lnk.getAttribute("realhref")); + + tinyMCEPopup.dom.removeClass(img, 'disabled'); + } + } +} + +function getBrowserHTML(id, target_form_element, type, prefix) { + var option = prefix + "_" + type + "_browser_callback", cb, html; + + cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback")); + + if (!cb) + return ""; + + html = ""; + html += '<a id="' + id + '_link" href="javascript:openBrowser(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;" class="browse">'; + html += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '">&nbsp;</span></a>'; + + return html; +} + +function openBrowser(img_id, target_form_element, type, option) { + var img = document.getElementById(img_id); + + if (img.className != "mceButtonDisabled") + tinyMCEPopup.openBrowser(target_form_element, type, option); +} + +function selectByValue(form_obj, field_name, value, add_custom, ignore_case) { + if (!form_obj || !form_obj.elements[field_name]) + return; + + if (!value) + value = ""; + + var sel = form_obj.elements[field_name]; + + var found = false; + for (var i=0; i<sel.options.length; i++) { + var option = sel.options[i]; + + if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) { + option.selected = true; + found = true; + } else + option.selected = false; + } + + if (!found && add_custom && value != '') { + var option = new Option(value, value); + option.selected = true; + sel.options[sel.options.length] = option; + sel.selectedIndex = sel.options.length - 1; + } + + return found; +} + +function getSelectValue(form_obj, field_name) { + var elm = form_obj.elements[field_name]; + + if (elm == null || elm.options == null || elm.selectedIndex === -1) + return ""; + + return elm.options[elm.selectedIndex].value; +} + +function addSelectValue(form_obj, field_name, name, value) { + var s = form_obj.elements[field_name]; + var o = new Option(name, value); + s.options[s.options.length] = o; +} + +function addClassesToList(list_id, specific_option) { + // Setup class droplist + var styleSelectElm = document.getElementById(list_id); + var styles = tinyMCEPopup.getParam('theme_advanced_styles', false); + styles = tinyMCEPopup.getParam(specific_option, styles); + + if (styles) { + var stylesAr = styles.split(';'); + + for (var i=0; i<stylesAr.length; i++) { + if (stylesAr != "") { + var key, value; + + key = stylesAr[i].split('=')[0]; + value = stylesAr[i].split('=')[1]; + + styleSelectElm.options[styleSelectElm.length] = new Option(key, value); + } + } + } else { + tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) { + styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']); + }); + } +} + +function isVisible(element_id) { + var elm = document.getElementById(element_id); + + return elm && elm.style.display != "none"; +} + +function convertRGBToHex(col) { + var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi"); + + var rgb = col.replace(re, "$1,$2,$3").split(','); + if (rgb.length == 3) { + r = parseInt(rgb[0]).toString(16); + g = parseInt(rgb[1]).toString(16); + b = parseInt(rgb[2]).toString(16); + + r = r.length == 1 ? '0' + r : r; + g = g.length == 1 ? '0' + g : g; + b = b.length == 1 ? '0' + b : b; + + return "#" + r + g + b; + } + + return col; +} + +function convertHexToRGB(col) { + if (col.indexOf('#') != -1) { + col = col.replace(new RegExp('[^0-9A-F]', 'gi'), ''); + + r = parseInt(col.substring(0, 2), 16); + g = parseInt(col.substring(2, 4), 16); + b = parseInt(col.substring(4, 6), 16); + + return "rgb(" + r + "," + g + "," + b + ")"; + } + + return col; +} + +function trimSize(size) { + return size.replace(/([0-9\.]+)(px|%|in|cm|mm|em|ex|pt|pc)/i, '$1$2'); +} + +function getCSSSize(size) { + size = trimSize(size); + + if (size == "") + return ""; + + // Add px + if (/^[0-9]+$/.test(size)) + size += 'px'; + // Sanity check, IE doesn't like broken values + else if (!(/^[0-9\.]+(px|%|in|cm|mm|em|ex|pt|pc)$/i.test(size))) + return ""; + + return size; +} + +function getStyle(elm, attrib, style) { + var val = tinyMCEPopup.dom.getAttrib(elm, attrib); + + if (val != '') + return '' + val; + + if (typeof(style) == 'undefined') + style = attrib; + + return tinyMCEPopup.dom.getStyle(elm, style); +} diff --git a/src/static/org_glizy/assets/js/tiny_mce/utils/mctabs.js b/src/static/org_glizy/assets/js/tiny_mce/utils/mctabs.js new file mode 100644 index 0000000..458ec86 --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/utils/mctabs.js @@ -0,0 +1,162 @@ +/** + * mctabs.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +function MCTabs() { + this.settings = []; + this.onChange = tinyMCEPopup.editor.windowManager.createInstance('tinymce.util.Dispatcher'); +}; + +MCTabs.prototype.init = function(settings) { + this.settings = settings; +}; + +MCTabs.prototype.getParam = function(name, default_value) { + var value = null; + + value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name]; + + // Fix bool values + if (value == "true" || value == "false") + return (value == "true"); + + return value; +}; + +MCTabs.prototype.showTab =function(tab){ + tab.className = 'current'; + tab.setAttribute("aria-selected", true); + tab.setAttribute("aria-expanded", true); + tab.tabIndex = 0; +}; + +MCTabs.prototype.hideTab =function(tab){ + var t=this; + + tab.className = ''; + tab.setAttribute("aria-selected", false); + tab.setAttribute("aria-expanded", false); + tab.tabIndex = -1; +}; + +MCTabs.prototype.showPanel = function(panel) { + panel.className = 'current'; + panel.setAttribute("aria-hidden", false); +}; + +MCTabs.prototype.hidePanel = function(panel) { + panel.className = 'panel'; + panel.setAttribute("aria-hidden", true); +}; + +MCTabs.prototype.getPanelForTab = function(tabElm) { + return tinyMCEPopup.dom.getAttrib(tabElm, "aria-controls"); +}; + +MCTabs.prototype.displayTab = function(tab_id, panel_id, avoid_focus) { + var panelElm, panelContainerElm, tabElm, tabContainerElm, selectionClass, nodes, i, t = this; + + tabElm = document.getElementById(tab_id); + + if (panel_id === undefined) { + panel_id = t.getPanelForTab(tabElm); + } + + panelElm= document.getElementById(panel_id); + panelContainerElm = panelElm ? panelElm.parentNode : null; + tabContainerElm = tabElm ? tabElm.parentNode : null; + selectionClass = t.getParam('selection_class', 'current'); + + if (tabElm && tabContainerElm) { + nodes = tabContainerElm.childNodes; + + // Hide all other tabs + for (i = 0; i < nodes.length; i++) { + if (nodes[i].nodeName == "LI") { + t.hideTab(nodes[i]); + } + } + + // Show selected tab + t.showTab(tabElm); + } + + if (panelElm && panelContainerElm) { + nodes = panelContainerElm.childNodes; + + // Hide all other panels + for (i = 0; i < nodes.length; i++) { + if (nodes[i].nodeName == "DIV") + t.hidePanel(nodes[i]); + } + + if (!avoid_focus) { + tabElm.focus(); + } + + // Show selected panel + t.showPanel(panelElm); + } +}; + +MCTabs.prototype.getAnchor = function() { + var pos, url = document.location.href; + + if ((pos = url.lastIndexOf('#')) != -1) + return url.substring(pos + 1); + + return ""; +}; + + +//Global instance +var mcTabs = new MCTabs(); + +tinyMCEPopup.onInit.add(function() { + var tinymce = tinyMCEPopup.getWin().tinymce, dom = tinyMCEPopup.dom, each = tinymce.each; + + each(dom.select('div.tabs'), function(tabContainerElm) { + var keyNav; + + dom.setAttrib(tabContainerElm, "role", "tablist"); + + var items = tinyMCEPopup.dom.select('li', tabContainerElm); + var action = function(id) { + mcTabs.displayTab(id, mcTabs.getPanelForTab(id)); + mcTabs.onChange.dispatch(id); + }; + + each(items, function(item) { + dom.setAttrib(item, 'role', 'tab'); + dom.bind(item, 'click', function(evt) { + action(item.id); + }); + }); + + dom.bind(dom.getRoot(), 'keydown', function(evt) { + if (evt.keyCode === 9 && evt.ctrlKey && !evt.altKey) { // Tab + keyNav.moveFocus(evt.shiftKey ? -1 : 1); + tinymce.dom.Event.cancel(evt); + } + }); + + each(dom.select('a', tabContainerElm), function(a) { + dom.setAttrib(a, 'tabindex', '-1'); + }); + + keyNav = tinyMCEPopup.editor.windowManager.createInstance('tinymce.ui.KeyboardNavigation', { + root: tabContainerElm, + items: items, + onAction: action, + actOnFocus: true, + enableLeftRight: true, + enableUpDown: true + }, tinyMCEPopup.dom); + }); +}); \ No newline at end of file diff --git a/src/static/org_glizy/assets/js/tiny_mce/utils/validate.js b/src/static/org_glizy/assets/js/tiny_mce/utils/validate.js new file mode 100644 index 0000000..27cbfab --- /dev/null +++ b/src/static/org_glizy/assets/js/tiny_mce/utils/validate.js @@ -0,0 +1,252 @@ +/** + * validate.js + * + * Copyright 2009, Moxiecode Systems AB + * Released under LGPL License. + * + * License: http://tinymce.moxiecode.com/license + * Contributing: http://tinymce.moxiecode.com/contributing + */ + +/** + // String validation: + + if (!Validator.isEmail('myemail')) + alert('Invalid email.'); + + // Form validation: + + var f = document.forms['myform']; + + if (!Validator.isEmail(f.myemail)) + alert('Invalid email.'); +*/ + +var Validator = { + isEmail : function(s) { + return this.test(s, '^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+@[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$'); + }, + + isAbsUrl : function(s) { + return this.test(s, '^(news|telnet|nttp|file|http|ftp|https)://[-A-Za-z0-9\\.]+\\/?.*$'); + }, + + isSize : function(s) { + return this.test(s, '^[0-9.]+(%|in|cm|mm|em|ex|pt|pc|px)?$'); + }, + + isId : function(s) { + return this.test(s, '^[A-Za-z_]([A-Za-z0-9_])*$'); + }, + + isEmpty : function(s) { + var nl, i; + + if (s.nodeName == 'SELECT' && s.selectedIndex < 1) + return true; + + if (s.type == 'checkbox' && !s.checked) + return true; + + if (s.type == 'radio') { + for (i=0, nl = s.form.elements; i<nl.length; i++) { + if (nl[i].type == "radio" && nl[i].name == s.name && nl[i].checked) + return false; + } + + return true; + } + + return new RegExp('^\\s*$').test(s.nodeType == 1 ? s.value : s); + }, + + isNumber : function(s, d) { + return !isNaN(s.nodeType == 1 ? s.value : s) && (!d || !this.test(s, '^-?[0-9]*\\.[0-9]*$')); + }, + + test : function(s, p) { + s = s.nodeType == 1 ? s.value : s; + + return s == '' || new RegExp(p).test(s); + } +}; + +var AutoValidator = { + settings : { + id_cls : 'id', + int_cls : 'int', + url_cls : 'url', + number_cls : 'number', + email_cls : 'email', + size_cls : 'size', + required_cls : 'required', + invalid_cls : 'invalid', + min_cls : 'min', + max_cls : 'max' + }, + + init : function(s) { + var n; + + for (n in s) + this.settings[n] = s[n]; + }, + + validate : function(f) { + var i, nl, s = this.settings, c = 0; + + nl = this.tags(f, 'label'); + for (i=0; i<nl.length; i++) { + this.removeClass(nl[i], s.invalid_cls); + nl[i].setAttribute('aria-invalid', false); + } + + c += this.validateElms(f, 'input'); + c += this.validateElms(f, 'select'); + c += this.validateElms(f, 'textarea'); + + return c == 3; + }, + + invalidate : function(n) { + this.mark(n.form, n); + }, + + getErrorMessages : function(f) { + var nl, i, s = this.settings, field, msg, values, messages = [], ed = tinyMCEPopup.editor; + nl = this.tags(f, "label"); + for (i=0; i<nl.length; i++) { + if (this.hasClass(nl[i], s.invalid_cls)) { + field = document.getElementById(nl[i].getAttribute("for")); + values = { field: nl[i].textContent }; + if (this.hasClass(field, s.min_cls, true)) { + message = ed.getLang('invalid_data_min'); + values.min = this.getNum(field, s.min_cls); + } else if (this.hasClass(field, s.number_cls)) { + message = ed.getLang('invalid_data_number'); + } else if (this.hasClass(field, s.size_cls)) { + message = ed.getLang('invalid_data_size'); + } else { + message = ed.getLang('invalid_data'); + } + + message = message.replace(/{\#([^}]+)\}/g, function(a, b) { + return values[b] || '{#' + b + '}'; + }); + messages.push(message); + } + } + return messages; + }, + + reset : function(e) { + var t = ['label', 'input', 'select', 'textarea']; + var i, j, nl, s = this.settings; + + if (e == null) + return; + + for (i=0; i<t.length; i++) { + nl = this.tags(e.form ? e.form : e, t[i]); + for (j=0; j<nl.length; j++) { + this.removeClass(nl[j], s.invalid_cls); + nl[j].setAttribute('aria-invalid', false); + } + } + }, + + validateElms : function(f, e) { + var nl, i, n, s = this.settings, st = true, va = Validator, v; + + nl = this.tags(f, e); + for (i=0; i<nl.length; i++) { + n = nl[i]; + + this.removeClass(n, s.invalid_cls); + + if (this.hasClass(n, s.required_cls) && va.isEmpty(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.number_cls) && !va.isNumber(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.int_cls) && !va.isNumber(n, true)) + st = this.mark(f, n); + + if (this.hasClass(n, s.url_cls) && !va.isAbsUrl(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.email_cls) && !va.isEmail(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.size_cls) && !va.isSize(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.id_cls) && !va.isId(n)) + st = this.mark(f, n); + + if (this.hasClass(n, s.min_cls, true)) { + v = this.getNum(n, s.min_cls); + + if (isNaN(v) || parseInt(n.value) < parseInt(v)) + st = this.mark(f, n); + } + + if (this.hasClass(n, s.max_cls, true)) { + v = this.getNum(n, s.max_cls); + + if (isNaN(v) || parseInt(n.value) > parseInt(v)) + st = this.mark(f, n); + } + } + + return st; + }, + + hasClass : function(n, c, d) { + return new RegExp('\\b' + c + (d ? '[0-9]+' : '') + '\\b', 'g').test(n.className); + }, + + getNum : function(n, c) { + c = n.className.match(new RegExp('\\b' + c + '([0-9]+)\\b', 'g'))[0]; + c = c.replace(/[^0-9]/g, ''); + + return c; + }, + + addClass : function(n, c, b) { + var o = this.removeClass(n, c); + n.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c; + }, + + removeClass : function(n, c) { + c = n.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' '); + return n.className = c != ' ' ? c : ''; + }, + + tags : function(f, s) { + return f.getElementsByTagName(s); + }, + + mark : function(f, n) { + var s = this.settings; + + this.addClass(n, s.invalid_cls); + n.setAttribute('aria-invalid', 'true'); + this.markLabels(f, n, s.invalid_cls); + + return false; + }, + + markLabels : function(f, n, ic) { + var nl, i; + + nl = this.tags(f, "label"); + for (i=0; i<nl.length; i++) { + if (nl[i].getAttribute("for") == n.id || nl[i].htmlFor == n.id) + this.addClass(nl[i], ic); + } + + return null; + } +}; diff --git a/src/static/timelinejs/css/loading.gif b/src/static/timelinejs/css/loading.gif new file mode 100755 index 0000000000000000000000000000000000000000..d3eef2d69f7665878adab097a5fd3948caf02e07 GIT binary patch literal 6909 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 literal 0 HcmV?d00001 diff --git a/src/static/timelinejs/css/themes/dark.css b/src/static/timelinejs/css/themes/dark.css new file mode 100755 index 0000000..ff435c2 --- /dev/null +++ b/src/static/timelinejs/css/themes/dark.css @@ -0,0 +1,281 @@ +.vco-storyjs{}.vco-storyjs div *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;} +.vco-storyjs h1,.vco-storyjs h2,.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6,.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs pre,.vco-storyjs a,.vco-storyjs abbr,.vco-storyjs acronym,.vco-storyjs address,.vco-storyjs cite,.vco-storyjs code,.vco-storyjs del,.vco-storyjs dfn,.vco-storyjs em,.vco-storyjs img,.vco-storyjs q,.vco-storyjs s,.vco-storyjs samp,.vco-storyjs small,.vco-storyjs strike,.vco-storyjs strong,.vco-storyjs sub,.vco-storyjs sup,.vco-storyjs tt,.vco-storyjs var,.vco-storyjs dd,.vco-storyjs dl,.vco-storyjs dt,.vco-storyjs li,.vco-storyjs ol,.vco-storyjs ul,.vco-storyjs fieldset,.vco-storyjs form,.vco-storyjs label,.vco-storyjs legend,.vco-storyjs button,.vco-storyjs table,.vco-storyjs caption,.vco-storyjs tbody,.vco-storyjs tfoot,.vco-storyjs thead,.vco-storyjs tr,.vco-storyjs th,.vco-storyjs td,.vco-storyjs .vco-container,.vco-storyjs .content-container,.vco-storyjs .media,.vco-storyjs .text,.vco-storyjs .vco-slider,.vco-storyjs .slider,.vco-storyjs .date,.vco-storyjs .title,.vco-storyjs .messege,.vco-storyjs .map,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .vco-feedback,.vco-storyjs .vco-feature,.vco-storyjs .toolbar,.vco-storyjs .marker,.vco-storyjs .dot,.vco-storyjs .line,.vco-storyjs .flag,.vco-storyjs .time,.vco-storyjs .era,.vco-storyjs .major,.vco-storyjs .minor,.vco-storyjs .vco-navigation,.vco-storyjs .start,.vco-storyjs .active{margin:0;padding:0;border:0;font-weight:normal;font-style:normal;font-size:100%;line-height:1;font-family:inherit;width:auto;float:none;} +.vco-storyjs h1,.vco-storyjs h2,.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6{clear:none;} +.vco-storyjs table{border-collapse:collapse;border-spacing:0;} +.vco-storyjs ol,.vco-storyjs ul{list-style:none;} +.vco-storyjs q:before,.vco-storyjs q:after,.vco-storyjs blockquote:before,.vco-storyjs blockquote:after{content:"";} +.vco-storyjs a:focus{outline:thin dotted;} +.vco-storyjs a:hover,.vco-storyjs a:active{outline:0;} +.vco-storyjs article,.vco-storyjs aside,.vco-storyjs details,.vco-storyjs figcaption,.vco-storyjs figure,.vco-storyjs footer,.vco-storyjs header,.vco-storyjs hgroup,.vco-storyjs nav,.vco-storyjs section{display:block;} +.vco-storyjs audio,.vco-storyjs canvas,.vco-storyjs video{display:inline-block;*display:inline;*zoom:1;} +.vco-storyjs audio:not([controls]){display:none;} +.vco-storyjs div{max-width:none;} +.vco-storyjs sub,.vco-storyjs sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;} +.vco-storyjs sup{top:-0.5em;} +.vco-storyjs sub{bottom:-0.25em;} +.vco-storyjs img{border:0;-ms-interpolation-mode:bicubic;} +.vco-storyjs button,.vco-storyjs input,.vco-storyjs select,.vco-storyjs textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;} +.vco-storyjs button,.vco-storyjs input{line-height:normal;*overflow:visible;} +.vco-storyjs button::-moz-focus-inner,.vco-storyjs input::-moz-focus-inner{border:0;padding:0;} +.vco-storyjs button,.vco-storyjs input[type="button"],.vco-storyjs input[type="reset"],.vco-storyjs input[type="submit"]{cursor:pointer;-webkit-appearance:button;} +.vco-storyjs input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;} +.vco-storyjs input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;} +.vco-storyjs textarea{overflow:auto;vertical-align:top;} +.vco-storyjs{font-family:"Georgia",Times New Roman,Times,serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;} +.vco-storyjs h1.date,.vco-storyjs h2.date,.vco-storyjs h3.date,.vco-storyjs h4.date,.vco-storyjs h5.date,.vco-storyjs h6.date{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:"Georgia",Times New Roman,Times,serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:"Georgia",Times New Roman,Times,serif;} +.tooltip{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;} +.thumbnail{background-image:url(themes/timeline-dark.png?v3.4);} +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.thumbnail{background-image:url(themes/timeline-dark@2x.png?v4.3);background-size:352px 260px;}}.vco-storyjs{font-size:15px;font-weight:normal;line-height:20px;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;}.vco-storyjs p{font-size:15px;font-weight:normal;line-height:20px;margin-bottom:20px;color:#aaaaaa;}.vco-storyjs p small{font-size:12px;line-height:17px;} +.vco-storyjs p:first-child{margin-top:20px;} +.vco-storyjs .vco-navigation p{color:#999999;} +.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{margin-bottom:15px;} +.vco-storyjs .vco-feature p{color:#aaaaaa;} +.vco-storyjs .vco-feature blockquote,.vco-storyjs .vco-feature blockquote p{color:#ffffff;} +.vco-storyjs .date a,.vco-storyjs .title a{color:#999999;} +.vco-storyjs .hyphenate{-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;} +.vco-storyjs h1,.vco-storyjs h2,.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6{font-weight:normal;color:#ffffff;text-transform:none;}.vco-storyjs h1 a,.vco-storyjs h2 a,.vco-storyjs h3 a,.vco-storyjs h4 a,.vco-storyjs h5 a,.vco-storyjs h6 a{color:#999999;} +.vco-storyjs h1 small,.vco-storyjs h2 small,.vco-storyjs h3 small,.vco-storyjs h4 small,.vco-storyjs h5 small,.vco-storyjs h6 small{color:#999999;} +.vco-storyjs h1.date,.vco-storyjs h2.date,.vco-storyjs h3.date,.vco-storyjs h4.date,.vco-storyjs h5.date,.vco-storyjs h6.date{font-weight:bold;} +.vco-storyjs h2.start{font-size:36px;line-height:38px;margin-bottom:15px;} +.vco-storyjs h1{margin-bottom:15px;font-size:32px;line-height:34px;}.vco-storyjs h1 small{font-size:18px;} +.vco-storyjs h2{margin-bottom:15px;font-size:28px;line-height:30px;}.vco-storyjs h2 small{font-size:14px;line-height:16px;} +.vco-storyjs h2.date{font-size:16px;line-height:18px;margin-bottom:3.75px;color:#999999;} +.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6{line-height:40px;}.vco-storyjs h3 .active,.vco-storyjs h4 .active,.vco-storyjs h5 .active,.vco-storyjs h6 .active{color:#0bd4e3;} +.vco-storyjs h3{font-size:28px;line-height:30px;}.vco-storyjs h3 small{font-size:14px;} +.vco-storyjs h4{font-size:20px;line-height:22px;}.vco-storyjs h4 small{font-size:12px;} +.vco-storyjs h5{font-size:16px;line-height:18px;} +.vco-storyjs h6{font-size:13px;line-height:14px;text-transform:uppercase;} +.vco-storyjs strong{font-weight:bold;font-style:inherit;} +.vco-storyjs em{font-style:italic;font-weight:inherit;} +.vco-storyjs Q{quotes:'„' '“';font-style:italic;} +.vco-storyjs blockquote,.vco-storyjs blockquote p{font-size:24px;line-height:32px;text-align:left;margin-bottom:6px;padding-top:10px;background-color:#1a1a1a;color:#ffffff;} +.vco-storyjs .credit{color:#999999;text-align:right;font-size:10px;line-height:10px;display:block;margin:0 auto;clear:both;} +.vco-storyjs .caption{text-align:left;margin-top:5px;color:#aaaaaa;font-size:11px;line-height:14px;clear:both;} +.vco-storyjs.vco-right-to-left h1,.vco-storyjs.vco-right-to-left h2,.vco-storyjs.vco-right-to-left h3,.vco-storyjs.vco-right-to-left h4,.vco-storyjs.vco-right-to-left h5,.vco-storyjs.vco-right-to-left h6,.vco-storyjs.vco-right-to-left p,.vco-storyjs.vco-right-to-left blockquote,.vco-storyjs.vco-right-to-left pre,.vco-storyjs.vco-right-to-left a,.vco-storyjs.vco-right-to-left abbr,.vco-storyjs.vco-right-to-left acronym,.vco-storyjs.vco-right-to-left address,.vco-storyjs.vco-right-to-left cite,.vco-storyjs.vco-right-to-left code,.vco-storyjs.vco-right-to-left del,.vco-storyjs.vco-right-to-left dfn,.vco-storyjs.vco-right-to-left em,.vco-storyjs.vco-right-to-left img,.vco-storyjs.vco-right-to-left q,.vco-storyjs.vco-right-to-left s,.vco-storyjs.vco-right-to-left samp,.vco-storyjs.vco-right-to-left small,.vco-storyjs.vco-right-to-left strike,.vco-storyjs.vco-right-to-left strong,.vco-storyjs.vco-right-to-left sub,.vco-storyjs.vco-right-to-left sup,.vco-storyjs.vco-right-to-left tt,.vco-storyjs.vco-right-to-left var,.vco-storyjs.vco-right-to-left dd,.vco-storyjs.vco-right-to-left dl,.vco-storyjs.vco-right-to-left dt,.vco-storyjs.vco-right-to-left li,.vco-storyjs.vco-right-to-left ol,.vco-storyjs.vco-right-to-left ul,.vco-storyjs.vco-right-to-left fieldset,.vco-storyjs.vco-right-to-left form,.vco-storyjs.vco-right-to-left label,.vco-storyjs.vco-right-to-left legend,.vco-storyjs.vco-right-to-left button,.vco-storyjs.vco-right-to-left table,.vco-storyjs.vco-right-to-left caption,.vco-storyjs.vco-right-to-left tbody,.vco-storyjs.vco-right-to-left tfoot,.vco-storyjs.vco-right-to-left thead,.vco-storyjs.vco-right-to-left tr,.vco-storyjs.vco-right-to-left th,.vco-storyjs.vco-right-to-left td{direction:rtl;} +.tooltip{position:absolute;z-index:205;display:block;visibility:visible;padding:5px;opacity:0;filter:alpha(opacity=0);font-size:15px;font-weight:bold;line-height:20px;font-size:12px;line-height:12px;} +.tooltip.in{opacity:0.8;filter:alpha(opacity=80);} +.tooltip.top{margin-top:-2px;} +.tooltip.right{margin-left:2px;} +.tooltip.bottom{margin-top:2px;} +.tooltip.left{margin-left:-2px;} +.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;} +.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;} +.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;} +.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;} +.tooltip-inner{max-width:200px;padding:3px 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;} +@media only screen and (max-width:480px),only screen and (max-device-width:480px){.vco-slider .nav-next,.vco-slider .nav-previous{display:none;}}@media (max-width:640px){}.vco-skinny .vco-slider .slider-item .content .layout-text-media .text .container{text-align:center !important;} +.vco-skinny .vco-slider .slider-item .content .layout-text-media h2,.vco-skinny .vco-slider .slider-item .content .layout-text-media h3{display:block !important;width:100% !important;text-align:center !important;} +.vco-skinny .vco-slider .slider-item .content .content-container{display:block;}.vco-skinny .vco-slider .slider-item .content .content-container .text{width:100%;max-width:100%;min-width:120px;display:block;}.vco-skinny .vco-slider .slider-item .content .content-container .text .container{display:block;-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;} +.vco-skinny .vco-slider .slider-item .content .content-container .media{width:100%;min-width:50%;float:none;}.vco-skinny .vco-slider .slider-item .content .content-container .media .media-wrapper{margin-left:0px;margin-right:0px;width:100%;display:block;} +.vco-skinny.vco-notouch .vco-slider .nav-previous,.vco-skinny.vco-notouch .vco-slider .nav-next{z-index:203;}.vco-skinny.vco-notouch .vco-slider .nav-previous .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-next .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-previous .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next .nav-container .title{filter:alpha(opacity=1);-khtml-opacity:0.01;-moz-opacity:0.01;opacity:0.01;} +.vco-skinny.vco-notouch .vco-slider .nav-previous .nav-container .icon,.vco-skinny.vco-notouch .vco-slider .nav-next .nav-container .icon{filter:alpha(opacity=15);-khtml-opacity:0.15;-moz-opacity:0.15;opacity:0.15;} +.vco-skinny.vco-notouch .vco-slider .nav-previous .icon{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-208px 0;width:24px;height:24px;overflow:hidden;margin-left:10px;} +.vco-skinny.vco-notouch .vco-slider .nav-next .icon{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-232px 0;width:24px;height:24px;overflow:hidden;margin-left:66px;} +.vco-skinny.vco-notouch .vco-slider .nav-previous:hover,.vco-skinny.vco-notouch .vco-slider .nav-next:hover{color:#aaaaaa !important;background-color:#aaaaaa;background-color:rgba(255, 255, 255, 0.65);-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;}.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .icon,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .icon,.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .title{-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;font-weight:bold;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .title{padding-bottom:5px;} +.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .title{padding-left:5px;padding-right:5px;} +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-skinny.vco-notouch .vco-slider .nav-previous .icon{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-208px 0;width:24px;height:24px;overflow:hidden;} .vco-skinny.vco-notouch .vco-slider .nav-next .icon{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-232px 0;width:24px;height:24px;overflow:hidden;}}.vco-slider{width:100%;height:100%;overflow:hidden;}.vco-slider .slider-container-mask{text-align:center;width:100%;height:100%;overflow:hidden;}.vco-slider .slider-container-mask .slider-container{position:absolute;top:0px;left:-2160px;width:100%;height:100%;text-align:center;display:block;}.vco-slider .slider-container-mask .slider-container .slider-item-container{display:table-cell;vertical-align:middle;} +.vco-notouch .vco-slider .nav-previous:hover,.vco-notouch .vco-slider .nav-next:hover{color:#aaaaaa;cursor:pointer;} +.vco-notouch .vco-slider .nav-previous:hover .icon{margin-left:10px;} +.vco-notouch .vco-slider .nav-next:hover .icon{margin-left:66px;} +.vco-notouch .vco-slider .slider-item .content .content-container .media .media-container .wikipedia h4 a:hover{color:#0bd4e3;text-decoration:none;} +.vco-notouch .vco-slider .slider-item .content .content-container .created-at:hover{filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-notouch .vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments a:hover{text-decoration:none;}.vco-notouch .vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments a:hover h5{text-decoration:underline;} +.vco-slider img,.vco-slider embed,.vco-slider object,.vco-slider video,.vco-slider iframe{max-width:100%;} +.vco-slider .nav-previous,.vco-slider .nav-next{position:absolute;top:0px;width:100px;color:#DBDBDB;font-size:11px;}.vco-slider .nav-previous .nav-container,.vco-slider .nav-next .nav-container{height:100px;width:100px;position:absolute;} +.vco-slider .nav-previous .icon,.vco-slider .nav-next .icon{margin-top:12px;margin-bottom:15px;} +.vco-slider .nav-previous .date,.vco-slider .nav-next .date,.vco-slider .nav-previous .title,.vco-slider .nav-next .title{line-height:14px;}.vco-slider .nav-previous .date a,.vco-slider .nav-next .date a,.vco-slider .nav-previous .title a,.vco-slider .nav-next .title a{color:#999999;} +.vco-slider .nav-previous .date small,.vco-slider .nav-next .date small,.vco-slider .nav-previous .title small,.vco-slider .nav-next .title small{display:none;} +.vco-slider .nav-previous .date,.vco-slider .nav-next .date{font-size:13px;line-height:13px;font-weight:bold;text-transform:uppercase;margin-bottom:5px;} +.vco-slider .nav-previous .title,.vco-slider .nav-next .title{font-size:11px;line-height:13px;} +.vco-slider .nav-previous{float:left;text-align:left;}.vco-slider .nav-previous .icon{margin-left:15px;background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-160px 0;width:24px;height:24px;overflow:hidden;} +.vco-slider .nav-previous .date,.vco-slider .nav-previous .title{text-align:left;padding-left:15px;} +.vco-slider .nav-next{float:right;text-align:right;}.vco-slider .nav-next .icon{margin-left:61px;background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-184px 0;width:24px;height:24px;overflow:hidden;} +.vco-slider .nav-next .date,.vco-slider .nav-next .title{text-align:right;padding-right:15px;} +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-slider .nav-previous .icon{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-160px 0;width:24px;height:24px;overflow:hidden;} .vco-slider .nav-next .icon{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-184px 0;width:24px;height:24px;overflow:hidden;}}.vco-slider .slider-item{position:absolute;width:700px;height:100%;padding:0px;margin:0px;display:table;overflow-y:auto;}.vco-slider .slider-item .content{display:table-cell;vertical-align:middle;}.vco-slider .slider-item .content .pad-top .text .container{padding-top:15px;} +.vco-slider .slider-item .content .pad-right .text .container{padding-right:15px;} +.vco-slider .slider-item .content .pad-left .text .container{padding-left:30px;} +.vco-slider .slider-item .content .pad-left .media.text-media .media-wrapper .media-container{border:none;background-color:#1a1a1a;} +.vco-slider .slider-item .content .content-container{display:table;vertical-align:middle;}.vco-slider .slider-item .content .content-container .text{width:40%;max-width:50%;min-width:120px;display:table-cell;vertical-align:middle;}.vco-slider .slider-item .content .content-container .text .container{display:table-cell;vertical-align:middle;text-align:left;}.vco-slider .slider-item .content .content-container .text .container p{-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;} +.vco-slider .slider-item .content .content-container .text .container h2.date{font-size:15px;line-height:15px;font-weight:normal;} +.vco-slider .slider-item .content .content-container .text .container .slide-tag{font-size:11px;font-weight:bold;color:#1a1a1a;background-color:#cccccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;vertical-align:baseline;white-space:nowrap;line-height:11px;padding:1px 3px 1px;margin-left:7.5px;margin-bottom:7.5px;} +.vco-slider .slider-item .content .content-container .media{width:100%;min-width:50%;float:left;}.vco-slider .slider-item .content .content-container .media .media-wrapper{display:inline-block;margin-left:auto;margin-right:auto;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container{display:inline-block;line-height:0px;padding:0px;max-height:100%;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-frame,.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-image img{border:1px solid;border-color:#333333 #999999 #999999 #333333;background-color:#1a1a1a;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-frame iframe{background-color:#1a1a1a;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .soundcloud{border:0;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-image{display:inline-block;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow{position:relative;z-index:1;background:#1a1a1a;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow:before,.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow:after{z-index:-1;position:absolute;content:"";bottom:15px;left:10px;width:50%;top:80%;max-width:300px;background:#999999;-webkit-box-shadow:0 15px 10px #999999;-moz-box-shadow:0 15px 10px #999999;box-shadow:0 15px 10px #999999;-webkit-transform:rotate(-2deg);-moz-transform:rotate(-2deg);-ms-transform:rotate(-2deg);-o-transform:rotate(-2deg);transform:rotate(-2deg);} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow::after{-webkit-transform:rotate(2deg);-moz-transform:rotate(2deg);-ms-transform:rotate(2deg);-o-transform:rotate(2deg);transform:rotate(2deg);right:10px;left:auto;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text{display:table;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text .container{display:table-cell;vertical-align:middle;font-size:15px;line-height:20px;color:#aaaaaa;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text .container p{margin-bottom:20px;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia{font-size:15px;line-height:20px;text-align:left;margin-left:auto;margin-right:auto;margin-bottom:15px;clear:both;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia .wiki-source{margin-bottom:15px;font-size:13px;line-height:19px;font-style:italic;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia h4{border-bottom:1px solid #333333;margin-bottom:5px;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia h4 a{color:#ffffff;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia p{font-size:13px;line-height:19px;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map{line-height:normal;z-index:200;text-align:left;background-color:#1a1a1a;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map img{max-height:none !important;max-width:none !important;border:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .google-map{height:100%;width:100%;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution{position:absolute;z-index:201;bottom:0px;width:100%;overflow:hidden;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution .attribution-text{height:19px;overflow:hidden;-webkit-user-select:none;line-height:19px;margin-right:60px;padding-left:65px;font-family:Arial,sans-serif;font-size:10px;color:#444;white-space:nowrap;color:#1a1a1a;text-shadow:1px 1px 1px #aaaaaa;text-align:center;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution .attribution-text a{color:#1a1a1a !important;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .credit{color:#999999;text-align:right;display:block;margin:0 auto;margin-top:6px;font-size:10px;line-height:13px;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .caption{text-align:left;margin-top:10px;color:#aaaaaa;font-size:11px;line-height:14px;text-rendering:optimizeLegibility;word-wrap:break-word;} +.vco-slider .slider-item .content .content-container .media.text-media .media-wrapper .media-container{border:none;background-color:#1a1a1a;} +.vco-slider .slider-item .content .content-container .created-at{width:24px;height:24px;overflow:hidden;margin-left:7.5px;margin-top:2px;display:inline-block;float:right;filter:alpha(opacity=25);-khtml-opacity:0.25;-moz-opacity:0.25;opacity:0.25;} +.vco-slider .slider-item .content .content-container .storify .created-at{background-repeat:no-repeat;background-position:-328px -96px;} +.vco-slider .slider-item .content .content-container .twitter .created-at{background-repeat:no-repeat;background-position:-256px -24px;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content{font-size:13px;line-height:19px;margin-bottom:6px;padding-top:10px;background-color:#1a1a1a;color:#aaaaaa;}.vco-slider .slider-item .content .content-container .googleplus .googleplus-content p{font-size:13px;line-height:19px;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-title{font-size:24px;line-height:32px;margin-bottom:6px;padding-top:10px;background-color:#1a1a1a;color:#ffffff;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-annotation{font-size:15px;line-height:20px;color:#ffffff;border-bottom:1px solid #e3e3e3;padding-bottom:7.5px;margin-bottom:7.5px;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments{border-top:1px solid #e3e3e3;padding-top:15px;margin-top:15px;border-bottom:1px solid #e3e3e3;padding-bottom:15px;margin-bottom:15px;*zoom:1;}.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments:before,.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments:after{display:table;content:"";} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments:after{clear:both;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments h5{margin-bottom:5px;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments div{width:50%;padding-left:15px;display:inline-block;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments p{font-size:11px;line-height:14px;margin-bottom:5px;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments img{float:left;display:block;bottom:0;left:0;margin:auto;position:relative;right:0;top:0;width:40%;} +.vco-slider .slider-item .content .content-container .googleplus .proflinkPrefix{color:#0bd4e3;} +.vco-slider .slider-item .content .content-container .googleplus .created-at{background-repeat:no-repeat;background-position:-208px -72px;} +.vco-slider .slider-item .content .content-container .twitter,.vco-slider .slider-item .content .content-container .plain-text-quote,.vco-slider .slider-item .content .content-container .storify,.vco-slider .slider-item .content .content-container .googleplus{text-align:left;margin-left:auto;margin-right:auto;margin-bottom:15px;clear:both;}.vco-slider .slider-item .content .content-container .twitter blockquote,.vco-slider .slider-item .content .content-container .plain-text-quote blockquote,.vco-slider .slider-item .content .content-container .storify blockquote,.vco-slider .slider-item .content .content-container .googleplus blockquote{color:#aaaaaa;}.vco-slider .slider-item .content .content-container .twitter blockquote p,.vco-slider .slider-item .content .content-container .plain-text-quote blockquote p,.vco-slider .slider-item .content .content-container .storify blockquote p,.vco-slider .slider-item .content .content-container .googleplus blockquote p{font-size:24px;line-height:32px;margin-bottom:6px;padding-top:10px;background-color:#1a1a1a;color:#ffffff;} +.vco-slider .slider-item .content .content-container .twitter blockquote .quote-mark,.vco-slider .slider-item .content .content-container .plain-text-quote blockquote .quote-mark,.vco-slider .slider-item .content .content-container .storify blockquote .quote-mark,.vco-slider .slider-item .content .content-container .googleplus blockquote .quote-mark{color:#aaaaaa;} +.vco-slider .slider-item .content .content-container.layout-text-media .text-media{border-top:1px solid #e3e3e3;padding-top:15px;padding-right:0;} +.vco-slider .slider-item .content .content-container.layout-text-media.pad-left .text-media{padding-right:15px;padding-top:0;border-right:1px solid #e3e3e3;border-top:0px solid #e3e3e3;} +.vco-slider .slider-item .content .content-container.layout-text{width:100%;}.vco-slider .slider-item .content .content-container.layout-text .text{width:100%;max-width:100%;}.vco-slider .slider-item .content .content-container.layout-text .text .container{display:block;vertical-align:middle;padding:0px;width:90%;text-align:left;margin-left:auto;margin-right:auto;} +.vco-slider .slider-item .content .content-container.layout-media{width:100%;}.vco-slider .slider-item .content .content-container.layout-media .text{width:100%;height:100%;max-width:100%;display:block;text-align:center;}.vco-slider .slider-item .content .content-container.layout-media .text .container{display:block;text-align:center;width:100%;margin-left:none;margin-right:none;} +.vco-slider .slider-item .content .content-container.layout-media .media{width:100%;min-width:50%;float:none;}.vco-slider .slider-item .content .content-container.layout-media .media .media-wrapper .media-container{margin-left:auto;margin-right:auto;line-height:0px;padding:0px;} +.vco-slider .slider-item .content .content-container.layout-media .twitter,.vco-slider .slider-item .content .content-container.layout-media .wikipedia,.vco-slider .slider-item .content .content-container.layout-media .googleplus{max-width:70%;} +.storyjs-embed{background-color:#1a1a1a;margin-bottom:20px;border:1px solid #333333;padding-top:20px;padding-bottom:20px;clear:both;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;-webkit-box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);-moz-box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);} +.storyjs-embed.full-embed{overflow:hidden;border:0 !important;padding:0 !important;margin:0 !important;clear:both;-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important;-webkit-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;-moz-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;} +.storyjs-embed.sized-embed{overflow:hidden;border:1px solid #333333;padding-top:7px;padding-bottom:7px;margin:0 !important;clear:both;-webkit-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;-moz-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;} +.vco-storyjs{width:100%;height:100%;padding:0px;margin:0px;background-color:#1a1a1a;position:absolute;z-index:100;clear:both;overflow:hidden;}.vco-storyjs .vmm-clear:before,.vco-storyjs .vmm-clear:after{content:"";display:table;} +.vco-storyjs .vmm-clear:after{clear:both;} +.vco-storyjs .vmm-clear{*zoom:1;} +.vco-storyjs .vco-feature{width:100%;}.vco-storyjs .vco-feature .slider,.vco-storyjs .vco-feature .vco-slider{width:100%;float:left;position:relative;z-index:10;padding-top:15px;-webkit-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);} +.vco-storyjs .vco-feedback{position:absolute;display:table;overflow:hidden;top:0px;left:0px;z-index:205;width:100%;height:100%;} +.vco-storyjs div.vco-loading,.vco-storyjs div.vco-explainer{display:table;text-align:center;min-width:100px;margin-top:15px;height:100%;width:100%;background-color:#1a1a1a;}.vco-storyjs div.vco-loading .vco-loading-container,.vco-storyjs div.vco-explainer .vco-loading-container,.vco-storyjs div.vco-loading .vco-explainer-container,.vco-storyjs div.vco-explainer .vco-explainer-container{display:table-cell;vertical-align:middle;}.vco-storyjs div.vco-loading .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-loading-icon{display:block;background-repeat:no-repeat;vertical-align:middle;margin-left:auto;margin-right:auto;text-align:center;background-image:url(themes/loading.gif?v3.4);width:28px;height:28px;} +.vco-storyjs div.vco-loading .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-gesture-icon{display:block;vertical-align:middle;margin-left:auto;margin-right:auto;text-align:center;background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-160px -160px;width:48px;height:48px;} +.vco-storyjs div.vco-loading .vco-loading-container .vco-message,.vco-storyjs div.vco-explainer .vco-loading-container .vco-message,.vco-storyjs div.vco-loading .vco-explainer-container .vco-message,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-message{display:block;} +.vco-storyjs div.vco-loading .vco-loading-container .vco-message,.vco-storyjs div.vco-explainer .vco-loading-container .vco-message,.vco-storyjs div.vco-loading .vco-explainer-container .vco-message,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-message,.vco-storyjs div.vco-loading .vco-loading-container .vco-message p,.vco-storyjs div.vco-explainer .vco-loading-container .vco-message p,.vco-storyjs div.vco-loading .vco-explainer-container .vco-message p,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-message p{text-align:center;font-size:11px;line-height:13px;text-transform:uppercase;margin-top:7.5px;margin-bottom:7.5px;} +.vco-storyjs div.vco-explainer{background-color:transparent;} +.vco-storyjs .vco-bezel{background-color:#aaaaaa;background-color:rgba(255, 255, 255, 0.8);width:80px;height:50px;padding:50px;padding-top:25px;padding:25px 20px 50px 20px;margin:auto;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;}.vco-storyjs .vco-bezel .vco-message,.vco-storyjs .vco-bezel .vco-message p{color:#1a1a1a;font-weight:bold;} +.vco-storyjs .vco-container.vco-main{position:absolute;top:0px;left:0px;padding-bottom:3px;width:auto;height:auto;margin:0px;clear:both;} +.vco-storyjs img,.vco-storyjs embed,.vco-storyjs object,.vco-storyjs video,.vco-storyjs iframe{max-width:100%;} +.vco-storyjs img{max-height:100%;border:1px solid #999999;} +.vco-storyjs a{color:#0bd4e3;text-decoration:none;} +.vco-storyjs a:hover{color:#07909a;text-decoration:underline;} +.vco-storyjs .vcard{float:right;margin-bottom:15px;}.vco-storyjs .vcard a{color:#aaaaaa;} +.vco-storyjs .vcard a:hover{text-decoration:none;}.vco-storyjs .vcard a:hover .fn{text-decoration:underline;} +.vco-storyjs .vcard .fn,.vco-storyjs .vcard .nickname{padding-left:42px;} +.vco-storyjs .vcard .fn{display:block;font-weight:bold;} +.vco-storyjs .vcard .nickname{margin-top:1px;display:block;color:#aaaaaa;} +.vco-storyjs .vcard .avatar{float:left;display:block;width:32px;height:32px;}.vco-storyjs .vcard .avatar img{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;} +.vco-storyjs .thumbnail{width:24px;height:24px;overflow:hidden;float:left;margin:0;margin-right:1px;margin-top:6px;border:0;padding:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} +.vco-storyjs a.thumbnail:hover{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} +.vco-storyjs .thumbnail.thumb-plaintext{background-repeat:no-repeat;background-position:-280px -48px;} +.vco-storyjs .thumbnail.thumb-quote{background-repeat:no-repeat;background-position:-232px -48px;} +.vco-storyjs .thumbnail.thumb-document{background-repeat:no-repeat;background-position:-256px -48px;} +.vco-storyjs .thumbnail.thumb-photo{background-repeat:no-repeat;background-position:-280px -24px;border:0;}.vco-storyjs .thumbnail.thumb-photo img{border:0px none #333333 !important;} +.vco-storyjs .thumbnail.thumb-twitter{background-repeat:no-repeat;background-position:-256px -24px;} +.vco-storyjs .thumbnail.thumb-vimeo{background-repeat:no-repeat;background-position:-328px -48px;} +.vco-storyjs .thumbnail.thumb-youtube{background-repeat:no-repeat;background-position:-328px -72px;} +.vco-storyjs .thumbnail.thumb-video{background-repeat:no-repeat;background-position:-328px -24px;} +.vco-storyjs .thumbnail.thumb-audio{background-repeat:no-repeat;background-position:-304px -24px;} +.vco-storyjs .thumbnail.thumb-map{background-repeat:no-repeat;background-position:-208px -48px;} +.vco-storyjs .thumbnail.thumb-website{background-repeat:no-repeat;background-position:-232px -24px;} +.vco-storyjs .thumbnail.thumb-link{background-repeat:no-repeat;background-position:-184px -72px;} +.vco-storyjs .thumbnail.thumb-wikipedia{background-repeat:no-repeat;background-position:-184px -48px;} +.vco-storyjs .thumbnail.thumb-storify{background-repeat:no-repeat;background-position:-328px -96px;} +.vco-storyjs .thumbnail.thumb-googleplus{background-repeat:no-repeat;background-position:-208px -72px;} +.vco-storyjs thumbnail.thumb-instagram{background-repeat:no-repeat;background-position:-208px -96px;} +.vco-storyjs thumbnail.thumb-instagram-full{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-232px -96px;width:48px;height:24px;} +.vco-storyjs .thumb-storify-full{height:12px;background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-280px -96px;width:48px;} +.vco-storyjs .thumbnail-inline{width:16px;height:14px;overflow:hidden;display:inline-block;margin-right:1px;margin-left:3px;margin-top:2px;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-storyjs .twitter .thumbnail-inline{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-160px -96px;} +.vco-storyjs .storify .thumbnail-inline{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-184px -96px;} +.vco-storyjs .googleplus .thumbnail-inline{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-208px -96px;} +.vco-storyjs .zFront{z-index:204;} +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-storyjs div.vco-loading .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-loading-icon{background-image:url(themes/loading@2x.gif?v3.4);} .vco-storyjs div.vco-loading .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-gesture-icon{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-160px -160px;width:48px;height:48px;}}.vco-notouch .vco-navigation .vco-toolbar .zoom-in:hover,.vco-notouch .vco-navigation .vco-toolbar .zoom-out:hover,.vco-notouch .vco-navigation .vco-toolbar .back-home:hover{color:#0bd4e3;cursor:pointer;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-notouch .vco-navigation .timenav .content .marker.active:hover{cursor:default;}.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag .flag-content h3,.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag-small .flag-content h3{color:#0bd4e3;} +.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag .flag-content h4,.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag-small .flag-content h4{color:#999999;} +.vco-notouch .vco-navigation .timenav .content .marker:hover .line{z-index:24;background:#999999;} +.vco-notouch .vco-navigation .timenav .content .marker .flag:hover,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover{cursor:pointer;}.vco-notouch .vco-navigation .timenav .content .marker .flag:hover .flag-content h3,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content h3{color:#aaaaaa;} +.vco-notouch .vco-navigation .timenav .content .marker .flag:hover .flag-content h4,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content h4{color:#aaaaaa;} +.vco-notouch .vco-navigation .timenav .content .marker .flag:hover .flag-content .thumbnail,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content .thumbnail{filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-notouch .vco-navigation .timenav .content .marker .flag:hover{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;} +.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover{height:56px;background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content{height:36px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content h3{margin-top:5px;} +.vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:0 -109px;width:153px;height:26px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover .flag-content{height:14px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover .flag-content h3{margin-top:4px;} +.vco-timeline .vco-navigation{clear:both;cursor:move;width:100%;height:200px;border-top:1px solid #e3e3e3;position:relative;}.vco-timeline .vco-navigation .vco-toolbar{position:absolute;top:45px;left:0px;z-index:202;background-color:#1a1a1a;border:1px solid #333333;-webkit-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);}.vco-timeline .vco-navigation .vco-toolbar .zoom-in,.vco-timeline .vco-navigation .vco-toolbar .zoom-out,.vco-timeline .vco-navigation .vco-toolbar .back-home{font-weight:normal;font-size:10px;line-height:20px;top:0px;z-index:202;width:18px;height:18px;color:#aaaaaa;text-align:center;font-weight:bold;border:1px solid #1a1a1a;padding:5px;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .vco-toolbar .zoom-in .icon{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-256px 0;width:24px;height:24px;} +.vco-timeline .vco-navigation .vco-toolbar .zoom-out .icon{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-280px 0;width:24px;height:24px;} +.vco-timeline .vco-navigation .vco-toolbar .back-home .icon{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-328px 0;width:24px;height:24px;} +.vco-timeline .vco-navigation .vco-toolbar.touch{-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;background-color:transparent;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-in,.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-out,.vco-timeline .vco-navigation .vco-toolbar.touch .back-home{width:40px;height:40px;padding:5px;background-color:#1a1a1a;border:1px solid #333333;-webkit-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-in .icon{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-208px -160px;width:40px;height:40px;} +.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-out .icon{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-256px -160px;width:40px;height:40px;} +.vco-timeline .vco-navigation .vco-toolbar.touch .back-home .icon{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-304px -160px;width:40px;height:40px;} +.vco-timeline .vco-navigation .timenav-background{position:absolute;cursor:move;top:0px;left:0px;height:150px;width:100%;background-color:#262626;}.vco-timeline .vco-navigation .timenav-background .timenav-interval-background{position:absolute;top:151px;left:0px;background:#1a1a1a;width:100%;height:49px;-webkit-box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);-moz-box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);}.vco-timeline .vco-navigation .timenav-background .timenav-interval-background .top-highlight{position:absolute;top:-1px;left:0px;z-index:30;width:100%;height:1px;background:#1a1a1a;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;-webkit-box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);} +.vco-timeline .vco-navigation .timenav-background .timenav-line{position:absolute;top:0px;left:50%;width:3px;height:150px;background-color:#0bd4e3;z-index:1;-webkit-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);} +.vco-timeline .vco-navigation .timenav-background .timenav-indicator{position:absolute;top:-1px;left:50%;z-index:202;background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-160px -48px;width:24px;height:24px;} +.vco-timeline .vco-navigation .timenav-background .timenav-tag div{height:50px;display:table;}.vco-timeline .vco-navigation .timenav-background .timenav-tag div h3{display:table-cell;vertical-align:middle;padding-left:65px;font-size:15px;color:#0c0c0c;font-weight:bold;text-shadow:0px 1px 1px #727272;} +.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-half{height:25px;}.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-half div{height:25px;} +.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-full{height:50px;}.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-full div{height:50px;} +.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-2,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-4,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-6{background:#2e2e2e;} +.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-1,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-3,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-5{background:#262626;} +.vco-timeline .vco-navigation .timenav{position:absolute;top:0px;left:-250px;z-index:1;}.vco-timeline .vco-navigation .timenav .content{position:relative;}.vco-timeline .vco-navigation .timenav .content .marker.start{display:none;} +.vco-timeline .vco-navigation .timenav .content .marker.active .dot{background:#0bd4e3;z-index:200;} +.vco-timeline .vco-navigation .timenav .content .marker.active .line{z-index:199;background:#0bd4e3;width:1px;}.vco-timeline .vco-navigation .timenav .content .marker.active .line .event-line{background:#0bd4e3;filter:alpha(opacity=75);-khtml-opacity:0.75;-moz-opacity:0.75;opacity:0.75;} +.vco-timeline .vco-navigation .timenav .content .marker.active .flag,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small{z-index:200;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content{height:36px;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content h3,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3{color:#0bd4e3;margin-top:5px;} +.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content .thumbnail,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content .thumbnail{filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-timeline .vco-navigation .timenav .content .marker.active .flag.row1,.vco-timeline .vco-navigation .timenav .content .marker.active .flag.row2,.vco-timeline .vco-navigation .timenav .content .marker.active .flag.row3,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small.row1,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small.row2,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small.row3{z-index:200;} +.vco-timeline .vco-navigation .timenav .content .marker.active .flag{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;} +.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:0 -109px;width:153px;height:26px;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content{height:14px;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3{margin-top:4px;} +.vco-timeline .vco-navigation .timenav .content .marker{position:absolute;top:0px;left:150px;display:block;}.vco-timeline .vco-navigation .timenav .content .marker .dot{position:absolute;top:150px;left:0px;display:block;width:6px;height:6px;background:#aaaaaa;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;z-index:21;} +.vco-timeline .vco-navigation .timenav .content .marker .line{position:absolute;top:0px;left:3px;width:1px;height:150px;background-color:#333333;background-color:rgba(51, 51, 51, 0.5);-webkit-box-shadow:1px 0 0 rgba(26, 26, 26, 0.5);-moz-box-shadow:1px 0 0 rgba(26, 26, 26, 0.5);box-shadow:1px 0 0 rgba(26, 26, 26, 0.5);z-index:22;}.vco-timeline .vco-navigation .timenav .content .marker .line .event-line{position:absolute;z-index:22;left:0px;height:1px;width:1px;background:#0bd4e3;filter:alpha(opacity=15);-khtml-opacity:0.15;-moz-opacity:0.15;opacity:0.15;} +.vco-timeline .vco-navigation .timenav .content .marker .flag,.vco-timeline .vco-navigation .timenav .content .marker .flag-small{position:absolute;top:15px;left:3px;padding:0px;display:block;z-index:23;width:153px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content{padding:0px 7px 2px 6px;overflow:hidden;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h3,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h3{font-weight:bold;font-size:15px;line-height:20px;font-size:11px;line-height:11px;color:#999999;margin-bottom:2px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h3 small,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h3 small{display:none;} +.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h4,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h4{display:none;font-weight:normal;font-size:15px;line-height:20px;margin-top:5px;font-size:10px;line-height:10px;color:#aaaaaa;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h4 small,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h4 small{display:none;} +.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content .thumbnail,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail{margin-bottom:15px;margin-right:3px;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content .thumbnail img,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail img{width:22px;height:22px;max-height:none;max-width:none;border:0;border:1px solid #999999;padding:0;margin:0;} +.vco-timeline .vco-navigation .timenav .content .marker .flag{height:56px;background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:0 0;width:153px;height:53px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content{height:36px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h3{margin-top:5px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:0 -135px;width:153px;height:26px;}.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content{height:14px;}.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h3{margin-top:4px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail{width:16px;height:10px;margin-right:1px;margin-top:6px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-plaintext{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-280px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-quote{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-232px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-document{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-256px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-photo{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-280px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-twitter{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-256px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-vimeo{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-328px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-youtube{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-304px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-video{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-328px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-audio{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-304px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-map{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-208px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-website{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-232px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-link{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-232px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-wikipedia{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-184px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-storify{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-184px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-googleplus{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-208px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content thumbnail.thumb-instagram{background-image:url(themes/timeline-dark.png?v3.4);background-repeat:no-repeat;background-position:-208px -96px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag.row1{z-index:25;top:48px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag.row2{z-index:24;top:96px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag.row3{z-index:23;top:1px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row1{z-index:28;top:24px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row2{z-index:27;top:48px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row3{z-index:26;top:72px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row4{z-index:25;top:96px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row5{z-index:24;top:120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row6{z-index:23;top:1px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag.zFront,.vco-timeline .vco-navigation .timenav .content .marker .flag-small.zFront{z-index:201;} +.vco-timeline .vco-navigation .timenav .content .era{position:absolute;top:138px;left:150px;height:12px;display:block;overflow:hidden;}.vco-timeline .vco-navigation .timenav .content .era div{height:50px;width:100%;height:100%;line-height:0px;background:#262626;background:rgba(38, 38, 38, 0.33);}.vco-timeline .vco-navigation .timenav .content .era div h3,.vco-timeline .vco-navigation .timenav .content .era div h4{position:absolute;bottom:1px;padding-left:15px;font-size:15px;font-weight:bold;color:rgba(11, 212, 227, 0.35);text-shadow:0px 1px 1px #727272;} +.vco-timeline .vco-navigation .timenav .content .era1 div{background:#e31a0b;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(227, 26, 11, 0.1);border-right:1px solid rgba(245, 58, 44, 0.05);}.vco-timeline .vco-navigation .timenav .content .era1 div h3,.vco-timeline .vco-navigation .timenav .content .era1 div h4{color:rgba(227, 26, 11, 0.35);text-shadow:0px 1px 1px #727272;} +.vco-timeline .vco-navigation .timenav .content .era2 div{background:#e30b68;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(227, 11, 104, 0.1);border-right:1px solid rgba(245, 44, 131, 0.05);}.vco-timeline .vco-navigation .timenav .content .era2 div h3,.vco-timeline .vco-navigation .timenav .content .era2 div h4{color:rgba(227, 11, 104, 0.35);text-shadow:0px 1px 1px #727272;} +.vco-timeline .vco-navigation .timenav .content .era3 div{background:#0b68e3;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(11, 104, 227, 0.1);border-right:1px solid rgba(44, 131, 245, 0.05);}.vco-timeline .vco-navigation .timenav .content .era3 div h3,.vco-timeline .vco-navigation .timenav .content .era3 div h4{color:rgba(11, 104, 227, 0.35);text-shadow:0px 1px 1px #727272;} +.vco-timeline .vco-navigation .timenav .content .era4 div{background:#e3860b;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(227, 134, 11, 0.1);border-right:1px solid rgba(245, 158, 44, 0.05);}.vco-timeline .vco-navigation .timenav .content .era4 div h3,.vco-timeline .vco-navigation .timenav .content .era4 div h4{color:rgba(227, 134, 11, 0.35);text-shadow:0px 1px 1px #727272;} +.vco-timeline .vco-navigation .timenav .content .era5 div{background:#0be386;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(11, 227, 134, 0.1);border-right:1px solid rgba(44, 245, 158, 0.05);}.vco-timeline .vco-navigation .timenav .content .era5 div h3,.vco-timeline .vco-navigation .timenav .content .era5 div h4{color:rgba(11, 227, 134, 0.35);text-shadow:0px 1px 1px #727272;} +.vco-timeline .vco-navigation .timenav .content .era6 div{background:#0bd4e3;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(11, 212, 227, 0.1);border-right:1px solid rgba(44, 231, 245, 0.05);}.vco-timeline .vco-navigation .timenav .content .era6 div h3,.vco-timeline .vco-navigation .timenav .content .era6 div h4{color:rgba(11, 212, 227, 0.35);text-shadow:0px 1px 1px #727272;} +.vco-timeline .vco-navigation .timenav .time{position:absolute;left:0px;top:150px;height:50px;background-color:#1a1a1a;line-height:0px;}.vco-timeline .vco-navigation .timenav .time .time-interval-minor{max-width:none;height:6px;white-space:nowrap;position:absolute;top:-2px;left:8px;z-index:10;}.vco-timeline .vco-navigation .timenav .time .time-interval-minor .minor{position:relative;top:2px;display:inline-block;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAMCAMAAACdvocfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFzMzM////040VdgAAAAJ0Uk5T/wDltzBKAAAAEklEQVR42mJgYAQCBopJgAADAAbwADHy2qHzAAAAAElFTkSuQmCC);width:100px;height:6px;background-position:center top;white-space:nowrap;color:#aaaaaa;margin-top:0px;padding-top:0px;} +.vco-timeline .vco-navigation .timenav .time .time-interval{white-space:nowrap;position:absolute;top:5px;left:0px;}.vco-timeline .vco-navigation .timenav .time .time-interval div{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAMCAMAAACdvocfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFzMzM////040VdgAAAAJ0Uk5T/wDltzBKAAAAEklEQVR42mJgYAQCBopJgAADAAbwADHy2qHzAAAAAElFTkSuQmCC);background-position:left top;background-repeat:no-repeat;padding-top:6px;position:absolute;height:3px;left:0px;display:block;font-weight:normal;font-size:10px;line-height:20px;text-transform:uppercase;text-align:left;text-indent:0px;white-space:nowrap;color:#aaaaaa;margin-left:0px;margin-right:0px;margin-top:0px;z-index:2;}.vco-timeline .vco-navigation .timenav .time .time-interval div strong{font-weight:bold;color:#ffffff;} +.vco-timeline .vco-navigation .timenav .time .time-interval div.era{font-weight:bold;padding-top:0px;margin-top:-3px;margin-left:2px;background-image:none;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era1{color:#e31a0b;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era2{color:#e30b68;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era3{color:#0b68e3;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era4{color:#e3860b;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era5{color:#0be386;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era6{color:#0bd4e3;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval-major{white-space:nowrap;position:absolute;top:5px;left:0px;}.vco-timeline .vco-navigation .timenav .time .time-interval-major div{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAQAQMAAADtUYf0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyOTAzRjI3REIzNDcxMUUxQUQ3QUZCOThEODQ1NDhCNyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyOTAzRjI3RUIzNDcxMUUxQUQ3QUZCOThEODQ1NDhCNyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjI5MDNGMjdCQjM0NzExRTFBRDdBRkI5OEQ4NDU0OEI3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjI5MDNGMjdDQjM0NzExRTFBRDdBRkI5OEQ4NDU0OEI3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+DPWNfQAAAANQTFRFzMzMylJEJwAAAAtJREFUCB1jYMAPAAAgAAHDvpOtAAAAAElFTkSuQmCC);background-position:left top;background-repeat:no-repeat;padding-top:15px;position:absolute;height:15px;left:0px;display:block;font-weight:bold;font-size:12px;line-height:20px;text-transform:uppercase;text-align:left;text-indent:0px;white-space:nowrap;color:#aaaaaa;margin-left:0px;margin-right:0px;margin-top:1px;z-index:5;}.vco-timeline .vco-navigation .timenav .time .time-interval-major div strong{font-weight:bold;color:#ffffff;} +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-notouch .vco-navigation .vco-toolbar .zoom-in .icon{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-256px 0;width:24px;height:24px;} .vco-notouch .vco-navigation .vco-toolbar .zoom-out .icon{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-280px 0;width:24px;height:24px;} .vco-notouch .vco-navigation .vco-toolbar .back-home .icon{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-328px 0;width:24px;height:24px;} .vco-notouch .vco-navigation .vco-toolbar.touch .zoom-in .icon{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-208px -160px;width:40px;height:40px;} .vco-notouch .vco-navigation .vco-toolbar.touch .zoom-out .icon{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-256px -160px;width:40px;height:40px;} .vco-notouch .vco-navigation .vco-toolbar.touch .back-home .icon{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-304px -160px;width:40px;height:40px;} .vco-notouch .vco-navigation .timenav .content .marker .flag:hover{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;} .vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;} .vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:0 -109px;width:153px;height:26px;} .vco-notouch .vco-navigation .timenav-background .timenav-indicator{background-image:url(themes/timeline-dark@2x.png?v4.3);background-repeat:no-repeat;background-position:-160px -48px;width:24px;height:24px;}} diff --git a/src/static/timelinejs/css/themes/font/AbrilFatface-Average.css b/src/static/timelinejs/css/themes/font/AbrilFatface-Average.css new file mode 100755 index 0000000..8ded170 --- /dev/null +++ b/src/static/timelinejs/css/themes/font/AbrilFatface-Average.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'Average',serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Average',serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Average',serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Average',serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Average',serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Abril Fatface',cursive;} +.tooltip{font-family:'Average',serif;} diff --git a/src/static/timelinejs/css/themes/font/Arvo-PTSans.css b/src/static/timelinejs/css/themes/font/Arvo-PTSans.css new file mode 100755 index 0000000..c5d51d0 --- /dev/null +++ b/src/static/timelinejs/css/themes/font/Arvo-PTSans.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'Arvo',serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'PT Sans',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'PT Sans',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'PT Sans',sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Arvo',serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Arvo',serif;} +.tooltip{font-family:'PT Sans',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/Bevan-PotanoSans.css b/src/static/timelinejs/css/themes/font/Bevan-PotanoSans.css new file mode 100755 index 0000000..620d15f --- /dev/null +++ b/src/static/timelinejs/css/themes/font/Bevan-PotanoSans.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'Pontano Sans',sans-serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Pontano Sans',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Pontano Sans',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Pontano Sans',sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Pontano Sans',sans-serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Bevan',serif;} +.tooltip{font-family:'Pontano Sans',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/BreeSerif-OpenSans.css b/src/static/timelinejs/css/themes/font/BreeSerif-OpenSans.css new file mode 100755 index 0000000..c969a5e --- /dev/null +++ b/src/static/timelinejs/css/themes/font/BreeSerif-OpenSans.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Bree Serif',Georgia,serif;} +.tooltip{font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/DroidSerif-DroidSans.css b/src/static/timelinejs/css/themes/font/DroidSerif-DroidSans.css new file mode 100755 index 0000000..fbd9772 --- /dev/null +++ b/src/static/timelinejs/css/themes/font/DroidSerif-DroidSans.css @@ -0,0 +1,7 @@ +.vco-storyjs{font-family:'Droid Serif',serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Droid Sans',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Droid Sans',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Droid Sans',sans-serif !important;} +.vco-storyjs p{font-family:'Droid Sans',sans-serif !important;} +.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Droid Serif',serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Droid Serif',serif;font-weight:700;} +.tooltip{font-family:'Droid Sans',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/Georgia-Helvetica.css b/src/static/timelinejs/css/themes/font/Georgia-Helvetica.css new file mode 100755 index 0000000..681eab2 --- /dev/null +++ b/src/static/timelinejs/css/themes/font/Georgia-Helvetica.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:"Georgia",Times New Roman,Times,serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;} +.vco-storyjs h1.date,.vco-storyjs h2.date,.vco-storyjs h3.date,.vco-storyjs h4.date,.vco-storyjs h5.date,.vco-storyjs h6.date{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:"Georgia",Times New Roman,Times,serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:"Georgia",Times New Roman,Times,serif;} +.tooltip{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/Lekton-Molengo.css b/src/static/timelinejs/css/themes/font/Lekton-Molengo.css new file mode 100755 index 0000000..2078650 --- /dev/null +++ b/src/static/timelinejs/css/themes/font/Lekton-Molengo.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'Lekton',sans-serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Lekton',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Lekton',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Lekton',sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Lekton',sans-serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Molengo',sans-serif;} +.tooltip{font-family:'Lekton',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/Lora-Istok.css b/src/static/timelinejs/css/themes/font/Lora-Istok.css new file mode 100755 index 0000000..6177e37 --- /dev/null +++ b/src/static/timelinejs/css/themes/font/Lora-Istok.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'Lora',serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Istok Web',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Istok Web',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Istok Web',sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Istok Web',sans-serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Lora',serif;font-weight:700;} +.tooltip{font-family:'Istok Web',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/Merriweather-NewsCycle.css b/src/static/timelinejs/css/themes/font/Merriweather-NewsCycle.css new file mode 100755 index 0000000..11bb678 --- /dev/null +++ b/src/static/timelinejs/css/themes/font/Merriweather-NewsCycle.css @@ -0,0 +1,8 @@ +.vco-storyjs{font-family:'Merriweather',serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'News Cycle',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'News Cycle',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'News Cycle',sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'News Cycle',sans-serif !important;} +.vco-storyjs p{font-size:16px;line-height:22px;} +.vco-storyjs .wikipedia p{font-size:14px !important;line-height:20px !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Merriweather',serif;font-weight:900;} +.tooltip{font-family:'News Cycle',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/NewsCycle-Merriweather.css b/src/static/timelinejs/css/themes/font/NewsCycle-Merriweather.css new file mode 100755 index 0000000..d17263c --- /dev/null +++ b/src/static/timelinejs/css/themes/font/NewsCycle-Merriweather.css @@ -0,0 +1,8 @@ +.vco-storyjs{font-family:'News Cycle',sans-serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'News Cycle',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'News Cycle',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'News Cycle',sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Merriweather',serif !important;} +.vco-storyjs p{font-size:16px;line-height:22px;} +.vco-storyjs .wikipedia p{font-size:14px !important;line-height:20px !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'News Cycle',sans-serif;font-weight:900;} +.tooltip{font-family:'News Cycle',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/NixieOne-Ledger.css b/src/static/timelinejs/css/themes/font/NixieOne-Ledger.css new file mode 100755 index 0000000..0be61b2 --- /dev/null +++ b/src/static/timelinejs/css/themes/font/NixieOne-Ledger.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'Ledger',serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Ledger',serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Ledger',serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Ledger',serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Ledger',serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Nixie One',cursive;} +.tooltip{font-family:'Ledger',serif;} diff --git a/src/static/timelinejs/css/themes/font/PT.css b/src/static/timelinejs/css/themes/font/PT.css new file mode 100755 index 0000000..45a7d2b --- /dev/null +++ b/src/static/timelinejs/css/themes/font/PT.css @@ -0,0 +1,7 @@ +.vco-storyjs{font-family:'PT Serif',serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'PT Sans',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'PT Sans',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'PT Sans',sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'PT Serif',serif !important;} +.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-style:italic;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'PT Sans Narrow',sans-serif;font-weight:700;} +.tooltip{font-family:'PT Sans',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/PTSerif-PTSans.css b/src/static/timelinejs/css/themes/font/PTSerif-PTSans.css new file mode 100755 index 0000000..3507bad --- /dev/null +++ b/src/static/timelinejs/css/themes/font/PTSerif-PTSans.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'PT Serif',serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'PT Sans',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'PT Sans',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'PT Sans',sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'PT Serif',serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'PT Sans',sans-serif;font-weight:700;} +.tooltip{font-family:'PT Sans',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/Pacifico-Arimo.css b/src/static/timelinejs/css/themes/font/Pacifico-Arimo.css new file mode 100755 index 0000000..b1df281 --- /dev/null +++ b/src/static/timelinejs/css/themes/font/Pacifico-Arimo.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'Arimo',sans-serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Arimo',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Arimo',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Arimo',sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Arimo',sans-serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Pacifico',cursive;} +.tooltip{font-family:'Arimo',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/PlayfairDisplay-Muli.css b/src/static/timelinejs/css/themes/font/PlayfairDisplay-Muli.css new file mode 100755 index 0000000..691908e --- /dev/null +++ b/src/static/timelinejs/css/themes/font/PlayfairDisplay-Muli.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'Muli',sans-serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Muli',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Muli',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Muli',sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Muli',sans-serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Playfair Display',serif;} +.tooltip{font-family:'Muli',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/PoiretOne-Molengo.css b/src/static/timelinejs/css/themes/font/PoiretOne-Molengo.css new file mode 100755 index 0000000..a911f22 --- /dev/null +++ b/src/static/timelinejs/css/themes/font/PoiretOne-Molengo.css @@ -0,0 +1,8 @@ +.vco-storyjs{font-family:'Poiret One',serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Molengo',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Molengo',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Molengo',sans-serif !important;} +.vco-storyjs p{font-family:'Molengo',sans-serif !important;font-size:16px !important;line-height:22px !important;} +.vco-storyjs .wikipedia p{font-size:14px !important;line-height:20px !important;} +.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Poiret One',serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Poiret One',serif;} +.tooltip{font-family:'Molengo',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/Rancho-Gudea.css b/src/static/timelinejs/css/themes/font/Rancho-Gudea.css new file mode 100755 index 0000000..d30093a --- /dev/null +++ b/src/static/timelinejs/css/themes/font/Rancho-Gudea.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'Gudea',sans-serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Gudea',sans-serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Gudea',sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Gudea',sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Gudea',sans-serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Rancho',cursive;} +.tooltip{font-family:'Gudea',sans-serif;} diff --git a/src/static/timelinejs/css/themes/font/SansitaOne-Kameron.css b/src/static/timelinejs/css/themes/font/SansitaOne-Kameron.css new file mode 100755 index 0000000..489cf50 --- /dev/null +++ b/src/static/timelinejs/css/themes/font/SansitaOne-Kameron.css @@ -0,0 +1,6 @@ +.vco-storyjs{font-family:'Kameron',serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:'Kameron',serif !important;} +.vco-storyjs .vco-feature h1.date,.vco-storyjs .vco-feature h2.date,.vco-storyjs .vco-feature h3.date,.vco-storyjs .vco-feature h4.date,.vco-storyjs .vco-feature h5.date,.vco-storyjs .vco-feature h6.date{font-family:'Kameron',serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:'Kameron',serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:'Kameron',serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:'Sansita One',cursive;} +.tooltip{font-family:'Kameron',serif;} diff --git a/src/static/timelinejs/css/themes/timeline-dark.png b/src/static/timelinejs/css/themes/timeline-dark.png new file mode 100755 index 0000000000000000000000000000000000000000..b41465c2e75efdfa4b468346690f7d17701240d6 GIT binary patch literal 19775 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 literal 0 HcmV?d00001 diff --git a/src/static/timelinejs/css/themes/timeline-dark@2x.png b/src/static/timelinejs/css/themes/timeline-dark@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..c2b30a8db9bdcf463fbc455a43ec9893787b7c59 GIT binary patch literal 49145 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 literal 0 HcmV?d00001 diff --git a/src/static/timelinejs/css/themes/timeline-texture.png b/src/static/timelinejs/css/themes/timeline-texture.png new file mode 100755 index 0000000000000000000000000000000000000000..a5e603e50473b70112f26eb02afd440ce1fda0bd GIT binary patch literal 42976 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 aa7NwUxm7pKvph)!eGGNYZoJXP#rz-oWrJ7% literal 0 HcmV?d00001 diff --git a/src/static/timelinejs/css/timeline.css b/src/static/timelinejs/css/timeline.css new file mode 100755 index 0000000..9e641bd --- /dev/null +++ b/src/static/timelinejs/css/timeline.css @@ -0,0 +1,281 @@ +.vco-storyjs{}.vco-storyjs div *{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;} +.vco-storyjs h1,.vco-storyjs h2,.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6,.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs pre,.vco-storyjs a,.vco-storyjs abbr,.vco-storyjs acronym,.vco-storyjs address,.vco-storyjs cite,.vco-storyjs code,.vco-storyjs del,.vco-storyjs dfn,.vco-storyjs em,.vco-storyjs img,.vco-storyjs q,.vco-storyjs s,.vco-storyjs samp,.vco-storyjs small,.vco-storyjs strike,.vco-storyjs strong,.vco-storyjs sub,.vco-storyjs sup,.vco-storyjs tt,.vco-storyjs var,.vco-storyjs dd,.vco-storyjs dl,.vco-storyjs dt,.vco-storyjs li,.vco-storyjs ol,.vco-storyjs ul,.vco-storyjs fieldset,.vco-storyjs form,.vco-storyjs label,.vco-storyjs legend,.vco-storyjs button,.vco-storyjs table,.vco-storyjs caption,.vco-storyjs tbody,.vco-storyjs tfoot,.vco-storyjs thead,.vco-storyjs tr,.vco-storyjs th,.vco-storyjs td,.vco-storyjs .vco-container,.vco-storyjs .content-container,.vco-storyjs .media,.vco-storyjs .text,.vco-storyjs .vco-slider,.vco-storyjs .slider,.vco-storyjs .date,.vco-storyjs .title,.vco-storyjs .messege,.vco-storyjs .map,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .vco-feedback,.vco-storyjs .vco-feature,.vco-storyjs .toolbar,.vco-storyjs .marker,.vco-storyjs .dot,.vco-storyjs .line,.vco-storyjs .flag,.vco-storyjs .time,.vco-storyjs .era,.vco-storyjs .major,.vco-storyjs .minor,.vco-storyjs .vco-navigation,.vco-storyjs .start,.vco-storyjs .active{margin:0;padding:0;border:0;font-weight:normal;font-style:normal;font-size:100%;line-height:1;font-family:inherit;width:auto;float:none;} +.vco-storyjs h1,.vco-storyjs h2,.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6{clear:none;} +.vco-storyjs table{border-collapse:collapse;border-spacing:0;} +.vco-storyjs ol,.vco-storyjs ul{list-style:none;} +.vco-storyjs q:before,.vco-storyjs q:after,.vco-storyjs blockquote:before,.vco-storyjs blockquote:after{content:"";} +.vco-storyjs a:focus{outline:thin dotted;} +.vco-storyjs a:hover,.vco-storyjs a:active{outline:0;} +.vco-storyjs article,.vco-storyjs aside,.vco-storyjs details,.vco-storyjs figcaption,.vco-storyjs figure,.vco-storyjs footer,.vco-storyjs header,.vco-storyjs hgroup,.vco-storyjs nav,.vco-storyjs section{display:block;} +.vco-storyjs audio,.vco-storyjs canvas,.vco-storyjs video{display:inline-block;*display:inline;*zoom:1;} +.vco-storyjs audio:not([controls]){display:none;} +.vco-storyjs div{max-width:none;} +.vco-storyjs sub,.vco-storyjs sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;} +.vco-storyjs sup{top:-0.5em;} +.vco-storyjs sub{bottom:-0.25em;} +.vco-storyjs img{border:0;-ms-interpolation-mode:bicubic;} +.vco-storyjs button,.vco-storyjs input,.vco-storyjs select,.vco-storyjs textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;} +.vco-storyjs button,.vco-storyjs input{line-height:normal;*overflow:visible;} +.vco-storyjs button::-moz-focus-inner,.vco-storyjs input::-moz-focus-inner{border:0;padding:0;} +.vco-storyjs button,.vco-storyjs input[type="button"],.vco-storyjs input[type="reset"],.vco-storyjs input[type="submit"]{cursor:pointer;-webkit-appearance:button;} +.vco-storyjs input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;} +.vco-storyjs input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;} +.vco-storyjs textarea{overflow:auto;vertical-align:top;} +.vco-storyjs{font-family:"Georgia",Times New Roman,Times,serif;}.vco-storyjs .twitter,.vco-storyjs .vcard,.vco-storyjs .messege,.vco-storyjs .credit,.vco-storyjs .caption,.vco-storyjs .zoom-in,.vco-storyjs .zoom-out,.vco-storyjs .back-home,.vco-storyjs .time-interval div,.vco-storyjs .time-interval-major div,.vco-storyjs .nav-container{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;} +.vco-storyjs h1.date,.vco-storyjs h2.date,.vco-storyjs h3.date,.vco-storyjs h4.date,.vco-storyjs h5.date,.vco-storyjs h6.date{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;} +.vco-storyjs .timenav h1,.vco-storyjs .flag-content h1,.vco-storyjs .era h1,.vco-storyjs .timenav h2,.vco-storyjs .flag-content h2,.vco-storyjs .era h2,.vco-storyjs .timenav h3,.vco-storyjs .flag-content h3,.vco-storyjs .era h3,.vco-storyjs .timenav h4,.vco-storyjs .flag-content h4,.vco-storyjs .era h4,.vco-storyjs .timenav h5,.vco-storyjs .flag-content h5,.vco-storyjs .era h5,.vco-storyjs .timenav h6,.vco-storyjs .flag-content h6,.vco-storyjs .era h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif !important;} +.vco-storyjs p,.vco-storyjs blockquote,.vco-storyjs blockquote p,.vco-storyjs .twitter blockquote p{font-family:"Georgia",Times New Roman,Times,serif !important;} +.vco-storyjs .vco-feature h1,.vco-storyjs .vco-feature h2,.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{font-family:"Georgia",Times New Roman,Times,serif;} +.tooltip{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;} +.thumbnail{background-image:url(timeline.png?v4.3);} +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.thumbnail{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;}}.vco-storyjs{font-size:15px;font-weight:normal;line-height:20px;-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;}.vco-storyjs p{font-size:15px;font-weight:normal;line-height:20px;margin-bottom:20px;color:#666666;}.vco-storyjs p small{font-size:12px;line-height:17px;} +.vco-storyjs p:first-child{margin-top:20px;} +.vco-storyjs .vco-navigation p{color:#999999;} +.vco-storyjs .vco-feature h3,.vco-storyjs .vco-feature h4,.vco-storyjs .vco-feature h5,.vco-storyjs .vco-feature h6{margin-bottom:15px;} +.vco-storyjs .vco-feature p{color:#666666;} +.vco-storyjs .vco-feature blockquote,.vco-storyjs .vco-feature blockquote p{color:#000000;} +.vco-storyjs .date a,.vco-storyjs .title a{color:#999999;} +.vco-storyjs .hyphenate{-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;} +.vco-storyjs h1,.vco-storyjs h2,.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6{font-weight:normal;color:#000000;text-transform:none;}.vco-storyjs h1 a,.vco-storyjs h2 a,.vco-storyjs h3 a,.vco-storyjs h4 a,.vco-storyjs h5 a,.vco-storyjs h6 a{color:#999999;} +.vco-storyjs h1 small,.vco-storyjs h2 small,.vco-storyjs h3 small,.vco-storyjs h4 small,.vco-storyjs h5 small,.vco-storyjs h6 small{color:#999999;} +.vco-storyjs h1.date,.vco-storyjs h2.date,.vco-storyjs h3.date,.vco-storyjs h4.date,.vco-storyjs h5.date,.vco-storyjs h6.date{font-weight:bold;} +.vco-storyjs h2.start{font-size:36px;line-height:38px;margin-bottom:15px;} +.vco-storyjs h1{margin-bottom:15px;font-size:32px;line-height:34px;}.vco-storyjs h1 small{font-size:18px;} +.vco-storyjs h2{margin-bottom:15px;font-size:28px;line-height:30px;}.vco-storyjs h2 small{font-size:14px;line-height:16px;} +.vco-storyjs h2.date{font-size:16px;line-height:18px;margin-bottom:3.75px;color:#999999;} +.vco-storyjs h3,.vco-storyjs h4,.vco-storyjs h5,.vco-storyjs h6{line-height:40px;}.vco-storyjs h3 .active,.vco-storyjs h4 .active,.vco-storyjs h5 .active,.vco-storyjs h6 .active{color:#0088cc;} +.vco-storyjs h3{font-size:28px;line-height:30px;}.vco-storyjs h3 small{font-size:14px;} +.vco-storyjs h4{font-size:20px;line-height:22px;}.vco-storyjs h4 small{font-size:12px;} +.vco-storyjs h5{font-size:16px;line-height:18px;} +.vco-storyjs h6{font-size:13px;line-height:14px;text-transform:uppercase;} +.vco-storyjs strong{font-weight:bold;font-style:inherit;} +.vco-storyjs em{font-style:italic;font-weight:inherit;} +.vco-storyjs Q{quotes:'„' '“';font-style:italic;} +.vco-storyjs blockquote,.vco-storyjs blockquote p{font-size:24px;line-height:32px;text-align:left;margin-bottom:6px;padding-top:10px;background-color:#ffffff;color:#000000;} +.vco-storyjs .credit{color:#999999;text-align:right;font-size:10px;line-height:10px;display:block;margin:0 auto;clear:both;} +.vco-storyjs .caption{text-align:left;margin-top:5px;color:#666666;font-size:11px;line-height:14px;clear:both;} +.vco-storyjs.vco-right-to-left h1,.vco-storyjs.vco-right-to-left h2,.vco-storyjs.vco-right-to-left h3,.vco-storyjs.vco-right-to-left h4,.vco-storyjs.vco-right-to-left h5,.vco-storyjs.vco-right-to-left h6,.vco-storyjs.vco-right-to-left p,.vco-storyjs.vco-right-to-left blockquote,.vco-storyjs.vco-right-to-left pre,.vco-storyjs.vco-right-to-left a,.vco-storyjs.vco-right-to-left abbr,.vco-storyjs.vco-right-to-left acronym,.vco-storyjs.vco-right-to-left address,.vco-storyjs.vco-right-to-left cite,.vco-storyjs.vco-right-to-left code,.vco-storyjs.vco-right-to-left del,.vco-storyjs.vco-right-to-left dfn,.vco-storyjs.vco-right-to-left em,.vco-storyjs.vco-right-to-left img,.vco-storyjs.vco-right-to-left q,.vco-storyjs.vco-right-to-left s,.vco-storyjs.vco-right-to-left samp,.vco-storyjs.vco-right-to-left small,.vco-storyjs.vco-right-to-left strike,.vco-storyjs.vco-right-to-left strong,.vco-storyjs.vco-right-to-left sub,.vco-storyjs.vco-right-to-left sup,.vco-storyjs.vco-right-to-left tt,.vco-storyjs.vco-right-to-left var,.vco-storyjs.vco-right-to-left dd,.vco-storyjs.vco-right-to-left dl,.vco-storyjs.vco-right-to-left dt,.vco-storyjs.vco-right-to-left li,.vco-storyjs.vco-right-to-left ol,.vco-storyjs.vco-right-to-left ul,.vco-storyjs.vco-right-to-left fieldset,.vco-storyjs.vco-right-to-left form,.vco-storyjs.vco-right-to-left label,.vco-storyjs.vco-right-to-left legend,.vco-storyjs.vco-right-to-left button,.vco-storyjs.vco-right-to-left table,.vco-storyjs.vco-right-to-left caption,.vco-storyjs.vco-right-to-left tbody,.vco-storyjs.vco-right-to-left tfoot,.vco-storyjs.vco-right-to-left thead,.vco-storyjs.vco-right-to-left tr,.vco-storyjs.vco-right-to-left th,.vco-storyjs.vco-right-to-left td{direction:rtl;} +.tooltip{position:absolute;z-index:205;display:block;visibility:visible;padding:5px;opacity:0;filter:alpha(opacity=0);font-size:15px;font-weight:bold;line-height:20px;font-size:12px;line-height:12px;} +.tooltip.in{opacity:0.8;filter:alpha(opacity=80);} +.tooltip.top{margin-top:-2px;} +.tooltip.right{margin-left:2px;} +.tooltip.bottom{margin-top:2px;} +.tooltip.left{margin-left:-2px;} +.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;} +.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;} +.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;} +.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;} +.tooltip-inner{max-width:200px;padding:3px 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;} +@media only screen and (max-width:480px),only screen and (max-device-width:480px){.vco-slider .nav-next,.vco-slider .nav-previous{display:none;}}@media (max-width:640px){}.vco-skinny .vco-slider .slider-item .content .layout-text-media .text .container{text-align:center !important;} +.vco-skinny .vco-slider .slider-item .content .layout-text-media h2,.vco-skinny .vco-slider .slider-item .content .layout-text-media h3{display:block !important;width:100% !important;text-align:center !important;} +.vco-skinny .vco-slider .slider-item .content .content-container{display:block;}.vco-skinny .vco-slider .slider-item .content .content-container .text{width:100%;max-width:100%;min-width:120px;display:block;}.vco-skinny .vco-slider .slider-item .content .content-container .text .container{display:block;-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;} +.vco-skinny .vco-slider .slider-item .content .content-container .media{width:100%;min-width:50%;float:none;}.vco-skinny .vco-slider .slider-item .content .content-container .media .media-wrapper{margin-left:0px;margin-right:0px;width:100%;display:block;} +.vco-skinny.vco-notouch .vco-slider .nav-previous,.vco-skinny.vco-notouch .vco-slider .nav-next{z-index:203;}.vco-skinny.vco-notouch .vco-slider .nav-previous .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-next .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-previous .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next .nav-container .title{filter:alpha(opacity=1);-khtml-opacity:0.01;-moz-opacity:0.01;opacity:0.01;} +.vco-skinny.vco-notouch .vco-slider .nav-previous .nav-container .icon,.vco-skinny.vco-notouch .vco-slider .nav-next .nav-container .icon{filter:alpha(opacity=15);-khtml-opacity:0.15;-moz-opacity:0.15;opacity:0.15;} +.vco-skinny.vco-notouch .vco-slider .nav-previous .icon{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-208px 0;width:24px;height:24px;overflow:hidden;margin-left:10px;} +.vco-skinny.vco-notouch .vco-slider .nav-next .icon{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-232px 0;width:24px;height:24px;overflow:hidden;margin-left:66px;} +.vco-skinny.vco-notouch .vco-slider .nav-previous:hover,.vco-skinny.vco-notouch .vco-slider .nav-next:hover{color:#aaaaaa !important;background-color:#333333;background-color:rgba(0, 0, 0, 0.65);-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;}.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .icon,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .icon,.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .title{-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;font-weight:bold;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .title{padding-bottom:5px;} +.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .date,.vco-skinny.vco-notouch .vco-slider .nav-previous:hover .nav-container .title,.vco-skinny.vco-notouch .vco-slider .nav-next:hover .nav-container .title{padding-left:5px;padding-right:5px;} +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-skinny.vco-notouch .vco-slider .nav-previous .icon{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-208px 0;width:24px;height:24px;overflow:hidden;} .vco-skinny.vco-notouch .vco-slider .nav-next .icon{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-232px 0;width:24px;height:24px;overflow:hidden;}}.vco-slider{width:100%;height:100%;overflow:hidden;}.vco-slider .slider-container-mask{text-align:center;width:100%;height:100%;overflow:hidden;}.vco-slider .slider-container-mask .slider-container{position:absolute;top:0px;left:-2160px;width:100%;height:100%;text-align:center;display:block;}.vco-slider .slider-container-mask .slider-container .slider-item-container{display:table-cell;vertical-align:middle;} +.vco-notouch .vco-slider .nav-previous:hover,.vco-notouch .vco-slider .nav-next:hover{color:#333333;cursor:pointer;} +.vco-notouch .vco-slider .nav-previous:hover .icon{margin-left:10px;} +.vco-notouch .vco-slider .nav-next:hover .icon{margin-left:66px;} +.vco-notouch .vco-slider .slider-item .content .content-container .media .media-container .wikipedia h4 a:hover{color:#0088cc;text-decoration:none;} +.vco-notouch .vco-slider .slider-item .content .content-container .created-at:hover{filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-notouch .vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments a:hover{text-decoration:none;}.vco-notouch .vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments a:hover h5{text-decoration:underline;} +.vco-slider img,.vco-slider embed,.vco-slider object,.vco-slider video,.vco-slider iframe{max-width:100%;} +.vco-slider .nav-previous,.vco-slider .nav-next{position:absolute;top:0px;width:100px;color:#DBDBDB;font-size:11px;}.vco-slider .nav-previous .nav-container,.vco-slider .nav-next .nav-container{height:100px;width:100px;position:absolute;} +.vco-slider .nav-previous .icon,.vco-slider .nav-next .icon{margin-top:12px;margin-bottom:15px;} +.vco-slider .nav-previous .date,.vco-slider .nav-next .date,.vco-slider .nav-previous .title,.vco-slider .nav-next .title{line-height:14px;}.vco-slider .nav-previous .date a,.vco-slider .nav-next .date a,.vco-slider .nav-previous .title a,.vco-slider .nav-next .title a{color:#999999;} +.vco-slider .nav-previous .date small,.vco-slider .nav-next .date small,.vco-slider .nav-previous .title small,.vco-slider .nav-next .title small{display:none;} +.vco-slider .nav-previous .date,.vco-slider .nav-next .date{font-size:13px;line-height:13px;font-weight:bold;text-transform:uppercase;margin-bottom:5px;} +.vco-slider .nav-previous .title,.vco-slider .nav-next .title{font-size:11px;line-height:13px;} +.vco-slider .nav-previous{float:left;text-align:left;}.vco-slider .nav-previous .icon{margin-left:15px;background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-160px 0;width:24px;height:24px;overflow:hidden;} +.vco-slider .nav-previous .date,.vco-slider .nav-previous .title{text-align:left;padding-left:15px;} +.vco-slider .nav-next{float:right;text-align:right;}.vco-slider .nav-next .icon{margin-left:61px;background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-184px 0;width:24px;height:24px;overflow:hidden;} +.vco-slider .nav-next .date,.vco-slider .nav-next .title{text-align:right;padding-right:15px;} +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-slider .nav-previous .icon{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-160px 0;width:24px;height:24px;overflow:hidden;} .vco-slider .nav-next .icon{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-184px 0;width:24px;height:24px;overflow:hidden;}}.vco-slider .slider-item{position:absolute;width:700px;height:100%;padding:0px;margin:0px;display:table;overflow-y:auto;}.vco-slider .slider-item .content{display:table-cell;vertical-align:middle;}.vco-slider .slider-item .content .pad-top .text .container{padding-top:15px;} +.vco-slider .slider-item .content .pad-right .text .container{padding-right:15px;} +.vco-slider .slider-item .content .pad-left .text .container{padding-left:30px;} +.vco-slider .slider-item .content .pad-left .media.text-media .media-wrapper .media-container{border:none;background-color:#ffffff;} +.vco-slider .slider-item .content .content-container{display:table;vertical-align:middle;}.vco-slider .slider-item .content .content-container .text{width:40%;max-width:50%;min-width:120px;display:table-cell;vertical-align:middle;}.vco-slider .slider-item .content .content-container .text .container{display:table-cell;vertical-align:middle;text-align:left;}.vco-slider .slider-item .content .content-container .text .container p{-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;word-wrap:break-word;} +.vco-slider .slider-item .content .content-container .text .container h2.date{font-size:15px;line-height:15px;font-weight:normal;} +.vco-slider .slider-item .content .content-container .text .container .slide-tag{font-size:11px;font-weight:bold;color:#ffffff;background-color:#cccccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;vertical-align:baseline;white-space:nowrap;line-height:11px;padding:1px 3px 1px;margin-left:7.5px;margin-bottom:7.5px;} +.vco-slider .slider-item .content .content-container .media{width:100%;min-width:50%;float:left;}.vco-slider .slider-item .content .content-container .media .media-wrapper{display:inline-block;margin-left:auto;margin-right:auto;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container{display:inline-block;line-height:0px;padding:0px;max-height:100%;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-frame,.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-image img{border:1px solid;border-color:#cccccc #999999 #999999 #cccccc;background-color:#ffffff;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-frame iframe{background-color:#ffffff;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .soundcloud{border:0;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-image{display:inline-block;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow{position:relative;z-index:1;background:#ffffff;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow:before,.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow:after{z-index:-1;position:absolute;content:"";bottom:15px;left:10px;width:50%;top:80%;max-width:300px;background:#999999;-webkit-box-shadow:0 15px 10px #999999;-moz-box-shadow:0 15px 10px #999999;box-shadow:0 15px 10px #999999;-webkit-transform:rotate(-2deg);-moz-transform:rotate(-2deg);-ms-transform:rotate(-2deg);-o-transform:rotate(-2deg);transform:rotate(-2deg);} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .media-shadow::after{-webkit-transform:rotate(2deg);-moz-transform:rotate(2deg);-ms-transform:rotate(2deg);-o-transform:rotate(2deg);transform:rotate(2deg);right:10px;left:auto;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text{display:table;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text .container{display:table-cell;vertical-align:middle;font-size:15px;line-height:20px;color:#666666;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .plain-text .container p{margin-bottom:20px;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia{font-size:15px;line-height:20px;text-align:left;margin-left:auto;margin-right:auto;margin-bottom:15px;clear:both;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia .wiki-source{margin-bottom:15px;font-size:13px;line-height:19px;font-style:italic;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia h4{border-bottom:1px solid #cccccc;margin-bottom:5px;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia h4 a{color:#000000;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .wikipedia p{font-size:13px;line-height:19px;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map{line-height:normal;z-index:200;text-align:left;background-color:#ffffff;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map img{max-height:none !important;max-width:none !important;border:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .google-map{height:100%;width:100%;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution{position:absolute;z-index:201;bottom:0px;width:100%;overflow:hidden;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution .attribution-text{height:19px;overflow:hidden;-webkit-user-select:none;line-height:19px;margin-right:60px;padding-left:65px;font-family:Arial,sans-serif;font-size:10px;color:#444;white-space:nowrap;color:#ffffff;text-shadow:1px 1px 1px #333333;text-align:center;}.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .map .map-attribution .attribution-text a{color:#ffffff !important;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .credit{color:#999999;text-align:right;display:block;margin:0 auto;margin-top:6px;font-size:10px;line-height:13px;} +.vco-slider .slider-item .content .content-container .media .media-wrapper .media-container .caption{text-align:left;margin-top:10px;color:#666666;font-size:11px;line-height:14px;text-rendering:optimizeLegibility;word-wrap:break-word;} +.vco-slider .slider-item .content .content-container .media.text-media .media-wrapper .media-container{border:none;background-color:#ffffff;} +.vco-slider .slider-item .content .content-container .created-at{width:24px;height:24px;overflow:hidden;margin-left:7.5px;margin-top:2px;display:inline-block;float:right;filter:alpha(opacity=25);-khtml-opacity:0.25;-moz-opacity:0.25;opacity:0.25;} +.vco-slider .slider-item .content .content-container .storify .created-at{background-repeat:no-repeat;background-position:-328px -96px;} +.vco-slider .slider-item .content .content-container .twitter .created-at{background-repeat:no-repeat;background-position:-256px -24px;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content{font-size:13px;line-height:19px;margin-bottom:6px;padding-top:10px;background-color:#ffffff;color:#666666;}.vco-slider .slider-item .content .content-container .googleplus .googleplus-content p{font-size:13px;line-height:19px;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-title{font-size:24px;line-height:32px;margin-bottom:6px;padding-top:10px;background-color:#ffffff;color:#000000;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-annotation{font-size:15px;line-height:20px;color:#000000;border-bottom:1px solid #e3e3e3;padding-bottom:7.5px;margin-bottom:7.5px;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments{border-top:1px solid #e3e3e3;padding-top:15px;margin-top:15px;border-bottom:1px solid #e3e3e3;padding-bottom:15px;margin-bottom:15px;*zoom:1;}.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments:before,.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments:after{display:table;content:"";} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments:after{clear:both;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments h5{margin-bottom:5px;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments div{width:50%;padding-left:15px;display:inline-block;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments p{font-size:11px;line-height:14px;margin-bottom:5px;} +.vco-slider .slider-item .content .content-container .googleplus .googleplus-content .googleplus-attachments img{float:left;display:block;bottom:0;left:0;margin:auto;position:relative;right:0;top:0;width:40%;} +.vco-slider .slider-item .content .content-container .googleplus .proflinkPrefix{color:#0088cc;} +.vco-slider .slider-item .content .content-container .googleplus .created-at{background-repeat:no-repeat;background-position:-208px -72px;} +.vco-slider .slider-item .content .content-container .twitter,.vco-slider .slider-item .content .content-container .plain-text-quote,.vco-slider .slider-item .content .content-container .storify,.vco-slider .slider-item .content .content-container .googleplus{text-align:left;margin-left:auto;margin-right:auto;margin-bottom:15px;clear:both;}.vco-slider .slider-item .content .content-container .twitter blockquote,.vco-slider .slider-item .content .content-container .plain-text-quote blockquote,.vco-slider .slider-item .content .content-container .storify blockquote,.vco-slider .slider-item .content .content-container .googleplus blockquote{color:#666666;}.vco-slider .slider-item .content .content-container .twitter blockquote p,.vco-slider .slider-item .content .content-container .plain-text-quote blockquote p,.vco-slider .slider-item .content .content-container .storify blockquote p,.vco-slider .slider-item .content .content-container .googleplus blockquote p{font-size:24px;line-height:32px;margin-bottom:6px;padding-top:10px;background-color:#ffffff;color:#000000;} +.vco-slider .slider-item .content .content-container .twitter blockquote .quote-mark,.vco-slider .slider-item .content .content-container .plain-text-quote blockquote .quote-mark,.vco-slider .slider-item .content .content-container .storify blockquote .quote-mark,.vco-slider .slider-item .content .content-container .googleplus blockquote .quote-mark{color:#666666;} +.vco-slider .slider-item .content .content-container.layout-text-media .text-media{border-top:1px solid #e3e3e3;padding-top:15px;padding-right:0;} +.vco-slider .slider-item .content .content-container.layout-text-media.pad-left .text-media{padding-right:15px;padding-top:0;border-right:1px solid #e3e3e3;border-top:0px solid #e3e3e3;} +.vco-slider .slider-item .content .content-container.layout-text{width:100%;}.vco-slider .slider-item .content .content-container.layout-text .text{width:100%;max-width:100%;}.vco-slider .slider-item .content .content-container.layout-text .text .container{display:block;vertical-align:middle;padding:0px;width:90%;text-align:left;margin-left:auto;margin-right:auto;} +.vco-slider .slider-item .content .content-container.layout-media{width:100%;}.vco-slider .slider-item .content .content-container.layout-media .text{width:100%;height:100%;max-width:100%;display:block;text-align:center;}.vco-slider .slider-item .content .content-container.layout-media .text .container{display:block;text-align:center;width:100%;margin-left:none;margin-right:none;} +.vco-slider .slider-item .content .content-container.layout-media .media{width:100%;min-width:50%;float:none;}.vco-slider .slider-item .content .content-container.layout-media .media .media-wrapper .media-container{margin-left:auto;margin-right:auto;line-height:0px;padding:0px;} +.vco-slider .slider-item .content .content-container.layout-media .twitter,.vco-slider .slider-item .content .content-container.layout-media .wikipedia,.vco-slider .slider-item .content .content-container.layout-media .googleplus{max-width:70%;} +.storyjs-embed{background-color:#ffffff;margin-bottom:20px;border:1px solid #cccccc;padding-top:20px;padding-bottom:20px;clear:both;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;-webkit-box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);-moz-box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);box-shadow:1px 1px 3px rgba(0, 0, 0, 0.35);} +.storyjs-embed.full-embed{overflow:hidden;border:0 !important;padding:0 !important;margin:0 !important;clear:both;-webkit-border-radius:0 !important;-moz-border-radius:0 !important;border-radius:0 !important;-webkit-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;-moz-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;} +.storyjs-embed.sized-embed{overflow:hidden;border:1px solid #cccccc;padding-top:7px;padding-bottom:7px;margin:0 !important;clear:both;-webkit-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;-moz-box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;box-shadow:0 0px 0px rgba(0, 0, 0, 0.25) !important;} +.vco-storyjs{width:100%;height:100%;padding:0px;margin:0px;background-color:#ffffff;position:absolute;z-index:100;clear:both;overflow:hidden;}.vco-storyjs .vmm-clear:before,.vco-storyjs .vmm-clear:after{content:"";display:table;} +.vco-storyjs .vmm-clear:after{clear:both;} +.vco-storyjs .vmm-clear{*zoom:1;} +.vco-storyjs .vco-feature{width:100%;}.vco-storyjs .vco-feature .slider,.vco-storyjs .vco-feature .vco-slider{width:100%;float:left;position:relative;z-index:10;padding-top:15px;-webkit-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);} +.vco-storyjs .vco-feedback{position:absolute;display:table;overflow:hidden;top:0px;left:0px;z-index:205;width:100%;height:100%;} +.vco-storyjs div.vco-loading,.vco-storyjs div.vco-explainer{display:table;text-align:center;min-width:100px;margin-top:15px;height:100%;width:100%;background-color:#ffffff;}.vco-storyjs div.vco-loading .vco-loading-container,.vco-storyjs div.vco-explainer .vco-loading-container,.vco-storyjs div.vco-loading .vco-explainer-container,.vco-storyjs div.vco-explainer .vco-explainer-container{display:table-cell;vertical-align:middle;}.vco-storyjs div.vco-loading .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-loading-icon{display:block;background-repeat:no-repeat;vertical-align:middle;margin-left:auto;margin-right:auto;text-align:center;background-image:url(loading.gif?v3.4);width:28px;height:28px;} +.vco-storyjs div.vco-loading .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-gesture-icon{display:block;vertical-align:middle;margin-left:auto;margin-right:auto;text-align:center;background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-160px -160px;width:48px;height:48px;} +.vco-storyjs div.vco-loading .vco-loading-container .vco-message,.vco-storyjs div.vco-explainer .vco-loading-container .vco-message,.vco-storyjs div.vco-loading .vco-explainer-container .vco-message,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-message{display:block;} +.vco-storyjs div.vco-loading .vco-loading-container .vco-message,.vco-storyjs div.vco-explainer .vco-loading-container .vco-message,.vco-storyjs div.vco-loading .vco-explainer-container .vco-message,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-message,.vco-storyjs div.vco-loading .vco-loading-container .vco-message p,.vco-storyjs div.vco-explainer .vco-loading-container .vco-message p,.vco-storyjs div.vco-loading .vco-explainer-container .vco-message p,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-message p{text-align:center;font-size:11px;line-height:13px;text-transform:uppercase;margin-top:7.5px;margin-bottom:7.5px;} +.vco-storyjs div.vco-explainer{background-color:transparent;} +.vco-storyjs .vco-bezel{background-color:#333333;background-color:rgba(0, 0, 0, 0.8);width:80px;height:50px;padding:50px;padding-top:25px;padding:25px 20px 50px 20px;margin:auto;-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;}.vco-storyjs .vco-bezel .vco-message,.vco-storyjs .vco-bezel .vco-message p{color:#ffffff;font-weight:bold;} +.vco-storyjs .vco-container.vco-main{position:absolute;top:0px;left:0px;padding-bottom:3px;width:auto;height:auto;margin:0px;clear:both;} +.vco-storyjs img,.vco-storyjs embed,.vco-storyjs object,.vco-storyjs video,.vco-storyjs iframe{max-width:100%;} +.vco-storyjs img{max-height:100%;border:1px solid #999999;} +.vco-storyjs a{color:#0088cc;text-decoration:none;} +.vco-storyjs a:hover{color:#005580;text-decoration:underline;} +.vco-storyjs .vcard{float:right;margin-bottom:15px;}.vco-storyjs .vcard a{color:#333333;} +.vco-storyjs .vcard a:hover{text-decoration:none;}.vco-storyjs .vcard a:hover .fn{text-decoration:underline;} +.vco-storyjs .vcard .fn,.vco-storyjs .vcard .nickname{padding-left:42px;} +.vco-storyjs .vcard .fn{display:block;font-weight:bold;} +.vco-storyjs .vcard .nickname{margin-top:1px;display:block;color:#666666;} +.vco-storyjs .vcard .avatar{float:left;display:block;width:32px;height:32px;}.vco-storyjs .vcard .avatar img{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;} +.vco-storyjs .thumbnail{width:24px;height:24px;overflow:hidden;float:left;margin:0;margin-right:1px;margin-top:6px;border:0;padding:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} +.vco-storyjs a.thumbnail:hover{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;} +.vco-storyjs .thumbnail.thumb-plaintext{background-repeat:no-repeat;background-position:-280px -48px;} +.vco-storyjs .thumbnail.thumb-quote{background-repeat:no-repeat;background-position:-232px -48px;} +.vco-storyjs .thumbnail.thumb-document{background-repeat:no-repeat;background-position:-256px -48px;} +.vco-storyjs .thumbnail.thumb-photo{background-repeat:no-repeat;background-position:-280px -24px;border:0;}.vco-storyjs .thumbnail.thumb-photo img{border:0px none #cccccc !important;} +.vco-storyjs .thumbnail.thumb-twitter{background-repeat:no-repeat;background-position:-256px -24px;} +.vco-storyjs .thumbnail.thumb-vimeo{background-repeat:no-repeat;background-position:-328px -48px;} +.vco-storyjs .thumbnail.thumb-youtube{background-repeat:no-repeat;background-position:-328px -72px;} +.vco-storyjs .thumbnail.thumb-video{background-repeat:no-repeat;background-position:-328px -24px;} +.vco-storyjs .thumbnail.thumb-audio{background-repeat:no-repeat;background-position:-304px -24px;} +.vco-storyjs .thumbnail.thumb-map{background-repeat:no-repeat;background-position:-208px -48px;} +.vco-storyjs .thumbnail.thumb-website{background-repeat:no-repeat;background-position:-232px -24px;} +.vco-storyjs .thumbnail.thumb-link{background-repeat:no-repeat;background-position:-184px -72px;} +.vco-storyjs .thumbnail.thumb-wikipedia{background-repeat:no-repeat;background-position:-184px -48px;} +.vco-storyjs .thumbnail.thumb-storify{background-repeat:no-repeat;background-position:-328px -96px;} +.vco-storyjs .thumbnail.thumb-googleplus{background-repeat:no-repeat;background-position:-208px -72px;} +.vco-storyjs thumbnail.thumb-instagram{background-repeat:no-repeat;background-position:-208px -96px;} +.vco-storyjs thumbnail.thumb-instagram-full{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-232px -96px;width:48px;height:24px;} +.vco-storyjs .thumb-storify-full{height:12px;background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-280px -96px;width:48px;} +.vco-storyjs .thumbnail-inline{width:16px;height:14px;overflow:hidden;display:inline-block;margin-right:1px;margin-left:3px;margin-top:2px;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-storyjs .twitter .thumbnail-inline{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-160px -96px;} +.vco-storyjs .storify .thumbnail-inline{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-184px -96px;} +.vco-storyjs .googleplus .thumbnail-inline{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-208px -96px;} +.vco-storyjs .zFront{z-index:204;} +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-storyjs div.vco-loading .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-loading-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-loading-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-loading-icon{background-image:url(loading@2x.gif?v3.4);} .vco-storyjs div.vco-loading .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-loading-container .vco-gesture-icon,.vco-storyjs div.vco-loading .vco-explainer-container .vco-gesture-icon,.vco-storyjs div.vco-explainer .vco-explainer-container .vco-gesture-icon{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-160px -160px;width:48px;height:48px;}}.vco-notouch .vco-navigation .vco-toolbar .zoom-in:hover,.vco-notouch .vco-navigation .vco-toolbar .zoom-out:hover,.vco-notouch .vco-navigation .vco-toolbar .back-home:hover{color:#0088cc;cursor:pointer;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-notouch .vco-navigation .timenav .content .marker.active:hover{cursor:default;}.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag .flag-content h3,.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag-small .flag-content h3{color:#0088cc;} +.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag .flag-content h4,.vco-notouch .vco-navigation .timenav .content .marker.active:hover .flag-small .flag-content h4{color:#999999;} +.vco-notouch .vco-navigation .timenav .content .marker:hover .line{z-index:24;background:#999999;} +.vco-notouch .vco-navigation .timenav .content .marker .flag:hover,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover{cursor:pointer;}.vco-notouch .vco-navigation .timenav .content .marker .flag:hover .flag-content h3,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content h3{color:#333333;} +.vco-notouch .vco-navigation .timenav .content .marker .flag:hover .flag-content h4,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content h4{color:#aaaaaa;} +.vco-notouch .vco-navigation .timenav .content .marker .flag:hover .flag-content .thumbnail,.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content .thumbnail{filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-notouch .vco-navigation .timenav .content .marker .flag:hover{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;} +.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover{height:56px;background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content{height:36px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover .flag-content h3{margin-top:5px;} +.vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:0 -109px;width:153px;height:26px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover .flag-content{height:14px;}.vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover .flag-content h3{margin-top:4px;} +.vco-timeline .vco-navigation{clear:both;cursor:move;width:100%;height:200px;border-top:1px solid #e3e3e3;position:relative;}.vco-timeline .vco-navigation .vco-toolbar{position:absolute;top:45px;left:0px;z-index:202;background-color:#ffffff;border:1px solid #cccccc;-webkit-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);}.vco-timeline .vco-navigation .vco-toolbar .zoom-in,.vco-timeline .vco-navigation .vco-toolbar .zoom-out,.vco-timeline .vco-navigation .vco-toolbar .back-home{font-weight:normal;font-size:10px;line-height:20px;top:0px;z-index:202;width:18px;height:18px;color:#333333;text-align:center;font-weight:bold;border:1px solid #ffffff;padding:5px;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .vco-toolbar .zoom-in .icon{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-256px 0;width:24px;height:24px;} +.vco-timeline .vco-navigation .vco-toolbar .zoom-out .icon{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-280px 0;width:24px;height:24px;} +.vco-timeline .vco-navigation .vco-toolbar .back-home .icon{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-328px 0;width:24px;height:24px;} +.vco-timeline .vco-navigation .vco-toolbar.touch{-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;background-color:transparent;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-in,.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-out,.vco-timeline .vco-navigation .vco-toolbar.touch .back-home{width:40px;height:40px;padding:5px;background-color:#ffffff;border:1px solid #cccccc;-webkit-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 0px rgba(0, 0, 0, 0.2);-webkit-border-radius:10px;-moz-border-radius:10px;border-radius:10px;filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-in .icon{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-208px -160px;width:40px;height:40px;} +.vco-timeline .vco-navigation .vco-toolbar.touch .zoom-out .icon{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-256px -160px;width:40px;height:40px;} +.vco-timeline .vco-navigation .vco-toolbar.touch .back-home .icon{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-304px -160px;width:40px;height:40px;} +.vco-timeline .vco-navigation .timenav-background{position:absolute;cursor:move;top:0px;left:0px;height:150px;width:100%;background-color:#e9e9e9;}.vco-timeline .vco-navigation .timenav-background .timenav-interval-background{position:absolute;top:151px;left:0px;background:#ffffff;width:100%;height:49px;-webkit-box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);-moz-box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);box-shadow:-1px -1px 7px rgba(0, 0, 0, 0.1);}.vco-timeline .vco-navigation .timenav-background .timenav-interval-background .top-highlight{position:absolute;top:-1px;left:0px;z-index:30;width:100%;height:1px;background:#ffffff;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;-webkit-box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);-moz-box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);box-shadow:1px 1px 5px rgba(0, 0, 0, 0.2);} +.vco-timeline .vco-navigation .timenav-background .timenav-line{position:absolute;top:0px;left:50%;width:3px;height:150px;background-color:#0088cc;z-index:1;-webkit-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);box-shadow:1px 1px 7px rgba(0, 0, 0, 0.3);} +.vco-timeline .vco-navigation .timenav-background .timenav-indicator{position:absolute;top:-1px;left:50%;z-index:202;background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-160px -48px;width:24px;height:24px;} +.vco-timeline .vco-navigation .timenav-background .timenav-tag div{height:50px;display:table;}.vco-timeline .vco-navigation .timenav-background .timenav-tag div h3{display:table-cell;vertical-align:middle;padding-left:65px;font-size:15px;color:#d0d0d0;font-weight:bold;text-shadow:0px 1px 1px #ffffff;} +.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-half{height:25px;}.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-half div{height:25px;} +.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-full{height:50px;}.vco-timeline .vco-navigation .timenav-background .timenav-tag-size-full div{height:50px;} +.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-2,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-4,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-6{background:#f1f1f1;} +.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-1,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-3,.vco-timeline .vco-navigation .timenav-background .timenav-tag-row-5{background:#e9e9e9;} +.vco-timeline .vco-navigation .timenav{position:absolute;top:0px;left:-250px;z-index:1;}.vco-timeline .vco-navigation .timenav .content{position:relative;}.vco-timeline .vco-navigation .timenav .content .marker.start{display:none;} +.vco-timeline .vco-navigation .timenav .content .marker.active .dot{background:#0088cc;z-index:200;} +.vco-timeline .vco-navigation .timenav .content .marker.active .line{z-index:199;background:#0088cc;width:1px;}.vco-timeline .vco-navigation .timenav .content .marker.active .line .event-line{background:#0088cc;filter:alpha(opacity=75);-khtml-opacity:0.75;-moz-opacity:0.75;opacity:0.75;} +.vco-timeline .vco-navigation .timenav .content .marker.active .flag,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small{z-index:200;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content{height:36px;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content h3,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3{color:#0088cc;margin-top:5px;} +.vco-timeline .vco-navigation .timenav .content .marker.active .flag .flag-content .thumbnail,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content .thumbnail{filter:alpha(opacity=100);-khtml-opacity:1;-moz-opacity:1;opacity:1;} +.vco-timeline .vco-navigation .timenav .content .marker.active .flag.row1,.vco-timeline .vco-navigation .timenav .content .marker.active .flag.row2,.vco-timeline .vco-navigation .timenav .content .marker.active .flag.row3,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small.row1,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small.row2,.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small.row3{z-index:200;} +.vco-timeline .vco-navigation .timenav .content .marker.active .flag{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;} +.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:0 -109px;width:153px;height:26px;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content{height:14px;}.vco-timeline .vco-navigation .timenav .content .marker.active .flag-small .flag-content h3{margin-top:4px;} +.vco-timeline .vco-navigation .timenav .content .marker{position:absolute;top:0px;left:150px;display:block;}.vco-timeline .vco-navigation .timenav .content .marker .dot{position:absolute;top:150px;left:0px;display:block;width:6px;height:6px;background:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;z-index:21;} +.vco-timeline .vco-navigation .timenav .content .marker .line{position:absolute;top:0px;left:3px;width:1px;height:150px;background-color:#cccccc;background-color:rgba(204, 204, 204, 0.5);-webkit-box-shadow:1px 0 0 rgba(255, 255, 255, 0.5);-moz-box-shadow:1px 0 0 rgba(255, 255, 255, 0.5);box-shadow:1px 0 0 rgba(255, 255, 255, 0.5);z-index:22;}.vco-timeline .vco-navigation .timenav .content .marker .line .event-line{position:absolute;z-index:22;left:0px;height:1px;width:1px;background:#0088cc;filter:alpha(opacity=15);-khtml-opacity:0.15;-moz-opacity:0.15;opacity:0.15;} +.vco-timeline .vco-navigation .timenav .content .marker .flag,.vco-timeline .vco-navigation .timenav .content .marker .flag-small{position:absolute;top:15px;left:3px;padding:0px;display:block;z-index:23;width:153px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content{padding:0px 7px 2px 6px;overflow:hidden;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h3,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h3{font-weight:bold;font-size:15px;line-height:20px;font-size:11px;line-height:11px;color:#999999;margin-bottom:2px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h3 small,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h3 small{display:none;} +.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h4,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h4{display:none;font-weight:normal;font-size:15px;line-height:20px;margin-top:5px;font-size:10px;line-height:10px;color:#aaaaaa;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h4 small,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h4 small{display:none;} +.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content .thumbnail,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail{margin-bottom:15px;margin-right:3px;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content .thumbnail img,.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail img{width:22px;height:22px;max-height:none;max-width:none;border:0;border:1px solid #999999;padding:0;margin:0;} +.vco-timeline .vco-navigation .timenav .content .marker .flag{height:56px;background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:0 0;width:153px;height:53px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content{height:36px;}.vco-timeline .vco-navigation .timenav .content .marker .flag .flag-content h3{margin-top:5px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:0 -135px;width:153px;height:26px;}.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content{height:14px;}.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content h3{margin-top:4px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail{width:16px;height:10px;margin-right:1px;margin-top:6px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-plaintext{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-280px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-quote{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-232px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-document{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-256px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-photo{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-280px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-twitter{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-256px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-vimeo{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-328px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-youtube{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-304px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-video{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-328px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-audio{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-304px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-map{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-208px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-website{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-232px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-link{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-232px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-wikipedia{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-184px -120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-storify{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-184px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content .thumbnail.thumb-googleplus{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-208px -130px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small .flag-content thumbnail.thumb-instagram{background-image:url(timeline.png?v4.3);background-repeat:no-repeat;background-position:-208px -96px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag.row1{z-index:25;top:48px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag.row2{z-index:24;top:96px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag.row3{z-index:23;top:1px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row1{z-index:28;top:24px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row2{z-index:27;top:48px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row3{z-index:26;top:72px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row4{z-index:25;top:96px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row5{z-index:24;top:120px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag-small.row6{z-index:23;top:1px;} +.vco-timeline .vco-navigation .timenav .content .marker .flag.zFront,.vco-timeline .vco-navigation .timenav .content .marker .flag-small.zFront{z-index:201;} +.vco-timeline .vco-navigation .timenav .content .era{position:absolute;top:138px;left:150px;height:12px;display:block;overflow:hidden;}.vco-timeline .vco-navigation .timenav .content .era div{height:50px;width:100%;height:100%;line-height:0px;background:#e9e9e9;background:rgba(233, 233, 233, 0.33);}.vco-timeline .vco-navigation .timenav .content .era div h3,.vco-timeline .vco-navigation .timenav .content .era div h4{position:absolute;bottom:1px;padding-left:15px;font-size:15px;font-weight:bold;color:rgba(0, 136, 204, 0.35);text-shadow:0px 1px 1px #ffffff;} +.vco-timeline .vco-navigation .timenav .content .era1 div{background:#cc4400;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(204, 68, 0, 0.1);border-right:1px solid rgba(255, 85, 0, 0.05);}.vco-timeline .vco-navigation .timenav .content .era1 div h3,.vco-timeline .vco-navigation .timenav .content .era1 div h4{color:rgba(204, 68, 0, 0.35);text-shadow:0px 1px 1px #ffffff;} +.vco-timeline .vco-navigation .timenav .content .era2 div{background:#cc0022;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(204, 0, 34, 0.1);border-right:1px solid rgba(255, 0, 43, 0.05);}.vco-timeline .vco-navigation .timenav .content .era2 div h3,.vco-timeline .vco-navigation .timenav .content .era2 div h4{color:rgba(204, 0, 34, 0.35);text-shadow:0px 1px 1px #ffffff;} +.vco-timeline .vco-navigation .timenav .content .era3 div{background:#0022cc;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(0, 34, 204, 0.1);border-right:1px solid rgba(0, 43, 255, 0.05);}.vco-timeline .vco-navigation .timenav .content .era3 div h3,.vco-timeline .vco-navigation .timenav .content .era3 div h4{color:rgba(0, 34, 204, 0.35);text-shadow:0px 1px 1px #ffffff;} +.vco-timeline .vco-navigation .timenav .content .era4 div{background:#ccaa00;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(204, 170, 0, 0.1);border-right:1px solid rgba(255, 213, 0, 0.05);}.vco-timeline .vco-navigation .timenav .content .era4 div h3,.vco-timeline .vco-navigation .timenav .content .era4 div h4{color:rgba(204, 170, 0, 0.35);text-shadow:0px 1px 1px #ffffff;} +.vco-timeline .vco-navigation .timenav .content .era5 div{background:#00ccaa;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(0, 204, 170, 0.1);border-right:1px solid rgba(0, 255, 213, 0.05);}.vco-timeline .vco-navigation .timenav .content .era5 div h3,.vco-timeline .vco-navigation .timenav .content .era5 div h4{color:rgba(0, 204, 170, 0.35);text-shadow:0px 1px 1px #ffffff;} +.vco-timeline .vco-navigation .timenav .content .era6 div{background:#0088cc;filter:alpha(opacity=10);-khtml-opacity:0.1;-moz-opacity:0.1;opacity:0.1;border-left:1px solid rgba(0, 136, 204, 0.1);border-right:1px solid rgba(0, 170, 255, 0.05);}.vco-timeline .vco-navigation .timenav .content .era6 div h3,.vco-timeline .vco-navigation .timenav .content .era6 div h4{color:rgba(0, 136, 204, 0.35);text-shadow:0px 1px 1px #ffffff;} +.vco-timeline .vco-navigation .timenav .time{position:absolute;left:0px;top:150px;height:50px;background-color:#ffffff;line-height:0px;}.vco-timeline .vco-navigation .timenav .time .time-interval-minor{max-width:none;height:6px;white-space:nowrap;position:absolute;top:-2px;left:8px;z-index:10;}.vco-timeline .vco-navigation .timenav .time .time-interval-minor .minor{position:relative;top:2px;display:inline-block;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAMCAMAAACdvocfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFzMzM////040VdgAAAAJ0Uk5T/wDltzBKAAAAEklEQVR42mJgYAQCBopJgAADAAbwADHy2qHzAAAAAElFTkSuQmCC);width:100px;height:6px;background-position:center top;white-space:nowrap;color:#666666;margin-top:0px;padding-top:0px;} +.vco-timeline .vco-navigation .timenav .time .time-interval{white-space:nowrap;position:absolute;top:5px;left:0px;}.vco-timeline .vco-navigation .timenav .time .time-interval div{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAMCAMAAACdvocfAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRFzMzM////040VdgAAAAJ0Uk5T/wDltzBKAAAAEklEQVR42mJgYAQCBopJgAADAAbwADHy2qHzAAAAAElFTkSuQmCC);background-position:left top;background-repeat:no-repeat;padding-top:6px;position:absolute;height:3px;left:0px;display:block;font-weight:normal;font-size:10px;line-height:20px;text-transform:uppercase;text-align:left;text-indent:0px;white-space:nowrap;color:#666666;margin-left:0px;margin-right:0px;margin-top:0px;z-index:2;}.vco-timeline .vco-navigation .timenav .time .time-interval div strong{font-weight:bold;color:#000000;} +.vco-timeline .vco-navigation .timenav .time .time-interval div.era{font-weight:bold;padding-top:0px;margin-top:-3px;margin-left:2px;background-image:none;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era1{color:#cc4400;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era2{color:#cc0022;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era3{color:#0022cc;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era4{color:#ccaa00;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era5{color:#00ccaa;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval .era6{color:#0088cc;filter:alpha(opacity=50);-khtml-opacity:0.5;-moz-opacity:0.5;opacity:0.5;} +.vco-timeline .vco-navigation .timenav .time .time-interval-major{white-space:nowrap;position:absolute;top:5px;left:0px;}.vco-timeline .vco-navigation .timenav .time .time-interval-major div{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAQAQMAAADtUYf0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyOTAzRjI3REIzNDcxMUUxQUQ3QUZCOThEODQ1NDhCNyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyOTAzRjI3RUIzNDcxMUUxQUQ3QUZCOThEODQ1NDhCNyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjI5MDNGMjdCQjM0NzExRTFBRDdBRkI5OEQ4NDU0OEI3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjI5MDNGMjdDQjM0NzExRTFBRDdBRkI5OEQ4NDU0OEI3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+DPWNfQAAAANQTFRFzMzMylJEJwAAAAtJREFUCB1jYMAPAAAgAAHDvpOtAAAAAElFTkSuQmCC);background-position:left top;background-repeat:no-repeat;padding-top:15px;position:absolute;height:15px;left:0px;display:block;font-weight:bold;font-size:12px;line-height:20px;text-transform:uppercase;text-align:left;text-indent:0px;white-space:nowrap;color:#333333;margin-left:0px;margin-right:0px;margin-top:1px;z-index:5;}.vco-timeline .vco-navigation .timenav .time .time-interval-major div strong{font-weight:bold;color:#000000;} +@media only screen and (-webkit-min-device-pixel-ratio:2),only screen and (min-device-pixel-ratio:2){.vco-notouch .vco-navigation .vco-toolbar .zoom-in .icon{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-256px 0;width:24px;height:24px;} .vco-notouch .vco-navigation .vco-toolbar .zoom-out .icon{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-280px 0;width:24px;height:24px;} .vco-notouch .vco-navigation .vco-toolbar .back-home .icon{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-328px 0;width:24px;height:24px;} .vco-notouch .vco-navigation .vco-toolbar.touch .zoom-in .icon{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-208px -160px;width:40px;height:40px;} .vco-notouch .vco-navigation .vco-toolbar.touch .zoom-out .icon{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-256px -160px;width:40px;height:40px;} .vco-notouch .vco-navigation .vco-toolbar.touch .back-home .icon{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-304px -160px;width:40px;height:40px;} .vco-notouch .vco-navigation .timenav .content .marker .flag:hover{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;} .vco-notouch .vco-navigation .timenav .content .marker .flag-small:hover{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:0 -53px;width:153px;height:53px;} .vco-notouch .vco-navigation .timenav .content .marker .flag-small.flag-small-last:hover{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:0 -109px;width:153px;height:26px;} .vco-notouch .vco-navigation .timenav-background .timenav-indicator{background-image:url(timeline@2x.png?v4.3);background-size:352px 260px;background-repeat:no-repeat;background-position:-160px -48px;width:24px;height:24px;}}@media screen and (-webkit-max-device-pixel-ratio:1){}@media only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (-o-min-device-pixel-ratio:3/2),only screen and (min--moz-device-pixel-ratio:1.5),only screen and (min-device-pixel-ratio:1.5){}@media screen and (max-device-width:480px) and (orientation:portrait){.storyjs-embed.full-embed{height:557px !important;width:320px !important;}.storyjs-embed.full-embed .vco-feature{height:356px !important;}}@media screen and (max-device-width:480px) and (orientation:landscape){.storyjs-embed.full-embed{height:409px !important;width:480px !important;}.storyjs-embed.full-embed .vco-feature{height:208px !important;}}@media screen and (min-device-width:481px) and (orientation:portrait){}@media screen and (min-device-width:481px) and (orientation:landscape){}@media (max-width:480px){}@media only screen and (max-width:480px){} diff --git a/src/static/timelinejs/css/timeline.png b/src/static/timelinejs/css/timeline.png new file mode 100755 index 0000000000000000000000000000000000000000..f01f1c08b88042a1e2b8f828e03dca3e14b30163 GIT binary patch literal 19364 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 E4XCptY5)KL literal 0 HcmV?d00001 diff --git a/src/static/timelinejs/css/timeline@2x.png b/src/static/timelinejs/css/timeline@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..41b4eb255a288552a13e0f23a76b28bb34333ead GIT binary patch literal 49364 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 WPIG0V0AoK0q^hK$SSJ52<o^JKr{S>x literal 0 HcmV?d00001 diff --git a/src/static/timelinejs/js/locale/ar.js b/src/static/timelinejs/js/locale/ar.js new file mode 100755 index 0000000..f67327a --- /dev/null +++ b/src/static/timelinejs/js/locale/ar.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"ar",right_to_left:!0,api:{wikipedia:"ar"},date:{month:["كانون الثاني","شباط","آذار","نيسان","أيار","حزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول"],month_abbr:["كانون الثاني","شباط","آذار","نيسان","أيار","حزيران","تموز","آب","أيلول","تشرين الأول","تشرين الثاني","كانون الأول"],day:["الأحد","الإثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],day_abbr:["الأحد","الإثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"mmm d',' yyyy 'at' hh:MM TT",full_long_small_date:"hh:MM TT'<br/><small>mmm d',' yyyy'</small>'"},messages:{loading_timeline:"جاري التحميل... ",return_to_title:"العودة",expand_timeline:"تكبير العرض",contract_timeline:"الاتÙاقية",wikipedia:"من ويكيبيديا, الموسوعة الحرة",loading_content:"تحميل المحتوى",loading:"تحميل"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/bg.js b/src/static/timelinejs/js/locale/bg.js new file mode 100755 index 0000000..be0ad12 --- /dev/null +++ b/src/static/timelinejs/js/locale/bg.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"bg",api:{wikipedia:"bg"},date:{month:["Януари","Февруари","Март","Ðприл","Май","Юни","Юли","ÐвгуÑÑ‚","Септември","Октомври","Ðоември","Декември"],month_abbr:["Ян.","Фев.","Март","Ðпр.","Май","Юни","Юли","Ðвг.","Септ.","Окт.","Ðоем.","Дек."],day:["ÐеделÑ","Понеделник","Вторник","СрÑда","Четвъртък","Петък","Събота"],day_abbr:["Ðед.","Пон.","Ð’Ñ‚.","Ср.","Четв.","Пет.","Съб."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'d mmmm yyyy'</small>'",full_long:"d mmm yyyy 'at' h:MM TT",full_long_small_date:"h:MM TT'<br/><small>d mmm yyyy'</small>'"},messages:{loading_timeline:"Зареждане... ",return_to_title:"Ð’ началото",expand_timeline:"РазширÑване",contract_timeline:"Свиване",wikipedia:"От УикипедиÑ, Ñвободната енциклопедиÑ",loading_content:"Съдържанието Ñе зарежда",loading:"Зарежда Ñе"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/ca.js b/src/static/timelinejs/js/locale/ca.js new file mode 100755 index 0000000..03ba948 --- /dev/null +++ b/src/static/timelinejs/js/locale/ca.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"ca",api:{wikipedia:"ca"},date:{month:["Gener","Febrer","Març","Abril","Maig","Juny","Juliol","Agost","Setembre","Octubre","Novembre","Desembre"],month_abbr:["Gen","Feb","Mar","Abr","Mai","Jun","Jul","Ago","Set","Oct","Nov","Des"],day:["Diumenge","Dilluns","Dimarts","Dimecres","Dijous","Divendres","Dissabte"],day_abbr:["Dg.","Dl.","Dt.","Dc.","Dj.","Dv.","Ds."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"'<small>'d mmmm yyyy'</small>' HH:MM",full_long:"dddd',' d mmm yyyy HH:MM",full_long_small_date:"HH:MM'<br/><small>d mmm yyyy'</small>'"},messages:{loading_timeline:"Carregant cronologia...",return_to_title:"Tornar al títol",expand_timeline:"Ampliar la cronologia",contract_timeline:"Reduir la cronologia",wikipedia:"Des de Wikipedia, l'enciclopèdia lliure",loading_content:"Carregant contingut",loading:"Carregant"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/cz.js b/src/static/timelinejs/js/locale/cz.js new file mode 100755 index 0000000..76c8c45 --- /dev/null +++ b/src/static/timelinejs/js/locale/cz.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"cz",api:{wikipedia:"cs"},date:{month:["ledna","února","bÅ™ezna","dubna","kvÄ›tna","Äervna","Äervence","srpna","září","října","listopadu","prosince"],month_abbr:["Led","Úno","BÅ™e","Dub","KvÄ›","ÄŒen","ÄŒec","Srp","Zář","Říj","Lis","Pro"],day:["nedÄ›le","pondÄ›lí","úterý","stÅ™eda","Ätvrtek","pátek","sobota"],day_abbr:["Ne","Po","Út","St","ÄŒt","Pá","So"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d. mmm ",full:"d. mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d. mmmm yyyy'</small>'",full_long:"dddd d. mmm yyyy 'v' HH:MM",full_long_small_date:"HH:MM'<br/><small>dddd d. mmm yyyy'</small>'"},messages:{loading_timeline:"NaÄítám Äasovou osu... ",return_to_title:"ZpÄ›t na zaÄátek",expand_timeline:"Rozbalit Äasovou osu",contract_timeline:"Sbalit Äasovou osu",wikipedia:"Zdroj: otevÅ™ená encyklopedie Wikipedia",loading_content:"Nahrávám obsah",loading:"Nahrávám"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/de.js b/src/static/timelinejs/js/locale/de.js new file mode 100755 index 0000000..cef495a --- /dev/null +++ b/src/static/timelinejs/js/locale/de.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"de",api:{wikipedia:"de"},date:{month:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],month_abbr:["Jan.","Feb.","März","Apr.","Mai","Juni","Juli","Aug.","Sept.","Okt.","Nov.","Dez."],day:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],day_abbr:["So.","Mo.","Di.","Mi.","Do.","Fr.","Sa."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d. mmm",full:"d. mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d. mmmm yyyy'</small>'",full_long:"dddd',' d. mmm yyyy 'um' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d. mmm yyyy'</small>'"},messages:{loading_timeline:"Chronologie wird geladen...",return_to_title:"Zurück zum Anfang",expand_timeline:"Chronologie vergrößern",contract_timeline:"Chronologie verkleinern",wikipedia:"Wikipedia, Die freie Enzyklopädie",loading_content:"Loading",loading:"Loading"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/dk.js b/src/static/timelinejs/js/locale/dk.js new file mode 100755 index 0000000..4e8b22d --- /dev/null +++ b/src/static/timelinejs/js/locale/dk.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"dk",api:{wikipedia:"dk"},date:{month:["Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],month_abbr:["Jan.","Feb.","Marts","April","Maj","Juni","Juli","Aug.","Sept.","Okt.","Nov.","Dec."],day:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],day_abbr:["Sø.","Ma.","Ti.","On.","To.","Fr.","L?."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d. mmm",full:"d. mmmm',' yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d mmmm',' yyyy'</small>'",full_long:"dddd',' d. mmm',' yyyy 'um' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d. mmm yyyy'</small>'"},messages:{loading_timeline:"Henter timeline... ",return_to_title:"Tilbage til titel",expand_timeline:"Forstør timeline",contract_timeline:"Minimør timeline",wikipedia:"Fra Wikipedia",loading_content:"Henter indhold",loading:"Arbejder"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/el.js b/src/static/timelinejs/js/locale/el.js new file mode 100755 index 0000000..e2737e5 --- /dev/null +++ b/src/static/timelinejs/js/locale/el.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"en",api:{wikipedia:"en"},date:{month:["ΙανουάÏιος","ΦεβÏουάÏιος","ΜάÏτιος","ΑπÏίλιος","Μάιος","ΙοÏνιος","ΙοÏλιος","ΑÏγουστος","ΣεπτέμβÏιος","ΟκτώβÏιος","ÎοέμβÏιος","ΔεκέμβÏιος"],month_abbr:["Ιαν.","Φεβ.","ΜαÏ.","ΑπÏ.","Μαη","Ιουν.","Ιουλ.","ΑÏγ.","Σεπτ.","Οκτ.","Îοεμ.","Δεκ."],day:["ΚυÏιακή","ΔευτέÏα","ΤÏίτη","ΤετάÏτη","Πέμπτη","ΠαÏασκευή","Σάββατο"],day_abbr:["ΚυÏ.","Δευ.","ΤÏίτη.","Τετ.","Πεμπ.","ΠαÏ.","Σαβ."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"mmm d',' yyyy 'at' h:MM TT",full_long_small_date:"h:MM TT'<br/><small>mmm d',' yyyy'</small>'"},messages:{loading_timeline:"ΦόÏτωση Timeline... ",return_to_title:"ΕπιστÏοφή στον Τίτλο",expand_timeline:"Μεγέθυνση",contract_timeline:"Contract Timeline",wikipedia:"From Wikipedia, the free encyclopedia",loading_content:"ΦόÏτωση ΠεÏιεχομένου",loading:"Γίνεται ΦόÏτωση"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/en.js b/src/static/timelinejs/js/locale/en.js new file mode 100755 index 0000000..b80fc36 --- /dev/null +++ b/src/static/timelinejs/js/locale/en.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"en",api:{wikipedia:"en"},date:{month:["January","February","March","April","May","June","July","August","September","October","November","December"],month_abbr:["Jan.","Feb.","March","April","May","June","July","Aug.","Sept.","Oct.","Nov.","Dec."],day:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],day_abbr:["Sun.","Mon.","Tues.","Wed.","Thurs.","Fri.","Sat."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"mmm d',' yyyy 'at' h:MM TT",full_long_small_date:"h:MM TT'<br/><small>mmm d',' yyyy'</small>'"},messages:{loading_timeline:"Loading Timeline... ",return_to_title:"Return to Title",expand_timeline:"Expand Timeline",contract_timeline:"Contract Timeline",wikipedia:"From Wikipedia, the free encyclopedia",loading_content:"Loading Content",loading:"Loading"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/es.js b/src/static/timelinejs/js/locale/es.js new file mode 100755 index 0000000..d9aae77 --- /dev/null +++ b/src/static/timelinejs/js/locale/es.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"es",api:{wikipedia:"es"},date:{month:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],month_abbr:["Ene.","Feb.","Mar.","Abr.","May.","Jun.","Jul.","Ago.","Sep.","Oct.","Nov.","Dic."],day:["Domingo","Lunes","Martes","iércoles","Jueves","Viernes","Sábado"],day_abbr:["Dom.","Lun.","Mar.","Mié.","Jue.","Vie.","Sáb."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d mmmm yyyy'</small>'",full_long:"dddd',' d mmm yyyy 'um' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d mmm yyyy'</small>'"},messages:{loading_timeline:"Cronología esta cargando",return_to_title:"Volver al título",expand_timeline:"Enlargar la cronología",contract_timeline:"Reducir la cronología",wikipedia:"Desde Wikipedia, la enciclopedia libre",loading_content:"cargando",loading:"cargando"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/eu.js b/src/static/timelinejs/js/locale/eu.js new file mode 100755 index 0000000..bbbd1ea --- /dev/null +++ b/src/static/timelinejs/js/locale/eu.js @@ -0,0 +1,2 @@ +/* LANGUAGE BASQUE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"eu",api:{wikipedia:"eu"},date:{month:["Urtarrila","Otsaila","Martxoa","Apirila","Maiatza","Ekaina","Uztaila","Abuztua","Iraila","Urria","Azaroa","Abendua"],month_abbr:["Urt.","Ots.","Mar.","Api.","Mai.","Eka.","Uzt.","Abu.","Ira.","Urr.","Aza.","Abe."],day:["Igandea","Astelehena","Asteartea","Asteazkena","Osteguna","Ostirala","Larunbata"],day_abbr:["Iga.","Asl.","Asr.","Asz.","Osg.","Osr.","Lar."]},dateformats:{year:"yyyy",month_short:"mmm",month:"yyyy'(e)ko' mmmm",full_short:"mmm'-'d",full:"yyyy'(e)ko' mmmm'k' d",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br /><small>'yyyy'-'mmm'-'d'</small>",full_long:"yyyy'(e)ko' mmmm'ren' d'(e)an,' hh:MM TT'(r)etan'",full_long_small_date:"hh:MM TT'<br /><small>'yyyy'-'mmm'-'d'</small>"},messages:{loading_timeline:"Kronologia kargatzen...",return_to_title:"Titulura itzuli",expand_timeline:"Handiago ikusi",contract_timeline:"Txikiago ikusi",wikipedia:"Wikipedia entziklopedia libretik",loading_content:"Edukia kargatzen",loading:"Kargatzen"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/fi.js b/src/static/timelinejs/js/locale/fi.js new file mode 100755 index 0000000..e9b93c0 --- /dev/null +++ b/src/static/timelinejs/js/locale/fi.js @@ -0,0 +1,2 @@ +/* LANGUAGE Finnish +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"fi",api:{wikipedia:"fi"},date:{month:["tammikuuta","helmikuuta","maaliskuuta","huhtikuuta","toukokuuta","kesäkuuta","heinäkuuta","elokuuta","syyskuuta","lokakuuta","marraskuuta","joulukuuta"],month_abbr:["tammi","helmi","maalis","huhti","touko","kesä","heinä","elo","syys","loka","marras","joulu"],day:["sunnuntai","maanantai","tiistai","keskiviikko","torstai","perjantai","lauauntai"],day_abbr:["su","ma","ti","ke","to","pe","la"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d. mmm",full:"d. mmmm yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'d. mmmm yyyy'</small>'",full_long:"mmm d yyyy 'klo' h:MM TT",full_long_small_date:"h:MM TT'<br/><small>d. mmm yyyy'</small>'"},messages:{loading_timeline:"Ladataan aikajanaa… ",return_to_title:"Takaisin etusivulle",expand_timeline:"Laajenna aikajanaa",contract_timeline:"Tiivistä aikajanaa",wikipedia:"Wikipediasta",loading_content:"Ladataan sisältöä",loading:"Ladataan"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/fo.js b/src/static/timelinejs/js/locale/fo.js new file mode 100755 index 0000000..c6e12cb --- /dev/null +++ b/src/static/timelinejs/js/locale/fo.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"fo",api:{wikipedia:"fo"},date:{month:["januar","februar","mars","aprÃŒl","mai","juni","juli","august","september","oktober","november","desember"],month_abbr:["jan.","febr.","mars","aprÃŒl","mai","juni","juli","aug.","sept.","okt.","nov.","des."],day:["sunnudagur","m·nadagur","tËsdagur","mikudagur","hÛsdagur","frÃŒggjadagur","leygardagur"],day_abbr:["sun.","m·n.","tËs.","mik.","hÛs.","frÃŒ.","ley."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d'.' mmm",full:"d'.' mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d'.' mmmm yyyy'</small>'",full_long:"d'.' mmmm yyyy 'klokkan' HH:MM",full_long_small_date:"HH:MM'<br/><small>'d'.' mmm yyyy'</small>'"},messages:{loading_timeline:"Lesur inn t&iacute;&eth;arr&aacute;s...",return_to_title:"V&iacute;&eth;ka t&iacute;&eth;arr&aacute;s...",expand_timeline:"Minka t&iacute;&eth;arr&aacute;s...",contract_timeline:"Minka t&iacute;&eth;arr&aacute;s",wikipedia:"Fr· Wikipedia",loading_content:"Lesur inn tilfar",loading:"Lesur inn"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/fr.js b/src/static/timelinejs/js/locale/fr.js new file mode 100755 index 0000000..73858b2 --- /dev/null +++ b/src/static/timelinejs/js/locale/fr.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"fr",api:{wikipedia:"fr"},date:{month:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],month_abbr:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","dec."],day:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],day_abbr:["Dim.","Lu.","Ma.","Me.","Jeu.","Vend.","Sam."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d mmmm yyyy'</small>'",full_long:"dddd',' d mmm yyyy 'à' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d mmm yyyy'</small>'"},messages:{loading_timeline:"Chargement de la frise en cours... ",return_to_title:"Retour à la page d'accueil",expand_timeline:"Elargir la frise",contract_timeline:"Réduire la frise",wikipedia:"Extrait de Wikipedia, l'encyclopédie libre",loading_content:"Chargement",loading:"Chargement"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/hu.js b/src/static/timelinejs/js/locale/hu.js new file mode 100755 index 0000000..c8e1903 --- /dev/null +++ b/src/static/timelinejs/js/locale/hu.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"hu",api:{wikipedia:"hu"},date:{month:["Január","Február","Március","Ãprilis","Május","Június","Július","Augusztus","Szeptember","Október","November","December"],month_abbr:["Jan.","Febr.","Márc","Ãpr.","Máj.","Jún.","Júl.","Aug.","Szept.","Okt.","Nov.","Dec."],day:["Vasárnap","HétfÅ‘","Kedd","Szerda","Csütörtök","Péntek","Szombat"],day_abbr:["Vas.","HétfÅ‘","Kedd","Szer.","Csüt.","Pén.","Szom."]},dateformats:{year:"yyyy",month_short:"mmm",month:"yyyy mmmm",full_short:"mmm d",full:"yyyy mmmm d",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM '<br/><small>'yyyy mmmm d'</small>'",full_long:"yyyy mmm d',' HH:MM",full_long_small_date:"HH:MM '<br/><small>yyyy mmm d'</small>'"},messages:{loading_timeline:"Az idÅ‘vonal betöltése... ",return_to_title:"Vissza a címhez",expand_timeline:"Nagyítás",contract_timeline:"Kicsinyítés",wikipedia:"A Wikipédiából, a szabad enciklopédiából",loading_content:"Tartalom betöltése",loading:"Betöltés"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/hy.js b/src/static/timelinejs/js/locale/hy.js new file mode 100755 index 0000000..7df00af --- /dev/null +++ b/src/static/timelinejs/js/locale/hy.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"hy",api:{wikipedia:"hy"},date:{month:["Õ€Õ¸Ö‚Õ¶Õ¾Õ¡Ö€","Õ“Õ¥Õ¿Ö€Õ¾Õ¡Ö€","Õ„Õ¡Ö€Õ¿","Ô±ÕºÖ€Õ«Õ¬","Õ„Õ¡ÕµÕ«Õ½","Õ€Õ¸Ö‚Õ¶Õ«Õ½","Õ€Õ¸Ö‚Õ¬Õ«Õ½","Õ•Õ£Õ¸Õ½Õ¿Õ¸Õ½","ÕÕ¥ÕºÕ¿Õ¥Õ´Õ¢Õ¥Ö€","Õ€Õ¸Õ¯Õ¿Õ¥Õ´Õ¢Õ¥Ö€","Õ†Õ¸ÕµÕ¥Õ´Õ¢Õ¥Ö€","Ô´Õ¥Õ¯Õ¿Õ¥Õ´Õ¢Õ¥Ö€"],month_abbr:["Õ€Õ¶Õ¾.","Õ“Õ¥Õ¿.","Õ„Õ¡Ö€","Ô±ÕºÖ€","Õ„Õ¡Õµ","Õ€Õ¸Ö‚Õ¶","Õ€Õ¸Ö‚Õ¬","Õ•Õ£Õ½.","ÕÕ¥Õº.","Õ€Õ¸Õ¯.","Õ†Õ¸Õµ.","Ô´Õ¥Õ¯."],day:["Ô¿Õ«Ö€Õ¡Õ¯Õ«","ÔµÖ€Õ¯Õ¸Ö‚Õ·Õ¡Õ¢Õ©Õ«","ÔµÖ€Õ¥Ö„Õ·Õ¡Õ¢Õ©Õ«","Õ‰Õ¸Ö€Õ¥Ö„Õ·Õ¡Õ¢Õ©Õ«","Õ€Õ«Õ¶Õ£Õ·Õ¡Õ¢Õ©Õ«","ÕˆÖ‚Ö€Õ¢Õ¡Õ©","Õ‡Õ¡Õ¢Õ¡Õ©"],day_abbr:["Ô¿Õ«.","ÔµÕ¯.","ÔµÖ„.","Õ‰Õ¸.","Õ€Õ«.","ÕˆÖ‚.","Õ‡Õ¡."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm',' yyyy",time_no_seconds_short:"H:MM",time_no_seconds_small_date:"H:MM'<br/><small>'d mmmm',' yyyy'</small>'",full_long:"d mmm',' yyyy 'at' H:MM",full_long_small_date:"H:MM '<br/><small>d mmm',' yyyy'</small>'"},messages:{loading_timeline:"ÔºÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ¢Õ¥Õ¼Õ¶Õ¾Õ¸Ö‚Õ´ Õ§... ",return_to_title:"ÕŽÕ¥Ö€Õ¡Õ¤Õ¡Õ¼Õ¶Õ¡Õ¬ Õ¾Õ¥Ö€Õ¶Õ¡Õ£Ö€Õ«Õ¶",expand_timeline:"Ô¼Õ¡ÕµÕ¶Õ¡ÖÕ¶Õ¥Õ¬ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨",contract_timeline:"Õ†Õ¥Õ²Õ¡ÖÕ¶Õ¥Õ¬ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡Õ£Ö€Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨",wikipedia:"Ô¸Õ½Õ¿ ÕŽÕ«Ö„Õ«ÕºÕ¥Õ¤Õ«Õ¡ Õ¡Õ¦Õ¡Õ¿ Õ°Õ¡Õ¶Ö€Õ¡Õ£Õ«Õ¿Õ¡Ö€Õ¡Õ¶Õ«",loading_content:"Ô²Õ¸Õ¾Õ¡Õ¶Õ¤Õ¡Õ¯Õ¸Ö‚Õ©ÕµÕ¸Ö‚Õ¶Õ¨ Õ¢Õ¥Õ¼Õ¶Õ¾Õ¸Ö‚Õ´ Õ§",loading:"Ô²Õ¥Õ¼Õ¶Õ¸Ö‚Õ´"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/id.js b/src/static/timelinejs/js/locale/id.js new file mode 100755 index 0000000..fc1a6ff --- /dev/null +++ b/src/static/timelinejs/js/locale/id.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"id",api:{wikipedia:"id"},date:{month:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","November","Desember"],month_abbr:["Jan.","Feb.","Maret","April","Mei","Juni","July","Agus.","Sept.","Okt.","Nov.","Des."],day:["Ahad","Senin","Selasa","Rabu","Kamis","Jum'at","Sabtu"],day_abbr:["Ahad","Sen.","Sel.","Rabu","Kamis","Jum.","Sab."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d mmmm yyyy'</small>'",full_long:"dddd',' d mmm yyyy 'pukul' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d mmm yyyy'</small>'"},messages:{loading_timeline:"Memuat Timeline... ",return_to_title:"Kembali ke Judul",expand_timeline:"Kembangkan Timeline",contract_timeline:"Ciutkan Timeline",wikipedia:"dari Wikipedia, ensiklopedia bebas",loading_content:"Memuat Isi",loading:"Memuat"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/is.js b/src/static/timelinejs/js/locale/is.js new file mode 100755 index 0000000..69cc6f5 --- /dev/null +++ b/src/static/timelinejs/js/locale/is.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"is",api:{wikipedia:"is"},date:{month:["janúar","febrúar","mars","apríl","maí","júní","júlí","ágúst","september","október","nóvember","desember"],month_abbr:["jan.","feb.","mars","apríl","maí","júní","júlí","ágúst","sept.","okt.","nóv.","des."],day:["sunnudagur","mánudagur","þriðjudagur","miðvikudagur","fimmtudagur","föstudagur","laugardagur"],day_abbr:["sun.","mán.","þri.","mið.","fim.","fös.","lau."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time_no_seconds_short:"hh:MM TT",time_no_seconds_small_date:"hh:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"dddd',' mmm d',' yyyy 'at' hh:MM TT",full_long_small_date:"hh:MM TT'<br/><small>'dddd',' mmm d',' yyyy'</small>'"},messages:{loading_timeline:"Raða upp tímalínu... ",return_to_title:"Til baka á forsíðu",expand_timeline:"Stækka tímalínu",contract_timeline:"Minnka tímalínu",wikipedia:"From Wikipedia, the free encyclopedia",loading_content:"Raða",loading:"Raða"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/it.js b/src/static/timelinejs/js/locale/it.js new file mode 100755 index 0000000..ea4ff6b --- /dev/null +++ b/src/static/timelinejs/js/locale/it.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"it",api:{wikipedia:"it"},date:{month:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],month_abbr:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],day:["Domenica","Lunedi","Martedi","Mercoledi","Giovedi","Venerdi","Sabato"],day_abbr:["Dom.","Lun.","Mar.","Mer.","Gio.","Ven.","Sab."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d mmmm yyyy'</small>'",full_long:"dddd',' d mmm yyyy 'um' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d mmm yyyy'</small>'"},messages:{loading_timeline:"Loading Timeline... ",return_to_title:"Return to Title",expand_timeline:"Expand Timeline",contract_timeline:"Contract Timeline",wikipedia:"Wikipedia, L’enciclopedia libera",loading_content:"Loading Content",loading:"Loading"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/iw.js b/src/static/timelinejs/js/locale/iw.js new file mode 100755 index 0000000..da35770 --- /dev/null +++ b/src/static/timelinejs/js/locale/iw.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"iw",right_to_left:!0,api:{wikipedia:"iw"},date:{month:["ינו×ר","פברו×ר","מרץ","×פריל","מ××™","יוני","יולי","×וגוסט","ספטמבר","×וקטובר","נובמבר","דצמבר"],month_abbr:["ינו×ר","פברו×ר","מרץ","×פריל","מ××™","יוני","יולי","×וגוסט","ספטמבר","×וקטובר","נובמבר","דצמבר"],day:["ר×שון","שני","שלישי","רביעי","חמישי","שישי","שבת"],day_abbr:["×™×•× ×'","×™×•× ×‘'","×™×•× ×’'","×™×•× ×“'","×™×•× ×”'","×™×•× ×•'","שבת"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm,' yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"d' mmm,' yyyy 'at' h:MM TT",full_long_small_date:"h:MM TT'<br/><small>mmm d',' yyyy'</small>'"},messages:{loading_timeline:"טוען ×ת ציר הזמן... ",return_to_title:"חזור לכותרת",expand_timeline:"הרחב ×ת ציר הזמן",contract_timeline:"×¦×ž×¦× ×ת ציר הזמן",wikipedia:"מויקיפדיה, ×”×ינציקלופדיה החופשית",loading_content:"התוכן בטעינה...",loading:"טוען..."}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/ja.js b/src/static/timelinejs/js/locale/ja.js new file mode 100755 index 0000000..efdb833 --- /dev/null +++ b/src/static/timelinejs/js/locale/ja.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"ja",api:{wikipedia:"ja"},date:{month:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],month_abbr:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],day:["日曜日","月曜日","ç«æ›œæ—¥","水曜日","木曜日","金曜日","土曜日"],day_abbr:["æ—¥","月","ç«","æ°´","木","金","土"]},dateformats:{year:"yyyyå¹´",month_short:"mmm",month:"yyyyå¹´ m月dæ—¥ (ddd)",full_short:"yyyyå¹´m月dæ—¥",full:"yyyyå¹´ m月dæ—¥ (ddd)",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'yyyyå¹´m月dæ—¥'</small>'",full_long:"yyyyå¹´m月dæ—¥ H時M分s秒",full_long_small_date:"HH:MM:ss'<br/><small>'yyyyå¹´m月dæ—¥'</small>'"},messages:{loading_timeline:"タイムラインをロードã—ã¦ã„ã¾ã™â€¦",return_to_title:"タイトルã¸æˆ»ã‚Šã¾ã™",expand_timeline:"タイムラインを展開ã—ã¾ã™",contract_timeline:"タイムラインを縮ã‚ã¾ã™",wikipedia:"出典:フリー百科事典『ウィキペディア(Wikipedia)ã€",loading_content:"コンテンツをロードã—ã¦ã„ã¾ã™",loading:"ローディング"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/ko.js b/src/static/timelinejs/js/locale/ko.js new file mode 100755 index 0000000..287c93a --- /dev/null +++ b/src/static/timelinejs/js/locale/ko.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"kr",api:{wikipedia:"kr"},date:{month:["1ì›”","2ì›”","3ì›”","4ì›”","5ì›”","6ì›”","7ì›”","8ì›”","9ì›”","10ì›”","11ì›”","12ì›”"],month_abbr:["1ì›”","2ì›”","3ì›”","4ì›”","5ì›”","6ì›”","7ì›”","8ì›”","9ì›”","10ì›”","11ì›”","12ì›”"],day:["ì¼ìš”ì¼","월요ì¼","화요ì¼","수요ì¼","목요ì¼","금요ì¼","토요ì¼"],day_abbr:["ì¼","ì›”","í™”","수","목","금","토"]},dateformats:{year:"yyyy",month_short:"mmm",month:"yyyy mmm",full_short:"mmm d",full:"yyyy mmm d ",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'yyyy mmm d'</small>'",full_long:"dddd',' d mmm yyyy 'um' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd','yyyy mmm d'</small>'"},messages:{loading_timeline:"타임ë¼ì¸ì„ 불러오고 있습니다.... ",return_to_title:"첫화면으로",expand_timeline:"타임ë¼ì¸ 확대",contract_timeline:"타임ë¼ì¸ 축소",wikipedia:"출처: 위키피디아, 우리 모ë‘ì˜ ë°±ê³¼ì‚¬ì „",loading_content:"ë‚´ìš©ì„ ë¶ˆëŸ¬ì˜¤ê³  있습니다.",loading:"불러오는중"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/kr.js b/src/static/timelinejs/js/locale/kr.js new file mode 100755 index 0000000..287c93a --- /dev/null +++ b/src/static/timelinejs/js/locale/kr.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"kr",api:{wikipedia:"kr"},date:{month:["1ì›”","2ì›”","3ì›”","4ì›”","5ì›”","6ì›”","7ì›”","8ì›”","9ì›”","10ì›”","11ì›”","12ì›”"],month_abbr:["1ì›”","2ì›”","3ì›”","4ì›”","5ì›”","6ì›”","7ì›”","8ì›”","9ì›”","10ì›”","11ì›”","12ì›”"],day:["ì¼ìš”ì¼","월요ì¼","화요ì¼","수요ì¼","목요ì¼","금요ì¼","토요ì¼"],day_abbr:["ì¼","ì›”","í™”","수","목","금","토"]},dateformats:{year:"yyyy",month_short:"mmm",month:"yyyy mmm",full_short:"mmm d",full:"yyyy mmm d ",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'yyyy mmm d'</small>'",full_long:"dddd',' d mmm yyyy 'um' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd','yyyy mmm d'</small>'"},messages:{loading_timeline:"타임ë¼ì¸ì„ 불러오고 있습니다.... ",return_to_title:"첫화면으로",expand_timeline:"타임ë¼ì¸ 확대",contract_timeline:"타임ë¼ì¸ 축소",wikipedia:"출처: 위키피디아, 우리 모ë‘ì˜ ë°±ê³¼ì‚¬ì „",loading_content:"ë‚´ìš©ì„ ë¶ˆëŸ¬ì˜¤ê³  있습니다.",loading:"불러오는중"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/nl.js b/src/static/timelinejs/js/locale/nl.js new file mode 100755 index 0000000..c94e070 --- /dev/null +++ b/src/static/timelinejs/js/locale/nl.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"nl",api:{wikipedia:"nl"},date:{month:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],month_abbr:["jan","febr","maa","apr","mei","juni","juli","aug","sept","okt","nov","dec"],day:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],day_abbr:["zo","ma","di","wo","do","vr","za"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d mmmm yyyy'</small>'",full_long:"dddd',' d mmm yyyy 'om' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d mmm yyyy'</small>'"},messages:{loading_timeline:"Tijdlijn laden ... ",return_to_title:"Terug naar het begin",expand_timeline:"Tijdlijn uitzoomen",contract_timeline:"Tijdlijn inzoomen",wikipedia:"From Wikipedia, the free encyclopedia",loading_content:"Inhoud laden",loading:"Laden"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/no.js b/src/static/timelinejs/js/locale/no.js new file mode 100755 index 0000000..8ff4ca9 --- /dev/null +++ b/src/static/timelinejs/js/locale/no.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"no",api:{wikipedia:"no"},date:{month:["Januar","Februar","Mars","April","Mai","Juni","Juli","August","September","Oktober","November","Desember"],month_abbr:["Jan.","Feb.","Mars","Apr.","Mai","Juni","Juli","Aug.","Sep.","Okt.","Nov.","Des."],day:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],day_abbr:["Søn.","Man.","Tir.","Ons.","Tor.","Fre.","Lør."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d. mmm",full:"d. mmmm',' yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d. mmmm',' yyyy'</small>'",full_long:"dddd',' d. mmm',' yyyy 'kl.' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d. mmm',' yyyy'</small>'"},messages:{loading_timeline:"Laster timeline... ",return_to_title:"Tilbake til tittel",expand_timeline:"Utvid timeline",contract_timeline:"Krymp timeline",wikipedia:"Fra Wikipedia, den frie encyklopedi",loading_content:"Laster innhold",loading:"Laster"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/pl.js b/src/static/timelinejs/js/locale/pl.js new file mode 100755 index 0000000..8f928d3 --- /dev/null +++ b/src/static/timelinejs/js/locale/pl.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"pl",api:{wikipedia:"pl"},date:{month:["StyczeÅ„","Luty","Marzec","KwiecieÅ„","Maj","Czerwiec","Lipiec","SierpieÅ„","WrzesieÅ„","Październik","Listopad","GrudzieÅ„"],month_abbr:["Sty.","Lut.","Mar.","Kwi.","Maj.","Cze.","Lip.","Sie.","Wrz.","Paź.","Lis.","Gru."],day:["Niedziela","PoniedziaÅ‚ek","Wtorek","Åšroda","Czwartek","PiÄ…tek","Sobota"],day_abbr:["Nie.","Pon.","Wto.","Åšro.","Czw.","PiÄ….","Sob."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d mmmm yyyy'</small>'",full_long:"dddd',' d mmm yyyy 'um' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d mmm yyyy'</small>'"},messages:{loading_timeline:"Åadowanie Timeline... ",return_to_title:"Wróć do tytuÅ‚u",expand_timeline:"PowiÄ™ksz Timeline",contract_timeline:"Zmniejsz Timeline",wikipedia:"Z Wikipedii, wolnej encyklopedii",loading_content:"Åadowanie zawartoÅ›ci",loading:"Åadowanie"}}); diff --git a/src/static/timelinejs/js/locale/pt-br.js b/src/static/timelinejs/js/locale/pt-br.js new file mode 100755 index 0000000..c857de9 --- /dev/null +++ b/src/static/timelinejs/js/locale/pt-br.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"pt-br",api:{wikipedia:"pt"},date:{month:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],month_abbr:["Jan.","Fev.","Mar.","Abr.","Mai.","Jun.","Jul.","Ago.","Set.","Out.","Nov.","Dez."],day:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sábado"],day_abbr:["Dom.","Seg.","Ter.","Qua.","Qui.","Sex.","Sáb."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm 'de' yyyy",full_short:"d 'de' mmm",full:"d 'de' mmmm',' yyyy",time_no_seconds_short:"hh:MM TT",time_no_seconds_small_date:"hh:MM TT'<br/><small>'d 'de' mmmm',' yyyy'</small>'",full_long:"dddd',' d 'de' mmm',' yyyy 'às' hh:MM TT",full_long_small_date:"hh:MM TT'<br/><small>'dddd',' d 'de' mmm',' yyyy'</small>'"},messages:{loading_timeline:"Carregando Timeline... ",return_to_title:"Voltar para o título",expand_timeline:"Expandir Timeline",contract_timeline:"Contrair Timeline",wikipedia:"Wikipedia, A enciclopédia livre",loading_content:"Carregando Conteúdo",loading:"Carregando"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/pt.js b/src/static/timelinejs/js/locale/pt.js new file mode 100755 index 0000000..25d66c5 --- /dev/null +++ b/src/static/timelinejs/js/locale/pt.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"pt",api:{wikipedia:"pt"},date:{month:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],month_abbr:["Jan","Fev","Mar","Abr","Maio","Jun","Jul","Ago","Set","Out","Nov","Dez"],day:["Domingo","Segunda","Terça","Quarta","Quinta","Sexta","Sabado"],day_abbr:["Dom","Seg","Ter","Qua","Qui","Sex","Sab"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"mmm d',' yyyy 'at' hh:MM TT",full_long_small_date:"hh:MM TT'<br/><small>mmm d',' yyyy'</small>'"},messages:{loading_timeline:"A carregar a timeline... ",return_to_title:"Voltar ao Título",expand_timeline:"Expandir Timeline",contract_timeline:"Colapsar Timeline",wikipedia:"Wikipedia, A enciclopedia Livre.",loading_content:"A carregar o conteúdo",loading:"A carregar"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/ru.js b/src/static/timelinejs/js/locale/ru.js new file mode 100755 index 0000000..577340e --- /dev/null +++ b/src/static/timelinejs/js/locale/ru.js @@ -0,0 +1,2 @@ +/* LANGUAGE + ================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"ru",api:{wikipedia:"ru"},date:{month:["Январь","Февраль","Март","Ðпрель","Май","Июнь","Июль","ÐвгуÑÑ‚","СентÑбрь","ОктÑбрь","ÐоÑбрь","Декабрь"],month_abbr:["Янв.","Фев.","Март","Ðпр.","Май","Июнь","Июль","Ðвг.","Сент.","Окт.","ÐоÑб.","Дек."],day:["ВоÑкреÑенье","Понедельник","Вторник","Среда","Четверг","ПÑтница","Суббота"],day_abbr:["Ð’Ñк.","Пн.","Ð’Ñ‚.","Ср.","Чт.","Пт.","Сб."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"mmm d',' yyyy 'at' hh:MM TT",full_long_small_date:"hh:MM TT'<br/><small>mmm d',' yyyy'</small>'"},messages:{loading_timeline:"Загрузка... ",return_to_title:"ВернутьÑÑ Ðº заголовку",expand_timeline:"Увеличить",contract_timeline:"Уменьшить",wikipedia:"Из Wikipedia",loading_content:"Загрузка контента",loading:"Загрузка"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/sk.js b/src/static/timelinejs/js/locale/sk.js new file mode 100755 index 0000000..5735e66 --- /dev/null +++ b/src/static/timelinejs/js/locale/sk.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"sk",api:{wikipedia:"sk"},date:{month:["Janu&#225;r","Febru&#225;r","Marec","Apr&#237;l","M&#225;j","J&#250;n","J&#250;l","August","September","Okt&#243;ber","November","December"],month_abbr:["Jan.","Feb.","Marec","Apr&#237;l","M&#225;j","J&#250;n","J&#250;l","Aug.","Sept.","Okt.","Nov.","Dec."],day:["Nede&#318;a","Pondelok","Utorok","Streda","&#352;tvrtok","Piatok","Sobota"],day_abbr:["Ned.","Pon.","Uto.","Str.","&#352;tv.","Pia.","Sob."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"d. mmmm',' yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"mmm d',' yyyy 'at' hh:MM TT",full_long_small_date:"hh:MM TT'<br/><small>mmm d',' yyyy'</small>'"},messages:{loading_timeline:"Na&#269;&#237;tam &#269;asov&#250; os... ",return_to_title:"Sp&#228;&#357; na &#250;vod",expand_timeline:"Zv&#228;&#269;&#353;i&#357; &#269;asov&#250; os",contract_timeline:"Zmen&#353;i&#357; &#269;asov&#250; os",wikipedia:"Z Wikipedie, encyklop&#233;die zadarmo",loading_content:"Na&#269;&#237;tam obsah",loading:"Na&#269;&#237;tanie"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/sl.js b/src/static/timelinejs/js/locale/sl.js new file mode 100755 index 0000000..7d35805 --- /dev/null +++ b/src/static/timelinejs/js/locale/sl.js @@ -0,0 +1,2 @@ +/* LANGUAGE SLOVENIAN +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"sl",api:{wikipedia:"sl"},date:{month:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"],month_abbr:["Jan.","Feb.","Marec","April","Maj","Junij","July","Avg.","Sept.","Okt.","Nov.","Dec."],day:["Nedelja","Ponedeljek","Torek","Sreda","ÄŒertek","Petek","Sobota"],day_abbr:["Ned.","Pon.","Tor.","Sre.","ÄŒet.","Pet.","Sob."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"h:MM",time_no_seconds_small_date:"h:MM' 'd mmmm' 'yyyy",full_long:"d mmm yyyy 'ob' hh:MM",full_long_small_date:"hh:MM' d mmm yyyy"},messages:{loading_timeline:"Nalagam Äasovni trak... ",return_to_title:"Nazaj na naslov",expand_timeline:"RazÅ¡iri Äasovni trak",contract_timeline:"PokrÄi Äasovni trak",wikipedia:"Vir Wikipedija",loading_content:"Nalaganje vsebine",loading:"Nalaganje"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/sr-cy.js b/src/static/timelinejs/js/locale/sr-cy.js new file mode 100755 index 0000000..e8a6c02 --- /dev/null +++ b/src/static/timelinejs/js/locale/sr-cy.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"рп",api:{wikipedia:"рп"},date:{month:["Јануар","Фебруар","Март","Ðприл","Мај","Јун","Јул","ÐвгуÑÑ‚","Септембар","Октобар","Ðовембар","Децембар"],month_abbr:["Јан.","Феб.","Март","Ðпр.","Мај","Јун","Јул","Ðвг.","Сеп.","Окт.","Ðов.","Дец."],day:["Ðедеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],day_abbr:["Ðед.","Пон.","Уто.","Сре.","Чет.","Пет.","Суб."]},dateformats:{year:"yyyy.",month_short:"mmm",month:"mmmm yyyy.",full_short:"d. mmm",full:"d. mmmm yyyy.",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d. mmmm yyyy.'</small>'",full_long:"d. mmm yyyy. 'u' HH:MM",full_long_small_date:"HH:MM'<br/><small>d. mmm yyyy.'</small>'"},messages:{loading_timeline:"Учитавање... ",return_to_title:"Почетак",expand_timeline:"Увећај",contract_timeline:"Умањи",wikipedia:"Из Википедије, Ñлободне енциклопедије",loading_content:"Садржај Ñе учитава",loading:"Учитава Ñе"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/sr-la.js b/src/static/timelinejs/js/locale/sr-la.js new file mode 100755 index 0000000..21dd331 --- /dev/null +++ b/src/static/timelinejs/js/locale/sr-la.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"sr",api:{wikipedia:"sr"},date:{month:["januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],month_abbr:["Jan.","Feb.","Mart","Apr.","Maj","Jun","Jul","Avg.","Sep.","Okt.","Nov.","Dec."],day:["Nedelja","Ponedeljak","Utorak","Sreda","ÄŒetvratk","Petak","Subota"],day_abbr:["Ned.","Pon.","Uto.","Sre.","ÄŒet.","Pet.","Sub."]},dateformats:{year:"yyyy.",month_short:"mmm",month:"mmmm yyyy.",full_short:"d. mmm",full:"d. mmmm yyyy.",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d. mmmm yyyy.'</small>'",full_long:"d. mmm yyyy. 'u' HH:MM",full_long_small_date:"HH:MM'<br/><small>d. mmm yyyy.'</small>'"},messages:{loading_timeline:"UÄitavanje... ",return_to_title:"PoÄetak",expand_timeline:"Uvećaj",contract_timeline:"Umanji",wikipedia:"Iz Vikipedije, slobodne enciklopedije",loading_content:"Sadržaj se uÄitava",loading:"UÄitava se"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/sv.js b/src/static/timelinejs/js/locale/sv.js new file mode 100755 index 0000000..8cbe7db --- /dev/null +++ b/src/static/timelinejs/js/locale/sv.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"sv",api:{wikipedia:"sv"},date:{month:["januari","februari","mars","april","maj","juni","juli","augusti","september","oktober","november","december"],month_abbr:["jan","febr","mars","april","maj","juni","juli","aug","sept","okt","nov","dec"],day:["söndag","mÃ¥ndag","tisdag","onsdag","torsdag","fredag","lördag"],day_abbr:["sön","mÃ¥n","tis","ons","tors","fre","lör"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm',' yyyy",time_no_seconds_short:"H:MM",time_no_seconds_small_date:"H:MM'<br/><small>'d mmmm',' yyyy'</small>'",full_long:"d mmm',' yyyy 'vid' H:MM",full_long_small_date:"H:MM'<br/><small>d mmm',' yyyy'</small>'"},messages:{loading_timeline:"Laddar tidslinje... ",return_to_title:"Tillbaka till start",expand_timeline:"Förstora tidslinje",contract_timeline:"Förminska tidslinje",wikipedia:"FrÃ¥n Wikipedia, den fria encyklopedin",loading_content:"Laddar innehÃ¥ll",loading:"Laddar"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/ta.js b/src/static/timelinejs/js/locale/ta.js new file mode 100755 index 0000000..3d44ead --- /dev/null +++ b/src/static/timelinejs/js/locale/ta.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"ta",api:{wikipedia:"ta"},date:{month:["ஜனவரி","பெபà¯à®°à®µà®°à®¿","மாரà¯à®šà¯","à®à®ªà¯à®°à®²à¯","மே","ஜà¯à®©à¯","ஜà¯à®²à¯ˆ","ஆகஸà¯à®Ÿà¯","செபà¯à®Ÿà®®à¯à®ªà®°à¯","ஒகà¯à®Ÿà¯‹à®ªà®°à¯","நவமà¯à®ªà®°à¯","டிசமà¯à®ªà®°à¯"],month_abbr:["ஜன.","பெபà¯.","மாரà¯à®šà¯","à®à®ªà¯à®°à®²à¯","மே","ஜà¯à®©à¯","ஜà¯à®²à¯ˆ","ஆகஸà¯à®Ÿà¯","செபà¯à®Ÿà¯.","ஒகà¯à®Ÿà¯‹.","நவமà¯à®ªà®°à¯","டிசமà¯à®ªà®°à¯"],day:["ஞாயிறà¯","திஙà¯à®•à®³à¯","செவà¯à®µà®¾à®¯à¯","பà¯à®¤à®©à¯","வியாழனà¯","வெளà¯à®³à®¿","சனி"],day_abbr:["ஞா","தி","செ","பà¯","வி","வெ","சனி"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"mmm d',' yyyy 'at' hh:MM TT",full_long_small_date:"hh:MM TT'<br/><small>mmm d',' yyyy'</small>'"},messages:{loading_timeline:"நேரகà¯à®•à¯‹à®Ÿà¯ தரவேறà¯à®•à®¿à®±à®¤à¯.... ",return_to_title:"தலைபà¯à®ªà®¿à®±à¯à®•à¯à®šà¯ செலà¯à®²",expand_timeline:"நேரகà¯à®•à¯‹à®Ÿà¯à®Ÿà¯ˆ விரிகà¯à®•",contract_timeline:"நேரகà¯à®•à¯‹à®Ÿà¯à®Ÿà¯ˆ சà¯à®°à¯à®•à¯à®•",wikipedia:"கடà¯à®Ÿà®±à¯à®± கலைகà¯à®•à®³à®žà¯à®šà®¿à®¯à®®à¯, விகà¯à®•à®¿à®ªà¯à®ªà¯€à®Ÿà®¿à®¯à®¾à®µà®¿à®²à®¿à®°à¯à®¨à¯à®¤à¯",loading_content:"உளà¯à®³à®Ÿà®•à¯à®•à®®à¯ தரவேறà¯à®•à®¿à®±à®¤à¯...",loading:"தரவேறà¯à®•à®¿à®±à®¤à¯"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/tl.js b/src/static/timelinejs/js/locale/tl.js new file mode 100755 index 0000000..24cc87d --- /dev/null +++ b/src/static/timelinejs/js/locale/tl.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"tl",api:{wikipedia:"tl"},date:{month:["Enemo","Pebrero","Marso","Abril","Mayo","Hunyo","Hulyo","Agosto","Setyembre","Oktubre","Nobyembre","Disyembre"],month_abbr:["Ene.","Peb.","Mar.","Abr.","Mayo","Hun.","Hul.","Ago.","Set.","Okt.","Nob.","Dis."],day:["Linggo","Lunes","Martes","Miyerkules","Huwebes","Biyernes","Sabado"],day_abbr:["Li.","L.","M.","Mi.","H.","B.","S."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"mmm d',' yyyy 'at' h:MM TT",full_long_small_date:"h:MM TT'<br/><small>mmm d',' yyyy'</small>'"},messages:{loading_timeline:"Loading Timeline... ",return_to_title:"Return to Title",expand_timeline:"Expand Timeline",contract_timeline:"Contract Timeline",wikipedia:"Mula sa Wikipedia, ang malayang ensiklopedya",loading_content:"Loading Content",loading:"Loading"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/tr.js b/src/static/timelinejs/js/locale/tr.js new file mode 100755 index 0000000..975fa5c --- /dev/null +++ b/src/static/timelinejs/js/locale/tr.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"tr",api:{wikipedia:"tr"},date:{month:["Ocak","Åžubat","Mart","Nisan","Mayıs","Haziran","Temmuz","AÄŸustos","Eylül","Ekim","Kasım","Aralık"],month_abbr:["Oca.","Åžub.","Mar.","Nis.","May.","Haz.","Tem.","AÄŸu.","Eyl.","Eki.","Kas.","Ara."],day:["Pazar","Pazartesi","Salı","ÇarÅŸamba","PerÅŸembe","Cuma","Cumartesi"],day_abbr:["Paz.","Pzt.","Sal.","Çar.","Per.","Cum.","Cts."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm',' yyyy",time_no_seconds_short:"H:MM",time_no_seconds_small_date:"H:MM'<br/><small>'d mmmm',' yyyy'</small>'",full_long:"d mmm',' yyyy 'at' H:MM",full_long_small_date:"H:MM '<br/><small>d mmm',' yyyy'</small>'"},messages:{loading_timeline:"Zaman Çizelgesi Yükleniyor... ",return_to_title:"BaÅŸlığa Dön",expand_timeline:"Zaman Çizelgesini GeniÅŸlet",contract_timeline:"Zaman Çizelgesini Daralt",wikipedia:"Wikipedia'dan, özgür ansiklopedi",loading_content:"İçerik Yükleniyor",loading:"Yükleniyor"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/zh-ch.js b/src/static/timelinejs/js/locale/zh-ch.js new file mode 100755 index 0000000..4114397 --- /dev/null +++ b/src/static/timelinejs/js/locale/zh-ch.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"zh-cn",api:{wikipedia:"zh"},date:{month:["一月","二月","三月","四月","五月","六月","七月","八月","ä¹æœˆ","å月","å一月","å二月"],month_abbr:["一月","二月","三月","四月","五月","六月","七月","八月","ä¹æœˆ","å月","å一月","å二月"],day:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],day_abbr:["周日","周一","周二","周三","周四","周五","周六"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d mmmm yyyy'</small>'",full_long:"dddd',' d mmm yyyy 'um' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d mmm yyyy'</small>'"},messages:{loading_timeline:"加载时间线... ",return_to_title:"回到开头",expand_timeline:"伸展时间",contract_timeline:"缩短时间",wikipedia:"From Wikipedia, the free encyclopedia",loading_content:"Loading Content",loading:"Loading"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/zh-cn.js b/src/static/timelinejs/js/locale/zh-cn.js new file mode 100755 index 0000000..4114397 --- /dev/null +++ b/src/static/timelinejs/js/locale/zh-cn.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"zh-cn",api:{wikipedia:"zh"},date:{month:["一月","二月","三月","四月","五月","六月","七月","八月","ä¹æœˆ","å月","å一月","å二月"],month_abbr:["一月","二月","三月","四月","五月","六月","七月","八月","ä¹æœˆ","å月","å一月","å二月"],day:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],day_abbr:["周日","周一","周二","周三","周四","周五","周六"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d mmmm yyyy'</small>'",full_long:"dddd',' d mmm yyyy 'um' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d mmm yyyy'</small>'"},messages:{loading_timeline:"加载时间线... ",return_to_title:"回到开头",expand_timeline:"伸展时间",contract_timeline:"缩短时间",wikipedia:"From Wikipedia, the free encyclopedia",loading_content:"Loading Content",loading:"Loading"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/locale/zh-tw.js b/src/static/timelinejs/js/locale/zh-tw.js new file mode 100755 index 0000000..63bd1d4 --- /dev/null +++ b/src/static/timelinejs/js/locale/zh-tw.js @@ -0,0 +1,2 @@ +/* LANGUAGE +================================================== */typeof VMM!="undefined"&&(VMM.Language={lang:"zh-tw",api:{wikipedia:"zh"},date:{month:["一月","二月","三月","四月","五月","六月","七月","八月","ä¹æœˆ","å月","å一月","å二月"],month_abbr:["一月","二月","三月","四月","五月","六月","七月","八月","ä¹æœˆ","å月","å一月","å二月"],day:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],day_abbr:["週日","週一","週二","週三","週四","週五","週六"]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"d mmm",full:"d mmmm yyyy",time_no_seconds_short:"HH:MM",time_no_seconds_small_date:"HH:MM'<br/><small>'d mmmm yyyy'</small>'",full_long:"dddd',' d mmm yyyy 'um' HH:MM",full_long_small_date:"HH:MM'<br/><small>'dddd',' d mmm yyyy'</small>'"},messages:{loading_timeline:"載入時間線... ",return_to_title:"回到開頭",expand_timeline:"展開時間",contract_timeline:"縮短時間",wikipedia:"æ“·å–自維基百科, 自由之百科全書",loading_content:"載入內容",loading:"載入中"}}); \ No newline at end of file diff --git a/src/static/timelinejs/js/storyjs-embed.js b/src/static/timelinejs/js/storyjs-embed.js new file mode 100755 index 0000000..3204326 --- /dev/null +++ b/src/static/timelinejs/js/storyjs-embed.js @@ -0,0 +1,45 @@ +/*! + StoryJS + Designed and built by Zach Wise at VéritéCo + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*//* ********************************************** + Begin LazyLoad.js +********************************************** *//*jslint browser: true, eqeqeq: true, bitwise: true, newcap: true, immed: true, regexp: false *//* +LazyLoad makes it easy and painless to lazily load one or more external +JavaScript or CSS files on demand either during or after the rendering of a web +page. + +Supported browsers include Firefox 2+, IE6+, Safari 3+ (including Mobile +Safari), Google Chrome, and Opera 9+. Other browsers may or may not work and +are not officially supported. + +Visit https://github.com/rgrove/lazyload/ for more info. + +Copyright (c) 2011 Ryan Grove <ryan@wonko.com> +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the 'Software'), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +@module lazyload +@class LazyLoad +@static +@version 2.0.3 (git) +*/function getEmbedScriptPath(e){var t=document.getElementsByTagName("script"),n="",r="";for(var i=0;i<t.length;i++)t[i].src.match(e)&&(n=t[i].src);n!=""&&(r="/");return n.split("?")[0].split("/").slice(0,-1).join("/")+r}function createStoryJS(e,t){function g(){LoadLib.js(h.js,y)}function y(){l.js=!0;h.lang!="en"?LazyLoad.js(c.locale,b):l.language=!0;x()}function b(){l.language=!0;x()}function w(){l.css=!0;x()}function E(){l.font.css=!0;x()}function S(){l.font.js=!0;x()}function x(){if(l.checks>40)return;l.checks++;if(l.js&&l.css&&l.font.css&&l.font.js&&l.language){if(!l.finished){l.finished=!0;N()}}else l.timeout=setTimeout("onloaded_check_again();",250)}function T(){var e="storyjs-embed";r=document.createElement("div");h.embed_id!=""?i=document.getElementById(h.embed_id):i=document.getElementById("timeline-embed");i.appendChild(r);r.setAttribute("id",h.id);if(h.width.toString().match("%"))i.style.width=h.width.split("%")[0]+"%";else{h.width=h.width-2;i.style.width=h.width+"px"}if(h.height.toString().match("%")){i.style.height=h.height;e+=" full-embed";i.style.height=h.height.split("%")[0]+"%"}else if(h.width.toString().match("%")){e+=" full-embed";h.height=h.height-16;i.style.height=h.height+"px"}else{e+=" sized-embed";h.height=h.height-16;i.style.height=h.height+"px"}i.setAttribute("class",e);i.setAttribute("className",e);r.style.position="relative"}function N(){VMM.debug=h.debug;n=new VMM.Timeline(h.id);n.init(h);o&&VMM.bindEvent(global,onHeadline,"HEADLINE")}var n,r,i,s,o=!1,u="2.17",a="1.7.1",f="",l={timeout:"",checks:0,finished:!1,js:!1,css:!1,jquery:!1,has_jquery:!1,language:!1,font:{css:!1,js:!1}},c={base:embed_path,css:embed_path+"css/",js:embed_path+"js/",locale:embed_path+"js/locale/",jquery:"http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js",font:{google:!1,css:embed_path+"css/themes/font/",js:"http://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"}},h={version:u,debug:!1,type:"timeline",id:"storyjs",embed_id:"timeline-embed",embed:!0,width:"100%",height:"100%",source:"https://docs.google.com/spreadsheet/pub?key=0Agl_Dv6iEbDadFYzRjJPUGktY0NkWXFUWkVIZDNGRHc&output=html",lang:"en",font:"default",css:c.css+"timeline.css?"+u,js:"",api_keys:{google:"",flickr:"",twitter:""},gmap_key:""},p=[{name:"Merriweather-NewsCycle",google:["News+Cycle:400,700:latin","Merriweather:400,700,900:latin"]},{name:"NewsCycle-Merriweather",google:["News+Cycle:400,700:latin","Merriweather:300,400,700:latin"]},{name:"PoiretOne-Molengo",google:["Poiret+One::latin","Molengo::latin"]},{name:"Arvo-PTSans",google:["Arvo:400,700,400italic:latin","PT+Sans:400,700,400italic:latin"]},{name:"PTSerif-PTSans",google:["PT+Sans:400,700,400italic:latin","PT+Serif:400,700,400italic:latin"]},{name:"PT",google:["PT+Sans+Narrow:400,700:latin","PT+Sans:400,700,400italic:latin","PT+Serif:400,700,400italic:latin"]},{name:"DroidSerif-DroidSans",google:["Droid+Sans:400,700:latin","Droid+Serif:400,700,400italic:latin"]},{name:"Lekton-Molengo",google:["Lekton:400,700,400italic:latin","Molengo::latin"]},{name:"NixieOne-Ledger",google:["Nixie+One::latin","Ledger::latin"]},{name:"AbrilFatface-Average",google:["Average::latin","Abril+Fatface::latin"]},{name:"PlayfairDisplay-Muli",google:["Playfair+Display:400,400italic:latin","Muli:300,400,300italic,400italic:latin"]},{name:"Rancho-Gudea",google:["Rancho::latin","Gudea:400,700,400italic:latin"]},{name:"Bevan-PotanoSans",google:["Bevan::latin","Pontano+Sans::latin"]},{name:"BreeSerif-OpenSans",google:["Bree+Serif::latin","Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800:latin"]},{name:"SansitaOne-Kameron",google:["Sansita+One::latin","Kameron:400,700:latin"]},{name:"Lora-Istok",google:["Lora:400,700,400italic,700italic:latin","Istok+Web:400,700,400italic,700italic:latin"]},{name:"Pacifico-Arimo",google:["Pacifico::latin","Arimo:400,700,400italic,700italic:latin"]}];if(typeof e=="object")for(s in e)Object.prototype.hasOwnProperty.call(e,s)&&(h[s]=e[s]);typeof t!="undefined"&&(h.source=t);if(typeof url_config=="object"){o=!0;h.source.match("docs.google.com")||h.source.match("json")||h.source.match("storify")||(h.source="https://docs.google.com/spreadsheet/pub?key="+h.source+"&output=html")}if(h.js.match("locale")){h.lang=h.js.split("locale/")[1].replace(".js","");h.js=c.js+"timeline-min.js?"+u}if(!h.js.match("/")){h.css=c.css+h.type+".css?"+u;h.js=c.js+h.type;h.debug?h.js+=".js?"+u:h.js+="-min.js?"+u;h.id="storyjs-"+h.type}h.lang.match("/")?c.locale=h.lang:c.locale=c.locale+h.lang+".js?"+u;T();LoadLib.css(h.css,w);if(h.font=="default"){l.font.js=!0;l.font.css=!0}else{var d;if(h.font.match("/")){d=h.font.split(".css")[0].split("/");c.font.name=d[d.length-1];c.font.css=h.font}else{c.font.name=h.font;c.font.css=c.font.css+h.font+".css?"+u}LoadLib.css(c.font.css,E);for(var v=0;v<p.length;v++)if(c.font.name==p[v].name){c.font.google=!0;WebFontConfig={google:{families:p[v].google}}}c.font.google?LoadLib.js(c.font.js,S):l.font.js=!0}try{l.has_jquery=jQuery;l.has_jquery=!0;if(l.has_jquery){var f=parseFloat(jQuery.fn.jquery);f<parseFloat(a)?l.jquery=!1:l.jquery=!0}}catch(m){l.jquery=!1}l.jquery?g():LoadLib.js(c.jquery,g);this.onloaded_check_again=function(){x()}}LazyLoad=function(e){function u(t,n){var r=e.createElement(t),i;for(i in n)n.hasOwnProperty(i)&&r.setAttribute(i,n[i]);return r}function a(e){var t=r[e],n,o;if(t){n=t.callback;o=t.urls;o.shift();i=0;if(!o.length){n&&n.call(t.context,t.obj);r[e]=null;s[e].length&&l(e)}}}function f(){var n=navigator.userAgent;t={async:e.createElement("script").async===!0};(t.webkit=/AppleWebKit\//.test(n))||(t.ie=/MSIE/.test(n))||(t.opera=/Opera/.test(n))||(t.gecko=/Gecko\//.test(n))||(t.unknown=!0)}function l(i,o,l,p,d){var v=function(){a(i)},m=i==="css",g=[],y,b,w,E,S,x;t||f();if(o){o=typeof o=="string"?[o]:o.concat();if(m||t.async||t.gecko||t.opera)s[i].push({urls:o,callback:l,obj:p,context:d});else for(y=0,b=o.length;y<b;++y)s[i].push({urls:[o[y]],callback:y===b-1?l:null,obj:p,context:d})}if(r[i]||!(E=r[i]=s[i].shift()))return;n||(n=e.head||e.getElementsByTagName("head")[0]);S=E.urls;for(y=0,b=S.length;y<b;++y){x=S[y];if(m)w=t.gecko?u("style"):u("link",{href:x,rel:"stylesheet"});else{w=u("script",{src:x});w.async=!1}w.className="lazyload";w.setAttribute("charset","utf-8");if(t.ie&&!m)w.onreadystatechange=function(){if(/loaded|complete/.test(w.readyState)){w.onreadystatechange=null;v()}};else if(m&&(t.gecko||t.webkit))if(t.webkit){E.urls[y]=w.href;h()}else{w.innerHTML='@import "'+x+'";';c(w)}else w.onload=w.onerror=v;g.push(w)}for(y=0,b=g.length;y<b;++y)n.appendChild(g[y])}function c(e){var t;try{t=!!e.sheet.cssRules}catch(n){i+=1;i<200?setTimeout(function(){c(e)},50):t&&a("css");return}a("css")}function h(){var e=r.css,t;if(e){t=o.length;while(--t>=0)if(o[t].href===e.urls[0]){a("css");break}i+=1;e&&(i<200?setTimeout(h,50):a("css"))}}var t,n,r={},i=0,s={css:[],js:[]},o=e.styleSheets;return{css:function(e,t,n,r){l("css",e,t,n,r)},js:function(e,t,n,r){l("js",e,t,n,r)}}}(this.document);LoadLib=function(e){function n(e){var n=0,r=!1;for(n=0;n<t.length;n++)t[n]==e&&(r=!0);if(r)return!0;t.push(e);return!1}var t=[];return{css:function(e,t,r,i){n(e)||LazyLoad.css(e,t,r,i)},js:function(e,t,r,i){n(e)||LazyLoad.js(e,t,r,i)}}}(this.document);var WebFontConfig;if(typeof embed_path=="undefined"||typeof embed_path=="undefined")var embed_path=getEmbedScriptPath("storyjs-embed.js").split("js/")[0];(function(){typeof url_config=="object"?createStoryJS(url_config):typeof timeline_config=="object"?createStoryJS(timeline_config):typeof storyjs_config=="object"?createStoryJS(storyjs_config):typeof config=="object"&&createStoryJS(config)})(); \ No newline at end of file diff --git a/src/static/timelinejs/js/timeline-min.js b/src/static/timelinejs/js/timeline-min.js new file mode 100755 index 0000000..b5eb93b --- /dev/null +++ b/src/static/timelinejs/js/timeline-min.js @@ -0,0 +1,36 @@ +/*! + TimelineJS + Version 2.17 + Designed and built by Zach Wise at VéritéCo + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +*//* ********************************************** + Begin VMM.StoryJS.License.js +********************************************** *//*! + StoryJS + Designed and built by Zach Wise at VéritéCo + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*//* ********************************************** + Begin VMM.js +********************************************** *//** + * VéritéCo JS Core + * Designed and built by Zach Wise at VéritéCo zach@verite.co + + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + +*//* Simple JavaScript Inheritance + By John Resig http://ejohn.org/ + MIT Licensed. +================================================== */function trace(e){VMM.debug&&(window.console?console.log(e):typeof jsTrace!="undefined"&&jsTrace.send(e))}function onYouTubePlayerAPIReady(){trace("GLOBAL YOUTUBE API CALLED");VMM.ExternalAPI.youtube.onAPIReady()}(function(){var e=!1,t=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend=function(n){function o(){!e&&this.init&&this.init.apply(this,arguments)}var r=this.prototype;e=!0;var i=new this;e=!1;for(var s in n)i[s]=typeof n[s]=="function"&&typeof r[s]=="function"&&t.test(n[s])?function(e,t){return function(){var n=this._super;this._super=r[e];var i=t.apply(this,arguments);this._super=n;return i}}(s,n[s]):n[s];o.prototype=i;o.prototype.constructor=o;o.extend=arguments.callee;return o}})();var global=function(){return this||(1,eval)("this")}();if(typeof VMM=="undefined"){var VMM=Class.extend({});VMM.debug=!0;VMM.master_config={init:function(){return this},sizes:{api:{width:0,height:0}},vp:"Pellentesque nibh felis, eleifend id, commodo in, interdum vitae, leo",api_keys_master:{flickr:"RAIvxHY4hE/Elm5cieh4X5ptMyDpj7MYIxziGxi0WGCcy1s+yr7rKQ==",google:"uQKadH1VMlCsp560gN2aOiMz4evWkl1s34yryl3F/9FJOsn+/948CbBUvKLN46U=",twitter:""},timers:{api:7e3},api:{pushques:[]},twitter:{active:!1,array:[],api_loaded:!1,que:[]},flickr:{active:!1,array:[],api_loaded:!1,que:[]},youtube:{active:!1,array:[],api_loaded:!1,que:[]},vimeo:{active:!1,array:[],api_loaded:!1,que:[]},webthumb:{active:!1,array:[],api_loaded:!1,que:[]},googlemaps:{active:!1,map_active:!1,places_active:!1,array:[],api_loaded:!1,que:[]},googledocs:{active:!1,array:[],api_loaded:!1,que:[]},googleplus:{active:!1,array:[],api_loaded:!1,que:[]},wikipedia:{active:!1,array:[],api_loaded:!1,que:[],tries:0},soundcloud:{active:!1,array:[],api_loaded:!1,que:[]}}.init();VMM.createElement=function(e,t,n,r,i){var s="";if(e!=null&&e!=""){s+="<"+e;n!=null&&n!=""&&(s+=" class='"+n+"'");r!=null&&r!=""&&(s+=" "+r);i!=null&&i!=""&&(s+=" style='"+i+"'");s+=">";t!=null&&t!=""&&(s+=t);s=s+"</"+e+">"}return s};VMM.createMediaElement=function(e,t,n){var r="",i=!1;r+="<div class='media'>";if(e!=null&&e!=""){valid=!0;r+="<img src='"+e+"'>";n!=null&&n!=""&&(r+=VMM.createElement("div",n,"credit"));t!=null&&t!=""&&(r+=VMM.createElement("div",t,"caption"))}r+="</div>";return r};VMM.hideUrlBar=function(){var e=window,t=e.document;if(!location.hash||!e.addEventListener){window.scrollTo(0,1);var n=1,r=setInterval(function(){if(t.body){clearInterval(r);n="scrollTop"in t.body?t.body.scrollTop:1;e.scrollTo(0,n===1?0:1)}},15);e.addEventListener("load",function(){setTimeout(function(){e.scrollTo(0,n===1?0:1)},0)},!1)}}}Array.prototype.remove=function(e,t){var n=this.slice((t||e)+1||this.length);this.length=e<0?this.length+e:e;return this.push.apply(this,n)};Date.prototype.getWeek=function(){var e=new Date(this.getFullYear(),0,1);return Math.ceil(((this-e)/864e5+e.getDay()+1)/7)};Date.prototype.getDayOfYear=function(){var e=new Date(this.getFullYear(),0,1);return Math.ceil((this-e)/864e5)};var is={Null:function(e){return e===null},Undefined:function(e){return e===undefined},nt:function(e){return e===null||e===undefined},Function:function(e){return typeof e=="function"?e.constructor.toString().match(/Function/)!==null:!1},String:function(e){return typeof e=="string"?!0:typeof e=="object"?e.constructor.toString().match(/string/i)!==null:!1},Array:function(e){return typeof e=="object"?e.constructor.toString().match(/array/i)!==null||e.length!==undefined:!1},Boolean:function(e){return typeof e=="boolean"?!0:typeof e=="object"?e.constructor.toString().match(/boolean/i)!==null:!1},Date:function(e){return typeof e=="date"?!0:typeof e=="object"?e.constructor.toString().match(/date/i)!==null:!1},HTML:function(e){return typeof e=="object"?e.constructor.toString().match(/html/i)!==null:!1},Number:function(e){return typeof e=="number"?!0:typeof e=="object"?e.constructor.toString().match(/Number/)!==null:!1},Object:function(e){return typeof e=="object"?e.constructor.toString().match(/object/i)!==null:!1},RegExp:function(e){return typeof e=="function"?e.constructor.toString().match(/regexp/i)!==null:!1}},type={of:function(e){for(var t in is)if(is[t](e))return t.toLowerCase()}};if(typeof VMM!="undefined"){VMM.smoothScrollTo=function(e,t,n){if(typeof jQuery!="undefined"){var r="easein",i=1e3;t!=null&&(t<1?i=1:i=Math.round(t));n!=null&&n!=""&&(r=n);jQuery(window).scrollTop()!=VMM.Lib.offset(e).top&&VMM.Lib.animate("html,body",i,r,{scrollTop:VMM.Lib.offset(e).top})}};VMM.attachElement=function(e,t){typeof jQuery!="undefined"&&jQuery(e).html(t)};VMM.appendElement=function(e,t){typeof jQuery!="undefined"&&jQuery(e).append(t)};VMM.getHTML=function(e){var t;if(typeof jQuery!="undefined"){t=jQuery(e).html();return t}};VMM.getElement=function(e,t){var n;if(typeof jQuery!="undefined"){t?n=jQuery(e).parent().get(0):n=jQuery(e).get(0);return n}};VMM.bindEvent=function(e,t,n,r){var i,s="click",o={};n!=null&&n!=""&&(s=n);o!=null&&o!=""&&(o=r);typeof jQuery!="undefined"&&jQuery(e).bind(s,o,t)};VMM.unbindEvent=function(e,t,n){var r,i="click",s={};n!=null&&n!=""&&(i=n);typeof jQuery!="undefined"&&jQuery(e).unbind(i,t)};VMM.fireEvent=function(e,t,n){var r,i="click",s=[];t!=null&&t!=""&&(i=t);n!=null&&n!=""&&(s=n);typeof jQuery!="undefined"&&jQuery(e).trigger(i,s)};VMM.getJSON=function(e,t,n){if(typeof jQuery!="undefined"){jQuery.ajaxSetup({timeout:3e3});if(VMM.Browser.browser=="Explorer"&&parseInt(VMM.Browser.version,10)>=7&&window.XDomainRequest){trace("IE JSON");var r=e;if(r.match("^http://"))return jQuery.getJSON(r,t,n);if(r.match("^https://")){r=r.replace("https://","http://");return jQuery.getJSON(r,t,n)}return jQuery.getJSON(e,t,n)}return jQuery.getJSON(e,t,n)}};VMM.parseJSON=function(e){if(typeof jQuery!="undefined")return jQuery.parseJSON(e)};VMM.appendAndGetElement=function(e,t,n,r){var i,s="<div>",o="",u="",a="";t!=null&&t!=""&&(s=t);n!=null&&n!=""&&(o=n);r!=null&&r!=""&&(u=r);if(typeof jQuery!="undefined"){i=jQuery(t);i.addClass(o);i.html(u);jQuery(e).append(i)}return i};VMM.Lib={init:function(){return this},hide:function(e,t){t!=null&&t!=""?typeof jQuery!="undefined"&&jQuery(e).hide(t):typeof jQuery!="undefined"&&jQuery(e).hide()},remove:function(e){typeof jQuery!="undefined"&&jQuery(e).remove()},detach:function(e){typeof jQuery!="undefined"&&jQuery(e).detach()},append:function(e,t){typeof jQuery!="undefined"&&jQuery(e).append(t)},prepend:function(e,t){typeof jQuery!="undefined"&&jQuery(e).prepend(t)},show:function(e,t){t!=null&&t!=""?typeof jQuery!="undefined"&&jQuery(e).show(t):typeof jQuery!="undefined"&&jQuery(e).show()},load:function(e,t,n){var r={elem:e};r!=null&&r!=""&&(r=n);typeof jQuery!="undefined"&&jQuery(e).load(r,t)},addClass:function(e,t){typeof jQuery!="undefined"&&jQuery(e).addClass(t)},removeClass:function(e,t){typeof jQuery!="undefined"&&jQuery(e).removeClass(t)},attr:function(e,t,n){if(n!=null&&n!="")typeof jQuery!="undefined"&&jQuery(e).attr(t,n);else if(typeof jQuery!="undefined")return jQuery(e).attr(t)},prop:function(e,t,n){typeof jQuery=="undefined"||!/[1-9]\.[3-9].[1-9]/.test(jQuery.fn.jquery)?VMM.Lib.attribute(e,t,n):jQuery(e).prop(t,n)},attribute:function(e,t,n){if(n!=null&&n!="")typeof jQuery!="undefined"&&jQuery(e).attr(t,n);else if(typeof jQuery!="undefined")return jQuery(e).attr(t)},visible:function(e,t){if(t!=null)typeof jQuery!="undefined"&&(t?jQuery(e).show(0):jQuery(e).hide(0));else if(typeof jQuery!="undefined")return jQuery(e).is(":visible")?!0:!1},css:function(e,t,n){if(n!=null&&n!="")typeof jQuery!="undefined"&&jQuery(e).css(t,n);else if(typeof jQuery!="undefined")return jQuery(e).css(t)},cssmultiple:function(e,t){if(typeof jQuery!="undefined")return jQuery(e).css(t)},offset:function(e){var t;typeof jQuery!="undefined"&&(t=jQuery(e).offset());return t},position:function(e){var t;typeof jQuery!="undefined"&&(t=jQuery(e).position());return t},width:function(e,t){if(t!=null&&t!="")typeof jQuery!="undefined"&&jQuery(e).width(t);else if(typeof jQuery!="undefined")return jQuery(e).width()},height:function(e,t){if(t!=null&&t!="")typeof jQuery!="undefined"&&jQuery(e).height(t);else if(typeof jQuery!="undefined")return jQuery(e).height()},toggleClass:function(e,t){typeof jQuery!="undefined"&&jQuery(e).toggleClass(t)},each:function(e,t){typeof jQuery!="undefined"&&jQuery(e).each(t)},html:function(e,t){var n;if(typeof jQuery!="undefined"){n=jQuery(e).html();return n}if(t!=null&&t!="")typeof jQuery!="undefined"&&jQuery(e).html(t);else{var n;if(typeof jQuery!="undefined"){n=jQuery(e).html();return n}}},find:function(e,t){if(typeof jQuery!="undefined")return jQuery(e).find(t)},stop:function(e){typeof jQuery!="undefined"&&jQuery(e).stop()},delay_animate:function(e,t,n,r,i,s){if(VMM.Browser.device=="mobile"||VMM.Browser.device=="tablet"){var o=Math.round(n/1500*10)/10,u=o+"s";VMM.Lib.css(t,"-webkit-transition","all "+u+" ease");VMM.Lib.css(t,"-moz-transition","all "+u+" ease");VMM.Lib.css(t,"-o-transition","all "+u+" ease");VMM.Lib.css(t,"-ms-transition","all "+u+" ease");VMM.Lib.css(t,"transition","all "+u+" ease");VMM.Lib.cssmultiple(t,_att)}else typeof jQuery!="undefined"&&jQuery(t).delay(e).animate(i,{duration:n,easing:r})},animate:function(e,t,n,r,i,s){var o="easein",u=!1,a=1e3,f={};t!=null&&(t<1?a=1:a=Math.round(t));n!=null&&n!=""&&(o=n);i!=null&&i!=""&&(u=i);r!=null?f=r:f={opacity:0};if(VMM.Browser.device=="mobile"||VMM.Browser.device=="tablet"){var l=Math.round(a/1500*10)/10,c=l+"s";o=" cubic-bezier(0.33, 0.66, 0.66, 1)";for(x in f)if(Object.prototype.hasOwnProperty.call(f,x)){trace(x+" to "+f[x]);VMM.Lib.css(e,"-webkit-transition",x+" "+c+o);VMM.Lib.css(e,"-moz-transition",x+" "+c+o);VMM.Lib.css(e,"-o-transition",x+" "+c+o);VMM.Lib.css(e,"-ms-transition",x+" "+c+o);VMM.Lib.css(e,"transition",x+" "+c+o)}VMM.Lib.cssmultiple(e,f)}else typeof jQuery!="undefined"&&(s!=null&&s!=""?jQuery(e).animate(f,{queue:u,duration:a,easing:o,complete:s}):jQuery(e).animate(f,{queue:u,duration:a,easing:o}))}}}if(typeof jQuery!="undefined"){(function(e){window.XDomainRequest&&e.ajaxTransport(function(t){if(t.crossDomain&&t.async){if(t.timeout){t.xdrTimeout=t.timeout;delete t.timeout}var n;return{send:function(r,i){function o(t,r,s,o){n.onload=n.onerror=n.ontimeout=e.noop;n=undefined;i(t,r,s,o)}n=new XDomainRequest;n.open(t.type,t.url);n.onload=function(){o(200,"OK",{text:n.responseText},"Content-Type: "+n.contentType)};n.onerror=function(){o(404,"Not Found")};if(t.xdrTimeout){n.ontimeout=function(){o(0,"timeout")};n.timeout=t.xdrTimeout}n.send(t.hasContent&&t.data||null)},abort:function(){if(n){n.onerror=e.noop();n.abort()}}}}})})(jQuery);jQuery.easing.jswing=jQuery.easing.swing;jQuery.extend(jQuery.easing,{def:"easeOutQuad",swing:function(e,t,n,r,i){return jQuery.easing[jQuery.easing.def](e,t,n,r,i)},easeInExpo:function(e,t,n,r,i){return t==0?n:r*Math.pow(2,10*(t/i-1))+n},easeOutExpo:function(e,t,n,r,i){return t==i?n+r:r*(-Math.pow(2,-10*t/i)+1)+n},easeInOutExpo:function(e,t,n,r,i){return t==0?n:t==i?n+r:(t/=i/2)<1?r/2*Math.pow(2,10*(t-1))+n:r/2*(-Math.pow(2,-10*--t)+2)+n},easeInQuad:function(e,t,n,r,i){return r*(t/=i)*t+n},easeOutQuad:function(e,t,n,r,i){return-r*(t/=i)*(t-2)+n},easeInOutQuad:function(e,t,n,r,i){return(t/=i/2)<1?r/2*t*t+n:-r/2*(--t*(t-2)-1)+n}})}if(typeof VMM!="undefined"&&typeof VMM.Browser=="undefined"){VMM.Browser={init:function(){this.browser=this.searchString(this.dataBrowser)||"An unknown browser";this.version=this.searchVersion(navigator.userAgent)||this.searchVersion(navigator.appVersion)||"an unknown version";this.OS=this.searchString(this.dataOS)||"an unknown OS";this.device=this.searchDevice(navigator.userAgent);this.orientation=this.searchOrientation(window.orientation)},searchOrientation:function(e){var t="";e==0||e==180?t="portrait":e==90||e==-90?t="landscape":t="normal";return t},searchDevice:function(e){var t="";e.match(/Android/i)||e.match(/iPhone|iPod/i)?t="mobile":e.match(/iPad/i)?t="tablet":e.match(/BlackBerry/i)||e.match(/IEMobile/i)?t="other mobile":t="desktop";return t},searchString:function(e){for(var t=0;t<e.length;t++){var n=e[t].string,r=e[t].prop;this.versionSearchString=e[t].versionSearch||e[t].identity;if(n){if(n.indexOf(e[t].subString)!=-1)return e[t].identity}else if(r)return e[t].identity}},searchVersion:function(e){var t=e.indexOf(this.versionSearchString);if(t==-1)return;return parseFloat(e.substring(t+this.versionSearchString.length+1))},dataBrowser:[{string:navigator.userAgent,subString:"Chrome",identity:"Chrome"},{string:navigator.userAgent,subString:"OmniWeb",versionSearch:"OmniWeb/",identity:"OmniWeb"},{string:navigator.vendor,subString:"Apple",identity:"Safari",versionSearch:"Version"},{prop:window.opera,identity:"Opera",versionSearch:"Version"},{string:navigator.vendor,subString:"iCab",identity:"iCab"},{string:navigator.vendor,subString:"KDE",identity:"Konqueror"},{string:navigator.userAgent,subString:"Firefox",identity:"Firefox"},{string:navigator.vendor,subString:"Camino",identity:"Camino"},{string:navigator.userAgent,subString:"Netscape",identity:"Netscape"},{string:navigator.userAgent,subString:"MSIE",identity:"Explorer",versionSearch:"MSIE"},{string:navigator.userAgent,subString:"Gecko",identity:"Mozilla",versionSearch:"rv"},{string:navigator.userAgent,subString:"Mozilla",identity:"Netscape",versionSearch:"Mozilla"}],dataOS:[{string:navigator.platform,subString:"Win",identity:"Windows"},{string:navigator.platform,subString:"Mac",identity:"Mac"},{string:navigator.userAgent,subString:"iPhone",identity:"iPhone/iPod"},{string:navigator.userAgent,subString:"iPad",identity:"iPad"},{string:navigator.platform,subString:"Linux",identity:"Linux"}]};VMM.Browser.init()}typeof VMM!="undefined"&&typeof VMM.FileExtention=="undefined"&&(VMM.FileExtention={googleDocType:function(e){var t=e.replace(/\s\s*$/,""),n="",r=["DOC","DOCX","XLS","XLSX","PPT","PPTX","PDF","PAGES","AI","PSD","TIFF","DXF","SVG","EPS","PS","TTF","XPS","ZIP","RAR"],i=!1;n=t.substr(t.length-5,5);for(var s=0;s<r.length;s++)if(n.toLowerCase().match(r[s].toString().toLowerCase())||t.match("docs.google.com"))i=!0;return i}});if(typeof VMM!="undefined"&&typeof VMM.Date=="undefined"){VMM.Date={init:function(){return this},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"mmm d',' yyyy 'at' hh:MM TT",full_long_small_date:"hh:MM TT'<br/><small>mmm d',' yyyy'</small>'"},month:["January","February","March","April","May","June","July","August","September","October","November","December"],month_abbr:["Jan.","Feb.","March","April","May","June","July","Aug.","Sept.","Oct.","Nov.","Dec."],day:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],day_abbr:["Sun.","Mon.","Tues.","Wed.","Thurs.","Fri.","Sat."],hour:[1,2,3,4,5,6,7,8,9,10,11,12,1,2,3,4,5,6,7,8,9,10,11,12],hour_suffix:["am"],bc_format:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time_no_seconds_short:"h:MM TT",time_no_seconds_small_date:"dddd', 'h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"dddd',' mmm d',' yyyy 'at' hh:MM TT",full_long_small_date:"hh:MM TT'<br/><small>'dddd',' mmm d',' yyyy'</small>'"},setLanguage:function(e){trace("SET DATE LANGUAGE");VMM.Date.dateformats=e.dateformats;VMM.Date.month=e.date.month;VMM.Date.month_abbr=e.date.month_abbr;VMM.Date.day=e.date.day;VMM.Date.day_abbr=e.date.day_abbr;dateFormat.i18n.dayNames=e.date.day_abbr.concat(e.date.day);dateFormat.i18n.monthNames=e.date.month_abbr.concat(e.date.month)},parse:function(e,t){"use strict";var n,r,i,s,o={year:!1,month:!1,day:!1,hour:!1,minute:!1,second:!1,millisecond:!1};if(type.of(e)=="date")n=e;else{n=new Date(0,0,1,0,0,0,0);if(e.match(/,/gi)){r=e.split(",");for(var u=0;u<r.length;u++)r[u]=parseInt(r[u],10);if(r[0]){n.setFullYear(r[0]);o.year=!0}if(r[1]){n.setMonth(r[1]-1);o.month=!0}if(r[2]){n.setDate(r[2]);o.day=!0}if(r[3]){n.setHours(r[3]);o.hour=!0}if(r[4]){n.setMinutes(r[4]);o.minute=!0}if(r[5]){n.setSeconds(r[5]);o.second=!0}if(r[6]){n.setMilliseconds(r[6]);o.millisecond=!0}}else if(e.match("/")){if(e.match(" ")){s=e.split(" ");if(e.match(":")){i=s[1].split(":");if(i[0]>=0){n.setHours(i[0]);o.hour=!0}if(i[1]>=0){n.setMinutes(i[1]);o.minute=!0}if(i[2]>=0){n.setSeconds(i[2]);o.second=!0}if(i[3]>=0){n.setMilliseconds(i[3]);o.millisecond=!0}}r=s[0].split("/")}else r=e.split("/");if(r[2]){n.setFullYear(r[2]);o.year=!0}if(r[0]>=0){n.setMonth(r[0]-1);o.month=!0}if(r[1]>=0)if(r[1].length>2){n.setFullYear(r[1]);o.year=!0}else{n.setDate(r[1]);o.day=!0}}else if(e.match("now")){var a=new Date;n.setFullYear(a.getFullYear());o.year=!0;n.setMonth(a.getMonth());o.month=!0;n.setDate(a.getDate());o.day=!0;if(e.match("hours")){n.setHours(a.getHours());o.hour=!0}if(e.match("minutes")){n.setHours(a.getHours());n.setMinutes(a.getMinutes());o.hour=!0;o.minute=!0}if(e.match("seconds")){n.setHours(a.getHours());n.setMinutes(a.getMinutes());n.setSeconds(a.getSeconds());o.hour=!0;o.minute=!0;o.second=!0}if(e.match("milliseconds")){n.setHours(a.getHours());n.setMinutes(a.getMinutes());n.setSeconds(a.getSeconds());n.setMilliseconds(a.getMilliseconds());o.hour=!0;o.minute=!0;o.second=!0;o.millisecond=!0}}else if(e.length<=5){o.year=!0;n.setFullYear(parseInt(e,10));n.setMonth(0);n.setDate(1);n.setHours(0);n.setMinutes(0);n.setSeconds(0);n.setMilliseconds(0)}else if(e.match("T"))if(navigator.userAgent.match(/MSIE\s(?!9.0)/)){s=e.split("T");if(e.match(":")){i=s[1].split(":");if(i[0]>=1){n.setHours(i[0]);o.hour=!0}if(i[1]>=1){n.setMinutes(i[1]);o.minute=!0}if(i[2]>=1){n.setSeconds(i[2]);o.second=!0}if(i[3]>=1){n.setMilliseconds(i[3]);o.millisecond=!0}}r=s[0].split("-");if(r[0]){n.setFullYear(r[0]);o.year=!0}if(r[1]>=0){n.setMonth(r[1]-1);o.month=!0}if(r[2]>=0){n.setDate(r[2]);o.day=!0}}else n=new Date(Date.parse(e));else{o.year=!0;o.month=!0;o.day=!0;o.hour=!0;o.minute=!0;o.second=!0;o.millisecond=!0;n=new Date(parseInt(e.slice(0,4),10),parseInt(e.slice(4,6),10)-1,parseInt(e.slice(6,8),10),parseInt(e.slice(8,10),10),parseInt(e.slice(10,12),10))}}return t!=null&&t!=""?{date:n,precision:o}:n},prettyDate:function(e,t,n,r){var i,s,o,u,a=!1,f,l,c;if(r!=null&&r!=""&&typeof r!="undefined"){a=!0;trace("D2 "+r)}if(type.of(e)=="date"){type.of(n)=="object"?n.millisecond||n.second||n.minute?t?o=VMM.Date.dateformats.time_no_seconds_short:o=VMM.Date.dateformats.time_no_seconds_small_date:n.hour?t?o=VMM.Date.dateformats.time_no_seconds_short:o=VMM.Date.dateformats.time_no_seconds_small_date:n.day?t?o=VMM.Date.dateformats.full_short:o=VMM.Date.dateformats.full:n.month?t?o=VMM.Date.dateformats.month_short:o=VMM.Date.dateformats.month:n.year?o=VMM.Date.dateformats.year:o=VMM.Date.dateformats.year:e.getMonth()===0&&e.getDate()==1&&e.getHours()===0&&e.getMinutes()===0?o=VMM.Date.dateformats.year:e.getDate()<=1&&e.getHours()===0&&e.getMinutes()===0?t?o=VMM.Date.dateformats.month_short:o=VMM.Date.dateformats.month:e.getHours()===0&&e.getMinutes()===0?t?o=VMM.Date.dateformats.full_short:o=VMM.Date.dateformats.full:e.getMinutes()===0?t?o=VMM.Date.dateformats.time_no_seconds_short:o=VMM.Date.dateformats.time_no_seconds_small_date:t?o=VMM.Date.dateformats.time_no_seconds_short:o=VMM.Date.dateformats.full_long;i=dateFormat(e,o,!1);u=i.split(" ");for(var h=0;h<u.length;h++)if(parseInt(u[h],10)<0){trace("YEAR IS BC");f=u[h];l=Math.abs(parseInt(u[h],10));c=l.toString()+" a.C.";i=i.replace(f,c)}if(a){s=dateFormat(r,o,!1);u=s.split(" ");for(var p=0;p<u.length;p++)if(parseInt(u[p],10)<0){trace("YEAR IS BC");f=u[p];l=Math.abs(parseInt(u[p],10));c=l.toString()+" a.C.";s=s.replace(f,c)}}}else{trace("NOT A VALID DATE?");trace(e)}return a?i+" &mdash; "+s:i}}.init();var dateFormat=function(){var e=/d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,t=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,n=/[^-+\dA-Z]/g,r=function(e,t){e=String(e);t=t||2;while(e.length<t)e="0"+e;return e};return function(i,s,o){var u=dateFormat;if(arguments.length==1&&Object.prototype.toString.call(i)=="[object String]"&&!/\d/.test(i)){s=i;i=undefined}isNaN(i)&&trace("invalid date "+i);s=String(u.masks[s]||s||u.masks["default"]);if(s.slice(0,4)=="UTC:"){s=s.slice(4);o=!0}var a=o?"getUTC":"get",f=i[a+"Date"](),l=i[a+"Day"](),c=i[a+"Month"](),h=i[a+"FullYear"](),p=i[a+"Hours"](),d=i[a+"Minutes"](),v=i[a+"Seconds"](),m=i[a+"Milliseconds"](),g=o?0:i.getTimezoneOffset(),y={d:f,dd:r(f),ddd:u.i18n.dayNames[l],dddd:u.i18n.dayNames[l+7],m:c+1,mm:r(c+1),mmm:u.i18n.monthNames[c],mmmm:u.i18n.monthNames[c+12],yy:String(h).slice(2),yyyy:h,h:p%12||12,hh:r(p%12||12),H:p,HH:r(p),M:d,MM:r(d),s:v,ss:r(v),l:r(m,3),L:r(m>99?Math.round(m/10):m),t:p<12?"a":"p",tt:p<12?"am":"pm",T:p<12?"A":"P",TT:p<12?"AM":"PM",Z:o?"UTC":(String(i).match(t)||[""]).pop().replace(n,""),o:(g>0?"-":"+")+r(Math.floor(Math.abs(g)/60)*100+Math.abs(g)%60,4),S:["th","st","nd","rd"][f%10>3?0:(f%100-f%10!=10)*f%10]};return s.replace(e,function(e){return e in y?y[e]:e.slice(1,e.length-1)})}}();dateFormat.masks={"default":"ddd mmm dd yyyy HH:MM:ss",shortDate:"m/d/yy",mediumDate:"mmm d, yyyy",longDate:"mmmm d, yyyy",fullDate:"dddd, mmmm d, yyyy",shortTime:"h:MM TT",mediumTime:"h:MM:ss TT",longTime:"h:MM:ss TT Z",isoDate:"yyyy-mm-dd",isoTime:"HH:MM:ss",isoDateTime:"yyyy-mm-dd'T'HH:MM:ss",isoUtcDateTime:"UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"};dateFormat.i18n={dayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec","January","February","March","April","May","June","July","August","September","October","November","December"]};Date.prototype.format=function(e,t){return dateFormat(this,e,t)}}typeof VMM!="undefined"&&typeof VMM.Util=="undefined"&&(VMM.Util={init:function(){return this},correctProtocol:function(e){var t=window.parent.location.protocol.toString(),n="",r=e.split("://",2);t.match("http")?n=t:n="https";return n+"://"+r[1]},mergeConfig:function(e,t){var n;for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e},getObjectAttributeByIndex:function(e,t){if(typeof e!="undefined"){var n=0;for(var r in e){if(t===n)return e[r];n++}return""}return""},ordinal:function(e){return["th","st","nd","rd"][!(e%10>3||Math.floor(e%100/10)==1)*(e%10)]},randomBetween:function(e,t){return Math.floor(Math.random()*(t-e+1)+e)},average:function(e){var t={mean:0,variance:0,deviation:0},n=e.length;for(var r,i=0,s=n;s--;i+=e[s]);for(r=t.mean=i/n,s=n,i=0;s--;i+=Math.pow(e[s]-r,2));return t.deviation=Math.sqrt(t.variance=i/n),t},customSort:function(e,t){var n=e,r=t;return n==r?0:n>r?1:-1},deDupeArray:function(e){var t,n=e.length,r=[],i={};for(t=0;t<n;t++)i[e[t]]=0;for(t in i)r.push(t);return r},number2money:function(e,t,n){var t=t!==null?t:!0,n=n!==null?n:!1,r=VMM.Math2.floatPrecision(e,2),i=this.niceNumber(r);!i.split(/\./g)[1]&&n&&(i+=".00");t&&(i="$"+i);return i},wordCount:function(e){var t=e+" ",n=/^[^A-Za-z0-9\'\-]+/gi,r=t.replace(n,""),i=/[^A-Za-z0-9\'\-]+/gi,s=r.replace(i," "),o=s.split(" "),u=o.length-1;t.length<2&&(u=0);return u},ratio:{fit:function(e,t,n,r){var i={width:0,height:0};i.width=e;i.height=Math.round(e/n*r);if(i.height>t){i.height=t;i.width=Math.round(t/r*n);i.width>e&&trace("FIT: DIDN'T FIT!!! ")}return i},r16_9:function(e,t){if(e!==null&&e!=="")return Math.round(t/16*9);if(t!==null&&t!=="")return Math.round(e/9*16)},r4_3:function(e,t){if(e!==null&&e!=="")return Math.round(t/4*3);if(t!==null&&t!=="")return Math.round(e/3*4)}},doubledigit:function(e){return(e<10?"0":"")+e},truncateWords:function(e,t,n){t||(t=30);n||(n=t);var r=/^[^A-Za-z0-9\'\-]+/gi,i=e.replace(r,""),s=i.split(" "),o=[];t=Math.min(s.length,t);n=Math.min(s.length,n);for(var u=0;u<t;u++)o.push(s[u]);for(var a=t;u<n;u++){var f=s[u];o.push(f);if(f.charAt(f.length-1)==".")break}return o.join(" ")},linkify:function(e,t,n){var r=/\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim,i=/(^|[^\/])(www\.[\S]+(\b|$))/gim,s=/(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim;return e.replace(r,"<a target='_blank' href='$&' onclick='void(0)'>$&</a>").replace(i,"$1<a target='_blank' onclick='void(0)' href='http://$2'>$2</a>").replace(s,"<a target='_blank' onclick='void(0)' href='mailto:$1'>$1</a>")},linkify_with_twitter:function(e,t,n){function u(e){var t=/(\b(https?|ftp|file):\/\/([-A-Z0-9+&@#%?=~_|!:,.;]*)([-A-Z0-9+&@#%?\/=~_|!:,.;]*)[-A-Z0-9+&@#\/%=~_|])/ig;return e.replace(t,"<a href='$1' target='_blank'>$3</a>")}var r=/\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim,i=/(\()((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\))|(\[)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\])|(\{)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\})|(<|&(?:lt|#60|#x3c);)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(>|&(?:gt|#62|#x3e);)|((?:^|[^=\s'"\]])\s*['"]?|[^=\s]\s+)(\b(?:ht|f)tps?:\/\/[a-z0-9\-._~!$'()*+,;=:\/?#[\]@%]+(?:(?!&(?:gt|#0*62|#x0*3e);|&(?:amp|apos|quot|#0*3[49]|#x0*2[27]);[.!&',:?;]?(?:[^a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]|$))&[a-z0-9\-._~!$'()*+,;=:\/?#[\]@%]*)*[a-z0-9\-_~$()*+=\/#[\]@%])/img,s='$1$4$7$10$13<a href="$2$5$8$11$14" class="hyphenate">$2$5$8$11$14</a>$3$6$9$12',o=/(^|[^\/])(www\.[\S]+(\b|$))/gim,a=/(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim,f=/\B@([\w-]+)/gm,l=/(#([\w]+))/g;return e.replace(i,s).replace(o,"$1<a target='_blank' class='hyphenate' onclick='void(0)' href='http://$2'>$2</a>").replace(a,"<a target='_blank' onclick='void(0)' href='mailto:$1'>$1</a>").replace(f,"<a href='http://twitter.com/$1' target='_blank' onclick='void(0)'>@$1</a>").replace(l,"<a href='http://twitter.com/#search?q=%23$2' target='_blank' 'void(0)'>$1</a>")},linkify_wikipedia:function(e){var t=/<i[^>]*>(.*?)<\/i>/gim;return e.replace(t,"<a target='_blank' href='http://en.wikipedia.org/wiki/$&' onclick='void(0)'>$&</a>").replace(/<i\b[^>]*>/gim,"").replace(/<\/i>/gim,"").replace(/<b\b[^>]*>/gim,"").replace(/<\/b>/gim,"")},unlinkify:function(e){if(!e)return e;e=e.replace(/<a\b[^>]*>/i,"");e=e.replace(/<\/a>/i,"");return e},untagify:function(e){if(!e)return e;e=e.replace(/<\s*\w.*?>/g,"");return e},nl2br:function(e){return e.replace(/(\r\n|[\r\n]|\\n|\\r)/g,"<br/>")},unique_ID:function(e){var t=function(e){return Math.floor(Math.random()*e)},n=function(){var e="abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ";return e.substr(t(62),1)},r=function(e){var t="";for(var r=0;r<e;r++)t+=n();return t};return r(e)},isEven:function(e){return e%2===0?!0:!1},getUrlVars:function(e){var t=e.toString();t.match("&#038;")?t=t.replace("&#038;","&"):t.match("&#38;")?t=t.replace("&#38;","&"):t.match("&amp;")&&(t=t.replace("&amp;","&"));var n=[],r,i=t.slice(t.indexOf("?")+1).split("&");for(var s=0;s<i.length;s++){r=i[s].split("=");n.push(r[0]);n[r[0]]=r[1]}return n},toHTML:function(e){e=this.nl2br(e);e=this.linkify(e);return e.replace(/\s\s/g,"&nbsp;&nbsp;")},toCamelCase:function(e,t){t!==!1&&(t=!0);var n=(t?e.toLowerCase():e).split(" ");for(var r=0;r<n.length;r++)n[r]=n[r].substr(0,1).toUpperCase()+n[r].substr(1);return n.join(" ")},properQuotes:function(e){return e.replace(/\"([^\"]*)\"/gi,"&#8220;$1&#8221;")},niceNumber:function(e){e+="";x=e.split(".");x1=x[0];x2=x.length>1?"."+x[1]:"";var t=/(\d+)(\d{3})/;while(t.test(x1))x1=x1.replace(t,"$1,$2");return x1+x2},toTitleCase:function(e){if(VMM.Browser.browser=="Explorer"&&parseInt(VMM.Browser.version,10)>=7)return e.replace("_","%20");var t={__smallWords:["a","an","and","as","at","but","by","en","for","if","in","of","on","or","the","to","v[.]?","via","vs[.]?"],init:function(){this.__smallRE=this.__smallWords.join("|");this.__lowerCaseWordsRE=new RegExp("\\b("+this.__smallRE+")\\b","gi");this.__firstWordRE=new RegExp("^([^a-zA-Z0-9 \\r\\n\\t]*)("+this.__smallRE+")\\b","gi");this.__lastWordRE=new RegExp("\\b("+this.__smallRE+")([^a-zA-Z0-9 \\r\\n\\t]*)$","gi")},toTitleCase:function(e){var t="",n=e.split(/([:.;?!][ ]|(?:[ ]|^)["“])/);for(var r=0;r<n.length;++r){var i=n[r];i=i.replace(/\b([a-zA-Z][a-z.'’]*)\b/g,this.__titleCaseDottedWordReplacer);i=i.replace(this.__lowerCaseWordsRE,this.__lowerReplacer);i=i.replace(this.__firstWordRE,this.__firstToUpperCase);i=i.replace(this.__lastWordRE,this.__firstToUpperCase);t+=i}t=t.replace(/ V(s?)\. /g," v$1. ");t=t.replace(/(['’])S\b/g,"$1s");t=t.replace(/\b(AT&T|Q&A)\b/ig,this.__upperReplacer);return t},__titleCaseDottedWordReplacer:function(e){return e.match(/[a-zA-Z][.][a-zA-Z]/)?e:t.__firstToUpperCase(e)},__lowerReplacer:function(e){return e.toLowerCase()},__upperReplacer:function(e){return e.toUpperCase()},__firstToUpperCase:function(e){var t=e.split(/(^[^a-zA-Z0-9]*[a-zA-Z0-9])(.*)$/);t[1]&&(t[1]=t[1].toUpperCase());return t.join("")}};t.init();e=e.replace(/_/g," ");e=t.toTitleCase(e);return e}}.init());LazyLoad=function(e){function u(t,n){var r=e.createElement(t),i;for(i in n)n.hasOwnProperty(i)&&r.setAttribute(i,n[i]);return r}function a(e){var t=r[e],n,o;if(t){n=t.callback;o=t.urls;o.shift();i=0;if(!o.length){n&&n.call(t.context,t.obj);r[e]=null;s[e].length&&l(e)}}}function f(){var n=navigator.userAgent;t={async:e.createElement("script").async===!0};(t.webkit=/AppleWebKit\//.test(n))||(t.ie=/MSIE/.test(n))||(t.opera=/Opera/.test(n))||(t.gecko=/Gecko\//.test(n))||(t.unknown=!0)}function l(i,o,l,p,d){var v=function(){a(i)},m=i==="css",g=[],y,b,w,E,S,x;t||f();if(o){o=typeof o=="string"?[o]:o.concat();if(m||t.async||t.gecko||t.opera)s[i].push({urls:o,callback:l,obj:p,context:d});else for(y=0,b=o.length;y<b;++y)s[i].push({urls:[o[y]],callback:y===b-1?l:null,obj:p,context:d})}if(r[i]||!(E=r[i]=s[i].shift()))return;n||(n=e.head||e.getElementsByTagName("head")[0]);S=E.urls;for(y=0,b=S.length;y<b;++y){x=S[y];if(m)w=t.gecko?u("style"):u("link",{href:x,rel:"stylesheet"});else{w=u("script",{src:x});w.async=!1}w.className="lazyload";w.setAttribute("charset","utf-8");if(t.ie&&!m)w.onreadystatechange=function(){if(/loaded|complete/.test(w.readyState)){w.onreadystatechange=null;v()}};else if(m&&(t.gecko||t.webkit))if(t.webkit){E.urls[y]=w.href;h()}else{w.innerHTML='@import "'+x+'";';c(w)}else w.onload=w.onerror=v;g.push(w)}for(y=0,b=g.length;y<b;++y)n.appendChild(g[y])}function c(e){var t;try{t=!!e.sheet.cssRules}catch(n){i+=1;i<200?setTimeout(function(){c(e)},50):t&&a("css");return}a("css")}function h(){var e=r.css,t;if(e){t=o.length;while(--t>=0)if(o[t].href===e.urls[0]){a("css");break}i+=1;e&&(i<200?setTimeout(h,50):a("css"))}}var t,n,r={},i=0,s={css:[],js:[]},o=e.styleSheets;return{css:function(e,t,n,r){l("css",e,t,n,r)},js:function(e,t,n,r){l("js",e,t,n,r)}}}(this.document);LoadLib=function(e){function n(e){var n=0,r=!1;for(n=0;n<t.length;n++)t[n]==e&&(r=!0);if(r)return!0;t.push(e);return!1}var t=[];return{css:function(e,t,r,i){n(e)||LazyLoad.css(e,t,r,i)},js:function(e,t,r,i){n(e)||LazyLoad.js(e,t,r,i)}}}(this.document);typeof VMM!="undefined"&&typeof VMM.Language=="undefined"&&(VMM.Language={lang:"en",api:{wikipedia:"en"},date:{month:["January","February","March","April","May","June","July","August","September","October","November","December"],month_abbr:["Jan.","Feb.","March","April","May","June","July","Aug.","Sept.","Oct.","Nov.","Dec."],day:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],day_abbr:["Sun.","Mon.","Tues.","Wed.","Thurs.","Fri.","Sat."]},dateformats:{year:"yyyy",month_short:"mmm",month:"mmmm yyyy",full_short:"mmm d",full:"mmmm d',' yyyy",time_no_seconds_short:"h:MM TT" +,time_no_seconds_small_date:"h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'",full_long:"mmm d',' yyyy 'at' h:MM TT",full_long_small_date:"h:MM TT'<br/><small>mmm d',' yyyy'</small>'"},messages:{loading_timeline:"Loading Timeline... ",return_to_title:"Return to Title",expand_timeline:"Expand Timeline",contract_timeline:"Contract Timeline",wikipedia:"From Wikipedia, the free encyclopedia",loading_content:"Loading Content",loading:"Loading"}});typeof VMM!="undefined"&&typeof VMM.ExternalAPI=="undefined"&&(VMM.ExternalAPI={keys:{google:"",flickr:"",twitter:""},keys_master:{vp:"Pellentesque nibh felis, eleifend id, commodo in, interdum vitae, leo",flickr:"RAIvxHY4hE/Elm5cieh4X5ptMyDpj7MYIxziGxi0WGCcy1s+yr7rKQ==",google:"jwNGnYw4hE9lmAez4ll0QD+jo6SKBJFknkopLS4FrSAuGfIwyj57AusuR0s8dAo=",twitter:""},init:function(){return this},setKeys:function(e){VMM.ExternalAPI.keys=e},pushQues:function(){VMM.master_config.googlemaps.active&&VMM.ExternalAPI.googlemaps.pushQue();VMM.master_config.youtube.active&&VMM.ExternalAPI.youtube.pushQue();VMM.master_config.soundcloud.active&&VMM.ExternalAPI.soundcloud.pushQue();VMM.master_config.googledocs.active&&VMM.ExternalAPI.googledocs.pushQue();VMM.master_config.googleplus.active&&VMM.ExternalAPI.googleplus.pushQue();VMM.master_config.wikipedia.active&&VMM.ExternalAPI.wikipedia.pushQue();VMM.master_config.vimeo.active&&VMM.ExternalAPI.vimeo.pushQue();VMM.master_config.twitter.active&&VMM.ExternalAPI.twitter.pushQue();VMM.master_config.flickr.active&&VMM.ExternalAPI.flickr.pushQue();VMM.master_config.webthumb.active&&VMM.ExternalAPI.webthumb.pushQue()},twitter:{tweetArray:[],get:function(e){var t={mid:e.id,id:e.uid};VMM.master_config.twitter.que.push(t);VMM.master_config.twitter.active=!0},create:function(e,t){var n=e.mid.toString(),r={twitterid:e.mid},i="http://api.twitter.com/1/statuses/show.json?id="+e.mid+"&include_entities=true&callback=?",s=setTimeout(VMM.ExternalAPI.twitter.errorTimeOut,VMM.master_config.timers.api,e),o=setTimeout(t,VMM.master_config.timers.api,e);VMM.getJSON(i,function(t){var n=t.id_str,r="<blockquote><p>",i=VMM.Util.linkify_with_twitter(t.text,"_blank");r+=i;r+="</p></blockquote>";typeof t.entities.media!="undefined"&&t.entities.media[0].type=="photo";r+="<div class='vcard author'>";r+="<a class='screen-name url' href='https://twitter.com/"+t.user.screen_name+"' data-screen-name='"+t.user.screen_name+"' target='_blank'>";r+="<span class='avatar'><img src=' "+t.user.profile_image_url+"' alt=''></span>";r+="<span class='fn'>"+t.user.name+"</span>";r+="<span class='nickname'>@"+t.user.screen_name+"<span class='thumbnail-inline'></span></span>";r+="</a>";r+="</div>";VMM.attachElement("#"+e.id.toString(),r);VMM.attachElement("#text_thumb_"+e.id.toString(),t.text);VMM.attachElement("#marker_content_"+e.id.toString(),t.text)}).error(function(t,n,r){trace("TWITTER error");trace("TWITTER ERROR: "+n+" "+t.responseText);VMM.attachElement("#"+e.id,VMM.MediaElement.loadingmessage("ERROR LOADING TWEET "+e.mid))}).success(function(e){clearTimeout(s);clearTimeout(o);t()})},errorTimeOut:function(e){trace("TWITTER JSON ERROR TIMEOUT "+e.mid);VMM.attachElement("#"+e.id.toString(),VMM.MediaElement.loadingmessage("Still waiting on Twitter: "+e.mid));VMM.getJSON("http://api.twitter.com/1/account/rate_limit_status.json",function(t){trace("REMAINING TWITTER API CALLS "+t.remaining_hits);trace("TWITTER RATE LIMIT WILL RESET AT "+t.reset_time);var n="";if(t.remaining_hits==0){n="<p>You've reached the maximum number of tweets you can load in an hour.</p>";n+="<p>You can view tweets again starting at: <br/>"+t.reset_time+"</p>"}else n="<p>Still waiting on Twitter. "+e.mid+"</p>";VMM.attachElement("#"+e.id.toString(),VMM.MediaElement.loadingmessage(n))})},pushQue:function(){if(VMM.master_config.twitter.que.length>0){VMM.ExternalAPI.twitter.create(VMM.master_config.twitter.que[0],VMM.ExternalAPI.twitter.pushQue);VMM.master_config.twitter.que.remove(0)}},getHTML:function(e){var t="http://api.twitter.com/1/statuses/oembed.json?id="+e+"&callback=?";VMM.getJSON(t,VMM.ExternalAPI.twitter.onJSONLoaded)},onJSONLoaded:function(e){trace("TWITTER JSON LOADED");var t=e.id;VMM.attachElement("#"+t,VMM.Util.linkify_with_twitter(e.html))},parseTwitterDate:function(e){var t=new Date(Date.parse(e));return t},prettyParseTwitterDate:function(e){var t=new Date(Date.parse(e));return VMM.Date.prettyDate(t,!0)},getTweets:function(e){var t=[],n=e.length;for(var r=0;r<e.length;r++){var i="";e[r].tweet.match("status/")?i=e[r].tweet.split("status/")[1]:e[r].tweet.match("statuses/")?i=e[r].tweet.split("statuses/")[1]:i="";var s="http://api.twitter.com/1/statuses/show.json?id="+i+"&include_entities=true&callback=?";VMM.getJSON(s,function(e){var r={},i="<div class='twitter'><blockquote><p>",s=VMM.Util.linkify_with_twitter(e.text,"_blank");i+=s;i+="</p>";i+="— "+e.user.name+" (<a href='https://twitter.com/"+e.user.screen_name+"'>@"+e.user.screen_name+"</a>) <a href='https://twitter.com/"+e.user.screen_name+"/status/"+e.id+"'>"+VMM.ExternalAPI.twitter.prettyParseTwitterDate(e.created_at)+" </a></blockquote></div>";r.content=i;r.raw=e;t.push(r);if(t.length==n){var o={tweetdata:t};VMM.fireEvent(global,"TWEETSLOADED",o)}}).success(function(){trace("second success")}).error(function(){trace("error")}).complete(function(){trace("complete")})}},getTweetSearch:function(e,t){var n=40;t!=null&&t!=""&&(n=t);var r="http://search.twitter.com/search.json?q="+e+"&rpp="+n+"&include_entities=true&result_type=mixed",i=[];VMM.getJSON(r,function(e){for(var t=0;t<e.results.length;t++){var n={},r="<div class='twitter'><blockquote><p>",s=VMM.Util.linkify_with_twitter(e.results[t].text,"_blank");r+=s;r+="</p>";r+="— "+e.results[t].from_user_name+" (<a href='https://twitter.com/"+e.results[t].from_user+"'>@"+e.results[t].from_user+"</a>) <a href='https://twitter.com/"+e.results[t].from_user+"/status/"+e.id+"'>"+VMM.ExternalAPI.twitter.prettyParseTwitterDate(e.results[t].created_at)+" </a></blockquote></div>";n.content=r;n.raw=e.results[t];i.push(n)}var o={tweetdata:i};VMM.fireEvent(global,"TWEETSLOADED",o)})},prettyHTML:function(e,t){var e=e.toString(),n={twitterid:e},r="http://api.twitter.com/1/statuses/show.json?id="+e+"&include_entities=true&callback=?",i=setTimeout(VMM.ExternalAPI.twitter.errorTimeOut,VMM.master_config.timers.api,e);VMM.getJSON(r,VMM.ExternalAPI.twitter.formatJSON).error(function(t,n,r){trace("TWITTER error");trace("TWITTER ERROR: "+n+" "+t.responseText);VMM.attachElement("#twitter_"+e,"<p>ERROR LOADING TWEET "+e+"</p>")}).success(function(e){clearTimeout(i);t&&VMM.ExternalAPI.twitter.secondaryMedia(e)})},formatJSON:function(e){var t=e.id_str,n="<blockquote><p>",r=VMM.Util.linkify_with_twitter(e.text,"_blank");n+=r;n+="</p></blockquote>";n+="<div class='vcard author'>";n+="<a class='screen-name url' href='https://twitter.com/"+e.user.screen_name+"' data-screen-name='"+e.user.screen_name+"' target='_blank'>";n+="<span class='avatar'><img src=' "+e.user.profile_image_url+"' alt=''></span>";n+="<span class='fn'>"+e.user.name+"</span>";n+="<span class='nickname'>@"+e.user.screen_name+"<span class='thumbnail-inline'></span></span>";n+="</a>";n+="</div>";typeof e.entities.media!="undefined"&&e.entities.media[0].type=="photo"&&(n+="<img src=' "+e.entities.media[0].media_url+"' alt=''>");VMM.attachElement("#twitter_"+t.toString(),n);VMM.attachElement("#text_thumb_"+t.toString(),e.text)}},googlemaps:{maptype:"toner",setMapType:function(e){e!=""&&(VMM.ExternalAPI.googlemaps.maptype=e)},get:function(e){var t,n,r;e.vars=VMM.Util.getUrlVars(e.id);VMM.ExternalAPI.keys.google!=""?n=VMM.ExternalAPI.keys.google:n=Aes.Ctr.decrypt(VMM.ExternalAPI.keys_master.google,VMM.ExternalAPI.keys_master.vp,256);r="http://maps.googleapis.com/maps/api/js?key="+n+"&libraries=places&sensor=false&callback=VMM.ExternalAPI.googlemaps.onMapAPIReady";if(VMM.master_config.googlemaps.active)VMM.master_config.googlemaps.que.push(e);else{VMM.master_config.googlemaps.que.push(e);VMM.master_config.googlemaps.api_loaded||LoadLib.js(r,function(){trace("Google Maps API Library Loaded")})}},create:function(e){VMM.ExternalAPI.googlemaps.createAPIMap(e)},createiFrameMap:function(e){var t=e.id+"&output=embed",n="",r=e.uid.toString()+"_gmap";n+="<div class='google-map' id='"+r+"' style='width=100%;height=100%;'>";n+="<iframe width='100%' height='100%' frameborder='0' scrolling='no' marginheight='0' marginwidth='0' src='"+t+"'></iframe>";n+="</div>";VMM.attachElement("#"+e.uid,n)},createAPIMap:function(e){function d(e){if(e in VMM.ExternalAPI.googlemaps.map_providers){t=VMM.ExternalAPI.googlemaps.map_attribution[VMM.ExternalAPI.googlemaps.map_providers[e].attribution];return VMM.ExternalAPI.googlemaps.map_providers[e]}if(VMM.ExternalAPI.googlemaps.defaultType(e)){trace("GOOGLE MAP DEFAULT TYPE");return google.maps.MapTypeId[e.toUpperCase()]}trace("Not a maptype: "+e)}function v(){var t=new google.maps.Geocoder,n=VMM.Util.getUrlVars(e.id).q,i;if(n.match("loc:")){var s=n.split(":")[1].split("+");u=new google.maps.LatLng(parseFloat(s[0]),parseFloat(s[1]));l=!0}t.geocode({address:n},function(e,t){if(t==google.maps.GeocoderStatus.OK){i=new google.maps.Marker({map:r,position:e[0].geometry.location});typeof e[0].geometry.viewport!="undefined"?r.fitBounds(e[0].geometry.viewport):typeof e[0].geometry.bounds!="undefined"?r.fitBounds(e[0].geometry.bounds):r.setCenter(e[0].geometry.location);l&&r.panTo(u);c&&r.setZoom(f)}else{trace("Geocode for "+n+" was not successful for the following reason: "+t);trace("TRYING PLACES SEARCH");l&&r.panTo(u);c&&r.setZoom(f);m()}})}function m(){function h(t,i){if(i==google.maps.places.PlacesServiceStatus.OK){for(var s=0;s<t.length;s++);if(l)r.panTo(u);else if(t.length>=1){r.panTo(t[0].geometry.location);c&&r.setZoom(f)}}else{trace("Place search for "+n.query+" was not successful for the following reason: "+i);trace("YOU MAY NEED A GOOGLE MAPS API KEY IN ORDER TO USE THIS FEATURE OF TIMELINEJS");trace("FIND OUT HOW TO GET YOUR KEY HERE: https://developers.google.com/places/documentation/#Authentication");if(l){r.panTo(u);c&&r.setZoom(f)}else{trace("USING SIMPLE IFRAME MAP EMBED");e.id[0].match("https")&&(e.id=e.url[0].replace("https","http"));VMM.ExternalAPI.googlemaps.createiFrameMap(e)}}}function p(e){var t,n;n=e.geometry.location;t=new google.maps.Marker({map:r,position:e.geometry.location});google.maps.event.addListener(t,"click",function(){i.setContent(e.name);i.open(r,this)})}var t,n,i,s,o,a;place_search=new google.maps.places.PlacesService(r);i=new google.maps.InfoWindow;n={query:"",types:["country","neighborhood","political","locality","geocode"]};type.of(VMM.Util.getUrlVars(e.id)["q"])=="string"&&(n.query=VMM.Util.getUrlVars(e.id).q);if(l){n.location=u;n.radius="15000"}else{o=new google.maps.LatLng(-89.999999,-179.999999);a=new google.maps.LatLng(89.999999,179.999999);s=new google.maps.LatLngBounds(o,a)}place_search.textSearch(n,h)}function g(){var t,n,i=!1;trace("LOADING PLACES API FOR GOOGLE MAPS");if(VMM.ExternalAPI.keys.google!=""){t=VMM.ExternalAPI.keys.google;i=!0}else{trace("YOU NEED A GOOGLE MAPS API KEY IN ORDER TO USE THIS FEATURE OF TIMELINEJS");trace("FIND OUT HOW TO GET YOUR KEY HERE: https://developers.google.com/places/documentation/#Authentication")}n="https://maps.googleapis.com/maps/api/place/textsearch/json?key="+t+"&sensor=false&language="+e.lang+"&";type.of(VMM.Util.getUrlVars(e.id)["q"])=="string"&&(n+="query="+VMM.Util.getUrlVars(e.id).q);l&&(n+="&location="+u);if(i)VMM.getJSON(n,function(t){trace("PLACES JSON");var n="",i="",s="",o="";trace(t);if(t.status=="OVER_QUERY_LIMIT"){trace("OVER_QUERY_LIMIT");if(l){r.panTo(u);c&&r.setZoom(f)}else{trace("DOING TRADITIONAL MAP IFRAME EMBED UNTIL QUERY LIMIT RESTORED");h=!0;VMM.ExternalAPI.googlemaps.createiFrameMap(e)}}else{if(t.results.length>=1){s=new google.maps.LatLng(parseFloat(t.results[0].geometry.viewport.northeast.lat),parseFloat(t.results[0].geometry.viewport.northeast.lng));o=new google.maps.LatLng(parseFloat(t.results[0].geometry.viewport.southwest.lat),parseFloat(t.results[0].geometry.viewport.southwest.lng));i=new google.maps.LatLngBounds(o,s);r.fitBounds(i)}else trace("NO RESULTS");l&&r.panTo(u);c&&r.setZoom(f)}}).error(function(e,t,n){trace("PLACES JSON ERROR");trace("PLACES JSON ERROR: "+t+" "+e.responseText)}).success(function(e){trace("PLACES JSON SUCCESS")});else if(l){r.panTo(u);c&&r.setZoom(f)}else{trace("DOING TRADITIONAL MAP IFRAME EMBED BECAUSE NO GOOGLE MAP API KEY WAS PROVIDED");VMM.ExternalAPI.googlemaps.createiFrameMap(e)}}function y(){var t,n,i,s;t=e.id+"&output=kml";t=t.replace("&output=embed","");n=new google.maps.KmlLayer(t,{preserveViewport:!0});i=new google.maps.InfoWindow;n.setMap(r);google.maps.event.addListenerOnce(n,"defaultviewport_changed",function(){l?r.panTo(u):r.fitBounds(n.getDefaultViewport());c&&r.setZoom(f)});google.maps.event.addListener(n,"click",function(e){function t(e){i.setContent(e);i.open(r)}s=e.featureData.description;t(s)})}var t="",n,r,i,s=e.uid.toString()+"_gmap",o="",u=new google.maps.LatLng(41.875696,-87.624207),a,f=11,l=!1,c=!1,h=!1,p;google.maps.VeriteMapType=function(e){if(VMM.ExternalAPI.googlemaps.defaultType(e))return google.maps.MapTypeId[e.toUpperCase()];var t=d(e);return google.maps.ImageMapType.call(this,{getTileUrl:function(e,n){var r=(n+e.x+e.y)%VMM.ExternalAPI.googlemaps.map_subdomains.length;return[t.url.replace("{S}",VMM.ExternalAPI.googlemaps.map_subdomains[r]).replace("{Z}",n).replace("{X}",e.x).replace("{Y}",e.y).replace("{z}",n).replace("{x}",e.x).replace("{y}",e.y)]},tileSize:new google.maps.Size(256,256),name:e,minZoom:t.minZoom,maxZoom:t.maxZoom})};google.maps.VeriteMapType.prototype=new google.maps.ImageMapType("_");VMM.ExternalAPI.googlemaps.maptype!=""?VMM.ExternalAPI.googlemaps.defaultType(VMM.ExternalAPI.googlemaps.maptype)?n=google.maps.MapTypeId[VMM.ExternalAPI.googlemaps.maptype.toUpperCase()]:n=VMM.ExternalAPI.googlemaps.maptype:n="toner";if(type.of(VMM.Util.getUrlVars(e.id)["ll"])=="string"){l=!0;a=VMM.Util.getUrlVars(e.id).ll.split(",");u=new google.maps.LatLng(parseFloat(a[0]),parseFloat(a[1]))}else if(type.of(VMM.Util.getUrlVars(e.id)["sll"])=="string"){a=VMM.Util.getUrlVars(e.id).sll.split(",");u=new google.maps.LatLng(parseFloat(a[0]),parseFloat(a[1]))}if(type.of(VMM.Util.getUrlVars(e.id)["z"])=="string"){c=!0;f=parseFloat(VMM.Util.getUrlVars(e.id).z)}i={zoom:f,draggable:!1,disableDefaultUI:!0,mapTypeControl:!1,zoomControl:!0,zoomControlOptions:{style:google.maps.ZoomControlStyle.SMALL,position:google.maps.ControlPosition.TOP_RIGHT},center:u,mapTypeId:n,mapTypeControlOptions:{mapTypeIds:[n]}};VMM.attachElement("#"+e.uid,"<div class='google-map' id='"+s+"' style='width=100%;height=100%;'></div>");r=new google.maps.Map(document.getElementById(s),i);if(!VMM.ExternalAPI.googlemaps.defaultType(VMM.ExternalAPI.googlemaps.maptype)){r.mapTypes.set(n,new google.maps.VeriteMapType(n));o="<div class='map-attribution'><div class='attribution-text'>"+t+"</div></div>";VMM.appendElement("#"+s,o)}type.of(VMM.Util.getUrlVars(e.id)["msid"])=="string"?y():type.of(VMM.Util.getUrlVars(e.id)["q"])=="string"&&v()},pushQue:function(){for(var e=0;e<VMM.master_config.googlemaps.que.length;e++)VMM.ExternalAPI.googlemaps.create(VMM.master_config.googlemaps.que[e]);VMM.master_config.googlemaps.que=[]},onMapAPIReady:function(){VMM.master_config.googlemaps.map_active=!0;VMM.master_config.googlemaps.places_active=!0;VMM.ExternalAPI.googlemaps.onAPIReady()},onPlacesAPIReady:function(){VMM.master_config.googlemaps.places_active=!0;VMM.ExternalAPI.googlemaps.onAPIReady()},onAPIReady:function(){if(!VMM.master_config.googlemaps.active&&VMM.master_config.googlemaps.map_active&&VMM.master_config.googlemaps.places_active){VMM.master_config.googlemaps.active=!0;VMM.ExternalAPI.googlemaps.pushQue()}},defaultType:function(e){return e.toLowerCase()=="satellite"||e.toLowerCase()=="hybrid"||e.toLowerCase()=="terrain"||e.toLowerCase()=="roadmap"?!0:!1},map_subdomains:["","a.","b.","c.","d."],map_attribution:{stamen:"Map tiles by <a href='http://stamen.com'>Stamen Design</a>, under <a href='http://creativecommons.org/licenses/by/3.0'>CC BY 3.0</a>. Data by <a href='http://openstreetmap.org'>OpenStreetMap</a>, under <a href='http://creativecommons.org/licenses/by-sa/3.0'>CC BY SA</a>.",apple:"Map data &copy; 2012 Apple, Imagery &copy; 2012 Apple"},map_providers:{toner:{url:"http://{S}tile.stamen.com/toner/{Z}/{X}/{Y}.png",minZoom:0,maxZoom:20,attribution:"stamen"},"toner-lines":{url:"http://{S}tile.stamen.com/toner-lines/{Z}/{X}/{Y}.png",minZoom:0,maxZoom:20,attribution:"stamen"},"toner-labels":{url:"http://{S}tile.stamen.com/toner-labels/{Z}/{X}/{Y}.png",minZoom:0,maxZoom:20,attribution:"stamen"},sterrain:{url:"http://{S}tile.stamen.com/terrain/{Z}/{X}/{Y}.jpg",minZoom:4,maxZoom:20,attribution:"stamen"},apple:{url:"http://gsp2.apple.com/tile?api=1&style=slideshow&layers=default&lang=en_US&z={z}&x={x}&y={y}&v=9",minZoom:4,maxZoom:14,attribution:"apple"},watercolor:{url:"http://{S}tile.stamen.com/watercolor/{Z}/{X}/{Y}.jpg",minZoom:3,maxZoom:16,attribution:"stamen"}}},googleplus:{get:function(e){var t,n={user:e.user,activity:e.id,id:e.uid};VMM.master_config.googleplus.que.push(n);VMM.master_config.googleplus.active=!0},create:function(e,t){var n="",r="",i="",s="",o="",u,a;googleplus_timeout=setTimeout(VMM.ExternalAPI.googleplus.errorTimeOut,VMM.master_config.timers.api,e),callback_timeout=setTimeout(t,VMM.master_config.timers.api,e);VMM.master_config.Timeline.api_keys.google!=""?r=VMM.master_config.Timeline.api_keys.google:r=Aes.Ctr.decrypt(VMM.master_config.api_keys_master.google,VMM.master_config.vp,256);u="https://www.googleapis.com/plus/v1/people/"+e.user+"/activities/public?alt=json&maxResults=100&fields=items(id,url)&key="+r;n="GOOGLE PLUS API CALL";VMM.getJSON(u,function(t){for(var u=0;u<t.items.length;u++){trace("loop");if(t.items[u].url.split("posts/")[1]==e.activity){trace("FOUND IT!!");i=t.items[u].id;a="https://www.googleapis.com/plus/v1/activities/"+i+"?alt=json&key="+r;VMM.getJSON(a,function(t){trace(t);if(typeof t.annotation!="undefined"){s+="<div class='googleplus-annotation'>'"+t.annotation+"</div>";s+=t.object.content}else s+=t.object.content;if(typeof t.object.attachments!="undefined"){for(var r=0;r<t.object.attachments.length;r++){if(t.object.attachments[r].objectType=="photo")o="<a href='"+t.object.url+"' target='_blank'>"+"<img src='"+t.object.attachments[r].image.url+"' class='article-thumb'></a>"+o;else if(t.object.attachments[r].objectType=="video"){o="<img src='"+t.object.attachments[r].image.url+"' class='article-thumb'>"+o;o+="<div>";o+="<a href='"+t.object.attachments[r].url+"' target='_blank'>";o+="<h5>"+t.object.attachments[r].displayName+"</h5>";o+="</a>";o+="</div>"}else if(t.object.attachments[r].objectType=="article"){o+="<div>";o+="<a href='"+t.object.attachments[r].url+"' target='_blank'>";o+="<h5>"+t.object.attachments[r].displayName+"</h5>";o+="<p>"+t.object.attachments[r].content+"</p>";o+="</a>";o+="</div>"}trace(t.object.attachments[r])}o="<div class='googleplus-attachments'>"+o+"</div>"}n="<div class='googleplus-content'>"+s+o+"</div>";n+="<div class='vcard author'><a class='screen-name url' href='"+t.url+"' target='_blank'>";n+="<span class='avatar'><img src='"+t.actor.image.url+"' style='max-width: 32px; max-height: 32px;'></span>";n+="<span class='fn'>"+t.actor.displayName+"</span>";n+="<span class='nickname'><span class='thumbnail-inline'></span></span>";n+="</a></div>";VMM.attachElement("#googleplus_"+e.activity,n)});break}}}).error(function(t,n,r){var i=VMM.parseJSON(t.responseText);trace(i.error.message);VMM.attachElement("#googleplus_"+e.activity,VMM.MediaElement.loadingmessage("<p>ERROR LOADING GOOGLE+ </p><p>"+i.error.message+"</p>"))}).success(function(e){clearTimeout(googleplus_timeout);clearTimeout(callback_timeout);t()})},pushQue:function(){if(VMM.master_config.googleplus.que.length>0){VMM.ExternalAPI.googleplus.create(VMM.master_config.googleplus.que[0],VMM.ExternalAPI.googleplus.pushQue);VMM.master_config.googleplus.que.remove(0)}},errorTimeOut:function(e){trace("GOOGLE+ JSON ERROR TIMEOUT "+e.activity);VMM.attachElement("#googleplus_"+e.activity,VMM.MediaElement.loadingmessage("<p>Still waiting on GOOGLE+ </p><p>"+e.activity+"</p>"))}},googledocs:{get:function(e){VMM.master_config.googledocs.que.push(e);VMM.master_config.googledocs.active=!0},create:function(e){var t="";e.id.match(/docs.google.com/i)?t="<iframe class='doc' frameborder='0' width='100%' height='100%' src='"+e.id+"&amp;embedded=true'></iframe>":t="<iframe class='doc' frameborder='0' width='100%' height='100%' src='http://docs.google.com/viewer?url="+e.id+"&amp;embedded=true'></iframe>";VMM.attachElement("#"+e.uid,t)},pushQue:function(){for(var e=0;e<VMM.master_config.googledocs.que.length;e++)VMM.ExternalAPI.googledocs.create(VMM.master_config.googledocs.que[e]);VMM.master_config.googledocs.que=[]}},flickr:{get:function(e){VMM.master_config.flickr.que.push(e);VMM.master_config.flickr.active=!0},create:function(e,t){var n,r=setTimeout(t,VMM.master_config.timers.api,e);typeof VMM.master_config.Timeline!="undefined"&&VMM.master_config.Timeline.api_keys.flickr!=""?n=VMM.master_config.Timeline.api_keys.flickr:n=Aes.Ctr.decrypt(VMM.master_config.api_keys_master.flickr,VMM.master_config.vp,256);var i="http://api.flickr.com/services/rest/?method=flickr.photos.getSizes&api_key="+n+"&photo_id="+e.id+"&format=json&jsoncallback=?";VMM.getJSON(i,function(t){var n=t.sizes.size[0].url.split("photos/")[1].split("/")[1],r="#"+e.uid,i="#"+e.uid+"_thumb",s,o,u=!1,a="Large";a=VMM.ExternalAPI.flickr.sizes(VMM.master_config.sizes.api.height);for(var f=0;f<t.sizes.size.length;f++)if(t.sizes.size[f].label==a){u=!0;s=t.sizes.size[f].source}u||(s=t.sizes.size[t.sizes.size.length-2].source);o=t.sizes.size[0].source;VMM.Lib.attr(r,"src",s);VMM.attachElement(i,"<img src='"+o+"'>")}).error(function(e,t,n){trace("FLICKR error");trace("FLICKR ERROR: "+t+" "+e.responseText)}).success(function(e){clearTimeout(r);t()})},pushQue:function(){if(VMM.master_config.flickr.que.length>0){VMM.ExternalAPI.flickr.create(VMM.master_config.flickr.que[0],VMM.ExternalAPI.flickr.pushQue);VMM.master_config.flickr.que.remove(0)}},sizes:function(e){var t="";e<=75?t="Thumbnail":e<=180?t="Small":e<=240?t="Small 320":e<=375?t="Medium":e<=480?t="Medium 640":e<=600?t="Large":t="Large";return t}},instagram:{get:function(e,t){return t?"http://instagr.am/p/"+e.id+"/media/?size=t":"http://instagr.am/p/"+e.id+"/media/?size="+VMM.ExternalAPI.instagram.sizes(VMM.master_config.sizes.api.height)},sizes:function(e){var t="";e<=150?t="t":e<=306?t="m":t="l";return t}},soundcloud:{get:function(e){VMM.master_config.soundcloud.que.push(e);VMM.master_config.soundcloud.active=!0},create:function(e,t){var n="http://soundcloud.com/oembed?url="+e.id+"&format=js&callback=?";VMM.getJSON(n,function(n){VMM.attachElement("#"+e.uid,n.html);t()})},pushQue:function(){if(VMM.master_config.soundcloud.que.length>0){VMM.ExternalAPI.soundcloud.create(VMM.master_config.soundcloud.que[0],VMM.ExternalAPI.soundcloud.pushQue);VMM.master_config.soundcloud.que.remove(0)}}},wikipedia:{get:function(e){VMM.master_config.wikipedia.que.push(e);VMM.master_config.wikipedia.active=!0},create:function(e,t){var n="http://"+e.lang+".wikipedia.org/w/api.php?action=query&prop=extracts&redirects=&titles="+e.id+"&exintro=1&format=json&callback=?";callback_timeout=setTimeout(t,VMM.master_config.timers.api,e);if(VMM.Browser.browser=="Explorer"&&parseInt(VMM.Browser.version,10)>=7&&window.XDomainRequest){var r="<h4><a href='http://"+VMM.master_config.language.api.wikipedia+".wikipedia.org/wiki/"+e.id+"' target='_blank'>"+e.url+"</a></h4>";r+="<span class='wiki-source'>"+VMM.master_config.language.messages.wikipedia+"</span>";r+="<p>Wikipedia entry unable to load using Internet Explorer 8 or below.</p>";VMM.attachElement("#"+e.uid,r)}VMM.getJSON(n,function(t){if(t.query){var n,r,i="",s="",o=1,u=[];n=VMM.Util.getObjectAttributeByIndex(t.query.pages,0).extract;r=VMM.Util.getObjectAttributeByIndex(t.query.pages,0).title;n.match("<p>")?u=n.split("<p>"):u.push(n);for(var a=0;a<u.length;a++)a+1<=o&&a+1<u.length&&(s+="<p>"+u[a+1]);i="<h4><a href='http://"+VMM.master_config.language.api.wikipedia+".wikipedia.org/wiki/"+r+"' target='_blank'>"+r+"</a></h4>";i+="<span class='wiki-source'>"+VMM.master_config.language.messages.wikipedia+"</span>";i+=VMM.Util.linkify_wikipedia(s);n.match("REDIRECT")||VMM.attachElement("#"+e.uid,i)}}).error(function(n,r,i){trace("WIKIPEDIA error");trace("WIKIPEDIA ERROR: "+r+" "+n.responseText);trace(i);VMM.attachElement("#"+e.uid,VMM.MediaElement.loadingmessage("<p>Wikipedia is not responding</p>"));clearTimeout(callback_timeout);if(VMM.master_config.wikipedia.tries<4){trace("WIKIPEDIA ATTEMPT "+VMM.master_config.wikipedia.tries);trace(e);VMM.master_config.wikipedia.tries++;VMM.ExternalAPI.wikipedia.create(e,t)}else t()}).success(function(e){VMM.master_config.wikipedia.tries=0;clearTimeout(callback_timeout);t()})},pushQue:function(){if(VMM.master_config.wikipedia.que.length>0){trace("WIKIPEDIA PUSH QUE "+VMM.master_config.wikipedia.que.length);VMM.ExternalAPI.wikipedia.create(VMM.master_config.wikipedia.que[0],VMM.ExternalAPI.wikipedia.pushQue);VMM.master_config.wikipedia.que.remove(0)}}},youtube:{get:function(e){var t="http://gdata.youtube.com/feeds/api/videos/"+e.id+"?v=2&alt=jsonc&callback=?";VMM.master_config.youtube.que.push(e);VMM.master_config.youtube.active||VMM.master_config.youtube.api_loaded||LoadLib.js("http://www.youtube.com/player_api",function(){trace("YouTube API Library Loaded")});VMM.getJSON(t,function(t){VMM.ExternalAPI.youtube.createThumb(t,e)})},create:function(e){if(typeof e.start!="undefined"){var t=e.start.toString(),n=0,r=0;if(t.match("m")){n=parseInt(t.split("m")[0],10);r=parseInt(t.split("m")[1].split("s")[0],10);e.start=n*60+r}else e.start=0}else e.start=0;var i={active:!1,player:{},name:e.uid,playing:!1,hd:!1};typeof e.hd!="undefined"&&(i.hd=!0);i.player[e.id]=new YT.Player(e.uid,{height:"390",width:"640",playerVars:{enablejsapi:1,color:"white",showinfo:0,theme:"light",start:e.start,rel:0},videoId:e.id,events:{onReady:VMM.ExternalAPI.youtube.onPlayerReady,onStateChange:VMM.ExternalAPI.youtube.onStateChange}});VMM.master_config.youtube.array.push(i)},createThumb:function(e,t){trace("CREATE THUMB");trace(e);trace(t);if(typeof e.data!="undefined"){var n="#"+t.uid+"_thumb";VMM.attachElement(n,"<img src='"+e.data.thumbnail.sqDefault+"'>")}},pushQue:function(){for(var e=0;e<VMM.master_config.youtube.que.length;e++)VMM.ExternalAPI.youtube.create(VMM.master_config.youtube.que[e]);VMM.master_config.youtube.que=[]},onAPIReady:function(){VMM.master_config.youtube.active=!0;VMM.ExternalAPI.youtube.pushQue()},stopPlayers:function(){for(var e=0;e<VMM.master_config.youtube.array.length;e++)if(VMM.master_config.youtube.array[e].playing){var t=VMM.master_config.youtube.array[e].name;VMM.master_config.youtube.array[e].player[t].stopVideo()}},onStateChange:function(e){for(var t=0;t<VMM.master_config.youtube.array.length;t++){var n=VMM.master_config.youtube.array[t].name;if(VMM.master_config.youtube.array[t].player[n]==e.target&&e.data==YT.PlayerState.PLAYING){VMM.master_config.youtube.array[t].playing=!0;trace(VMM.master_config.youtube.array[t].hd);VMM.master_config.youtube.array[t].hd}}},onPlayerReady:function(e){}},vimeo:{get:function(e){VMM.master_config.vimeo.que.push(e);VMM.master_config.vimeo.active=!0},create:function(e,t){trace("VIMEO CREATE");var n="http://vimeo.com/api/v2/video/"+e.id+".json",r="http://player.vimeo.com/video/"+e.id+"?title=0&amp;byline=0&amp;portrait=0&amp;color=ffffff";VMM.getJSON(n,function(n){VMM.ExternalAPI.vimeo.createThumb(n,e);t()});VMM.attachElement("#"+e.uid,"<iframe autostart='false' frameborder='0' width='100%' height='100%' src='"+r+"'></iframe>")},createThumb:function(e,t){trace("VIMEO CREATE THUMB");var n="#"+t.uid+"_thumb";VMM.attachElement(n,"<img src='"+e[0].thumbnail_small+"'>")},pushQue:function(){if(VMM.master_config.vimeo.que.length>0){VMM.ExternalAPI.vimeo.create(VMM.master_config.vimeo.que[0],VMM.ExternalAPI.vimeo.pushQue);VMM.master_config.vimeo.que.remove(0)}}},webthumb:{get:function(e,t){VMM.master_config.webthumb.que.push(e);VMM.master_config.webthumb.active=!0},sizes:function(e){var t="";e<=150?t="t":e<=306?t="m":t="l";return t},create:function(e){trace("WEB THUMB CREATE");var t="http://free.pagepeeker.com/v2/thumbs.php?";url=e.id.replace("http://","");VMM.attachElement("#"+e.uid,"<a href='"+e.id+"' target='_blank'><img src='"+t+"size=x&url="+url+"'></a>");VMM.attachElement("#"+e.uid+"_thumb","<a href='"+e.id+"' target='_blank'><img src='"+t+"size=t&url="+url+"'></a>")},pushQue:function(){for(var e=0;e<VMM.master_config.webthumb.que.length;e++)VMM.ExternalAPI.webthumb.create(VMM.master_config.webthumb.que[e]);VMM.master_config.webthumb.que=[]}}}.init());typeof VMM!="undefined"&&typeof VMM.MediaElement=="undefined"&&(VMM.MediaElement={init:function(){return this},loadingmessage:function(e){return"<div class='vco-loading'><div class='vco-loading-container'><div class='vco-loading-icon'></div><div class='vco-message'><p>"+e+"</p></div></div></div>"},thumbnail:function(e,t,n,r){var i=16,s=24,o="";t!=null&&t!=""&&(i=t);n!=null&&n!=""&&(s=n);r!=null&&r!=""&&(o=r);if(e.media!=null&&e.media!=""){var u=!0,a="",f=VMM.MediaType(e.media);if(e.thumbnail!=null&&e.thumbnail!=""){trace("CUSTOM THUMB");a="<div class='thumbnail thumb-custom' id='"+r+"_custom_thumb'><img src='"+e.thumbnail+"'></div>";return a}if(f.type=="image"){a="<div class='thumbnail thumb-photo'></div>";return a}if(f.type=="flickr"){a="<div class='thumbnail thumb-photo' id='"+r+"_thumb'></div>";return a}if(f.type=="instagram"){a="<div class='thumbnail thumb-instagram' id='"+r+"_thumb'><img src='"+VMM.ExternalAPI.instagram.get(f.id,!0)+"'></div>";return a}if(f.type=="youtube"){a="<div class='thumbnail thumb-youtube' id='"+r+"_thumb'></div>";return a}if(f.type=="googledoc"){a="<div class='thumbnail thumb-document'></div>";return a}if(f.type=="vimeo"){a="<div class='thumbnail thumb-vimeo' id='"+r+"_thumb'></div>";return a}if(f.type=="dailymotion"){a="<div class='thumbnail thumb-video'></div>";return a}if(f.type=="twitter"){a="<div class='thumbnail thumb-twitter'></div>";return a}if(f.type=="twitter-ready"){a="<div class='thumbnail thumb-twitter'></div>";return a}if(f.type=="soundcloud"){a="<div class='thumbnail thumb-audio'></div>";return a}if(f.type=="google-map"){a="<div class='thumbnail thumb-map'></div>";return a}if(f.type=="googleplus"){a="<div class='thumbnail thumb-googleplus'></div>";return a}if(f.type=="wikipedia"){a="<div class='thumbnail thumb-wikipedia'></div>";return a}if(f.type=="storify"){a="<div class='thumbnail thumb-storify'></div>";return a}if(f.type=="quote"){a="<div class='thumbnail thumb-quote'></div>";return a}if(f.type=="unknown"){f.id.match("blockquote")?a="<div class='thumbnail thumb-quote'></div>":a="<div class='thumbnail thumb-plaintext'></div>";return a}if(f.type=="website"){a="<div class='thumbnail thumb-website' id='"+r+"_thumb'></div>";return a}a="<div class='thumbnail thumb-plaintext'></div>";return a}},create:function(e,t){var n=!1,r=VMM.MediaElement.loadingmessage(VMM.master_config.language.messages.loading+"...");if(e.media!=null&&e.media!=""){var i="",s="",o="",u="",a=!1,f;f=VMM.MediaType(e.media);f.uid=t;n=!0;e.credit!=null&&e.credit!=""&&(o="<div class='credit'>"+VMM.Util.linkify_with_twitter(e.credit,"_blank")+"</div>");e.caption!=null&&e.caption!=""&&(s="<div class='caption'>"+VMM.Util.linkify_with_twitter(e.caption,"_blank")+"</div>");if(f.type=="image"){f.id.match("https://")&&(f.id=f.id.replace("https://","http://"));i="<div class='media-image media-shadow'><img src='"+f.id+"' class='media-image'></div>"}else if(f.type=="flickr"){i="<div class='media-image media-shadow'><a href='"+f.link+"' target='_blank'><img id='"+t+"'></a></div>";VMM.ExternalAPI.flickr.get(f)}else if(f.type=="instagram")i="<div class='media-image media-shadow'><a href='"+f.link+"' target='_blank'><img src='"+VMM.ExternalAPI.instagram.get(f)+"'></a></div>";else if(f.type=="googledoc"){i="<div class='media-frame media-shadow doc' id='"+f.uid+"'>"+r+"</div>";VMM.ExternalAPI.googledocs.get(f)}else if(f.type=="youtube"){i="<div class='media-shadow'><div class='media-frame video youtube' id='"+f.uid+"'>"+r+"</div></div>";VMM.ExternalAPI.youtube.get(f)}else if(f.type=="vimeo"){i="<div class='media-shadow media-frame video vimeo' id='"+f.uid+"'>"+r+"</div>";VMM.ExternalAPI.vimeo.get(f)}else if(f.type=="dailymotion")i="<div class='media-shadow'><iframe class='media-frame video dailymotion' autostart='false' frameborder='0' width='100%' height='100%' src='http://www.dailymotion.com/embed/video/"+f.id+"'></iframe></div>" +;else if(f.type=="twitter"){i="<div class='twitter' id='"+f.uid+"'>"+r+"</div>";a=!0;VMM.ExternalAPI.twitter.get(f)}else if(f.type=="twitter-ready"){a=!0;i=f.id}else if(f.type=="soundcloud"){i="<div class='media-frame media-shadow soundcloud' id='"+f.uid+"'>"+r+"</div>";VMM.ExternalAPI.soundcloud.get(f)}else if(f.type=="google-map"){i="<div class='media-frame media-shadow map' id='"+f.uid+"'>"+r+"</div>";VMM.ExternalAPI.googlemaps.get(f)}else if(f.type=="googleplus"){u="googleplus_"+f.id;i="<div class='googleplus' id='"+u+"'>"+r+"</div>";a=!0;VMM.ExternalAPI.googleplus.get(f)}else if(f.type=="wikipedia"){i="<div class='wikipedia' id='"+f.uid+"'>"+r+"</div>";a=!0;VMM.ExternalAPI.wikipedia.get(f)}else if(f.type=="storify"){a=!0;i="<div class='plain-text-quote'>"+f.id+"</div>"}else if(f.type=="quote"){a=!0;i="<div class='plain-text-quote'>"+f.id+"</div>"}else if(f.type=="unknown"){trace("NO KNOWN MEDIA TYPE FOUND TRYING TO JUST PLACE THE HTML");a=!0;i="<div class='plain-text'><div class='container'>"+VMM.Util.properQuotes(f.id)+"</div></div>"}else if(f.type=="website"){i="<div class='media-shadow website' id='"+f.uid+"'>"+r+"</div>";VMM.ExternalAPI.webthumb.get(f)}else{trace("NO KNOWN MEDIA TYPE FOUND");trace(f.type)}i="<div class='media-container' >"+i+o+s+"</div>";return a?"<div class='text-media'><div class='media-wrapper'>"+i+"</div></div>":"<div class='media-wrapper'>"+i+"</div>"}}}.init());typeof VMM!="undefined"&&typeof VMM.MediaType=="undefined"&&(VMM.MediaType=function(e){var t=e.replace(/^\s\s*/,"").replace(/\s\s*$/,""),n=!1,r={type:"unknown",id:"",start:0,hd:!1,link:"",lang:VMM.Language.lang,uniqueid:VMM.Util.unique_ID(6)};if(t.match("div class='twitter'")){r.type="twitter-ready";r.id=t;n=!0}else if(t.match("(www.)?youtube|youtu.be")){t.match("v=")?r.id=VMM.Util.getUrlVars(t).v:t.match("/embed/")?r.id=t.split("embed/")[1].split(/[?&]/)[0]:t.match(/v\/|v=|youtu\.be\//)?r.id=t.split(/v\/|v=|youtu\.be\//)[1].split(/[?&]/)[0]:trace("YOUTUBE IN URL BUT NOT A VALID VIDEO");r.start=VMM.Util.getUrlVars(t).t;r.hd=VMM.Util.getUrlVars(t).hd;r.type="youtube";n=!0}else if(t.match("(player.)?vimeo.com")){r.type="vimeo";r.id=t.split(/video\/|\/\/vimeo\.com\//)[1].split(/[?&]/)[0];n=!0}else if(t.match("(www.)?dailymotion.com")){r.id=t.split(/video\/|\/\/dailymotion\.com\//)[1];r.type="dailymotion";n=!0}else if(t.match("(player.)?soundcloud.com")){r.type="soundcloud";r.id=t;n=!0}else if(t.match("(www.)?twitter.com")&&t.match("status")){t.match("status/")?r.id=t.split("status/")[1]:t.match("statuses/")?r.id=t.split("statuses/")[1]:r.id="";r.type="twitter";n=!0}else if(t.match("maps.google")&&!t.match("staticmap")){r.type="google-map";r.id=t.split(/src=['|"][^'|"]*?['|"]/gi);n=!0}else if(t.match("plus.google")){r.type="googleplus";r.id=t.split("/posts/")[1];t.split("/posts/")[0].match("u/0/")?r.user=t.split("u/0/")[1].split("/posts")[0]:r.user=t.split("google.com/")[1].split("/posts/")[0];n=!0}else if(t.match("flickr.com/photos")){r.type="flickr";r.id=t.split("photos/")[1].split("/")[1];r.link=t;n=!0}else if(t.match("instagr.am/p/")){r.type="instagram";r.link=t;r.id=t.split("/p/")[1].split("/")[0];n=!0}else if(t.match(/jpg|jpeg|png|gif/i)||t.match("staticmap")||t.match("yfrog.com")||t.match("twitpic.com")){r.type="image";r.id=t;n=!0}else if(VMM.FileExtention.googleDocType(t)){r.type="googledoc";r.id=t;n=!0}else if(t.match("(www.)?wikipedia.org")){r.type="wikipedia";var i=t.split("wiki/")[1].split("#")[0].replace("_"," ");r.id=i.replace(" ","%20");r.lang=t.split("//")[1].split(".wikipedia")[0];n=!0}else if(t.indexOf("http://")==0){r.type="website";r.id=t;n=!0}else if(t.match("storify")){r.type="storify";r.id=t;n=!0}else if(t.match("blockquote")){r.type="quote";r.id=t;n=!0}else{trace("unknown media");r.type="unknown";r.id=t;n=!0}if(n)return r;trace("No valid media id detected");trace(t);return!1});typeof VMM!="undefined"&&typeof VMM.TextElement=="undefined"&&(VMM.TextElement={init:function(){return this},create:function(e){return e}}.init());typeof VMM!="undefined"&&typeof VMM.DragSlider=="undefined"&&(VMM.DragSlider=function(){function o(e,n){VMM.bindEvent(e,a,t.down,{element:n,delement:e});VMM.bindEvent(e,f,t.up,{element:n,delement:e});VMM.bindEvent(e,u,t.leave,{element:n,delement:e})}function u(n){VMM.unbindEvent(n.data.delement,l,t.move);e.touch||n.preventDefault();n.stopPropagation();if(e.sliding){e.sliding=!1;h(n.data.element,n.data.delement,n);return!1}return!0}function a(t){c(t.data.element,t.data.delement,t);e.touch||t.preventDefault();t.stopPropagation();return!0}function f(t){e.touch||t.preventDefault();t.stopPropagation();if(e.sliding){e.sliding=!1;h(t.data.element,t.data.delement,t);return!1}return!0}function l(e){p(e.data.element,e);return!1}function c(n,r,i){if(e.touch){trace("IS TOUCH");VMM.Lib.css(n,"-webkit-transition-duration","0");e.pagex.start=i.originalEvent.touches[0].screenX}else e.pagex.start=i.pageX;e.left.start=v(n);e.time.start=(new Date).getTime();VMM.Lib.stop(n);VMM.bindEvent(r,l,t.move,{element:n})}function h(e,n,r){VMM.unbindEvent(n,l,t.move);d(e,r)}function p(t,n){var r;e.sliding=!0;e.touch?e.pagex.end=n.originalEvent.touches[0].screenX:e.pagex.end=n.pageX;e.left.end=v(t);r=-(e.pagex.start-e.pagex.end-e.left.start);if(Math.abs(r-e.left.start)>10){VMM.Lib.css(t,"left",r);n.preventDefault();n.stopPropagation()}}function d(t,n){var r={left:e.left.end,left_adjust:0,change:{x:0},time:((new Date).getTime()-e.time.start)*10,time_adjust:((new Date).getTime()-e.time.start)*10},o=3e3;e.touch&&(o=6e3);r.change.x=o*(Math.abs(e.pagex.end)-Math.abs(e.pagex.start));r.left_adjust=Math.round(r.change.x/r.time);r.left=Math.min(r.left+r.left_adjust);if(e.constraint)if(r.left>e.constraint.left){r.left=e.constraint.left;r.time>5e3&&(r.time=5e3)}else if(r.left<e.constraint.right){r.left=e.constraint.right;r.time>5e3&&(r.time=5e3)}VMM.fireEvent(i,"DRAGUPDATE",[r]);s||r.time>0&&(e.touch?VMM.Lib.animate(t,r.time,"easeOutCirc",{left:r.left}):VMM.Lib.animate(t,r.time,e.ease,{left:r.left}))}function v(e){return parseInt(VMM.Lib.css(e,"left").substring(0,VMM.Lib.css(e,"left").length-2),10)}var e={element:"",element_move:"",constraint:"",sliding:!1,pagex:{start:0,end:0},left:{start:0,end:0},time:{start:0,end:0},touch:!1,ease:"easeOutExpo"},t={down:"mousedown",up:"mouseup",leave:"mouseleave",move:"mousemove"},n={down:"mousedown",up:"mouseup",leave:"mouseleave",move:"mousemove"},r={down:"touchstart",up:"touchend",leave:"mouseleave",move:"touchmove"},i=this,s=!1;this.createPanel=function(i,u,a,f,l){e.element=i;e.element_move=u;l!=null&&l!=""&&(s=l);a!=null&&a!=""?e.constraint=a:e.constraint=!1;f?e.touch=f:e.touch=!1;trace("TOUCH"+e.touch);e.touch?t=r:t=n;o(e.element,e.element_move)};this.updateConstraint=function(t){trace("updateConstraint");e.constraint=t};this.cancelSlide=function(n){VMM.unbindEvent(e.element,l,t.move);return!0}});typeof VMM!="undefined"&&typeof VMM.Slider=="undefined"&&(VMM.Slider=function(e,t){function S(){trace("onConfigSet")}function x(e,t){var r=!0,i=!1;e!=null&&(r=e);t!=null&&(i=t);m=n.slider.width;n.slider.nav.height=VMM.Lib.height(E.prevBtnContainer);VMM.Browser.device=="mobile"||m<=640?n.slider.content.padding=10:n.slider.content.padding=n.slider.content.padding_default;n.slider.content.width=m-n.slider.content.padding*2;VMM.Lib.width(u,h.length*n.slider.content.width);i&&VMM.Lib.css(o,"left",h[v].leftpos());B();j();VMM.Lib.css(E.nextBtn,"left",m-n.slider.nav.width);VMM.Lib.height(E.prevBtn,n.slider.height);VMM.Lib.height(E.nextBtn,n.slider.height);VMM.Lib.css(E.nextBtnContainer,"top",n.slider.height/2-n.slider.nav.height/2+10);VMM.Lib.css(E.prevBtnContainer,"top",n.slider.height/2-n.slider.nav.height/2+10);VMM.Lib.height(s,n.slider.height);VMM.Lib.width(s,m);r&&I(v,"linear",1);v==0&&VMM.Lib.visible(E.prevBtn,!1)}function T(e,t){trace("DRAG FINISH");trace(t.left_adjust);trace(n.slider.width/2);if(t.left_adjust<0)if(Math.abs(t.left_adjust)>n.slider.width/2)if(v==h.length-1)q();else{I(v+1,"easeOutExpo");O()}else q();else if(Math.abs(t.left_adjust)>n.slider.width/2)if(v==0)q();else{I(v-1,"easeOutExpo");O()}else q()}function N(e){if(v==h.length-1)q();else{I(v+1);O()}}function C(e){if(v==0)q();else{I(v-1);O()}}function k(e){switch(e.keyCode){case 39:N(e);break;case 37:C(e)}}function L(e,t){if(p.length==0)for(var r=0;r<h.length;r++)p.push(h[r].leftpos());if(typeof t.left=="number"){var i=t.left,s=-h[v].leftpos();i<s-n.slider_width/3?N():i>s+n.slider_width/3?C():VMM.Lib.animate(o,n.duration,n.ease,{left:s})}else VMM.Lib.animate(o,n.duration,n.ease,{left:s});typeof t.top=="number"&&VMM.Lib.animate(o,n.duration,n.ease,{top:-t.top})}function A(e){z()}function O(){n.current_slide=v;VMM.fireEvent(w,"UPDATE")}function M(e){c=e}function _(e){var t=0;VMM.attachElement(u,"");h=[];for(t=0;t<e.length;t++){var n=new VMM.Slider.Slide(e[t],u);h.push(n)}}function D(e){var t=0;if(e)P();else{for(t=0;t<h.length;t++)h[t].clearTimers();r=setTimeout(P,n.duration)}}function P(){var e=0;for(e=0;e<h.length;e++)h[e].enqueue=!0;for(e=0;e<n.preload;e++){if(!(v+e>h.length-1)){h[v+e].show();h[v+e].enqueue=!1}if(!(v-e<0)){h[v-e].show();h[v-e].enqueue=!1}}if(h.length>50)for(e=0;e<h.length;e++)h[e].enqueue&&h[e].hide();B()}function H(e){}function B(){var e=0,t=".slider-item .layout-text-media .media .media-container ",r=".slider-item .layout-media .media .media-container ",i=".slider-item .media .media-container",s=".slider-item .media .media-container .media-shadow .caption",o=!1,u={text_media:{width:n.slider.content.width/100*60,height:n.slider.height-60,video:{width:0,height:0},text:{width:n.slider.content.width/100*40-30,height:n.slider.height}},media:{width:n.slider.content.width,height:n.slider.height-110,video:{width:0,height:0}}};if(VMM.Browser.device=="mobile"||m<641)o=!0;VMM.master_config.sizes.api.width=u.media.width;VMM.master_config.sizes.api.height=u.media.height;u.text_media.video=VMM.Util.ratio.fit(u.text_media.width,u.text_media.height,16,9);u.media.video=VMM.Util.ratio.fit(u.media.width,u.media.height,16,9);VMM.Lib.css(".slider-item","width",n.slider.content.width);VMM.Lib.height(".slider-item",n.slider.height);if(o){u.text_media.width=n.slider.content.width-n.slider.content.padding*2;u.media.width=n.slider.content.width-n.slider.content.padding*2;u.text_media.height=n.slider.height/100*50-50;u.media.height=n.slider.height/100*70-40;u.text_media.video=VMM.Util.ratio.fit(u.text_media.width,u.text_media.height,16,9);u.media.video=VMM.Util.ratio.fit(u.media.width,u.media.height,16,9);VMM.Lib.css(".slider-item .layout-text-media .text","width","100%");VMM.Lib.css(".slider-item .layout-text-media .text","display","block");VMM.Lib.css(".slider-item .layout-text-media .text .container","display","block");VMM.Lib.css(".slider-item .layout-text-media .text .container","width",u.media.width);VMM.Lib.css(".slider-item .layout-text-media .text .container .start","width","auto");VMM.Lib.css(".slider-item .layout-text-media .media","float","none");VMM.Lib.addClass(".slider-item .content-container","pad-top");VMM.Lib.css(".slider-item .media blockquote p","line-height","18px");VMM.Lib.css(".slider-item .media blockquote p","font-size","16px");VMM.Lib.css(".slider-item","overflow-y","auto")}else{VMM.Lib.css(".slider-item .layout-text-media .text","width","40%");VMM.Lib.css(".slider-item .layout-text-media .text","display","table-cell");VMM.Lib.css(".slider-item .layout-text-media .text .container","display","table-cell");VMM.Lib.css(".slider-item .layout-text-media .text .container","width","auto");VMM.Lib.css(".slider-item .layout-text-media .text .container .start","width",u.text_media.text.width);VMM.Lib.removeClass(".slider-item .content-container","pad-top");VMM.Lib.css(".slider-item .layout-text-media .media","float","left");VMM.Lib.css(".slider-item .layout-text-media","display","table");VMM.Lib.css(".slider-item .media blockquote p","line-height","36px");VMM.Lib.css(".slider-item .media blockquote p","font-size","28px");VMM.Lib.css(".slider-item","display","table");VMM.Lib.css(".slider-item","overflow-y","auto")}VMM.Lib.css(t+".media-frame","max-width",u.text_media.width);VMM.Lib.height(t+".media-frame",u.text_media.height);VMM.Lib.width(t+".media-frame",u.text_media.width);VMM.Lib.css(t+"img","max-height",u.text_media.height);VMM.Lib.css(r+"img","max-height",u.media.height);VMM.Lib.css(t+"img","max-width",u.text_media.width);VMM.Lib.css(t+".avatar img","max-width",32);VMM.Lib.css(t+".avatar img","max-height",32);VMM.Lib.css(r+".avatar img","max-width",32);VMM.Lib.css(r+".avatar img","max-height",32);VMM.Lib.css(t+".article-thumb","max-width","50%");VMM.Lib.css(r+".article-thumb","max-width",200);VMM.Lib.width(t+".media-frame",u.text_media.video.width);VMM.Lib.height(t+".media-frame",u.text_media.video.height);VMM.Lib.width(r+".media-frame",u.media.video.width);VMM.Lib.height(r+".media-frame",u.media.video.height);VMM.Lib.css(r+".media-frame","max-height",u.media.video.height);VMM.Lib.css(r+".media-frame","max-width",u.media.video.width);VMM.Lib.height(r+".soundcloud",168);VMM.Lib.height(t+".soundcloud",168);VMM.Lib.width(r+".soundcloud",u.media.width);VMM.Lib.width(t+".soundcloud",u.text_media.width);VMM.Lib.css(i+".soundcloud","max-height",168);VMM.Lib.height(t+".map",u.text_media.height);VMM.Lib.width(t+".map",u.text_media.width);VMM.Lib.css(r+".map","max-height",u.media.height);VMM.Lib.width(r+".map",u.media.width);VMM.Lib.height(t+".doc",u.text_media.height);VMM.Lib.width(t+".doc",u.text_media.width);VMM.Lib.height(r+".doc",u.media.height);VMM.Lib.width(r+".doc",u.media.width);VMM.Lib.width(r+".wikipedia",u.media.width);VMM.Lib.width(r+".twitter",u.media.width);VMM.Lib.width(r+".plain-text-quote",u.media.width);VMM.Lib.width(r+".plain-text",u.media.width);VMM.Lib.css(i,"max-width",u.media.width);VMM.Lib.css(t+".caption","max-width",u.text_media.video.width);VMM.Lib.css(r+".caption","max-width",u.media.video.width);for(e=0;e<h.length;e++){h[e].layout(o);h[e].content_height()>n.slider.height+20?h[e].css("display","block"):h[e].css("display","table")}}function j(){var e=0,t=0;for(t=0;t<h.length;t++){e=t*(n.slider.width+n.spacing);h[t].leftpos(e)}}function F(e){var t="linear",r=0;for(r=0;r<h.length;r++)r==v?h[r].animate(n.duration,t,{opacity:1}):r==v-1||r==v+1?h[r].animate(n.duration,t,{opacity:.1}):h[r].opacity(e)}function I(e,t,r,s,u){var a=n.ease,f=n.duration,l=!1,p=!1,d="",m;VMM.ExternalAPI.youtube.stopPlayers();v=e;m=h[v].leftpos();v==0&&(p=!0);v+1>=h.length&&(l=!0);t!=null&&t!=""&&(a=t);r!=null&&r!=""&&(f=r);if(VMM.Browser.device=="mobile"){VMM.Lib.visible(E.prevBtn,!1);VMM.Lib.visible(E.nextBtn,!1)}else{if(p)VMM.Lib.visible(E.prevBtn,!1);else{VMM.Lib.visible(E.prevBtn,!0);d=VMM.Util.unlinkify(c[v-1].title);if(n.type=="timeline")if(typeof c[v-1].date=="undefined"){VMM.attachElement(E.prevDate,d);VMM.attachElement(E.prevTitle,"")}else{VMM.attachElement(E.prevDate,VMM.Date.prettyDate(c[v-1].startdate,!1,c[v-1].precisiondate));VMM.attachElement(E.prevTitle,d)}else VMM.attachElement(E.prevTitle,d)}if(l)VMM.Lib.visible(E.nextBtn,!1);else{VMM.Lib.visible(E.nextBtn,!0);d=VMM.Util.unlinkify(c[v+1].title);if(n.type=="timeline")if(typeof c[v+1].date=="undefined"){VMM.attachElement(E.nextDate,d);VMM.attachElement(E.nextTitle,"")}else{VMM.attachElement(E.nextDate,VMM.Date.prettyDate(c[v+1].startdate,!1,c[v+1].precisiondate));VMM.attachElement(E.nextTitle,d)}else VMM.attachElement(E.nextTitle,d)}}if(s)VMM.Lib.css(o,"left",-(m-n.slider.content.padding));else{VMM.Lib.stop(o);VMM.Lib.animate(o,f,a,{left:-(m-n.slider.content.padding)})}u&&VMM.fireEvent(w,"LOADED");if(h[v].height()>n.slider_height)VMM.Lib.css(".slider","overflow-y","scroll");else{VMM.Lib.css(w,"overflow-y","hidden");var g=0;try{g=VMM.Lib.prop(w,"scrollHeight");VMM.Lib.animate(w,f,a,{scrollTop:g-VMM.Lib.height(w)})}catch(y){g=VMM.Lib.height(w)}}D();VMM.fireEvent(i,"MESSAGE","TEST")}function q(){VMM.Lib.stop(o);VMM.Lib.animate(o,n.duration,"easeOutExpo",{left:-h[v].leftpos()+n.slider.content.padding})}function R(e,t,n){trace("showMessege "+t);VMM.attachElement(f,"<div class='vco-explainer'><div class='vco-explainer-container'><div class='vco-bezel'><div class='vco-gesture-icon'></div><div class='vco-message'><p>"+t+"</p></div></div></div></div>")}function U(){VMM.Lib.animate(f,n.duration,n.ease,{opacity:0},z)}function z(){VMM.Lib.detach(f)}function W(){var e="<div class='icon'>&nbsp;</div>";E.nextBtn=VMM.appendAndGetElement(i,"<div>","nav-next");E.prevBtn=VMM.appendAndGetElement(i,"<div>","nav-previous");E.nextBtnContainer=VMM.appendAndGetElement(E.nextBtn,"<div>","nav-container",e);E.prevBtnContainer=VMM.appendAndGetElement(E.prevBtn,"<div>","nav-container",e);if(n.type=="timeline"){E.nextDate=VMM.appendAndGetElement(E.nextBtnContainer,"<div>","date","");E.prevDate=VMM.appendAndGetElement(E.prevBtnContainer,"<div>","date","")}E.nextTitle=VMM.appendAndGetElement(E.nextBtnContainer,"<div>","title","");E.prevTitle=VMM.appendAndGetElement(E.prevBtnContainer,"<div>","title","");VMM.bindEvent(".nav-next",N);VMM.bindEvent(".nav-previous",C);VMM.bindEvent(window,k,"keydown")}function X(){var e=3e3;VMM.attachElement(w,"");i=VMM.getElement(w);s=VMM.appendAndGetElement(i,"<div>","slider-container-mask");o=VMM.appendAndGetElement(s,"<div>","slider-container");u=VMM.appendAndGetElement(o,"<div>","slider-item-container");W();_(c);if(VMM.Browser.device=="tablet"||VMM.Browser.device=="mobile"){n.duration=500;e=1e3;a=new VMM.DragSlider;a.createPanel(i,o,"",n.touch,!0);VMM.bindEvent(a,T,"DRAGUPDATE");f=VMM.appendAndGetElement(s,"<div>","vco-feedback","");R(null,"Swipe to Navigate");VMM.Lib.height(f,n.slider.height);VMM.bindEvent(f,A);VMM.bindEvent(f,A,"touchend")}x(!1,!0);VMM.Lib.visible(E.prevBtn,!1);I(n.current_slide,"easeOutExpo",e,!0,!0);b=!0}var n,r,i,s,o,u,a,f,l={},c=[],h=[],p=[],d="",v=0,m=960,g={move:!1,x:10,y:0,off:0,dampen:48},y="",b=!1,w=e,E={nextBtn:"",prevBtn:"",nextDate:"",prevDate:"",nextTitle:"",prevTitle:""};typeof t!="undefined"?n=t:n={preload:4,current_slide:0,interval:10,something:0,width:720,height:400,ease:"easeInOutExpo",duration:1e3,timeline:!1,spacing:15,slider:{width:720,height:400,content:{width:720,height:400,padding:120,padding_default:120},nav:{width:100,height:200}}};this.ver="0.6";n.slider.width=n.width;n.slider.height=n.height;this.init=function(e){h=[];p=[];typeof e!="undefined"?this.setData(e):trace("WAITING ON DATA")};this.width=function(e){if(e==null||e=="")return n.slider.width;n.slider.width=e;x()};this.height=function(e){if(e==null||e=="")return n.slider.height;n.slider.height=e;x()};this.setData=function(e){if(typeof e!="undefined"){c=e;X()}else trace("NO DATA")};this.getData=function(){return c};this.setConfig=function(e){typeof e!="undefined"?n=e:trace("NO CONFIG DATA")};this.getConfig=function(){return n};this.setSize=function(e,t){e!=null&&(n.slider.width=e);t!=null&&(n.slider.height=t);b&&x()};this.active=function(){return b};this.getCurrentNumber=function(){return v};this.setSlide=function(e){I(e)}});typeof VMM.Slider!="undefined"&&(VMM.Slider.Slide=function(e,t){var n,r,i,s,o,u,a=e,f={},o="",l="",c=!1,h=!1,p=!1,d=!0,v=!1,m="slide_",g=0,y={pushque:"",render:"",relayout:"",remove:"",skinny:!1},b={pushque:500,render:100,relayout:100,remove:3e4};m+=a.uniqueid;this.enqueue=d;this.id=m;o=VMM.appendAndGetElement(t,"<div>","slider-item");if(typeof a.classname!="undefined"){trace("HAS CLASSNAME");VMM.Lib.addClass(o,a.classname)}else{trace("NO CLASSNAME");trace(a)}u={slide:"",text:"",media:"",media_element:"",layout:"content-container layout",has:{headline:!1,text:!1,media:!1}};this.show=function(e){d=!1;y.skinny=e;v=!1;clearTimeout(y.remove);if(!c)if(h){clearTimeout(y.relayout);y.relayout=setTimeout(S,b.relayout)}else w(e)};this.hide=function(){if(c&&!v){v=!0;clearTimeout(y.remove);y.remove=setTimeout(E,b.remove)}};this.clearTimers=function(){clearTimeout(y.relayout);clearTimeout(y.pushque);clearTimeout(y.render)};this.layout=function(e){c&&h&&x(e)};this.elem=function(){return o};this.position=function(){return VMM.Lib.position(o)};this.leftpos=function(e){if(typeof e=="undefined")return VMM.Lib.position(o).left;VMM.Lib.css(o,"left",e)};this.animate=function(e,t,n){VMM.Lib.animate(o,e,t,n)};this.css=function(e,t){VMM.Lib.css(o,e,t)};this.opacity=function(e){VMM.Lib.css(o,"opacity",e)};this.width=function(){return VMM.Lib.width(o)};this.height=function(){return VMM.Lib.height(o)};this.content_height=function(){var e=VMM.Lib.find(o,".content")[0];return e!="undefined"&&e!=null?VMM.Lib.height(e):0};var w=function(e){trace("RENDER "+m);c=!0;h=!0;y.skinny=e;T();clearTimeout(y.pushque);clearTimeout(y.render);y.pushque=setTimeout(VMM.ExternalAPI.pushQues,b.pushque)},E=function(){trace("REMOVE SLIDE TIMER FINISHED");c=!1;VMM.Lib.detach(r);VMM.Lib.detach(n)},S=function(){c=!0;x(y.skinny,!0)},x=function(e,t){if(u.has.text){if(e){if(!p||t){VMM.Lib.removeClass(i,"pad-left");VMM.Lib.detach(r);VMM.Lib.detach(n);VMM.Lib.append(i,r);VMM.Lib.append(i,n);p=!0}}else if(p||t){VMM.Lib.addClass(i,"pad-left");VMM.Lib.detach(r);VMM.Lib.detach(n);VMM.Lib.append(i,n);VMM.Lib.append(i,r);p=!1}}else if(t){if(u.has.headline){VMM.Lib.detach(r);VMM.Lib.append(i,r)}VMM.Lib.detach(n);VMM.Lib.append(i,n)}},T=function(){trace("BUILDSLIDE");s=VMM.appendAndGetElement(o,"<div>","content");i=VMM.appendAndGetElement(s,"<div>");if(a.startdate!=null&&a.startdate!=""&&type.of(a.startdate)=="date"&&a.type!="start"){var e=VMM.Date.prettyDate(a.startdate,!1,a.precisiondate),t=VMM.Date.prettyDate(a.enddate,!1,a.precisiondate),f="";a.tag!=null&&a.tag!=""&&(f=VMM.createElement("span",a.tag,"slide-tag"));e!=t?u.text+=VMM.createElement("h2",e+" &mdash; "+t+f,"date"):u.text+=VMM.createElement("h2",e+f,"date")}if(a.headline!=null&&a.headline!=""){u.has.headline=!0;a.type=="start"?u.text+=VMM.createElement("h2",VMM.Util.linkify_with_twitter(a.headline,"_blank"),"start"):u.text+=VMM.createElement("h3",VMM.Util.linkify_with_twitter(a.headline,"_blank"))}if(a.text!=null&&a.text!=""){u.has.text=!0;u.text+=VMM.createElement("p",VMM.Util.linkify_with_twitter(a.text,"_blank"))}if(u.has.text||u.has.headline){u.text=VMM.createElement("div",u.text,"container");r=VMM.appendAndGetElement(i,"<div>","text",VMM.TextElement.create(u.text))}a.needs_slug;if(a.asset!=null&&a.asset!=""&&a.asset.media!=null&&a.asset.media!=""){u.has.media=!0;n=VMM.appendAndGetElement(i,"<div>","media",VMM.MediaElement.create(a.asset,a.uniqueid))}u.has.text&&(u.layout+="-text");u.has.media&&(u.layout+="-media");if(u.has.text)if(y.skinny){VMM.Lib.addClass(i,u.layout);p=!0}else{VMM.Lib.addClass(i,u.layout);VMM.Lib.addClass(i,"pad-left");VMM.Lib.detach(r);VMM.Lib.append(i,r)}else VMM.Lib.addClass(i,u.layout)}});var Aes={};Aes.cipher=function(e,t){var n=4,r=t.length/n-1,i=[[],[],[],[]];for(var s=0;s<4*n;s++)i[s%4][Math.floor(s/4)]=e[s];i=Aes.addRoundKey(i,t,0,n);for(var o=1;o<r;o++){i=Aes.subBytes(i,n);i=Aes.shiftRows(i,n);i=Aes.mixColumns(i,n);i=Aes.addRoundKey(i,t,o,n)}i=Aes.subBytes(i,n);i=Aes.shiftRows(i,n);i=Aes.addRoundKey(i,t,r,n);var u=new Array(4*n);for(var s=0;s<4*n;s++)u[s]=i[s%4][Math.floor(s/4)];return u};Aes.keyExpansion=function(e){var t=4,n=e.length/4,r=n+6,i=new Array(t*(r+1)),s=new Array(4);for(var o=0;o<n;o++){var u=[e[4*o],e[4*o+1],e[4*o+2],e[4*o+3]];i[o]=u}for(var o=n;o<t*(r+1);o++){i[o]=new Array(4);for(var a=0;a<4;a++)s[a]=i[o-1][a];if(o%n==0){s=Aes.subWord(Aes.rotWord(s));for(var a=0;a<4;a++)s[a]^=Aes.rCon[o/n][a]}else n>6&&o%n==4&&(s=Aes.subWord(s));for(var a=0;a<4;a++)i[o][a]=i[o-n][a]^s[a]}return i};Aes.subBytes=function(e,t){for(var n=0;n<4;n++)for(var r=0;r<t;r++)e[n][r]=Aes.sBox[e[n][r]];return e};Aes.shiftRows=function(e,t){var n=new Array(4);for(var r=1;r<4;r++){for(var i=0;i<4;i++)n[i]=e[r][(i+r)%t];for(var i=0;i<4;i++)e[r][i]=n[i]}return e};Aes.mixColumns=function(e,t){for(var n=0;n<4;n++){var r=new Array(4),i=new Array(4);for(var s=0;s<4;s++){r[s]=e[s][n];i[s]=e[s][n]&128?e[s][n]<<1^283:e[s][n]<<1}e[0][n]=i[0]^r[1]^i[1]^r[2]^r[3];e[1][n]=r[0]^i[1]^r[2]^i[2]^r[3];e[2][n]=r[0]^r[1]^i[2]^r[3]^i[3];e[3][n]=r[0]^i[0]^r[1]^r[2]^i[3]}return e};Aes.addRoundKey=function(e,t,n,r){for(var i=0;i<4;i++)for(var s=0;s<r;s++)e[i][s]^=t[n*4+s][i];return e};Aes.subWord=function(e){for(var t=0;t<4;t++)e[t]=Aes.sBox[e[t]];return e};Aes.rotWord=function(e){var t=e[0];for(var n=0;n<3;n++)e[n]=e[n+1];e[3]=t;return e};Aes.sBox=[99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22];Aes.rCon=[[0,0,0,0],[1,0,0,0],[2,0,0,0],[4,0,0,0],[8,0,0,0],[16,0,0,0],[32,0,0,0],[64,0,0,0],[128,0,0,0],[27,0,0,0],[54,0,0,0]];Aes.Ctr={};Aes.Ctr.encrypt=function(e,t,n){var r=16;if(n!=128&&n!=192&&n!=256)return"";e=Utf8.encode(e);t=Utf8.encode(t);var i=n/8,s=new Array(i);for(var o=0;o<i;o++)s[o]=isNaN(t.charCodeAt(o))?0:t.charCodeAt(o);var u=Aes.cipher(s,Aes.keyExpansion(s));u=u.concat(u.slice(0,i-16));var a=new Array(r),f=(new Date).getTime(),l=f%1e3,c=Math.floor(f/1e3),h=Math.floor(Math.random()*65535);for(var o=0;o<2;o++)a[o]=l>>>o*8&255;for(var o=0;o<2;o++)a[o+2]=h>>>o*8&255;for(var o=0;o<4;o++)a[o+4]=c>>>o*8&255;var p="";for(var o=0;o<8;o++)p+=String.fromCharCode(a[o]);var d=Aes.keyExpansion(u),v=Math.ceil(e.length/r),m=new Array(v);for(var g=0;g<v;g++){for(var y=0;y<4;y++)a[15-y]=g>>>y*8&255;for(var y=0;y<4;y++)a[15-y-4]=g/4294967296>>>y*8;var b=Aes.cipher(a,d),w=g<v-1?r:(e.length-1)%r+1,E=new Array(w);for(var o=0;o<w;o++){E[o]=b[o]^e.charCodeAt(g*r+o);E[o]=String.fromCharCode(E[o])}m[g]=E.join("")}var S=p+m.join("");S=Base64.encode(S);return S};Aes.Ctr.decrypt=function(e,t,n){var r=16;if(n!=128&&n!=192&&n!=256)return"";e=Base64.decode(e);t=Utf8.encode(t);var i=n/8,s=new Array(i);for(var o=0;o<i;o++)s[o]=isNaN(t.charCodeAt(o))?0:t.charCodeAt(o);var u=Aes.cipher(s,Aes.keyExpansion(s));u=u.concat(u.slice(0,i-16));var a=new Array(8);ctrTxt=e.slice(0,8);for(var o=0;o<8;o++)a[o]=ctrTxt.charCodeAt(o);var f=Aes.keyExpansion(u),l=Math.ceil((e.length-8)/r),c=new Array(l);for(var h=0;h<l;h++)c[h]=e.slice(8+h*r,8+h*r+r);e=c;var p=new Array(e.length);for(var h=0;h<l;h++){for(var d=0;d<4;d++)a[15-d]=h>>>d*8&255;for(var d=0;d<4;d++)a[15-d-4]=(h+1)/4294967296-1>>>d*8&255;var v=Aes.cipher(a,f),m=new Array(e[h].length);for(var o=0;o<e[h].length;o++){m[o]=v[o]^e[h].charCodeAt(o);m[o]=String.fromCharCode(m[o])}p[h]=m.join("")}var g=p.join("");g=Utf8.decode(g);return g};var Base64={};Base64.code="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";Base64.encode=function(e,t){t=typeof t=="undefined"?!1:t;var n,r,i,s,o,u,a,f,l=[],c="",h,p,d,v=Base64.code;p=t?e.encodeUTF8():e;h=p.length%3;if(h>0)while(h++<3){c+="=";p+="\0"}for(h=0;h<p.length;h+=3){n=p.charCodeAt(h);r=p.charCodeAt(h+1);i=p.charCodeAt(h+2);s=n<<16|r<<8|i;o=s>>18&63;u=s>>12&63;a=s>>6&63;f=s&63;l[h/3]=v.charAt(o)+v.charAt(u)+v.charAt(a)+v.charAt(f)}d=l.join("");d=d.slice(0,d.length-c.length)+c;return d};Base64.decode=function(e,t){t=typeof t=="undefined"?!1:t;var n,r,i,s,o,u,a,f,l=[],c,h,p=Base64.code;h=t?e.decodeUTF8():e;for(var d=0;d<h.length;d+=4){s=p.indexOf(h.charAt(d));o=p.indexOf(h.charAt(d+1));u=p.indexOf(h.charAt(d+2));a=p.indexOf(h.charAt(d+3));f=s<<18|o<<12|u<<6|a;n=f>>>16&255;r=f>>>8&255;i=f&255;l[d/4]=String.fromCharCode(n,r,i);a==64&&(l[d/4]=String.fromCharCode(n,r));u==64&&(l[d/4]=String.fromCharCode(n))}c=l.join("");return t?c.decodeUTF8():c};var Utf8={};Utf8.encode=function(e){var t=e.replace(/[\u0080-\u07ff]/g,function(e){var t=e.charCodeAt(0);return String.fromCharCode(192|t>>6,128|t&63)});t=t.replace(/[\u0800-\uffff]/g,function(e){var t=e.charCodeAt(0);return String.fromCharCode(224|t>>12,128|t>>6&63,128|t&63)});return t};Utf8.decode=function(e){var t=e.replace(/[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g,function(e){var t=(e.charCodeAt(0)&15)<<12|(e.charCodeAt(1)&63)<<6|e.charCodeAt(2)&63;return String.fromCharCode(t)});t=t.replace(/[\u00c0-\u00df][\u0080-\u00bf]/g,function(e){var t=(e.charCodeAt(0)&31)<<6|e.charCodeAt(1)&63;return String.fromCharCode(t)});return t};!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s;this.type=t;this.$element=e(n);this.options=this.getOptions(r);this.enabled=!0;if(this.options.trigger!="manual"){i=this.options.trigger=="hover"?"mouseenter":"focus";s=this.options.trigger=="hover"?"mouseleave":"blur";this.$element.on(i,this.options.selector,e.proxy(this.enter,this));this.$element.on(s,this.options.selector,e.proxy(this.leave,this))}this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){t=e.extend({},e.fn[this.type].defaults,t,this.$element.data());t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay});return t},enter:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);if(!n.options.delay||!n.options.delay.show)n.show();else{n.hoverState="in";setTimeout(function(){n.hoverState=="in"&&n.show()},n.options.delay.show)}},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);if(!n.options.delay||!n.options.delay.hide)n.hide();else{n.hoverState="out";setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)}},show:function(){var e,t,n,r,i,s,o;if(this.hasContent()&&this.enabled){e=this.tip();this.setContent();this.options.animation&&e.addClass("fade");s=typeof this.options.placement=="function"?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement;t=/in/.test(s);e.remove().css({top:0,left:0,display:"block"}).appendTo(t?this.$element:document.body);n=this.getPosition(t);r=e[0].offsetWidth;i=e[0].offsetHeight;switch(t?s.split(" ")[1]:s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}e.css(o).addClass(s).addClass("in")}},setContent:function(){var e=this.tip();e.find(".tooltip-inner").html(this.getTitle());e.removeClass("fade in top bottom left right")},hide:function(){function r(){var t=setTimeout(function(){n.off(e.support.transition.end).remove()},500);n.one(e.support.transition.end,function(){clearTimeout(t);n.remove()})}var t=this,n=this.tip();n.removeClass("in");e.support.transition&&this.$tip.hasClass("fade")?r():n.remove()},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(t){return e.extend({},t?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var e,t=this.$element,n=this.options;e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title);e=e.toString().replace(/(^\s*|\s*$)/,"");return e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},validate:function(){if(!this.$element[0].parentNode){this.hide();this.$element=null;this.options=null}},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(){this[this.tip().hasClass("in")?"hide":"show"]()}};e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s));typeof n=="string"&&i[n]()})};e.fn.tooltip.Constructor=t;e.fn.tooltip.defaults={animation:!0,delay:0,selector:!1,placement:"top",trigger:"hover",title:"",template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'}}(window.jQuery);typeof VMM!="undefined"&&typeof VMM.StoryJS=="undefined"&&(VMM.StoryJS=function(){this.init=function(e){}});if(typeof VMM!="undefined"&&typeof VMM.Timeline=="undefined"){VMM.Timeline=function(e,t,n){function S(e){typeof embed_config=="object"&&(timeline_config=embed_config);if(typeof timeline_config=="object" +){trace("HAS TIMELINE CONFIG");m=VMM.Util.mergeConfig(m,timeline_config)}else typeof e=="object"&&(m=VMM.Util.mergeConfig(m,e));if(VMM.Browser.device=="mobile"||VMM.Browser.device=="tablet")m.touch=!0;m.nav.width=m.width;m.nav.height=200;m.feature.width=m.width;m.feature.height=m.height-m.nav.height;m.nav.zoom.adjust=parseInt(m.start_zoom_adjust,10);VMM.Timeline.Config=m;VMM.master_config.Timeline=VMM.Timeline.Config;this.events=m.events;m.gmap_key!=""&&(m.api_keys.google=m.gmap_key);trace("VERSION "+m.version);c=m.version}function x(){r=VMM.getElement(h);VMM.Lib.addClass(r,"vco-timeline");VMM.Lib.addClass(r,"vco-storyjs");i=VMM.appendAndGetElement(r,"<div>","vco-container vco-main");s=VMM.appendAndGetElement(i,"<div>","vco-feature");u=VMM.appendAndGetElement(s,"<div>","vco-slider");a=VMM.appendAndGetElement(i,"<div>","vco-navigation");o=VMM.appendAndGetElement(r,"<div>","vco-feedback","");typeof m.language.right_to_left!="undefined"&&VMM.Lib.addClass(r,"vco-right-to-left");f=new VMM.Slider(u,m);l=new VMM.Timeline.TimeNav(a);g?VMM.Lib.width(r,m.width):m.width=VMM.Lib.width(r);y?VMM.Lib.height(r,m.height):m.height=VMM.Lib.height(r);m.touch?VMM.Lib.addClass(r,"vco-touch"):VMM.Lib.addClass(r,"vco-notouch")}function T(e,t){trace("onDataReady");d=t.timeline;type.of(d.era)!="array"&&(d.era=[]);X()}function N(){U()}function C(){W();f.setSize(m.feature.width,m.feature.height);l.setSize(m.width,m.height);j()&&H()}function k(e){m.loaded.slider=!0;L()}function L(e){m.loaded.percentloaded=m.loaded.percentloaded+25;m.loaded.slider&&m.loaded.timenav&&q()}function A(e){m.loaded.timenav=!0;L()}function O(e){w=!0;m.current_slide=f.getCurrentNumber();D(m.current_slide);l.setMarker(m.current_slide,m.ease,m.duration)}function M(e){w=!0;m.current_slide=l.getCurrentNumber();D(m.current_slide);f.setSlide(m.current_slide)}function _(e){if(e<=v.length-1&&e>=0){m.current_slide=e;f.setSlide(m.current_slide);l.setMarker(m.current_slide,m.ease,m.duration)}}function D(e){m.hash_bookmark&&(window.location.hash="#"+e.toString())}function P(){}function H(){var e="",t=B(window.orientation);VMM.Browser.device=="mobile"?t=="portrait"?e="width=device-width; initial-scale=0.5, maximum-scale=0.5":t=="landscape"?e="width=device-width; initial-scale=0.5, maximum-scale=0.5":e="width=device-width, initial-scale=1, maximum-scale=1.0":VMM.Browser.device=="tablet";document.getElementById("viewport")}function B(e){var t="";e==0||e==180?t="portrait":e==90||e==-90?t="landscape":t="normal";return t}function j(){var e=B(window.orientation);if(e==m.orientation)return!1;m.orientation=e;return!0}function F(e){VMM.getJSON(e,function(e){d=VMM.Timeline.DataObj.getData(e);VMM.fireEvent(global,m.events.data_ready)})}function I(e,t,n){trace("showMessege "+t);n?VMM.attachElement(o,t):VMM.attachElement(o,VMM.MediaElement.loadingmessage(t))}function q(){VMM.Lib.animate(o,m.duration,m.ease*4,{opacity:0},R)}function R(){VMM.Lib.detach(o)}function U(){parseInt(m.start_at_slide)>0&&m.current_slide==0&&(m.current_slide=parseInt(m.start_at_slide));m.start_at_end&&m.current_slide==0&&(m.current_slide=v.length-1);if(b){b=!0;VMM.fireEvent(global,m.events.messege,"Internet Explorer "+VMM.Browser.version+" is not supported by TimelineJS. Please update your browser to version 8 or higher.")}else{R();C();VMM.bindEvent(u,k,"LOADED");VMM.bindEvent(a,A,"LOADED");VMM.bindEvent(u,O,"UPDATE");VMM.bindEvent(a,M,"UPDATE");f.init(v);l.init(v,d.era);VMM.bindEvent(global,C,m.events.resize)}}function z(){trace("IE7 or lower");for(var e=0;e<v.length;e++)trace(v[e])}function W(){trace("UPDATE SIZE");m.width=VMM.Lib.width(r);m.height=VMM.Lib.height(r);m.nav.width=m.width;m.feature.width=m.width;m.feature.height=m.height-m.nav.height-3;VMM.Browser.device=="mobile";m.width<641?VMM.Lib.addClass(r,"vco-skinny"):VMM.Lib.removeClass(r,"vco-skinny")}function X(){v=[];VMM.fireEvent(global,m.events.messege,"Building Dates");W();for(var e=0;e<d.date.length;e++)if(d.date[e].startDate!=null&&d.date[e].startDate!=""){var t={},n=VMM.Date.parse(d.date[e].startDate,!0),r;t.startdate=n.date;t.precisiondate=n.precision;if(!isNaN(t.startdate)){d.date[e].endDate!=null&&d.date[e].endDate!=""?t.enddate=VMM.Date.parse(d.date[e].endDate):t.enddate=t.startdate;t.needs_slug=!1;d.date[e].headline==""&&d.date[e].slug!=null&&d.date[e].slug!=""&&(t.needs_slug=!0);t.title=d.date[e].headline;t.headline=d.date[e].headline;t.type=d.date[e].type;t.date=VMM.Date.prettyDate(t.startdate,!1,t.precisiondate);t.asset=d.date[e].asset;t.fulldate=t.startdate.getTime();t.text=d.date[e].text;t.content="";t.tag=d.date[e].tag;t.slug=d.date[e].slug;t.uniqueid=VMM.Util.unique_ID(7);t.classname=d.date[e].classname;v.push(t)}}d.type!="storify"&&v.sort(function(e,t){return e.fulldate-t.fulldate});if(d.headline!=null&&d.headline!=""&&d.text!=null&&d.text!=""){var i,n,t={},s=0,o;if(typeof d.startDate!="undefined"){n=VMM.Date.parse(d.startDate,!0);i=n.date}else i=!1;trace("HAS STARTPAGE");trace(i);if(i&&i<v[0].startdate)t.startdate=new Date(i);else{o=v[0].startdate;t.startdate=new Date(v[0].startdate);o.getMonth()===0&&o.getDate()==1&&o.getHours()===0&&o.getMinutes()===0?t.startdate.setFullYear(o.getFullYear()-1):o.getDate()<=1&&o.getHours()===0&&o.getMinutes()===0?t.startdate.setMonth(o.getMonth()-1):o.getHours()===0&&o.getMinutes()===0?t.startdate.setDate(o.getDate()-1):o.getMinutes()===0?t.startdate.setHours(o.getHours()-1):t.startdate.setMinutes(o.getMinutes()-1)}t.uniqueid=VMM.Util.unique_ID(7);t.enddate=t.startdate;t.precisiondate=n.precision;t.title=d.headline;t.headline=d.headline;t.text=d.text;t.type="start";t.date=VMM.Date.prettyDate(d.startDate,!1,t.precisiondate);t.asset=d.asset;t.slug=!1;t.needs_slug=!1;t.fulldate=t.startdate.getTime();m.embed&&VMM.fireEvent(global,m.events.headline,t.headline);v.unshift(t)}d.type!="storify"&&v.sort(function(e,t){return e.fulldate-t.fulldate});N()}var r,i,s,o,u,a,f,l,c="2.x",h="#timelinejs",p={},d={},v=[],m={},g=!1,y=!1,b=!1,w=!1;type.of(e)=="string"?e.match("#")?h=e:h="#"+e:h="#timelinejs";m={embed:!1,events:{data_ready:"DATAREADY",messege:"MESSEGE",headline:"HEADLINE",slide_change:"SLIDE_CHANGE",resize:"resize"},id:h,source:"nothing",type:"timeline",touch:!1,orientation:"normal",maptype:"toner",version:"2.x",preload:4,current_slide:0,hash_bookmark:!1,start_at_end:!1,start_at_slide:0,start_zoom_adjust:0,start_page:!1,api_keys:{google:"",flickr:"",twitter:""},interval:10,something:0,width:960,height:540,spacing:15,loaded:{slider:!1,timenav:!1,percentloaded:0},nav:{start_page:!1,interval_width:200,density:4,minor_width:0,minor_left:0,constraint:{left:0,right:0,right_min:0,right_max:0},zoom:{adjust:0},multiplier:{current:6,min:.1,max:50},rows:[1,1,1],width:960,height:200,marker:{width:150,height:50}},feature:{width:960,height:540},slider:{width:720,height:400,content:{width:720,height:400,padding:130,padding_default:130},nav:{width:100,height:200}},ease:"easeInOutExpo",duration:1e3,gmap_key:"",language:VMM.Language};if(t!=null&&t!=""){m.width=t;g=!0}if(n!=null&&n!=""){m.height=n;y=!0}if(window.location.hash){var E=window.location.hash.substring(1);isNaN(E)||(m.current_slide=parseInt(E))}window.onhashchange=function(){var e=window.location.hash.substring(1);m.hash_bookmark?w?_(parseInt(e)):w=!1:_(parseInt(e))};this.init=function(e,t){trace("INIT");H();S(e);x();type.of(t)=="string"&&(m.source=t);VMM.Date.setLanguage(m.language);VMM.master_config.language=m.language;VMM.ExternalAPI.setKeys(m.api_keys);VMM.ExternalAPI.googlemaps.setMapType(m.maptype);VMM.bindEvent(global,T,m.events.data_ready);VMM.bindEvent(global,I,m.events.messege);VMM.fireEvent(global,m.events.messege,m.language.messages.loading_timeline);(VMM.Browser.browser=="Explorer"||VMM.Browser.browser=="MSIE")&&parseInt(VMM.Browser.version,10)<=7&&(b=!0);type.of(m.source)=="string"||type.of(m.source)=="object"?VMM.Timeline.DataObj.getData(m.source):VMM.fireEvent(global,m.events.messege,"No data source provided")};this.iframeLoaded=function(){trace("iframeLoaded")};this.reload=function(e){trace("Load new timeline data"+e);VMM.fireEvent(global,m.events.messege,m.language.messages.loading_timeline);d={};VMM.Timeline.DataObj.getData(e);m.current_slide=0;f.setSlide(0);l.setMarker(0,m.ease,m.duration)}};VMM.Timeline.Config={}}typeof VMM.Timeline!="undefined"&&typeof VMM.Timeline.TimeNav=="undefined"&&(VMM.Timeline.TimeNav=function(e,t,n){function U(){trace("onConfigSet")}function z(e){b.nav.constraint.left=b.width/2;b.nav.constraint.right=b.nav.constraint.right_min-b.width/2;y.updateConstraint(b.nav.constraint);VMM.Lib.css(h,"left",Math.round(b.width/2)+2);VMM.Lib.css(p,"left",Math.round(b.width/2)-8);Y(b.current_slide,b.ease,b.duration,!0,e)}function W(){VMM.fireEvent(x,"UPDATE")}function X(){y.cancelSlide();if(b.nav.multiplier.current>b.nav.multiplier.min){b.nav.multiplier.current<=1?b.nav.multiplier.current=b.nav.multiplier.current-.25:b.nav.multiplier.current>5?b.nav.multiplier.current>16?b.nav.multiplier.current=Math.round(b.nav.multiplier.current-10):b.nav.multiplier.current=Math.round(b.nav.multiplier.current-4):b.nav.multiplier.current=Math.round(b.nav.multiplier.current-1);b.nav.multiplier.current<=0&&(b.nav.multiplier.current=b.nav.multiplier.min);K()}}function V(){y.cancelSlide();if(b.nav.multiplier.current<b.nav.multiplier.max){b.nav.multiplier.current>4?b.nav.multiplier.current>16?b.nav.multiplier.current=Math.round(b.nav.multiplier.current+10):b.nav.multiplier.current=Math.round(b.nav.multiplier.current+4):b.nav.multiplier.current=Math.round(b.nav.multiplier.current+1);b.nav.multiplier.current>=b.nav.multiplier.max&&(b.nav.multiplier.current=b.nav.multiplier.max);K()}}function $(e){y.cancelSlide();Y(0);W()}function J(e){var t=0,n=0;e||(e=window.event);e.originalEvent&&(e=e.originalEvent);e.wheelDelta?t=e.wheelDelta/6:e.detail&&(t=-e.detail*12);if(t){e.preventDefault&&e.preventDefault();e.returnValue=!1}if(typeof e.wheelDeltaX!="undefined"){t=e.wheelDeltaY/6;Math.abs(e.wheelDeltaX)>Math.abs(e.wheelDeltaY)?t=e.wheelDeltaX/6:t=e.wheelDeltaY/6}n=VMM.Lib.position(r).left+t;n>b.nav.constraint.left?n=b.width/2:n<b.nav.constraint.right&&(n=b.nav.constraint.right);VMM.Lib.css(r,"left",n)}function K(){trace("config.nav.multiplier "+b.nav.multiplier.current);ut(!0);at(!0);ft(a,k,!0,!0);ft(f,L,!0);b.nav.constraint.left=b.width/2;b.nav.constraint.right=b.nav.constraint.right_min-b.width/2;y.updateConstraint(b.nav.constraint)}function Q(e){y.cancelSlide();Y(e.data.number);W()}function G(e){VMM.Lib.toggleClass(e.data.elem,"zFront")}function Y(e,t,n,i,s){trace("GO TO MARKER");var o=b.ease,u=b.duration,a=!1,f=!1;O=e;H.left=b.width/2-C[O].pos_left;H.visible.left=Math.abs(H.left)-100;H.visible.right=Math.abs(H.left)+b.width+100;O==0&&(f=!0);O+1==C.length&&(a=!0);t!=null&&t!=""&&(o=t);n!=null&&n!=""&&(u=n);for(var l=0;l<C.length;l++)VMM.Lib.removeClass(C[l].marker,"active");if(b.start_page&&C[0].type=="start"){VMM.Lib.visible(C[0].marker,!1);VMM.Lib.addClass(C[0].marker,"start")}VMM.Lib.addClass(C[O].marker,"active");VMM.Lib.stop(r);VMM.Lib.animate(r,u,o,{left:H.left})}function Z(e,t){VMM.Lib.animate(r,t.time/2,b.ease,{left:t.left})}function et(){var e=0,t=0,n=0,r=[],i=0;for(i=0;i<C.length;i++)if(T[i].type!="start"){var s=ot(F,C[i].relative_pos),e=t;t=s.begin;n=t-e;r.push(n)}return VMM.Util.average(r).mean}function tt(){var e=0,t=0,n="",r=0,i=[],s=!0,o=0;for(o=0;o<T.length;o++)if(T[o].type=="start")trace("DATA DATE IS START");else{n=T[o].startdate;e=t;t=n;r=t-e;i.push(r)}return VMM.Util.average(i)}function nt(){var e=b.nav.multiplier.current,t=0;for(t=0;t<e;t++)et()<75&&b.nav.multiplier.current>1&&(b.nav.multiplier.current=b.nav.multiplier.current-1)}function rt(){var e=it(T[0].startdate),t=it(T[T.length-1].enddate);R.eon.type="eon";R.eon.first=e.eons;R.eon.base=Math.floor(e.eons);R.eon.last=t.eons;R.eon.number=S.eons;R.eon.multiplier=B.eons;R.eon.minor=B.eons;R.era.type="era";R.era.first=e.eras;R.era.base=Math.floor(e.eras);R.era.last=t.eras;R.era.number=S.eras;R.era.multiplier=B.eras;R.era.minor=B.eras;R.epoch.type="epoch";R.epoch.first=e.epochs;R.epoch.base=Math.floor(e.epochs);R.epoch.last=t.epochs;R.epoch.number=S.epochs;R.epoch.multiplier=B.epochs;R.epoch.minor=B.epochs;R.age.type="age";R.age.first=e.ages;R.age.base=Math.floor(e.ages);R.age.last=t.ages;R.age.number=S.ages;R.age.multiplier=B.ages;R.age.minor=B.ages;R.millenium.type="millenium";R.millenium.first=e.milleniums;R.millenium.base=Math.floor(e.milleniums);R.millenium.last=t.milleniums;R.millenium.number=S.milleniums;R.millenium.multiplier=B.millenium;R.millenium.minor=B.millenium;R.century.type="century";R.century.first=e.centuries;R.century.base=Math.floor(e.centuries);R.century.last=t.centuries;R.century.number=S.centuries;R.century.multiplier=B.century;R.century.minor=B.century;R.decade.type="decade";R.decade.first=e.decades;R.decade.base=Math.floor(e.decades);R.decade.last=t.decades;R.decade.number=S.decades;R.decade.multiplier=B.decade;R.decade.minor=B.decade;R.year.type="year";R.year.first=e.years;R.year.base=Math.floor(e.years);R.year.last=t.years;R.year.number=S.years;R.year.multiplier=1;R.year.minor=B.month;R.month.type="month";R.month.first=e.months;R.month.base=Math.floor(e.months);R.month.last=t.months;R.month.number=S.months;R.month.multiplier=1;R.month.minor=Math.round(B.week);R.week.type="week";R.week.first=e.weeks;R.week.base=Math.floor(e.weeks);R.week.last=t.weeks;R.week.number=S.weeks;R.week.multiplier=1;R.week.minor=7;R.day.type="day";R.day.first=e.days;R.day.base=Math.floor(e.days);R.day.last=t.days;R.day.number=S.days;R.day.multiplier=1;R.day.minor=24;R.hour.type="hour";R.hour.first=e.hours;R.hour.base=Math.floor(e.hours);R.hour.last=t.hours;R.hour.number=S.hours;R.hour.multiplier=1;R.hour.minor=60;R.minute.type="minute";R.minute.first=e.minutes;R.minute.base=Math.floor(e.minutes);R.minute.last=t.minutes;R.minute.number=S.minutes;R.minute.multiplier=1;R.minute.minor=60;R.second.type="decade";R.second.first=e.seconds;R.second.base=Math.floor(e.seconds);R.second.last=t.seconds;R.second.number=S.seconds;R.second.multiplier=1;R.second.minor=10}function it(e,t){var n={};n.days=e/j.day;n.weeks=n.days/j.week;n.months=n.days/j.month;n.years=n.months/j.year;n.hours=n.days*j.hour;n.minutes=n.days*j.minute;n.seconds=n.days*j.second;n.decades=n.years/j.decade;n.centuries=n.years/j.century;n.milleniums=n.years/j.millenium;n.ages=n.years/j.age;n.epochs=n.years/j.epoch;n.eras=n.years/j.era;n.eons=n.years/j.eon;return n}function st(e,t,n){var r,i,s=e.type,o={start:"",end:"",type:s};r=it(t);o.start=t.months;s=="eon"?o.start=r.eons:s=="era"?o.start=r.eras:s=="epoch"?o.start=r.epochs:s=="age"?o.start=r.ages:s=="millenium"?o.start=t.milleniums:s=="century"?o.start=r.centuries:s=="decade"?o.start=r.decades:s=="year"?o.start=r.years:s=="month"?o.start=r.months:s=="week"?o.start=r.weeks:s=="day"?o.start=r.days:s=="hour"?o.start=r.hours:s=="minute"&&(o.start=r.minutes);if(type.of(n)=="date"){i=it(n);o.end=n.months;s=="eon"?o.end=i.eons:s=="era"?o.end=i.eras:s=="epoch"?o.end=i.epochs:s=="age"?o.end=i.ages:s=="millenium"?o.end=n.milleniums:s=="century"?o.end=i.centuries:s=="decade"?o.end=i.decades:s=="year"?o.end=i.years:s=="month"?o.end=i.months:s=="week"?o.end=i.weeks:s=="day"?o.end=i.days:s=="hour"?o.end=i.hours:s=="minute"&&(o.end=i.minutes)}else o.end=o.start;return o}function ot(e,t){return{begin:(t.start-F.base)*(b.nav.interval_width/b.nav.multiplier.current),end:(t.end-F.base)*(b.nav.interval_width/b.nav.multiplier.current)}}function ut(e){var t=2,n=0,i=-2,s=0,o=0,u=150,a=6,f=0,l=b.width,c=[],h=6,p={left:H.visible.left-l,right:H.visible.right+l},d=0,v=0;b.nav.minor_width=b.width;VMM.Lib.removeClass(".flag","row1");VMM.Lib.removeClass(".flag","row2");VMM.Lib.removeClass(".flag","row3");for(d=0;d<C.length;d++){var m,g=C[d],y=ot(F,C[d].relative_pos),w=0,E=!1,S={id:d,pos:0,row:0},x=0;y.begin=Math.round(y.begin+i);y.end=Math.round(y.end+i);m=Math.round(y.end-y.begin);g.pos_left=y.begin;if(O==d){H.left=b.width/2-y;H.visible.left=Math.abs(H.left);H.visible.right=Math.abs(H.left)+b.width;p.left=H.visible.left-l;p.right=H.visible.right+l}Math.abs(y.begin)>=p.left&&Math.abs(y.begin)<=p.right&&(E=!0);if(e){VMM.Lib.stop(g.marker);VMM.Lib.animate(g.marker,b.duration/2,b.ease,{left:y.begin})}else{VMM.Lib.stop(g.marker);VMM.Lib.css(g.marker,"left",y.begin)}d==O&&(f=y.begin);if(m>5){VMM.Lib.css(g.lineevent,"height",a);VMM.Lib.css(g.lineevent,"top",u);e?VMM.Lib.animate(g.lineevent,b.duration/2,b.ease,{width:m}):VMM.Lib.css(g.lineevent,"width",m)}if(A.length>0){for(v=0;v<A.length;v++)if(v<b.nav.rows.current.length&&g.tag==A[v]){t=v;if(v==b.nav.rows.current.length-1){trace("ON LAST ROW");VMM.Lib.addClass(g.flag,"flag-small-last")}}w=b.nav.rows.current[t]}else{if(y.begin-n.begin<b.nav.marker.width+b.spacing)if(t<b.nav.rows.current.length-1)t++;else{t=0;s++}else{s=1;t=1}w=b.nav.rows.current[t]}n=y;S.pos=y;S.row=t;c.push(S);c.length>h&&c.remove(0);if(e){VMM.Lib.stop(g.flag);VMM.Lib.animate(g.flag,b.duration,b.ease,{top:w})}else{VMM.Lib.stop(g.flag);VMM.Lib.css(g.flag,"top",w)}b.start_page&&C[d].type=="start"&&VMM.Lib.visible(g.marker,!1);y>b.nav.minor_width&&(b.nav.minor_width=y);y<b.nav.minor_left&&(b.nav.minor_left=y)}if(e){VMM.Lib.stop(r);VMM.Lib.animate(r,b.duration/2,b.ease,{left:b.width/2-f})}}function at(e){var t=0,n=0;for(t=0;t<N.length;t++){var r=N[t],i=ot(F,r.relative_pos),s=0,o=0,u=b.nav.marker.height*b.nav.rows.full.length,a=i.end-i.begin;if(r.tag!=""){u=b.nav.marker.height*b.nav.rows.full.length/b.nav.rows.current.length;for(n=0;n<A.length;n++)n<b.nav.rows.current.length&&r.tag==A[n]&&(o=n);s=b.nav.rows.current[o]}else s=-1;if(e){VMM.Lib.stop(r.content);VMM.Lib.stop(r.text_content);VMM.Lib.animate(r.content,b.duration/2,b.ease,{top:s,left:i.begin,width:a,height:u});VMM.Lib.animate(r.text_content,b.duration/2,b.ease,{left:i.begin})}else{VMM.Lib.stop(r.content);VMM.Lib.stop(r.text_content);VMM.Lib.css(r.content,"left",i.begin);VMM.Lib.css(r.content,"width",a);VMM.Lib.css(r.content,"height",u);VMM.Lib.css(r.content,"top",s);VMM.Lib.css(r.text_content,"left",i.begin)}}}function ft(e,t,n,r){var s=0,o=0,u=b.width,a={left:H.visible.left-u,right:H.visible.right+u};not_too_many=!0,i=0;b.nav.minor_left=0;if(t.length>100){not_too_many=!1;trace("TOO MANY "+t.length)}for(i=0;i<t.length;i++){var f=t[i].element,l=t[i].date,c=t[i].visible,h=ot(F,t[i].relative_pos),p=h.begin,v=t[i].animation,m=!0,g=!1,y=50;v.pos=p;v.animate=!1;Math.abs(p)>=a.left&&Math.abs(p)<=a.right&&(g=!0);b.nav.multiplier.current>16&&r?m=!1:p-s<65&&(p-s<35?i%4==0?p==0&&(m=!1):m=!1:VMM.Util.isEven(i)||(m=!1));if(m){if(t[i].is_detached){VMM.Lib.append(e,f);t[i].is_detached=!1}}else{t[i].is_detached=!0;VMM.Lib.detach(f)}if(c)if(!m){v.opacity="0";n&&not_too_many&&(v.animate=!0);t[i].interval_visible=!1}else{v.opacity="100";n&&g&&(v.animate=!0)}else{v.opacity="100";if(m){n&&not_too_many?v.animate=!0:n&&g&&(v.animate=!0);t[i].interval_visible=!0}else n&&not_too_many&&(v.animate=!0)}s=p;p>b.nav.minor_width&&(b.nav.minor_width=p);p<b.nav.minor_left&&(b.nav.minor_left=p);if(v.animate)VMM.Lib.animate(f,b.duration/2,b.ease,{opacity:v.opacity,left:v.pos});else{VMM.Lib.css(f,"opacity",v.opacity);VMM.Lib.css(f,"left",p)}}b.nav.constraint.right_min=-b.nav.minor_width+b.width;b.nav.constraint.right=b.nav.constraint.right_min+b.width/2;VMM.Lib.css(d,"left",b.nav.minor_left-b.width/2);VMM.Lib.width(d,b.nav.minor_width+b.width+Math.abs(b.nav.minor_left))}function lt(e,t,n){var r=0,i=!0,s=0,o=0,u,a,f,l=Math.ceil(e.number)+2,c={flag:!1,offset:0},h=0;VMM.attachElement(n,"");e.date=new Date(T[0].startdate.getFullYear(),0,1,0,0,0);u=e.date.getTimezoneOffset();for(h=0;h<l;h++){trace(e.type);var p=!1,v={element:VMM.appendAndGetElement(n,"<div>",e.classname),date:new Date(T[0].startdate.getFullYear(),0,1,0,0,0),visible:!1,date_string:"",type:e.interval_type,relative_pos:0,is_detached:!1,animation:{animate:!1,pos:"",opacity:"100"}};if(e.type=="eon"){i&&(a=Math.floor(T[0].startdate.getFullYear()/5e8)*5e8);v.date.setFullYear(a+r*5e8);p=!0}else if(e.type=="era"){i&&(a=Math.floor(T[0].startdate.getFullYear()/1e8)*1e8);v.date.setFullYear(a+r*1e8);p=!0}else if(e.type=="epoch"){i&&(a=Math.floor(T[0].startdate.getFullYear()/1e7)*1e7);v.date.setFullYear(a+r*1e7);p=!0}else if(e.type=="age"){i&&(a=Math.floor(T[0].startdate.getFullYear()/1e6)*1e6);v.date.setFullYear(a+r*1e6);p=!0}else if(e.type=="millenium"){i&&(a=Math.floor(T[0].startdate.getFullYear()/1e3)*1e3);v.date.setFullYear(a+r*1e3);p=!0}else if(e.type=="century"){i&&(a=Math.floor(T[0].startdate.getFullYear()/100)*100);v.date.setFullYear(a+r*100);p=!0}else if(e.type=="decade"){i&&(a=Math.floor(T[0].startdate.getFullYear()/10)*10);v.date.setFullYear(a+r*10);p=!0}else if(e.type=="year"){i&&(a=T[0].startdate.getFullYear());v.date.setFullYear(a+r);p=!0}else if(e.type=="month"){i&&(a=T[0].startdate.getMonth());v.date.setMonth(a+r)}else if(e.type=="week"){i&&(a=T[0].startdate.getMonth());v.date.setMonth(T[0].startdate.getMonth());v.date.setDate(a+r*7)}else if(e.type=="day"){i&&(a=T[0].startdate.getDate());v.date.setMonth(T[0].startdate.getMonth());v.date.setDate(a+r)}else if(e.type=="hour"){i&&(a=T[0].startdate.getHours());v.date.setMonth(T[0].startdate.getMonth());v.date.setDate(T[0].startdate.getDate());v.date.setHours(a+r)}else if(e.type=="minute"){i&&(a=T[0].startdate.getMinutes());v.date.setMonth(T[0].startdate.getMonth());v.date.setDate(T[0].startdate.getDate());v.date.setHours(T[0].startdate.getHours());v.date.setMinutes(a+r)}else if(e.type=="second"){i&&(a=T[0].startdate.getSeconds());v.date.setMonth(T[0].startdate.getMonth());v.date.setDate(T[0].startdate.getDate());v.date.setHours(T[0].startdate.getHours());v.date.setMinutes(T[0].startdate.getMinutes());v.date.setSeconds(a+r)}else if(e.type=="millisecond"){i&&(a=T[0].startdate.getMilliseconds());v.date.setMonth(T[0].startdate.getMonth());v.date.setDate(T[0].startdate.getDate());v.date.setHours(T[0].startdate.getHours());v.date.setMinutes(T[0].startdate.getMinutes());v.date.setSeconds(T[0].startdate.getSeconds());v.date.setMilliseconds(a+r)}if(VMM.Browser.browser=="Firefox")if(v.date.getFullYear()=="1970"&&v.date.getTimezoneOffset()!=u){trace("FIREFOX 1970 TIMEZONE OFFSET "+v.date.getTimezoneOffset()+" SHOULD BE "+u);trace(e.type+" "+e.date);c.offset=v.date.getTimezoneOffset()/60;c.flag=!0;v.date.setHours(v.date.getHours()+c.offset)}else if(c.flag){c.flag=!1;v.date.setHours(v.date.getHours()+c.offset);p&&(c.flag=!0)}p?v.date.getFullYear()<0?v.date_string=Math.abs(v.date.getFullYear()).toString()+" a.C.":v.date_string=v.date.getFullYear():v.date_string=VMM.Date.prettyDate(v.date,!0);r+=1;i=!1;v.relative_pos=st(F,v.date);s=v.relative_pos.begin;v.relative_pos.begin>o&&(o=v.relative_pos.begin);VMM.appendElement(v.element,v.date_string);VMM.Lib.css(v.element,"text-indent",-(VMM.Lib.width(v.element)/2));VMM.Lib.css(v.element,"opacity","0");t.push(v)}VMM.Lib.width(d,o);ft(n,t)}function ct(){var e=0,t=0;VMM.attachElement(x,"");r=VMM.appendAndGetElement(x,"<div>","timenav");s=VMM.appendAndGetElement(r,"<div>","content");o=VMM.appendAndGetElement(r,"<div>","time");u=VMM.appendAndGetElement(o,"<div>","time-interval-minor");d=VMM.appendAndGetElement(u,"<div>","minor");f=VMM.appendAndGetElement(o,"<div>","time-interval-major");a=VMM.appendAndGetElement(o,"<div>","time-interval");l=VMM.appendAndGetElement(x,"<div>","timenav-background");h=VMM.appendAndGetElement(l,"<div>","timenav-line");p=VMM.appendAndGetElement(l,"<div>","timenav-indicator");c=VMM.appendAndGetElement(l,"<div>","timenav-interval-background","<div class='top-highlight'></div>");v=VMM.appendAndGetElement(x,"<div>","vco-toolbar");ht();pt();dt();nt();ut(!1);at();ft(a,k,!1,!0);ft(f,L);if(b.start_page){$backhome=VMM.appendAndGetElement(v,"<div>","back-home","<div class='icon'></div>");VMM.bindEvent(".back-home",$,"click");VMM.Lib.attribute($backhome,"title",VMM.master_config.language.messages.return_to_title);VMM.Lib.attribute($backhome,"rel","tooltip")}y=new VMM.DragSlider;y.createPanel(x,r,b.nav.constraint,b.touch);if(b.touch&&b.start_page){VMM.Lib.addClass(v,"touch");VMM.Lib.css(v,"top",55);VMM.Lib.css(v,"left",10)}else{b.start_page&&VMM.Lib.css(v,"top",27);m=VMM.appendAndGetElement(v,"<div>","zoom-in","<div class='icon'></div>");g=VMM.appendAndGetElement(v,"<div>","zoom-out","<div class='icon'></div>");VMM.bindEvent(m,X,"click");VMM.bindEvent(g,V,"click");VMM.Lib.attribute(m,"title",VMM.master_config.language.messages.expand_timeline);VMM.Lib.attribute(m,"rel","tooltip");VMM.Lib.attribute(g,"title",VMM.master_config.language.messages.contract_timeline);VMM.Lib.attribute(g,"rel","tooltip");v.tooltip({selector:"div[rel=tooltip]",placement:"right"});VMM.bindEvent(x,J,"DOMMouseScroll");VMM.bindEvent(x,J,"mousewheel")}if(b.nav.zoom.adjust!=0)if(b.nav.zoom.adjust<0)for(e=0;e<Math.abs(b.nav.zoom.adjust);e++)V();else for(t=0;t<b.nav.zoom.adjust;t++)X();M=!0;z(!0);VMM.fireEvent(x,"LOADED")}function ht(){var e=0,t=0;S=it(T[T.length-1].enddate-T[0].startdate,!0);trace(S);rt();if(S.centuries>T.length/b.nav.density){F=R.century;I=R.millenium;q=R.decade}else if(S.decades>T.length/b.nav.density){F=R.decade;I=R.century;q=R.year}else if(S.years>T.length/b.nav.density){F=R.year;I=R.decade;q=R.month}else if(S.months>T.length/b.nav.density){F=R.month;I=R.year;q=R.day}else if(S.days>T.length/b.nav.density){F=R.day;I=R.month;q=R.hour}else if(S.hours>T.length/b.nav.density){F=R.hour;I=R.day;q=R.minute}else if(S.minutes>T.length/b.nav.density){F=R.minute;I=R.hour;q=R.second}else if(S.seconds>T.length/b.nav.density){F=R.second;I=R.minute;q=R.second}else{trace("NO IDEA WHAT THE TYPE SHOULD BE");F=R.day;I=R.month;q=R.hour}trace("INTERVAL TYPE: "+F.type);trace("INTERVAL MAJOR TYPE: "+I.type);lt(F,k,a);lt(I,L,f);for(e=0;e<k.length;e++)for(t=0;t<L.length;t++)k[e].date_string==L[t].date_string&&VMM.attachElement(k[e].element,"")}function pt(){var e=2,t=0,n=0,r=0,i=0,o=0;C=[];N=[];for(r=0;r<T.length;r++){var u,a,f,c,h,p,d,v="",m=!1;u=VMM.appendAndGetElement(s,"<div>","marker");a=VMM.appendAndGetElement(u,"<div>","flag");f=VMM.appendAndGetElement(a,"<div>","flag-content");c=VMM.appendAndGetElement(u,"<div>","dot");h=VMM.appendAndGetElement(u,"<div>","line");p=VMM.appendAndGetElement(h,"<div>","event-line");_marker_relative_pos=st(F,T[r].startdate,T[r].enddate);_marker_thumb="";T[r].asset!=null&&T[r].asset!=""?VMM.appendElement(f,VMM.MediaElement.thumbnail(T[r].asset,24,24,T[r].uniqueid)):VMM.appendElement(f,"<div style='margin-right:7px;height:50px;width:2px;float:left;'></div>");if(T[r].title==""||T[r].title==" "){trace("TITLE NOTHING");if(typeof T[r].slug!="undefined"&&T[r].slug!=""){trace("SLUG");v=VMM.Util.untagify(T[r].slug);m=!0}else{var g=VMM.MediaType(T[r].asset.media);if(g.type=="quote"||g.type=="unknown"){v=VMM.Util.untagify(g.id);m=!0}else m=!1}}else if(T[r].title!=""||T[r].title!=" "){trace(T[r].title);v=VMM.Util.untagify(T[r].title);m=!0}else trace("TITLE SLUG NOT FOUND "+T[r].slug);if(m)VMM.appendElement(f,"<h3>"+v+"</h3>");else{VMM.appendElement(f,"<h3>"+v+"</h3>");VMM.appendElement(f,"<h3 id='marker_content_"+T[r].uniqueid+"'>"+v+"</h3>")}VMM.Lib.attr(u,"id",("marker_"+T[r].uniqueid).toString());VMM.bindEvent(a,Q,"",{number:r});VMM.bindEvent(a,G,"mouseenter mouseleave",{number:r,elem:a});d={marker:u,flag:a,lineevent:p,type:"marker",full:!0,relative_pos:_marker_relative_pos,tag:T[r].tag,pos_left:0};if(T[r].type=="start"){trace("BUILD MARKER HAS START PAGE");b.start_page=!0;d.type="start"}T[r].type=="storify"&&(d.type="storify");T[r].tag&&A.push(T[r].tag);C.push(d)}A=VMM.Util.deDupeArray(A);A.length>3?b.nav.rows.current=b.nav.rows.half:b.nav.rows.current=b.nav.rows.full;for(i=0;i<A.length;i++)if(i<b.nav.rows.current.length){var y=VMM.appendAndGetElement(l,"<div>","timenav-tag");VMM.Lib.addClass(y,"timenav-tag-row-"+(i+1));A.length>3?VMM.Lib.addClass(y,"timenav-tag-size-half"):VMM.Lib.addClass(y,"timenav-tag-size-full");VMM.appendElement(y,"<div><h3>"+A[i]+"</h3></div>")}if(A.length>3)for(o=0;o<C.length;o++){VMM.Lib.addClass(C[o].flag,"flag-small");C[o].full=!1}}function dt(){var e=6,t=0,n=0;for(n=0;n<_.length;n++){var r={content:VMM.appendAndGetElement(s,"<div>","era"),text_content:VMM.appendAndGetElement(a,"<div>","era"),startdate:VMM.Date.parse(_[n].startDate),enddate:VMM.Date.parse(_[n].endDate),title:_[n].headline,uniqueid:VMM.Util.unique_ID(6),tag:"",relative_pos:""},i=VMM.Date.prettyDate(r.startdate),o=VMM.Date.prettyDate(r.enddate),u="<div>&nbsp;</div>";typeof _[n].tag!="undefined"&&(r.tag=_[n].tag);r.relative_pos=st(F,r.startdate,r.enddate);VMM.Lib.attr(r.content,"id",r.uniqueid);VMM.Lib.attr(r.text_content,"id",r.uniqueid+"_text");VMM.Lib.addClass(r.content,"era"+(t+1));VMM.Lib.addClass(r.text_content,"era"+(t+1));t<e?t++:t=0;VMM.appendElement(r.content,u);VMM.appendElement(r.text_content,VMM.Util.unlinkify(r.title));N.push(r)}}trace("VMM.Timeline.TimeNav");var r,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b=VMM.Timeline.Config,w,E={},S={},x=e,T=[],N=[],C=[],k=[],L=[],A=[],O=0,M=!1,_,D,P={interval_position:""},H={left:"",visible:{left:"",right:""}},B={day:24,month:12,year:10,hour:60,minute:60,second:1e3,decade:10,century:100,millenium:1e3,age:1e6,epoch:1e7,era:1e8,eon:5e8,week:4.34812141,days_in_month:30.4368499,days_in_week:7,weeks_in_month:4.34812141,weeks_in_year:52.177457,days_in_year:365.242199,hours_in_day:24},j={day:864e5,week:7,month:30.4166666667,year:12,hour:24,minute:1440,second:86400,decade:10,century:100,millenium:1e3,age:1e6,epoch:1e7,era:1e8,eon:5e8},F={type:"year",number:10,first:1970,last:2011,multiplier:100,classname:"_idd",interval_type:"interval"},I={type:"year",number:10,first:1970,last:2011,multiplier:100,classname:"major",interval_type:"interval major"},q={type:"year",number:10,first:1970,last:2011,multiplier:100,classname:"_dd_minor",interval_type:"interval minor"},R={day:{},month:{},year:{},hour:{},minute:{},second:{},decade:{},century:{},millenium:{},week:{},age:{},epoch:{},era:{},eon:{}};w=b.nav.marker.height/2;b.nav.rows={full:[1,w*2,w*4],half:[1,w,w*2,w*3,w*4,w*5],current:[]};t!=null&&t!=""&&(b.nav.width=t);n!=null&&n!=""&&(b.nav.height=n);this.init=function(e,t){trace("VMM.Timeline.TimeNav init");typeof e!="undefined"?this.setData(e,t):trace("WAITING ON DATA")};this.setData=function(e,t){if(typeof e!="undefined"){T={};T=e;_=t;ct()}else trace("NO DATA")};this.setSize=function(e,t){e!=null&&(b.width=e);t!=null&&(b.height=t);M&&z()};this.setMarker=function(e,t,n,r){Y(e,t,n)};this.getCurrentNumber=function(){return O}});typeof VMM.Timeline!="undefined"&&typeof VMM.Timeline.DataObj=="undefined"&&(VMM.Timeline.DataObj={data_obj:{},model_array:[],getData:function(e){VMM.Timeline.DataObj.data_obj={};VMM.fireEvent(global,VMM.Timeline.Config.events.messege,VMM.Timeline.Config.language.messages.loading_timeline);if(type.of(e)=="object"){trace("DATA SOURCE: JSON OBJECT");VMM.Timeline.DataObj.parseJSON(e)}else if(type.of(e)=="string")if(e.match("%23")){trace("DATA SOURCE: TWITTER SEARCH");VMM.Timeline.DataObj.model.tweets.getData("%23medill")}else if(e.match("spreadsheet")){trace("DATA SOURCE: GOOGLE SPREADSHEET");VMM.Timeline.DataObj.model.googlespreadsheet.getData(e)}else if(e.match("storify.com")){trace("DATA SOURCE: STORIFY");VMM.Timeline.DataObj.model.storify.getData(e)}else if(e.match(".jsonp")){trace("DATA SOURCE: JSONP");LoadLib.js(e,VMM.Timeline.DataObj.onJSONPLoaded)}else{trace("DATA SOURCE: JSON");var t="";e.indexOf("?")>-1?t=e+"&callback=onJSONP_Data":t=e+"?callback=onJSONP_Data";VMM.getJSON(t,VMM.Timeline.DataObj.parseJSON)}else if(type.of(e)=="html"){trace("DATA SOURCE: HTML");VMM.Timeline.DataObj.parseHTML(e)}else trace("DATA SOURCE: UNKNOWN")},onJSONPLoaded:function(){trace("JSONP IS LOADED");VMM.fireEvent(global,VMM.Timeline.Config.events.data_ready,storyjs_jsonp_data)},parseHTML:function(e){trace("parseHTML");trace("WARNING: THIS IS STILL ALPHA AND WILL NOT WORK WITH ID's other than #timeline");var t=VMM.Timeline.DataObj.data_template_obj;if(VMM.Lib.find("#timeline section","time")[0]){t.timeline.startDate=VMM.Lib.html(VMM.Lib.find("#timeline section","time")[0]);t.timeline.headline=VMM.Lib.html(VMM.Lib.find("#timeline section","h2"));t.timeline.text=VMM.Lib.html(VMM.Lib.find("#timeline section","article"));var n=!1;if(VMM.Lib.find("#timeline section","figure img").length!=0){n=!0;t.timeline.asset.media=VMM.Lib.attr(VMM.Lib.find("#timeline section","figure img"),"src")}else if(VMM.Lib.find("#timeline section","figure a").length!=0){n=!0;t.timeline.asset.media=VMM.Lib.attr(VMM.Lib.find("#timeline section","figure a"),"href")}if(n){VMM.Lib.find("#timeline section","cite").length!=0&&(t.timeline.asset.credit=VMM.Lib.html(VMM.Lib.find("#timeline section","cite")));VMM.Lib.find(this,"figcaption").length!=0&&(t.timeline.asset.caption=VMM.Lib.html(VMM.Lib.find("#timeline section","figcaption")))}}VMM.Lib.each("#timeline li",function(e,n){var r=!1,i= +{type:"default",startDate:"",headline:"",text:"",asset:{media:"",credit:"",caption:""},tags:"Optional"};if(VMM.Lib.find(this,"time")!=0){r=!0;i.startDate=VMM.Lib.html(VMM.Lib.find(this,"time")[0]);VMM.Lib.find(this,"time")[1]&&(i.endDate=VMM.Lib.html(VMM.Lib.find(this,"time")[1]));i.headline=VMM.Lib.html(VMM.Lib.find(this,"h3"));i.text=VMM.Lib.html(VMM.Lib.find(this,"article"));var s=!1;if(VMM.Lib.find(this,"figure img").length!=0){s=!0;i.asset.media=VMM.Lib.attr(VMM.Lib.find(this,"figure img"),"src")}else if(VMM.Lib.find(this,"figure a").length!=0){s=!0;i.asset.media=VMM.Lib.attr(VMM.Lib.find(this,"figure a"),"href")}if(s){VMM.Lib.find(this,"cite").length!=0&&(i.asset.credit=VMM.Lib.html(VMM.Lib.find(this,"cite")));VMM.Lib.find(this,"figcaption").length!=0&&(i.asset.caption=VMM.Lib.html(VMM.Lib.find(this,"figcaption")))}trace(i);t.timeline.date.push(i)}});VMM.fireEvent(global,VMM.Timeline.Config.events.data_ready,t)},parseJSON:function(e){trace("parseJSON");if(e.timeline.type=="default"){trace("DATA SOURCE: JSON STANDARD TIMELINE");VMM.fireEvent(global,VMM.Timeline.Config.events.data_ready,e)}else if(e.timeline.type=="twitter"){trace("DATA SOURCE: JSON TWEETS");VMM.Timeline.DataObj.model_Tweets.buildData(e)}else{trace("DATA SOURCE: UNKNOWN JSON");trace(type.of(e.timeline))}},model:{googlespreadsheet:{getData:function(e){function u(){t=VMM.getJSON(i,function(e){clearTimeout(s);VMM.Timeline.DataObj.model.googlespreadsheet.buildData(e)}).error(function(e,t,n){trace("Google Docs ERROR");trace("Google Docs ERROR: "+t+" "+e.responseText)}).success(function(e){clearTimeout(s)})}var t,n,r,i,s,o=0;n=VMM.Util.getUrlVars(e).key;r=VMM.Util.getUrlVars(e).worksheet;typeof r=="undefined"&&(r="od6");i="https://spreadsheets.google.com/feeds/list/"+n+"/"+r+"/public/values?alt=json";s=setTimeout(function(){trace("Google Docs timeout "+i);trace(i);if(o<3){VMM.fireEvent(global,VMM.Timeline.Config.events.messege,"Still waiting on Google Docs, trying again "+o);o++;t.abort();u()}else VMM.fireEvent(global,VMM.Timeline.Config.events.messege,"Google Docs is not responding")},16e3);u()},buildData:function(e){function r(e){return typeof e!="undefined"?e.$t:""}var t=VMM.Timeline.DataObj.data_template_obj,n=!1;VMM.fireEvent(global,VMM.Timeline.Config.events.messege,"Parsing Google Doc Data");if(typeof e.feed.entry!="undefined"){n=!0;for(var i=0;i<e.feed.entry.length;i++){var s=e.feed.entry[i],o="";typeof s.gsx$type!="undefined"?o=s.gsx$type.$t:typeof s.gsx$titleslide!="undefined"&&(o=s.gsx$titleslide.$t);if(o.match("start")||o.match("title")){t.timeline.startDate=r(s.gsx$startdate);t.timeline.headline=r(s.gsx$headline);t.timeline.asset.media=r(s.gsx$media);t.timeline.asset.caption=r(s.gsx$mediacaption);t.timeline.asset.credit=r(s.gsx$mediacredit);t.timeline.text=r(s.gsx$text);t.timeline.type="google spreadsheet"}else if(o.match("era")){var u={startDate:r(s.gsx$startdate),endDate:r(s.gsx$enddate),headline:r(s.gsx$headline),text:r(s.gsx$text),tag:r(s.gsx$tag)};t.timeline.era.push(u)}else{var a={type:"google spreadsheet",startDate:r(s.gsx$startdate),endDate:r(s.gsx$enddate),headline:r(s.gsx$headline),text:r(s.gsx$text),tag:r(s.gsx$tag),asset:{media:r(s.gsx$media),credit:r(s.gsx$mediacredit),caption:r(s.gsx$mediacaption),thumbnail:r(s.gsx$mediathumbnail)}};t.timeline.date.push(a)}}}if(n){VMM.fireEvent(global,VMM.Timeline.Config.events.messege,"Finished Parsing Data");VMM.fireEvent(global,VMM.Timeline.Config.events.data_ready,t)}else{VMM.fireEvent(global,VMM.Timeline.Config.events.messege,VMM.Language.messages.loading+" Google Doc Data (cells)");trace("There may be too many entries. Still trying to load data. Now trying to load cells to avoid Googles limitation on cells");VMM.Timeline.DataObj.model.googlespreadsheet.getDataCells(e.feed.link[0].href)}},getDataCells:function(e){function o(){t=VMM.getJSON(r,function(e){clearTimeout(i);VMM.Timeline.DataObj.model.googlespreadsheet.buildDataCells(e)}).error(function(e,t,n){trace("Google Docs ERROR");trace("Google Docs ERROR: "+t+" "+e.responseText)}).success(function(e){clearTimeout(i)})}var t,n,r,i,s=0;n=VMM.Util.getUrlVars(e).key;r="https://spreadsheets.google.com/feeds/cells/"+n+"/od6/public/values?alt=json";i=setTimeout(function(){trace("Google Docs timeout "+r);trace(r);if(s<3){VMM.fireEvent(global,VMM.Timeline.Config.events.messege,"Still waiting on Google Docs, trying again "+s);s++;t.abort();o()}else VMM.fireEvent(global,VMM.Timeline.Config.events.messege,"Google Docs is not responding")},16e3);o()},buildDataCells:function(e){function a(e){return typeof e!="undefined"?e.$t:""}var t=VMM.Timeline.DataObj.data_template_obj,n=!1,r=["timeline"],i=[],s=0,o=0,u=0;VMM.fireEvent(global,VMM.Timeline.Config.events.messege,VMM.Language.messages.loading_timeline+" Parsing Google Doc Data (cells)");if(typeof e.feed.entry!="undefined"){n=!0;for(o=0;o<e.feed.entry.length;o++){var f=e.feed.entry[o];parseInt(f.gs$cell.row)>s&&(s=parseInt(f.gs$cell.row))}for(var o=0;o<s+1;o++){var l={type:"",startDate:"",endDate:"",headline:"",text:"",tag:"",asset:{media:"",credit:"",caption:"",thumbnail:""}};i.push(l)}for(o=0;o<e.feed.entry.length;o++){var f=e.feed.entry[o],c="",h="",p={content:a(f.gs$cell),col:f.gs$cell.col,row:f.gs$cell.row,name:""};if(p.row==1){p.content=="Start Date"?h="startDate":p.content=="End Date"?h="endDate":p.content=="Headline"?h="headline":p.content=="Text"?h="text":p.content=="Media"?h="media":p.content=="Media Credit"?h="credit":p.content=="Media Caption"?h="caption":p.content=="Media Thumbnail"?h="thumbnail":p.content=="Type"?h="type":p.content=="Tag"&&(h="tag");r.push(h)}else{p.name=r[p.col];i[p.row][p.name]=p.content}}for(o=0;o<i.length;o++){var l=i[o];if(l.type.match("start")||l.type.match("title")){t.timeline.startDate=l.startDate;t.timeline.headline=l.headline;t.timeline.asset.media=l.media;t.timeline.asset.caption=l.caption;t.timeline.asset.credit=l.credit;t.timeline.text=l.text;t.timeline.type="google spreadsheet"}else if(l.type.match("era")){var d={startDate:l.startDate,endDate:l.endDate,headline:l.headline,text:l.text,tag:l.tag};t.timeline.era.push(d)}else{var l={type:"google spreadsheet",startDate:l.startDate,endDate:l.endDate,headline:l.headline,text:l.text,tag:l.tag,asset:{media:l.media,credit:l.credit,caption:l.caption,thumbnail:l.thumbnail}};t.timeline.date.push(l)}}}if(n){VMM.fireEvent(global,VMM.Timeline.Config.events.messege,"Finished Parsing Data");VMM.fireEvent(global,VMM.Timeline.Config.events.data_ready,t)}else VMM.fireEvent(global,VMM.Timeline.Config.events.messege,"Unable to load Google Doc data source")}},storify:{getData:function(e){var t,n,r;VMM.fireEvent(global,VMM.Timeline.Config.events.messege,"Loading Storify...");t=e.split("storify.com/")[1];n="http://api.storify.com/v1/stories/"+t+"?per_page=300&callback=?";r=setTimeout(function(){trace("STORIFY timeout");VMM.fireEvent(global,VMM.Timeline.Config.events.messege,"Storify is not responding")},6e3);VMM.getJSON(n,VMM.Timeline.DataObj.model.storify.buildData).error(function(e,t,n){trace("STORIFY error");trace("STORIFY ERROR: "+t+" "+e.responseText)}).success(function(e){clearTimeout(r)})},buildData:function(e){VMM.fireEvent(global,VMM.Timeline.Config.events.messege,"Parsing Data");var t=VMM.Timeline.DataObj.data_template_obj;t.timeline.startDate=new Date(e.content.date.created);t.timeline.headline=e.content.title;trace(e);var n="",r=e.content.author.username,i="";if(typeof e.content.author.name!="undefined"){r=e.content.author.name;i=e.content.author.username+"&nbsp;"}typeof e.content.description!="undefined"&&e.content.description!=null&&(n+=e.content.description);n+="<div class='storify'>";n+="<div class='vcard author'><a class='screen-name url' href='"+e.content.author.permalink+"' target='_blank'>";n+="<span class='avatar'><img src='"+e.content.author.avatar+"' style='max-width: 32px; max-height: 32px;'></span>";n+="<span class='fn'>"+r+"</span>";n+="<span class='nickname'>"+i+"<span class='thumbnail-inline'></span></span>";n+="</a>";n+="</div>";n+="</div>";t.timeline.text=n;t.timeline.asset.media=e.content.thumbnail;t.timeline.type="storify";for(var s=0;s<e.content.elements.length;s++){var o=e.content.elements[s],u=!1,a=new Date(o.posted_at);trace(o.type);var f={type:"storify",startDate:o.posted_at,endDate:o.posted_at,headline:" ",slug:"",text:"",asset:{media:"",credit:"",caption:""}};if(o.type=="image"){if(typeof o.source.name!="undefined")if(o.source.name=="flickr"){f.asset.media="http://flickr.com/photos/"+o.meta.pathalias+"/"+o.meta.id+"/";f.asset.credit="<a href='"+f.asset.media+"'>"+o.attribution.name+"</a>";f.asset.credit+=" on <a href='"+o.source.href+"'>"+o.source.name+"</a>"}else if(o.source.name=="instagram"){f.asset.media=o.permalink;f.asset.credit="<a href='"+o.permalink+"'>"+o.attribution.name+"</a>";f.asset.credit+=" on <a href='"+o.source.href+"'>"+o.source.name+"</a>"}else{f.asset.credit="<a href='"+o.permalink+"'>"+o.attribution.name+"</a>";typeof o.source.href!="undefined"&&(f.asset.credit+=" on <a href='"+o.source.href+"'>"+o.source.name+"</a>");f.asset.media=o.data.image.src}else{f.asset.credit="<a href='"+o.permalink+"'>"+o.attribution.name+"</a>";f.asset.media=o.data.image.src}f.slug=o.attribution.name;if(typeof o.data.image.caption!="undefined"&&o.data.image.caption!="undefined"){f.asset.caption=o.data.image.caption;f.slug=o.data.image.caption}}else if(o.type=="quote"){if(o.permalink.match("twitter")){f.asset.media=o.permalink;f.slug=VMM.Util.untagify(o.data.quote.text)}else if(o.permalink.match("storify")){u=!0;f.asset.media="<blockquote>"+o.data.quote.text.replace(/<\s*\/?\s*b\s*.*?>/g,"")+"</blockquote>"}}else if(o.type=="link"){f.headline=o.data.link.title;f.text=o.data.link.description;o.data.link.thumbnail!="undefined"&&o.data.link.thumbnail!=""?f.asset.media=o.data.link.thumbnail:f.asset.media=o.permalink;f.asset.caption="<a href='"+o.permalink+"' target='_blank'>"+o.data.link.title+"</a>";f.slug=o.data.link.title}else if(o.type=="text"){if(o.permalink.match("storify")){u=!0;var l=e.content.author.username,c="";if(typeof o.attribution.name!="undefined"){r=o.attribution.name;i=o.attribution.username+"&nbsp;"}var h="<div class='storify'>";h+="<blockquote><p>"+o.data.text.replace(/<\s*\/?\s*b\s*.*?>/g,"")+"</p></blockquote>";h+="<div class='vcard author'><a class='screen-name url' href='"+o.attribution.href+"' target='_blank'>";h+="<span class='avatar'><img src='"+o.attribution.thumbnail+"' style='max-width: 32px; max-height: 32px;'></span>";h+="<span class='fn'>"+r+"</span>";h+="<span class='nickname'>"+i+"<span class='thumbnail-inline'></span></span>";h+="</a></div></div>";f.text=h;if(s+1>=e.content.elements.length)f.startDate=e.content.elements[s-1].posted_at;else if(e.content.elements[s+1].type=="text"&&e.content.elements[s+1].permalink.match("storify"))if(s+2>=e.content.elements.length)f.startDate=e.content.elements[s-1].posted_at;else if(e.content.elements[s+2].type=="text"&&e.content.elements[s+2].permalink.match("storify"))if(s+3>=e.content.elements.length)f.startDate=e.content.elements[s-1].posted_at;else if(e.content.elements[s+3].type=="text"&&e.content.elements[s+3].permalink.match("storify"))f.startDate=e.content.elements[s-1].posted_at;else{trace("LEVEL 3");f.startDate=e.content.elements[s+3].posted_at}else{trace("LEVEL 2");f.startDate=e.content.elements[s+2].posted_at}else{trace("LEVEL 1");f.startDate=e.content.elements[s+1].posted_at}f.endDate=f.startDate}}else if(o.type=="video"){f.headline=o.data.video.title;f.asset.caption=o.data.video.description;f.asset.caption=o.source.username;f.asset.media=o.data.video.src}else{trace("NO MATCH ");trace(o)}u&&(f.slug=VMM.Util.untagify(o.data.text));t.timeline.date.push(f)}VMM.fireEvent(global,VMM.Timeline.Config.events.data_ready,t)}},tweets:{type:"twitter",buildData:function(e){VMM.bindEvent(global,VMM.Timeline.DataObj.model.tweets.onTwitterDataReady,"TWEETSLOADED");VMM.ExternalAPI.twitter.getTweets(e.timeline.tweets)},getData:function(e){VMM.bindEvent(global,VMM.Timeline.DataObj.model.tweets.onTwitterDataReady,"TWEETSLOADED");VMM.ExternalAPI.twitter.getTweetSearch(e)},onTwitterDataReady:function(e,t){var n=VMM.Timeline.DataObj.data_template_obj;for(var r=0;r<t.tweetdata.length;r++){var i={type:"tweets",startDate:"",headline:"",text:"",asset:{media:"",credit:"",caption:""},tags:"Optional"};i.startDate=t.tweetdata[r].raw.created_at;type.of(t.tweetdata[r].raw.from_user_name)?i.headline=t.tweetdata[r].raw.from_user_name+" (<a href='https://twitter.com/"+t.tweetdata[r].raw.from_user+"'>"+"@"+t.tweetdata[r].raw.from_user+"</a>)":i.headline=t.tweetdata[r].raw.user.name+" (<a href='https://twitter.com/"+t.tweetdata[r].raw.user.screen_name+"'>"+"@"+t.tweetdata[r].raw.user.screen_name+"</a>)";i.asset.media=t.tweetdata[r].content;n.timeline.date.push(i)}VMM.fireEvent(global,VMM.Timeline.Config.events.data_ready,n)}}},data_template_obj:{timeline:{headline:"",description:"",asset:{media:"",credit:"",caption:""},date:[],era:[]}},date_obj:{startDate:"2012,2,2,11,30",headline:"",text:"",asset:{media:"http://youtu.be/vjVfu8-Wp6s",credit:"",caption:""},tags:"Optional"}});VMM.debug=!1; \ No newline at end of file diff --git a/src/static/timelinejs/js/timeline.js b/src/static/timelinejs/js/timeline.js new file mode 100755 index 0000000..5754cd9 --- /dev/null +++ b/src/static/timelinejs/js/timeline.js @@ -0,0 +1,9875 @@ +/*! + TimelineJS + Version 2.17 + Designed and built by Zach Wise at VéritéCo + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +*/ + +/* ********************************************** + Begin VMM.StoryJS.License.js +********************************************** */ + +/*! + StoryJS + Designed and built by Zach Wise at VéritéCo + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +/* ********************************************** + Begin VMM.js +********************************************** */ + +/** + * VéritéCo JS Core + * Designed and built by Zach Wise at VéritéCo zach@verite.co + + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + +*/ + + +/* Simple JavaScript Inheritance + By John Resig http://ejohn.org/ + MIT Licensed. +================================================== */ +(function() { + var initializing = false, + fnTest = /xyz/.test(function() { + xyz; + }) ? /\b_super\b/: /.*/; + // The base Class implementation (does nothing) + this.Class = function() {}; + + // Create a new Class that inherits from this class + Class.extend = function(prop) { + var _super = this.prototype; + + // Instantiate a base class (but only create the instance, + // don't run the init constructor) + initializing = true; + var prototype = new this(); + initializing = false; + + // Copy the properties over onto the new prototype + for (var name in prop) { + // Check if we're overwriting an existing function + prototype[name] = typeof prop[name] == "function" && + typeof _super[name] == "function" && fnTest.test(prop[name]) ? + (function(name, fn) { + return function() { + var tmp = this._super; + + // Add a new ._super() method that is the same method + // but on the super-class + this._super = _super[name]; + + // The method only need to be bound temporarily, so we + // remove it when we're done executing + var ret = fn.apply(this, arguments); + this._super = tmp; + + return ret; + }; + })(name, prop[name]) : + prop[name]; + } + + // The dummy class constructor + function Class() { + // All construction is actually done in the init method + if (!initializing && this.init) + this.init.apply(this, arguments); + } + + // Populate our constructed prototype object + Class.prototype = prototype; + + // Enforce the constructor to be what we expect + Class.prototype.constructor = Class; + + // And make this class extendable + Class.extend = arguments.callee; + + return Class; + }; +})(); + +/* Access to the Global Object + access the global object without hard-coding the identifier window +================================================== */ +var global = (function () { + return this || (1,eval)('this'); +}()); + +/* VMM +================================================== */ +if (typeof VMM == 'undefined') { + + /* Main Scope Container + ================================================== */ + //var VMM = {}; + var VMM = Class.extend({}); + + /* Debug + ================================================== */ + VMM.debug = true; + + /* Master Config + ================================================== */ + + VMM.master_config = ({ + + init: function() { + return this; + }, + + sizes: { + api: { + width: 0, + height: 0 + } + }, + + vp: "Pellentesque nibh felis, eleifend id, commodo in, interdum vitae, leo", + + api_keys_master: { + flickr: "RAIvxHY4hE/Elm5cieh4X5ptMyDpj7MYIxziGxi0WGCcy1s+yr7rKQ==", + //google: "jwNGnYw4hE9lmAez4ll0QD+jo6SKBJFknkopLS4FrSAuGfIwyj57AusuR0s8dAo=", + google: "uQKadH1VMlCsp560gN2aOiMz4evWkl1s34yryl3F/9FJOsn+/948CbBUvKLN46U=", + twitter: "" + }, + + timers: { + api: 7000 + }, + + api: { + pushques: [] + + }, + + twitter: { + active: false, + array: [], + api_loaded: false, + que: [] + }, + + flickr: { + active: false, + array: [], + api_loaded: false, + que: [] + }, + + youtube: { + active: false, + array: [], + api_loaded: false, + que: [] + }, + + vimeo: { + active: false, + array: [], + api_loaded: false, + que: [] + }, + + webthumb: { + active: false, + array: [], + api_loaded: false, + que: [] + }, + + googlemaps: { + active: false, + map_active: false, + places_active: false, + array: [], + api_loaded: false, + que: [] + }, + + googledocs: { + active: false, + array: [], + api_loaded: false, + que: [] + }, + + googleplus: { + active: false, + array: [], + api_loaded: false, + que: [] + }, + + wikipedia: { + active: false, + array: [], + api_loaded: false, + que: [], + tries: 0 + }, + + soundcloud: { + active: false, + array: [], + api_loaded: false, + que: [] + } + + }).init(); + + //VMM.createElement(tag, value, cName, attrs, styles); + VMM.createElement = function(tag, value, cName, attrs, styles) { + + var ce = ""; + + if (tag != null && tag != "") { + + // TAG + ce += "<" + tag; + if (cName != null && cName != "") { + ce += " class='" + cName + "'"; + }; + + if (attrs != null && attrs != "") { + ce += " " + attrs; + }; + + if (styles != null && styles != "") { + ce += " style='" + styles + "'"; + }; + + ce += ">"; + + if (value != null && value != "") { + ce += value; + } + + // CLOSE TAG + ce = ce + "</" + tag + ">"; + } + + return ce; + + }; + + VMM.createMediaElement = function(media, caption, credit) { + + var ce = ""; + + var _valid = false; + + ce += "<div class='media'>"; + + if (media != null && media != "") { + + valid = true; + + ce += "<img src='" + media + "'>"; + + // CREDIT + if (credit != null && credit != "") { + ce += VMM.createElement("div", credit, "credit"); + } + + // CAPTION + if (caption != null && caption != "") { + ce += VMM.createElement("div", caption, "caption"); + } + + } + + ce += "</div>"; + + return ce; + + }; + + // Hide URL Bar for iOS and Android by Scott Jehl + // https://gist.github.com/1183357 + + VMM.hideUrlBar = function () { + var win = window, + doc = win.document; + + // If there's a hash, or addEventListener is undefined, stop here + if( !location.hash || !win.addEventListener ){ + + //scroll to 1 + window.scrollTo( 0, 1 ); + var scrollTop = 1, + + //reset to 0 on bodyready, if needed + bodycheck = setInterval(function(){ + if( doc.body ){ + clearInterval( bodycheck ); + scrollTop = "scrollTop" in doc.body ? doc.body.scrollTop : 1; + win.scrollTo( 0, scrollTop === 1 ? 0 : 1 ); + } + }, 15 ); + + win.addEventListener( "load", function(){ + setTimeout(function(){ + //reset to hide addr bar at onload + win.scrollTo( 0, scrollTop === 1 ? 0 : 1 ); + }, 0); + }, false ); + } + }; + + +} + +/* Trace (console.log) +================================================== */ +function trace( msg ) { + if (VMM.debug) { + if (window.console) { + console.log(msg); + } else if ( typeof( jsTrace ) != 'undefined' ) { + jsTrace.send( msg ); + } else { + //alert(msg); + } + } +} + +/* Array Remove - By John Resig (MIT Licensed) + http://ejohn.org/blog/javascript-array-remove/ +================================================== */ +Array.prototype.remove = function(from, to) { + var rest = this.slice((to || from) + 1 || this.length); + this.length = from < 0 ? this.length + from : from; + return this.push.apply(this, rest); +} + +/* Extending Date to include Week +================================================== */ +Date.prototype.getWeek = function() { + var onejan = new Date(this.getFullYear(),0,1); + return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7); +} + +/* Extending Date to include Day of Year +================================================== */ +Date.prototype.getDayOfYear = function() { + var onejan = new Date(this.getFullYear(),0,1); + return Math.ceil((this - onejan) / 86400000); +} + +/* A MORE SPECIFIC TYPEOF(); +// http://rolandog.com/archives/2007/01/18/typeof-a-more-specific-typeof/ +================================================== */ +// type.of() +var is={ + Null:function(a){return a===null;}, + Undefined:function(a){return a===undefined;}, + nt:function(a){return(a===null||a===undefined);}, + Function:function(a){return(typeof(a)==="function")?a.constructor.toString().match(/Function/)!==null:false;}, + String:function(a){return(typeof(a)==="string")?true:(typeof(a)==="object")?a.constructor.toString().match(/string/i)!==null:false;}, + Array:function(a){return(typeof(a)==="object")?a.constructor.toString().match(/array/i)!==null||a.length!==undefined:false;}, + Boolean:function(a){return(typeof(a)==="boolean")?true:(typeof(a)==="object")?a.constructor.toString().match(/boolean/i)!==null:false;}, + Date:function(a){return(typeof(a)==="date")?true:(typeof(a)==="object")?a.constructor.toString().match(/date/i)!==null:false;}, + HTML:function(a){return(typeof(a)==="object")?a.constructor.toString().match(/html/i)!==null:false;}, + Number:function(a){return(typeof(a)==="number")?true:(typeof(a)==="object")?a.constructor.toString().match(/Number/)!==null:false;}, + Object:function(a){return(typeof(a)==="object")?a.constructor.toString().match(/object/i)!==null:false;}, + RegExp:function(a){return(typeof(a)==="function")?a.constructor.toString().match(/regexp/i)!==null:false;} +}; +var type={ + of:function(a){ + for(var i in is){ + if(is[i](a)){ + return i.toLowerCase(); + } + } + } +}; + + + + + +/* ********************************************** + Begin VMM.Library.js +********************************************** */ + +/* * LIBRARY ABSTRACTION +================================================== */ +if(typeof VMM != 'undefined') { + + VMM.smoothScrollTo = function(elem, duration, ease) { + if( typeof( jQuery ) != 'undefined' ){ + var _ease = "easein", + _duration = 1000; + + if (duration != null) { + if (duration < 1) { + _duration = 1; + } else { + _duration = Math.round(duration); + } + + } + + if (ease != null && ease != "") { + _ease = ease; + } + + if (jQuery(window).scrollTop() != VMM.Lib.offset(elem).top) { + VMM.Lib.animate('html,body', _duration, _ease, {scrollTop: VMM.Lib.offset(elem).top}) + } + + } + + }; + + VMM.attachElement = function(element, content) { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).html(content); + } + + }; + + VMM.appendElement = function(element, content) { + + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).append(content); + } + + }; + + VMM.getHTML = function(element) { + var e; + if( typeof( jQuery ) != 'undefined' ){ + e = jQuery(element).html(); + return e; + } + + }; + + VMM.getElement = function(element, p) { + var e; + if( typeof( jQuery ) != 'undefined' ){ + if (p) { + e = jQuery(element).parent().get(0); + + } else { + e = jQuery(element).get(0); + } + return e; + } + + }; + + VMM.bindEvent = function(element, the_handler, the_event_type, event_data) { + var e; + var _event_type = "click"; + var _event_data = {}; + + if (the_event_type != null && the_event_type != "") { + _event_type = the_event_type; + } + + if (_event_data != null && _event_data != "") { + _event_data = event_data; + } + + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).bind(_event_type, _event_data, the_handler); + + //return e; + } + + }; + + VMM.unbindEvent = function(element, the_handler, the_event_type) { + var e; + var _event_type = "click"; + var _event_data = {}; + + if (the_event_type != null && the_event_type != "") { + _event_type = the_event_type; + } + + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).unbind(_event_type, the_handler); + + //return e; + } + + }; + + VMM.fireEvent = function(element, the_event_type, the_data) { + var e; + var _event_type = "click"; + var _data = []; + + if (the_event_type != null && the_event_type != "") { + _event_type = the_event_type; + } + if (the_data != null && the_data != "") { + _data = the_data; + } + + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).trigger(_event_type, _data); + + //return e; + } + + }; + + VMM.getJSON = function(url, data, callback) { + if( typeof( jQuery ) != 'undefined' ){ + jQuery.ajaxSetup({ + timeout: 3000 + }); + /* CHECK FOR IE + ================================================== */ + if ( VMM.Browser.browser == "Explorer" && parseInt(VMM.Browser.version, 10) >= 7 && window.XDomainRequest) { + trace("IE JSON"); + var ie_url = url; + if (ie_url.match('^http://')){ + return jQuery.getJSON(ie_url, data, callback); + } else if (ie_url.match('^https://')) { + ie_url = ie_url.replace("https://","http://"); + return jQuery.getJSON(ie_url, data, callback); + } else { + return jQuery.getJSON(url, data, callback); + } + + } else { + return jQuery.getJSON(url, data, callback); + + } + } + } + + VMM.parseJSON = function(the_json) { + if( typeof( jQuery ) != 'undefined' ){ + return jQuery.parseJSON(the_json); + } + } + + // ADD ELEMENT AND RETURN IT + VMM.appendAndGetElement = function(append_to_element, tag, cName, content) { + var e, + _tag = "<div>", + _class = "", + _content = "", + _id = ""; + + if (tag != null && tag != "") { + _tag = tag; + } + + if (cName != null && cName != "") { + _class = cName; + } + + if (content != null && content != "") { + _content = content; + } + + if( typeof( jQuery ) != 'undefined' ){ + + e = jQuery(tag); + + e.addClass(_class); + e.html(_content); + + jQuery(append_to_element).append(e); + + } + + return e; + + }; + + VMM.Lib = { + + init: function() { + return this; + }, + + hide: function(element, duration) { + if (duration != null && duration != "") { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).hide(duration); + } + } else { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).hide(); + } + } + + }, + + remove: function(element) { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).remove(); + } + }, + + detach: function(element) { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).detach(); + } + }, + + append: function(element, value) { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).append(value); + } + }, + + prepend: function(element, value) { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).prepend(value); + } + }, + + show: function(element, duration) { + if (duration != null && duration != "") { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).show(duration); + } + } else { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).show(); + } + } + + }, + + load: function(element, callback_function, event_data) { + var _event_data = {elem:element}; // return element by default + if (_event_data != null && _event_data != "") { + _event_data = event_data; + } + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).load(_event_data, callback_function); + } + }, + + addClass: function(element, cName) { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).addClass(cName); + } + }, + + removeClass: function(element, cName) { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).removeClass(cName); + } + }, + + attr: function(element, aName, value) { + if (value != null && value != "") { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).attr(aName, value); + } + } else { + if( typeof( jQuery ) != 'undefined' ){ + return jQuery(element).attr(aName); + } + } + }, + + prop: function(element, aName, value) { + if (typeof jQuery == 'undefined' || !/[1-9]\.[3-9].[1-9]/.test(jQuery.fn.jquery)) { + VMM.Lib.attribute(element, aName, value); + } else { + jQuery(element).prop(aName, value); + } + }, + + attribute: function(element, aName, value) { + + if (value != null && value != "") { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).attr(aName, value); + } + } else { + if( typeof( jQuery ) != 'undefined' ){ + return jQuery(element).attr(aName); + } + } + }, + + visible: function(element, show) { + if (show != null) { + if( typeof( jQuery ) != 'undefined' ){ + if (show) { + jQuery(element).show(0); + } else { + jQuery(element).hide(0); + } + } + } else { + if( typeof( jQuery ) != 'undefined' ){ + if ( jQuery(element).is(':visible')){ + return true; + } else { + return false; + } + } + } + }, + + css: function(element, prop, value) { + + if (value != null && value != "") { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).css(prop, value); + } + } else { + if( typeof( jQuery ) != 'undefined' ){ + return jQuery(element).css(prop); + } + } + }, + + cssmultiple: function(element, propval) { + + if( typeof( jQuery ) != 'undefined' ){ + return jQuery(element).css(propval); + } + }, + + offset: function(element) { + var p; + if( typeof( jQuery ) != 'undefined' ){ + p = jQuery(element).offset(); + } + return p; + }, + + position: function(element) { + var p; + if( typeof( jQuery ) != 'undefined' ){ + p = jQuery(element).position(); + } + return p; + }, + + width: function(element, s) { + if (s != null && s != "") { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).width(s); + } + } else { + if( typeof( jQuery ) != 'undefined' ){ + return jQuery(element).width(); + } + } + }, + + height: function(element, s) { + if (s != null && s != "") { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).height(s); + } + } else { + if( typeof( jQuery ) != 'undefined' ){ + return jQuery(element).height(); + } + } + }, + + toggleClass: function(element, cName) { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).toggleClass(cName); + } + }, + + each:function(element, return_function) { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).each(return_function); + } + + }, + + html: function(element, str) { + var e; + if( typeof( jQuery ) != 'undefined' ){ + e = jQuery(element).html(); + return e; + } + + if (str != null && str != "") { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).html(str); + } + } else { + var e; + if( typeof( jQuery ) != 'undefined' ){ + e = jQuery(element).html(); + return e; + } + } + + }, + + find: function(element, selec) { + if( typeof( jQuery ) != 'undefined' ){ + return jQuery(element).find(selec); + } + }, + + stop: function(element) { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).stop(); + } + }, + + delay_animate: function(delay, element, duration, ease, att, callback_function) { + if (VMM.Browser.device == "mobile" || VMM.Browser.device == "tablet") { + var _tdd = Math.round((duration/1500)*10)/10, + __duration = _tdd + 's'; + + VMM.Lib.css(element, '-webkit-transition', 'all '+ __duration + ' ease'); + VMM.Lib.css(element, '-moz-transition', 'all '+ __duration + ' ease'); + VMM.Lib.css(element, '-o-transition', 'all '+ __duration + ' ease'); + VMM.Lib.css(element, '-ms-transition', 'all '+ __duration + ' ease'); + VMM.Lib.css(element, 'transition', 'all '+ __duration + ' ease'); + VMM.Lib.cssmultiple(element, _att); + } else { + if( typeof( jQuery ) != 'undefined' ){ + jQuery(element).delay(delay).animate(att, {duration:duration, easing:ease} ); + } + } + + }, + + animate: function(element, duration, ease, att, que, callback_function) { + + var _ease = "easein", + _que = false, + _duration = 1000, + _att = {}; + + if (duration != null) { + if (duration < 1) { + _duration = 1; + } else { + _duration = Math.round(duration); + } + + } + + if (ease != null && ease != "") { + _ease = ease; + } + + if (que != null && que != "") { + _que = que; + } + + + if (att != null) { + _att = att + } else { + _att = {opacity: 0} + } + + + if (VMM.Browser.device == "mobile" || VMM.Browser.device == "tablet") { + + var _tdd = Math.round((_duration/1500)*10)/10, + __duration = _tdd + 's'; + + _ease = " cubic-bezier(0.33, 0.66, 0.66, 1)"; + //_ease = " ease-in-out"; + for (x in _att) { + if (Object.prototype.hasOwnProperty.call(_att, x)) { + trace(x + " to " + _att[x]); + VMM.Lib.css(element, '-webkit-transition', x + ' ' + __duration + _ease); + VMM.Lib.css(element, '-moz-transition', x + ' ' + __duration + _ease); + VMM.Lib.css(element, '-o-transition', x + ' ' + __duration + _ease); + VMM.Lib.css(element, '-ms-transition', x + ' ' + __duration + _ease); + VMM.Lib.css(element, 'transition', x + ' ' + __duration + _ease); + } + } + + VMM.Lib.cssmultiple(element, _att); + + } else { + if( typeof( jQuery ) != 'undefined' ){ + if (callback_function != null && callback_function != "") { + jQuery(element).animate(_att, {queue:_que, duration:_duration, easing:_ease, complete:callback_function} ); + } else { + jQuery(element).animate(_att, {queue:_que, duration:_duration, easing:_ease} ); + } + } + } + + } + + } +} + +if( typeof( jQuery ) != 'undefined' ){ + + /* XDR AJAX EXTENTION FOR jQuery + https://github.com/jaubourg/ajaxHooks/blob/master/src/ajax/xdr.js + ================================================== */ + (function( jQuery ) { + if ( window.XDomainRequest ) { + jQuery.ajaxTransport(function( s ) { + if ( s.crossDomain && s.async ) { + if ( s.timeout ) { + s.xdrTimeout = s.timeout; + delete s.timeout; + } + var xdr; + return { + send: function( _, complete ) { + function callback( status, statusText, responses, responseHeaders ) { + xdr.onload = xdr.onerror = xdr.ontimeout = jQuery.noop; + xdr = undefined; + complete( status, statusText, responses, responseHeaders ); + } + xdr = new XDomainRequest(); + xdr.open( s.type, s.url ); + xdr.onload = function() { + callback( 200, "OK", { text: xdr.responseText }, "Content-Type: " + xdr.contentType ); + }; + xdr.onerror = function() { + callback( 404, "Not Found" ); + }; + if ( s.xdrTimeout ) { + xdr.ontimeout = function() { + callback( 0, "timeout" ); + }; + xdr.timeout = s.xdrTimeout; + } + xdr.send( ( s.hasContent && s.data ) || null ); + }, + abort: function() { + if ( xdr ) { + xdr.onerror = jQuery.noop(); + xdr.abort(); + } + } + }; + } + }); + } + })( jQuery ); + + /* jQuery Easing v1.3 + http://gsgd.co.uk/sandbox/jquery/easing/ + ================================================== */ + jQuery.easing['jswing'] = jQuery.easing['swing']; + + jQuery.extend( jQuery.easing, { + def: 'easeOutQuad', + swing: function (x, t, b, c, d) { + //alert(jQuery.easing.default); + return jQuery.easing[jQuery.easing.def](x, t, b, c, d); + }, + easeInExpo: function (x, t, b, c, d) { + return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b; + }, + easeOutExpo: function (x, t, b, c, d) { + return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; + }, + easeInOutExpo: function (x, t, b, c, d) { + if (t==0) return b; + if (t==d) return b+c; + if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b; + return c/2 * (-Math.pow(2, -10 * --t) + 2) + b; + }, + easeInQuad: function (x, t, b, c, d) { + return c*(t/=d)*t + b; + }, + easeOutQuad: function (x, t, b, c, d) { + return -c *(t/=d)*(t-2) + b; + }, + easeInOutQuad: function (x, t, b, c, d) { + if ((t/=d/2) < 1) return c/2*t*t + b; + return -c/2 * ((--t)*(t-2) - 1) + b; + } + }); +} + + +/* ********************************************** + Begin VMM.Browser.js +********************************************** */ + +/* * DEVICE AND BROWSER DETECTION +================================================== */ +if(typeof VMM != 'undefined' && typeof VMM.Browser == 'undefined') { + + VMM.Browser = { + init: function () { + this.browser = this.searchString(this.dataBrowser) || "An unknown browser"; + this.version = this.searchVersion(navigator.userAgent) + || this.searchVersion(navigator.appVersion) + || "an unknown version"; + this.OS = this.searchString(this.dataOS) || "an unknown OS"; + this.device = this.searchDevice(navigator.userAgent); + this.orientation = this.searchOrientation(window.orientation); + }, + searchOrientation: function(orientation) { + var orient = ""; + if ( orientation == 0 || orientation == 180) { + orient = "portrait"; + } else if ( orientation == 90 || orientation == -90) { + orient = "landscape"; + } else { + orient = "normal"; + } + return orient; + }, + searchDevice: function(d) { + var device = ""; + if (d.match(/Android/i) || d.match(/iPhone|iPod/i)) { + device = "mobile"; + } else if (d.match(/iPad/i)) { + device = "tablet"; + } else if (d.match(/BlackBerry/i) || d.match(/IEMobile/i)) { + device = "other mobile"; + } else { + device = "desktop"; + } + return device; + }, + searchString: function (data) { + for (var i=0;i<data.length;i++) { + var dataString = data[i].string, + dataProp = data[i].prop; + + this.versionSearchString = data[i].versionSearch || data[i].identity; + + if (dataString) { + if (dataString.indexOf(data[i].subString) != -1) { + return data[i].identity; + } + } else if (dataProp) { + return data[i].identity; + } + } + }, + searchVersion: function (dataString) { + var index = dataString.indexOf(this.versionSearchString); + if (index == -1) return; + return parseFloat(dataString.substring(index+this.versionSearchString.length+1)); + }, + dataBrowser: [ + { + string: navigator.userAgent, + subString: "Chrome", + identity: "Chrome" + }, + { string: navigator.userAgent, + subString: "OmniWeb", + versionSearch: "OmniWeb/", + identity: "OmniWeb" + }, + { + string: navigator.vendor, + subString: "Apple", + identity: "Safari", + versionSearch: "Version" + }, + { + prop: window.opera, + identity: "Opera", + versionSearch: "Version" + }, + { + string: navigator.vendor, + subString: "iCab", + identity: "iCab" + }, + { + string: navigator.vendor, + subString: "KDE", + identity: "Konqueror" + }, + { + string: navigator.userAgent, + subString: "Firefox", + identity: "Firefox" + }, + { + string: navigator.vendor, + subString: "Camino", + identity: "Camino" + }, + { // for newer Netscapes (6+) + string: navigator.userAgent, + subString: "Netscape", + identity: "Netscape" + }, + { + string: navigator.userAgent, + subString: "MSIE", + identity: "Explorer", + versionSearch: "MSIE" + }, + { + string: navigator.userAgent, + subString: "Gecko", + identity: "Mozilla", + versionSearch: "rv" + }, + { // for older Netscapes (4-) + string: navigator.userAgent, + subString: "Mozilla", + identity: "Netscape", + versionSearch: "Mozilla" + } + ], + dataOS : [ + { + string: navigator.platform, + subString: "Win", + identity: "Windows" + }, + { + string: navigator.platform, + subString: "Mac", + identity: "Mac" + }, + { + string: navigator.userAgent, + subString: "iPhone", + identity: "iPhone/iPod" + }, + { + string: navigator.userAgent, + subString: "iPad", + identity: "iPad" + }, + { + string: navigator.platform, + subString: "Linux", + identity: "Linux" + } + ] + + } + VMM.Browser.init(); +} + +/* ********************************************** + Begin VMM.FileExtention.js +********************************************** */ + +/* * File Extention +================================================== */ +if(typeof VMM != 'undefined' && typeof VMM.FileExtention == 'undefined') { + VMM.FileExtention = { + googleDocType: function(url) { + var fileName = url.replace(/\s\s*$/, ''), + fileExtension = "", + validFileExtensions = ["DOC","DOCX","XLS","XLSX","PPT","PPTX","PDF","PAGES","AI","PSD","TIFF","DXF","SVG","EPS","PS","TTF","XPS","ZIP","RAR"], + flag = false; + + fileExtension = fileName.substr(fileName.length - 5, 5); + + for (var i = 0; i < validFileExtensions.length; i++) { + if (fileExtension.toLowerCase().match(validFileExtensions[i].toString().toLowerCase()) || fileName.match("docs.google.com") ) { + flag = true; + } + } + return flag; + } + } +} + +/* ********************************************** + Begin VMM.Date.js +********************************************** */ + +/* * Utilities and Useful Functions +================================================== */ +if(typeof VMM != 'undefined' && typeof VMM.Date == 'undefined') { + + VMM.Date = ({ + + init: function() { + return this; + }, + + dateformats: { + year: "yyyy", + month_short: "mmm", + month: "mmmm yyyy", + full_short: "mmm d", + full: "mmmm d',' yyyy", + time_no_seconds_short: "h:MM TT", + time_no_seconds_small_date: "h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'", + full_long: "mmm d',' yyyy 'at' hh:MM TT", + full_long_small_date: "hh:MM TT'<br/><small>mmm d',' yyyy'</small>'" + }, + + month: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + month_abbr: ["Jan.", "Feb.", "March", "April", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec."], + day: ["Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], + day_abbr: ["Sun.", "Mon.", "Tues.", "Wed.", "Thurs.", "Fri.", "Sat."], + hour: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], + hour_suffix: ["am"], + + //B.C. + bc_format: { + year: "yyyy", + month_short: "mmm", + month: "mmmm yyyy", + full_short: "mmm d", + full: "mmmm d',' yyyy", + time_no_seconds_short: "h:MM TT", + time_no_seconds_small_date: "dddd', 'h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'", + full_long: "dddd',' mmm d',' yyyy 'at' hh:MM TT", + full_long_small_date: "hh:MM TT'<br/><small>'dddd',' mmm d',' yyyy'</small>'" + }, + + setLanguage: function(lang) { + trace("SET DATE LANGUAGE"); + VMM.Date.dateformats = lang.dateformats; + VMM.Date.month = lang.date.month; + VMM.Date.month_abbr = lang.date.month_abbr; + VMM.Date.day = lang.date.day; + VMM.Date.day_abbr = lang.date.day_abbr; + dateFormat.i18n.dayNames = lang.date.day_abbr.concat(lang.date.day); + dateFormat.i18n.monthNames = lang.date.month_abbr.concat(lang.date.month); + }, + + parse: function(d, precision) { + "use strict"; + var date, + date_array, + time_array, + time_parse, + p = { + year: false, + month: false, + day: false, + hour: false, + minute: false, + second: false, + millisecond: false + }; + + if (type.of(d) == "date") { + date = d; + } else { + date = new Date(0, 0, 1, 0, 0, 0, 0); + + if ( d.match(/,/gi) ) { + date_array = d.split(","); + for(var i = 0; i < date_array.length; i++) { + date_array[i] = parseInt(date_array[i], 10); + } + if (date_array[0]) { + date.setFullYear(date_array[0]); + p.year = true; + } + if (date_array[1]) { + date.setMonth(date_array[1] - 1); + p.month = true; + } + if (date_array[2]) { + date.setDate(date_array[2]); + p.day = true; + } + if (date_array[3]) { + date.setHours(date_array[3]); + p.hour = true; + } + if (date_array[4]) { + date.setMinutes(date_array[4]); + p.minute = true; + } + if (date_array[5]) { + date.setSeconds(date_array[5]); + p.second = true; + } + if (date_array[6]) { + date.setMilliseconds(date_array[6]); + p.millisecond = true; + } + } else if (d.match("/")) { + if (d.match(" ")) { + + time_parse = d.split(" "); + if (d.match(":")) { + time_array = time_parse[1].split(":"); + if (time_array[0] >= 0 ) { + date.setHours(time_array[0]); + p.hour = true; + } + if (time_array[1] >= 0) { + date.setMinutes(time_array[1]); + p.minute = true; + } + if (time_array[2] >= 0) { + date.setSeconds(time_array[2]); + p.second = true; + } + if (time_array[3] >= 0) { + date.setMilliseconds(time_array[3]); + p.millisecond = true; + } + } + date_array = time_parse[0].split("/"); + } else { + date_array = d.split("/"); + } + if (date_array[2]) { + date.setFullYear(date_array[2]); + p.year = true; + } + if (date_array[0] >= 0) { + date.setMonth(date_array[0] - 1); + p.month = true; + } + if (date_array[1] >= 0) { + if (date_array[1].length > 2) { + date.setFullYear(date_array[1]); + p.year = true; + } else { + date.setDate(date_array[1]); + p.day = true; + } + } + } else if (d.match("now")) { + var now = new Date(); + + date.setFullYear(now.getFullYear()); + p.year = true; + + date.setMonth(now.getMonth()); + p.month = true; + + date.setDate(now.getDate()); + p.day = true; + + if (d.match("hours")) { + date.setHours(now.getHours()); + p.hour = true; + } + if (d.match("minutes")) { + date.setHours(now.getHours()); + date.setMinutes(now.getMinutes()); + p.hour = true; + p.minute = true; + } + if (d.match("seconds")) { + date.setHours(now.getHours()); + date.setMinutes(now.getMinutes()); + date.setSeconds(now.getSeconds()); + p.hour = true; + p.minute = true; + p.second = true; + } + if (d.match("milliseconds")) { + date.setHours(now.getHours()); + date.setMinutes(now.getMinutes()); + date.setSeconds(now.getSeconds()); + date.setMilliseconds(now.getMilliseconds()); + p.hour = true; + p.minute = true; + p.second = true; + p.millisecond = true; + } + } else if (d.length <= 5) { + p.year = true; + date.setFullYear(parseInt(d, 10)); + date.setMonth(0); + date.setDate(1); + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + date.setMilliseconds(0); + } else if (d.match("T")) { + if (navigator.userAgent.match(/MSIE\s(?!9.0)/)) { + // IE 8 < Won't accept dates with a "-" in them. + time_parse = d.split("T"); + if (d.match(":")) { + time_array = time_parse[1].split(":"); + if (time_array[0] >= 1) { + date.setHours(time_array[0]); + p.hour = true; + } + if (time_array[1] >= 1) { + date.setMinutes(time_array[1]); + p.minute = true; + } + if (time_array[2] >= 1) { + date.setSeconds(time_array[2]); + p.second = true; + } + if (time_array[3] >= 1) { + date.setMilliseconds(time_array[3]); + p.millisecond = true; + } + } + date_array = time_parse[0].split("-"); + if (date_array[0]) { + date.setFullYear(date_array[0]); + p.year = true; + } + if (date_array[1] >= 0) { + date.setMonth(date_array[1] - 1); + p.month = true; + } + if (date_array[2] >= 0) { + date.setDate(date_array[2]); + p.day = true; + } + + } else { + date = new Date(Date.parse(d)); + } + } else { + p.year = true; + p.month = true; + p.day = true; + p.hour = true; + p.minute = true; + p.second = true; + p.millisecond = true; + date = new Date( + parseInt(d.slice(0,4), 10), + parseInt(d.slice(4,6), 10) - 1, + parseInt(d.slice(6,8), 10), + parseInt(d.slice(8,10), 10), + parseInt(d.slice(10,12), 10) + ); + } + + } + + if (precision != null && precision != "") { + return { + date: date, + precision: p + }; + } else { + return date; + } + }, + + + + prettyDate: function(d, is_abbr, p, d2) { + var _date, + _date2, + format, + bc_check, + is_pair = false, + bc_original, + bc_number, + bc_string; + + if (d2 != null && d2 != "" && typeof d2 != 'undefined') { + is_pair = true; + trace("D2 " + d2); + } + + + if (type.of(d) == "date") { + + if (type.of(p) == "object") { + if (p.millisecond || p.second || p.minute) { + // YEAR MONTH DAY HOUR MINUTE + if (is_abbr){ + format = VMM.Date.dateformats.time_no_seconds_short; + } else { + format = VMM.Date.dateformats.time_no_seconds_small_date; + } + } else if (p.hour) { + // YEAR MONTH DAY HOUR + if (is_abbr) { + format = VMM.Date.dateformats.time_no_seconds_short; + } else { + format = VMM.Date.dateformats.time_no_seconds_small_date; + } + } else if (p.day) { + // YEAR MONTH DAY + if (is_abbr) { + format = VMM.Date.dateformats.full_short; + } else { + format = VMM.Date.dateformats.full; + } + } else if (p.month) { + // YEAR MONTH + if (is_abbr) { + format = VMM.Date.dateformats.month_short; + } else { + format = VMM.Date.dateformats.month; + } + } else if (p.year) { + format = VMM.Date.dateformats.year; + } else { + format = VMM.Date.dateformats.year; + } + + } else { + + if (d.getMonth() === 0 && d.getDate() == 1 && d.getHours() === 0 && d.getMinutes() === 0 ) { + // YEAR ONLY + format = VMM.Date.dateformats.year; + } else if (d.getDate() <= 1 && d.getHours() === 0 && d.getMinutes() === 0) { + // YEAR MONTH + if (is_abbr) { + format = VMM.Date.dateformats.month_short; + } else { + format = VMM.Date.dateformats.month; + } + } else if (d.getHours() === 0 && d.getMinutes() === 0) { + // YEAR MONTH DAY + if (is_abbr) { + format = VMM.Date.dateformats.full_short; + } else { + format = VMM.Date.dateformats.full; + } + } else if (d.getMinutes() === 0) { + // YEAR MONTH DAY HOUR + if (is_abbr) { + format = VMM.Date.dateformats.time_no_seconds_short; + } else { + format = VMM.Date.dateformats.time_no_seconds_small_date; + } + } else { + // YEAR MONTH DAY HOUR MINUTE + if (is_abbr){ + format = VMM.Date.dateformats.time_no_seconds_short; + } else { + format = VMM.Date.dateformats.full_long; + } + } + } + + _date = dateFormat(d, format, false); + //_date = "Jan" + bc_check = _date.split(" "); + + // BC TIME SUPPORT + for(var i = 0; i < bc_check.length; i++) { + if ( parseInt(bc_check[i], 10) < 0 ) { + trace("YEAR IS BC"); + bc_original = bc_check[i]; + bc_number = Math.abs( parseInt(bc_check[i], 10) ); + bc_string = bc_number.toString() + " a.C."; + _date = _date.replace(bc_original, bc_string); + } + } + + + if (is_pair) { + _date2 = dateFormat(d2, format, false); + bc_check = _date2.split(" "); + // BC TIME SUPPORT + for(var j = 0; j < bc_check.length; j++) { + if ( parseInt(bc_check[j], 10) < 0 ) { + trace("YEAR IS BC"); + bc_original = bc_check[j]; + bc_number = Math.abs( parseInt(bc_check[j], 10) ); + bc_string = bc_number.toString() + " a.C."; + _date2 = _date2.replace(bc_original, bc_string); + } + } + + } + } else { + trace("NOT A VALID DATE?"); + trace(d); + } + + if (is_pair) { + return _date + " &mdash; " + _date2; + } else { + return _date; + } + } + + }).init(); + + /* + * Date Format 1.2.3 + * (c) 2007-2009 Steven Levithan <stevenlevithan.com> + * MIT license + * + * Includes enhancements by Scott Trenda <scott.trenda.net> + * and Kris Kowal <cixar.com/~kris.kowal/> + * + * Accepts a date, a mask, or a date and a mask. + * Returns a formatted version of the given date. + * The date defaults to the current date/time. + * The mask defaults to dateFormat.masks.default. + */ + + var dateFormat = function () { + var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, + timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, + timezoneClip = /[^-+\dA-Z]/g, + pad = function (val, len) { + val = String(val); + len = len || 2; + while (val.length < len) val = "0" + val; + return val; + }; + + // Regexes and supporting functions are cached through closure + return function (date, mask, utc) { + var dF = dateFormat; + + // You can't provide utc if you skip other args (use the "UTC:" mask prefix) + if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { + mask = date; + date = undefined; + } + + // Passing date through Date applies Date.parse, if necessary + // Caused problems in IE + // date = date ? new Date(date) : new Date; + if (isNaN(date)) { + trace("invalid date " + date); + //return ""; + } + + mask = String(dF.masks[mask] || mask || dF.masks["default"]); + + // Allow setting the utc argument via the mask + if (mask.slice(0, 4) == "UTC:") { + mask = mask.slice(4); + utc = true; + } + + var _ = utc ? "getUTC" : "get", + d = date[_ + "Date"](), + D = date[_ + "Day"](), + m = date[_ + "Month"](), + y = date[_ + "FullYear"](), + H = date[_ + "Hours"](), + M = date[_ + "Minutes"](), + s = date[_ + "Seconds"](), + L = date[_ + "Milliseconds"](), + o = utc ? 0 : date.getTimezoneOffset(), + flags = { + d: d, + dd: pad(d), + ddd: dF.i18n.dayNames[D], + dddd: dF.i18n.dayNames[D + 7], + m: m + 1, + mm: pad(m + 1), + mmm: dF.i18n.monthNames[m], + mmmm: dF.i18n.monthNames[m + 12], + yy: String(y).slice(2), + yyyy: y, + h: H % 12 || 12, + hh: pad(H % 12 || 12), + H: H, + HH: pad(H), + M: M, + MM: pad(M), + s: s, + ss: pad(s), + l: pad(L, 3), + L: pad(L > 99 ? Math.round(L / 10) : L), + t: H < 12 ? "a" : "p", + tt: H < 12 ? "am" : "pm", + T: H < 12 ? "A" : "P", + TT: H < 12 ? "AM" : "PM", + Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), + o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), + S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] + }; + + return mask.replace(token, function ($0) { + return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); + }); + }; + }(); + + // Some common format strings + dateFormat.masks = { + "default": "ddd mmm dd yyyy HH:MM:ss", + shortDate: "m/d/yy", + mediumDate: "mmm d, yyyy", + longDate: "mmmm d, yyyy", + fullDate: "dddd, mmmm d, yyyy", + shortTime: "h:MM TT", + mediumTime: "h:MM:ss TT", + longTime: "h:MM:ss TT Z", + isoDate: "yyyy-mm-dd", + isoTime: "HH:MM:ss", + isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", + isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" + }; + + // Internationalization strings + dateFormat.i18n = { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ] + }; + + // For convenience... + Date.prototype.format = function (mask, utc) { + return dateFormat(this, mask, utc); + }; + +} + +/* ********************************************** + Begin VMM.Util.js +********************************************** */ + +/* * Utilities and Useful Functions +================================================== */ +if(typeof VMM != 'undefined' && typeof VMM.Util == 'undefined') { + + VMM.Util = ({ + + init: function() { + return this; + }, + + /* * CORRECT PROTOCOL (DOES NOT WORK) + ================================================== */ + correctProtocol: function(url) { + var loc = (window.parent.location.protocol).toString(), + prefix = "", + the_url = url.split("://", 2); + + if (loc.match("http")) { + prefix = loc; + } else { + prefix = "https"; + } + + return prefix + "://" + the_url[1]; + + }, + + /* * MERGE CONFIG + ================================================== */ + mergeConfig: function(config_main, config_to_merge) { + var x; + for (x in config_to_merge) { + if (Object.prototype.hasOwnProperty.call(config_to_merge, x)) { + config_main[x] = config_to_merge[x]; + } + } + return config_main; + }, + + /* * GET OBJECT ATTRIBUTE BY INDEX + ================================================== */ + getObjectAttributeByIndex: function(obj, index) { + if(typeof obj != 'undefined') { + var i = 0; + for (var attr in obj){ + if (index === i){ + return obj[attr]; + } + i++; + } + return ""; + } else { + return ""; + } + + }, + + /* * ORDINAL + ================================================== */ + ordinal: function(n) { + return ["th","st","nd","rd"][(!( ((n%10) >3) || (Math.floor(n%100/10)==1)) ) * (n%10)]; + }, + + /* * RANDOM BETWEEN + ================================================== */ + //VMM.Util.randomBetween(1, 3) + randomBetween: function(min, max) { + return Math.floor(Math.random() * (max - min + 1) + min); + }, + + /* * AVERAGE + * http://jsfromhell.com/array/average + * var x = VMM.Util.average([2, 3, 4]); + * VMM.Util.average([2, 3, 4]).mean + ================================================== */ + average: function(a) { + var r = {mean: 0, variance: 0, deviation: 0}, t = a.length; + for(var m, s = 0, l = t; l--; s += a[l]); + for(m = r.mean = s / t, l = t, s = 0; l--; s += Math.pow(a[l] - m, 2)); + return r.deviation = Math.sqrt(r.variance = s / t), r; + }, + + /* * CUSTOM SORT + ================================================== */ + customSort: function(a, b) { + var a1= a, b1= b; + if(a1== b1) return 0; + return a1> b1? 1: -1; + }, + + /* * Remove Duplicates from Array + ================================================== */ + deDupeArray: function(arr) { + var i, + len=arr.length, + out=[], + obj={}; + + for (i=0;i<len;i++) { + obj[arr[i]]=0; + } + for (i in obj) { + out.push(i); + } + return out; + }, + + /* * Given an int or decimal, turn that into string in $xxx,xxx.xx format. + ================================================== */ + number2money: function(n, symbol, padding) { + var symbol = (symbol !== null) ? symbol : true; // add $ + var padding = (padding !== null) ? padding : false; //pad with .00 + var number = VMM.Math2.floatPrecision(n,2); // rounded correctly to two digits, if decimals passed + var formatted = this.niceNumber(number); + // no decimal and padding is enabled + if (!formatted.split(/\./g)[1] && padding) formatted = formatted + ".00"; + // add money sign + if (symbol) formatted = "$"+formatted; + return formatted; + }, + + /* * Returns a word count number + ================================================== */ + wordCount: function(s) { + var fullStr = s + " "; + var initial_whitespace_rExp = /^[^A-Za-z0-9\'\-]+/gi; + var left_trimmedStr = fullStr.replace(initial_whitespace_rExp, ""); + var non_alphanumerics_rExp = /[^A-Za-z0-9\'\-]+/gi; + var cleanedStr = left_trimmedStr.replace(non_alphanumerics_rExp, " "); + var splitString = cleanedStr.split(" "); + var word_count = splitString.length -1; + if (fullStr.length <2) { + word_count = 0; + } + return word_count; + }, + + ratio: { + fit: function(w, h, ratio_w, ratio_h) { + //VMM.Util.ratio.fit(w, h, ratio_w, ratio_h).width; + var _fit = {width:0,height:0}; + // TRY WIDTH FIRST + _fit.width = w; + //_fit.height = Math.round((h / ratio_h) * ratio_w); + _fit.height = Math.round((w / ratio_w) * ratio_h); + if (_fit.height > h) { + _fit.height = h; + //_fit.width = Math.round((w / ratio_w) * ratio_h); + _fit.width = Math.round((h / ratio_h) * ratio_w); + + if (_fit.width > w) { + trace("FIT: DIDN'T FIT!!! ") + } + } + + return _fit; + + }, + r16_9: function(w,h) { + //VMM.Util.ratio.r16_9(w, h) // Returns corresponding number + if (w !== null && w !== "") { + return Math.round((h / 16) * 9); + } else if (h !== null && h !== "") { + return Math.round((w / 9) * 16); + } + }, + r4_3: function(w,h) { + if (w !== null && w !== "") { + return Math.round((h / 4) * 3); + } else if (h !== null && h !== "") { + return Math.round((w / 3) * 4); + } + } + }, + + doubledigit: function(n) { + return (n < 10 ? '0' : '') + n; + }, + + /* * Returns a truncated segement of a long string of between min and max words. If possible, ends on a period (otherwise goes to max). + ================================================== */ + truncateWords: function(s, min, max) { + + if (!min) min = 30; + if (!max) max = min; + + var initial_whitespace_rExp = /^[^A-Za-z0-9\'\-]+/gi; + var left_trimmedStr = s.replace(initial_whitespace_rExp, ""); + var words = left_trimmedStr.split(" "); + + var result = []; + + min = Math.min(words.length, min); + max = Math.min(words.length, max); + + for (var i = 0; i<min; i++) { + result.push(words[i]); + } + + for (var j = min; i<max; i++) { + var word = words[i]; + + result.push(word); + + if (word.charAt(word.length-1) == '.') { + break; + } + } + + return (result.join(' ')); + }, + + /* * Turns plain text links into real links + ================================================== */ + linkify: function(text,targets,is_touch) { + + // http://, https://, ftp:// + var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim; + + // www. sans http:// or https:// + var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim; + + // Email addresses + var emailAddressPattern = /(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim; + + + return text + .replace(urlPattern, "<a target='_blank' href='$&' onclick='void(0)'>$&</a>") + .replace(pseudoUrlPattern, "$1<a target='_blank' onclick='void(0)' href='http://$2'>$2</a>") + .replace(emailAddressPattern, "<a target='_blank' onclick='void(0)' href='mailto:$1'>$1</a>"); + }, + + linkify_with_twitter: function(text,targets,is_touch) { + + // http://, https://, ftp:// + var urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim; + var url_pattern = /(\()((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\))|(\[)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\])|(\{)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(\})|(<|&(?:lt|#60|#x3c);)((?:ht|f)tps?:\/\/[a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]+)(>|&(?:gt|#62|#x3e);)|((?:^|[^=\s'"\]])\s*['"]?|[^=\s]\s+)(\b(?:ht|f)tps?:\/\/[a-z0-9\-._~!$'()*+,;=:\/?#[\]@%]+(?:(?!&(?:gt|#0*62|#x0*3e);|&(?:amp|apos|quot|#0*3[49]|#x0*2[27]);[.!&',:?;]?(?:[^a-z0-9\-._~!$&'()*+,;=:\/?#[\]@%]|$))&[a-z0-9\-._~!$'()*+,;=:\/?#[\]@%]*)*[a-z0-9\-_~$()*+=\/#[\]@%])/img; + var url_replace = '$1$4$7$10$13<a href="$2$5$8$11$14" class="hyphenate">$2$5$8$11$14</a>$3$6$9$12'; + + // www. sans http:// or https:// + var pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim; + function replaceURLWithHTMLLinks(text) { + var exp = /(\b(https?|ftp|file):\/\/([-A-Z0-9+&@#%?=~_|!:,.;]*)([-A-Z0-9+&@#%?\/=~_|!:,.;]*)[-A-Z0-9+&@#\/%=~_|])/ig; + return text.replace(exp, "<a href='$1' target='_blank'>$3</a>"); + } + // Email addresses + var emailAddressPattern = /(([a-zA-Z0-9_\-\.]+)@[a-zA-Z_]+?(?:\.[a-zA-Z]{2,6}))+/gim; + + //var twitterHandlePattern = /(@([\w]+))/g; + var twitterHandlePattern = /\B@([\w-]+)/gm; + var twitterSearchPattern = /(#([\w]+))/g; + + return text + //.replace(urlPattern, "<a target='_blank' href='$&' onclick='void(0)'>$&</a>") + .replace(url_pattern, url_replace) + .replace(pseudoUrlPattern, "$1<a target='_blank' class='hyphenate' onclick='void(0)' href='http://$2'>$2</a>") + .replace(emailAddressPattern, "<a target='_blank' onclick='void(0)' href='mailto:$1'>$1</a>") + .replace(twitterHandlePattern, "<a href='http://twitter.com/$1' target='_blank' onclick='void(0)'>@$1</a>") + .replace(twitterSearchPattern, "<a href='http://twitter.com/#search?q=%23$2' target='_blank' 'void(0)'>$1</a>"); + }, + + linkify_wikipedia: function(text) { + + var urlPattern = /<i[^>]*>(.*?)<\/i>/gim; + return text + .replace(urlPattern, "<a target='_blank' href='http://en.wikipedia.org/wiki/$&' onclick='void(0)'>$&</a>") + .replace(/<i\b[^>]*>/gim, "") + .replace(/<\/i>/gim, "") + .replace(/<b\b[^>]*>/gim, "") + .replace(/<\/b>/gim, ""); + }, + + /* * Turns plain text links into real links + ================================================== */ + // VMM.Util.unlinkify(); + unlinkify: function(text) { + if(!text) return text; + text = text.replace(/<a\b[^>]*>/i,""); + text = text.replace(/<\/a>/i, ""); + return text; + }, + + untagify: function(text) { + if (!text) { + return text; + } + text = text.replace(/<\s*\w.*?>/g,""); + return text; + }, + + /* * TK + ================================================== */ + nl2br: function(text) { + return text.replace(/(\r\n|[\r\n]|\\n|\\r)/g,"<br/>"); + }, + + /* * Generate a Unique ID + ================================================== */ + // VMM.Util.unique_ID(size); + unique_ID: function(size) { + + var getRandomNumber = function(range) { + return Math.floor(Math.random() * range); + }; + + var getRandomChar = function() { + var chars = "abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ"; + return chars.substr( getRandomNumber(62), 1 ); + }; + + var randomID = function(size) { + var str = ""; + for(var i = 0; i < size; i++) { + str += getRandomChar(); + } + return str; + }; + + return randomID(size); + }, + /* * Tells you if a number is even or not + ================================================== */ + // VMM.Util.isEven(n) + isEven: function(n){ + return (n%2 === 0) ? true : false; + }, + /* * Get URL Variables + ================================================== */ + // var somestring = VMM.Util.getUrlVars(str_url)["varname"]; + getUrlVars: function(string) { + + var str = string.toString(); + + if (str.match('&#038;')) { + str = str.replace("&#038;", "&"); + } else if (str.match('&#38;')) { + str = str.replace("&#38;", "&"); + } else if (str.match('&amp;')) { + str = str.replace("&amp;", "&"); + } + + var vars = [], hash; + var hashes = str.slice(str.indexOf('?') + 1).split('&'); + for(var i = 0; i < hashes.length; i++) { + hash = hashes[i].split('='); + vars.push(hash[0]); + vars[hash[0]] = hash[1]; + } + + + return vars; + }, + + /* * Cleans up strings to become real HTML + ================================================== */ + toHTML: function(text) { + + text = this.nl2br(text); + text = this.linkify(text); + + return text.replace(/\s\s/g,"&nbsp;&nbsp;"); + }, + + /* * Returns text strings as CamelCase + ================================================== */ + toCamelCase: function(s,forceLowerCase) { + + if(forceLowerCase !== false) forceLowerCase = true; + + var sps = ((forceLowerCase) ? s.toLowerCase() : s).split(" "); + + for(var i=0; i<sps.length; i++) { + + sps[i] = sps[i].substr(0,1).toUpperCase() + sps[i].substr(1); + } + + return sps.join(" "); + }, + + /* * Replaces dumb quote marks with smart ones + ================================================== */ + properQuotes: function(str) { + return str.replace(/\"([^\"]*)\"/gi,"&#8220;$1&#8221;"); + }, + /* * Add Commas to numbers + ================================================== */ + niceNumber: function(nStr){ + nStr += ''; + x = nStr.split('.'); + x1 = x[0]; + x2 = x.length > 1 ? '.' + x[1] : ''; + var rgx = /(\d+)(\d{3})/; + while (rgx.test(x1)) { + x1 = x1.replace(rgx, '$1' + ',' + '$2'); + } + return x1 + x2; + }, + /* * Transform text to Title Case + ================================================== */ + toTitleCase: function(t){ + if ( VMM.Browser.browser == "Explorer" && parseInt(VMM.Browser.version, 10) >= 7) { + return t.replace("_", "%20"); + } else { + var __TitleCase = { + __smallWords: ['a', 'an', 'and', 'as', 'at', 'but','by', 'en', 'for', 'if', 'in', 'of', 'on', 'or','the', 'to', 'v[.]?', 'via', 'vs[.]?'], + + init: function() { + this.__smallRE = this.__smallWords.join('|'); + this.__lowerCaseWordsRE = new RegExp('\\b(' + this.__smallRE + ')\\b', 'gi'); + this.__firstWordRE = new RegExp('^([^a-zA-Z0-9 \\r\\n\\t]*)(' + this.__smallRE + ')\\b', 'gi'); + this.__lastWordRE = new RegExp('\\b(' + this.__smallRE + ')([^a-zA-Z0-9 \\r\\n\\t]*)$', 'gi'); + }, + + toTitleCase: function(string) { + var line = ''; + + var split = string.split(/([:.;?!][ ]|(?:[ ]|^)["“])/); + + for (var i = 0; i < split.length; ++i) { + var s = split[i]; + + s = s.replace(/\b([a-zA-Z][a-z.'’]*)\b/g,this.__titleCaseDottedWordReplacer); + + // lowercase the list of small words + s = s.replace(this.__lowerCaseWordsRE, this.__lowerReplacer); + + // if the first word in the title is a small word then capitalize it + s = s.replace(this.__firstWordRE, this.__firstToUpperCase); + + // if the last word in the title is a small word, then capitalize it + s = s.replace(this.__lastWordRE, this.__firstToUpperCase); + + line += s; + } + + // special cases + line = line.replace(/ V(s?)\. /g, ' v$1. '); + line = line.replace(/(['’])S\b/g, '$1s'); + line = line.replace(/\b(AT&T|Q&A)\b/ig, this.__upperReplacer); + + return line; + }, + + __titleCaseDottedWordReplacer: function (w) { + return (w.match(/[a-zA-Z][.][a-zA-Z]/)) ? w : __TitleCase.__firstToUpperCase(w); + }, + + __lowerReplacer: function (w) { return w.toLowerCase() }, + + __upperReplacer: function (w) { return w.toUpperCase() }, + + __firstToUpperCase: function (w) { + var split = w.split(/(^[^a-zA-Z0-9]*[a-zA-Z0-9])(.*)$/); + if (split[1]) { + split[1] = split[1].toUpperCase(); + } + + return split.join(''); + + + } + }; + + __TitleCase.init(); + + t = t.replace(/_/g," "); + t = __TitleCase.toTitleCase(t); + + return t; + + } + + } + + }).init(); +} + +/* ********************************************** + Begin LazyLoad.js +********************************************** */ + +/*jslint browser: true, eqeqeq: true, bitwise: true, newcap: true, immed: true, regexp: false */ + +/* +LazyLoad makes it easy and painless to lazily load one or more external +JavaScript or CSS files on demand either during or after the rendering of a web +page. + +Supported browsers include Firefox 2+, IE6+, Safari 3+ (including Mobile +Safari), Google Chrome, and Opera 9+. Other browsers may or may not work and +are not officially supported. + +Visit https://github.com/rgrove/lazyload/ for more info. + +Copyright (c) 2011 Ryan Grove <ryan@wonko.com> +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the 'Software'), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +@module lazyload +@class LazyLoad +@static +@version 2.0.3 (git) +*/ + +LazyLoad = (function (doc) { + // -- Private Variables ------------------------------------------------------ + + // User agent and feature test information. + var env, + + // Reference to the <head> element (populated lazily). + head, + + // Requests currently in progress, if any. + pending = {}, + + // Number of times we've polled to check whether a pending stylesheet has + // finished loading. If this gets too high, we're probably stalled. + pollCount = 0, + + // Queued requests. + queue = {css: [], js: []}, + + // Reference to the browser's list of stylesheets. + styleSheets = doc.styleSheets; + + // -- Private Methods -------------------------------------------------------- + + /** + Creates and returns an HTML element with the specified name and attributes. + + @method createNode + @param {String} name element name + @param {Object} attrs name/value mapping of element attributes + @return {HTMLElement} + @private + */ + function createNode(name, attrs) { + var node = doc.createElement(name), attr; + + for (attr in attrs) { + if (attrs.hasOwnProperty(attr)) { + node.setAttribute(attr, attrs[attr]); + } + } + + return node; + } + + /** + Called when the current pending resource of the specified type has finished + loading. Executes the associated callback (if any) and loads the next + resource in the queue. + + @method finish + @param {String} type resource type ('css' or 'js') + @private + */ + function finish(type) { + var p = pending[type], + callback, + urls; + + if (p) { + callback = p.callback; + urls = p.urls; + + urls.shift(); + pollCount = 0; + + // If this is the last of the pending URLs, execute the callback and + // start the next request in the queue (if any). + if (!urls.length) { + callback && callback.call(p.context, p.obj); + pending[type] = null; + queue[type].length && load(type); + } + } + } + + /** + Populates the <code>env</code> variable with user agent and feature test + information. + + @method getEnv + @private + */ + function getEnv() { + var ua = navigator.userAgent; + + env = { + // True if this browser supports disabling async mode on dynamically + // created script nodes. See + // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order + async: doc.createElement('script').async === true + }; + + (env.webkit = /AppleWebKit\//.test(ua)) + || (env.ie = /MSIE/.test(ua)) + || (env.opera = /Opera/.test(ua)) + || (env.gecko = /Gecko\//.test(ua)) + || (env.unknown = true); + } + + /** + Loads the specified resources, or the next resource of the specified type + in the queue if no resources are specified. If a resource of the specified + type is already being loaded, the new request will be queued until the + first request has been finished. + + When an array of resource URLs is specified, those URLs will be loaded in + parallel if it is possible to do so while preserving execution order. All + browsers support parallel loading of CSS, but only Firefox and Opera + support parallel loading of scripts. In other browsers, scripts will be + queued and loaded one at a time to ensure correct execution order. + + @method load + @param {String} type resource type ('css' or 'js') + @param {String|Array} urls (optional) URL or array of URLs to load + @param {Function} callback (optional) callback function to execute when the + resource is loaded + @param {Object} obj (optional) object to pass to the callback function + @param {Object} context (optional) if provided, the callback function will + be executed in this object's context + @private + */ + function load(type, urls, callback, obj, context) { + var _finish = function () { finish(type); }, + isCSS = type === 'css', + nodes = [], + i, len, node, p, pendingUrls, url; + + env || getEnv(); + + if (urls) { + // If urls is a string, wrap it in an array. Otherwise assume it's an + // array and create a copy of it so modifications won't be made to the + // original. + urls = typeof urls === 'string' ? [urls] : urls.concat(); + + // Create a request object for each URL. If multiple URLs are specified, + // the callback will only be executed after all URLs have been loaded. + // + // Sadly, Firefox and Opera are the only browsers capable of loading + // scripts in parallel while preserving execution order. In all other + // browsers, scripts must be loaded sequentially. + // + // All browsers respect CSS specificity based on the order of the link + // elements in the DOM, regardless of the order in which the stylesheets + // are actually downloaded. + if (isCSS || env.async || env.gecko || env.opera) { + // Load in parallel. + queue[type].push({ + urls : urls, + callback: callback, + obj : obj, + context : context + }); + } else { + // Load sequentially. + for (i = 0, len = urls.length; i < len; ++i) { + queue[type].push({ + urls : [urls[i]], + callback: i === len - 1 ? callback : null, // callback is only added to the last URL + obj : obj, + context : context + }); + } + } + } + + // If a previous load request of this type is currently in progress, we'll + // wait our turn. Otherwise, grab the next item in the queue. + if (pending[type] || !(p = pending[type] = queue[type].shift())) { + return; + } + + head || (head = doc.head || doc.getElementsByTagName('head')[0]); + pendingUrls = p.urls; + + for (i = 0, len = pendingUrls.length; i < len; ++i) { + url = pendingUrls[i]; + + if (isCSS) { + node = env.gecko ? createNode('style') : createNode('link', { + href: url, + rel : 'stylesheet' + }); + } else { + node = createNode('script', {src: url}); + node.async = false; + } + + node.className = 'lazyload'; + node.setAttribute('charset', 'utf-8'); + + if (env.ie && !isCSS) { + node.onreadystatechange = function () { + if (/loaded|complete/.test(node.readyState)) { + node.onreadystatechange = null; + _finish(); + } + }; + } else if (isCSS && (env.gecko || env.webkit)) { + // Gecko and WebKit don't support the onload event on link nodes. + if (env.webkit) { + // In WebKit, we can poll for changes to document.styleSheets to + // figure out when stylesheets have loaded. + p.urls[i] = node.href; // resolve relative URLs (or polling won't work) + pollWebKit(); + } else { + // In Gecko, we can import the requested URL into a <style> node and + // poll for the existence of node.sheet.cssRules. Props to Zach + // Leatherman for calling my attention to this technique. + node.innerHTML = '@import "' + url + '";'; + pollGecko(node); + } + } else { + node.onload = node.onerror = _finish; + } + + nodes.push(node); + } + + for (i = 0, len = nodes.length; i < len; ++i) { + head.appendChild(nodes[i]); + } + } + + /** + Begins polling to determine when the specified stylesheet has finished loading + in Gecko. Polling stops when all pending stylesheets have loaded or after 10 + seconds (to prevent stalls). + + Thanks to Zach Leatherman for calling my attention to the @import-based + cross-domain technique used here, and to Oleg Slobodskoi for an earlier + same-domain implementation. See Zach's blog for more details: + http://www.zachleat.com/web/2010/07/29/load-css-dynamically/ + + @method pollGecko + @param {HTMLElement} node Style node to poll. + @private + */ + function pollGecko(node) { + var hasRules; + + try { + // We don't really need to store this value or ever refer to it again, but + // if we don't store it, Closure Compiler assumes the code is useless and + // removes it. + hasRules = !!node.sheet.cssRules; + } catch (ex) { + // An exception means the stylesheet is still loading. + pollCount += 1; + + if (pollCount < 200) { + setTimeout(function () { pollGecko(node); }, 50); + } else { + // We've been polling for 10 seconds and nothing's happened. Stop + // polling and finish the pending requests to avoid blocking further + // requests. + hasRules && finish('css'); + } + + return; + } + + // If we get here, the stylesheet has loaded. + finish('css'); + } + + /** + Begins polling to determine when pending stylesheets have finished loading + in WebKit. Polling stops when all pending stylesheets have loaded or after 10 + seconds (to prevent stalls). + + @method pollWebKit + @private + */ + function pollWebKit() { + var css = pending.css, i; + + if (css) { + i = styleSheets.length; + + // Look for a stylesheet matching the pending URL. + while (--i >= 0) { + if (styleSheets[i].href === css.urls[0]) { + finish('css'); + break; + } + } + + pollCount += 1; + + if (css) { + if (pollCount < 200) { + setTimeout(pollWebKit, 50); + } else { + // We've been polling for 10 seconds and nothing's happened, which may + // indicate that the stylesheet has been removed from the document + // before it had a chance to load. Stop polling and finish the pending + // request to prevent blocking further requests. + finish('css'); + } + } + } + } + + return { + + /** + Requests the specified CSS URL or URLs and executes the specified + callback (if any) when they have finished loading. If an array of URLs is + specified, the stylesheets will be loaded in parallel and the callback + will be executed after all stylesheets have finished loading. + + @method css + @param {String|Array} urls CSS URL or array of CSS URLs to load + @param {Function} callback (optional) callback function to execute when + the specified stylesheets are loaded + @param {Object} obj (optional) object to pass to the callback function + @param {Object} context (optional) if provided, the callback function + will be executed in this object's context + @static + */ + css: function (urls, callback, obj, context) { + load('css', urls, callback, obj, context); + }, + + /** + Requests the specified JavaScript URL or URLs and executes the specified + callback (if any) when they have finished loading. If an array of URLs is + specified and the browser supports it, the scripts will be loaded in + parallel and the callback will be executed after all scripts have + finished loading. + + Currently, only Firefox and Opera support parallel loading of scripts while + preserving execution order. In other browsers, scripts will be + queued and loaded one at a time to ensure correct execution order. + + @method js + @param {String|Array} urls JS URL or array of JS URLs to load + @param {Function} callback (optional) callback function to execute when + the specified scripts are loaded + @param {Object} obj (optional) object to pass to the callback function + @param {Object} context (optional) if provided, the callback function + will be executed in this object's context + @static + */ + js: function (urls, callback, obj, context) { + load('js', urls, callback, obj, context); + } + + }; +})(this.document); + + +/* ********************************************** + Begin VMM.LoadLib.js +********************************************** */ + +/* + LoadLib + Designed and built by Zach Wise digitalartwork.net +*/ + +/* * CodeKit Import + * http://incident57.com/codekit/ +================================================== */ +// @codekit-prepend "../Library/LazyLoad.js"; + +LoadLib = (function (doc) { + var loaded = []; + + function isLoaded(url) { + + var i = 0, + has_loaded = false; + + for (i = 0; i < loaded.length; i++) { + if (loaded[i] == url) { + has_loaded = true; + } + } + + if (has_loaded) { + return true; + } else { + loaded.push(url); + return false; + } + + } + + return { + + css: function (urls, callback, obj, context) { + if (!isLoaded(urls)) { + LazyLoad.css(urls, callback, obj, context); + } + }, + + js: function (urls, callback, obj, context) { + if (!isLoaded(urls)) { + LazyLoad.js(urls, callback, obj, context); + } + } + }; + +})(this.document); + + +/* ********************************************** + Begin VMM.Core.js +********************************************** */ + +/* VeriteCo Core +================================================== */ + +/* * CodeKit Import + * http://incident57.com/codekit/ +================================================== */ +// @codekit-prepend "VMM.js"; +// @codekit-prepend "VMM.Library.js"; +// @codekit-prepend "VMM.Browser.js"; +// @codekit-prepend "VMM.FileExtention.js"; +// @codekit-prepend "VMM.Date.js"; +// @codekit-prepend "VMM.Util.js"; +// @codekit-prepend "VMM.LoadLib.js"; +// @codekit-prepend "VMM.Language.js"; + + + +/* ********************************************** + Begin VMM.Language.js +********************************************** */ + +/* DEFAULT LANGUAGE +================================================== */ +if(typeof VMM != 'undefined' && typeof VMM.Language == 'undefined') { + VMM.Language = { + lang: "en", + api: { + wikipedia: "en" + }, + date: { + month: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + month_abbr: ["Jan.", "Feb.", "March", "April", "May", "June", "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec."], + day: ["Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], + day_abbr: ["Sun.","Mon.", "Tues.", "Wed.", "Thurs.", "Fri.", "Sat."] + }, + dateformats: { + year: "yyyy", + month_short: "mmm", + month: "mmmm yyyy", + full_short: "mmm d", + full: "mmmm d',' yyyy", + time_no_seconds_short: "h:MM TT", + time_no_seconds_small_date: "h:MM TT'<br/><small>'mmmm d',' yyyy'</small>'", + full_long: "mmm d',' yyyy 'at' h:MM TT", + full_long_small_date: "h:MM TT'<br/><small>mmm d',' yyyy'</small>'" + }, + messages: { + loading_timeline: "Loading Timeline... ", + return_to_title: "Return to Title", + expand_timeline: "Expand Timeline", + contract_timeline: "Contract Timeline", + wikipedia: "From Wikipedia, the free encyclopedia", + loading_content: "Loading Content", + loading: "Loading" + } + } +}; + +/* ********************************************** + Begin VMM.ExternalAPI.js +********************************************** */ + +/* External API +================================================== */ +if(typeof VMM != 'undefined' && typeof VMM.ExternalAPI == 'undefined') { + + VMM.ExternalAPI = ({ + + keys: { + google: "", + flickr: "", + twitter: "" + }, + + keys_master: { + vp: "Pellentesque nibh felis, eleifend id, commodo in, interdum vitae, leo", + flickr: "RAIvxHY4hE/Elm5cieh4X5ptMyDpj7MYIxziGxi0WGCcy1s+yr7rKQ==", + google: "jwNGnYw4hE9lmAez4ll0QD+jo6SKBJFknkopLS4FrSAuGfIwyj57AusuR0s8dAo=", + twitter: "" + }, + + init: function() { + return this; + }, + + setKeys: function(d) { + VMM.ExternalAPI.keys = d; + }, + + pushQues: function() { + + if (VMM.master_config.googlemaps.active) { + VMM.ExternalAPI.googlemaps.pushQue(); + } + if (VMM.master_config.youtube.active) { + VMM.ExternalAPI.youtube.pushQue(); + } + if (VMM.master_config.soundcloud.active) { + VMM.ExternalAPI.soundcloud.pushQue(); + } + if (VMM.master_config.googledocs.active) { + VMM.ExternalAPI.googledocs.pushQue(); + } + if (VMM.master_config.googleplus.active) { + VMM.ExternalAPI.googleplus.pushQue(); + } + if (VMM.master_config.wikipedia.active) { + VMM.ExternalAPI.wikipedia.pushQue(); + } + if (VMM.master_config.vimeo.active) { + VMM.ExternalAPI.vimeo.pushQue(); + } + if (VMM.master_config.twitter.active) { + VMM.ExternalAPI.twitter.pushQue(); + } + if (VMM.master_config.flickr.active) { + VMM.ExternalAPI.flickr.pushQue(); + } + if (VMM.master_config.webthumb.active) { + VMM.ExternalAPI.webthumb.pushQue(); + } + }, + + twitter: { + tweetArray: [], + + get: function(m) { + var tweet = {mid: m.id, id: m.uid}; + VMM.master_config.twitter.que.push(tweet); + VMM.master_config.twitter.active = true; + //VMM.master_config.api.pushques.push(VMM.ExternalAPI.twitter.pushQue); + + }, + + create: function(tweet, callback) { + + var id = tweet.mid.toString(), + error_obj = { twitterid: tweet.mid }, + the_url = "http://api.twitter.com/1/statuses/show.json?id=" + tweet.mid + "&include_entities=true&callback=?", + twitter_timeout = setTimeout(VMM.ExternalAPI.twitter.errorTimeOut, VMM.master_config.timers.api, tweet), + callback_timeout= setTimeout(callback, VMM.master_config.timers.api, tweet); + + VMM.getJSON(the_url, function(d) { + var id = d.id_str, + twit = "<blockquote><p>", + td = VMM.Util.linkify_with_twitter(d.text, "_blank"); + + // TWEET CONTENT + twit += td; + twit += "</p></blockquote>"; + + // TWEET MEDIA + if (typeof d.entities.media != 'undefined') { + if (d.entities.media[0].type == "photo") { + //twit += "<img src=' " + d.entities.media[0].media_url + "' alt=''>" + } + } + + // TWEET AUTHOR + twit += "<div class='vcard author'>"; + twit += "<a class='screen-name url' href='https://twitter.com/" + d.user.screen_name + "' data-screen-name='" + d.user.screen_name + "' target='_blank'>"; + twit += "<span class='avatar'><img src=' " + d.user.profile_image_url + "' alt=''></span>"; + twit += "<span class='fn'>" + d.user.name + "</span>"; + twit += "<span class='nickname'>@" + d.user.screen_name + "<span class='thumbnail-inline'></span></span>"; + twit += "</a>"; + twit += "</div>"; + + + + VMM.attachElement("#"+tweet.id.toString(), twit ); + VMM.attachElement("#text_thumb_"+tweet.id.toString(), d.text ); + VMM.attachElement("#marker_content_" + tweet.id.toString(), d.text ); + + }) + .error(function(jqXHR, textStatus, errorThrown) { + trace("TWITTER error"); + trace("TWITTER ERROR: " + textStatus + " " + jqXHR.responseText); + VMM.attachElement("#"+tweet.id, VMM.MediaElement.loadingmessage("ERROR LOADING TWEET " + tweet.mid) ); + }) + .success(function(d) { + clearTimeout(twitter_timeout); + clearTimeout(callback_timeout); + callback(); + }); + + }, + + errorTimeOut: function(tweet) { + trace("TWITTER JSON ERROR TIMEOUT " + tweet.mid); + VMM.attachElement("#"+tweet.id.toString(), VMM.MediaElement.loadingmessage("Still waiting on Twitter: " + tweet.mid) ); + // CHECK RATE STATUS + VMM.getJSON("http://api.twitter.com/1/account/rate_limit_status.json", function(d) { + trace("REMAINING TWITTER API CALLS " + d.remaining_hits); + trace("TWITTER RATE LIMIT WILL RESET AT " + d.reset_time); + var mes = ""; + if (d.remaining_hits == 0) { + mes = "<p>You've reached the maximum number of tweets you can load in an hour.</p>"; + mes += "<p>You can view tweets again starting at: <br/>" + d.reset_time + "</p>"; + } else { + mes = "<p>Still waiting on Twitter. " + tweet.mid + "</p>"; + //mes = "<p>Tweet " + id + " was not found.</p>"; + } + VMM.attachElement("#"+tweet.id.toString(), VMM.MediaElement.loadingmessage(mes) ); + }); + + }, + + pushQue: function() { + if (VMM.master_config.twitter.que.length > 0) { + VMM.ExternalAPI.twitter.create(VMM.master_config.twitter.que[0], VMM.ExternalAPI.twitter.pushQue); + VMM.master_config.twitter.que.remove(0); + } + }, + + + + getHTML: function(id) { + //var the_url = document.location.protocol + "//api.twitter.com/1/statuses/oembed.json?id=" + id+ "&callback=?"; + var the_url = "http://api.twitter.com/1/statuses/oembed.json?id=" + id+ "&callback=?"; + VMM.getJSON(the_url, VMM.ExternalAPI.twitter.onJSONLoaded); + }, + + onJSONLoaded: function(d) { + trace("TWITTER JSON LOADED"); + var id = d.id; + VMM.attachElement("#"+id, VMM.Util.linkify_with_twitter(d.html) ); + }, + + parseTwitterDate: function(d) { + var date = new Date(Date.parse(d)); + /* + var t = d.replace(/(\d{1,2}[:]\d{2}[:]\d{2}) (.*)/, '$2 $1'); + t = t.replace(/(\+\S+) (.*)/, '$2 $1'); + var date = new Date(Date.parse(t)).toLocaleDateString(); + var time = new Date(Date.parse(t)).toLocaleTimeString(); + */ + return date; + }, + + prettyParseTwitterDate: function(d) { + var date = new Date(Date.parse(d)); + return VMM.Date.prettyDate(date, true); + }, + + getTweets: function(tweets) { + var tweetArray = []; + var number_of_tweets = tweets.length; + + for(var i = 0; i < tweets.length; i++) { + + var twitter_id = ""; + + + /* FIND THE TWITTER ID + ================================================== */ + if (tweets[i].tweet.match("status\/")) { + twitter_id = tweets[i].tweet.split("status\/")[1]; + } else if (tweets[i].tweet.match("statuses\/")) { + twitter_id = tweets[i].tweet.split("statuses\/")[1]; + } else { + twitter_id = ""; + } + + /* FETCH THE DATA + ================================================== */ + var the_url = "http://api.twitter.com/1/statuses/show.json?id=" + twitter_id + "&include_entities=true&callback=?"; + VMM.getJSON(the_url, function(d) { + + var tweet = {} + /* FORMAT RESPONSE + ================================================== */ + var twit = "<div class='twitter'><blockquote><p>"; + var td = VMM.Util.linkify_with_twitter(d.text, "_blank"); + twit += td; + twit += "</p>"; + + twit += "— " + d.user.name + " (<a href='https://twitter.com/" + d.user.screen_name + "'>@" + d.user.screen_name + "</a>) <a href='https://twitter.com/" + d.user.screen_name + "/status/" + d.id + "'>" + VMM.ExternalAPI.twitter.prettyParseTwitterDate(d.created_at) + " </a></blockquote></div>"; + + tweet.content = twit; + tweet.raw = d; + + tweetArray.push(tweet); + + + /* CHECK IF THATS ALL OF THEM + ================================================== */ + if (tweetArray.length == number_of_tweets) { + var the_tweets = {tweetdata: tweetArray} + VMM.fireEvent(global, "TWEETSLOADED", the_tweets); + } + }) + .success(function() { trace("second success"); }) + .error(function() { trace("error"); }) + .complete(function() { trace("complete"); }); + + } + + + }, + + getTweetSearch: function(tweets, number_of_tweets) { + var _number_of_tweets = 40; + if (number_of_tweets != null && number_of_tweets != "") { + _number_of_tweets = number_of_tweets; + } + + var the_url = "http://search.twitter.com/search.json?q=" + tweets + "&rpp=" + _number_of_tweets + "&include_entities=true&result_type=mixed"; + var tweetArray = []; + VMM.getJSON(the_url, function(d) { + + /* FORMAT RESPONSE + ================================================== */ + for(var i = 0; i < d.results.length; i++) { + var tweet = {} + var twit = "<div class='twitter'><blockquote><p>"; + var td = VMM.Util.linkify_with_twitter(d.results[i].text, "_blank"); + twit += td; + twit += "</p>"; + twit += "— " + d.results[i].from_user_name + " (<a href='https://twitter.com/" + d.results[i].from_user + "'>@" + d.results[i].from_user + "</a>) <a href='https://twitter.com/" + d.results[i].from_user + "/status/" + d.id + "'>" + VMM.ExternalAPI.twitter.prettyParseTwitterDate(d.results[i].created_at) + " </a></blockquote></div>"; + tweet.content = twit; + tweet.raw = d.results[i]; + tweetArray.push(tweet); + } + var the_tweets = {tweetdata: tweetArray} + VMM.fireEvent(global, "TWEETSLOADED", the_tweets); + }); + + }, + + prettyHTML: function(id, secondary) { + var id = id.toString(); + var error_obj = { + twitterid: id + }; + var the_url = "http://api.twitter.com/1/statuses/show.json?id=" + id + "&include_entities=true&callback=?"; + var twitter_timeout = setTimeout(VMM.ExternalAPI.twitter.errorTimeOut, VMM.master_config.timers.api, id); + + VMM.getJSON(the_url, VMM.ExternalAPI.twitter.formatJSON) + .error(function(jqXHR, textStatus, errorThrown) { + trace("TWITTER error"); + trace("TWITTER ERROR: " + textStatus + " " + jqXHR.responseText); + VMM.attachElement("#twitter_"+id, "<p>ERROR LOADING TWEET " + id + "</p>" ); + }) + .success(function(d) { + clearTimeout(twitter_timeout); + if (secondary) { + VMM.ExternalAPI.twitter.secondaryMedia(d); + } + }); + }, + + + + formatJSON: function(d) { + var id = d.id_str; + + var twit = "<blockquote><p>"; + var td = VMM.Util.linkify_with_twitter(d.text, "_blank"); + //td = td.replace(/(@([\w]+))/g,"<a href='http://twitter.com/$2' target='_blank'>$1</a>"); + //td = td.replace(/(#([\w]+))/g,"<a href='http://twitter.com/#search?q=%23$2' target='_blank'>$1</a>"); + twit += td; + twit += "</p></blockquote>"; + //twit += " <a href='https://twitter.com/" + d.user.screen_name + "/status/" + d.id_str + "' target='_blank' alt='link to original tweet' title='link to original tweet'>" + "<span class='created-at'></span>" + " </a>"; + + twit += "<div class='vcard author'>"; + twit += "<a class='screen-name url' href='https://twitter.com/" + d.user.screen_name + "' data-screen-name='" + d.user.screen_name + "' target='_blank'>"; + twit += "<span class='avatar'><img src=' " + d.user.profile_image_url + "' alt=''></span>"; + twit += "<span class='fn'>" + d.user.name + "</span>"; + twit += "<span class='nickname'>@" + d.user.screen_name + "<span class='thumbnail-inline'></span></span>"; + twit += "</a>"; + twit += "</div>"; + + if (typeof d.entities.media != 'undefined') { + if (d.entities.media[0].type == "photo") { + twit += "<img src=' " + d.entities.media[0].media_url + "' alt=''>" + } + } + + VMM.attachElement("#twitter_"+id.toString(), twit ); + VMM.attachElement("#text_thumb_"+id.toString(), d.text ); + + } + + + }, + + googlemaps: { + + maptype: "toner", + + setMapType: function(d) { + if (d != "") { + VMM.ExternalAPI.googlemaps.maptype = d; + } + }, + + get: function(m) { + var timer, + api_key, + map_url; + + m.vars = VMM.Util.getUrlVars(m.id); + + if (VMM.ExternalAPI.keys.google != "") { + api_key = VMM.ExternalAPI.keys.google; + } else { + api_key = Aes.Ctr.decrypt(VMM.ExternalAPI.keys_master.google, VMM.ExternalAPI.keys_master.vp, 256); + } + + map_url = "http://maps.googleapis.com/maps/api/js?key=" + api_key + "&libraries=places&sensor=false&callback=VMM.ExternalAPI.googlemaps.onMapAPIReady"; + + if (VMM.master_config.googlemaps.active) { + VMM.master_config.googlemaps.que.push(m); + } else { + VMM.master_config.googlemaps.que.push(m); + + if (VMM.master_config.googlemaps.api_loaded) { + + } else { + LoadLib.js(map_url, function() { + trace("Google Maps API Library Loaded"); + }); + } + } + }, + + create: function(m) { + VMM.ExternalAPI.googlemaps.createAPIMap(m); + }, + + createiFrameMap: function(m) { + var embed_url = m.id + "&output=embed", + mc = "", + unique_map_id = m.uid.toString() + "_gmap"; + + mc += "<div class='google-map' id='" + unique_map_id + "' style='width=100%;height=100%;'>"; + mc += "<iframe width='100%' height='100%' frameborder='0' scrolling='no' marginheight='0' marginwidth='0' src='" + embed_url + "'></iframe>"; + mc += "</div>"; + + VMM.attachElement("#" + m.uid, mc); + + }, + + createAPIMap: function(m) { + var map_attribution = "", + layer, + map, + map_options, + unique_map_id = m.uid.toString() + "_gmap", + map_attribution_html = "", + location = new google.maps.LatLng(41.875696,-87.624207), + latlong, + zoom = 11, + has_location = false, + has_zoom = false, + api_limit = false, + map_bounds; + + + function mapProvider(name) { + if (name in VMM.ExternalAPI.googlemaps.map_providers) { + map_attribution = VMM.ExternalAPI.googlemaps.map_attribution[VMM.ExternalAPI.googlemaps.map_providers[name].attribution]; + return VMM.ExternalAPI.googlemaps.map_providers[name]; + } else { + if (VMM.ExternalAPI.googlemaps.defaultType(name)) { + trace("GOOGLE MAP DEFAULT TYPE"); + return google.maps.MapTypeId[name.toUpperCase()]; + } else { + trace("Not a maptype: " + name ); + } + } + } + + google.maps.VeriteMapType = function(name) { + if (VMM.ExternalAPI.googlemaps.defaultType(name)) { + return google.maps.MapTypeId[name.toUpperCase()]; + } else { + var provider = mapProvider(name); + return google.maps.ImageMapType.call(this, { + "getTileUrl": function(coord, zoom) { + var index = (zoom + coord.x + coord.y) % VMM.ExternalAPI.googlemaps.map_subdomains.length; + return [ + provider.url + .replace("{S}", VMM.ExternalAPI.googlemaps.map_subdomains[index]) + .replace("{Z}", zoom) + .replace("{X}", coord.x) + .replace("{Y}", coord.y) + .replace("{z}", zoom) + .replace("{x}", coord.x) + .replace("{y}", coord.y) + ]; + }, + "tileSize": new google.maps.Size(256, 256), + "name": name, + "minZoom": provider.minZoom, + "maxZoom": provider.maxZoom + }); + } + }; + + google.maps.VeriteMapType.prototype = new google.maps.ImageMapType("_"); + + /* Make the Map + ================================================== */ + + if (VMM.ExternalAPI.googlemaps.maptype != "") { + if (VMM.ExternalAPI.googlemaps.defaultType(VMM.ExternalAPI.googlemaps.maptype)) { + layer = google.maps.MapTypeId[VMM.ExternalAPI.googlemaps.maptype.toUpperCase()]; + } else { + layer = VMM.ExternalAPI.googlemaps.maptype; + } + } else { + layer = "toner"; + } + + + if (type.of(VMM.Util.getUrlVars(m.id)["ll"]) == "string") { + has_location = true; + latlong = VMM.Util.getUrlVars(m.id)["ll"].split(","); + location = new google.maps.LatLng(parseFloat(latlong[0]),parseFloat(latlong[1])); + + } else if (type.of(VMM.Util.getUrlVars(m.id)["sll"]) == "string") { + latlong = VMM.Util.getUrlVars(m.id)["sll"].split(","); + location = new google.maps.LatLng(parseFloat(latlong[0]),parseFloat(latlong[1])); + } + + if (type.of(VMM.Util.getUrlVars(m.id)["z"]) == "string") { + has_zoom = true; + zoom = parseFloat(VMM.Util.getUrlVars(m.id)["z"]); + } + + map_options = { + zoom: zoom, + draggable: false, + disableDefaultUI: true, + mapTypeControl: false, + zoomControl: true, + zoomControlOptions: { + style: google.maps.ZoomControlStyle.SMALL, + position: google.maps.ControlPosition.TOP_RIGHT + }, + center: location, + mapTypeId: layer, + mapTypeControlOptions: { + mapTypeIds: [layer] + } + } + + VMM.attachElement("#" + m.uid, "<div class='google-map' id='" + unique_map_id + "' style='width=100%;height=100%;'></div>"); + + map = new google.maps.Map(document.getElementById(unique_map_id), map_options); + + if (VMM.ExternalAPI.googlemaps.defaultType(VMM.ExternalAPI.googlemaps.maptype)) { + + } else { + map.mapTypes.set(layer, new google.maps.VeriteMapType(layer)); + // ATTRIBUTION + map_attribution_html = "<div class='map-attribution'><div class='attribution-text'>" + map_attribution + "</div></div>"; + VMM.appendElement("#"+unique_map_id, map_attribution_html); + } + + // DETERMINE IF KML IS POSSIBLE + if (type.of(VMM.Util.getUrlVars(m.id)["msid"]) == "string") { + loadKML(); + } else { + //loadPlaces(); + if (type.of(VMM.Util.getUrlVars(m.id)["q"]) == "string") { + geocodePlace(); + } + } + + // GEOCODE + function geocodePlace() { + + + + var geocoder = new google.maps.Geocoder(), + address = VMM.Util.getUrlVars(m.id)["q"], + marker; + + if (address.match("loc:")) { + var address_latlon = address.split(":")[1].split("+"); + location = new google.maps.LatLng(parseFloat(address_latlon[0]),parseFloat(address_latlon[1])); + has_location = true; + } + + geocoder.geocode( { 'address': address}, function(results, status) { + if (status == google.maps.GeocoderStatus.OK) { + + marker = new google.maps.Marker({ + map: map, + position: results[0].geometry.location + }); + + // POSITION MAP + //map.setCenter(results[0].geometry.location); + //map.panTo(location); + if (typeof results[0].geometry.viewport != 'undefined') { + map.fitBounds(results[0].geometry.viewport); + } else if (typeof results[0].geometry.bounds != 'undefined') { + map.fitBounds(results[0].geometry.bounds); + } else { + map.setCenter(results[0].geometry.location); + } + + if (has_location) { + map.panTo(location); + } + if (has_zoom) { + map.setZoom(zoom); + } + + } else { + trace("Geocode for " + address + " was not successful for the following reason: " + status); + trace("TRYING PLACES SEARCH"); + + if (has_location) { + map.panTo(location); + } + if (has_zoom) { + map.setZoom(zoom); + } + + loadPlaces(); + } + }); + } + + // PLACES + function loadPlaces() { + var place, + search_request, + infowindow, + search_bounds, + bounds_sw, + bounds_ne; + + place_search = new google.maps.places.PlacesService(map); + infowindow = new google.maps.InfoWindow(); + + search_request = { + query: "", + types: ['country', 'neighborhood', 'political', 'locality', 'geocode'] + }; + + if (type.of(VMM.Util.getUrlVars(m.id)["q"]) == "string") { + search_request.query = VMM.Util.getUrlVars(m.id)["q"]; + } + + if (has_location) { + search_request.location = location; + search_request.radius = "15000"; + } else { + bounds_sw = new google.maps.LatLng(-89.999999,-179.999999); + bounds_ne = new google.maps.LatLng(89.999999,179.999999); + search_bounds = new google.maps.LatLngBounds(bounds_sw,bounds_ne); + + //search_request.location = search_bounds; + } + + place_search.textSearch(search_request, placeResults); + + function placeResults(results, status) { + + if (status == google.maps.places.PlacesServiceStatus.OK) { + + for (var i = 0; i < results.length; i++) { + //createMarker(results[i]); + } + + if (has_location) { + map.panTo(location); + } else { + if (results.length >= 1) { + map.panTo(results[0].geometry.location); + if (has_zoom) { + map.setZoom(zoom); + } + } + } + + + } else { + trace("Place search for " + search_request.query + " was not successful for the following reason: " + status); + // IF There's a problem loading the map, load a simple iFrame version instead + trace("YOU MAY NEED A GOOGLE MAPS API KEY IN ORDER TO USE THIS FEATURE OF TIMELINEJS"); + trace("FIND OUT HOW TO GET YOUR KEY HERE: https://developers.google.com/places/documentation/#Authentication"); + + + if (has_location) { + map.panTo(location); + if (has_zoom) { + map.setZoom(zoom); + } + } else { + trace("USING SIMPLE IFRAME MAP EMBED"); + if (m.id[0].match("https")) { + m.id = m.url[0].replace("https", "http"); + } + VMM.ExternalAPI.googlemaps.createiFrameMap(m); + } + + } + + } + + function createMarker(place) { + var marker, placeLoc; + + placeLoc = place.geometry.location; + marker = new google.maps.Marker({ + map: map, + position: place.geometry.location + }); + + google.maps.event.addListener(marker, 'click', function() { + infowindow.setContent(place.name); + infowindow.open(map, this); + }); + } + + } + + function loadPlacesAlt() { + var api_key, + places_url, + has_key = false; + + trace("LOADING PLACES API FOR GOOGLE MAPS"); + + if (VMM.ExternalAPI.keys.google != "") { + api_key = VMM.ExternalAPI.keys.google; + has_key = true; + } else { + trace("YOU NEED A GOOGLE MAPS API KEY IN ORDER TO USE THIS FEATURE OF TIMELINEJS"); + trace("FIND OUT HOW TO GET YOUR KEY HERE: https://developers.google.com/places/documentation/#Authentication"); + } + + places_url = "https://maps.googleapis.com/maps/api/place/textsearch/json?key=" + api_key + "&sensor=false&language=" + m.lang + "&"; + + if (type.of(VMM.Util.getUrlVars(m.id)["q"]) == "string") { + places_url += "query=" + VMM.Util.getUrlVars(m.id)["q"]; + } + + if (has_location) { + places_url += "&location=" + location; + } + + if (has_key) { + VMM.getJSON(places_url, function(d) { + trace("PLACES JSON"); + + var places_location = "", + places_bounds = "", + places_bounds_ne = "", + places_bounds_sw = ""; + + trace(d); + + if (d.status == "OVER_QUERY_LIMIT") { + trace("OVER_QUERY_LIMIT"); + if (has_location) { + map.panTo(location); + if (has_zoom) { + map.setZoom(zoom); + } + } else { + trace("DOING TRADITIONAL MAP IFRAME EMBED UNTIL QUERY LIMIT RESTORED"); + api_limit = true; + VMM.ExternalAPI.googlemaps.createiFrameMap(m); + } + + } else { + if (d.results.length >= 1) { + //location = new google.maps.LatLng(parseFloat(d.results[0].geometry.location.lat),parseFloat(d.results[0].geometry.location.lng)); + //map.panTo(location); + + places_bounds_ne = new google.maps.LatLng(parseFloat(d.results[0].geometry.viewport.northeast.lat),parseFloat(d.results[0].geometry.viewport.northeast.lng)); + places_bounds_sw = new google.maps.LatLng(parseFloat(d.results[0].geometry.viewport.southwest.lat),parseFloat(d.results[0].geometry.viewport.southwest.lng)); + + places_bounds = new google.maps.LatLngBounds(places_bounds_sw, places_bounds_ne) + map.fitBounds(places_bounds); + + } else { + trace("NO RESULTS"); + } + + if (has_location) { + map.panTo(location); + } + if (has_zoom) { + map.setZoom(zoom); + } + } + + }) + .error(function(jqXHR, textStatus, errorThrown) { + trace("PLACES JSON ERROR"); + trace("PLACES JSON ERROR: " + textStatus + " " + jqXHR.responseText); + }) + .success(function(d) { + trace("PLACES JSON SUCCESS"); + }); + } else { + if (has_location) { + map.panTo(location); + if (has_zoom) { + map.setZoom(zoom); + } + } else { + trace("DOING TRADITIONAL MAP IFRAME EMBED BECAUSE NO GOOGLE MAP API KEY WAS PROVIDED"); + VMM.ExternalAPI.googlemaps.createiFrameMap(m); + } + } + + + } + + // KML + function loadKML() { + var kml_url, kml_layer, infowindow, text; + + kml_url = m.id + "&output=kml"; + kml_url = kml_url.replace("&output=embed", ""); + kml_layer = new google.maps.KmlLayer(kml_url, {preserveViewport:true}); + infowindow = new google.maps.InfoWindow(); + kml_layer.setMap(map); + + google.maps.event.addListenerOnce(kml_layer, "defaultviewport_changed", function() { + + if (has_location) { + map.panTo(location); + } else { + map.fitBounds(kml_layer.getDefaultViewport() ); + } + if (has_zoom) { + map.setZoom(zoom); + } + }); + + google.maps.event.addListener(kml_layer, 'click', function(kmlEvent) { + text = kmlEvent.featureData.description; + showInfoWindow(text); + + function showInfoWindow(c) { + infowindow.setContent(c); + infowindow.open(map); + } + }); + } + + + }, + + pushQue: function() { + for(var i = 0; i < VMM.master_config.googlemaps.que.length; i++) { + VMM.ExternalAPI.googlemaps.create(VMM.master_config.googlemaps.que[i]); + } + VMM.master_config.googlemaps.que = []; + }, + + onMapAPIReady: function() { + VMM.master_config.googlemaps.map_active = true; + VMM.master_config.googlemaps.places_active = true; + VMM.ExternalAPI.googlemaps.onAPIReady(); + }, + + onPlacesAPIReady: function() { + VMM.master_config.googlemaps.places_active = true; + VMM.ExternalAPI.googlemaps.onAPIReady(); + }, + + onAPIReady: function() { + if (!VMM.master_config.googlemaps.active) { + if (VMM.master_config.googlemaps.map_active && VMM.master_config.googlemaps.places_active) { + VMM.master_config.googlemaps.active = true; + VMM.ExternalAPI.googlemaps.pushQue(); + } + } + }, + + defaultType: function(name) { + if (name.toLowerCase() == "satellite" || name.toLowerCase() == "hybrid" || name.toLowerCase() == "terrain" || name.toLowerCase() == "roadmap") { + return true; + } else { + return false; + } + }, + + map_subdomains: ["", "a.", "b.", "c.", "d."], + + map_attribution: { + "stamen": "Map tiles by <a href='http://stamen.com'>Stamen Design</a>, under <a href='http://creativecommons.org/licenses/by/3.0'>CC BY 3.0</a>. Data by <a href='http://openstreetmap.org'>OpenStreetMap</a>, under <a href='http://creativecommons.org/licenses/by-sa/3.0'>CC BY SA</a>.", + "apple": "Map data &copy; 2012 Apple, Imagery &copy; 2012 Apple" + }, + + map_providers: { + "toner": { + "url": "http://{S}tile.stamen.com/toner/{Z}/{X}/{Y}.png", + "minZoom": 0, + "maxZoom": 20, + "attribution": "stamen" + + }, + "toner-lines": { + "url": "http://{S}tile.stamen.com/toner-lines/{Z}/{X}/{Y}.png", + "minZoom": 0, + "maxZoom": 20, + "attribution": "stamen" + }, + "toner-labels": { + "url": "http://{S}tile.stamen.com/toner-labels/{Z}/{X}/{Y}.png", + "minZoom": 0, + "maxZoom": 20, + "attribution": "stamen" + }, + "sterrain": { + "url": "http://{S}tile.stamen.com/terrain/{Z}/{X}/{Y}.jpg", + "minZoom": 4, + "maxZoom": 20, + "attribution": "stamen" + }, + "apple": { + "url": "http://gsp2.apple.com/tile?api=1&style=slideshow&layers=default&lang=en_US&z={z}&x={x}&y={y}&v=9", + "minZoom": 4, + "maxZoom": 14, + "attribution": "apple" + }, + "watercolor": { + "url": "http://{S}tile.stamen.com/watercolor/{Z}/{X}/{Y}.jpg", + "minZoom": 3, + "maxZoom": 16, + "attribution": "stamen" + } + } + }, + + googleplus: { + + get: function(m) { + var api_key; + var gplus = {user: m.user, activity: m.id, id: m.uid}; + + VMM.master_config.googleplus.que.push(gplus); + VMM.master_config.googleplus.active = true; + }, + + create: function(gplus, callback) { + var mediaElem = "", + api_key = "", + g_activity = "", + g_content = "", + g_attachments = "", + gperson_api_url, + gactivity_api_url; + googleplus_timeout = setTimeout(VMM.ExternalAPI.googleplus.errorTimeOut, VMM.master_config.timers.api, gplus), + callback_timeout = setTimeout(callback, VMM.master_config.timers.api, gplus); + + + if (VMM.master_config.Timeline.api_keys.google != "") { + api_key = VMM.master_config.Timeline.api_keys.google; + } else { + api_key = Aes.Ctr.decrypt(VMM.master_config.api_keys_master.google, VMM.master_config.vp, 256); + } + + gperson_api_url = "https://www.googleapis.com/plus/v1/people/" + gplus.user + "/activities/public?alt=json&maxResults=100&fields=items(id,url)&key=" + api_key; + + //mediaElem = "<iframe class='doc' frameborder='0' width='100%' height='100%' src='" + gplus.url + "&amp;embedded=true'></iframe>"; + mediaElem = "GOOGLE PLUS API CALL"; + + VMM.getJSON(gperson_api_url, function(p_data) { + for(var i = 0; i < p_data.items.length; i++) { + trace("loop"); + if (p_data.items[i].url.split("posts/")[1] == gplus.activity) { + trace("FOUND IT!!"); + + g_activity = p_data.items[i].id; + gactivity_api_url = "https://www.googleapis.com/plus/v1/activities/" + g_activity + "?alt=json&key=" + api_key; + + VMM.getJSON(gactivity_api_url, function(a_data) { + trace(a_data); + //a_data.url + //a_data.image.url + //a_data.actor.displayName + //a_data.provider.title + //a_data.object.content + + //g_content += "<h4>" + a_data.title + "</h4>"; + + if (typeof a_data.annotation != 'undefined') { + g_content += "<div class='googleplus-annotation'>'" + a_data.annotation + "</div>"; + g_content += a_data.object.content; + } else { + g_content += a_data.object.content; + } + + if (typeof a_data.object.attachments != 'undefined') { + + //g_attachments += "<div class='googleplus-attachemnts'>"; + + for(var k = 0; k < a_data.object.attachments.length; k++) { + if (a_data.object.attachments[k].objectType == "photo") { + g_attachments = "<a href='" + a_data.object.url + "' target='_blank'>" + "<img src='" + a_data.object.attachments[k].image.url + "' class='article-thumb'></a>" + g_attachments; + } else if (a_data.object.attachments[k].objectType == "video") { + g_attachments = "<img src='" + a_data.object.attachments[k].image.url + "' class='article-thumb'>" + g_attachments; + g_attachments += "<div>"; + g_attachments += "<a href='" + a_data.object.attachments[k].url + "' target='_blank'>" + g_attachments += "<h5>" + a_data.object.attachments[k].displayName + "</h5>"; + //g_attachments += "<p>" + a_data.object.attachments[k].content + "</p>"; + g_attachments += "</a>"; + g_attachments += "</div>"; + } else if (a_data.object.attachments[k].objectType == "article") { + g_attachments += "<div>"; + g_attachments += "<a href='" + a_data.object.attachments[k].url + "' target='_blank'>" + g_attachments += "<h5>" + a_data.object.attachments[k].displayName + "</h5>"; + g_attachments += "<p>" + a_data.object.attachments[k].content + "</p>"; + g_attachments += "</a>"; + g_attachments += "</div>"; + } + + trace(a_data.object.attachments[k]); + } + + g_attachments = "<div class='googleplus-attachments'>" + g_attachments + "</div>"; + } + + //mediaElem = "<div class='googleplus'>"; + mediaElem = "<div class='googleplus-content'>" + g_content + g_attachments + "</div>"; + + mediaElem += "<div class='vcard author'><a class='screen-name url' href='" + a_data.url + "' target='_blank'>"; + mediaElem += "<span class='avatar'><img src='" + a_data.actor.image.url + "' style='max-width: 32px; max-height: 32px;'></span>" + mediaElem += "<span class='fn'>" + a_data.actor.displayName + "</span>"; + mediaElem += "<span class='nickname'><span class='thumbnail-inline'></span></span>"; + mediaElem += "</a></div>"; + + VMM.attachElement("#googleplus_" + gplus.activity, mediaElem); + + + }); + + break; + } + } + + + + }) + .error(function(jqXHR, textStatus, errorThrown) { + var error_obj = VMM.parseJSON(jqXHR.responseText); + trace(error_obj.error.message); + VMM.attachElement("#googleplus_" + gplus.activity, VMM.MediaElement.loadingmessage("<p>ERROR LOADING GOOGLE+ </p><p>" + error_obj.error.message + "</p>")); + }) + .success(function(d) { + clearTimeout(googleplus_timeout); + clearTimeout(callback_timeout); + callback(); + }); + + + + }, + + pushQue: function() { + if (VMM.master_config.googleplus.que.length > 0) { + VMM.ExternalAPI.googleplus.create(VMM.master_config.googleplus.que[0], VMM.ExternalAPI.googleplus.pushQue); + VMM.master_config.googleplus.que.remove(0); + } + /* + for(var i = 0; i < VMM.master_config.googleplus.que.length; i++) { + VMM.ExternalAPI.googleplus.create(VMM.master_config.googleplus.que[i]); + } + VMM.master_config.googleplus.que = []; + */ + }, + + errorTimeOut: function(gplus) { + trace("GOOGLE+ JSON ERROR TIMEOUT " + gplus.activity); + VMM.attachElement("#googleplus_" + gplus.activity, VMM.MediaElement.loadingmessage("<p>Still waiting on GOOGLE+ </p><p>" + gplus.activity + "</p>")); + + } + + }, + + googledocs: { + + get: function(m) { + VMM.master_config.googledocs.que.push(m); + VMM.master_config.googledocs.active = true; + }, + + create: function(m) { + var mediaElem = ""; + if (m.id.match(/docs.google.com/i)) { + mediaElem = "<iframe class='doc' frameborder='0' width='100%' height='100%' src='" + m.id + "&amp;embedded=true'></iframe>"; + } else { + mediaElem = "<iframe class='doc' frameborder='0' width='100%' height='100%' src='" + "http://docs.google.com/viewer?url=" + m.id + "&amp;embedded=true'></iframe>"; + } + VMM.attachElement("#"+m.uid, mediaElem); + }, + + pushQue: function() { + + for(var i = 0; i < VMM.master_config.googledocs.que.length; i++) { + VMM.ExternalAPI.googledocs.create(VMM.master_config.googledocs.que[i]); + } + VMM.master_config.googledocs.que = []; + } + + }, + + flickr: { + + get: function(m) { + VMM.master_config.flickr.que.push(m); + VMM.master_config.flickr.active = true; + }, + + create: function(m, callback) { + var api_key, + callback_timeout= setTimeout(callback, VMM.master_config.timers.api, m); + + if (typeof VMM.master_config.Timeline != 'undefined' && VMM.master_config.Timeline.api_keys.flickr != "") { + api_key = VMM.master_config.Timeline.api_keys.flickr; + } else { + api_key = Aes.Ctr.decrypt(VMM.master_config.api_keys_master.flickr, VMM.master_config.vp, 256) + } + var the_url = "http://api.flickr.com/services/rest/?method=flickr.photos.getSizes&api_key=" + api_key + "&photo_id=" + m.id + "&format=json&jsoncallback=?"; + + VMM.getJSON(the_url, function(d) { + var flickr_id = d.sizes.size[0].url.split("photos\/")[1].split("/")[1]; + + var flickr_large_id = "#" + m.uid, + flickr_thumb_id = "#" + m.uid + "_thumb"; + //flickr_thumb_id = "flickr_" + uid + "_thumb"; + + var flickr_img_size, + flickr_img_thumb, + flickr_size_found = false, + flickr_best_size = "Large"; + + flickr_best_size = VMM.ExternalAPI.flickr.sizes(VMM.master_config.sizes.api.height); + for(var i = 0; i < d.sizes.size.length; i++) { + if (d.sizes.size[i].label == flickr_best_size) { + + flickr_size_found = true; + flickr_img_size = d.sizes.size[i].source; + } + } + if (!flickr_size_found) { + flickr_img_size = d.sizes.size[d.sizes.size.length - 2].source; + } + + flickr_img_thumb = d.sizes.size[0].source; + VMM.Lib.attr(flickr_large_id, "src", flickr_img_size); + //VMM.attachElement(flickr_large_id, "<a href='" + flick.link + "' target='_blank'><img src='" + flickr_img_size + "'></a>"); + VMM.attachElement(flickr_thumb_id, "<img src='" + flickr_img_thumb + "'>"); + + }) + .error(function(jqXHR, textStatus, errorThrown) { + trace("FLICKR error"); + trace("FLICKR ERROR: " + textStatus + " " + jqXHR.responseText); + }) + .success(function(d) { + clearTimeout(callback_timeout); + callback(); + }); + + }, + + pushQue: function() { + if (VMM.master_config.flickr.que.length > 0) { + VMM.ExternalAPI.flickr.create(VMM.master_config.flickr.que[0], VMM.ExternalAPI.flickr.pushQue); + VMM.master_config.flickr.que.remove(0); + } + }, + + sizes: function(s) { + var _size = ""; + if (s <= 75) { + _size = "Thumbnail"; + } else if (s <= 180) { + _size = "Small"; + } else if (s <= 240) { + _size = "Small 320"; + } else if (s <= 375) { + _size = "Medium"; + } else if (s <= 480) { + _size = "Medium 640"; + } else if (s <= 600) { + _size = "Large"; + } else { + _size = "Large"; + } + + return _size; + } + + }, + + instagram: { + get: function(m, thumb) { + if (thumb) { + return "http://instagr.am/p/" + m.id + "/media/?size=t"; + } else { + return "http://instagr.am/p/" + m.id + "/media/?size=" + VMM.ExternalAPI.instagram.sizes(VMM.master_config.sizes.api.height); + } + }, + + sizes: function(s) { + var _size = ""; + if (s <= 150) { + _size = "t"; + } else if (s <= 306) { + _size = "m"; + } else { + _size = "l"; + } + + return _size; + } + }, + + soundcloud: { + + get: function(m) { + VMM.master_config.soundcloud.que.push(m); + VMM.master_config.soundcloud.active = true; + }, + + create: function(m, callback) { + var the_url = "http://soundcloud.com/oembed?url=" + m.id + "&format=js&callback=?"; + VMM.getJSON(the_url, function(d) { + VMM.attachElement("#"+m.uid, d.html); + callback(); + }); + }, + + pushQue: function() { + if (VMM.master_config.soundcloud.que.length > 0) { + VMM.ExternalAPI.soundcloud.create(VMM.master_config.soundcloud.que[0], VMM.ExternalAPI.soundcloud.pushQue); + VMM.master_config.soundcloud.que.remove(0); + } + } + + }, + + wikipedia: { + + get: function(m) { + VMM.master_config.wikipedia.que.push(m); + VMM.master_config.wikipedia.active = true; + }, + + create: function(m, callback) { + var the_url = "http://" + m.lang + ".wikipedia.org/w/api.php?action=query&prop=extracts&redirects=&titles=" + m.id + "&exintro=1&format=json&callback=?"; + callback_timeout= setTimeout(callback, VMM.master_config.timers.api, m); + + if ( VMM.Browser.browser == "Explorer" && parseInt(VMM.Browser.version, 10) >= 7 && window.XDomainRequest) { + var temp_text = "<h4><a href='http://" + VMM.master_config.language.api.wikipedia + ".wikipedia.org/wiki/" + m.id + "' target='_blank'>" + m.url + "</a></h4>"; + temp_text += "<span class='wiki-source'>" + VMM.master_config.language.messages.wikipedia + "</span>"; + temp_text += "<p>Wikipedia entry unable to load using Internet Explorer 8 or below.</p>"; + VMM.attachElement("#"+m.uid, temp_text ); + } + + VMM.getJSON(the_url, function(d) { + if (d.query) { + var wiki_extract, + wiki_title, + _wiki = "", + wiki_text = "", + wiki_number_of_paragraphs = 1, + wiki_text_array = []; + + wiki_extract = VMM.Util.getObjectAttributeByIndex(d.query.pages, 0).extract; + wiki_title = VMM.Util.getObjectAttributeByIndex(d.query.pages, 0).title; + + if (wiki_extract.match("<p>")) { + wiki_text_array = wiki_extract.split("<p>"); + } else { + wiki_text_array.push(wiki_extract); + } + + for(var i = 0; i < wiki_text_array.length; i++) { + if (i+1 <= wiki_number_of_paragraphs && i+1 < wiki_text_array.length) { + wiki_text += "<p>" + wiki_text_array[i+1]; + } + } + + _wiki = "<h4><a href='http://" + VMM.master_config.language.api.wikipedia + ".wikipedia.org/wiki/" + wiki_title + "' target='_blank'>" + wiki_title + "</a></h4>"; + _wiki += "<span class='wiki-source'>" + VMM.master_config.language.messages.wikipedia + "</span>"; + _wiki += VMM.Util.linkify_wikipedia(wiki_text); + + if (wiki_extract.match("REDIRECT")) { + + } else { + VMM.attachElement("#"+m.uid, _wiki ); + } + } + //callback(); + }) + .error(function(jqXHR, textStatus, errorThrown) { + trace("WIKIPEDIA error"); + trace("WIKIPEDIA ERROR: " + textStatus + " " + jqXHR.responseText); + trace(errorThrown); + + VMM.attachElement("#"+m.uid, VMM.MediaElement.loadingmessage("<p>Wikipedia is not responding</p>")); + // TRY AGAIN? + clearTimeout(callback_timeout); + if (VMM.master_config.wikipedia.tries < 4) { + trace("WIKIPEDIA ATTEMPT " + VMM.master_config.wikipedia.tries); + trace(m); + VMM.master_config.wikipedia.tries++; + VMM.ExternalAPI.wikipedia.create(m, callback); + } else { + callback(); + } + + }) + .success(function(d) { + VMM.master_config.wikipedia.tries = 0; + clearTimeout(callback_timeout); + callback(); + }); + + + }, + + pushQue: function() { + + if (VMM.master_config.wikipedia.que.length > 0) { + trace("WIKIPEDIA PUSH QUE " + VMM.master_config.wikipedia.que.length); + VMM.ExternalAPI.wikipedia.create(VMM.master_config.wikipedia.que[0], VMM.ExternalAPI.wikipedia.pushQue); + VMM.master_config.wikipedia.que.remove(0); + } + + } + + }, + + youtube: { + + get: function(m) { + var the_url = "http://gdata.youtube.com/feeds/api/videos/" + m.id + "?v=2&alt=jsonc&callback=?"; + + VMM.master_config.youtube.que.push(m); + + if (!VMM.master_config.youtube.active) { + if (!VMM.master_config.youtube.api_loaded) { + LoadLib.js('http://www.youtube.com/player_api', function() { + trace("YouTube API Library Loaded"); + }); + } + } + + // THUMBNAIL + VMM.getJSON(the_url, function(d) { + VMM.ExternalAPI.youtube.createThumb(d, m) + }); + + }, + + create: function(m) { + if (typeof(m.start) != 'undefined') { + + var vidstart = m.start.toString(), + vid_start_minutes = 0, + vid_start_seconds = 0; + + if (vidstart.match('m')) { + vid_start_minutes = parseInt(vidstart.split("m")[0], 10); + vid_start_seconds = parseInt(vidstart.split("m")[1].split("s")[0], 10); + m.start = (vid_start_minutes * 60) + vid_start_seconds; + } else { + m.start = 0; + } + } else { + m.start = 0; + } + + var p = { + active: false, + player: {}, + name: m.uid, + playing: false, + hd: false + }; + + if (typeof(m.hd) != 'undefined') { + p.hd = true; + } + + p.player[m.id] = new YT.Player(m.uid, { + height: '390', + width: '640', + playerVars: { + enablejsapi: 1, + color: 'white', + showinfo: 0, + theme: 'light', + start: m.start, + rel: 0 + }, + videoId: m.id, + events: { + 'onReady': VMM.ExternalAPI.youtube.onPlayerReady, + 'onStateChange': VMM.ExternalAPI.youtube.onStateChange + } + }); + + VMM.master_config.youtube.array.push(p); + }, + + createThumb: function(d, m) { + trace("CREATE THUMB"); + trace(d); + trace(m); + if (typeof d.data != 'undefined') { + var thumb_id = "#" + m.uid + "_thumb"; + VMM.attachElement(thumb_id, "<img src='" + d.data.thumbnail.sqDefault + "'>"); + + } + }, + + pushQue: function() { + for(var i = 0; i < VMM.master_config.youtube.que.length; i++) { + VMM.ExternalAPI.youtube.create(VMM.master_config.youtube.que[i]); + } + VMM.master_config.youtube.que = []; + }, + + onAPIReady: function() { + VMM.master_config.youtube.active = true; + VMM.ExternalAPI.youtube.pushQue(); + }, + + stopPlayers: function() { + for(var i = 0; i < VMM.master_config.youtube.array.length; i++) { + if (VMM.master_config.youtube.array[i].playing) { + var the_name = VMM.master_config.youtube.array[i].name; + VMM.master_config.youtube.array[i].player[the_name].stopVideo(); + } + } + }, + + onStateChange: function(e) { + for(var i = 0; i < VMM.master_config.youtube.array.length; i++) { + var the_name = VMM.master_config.youtube.array[i].name; + if (VMM.master_config.youtube.array[i].player[the_name] == e.target) { + if (e.data == YT.PlayerState.PLAYING) { + VMM.master_config.youtube.array[i].playing = true; + trace(VMM.master_config.youtube.array[i].hd) + if (VMM.master_config.youtube.array[i].hd) { + // SET TO HD + // DOESN'T WORK AS OF NOW + //VMM.master_config.youtube.array[i].player.setPlaybackQuality("hd720"); + } + } + } + } + }, + + onPlayerReady: function(e) { + + } + + + }, + + vimeo: { + + get: function(m) { + VMM.master_config.vimeo.que.push(m); + VMM.master_config.vimeo.active = true; + }, + + create: function(m, callback) { + trace("VIMEO CREATE"); + + // THUMBNAIL + var thumb_url = "http://vimeo.com/api/v2/video/" + m.id + ".json", + video_url = "http://player.vimeo.com/video/" + m.id + "?title=0&amp;byline=0&amp;portrait=0&amp;color=ffffff"; + + VMM.getJSON(thumb_url, function(d) { + VMM.ExternalAPI.vimeo.createThumb(d, m); + callback(); + }); + + + // VIDEO + VMM.attachElement("#" + m.uid, "<iframe autostart='false' frameborder='0' width='100%' height='100%' src='" + video_url + "'></iframe>"); + + }, + + createThumb: function(d, m) { + trace("VIMEO CREATE THUMB"); + var thumb_id = "#" + m.uid + "_thumb"; + VMM.attachElement(thumb_id, "<img src='" + d[0].thumbnail_small + "'>"); + }, + + pushQue: function() { + if (VMM.master_config.vimeo.que.length > 0) { + VMM.ExternalAPI.vimeo.create(VMM.master_config.vimeo.que[0], VMM.ExternalAPI.vimeo.pushQue); + VMM.master_config.vimeo.que.remove(0); + } + } + + }, + + webthumb: { + + get: function(m, thumb) { + VMM.master_config.webthumb.que.push(m); + VMM.master_config.webthumb.active = true; + }, + + sizes: function(s) { + var _size = ""; + if (s <= 150) { + _size = "t"; + } else if (s <= 306) { + _size = "m"; + } else { + _size = "l"; + } + + return _size; + }, + + create: function(m) { + trace("WEB THUMB CREATE"); + + var thumb_url = "http://free.pagepeeker.com/v2/thumbs.php?"; + url = m.id.replace("http://", "");//.split("/")[0]; + + // Main Image + VMM.attachElement("#" + m.uid, "<a href='" + m.id + "' target='_blank'><img src='" + thumb_url + "size=x&url=" + url + "'></a>"); + + // Thumb + VMM.attachElement("#" + m.uid + "_thumb", "<a href='" + m.id + "' target='_blank'><img src='" + thumb_url + "size=t&url=" + url + "'></a>"); + }, + + pushQue: function() { + for(var i = 0; i < VMM.master_config.webthumb.que.length; i++) { + VMM.ExternalAPI.webthumb.create(VMM.master_config.webthumb.que[i]); + } + VMM.master_config.webthumb.que = []; + } + } + + }).init(); + +} + +/* YOUTUBE API READY + Can't find a way to customize this callback and keep it in the VMM namespace + Youtube wants it to be this function. +================================================== */ +function onYouTubePlayerAPIReady() { + trace("GLOBAL YOUTUBE API CALLED") + VMM.ExternalAPI.youtube.onAPIReady(); +} + +/* ********************************************** + Begin VMM.MediaElement.js +********************************************** */ + +/* MediaElement +================================================== */ +if(typeof VMM != 'undefined' && typeof VMM.MediaElement == 'undefined') { + + VMM.MediaElement = ({ + + init: function() { + return this; + }, + + loadingmessage: function(m) { + return "<div class='vco-loading'><div class='vco-loading-container'><div class='vco-loading-icon'></div>" + "<div class='vco-message'><p>" + m + "</p></div></div></div>"; + }, + + thumbnail: function(data, w, h, uid) { + var _w = 16, + _h = 24, + _uid = ""; + + if (w != null && w != "") {_w = w}; + if (h != null && h != "") {_h = h}; + if (uid != null && uid != "") {_uid = uid}; + + if (data.media != null && data.media != "") { + var _valid = true, + mediaElem = "", + m = VMM.MediaType(data.media); //returns an object with .type and .id + + // DETERMINE THUMBNAIL OR ICON + if (data.thumbnail != null && data.thumbnail != "") { + trace("CUSTOM THUMB"); + mediaElem = "<div class='thumbnail thumb-custom' id='" + uid + "_custom_thumb'><img src='" + data.thumbnail + "'></div>"; + return mediaElem; + } else if (m.type == "image") { + mediaElem = "<div class='thumbnail thumb-photo'></div>"; + return mediaElem; + } else if (m.type == "flickr") { + mediaElem = "<div class='thumbnail thumb-photo' id='" + uid + "_thumb'></div>"; + return mediaElem; + } else if (m.type == "instagram") { + mediaElem = "<div class='thumbnail thumb-instagram' id='" + uid + "_thumb'><img src='" + VMM.ExternalAPI.instagram.get(m.id, true) + "'></div>"; + return mediaElem; + } else if (m.type == "youtube") { + mediaElem = "<div class='thumbnail thumb-youtube' id='" + uid + "_thumb'></div>"; + return mediaElem; + } else if (m.type == "googledoc") { + mediaElem = "<div class='thumbnail thumb-document'></div>"; + return mediaElem; + } else if (m.type == "vimeo") { + mediaElem = "<div class='thumbnail thumb-vimeo' id='" + uid + "_thumb'></div>"; + return mediaElem; + } else if (m.type == "dailymotion") { + mediaElem = "<div class='thumbnail thumb-video'></div>"; + return mediaElem; + } else if (m.type == "twitter"){ + mediaElem = "<div class='thumbnail thumb-twitter'></div>"; + return mediaElem; + } else if (m.type == "twitter-ready") { + mediaElem = "<div class='thumbnail thumb-twitter'></div>"; + return mediaElem; + } else if (m.type == "soundcloud") { + mediaElem = "<div class='thumbnail thumb-audio'></div>"; + return mediaElem; + } else if (m.type == "google-map") { + mediaElem = "<div class='thumbnail thumb-map'></div>"; + return mediaElem; + } else if (m.type == "googleplus") { + mediaElem = "<div class='thumbnail thumb-googleplus'></div>"; + return mediaElem; + } else if (m.type == "wikipedia") { + mediaElem = "<div class='thumbnail thumb-wikipedia'></div>"; + return mediaElem; + } else if (m.type == "storify") { + mediaElem = "<div class='thumbnail thumb-storify'></div>"; + return mediaElem; + } else if (m.type == "quote") { + mediaElem = "<div class='thumbnail thumb-quote'></div>"; + return mediaElem; + } else if (m.type == "unknown") { + if (m.id.match("blockquote")) { + mediaElem = "<div class='thumbnail thumb-quote'></div>"; + } else { + mediaElem = "<div class='thumbnail thumb-plaintext'></div>"; + } + return mediaElem; + } else if (m.type == "website") { + mediaElem = "<div class='thumbnail thumb-website' id='" + uid + "_thumb'></div>"; + return mediaElem; + } else { + mediaElem = "<div class='thumbnail thumb-plaintext'></div>"; + return mediaElem; + } + } + }, + + create: function(data, uid) { + var _valid = false, + //loading_messege = "<span class='messege'><p>" + VMM.master_config.language.messages.loading + "</p></span>"; + loading_messege = VMM.MediaElement.loadingmessage(VMM.master_config.language.messages.loading + "..."); + + if (data.media != null && data.media != "") { + var mediaElem = "", captionElem = "", creditElem = "", _id = "", isTextMedia = false, m; + + m = VMM.MediaType(data.media); //returns an object with .type and .id + m.uid = uid; + _valid = true; + + // CREDIT + if (data.credit != null && data.credit != "") { + creditElem = "<div class='credit'>" + VMM.Util.linkify_with_twitter(data.credit, "_blank") + "</div>"; + } + // CAPTION + if (data.caption != null && data.caption != "") { + captionElem = "<div class='caption'>" + VMM.Util.linkify_with_twitter(data.caption, "_blank") + "</div>"; + } + // IMAGE + if (m.type == "image") { + if (m.id.match("https://")) { + m.id = m.id.replace("https://","http://"); + } + mediaElem = "<div class='media-image media-shadow'><img src='" + m.id + "' class='media-image'></div>"; + // FLICKR + } else if (m.type == "flickr") { + //mediaElem = "<div class='media-image media-shadow' id='" + uid + "'>" + loading_messege + "</div>"; + mediaElem = "<div class='media-image media-shadow'><a href='" + m.link + "' target='_blank'><img id='" + uid + "'></a></div>"; + VMM.ExternalAPI.flickr.get(m); + // INSTAGRAM + } else if (m.type == "instagram") { + mediaElem = "<div class='media-image media-shadow'><a href='" + m.link + "' target='_blank'><img src='" + VMM.ExternalAPI.instagram.get(m) + "'></a></div>"; + //VMM.ExternalAPI.instagram.get(m.id, uid); + // GOOGLE DOCS + } else if (m.type == "googledoc") { + mediaElem = "<div class='media-frame media-shadow doc' id='" + m.uid + "'>" + loading_messege + "</div>"; + VMM.ExternalAPI.googledocs.get(m); + // YOUTUBE + } else if (m.type == "youtube") { + mediaElem = "<div class='media-shadow'><div class='media-frame video youtube' id='" + m.uid + "'>" + loading_messege + "</div></div>"; + VMM.ExternalAPI.youtube.get(m); + // VIMEO + } else if (m.type == "vimeo") { + mediaElem = "<div class='media-shadow media-frame video vimeo' id='" + m.uid + "'>" + loading_messege + "</div>"; + VMM.ExternalAPI.vimeo.get(m); + // DAILYMOTION + } else if (m.type == "dailymotion") { + mediaElem = "<div class='media-shadow'><iframe class='media-frame video dailymotion' autostart='false' frameborder='0' width='100%' height='100%' src='http://www.dailymotion.com/embed/video/" + m.id + "'></iframe></div>"; + // TWITTER + } else if (m.type == "twitter"){ + mediaElem = "<div class='twitter' id='" + m.uid + "'>" + loading_messege + "</div>"; + isTextMedia = true; + VMM.ExternalAPI.twitter.get(m); + // TWITTER + } else if (m.type == "twitter-ready") { + isTextMedia = true; + mediaElem = m.id; + // SOUNDCLOUD + } else if (m.type == "soundcloud") { + mediaElem = "<div class='media-frame media-shadow soundcloud' id='" + m.uid + "'>" + loading_messege + "</div>"; + VMM.ExternalAPI.soundcloud.get(m); + // GOOGLE MAPS + } else if (m.type == "google-map") { + mediaElem = "<div class='media-frame media-shadow map' id='" + m.uid + "'>" + loading_messege + "</div>"; + VMM.ExternalAPI.googlemaps.get(m); + // GOOGLE PLUS + } else if (m.type == "googleplus") { + _id = "googleplus_" + m.id; + mediaElem = "<div class='googleplus' id='" + _id + "'>" + loading_messege + "</div>"; + isTextMedia = true; + VMM.ExternalAPI.googleplus.get(m); + // WIKIPEDIA + } else if (m.type == "wikipedia") { + mediaElem = "<div class='wikipedia' id='" + m.uid + "'>" + loading_messege + "</div>"; + isTextMedia = true; + VMM.ExternalAPI.wikipedia.get(m); + // STORIFY + } else if (m.type == "storify") { + isTextMedia = true; + mediaElem = "<div class='plain-text-quote'>" + m.id + "</div>"; + // QUOTE + } else if (m.type == "quote") { + isTextMedia = true; + mediaElem = "<div class='plain-text-quote'>" + m.id + "</div>"; + // UNKNOWN + } else if (m.type == "unknown") { + trace("NO KNOWN MEDIA TYPE FOUND TRYING TO JUST PLACE THE HTML"); + isTextMedia = true; + mediaElem = "<div class='plain-text'><div class='container'>" + VMM.Util.properQuotes(m.id) + "</div></div>"; + // WEBSITE + } else if (m.type == "website") { + + mediaElem = "<div class='media-shadow website' id='" + m.uid + "'>" + loading_messege + "</div>"; + VMM.ExternalAPI.webthumb.get(m); + //mediaElem = "<div class='media-shadow website'><a href='" + m.id + "' target='_blank'>" + "<img src='http://api1.thumbalizr.com/?url=" + m.id.replace(/[\./]$/g, "") + "&width=300' class='media-image'></a></div>"; + + // NO MATCH + } else { + trace("NO KNOWN MEDIA TYPE FOUND"); + trace(m.type); + } + + // WRAP THE MEDIA ELEMENT + mediaElem = "<div class='media-container' >" + mediaElem + creditElem + captionElem + "</div>"; + // RETURN + if (isTextMedia) { + return "<div class='text-media'><div class='media-wrapper'>" + mediaElem + "</div></div>"; + } else { + return "<div class='media-wrapper'>" + mediaElem + "</div>"; + } + + }; + + } + + }).init(); +} + +/* ********************************************** + Begin VMM.MediaType.js +********************************************** */ + +/* MediaType + Determines the type of media the url string is. + returns an object with .type and .id + the id is a key piece of information needed to make + the request of the api. +================================================== */ +if(typeof VMM != 'undefined' && typeof VMM.MediaType == 'undefined') { + + VMM.MediaType = function(_d) { + var d = _d.replace(/^\s\s*/, '').replace(/\s\s*$/, ''), + success = false, + media = { + type: "unknown", + id: "", + start: 0, + hd: false, + link: "", + lang: VMM.Language.lang, + uniqueid: VMM.Util.unique_ID(6) + }; + + if (d.match("div class='twitter'")) { + media.type = "twitter-ready"; + media.id = d; + success = true; + } else if (d.match('(www.)?youtube|youtu\.be')) { + if (d.match('v=')) { + media.id = VMM.Util.getUrlVars(d)["v"]; + } else if (d.match('\/embed\/')) { + media.id = d.split("embed\/")[1].split(/[?&]/)[0]; + } else if (d.match(/v\/|v=|youtu\.be\//)){ + media.id = d.split(/v\/|v=|youtu\.be\//)[1].split(/[?&]/)[0]; + } else { + trace("YOUTUBE IN URL BUT NOT A VALID VIDEO"); + } + media.start = VMM.Util.getUrlVars(d)["t"]; + media.hd = VMM.Util.getUrlVars(d)["hd"]; + media.type = "youtube"; + success = true; + } else if (d.match('(player.)?vimeo\.com')) { + media.type = "vimeo"; + media.id = d.split(/video\/|\/\/vimeo\.com\//)[1].split(/[?&]/)[0];; + success = true; + } else if (d.match('(www.)?dailymotion\.com')) { + media.id = d.split(/video\/|\/\/dailymotion\.com\//)[1]; + media.type = "dailymotion"; + success = true; + } else if (d.match('(player.)?soundcloud\.com')) { + media.type = "soundcloud"; + media.id = d; + success = true; + } else if (d.match('(www.)?twitter\.com') && d.match('status') ) { + if (d.match("status\/")) { + media.id = d.split("status\/")[1]; + } else if (d.match("statuses\/")) { + media.id = d.split("statuses\/")[1]; + } else { + media.id = ""; + } + media.type = "twitter"; + success = true; + } else if (d.match("maps.google") && !d.match("staticmap")) { + media.type = "google-map"; + media.id = d.split(/src=['|"][^'|"]*?['|"]/gi); + success = true; + } else if (d.match("plus.google")) { + media.type = "googleplus"; + media.id = d.split("/posts/")[1]; + //https://plus.google.com/u/0/112374836634096795698/posts/bRJSvCb5mUU + //https://plus.google.com/107096716333816995401/posts/J5iMpEDHWNL + if (d.split("/posts/")[0].match("u/0/")) { + media.user = d.split("u/0/")[1].split("/posts")[0]; + } else { + media.user = d.split("google.com/")[1].split("/posts/")[0]; + } + success = true; + } else if (d.match("flickr.com/photos")) { + media.type = "flickr"; + media.id = d.split("photos\/")[1].split("/")[1]; + media.link = d; + success = true; + } else if (d.match("instagr.am/p/")) { + media.type = "instagram"; + media.link = d; + media.id = d.split("\/p\/")[1].split("/")[0]; + success = true; + } else if (d.match(/jpg|jpeg|png|gif/i) || d.match("staticmap") || d.match("yfrog.com") || d.match("twitpic.com")) { + media.type = "image"; + media.id = d; + success = true; + } else if (VMM.FileExtention.googleDocType(d)) { + media.type = "googledoc"; + media.id = d; + success = true; + } else if (d.match('(www.)?wikipedia\.org')) { + media.type = "wikipedia"; + //media.id = d.split("wiki\/")[1]; + var wiki_id = d.split("wiki\/")[1].split("#")[0].replace("_", " "); + media.id = wiki_id.replace(" ", "%20"); + media.lang = d.split("//")[1].split(".wikipedia")[0]; + success = true; + } else if (d.indexOf('http://') == 0) { + media.type = "website"; + media.id = d; + success = true; + } else if (d.match('storify')) { + media.type = "storify"; + media.id = d; + success = true; + } else if (d.match('blockquote')) { + media.type = "quote"; + media.id = d; + success = true; + } else { + trace("unknown media"); + media.type = "unknown"; + media.id = d; + success = true; + } + + if (success) { + return media; + } else { + trace("No valid media id detected"); + trace(d); + } + return false; + } +} + +/* ********************************************** + Begin VMM.TextElement.js +********************************************** */ + +/* TextElement +================================================== */ +if(typeof VMM != 'undefined' && typeof VMM.TextElement == 'undefined') { + + VMM.TextElement = ({ + + init: function() { + return this; + }, + + create: function(data) { + return data; + } + + }).init(); +} + +/* ********************************************** + Begin VMM.Media.js +********************************************** */ + +/* Media +================================================== */ + +/* * CodeKit Import + * http://incident57.com/codekit/ +================================================== */ +// @codekit-prepend "VMM.ExternalAPI.js"; +// @codekit-prepend "VMM.MediaElement.js"; +// @codekit-prepend "VMM.MediaType.js"; +// @codekit-prepend "VMM.TextElement.js"; + + +/* ********************************************** + Begin VMM.DragSlider.js +********************************************** */ + +/* DRAG SLIDER +================================================== */ +if(typeof VMM != 'undefined' && typeof VMM.DragSlider == 'undefined') { + + VMM.DragSlider = function() { + var drag = { + element: "", + element_move: "", + constraint: "", + sliding: false, + pagex: { + start: 0, + end: 0 + }, + left: { + start: 0, + end: 0 + }, + time: { + start: 0, + end: 0 + }, + touch: false, + ease: "easeOutExpo" + }, + dragevent = { + down: "mousedown", + up: "mouseup", + leave: "mouseleave", + move: "mousemove" + }, + mousedrag = { + down: "mousedown", + up: "mouseup", + leave: "mouseleave", + move: "mousemove" + }, + touchdrag = { + down: "touchstart", + up: "touchend", + leave: "mouseleave", + move: "touchmove" + }, + dragslider = this, + is_sticky = false; + + /* PUBLIC FUNCTIONS + ================================================== */ + this.createPanel = function(drag_object, move_object, constraint, touch, sticky) { + drag.element = drag_object; + drag.element_move = move_object; + //dragslider = drag_object; + if ( sticky != null && sticky != "") { + is_sticky = sticky; + } + if ( constraint != null && constraint != "") { + drag.constraint = constraint; + } else { + drag.constraint = false; + } + if ( touch) { + drag.touch = touch; + } else { + drag.touch = false; + } + trace("TOUCH" + drag.touch); + if (drag.touch) { + dragevent = touchdrag; + } else { + dragevent = mousedrag; + } + + makeDraggable(drag.element, drag.element_move); + } + + this.updateConstraint = function(constraint) { + trace("updateConstraint"); + drag.constraint = constraint; + } + + this.cancelSlide = function(e) { + VMM.unbindEvent(drag.element, onDragMove, dragevent.move); + return true; + } + + /* PRIVATE FUNCTIONS + ================================================== */ + function makeDraggable(drag_object, move_object) { + + VMM.bindEvent(drag_object, onDragStart, dragevent.down, {element: move_object, delement: drag_object}); + VMM.bindEvent(drag_object, onDragEnd, dragevent.up, {element: move_object, delement: drag_object}); + VMM.bindEvent(drag_object, onDragLeave, dragevent.leave, {element: move_object, delement: drag_object}); + + } + + function onDragLeave(e) { + VMM.unbindEvent(e.data.delement, onDragMove, dragevent.move); + if (!drag.touch) { + e.preventDefault(); + } + e.stopPropagation(); + if (drag.sliding) { + drag.sliding = false; + dragEnd(e.data.element, e.data.delement, e); + return false; + } else { + return true; + } + } + + function onDragStart(e) { + dragStart(e.data.element, e.data.delement, e); + if (!drag.touch) { + e.preventDefault(); + } + e.stopPropagation(); + return true; + } + + function onDragEnd(e) { + if (!drag.touch) { + e.preventDefault(); + } + e.stopPropagation(); + if (drag.sliding) { + drag.sliding = false; + dragEnd(e.data.element, e.data.delement, e); + return false; + } else { + return true; + } + } + + function onDragMove(e) { + dragMove(e.data.element, e); + + return false; + } + + function dragStart(elem, delem, e) { + if (drag.touch) { + trace("IS TOUCH") + VMM.Lib.css(elem, '-webkit-transition-duration', '0'); + drag.pagex.start = e.originalEvent.touches[0].screenX; + } else { + drag.pagex.start = e.pageX; + } + drag.left.start = getLeft(elem); + drag.time.start = new Date().getTime(); + + VMM.Lib.stop(elem); + VMM.bindEvent(delem, onDragMove, dragevent.move, {element: elem}); + + } + + function dragEnd(elem, delem, e) { + VMM.unbindEvent(delem, onDragMove, dragevent.move); + dragMomentum(elem, e); + } + + function dragMove(elem, e) { + var drag_to; + drag.sliding = true; + if (drag.touch) { + drag.pagex.end = e.originalEvent.touches[0].screenX; + } else { + drag.pagex.end = e.pageX; + } + drag.left.end = getLeft(elem); + drag_to = -(drag.pagex.start - drag.pagex.end - drag.left.start); + + if (Math.abs(drag_to - drag.left.start) > 10) { + VMM.Lib.css(elem, 'left', drag_to); + e.preventDefault(); + e.stopPropagation(); + } + } + + function dragMomentum(elem, e) { + var drag_info = { + left: drag.left.end, + left_adjust: 0, + change: { + x: 0 + }, + time: (new Date().getTime() - drag.time.start) * 10, + time_adjust: (new Date().getTime() - drag.time.start) * 10 + }, + multiplier = 3000; + + if (drag.touch) { + multiplier = 6000; + } + + drag_info.change.x = multiplier * (Math.abs(drag.pagex.end) - Math.abs(drag.pagex.start)); + + + drag_info.left_adjust = Math.round(drag_info.change.x / drag_info.time); + + drag_info.left = Math.min(drag_info.left + drag_info.left_adjust); + + if (drag.constraint) { + if (drag_info.left > drag.constraint.left) { + drag_info.left = drag.constraint.left; + if (drag_info.time > 5000) { + drag_info.time = 5000; + } + } else if (drag_info.left < drag.constraint.right) { + drag_info.left = drag.constraint.right; + if (drag_info.time > 5000) { + drag_info.time = 5000; + } + } + } + + VMM.fireEvent(dragslider, "DRAGUPDATE", [drag_info]); + + if (!is_sticky) { + if (drag_info.time > 0) { + if (drag.touch) { + VMM.Lib.animate(elem, drag_info.time, "easeOutCirc", {"left": drag_info.left}); + } else { + VMM.Lib.animate(elem, drag_info.time, drag.ease, {"left": drag_info.left}); + } + } + } + } + + function getLeft(elem) { + return parseInt(VMM.Lib.css(elem, 'left').substring(0, VMM.Lib.css(elem, 'left').length - 2), 10); + } + + } +} + +/* ********************************************** + Begin VMM.Slider.js +********************************************** */ + +/* Slider +================================================== */ +/* * CodeKit Import + * http://incident57.com/codekit/ +================================================== */ +// @codekit-append "VMM.Slider.Slide.js"; + +if(typeof VMM != 'undefined' && typeof VMM.Slider == 'undefined') { + + VMM.Slider = function(parent, parent_config) { + + var config, + timer, + $slider, + $slider_mask, + $slider_container, + $slides_items, + $dragslide, + $explainer, + events = {}, + data = [], + slides = [], + slide_positions = [], + slides_content = "", + current_slide = 0, + current_width = 960, + touch = { + move: false, + x: 10, + y: 0, + off: 0, + dampen: 48 + }, + content = "", + _active = false, + layout = parent, + navigation = { + nextBtn: "", + prevBtn: "", + nextDate: "", + prevDate: "", + nextTitle: "", + prevTitle: "" + }; + + // CONFIG + if(typeof parent_config != 'undefined') { + config = parent_config; + } else { + config = { + preload: 4, + current_slide: 0, + interval: 10, + something: 0, + width: 720, + height: 400, + ease: "easeInOutExpo", + duration: 1000, + timeline: false, + spacing: 15, + slider: { + width: 720, + height: 400, + content: { + width: 720, + height: 400, + padding: 120, + padding_default: 120 + }, + nav: { + width: 100, + height: 200 + } + } + }; + } + + /* PUBLIC VARS + ================================================== */ + this.ver = "0.6"; + + config.slider.width = config.width; + config.slider.height = config.height; + + /* PUBLIC FUNCTIONS + ================================================== */ + this.init = function(d) { + slides = []; + slide_positions = []; + + if(typeof d != 'undefined') { + this.setData(d); + } else { + trace("WAITING ON DATA"); + } + }; + + this.width = function(w) { + if (w != null && w != "") { + config.slider.width = w; + reSize(); + } else { + return config.slider.width; + } + } + + this.height = function(h) { + if (h != null && h != "") { + config.slider.height = h; + reSize(); + } else { + return config.slider.height; + } + } + + /* GETTERS AND SETTERS + ================================================== */ + this.setData = function(d) { + if(typeof d != 'undefined') { + data = d; + build(); + } else{ + trace("NO DATA"); + } + }; + + this.getData = function() { + return data; + }; + + this.setConfig = function(d) { + if(typeof d != 'undefined') { + config = d; + } else{ + trace("NO CONFIG DATA"); + } + } + + this.getConfig = function() { + return config; + }; + + this.setSize = function(w, h) { + if (w != null) {config.slider.width = w}; + if (h != null) {config.slider.height = h}; + if (_active) { + reSize(); + } + + } + + this.active = function() { + return _active; + }; + + this.getCurrentNumber = function() { + return current_slide; + }; + + this.setSlide = function(n) { + goToSlide(n); + }; + + /* ON EVENT + ================================================== */ + function onConfigSet() { + trace("onConfigSet"); + }; + + function reSize(go_to_slide, from_start) { + var _go_to_slide = true, + _from_start = false; + + if (go_to_slide != null) {_go_to_slide = go_to_slide}; + if (from_start != null) {_from_start = from_start}; + + current_width = config.slider.width; + + config.slider.nav.height = VMM.Lib.height(navigation.prevBtnContainer); + + // Handle smaller sizes + if (VMM.Browser.device == "mobile" || current_width <= 640) { + config.slider.content.padding = 10; + } else { + config.slider.content.padding = config.slider.content.padding_default; + } + + config.slider.content.width = current_width - (config.slider.content.padding *2); + + VMM.Lib.width($slides_items, (slides.length * config.slider.content.width)); + + if (_from_start) { + VMM.Lib.css($slider_container, "left", slides[current_slide].leftpos()); + } + + // RESIZE SLIDES + sizeSlides(); + + // POSITION SLIDES + positionSlides(); + + // POSITION NAV + VMM.Lib.css(navigation.nextBtn, "left", (current_width - config.slider.nav.width)); + VMM.Lib.height(navigation.prevBtn, config.slider.height); + VMM.Lib.height(navigation.nextBtn, config.slider.height); + VMM.Lib.css(navigation.nextBtnContainer, "top", ( (config.slider.height/2) - (config.slider.nav.height/2) ) + 10 ); + VMM.Lib.css(navigation.prevBtnContainer, "top", ( (config.slider.height/2) - (config.slider.nav.height/2) ) + 10 ); + + // Animate Changes + VMM.Lib.height($slider_mask, config.slider.height); + VMM.Lib.width($slider_mask, current_width); + + if (_go_to_slide) { + goToSlide(current_slide, "linear", 1); + }; + + if (current_slide == 0) { + VMM.Lib.visible(navigation.prevBtn, false); + } + + } + + function onDragFinish(e, d) { + trace("DRAG FINISH"); + trace(d.left_adjust); + trace((config.slider.width / 2)); + + if (d.left_adjust < 0 ) { + if (Math.abs(d.left_adjust) > (config.slider.width / 2) ) { + //onNextClick(e); + if (current_slide == slides.length - 1) { + backToCurrentSlide(); + } else { + goToSlide(current_slide+1, "easeOutExpo"); + upDate(); + } + } else { + backToCurrentSlide(); + + } + } else if (Math.abs(d.left_adjust) > (config.slider.width / 2) ) { + if (current_slide == 0) { + backToCurrentSlide(); + } else { + goToSlide(current_slide-1, "easeOutExpo"); + upDate(); + } + } else { + backToCurrentSlide(); + } + + + + } + /* NAVIGATION + ================================================== */ + function onNextClick(e) { + if (current_slide == slides.length - 1) { + backToCurrentSlide(); + } else { + goToSlide(current_slide+1); + upDate(); + } + } + + function onPrevClick(e) { + if (current_slide == 0) { + backToCurrentSlide(); + } else { + goToSlide(current_slide-1); + upDate(); + } + } + + function onKeypressNav(e) { + switch(e.keyCode) { + case 39: + // RIGHT ARROW + onNextClick(e); + break; + case 37: + // LEFT ARROW + onPrevClick(e); + break; + } + } + + function onTouchUpdate(e, b) { + if (slide_positions.length == 0) { + for(var i = 0; i < slides.length; i++) { + slide_positions.push( slides[i].leftpos() ); + } + } + if (typeof b.left == "number") { + var _pos = b.left; + var _slide_pos = -(slides[current_slide].leftpos()); + if (_pos < _slide_pos - (config.slider_width/3)) { + onNextClick(); + } else if (_pos > _slide_pos + (config.slider_width/3)) { + onPrevClick(); + } else { + VMM.Lib.animate($slider_container, config.duration, config.ease, {"left": _slide_pos }); + } + } else { + VMM.Lib.animate($slider_container, config.duration, config.ease, {"left": _slide_pos }); + } + + if (typeof b.top == "number") { + VMM.Lib.animate($slider_container, config.duration, config.ease, {"top": -b.top}); + } else { + + } + }; + + function onExplainerClick(e) { + detachMessege(); + } + + /* UPDATE + ================================================== */ + function upDate() { + config.current_slide = current_slide; + VMM.fireEvent(layout, "UPDATE"); + }; + + /* GET DATA + ================================================== */ + function getData(d) { + data = d; + }; + + /* BUILD SLIDES + ================================================== */ + function buildSlides(d) { + var i = 0; + + VMM.attachElement($slides_items, ""); + slides = []; + + for(i = 0; i < d.length; i++) { + var _slide = new VMM.Slider.Slide(d[i], $slides_items); + //_slide.show(); + slides.push(_slide); + } + } + + function preloadSlides(skip) { + var i = 0; + + if (skip) { + preloadTimeOutSlides(); + } else { + for(i = 0; i < slides.length; i++) { + slides[i].clearTimers(); + } + timer = setTimeout(preloadTimeOutSlides, config.duration); + + } + } + + function preloadTimeOutSlides() { + var i = 0; + + for(i = 0; i < slides.length; i++) { + slides[i].enqueue = true; + } + + for(i = 0; i < config.preload; i++) { + if ( !((current_slide + i) > slides.length - 1)) { + slides[current_slide + i].show(); + slides[current_slide + i].enqueue = false; + } + if ( !( (current_slide - i) < 0 ) ) { + slides[current_slide - i].show(); + slides[current_slide - i].enqueue = false; + } + } + + if (slides.length > 50) { + for(i = 0; i < slides.length; i++) { + if (slides[i].enqueue) { + slides[i].hide(); + } + } + } + + sizeSlides(); + } + + function sizeSlide(slide_id) { + + } + + /* SIZE SLIDES + ================================================== */ + function sizeSlides() { + var i = 0, + layout_text_media = ".slider-item .layout-text-media .media .media-container ", + layout_media = ".slider-item .layout-media .media .media-container ", + layout_both = ".slider-item .media .media-container", + layout_caption = ".slider-item .media .media-container .media-shadow .caption", + is_skinny = false, + mediasize = { + text_media: { + width: (config.slider.content.width/100) * 60, + height: config.slider.height - 60, + video: { + width: 0, + height: 0 + }, + text: { + width: ((config.slider.content.width/100) * 40) - 30, + height: config.slider.height + } + }, + media: { + width: config.slider.content.width, + height: config.slider.height - 110, + video: { + width: 0, + height: 0 + } + } + }; + + // Handle smaller sizes + if (VMM.Browser.device == "mobile" || current_width < 641) { + is_skinny = true; + + } + + VMM.master_config.sizes.api.width = mediasize.media.width; + VMM.master_config.sizes.api.height = mediasize.media.height; + + mediasize.text_media.video = VMM.Util.ratio.fit(mediasize.text_media.width, mediasize.text_media.height, 16, 9); + mediasize.media.video = VMM.Util.ratio.fit(mediasize.media.width, mediasize.media.height, 16, 9); + + VMM.Lib.css(".slider-item", "width", config.slider.content.width ); + VMM.Lib.height(".slider-item", config.slider.height); + + + + if (is_skinny) { + + mediasize.text_media.width = config.slider.content.width - (config.slider.content.padding*2); + mediasize.media.width = config.slider.content.width - (config.slider.content.padding*2); + mediasize.text_media.height = ((config.slider.height/100) * 50 ) - 50; + mediasize.media.height = ((config.slider.height/100) * 70 ) - 40; + + mediasize.text_media.video = VMM.Util.ratio.fit(mediasize.text_media.width, mediasize.text_media.height, 16, 9); + mediasize.media.video = VMM.Util.ratio.fit(mediasize.media.width, mediasize.media.height, 16, 9); + + VMM.Lib.css(".slider-item .layout-text-media .text", "width", "100%" ); + VMM.Lib.css(".slider-item .layout-text-media .text", "display", "block" ); + VMM.Lib.css(".slider-item .layout-text-media .text .container", "display", "block" ); + VMM.Lib.css(".slider-item .layout-text-media .text .container", "width", mediasize.media.width ); + VMM.Lib.css(".slider-item .layout-text-media .text .container .start", "width", "auto" ); + + VMM.Lib.css(".slider-item .layout-text-media .media", "float", "none" ); + VMM.Lib.addClass(".slider-item .content-container", "pad-top"); + + VMM.Lib.css(".slider-item .media blockquote p", "line-height", "18px" ); + VMM.Lib.css(".slider-item .media blockquote p", "font-size", "16px" ); + + VMM.Lib.css(".slider-item", "overflow-y", "auto" ); + + + } else { + + VMM.Lib.css(".slider-item .layout-text-media .text", "width", "40%" ); + VMM.Lib.css(".slider-item .layout-text-media .text", "display", "table-cell" ); + VMM.Lib.css(".slider-item .layout-text-media .text .container", "display", "table-cell" ); + VMM.Lib.css(".slider-item .layout-text-media .text .container", "width", "auto" ); + VMM.Lib.css(".slider-item .layout-text-media .text .container .start", "width", mediasize.text_media.text.width ); + //VMM.Lib.addClass(".slider-item .content-container", "pad-left"); + VMM.Lib.removeClass(".slider-item .content-container", "pad-top"); + + VMM.Lib.css(".slider-item .layout-text-media .media", "float", "left" ); + VMM.Lib.css(".slider-item .layout-text-media", "display", "table" ); + + VMM.Lib.css(".slider-item .media blockquote p", "line-height", "36px" ); + VMM.Lib.css(".slider-item .media blockquote p", "font-size", "28px" ); + + VMM.Lib.css(".slider-item", "display", "table" ); + VMM.Lib.css(".slider-item", "overflow-y", "auto" ); + } + + // MEDIA FRAME + VMM.Lib.css( layout_text_media + ".media-frame", "max-width", mediasize.text_media.width); + VMM.Lib.height( layout_text_media + ".media-frame", mediasize.text_media.height); + VMM.Lib.width( layout_text_media + ".media-frame", mediasize.text_media.width); + + // WEBSITES + //VMM.Lib.css( layout_both + ".website", "max-width", 300 ); + + // IMAGES + VMM.Lib.css( layout_text_media + "img", "max-height", mediasize.text_media.height ); + VMM.Lib.css( layout_media + "img", "max-height", mediasize.media.height ); + + // FIX FOR NON-WEBKIT BROWSERS + VMM.Lib.css( layout_text_media + "img", "max-width", mediasize.text_media.width ); + VMM.Lib.css( layout_text_media + ".avatar img", "max-width", 32 ); + VMM.Lib.css( layout_text_media + ".avatar img", "max-height", 32 ); + VMM.Lib.css( layout_media + ".avatar img", "max-width", 32 ); + VMM.Lib.css( layout_media + ".avatar img", "max-height", 32 ); + + VMM.Lib.css( layout_text_media + ".article-thumb", "max-width", "50%" ); + //VMM.Lib.css( layout_text_media + ".article-thumb", "max-height", 100 ); + VMM.Lib.css( layout_media + ".article-thumb", "max-width", 200 ); + //VMM.Lib.css( layout_media + ".article-thumb", "max-height", 100 ); + + + // IFRAME FULL SIZE VIDEO + VMM.Lib.width( layout_text_media + ".media-frame", mediasize.text_media.video.width); + VMM.Lib.height( layout_text_media + ".media-frame", mediasize.text_media.video.height); + VMM.Lib.width( layout_media + ".media-frame", mediasize.media.video.width); + VMM.Lib.height( layout_media + ".media-frame", mediasize.media.video.height); + VMM.Lib.css( layout_media + ".media-frame", "max-height", mediasize.media.video.height); + VMM.Lib.css( layout_media + ".media-frame", "max-width", mediasize.media.video.width); + + // SOUNDCLOUD + VMM.Lib.height( layout_media + ".soundcloud", 168); + VMM.Lib.height( layout_text_media + ".soundcloud", 168); + VMM.Lib.width( layout_media + ".soundcloud", mediasize.media.width); + VMM.Lib.width( layout_text_media + ".soundcloud", mediasize.text_media.width); + VMM.Lib.css( layout_both + ".soundcloud", "max-height", 168 ); + + // MAPS + VMM.Lib.height( layout_text_media + ".map", mediasize.text_media.height); + VMM.Lib.width( layout_text_media + ".map", mediasize.text_media.width); + VMM.Lib.css( layout_media + ".map", "max-height", mediasize.media.height); + VMM.Lib.width( layout_media + ".map", mediasize.media.width); + + + // DOCS + VMM.Lib.height( layout_text_media + ".doc", mediasize.text_media.height); + VMM.Lib.width( layout_text_media + ".doc", mediasize.text_media.width); + VMM.Lib.height( layout_media + ".doc", mediasize.media.height); + VMM.Lib.width( layout_media + ".doc", mediasize.media.width); + + // IE8 NEEDS THIS + VMM.Lib.width( layout_media + ".wikipedia", mediasize.media.width); + VMM.Lib.width( layout_media + ".twitter", mediasize.media.width); + VMM.Lib.width( layout_media + ".plain-text-quote", mediasize.media.width); + VMM.Lib.width( layout_media + ".plain-text", mediasize.media.width); + + VMM.Lib.css( layout_both, "max-width", mediasize.media.width); + + + // CAPTION WIDTH + VMM.Lib.css( layout_text_media + ".caption", "max-width", mediasize.text_media.video.width); + VMM.Lib.css( layout_media + ".caption", "max-width", mediasize.media.video.width); + //VMM.Lib.css( layout_text_media + ".caption", "max-width", mediasize.text_media.width); + //VMM.Lib.css( layout_media + ".caption", "max-width", mediasize.media.width); + + // MAINTAINS VERTICAL CENTER IF IT CAN + for(i = 0; i < slides.length; i++) { + + slides[i].layout(is_skinny); + + if (slides[i].content_height() > config.slider.height + 20) { + slides[i].css("display", "block"); + } else { + slides[i].css("display", "table"); + } + } + + } + + /* POSITION SLIDES + ================================================== */ + function positionSlides() { + var pos = 0, + i = 0; + + for(i = 0; i < slides.length; i++) { + pos = i * (config.slider.width+config.spacing); + slides[i].leftpos(pos); + } + } + + /* OPACITY SLIDES + ================================================== */ + function opacitySlides(n) { + var _ease = "linear", + i = 0; + + for(i = 0; i < slides.length; i++) { + if (i == current_slide) { + slides[i].animate(config.duration, _ease, {"opacity": 1}); + } else if (i == current_slide - 1 || i == current_slide + 1) { + slides[i].animate(config.duration, _ease, {"opacity": 0.1}); + } else { + slides[i].opacity(n); + } + } + } + + /* GO TO SLIDE + goToSlide(n, ease, duration); + ================================================== */ + function goToSlide(n, ease, duration, fast, firstrun) { + var _ease = config.ease, + _duration = config.duration, + is_last = false, + is_first = false, + _title = "", + _pos; + + /* STOP ANY VIDEO PLAYERS ACTIVE + ================================================== */ + VMM.ExternalAPI.youtube.stopPlayers(); + + // Set current slide + current_slide = n; + _pos = slides[current_slide].leftpos(); + + + if (current_slide == 0) {is_first = true}; + if (current_slide +1 >= slides.length) {is_last = true}; + if (ease != null && ease != "") {_ease = ease}; + if (duration != null && duration != "") {_duration = duration}; + + /* NAVIGATION + set proper nav titles and dates etc. + ================================================== */ + // Handle smaller sizes + if (VMM.Browser.device == "mobile") { + //if (VMM.Browser.device == "mobile" || current_width <= 640) { + VMM.Lib.visible(navigation.prevBtn, false); + VMM.Lib.visible(navigation.nextBtn, false); + } else { + if (is_first) { + VMM.Lib.visible(navigation.prevBtn, false); + } else { + VMM.Lib.visible(navigation.prevBtn, true); + _title = VMM.Util.unlinkify(data[current_slide - 1].title) + if (config.type == "timeline") { + if(typeof data[current_slide - 1].date === "undefined") { + VMM.attachElement(navigation.prevDate, _title); + VMM.attachElement(navigation.prevTitle, ""); + } else { + VMM.attachElement(navigation.prevDate, VMM.Date.prettyDate(data[current_slide - 1].startdate, false, data[current_slide - 1].precisiondate)); + VMM.attachElement(navigation.prevTitle, _title); + } + } else { + VMM.attachElement(navigation.prevTitle, _title); + } + + } + if (is_last) { + VMM.Lib.visible(navigation.nextBtn, false); + } else { + VMM.Lib.visible(navigation.nextBtn, true); + _title = VMM.Util.unlinkify(data[current_slide + 1].title); + if (config.type == "timeline") { + if(typeof data[current_slide + 1].date === "undefined") { + VMM.attachElement(navigation.nextDate, _title); + VMM.attachElement(navigation.nextTitle, ""); + } else { + VMM.attachElement(navigation.nextDate, VMM.Date.prettyDate(data[current_slide + 1].startdate, false, data[current_slide + 1].precisiondate) ); + VMM.attachElement(navigation.nextTitle, _title); + } + } else { + VMM.attachElement(navigation.nextTitle, _title); + } + + } + } + + + /* ANIMATE SLIDE + ================================================== */ + if (fast) { + VMM.Lib.css($slider_container, "left", -(_pos - config.slider.content.padding)); + } else{ + VMM.Lib.stop($slider_container); + VMM.Lib.animate($slider_container, _duration, _ease, {"left": -(_pos - config.slider.content.padding)}); + } + + if (firstrun) { + VMM.fireEvent(layout, "LOADED"); + } + + /* SET Vertical Scoll + ================================================== */ + if (slides[current_slide].height() > config.slider_height) { + VMM.Lib.css(".slider", "overflow-y", "scroll" ); + } else { + VMM.Lib.css(layout, "overflow-y", "hidden" ); + var scroll_height = 0; + try { + scroll_height = VMM.Lib.prop(layout, "scrollHeight"); + VMM.Lib.animate(layout, _duration, _ease, {scrollTop: scroll_height - VMM.Lib.height(layout) }); + } + catch(err) { + scroll_height = VMM.Lib.height(layout); + } + } + + preloadSlides(); + VMM.fireEvent($slider, "MESSAGE", "TEST"); + } + + function backToCurrentSlide() { + VMM.Lib.stop($slider_container); + VMM.Lib.animate($slider_container, config.duration, "easeOutExpo", {"left": -(slides[current_slide].leftpos()) + config.slider.content.padding} ); + } + + /* MESSEGES + ================================================== */ + function showMessege(e, msg, other) { + trace("showMessege " + msg); + //VMM.attachElement($timeline, $feedback); + VMM.attachElement($explainer, "<div class='vco-explainer'><div class='vco-explainer-container'><div class='vco-bezel'><div class='vco-gesture-icon'></div>" + "<div class='vco-message'><p>" + msg + "</p></div></div></div></div>"); + }; + + function hideMessege() { + VMM.Lib.animate($explainer, config.duration, config.ease, {"opacity": 0}, detachMessege); + }; + + function detachMessege() { + VMM.Lib.detach($explainer); + } + + /* BUILD NAVIGATION + ================================================== */ + function buildNavigation() { + + var temp_icon = "<div class='icon'>&nbsp;</div>"; + + navigation.nextBtn = VMM.appendAndGetElement($slider, "<div>", "nav-next"); + navigation.prevBtn = VMM.appendAndGetElement($slider, "<div>", "nav-previous"); + navigation.nextBtnContainer = VMM.appendAndGetElement(navigation.nextBtn, "<div>", "nav-container", temp_icon); + navigation.prevBtnContainer = VMM.appendAndGetElement(navigation.prevBtn, "<div>", "nav-container", temp_icon); + if (config.type == "timeline") { + navigation.nextDate = VMM.appendAndGetElement(navigation.nextBtnContainer, "<div>", "date", ""); + navigation.prevDate = VMM.appendAndGetElement(navigation.prevBtnContainer, "<div>", "date", ""); + } + navigation.nextTitle = VMM.appendAndGetElement(navigation.nextBtnContainer, "<div>", "title", ""); + navigation.prevTitle = VMM.appendAndGetElement(navigation.prevBtnContainer, "<div>", "title", ""); + + VMM.bindEvent(".nav-next", onNextClick); + VMM.bindEvent(".nav-previous", onPrevClick); + VMM.bindEvent(window, onKeypressNav, 'keydown'); + + } + + /* BUILD + ================================================== */ + function build() { + var __duration = 3000; + // Clear out existing content + VMM.attachElement(layout, ""); + + // Get DOM Objects to local objects + $slider = VMM.getElement(layout); + $slider_mask = VMM.appendAndGetElement($slider, "<div>", "slider-container-mask"); + $slider_container = VMM.appendAndGetElement($slider_mask, "<div>", "slider-container"); + $slides_items = VMM.appendAndGetElement($slider_container, "<div>", "slider-item-container"); + + + // BUILD NAVIGATION + buildNavigation(); + + // ATTACH SLIDES + buildSlides(data); + + /* MAKE SLIDER DRAGGABLE/TOUCHABLE + ================================================== */ + + if (VMM.Browser.device == "tablet" || VMM.Browser.device == "mobile") { + // Different Animation duration for touch + config.duration = 500; + __duration = 1000; + + // Make touchable + $dragslide = new VMM.DragSlider(); + $dragslide.createPanel($slider, $slider_container, "", config.touch, true); + VMM.bindEvent($dragslide, onDragFinish, 'DRAGUPDATE'); + + // EXPLAINER + $explainer = VMM.appendAndGetElement($slider_mask, "<div>", "vco-feedback", ""); + showMessege(null, "Swipe to Navigate"); + VMM.Lib.height($explainer, config.slider.height); + VMM.bindEvent($explainer, onExplainerClick); + VMM.bindEvent($explainer, onExplainerClick, 'touchend'); + } + + reSize(false, true); + + + VMM.Lib.visible(navigation.prevBtn, false); + goToSlide(config.current_slide, "easeOutExpo", __duration, true, true); + + _active = true; + }; + + }; + +} + + + + + + +/* ********************************************** + Begin VMM.Slider.Slide.js +********************************************** */ + +/* Slider Slide +================================================== */ + +if (typeof VMM.Slider != 'undefined') { + VMM.Slider.Slide = function(d, _parent) { + + var $media, $text, $slide, $wrap, element, c, + data = d, + slide = {}, + element = "", + media = "", + loaded = false, + preloaded = false, + is_skinny = false, + _enqueue = true, + _removeque = false, + _id = "slide_", + _class = 0, + timer = {pushque:"", render:"", relayout:"", remove:"", skinny:false}, + times = {pushque:500, render:100, relayout:100, remove:30000}; + + _id = _id + data.uniqueid; + this.enqueue = _enqueue; + this.id = _id; + + + element = VMM.appendAndGetElement(_parent, "<div>", "slider-item"); + + if (typeof data.classname != 'undefined') { + trace("HAS CLASSNAME"); + VMM.Lib.addClass(element, data.classname); + } else { + trace("NO CLASSNAME"); + trace(data); + } + + c = {slide:"", text: "", media: "", media_element: "", layout: "content-container layout", has: { headline: false, text: false, media: false }}; + + /* PUBLIC + ================================================== */ + this.show = function(skinny) { + _enqueue = false; + timer.skinny = skinny; + _removeque = false; + clearTimeout(timer.remove); + + if (!loaded) { + if (preloaded) { + clearTimeout(timer.relayout); + timer.relayout = setTimeout(reloadLayout, times.relayout); + } else { + render(skinny); + } + } + }; + + this.hide = function() { + if (loaded && !_removeque) { + _removeque = true; + clearTimeout(timer.remove); + timer.remove = setTimeout(removeSlide, times.remove); + } + }; + + this.clearTimers = function() { + //clearTimeout(timer.remove); + clearTimeout(timer.relayout); + clearTimeout(timer.pushque); + clearTimeout(timer.render); + }; + + this.layout = function(skinny) { + if (loaded && preloaded) { + reLayout(skinny); + } + }; + + this.elem = function() { + return element; + }; + + this.position = function() { + return VMM.Lib.position(element); + }; + + this.leftpos = function(p) { + if(typeof p != 'undefined') { + VMM.Lib.css(element, "left", p); + } else { + return VMM.Lib.position(element).left + } + }; + + this.animate = function(d, e, p) { + VMM.Lib.animate(element, d, e, p); + }; + + this.css = function(p, v) { + VMM.Lib.css(element, p, v ); + } + + this.opacity = function(p) { + VMM.Lib.css(element, "opacity", p); + } + + this.width = function() { + return VMM.Lib.width(element); + }; + + this.height = function() { + return VMM.Lib.height(element); + }; + + this.content_height = function () { + var ch = VMM.Lib.find( element, ".content")[0]; + + if (ch != 'undefined' && ch != null) { + return VMM.Lib.height(ch); + } else { + return 0; + } + } + + /* PRIVATE + ================================================== */ + var render = function(skinny) { + trace("RENDER " + _id); + + loaded = true; + preloaded = true; + timer.skinny = skinny; + + buildSlide(); + + clearTimeout(timer.pushque); + clearTimeout(timer.render); + timer.pushque = setTimeout(VMM.ExternalAPI.pushQues, times.pushque); + + }; + + var removeSlide = function() { + //VMM.attachElement(element, ""); + trace("REMOVE SLIDE TIMER FINISHED"); + loaded = false; + VMM.Lib.detach($text); + VMM.Lib.detach($media); + + }; + + var reloadLayout = function() { + loaded = true; + reLayout(timer.skinny, true); + }; + + var reLayout = function(skinny, reload) { + if (c.has.text) { + if (skinny) { + if (!is_skinny || reload) { + VMM.Lib.removeClass($slide, "pad-left"); + VMM.Lib.detach($text); + VMM.Lib.detach($media); + VMM.Lib.append($slide, $text); + VMM.Lib.append($slide, $media); + is_skinny = true; + } + } else { + if (is_skinny || reload) { + VMM.Lib.addClass($slide, "pad-left"); + VMM.Lib.detach($text); + VMM.Lib.detach($media); + VMM.Lib.append($slide, $media); + VMM.Lib.append($slide, $text); + is_skinny = false; + + } + } + } else if (reload) { + if (c.has.headline) { + VMM.Lib.detach($text); + VMM.Lib.append($slide, $text); + } + VMM.Lib.detach($media); + VMM.Lib.append($slide, $media); + } + } + + var buildSlide = function() { + trace("BUILDSLIDE"); + $wrap = VMM.appendAndGetElement(element, "<div>", "content"); + $slide = VMM.appendAndGetElement($wrap, "<div>"); + + /* DATE + ================================================== */ + if (data.startdate != null && data.startdate != "") { + if (type.of(data.startdate) == "date") { + if (data.type != "start") { + var st = VMM.Date.prettyDate(data.startdate, false, data.precisiondate); + var en = VMM.Date.prettyDate(data.enddate, false, data.precisiondate); + var tag = ""; + /* TAG / CATEGORY + ================================================== */ + if (data.tag != null && data.tag != "") { + tag = VMM.createElement("span", data.tag, "slide-tag"); + } + + if (st != en) { + c.text += VMM.createElement("h2", st + " &mdash; " + en + tag, "date"); + } else { + c.text += VMM.createElement("h2", st + tag, "date"); + } + } + } + } + + /* HEADLINE + ================================================== */ + if (data.headline != null && data.headline != "") { + c.has.headline = true; + if (data.type == "start") { + c.text += VMM.createElement("h2", VMM.Util.linkify_with_twitter(data.headline, "_blank"), "start"); + } else { + c.text += VMM.createElement("h3", VMM.Util.linkify_with_twitter(data.headline, "_blank")); + } + } + + /* TEXT + ================================================== */ + if (data.text != null && data.text != "") { + c.has.text = true; + c.text += VMM.createElement("p", VMM.Util.linkify_with_twitter(data.text, "_blank")); + } + + if (c.has.text || c.has.headline) { + c.text = VMM.createElement("div", c.text, "container"); + //$text = VMM.appendAndGetElement($slide, "<div>", "text", c.text); + + $text = VMM.appendAndGetElement($slide, "<div>", "text", VMM.TextElement.create(c.text)); + + } + + /* SLUG + ================================================== */ + if (data.needs_slug) { + + } + + /* MEDIA + ================================================== */ + if (data.asset != null && data.asset != "") { + if (data.asset.media != null && data.asset.media != "") { + c.has.media = true; + $media = VMM.appendAndGetElement($slide, "<div>", "media", VMM.MediaElement.create(data.asset, data.uniqueid)); + } + } + + /* COMBINE + ================================================== */ + if (c.has.text) { c.layout += "-text" }; + if (c.has.media){ c.layout += "-media" }; + + if (c.has.text) { + if (timer.skinny) { + VMM.Lib.addClass($slide, c.layout); + is_skinny = true; + } else { + VMM.Lib.addClass($slide, c.layout); + VMM.Lib.addClass($slide, "pad-left"); + VMM.Lib.detach($text); + VMM.Lib.append($slide, $text); + } + + } else { + VMM.Lib.addClass($slide, c.layout); + } + + + }; + + } + +}; + + +/* ********************************************** + Begin AES.js +********************************************** */ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* AES implementation in JavaScript (c) Chris Veness 2005-2011 */ +/* - see http://csrc.nist.gov/publications/PubsFIPS.html#197 */ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +var Aes = {}; // Aes namespace + +/** + * AES Cipher function: encrypt 'input' state with Rijndael algorithm + * applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage + * + * @param {Number[]} input 16-byte (128-bit) input state array + * @param {Number[][]} w Key schedule as 2D byte-array (Nr+1 x Nb bytes) + * @returns {Number[]} Encrypted output state array + */ +Aes.cipher = function(input, w) { // main Cipher function [§5.1] + var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES) + var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys + + var state = [[],[],[],[]]; // initialise 4xNb byte-array 'state' with input [§3.4] + for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i]; + + state = Aes.addRoundKey(state, w, 0, Nb); + + for (var round=1; round<Nr; round++) { + state = Aes.subBytes(state, Nb); + state = Aes.shiftRows(state, Nb); + state = Aes.mixColumns(state, Nb); + state = Aes.addRoundKey(state, w, round, Nb); + } + + state = Aes.subBytes(state, Nb); + state = Aes.shiftRows(state, Nb); + state = Aes.addRoundKey(state, w, Nr, Nb); + + var output = new Array(4*Nb); // convert state to 1-d array before returning [§3.4] + for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)]; + return output; +} + +/** + * Perform Key Expansion to generate a Key Schedule + * + * @param {Number[]} key Key as 16/24/32-byte array + * @returns {Number[][]} Expanded key schedule as 2D byte-array (Nr+1 x Nb bytes) + */ +Aes.keyExpansion = function(key) { // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2] + var Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES) + var Nk = key.length/4 // key length (in words): 4/6/8 for 128/192/256-bit keys + var Nr = Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys + + var w = new Array(Nb*(Nr+1)); + var temp = new Array(4); + + for (var i=0; i<Nk; i++) { + var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]]; + w[i] = r; + } + + for (var i=Nk; i<(Nb*(Nr+1)); i++) { + w[i] = new Array(4); + for (var t=0; t<4; t++) temp[t] = w[i-1][t]; + if (i % Nk == 0) { + temp = Aes.subWord(Aes.rotWord(temp)); + for (var t=0; t<4; t++) temp[t] ^= Aes.rCon[i/Nk][t]; + } else if (Nk > 6 && i%Nk == 4) { + temp = Aes.subWord(temp); + } + for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t]; + } + + return w; +} + +/* + * ---- remaining routines are private, not called externally ---- + */ + +Aes.subBytes = function(s, Nb) { // apply SBox to state S [§5.1.1] + for (var r=0; r<4; r++) { + for (var c=0; c<Nb; c++) s[r][c] = Aes.sBox[s[r][c]]; + } + return s; +} + +Aes.shiftRows = function(s, Nb) { // shift row r of state S left by r bytes [§5.1.2] + var t = new Array(4); + for (var r=1; r<4; r++) { + for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb]; // shift into temp copy + for (var c=0; c<4; c++) s[r][c] = t[c]; // and copy back + } // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES): + return s; // see asmaes.sourceforge.net/rijndael/rijndaelImplementation.pdf +} + +Aes.mixColumns = function(s, Nb) { // combine bytes of each col of state S [§5.1.3] + for (var c=0; c<4; c++) { + var a = new Array(4); // 'a' is a copy of the current column from 's' + var b = new Array(4); // 'b' is a•{02} in GF(2^8) + for (var i=0; i<4; i++) { + a[i] = s[i][c]; + b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1; + + } + // a[n] ^ b[n] is a•{03} in GF(2^8) + s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3 + s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3 + s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3 + s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3 + } + return s; +} + +Aes.addRoundKey = function(state, w, rnd, Nb) { // xor Round Key into state S [§5.1.4] + for (var r=0; r<4; r++) { + for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r]; + } + return state; +} + +Aes.subWord = function(w) { // apply SBox to 4-byte word w + for (var i=0; i<4; i++) w[i] = Aes.sBox[w[i]]; + return w; +} + +Aes.rotWord = function(w) { // rotate 4-byte word w left by one byte + var tmp = w[0]; + for (var i=0; i<3; i++) w[i] = w[i+1]; + w[3] = tmp; + return w; +} + +// sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [§5.1.1] +Aes.sBox = [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, + 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, + 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, + 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, + 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, + 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, + 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, + 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, + 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, + 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, + 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, + 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, + 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, + 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, + 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, + 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16]; + +// rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2] +Aes.rCon = [ [0x00, 0x00, 0x00, 0x00], + [0x01, 0x00, 0x00, 0x00], + [0x02, 0x00, 0x00, 0x00], + [0x04, 0x00, 0x00, 0x00], + [0x08, 0x00, 0x00, 0x00], + [0x10, 0x00, 0x00, 0x00], + [0x20, 0x00, 0x00, 0x00], + [0x40, 0x00, 0x00, 0x00], + [0x80, 0x00, 0x00, 0x00], + [0x1b, 0x00, 0x00, 0x00], + [0x36, 0x00, 0x00, 0x00] ]; + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* AES Counter-mode implementation in JavaScript (c) Chris Veness 2005-2011 */ +/* - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf */ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +Aes.Ctr = {}; // Aes.Ctr namespace: a subclass or extension of Aes + +/** + * Encrypt a text using AES encryption in Counter mode of operation + * + * Unicode multi-byte character safe + * + * @param {String} plaintext Source text to be encrypted + * @param {String} password The password to use to generate a key + * @param {Number} nBits Number of bits to be used in the key (128, 192, or 256) + * @returns {string} Encrypted text + */ +Aes.Ctr.encrypt = function(plaintext, password, nBits) { + var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES + if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys + plaintext = Utf8.encode(plaintext); + password = Utf8.encode(password); + //var t = new Date(); // timer + + // use AES itself to encrypt password to get cipher key (using plain password as source for key + // expansion) - gives us well encrypted key (though hashed key might be preferred for prod'n use) + var nBytes = nBits/8; // no bytes in key (16/24/32) + var pwBytes = new Array(nBytes); + for (var i=0; i<nBytes; i++) { // use 1st 16/24/32 chars of password for key + pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i); + } + var key = Aes.cipher(pwBytes, Aes.keyExpansion(pwBytes)); // gives us 16-byte key + key = key.concat(key.slice(0, nBytes-16)); // expand key to 16/24/32 bytes long + + // initialise 1st 8 bytes of counter block with nonce (NIST SP800-38A §B.2): [0-1] = millisec, + // [2-3] = random, [4-7] = seconds, together giving full sub-millisec uniqueness up to Feb 2106 + var counterBlock = new Array(blockSize); + + var nonce = (new Date()).getTime(); // timestamp: milliseconds since 1-Jan-1970 + var nonceMs = nonce%1000; + var nonceSec = Math.floor(nonce/1000); + var nonceRnd = Math.floor(Math.random()*0xffff); + + for (var i=0; i<2; i++) counterBlock[i] = (nonceMs >>> i*8) & 0xff; + for (var i=0; i<2; i++) counterBlock[i+2] = (nonceRnd >>> i*8) & 0xff; + for (var i=0; i<4; i++) counterBlock[i+4] = (nonceSec >>> i*8) & 0xff; + + // and convert it to a string to go on the front of the ciphertext + var ctrTxt = ''; + for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]); + + // generate key schedule - an expansion of the key into distinct Key Rounds for each round + var keySchedule = Aes.keyExpansion(key); + + var blockCount = Math.ceil(plaintext.length/blockSize); + var ciphertxt = new Array(blockCount); // ciphertext as array of strings + + for (var b=0; b<blockCount; b++) { + // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes) + // done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB) + for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff; + for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8) + + var cipherCntr = Aes.cipher(counterBlock, keySchedule); // -- encrypt counter block -- + + // block size is reduced on final block + var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1; + var cipherChar = new Array(blockLength); + + for (var i=0; i<blockLength; i++) { // -- xor plaintext with ciphered counter char-by-char -- + cipherChar[i] = cipherCntr[i] ^ plaintext.charCodeAt(b*blockSize+i); + cipherChar[i] = String.fromCharCode(cipherChar[i]); + } + ciphertxt[b] = cipherChar.join(''); + } + + // Array.join is more efficient than repeated string concatenation in IE + var ciphertext = ctrTxt + ciphertxt.join(''); + ciphertext = Base64.encode(ciphertext); // encode in base64 + + //alert((new Date()) - t); + return ciphertext; +} + +/** + * Decrypt a text encrypted by AES in counter mode of operation + * + * @param {String} ciphertext Source text to be encrypted + * @param {String} password The password to use to generate a key + * @param {Number} nBits Number of bits to be used in the key (128, 192, or 256) + * @returns {String} Decrypted text + */ +Aes.Ctr.decrypt = function(ciphertext, password, nBits) { + var blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES + if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys + ciphertext = Base64.decode(ciphertext); + password = Utf8.encode(password); + //var t = new Date(); // timer + + // use AES to encrypt password (mirroring encrypt routine) + var nBytes = nBits/8; // no bytes in key + var pwBytes = new Array(nBytes); + for (var i=0; i<nBytes; i++) { + pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i); + } + var key = Aes.cipher(pwBytes, Aes.keyExpansion(pwBytes)); + key = key.concat(key.slice(0, nBytes-16)); // expand key to 16/24/32 bytes long + + // recover nonce from 1st 8 bytes of ciphertext + var counterBlock = new Array(8); + ctrTxt = ciphertext.slice(0, 8); + for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i); + + // generate key schedule + var keySchedule = Aes.keyExpansion(key); + + // separate ciphertext into blocks (skipping past initial 8 bytes) + var nBlocks = Math.ceil((ciphertext.length-8) / blockSize); + var ct = new Array(nBlocks); + for (var b=0; b<nBlocks; b++) ct[b] = ciphertext.slice(8+b*blockSize, 8+b*blockSize+blockSize); + ciphertext = ct; // ciphertext is now array of block-length strings + + // plaintext will get generated block-by-block into array of block-length strings + var plaintxt = new Array(ciphertext.length); + + for (var b=0; b<nBlocks; b++) { + // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes) + for (var c=0; c<4; c++) counterBlock[15-c] = ((b) >>> c*8) & 0xff; + for (var c=0; c<4; c++) counterBlock[15-c-4] = (((b+1)/0x100000000-1) >>> c*8) & 0xff; + + var cipherCntr = Aes.cipher(counterBlock, keySchedule); // encrypt counter block + + var plaintxtByte = new Array(ciphertext[b].length); + for (var i=0; i<ciphertext[b].length; i++) { + // -- xor plaintxt with ciphered counter byte-by-byte -- + plaintxtByte[i] = cipherCntr[i] ^ ciphertext[b].charCodeAt(i); + plaintxtByte[i] = String.fromCharCode(plaintxtByte[i]); + } + plaintxt[b] = plaintxtByte.join(''); + } + + // join array of blocks into single plaintext string + var plaintext = plaintxt.join(''); + plaintext = Utf8.decode(plaintext); // decode from UTF8 back to Unicode multi-byte chars + + //alert((new Date()) - t); + return plaintext; +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Base64 class: Base 64 encoding / decoding (c) Chris Veness 2002-2011 */ +/* note: depends on Utf8 class */ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +var Base64 = {}; // Base64 namespace + +Base64.code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + +/** + * Encode string into Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648] + * (instance method extending String object). As per RFC 4648, no newlines are added. + * + * @param {String} str The string to be encoded as base-64 + * @param {Boolean} [utf8encode=false] Flag to indicate whether str is Unicode string to be encoded + * to UTF8 before conversion to base64; otherwise string is assumed to be 8-bit characters + * @returns {String} Base64-encoded string + */ +Base64.encode = function(str, utf8encode) { // http://tools.ietf.org/html/rfc4648 + utf8encode = (typeof utf8encode == 'undefined') ? false : utf8encode; + var o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = '', c, plain, coded; + var b64 = Base64.code; + + plain = utf8encode ? str.encodeUTF8() : str; + + c = plain.length % 3; // pad string to length of multiple of 3 + if (c > 0) { while (c++ < 3) { pad += '='; plain += '\0'; } } + // note: doing padding here saves us doing special-case packing for trailing 1 or 2 chars + + for (c=0; c<plain.length; c+=3) { // pack three octets into four hexets + o1 = plain.charCodeAt(c); + o2 = plain.charCodeAt(c+1); + o3 = plain.charCodeAt(c+2); + + bits = o1<<16 | o2<<8 | o3; + + h1 = bits>>18 & 0x3f; + h2 = bits>>12 & 0x3f; + h3 = bits>>6 & 0x3f; + h4 = bits & 0x3f; + + // use hextets to index into code string + e[c/3] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); + } + coded = e.join(''); // join() is far faster than repeated string concatenation in IE + + // replace 'A's from padded nulls with '='s + coded = coded.slice(0, coded.length-pad.length) + pad; + + return coded; +} + +/** + * Decode string from Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648] + * (instance method extending String object). As per RFC 4648, newlines are not catered for. + * + * @param {String} str The string to be decoded from base-64 + * @param {Boolean} [utf8decode=false] Flag to indicate whether str is Unicode string to be decoded + * from UTF8 after conversion from base64 + * @returns {String} decoded string + */ +Base64.decode = function(str, utf8decode) { + utf8decode = (typeof utf8decode == 'undefined') ? false : utf8decode; + var o1, o2, o3, h1, h2, h3, h4, bits, d=[], plain, coded; + var b64 = Base64.code; + + coded = utf8decode ? str.decodeUTF8() : str; + + + for (var c=0; c<coded.length; c+=4) { // unpack four hexets into three octets + h1 = b64.indexOf(coded.charAt(c)); + h2 = b64.indexOf(coded.charAt(c+1)); + h3 = b64.indexOf(coded.charAt(c+2)); + h4 = b64.indexOf(coded.charAt(c+3)); + + bits = h1<<18 | h2<<12 | h3<<6 | h4; + + o1 = bits>>>16 & 0xff; + o2 = bits>>>8 & 0xff; + o3 = bits & 0xff; + + d[c/4] = String.fromCharCode(o1, o2, o3); + // check for padding + if (h4 == 0x40) d[c/4] = String.fromCharCode(o1, o2); + if (h3 == 0x40) d[c/4] = String.fromCharCode(o1); + } + plain = d.join(''); // join() is far faster than repeated string concatenation in IE + + return utf8decode ? plain.decodeUTF8() : plain; +} + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Utf8 class: encode / decode between multi-byte Unicode characters and UTF-8 multiple */ +/* single-byte character encoding (c) Chris Veness 2002-2011 */ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +var Utf8 = {}; // Utf8 namespace + +/** + * Encode multi-byte Unicode string into utf-8 multiple single-byte characters + * (BMP / basic multilingual plane only) + * + * Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars + * + * @param {String} strUni Unicode string to be encoded as UTF-8 + * @returns {String} encoded string + */ +Utf8.encode = function(strUni) { + // use regular expressions & String.replace callback function for better efficiency + // than procedural approaches + var strUtf = strUni.replace( + /[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz + function(c) { + var cc = c.charCodeAt(0); + return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); } + ); + strUtf = strUtf.replace( + /[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz + function(c) { + var cc = c.charCodeAt(0); + return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); } + ); + return strUtf; +} + +/** + * Decode utf-8 encoded string back into multi-byte Unicode characters + * + * @param {String} strUtf UTF-8 string to be decoded back to Unicode + * @returns {String} decoded string + */ +Utf8.decode = function(strUtf) { + // note: decode 3-byte chars first as decoded 2-byte strings could appear to be 3-byte char! + var strUni = strUtf.replace( + /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars + function(c) { // (note parentheses for precence) + var cc = ((c.charCodeAt(0)&0x0f)<<12) | ((c.charCodeAt(1)&0x3f)<<6) | ( c.charCodeAt(2)&0x3f); + return String.fromCharCode(cc); } + ); + strUni = strUni.replace( + /[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars + function(c) { // (note parentheses for precence) + var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f; + return String.fromCharCode(cc); } + ); + return strUni; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* ********************************************** + Begin bootstrap-tooltip.js +********************************************** */ + +/* =========================================================== + * bootstrap-tooltip.js v2.0.1 + * http://twitter.github.com/bootstrap/javascript.html#tooltips + * Inspired by the original jQuery.tipsy by Jason Frame + * =========================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================================================== */ + +!function( $ ) { + + "use strict" + + /* TOOLTIP PUBLIC CLASS DEFINITION + * =============================== */ + + var Tooltip = function ( element, options ) { + this.init('tooltip', element, options) + } + + Tooltip.prototype = { + + constructor: Tooltip + + , init: function ( type, element, options ) { + var eventIn + , eventOut + + this.type = type + this.$element = $(element) + this.options = this.getOptions(options) + this.enabled = true + + if (this.options.trigger != 'manual') { + eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus' + eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur' + this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this)) + } + + this.options.selector ? + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : + this.fixTitle() + } + + , getOptions: function ( options ) { + options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data()) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { + show: options.delay + , hide: options.delay + } + } + + return options + } + + , enter: function ( e ) { + var self = $(e.currentTarget)[this.type](this._options).data(this.type) + + if (!self.options.delay || !self.options.delay.show) { + self.show() + } else { + self.hoverState = 'in' + setTimeout(function() { + if (self.hoverState == 'in') { + self.show() + } + }, self.options.delay.show) + } + } + + , leave: function ( e ) { + var self = $(e.currentTarget)[this.type](this._options).data(this.type) + + if (!self.options.delay || !self.options.delay.hide) { + self.hide() + } else { + self.hoverState = 'out' + setTimeout(function() { + if (self.hoverState == 'out') { + self.hide() + } + }, self.options.delay.hide) + } + } + + , show: function () { + var $tip + , inside + , pos + , actualWidth + , actualHeight + , placement + , tp + + if (this.hasContent() && this.enabled) { + $tip = this.tip() + this.setContent() + + if (this.options.animation) { + $tip.addClass('fade') + } + + placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + inside = /in/.test(placement) + + $tip + .remove() + .css({ top: 0, left: 0, display: 'block' }) + .appendTo(inside ? this.$element : document.body) + + pos = this.getPosition(inside) + + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + + switch (inside ? placement.split(' ')[1] : placement) { + case 'bottom': + tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'top': + tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'left': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth} + break + case 'right': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} + break + } + + $tip + .css(tp) + .addClass(placement) + .addClass('in') + } + } + + , setContent: function () { + var $tip = this.tip() + $tip.find('.tooltip-inner').html(this.getTitle()) + $tip.removeClass('fade in top bottom left right') + } + + , hide: function () { + var that = this + , $tip = this.tip() + + $tip.removeClass('in') + + function removeWithAnimation() { + var timeout = setTimeout(function () { + $tip.off($.support.transition.end).remove() + }, 500) + + $tip.one($.support.transition.end, function () { + clearTimeout(timeout) + $tip.remove() + }) + } + + $.support.transition && this.$tip.hasClass('fade') ? + removeWithAnimation() : + $tip.remove() + } + + , fixTitle: function () { + var $e = this.$element + if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title') + } + } + + , hasContent: function () { + return this.getTitle() + } + + , getPosition: function (inside) { + return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), { + width: this.$element[0].offsetWidth + , height: this.$element[0].offsetHeight + }) + } + + , getTitle: function () { + var title + , $e = this.$element + , o = this.options + + title = $e.attr('data-original-title') + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) + + title = title.toString().replace(/(^\s*|\s*$)/, "") + + return title + } + + , tip: function () { + return this.$tip = this.$tip || $(this.options.template) + } + + , validate: function () { + if (!this.$element[0].parentNode) { + this.hide() + this.$element = null + this.options = null + } + } + + , enable: function () { + this.enabled = true + } + + , disable: function () { + this.enabled = false + } + + , toggleEnabled: function () { + this.enabled = !this.enabled + } + + , toggle: function () { + this[this.tip().hasClass('in') ? 'hide' : 'show']() + } + + } + + + /* TOOLTIP PLUGIN DEFINITION + * ========================= */ + + $.fn.tooltip = function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('tooltip') + , options = typeof option == 'object' && option + if (!data) $this.data('tooltip', (data = new Tooltip(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.tooltip.Constructor = Tooltip + + $.fn.tooltip.defaults = { + animation: true + , delay: 0 + , selector: false + , placement: 'top' + , trigger: 'hover' + , title: '' + , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' + } + +}( window.jQuery ); + +/* ********************************************** + Begin VMM.StoryJS.js +********************************************** */ + +/* VeriteCo StoryJS +================================================== */ + +/* * CodeKit Import + * http://incident57.com/codekit/ +================================================== */ +// @codekit-prepend "VMM.StoryJS.License.js"; +// @codekit-prepend "Core/VMM.Core.js"; +// @codekit-prepend "Language/VMM.Language.js"; +// @codekit-prepend "Media/VMM.Media.js"; +// @codekit-prepend "Slider/VMM.DragSlider.js"; +// @codekit-prepend "Slider/VMM.Slider.js"; +// @codekit-prepend "Library/AES.js"; +// @codekit-prepend "Library/bootstrap-tooltip.js"; + + +if(typeof VMM != 'undefined' && typeof VMM.StoryJS == 'undefined') { + + VMM.StoryJS = function() { + + /* PRIVATE VARS + ================================================== */ + + /* PUBLIC FUNCTIONS + ================================================== */ + this.init = function(d) { + + }; + + } +} + + +/* ********************************************** + Begin VMM.Timeline.js +********************************************** */ + +/** + * TimelineJS + * Designed and built by Zach Wise at VéritéCo + + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +/* * CodeKit Import + * http://incident57.com/codekit/ +================================================== */ +// @codekit-prepend "VMM.Timeline.License.js"; + +// @codekit-prepend "Core/VMM.StoryJS.js"; + +// @codekit-append "VMM.Timeline.TimeNav.js"; +// @codekit-append "VMM.Timeline.DataObj.js"; + + +/* Timeline +================================================== */ + +if(typeof VMM != 'undefined' && typeof VMM.Timeline == 'undefined') { + + VMM.Timeline = function(_timeline_id, w, h) { + + var $timeline, + $container, + $feature, + $feedback, + $slider, + $navigation, + slider, + timenav, + version = "2.x", + timeline_id = "#timelinejs", + events = {}, + data = {}, + _dates = [], + config = {}, + has_width = false, + has_height = false, + ie7 = false, + is_moving = false; + + + if (type.of(_timeline_id) == "string") { + if (_timeline_id.match("#")) { + timeline_id = _timeline_id; + } else { + timeline_id = "#" + _timeline_id; + } + } else { + timeline_id = "#timelinejs"; + } + + + /* CONFIG + ================================================== */ + config = { + embed: false, + events: { + data_ready: "DATAREADY", + messege: "MESSEGE", + headline: "HEADLINE", + slide_change: "SLIDE_CHANGE", + resize: "resize" + }, + id: timeline_id, + source: "nothing", + type: "timeline", + touch: false, + orientation: "normal", + maptype: "toner", + version: "2.x", + preload: 4, + current_slide: 0, + hash_bookmark: false, + start_at_end: false, + start_at_slide: 0, + start_zoom_adjust: 0, + start_page: false, + api_keys: { + google: "", + flickr: "", + twitter: "" + }, + interval: 10, + something: 0, + width: 960, + height: 540, + spacing: 15, + loaded: { + slider: false, + timenav: false, + percentloaded: 0 + }, + nav: { + start_page: false, + interval_width: 200, + density: 4, + minor_width: 0, + minor_left: 0, + constraint: { + left: 0, + right: 0, + right_min: 0, + right_max: 0 + }, + zoom: { + adjust: 0 + }, + multiplier: { + current: 6, + min: .1, + max: 50 + }, + rows: [1, 1, 1], + width: 960, + height: 200, + marker: { + width: 150, + height: 50 + } + }, + feature: { + width: 960, + height: 540 + }, + slider: { + width: 720, + height: 400, + content: { + width: 720, + height: 400, + padding: 130, + padding_default:130 + }, + nav: { + width: 100, + height: 200 + } + }, + ease: "easeInOutExpo", + duration: 1000, + gmap_key: "", + language: VMM.Language + }; + + if ( w != null && w != "") { + config.width = w; + has_width = true; + } + + if ( h != null && h != "") { + config.height = h; + has_height = true; + } + + if(window.location.hash) { + var hash = window.location.hash.substring(1); + if (!isNaN(hash)) { + config.current_slide = parseInt(hash); + } + } + + window.onhashchange = function () { + var hash = window.location.hash.substring(1); + if (config.hash_bookmark) { + if (is_moving) { + goToEvent(parseInt(hash)); + } else { + is_moving = false; + } + } else { + goToEvent(parseInt(hash)); + } + } + + /* CREATE CONFIG + ================================================== */ + function createConfig(conf) { + + // APPLY SUPPLIED CONFIG TO TIMELINE CONFIG + if (typeof embed_config == 'object') { + timeline_config = embed_config; + } + if (typeof timeline_config == 'object') { + trace("HAS TIMELINE CONFIG"); + config = VMM.Util.mergeConfig(config, timeline_config); + } else if (typeof conf == 'object') { + config = VMM.Util.mergeConfig(config, conf); + } + + if (VMM.Browser.device == "mobile" || VMM.Browser.device == "tablet") { + config.touch = true; + } + + config.nav.width = config.width; + config.nav.height = 200; + config.feature.width = config.width; + config.feature.height = config.height - config.nav.height; + config.nav.zoom.adjust = parseInt(config.start_zoom_adjust, 10); + VMM.Timeline.Config = config; + VMM.master_config.Timeline = VMM.Timeline.Config; + this.events = config.events; + + if (config.gmap_key != "") { + config.api_keys.google = config.gmap_key; + } + + trace("VERSION " + config.version); + version = config.version; + } + + /* CREATE TIMELINE STRUCTURE + ================================================== */ + function createStructure() { + // CREATE DOM STRUCTURE + $timeline = VMM.getElement(timeline_id); + VMM.Lib.addClass($timeline, "vco-timeline"); + VMM.Lib.addClass($timeline, "vco-storyjs"); + + $container = VMM.appendAndGetElement($timeline, "<div>", "vco-container vco-main"); + $feature = VMM.appendAndGetElement($container, "<div>", "vco-feature"); + $slider = VMM.appendAndGetElement($feature, "<div>", "vco-slider"); + $navigation = VMM.appendAndGetElement($container, "<div>", "vco-navigation"); + $feedback = VMM.appendAndGetElement($timeline, "<div>", "vco-feedback", ""); + + + if (typeof config.language.right_to_left != 'undefined') { + VMM.Lib.addClass($timeline, "vco-right-to-left"); + } + + slider = new VMM.Slider($slider, config); + timenav = new VMM.Timeline.TimeNav($navigation); + + if (!has_width) { + config.width = VMM.Lib.width($timeline); + } else { + VMM.Lib.width($timeline, config.width); + } + + if (!has_height) { + config.height = VMM.Lib.height($timeline); + } else { + VMM.Lib.height($timeline, config.height); + } + + if (config.touch) { + VMM.Lib.addClass($timeline, "vco-touch"); + } else { + VMM.Lib.addClass($timeline, "vco-notouch"); + } + + + } + + /* ON EVENT + ================================================== */ + + function onDataReady(e, d) { + trace("onDataReady"); + data = d.timeline; + + if (type.of(data.era) != "array") { + data.era = []; + } + + buildDates(); + + }; + + function onDatesProcessed() { + build(); + } + + function reSize() { + + updateSize(); + + slider.setSize(config.feature.width, config.feature.height); + timenav.setSize(config.width, config.height); + if (orientationChange()) { + setViewport(); + } + + }; + + function onSliderLoaded(e) { + config.loaded.slider = true; + onComponentLoaded(); + }; + + function onComponentLoaded(e) { + config.loaded.percentloaded = config.loaded.percentloaded + 25; + + if (config.loaded.slider && config.loaded.timenav) { + hideMessege(); + } + } + + function onTimeNavLoaded(e) { + config.loaded.timenav = true; + onComponentLoaded(); + } + + function onSlideUpdate(e) { + is_moving = true; + config.current_slide = slider.getCurrentNumber(); + setHash(config.current_slide); + timenav.setMarker(config.current_slide, config.ease,config.duration); + }; + + function onMarkerUpdate(e) { + is_moving = true; + config.current_slide = timenav.getCurrentNumber(); + setHash(config.current_slide); + slider.setSlide(config.current_slide); + }; + + function goToEvent(n) { + if (n <= _dates.length - 1 && n >= 0) { + config.current_slide = n; + slider.setSlide(config.current_slide); + timenav.setMarker(config.current_slide, config.ease,config.duration); + } + } + + function setHash(n) { + if (config.hash_bookmark) { + window.location.hash = "#" + n.toString(); + } + } + + function getViewport() { + + } + + function setViewport() { + var viewport_content = "", + viewport_orientation = searchOrientation(window.orientation); + + if (VMM.Browser.device == "mobile") { + if (viewport_orientation == "portrait") { + //viewport_content = "width=device-width; initial-scale=0.75, maximum-scale=0.75"; + viewport_content = "width=device-width; initial-scale=0.5, maximum-scale=0.5"; + } else if (viewport_orientation == "landscape") { + viewport_content = "width=device-width; initial-scale=0.5, maximum-scale=0.5"; + } else { + viewport_content = "width=device-width, initial-scale=1, maximum-scale=1.0"; + } + } else if (VMM.Browser.device == "tablet") { + //viewport_content = "width=device-width, initial-scale=1, maximum-scale=1.0"; + } + + if (document.getElementById("viewport")) { + //VMM.Lib.attr("#viewport", "content", viewport_content); + } else { + //VMM.appendElement("head", "<meta id='viewport' name='viewport' content=" + viewport_content + "/>"); + } + + } + + /* ORIENTATION + ================================================== */ + function searchOrientation(orientation) { + var orient = ""; + + if ( orientation == 0 || orientation == 180) { + orient = "portrait"; + } else if ( orientation == 90 || orientation == -90) { + orient = "landscape"; + } else { + orient = "normal"; + } + + return orient; + } + + function orientationChange() { + var orientation = searchOrientation(window.orientation); + + if (orientation == config.orientation) { + return false; + } else { + config.orientation = orientation; + return true; + } + + } + + + /* PUBLIC FUNCTIONS + ================================================== */ + this.init = function(c, _data) { + trace('INIT'); + setViewport(); + createConfig(c); + createStructure(); + + if (type.of(_data) == "string") { + config.source = _data; + } + + // LANGUAGE + VMM.Date.setLanguage(config.language); + VMM.master_config.language = config.language; + + // EXTERNAL API + VMM.ExternalAPI.setKeys(config.api_keys); + VMM.ExternalAPI.googlemaps.setMapType(config.maptype); + + // EVENTS + VMM.bindEvent(global, onDataReady, config.events.data_ready); + VMM.bindEvent(global, showMessege, config.events.messege); + + VMM.fireEvent(global, config.events.messege, config.language.messages.loading_timeline); + + /* GET DATA + ================================================== */ + if (VMM.Browser.browser == "Explorer" || VMM.Browser.browser == "MSIE") { + if ( parseInt(VMM.Browser.version, 10) <= 7 ) { + ie7 = true; + } + } + + if (type.of(config.source) == "string" || type.of(config.source) == "object") { + VMM.Timeline.DataObj.getData(config.source); + } else { + VMM.fireEvent(global, config.events.messege, "No data source provided"); + //VMM.Timeline.DataObj.getData(VMM.getElement(timeline_id)); + } + + + }; + + this.iframeLoaded = function() { + trace("iframeLoaded"); + }; + + this.reload = function(_d) { + trace("Load new timeline data" + _d); + VMM.fireEvent(global, config.events.messege, config.language.messages.loading_timeline); + data = {}; + VMM.Timeline.DataObj.getData(_d); + config.current_slide = 0; + slider.setSlide(0); + timenav.setMarker(0, config.ease,config.duration); + }; + + /* DATA + ================================================== */ + function getData(url) { + VMM.getJSON(url, function(d) { + data = VMM.Timeline.DataObj.getData(d); + VMM.fireEvent(global, config.events.data_ready); + }); + }; + + /* MESSEGES + ================================================== */ + function showMessege(e, msg, other) { + trace("showMessege " + msg); + //VMM.attachElement($timeline, $feedback); + if (other) { + VMM.attachElement($feedback, msg); + } else{ + VMM.attachElement($feedback, VMM.MediaElement.loadingmessage(msg)); + } + }; + + function hideMessege() { + VMM.Lib.animate($feedback, config.duration, config.ease*4, {"opacity": 0}, detachMessege); + }; + + function detachMessege() { + VMM.Lib.detach($feedback); + } + + /* BUILD DISPLAY + ================================================== */ + function build() { + + // START AT SLIDE + if (parseInt(config.start_at_slide) > 0 && config.current_slide == 0) { + config.current_slide = parseInt(config.start_at_slide); + } + // START AT END + if (config.start_at_end && config.current_slide == 0) { + config.current_slide = _dates.length - 1; + } + + + // IE7 + if (ie7) { + ie7 = true; + VMM.fireEvent(global, config.events.messege, "Internet Explorer " + VMM.Browser.version + " is not supported by TimelineJS. Please update your browser to version 8 or higher."); + } else { + + detachMessege(); + reSize(); + + // EVENT LISTENERS + VMM.bindEvent($slider, onSliderLoaded, "LOADED"); + VMM.bindEvent($navigation, onTimeNavLoaded, "LOADED"); + VMM.bindEvent($slider, onSlideUpdate, "UPDATE"); + VMM.bindEvent($navigation, onMarkerUpdate, "UPDATE"); + + // INITIALIZE COMPONENTS + slider.init(_dates); + timenav.init(_dates, data.era); + + // RESIZE EVENT LISTENERS + VMM.bindEvent(global, reSize, config.events.resize); + + + + } + + + }; + + function ie7Build() { + trace("IE7 or lower"); + for(var i = 0; i < _dates.length; i++) { + trace(_dates[i]); + /* + var st = VMM.Date.prettyDate(data.startdate); + var en = VMM.Date.prettyDate(data.enddate); + var tag = ""; + if (data.tag != null && data.tag != "") { + tag = VMM.createElement("span", data.tag, "slide-tag"); + } + + if (st != en) { + c.text += VMM.createElement("h2", st + " &mdash; " + en + tag, "date"); + } else { + c.text += VMM.createElement("h2", st + tag, "date"); + } + */ + + } + }; + + function updateSize() { + trace("UPDATE SIZE"); + config.width = VMM.Lib.width($timeline); + config.height = VMM.Lib.height($timeline); + + config.nav.width = config.width; + config.feature.width = config.width; + + config.feature.height = config.height - config.nav.height - 3; + + if (VMM.Browser.device == "mobile") { + /* + if (VMM.Browser.orientation == "portrait") { + config.feature.height = 480; + config.height = 480 + config.nav.height; + } else if(VMM.Browser.orientation == "landscape") { + config.feature.height = 320; + config.height = 320 + config.nav.height; + } else { + config.feature.height = config.height - config.nav.height - 3; + } + */ + } + + if (config.width < 641) { + VMM.Lib.addClass($timeline, "vco-skinny"); + } else { + VMM.Lib.removeClass($timeline, "vco-skinny"); + } + + }; + + // BUILD DATE OBJECTS + function buildDates() { + + _dates = []; + VMM.fireEvent(global, config.events.messege, "Building Dates"); + updateSize(); + + for(var i = 0; i < data.date.length; i++) { + + if (data.date[i].startDate != null && data.date[i].startDate != "") { + + var _date = {}, + do_start = VMM.Date.parse(data.date[i].startDate, true), + do_end; + + _date.startdate = do_start.date; + _date.precisiondate = do_start.precision; + + if (!isNaN(_date.startdate)) { + + + // END DATE + if (data.date[i].endDate != null && data.date[i].endDate != "") { + _date.enddate = VMM.Date.parse(data.date[i].endDate); + } else { + _date.enddate = _date.startdate; + } + + _date.needs_slug = false; + + if (data.date[i].headline == "") { + if (data.date[i].slug != null && data.date[i].slug != "") { + _date.needs_slug = true; + } + } + + _date.title = data.date[i].headline; + _date.headline = data.date[i].headline; + _date.type = data.date[i].type; + _date.date = VMM.Date.prettyDate(_date.startdate, false, _date.precisiondate); + _date.asset = data.date[i].asset; + _date.fulldate = _date.startdate.getTime(); + _date.text = data.date[i].text; + _date.content = ""; + _date.tag = data.date[i].tag; + _date.slug = data.date[i].slug; + _date.uniqueid = VMM.Util.unique_ID(7); + _date.classname = data.date[i].classname; + + + _dates.push(_date); + } + + } + + }; + + /* CUSTOM SORT + ================================================== */ + if (data.type != "storify") { + _dates.sort(function(a, b){ + return a.fulldate - b.fulldate + }); + } + + /* CREATE START PAGE IF AVAILABLE + ================================================== */ + if (data.headline != null && data.headline != "" && data.text != null && data.text != "") { + + var startpage_date, + do_start, + _date = {}, + td_num = 0, + td; + + if (typeof data.startDate != 'undefined') { + do_start = VMM.Date.parse(data.startDate, true); + startpage_date = do_start.date; + } else { + startpage_date = false; + } + trace("HAS STARTPAGE"); + trace(startpage_date); + + if (startpage_date && startpage_date < _dates[0].startdate) { + _date.startdate = new Date(startpage_date); + } else { + td = _dates[0].startdate; + _date.startdate = new Date(_dates[0].startdate); + + if (td.getMonth() === 0 && td.getDate() == 1 && td.getHours() === 0 && td.getMinutes() === 0 ) { + // trace("YEAR ONLY"); + _date.startdate.setFullYear(td.getFullYear() - 1); + } else if (td.getDate() <= 1 && td.getHours() === 0 && td.getMinutes() === 0) { + // trace("YEAR MONTH"); + _date.startdate.setMonth(td.getMonth() - 1); + } else if (td.getHours() === 0 && td.getMinutes() === 0) { + // trace("YEAR MONTH DAY"); + _date.startdate.setDate(td.getDate() - 1); + } else if (td.getMinutes() === 0) { + // trace("YEAR MONTH DAY HOUR"); + _date.startdate.setHours(td.getHours() - 1); + } else { + // trace("YEAR MONTH DAY HOUR MINUTE"); + _date.startdate.setMinutes(td.getMinutes() - 1); + } + } + + _date.uniqueid = VMM.Util.unique_ID(7); + _date.enddate = _date.startdate; + _date.precisiondate = do_start.precision; + _date.title = data.headline; + _date.headline = data.headline; + _date.text = data.text; + _date.type = "start"; + _date.date = VMM.Date.prettyDate(data.startDate, false, _date.precisiondate); + _date.asset = data.asset; + _date.slug = false; + _date.needs_slug = false; + _date.fulldate = _date.startdate.getTime(); + + if (config.embed) { + VMM.fireEvent(global, config.events.headline, _date.headline); + } + + _dates.unshift(_date); + } + + /* CUSTOM SORT + ================================================== */ + if (data.type != "storify") { + _dates.sort(function(a, b){ + return a.fulldate - b.fulldate + }); + } + + onDatesProcessed(); + } + + }; + + VMM.Timeline.Config = {}; + +}; + +/* ********************************************** + Begin VMM.Timeline.TimeNav.js +********************************************** */ + +/* TimeNav + This class handles the bottom timeline navigation. + It requires the VMM.Util class and VMM.Date class +================================================== */ + +if(typeof VMM.Timeline != 'undefined' && typeof VMM.Timeline.TimeNav == 'undefined') { + + VMM.Timeline.TimeNav = function(parent, content_width, content_height) { + trace("VMM.Timeline.TimeNav"); + + var $timenav, $content, $time, $timeintervalminor, $timeinterval, $timeintervalmajor, $timebackground, + $timeintervalbackground, $timenavline, $timenavindicator, $timeintervalminor_minor, $toolbar, $zoomin, $zoomout, $dragslide, + config = VMM.Timeline.Config, + row_height, + events = {}, + timespan = {}, + layout = parent, + data = [], + era_markers = [], + markers = [], + interval_array = [], + interval_major_array = [], + tags = [], + current_marker = 0, + _active = false, + eras, + content, + timeouts = { + interval_position: "" + }, + timenav_pos = { + left: "", + visible: { + left: "", + right: "" + } + }, + timelookup = { + day: 24, + month: 12, + year: 10, + hour: 60, + minute: 60, + second: 1000, + decade: 10, + century: 100, + millenium: 1000, + age: 1000000, + epoch: 10000000, + era: 100000000, + eon: 500000000, + week: 4.34812141, + days_in_month: 30.4368499, + days_in_week: 7, + weeks_in_month: 4.34812141, + weeks_in_year: 52.177457, + days_in_year: 365.242199, + hours_in_day: 24 + }, + dateFractionBrowser = { + day: 86400000, + week: 7, + month: 30.4166666667, + year: 12, + hour: 24, + minute: 1440, + second: 86400, + decade: 10, + century: 100, + millenium: 1000, + age: 1000000, + epoch: 10000000, + era: 100000000, + eon: 500000000 + }, + interval = { + type: "year", + number: 10, + first: 1970, + last: 2011, + multiplier: 100, + classname: "_idd", + interval_type: "interval" + }, + interval_major = { + type: "year", + number: 10, + first: 1970, + last: 2011, + multiplier: 100, + classname: "major", + interval_type: "interval major" + }, + interval_macro = { + type: "year", + number: 10, + first: 1970, + last: 2011, + multiplier: 100, + classname: "_dd_minor", + interval_type: "interval minor" + }, + interval_calc = { + day: {}, + month: {}, + year: {}, + hour: {}, + minute: {}, + second: {}, + decade: {}, + century: {}, + millenium: {}, + week: {}, + age: {}, + epoch: {}, + era: {}, + eon: {} + }; + + + /* ADD to Config + ================================================== */ + row_height = config.nav.marker.height/2; + config.nav.rows = { + full: [1, row_height*2, row_height*4], + half: [1, row_height, row_height*2, row_height*3, row_height*4, row_height*5], + current: [] + } + + if (content_width != null && content_width != "") { + config.nav.width = content_width; + } + if (content_height != null && content_height != "") { + config.nav.height = content_height; + } + + /* INIT + ================================================== */ + this.init = function(d,e) { + trace('VMM.Timeline.TimeNav init'); + // need to evaluate d + // some function to determine type of data and prepare it + if(typeof d != 'undefined') { + this.setData(d, e); + } else { + trace("WAITING ON DATA"); + } + }; + + /* GETTERS AND SETTERS + ================================================== */ + this.setData = function(d,e) { + if(typeof d != 'undefined') { + data = {}; + data = d; + eras = e; + build(); + } else{ + trace("NO DATA"); + } + }; + + this.setSize = function(w, h) { + if (w != null) {config.width = w}; + if (h != null) {config.height = h}; + if (_active) { + reSize(); + } + + + } + + this.setMarker = function(n, ease, duration, fast) { + goToMarker(n, ease, duration); + } + + this.getCurrentNumber = function() { + return current_marker; + } + + /* ON EVENT + ================================================== */ + + function onConfigSet() { + trace("onConfigSet"); + }; + + function reSize(firstrun) { + config.nav.constraint.left = (config.width/2); + config.nav.constraint.right = config.nav.constraint.right_min - (config.width/2); + $dragslide.updateConstraint(config.nav.constraint); + + VMM.Lib.css($timenavline, "left", Math.round(config.width/2)+2); + VMM.Lib.css($timenavindicator, "left", Math.round(config.width/2)-8); + goToMarker(config.current_slide, config.ease, config.duration, true, firstrun); + }; + + function upDate() { + VMM.fireEvent(layout, "UPDATE"); + } + + function onZoomIn() { + + $dragslide.cancelSlide(); + if (config.nav.multiplier.current > config.nav.multiplier.min) { + if (config.nav.multiplier.current <= 1) { + config.nav.multiplier.current = config.nav.multiplier.current - .25; + } else { + if (config.nav.multiplier.current > 5) { + if (config.nav.multiplier.current > 16) { + config.nav.multiplier.current = Math.round(config.nav.multiplier.current - 10); + } else { + config.nav.multiplier.current = Math.round(config.nav.multiplier.current - 4); + } + } else { + config.nav.multiplier.current = Math.round(config.nav.multiplier.current - 1); + } + + } + if (config.nav.multiplier.current <= 0) { + config.nav.multiplier.current = config.nav.multiplier.min; + } + refreshTimeline(); + } + } + + function onZoomOut() { + $dragslide.cancelSlide(); + if (config.nav.multiplier.current < config.nav.multiplier.max) { + if (config.nav.multiplier.current > 4) { + if (config.nav.multiplier.current > 16) { + config.nav.multiplier.current = Math.round(config.nav.multiplier.current + 10); + } else { + config.nav.multiplier.current = Math.round(config.nav.multiplier.current + 4); + } + } else { + config.nav.multiplier.current = Math.round(config.nav.multiplier.current + 1); + } + + if (config.nav.multiplier.current >= config.nav.multiplier.max) { + config.nav.multiplier.current = config.nav.multiplier.max; + } + refreshTimeline(); + } + } + + function onBackHome(e) { + $dragslide.cancelSlide(); + goToMarker(0); + upDate(); + } + + function onMouseScroll(e) { + var delta = 0, + scroll_to = 0; + if (!e) { + e = window.event; + } + if (e.originalEvent) { + e = e.originalEvent; + } + if (e.wheelDelta) { + delta = e.wheelDelta/6; + } else if (e.detail) { + delta = -e.detail*12; + } + if (delta) { + if (e.preventDefault) { + e.preventDefault(); + } + e.returnValue = false; + } + // Webkit + if (typeof e.wheelDeltaX != 'undefined' ) { + delta = e.wheelDeltaY/6; + if (Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY)) { + delta = e.wheelDeltaX/6; + } else { + delta = e.wheelDeltaY/6; + } + } + + // Stop from scrolling too far + scroll_to = VMM.Lib.position($timenav).left + delta; + + if (scroll_to > config.nav.constraint.left) { + scroll_to = config.width/2; + } else if (scroll_to < config.nav.constraint.right) { + scroll_to = config.nav.constraint.right; + } + + //VMM.Lib.stop($timenav); + //VMM.Lib.animate($timenav, config.duration/2, "linear", {"left": scroll_to}); + VMM.Lib.css($timenav, "left", scroll_to); + } + + function refreshTimeline() { + trace("config.nav.multiplier " + config.nav.multiplier.current); + positionMarkers(true); + positionEras(true); + positionInterval($timeinterval, interval_array, true, true); + positionInterval($timeintervalmajor, interval_major_array, true); + config.nav.constraint.left = (config.width/2); + config.nav.constraint.right = config.nav.constraint.right_min - (config.width/2); + $dragslide.updateConstraint(config.nav.constraint); + }; + + /* MARKER EVENTS + ================================================== */ + function onMarkerClick(e) { + $dragslide.cancelSlide(); + goToMarker(e.data.number); + upDate(); + }; + + function onMarkerHover(e) { + VMM.Lib.toggleClass(e.data.elem, "zFront"); + }; + + function goToMarker(n, ease, duration, fast, firstrun) { + trace("GO TO MARKER"); + var _ease = config.ease, + _duration = config.duration, + is_last = false, + is_first = false; + + current_marker = n; + + timenav_pos.left = (config.width/2) - markers[current_marker].pos_left + timenav_pos.visible.left = Math.abs(timenav_pos.left) - 100; + timenav_pos.visible.right = Math.abs(timenav_pos.left) + config.width + 100; + + if (current_marker == 0) { + is_first = true; + } + if (current_marker +1 == markers.length) { + is_last = true + } + if (ease != null && ease != "") {_ease = ease}; + if (duration != null && duration != "") {_duration = duration}; + + // set marker style + for(var i = 0; i < markers.length; i++) { + VMM.Lib.removeClass(markers[i].marker, "active"); + } + + if (config.start_page && markers[0].type == "start") { + VMM.Lib.visible(markers[0].marker, false); + VMM.Lib.addClass(markers[0].marker, "start"); + } + + VMM.Lib.addClass(markers[current_marker].marker, "active"); + + // ANIMATE MARKER + VMM.Lib.stop($timenav); + VMM.Lib.animate($timenav, _duration, _ease, {"left": timenav_pos.left}); + + } + + /* TOUCH EVENTS + ================================================== */ + function onTouchUpdate(e, b) { + VMM.Lib.animate($timenav, b.time/2, config.ease, {"left": b.left}); + }; + + /* CALCULATIONS + ================================================== */ + function averageMarkerPositionDistance() { + var last_pos = 0, + pos = 0, + pos_dif = 0, + mp_diff = [], + i = 0; + + for(i = 0; i < markers.length; i++) { + if (data[i].type == "start") { + + } else { + var _pos = positionOnTimeline(interval, markers[i].relative_pos), + last_pos = pos; + pos = _pos.begin; + pos_dif = pos - last_pos; + mp_diff.push(pos_dif); + } + } + return VMM.Util.average(mp_diff).mean; + } + + function averageDateDistance() { + var last_dd = 0, + dd = 0, + _dd = "", + date_dif = 0, + date_diffs = [], + is_first_date = true, + i = 0; + + for(i = 0; i < data.length; i++) { + if (data[i].type == "start") { + trace("DATA DATE IS START") + } else { + _dd = data[i].startdate; + last_dd = dd; + dd = _dd; + date_dif = dd - last_dd; + date_diffs.push(date_dif); + } + } + + return VMM.Util.average(date_diffs); + } + + function calculateMultiplier() { + var temp_multiplier = config.nav.multiplier.current, + i = 0; + + for(i = 0; i < temp_multiplier; i++) { + if (averageMarkerPositionDistance() < 75) { + if (config.nav.multiplier.current > 1) { + config.nav.multiplier.current = (config.nav.multiplier.current - 1); + } + } + } + + } + + function calculateInterval() { + // NEED TO REWRITE ALL OF THIS + var _first = getDateFractions(data[0].startdate), + _last = getDateFractions(data[data.length - 1].enddate); + + // EON + interval_calc.eon.type = "eon"; + interval_calc.eon.first = _first.eons; + interval_calc.eon.base = Math.floor(_first.eons); + interval_calc.eon.last = _last.eons; + interval_calc.eon.number = timespan.eons; + interval_calc.eon.multiplier = timelookup.eons; + interval_calc.eon.minor = timelookup.eons; + + // ERA + interval_calc.era.type = "era"; + interval_calc.era.first = _first.eras; + interval_calc.era.base = Math.floor(_first.eras); + interval_calc.era.last = _last.eras; + interval_calc.era.number = timespan.eras; + interval_calc.era.multiplier = timelookup.eras; + interval_calc.era.minor = timelookup.eras; + + // EPOCH + interval_calc.epoch.type = "epoch"; + interval_calc.epoch.first = _first.epochs; + interval_calc.epoch.base = Math.floor(_first.epochs); + interval_calc.epoch.last = _last.epochs; + interval_calc.epoch.number = timespan.epochs; + interval_calc.epoch.multiplier = timelookup.epochs; + interval_calc.epoch.minor = timelookup.epochs; + + // AGE + interval_calc.age.type = "age"; + interval_calc.age.first = _first.ages; + interval_calc.age.base = Math.floor(_first.ages); + interval_calc.age.last = _last.ages; + interval_calc.age.number = timespan.ages; + interval_calc.age.multiplier = timelookup.ages; + interval_calc.age.minor = timelookup.ages; + + // MILLENIUM + interval_calc.millenium.type = "millenium"; + interval_calc.millenium.first = _first.milleniums; + interval_calc.millenium.base = Math.floor(_first.milleniums); + interval_calc.millenium.last = _last.milleniums; + interval_calc.millenium.number = timespan.milleniums; + interval_calc.millenium.multiplier = timelookup.millenium; + interval_calc.millenium.minor = timelookup.millenium; + + // CENTURY + interval_calc.century.type = "century"; + interval_calc.century.first = _first.centuries; + interval_calc.century.base = Math.floor(_first.centuries); + interval_calc.century.last = _last.centuries; + interval_calc.century.number = timespan.centuries; + interval_calc.century.multiplier = timelookup.century; + interval_calc.century.minor = timelookup.century; + + // DECADE + interval_calc.decade.type = "decade"; + interval_calc.decade.first = _first.decades; + interval_calc.decade.base = Math.floor(_first.decades); + interval_calc.decade.last = _last.decades; + interval_calc.decade.number = timespan.decades; + interval_calc.decade.multiplier = timelookup.decade; + interval_calc.decade.minor = timelookup.decade; + + // YEAR + interval_calc.year.type = "year"; + interval_calc.year.first = _first.years; + interval_calc.year.base = Math.floor(_first.years); + interval_calc.year.last = _last.years; + interval_calc.year.number = timespan.years; + interval_calc.year.multiplier = 1; + interval_calc.year.minor = timelookup.month; + + // MONTH + interval_calc.month.type = "month"; + interval_calc.month.first = _first.months; + interval_calc.month.base = Math.floor(_first.months); + interval_calc.month.last = _last.months; + interval_calc.month.number = timespan.months; + interval_calc.month.multiplier = 1; + interval_calc.month.minor = Math.round(timelookup.week); + + // WEEK + // NOT DONE + interval_calc.week.type = "week"; + interval_calc.week.first = _first.weeks; + interval_calc.week.base = Math.floor(_first.weeks); + interval_calc.week.last = _last.weeks; + interval_calc.week.number = timespan.weeks; + interval_calc.week.multiplier = 1; + interval_calc.week.minor = 7; + + // DAY + interval_calc.day.type = "day"; + interval_calc.day.first = _first.days; + interval_calc.day.base = Math.floor(_first.days); + interval_calc.day.last = _last.days; + interval_calc.day.number = timespan.days; + interval_calc.day.multiplier = 1; + interval_calc.day.minor = 24; + + // HOUR + interval_calc.hour.type = "hour"; + interval_calc.hour.first = _first.hours; + interval_calc.hour.base = Math.floor(_first.hours); + interval_calc.hour.last = _last.hours; + interval_calc.hour.number = timespan.hours; + interval_calc.hour.multiplier = 1; + interval_calc.hour.minor = 60; + + // MINUTE + interval_calc.minute.type = "minute"; + interval_calc.minute.first = _first.minutes; + interval_calc.minute.base = Math.floor(_first.minutes); + interval_calc.minute.last = _last.minutes; + interval_calc.minute.number = timespan.minutes; + interval_calc.minute.multiplier = 1; + interval_calc.minute.minor = 60; + + // SECOND + interval_calc.second.type = "decade"; + interval_calc.second.first = _first.seconds; + interval_calc.second.base = Math.floor(_first.seconds); + interval_calc.second.last = _last.seconds; + interval_calc.second.number = timespan.seconds; + interval_calc.second.multiplier = 1; + interval_calc.second.minor = 10; + } + + function getDateFractions(the_date, is_utc) { + + var _time = {}; + _time.days = the_date / dateFractionBrowser.day; + _time.weeks = _time.days / dateFractionBrowser.week; + _time.months = _time.days / dateFractionBrowser.month; + _time.years = _time.months / dateFractionBrowser.year; + _time.hours = _time.days * dateFractionBrowser.hour; + _time.minutes = _time.days * dateFractionBrowser.minute; + _time.seconds = _time.days * dateFractionBrowser.second; + _time.decades = _time.years / dateFractionBrowser.decade; + _time.centuries = _time.years / dateFractionBrowser.century; + _time.milleniums = _time.years / dateFractionBrowser.millenium; + _time.ages = _time.years / dateFractionBrowser.age; + _time.epochs = _time.years / dateFractionBrowser.epoch; + _time.eras = _time.years / dateFractionBrowser.era; + _time.eons = _time.years / dateFractionBrowser.eon; + + /* + trace("AGES " + _time.ages); + trace("EPOCHS " + _time.epochs); + trace("MILLENIUMS " + _time.milleniums); + trace("CENTURIES " + _time.centuries); + trace("DECADES " + _time.decades); + trace("YEARS " + _time.years); + trace("MONTHS " + _time.months); + trace("WEEKS " + _time.weeks); + trace("DAYS " + _time.days); + trace("HOURS " + _time.hours); + trace("MINUTES " + _time.minutes); + trace("SECONDS " + _time.seconds); + */ + return _time; + } + + /* POSITION + Positions elements on the timeline based on date + relative to the calculated interval + ================================================== */ + function positionRelative(_interval, first, last) { + var _first, + _last, + _type = _interval.type, + timerelative = { + start: "", + end: "", + type: _type + }; + + /* FIRST + ================================================== */ + _first = getDateFractions(first); + timerelative.start = first.months; + + if (_type == "eon") { + timerelative.start = _first.eons; + } else if (_type == "era") { + timerelative.start = _first.eras; + } else if (_type == "epoch") { + timerelative.start = _first.epochs; + } else if (_type == "age") { + timerelative.start = _first.ages; + } else if (_type == "millenium") { + timerelative.start = first.milleniums; + } else if (_type == "century") { + timerelative.start = _first.centuries; + } else if (_type == "decade") { + timerelative.start = _first.decades; + } else if (_type == "year") { + timerelative.start = _first.years; + } else if (_type == "month") { + timerelative.start = _first.months; + } else if (_type == "week") { + timerelative.start = _first.weeks; + } else if (_type == "day") { + timerelative.start = _first.days; + } else if (_type == "hour") { + timerelative.start = _first.hours; + } else if (_type == "minute") { + timerelative.start = _first.minutes; + } + + /* LAST + ================================================== */ + if (type.of(last) == "date") { + + _last = getDateFractions(last); + timerelative.end = last.months; + + if (_type == "eon") { + timerelative.end = _last.eons; + } else if (_type == "era") { + timerelative.end = _last.eras; + } else if (_type == "epoch") { + timerelative.end = _last.epochs; + } else if (_type == "age") { + timerelative.end = _last.ages; + } else if (_type == "millenium") { + timerelative.end = last.milleniums; + } else if (_type == "century") { + timerelative.end = _last.centuries; + } else if (_type == "decade") { + timerelative.end = _last.decades; + } else if (_type == "year") { + timerelative.end = _last.years; + } else if (_type == "month") { + timerelative.end = _last.months; + } else if (_type == "week") { + timerelative.end = _last.weeks; + } else if (_type == "day") { + timerelative.end = _last.days; + } else if (_type == "hour") { + timerelative.end = _last.hours; + } else if (_type == "minute") { + timerelative.end = _last.minutes; + } + + } else { + + timerelative.end = timerelative.start; + + } + + return timerelative + } + + function positionOnTimeline(the_interval, timerelative) { + return { + begin: (timerelative.start - interval.base) * (config.nav.interval_width / config.nav.multiplier.current), + end: (timerelative.end - interval.base) * (config.nav.interval_width / config.nav.multiplier.current) + }; + } + + function positionMarkers(is_animated) { + + var row = 2, + previous_pos = 0, + pos_offset = -2, + row_depth = 0, + row_depth_sub = 0, + line_last_height_pos = 150, + line_height = 6, + cur_mark = 0, + in_view_margin = config.width, + pos_cache_array = [], + pos_cache_max = 6, + in_view = { + left: timenav_pos.visible.left - in_view_margin, + right: timenav_pos.visible.right + in_view_margin + }, + i = 0, + k = 0; + + config.nav.minor_width = config.width; + + VMM.Lib.removeClass(".flag", "row1"); + VMM.Lib.removeClass(".flag", "row2"); + VMM.Lib.removeClass(".flag", "row3"); + + for(i = 0; i < markers.length; i++) { + + var line, + marker = markers[i], + pos = positionOnTimeline(interval, markers[i].relative_pos), + row_pos = 0, + is_in_view = false, + pos_cache_obj = {id: i, pos: 0, row: 0}, + pos_cache_close = 0; + + + // COMPENSATE FOR DATES BEING POITIONED IN THE MIDDLE + pos.begin = Math.round(pos.begin + pos_offset); + pos.end = Math.round(pos.end + pos_offset); + line = Math.round(pos.end - pos.begin); + marker.pos_left = pos.begin; + + if (current_marker == i) { + timenav_pos.left = (config.width/2) - pos; + timenav_pos.visible.left = Math.abs(timenav_pos.left); + timenav_pos.visible.right = Math.abs(timenav_pos.left) + config.width; + in_view.left = timenav_pos.visible.left - in_view_margin; + in_view.right = timenav_pos.visible.right + in_view_margin; + } + + if (Math.abs(pos.begin) >= in_view.left && Math.abs(pos.begin) <= in_view.right ) { + is_in_view = true; + } + + // APPLY POSITION TO MARKER + if (is_animated) { + VMM.Lib.stop(marker.marker); + VMM.Lib.animate(marker.marker, config.duration/2, config.ease, {"left": pos.begin}); + } else { + VMM.Lib.stop(marker.marker); + VMM.Lib.css(marker.marker, "left", pos.begin); + } + + if (i == current_marker) { + cur_mark = pos.begin; + } + + // EVENT LENGTH LINE + if (line > 5) { + VMM.Lib.css(marker.lineevent, "height", line_height); + VMM.Lib.css(marker.lineevent, "top", line_last_height_pos); + if (is_animated) { + VMM.Lib.animate(marker.lineevent, config.duration/2, config.ease, {"width": line}); + } else { + VMM.Lib.css(marker.lineevent, "width", line); + } + } + + // CONTROL ROW POSITION + if (tags.length > 0) { + + for (k = 0; k < tags.length; k++) { + if (k < config.nav.rows.current.length) { + if (marker.tag == tags[k]) { + row = k; + if (k == config.nav.rows.current.length - 1) { + trace("ON LAST ROW"); + VMM.Lib.addClass(marker.flag, "flag-small-last"); + } + } + } + } + row_pos = config.nav.rows.current[row]; + } else { + + if (pos.begin - previous_pos.begin < (config.nav.marker.width + config.spacing)) { + if (row < config.nav.rows.current.length - 1) { + row ++; + + } else { + row = 0; + row_depth ++; + } + } else { + row_depth = 1; + row = 1; + } + row_pos = config.nav.rows.current[row]; + + } + + // SET LAST MARKER POSITION + previous_pos = pos; + + // POSITION CACHE + pos_cache_obj.pos = pos; + pos_cache_obj.row = row; + pos_cache_array.push(pos_cache_obj); + if (pos_cache_array.length > pos_cache_max) { + pos_cache_array.remove(0); + } + + //if (is_animated && is_in_view) { + if (is_animated) { + VMM.Lib.stop(marker.flag); + VMM.Lib.animate(marker.flag, config.duration, config.ease, {"top": row_pos}); + } else { + VMM.Lib.stop(marker.flag); + VMM.Lib.css(marker.flag, "top", row_pos); + } + + // IS THE MARKER A REPRESENTATION OF A START SCREEN? + if (config.start_page && markers[i].type == "start") { + VMM.Lib.visible(marker.marker, false); + + } + + if (pos > config.nav.minor_width) { + config.nav.minor_width = pos; + } + + if (pos < config.nav.minor_left) { + config.nav.minor_left = pos; + } + + } + + // ANIMATE THE TIMELINE TO ADJUST TO CHANGES + if (is_animated) { + VMM.Lib.stop($timenav); + VMM.Lib.animate($timenav, config.duration/2, config.ease, {"left": (config.width/2) - (cur_mark)}); + } else { + + } + + //VMM.Lib.delay_animate(config.duration, $timenav, config.duration/2, config.ease, {"left": (config.width/2) - (cur_mark)}); + + + } + + function positionEras(is_animated) { + var i = 0, + p = 0; + + for(i = 0; i < era_markers.length; i++) { + var era = era_markers[i], + pos = positionOnTimeline(interval, era.relative_pos), + row_pos = 0, + row = 0, + era_height = config.nav.marker.height * config.nav.rows.full.length, + era_length = pos.end - pos.begin; + + // CONTROL ROW POSITION + if (era.tag != "") { + era_height = (config.nav.marker.height * config.nav.rows.full.length) / config.nav.rows.current.length; + for (p = 0; p < tags.length; p++) { + if (p < config.nav.rows.current.length) { + if (era.tag == tags[p]) { + row = p; + } + } + } + row_pos = config.nav.rows.current[row]; + + } else { + row_pos = -1; + } + + // APPLY POSITION TO MARKER + if (is_animated) { + VMM.Lib.stop(era.content); + VMM.Lib.stop(era.text_content); + VMM.Lib.animate(era.content, config.duration/2, config.ease, {"top": row_pos, "left": pos.begin, "width": era_length, "height":era_height}); + VMM.Lib.animate(era.text_content, config.duration/2, config.ease, {"left": pos.begin}); + } else { + VMM.Lib.stop(era.content); + VMM.Lib.stop(era.text_content); + VMM.Lib.css(era.content, "left", pos.begin); + VMM.Lib.css(era.content, "width", era_length); + VMM.Lib.css(era.content, "height", era_height); + VMM.Lib.css(era.content, "top", row_pos); + VMM.Lib.css(era.text_content, "left", pos.begin); + + } + + } + } + + function positionInterval(the_main_element, the_intervals, is_animated, is_minor) { + + var last_position = 0, + last_position_major = 0, + //in_view_margin = (config.nav.minor_width/config.nav.multiplier.current)/2, + in_view_margin = config.width, + in_view = { + left: timenav_pos.visible.left - in_view_margin, + right: timenav_pos.visible.right + in_view_margin + } + not_too_many = true, + i = 0; + + config.nav.minor_left = 0; + + if (the_intervals.length > 100) { + not_too_many = false; + trace("TOO MANY " + the_intervals.length); + } + + + for(i = 0; i < the_intervals.length; i++) { + var _interval = the_intervals[i].element, + _interval_date = the_intervals[i].date, + _interval_visible = the_intervals[i].visible, + _pos = positionOnTimeline(interval, the_intervals[i].relative_pos), + pos = _pos.begin, + _animation = the_intervals[i].animation, + is_visible = true, + is_in_view = false, + pos_offset = 50; + + + _animation.pos = pos; + _animation.animate = false; + + if (Math.abs(pos) >= in_view.left && Math.abs(pos) <= in_view.right ) { + is_in_view = true; + } + + if (true) { + + // CONDENSE WHAT IS DISPLAYED + if (config.nav.multiplier.current > 16 && is_minor) { + is_visible = false; + } else { + if ((pos - last_position) < 65 ) { + if ((pos - last_position) < 35 ) { + if (i%4 == 0) { + if (pos == 0) { + is_visible = false; + } + } else { + is_visible = false; + } + } else { + if (!VMM.Util.isEven(i)) { + is_visible = false; + } + } + } + } + + if (is_visible) { + if (the_intervals[i].is_detached) { + VMM.Lib.append(the_main_element, _interval); + the_intervals[i].is_detached = false; + } + } else { + the_intervals[i].is_detached = true; + VMM.Lib.detach(_interval); + } + + + if (_interval_visible) { + if (!is_visible) { + _animation.opacity = "0"; + if (is_animated && not_too_many) { + _animation.animate = true; + } + the_intervals[i].interval_visible = false; + } else { + _animation.opacity = "100"; + if (is_animated && is_in_view) { + _animation.animate = true; + } + } + } else { + _animation.opacity = "100"; + if (is_visible) { + if (is_animated && not_too_many) { + _animation.animate = true; + } else { + if (is_animated && is_in_view) { + _animation.animate = true; + } + } + the_intervals[i].interval_visible = true; + } else { + if (is_animated && not_too_many) { + _animation.animate = true; + } + } + } + + last_position = pos; + + if (pos > config.nav.minor_width) { + config.nav.minor_width = pos; + } + + if (pos < config.nav.minor_left) { + config.nav.minor_left = pos; + } + + } + + if (_animation.animate) { + VMM.Lib.animate(_interval, config.duration/2, config.ease, {opacity: _animation.opacity, left: _animation.pos}); + } else { + VMM.Lib.css(_interval, "opacity", _animation.opacity); + VMM.Lib.css(_interval, "left", pos); + } + } + + config.nav.constraint.right_min = -(config.nav.minor_width)+(config.width); + config.nav.constraint.right = config.nav.constraint.right_min + (config.width/2); + + VMM.Lib.css($timeintervalminor_minor, "left", config.nav.minor_left - (config.width)/2); + VMM.Lib.width($timeintervalminor_minor, (config.nav.minor_width)+(config.width) + Math.abs(config.nav.minor_left) ); + + } + + /* Interval Elements + ================================================== */ + function createIntervalElements(_interval, _array, _element_parent) { + + var inc_time = 0, + _first_run = true, + _last_pos = 0, + _largest_pos = 0, + _timezone_offset, + _first_date, + _last_date, + int_number = Math.ceil(_interval.number) + 2, + firefox = { + flag: false, + offset: 0 + }, + i = 0; + + VMM.attachElement(_element_parent, ""); + + _interval.date = new Date(data[0].startdate.getFullYear(), 0, 1, 0,0,0); + _timezone_offset = _interval.date.getTimezoneOffset(); + + for(i = 0; i < int_number; i++) { + trace(_interval.type); + var _is_year = false, + int_obj = { + element: VMM.appendAndGetElement(_element_parent, "<div>", _interval.classname), + date: new Date(data[0].startdate.getFullYear(), 0, 1, 0,0,0), + visible: false, + date_string: "", + type: _interval.interval_type, + relative_pos: 0, + is_detached: false, + animation: { + animate: false, + pos: "", + opacity: "100" + + } + }; + + if (_interval.type == "eon") { + if (_first_run) { + _first_date = Math.floor(data[0].startdate.getFullYear() / 500000000) * 500000000; + } + int_obj.date.setFullYear(_first_date + (inc_time * 500000000)); + _is_year = true; + } else if (_interval.type == "era") { + if (_first_run) { + _first_date = Math.floor(data[0].startdate.getFullYear() / 100000000) * 100000000; + } + int_obj.date.setFullYear(_first_date + (inc_time * 100000000)); + _is_year = true; + } else if (_interval.type == "epoch") { + if (_first_run) { + _first_date = Math.floor(data[0].startdate.getFullYear() / 10000000) * 10000000 + } + int_obj.date.setFullYear(_first_date + (inc_time * 10000000)); + _is_year = true; + } else if (_interval.type == "age") { + if (_first_run) { + _first_date = Math.floor(data[0].startdate.getFullYear() / 1000000) * 1000000 + } + int_obj.date.setFullYear(_first_date + (inc_time * 1000000)); + _is_year = true; + } else if (_interval.type == "millenium") { + if (_first_run) { + _first_date = Math.floor(data[0].startdate.getFullYear() / 1000) * 1000; + } + int_obj.date.setFullYear(_first_date + (inc_time * 1000)); + _is_year = true; + } else if (_interval.type == "century") { + if (_first_run) { + _first_date = Math.floor(data[0].startdate.getFullYear() / 100) * 100 + } + int_obj.date.setFullYear(_first_date + (inc_time * 100)); + _is_year = true; + } else if (_interval.type == "decade") { + if (_first_run) { + _first_date = Math.floor(data[0].startdate.getFullYear() / 10) * 10; + } + int_obj.date.setFullYear(_first_date + (inc_time * 10)); + _is_year = true; + } else if (_interval.type == "year") { + if (_first_run) { + _first_date = data[0].startdate.getFullYear(); + } + int_obj.date.setFullYear(_first_date + inc_time); + _is_year = true; + } else if (_interval.type == "month") { + if (_first_run) { + _first_date = data[0].startdate.getMonth(); + } + int_obj.date.setMonth(_first_date + inc_time); + } else if (_interval.type == "week") { + if (_first_run) { + _first_date = data[0].startdate.getMonth(); + } + int_obj.date.setMonth(data[0].startdate.getMonth()); + int_obj.date.setDate(_first_date + (inc_time * 7) ); + } else if (_interval.type == "day") { + if (_first_run) { + _first_date = data[0].startdate.getDate(); + } + int_obj.date.setMonth(data[0].startdate.getMonth()); + int_obj.date.setDate(_first_date + inc_time); + } else if (_interval.type == "hour") { + if (_first_run) { + _first_date = data[0].startdate.getHours(); + } + int_obj.date.setMonth(data[0].startdate.getMonth()); + int_obj.date.setDate(data[0].startdate.getDate()); + int_obj.date.setHours(_first_date + inc_time); + } else if (_interval.type == "minute") { + if (_first_run) { + _first_date = data[0].startdate.getMinutes(); + } + int_obj.date.setMonth(data[0].startdate.getMonth()); + int_obj.date.setDate(data[0].startdate.getDate()); + int_obj.date.setHours(data[0].startdate.getHours()); + int_obj.date.setMinutes(_first_date + inc_time); + } else if (_interval.type == "second") { + if (_first_run) { + _first_date = data[0].startdate.getSeconds(); + } + int_obj.date.setMonth(data[0].startdate.getMonth()); + int_obj.date.setDate(data[0].startdate.getDate()); + int_obj.date.setHours(data[0].startdate.getHours()); + int_obj.date.setMinutes(data[0].startdate.getMinutes()); + int_obj.date.setSeconds(_first_date + inc_time); + } else if (_interval.type == "millisecond") { + if (_first_run) { + _first_date = data[0].startdate.getMilliseconds(); + } + int_obj.date.setMonth(data[0].startdate.getMonth()); + int_obj.date.setDate(data[0].startdate.getDate()); + int_obj.date.setHours(data[0].startdate.getHours()); + int_obj.date.setMinutes(data[0].startdate.getMinutes()); + int_obj.date.setSeconds(data[0].startdate.getSeconds()); + int_obj.date.setMilliseconds(_first_date + inc_time); + } + + // FIX WEIRD FIREFOX BUG FOR GMT TIME FORMATTING + if (VMM.Browser.browser == "Firefox") { + if (int_obj.date.getFullYear() == "1970" && int_obj.date.getTimezoneOffset() != _timezone_offset) { + + trace("FIREFOX 1970 TIMEZONE OFFSET " + int_obj.date.getTimezoneOffset() + " SHOULD BE " + _timezone_offset); + trace(_interval.type + " " + _interval.date); + + // try and fix firefox bug, if not the flag will catch it + firefox.offset = (int_obj.date.getTimezoneOffset()/60); + firefox.flag = true; + int_obj.date.setHours(int_obj.date.getHours() + firefox.offset ); + + } else if (firefox.flag) { + // catch the bug the second time around + firefox.flag = false; + int_obj.date.setHours(int_obj.date.getHours() + firefox.offset ); + if (_is_year) { + firefox.flag = true; + } + } + + } + + if (_is_year) { + if ( int_obj.date.getFullYear() < 0 ) { + int_obj.date_string = Math.abs( int_obj.date.getFullYear() ).toString() + " a.C."; + } else { + int_obj.date_string = int_obj.date.getFullYear(); + } + } else { + int_obj.date_string = VMM.Date.prettyDate(int_obj.date, true); + } + + // Increment Time + inc_time = inc_time + 1; + + // No longer first run + _first_run = false; + + int_obj.relative_pos = positionRelative(interval, int_obj.date); + _last_pos = int_obj.relative_pos.begin; + if (int_obj.relative_pos.begin > _largest_pos) { + _largest_pos = int_obj.relative_pos.begin; + } + + // Add the time string to the element and position it. + VMM.appendElement(int_obj.element, int_obj.date_string); + VMM.Lib.css(int_obj.element, "text-indent", -(VMM.Lib.width(int_obj.element)/2)); + VMM.Lib.css(int_obj.element, "opacity", "0"); + + // add the interval element to the array + _array.push(int_obj); + + } + + VMM.Lib.width($timeintervalminor_minor, _largest_pos); + + positionInterval(_element_parent, _array); + + + + } + + /* BUILD + ================================================== */ + function build() { + var i = 0, + j = 0; + + VMM.attachElement(layout, ""); + + $timenav = VMM.appendAndGetElement(layout, "<div>", "timenav"); + $content = VMM.appendAndGetElement($timenav, "<div>", "content"); + $time = VMM.appendAndGetElement($timenav, "<div>", "time"); + $timeintervalminor = VMM.appendAndGetElement($time, "<div>", "time-interval-minor"); + $timeintervalminor_minor = VMM.appendAndGetElement($timeintervalminor, "<div>", "minor"); + $timeintervalmajor = VMM.appendAndGetElement($time, "<div>", "time-interval-major"); + $timeinterval = VMM.appendAndGetElement($time, "<div>", "time-interval"); + $timebackground = VMM.appendAndGetElement(layout, "<div>", "timenav-background"); + $timenavline = VMM.appendAndGetElement($timebackground, "<div>", "timenav-line"); + $timenavindicator = VMM.appendAndGetElement($timebackground, "<div>", "timenav-indicator"); + $timeintervalbackground = VMM.appendAndGetElement($timebackground, "<div>", "timenav-interval-background", "<div class='top-highlight'></div>"); + $toolbar = VMM.appendAndGetElement(layout, "<div>", "vco-toolbar"); + + + buildInterval(); + buildMarkers(); + buildEras(); + calculateMultiplier(); + positionMarkers(false); + positionEras(); + + positionInterval($timeinterval, interval_array, false, true); + positionInterval($timeintervalmajor, interval_major_array); + + + if (config.start_page) { + $backhome = VMM.appendAndGetElement($toolbar, "<div>", "back-home", "<div class='icon'></div>"); + VMM.bindEvent(".back-home", onBackHome, "click"); + VMM.Lib.attribute($backhome, "title", VMM.master_config.language.messages.return_to_title); + VMM.Lib.attribute($backhome, "rel", "tooltip"); + + } + + + // MAKE TIMELINE DRAGGABLE/TOUCHABLE + $dragslide = new VMM.DragSlider; + $dragslide.createPanel(layout, $timenav, config.nav.constraint, config.touch); + + + + if (config.touch && config.start_page) { + VMM.Lib.addClass($toolbar, "touch"); + VMM.Lib.css($toolbar, "top", 55); + VMM.Lib.css($toolbar, "left", 10); + } else { + if (config.start_page) { + VMM.Lib.css($toolbar, "top", 27); + } + $zoomin = VMM.appendAndGetElement($toolbar, "<div>", "zoom-in", "<div class='icon'></div>"); + $zoomout = VMM.appendAndGetElement($toolbar, "<div>", "zoom-out", "<div class='icon'></div>"); + // ZOOM EVENTS + VMM.bindEvent($zoomin, onZoomIn, "click"); + VMM.bindEvent($zoomout, onZoomOut, "click"); + // TOOLTIP + VMM.Lib.attribute($zoomin, "title", VMM.master_config.language.messages.expand_timeline); + VMM.Lib.attribute($zoomin, "rel", "tooltip"); + VMM.Lib.attribute($zoomout, "title", VMM.master_config.language.messages.contract_timeline); + VMM.Lib.attribute($zoomout, "rel", "tooltip"); + $toolbar.tooltip({selector: "div[rel=tooltip]", placement: "right"}); + + + // MOUSE EVENTS + VMM.bindEvent(layout, onMouseScroll, 'DOMMouseScroll'); + VMM.bindEvent(layout, onMouseScroll, 'mousewheel'); + } + + + + // USER CONFIGURABLE ADJUSTMENT TO DEFAULT ZOOM + if (config.nav.zoom.adjust != 0) { + if (config.nav.zoom.adjust < 0) { + for(i = 0; i < Math.abs(config.nav.zoom.adjust); i++) { + onZoomOut(); + } + } else { + for(j = 0; j < config.nav.zoom.adjust; j++) { + onZoomIn(); + } + } + } + + //VMM.fireEvent(layout, "LOADED"); + _active = true; + + reSize(true); + VMM.fireEvent(layout, "LOADED"); + + }; + + function buildInterval() { + var i = 0, + j = 0; + // CALCULATE INTERVAL + timespan = getDateFractions((data[data.length - 1].enddate) - (data[0].startdate), true); + trace(timespan); + calculateInterval(); + + /* DETERMINE DEFAULT INTERVAL TYPE + millenium, ages, epoch, era and eon are not working yet + ================================================== */ + /* + if (timespan.eons > data.length / config.nav.density) { + interval = interval_calc.eon; + interval_major = interval_calc.eon; + interval_macro = interval_calc.era; + } else if (timespan.eras > data.length / config.nav.density) { + interval = interval_calc.era; + interval_major = interval_calc.eon; + interval_macro = interval_calc.epoch; + } else if (timespan.epochs > data.length / config.nav.density) { + interval = interval_calc.epoch; + interval_major = interval_calc.era; + interval_macro = interval_calc.age; + } else if (timespan.ages > data.length / config.nav.density) { + interval = interval_calc.ages; + interval_major = interval_calc.epoch; + interval_macro = interval_calc.millenium; + } else if (timespan.milleniums > data.length / config.nav.density) { + interval = interval_calc.millenium; + interval_major = interval_calc.age; + interval_macro = interval_calc.century; + } else + */ + if (timespan.centuries > data.length / config.nav.density) { + interval = interval_calc.century; + interval_major = interval_calc.millenium; + interval_macro = interval_calc.decade; + } else if (timespan.decades > data.length / config.nav.density) { + interval = interval_calc.decade; + interval_major = interval_calc.century; + interval_macro = interval_calc.year; + } else if (timespan.years > data.length / config.nav.density) { + interval = interval_calc.year; + interval_major = interval_calc.decade; + interval_macro = interval_calc.month; + } else if (timespan.months > data.length / config.nav.density) { + interval = interval_calc.month; + interval_major = interval_calc.year; + interval_macro = interval_calc.day; + } else if (timespan.days > data.length / config.nav.density) { + interval = interval_calc.day; + interval_major = interval_calc.month; + interval_macro = interval_calc.hour; + } else if (timespan.hours > data.length / config.nav.density) { + interval = interval_calc.hour; + interval_major = interval_calc.day; + interval_macro = interval_calc.minute; + } else if (timespan.minutes > data.length / config.nav.density) { + interval = interval_calc.minute; + interval_major = interval_calc.hour; + interval_macro = interval_calc.second; + } else if (timespan.seconds > data.length / config.nav.density) { + interval = interval_calc.second; + interval_major = interval_calc.minute; + interval_macro = interval_calc.second; + } else { + trace("NO IDEA WHAT THE TYPE SHOULD BE"); + interval = interval_calc.day; + interval_major = interval_calc.month; + interval_macro = interval_calc.hour; + } + + trace("INTERVAL TYPE: " + interval.type); + trace("INTERVAL MAJOR TYPE: " + interval_major.type); + + createIntervalElements(interval, interval_array, $timeinterval); + createIntervalElements(interval_major, interval_major_array, $timeintervalmajor); + + // Cleanup duplicate interval elements between normal and major + for(i = 0; i < interval_array.length; i++) { + for(j = 0; j < interval_major_array.length; j++) { + if (interval_array[i].date_string == interval_major_array[j].date_string) { + VMM.attachElement(interval_array[i].element, ""); + } + } + } + } + + function buildMarkers() { + + var row = 2, + lpos = 0, + row_depth = 0, + i = 0, + k = 0, + l = 0; + + + markers = []; + era_markers = []; + + for(i = 0; i < data.length; i++) { + + var _marker, + _marker_flag, + _marker_content, + _marker_dot, + _marker_line, + _marker_line_event, + _marker_obj, + _marker_title = "", + has_title = false; + + + _marker = VMM.appendAndGetElement($content, "<div>", "marker"); + _marker_flag = VMM.appendAndGetElement(_marker, "<div>", "flag"); + _marker_content = VMM.appendAndGetElement(_marker_flag, "<div>", "flag-content"); + _marker_dot = VMM.appendAndGetElement(_marker, "<div>", "dot"); + _marker_line = VMM.appendAndGetElement(_marker, "<div>", "line"); + _marker_line_event = VMM.appendAndGetElement(_marker_line, "<div>", "event-line"); + _marker_relative_pos = positionRelative(interval, data[i].startdate, data[i].enddate); + _marker_thumb = ""; + + // THUMBNAIL + if (data[i].asset != null && data[i].asset != "") { + VMM.appendElement(_marker_content, VMM.MediaElement.thumbnail(data[i].asset, 24, 24, data[i].uniqueid)); + } else { + VMM.appendElement(_marker_content, "<div style='margin-right:7px;height:50px;width:2px;float:left;'></div>"); + } + + // ADD DATE AND TITLE + if (data[i].title == "" || data[i].title == " " ) { + trace("TITLE NOTHING") + if (typeof data[i].slug != 'undefined' && data[i].slug != "") { + trace("SLUG") + _marker_title = VMM.Util.untagify(data[i].slug); + has_title = true; + } else { + var m = VMM.MediaType(data[i].asset.media); + if (m.type == "quote" || m.type == "unknown") { + _marker_title = VMM.Util.untagify(m.id); + has_title = true; + } else { + has_title = false; + } + } + } else if (data[i].title != "" || data[i].title != " ") { + trace(data[i].title) + _marker_title = VMM.Util.untagify(data[i].title); + has_title = true; + } else { + trace("TITLE SLUG NOT FOUND " + data[i].slug) + } + + if (has_title) { + VMM.appendElement(_marker_content, "<h3>" + _marker_title + "</h3>"); + } else { + VMM.appendElement(_marker_content, "<h3>" + _marker_title + "</h3>"); + VMM.appendElement(_marker_content, "<h3 id='marker_content_" + data[i].uniqueid + "'>" + _marker_title + "</h3>"); + } + + // ADD ID + VMM.Lib.attr(_marker, "id", ( "marker_" + data[i].uniqueid).toString() ); + + // MARKER CLICK + VMM.bindEvent(_marker_flag, onMarkerClick, "", {number: i}); + VMM.bindEvent(_marker_flag, onMarkerHover, "mouseenter mouseleave", {number: i, elem:_marker_flag}); + + _marker_obj = { + marker: _marker, + flag: _marker_flag, + lineevent: _marker_line_event, + type: "marker", + full: true, + relative_pos: _marker_relative_pos, + tag: data[i].tag, + pos_left: 0 + }; + + + if (data[i].type == "start") { + trace("BUILD MARKER HAS START PAGE"); + config.start_page = true; + _marker_obj.type = "start"; + } + + if (data[i].type == "storify") { + _marker_obj.type = "storify"; + } + + + if (data[i].tag) { + tags.push(data[i].tag); + } + + markers.push(_marker_obj); + + + + } + + // CREATE TAGS + tags = VMM.Util.deDupeArray(tags); + if (tags.length > 3) { + config.nav.rows.current = config.nav.rows.half; + } else { + config.nav.rows.current = config.nav.rows.full; + } + for(k = 0; k < tags.length; k++) { + if (k < config.nav.rows.current.length) { + var tag_element = VMM.appendAndGetElement($timebackground, "<div>", "timenav-tag"); + VMM.Lib.addClass(tag_element, "timenav-tag-row-" + (k+1)); + if (tags.length > 3) { + VMM.Lib.addClass(tag_element, "timenav-tag-size-half"); + } else { + VMM.Lib.addClass(tag_element, "timenav-tag-size-full"); + } + VMM.appendElement(tag_element, "<div><h3>" + tags[k] + "</h3></div>"); + } + + } + + // RESIZE FLAGS IF NEEDED + if (tags.length > 3) { + for(l = 0; l < markers.length; l++) { + VMM.Lib.addClass(markers[l].flag, "flag-small"); + markers[l].full = false; + } + } + + + } + + function buildEras() { + var number_of_colors = 6, + current_color = 0, + j = 0; + // CREATE ERAS + for(j = 0; j < eras.length; j++) { + var era = { + content: VMM.appendAndGetElement($content, "<div>", "era"), + text_content: VMM.appendAndGetElement($timeinterval, "<div>", "era"), + startdate: VMM.Date.parse(eras[j].startDate), + enddate: VMM.Date.parse(eras[j].endDate), + title: eras[j].headline, + uniqueid: VMM.Util.unique_ID(6), + tag: "", + relative_pos: "" + }, + st = VMM.Date.prettyDate(era.startdate), + en = VMM.Date.prettyDate(era.enddate), + era_text = "<div>&nbsp;</div>"; + + if (typeof eras[j].tag != "undefined") { + era.tag = eras[j].tag; + } + + era.relative_pos = positionRelative(interval, era.startdate, era.enddate); + + VMM.Lib.attr(era.content, "id", era.uniqueid); + VMM.Lib.attr(era.text_content, "id", era.uniqueid + "_text"); + + // Background Color + VMM.Lib.addClass(era.content, "era"+(current_color+1)); + VMM.Lib.addClass(era.text_content, "era"+(current_color+1)); + + if (current_color < number_of_colors) { + current_color++; + } else { + current_color = 0; + } + + VMM.appendElement(era.content, era_text); + VMM.appendElement(era.text_content, VMM.Util.unlinkify(era.title)); + + era_markers.push(era); + + } + + } + + }; + +} + +/* ********************************************** + Begin VMM.Timeline.DataObj.js +********************************************** */ + +/* TIMELINE SOURCE DATA PROCESSOR +================================================== */ + +if (typeof VMM.Timeline !== 'undefined' && typeof VMM.Timeline.DataObj == 'undefined') { + VMM.Timeline.DataObj = { + data_obj: {}, + model_array: [], + getData: function (raw_data) { + VMM.Timeline.DataObj.data_obj = {}; + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, VMM.Timeline.Config.language.messages.loading_timeline); + if (type.of(raw_data) == "object") { + trace("DATA SOURCE: JSON OBJECT"); + VMM.Timeline.DataObj.parseJSON(raw_data); + } else if (type.of(raw_data) == "string") { + if (raw_data.match("%23")) { + trace("DATA SOURCE: TWITTER SEARCH"); + VMM.Timeline.DataObj.model.tweets.getData("%23medill"); + } else if ( raw_data.match("spreadsheet") ) { + trace("DATA SOURCE: GOOGLE SPREADSHEET"); + VMM.Timeline.DataObj.model.googlespreadsheet.getData(raw_data); + } else if (raw_data.match("storify.com")) { + trace("DATA SOURCE: STORIFY"); + VMM.Timeline.DataObj.model.storify.getData(raw_data); + //http://api.storify.com/v1/stories/number10gov/g8-and-nato-chicago-summit + } else if (raw_data.match("\.jsonp")) { + trace("DATA SOURCE: JSONP"); + LoadLib.js(raw_data, VMM.Timeline.DataObj.onJSONPLoaded); + } else { + trace("DATA SOURCE: JSON"); + var req = ""; + if (raw_data.indexOf("?") > -1) { + req = raw_data + "&callback=onJSONP_Data"; + } else { + req = raw_data + "?callback=onJSONP_Data"; + } + VMM.getJSON(req, VMM.Timeline.DataObj.parseJSON); + } + } else if (type.of(raw_data) == "html") { + trace("DATA SOURCE: HTML"); + VMM.Timeline.DataObj.parseHTML(raw_data); + } else { + trace("DATA SOURCE: UNKNOWN"); + } + + }, + + onJSONPLoaded: function() { + trace("JSONP IS LOADED"); + VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, storyjs_jsonp_data); + }, + + parseHTML: function (d) { + trace("parseHTML"); + trace("WARNING: THIS IS STILL ALPHA AND WILL NOT WORK WITH ID's other than #timeline"); + var _data_obj = VMM.Timeline.DataObj.data_template_obj; + + /* Timeline start slide + ================================================== */ + if (VMM.Lib.find("#timeline section", "time")[0]) { + _data_obj.timeline.startDate = VMM.Lib.html(VMM.Lib.find("#timeline section", "time")[0]); + _data_obj.timeline.headline = VMM.Lib.html(VMM.Lib.find("#timeline section", "h2")); + _data_obj.timeline.text = VMM.Lib.html(VMM.Lib.find("#timeline section", "article")); + + var found_main_media = false; + + if (VMM.Lib.find("#timeline section", "figure img").length != 0) { + found_main_media = true; + _data_obj.timeline.asset.media = VMM.Lib.attr(VMM.Lib.find("#timeline section", "figure img"), "src"); + } else if (VMM.Lib.find("#timeline section", "figure a").length != 0) { + found_main_media = true; + _data_obj.timeline.asset.media = VMM.Lib.attr(VMM.Lib.find("#timeline section", "figure a"), "href"); + } else { + //trace("NOT FOUND"); + } + + if (found_main_media) { + if (VMM.Lib.find("#timeline section", "cite").length != 0) { + _data_obj.timeline.asset.credit = VMM.Lib.html(VMM.Lib.find("#timeline section", "cite")); + } + if (VMM.Lib.find(this, "figcaption").length != 0) { + _data_obj.timeline.asset.caption = VMM.Lib.html(VMM.Lib.find("#timeline section", "figcaption")); + } + } + } + + /* Timeline Date Slides + ================================================== */ + VMM.Lib.each("#timeline li", function(i, elem){ + + var valid_date = false; + + var _date = { + "type":"default", + "startDate":"", + "headline":"", + "text":"", + "asset": + { + "media":"", + "credit":"", + "caption":"" + }, + "tags":"Optional" + }; + + if (VMM.Lib.find(this, "time") != 0) { + + valid_date = true; + + _date.startDate = VMM.Lib.html(VMM.Lib.find(this, "time")[0]); + + if (VMM.Lib.find(this, "time")[1]) { + _date.endDate = VMM.Lib.html(VMM.Lib.find(this, "time")[1]); + } + + _date.headline = VMM.Lib.html(VMM.Lib.find(this, "h3")); + + _date.text = VMM.Lib.html(VMM.Lib.find(this, "article")); + + var found_media = false; + if (VMM.Lib.find(this, "figure img").length != 0) { + found_media = true; + _date.asset.media = VMM.Lib.attr(VMM.Lib.find(this, "figure img"), "src"); + } else if (VMM.Lib.find(this, "figure a").length != 0) { + found_media = true; + _date.asset.media = VMM.Lib.attr(VMM.Lib.find(this, "figure a"), "href"); + } else { + //trace("NOT FOUND"); + } + + if (found_media) { + if (VMM.Lib.find(this, "cite").length != 0) { + _date.asset.credit = VMM.Lib.html(VMM.Lib.find(this, "cite")); + } + if (VMM.Lib.find(this, "figcaption").length != 0) { + _date.asset.caption = VMM.Lib.html(VMM.Lib.find(this, "figcaption")); + } + } + + trace(_date); + _data_obj.timeline.date.push(_date); + + } + + }); + + VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, _data_obj); + + }, + + parseJSON: function(d) { + trace("parseJSON"); + if (d.timeline.type == "default") { + trace("DATA SOURCE: JSON STANDARD TIMELINE"); + VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, d); + } else if (d.timeline.type == "twitter") { + trace("DATA SOURCE: JSON TWEETS"); + VMM.Timeline.DataObj.model_Tweets.buildData(d); + + } else { + trace("DATA SOURCE: UNKNOWN JSON"); + trace(type.of(d.timeline)); + }; + }, + + /* MODEL OBJECTS + New Types of Data can be formatted for the timeline here + ================================================== */ + + model: { + + googlespreadsheet: { + + getData: function(raw) { + var getjsondata, key, worksheet, url, timeout, tries = 0; + + key = VMM.Util.getUrlVars(raw)["key"]; + worksheet = VMM.Util.getUrlVars(raw)["worksheet"]; + if (typeof worksheet == "undefined") worksheet = "od6"; + + url = "https://spreadsheets.google.com/feeds/list/" + key + "/" + worksheet + "/public/values?alt=json"; + + timeout = setTimeout(function() { + trace("Google Docs timeout " + url); + trace(url); + if (tries < 3) { + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Still waiting on Google Docs, trying again " + tries); + tries ++; + getjsondata.abort() + requestJsonData(); + } else { + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Google Docs is not responding"); + } + }, 16000); + + function requestJsonData() { + getjsondata = VMM.getJSON(url, function(d) { + clearTimeout(timeout); + VMM.Timeline.DataObj.model.googlespreadsheet.buildData(d); + }) + .error(function(jqXHR, textStatus, errorThrown) { + trace("Google Docs ERROR"); + trace("Google Docs ERROR: " + textStatus + " " + jqXHR.responseText); + }) + .success(function(d) { + clearTimeout(timeout); + }); + } + + requestJsonData(); + }, + + buildData: function(d) { + var data_obj = VMM.Timeline.DataObj.data_template_obj, + is_valid = false; + + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Parsing Google Doc Data"); + + function getGVar(v) { + if (typeof v != 'undefined') { + return v.$t; + } else { + return ""; + } + } + if (typeof d.feed.entry != 'undefined') { + is_valid = true; + + for(var i = 0; i < d.feed.entry.length; i++) { + var dd = d.feed.entry[i], + dd_type = ""; + + if (typeof dd.gsx$type != 'undefined') { + dd_type = dd.gsx$type.$t; + } else if (typeof dd.gsx$titleslide != 'undefined') { + dd_type = dd.gsx$titleslide.$t; + } + + if (dd_type.match("start") || dd_type.match("title") ) { + data_obj.timeline.startDate = getGVar(dd.gsx$startdate); + data_obj.timeline.headline = getGVar(dd.gsx$headline); + data_obj.timeline.asset.media = getGVar(dd.gsx$media); + data_obj.timeline.asset.caption = getGVar(dd.gsx$mediacaption); + data_obj.timeline.asset.credit = getGVar(dd.gsx$mediacredit); + data_obj.timeline.text = getGVar(dd.gsx$text); + data_obj.timeline.type = "google spreadsheet"; + } else if (dd_type.match("era")) { + var era = { + startDate: getGVar(dd.gsx$startdate), + endDate: getGVar(dd.gsx$enddate), + headline: getGVar(dd.gsx$headline), + text: getGVar(dd.gsx$text), + tag: getGVar(dd.gsx$tag) + } + data_obj.timeline.era.push(era); + } else { + var date = { + type: "google spreadsheet", + startDate: getGVar(dd.gsx$startdate), + endDate: getGVar(dd.gsx$enddate), + headline: getGVar(dd.gsx$headline), + text: getGVar(dd.gsx$text), + tag: getGVar(dd.gsx$tag), + asset: { + media: getGVar(dd.gsx$media), + credit: getGVar(dd.gsx$mediacredit), + caption: getGVar(dd.gsx$mediacaption), + thumbnail: getGVar(dd.gsx$mediathumbnail) + } + }; + + data_obj.timeline.date.push(date); + } + }; + + } else { + + } + + + if (is_valid) { + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Finished Parsing Data"); + VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, data_obj); + } else { + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, VMM.Language.messages.loading + " Google Doc Data (cells)"); + trace("There may be too many entries. Still trying to load data. Now trying to load cells to avoid Googles limitation on cells"); + VMM.Timeline.DataObj.model.googlespreadsheet.getDataCells(d.feed.link[0].href); + } + }, + + getDataCells: function(raw) { + var getjsondata, key, url, timeout, tries = 0; + + key = VMM.Util.getUrlVars(raw)["key"]; + url = "https://spreadsheets.google.com/feeds/cells/" + key + "/od6/public/values?alt=json"; + + timeout = setTimeout(function() { + trace("Google Docs timeout " + url); + trace(url); + if (tries < 3) { + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Still waiting on Google Docs, trying again " + tries); + tries ++; + getjsondata.abort() + requestJsonData(); + } else { + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Google Docs is not responding"); + } + }, 16000); + + function requestJsonData() { + getjsondata = VMM.getJSON(url, function(d) { + clearTimeout(timeout); + VMM.Timeline.DataObj.model.googlespreadsheet.buildDataCells(d); + }) + .error(function(jqXHR, textStatus, errorThrown) { + trace("Google Docs ERROR"); + trace("Google Docs ERROR: " + textStatus + " " + jqXHR.responseText); + }) + .success(function(d) { + clearTimeout(timeout); + }); + } + + requestJsonData(); + }, + + buildDataCells: function(d) { + var data_obj = VMM.Timeline.DataObj.data_template_obj, + is_valid = false, + cellnames = ["timeline"], + list = [], + max_row = 0, + i = 0, + k = 0; + + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, VMM.Language.messages.loading_timeline + " Parsing Google Doc Data (cells)"); + + function getGVar(v) { + if (typeof v != 'undefined') { + return v.$t; + } else { + return ""; + } + } + + if (typeof d.feed.entry != 'undefined') { + is_valid = true; + + // DETERMINE NUMBER OF ROWS + for(i = 0; i < d.feed.entry.length; i++) { + var dd = d.feed.entry[i]; + + if (parseInt(dd.gs$cell.row) > max_row) { + max_row = parseInt(dd.gs$cell.row); + } + } + + // CREATE OBJECT FOR EACH ROW + for(var i = 0; i < max_row + 1; i++) { + var date = { + type: "", + startDate: "", + endDate: "", + headline: "", + text: "", + tag: "", + asset: { + media: "", + credit: "", + caption: "", + thumbnail: "" + } + }; + list.push(date); + } + + // PREP GOOGLE DOC CELL DATA TO EVALUATE + for(i = 0; i < d.feed.entry.length; i++) { + var dd = d.feed.entry[i], + dd_type = "", + column_name = "", + cell = { + content: getGVar(dd.gs$cell), + col: dd.gs$cell.col, + row: dd.gs$cell.row, + name: "" + }; + + //trace(cell); + + if (cell.row == 1) { + if (cell.content == "Start Date") { + column_name = "startDate"; + } else if (cell.content == "End Date") { + column_name = "endDate"; + } else if (cell.content == "Headline") { + column_name = "headline"; + } else if (cell.content == "Text") { + column_name = "text"; + } else if (cell.content == "Media") { + column_name = "media"; + } else if (cell.content == "Media Credit") { + column_name = "credit"; + } else if (cell.content == "Media Caption") { + column_name = "caption"; + } else if (cell.content == "Media Thumbnail") { + column_name = "thumbnail"; + } else if (cell.content == "Type") { + column_name = "type"; + } else if (cell.content == "Tag") { + column_name = "tag"; + } + + cellnames.push(column_name); + + } else { + cell.name = cellnames[cell.col]; + list[cell.row][cell.name] = cell.content; + } + + }; + + + for(i = 0; i < list.length; i++) { + var date = list[i]; + + if (date.type.match("start") || date.type.match("title") ) { + data_obj.timeline.startDate = date.startDate; + data_obj.timeline.headline = date.headline; + data_obj.timeline.asset.media = date.media; + data_obj.timeline.asset.caption = date.caption; + data_obj.timeline.asset.credit = date.credit; + data_obj.timeline.text = date.text; + data_obj.timeline.type = "google spreadsheet"; + } else if (date.type.match("era")) { + var era = { + startDate: date.startDate, + endDate: date.endDate, + headline: date.headline, + text: date.text, + tag: date.tag + } + data_obj.timeline.era.push(era); + } else { + var date = { + type: "google spreadsheet", + startDate: date.startDate, + endDate: date.endDate, + headline: date.headline, + text: date.text, + tag: date.tag, + asset: { + media: date.media, + credit: date.credit, + caption: date.caption, + thumbnail: date.thumbnail + } + }; + + data_obj.timeline.date.push(date); + } + + } + + //trace(cellnames); + //trace(max_row); + //trace(list); + + } + + if (is_valid) { + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Finished Parsing Data"); + VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, data_obj); + } else { + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Unable to load Google Doc data source"); + } + } + + }, + + storify: { + + getData: function(raw) { + var key, url, storify_timeout; + //http://storify.com/number10gov/g8-and-nato-chicago-summit + //http://api.storify.com/v1/stories/number10gov/g8-and-nato-chicago-summit + + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Loading Storify..."); + + key = raw.split("storify.com\/")[1]; + url = "http://api.storify.com/v1/stories/" + key + "?per_page=300&callback=?"; + + storify_timeout = setTimeout(function() { + trace("STORIFY timeout"); + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Storify is not responding"); + }, 6000); + + VMM.getJSON(url, VMM.Timeline.DataObj.model.storify.buildData) + .error(function(jqXHR, textStatus, errorThrown) { + trace("STORIFY error"); + trace("STORIFY ERROR: " + textStatus + " " + jqXHR.responseText); + }) + .success(function(d) { + clearTimeout(storify_timeout); + }); + + }, + + buildData: function(d) { + VMM.fireEvent(global, VMM.Timeline.Config.events.messege, "Parsing Data"); + var _data_obj = VMM.Timeline.DataObj.data_template_obj; + + _data_obj.timeline.startDate = new Date(d.content.date.created);; + _data_obj.timeline.headline = d.content.title; + + trace(d); + //d.permalink + var tt = ""; + var t_name = d.content.author.username; + var t_nickname = ""; + if (typeof d.content.author.name != 'undefined') { + t_name = d.content.author.name; + t_nickname = d.content.author.username + "&nbsp;"; + } + if (typeof d.content.description != 'undefined' && d.content.description != null) { + tt += d.content.description; + } + + tt += "<div class='storify'>" + //tt += " <a href='" + d.content.permalink + "' target='_blank' alt='link to original story' title='link to original story'>" + "<span class='created-at'></span>" + " </a>"; + + tt += "<div class='vcard author'><a class='screen-name url' href='" + d.content.author.permalink + "' target='_blank'>"; + + tt += "<span class='avatar'><img src='" + d.content.author.avatar + "' style='max-width: 32px; max-height: 32px;'></span>" + tt += "<span class='fn'>" + t_name + "</span>"; + tt += "<span class='nickname'>" + t_nickname + "<span class='thumbnail-inline'></span></span>"; + tt += "</a>"; + //tt += "<span class='nickname'>" + d.content.author.stats.stories + " Stories</span>"; + //tt += "<span class='nickname'>" + d.content.author.stats.subscribers + " Subscribers</span>"; + tt += "</div>" + tt += "</div>"; + + _data_obj.timeline.text = tt; + _data_obj.timeline.asset.media = d.content.thumbnail; + + //_data_obj.timeline.asset.media = dd.gsx$media.$t; + //_data_obj.timeline.asset.caption = dd.gsx$mediacaption.$t; + //_data_obj.timeline.asset.credit = dd.gsx$mediacredit.$t; + _data_obj.timeline.type = "storify"; + + for(var i = 0; i < d.content.elements.length; i++) { + var dd = d.content.elements[i]; + var is_text = false; + var d_date = new Date(dd.posted_at); + //trace(tempdat); + trace(dd.type); + //trace(dd); + var _date = { + "type": "storify", + "startDate": dd.posted_at, + "endDate": dd.posted_at, + "headline": " ", + "slug": "", + "text": "", + "asset": { + "media": "", + "credit": "", + "caption": "" + } + }; + + /* MEDIA + ================================================== */ + if (dd.type == "image") { + + if (typeof dd.source.name != 'undefined') { + if (dd.source.name == "flickr") { + _date.asset.media = "http://flickr.com/photos/" + dd.meta.pathalias + "/" + dd.meta.id + "/"; + _date.asset.credit = "<a href='" + _date.asset.media + "'>" + dd.attribution.name + "</a>"; + _date.asset.credit += " on <a href='" + dd.source.href + "'>" + dd.source.name + "</a>"; + } else if (dd.source.name == "instagram") { + _date.asset.media = dd.permalink; + _date.asset.credit = "<a href='" + dd.permalink + "'>" + dd.attribution.name + "</a>"; + _date.asset.credit += " on <a href='" + dd.source.href + "'>" + dd.source.name + "</a>"; + } else { + _date.asset.credit = "<a href='" + dd.permalink + "'>" + dd.attribution.name + "</a>"; + + if (typeof dd.source.href != 'undefined') { + _date.asset.credit += " on <a href='" + dd.source.href + "'>" + dd.source.name + "</a>"; + } + + _date.asset.media = dd.data.image.src; + } + } else { + _date.asset.credit = "<a href='" + dd.permalink + "'>" + dd.attribution.name + "</a>"; + _date.asset.media = dd.data.image.src; + } + + _date.slug = dd.attribution.name; + if (typeof dd.data.image.caption != 'undefined') { + if (dd.data.image.caption != 'undefined') { + _date.asset.caption = dd.data.image.caption; + _date.slug = dd.data.image.caption; + } + } + + } else if (dd.type == "quote") { + if (dd.permalink.match("twitter")) { + _date.asset.media = dd.permalink; + _date.slug = VMM.Util.untagify(dd.data.quote.text); + } else if (dd.permalink.match("storify")) { + is_text = true; + _date.asset.media = "<blockquote>" + dd.data.quote.text.replace(/<\s*\/?\s*b\s*.*?>/g,"") + "</blockquote>"; + } + } else if (dd.type == "link") { + _date.headline = dd.data.link.title; + _date.text = dd.data.link.description; + if (dd.data.link.thumbnail != 'undefined' && dd.data.link.thumbnail != '') { + _date.asset.media = dd.data.link.thumbnail; + } else { + _date.asset.media = dd.permalink; + } + //_date.asset.media = dd.permalink; + _date.asset.caption = "<a href='" + dd.permalink + "' target='_blank'>" + dd.data.link.title + "</a>" + _date.slug = dd.data.link.title; + + } else if (dd.type == "text") { + if (dd.permalink.match("storify")) { + is_text = true; + var d_name = d.content.author.username; + var d_nickname = ""; + if (typeof dd.attribution.name != 'undefined') { + t_name = dd.attribution.name; + t_nickname = dd.attribution.username + "&nbsp;"; + } + + var asset_text = "<div class='storify'>" + asset_text += "<blockquote><p>" + dd.data.text.replace(/<\s*\/?\s*b\s*.*?>/g,"") + "</p></blockquote>"; + //asset_text += " <a href='" + dd.attribution.href + "' target='_blank' alt='link to author' title='link to author'>" + "<span class='created-at'></span>" + " </a>"; + + asset_text += "<div class='vcard author'><a class='screen-name url' href='" + dd.attribution.href + "' target='_blank'>"; + asset_text += "<span class='avatar'><img src='" + dd.attribution.thumbnail + "' style='max-width: 32px; max-height: 32px;'></span>" + asset_text += "<span class='fn'>" + t_name + "</span>"; + asset_text += "<span class='nickname'>" + t_nickname + "<span class='thumbnail-inline'></span></span>"; + asset_text += "</a></div></div>"; + _date.text = asset_text; + + // Try and put it before the element where it is expected on storify + if ( (i+1) >= d.content.elements.length ) { + _date.startDate = d.content.elements[i-1].posted_at; + + } else { + if (d.content.elements[i+1].type == "text" && d.content.elements[i+1].permalink.match("storify")) { + if ( (i+2) >= d.content.elements.length ) { + _date.startDate = d.content.elements[i-1].posted_at; + } else { + if (d.content.elements[i+2].type == "text" && d.content.elements[i+2].permalink.match("storify")) { + if ( (i+3) >= d.content.elements.length ) { + _date.startDate = d.content.elements[i-1].posted_at; + } else { + if (d.content.elements[i+3].type == "text" && d.content.elements[i+3].permalink.match("storify")) { + _date.startDate = d.content.elements[i-1].posted_at; + } else { + trace("LEVEL 3"); + _date.startDate = d.content.elements[i+3].posted_at; + } + } + } else { + trace("LEVEL 2"); + _date.startDate = d.content.elements[i+2].posted_at; + } + } + } else { + trace("LEVEL 1"); + _date.startDate = d.content.elements[i+1].posted_at; + } + + } + _date.endDate = _date.startDate + } + + + } else if (dd.type == "video") { + _date.headline = dd.data.video.title; + _date.asset.caption = dd.data.video.description; + _date.asset.caption = dd.source.username; + _date.asset.media = dd.data.video.src; + } else { + trace("NO MATCH "); + trace(dd); + } + + if (is_text) { + _date.slug = VMM.Util.untagify(dd.data.text); + } + + _data_obj.timeline.date.push(_date); + + + }; + + VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, _data_obj); + } + + }, + + tweets: { + + type: "twitter", + + buildData: function(raw_data) { + VMM.bindEvent(global, VMM.Timeline.DataObj.model.tweets.onTwitterDataReady, "TWEETSLOADED"); + VMM.ExternalAPI.twitter.getTweets(raw_data.timeline.tweets); + }, + + getData: function(raw_data) { + VMM.bindEvent(global, VMM.Timeline.DataObj.model.tweets.onTwitterDataReady, "TWEETSLOADED"); + VMM.ExternalAPI.twitter.getTweetSearch(raw_data); + }, + + onTwitterDataReady: function(e, d) { + var _data_obj = VMM.Timeline.DataObj.data_template_obj; + + for(var i = 0; i < d.tweetdata.length; i++) { + + var _date = { + "type":"tweets", + "startDate":"", + "headline":"", + "text":"", + "asset": + { + "media":"", + "credit":"", + "caption":"" + }, + "tags":"Optional" + }; + // pass in the 'created_at' string returned from twitter // + // stamp arrives formatted as Tue Apr 07 22:52:51 +0000 2009 // + + //var twit_date = VMM.ExternalAPI.twitter.parseTwitterDate(d.tweetdata[i].raw.created_at); + //trace(twit_date); + + _date.startDate = d.tweetdata[i].raw.created_at; + + if (type.of(d.tweetdata[i].raw.from_user_name)) { + _date.headline = d.tweetdata[i].raw.from_user_name + " (<a href='https://twitter.com/" + d.tweetdata[i].raw.from_user + "'>" + "@" + d.tweetdata[i].raw.from_user + "</a>)" ; + } else { + _date.headline = d.tweetdata[i].raw.user.name + " (<a href='https://twitter.com/" + d.tweetdata[i].raw.user.screen_name + "'>" + "@" + d.tweetdata[i].raw.user.screen_name + "</a>)" ; + } + + _date.asset.media = d.tweetdata[i].content; + _data_obj.timeline.date.push(_date); + + }; + + VMM.fireEvent(global, VMM.Timeline.Config.events.data_ready, _data_obj); + } + + } + }, + + + /* TEMPLATE OBJECTS + ================================================== */ + data_template_obj: { "timeline": { "headline":"", "description":"", "asset": { "media":"", "credit":"", "caption":"" }, "date": [], "era":[] } }, + date_obj: {"startDate":"2012,2,2,11,30", "headline":"", "text":"", "asset": {"media":"http://youtu.be/vjVfu8-Wp6s", "credit":"", "caption":"" }, "tags":"Optional"} + + }; + +} \ No newline at end of file diff --git a/src/static/viz.js-master/.gitattributes b/src/static/viz.js-master/.gitattributes new file mode 100755 index 0000000..291556a --- /dev/null +++ b/src/static/viz.js-master/.gitattributes @@ -0,0 +1 @@ +viz.js -diff \ No newline at end of file diff --git a/src/static/viz.js-master/COPYING b/src/static/viz.js-master/COPYING new file mode 100755 index 0000000..a681d9f --- /dev/null +++ b/src/static/viz.js-master/COPYING @@ -0,0 +1,129 @@ +* The original parts of this project (including files used in compiling the viz.js file) are made available under the following terms: + +Copyright (c) 2012 Michael Daines + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +* Graphviz is distributed under the Eclipse Public License: + +AT&T has previously made versions of this software available under the AT&T Source Code Agreement, version 1.2D and earlier. If you received a copy of the software under that license agreement, you may continue to use and distribute the same version of the software subject to the terms and conditions of the license agreement under which the software was received. However, current versions of the software are now licensed on an open source basis only under The Eclipse Public License (EPL). + +For more information on the Eclipse Public License, see the FAQ. If you have any concerns about the what the license means, especially if money is involved, you should contact an intellectual property lawyer. + +Eclipse Public License - v 1.0 +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + +a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and + +b) in the case of each subsequent Contributor: + +i) changes to the Program, and + +ii) additions to the Program; + +where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. + +"Program" means the Contributions distributed in accordance with this Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. + +b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. + +c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. + +d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: + +a) it complies with the terms and conditions of this Agreement; and + +b) its license agreement: + +i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; + +ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; + +iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and + +iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. + +When the Program is made available in source code form: + +a) it must be made available under this Agreement; and + +b) a copy of this Agreement must be included with each copy of the Program. + +Contributors may not remove or alter any copyright notices contained within the Program. + +Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. + + +* This project, including the Makefile, uses work by Satoshi Ueyama, made available under the following terms: + + -> Liviz.js (JSViz) <- + Interactive GraphViz on DHTML + +-- MIT License + +Copyright (c) 2011-2012 Satoshi Ueyama + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/src/static/viz.js-master/Makefile b/src/static/viz.js-master/Makefile new file mode 100755 index 0000000..0d5db5f --- /dev/null +++ b/src/static/viz.js-master/Makefile @@ -0,0 +1,46 @@ +# To compile, emcc must be in your path or EMSCRIPTEN_ROOT must be set. +EMCC:=$(shell if command -v emcc > /dev/null; then echo "emcc"; else echo "$(EMSCRIPTEN_ROOT)/emcc"; fi) +SRCDIR=graphviz-src + +viz.js: $(SRCDIR) viz.c $(SRCDIR)/lib/cdt/libcdt-em.bc $(SRCDIR)/lib/common/libcommon-em.bc $(SRCDIR)/lib/gvc/libgvc-em.bc $(SRCDIR)/lib/pathplan/libpathplan-em.bc $(SRCDIR)/lib/graph/libgraph-em.bc $(SRCDIR)/lib/dotgen/libdotgen-em.bc $(SRCDIR)/plugin/core/libgvplugin_core-em.bc $(SRCDIR)/plugin/dot_layout/libgvplugin_dot_layout-em.bc post.js pre.js + $(EMCC) -v -O2 -s EXPORTED_FUNCTIONS='["_vizRenderFromString"]' -o viz.js -I$(SRCDIR)/lib/gvc -I$(SRCDIR)/lib/common -I$(SRCDIR)/lib/pathplan -I$(SRCDIR)/lib/cdt -I$(SRCDIR)/lib/graph viz.c $(SRCDIR)/lib/cdt/libcdt-em.bc $(SRCDIR)/lib/common/libcommon-em.bc $(SRCDIR)/lib/gvc/libgvc-em.bc $(SRCDIR)/lib/pathplan/libpathplan-em.bc $(SRCDIR)/lib/graph/libgraph-em.bc $(SRCDIR)/lib/dotgen/libdotgen-em.bc $(SRCDIR)/plugin/dot_layout/libgvplugin_dot_layout-em.bc $(SRCDIR)/plugin/core/libgvplugin_core-em.bc --pre-js pre.js --post-js post.js --closure 1 + +$(SRCDIR)/lib/cdt/libcdt-em.bc: + cd $(SRCDIR)/lib/cdt; $(EMCC) -o libcdt-em.bc -I. dtclose.c dtdisc.c dtextract.c dtflatten.c dthash.c dtlist.c dtmethod.c dtopen.c dtsize.c dtstrhash.c dttree.c dttreeset.c dtrestore.c dtview.c dtwalk.c + +$(SRCDIR)/lib/common/libcommon-em.bc: + cd $(SRCDIR)/lib/common; $(EMCC) -o libcommon-em.bc -I. -I.. -I../.. -I../../.. -I../gvc -I../pathplan -I../cdt -I../graph -I../xdot -DHAVE_CONFIG_H arrows.c emit.c utils.c labels.c memory.c fontmetrics.c geom.c globals.c htmllex.c htmlparse.c htmltable.c ns.c postproc.c routespl.c shapes.c splines.c colxlate.c psusershape.c input.c timing.c output.c + +$(SRCDIR)/lib/gvc/libgvc-em.bc: + cd $(SRCDIR)/lib/gvc; $(EMCC) -o libgvc-em.bc -I. -I.. -I../.. -I../../.. -I../common -I../pathplan -I../cdt -I../graph -DHAVE_CONFIG_H gvc.c gvconfig.c gvcontext.c gvdevice.c gvlayout.c gvevent.c gvjobs.c gvplugin.c gvrender.c gvusershape.c gvloadimage.c gvtextlayout.c + +$(SRCDIR)/lib/pathplan/libpathplan-em.bc: + cd $(SRCDIR)/lib/pathplan; $(EMCC) -o libpathplan-em.bc -I. cvt.c inpoly.c route.c shortest.c solvers.c triang.c util.c visibility.c + +$(SRCDIR)/lib/graph/libgraph-em.bc: + cd $(SRCDIR)/lib/graph; $(EMCC) -o libgraph-em.bc -I. -I../cdt -I../gvc -I../common -I../pathplan agxbuf.c attribs.c edge.c graph.c graphio.c lexer.c node.c parser.c refstr.c trie.c + +$(SRCDIR)/lib/dotgen/libdotgen-em.bc: + cd $(SRCDIR)/lib/dotgen; $(EMCC) -o libdotgen-em.bc -I. -I.. -I../.. -I../../.. -I../common -I../gvc -I../pathplan -I../cdt -I../graph -DHAVE_CONFIG_H acyclic.c aspect.c class1.c class2.c cluster.c compound.c conc.c decomp.c dotinit.c dotsplines.c fastgr.c flat.c mincross.c position.c rank.c sameport.c + +$(SRCDIR)/plugin/core/libgvplugin_core-em.bc: + cd $(SRCDIR)/plugin/core; $(EMCC) -o libgvplugin_core-em.bc -I. -I.. -I../.. -I../../.. -I../../lib -I../../lib/common -I../../lib/gvc -I../../lib/pathplan -I../../lib/cdt -I../../lib/graph -DHAVE_CONFIG_H gvplugin_core.c gvrender_core_dot.c gvrender_core_fig.c gvrender_core_map.c gvrender_core_ps.c gvrender_core_svg.c gvrender_core_tk.c gvrender_core_vml.c gvloadimage_core.c + +$(SRCDIR)/plugin/dot_layout/libgvplugin_dot_layout-em.bc: + cd $(SRCDIR)/plugin/dot_layout; $(EMCC) -o libgvplugin_dot_layout-em.bc -I. -I.. -I../.. -I../../.. -I../../lib -I../../lib/common -I../../lib/gvc -I../../lib/pathplan -I../../lib/cdt -I../../lib/graph -DHAVE_CONFIG_H gvplugin_dot_layout.c gvlayout_dot_layout.c + +$(SRCDIR): | graphviz-src.tar.gz + mkdir -p $(SRCDIR) + tar xf graphviz-src.tar.gz -C $(SRCDIR) --strip=1 + +graphviz-src.tar.gz: + curl "http://www.graphviz.org/pub/graphviz/stable/SOURCES/graphviz-2.28.0.tar.gz" -o graphviz-src.tar.gz + +clean: + rm -f $(SRCDIR)/lib/*/*.bc + rm -f $(SRCDIR)/plugin/*/*.bc + rm -f viz.js + +clobber: clean + rm -rf $(SRCDIR) + rm -f graphviz-src.tar.gz diff --git a/src/static/viz.js-master/README.txt b/src/static/viz.js-master/README.txt new file mode 100755 index 0000000..ec8a040 --- /dev/null +++ b/src/static/viz.js-master/README.txt @@ -0,0 +1,13 @@ +Viz.js +====== + +Simple Graphviz for the web, compiled with Emscripten. + +To render as SVG (produces an XML string): + + svg = Viz("digraph { a -> b; }", "svg"); + +This project is based on work by Satoshi Ueyama and Brenton Partridge: + + https://github.com/gyuque/livizjs + https://github.com/bpartridge/graphviz.js diff --git a/src/static/viz.js-master/config.h b/src/static/viz.js-master/config.h new file mode 100755 index 0000000..a129842 --- /dev/null +++ b/src/static/viz.js-master/config.h @@ -0,0 +1,22 @@ +#define GVPLUGIN_CONFIG_FILE "config6" +#define GVPLUGIN_VERSION 6 +#define PACKAGE "graphviz" +#define PACKAGE_BUGREPORT "http://www.graphviz.org/" +#define PACKAGE_NAME "graphviz" +#define PACKAGE_STRING "graphviz 2.28.0" +#define PACKAGE_TARNAME "graphviz" +#define PACKAGE_URL "" +#define PACKAGE_VERSION "2.28.0" +#define VERSION "2.28.0" + +#define HAVE_BOOL 1 +#undef ENABLE_LTDL + +#undef HAVE_EXPAT +#undef HAVE_EXPAT_H + +#define HAVE_ERRNO_H 1 + +#define DEFAULT_DPI 96 + +#define HAVE_STRDUP 1 diff --git a/src/static/viz.js-master/example.html b/src/static/viz.js-master/example.html new file mode 100755 index 0000000..e1203a5 --- /dev/null +++ b/src/static/viz.js-master/example.html @@ -0,0 +1,321 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Viz.js</title> + </head> + <body> + + <script type="text/vnd.graphviz" id="cluster"> +digraph G { + + subgraph cluster_0 { + style=filled; + color=lightgrey; + node [style=filled,color=white]; + a0 -> a1 -> a2 -> a3; + label = "process #1"; + } + + subgraph cluster_1 { + node [style=filled]; + b0 -> b1 -> b2 -> b3; + label = "process #2"; + color=blue + } + start -> a0; + start -> b0; + a1 -> b3; + b2 -> a3; + a3 -> a0; + a3 -> end; + b3 -> end; + + start [shape=Mdiamond]; + end [shape=Msquare]; +} +</script> + + <script type="text/vnd.graphviz" id="crazy"> +digraph "unix" { + graph [ fontname = "Helvetica-Oblique", + fontsize = 36, + label = "\n\n\n\nObject Oriented Graphs\nStephen North, 3/19/93", + size = "6,6" ]; + node [ shape = polygon, + sides = 4, + distortion = "0.0", + orientation = "0.0", + skew = "0.0", + color = white, + style = filled, + fontname = "Helvetica-Outline" ]; + "5th Edition" [sides=9, distortion="0.936354", orientation=28, skew="-0.126818", color=salmon2]; + "6th Edition" [sides=5, distortion="0.238792", orientation=11, skew="0.995935", color=deepskyblue]; + "PWB 1.0" [sides=8, distortion="0.019636", orientation=79, skew="-0.440424", color=goldenrod2]; + LSX [sides=9, distortion="-0.698271", orientation=22, skew="-0.195492", color=burlywood2]; + "1 BSD" [sides=7, distortion="0.265084", orientation=26, skew="0.403659", color=gold1]; + "Mini Unix" [distortion="0.039386", orientation=2, skew="-0.461120", color=greenyellow]; + Wollongong [sides=5, distortion="0.228564", orientation=63, skew="-0.062846", color=darkseagreen]; + Interdata [distortion="0.624013", orientation=56, skew="0.101396", color=dodgerblue1]; + "Unix/TS 3.0" [sides=8, distortion="0.731383", orientation=43, skew="-0.824612", color=thistle2]; + "PWB 2.0" [sides=6, distortion="0.592100", orientation=34, skew="-0.719269", color=darkolivegreen3]; + "7th Edition" [sides=10, distortion="0.298417", orientation=65, skew="0.310367", color=chocolate]; + "8th Edition" [distortion="-0.997093", orientation=50, skew="-0.061117", color=turquoise3]; + "32V" [sides=7, distortion="0.878516", orientation=19, skew="0.592905", color=steelblue3]; + V7M [sides=10, distortion="-0.960249", orientation=32, skew="0.460424", color=navy]; + "Ultrix-11" [sides=10, distortion="-0.633186", orientation=10, skew="0.333125", color=darkseagreen4]; + Xenix [sides=8, distortion="-0.337997", orientation=52, skew="-0.760726", color=coral]; + "UniPlus+" [sides=7, distortion="0.788483", orientation=39, skew="-0.526284", color=darkolivegreen3]; + "9th Edition" [sides=7, distortion="0.138690", orientation=55, skew="0.554049", color=coral3]; + "2 BSD" [sides=7, distortion="-0.010661", orientation=84, skew="0.179249", color=blanchedalmond]; + "2.8 BSD" [distortion="-0.239422", orientation=44, skew="0.053841", color=lightskyblue1]; + "2.9 BSD" [distortion="-0.843381", orientation=70, skew="-0.601395", color=aquamarine2]; + "3 BSD" [sides=10, distortion="0.251820", orientation=18, skew="-0.530618", color=lemonchiffon]; + "4 BSD" [sides=5, distortion="-0.772300", orientation=24, skew="-0.028475", color=darkorange1]; + "4.1 BSD" [distortion="-0.226170", orientation=38, skew="0.504053", color=lightyellow1]; + "4.2 BSD" [sides=10, distortion="-0.807349", orientation=50, skew="-0.908842", color=darkorchid4]; + "4.3 BSD" [sides=10, distortion="-0.030619", orientation=76, skew="0.985021", color=lemonchiffon2]; + "Ultrix-32" [distortion="-0.644209", orientation=21, skew="0.307836", color=goldenrod3]; + "PWB 1.2" [sides=7, distortion="0.640971", orientation=84, skew="-0.768455", color=cyan]; + "USG 1.0" [distortion="0.758942", orientation=42, skew="0.039886", color=blue]; + "CB Unix 1" [sides=9, distortion="-0.348692", orientation=42, skew="0.767058", color=firebrick]; + "USG 2.0" [distortion="0.748625", orientation=74, skew="-0.647656", color=chartreuse4]; + "CB Unix 2" [sides=10, distortion="0.851818", orientation=32, skew="-0.020120", color=greenyellow]; + "CB Unix 3" [sides=10, distortion="0.992237", orientation=29, skew="0.256102", color=bisque4]; + "Unix/TS++" [sides=6, distortion="0.545461", orientation=16, skew="0.313589", color=mistyrose2]; + "PDP-11 Sys V" [sides=9, distortion="-0.267769", orientation=40, skew="0.271226", color=cadetblue1]; + "USG 3.0" [distortion="-0.848455", orientation=44, skew="0.267152", color=bisque2]; + "Unix/TS 1.0" [distortion="0.305594", orientation=75, skew="0.070516", color=orangered]; + "TS 4.0" [sides=10, distortion="-0.641701", orientation=50, skew="-0.952502", color=crimson]; + "System V.0" [sides=9, distortion="0.021556", orientation=26, skew="-0.729938", color=darkorange1]; + "System V.2" [sides=6, distortion="0.985153", orientation=33, skew="-0.399752", color=darkolivegreen4]; + "System V.3" [sides=7, distortion="-0.687574", orientation=58, skew="-0.180116", color=lightsteelblue1]; + "5th Edition" -> "6th Edition"; + "5th Edition" -> "PWB 1.0"; + "6th Edition" -> LSX; + "6th Edition" -> "1 BSD"; + "6th Edition" -> "Mini Unix"; + "6th Edition" -> Wollongong; + "6th Edition" -> Interdata; + Interdata -> "Unix/TS 3.0"; + Interdata -> "PWB 2.0"; + Interdata -> "7th Edition"; + "7th Edition" -> "8th Edition"; + "7th Edition" -> "32V"; + "7th Edition" -> V7M; + "7th Edition" -> "Ultrix-11"; + "7th Edition" -> Xenix; + "7th Edition" -> "UniPlus+"; + V7M -> "Ultrix-11"; + "8th Edition" -> "9th Edition"; + "1 BSD" -> "2 BSD"; + "2 BSD" -> "2.8 BSD"; + "2.8 BSD" -> "Ultrix-11"; + "2.8 BSD" -> "2.9 BSD"; + "32V" -> "3 BSD"; + "3 BSD" -> "4 BSD"; + "4 BSD" -> "4.1 BSD"; + "4.1 BSD" -> "4.2 BSD"; + "4.1 BSD" -> "2.8 BSD"; + "4.1 BSD" -> "8th Edition"; + "4.2 BSD" -> "4.3 BSD"; + "4.2 BSD" -> "Ultrix-32"; + "PWB 1.0" -> "PWB 1.2"; + "PWB 1.0" -> "USG 1.0"; + "PWB 1.2" -> "PWB 2.0"; + "USG 1.0" -> "CB Unix 1"; + "USG 1.0" -> "USG 2.0"; + "CB Unix 1" -> "CB Unix 2"; + "CB Unix 2" -> "CB Unix 3"; + "CB Unix 3" -> "Unix/TS++"; + "CB Unix 3" -> "PDP-11 Sys V"; + "USG 2.0" -> "USG 3.0"; + "USG 3.0" -> "Unix/TS 3.0"; + "PWB 2.0" -> "Unix/TS 3.0"; + "Unix/TS 1.0" -> "Unix/TS 3.0"; + "Unix/TS 3.0" -> "TS 4.0"; + "Unix/TS++" -> "TS 4.0"; + "CB Unix 3" -> "TS 4.0"; + "TS 4.0" -> "System V.0"; + "System V.0" -> "System V.2"; + "System V.2" -> "System V.3"; +} +</script> + + <script type="text/vnd.graphviz" id="data"> +digraph g { +graph [ +rankdir = "LR" +]; +node [ +fontsize = "16" +shape = "ellipse" +]; +edge [ +]; +"node0" [ +label = "<f0> 0x10ba8| <f1>" +shape = "record" +]; +"node1" [ +label = "<f0> 0xf7fc4380| <f1> | <f2> |-1" +shape = "record" +]; +"node2" [ +label = "<f0> 0xf7fc44b8| | |2" +shape = "record" +]; +"node3" [ +label = "<f0> 3.43322790286038071e-06|44.79998779296875|0" +shape = "record" +]; +"node4" [ +label = "<f0> 0xf7fc4380| <f1> | <f2> |2" +shape = "record" +]; +"node5" [ +label = "<f0> (nil)| | |-1" +shape = "record" +]; +"node6" [ +label = "<f0> 0xf7fc4380| <f1> | <f2> |1" +shape = "record" +]; +"node7" [ +label = "<f0> 0xf7fc4380| <f1> | <f2> |2" +shape = "record" +]; +"node8" [ +label = "<f0> (nil)| | |-1" +shape = "record" +]; +"node9" [ +label = "<f0> (nil)| | |-1" +shape = "record" +]; +"node10" [ +label = "<f0> (nil)| <f1> | <f2> |-1" +shape = "record" +]; +"node11" [ +label = "<f0> (nil)| <f1> | <f2> |-1" +shape = "record" +]; +"node12" [ +label = "<f0> 0xf7fc43e0| | |1" +shape = "record" +]; +"node0":f0 -> "node1":f0 [ +id = 0 +]; +"node0":f1 -> "node2":f0 [ +id = 1 +]; +"node1":f0 -> "node3":f0 [ +id = 2 +]; +"node1":f1 -> "node4":f0 [ +id = 3 +]; +"node1":f2 -> "node5":f0 [ +id = 4 +]; +"node4":f0 -> "node3":f0 [ +id = 5 +]; +"node4":f1 -> "node6":f0 [ +id = 6 +]; +"node4":f2 -> "node10":f0 [ +id = 7 +]; +"node6":f0 -> "node3":f0 [ +id = 8 +]; +"node6":f1 -> "node7":f0 [ +id = 9 +]; +"node6":f2 -> "node9":f0 [ +id = 10 +]; +"node7":f0 -> "node3":f0 [ +id = 11 +]; +"node7":f1 -> "node1":f0 [ +id = 12 +]; +"node7":f2 -> "node8":f0 [ +id = 13 +]; +"node10":f1 -> "node11":f0 [ +id = 14 +]; +"node10":f2 -> "node12":f0 [ +id = 15 +]; +"node11":f2 -> "node1":f0 [ +id = 16 +]; +} +</script> + + <script type="text/vnd.graphviz" id="gradients"> +digraph G { bgcolor="purple:pink" label="agraph" fontcolor="white" + subgraph cluster1 {fillcolor="blue:cyan" label="acluster" fontcolor="white" style="filled" gradientangle="270" + node [shape=box fillcolor="red:yellow" style="filled" gradientangle=90] + anode; + } + +} + +</script> + + <script src="viz.js"></script> + <script> + + function inspect(s) { + return "<pre>" + s.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\"/g, "&quot;") + "</pre>" + } + + function src(id) { + return document.getElementById(id).innerHTML; + } + + function example(id, format) { + var result; + try { + result = Viz(src(id), format); + if (format === "svg") + return result; + else + return inspect(result); + } catch(e) { + return inspect(e.toString()); + } + } + + document.body.innerHTML += "<p>Examples from the <a href=\"http://graphviz.org/Gallery.php\">Graphviz gallery</a>.</p>" + + document.body.innerHTML += "<h1>Cluster (svg output)</h1>"; + document.body.innerHTML += example("cluster", "svg"); + + document.body.innerHTML += "<h1>Crazy (svg output)</h1>"; + document.body.innerHTML += example("crazy", "svg"); + + document.body.innerHTML += "<h1>Data Structures (svg output)</h1>"; + document.body.innerHTML += example("data", "svg"); + + document.body.innerHTML += "<h1>Gradients (svg output)</h1>"; + document.body.innerHTML += example("gradients", "svg"); + + document.body.innerHTML += "<h1>Cluster (plain output)</h1>"; + document.body.innerHTML += example("cluster", "plain"); + + document.body.innerHTML += "<h1>Cluster (xdot output)</h1>"; + document.body.innerHTML += example("cluster", "xdot"); + + </script> + + </body> +</html> diff --git a/src/static/viz.js-master/post.js b/src/static/viz.js-master/post.js new file mode 100755 index 0000000..fd77583 --- /dev/null +++ b/src/static/viz.js-master/post.js @@ -0,0 +1,3 @@ + Module["ccall"]("vizRenderFromString", "number", ["string", "string"], [src, format]); + return Module["return"]; +} diff --git a/src/static/viz.js-master/pre.js b/src/static/viz.js-master/pre.js new file mode 100755 index 0000000..3534fbf --- /dev/null +++ b/src/static/viz.js-master/pre.js @@ -0,0 +1,6 @@ +((typeof exports !== "undefined" && exports !== null) ? exports : this)["Viz"] = function(src, format) { + var Module = {}; + Module["return"] = ""; + Module["print"] = function(text) { + Module["return"] += text + "\n"; + } diff --git a/src/static/viz.js-master/prova.html b/src/static/viz.js-master/prova.html new file mode 100755 index 0000000..0ec6287 --- /dev/null +++ b/src/static/viz.js-master/prova.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Viz.js</title> + </head> + <body> + + <script type="text/vnd.graphviz" id="cluster"> +digraph graphname { + Artist -> Place [label="places"]; + Character -> Artist [label="was created"]; + Work -> Artist [label="was created"]; + Work -> Episode [label="is composed"]; + Work -> Character [label="is carryed"]; + Work -> Place [label="took place"]; + } + </script> + <script src="viz.js"></script> + <script> + + function inspect(s) { + return "<pre>" + s.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\"/g, "&quot;") + "</pre>" + } + + function src(id) { + return document.getElementById(id).innerHTML; + } + + function example(id, format) { + var result; + try { + result = Viz(src(id), format); + if (format === "svg") + return result; + else + return inspect(result); + } catch(e) { + return inspect(e.toString()); + } + } + + document.body.innerHTML += "<p>Examples from the <a href=\"http://graphviz.org/Gallery.php\">Graphviz gallery</a>.</p>" + + document.body.innerHTML += "<h1>Cluster (svg output)</h1>"; + document.body.innerHTML += example("cluster", "svg"); + </script> + + </body> +</html> diff --git a/src/static/viz.js-master/viz.c b/src/static/viz.js-master/viz.c new file mode 100755 index 0000000..aa1a100 --- /dev/null +++ b/src/static/viz.js-master/viz.c @@ -0,0 +1,21 @@ +#include "cdt.h" +#include "gvc.h" + +extern gvplugin_library_t gvplugin_dot_layout_LTX_library; +extern gvplugin_library_t gvplugin_core_LTX_library; + +__attribute__((used)) void vizRenderFromString(char *string, char *format) { + + GVC_t *context = gvContext(); + gvAddLibrary(context, &gvplugin_core_LTX_library); + gvAddLibrary(context, &gvplugin_dot_layout_LTX_library); + + Agraph_t *graph = agmemread(string); + gvLayout(context, graph, "dot"); + gvRender(context, graph, format, stdout); + + gvFreeLayout(context, graph); + agclose(graph); + gvFreeContext(context); + +} diff --git a/src/static/viz.js-master/viz.js b/src/static/viz.js-master/viz.js new file mode 100755 index 0000000..cd928b3 --- /dev/null +++ b/src/static/viz.js-master/viz.js @@ -0,0 +1,9 @@ +function Ob(Mi){throw Mi}var Wb=void 0,qc=!0,Ac=null,Ud=!1;function ng(){return(function(){})} + + + +("undefined"!==typeof exports&&exports!==Ac?exports:this).Viz=(function(Mi,it){function am(a){eval.call(Ac,a)}function og(a){H.print(a+":\n"+Error().stack);Ob("Assertion: "+a)}function Nc(a,b){a||og("Assertion failed: "+b)}function bm(a){try{var b=eval("_"+a)}catch(g){try{b=jt.Module["_"+a]}catch(e){}}Nc(b,"Cannot call unknown function "+a+" (perhaps LLVM optimizations or closure removed it?)");return b}function cm(a,b,g,e){function l(a,b){if("string"==b){if(a===Ac||a===Wb||0===a){return 0}p||(p=fa.na());var u=fa.ma(a.length+1);dm(a,u);return u}return"array"==b?(p||(p=fa.na()),u=fa.ma(a.length),em(a,u),u):a}var p=0,d=0,e=e?e.map((function(a){return l(a,g[d++])})):[];a=a.apply(Ac,e);"string"==b?b=Vd(a):(Nc("array"!=b),b=a);p&&fa.Ha(p);return b}function pg(u,s,g){g=g||"i8";"*"===g.charAt(g.length-1)&&(g="i32");switch(g){case"i1":n[u]=s;break;case"i8":n[u]=s;break;case"i16":C[u>>1]=s;break;case"i32":a[u>>2]=s;break;case"i64":Cf=[s>>>0,Math.min(Math.floor(s/4294967296),4294967295)>>>0];a[u>>2]=Cf[0];a[u+4>>2]=Cf[1];break;case"float":hb[u>>2]=s;break;case"double":f[b>>3]=s;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2];break;default:og("invalid type for setValue: "+g)}}function Df(u,s){s=s||"i8";"*"===s.charAt(s.length-1)&&(s="i32");switch(s){case"i1":return n[u];case"i8":return n[u];case"i16":return C[u>>1];case"i32":return a[u>>2];case"i64":return a[u>>2];case"float":return hb[u>>2];case"double":return a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3];default:og("invalid type for setValue: "+s)}return Ac}function d(a,b,g,e){var l,p;"number"===typeof a?(l=qc,p=a):(l=Ud,p=a.length);var d="string"===typeof b?b:Ac,g=g==c?e:[wb,fa.ma,fa.oa][g===Wb?qe:g](Math.max(p,d?1:b.length));if(l){return Ef(g,0,p),g}if("i8"===d){return ca.set(new Uint8Array(a),g),g}for(l=0;l<p;){var f=a[l];"function"===typeof f&&(f=fa.md(f));e=d||b[l];0===e?l++:("i64"==e&&(e="i32"),pg(g+l,f,e),l+=fa.ea(e))}return g}function Vd(a,b){for(var g=new fa.U,e="undefined"==typeof b,l="",p=0,d;;){d=ca[a+p|0];if(e&&0==d){break}l+=g.Da(d);p+=1;if(!e&&p==b){break}}return l}function wh(a){for(;0<a.length;){var b=a.shift(),g=b.ca;"number"===typeof g?b.W===Wb?fa.t("v",g):fa.t("vi",g,[b.W]):g(b.W===Wb?Ac:b.W)}}function Od(a,b,g){a=(new fa.U).jb(a);g&&(a.length=g);b||a.push(0);return a}function dm(a,b,g){a=Od(a,g);for(g=0;g<a.length;){n[b+g|0]=a[g],g+=1}}function em(a,b){for(var g=0;g<a.length;g++){n[b+g|0]=a[g]}}function fm(a,b){return 0<=a?a:32>=b?2*Math.abs(1<<b-1)+a:Math.pow(2,b)+a}function gm(a,b){if(0>=a){return a}var g=32>=b?Math.abs(1<<b-1):Math.pow(2,b-1);if(a>=g&&(32>=b||a>g)){a=-2*g+a}return a}function Ni(a){ff++;H.monitorRunDependencies&&H.monitorRunDependencies(ff);a?(Nc(!qg[a]),qg[a]=1,rg===Ac&&"undefined"!==typeof setInterval&&(rg=setInterval((function(){var a=Ud,b;for(b in qg){a||(a=qc,H.o("still waiting on run dependencies:")),H.o("dependency: "+b)}a&&H.o("(end of list)")}),6e3))):H.o("warning: run dependency added without ID")}function xh(a){ff--;H.monitorRunDependencies&&H.monitorRunDependencies(ff);a?(Nc(qg[a]),delete qg[a]):H.o("warning: run dependency removed without ID");0==ff&&(rg!==Ac&&(clearInterval(rg),rg=Ac),!hm&&Oi&&Pi())}function Pd(a,b,g){for(var e=0;e<g;){var l=ca[a+e|0],p=ca[b+e|0];if(l==p&&0==l){break}if(0==l){return-1}if(0==p){return 1}if(l==p){e++}else{return l>p?1:-1}}return 0}function $(a,b){return Pd(a,b,sg)}function Ne(a,b,g){for(var a=a|0,b=b|0,g=g|0,e=0,l=0,p=0;(e|0)<(g|0);){l=ca[a+e|0];p=ca[b+e|0];if((l|0)!=(p|0)){return((l|0)>(p|0)?1:-1)|0}e=e+1|0}return 0}function $d(b,s,g){b|=0;s|=0;g|=0;if((b&3)==(s&3)){for(;b&3;){if(0==(g|0)){return}n[b]=n[s];b=b+1|0;s=s+1|0;g=g-1|0}for(;4<=(g|0);){a[b>>2]=a[s>>2],b=b+4|0,s=s+4|0,g=g-4|0}}for(;0<(g|0);){n[b]=n[s],b=b+1|0,s=s+1|0,g=g-1|0}}function xa(a){for(var a=a|0,b=0,b=a;n[b]|0;){b=b+1|0}return b-a|0}function Ha(b){Ha.d||(Ha.d=d([0],"i32",qe));return a[Ha.d>>2]=b}function kt(a,b,g){var e=N.b[a];if(e){if(e.q){if(0>g){return Ha(ta.i),-1}if(e.object.e){if(e.object.m){for(var l=0;l<g;l++){try{e.object.m(n[b+l|0])}catch(p){return Ha(ta.r),-1}}e.object.timestamp=Date.now();return l}Ha(ta.ra);return-1}l=e.position;a=N.b[a];if(!a||a.object.e){Ha(ta.l),b=-1}else{if(a.q){if(a.object.g){Ha(ta.R),b=-1}else{if(0>g||0>l){Ha(ta.i),b=-1}else{for(var d=a.object.c;d.length<l;){d.push(0)}for(var c=0;c<g;c++){d[l+c]=ca[b+c|0]}a.object.timestamp=Date.now();b=c}}}else{Ha(ta.j),b=-1}}-1!=b&&(e.position+=b);return b}Ha(ta.j);return-1}Ha(ta.l);return-1}function re(a,b,g,e){g*=b;if(0==g){return 0}a=kt(e,a,g);return-1==a?(N.b[e]&&(N.b[e].error=qc),0):Math.floor(a/b)}function im(u,s){function g(u){var g;"double"===u?g=(a[b>>2]=a[s+l>>2],a[b+4>>2]=a[s+(l+4)>>2],f[b>>3]):"i64"==u?g=[a[s+l>>2],a[s+(l+4)>>2]]:(u="i32",g=a[s+l>>2]);l+=fa.I(u);return g}for(var e=u,l=0,p=[],d,c;;){var r=e;d=n[e];if(0===d){break}c=n[e+1|0];if(37==d){var q=Ud,h=Ud,w=Ud,i=Ud;a:for(;;){switch(c){case 43:q=qc;break;case 45:h=qc;break;case 35:w=qc;break;case 48:if(i){break a}else{i=qc;break};default:break a}e++;c=n[e+1|0]}var v=0;if(42==c){v=g("i32"),e++,c=n[e+1|0]}else{for(;48<=c&&57>=c;){v=10*v+(c-48),e++,c=n[e+1|0]}}var t=Ud;if(46==c){var y=0,t=qc;e++;c=n[e+1|0];if(42==c){y=g("i32"),e++}else{for(;;){c=n[e+1|0];if(48>c||57<c){break}y=10*y+(c-48);e++}}c=n[e+1|0]}else{y=6}var z;switch(String.fromCharCode(c)){case"h":c=n[e+2|0];104==c?(e++,z=1):z=2;break;case"l":c=n[e+2|0];108==c?(e++,z=8):z=4;break;case"L":;case"q":;case"j":z=8;break;case"z":;case"t":;case"I":z=4;break;default:z=Ac}z&&e++;c=n[e+1|0];if(-1!="diuoxXp".split("").indexOf(String.fromCharCode(c))){r=100==c||105==c;z=z||4;var B=d=g("i"+8*z),F;8==z&&(d=fa.eb(d[0],d[1],117==c));4>=z&&(d=(r?gm:fm)(d&Math.pow(256,z)-1,8*z));var D=Math.abs(d),r="";if(100==c||105==c){F=8==z&&tg?tg.stringify(B[0],B[1],Ac):gm(d,8*z).toString(10)}else{if(117==c){F=8==z&&tg?tg.stringify(B[0],B[1],qc):fm(d,8*z).toString(10),d=Math.abs(d)}else{if(111==c){F=(w?"0":"")+D.toString(8)}else{if(120==c||88==c){r=w?"0x":"";if(8==z&&tg){F=(B[1]>>>0).toString(16)+(B[0]>>>0).toString(16)}else{if(0>d){d=-d;F=(D-1).toString(16);B=[];for(w=0;w<F.length;w++){B.push((15-parseInt(F[w],16)).toString(16))}for(F=B.join("");F.length<2*z;){F="f"+F}}else{F=D.toString(16)}}88==c&&(r=r.toUpperCase(),F=F.toUpperCase())}else{112==c&&(0===D?F="(nil)":(r="0x",F=D.toString(16)))}}}}if(t){for(;F.length<y;){F="0"+F}}for(q&&(r=0>d?"-"+r:"+"+r);r.length+F.length<v;){h?F+=" ":i?F="0"+F:r=" "+r}F=r+F;F.split("").forEach((function(a){p.push(a.charCodeAt(0))}))}else{if(-1!="fFeEgG".split("").indexOf(String.fromCharCode(c))){d=g("double");if(isNaN(d)){F="nan",i=Ud}else{if(isFinite(d)){t=Ud;z=Math.min(y,20);if(103==c||71==c){t=qc,y=y||1,z=parseInt(d.toExponential(z).split("e")[1],10),y>z&&-4<=z?(c=(103==c?"f":"F").charCodeAt(0),y-=z+1):(c=(103==c?"e":"E").charCodeAt(0),y--),z=Math.min(y,20)}if(101==c||69==c){F=d.toExponential(z),/[eE][-+]\d$/.test(F)&&(F=F.slice(0,-1)+"0"+F.slice(-1))}else{if(102==c||70==c){F=d.toFixed(z)}}r=F.split("e");if(t&&!w){for(;1<r[0].length&&-1!=r[0].indexOf(".")&&("0"==r[0].slice(-1)||"."==r[0].slice(-1));){r[0]=r[0].slice(0,-1)}}else{for(w&&-1==F.indexOf(".")&&(r[0]+=".");y>z++;){r[0]+="0"}}F=r[0]+(1<r.length?"e"+r[1]:"");69==c&&(F=F.toUpperCase());q&&0<=d&&(F="+"+F)}else{F=(0>d?"-":"")+"inf",i=Ud}}for(;F.length<v;){F=h?F+" ":i&&("-"==F[0]||"+"==F[0])?F[0]+"0"+F.slice(1):(i?"0":" ")+F}97>c&&(F=F.toUpperCase());F.split("").forEach((function(a){p.push(a.charCodeAt(0))}))}else{if(115==c){q=g("i8*")||lt;i=xa(q);t&&(i=Math.min(i,y));if(!h){for(;i<v--;){p.push(32)}}for(w=0;w<i;w++){p.push(ca[q++|0])}if(h){for(;i<v--;){p.push(32)}}}else{if(99==c){for(h&&p.push(g("i8"));0<--v;){p.push(32)}h||p.push(g("i8"))}else{if(110==c){h=g("i32*"),a[h>>2]=p.length}else{if(37==c){p.push(d)}else{for(w=r;w<e+2;w++){p.push(n[w])}}}}}}}e+=2}else{p.push(d),e+=1}}return p}function Lb(a,b,g){b=im(b,g);g=fa.na();re(d(b,"i8",ce),1,b.length,a);fa.Ha(g)}function ia(a,b,g,e){Ob("Assertion failed: "+(e?Vd(e):"unknown condition")+", at: "+[a?Vd(a):"unknown filename",b,g?Vd(g):"unknown function"]+" at "+Error().stack)}function Hb(a){var b=xa(a),g=wb(b+1);$d(g,a,b);n[g+b|0]=0;return g}function jm(b,s,g){s=im(s,g);g=s.length;if(0>b){var b=-b,e=wb(g+1),b=a[b>>2]=e}for(e=0;e<g;e++){n[b+e|0]=s[e]}n[b+e|0]=0;return s.length}function Pa(a,b,g){return jm(a,b,g)}function Ff(){Ff.d||(Ff.d=d([0],"i8",Qi));return Ff.d}function Ef(b,s,g){var b=b|0,s=s|0,g=g|0,e=0,l=0,p=0,d=0,e=b+g|0;if(g|0){d=b&3;l=s|s<<8|s<<16|s<<24;p=e&-4;if(d){for(d=b+4-d|0;(b|0)<(d|0);){n[b]=s,b=b+1|0}}for(;(b|0)<(p|0);){a[b>>2]=l,b=b+4|0}}for(;(b|0)<(e|0);){n[b]=s,b=b+1|0}}function yc(u,s,g,e){yc.whiteSpace||(yc.whiteSpace={},yc.whiteSpace[32]=1,yc.whiteSpace[9]=1,yc.whiteSpace[10]=1,yc.whiteSpace[" "]=1,yc.whiteSpace["\t"]=1,yc.whiteSpace["\n"]=1);var u=Vd(u),l=0;if(0<=u.indexOf("%n")){var p=s,s=(function(){l++;return p()}),d=g,g=(function(){l--;return d()})}var c=0,r=0,q=0,h,c=0;a:for(;c<u.length;){if("%"===u[c]&&"n"==u[c+1]){var w=a[e+q>>2],q=q+fa.I("void*");a[w>>2]=l;c+=2}else{if("%"===u[c]&&"c"==u[c+1]){w=a[e+q>>2],q+=fa.I("void*"),r++,h=s(),n[w]=h,c+=2}else{for(;;){h=s();if(0==h){return r}if(!(h in yc.whiteSpace)){break}}g();if("%"===u[c]){c++;for(var i=c;48<=u[c].charCodeAt(0)&&57>=u[c].charCodeAt(0);){c++}var v;c!=i&&(v=parseInt(u.slice(i,c),10));var t=i=Ud,y=Ud;"l"==u[c]?(i=qc,c++,"l"==u[c]&&(y=qc,c++)):"h"==u[c]&&(t=qc,c++);var z=u[c];c++;var B=0,w=[];if("f"==z||"e"==z||"g"==z||"E"==z){B=0;for(h=s();0<h;){w.push(String.fromCharCode(h)),/^[+-]?[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)?$/.exec(w.join(""))&&(B=w.length),h=s()}for(h=0;h<w.length-B+1;h++){g()}w.length=B}else{h=s();for(var F=qc;(B<v||isNaN(v))&&0<h;){if(!(h in yc.whiteSpace)&&("s"==z||("d"===z||"u"==z||"i"==z)&&(48<=h&&57>=h||F&&45==h)||"x"===z&&(48<=h&&57>=h||97<=h&&102>=h||65<=h&&70>=h))&&(c>=u.length||h!==u[c].charCodeAt(0))){w.push(String.fromCharCode(h)),h=s(),B++,F=Ud}else{break}}g()}if(0===w.length){return 0}h=w.join("");w=a[e+q>>2];q+=fa.I("void*");switch(z){case"d":;case"u":;case"i":t?C[w>>1]=parseInt(h,10):y?(Cf=[parseInt(h,10)>>>0,Math.min(Math.floor(parseInt(h,10)/4294967296),4294967295)>>>0],a[w>>2]=Cf[0],a[w+4>>2]=Cf[1]):a[w>>2]=parseInt(h,10);break;case"x":a[w>>2]=parseInt(h,16);break;case"f":;case"e":;case"g":;case"E":i?(f[b>>3]=parseFloat(h),a[w>>2]=a[b>>2],a[w+4>>2]=a[b+4>>2]):hb[w>>2]=parseFloat(h);break;case"s":i=Od(h);for(t=0;t<i.length;t++){n[w+t|0]=i[t]}}r++}else{if(u[c]in yc.whiteSpace){for(h=s();h in yc.whiteSpace;){if(0>=h){break a}h=s()}g(h)}else{if(h=s(),u[c].charCodeAt(0)!==h){g(h);break a}}c++}}}}return r}function gd(a,b,g){var e=0;return yc(b,(function(){return n[a+e++|0]}),(function(){e--}),g)}function Jd(a,b,g){var e,l,p,c;if(0==a&&0==(a=Df(g,"i8*"))){return 0}a:for(;;){l=Df(a++,"i8");for(e=b;0!=(p=Df(e++,"i8"));){if(l==p){continue a}}break}if(0==l){return pg(g,0,"i8*"),0}for(c=a-1;;){l=Df(a++,"i8");e=b;do{if((p=Df(e++,"i8"))==l){return 0==l?a=0:pg(a-1,0,"i8"),pg(g,a,"i8*"),c}}while(0!=p)}og("strtok_r error!")}function Ze(a){return a in{32:0,9:0,10:0,11:0,12:0,13:0}}function ee(a,b){var g=0;do{n[a+g|0]=n[b+g|0],g++}while(0!=n[b+(g-1)|0])}function fe(a,b){var g=xa(a),e=0;do{n[a+g+e|0]=n[b+e|0],e++}while(0!=n[b+(e-1)|0])}function oc(a,b){a--;do{a++;var g=n[a];if(g==b){return a}}while(g);return 0}function Oe(b,s){for(var g=b;Ze(n[b]);){b++}var e=1;45==n[b]?(e=-1,b++):43==n[b]&&b++;for(var l,p=0,c=Ud;;){l=n[b];if(!(48<=l&&57>=l)){break}c=qc;p=10*p+l-48;b++}var d=Ud;if(46==n[b]){b++;for(var f=.1;;){l=n[b];if(!(48<=l&&57>=l)){break}d=qc;p+=f*(l-48);f/=10;b++}}if(!c&&!d){return s&&(a[s>>2]=g),0}l=n[b];if(101==l||69==l){b++;g=0;c=Ud;l=n[b];45==l?(c=qc,b++):43==l&&b++;for(l=n[b];48<=l&&57>=l;){g=10*g+l-48,b++,l=n[b]}c&&(g=-g);p*=Math.pow(10,g)}s&&(a[s>>2]=b);return p*e}function Ee(a){for(;Ze(n[a]);){a++}var b=1;45==n[a]?(b=-1,a++):43==n[a]&&a++;var g=10;!g&&48==n[a]&&(120==n[a+1|0]||88==n[a+1|0]?(g=16,a+=2):(g=8,a++));g||(g=10);for(var e,l=0;0!=(e=n[a])&&!(e=parseInt(String.fromCharCode(e),g),isNaN(e));){l=l*g+e,a++}l*=b;if(2147483647<l||-2147483648>l){l=2147483647<l?2147483647:-2147483648,Ha(ta.sa)}return l}function mt(a,b,g,e){var l=N.b[a];if(!l||l.object.e){return Ha(ta.l),-1}if(l.p){if(l.object.g){return Ha(ta.R),-1}if(0>g||0>e){return Ha(ta.i),-1}for(a=0;l.h.length&&0<g;){n[b++|0]=l.h.pop(),g--,a++}l=l.object.c;g=Math.min(l.length-e,g);if(l.subarray||l.slice){for(var p=0;p<g;p++){n[b+p|0]=l[e+p]}}else{for(p=0;p<g;p++){n[b+p|0]=l.get(e+p)}}return a+g}Ha(ta.j);return-1}function Ri(a,b,g){var e=N.b[a];if(e){if(e.p){if(0>g){return Ha(ta.i),-1}if(e.object.e){if(e.object.input){for(a=0;e.h.length&&0<g;){n[b++|0]=e.h.pop(),g--,a++}for(var l=0;l<g;l++){try{var p=e.object.input()}catch(c){return Ha(ta.r),-1}if(p===Ac||p===Wb){break}a++;n[b+l|0]=p}return a}Ha(ta.ra);return-1}p=e.h.length;a=mt(a,b,g,e.position);-1!=a&&(e.position+=e.h.length-p+a);return a}Ha(ta.j);return-1}Ha(ta.l);return-1}function Gf(a){if(!N.b[a]){return-1}var b=N.b[a];if(b.f||b.error){return-1}a=Ri(a,Gf.d,1);return 0==a?(b.f=qc,-1):-1==a?(b.error=qc,-1):ca[Gf.d|0]}function Hf(a,b,g){if(!N.b[g]){return 0}var e=N.b[g];if(e.error||e.f){return 0}for(var l,p=0;p<b-1&&10!=l;p++){l=Gf(g);if(-1==l){if(e.error){return 0}if(e.f){break}}n[a+p|0]=l}n[a+p|0]=0;return a}function km(a){var b=a+xa(a);do{if(58==n[b]){return b}b--}while(b>=a);return 0}function ug(a,b){for(var g=Ud,e,l=0;63>l;l++){e=g?0:n[b+l|0],n[a+l|0]=e,g=g||0==n[b+l|0]}}function yh(a,b,g,e,l){for(var p=0,c,d,f;p<g;){if(c=p+g>>>1,f=b+c*e,d=fa.t("iii",l,[a,f]),0>d){g=c}else{if(0<d){p=c+1}else{return f}}}return 0}function Qd(){wh(Si);Ob("exit(1) called, at "+Error().stack)}function se(a){return 65<=a&&90>=a?a-65+97:a}function P(){Ob("abort() at "+Error().stack)}function If(a,b){return Math.sqrt(a*a+b*b)}function nt(b,s,g){var e=a[g>>2],l=s&3,g=0!=l,l=1!=l,p=Boolean(s&512),c=Boolean(s&2048),d=Boolean(s&1024),f=Boolean(s&8),b=N.C(Vd(b));if(!b.L){return Ha(b.error),-1}if(s=b.object||Ac){if(p&&c){return Ha(ta.pa),-1}if((g||p||d)&&s.g){return Ha(ta.R),-1}if(l&&!s.N||g&&!s.write){return Ha(ta.j),-1}if(d&&!s.e){s.c=[]}else{if(!N.Ba(s)){return Ha(ta.r),-1}}b=b.path}else{if(!p){return Ha(ta.S),-1}if(!b.v.write){return Ha(ta.j),-1}s=N.$(b.v,b.name,[],e&256,e&128);b=b.ia+"/"+b.name}e=N.b.length;if(s.g){g=0;lm&&(g=wb(lm.V));var l=[],h;for(h in s.c){l.push(h)}N.b[e]={path:b,object:s,position:-2,p:qc,q:Ud,K:Ud,error:Ud,f:Ud,h:[],c:l,xa:g}}else{N.b[e]={path:b,object:s,position:0,p:l,q:g,K:f,error:Ud,f:Ud,h:[]}}return e}function vg(a,b){var g,b=Vd(b);if("r"==b[0]){g=-1!=b.indexOf("+")?2:0}else{if("w"==b[0]){g=-1!=b.indexOf("+")?2:1,g|=1536}else{if("a"==b[0]){g=-1!=b.indexOf("+")?2:1,g|=512,g|=8}else{return Ha(ta.i),0}}}g=nt(a,g,d([511,0,0,0],"i32",ce));return-1==g?0:g}function Jf(a){N.b[a]||Ha(ta.l);N.b[a]?(N.b[a].xa&&E(N.b[a].xa),N.b[a]=Ac):Ha(ta.l)}function zh(a,b){var g=0,e;do{g||(e=a,g=b);var l=n[a++|0],p=n[g++|0];if(0==p){return e}p!=l&&(a=e+1,g=0)}while(l);return 0}function mm(b,s){if(N.b[b]){var g=Od(N.b[b].path);g=d(g,"i8",ce);g=N.ba(Vd(g),Wb);if(g!==Ac&&N.Ba(g)){var e=ot;a[s+e.zb>>2]=1;a[s+e.Cb>>2]=0;a[s+e.vb>>2]=0;a[s+e.rb>>2]=4096;a[s+e.wb>>2]=g.ga;var l=Math.floor(g.timestamp/1e3);if(e.la===Wb){e.la=e.qb.Ja;e.Ga=e.yb.Ja;e.Fa=e.tb.Ja;var p=1e3*(g.timestamp%1e3);a[s+e.qb.Ia>>2]=p;a[s+e.yb.Ia>>2]=p;a[s+e.tb.Ia>>2]=p}a[s+e.la>>2]=l;a[s+e.Ga>>2]=l;a[s+e.Fa>>2]=l;var c=0,f=l=0,r=p=0;g.e?(p=r=g.ga,l=f=0,c=8192):(p=1,r=0,g.g?(l=4096,f=1,c=16384):(c=g.c||g.link,l=c.length,f=Math.ceil(c.length/4096),c=g.link===Wb?32768:40960));a[s+e.ub>>2]=p;a[s+e.Ab>>2]=r;a[s+e.Bb>>2]=l;a[s+e.sb>>2]=f;g.N&&(c|=365);g.write&&(c|=146);a[s+e.xb>>2]=c}}else{Ha(ta.l)}}function $e(a,b,g){if(N.b[a]&&!N.b[a].object.e){var e=N.b[a];1===g?b+=e.position:2===g&&(b+=e.object.c.length);0>b?(Ha(ta.i),g=-1):(e.h=[],g=e.position=b)}else{Ha(ta.l),g=-1}-1!=g&&(N.b[a].f=Ud)}function nm(a,b,g,e){g*=b;if(0==g){return 0}a=Ri(e,a,g);e=N.b[e];if(-1==a){return e&&(e.error=qc),0}a<g&&(e.f=qc);return Math.floor(a/b)}function Ah(b){var s,g;Ah.Z?(g=a[om>>2],s=a[g>>2]):(Ah.Z=qc,Fd.USER="root",Fd.PATH="/",Fd.PWD="/",Fd.HOME="/home/emscripten",Fd.LANG="en_US.UTF-8",Fd._="./this.program",s=d(1024,"i8",qe),g=d(256,"i8*",qe),a[g>>2]=s,a[om>>2]=g);var e=[],l=0,p;for(p in b){if("string"===typeof b[p]){var c=p+"="+b[p];e.push(c);l+=c.length}}1024<l&&Ob(Error("Environment size exceeded TOTAL_ENV_SIZE!"));for(b=0;b<e.length;b++){c=e[b];for(l=0;l<c.length;l++){n[s+l|0]=c.charCodeAt(l)}n[s+l|0]=0;a[g+4*b>>2]=s;s+=c.length+1}a[g+4*e.length>>2]=0}function wg(a){if(0===a){return 0}a=Vd(a);if(!Fd.hasOwnProperty(a)){return 0}wg.d&&E(wg.d);wg.d=d(Od(Fd[a]),"i8",Qi);return wg.d}function Kf(a){Kf.buffer||(Kf.buffer=wb(256));var b=Kf.buffer;if(a in Ti){if(255<Ti[a].length){Ha(ta.sa)}else{for(var a=Ti[a],g=0;g<a.length;g++){n[b+g|0]=a.charCodeAt(g)}n[b+g|0]=0}}else{Ha(ta.i)}return Kf.buffer}function pm(a){return Number(N.b[a]&&N.b[a].error)}function qm(a){return 48<=a&&57>=a||97<=a&&122>=a||65<=a&&90>=a}function Lf(a){return 97<=a&&122>=a||65<=a&&90>=a}function af(a,b,g){if(0!=b){for(var e=[],l=0;l<b;l++){e.push(l)}e.sort((function(b,e){return fa.t("iii",g,[a+4*b,a+4*e])}));var p=wb(4*b);$d(p,a,4*b);for(l=0;l<b;l++){e[l]!=l&&$d(a+4*l,p+4*e[l],4)}E(p)}}function pt(){switch(8){case 8:return qt;case 54:;case 56:;case 21:;case 61:;case 63:;case 22:;case 67:;case 23:;case 24:;case 25:;case 26:;case 27:;case 69:;case 28:;case 101:;case 70:;case 71:;case 29:;case 30:;case 199:;case 75:;case 76:;case 32:;case 43:;case 44:;case 80:;case 46:;case 47:;case 45:;case 48:;case 49:;case 42:;case 82:;case 33:;case 7:;case 108:;case 109:;case 107:;case 112:;case 119:;case 121:return 200809;case 13:;case 104:;case 94:;case 95:;case 34:;case 35:;case 77:;case 81:;case 83:;case 84:;case 85:;case 86:;case 87:;case 88:;case 89:;case 90:;case 91:;case 94:;case 95:;case 110:;case 111:;case 113:;case 114:;case 115:;case 116:;case 117:;case 118:;case 120:;case 40:;case 16:;case 79:;case 19:return-1;case 92:;case 93:;case 5:;case 72:;case 6:;case 74:;case 92:;case 93:;case 96:;case 97:;case 98:;case 99:;case 102:;case 103:;case 105:return 1;case 38:;case 66:;case 50:;case 51:;case 4:return 1024;case 15:;case 64:;case 41:return 32;case 55:;case 37:;case 17:return 2147483647;case 18:;case 1:return 47839;case 59:;case 57:return 99;case 68:;case 58:return 2048;case 0:return 2097152;case 3:return 65536;case 14:return 32768;case 73:return 32767;case 39:return 16384;case 60:return 1e3;case 106:return 700;case 52:return 256;case 62:return 255;case 2:return 100;case 65:return 64;case 36:return 20;case 100:return 16;case 20:return 6;case 53:return 4}Ha(ta.i);return-1}function Gd(a){var b=Gd;b.Z||(kd=kd+4095>>12<<12,b.Z=qc,Gd.Fb=kd);b=kd;0!=a&&fa.oa(a);return b}function xg(a,b){var g,a=a|0,b=b|0;g=16;if((b|0)<(a|0)&(a|0)<(b+g|0)){b=b+g|0;for(a=a+g|0;0<(g|0);){a=a-1|0,b=b-1|0,g=g-1|0,n[a]=n[b]}}else{$d(a,b,g)}}function rm(b){var s;s=(b+8|0)>>2;var b=a[s]>>2,g=a[b];if(0!=(g&4096|0)){var e=a[b+1];return e}a:do{if(0==(g&3|0)){if(0!=(g&112|0)){e=a[b+2]}else{var l=a[b+1];if(0==(l|0)){e=0}else{var p=l+4|0,c=a[p>>2];b:do{if(0==(c|0)){var d=l,f=a[l>>2]}else{for(var h=l,m=p,w=c;;){var i=w|0;a[m>>2]=a[i>>2];a[i>>2]=h;m=w+4|0;i=a[m>>2];if(0==(i|0)){d=w;f=h;break b}else{h=w,w=i}}}}while(0);if(0==(f|0)){e=d}else{l=d|0;for(c=f;;){p=a[c+4>>2];if(0==(p|0)){l=c}else{for(;!(h=p|0,a[c+4>>2]=a[h>>2],a[h>>2]=c,h=a[p+4>>2],0==(h|0));){c=p,p=h}l=a[l>>2]=p}l|=0;p=a[l>>2];if(0==(p|0)){e=d;break a}else{c=p}}}}}}else{if(p=a[b+2],c=a[b+3],l=(c<<2)+p|0,0<(c|0)){for(h=c=0;;){w=a[p>>2];if(0!=(w|0)){0==(c|0)?c=h=w:a[c>>2]=w;for(;!(w=a[c>>2],0==(w|0));){c=w}a[p>>2]=c}p=p+4|0;if(p>>>0>=l>>>0){e=h;break a}}}else{e=0}}}while(0);a[a[s]+4>>2]=e;d=a[s]|0;a[d>>2]|=4096;return e}function sm(b,s){var g=h;if(0==(a[1345659]|0)){n[5382660]=1;n[5382644]=1;n[5382640]=1;n[5382612]=1;var e;e=Bh(5351280,0);a[1345659]=e;e=(e+40|0)>>2;0!=(a[Mf(a[a[e]+4>>2]|0,5345132,5338228)+8>>2]|0)&&P();var l=Mf(a[a[e]+4>>2]|0,5375068,5338228);1!=(a[l+8>>2]|0)&&P();n[l+12|0]=0;e=Mf(a[a[e]+4>>2]|0,5377776,5338228);2==(a[e+8>>2]|0)?n[e+12|0]=0:P()}else{n[5382660]&n[5382644]&n[5382640]||aa(0,5347112,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i))}h=g;Nf(0,5332600,5368832);g=da(340);e=g>>2;0!=(g|0)&&(a[e]=5381524,a[e+4]=88,a[e+8]=0,a[e+9]=1);e=a[g+32>>2];if(0!=(e|0)&&(l=a[e>>2],0!=(l|0))){for(;!(103==n[l]<<24>>24&&0!=(zh(l,5327332)|0)&&Ui(g,a[e+4>>2]),e=e+8|0,l=a[e>>2],0==(l|0));){}}n[g+44|0]=0;e=lf(g,2,5361972);0!=(e|0)&&(a[g+132>>2]=a[a[e+16>>2]+12>>2]);Ui(g,5251580);Ui(g,5251572);e=a[1345664];a[1345664]=22;tm(b);Vi();a[1345664]=e;e=a[1345658];Ch(g,e,5345064);var l=a[e+32>>2],p=a[Fe>>2],c;um(g,s);var d=a[g+124>>2];c=d>>2;a[c+14]=Dh(d,a[c+13]);0==(a[l+44>>2]|0)&&0==(a[c+37]&67108864|0)?re(5332896,20,1,a[Qa>>2]):(a[c+9]=p,0==(p|0)&&(p=d+148|0,a[p>>2]|=134217728),Wi(g,l),Xi(d),Yi(g));l=e+176|0;d=a[l>>2];0!=(d|0)&&(J[d](e),a[l>>2]=0);l=e+44|0;0!=(a[l>>2]|0)&&(vm(e),a[l>>2]=0,a[a[e+32>>2]+44>>2]=0);Pe(e);e=a[1311586];0!=(e|0)&&(Rc(e),a[1311586]=0);e=a[g+52>>2];a:do{if(0!=(e|0)){for(l=e;;){if(d=a[l+4>>2],E(l),0==(d|0)){break a}else{l=d}}}}while(0);l=a[g+100>>2];a:do{if(0!=(l|0)){d=l;for(e=d>>2;;){if(p=a[e],E(a[e+1]),E(a[e+2]),E(d),0==(p|0)){break a}else{d=p,e=d>>2}}}}while(0);Yi(g);e=a[g+40>>2];0!=(e|0)&&E(e);e=a[g+48>>2];0!=(e|0)&&E(e);E(g)}function Rc(b){var s=b>>2;if(0!=(b|0)&&0>=(a[s+6]|0)){var g=a[s+1],e=g+32|0,l=a[e>>2];if(0==(l|0)){l=0}else{if(l=J[l](b,2,0,g),0>(l|0)){return}}if(0!=(a[s+7]|0)){0!=(a[a[b+8>>2]>>2]&4096|0)&&Of(b);var p=b+28|0,c=a[p>>2];0!=(c|0)&&(c=c+24|0,a[c>>2]=a[c>>2]-1|0);a[b+32>>2]=0;a[p>>2]=0;a[b>>2]=a[a[b+16>>2]>>2]}if(l=0==(l|0)){J[a[a[s+4]>>2]](b,0,64);if(0<(Mb(b)|0)){return}var c=b+8|0,d=a[c>>2],p=b+12|0;0<(a[d+12>>2]|0)?(J[a[p>>2]](b,a[d+8>>2],0,g),c=a[c>>2]):c=d;J[a[p>>2]](b,c,0,g)}p=a[s+5];if(0==(p|0)){E(b)}else{if(l&1==(p|0)){J[a[s+3]](b,b,0,g)}}s=a[e>>2];if(0!=(s|0)){J[s](b,6,0,g)}}}function yg(b,s){var g,e,l;l=(b+4|0)>>2;var p=a[l];if(0==(p|0)){a[l]=s;var c=a[s+28>>2];a[b+12>>2]=0==(c|0)?136:c}else{if(0!=(s|0)){c=a[a[b+16>>2]>>2];e=(b+8|0)>>2;0!=(a[a[e]>>2]&4096|0)&&Of(b);var d=a[p+32>>2];if(!(0!=(d|0)&&0>(J[d](b,3,s,p)|0))&&(a[l]=s,l=a[s+28>>2],a[b+12>>2]=0==(l|0)?136:l,0==(a[a[e]>>2]&112|0))){g=rm(b);l=a[e]|0;a[l>>2]&=-4097;a[a[e]+4>>2]=0;a[a[e]+16>>2]=0;e=a[e]>>2;a:do{if(0!=(a[e]&3|0)&&(p=a[e+2],d=a[e+3],l=(d<<2)+p|0,0<(d|0))){for(;;){if(d=p+4|0,a[p>>2]=0,d>>>0<l>>>0){p=d}else{break a}}}}while(0);if(0!=(g|0)){e=s+8|0;l=s+4|0;var p=s|0,d=s+24|0,f=g;for(g=f>>2;;){var h=a[g],m=a[e>>2],w=a[l>>2],m=(0>(m|0)?a[g+2]:f+ -m|0)+a[p>>2]|0,m=0>(w|0)?a[m>>2]:m,i=a[d>>2],w=0==(i|0)?wm(m,w):J[i](b,m,s);a[g+1]=w;J[c](b,f,32);if(0==(h|0)){break}else{f=h,g=f>>2}}}}}}}function xm(b,s,g){var e,l,p,c,d,f;e=0;c=(b+8|0)>>2;0!=(a[a[c]>>2]&4096|0)&&Of(b);var h=a[b+4>>2];l=h>>2;var m=a[l],w=a[l+1];f=(h+8|0)>>2;var i=a[f],n=a[l+5];d=(b+20|0)>>2;a[d]&=-32769;do{if(0==(s|0)){if(0!=(g&384|0)){c=a[c]>>2;b=a[c+2];if(0==(b|0)){var t=0;return t}if(0==(g&256|0)){c=a[c+1]=b}else{g=a[b+4>>2];a[c+1]=g;if(0==(g|0)){return t=0}c=g}return t=0>(i|0)?a[c+8>>2]:c+ -i|0}if(0!=(g&4098|0)){e=a[c];if(0!=(a[e>>2]&144|0)){return t=0}e=a[e+8>>2];if(0==(e|0)){t=0}else{var y=e;p=y>>2;break}return t}if(0==(g&64|0)){return t=0}g=h+16|0;l=a[g>>2];0==(l|0)?0>(a[f]|0)&&(e=106):e=106;a:do{if(106==e&&(n=a[a[c]+8>>2],0!=(n|0))){d=b+12|0;m=0>(i|0);w=-i|0;for(t=l;;){y=a[n>>2];if(0!=(t|0)){J[t](b,m?a[n+8>>2]:n+w|0,h)}if(0>(a[f]|0)){J[a[d>>2]](b,n,0,h)}if(0==(y|0)){break a}n=y;t=a[g>>2]}}}while(0);a[a[c]+4>>2]=0;a[a[c]+8>>2]=0;t=a[a[c]+16>>2]=0}else{if(0==(g&2049|0)){y=a[c];do{if(0==(g&512|0)){p=a[y+4>>2];if(0!=(p|0)&&((0>(i|0)?a[p+8>>2]:p+ -i|0)|0)==(s|0)){var z=p;break}e=s+m|0;var B=0>(w|0)?a[e>>2]:e}else{B=s}e=162}while(0);a:do{if(162==e){e=0>(i|0);p=0>(w|0);for(var s=0==(n|0),z=1>(w|0),F=-i|0,y=y+8|0;;){y=a[y>>2];if(0==(y|0)){t=0;break}var D=(e?a[y+8>>2]:y+F|0)+m|0,D=p?a[D>>2]:D;if(0==((s?z?$(B,D):Ne(B,D,w):J[n](b,B,D,h))|0)){z=y;break a}else{y|=0}}return t}}while(0);if(0==(z|0)){return t=0}a[d]|=32768;if(0!=(g&4098|0)){y=z;p=y>>2;break}if(0==(g&8|0)){if(0==(g&16|0)){g=z}else{if(g=a[c],(z|0)!=(a[g+8>>2]|0)){g=a[z+4>>2]}else{return t=a[g+4>>2]=0}}}else{g=a[z>>2]}a[a[c]+4>>2]=g;return 0==(g|0)?t=0:t=0>(i|0)?a[g+8>>2]:g+ -i|0}f=h+12|0;d=a[f>>2];if(0==(d|0)){d=s}else{if(0==(g&1|0)){d=s}else{if(d=J[d](b,s,h),0==(d|0)){return t=0}}}if(-1<(i|0)){h=d+i|0,b=h>>2}else{if(m=J[a[b+12>>2]](b,0,12,h),0!=(m|0)){a[m+8>>2]=d,h=m,b=h>>2}else{if(0==(a[f>>2]|0)){return t=0}i=a[l+4];if(0==(i|0)||0==(g&1|0)){return t=0}J[i](b,d,h);return t=0}}f=h;d=a[c];l=d>>2;m=a[l];0==(m&128|0)?0==(m&16|0)?e=0==(m&32|0)?145:141:(m=a[l+1],w=0!=(m|0),0==(g&8192|0)?w?(m|0)==(a[l+2]|0)?e=141:(g=m+4|0,w=a[g>>2],a[b+1]=w,a[w>>2]=f,a[b]=m,a[g>>2]=h):e=141:w?(g=m|0,w=a[g>>2],0==(w|0)?e=145:(a[b]=w,a[w+4>>2]=h,a[b+1]=m,a[g>>2]=f)):e=145):e=0==(g&8192|0)?141:145;141==e?(l=a[l+2],g=h,a[g>>2]=l,0==(l|0)?a[b+1]=f:(l=l+4|0,a[b+1]=a[l>>2],a[l>>2]=h),a[a[c]+8>>2]=g):145==e&&(g=d+8|0,l=a[g>>2],0==(l|0)?(l=h,a[g>>2]=l,a[b+1]=f,g=l):(l=g=l+4|0,a[a[l>>2]>>2]=f,a[b+1]=a[l>>2],g=a[g>>2]=h),a[g>>2]=0);g=a[c];l=g+16|0;e=a[l>>2];-1<(e|0)?(a[l>>2]=e+1|0,c=a[c]):c=g;a[c+4>>2]=f;t=0>(i|0)?a[b+2]:h+ -i|0}return t}while(0);e=(y|0)>>2;d=a[e];0==(d|0)?d=0:(a[d+4>>2]=a[p+1],d=a[e]);w=a[c]+8|0;m=a[w>>2];(y|0)==(m|0)?(a[w>>2]=d|0,d=a[a[c]+8>>2],0!=(d|0)&&(a[d+4>>2]=a[p+1])):(w=y+4|0,a[a[w>>2]>>2]=d,d=m+4|0,(y|0)==(a[d>>2]|0)&&(a[d>>2]=a[w>>2]));d=a[c]+4|0;a[d>>2]=(y|0)==(a[d>>2]|0)?a[e]:0;c=a[c]+16|0;a[c>>2]=a[c>>2]-1|0;i=0>(i|0)?a[p+2]:y+ -i|0;c=a[l+4];if(0!=(c|0)&&0!=(g&2|0)){J[c](b,i,h)}if(0<=(a[f]|0)){return i}J[a[b+12>>2]](b,y,0,h);return i}function Bc(b,s){var g,e,l,p,c,d=0,f=h;h=h+4|0;c=f>>2;if(0==(b|0)|0==(s|0)){return h=f,0}var q=wb(40);p=q>>2;if(0==(q|0)){return h=f,0}a[p]=0;a[p+4]=0;a[p+1]=0;yg(q,b);l=(q+20|0)>>2;p=b+32|0;a[l]=0;a[l+1]=0;a[l+2]=0;a[l+3]=0;a[l+4]=0;l=a[p>>2];if(0==(l|0)){g=q,d=238}else{if(a[c]=0,l=J[l](q,1,f,b),0>(l|0)){var m=q,d=239}else{if(0<(l|0)){if(l=a[c],0!=(l|0)){if(0==(a[s+4>>2]&a[l>>2]|0)){m=q,d=239}else{var w=q;e=w>>2;var i=l}}else{if(d=b+28|0,0==(a[d>>2]|0)){m=q,d=239}else{E(q);d=J[a[d>>2]](0,0,40,b);g=d>>2;if(0==(d|0)){return h=f,0}a[g]=0;a[g+4]=0;a[g+1]=0;yg(d,b);a[g+5]=1;a[g+6]=0;a[g+8]=0;a[g+7]=0;g=d;d=238}}}else{g=q,d=238}}}238==d&&(q=J[a[g+12>>2]](g,0,28,b),a[c]=q,0==(q|0)?(m=g,d=239):(a[q>>2]=a[s+4>>2],a[a[c]+4>>2]=0,a[a[c]+8>>2]=0,a[a[c]+20>>2]=0,a[a[c]+16>>2]=0,a[a[c]+12>>2]=0,a[a[c]+24>>2]=0,w=g,e=w>>2,i=a[c]));if(239==d){return E(m),h=f,0}a[e+2]=i;a[e]=a[s>>2];a[e+4]=s;e=a[p>>2];if(0==(e|0)){return h=f,w}J[e](w,5,w,b);h=f;return w}function Mb(b){var s,g;g=(b+8|0)>>2;s=a[g];0!=(a[s>>2]&4096|0)&&(Of(b),s=a[g]);b=s>>2;s=(s+16|0)>>2;do{if(0>(a[s]|0)){var e=a[b];if(0!=(e&12|0)){a[s]=Zi(a[b+1])}else{if(0!=(e&112|0)){e=a[b+2];a:do{if(0==(e|0)){var l=0}else{for(var p=0,c=e;;){if(p=p+1|0,c=a[c>>2],0==(c|0)){l=p;break a}}}}while(0);a[s]=l}}}}while(0);return a[a[g]+16>>2]}function Zi(b){return 0==(b|0)?0:Zi(a[b+4>>2])+Zi(a[b>>2])+1|0}function wm(a,b){if(1>(b|0)){var g=n[a];a:do{if(0==g<<24>>24){var e=a,l=0}else{for(var p=a,c=0,d=g;;){var f=n[p+1|0],c=Math.a(((d&255)<<8)+c+(f&255)|0,17109811),p=p+(0!=f<<24>>24?2:1)|0,f=n[p];if(0==f<<24>>24){e=p;l=c;break a}else{d=f}}}}while(0);e=l+(e-a|0)|0;return e=Math.a(e,17109811)}e=b-1|0;l=a+e|0;a:do{if(0<(e|0)){c=a;for(f=0;;){if(f=Math.a((ca[c]<<8)+ca[c+1|0]+f|0,17109811),c=c+2|0,c>>>0>=l>>>0){g=c;p=f;break a}}}else{g=a,p=0}}while(0);if(g>>>0>l>>>0){return e=p+b|0,e=Math.a(e,17109811)}e=Math.a((ca[g]<<8)+p|0,17109811);e=e+b|0;return e=Math.a(e,17109811)}function ym(b,s,g){var e,l,p,c,d,f,q,m,w,i,n,t,y,z,B,F,D=0,S=h;h=h+128|0;F=S>>2;B=S+8>>2;z=(b+8|0)>>2;var Gb=a[z];if(0==(a[Gb>>2]&4096|0)){var $i=Gb}else{Of(b),$i=a[z]}var I=a[b+4>>2];y=I>>2;var A=a[y],T=a[y+1];t=(I+8|0)>>2;var K=a[t],M=a[y+5];n=(b+20|0)>>2;a[n]&=-32769;var L=a[$i+4>>2];if(0==(s|0)){if(0==(L|0)){var C=0;h=S;return C}if(0==(g&448|0)){return C=0,h=S,C}if(0==(g&64|0)){a:do{if(0==(g&256|0)){var yb=L+4|0,E=a[yb>>2];if(0==(E|0)){var R=L}else{for(var Y=L,he=yb,Rb=E;;){var H=Rb|0;a[he>>2]=a[H>>2];a[H>>2]=Y;var ea=Rb+4|0,wa=a[ea>>2];if(0==(wa|0)){R=Rb;break a}else{Y=Rb,he=ea,Rb=wa}}}}else{var Fb=L|0,V=a[Fb>>2];if(0==(V|0)){R=L}else{for(var W=L,X=Fb,ba=V;;){var ma=ba+4|0;a[X>>2]=a[ma>>2];a[ma>>2]=W;var ib=ba|0,G=a[ib>>2];if(0==(G|0)){R=ba;break a}else{W=ba,X=ib,ba=G}}}}}while(0);a[a[z]+4>>2]=R;C=0>(K|0)?a[R+8>>2]:R+ -K|0;h=S;return C}var mc=I+16|0;if(0==(a[mc>>2]|0)){if(0>(a[t]|0)){D=283}else{var O=$i}}else{D=283}if(283==D){for(var ga=b+12|0,Tb=0>(K|0),ie=-K|0,ua=L;;){var Da=ua+4|0,Ja=a[Da>>2];if(0!=(Ja|0)){var Ab=Ja|0;a[Da>>2]=a[Ab>>2];a[Ab>>2]=ua;ua=Ja}else{var ra=a[ua>>2],P=a[mc>>2];if(0!=(P|0)){J[P](b,Tb?a[ua+8>>2]:ua+ie|0,I)}if(0>(a[t]|0)){J[a[ga>>2]](b,ua,0,I)}if(0==(ra|0)){break}else{ua=ra}}}O=a[z]}a[O+16>>2]=0;C=a[a[z]+4>>2]=0;h=S;return C}i=(b+16|0)>>2;a:do{if(8==(a[a[i]+4>>2]|0)){if(0==(g&4098|0)){D=321}else{for(var ya=0>(T|0),ja=s+A|0,la=ya?a[ja>>2]:ja,va=b,oa=0==(M|0),ka=1>(T|0),Ea=J[a[va>>2]](b,s,4);;){if(0==(Ea|0)){D=321;break a}var Ka=Ea+A|0,Na=ya?a[Ka>>2]:Ka;if(0!=((oa?ka?$(la,Na):Ne(la,Na,T):J[M](b,la,Na,I))|0)){D=321;break a}if((Ea|0)==(s|0)){break}Ea=J[a[va>>2]](b,Ea,8)}var Ba=a[a[z]+4>>2];a[F]=a[Ba+4>>2];a[F+1]=a[Ba>>2];var Wa=Ba,U=S,D=463}}else{D=321}}while(0);a:do{if(321==D){if(0==(g&2565|0)){if(0!=(g&32|0)){var Rd=s,Ra=0>(K|0)?a[s+8>>2]:s+ -K|0,bb=Ra+A|0,Xa=0>(T|0)?a[bb>>2]:bb;if(0==(L|0)){var Sa=S,ue=S,Va=Rd,Ta=Ra,D=483}else{var Aa=Ra,fb=Rd,Ca=Xa,D=340}}else{if(0==(L|0)){ue=Sa=S,Ta=s,D=483}else{if(((0>(K|0)?a[L+8>>2]:L+ -K|0)|0)==(s|0)){var Ya=s,$a=L,La=S,pa=S,D=420}else{var Ga=s+A|0;0>(T|0)?(Aa=s,Ca=a[Ga>>2]):(Aa=s,Ca=Ga);D=340}}}}else{if(0==(g&512|0)){var Fa=s+A|0,N=0>(T|0)?a[Fa>>2]:Fa}else{N=s}0==(L|0)?(ue=Sa=S,Ta=s,D=483):(Aa=s,Ca=N,D=340)}b:do{if(340==D){c:do{if(4==(a[a[i]+4>>2]|0)){var nb=a[a[z]+24>>2];if(0==(nb|0)){var jb=L,cb=S,aa=S}else{if(0==(g&516|0)){jb=L,aa=cb=S}else{for(var kb=0>(K|0),Kb=0>(T|0),Ma=0==(M|0),Q=1>(T|0),lb=-K|0,rb=0,ab=L;;){if((rb|0)>=(nb|0)){D=345;break}var db=(kb?a[ab+8>>2]:ab+lb|0)+A|0,ob=Kb?a[db>>2]:db,pb=Ma?Q?$(Ca,ob):Ne(Ca,ob,T):J[M](b,Ca,ob,I);if(0==(pb|0)){D=357;break}a[(rb<<2>>2)+B]=pb;var ub=a[(0>(pb|0)?ab+4|0:ab|0)>>2];if(0==(ub|0)){C=0;D=518;break}else{rb=rb+1|0,ab=ub}}if(345==D){if(0<(nb|0)){var gb=S;w=gb>>2;var sb=S;m=sb>>2;for(var Ia=L,vb=0;;){if(0>(a[(vb<<2>>2)+B]|0)){var Ua=Ia+4|0,da=a[Ua>>2];if(0>(a[((vb|1)<<2>>2)+B]|0)){var gf=da|0;a[Ua>>2]=a[gf>>2];a[gf>>2]=Ia;a[m+1]=da;var qb=da+4|0,Bb=da,sc=gb}else{a[w]=da,a[m+1]=Ia,qb=da|0,Bb=Ia,sc=da}}else{var xb=Ia|0,za=a[xb>>2];if(0<(a[((vb|1)<<2>>2)+B]|0)){var Nb=za+4|0;a[xb>>2]=a[Nb>>2];a[Nb>>2]=Ia;a[w]=za;qb=za|0;Bb=sb;sc=za}else{a[m+1]=za,a[w]=Ia,qb=za+4|0,Bb=za,sc=Ia}}var Jb=a[qb>>2],ia=vb+2|0;if((ia|0)<(nb|0)){gb=sc,w=gb>>2,sb=Bb,m=sb>>2,Ia=Jb,vb=ia}else{jb=Jb;cb=Bb;aa=sc;break c}}}else{jb=L,aa=cb=S}}else{if(357==D){return C=kb?a[ab+8>>2]:ab+lb|0,h=S,C}if(518==D){return h=S,C}}}}}else{jb=L,aa=cb=S}}while(0);var ca=0>(K|0),Ic=0>(T|0),aj=0!=(M|0),ha=1>(T|0),sa=-K|0,qa=jb,fa=cb,xa=aa;q=xa>>2;c:for(;;){var Ub=qa,na=fa;for(f=na>>2;;){var Za=(ca?a[Ub+8>>2]:Ub+sa|0)+A|0,Ha=Ic?a[Za>>2]:Za,eb=aj?J[M](b,Ca,Ha,I):ha?$(Ca,Ha):Ne(Ca,Ha,T);if(0==(eb|0)){var Ya=Aa,me=fb,$a=Ub,La=na,pa=xa,D=420;break b}if(0<=(eb|0)){break}var te=Ub+4|0,je=a[te>>2];d=je>>2;if(0==(je|0)){D=402;break c}var Oa=(ca?a[d+2]:je+sa|0)+A|0,cc=Ic?a[Oa>>2]:Oa,pc=aj?J[M](b,Ca,cc,I):ha?$(Ca,cc):Ne(Ca,cc,T);if(0<=(pc|0)){D=399;break}var Pa=je|0;a[te>>2]=a[Pa>>2];a[Pa>>2]=Ub;a[f+1]=je;var hd=a[d+1];if(0==(hd|0)){Sa=xa;ue=je;Va=fb;Ta=Aa;D=483;break b}else{Ub=hd,na=je,f=na>>2}}if(399==D){D=0;if(0==(pc|0)){D=400;break}a[q]=je;a[f+1]=Ub;var qd=a[d];if(0==(qd|0)){Sa=je;ue=Ub;Va=fb;Ta=Aa;D=483;break b}else{qa=qd;fa=Ub;xa=je;q=xa>>2;continue}}var Vb=Ub|0,Yb=a[Vb>>2];c=Yb>>2;if(0==(Yb|0)){D=419;break}var Jc=(ca?a[c+2]:Yb+sa|0)+A|0,ta=Ic?a[Jc>>2]:Jc,mb=aj?J[M](b,Ca,ta,I):ha?$(Ca,ta):Ne(Ca,ta,T);if(0<(mb|0)){var hb=Yb+4|0;a[Vb>>2]=a[hb>>2];a[hb>>2]=Ub;a[q]=Yb;var wb=a[c];if(0==(wb|0)){Sa=Yb;ue=na;Va=fb;Ta=Aa;D=483;break b}else{qa=wb;fa=na;xa=Yb;q=xa>>2;continue}}if(0==(mb|0)){D=417;break}a[f+1]=Yb;a[q]=Ub;var zb=a[c+1];if(0==(zb|0)){Sa=Ub;ue=Yb;Va=fb;Ta=Aa;D=483;break b}else{qa=zb,fa=Yb,xa=Ub,q=xa>>2}}419==D?(Sa=a[q]=Ub,ue=na,Va=fb,Ta=Aa,D=483):400==D?(a[f+1]=Ub,Ya=Aa,me=fb,$a=je,La=Ub,pa=xa,D=420):402==D?(a[f+1]=Ub,Sa=xa,ue=Ub,Va=fb,Ta=Aa,D=483):417==D&&(a[q]=Ub,Ya=Aa,me=fb,$a=Yb,La=na,pa=Ub,D=420)}}while(0);do{if(420==D){if(0==($a|0)){Sa=pa,ue=La,Va=me,Ta=Ya,D=483}else{if(a[n]|=32768,p=($a+4|0)>>2,a[pa>>2]=a[p],l=($a|0)>>2,a[La+4>>2]=a[l],0!=(g&516|0)){var kc=$a;e=kc>>2}else{if(0!=(g&8|0)){var uc=S|0;a[p]=a[uc>>2];a[l]=0;a[uc>>2]=$a;var Db=La,Am=Ya,D=450}else{if(0!=(g&16|0)){var ne=S+4|0;a[l]=a[ne>>2];a[p]=0;a[ne>>2]=$a;var Kc=La,rc=Ya,D=457}else{if(0!=(g&4098|0)){Wa=$a;U=La;D=463;break a}if(0!=(g&2049|0)){if(0!=(a[a[i]+4>>2]&4|0)){kc=$a,e=kc>>2}else{a[p]=0;var Pf=S+4|0;a[l]=a[Pf>>2];a[Pf>>2]=$a;var Cc=La,tb=$a,Dc=Ya,D=490}}else{if(0==(g&32|0)){return C=0,h=S,C}if(0==(a[a[i]+4>>2]&4|0)){a[me+4>>2]=0;var Cb=S+4|0;a[me>>2]=a[Cb>>2];a[Cb>>2]=me;var Eb=a[z]+16|0;a[Eb>>2]=a[Eb>>2]+1|0}else{var Hb=a[y+4];if(0!=(Hb|0)){J[Hb](b,Ya,I)}if(0>(a[t]|0)){J[a[b+12>>2]](b,me,0,I)}}kc=$a;e=kc>>2}}}}}}}while(0);do{if(483==D){if(a[ue+4>>2]=0,a[Sa>>2]=0,0!=(g&8|0)){Db=ue,Am=Ta,D=450}else{if(0!=(g&16|0)){Kc=ue,rc=Ta,D=457}else{if(0!=(g&516|0)){var Yc=Ta,xc=ue;break a}if(0!=(g&2049|0)){Cc=ue,tb=0,Dc=Ta,D=490}else{if(0==(g&32|0)){Yc=0;xc=ue;break a}var Sb=a[z]+16|0;a[Sb>>2]=a[Sb>>2]+1|0;kc=Va;e=kc>>2}}}}}while(0);do{if(490==D){var Wc=I+12|0,ae=a[Wc>>2],Ib=0==(ae|0)?Dc:0==(g&1|0)?Dc:J[ae](b,Dc,I);if(0==(Ib|0)){var Qa=tb}else{if(-1<(K|0)){Qa=Ib+K|0}else{var Mb=J[a[b+12>>2]](b,0,12,I),Kd=Mb;if(0!=(Mb|0)){a[Mb+8>>2]=Ib}else{if(0!=(a[Wc>>2]|0)){var Sc=a[y+4];if(0!=(Sc|0)&&0!=(g&1|0)){J[Sc](b,Ib,I)}}}Qa=Kd}}if(0==(Qa|0)){Yc=Ib;xc=Cc;break a}var bd=a[z]+16|0,Vc=a[bd>>2];-1<(Vc|0)&&(a[bd>>2]=Vc+1|0);kc=Qa;e=kc>>2}else{if(450==D){var cd=S+4|0,Zc=a[cd>>2];if(0==(Zc|0)){Yc=Am;xc=Db;break a}var nc=Zc+4|0,Oc=a[nc>>2];b:do{if(0==(Oc|0)){var Lc=Zc,dd=a[Zc>>2]}else{for(var Sd=Zc,id=nc,Xc=Oc;;){var bf=Xc|0;a[id>>2]=a[bf>>2];a[bf>>2]=Sd;var $c=Xc+4|0,Pb=a[$c>>2];if(0==(Pb|0)){Lc=Xc;dd=Sd;break b}else{Sd=Xc,id=$c,Xc=Pb}}}}while(0);a[cd>>2]=dd;kc=Lc;e=kc>>2}else{if(457==D){var Re=S|0,ad=a[Re>>2];if(0==(ad|0)){Yc=rc;xc=Kc;break a}var Xb=ad|0,Tc=a[Xb>>2];b:do{if(0==(Tc|0)){var Ke=ad,fc=a[ad+4>>2]}else{for(var Ge=ad,Ie=Xb,Uc=Tc;;){var wd=Uc+4|0;a[Ie>>2]=a[wd>>2];a[wd>>2]=Ge;var Zb=Uc|0,xd=a[Zb>>2];if(0==(xd|0)){Ke=Uc;fc=Ge;break b}else{Ge=Uc,Ie=Zb,Uc=xd}}}}while(0);a[Re>>2]=fc;kc=Ke;e=kc>>2}}}}while(0);a[e+1]=a[F];a[e]=a[F+1];b:do{if(0==(a[a[i]+4>>2]&8|0)){var rd=kc}else{if(0==(g&516|0)){rd=kc}else{for(var yd=0>(K|0),Bm=0>(T|0),Cd=(yd?a[e+2]:kc+ -K|0)+A|0,md=Bm?a[Cd>>2]:Cd,sd=0==(M|0),tt=1>(T|0),ed=-K|0,zd=kc;;){var ke=zd+4|0,Je=a[ke>>2];if(0==(Je|0)){rd=zd;break b}var jd=Je|0,Ld=a[jd>>2];c:do{if(0==(Ld|0)){var Ad=Je,$b=jd}else{for(var ec=Je,Hd=jd,Id=Ld;;){var hc=Id+4|0;a[Hd>>2]=a[hc>>2];a[hc>>2]=ec;var lc=Id|0,Md=a[lc>>2];if(0==(Md|0)){Ad=Id;$b=lc;break c}else{ec=Id,Hd=lc,Id=Md}}}}while(0);var nd=ke|0;a[nd>>2]=Ad;var gc=(yd?a[Ad+8>>2]:Ad+ed|0)+A|0,ic=Bm?a[gc>>2]:gc;if(0!=((sd?tt?$(md,ic):Ne(md,ic,T):J[M](b,md,ic,I))|0)){rd=zd;break b}a[nd>>2]=a[$b>>2];a[$b>>2]=zd;zd=Ad}}}}while(0);a[a[z]+4>>2]=rd;C=0>(K|0)?a[rd+8>>2]:rd+ -K|0;h=S;return C}}while(0);if(463==D){var Qb=0>(K|0)?a[Wa+8>>2]:Wa+ -K|0,Lb=a[y+4];if(0!=(Lb|0)&&0!=(g&2|0)){J[Lb](b,Qb,I)}if(0>(a[t]|0)){J[a[b+12>>2]](b,Wa,0,I)}var ac=a[z]+16|0,jc=a[ac>>2]-1|0;a[ac>>2]=jc;0>(jc|0)&&(a[a[z]+16>>2]=-1);Yc=Qb;xc=U}for(var tc=xc;;){var bc=tc+4|0,dc=a[bc>>2];if(0==(dc|0)){break}else{tc=dc}}a[bc>>2]=a[F];a[a[z]+4>>2]=a[F+1];C=0!=(g&2|0)?Yc:0;h=S;return C}function Of(b){var s;s=(b+8|0)>>2;var b=a[s],g=b|0,e=a[g>>2];if(0!=(e&4096|0)){if(b=a[b+4>>2],a[g>>2]=e&-4097,e=a[s],g=a[e>>2],0==(g&3|0)){e=e+4|0,0==(g&12|0)?(a[e>>2]=0,a[a[s]+8>>2]=b|0):a[e>>2]=b}else{if(a[e+4>>2]=0,s=a[s],g=a[s+8>>2],e=a[s+12>>2],s=(e<<2)+g|0,0<(e|0)){for(;!(e=a[g>>2],0!=(e|0)&&(a[g>>2]=b,b=e|0,e=a[b>>2],a[b>>2]=0,b=e),g=g+4|0,g>>>0>=s>>>0);){}}}}}function Fh(b,s){for(var g=b|0,e=b+32|0,l=J[a[g>>2]](b,0,128);0!=(l|0);){var p=a[e>>2],c=J[a[g>>2]](b,l,8);if(0>(J[s](0==(p|0)?b:p,l,0)|0)){break}else{l=c}}}function zg(b,s,g){var e,l=s>>2,p=h;h=h+8|0;var c=p+4;a[l]=0;var d=b+16|0,f=a[a[a[d>>2]+20>>2]>>2]>>>4&1;a[g>>2]=f;var q=a[1345513];a:do{if(0==(q|0)){e=f}else{var m=tb(b|0,a[q+8>>2]),w=n[m];if(0==w<<24>>24){e=f}else{var i=5382548;for(e=i>>2;;){var v=a[e];if(0==(v|0)){e=f;break a}if(w<<24>>24==n[v]<<24>>24&&0==($(m,v)|0)){break}i=i+12|0;e=i>>2}a[l]=a[e+1];e=a[e+2];a[g>>2]=e}}}while(0);f=a[1345520];0!=(f|0)&1==(e|0)&&(f=tb(b|0,a[f+8>>2]),0!=n[f]<<24>>24&&Cm(f,g));f=a[1345518];0!=(f|0)&&1==(a[l]|0)&&(f=tb(b|0,a[f+8>>2]),0!=n[f]<<24>>24&&Cm(f,s));0!=n[b+161|0]<<24>>24&&(b=a[b+12>>2],zg(bj(a[b+20>>2],b,a[d>>2]),p,c),a[g>>2]|=a[p>>2],a[l]|=a[c>>2]);h=p}function Cm(b,s){var g=h;h=h+4|0;a[s>>2]=0;if(0!=n[b]<<24>>24){for(var e=b,l=0;;){a[g>>2]=0;var c=e,e=g,d=Wb,f=h;h=h+4|0;d=f>>2;a[d]=0;var r=cj(c,5382388,f);if((r|0)==(c|0)){for(;!(r=cj(c,5382500,f),(c|0)==(r|0));){c=r}c=cj(c,5382404,f)}else{c=r}r=a[d];0!=(r|0)&0==(r&7|0)&&(r|=1,a[d]=r);d=r;r=a[e>>2];d|=r;a[e>>2]=d;h=f;e=c;a[s>>2]|=a[g>>2]<<(l<<3);l=l+1|0;if(!(0!=n[e]<<24>>24&4>(l|0))){break}}}h=g}function Se(u,s){for(var g=0,e=s&7,l=5382276;;){if(0==(a[l+12>>2]|0)){var c=0;break}if((e|0)==(a[l>>2]|0)){g=574;break}else{l=l+16|0}}574==g&&(c=l+4|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]));e=s>>>8&7;for(l=5382276;;){if(0==(a[l+12>>2]|0)){var d=c;break}if((e|0)==(a[l>>2]|0)){g=578;break}else{l=l+16|0}}578==g&&(d=l+4|0,d=c+(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]));c=s>>>16&7;for(e=5382276;;){if(0==(a[e+12>>2]|0)){var k=d;break}if((c|0)==(a[e>>2]|0)){g=582;break}else{e=e+16|0}}582==g&&(k=e+4|0,k=d+(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]));d=s>>>24&7;for(c=5382276;;){if(0==(a[c+12>>2]|0)){var r=k,g=588;break}if((d|0)==(a[c>>2]|0)){break}else{c=c+16|0}}if(588==g){return g=10*r,k=a[1345519],k=lc(u|0,k,1,0),g*k}g=c+4|0;r=k+(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);g=10*r;k=a[1345519];k=lc(u|0,k,1,0);return g*k}function Gh(u,s,g,e,l,c){var d,k,r,q,m=h;h=h+80|0;d=m+8;var w=m+72,u=Se(u,c),u=u*u;f[b>>3]=u;a[w>>2]=a[b>>2];a[w+4>>2]=a[b+4>>2];a[l+12>>2]=c;c=e+3|0;k=(c<<4)+s|0;l=(l+32|0)>>2;r=k>>2;a[l]=a[r];a[l+1]=a[r+1];a[l+2]=a[r+2];a[l+3]=a[r+3];(e|0)>(g|0)&&(g=(e<<4)+s|0,k|=0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),k=(e<<4)+s+8|0,c=(c<<4)+s+8|0,c=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])-(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),e=g*g+c*c<u?e-3|0:e);q=(d+48|0)>>2;r=((e<<4)+s|0)>>2;a[q]=a[r];a[q+1]=a[r+1];a[q+2]=a[r+2];a[q+3]=a[r+3];k=(d+32|0)>>2;g=((e+1<<4)+s|0)>>2;a[k]=a[g];a[k+1]=a[g+1];a[k+2]=a[g+2];a[k+3]=a[g+3];c=(d+16|0)>>2;u=((e+2<<4)+s|0)>>2;a[c]=a[u];a[c+1]=a[u+1];a[c+2]=a[u+2];a[c+3]=a[u+3];var i=d|0;d>>=2;a[d]=a[l];a[d+1]=a[l+1];a[d+2]=a[l+2];a[d+3]=a[l+3];a[m>>2]=i;a[m+4>>2]=w;Ag(m,308,i,1);a[r]=a[q];a[r+1]=a[q+1];a[r+2]=a[q+2];a[r+3]=a[q+3];a[g]=a[k];a[g+1]=a[k+1];a[g+2]=a[k+2];a[g+3]=a[k+3];a[u]=a[c];a[u+1]=a[c+1];a[u+2]=a[c+2];a[u+3]=a[c+3];s=((e+3<<4)+s|0)>>2;a[s]=a[d];a[s+1]=a[d+1];a[s+2]=a[d+2];a[s+3]=a[d+3];h=m;return e}function Hh(u,s,g,e,l,c){var d,k,r,q=h;h=h+80|0;var m=q+8,w=q+72,u=Se(u,c),u=u*u;f[b>>3]=u;a[w>>2]=a[b>>2];a[w+4>>2]=a[b+4>>2];a[l+8>>2]=c;c=(g<<4)+s|0;l=(l+16|0)>>2;d=c>>2;a[l]=a[d];a[l+1]=a[d+1];a[l+2]=a[d+2];a[l+3]=a[d+3];if((e|0)>(g|0)){c|=0;e=g+3|0;d=(e<<4)+s|0;c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])-(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);d=(g<<4)+s+8|0;k=(e<<4)+s+8|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);var i=c*c+d*d<u?e:g}else{i=g}r=m>>2;k=((i+3<<4)+s|0)>>2;a[r]=a[k];a[r+1]=a[k+1];a[r+2]=a[k+2];a[r+3]=a[k+3];d=(m+16|0)>>2;c=((i+2<<4)+s|0)>>2;a[d]=a[c];a[d+1]=a[c+1];a[d+2]=a[c+2];a[d+3]=a[c+3];e=(m+32|0)>>2;u=((i+1<<4)+s|0)>>2;a[e]=a[u];a[e+1]=a[u+1];a[e+2]=a[u+2];a[e+3]=a[u+3];var n=m+48|0,g=n>>2;a[g]=a[l];a[g+1]=a[l+1];a[g+2]=a[l+2];a[g+3]=a[l+3];a[q>>2]=n;a[q+4>>2]=w;Ag(q,308,m|0,0);s=((i<<4)+s|0)>>2;a[s]=a[g];a[s+1]=a[g+1];a[s+2]=a[g+2];a[s+3]=a[g+3];a[u]=a[e];a[u+1]=a[e+1];a[u+2]=a[e+2];a[u+3]=a[e+3];a[c]=a[d];a[c+1]=a[d+1];a[c+2]=a[d+2];a[c+3]=a[d+3];a[k]=a[r];a[k+1]=a[r+1];a[k+2]=a[r+2];a[k+3]=a[r+3];h=q;return i}function Dm(u,s,g,e,l,c,d){var k,r,h,m,w,i,n;r=0!=(c|0);n=0==(d|0);if(r&(n^1)&(e|0)==(g|0)){h=(e<<4)+s|0;var g=h|0,t=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),g=(e<<4)+s+8|0;i=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);r=e+3|0;k=(r<<4)+s|0;n=(k|0)>>2;g=(a[b>>2]=a[n],a[b+4>>2]=a[n+1],f[b>>3]);w=((r<<4)+s+8|0)>>2;r=(a[b>>2]=a[w],a[b+4>>2]=a[w+1],f[b>>3]);m=Se(u,c);var u=Se(u,d),y=t-g,z=i-r,y=Math.sqrt(y*y+z*z);u+m<y?(z=u,u=m):z=u=y/3;i==r?(t<g?(m=t+u,y=i,u=g-z):(m=t-u,y=i,u=g+z),t=i):i<r?(m=t,y=i+u,u=t,t=r-z):(m=t,y=i-u,u=t,t=r+z);z=e+1|0;i=(z<<4)+s|0;var B=i|0;f[b>>3]=m;a[B>>2]=a[b>>2];a[B+4>>2]=a[b+4>>2];m=(z<<4)+s+8|0;f[b>>3]=y;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];h>>=2;i>>=2;a[h]=a[i];a[h+1]=a[i+1];a[h+2]=a[i+2];a[h+3]=a[i+3];f[b>>3]=u;a[n]=a[b>>2];a[n+1]=a[b+4>>2];f[b>>3]=t;a[w]=a[b>>2];a[w+1]=a[b+4>>2];s=((e+2<<4)+s|0)>>2;e=k>>2;a[s]=a[e];a[s+1]=a[e+1];a[s+2]=a[e+2];a[s+3]=a[e+3];a[l+12>>2]=d;s=l+32|0;d=l+40|0;a[l+8>>2]=c;f[b>>3]=g;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];f[b>>3]=r;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2]}else{if(!n){y=Se(u,d);k=(e<<4)+s|0;t=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);k=(e<<4)+s+8|0;i=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);n=e+3|0;h=(n<<4)+s|0;w=(h|0)>>2;k=(a[b>>2]=a[w],a[b+4>>2]=a[w+1],f[b>>3]);m=((n<<4)+s+8|0)>>2;n=(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3]);z=t-k;B=i-n;z=.9*Math.sqrt(z*z+B*B);y=y<z?y:z;i==n?(z=t<k?k-y:k+y,B=i):i<n?(z=t,B=n-y):(z=t,B=n+y);var F=e+1|0,D=(F<<4)+s|0;f[b>>3]=t;a[D>>2]=a[b>>2];a[D+4>>2]=a[b+4>>2];t=(F<<4)+s+8|0;f[b>>3]=i;a[t>>2]=a[b>>2];a[t+4>>2]=a[b+4>>2];f[b>>3]=z;a[w]=a[b>>2];a[w+1]=a[b+4>>2];f[b>>3]=B;a[m]=a[b>>2];a[m+1]=a[b+4>>2];e=((e+2<<4)+s|0)>>2;h>>=2;a[e]=a[h];a[e+1]=a[h+1];a[e+2]=a[h+2];a[e+3]=a[h+3];a[l+12>>2]=d;d=l+32|0;f[b>>3]=k;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];d=l+40|0;f[b>>3]=n;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];k=y}r&&(h=Se(u,c),r=(g<<4)+s|0,d=r|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),e=(g<<4)+s+8|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),n=g+3|0,u=(n<<4)+s|0,u=(a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3]),n=(n<<4)+s+8|0,n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),w=d-u,t=e-n,w=.9*Math.sqrt(w*w+t*t),e==n?(h=d<u?d+(h<w?h:w):d-k,w=e):e<n?(h=d,w=e+k):(h=d,w=e-k),t=g+1|0,k=(t<<4)+s|0,i=k|0,f[b>>3]=h,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],h=(t<<4)+s+8|0,f[b>>3]=w,a[h>>2]=a[b>>2],a[h+4>>2]=a[b+4>>2],r>>=2,k>>=2,a[r]=a[k],a[r+1]=a[k+1],a[r+2]=a[k+2],a[r+3]=a[k+3],g=g+2|0,r=(g<<4)+s|0,f[b>>3]=u,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],s=(g<<4)+s+8|0,f[b>>3]=n,a[s>>2]=a[b>>2],a[s+4>>2]=a[b+4>>2],a[l+8>>2]=c,c=l+16|0,f[b>>3]=d,a[c>>2]=a[b>>2],a[c+4>>2]=a[b+4>>2],l=l+24|0,f[b>>3]=e,a[l>>2]=a[b>>2],a[l+4>>2]=a[b+4>>2])}}function mf(u,s,g,e,l){var e=e-s,l=l-g,c=10/(Math.sqrt(e*e+l*l)+1e-4),d=(e+(0<=e?1e-4:-1e-4))*c,k=(l+(0<=l?1e-4:-1e-4))*c,c=.5*d,r=.5*k,l=s-r,e=g-c,s=r+s,c=c+g,h=l+d,r=e+k,m=s+d,k=c+k,g=h>m?h:m,g=s>g?s:g,d=r>k?r:k,d=c>d?c:d,h=h<m?h:m,s=s<h?s:h,r=r<k?r:k,c=c<r?c:r,r=u|0;f[b>>3]=l<s?l:s;a[r>>2]=a[b>>2];a[r+4>>2]=a[b+4>>2];s=u+8|0;f[b>>3]=e<c?e:c;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];s=u+16|0;f[b>>3]=l>g?l:g;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];u=u+24|0;f[b>>3]=e>d?e:d;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}function nf(u,s,g,e,l,c,d,k,r){var q,m=0,w=h;h=h+16|0;var i=u+16|0;q=(a[i>>2]+12|0)>>2;var n=a[q];a[q]=s;Dd(a[i>>2],a[u+60>>2],a[a[u>>2]+296>>2]);for(var s=l-g,l=c-e,i=10/(Math.sqrt(s*s+l*l)+1e-4),c=(s+(0<=s?1e-4:-1e-4))*i,s=(l+(0<=l?1e-4:-1e-4))*i,l=w|0,i=w+8|0,t=0,y=g,z=e;;){if(4<=(t|0)){m=638;break}var B=r>>(t<<3)&255;if(0==(B|0)){m=637;break}for(var e=w,g=u,F=c,D=s,S=d,Gb=k,A=0,I=B&7,Z=5382276;;){var T=a[Z>>2];if(0==(T|0)){var K=y,M=z;break}if((I|0)==(T|0)){A=642;break}else{Z=Z+16|0}}642==A&&(K=Z+4|0,K=(a[b>>2]=a[K>>2],a[b+4>>2]=a[K+4>>2],f[b>>3])*S,M=K*F,D*=K,J[a[Z+12>>2]](g,y,z,M,D,S,Gb,B),K=M+y,M=D+z);g=e|0;f[b>>3]=K;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];e=e+8|0;f[b>>3]=M;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];t=t+1|0;y=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);z=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3])}637==m?(a[q]=n,h=w):638==m&&(a[q]=n,h=w)}function Em(u,s,g,e,l,c,d,k){var r,q,c=h;h=h+80|0;var d=4<d?.0875*d:.35,m=d*-l,d=d*e,e=s+e,l=g+l;r=c+64|0;q=(r|0)>>2;0==(k&16|0)?(f[b>>3]=e,a[q]=a[b>>2],a[q+1]=a[b+4>>2],q=c+72|0,f[b>>3]=l,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=c>>2,r>>=2,a[q]=a[r],a[q+1]=a[r+1],a[q+2]=a[r+2],a[q+3]=a[r+3],r=c+16|0,f[b>>3]=e-m,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],r=c+24|0,f[b>>3]=l-d,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],r=c+32|0,f[b>>3]=s,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],s=c+40|0,f[b>>3]=g,a[s>>2]=a[b>>2],a[s+4>>2]=a[b+4>>2],g=c+48|0,f[b>>3]=e+m,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=c+56|0,f[b>>3]=l+d,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2]):(f[b>>3]=s,a[q]=a[b>>2],a[q+1]=a[b+4>>2],q=c+72|0,f[b>>3]=g,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=c>>2,r>>=2,a[q]=a[r],a[q+1]=a[r+1],a[q+2]=a[r+2],a[q+3]=a[r+3],r=c+16|0,f[b>>3]=s-m,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],r=c+24|0,f[b>>3]=g-d,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],r=c+32|0,f[b>>3]=e,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],e=c+40|0,f[b>>3]=l,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],l=c+48|0,f[b>>3]=m+s,a[l>>2]=a[b>>2],a[l+4>>2]=a[b+4>>2],s=c+56|0,f[b>>3]=d+g,a[s>>2]=a[b>>2],a[s+4>>2]=a[b+4>>2]);0!=(k&32|0)?tc(u,c|0,3,(k>>>3&1^1)&255):0==(k&64|0)?tc(u,c+16|0,3,(k>>>3&1^1)&255):tc(u,c+32|0,3,(k>>>3&1^1)&255);h=c}function Fm(u,s,g,e,l,c,d,k){var r,q,m,w=h;h=h+144|0;var i=4*c,n=k&16,i=i>=d|0==(n|0)?.45:.45*(d/i);if(1<d){if(0==(n|0)){var t=c=0}else{c=.05*(d-1)/c,t=n}}else{c=0,t=n}d=-l;n=i*d;i*=e;d*=c;c*=e;r=s+e;q=g+l;var y=.5*e+s,e=.5*l+g,l=w|0,z=w+128|0;m=(z|0)>>2;0==(t|0)?(f[b>>3]=r,a[m]=a[b>>2],a[m+1]=a[b+4>>2],r=w+136|0,f[b>>3]=q,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],q=w>>2,r=z>>2,a[q]=a[r],a[q+1]=a[r+1],a[q+2]=a[r+2],a[q+3]=a[r+3],q=w+16|0,f[b>>3]=s-n,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=w+24|0,f[b>>3]=g-i,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=w+32|0,f[b>>3]=y-d,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=w+40|0,f[b>>3]=e-c,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=w+48|0,f[b>>3]=s,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=w+56|0,f[b>>3]=g,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=w+64|0,f[b>>3]=s,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=w+72|0,f[b>>3]=g,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=w+80|0,f[b>>3]=s,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=w+88|0,f[b>>3]=g,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=w+96|0,f[b>>3]=y+d,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],d=w+104|0,f[b>>3]=e+c,a[d>>2]=a[b>>2],a[d+4>>2]=a[b+4>>2],c=w+112|0,f[b>>3]=n+s,a[c>>2]=a[b>>2],a[c+4>>2]=a[b+4>>2],n=w+120|0,f[b>>3]=i+g):(f[b>>3]=s,a[m]=a[b>>2],a[m+1]=a[b+4>>2],s=w+136|0,f[b>>3]=g,a[s>>2]=a[b>>2],a[s+4>>2]=a[b+4>>2],g=w>>2,s=z>>2,a[g]=a[s],a[g+1]=a[s+1],a[g+2]=a[s+2],a[g+3]=a[s+3],g=w+16|0,f[b>>3]=r-n,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=w+24|0,f[b>>3]=q-i,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=w+32|0,f[b>>3]=y-d,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=w+40|0,f[b>>3]=e-c,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=w+48|0,f[b>>3]=r-d,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=w+56|0,f[b>>3]=q-c,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=w+64|0,f[b>>3]=r,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=w+72|0,f[b>>3]=q,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=w+80|0,f[b>>3]=r+d,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=w+88|0,f[b>>3]=q+c,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=w+96|0,f[b>>3]=y+d,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],d=w+104|0,f[b>>3]=e+c,a[d>>2]=a[b>>2],a[d+4>>2]=a[b+4>>2],c=w+112|0,f[b>>3]=r+n,a[c>>2]=a[b>>2],a[c+4>>2]=a[b+4>>2],n=w+120|0,f[b>>3]=q+i);a[n>>2]=a[b>>2];a[n+4>>2]=a[b+4>>2];0!=(k&32|0)?tc(u,l,6,1):0==(k&64|0)?tc(u,l,9,1):tc(u,w+48|0,6,1);h=w}function Gm(u,s,g,e,l,c,d,k){var r,q,m,w,i,n=h;h=h+64|0;var t=s+e,y=g+l,z=.2*e+s,B=.2*l+g,F=.6*e+s,D=.6*l+g,S=n|0;i=(n|0)>>2;f[b>>3]=z-l;a[i]=a[b>>2];a[i+1]=a[b+4>>2];w=(n+8|0)>>2;f[b>>3]=B+e;a[w]=a[b>>2];a[w+1]=a[b+4>>2];m=(n+16|0)>>2;f[b>>3]=z+l;a[m]=a[b>>2];a[m+1]=a[b+4>>2];q=(n+24|0)>>2;f[b>>3]=B-e;a[q]=a[b>>2];a[q+1]=a[b+4>>2];r=(n+32|0)>>2;f[b>>3]=F+l;a[r]=a[b>>2];a[r+1]=a[b+4>>2];d=(n+40|0)>>2;f[b>>3]=D-e;a[d]=a[b>>2];a[d+1]=a[b+4>>2];c=(n+48|0)>>2;f[b>>3]=F-l;a[c]=a[b>>2];a[c+1]=a[b+4>>2];l=(n+56|0)>>2;f[b>>3]=D+e;a[l]=a[b>>2];a[l+1]=a[b+4>>2];0==(k&32|0)?0!=(k&64|0)&&(f[b>>3]=z,a[m]=a[b>>2],a[m+1]=a[b+4>>2],f[b>>3]=B,a[q]=a[b>>2],a[q+1]=a[b+4>>2],f[b>>3]=F,a[r]=a[b>>2],a[r+1]=a[b+4>>2],f[b>>3]=D,a[d]=a[b>>2],a[d+1]=a[b+4>>2]):(f[b>>3]=z,a[i]=a[b>>2],a[i+1]=a[b+4>>2],f[b>>3]=B,a[w]=a[b>>2],a[w+1]=a[b+4>>2],f[b>>3]=F,a[c]=a[b>>2],a[c+1]=a[b+4>>2],f[b>>3]=D,a[l]=a[b>>2],a[l+1]=a[b+4>>2]);tc(u,S,4,1);f[b>>3]=s;a[i]=a[b>>2];a[i+1]=a[b+4>>2];f[b>>3]=g;a[w]=a[b>>2];a[w+1]=a[b+4>>2];f[b>>3]=t;a[m]=a[b>>2];a[m+1]=a[b+4>>2];f[b>>3]=y;a[q]=a[b>>2];a[q+1]=a[b+4>>2];td(u,S,2);h=n}function Hm(u,s,g,e,l,c,d,k){var r,q,m,w,i,n,t,c=h;h=h+64|0;r=-.4*l;var d=.4*e,y=.8*e+s,z=.8*l+g,e=s+e,B=g+l,F=c|0;t=(c|0)>>2;f[b>>3]=r+s;a[t]=a[b>>2];a[t+1]=a[b+4>>2];n=(c+8|0)>>2;f[b>>3]=d+g;a[n]=a[b>>2];a[n+1]=a[b+4>>2];i=(c+16|0)>>2;f[b>>3]=s-r;a[i]=a[b>>2];a[i+1]=a[b+4>>2];w=(c+24|0)>>2;f[b>>3]=g-d;a[w]=a[b>>2];a[w+1]=a[b+4>>2];m=(c+32|0)>>2;f[b>>3]=y-r;a[m]=a[b>>2];a[m+1]=a[b+4>>2];q=(c+40|0)>>2;f[b>>3]=z-d;a[q]=a[b>>2];a[q+1]=a[b+4>>2];l=(c+48|0)>>2;f[b>>3]=y+r;a[l]=a[b>>2];a[l+1]=a[b+4>>2];r=(c+56|0)>>2;f[b>>3]=z+d;a[r]=a[b>>2];a[r+1]=a[b+4>>2];0==(k&32|0)?0!=(k&64|0)&&(f[b>>3]=s,a[i]=a[b>>2],a[i+1]=a[b+4>>2],f[b>>3]=g,a[w]=a[b>>2],a[w+1]=a[b+4>>2],f[b>>3]=y,a[m]=a[b>>2],a[m+1]=a[b+4>>2],f[b>>3]=z,a[q]=a[b>>2],a[q+1]=a[b+4>>2]):(f[b>>3]=s,a[t]=a[b>>2],a[t+1]=a[b+4>>2],f[b>>3]=g,a[n]=a[b>>2],a[n+1]=a[b+4>>2],f[b>>3]=y,a[l]=a[b>>2],a[l+1]=a[b+4>>2],f[b>>3]=z,a[r]=a[b>>2],a[r+1]=a[b+4>>2]);tc(u,F,4,(k>>>3&1^1)&255);f[b>>3]=y;a[t]=a[b>>2];a[t+1]=a[b+4>>2];f[b>>3]=z;a[n]=a[b>>2];a[n+1]=a[b+4>>2];f[b>>3]=e;a[i]=a[b>>2];a[i+1]=a[b+4>>2];f[b>>3]=B;a[w]=a[b>>2];a[w+1]=a[b+4>>2];td(u,F,2);h=c}function Im(u,s,g,e,l,c,d,k){c=h;h=h+80|0;var r=-l/3,q=e/3,m=.5*e+s,w=.5*l+g,d=c|0,i=c+64|0,n=i|0;f[b>>3]=s+e;a[n>>2]=a[b>>2];a[n+4>>2]=a[b+4>>2];e=c+72|0;f[b>>3]=g+l;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];l=c>>2;e=i>>2;a[l]=a[e];a[l+1]=a[e+1];a[l+2]=a[e+2];a[l+3]=a[e+3];l=c+16|0;f[b>>3]=m+r;a[l>>2]=a[b>>2];a[l+4>>2]=a[b+4>>2];l=c+24|0;f[b>>3]=w+q;a[l>>2]=a[b>>2];a[l+4>>2]=a[b+4>>2];l=c+32|0;e=l|0;f[b>>3]=s;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];s=c+40|0;f[b>>3]=g;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];g=c+48|0;f[b>>3]=m-r;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];g=c+56|0;f[b>>3]=w-q;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];0!=(k&32|0)?tc(u,l,3,(k>>>3&1^1)&255):(g=(k>>>3&1^1)&255,0==(k&64|0)?tc(u,d,4,g):tc(u,d,3,g));h=c}function cj(b,s,g){for(var e=0;;){var l=a[s>>2];if(0==(l|0)){var c=b,e=708;break}var d=xa(l);if(0==(Pd(b,l,d)|0)){break}else{s=s+8|0}}if(708==e){return c}a[g>>2]|=a[s+4>>2];return b+d|0}function Bg(u){var s,g=h,e=da(244);s=e>>2;0==(e|0)&&aa(1,5327148,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));var l=u+16|0,u=a[l>>2];a[s]=u;a[l>>2]=e;if(0==(u|0)){a[s+22]=3,a[s+23]=0,s=e+96|0,f[b>>3]=1,a[s>>2]=a[b>>2],a[s+4>>2]=a[b+4>>2]}else{for(var l=(u+16|0)>>2,c=(e+16|0)>>2,d=l+9;l<d;l++,c++){a[c]=a[l]}l=(u+52|0)>>2;c=(e+52|0)>>2;for(d=l+9;l<d;l++,c++){a[c]=a[l]}a[s+22]=a[u+88>>2];a[s+23]=a[u+92>>2];s=u+96|0;s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]);u=e+96|0;f[b>>3]=s;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}h=g;return e}function Qf(b){var s=b+16|0,g=a[s>>2],b=g>>2;0==(g|0)&&ia(5378016,110,5379528,5335416);E(a[b+38]);E(a[b+37]);E(a[b+39]);E(a[b+40]);E(a[b+41]);E(a[b+42]);E(a[b+43]);E(a[b+44]);E(a[b+45]);E(a[b+46]);E(a[b+47]);E(a[b+48]);E(a[b+49]);E(a[b+53]);E(a[b+56]);E(a[b+55]);a[s>>2]=a[b];E(g)}function dj(b,s,g,e,l,c,d,f){var r=b>>2;0==(s&32768|0)|0==(g|0)||(a[r+33]=g);0==(s&65536|0)?g=0:(a[r+38]=Zb(d,f),0==(e|0)?g=0:0==n[e]<<24>>24?g=0:(a[r+37]=Zb(e,f),g=1));a:do{if(0==(s&4194304|0)){e=g}else{do{if(0!=(l|0)&&0!=n[l]<<24>>24){a[r+42]=Zb(l,f);b=b+200|0;a[b>>2]|=1;e=1;break a}}while(0);e=a[r+33];0==(e|0)?e=g:(a[r+42]=Hb(e),e=1)}}while(0);if(0==(s&8388608|0)|0==(c|0)||0==n[c]<<24>>24){return e}a[r+46]=Zb(c,f);return 1}function ej(b){var s=a[b+192>>2];-1<(s|0)?(s|0)<(a[b+160>>2]|0)?(s=a[b+196>>2],b=-1<(s|0)?(s|0)<(a[b+164>>2]|0):0):b=0:b=0;return b&1}function Ih(b,s,g){var e=h;h=h+32|0;var l=U(s,5378532);if(0!=(l|0)&&0!=n[l]<<24>>24){return h=e,l}l=a[s>>2]<<28>>28;if(1==(l|0)){var c=5329472,d=a[s+16>>2]}else{2==(l|0)?(c=5374900,d=a[s+20>>2]):3==(l|0)&&(c=5372324,d=a[a[s+36>>2]+16>>2])}if(0==(b|0)){b=(g+4|0)>>2,s=g+8|0}else{Cb(g,b);var l=g+4|0,b=l>>2,f=a[b],s=g+8|0;f>>>0<a[s>>2]>>>0||(qa(g,1),f=a[b]);a[b]=f+1|0;n[f]=95;b=l>>2}Cb(g,c);c=e|0;Pa(c,5362528,(i=h,h=h+4|0,a[i>>2]=d,i));Cb(g,c);d=a[b];d>>>0<a[s>>2]>>>0||(qa(g,1),d=a[b]);n[d]=0;g=a[g>>2];a[b]=g;h=e;return g}function Jh(b,s){var g,e,l,c,d=h;c=s>>2;s=h;h=h+32|0;a[s>>2]=a[c];a[s+4>>2]=a[c+1];a[s+8>>2]=a[c+2];a[s+12>>2]=a[c+3];a[s+16>>2]=a[c+4];a[s+20>>2]=a[c+5];a[s+24>>2]=a[c+6];a[s+28>>2]=a[c+7];g=a[b+16>>2];l=g>>2;c=a[b+148>>2];if(0!=(c&4259840|0)){var f=0!=(c&131072|0);e=g+204|0;f?(a[e>>2]=0,a[l+52]=2):(a[e>>2]=2,a[l+52]=4);e=g+212|0;E(a[e>>2]);l=da(a[l+52]<<4);g=l>>2;a[e>>2]=l;e=s>>2;a[g]=a[e];a[g+1]=a[e+1];a[g+2]=a[e+2];a[g+3]=a[e+3];e=(l+16|0)>>2;g=(s+16|0)>>2;a[e]=a[g];a[e+1]=a[g+1];a[e+2]=a[g+2];a[e+3]=a[g+3];0==(c&8192|0)&&Wd(b,l,l,2);f||Kh(l)}h=d}function Cg(u,s){var g,e,l,c,d=h;h=h+144|0;l=d+64;e=d+128;c=s|0;var k=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);c=(u+16|0)>>2;var r=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3]),q=k>r;if(!q&&(g=u|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),k>=g)){var m=s+8|0,w=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),m=u+24|0,m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]);if(w<=m){var i=u+8|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);if(w>=i&&(w=s+16|0,w=(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]),!(w>r|w<g)&&(w=s+24|0,w=(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]),!(w>m|w<i)&&(w=s+32|0,w=(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]),!(w>r|w<g)&&(w=s+40|0,w=(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]),!(w>m|w<i)&&(w=s+48|0,w=(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]),!(w>r|w<g)&&(g=s+56|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),!(g>m|g<i)))))))){h=d;return}}}if(0==(Jm(s)|0)){c=d|0,k=l|0,zc(e,s,.5,c,k),Cg(u,c),Cg(u,k)}else{l=(u+24|0)>>2;e=(u+8|0)>>2;g=(u|0)>>2;if(q){f[b>>3]=k,a[c]=a[b>>2],a[c+1]=a[b+4>>2]}else{if(k<(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])){f[b>>3]=k,a[g]=a[b>>2],a[g+1]=a[b+4>>2]}k=r}r=s+8|0;r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]);q=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]);if(r>q){f[b>>3]=r,a[l]=a[b>>2],a[l+1]=a[b+4>>2]}else{if(r<(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])){f[b>>3]=r,a[e]=a[b>>2],a[e+1]=a[b+4>>2]}r=q}q=s+16|0;q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);if(q>k){f[b>>3]=q,a[c]=a[b>>2],a[c+1]=a[b+4>>2],k=q}else{if(q<(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])){f[b>>3]=q,a[g]=a[b>>2],a[g+1]=a[b+4>>2]}}q=s+24|0;q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);if(q>r){f[b>>3]=q,a[l]=a[b>>2],a[l+1]=a[b+4>>2],r=q}else{if(q<(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])){f[b>>3]=q,a[e]=a[b>>2],a[e+1]=a[b+4>>2]}}q=s+32|0;q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);if(q>k){f[b>>3]=q,a[c]=a[b>>2],a[c+1]=a[b+4>>2],k=q}else{if(q<(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])){f[b>>3]=q,a[g]=a[b>>2],a[g+1]=a[b+4>>2]}}q=s+40|0;q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);if(q>r){f[b>>3]=q,a[l]=a[b>>2],a[l+1]=a[b+4>>2],r=q}else{if(q<(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])){f[b>>3]=q,a[e]=a[b>>2],a[e+1]=a[b+4>>2]}}q=s+48|0;q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);if(q>k){f[b>>3]=q,a[c]=a[b>>2],a[c+1]=a[b+4>>2]}else{if(q<(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])){f[b>>3]=q,a[g]=a[b>>2],a[g+1]=a[b+4>>2]}}c=s+56|0;c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);if(c>r){f[b>>3]=c,a[l]=a[b>>2],a[l+1]=a[b+4>>2]}else{if(c<(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])){f[b>>3]=c,a[e]=a[b>>2],a[e+1]=a[b+4>>2]}}}h=d}function Jm(u){var s=u|0,s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]),g=u+8|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),e=u+48|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),l=u+56|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),c=u+16|0,d=u+24|0,c=Km(s,g,e,l,(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])),d=u+32|0,u=u+40|0;return 4>c&4>Km(s,g,e,l,(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),(a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3]))&1}function fj(u,s){var g,e=u>>2;g=a[e+37];var l=u+348|0,c=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),l=u+424|0,d=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),l=c*d/72,k=u+480|0;f[b>>3]=l;a[k>>2]=a[b>>2];a[k+4>>2]=a[b+4>>2];var k=u+432|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),c=c*k/72,r=u+488|0;f[b>>3]=c;a[r>>2]=a[b>>2];a[r+4>>2]=a[b+4>>2];r=u+512|0;f[b>>3]=d/72;a[r>>2]=a[b>>2];a[r+4>>2]=a[b+4>>2];d=k/72;k=u+520|0;f[b>>3]=0==(g&4096|0)?d:-1*d;a[k>>2]=a[b>>2];a[k+4>>2]=a[b+4>>2];d=a[e+110]>>>0;0==(a[e+89]|0)?(k=u+360|0,f[b>>3]=d/l,a[k>>2]=a[b>>2],a[k+4>>2]=a[b+4>>2],l=u+368|0,f[b>>3]=(a[e+111]>>>0)/c,a[l>>2]=a[b>>2],a[l+4>>2]=a[b+4>>2]):(k=u+368|0,f[b>>3]=d/c,a[k>>2]=a[b>>2],a[k+4>>2]=a[b+4>>2],c=u+360|0,f[b>>3]=(a[e+111]>>>0)/l,a[c>>2]=a[b>>2],a[c+4>>2]=a[b+4>>2]);e=s|0;Dg(u,$b(e,Q(e,5330564),5338228));e=Bg(u)>>2;a[e+1]=0;a[e+2]=s;a[e+3]=0;gj(u,a[s+48>>2],s|0);l=a[u>>2];e=a[u+60>>2];if(0!=(e|0)){c=a[e+8>>2];if(0!=(c|0)){J[c](u)}c=U(s|0,5325800);if(0!=(c|0)&&0!=n[c]<<24>>24&&(l=l+300|0,hj(a[u+68>>2],c,l),e=a[e+92>>2],0!=(e|0))){J[e](u,l)}}0!=(g&2|0)&&Lm(u,s);g=s+20|0;e=ha(a[g>>2]);a:do{if(0!=(e|0)){for(l=e;;){if(n[l+132|0]=0,l=sa(a[g>>2],l),0==(l|0)){break a}}}}while(0);g=h;e=a[a[u>>2]+280>>2];l=u+152|0;a[l>>2]=e;1<(e|0)&&0==(a[u+148>>2]&64|0)&&(aa(0,5376076,(i=h,h=h+4|0,a[i>>2]=a[u+52>>2],i)),a[l>>2]=1);a[u+156>>2]=1;h=g;g=(u+152|0)>>2;l=a[g];e=u+156|0;if(0!=((a[e>>2]|0)<=(l|0)&1)<<24>>24){for(;;){1<(l|0)&&(l=a[u+60>>2],0!=(l|0)&&(l=a[l+16>>2],0!=(l|0)&&(c=a[u+156>>2],J[l](u,a[a[a[u>>2]+276>>2]+(c<<2)>>2],c,a[u+152>>2]))));l=u+168|0;c=u+192|0;d=a[l+4>>2];a[c>>2]=a[l>>2];a[c+4>>2]=d;a:do{if(0!=ej(u)<<24>>24){for(;;){if(Mm(u,s),Nm(u),0==ej(u)<<24>>24){break a}}}}while(0);if(1<(a[g]|0)&&(l=a[u+60>>2],0!=(l|0)&&(l=a[l+20>>2],0!=(l|0)))){J[l](u)}l=u+156|0;a[l>>2]=a[l>>2]+1|0;l=a[g];if(0==((a[e>>2]|0)<=(l|0)&1)<<24>>24){break}}}g=a[u+60>>2];if(0!=(g|0)&&(g=a[g+12>>2],0!=(g|0))){J[g](u)}g=a[u+76>>2];if(0!=(g|0)&&(g=a[g+4>>2],0!=(g|0))){J[g](u)}Om(u);Qf(u)}function Lm(b,s){Sb(b,5332120);var g=s|0,e=U(g,5325800);0!=(e|0)&&0!=n[e]<<24>>24&&Sb(b,e);g=U(g,5334160);0!=(g|0)&&0!=n[g]<<24>>24&&eb(b,g);Pm(b,s);var g=s+20|0,l=ha(a[g>>2]);if(0!=(l|0)){for(e=s+28|0;;){var c=l|0,d=U(c,5335528);0!=(d|0)&&0!=n[d]<<24>>24&&eb(b,d);d=U(c,5335284);0!=(d|0)&&0!=n[d]<<24>>24&&Sb(b,d);c=U(c,5334160);0!=(c|0)&&0!=n[c]<<24>>24&&eb(b,c);c=zb(s,l);a:do{if(0!=(c|0)){for(d=c;;){var f=d|0,r=U(f,5335528);do{if(0!=(r|0)&&0!=n[r]<<24>>24){if(0==(oc(r,58)|0)){eb(b,r)}else{var h=Hb(r),m=Jd(h,5331664,ud);b:do{if(0!=(m|0)){for(var w=m;;){if(0!=n[w]<<24>>24&&eb(b,w),w=Jd(0,5331664,ud),0==(w|0)){break b}}}}while(0);E(h)}}}while(0);f=U(f,5334160);0!=(f|0)&&0!=n[f]<<24>>24&&eb(b,f);d=Db(a[e>>2],d);if(0==(d|0)){break a}}}}while(0);l=sa(a[g>>2],l);if(0==(l|0)){break}}}}function Mm(b,s){var g,e,l,c=a[b+16>>2];l=c>>2;var d=a[b+148>>2],f=U(s|0,5356744);a[1315020]=f;Qm(b);f=a[b+60>>2];if(0!=(f|0)&&(f=a[f+24>>2],0!=(f|0))){J[f](b)}eb(b,5374748);Sb(b,5332120);if(0!=(d&4259840|0)&&!(0==(a[l+37]|0)&&0==(a[l+50]&1|0))){if(0==(d&655360|0)){var r=0,f=0}else{var r=d&131072,h=r>>>16^2,f=h+2|0;a[l+51]=h;h=da(f<<4);e=h>>2;g=(b+284|0)>>2;a[e]=a[g];a[e+1]=a[g+1];a[e+2]=a[g+2];a[e+3]=a[g+3];e=(h+16|0)>>2;g=(b+300|0)>>2;a[e]=a[g];a[e+1]=a[g+1];a[e+2]=a[g+2];a[e+3]=a[g+3];0==(r|0)&&Kh(h);r=h}0==(d&8192|0)&&Wd(b,r,r,f);a[l+53]=r;a[l+52]=f}0!=(d&32768|0)&&(f=a[s+48>>2],0!=(f|0)&&(a[l+33]=a[f>>2]));f=0!=(d&4|0);f||(c=c+148|0,0==(a[c>>2]|0)&&0==(a[l+50]&1|0)||(Jh(b,b+252|0),Mc(b,a[c>>2],a[l+42],a[l+46],a[l+38])));if(1==(a[b+152>>2]|0)){c=0;h=U(s|0,5325800);0==(h|0)?(r=1,h=5348884):(g=0==n[h]<<24>>24,r=g&1,h=g?5348884:h);g=a[b+148>>2];e=116==n[h]<<24>>24;if(0==(g&256|0)){var m=e?0==($(h,5348676)|0)?5348884:h:h,c=1948}else{e?0!=($(h,5348676)|0)&&(m=h,c=1948):(m=h,c=1948)}1948==c&&0==(g&33554432|0)|0==(r|0)&&(Sb(b,m),eb(b,m),of(b,b+252|0,1));m=a[a[s+44>>2]+88>>2];0!=(m|0)&&Rm(b,m)}m=a[s+48>>2];0!=(m|0)&&Te(b,4,m);if(!f){if(0==(a[l+37]|0)&&0==(a[l+50]&1|0)){ij(b,s,d);Sm(b);return}de(b)}ij(b,s,d);Sm(b)}function Nm(b){var s,g=b>>2,e=h;h=h+16|0;var l=e+8;s=b+192|0;var c=s|0,d=b+196|0,f=a[d>>2],r=a[g+47];a[e>>2]=a[g+46]+a[c>>2]|0;a[e+4>>2]=r+f|0;s>>=2;r=a[e>>2];f=a[e+4>>2];a[s]=r;a[s+1]=f;0==ej(b)<<24>>24&&(b=a[g+45],0==(b|0)?(c=a[g+43],a[d>>2]=c,d=r):(d=a[g+42],a[c>>2]=d,c=f),a[l>>2]=a[g+44]+d|0,a[l+4>>2]=b+c|0,g=a[l+4>>2],a[s]=a[l>>2],a[s+1]=g);h=e}function Eg(u,s,g){var e,l,c,d,k,r=h;h=h+68|0;k=r>>2;var q=r+4,m=s+208|0;if(1<=(a[m>>2]|0)){var w=s+212|0,i=0!=(g&4|0),v=u+16|0,t=0==(g&8|0),y=q|0;d=q>>2;for(var z=q+32|0,s=z>>2,z=z|0,B=q+16|0,F=q+8|0,D=q+24|0,S=q|0,Gb=q+48|0,A=q+40|0,q=q+56|0,I=u+60|0,Z=1;;){var T=a[a[w>>2]+(Z<<2)>>2];do{if(0!=ut(u,T)<<24>>24){i&&Eg(u,T,g);c=u;l=T;var K=Wb,K=Bg(c)>>2;a[K+1]=1;a[K+2]=l;a[K+3]=1;gj(c,a[l+48>>2],l|0);l=a[c+60>>2];if(0!=(l|0)&&(l=a[l+32>>2],0!=(l|0))){J[l](c)}l=a[v>>2];c=l>>2;l=(l+148|0)>>2;K=0==(a[l]|0)?0!=(a[c+50]&1|0):1;e=T|0;var M=U(e,5356744);a[1315020]=M;i|K^1||(Jh(u,T+52|0),Mc(u,a[l],a[c+42],a[c+46],a[c+38]));a[k]=0;var M=r,L=0,C=U(T|0,5334992);a:do{if(0==(C|0)){var yb=0,E=0}else{if(0==n[C]<<24>>24){E=yb=0}else{pf(C);for(var R=5249092,Y=0;;){for(;;){var he=a[R>>2];if(0==(he|0)){yb=Y;E=5249092;break a}if(0==($(he,5362648)|0)){L=1026;break}if(0==($(he,5337692)|0)){var Rb=R;break}else{R=R+4|0}}if(1026==L){L=0,R=R+4|0,Y|=1}else{for(;;){var he=Rb+4|0,H=a[he>>2];a[Rb>>2]=H;if(0==(H|0)){break}else{Rb=he}}Y|=2}}}}}while(0);a[M>>2]=yb;M=E;0==(M|0)?M=0:(Dd(a[v>>2],a[I>>2],M),M=a[k]&1);L=ca[T+148|0];0==(L&1|0)?0!=(L&2|0)?(L=na(e,0,5336384),C=1,Y=na(e,0,5336016)):0!=(L&8|0)?(L=na(e,0,5335712),C=1,Y=na(e,0,5335408)):0!=(L&4|0)?(L=na(e,0,5335120),C=1,Y=na(e,0,5334856)):(L=U(e,5335528),C=0==(L|0)?0:0==n[L]<<24>>24?0:L,L=U(e,5346500),L=0==(L|0)?C:0==n[L]<<24>>24?C:L,Y=U(e,5335284),Y=0==(Y|0)?C:0==n[Y]<<24>>24?C:Y,0!=(M|0)?C=M:(M=U(e,5325800),0==(M|0)?C=0:(R=0==n[M]<<24>>24,C=R&1^1,Y=R?Y:M))):(L=na(e,0,5336884),C=1,Y=na(e,0,5336656));M=0==(L|0)?5374748:L;L=0==(Y|0)?5332120:Y;Y=a[1345480];0!=(Y|0)&&(R=tb(e,a[Y+8>>2]),0!=(R|0)&&0!=n[R]<<24>>24&&jj(u,lc(e,Y,1,0)));Y=a[k];0==(Y&2|0)?(eb(u,M),Sb(u,L),0!=(ve(e,a[1345479],1)|0)?of(u,T+52|0,C&255):0!=(C|0)&&((L|0)!=(M|0)&&eb(u,L),of(u,T+52|0,C&255))):0!=(ve(e,a[1345479],1)|C|0)&&(e=(T+52|0)>>2,a[d]=a[e],a[d+1]=a[e+1],a[d+2]=a[e+2],a[d+3]=a[e+3],e=(T+68|0)>>2,a[s]=a[e],a[s+1]=a[e+1],a[s+2]=a[e+2],a[s+3]=a[e+3],e=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3]),f[b>>3]=e,a[B>>2]=a[b>>2],a[B+4>>2]=a[b+4>>2],e=(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]),f[b>>3]=e,a[D>>2]=a[b>>2],a[D+4>>2]=a[b+4>>2],e=(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3]),f[b>>3]=e,a[Gb>>2]=a[b>>2],a[Gb+4>>2]=a[b+4>>2],e=(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]),f[b>>3]=e,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],Rf(u,L,M,y,4,Y,Y&1));e=a[T+48>>2];0!=(e|0)&&Te(u,5,e);K&&(i&&(Jh(u,T+52|0),Mc(u,a[l],a[c+42],a[c+46],a[c+38])),de(u));a:do{if(!t&&(c=T,l=T+20|0,e=ha(a[l>>2]),0!=(e|0))){for(K=T+28|0;;){qf(u,e);M=zb(c,e);b:do{if(0!=(M|0)){for(L=M;;){if(Sf(u,L),L=Db(a[K>>2],L),0==(L|0)){break b}}}}while(0);e=sa(a[l>>2],e);if(0==(e|0)){break a}}}}while(0);c=u;l=a[c+60>>2];if(0!=(l|0)&&(l=a[l+36>>2],0!=(l|0))){J[l](c)}Qf(c);i||Eg(u,T,g)}}while(0);Z=Z+1|0;if((Z|0)>(a[m>>2]|0)){break}}}h=r}function ut(b,s){var g=0;if(2>(a[b+152>>2]|0)){var e;return 1}var l=s|0,l=$b(l,Q(l,5331176),5338228);if(0!=Tf(b,l)<<24>>24){return 1}if(0!=n[l]<<24>>24){return 0}for(var l=s+20|0,c=ha(a[l>>2]);;){if(0==(c|0)){e=0;g=1015;break}if(0!=Tm(b,s,c)<<24>>24){e=1;g=1017;break}c=sa(a[l>>2],c)}if(1015==g||1017==g){return e}}function qf(b,s){var g=a[b>>2],e=s+24|0,l;if(l=0!=(a[e>>2]|0)){if(l=0!=Tm(b,a[s+20>>2],s)<<24>>24){var c,d;l=h;d=(b+252|0)>>2;c=h;h=h+32|0;a[c>>2]=a[d];a[c+4>>2]=a[d+1];a[c+8>>2]=a[d+2];a[c+12>>2]=a[d+3];a[c+16>>2]=a[d+4];a[c+20>>2]=a[d+5];a[c+24>>2]=a[d+6];a[c+28>>2]=a[d+7];c=rf(s+64|0,c)&255;h=l;l=0!=c<<24>>24}}if(l&&(l=s+132|0,g=a[g+28>>2],(n[l]<<24>>24|0)!=(g|0))){n[l]=g&255;Dg(b,a[s+12>>2]);g=s|0;l=$b(g,a[1345368],5338228);0!=n[l]<<24>>24&&Dg(b,l);g=$b(g,a[1345345],5338228);a:do{if(0!=n[g]<<24>>24){pf(g);for(l=5249092;;){g=l+4|0;l=a[l>>2];if(0==(l|0)){break a}if(105!=n[l]<<24>>24){l=g}else{if(0==($(l,5365092)|0)){break}else{l=g}}}return}}while(0);Um(b,s);J[a[a[a[e>>2]+4>>2]+20>>2]](b,s);e=a[s+124>>2];0!=(e|0)&&Te(b,10,e);e=a[b+60>>2];if(0!=(e|0)&&(e=a[e+60>>2],0!=(e|0))){J[e](b)}Qf(b)}}function Sf(b,s){var g,e,l=0,c=h;e=(b+252|0)>>2;g=h;h=h+32|0;a[g>>2]=a[e];a[g+4>>2]=a[e+1];a[g+8>>2]=a[e+2];a[g+12>>2]=a[e+3];a[g+16>>2]=a[e+4];a[g+20>>2]=a[e+5];a[g+24>>2]=a[e+6];a[g+28>>2]=a[e+7];e=a[s+24>>2];if(0==(e|0)){l=1361}else{if(0==(rf(e+8|0,g)|0)){l=1361}else{var d=1}}1361==l&&(l=a[s+108>>2],0!=(l|0)&&0!=kj(l,g)<<24>>24?d=1:(l=a[s+120>>2],d=0!=(l|0)&&0!=kj(l,g)<<24>>24?1:0));h=c;if(0!=d<<24>>24){g=(s+12|0)>>2;a:do{if(2>(a[b+152>>2]|0)){var f=1}else{if(c=$b(s|0,a[1345500],5338228),0!=Tf(b,c)<<24>>24){f=1}else{if(0!=n[c]<<24>>24){f=0}else{c=s+16|0;l=s+12|0;for(d=0;;){if(2<=(d|0)){f=0;break a}e=$b(a[(1>(d|0)?c:l)>>2]|0,a[1345356],5338228);if(0==n[e]<<24>>24){f=1;break a}if(0==Tf(b,e)<<24>>24){d=d+1|0}else{f=1;break a}}}}}}while(0);if(0!=f<<24>>24){c=s+16|0;f=wb(xa(a[a[c>>2]+12>>2])+xa(a[a[g]+12>>2])+3|0);ee(f,a[a[c>>2]+12>>2]);c=f+xa(f)|0;0==(a[a[a[g]+20>>2]>>2]&16|0)?(n[c]=n[5332132],n[c+1|0]=n[5332133],n[c+2|0]=n[5332134]):(n[c]=n[5360020],n[c+1|0]=n[5360021],n[c+2|0]=n[5360022]);fe(f,a[a[g]+12>>2]);Dg(b,f);E(f);f=s|0;g=$b(f,a[1345516],5338228);0!=n[g]<<24>>24&&Dg(b,g);f=$b(f,a[1345494],5338228);a:do{if(0==n[f]<<24>>24){g=0}else{pf(f);for(g=5249092;;){f=g+4|0;g=a[g>>2];if(0==(g|0)){g=5249092;break a}if(105!=n[g]<<24>>24){g=f}else{if(0==($(g,5365092)|0)){break}else{g=f}}}return}}while(0);Vm(b,s,g);Wm(b,s,g);Xm(b)}}}function pf(b){var s,g,e,l=0,c=h;h=h+148|0;var d=c+128,f=c+132;e=f>>2;n[5249348]||(ac(5246844,128,5250684),n[5249348]=1);ac(f,128,c|0);a[d>>2]=b;g=(f+4|0)>>2;var r=f+8|0;s=(f|0)>>2;var q=0,m=0;a:for(;;){for(var w=q;;){for(var q=d,x=f,v=Wb,t=a[q>>2];;){v=n[t];if(0==v<<24>>24){var y=0;break}if(0==(Ze(v<<24>>24)|0)&&(v=n[t],44!=v<<24>>24)){y=v;break}t=t+1|0}var z=y<<24>>24;b:do{if(0==(z|0)){var B=0,F=t}else{if(40==(z|0)|41==(z|0)){B=z,F=t+1|0}else{if(0!=Ym(z)<<24>>24){B=1,F=t}else{for(var v=(x+4|0)>>2,D=x+8|0,S=t,Gb=y;;){var A=a[v];A>>>0<a[D>>2]>>>0||(qa(x,1),A=a[v]);a[v]=A+1|0;n[A]=Gb;S=S+1|0;Gb=n[S];if(0!=Ym(Gb<<24>>24)<<24>>24){B=1;F=S;break b}}}}}}while(0);a[q>>2]=F;q=B;if(40==(q|0)){if(0==w<<24>>24){w=1}else{l=1076;break a}}else{if(41==(q|0)){if(0==w<<24>>24){l=1078;break a}else{w=0}}else{if(0==(q|0)){l=1090;break a}else{break}}}}if(0==w<<24>>24){if(63==(m|0)){l=1081;break}q=a[1311712];q>>>0<a[1311713]>>>0||(qa(5246844,1),q=a[1311712]);a[1311712]=q+1|0;n[q]=0;a[(m<<2)+5249092>>2]=a[1311712];m=m+1|0}q=a[g];q>>>0<a[r>>2]>>>0||(qa(f,1),q=a[g]);n[q]=0;q=a[s];a[g]=q;Cb(5246844,q);q=a[1311712];q>>>0<a[1311713]>>>0||(qa(5246844,1),q=a[1311712]);a[1311712]=q+1|0;n[q]=0;q=w}1078==l?(aa(1,5344432,(i=h,h=h+4|0,a[i>>2]=b,i)),a[1312273]=0,Xb(a[s],a[e+3]),h=c):1081==l?(aa(0,5344088,(i=h,h=h+4|0,a[i>>2]=b,i)),a[1312336]=0,Xb(a[s],a[e+3]),h=c):1076==l?(aa(1,5344724,(i=h,h=h+4|0,a[i>>2]=b,i)),a[1312273]=0,Xb(a[s],a[e+3]),h=c):1090==l&&(0!=w<<24>>24?(aa(1,5343688,(i=h,h=h+4|0,a[i>>2]=b,i)),a[1312273]=0,Xb(a[s],a[e+3])):(a[(m<<2)+5249092>>2]=0,Xb(a[s],a[e+3]),b=a[1311712],b>>>0<a[1311713]>>>0||(qa(5246844,1),b=a[1311712]),n[b]=0,a[1311712]=a[1311711]),h=c)}function Ue(b){var s=a[1313330];0!=(b|0)?(a[1313330]=s+1|0,0==(s|0)&&(a[1313329]=Hb(Ff()),Ff())):0<(s|0)&&(b=s-1|0,a[1313330]=b,0==(b|0)&&(Ff(),E(a[1313329])))}function Wi(u,s){var g,e,l,c,d=0,k=h;c=(s+44|0)>>2;if(0==(a[c]|0)){return aa(1,5342880,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),h=k,-1}l=s+20|0;var r=ha(a[l>>2]);if(0!=(r|0)){for(;;){var q=s,m=r,w=m+32|0,w=(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]);e=m+104|0;e=w-(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);var x=m+64|0;f[b>>3]=e;a[x>>2]=a[b>>2];a[x+4>>2]=a[b+4>>2];e=m+40|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);var x=m+96|0,x=.5*(a[b>>2]=a[x>>2],a[b+4>>2]=a[x+4>>2],f[b>>3]),v=m+72|0;f[b>>3]=e-x;a[v>>2]=a[b>>2];a[v+4>>2]=a[b+4>>2];v=m+112|0;w+=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]);v=m+80|0;f[b>>3]=w;a[v>>2]=a[b>>2];a[v+4>>2]=a[b+4>>2];w=m+88|0;f[b>>3]=e+x;a[w>>2]=a[b>>2];a[w+4>>2]=a[b+4>>2];m=zb(q,m);if(0!=(m|0)){for(q=q+28|0;!(w=a[m+24>>2],0!=(w|0)&&Zm(w),m=Db(a[q>>2],m),0==(m|0));){}}r=sa(a[l>>2],r);if(0==(r|0)){break}}}$m(u,s);l=u+272|0;r=a[l>>2];0!=(r|0)&&(E(r),a[l>>2]=0);l=(u+276|0)>>2;r=a[l];0!=(r|0)&&(E(r),a[l]=0);r=U(s|0,5339420);0==(r|0)?(a[l]=0,a[u+280>>2]=1):a[u+280>>2]=an(u,s,r);a[u+104>>2]=5252648;a[u+108>>2]=14;Ue(1);r=u+56|0;q=u|0;m=u+156|0;l=(u+164|0)>>2;w=u+28|0;e=a[u+120>>2];x=a[u+124>>2]=e;for(e=x>>2;;){if(0==(x|0)){d=1153;break}d=a[r>>2];0==(d|0)?(a[e+5]=0,a[e+6]=0):(a[e+5]=a[d+8>>2],a[e+6]=a[a[r>>2]+12>>2]);v=x+12|0;a[v>>2]=q;a[e+7]=a[m>>2];if(0==(a[c]|0)){d=1134;break}g=(x+52|0)>>2;d=Dh(x,a[g]);a[e+14]=d;if(999==(d|0)){d=1136;break}else{if(24==(d|0)){d=x+148|0,a[d>>2]|=520}else{if(21==(d|0)){d=x+148|0,a[d>>2]|=1}else{var d=x+148|0,t=a,y=d>>2,z;a:{z=U(s|0,5340316);if(0!=(z|0)){var B=n[z];if(110==B<<24>>24){if(0==($(z+1|0,5339984)|0)){z=1;break a}}else{if(101==B<<24>>24&&0==($(z+1|0,5339724)|0)){z=16;break a}}}z=0}t[y]=z|a[d>>2]}}}t=a[l];a:do{if(0!=(t|0)){do{if(0!=(a[t+148>>2]&32|0)&&0==($(a[g],a[t+52>>2])|0)){d=a[1313331];if(0==(d|0)){d=1147;break a}a[d+8>>2]=x;a[e+9]=a[d+36>>2];d=1149;break a}}while(0);Xi(t);a[l]=0;a[w>>2]=0}a[1313331]=0;d=1147}while(0);if(1147==d){d=0;t=x;y=a[t+60>>2];if(0==(bn(t)|0)){if(0!=(y|0)&&(y=a[y>>2],0!=(y|0))){J[y](t)}t=0}else{t=1}0==(t|0)&&(a[l]=x,d=1149)}1149==d&&(d=0,a[e+2]=0,a[e+26]=5253280,t=x,y=z=Wb,z=a[t>>2],0!=n[z+264|0]<<24>>24?(y=(t+236|0)>>2,z=(z+188|0)>>2,a[y]=a[z],a[y+1]=a[z+1],a[y+2]=a[z+2],a[y+3]=a[z+3]):(300==(a[t+56>>2]|0)?(y=a[t+68>>2]+4|0,y=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),z=t+244|0,f[b>>3]=y,a[z>>2]=a[b>>2],a[z+4>>2]=a[b+4>>2],t=t+236|0,f[b>>3]=y):(y=t+244|0,f[b>>3]=4,a[y>>2]=a[b>>2],a[y+4>>2]=a[b+4>>2],t=t+236|0,f[b>>3]=4),a[t>>2]=a[b>>2],a[t+4>>2]=a[b+4>>2]),t=x,y=z=z=y=y=Wb,z=a[t>>2],0!=n[z+265|0]<<24>>24?(y=(t+408|0)>>2,z=(z+172|0)>>2,a[y]=a[z],a[y+1]=a[z+1],a[y+2]=a[z+2],a[y+3]=a[z+3]):(y=a[t+56>>2],300==(y|0)?(z=(t+408|0)>>2,y=(a[t+84>>2]+4|0)>>2,a[z]=a[y],a[z+1]=a[y+1],a[z+2]=a[y+2],a[z+3]=a[y+3]):2==(y|0)|3==(y|0)|4==(y|0)|22==(y|0)|21==(y|0)|30==(y|0)?(y=t+416|0,f[b>>3]=36,a[y>>2]=a[b>>2],a[y+4>>2]=a[b+4>>2],t=t+408|0,f[b>>3]=36,a[t>>2]=a[b>>2],a[t+4>>2]=a[b+4>>2]):(y=(t+408|0)>>2,a[y]=0,a[y+1]=0,a[y+2]=0,a[y+3]=0)),y=a[c]+24|0,t=x,y=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),z=B=B=z=Wb,B=a[a[t>>2]+164>>2],0!=y?(z=t+432|0,f[b>>3]=y,a[z>>2]=a[b>>2],a[z+4>>2]=a[b+4>>2],t=t+424|0,f[b>>3]=y,a[t>>2]=a[b>>2],a[t+4>>2]=a[b+4>>2]):0!=(B|0)&&0!=n[B+124|0]<<24>>24?(z=(t+424|0)>>2,B=(B+108|0)>>2,a[z]=a[B],a[z+1]=a[B+1],a[z+2]=a[B+2],a[z+3]=a[B+3]):(y=t+424|0,300==(a[t+56>>2]|0)?(B=y>>2,z=(a[t+84>>2]+36|0)>>2,a[B]=a[z],a[B+1]=a[z+1],a[B+2]=a[z+2],a[B+3]=a[z+3]):(t=t+432|0,f[b>>3]=96,a[t>>2]=a[b>>2],a[t+4>>2]=a[b+4>>2],t=y|0,f[b>>3]=96,a[t>>2]=a[b>>2],a[t+4>>2]=a[b+4>>2])),cn(x,s),dn(x,s),0==(a[e+37]&128|0)&&(a[a[v>>2]+20>>2]=0,fj(x,s)),a[1313331]=x);e=Wb;e=(u+124|0)>>2;x=a[e];v=a[x+4>>2];0!=(v|0)&&(t=v+52|0,0==(a[t>>2]|0)&&(a[t>>2]=a[x+52>>2]));x=a[e]=v;e=x>>2}if(1136==d){return aa(1,5342324,(i=h,h=h+4|0,a[i>>2]=a[g],i)),Ue(0),h=k,-1}if(1153==d){return Ue(0),h=k,0}if(1134==d){return aa(1,5342612,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Ue(0),h=k,-1}}function $m(u,s){var g,e,l,c,d,k,r=u>>2,q=h;h=h+16|0;d=q>>2;l=q+8;e=l>>2;a[r+32]=s;c=u+265|0;n[c]=0;g=s|0;k=U(g,5332848);if(0!=(k|0)){var m=gd(k,5332588,(i=h,h=h+8|0,a[i>>2]=q,a[i+4>>2]=l,i));if(0<(m|0)){var w=72*(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);k=(u+180|0)>>2;f[b>>3]=w;a[k]=a[b>>2];a[k+1]=a[b+4>>2];var x=u+172|0;f[b>>3]=w;a[x>>2]=a[b>>2];a[x+4>>2]=a[b+4>>2];1<(m|0)&&(m=72*(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),f[b>>3]=m,a[k]=a[b>>2],a[k+1]=a[b+4>>2]);n[c]=1}}c=u+264|0;n[c]=0;k=U(g,5337916);0!=(k|0)&&(l=gd(k,5332588,(i=h,h=h+8|0,a[i>>2]=q,a[i+4>>2]=l,i)),0<(l|0)&&(k=72*(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),d=(u+196|0)>>2,f[b>>3]=k,a[d]=a[b>>2],a[d+1]=a[b+4>>2],m=u+188|0,f[b>>3]=k,a[m>>2]=a[b>>2],a[m+4>>2]=a[b+4>>2],1<(l|0)&&(e=72*(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),f[b>>3]=e,a[d]=a[b>>2],a[d+1]=a[b+4>>2]),n[c]=1));d=u+266|0;n[d]=0;e=(s+44|0)>>2;c=(u+204|0)>>2;l=(a[e]+48|0)>>2;a[c]=a[l];a[c+1]=a[l+1];a[c+2]=a[l+2];a[c+3]=a[l+3];l=a[e];c=l+48|0;.001<(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])?(c=l+56|0,.001<(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])?(n[d]=1,e=a[e]):e=l):e=l;a[r+65]=0==n[e+81|0]<<24>>24?0:90;e=u+168|0;a[e>>2]=5337616;g=U(g,5337344);0!=(g|0)&&0!=n[g]<<24>>24&&(a[e>>2]=g);e=(u+228|0)>>2;g=(s+52|0)>>2;a[e]=a[g];a[e+1]=a[g+1];a[e+2]=a[g+2];a[e+3]=a[g+3];a[e+4]=a[g+4];a[e+5]=a[g+5];a[e+6]=a[g+6];a[e+7]=a[g+7];g=s+32|0;a[1345479]=Q(a[g>>2]|0,5333004);a[1345480]=Q(a[g>>2]|0,5333672);g=s+40|0;a[r+71]=na(a[a[g>>2]>>2]|0,a[1345362],5377304);g=lc(a[a[g>>2]>>2]|0,a[1345361],14,1);e=u+288|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];a[r+74]=5258e3;a[r+40]=a[s+12>>2];h=q}function Fg(u,s,g){var e=u|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];u=u+8|0;f[b>>3]=s;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}function Lh(b,s,g){g=g<<24>>24;76==(g|0)?(s=1,g=0):82==(g|0)?(a[s+168>>2]=a[s+160>>2]-1|0,s=-1,g=0):84==(g|0)?(a[s+172>>2]=a[s+164>>2]-1|0,s=0,g=-1):66==(g|0)?(s=0,g=1):g=s=0;a[b>>2]=s;a[b+4>>2]=g}function Mh(b,s,g){a[b>>2]=g;a[b+4>>2]=s}function cn(u,s){var g,e,l,c,d,k=h;h=h+40|0;d=k>>2;var r=k+8;c=r>>2;var q=k+16;l=q>>2;var m=k+24;g=m>>2;var w=k+32;e=w>>2;var x=a[u>>2],v=x+244|0,v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),t=x+252|0,t=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),y=x+228|0,y=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),z=x+236|0,z=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3]),B=u+236|0,F=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),B=y-F,D=u+204|0;f[b>>3]=B;a[D>>2]=a[b>>2];a[D+4>>2]=a[b+4>>2];var D=u+244|0,S=(a[b>>2]=a[D>>2],a[b+4>>2]=a[D+4>>2],f[b>>3]),D=z-S,Gb=u+212|0;f[b>>3]=D;a[Gb>>2]=a[b>>2];a[Gb+4>>2]=a[b+4>>2];F=v+F;Gb=u+220|0;f[b>>3]=F;a[Gb>>2]=a[b>>2];a[Gb+4>>2]=a[b+4>>2];S=t+S;Gb=u+228|0;f[b>>3]=S;a[Gb>>2]=a[b>>2];a[Gb+4>>2]=a[b+4>>2];B=F-B;D=S-D;f[b>>3]=1;a[l]=a[b>>2];a[l+1]=a[b+4>>2];F=a[s+44>>2];S=F+64|0;S=(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3]);.001<S?(Gb=F+72|0,Gb=(a[b>>2]=a[Gb>>2],a[b+4>>2]=a[Gb+4>>2],f[b>>3]),.001<Gb?!(S<B|Gb<D)&&!(0!=n[F+80|0]<<24>>24&S>B&Gb>D)?F=1:(F=S/B,S=Gb/D,F=F<S?F:S,f[b>>3]=F,a[l]=a[b>>2],a[l+1]=a[b+4>>2]):F=1):F=1;v=.5*(y+v);f[b>>3]=v;a[g]=a[b>>2];a[g+1]=a[b+4>>2];t=.5*(z+t);f[b>>3]=t;a[e]=a[b>>2];a[e+1]=a[b+4>>2];a[u+356>>2]=a[x+260>>2];x=B*F;f[b>>3]=x;a[d]=a[b>>2];a[d+1]=a[b+4>>2];y=D*F;f[b>>3]=y;a[c]=a[b>>2];a[c+1]=a[b+4>>2];z=U(s|0,5341576);0==(z|0)?(e=t,g=(u+360|0)>>2,f[b>>3]=x,a[g]=a[b>>2],a[g+1]=a[b+4>>2],g=(u+368|0)>>2,f[b>>3]=y,a[g]=a[b>>2],a[g+1]=a[b+4>>2],g=(u+348|0)>>2,f[b>>3]=F,a[g]=a[b>>2],a[g+1]=a[b+4>>2],g=(u+332|0)>>2,f[b>>3]=v):(x=wb(xa(z)+1|0),v=wb(xa(z)+1|0),4==(gd(z,5341236,(i=h,h=h+16|0,a[i>>2]=k,a[i+4>>2]=r,a[i+8>>2]=q,a[i+12>>2]=x,i))|0)?(r=Uf(a[s+32>>2],x),0!=(r|0)&&(r=r+24|0,q=r+8|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),f[b>>3]=q,a[g]=a[b>>2],a[g+1]=a[b+4>>2],r=r+16|0,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),f[b>>3]=r,a[e]=a[b>>2],a[e+1]=a[b+4>>2])):4!=(gd(z,5340880,(i=h,h=h+20|0,a[i>>2]=k,a[i+4>>2]=r,a[i+8>>2]=q,a[i+12>>2]=x,a[i+16>>2]=v,i))|0)?gd(z,5340636,(i=h,h=h+20|0,a[i>>2]=k,a[i+4>>2]=r,a[i+8>>2]=q,a[i+12>>2]=m,a[i+16>>2]=w,i)):(r=Uf(a[s+32>>2],x),0!=(r|0)&&(r=r+24|0,q=r+8|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),f[b>>3]=q,a[g]=a[b>>2],a[g+1]=a[b+4>>2],r=r+16|0,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),f[b>>3]=r,a[e]=a[b>>2],a[e+1]=a[b+4>>2])),E(x),E(v),d=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),c=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3]),r=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]),l=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]),e=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),g=(u+360|0)>>2,f[b>>3]=d,a[g]=a[b>>2],a[g+1]=a[b+4>>2],g=(u+368|0)>>2,f[b>>3]=c,a[g]=a[b>>2],a[g+1]=a[b+4>>2],g=(u+348|0)>>2,f[b>>3]=r,a[g]=a[b>>2],a[g+1]=a[b+4>>2],g=(u+332|0)>>2,f[b>>3]=l);a[g]=a[b>>2];a[g+1]=a[b+4>>2];g=u+340|0;g>>=2;f[b>>3]=e;a[g]=a[b>>2];a[g+1]=a[b+4>>2];h=k}function dn(u,s){var g,e,l,c,d,k,r,q=u>>2,m=0,w=h;h=h+128|0;var x=w+16,v=w+24,t=w+32,y=w+40,z=w+48,B=w+64,F=w+80,D=w+96,S=w+112,Gb=w+120,A=a[q],I=u+360|0,Z=(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3]),C=u+368|0,K=(a[b>>2]=a[C>>2],a[b+4>>2]=a[C+4>>2],f[b>>3]);r=(u+356|0)>>2;if(0==(a[r]|0)){var M=Z,L=K}else{Fg(w,Z,K);var E=w|0,yb=w+8|0,M=(a[b>>2]=a[E>>2],a[b+4>>2]=a[E+4>>2],f[b>>3]),L=(a[b>>2]=a[yb>>2],a[b+4>>2]=a[yb+4>>2],f[b>>3])}var J=u+408|0,R=(a[b>>2]=a[J>>2],a[b+4>>2]=a[J+4>>2],f[b>>3]),Y=u+416|0,he=(a[b>>2]=a[Y>>2],a[b+4>>2]=a[Y+4>>2],f[b>>3]);if(0==n[A+266|0]<<24>>24){m=1271}else{if(0==(a[q+37]&32|0)){m=1271}else{var Rb=A+204|0,H=(a[b>>2]=a[Rb>>2],a[b+4>>2]=a[Rb+4>>2],f[b>>3])-2*R,ea=A+212|0,wa=(a[b>>2]=a[ea>>2],a[b+4>>2]=a[ea+4>>2],f[b>>3])-2*he;if(1e-4>H){var Fb=a[q+40]=1}else{var V=M/H&-1,W=u+160|0;a[W>>2]=V;if(1e-4<M-(V|0)*H){var X=V+1|0,Fb=a[W>>2]=X}else{Fb=V}}if(1e-4>wa){var ba=a[q+41]=1}else{var ma=L/wa&-1,ib=u+164|0;a[ib>>2]=ma;if(1e-4<L-(ma|0)*wa){var G=ma+1|0,ba=a[ib>>2]=G}else{ba=ma}}a[q+50]=Math.a(ba,Fb);var mc=H,O=wa,ga=M<H?M:H,Tb=L<wa?L:wa}}if(1271==m){if(0==(a[q+17]|0)){var ie=0,ua=0}else{var Da=a[q+21],Ja=Da+20|0,Ab=(a[b>>2]=a[Ja>>2],a[b+4>>2]=a[Ja+4>>2],f[b>>3])-2*R,ra=0>Ab?0:Ab,P=Da+28|0,ya=(a[b>>2]=a[P>>2],a[b+4>>2]=a[P+4>>2],f[b>>3])-2*he;0>ya?(ie=ra,ua=0):(ie=ra,ua=ya)}a[q+50]=1;a[q+41]=1;a[q+40]=1;var ja=ie<M?M:ie;ua<L?(mc=ja,O=L):(mc=ja,O=ua);ga=M;Tb=L}k=(u+424|0)>>2;var la=(mc+2*R)*(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3])/72;a[q+110]=(0>la?la-.5:la+.5)&-1;d=(u+432|0)>>2;var va=(O+2*he)*(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3])/72;a[q+111]=(0>va?va-.5:va+.5)&-1;var oa=u+176|0;c=(A+168|0)>>2;l=(u+168|0)>>2;a[l]=0;a[l+1]=0;a[l+2]=0;a[l+3]=0;a[l+4]=0;a[l+5]=0;Lh(x,u,n[a[c]]);var ka=x|0;e=ka>>2;var Ea=x+4|0;g=Ea>>2;var Ka=a[g],Na=oa|0;a[Na>>2]=a[e];var Ba=oa+4|0;a[Ba>>2]=Ka;Lh(v,u,n[a[c]+1|0]);var Wa=u+184|0,U=a[v>>2],Rd=a[v+4>>2];a[Wa>>2]=U;a[Wa+4>>2]=Rd;var Ra=U+a[oa>>2]|0;if(1==((-1<(Ra|0)?Ra:-Ra|0)|0)){var bb=Rd+a[q+45]|0;if(1!=((-1<(bb|0)?bb:-bb|0)|0)){m=1284}}else{m=1284}if(1284==m){Lh(t,u,66);var Xa=a[t+4>>2];a[oa>>2]=a[t>>2];a[oa+4>>2]=Xa;Lh(y,u,76);var Sa=a[y+4>>2],ka=Wa|0;e=ka>>2;a[e]=a[y>>2];Ea=Wa+4|0;g=Ea>>2;a[g]=Sa;aa(0,5341920,(i=h,h=h+4|0,a[i>>2]=a[c],i))}if(0==n[a[s+44>>2]+82|0]<<24>>24){var N=0,Va=0}else{var Ta=mc>ga?.5*(mc-ga):0;O>Tb?(N=Ta,Va=.5*(O-Tb)):(N=Ta,Va=0)}if(0==(a[r]|0)){var Aa=ga,fb=Tb,Ca=R,Ya=he,$a=N,La=Va}else{Fg(z,ga,Tb);var pa=z|0,Ga=(a[b>>2]=a[pa>>2],a[b+4>>2]=a[pa+4>>2],f[b>>3]),Fa=z+8|0,da=(a[b>>2]=a[Fa>>2],a[b+4>>2]=a[Fa+4>>2],f[b>>3]);Fg(B,mc,O);Fg(F,R,he);var nb=F|0,jb=(a[b>>2]=a[nb>>2],a[b+4>>2]=a[nb+4>>2],f[b>>3]),cb=F+8|0,Q=(a[b>>2]=a[cb>>2],a[b+4>>2]=a[cb+4>>2],f[b>>3]);Fg(D,N,Va);var kb=D|0,Kb=D+8|0,Aa=Ga,fb=da,Ca=jb,Ya=Q,$a=(a[b>>2]=a[kb>>2],a[b+4>>2]=a[kb+4>>2],f[b>>3]),La=(a[b>>2]=a[Kb>>2],a[b+4>>2]=a[Kb+4>>2],f[b>>3])}var Ma=Ca+$a,ld=u+376|0;f[b>>3]=Ma;a[ld>>2]=a[b>>2];a[ld+4>>2]=a[b+4>>2];var lb=Ya+La,rb=u+384|0;f[b>>3]=lb;a[rb>>2]=a[b>>2];a[rb+4>>2]=a[b+4>>2];var ab=Ma+Aa,db=u+392|0;f[b>>3]=ab;a[db>>2]=a[b>>2];a[db+4>>2]=a[b+4>>2];var ob=lb+fb,pb=u+400|0;f[b>>3]=ob;a[pb>>2]=a[b>>2];a[pb+4>>2]=a[b+4>>2];var ub=u+348|0,gb=(a[b>>2]=a[ub>>2],a[b+4>>2]=a[ub+4>>2],f[b>>3]),sb=u+316|0;f[b>>3]=Aa/gb;a[sb>>2]=a[b>>2];a[sb+4>>2]=a[b+4>>2];var Ia=u+324|0;f[b>>3]=fb/gb;a[Ia>>2]=a[b>>2];a[Ia+4>>2]=a[b+4>>2];var vb=(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3]),Ua=Ma*vb/72,$=(0>Ua?Ua-.5:Ua+.5)&-1,ca=u+448|0;a[ca>>2]=$;var qb=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),Bb=lb*qb/72,ia=(0>Bb?Bb-.5:Bb+.5)&-1;a[q+113]=ia;var xb=ab*vb/72,za=u+456|0,Nb=za|0;a[Nb>>2]=(0>xb?xb-.5:xb+.5)&-1;var Jb=ob*qb/72,zm=u+460|0;a[zm>>2]=(0>Jb?Jb-.5:Jb+.5)&-1;if(0!=(a[r]|0)){Mh(S,$,ia);var ha=a[S+4>>2];a[ca>>2]=a[S>>2];a[ca+4>>2]=ha;Mh(Gb,a[Nb>>2],a[zm>>2]);ka=Gb|0;e=ka>>2;Ea=Gb+4|0;g=Ea>>2;var Ic=a[g],Na=za|0;a[Na>>2]=a[e];Ba=za+4|0;a[Ba>>2]=Ic}h=w}function an(b,s,g){var e=U(s|0,5339088),s=(b+268|0)>>2;a[s]=0==(e|0)?5338732:e;g=Hb(g);a[b+272>>2]=g;e=Jd(g,a[s],ud);if(0==(e|0)){return 0}for(var b=(b+276|0)>>2,l=g=0;;){var c=g+1|0;if((c|0)>(l|0)){var l=l+128|0,d=a[b],d=0==(d|0)?Za(l<<2):Oa(d,l<<2);a[b]=d}else{d=a[b]}a[d+(c<<2)>>2]=e;e=Jd(0,a[s],ud);if(0==(e|0)){break}else{g=c}}if(0==(c|0)){return 0}s=Oa(a[b],(c<<2)+8|0);a[b]=s;a[s>>2]=0;a[a[b]+(g+2<<2)>>2]=0;return c}function Ym(a){return 40==(a|0)|41==(a|0)|44==(a|0)|0==(a|0)?1:0}function Zm(u){var s,g,e,l,c,d,k,r=h;h=h+128|0;var q=r+32,m=r+64,w=r+96;k=(u+4|0)>>2;0<(a[k]|0)||ia(5378016,3408,5379748,5335604);var i=u|0,n=a[i>>2];d=n>>2;var t=a[d],y=a[d+1],z=a[d+2],B=a[d+3],F=n+16|0,D=(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]),S=n+24|0,Gb=(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3]),A=n+32|0,I=(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]),Z=n+40|0,C=(a[b>>2]=a[Z>>2],a[b+4>>2]=a[Z+4>>2],f[b>>3]);lj(r,n);var K=r|0,M=(a[b>>2]=a[K>>2],a[b+4>>2]=a[K+4>>2],f[b>>3]),L=r+8|0,E=(a[b>>2]=a[L>>2],a[b+4>>2]=a[L+4>>2],f[b>>3]),yb=r+16|0,J=(a[b>>2]=a[yb>>2],a[b+4>>2]=a[yb+4>>2],f[b>>3]),R=r+24|0,Y=(a[b>>2]=a[R>>2],a[b+4>>2]=a[R+4>>2],f[b>>3]);if(0<(a[k]|0)){for(var he=q|0,Rb=q+8|0,H=q+16|0,ea=q+24|0,wa=w|0,Fb=w+8|0,V=w+16|0,W=w+24|0,X=m|0,ba=m+8|0,ma=m+16|0,ib=m+24|0,G=Y,mc=J,O=E,ga=M,Tb=0,ie=t,ua=y,Da=z,Ja=B,Ab=D,ra=Gb,P=I,ya=C;;){if(0<(Tb|0)){var ja=a[i>>2];s=ja>>2;var la=ja+(48*Tb&-1)|0,va=a[la>>2],oa=a[((48*Tb&-1)+4>>2)+s],ka=a[((48*Tb&-1)+8>>2)+s],Ea=a[((48*Tb&-1)+12>>2)+s],Ka=ja+(48*Tb&-1)+16|0,Na=(a[b>>2]=a[Ka>>2],a[b+4>>2]=a[Ka+4>>2],f[b>>3]),Ba=ja+(48*Tb&-1)+24|0,Wa=(a[b>>2]=a[Ba>>2],a[b+4>>2]=a[Ba+4>>2],f[b>>3]),U=ja+(48*Tb&-1)+32|0,N=(a[b>>2]=a[U>>2],a[b+4>>2]=a[U+4>>2],f[b>>3]),Ra=ja+(48*Tb&-1)+40|0,bb=(a[b>>2]=a[Ra>>2],a[b+4>>2]=a[Ra+4>>2],f[b>>3]);lj(q,la);var Xa=(a[b>>2]=a[he>>2],a[b+4>>2]=a[he+4>>2],f[b>>3]),Sa=(a[b>>2]=a[Rb>>2],a[b+4>>2]=a[Rb+4>>2],f[b>>3]),aa=(a[b>>2]=a[H>>2],a[b+4>>2]=a[H+4>>2],f[b>>3]),Va=(a[b>>2]=a[ea>>2],a[b+4>>2]=a[ea+4>>2],f[b>>3]),Ta=ga<Xa?ga:Xa,Aa=O<Sa?O:Sa,fb=mc>aa?mc:aa,Ca=G>Va?G:Va,Ya=va,$a=oa,La=ka,pa=Ea,Ga=Na,Fa=Wa,da=N,nb=bb}else{Ta=ga,Aa=O,fb=mc,Ca=G,Ya=ie,$a=ua,La=Da,pa=Ja,Ga=Ab,Fa=ra,da=P,nb=ya}if(0==(La|0)){var jb=Ta,cb=Aa,Q=fb,kb=Ca}else{var Kb=Ya|0,Ma=Ya+8|0;mf(m,Ga,Fa,(a[b>>2]=a[Kb>>2],a[b+4>>2]=a[Kb+4>>2],f[b>>3]),(a[b>>2]=a[Ma>>2],a[b+4>>2]=a[Ma+4>>2],f[b>>3]));var ld=(a[b>>2]=a[X>>2],a[b+4>>2]=a[X+4>>2],f[b>>3]),lb=(a[b>>2]=a[ba>>2],a[b+4>>2]=a[ba+4>>2],f[b>>3]),rb=(a[b>>2]=a[ma>>2],a[b+4>>2]=a[ma+4>>2],f[b>>3]),ab=(a[b>>2]=a[ib>>2],a[b+4>>2]=a[ib+4>>2],f[b>>3]),jb=Ta<ld?Ta:ld,cb=Aa<lb?Aa:lb,Q=fb>rb?fb:rb,kb=Ca>ab?Ca:ab}if(0==(pa|0)){var db=jb,ob=cb,pb=Q,ub=kb}else{var gb=$a-1|0,sb=(gb<<4)+Ya|0,Ia=(gb<<4)+Ya+8|0;mf(w,da,nb,(a[b>>2]=a[sb>>2],a[b+4>>2]=a[sb+4>>2],f[b>>3]),(a[b>>2]=a[Ia>>2],a[b+4>>2]=a[Ia+4>>2],f[b>>3]));var vb=(a[b>>2]=a[wa>>2],a[b+4>>2]=a[wa+4>>2],f[b>>3]),Ua=(a[b>>2]=a[Fb>>2],a[b+4>>2]=a[Fb+4>>2],f[b>>3]),$=(a[b>>2]=a[V>>2],a[b+4>>2]=a[V+4>>2],f[b>>3]),ca=(a[b>>2]=a[W>>2],a[b+4>>2]=a[W+4>>2],f[b>>3]),db=jb<vb?jb:vb,ob=cb<Ua?cb:Ua,pb=Q>$?Q:$,ub=kb>ca?kb:ca}var qb=Tb+1|0;if((qb|0)<(a[k]|0)){G=ub,mc=pb,O=ob,ga=db,Tb=qb,ie=Ya,ua=$a,Da=La,Ja=pa,Ab=Ga,ra=Fa,P=da,ya=nb}else{Bb=ub;sc=pb;xb=ob;za=db;break}}Nb=u+8|0;c=Nb>>2;f[b>>3]=za;a[c]=a[b>>2];a[c+1]=a[b+4>>2];Jb=u+16|0;l=Jb>>2;f[b>>3]=xb;a[l]=a[b>>2];a[l+1]=a[b+4>>2];ha=u+24|0;e=ha>>2;f[b>>3]=sc;a[e]=a[b>>2];a[e+1]=a[b+4>>2];sa=u+32|0}else{var Bb=Y,sc=J,xb=E,za=M,Nb=u+8|0;c=Nb>>2;f[b>>3]=za;a[c]=a[b>>2];a[c+1]=a[b+4>>2];var Jb=u+16|0;l=Jb>>2;f[b>>3]=xb;a[l]=a[b>>2];a[l+1]=a[b+4>>2];var ha=u+24|0;e=ha>>2;f[b>>3]=sc;a[e]=a[b>>2];a[e+1]=a[b+4>>2];var sa=u+32|0}g=sa>>2;f[b>>3]=Bb;a[g]=a[b>>2];a[g+1]=a[b+4>>2];h=r}function lj(u,s){var g=h,e=s,s=h;h=h+48|0;for(var e=e>>2,l=s>>2,c=e+12;e<c;e++,l++){a[l]=a[e]}e=a[s+4>>2];0<(e|0)||ia(5378016,3382,5380112,5335340);1!=((e|0)%3|0)&&ia(5378016,3383,5380112,5335044);var l=a[s>>2],c=l|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),d=l+8|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);a:do{if(1<(e|0)){for(var k=c,r=d,q=c,m=d,w=1;;){var i=(w<<4)+l|0,n=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),i=(w<<4)+l+8|0,t=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),i=w+1|0,y=(i<<4)+l|0,z=(i<<4)+l+8|0,i=w+2|0,n=.5*(n+(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3])),t=.5*(t+(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3])),k=k<n?k:n,r=r<t?r:t,q=q>n?q:n,m=m>t?m:t,n=(i<<4)+l|0,n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),i=(i<<4)+l+8|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),k=k<n?k:n,r=r<i?r:i,q=q>n?q:n,m=m>i?m:i,w=w+3|0;if((w|0)>=(e|0)){var B=k,F=r,D=q,S=m;break a}}}else{B=c,F=d,D=c,S=d}}while(0);e=u|0;f[b>>3]=B;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];B=u+8|0;f[b>>3]=F;a[B>>2]=a[b>>2];a[B+4>>2]=a[b+4>>2];F=u+16|0;f[b>>3]=D;a[F>>2]=a[b>>2];a[F+4>>2]=a[b+4>>2];D=u+24|0;f[b>>3]=S;a[D>>2]=a[b>>2];a[D+4>>2]=a[b+4>>2];h=g}function Vm(u,s,g){var e,l,c,d=s>>2,k=u>>2,r=0,q=h;h=h+156|0;c=q>>2;var m=q+4,w=q+8,i=q+12,v=q+28,t=a[k+37];a[c]=0;a[m>>2]=0;a[w>>2]=0;var y=Bg(u);l=y>>2;a[l+1]=3;a[l+2]=s;a[l+3]=9;0!=(g|0)&&0!=(a[d+6]|0)&&Dd(a[k+4],a[k+15],g);var z=a[1345498];if(0!=(z|0)){var B=s|0,F=tb(B,a[z+8>>2]);0!=(F|0)&&0!=n[F]<<24>>24&&jj(u,lc(B,z,1,0))}if(0!=(t&16777216|0)){var D=a[d+4];if(2<fc[a[D+20>>2]+206>>1]){var S=a[D+148>>2]+16|0,Gb=72*(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3]),A=y+116|0;f[b>>3]=(0>Gb?Gb-.5:Gb+.5)&-1|0;a[A>>2]=a[b>>2];a[A+4>>2]=a[b+4>>2];var I=a[a[d+3]+148>>2]+16|0,Z=72*(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3]),C=y+124|0;f[b>>3]=(0>Z?Z-.5:Z+.5)&-1|0;a[C>>2]=a[b>>2];a[C+4>>2]=a[b+4>>2]}else{e=(y+116|0)>>2,a[e]=0,a[e+1]=0,a[e+2]=0,a[e+3]=0}}if(0!=(t&32768|0)){var K=a[d+27];if(0==(K|0)){var M=a[l+33]}else{var L=a[K>>2],M=a[l+33]=L}var Qe=y+136|0;a[Qe>>2]=M;var yb=y+144|0;a[yb>>2]=M;var H=y+140|0;a[H>>2]=M;var R=a[d+30];0!=(R|0)&&(a[Qe>>2]=a[R>>2]);var Y=a[d+29];0!=(Y|0)&&(a[H>>2]=a[Y>>2]);var he=a[d+28];0!=(he|0)&&(a[yb>>2]=a[he>>2])}a:do{if(0==(t&65536|0)){var Rb=0}else{ac(i,128,v|0);var G=s|0;a[l+38]=Zb(Ih(a[a[a[a[k]+128>>2]+44>>2]+92>>2],G,i),G);Xb(a[i>>2],a[i+12>>2]);var ea=U(G,5353856);if(0==(ea|0)){r=1405}else{if(0==n[ea]<<24>>24){r=1405}else{var wa=ea,r=1407}}if(1405==r){var Fb=U(G,5355416);if(0==(Fb|0)){var V=0}else{0==n[Fb]<<24>>24?V=0:(wa=Fb,r=1407)}}1407==r&&(V=Zb(wa,G));var W=U(G,5329568);if(0==(W|0)){r=1410}else{if(0==n[W]<<24>>24){r=1410}else{var X=W,r=1412}}if(1410==r){var ba=U(G,5329356);0!=(ba|0)&&0!=n[ba]<<24>>24?(X=ba,r=1412):0!=(V|0)&&(a[l+37]=Hb(V))}1412==r&&(a[l+37]=Zb(X,G));var ma=U(G,5329136);if(0==(ma|0)){r=1417}else{if(0==n[ma]<<24>>24){r=1417}else{var ib=ma,r=1419}}if(1417==r){var P=U(G,5328876);0!=(P|0)&&0!=n[P]<<24>>24?(ib=P,r=1419):0!=(V|0)&&(a[l+39]=Hb(V))}1419==r&&(a[l+39]=Zb(ib,G));var mc=U(G,5328632);if(0==(mc|0)){r=1424}else{if(0==n[mc]<<24>>24){r=1424}else{var O=mc,r=1426}}if(1424==r){var ga=U(G,5328332);0!=(ga|0)&&0!=n[ga]<<24>>24?(O=ga,r=1426):0!=(V|0)&&(a[l+40]=Hb(V))}if(1426==r){a[l+40]=Zb(O,G);var Tb=y+200|0;a[Tb>>2]|=128}var ie=U(G,5328072);if(0==(ie|0)){r=1431}else{if(0==n[ie]<<24>>24){r=1431}else{var ua=ie}}do{if(1431==r){var Da=U(G,5327780);if(0!=(Da|0)&&0!=n[Da]<<24>>24){ua=Da}else{if(0==(V|0)){Rb=0;break a}a[l+41]=Hb(V);Rb=V;break a}}}while(0);a[l+41]=Zb(ua,G);var Ja=y+200|0;a[Ja>>2]|=256;Rb=V}}while(0);a:do{if(0==(t&8388608|0)){var Ab=0}else{var ra=s|0,N=U(ra,5327484),ya=0==(N|0)?0:0==n[N]<<24>>24?0:Zb(N,ra),ja=U(ra,5327080);if(0==(ja|0)){r=1443}else{if(0==n[ja]<<24>>24){r=1443}else{var la=y+200|0;a[la>>2]|=64;a[l+46]=Zb(ja,ra)}}1443==r&&0!=(ya|0)&&(a[l+46]=Hb(ya));var va=U(ra,5326824);0==(va|0)?r=1448:0==n[va]<<24>>24?r=1448:a[l+47]=Zb(va,ra);1448==r&&0!=(ya|0)&&(a[l+47]=Hb(ya));var oa=U(ra,5326608);if(0==(oa|0)){r=1453}else{if(0==n[oa]<<24>>24){r=1453}else{a[l+48]=Zb(oa,ra);var ka=y+200|0;a[ka>>2]|=16}}1453==r&&0!=(ya|0)&&(a[l+48]=Hb(ya));var Ea=U(ra,5326320);do{if(0!=(Ea|0)&&0!=n[Ea]<<24>>24){var Ka=y+200|0;a[Ka>>2]|=32;a[l+49]=Zb(Ea,ra);Ab=ya;break a}}while(0);0==(ya|0)?Ab=0:(a[l+49]=Hb(ya),Ab=ya)}}while(0);a:do{if(0!=(t&4194304|0)){var Na=s|0,Ba=U(Na,5360720);if(0==(Ba|0)){r=1463}else{if(0==n[Ba]<<24>>24){r=1463}else{var Wa=Ba,r=1465}}if(1463==r){var aa=U(Na,5325852);if(0!=(aa|0)&&0!=n[aa]<<24>>24){Wa=aa,r=1465}else{var Rd=a[l+33];0!=(Rd|0)&&(a[l+42]=Hb(Rd))}}if(1465==r){a[l+42]=Zb(Wa,Na);var Ra=y+200|0;a[Ra>>2]|=1}var bb=U(Na,5325620);if(0==(bb|0)){r=1471}else{if(0==n[bb]<<24>>24){r=1471}else{a[l+43]=Zb(bb,Na);var Xa=y+200|0;a[Xa>>2]|=8}}if(1471==r){var Sa=a[l+33];0!=(Sa|0)&&(a[l+43]=Hb(Sa))}var Q=U(Na,5378856);if(0==(Q|0)){r=1476}else{if(0==n[Q]<<24>>24){r=1476}else{a[l+44]=Zb(Q,Na);var Va=y+200|0;a[Va>>2]|=2}}if(1476==r){var Ta=a[l+35];0!=(Ta|0)&&(a[l+44]=Hb(Ta))}var Aa=U(Na,5378632);do{if(0!=(Aa|0)&&0!=n[Aa]<<24>>24){a[l+45]=Zb(Aa,Na);var fb=y+200|0;a[fb>>2]|=4;break a}}while(0);var Ca=a[l+36];0!=(Ca|0)&&(a[l+45]=Hb(Ca))}}while(0);E(Rb);E(Ab);do{if(0!=(t&4259840|0)){var Ya=a[d+6];if(0!=(Ya|0)&&!(0==(a[l+37]|0)&&0==(a[l+42]|0))&&0!=(t&524288|0)){var $a=a[k+4]+96|0,La=.5*(a[b>>2]=a[$a>>2],a[b+4>>2]=a[$a+4>>2],f[b>>3]),pa=2<La?La:2,Ga=a[Ya+4>>2];if(0<(Ga|0)){for(var Fa=Ya|0,da=0;;){en(q,m,w,a[Fa>>2]+(48*da&-1)|0,pa);var nb=da+1|0;if((nb|0)==(Ga|0)){break}else{da=nb}}var jb=a[w>>2],cb=a[m>>2]}else{cb=jb=0}a[l+54]=jb;a[l+55]=cb;if(0==(t&8192|0)){a:do{if(0<(jb|0)){for(var $=0,kb=0;;){var Kb=a[cb+($<<2)>>2]+kb|0,Ma=$+1|0;if((Ma|0)<(jb|0)){$=Ma,kb=Kb}else{var ld=Kb;break a}}}else{ld=0}}while(0);var lb=a[c];Wd(u,lb,lb,ld);var rb=lb}else{rb=a[c]}a[l+56]=rb;a[l+51]=2;a[l+53]=rb;a[l+52]=a[cb>>2]}}}while(0);var ab=a[u+60>>2];if(0!=(ab|0)){var db=a[ab+64>>2];if(0!=(db|0)){J[db](u)}}var ob=a[l+37];0==(ob|0)&&0==(a[l+50]&1|0)||Mc(u,ob,a[l+42],a[l+46],a[l+38]);h=q}function Wm(u,s,g){var e,l,c,d,k,r,q,m,w,i,v,t,y,z,B,F,D=0,S=h;h=h+64|0;var Gb=S+16,A=S+32,I=S+48,Z=u+16|0,C=a[Z>>2]+96|0,K=(a[b>>2]=a[C>>2],a[b+4>>2]=a[C+4>>2],f[b>>3]),M=s|0,L=U(M,5356744);a[1315020]=L;F=(s+24|0)>>2;if(0!=(a[F]|0)){for(var Qe=lc(M,a[1345519],1,0),yb=$b(M,a[1345517],5338228),J=yb,R=0,Y=0;;){var H=n[J];if(0==H<<24>>24){break}else{if(44==H<<24>>24){var Rb=R,G=Y+1|0}else{Rb=58==H<<24>>24?R+1|0:R,G=Y}}J=J+1|0;R=Rb;Y=G}var ea=0==(R|0);if(0==(Y|0)|ea){var wa=yb}else{if(0!=(fn(u,s,g,yb,R+1|0,Qe,K)|0)){wa=5374748}else{h=S;return}}var Fb=s+127|0,V=ca[Fb];if(0==(V&1|0)){if(0!=(V&2|0)){var W=na(M,0,Nh(wa,5336384)),X=na(M,0,5336016),D=1520}else{if(0!=(V&8|0)){W=na(M,0,Nh(wa,5335712)),X=na(M,0,5335408),D=1520}else{if(0==(V&4|0)){var ba=wa}else{W=na(M,0,Nh(wa,5335120)),X=na(M,0,5334856),D=1520}}}}else{W=na(M,0,Nh(wa,5336884)),X=na(M,0,5336656),D=1520}1520==D&&((W|0)!=(wa|0)&&eb(u,W),(X|0)!=(wa|0)&&Sb(u,X),ba=W);if(ea){0==(n[Fb]&3)<<24>>24&&(0==n[ba]<<24>>24?(eb(u,5374748),Sb(u,5374748)):(eb(u,ba),Sb(u,ba)));var ma=a[F];if(0<(a[ma+4>>2]|0)){for(var ib=u+148|0,P=0==(g|0),mc=u+60|0,O=0,ga=ma;;){var Tb=a[ga>>2];B=Tb>>2;var ie=a[((48*O&-1)>>2)+B],ua=a[((48*O&-1)+4>>2)+B],Da=a[((48*O&-1)+8>>2)+B],Ja=a[((48*O&-1)+12>>2)+B],Ab=Tb+(48*O&-1)+16|0,ra=(a[b>>2]=a[Ab>>2],a[b+4>>2]=a[Ab+4>>2],f[b>>3]),N=Tb+(48*O&-1)+24|0,ya=(a[b>>2]=a[N>>2],a[b+4>>2]=a[N+4>>2],f[b>>3]),ja=Tb+(48*O&-1)+32|0,la=(a[b>>2]=a[ja>>2],a[b+4>>2]=a[ja+4>>2],f[b>>3]),va=Tb+(48*O&-1)+40|0,oa=(a[b>>2]=a[va>>2],a[b+4>>2]=a[va+4>>2],f[b>>3]);if(0==(a[ib>>2]&16384|0)){hf(u,ie,ua,0,0,0);if(0!=(Da|0)){var ka=ie|0,Ea=ie+8|0;nf(u,2,ra,ya,(a[b>>2]=a[ka>>2],a[b+4>>2]=a[ka+4>>2],f[b>>3]),(a[b>>2]=a[Ea>>2],a[b+4>>2]=a[Ea+4>>2],f[b>>3]),Qe,K,Da)}if(0!=(Ja|0)){var Ka=ua-1|0,Na=(Ka<<4)+ie|0,Ba=(Ka<<4)+ie+8|0;nf(u,3,la,oa,(a[b>>2]=a[Na>>2],a[b+4>>2]=a[Na+4>>2],f[b>>3]),(a[b>>2]=a[Ba>>2],a[b+4>>2]=a[Ba+4>>2],f[b>>3]),Qe,K,Ja)}1<(a[a[F]+4>>2]|0)&&(0==(Ja|Da|0)|P||Dd(a[Z>>2],a[mc>>2],g))}else{hf(u,ie,ua,Da,Ja,0)}var Wa=O+1|0,aa=a[F];if((Wa|0)<(a[aa+4>>2]|0)){O=Wa,ga=aa}else{break}}}}else{var Rd=a[a[F]+4>>2],Ra=48*Rd&-1,bb=wb(Ra);z=bb>>2;var Xa=wb(Ra);y=Xa>>2;var Sa=.5*(R+2|0),Q=0<(Rd|0);a:do{if(Q){t=I>>2;v=S>>2;i=A>>2;w=Gb>>2;for(var Va=0,Ta=0,Aa=0;;){var fb=a[a[F]>>2];m=fb>>2;var Ca=a[((48*Aa&-1)>>2)+m],Ya=a[((48*Aa&-1)+4>>2)+m],$a=a[((48*Aa&-1)+8>>2)+m],La=a[((48*Aa&-1)+12>>2)+m],pa=fb+(48*Aa&-1)+16|0,Ga=(a[b>>2]=a[pa>>2],a[b+4>>2]=a[pa+4>>2],f[b>>3]),Fa=fb+(48*Aa&-1)+24|0,da=(a[b>>2]=a[Fa>>2],a[b+4>>2]=a[Fa+4>>2],f[b>>3]),nb=fb+(48*Aa&-1)+32|0,jb=(a[b>>2]=a[nb>>2],a[b+4>>2]=a[nb+4>>2],f[b>>3]),cb=fb+(48*Aa&-1)+40|0,$=(a[b>>2]=a[cb>>2],a[b+4>>2]=a[cb+4>>2],f[b>>3]);a[((48*Aa&-1)+4>>2)+z]=Ya;a[((48*Aa&-1)+4>>2)+y]=Ya;var kb=Ya<<4,Kb=wb(kb);a[((48*Aa&-1)>>2)+z]=Kb;var Ma=wb(kb);a[((48*Aa&-1)>>2)+y]=Ma;var ld=Ca|0,lb=(a[b>>2]=a[ld>>2],a[b+4>>2]=a[ld+4>>2],f[b>>3]),rb=Ca+8|0,ab=(a[b>>2]=a[rb>>2],a[b+4>>2]=a[rb+4>>2],f[b>>3]),db=Ya-1|0;b:do{if(0<(db|0)){for(var ob=Va,pb=Ta,ub=lb,gb=ab,sb=0;;){var Ia=sb+1|0,vb=(Ia<<4)+Ca|0,Ua=(a[b>>2]=a[vb>>2],a[b+4>>2]=a[vb+4>>2],f[b>>3]),ia=(Ia<<4)+Ca+8|0,gf=(a[b>>2]=a[ia>>2],a[b+4>>2]=a[ia+4>>2],f[b>>3]),qb=(sb<<4)+Kb|0;0==(sb|0)?(mj(S,ub,gb,Ua,gf),q=qb>>2,a[q]=a[v],a[q+1]=a[v+1],a[q+2]=a[v+2],a[q+3]=a[v+3]):(mj(Gb,ob,pb,Ua,gf),r=qb>>2,a[r]=a[w],a[r+1]=a[w+1],a[r+2]=a[w+2],a[r+3]=a[w+3]);var Bb=sb+2|0,sc=(Bb<<4)+Ca|0,xb=(a[b>>2]=a[sc>>2],a[b+4>>2]=a[sc+4>>2],f[b>>3]),za=(Bb<<4)+Ca+8|0,Nb=(a[b>>2]=a[za>>2],a[b+4>>2]=a[za+4>>2],f[b>>3]),Jb=sb+3|0,ha=(Jb<<4)+Ca|0,sa=(a[b>>2]=a[ha>>2],a[b+4>>2]=a[ha+4>>2],f[b>>3]),Ic=(Jb<<4)+Ca+8|0,qa=(a[b>>2]=a[Ic>>2],a[b+4>>2]=a[Ic+4>>2],f[b>>3]),xa=(Ia<<4)+Kb|0,fa=(Bb<<4)+Kb|0,Ha=A,Za=Ua-xb,Oa=gf-Nb,Ub=Math.sqrt(Za*Za+Oa*Oa);if(1e-4>Ub){var ta=ub-sa,Pa=gb-qa,mb=Math.sqrt(ta*ta+Pa*Pa+1e-4),hb=ta,me=Pa}else{mb=Ub,hb=Za,me=Oa}var te=2/mb,je=te*-hb,zb=Ha|0;f[b>>3]=me*te;a[zb>>2]=a[b>>2];a[zb+4>>2]=a[b+4>>2];var cc=Ha+8|0;f[b>>3]=je;a[cc>>2]=a[b>>2];a[cc+4>>2]=a[b+4>>2];k=fa>>2;a[k]=a[i];a[k+1]=a[i+1];a[k+2]=a[i+2];a[k+3]=a[i+3];d=xa>>2;a[d]=a[i];a[d+1]=a[i+1];a[d+2]=a[i+2];a[d+3]=a[i+3];var pc=qb|0,Db=ub-Sa*(a[b>>2]=a[pc>>2],a[b+4>>2]=a[pc+4>>2],f[b>>3]),hd=(sb<<4)+Ma|0;f[b>>3]=Db;a[hd>>2]=a[b>>2];a[hd+4>>2]=a[b+4>>2];var qd=(sb<<4)+Kb+8|0,Vb=gb-Sa*(a[b>>2]=a[qd>>2],a[b+4>>2]=a[qd+4>>2],f[b>>3]),Yb=(sb<<4)+Ma+8|0;f[b>>3]=Vb;a[Yb>>2]=a[b>>2];a[Yb+4>>2]=a[b+4>>2];var Jc=xa|0,Ib=Ua-Sa*(a[b>>2]=a[Jc>>2],a[b+4>>2]=a[Jc+4>>2],f[b>>3]),Qa=(Ia<<4)+Ma|0;f[b>>3]=Ib;a[Qa>>2]=a[b>>2];a[Qa+4>>2]=a[b+4>>2];var tb=(Ia<<4)+Kb+8|0,Eh=gf-Sa*(a[b>>2]=a[tb>>2],a[b+4>>2]=a[tb+4>>2],f[b>>3]),kf=(Ia<<4)+Ma+8|0;f[b>>3]=Eh;a[kf>>2]=a[b>>2];a[kf+4>>2]=a[b+4>>2];var kc=fa|0,uc=xb-Sa*(a[b>>2]=a[kc>>2],a[b+4>>2]=a[kc+4>>2],f[b>>3]),Cb=(Bb<<4)+Ma|0;f[b>>3]=uc;a[Cb>>2]=a[b>>2];a[Cb+4>>2]=a[b+4>>2];var Eb=(Bb<<4)+Kb+8|0,ne=Nb-Sa*(a[b>>2]=a[Eb>>2],a[b+4>>2]=a[Eb+4>>2],f[b>>3]),Kc=(Bb<<4)+Ma+8|0;f[b>>3]=ne;a[Kc>>2]=a[b>>2];a[Kc+4>>2]=a[b+4>>2];if((Jb|0)<(db|0)){ob=xb,pb=Nb,ub=sa,gb=qa,sb=Jb}else{var rc=xb,Pf=Nb,Cc=sa,Mb=qa,Dc=Jb;break b}}}else{rc=Va,Pf=Ta,Cc=lb,Mb=ab,Dc=0}}while(0);var Pb=(Dc<<4)+Kb|0;mj(I,rc,Pf,Cc,Mb);c=Pb>>2;a[c]=a[t];a[c+1]=a[t+1];a[c+2]=a[t+2];a[c+3]=a[t+3];var Xb=Pb|0,rt=Cc-Sa*(a[b>>2]=a[Xb>>2],a[b+4>>2]=a[Xb+4>>2],f[b>>3]),Yc=(Dc<<4)+Ma|0;f[b>>3]=rt;a[Yc>>2]=a[b>>2];a[Yc+4>>2]=a[b+4>>2];var xc=(Dc<<4)+Kb+8|0,fc=Mb-Sa*(a[b>>2]=a[xc>>2],a[b+4>>2]=a[xc+4>>2],f[b>>3]),Wc=(Dc<<4)+Ma+8|0;f[b>>3]=fc;a[Wc>>2]=a[b>>2];a[Wc+4>>2]=a[b+4>>2];var ae=Aa+1|0;if((ae|0)==(Rd|0)){var Zb=$,st=jb,ec=da,Kd=Ga,Sc=La,bd=$a,Vc=db,cd=Ca;break a}else{Va=rc,Ta=Pf,Aa=ae}}}}while(0);var Zc=Hb(ba),nc=Jd(Zc,5331664,ud);a:do{if(0==(nc|0)){var Oc=ba,Lc=ba}else{for(var dd=ba,Sd=ba,id=ba,Xc=nc,bf=0;;){var $c=0==n[Xc]<<24>>24?5374748:Xc;if(($c|0)==(dd|0)){var ic=dd}else{0==(n[Fb]&3)<<24>>24&&(eb(u,$c),Sb(u,$c)),ic=$c}var Re=0==(bf|0),ad=Re?$c:id,hc=1==(bf|0)?$c:Re?$c:Sd;b:do{if(Q){for(var Tc=0;;){var Ke=a[((48*Tc&-1)>>2)+y],gc=a[((48*Tc&-1)>>2)+z],Ge=Xa+(48*Tc&-1)+4|0,Ie=a[Ge>>2];c:do{if(0<(Ie|0)){for(var Uc=0;;){var wd=(Uc<<4)+gc|0;l=((Uc<<4)+Ke|0)>>2;var Qb=(a[b>>2]=a[wd>>2],a[b+4>>2]=a[wd+4>>2],f[b>>3])+(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]);f[b>>3]=Qb;a[l]=a[b>>2];a[l+1]=a[b+4>>2];var xd=(Uc<<4)+gc+8|0;e=((Uc<<4)+Ke+8|0)>>2;var rd=(a[b>>2]=a[xd>>2],a[b+4>>2]=a[xd+4>>2],f[b>>3])+(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);f[b>>3]=rd;a[e]=a[b>>2];a[e+1]=a[b+4>>2];var yd=Uc+1|0,Lb=a[Ge>>2];if((yd|0)<(Lb|0)){Uc=yd}else{var Cd=Lb;break c}}}else{Cd=Ie}}while(0);hf(u,Ke,Cd,0,0,0);var md=Tc+1|0;if((md|0)==(Rd|0)){break b}else{Tc=md}}}}while(0);var sd=Jd(0,5331664,ud);if(0==(sd|0)){Oc=hc;Lc=ad;break a}else{dd=ic,Sd=hc,id=ad,Xc=sd,bf=bf+1|0}}}}while(0);if(0==(bd|0)){var ac=0}else{if(0==(Oc|0)){var ed=0}else{0==(n[Fb]&3)<<24>>24&&(eb(u,Oc),Sb(u,Oc)),ed=Oc}var zd=cd|0,ke=cd+8|0;nf(u,2,Kd,ec,(a[b>>2]=a[zd>>2],a[b+4>>2]=a[zd+4>>2],f[b>>3]),(a[b>>2]=a[ke>>2],a[b+4>>2]=a[ke+4>>2],f[b>>3]),Qe,K,bd);ac=ed}if(0!=(Sc|0)){(ac|0)!=(Lc|0)&&0==(n[Fb]&3)<<24>>24&&(eb(u,Lc),Sb(u,Lc));var jc=(Vc<<4)+cd|0,jd=(Vc<<4)+cd+8|0;nf(u,3,st,Zb,(a[b>>2]=a[jc>>2],a[b+4>>2]=a[jc+4>>2],f[b>>3]),(a[b>>2]=a[jd>>2],a[b+4>>2]=a[jd+4>>2],f[b>>3]),Qe,K,Sc)}E(Zc);a:do{if(Q){for(var Ld=0;;){E(a[((48*Ld&-1)>>2)+z]);E(a[((48*Ld&-1)>>2)+y]);var Ad=Ld+1|0;if((Ad|0)==(Rd|0)){break a}else{Ld=Ad}}}}while(0);E(bb);E(Xa)}}h=S}function Xm(u){var s,g,e,l;l=0;var c=a[u+16>>2];s=c>>2;var d=a[s+2];e=c+148|0;0==(a[e>>2]|0)?0!=(a[s+50]&1|0)&&(l=1579):l=1579;a:do{if(1579==l){de(u);g=c+216|0;var k=a[g>>2];if(0!=(k|0)){var r=c+220|0;if(1<(k|0)){for(var h=a[r>>2],k=c+208|0,m=c+224|0,w=c+212|0,i=c+168|0,n=c+184|0,t=c+152|0,y=1,z=a[h>>2];;){if(a[k>>2]=a[h+(y<<2)>>2],a[w>>2]=(z<<4)+a[m>>2]|0,Mc(u,a[e>>2],a[i>>2],a[n>>2],a[t>>2]),de(u),h=a[r>>2],z=a[h+(y<<2)>>2]+z|0,y=y+1|0,(y|0)>=(a[g>>2]|0)){break a}}}}}}while(0);a[s+52]=0;a[s+53]=0;l=(d+24|0)>>2;e=a[l];0==(e|0)?s=c+200|0:(e=a[e>>2],r=a[e>>2],0==(a[e+8>>2]|0)?(g=r|0,r=r+8|0):(g=e+16|0,r=e+24|0),e=c+200|0,k=a[e>>2],gn(u,(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),k<<24>>31&255,a[s+40],k<<30>>31&255),g=a[l],r=a[g+4>>2]-1|0,k=a[g>>2],g=k>>2,0==(a[((48*r&-1)+12>>2)+g]|0)?(k=a[((48*r&-1)>>2)+g],r=a[((48*r&-1)+4>>2)+g]-1|0,g=(r<<4)+k|0,r=(r<<4)+k+8|0):(g=k+(48*r&-1)+32|0,r=k+(48*r&-1)+40|0),k=a[e>>2],gn(u,(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),k<<23>>31&255,a[s+41],k<<29>>31&255),s=e);e=s>>2;w=a[d+108>>2];i=a[e]<<28>>31;m=c+156|0;n=a[m>>2];k=c+172|0;t=a[k>>2];r=c+188|0;y=a[r>>2];s=(c+152|0)>>2;z=a[s];g=d|0;h=0==Xd($b(g,a[1345514],5333780))<<24>>24?0:a[l];Vf(u,w,11,i,n,t,y,z,h);w=a[d+120>>2];i=a[e]<<28>>31;m=a[m>>2];k=a[k>>2];r=a[r>>2];n=a[s];0==Xd($b(g,a[1345514],5333780))<<24>>24?Vf(u,w,11,i,m,k,r,n,0):(l=a[l],Vf(u,w,11,i,m,k,r,n,l));l=a[(d+112|0)>>2];g=a[e];g=g<<29>>31;r=a[(c+164|0)>>2];k=a[(c+180|0)>>2];m=a[(c+196|0)>>2];w=a[s];Vf(u,l,7,g,r,k,m,w,0);d=a[(d+116|0)>>2];l=a[e];l=l<<30>>31;e=a[(c+160|0)>>2];g=a[(c+176|0)>>2];c=a[(c+192|0)>>2];s=a[s];Vf(u,d,6,l,e,g,c,s,0);c=a[u+60>>2];if(0!=(c|0)&&(c=a[c+68>>2],0!=(c|0))){J[c](u)}Qf(u)}function gn(b,s,g,e,l,c){var d=a[b+16>>2],e=0==e<<24>>24?a[d+148>>2]:l;0==c<<24>>24&&0==(e|0)&0==(a[d+200>>2]&1|0)||hn(b,s,g)}function Vf(b,s,g,e,l,c,d,f,r){var q=h,m=a[b+148>>2];if(0!=(s|0)){if(0==(f|0)){f=0}else{var w=da(xa(f)+11|0);if(11==(g|0)){var n=5332600}else{7==(g|0)?n=5328576:6==(g|0)?n=5328276:ia(5378016,2201,5379868,5340724)}Pa(w,5332524,(i=h,h=h+8|0,a[i>>2]=f,a[i+4>>2]=n,i));f=w}var w=b+16|0,v=a[w>>2]+12|0,n=a[v>>2];a[v>>2]=g;e=0==(l|0)&0==(e|0);!e&&0==(m&4|0)&&(nj(b,s),Mc(b,l,c,d,f));Te(b,g,s);0!=(r|0)&&jn(b,s,r);e||(0!=(m&4|0)&&(nj(b,s),Mc(b,l,c,d,f)),de(b));0!=(f|0)&&E(f);a[a[w>>2]+12>>2]=n}h=q}function kn(u,s,g){var e=u|0;f[b>>3]=s;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];u=u+8|0;f[b>>3]=g;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}function nj(u,s){var g,e,l,c,d;g=a[u+16>>2];d=g>>2;var k=a[u+148>>2];if(0!=(k&4259840|0)){var r=0!=(k&131072|0);e=g+204|0;r?(a[e>>2]=0,a[d+52]=2):(a[e>>2]=2,a[d+52]=4);g=g+212|0;E(a[g>>2]);d=da(a[d+52]<<4);a[g>>2]=d;c=(s+56|0)>>2;l=(s+24|0)>>2;g=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3])-.5*(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]);f[b>>3]=g;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];e=(s+64|0)>>2;g=(s+32|0)>>2;var h=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])-.5*(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]),m=d+8|0;f[b>>3]=h;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];l=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3])+.5*(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]);c=d+16|0;f[b>>3]=l;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];g=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])+.5*(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]);e=d+24|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];0==(k&8192|0)&&Wd(u,d,d,2);r||Kh(d)}}function jn(u,s,g){var e,l,c,d,k,r;k=0;var q=h;h=h+96|0;c=q+48;l=q+64;e=q+80;for(r=a[s>>2];;){var m=n[r];if(0==m<<24>>24){k=1648;break}if(0==(Ze(m&255)|0)){break}else{r=r+1|0}}1648!=k&&0!=n[r]<<24>>24&&(k=s+24|0,m=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),k=s+32|0,d=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),r=(s+56|0)>>2,k=(s+64|0)>>2,kn(c,(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3])+.5*m,(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3])-.5*d),d=q>>2,c>>=2,a[d]=a[c],a[d+1]=a[c+1],a[d+2]=a[c+2],a[d+3]=a[c+3],c=q|0,d=q+8|0,kn(l,(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])-m,(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])),c=(q+16|0)>>2,l>>=2,a[c]=a[l],a[c+1]=a[l+1],a[c+2]=a[l+2],a[c+3]=a[l+3],ln(e,a[g>>2],a[g+4>>2],(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3]),(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3])),g=(q+32|0)>>2,e>>=2,a[g]=a[e],a[g+1]=a[e+1],a[g+2]=a[e+2],a[g+3]=a[e+3],Dd(a[u+16>>2],a[u+60>>2],a[a[u>>2]+296>>2]),eb(u,a[s+8>>2]),td(u,q|0,3));h=q}function hn(u,s,g){var e,l=a[u+16>>2];e=l>>2;var c=a[u+148>>2];if(0!=(c&4259840|0)){var d=0!=(c&131072|0),k=l+204|0;d?(a[k>>2]=0,a[e+52]=2):(a[k>>2]=2,a[e+52]=4);l=l+212|0;E(a[l>>2]);e=da(a[e+52]<<4);a[l>>2]=e;f[b>>3]=s-3;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];l=e+8|0;f[b>>3]=g-3;a[l>>2]=a[b>>2];a[l+4>>2]=a[b+4>>2];l=e+16|0;f[b>>3]=s+3;a[l>>2]=a[b>>2];a[l+4>>2]=a[b+4>>2];s=e+24|0;f[b>>3]=g+3;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];0==(c&8192|0)&&Wd(u,e,e,2);d||Kh(e)}}function fn(u,s,g,e,l,c,d){var k=h;h=h+196|0;var r=k+48,q=k+96,m=k+144,w=k+192,e=mn(e,l,w);if(1<(e|0)){var l=a[s+16>>2],n=0!=(a[a[l+20>>2]>>2]&16|0)?5345196:5341668,v=a[a[s+12>>2]+12>>2];aa(3,5331876,(i=h,h=h+12|0,a[i>>2]=a[l+12>>2],a[i+4>>2]=n,a[i+8>>2]=v,i));if(2==(e|0)){return h=k,1}}else{if(1==(e|0)){return h=k,1}}e=(s+24|0)>>2;l=a[e];a:do{if(0<(a[l+4>>2]|0)){for(var n=k,v=k+8|0,t=k+12|0,y=0==(g|0),z=k+4|0,B=k|0,F=k+32|0,D=k+40|0,S=k+16|0,Gb=k+24|0,A=q|0,I=q+4|0,Z=r,C=m,K=r|0,M=m|0,L=m+4|0,Qe=a[w>>2],s=(Qe+4|0)>>2,yb=u+16|0,J=u+60|0,R=0,Y=l;;){for(var H,Rb=(a[Y>>2]+(48*R&-1)|0)>>2,G=n>>2,ea=Rb+12;Rb<ea;Rb++,G++){a[G]=a[Rb]}var Y=a[s]|0,wa=a[Y>>2];b:do{if(0==(wa|0)){var Fb=H}else{for(var V=H,W=Y,X=wa;;){eb(u,X);X=W+4|0;Rb=hb[X>>2];if((W|0)==(a[s]|0)){oj(k,Rb,q,m),X=a[A>>2],hf(u,X,a[I>>2],0,0,0)}else{if(1>Rb){Rb=C>>2;G=Z>>2;for(ea=Rb+12;Rb<ea;Rb++,G++){a[G]=a[Rb]}oj(r,hb[X>>2],q,m);E(a[K>>2]);X=a[A>>2];hf(u,X,a[I>>2],0,0,0)}else{V=a[W>>2],X=a[M>>2],hf(u,X,a[L>>2],0,0,0)}}E(X);W=W+8|0;X=a[W>>2];if(0==(X|0)){Fb=V;break b}}}}while(0);Y=a[v>>2];H=0==(Y|0);H||(eb(u,a[a[s]>>2]),Sb(u,a[a[s]>>2]),X=a[B>>2],wa=(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3]),W=(a[b>>2]=a[Gb>>2],a[b+4>>2]=a[Gb+4>>2],f[b>>3]),V=X|0,X=X+8|0,nf(u,2,wa,W,(a[b>>2]=a[V>>2],a[b+4>>2]=a[V+4>>2],f[b>>3]),(a[b>>2]=a[X>>2],a[b+4>>2]=a[X+4>>2],f[b>>3]),c,d,Y));Y=a[t>>2];0==(Y|0)?wa=0:(eb(u,Fb),Sb(u,Fb),X=a[z>>2]-1|0,Rb=a[B>>2],wa=(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]),W=(a[b>>2]=a[D>>2],a[b+4>>2]=a[D+4>>2],f[b>>3]),V=(X<<4)+Rb|0,X=(X<<4)+Rb+8|0,nf(u,3,wa,W,(a[b>>2]=a[V>>2],a[b+4>>2]=a[V+4>>2],f[b>>3]),(a[b>>2]=a[X>>2],a[b+4>>2]=a[X+4>>2],f[b>>3]),c,d,Y),wa=Y);W=a[e];V=a[W+4>>2];do{if(1<(V|0)){if(H){if(0==(wa|0)|y){Y=W;X=V;break}}else{if(y){Y=W;X=V;break}}Dd(a[yb>>2],a[J>>2],g);Y=X=a[e];X=a[X+4>>2]}else{Y=W,X=V}}while(0);R=R+1|0;if((R|0)<(X|0)){H=Fb}else{var ba=Qe;break a}}}else{ba=a[w>>2]}}while(0);E(ba);h=k;return 0}function Nh(b,s){for(var g=1,e=b;;){var l=n[e];if(0==l<<24>>24){break}else{g=58==l<<24>>24?g+1|0:g}e=e+1|0}e=Math.a(xa(s)+1|0,g);(a[1314503]|0)<(e|0)&&(e=e+10|0,a[1314503]=e,a[1314504]=gc(a[1314504],e));ee(a[1314504],s);g=g-1|0;e=a[1314504];if(0==(g|0)){var c;return e}for(;;){if(l=e+xa(e)|0,Ib=58,n[l]=Ib&255,Ib>>=8,n[l+1|0]=Ib&255,fe(e,s),g=g-1|0,e=a[1314504],0==(g|0)){c=e;break}}return c}function mj(u,s,g,e,l){s-=e;l=g-l;g=2/Math.sqrt(s*s+l*l+1e-4);e=u|0;f[b>>3]=l*g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];u=u+8|0;f[b>>3]=g*-s;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}function mn(b,s,g){var e,l=0,c=h,d=da(8);e=(s<<3)+8|0;da(e);var f=Hb(b);a[d>>2]=f;var r=da(e);e=r>>2;a[d+4>>2]=r;var q=r=0,m=0,f=Jd(f,5331664,ud);a:for(;0!=(f|0);){var w=s-1|0;do{if((m|0)==(w|0)){if(1>q){var x=oc(f,44);0!=(x|0)&&(n[x]=0);a[(m<<3>>2)+e]=f;hb[((m<<3)+4>>2)+e]=1;x=r;v=s;t=q;y=m+1|0}else{var x=r,v=s,t=q,y=m}}else{y=f;v=q;x=h;h=h+4|0;t=oc(y,44);0==(t|0)?(aa(1,5330344,(i=h,h=h+4|0,a[i>>2]=y,i)),v=-1):(y=t+1|0,n[t]=0,t=Oe(y,x),v=(a[x>>2]|0)!=(y|0)&&t>=v&1>=t?t:-1);h=x;t=v;if(0>t){l=1718;break a}q<t?(a[(m<<3>>2)+e]=f,hb[((m<<3)+4>>2)+e]=(t-q)/(1-q),x=r,v=s,y=m+1|0):(n[5249352]?x=r:(aa(0,5330972,(i=h,h=h+4|0,a[i>>2]=b,i)),n[5249352]=1,x=3),v=w,t=q,y=m)}}while(0);r=x;s=v;q=t;m=y;f=Jd(0,5331664,ud)}if(1718==l){return n[5249352]?b=1:(aa(1,5330616,(i=h,h=h+4|0,a[i>>2]=b,i)),n[5249352]=1,b=2),nn(d),h=c,b}0==(m|0)?(nn(d),d=1):(a[g>>2]=d,d=r);h=c;return d}function oj(u,s,g,e){var l,c,d,k,r=h;h=h+32|0;var q=r+16,m=a[u+4>>2],w=m-1|0;d=(w|0)/3&-1;if(3>(m-4|0)>>>0){a[g+4>>2]=4;q=g|0;a[q>>2]=da(64);a[e+4>>2]=4;var i=da(64);a[e>>2]=i;zc(r,a[u>>2],s,a[q>>2],i)}else{m=da(d<<3);u=(u|0)>>2;a:do{if(2<(w|0)){var n=0;l=0;for(k=a[u];;){c=k;var t=c|0,y=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),t=c+16|0,t=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),z=y-t,y=c+8|0,B=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),y=c+24|0,y=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),B=B-y,B=Math.sqrt(z*z+B*B),z=c+32|0,z=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3]),F=t-z,t=c+40|0,t=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),y=y-t,y=B+Math.sqrt(F*F+y*y),B=c+48|0,z=z-(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]);c=c+56|0;c=t-(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);c=y+Math.sqrt(z*z+c*c);t=(n<<3)+m|0;f[b>>3]=c;a[t>>2]=a[b>>2];a[t+4>>2]=a[b+4>>2];l+=c;n=n+1|0;if((n|0)<(d|0)){k=k+48|0}else{var D=l;break a}}}else{D=0}}while(0);s*=D;for(w=D=0;;){if((w|0)>=(d|0)){i=D;break}k=(w<<3)+m|0;D+=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);if(D<s){w=w+1|0}else{i=D;break}}D=3*w&-1;n=D+4|0;k=(g+4|0)>>2;a[k]=n;g=(g|0)>>2;a[g]=da(n<<4);n=(3*(d-w)&-1)+1|0;d=(e+4|0)>>2;a[d]=n;e=(e|0)>>2;a[e]=da(n<<4);if(0<(a[k]|0)){for(n=0;;){if(c=((n<<4)+a[g]|0)>>2,l=((n<<4)+a[u]|0)>>2,a[c]=a[l],a[c+1]=a[l+1],a[c+2]=a[l+2],a[c+3]=a[l+3],l=n+1|0,(l|0)<(a[k]|0)){n=l}else{break}}k=n-3|0}else{k=-4}a:do{if(0<(a[d]|0)){t=0;for(n=k;;){c=((t<<4)+a[e]|0)>>2;l=((n<<4)+a[u]|0)>>2;a[c]=a[l];a[c+1]=a[l+1];a[c+2]=a[l+2];a[c+3]=a[l+3];l=t+1|0;if((l|0)>=(a[d]|0)){break a}t=l;n=n+1|0}}}while(0);d=(w<<3)+m|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);zc(q,(D<<4)+a[u]|0,(s-(i-d))/d,(D<<4)+a[g]|0,a[e]);E(m)}h=r}function nn(b){E(a[b>>2]);E(a[b+4>>2]);E(b)}function rf(u,s){var g,e=h;g=u>>2;u=h;h=h+32|0;a[u>>2]=a[g];a[u+4>>2]=a[g+1];a[u+8>>2]=a[g+2];a[u+12>>2]=a[g+3];a[u+16>>2]=a[g+4];a[u+20>>2]=a[g+5];a[u+24>>2]=a[g+6];a[u+28>>2]=a[g+7];g=s>>2;s=h;h=h+32|0;a[s>>2]=a[g];a[s+4>>2]=a[g+1];a[s+8>>2]=a[g+2];a[s+12>>2]=a[g+3];a[s+16>>2]=a[g+4];a[s+20>>2]=a[g+5];a[s+24>>2]=a[g+6];a[s+28>>2]=a[g+7];g=u+16|0;var l=s|0;if((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])<(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])){return h=e,0}g=s+16|0;l=u|0;if((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])<(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])){return h=e,0}g=u+24|0;l=s+8|0;if((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])<(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])){return h=e,0}g=s+24|0;l=u+8|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])>=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);h=e;return g&1}function en(u,s,g,e,l){var c,d,k,r,q,m,w,i,n=h;h=h+1664|0;var t=n+64,y=n+864,z=Za(20);a[z+16>>2]=1;var B=a[e+4>>2]-1|0;c=(B|0)/3&-1;a:do{if(2<(B|0)){d=e|0;var F=n|0;i=n>>2;w=(n+16|0)>>2;m=(n+32|0)>>2;k=(n+48|0)>>2;for(var D=z,S=0;;){r=3*S&-1;var Gb=a[d>>2];q=((r<<4)+Gb|0)>>2;a[i]=a[q];a[i+1]=a[q+1];a[i+2]=a[q+2];a[i+3]=a[q+3];q=((r+1<<4)+Gb|0)>>2;a[w]=a[q];a[w+1]=a[q+1];a[w+2]=a[q+2];a[w+3]=a[q+3];q=((r+2<<4)+Gb|0)>>2;a[m]=a[q];a[m+1]=a[q+1];a[m+2]=a[q+2];a[m+3]=a[q+3];r=((r+3<<4)+Gb|0)>>2;a[k]=a[r];a[k+1]=a[r+1];a[k+2]=a[r+2];a[k+3]=a[r+3];D=pj(F,D);S=S+1|0;if((S|0)>=(c|0)){break a}}}}while(0);if(0!=(z|0)){m=y|0;w=t|0;k=t>>2;e=y>>2;i=z;for(F=D=0;;){B=a[i+16>>2];d=(F<<4)+t|0;c=(F<<4)+y|0;r=i|0;var S=i+8|0,A=D,D=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]);r=(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3]);var I=B,Gb=d,S=c;q=l;if(0==(A|0)){var Z=I|0,Z=(a[b>>2]=a[Z>>2],a[b+4>>2]=a[Z+4>>2],f[b>>3]),I=I+8|0,C=(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3]),I=C,A=Z,Z=2*D-Z,C=2*r-C}else{Z=A|0,Z=(a[b>>2]=a[Z>>2],a[b+4>>2]=a[Z+4>>2],f[b>>3]),A=A+8|0,C=(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]),0==(I|0)?(I=2*r-C,A=2*D-Z):(A=I|0,A=(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]),I=I+8|0,I=(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3]))}Z=Math.atan2(C-r,Z-D);I=Math.atan2(I-r,A-D)-Z;Z+=.5*(0<I?I-6.283185307179586:I);I=Math.cos(Z)*q;q*=Math.sin(Z);Z=q+r;A=Gb|0;f[b>>3]=I+D;a[A>>2]=a[b>>2];a[A+4>>2]=a[b+4>>2];Gb=Gb+8|0;f[b>>3]=Z;a[Gb>>2]=a[b>>2];a[Gb+4>>2]=a[b+4>>2];r-=q;Gb=S|0;f[b>>3]=D-I;a[Gb>>2]=a[b>>2];a[Gb+4>>2]=a[b+4>>2];D=S+8|0;f[b>>3]=r;a[D>>2]=a[b>>2];a[D+4>>2]=a[b+4>>2];D=F+1|0;F=0==(B|0);F|50==(D|0)?(on(u,s,g,D,w,m),d>>=2,a[k]=a[d],a[k+1]=a[d+1],a[k+2]=a[d+2],a[k+3]=a[d+3],c>>=2,a[e]=a[c],a[e+1]=a[c+1],a[e+2]=a[c+2],a[e+3]=a[c+3],c=1):c=D;if(F){var K=z;break}else{D=i,i=B,F=c}}for(;!(u=a[K+16>>2],E(K),0==(u|0));){K=u}}h=n}function pj(u,s){var g,e,l=h;h=h+144|0;if(0==(Jm(u)|0)){return g=l|0,e=l+64|0,zc(l+128,u,.5,g,e),g=pj(e,pj(g,s)),h=l,g}g=s+16|0;1==(a[g>>2]|0)&&(a[g>>2]=0,e=s>>2,g=u>>2,a[e]=a[g],a[e+1]=a[g+1],a[e+2]=a[g+2],a[e+3]=a[g+3]);g=u+48|0;e=u+56|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);var c=Za(20);a[c+16>>2]=0;f[b>>3]=g;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];g=c+8|0;f[b>>3]=e;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];a[s+16>>2]=c;h=l;return c}function on(b,s,g,e,l,c){var d,f=e<<1;d=a[g>>2];if(0<(d|0)){for(var r=a[s>>2],h=0,m=0;;){var w=a[r+(h<<2)>>2]+m|0,h=h+1|0;if((h|0)<(d|0)){m=w}else{break}}r=1<(d|0)?d:1}else{w=r=0}d=d+1|0;a[g>>2]=d;g=Oa(a[s>>2],d<<2);a[s>>2]=g;a[g+(r<<2)>>2]=f;g=Oa(a[b>>2],w+f<<4);a[b>>2]=g;if(0<(e|0)){f=f-1+w|0;for(s=0;;){d=((s+w<<4)+g|0)>>2;g=((s<<4)+l|0)>>2;a[d]=a[g];a[d+1]=a[g+1];a[d+2]=a[g+2];a[d+3]=a[g+3];d=((f-s<<4)+a[b>>2]|0)>>2;g=((s<<4)+c|0)>>2;a[d]=a[g];a[d+1]=a[g+1];a[d+2]=a[g+2];a[d+3]=a[g+3];s=s+1|0;if((s|0)==(e|0)){break}g=a[b>>2]}}}function Tf(b,s){var g,e,l=h;h=h+144|0;g=l+128;var c=a[b>>2];ac(g,128,l|0);Cb(g,s);e=(g+4|0)>>2;var d=a[e];d>>>0<a[g+8>>2]>>>0||(qa(g,1),d=a[e]);n[d]=0;d=a[g>>2];a[e]=d;var f=c+268|0;e=Jd(d,a[f>>2],ud);var r=0!=(e|0),f=r?Jd(0,a[f>>2],ud):0,r=(0!=(f|0)&1)+(r&1)|0;1==(r|0)?(f=a[b+156>>2],c=(qj(c,e,f)|0)==(f|0)&1):2==(r|0)?(e=qj(c,e,0),c=qj(c,f,a[b+152>>2]),f=-1<(c|e|0)&(e|0)>(c|0),r=a[b+156>>2],c=(r|0)<=((f?e:c)|0)&((f?c:e)|0)<=(r|0)&1):c=0;g=(g+12|0)>>2;g=a[g];Xb(d,g);h=l;return c}function qj(b,s,g){var e=0,l=a[b+124>>2],c=n[s];if(97==c<<24>>24&&0==($(s,5378388)|0)){var d;return g}for(var g=0,f=s;;){var r=n[f];if(0==r<<24>>24){var h=1,g=1760;break}if(10>((r&255)-48|0)>>>0){f=f+1|0}else{h=0;g=1759;break}}if(0!=(1759==g||1760==g?h:Wb)<<24>>24){return d=Ee(s)}b=a[b+276>>2];if(0==(b|0)){return-1}l=a[l+152>>2];for(h=1;;){if((h|0)>(l|0)){d=-1;e=1837;break}g=a[b+(h<<2)>>2];if(c<<24>>24==n[g]<<24>>24&&0==($(s,g)|0)){d=h;e=1834;break}h=h+1|0}if(1834==e||1837==e){return d}}function Tm(b,s,g){a:do{if(2>(a[b+152>>2]|0)){var e=1}else{var l=$b(g|0,a[1345356],5338228);if(0!=Tf(b,l)<<24>>24){e=1}else{if(0!=n[l]<<24>>24){e=0}else{var l=s,c=g;if(0==(Gg(l,c)|0)){e=1}else{for(var d=Gg(l,c);;){if(0==(d|0)){e=0;break a}var f=$b(d|0,a[1345500],5338228);if(0==n[f]<<24>>24){e=1;break a}if(0!=Tf(b,f)<<24>>24){e=1;break a}d=Hg(l,d,c)}}}}}}while(0);return e}function Um(u,s){var g,e,l,c,d,k,r,h,m=s>>2,w=0,i=a[u+148>>2],v=Bg(u);h=v>>2;a[h+1]=2;a[h+2]=s;a[h+3]=8;if(0!=(i&16777216|0)){if(2<fc[a[m+5]+206>>1]){var t=a[m+37]+16|0,y=72*(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),z=v+108|0;f[b>>3]=(0>y?y-.5:y+.5)&-1|0;a[z>>2]=a[b>>2];a[z+4>>2]=a[b+4>>2]}else{var B=v+108|0;f[b>>3]=0;a[B>>2]=a[b>>2];a[B+4>>2]=a[b+4>>2]}}var F=s|0;gj(u,a[m+30],F);if(0==(i&4259840|0)){var D=U(F,5356744)}else{if(0==(a[h+37]|0)&&0==(a[h+50]&1|0)){D=U(F,5356744);a[1315020]=D;pn(u);return}var S=rj(a[m+6]),Gb=s+32|0,A=(a[b>>2]=a[Gb>>2],a[b+4>>2]=a[Gb+4>>2],f[b>>3]),I=s+40|0,C=(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3]),T;var K=na(s|0,a[1345345],5338228);if(0==n[K]<<24>>24){var M=0}else{pf(K);var L=a[1312273];if(0==(L|0)){M=0}else{for(var E=5249092,yb=0,J=L;;){var R=0==($(J,5362648)|0)?1:yb,Y=E+4|0,H=a[Y>>2];if(0==(H|0)){M=R;break}else{E=Y,yb=R,J=H}}}}T=M;a:do{if(3==(S|0)|1==(S|0)){var Rb=a[m+7];r=Rb>>2;var G=0==vt(Rb)<<24>>24?1:0==(a[r+1]|T|0);if(0!=(Rb|0)&G){if(0==(i&524288|0)){w=1880}else{k=(Rb+8|0)>>2;var ea=a[k],wa=3>(ea|0)?1:ea,Fb=Rb+4|0,V=a[Fb>>2],W=1<(V|0)?V:1,X=a[r+10],ba=U(F,5347768),ma=0==(ba|0)?0:Ee(ba),ib=56<(ma-4|0)>>>0?20:ma;if(0==(a[Fb>>2]|T|0)){a[h+51]=0;var P=da(32),mc=P;d=(s+104|0)>>2;var O=A-(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),ga=P;f[b>>3]=O;a[ga>>2]=a[b>>2];a[ga+4>>2]=a[b+4>>2];c=(s+96|0)>>2;var Tb=C-.5*(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3]),N=P+8|0;f[b>>3]=Tb;a[N>>2]=a[b>>2];a[N+4>>2]=a[b+4>>2];var ua=A+(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),Da=P+16|0;f[b>>3]=ua;a[Da>>2]=a[b>>2];a[Da+4>>2]=a[b+4>>2];var Ja=C+.5*(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3]),Ab=P+24|0;f[b>>3]=Ja;a[Ab>>2]=a[b>>2];a[Ab+4>>2]=a[b+4>>2];var ra=mc,aa=2}else{var ya=a[k];do{if(3>(ya|0)){var ja=Rb+28|0;if(0==(a[b>>2]=a[ja>>2],a[b+4>>2]=a[ja+4>>2],f[b>>3])){var la=Rb+20|0;if(0==(a[b>>2]=a[la>>2],a[b+4>>2]=a[la+4>>2],f[b>>3])){var va=v+204|0;if(0!=(a[r]|0)){a[va>>2]=1;var oa=da(32),ka=oa,Ea=oa;f[b>>3]=A;a[Ea>>2]=a[b>>2];a[Ea+4>>2]=a[b+4>>2];var Ka=oa+8|0;f[b>>3]=C;a[Ka>>2]=a[b>>2];a[Ka+4>>2]=a[b+4>>2];var Na=(W<<1)-1|0,Ba=(Na<<4)+X|0,Wa=A+(a[b>>2]=a[Ba>>2],a[b+4>>2]=a[Ba+4>>2],f[b>>3]),Q=oa+16|0;f[b>>3]=Wa;a[Q>>2]=a[b>>2];a[Q+4>>2]=a[b+4>>2];var Rd=(Na<<4)+X+8|0,Ra=C+(a[b>>2]=a[Rd>>2],a[b+4>>2]=a[Rd+4>>2],f[b>>3]),bb=oa+24|0;f[b>>3]=Ra;a[bb>>2]=a[b>>2];a[bb+4>>2]=a[b+4>>2];ra=ka;aa=2;break a}a[va>>2]=2;var Xa=(W<<1)-1|0,Sa=(Xa<<4)+X|0,ca=(Xa<<4)+X+8|0,Va;var Ta=(a[b>>2]=a[Sa>>2],a[b+4>>2]=a[Sa+4>>2],f[b>>3]),Aa=(a[b>>2]=a[ca>>2],a[b+4>>2]=a[ca+4>>2],f[b>>3]),fb=ib,Ca=6.283185307179586/(fb|0),Ya=da(fb<<4);if(0<(fb|0)){for(var $a=0,La=0;;){var pa=(La<<4)+Ya|0;f[b>>3]=Math.cos($a)*Ta;a[pa>>2]=a[b>>2];a[pa+4>>2]=a[b+4>>2];var Ga=(La<<4)+Ya+8|0;f[b>>3]=Math.sin($a)*Aa;a[Ga>>2]=a[b>>2];a[Ga+4>>2]=a[b+4>>2];var Fa=La+1|0;if((Fa|0)==(fb|0)){break}else{$a+=Ca,La=Fa}}}Va=Ya;if(0<(ib|0)){var ia=0}else{ra=Va;aa=ib;break a}for(;;){l=((ia<<4)+Va|0)>>2;var nb=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3])+A;f[b>>3]=nb;a[l]=a[b>>2];a[l+1]=a[b+4>>2];e=((ia<<4)+Va+8|0)>>2;var jb=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])+C;f[b>>3]=jb;a[e]=a[b>>2];a[e+1]=a[b+4>>2];var cb=ia+1|0;if((cb|0)==(ib|0)){ra=Va;aa=ib;break a}else{ia=cb}}}}}}while(0);var ha=Math.a(ya,W-1|0);a[h+51]=2;var kb=a[k];if((kb|0)<(ib|0)){var Kb=da(wa<<4);if(0<(wa|0)){for(var Ma=0;;){var ld=Ma+ha|0,lb=(ld<<4)+X|0,rb=A+(a[b>>2]=a[lb>>2],a[b+4>>2]=a[lb+4>>2],f[b>>3]),ab=(Ma<<4)+Kb|0;f[b>>3]=rb;a[ab>>2]=a[b>>2];a[ab+4>>2]=a[b+4>>2];var db=(ld<<4)+X+8|0,ob=C+(a[b>>2]=a[db>>2],a[b+4>>2]=a[db+4>>2],f[b>>3]),pb=(Ma<<4)+Kb+8|0;f[b>>3]=ob;a[pb>>2]=a[b>>2];a[pb+4>>2]=a[b+4>>2];var ub=Ma+1|0;if((ub|0)==(wa|0)){ra=Kb;aa=wa;break a}else{Ma=ub}}}else{ra=Kb,aa=wa}}else{var gb=(kb|0)/(ib|0)&-1,sb=da(ib<<4);if(0<(ib|0)){for(var Ia=0,vb=0;;){var Ua=vb+ha|0,sa=(Ua<<4)+X|0,gf=A+(a[b>>2]=a[sa>>2],a[b+4>>2]=a[sa+4>>2],f[b>>3]),qb=(Ia<<4)+sb|0;f[b>>3]=gf;a[qb>>2]=a[b>>2];a[qb+4>>2]=a[b+4>>2];var Bb=(Ua<<4)+X+8|0,sc=C+(a[b>>2]=a[Bb>>2],a[b+4>>2]=a[Bb+4>>2],f[b>>3]),xb=(Ia<<4)+sb+8|0;f[b>>3]=sc;a[xb>>2]=a[b>>2];a[xb+4>>2]=a[b+4>>2];var za=Ia+1|0;if((za|0)==(ib|0)){ra=sb;aa=ib;break a}else{Ia=za,vb=vb+gb|0}}}else{ra=sb,aa=ib}}}}}else{w=1880}}else{w=1880}}while(0);if(1880==w){a[h+51]=0;var Nb=da(32),Jb=s+104|0,qa=A-(a[b>>2]=a[Jb>>2],a[b+4>>2]=a[Jb+4>>2],f[b>>3]);f[b>>3]=qa;a[Nb>>2]=a[b>>2];a[Nb+4>>2]=a[b+4>>2];g=(s+96|0)>>2;var xa=C-.5*(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]),Ic=Nb+8|0;f[b>>3]=xa;a[Ic>>2]=a[b>>2];a[Ic+4>>2]=a[b+4>>2];var fa=s+112|0,Za=A+(a[b>>2]=a[fa>>2],a[b+4>>2]=a[fa+4>>2],f[b>>3]),Ha=Nb+16|0;f[b>>3]=Za;a[Ha>>2]=a[b>>2];a[Ha+4>>2]=a[b+4>>2];var Oa=C+.5*(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]),ta=Nb+24|0;f[b>>3]=Oa;a[ta>>2]=a[b>>2];a[ta+4>>2]=a[b+4>>2];ra=Nb;aa=2}0==(i&8192|0)&&Wd(u,ra,ra,aa);a[h+53]=ra;a[h+52]=aa;D=U(F,5356744)}a[1315020]=D;pn(u)}function vt(u){if(4!=(a[u+8>>2]|0)){return 0}var s=u+12|0,s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]);if(0!=(((0>s?s-.5:s+.5)&-1|0)%90|0)){return 0}s=u+20|0;if(0!=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3])){return 0}u=u+28|0;u=0==(a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3]);return u&1}function gj(b,s,g){var e=0,l=h;h=h+144|0;var c=l+128,d=U(g,5353856),f=U(g,5360720),r=U(g,5327484);ac(c,128,l|0);s=0==(s|0)?0:a[s>>2];if(0==(d|0)){e=1906}else{if(0==n[d]<<24>>24){e=1906}else{var q=d}}1906==e&&(q=U(g,5355416));e=Ih(a[a[a[a[b>>2]+128>>2]+44>>2]+92>>2],g,c);dj(a[b+16>>2],a[b+148>>2],s,q,f,r,e,g);Xb(a[c>>2],a[c+12>>2]);h=l}function Qm(u){var s,g,e=u>>2,l=h;h=h+16|0;var c=l+8,d=a[e+48],k=a[e+49],r=a[e+40],q=a[e+41],m=u+356|0;0==(a[m>>2]|0)?c=q:(Mh(l,d,k),d=a[l>>2],k=a[l+4>>2],Mh(c,r,q),r=a[c>>2],c=a[c+4>>2]);var d=d|0,q=u+316|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),w=u+236|0;s=d*q-(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]);w=u+284|0;f[b>>3]=s;a[w>>2]=a[b>>2];a[w+4>>2]=a[b+4>>2];w=k|0;k=u+324|0;k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);g=u+244|0;g=w*k-(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);var i=u+292|0;f[b>>3]=g;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];i=u+300|0;f[b>>3]=s+q;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];s=u+308|0;f[b>>3]=g+k;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];s=u+464|0;0==(a[a[e+3]+28>>2]|0)?(g=s>>2,s=(u+448|0)>>2,a[g]=a[s],a[g+1]=a[s+1],a[g+2]=a[s+2],a[g+3]=a[s+3]):(s|=0,g=a[s>>2],i=a[e+112],a[s>>2]=(g|0)<(i|0)?g:i,s=u+468|0,g=a[s>>2],i=a[e+113],a[s>>2]=(g|0)<(i|0)?g:i,s=u+472|0,g=a[s>>2],i=a[e+114],a[s>>2]=(g|0)>(i|0)?g:i,s=u+476|0,g=a[s>>2],i=a[e+115],a[s>>2]=(g|0)>(i|0)?g:i);e=a[e+37];s=u+332|0;s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]);0==(e&128|0)?(r=s+q*(d-.5*(r|0)),d=u+252|0,f[b>>3]=r,a[d>>2]=a[b>>2],a[d+4>>2]=a[b+4>>2],d=u+340|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])+k*(w-.5*(c|0))-1,c=u+260|0,f[b>>3]=d,a[c>>2]=a[b>>2],a[c+4>>2]=a[b+4>>2],w=r+(q+1),c=u+268|0,f[b>>3]=w,a[c>>2]=a[b>>2],a[c+4>>2]=a[b+4>>2],q=d+(k+1),c=u+276|0,f[b>>3]=q,a[c>>2]=a[b>>2],a[c+4>>2]=a[b+4>>2],c=r,r=d,k=w):(c=u+360|0,r=.5*(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),c=s-r,q=u+252|0,f[b>>3]=c,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=u+340|0,d=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),q=u+368|0,w=.5*(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),q=d-w,k=u+260|0,f[b>>3]=q,a[k>>2]=a[b>>2],a[k+4>>2]=a[b+4>>2],k=s+r,r=u+268|0,f[b>>3]=k,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],d+=w,r=u+276|0,f[b>>3]=d,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],r=q,q=d);0==(a[m>>2]|0)?(m=u+376|0,k=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),m=u+348|0,m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),d=u+496|0,f[b>>3]=k/m-c,a[d>>2]=a[b>>2],a[d+4>>2]=a[b+4>>2],0==(e&4096|0)?(e=u+384|0,m=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])/m-r):(e=u+384|0,m=-q-(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])/m),u=u+504|0,f[b>>3]=m,a[u>>2]=a[b>>2],a[u+4>>2]=a[b+4>>2]):(r=u+376|0,m=u+384|0,w=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),m=u+348|0,d=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),m=u+496|0,u=u+504|0,f[b>>3]=-q-w/d,a[u>>2]=a[b>>2],a[u+4>>2]=a[b+4>>2],0==(e&4096|0)?(u=r|0,u=(a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3])/d-c):(u=r|0,u=-k-(a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3])/d),m|=0,f[b>>3]=u,a[m>>2]=a[b>>2],a[m+4>>2]=a[b+4>>2]);h=l}function ij(b,s,g){var e,l=a[b>>2]+28|0;a[l>>2]=a[l>>2]+1|0;(l=0!=(g&4|0))||Eg(b,s,g);a:do{if(0==(g&1|0)){if(0!=(g&16|0)){sj(b);var c=s;e=(s+20|0)>>2;var d=ha(a[e]);b:do{if(0!=(d|0)){for(var f=s+28|0,r=d;;){var h=zb(c,r);c:do{if(0!=(h|0)){for(var m=h;;){if(Sf(b,m),m=Db(a[f>>2],m),0==(m|0)){break c}}}}while(0);r=sa(a[e],r);if(0==(r|0)){break b}}}}while(0);tj(b);uj(b);c=ha(a[e]);b:do{if(0!=(c|0)){for(d=c;;){if(qf(b,d),d=sa(a[e],d),0==(d|0)){break b}}}}while(0);vj(b)}else{if(0==(g&8|0)){e=s;c=s+20|0;f=ha(a[c>>2]);if(0==(f|0)){break}for(d=s+28|0;;){qf(b,f);r=zb(e,f);b:do{if(0!=(r|0)){for(h=r;;){if(qf(b,a[h+12>>2]),Sf(b,h),h=Db(a[d>>2],h),0==(h|0)){break b}}}}while(0);f=sa(a[c>>2],f);if(0==(f|0)){break a}}}uj(b);c=s;e=(s+20|0)>>2;d=ha(a[e]);b:do{if(0!=(d|0)){for(f=d;;){r=f;for(var h=0,m=s+212|0,w=s+208|0,i=r|0,n=1;;){if((n|0)>(a[w>>2]|0)){var t=1,h=2003;break}if(0==(fd(a[a[m>>2]+(n<<2)>>2],i)|0)){n=n+1|0}else{t=0;h=2002;break}}h=2003==h||2002==h?t:Wb;0!=h<<24>>24&&qf(b,r);f=sa(a[e],f);if(0==(f|0)){break b}}}}while(0);vj(b);sj(b);d=ha(a[e]);b:do{if(0!=(d|0)){f=s+28|0;for(r=d;;){h=zb(c,r);c:do{if(0!=(h|0)){for(m=h;;){w=m;for(var i=0,n=s+212|0,y=s+208|0,z=w|0,B=1;;){if((B|0)>(a[y>>2]|0)){var F=1,i=2009;break}if(0==(fd(a[a[n>>2]+(B<<2)>>2],z)|0)){B=B+1|0}else{F=0;i=2008;break}}i=2008==i||2009==i?F:Wb;0!=i<<24>>24&&Sf(b,w);m=Db(a[f>>2],m);if(0==(m|0)){break c}}}}while(0);r=sa(a[e],r);if(0==(r|0)){break b}}}}while(0);tj(b)}}else{uj(b);c=s;e=(s+20|0)>>2;d=ha(a[e]);b:do{if(0!=(d|0)){for(f=d;;){if(qf(b,f),f=sa(a[e],f),0==(f|0)){break b}}}}while(0);vj(b);sj(b);d=ha(a[e]);b:do{if(0!=(d|0)){f=s+28|0;for(r=d;;){h=zb(c,r);c:do{if(0!=(h|0)){for(m=h;;){if(Sf(b,m),m=Db(a[f>>2],m),0==(m|0)){break c}}}}while(0);r=sa(a[e],r);if(0==(r|0)){break b}}}}while(0);tj(b)}}while(0);l&&Eg(b,s,g)}function Oh(a){return 0==(a|0)?0:0==n[a]<<24>>24?0:a}function Ig(b,s){var g;g=(b+12|0)>>2;var e=a[g];a[g]=e+4|0;a[e>>2]=s;a[g]>>>0<a[b+4>>2]>>>0||(a[g]=a[b>>2])}function Jg(b){var s;s=(b+8|0)>>2;var g=a[s];if((g|0)==(a[b+12>>2]|0)){return 0}var e=g+4|0;a[s]=e;g=a[g>>2];if(e>>>0<a[b+4>>2]>>>0){return g}a[s]=a[b>>2];return g}function ec(b){var s=0,g=b+224|0,e=a[g>>2];if((e|0)!=(b|0)&0!=(e|0)){b=g,g=e}else{var l;return b}for(;;){e=a[g+224>>2];if(0==(e|0)){l=g;s=2029;break}a[b>>2]=e;b=e+224|0;g=a[b>>2];if(!((g|0)!=(e|0)&0!=(g|0))){l=e;s=2030;break}}if(2030==s||2029==s){return l}}function qn(b){a[b+220>>2]=1;a[b+224>>2]=0;n[b+165|0]=0}function Rm(u,s){var g,e,l,c=h;h=h+4|0;a[c>>2]=1e3;var d=Za(16e3),k=s|0;if(0<(a[k>>2]|0)){var r=u+252|0,q=u+16|0,m=u+60|0,w=a[s+8>>2];e=w>>2;for(var n=d,d=1,v=0,t=0;;){l=(w|0)>>2;g=a[l];if(8==(g|0)){Sb(u,a[e+1]),l=t}else{if(2==(g|0)|3==(g|0)){0!=(rf(w+44|0,r)|0)&&(e=g=w+4|0,n=wj(n,c,a[g+4>>2],a[e>>2]),tc(u,n,a[e>>2],2==(a[l]|0)&1)),l=t}else{if(9==(g|0)){eb(u,a[e+1]),l=t}else{if(6==(g|0)){0!=(rf(w+44|0,r)|0)&&(l=e=w+4|0,n=wj(n,c,a[e+4>>2],a[l>>2]),td(u,n,a[l>>2])),l=t}else{if(4==(g|0)|5==(g|0)){0!=(rf(w+44|0,r)|0)&&(e=g=w+4|0,n=wj(n,c,a[g+4>>2],a[e>>2]),hf(u,n,a[e>>2],0,0,4==(a[l]|0)&1)),l=t}else{if(12==(g|0)){0!=(d|0)&&aa(0,5376328,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),l=t,d=0}else{if(0==(g|0)|1==(g|0)){if(0!=(rf(w+44|0,r)|0)){g=w+4|0;e=(w+20|0)>>2;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])-(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);var y=n|0;f[b>>3]=g;a[y>>2]=a[b>>2];a[y+4>>2]=a[b+4>>2];y=w+12|0;g=(w+28|0)>>2;var y=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3])-(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]),z=n+8|0;f[b>>3]=y;a[z>>2]=a[b>>2];a[z+4>>2]=a[b+4>>2];e=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);y=n+16|0;f[b>>3]=e;a[y>>2]=a[b>>2];a[y+4>>2]=a[b+4>>2];e=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]);g=n+24|0;f[b>>3]=e;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];Kg(u,n,0==(a[l]|0)&1)}l=t}else{7==(g|0)?(0!=(rf(w+44|0,r)|0)&&(l=w+4|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),g=n|0,f[b>>3]=l,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],g=w+12|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),y=n+8|0,f[b>>3]=g,a[y>>2]=a[b>>2],a[y+4>>2]=a[b+4>>2],xj(u,l,g,a[e+19])),l=t):11==(g|0)?(pf(a[e+1]),Dd(a[q>>2],a[m>>2],5249092),l=5249092):l=t}}}}}}}g=n;v=v+1|0;if((v|0)<(a[k>>2]|0)){w=w+80|0,e=w>>2,n=g,t=l}else{break}}0!=(l|0)&&Dd(a[q>>2],a[m>>2],a[a[u>>2]+296>>2]);k=g}else{k=d}E(k);h=c}function wj(u,s,g,e){var l=a[s>>2];(l|0)<(e|0)&&(l<<=1,l=(l|0)>(e|0)?l:e,u=Oa(u,l<<4),a[s>>2]=l);s=u;if(0<(e|0)){u=0}else{return s}for(;;){var l=g+(24*u&-1)|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),c=(u<<4)+s|0;f[b>>3]=l;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];l=g+(24*u&-1)+8|0;l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);c=(u<<4)+s+8|0;f[b>>3]=l;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];u=u+1|0;if((u|0)==(e|0)){break}}return s}function Pm(b,s){var g=s+208|0;if(1<=(a[g>>2]|0)){for(var e=s+212|0,l=1;;){var c=a[a[e>>2]+(l<<2)>>2];Pm(b,c);var c=c|0,d=U(c,5335528);0!=(d|0)&&0!=n[d]<<24>>24&&eb(b,d);d=U(c,5335284);0!=(d|0)&&0!=n[d]<<24>>24&&Sb(b,d);c=U(c,5334160);0!=(c|0)&&0!=n[c]<<24>>24&&eb(b,c);l=l+1|0;if((l|0)>(a[g>>2]|0)){break}}}}function rn(b){var s,g=da(16);s=g>>2;var b=2>(b|0)?2:b,e=da(b<<2);a[s]=e;a[s+3]=e;a[s+2]=e;a[s+1]=(b<<2)+e|0;return g}function ve(b,s,g){0!=(s|0)&&(b=tb(b,a[s+8>>2]),0!=(b|0)&&0!=n[b]<<24>>24&&(g=Ee(b),g=0>(g|0)?0:g));return g}function lc(b,s,g,e){0==(s|0)|0==(b|0)?e=g:(b=tb(b,a[s+8>>2]),0==(b|0)?e=g:0==n[b]<<24>>24?e=g:(g=Oe(b,Ac),e=g<e?e:g));return e}function $b(b,s,g){return 0==(s|0)|0==(b|0)?g:b=tb(b,a[s+8>>2])}function na(a,b,g){a=$b(a,b,g);return 0!=(a|0)&&0!=n[a]<<24>>24?a:g}function Ph(a){return Xd(a)}function Lg(b,s){var g,e;if((b|0)==(s|0)){return b}e=b+224|0;if(0==(a[e>>2]|0)){a[e>>2]=b;a[b+220>>2]=1;var l=b}else{l=ec(b)}e=l>>2;g=s+224|0;if(0==(a[g>>2]|0)){a[g>>2]=s;a[s+220>>2]=1;var c=s}else{c=ec(s)}g=c>>2;(a[e+4]|0)>(a[g+4]|0)?(a[e+56]=c,l=c+220|0,a[l>>2]=a[l>>2]+a[e+55]|0,e=c):(a[g+56]=l,e=l+220|0,a[e>>2]=a[e>>2]+a[g+55]|0,e=l);return e}function zc(u,s,g,e,l){var c,d,k=h;h=h+576|0;for(var r=0;!(d=((r<<4)+k|0)>>2,c=((r<<4)+s|0)>>2,a[d]=a[c],a[d+1]=a[c+1],a[d+2]=a[c+2],a[d+3]=a[c+3],c=r+1|0,4==(c|0));){r=c}s=1-g;d=1;for(c=3;;){a:do{if(0<=(3-d|0)){for(var r=d-1|0,q=k+(96*r&-1)|0,m=k+(96*r&-1)+8|0,w=0,i=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]);;){var q=w+1|0,n=(q<<4)+k+(96*r&-1)|0,n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),t=(w<<4)+k+(96*d&-1)|0;f[b>>3]=s*i+n*g;a[t>>2]=a[b>>2];a[t+4>>2]=a[b+4>>2];i=(q<<4)+k+(96*r&-1)+8|0;t=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);w=(w<<4)+k+(96*d&-1)+8|0;f[b>>3]=s*m+t*g;a[w>>2]=a[b>>2];a[w+4>>2]=a[b+4>>2];if((q|0)==(c|0)){break a}else{w=q,i=n,m=t}}}}while(0);d=d+1|0;if(4==(d|0)){break}else{c=c-1|0}}a:do{if(0!=(e|0)){for(c=0;;){if(s=((c<<4)+e|0)>>2,g=(k+(96*c&-1)|0)>>2,a[s]=a[g],a[s+1]=a[g+1],a[s+2]=a[g+2],a[s+3]=a[g+3],g=c+1|0,4==(g|0)){break a}else{c=g}}}}while(0);if(0!=(l|0)){for(s=0;!(g=((s<<4)+l|0)>>2,e=((s<<4)+k+(96*(3-s)&-1)|0)>>2,a[g]=a[e],a[g+1]=a[e+1],a[g+2]=a[e+2],a[g+3]=a[e+3],e=s+1|0,4==(e|0));){s=e}}u>>=2;l=k+288|0;l>>=2;a[u]=a[l];a[u+1]=a[l+1];a[u+2]=a[l+2];a[u+3]=a[l+3];h=k}function sn(b){for(var s=0,g=0;;){var e=a[1345488];if(1024>(e-g|0)){e=e+1024|0;a[1345488]=e;var l=Oa(a[1345487],e);a[1345487]=l;e=a[1345488]}else{l=a[1345487]}e=Hf(l+g|0,e-g|0,b);if(0==(e|0)){break}e=xa(e)+g|0;l=a[1345487];if(10==n[l+(e-1)|0]<<24>>24){var c=e,d=l,s=2143;break}else{g=e}}if(2143==s){return d=0<(c|0)?d:0}d=a[1345487];return d=(b=0<(g|0))?d:0}function yj(b,s,g){var e=0==(b|0),l=0;a:for(;;){var c=a[s+(l<<2)>>2];if(0==(c|0)){break}do{if(!e&&n[b]<<24>>24==n[c]<<24>>24&&0==($(b,c)|0)){break a}}while(0);l=l+1|0}return a[g+(l<<2)>>2]}function Xd(a){return 0==(a|0)?0:0==n[a]<<24>>24?0:0==(Eb(a,5333780)|0)?0:0==(Eb(a,5327700)|0)?0:0==(Eb(a,5346992)|0)?1:0==(Eb(a,5375956)|0)?1:10>((n[a]<<24>>24)-48|0)>>>0?Ee(a)&255:0}function Eb(a,b){for(var g=0,e=a,l=b;;){var c=n[e];if(0==c<<24>>24){var d=0;break}if((se(c&255)|0)!=(se(ca[l])|0)){g=2164;break}e=e+1|0;l=l+1|0}2164==g&&(d=ca[e]);return se(d)-se(ca[l])|0}function tn(u,s,g,e,l){var c=u|0;f[b>>3]=s-e;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];u=u+8|0;f[b>>3]=g-l;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}function ln(u,s,g,e,l){var c=0,d=h;h=h+80|0;var k=d+64;a:do{if(0<(g|0)){for(var r=1e+38,q=-1,m=-1,w=0;;){var i=a[s+(48*w&-1)>>2],n=a[s+(48*w&-1)+4>>2];b:do{if(0<(n|0)){for(var t=r,y=q,z=m,B=0;;){var F=(B<<4)+i|0,D=(B<<4)+i+8|0,F=(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3])-e,D=(a[b>>2]=a[D>>2],a[b+4>>2]=a[D+4>>2],f[b>>3])-l,F=F*F+D*D,t=(D=-1==(y|0)|F<t)?F:t,y=D?B:y,z=D?w:z,B=B+1|0;if((B|0)==(n|0)){var S=t,Gb=y,A=z;break b}}}else{S=r,Gb=q,A=m}}while(0);w=w+1|0;if((w|0)<(g|0)){r=S,q=Gb,m=A}else{var I=Gb,C=A;break a}}}else{C=I=-1}}while(0);s=a[s+(48*C&-1)>>2];I=(I|0)/3&-1;r=(((I|0)>=(g|0))<<31>>31)+I|0;g=(r<<4)+s|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);I=d|0;f[b>>3]=g;a[I>>2]=a[b>>2];a[I+4>>2]=a[b+4>>2];I=(r<<4)+s+8|0;I=(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3]);q=d+8|0;f[b>>3]=I;a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];q=r+1|0;m=(q<<4)+s|0;m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]);S=d+16|0;f[b>>3]=m;a[S>>2]=a[b>>2];a[S+4>>2]=a[b+4>>2];q=(q<<4)+s+8|0;q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);m=d+24|0;f[b>>3]=q;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];q=r+2|0;m=(q<<4)+s|0;m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]);S=d+32|0;f[b>>3]=m;a[S>>2]=a[b>>2];a[S+4>>2]=a[b+4>>2];q=(q<<4)+s+8|0;q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);m=d+40|0;f[b>>3]=q;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];q=r+3|0;r=(q<<4)+s|0;r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]);m=d+48|0;f[b>>3]=r;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];s=(q<<4)+s+8|0;q=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]);s=d+56|0;f[b>>3]=q;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];s=d|0;m=g-e;S=I-l;Gb=r-e;A=q-l;g=k|0;I=k+8|0;r=1;q=0;m=m*m+S*S;for(S=Gb*Gb+A*A;;){Gb=.5*(q+r);zc(k,s,Gb,0,0);var T=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),K=(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3]);if(1>Math.abs(m-S)){c=2179;break}if(1e-5>Math.abs(r-q)){c=2178;break}A=m<S;C=T-e;w=K-l;C=C*C+w*w;r=A?Gb:r;q=A?q:Gb;m=A?m:C;S=A?C:S}2178==c?(e=(u|0)>>2,f[b>>3]=T,a[e]=a[b>>2],a[e+1]=a[b+4>>2],u=(u+8|0)>>2,f[b>>3]=K,a[u]=a[b>>2],a[u+1]=a[b+4>>2],h=d):2179==c&&(e=(u|0)>>2,f[b>>3]=T,a[e]=a[b>>2],a[e+1]=a[b+4>>2],u=(u+8|0)>>2,f[b>>3]=K,a[u]=a[b>>2],a[u+1]=a[b+4>>2],h=d)}function un(u){var s=u|0,g=lc(s,a[1345343],.75,.01),e=u+48|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];g=lc(s,a[1345359],.5,.02);e=u+56|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];var l;a:{var g=na(s,a[1345349],5371884),e=0,g=0==(Oh(U(u|0,5348352))|0)?g:101==n[g]<<24>>24&&0==($(g,5343944)|0)?g:5340528,c=n[g];if(99==c<<24>>24){if(0!=($(g,5340528)|0)){var d=5380664,e=876}}else{d=5380664,e=876}b:do{if(876==e){for(;;){e=0;l=a[d>>2];if(0==(l|0)){break b}if(n[l]<<24>>24==c<<24>>24&&0==($(l,g)|0)){break}d=d+16|0}if(0!=(d|0)){l=g=d;break a}}}while(0);d=h;e=zj(g);0!=(e|0)?g=e:(e=a[1345370],c=e+1|0,a[1345370]=c,l=a[1345052],c=0==(l|0)?Za(c<<2):Oa(l,c<<2),a[1345052]=c,l=da(16),c=l>>2,a[a[1345052]+(e<<2)>>2]=l,a[c]=a[1345166],a[c+1]=a[1345167],a[c+2]=a[1345168],a[c+3]=a[1345169],e=Hb(g),a[c]=e,99==n[g]<<24>>24&&0==($(g,5340528)|0)?n[l+12|0]=1:(aa(0,5326212,(i=h,h=h+8|0,a[i>>2]=a[1345166],a[i+4>>2]=e,i)),n[l+12|0]=0),g=l);h=d;l=g}g=u+24|0;a[g>>2]=l;var k=tb(s,a[a[1345357]+8>>2]),d=lc(s,a[1345361],14,1),e=na(s,a[1345362],5377304),c=na(s,a[1345363],5374748);a[u+120>>2]=we(s,k,(0!=(Ve(k)|0)?2:0)|(2==(rj(l)|0)?4:0),d,e,c);l=a[1345342];0!=(l|0)&&(l=tb(s,a[l+8>>2]),0!=(l|0)&&0!=n[l]<<24>>24&&(a[u+124>>2]=we(s,l,0!=(Ve(l)|0)?2:0,d,e,c),d=a[u+20>>2]+149|0,n[d]|=16));n[u+160|0]=ve(s,a[1345348],0)&255;J[a[a[a[g>>2]+4>>2]>>2]](u)}function vn(u){var s,g,e,l=u>>2,c=h;h=h+112|0;var d=c+16,k=c+32,r=c+72;e=(u+16|0)>>2;var q=a[a[e]+20>>2];g=(c+8|0)>>2;a[g]=0;s=(d+8|0)>>2;a[s]=0;var m=a[1345507];if(0==(m|0)){m=0}else{var w=u|0,m=tb(w,a[m+8>>2]);if(0==(m|0)){m=0}else{if(0==n[m]<<24>>24){m=0}else{Aj(u,c);var i=0!=(Ve(m)|0)?2:0,v=c|0,t=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),y=a[g],v=a[c+12>>2];a[l+27]=we(w,m,i,t,y,v);m=q+149|0;n[m]|=1;n[u+126|0]=Xd($b(w,a[1345506],5333780));m=y}}}i=a[1345490];0!=(i|0)&&(w=u|0,i=tb(w,a[i+8>>2]),0!=(i|0)&&0!=n[i]<<24>>24&&(0==(m|0)?(Aj(u,c),v=c|0,t=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),g=a[g],v=a[c+12>>2]):g=m,a[l+30]=we(w,i,0!=(Ve(i)|0)?2:0,t,g,v),g=q+149|0,n[g]|=32));w=a[1345508];g=u|0;if(0==(w|0)){w=0}else{if(w=tb(g,a[w+8>>2]),0==(w|0)){w=0}else{if(0==n[w]<<24>>24){w=0}else{wn(u,c,d);var v=0!=(Ve(w)|0)?2:0,z=d|0,B=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3]),t=a[s],z=a[d+12>>2];a[l+28]=we(g,w,v,B,t,z);w=q+149|0;n[w]|=2;w=t}}}v=a[1345492];0!=(v|0)&&(v=tb(g,a[v+8>>2]),0!=(v|0)&&0!=n[v]<<24>>24&&(0==(w|0)?(wn(u,c,d),z=d|0,B=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3]),s=a[s],d=a[d+12>>2]):(s=w,d=z),a[l+29]=we(g,v,0!=(Ve(v)|0)?2:0,B,s,d),q=q+149|0,n[q]|=4));q=U(g,5375068);0!=(q|0)&&0!=n[q]<<24>>24&&(n[a[e]+161|0]=1);e=a[e];Bj(k,a[a[a[e+24>>2]+4>>2]+8>>2],e,q);k>>=2;e=(u+28|0)>>2;for(q=k+10;k<q;k++,e++){a[e]=a[k]}0!=xn(u,a[1345493])<<24>>24&&(n[u+58|0]=0);k=U(g,5377776);0!=(k|0)&&0!=n[k]<<24>>24&&(n[a[l+3]+161|0]=1);l=a[l+3];Bj(r,a[a[a[l+24>>2]+4>>2]+8>>2],l,k);k=r>>2;e=(u+68|0)>>2;for(q=k+10;k<q;k++,e++){a[e]=a[k]}0!=xn(u,a[1345509])<<24>>24&&(n[u+98|0]=0);h=c}function Aj(u,s){var g=u|0,e=lc(g,a[1345510],14,1),c=s|0;f[b>>3]=e;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];a[s+8>>2]=na(g,a[1345511],5377304);a[s+12>>2]=na(g,a[1345512],5374748)}function wn(u,s,g){var e=s+8|0;0==(a[e>>2]|0)&&Aj(u,s);var u=u|0,c=s|0,c=lc(u,a[1345501],(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),1),d=g|0;f[b>>3]=c;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];a[g+8>>2]=na(u,a[1345502],a[e>>2]);a[g+12>>2]=na(u,a[1345503],a[s+12>>2])}function Bj(b,s,g,e){var c,d=h;h=h+80|0;var f=d+40,k=oc(e,58);if(0==(k|0)){J[s](f,g,e,0);var s=f>>2,k=a[s+9],f=a[s+8],r=a[s+7],q=a[s+6],m=a[s+5],w=a[s+4],i=a[s+3],v=a[s+2],g=a[s+1],s=a[s]}else{n[k]=0;f=k+1|0;J[s](d,g,e,f);c=d>>2;var s=a[c],g=a[c+1],v=a[c+2],i=a[c+3],w=a[c+4],m=a[c+5],q=a[c+6],r=a[c+7],t=a[c+8];c=a[c+9];n[k]=58;k=c&0|f;f=t&-1|0;r=r&-1|0;q=q&-1|0;m=m&-1|0;w=w&-1|0;i=i&-1|0;v=v&-1|0;g=g&-1|0;s=s&-1|0}b>>=2;a[b]=s&-1|0;a[b+1]=g&-1|0;a[b+2]=v&-1|0;a[b+3]=i&-1|0;a[b+4]=w&-1|0;a[b+5]=m&-1|0;a[b+6]=q&-1|0;a[b+7]=r&-1|0;a[b+8]=f&-1|0;a[b+9]=k&0|e;h=d}function xn(b,s){if(0==(s|0)){var g=0}else{g=tb(b|0,a[s+8>>2]),g=0==(g|0)?0:0==n[g]<<24>>24?0:0==Xd(g)<<24>>24&1}return g}function Mg(u,s){var g,e,c=h;h=h+32|0;g=u+52|0;var d,j=a[u+152>>2]&1,k,r,q,m;e=h;k=g>>2;d=h;h=h+32|0;a[d>>2]=a[k];a[d+4>>2]=a[k+1];a[d+8>>2]=a[k+2];a[d+12>>2]=a[k+3];a[d+16>>2]=a[k+4];a[d+20>>2]=a[k+5];a[d+24>>2]=a[k+6];a[d+28>>2]=a[k+7];k=s+56|0;r=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);k=s+64|0;k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);var j=0==j<<24>>24,w=s+24|0,w=(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]),i=s+32|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);m=.5*(j?w:i);q=r-m;r+=m;m=(d|0)>>2;if(q<(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3])){f[b>>3]=q,a[m]=a[b>>2],a[m+1]=a[b+4>>2]}q=(d+16|0)>>2;if(r>(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3])){f[b>>3]=r,a[q]=a[b>>2],a[q+1]=a[b+4>>2]}r=.5*(j?i:w);j=k-r;k+=r;r=(d+8|0)>>2;if(j<(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3])){f[b>>3]=j,a[r]=a[b>>2],a[r+1]=a[b+4>>2]}j=(d+24|0)>>2;if(k>(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3])){f[b>>3]=k,a[j]=a[b>>2],a[j+1]=a[b+4>>2]}k=c>>2;d>>=2;a[k]=a[d];a[k+1]=a[d+1];a[k+2]=a[d+2];a[k+3]=a[d+3];a[k+4]=a[d+4];a[k+5]=a[d+5];a[k+6]=a[d+6];a[k+7]=a[d+7];h=e;e=g>>2;g=c>>2;a[e]=a[g];a[e+1]=a[g+1];a[e+2]=a[g+2];a[e+3]=a[g+3];a[e+4]=a[g+4];a[e+5]=a[g+5];a[e+6]=a[g+6];a[e+7]=a[g+7];h=c}function oe(a,b,g){var e=0;if(0==(g|0)){var c;return 0}for(;;){var d=g-1|0;if(0==(g|0)){e=2250;break}if((se(ca[a])|0)!=(se(ca[b])|0)){e=2250;break}if(0==(d|0)){c=0;e=2255;break}if(0==n[a]<<24>>24){c=0;e=2253;break}if(0==n[b]<<24>>24){c=0;e=2256;break}a=a+1|0;b=b+1|0;g=d}if(2250==e){return c=se(ca[a])-se(ca[b])|0}if(2255==e||2253==e||2256==e){return c}}function yn(b){var s=Qh(b,5355592),g=b+20|0,e=ha(a[g>>2]);a:do{if(0!=(e|0)){for(var c=b+28|0,d=e;;){var f=zb(b,d);b:do{if(0!=(f|0)){for(var k=f;;){var r=s,h=a[k+16>>2],m=a[k+12>>2];0==n[h+134|0]<<24>>24&&0==n[m+134|0]<<24>>24||(h=Cj(h,r),r=Cj(m,r),Rh(k|0,sf(a[h+20>>2],h,r)|0));k=Db(a[c>>2],k);if(0==(k|0)){break b}}}}while(0);d=sa(a[g>>2],d);if(0==(d|0)){break a}}}}while(0);g=s+20|0;e=ha(a[g>>2]);if(0!=(e|0)){for(;!(Ng(b,e|0),e=sa(a[g>>2],e),0==(e|0));){}}Pe(s)}function ic(a,b,g,e){b=Q(b,g);return 0!=(b|0)?b:a=J[e](a,g,5338228)}function wt(u,s){var g,e=h;g=u>>2;u=h;h=h+32|0;a[u>>2]=a[g];a[u+4>>2]=a[g+1];a[u+8>>2]=a[g+2];a[u+12>>2]=a[g+3];a[u+16>>2]=a[g+4];a[u+20>>2]=a[g+5];a[u+24>>2]=a[g+6];a[u+28>>2]=a[g+7];g=s>>2;s=h;h=h+32|0;a[s>>2]=a[g];a[s+4>>2]=a[g+1];a[s+8>>2]=a[g+2];a[s+12>>2]=a[g+3];a[s+16>>2]=a[g+4];a[s+20>>2]=a[g+5];a[s+24>>2]=a[g+6];a[s+28>>2]=a[g+7];g=u+16|0;var c=s|0;if((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])<(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])){return h=e,0}g=s+16|0;c=u|0;if((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])<(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])){return h=e,0}g=u+24|0;c=s+8|0;if((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])<(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])){return h=e,0}g=s+24|0;c=u+8|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])>=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);h=e;return g&1}function Dj(b){var s=h;h=h+20|0;var g=s+8,e=a[b>>2];a:do{if(35==n[e]<<24>>24){var c=n[e+1|0],d=c&255;b:do{if(120==c<<24>>24|88==c<<24>>24){for(var f=0,k=2,r=d;;){if(8<=(k|0)){var q=f,m=k,w=r;break b}var r=n[e+k|0],i=r&255;do{if(6>(r-65&255)){var v=i-55|0}else{if(6>(r-97&255)){v=i-87|0}else{if(10<=(r-48&255)){q=f;m=k;w=i;break b}v=i-48|0}}}while(0);f=(f<<4)+v|0;k=k+1|0;r=v}}else{f=0;k=1;for(r=d;;){if(8<=(k|0)){q=f;m=k;w=r;break b}r=n[e+k|0];i=r&255;if(10<=(r-48&255)){q=f;m=k;w=i;break b}f=(10*f&-1)-48+i|0;k=k+1|0;r=i}}}while(0);59!=(w|0)?(d=0,c=e):(d=q,c=m+(e+1)|0)}else{c=g|0;d=a[s>>2]=c;for(c=0;;){if(8<=(c|0)){d=0;c=e;break a}f=n[e+c|0];if(0==f<<24>>24){d=0;c=e;break a}else{if(59==f<<24>>24){break}}n[d]=f;d=d+1|0;c=c+1|0}n[d]=0;d=yh(s,5255256,252,8,104);0==(d|0)?(d=0,c=e):(d=a[d+4>>2],c=c+(e+1)|0)}}while(0);a[b>>2]=c;h=s;return d}function Ej(b){var s,g,e=h;h=h+1044|0;g=e>>2;var c=e+4;ac(c,1024,e+20|0);a[g]=b+1|0;var d=n[b],b=(c+4|0)>>2;s=(c+8|0)>>2;a:do{if(0!=d<<24>>24){for(var f=d;;){38==f<<24>>24?(f=Dj(e),f=0==(f|0)?38:f):f&=255;if(127>f>>>0){var k=a[b];k>>>0<a[s]>>>0||(qa(c,1),k=a[b]);a[b]=k+1|0;n[k]=f&255}else{var r=a[b],k=a[s],q=r>>>0>=k>>>0;2047>f>>>0?(q&&(qa(c,1),r=a[b],k=a[s]),q=r+1|0,a[b]=q,n[r]=(f>>>6|192)&255):(q&&(qa(c,1),r=a[b],k=a[s]),q=r+1|0,a[b]=q,n[r]=(f>>>12|224)&255,q>>>0<k>>>0?r=q:(qa(c,1),r=a[b],k=a[s]),q=r+1|0,a[b]=q,n[r]=(f>>>6&63|128)&255);q>>>0<k>>>0?k=q:(qa(c,1),k=a[b]);a[b]=k+1|0;n[k]=(f&63|128)&255}f=a[g];a[g]=f+1|0;f=n[f];if(0==f<<24>>24){break a}}}}while(0);g=a[b];if(g>>>0<a[s]>>>0){return n[g]=0,s=a[(c|0)>>2],a[b]=s,b=Hb(s),c=a[(c+12|0)>>2],Xb(s,c),h=e,b}qa(c,1);s=a[b];n[s]=0;s=a[(c|0)>>2];a[b]=s;b=Hb(s);c=a[(c+12|0)>>2];Xb(s,c);h=e;return b}function Fj(b){var s,g=h;h=h+1040|0;ac(g,1024,g+16|0);var e=n[b];s=(g+4|0)>>2;a:do{if(0==e<<24>>24){var c=a[s],d=g+8|0}else{for(var f=g+8|0,k=b,r=e;;){var q=k+1|0;if(127>(r&255)){k=a[s];if(k>>>0<a[f>>2]>>>0){var m=k}else{qa(g,1),m=a[s]}k=m+1|0;a[s]=k;n[m]=r;r=q}else{r=n[q]&63|r<<6,q=a[s],q>>>0<a[f>>2]>>>0?m=q:(qa(g,1),m=a[s]),q=m+1|0,a[s]=q,n[m]=r,r=k+2|0,k=q}q=n[r];if(0==q<<24>>24){c=k;d=f;break a}else{k=r,r=q}}}}while(0);if(c>>>0<a[d>>2]>>>0){return n[c]=0,b=a[(g|0)>>2],a[s]=b,s=Hb(b),e=a[(g+12|0)>>2],Xb(b,e),h=g,s}qa(g,1);b=a[s];n[b]=0;b=a[(g|0)>>2];a[s]=b;s=Hb(b);e=a[(g+12|0)>>2];Xb(b,e);h=g;return s}function zn(u,s){var g,e=h;h=h+40|0;g=s>>2;s=h;h=h+32|0;a[s>>2]=a[g];a[s+4>>2]=a[g+1];a[s+8>>2]=a[g+2];a[s+12>>2]=a[g+3];a[s+16>>2]=a[g+4];a[s+20>>2]=a[g+5];a[s+24>>2]=a[g+6];a[s+28>>2]=a[g+7];var c=e+8;g=e+24;var d=s+16|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),j=u+64|0;if(d<(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])){return h=e,0}var j=u+80|0,k=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),j=s|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);if(k<j){return h=e,0}var k=s+24|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),r=u+72|0;if(k<(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3])){return h=e,0}var r=u+88|0,q=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),r=s+8|0,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]);if(q<r){return h=e,0}q=c|0;f[b>>3]=.5*(d+j);a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];d=c+8|0;f[b>>3]=.5*(k+r);a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];d=u+32|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);j=u+40|0;j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);k=c|0;c=c+8|0;tn(g,d,j,(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]));c=g|0;c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);g=g+8|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);a[e>>2]=u;a[e+4>>2]=0;g=J[a[a[a[u+24>>2]+4>>2]+12>>2]](e,c,g);h=e;return g}function kj(u,s){var g,e,c,d=h;h=h+32|0;c=s>>2;s=h;h=h+32|0;a[s>>2]=a[c];a[s+4>>2]=a[c+1];a[s+8>>2]=a[c+2];a[s+12>>2]=a[c+3];a[s+16>>2]=a[c+4];a[s+20>>2]=a[c+5];a[s+24>>2]=a[c+6];a[s+28>>2]=a[c+7];c=d+16;var j=u+24|0,k=.5*(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),j=u+32|0,r=.5*(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);e=(u+56|0)>>2;g=(u+64|0)>>2;tn(d,(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]),k,r);var j=d|0,q=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),j=d+8|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);e=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);g=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])+r;r=c|0;f[b>>3]=e+k;a[r>>2]=a[b>>2];a[r+4>>2]=a[b+4>>2];k=c+8|0;f[b>>3]=g;a[k>>2]=a[b>>2];a[k+4>>2]=a[b+4>>2];k=c+8|0;k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);g=s+16|0;if((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])<q){return h=d,0}c|=0;q=s|0;if((a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])<(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])){return h=d,0}c=s+24|0;if((a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])<j){return h=d,0}c=s+8|0;c=k>=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);h=d;return c&1}function An(u,s){var g,e=0,c=h;g=u>>2;u=h;h=h+48|0;for(var d=u>>2,j=g+12;g<j;g++,d++){a[d]=a[g]}g=s>>2;s=h;h=h+32|0;a[s>>2]=a[g];a[s+4>>2]=a[g+1];a[s+8>>2]=a[g+2];a[s+12>>2]=a[g+3];a[s+16>>2]=a[g+4];a[s+20>>2]=a[g+5];a[s+24>>2]=a[g+6];a[s+28>>2]=a[g+7];d=a[u+4>>2];0==(d|0)&&ia(5375372,1634,5379544,5343640);g=a[u>>2];for(var j=g|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),k=g+8|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),r=1,q=k,m=j;(r|0)<(d|0);){var i=(r<<4)+g|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),n=(r<<4)+g+8|0,n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]);if(-1==(Bn(i,n,m,q,s)|0)){r=r+1|0,q=n,m=i}else{var v=1,e=2396;break}}if(2396==e){return h=c,v}if(0!=(a[u+8>>2]|0)&&(e=u+16|0,v=u+24|0,0!=Cn((a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),j,k,s)<<24>>24)||0!=(a[u+12>>2]|0)&&(e=d-1|0,v=u+32|0,v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),d=u+40|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),j=(e<<4)+g|0,g=(e<<4)+g+8|0,0!=Cn(v,d,(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),s)<<24>>24)){return h=c,1}h=c;return 0}function Gj(b){var s,g,e,c=0,d=h;h=h+1044|0;e=d>>2;var f=d+4;a[e]=b;ac(f,1024,d+20|0);g=(f+4|0)>>2;s=(f+8|0)>>2;a:for(;;){var k=b+1|0;a[e]=k;var r=n[b];if(0==r<<24>>24){c=2435;break}do{if(192>(r&255)){if(38!=r<<24>>24){var q=r}else{if(q=Dj(d),0==(q|0)){q=38}else{if(127>q>>>0){q&=255}else{var m=a[g],w=a[s],x=m>>>0>=w>>>0;2047>q>>>0?(x?(qa(f,1),w=a[g]):w=m,a[g]=w+1|0,n[w]=(q>>>6|192)&255):(x&&(qa(f,1),m=a[g],w=a[s]),x=m+1|0,a[g]=x,n[m]=(q>>>12|224)&255,x>>>0<w>>>0?w=x:(qa(f,1),w=a[g]),a[g]=w+1|0,n[w]=(q>>>6&63|128)&255);q=(q&63|128)&255}}}}else{if(224>(r&255)){if(-128!=(n[k]&-64)<<24>>24){c=2421;break a}q=a[g];q>>>0<a[s]>>>0||(qa(f,1),q=a[g]);a[g]=q+1|0;n[q]=r;a[e]=b+2|0;q=n[k]}else{if(240<=(r&255)){c=2431;break a}if(-128!=(n[k]&-64)<<24>>24){c=2439;break a}q=b+2|0;if(-128!=(n[q]&-64)<<24>>24){c=2438;break a}w=a[g];m=a[s];w>>>0<m>>>0||(qa(f,1),w=a[g],m=a[s]);x=w+1|0;a[g]=x;n[w]=r;a[e]=q;w=n[k];x>>>0<m>>>0?m=x:(qa(f,1),m=a[g]);a[g]=m+1|0;n[m]=w;a[e]=b+3|0;q=n[q]}}}while(0);b=a[g];b>>>0<a[s]>>>0||(qa(f,1),b=a[g]);a[g]=b+1|0;n[b]=q;b=a[e]}if(2435==c){e=a[g];if(e>>>0<a[s]>>>0){return n[e]=0,s=a[(f|0)>>2],a[g]=s,g=Hb(s),f=a[(f+12|0)>>2],Xb(s,f),h=d,g}qa(f,1);s=a[g];n[s]=0;s=a[(f|0)>>2];a[g]=s;g=Hb(s);f=a[(f+12|0)>>2];Xb(s,f);h=d;return g}2431==c?(aa(1,5349348,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Qd()):2439==c?(aa(1,5350724,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Qd()):2421==c?(aa(1,5352384,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Qd()):2438==c&&(aa(1,5350724,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Qd())}function Hj(u,s){if(0==s<<24>>24){var g=u+48|0,g=36*(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),e=u+112|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];e=u+104|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];g=u+56|0}else{g=u+56|0,g=36*(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),e=u+112|0,f[b>>3]=g,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],e=u+104|0,f[b>>3]=g,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],g=u+48|0}g=72*(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);e=u+96|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2]}function Dn(b,s){var g=0,e=h;a:do{if(0==(b|0)){var c=s}else{c=n[b];if(0!=c<<24>>24){c=c<<24>>24;do{if(108==(c|0)|76==(c|0)){var d=0==(Eb(b+1|0,5347348)|0)?2:0,g=2462}else{if(102==(c|0)|70==(c|0)){d=0==(Eb(b+1|0,5347836)|0)?2:0,g=2462}else{if(115==(c|0)|83==(c|0)){d=0==(Eb(b+1|0,5345436)|0)?8:0,g=2462}else{if(110==(c|0)|78==(c|0)){var f=b+1|0;if(0==(Eb(f,5346840)|0)){c=0;break a}if(0==(Eb(f,5346428)|0)){c=2;break a}}else{if(99==(c|0)|67==(c|0)){d=0==(Eb(b+1|0,5348244)|0)?10:0,g=2462}else{if(121==(c|0)|89==(c|0)){d=0==(Eb(b+1|0,5344648)|0)?8:0,g=2462}else{if(112==(c|0)|80==(c|0)){d=0==(Eb(b+1|0,5345808)|0)?4:0,g=2462}else{if(111==(c|0)|79==(c|0)){d=0==(Eb(b+1|0,5346116)|0)?6:0,g=2462}else{if(48==(c|0)){c=2;break a}else{if(49==(c|0)|50==(c|0)|51==(c|0)|52==(c|0)|53==(c|0)|54==(c|0)|55==(c|0)|56==(c|0)|57==(c|0)){c=8;break a}else{116==(c|0)|84==(c|0)&&(d=0==(Eb(b+1|0,5345e3)|0)?8:0,g=2462)}}}}}}}}}}}while(0);if(2462==g&&0!=(d|0)){c=d;break}aa(0,5344288,(i=h,h=h+4|0,a[i>>2]=b,i))}c=s}}while(0);h=e;return c}function En(a,b){var g=U(a|0,5343976),g=0==(g|0)?b:0==n[g]<<24>>24?0:Dn(g,b),e=a+164|0;C[e>>1]=(fc[e>>1]|g)&65535}function Cn(u,s,g,e,c){var d,j=h;h=h+128|0;d=c>>2;c=h;h=h+32|0;a[c>>2]=a[d];a[c+4>>2]=a[d+1];a[c+8>>2]=a[d+2];a[c+12>>2]=a[d+3];a[c+16>>2]=a[d+4];a[c+20>>2]=a[d+5];a[c+24>>2]=a[d+6];a[c+28>>2]=a[d+7];var k=j+32,r=j+64;d=j+96;var q=c+16|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);mf(j,u,s,g,e);var m=j|0;if(q>=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])){if(mf(k,u,s,g,e),k=k+16|0,q=c|0,(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])>=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])){if(k=c+24|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),mf(r,u,s,g,e),r=r+8|0,k>=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3])){if(mf(d,u,s,g,e),u=d+24|0,c=c+8|0,(a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3])>=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])){return h=j,1}}}}h=j;return 0}function Cj(b,s){var g=a[b+20>>2];if(0==n[b+134|0]<<24>>24){var e;return b}var c=b|0;Ij(s,c);var d=oc(a[b+12>>2],58);0==(d|0)&&ia(5375372,1243,5379652,5346492);var d=d+1|0,f=Uf(g,d);if(0!=(f|0)){return f}g=Og(g,d);d=a[Sh(c)+8>>2];f=a[d>>2];if(0==(f|0)){return g}for(c=g|0;;){var d=d+4|0,k=a[f+8>>2],f=a[f+4>>2];(tb(c,k)|0)!=(f|0)&&hc(c,k,f);f=a[d>>2];if(0==(f|0)){e=g;break}}return e}function Jj(b,s){var g,e;g=0;var c=a[s>>2];e=(s+24|0)>>2;a[e]=0;a[e+1]=0;a[e+2]=0;a[e+3]=0;if(0!=n[c]<<24>>24){var d=Za(xa(c)+1|0);n[d]=0;var f=s+12|0,k=d;a:for(;;){for(;;){var r=c+1|0,h=n[c];if(0==h<<24>>24){var m=k;break a}if(!(161>(h&255)|2!=(a[f>>2]|0)|-1==h<<24>>24)){n[k]=h;var h=n[r],i=k+2|0;n[k+1|0]=h;if(0==h<<24>>24){m=i;break a}else{k=i;c=c+2|0;continue}}if(10==h<<24>>24){g=2512;break}else{if(92==h<<24>>24){break}}n[k]=h;k=k+1|0;c=r}2512==g?(g=0,h=k+1|0,n[k]=0,Th(b,s,d,110),k=h,c=r,d=h):(h=n[r],i=h<<24>>24,110==(i|0)|108==(i|0)|114==(i|0)?(h=k+1|0,n[k]=0,Th(b,s,d,n[r]),d=k=h):(n[k]=h,k=k+1|0),c=0==n[r]<<24>>24?r:c+2|0)}(d|0)!=(m|0)&&(n[m]=0,Th(b,s,d,110));g=(s+40|0)>>2;a[g]=a[e];a[g+1]=a[e+1];a[g+2]=a[e+2];a[g+3]=a[e+3]}}function Th(u,s,g,e){var c,d=0,j=h;h=h+16|0;c=(s+76|0)>>1;var k=C[c]<<16>>16,r=s+72|0,q=a[r>>2],k=0==(q|0)?da((76*k&-1)+152|0):Fn(q,k+2|0,76,k+1|0);a[r>>2]=k;r=C[c]<<16>>16;q=k+(76*r&-1)|0;a[q>>2]=g;n[k+(76*r&-1)+72|0]=e;if(0==(g|0)){d=2526}else{if(0==n[g]<<24>>24){d=2526}else{var m=s+16|0,i=a[s+4>>2],m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]);a[q+20>>2]=i;g=q+24|0;f[b>>3]=m;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];m=a;g=q+4>>2;e=a[1310849];0!=(e|0)&&0==(Eb(e,i)|0)?i=a[1310848]:(a[1310849]=i,i=yh(5243396,5247572,35,36,280),a[1310848]=i);m[g]=i;u=a[a[u+172>>2]+132>>2];0==(u|0)?u=0:(u=a[u>>2],u=0==(u|0)?0:J[u](q,0));0==u<<24>>24&&Gn(q);u=q+56|0;u=(a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3]);q=q+64|0;q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);i=j|0;f[b>>3]=u;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];u=j+8|0;f[b>>3]=q;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2];u=j|0;q=j+8|0;i=(a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3]);m=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])}}2526==d&&(d=s+16|0,d=1.2*(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])&-1|0,k=k+(76*r&-1)+64|0,f[b>>3]=d,a[k>>2]=a[b>>2],a[k+4>>2]=a[b+4>>2],i=0,m=d);C[c]=C[c]+1&65535;c=(s+24|0)>>2;d=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3]);f[b>>3]=d>i?d:i;a[c]=a[b>>2];a[c+1]=a[b+4>>2];s=(s+32|0)>>2;c=(a[b>>2]=a[s],a[b+4>>2]=a[s+1],f[b>>3])+m;f[b>>3]=c;a[s]=a[b>>2];a[s+1]=a[b+4>>2];h=j}function we(u,s,g,e,c,d){var j,k,r=h,q=da(84);k=q>>2;var m=a[u>>2]<<28>>28;if(2==(m|0)){j=u;var w=0,x=0,m=a[a[a[u+12>>2]+20>>2]+32>>2]}else{1==(m|0)?(j=0,w=u,x=0,m=a[a[u+20>>2]+32>>2]):3==(m|0)?(w=j=0,x=u,m=a[u+32>>2]):m=x=w=j=0}a[k+1]=c;a[k+2]=d;c=q+16|0;f[b>>3]=e;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];e=q+12|0;a[e>>2]=ca[m+151|0];if(0!=(g&4|0)){a[k]=Hb(s);if(0==(g&2|0)){return h=r,q}n[q+82|0]=1;h=r;return q}if(2==(g|0)){a[k]=Hb(s);n[q+82|0]=1;if(0==(Hn(u,q)|0)){return h=r,q}u=a[u>>2]<<28>>28;1==(u|0)?aa(3,5370868,(i=h,h=h+4|0,a[i>>2]=a[w+12>>2],i)):3==(u|0)?aa(3,5346084,(i=h,h=h+4|0,a[i>>2]=a[x+12>>2],i)):2==(u|0)&&(m=0!=(a[m>>2]&16|0)?5360020:5332132,u=a[a[j+12>>2]+12>>2],aa(3,5350884,(i=h,h=h+12|0,a[i>>2]=a[a[j+16>>2]+12>>2],a[i+4>>2]=m,a[i+8>>2]=u,i)));h=r;return q}0!=(g|0)&&ia(5338392,169,5379660,5335568);u=Kj(s,u,0);j=q>>2;a[j]=u;u=1==(a[e>>2]|0)?Ej(u):Gj(u);E(a[j]);a[j]=u;Jj(m,q);h=r;return q}function In(a){var b=a+1|0,g=n[b];if(35!=g<<24>>24){for(a=b;;){b=a+1|0;if(!(26>(g-97&255)|26>(g-65&255))){var e=g;break}a=b;g=n[b]}return e=59==e<<24>>24&1}b=a+2|0;g=n[b];if(120==g<<24>>24|88==g<<24>>24){for(a=a+3|0;;){if(g=n[a],10>(g-48&255)|6>(g-97&255)|6>(g-65&255)){a=a+1|0}else{e=g;break}}}else{for(a=b;;){b=a+1|0;if(10<=(g-48&255)){e=g;break}a=b;g=n[b]}}return e=59==e<<24>>24&1}function Kj(b,s,g){var e=s>>2,c=a[e]<<28>>28;if(3==(c|0)){var d=a[e+3],f=xa(d),k=a[e+12];if(0==(k|0)){var r=0,h=0,m=5338228,i=5338228,x=d,v=5368832,t=5355212,y=5358508,z=5356932,B=5355288,F=f,D=2,S=2,Gb=2,A=2,I=2,C=0}else{var T=a[k>>2];0==(b|0)?(h=r=0,i=m=5338228,x=d,v=5368832,t=5355212,y=5358508,z=5356932,B=T,F=f,I=A=Gb=S=D=2):(h=r=0,i=m=5338228,x=d,v=5368832,t=5355212,y=5358508,z=5356932,B=T,F=f,A=Gb=S=D=2,I=xa(T));C=0}}else{if(1==(c|0)){var K=a[a[e+5]+12>>2],M=xa(K),L=a[e+3],E=xa(L),yb=a[e+30];if(0==(yb|0)){h=r=0,i=m=5338228,x=K,v=L,t=5355212,y=5358508,z=5356932,B=5355288,F=M,D=E,I=A=Gb=S=2}else{var J=a[yb>>2];0==(b|0)?(h=r=0,i=m=5338228,x=K,v=L,t=5355212,y=5358508,z=5356932,B=J,F=M,D=E,I=A=Gb=S=2):(h=r=0,i=m=5338228,x=K,v=L,t=5355212,y=5358508,z=5356932,B=J,F=M,D=E,A=Gb=S=2,I=xa(J))}C=0}else{if(2==(c|0)){var R=a[e+4],Y=a[a[R+20>>2]+32>>2],H=a[Y+12>>2],Rb=xa(H),G=a[R+12>>2],ea=xa(G),wa=a[e+16],Fb=0==(wa|0)?0:xa(wa),V=a[a[e+3]+12>>2],W=a[e+26],X=0==(W|0)?0:xa(W),ba=xa(V),ma=a[e+27];if(0==(ma|0)){var ib=5355288,P=2}else{var mc=a[ma>>2];0==(b|0)?(ib=mc,P=2):(ib=mc,P=xa(mc))}r=1;h=X;m=wa;i=W;x=H;v=5368832;t=0==(a[Y>>2]&16|0)?5332132:5360020;y=V;z=G;B=ib;F=Rb;D=2;S=ea+(0==(Fb|0)?0:Fb+1|0)+ba+(0==(X|0)?0:X+1|0)+2|0;Gb=ba;A=ea;I=P;C=Fb}else{h=r=0,i=m=5338228,x=5365128,v=5368832,t=5355212,y=5358508,z=5356932,B=5355288,I=A=Gb=S=D=F=2,C=0}}}var O=0==(g|0),ga=0,Tb=b;a:for(;;){var aa=Tb+1|0,ua=n[Tb];if(0==ua<<24>>24){break}else{if(92!=ua<<24>>24){ga=ga+1|0;Tb=aa;continue}}var Da=Tb+2|0,Ja=n[aa]<<24>>24;do{if(71==(Ja|0)){ga=ga+F|0;Tb=Da;continue a}else{if(69==(Ja|0)){ga=ga+S|0;Tb=Da;continue a}else{if(72==(Ja|0)){ga=ga+Gb|0;Tb=Da;continue a}else{if(84==(Ja|0)){ga=ga+A|0;Tb=Da;continue a}else{if(76==(Ja|0)){ga=ga+I|0;Tb=Da;continue a}else{if(78==(Ja|0)){ga=ga+D|0;Tb=Da;continue a}else{if(92==(Ja|0)&&!O){ga=ga+1|0;Tb=Da;continue a}}}}}}}}while(0);ga=ga+2|0;Tb=Da}var Ab=Za(ga+1|0),ra=0==(r|0),N=0==(C|0),ya=0==(h|0),ja=b,la=Ab;a:for(;;){var va=ja+1|0,oa=n[ja];if(0==oa<<24>>24){break}else{if(92!=oa<<24>>24){n[la]=oa;ja=va;la=la+1|0;continue}}var ka=ja+2|0,Ea=n[va],Ka=Ea<<24>>24;do{if(78==(Ka|0)){var Na=n[v];n[la]=Na;if(0==Na<<24>>24){ja=ka;continue a}else{var Ba=v,Wa=la}for(;;){var U=Ba+1|0,Q=Wa+1|0,Ra=n[U];n[Q]=Ra;if(0==Ra<<24>>24){ja=ka;la=Q;continue a}else{Ba=U,Wa=Q}}}else{if(71==(Ka|0)){var bb=n[x];n[la]=bb;if(0==bb<<24>>24){ja=ka;continue a}else{var Xa=x,Sa=la}for(;;){var da=Xa+1|0,Va=Sa+1|0,Ta=n[da];n[Va]=Ta;if(0==Ta<<24>>24){ja=ka;la=Va;continue a}else{Xa=da,Sa=Va}}}else{if(76==(Ka|0)){var Aa=n[B];n[la]=Aa;if(0==Aa<<24>>24){ja=ka;continue a}else{var fb=B,Ca=la}for(;;){var Ya=fb+1|0,$a=Ca+1|0,La=n[Ya];n[$a]=La;if(0==La<<24>>24){ja=ka;la=$a;continue a}else{fb=Ya,Ca=$a}}}else{if(72==(Ka|0)){var pa=n[y];n[la]=pa;if(0==pa<<24>>24){ja=ka;continue a}else{var Ga=y,Fa=la}for(;;){var $=Ga+1|0,nb=Fa+1|0,jb=n[$];n[nb]=jb;if(0==jb<<24>>24){ja=ka;la=nb;continue a}else{Ga=$,Fa=nb}}}else{if(84==(Ka|0)){var cb=n[z];n[la]=cb;if(0==cb<<24>>24){ja=ka;continue a}else{var ia=z,kb=la}for(;;){var Kb=ia+1|0,Ma=kb+1|0,ca=n[Kb];n[Ma]=ca;if(0==ca<<24>>24){ja=ka;la=Ma;continue a}else{ia=Kb,kb=Ma}}}else{if(92==(Ka|0)){if(!O){n[la]=92;ja=ka;la=la+1|0;continue a}}else{if(69==(Ka|0)){if(ra){ja=ka;continue a}var lb=n[z];n[la]=lb;b:do{if(0==lb<<24>>24){var rb=la}else{for(var ab=z,db=la;;){var ob=ab+1|0,pb=db+1|0,ub=n[ob];n[pb]=ub;if(0==ub<<24>>24){rb=pb;break b}else{ab=ob,db=pb}}}}while(0);b:do{if(N){var gb=rb}else{n[rb]=58;for(var sb=rb,Ia=m;;){var vb=sb+1|0,Ua=n[Ia];n[vb]=Ua;if(0==Ua<<24>>24){gb=vb;break b}else{sb=vb,Ia=Ia+1|0}}}}while(0);var ha=n[t];n[gb]=ha;b:do{if(0==ha<<24>>24){var sa=gb}else{for(var qb=t,Bb=gb;;){var sc=qb+1|0,xb=Bb+1|0,za=n[sc];n[xb]=za;if(0==za<<24>>24){sa=xb;break b}else{qb=sc,Bb=xb}}}}while(0);var Nb=n[y];n[sa]=Nb;b:do{if(0==Nb<<24>>24){var Jb=sa}else{for(var qa=y,fa=sa;;){var Ic=qa+1|0,na=fa+1|0,Ha=n[Ic];n[na]=Ha;if(0==Ha<<24>>24){Jb=na;break b}else{qa=Ic,fa=na}}}}while(0);if(ya){ja=ka;la=Jb;continue a}n[Jb]=58;for(var Oa=Jb,ta=i;;){var Pa=Oa+1|0,eb=n[ta];n[Pa]=eb;if(0==eb<<24>>24){ja=ka;la=Pa;continue a}else{Oa=Pa,ta=ta+1|0}}}}}}}}}}while(0);n[la]=92;n[la+1|0]=Ea;ja=ka;la=la+2|0}n[la]=0;return Ab}function tf(b){if(0!=(b|0)){E(a[b>>2]);var s=b+72|0;if(0==n[b+82|0]<<24>>24){var s=a[s>>2],g=C[b+76>>1]<<16>>16,e;if(0!=(s|0)){a:do{if(0<(g|0)){var c=0,d=s;for(e=d>>2;;){if(0==(c|0)){var f=a[e];0!=(f|0)&&E(f)}f=a[e+2];if(0!=(f|0)&&(e=a[e+3],0!=(e|0))){J[e](f)}c=c+1|0;if((c|0)==(g|0)){break a}else{d=d+76|0,e=d>>2}}}}while(0);E(s)}}else{Jn(a[s>>2],1)}E(b)}}function Te(u,s,g){var e,c,d;d=(a[u+16>>2]+12|0)>>2;var j=a[d];a[d]=s;if(0!=n[g+82|0]<<24>>24){Kn(u,a[g+72>>2],g),a[d]=j}else{if(s=(g+76|0)>>1,1<=C[s]<<16>>16){Ln(u,0);eb(u,a[g+8>>2]);e=n[g+80|0]<<24>>24;if(98==(e|0)){e=g+64|0;c=g+48|0;var k=g+32|0,r=g+16|0,k=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-.5*(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])+(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])-(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3])}else{116==(e|0)?(e=g+64|0,c=g+48|0):(e=g+64|0,c=g+32|0),k=g+16|0,k=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])+.5*(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])}a:do{if(0<C[s]<<16>>16){r=g+72|0;c=(g+56|0)>>2;e=(g+40|0)>>2;for(var h=k,m=0,i=a[r>>2];;){var x=n[i+(76*m&-1)+72|0]<<24>>24,x=114==(x|0)?(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3])+.5*(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]):108==(x|0)?(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3])-.5*(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]):(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3]);xj(u,x,h,i+(76*m&-1)|0);i=a[r>>2];x=i+(76*m&-1)+64|0;m=m+1|0;if((m|0)<(C[s]<<16>>16|0)){h-=(a[b>>2]=a[x>>2],a[b+4>>2]=a[x+4>>2],f[b>>3])}else{break a}}}}while(0);Mn(u);a[d]=j}}}function Zb(a,b){return Kj(a,b,1)}function jc(b){var s=0,g=a[1310723];if(0==(g|0)){a[1310722]=64;var g=Za(64),e=a[1310723]=g,c=0,d=0}else{e=g,d=c=0}for(;;){if(0==(b|0)){s=2687;break}var f=n[b];if(0==f<<24>>24){s=2686;break}var k=a[1310722];(d|0)>(k-8|0)&&(e=k<<1,a[1310722]=e,g=Oa(g,e),a[1310723]=g,e=g+d|0,f=n[b]);if(38==f<<24>>24){if(0==(In(b)|0)){var r=5340252,h=5}else{s=2681}}else{45==f<<24>>24?(r=5344496,h=5):62==f<<24>>24?(r=5348588,h=4):32==f<<24>>24?0==(c|0)?s=2681:32==n[c]<<24>>24?(r=5340936,h=6):s=2681:60==f<<24>>24?(r=5366660,h=4):34==f<<24>>24?(r=5337956,h=6):39!=f<<24>>24?s=2681:(r=5335100,h=5)}2681==s&&(s=0,r=b,h=1);d=h+d|0;k=h;c=r;for(f=e;!(k=k-1|0,n[f]=n[c],0==(k|0));){c=c+1|0,f=f+1|0}c=b;b=b+1|0;e=e+h|0}if(2686==s||2687==s){return n[e]=0,g}}function Uh(b){var s=0,g=a[1310721];if(0==(g|0)){a[1310720]=64;var g=Za(64),e=a[1310721]=g,c=0}else{e=g,c=0}for(;;){if(0==(b|0)){s=2704;break}var d=n[b];if(0==d<<24>>24){s=2705;break}var f=a[1310720];(c|0)>(f-8|0)&&(e=f<<1,a[1310720]=e,g=Oa(g,e),a[1310721]=g,e=g+c|0,d=n[b]);if(38==d<<24>>24){if(0==(In(b)|0)){var k=5340252,r=5}else{s=2699}}else{34==d<<24>>24?(k=5337956,r=6):62==d<<24>>24?(k=5348588,r=4):39==d<<24>>24?(k=5335100,r=5):60==d<<24>>24?(k=5366660,r=4):s=2699}2699==s&&(s=0,k=b,r=1);for(var c=r+c|0,h=r,d=k,f=e;!(h=h-1|0,n[f]=n[d],0==(h|0));){d=d+1|0,f=f+1|0}b=b+1|0;e=e+r|0}if(2705==s||2704==s){return n[e]=0,g}}function da(a){if(0==(a|0)){a=0}else{var b=Za(a);Ef(b,0,a);a=b}return a}function Za(b){if(0==(b|0)){return 0}b=wb(b);if(0==(b|0)){re(5344948,14,1,a[Qa>>2]),P()}else{return b}}function Km(a,b,g,e,c,d){g-=a;e-=b;a=(d-b)*g-(c-a)*e;a*=a;return 1e-10>a?0:a/(g*g+e*e)}function Bn(u,s,g,e,c){var d,j=0,k=h;d=c>>2;c=h;h=h+32|0;a[c>>2]=a[d];a[c+4>>2]=a[d+1];a[c+8>>2]=a[d+2];a[c+12>>2]=a[d+3];a[c+16>>2]=a[d+4];a[c+20>>2]=a[d+5];a[c+24>>2]=a[d+6];a[c+28>>2]=a[d+7];d=c|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);var r=d>u;if(r){var q=0}else{q=c+16|0,(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])<u?q=0:(q=c+8|0,(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])>s?q=0:(q=c+24|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])>=s))}if(d>g){j=2727}else{var m=c+16|0;if((a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])<g){j=2727}else{if(m=c+8|0,(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])>e){j=2727}else{m=c+24|0;m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])>=e;if(q^m){return h=k,0}if(q&m){return h=k,1}}}}if(2727==j&&q){return h=k,0}do{if(u==g){if(j=c+8|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),!(r|j<=s^j<=e^1)&&(j=c+16|0,(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])>=u)){return s=0,h=k,s}}else{if(s==e){if(!(d<=u^d<=g)){break}u=c+8|0;if((a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3])>s){break}c=c+24|0;if((a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])<s){break}else{s=0}h=k;return s}var j=(e-s)/(g-u),i=(q=u<g)?u:g,n=q?g:u,v=(d-u)*j+s,q=c+8|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);if(!(d<i|d>n|v<q)&&(m=c+24|0,v<=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]))){return s=0,h=k,s}m=c+16|0;m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]);v+=(m-d)*j;if(v>=q){var t=c+24|0;if(!(v>(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3])|m<i|m>n)){return s=0,h=k,s}}i=(n=s<e)?s:e;n=n?e:s;v=(q-s)/j+u;if(v>=d&&!(v>m|q<i|q>n)){return s=0,h=k,s}t=c+24|0;t=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]);j=v+(t-q)/j;if(j>=d&&!(j>m|t<i|t>n)){return s=0,h=k,s}}}while(0);h=k;return-1}function Kh(u){var s;s=(u+16|0)>>2;var g=(a[b>>2]=a[s],a[b+4>>2]=a[s+1],f[b>>3]),e=u+32|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];e=u+48|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];g=u+24|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);e=u+40|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];g=u+8|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);e=u+56|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];u|=0;u=(a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3]);f[b>>3]=u;a[s]=a[b>>2];a[s+1]=a[b+4>>2]}function Gn(u){var s,g,e;e=(u+56|0)>>2;f[b>>3]=0;a[e]=a[b>>2];a[e+1]=a[b+4>>2];g=(u+24|0)>>2;s=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]);var c=u+64|0;f[b>>3]=1.2*s;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];c=u+40|0;f[b>>3]=0;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];c=u+48|0;f[b>>3]=.1*s;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];s=(u+20|0)>>2;c=a[s];a[u+8>>2]=c;a[u+12>>2]=0;s=0==(oe(c,5350228,4)|0)?5258020:0==(oe(a[s],5341376,5)|0)?5322032:0==(oe(a[s],5338244,9)|0)?5322032:5243552;u=a[u>>2];if(0!=(u|0)){var c=n[u],d=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);a:do{if(0==c<<24>>24){var j=d}else{for(var k=u,r=c,h=d;;){if(k=k+1|0,r=((r&255)<<3)+s|0,h+=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),f[b>>3]=h,a[e]=a[b>>2],a[e+1]=a[b+4>>2],r=n[k],0==r<<24>>24){j=h;break a}}}}while(0);g=j*(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]);f[b>>3]=g;a[e]=a[b>>2];a[e+1]=a[b+4>>2]}}function Nn(u,s,g,e){for(var c=0;;){if(90==(e|0)){c=2782;break}else{if(270==(e|0)){c=2789;break}else{if(0==(e|0)){var d=s,j=g;break}else{if(180==(e|0)){c=2783;break}}}}if(0>(e|0)){c=2785;break}if(360>=(e|0)){c=2788;break}e=(e|0)%360}if(2782==c){d=g,j=-s}else{if(2788==c){On(u,s,g,e);return}if(2789==c){d=g,j=s}else{if(2783==c){d=s,j=-g}else{if(2785==c){Wf(u,s,g,-e|0);return}}}}s=u|0;f[b>>3]=d;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];u=u+8|0;f[b>>3]=j;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}function Wf(u,s,g,e){for(var c=0;;){if(0==(e|0)){var d=s,j=g;break}else{if(180==(e|0)){c=2798;break}else{if(90==(e|0)){c=2797;break}else{if(270==(e|0)){c=2804;break}}}}if(0>(e|0)){c=2800;break}if(360>=(e|0)){c=2803;break}e=(e|0)%360}if(2803==c){On(u,s,g,360-e|0)}else{if(2798==c){d=s,j=-g}else{if(2797==c){d=-g,j=s}else{if(2800==c){Nn(u,s,g,-e|0);return}2804==c&&(d=g,j=s)}}s=u|0;f[b>>3]=d;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];u=u+8|0;f[b>>3]=j;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}}function On(u,s,g,e){if((a[1311607]|0)==(e|0)){var e=(a[b>>2]=a[1311608],a[b+4>>2]=a[1311609],f[b>>3]),c=(a[b>>2]=a[1311605],a[b+4>>2]=a[1311606],f[b>>3])}else{var d=(e|0)/6.283185307179586,c=Math.sin(d);f[b>>3]=c;a[1311605]=a[b>>2];a[1311606]=a[b+4>>2];d=Math.cos(d);f[b>>3]=d;a[1311608]=a[b>>2];a[1311609]=a[b+4>>2];a[1311607]=e;e=d}d=u|0;f[b>>3]=e*s-c*g;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];u=u+8|0;f[b>>3]=e*g+c*s;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}function Kn(u,s,g){var e,c,d=0,j=h;h=h+60|0;Pn(u);c=j>>2;e=(g+56|0)>>2;a[c]=a[e];a[c+1]=a[e+1];a[c+2]=a[e+2];a[c+3]=a[e+3];a[j+20>>2]=a[g+8>>2];a[j+16>>2]=a[g+4>>2];g=g+16|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);e=j+32|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];g=u+16|0;c=U(a[a[g>>2]+8>>2]|0,5331808);var k=j+48|0;a[k>>2]=c;var r=a[g>>2],g=j+52|0;a[g>>2]=a[r+152>>2];e=j+56|0;n[e]=0;0==(c|0)?d=2823:0==n[c]<<24>>24&&(d=2823);2823==d&&(a[k>>2]=5333780);1==n[s+4|0]<<24>>24?(s=a[s>>2],Dd(r,a[u+60>>2],a[a[u>>2]+296>>2]),d=a[s+24>>2],0==(d|0)?eb(u,5374748):eb(u,d),Lj(u,s,j)):Qn(u,a[s>>2],j);0!=n[e]<<24>>24&&E(a[g>>2]);s=a[u+16>>2]>>2;a[s+37]=0;a[s+42]=0;a[s+46]=0;a[s+38]=0;Qf(u);h=j}function Pn(b){var s,g=Bg(b);s=g>>2;var b=a[s]>>2,e=a[b+1];a[s+1]=e;a[s+3]=a[b+3];3==(e|0)?a[s+2]=a[b+2]:0==(e|0)?a[s+2]=a[b+2]:1==(e|0)?a[s+2]=a[b+2]:2==(e|0)&&(a[s+2]=a[b+2]);a[s+37]=a[b+37];a[s+42]=a[b+42];a[s+46]=a[b+46];s=g+200|0;a[s>>2]=a[s>>2]&-2|a[b+50]&1}function Fn(b,s,g,e){b=gc(b,Math.a(g,s));0!=(b|0)|0==(s|0)||(re(5344948,14,1,a[Qa>>2]),P());if(e>>>0>=s>>>0){return b}Ef(b+Math.a(e,g)|0,0,Math.a(s-e|0,g));return b}function Oa(b,s){var g=gc(b,s);if(0!=(g|0)|0==(s|0)){return g}re(5344948,14,1,a[Qa>>2]);P()}function Lj(u,s,g){var e,c,d,j,k,r=s>>2,q=h;h=h+132|0;var m=q+32,i=q+68,x=s|0;c=q>>2;k=(s+40|0)>>2;a[c]=a[k];a[c+1]=a[k+1];a[c+2]=a[k+2];a[c+3]=a[k+3];a[c+4]=a[k+4];a[c+5]=a[k+5];a[c+6]=a[k+6];a[c+7]=a[k+7];k=g|0;j=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);k=g+8|0;var v=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);k=a[r+19];var t=0==(a[r]|0)?0!=(a[r+2]|0):1,y=s+100|0;e=a[y>>2];if(0!=(e|0)){d=g+16|0;var z=a[d>>2];if(0!=(z|0)){var B=a[e>>2];0==(B|0)?a[1314329]=0:(a[1314329]=z,a[d>>2]=B)}d=g+20|0;z=a[d>>2];0!=(z|0)&&(B=a[e+4>>2],0==(B|0)?a[1314328]=0:(a[1314328]=z,a[d>>2]=B));d=(g+32|0)>>2;z=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);0>z||(e=e+16|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),0>e?(f[b>>3]=-1,a[1314326]=a[b>>2],a[1314327]=a[b+4>>2]):(f[b>>3]=z,a[1314326]=a[b>>2],a[1314327]=a[b+4>>2],f[b>>3]=e,a[d]=a[b>>2],a[d+1]=a[b+4>>2]))}e=(q|0)>>2;d=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])+j;f[b>>3]=d;a[e]=a[b>>2];a[e+1]=a[b+4>>2];e=q+16|0;d=(e|0)>>2;j=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3])+j;f[b>>3]=j;a[d]=a[b>>2];a[d+1]=a[b+4>>2];j=(q+8|0)>>2;d=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3])+v;f[b>>3]=d;a[j]=a[b>>2];a[j+1]=a[b+4>>2];j=(q+24|0)>>2;v=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3])+v;f[b>>3]=v;a[j]=a[b>>2];a[j+1]=a[b+4>>2];v=t?0!=(a[u+148>>2]&4|0)?0:Pg(u,g,x,q,m,1):0;j=n[s+104|0];0==(j&2)<<24>>24?(i=a[r+5],0!=(i|0)&&Rn(u,i,q),i=n[s+29|0],0!=i<<24>>24&&Sn(u,a[r+6],i&255,q)):(s=a[r+6],d=i>>2,a[d]=a[c],a[d+1]=a[c+1],a[d+2]=a[c+2],a[d+3]=a[c+3],d=i+32|0,c=d>>2,e>>=2,a[c]=a[e],a[c+1]=a[e+1],a[c+2]=a[e+2],a[c+3]=a[e+3],c=d|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),e=i+16|0,f[b>>3]=c,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],c=i+8|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),e=i+24|0,f[b>>3]=c,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],c=i|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),e=i+48|0,f[b>>3]=c,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],c=i+40|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),e=i+56|0,f[b>>3]=c,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],r=a[r+5],Rf(u,r,0==(s|0)?5374748:s,i|0,4,j&255,0!=(r|0)&1));r=a[k>>2];a:do{if(0!=(r|0)){i=k;for(c=r;;){if(Tn(u,c,g),i=i+4|0,c=a[i>>2],0==(c|0)){break a}}}}while(0);0!=(v|0)&&Qg(u,m,1);t&&0!=(a[u+148>>2]&4|0)&&0!=(Pg(u,g,x,q,m,0)|0)&&Qg(u,m,0);0!=(a[y>>2]|0)&&(u=a[1314329],0!=(u|0)&&(a[g+16>>2]=u),u=a[1314328],0!=(u|0)&&(a[g+20>>2]=u),u=(a[b>>2]=a[1314326],a[b+4>>2]=a[1314327],f[b>>3]),0>u||(g=g+32|0,f[b>>3]=u,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2]));h=q}function Qn(u,s,g){var e=C[s+4>>1];if(1<=e<<16>>16){var c=s+24|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),d=s+8|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),j=g|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])+.5*(c+d),k=g+8|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),r=s+32|0,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),h=s+16|0,h=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]);Un(u,e<<16>>16,a[s>>2],j,k+.5*(r+h),.5*(c-d),g+16|0,h,r)}}function Vn(b){var s=b+12|0,g=a[s>>2]-1|0;a[s>>2]=g;0==(g|0)&&(s=a[b>>2],0!=(s|0)&&E(s),s=a[b+4>>2],0!=(s|0)&&E(s),E(b))}function Wn(b){b>>=2;E(a[b]);E(a[b+1]);E(a[b+2]);E(a[b+4]);E(a[b+3]);E(a[b+5]);E(a[b+6])}function Xn(b){var s;if(0!=(b|0)){var g=b|0,e=b+4|0,c=C[e>>1];a:do{if(0<c<<16>>16){for(var d=0,f=a[g>>2],k=c;;){var r=f+4|0;if(0<C[r>>1]<<16>>16){k=a[f>>2];s=k>>2;for(var h=0;;){var m=a[s];0!=(m|0)&&E(m);m=a[s+4];0!=(m|0)&&Vn(m);m=a[s+2];if(0!=(m|0)&&(s=a[s+3],0!=(s|0))){J[s](m)}h=h+1|0;if((h|0)<(C[r>>1]<<16>>16|0)){k=k+76|0,s=k>>2}else{break}}r=C[e>>1]}else{r=k}d=d+1|0;if((d|0)<(r<<16>>16|0)){f=f+24|0,k=r}else{break a}}}}while(0);g=a[g>>2];0!=(g|0)&&E(g);E(b)}}function Jn(b,s){var g=n[b+4|0];if(1==g<<24>>24){var g=a[b>>2],e=g+76|0,c=a[e>>2];if(-1==(a[g+92>>2]|0)){Rc(c)}else{E(a[g+84>>2]);E(a[g+88>>2]);var d=a[c>>2];a:do{if(0!=(d|0)){for(var f=c,k=d;;){if(Jn(k+80|0,0),Wn(k|0),E(k),f=f+4|0,k=a[f>>2],0==(k|0)){break a}}}}while(0);E(a[e>>2])}e=a[g+100>>2];0!=(e|0)&&Vn(e);Wn(g|0);E(g)}else{3==g<<24>>24?(g=a[b>>2],E(a[g+32>>2]),E(g)):Xn(a[b>>2])}0!=(s|0)&&E(b)}function Yn(b,s){var g=0,e=a[b+4>>2];if(0!=(e|0)&&0==(Eb(e,s)|0)){var c;return b|0}for(e=a[b+76>>2];;){var d=a[e>>2];if(0==(d|0)){c=0;g=2972;break}var f=a[d+4>>2],d=0!=(f|0)&&0==(Eb(f,s)|0)?d|0:1!=n[d+84|0]<<24>>24?0:Yn(a[d+80>>2],s);if(0==(d|0)){e=e+4|0}else{c=d;g=2973;break}}if(2973==g||2972==g){return c}}function Hn(b,s){var g,e=h;h=h+148|0;var c=e+4,d=e+20;g=a[b>>2]<<28>>28;if(1==(g|0)){var f=a[b+20>>2]}else{2==(g|0)?f=a[a[b+12>>2]+20>>2]:3==(g|0)&&(f=a[b+32>>2])}f=a[f+32>>2];g=(s|0)>>2;var k=h;h=h+144|0;var r=k+128;a[1345411]=Bc(5253420,5380192);a[1345410]=Bc(5253456,5380192);ac(r,128,k|0);var q=h;0==(a[1312803]|0)&&(aa(0,5365272,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),a[1312803]=a[1312803]+1|0);h=q;a[e>>2]=2;Rc(a[1345411]);Rc(a[1345410]);a[1345411]=0;a[1345410]=0;Xb(a[r>>2],a[r+12>>2]);h=k;ac(c,128,d|0);n[s+82|0]=0;d=Hb(Zn(b,c));a[g]=d;d=1==(a[s+12>>2]|0)?Ej(d):Gj(d);E(a[g]);a[g]=d;Jj(f,s);Xb(a[c>>2],a[c+12>>2]);h=e;return a[e>>2]}function Zn(b,s){var g;g=a[b>>2]<<28>>28;1==(g|0)?Cb(s,a[b+12>>2]):2==(g|0)?(Cb(s,a[a[b+16>>2]+12>>2]),g=b+12|0,Cb(s,a[a[g>>2]+12>>2]),0==(a[a[a[g>>2]+20>>2]>>2]&16|0)?Cb(s,5332132):Cb(s,5360020)):3==(g|0)&&Cb(s,a[b+12>>2]);g=(s+4|0)>>2;var e=a[g];if(e>>>0<a[s+8>>2]>>>0){return n[e]=0,e=a[(s|0)>>2],a[g]=e}qa(s,1);e=a[g];n[e]=0;e=a[(s|0)>>2];return a[g]=e}function Un(u,s,g,e,c,d,j,k,r){var q,m,i=0,x=h;h=h+76|0;m=j>>2;j=h;h=h+24|0;a[j>>2]=a[m];a[j+4>>2]=a[m+1];a[j+8>>2]=a[m+2];a[j+12>>2]=a[m+3];a[j+16>>2]=a[m+4];a[j+20>>2]=a[m+5];m=e-d;var v=e+d;Ln(u,1);if(0<(s|0)){for(var d=(j+16|0)>>2,t=j|0,j=j+4|0,y=x|0,z=x+20|0,B=x+24|0,F=x+40|0,D=x+48|0,S=x+4|0,Gb=x+8|0,A=x+56|0,I=x+64|0,Z=x+72|0,T=.5*(r-k)+c,c=0;;){k=n[g+(24*c&-1)+6|0]<<24>>24;114==(k|0)?(k=g+(24*c&-1)+8|0,r=v-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])):108==(k|0)?r=m:(k=g+(24*c&-1)+8|0,r=e-.5*(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]));var k=(g+(24*c&-1)+16|0)>>2,T=T-(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3]),K=g+(24*c&-1)+4|0;a:do{if(0<C[K>>1]<<16>>16){var M=r,L=0,E=a[g+(24*c&-1)>>2];for(q=E>>2;;){var yb=a[q+4];if(0==(yb|0)){var J=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),R=a[t>>2],i=3013}else{var Y=yb+16|0,Y=(a[b>>2]=a[Y>>2],a[b+4>>2]=a[Y+4>>2],f[b>>3]),Y=0<Y?Y:(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),H=a[yb>>2],H=0==(H|0)?a[t>>2]:H,yb=a[yb+4>>2];if(0==(yb|0)){J=Y,R=H,i=3013}else{var G=yb,P=Y,ea=H}}3013==i&&(i=0,G=a[j>>2],P=J,ea=R);eb(u,G);a[y>>2]=a[q];a[z>>2]=ea;f[b>>3]=P;a[B>>2]=a[b>>2];a[B+4>>2]=a[b+4>>2];yb=E+40|0;yb=(a[b>>2]=a[yb>>2],a[b+4>>2]=a[yb+4>>2],f[b>>3]);f[b>>3]=yb;a[F>>2]=a[b>>2];a[F+4>>2]=a[b+4>>2];f[b>>3]=1;a[D>>2]=a[b>>2];a[D+4>>2]=a[b+4>>2];a[S>>2]=a[q+1];a[Gb>>2]=a[q+2];q=(E+32|0)>>2;yb=(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3]);f[b>>3]=yb;a[A>>2]=a[b>>2];a[A+4>>2]=a[b+4>>2];yb=(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3]);f[b>>3]=yb;a[I>>2]=a[b>>2];a[I+4>>2]=a[b+4>>2];n[Z]=108;xj(u,M,T,x);L=L+1|0;if((L|0)<(C[K>>1]<<16>>16|0)){M+=(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3]),E=E+76|0,q=E>>2}else{break a}}}}while(0);c=c+1|0;if((c|0)==(s|0)){break}}}Mn(u);h=x}function Pg(b,s,g,e,c,d){var f,k,r=0,q=h;h=h+176|0;f=e>>2;e=h;h=h+32|0;a[e>>2]=a[f];a[e+4>>2]=a[f+1];a[e+8>>2]=a[f+2];a[e+12>>2]=a[f+3];a[e+16>>2]=a[f+4];a[e+20>>2]=a[f+5];a[e+24>>2]=a[f+6];a[e+28>>2]=a[f+7];k=q>>2;var m=q+16,w=q+48,x=b+16|0,v=a[x>>2];f=(v+148|0)>>2;var t=c|0;a[t>>2]=a[f];var y=v+168|0;a[c+4>>2]=a[y>>2];var z=v+184|0;a[c+8>>2]=a[z>>2];var B=v+152|0;a[c+12>>2]=a[B>>2];var F=v+200|0,c=c+16|0;n[c]=a[F>>2]<<31>>31&255;var D=a[g+16>>2];if(0==(D|0)){r=3021}else{if(0==n[D]<<24>>24){r=3021}else{var S=0,A=D}}if(3021==r){ac(q,128,w|0);S=s+52|0;A=a[S>>2];0==(A|0)&&(A=Hb(Ih(a[a[a[a[b>>2]+128>>2]+44>>2]+92>>2],a[v+8>>2]|0,q)),a[S>>2]=A,n[s+56|0]=1);s=A;Cb(q,s);s=m|0;m=a[1312804];a[1312804]=m+1|0;Pa(s,5342444,(i=h,h=h+4|0,a[i>>2]=m,i));Cb(q,s);s=(q+4|0)>>2;m=a[s];m>>>0<a[k+2]>>>0||(qa(q,1),m=a[s]);n[m]=0;m=a[k];a[s]=m;var S=1,C=A=m}g=dj(a[x>>2],a[b+148>>2],0,a[g>>2],a[g+12>>2],a[g+8>>2],A,a[v+8>>2]|0);S&&Xb(C,a[k+3]);if(0==(g|0)){return h=q,g}0!=(d|0)&&!(0==(a[t>>2]|0)&&0==n[c]<<24>>24)&&de(b);if(0==(a[f]|0)&&0==(a[F>>2]&1|0)){return h=q,g}Jh(b,e);Mc(b,a[f],a[y>>2],a[z>>2],a[B>>2]);h=q;return g}function Rn(b,s,g){var e,c=h;e=g>>2;g=h;h=h+32|0;a[g>>2]=a[e];a[g+4>>2]=a[e+1];a[g+8>>2]=a[e+2];a[g+12>>2]=a[e+3];a[g+16>>2]=a[e+4];a[g+20>>2]=a[e+5];a[g+24>>2]=a[e+6];a[g+28>>2]=a[e+7];Sb(b,s);eb(b,s);of(b,g,1);h=c}function Sn(u,s,g,e){var c,d=h;c=e>>2;e=h;h=h+32|0;a[e>>2]=a[c];a[e+4>>2]=a[c+1];a[e+8>>2]=a[c+2];a[e+12>>2]=a[c+3];a[e+16>>2]=a[c+4];a[e+20>>2]=a[c+5];a[e+24>>2]=a[c+6];a[e+28>>2]=a[c+7];s=0==(s|0)?5374748:s;Sb(u,s);eb(u,s);if(1==(g|0)){of(u,e,0)}else{s=e+24|0;s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]);c=e+8|0;c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);var j=s-c,k=e+16|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),e=e|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),r=k-e,q=g-1|0;Vh(u,e,c,q,j);g=1-g|0;Vh(u,e,s,r,g);Vh(u,k,s,g,-j);Vh(u,k,c,-r,q)}h=d}function Tn(u,s,g){var e,c,d,j,k=h;h=h+68|0;var r=k+36,q=s|0;j=r>>2;d=(s+40|0)>>2;a[j]=a[d];a[j+1]=a[d+1];a[j+2]=a[d+2];a[j+3]=a[d+3];a[j+4]=a[d+4];a[j+5]=a[d+5];a[j+6]=a[d+6];a[j+7]=a[d+7];d=g|0;e=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);d=g+8|0;j=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);d=0==(a[s>>2]|0)?0!=(a[s+8>>2]|0):1;c=(r|0)>>2;var m=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3])+e;f[b>>3]=m;a[c]=a[b>>2];a[c+1]=a[b+4>>2];c=(r+16|0)>>2;e=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3])+e;f[b>>3]=e;a[c]=a[b>>2];a[c+1]=a[b+4>>2];e=(r+8|0)>>2;c=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])+j;f[b>>3]=c;a[e]=a[b>>2];a[e+1]=a[b+4>>2];e=(r+24|0)>>2;j=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])+j;f[b>>3]=j;a[e]=a[b>>2];a[e+1]=a[b+4>>2];j=d?0!=(a[u+148>>2]&4|0)?0:Pg(u,g,q,r,k,1):0;e=a[s+20>>2];0!=(e|0)&&Rn(u,e,r);e=n[s+29|0];0!=e<<24>>24&&Sn(u,a[s+24>>2],e&255,r);e=(s+80|0)>>2;s=n[s+84|0];if(1==s<<24>>24){Lj(u,a[e],g)}else{if(3==s<<24>>24){e=a[e];s=h;h=h+64|0;c=e|0;m=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);c=e+8|0;c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);var i=e+16|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),x=e+24|0,x=(a[b>>2]=a[x>>2],a[b+4>>2]=a[x+4>>2],f[b>>3]),v=g|0,v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),m=m+v,t=g+8|0,t=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]);c+=t;i+=v;x+=t;v=s|0;f[b>>3]=i;a[v>>2]=a[b>>2];a[v+4>>2]=a[b+4>>2];v=s+8|0;f[b>>3]=x;a[v>>2]=a[b>>2];a[v+4>>2]=a[b+4>>2];v=s+32|0;f[b>>3]=m;a[v>>2]=a[b>>2];a[v+4>>2]=a[b+4>>2];v=s+40|0;f[b>>3]=c;a[v>>2]=a[b>>2];a[v+4>>2]=a[b+4>>2];v=s+16|0;f[b>>3]=m;a[v>>2]=a[b>>2];a[v+4>>2]=a[b+4>>2];m=s+24|0;f[b>>3]=x;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];m=s+48|0;f[b>>3]=i;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];m=s+56|0;f[b>>3]=c;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];c=a[e+36>>2];0==(c|0)&&(c=a[g+48>>2]);e=a[(e+32|0)>>2];Mj(u,e,s|0,4,1,c);h=s}else{Qn(u,a[e],g)}}0!=(j|0)&&Qg(u,k,1);d&&0!=(a[u+148>>2]&4|0)&&0!=(Pg(u,g,q,r,k,0)|0)&&Qg(u,k,0);h=k}function Qg(b,s,g){var e,c,d;e=0;var f=a[b+16>>2];d=(f+148|0)>>2;0==(a[d]|0)?0==(a[f+200>>2]&1|0)?c=0:e=3073:e=3073;3073==e&&(de(b),c=a[d]);e=s|0;(c|0)!=(a[e>>2]|0)&&(E(c),a[d]=a[e>>2]);c=(f+168|0)>>2;e=a[c];var k=s+4|0;(e|0)!=(a[k>>2]|0)&&(E(e),a[c]=a[k>>2]);e=(f+184|0)>>2;var k=a[e],r=s+8|0;(k|0)!=(a[r>>2]|0)&&(E(k),a[e]=a[r>>2]);var k=f+152|0,r=a[k>>2],h=s+12|0;(r|0)!=(a[h>>2]|0)&&(E(r),r=a[h>>2],a[k>>2]=r);k=r;s=n[s+16|0]&1;f=f+200|0;a[f>>2]=a[f>>2]&-2|s;0!=(g|0)&&(g=a[d],0==(g|0)&0==(s|0)||Mc(b,g,a[c],a[e],k))}function Vh(u,s,g,e,c){var d=h;h=h+32|0;var j=d|0;f[b>>3]=s;a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];j=d+8|0;f[b>>3]=g;a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];j=d+16|0;f[b>>3]=s+e;a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];s=d+24|0;f[b>>3]=g+c;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];of(u,d,1);h=d}function Nj(b,s,g){0==($n(b)|0)&&ao();if(1>(g|0)){return Oj(),0}b=U(b|0,5347964);b=0==(b|0)?30:Ee(b);a[1345322]=b;if(0==(bo()|0)){b=0}else{return Oj(),1}for(;;){var e=co();if(0==(e|0)){break}eo(e,fo(a[e+12>>2],a[e+16>>2]));b=b+1|0;if((b|0)>=(g|0)){break}}1==(s|0)?go():2==(s|0)?ho():io();return 0}function $n(b){var s;a[1345485]=b;a[1345323]=0;a[1345366]=0;a[1345355]=0;var b=b+216|0,g=a[b>>2];if(0==(g|0)){s=0}else{for(var e=0,c=0;;){n[g+163|0]=0;s=e+1|0;a[1345355]=s;e=a[g+184>>2];a:do{if(0==(a[e>>2]|0)){var d=c}else{for(var f=0,k=c;;){if(k=k+1|0,a[1345366]=k,f=f+1|0,0==(a[e+(f<<2)>>2]|0)){d=k;break a}}}}while(0);g=a[g+168>>2];if(0==(g|0)){break}else{e=s,c=d}}s<<=2}d=a[1345155];s=0==(d|0)?Za(s):Oa(d,s);a[1345155]=s;a[1345154]=0;s=a[1345157];s=0==(s|0)?Za(a[1345355]<<2):Oa(s,a[1345355]<<2);a[1345157]=s;a[1345156]=0;b=a[b>>2];if(0==(b|0)){var r;return 1}g=1;d=b;for(b=d>>2;;){s=(d+292|0)>>2;a[s]=0;d=d+176|0;e=a[a[d>>2]>>2];if(0==(e|0)){s=g,d=4}else{c=g;for(f=g=1;;){a[s]=f;a[e+168>>2]=0;a[e+172>>2]=-1;var h=0==(c|0)?0:(a[a[e+12>>2]+236>>2]-a[a[e+16>>2]+236>>2]|0)<(fc[e+178>>1]|0)?0:c,e=a[a[d>>2]+(g<<2)>>2];if(0==(e|0)){break}c=h;g=g+1|0;f=a[s]+1|0}s=h;d=(g<<2)+4|0}a[b+66]=da(d);a[b+67]=0;d=a[b+46];for(g=0;;){var m=g+1|0;if(0==(a[d+(g<<2)>>2]|0)){break}else{g=m}}a[b+68]=da(m<<2);a[b+69]=0;b=a[b+42];if(0==(b|0)){r=s;break}else{g=s,d=b,b=d>>2}}return r}function ao(){var b,s=h,g=rn(a[1345355]),e=a[a[1345485]+216>>2];a:do{if(0!=(e|0)){for(var c=e;;){if(0==(a[c+292>>2]|0)&&Ig(g,c),c=a[c+168>>2],0==(c|0)){break a}}}}while(0);e=Jg(g);a:do{if(0==(e|0)){b=0}else{for(var c=0,d=e;;){var f=d+236|0;a[f>>2]=0;var c=c+1|0,k=a[d+176>>2],r=a[k>>2];b:do{if(0!=(r|0)){for(var q=0,m=r,w=0;;){if(m=fc[m+178>>1]+a[a[m+16>>2]+236>>2]|0,w=(w|0)>(m|0)?w:m,a[f>>2]=w,q=q+1|0,m=a[k+(q<<2)>>2],0==(m|0)){break b}}}}while(0);d=d+184|0;f=a[a[d>>2]>>2];b:do{if(0!=(f|0)){k=0;for(r=f;;){if(r=r+12|0,q=a[r>>2]+292|0,w=a[q>>2]-1|0,a[q>>2]=w,1>(w|0)&&Ig(g,a[r>>2]),k=k+1|0,r=a[a[d>>2]+(k<<2)>>2],0==(r|0)){break b}}}}while(0);d=Jg(g);if(0==(d|0)){b=c;break a}}}}while(0);if((b|0)!=(a[1345355]|0)&&(aa(1,5337620,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),b=a[a[1345485]+216>>2],0!=(b|0))){for(b>>=2;!(e=a[b+73],0!=(e|0)&&aa(3,5334800,(i=h,h=h+8|0,a[i>>2]=a[b+3],a[i+4>>2]=e,i)),b=a[b+42],0==(b|0));){b>>=2}}E(a[g>>2]);E(g);h=s}function Oj(){var b;b=a[a[1345485]+216>>2];if(0!=(b|0)){var s=b;for(b=s>>2;;){var g=a[b+66];0!=(g|0)&&E(g);g=a[b+68];0!=(g|0)&&E(g);n[s+163|0]=0;b=a[b+42];if(0==(b|0)){break}else{s=b,b=s>>2}}}}function co(){for(var b=0,s=a[1345323],g=a[1345156],e=0,c=0,d=s;(d|0)<(g|0);){var f=a[a[1345157]+(d<<2)>>2],k=a[f+168>>2];if(0>(k|0)){if(k=0==(e|0)?f:(a[e+168>>2]|0)>(k|0)?f:e,f=c+1|0,(f|0)<(a[1345322]|0)){e=k,c=f}else{var r=k,b=16;break}}d=d+1|0;a[1345323]=d}if(16==b){return r}if(0<(s|0)){g=0}else{return e}for(;;){a[1345323]=g;if((g|0)>=(s|0)){r=e;b=18;break}d=a[a[1345157]+(g<<2)>>2];f=a[d+168>>2];if(0>(f|0)&&(e=0==(e|0)?d:(a[e+168>>2]|0)>(f|0)?d:e,c=c+1|0,(c|0)>=(a[1345322]|0))){r=e;b=19;break}g=g+1|0}if(18==b||19==b){return r}}function io(){a[1345373]=2147483647;a[1345375]=-2147483647;var b=a[a[1345485]+216>>2];a:do{if(0==(b|0)){var s=2147483647,g=-2147483647}else{for(var e=b,c=2147483647,d=-2147483647;;){if(0==n[e+162|0]<<24>>24){var f=a[e+236>>2],k=(c|0)<(f|0)?c:f;a[1345373]=k;d=(d|0)>(f|0)?d:f;a[1345375]=d;f=k}else{f=c}k=d;e=a[e+168>>2];if(0==(e|0)){break}else{c=f,d=k}}if(0==(f|0)){return}for(e=b;;){if(d=e+236|0,a[d>>2]=a[d>>2]-f|0,e=a[e+168>>2],0==(e|0)){s=f;g=k;break a}}}}while(0);a[1345375]=g-s|0;a[1345373]=0}function jo(b,s,g,e){var c,s=s+288|0,d=-g|0,f=0==(e|0)&1;for(c=b>>2;;){var k=a[s>>2];if((a[c+71]|0)<=(k|0)&&(k|0)<=(a[c+72]|0)){break}k=a[c+70];c=a[k+16>>2];var r=k+168|0;a[r>>2]=(0==(((b|0)==(c|0)?e:f)|0)?d:g)+a[r>>2]|0;b=a[k+12>>2];b=(a[c+288>>2]|0)>(a[b+288>>2]|0)?c:b;c=b>>2}return b}function ko(b,s){var g,e;e=(b+172|0)>>2;a[s+172>>2]=a[e];a[a[1345157]+(a[e]<<2)>>2]=s;a[e]=-1;var c=a[b+16>>2],d=c+276|0;e=a[d>>2]-1|0;a[d>>2]=e;for(var c=c+272|0,d=a[c>>2],f=0;;){var k=(f<<2)+d|0;if((f|0)>(e|0)){var r=k;break}if((a[k>>2]|0)==(b|0)){r=k;break}else{f=f+1|0}}a[r>>2]=a[d+(e<<2)>>2];a[a[c>>2]+(e<<2)>>2]=0;e=a[b+12>>2];c=e+268|0;r=a[c>>2]-1|0;a[c>>2]=r;e=e+264|0;c=a[e>>2];for(d=0;;){f=(d<<2)+c|0;if((d|0)>(r|0)){g=f;break}if((a[f>>2]|0)==(b|0)){g=f;break}else{d=d+1|0}}a[g>>2]=a[c+(r<<2)>>2];a[a[e>>2]+(r<<2)>>2]=0;e=a[s+16>>2];g=(e+276|0)>>2;r=a[g];a[g]=r+1|0;e=e+272|0;a[a[e>>2]+(r<<2)>>2]=s;a[a[e>>2]+(a[g]<<2)>>2]=0;e=a[s+12>>2];g=(e+268|0)>>2;r=a[g];a[g]=r+1|0;e=e+264|0;a[a[e>>2]+(r<<2)>>2]=s;a[a[e>>2]+(a[g]<<2)>>2]=0}function bo(){var b=0;if(2>(a[1345355]|0)){var s;return 0}a:for(;;){if((lo()|0)>=(a[1345355]|0)){b=58;break}var g=a[a[1345485]+216>>2];if(0==(g|0)){s=1;b=62;break}else{var e=0}for(;;){var c=a[g+184>>2],d=a[c>>2];b:do{if(0==(d|0)){var f=e}else{for(var k=e,r=0,h=d;;){if(0>(a[h+172>>2]|0)){var m=a[h+12>>2],i=a[h+16>>2],k=0==(mo(m,i)|0)?k:0!=(k|0)&&(a[m+236>>2]-a[i+236>>2]-fc[h+178>>1]|0)>=(a[a[k+12>>2]+236>>2]-a[a[k+16>>2]+236>>2]-fc[k+178>>1]|0)?k:h}r=r+1|0;h=a[c+(r<<2)>>2];if(0==(h|0)){f=k;break b}}}}while(0);g=a[g+168>>2];if(0==(g|0)){break}else{e=f}}if(0==(f|0)){s=1;b=63;break}e=a[f+12>>2];g=a[f+16>>2];c=a[e+236>>2]-a[g+236>>2]|0;d=fc[f+178>>1];k=c-d|0;if((c|0)!=(d|0)&&(e=(mo(e,g)|0)==(e|0)?-k|0:k,g=a[1345154],0<(g|0))){c=a[1345155];for(d=0;;){if(k=a[c+(d<<2)>>2]+236|0,a[k>>2]=a[k>>2]+e|0,d=d+1|0,(d|0)>=(g|0)){continue a}}}}if(58==b){return b=a[1345485]+216|0,Rg(a[b>>2],0,1),Pj(a[b>>2],0),0}if(62==b||63==b){return s}}function fo(b,s){var g=(a[s+288>>2]|0)<(a[b+288>>2]|0),e=g?s:b;a[1345489]=0;a[1345165]=2147483647;a[1345377]=a[e+284>>2];a[1345380]=a[e+288>>2];g?Wh(e):Xh(e);return g=a[1345489]}function go(){var b,s;io();var g=da((a[1345375]<<2)+4|0);s=g>>2;b=a[1345375];a:do{if(0<=(b|0)){for(var e=0;;){if(a[(e<<2>>2)+s]=0,e=e+1|0,(e|0)>(b|0)){break a}}}}while(0);b=a[1345485]+216|0;e=a[b>>2];if(0!=(e|0)){for(;;){if(0==n[e+162|0]<<24>>24){var c=(a[e+236>>2]<<2)+g|0;a[c>>2]=a[c>>2]+1|0}e=a[e+168>>2];if(0==(e|0)){break}}b=a[b>>2];if(0!=(b|0)){e=b;for(b=e>>2;;){if(0==n[e+162|0]<<24>>24){var c=a[1345375],d=a[b+44],f=a[d>>2];a:do{if(0==(f|0)){var k=0,h=0}else{for(var q=0,m=0,i=0,x=f;;){if(q=q+hb[x+164>>2]&-1,x=fc[x+178>>1]+a[a[x+16>>2]+236>>2]|0,m=(m|0)>(x|0)?m:x,i=i+1|0,x=a[d+(i<<2)>>2],0==(x|0)){k=q;h=m;break a}}}}while(0);d=a[b+46];f=a[d>>2];a:do{if(0==(f|0)){var v=0,t=c}else{q=0;m=c;i=0;for(x=f;;){if(q=q+hb[x+164>>2]&-1,x=a[a[x+12>>2]+236>>2]-fc[x+178>>1]|0,m=(m|0)<(x|0)?m:x,i=i+1|0,x=a[d+(i<<2)>>2],0==(x|0)){v=q;t=m;break a}}}}while(0);c=0>(h|0)?0:h;if((k|0)==(v|0)){d=c+1|0;a:do{if((d|0)>(t|0)){var y=c}else{f=c;for(m=d;;){if(f=(a[(m<<2>>2)+s]|0)<(a[(f<<2>>2)+s]|0)?m:f,m=m+1|0,(m|0)>(t|0)){y=f;break a}}}}while(0);c=e+236|0;d=(a[c>>2]<<2)+g|0;a[d>>2]=a[d>>2]-1|0;d=(y<<2)+g|0;a[d>>2]=a[d>>2]+1|0;a[c>>2]=y}c=a[b+66];0!=(c|0)&&E(c);c=a[b+68];0!=(c|0)&&E(c);n[e+163|0]=0}b=a[b+42];if(0==(b|0)){break}else{e=b,b=e>>2}}}}E(g)}function ho(){var b=a[1345156];if(0<(b|0)){for(var s=a[1345157],g=0;;){var e=a[s+(g<<2)>>2];if(0==(a[e+168>>2]|0)){var c=e+12|0,d=e+16|0,e=fo(a[c>>2],a[d>>2]);0!=(e|0)&&(e=a[a[e+12>>2]+236>>2]-a[a[e+16>>2]+236>>2]-fc[e+178>>1]|0,2>(e|0)||(d=a[d>>2],c=a[c>>2],(a[d+288>>2]|0)<(a[c+288>>2]|0)?He(d,(e|0)/2&-1):He(c,(e|0)/-2&-1)))}g=g+1|0;if((g|0)>=(b|0)){break}}}Oj()}function He(b,s){var g=b+236|0;a[g>>2]=a[g>>2]-s|0;var g=b+272|0,e=a[g>>2],c=a[e>>2];a:do{if(0!=(c|0)){for(var d=b+280|0,f=1,k=c,h=e;;){(k|0)!=(a[d>>2]|0)&&(He(a[k+12>>2],s),h=a[g>>2]);k=a[h+(f<<2)>>2];if(0==(k|0)){break a}f=f+1|0}}}while(0);g=b+264|0;f=a[g>>2];d=a[f>>2];if(0!=(d|0)){e=b+280|0;for(c=1;;){(d|0)!=(a[e>>2]|0)&&(He(a[d+16>>2],s),f=a[g>>2]);d=a[f+(c<<2)>>2];if(0==(d|0)){break}c=c+1|0}}}function eo(b,s){var g,e,c,d;d=(s+12|0)>>2;c=(s+16|0)>>2;var f=a[a[d]+236>>2]-a[a[c]+236>>2]-fc[s+178>>1]|0;if(0<(f|0)){var k=a[b+16>>2];e=k>>2;if(1==(a[e+69]+a[e+67]|0)){He(k,f)}else{var h=a[b+12>>2];g=h>>2;1==(a[g+69]+a[g+67]|0)?He(h,-f|0):(a[e+72]|0)<(a[g+72]|0)?He(k,f):He(h,-f|0)}}g=b+168|0;e=a[g>>2];f=jo(a[c],a[d],e,1);(jo(a[d],a[c],e,0)|0)==(f|0)?(a[s+168>>2]=-e|0,a[g>>2]=0,ko(b,s),Rg(f,a[f+280>>2],a[f+284>>2])):P()}function mo(a,b){var g=0,e=0==n[a+163|0]<<24>>24;if(0==n[b+163|0]<<24>>24){if(e){g=137}else{var c=a}}else{e?c=b:g=137}137==g&&(c=0);return c}function Qj(b,s,g){var b=b>>2,e=0,c=a[b+4],d=(c|0)==(s|0),c=a[(d?a[b+3]:c)+288>>2];if((a[s+284>>2]|0)>(c|0)){e=143}else{if((c|0)>(a[s+288>>2]|0)){e=143}else{var f=0,k=(-1<(a[b+43]|0)?a[b+42]|0:0)-hb[b+41]}}143==e&&(f=1,k=hb[b+41]);k&=-1;s=0<(g|0)?(a[b+3]|0)==(s|0)?1:-1:d?1:-1;f=0==(f|0)?s:-s|0;return f=0>(f|0)?-k|0:k}function Rg(b,s,g){a[b+280>>2]=s;a[b+284>>2]=g;var e=b+272|0,c=a[e>>2],d=a[c>>2];a:do{if(0==(d|0)){var f=g}else{for(var k=0,h=g,q=d,m=c;;){if((q|0)!=(s|0)&&(h=Rg(a[q+12>>2],q,h),m=a[e>>2]),k=k+1|0,q=a[m+(k<<2)>>2],0==(q|0)){f=h;break a}}}}while(0);g=b+264|0;c=a[g>>2];d=a[c>>2];if(0==(d|0)){var i=f;a[(b+288|0)>>2]=i;return i+1|0}for(e=0;;){if((d|0)!=(s|0)&&(f=Rg(a[d+16>>2],d,f),c=a[g>>2]),e=e+1|0,d=a[c+(e<<2)>>2],0==(d|0)){i=f;break}}a[(b+288|0)>>2]=i;return i+1|0}function Xh(b){var s=b+184|0,g=a[s>>2],e=a[g>>2];a:do{if(0!=(e|0)){for(var c=b+288|0,d=0,f=e,k=g;;){if(0>(a[f+172>>2]|0)){var h=a[f+12>>2],q=a[h+288>>2];(a[1345377]|0)>(q|0)|(q|0)>(a[1345380]|0)&&(h=a[h+236>>2]-a[a[f+16>>2]+236>>2]-fc[f+178>>1]|0,(h|0)<(a[1345165]|0)|0==(a[1345489]|0)&&(a[1345489]=f,a[1345165]=h))}else{f=a[f+12>>2],(a[f+288>>2]|0)<(a[c>>2]|0)&&(Xh(f),k=a[s>>2])}d=d+1|0;f=a[k+(d<<2)>>2];if(0==(f|0)){break a}}}}while(0);s=b+264|0;d=a[s>>2];e=a[d>>2];c=a[1345165];if(0!=(e|0)&0<(c|0)){b=b+288|0;for(g=1;;){e=a[e+16>>2];(a[e+288>>2]|0)<(a[b>>2]|0)&&(Xh(e),d=a[s>>2],c=a[1345165]);e=a[d+(g<<2)>>2];if(!(0!=(e|0)&0<(c|0))){break}g=g+1|0}}}function Wh(b){var s=b+176|0,g=a[s>>2],e=a[g>>2];a:do{if(0!=(e|0)){for(var c=b+288|0,d=0,f=e,k=g;;){if(0>(a[f+172>>2]|0)){var h=a[f+16>>2],q=a[h+288>>2];(a[1345377]|0)>(q|0)|(q|0)>(a[1345380]|0)&&(h=a[a[f+12>>2]+236>>2]-a[h+236>>2]-fc[f+178>>1]|0,(h|0)<(a[1345165]|0)|0==(a[1345489]|0)&&(a[1345489]=f,a[1345165]=h))}else{f=a[f+16>>2],(a[f+288>>2]|0)<(a[c>>2]|0)&&(Wh(f),k=a[s>>2])}d=d+1|0;f=a[k+(d<<2)>>2];if(0==(f|0)){break a}}}}while(0);s=b+272|0;d=a[s>>2];e=a[d>>2];c=a[1345165];if(0!=(e|0)&0<(c|0)){b=b+288|0;for(g=1;;){e=a[e+12>>2];(a[e+288>>2]|0)<(a[b>>2]|0)&&(Wh(e),d=a[s>>2],c=a[1345165]);e=a[d+(g<<2)>>2];if(!(0!=(e|0)&0<(c|0))){break}g=g+1|0}}}function lo(){var b,s=a[1345485]+216|0,g=a[s>>2];a:do{if(0!=(g|0)){var e=g;for(b=e>>2;;){if(n[e+163|0]=0,a[a[b+68]>>2]=0,a[a[b+66]>>2]=0,a[b+69]=0,a[b+67]=0,b=a[b+42],0==(b|0)){break a}else{e=b,b=e>>2}}}}while(0);g=a[1345156];a:do{if(0<(g|0)){b=a[1345157];for(e=0;;){if(a[a[b+(e<<2)>>2]+172>>2]=-1,e=e+1|0,(e|0)>=(g|0)){break a}}}}while(0);a[1345156]=0;a[1345154]=0;s=a[s>>2];if(0==(s|0)){return 0}for(;!(Yh(s),s=a[s+168>>2],!(0!=(s|0)&0==(a[1345156]|0)));){}return s=a[1345154]}function Pj(b,s){var g=b+272|0,e=a[g>>2],c=a[e>>2];a:do{if(0!=(c|0)){for(var d=0,f=c,k=e;;){if((f|0)!=(s|0)&&(Pj(a[f+12>>2],f),k=a[g>>2]),d=d+1|0,f=a[k+(d<<2)>>2],0==(f|0)){break a}}}}while(0);g=b+264|0;e=a[g>>2];c=a[e>>2];a:do{if(0!=(c|0)){d=0;f=c;for(k=e;;){if((f|0)!=(s|0)&&(Pj(a[f+16>>2],f),k=a[g>>2]),d=d+1|0,f=a[k+(d<<2)>>2],0==(f|0)){break a}}}}while(0);if(0!=(s|0)){e=a[s+16>>2];(a[e+280>>2]|0)==(s|0)?g=1:(g=-1,e=a[s+12>>2]);c=a[e+184>>2];d=a[c>>2];a:do{if(0==(d|0)){var h=0}else{for(var f=k=0,q=d;;){if(k=Qj(q,e,g)+k|0,f=f+1|0,q=a[c+(f<<2)>>2],0==(q|0)){h=k;break a}}}}while(0);c=a[e+176>>2];k=a[c>>2];if(0==(k|0)){var m=h}else{for(d=0;;){if(h=Qj(k,e,g)+h|0,d=d+1|0,k=a[c+(d<<2)>>2],0==(k|0)){m=h;break}}}h=s+168|0;a[h>>2]=m}}function Yh(b){var s=0,g=b+184|0,e=0;a:for(;;){var c=a[a[g>>2]+(e<<2)>>2];if(0==(c|0)){s=236;break}var d=c+12|0,f=a[d>>2];do{if(0==n[f+163|0]<<24>>24&&(a[f+236>>2]-a[a[c+16>>2]+236>>2]|0)==(fc[c+178>>1]|0)){Rj(c);if((a[1345156]|0)==(a[1345355]-1|0)){var k=1,s=253;break a}if(0!=(Yh(a[d>>2])|0)){k=1;s=251;break a}}}while(0);e=e+1|0}if(251==s||253==s){return k}if(236==s){b=b+176|0;g=0;a:for(;;){e=a[a[b>>2]+(g<<2)>>2];if(0==(e|0)){k=0;s=250;break}c=e+16|0;d=a[c>>2];do{if(0==n[d+163|0]<<24>>24&&(a[a[e+12>>2]+236>>2]-a[d+236>>2]|0)==(fc[e+178>>1]|0)){Rj(e);if((a[1345156]|0)==(a[1345355]-1|0)){k=1;s=252;break a}if(0!=(Yh(a[c>>2])|0)){k=1;s=249;break a}}}while(0);g=g+1|0}if(252==s||249==s||250==s){return k}}}function Sj(u,s){var g,e,c,d,j,k=h;h=h+144|0;var r=k+16,q=k+32,m=k+48,i=k+64,n=k+80,v=k+96,t=k+112;g=k+128;j=(u+52|0)>>2;var y=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3]);d=(u+60|0)>>2;var z=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);c=(u+68|0)>>2;var B=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3]);e=(u+76|0)>>2;var F=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);2>(s-1|0)>>>0?(uf(k,y,F),t=k|0,v=k+8|0,Ed(r,(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3])),t=r|0,t=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),v=r+8|0,v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),uf(q,B,z),B=q|0,q=q+8|0,Ed(m,(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])),B=m|0,q=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),B=m+8|0,B=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),z=q,q=v,m=t):(uf(i,y,z),m=i|0,q=i+8|0,Ed(n,(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])),m=n|0,m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),q=n+8|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),uf(v,B,F),B=v|0,v=v+8|0,Ed(t,(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3])),B=t|0,v=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),B=t+8|0,B=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),z=v);f[b>>3]=m;a[j]=a[b>>2];a[j+1]=a[b+4>>2];f[b>>3]=q;a[d]=a[b>>2];a[d+1]=a[b+4>>2];f[b>>3]=z;a[c]=a[b>>2];a[c+1]=a[b+4>>2];f[b>>3]=B;a[e]=a[b>>2];a[e+1]=a[b+4>>2];d=a[u+48>>2];0!=(d|0)&&(e=d+56|0,c=e|0,d=d+64|0,Ed(g,(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])),e>>=2,g>>=2,a[e]=a[g],a[e+1]=a[g+1],a[e+2]=a[g+2],a[e+3]=a[g+3]);g=u+208|0;if(1<=(a[g>>2]|0)){e=u+212|0;for(c=1;!(Sj(a[a[e>>2]+(c<<2)>>2],s),c=c+1|0,(c|0)>(a[g>>2]|0));){}}h=k}function Rj(b){var s,g;s=b+172|0;-1<(a[s>>2]|0)&&P();g=a[1345156];a[s>>2]=g;a[1345156]=g+1|0;a[a[1345157]+(g<<2)>>2]=b;g=b+16|0;s=a[g>>2];if(0==n[s+163|0]<<24>>24){var e=a[1345154];a[1345154]=e+1|0;a[a[1345155]+(e<<2)>>2]=s}s=b+12|0;e=a[s>>2];if(0==n[e+163|0]<<24>>24){var c=a[1345154];a[1345154]=c+1|0;a[a[1345155]+(c<<2)>>2]=e}e=a[g>>2];n[e+163|0]=1;g=(e+276|0)>>2;c=a[g];a[g]=c+1|0;var d=e+272|0;a[a[d>>2]+(c<<2)>>2]=b;a[a[d>>2]+(a[g]<<2)>>2]=0;0==(a[a[e+184>>2]+(a[g]-1<<2)>>2]|0)&&P();g=a[s>>2];n[g+163|0]=1;s=(g+268|0)>>2;e=a[s];a[s]=e+1|0;c=g+264|0;a[a[c>>2]+(e<<2)>>2]=b;a[a[c>>2]+(a[s]<<2)>>2]=0;0==(a[a[g+176>>2]+(a[s]-1<<2)>>2]|0)&&P()}function uf(u,s,g){var e=u|0;f[b>>3]=s;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];u=u+8|0;f[b>>3]=g;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}function Ed(u,s,g){var e=h;h=h+16|0;Wf(e,s,g,90*a[1345336]&-1);var s=e|0,s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]),g=e+8|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),s=s-(a[b>>2]=a[1345338],a[b+4>>2]=a[1345339],f[b>>3]),g=g-(a[b>>2]=a[1345340],a[b+4>>2]=a[1345341],f[b>>3]),c=u|0;f[b>>3]=s;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];u=u+8|0;f[b>>3]=g;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2];h=e}function Tj(u){var s,g,e,c=h;h=h+48|0;s=c+16;var d=c+32,j=u+20|0,k=ha(a[j>>2]);if(0!=(k|0)){for(;;){var r,q=k+24|0,m=a[k+124>>2];if(0!=(m|0)){g=q+8|0;e=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);g=q+16|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);var q=q+88|0,i=m+24|0;r=r+(e+(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]))+.5*(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);e=m+56|0;f[b>>3]=r;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];e=m+64|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];n[m+81|0]=1}m=r;k=sa(a[j>>2],k);if(0==(k|0)){break}else{r=m}}}j=a[u+152>>2];k=j&3;a[1345336]=k;j&=1;n[5381944]=j;(g=0==j<<24>>24)?Uj(u):Vj(u);j=u+48|0;r=a[j>>2];if(0==(r|0)){r=m=0}else{if(0!=n[r+81|0]<<24>>24){r=m=0}else{m=r+24|0;r=r+32|0;m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])+16;r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3])+8;e=0!=(n[u+283|0]&1)<<24>>24;if(g){g=0==(k|0);e?g?(g=(u+76|0)>>2,e=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])+r):(g=(u+60|0)>>2,e=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])-r):g?(g=(u+60|0)>>2,e=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])-r):(g=(u+76|0)>>2,e=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])+r);f[b>>3]=e;a[g]=a[b>>2];a[g+1]=a[b+4>>2];e=(u+68|0)>>2;q=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);g=(u+52|0)>>2;var i=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]),x=q-i}else{e?(g=(u+68|0)>>2,e=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])+r):(g=(u+52|0)>>2,e=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])-r),f[b>>3]=e,a[g]=a[b>>2],a[g+1]=a[b+4>>2],e=(u+76|0)>>2,q=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),g=(u+60|0)>>2,i=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]),x=q-i}m>x&&(x=.5*(m-x),f[b>>3]=i-x,a[g]=a[b>>2],a[g+1]=a[b+4>>2],f[b>>3]=q+x,a[e]=a[b>>2],a[e+1]=a[b+4>>2])}}0==(k|0)?(s=(u+52|0)>>2,a[1345338]=a[s],a[1345339]=a[s+1],a[1345340]=a[s+2],a[1345341]=a[s+3]):1==(k|0)?(s=u+76|0,d=u+52|0,uf(c,-(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]),(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])),s=c>>2,a[1345338]=a[s],a[1345339]=a[s+1],a[1345340]=a[s+2],a[1345341]=a[s+3]):2==(k|0)?(d=u+52|0,k=u+76|0,uf(s,(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])),s>>=2,a[1345338]=a[s],a[1345339]=a[s+1],a[1345340]=a[s+2],a[1345341]=a[s+3]):3==(k|0)&&(s=u+60|0,k=u+52|0,uf(d,(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]),(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])),s=d>>2,a[1345338]=a[s],a[1345339]=a[s+1],a[1345340]=a[s+2],a[1345341]=a[s+3]);no(u);s=a[j>>2];0!=(s|0)&&0==n[s+81|0]<<24>>24&&(j=m,s=r,d=n[u+283|0],k=d<<24>>24,0==(k&4|0)?(m=u+52|0,m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),0==(k&2|0)?(j=u+68|0,j=.5*(m+(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]))):j=m+.5*j):(k=u+68|0,j=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])-.5*j),0==(d&1)<<24>>24?(d=u+60|0,s=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])+.5*s):(d=u+76|0,s=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])-.5*s),u=u+48|0,d=a[u>>2],k=d+56|0,f[b>>3]=j,a[k>>2]=a[b>>2],a[k+4>>2]=a[b+4>>2],d=d+64|0,f[b>>3]=s,a[d>>2]=a[b>>2],a[d+4>>2]=a[b+4>>2],n[a[u>>2]+81|0]=1);h=c}function Vj(u){if((a[u+32>>2]|0)!=(u|0)){var s=u+48|0,g=a[s>>2];if(0!=(g|0)&&0==n[g+81|0]<<24>>24){var e=n[u+283|0];if(0==(e&1)<<24>>24){var c=u+132|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),d=u+52|0,c=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])+.5*c,d=u+140|0}else{c=u+100|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),d=u+68|0,c=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])-.5*c,d=u+108|0}d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);e=e<<24>>24;0==(e&4|0)?0==(e&2|0)?(e=u+60|0,d=u+76|0,e=.5*((a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])+(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]))):(e=u+76|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-.5*d):(e=u+60|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])+.5*d);d=g+56|0;f[b>>3]=c;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];g=g+64|0;f[b>>3]=e;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];n[a[s>>2]+81|0]=1}}s=u+208|0;if(1<=(a[s>>2]|0)){u=u+212|0;for(g=1;!(Vj(a[a[u>>2]+(g<<2)>>2]),g=g+1|0,(g|0)>(a[s>>2]|0));){}}}function Uj(u){if((a[u+32>>2]|0)!=(u|0)){var s=u+48|0,g=a[s>>2];if(0!=(g|0)&&0==n[g+81|0]<<24>>24){var e=n[u+283|0];if(0==(e&1)<<24>>24){var c=u+92|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),d=u+60|0,c=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])+.5*c,d=u+84|0}else{c=u+124|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),d=u+76|0,c=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])-.5*c,d=u+116|0}d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);e=e<<24>>24;if(0==(e&4|0)){var j=u+52|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);0==(e&2|0)?(e=u+68|0,e=.5*(j+(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]))):e=j+.5*d}else{e=u+68|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-.5*d}d=g+56|0;f[b>>3]=e;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];g=g+64|0;f[b>>3]=c;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];n[a[s>>2]+81|0]=1}}s=u+208|0;if(1<=(a[s>>2]|0)){u=u+212|0;for(g=1;!(Uj(a[a[u>>2]+(g<<2)>>2]),g=g+1|0,(g|0)>(a[s>>2]|0));){}}}function no(u){var s,g,e,c=h;h=h+32|0;var d=c+16;if(0==(a[b>>2]=a[1345338],a[b+4>>2]=a[1345339],f[b>>3])){if(!(0!=(a[b>>2]=a[1345340],a[b+4>>2]=a[1345341],f[b>>3])|0!=(a[1345336]|0))){h=c;return}}var j=u+20|0,k=ha(a[j>>2]);a:do{if(0!=(k|0)){e=c>>2;g=d>>2;for(var r=u+28|0,q=k;;){0!=(a[1345336]|0)&&Hj(q,0);var m=s=q+32|0,i=q+40|0;Ed(c,(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]));s>>=2;a[s]=a[e];a[s+1]=a[e+1];a[s+2]=a[e+2];a[s+3]=a[e+3];m=a[q+124>>2];0!=(m|0)&&(i=m+56|0,s=i>>2,m=m+64|0,Ed(d,(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])),a[s]=a[g],a[s+1]=a[g+1],a[s+2]=a[g+2],a[s+3]=a[g+3]);b:do{if(1==(a[1345163]|0)&&(s=zb(u,q),0!=(s|0))){for(;;){if(oo(s),s=Db(a[r>>2],s),0==(s|0)){break b}}}}while(0);q=sa(a[j>>2],q);if(0==(q|0)){break a}}}}while(0);Sj(u,a[u+152>>2]&3);h=c}function oo(u){var s,g,e,c,d,j,k,r,q,m,w;g=u>>2;var x=h;h=h+112|0;var v=x+16,t=x+32;d=x+48;c=x+64;e=x+80;s=x+96;j=(u+24|0)>>2;var y=a[j];if(0==(y|0)){if(0!=n[5382112]<<24>>24&&6==n[u+124|0]<<24>>24){h=x;return}s=a[a[g+3]+12>>2];aa(1,5347924,(i=h,h=h+8|0,a[i>>2]=a[a[g+4]+12>>2],a[i+4>>2]=s,i))}else{a:do{if(0<(a[y+4>>2]|0)){w=t>>2;m=v>>2;var u=x>>2,z=0;for(k=y;;){k=a[k>>2]>>2;r=a[((48*z&-1)>>2)+k];var B=a[((48*z&-1)+4>>2)+k],F=a[((48*z&-1)+8>>2)+k];k=a[((48*z&-1)+12>>2)+k];b:do{if(0<(B|0)){for(var D=0;;){q=(D<<4)+r|0;var S=q|0,A=(D<<4)+r+8|0;Ed(x,(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3]),(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]));q>>=2;a[q]=a[u];a[q+1]=a[u+1];a[q+2]=a[u+2];a[q+3]=a[u+3];D=D+1|0;if((D|0)==(B|0)){break b}}}}while(0);0!=(F|0)&&(F=a[a[j]>>2],r=F+(48*z&-1)+16|0,B=r|0,F=F+(48*z&-1)+24|0,Ed(v,(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3])),r>>=2,a[r]=a[m],a[r+1]=a[m+1],a[r+2]=a[m+2],a[r+3]=a[m+3]);0!=(k|0)&&(B=a[a[j]>>2],k=B+(48*z&-1)+32|0,r=k|0,B=B+(48*z&-1)+40|0,Ed(t,(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3])),k>>=2,a[k]=a[w],a[k+1]=a[w+1],a[k+2]=a[w+2],a[k+3]=a[w+3]);z=z+1|0;k=a[j];if((z|0)>=(a[k+4>>2]|0)){break a}}}}while(0);t=a[g+27];0!=(t|0)&&(j=t+56|0,v=j|0,t=t+64|0,Ed(d,(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3])),j>>=2,d>>=2,a[j]=a[d],a[j+1]=a[d+1],a[j+2]=a[d+2],a[j+3]=a[d+3]);v=a[g+30];0!=(v|0)&&(d=v+56|0,j=d|0,v=v+64|0,Ed(c,(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3])),d>>=2,c>>=2,a[d]=a[c],a[d+1]=a[c+1],a[d+2]=a[c+2],a[d+3]=a[c+3]);j=a[g+28];0!=(j|0)&&(c=j+56|0,d=c|0,j=j+64|0,Ed(e,(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])),c>>=2,e>>=2,a[c]=a[e],a[c+1]=a[e+1],a[c+2]=a[e+2],a[c+3]=a[e+3]);c=a[g+29];0!=(c|0)&&(g=c+56|0,e=g|0,c=c+64|0,Ed(s,(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])),g>>=2,s>>=2,a[g]=a[s],a[g+1]=a[s+1],a[g+2]=a[s+2],a[g+3]=a[s+3])}h=x}function Wj(u,s,g,e,c,d,j){var k,r,q,m=h;h=h+88|0;var i=m+8;q=i>>2;var n=m+16;r=m+24;var v=m+56;k=m|0;a[k>>2]=c;c=m+4|0;a[c>>2]=8;var t=r|0;f[b>>3]=u;a[t>>2]=a[b>>2];a[t+4>>2]=a[b+4>>2];u=r+8|0;f[b>>3]=s;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2];s=r+16|0;f[b>>3]=g;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];g=r+24|0;f[b>>3]=e;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];if(-1==(Xj(m,r|0,i)|0)){return h=m,0}do{if(0==(j|0)){e=a[c>>2];i=a[1314330];(e|0)>(a[1314331]|0)&&(i=0==(i|0)?Za(e<<5):Oa(i,e<<5),a[1314330]=i,a[1314331]=e);a:do{if(0<(e|0)){r=a[k>>2];for(g=0;;){if(u=((g<<5)+i|0)>>2,s=((g<<4)+r|0)>>2,a[u]=a[s],a[u+1]=a[s+1],a[u+2]=a[s+2],a[u+3]=a[s+3],s=g+1|0,u=((g<<5)+i+16|0)>>2,g=(((s|0)%(e|0)<<4)+r|0)>>2,a[u]=a[g],a[u+1]=a[g+1],a[u+2]=a[g+2],a[u+3]=a[g+3],(s|0)<(e|0)){g=s}else{break a}}}}while(0);r=v>>2;a[r]=0;a[r+1]=0;a[r+2]=0;a[r+3]=0;a[r+4]=0;a[r+5]=0;a[r+6]=0;a[r+7]=0;if(-1==(po(i,e,a[q],a[q+1],v|0,n)|0)){return d=0,h=m,d}}else{Yj(a[q],a[q+1],n)}}while(0);j=a[n+4>>2];qo(j);q=a[1311892];a:do{if(0<(j|0)){v=a[n>>2];for(e=0;;){if(c=((e<<4)+q|0)>>2,k=((e<<4)+v|0)>>2,a[c]=a[k],a[c+1]=a[k+1],a[c+2]=a[k+2],a[c+3]=a[k+3],k=e+1|0,(k|0)<(j|0)){e=k}else{var y=q;break a}}}else{y=q}}while(0);a[d>>2]=j;h=m;return y}function qo(b){var s=h,g=a[1312721];(g|0)<(b|0)&&(b=g+(b+300)-(b|0)%300|0,g=Oa(a[1311892],b<<4),a[1311892]=g,0==(g|0)&&(aa(1,5347900,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),P()),a[1312721]=b);h=s}function le(u,s,g){var e,c,d,j,k,r,q,m,w,x,v,t,y,z,B,F,D,S,A,C,I,Z,T,K,M,L,E=0,yb=h;h=h+88|0;var J=yb+8;L=J>>2;var R=yb+16,Y=yb+24,H=yb+56;a[1312709]=a[1312709]+1|0;var G=a[u+80>>2];a[1312710]=a[1312710]+G|0;var N=a[u+88>>2];for(M=N>>2;;){if(0==(N|0)){E=450;break}if(0==n[N+124|0]<<24>>24){break}N=a[M+32];M=N>>2}450==E&&(aa(1,5344032,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),P());var ea=a[u+84>>2];ro(G,ea,u);var wa=G<<3;if((wa|0)>(a[1312209]|0)){var Fb=a[1312208],V=0==(Fb|0)?Za(G<<7):Oa(Fb,G<<7);a[1312208]=V;a[1312209]=wa}a:do{if(1<(G|0)){var W=ea+8|0,X=(a[b>>2]=a[W>>2],a[b+4>>2]=a[W+4>>2],f[b>>3]),ba=ea+40|0;if(X>(a[b>>2]=a[ba>>2],a[b+4>>2]=a[ba+4>>2],f[b>>3])){if(0<(G|0)){for(var ma=0,ib=X;;){K=((ma<<5)+ea+24|0)>>2;var U=(a[b>>2]=a[K],a[b+4>>2]=a[K+1],f[b>>3]),mc=(ma<<5)+ea+8|0;f[b>>3]=-1*ib;a[K]=a[b>>2];a[K+1]=a[b+4>>2];f[b>>3]=-U;a[mc>>2]=a[b>>2];a[mc+4>>2]=a[b+4>>2];var O=ma+1|0;if((O|0)==(G|0)){Tb=1;break a}var ga=(O<<5)+ea+8|0,ma=O,ib=(a[b>>2]=a[ga>>2],a[b+4>>2]=a[ga+4>>2],f[b>>3])}}else{Tb=1}}else{var Tb=0}}else{Tb=0}}while(0);(a[M+4]|0)==(a[M+3]|0)&&P();var Q=G-1|0,ua=a[1312208],Da=0,Ja=0;a:for(;;){if((Ja|0)>=(G|0)){var Ab=Da,ra=Q;break}if(0<(Ja|0)){var da=(Ja<<5)+ea+8|0,ya=(Ja-1<<5)+ea+8|0,ja=(a[b>>2]=a[da>>2],a[b+4>>2]=a[da+4>>2],f[b>>3])>(a[b>>2]=a[ya>>2],a[b+4>>2]=a[ya+4>>2],f[b>>3])?-1:1}else{ja=0}if((Ja|0)<(Q|0)){var la=(Ja+1<<5)+ea+8|0,va=(Ja<<5)+ea+8|0,oa=(a[b>>2]=a[la>>2],a[b+4>>2]=a[la+4>>2],f[b>>3])>(a[b>>2]=a[va>>2],a[b+4>>2]=a[va+4>>2],f[b>>3])?1:-1}else{oa=0}do{if((ja|0)==(oa|0)){if(-1==(ja|0)){var ka=Da}else{if(0!=(ja|0)){E=474;break a}T=((Ja<<5)+ea|0)>>2;var Ea=(a[b>>2]=a[T],a[b+4>>2]=a[T+1],f[b>>3]),Ka=(Da<<4)+ua|0;f[b>>3]=Ea;a[Ka>>2]=a[b>>2];a[Ka+4>>2]=a[b+4>>2];var Na=(Ja<<5)+ea+24|0,Ba=(a[b>>2]=a[Na>>2],a[b+4>>2]=a[Na+4>>2],f[b>>3]),Wa=Da+1|0,$=(Da<<4)+ua+8|0;f[b>>3]=Ba;a[$>>2]=a[b>>2];a[$+4>>2]=a[b+4>>2];var Rd=(a[b>>2]=a[T],a[b+4>>2]=a[T+1],f[b>>3]),Ra=(Wa<<4)+ua|0;f[b>>3]=Rd;a[Ra>>2]=a[b>>2];a[Ra+4>>2]=a[b+4>>2];var bb=(Ja<<5)+ea+8|0,Xa=(a[b>>2]=a[bb>>2],a[b+4>>2]=a[bb+4>>2],f[b>>3]),Sa=Da+2|0,ia=(Wa<<4)+ua+8|0;f[b>>3]=Xa;a[ia>>2]=a[b>>2];a[ia+4>>2]=a[b+4>>2];ka=Sa}}else{if(-1==(oa|0)|1==(ja|0)){Z=((Ja<<5)+ea|0)>>2;var Va=(a[b>>2]=a[Z],a[b+4>>2]=a[Z+1],f[b>>3]),Ta=(Da<<4)+ua|0;f[b>>3]=Va;a[Ta>>2]=a[b>>2];a[Ta+4>>2]=a[b+4>>2];var Aa=(Ja<<5)+ea+24|0,fb=(a[b>>2]=a[Aa>>2],a[b+4>>2]=a[Aa+4>>2],f[b>>3]),Ca=Da+1|0,Ya=(Da<<4)+ua+8|0;f[b>>3]=fb;a[Ya>>2]=a[b>>2];a[Ya+4>>2]=a[b+4>>2];var $a=(a[b>>2]=a[Z],a[b+4>>2]=a[Z+1],f[b>>3]),La=(Ca<<4)+ua|0;f[b>>3]=$a;a[La>>2]=a[b>>2];a[La+4>>2]=a[b+4>>2];var pa=(Ja<<5)+ea+8|0,Ga=(a[b>>2]=a[pa>>2],a[b+4>>2]=a[pa+4>>2],f[b>>3]),Fa=Da+2|0,ca=(Ca<<4)+ua+8|0;f[b>>3]=Ga;a[ca>>2]=a[b>>2];a[ca+4>>2]=a[b+4>>2];ka=Fa}else{I=((Ja<<5)+ea+16|0)>>2;var nb=(a[b>>2]=a[I],a[b+4>>2]=a[I+1],f[b>>3]),jb=(Da<<4)+ua|0;f[b>>3]=nb;a[jb>>2]=a[b>>2];a[jb+4>>2]=a[b+4>>2];var cb=(Ja<<5)+ea+8|0,ha=(a[b>>2]=a[cb>>2],a[b+4>>2]=a[cb+4>>2],f[b>>3]),kb=Da+1|0,Kb=(Da<<4)+ua+8|0;f[b>>3]=ha;a[Kb>>2]=a[b>>2];a[Kb+4>>2]=a[b+4>>2];var Ma=(a[b>>2]=a[I],a[b+4>>2]=a[I+1],f[b>>3]),ld=(kb<<4)+ua|0;f[b>>3]=Ma;a[ld>>2]=a[b>>2];a[ld+4>>2]=a[b+4>>2];var lb=(Ja<<5)+ea+24|0,rb=(a[b>>2]=a[lb>>2],a[b+4>>2]=a[lb+4>>2],f[b>>3]),ab=Da+2|0,db=(kb<<4)+ua+8|0;f[b>>3]=rb;a[db>>2]=a[b>>2];a[db+4>>2]=a[b+4>>2];ka=ab}}}while(0);Da=ka;Ja=Ja+1|0}474==E&&P();a:for(;-1<(ra|0);){if((ra|0)<(Q|0)){var ob=(ra<<5)+ea+8|0,pb=(ra+1<<5)+ea+8|0,ub=(a[b>>2]=a[ob>>2],a[b+4>>2]=a[ob+4>>2],f[b>>3])>(a[b>>2]=a[pb>>2],a[b+4>>2]=a[pb+4>>2],f[b>>3])?-1:1}else{ub=0}if(0<(ra|0)){var gb=(ra-1<<5)+ea+8|0,sb=(ra<<5)+ea+8|0,Ia=(a[b>>2]=a[gb>>2],a[b+4>>2]=a[gb+4>>2],f[b>>3])>(a[b>>2]=a[sb>>2],a[b+4>>2]=a[sb+4>>2],f[b>>3])?1:-1}else{Ia=0}do{if((ub|0)==(Ia|0)){if(-1==(ub|0)){C=((ra<<5)+ea+16|0)>>2;var vb=(a[b>>2]=a[C],a[b+4>>2]=a[C+1],f[b>>3]),Ua=(Ab<<4)+ua|0;f[b>>3]=vb;a[Ua>>2]=a[b>>2];a[Ua+4>>2]=a[b+4>>2];A=((ra<<5)+ea+8|0)>>2;var sa=(a[b>>2]=a[A],a[b+4>>2]=a[A+1],f[b>>3]),qa=Ab+1|0,qb=(Ab<<4)+ua+8|0;f[b>>3]=sa;a[qb>>2]=a[b>>2];a[qb+4>>2]=a[b+4>>2];var Bb=(a[b>>2]=a[C],a[b+4>>2]=a[C+1],f[b>>3]),sc=(qa<<4)+ua|0;f[b>>3]=Bb;a[sc>>2]=a[b>>2];a[sc+4>>2]=a[b+4>>2];S=((ra<<5)+ea+24|0)>>2;var xb=(a[b>>2]=a[S],a[b+4>>2]=a[S+1],f[b>>3]),za=Ab+2|0,Nb=(qa<<4)+ua+8|0;f[b>>3]=xb;a[Nb>>2]=a[b>>2];a[Nb+4>>2]=a[b+4>>2];D=((ra<<5)+ea|0)>>2;var Jb=(a[b>>2]=a[D],a[b+4>>2]=a[D+1],f[b>>3]),fa=(za<<4)+ua|0;f[b>>3]=Jb;a[fa>>2]=a[b>>2];a[fa+4>>2]=a[b+4>>2];var xa=(a[b>>2]=a[S],a[b+4>>2]=a[S+1],f[b>>3]),Ic=Ab+3|0,na=(za<<4)+ua+8|0;f[b>>3]=xa;a[na>>2]=a[b>>2];a[na+4>>2]=a[b+4>>2];var Ha=(a[b>>2]=a[D],a[b+4>>2]=a[D+1],f[b>>3]),ta=(Ic<<4)+ua|0;f[b>>3]=Ha;a[ta>>2]=a[b>>2];a[ta+4>>2]=a[b+4>>2];var Pa=(a[b>>2]=a[A],a[b+4>>2]=a[A+1],f[b>>3]),eb=Ab+4|0,mb=(Ic<<4)+ua+8|0;f[b>>3]=Pa;a[mb>>2]=a[b>>2];a[mb+4>>2]=a[b+4>>2];var Ub=eb}else{if(0==(ub|0)){F=((ra<<5)+ea+16|0)>>2;var hb=(a[b>>2]=a[F],a[b+4>>2]=a[F+1],f[b>>3]),zb=(Ab<<4)+ua|0;f[b>>3]=hb;a[zb>>2]=a[b>>2];a[zb+4>>2]=a[b+4>>2];var wb=(ra<<5)+ea+8|0,Db=(a[b>>2]=a[wb>>2],a[b+4>>2]=a[wb+4>>2],f[b>>3]),me=Ab+1|0,te=(Ab<<4)+ua+8|0;f[b>>3]=Db;a[te>>2]=a[b>>2];a[te+4>>2]=a[b+4>>2];var je=(a[b>>2]=a[F],a[b+4>>2]=a[F+1],f[b>>3]),Ib=(me<<4)+ua|0;f[b>>3]=je;a[Ib>>2]=a[b>>2];a[Ib+4>>2]=a[b+4>>2];var cc=(ra<<5)+ea+24|0,pc=(a[b>>2]=a[cc>>2],a[b+4>>2]=a[cc+4>>2],f[b>>3]),Qa=Ab+2|0,hd=(me<<4)+ua+8|0;f[b>>3]=pc;a[hd>>2]=a[b>>2];a[hd+4>>2]=a[b+4>>2];Ub=Qa}else{E=487;break a}}}else{if(-1==(Ia|0)|1==(ub|0)){B=((ra<<5)+ea|0)>>2;var qd=(a[b>>2]=a[B],a[b+4>>2]=a[B+1],f[b>>3]),Vb=(Ab<<4)+ua|0;f[b>>3]=qd;a[Vb>>2]=a[b>>2];a[Vb+4>>2]=a[b+4>>2];var Yb=(ra<<5)+ea+24|0,Jc=(a[b>>2]=a[Yb>>2],a[b+4>>2]=a[Yb+4>>2],f[b>>3]),tb=Ab+1|0,Cb=(Ab<<4)+ua+8|0;f[b>>3]=Jc;a[Cb>>2]=a[b>>2];a[Cb+4>>2]=a[b+4>>2];var Eb=(a[b>>2]=a[B],a[b+4>>2]=a[B+1],f[b>>3]),Eh=(tb<<4)+ua|0;f[b>>3]=Eb;a[Eh>>2]=a[b>>2];a[Eh+4>>2]=a[b+4>>2];var kf=(ra<<5)+ea+8|0,kc=(a[b>>2]=a[kf>>2],a[b+4>>2]=a[kf+4>>2],f[b>>3]),uc=Ab+2|0,Mb=(tb<<4)+ua+8|0;f[b>>3]=kc;a[Mb>>2]=a[b>>2];a[Mb+4>>2]=a[b+4>>2];Ub=uc}else{z=((ra<<5)+ea+16|0)>>2;var Hb=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]),ne=(Ab<<4)+ua|0;f[b>>3]=Hb;a[ne>>2]=a[b>>2];a[ne+4>>2]=a[b+4>>2];var Kc=(ra<<5)+ea+8|0,rc=(a[b>>2]=a[Kc>>2],a[b+4>>2]=a[Kc+4>>2],f[b>>3]),Sb=Ab+1|0,Cc=(Ab<<4)+ua+8|0;f[b>>3]=rc;a[Cc>>2]=a[b>>2];a[Cc+4>>2]=a[b+4>>2];var Pb=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]),Dc=(Sb<<4)+ua|0;f[b>>3]=Pb;a[Dc>>2]=a[b>>2];a[Dc+4>>2]=a[b+4>>2];var Xb=(ra<<5)+ea+24|0,fc=(a[b>>2]=a[Xb>>2],a[b+4>>2]=a[Xb+4>>2],f[b>>3]),Zb=Ab+2|0,Yc=(Sb<<4)+ua+8|0;f[b>>3]=fc;a[Yc>>2]=a[b>>2];a[Yc+4>>2]=a[b+4>>2];Ub=Zb}}}while(0);Ab=Ub;ra=ra-1|0}487==E&&(a[s>>2]=0,P());a:do{if(0!=(Tb|0)){b:do{if(0<(G|0)){for(var xc=0;;){y=((xc<<5)+ea+24|0)>>2;var ic=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3])&-1;t=((xc<<5)+ea+8|0)>>2;var Wc=-1*(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3]);f[b>>3]=Wc;a[y]=a[b>>2];a[y+1]=a[b+4>>2];f[b>>3]=-ic|0;a[t]=a[b>>2];a[t+1]=a[b+4>>2];var ae=xc+1|0;if((ae|0)==(G|0)){break b}else{xc=ae}}}}while(0);if(0<(Ab|0)){for(var hc=0;;){v=((hc<<4)+ua+8|0)>>2;var gc=-1*(a[b>>2]=a[v],a[b+4>>2]=a[v+1],f[b>>3]);f[b>>3]=gc;a[v]=a[b>>2];a[v+1]=a[b+4>>2];var ec=hc+1|0;if((ec|0)==(Ab|0)){break a}else{hc=ec}}}}}while(0);var Kd=0<(G|0);a:do{if(Kd){for(var Sc=0;;){var bd=(Sc<<5)+ea|0;f[b>>3]=2147483647;a[bd>>2]=a[b>>2];a[bd+4>>2]=a[b+4>>2];var Vc=(Sc<<5)+ea+16|0;f[b>>3]=-2147483648;a[Vc>>2]=a[b>>2];a[Vc+4>>2]=a[b+4>>2];var cd=Sc+1|0;if((cd|0)==(G|0)){break a}else{Sc=cd}}}}while(0);a[yb>>2]=ua;var Zc=yb+4|0;a[Zc>>2]=Ab;var nc=u|0,Oc=(a[b>>2]=a[nc>>2],a[b+4>>2]=a[nc+4>>2],f[b>>3]),Lc=Y|0,dd=Y|0;f[b>>3]=Oc;a[dd>>2]=a[b>>2];a[dd+4>>2]=a[b+4>>2];var Sd=u+8|0,id=(a[b>>2]=a[Sd>>2],a[b+4>>2]=a[Sd+4>>2],f[b>>3]),Xc=Y+8|0;f[b>>3]=id;a[Xc>>2]=a[b>>2];a[Xc+4>>2]=a[b+4>>2];var bf=u+40|0,$c=(a[b>>2]=a[bf>>2],a[b+4>>2]=a[bf+4>>2],f[b>>3]),Lb=Y+16|0;f[b>>3]=$c;a[Lb>>2]=a[b>>2];a[Lb+4>>2]=a[b+4>>2];var Re=u+48|0,ad=(a[b>>2]=a[Re>>2],a[b+4>>2]=a[Re+4>>2],f[b>>3]),$b=Y+24|0;f[b>>3]=ad;a[$b>>2]=a[b>>2];a[$b+4>>2]=a[b+4>>2];-1==(Xj(yb,Lc,J)|0)&&P();do{if(0==(g|0)){var Tc=a[Zc>>2];if((Tc|0)>(a[1314331]|0)){var ac=a[1314330],jc=0==(ac|0)?Za(Tc<<5):Oa(ac,Tc<<5);a[1314330]=jc;a[1314331]=Tc}a:do{if(0<(Tc|0)){for(var Qb=a[1314330],lc=a[1312208],Uc=0;;){x=((Uc<<5)+Qb|0)>>2;w=((Uc<<4)+lc|0)>>2;a[x]=a[w];a[x+1]=a[w+1];a[x+2]=a[w+2];a[x+3]=a[w+3];var wd=Uc+1|0;m=((Uc<<5)+Qb+16|0)>>2;q=(((wd|0)%(Tc|0)<<4)+lc|0)>>2;a[m]=a[q];a[m+1]=a[q+1];a[m+2]=a[q+2];a[m+3]=a[q+3];if((wd|0)<(Tc|0)){Uc=wd}else{break a}}}}while(0);if(0==n[u+29|0]<<24>>24){r=H>>2,a[r]=0,a[r+1]=0,a[r+2]=0,a[r+3]=0}else{var tc=u+16|0,xd=(a[b>>2]=a[tc>>2],a[b+4>>2]=a[tc+4>>2],f[b>>3]),rd=H|0;f[b>>3]=Math.cos(xd);a[rd>>2]=a[b>>2];a[rd+4>>2]=a[b+4>>2];var yd=H+8|0;f[b>>3]=Math.sin(xd);a[yd>>2]=a[b>>2];a[yd+4>>2]=a[b+4>>2]}if(0==n[u+69|0]<<24>>24){k=(H+16|0)>>2,a[k]=0,a[k+1]=0,a[k+2]=0,a[k+3]=0}else{var bc=u+56|0,Cd=(a[b>>2]=a[bc>>2],a[b+4>>2]=a[bc+4>>2],f[b>>3]),md=H+16|0;f[b>>3]=-Math.cos(Cd);a[md>>2]=a[b>>2];a[md+4>>2]=a[b+4>>2];var sd=H+24|0;f[b>>3]=-Math.sin(Cd);a[sd>>2]=a[b>>2];a[sd+4>>2]=a[b+4>>2]}-1==(po(a[1314330],Tc,a[L],a[L+1],H|0,R)|0)&&P()}else{Yj(a[L],a[L+1],R)}}while(0);var dc=a[R+4>>2];qo(dc);a:do{if(Kd){for(var ed=0;;){var zd=(ed<<5)+ea|0;f[b>>3]=2147483647;a[zd>>2]=a[b>>2];a[zd+4>>2]=a[b+4>>2];var ke=(ed<<5)+ea+16|0;f[b>>3]=-2147483648;a[ke>>2]=a[b>>2];a[ke+4>>2]=a[b+4>>2];var Je=ed+1|0;if((Je|0)==(G|0)){break a}else{ed=Je}}}}while(0);var jd=a[1311892];a:do{if(0<(dc|0)){for(var Ld=a[R>>2],Ad=0;;){j=((Ad<<4)+jd|0)>>2;d=((Ad<<4)+Ld|0)>>2;a[j]=a[d];a[j+1]=a[d+1];a[j+2]=a[d+2];a[j+3]=a[d+3];var oc=Ad+1|0;if((oc|0)<(dc|0)){Ad=oc}else{break a}}}}while(0);var Bc=3<(dc|0),Hd=10;a:for(;;){b:do{if(Bc){for(var Id=Math.a(Hd,G),Ec=0>(Id|0),wc=Id|0,Md=0,nd=3;;){c:do{if(!Ec){for(var Hc=(Md<<4)+jd|0,gd=(Md<<4)+jd+8|0,Rc=Md+1|0,vc=(Rc<<4)+jd|0,Nc=(Rc<<4)+jd+8|0,td=Md+2|0,Mc=(td<<4)+jd|0,Pc=(td<<4)+jd+8|0,Gc=(nd<<4)+jd|0,kd=(nd<<4)+jd+8|0,zc=0;;){var be=(zc|0)/wc,Fc=(a[b>>2]=a[Hc>>2],a[b+4>>2]=a[Hc+4>>2],f[b>>3]),fd=(a[b>>2]=a[gd>>2],a[b+4>>2]=a[gd+4>>2],f[b>>3]),Zj=(a[b>>2]=a[vc>>2],a[b+4>>2]=a[vc+4>>2],f[b>>3]),Nd=(a[b>>2]=a[Nc>>2],a[b+4>>2]=a[Nc+4>>2],f[b>>3]),pd=(a[b>>2]=a[Mc>>2],a[b+4>>2]=a[Mc+4>>2],f[b>>3]),ge=(a[b>>2]=a[Pc>>2],a[b+4>>2]=a[Pc+4>>2],f[b>>3]),Ed=Fc+be*(Zj-Fc),od=fd+be*(Nd-fd),vd=Zj+be*(pd-Zj),yc=Nd+be*(ge-Nd),Fd=Ed+be*(vd-Ed),Dd=od+be*(yc-od),ud=Fd+be*(vd+be*(pd+be*((a[b>>2]=a[Gc>>2],a[b+4>>2]=a[Gc+4>>2],f[b>>3])-pd)-vd)-Fd),Xd=Dd+be*(yc+be*(ge+be*((a[b>>2]=a[kd>>2],a[b+4>>2]=a[kd+4>>2],f[b>>3])-ge)-yc)-Dd);d:do{if(Kd){for(var jf=0;;){var Bd=(jf<<5)+ea+24|0;if(Xd<=(a[b>>2]=a[Bd>>2],a[b+4>>2]=a[Bd+4>>2],f[b>>3])+1e-4){var Pd=(jf<<5)+ea+8|0;if(Xd>=(a[b>>2]=a[Pd>>2],a[b+4>>2]=a[Pd+4>>2],f[b>>3])-1e-4){c=((jf<<5)+ea|0)>>2;if((a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3])>ud){f[b>>3]=ud,a[c]=a[b>>2],a[c+1]=a[b+4>>2]}e=((jf<<5)+ea+16|0)>>2;if((a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])<ud){f[b>>3]=ud,a[e]=a[b>>2],a[e+1]=a[b+4>>2]}}}var Jd=jf+1|0;if((Jd|0)==(G|0)){break d}else{jf=Jd}}}}while(0);var Qd=zc+1|0;if((Qd|0)>(Id|0)){break c}else{zc=Qd}}}}while(0);var Gd=nd+3|0;if((Gd|0)<(dc|0)){Md=nd,nd=Gd}else{var Qc=0;break b}}}else{Qc=0}}while(0);for(;;){if((Qc|0)>=(G|0)){break a}var Vd=(Qc<<5)+ea|0;if(2147483647==(a[b>>2]=a[Vd>>2],a[b+4>>2]=a[Vd+4>>2],f[b>>3])){break}var Od=(Qc<<5)+ea+16|0;if(-2147483648==(a[b>>2]=a[Od>>2],a[b+4>>2]=a[Od+4>>2],f[b>>3])){break}else{Qc=Qc+1|0}}Hd<<=1}a[s>>2]=dc;h=yb;return jd}function so(a,b,g,e){if(!((b|0)>(g|0)&(a|0)<(e|0))){return 0}if(!((g|0)>(a|0)|(a|0)>(e|0))){return e-a|0}(g|0)>(b|0)|(b|0)>(e|0)?(a=b-a|0,g=e-g|0,g=(a|0)<(g|0)?a:g):g=b-g|0;return g}function Sg(u){var s,g=h;s=(u+80|0)>>2;Lb(a[Qa>>2],5326284,(i=h,h=h+4|0,a[i>>2]=a[s],i));var e=a[Qa>>2];a:do{if(0<(a[s]|0)){for(var c=u+84|0,d=0,j=e;;){var k=a[c>>2],r=(d<<5)+k|0,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),q=(d<<5)+k+8|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),m=(d<<5)+k+16|0,m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),k=(d<<5)+k+24|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);Lb(j,5377332,(i=h,h=h+36|0,a[i>>2]=d,f[b>>3]=r,a[i+4>>2]=a[b>>2],a[i+8>>2]=a[b+4>>2],f[b>>3]=q,a[i+12>>2]=a[b>>2],a[i+16>>2]=a[b+4>>2],f[b>>3]=m,a[i+20>>2]=a[b>>2],a[i+24>>2]=a[b+4>>2],f[b>>3]=k,a[i+28>>2]=a[b>>2],a[i+32>>2]=a[b+4>>2],i));d=d+1|0;j=a[Qa>>2];if((d|0)>=(a[s]|0)){var w=j;break a}}}else{w=e}}while(0);s=u|0;s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]);e=u+8|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);c=u+16|0;c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);d=0!=n[u+29|0]<<24>>24?5371936:5369068;Lb(w,5374380,(i=h,h=h+28|0,f[b>>3]=s,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=e,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],f[b>>3]=c,a[i+16>>2]=a[b>>2],a[i+20>>2]=a[b+4>>2],a[i+24>>2]=d,i));w=a[Qa>>2];s=u+40|0;s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]);e=u+48|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);c=u+56|0;c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);u=0!=n[u+69|0]<<24>>24?5371936:5369068;Lb(w,5366928,(i=h,h=h+28|0,f[b>>3]=s,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=e,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],f[b>>3]=c,a[i+16>>2]=a[b>>2],a[i+20>>2]=a[b+4>>2],a[i+24>>2]=u,i));h=g}function ro(u,s,g){var e,c,d,j,k,r,q,m,w,n,v,t,y,z,B,F,D,S,A=0,C=h;a:do{if(0<(u|0)){for(var I=0,Z=0;;){var T=(Z<<5)+s|0,K=(Z<<5)+s+8|0,M=(Z<<5)+s+24|0,L=(a[b>>2]=a[K>>2],a[b+4>>2]=a[K+4>>2],f[b>>3])-(a[b>>2]=a[M>>2],a[b+4>>2]=a[M+4>>2],f[b>>3]);if(.01>(0>L?-L:L)){var E=I}else{var yb=T|0,H=(Z<<5)+s+16|0,R=(a[b>>2]=a[yb>>2],a[b+4>>2]=a[yb+4>>2],f[b>>3])-(a[b>>2]=a[H>>2],a[b+4>>2]=a[H+4>>2],f[b>>3]);.01>(0>R?-R:R)?E=I:((I|0)!=(Z|0)&&(S=((I<<5)+s|0)>>2,D=T>>2,a[S]=a[D],a[S+1]=a[D+1],a[S+2]=a[D+2],a[S+3]=a[D+3],a[S+4]=a[D+4],a[S+5]=a[D+5],a[S+6]=a[D+6],a[S+7]=a[D+7]),E=I+1|0)}var Y=Z+1|0;if((Y|0)==(u|0)){var J=E;break a}else{I=E,Z=Y}}}else{J=0}}while(0);F=(s|0)>>2;var G=(a[b>>2]=a[F],a[b+4>>2]=a[F+1],f[b>>3]);B=(s+16|0)>>2;var N=(a[b>>2]=a[B],a[b+4>>2]=a[B+1],f[b>>3]);G>N&&(aa(1,5340576,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Sg(g),P());z=(s+8|0)>>2;var ea=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]);y=(s+24|0)>>2;var wa=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]);ea>wa&&(aa(1,5340576,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Sg(g),P());for(var Fb=J-1|0,V=0,W=N,X=G,ba=wa,ma=ea;;){if((V|0)>=(Fb|0)){A=613;break}var ib=V+1|0;t=((ib<<5)+s|0)>>2;var U=(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3]);v=((ib<<5)+s+16|0)>>2;var mc=(a[b>>2]=a[v],a[b+4>>2]=a[v+1],f[b>>3]);if(U>mc){A=639;break}n=((ib<<5)+s+8|0)>>2;var O=(a[b>>2]=a[n],a[b+4>>2]=a[n+1],f[b>>3]);w=((ib<<5)+s+24|0)>>2;var ga=(a[b>>2]=a[w],a[b+4>>2]=a[w+1],f[b>>3]);if(O>ga){A=638;break}m=((V<<5)+s+16|0)>>2;var Tb=W<U,Q=Tb&1;q=((V<<5)+s|0)>>2;var ua=X>mc,Da=ua&1;r=((V<<5)+s+24|0)>>2;var Ja=ba<O,Ab=Ja&1;k=((V<<5)+s+8|0)>>2;var ra=ma>ga,da=ra&1,ya=Da+Q+Ab+da|0;a:do{if(0<(ya|0)){if(Tb){var ja=W&-1;f[b>>3]=U;a[m]=a[b>>2];a[m+1]=a[b+4>>2];var la=ja|0;f[b>>3]=la;a[t]=a[b>>2];a[t+1]=a[b+4>>2];var va=da,oa=Ab,ka=Da,Ea=0,Ka=U,Na=la,Ba=X,Wa=mc,$=ba,Rd=O,Ra=ma,bb=ga}else{if(ua){var Xa=X&-1;f[b>>3]=mc;a[q]=a[b>>2];a[q+1]=a[b+4>>2];var Sa=Xa|0;f[b>>3]=Sa;a[v]=a[b>>2];a[v+1]=a[b+4>>2];va=da;oa=Ab;ka=0;Ea=Q;Ka=W;Na=U;Ba=mc;Wa=Sa;$=ba;Rd=O;Ra=ma;bb=ga}else{if(Ja){var ia=ba&-1;f[b>>3]=O;a[r]=a[b>>2];a[r+1]=a[b+4>>2];var Va=ia|0;f[b>>3]=Va;a[n]=a[b>>2];a[n+1]=a[b+4>>2];va=da;oa=0;ka=Da;Ea=Q;Ka=W;Na=U;Ba=X;Wa=mc;$=O;Rd=Va;Ra=ma;bb=ga}else{if(ra){var Ta=ma&-1;f[b>>3]=ga;a[k]=a[b>>2];a[k+1]=a[b+4>>2];var Aa=Ta|0;f[b>>3]=Aa;a[w]=a[b>>2];a[w+1]=a[b+4>>2];va=0;oa=Ab;ka=Da;Ea=Q;Ka=W;Na=U;Ba=X;Wa=mc;$=ba;Rd=O;Ra=ga;bb=Aa}else{va=da,oa=Ab,ka=Da,Ea=Q,Ka=W,Na=U,Ba=X,Wa=mc,$=ba,Rd=O,Ra=ma,bb=ga}}}}if(0<(ya-1|0)){for(var fb=((ua^1)<<31>>31)+Q+Ab+da|0,Ca=Ea,Ya=ka,$a=0,La=oa,pa=va,Ga=Ka,Fa=Na,ca=Ba,nb=Wa,jb=$,cb=Rd,ha=Ra,kb=bb;;){if(1==(Ca|0)){var Kb=.5*(Ga+Fa)+.5&-1|0;f[b>>3]=Kb;a[t]=a[b>>2];a[t+1]=a[b+4>>2];f[b>>3]=Kb;a[m]=a[b>>2];a[m+1]=a[b+4>>2];var Ma=pa,ld=La,lb=Ya,rb=0,ab=Kb,db=Kb,ob=ca,pb=nb,ub=jb,gb=cb,sb=ha,Ia=kb}else{if(1==(Ya|0)){var vb=.5*(ca+nb)+.5&-1|0;f[b>>3]=vb;a[v]=a[b>>2];a[v+1]=a[b+4>>2];f[b>>3]=vb;a[q]=a[b>>2];a[q+1]=a[b+4>>2];Ma=pa;ld=La;lb=0;rb=Ca;ab=Ga;db=Fa;pb=ob=vb;ub=jb;gb=cb;sb=ha;Ia=kb}else{if(1==(La|0)){var Ua=.5*(jb+cb)+.5&-1|0;f[b>>3]=Ua;a[n]=a[b>>2];a[n+1]=a[b+4>>2];f[b>>3]=Ua;a[r]=a[b>>2];a[r+1]=a[b+4>>2];Ma=pa;ld=0;lb=Ya;rb=Ca;ab=Ga;db=Fa;ob=ca;pb=nb;gb=ub=Ua;sb=ha;Ia=kb}else{if(1!=(pa|0)){Ma=pa,ld=La,lb=Ya,rb=Ca,ab=Ga,db=Fa,ob=ca,pb=nb,ub=jb,gb=cb,sb=ha,Ia=kb}else{var sa=.5*(ha+kb)+.5&-1|0;f[b>>3]=sa;a[w]=a[b>>2];a[w+1]=a[b+4>>2];f[b>>3]=sa;a[k]=a[b>>2];a[k+1]=a[b+4>>2];Ma=0;ld=La;lb=Ya;rb=Ca;ab=Ga;db=Fa;ob=ca;pb=nb;ub=jb;gb=cb;Ia=sb=sa}}}}var qa=$a+1|0;if((qa|0)==(fb|0)){qb=ob;Bb=ab;sc=db;xb=pb;za=sb;Nb=ub;Jb=gb;fa=Ia;break a}else{Ca=rb,Ya=lb,$a=qa,La=ld,pa=Ma,Ga=ab,Fa=db,ca=ob,nb=pb,jb=ub,cb=gb,ha=sb,kb=Ia}}}else{var qb=Ba,Bb=Ka,sc=Na,xb=Wa,za=Ra,Nb=$,Jb=Rd,fa=bb}}else{qb=X,Bb=W,sc=U,xb=mc,za=ma,Nb=ba,Jb=O,fa=ga}}while(0);var xa=so(qb&-1,Bb&-1,sc&-1,xb&-1),Ic=so(za&-1,Nb&-1,Jb&-1,fa&-1);if(0==(xa|0)|0==(Ic|0)){V=ib,W=xb,X=sc,ba=fa,ma=Jb}else{if((xa|0)<(Ic|0)){var na=Bb<xb;Bb-qb>xb-sc?(na?(f[b>>3]=sc,a[m]=a[b>>2],a[m+1]=a[b+4>>2]):(f[b>>3]=xb,a[q]=a[b>>2],a[q+1]=a[b+4>>2]),V=ib,W=xb,X=sc):na?(f[b>>3]=Bb,a[t]=a[b>>2],a[t+1]=a[b+4>>2],V=ib,W=xb,X=Bb):(f[b>>3]=qb,a[v]=a[b>>2],a[v+1]=a[b+4>>2],V=ib,W=qb,X=sc);ba=fa;ma=Jb}else{var Ha=Nb<fa;Nb-za>fa-Jb?(Ha?(f[b>>3]=Jb,a[r]=a[b>>2],a[r+1]=a[b+4>>2]):(f[b>>3]=fa,a[k]=a[b>>2],a[k+1]=a[b+4>>2]),V=ib,W=xb,X=sc,ba=fa,ma=Jb):Ha?(f[b>>3]=Nb,a[n]=a[b>>2],a[n+1]=a[b+4>>2],V=ib,W=xb,X=sc,ba=fa,ma=Nb):(f[b>>3]=za,a[w]=a[b>>2],a[w+1]=a[b+4>>2],V=ib,W=xb,X=sc,ba=za,ma=Jb)}}}if(613==A){j=(g|0)>>2;var ta=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3]),Za=(a[b>>2]=a[F],a[b+4>>2]=a[F+1],f[b>>3]);if(ta<Za){f[b>>3]=Za;a[j]=a[b>>2];a[j+1]=a[b+4>>2];var Oa=Za,A=618}else{if(ta>(a[b>>2]=a[B],a[b+4>>2]=a[B+1],f[b>>3])){Oa=ta,A=618}else{var Pa=g+8|0,Ub=(a[b>>2]=a[Pa>>2],a[b+4>>2]=a[Pa+4>>2],f[b>>3]);if(Ub<(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3])){Oa=ta,A=618}else{if(Ub>(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3])){Oa=ta,A=618}}}}if(618==A){var eb=(a[b>>2]=a[B],a[b+4>>2]=a[B+1],f[b>>3]);Oa>eb&&(f[b>>3]=eb,a[j]=a[b>>2],a[j+1]=a[b+4>>2]);d=(g+8|0)>>2;var mb=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),zb=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]);if(mb<zb){f[b>>3]=zb;a[d]=a[b>>2];a[d+1]=a[b+4>>2];var hb=zb}else{hb=mb}var me=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]);hb>me&&(f[b>>3]=me,a[d]=a[b>>2],a[d+1]=a[b+4>>2])}c=(g+40|0)>>2;var te=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3]),je=(Fb<<5)+s|0,wb=(a[b>>2]=a[je>>2],a[b+4>>2]=a[je+4>>2],f[b>>3]);if(te<wb){f[b>>3]=wb;a[c]=a[b>>2];a[c+1]=a[b+4>>2];var cc=wb}else{var pc=(Fb<<5)+s+16|0;if(te>(a[b>>2]=a[pc>>2],a[b+4>>2]=a[pc+4>>2],f[b>>3])){cc=te}else{var Db=g+48|0,hd=(a[b>>2]=a[Db>>2],a[b+4>>2]=a[Db+4>>2],f[b>>3]),qd=(Fb<<5)+s+8|0;if(hd<(a[b>>2]=a[qd>>2],a[b+4>>2]=a[qd+4>>2],f[b>>3])){cc=te}else{var Vb=(Fb<<5)+s+24|0;if(hd>(a[b>>2]=a[Vb>>2],a[b+4>>2]=a[Vb+4>>2],f[b>>3])){cc=te}else{h=C;return}}}}var Yb=(Fb<<5)+s+16|0,Jc=(a[b>>2]=a[Yb>>2],a[b+4>>2]=a[Yb+4>>2],f[b>>3]);cc>Jc&&(f[b>>3]=Jc,a[c]=a[b>>2],a[c+1]=a[b+4>>2]);e=(g+48|0)>>2;var Ib=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),tb=(Fb<<5)+s+8|0,Cb=(a[b>>2]=a[tb>>2],a[b+4>>2]=a[tb+4>>2],f[b>>3]);if(Ib<Cb){f[b>>3]=Cb;a[e]=a[b>>2];a[e+1]=a[b+4>>2];var Qa=Cb}else{Qa=Ib}var Eb=(Fb<<5)+s+24|0,kc=(a[b>>2]=a[Eb>>2],a[b+4>>2]=a[Eb+4>>2],f[b>>3]);Qa>kc&&(f[b>>3]=kc,a[e]=a[b>>2],a[e+1]=a[b+4>>2]);h=C}else{638==A?(aa(1,5337544,(i=h,h=h+4|0,a[i>>2]=ib,i)),Sg(g),P()):639==A&&(aa(1,5337544,(i=h,h=h+4|0,a[i>>2]=ib,i)),Sg(g),P())}}function Zh(u,s,g,e,c,d){var j=u|0;f[b>>3]=(c-g)*s+g;a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];u=u+8|0;f[b>>3]=(d-e)*s+e;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}function rj(b){0==(b|0)?b=0:(b=a[a[b+4>>2]>>2],b=244==(b|0)?1:52==(b|0)?2:50==(b|0)?3:326==(b|0)?4:0);return b}function Rf(u,s,g,e,c,d,j){var k,r,q,m,i,n,v,t,y,z,B,F,D,S,A,C,I,Z,T,K,M,L,H,yb,J,R,Y,G,Rb,P,ea,wa,Fb,V,W,X,ba,ma,ib,N,mc,O,ga,Tb,U,ua,Da,Ja,aa,ra,Q,ya,ja,la,va,oa,ka,Ea,Ka,Na,Ba,Wa,$,ca,Ra,bb,Xa,Sa,ha,Va,Ta,Aa,fb,Ca,Ya,$a,La,pa,Ga,Fa,sa,nb,jb,cb,fa,kb,Kb,Ma,ld,lb,rb,ab,db,ob,pb,ub,gb,sb,Ia,vb,Ua=h;h=h+128|0;var qa=Ua+64,xa=Ua+80,qb=Ua+96,Bb=Ua+112;if(0==(d&4|0)){var sc=d&992,xb=0==(sc|0)?2:sc}else{xb=4}var za=da((c<<6)+64|0);vb=za>>2;var Nb=0<(c|0);a:do{if(Nb){for(var Jb=c-1|0,na=e+8|0,Ha=12,Ic=0;;){var ta=(Ic<<4)+e|0,Oa=(a[b>>2]=a[ta>>2],a[b+4>>2]=a[ta+4>>2],f[b>>3]),Pa=(Ic<<4)+e+8|0,mb=(a[b>>2]=a[Pa>>2],a[b+4>>2]=a[Pa+4>>2],f[b>>3]),zb=Ic+1|0;if((Ic|0)<(Jb|0)){var hb=(zb<<4)+e|0,Ub=(zb<<4)+e+8|0}else{hb=e,Ub=na}var wb=hb|0,Db=(a[b>>2]=a[wb>>2],a[b+4>>2]=a[wb+4>>2],f[b>>3])-Oa,Cb=(a[b>>2]=a[Ub>>2],a[b+4>>2]=a[Ub+4>>2],f[b>>3])-mb,Ib=Math.sqrt(Db*Db+Cb*Cb)/3,me=Ha<Ib?Ha:Ib;if((zb|0)==(c|0)){break}else{Ha=me,Ic=zb}}var te=0==(d&768|0),je=0==(d&32|0),tb=2==(xb|0);Ia=qa>>2;sb=xa>>2;gb=qb>>2;ub=Bb>>2;for(var cc=0,pc=0;;){var Qa=(pc<<4)+e|0,hd=(a[b>>2]=a[Qa>>2],a[b+4>>2]=a[Qa+4>>2],f[b>>3]),qd=(pc<<4)+e+8|0,Vb=(a[b>>2]=a[qd>>2],a[b+4>>2]=a[qd+4>>2],f[b>>3]);if((pc|0)<(Jb|0)){var Yb=pc+1|0,Jc=(Yb<<4)+e|0,Eb=(Yb<<4)+e+8|0}else{Jc=e,Eb=na}var Mb=Jc|0,Hb=(a[b>>2]=a[Mb>>2],a[b+4>>2]=a[Mb+4>>2],f[b>>3]),Pb=(a[b>>2]=a[Eb>>2],a[b+4>>2]=a[Eb+4>>2],f[b>>3]),kf=Hb-hd,kc=Pb-Vb,uc=me/Math.sqrt(kf*kf+kc*kc),Xb=te?je?uc:.5*uc:uc/3;if(tb){Zh(qa,.5*Xb,hd,Vb,Hb,Pb),pb=((cc<<4)+za|0)>>2,a[pb]=a[Ia],a[pb+1]=a[Ia+1],a[pb+2]=a[Ia+2],a[pb+3]=a[Ia+3]}else{var hc=(cc<<4)+za|0;f[b>>3]=hd;a[hc>>2]=a[b>>2];a[hc+4>>2]=a[b+4>>2];var ne=(cc<<4)+za+8|0;f[b>>3]=Vb;a[ne>>2]=a[b>>2];a[ne+4>>2]=a[b+4>>2]}Zh(xa,Xb,hd,Vb,Hb,Pb);ob=((cc+1<<4)+za|0)>>2;a[ob]=a[sb];a[ob+1]=a[sb+1];a[ob+2]=a[sb+2];a[ob+3]=a[sb+3];var Kc=cc+3|0;Zh(qb,1-Xb,hd,Vb,Hb,Pb);db=((cc+2<<4)+za|0)>>2;a[db]=a[gb];a[db+1]=a[gb+1];a[db+2]=a[gb+2];a[db+3]=a[gb+3];if(tb){Zh(Bb,1-.5*Xb,hd,Vb,Hb,Pb);ab=((Kc<<4)+za|0)>>2;a[ab]=a[ub];a[ab+1]=a[ub+1];a[ab+2]=a[ub+2];a[ab+3]=a[ub+3];var rc=cc+4|0}else{rc=Kc}var fc=pc+1|0;if((fc|0)==(c|0)){var Cc=rc;break a}else{cc=rc,pc=fc}}}else{Cc=0}}while(0);rb=((Cc<<4)+za|0)>>2;a[rb]=a[vb];a[rb+1]=a[vb+1];a[rb+2]=a[vb+2];a[rb+3]=a[vb+3];var Zb=za+16|0;lb=Zb>>2;ld=((Cc+1<<4)+za|0)>>2;a[ld]=a[lb];a[ld+1]=a[lb+1];a[ld+2]=a[lb+2];a[ld+3]=a[lb+3];var Dc=za+32|0;Ma=Dc>>2;Kb=((Cc+2<<4)+za|0)>>2;a[Kb]=a[Ma];a[Kb+1]=a[Ma+1];a[Kb+2]=a[Ma+2];a[Kb+3]=a[Ma+3];if(2==(xb|0)){a:do{if(0!=(j|0)){var ec=c<<1,ic=Za(c<<5),Lb=ic;eb(u,s);Sb(u,s);if(Nb){var Yc=0,xc=0}else{tc(u,Lb,ec,1);E(ic);eb(u,g);E(za);h=Ua;return}for(;;){var $b=Yc<<2;kb=((xc<<4)+Lb|0)>>2;fa=((($b|1)<<4)+za|0)>>2;a[kb]=a[fa];a[kb+1]=a[fa+1];a[kb+2]=a[fa+2];a[kb+3]=a[fa+3];cb=(((xc|1)<<4)+Lb|0)>>2;jb=((($b|2)<<4)+za|0)>>2;a[cb]=a[jb];a[cb+1]=a[jb+1];a[cb+2]=a[jb+2];a[cb+3]=a[jb+3];var Wc=Yc+1|0;if((Wc|0)==(c|0)){break}else{Yc=Wc,xc=xc+2|0}}tc(u,Lb,ec,1);E(ic);for(var ae=0;;){hf(u,((ae<<2|2)<<4)+za|0,4,0,0,1);var ac=ae+1|0;if((ac|0)==(c|0)){break a}else{ae=ac}}}}while(0);eb(u,g);if(Nb){for(var gc=0;;){var Qb=gc<<2;td(u,((Qb|1)<<4)+za|0,2);hf(u,((Qb|2)<<4)+za|0,4,0,0,0);var Kd=gc+1|0;if((Kd|0)==(c|0)){break}else{gc=Kd}}}}else{if(4==(xb|0)){if(eb(u,g),0!=(j|0)&&Sb(u,s),tc(u,e,c,j&255),Nb){var Sc=Ua|0;nb=Ua>>2;sa=(Ua+16|0)>>2;for(var bd=0;;){var Vc=3*bd&-1;Fa=((Vc+2<<4)+za|0)>>2;a[nb]=a[Fa];a[nb+1]=a[Fa+1];a[nb+2]=a[Fa+2];a[nb+3]=a[Fa+3];Ga=((Vc+4<<4)+za|0)>>2;a[sa]=a[Ga];a[sa+1]=a[Ga+1];a[sa+2]=a[Ga+2];a[sa+3]=a[Ga+3];td(u,Sc,2);var cd=bd+1|0;if((cd|0)==(c|0)){break}else{bd=cd}}}}else{if(512==(xb|0)){4!=(c|0)&&ia(5335932,588,5379500,5362900);eb(u,g);0!=(j|0)&&Sb(u,s);var Zc=c+8|0,nc=da(Zc<<4);pa=nc>>2;La=e>>2;a[pa]=a[La];a[pa+1]=a[La+1];a[pa+2]=a[La+2];a[pa+3]=a[La+3];$a=(nc+16|0)>>2;Ya=(e+16|0)>>2;a[$a]=a[Ya];a[$a+1]=a[Ya+1];a[$a+2]=a[Ya+2];a[$a+3]=a[Ya+3];Ca=(za+48|0)>>2;var Oc=(a[b>>2]=a[Ca],a[b+4>>2]=a[Ca+1],f[b>>3]);fb=(za+64|0)>>2;var Lc=Oc+((a[b>>2]=a[fb],a[b+4>>2]=a[fb+1],f[b>>3])-Oc),dd=nc+32|0;Aa=dd>>2;Ta=dd>>2;f[b>>3]=Lc;a[Ta]=a[b>>2];a[Ta+1]=a[b+4>>2];Va=(za+56|0)>>2;var Sd=(a[b>>2]=a[Va],a[b+4>>2]=a[Va+1],f[b>>3]);ha=(za+72|0)>>2;var id=Sd+((a[b>>2]=a[ha],a[b+4>>2]=a[ha+1],f[b>>3])-Sd);Sa=(nc+40|0)>>2;f[b>>3]=id;a[Sa]=a[b>>2];a[Sa+1]=a[b+4>>2];var Xc=Lc+((a[b>>2]=a[Ca],a[b+4>>2]=a[Ca+1],f[b>>3])-(a[b>>2]=a[Dc>>2],a[b+4>>2]=a[Dc+4>>2],f[b>>3]));Xa=(nc+48|0)>>2;f[b>>3]=Xc;a[Xa]=a[b>>2];a[Xa+1]=a[b+4>>2];var lc=za+40|0,$c=id+((a[b>>2]=a[Va],a[b+4>>2]=a[Va+1],f[b>>3])-(a[b>>2]=a[lc>>2],a[b+4>>2]=a[lc+4>>2],f[b>>3]));bb=(nc+56|0)>>2;f[b>>3]=$c;a[bb]=a[b>>2];a[bb+1]=a[b+4>>2];var jc=Xc+((a[b>>2]=a[fb],a[b+4>>2]=a[fb+1],f[b>>3])-(a[b>>2]=a[Ca],a[b+4>>2]=a[Ca+1],f[b>>3]));Ra=(nc+64|0)>>2;f[b>>3]=jc;a[Ra]=a[b>>2];a[Ra+1]=a[b+4>>2];var dc=$c+((a[b>>2]=a[ha],a[b+4>>2]=a[ha+1],f[b>>3])-(a[b>>2]=a[Va],a[b+4>>2]=a[Va+1],f[b>>3]));ca=(nc+72|0)>>2;f[b>>3]=dc;a[ca]=a[b>>2];a[ca+1]=a[b+4>>2];var ad=jc+(Lc-Xc),bc=nc+80|0;$=bc>>2;f[b>>3]=ad;a[bc>>2]=a[b>>2];a[bc+4>>2]=a[b+4>>2];var Tc=nc+88|0;f[b>>3]=dc+(id-$c);a[Tc>>2]=a[b>>2];a[Tc+4>>2]=a[b+4>>2];Wa=(za+96|0)>>2;var Ke=(a[b>>2]=a[Wa],a[b+4>>2]=a[Wa+1],f[b>>3]);Ba=(za+80|0)>>2;var oc=Ke+((a[b>>2]=a[Ba],a[b+4>>2]=a[Ba+1],f[b>>3])-Ke),Ge=nc+144|0;Na=Ge>>2;f[b>>3]=oc;a[Ge>>2]=a[b>>2];a[Ge+4>>2]=a[b+4>>2];Ka=(za+104|0)>>2;var Ie=(a[b>>2]=a[Ka],a[b+4>>2]=a[Ka+1],f[b>>3]);Ea=(za+88|0)>>2;var Uc=Ie+((a[b>>2]=a[Ea],a[b+4>>2]=a[Ea+1],f[b>>3])-Ie),wd=nc+152|0;f[b>>3]=Uc;a[wd>>2]=a[b>>2];a[wd+4>>2]=a[b+4>>2];var Hc=za+112|0,xd=oc+((a[b>>2]=a[Wa],a[b+4>>2]=a[Wa+1],f[b>>3])-(a[b>>2]=a[Hc>>2],a[b+4>>2]=a[Hc+4>>2],f[b>>3]));ka=(nc+128|0)>>2;f[b>>3]=xd;a[ka]=a[b>>2];a[ka+1]=a[b+4>>2];var rd=za+120|0,yd=Uc+((a[b>>2]=a[Ka],a[b+4>>2]=a[Ka+1],f[b>>3])-(a[b>>2]=a[rd>>2],a[b+4>>2]=a[rd+4>>2],f[b>>3]));oa=(nc+136|0)>>2;f[b>>3]=yd;a[oa]=a[b>>2];a[oa+1]=a[b+4>>2];var Bc=xd+((a[b>>2]=a[Ba],a[b+4>>2]=a[Ba+1],f[b>>3])-(a[b>>2]=a[Wa],a[b+4>>2]=a[Wa+1],f[b>>3]));va=(nc+112|0)>>2;f[b>>3]=Bc;a[va]=a[b>>2];a[va+1]=a[b+4>>2];var Cd=yd+((a[b>>2]=a[Ea],a[b+4>>2]=a[Ea+1],f[b>>3])-(a[b>>2]=a[Ka],a[b+4>>2]=a[Ka+1],f[b>>3]));la=(nc+120|0)>>2;f[b>>3]=Cd;a[la]=a[b>>2];a[la+1]=a[b+4>>2];var md=Bc+(oc-xd),sd=nc+96|0;ja=sd>>2;ya=sd>>2;f[b>>3]=md;a[ya]=a[b>>2];a[ya+1]=a[b+4>>2];var Ec=Cd+(Uc-yd);Q=(nc+104|0)>>2;f[b>>3]=Ec;a[Q]=a[b>>2];a[Q+1]=a[b+4>>2];ra=(nc+160|0)>>2;aa=(e+32|0)>>2;a[ra]=a[aa];a[ra+1]=a[aa+1];a[ra+2]=a[aa+2];a[ra+3]=a[aa+3];Ja=(nc+176|0)>>2;Da=(e+48|0)>>2;a[Ja]=a[Da];a[Ja+1]=a[Da+1];a[Ja+2]=a[Da+2];a[Ja+3]=a[Da+3];tc(u,nc,Zc,j&255);var ed=Ua|0;ua=Ua>>2;a[ua]=a[Aa];a[ua+1]=a[Aa+1];a[ua+2]=a[Aa+2];a[ua+3]=a[Aa+3];var zd=(a[b>>2]=a[Ta],a[b+4>>2]=a[Ta+1],f[b>>3]),ke=zd-((a[b>>2]=a[Xa],a[b+4>>2]=a[Xa+1],f[b>>3])-zd);U=(Ua+16|0)>>2;f[b>>3]=ke;a[U]=a[b>>2];a[U+1]=a[b+4>>2];var Je=(a[b>>2]=a[Sa],a[b+4>>2]=a[Sa+1],f[b>>3]),jd=Je-((a[b>>2]=a[bb],a[b+4>>2]=a[bb+1],f[b>>3])-Je);Tb=(Ua+24|0)>>2;f[b>>3]=jd;a[Tb]=a[b>>2];a[Tb+1]=a[b+4>>2];var Ld=ke+((a[b>>2]=a[Ra],a[b+4>>2]=a[Ra+1],f[b>>3])-(a[b>>2]=a[Xa],a[b+4>>2]=a[Xa+1],f[b>>3]));ga=(Ua+32|0)>>2;f[b>>3]=Ld;a[ga]=a[b>>2];a[ga+1]=a[b+4>>2];var Ad=jd+((a[b>>2]=a[ca],a[b+4>>2]=a[ca+1],f[b>>3])-(a[b>>2]=a[bb],a[b+4>>2]=a[bb+1],f[b>>3]));O=(Ua+40|0)>>2;f[b>>3]=Ad;a[O]=a[b>>2];a[O+1]=a[b+4>>2];mc=(Ua+48|0)>>2;a[mc]=a[$];a[mc+1]=a[$+1];a[mc+2]=a[$+2];a[mc+3]=a[$+3];td(u,ed,4);a[ua]=a[ja];a[ua+1]=a[ja+1];a[ua+2]=a[ja+2];a[ua+3]=a[ja+3];var wc=(a[b>>2]=a[ya],a[b+4>>2]=a[ya+1],f[b>>3]),gd=wc-((a[b>>2]=a[va],a[b+4>>2]=a[va+1],f[b>>3])-wc);f[b>>3]=gd;a[U]=a[b>>2];a[U+1]=a[b+4>>2];var Hd=(a[b>>2]=a[Q],a[b+4>>2]=a[Q+1],f[b>>3]),Id=Hd-((a[b>>2]=a[la],a[b+4>>2]=a[la+1],f[b>>3])-Hd);f[b>>3]=Id;a[Tb]=a[b>>2];a[Tb+1]=a[b+4>>2];var Rc=gd+((a[b>>2]=a[ka],a[b+4>>2]=a[ka+1],f[b>>3])-(a[b>>2]=a[va],a[b+4>>2]=a[va+1],f[b>>3]));f[b>>3]=Rc;a[ga]=a[b>>2];a[ga+1]=a[b+4>>2];var vc=Id+((a[b>>2]=a[oa],a[b+4>>2]=a[oa+1],f[b>>3])-(a[b>>2]=a[la],a[b+4>>2]=a[la+1],f[b>>3]));f[b>>3]=vc;a[O]=a[b>>2];a[O+1]=a[b+4>>2];a[mc]=a[Na];a[mc+1]=a[Na+1];a[mc+2]=a[Na+2];a[mc+3]=a[Na+3];td(u,ed,4);E(nc)}else{if(64==(xb|0)){eb(u,g);0!=(j|0)&&Sb(u,s);var Md=c+2|0,nd=da(Md<<4);N=nd>>2;ib=e>>2;a[N]=a[ib];a[N+1]=a[ib+1];a[N+2]=a[ib+2];a[N+3]=a[ib+3];ma=(nd+16|0)>>2;a[ma]=a[Ma];a[ma+1]=a[Ma+1];a[ma+2]=a[Ma+2];a[ma+3]=a[Ma+3];var Nc=(a[b>>2]=a[Dc>>2],a[b+4>>2]=a[Dc+4>>2],f[b>>3]),zc=za+48|0;ba=zc>>2;X=zc>>2;W=(za+64|0)>>2;var Mc=Nc+((a[b>>2]=a[X],a[b+4>>2]=a[X+1],f[b>>3])-(a[b>>2]=a[W],a[b+4>>2]=a[W+1],f[b>>3]))/3,Pc=nd+32|0;f[b>>3]=Mc;a[Pc>>2]=a[b>>2];a[Pc+4>>2]=a[b+4>>2];var Gc=za+40|0,kd=(a[b>>2]=a[Gc>>2],a[b+4>>2]=a[Gc+4>>2],f[b>>3]);V=(za+56|0)>>2;Fb=(za+72|0)>>2;var Nd=kd+((a[b>>2]=a[V],a[b+4>>2]=a[V+1],f[b>>3])-(a[b>>2]=a[Fb],a[b+4>>2]=a[Fb+1],f[b>>3]))/3,Qc=nd+40|0;f[b>>3]=Nd;a[Qc>>2]=a[b>>2];a[Qc+4>>2]=a[b+4>>2];var Fc=(a[b>>2]=a[X],a[b+4>>2]=a[X+1],f[b>>3]),pd=Fc+(Fc-(a[b>>2]=a[W],a[b+4>>2]=a[W+1],f[b>>3]))/3,ud=nd+48|0;f[b>>3]=pd;a[ud>>2]=a[b>>2];a[ud+4>>2]=a[b+4>>2];var be=(a[b>>2]=a[V],a[b+4>>2]=a[V+1],f[b>>3]),fd=be+(be-(a[b>>2]=a[Fb],a[b+4>>2]=a[Fb+1],f[b>>3]))/3,vd=nd+56|0;f[b>>3]=fd;a[vd>>2]=a[b>>2];a[vd+4>>2]=a[b+4>>2];a:do{if(4<(Md|0)){for(var yc=4;;){wa=((yc<<4)+nd|0)>>2;ea=((yc-2<<4)+e|0)>>2;a[wa]=a[ea];a[wa+1]=a[ea+1];a[wa+2]=a[ea+2];a[wa+3]=a[ea+3];var Ed=yc+1|0;if((Ed|0)==(Md|0)){break a}else{yc=Ed}}}}while(0);tc(u,nd,Md,j&255);E(nd);P=Ua>>2;a[P]=a[ba];a[P+1]=a[ba+1];a[P+2]=a[ba+2];a[P+3]=a[ba+3];Rb=(Ua+16|0)>>2;a[Rb]=a[Ma];a[Rb+1]=a[Ma+1];a[Rb+2]=a[Ma+2];a[Rb+3]=a[Ma+3];td(u,Ua|0,2)}else{if(256==(xb|0)){4!=(c|0)&&ia(5335932,562,5379500,5362900);eb(u,g);0!=(j|0)&&Sb(u,s);var od=c+2|0,ge=da(od<<4);G=ge>>2;Y=e>>2;a[G]=a[Y];a[G+1]=a[Y+1];a[G+2]=a[Y+2];a[G+3]=a[Y+3];R=(ge+16|0)>>2;a[R]=a[Ma];a[R+1]=a[Ma+1];a[R+2]=a[Ma+2];a[R+3]=a[Ma+3];J=(ge+32|0)>>2;yb=(za+64|0)>>2;a[J]=a[yb];a[J+1]=a[yb+1];a[J+2]=a[yb+2];a[J+3]=a[yb+3];H=(ge+48|0)>>2;L=(e+32|0)>>2;a[H]=a[L];a[H+1]=a[L+1];a[H+2]=a[L+2];a[H+3]=a[L+3];M=(ge+64|0)>>2;K=(za+128|0)>>2;a[M]=a[K];a[M+1]=a[K+1];a[M+2]=a[K+2];a[M+3]=a[K+3];T=(ge+80|0)>>2;Z=(za+160|0)>>2;a[T]=a[Z];a[T+1]=a[Z+1];a[T+2]=a[Z+2];a[T+3]=a[Z+3];tc(u,ge,od,j&255);E(ge);var Fd=(a[b>>2]=a[Zb>>2],a[b+4>>2]=a[Zb+4>>2],f[b>>3]),Dd=za+176|0,Xd=Fd+((a[b>>2]=a[Dd>>2],a[b+4>>2]=a[Dd+4>>2],f[b>>3])-(a[b>>2]=a[za>>2],a[b+4>>2]=a[za+4>>2],f[b>>3])),Bd=Ua|0,Pd=Ua|0;f[b>>3]=Xd;a[Pd>>2]=a[b>>2];a[Pd+4>>2]=a[b+4>>2];var Jd=za+24|0,Qd=(a[b>>2]=a[Jd>>2],a[b+4>>2]=a[Jd+4>>2],f[b>>3]),Gd=za+184|0,jf=za+8|0,Vd=Qd+((a[b>>2]=a[Gd>>2],a[b+4>>2]=a[Gd+4>>2],f[b>>3])-(a[b>>2]=a[jf>>2],a[b+4>>2]=a[jf+4>>2],f[b>>3])),Od=Ua+8|0;f[b>>3]=Vd;a[Od>>2]=a[b>>2];a[Od+4>>2]=a[b+4>>2];I=(Ua+16|0)>>2;a[I]=a[yb];a[I+1]=a[yb+1];a[I+2]=a[yb+2];a[I+3]=a[yb+3];td(u,Bd,2);a[I]=a[K];a[I+1]=a[K+1];a[I+2]=a[K+2];a[I+3]=a[K+3];td(u,Bd,2);a[I]=a[vb];a[I+1]=a[vb+1];a[I+2]=a[vb+2];a[I+3]=a[vb+3];td(u,Bd,2)}else{if(32==(xb|0)){eb(u,g);0!=(j|0)&&Sb(u,s);var ce=c+1|0,Wd=da(ce<<4);C=Wd>>2;a:do{if(1<(c|0)){for(var de=1;;){A=((de<<4)+Wd|0)>>2;S=((de<<4)+e|0)>>2;a[A]=a[S];a[A+1]=a[S+1];a[A+2]=a[S+2];a[A+3]=a[S+3];var le=de+1|0;if((le|0)==(c|0)){break a}else{de=le}}}}while(0);var Td=3*c&-1;D=((Td+1<<4)+za|0)>>2;a[C]=a[D];a[C+1]=a[D+1];a[C+2]=a[D+2];a[C+3]=a[D+3];F=((c<<4)+Wd|0)>>2;B=((Td-1<<4)+za|0)>>2;a[F]=a[B];a[F+1]=a[B+1];a[F+2]=a[B+2];a[F+3]=a[B+3];tc(u,Wd,ce,j&255);E(Wd);var xe=Ua|0;z=Ua>>2;a[z]=a[B];a[z+1]=a[B+1];a[z+2]=a[B+2];a[z+3]=a[B+3];var Yd=Ua+16|0;y=Yd>>2;a[y]=a[D];a[y+1]=a[D+1];a[y+2]=a[D+2];a[y+3]=a[D+3];var Zd=Yd|0,qe=(a[b>>2]=a[Zd>>2],a[b+4>>2]=a[Zd+4>>2],f[b>>3]),$d=Ua|0,fe=(Td<<4)+za|0,se=qe+((a[b>>2]=a[$d>>2],a[b+4>>2]=a[$d+4>>2],f[b>>3])-(a[b>>2]=a[fe>>2],a[b+4>>2]=a[fe+4>>2],f[b>>3])),oe=Ua+32|0,ye=oe|0;f[b>>3]=se;a[ye>>2]=a[b>>2];a[ye+4>>2]=a[b+4>>2];var ze=Ua+24|0,Me=(a[b>>2]=a[ze>>2],a[b+4>>2]=a[ze+4>>2],f[b>>3]),Ce=Ua+8|0,De=(Td<<4)+za+8|0,Ne=Me+((a[b>>2]=a[Ce>>2],a[b+4>>2]=a[Ce+4>>2],f[b>>3])-(a[b>>2]=a[De>>2],a[b+4>>2]=a[De+4>>2],f[b>>3])),re=Ua+40|0;f[b>>3]=Ne;a[re>>2]=a[b>>2];a[re+4>>2]=a[b+4>>2];td(u,Yd,2);t=oe>>2;a[y]=a[t];a[y+1]=a[t+1];a[y+2]=a[t+2];a[y+3]=a[t+3];td(u,xe,2)}else{if(128==(xb|0)){eb(u,g);0!=(j|0)&&Sb(u,s);var ee=c+3|0,Le=da(ee<<4);v=Le>>2;n=e>>2;a[v]=a[n];a[v+1]=a[n+1];a[v+2]=a[n+2];a[v+3]=a[n+3];i=(e|0)>>2;var Fe=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3]);m=Zb>>2;var Pe=Fe-.25*(Fe-(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3])),ve=Le+16|0;f[b>>3]=Pe;a[ve>>2]=a[b>>2];a[ve+4>>2]=a[b+4>>2];var we=e+8|0,Ve=(a[b>>2]=a[we>>2],a[b+4>>2]=a[we+4>>2],f[b>>3]),He=za+48|0;q=(za+56|0)>>2;var pe=za+72|0,Ae=Ve+((a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3])-(a[b>>2]=a[pe>>2],a[b+4>>2]=a[pe+4>>2],f[b>>3]))/3,Be=Le+24|0;f[b>>3]=Ae;a[Be>>2]=a[b>>2];a[Be+4>>2]=a[b+4>>2];var Oe=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3]),$e=Oe-2*(Oe-(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3])),Se=Le+32|0;f[b>>3]=$e;a[Se>>2]=a[b>>2];a[Se+4>>2]=a[b+4>>2];var Te=Le+40|0;f[b>>3]=Ae;a[Te>>2]=a[b>>2];a[Te+4>>2]=a[b+4>>2];var Ue=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3]),cf=Ue-2.25*(Ue-(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3])),We=Le+48|0;f[b>>3]=cf;a[We>>2]=a[b>>2];a[We+4>>2]=a[b+4>>2];var df=(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3]),Xe=Le+56|0;f[b>>3]=df;a[Xe>>2]=a[b>>2];a[Xe+4>>2]=a[b+4>>2];var ef=(a[b>>2]=a[He>>2],a[b+4>>2]=a[He+4>>2],f[b>>3]),Ye=Le+64|0;f[b>>3]=ef;a[Ye>>2]=a[b>>2];a[Ye+4>>2]=a[b+4>>2];var ff=(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3]),Ze=Le+72|0;f[b>>3]=ff;a[Ze>>2]=a[b>>2];a[Ze+4>>2]=a[b+4>>2];a:do{if(4<(ee|0)){for(var Ee=4;;){r=((Ee<<4)+Le|0)>>2;k=((Ee-3<<4)+e|0)>>2;a[r]=a[k];a[r+1]=a[k+1];a[r+2]=a[k+2];a[r+3]=a[k+3];var af=Ee+1|0;if((af|0)==(ee|0)){break a}else{Ee=af}}}}while(0);tc(u,Le,ee,j&255);E(Le)}}}}}}}E(za);h=Ua}function to(u){var s,g,e,c,d,j,k,r,q=0,m=h;h=h+32|0;r=m>>2;var w=m+8;k=w>>2;var x=m+16,v=m+24,t=da(44);j=t>>2;var y=u+24|0,z=a[a[y>>2]+8>>2];d=z>>2;var B=a[d],F=a[d+1],D=a[d+2],S=z+12|0,A=(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3]),C=z+28|0,I=(a[b>>2]=a[C>>2],a[b+4>>2]=a[C+4>>2],f[b>>3]),Z=z+20|0,T=(a[b>>2]=a[Z>>2],a[b+4>>2]=a[Z+4>>2],f[b>>3]),K=u|0,M=Ph(U(K,5332288))&255|B,L=0!=(M|0);if(L){var E,yb=u|0,H=lc(yb,a[1345343],0,.01),R=lc(yb,a[1345359],0,.02),J=72*(H>R?H:R);E=(0>J?J-.5:J+.5)&-1|0;if(0<E){var G=E,Rb=E}else{var P=u+48|0,ea=(a[b>>2]=a[P>>2],a[b+4>>2]=a[P+4>>2],f[b>>3]),wa=u+56|0,Fb=(a[b>>2]=a[wa>>2],a[b+4>>2]=a[wa+4>>2],f[b>>3]),V=72*(ea<Fb?ea:Fb),W=(0>V?V-.5:V+.5)&-1|0,Rb=G=W}}else{var X=u+48|0,ba=72*(a[b>>2]=a[X>>2],a[b+4>>2]=a[X+4>>2],f[b>>3]),ma=0>ba?ba-.5:ba+.5,ib=u+56|0,N=72*(a[b>>2]=a[ib>>2],a[b+4>>2]=a[ib+4>>2],f[b>>3]),G=(0>N?N-.5:N+.5)&-1|0,Rb=ma&-1|0}var mc=ve(K,a[1345350],F),O=A+lc(K,a[1345352],0,-360);if(0==(D|0)){var ga=lc(K,a[1345346],0,-100),Tb=ve(K,a[1345347],4),Q=lc(K,a[1345367],0,-100),ua=ga,Da=Tb}else{Q=T,ua=I,Da=D}c=(u+120|0)>>2;var Ja=a[c],Ab=Ja+24|0,ra=(a[b>>2]=a[Ab>>2],a[b+4>>2]=a[Ab+4>>2],f[b>>3]),ca=Ja+32|0,ya=(a[b>>2]=a[ca>>2],a[b+4>>2]=a[ca+4>>2],f[b>>3]),ja=ra&-1,la=-1<(ja|0)?ja:-ja|0,va=la|0,q=-1<(la|0)?0==(va+.5&-1|0)?739:742:0==(va-.5&-1|0)?739:742;if(739==q){var oa=ya&-1,ka=-1<(oa|0)?oa:-oa|0,Ea=ka|0;if(-1<(ka|0)){if(0==(Ea+.5&-1|0)){var Ka=ra,Na=ya}else{q=742}}else{0==(Ea-.5&-1|0)?(Ka=ra,Na=ya):q=742}}if(742==q){var Ba=U(K,5332848);if(0==(Ba|0)){Ka=ra+16,Na=ya+8}else{var Wa=gd(Ba,5332588,(i=h,h=h+8|0,a[i>>2]=m,a[i+4>>2]=w,i)),ia=(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3]);if(0>ia){f[b>>3]=0;a[r]=a[b>>2];a[r+1]=a[b+4>>2];var ha=0}else{ha=ia}var Ra=(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3]);if(0>Ra){f[b>>3]=0;a[k]=a[b>>2];a[k+1]=a[b+4>>2];var bb=0}else{bb=Ra}if(0<(Wa|0)){var Xa=72*ha,Sa=0>Xa,sa=ra+(((Sa?Xa-.5:Xa+.5)&-1)<<1|0);if(1<(Wa|0)){var Va=72*bb,Ta=0>Va?Va-.5:Va+.5,Ka=sa,Na=ya+((Ta&-1)<<1|0)}else{var Aa=Sa?Xa-.5:Xa+.5,Ka=sa,Na=ya+((Aa&-1)<<1|0)}}else{Ka=ra+16,Na=ya+8}}}var fb=a[c]+24|0,Ca=Ka-(a[b>>2]=a[fb>>2],a[b+4>>2]=a[fb+4>>2],f[b>>3]);e=(u+20|0)>>2;var Ya=a[a[e]+44>>2]|0,$a=(a[b>>2]=a[Ya>>2],a[b+4>>2]=a[Ya+4>>2],f[b>>3]);if(0<$a){var La=72*$a,pa=(0>La?La-.5:La+.5)&-1|0,Ga=uo(Ka,pa),Fa=uo(Na,pa)}else{Ga=Ka,Fa=Na}var fa=a[y>>2];if(0==n[fa+12|0]<<24>>24){var nb=U(K,5334020);if(0==(nb|0)){var jb=0,cb=0}else{if(0==n[nb]<<24>>24){cb=jb=0}else{vo(v,a[e],nb);var qa=a[v>>2],kb=a[v+4>>2];if(-1==(qa|0)&-1==(kb|0)){var Kb=a[u+12>>2];aa(0,5331296,(i=h,h=h+8|0,a[i>>2]=nb,a[i+4>>2]=Kb,i));cb=jb=0}else{n[a[e]+150|0]=1,jb=qa+2|0,cb=kb+2|0}}}}else{var Ma=a[fa>>2];if(99!=n[Ma]<<24>>24){cb=jb=0}else{if(0!=($(Ma,5340528)|0)){cb=jb=0}else{var ld=U(K,5348352);vo(x,a[e],ld);var lb=a[x>>2],rb=a[x+4>>2];if(-1==(lb|0)&-1==(rb|0)){var ab=a[u+12>>2];aa(0,5331940,(i=h,h=h+8|0,a[i>>2]=0!=(ld|0)?ld:5331680,a[i+4>>2]=ab,i));cb=jb=0}else{n[a[e]+150|0]=1,jb=lb+2|0,cb=rb+2|0}}}}var db=jb|0,ob=Ga>db?Ga:db,pb=cb|0,ub=Fa>pb?Fa:pb,gb=3>(Da|0)?0!=Q|0!=ua?120:Da:Da,sb=U(K,5376820);if(0==(sb|0)){q=783}else{var Ia=n[sb];116==Ia<<24>>24|98==Ia<<24>>24?n[a[c]+80|0]=Ia:q=783}783==q&&(n[a[c]+80|0]=99);if(4==(gb|0)){if(0==(((0>O?O-.5:O+.5)&-1|0)%90|0)&0==Q&0==ua){var vb=ob,Ua=ub,xa=1}else{q=789}}else{q=789}if(789==q){var na=1.4142135623730951*ub;if(G>na){if(99!=n[a[c]+80|0]<<24>>24){var qb=1.4142135623730951,Bb=na}else{var sc=ub/G,qb=Math.sqrt(1/(1-sc*sc)),Bb=ub}}else{qb=1.4142135623730951,Bb=na}var xb=ob*qb;if(2<(gb|0)){var za=Math.cos(3.141592653589793/(gb|0)),vb=xb/za,Ua=Bb/za}else{vb=xb,Ua=Bb}xa=0}if(0==Xd($b(K,a[1345364],5333780))<<24>>24){var Nb=Rb>vb?Rb:vb,Jb=G>Ua?G:Ua}else{if(Rb<vb|G<Ua){var Ha=a[a[e]+12>>2];aa(0,5330716,(i=h,h=h+8|0,a[i>>2]=a[u+12>>2],a[i+4>>2]=Ha,i))}Nb=Rb;Jb=G}if(L){var ta=Nb>Jb?Nb:Jb,Ic=ta,Oa=ta}else{Ic=Nb,Oa=Jb}if(0==Xd($b(K,a[1345354],5333780))<<24>>24){if(xa){var Pa=a[c]+40|0;f[b>>3]=(Ga>Ic?Ga:Ic)-Ca;a[Pa>>2]=a[b>>2];a[Pa+4>>2]=a[b+4>>2]}else{if(Fa<Oa){var Za=Ic*Math.sqrt(1-Fa*Fa/(Oa*Oa)),zb=a[c]+40|0;f[b>>3]=(Ga>Za?Ga:Za)-Ca;a[zb>>2]=a[b>>2];a[zb+4>>2]=a[b+4>>2]}else{var eb=a[c]+40|0;f[b>>3]=Ga-Ca;a[eb>>2]=a[b>>2];a[eb+4>>2]=a[b+4>>2]}}}else{var mb=a[c]+40|0;f[b>>3]=Ga-Ca;a[mb>>2]=a[b>>2];a[mb+4>>2]=a[b+4>>2]}var Ub=Oa-Ua,hb=a[c]+48|0;f[b>>3]=Fa+(Fa<pb?Ub+(pb-Fa):Ub);a[hb>>2]=a[b>>2];a[hb+4>>2]=a[b+4>>2];var wb=1>(mc|0)?1:mc;a:do{if(3>(gb|0)){var Db=da(wb<<5),Cb=Db,Ib=.5*Ic,tb=.5*Oa,Eb=Db;f[b>>3]=-Ib;a[Eb>>2]=a[b>>2];a[Eb+4>>2]=a[b+4>>2];var Qa=Db+8|0;f[b>>3]=-tb;a[Qa>>2]=a[b>>2];a[Qa+4>>2]=a[b+4>>2];var cc=Db+16|0;f[b>>3]=Ib;a[cc>>2]=a[b>>2];a[cc+4>>2]=a[b+4>>2];var pc=Db+24|0;f[b>>3]=tb;a[pc>>2]=a[b>>2];a[pc+4>>2]=a[b+4>>2];if(1<(mc|0)){for(var Hb=tb,hd=Ib,qd=2,Vb=1;;){var Yb=hd+4,Jc=Hb+4,Mb=(qd<<4)+Cb|0;f[b>>3]=-Yb;a[Mb>>2]=a[b>>2];a[Mb+4>>2]=a[b+4>>2];var Pb=(qd<<4)+Cb+8|0;f[b>>3]=-Jc;a[Pb>>2]=a[b>>2];a[Pb+4>>2]=a[b+4>>2];var Sb=qd|1,Xb=(Sb<<4)+Cb|0;f[b>>3]=Yb;a[Xb>>2]=a[b>>2];a[Xb+4>>2]=a[b+4>>2];var Zb=(Sb<<4)+Cb+8|0;f[b>>3]=Jc;a[Zb>>2]=a[b>>2];a[Zb+4>>2]=a[b+4>>2];var kc=Vb+1|0;if((kc|0)==(mc|0)){break}else{Hb=Jc,hd=Yb,qd=qd+2|0,Vb=kc}}uc=Cb;hc=2;Lb=2*Yb;ne=2*Jc}else{var uc=Cb,hc=2,Lb=Ic,ne=Oa}}else{for(var Kc=da(Math.a(wb<<4,gb)),rc=Kc,fc=6.283185307179586/(gb|0),Cc=.5*fc,ic=Math.sin(Cc),Dc=If(Math.abs(Q)+Math.abs(ua),1),gc=1.4142135623730951*Q/Math.cos(Cc),ec=.5*ua,ac=.5*(fc-3.141592653589793),Yc=3.141592653589793*(O/180),xc=0,Qb=ac+.5*(3.141592653589793-fc),Wc=0,ae=0,jc=.5*Math.sin(ac),dc=.5*Math.cos(ac);;){if((xc|0)>=(gb|0)){var bc=Wc,Kd=ae;break}var Sc=Qb+fc,bd=dc+ic*Math.cos(Sc),Vc=jc+ic*Math.sin(Sc),cd=bd*(Dc+Vc*gc)+Vc*ec,Zc=Yc+Math.atan2(Vc,cd),nc=If(cd,Vc),Oc=nc*Math.cos(Zc)*Ic,Lc=nc*Math.sin(Zc)*Oa,dd=Math.abs(Oc)>Wc?Math.abs(Oc):Wc,Sd=Math.abs(Lc)>ae?Math.abs(Lc):ae,id=(xc<<4)+rc|0;f[b>>3]=Oc;a[id>>2]=a[b>>2];a[id+4>>2]=a[b+4>>2];var Xc=(xc<<4)+rc+8|0;f[b>>3]=Lc;a[Xc>>2]=a[b>>2];a[Xc+4>>2]=a[b+4>>2];if(xa){q=820;break}else{xc=xc+1|0,Qb=Sc,Wc=dd,ae=Sd,jc=Vc,dc=bd}}if(820==q){var tc=-Oc,$c=Kc+16|0;f[b>>3]=tc;a[$c>>2]=a[b>>2];a[$c+4>>2]=a[b+4>>2];var oc=Kc+24|0;f[b>>3]=Lc;a[oc>>2]=a[b>>2];a[oc+4>>2]=a[b+4>>2];var Re=Kc+32|0;f[b>>3]=tc;a[Re>>2]=a[b>>2];a[Re+4>>2]=a[b+4>>2];var ad=-Lc,Hc=Kc+40|0;f[b>>3]=ad;a[Hc>>2]=a[b>>2];a[Hc+4>>2]=a[b+4>>2];var Tc=Kc+48|0;f[b>>3]=Oc;a[Tc>>2]=a[b>>2];a[Tc+4>>2]=a[b+4>>2];var Ke=Kc+56|0;f[b>>3]=ad;a[Ke>>2]=a[b>>2];a[Ke+4>>2]=a[b+4>>2];bc=dd;Kd=Sd}var Bc=2*bc,Ge=2*Kd,Ie=Ic>Bc?Ic:Bc,Uc=Oa>Ge?Oa:Ge,wd=Ie/Bc,wc=Uc/Ge,xd=0<(gb|0);b:do{if(xd){for(var rd=0;;){g=((rd<<4)+rc|0)>>2;s=((rd<<4)+rc+8|0)>>2;var yd=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])*wd,Ec=(a[b>>2]=a[s],a[b+4>>2]=a[s+1],f[b>>3])*wc;f[b>>3]=yd;a[g]=a[b>>2];a[g+1]=a[b+4>>2];f[b>>3]=Ec;a[s]=a[b>>2];a[s+1]=a[b+4>>2];var Cd=rd+1|0;if((Cd|0)==(gb|0)){break b}else{rd=Cd}}}}while(0);if(1<(mc|0)){var md=gb-1|0,sd=(md<<4)+rc|0,Rc=(a[b>>2]=a[sd>>2],a[b+4>>2]=a[sd+4>>2],f[b>>3]),ed=(md<<4)+rc+8|0,zd=(a[b>>2]=a[ed>>2],a[b+4>>2]=a[ed+4>>2],f[b>>3]),ke=Kc,Je=(a[b>>2]=a[ke>>2],a[b+4>>2]=a[ke+4>>2],f[b>>3]),jd=Kc+8|0,Ld=(a[b>>2]=a[jd>>2],a[b+4>>2]=a[jd+4>>2],f[b>>3]),Ad=Math.atan2(Ld-zd,Je-Rc);if(xd){for(var zc=Je,vc=Ld,Hd=0,Id=Ad;;){for(var Pc=Hd+1|0,Gc=(Pc|0)==(gb|0),Md=Gc?0:Pc,nd=(Md<<4)+rc|0,Nc=(a[b>>2]=a[nd>>2],a[b+4>>2]=a[nd+4>>2],f[b>>3]),yc=(Md<<4)+rc+8|0,Mc=(a[b>>2]=a[yc>>2],a[b+4>>2]=a[yc+4>>2],f[b>>3]),Qc=Math.atan2(Mc-vc,Nc-zc),Fc=.5*(Id+3.141592653589793-Qc),kd=4/Math.sin(Fc),ud=Id-Fc,Nd=Math.sin(ud)*kd,vd=Math.cos(ud)*kd,pd=vc,td=zc,be=1;;){var fd=td+vd,Ed=pd+Nd,Bd=Math.a(be,gb)+Hd|0,od=(Bd<<4)+rc|0;f[b>>3]=fd;a[od>>2]=a[b>>2];a[od+4>>2]=a[b+4>>2];var Dd=(Bd<<4)+rc+8|0;f[b>>3]=Ed;a[Dd>>2]=a[b>>2];a[Dd+4>>2]=a[b+4>>2];var ge=be+1|0;if((ge|0)==(mc|0)){break}else{pd=Ed,td=fd,be=ge}}if(Gc){break}else{zc=Nc,vc=Mc,Hd=Pc,Id=Qc}}for(var Pd=Math.a(gb,mc-1|0),Jd=Uc,Fd=Ie,Gd=0;;){var Od=Gd+Pd|0,Qd=(Od<<4)+rc|0,Wd=(a[b>>2]=a[Qd>>2],a[b+4>>2]=a[Qd+4>>2],f[b>>3]),Vd=(Od<<4)+rc+8|0,de=(a[b>>2]=a[Vd>>2],a[b+4>>2]=a[Vd+4>>2],f[b>>3]),Td=2*Math.abs(Wd)>Fd?2*Math.abs(Wd):Fd,Yd=2*Math.abs(de)>Jd?2*Math.abs(de):Jd,ce=Gd+1|0;if((ce|0)==(gb|0)){uc=rc;hc=gb;Lb=Td;ne=Yd;break a}else{Jd=Yd,Fd=Td,Gd=ce}}}else{uc=rc,hc=gb,Lb=Ie,ne=Uc}}else{uc=rc,hc=gb,Lb=Ie,ne=Uc}}}while(0);a[j]=M;a[j+1]=mc;a[j+2]=hc;var ee=t+12|0;f[b>>3]=O;a[ee>>2]=a[b>>2];a[ee+4>>2]=a[b+4>>2];var le=t+28|0;f[b>>3]=ua;a[le>>2]=a[b>>2];a[le+4>>2]=a[b+4>>2];var Zd=t+20|0;f[b>>3]=Q;a[Zd>>2]=a[b>>2];a[Zd+4>>2]=a[b+4>>2];a[j+10]=uc;var $d=u+48|0;f[b>>3]=Lb/72;a[$d>>2]=a[b>>2];a[$d+4>>2]=a[b+4>>2];var fe=u+56|0;f[b>>3]=ne/72;a[fe>>2]=a[b>>2];a[fe+4>>2]=a[b+4>>2];a[u+28>>2]=t;h=m}function Xf(u,s,g){var e=u|0;f[b>>3]=s;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];u=u+8|0;f[b>>3]=g;a[u>>2]=a[b>>2];a[u+4>>2]=a[b+4>>2]}function wo(u){var s,g,e,c=h;h=h+32|0;var d=c+16,j=a[a[u+20>>2]+152>>2]>>>2&1^1;g=u+120|0;e=a[a[g>>2]>>2];a[1311664]=e;e=xa(e);e=da(1<(e|0)?e+1|0:2);s=$h(u,j,1,e);0==(s|0)?(aa(1,5333516,(i=h,h=h+4|0,a[i>>2]=a[a[g>>2]>>2],i)),a[1311664]=5368832,j=$h(u,j,1,e)):j=s;E(e);$j(c,u,j);e=(u+48|0)>>2;g=72*(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);var k=(0>g?g-.5:g+.5)&-1|0;g=(u+56|0)>>2;s=72*(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]);var r=(0>s?s-.5:s+.5)&-1|0,q=u|0;s=(j|0)>>2;if(0==Xd($b(q,a[1345364],5333780))<<24>>24){var m=(a[b>>2]=a[s],a[b+4>>2]=a[s+1],f[b>>3]),w=j+8|0,n=(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]),r=n>r?n:r,m=m>k?m:k,k=w}else{m=k,k=j+8|0}ak(j,m,r,Xd($b(q,a[1345354],5333780))&255);Xf(d,-.5*m,.5*r);q=d|0;d=d+8|0;bk(j,(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),15);d=(a[b>>2]=a[s],a[b+4>>2]=a[s+1],f[b>>3])/72;f[b>>3]=d;a[e]=a[b>>2];a[e+1]=a[b+4>>2];d=((a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])+1)/72;f[b>>3]=d;a[g]=a[b>>2];a[g+1]=a[b+4>>2];a[u+28>>2]=j;h=c}function xo(u){var s,g,e,c=da(44);e=c>>2;var d=a[a[a[u+24>>2]+8>>2]+4>>2];s=u|0;g=lc(s,a[1345343],1.7976931348623157e+308,3e-4);var j=lc(s,a[1345359],1.7976931348623157e+308,3e-4),k=g<j?g:j;g=(u+56|0)>>2;1.7976931348623157e+308==k&1.7976931348623157e+308==j?(f[b>>3]=.05,a[g]=a[b>>2],a[g+1]=a[b+4>>2],j=u+48|0,f[b>>3]=.05,a[j>>2]=a[b>>2],a[j+4>>2]=a[b+4>>2],k=3.6):(f[b>>3]=k,a[g]=a[b>>2],a[g+1]=a[b+4>>2],j=u+48|0,f[b>>3]=k,a[j>>2]=a[b>>2],a[j+4>>2]=a[b+4>>2],k*=72);j=u+48|0;s=ve(s,a[1345350],d);var d=da(1>(s|0)?32:s<<5),h=.5*k,q=-h;f[b>>3]=q;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];var m=d+8|0;f[b>>3]=q;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];q=d+16|0;f[b>>3]=h;a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];q=d+24|0;f[b>>3]=h;a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];if(1<(s|0)){m=q=h;k=2;for(h=1;;){var i=m+4,q=q+4,m=(k<<4)+d|0;f[b>>3]=-i;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];m=(k<<4)+d+8|0;f[b>>3]=-q;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];var m=k|1,n=(m<<4)+d|0;f[b>>3]=i;a[n>>2]=a[b>>2];a[n+4>>2]=a[b+4>>2];m=(m<<4)+d+8|0;f[b>>3]=q;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];h=h+1|0;if((h|0)==(s|0)){break}else{m=i,k=k+2|0}}i*=2}else{i=k}a[e]=1;a[e+1]=s;a[e+2]=2;s=(c+12|0)>>2;a[s]=0;a[s+1]=0;a[s+2]=0;a[s+3]=0;a[s+4]=0;a[s+5]=0;a[e+10]=d;e=i/72;f[b>>3]=e;a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];f[b>>3]=e;a[g]=a[b>>2];a[g+1]=a[b+4>>2];a[u+28>>2]=c}function zj(b){var c=0,g=a[1345052];if(0==(g|0)){var e;return 0}for(var d=a[1345370],f=0;;){if((f|0)>=(d|0)){e=0;c=867;break}var j=a[g+(f<<2)>>2],k=a[j>>2];if(n[k]<<24>>24==n[b]<<24>>24&&0==($(k,b)|0)){e=j;c=868;break}f=f+1|0}if(867==c||868==c){return e}}function yo(b,c,g,e){var d=h;h=h+40|0;g=zo(c,g,e);a[d+36>>2]=a[e+36>>2];Yf(c,a[e+24>>2],d,g,ca[e+33|0],0);c=d>>2;b>>=2;for(e=c+10;c<e;c++,b++){a[b]=a[c]}h=d}function zo(u,c,g){var e=h;h=h+16|0;var d=e+8,p=u+20|0,j=a[a[a[p>>2]+32>>2]+152>>2]&3,k=u+32|0,r=u+40|0;Ao(e,(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),j);k=c+32|0;c=c+40|0;Ao(d,(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),j);c=n[g+33|0];j=c&255;if(15==c<<24>>24|0==c<<24>>24){return h=e,0}g=a[g+24>>2];if(0==(g|0)){var p=0==(a[a[p>>2]+152>>2]&1|0),g=u+96|0,g=.5*(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),c=-g,u=u+104|0,k=(a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3]),r=-k,u=p?r:c,q=p?c:r,m=p?k:g,r=p?g:k}else{u=g|0,u=(a[b>>2]=a[u>>2],a[b+4>>2]=a[u+4>>2],f[b>>3]),p=g+8|0,c=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),p=g+16|0,g=g+24|0,q=c,m=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),r=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])}var g=a[e>>2],p=a[e+4>>2],c=a[d>>2],d=a[d+4>>2],i=.5*(u+m)&-1,k=.5*(q+r)&-1;if(0==(j&1|0)){var x=0,q=0}else{x=g+i-c|0,q=p+(q&-1)-d|0,x=Math.a(q,q)+Math.a(x,x)|0,q=5337516}if(0==(j&2|0)){m=x}else{var m=g+(m&-1)-c|0,v=p+k-d|0,m=Math.a(m,m)+Math.a(v,v)|0,m=(v=0==(q|0)|(m|0)<(x|0))?m:x,q=v?5334736:q}0==(j&4|0)?(r=m,i=q):(i=g+i-c|0,r=p+(r&-1)-d|0,r=Math.a(i,i)+Math.a(r,r)|0,r=(i=0==(q|0)|(r|0)<(m|0))?r:m,i=i?5335128:q);if(0==(j&8|0)){return h=e,i}j=g+(u&-1)-c|0;u=p+k-d|0;j=0==(i|0)|(Math.a(j,j)+Math.a(u,u)|0)<(r|0)?5357032:i;h=e;return j}function Yf(u,c,g,e,d,p){var j=h;h=h+128|0;var k=j+16,r=j+32,q=j+48,m=j+64,i=j+80,x=j+96,v=j+112;if(0==(c|0)){var t=0==(a[a[u+20>>2]+152>>2]&1|0),y=u+96|0,y=.5*(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),z=u+104|0,z=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3]),B=t?y:z,y=t?z:y,z=0,t=-y,F=-B,D=B,S=B=0}else{var t=c|0,t=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),y=c+8|0,y=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),z=c+16|0,D=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3]),z=c+24|0,A=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3]);Xf(j,.5*(t+D),.5*(y+A));B=j|0;S=j+8|0;z=1;F=y;y=D;D=A;B=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]);S=(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3])}0==(e|0)?(p=z,k=1,q=m=r=d=i=0,x=B,t=S):(A=n[e],0==A<<24>>24?(p=z,k=1,q=m=r=d=i=0,x=B,t=S):(A=A<<24>>24,e=e+1|0,101==(A|0)?(x=0==n[e]<<24>>24,q=x&1,p=x?1:z,k=q^1,i=x?d&2:0,d=0,r=x&1^1,m=0,x=x?y:B,t=S):115==(A|0)?(m=n[e]<<24>>24,101==(m|0)?(0==(p|0)?(x=y,t=F):(Zf(r,p,-2147483647,2147483647),p=r|0,k=r+8|0,x=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),t=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])),p=1,k=0,i=d&3,r=d=0,m=-.7853981633974483,q=1):119==(m|0)?(0==(p|0)?(x=t,t=F):(Zf(q,p,-2147483647,-2147483647),p=q|0,k=q+8|0,x=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),t=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])),p=1,k=0,i=d&9,r=d=0,m=-2.356194490192345,q=1):0==(m|0)?(0==(p|0)?(x=B,t=F):(Zf(k,p,-2147483647,B),p=k|0,k=k+8|0,x=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),t=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])),p=1,k=0,i=d&1,r=d=0,m=-1.5707963267948966,q=1):(p=z,k=1,d=i=0,r=1,q=m=0,x=B,t=S)):110==(A|0)?(k=n[e]<<24>>24,119==(k|0)?(0==(p|0)?(x=t,t=D):(Zf(x,p,2147483647,-2147483647),p=x|0,k=x+8|0,x=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),t=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])),p=1,k=0,i=d&12,r=d=0,m=2.356194490192345,q=1):101==(k|0)?(0==(p|0)?(x=y,t=D):(Zf(i,p,2147483647,2147483647),p=i|0,k=i+8|0,x=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),t=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])),p=1,k=0,i=d&6,r=d=0,m=.7853981633974483,q=1):0==(k|0)?(0==(p|0)?(x=B,t=D):(Zf(m,p,2147483647,B),p=m|0,k=m+8|0,x=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),t=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])),p=1,k=0,i=d&4,r=d=0,m=1.5707963267948966,q=1):(p=z,k=1,d=i=0,r=1,q=m=0,x=B,t=S)):(99==(A|0)?(p=z,k=1,q=m=r=d=i=0,x=B):95==(A|0)?(p=z,k=1,i=d,d=1,q=m=r=0,x=B):119==(A|0)?(x=0==n[e]<<24>>24,q=x&1,p=x?1:z,k=q^1,i=x?d&8:0,d=0,r=x&1^1,m=x?3.141592653589793:0,x=x?t:B):(p=z,k=1,d=i=0,r=1,q=m=0,x=B),t=S)));u=(u+20|0)>>2;Nn(v,x,t,90*(a[a[u]+152>>2]&3)&-1);x=v|0;x=(a[b>>2]=a[x>>2],a[b+4>>2]=a[x+4>>2],f[b>>3]);v=v+8|0;v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]);n[g+33|0]=0==d<<24>>24?(2==(a[a[u]+152>>2]&3|0)?1==(i|0)?4:4==(i|0)?1:i:1==(a[a[u]+152>>2]&3|0)?2==(i|0)?1:4==(i|0)?2:8==(i|0)?4:1==(i|0)?8:i:3==(a[a[u]+152>>2]&3|0)?4==(i|0)?2:1==(i|0)?8:8==(i|0)?1:2==(i|0)?4:i:i)&255:i&255;a[g+24>>2]=c;c=g|0;f[b>>3]=(0>x?x-.5:x+.5)&-1|0;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];c=g+8|0;f[b>>3]=(0>v?v-.5:v+.5)&-1|0;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];c=g+16|0;a:{if(u=a[a[u]+152>>2]&3,3==(u|0)){if(3.141592653589793==m){u=-1.5707963267948966}else{if(2.356194490192345==m){u=-.7853981633974483}else{if(1.5707963267948966==m){u=0}else{if(.7853981633974483==m){u=m}else{if(0==m){u=1.5707963267948966}else{if(-.7853981633974483==m){u=2.356194490192345}else{u=-1.5707963267948966==m?3.141592653589793:m;break a}}}}}}}else{u=2==(u|0)?-1*m:1==(u|0)?m-1.5707963267948966:m}}f[b>>3]=u;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];if(0==x&0==v){return n[g+32|0]=-128,n[g+29|0]=q,n[g+28|0]=p,n[g+30|0]=k,n[g+31|0]=d,h=j,r}c=Math.atan2(v,x)+4.71238898038469;n[g+32|0]=256*(6.283185307179586>c?c:c-6.283185307179586)/6.283185307179586&255;n[g+29|0]=q;n[g+28|0]=p;n[g+30|0]=k;n[g+31|0]=d;h=j;return r}function Ao(b,c,g,e){var d=0;if(3==(e|0)){var f=c,j=g,d=990}else{if(1==(e|0)){f=c,j=-g,d=990}else{if(2==(e|0)){f=-g,j=c,d=990}else{if(0==(e|0)){f=g,j=c,d=990}else{var k=0,h=0,d=991}}}}if(990==d){if(0>j){var q=j-.5,m=f}else{k=j,h=f,d=991}}991==d&&(q=k+.5,m=h);a[b>>2]=q&-1;a[b+4>>2]=(0>m?m-.5:m+.5)&-1}function Zf(u,c,g,e){var d,p=h;h=h+64|0;var j=a[c>>2],k=p+16|0;d=p>>2;a[d]=0;a[d+1]=0;a[d+2]=0;a[d+3]=0;f[b>>3]=e/3;a[k>>2]=a[b>>2];a[k+4>>2]=a[b+4>>2];k=p+24|0;f[b>>3]=g/3;a[k>>2]=a[b>>2];a[k+4>>2]=a[b+4>>2];k=p+32|0;f[b>>3]=2*e/3;a[k>>2]=a[b>>2];a[k+4>>2]=a[b+4>>2];k=p+40|0;f[b>>3]=2*g/3;a[k>>2]=a[b>>2];a[k+4>>2]=a[b+4>>2];k=p+48|0;f[b>>3]=e;a[k>>2]=a[b>>2];a[k+4>>2]=a[b+4>>2];e=p+56|0;f[b>>3]=g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];Ag(c,a[a[a[j+24>>2]+4>>2]+12>>2],p|0,1);u>>=2;a[u]=a[d];a[u+1]=a[d+1];a[u+2]=a[d+2];a[u+3]=a[d+3];h=p}function Bo(b,c,g,e){var d,f=0,j=h;h=h+52|0;var k=j+40;d=k>>2;var r=j+44;if(0==n[g]<<24>>24){c=1345557}else{e=0==(e|0)?5339788:e;a[d]=15;var q=a[c+120>>2];0==n[q+82|0]<<24>>24?f=1004:(q=a[q+72>>2],2==n[q+4|0]<<24>>24?k=0:(q=Yn(a[q>>2],g),0==(q|0)?k=0:(a[k>>2]=ca[q+31|0],k=q+40|0)),0==(k|0)?f=1004:0!=(Yf(c,k,j,e,a[d],0)|0)&&aa(0,5339476,(i=h,h=h+12|0,a[i>>2]=a[c+12>>2],a[i+4>>2]=g,a[i+8>>2]=e,i)));1004==f&&(5250500==(a[a[c+24>>2]+8>>2]|0)?f=0:(a[r>>2]=c,a[r+4>>2]=0,f=r),0!=(Yf(c,0,j,g,a[d],f)|0)&&Co(a[c+12>>2],g));c=j>>2}b>>=2;for(g=c+10;c<g;c++,b++){a[b]=a[c]}h=j}function Do(c,s){var g,e,d,p=h,j=a[c+16>>2];d=j>>2;j=j+148|0;e=a[j>>2];var k=0==(e|0)?0!=(a[d+50]&1|0):1,r=a[s+28>>2];g=r>>2;if(0!=(r|0)){k&&0==(a[c+148>>2]&4|0)&&Mc(c,e,a[d+42],a[d+46],a[d+38]);e=a[c+36>>2];var r=s+32|0,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3])+(a[g+1]|0),q=s+40|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])+(a[g+2]|0);g=a[g];Lb(e,5340064,(i=h,h=h+20|0,f[b>>3]=r,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=q,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],a[i+16>>2]=g,i));r=s+120|0;e=(a[r>>2]+56|0)>>2;g=(s+32|0)>>2;a[e]=a[g];a[e+1]=a[g+1];a[e+2]=a[g+2];a[e+3]=a[g+3];Te(c,10,a[r>>2]);k&&(0!=(a[c+148>>2]&4|0)&&Mc(c,a[j>>2],a[d+42],a[d+46],a[d+38]),de(c))}h=p}function Co(b,c){var g=h;aa(0,5339148,(i=h,h=h+8|0,a[i>>2]=b,a[i+4>>2]=c,i));h=g}function Eo(c,s,g){var e=h;h=h+16|0;var d=a[c+4>>2],c=a[c>>2];Wf(e,s,g,90*(a[a[c+20>>2]+152>>2]&3)&-1);s=e|0;s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]);g=e+8|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);if(0==(d|0)){var d=a[c+28>>2],p=d+16|0,j=d+24|0,c=d+32|0,d=d+40|0}else{p=d,j=d+8|0,c=d+16|0,d=d+24|0}p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);if(p>s){return h=e,0}j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);if(s>(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])|j>g){return h=e,0}s=g<=d&1;h=e;return s}function Fo(c,s,g,e,d){var p,j,k=0,r=h;h=h+32|0;if(0==n[s+28|0]<<24>>24){var q;h=r;return 0}for(var s=s|0,s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]),m=a[c+28>>2],i=a[m+48>>2],x=c+20|0,m=m+56|0,v=0;;){if((v|0)>=(i|0)){q=g;k=1070;break}var t=0==(a[a[x>>2]+152>>2]&1|0);j=a[a[m>>2]+(v<<2)>>2];if(t){var y=j+32|0,z=j+16|0}else{y=j+40|0,z=j+24|0}z=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3])&-1|0;if(z<=s&&(p=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3])&-1|0,s<=p)){break}v=v+1|0}if(1070==k){return h=r,q}t?(j=(c+32|0)>>2,k=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3])+z,q=e|0,f[b>>3]=k,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],q=c+40|0,k=c+96|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])-.5*(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),t=e+8|0,f[b>>3]=q,a[t>>2]=a[b>>2],a[t+4>>2]=a[b+4>>2],p=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3])+p,j=e+16|0,f[b>>3]=p,a[j>>2]=a[b>>2],a[j+4>>2]=a[b+4>>2],p=k):(p=c+32|0,k=c+40|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),q=h,j=(j+16|0)>>2,z=h,h=h+32|0,a[z>>2]=a[j],a[z+4>>2]=a[j+1],a[z+8>>2]=a[j+2],a[z+12>>2]=a[j+3],a[z+16>>2]=a[j+4],a[z+20>>2]=a[j+5],a[z+24>>2]=a[j+6],a[z+28>>2]=a[j+7],j=z+24|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),t=z+16|0,t=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),s=z+8|0,i=z|0,z=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3])+p,s=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3])+k,i=r|0,f[b>>3]=z,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],z=r+8|0,f[b>>3]=s,a[z>>2]=a[b>>2],a[z+4>>2]=a[b+4>>2],z=r+16|0,f[b>>3]=j+p,a[z>>2]=a[b>>2],a[z+4>>2]=a[b+4>>2],p=r+24|0,f[b>>3]=t+k,a[p>>2]=a[b>>2],a[p+4>>2]=a[b+4>>2],h=q,j=e>>2,p=r>>2,a[j]=a[p],a[j+1]=a[p+1],a[j+2]=a[p+2],a[j+3]=a[p+3],a[j+4]=a[p+4],a[j+5]=a[p+5],a[j+6]=a[p+6],a[j+7]=a[p+7],p=c+96|0);c=c+40|0;c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])+.5*(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);e=e+24|0;f[b>>3]=c;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];a[d>>2]=1;h=r;return g}function Go(c,s){var g,e,d,p,j,k=h;h=h+96|0;var r=k+32,q=a[c+16>>2];j=q>>2;var q=q+148|0,m=a[q>>2],i=0==(m|0)?0!=(a[j+50]&1|0):1,x=a[s+28>>2];g=(x+16|0)>>2;e=k>>2;a[e]=a[g];a[e+1]=a[g+1];a[e+2]=a[g+2];a[e+3]=a[g+3];a[e+4]=a[g+4];a[e+5]=a[g+5];a[e+6]=a[g+6];a[e+7]=a[g+7];g=s+32|0;d=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);g=(k|0)>>2;var v=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])+d;f[b>>3]=v;a[g]=a[b>>2];a[g+1]=a[b+4>>2];g=s+40|0;v=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);g=(k+8|0)>>2;p=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])+v;f[b>>3]=p;a[g]=a[b>>2];a[g+1]=a[b+4>>2];g=k+16|0;p=(g|0)>>2;d=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])+d;f[b>>3]=d;a[p]=a[b>>2];a[p+1]=a[b+4>>2];d=(k+24|0)>>2;v=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3])+v;f[b>>3]=v;a[d]=a[b>>2];a[d+1]=a[b+4>>2];i&&0==(a[c+148>>2]&4|0)&&Mc(c,m,a[j+42],a[j+46],a[j+38]);m=Ho(c,s);ai(c,s);0!=(m&1|0)&&Sb(c,vf(s,5332120));d=a[a[s+24>>2]>>2];m=77==n[d]<<24>>24?0==($(d,5340380)|0)?m|2:m:m;0==(m&998|0)?of(c,k,m&1):(d=r>>2,a[d]=a[e],a[d+1]=a[e+1],a[d+2]=a[e+2],a[d+3]=a[e+3],d=r+32|0,e=d>>2,g>>=2,a[e]=a[g],a[e+1]=a[g+1],a[e+2]=a[g+2],a[e+3]=a[g+3],e=d|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),g=r+16|0,f[b>>3]=e,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],e=r+8|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),g=r+24|0,f[b>>3]=e,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],e=r|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),g=r+48|0,f[b>>3]=e,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],e=r+40|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),g=r+56|0,f[b>>3]=e,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],Rf(c,vf(s,5332120),ck(s),r|0,4,m,m&1));dk(c,s,x);i&&(0!=(a[c+148>>2]&4|0)&&Mc(c,a[q>>2],a[j+42],a[j+46],a[j+38]),de(c));h=k}function Ho(b,c){var g=h;h=h+4|0;var e=ek(c,g);0!=(e|0)&&Dd(a[b+16>>2],a[b+60>>2],e);e=a[1345351];if(0!=(e|0)){var d=c|0,f=tb(d,a[e+8>>2]);0!=(f|0)&&0!=n[f]<<24>>24&&jj(b,lc(d,e,1,0))}h=g;return a[g>>2]}function ai(b,c){var g=na(c|0,a[1345369],5338228);0==n[g]<<24>>24?eb(b,5374748):eb(b,g)}function bi(c,s,g,e,d){var p=c|0;f[b>>3]=s+e;a[p>>2]=a[b>>2];a[p+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=g+d;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function dk(c,s,g){var e,d,p,j,k,r,q,m,i,x,v=h;h=h+96|0;var t=v+32;i=v+48;var y=v+64,z=v+80,B=g+52|0;x=a[B>>2];0==(x|0)?(B=s+32|0,i=s+40|0):(j=g+16|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),k=g+24|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),r=g+32|0,q=g+40|0,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),m=t|0,f[b>>3]=.5*(j+r),a[m>>2]=a[b>>2],a[m+4>>2]=a[b+4>>2],j=t+8|0,f[b>>3]=.5*(k+q),a[j>>2]=a[b>>2],a[j+4>>2]=a[b+4>>2],j=t|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),t=t+8|0,r=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),k=s+32|0,t=s+40|0,bi(i,j,r,(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3])),x=(x+56|0)>>2,i>>=2,a[x]=a[i],a[x+1]=a[i+1],a[x+2]=a[i+2],a[x+3]=a[i+3],Te(c,10,a[B>>2]),ai(c,s),B=k,i=t);B=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]);i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);x=g+48|0;if(0<(a[x>>2]|0)){t=g+64|0;p=v+16|0;var F=g+56|0;m=p>>2;q=(v|0)>>2;r=(v+24|0)>>2;k=(v+8|0)>>2;var D=v|0;j=v>>2;var g=y>>2,S=p|0;p=z>>2;for(var A=v+16|0,C=0;;){if(0<(C|0)){d=((C<<2)+a[F>>2]|0)>>2;e=a[d];if(0==n[t]<<24>>24){e=(e+32|0)>>2;a[m]=a[e];a[m+1]=a[e+1];a[m+2]=a[e+2];a[m+3]=a[e+3];d=a[d]+16|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);f[b>>3]=d;a[q]=a[b>>2];a[q+1]=a[b+4>>2];var I=(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3]);f[b>>3]=I;a[k]=a[b>>2];a[k+1]=a[b+4>>2];e=I;var Z=(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3])}else{e=(e+16|0)>>2,a[j]=a[e],a[j+1]=a[e+1],a[j+2]=a[e+2],a[j+3]=a[e+3],Z=(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3]),f[b>>3]=Z,a[A>>2]=a[b>>2],a[A+4>>2]=a[b+4>>2],d=a[d]+40|0,I=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),f[b>>3]=I,a[r]=a[b>>2],a[r+1]=a[b+4>>2],d=Z,e=(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3])}bi(y,d,e,B,i);a[j]=a[g];a[j+1]=a[g+1];a[j+2]=a[g+2];a[j+3]=a[g+3];bi(z,Z,I,B,i);a[m]=a[p];a[m+1]=a[p+1];a[m+2]=a[p+2];a[m+3]=a[p+3];td(c,D,2)}dk(c,s,a[a[F>>2]+(C<<2)>>2]);C=C+1|0;if((C|0)>=(a[x>>2]|0)){break}}}h=v}function ck(b){b=na(b|0,a[1345369],5338228);return 0==n[b]<<24>>24?5374748:b}function vf(b,c){var g=b|0,e=na(g,a[1345365],5338228);return 0==n[e]<<24>>24?(g=na(g,a[1345369],5338228),0==n[g]<<24>>24?c:g):e}function ek(b,c){var g=0,e=na(b|0,a[1345345],5338228);a:do{if(0==n[e]<<24>>24){var d=0,f=0}else{pf(e);for(var j=5249092,k=0;;){for(var h=j;;){var q=a[h>>2];if(0==(q|0)){d=k;f=5249092;break a}var m=n[q];if(114==m<<24>>24){if(0==($(q,5337692)|0)){var i=h,g=1138;break}}else{if(105==m<<24>>24){if(0==($(q,5365092)|0)){g=1142;break}}else{if(102==m<<24>>24){if(0==($(q,5362648)|0)){g=1136;break}}else{if(100==m<<24>>24&&0==($(q,5337400)|0)){var x=h,g=1140;break}}}}h=h+4|0}if(1138==g){for(;!(g=0,j=i+4|0,q=a[j>>2],a[i>>2]=q,0==(q|0));){i=j,g=1138}j=h;k|=2}else{if(1142==g){g=0,j=h+4|0,k|=16}else{if(1136==g){g=0,j=h+4|0,k|=1}else{if(1140==g){for(;!(g=0,j=x+4|0,q=a[j>>2],a[x>>2]=q,0==(q|0));){x=j,g=1140}j=h;k|=4}}}}}}}while(0);g=a[a[b+24>>2]+8>>2];if(0==(g|0)){return a[c>>2]=d,f}d|=a[g+36>>2];a[c>>2]=d;return f}function Io(b,c){var g=0,e=a[b+60>>2];if(0!=(e|0)&&n[e]<<24>>24==n[c]<<24>>24&&0==($(e,c)|0)){var d;return b}for(var e=b+56|0,f=a[b+48>>2],j=0;;){if((j|0)>=(f|0)){d=0;g=1156;break}var k=Io(a[a[e>>2]+(j<<2)>>2],c);if(0==(k|0)){j=j+1|0}else{d=k;g=1158;break}}if(1158==g||1156==g){return d}}function fk(b){var c=b+48|0,g=b+56|0;a:do{if(0<(a[c>>2]|0)){for(var e=0;;){if(fk(a[a[g>>2]+(e<<2)>>2]),e=e+1|0,(e|0)>=(a[c>>2]|0)){break a}}}}while(0);E(a[b+60>>2]);tf(a[b+52>>2]);E(a[g>>2]);E(b)}function Jo(c,s,g){var e=h;h=h+16|0;c=a[c>>2];Wf(e,s,g,90*(a[a[c+20>>2]+152>>2]&3)&-1);s=e|0;s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]);g=e+8|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);if((c|0)!=(a[1312236]|0)){var d=a[c+28>>2],p=(a[d+4>>2]<<1)-2|0,d=((0>(p|0)?1:p|1)<<4)+a[d+40>>2]|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);f[b>>3]=d;a[1312234]=a[b>>2];a[1312235]=a[b+4>>2];a[1312236]=c}if(Math.abs(s)>(a[b>>2]=a[1312234],a[b+4>>2]=a[1312235],f[b>>3])||Math.abs(g)>(a[b>>2]=a[1312234],a[b+4>>2]=a[1312235],f[b>>3])){return h=e,0}c=If(s,g)<=(a[b>>2]=a[1312234],a[b+4>>2]=a[1312235],f[b>>3])&1;h=e;return c}function Ko(c,s){var g,e,d=0,p=h;h=h+4|0;var j=c+16|0,k=a[j>>2];e=k>>2;var k=k+148|0,r=a[k>>2];if(0==(r|0)){if(0==(a[e+50]&1|0)){var q=0}else{d=1178}}else{d=1178}1178==d&&(0==(a[c+148>>2]&4|0)&&Mc(c,r,a[e+42],a[e+46],a[e+38]),q=1);g=a[s+28>>2]>>2;var r=a[g+10],m=a[g+2];g=a[g+1];if((a[1312237]|0)<(m|0)){var i=m+2|0;a[1312237]=i;var x=a[1312238],i=0==(x|0)?Za(i<<4):Oa(x,i<<4);a[1312238]=i}ek(s,p);j=a[j>>2];i=a[c+60>>2];0==(a[p>>2]&16|0)?Dd(j,i,5248928):Dd(j,i,5248924);j=ca[s+133|0];0==(j&1|0)?0!=(j&2|0)?(j=s|0,eb(c,na(j,0,5336384)),j=na(j,0,5336016),Sb(c,j)):0!=(j&8|0)?(j=s|0,eb(c,na(j,0,5335712)),j=na(j,0,5335408),Sb(c,j)):0==(j&4|0)?(j=vf(s,5374748),Sb(c,j),ai(c,s)):(j=s|0,eb(c,na(j,0,5335120)),j=na(j,0,5334856),Sb(c,j)):(j=s|0,eb(c,na(j,0,5336884)),j=na(j,0,5336656),Sb(c,j));if(0==(g|0)){if(0==n[j]<<24>>24){var v=1}else{eb(c,j),v=1}d=1201}else{0<(g|0)&&(v=g,d=1201)}a:do{if(1201==d){g=0<(m|0);for(var j=s+32|0,i=s+40|0,x=0,t=1;;){b:do{if(g){for(var y=Math.a(x,m),z=a[1312238],B=0;;){var F=B+y|0,D=(F<<4)+r|0,D=(a[b>>2]=a[D>>2],a[b+4>>2]=a[D+4>>2],f[b>>3]),F=(F<<4)+r+8|0,F=(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]),D=D+(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),S=(B<<4)+z|0;f[b>>3]=D;a[S>>2]=a[b>>2];a[S+4>>2]=a[b+4>>2];D=F+(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);F=(B<<4)+z+8|0;f[b>>3]=D;a[F>>2]=a[b>>2];a[F+4>>2]=a[b+4>>2];B=B+1|0;if((B|0)==(m|0)){var A=z;break b}}}else{A=a[1312238]}}while(0);Kg(c,A,t);x=x+1|0;if((x|0)==(v|0)){break a}else{t=0}}}}while(0);q&&(0!=(a[c+148>>2]&4|0)&&Mc(c,a[k>>2],a[e+42],a[e+46],a[e+38]),de(c));h=p}function Lo(c,s,g){var e,d=0,p=h;h=h+16|0;e=a[c+4>>2];var c=a[c>>2],j=c+20|0;Wf(p,s,g,90*(a[a[j>>2]+152>>2]&3)&-1);s=p|0;s=(a[b>>2]=a[s>>2],a[b+4>>2]=a[s+4>>2],f[b>>3]);g=p+8|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);if(0!=(e|0)){var k=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),d=e+24|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);k>s?d=0:(k=e+8|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),c=e+16|0,d=s>(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])|k>g?0:g<=d);h=p;return d&1}if((c|0)==(a[1312217]|0)){c=(a[b>>2]=a[1312214],a[b+4>>2]=a[1312215],f[b>>3]),e=(a[b>>2]=a[1312212],a[b+4>>2]=a[1312213],f[b>>3])}else{e=a[c+28>>2]>>2;a[1312210]=a[e+10];var r=a[e+2];a[1312211]=r;var q=0==(a[a[j>>2]+152>>2]&1|0),j=c+104|0,m=c+112|0,m=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])+(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),j=c+96|0,i=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),j=q?i:m,i=q?m:i,q=c+48|0,q=72*(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),m=0>q,i=((m?q-.5:q+.5)&-1|0)/(0==i?1:i);f[b>>3]=i;a[1312214]=a[b>>2];a[1312215]=a[b+4>>2];var n=c+56|0,n=72*(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),v=0>n,j=((v?n-.5:n+.5)&-1|0)/(0==j?1:j);f[b>>3]=j;a[1312212]=a[b>>2];a[1312213]=a[b+4>>2];f[b>>3]=.5*((m?q-.5:q+.5)&-1|0);a[1312221]=a[b>>2];a[1312222]=a[b+4>>2];f[b>>3]=.5*((v?n-.5:n+.5)&-1|0);a[1312219]=a[b>>2];a[1312220]=a[b+4>>2];e=Math.a(a[e+1]-1|0,r);a[1312216]=0>(e|0)?0:e;a[1312217]=c;c=i;e=j}s*=c;g*=e;if(Math.abs(s)>(a[b>>2]=a[1312221],a[b+4>>2]=a[1312222],f[b>>3])){return h=p,0}c=Math.abs(g);e=(a[b>>2]=a[1312219],a[b+4>>2]=a[1312220],f[b>>3]);if(c>e){return h=p,0}c=a[1312211];if(3>(c|0)){return d=1>If(s/(a[b>>2]=a[1312221],a[b+4>>2]=a[1312222],f[b>>3]),g/e)&1,h=p,d}i=(a[1312218]|0)%(c|0);q=(i+1|0)%(c|0);e=a[1312216];var j=e+i|0,r=a[1312210],m=(j<<4)+r|0,m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),j=(j<<4)+r+8|0,n=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),j=e+q|0,v=(j<<4)+r|0,v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),j=(j<<4)+r+8|0,t=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);if(0==(ci(s,g,0,0,m,n,v,t)|0)){return h=p,0}if(j=0!=(ci(s,g,m,n,v,t,0,0)|0)){if(0==(ci(s,g,v,t,0,0,m,n)|0)){m=1}else{return h=p,1}}else{m=1}for(;;){if((m|0)>=(c|0)){d=1247;break}j?(k=q,q=(q+1|0)%(c|0)):(k=(i-1+c|0)%(c|0),q=i);var t=e+k|0,n=e+q|0,v=(t<<4)+r|0,v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),t=(t<<4)+r+8|0,t=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),y=(n<<4)+r|0,n=(n<<4)+r+8|0;if(0==(ci(s,g,0,0,v,t,(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]))|0)){d=1246;break}else{m=m+1|0,i=k}}if(1246==d){return a[1312218]=k,h=p,0}if(1247==d){return a[1312218]=i,h=p,1}}function ci(a,b,g,e,c,d,f,k){k=-(k-d);f-=c;c=k*c+f*d;return(0<=k*a+f*b-c^0<=k*g+f*e-c)&1^1}function Mo(c,s){var g,e,d,p,j=0,k=a[c+16>>2];p=k>>2;var k=k+148|0,h=a[k>>2];if(0==(h|0)){if(0==(a[p+50]&1|0)){var q=0}else{j=1260}}else{j=1260}1260==j&&(0==(a[c+148>>2]&4|0)&&Mc(c,h,a[p+42],a[p+46],a[p+38]),q=1);d=a[s+28>>2]>>2;var h=a[d+10],m=a[d+2],i=a[d+1];if((a[1312223]|0)<(m|0)){d=m+5|0;a[1312223]=d;var x=a[1312224];d=0==(x|0)?Za(d<<4):Oa(x,d<<4);a[1312224]=d}d=s+120|0;x=s+32|0;e=(a[d>>2]+56|0)>>2;g=x>>2;a[e]=a[g];a[e+1]=a[g+1];a[e+2]=a[g+2];a[e+3]=a[g+3];g=s+104|0;e=s+112|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])+(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);e=s+48|0;e=72*(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);g/=(0>e?e-.5:e+.5)&-1|0;e=s+96|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);var v=s+56|0,v=72*(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]);e/=(0>v?v-.5:v+.5)&-1|0;var v=Ho(c,s),t=ca[s+133|0];0==(t&1|0)?0!=(t&2|0)?(t=s|0,eb(c,na(t,0,5336384)),Sb(c,na(t,0,5336016)),t=1):0!=(t&8|0)?(t=s|0,eb(c,na(t,0,5335712)),Sb(c,na(t,0,5335408)),t=1):0!=(t&4|0)?(t=s|0,eb(c,na(t,0,5335120)),Sb(c,na(t,0,5334856)),t=1):(0==(v&1|0)?t=0:(Sb(c,vf(s,5332120)),t=1),ai(c,s)):(t=s|0,eb(c,na(t,0,5336884)),Sb(c,na(t,0,5336656)),t=1);var y=s+24|0,z=a[y>>2],B=n[z+12|0];if(0==B<<24>>24){var F=0,j=1288}else{if(j=a[z>>2],99==n[j]<<24>>24){F=0!=($(j,5340528)|0),j=1288}else{var D=j,S=1,A=0==t<<24>>24,C=i,j=1296}}if(1288==j){var I=0==t<<24>>24;0!=(i|0)|I|F?y=I:(F=vf(s,5332120),0==n[F]<<24>>24?(i=1,F=y=0):(eb(c,F),B=a[y>>2],i=1,F=y=0,z=B,B=n[B+12|0]));if(0==B<<24>>24){if(B=U(s|0,5334020),0==(B|0)){var Z=t,T=i}else{D=B,S=F,A=y,C=i,j=1296}}else{D=a[z>>2],D=99!=n[D]<<24>>24?D:0!=($(D,5340528)|0)?D:U(s|0,5348352),S=F,A=y,C=i,j=1296}}if(1296==j){a:do{if(0<(m|0)){Z=x|0;T=a[1312224];F=s+40|0;for(i=0;;){if(j=(i<<4)+h|0,B=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),j=(i<<4)+h+8|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),B=B*g+(a[b>>2]=a[Z>>2],a[b+4>>2]=a[Z+4>>2],f[b>>3]),z=(i<<4)+T|0,f[b>>3]=B,a[z>>2]=a[b>>2],a[z+4>>2]=a[b+4>>2],j=j*e+(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]),B=(i<<4)+T+8|0,f[b>>3]=j,a[B>>2]=a[b>>2],a[B+4>>2]=a[b+4>>2],i=i+1|0,(i|0)==(m|0)){break a}}}}while(0);Z=t&255;A|S||(3>(m|0)?(Kg(c,a[1312224],t),0!=(v&4|0)&&No(c,s)):(T=a[1312224],0==(v&6|0)?tc(c,T,m,t):Rf(c,vf(s,5332120),ck(s),T,m,v,Z)));Mj(c,D,a[1312224],m,t,$b(s|0,a[1345358],5333780));Z=0;T=C}a:do{if(0<(T|0)){D=0<(m|0);C=3>(m|0);S=0==(v&4|0);A=0==(v&998|0);F=x|0;t=s+40|0;i=0;for(j=Z;;){b:do{if(D){B=Math.a(i,m);z=a[1312224];for(y=0;;){var K=y+B|0,I=(K<<4)+h|0,I=(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3]),K=(K<<4)+h+8|0,K=(a[b>>2]=a[K>>2],a[b+4>>2]=a[K+4>>2],f[b>>3]),I=I*g+(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]),M=(y<<4)+z|0;f[b>>3]=I;a[M>>2]=a[b>>2];a[M+4>>2]=a[b+4>>2];I=K*e+(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]);K=(y<<4)+z+8|0;f[b>>3]=I;a[K>>2]=a[b>>2];a[K+4>>2]=a[b+4>>2];y=y+1|0;if((y|0)==(m|0)){var L=z;break b}}}else{L=a[1312224]}}while(0);C?(Kg(c,L,j),S||No(c,s)):A?tc(c,L,m,j):Rf(c,vf(s,5332120),ck(s),L,m,v,j&255);i=i+1|0;if((i|0)==(T|0)){break a}else{j=0}}}}while(0);Te(c,10,a[d>>2]);q&&(0!=(a[c+148>>2]&4|0)&&Mc(c,a[k>>2],a[p+42],a[p+46],a[p+38]),de(c))}function No(c,s){var g,e,d=h;h=h+48|0;g=d+32;var p=s+96|0,p=.375*(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=s+112|0,k=.6614*(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),j=d|0;e=s+32|0;var r=s+40|0;bi(g,k,p,(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]));e=d>>2;g>>=2;a[e]=a[g];a[e+1]=a[g+1];a[e+2]=a[g+2];a[e+3]=a[g+3];e=(d+8|0)>>2;r=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);g=(d+24|0)>>2;f[b>>3]=r;a[g]=a[b>>2];a[g+1]=a[b+4>>2];r=d|0;k=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3])-2*k;r=d+16|0;f[b>>3]=k;a[r>>2]=a[b>>2];a[r+4>>2]=a[b+4>>2];td(c,j,2);p=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])-2*p;f[b>>3]=p;a[e]=a[b>>2];a[e+1]=a[b+4>>2];f[b>>3]=p;a[g]=a[b>>2];a[g+1]=a[b+4>>2];td(c,j,2);h=d}function uo(a,b){var g=a/b&-1;return(((g|0)*b+1e-5<a&1)+g|0)*b}function $h(c,s,g,e){var d,p=0,j=da(68),k=a[c+120>>2],h=0,q=a[1311664],m=1;a:for(;;){var i=n[q];do{if(0==i<<24>>24){var x=m;break a}else{if(92==i<<24>>24){var v=q+1|0,t=n[v];if(92==t<<24>>24|123==t<<24>>24|125==t<<24>>24|124==t<<24>>24){var y=h,z=v,B=m}else{var F=v,D=t,p=1332}}else{F=q,D=i,p=1332}}}while(0);if(1332==p){p=0;if(123==D<<24>>24){var S=h+1|0,A=m}else{124==D<<24>>24?(S=h,A=(0==(h|0)&1)+m|0):(S=125==D<<24>>24?h-1|0:h,A=m)}if(0>(S|0)){x=A;break}else{y=S,z=F,B=A}}h=y;q=z+1|0;m=B}d=(j+56|0)>>2;a[d]=da(x<<2);n[j+64|0]=s&255;var C=0==(s|0)&1,I=k+82|0,Z=e+1|0,T=0==(g|0),K=c|0,M=k+16|0,L=k+4|0,E=k+8|0,yb=0,H=0,R=0,J=0,G=0,Rb=e,P=0,ea=e,wa=0;a:for(;;){for(var Fb=yb,V=H,W=J,X=G,ba=Rb,ma=P,ib=ea,N=wa;;){var Q=Fb,O=V,ga=W,U=ba,aa=ma,ua=ib,Da=N,Ja=0;b:for(;;){var Ab=Q,ra=O,$=ga,ya=U,ja=aa,la=ua,va=Da;c:for(;;){var oa=Ab,ka=$,Ea=ja,Ka=va;d:for(;;){for(var Na=oa,Ba=ka;;){if(R){p=1405;break a}var Wa=a[1311664],ca=n[Wa],ia=ca<<24>>24;if(60==(ia|0)){break}else{if(62==(ia|0)){p=1350;break d}else{if(125==(ia|0)|124==(ia|0)|0==(ia|0)){break b}else{if(92==(ia|0)){p=1379;break d}else{if(123!=(ia|0)){var Ra=ra,bb=Ba,Xa=ya,Sa=Wa;break d}}}}}var ha=Wa+1|0;a[1311664]=ha;if(0!=(Ba|0)){p=1359;break a}if(0==n[ha]<<24>>24){p=1359;break a}var Va=$h(c,C,0,e);a[a[d]+(Na<<2)>>2]=Va;if(0==(Va|0)){p=1361;break a}else{Na=Na+1|0,Ba=4}}if(0!=(Ba&6|0)){p=1347;break a}if(0!=n[I]<<24>>24){Ra=ra;bb=Ba;Xa=ya;Sa=Wa;break}a[1311664]=Wa+1|0;oa=Na;ka=Ba|18;Ka=Ea=e}d:do{if(1350==p){if(p=0,0==n[I]<<24>>24){break c}else{Ra=ra,bb=Ba,Xa=ya,Sa=Wa}}else{if(1379==p){var p=0,Ta=Wa+1|0,Aa=n[Ta];if(123==Aa<<24>>24|125==Aa<<24>>24|124==Aa<<24>>24|60==Aa<<24>>24|62==Aa<<24>>24){a[1311664]=Ta,Ra=ra,bb=Ba,Xa=ya}else{if(32==Aa<<24>>24){p=1381}else{if(0==Aa<<24>>24){Ra=ra;bb=Ba;Xa=ya;Sa=Wa;break}}do{if(1381==p&&(p=0,0==n[I]<<24>>24)){a[1311664]=Ta;Ra=1;bb=Ba;Xa=ya;Sa=Ta;break d}}while(0);n[ya]=92;a[1311664]=Ta;Ra=ra;bb=Ba|9;Xa=ya+1|0}Sa=Ta}}}while(0);if(0!=(bb&4|0)&&32!=n[Sa]<<24>>24){p=1386;break a}var fb=0==(bb&24|0)?32==n[Sa]<<24>>24?bb:bb|9:bb;if(0==(fb&8|0)){if(0==(fb&16|0)){var Ca=Xa,Ya=Ea,$a=la,La=Ka}else{var pa=n[Sa],Ga=0==(Ra|0);if(32==pa<<24>>24&Ga){if((Ea|0)==(e|0)){var Fa=Ea}else{32==n[Ea-1|0]<<24>>24?Fa=Ea:p=1400}}else{p=1400}1400==p&&(p=0,n[Ea]=pa,Fa=Ea+1|0);Ga?(Ca=Xa,Ya=Fa,$a=la,La=Ka):(Ca=Xa,Ya=Fa,$a=la,La=Fa-1|0)}}else{var sa=n[Sa],nb=0==(Ra|0);if(32==sa<<24>>24&nb){if(32!=n[Xa-1|0]<<24>>24){p=1393}else{if(0==n[I]<<24>>24){var jb=Xa}else{p=1393}}}else{p=1393}1393==p&&(p=0,n[Xa]=sa,jb=Xa+1|0);nb?(Ca=jb,Ya=Ea,$a=la):(Ca=jb,Ya=Ea,$a=jb-1|0);La=Ka}var cb=Sa+1|0;a[1311664]=cb;var fa=n[cb];if(0>fa<<24>>24){for(var kb=Ca,Kb=cb,Ma=fa;;){var qa=Kb+1|0;a[1311664]=qa;var lb=kb+1|0;n[kb]=Ma;var rb=n[qa];if(0>rb<<24>>24){kb=lb,Kb=qa,Ma=rb}else{Ab=Na;ra=Ra;$=fb;ya=lb;ja=Ya;la=$a;va=La;continue c}}}else{Ab=Na,ra=Ra,$=fb,ya=Ca,ja=Ya,la=$a,va=La}}if(0==(Ba&16|0)){p=1352;break a}if(Ea>>>0>Z>>>0){var ab=Ea-1|0,db=(ab|0)==(Ka|0)?Ea:32==n[ab]<<24>>24?ab:Ea}else{db=Ea}n[db]=0;var ob=Hb(e);a[1311664]=a[1311664]+1|0;Q=Na;O=ra;ga=Ba&-17;U=ya;aa=db;ua=la;Da=Ka;Ja=ob}if(0==ca<<24>>24&T){p=1364;break a}if(0!=(Ba&16|0)){p=1364;break a}if(0==(Ba&4|0)){var pb=da(68);a[a[d]+(Na<<2)>>2]=pb;var ub=Na+1|0,gb=pb}else{ub=Na,gb=X}0!=(Ja|0)&&(a[gb+60>>2]=Ja);if(0==(Ba&5|0)){n[ya]=32;var sb=Ba|1,Ia=ya+1|0}else{sb=Ba,Ia=ya}if(0==(sb&1|0)){var vb=Ia,Ua=la}else{if(Ia>>>0>Z>>>0){var xa=Ia-1|0,na=(xa|0)==(la|0)?Ia:32==n[xa]<<24>>24?xa:Ia}else{na=Ia}n[na]=0;var qb=Hb(e);a[gb+52>>2]=we(K,qb,0!=n[I]<<24>>24?2:0,(a[b>>2]=a[M>>2],a[b+4>>2]=a[M+4>>2],f[b>>3]),a[L>>2],a[E>>2]);n[gb+64|0]=1;Ua=vb=e}var Bb=a[1311664],sc=n[Bb];if(0==sc<<24>>24){yb=ub;H=ra;R=1;J=sb;G=gb;Rb=vb;P=Ea;ea=Ua;wa=Ka;continue a}else{if(125==sc<<24>>24){p=1377;break a}}a[1311664]=Bb+1|0;Fb=ub;V=ra;W=0;X=gb;ba=vb;ma=Ea;ib=Ua;N=Ka}}if(1347==p){$f(j,Ja);var xb=0;return xb}if(1352==p||1359==p||1361==p||1364==p){return $f(j,Ja),xb=0}if(1377==p){return a[1311664]=Bb+1|0,a[j+48>>2]=ub,xb=j}if(1386==p){return $f(j,Ja),xb=0}if(1405==p){return a[j+48>>2]=Na,xb=j}}function $j(c,s,g){var e=h;h=h+32|0;var d=e+8,p=e+16,j=a[g+52>>2];a:do{if(0==(j|0)){var k=g+48|0;if(0<(a[k>>2]|0)){for(var r=g+56|0,q=p|0,m=p+8|0,w=g+64|0,x=0,v=0,t=0;;){$j(p,s,a[a[r>>2]+(t<<2)>>2]);var y=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),z=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]);0==n[w]<<24>>24?(v=v>y?v:y,x+=z):(v+=y,x=x>z?x:z);t=t+1|0;if((t|0)>=(a[k>>2]|0)){B=v;F=x;break a}}}else{var B=0,F=0}}else{B=j+24|0,k=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),B=j+32|0,F=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),0<k|0<F?(B=U(s|0,5332848),0==(B|0)?(B=k+16,F+=8):(B=gd(B,5332588,(i=h,h=h+8|0,a[i>>2]=e,a[i+4>>2]=d,i)),0<(B|0)?(r=72*(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),k+=((0>r?r-.5:r+.5)&-1)<<1|0,r=72*(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),r=(q=0<=r)?r+.5:r-.5,B=k,F+=(r&-1)<<1|0):(B=k+16,F+=8))):B=k}}while(0);s=g|0;f[b>>3]=B;a[s>>2]=a[b>>2];a[s+4>>2]=a[b+4>>2];g=g+8|0;f[b>>3]=F;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];g=c|0;f[b>>3]=B;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=F;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];h=e}function ak(c,d,g,e){var l,p,j=h;h=h+32|0;var k=j+16;p=(c|0)>>2;var r=d-(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]);l=(c+8|0)>>2;var q=g-(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]);f[b>>3]=d;a[p]=a[b>>2];a[p+1]=a[b+4>>2];f[b>>3]=g;a[l]=a[b>>2];a[l+1]=a[b+4>>2];l=c+52|0;p=a[l>>2];if(0!=(p|0)&0==(e|0)){p=(p+40|0)>>2;var m=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])+r;f[b>>3]=m;a[p]=a[b>>2];a[p+1]=a[b+4>>2];l=(a[l>>2]+48|0)>>2;p=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3])+q;f[b>>3]=p;a[l]=a[b>>2];a[l+1]=a[b+4>>2]}l=c+48|0;m=a[l>>2];if(0!=(m|0)){p=c+64|0;var i=n[p],r=(0==i<<24>>24?q:r)/(m|0);if(0<(m|0)){for(var c=c+56|0,q=k|0,m=k+8|0,x=j|0,v=j+8|0,t=0,y=i;;){var i=a[a[c>>2]+(t<<2)>>2],z=t+1|0,t=(z*r&-1)-(t*r&-1)|0;0==y<<24>>24?(y=i+8|0,Xf(k,d,(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3])+(t|0)),y=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),t=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])):(y=i|0,Xf(j,(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3])+(t|0),g),y=(a[b>>2]=a[x>>2],a[b+4>>2]=a[x+4>>2],f[b>>3]),t=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]));ak(i,y,t,e);if((z|0)>=(a[l>>2]|0)){break}t=z;y=n[p]}}}h=j}function bk(c,d,g,e){var l,p,j,k=h;h=h+32|0;l=k+16;n[c+65|0]=e&255;p=c+8|0;Xf(k,d,g-(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]));j=(c+16|0)>>2;p=k>>2;a[j]=a[p];a[j+1]=a[p+1];a[j+2]=a[p+2];a[j+3]=a[p+3];p=c|0;Xf(l,(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])+d,g);p=(c+32|0)>>2;l>>=2;a[p]=a[l];a[p+1]=a[l+1];a[p+2]=a[l+2];a[p+3]=a[l+3];l=a[c+48>>2];p=l-1|0;if(0<=(p|0)){j=0==(e|0);for(var r=c+56|0,c=c+64|0,q=d,d=0;;){if(j){var m=0}else{var m=0==(d|0),i=(d|0)==(p|0),m=0==n[c]<<24>>24?m?i?15:14:i?11:10:m?i?15:13:i?7:5}bk(a[a[r>>2]+(d<<2)>>2],q,g,m&e);m=a[a[r>>2]+(d<<2)>>2];0==n[c]<<24>>24?(m=m+8|0,g-=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])):(m|=0,q+=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]));d=d+1|0;if((d|0)==(l|0)){break}}}h=k}function $f(a,b){fk(a);0!=(b|0)&&E(b)}function Ag(c,d,g,e){var l,p,j,k=h;h=h+96|0;var r=k+64;j=r>>2;var q=k+72;p=q>>2;var m=k+80;l=k|0;if(0==e<<24>>24){var e=r,i=l,n=0,r=g+48|0;l=g+56|0}else{e=q,q=r,i=0,n=l,r=g|0,l=g+8|0}var v=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),t=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);f[b>>3]=0;a[j]=a[b>>2];a[j+1]=a[b+4>>2];f[b>>3]=1;a[p]=a[b>>2];a[p+1]=a[b+4>>2];var y=m|0,z=m+8|0,B=k|0,F=k+8|0,D=k+16|0,S=D|0,A=k+24|0,r=k+32|0,C=r|0,I=k+40|0;l=k+48|0;for(var Z=l|0,T=k+56|0,K=0,M=1,L=0;;){var E,yb,H,R,G,P,Rb,N,ea=.5*(M+L);zc(m,g,ea,i,n);M=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]);L=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3]);if(0==J[d](c,M,L)<<24>>24){var wa=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),Fb=(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]),V=(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3]),W=(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]),X=(a[b>>2]=a[C>>2],a[b+4>>2]=a[C+4>>2],f[b>>3]),ba=(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3]),ma=(a[b>>2]=a[Z>>2],a[b+4>>2]=a[Z+4>>2],f[b>>3]),ib=(a[b>>2]=a[T>>2],a[b+4>>2]=a[T+4>>2],f[b>>3]);f[b>>3]=ea;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];ea=1}else{f[b>>3]=ea,a[q>>2]=a[b>>2],a[q+4>>2]=a[b+4>>2],ea=K,wa=N,Fb=Rb,V=P,W=G,X=R,ba=H,ma=yb,ib=E}v-=M;if(.5>=(0>v?-v:v)){if(v=t-L,.5>=(0>v?-v:v)){break}}K=ea;v=M;t=L;M=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]);L=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3]);N=wa;Rb=Fb;P=V;G=W;R=X;H=ba;yb=ma;E=ib}0==ea<<24>>24?(d=g>>2,c=k>>2,a[d]=a[c],a[d+1]=a[c+1],a[d+2]=a[c+2],a[d+3]=a[c+3],c=(g+16|0)>>2,d=D>>2,a[c]=a[d],a[c+1]=a[d+1],a[c+2]=a[d+2],a[c+3]=a[d+3],c=(g+32|0)>>2,d=r>>2,a[c]=a[d],a[c+1]=a[d+1],a[c+2]=a[d+2],a[c+3]=a[d+3],g=(g+48|0)>>2,l>>=2,a[g]=a[l],a[g+1]=a[l+1],a[g+2]=a[l+2],a[g+3]=a[l+3]):(l=g|0,f[b>>3]=wa,a[l>>2]=a[b>>2],a[l+4>>2]=a[b+4>>2],l=g+8|0,f[b>>3]=Fb,a[l>>2]=a[b>>2],a[l+4>>2]=a[b+4>>2],l=g+16|0,f[b>>3]=V,a[l>>2]=a[b>>2],a[l+4>>2]=a[b+4>>2],l=g+24|0,f[b>>3]=W,a[l>>2]=a[b>>2],a[l+4>>2]=a[b+4>>2],l=g+32|0,f[b>>3]=X,a[l>>2]=a[b>>2],a[l+4>>2]=a[b+4>>2],l=g+40|0,f[b>>3]=ba,a[l>>2]=a[b>>2],a[l+4>>2]=a[b+4>>2],l=g+48|0,f[b>>3]=ma,a[l>>2]=a[b>>2],a[l+4>>2]=a[b+4>>2],g=g+56|0,f[b>>3]=ib,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2]);h=k}function di(c,d,g,e){var l,p,j,k,r,q,m,i,n,v,t,y,z,B,F,D,S,A,C=h;h=h+64|0;A=(d+112|0)>>2;var I=(a[b>>2]=a[A],a[b+4>>2]=a[A+1],f[b>>3]);S=(d+32|0)>>2;p=(a[b>>2]=a[S],a[b+4>>2]=a[S+1],f[b>>3]);D=(d+40|0)>>2;l=(a[b>>2]=a[D],a[b+4>>2]=a[D+1],f[b>>3]);F=(g|0)>>2;j=(a[b>>2]=a[F],a[b+4>>2]=a[F+1],f[b>>3])-p;B=(C|0)>>2;f[b>>3]=j;a[B]=a[b>>2];a[B+1]=a[b+4>>2];z=(g+8|0)>>2;j=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3])-l;y=(C+8|0)>>2;f[b>>3]=j;a[y]=a[b>>2];a[y+1]=a[b+4>>2];t=(g+16|0)>>2;j=(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3])-p;v=(C+16|0)>>2;f[b>>3]=j;a[v]=a[b>>2];a[v+1]=a[b+4>>2];n=(g+24|0)>>2;j=(a[b>>2]=a[n],a[b+4>>2]=a[n+1],f[b>>3])-l;i=(C+24|0)>>2;f[b>>3]=j;a[i]=a[b>>2];a[i+1]=a[b+4>>2];m=(g+32|0)>>2;j=(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3])-p;q=(C+32|0)>>2;f[b>>3]=j;a[q]=a[b>>2];a[q+1]=a[b+4>>2];r=(g+40|0)>>2;j=(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3])-l;k=(C+40|0)>>2;f[b>>3]=j;a[k]=a[b>>2];a[k+1]=a[b+4>>2];j=(g+48|0)>>2;var Z=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3])-p;p=(C+48|0)>>2;f[b>>3]=Z;a[p]=a[b>>2];a[p+1]=a[b+4>>2];g=(g+56|0)>>2;Z=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])-l;l=(C+56|0)>>2;f[b>>3]=Z;a[l]=a[b>>2];a[l+1]=a[b+4>>2];I&=-1;Ag(c,a[a[a[d+24>>2]+4>>2]+12>>2],C|0,e);c=(a[b>>2]=a[B],a[b+4>>2]=a[B+1],f[b>>3])+(a[b>>2]=a[S],a[b+4>>2]=a[S+1],f[b>>3]);f[b>>3]=c;a[F]=a[b>>2];a[F+1]=a[b+4>>2];F=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3])+(a[b>>2]=a[D],a[b+4>>2]=a[D+1],f[b>>3]);f[b>>3]=F;a[z]=a[b>>2];a[z+1]=a[b+4>>2];z=(a[b>>2]=a[v],a[b+4>>2]=a[v+1],f[b>>3])+(a[b>>2]=a[S],a[b+4>>2]=a[S+1],f[b>>3]);f[b>>3]=z;a[t]=a[b>>2];a[t+1]=a[b+4>>2];t=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3])+(a[b>>2]=a[D],a[b+4>>2]=a[D+1],f[b>>3]);f[b>>3]=t;a[n]=a[b>>2];a[n+1]=a[b+4>>2];n=(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3])+(a[b>>2]=a[S],a[b+4>>2]=a[S+1],f[b>>3]);f[b>>3]=n;a[m]=a[b>>2];a[m+1]=a[b+4>>2];m=(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3])+(a[b>>2]=a[D],a[b+4>>2]=a[D+1],f[b>>3]);f[b>>3]=m;a[r]=a[b>>2];a[r+1]=a[b+4>>2];S=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])+(a[b>>2]=a[S],a[b+4>>2]=a[S+1],f[b>>3]);f[b>>3]=S;a[j]=a[b>>2];a[j+1]=a[b+4>>2];D=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3])+(a[b>>2]=a[D],a[b+4>>2]=a[D+1],f[b>>3]);f[b>>3]=D;a[g]=a[b>>2];a[g+1]=a[b+4>>2];f[b>>3]=I|0;a[A]=a[b>>2];a[A+1]=a[b+4>>2];h=C}function gk(b,c){var g,e;a:do{if(0==n[b+124|0]<<24>>24){g=b}else{for(e=b;;){if(e=a[e+128>>2],0==n[e+124|0]<<24>>24){g=e;break a}}}}while(0);g=(g+24|0)>>2;e=a[g];0==(e|0)&&(e=da(40),a[g]=e);e>>=2;var d=a[e];e=0==(d|0)?Za((48*a[e+1]&-1)+48|0):Oa(d,(48*a[e+1]&-1)+48|0);a[a[g]>>2]=e;d=a[g]+4|0;e=a[d>>2];a[d>>2]=e+1|0;d=a[a[g]>>2];g=d>>2;d=d+(48*e&-1)|0;a[d>>2]=da(c<<4);a[((48*e&-1)+4>>2)+g]=c;a[((48*e&-1)+12>>2)+g]=0;a[((48*e&-1)+8>>2)+g]=0;return d}function Nd(c,d,g,e){var l,p,j,k,r,q,m,i,x=0,v=h;h=h+80|0;r=v>>2;q=v+4;k=q>>2;l=v+8;p=l>>2;j=v+16;var t=a[c+16>>2];i=t>>2;var y=a[i+5],z=gk(c,e);a:do{if(0==n[c+124|0]<<24>>24){var B=c}else{for(var F=c;;){if(F=a[F+128>>2],0==n[F+124|0]<<24>>24){B=F;break a}}}}while(0);0==n[5246408]<<24>>24?(a[i+59]|0)!=(a[d+236>>2]|0)?i=d:(i=(F=(a[i+60]|0)>(a[d+240>>2]|0))?t:d,t=F?d:t):i=d;if((t|0)==(a[B+16>>2]|0)){var d=B+92|0,D=B+52|0,S=B+98|0,F=B+58|0}else{d=B+52|0,D=B+92|0,S=B+58|0,F=B+98|0}B=n[S];d=a[d>>2];D=a[D>>2];do{if(0==n[F]<<24>>24){x=1531}else{var S=t+24|0,A=a[S>>2];if(0==(A|0)){x=1531}else{if(0==(a[a[A+4>>2]+12>>2]|0)){x=1531}else{a[p]=t;a[p+1]=D|0;for(var C=e-4|0,A=t+32|0,I=t+40|0,Z=0;(Z|0)<(C|0);){var T=Z+3|0,K=(T<<4)+g|0,K=(a[b>>2]=a[K>>2],a[b+4>>2]=a[K+4>>2],f[b>>3])-(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]),M=(T<<4)+g+8|0;if(0==J[a[a[a[S>>2]+4>>2]+12>>2]](l,K,(a[b>>2]=a[M>>2],a[b+4>>2]=a[M+4>>2],f[b>>3])-(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3]))<<24>>24){break}else{Z=T}}a[r]=Z;di(l,t,(Z<<4)+g|0,1);C=Z}}}}while(0);1531==x&&(C=a[r]=0);do{if(0==B<<24>>24){x=1540}else{if(t=i+24|0,F=a[t>>2],0==(F|0)){x=1540}else{if(0==(a[a[F+4>>2]+12>>2]|0)){x=1540}else{a[p]=i;a[p+1]=d|0;for(var L=i+32|0,F=i+40|0,D=e-4|0;0<(D|0);){S=(D<<4)+g|0;S=(a[b>>2]=a[S>>2],a[b+4>>2]=a[S+4>>2],f[b>>3])-(a[b>>2]=a[L>>2],a[b+4>>2]=a[L+4>>2],f[b>>3]);A=(D<<4)+g+8|0;if(0==J[a[a[a[t>>2]+4>>2]+12>>2]](l,S,(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3])-(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]))<<24>>24){break}D=D-3|0}a[k]=D;di(l,i,(D<<4)+g|0,0);L=D}}}}while(0);1540==x&&(L=e-4|0,a[k]=L);for(e=e-4|0;;){if((C|0)>=(e|0)){m=L;break}l=(C<<4)+g|0;p=C+3|0;B=(p<<4)+g|0;l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])-(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]);C=(C<<4)+g+8|0;B=(p<<4)+g+8|0;C=(a[b>>2]=a[C>>2],a[b+4>>2]=a[C+4>>2],f[b>>3])-(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]);if(1e-6<=l*l+C*C){m=L;break}C=a[r]=p}for(;0<(m|0);){e=(m<<4)+g|0;L=m+3|0;p=(L<<4)+g|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);p=(m<<4)+g+8|0;L=(L<<4)+g+8|0;L=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])-(a[b>>2]=a[L>>2],a[b+4>>2]=a[L+4>>2],f[b>>3]);if(1e-6<=e*e+L*L){break}m=m-3|0;a[k]=m}Oo(c,i,g,v,q,z);c=a[r];i=a[k]+4|0;m=(z|0)>>2;q=j>>2;L=j|0;r=(j+16|0)>>2;k=(j+32|0)>>2;j=(j+48|0)>>2;y=y+52|0;for(e=c;;){if((e|0)>=(i|0)){x=1553;break}l=((e-c<<4)+a[m]|0)>>2;p=((e<<4)+g|0)>>2;a[l]=a[p];a[l+1]=a[p+1];a[l+2]=a[p+2];a[l+3]=a[p+3];a[q]=a[p];a[q+1]=a[p+1];a[q+2]=a[p+2];a[q+3]=a[p+3];l=e+1|0;if((l|0)>=(i|0)){x=1554;break}p=((l-c<<4)+a[m]|0)>>2;l=((l<<4)+g|0)>>2;a[p]=a[l];a[p+1]=a[l+1];a[p+2]=a[l+2];a[p+3]=a[l+3];a[r]=a[l];a[r+1]=a[l+1];a[r+2]=a[l+2];a[r+3]=a[l+3];l=e+2|0;p=((l-c<<4)+a[m]|0)>>2;l=((l<<4)+g|0)>>2;a[p]=a[l];a[p+1]=a[l+1];a[p+2]=a[l+2];a[p+3]=a[l+3];a[k]=a[l];a[k+1]=a[l+1];a[k+2]=a[l+2];a[k+3]=a[l+3];p=e+3|0;e=((p<<4)+g|0)>>2;a[j]=a[e];a[j+1]=a[e+1];a[j+2]=a[e+2];a[j+3]=a[e+3];Cg(y,L);e=p}1553==x?(a[(z+4|0)>>2]=i-c|0,h=v):1554==x&&(a[(z+4|0)>>2]=i-c|0,h=v)}function Oo(b,c,g,e,d,f){var j,k,r=h;h=h+8|0;k=r>>2;var q=r+4;j=q>>2;for(var m=b;;){var i=a[m+128>>2];if(0==(i|0)){break}else{m=i}}i=0==n[5246408]<<24>>24?J[a[1311600]](m)&255:0;zg(m,r,q);0!=J[a[1311601]](c)<<24>>24&&(a[j]=0);0!=J[a[1311601]](a[b+16>>2])<<24>>24&&(a[k]=0);0!=(i|0)&&(b=a[k],a[k]=a[j],a[j]=b);0!=n[5246409]<<24>>24?(j=a[j],k=a[k],0!=(j|k|0)&&Dm(m,g,a[e>>2],a[d>>2],f,k,j)):(k=a[k],0!=(k|0)&&(a[e>>2]=Hh(m,g,a[e>>2],a[d>>2],f,k)),j=a[j],0!=(j|0)&&(a[d>>2]=Gh(m,g,a[e>>2],a[d>>2],f,j)));h=r}function vc(c,d){var g,e,l=h;g=d>>2;d=h;h=h+32|0;a[d>>2]=a[g];a[d+4>>2]=a[g+1];a[d+8>>2]=a[g+2];a[d+12>>2]=a[g+3];a[d+16>>2]=a[g+4];a[d+20>>2]=a[g+5];a[d+24>>2]=a[g+6];a[d+28>>2]=a[g+7];g=d|0;e=d+16|0;if((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])<(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])){if(g=d+8|0,e=d+24|0,(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])<(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])){g=c+80|0,e=a[g>>2],a[g>>2]=e+1|0,e=((e<<5)+a[c+84>>2]|0)>>2,g=d>>2,a[e]=a[g],a[e+1]=a[g+1],a[e+2]=a[g+2],a[e+3]=a[g+3],a[e+4]=a[g+4],a[e+5]=a[g+5],a[e+6]=a[g+6],a[e+7]=a[g+7]}}h=l}function Po(c,d,g,e,l){var p=c|0;f[b>>3]=d+e;a[p>>2]=a[b>>2];a[p+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=g+l;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function Tg(c,d,g,e,l){var p,j,k,r,q,m,i,x,v,t,y,z,B,F=e>>2,D=0,A=h;h=h+56|0;var C=A+40,E=d+16|0,I=a[E>>2];B=I>>2;var Z=d+28|0;if(0!=n[d+59|0]<<24>>24){yo(A,I,a[d+12>>2],Z);for(var T=A>>2,K=Z>>2,M=T+10;T<M;T++,K++){a[K]=a[T]}}var L=a[B+6],H=0==(L|0)?0:a[a[L+4>>2]+16>>2];z=(I+32|0)>>2;var yb=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]);y=(I+40|0)>>2;var G=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),R=Z|0,Y=d+36|0;Po(C,yb,G,(a[b>>2]=a[R>>2],a[b+4>>2]=a[R+4>>2],f[b>>3]),(a[b>>2]=a[Y>>2],a[b+4>>2]=a[Y+4>>2],f[b>>3]));t=c>>2;v=C>>2;a[t]=a[v];a[t+1]=a[v+1];a[t+2]=a[v+2];a[t+3]=a[v+3];if(0==l<<24>>24){if(0==n[d+57|0]<<24>>24){n[c+29|0]=0}else{var P=d+44|0,Rb=(a[b>>2]=a[P>>2],a[b+4>>2]=a[P+4>>2],f[b>>3]),N=c+16|0;f[b>>3]=Rb;a[N>>2]=a[b>>2];a[N+4>>2]=a[b+4>>2];n[c+29|0]=1}}else{var ea=hk(a[E>>2]),wa=c+16|0;f[b>>3]=ea;a[wa>>2]=a[b>>2];a[wa+4>>2]=a[b+4>>2];n[c+29|0]=1}a[c+80>>2]=0;a[c+88>>2]=d|0;x=(e+32|0)>>2;a[x]=a[t];a[x+1]=a[t+1];a[x+2]=a[t+2];a[x+3]=a[t+3];var Fb=1==(g|0);do{if(Fb){if(0!=n[I+162|0]<<24>>24){var V=1}else{var W=n[d+61|0],X=W&255;if(0==W<<24>>24){D=1630}else{var ba=e|0,ma=(a[b>>2]=a[ba>>2],a[b+4>>2]=a[ba+4>>2],f[b>>3]),ib=e+8|0,Q=(a[b>>2]=a[ib>>2],a[b+4>>2]=a[ib+4>>2],f[b>>3]),U=e+16|0,O=(a[b>>2]=a[U>>2],a[b+4>>2]=a[U+4>>2],f[b>>3]),ga=e+24|0,aa=(a[b>>2]=a[ga>>2],a[b+4>>2]=a[ga+4>>2],f[b>>3]);if(0==(X&4|0)){if(0!=(X&1|0)){a[F+12]=1;i=(c+8|0)>>2;var $=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3]),ua=aa>$?aa:$,Da=e+56|0;f[b>>3]=ma;a[Da>>2]=a[b>>2];a[Da+4>>2]=a[b+4>>2];var Ja=e+64|0;f[b>>3]=Q;a[Ja>>2]=a[b>>2];a[Ja+4>>2]=a[b+4>>2];var Ab=e+72|0;f[b>>3]=O;a[Ab>>2]=a[b>>2];a[Ab+4>>2]=a[b+4>>2];var ra=e+80|0;f[b>>3]=ua;a[ra>>2]=a[b>>2];a[ra+4>>2]=a[b+4>>2];a[F+13]=1;var da=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3])-1;f[b>>3]=da;a[i]=a[b>>2];a[i+1]=a[b+4>>2]}else{var ya=e+48|0;if(0==(X&8|0)){a[ya>>2]=2;m=(c|0)>>2;var ja=(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3]),la=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),va=I+96|0,oa=(a[b>>2]=a[va>>2],a[b+4>>2]=a[va+4>>2],f[b>>3]),ka=la-((((0>oa?oa-.5:oa+.5)&-1)+1|0)/2&-1|0),Ea=c+8|0,Ka=(a[b>>2]=a[Ea>>2],a[b+4>>2]=a[Ea+4>>2],f[b>>3]),Na=e+56|0;f[b>>3]=ja;a[Na>>2]=a[b>>2];a[Na+4>>2]=a[b+4>>2];var Ba=e+64|0;f[b>>3]=ka;a[Ba>>2]=a[b>>2];a[Ba+4>>2]=a[b+4>>2];var Wa=e+72|0;f[b>>3]=O;a[Wa>>2]=a[b>>2];a[Wa+4>>2]=a[b+4>>2];var ca=e+80|0;f[b>>3]=Ka;a[ca>>2]=a[b>>2];a[ca+4>>2]=a[b+4>>2];a[F+13]=1;var ha=(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3])+1;f[b>>3]=ha;a[m]=a[b>>2];a[m+1]=a[b+4>>2]}else{a[ya>>2]=8;q=(c|0)>>2;var Ra=(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3]),bb=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),Xa=I+96|0,Sa=(a[b>>2]=a[Xa>>2],a[b+4>>2]=a[Xa+4>>2],f[b>>3]),sa=bb-((((0>Sa?Sa-.5:Sa+.5)&-1)+1|0)/2&-1|0),Va=c+8|0,Ta=(a[b>>2]=a[Va>>2],a[b+4>>2]=a[Va+4>>2],f[b>>3]),Aa=e+56|0;f[b>>3]=ma;a[Aa>>2]=a[b>>2];a[Aa+4>>2]=a[b+4>>2];var fb=e+64|0;f[b>>3]=sa;a[fb>>2]=a[b>>2];a[fb+4>>2]=a[b+4>>2];var Ca=e+72|0;f[b>>3]=Ra;a[Ca>>2]=a[b>>2];a[Ca+4>>2]=a[b+4>>2];var Ya=e+80|0;f[b>>3]=Ta;a[Ya>>2]=a[b>>2];a[Ya+4>>2]=a[b+4>>2];a[F+13]=1;var $a=(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3])-1;f[b>>3]=$a;a[q]=a[b>>2];a[q+1]=a[b+4>>2]}}}else{a[F+12]=4;var La=c|0,pa=(a[b>>2]=a[La>>2],a[b+4>>2]=a[La+4>>2],f[b>>3]),Ga=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]);if(pa<Ga){var Fa=ma-1,fa=c+8|0,nb=(a[b>>2]=a[fa>>2],a[b+4>>2]=a[fa+4>>2],f[b>>3]),jb=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),cb=I+96|0,qa=(a[b>>2]=a[cb>>2],a[b+4>>2]=a[cb+4>>2],f[b>>3]),kb=0>qa,Kb=jb+((((kb?qa-.5:qa+.5)&-1)+1|0)/2&-1|0)+((a[a[B+5]+260>>2]|0)/2&-1|0),Ma=I+104|0,xa=Ga-(a[b>>2]=a[Ma>>2],a[b+4>>2]=a[Ma+4>>2],f[b>>3]),lb=jb-((((kb?qa-.5:qa+.5)&-1)+1|0)/2&-1|0),rb=e+56|0;f[b>>3]=Fa;a[rb>>2]=a[b>>2];a[rb+4>>2]=a[b+4>>2];var ab=e+64|0;f[b>>3]=nb;a[ab>>2]=a[b>>2];a[ab+4>>2]=a[b+4>>2];var db=e+72|0;f[b>>3]=O;a[db>>2]=a[b>>2];a[db+4>>2]=a[b+4>>2];var ob=e+80|0;f[b>>3]=Kb;a[ob>>2]=a[b>>2];a[ob+4>>2]=a[b+4>>2];var pb=e+88|0;f[b>>3]=Fa;a[pb>>2]=a[b>>2];a[pb+4>>2]=a[b+4>>2];var ub=e+96|0;f[b>>3]=lb;a[ub>>2]=a[b>>2];a[ub+4>>2]=a[b+4>>2];var gb=e+104|0;f[b>>3]=xa;a[gb>>2]=a[b>>2];a[gb+4>>2]=a[b+4>>2];var sb=e+112|0;f[b>>3]=nb;a[sb>>2]=a[b>>2];a[sb+4>>2]=a[b+4>>2]}else{var Ia=c+8|0,vb=(a[b>>2]=a[Ia>>2],a[b+4>>2]=a[Ia+4>>2],f[b>>3]),Ua=O+1,na=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),Oa=I+96|0,qb=(a[b>>2]=a[Oa>>2],a[b+4>>2]=a[Oa+4>>2],f[b>>3]),Bb=0>qb,sc=na+((((Bb?qb-.5:qb+.5)&-1)+1|0)/2&-1|0)+((a[a[B+5]+260>>2]|0)/2&-1|0),xb=I+112|0,za=Ga+(a[b>>2]=a[xb>>2],a[b+4>>2]=a[xb+4>>2],f[b>>3]),Nb=na-((((Bb?qb-.5:qb+.5)&-1)+1|0)/2&-1|0),Jb=e+56|0;f[b>>3]=ma;a[Jb>>2]=a[b>>2];a[Jb+4>>2]=a[b+4>>2];var Ha=e+64|0;f[b>>3]=vb;a[Ha>>2]=a[b>>2];a[Ha+4>>2]=a[b+4>>2];var ta=e+72|0;f[b>>3]=Ua;a[ta>>2]=a[b>>2];a[ta+4>>2]=a[b+4>>2];var Ic=e+80|0;f[b>>3]=sc;a[Ic>>2]=a[b>>2];a[Ic+4>>2]=a[b+4>>2];var Pa=e+88|0;f[b>>3]=za;a[Pa>>2]=a[b>>2];a[Pa+4>>2]=a[b+4>>2];var Za=e+96|0;f[b>>3]=Nb;a[Za>>2]=a[b>>2];a[Za+4>>2]=a[b+4>>2];var zb=e+104|0;f[b>>3]=Ua;a[zb>>2]=a[b>>2];a[zb+4>>2]=a[b+4>>2];var eb=e+112|0;f[b>>3]=vb;a[eb>>2]=a[b>>2];a[eb+4>>2]=a[b+4>>2]}r=(c+8|0)>>2;var mb=(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3])+1;f[b>>3]=mb;a[r]=a[b>>2];a[r+1]=a[b+4>>2];a[F+13]=2}a:do{if(0==n[d+124|0]<<24>>24){var hb=d}else{for(var Ub=d;;){var Db=a[Ub+128>>2];if(0==n[Db+124|0]<<24>>24){hb=Db;break a}else{Ub=Db}}}}while(0);(I|0)==(a[hb+16>>2]|0)?n[hb+58|0]=0:n[hb+98|0]=0;h=A;return}}}else{D=1630}}while(0);do{if(1630==D){do{if(2==(g|0)){var wb=n[d+61|0],Cb=wb&255;if(0!=wb<<24>>24){var Ib=e|0,tb=(a[b>>2]=a[Ib>>2],a[b+4>>2]=a[Ib+4>>2],f[b>>3]),Eb=e+8|0,Qa=(a[b>>2]=a[Eb>>2],a[b+4>>2]=a[Eb+4>>2],f[b>>3]),Hb=e+16|0,cc=(a[b>>2]=a[Hb>>2],a[b+4>>2]=a[Hb+4>>2],f[b>>3]),pc=e+24|0,Mb=(a[b>>2]=a[pc>>2],a[b+4>>2]=a[pc+4>>2],f[b>>3]);if(0==(Cb&4|0)){if(0!=(Cb&1|0)){if(4!=(a[F+12]|0)){var hd=c+8|0,qd=(a[b>>2]=a[hd>>2],a[b+4>>2]=a[hd+4>>2],f[b>>3]),Vb=Mb>qd?Mb:qd,Yb=e+56|0;f[b>>3]=tb;a[Yb>>2]=a[b>>2];a[Yb+4>>2]=a[b+4>>2];var Jc=e+64|0;f[b>>3]=Qa;a[Jc>>2]=a[b>>2];a[Jc+4>>2]=a[b+4>>2];var Pb=e+72|0;f[b>>3]=cc;a[Pb>>2]=a[b>>2];a[Pb+4>>2]=a[b+4>>2];var Sb=e+80|0;f[b>>3]=Vb;a[Sb>>2]=a[b>>2];a[Sb+4>>2]=a[b+4>>2];a[F+13]=1}else{var Xb=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),hc=I+96|0,Lb=(a[b>>2]=a[hc>>2],a[b+4>>2]=a[hc+4>>2],f[b>>3]),kc=0>Lb,uc=Xb-((((kc?Lb-.5:Lb+.5)&-1)+1|0)/2&-1|0),fc=cc+1,Zb=c|0,ic=(a[b>>2]=a[Zb>>2],a[b+4>>2]=a[Zb+4>>2],f[b>>3]),Kc=uc-((a[a[B+5]+260>>2]|0)/2&-1|0),rc=I+112|0,ac=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3])+(a[b>>2]=a[rc>>2],a[b+4>>2]=a[rc+4>>2],f[b>>3]),Cc=Xb+((((kc?Lb-.5:Lb+.5)&-1)+1|0)/2&-1|0),gc=e+56|0;f[b>>3]=ic;a[gc>>2]=a[b>>2];a[gc+4>>2]=a[b+4>>2];var Dc=e+64|0;f[b>>3]=Kc;a[Dc>>2]=a[b>>2];a[Dc+4>>2]=a[b+4>>2];var ec=e+72|0;f[b>>3]=fc;a[ec>>2]=a[b>>2];a[ec+4>>2]=a[b+4>>2];var Qb=e+80|0;f[b>>3]=uc;a[Qb>>2]=a[b>>2];a[Qb+4>>2]=a[b+4>>2];var jc=e+88|0;f[b>>3]=ac;a[jc>>2]=a[b>>2];a[jc+4>>2]=a[b+4>>2];var Yc=e+96|0;f[b>>3]=uc;a[Yc>>2]=a[b>>2];a[Yc+4>>2]=a[b+4>>2];var xc=e+104|0;f[b>>3]=fc;a[xc>>2]=a[b>>2];a[xc+4>>2]=a[b+4>>2];var dc=e+112|0;f[b>>3]=Cc;a[dc>>2]=a[b>>2];a[dc+4>>2]=a[b+4>>2];a[F+13]=2}}else{var Wc=c|0,ae=(a[b>>2]=a[Wc>>2],a[b+4>>2]=a[Wc+4>>2],f[b>>3]);if(0==(Cb&8|0)){var $b=4==(a[F+12]|0),lc=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),bc=I+96|0,Kd=(a[b>>2]=a[bc>>2],a[b+4>>2]=a[bc+4>>2],f[b>>3]),Sc=0<=Kd;if($b){var bd=c+8|0,Vc=lc+((((Sc?Kd+.5:Kd-.5)&-1)+1|0)/2&-1|0),cd=(a[b>>2]=a[bd>>2],a[b+4>>2]=a[bd+4>>2],f[b>>3])}else{var Zc=Sc?Kd+.5:Kd-.5,nc=c+8|0,Vc=(a[b>>2]=a[nc>>2],a[b+4>>2]=a[nc+4>>2],f[b>>3])+1,cd=lc-(((Zc&-1)+1|0)/2&-1|0)}var Oc=e+56|0;f[b>>3]=ae;a[Oc>>2]=a[b>>2];a[Oc+4>>2]=a[b+4>>2];var Lc=e+64|0;f[b>>3]=cd;a[Lc>>2]=a[b>>2];a[Lc+4>>2]=a[b+4>>2];var dd=e+72|0;f[b>>3]=cc;a[dd>>2]=a[b>>2];a[dd+4>>2]=a[b+4>>2];var Sd=e+80|0;f[b>>3]=Vc;a[Sd>>2]=a[b>>2];a[Sd+4>>2]=a[b+4>>2]}else{var id=ae+1,Xc=4==(a[F+12]|0),tc=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),$c=I+96|0,oc=(a[b>>2]=a[$c>>2],a[b+4>>2]=a[$c+4>>2],f[b>>3]),Bc=0<=oc;if(Xc){var ad=c+8|0,Hc=tc+((((Bc?oc+.5:oc-.5)&-1)+1|0)/2&-1|0),Tc=(a[b>>2]=a[ad>>2],a[b+4>>2]=a[ad+4>>2],f[b>>3])-1}else{var zc=Bc?oc+.5:oc-.5,vc=c+8|0,Hc=(a[b>>2]=a[vc>>2],a[b+4>>2]=a[vc+4>>2],f[b>>3])+1,Tc=tc-(((zc&-1)+1|0)/2&-1|0)}var Pc=e+56|0;f[b>>3]=tb;a[Pc>>2]=a[b>>2];a[Pc+4>>2]=a[b+4>>2];var wc=e+64|0;f[b>>3]=Tc;a[wc>>2]=a[b>>2];a[wc+4>>2]=a[b+4>>2];var Uc=e+72|0;f[b>>3]=id;a[Uc>>2]=a[b>>2];a[Uc+4>>2]=a[b+4>>2];var wd=e+80|0;f[b>>3]=Hc;a[wd>>2]=a[b>>2];a[wd+4>>2]=a[b+4>>2]}a[F+13]=1}}else{var Ec=c+8|0,xd=(a[b>>2]=a[Ec>>2],a[b+4>>2]=a[Ec+4>>2],f[b>>3]),rd=Qa<xd?Qa:xd,yd=e+56|0;f[b>>3]=tb;a[yd>>2]=a[b>>2];a[yd+4>>2]=a[b+4>>2];var Gc=e+64|0;f[b>>3]=rd;a[Gc>>2]=a[b>>2];a[Gc+4>>2]=a[b+4>>2];var Cd=e+72|0;f[b>>3]=cc;a[Cd>>2]=a[b>>2];a[Cd+4>>2]=a[b+4>>2];var md=e+80|0;f[b>>3]=Mb;a[md>>2]=a[b>>2];a[md+4>>2]=a[b+4>>2];a[F+13]=1}a:do{if(0==n[d+124|0]<<24>>24){var sd=d}else{for(var Nc=d;;){var ed=a[Nc+128>>2];if(0==n[ed+124|0]<<24>>24){sd=ed;break a}else{Nc=ed}}}}while(0);(I|0)==(a[sd+16>>2]|0)?n[sd+58|0]=0:n[sd+98|0]=0;a[F+12]=Cb;h=A;return}}}while(0);V=Fb?1:a[F+12]}}while(0);var zd=e+56|0,ke=e+52|0;if(0!=(H|0)){var yc=J[H](I,Z,V,zd,ke);if(0!=(yc|0)){a[F+12]=yc;h=A;return}}k=zd>>2;j=e>>2;a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];a[k+4]=a[j+4];a[k+5]=a[j+5];a[k+6]=a[j+6];a[k+7]=a[j+7];a[ke>>2]=1;if(8==(g|0)){ia(5333468,565,5380124,5340724);var jd=c+8|0,Ld=(a[b>>2]=a[jd>>2],a[b+4>>2]=a[jd+4>>2],f[b>>3])-1,Ad=e+80|0;f[b>>3]=Ld;a[Ad>>2]=a[b>>2];a[Ad+4>>2]=a[b+4>>2];a[F+12]=1}else{if(1==(g|0)){p=(c+8|0)>>2;var Rc=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]),Mc=e+80|0;f[b>>3]=Rc;a[Mc>>2]=a[b>>2];a[Mc+4>>2]=a[b+4>>2];a[F+12]=1;var Hd=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])-1;f[b>>3]=Hd;a[p]=a[b>>2];a[p+1]=a[b+4>>2]}else{if(2==(g|0)){var Id=4==(a[F+12]|0),Qc=c+8|0,Fc=(a[b>>2]=a[Qc>>2],a[b+4>>2]=a[Qc+4>>2],f[b>>3]);if(Id){var Md=e+64|0;f[b>>3]=Fc;a[Md>>2]=a[b>>2];a[Md+4>>2]=a[b+4>>2]}else{var nd=e+80|0;f[b>>3]=Fc;a[nd>>2]=a[b>>2];a[nd+4>>2]=a[b+4>>2]}}}}h=A}function hk(c){var d,g=a[c+176>>2],e=a[g>>2];if(0==(e|0)){var l=0,p=0}else{for(var p=l=0,j=e;;){var k=a[j+16>>2]+32|0,k=p+(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),h=l+1|0,j=a[g+(h<<2)>>2];if(0==(j|0)){break}else{l=h,p=k}}l=h|0;p=k}var g=c+184|0,k=a[g>>2],q=a[k>>2];if(0==(q|0)){var m=0,k=0}else{for(j=h=0;!(d=a[q+12>>2]+32|0,d=j+(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),m=h+1|0,q=a[k+(m<<2)>>2],0==(q|0));){h=m,j=d}m|=0;k=d}d=(c+32|0)>>2;l=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3])-p/l;c=(c+40|0)>>2;e=a[e+16>>2]+40|0;e=Math.atan2((a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3])-(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),l);d=k/m-(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);g=a[a[a[g>>2]>>2]+12>>2]+40|0;return.5*(e+Math.atan2((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])-(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3]),d))}function xt(c){var d=0,g=a[c+108>>2];0==n[c+56|0]<<24>>24?0!=n[c+96|0]<<24>>24&&(d=1701):d=1701;if(1701==d){var d=n[c+61|0],e=d&255;if(0!=(e&8|0)){return 0}var l=n[c+101|0];if(0!=(l&8)<<24>>24||d<<24>>24==l<<24>>24&&0!=(e&5|0)){return 0}}if(0==(g|0)){return 18}c=0==(a[a[a[c+12>>2]+20>>2]+152>>2]&1|0)?g+24|0:g+32|0;return c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])+18&-1}function Ug(c,d,g,e,l){var p,j,k,r,q,m,i,x,v,t,y,z,B,F=e>>2,D=0,A=h;h=h+56|0;var C=A+40,E=d+12|0,I=a[E>>2];B=I>>2;var Z=d+68|0;if(0!=n[d+99|0]<<24>>24){yo(A,I,a[d+16>>2],Z);for(var T=A>>2,K=Z>>2,M=T+10;T<M;T++,K++){a[K]=a[T]}}var L=a[B+6],H=0==(L|0)?0:a[a[L+4>>2]+16>>2],yb=c+40|0;z=(I+32|0)>>2;var G=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]);y=(I+40|0)>>2;var R=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),Y=Z|0,P=d+76|0;Po(C,G,R,(a[b>>2]=a[Y>>2],a[b+4>>2]=a[Y+4>>2],f[b>>3]),(a[b>>2]=a[P>>2],a[b+4>>2]=a[P+4>>2],f[b>>3]));t=yb>>2;v=C>>2;a[t]=a[v];a[t+1]=a[v+1];a[t+2]=a[v+2];a[t+3]=a[v+3];if(0==l<<24>>24){if(0==n[d+97|0]<<24>>24){n[c+69|0]=0}else{var Rb=d+84|0,N=(a[b>>2]=a[Rb>>2],a[b+4>>2]=a[Rb+4>>2],f[b>>3]),ea=c+56|0;f[b>>3]=N;a[ea>>2]=a[b>>2];a[ea+4>>2]=a[b+4>>2];n[c+69|0]=1}}else{var wa=hk(a[E>>2])+3.141592653589793,Fb=c+56|0;f[b>>3]=wa;a[Fb>>2]=a[b>>2];a[Fb+4>>2]=a[b+4>>2];6.283185307179586>wa||ia(5333468,602,5379860,5347384);n[c+69|0]=1}x=(e+32|0)>>2;a[x]=a[t];a[x+1]=a[t+1];a[x+2]=a[t+2];a[x+3]=a[t+3];var V=1==(g|0);do{if(V){if(0!=n[I+162|0]<<24>>24){var W=4}else{var X=n[d+101|0],ba=X&255;if(0==X<<24>>24){D=1761}else{var ma=e|0,ib=(a[b>>2]=a[ma>>2],a[b+4>>2]=a[ma+4>>2],f[b>>3]),Q=e+8|0,U=(a[b>>2]=a[Q>>2],a[b+4>>2]=a[Q+4>>2],f[b>>3]),O=e+16|0,ga=(a[b>>2]=a[O>>2],a[b+4>>2]=a[O+4>>2],f[b>>3]);if(0==(ba&4|0)){if(0==(ba&1|0)){var aa=e+48|0;if(0==(ba&8|0)){a[aa>>2]=2;i=(yb|0)>>2;var $=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3]),ua=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),Da=I+96|0,Ja=(a[b>>2]=a[Da>>2],a[b+4>>2]=a[Da+4>>2],f[b>>3]),da=ua+((((0>Ja?Ja-.5:Ja+.5)&-1)+1|0)/2&-1|0),ra=c+48|0,ca=(a[b>>2]=a[ra>>2],a[b+4>>2]=a[ra+4>>2],f[b>>3]),ya=e+56|0;f[b>>3]=$;a[ya>>2]=a[b>>2];a[ya+4>>2]=a[b+4>>2];var ja=e+64|0;f[b>>3]=ca;a[ja>>2]=a[b>>2];a[ja+4>>2]=a[b+4>>2];var la=e+72|0;f[b>>3]=ga;a[la>>2]=a[b>>2];a[la+4>>2]=a[b+4>>2];var va=e+80|0;f[b>>3]=da;a[va>>2]=a[b>>2];a[va+4>>2]=a[b+4>>2];a[F+13]=1;var oa=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3])+1;f[b>>3]=oa;a[i]=a[b>>2];a[i+1]=a[b+4>>2]}else{a[aa>>2]=8;m=(yb|0)>>2;var ka=(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3]),Ea=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),Ka=I+96|0,Na=(a[b>>2]=a[Ka>>2],a[b+4>>2]=a[Ka+4>>2],f[b>>3]),Ba=Ea+((((0>Na?Na-.5:Na+.5)&-1)+1|0)/2&-1|0),Wa=c+48|0,ha=(a[b>>2]=a[Wa>>2],a[b+4>>2]=a[Wa+4>>2],f[b>>3]),fa=e+56|0;f[b>>3]=ib;a[fa>>2]=a[b>>2];a[fa+4>>2]=a[b+4>>2];var Ra=e+64|0;f[b>>3]=ha;a[Ra>>2]=a[b>>2];a[Ra+4>>2]=a[b+4>>2];var bb=e+72|0;f[b>>3]=ka;a[bb>>2]=a[b>>2];a[bb+4>>2]=a[b+4>>2];var Xa=e+80|0;f[b>>3]=Ba;a[Xa>>2]=a[b>>2];a[Xa+4>>2]=a[b+4>>2];a[F+13]=1;var Sa=(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3])-1;f[b>>3]=Sa;a[m]=a[b>>2];a[m+1]=a[b+4>>2]}}else{a[F+12]=1;var sa=yb|0,Va=(a[b>>2]=a[sa>>2],a[b+4>>2]=a[sa+4>>2],f[b>>3]),Ta=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]);if(Va<Ta){var Aa=ib-1,fb=c+48|0,Ca=(a[b>>2]=a[fb>>2],a[b+4>>2]=a[fb+4>>2],f[b>>3]),Ya=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),$a=I+96|0,La=(a[b>>2]=a[$a>>2],a[b+4>>2]=a[$a+4>>2],f[b>>3]),pa=0>La,Ga=Ya-((((pa?La-.5:La+.5)&-1)+1|0)/2&-1|0)-((a[a[B+5]+260>>2]|0)/2&-1|0),Fa=I+104|0,qa=Ta-(a[b>>2]=a[Fa>>2],a[b+4>>2]=a[Fa+4>>2],f[b>>3]),nb=Ya+((((pa?La-.5:La+.5)&-1)+1|0)/2&-1|0),jb=e+56|0;f[b>>3]=Aa;a[jb>>2]=a[b>>2];a[jb+4>>2]=a[b+4>>2];var cb=e+64|0;f[b>>3]=Ga;a[cb>>2]=a[b>>2];a[cb+4>>2]=a[b+4>>2];var xa=e+72|0;f[b>>3]=ga;a[xa>>2]=a[b>>2];a[xa+4>>2]=a[b+4>>2];var kb=e+80|0;f[b>>3]=Ca;a[kb>>2]=a[b>>2];a[kb+4>>2]=a[b+4>>2];var Kb=e+88|0;f[b>>3]=Aa;a[Kb>>2]=a[b>>2];a[Kb+4>>2]=a[b+4>>2];var Ma=e+96|0;f[b>>3]=Ca;a[Ma>>2]=a[b>>2];a[Ma+4>>2]=a[b+4>>2];var na=e+104|0;f[b>>3]=qa;a[na>>2]=a[b>>2];a[na+4>>2]=a[b+4>>2];var lb=e+112|0;f[b>>3]=nb;a[lb>>2]=a[b>>2];a[lb+4>>2]=a[b+4>>2]}else{var rb=c+48|0,ab=(a[b>>2]=a[rb>>2],a[b+4>>2]=a[rb+4>>2],f[b>>3]),db=ga+1,ob=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),pb=I+96|0,ub=(a[b>>2]=a[pb>>2],a[b+4>>2]=a[pb+4>>2],f[b>>3]),gb=0>ub,sb=ob-((((gb?ub-.5:ub+.5)&-1)+1|0)/2&-1|0)-((a[a[B+5]+260>>2]|0)/2&-1|0),Ia=I+112|0,vb=Ta+(a[b>>2]=a[Ia>>2],a[b+4>>2]=a[Ia+4>>2],f[b>>3]),Ua=ob+((((gb?ub-.5:ub+.5)&-1)+1|0)/2&-1|0),Oa=e+56|0;f[b>>3]=ib;a[Oa>>2]=a[b>>2];a[Oa+4>>2]=a[b+4>>2];var Ha=e+64|0;f[b>>3]=sb;a[Ha>>2]=a[b>>2];a[Ha+4>>2]=a[b+4>>2];var qb=e+72|0;f[b>>3]=db;a[qb>>2]=a[b>>2];a[qb+4>>2]=a[b+4>>2];var Bb=e+80|0;f[b>>3]=ab;a[Bb>>2]=a[b>>2];a[Bb+4>>2]=a[b+4>>2];var sc=e+88|0;f[b>>3]=vb;a[sc>>2]=a[b>>2];a[sc+4>>2]=a[b+4>>2];var xb=e+96|0;f[b>>3]=ab;a[xb>>2]=a[b>>2];a[xb+4>>2]=a[b+4>>2];var za=e+104|0;f[b>>3]=db;a[za>>2]=a[b>>2];a[za+4>>2]=a[b+4>>2];var Nb=e+112|0;f[b>>3]=Ua;a[Nb>>2]=a[b>>2];a[Nb+4>>2]=a[b+4>>2]}a[F+13]=2;q=(c+48|0)>>2;var Jb=(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3])-1;f[b>>3]=Jb;a[q]=a[b>>2];a[q+1]=a[b+4>>2]}}else{var ta=e+24|0,Pa=(a[b>>2]=a[ta>>2],a[b+4>>2]=a[ta+4>>2],f[b>>3]);a[F+12]=4;r=(c+48|0)>>2;var Za=(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3]),zb=U<Za?U:Za,eb=e+56|0;f[b>>3]=ib;a[eb>>2]=a[b>>2];a[eb+4>>2]=a[b+4>>2];var hb=e+64|0;f[b>>3]=zb;a[hb>>2]=a[b>>2];a[hb+4>>2]=a[b+4>>2];var Cb=e+72|0;f[b>>3]=ga;a[Cb>>2]=a[b>>2];a[Cb+4>>2]=a[b+4>>2];var Db=e+80|0;f[b>>3]=Pa;a[Db>>2]=a[b>>2];a[Db+4>>2]=a[b+4>>2];a[F+13]=1;var mb=(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3])+1;f[b>>3]=mb;a[r]=a[b>>2];a[r+1]=a[b+4>>2]}a:do{if(0==n[d+124|0]<<24>>24){var Ub=d}else{for(var wb=d;;){var tb=a[wb+128>>2];if(0==n[tb+124|0]<<24>>24){Ub=tb;break a}else{wb=tb}}}}while(0);(I|0)==(a[Ub+12>>2]|0)?n[Ub+98|0]=0:n[Ub+58|0]=0;a[F+12]=ba;h=A;return}}}else{D=1761}}while(0);do{if(1761==D){do{if(2==(g|0)){var Ib=n[d+101|0],Qa=Ib&255;if(0!=Ib<<24>>24){var Eb=e|0,Hb=(a[b>>2]=a[Eb>>2],a[b+4>>2]=a[Eb+4>>2],f[b>>3]),Mb=e+8|0,Pb=(a[b>>2]=a[Mb>>2],a[b+4>>2]=a[Mb+4>>2],f[b>>3]),cc=e+16|0,pc=(a[b>>2]=a[cc>>2],a[b+4>>2]=a[cc+4>>2],f[b>>3]),Lb=e+24|0,hd=(a[b>>2]=a[Lb>>2],a[b+4>>2]=a[Lb+4>>2],f[b>>3]);if(0==(Qa&4|0)){if(0!=(Qa&1|0)){if(4!=(a[F+12]|0)){var qd=c+8|0,Vb=(a[b>>2]=a[qd>>2],a[b+4>>2]=a[qd+4>>2],f[b>>3]),Yb=hd>Vb?hd:Vb,Jc=e+56|0;f[b>>3]=Hb;a[Jc>>2]=a[b>>2];a[Jc+4>>2]=a[b+4>>2];var Sb=e+64|0;f[b>>3]=Pb;a[Sb>>2]=a[b>>2];a[Sb+4>>2]=a[b+4>>2];var Xb=e+72|0;f[b>>3]=pc;a[Xb>>2]=a[b>>2];a[Xb+4>>2]=a[b+4>>2];var hc=e+80|0;f[b>>3]=Yb;a[hc>>2]=a[b>>2];a[hc+4>>2]=a[b+4>>2];a[F+13]=1}else{var fc=Hb-1,Zb=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),kc=I+96|0,uc=(a[b>>2]=a[kc>>2],a[b+4>>2]=a[kc+4>>2],f[b>>3]),ic=0>uc,ac=Zb-((((ic?uc-.5:uc+.5)&-1)+1|0)/2&-1|0),gc=yb|0,Kc=(a[b>>2]=a[gc>>2],a[b+4>>2]=a[gc+4>>2],f[b>>3]),rc=ac-((a[a[B+5]+260>>2]|0)/2&-1|0),ec=I+104|0,Cc=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3])-(a[b>>2]=a[ec>>2],a[b+4>>2]=a[ec+4>>2],f[b>>3])-2,Qb=Zb+((((ic?uc-.5:uc+.5)&-1)+1|0)/2&-1|0),Dc=e+56|0;f[b>>3]=fc;a[Dc>>2]=a[b>>2];a[Dc+4>>2]=a[b+4>>2];var jc=e+64|0;f[b>>3]=rc;a[jc>>2]=a[b>>2];a[jc+4>>2]=a[b+4>>2];var dc=e+72|0;f[b>>3]=Kc;a[dc>>2]=a[b>>2];a[dc+4>>2]=a[b+4>>2];var lc=e+80|0;f[b>>3]=ac;a[lc>>2]=a[b>>2];a[lc+4>>2]=a[b+4>>2];var Yc=e+88|0;f[b>>3]=fc;a[Yc>>2]=a[b>>2];a[Yc+4>>2]=a[b+4>>2];var xc=e+96|0;f[b>>3]=ac;a[xc>>2]=a[b>>2];a[xc+4>>2]=a[b+4>>2];var $b=e+104|0;f[b>>3]=Cc;a[$b>>2]=a[b>>2];a[$b+4>>2]=a[b+4>>2];var Wc=e+112|0;f[b>>3]=Qb;a[Wc>>2]=a[b>>2];a[Wc+4>>2]=a[b+4>>2];a[F+13]=2}}else{var bc=yb|0,oc=(a[b>>2]=a[bc>>2],a[b+4>>2]=a[bc+4>>2],f[b>>3]);if(0==(Qa&8|0)){var tc=oc-1,Bc=4==(a[F+12]|0),Kd=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),Sc=I+96|0,bd=(a[b>>2]=a[Sc>>2],a[b+4>>2]=a[Sc+4>>2],f[b>>3]),Vc=0<=bd;if(Bc){var cd=c+48|0,Zc=Kd+((((Vc?bd+.5:bd-.5)&-1)+1|0)/2&-1|0),nc=(a[b>>2]=a[cd>>2],a[b+4>>2]=a[cd+4>>2],f[b>>3])-1}else{var Oc=Vc?bd+.5:bd-.5,Lc=c+48|0,Zc=(a[b>>2]=a[Lc>>2],a[b+4>>2]=a[Lc+4>>2],f[b>>3]),nc=Kd-(((Oc&-1)+1|0)/2&-1|0)}var dd=e+56|0;f[b>>3]=tc;a[dd>>2]=a[b>>2];a[dd+4>>2]=a[b+4>>2];var Sd=e+64|0;f[b>>3]=nc;a[Sd>>2]=a[b>>2];a[Sd+4>>2]=a[b+4>>2];var id=e+72|0;f[b>>3]=pc;a[id>>2]=a[b>>2];a[id+4>>2]=a[b+4>>2];var Xc=e+80|0;f[b>>3]=Zc;a[Xc>>2]=a[b>>2];a[Xc+4>>2]=a[b+4>>2]}else{var Hc=oc+1,$c=4==(a[F+12]|0),vc=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),Pc=I+96|0,ad=(a[b>>2]=a[Pc>>2],a[b+4>>2]=a[Pc+4>>2],f[b>>3]),wc=0<=ad;if($c){var Tc=c+48|0,zc=vc+((((wc?ad+.5:ad-.5)&-1)+1|0)/2&-1|0),Ec=(a[b>>2]=a[Tc>>2],a[b+4>>2]=a[Tc+4>>2],f[b>>3])-1}else{var Gc=wc?ad+.5:ad-.5,Nc=c+48|0,zc=(a[b>>2]=a[Nc>>2],a[b+4>>2]=a[Nc+4>>2],f[b>>3])+1,Ec=vc-(((Gc&-1)+1|0)/2&-1|0)}var Uc=e+56|0;f[b>>3]=Hb;a[Uc>>2]=a[b>>2];a[Uc+4>>2]=a[b+4>>2];var wd=e+64|0;f[b>>3]=Ec;a[wd>>2]=a[b>>2];a[wd+4>>2]=a[b+4>>2];var yc=e+72|0;f[b>>3]=Hc;a[yc>>2]=a[b>>2];a[yc+4>>2]=a[b+4>>2];var xd=e+80|0;f[b>>3]=zc;a[xd>>2]=a[b>>2];a[xd+4>>2]=a[b+4>>2]}a[F+13]=1}}else{var rd=c+48|0,yd=(a[b>>2]=a[rd>>2],a[b+4>>2]=a[rd+4>>2],f[b>>3]),Mc=Pb<yd?Pb:yd,Cd=e+56|0;f[b>>3]=Hb;a[Cd>>2]=a[b>>2];a[Cd+4>>2]=a[b+4>>2];var md=e+64|0;f[b>>3]=Mc;a[md>>2]=a[b>>2];a[md+4>>2]=a[b+4>>2];var sd=e+72|0;f[b>>3]=pc;a[sd>>2]=a[b>>2];a[sd+4>>2]=a[b+4>>2];var Qc=e+80|0;f[b>>3]=hd;a[Qc>>2]=a[b>>2];a[Qc+4>>2]=a[b+4>>2];a[F+13]=1}a:do{if(0==n[d+124|0]<<24>>24){var ed=d}else{for(var zd=d;;){var Fc=a[zd+128>>2];if(0==n[Fc+124|0]<<24>>24){ed=Fc;break a}else{zd=Fc}}}}while(0);(I|0)==(a[ed+12>>2]|0)?n[ed+98|0]=0:n[ed+58|0]=0;a[F+12]=Qa;h=A;return}}}while(0);W=V?4:a[F+12]}}while(0);var Rc=e+56|0,jd=e+52|0;if(0!=(H|0)){var Ld=J[H](I,Z,W,Rc,jd);if(0!=(Ld|0)){a[F+12]=Ld;h=A;return}}k=Rc>>2;j=e>>2;a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];a[k+4]=a[j+4];a[k+5]=a[j+5];a[k+6]=a[j+6];a[k+7]=a[j+7];a[jd>>2]=1;if(8==(g|0)){ia(5333468,757,5379860,5340724);var Ad=c+48|0,gd=(a[b>>2]=a[Ad>>2],a[b+4>>2]=a[Ad+4>>2],f[b>>3])+1,kd=e+64|0;f[b>>3]=gd;a[kd>>2]=a[b>>2];a[kd+4>>2]=a[b+4>>2];a[F+12]=4}else{if(2==(g|0)){var Hd=4==(a[F+12]|0),Id=c+48|0,ud=(a[b>>2]=a[Id>>2],a[b+4>>2]=a[Id+4>>2],f[b>>3]);if(Hd){var pd=e+64|0;f[b>>3]=ud;a[pd>>2]=a[b>>2];a[pd+4>>2]=a[b+4>>2]}else{var Md=e+80|0;f[b>>3]=ud;a[Md>>2]=a[b>>2];a[Md+4>>2]=a[b+4>>2]}}else{if(1==(g|0)){p=(c+48|0)>>2;var nd=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]),td=e+64|0;f[b>>3]=nd;a[td>>2]=a[b>>2];a[td+4>>2]=a[b+4>>2];a[F+12]=4;var fd=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])+1;f[b>>3]=fd;a[p]=a[b>>2];a[p+1]=a[b+4>>2]}}}h=A}function Qo(b,c,g,e,d){var f=0,j=a[b+(c<<2)>>2];0==n[j+56|0]<<24>>24?0!=n[j+96|0]<<24>>24&&(f=1824):f=1824;a:do{if(1824==f){var f=n[j+61|0],k=f&255;do{if(0==(k&8|0)){var h=n[j+101|0],q=0==(h&8)<<24>>24;if(q){if(f<<24>>24!=h<<24>>24){break a}if(0==(k&5|0)){break a}if(q){if(0!=(k&4|0)){ik(b,c,g,e,d);return}0==(k&1|0)?ia(5333468,1114,5379684,5340724):Ro(b,c,g,e,d);return}}}}while(0);if(0==(f&2)<<24>>24&&0==(n[j+101|0]&2)<<24>>24){So(b,c,g,e,d);return}ik(b,c,g,e,d);return}}while(0);To(b,c,g,e,d)}function To(c,d,g,e,l){var p,j,k,r,q,m,i,x,v,t,y,z,B=h;h=h+16080|0;var F=B+16e3,D=B+16016,A=B+16032,C=B+16048,E=B+16064,I=a[c+(d<<2)>>2];j=a[I+16>>2];var l=.5*l/(g|0),Z=2<l?l:2;z=(j+32|0)>>2;var T=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]),l=(j+40|0)>>2,K=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]),M=I+28|0,L=I+36|0,M=(a[b>>2]=a[M>>2],a[b+4>>2]=a[M+4>>2],f[b>>3])+T,L=(a[b>>2]=a[L>>2],a[b+4>>2]=a[L+4>>2],f[b>>3])+K,H=I+68|0;k=I+76|0;H=(a[b>>2]=a[H>>2],a[b+4>>2]=a[H+4>>2],f[b>>3])+T;K=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])+K;j=j+112|0;var yb=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);j=T+yb;var G=3*(j-M),R=3*(j-H);if(0<(g|0)){var J=(L<K?-1:1)*Z,P=B|0,N=B+8|0;y=(B+16|0)>>2;t=F>>2;v=(B+32|0)>>2;x=D>>2;var Q=.5*(L+K);i=(B+48|0)>>2;m=A>>2;q=(B+64|0)>>2;r=C>>2;k=(B+80|0)>>2;j=E>>2;var ea=B+96|0,wa=B+104|0,Fb=B|0,g=g+d|0,V=yb,G=yb<G?yb:G,yb=yb<R?yb:R,R=0;for(p=d;;){d=p+1|0;V+=e;G+=e;yb+=e;R+=J;f[b>>3]=M;a[P>>2]=a[b>>2];a[P+4>>2]=a[b+4>>2];f[b>>3]=L;a[N>>2]=a[b>>2];a[N+4>>2]=a[b+4>>2];var W=L+R;Ec(F,M+G/3,W);a[y]=a[t];a[y+1]=a[t+1];a[y+2]=a[t+2];a[y+3]=a[t+3];p=T+V;Ec(D,p,W);a[v]=a[x];a[v+1]=a[x+1];a[v+2]=a[x+2];a[v+3]=a[x+3];Ec(A,p,Q);a[i]=a[m];a[i+1]=a[m+1];a[i+2]=a[m+2];a[i+3]=a[m+3];W=K-R;Ec(C,p,W);a[q]=a[r];a[q+1]=a[r+1];a[q+2]=a[r+2];a[q+3]=a[r+3];Ec(E,H+yb/3,W);a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];f[b>>3]=H;a[ea>>2]=a[b>>2];a[ea+4>>2]=a[b+4>>2];f[b>>3]=K;a[wa>>2]=a[b>>2];a[wa+4>>2]=a[b+4>>2];p=(I+108|0)>>2;var X=a[p];if(0!=(X|0)){var ba=X+24|0;0==(a[a[a[I+16>>2]+20>>2]+152>>2]&1|0)?(W=X+32|0,ba|=0):(W=ba|0,ba=X+32|0);var W=(a[b>>2]=a[W>>2],a[b+4>>2]=a[W+4>>2],f[b>>3]),ba=(a[b>>2]=a[ba>>2],a[b+4>>2]=a[ba+4>>2],f[b>>3]),ma=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3])+V+.5*ba,X=X+56|0;f[b>>3]=ma;a[X>>2]=a[b>>2];a[X+4>>2]=a[b+4>>2];X=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]);ma=a[p]+64|0;f[b>>3]=X;a[ma>>2]=a[b>>2];a[ma+4>>2]=a[b+4>>2];n[a[p]+81|0]=1;V=ba>e?V+(ba-e):V;R=R+Z<W?R+(W-Z):R}Nd(I,a[I+12>>2],Fb,7);if((d|0)==(g|0)){break}p=d;I=a[c+(d<<2)>>2]}}h=B}function ik(c,d,g,e,l){var p,j,k,r,q,m,i,x,v,t,y,z,B=h;h=h+16080|0;var F=B+16e3,D=B+16016,A=B+16032,C=B+16048,E=B+16064,I=a[c+(d<<2)>>2];j=a[I+16>>2];var e=.5*e/(g|0),Z=2<e?e:2;z=(j+32|0)>>2;var T=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]),e=(j+40|0)>>2,K=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),M=I+28|0,L=I+36|0,M=(a[b>>2]=a[M>>2],a[b+4>>2]=a[M+4>>2],f[b>>3])+T,L=(a[b>>2]=a[L>>2],a[b+4>>2]=a[L+4>>2],f[b>>3])+K;k=I+68|0;var H=I+76|0,T=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])+T,H=(a[b>>2]=a[H>>2],a[b+4>>2]=a[H+4>>2],f[b>>3])+K;j=j+96|0;var G=.5*(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);j=K+G;var J=3*(j-L),R=3*(j-H);if(0<(g|0)){var Y=(M<T?-1:1)*Z,P=B|0,N=B+8|0;y=(B+16|0)>>2;t=F>>2;v=(B+32|0)>>2;x=D>>2;var Q=.5*(M+T);i=(B+48|0)>>2;m=A>>2;q=(B+64|0)>>2;r=C>>2;k=(B+80|0)>>2;j=E>>2;var ea=B+96|0,wa=B+104|0,Fb=B|0,g=g+d|0,V=0,J=G<J?G:J,R=G<R?G:R;for(p=d;;){d=p+1|0;G+=l;J+=l;R+=l;V+=Y;f[b>>3]=M;a[P>>2]=a[b>>2];a[P+4>>2]=a[b+4>>2];f[b>>3]=L;a[N>>2]=a[b>>2];a[N+4>>2]=a[b+4>>2];var W=M+V;Ec(F,W,L+J/3);a[y]=a[t];a[y+1]=a[t+1];a[y+2]=a[t+2];a[y+3]=a[t+3];p=K+G;Ec(D,W,p);a[v]=a[x];a[v+1]=a[x+1];a[v+2]=a[x+2];a[v+3]=a[x+3];Ec(A,Q,p);a[i]=a[m];a[i+1]=a[m+1];a[i+2]=a[m+2];a[i+3]=a[m+3];W=T-V;Ec(C,W,p);a[q]=a[r];a[q+1]=a[r+1];a[q+2]=a[r+2];a[q+3]=a[r+3];Ec(E,W,H+R/3);a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];f[b>>3]=T;a[ea>>2]=a[b>>2];a[ea+4>>2]=a[b+4>>2];f[b>>3]=H;a[wa>>2]=a[b>>2];a[wa+4>>2]=a[b+4>>2];p=(I+108|0)>>2;var X=a[p];if(0!=(X|0)){var ba=X+24|0;if(0==(a[a[a[I+16>>2]+20>>2]+152>>2]&1|0)){var W=X+32|0,ma=ba|0}else{W=ba|0,ma=X+32|0}ba=(a[b>>2]=a[W>>2],a[b+4>>2]=a[W+4>>2],f[b>>3]);W=(a[b>>2]=a[ma>>2],a[b+4>>2]=a[ma+4>>2],f[b>>3]);ma=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])+G+.5*ba;X=X+64|0;f[b>>3]=ma;a[X>>2]=a[b>>2];a[X+4>>2]=a[b+4>>2];X=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]);ma=a[p]+56|0;f[b>>3]=X;a[ma>>2]=a[b>>2];a[ma+4>>2]=a[b+4>>2];n[a[p]+81|0]=1;G=ba>l?G+(ba-l):G;V+Z<W&&(V+=W-Z)}Nd(I,a[I+12>>2],Fb,7);if((d|0)==(g|0)){break}p=d;I=a[c+(d<<2)>>2]}}h=B}function So(c,d,g,e,l){var p,j,k,r,q,i,w,x,v,t,y,z,B=h;h=h+16080|0;var F=B+16e3,D=B+16016,A=B+16032,C=B+16048,E=B+16064,I=a[c+(d<<2)>>2];j=a[I+16>>2];var l=.5*l/(g|0),Z=2<l?l:2;z=(j+32|0)>>2;var T=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]),l=(j+40|0)>>2,K=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]),M=I+28|0,L=I+36|0,M=(a[b>>2]=a[M>>2],a[b+4>>2]=a[M+4>>2],f[b>>3])+T,L=(a[b>>2]=a[L>>2],a[b+4>>2]=a[L+4>>2],f[b>>3])+K,G=I+68|0;k=I+76|0;G=(a[b>>2]=a[G>>2],a[b+4>>2]=a[G+4>>2],f[b>>3])+T;K=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])+K;j=j+104|0;var H=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),J=3*(M+H-T),R=3*(G+H-T);if(0<(g|0)){var Y=(L<K?-1:1)*Z,P=B|0,N=B+8|0;y=(B+16|0)>>2;t=F>>2;v=(B+32|0)>>2;x=D>>2;var Q=.5*(L+K);w=(B+48|0)>>2;i=A>>2;q=(B+64|0)>>2;r=C>>2;k=(B+80|0)>>2;j=E>>2;var ea=B+96|0,wa=B+104|0,Fb=B|0,g=g+d|0,V=H,J=H<J?H:J,H=H<R?H:R,R=0;for(p=d;;){d=p+1|0;V+=e;J+=e;H+=e;R+=Y;f[b>>3]=M;a[P>>2]=a[b>>2];a[P+4>>2]=a[b+4>>2];f[b>>3]=L;a[N>>2]=a[b>>2];a[N+4>>2]=a[b+4>>2];var W=L+R;Ec(F,M-J/3,W);a[y]=a[t];a[y+1]=a[t+1];a[y+2]=a[t+2];a[y+3]=a[t+3];p=T-V;Ec(D,p,W);a[v]=a[x];a[v+1]=a[x+1];a[v+2]=a[x+2];a[v+3]=a[x+3];Ec(A,p,Q);a[w]=a[i];a[w+1]=a[i+1];a[w+2]=a[i+2];a[w+3]=a[i+3];W=K-R;Ec(C,p,W);a[q]=a[r];a[q+1]=a[r+1];a[q+2]=a[r+2];a[q+3]=a[r+3];Ec(E,G-H/3,W);a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];f[b>>3]=G;a[ea>>2]=a[b>>2];a[ea+4>>2]=a[b+4>>2];f[b>>3]=K;a[wa>>2]=a[b>>2];a[wa+4>>2]=a[b+4>>2];p=(I+108|0)>>2;var X=a[p];if(0!=(X|0)){var ba=X+24|0;0==(a[a[a[I+16>>2]+20>>2]+152>>2]&1|0)?(W=X+32|0,ba|=0):(W=ba|0,ba=X+32|0);var W=(a[b>>2]=a[W>>2],a[b+4>>2]=a[W+4>>2],f[b>>3]),ba=(a[b>>2]=a[ba>>2],a[b+4>>2]=a[ba+4>>2],f[b>>3]),ma=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3])-V-.5*ba,X=X+56|0;f[b>>3]=ma;a[X>>2]=a[b>>2];a[X+4>>2]=a[b+4>>2];X=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]);ma=a[p]+64|0;f[b>>3]=X;a[ma>>2]=a[b>>2];a[ma+4>>2]=a[b+4>>2];n[a[p]+81|0]=1;V=ba>e?V+(ba-e):V;R=R+Z<W?R+(W-Z):R}Nd(I,a[I+12>>2],Fb,7);if((d|0)==(g|0)){break}p=d;I=a[c+(d<<2)>>2]}}h=B}function Ro(c,d,g,e,l){var p,j,k,r,q,i,w,x,v,t,y,z,B=h;h=h+16080|0;var F=B+16e3,D=B+16016,A=B+16032,C=B+16048,E=B+16064,I=a[c+(d<<2)>>2];j=a[I+16>>2];var e=.5*e/(g|0),Z=2<e?e:2;z=(j+32|0)>>2;var T=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]),e=(j+40|0)>>2,K=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),M=I+28|0,L=I+36|0,M=(a[b>>2]=a[M>>2],a[b+4>>2]=a[M+4>>2],f[b>>3])+T,L=(a[b>>2]=a[L>>2],a[b+4>>2]=a[L+4>>2],f[b>>3])+K;k=I+68|0;var H=I+76|0,T=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])+T,H=(a[b>>2]=a[H>>2],a[b+4>>2]=a[H+4>>2],f[b>>3])+K;j=j+96|0;var G=.5*(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),J=3*(L+G-K),R=3*(H+G-K);if(0<(g|0)){var Y=(M<T?-1:1)*Z,P=B|0,N=B+8|0;y=(B+16|0)>>2;t=F>>2;v=(B+32|0)>>2;x=D>>2;var Q=.5*(M+T);w=(B+48|0)>>2;i=A>>2;q=(B+64|0)>>2;r=C>>2;k=(B+80|0)>>2;j=E>>2;var ea=B+96|0,wa=B+104|0,Fb=B|0,g=g+d|0,J=G<J?G:J,R=G<R?G:R,V=0;for(p=d;;){d=p+1|0;G+=l;J+=l;R+=l;V+=Y;f[b>>3]=M;a[P>>2]=a[b>>2];a[P+4>>2]=a[b+4>>2];f[b>>3]=L;a[N>>2]=a[b>>2];a[N+4>>2]=a[b+4>>2];var W=M+V;Ec(F,W,L-J/3);a[y]=a[t];a[y+1]=a[t+1];a[y+2]=a[t+2];a[y+3]=a[t+3];p=K-G;Ec(D,W,p);a[v]=a[x];a[v+1]=a[x+1];a[v+2]=a[x+2];a[v+3]=a[x+3];Ec(A,Q,p);a[w]=a[i];a[w+1]=a[i+1];a[w+2]=a[i+2];a[w+3]=a[i+3];W=T-V;Ec(C,W,p);a[q]=a[r];a[q+1]=a[r+1];a[q+2]=a[r+2];a[q+3]=a[r+3];Ec(E,W,H-R/3);a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];f[b>>3]=T;a[ea>>2]=a[b>>2];a[ea+4>>2]=a[b+4>>2];f[b>>3]=H;a[wa>>2]=a[b>>2];a[wa+4>>2]=a[b+4>>2];p=(I+108|0)>>2;var X=a[p];if(0!=(X|0)){var ba=X+24|0;if(0==(a[a[a[I+16>>2]+20>>2]+152>>2]&1|0)){var W=X+32|0,ma=ba|0}else{W=ba|0,ma=X+32|0}ba=(a[b>>2]=a[W>>2],a[b+4>>2]=a[W+4>>2],f[b>>3]);W=(a[b>>2]=a[ma>>2],a[b+4>>2]=a[ma+4>>2],f[b>>3]);ma=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])-G-.5*ba;X=X+64|0;f[b>>3]=ma;a[X>>2]=a[b>>2];a[X+4>>2]=a[b+4>>2];X=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]);ma=a[p]+56|0;f[b>>3]=X;a[ma>>2]=a[b>>2];a[ma+4>>2]=a[b+4>>2];n[a[p]+81|0]=1;G=ba>l?G+(ba-l):G;V+Z<W&&(V+=W-Z)}Nd(I,a[I+12>>2],Fb,7);if((d|0)==(g|0)){break}p=d;I=a[c+(d<<2)>>2]}}h=B}function Ec(c,d,g){var e=c|0;f[b>>3]=d;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=g;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function jk(c,d){var g,e,l,p,j,k,r=h;h=h+96|0;var q=r+64,i=r+80;if(6!=n[c+124|0]<<24>>24){k=0==d<<24>>24;var w=a[(k?c+116|0:c+112|0)>>2];g=Vg(c)>>2;k?(g=a[g],k=g>>2,0==(a[k+2]|0)?(g=a[k],i=g|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),k=g+8|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),e=r>>2,j=g>>2,a[e]=a[j],a[e+1]=a[j+1],a[e+2]=a[j+2],a[e+3]=a[j+3],e=(r+16|0)>>2,j=(g+16|0)>>2,a[e]=a[j],a[e+1]=a[j+1],a[e+2]=a[j+2],a[e+3]=a[j+3],e=(r+32|0)>>2,j=(g+32|0)>>2,a[e]=a[j],a[e+1]=a[j+1],a[e+2]=a[j+2],a[e+3]=a[j+3],j=(r+48|0)>>2,g=(g+48|0)>>2,a[j]=a[g],a[j+1]=a[g+1],a[j+2]=a[g+2],a[j+3]=a[g+3],zc(q,r|0,.1,0,0),g=q|0,j=q+8|0,q=k,k=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])):(i=g+16|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),q=g+24|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),g=a[k],k=g|0,g=g+8|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),j=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]))):(k=a[g+1]-1|0,g=a[g],j=g>>2,q=g+(48*k&-1)|0,0==(a[((48*k&-1)+12>>2)+j]|0)?(e=a[((48*k&-1)+4>>2)+j],g=e-1|0,j=a[q>>2],q=(g<<4)+j|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),k=(g<<4)+j+8|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),p=r>>2,l=((e-4<<4)+j|0)>>2,a[p]=a[l],a[p+1]=a[l+1],a[p+2]=a[l+2],a[p+3]=a[l+3],p=(r+16|0)>>2,l=((e-3<<4)+j|0)>>2,a[p]=a[l],a[p+1]=a[l+1],a[p+2]=a[l+2],a[p+3]=a[l+3],l=(r+32|0)>>2,e=((e-2<<4)+j|0)>>2,a[l]=a[e],a[l+1]=a[e+1],a[l+2]=a[e+2],a[l+3]=a[e+3],e=(r+48|0)>>2,g=((g<<4)+j|0)>>2,a[e]=a[g],a[e+1]=a[g+1],a[e+2]=a[g+2],a[e+3]=a[g+3],zc(i,r|0,.9,0,0),g=i|0,j=i+8|0,i=q,q=k,k=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])):(i=g+(48*k&-1)+32|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),g=g+(48*k&-1)+40|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),j=a[((48*k&-1)+4>>2)+j]-1|0,q=a[q>>2],k=(j<<4)+q|0,j=(j<<4)+q+8|0,q=g,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])),j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]));g=c|0;k=Math.atan2(j-q,k-i)+3.141592653589793*(lc(g,a[1345505],-25,-180)/180);g=10*lc(g,a[1345504],1,0);j=w+56|0;f[b>>3]=i+g*Math.cos(k);a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];i=w+64|0;f[b>>3]=q+g*Math.sin(k);a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];n[w+81|0]=1}h=r}function Uo(b){var c=xa(b);if((c|0)<(a[1322498]|0)){c=a[1322497]}else{if(c=c+11|0,a[1322498]=c,c=Oa(a[1322497],c),a[1322497]=c,0==(c|0)){return 0}}var g=n[b];if(0==g<<24>>24){var e=c}else{for(;;){var b=b+1|0,d=g&255,e=c+1|0;n[c]=0==((65<=d&&90>=d)|0)?g:se(d)&255;g=n[b];if(0==g<<24>>24){break}else{c=e}}c=a[1322497]}n[e]=0;return c}function Vo(c,d,g){var e,l,p,j,k,r,q,m,w,x,v,t,y,z,B,F,D=d>>2,A=0,C=h;h=h+108|0;var E=C+12;F=E>>2;var I=C+20;B=I>>2;var Z=C+28;z=Z>>2;var T=C+36;y=T>>2;var K=C+44;t=K>>2;var M=C+52;v=M>>2;var L=C+60;x=L>>2;var G=C+68;w=G>>2;var H=C+76;m=H>>2;var J=C+84;q=J>>2;var R=C+92;r=R>>2;var Y=C+96;k=Y>>2;var P=C+100;j=P>>2;var N=C+104;p=N>>2;a[D+8]=g;for(var Q=c;;){if(32==n[Q]<<24>>24){Q=Q+1|0}else{break}}a[p]=255;var ea=n[Q];if(35==ea<<24>>24){if(2<(gd(Q,5333116,(i=h,h=h+16|0,a[i>>2]=R,a[i+4>>2]=Y,a[i+8>>2]=P,a[i+12>>2]=N,i))|0)){if(0==(g|0)){var wa=(a[r]>>>0)/255;f[b>>3]=wa;a[y]=a[b>>2];a[y+1]=a[b+4>>2];var Fb=(a[k]>>>0)/255;f[b>>3]=Fb;a[t]=a[b>>2];a[t+1]=a[b+4>>2];var V=(a[j]>>>0)/255;f[b>>3]=V;a[v]=a[b>>2];a[v+1]=a[b+4>>2];var W=(a[p]>>>0)/255,X=Fb<V?Fb:V,ba=Fb>V?Fb:V,ma=ba<wa?wa:ba;if(0<ma){var ib=ma-(X>wa?wa:X),U=ib/ma;if(0<U){var aa=(ma-wa)/ib,O=(ma-Fb)/ib,ga=(ma-V)/ib,Tb=60*(ma==wa?ga-O:ma==Fb?aa+2-ga:ma!=V?0:O+4-aa),da=0>Tb?Tb+360:Tb,ua=U}else{var da=0,ua=U}}else{ua=da=0}f[b>>3]=da/360;a[E>>2]=a[b>>2];a[E+4>>2]=a[b+4>>2];f[b>>3]=ma;a[Z>>2]=a[b>>2];a[Z+4>>2]=a[b+4>>2];f[b>>3]=ua;a[I>>2]=a[b>>2];a[I+4>>2]=a[b+4>>2];var Da=(a[b>>2]=a[F],a[b+4>>2]=a[F+1],f[b>>3]),Ja=d|0;f[b>>3]=Da;a[Ja>>2]=a[b>>2];a[Ja+4>>2]=a[b+4>>2];var Ab=(a[b>>2]=a[B],a[b+4>>2]=a[B+1],f[b>>3]),ra=d+8|0;f[b>>3]=Ab;a[ra>>2]=a[b>>2];a[ra+4>>2]=a[b+4>>2];var ia=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]),ya=d+16|0;f[b>>3]=ia;a[ya>>2]=a[b>>2];a[ya+4>>2]=a[b+4>>2];var ja=d+24|0;f[b>>3]=W;a[ja>>2]=a[b>>2];a[ja+4>>2]=a[b+4>>2];var la=0}else{if(1==(g|0)){n[d]=a[r]&255,n[d+1|0]=a[k]&255,n[d+2|0]=a[j]&255,n[d+3|0]=a[p]&255}else{if(4==(g|0)){var va=d|0;f[b>>3]=(a[r]>>>0)/255;a[va>>2]=a[b>>2];a[va+4>>2]=a[b+4>>2];var oa=d+8|0;f[b>>3]=(a[k]>>>0)/255;a[oa>>2]=a[b>>2];a[oa+4>>2]=a[b+4>>2];var ka=d+16|0;f[b>>3]=(a[j]>>>0)/255;a[ka>>2]=a[b>>2];a[ka+4>>2]=a[b+4>>2];var Ea=d+24|0;f[b>>3]=(a[p]>>>0)/255;a[Ea>>2]=a[b>>2];a[Ea+4>>2]=a[b+4>>2]}else{if(2==(g|0)){a[D]=Math.floor(((65535*a[r]&-1)>>>0)/255),a[d+4>>2]=Math.floor(((65535*a[k]&-1)>>>0)/255),a[D+2]=Math.floor(((65535*a[j]&-1)>>>0)/255),a[d+12>>2]=Math.floor(((65535*a[p]&-1)>>>0)/255)}else{if(3==(g|0)){var Ka=(a[r]>>>0)/255;f[b>>3]=Ka;a[y]=a[b>>2];a[y+1]=a[b+4>>2];var Na=(a[k]>>>0)/255;f[b>>3]=Na;a[t]=a[b>>2];a[t+1]=a[b+4>>2];var Ba=(a[j]>>>0)/255;f[b>>3]=Ba;a[v]=a[b>>2];a[v+1]=a[b+4>>2];kk(Ka,Na,Ba,L,G,H,J);n[d]=255*((a[b>>2]=a[x],a[b+4>>2]=a[x+1],f[b>>3])&-1)&255;n[d+1|0]=255*((a[b>>2]=a[w],a[b+4>>2]=a[w+1],f[b>>3])&-1)&255;n[d+2|0]=255*((a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3])&-1)&255;n[d+3|0]=255*((a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3])&-1)&255}}}}la=0}h=C;return la}var Wa=n[Q]}else{Wa=ea}46==Wa<<24>>24?A=1955:10>((Wa&255)-48|0)>>>0&&(A=1955);do{if(1955==A){var ha=xa(Q);if((ha|0)<(a[1315019]|0)){var fa=a[1315018]}else{var Ra=ha+11|0;a[1315019]=Ra;var bb=Oa(a[1315018],Ra);a[1315018]=bb;if(0==(bb|0)){return la=-1,h=C,la}fa=bb}for(var Xa=Q,Sa=fa;;){var sa=Xa+1|0,Va=n[Xa];if(44==Va<<24>>24){var Ta=32}else{if(0==Va<<24>>24){break}else{Ta=Va}}n[Sa]=Ta;Xa=sa;Sa=Sa+1|0}n[Sa]=0;if(3==(gd(fa,5360884,(i=h,h=h+12|0,a[i>>2]=E,a[i+4>>2]=I,a[i+8>>2]=Z,i))|0)){var Aa=(a[b>>2]=a[F],a[b+4>>2]=a[F+1],f[b>>3]),fb=1>Aa?Aa:1,Ca=0<fb?fb:0;f[b>>3]=Ca;a[F]=a[b>>2];a[F+1]=a[b+4>>2];var Ya=(a[b>>2]=a[B],a[b+4>>2]=a[B+1],f[b>>3]),$a=1>Ya?Ya:1,La=0<$a?$a:0;f[b>>3]=La;a[B]=a[b>>2];a[B+1]=a[b+4>>2];var pa=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]),Ga=1>pa?pa:1,Fa=0<Ga?Ga:0;f[b>>3]=Fa;a[z]=a[b>>2];a[z+1]=a[b+4>>2];if(2==(g|0)){ei(Ca,La,Fa,T,K,M);var qa=d;a[D]=65535*(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3])&-1;a[qa+4>>2]=65535*(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3])&-1;a[D+2]=65535*(a[b>>2]=a[v],a[b+4>>2]=a[v+1],f[b>>3])&-1;a[qa+12>>2]=65535}else{if(3==(g|0)){ei(Ca,La,Fa,T,K,M);var nb=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]);kk(nb,(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3]),(a[b>>2]=a[v],a[b+4>>2]=a[v+1],f[b>>3]),L,G,H,J);var jb=d;n[d]=255*((a[b>>2]=a[x],a[b+4>>2]=a[x+1],f[b>>3])&-1)&255;n[jb+1|0]=255*((a[b>>2]=a[w],a[b+4>>2]=a[w+1],f[b>>3])&-1)&255;n[jb+2|0]=255*((a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3])&-1)&255;n[jb+3|0]=255*((a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3])&-1)&255}else{if(1==(g|0)){ei(Ca,La,Fa,T,K,M);var cb=d;n[d]=255*(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3])&255;n[cb+1|0]=255*(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3])&255;n[cb+2|0]=255*(a[b>>2]=a[v],a[b+4>>2]=a[v+1],f[b>>3])&255;n[cb+3|0]=-1}else{if(4==(g|0)){ei(Ca,La,Fa,T,K,M);var na=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),kb=d|0;f[b>>3]=na;a[kb>>2]=a[b>>2];a[kb+4>>2]=a[b+4>>2];var Kb=(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3]),Ma=d+8|0;f[b>>3]=Kb;a[Ma>>2]=a[b>>2];a[Ma+4>>2]=a[b+4>>2];var Ha=(a[b>>2]=a[v],a[b+4>>2]=a[v+1],f[b>>3]),lb=d+16|0;f[b>>3]=Ha;a[lb>>2]=a[b>>2];a[lb+4>>2]=a[b+4>>2];var rb=d+24|0;f[b>>3]=1;a[rb>>2]=a[b>>2];a[rb+4>>2]=a[b+4>>2]}else{if(0==(g|0)){var ab=d|0;f[b>>3]=Ca;a[ab>>2]=a[b>>2];a[ab+4>>2]=a[b+4>>2];var db=d+8|0;f[b>>3]=La;a[db>>2]=a[b>>2];a[db+4>>2]=a[b+4>>2];var ob=d+16|0;f[b>>3]=Fa;a[ob>>2]=a[b>>2];a[ob+4>>2]=a[b+4>>2];var pb=d+24|0;f[b>>3]=1;a[pb>>2]=a[b>>2];a[pb+4>>2]=a[b+4>>2]}}}}}la=0;h=C;return la}}}while(0);var ub=Wo(Q);a[C>>2]=ub;if(0==(ub|0)){return la=-1,h=C,la}var gb=a[1315017];if(0==(gb|0)){A=1973}else{var sb=a[gb>>2];if(n[sb]<<24>>24!=n[ub]<<24>>24){A=1973}else{if(0==($(sb,ub)|0)){var Ia=gb}else{A=1973}}}if(1973==A){var vb=yh(C,5260084,2491,12,284),Ia=a[1315017]=vb}if(0==(Ia|0)){if(1==(g|0)){n[d+2|0]=0,n[d+1|0]=0,n[d]=0,n[d+3|0]=-1}else{if(3==(g|0)){Ib=0,n[d]=Ib&255,Ib>>=8,n[d+1|0]=Ib&255,Ib>>=8,n[d+2|0]=Ib&255,Ib>>=8,n[d+3|0]=Ib&255}else{if(0==(g|0)){var Ua=d+24|0;l=d>>2;a[l]=0;a[l+1]=0;a[l+2]=0;a[l+3]=0;a[l+4]=0;a[l+5]=0;f[b>>3]=1;a[Ua>>2]=a[b>>2];a[Ua+4>>2]=a[b+4>>2]}else{if(2==(g|0)){a[D+2]=0,a[d+4>>2]=0,a[D]=0,a[d+12>>2]=65535}else{if(4==(g|0)){var ta=d+24|0;e=d>>2;a[e]=0;a[e+1]=0;a[e+2]=0;a[e+3]=0;a[e+4]=0;a[e+5]=0;f[b>>3]=1;a[ta>>2]=a[b>>2];a[ta+4>>2]=a[b+4>>2]}}}}}la=1}else{if(0==(g|0)){var Za=d|0;f[b>>3]=ca[Ia+4|0]/255;a[Za>>2]=a[b>>2];a[Za+4>>2]=a[b+4>>2];var qb=d+8|0;f[b>>3]=ca[Ia+5|0]/255;a[qb>>2]=a[b>>2];a[qb+4>>2]=a[b+4>>2];var Bb=d+16|0;f[b>>3]=ca[Ia+6|0]/255;a[Bb>>2]=a[b>>2];a[Bb+4>>2]=a[b+4>>2];var sc=d+24|0;f[b>>3]=ca[Ia+10|0]/255;a[sc>>2]=a[b>>2];a[sc+4>>2]=a[b+4>>2]}else{if(1==(g|0)){n[d]=n[Ia+7|0],n[d+1|0]=n[Ia+8|0],n[d+2|0]=n[Ia+9|0],n[d+3|0]=n[Ia+10|0]}else{if(3==(g|0)){var xb=(ca[Ia+7|0]|0)/255;f[b>>3]=xb;a[y]=a[b>>2];a[y+1]=a[b+4>>2];var za=(ca[Ia+8|0]|0)/255;f[b>>3]=za;a[t]=a[b>>2];a[t+1]=a[b+4>>2];var Nb=(ca[Ia+9|0]|0)/255;f[b>>3]=Nb;a[v]=a[b>>2];a[v+1]=a[b+4>>2];kk(xb,za,Nb,L,G,H,J);n[d]=255*((a[b>>2]=a[x],a[b+4>>2]=a[x+1],f[b>>3])&-1)&255;n[d+1|0]=255*((a[b>>2]=a[w],a[b+4>>2]=a[w+1],f[b>>3])&-1)&255;n[d+2|0]=255*((a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3])&-1)&255;n[d+3|0]=255*((a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3])&-1)&255}else{if(2==(g|0)){a[D]=Math.floor(((65535*ca[Ia+7|0]&-1)>>>0)/255),a[d+4>>2]=Math.floor(((65535*ca[Ia+8|0]&-1)>>>0)/255),a[D+2]=Math.floor(((65535*ca[Ia+9|0]&-1)>>>0)/255),a[d+12>>2]=Math.floor(((65535*ca[Ia+10|0]&-1)>>>0)/255)}else{if(4==(g|0)){var Jb=d|0;f[b>>3]=(ca[Ia+7|0]|0)/255;a[Jb>>2]=a[b>>2];a[Jb+4>>2]=a[b+4>>2];var Pa=d+8|0;f[b>>3]=(ca[Ia+8|0]|0)/255;a[Pa>>2]=a[b>>2];a[Pa+4>>2]=a[b+4>>2];var eb=d+16|0;f[b>>3]=(ca[Ia+9|0]|0)/255;a[eb>>2]=a[b>>2];a[eb+4>>2]=a[b+4>>2];var zb=d+24|0;f[b>>3]=(ca[Ia+10|0]|0)/255;a[zb>>2]=a[b>>2];a[zb+4>>2]=a[b+4>>2]}}}}}la=0}h=C;return la}function Vg(b){for(var c=0;;){var g=a[b+24>>2];if(0!=(g|0)){c=2019;break}if(0==n[b+124|0]<<24>>24){c=2018;break}b=a[b+128>>2]}if(2019==c){return g}2018==c&&P()}function kk(c,d,g,e,l,p,j){j>>=2;p>>=2;l>>=2;e>>=2;f[b>>3]=1-c;a[e]=a[b>>2];a[e+1]=a[b+4>>2];f[b>>3]=1-d;a[l]=a[b>>2];a[l+1]=a[b+4>>2];f[b>>3]=1-g;a[p]=a[b>>2];a[p+1]=a[b+4>>2];c=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);d=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]);c=c<d?c:d;f[b>>3]=c;a[j]=a[b>>2];a[j+1]=a[b+4>>2];d=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]);c=d<c?d:c;f[b>>3]=c;a[j]=a[b>>2];a[j+1]=a[b+4>>2];c=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])-c;f[b>>3]=c;a[e]=a[b>>2];a[e+1]=a[b+4>>2];e=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3]);e=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3])-e;f[b>>3]=e;a[l]=a[b>>2];a[l+1]=a[b+4>>2];j=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3]);j=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])-j;f[b>>3]=j;a[p]=a[b>>2];a[p+1]=a[b+4>>2]}function ei(c,d,g,e,l,p){p>>=2;l>>=2;e>>=2;if(0<d){var j=1>c?6*c:0,c=j&-1,k=j-(c|0),j=(1-d)*g,h=(1-k*d)*g,d=(1-(1-k)*d)*g;2==(c|0)?(f[b>>3]=j,a[e]=a[b>>2],a[e+1]=a[b+4>>2],f[b>>3]=g,a[l]=a[b>>2],a[l+1]=a[b+4>>2],f[b>>3]=d,a[p]=a[b>>2],a[p+1]=a[b+4>>2]):5==(c|0)?(f[b>>3]=g,a[e]=a[b>>2],a[e+1]=a[b+4>>2],f[b>>3]=j,a[l]=a[b>>2],a[l+1]=a[b+4>>2],f[b>>3]=h,a[p]=a[b>>2],a[p+1]=a[b+4>>2]):4==(c|0)?(f[b>>3]=d,a[e]=a[b>>2],a[e+1]=a[b+4>>2],f[b>>3]=j,a[l]=a[b>>2],a[l+1]=a[b+4>>2],f[b>>3]=g,a[p]=a[b>>2],a[p+1]=a[b+4>>2]):3==(c|0)?(f[b>>3]=j,a[e]=a[b>>2],a[e+1]=a[b+4>>2],f[b>>3]=h,a[l]=a[b>>2],a[l+1]=a[b+4>>2],f[b>>3]=g,a[p]=a[b>>2],a[p+1]=a[b+4>>2]):0==(c|0)?(f[b>>3]=g,a[e]=a[b>>2],a[e+1]=a[b+4>>2],f[b>>3]=d,a[l]=a[b>>2],a[l+1]=a[b+4>>2],f[b>>3]=j,a[p]=a[b>>2],a[p+1]=a[b+4>>2]):1==(c|0)&&(f[b>>3]=h,a[e]=a[b>>2],a[e+1]=a[b+4>>2],f[b>>3]=g,a[l]=a[b>>2],a[l+1]=a[b+4>>2],f[b>>3]=j,a[p]=a[b>>2],a[p+1]=a[b+4>>2])}else{f[b>>3]=g,a[e]=a[b>>2],a[e+1]=a[b+4>>2],f[b>>3]=g,a[l]=a[b>>2],a[l+1]=a[b+4>>2],f[b>>3]=g,a[p]=a[b>>2],a[p+1]=a[b+4>>2]}}function Wo(b){var c=n[b];if(98==c<<24>>24){return b}var g=b+1|0;if(0==(Pd(g,5348400,4)|0)|119==c<<24>>24||0==(Pd(g,5348392,4)|0)|108==c<<24>>24||0==(Pd(g,5348380,8)|0)){return b}a:do{if(47==c<<24>>24){var e=oc(g,47);if(0==(e|0)){e=g}else{if(47!=n[g]<<24>>24){e=0==(oe(5348372,g,4)|0)?e+1|0:b}else{e=a[1315020];do{if(0!=(e|0)&&0!=n[e]<<24>>24&&0!=(oe(5348372,e,3)|0)){e=Xo(a[1315020],b+2|0);break a}}while(0);e=b+2|0}}}else{e=a[1315020],e=0==(e|0)?b:0==n[e]<<24>>24?b:0==(oe(5348372,e,3)|0)?b:Xo(a[1315020],b)}}while(0);return b=Uo(e)}function Xo(b,c){var g=h,e=xa(b)+xa(c)|0;(e+3|0)<(a[1313354]|0)?e=a[1313353]:(e=e+13|0,a[1313354]=e,e=Oa(a[1313353],e),a[1313353]=e);Pa(e,5348364,(i=h,h=h+8|0,a[i>>2]=b,a[i+4>>2]=c,i));h=g;return a[1313353]}function Yo(b){var c,g=h;h=h+1112|0;var e=g+1024,d=g+1096,f=g+1100,j=g+1104,k=g+1108,r=a[1345521];0==(r|0)&&(r=Bc(5381600,5380200),a[1345521]=r);r=J[a[r>>2]](r,b,512);if(0!=(r|0)){return h=g,r}r=vg(b,5345784);if(0==(r|0)){return aa(0,5365368,(i=h,h=h+4|0,a[i>>2]=b,i)),h=g,0}c=g|0;for(var q=0,m=0;;){if(0==(Hf(c,1024,r)|0)){var w=q,x=m;break}m=4==(gd(c,5360956,(i=h,h=h+16|0,a[i>>2]=d,a[i+4>>2]=f,a[i+8>>2]=j,a[i+12>>2]=k,i))|0)?1:m;q=37==n[c]<<24>>24?q:0==(zh(c,5360728)|0)?q:1;if(!(0==(m|0)|0==(q|0))){w=q;x=m;break}}0==(x|0)?(aa(0,5358620,(i=h,h=h+4|0,a[i>>2]=b,i)),w=0):(x=Za(64),c=x>>2,a[c+8]=a[d>>2],q=x+36|0,a[q>>2]=a[f>>2],a[c+10]=a[j>>2]-a[d>>2]|0,a[q>>2]=a[k>>2]-a[f>>2]|0,a[c+2]=b,b=a[1345371],a[1345371]=b+1|0,a[c+3]=b,mm(r,e),e=a[e+28>>2],b=Za(e+1|0),a[c+13]=b,$e(r,0,0),nm(b,e,1,r),n[b+e|0]=0,e=a[1345521],J[a[e>>2]](e,x,1),n[x+16|0]=w&255,w=x);Jf(r);h=g;return w}function fi(b,c,g){var e=0,d=h,f=0!=(c|0);a:do{if(f){for(var j=1,k=0;;){if(0==j<<24>>24){break a}var r=a[c+(k<<2)>>2];if(0==(r|0)){e=2111;break a}j=0==n[r]<<24>>24?0:j;k=k+1|0}}else{e=2111}}while(0);a:do{if(2111==e&&(r=a[g>>2],0!=(r|0))){j=b;for(k=g;;){if(A(j,r),A(j,5344600),k=k+4|0,r=a[k>>2],0==(r|0)){break a}}}}while(0);if(f&&(e=a[c>>2],0!=(e|0))){for(g=0;;){do{if(0!=n[e]<<24>>24){if(j=Oh(e),0==(j|0)){aa(0,5345240,(i=h,h=h+4|0,a[i>>2]=e,i))}else{if(f=vg(j,5345784),0==(f|0)){aa(0,5338560,(i=h,h=h+4|0,a[i>>2]=j,i))}else{j=sn(f);a:do{if(0!=(j|0)){for(k=j;;){if(A(b,k),k=sn(f),0==(k|0)){break a}}}}while(0);A(b,5344600);Jf(f)}}}}while(0);g=g+1|0;e=a[c+(g<<2)>>2];if(0==(e|0)){break}}}h=d}function lk(a,b){var g=0,e=b;a:for(;;){var c=n[e];b:do{if(0==c<<24>>24){break a}else{if(37==c<<24>>24){if(37!=n[e+1|0]<<24>>24){var d=e}else{c=e+2|0;do{if(0==(oe(c,5335788,3)|0)){d=e}else{if(0==(oe(c,5332920,5)|0)){d=e}else{if(0==(oe(c,5329948,3)|0)){d=e}else{if(0==(oe(c,5327348,7)|0)){d=e}else{d=e;break b}}}}}while(0);for(;;){var f=n[d];if(0==f<<24>>24|10==f<<24>>24){g=2144;break}else{if(13==f<<24>>24){g=2142;break}}d=d+1|0}do{if(2144==g){var g=0,k=d+1|0}else{if(2142==g){if(g=0,e=d+1|0,10!=n[e]<<24>>24){k=e}else{e=d+2|0;continue a}}}}while(0);e=0==f<<24>>24?d:k;continue a}}else{d=e}}}while(0);for(;;){var h=n[d];if(13==h<<24>>24){g=2148;break}else{if(0==h<<24>>24|10==h<<24>>24){g=2150;break}}Zo(a,h<<24>>24);d=d+1|0}if(2148==g){if(g=0,e=d+1|0,10!=n[e]<<24>>24){var q=e,g=2151}else{var i=d+2|0}}else{2150==g&&(q=d+1|0,g=2151)}2151==g&&(g=0,i=0==h<<24>>24?d:q);Zo(a,10);e=i}}function mk(b,c){var g=h;if(0==(c|0)){var e;e=0;var d=b,f=0;b:for(;;){for(;;){var j=n[d];if(0==j<<24>>24){var k=f;e=2047;break b}if(127>(j&255)){d=d+1|0}else{break}}if(-64==(j&-4)<<24>>24){d=d+2|0,f=1}else{k=2;e=2046;break}}e=2047==e||2046==e?k:Wb;1==(e|0)?e=Fj(b):(2==(e|0)&&!n[5247564]&&(aa(0,5367696,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),n[5247564]=1),e=b)}else{e=Fj(b)}0==(a[1311887]|0)&&ac(5247548,0,0);f=a[1311888];f>>>0<a[1311889]>>>0||(qa(5247548,1),f=a[1311888]);a[1311888]=f+1|0;n[f]=40;for(f=e;;){j=n[f];if(40==j<<24>>24|41==j<<24>>24|92==j<<24>>24){j=a[1311888],j>>>0<a[1311889]>>>0||(qa(5247548,1),j=a[1311888]),a[1311888]=j+1|0,n[j]=92}else{if(0==j<<24>>24){break}}j=a[1311888];j>>>0<a[1311889]>>>0||(qa(5247548,1),j=a[1311888]);k=n[f];a[1311888]=j+1|0;n[j]=k;f=f+1|0}f=a[1311888];f>>>0<a[1311889]>>>0||(qa(5247548,1),f=a[1311888]);a[1311888]=f+1|0;n[f]=41;(e|0)!=(b|0)&&E(e);e=a[1311888];if(e>>>0<a[1311889]>>>0){return n[e]=0,e=a[1311887],a[1311888]=e,h=g,e}qa(5247548,1);e=a[1311888];n[e]=0;e=a[1311887];a[1311888]=e;h=g;return e}function $o(c,d){var g,e,l,p,j=c>>2,k=0,r=h;h=h+8|0;p=r>>2;l=(c+44|0)>>2;a[l]=da(96);var q=c|0,m=U(q,5343916);0==(m|0)?(m=wg(5343584),0!=(m|0)&&(e=m,k=2193)):(e=m,k=2193);if(2193==k){k=Oa(a[1313348],xa(e)+12|0);a[1313348]=k;for(var m=5343232,w=k,x=m+12;m<x;m++,w++){n[w]=n[m]}fe(k,e);k=a[1313348];if(0===k){Ha(ta.i)}else{if(k=Vd(k),m=k.indexOf("="),""===k||-1===k.indexOf("=")){Ha(ta.i)}else{if(e=k.slice(0,m),k=k.slice(m+1),!(e in Fd)||Fd[e]!==k){Fd[e]=k,Ah(Fd)}}}}e=n;k=c+151|0;m=h;w=na(c|0,Q(a[c+32>>2]|0,5374112),5373892);0==(Eb(w,5373700)|0)?w=1:0==(Eb(w,5373428)|0)?w=1:0==(Eb(w,5373096)|0)?w=1:0==(Eb(w,5377948)|0)?w=1:0==(Eb(w,5372864)|0)?w=1:0==(Eb(w,5372604)|0)?w=1:0==(Eb(w,5372404)|0)?w=1:0==(Eb(w,5372108)|0)?w=2:0==(Eb(w,5371916)|0)?w=2:(0!=(Eb(w,5373892)|0)&&0!=(Eb(w,5371664)|0)&&aa(0,5371376,(i=h,h=h+4|0,a[i>>2]=w,i)),w=0);h=m;e[k]=w&255;e=(c+32|0)>>2;k=lc(q,Q(a[e]|0,5342812),0,0);m=a[l]|0;f[b>>3]=k;a[m>>2]=a[b>>2];a[m+4>>2]=a[b+4>>2];k=U(q,5377096);do{if(0!=(k|0)){if(m=n[k],66==m<<24>>24){if(0==($(k,5341872)|0)){m=2;break}}else{if(82==m<<24>>24){m=0==($(k,5341520)|0)?3:0;break}else{if(76==m<<24>>24){if(0==($(k,5364168)|0)){m=1;break}}else{m=0;break}}}}m=0}while(0);k=m<<2;a[j+38]=0==d<<24>>24?k:k|m;k=lc(q,Q(a[e]|0,5341172),.25,.02);f[b>>3]=k;a[p]=a[b>>2];a[p+1]=a[b+4>>2];k*=72;a[j+64]=(0>k?k-.5:k+.5)&-1;k=$b(q,Q(a[e]|0,5371672),0);0==(k|0)?(f[b>>3]=.5,a[p]=a[b>>2],a[p+1]=a[b+4>>2],p=.5):(0==(gd(k,5347784,(i=h,h=h+4|0,a[i>>2]=r,i))|0)?(f[b>>3]=.5,a[p]=a[b>>2],a[p+1]=a[b+4>>2],p=.5):(m=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]),.02>m?(f[b>>3]=.02,a[p]=a[b>>2],a[p+1]=a[b+4>>2],p=.02):p=m),0!=(zh(k,5340520)|0)&&(n[c+284|0]=1));p*=72;a[j+65]=(0>p?p-.5:p+.5)&-1;n[c+249|0]=ve(q,Q(a[e]|0,5340240),0)&255;a[j+63]=yj($b(q,Q(a[e]|0,5339932),0),5253360,5253376);ap(c);j=nk(c,5339664,a[l]+64|0);n[a[l]+80|0]=j;nk(c,5339368,a[l]+48|0);j=Ph(U(q,5339012));n[a[l]+82|0]=j;j=U(q,5338668);0==(j|0)?(j=U(q,5338348),0!=(j|0)?(j=n[j],n[a[l]+81|0]=(108==j<<24>>24|76==j<<24>>24)&1):(j=U(q,5338096),0!=(j|0)&&(j=Xd(j),n[a[l]+81|0]=j))):(j=90==(Ee(j)|0)&1,n[a[l]+81|0]=j);a[1345568]=yj(U(q,5337836),5253328,5253344);n[5382112]=Ph(U(q,5337504));a[1345163]=0;j=a[l]+24|0;f[b>>3]=0;a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];j=U(q,5337284);0==(j|0)?k=2225:0==n[j]<<24>>24?k=2225:(g=j,k=2227);2225==k&&(j=U(q,5337048),0!=(j|0)&&0!=n[j]<<24>>24&&(g=j,k=2227));2227==k&&(g=Oe(g,Ac),j=a[l]+24|0,f[b>>3]=g,a[j>>2]=a[b>>2],a[j+4>>2]=a[b+4>>2]);ok(c);a[1345481]=Q(a[e]|0,5336780);g=(c+40|0)>>2;a[1345359]=Q(a[a[g]>>2]|0,5370656);a[1345343]=Q(a[a[g]>>2]|0,5373184);a[1345349]=Q(a[a[g]>>2]|0,5335872);a[1345369]=Q(a[a[g]>>2]|0,5335528);a[1345365]=Q(a[a[g]>>2]|0,5335284);a[1345345]=Q(a[a[g]>>2]|0,5334992);a[1345361]=Q(a[a[g]>>2]|0,5334740);a[1345362]=Q(a[a[g]>>2]|0,5334476);a[1345363]=Q(a[a[g]>>2]|0,5334160);a[1345357]=Q(a[a[g]>>2]|0,5332600);a[1345342]=Q(a[a[g]>>2]|0,5333916);a[1345348]=Q(a[a[g]>>2]|0,5340240);a[1345351]=Q(a[a[g]>>2]|0,5333672);a[1345353]=Q(a[a[g]>>2]|0,5336780);a[1345347]=Q(a[a[g]>>2]|0,5333276);a[1345350]=Q(a[a[g]>>2]|0,5333004);a[1345346]=Q(a[a[g]>>2]|0,5332700);a[1345352]=Q(a[a[g]>>2]|0,5338348);a[1345367]=Q(a[a[g]>>2]|0,5332468);a[1345364]=Q(a[a[g]>>2]|0,5332136);a[1345358]=Q(a[a[g]>>2]|0,5331808);a[1345354]=Q(a[a[g]>>2]|0,5331560);a[1345356]=Q(a[a[g]>>2]|0,5331176);a[1345360]=Q(a[a[g]>>2]|0,5330924);a[1345368]=Q(a[a[g]>>2]|0,5330564);a[1345344]=Q(a[a[g]>>2]|0,5330236);Q(a[a[g]>>2]|0,5330016);a[1345491]=Q(a[a[g]+4>>2]|0,5367600);a[1345517]=Q(a[a[g]+4>>2]|0,5335528);a[1345510]=Q(a[a[g]+4>>2]|0,5334740);a[1345511]=Q(a[a[g]+4>>2]|0,5334476);a[1345512]=Q(a[a[g]+4>>2]|0,5334160);a[1345507]=Q(a[a[g]+4>>2]|0,5332600);a[1345490]=Q(a[a[g]+4>>2]|0,5333916);a[1345506]=Q(a[a[g]+4>>2]|0,5329512);a[1345513]=Q(a[a[g]+4>>2]|0,5329308);a[1345520]=Q(a[a[g]+4>>2]|0,5329076);a[1345518]=Q(a[a[g]+4>>2]|0,5328808);a[1345508]=Q(a[a[g]+4>>2]|0,5328576);a[1345492]=Q(a[a[g]+4>>2]|0,5328276);a[1345501]=Q(a[a[g]+4>>2]|0,5328012);a[1345502]=Q(a[a[g]+4>>2]|0,5327680);a[1345503]=Q(a[a[g]+4>>2]|0,5327424);a[1345504]=Q(a[a[g]+4>>2]|0,5327008);a[1345505]=Q(a[a[g]+4>>2]|0,5326768);a[1345499]=Q(a[a[g]+4>>2]|0,5326556);a[1345495]=Q(a[a[g]+4>>2]|0,5340240);a[1345494]=Q(a[a[g]+4>>2]|0,5334992);a[1345514]=Q(a[a[g]+4>>2]|0,5326244);a[1345519]=Q(a[a[g]+4>>2]|0,5326008);a[1345515]=Q(a[a[g]+4>>2]|0,5325788);a[1345500]=Q(a[a[g]+4>>2]|0,5331176);a[1345516]=Q(a[a[g]+4>>2]|0,5330564);a[1345493]=Q(a[a[g]+4>>2]|0,5325516);a[1345509]=Q(a[a[g]+4>>2]|0,5378800);a[1345498]=Q(a[a[g]+4>>2]|0,5333672);g=h;j=U(c|0,5349136);0==(j|0)?j=0:0==n[j]<<24>>24?j=0:(e=yt(j,0,80),0==(e|0)&&(aa(0,5373216,(i=h,h=h+4|0,a[i>>2]=a[c+12>>2],i)),aa(3,5352308,(i=h,h=h+4|0,a[i>>2]=j,i))),j=e);h=g;a[a[l]+88>>2]=j;g=U(q,5378532);0!=(g|0)&&0!=n[g]<<24>>24&&(q=Zb(g,q),a[a[l]+92>>2]=q);h=r}function ap(c){var d=U(c|0,5375600);if(0!=(d|0)){var g=n[d];if(0!=g<<24>>24){var e=g<<24>>24;101==(e|0)?101==g<<24>>24&&0==($(d,5374680)|0)&&(a[a[c+44>>2]+84>>2]=5):102==(e|0)?102==g<<24>>24&&0==($(d,5374360)|0)&&(a[a[c+44>>2]+84>>2]=2):99==(e|0)?99==g<<24>>24&&0==($(d,5375024)|0)&&(a[a[c+44>>2]+84>>2]=3):97==(e|0)?97==g<<24>>24&&0==($(d,5375304)|0)&&(a[a[c+44>>2]+84>>2]=4):(d=Oe(d,Ac),0<d&&(c=c+44|0,a[a[c>>2]+84>>2]=1,c=a[c>>2]+16|0,f[b>>3]=d,a[c>>2]=a[b>>2],a[c+4>>2]=a[b+4>>2]))}}}function nk(c,d,g){var e,l=h;h=h+20|0;e=l>>2;var p=l+8,j=l+16;n[j]=0;c=U(c|0,d);if(0==(c|0)){return h=l,0}if(1<(gd(c,5376272,(i=h,h=h+12|0,a[i>>2]=l,a[i+4>>2]=p,a[i+8>>2]=j,i))|0)){if(d=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),0<d&&(p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),0<p)){return e=72*d,c=g|0,f[b>>3]=(0>e?e-.5:e+.5)&-1|0,a[c>>2]=a[b>>2],a[c+4>>2]=a[b+4>>2],e=72*p,g=g+8|0,f[b>>3]=(0>e?e-.5:e+.5)&-1|0,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],j=33==n[j]<<24>>24&1,h=l,j}}n[j]=0;if(0>=(gd(c,5375948,(i=h,h=h+8|0,a[i>>2]=l,a[i+4>>2]=j,i))|0)){return h=l,0}e=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);if(0>=e){return h=l,0}e*=72;e=(0>e?e-.5:e+.5)&-1|0;p=g|0;f[b>>3]=e;a[p>>2]=a[b>>2];a[p+4>>2]=a[b+4>>2];g=g+8|0;f[b>>3]=e;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];h=l;return 33==n[j]<<24>>24&1}function ok(c){var d,g=c|0,e=U(g,5332600);if(0!=(e|0)&&0!=n[e]<<24>>24){d=(c+32|0)>>2;var l=a[d]+149|0;n[l]|=8;var p=0!=(Ve(e)|0)?2:0,j=lc(g,Q(a[d]|0,5334740),14,1),l=c+48|0;a[l>>2]=we(g,e,p,j,na(g,Q(a[d]|0,5334476),5377304),na(g,Q(a[d]|0,5334160),5374748));e=U(g,5376820);p=0!=(e|0);e=(a[d]|0)==(c|0)?p&&116==n[e]<<24>>24?1:0:p&&98==n[e]<<24>>24?0:1;g=U(g,5376560);0==(g|0)?g=e:(g=n[g],g=108==g<<24>>24?e|2:114==g<<24>>24?e|4:e);n[c+283|0]=g;e=a[d];(e|0)!=(c|0)&&(l=a[l>>2],d=l+24|0,l=l+32|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])+16,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])+8,g=0!=(g&1)<<24>>24,0==(a[e+152>>2]&1|0)?(g=g?2:0,e=(g<<4)+c+84|0,f[b>>3]=d,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],c=(g<<4)+c+92|0,f[b>>3]=l):(g=g?1:3,e=(g<<4)+c+84|0,f[b>>3]=l,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],c=(g<<4)+c+92|0,f[b>>3]=d),a[c>>2]=a[b>>2],a[c+4>>2]=a[b+4>>2])}}function vm(b){var c,g=b+44|0;c=(g|0)>>2;var e=a[c],d=a[e+88>>2];0!=(d|0)&&(zt(d),e=a[c]);d=a[e+92>>2];0!=(d|0)&&(E(d),e=a[c]);E(e);a[c]=0;tf(a[b+48>>2]);b=g>>2;for(c=b+61;b<c;b++){a[b]=0}}function pk(c,d,g,e){var l,p,j,k=d+68|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),r=d+76|0,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),c=c+348|0;Td(g,5347532,(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]));Td(g,5366668,k/72);Td(g,5366668,r/72);Bd(10,g);c=(d+20|0)>>2;k=ha(a[c]);a:do{if(0!=(k|0)){r=k;for(j=r>>2;;){if(0==n[r+134|0]<<24>>24){Qc(g,5351404,Fc(a[j+3]));var q=r+32|0;p=r+40|0;var m=g,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);Td(m,5366668,q/72);Td(m,5366668,p/72);m=a[j+30];0==n[m+82|0]<<24>>24?(m=qk(a[m>>2]),p=r|0):(p=r|0,m=Fc(tb(p,a[a[1345357]+8>>2])));q=r+48|0;Td(g,5366668,(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]));q=r+56|0;Td(g,5366668,(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]));Qc(g,5366668,m);Qc(g,5366668,na(p,a[1345345],5354244));Qc(g,5366668,a[a[j+6]>>2]);Qc(g,5366668,na(p,a[1345369],5374748));j=na(p,a[1345365],5338228);Qc(g,5366668,0==n[j]<<24>>24?na(p,a[1345369],5332120):j);Bd(10,g)}r=sa(a[c],r);if(0==(r|0)){break a}else{j=r>>2}}}}while(0);r=ha(a[c]);if(0!=(r|0)){e=0==e<<24>>24;for(k=d+28|0;;){j=zb(d,r);a:do{if(0!=(j|0)){m=j;for(p=m>>2;;){if(e){var w=q=5338228}else{l=a[p+1],0==(l|0)?w=q=5338228:(q=a[l+4>>2],w=a[l+8>>2])}l=(m+24|0)>>2;var x=a[l];b:do{if(0!=(x|0)){var v=a[x+4>>2];c:do{if(0<(v|0)){for(var t=a[x>>2],y=0,z=0;;){if(y=a[t+(48*z&-1)+4>>2]+y|0,z=z+1|0,(z|0)>=(v|0)){var B=y;break c}}}else{B=0}}while(0);Qc(g,0,5374900);v=a[p+4];bp(g,a[v+12>>2],n[v+134|0],q);v=a[p+3];bp(g,a[v+12>>2],n[v+134|0],w);v=g;t=B;y=h;h=h+1024|0;mb(5366668,v);z=y|0;Pa(z,5335676,(i=h,h=h+4|0,a[i>>2]=t,i));mb(z,v);h=y;t=a[l];if(0<(a[t+4>>2]|0)){v=0;for(z=t;;){y=a[z>>2];t=a[y+(48*v&-1)>>2];y=a[y+(48*v&-1)+4>>2];if(0<(y|0)){for(z=0;;){var F=(z<<4)+t|0,D=(z<<4)+t+8|0,A=g,F=(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]),D=(a[b>>2]=a[D>>2],a[b+4>>2]=a[D+4>>2],f[b>>3]);Td(A,5366668,F/72);Td(A,5366668,D/72);z=z+1|0;if((z|0)==(y|0)){break}}t=a[l]}else{t=z}v=v+1|0;if((v|0)<(a[t+4>>2]|0)){z=t}else{break b}}}}}while(0);p=m+108|0;q=a[p>>2];0!=(q|0)&&(Qc(g,5366668,qk(a[q>>2])),p=a[p>>2],q=p+56|0,l=p+64|0,p=g,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),Td(p,5366668,q/72),Td(p,5366668,l/72));p=m|0;Qc(g,5366668,na(p,a[1345494],5354244));Qc(g,5366668,na(p,a[1345517],5374748));Bd(10,g);m=Db(a[k>>2],m);if(0==(m|0)){break a}else{p=m>>2}}}}while(0);r=sa(a[c],r);if(0==(r|0)){break}}}mb(5329912,g)}function Td(c,d,g){var e=h;h=h+1024|0;0!=(d|0)&&mb(d,c);d=e|0;Pa(d,5349196,(i=h,h=h+8|0,f[b>>3]=g,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i));mb(d,c);h=e}function Qc(a,b,g){0!=(b|0)&&mb(b,a);mb(g,a)}function qk(a){var a=dc(a),b=Fc(a);Qb(a);return b}function bp(a,b,g,c){b=0==g<<24>>24?Fc(b):qk(oc(b,58)+1|0);Qc(a,5366668,b);0!=(c|0)&&0!=n[c]<<24>>24&&Qc(a,5331664,Fc(c))}function rk(c,d,g){var e,l,p,j,k,r,q,m,w,x=0,v=h;h=h+2064|0;var t=v+2048;w=(c+206|0)>>1;var y=2<fc[w];Ue(1);ac(t,1024,v+1024|0);m=(c+40|0)>>2;ic(c,a[a[m]>>2]|0,5327264,196);ic(c,a[a[m]>>2]|0,5378144,196);a[1345343]=ic(c,a[a[m]>>2]|0,5373184,196);a[1345359]=ic(c,a[a[m]>>2]|0,5370656,196);ic(c,a[a[m]+4>>2]|0,5327264,260);var z=c+149|0,B=n[z];if(0==(B&16)<<24>>24){var F=B}else{ic(c,a[a[m]>>2]|0,5370116,196),F=n[z]}if(0==(F&1)<<24>>24){var D=F}else{ic(c,a[a[m]+4>>2]|0,5367680,260),D=n[z]}if(0==(D&32)<<24>>24){var A=D}else{ic(c,a[a[m]+4>>2]|0,5370116,260),A=n[z]}if(0==(A&2)<<24>>24){var Gb=A}else{ic(c,a[a[m]+4>>2]|0,5365336,260),Gb=n[z]}0!=(Gb&4)<<24>>24&&ic(c,a[a[m]+4>>2]|0,5362776,260);q=(c+48|0)>>2;var E=c|0;if(0!=(a[q]|0)){ic(c,E,5367680,188);ic(c,E,5360700,188);ic(c,E,5358600,188);var I=a[q];if(0!=n[a[I>>2]]<<24>>24){var Z=v|0,T=I+64|0,K=I+56|0,M=(a[b>>2]=a[T>>2],a[b+4>>2]=a[T+4>>2],f[b>>3]),L=(a[b>>2]=a[K>>2],a[b+4>>2]=a[K+4>>2],f[b>>3]);Pa(Z,5357008,(i=h,h=h+16|0,f[b>>3]=L,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=M,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));Pc(E,5367680,Z);var G=a[q],H=G+24|0,J=(a[b>>2]=a[H>>2],a[b+4>>2]=a[H+4>>2],f[b>>3]),R=G+32|0,Y=(a[b>>2]=a[R>>2],a[b+4>>2]=a[R+4>>2],f[b>>3]);Pa(Z,5355400,(i=h,h=h+8|0,f[b>>3]=J/72,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i));Pc(E,5360700,Z);Pa(Z,5355400,(i=h,h=h+8|0,f[b>>3]=Y/72,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i));Pc(E,5358600,Z)}}var P=ic(c,E,5341732,188),N=c+20|0,Q=ha(a[N>>2]);a:do{if(0==(Q|0)){var ea=0,wa=0,Fb=t|0}else{var V=v|0;r=(t+4|0)>>2;k=(t+8|0)>>2;var W=t|0;j=W>>2;for(var X=c+28|0,ba=0,ma=0,ib=Q;;){var aa=ib,da=ib+24|0;p=da>>2;var O=ib+32|0,ga=O,Tb=(a[b>>2]=a[ga>>2],a[b+4>>2]=a[ga+4>>2],f[b>>3]);if(y){var ca=O+8|0,ua=(a[b>>2]=a[ca>>2],a[b+4>>2]=a[ca+4>>2],f[b>>3]),Da=da+124|0,Ja=a[Da>>2]+16|0,Ab=72*(a[b>>2]=a[Ja>>2],a[b+4>>2]=a[Ja+4>>2],f[b>>3]);Pa(V,5352124,(i=h,h=h+24|0,f[b>>3]=Tb,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=ua,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],f[b>>3]=Ab,a[i+16>>2]=a[b>>2],a[i+20>>2]=a[b+4>>2],i));Cb(t,V);b:do{if(3<fc[w]){for(var ra=3;;){var ia=(ra<<3)+a[Da>>2]|0,ya=72*(a[b>>2]=a[ia>>2],a[b+4>>2]=a[ia+4>>2],f[b>>3]);Pa(V,5350572,(i=h,h=h+8|0,f[b>>3]=ya,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i));Cb(t,V);var ja=ra+1|0;if((ja|0)<(fc[w]|0)){ra=ja}else{break b}}}}while(0);var la=a[r];if(la>>>0<a[k]>>>0){var va=la}else{qa(t,1),va=a[r]}n[va]=0;var oa=a[j];a[r]=oa;Pc(ib|0,5327264,oa)}else{var ka=ib+40|0,Ea=(a[b>>2]=a[ka>>2],a[b+4>>2]=a[ka+4>>2],f[b>>3]);Pa(V,5357008,(i=h,h=h+16|0,f[b>>3]=Tb,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=Ea,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));Pc(ib|0,5327264,V)}var Ka=ib+96|0,Na=(a[b>>2]=a[Ka>>2],a[b+4>>2]=a[Ka+4>>2],f[b>>3])/72;Pa(V,5349196,(i=h,h=h+8|0,f[b>>3]=Na,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i));var Ba=ib|0;hc(Ba,a[a[1345359]+8>>2],V);var Wa=ib+104|0,fa=ib+112|0,xa=((a[b>>2]=a[Wa>>2],a[b+4>>2]=a[Wa+4>>2],f[b>>3])+(a[b>>2]=a[fa>>2],a[b+4>>2]=a[fa+4>>2],f[b>>3]))/72;Pa(V,5349196,(i=h,h=h+8|0,f[b>>3]=xa,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i));hc(Ba,a[a[1345343]+8>>2],V);var Ra=a[ib+124>>2];if(0!=(Ra|0)){var bb=Ra+64|0,Xa=Ra+56|0,Sa=(a[b>>2]=a[bb>>2],a[b+4>>2]=a[bb+4>>2],f[b>>3]),na=(a[b>>2]=a[Xa>>2],a[b+4>>2]=a[Xa+4>>2],f[b>>3]);Pa(V,5357008,(i=h,h=h+16|0,f[b>>3]=na,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=Sa,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));Pc(Ba,5370116,V)}var Va=a[p];do{if(0==($(a[Va>>2],5348196)|0)){cp(aa,a[p+1],t);var Ta=t+4|0,Aa=a[Ta>>2];Aa>>>0>a[t>>2]>>>0&&(a[Ta>>2]=Aa-1|0);var fb=a[r];if(fb>>>0<a[k]>>>0){var Ca=fb}else{qa(t,1),Ca=a[r]}n[Ca]=0;var Ya=a[j];a[r]=Ya;Pc(Ba,5378144,Ya)}else{var $a;if($a=0!=(a[1345344]|0)){var La;if(0==(Va|0)){var pa=0,Ga=pa&1}else{pa=244==(a[a[Va+4>>2]>>2]|0),Ga=pa&1}La=Ga;$a=0!=La<<24>>24}if($a){var Fa=a[p+1],ta=Fa+8|0,nb=a[ta>>2];if(3>(nb|0)){var jb=U(Ba,5347768),cb=0==(jb|0)?8:Ee(jb),Oa=3>(cb|0)?8:cb;if(0<(Oa|0)){var kb=Oa,x=36}}else{kb=nb,x=36}b:do{if(36==x){for(var x=0,Kb=Fa+40|0,Ma=da+24|0,Ha=kb|0,lb=da+32|0,rb=0;;){if(0<(rb|0)){var ab=a[r];if(ab>>>0<a[k]>>>0){var db=ab}else{qa(t,1),db=a[r]}a[r]=db+1|0;n[db]=32}if(2<(a[ta>>2]|0)){var ob=a[Kb>>2],pb=(rb<<4)+ob|0,ub=(a[b>>2]=a[pb>>2],a[b+4>>2]=a[pb+4>>2],f[b>>3])/72,gb=(rb<<4)+ob+8|0,sb=(a[b>>2]=a[gb>>2],a[b+4>>2]=a[gb+4>>2],f[b>>3])/72;Pa(V,5347272,(i=h,h=h+16|0,f[b>>3]=ub,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=sb,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i))}else{var Ia=6.283185307179586*((rb|0)/Ha),vb=.5*(a[b>>2]=a[Ma>>2],a[b+4>>2]=a[Ma+4>>2],f[b>>3])*Math.cos(Ia),Ua=.5*(a[b>>2]=a[lb>>2],a[b+4>>2]=a[lb+4>>2],f[b>>3])*Math.sin(Ia);Pa(V,5347272,(i=h,h=h+16|0,f[b>>3]=vb,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=Ua,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i))}Cb(t,V);var Za=rb+1|0;if((Za|0)==(kb|0)){break b}else{rb=Za}}}}while(0);var eb=a[a[1345344]+8>>2],qb=a[r];if(qb>>>0<a[k]>>>0){var Bb=qb}else{qa(t,1),Bb=a[r]}n[Bb]=0;var sc=a[j];a[r]=sc;hc(Ba,eb,sc)}}}while(0);b:do{if(0<(a[1345163]|0)){var xb=zb(c,ib);if(0==(xb|0)){var za=ma,Nb=ba}else{var Jb=ba,hb=ma,mb=xb;for(l=mb>>2;;){do{if(6==n[mb+124|0]<<24>>24){var Ic=hb,wb=Jb}else{e=(mb+24|0)>>2;var tb=a[e];if(0==(tb|0)){Ic=hb,wb=Jb}else{c:do{if(0<(a[tb+4>>2]|0)){for(var Qa=0,Ib=Jb,Eb=hb,Hb=tb;;){if(0<(Qa|0)){var Ub=a[r];if(Ub>>>0<a[k]>>>0){var Mb=Ub}else{qa(t,1),Mb=a[r]}a[r]=Mb+1|0;n[Mb]=59;var Pb=a[e]}else{Pb=Hb}var Lb=a[Pb>>2];if(0==(a[Lb+(48*Qa&-1)+8>>2]|0)){var Sb=Ib,Zb=Pb,gc=Lb}else{var ec=Lb+(48*Qa&-1)+16|0,jc=(a[b>>2]=a[ec>>2],a[b+4>>2]=a[ec+4>>2],f[b>>3]),cc=Lb+(48*Qa&-1)+24|0,pc=(a[b>>2]=a[cc>>2],a[b+4>>2]=a[cc+4>>2],f[b>>3]);Pa(V,5346788,(i=h,h=h+16|0,f[b>>3]=jc,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=pc,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));Cb(t,V);var Qb=a[e],Sb=1,Zb=Qb,gc=a[Qb>>2]}if(0==(a[gc+(48*Qa&-1)+12>>2]|0)){var hd=Eb,qd=Zb,Vb=gc}else{var Yb=gc+(48*Qa&-1)+32|0,Jc=(a[b>>2]=a[Yb>>2],a[b+4>>2]=a[Yb+4>>2],f[b>>3]),dc=gc+(48*Qa&-1)+40|0,lc=(a[b>>2]=a[dc>>2],a[b+4>>2]=a[dc+4>>2],f[b>>3]);Pa(V,5346380,(i=h,h=h+16|0,f[b>>3]=Jc,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=lc,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));Cb(t,V);var $b=a[e],hd=1,qd=$b,Vb=a[$b>>2]}d:do{if(0<(a[Vb+(48*Qa&-1)+4>>2]|0)){for(var bc=0,oc=qd;;){if(0<(bc|0)){var kc=a[r];if(kc>>>0<a[k]>>>0){var uc=kc}else{qa(t,1),uc=a[r]}a[r]=uc+1|0;n[uc]=32;var tc=a[e]}else{tc=oc}var Bc=a[a[tc>>2]+(48*Qa&-1)>>2],ne=(bc<<4)+Bc+8|0,Kc=(bc<<4)+Bc|0,rc=(a[b>>2]=a[ne>>2],a[b+4>>2]=a[ne+4>>2],f[b>>3]),Hc=(a[b>>2]=a[Kc>>2],a[b+4>>2]=a[Kc+4>>2],f[b>>3]);Pa(V,5357008,(i=h,h=h+16|0,f[b>>3]=Hc,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=rc,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));Cb(t,V);var Cc=bc+1|0,vc=a[e];if((Cc|0)<(a[a[vc>>2]+(48*Qa&-1)+4>>2]|0)){bc=Cc,oc=vc}else{var Dc=vc;break d}}}else{Dc=qd}}while(0);var wc=Qa+1|0;if((wc|0)<(a[Dc+4>>2]|0)){Qa=wc,Ib=Sb,Eb=hd,Hb=Dc}else{var zc=Sb,Ec=hd;break c}}}else{zc=Jb,Ec=hb}}while(0);var Yc=mb|0,xc=a[r];if(xc>>>0<a[k]>>>0){var Fc=xc}else{qa(t,1),Fc=a[r]}n[Fc]=0;var Wc=a[j];a[r]=Wc;Pc(Yc,5327264,Wc);var ae=a[l+27];if(0!=(ae|0)){var Nc=ae+64|0,yc=ae+56|0,Qc=(a[b>>2]=a[Nc>>2],a[b+4>>2]=a[Nc+4>>2],f[b>>3]),Kd=(a[b>>2]=a[yc>>2],a[b+4>>2]=a[yc+4>>2],f[b>>3]);Pa(V,5357008,(i=h,h=h+16|0,f[b>>3]=Kd,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=Qc,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));Pc(Yc,5367680,V)}var Sc=a[l+30];if(0!=(Sc|0)){var bd=Sc+64|0,Vc=Sc+56|0,cd=(a[b>>2]=a[bd>>2],a[b+4>>2]=a[bd+4>>2],f[b>>3]),Zc=(a[b>>2]=a[Vc>>2],a[b+4>>2]=a[Vc+4>>2],f[b>>3]);Pa(V,5357008,(i=h,h=h+16|0,f[b>>3]=Zc,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=cd,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));Pc(Yc,5370116,V)}var nc=a[l+28];if(0!=(nc|0)){var Oc=nc+64|0,Lc=nc+56|0,dd=(a[b>>2]=a[Oc>>2],a[b+4>>2]=a[Oc+4>>2],f[b>>3]),Sd=(a[b>>2]=a[Lc>>2],a[b+4>>2]=a[Lc+4>>2],f[b>>3]);Pa(V,5357008,(i=h,h=h+16|0,f[b>>3]=Sd,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=dd,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));Pc(Yc,5365336,V)}var id=a[l+29];if(0!=(id|0)){var Xc=id+64|0,Gc=id+56|0,$c=(a[b>>2]=a[Xc>>2],a[b+4>>2]=a[Xc+4>>2],f[b>>3]),Rc=(a[b>>2]=a[Gc>>2],a[b+4>>2]=a[Gc+4>>2],f[b>>3]);Pa(V,5357008,(i=h,h=h+16|0,f[b>>3]=Rc,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=$c,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));Pc(Yc,5362776,V)}Ic=Ec;wb=zc}}}while(0);var Mc=Db(a[X>>2],mb);if(0==(Mc|0)){za=Ic;Nb=wb;break b}else{Jb=wb,hb=Ic,mb=Mc,l=mb>>2}}}}else{za=ma,Nb=ba}}while(0);var ad=sa(a[N>>2],ib);if(0==(ad|0)){ea=Nb;wa=za;Fb=W;break a}else{ba=Nb,ma=za,ib=ad}}}}while(0);sk(c,P);Xb(a[Fb>>2],a[t+12>>2]);0!=(C[c+164>>1]&1)<<16>>16&&yn(c);a[d>>2]=ea;a[g>>2]=wa;Ue(0);h=v}function cp(c,d,g){var e,l=h;h=h+1024|0;e=(d+48|0)>>2;var p=a[e];if(0==(p|0)){var p=l|0,j=d+16|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),k=c+32|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),r=c+40|0,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),q=d+40|0,m=d+24|0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])+r,n=d+32|0,n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3])+k;Pa(p,5345340,(i=h,h=h+32|0,f[b>>3]=j+k,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=m,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],f[b>>3]=n,a[i+16>>2]=a[b>>2],a[i+20>>2]=a[b+4>>2],f[b>>3]=q+r,a[i+24>>2]=a[b>>2],a[i+28>>2]=a[b+4>>2],i));Cb(g,p);p=a[e]}if(0<(p|0)){d=d+56|0;for(p=0;!(cp(c,a[a[d>>2]+(p<<2)>>2],g),p=p+1|0,(p|0)>=(a[e]|0));){}}h=l}function sk(c,d){var g=h;h=h+1024|0;var e=g|0,l=c+52|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),p=c+76|0,j=c+60|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),k=c+68|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);Pa(e,5345740,(i=h,h=h+32|0,f[b>>3]=l,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],f[b>>3]=k,a[i+16>>2]=a[b>>2],a[i+20>>2]=a[b+4>>2],f[b>>3]=p,a[i+24>>2]=a[b>>2],a[i+28>>2]=a[b+4>>2],i));l=c|0;hc(l,a[d+8>>2],e);p=c+48|0;k=a[p>>2];0!=(k|0)&&0!=n[a[k>>2]]<<24>>24&&(j=k+64|0,k=k+56|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),Pa(e,5357008,(i=h,h=h+16|0,f[b>>3]=k,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i)),Pc(l,5367680,e),j=a[p>>2],p=j+24|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=j+32|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),Pa(e,5355400,(i=h,h=h+8|0,f[b>>3]=p/72,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i)),Pc(l,5360700,e),Pa(e,5355400,(i=h,h=h+8|0,f[b>>3]=j/72,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i)),Pc(l,5358600,e));e=c+208|0;if(1<=(a[e>>2]|0)){l=c+212|0;for(p=1;!(sk(a[a[l>>2]+(p<<2)>>2],d),p=p+1|0,(p|0)>(a[e>>2]|0));){}}h=g}function gi(b,c,g){var e=h;h=h+1024|0;var d=e|0;Pa(d,5372640,(i=h,h=h+8|0,a[i>>2]=(0>c?c-.5:c+.5)&-1,a[i+4>>2]=(0>g?g-.5:g+.5)&-1,i));Cb(b,d);h=e}function Ch(c,d,g){var e=h;h=h+256|0;if(999==(dp(c,g)|0)){d=tk(c,g),aa(1,5370292,(i=h,h=h+8|0,a[i>>2]=g,a[i+4>>2]=d,i))}else{ep(c,d);var g=e|0,l=d+52|0;if(0==n[a[d+44>>2]+81|0]<<24>>24){var c=l|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),l=d+60|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),p=d+68|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=d+76|0}else{c=d+60|0,c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),l|=0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),p=d+76|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=d+68|0}j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);Pa(g,5345228,(i=h,h=h+16|0,a[i>>2]=(0>c?c-.5:c+.5)&-1,a[i+4>>2]=(0>l?l-.5:l+.5)&-1,a[i+8>>2]=(0>p?p-.5:p+.5)&-1,a[i+12>>2]=(0>j?j-.5:j+.5)&-1,i));fp(d|0,5341732,g)}h=e}function Ui(b,c){var g;g=a[c>>2];var e,d=Za(12);e=d>>2;a[e+1]=0;a[e+2]=Hb(g);g=b+100|0;a[e]=a[g>>2];a[g>>2]=d;e=a[c+4>>2];g=a[e+4>>2];if(0!=(g|0)){var f=g;for(g=f>>2;;){var j=a[g+1];a:do{if(0!=(j|0)){for(var k=e|0,h=0,q=j;;){if(gp(b,a[k>>2],q,a[((20*h&-1)+8>>2)+g],d,f+(20*h&-1)|0),h=h+1|0,q=a[((20*h&-1)+4>>2)+g],0==(q|0)){break a}}}}while(0);g=a[e+12>>2];if(0==(g|0)){break}else{e=e+8|0,f=g,g=f>>2}}}}function bn(b){var c,g=b>>2;c=0;var e=h,d=a[g+19],f=a[g];if(0==(d|0)){c=200}else{if(d=a[d>>2],0==(d|0)){c=200}else{J[d](b)}}if(200==c&&0==(a[g+10]|0)&&(c=(b+36|0)>>2,0==(a[c]|0))){if(0!=n[f+13|0]<<24>>24&&hp(b),b=b+32|0,f=a[b>>2],0==(f|0)){a[c]=a[Fe>>2]}else{if(f=vg(f,5357032),a[c]=f,0==(f|0)){return g=a[a[g+3]+16>>2],b=a[b>>2],c=Kf(a[Ha.d>>2]),J[g](5373436,(i=h,h=h+8|0,a[i>>2]=b,a[i+4>>2]=c,i)),h=e,1}}}if(0==(a[g+37]&1024|0)){return h=e,0}J[a[a[g+3]+16>>2]](5352520,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));h=e;return 1}function hp(b){var c=h;h=h+100|0;var g=a[b+24>>2],e=c|0;0==(g|0)?n[e]=0:Pa(e,5378208,(i=h,h=h+4|0,a[i>>2]=g+1|0,i));var g=a[b+20>>2],d=0==(g|0)?5375500:g,g=b+52|0,f=xa(d)+xa(e)+xa(a[g>>2])+1|0;a[1330499]>>>0<(f+1|0)>>>0?(f=f+11|0,a[1330499]=f,f=gc(a[1330500],f),a[1330500]=f):f=a[1330500];ee(f,d);fe(a[1330500],e);e=a[1330500];e=e+xa(e)|0;Ib=46;n[e]=Ib&255;Ib>>=8;n[e+1|0]=Ib&255;e=Hb(a[g>>2]);g=km(e);d=a[1330500];if(0==(g|0)){var j;fe(d,e)}else{for(;;){if(fe(d,g+1|0),d=a[1330500],f=d+xa(d)|0,Ib=46,n[f]=Ib&255,Ib>>=8,n[f+1|0]=Ib&255,n[g]=0,g=km(e),0==(g|0)){j=d;break}}fe(j,e)}E(e);j=a[1330500];b=b+32|0;a[b>>2]=j;h=c}function A(a,b){pe(a,b,xa(b))}function Zo(a,b){var g=h;h=h+4|0;n[g]=b&255;pe(a,g,1);h=g}function Om(b){var c=a[b+36>>2];if(0!=(c|0)&&0==n[b+140|0]<<24>>24&&0==(a[a[b>>2]+116>>2]|0)){b=(function(a){N.b[a]&&N.b[a].object.m&&(N.b[a].ha||N.b[a].object.m(Ac))});try{if(0===c){for(c=0;c<N.b.length;c++){N.b[c]&&b(c)}}else{b(c)}}catch(g){Ha(ta.r)}}}function G(b,c,g){var e=h;h=h+1028|0;var d=e+1024;a[d>>2]=g;g=e|0;pe(b,g,jm(g,c,a[d>>2]));h=e}function ag(b,c){var g=h;h=h+4|0;pe(b,hi(g,c),a[g>>2]);h=g}function pe(b,c,g){var e=h;if(0==(g|0)|0==(c|0)){return h=e,0}0!=(a[b+148>>2]&1024|0)&&(J[a[a[b+12>>2]+16>>2]](5352520,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Qd());if((ip(b,c,g)|0)==(g|0)){return h=e,g}J[a[a[b+12>>2]+16>>2]](5345376,(i=h,h=h+4|0,a[i>>2]=g,i));Qd()}function ip(b,c,g){var e,d,f=h;e=a[a[b>>2]+116>>2];if(0!=(e|0)){return g=J[e](b,c,g),h=f,g}d=(b+40|0)>>2;var j=a[d];if(0==(j|0)){return g=re(c,1,g,a[b+36>>2]),h=f,g}var k=b+44|0;e=(b+48|0)>>2;var r=a[e];if((a[k>>2]-1-r|0)>>>0<g>>>0){if(r=r+(g+4096)&-4096,a[k>>2]=r,j=gc(j,r),a[d]=j,0==(j|0)){J[a[a[b+12>>2]+16>>2]](5327176,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Qd()}else{var q=j,m=a[e]}}else{q=j,m=r}$d(q+m|0,c,g);b=a[e]+g|0;a[e]=b;n[a[d]+b|0]=0;h=f;return g}function jp(b){var c=h,g=a[b+76>>2];0!=(a[b+148>>2]&1024|0)&&(J[a[a[b+12>>2]+16>>2]](5335768,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Qd());if(0!=(g|0)&&(g=a[g+8>>2],0!=(g|0))){J[g](b);h=c;return}Om(b);g=b+32|0;if(0!=(a[g>>2]|0)){var e=b+36|0,d=a[e>>2];(d|0)!=(a[Fe>>2]|0)&&0==n[b+140|0]<<24>>24&&(0!=(d|0)&&(Jf(d),a[e>>2]=0),a[g>>2]=0)}h=c}function hi(b,c){if(-1e15>c){return a[b>>2]=19,5250888}if(1e15<c){return a[b>>2]=18,5250889}var g=100*c,e=(0>g?g-.5:g+.5)&-1;if(0==(e|0)){return a[b>>2]=1,5340724}for(var g=0>(e|0),d=0,e=g?-e|0:e,f=5251552,j=2;;){var k=(e|0)%10,h=(e|0)/10&-1;0==(k|0)&0==d<<24>>24?k=f:(d=f-1|0,n[d]=(k|48)&255,k=d,d=1);1==(j|0)&&(0!=d<<24>>24&&(k=k-1|0,n[k]=46),d=1);j=j-1|0;if(18<(e+9|0)>>>0|0<(j|0)){e=h,f=k}else{break}}g?(g=k-1|0,n[g]=45):g=k;a[b>>2]=5251552-g|0;return g}function od(b,c,g){var e=h;h=h+4|0;pe(b,hi(e,c),a[e>>2]);pe(b,5366668,1);pe(b,hi(e,g),a[e>>2]);h=e}function xe(c,d,g){var e=d|0,l=d+8|0;od(c,(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]));if(1<(g|0)){for(e=1;;){pe(c,5366668,1);var l=(e<<4)+d|0,p=(e<<4)+d+8|0;od(c,(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]));e=e+1|0;if((e|0)==(g|0)){break}}}}function dp(b,c){var g;g=lf(b,1,c);if(0==(g|0)){return 999}g=a[g+16>>2]>>2;a[b+156>>2]=a[g+1];a[b+144>>2]=a[g+3];a[b+148>>2]=a[g];a[b+152>>2]=a[g+4];return 300}function ep(b,c){var g=h;a[c+172>>2]=b;var e=c+32|0,d=a[e>>2];(d|0)!=(c|0)&&(a[d+172>>2]=b);d=U(c|0,5343224);0!=(d|0)&&999==(dp(b,d)|0)?(e=tk(b,d),aa(1,5370292,(i=h,h=h+8|0,a[i>>2]=d,a[i+4>>2]=e,i))):(d=a[b+144>>2],0!=(d|0)&&(Ue(1),$o(c,a[a[b+152>>2]>>2]&1),a[a[e>>2]+44>>2]=a[c+44>>2],e=a[d>>2],0!=(e|0)&&(J[e](c),e=a[d+4>>2],0!=(e|0)&&(a[c+176>>2]=e)),Ue(0)));h=g}function kp(c,d,g,e){var l,p;l=c>>2;if(1==(d|0)){uk(c,g,e),lp(c),n[c+530|0]=1,n[c+533|0]=1,n[c+529|0]=1}else{if(4==(d|0)){n[c+528|0]=0;if(0==(a[l+89]|0)){var j=.10000000000000009*(g-.5*(a[l+110]>>>0)),d=c+348|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),k=c+512|0;p=(c+332|0)>>2;j=j/(d*(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]))+(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]);f[b>>3]=j;a[p]=a[b>>2];a[p+1]=a[b+4>>2];j=c+520|0;p=(c+340|0)>>2;l=.10000000000000009*(e-.5*(a[l+111]>>>0))/(d*(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]))+(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])}else{p=.10000000000000009*(e-.5*(a[l+111]>>>0)),d=c+348|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),j=c+520|0,j=p/(d*(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])),p=(c+332|0)>>2,j=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])-j,f[b>>3]=j,a[p]=a[b>>2],a[p+1]=a[b+4>>2],j=c+512|0,p=(c+340|0)>>2,l=.10000000000000009*(g-.5*(a[l+110]>>>0))/(d*(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]))+(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])}f[b>>3]=l;a[p]=a[b>>2];a[p+1]=a[b+4>>2];l=d;d=c+348|0;f[b>>3]=1.1*l;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];n[c+529|0]=1}else{3==(d|0)?(uk(c,g,e),n[c+530|0]=1,n[c+533|0]=3,n[c+529|0]=1):2==(d|0)?(n[c+530|0]=1,n[c+533|0]=2,n[c+529|0]=1):5==(d|0)&&(n[c+528|0]=0,p=(c+348|0)>>2,d=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])/1.1,f[b>>3]=d,a[p]=a[b>>2],a[p+1]=a[b+4>>2],0==(a[l+89]|0)?(p=c+512|0,j=.10000000000000009*(g-.5*(a[l+110]>>>0))/(d*(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])),p=(c+332|0)>>2,j=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])-j,f[b>>3]=j,a[p]=a[b>>2],a[p+1]=a[b+4>>2],p=c+520|0,d=.10000000000000009*(e-.5*(a[l+111]>>>0))/(d*(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]))):(j=c+520|0,p=(c+332|0)>>2,j=.10000000000000009*(e-.5*(a[l+111]>>>0))/(d*(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]))+(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]),f[b>>3]=j,a[p]=a[b>>2],a[p+1]=a[b+4>>2],p=c+512|0,d=.10000000000000009*(g-.5*(a[l+110]>>>0))/(d*(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]))),l=(c+340|0)>>2,d=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3])-d,f[b>>3]=d,a[l]=a[b>>2],a[l+1]=a[b+4>>2],n[c+529|0]=1)}}l=c+552|0;f[b>>3]=g;a[l>>2]=a[b>>2];a[l+4>>2]=a[b+4>>2];c=c+560|0;f[b>>3]=e;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function mp(c,d,g){var e,l,p,j,k;k=(c+552|0)>>2;j=c+512|0;p=(d-(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3]))/(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);j=(c+560|0)>>2;e=c+520|0;e=(g-(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3]))/(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);var h=p&-1;if(1>((-1<(h|0)?h:-h|0)|0)){if(h=e&-1,1>((-1<(h|0)?h:-h|0)|0)){return}}h=ca[c+533|0];0==(h|0)?uk(c,d,g):2==(h|0)&&(l=0==(a[c+356>>2]|0),h=c+348|0,h=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]),l?(l=(c+332|0)>>2,p=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3])-p/h,f[b>>3]=p,a[l]=a[b>>2],a[l+1]=a[b+4>>2],p=(c+340|0)>>2,e=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])-e/h,f[b>>3]=e,a[p]=a[b>>2],a[p+1]=a[b+4>>2]):(l=(c+332|0)>>2,e=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3])-e/h,f[b>>3]=e,a[l]=a[b>>2],a[l+1]=a[b+4>>2],e=(c+340|0)>>2,p=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])+p/h,f[b>>3]=p,a[e]=a[b>>2],a[e+1]=a[b+4>>2]),n[c+529|0]=1);f[b>>3]=d;a[k]=a[b>>2];a[k+1]=a[b+4>>2];f[b>>3]=g;a[j]=a[b>>2];a[j+1]=a[b+4>>2]}function np(b,c,g){var e=a[b>>2];if(0==(c|0)){c=Bh(5366640,1);a[b+32>>2]=5365360;var d=c}else{c=vg(c,5345784);if(0==(c|0)){return}tm(c);Vi();d=a[1345658];Jf(c)}if(0!=(d|0)){var c=(e+128|0)>>2,f=a[c];if(0!=(f|0)){var j=a[e+144>>2];0!=(j|0)&&(j=a[j+4>>2],0!=(j|0)&&(J[j](f),f=a[c]));vm(f);Pe(a[c])}a[c]=d;a[d+172>>2]=e;Ch(e,d,g);a[b+572>>2]=0;a[b+568>>2]=0;n[b+529|0]=1}}function uk(c,d,g){var e=h;h=h+48|0;var l=e+32,p;p=0==(a[c+356>>2]|0);var j=c+348|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);if(p){p=c+512|0;var k=c+496|0,d=d/(j*(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]))-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);p=c+520|0;k=c+504|0;j=g/(j*(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]))-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);p=(l|0)>>2;f[b>>3]=d}else{p=c+520|0,k=c+496|0,g=g/(j*(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]))-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),p=c+512|0,k=c+504|0,j=-d/(j*(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]))-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),p=(l|0)>>2,f[b>>3]=g}a[p]=a[b>>2];a[p+1]=a[b+4>>2];d=l+8|0;d>>=2;f[b>>3]=j;a[d]=a[b>>2];a[d+1]=a[b+4>>2];j=l|0;j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);l=l+8|0;l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);d=c+348|0;d=1/(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);g=e+16|0;f[b>>3]=j+d;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];g=e+24|0;f[b>>3]=l+d;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];g=e|0;f[b>>3]=j-d;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];j=e+8|0;f[b>>3]=l-d;a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];l=op(a[a[c>>2]+128>>2],e);j=c+568|0;(l|0)!=(a[j>>2]|0)&&(d=a[c+568>>2],0!=(d|0)&&(g=a[d>>2]<<28>>28,1==(g|0)?(d=d+133|0,n[d]&=-2):2==(g|0)?(d=d+127|0,n[d]&=-2):3==(g|0)&&(d=d+148|0,n[d]&=-2)),a[c+576>>2]=0,a[j>>2]=l,pp(c),n[c+529|0]=1);h=e}function op(b,c){var g,e=0,d=h;g=c>>2;c=h;h=h+32|0;a[c>>2]=a[g];a[c+4>>2]=a[g+1];a[c+8>>2]=a[g+2];a[c+12>>2]=a[g+3];a[c+16>>2]=a[g+4];a[c+20>>2]=a[g+5];a[c+24>>2]=a[g+6];a[c+28>>2]=a[g+7];g=(b+20|0)>>2;var f=b+28|0,j=ha(a[g]);a:for(;0!=(j|0);){for(var k=zb(b,j);0!=(k|0);){var r;b:{var q=k;r=c;var i=Wb,n=h,i=r>>2;r=h;h=h+32|0;a[r>>2]=a[i];a[r+4>>2]=a[i+1];a[r+8>>2]=a[i+2];a[r+12>>2]=a[i+3];a[r+16>>2]=a[i+4];a[r+20>>2]=a[i+5];a[r+24>>2]=a[i+6];a[r+28>>2]=a[i+7];var x=a[q+24>>2];c:do{if(0!=(x|0)&&0!=(wt(x+8|0,r)|0)){for(var i=x+4|0,x=x|0,v=0;;){if((v|0)>=(a[i>>2]|0)){break c}if(0==An(a[x>>2]+(48*v&-1)|0,r)<<24>>24){v=v+1|0}else{var t=1;break}}h=n;r=t;break b}}while(0);t=a[q+108>>2];t=0!=(t|0)&&0!=kj(t,r)<<24>>24?1:0;h=n;r=t}if(0!=r<<24>>24){e=437;break a}k=Db(a[f>>2],k)}j=sa(a[g],j)}if(437==e){return h=d,k|0}for(k=J[a[a[g]>>2]](a[g],0,256);0!=(k|0);){if(0!=zn(k,c)<<24>>24){e=443;break}k=J[a[a[g]>>2]](a[g],k|0,16)}if(443==e){return h=d,k|0}e=qp(b,c);h=d;return 0==(e|0)?b|0:e|0}function pp(b){var c,g;g=(b+576|0)>>2;c=a[g];0!=(c|0)&&(E(c),a[g]=0);b=a[b+568>>2];c=b>>2;if(0!=(b|0)){var e=a[c]<<28>>28;1==(e|0)?(e=b+133|0,n[e]|=1,c=Q(a[a[a[c+5]+40>>2]>>2]|0,5360720),0!=(c|0)&&(a[g]=Zb(tb(b,a[c+8>>2]),b))):2==(e|0)?(e=b+127|0,n[e]|=1,c=Q(a[a[a[a[c+3]+20>>2]+40>>2]+4>>2]|0,5360720),0!=(c|0)&&(a[g]=Zb(tb(b,a[c+8>>2]),b))):3==(e|0)&&(e=b+148|0,n[e]|=1,c=Q(a[c+8]|0,5360720),0!=(c|0)&&(a[g]=Zb(tb(b,a[c+8>>2]),b)))}}function qp(c,d){var g,e=0,l=h;g=d>>2;d=h;h=h+32|0;a[d>>2]=a[g];a[d+4>>2]=a[g+1];a[d+8>>2]=a[g+2];a[d+12>>2]=a[g+3];a[d+16>>2]=a[g+4];a[d+20>>2]=a[g+5];a[d+24>>2]=a[g+6];a[d+28>>2]=a[g+7];g=a[c+208>>2];for(var p=c+212|0,j=1;(j|0)<=(g|0);){var k=qp(a[a[p>>2]+(j<<2)>>2],d);if(0==(k|0)){j=j+1|0}else{var r=k,e=481;break}}if(481==e){return h=l,r}e=c+52|0;g=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);e=c+60|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);r=c+76|0;r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]);p=d+16|0;if((a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])>=g){if(g=c+68|0,p=d|0,(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])>=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])){if(g=d+24|0,(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])>=e){if(e=d+8|0,r>=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])){return h=l,c}}}}h=l;return 0}function lp(b){var c=b+572|0,g=a[c>>2];if(0!=(g|0)){var e=a[g>>2]<<28>>28;3==(e|0)?(g=g+148|0,n[g]=n[g]&-7|4):1==(e|0)?(g=g+133|0,n[g]=n[g]&-7|4):2==(e|0)&&(g=g+127|0,n[g]=n[g]&-7|4)}g=b+580|0;e=a[g>>2];0!=(e|0)&&(E(e),a[g>>2]=0);g=a[b+568>>2];a[c>>2]=g;0!=(g|0)&&(c=a[g>>2]<<28>>28,2==(c|0)?(c=g+127|0,n[c]|=2,rp(b,g)):1==(c|0)?(c=g+133|0,n[c]|=2,sp(b,g)):3==(c|0)&&(c=g+148|0,n[c]|=2,vk(b,g)))}function vk(b,c){var g,e;g=b+584|0;e=(c+32|0)>>2;(a[e]|0)==(c|0)?0==(a[c>>2]&16|0)?wc(g,0,5372324):wc(g,0,5335632):wc(g,0,5347284);wc(g,1,a[c+12>>2]);a[b+588>>2]=2;var d=b+596|0;g=(c+16|0)>>2;a:do{if(0<(Mb(a[a[a[g]+12>>2]+4>>2])|0)){for(var f=c|0,j=0,k=0;;){var h=a[a[a[a[g]+12>>2]+8>>2]+(k<<2)>>2];wc(d,j,a[h>>2]);wc(d,j+1|0,tb(f,a[h+8>>2]));h=j+3|0;wc(d,j+2|0,0);k=k+1|0;if((k|0)<(Mb(a[a[a[g]+12>>2]+4>>2])|0)){j=h}else{var q=h;break a}}}else{q=0}}while(0);a[b+600>>2]=q;q=Q(a[e]|0,5353856);if(0==(q|0)){if(e=Q(a[e]|0,5355416),0==(e|0)){return}}else{e=q}q=c|0;a[b+580>>2]=Zb(tb(q,a[e+8>>2]),q)}function sp(b,c){var g,e;e=b+584|0;wc(e,0,5329472);wc(e,1,a[c+12>>2]);a[b+588>>2]=2;var d=b+596|0;e=(c+20|0)>>2;g=(a[a[e]+32>>2]+16|0)>>2;a:do{if(0<(Mb(a[a[a[g]+4>>2]+4>>2])|0)){for(var f=c|0,j=0,k=0;;){var h=a[a[a[a[g]+4>>2]+8>>2]+(k<<2)>>2];wc(d,j,a[h>>2]);var q=j+2|0;wc(d,j|1,tb(f,a[h+8>>2]));k=k+1|0;if((k|0)<(Mb(a[a[a[g]+4>>2]+4>>2])|0)){j=q}else{var i=q;break a}}}else{i=0}}while(0);a[b+600>>2]=i;i=Q(a[a[a[e]+40>>2]>>2]|0,5353856);if(0==(i|0)){if(e=Q(a[a[a[e]+40>>2]>>2]|0,5355416),0==(e|0)){return}}else{e=i}i=c|0;a[b+580>>2]=Zb(tb(i,a[e+8>>2]),i)}function rp(b,c){var g,e,d=0,f=b+584|0;wc(f,0,5374900);e=c+16|0;wc(f,1,a[a[e>>2]+12>>2]);wc(f,3,0!=(a[a[a[e>>2]+20>>2]>>2]&16|0)?5360020:5332132);e=(c+12|0)>>2;wc(f,4,a[a[e]+12>>2]);a[b+588>>2]=7;var j=b+596|0;g=(a[a[a[e]+20>>2]+32>>2]+16|0)>>2;a:do{if(0<(Mb(a[a[a[g]+8>>2]+4>>2])|0)){for(var k=c|0,h=0,q=0;;){var i=a[a[a[a[g]+8>>2]+8>>2]+(h<<2)>>2],n=i|0,x=a[n>>2];if(0==($(x,5375068)|0)){d=i+8|0;wc(f,2,tb(k,a[d>>2]));var v=d,d=533}else{if(0==($(x,5377776)|0)){d=i+8|0,wc(f,5,tb(k,a[d>>2])),v=d,d=533}else{if(i=i+8|0,0!=($(x,5345132)|0)){v=i,d=533}else{wc(f,6,tb(k,a[i>>2]));var t=q}}}533==d&&(d=0,wc(j,q,a[n>>2]),wc(j,q+1|0,tb(k,a[v>>2])),t=q+2|0);h=h+1|0;if((h|0)<(Mb(a[a[a[g]+8>>2]+4>>2])|0)){q=t}else{var y=t;break a}}}else{y=0}}while(0);a[b+600>>2]=y;f=Q(a[a[a[a[e]+20>>2]+40>>2]+4>>2]|0,5353856);if(0==(f|0)){if(e=Q(a[a[a[a[e]+20>>2]+40>>2]+4>>2]|0,5355416),0==(e|0)){return}}else{e=f}f=c|0;a[b+580>>2]=Zb(tb(f,a[e+8>>2]),f)}function um(b,c){var g=b+120|0,e=a[g>>2];0==(e|0)?(e=da(624),a[g>>2]=e,a[b+124>>2]=e,g=a[1312669]=e):(g=a[1312669],0==(g|0)?g=a[1312669]=e:(g=a[g+4>>2],0==(g|0)&&(g=da(624),a[a[1312669]+4>>2]=g),a[1312669]=g));a[g+52>>2]=c;a[g>>2]=b;lf(b,3,c)}function wc(b,c,g){var e=b+8|0;if((a[e>>2]|0)>(c|0)){var d=a[b>>2]}else{d=c+10|0,a[e>>2]=d,b|=0,d=Oa(a[b>>2],d<<2),a[b>>2]=d}c=(c<<2)+d|0;a[c>>2]=g}function tp(b){var c=b|0,g=a[c>>2];0!=(g|0)&&E(g);a[c>>2]=0;a[b+8>>2]=0;a[b+4>>2]=0}function Yi(b){var c,g=b+120|0,e=a[g>>2];a:do{if(0!=(e|0)){var d=e;for(c=d>>2;;){var f=a[c+1];tp(d+596|0);tp(d+584|0);var j=a[c+144];0!=(j|0)&&E(j);c=a[c+145];0!=(c|0)&&E(c);E(d);if(0==(f|0)){break a}else{d=f,c=d>>2}}}}while(0);a[1312669]=0;a[1312670]=0;a[b+164>>2]=0;a[b+124>>2]=0;a[g>>2]=0;a[b+28>>2]=0}function wk(c,d,g,e){var l=d+496|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),p=d+504|0,j=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),p=d+348|0,k=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),p=d+512|0,p=k*(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),h=d+520|0;0==(a[d+356>>2]|0)?(d=j+e,g=l+g):(d=l+g,g=-(j+e));e=d*k*(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]);d=c|0;f[b>>3]=g*p;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=e;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function Wd(c,d,g,e){var l=c+496|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),p=c+504|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=c+348|0,k=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),j=c+512|0,j=k*(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),h=c+520|0,k=k*(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]),h=0<(e|0);if(0==(a[c+356>>2]|0)){if(h){for(c=0;;){var h=(c<<4)+d|0,h=((a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])+l)*j,q=(c<<4)+g|0;f[b>>3]=h;a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];h=(c<<4)+d+8|0;h=((a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])+p)*k;q=(c<<4)+g+8|0;f[b>>3]=h;a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];c=c+1|0;if((c|0)==(e|0)){break}}}}else{if(h){for(c=0;;){var h=(c<<4)+d+8|0,h=j*-((a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])+p),q=(c<<4)+d|0,q=((a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])+l)*k,i=(c<<4)+g+8|0;f[b>>3]=q;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];q=(c<<4)+g|0;f[b>>3]=h;a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];c=c+1|0;if((c|0)==(e|0)){break}}}}}function gp(b,c,g,e,d,f){var j,k,r=h;h=h+128|0;j=r|0;ug(j,g);var q=oc(j,58);0!=(q|0)&&(n[q]=0);q=r+64|0;for(b=(c<<2)+b+60|0;;){c=a[b>>2];if(0==(c|0)){k=b;k>>=2;break}ug(q,a[c+4>>2]);c=oc(q,58);0!=(c|0)&&(n[c]=0);if(1>($(j,q)|0)){k=b;k>>=2;break}b=a[b>>2]|0}for(;;){b=a[k];if(0==(b|0)){break}ug(q,a[b+4>>2]);b=oc(q,58);0!=(b|0)&&(n[b]=0);if(0!=($(j,q)|0)){break}b=a[k];if((a[b+8>>2]|0)<=(e|0)){break}k=b|0;k>>=2}q=Za(20);j=q>>2;a[j]=a[k];a[k]=q;a[j+1]=g;a[j+2]=e;a[j+3]=d;a[j+4]=f;h=r}function lf(b,c,g){var e,d=0,f=h;h=h+128|0;var j=f+64,k=2>(c-3|0)>>>0?0:c,r=f|0;ug(r,g);g=oc(r,58);if(0==(g|0)){var q=g=0}else{q=g+1|0,n[g]=0,g=oc(q,58),0==(g|0)?g=0:(n[g]=0,g=g+1|0)}var j=j|0,m=0==(q|0),w=0==(g|0),x=(k|0)==(c|0);e=((c<<2)+b+60|0)>>2;a:for(;;){var v=a[e];if(0==(v|0)){var t=0;break}ug(j,a[v+4>>2]);v=oc(j,58);0==(v|0)?v=0:(n[v]=0,v=v+1|0);do{if(0==($(j,r)|0)){var y=0==(v|0);if(y|m||0==($(v,q)|0)){if(w||0==($(g,a[a[a[e]+12>>2]+8>>2])|0)){if(y|x){d=618;break a}if(0!=(lf(b,k,v)|0)){d=618;break a}}}}}while(0);e=a[e]|0;e>>=2}618==d&&(d=a[e],0==(d|0)?t=0:(k=d+16|0,r=a[k>>2],0==(r|0)?(r=h,aa(1,5336532,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),h=r,k=a[k>>2]):k=r,d=0==(k|0)?0:d,0==(d|0)?t=0:(0<(a[b+8>>2]|0)&&(k=a[d+4>>2],r=a[a[d+12>>2]+8>>2],Lb(a[Qa>>2],5343876,(i=h,h=h+12|0,a[i>>2]=a[(c<<2)+5324224>>2],a[i+4>>2]=k,a[i+8>>2]=r,i))),t=d)));a[b+(c<<2)+80>>2]=t;h=f;return t}function tk(b,c){var g,e=0;n[5251568]||(ac(5251552,0,0),n[5251568]=1);var d=Hb(c),f=oc(d,58);do{if(0==(f|0)){var j=b+64|0,e=642}else{n[f]=0;var k=b+64|0;if(0==(f+1|0)){j=k,e=642}else{var h=a[k>>2];if(0==(h|0)){E(d);var q=1,i=k,e=644}else{g=k;g>>=2;for(var w=1;;){var h=Hb(a[h+4>>2]),x=oc(h,58);0!=(x|0)&&(n[x]=0);if(0==n[d]<<24>>24){e=636}else{if(0==(Eb(d,h)|0)){e=636}else{var v=w}}636==e&&(e=0,v=a[1312889],v>>>0<a[1312890]>>>0||(qa(5251552,1),v=a[1312889]),a[1312889]=v+1|0,n[v]=32,Cb(5251552,a[a[g]+4>>2]),v=a[1312889],v>>>0<a[1312890]>>>0||(qa(5251552,1),v=a[1312889]),a[1312889]=v+1|0,n[v]=58,Cb(5251552,a[a[a[g]+12>>2]+8>>2]),v=0);E(h);g=a[g]|0;h=a[g>>2];if(0==(h|0)){break}else{g>>=2,w=v}}E(d);0!=v<<24>>24&&(q=v,i=k,e=644)}}}}while(0);642==e&&(E(d),q=1,i=j,e=644);do{if(644==e){d=a[i>>2];do{if(0==(d|0)){var t=q,e=655}else{f=i;j=0;k=q;for(g=d;;){var y=Hb(a[g+4>>2]);g=oc(y,58);0!=(g|0)&&(n[g]=0);if(g=0!=(j|0)){if(0==(Eb(j,y)|0)){var z=k}else{e=649}}else{e=649}649==e&&(e=0,z=a[1312889],z>>>0<a[1312890]>>>0||(qa(5251552,1),z=a[1312889]),a[1312889]=z+1|0,n[z]=32,Cb(5251552,y),g||E(0),z=0);f=a[f>>2]|0;g=a[f>>2];if(0==(g|0)){break}else{j=y,k=z}}if(0==(y|0)){t=z,e=655}else{var B=z}}}while(0);655==e&&(E(0),B=t);if(0!=B<<24>>24){return e=5338228}}}while(0);e=a[1312889];e>>>0<a[1312890]>>>0||(qa(5251552,1),e=a[1312889]);n[e]=0;e=a[1312888];return a[1312889]=e}function Dh(b,c){var g,e,d,f=b>>2;g=a[f];lf(g,3,c);e=a[g+92>>2];if(0==(e|0)){return 999}d=a[e+16>>2]>>2;var j=a[d+3];a[f+19]=j;var k=a[d+4];a[f+21]=k;d=a[d];a[f+20]=d;a[f+22]=a[e+4>>2];e=(b+148|0)>>2;k=a[e]|a[k>>2];a[e]=k;var h=a[g+80>>2];if(0==(h|0)){return a[f+15]=0,999}g=a[h+16>>2]>>2;a[f+15]=a[g+3];var i=a[g+4];a[f+17]=i;a[f+18]=a[h+4>>2];a[e]=k|a[i>>2];a[f+16]=0==(j|0)?d:a[g];return 300}function Xi(b){var c=a[b+60>>2];if(0!=(c|0)&&(c=a[c+4>>2],0!=(c|0))){J[c](b)}a[a[b>>2]+24>>2]=0;jp(b)}function hj(b,c,g){var e=h;h=h+4|0;a[g>>2]=c;a[g+32>>2]=5;a[e>>2]=Uo(c);var d=a[b+12>>2];if(!(0!=(d|0)&&0!=(yh(e,d,a[b+16>>2],4,122)|0))){if(b=Vo(c,g,a[b+20>>2]),1==(b|0)){b=Za(xa(c)+16|0);Pa(b,5365752,(i=h,h=h+4|0,a[i>>2]=c,i));g=a[1311586];0==(g|0)&&(g=Bc(5246348,5380200),a[1311586]=g);if(0!=(J[a[g>>2]](g,b,4)|0)){g=0}else{var g=a[1311586],d=a[g>>2],f=dc(b);J[d](g,f,1);g=1}0!=(g|0)&&aa(0,5363208,(i=h,h=h+4|0,a[i>>2]=c,i));E(b)}else{0!=(b|0)&&aa(1,5361036,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i))}}h=e}function Sm(b){var c=a[b+60>>2];if(0!=(c|0)&&(c=a[c+28>>2],0!=(c|0))){J[c](b)}}function uj(b){var c=a[b+60>>2];if(0!=(c|0)&&(c=a[c+40>>2],0!=(c|0))){J[c](b)}}function vj(b){var c=a[b+60>>2];if(0!=(c|0)&&(c=a[c+44>>2],0!=(c|0))){J[c](b)}}function sj(b){var c=a[b+60>>2];if(0!=(c|0)&&(c=a[c+48>>2],0!=(c|0))){J[c](b)}}function tj(b){var c=a[b+60>>2];if(0!=(c|0)&&(c=a[c+52>>2],0!=(c|0))){J[c](b)}}function pn(b){var c=a[b+60>>2];if(0!=(c|0)&&(c=a[c+56>>2],0!=(c|0))){J[c](b)}}function Mc(b,c,g,e,d){var f=a[b+60>>2];if(0!=(f|0)&&(f=a[f+72>>2],0!=(f|0))){J[f](b,c,g,e,d)}}function de(b){var c=a[b+60>>2];if(0!=(c|0)&&(c=a[c+76>>2],0!=(c|0))){J[c](b)}}function Ln(b,c){var g=a[b+60>>2];if(0!=(g|0)&&(g=a[g+80>>2],0!=(g|0))){J[g](b,c)}}function Mn(b){var c=a[b+60>>2];if(0!=(c|0)&&(c=a[c+84>>2],0!=(c|0))){J[c](b)}}function xj(c,d,g,e){var l=h;h=h+16|0;var p=a[c+60>>2],j=a[e>>2];if(0!=(j|0)&&0!=n[j]<<24>>24){j=a[c+16>>2];if(0!=(j|0)&&0==(a[j+88>>2]|0)){h=l;return}0==(a[c+148>>2]&8192|0)&&(wk(l,c,d,g),d=l|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),g=l+8|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]));if(0!=(p|0)&&(p=a[p+88>>2],0!=(p|0))){J[p](c,d,g,e)}}h=l}function eb(b,c){var g=a[b+60>>2],d=a[b+16>>2]+16|0,f=oc(c,58),p=0!=(f|0);p&&(n[f]=0);if(0!=(g|0)&&(hj(a[b+68>>2],c,d),g=a[g+92>>2],0!=(g|0))){J[g](b,d)}p&&(n[f]=58)}function Sb(b,c){var g=a[b+60>>2],d=a[b+16>>2]+52|0,f=oc(c,58),p=0!=(f|0);p&&(n[f]=0);if(0!=(g|0)&&(hj(a[b+68>>2],c,d),g=a[g+92>>2],0!=(g|0))){J[g](b,d)}p&&(n[f]=58)}function Dd(c,d,g){var e,l=0,p=h;a[c+104>>2]=g;if(!(0==(d|0)|0==(g|0))){var j=a[g>>2];if(0!=(j|0)){e=(c+88|0)>>2;for(var d=(c+96|0)>>2,c=c+92|0,k=g,g=j;;){j=k+4|0;k=n[g];a:do{if(115==k<<24>>24){if(0==($(g,5354244)|0)){a[e]=3}else{if(0==($(g,5365664)|0)){for(var r=g,q=0;;){var m=r+1|0;if(q){break}r=m;q=0==n[m]<<24>>24}r=Oe(m,Ac);f[b>>3]=r;a[d]=a[b>>2];a[d+1]=a[b+4>>2]}else{l=900}}}else{if(100==k<<24>>24){0==($(g,5345848)|0)?a[e]=1:0==($(g,5342304)|0)?a[e]=2:l=102==k<<24>>24?896:117==k<<24>>24?898:900}else{if(98==k<<24>>24){l=889}else{if(102==k<<24>>24){l=896}else{if(117==k<<24>>24){l=898}else{if(105==k<<24>>24){do{if(0!=($(g,5365092)|0)&&0!=($(g,5336304)|0)){l=98==k<<24>>24?889:102==k<<24>>24?896:117==k<<24>>24?898:900;break a}}while(0);a[e]=0}else{l=900}}}}}}}while(0);889==l?(l=0,0!=($(g,5360600)|0)?l=900:(f[b>>3]=2,a[d]=a[b>>2],a[d+1]=a[b+4>>2])):896==l?(l=0,0!=($(g,5362648)|0)?l=900:a[c>>2]=1):898==l&&(l=0,0!=($(g,5378608)|0)?l=900:a[c>>2]=0);900==l&&(l=0,aa(0,5376008,(i=h,h=h+4|0,a[i>>2]=g,i)));g=a[j>>2];if(0==(g|0)){break}else{k=j}}}}h=p}function Kg(c,d,g){var e,l=h;h=h+32|0;var p=a[c+60>>2];if(0!=(p|0)&&(p=p+96|0,0!=(a[p>>2]|0)&&0!=(a[a[c+16>>2]+88>>2]|0))){var j=d|0;e=d+16|0;var k=e|0,k=.5*((a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])+(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])),j=l|0,r=l|0;f[b>>3]=k;a[r>>2]=a[b>>2];a[r+4>>2]=a[b+4>>2];k=d+8|0;d=d+24|0;d=.5*((a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])+(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]));k=l+8|0;f[b>>3]=d;a[k>>2]=a[b>>2];a[k+4>>2]=a[b+4>>2];d=(l+16|0)>>2;e>>=2;a[d]=a[e];a[d+1]=a[e+1];a[d+2]=a[e+2];a[d+3]=a[e+3];0==(a[c+148>>2]&8192|0)&&Wd(c,j,j,2);J[a[p>>2]](c,j,g&255)}h=l}function tc(b,c,g,d){var f=a[b+60>>2];if(0!=(f|0)){var f=f+100|0,p=a[f>>2];if(0!=(p|0)&&0!=(a[a[b+16>>2]+88>>2]|0)){if(0!=(a[b+148>>2]&8192|0)){J[p](b,c,g,d&255)}else{(a[1311599]|0)<(g|0)?(p=g+10|0,a[1311599]=p,p=Oa(a[1345666],p<<4),a[1345666]=p):p=a[1345666],Wd(b,c,p,g),J[a[f>>2]](b,p,g,d&255)}}}}function of(c,d,g){var e,l,p=h;h=h+64|0;l=d>>2;d=h;h=h+32|0;a[d>>2]=a[l];a[d+4>>2]=a[l+1];a[d+8>>2]=a[l+2];a[d+12>>2]=a[l+3];a[d+16>>2]=a[l+4];a[d+20>>2]=a[l+5];a[d+24>>2]=a[l+6];a[d+28>>2]=a[l+7];e=p>>2;l=d>>2;a[e]=a[l];a[e+1]=a[l+1];a[e+2]=a[l+2];a[e+3]=a[l+3];l=p+32|0;e=l>>2;d=(d+16|0)>>2;a[e]=a[d];a[e+1]=a[d+1];a[e+2]=a[d+2];a[e+3]=a[d+3];d=p|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);e=p+16|0;f[b>>3]=d;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];d=p+40|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);e=p+24|0;f[b>>3]=d;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];l|=0;l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);d=p+48|0;f[b>>3]=l;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];l=p+8|0;l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);d=p+56|0;f[b>>3]=l;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];tc(c,p|0,4,g);h=p}function hf(b,c,g,d,f,p){var j=a[b+60>>2];if(0!=(j|0)){var j=j+104|0,k=a[j>>2];if(0!=(k|0)&&0!=(a[a[b+16>>2]+88>>2]|0)){if(0!=(a[b+148>>2]&8192|0)){J[k](b,c,g,d,f,p&255)}else{(a[1311599]|0)<(g|0)?(k=g+10|0,a[1311599]=k,k=Oa(a[1345666],k<<4),a[1345666]=k):k=a[1345666],Wd(b,c,k,g),J[a[j>>2]](b,k,g,d,f,p&255)}}}}function td(b,c,g){var d=a[b+60>>2];if(0!=(d|0)){var d=d+108|0,f=a[d>>2];if(0!=(f|0)&&0!=(a[a[b+16>>2]+88>>2]|0)){if(0!=(a[b+148>>2]&8192|0)){J[f](b,c,g)}else{(a[1311599]|0)<(g|0)?(f=g+10|0,a[1311599]=f,f=Oa(a[1345666],f<<4),a[1345666]=f):f=a[1345666],Wd(b,c,f,g),J[a[d>>2]](b,f,g)}}}}function Dg(b,c){var g=a[b+60>>2];if(0!=(c|0)&&!(0==n[c]<<24>>24|0==(g|0))&&(g=a[g+112>>2],0!=(g|0))){J[g](b,c)}}function jj(c,d){if(0!=(a[c+60>>2]|0)){var g=a[c+16>>2]+96|0;f[b>>3]=d;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2]}}function up(b,c,g,d){if(0==(c|0)){c=d=-1}else{var f=a[c+48>>2];0!=(f|0)&&(g=d=f|0);f=d;d=(72*a[c+40>>2]&-1|0)/g&-1;c=(72*a[c+44>>2]&-1|0)/f&-1}a[b>>2]=d;a[b+4>>2]=c}function Mj(c,d,g,e,l,p){var j,k,r,q,m,w,x,v,t,y=h;h=h+72|0;t=y+32;k=y+40;j=y+56;var z=a[c+60>>2],B=vp(d);if(0==(B|0)){if(!(0==(zj(d)|0)|0==(z|0))&&(B=a[z+116>>2],0!=(B|0))){J[B](c,d,g,e,l&255)}}else{var d=c+424|0,F=c+432|0;up(t,B,(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]));var F=a[t>>2],D=a[t+4>>2];if(!(1>(F|0)&1>(D|0))){r=y+16|0;t=r>>2;m=g>>2;a[t]=a[m];a[t+1]=a[m+1];a[t+2]=a[m+2];a[t+3]=a[m+3];d=y>>2;a[d]=a[m];a[d+1]=a[m+1];a[d+2]=a[m+2];a[d+3]=a[m+3];if(1<(e|0)){v=(y|0)>>2;x=(y+8|0)>>2;w=(r|0)>>2;m=(y+24|0)>>2;for(var A=(a[b>>2]=a[v],a[b+4>>2]=a[v+1],f[b>>3]),C=(a[b>>2]=a[x],a[b+4>>2]=a[x+1],f[b>>3]),E=1,I=A,A=(a[b>>2]=a[w],a[b+4>>2]=a[w+1],f[b>>3]),Z=(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3]);;){q=(E<<4)+g|0;var T=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),K=I<T?I:T;q=(E<<4)+g+8|0;var M=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);q=C<M?C:M;T=A>T?A:T;M=Z>M?Z:M;E=E+1|0;if((E|0)==(e|0)){break}else{I=K,C=q,A=T,Z=M}}f[b>>3]=M;a[m]=a[b>>2];a[m+1]=a[b+4>>2];f[b>>3]=T;a[w]=a[b>>2];a[w+1]=a[b+4>>2];f[b>>3]=q;a[x]=a[b>>2];a[x+1]=a[b+4>>2];f[b>>3]=K;a[v]=a[b>>2];a[v+1]=a[b+4>>2];m=K;K=M;M=q}else{g=r|0,q=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),g=y|0,K=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),e=y+24|0,g=y+8|0,T=q,m=K,K=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),M=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])}q=(r|0)>>2;e=(y|0)>>2;x=T-m;g=(y+24|0)>>2;r=(y+8|0)>>2;w=K-M;D|=0;F|=0;v=x/F;E=w/D;p=0==n[p]<<24>>24?0:0==(Eb(p,5373184)|0)?2:0==(Eb(p,5370656)|0)?3:0==(Eb(p,5368056)|0)?4:0!=Xd(p)<<24>>24&1;1==(p|0)?v<E?(p=D*v,F*=v):(p=D*E,F*=E):4==(p|0)?(p=D*E,F*=v):3==(p|0)?p=D*E:2==(p|0)?(p=D,F*=v):p=D;F<x?(F=.5*(x-F),D=m+F,f[b>>3]=D,a[e]=a[b>>2],a[e+1]=a[b+4>>2],T-=F,f[b>>3]=T,a[q]=a[b>>2],a[q+1]=a[b+4>>2],F=D):F=m;D=T;p<w?(p=.5*(w-p),T=M+p,f[b>>3]=T,a[r]=a[b>>2],a[r+1]=a[b+4>>2],f[b>>3]=K-p,a[g]=a[b>>2],a[g+1]=a[b+4>>2],p=T):p=M;0==(a[c+148>>2]&8192|0)?(wk(k,c,F,p),k>>=2,a[d]=a[k],a[d+1]=a[k+1],a[d+2]=a[k+2],a[d+3]=a[k+3],wk(j,c,(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3]),(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])),j>>=2,a[t]=a[j],a[t+1]=a[j+1],a[t+2]=a[j+2],a[t+3]=a[j+3],j=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),k=(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3])):(j=F,k=D);j>k&&(f[b>>3]=k,a[e]=a[b>>2],a[e+1]=a[b+4>>2],f[b>>3]=j,a[q]=a[b>>2],a[q+1]=a[b+4>>2]);j=(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3]);k=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]);j>k&&(f[b>>3]=k,a[r]=a[b>>2],a[r+1]=a[b+4>>2],f[b>>3]=j,a[g]=a[b>>2],a[g+1]=a[b+4>>2]);if(0!=(z|0)){t=a[c+72>>2];j=h;h=h+128|0;k=y>>2;z=h;h=h+32|0;a[z>>2]=a[k];a[z+4>>2]=a[k+1];a[z+8>>2]=a[k+2];a[z+12>>2]=a[k+3];a[z+16>>2]=a[k+4];a[z+20>>2]=a[k+5];a[z+24>>2]=a[k+6];a[z+28>>2]=a[k+7];k=j|0;ee(k,a[B+28>>2]);d=j+xa(k)|0;Ib=58;n[d]=Ib&255;Ib>>=8;n[d+1|0]=Ib&255;fe(k,t);t=lf(a[c>>2],4,k);0==(t|0)?t=999:(t=a[t+16>>2],a[c+92>>2]=a[t+12>>2],a[c+96>>2]=a[t>>2],t=300);999==(t|0)&&aa(0,5374268,(i=h,h=h+4|0,a[i>>2]=k,i));k=a[c+92>>2];if(0!=(k|0)&&(k=a[k>>2],0!=(k|0))){J[k](c,B,z,l)}h=j}}}h=y}function vp(b){var c=h;h=h+64|0;var g=a[1345409];if(0==(g|0)){return h=c,0}a[c+8>>2]=b;b=J[a[g>>2]](g,c,4);h=c;return b}function wp(b){var c=h;0==(b|0)&&ia(5373100,363,5379764,5337976);var g=b+8|0;0==(a[g>>2]|0)&&ia(5373100,364,5379764,5337700);var d=b+20|0,f=a[d>>2];0==(f|0)?(g=Oh(a[g>>2]),0==(g|0)?b=1:(f=vg(g,5345784),a[d>>2]=f,0==(f|0)?(b=Kf(a[Ha.d>>2]),aa(0,5342232,(i=h,h=h+8|0,a[i>>2]=b,a[i+4>>2]=g,i)),b=0):(d=a[1312807],49<(d|0)?n[b+17|0]=1:a[1312807]=d+1|0,b=1))):($e(f,0,0),b=1);h=c;return b}function xp(b){if(0!=n[b+17|0]<<24>>24){var b=b+20|0,c=a[b>>2];0!=(c|0)&&(Jf(c),a[b>>2]=0)}}function vo(c,d,g){0!=(g|0)&&0!=n[g]<<24>>24?(d=a[d+44>>2]+24|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),d=1>d?96:d,up(c,yp(g),d,d)):(a[c>>2]=-1,a[c+4>>2]=-1)}function yp(b){var c=h;0==(a[1345409]|0)&&(a[1345409]=Bc(5381564,5380184));var g=vp(b);if(0==(g|0)){g=da(64);if(0==(g|0)){return h=c,0}var d=g+8|0;a[d>>2]=b;if(0==wp(g)<<24>>24){return h=c,0}b=zp(g);if(4==(b|0)){Ap(g)}else{if(1==(b|0)){d=h;h=h+16|0;var f=d+4,p=d+8,j=d+12;a[g+48>>2]=0;b=(g+20|0)>>2;$e(a[b],16,0);0!=bg(a[b],d)<<24>>24&&0!=bg(a[b],f)<<24>>24&&0!=bg(a[b],p)<<24>>24&&0!=bg(a[b],j)<<24>>24&&(a[g+40>>2]=a[d>>2]<<16|a[f>>2],a[g+44>>2]=a[p>>2]<<16|a[j>>2]);h=d}else{if(0==(b|0)){return b=a[d>>2],d=zj(b),a[g+52>>2]=d,0==(d|0)&&aa(0,5338952,(i=h,h=h+4|0,a[i>>2]=b,i)),E(g),h=c,0}if(2==(b|0)){d=h,h=h+8|0,f=d+4,a[g+48>>2]=0,b=(g+20|0)>>2,$e(a[b],6,0),0!=bg(a[b],d)<<24>>24&&0!=bg(a[b],f)<<24>>24&&(a[g+40>>2]=a[d>>2],a[g+44>>2]=a[f>>2]),h=d}else{if(8==(b|0)){Bp(g)}else{if(3==(b|0)){d=h,h=h+8|0,f=d+4,a[g+48>>2]=0,b=(g+20|0)>>2,$e(a[b],16,0),0!=ye(a[b],4,d)<<24>>24&&0!=ye(a[b],4,f)<<24>>24&&(a[g+40>>2]=a[d>>2],a[g+44>>2]=a[f>>2]),h=d}else{if(6==(b|0)){var b=g>>2,k=0,d=h;h=h+1040|0;var r=d+1024,j=d+1028,f=d+1032,p=d+1036;a[b+12]=72;var q=g+20|0;$e(a[q>>2],0,0);for(var m=d|0;;){if(0==(Hf(m,1024,a[q>>2])|0)){k=1160;break}var n=zh(m,5363116);if(0!=(n|0)&&4==(gd(n,5360956,(i=h,h=h+16|0,a[i>>2]=r,a[i+4>>2]=j,a[i+8>>2]=f,a[i+12>>2]=p,i))|0)){break}}1160!=k&&(k=a[r>>2],a[b+8]=k,j=a[j>>2],a[b+9]=j,a[b+10]=a[f>>2]-k|0,a[b+11]=a[p>>2]-j|0);h=d}}}}}}b=a[1345409];J[a[b>>2]](b,g,1)}xp(g);h=c;return g}function zp(b){var c=0,g=h;h=h+220|0;var d=g+20,f=b+20|0,p=a[f>>2];a:do{if(0!=(p|0)){var j=g|0;if(20==(nm(j,1,20,p)|0)){var p=b+28|0,k=b+24|0,d=d|0,r=0;b:for(;;){if(8<=r>>>0){break a}c:do{if(0==(Ne(j,a[(r<<4)+5251068>>2],a[(r<<4)+5251072>>2])|0)){a[p>>2]=a[(r<<4)+5251080>>2];var i=a[(r<<4)+5251076>>2];a[k>>2]=i;if(7!=(r|0)){var m=i,c=1101;break b}for(;;){if(0==(Hf(d,200,a[f>>2])|0)){break c}if(0==(Ne(d,5358928,4)|0)){break b}}}}while(0);r=r+1|0}if(1101==c){return h=g,m}a[p>>2]=5354076;m=a[k>>2]=8;h=g;return m}}}while(0);a[b+28>>2]=5355576;a[b+24>>2]=0;h=g;return 0}function Ap(b){var c=b>>2,g=0,d=h;h=h+20|0;var f=d+4,p=d+8,j=d+12,k=d+16;a[c+12]=0;for(b=(b+20|0)>>2;;){if(0==ye(a[b],1,d)<<24>>24){g=1144;break}var r=a[d>>2];if(255!=(r|0)&&0==(oc(5251196,r)|0)){if(192==(r|0)){g=1132;break}var i=a[b];if(194==(r|0)){g=1137;break}if(0==ye(i,2,f)<<24>>24){g=1149;break}$e(a[b],a[f>>2]-2|0,1)}}1132==g?(0!=ye(a[b],3,k)<<24>>24&&0!=ye(a[b],2,p)<<24>>24&&0!=ye(a[b],2,j)<<24>>24&&(a[c+11]=a[p>>2],a[c+10]=a[j>>2]),h=d):1149==g?h=d:1144==g?h=d:1137==g&&(0!=ye(i,3,k)<<24>>24&&0!=ye(a[b],2,p)<<24>>24&&0!=ye(a[b],2,j)<<24>>24&&(a[c+11]=a[p>>2],a[c+10]=a[j>>2]),h=d)}function Cp(a){var b=1-a;return 3*a*b*b}function ze(c,d,g,e){var l=c|0;f[b>>3]=d*e;a[l>>2]=a[b>>2];a[l+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=g*e;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function Bp(c){var d,g=0,e=h;h=h+220|0;d=e>>2;var l=c+20|0,p=e+20|0;$e(a[l>>2],-xa(p)|0,1);var j=e+8|0,k=0,r=0,q=0,m=0;a:for(;;){if(0==(Hf(p,200,a[l>>2])|0)){g=1178;break}if(!(0==m<<24>>24|0==k<<24>>24)){g=1177;break}for(var w=k,x=r,v=q,t=Jd(p,5366668,ud),y=m;;){if(0==(t|0)){k=w;r=x;q=v;m=y;continue a}if(62==n[t+(xa(t)-1)|0]<<24>>24){k=w;r=x;q=v;m=y;continue a}if(2==(gd(t,5333260,(i=h,h=h+8|0,a[i>>2]=e,a[i+4>>2]=j,i))|0)){if(x=xk((a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),j),0==w<<24>>24){y=1}else{k=w;r=x;q=v;m=1;continue a}}if(2==(gd(t,5330220,(i=h,h=h+8|0,a[i>>2]=e,a[i+4>>2]=j,i))|0)){if(v=xk((a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),j),0==y<<24>>24){w=1}else{k=1;r=x;q=v;m=y;continue a}}t=Jd(0,5366668,ud)}}1178==g?(a[(c+48|0)>>2]=72,a[(c+40|0)>>2]=r,a[(c+44|0)>>2]=q,h=e):1177==g&&(a[(c+48|0)>>2]=72,a[(c+40|0)>>2]=r,a[(c+44|0)>>2]=q,h=e)}function xk(a,b){if(0==($(b,5331016)|0)){var c=72*a;return(0>c?c-.5:c+.5)&-1}if(0==($(b,5378516)|0)){return c=72*a/96,(0>c?c-.5:c+.5)&-1}if(0==($(b,5375880)|0)){return c=72*a/6,(0>c?c-.5:c+.5)&-1}if(0!=($(b,5373048)|0)&&0!=($(b,5337992)|0)){if(0==($(b,5367996)|0)){return c=28.346456664*a,(0>c?c-.5:c+.5)&-1}if(0!=($(b,5365660)|0)){return 0}c=2.8346456663999997*a;return(0>c?c-.5:c+.5)&-1}return(0>a?a-.5:a+.5)&-1}function ye(b,c,g){for(var d=0,f=a[g>>2]=0;;){if(f>>>0>=c>>>0){var p=1,d=1224;break}var j=Gf(b);if(0!=(Number(N.b[b]&&N.b[b].f)|0)){p=0;d=1223;break}a[g>>2]=a[g>>2]<<8|j;f=f+1|0}if(1224==d||1223==d){return p}}function bg(b,c){for(var g=0,d=a[c>>2]=0;;){if(2<=d>>>0){var f=1,g=1231;break}var p=Gf(b);if(0!=(Number(N.b[b]&&N.b[b].f)|0)){f=0;g=1230;break}a[c>>2]|=p<<(d<<3);d=d+1|0}if(1231==g||1230==g){return f}}function po(c,d,g,e,l,p){var j,k,r,i,m,n=h;h=h+32|0;j=n+16;m=(l|0)>>2;i=(l+8|0)>>2;Wg(n,(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3]),(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3]));k=l>>2;r=n>>2;a[k]=a[r];a[k+1]=a[r+1];a[k+2]=a[r+2];a[k+3]=a[r+3];k=l+16|0;r=(k|0)>>2;l=(l+24|0)>>2;Wg(j,(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3]),(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]));k>>=2;j>>=2;a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];a[1312707]=0;yk(4);j=a[1312707];a[1312707]=j+1|0;k=((j<<4)+a[1312704]|0)>>2;j=g>>2;a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];m=(a[b>>2]=a[m],a[b+4>>2]=a[m+1],f[b>>3]);i=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3]);if(-1==(ii(c,d,g,e,m,i,(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3]),(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]))|0)){return h=n,-1}a[p+4>>2]=a[1312707];a[p>>2]=a[1312704];h=n;return 0}function Wg(c,d,g){var e=d*d+g*g;1e-6<e&&(e=Math.sqrt(e),d/=e,g/=e);e=c|0;f[b>>3]=d;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=g;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function ii(c,d,g,e,l,p,j,k){var r,i,m,n,x,v,t,y,z=h;h=h+256|0;var B=z+16,F=z+32,D=z+48,A=z+64,C=z+80,E=z+96,I=z+112,Z=z+128,T=z+144,K=z+160,M=z+176,L=z+192,G=z+208,H=z+224,J=z+240,R=a[1311665];if((a[1311666]|0)<(e|0)){if(0==(R|0)){var Y=wb(40*e&-1);a[1311665]=Y;if(0==(Y|0)){var P=-1;h=z;return P}var N=Y}else{var Q=gc(R,40*e&-1);a[1311665]=Q;if(0==(Q|0)){return P=-1,h=z,P}N=Q}a[1311666]=e;var ea=N}else{ea=R}var wa=ea|0;f[b>>3]=0;a[wa>>2]=a[b>>2];a[wa+4>>2]=a[b+4>>2];a:do{if(1<(e|0)){for(var U=1,V=0;;){var W=U-1|0,X=(U<<4)+g|0,ba=(a[b>>2]=a[X>>2],a[b+4>>2]=a[X+4>>2],f[b>>3]),ma=(U<<4)+g+8|0,aa=(a[b>>2]=a[ma>>2],a[b+4>>2]=a[ma+4>>2],f[b>>3]),da=(W<<4)+g|0,ca=(W<<4)+g+8|0,O=V+zk(ba,aa,(a[b>>2]=a[da>>2],a[b+4>>2]=a[da+4>>2],f[b>>3]),(a[b>>2]=a[ca>>2],a[b+4>>2]=a[ca+4>>2],f[b>>3])),ga=ea+(40*U&-1)|0;f[b>>3]=O;a[ga>>2]=a[b>>2];a[ga+4>>2]=a[b+4>>2];var Tb=U+1|0;if((Tb|0)==(e|0)){break}else{U=Tb,V=O}}for(var $=ea+(40*(e-1)&-1)|0,ua=1;;){var Da=(a[b>>2]=a[$>>2],a[b+4>>2]=a[$+4>>2],f[b>>3]);y=(ea+(40*ua&-1)|0)>>2;var Ja=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3])/Da;f[b>>3]=Ja;a[y]=a[b>>2];a[y+1]=a[b+4>>2];var Ab=ua+1|0;if((Ab|0)==(e|0)){break a}else{ua=Ab}}}}while(0);a:do{if(0<(e|0)){t=A>>2;v=C>>2;for(var ra=0;;){x=(ea+(40*ra&-1)|0)>>2;ze(A,l,p,Cp((a[b>>2]=a[x],a[b+4>>2]=a[x+1],f[b>>3])));n=(ea+(40*ra&-1)+8|0)>>2;a[n]=a[t];a[n+1]=a[t+1];a[n+2]=a[t+2];a[n+3]=a[t+3];var ia=C,ya=j,ja=k,la=(a[b>>2]=a[x],a[b+4>>2]=a[x+1],f[b>>3]);ze(ia,ya,ja,3*la*la*(1-la));m=(ea+(40*ra&-1)+24|0)>>2;a[m]=a[v];a[m+1]=a[v+1];a[m+2]=a[v+2];a[m+3]=a[v+3];var va=ra+1|0;if((va|0)==(e|0)){break a}else{ra=va}}}}while(0);Dp(g,e,ea,l,p,j,k,z,F,B,D);var oa=z|0,ka=(a[b>>2]=a[oa>>2],a[b+4>>2]=a[oa+4>>2],f[b>>3]),Ea=z+8|0,Ka=(a[b>>2]=a[Ea>>2],a[b+4>>2]=a[Ea+4>>2],f[b>>3]),Na=F|0,Ba=(a[b>>2]=a[Na>>2],a[b+4>>2]=a[Na+4>>2],f[b>>3]),Wa=F+8|0,fa=(a[b>>2]=a[Wa>>2],a[b+4>>2]=a[Wa+4>>2],f[b>>3]),ha=B|0,Ra=(a[b>>2]=a[ha>>2],a[b+4>>2]=a[ha+4>>2],f[b>>3]),bb=B+8|0,Xa=(a[b>>2]=a[bb>>2],a[b+4>>2]=a[bb+4>>2],f[b>>3]),Sa=D|0,sa=(a[b>>2]=a[Sa>>2],a[b+4>>2]=a[Sa+4>>2],f[b>>3]),Va=D+8|0,Ta=(a[b>>2]=a[Va>>2],a[b+4>>2]=a[Va+4>>2],f[b>>3]);if(0!=(Ep(c,d,ka,Ka,Ba,fa,Ra,Xa,sa,Ta,g,e)|0)){return P=0,h=z,P}ze(E,Ba,fa,.3333333333333333);var Aa=E|0,fb=E+8|0;Ak(I,ka,Ka,(a[b>>2]=a[Aa>>2],a[b+4>>2]=a[Aa+4>>2],f[b>>3]),(a[b>>2]=a[fb>>2],a[b+4>>2]=a[fb+4>>2],f[b>>3]));var Ca=I|0,Ya=(a[b>>2]=a[Ca>>2],a[b+4>>2]=a[Ca+4>>2],f[b>>3]),$a=I+8|0,La=(a[b>>2]=a[$a>>2],a[b+4>>2]=a[$a+4>>2],f[b>>3]);ze(Z,sa,Ta,.3333333333333333);var pa=Z|0,Ga=Z+8|0;ji(T,Ra,Xa,(a[b>>2]=a[pa>>2],a[b+4>>2]=a[pa+4>>2],f[b>>3]),(a[b>>2]=a[Ga>>2],a[b+4>>2]=a[Ga+4>>2],f[b>>3]));var Fa=T|0,qa=(a[b>>2]=a[Fa>>2],a[b+4>>2]=a[Fa+4>>2],f[b>>3]),nb=T+8|0,jb=(a[b>>2]=a[nb>>2],a[b+4>>2]=a[nb+4>>2],f[b>>3]),cb=e-1|0;a:do{if(1<(cb|0)){for(var xa=a[1311665],kb=-1,Kb=-1,Ma=1;;){var na=xa+(40*Ma&-1)|0,lb=(a[b>>2]=a[na>>2],a[b+4>>2]=a[na+4>>2],f[b>>3]),rb,ab=1-lb;rb=ab*ab*ab;var db=Cp(lb),ob=3*lb*lb*(1-lb),pb=lb*lb*lb,ub=(Ma<<4)+g|0,gb=(Ma<<4)+g+8|0,sb=zk(rb*ka+db*Ya+ob*qa+pb*Ra,rb*Ka+db*La+ob*jb+pb*Xa,(a[b>>2]=a[ub>>2],a[b+4>>2]=a[ub+4>>2],f[b>>3]),(a[b>>2]=a[gb>>2],a[b+4>>2]=a[gb+4>>2],f[b>>3])),Ia=sb>kb,vb=Ia?Ma:Kb,Ua=Ma+1|0;if((Ua|0)==(cb|0)){var ta=vb;break a}else{kb=Ia?sb:kb,Kb=vb,Ma=Ua}}}else{ta=-1}}while(0);var Oa=(ta<<4)+g|0,qb=ta-1|0;i=(Oa|0)>>2;var Bb=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3]);r=((ta<<4)+g+8|0)>>2;var Ha=(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3]),xb=(qb<<4)+g|0,za=(qb<<4)+g+8|0;ji(K,Bb,Ha,(a[b>>2]=a[xb>>2],a[b+4>>2]=a[xb+4>>2],f[b>>3]),(a[b>>2]=a[za>>2],a[b+4>>2]=a[za+4>>2],f[b>>3]));var Nb=K|0,Jb=K+8|0;Wg(M,(a[b>>2]=a[Nb>>2],a[b+4>>2]=a[Nb+4>>2],f[b>>3]),(a[b>>2]=a[Jb>>2],a[b+4>>2]=a[Jb+4>>2],f[b>>3]));var Za=M|0,Pa=(a[b>>2]=a[Za>>2],a[b+4>>2]=a[Za+4>>2],f[b>>3]),Qa=M+8|0,hb=(a[b>>2]=a[Qa>>2],a[b+4>>2]=a[Qa+4>>2],f[b>>3]),eb=ta+1|0,mb=(eb<<4)+g|0,zb=(a[b>>2]=a[mb>>2],a[b+4>>2]=a[mb+4>>2],f[b>>3]),tb=(eb<<4)+g+8|0,Cb=(a[b>>2]=a[tb>>2],a[b+4>>2]=a[tb+4>>2],f[b>>3]);ji(L,zb,Cb,(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3]),(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3]));var Ub=L|0,Db=L+8|0;Wg(G,(a[b>>2]=a[Ub>>2],a[b+4>>2]=a[Ub+4>>2],f[b>>3]),(a[b>>2]=a[Db>>2],a[b+4>>2]=a[Db+4>>2],f[b>>3]));var Ib=G|0,Eb=G+8|0;Ak(H,Pa,hb,(a[b>>2]=a[Ib>>2],a[b+4>>2]=a[Ib+4>>2],f[b>>3]),(a[b>>2]=a[Eb>>2],a[b+4>>2]=a[Eb+4>>2],f[b>>3]));var Hb=H|0,Mb=H+8|0;Wg(J,(a[b>>2]=a[Hb>>2],a[b+4>>2]=a[Hb+4>>2],f[b>>3]),(a[b>>2]=a[Mb>>2],a[b+4>>2]=a[Mb+4>>2],f[b>>3]));var Pb=J|0,Lb=(a[b>>2]=a[Pb>>2],a[b+4>>2]=a[Pb+4>>2],f[b>>3]),Sb=J+8|0,cc=(a[b>>2]=a[Sb>>2],a[b+4>>2]=a[Sb+4>>2],f[b>>3]);ii(c,d,g,eb,l,p,Lb,cc);ii(c,d,Oa,e-ta|0,Lb,cc,j,k);P=0;h=z;return P}function zk(a,b,c,d){a=c-a;b=d-b;return Math.sqrt(a*a+b*b)}function Dp(c,d,g,e,l,p,j,k,r,i,m){var n,x,v,t,y,z,B,F,D,A,C,E,I,Z=h;h=h+96|0;var T=Z+16,K=Z+32,M=Z+48,L=Z+64,G=Z+80;a:do{if(0<(d|0)){for(var H=c|0,J=c+8|0,R=d-1|0,Y=(R<<4)+c|0,P=(R<<4)+c+8|0,N=T|0,Q=T+8|0,ea=K|0,wa=K+8|0,U=Z|0,V=Z+8|0,W=M|0,X=M+8|0,ba=0,ma=0,aa=0,da=0,ca=0,O=0;;){I=(g+(40*O&-1)+8|0)>>2;var ga=(a[b>>2]=a[I],a[b+4>>2]=a[I+1],f[b>>3]);E=(g+(40*O&-1)+16|0)>>2;var $=(a[b>>2]=a[E],a[b+4>>2]=a[E+1],f[b>>3]),ia=ba+(ga*ga+$*$);C=(g+(40*O&-1)+24|0)>>2;var ua=(a[b>>2]=a[C],a[b+4>>2]=a[C+1],f[b>>3]);A=(g+(40*O&-1)+32|0)>>2;var Da=(a[b>>2]=a[A],a[b+4>>2]=a[A+1],f[b>>3]),Ja=ma+(ga*ua+$*Da),Ab=aa+(ua*ua+Da*Da);D=(g+(40*O&-1)|0)>>2;var ra,fa=(a[b>>2]=a[D],a[b+4>>2]=a[D+1],f[b>>3]),ya=1-fa;ra=ya*ya*(ya+3*fa);ze(T,(a[b>>2]=a[H>>2],a[b+4>>2]=a[H+4>>2],f[b>>3]),(a[b>>2]=a[J>>2],a[b+4>>2]=a[J+4>>2],f[b>>3]),ra);var ja,la=(a[b>>2]=a[D],a[b+4>>2]=a[D+1],f[b>>3]);ja=la*la*(3*(1-la)+la);ze(K,(a[b>>2]=a[Y>>2],a[b+4>>2]=a[Y+4>>2],f[b>>3]),(a[b>>2]=a[P>>2],a[b+4>>2]=a[P+4>>2],f[b>>3]),ja);var va=(a[b>>2]=a[N>>2],a[b+4>>2]=a[N+4>>2],f[b>>3]),oa=(a[b>>2]=a[Q>>2],a[b+4>>2]=a[Q+4>>2],f[b>>3]);Ak(Z,va,oa,(a[b>>2]=a[ea>>2],a[b+4>>2]=a[ea+4>>2],f[b>>3]),(a[b>>2]=a[wa>>2],a[b+4>>2]=a[wa+4>>2],f[b>>3]));var ka=(O<<4)+c|0,Ea=(a[b>>2]=a[ka>>2],a[b+4>>2]=a[ka+4>>2],f[b>>3]),Ka=(O<<4)+c+8|0,Na=(a[b>>2]=a[Ka>>2],a[b+4>>2]=a[Ka+4>>2],f[b>>3]);ji(M,Ea,Na,(a[b>>2]=a[U>>2],a[b+4>>2]=a[U+4>>2],f[b>>3]),(a[b>>2]=a[V>>2],a[b+4>>2]=a[V+4>>2],f[b>>3]));var Ba=(a[b>>2]=a[W>>2],a[b+4>>2]=a[W+4>>2],f[b>>3]),Wa=(a[b>>2]=a[X>>2],a[b+4>>2]=a[X+4>>2],f[b>>3]),ha=da,sa=(a[b>>2]=a[I],a[b+4>>2]=a[I+1],f[b>>3]),Ra=(a[b>>2]=a[E],a[b+4>>2]=a[E+1],f[b>>3]),bb=ha+(sa*Ba+Ra*Wa),Xa=ca,Sa=(a[b>>2]=a[C],a[b+4>>2]=a[C+1],f[b>>3]),qa=(a[b>>2]=a[A],a[b+4>>2]=a[A+1],f[b>>3]),Va=Xa+(Sa*Ba+qa*Wa),Ta=O+1|0;if((Ta|0)==(d|0)){var Aa=ia,fb=Ja,Ca=Ab,Ya=bb,$a=Va;break a}else{ba=ia,ma=Ja,aa=Ab,da=bb,ca=Va,O=Ta}}}else{$a=Ya=Ca=fb=Aa=0}}while(0);var La=Aa*Ca-fb*fb,pa=0<=La;if(1e-6>(pa?La:-La)){var Ga=0,Fa=0}else{Ga=(Aa*$a-fb*Ya)/La,Fa=(Ya*Ca-$a*fb)/La}var xa=d-1|0;if(1e-6<=(pa?La:-La)&0<Fa&0<Ga){var nb=Ga,jb=Fa,cb=k;F=cb>>2;var na=c;B=na>>2;a[F]=a[B];a[F+1]=a[B+1];a[F+2]=a[B+2];a[F+3]=a[B+3];ze(L,e,l,jb);var kb=r;z=kb>>2;var Kb=L;y=Kb>>2;a[z]=a[y];a[z+1]=a[y+1];a[z+2]=a[y+2];a[z+3]=a[y+3];var Ma=(xa<<4)+c|0,ta=i;t=ta>>2;var lb=Ma;v=lb>>2;a[t]=a[v];a[t+1]=a[v+1];a[t+2]=a[v+2];a[t+3]=a[v+3];ze(G,p,j,nb);var rb=m;x=rb>>2;var ab=G}else{var db=c|0,ob=(a[b>>2]=a[db>>2],a[b+4>>2]=a[db+4>>2],f[b>>3]),pb=c+8|0,ub=(a[b>>2]=a[pb>>2],a[b+4>>2]=a[pb+4>>2],f[b>>3]),gb=(xa<<4)+c|0,sb=(xa<<4)+c+8|0,Ia=zk(ob,ub,(a[b>>2]=a[gb>>2],a[b+4>>2]=a[gb+4>>2],f[b>>3]),(a[b>>2]=a[sb>>2],a[b+4>>2]=a[sb+4>>2],f[b>>3]))/3,jb=nb=Ia,cb=k;F=cb>>2;na=c;B=na>>2;a[F]=a[B];a[F+1]=a[B+1];a[F+2]=a[B+2];a[F+3]=a[B+3];ze(L,e,l,jb);kb=r;z=kb>>2;Kb=L;y=Kb>>2;a[z]=a[y];a[z+1]=a[y+1];a[z+2]=a[y+2];a[z+3]=a[y+3];Ma=(xa<<4)+c|0;ta=i;t=ta>>2;lb=Ma;v=lb>>2;a[t]=a[v];a[t+1]=a[v+1];a[t+2]=a[v+2];a[t+3]=a[v+3];ze(G,p,j,nb);rb=m;x=rb>>2;ab=G}n=ab>>2;a[x]=a[n];a[x+1]=a[n+1];a[x+2]=a[n+2];a[x+3]=a[n+3];h=Z}function yk(b){var c=h;if((a[1312706]|0)<(b|0)){var g=a[1312704];0==(g|0)?(g=wb(b<<4),a[1312704]=g,0==(g|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5370096,a[i+4>>2]=519,a[i+8>>2]=5339044,i)),P())):(g=gc(g,b<<4),a[1312704]=g,0==(g|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5370096,a[i+4>>2]=525,a[i+8>>2]=5335680,i)),P()));a[1312706]=b}h=c}function Ak(c,d,g,e,l){var p=c|0;f[b>>3]=d+e;a[p>>2]=a[b>>2];a[p+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=g+l;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function ji(c,d,g,e,l){var p=c|0;f[b>>3]=d-e;a[p>>2]=a[b>>2];a[p+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=g-l;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function Xg(c,d,g,e,l){var g=3*g,p=l+24|0;f[b>>3]=3*d+e-(g+c);a[p>>2]=a[b>>2];a[p+4>>2]=a[b+4>>2];e=l+16|0;f[b>>3]=3*c+g-6*d;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];e=l+8|0;f[b>>3]=3*(d-c);a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];f[b>>3]=c;a[l>>2]=a[b>>2];a[l+4>>2]=a[b+4>>2]}function Yg(c,d,g){0<=c&1>=c&&(d=(a[g>>2]<<3)+d|0,f[b>>3]=c,a[d>>2]=a[b>>2],a[d+4>>2]=a[b+4>>2],a[g>>2]=a[g>>2]+1|0)}function Ep(c,d,g,e,l,p,j,k,r,i,m,n){var x,v,t,y,z,B,F=0,D=h;h=h+64|0;var A=2==(n|0),C=D|0,E=D|0,I=D+8|0;B=(D+16|0)>>2;z=(D+24|0)>>2;y=(D+32|0)>>2;t=(D+40|0)>>2;v=(D+48|0)>>2;x=(D+56|0)>>2;for(var Z=1,T=4,K=4;;){f[b>>3]=g;a[E>>2]=a[b>>2];a[E+4>>2]=a[b+4>>2];f[b>>3]=e;a[I>>2]=a[b>>2];a[I+4>>2]=a[b+4>>2];f[b>>3]=K*l/3+g;a[B]=a[b>>2];a[B+1]=a[b+4>>2];f[b>>3]=K*p/3+e;a[z]=a[b>>2];a[z+1]=a[b+4>>2];f[b>>3]=j-T*r/3;a[y]=a[b>>2];a[y+1]=a[b+4>>2];f[b>>3]=k-T*i/3;a[t]=a[b>>2];a[t+1]=a[b+4>>2];f[b>>3]=j;a[v]=a[b>>2];a[v+1]=a[b+4>>2];f[b>>3]=k;a[x]=a[b>>2];a[x+1]=a[b+4>>2];if(Z&&Fp(C,4)<Fp(m,n)-.001){var M=0,F=1337;break}if(0!=(Gp(c,d,C)|0)){F=1327;break}if(0==K&0==T){F=1329;break}.01<K?(Z=0,T*=.5,K*=.5):K=T=Z=0}if(1327==F){return yk(a[1312707]+4|0),d=a[1312704],c=a[1312707],B=(a[b>>2]=a[B],a[b+4>>2]=a[B+1],f[b>>3]),g=(c<<4)+d|0,f[b>>3]=B,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],B=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]),z=c+1|0,g=(c<<4)+d+8|0,f[b>>3]=B,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2],y=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),B=(z<<4)+d|0,f[b>>3]=y,a[B>>2]=a[b>>2],a[B+4>>2]=a[b+4>>2],y=(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3]),t=c+2|0,z=(z<<4)+d+8|0,f[b>>3]=y,a[z>>2]=a[b>>2],a[z+4>>2]=a[b+4>>2],v=(a[b>>2]=a[v],a[b+4>>2]=a[v+1],f[b>>3]),y=(t<<4)+d|0,f[b>>3]=v,a[y>>2]=a[b>>2],a[y+4>>2]=a[b+4>>2],x=(a[b>>2]=a[x],a[b+4>>2]=a[x+1],f[b>>3]),v=(t<<4)+d+8|0,f[b>>3]=x,a[v>>2]=a[b>>2],a[v+4>>2]=a[b+4>>2],a[1312707]=c+3|0,h=D,1}if(1329==F){if(!A){return h=D,0}yk(a[1312707]+4|0);d=a[1312704];c=a[1312707];B=(a[b>>2]=a[B],a[b+4>>2]=a[B+1],f[b>>3]);g=(c<<4)+d|0;f[b>>3]=B;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];B=(a[b>>2]=a[z],a[b+4>>2]=a[z+1],f[b>>3]);z=c+1|0;g=(c<<4)+d+8|0;f[b>>3]=B;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];y=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]);B=(z<<4)+d|0;f[b>>3]=y;a[B>>2]=a[b>>2];a[B+4>>2]=a[b+4>>2];y=(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3]);t=c+2|0;z=(z<<4)+d+8|0;f[b>>3]=y;a[z>>2]=a[b>>2];a[z+4>>2]=a[b+4>>2];v=(a[b>>2]=a[v],a[b+4>>2]=a[v+1],f[b>>3]);y=(t<<4)+d|0;f[b>>3]=v;a[y>>2]=a[b>>2];a[y+4>>2]=a[b+4>>2];x=(a[b>>2]=a[x],a[b+4>>2]=a[x+1],f[b>>3]);v=(t<<4)+d+8|0;f[b>>3]=x;a[v>>2]=a[b>>2];a[v+4>>2]=a[b+4>>2];a[1312707]=c+3|0;h=D;return 1}if(1337==F){return h=D,M}}function Fp(c,d){if(1>=(d|0)){var g;return 0}for(var e=c|0,l=c+8|0,p=1,j=0,k=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),h=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);;){if(l=(p<<4)+c|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),k=l-k,e=(p<<4)+c+8|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),h=e-h,j+=Math.sqrt(k*k+h*h),p=p+1|0,(p|0)==(d|0)){g=j;break}else{k=l,h=e}}return g}function Gp(c,d,g){var e,l,p,j=0,k=h;h=h+64|0;var r=k+32,i=r|0;p=r>>2;var m=r+16|0;l=m>>2;var n=k|0,x=g|0,v=g+16|0,t=g+32|0,y=g+48|0,z=g+8|0,B=g+24|0,F=g+40|0,D=g+56|0,A=r|0,C=r+8|0,m=m|0,r=r+24|0,E=0;a:for(;;){if((E|0)>=(d|0)){var I=1,j=1355;break}e=((E<<5)+c|0)>>2;a[p]=a[e];a[p+1]=a[e+1];a[p+2]=a[e+2];a[p+3]=a[e+3];e=((E<<5)+c+16|0)>>2;a[l]=a[e];a[l+1]=a[e+1];a[l+2]=a[e+2];a[l+3]=a[e+3];e=Hp(g,i,n);b:do{if(4!=(e|0)){for(var Z=(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]),T=(a[b>>2]=a[C>>2],a[b+4>>2]=a[C+4>>2],f[b>>3]),K=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),M=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),L=0;;){if((L|0)>=(e|0)){break b}var G=(L<<3)+k|0,G=(a[b>>2]=a[G>>2],a[b+4>>2]=a[G+4>>2],f[b>>3]);do{if(!(1e-6>G|.999999<G)){var H=G*G*G,J=3*G,R=1-G,Y=J*G*R,J=J*R*R,P=R*R*R,R=P*(a[b>>2]=a[x>>2],a[b+4>>2]=a[x+4>>2],f[b>>3])+J*(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3])+Y*(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3])+H*(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),H=P*(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3])+J*(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3])+Y*(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3])+H*(a[b>>2]=a[D>>2],a[b+4>>2]=a[D+4>>2],f[b>>3]),Y=R-Z,J=H-T;if(.001<=Y*Y+J*J&&(R-=K,H-=M,.001<=R*R+H*H)){I=0;j=1356;break a}}}while(0);L=L+1|0}}}while(0);E=E+1|0}if(1356==j||1355==j){return h=k,I}}function Hp(c,d,g){var e,l,p,j,k,r=h;h=h+84|0;var i=r+32;j=r+56;var m=r+80;k=m>>2;var n=d|0,x=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),n=d+16|0;e=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3])-x;n=d+8|0;n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]);d=d+24|0;p=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])-n;a[k]=0;if(0!=e){var v=p/e,d=c+8|0;j=(c|0)>>2;var t=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])-v*(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3]);p=c+24|0;var d=(c+16|0)>>2,y=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])-v*(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);l=c+40|0;p=(c+32|0)>>2;var z=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])-v*(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]),B=c+56|0;l=(c+48|0)>>2;var F=r|0,c=F>>2;Xg(t,y,z,(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3])-v*(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]),F);n=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3])+(v*x-n);f[b>>3]=n;a[c]=a[b>>2];a[c+1]=a[b+4>>2];n=ki(F,i|0);if(4==(n|0)){return h=r,4}if(0>=(n|0)){return h=r,0}v=r+8|0;t=r+16|0;y=r+24|0;for(z=0;;){B=(z<<3)+i|0;B=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]);if(0<=B&1>=B){var D=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3]),A=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);Xg(D,A,(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]),(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]),F);D=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3]);A=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]);D=(D+B*(A+B*((a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3])+B*(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3])))-x)/e;0<=D&1>=D&&Yg(B,g,m)}z=z+1|0;if((z|0)==(n|0)){break}}g=a[k];h=r;return g}l=0==p;e=c|0;F=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);e=c+16|0;v=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);t=c+32|0;y=c+48|0;d=r|0;e=d>>2;Xg(F,v,(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),d);x=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])-x;f[b>>3]=x;a[e]=a[b>>2];a[e+1]=a[b+4>>2];x=ki(d,i|0);if(!l){if(4==(x|0)){return h=r,4}if(0>=(x|0)){return h=r,0}j=c+8|0;l=c+24|0;F=c+40|0;c=c+56|0;v=r+8|0;t=r+16|0;y=r+24|0;for(z=0;!(B=(z<<3)+i|0,B=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),0<=B&1>=B&&(D=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),A=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),Xg(D,A,(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]),(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),d),D=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),A=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),D=(D+B*(A+B*((a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3])+B*(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3])))-n)/p,0<=D&1>=D&&Yg(B,g,m)),z=z+1|0,(z|0)==(x|0));){}g=a[k];h=r;return g}p=c+8|0;p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);l=c+24|0;l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);F=c+40|0;c=c+56|0;Xg(p,l,(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]),(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),d);n=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])-n;f[b>>3]=n;a[e]=a[b>>2];a[e+1]=a[b+4>>2];n=ki(d,j|0);c=4==(n|0);a:do{if(4==(x|0)){if(c){return g=4,h=r,g}if(0<(n|0)){for(e=0;;){if(d=(e<<3)+j|0,Yg((a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),g,m),e=e+1|0,(e|0)==(n|0)){break a}}}}else{e=0<(x|0);if(c){if(e){d=0}else{break}for(;;){if(p=(d<<3)+i|0,Yg((a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),g,m),d=d+1|0,(d|0)==(x|0)){break a}}}if(e){e=0<(n|0);for(d=0;;){b:do{if(e){p=(d<<3)+i|0;p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);for(l=0;;){if(F=(l<<3)+j|0,p==(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3])&&Yg(p,g,m),l=l+1|0,(l|0)==(n|0)){break b}}}}while(0);d=d+1|0;if((d|0)==(x|0)){break a}}}}}while(0);g=a[k];h=r;return g}function Gc(a,b,c,d,f,p){a=(b-d)*(f-c)-(p-d)*(a-c);return 0<a?1:0>a?2:3}function Ip(b,c){var g,d,f=0,p=a[1310845];d=p>>2;for(var j=0;;){var k=p+(52*b&-1)|0,h=p+(52*c&-1)|0;g=((j<<4)+p+(52*b&-1)+4|0)>>2;var i=a[a[g]>>2],m=a[a[((52*c&-1)+4>>2)+d]>>2];if((i|0)==(m|0)){if(f=a[a[((52*c&-1)+8>>2)+d]>>2],(a[a[((j<<4)+(52*b&-1)+8>>2)+d]>>2]|0)==(f|0)){f=1411}else{var n=f,f=1409}}else{n=a[a[((52*c&-1)+8>>2)+d]>>2],f=1409}if(1409==f){if(f=0,(i|0)!=(n|0)){var x=i}else{(a[a[((j<<4)+(52*b&-1)+8>>2)+d]>>2]|0)==(m|0)?f=1411:x=i}}1411==f&&(a[((j<<4)+(52*b&-1)+16>>2)+d]=h,a[((52*c&-1)+16>>2)+d]=k,x=a[a[g]>>2]);i=a[a[((52*c&-1)+20>>2)+d]>>2];if((x|0)==(i|0)){if(f=a[a[((52*c&-1)+24>>2)+d]>>2],(a[a[((j<<4)+(52*b&-1)+8>>2)+d]>>2]|0)==(f|0)){f=1418}else{var v=f,f=1416}}else{v=a[a[((52*c&-1)+24>>2)+d]>>2],f=1416}if(1416==f){if(f=0,(x|0)!=(v|0)){var t=x}else{(a[a[((j<<4)+(52*b&-1)+8>>2)+d]>>2]|0)==(i|0)?f=1418:t=x}}1418==f&&(a[((j<<4)+(52*b&-1)+16>>2)+d]=h,a[((52*c&-1)+32>>2)+d]=k,t=a[a[g]>>2]);g=a[a[((52*c&-1)+36>>2)+d]>>2];if((t|0)==(g|0)){if(f=a[a[((52*c&-1)+40>>2)+d]>>2],(a[a[((j<<4)+(52*b&-1)+8>>2)+d]>>2]|0)==(f|0)){f=1424}else{var y=f,f=1422}}else{y=a[a[((52*c&-1)+40>>2)+d]>>2],f=1422}1422==f&&(f=0,(t|0)==(y|0)&&(a[a[((j<<4)+(52*b&-1)+8>>2)+d]>>2]|0)==(g|0)&&(f=1424));1424==f&&(a[((j<<4)+(52*b&-1)+16>>2)+d]=h,a[((52*c&-1)+48>>2)+d]=k);j=j+1|0;if(3==(j|0)){break}}}function Xj(c,d,g){var e,l,p,j,k,r,q,m,n,x,v,t,y,z,B,F,D=g>>2,A=0,C=h;h=h+16|0;F=C>>2;B=(c+4|0)>>2;Jp(a[B]);a[1312248]=0;a[1310847]=0;var E=a[B]<<1,I=h;if((a[1314335]|0)<(E|0)){var Z=a[1314336];if(0==(Z|0)){var G=wb(E<<2);a[1314336]=G;0==(G|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=564,a[i+8>>2]=5332812,i)),P())}else{var K=gc(Z,E<<2);a[1314336]=K;0==(K|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=571,a[i+8>>2]=5329876,i)),P())}a[1314335]=E}h=I;var M=(a[1314335]|0)/2&-1;a[1314334]=M;a[1314333]=M-1|0;var L=a[B],H=0<(L|0);z=(c|0)>>2;var J=a[z];a:do{if(H){for(var N=Infinity,R=-1,Y=0;;){var Q=(Y<<4)+J|0,U=(a[b>>2]=a[Q>>2],a[b+4>>2]=a[Q+4>>2],f[b>>3]),aa=N>U,ea=aa?Y:R,wa=Y+1|0;if((wa|0)<(L|0)){N=aa?U:N,R=ea,Y=wa}else{var da=ea;break a}}}else{da=-1}}while(0);var V=(da<<4)+J|0,W=(a[b>>2]=a[V>>2],a[b+4>>2]=a[V+4>>2],f[b>>3]),X=(da<<4)+J+8|0,ba=(a[b>>2]=a[X>>2],a[b+4>>2]=a[X+4>>2],f[b>>3]),ma=(0==(da|0)?L:da)-1|0,ib=(ma<<4)+J|0,ca=(a[b>>2]=a[ib>>2],a[b+4>>2]=a[ib+4>>2],f[b>>3]),$=(da|0)==(L-1|0)?0:da+1|0,O=($<<4)+J|0,ga=(a[b>>2]=a[O>>2],a[b+4>>2]=a[O+4>>2],f[b>>3]),ia=($<<4)+J+8|0,fa=(a[b>>2]=a[ia>>2],a[b+4>>2]=a[ia+4>>2],f[b>>3]);a:do{if(ca==W&W==ga&fa>ba){A=1431}else{var ua=(ma<<4)+J+8|0;if(1!=(Gc(ca,(a[b>>2]=a[ua>>2],a[b+4>>2]=a[ua+4>>2],f[b>>3]),W,ba,ga,fa)|0)){A=1431}else{if(H){for(var Da=0,Ja=L,Ab=J;;){if(0<(Da|0)){var ra=(Da<<4)+Ab|0,ha=Da-1|0,ya=(ha<<4)+Ab|0;if((a[b>>2]=a[ra>>2],a[b+4>>2]=a[ra+4>>2],f[b>>3])!=(a[b>>2]=a[ya>>2],a[b+4>>2]=a[ya+4>>2],f[b>>3])){A=1441}else{var ja=(Da<<4)+Ab+8|0,la=(ha<<4)+Ab+8|0;if((a[b>>2]=a[ja>>2],a[b+4>>2]=a[ja+4>>2],f[b>>3])==(a[b>>2]=a[la>>2],a[b+4>>2]=a[la+4>>2],f[b>>3])){var va=Ja}else{A=1441}}}else{A=1441}if(1441==A){var A=0,oa=a[1312248],ka=a[1312245];a[ka+(oa<<3)>>2]=(Da<<4)+Ab|0;a[ka+(oa<<3)+4>>2]=((oa|0)%(a[B]|0)<<3)+ka|0;a[a[1312246]+(oa<<2)>>2]=(oa<<3)+ka|0;a[1312248]=oa+1|0;va=a[B]}var Ea=Da+1|0;if((Ea|0)>=(va|0)){break a}Da=Ea;Ja=va;Ab=a[z]}}}}}while(0);a:do{if(1431==A&&H){for(var Ka=L,Na=L,Ba=J;;){var Wa=Ka-1|0;if((Wa|0)<(Na-1|0)){var sa=(Wa<<4)+Ba|0,qa=(Ka<<4)+Ba|0;if((a[b>>2]=a[sa>>2],a[b+4>>2]=a[sa+4>>2],f[b>>3])!=(a[b>>2]=a[qa>>2],a[b+4>>2]=a[qa+4>>2],f[b>>3])){A=1437}else{var Ra=(Wa<<4)+Ba+8|0,bb=(Ka<<4)+Ba+8|0;if((a[b>>2]=a[Ra>>2],a[b+4>>2]=a[Ra+4>>2],f[b>>3])!=(a[b>>2]=a[bb>>2],a[b+4>>2]=a[bb+4>>2],f[b>>3])){A=1437}}}else{A=1437}if(1437==A){var A=0,Xa=a[1312248],Sa=a[1312245];a[Sa+(Xa<<3)>>2]=(Wa<<4)+Ba|0;a[Sa+(Xa<<3)+4>>2]=((Xa|0)%(a[B]|0)<<3)+Sa|0;a[a[1312246]+(Xa<<2)>>2]=(Xa<<3)+Sa|0;a[1312248]=Xa+1|0}if(0>=(Wa|0)){break a}Ka=Wa;Na=a[B];Ba=a[z]}}}while(0);var xa=a[1312246],Va=a[1312248],Ta=xa>>2,Aa=0,fb=h,Ca=Va,Ya=Va;a:for(;;){var $a=Ya-1|0;if(3<(Ca|0)){var La=0}else{Aa=1503;break}for(;;){if((La|0)>=(Ca|0)){Aa=1502;break a}var pa=La+1|0,Ga=(La+2|0)%(Ca|0);if(0==(Kp(La,Ga,xa,Ca)|0)){La=pa}else{break}}var Fa=(pa|0)%(Ca|0);Lp(a[(La<<2>>2)+Ta],a[(Fa<<2>>2)+Ta],a[(Ga<<2>>2)+Ta]);var na=Ca-1|0;if((Fa|0)<(na|0)){for(var nb=Fa;;){var jb=nb+1|0;a[(nb<<2>>2)+Ta]=a[(jb<<2>>2)+Ta];if((jb|0)==($a|0)){Ca=na;Ya=$a;continue a}else{nb=jb}}}else{Ca=na,Ya=$a}}1502==Aa?(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=315,a[i+8>>2]=5370620,i)),h=fb):1503==Aa&&(Lp(a[Ta],a[Ta+1],a[Ta+2]),h=fb);var cb=a[1310847];a:do{if(0<(cb|0)){for(var ta=0;;){var kb=ta+1|0,Kb=(kb|0)<(cb|0);if(Kb){var Ma=kb}else{break a}for(;;){Ip(ta,Ma);var Oa=Ma+1|0;if((Oa|0)<(cb|0)){Ma=Oa}else{break}}if(Kb){ta=kb}else{break a}}}}while(0);for(var lb=d|0,rb=d+8|0,ab=0;(ab|0)<(cb|0);){if(0==(Bk(ab,(a[b>>2]=a[lb>>2],a[b+4>>2]=a[lb+4>>2],f[b>>3]),(a[b>>2]=a[rb>>2],a[b+4>>2]=a[rb+4>>2],f[b>>3]))|0)){ab=ab+1|0}else{break}}if((ab|0)==(cb|0)){Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=183,a[i+8>>2]=5347236,i));var db=-1;h=C;return db}var ob=d+16|0;y=(ob|0)>>2;t=(d+24|0)>>2;for(var pb=0;(pb|0)<(cb|0);){if(0==(Bk(pb,(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3]))|0)){pb=pb+1|0}else{break}}if((pb|0)==(cb|0)){return Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=191,a[i+8>>2]=5343184,i)),db=-1,h=C,db}if(0==(Mp(ab,pb)|0)){Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=198,a[i+8>>2]=5341640,i));Ck(2);a[D+1]=2;var ub=a[1312703];v=ub>>2;x=d>>2;a[v]=a[x];a[v+1]=a[x+1];a[v+2]=a[x+2];a[v+3]=a[x+3];n=(ub+16|0)>>2;m=ob>>2;a[n]=a[m];a[n+1]=a[m+1];a[n+2]=a[m+2];a[n+3]=a[m+3];a[D]=ub;db=0;h=C;return db}if((ab|0)==(pb|0)){Ck(2);a[D+1]=2;var gb=a[1312703];q=gb>>2;r=d>>2;a[q]=a[r];a[q+1]=a[r+1];a[q+2]=a[r+2];a[q+3]=a[r+3];k=(gb+16|0)>>2;j=ob>>2;a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];a[D]=gb;db=0;h=C;return db}a[F]=d;a[F+1]=0;var sb=C+8|0;a[sb>>2]=ob;a[F+3]=0;Zg(1,C|0);var Ia=a[1314334];a[1314332]=Ia;a:do{if(-1==(ab|0)){var vb=0,Ua=sb}else{var Ha=a[1310845];p=Ha>>2;for(var Za=ab,qb=Ia;;){a[((52*Za&-1)>>2)+p]=2;for(var Bb=0;3>(Bb|0);){var Pa=a[((Bb<<4)+(52*Za&-1)+16>>2)+p];if(0!=(Pa|0)&&1==(a[Pa>>2]|0)){break}Bb=Bb+1|0}if(3==(Bb|0)){var xb=a[1314336],za=a[a[xb+(a[1314334]<<2)>>2]>>2],Nb=a[xb+(a[1314333]<<2)>>2],Jb=a[Nb>>2],eb=(a[b>>2]=a[y],a[b+4>>2]=a[y+1],f[b>>3]),mb=(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3]),hb=za|0,zb=(a[b>>2]=a[hb>>2],a[b+4>>2]=a[hb+4>>2],f[b>>3]),tb=za+8|0,Db=(a[b>>2]=a[tb>>2],a[b+4>>2]=a[tb+4>>2],f[b>>3]),Cb=Jb|0,Ib=Jb+8|0,Eb=1==(Gc(eb,mb,zb,Db,(a[b>>2]=a[Cb>>2],a[b+4>>2]=a[Cb+4>>2],f[b>>3]),(a[b>>2]=a[Ib>>2],a[b+4>>2]=a[Ib+4>>2],f[b>>3]))|0),Ub=Eb?sb:Nb,Hb=Eb?Nb:sb}else{var Mb=a[((Bb<<4)+(52*Za&-1)+4>>2)+p],Pb=a[Mb>>2],Sb=a[a[(((Bb+1|0)%3<<4)+(52*Za&-1)+8>>2)+p]>>2],Zb=a[((Bb<<4)+(52*Za&-1)+8>>2)+p],Xb=a[Zb>>2],hc=Pb|0,fc=(a[b>>2]=a[hc>>2],a[b+4>>2]=a[hc+4>>2],f[b>>3]),cc=Pb+8|0,pc=(a[b>>2]=a[cc>>2],a[b+4>>2]=a[cc+4>>2],f[b>>3]),ec=Sb|0,hd=(a[b>>2]=a[ec>>2],a[b+4>>2]=a[ec+4>>2],f[b>>3]),qd=Sb+8|0,Vb=(a[b>>2]=a[qd>>2],a[b+4>>2]=a[qd+4>>2],f[b>>3]),Yb=Xb|0,Jc=Xb+8|0,Qb=1==(Gc(fc,pc,hd,Vb,(a[b>>2]=a[Yb>>2],a[b+4>>2]=a[Yb+4>>2],f[b>>3]),(a[b>>2]=a[Jc>>2],a[b+4>>2]=a[Jc+4>>2],f[b>>3]))|0),Ub=Qb?Mb:Zb,Hb=Qb?Zb:Mb}b:do{if((Za|0)==(ab|0)){Zg(2,Hb);Zg(1,Ub);var bc=qb}else{var ac=a[1314336];do{if((a[ac+(a[1314334]<<2)>>2]|0)!=(Ub|0)&&(a[ac+(a[1314333]<<2)>>2]|0)!=(Ub|0)){var ic=Dk(Ub);a[1314334]=ic;Zg(1,Ub);if((ic|0)<=(qb|0)){bc=qb;break b}bc=a[1314332]=ic;break b}}while(0);var jc=Dk(Hb);a[1314333]=jc;Zg(2,Hb);bc=(jc|0)<(qb|0)?a[1314332]=jc:qb}}while(0);for(var kc=0;;){if(3<=(kc|0)){vb=0;Ua=sb;break a}var uc=a[((kc<<4)+(52*Za&-1)+16>>2)+p];if(0!=(uc|0)&&1==(a[uc>>2]|0)){break}kc=kc+1|0}var dc=uc-Ha|0;if(-52==(dc|0)){vb=0;Ua=sb;break a}else{Za=(dc|0)/52&-1,qb=bc}}}}while(0);for(;;){var $b=vb+1|0,lc=a[Ua+4>>2];if(0==(lc|0)){break}else{vb=$b,Ua=lc}}Ck($b);a[D+1]=$b;for(var Kc=a[1312703],rc=sb,oc=vb;;){l=((oc<<4)+Kc|0)>>2;e=a[rc>>2]>>2;a[l]=a[e];a[l+1]=a[e+1];a[l+2]=a[e+2];a[l+3]=a[e+3];var Cc=a[rc+4>>2];if(0==(Cc|0)){break}else{rc=Cc,oc=oc-1|0}}a[D]=Kc;db=0;h=C;return db}function Bk(c,d,g){var e;e=a[1310845]>>2;var l=a[a[((52*c&-1)+4>>2)+e]>>2],p=a[a[((52*c&-1)+8>>2)+e]>>2],j=l|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),l=l+8|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),k=p|0,p=p+8|0,p=2!=(Gc(j,l,(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),d,g)|0)&1,k=a[a[((52*c&-1)+20>>2)+e]>>2],j=a[a[((52*c&-1)+24>>2)+e]>>2],l=k|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),k=k+8|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),h=j|0,j=j+8|0,p=(2!=(Gc(l,k,(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]),(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),d,g)|0)&1)+p|0,j=a[a[((52*c&-1)+36>>2)+e]>>2],c=a[a[((52*c&-1)+40>>2)+e]>>2];e=j|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);j=j+8|0;j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);l=c|0;c=c+8|0;d=(2!=(Gc(e,j,(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),d,g)|0)&1)+p|0;return(3==(d|0)|0==(d|0))&1}function Jp(b){var c=h;if((a[1312247]|0)<(b|0)){var g=a[1312245];0==(g|0)?(g=wb(b<<3),a[1312245]=g,0==(g|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=514,a[i+8>>2]=5327232,i)),P()),g=wb(b<<2),a[1312246]=g,0==(g|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=518,a[i+8>>2]=5378112,i)),P())):(g=gc(g,b<<3),a[1312245]=g,0==(g|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=524,a[i+8>>2]=5375428,i)),P()),g=gc(a[1312246],b<<2),a[1312246]=g,0==(g|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=530,a[i+8>>2]=5372708,i)),P()));a[1312247]=b}h=c}function Zg(b,c){var g,d=a[1314333],f=a[1314334],p=-1<(d-f|0);g=a[1314336]>>2;1==(b|0)?(p&&(a[c+4>>2]=a[(f<<2>>2)+g]),d=f-1|0,a[1314334]=d):(p&&(a[c+4>>2]=a[(d<<2>>2)+g]),d=d+1|0,a[1314333]=d);a[(d<<2>>2)+g]=c}function Mp(b,c){var d,e=0,f=a[1310845];d=(f+(52*b&-1)|0)>>2;if(0!=(a[d]|0)){var p;return 0}a[d]=1;if((b|0)==(c|0)){return 1}for(var j=0;3>(j|0);){var k=a[f+(52*b&-1)+(j<<4)+16>>2];if(0!=(k|0)&&0!=(Mp((k-f|0)/52&-1,c)|0)){p=1;e=1570;break}j=j+1|0}return 1570==e?p:a[d]=0}function Dk(c){var d,g=0,e=a[1314332];d=a[1314336]>>2;for(var c=c|0,l=a[1314334];(l|0)<(e|0);){var p=l+1|0,j=a[a[(p<<2>>2)+d]>>2],k=a[a[(l<<2>>2)+d]>>2],h=a[c>>2],i=j|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),j=j+8|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),m=k|0,m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),k=k+8|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),n=h|0,h=h+8|0;if(1==(Gc(i,j,m,k,(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]))|0)){var x=l,g=1580;break}else{l=p}}if(1580==g){return x}for(l=a[1314333];;){if((l|0)<=(e|0)){x=e;g=1578;break}p=l-1|0;j=a[a[(p<<2>>2)+d]>>2];k=a[a[(l<<2>>2)+d]>>2];h=a[c>>2];i=j|0;i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);j=j+8|0;j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);m=k|0;m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]);k=k+8|0;k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);n=h|0;h=h+8|0;if(2==(Gc(i,j,m,k,(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]))|0)){x=l;g=1579;break}else{l=p}}if(1578==g||1579==g){return x}}function Kp(c,d,g,e){var g=g>>2,l=0,p=a[a[((c-1+e|0)%(e|0)<<2>>2)+g]>>2],j=a[a[(c<<2>>2)+g]>>2],k=a[a[((c+1|0)%(e|0)<<2>>2)+g]>>2],h=p|0,i=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]),p=p+8|0,m=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),p=j|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=j+8|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),h=k|0,n=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]),k=k+8|0,x=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),v=1==(Gc(i,m,p,j,n,x)|0),h=a[a[(d<<2>>2)+g]>>2],k=h|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),h=h+8|0,h=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]);if(0==((v?(1==(Gc(p,j,k,h,i,m)|0)?1==(Gc(k,h,p,j,n,x)|0):0)&1:2==(Gc(p,j,k,h,n,x)|0)&1)|0)){var t;return 0}for(m=0;;){if((m|0)>=(e|0)){t=1;l=1591;break}i=m+1|0;n=(i|0)%(e|0);if((m|0)==(c|0)|(n|0)==(c|0)|(m|0)==(d|0)|(n|0)==(d|0)){m=i}else{var m=a[a[(m<<2>>2)+g]>>2],y=a[a[(n<<2>>2)+g]>>2],z=m|0,B=m+8|0;a:{var m=p,n=j,x=k,v=h,z=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3]),B=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),F=Gc(m,n,x,v,z,B);if(3!=(F|0)){var A=y|0,A=(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]),C=y+8|0,E=(a[b>>2]=a[C>>2],a[b+4>>2]=a[C+4>>2],f[b>>3]),C=Gc(m,n,x,v,A,E);if(3!=(C|0)){var G=Gc(z,B,A,E,m,n);if(3!=(G|0)&&(A=Gc(z,B,A,E,x,v),3!=(A|0))){m=(1==(F|0)^1==(C|0)?1==(G|0)^1==(A|0):0)&1;break a}}}0!=(li(m,n,x,v,z,B)|0)?m=1:(F=y|0,F=(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3]),y=y+8|0,y=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),m=0!=(li(m,n,x,v,F,y)|0)?1:0==(li(z,B,F,y,m,n)|0)?0!=(li(z,B,F,y,x,v)|0)&1:1)}if(0==(m|0)){m=i}else{t=0;l=1592;break}}}if(1592==l||1591==l){return t}}function Lp(b,c,d){var e;e=a[1310847];var f=a[1310846];if((e|0)<(f|0)){f=e}else{e=f+20|0;f=h;if((a[1310846]|0)<(e|0)){var p=a[1310845];0==(p|0)?(p=wb(52*e&-1),a[1310845]=p,0==(p|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=543,a[i+8>>2]=5367648,i)),P())):(p=gc(p,52*e&-1),a[1310845]=p,0==(p|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=549,a[i+8>>2]=5365240,i)),P()));a[1310846]=e}h=f;f=a[1310847]}a[1310847]=f+1|0;p=a[1310845];e=p>>2;p=p+(52*f&-1)|0;a[p>>2]=0;a[((52*f&-1)+4>>2)+e]=b;a[((52*f&-1)+8>>2)+e]=c;a[((52*f&-1)+16>>2)+e]=0;a[((52*f&-1)+20>>2)+e]=c;a[((52*f&-1)+24>>2)+e]=d;a[((52*f&-1)+32>>2)+e]=0;a[((52*f&-1)+36>>2)+e]=d;a[((52*f&-1)+40>>2)+e]=b;a[((52*f&-1)+48>>2)+e]=0;a[((52*f&-1)+12>>2)+e]=p;a[((52*f&-1)+28>>2)+e]=p;a[((52*f&-1)+44>>2)+e]=p}function li(a,b,c,d,f,p){var j=c-a,k=d-b,h=f-a,i=p-b;return 3!=(Gc(a,b,c,d,f,p)|0)?0:(0>h*j+i*k?0:h*h+i*i<=j*j+k*k)&1}function ki(c,d){var g=c+24|0,e=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);if(1e-7>e&-1e-7<e){var l;l=c+16|0;g=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);1e-7>g&-1e-7<g?(g=c+8|0,l=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),1e-7>g&-1e-7<g?l=1e-7>l&-1e-7<l?4:0:(f[b>>3]=-l/g,a[d>>2]=a[b>>2],a[d+4>>2]=a[b+4>>2],l=1)):(l=c+8|0,e=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])/(2*g),g=l*l-e/g,0>g?l=0:0==g?(f[b>>3]=-l,a[d>>2]=a[b>>2],a[d+4>>2]=a[b+4>>2],l=1):(g=Math.sqrt(g)-l,f[b>>3]=g,a[d>>2]=a[b>>2],a[d+4>>2]=a[b+4>>2],e=d+8|0,f[b>>3]=-2*l-g,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],l=2));return l}var p=c+8|0,g=c+16|0,j=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])/(3*e),p=p/e,k=g*g,e=2*g*k-g*p+j/e,j=p/3-k,p=e*e,j=p+4*j*j*j;0>j?(p=.5*Math.sqrt(p-j),e=Math.atan2(Math.sqrt(-j),-e),p=2*(0>p?-1*Math.pow(-p,.3333333333333333):Math.pow(p,.3333333333333333)),j=p*Math.cos(e/3),f[b>>3]=j,a[d>>2]=a[b>>2],a[d+4>>2]=a[b+4>>2],k=d+8|0,f[b>>3]=p*Math.cos((e+6.283185307179586)/3),a[k>>2]=a[b>>2],a[k+4>>2]=a[b+4>>2],k=d+16|0,f[b>>3]=p*Math.cos((e-3.141592653589793-3.141592653589793)/3),a[k>>2]=a[b>>2],a[k+4>>2]=a[b+4>>2],e=3,p=j):(p=.5*(Math.sqrt(j)-e),e=-e-p,p=(0>p?-1*Math.pow(-p,.3333333333333333):Math.pow(p,.3333333333333333))+(0>e?-1*Math.pow(-e,.3333333333333333):Math.pow(e,.3333333333333333)),f[b>>3]=p,a[d>>2]=a[b>>2],a[d+4>>2]=a[b+4>>2],0<j?e=1:(e=-.5*p,j=d+16|0,f[b>>3]=e,a[j>>2]=a[b>>2],a[j+4>>2]=a[b+4>>2],j=d+8|0,f[b>>3]=e,a[j>>2]=a[b>>2],a[j+4>>2]=a[b+4>>2],e=3));for(j=0;;){k=(j<<3)+d|0;f[b>>3]=p-g;a[k>>2]=a[b>>2];a[k+4>>2]=a[b+4>>2];j=j+1|0;if((j|0)>=(e|0)){l=e;break}p=(j<<3)+d|0;p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])}return l}function Yj(b,c,d){var e,f,p,j,k,h;e=3*c&-1;var i=e-2|0,m=a[1312764];(i|0)>(a[1312763]|0)&&(m=0==(m|0)?wb(i<<4):gc(m,i<<4),a[1312764]=m,a[1312763]=i);h=m>>2;k=b>>2;a[h]=a[k];a[h+1]=a[k+1];a[h+2]=a[k+2];a[h+3]=a[k+3];xg(m+16|0,b);c=c-1|0;if(1<(c|0)){h=1;for(k=2;!(j=((k<<4)+m|0)>>2,f=(h<<4)+b|0,p=f>>2,a[j]=a[p],a[j+1]=a[p+1],a[j+2]=a[p+2],a[j+3]=a[p+3],j=(k+1<<4)+m|0,p=j>>2,xg(j,f),f=((k+2<<4)+m|0)>>2,a[f]=a[p],a[f+1]=a[p+1],a[f+2]=a[p+2],a[f+3]=a[p+3],h=h+1|0,(h|0)==(c|0));){k=k+3|0}k=c;c=e-4|0}else{k=1,c=2}e=((c<<4)+m|0)>>2;k=(k<<4)+b|0;b=k>>2;a[e]=a[b];a[e+1]=a[b+1];a[e+2]=a[b+2];a[e+3]=a[b+3];xg((c+1<<4)+m|0,k);a[d+4>>2]=i;a[d>>2]=m}function ac(b,c,d){b>>=2;0==(d|0)?(c=0==(c|0)?1024:c,a[b+3]=1,d=wb(c),a[b]=d):(a[b]=d,a[b+3]=0);a[b+2]=d+c|0;a[b+1]=d;n[d]=0}function qa(b,c){var d,e=b+8|0;d=(b|0)>>2;var f=a[d],p=a[e>>2]-f|0,j=p<<1,p=p+c|0,j=p>>>0>j>>>0?p:j,p=b+4|0,k=a[p>>2]-f|0,h=b+12|0;0==(a[h>>2]|0)?(f=wb(j),$d(f,a[d],k),a[h>>2]=1):f=gc(f,j);a[d]=f;a[p>>2]=f+k|0;a[e>>2]=f+j|0}function Cb(b,c){var d=xa(c),e;e=(b+4|0)>>2;var f=a[e];(f+d|0)>>>0>a[b+8>>2]>>>0&&(qa(b,d),f=a[e]);$d(f,c,d);a[e]=a[e]+d|0}function Xb(a,b){0!=(b|0)&&E(a)}function Ck(b){var c=h;if((a[1312705]|0)<(b|0)){var d=a[1312703];0==(d|0)?(d=wb(b<<4),a[1312703]=d,0==(d|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=584,a[i+8>>2]=5339044,i)),P())):(d=gc(d,b<<4),a[1312703]=d,0==(d|0)&&(Lb(a[Qa>>2],5338480,(i=h,h=h+12|0,a[i>>2]=5362748,a[i+4>>2]=590,a[i+8>>2]=5335680,i)),P()));a[1312705]=b}h=c}function Sh(b){var c=a[b>>2]<<28>>28;return 3==(c|0)?a[a[b+16>>2]+12>>2]:1==(c|0)?a[a[a[b+20>>2]+16>>2]+4>>2]:2==(c|0)?a[a[a[a[b+16>>2]+20>>2]+16>>2]+8>>2]:0}function tb(b,c){if(-1>=(c|0)){var d;return 0}return d=a[a[b+4>>2]+(c<<2)>>2]}function Np(b,c,d){var e,f=bc(1,16);e=f>>2;a[e]=dc(c);a[e+1]=dc(d);n[f+12|0]=1;c=b+4|0;d=Mb(a[c>>2]);a[e+2]=d;b=(b+8|0)>>2;e=a[b];e=0==(e|0)?wb((d<<2)+8|0):gc(e,(d<<2)+8|0);a[b]=e;a[e+(d<<2)>>2]=f;a[a[b]+(d+1<<2)>>2]=0;c=a[c>>2];J[a[c>>2]](c,f,1);return f}function Mf(b,c,d){var e=0,f=Q(b,c);if(0==(f|0)){var p=1,j=Np(Sh(b),c,d),e=1720}else{var c=f+4|0,k=a[c>>2];if(0==($(k,d)|0)){var h=f}else{Qb(k),a[c>>2]=dc(d),p=0,j=f,e=1720}}if(1720==e){if(0==(j|0)){h=0}else{d=a[b>>2]<<28>>28;if(2==(d|0)){Op(a[a[b+12>>2]+20>>2],j,p)}else{if(1==(d|0)){Pp(a[b+20>>2],j,p)}else{if(3==(d|0)){if(d=j,e=b+36|0,f=a[e>>2],0==(f|0)){Ae(b|0,d,p)}else{if(b=ha(a[a[f+20>>2]+20>>2]),0!=(b|0)){for(;!(Ae(vd(b)|0,d,p),b=sa(a[a[a[e>>2]+20>>2]+20>>2],b),0==(b|0));){}}}}}}h=j}}return h}function Q(b,c){var d=a[Sh(b)+4>>2];return J[a[d>>2]](d,c,512)}function Pp(b,c,d){var e=b+20|0,f=ha(a[e>>2]);a:do{if(0!=(f|0)){for(var p=f;;){if(Ae(p|0,c,d),p=sa(a[e>>2],p),0==(p|0)){break a}}}}while(0);e=b+36|0;f=a[e>>2];if(0==(f|0)){if(e=a[b+40>>2],0!=(e|0)){for(;!(Ae(a[e>>2]|0,c,d),e=a[e+8>>2],0==(e|0));){}}}else{if(b=ha(a[a[f+20>>2]+20>>2]),0!=(b|0)){for(;;){f=a[vd(b)+40>>2];a:do{if(0!=(f|0)){for(p=f;;){if(Ae(a[p>>2]|0,c,d),p=a[p+8>>2],0==(p|0)){break a}}}}while(0);b=sa(a[a[a[e>>2]+20>>2]+20>>2],b);if(0==(b|0)){break}}}}}function Op(b,c,d){var e=b+20|0,f=ha(a[e>>2]);a:do{if(0!=(f|0)){for(var p=b+28|0,j=f;;){var k=zb(b,j);b:do{if(0!=(k|0)){for(var h=k;;){if(Ae(h|0,c,d),h=Db(a[p>>2],h),0==(h|0)){break b}}}}while(0);j=sa(a[e>>2],j);if(0==(j|0)){break a}}}}while(0);e=b+36|0;f=a[e>>2];if(0==(f|0)){if(b=a[b+40>>2],0!=(b|0)){for(;!(Ae(a[b+4>>2]|0,c,d),b=a[b+8>>2],0==(b|0));){}}}else{if(b=ha(a[a[f+20>>2]+20>>2]),0!=(b|0)){for(;;){f=a[vd(b)+40>>2];a:do{if(0!=(f|0)){for(p=f;;){if(Ae(a[p+4>>2]|0,c,d),p=a[p+8>>2],0==(p|0)){break a}}}}while(0);b=sa(a[a[a[e>>2]+20>>2]+20>>2],b);if(0==(b|0)){break}}}}}function mi(b,c,d){b=0==(b|0)?a[1345659]:b;return(b|0)!=(a[b+32>>2]|0)?0:c=Mf(b|0,c,d)}function Nf(b,c,d){b=0==(b|0)?a[1345659]:b;return(b|0)!=(a[b+32>>2]|0)?0:c=Mf(a[a[b+40>>2]>>2]|0,c,d)}function wf(b,c,d){b=0==(b|0)?a[1345659]:b;return(b|0)!=(a[b+32>>2]|0)?0:c=Mf(a[a[b+40>>2]+4>>2]|0,c,d)}function Ek(b){Rc(a[b+4>>2]);var c=b+8|0,d=a[c>>2];if(0!=(d|0)){var e=a[d>>2];a:do{if(0==(e|0)){var f=d}else{for(var p=0,j=e;;){p=p+1|0;Qb(a[j>>2]);Qb(a[j+4>>2]);E(j);var k=a[c>>2],j=a[k+(p<<2)>>2];if(0==(j|0)){f=k;break a}}}}while(0);E(f)}E(b)}function Fk(b){var c,d=bc(1,12);c=d>>2;a[c]=b;a[c+1]=Bc(5325232,5380184);a[c+2]=0;return d}function Gk(b,c){var d=Mb(a[c+4>>2]);if(0<(d|0)){for(var e=c+8|0,f=0;;){var p=a[a[e>>2]+(f<<2)>>2],j=Np(b,a[p>>2],a[p+4>>2]);n[j+12|0]=n[p+12|0];n[j+13|0]=n[p+13|0];f=f+1|0;if((f|0)==(d|0)){break}}}}function U(a,b){return tb(a,Qp(a,b))}function Qp(b,c){var d=Q(b,c);return 0==(d|0)?-1:d=a[d+8>>2]}function Pc(a,b,c){hc(a,Qp(a,b),c)}function hc(b,c,d){if(-1>=(c|0)){return-1}var e=(c<<2)+a[b+4>>2]|0;Qb(a[e>>2]);a[e>>2]=dc(d);b=a[b+8>>2]+((c|0)/8&-1)|0;n[b]=(ca[b]|1<<(c&7))&255;return 0}function fp(b,c,d){var e=Q(b,c);0==(e|0)?(e=a[b>>2]<<28>>28,c=2==(e|0)?wf(a[a[b+12>>2]+20>>2],c,5338228):3==(e|0)?mi(a[b+32>>2],c,5338228):1==(e|0)?Nf(a[b+20>>2],c,5338228):0):c=e;hc(b,a[c+8>>2],d)}function Rh(b,c){var d,e=a[b>>2]<<28>>28,f=2==(e|0);if((e|0)==(a[c>>2]<<28>>28|0)){var e=1,p=a[Sh(b)+8>>2];a:for(;;){for(;;){if(!e){break a}var j=p+4|0,p=a[p>>2];d=p>>2;if(0==(p|0)){break a}if(!f){break}if(0==(a[d+2]|0)){p=j}else{break}}e=Q(c,a[d]);if(0==(e|0)){break}e=0==(hc(c,a[e+8>>2],tb(b,a[d+2]))|0);p=j}}}function Ae(b,c,d){var e=a[c+8>>2];if(0==(d|0)){0==(n[a[b+8>>2]+((e|0)/8&-1)|0]<<24>>24&1<<(e&7)|0)&&(b=b+4|0,Qb(a[a[b>>2]+(e<<2)>>2]),c=dc(a[c+4>>2]),a[a[b>>2]+(e<<2)>>2]=c)}else{var d=(b+4|0)>>2,f=a[d],f=0==(f|0)?wb((e<<2)+4|0):gc(f,(e<<2)+4|0);a[d]=f;c=dc(a[c+4>>2]);a[a[d]+(e<<2)>>2]=c;0==(e&7|0)&&(b=b+8|0,c=a[b>>2],e=(e|0)/8&-1,d=e+1|0,c=0==(c|0)?wb(d):gc(c,d),a[b>>2]=c,n[c+e|0]=0)}}function bj(b,c,d){var e=b+24|0,f=cg(a[e>>2],c,d,0);return 0!=(f|0)?f:0!=(a[b>>2]&16|0)?0:b=cg(a[e>>2],d,c,0)}function cg(b,c,d,e){var f,p=h;h=h+32|0;f=p>>2;var j=p+28|0;a[j>>2]=e;a[f+4]=c;a[f+3]=d;e=0!=(e|0);a[f+1]=e?j:0;f=a[b>>2];j=p|0;if(e){return c=J[f](b,j,4),h=p,c}b=J[f](b,j,8);if(0==(b|0)||(a[b+16>>2]|0)==(c|0)&&(a[b+12>>2]|0)==(d|0)){return h=p,b}h=p;return 0}function Rp(b,c){var d=a[c>>2];16==(d&240|0)&&(a[c>>2]=d&-241|32);$g(b,c)}function $g(b,c){var d=b+24|0,e=a[d>>2],f=c|0;if(0==(J[a[e>>2]](e,f,4)|0)){e=c+16|0;dg(b,a[e>>2]);var p=c+12|0;dg(b,a[p>>2]);var j=b+28|0,k=a[j>>2];J[a[k>>2]](k,f,1);d=a[d>>2];J[a[d>>2]](d,f,1);d=a[j>>2];f=J[a[d>>2]](d,f,16);0!=(f|0)&&(a[f+16>>2]|0)==(a[e>>2]|0)&&(a[f+12>>2]|0)==(a[p>>2]|0)&&(f=a[c>>2],268435456>f<<24>>>0&&(a[c>>2]=f&-241|16));if(0==(a[b>>2]&64|0)&&(e=a[b+36>>2],f=a[e+20>>2],e=cf(f,e),0!=(e|0))){for(f=f+24|0;!($g(vd(a[e+16>>2]),c),e=ah(a[f>>2],e),0==(e|0));){}}}}function Gg(a,b){if(0==(a|0)|0==(b|0)){var c=0}else{c=zb(a,b),c=0!=(c|0)?c:cf(a,b)}return c}function zb(b,c){var d,e=h;h=h+28|0;d=e>>2;if(0==(b|0)|0==(c|0)){return h=e,0}a[d+4]=c;a[d+3]=0;a[d+1]=0;d=a[b+28>>2];d=J[a[d>>2]](d,e|0,8);if(0==(d|0)){return h=e,d}h=e;return(a[d+16>>2]|0)==(c|0)?d:0}function cf(b,c){var d,e=h;h=h+28|0;d=e>>2;if(0==(b|0)|0==(c|0)){return h=e,0}a[d+3]=c;a[d+4]=0;a[d+1]=0;d=a[b+24>>2];d=J[a[d>>2]](d,e|0,8);if(0==(d|0)){return h=e,d}h=e;return(a[d+12>>2]|0)==(c|0)?d:0}function Hg(b,c,d){var e=0;if(0==(b|0)|0==(c|0)|0==(d|0)){var f;return 0}a:do{if((a[c+16>>2]|0)==(d|0)){var p=a[b+28>>2],p=J[a[p>>2]](p,c|0,8);if(0!=(p|0)&&(a[p+16>>2]|0)==(d|0)){return f=p}for(var p=b+24|0,j=cf(b,d);;){if(0==(j|0)){var k=0;break a}var h=a[j+12>>2];if(!((h|0)==(a[j+16>>2]|0)&(h|0)==(d|0))){k=j;break a}h=a[p>>2];j=J[a[h>>2]](h,j|0,8)}}else{if((a[c+12>>2]|0)==(d|0)){k=a[b+24>>2],k=J[a[k>>2]](k,c|0,8)}else{return f=0}}}while(0);b=b+24|0;for(c=k;;){if(0==(c|0)){f=0;e=1932;break}var k=a[c+12>>2],i=(k|0)==(d|0);if(!((k|0)==(a[c+16>>2]|0)&i)){e=1930;break}k=a[b>>2];c=J[a[k>>2]](k,c|0,8)}if(1930==e){return i?c:0}if(1932==e){return f}}function Db(b,c){var d=J[a[b>>2]](b,c|0,8);return 0==(d|0)?d:(a[d+16>>2]|0)==(a[c+16>>2]|0)?d:0}function ah(b,c){var d=J[a[b>>2]](b,c|0,8);return 0==(d|0)?d:(a[d+12>>2]|0)==(a[c+12>>2]|0)?d:0}function Hk(b,c,d,e){var f,p=bc(1,n[5382640]?184:0);f=p>>2;a[p>>2]=a[p>>2]&-16|2;a[f+4]=c;a[f+3]=d;d=(b+16|0)>>2;b=a[d]+20|0;c=a[b>>2];a[b>>2]=c+1|0;a[f+5]=c;c=Mb(a[a[a[d]+8>>2]+4>>2]);if(0==(c|0)){return a[f+1]=0,a[f+2]=0,p}b=(p+4|0)>>2;a[b]=bc(c,4);a[f+2]=bc((c+7|0)/8&-1,1);if(0>=(c|0)){return p}f=e+4|0;if(0==(e|0)){for(e=0;!(f=dc(a[a[a[a[a[d]+8>>2]+8>>2]+(e<<2)>>2]+4>>2]),a[a[b]+(e<<2)>>2]=f,e=e+1|0,(e|0)==(c|0));){}}else{for(e=0;!(d=dc(a[a[f>>2]+(e<<2)>>2]),a[a[b]+(e<<2)>>2]=d,e=e+1|0,(e|0)==(c|0));){}}return p}function sf(b,c,d){var e,f,p=h;h=h+128|0;e=(b+40|0)>>2;f=a[a[e]+4>>2];var j=a[a[f+4>>2]>>2];a[f+12>>2]=d;a[a[a[e]+4>>2]+16>>2]=c;f=b>>2;do{if(0==(a[f]&32|0)){if(0==n[j]<<24>>24){var k=p|0,r=a[1331225];a[1331225]=r+1|0;Pa(k,5335676,(i=h,h=h+4|0,a[i>>2]=r,i));a[a[a[a[e]+4>>2]+4>>2]>>2]=k;k=0}else{k=b+24|0;r=cg(a[k>>2],c,d,j);if(0==(r|0)){if(0!=(a[f]&16|0)){k=32;break}f=cg(a[k>>2],d,c,j);if(0==(f|0)){k=32;break}else{c=f}}else{c=r}Rp(b,c);b=c;e=a[e];e=e+4|0;e>>=2;e=a[e];e=e+4|0;e>>=2;e=a[e];e>>=2;a[e]=j;h=p;return b}}else{k=b+24|0;r=cg(a[k>>2],c,d,0);if(0==(r|0)){if(0!=(a[f]&16|0)){k=0;break}f=cg(a[k>>2],d,c,0);if(0==(f|0)){k=0;break}else{c=f}}else{c=r}$g(b,c);b=c;e=a[e];e=e+4|0;e>>=2;e=a[e];e=e+4|0;e>>=2;e=a[e];e>>=2;a[e]=j;h=p;return b}}while(0);c=Hk(b,c,d,a[a[e]+4>>2]);$g(b,c);b=a[e];d=a[b>>2];a[a[b+4>>2]+16>>2]=d;a[a[a[e]+4>>2]+12>>2]=d;a[c>>2]=a[c>>2]&-241|k;e=a[e];e=(e+4|0)>>2;e=a[e];e=(e+4|0)>>2;e=a[e];a[e>>2]=j;h=p;return c}function Sp(b){var c=b|0;a[b>>2]|=15;var d=Mb(a[a[a[a[a[b+16>>2]+20>>2]+16>>2]+8>>2]+4>>2]),e=b+4|0,f=a[e>>2];if(0<(d|0)){for(var p=0;;){if(Qb(a[f+(p<<2)>>2]),p=p+1|0,f=a[e>>2],(p|0)==(d|0)){j=f;break}}E(j)}else{var j,d=f;E(d)}b=a[(b+8|0)>>2];E(b);E(c)}function ni(b,c){var d,e=h;d=(b+24|0)>>2;var f=a[d],p=c|0;if(0==(J[a[f>>2]](f,p,4)|0)){aa(1,5360664,(i=h,h=h+4|0,a[i>>2]=c,i)),Fh(a[d],64)}else{a:do{if(0==(a[b>>2]&64|0)){var j=a[b+36>>2],f=a[j+20>>2],j=zb(f,j);if(0!=(j|0)){for(f=f+28|0;;){var k=vd(a[j+12>>2]),r=a[k+24>>2];0!=(J[a[r>>2]](r,p,4)|0)&&ni(k,c);j=Db(a[f>>2],j);if(0==(j|0)){break a}}}}}while(0);d=a[d];J[a[d>>2]](d,p,2);d=a[b+28>>2];J[a[d>>2]](d,p,2);(a[b+32>>2]|0)==(b|0)&&Sp(c)}h=e}function Tp(b,c){var d=0==(b|0)?0:a[b>>2],e=a[c+4>>2],e=0==(e|0)?0:a[e>>2];return 0==(d|0)?(0!=(e|0))<<31>>31:0==(e|0)?1:d=$(d,e)}function vd(b){return 0!=(a[a[b+20>>2]+36>>2]|0)?0:b=a[a[b+4>>2]>>2]}function Ik(b,c){var d,e=bc(1,12);d=e>>2;var f=b+40|0;a[d+2]=a[f>>2];if(0==(c|0)){var p=0,j=0}else{p=a[c+4>>2],j=a[c>>2]}j=Jk(b,5338748,j);a[d]=j;a[d+1]=Hk(b,j,j,p);a[f>>2]=e}function Up(b){var c;c=b+40|0;b=a[c>>2];if(0!=(b|0)){a[c>>2]=a[b+8>>2];var d=b|0,e=a[d>>2];c=(b+4|0)>>2;a[a[c]+12>>2]=e;a[a[c]+16>>2]=e;Sp(a[c]);Kk(a[d>>2]);E(b)}}function Bh(b,c){var d=oi(b,0,c),e=oi(b,0,7);if(0==(d|0)|0==(e|0)){return 0}Nf(e,5370084,0);e=Og(e,b);a[d+36>>2]=e;a[a[e+4>>2]>>2]=d|0;return d}function oi(b,c,d){var e,f=h;if(!n[5382612]){return aa(1,5374984,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),h=f,0}var p=bc(1,n[5382660]?288:0);e=p>>2;a[p>>2]=d<<4&240|a[p>>2]&-256|3;a[e+5]=Bc(5325160,5380184);a[e+6]=Bc(5325268,5380184);a[e+7]=Bc(5325124,5380184);d=0==(c|0);a:do{if(d){var j;j=bc(1,24);a[j>>2]=Bc(5325196,5380184);var k=j+12|0;a[k>>2]=Fk(5372324);var r=j+4|0;a[r>>2]=Fk(5329472);var q=j+8|0;a[q>>2]=Fk(5374900);var m=a[1345659];0!=(m|0)&&(Gk(a[k>>2],a[a[m+16>>2]+12>>2]),Gk(a[r>>2],a[a[a[1345659]+16>>2]+4>>2]),Gk(a[q>>2],a[a[a[1345659]+16>>2]+8>>2]));a[e+4]=j;a[e+8]=p;j=Mb(a[a[j+12>>2]+4>>2]);if(0==(j|0)){a[e+1]=0,a[e+2]=0}else{if(k=p+4|0,a[k>>2]=bc(j,4),a[e+2]=bc((j+7|0)/8&-1,1),0<(j|0)){for(r=0;;){if(q=dc(a[a[a[1345659]+4>>2]+(r<<2)>>2]),a[a[k>>2]+(r<<2)>>2]=q,r=r+1|0,(r|0)==(j|0)){break a}}}}}else{if(j=c+16|0,a[e+4]=a[j>>2],a[e+8]=a[c+32>>2],j=Mb(a[a[a[j>>2]+12>>2]+4>>2]),0==(j|0)){a[e+1]=0,a[e+2]=0}else{if(k=p+4|0,a[k>>2]=bc(j,4),a[e+2]=bc((j+7|0)/8&-1,1),0<(j|0)){r=c+4|0;for(q=0;;){if(m=dc(a[a[r>>2]+(q<<2)>>2]),a[a[k>>2]+(q<<2)>>2]=m,q=q+1|0,(q|0)==(j|0)){break a}}}}}}while(0);a[e+9]=0;a[e+3]=dc(b);a[e+10]=0;d?Ik(p,a[p+40>>2]):Ik(p,a[c+40>>2]);h=f;return p}function Qh(b,c){var d=b+36|0,e=a[a[d>>2]+20>>2],f=Uf(e,c);if(0==(f|0)){f=oi(c,b,a[b>>2]<<24>>28);if(0==(f|0)){return 0}e=Og(e,c);a[f+36>>2]=e;a[a[e+4>>2]>>2]=f|0;e=f}else{e=vd(f)}Vp(a[d>>2],a[e+36>>2]);return e}function Vp(b,c){0==(b|0)|0==(c|0)||0==(Wp(c,b)|0)&&sf(a[b+20>>2],b,c)}function Xp(b,c){if(0==(b|0)){var d=0}else{d=Uf(a[b+20>>2],c),d=0==(d|0)?0:vd(d)}return d}function Wp(a,b){var c=Bc(5325160,5380184),d=Yp(c,a,b);Rc(c);return d}function Pe(b){var c,d=b>>2;if(0!=(b|0)){c=b>>2;var e=a[c];if(3==(e&15|0)){e=0==(e&64|0);a:do{if(e){for(var f=b+36|0,p=a[f>>2],j=a[p+20>>2],k=j,h=j+28|0,i=j+24|0,m=p;;){p=0;m=zb(k,m);b:for(;;){for(;;){if(0==(m|0)){break b}var n=Db(a[h>>2],m),x=m+12|0,m=cf(k,a[x>>2]);if(0==(ah(a[i>>2],m)|0)){break}else{m=n}}Pe(vd(a[x>>2]));p=1;m=n}if(0==(p|0)){var v=j;break a}m=a[f>>2]}}else{v=0}}while(0);n=b+40|0;a:do{if(0!=(a[n>>2]|0)){for(;;){if(Up(b),0==(a[n>>2]|0)){break a}}}}while(0);a:do{if(e&&(n=Mb(a[a[a[d+4]+12>>2]+4>>2]),0<(n|0))){x=b+4|0;for(f=0;;){if(Qb(a[a[x>>2]+(f<<2)>>2]),f=f+1|0,(f|0)==(n|0)){break a}}}}while(0);n=a[d+1];0!=(n|0)&&E(n);n=a[d+2];0!=(n|0)&&E(n);do{if((a[d+8]|0)==(b|0)){n=b;x=b+20|0;f=ha(a[x>>2]);a:do{if(0!=(f|0)){for(j=f;;){if(k=sa(a[x>>2],j),pi(n,j),0==(k|0)){break a}else{j=k}}}}while(0);e&&Pe(a[a[d+9]+20>>2]);n=Wb;n=(b+16|0)>>2;Ek(a[a[n]+12>>2]);Ek(a[a[n]+4>>2]);Ek(a[a[n]+8>>2]);Rc(a[a[n]>>2]);E(a[n])}else{e&&Ng(v,a[d+9]|0)}}while(0);Rc(a[d+5]);Rc(a[d+6]);Rc(a[d+7]);Qb(a[d+3]);a[c]|=15;E(b|0)}}}function Ng(b,c){var d=a[c>>2]<<28>>28;2==(d|0)?ni(b,c):3==(d|0)?Pe(c):1==(d|0)&&pi(b,c)}function fd(b,c){var d=a[c>>2]<<28>>28;3==(d|0)?d=Wp(a[b+36>>2],a[c+36>>2]):2==(d|0)?(d=a[b+24>>2],d=0!=(J[a[d>>2]](d,c,4)|0)&1):d=1==(d|0)?0!=(Zp(a[b+20>>2],a[c+16>>2])|0)&1:0;return d}function Ij(b,c){var d=a[c>>2]<<28>>28;3==(d|0)?Vp(a[b+36>>2],a[c+36>>2]):2==(d|0)?Rp(b,c):1==(d|0)&&dg(b,c)}function Yp(b,c,d){var e,f=0;if((c|0)==(d|0)){var p;return 1}e=(c+20|0)>>2;if(0!=(bj(a[a[e]+32>>2],c,d)|0)){return 1}var j=b|0;J[a[j>>2]](b,c|0,1);for(c=zb(a[e],c);;){if(0==(c|0)){p=0;f=2176;break}var k=c+12|0;if(0==(J[a[j>>2]](b,a[k>>2]|0,4)|0)&&0!=(Yp(b,a[k>>2],d)|0)){p=1;f=2175;break}c=Db(a[a[e]+28>>2],c)}if(2176==f||2175==f){return p}}function $p(a,b){if(0==(Ve(a)|0)){var c=bh(a,b);return c}n[b]=60;var c=b+1|0,d=n[a];a:do{if(0==d<<24>>24){var f=b,p=c}else{for(var j=a,k=c,h=d;;){j=j+1|0;n[k]=h;var h=k+1|0,i=n[j];if(0==i<<24>>24){f=k;p=h;break a}else{k=h,h=i}}}}while(0);n[p]=62;n[f+2|0]=0;return b}function aq(b,c){0!=(b|0)&&(a[1345663]=b);0!=(c|0)&&(a[1345662]=c)}function bh(a,b){var c=0;if(0==(a|0)||0==n[a]<<24>>24){return 5360332}n[b]=34;var d=n[a],f=0==(eg(d)|0),p=1,j=0,k=a+1|0,h=d,d=b+1|0,i=0;a:for(;;){var m=j,j=h,w=d;b:for(;;){do{if(0==j<<24>>24){break a}else{if(34==j<<24>>24){n[w]=92;var d=1,x=w+1|0}else{x=95!=j<<24>>24&0==(qm(j&255)|0)&-1<j<<24>>24,d=x|f?x?1:m:0==(eg(j)|0)?1:m,x=w}}}while(0);var v=x+1|0;n[x]=j;var t=k+1|0,y=n[k],z=i+1|0,k=y&255,i=0!=y<<24>>24;do{if(!(p|i^1)){do{if(0==(eg(j)|0)&&0==(Lf(j<<24>>24)|0)&&92!=n[x]<<24>>24){break b}}while(0);if(0==(eg(y)|0)&&0==(Lf(k)|0)){break b}}}while(0);if(i){if(0!=(z&127|0)){m=d,k=t,j=y,w=v}else{j=n[x];0==(eg(j)|0)?0!=(Lf(j<<24>>24)|0)?c=2221:92==n[x]<<24>>24&&(c=2221):c=2221;if(2221==c){c=0;if(0!=(eg(y)|0)){p=0;j=d;k=t;h=y;d=v;i=z;continue a}if(0!=(Lf(k)|0)){p=0;j=d;k=t;h=y;d=v;i=z;continue a}}n[v]=92;n[x+2|0]=10;m=1;k=t;j=y;w=x+3|0}}else{m=d,k=t,j=0,w=v}i=z}n[v]=92;n[x+2|0]=10;j=p=1;k=t;h=y;d=x+3|0;i=z}n[w]=34;n[w+1|0]=0;return 0!=(m|0)?b:c=-1<(Lk(a)|0)?b:a}function mb(b,c){J[a[1345663]](b,1,xa(b),c)}function Bd(b,c){var d=h;h=h+4|0;n[d]=b&255;J[a[1345663]](d,1,1,c);h=d}function Fc(a){return $p(a,ch(a))}function ch(b){var b=(xa(b)<<1)+2|0,b=1024<b>>>0?b:1024,c=a[1313351];if((b|0)<=(a[1313352]|0)){return c}c=0==(c|0)?wb(b):gc(c,b);a[1313351]=c;a[1313352]=b;return c}function Mk(b,c,d,e,f){var p,j=h;h=h+4|0;a[j>>2]=0;var k=d+20|0,r=a[a[a[k>>2]+16>>2]+4>>2];do{if(0!=(e|0)){var i=r+4|0;if(0<(Mb(a[i>>2])|0)){for(var m=r+8|0,w=d|0,x=d+12|0,v=b+40|0,t=0,y=0;;){var z=a[a[m>>2]+(t<<2)>>2];if(0!=n[z+12|0]<<24>>24){p=(z|0)>>2;var B=U(w,a[p]),z=(a[k>>2]|0)==(b|0)?a[z+4>>2]:U(a[a[v>>2]>>2]|0,a[p]);0!=($(z,B)|0)&&(0==(y|0)&&(We(c,f),mb(Fc(a[x>>2]),c),y=1),bq(c,j,a[p],B))}p=y;t=t+1|0;if((t|0)<(Mb(a[i>>2])|0)){y=p}else{break}}if(0!=(p|0)){mb(0<(a[j>>2]|0)?5350556:5372400,c);h=j;return}}}}while(0);0==(zb(b,d)|0)&&0==(cf(b,d)|0)&&(We(c,f),mb(Fc(a[d+12>>2]),c),mb(5372400,c));h=j}function We(a,b){if(0!=(b|0)){for(var c=b;!(c=c-1|0,Bd(9,a),0==(c|0));){}}}function bq(b,c,d,e){var f=a[c>>2];a[c>>2]=f+1|0;mb(0<(f|0)?5365236:5370016,b);mb(Fc(d),b);Bd(61,b);mb(Fc(e),b)}function Nk(b,c,d,e){var f,p=h;h=h+4|0;a[p>>2]=0;var j=a[d+16>>2],k=a[a[a[j+20>>2]+16>>2]+8>>2],r=a[d+4>>2];if(0==(r|0)){var i=5338228,r=5338228}else{i=a[r+8>>2],r=a[r+4>>2]}cq(c,a[j+12>>2],r);mb(0!=(a[b>>2]&16|0)?5345196:5341668,c);cq(c,a[a[d+12>>2]+12>>2],i);if(0==(e|0)){b=5372400}else{if(e=k+4|0,0<(Mb(a[e>>2])|0)){for(var k=k+8|0,j=d|0,i=b+32|0,r=b+40|0,m=0;;){var w=a[a[k>>2]+(m<<2)>>2];if(0!=n[w+12|0]<<24>>24&&!(0==(m|0)&&32!=(a[d>>2]&240|0))){f=(w|0)>>2;var x=U(j,a[f]),w=(a[i>>2]|0)==(b|0)?a[w+4>>2]:U(a[a[r>>2]+4>>2]|0,a[f]);0!=($(w,x)|0)&&bq(c,p,a[f],x)}f=m+1|0;if((f|0)<(Mb(a[e>>2])|0)){m=f}else{break}}b=0<(a[p>>2]|0)?5350556:5372400}else{b=5372400}}mb(b,c);h=p}function cq(a,b,c){mb(Fc(b),a);0!=(c|0)&&0!=n[c]<<24>>24&&(0!=(Ve(c)|0)?(Bd(58,a),mb($p(c,ch(c)),a)):(b=oc(c,58),0==(b|0)?(Bd(58,a),mb(bh(c,ch(c)),a)):(n[b]=0,Bd(58,a),mb(bh(c,ch(c)),a),Bd(58,a),c=b+1|0,mb(bh(c,ch(c)),a),n[b]=58)))}function Ok(b,c){var d;0==(a[1345663]|0)&&(a[1345663]=168);0==(a[1345662]|0)&&(a[1345662]=54);mb(0!=(a[b>>2]&32|0)?5338448:5338228,c);mb(0!=(a[b>>2]&16|0)?5335632:5372324,c);d=b+12|0;0!=(Pd(a[d>>2],5329864,10)|0)&&(Bd(32,c),mb(Fc(a[d>>2]),c));mb(5327228,c);d=(b+16|0)>>2;Pk(a[a[d]+12>>2],c);Pk(a[a[d]+4>>2],c);Pk(a[a[d]+8>>2],c);var e;d=bc(1,20);e=d>>2;var f=Bc(5325160,5380184);a[e]=f;var p=a[b+20>>2];a[1345525]=f;Fh(p,212);f=Bc(5325304,5380184);a[e+1]=f;p=a[b+28>>2];a[1345525]=f;Fh(p,212);a[e+4]=Bc(5325160,5380184);a[e+3]=Bc(5325124,5380184);f=Bc(5325160,5380184);a[e+2]=f;e=a[a[a[b+36>>2]+20>>2]+20>>2];a[1345525]=f;Fh(e,212);Qk(b,c,0,0,d);mb(5332596,c);e=d>>2;Rc(a[e]);Rc(a[e+4]);Rc(a[e+1]);Rc(a[e+3]);Rc(a[e+2]);E(d);J[a[1345662]](c)}function Pk(b,c){var d=b+4|0;if(0<(Mb(a[d>>2])|0)){for(var e=b+8|0,f=b|0,p=0,j=0;;){var k=a[a[e>>2]+(p<<2)>>2],h=k+4|0,i=a[h>>2];0==(i|0)?k=j:0==n[i]<<24>>24?k=j:(0==(j|0)?(Bd(9,c),mb(a[f>>2],c),mb(5370016,c)):mb(5365236,c),mb(a[k>>2],c),Bd(61,c),mb(Fc(a[h>>2]),c),k=j+1|0);p=p+1|0;if((p|0)<(Mb(a[d>>2])|0)){j=k}else{break}}0<(k|0)&&mb(5350556,c)}}function eg(a){return 10>((a<<24>>24)-48|0)>>>0?1:46==a<<24>>24|45==a<<24>>24|43==a<<24>>24?1:0}function Qk(b,c,d,e,f){var p,j,k,h,i=e+1|0;if(0==(e|0)){dh(c,i,b|0,0,a[a[b+16>>2]+12>>2]);var m=b+36|0}else{We(c,e);k=f+8|0;h=a[k>>2];j=b+36|0;if(0==(J[a[h>>2]](h,a[j>>2]|0,4)|0)){mb(5375416,c);mb(Fc(a[b+12>>2]),c);mb(5372400,c);return}h=b+12|0;0==(Pd(a[h>>2],5329864,10)|0)?mb(5372704,c):(mb(5375416,c),mb(Fc(a[h>>2]),c),mb(5327228,c));h=(b+16|0)>>2;dh(c,i,b|0,d|0,a[a[h]+12>>2]);(a[b+32>>2]|0)==(d|0)?p=d=0:(p=a[d+40>>2],d=a[p+4>>2],p=a[p>>2]);m=b+40|0;dh(c,i,a[a[m>>2]>>2]|0,p|0,a[a[h]+4>>2]);dh(c,i,a[a[m>>2]+4>>2]|0,d|0,a[a[h]+8>>2]);k=a[k>>2];J[a[k>>2]](k,a[j>>2]|0,2);m=j}k=(f+16|0)>>2;h=a[k];j=(f+12|0)>>2;d=a[j];p=a[a[m>>2]+20>>2];a[k]=Bc(5325196,5380184);a[j]=Bc(5325124,5380184);m=zb(p,a[m>>2]);a:do{if(0!=(m|0)){for(var n=p+28|0,x=m;;){if(Qk(vd(a[x+12>>2]),c,b,i,f),x=Db(a[n>>2],x),0==(x|0)){break a}}}}while(0);p=b+20|0;m=ha(a[p>>2]);a:do{if(0!=(m|0)){for(var n=f|0,x=h|0,v=m;;){var t=a[n>>2],y=v|0;0==(J[a[t>>2]](t,y,4)|0)?(t=a[k],0==(J[a[t>>2]](t,y,4)|0)&&Mk(b,c,v,0,i)):(Mk(b,c,v,1,i),t=a[n>>2],J[a[t>>2]](t,y,2));J[a[x>>2]](h,y,1);v=sa(a[p>>2],v);if(0==(v|0)){break a}}}}while(0);p=(b+28|0)>>2;yg(a[p],5325304);m=a[p];m=J[a[m>>2]](m,0,128);a:do{if(0!=(m|0)){n=f+4|0;x=d|0;for(v=m;;){if(y=v,t=a[n>>2],0==(J[a[t>>2]](t,v,4)|0)?(t=a[j],0==(J[a[t>>2]](t,v,4)|0)&&(We(c,i),Nk(b,c,y,0))):(We(c,i),Nk(b,c,y,1),y=a[n>>2],J[a[y>>2]](y,v,2)),J[a[x>>2]](d,v,1),y=a[p],v=J[a[y>>2]](y,v,8),0==(v|0)){break a}}}}while(0);yg(a[p],5325124);Rc(a[k]);a[k]=h;Rc(a[j]);a[j]=d;0<(e|0)&&(We(c,e),mb(5332596,c))}function dh(b,c,d,e,f){var p,j=f+4|0;if(0<(Mb(a[j>>2])|0)){for(var k=f+8|0,h=0==(e|0),f=f|0,i=c+1|0,m=0,w=0;;){var x=a[a[k>>2]+(m<<2)>>2];p=x>>2;if(0==n[x+12|0]<<24>>24){p=w}else{var x=a[p+2],v=tb(d,x);0==($(v,h?a[p+1]:tb(e,x))|0)?p=w:(0==(w|0)?(We(b,c),mb(a[f>>2],b),mb(5370016,b)):(mb(5367644,b),We(b,i)),mb(Fc(a[p]),b),Bd(61,b),mb(Fc(v),b),p=w+1|0)}m=m+1|0;if((m|0)<(Mb(a[j>>2])|0)){w=p}else{break}}0<(p|0)&&mb(5350556,b)}}function tm(b){a[1345384]=b;var c=a[1345664];var d=0==(c|0)?a[1345664]=352:c;a[1345385]=0;c=a[1345656];0==(c|0)&&(a[1345379]=1024,a[1345656]=bc(1024,1),a[1345158]=bc(a[1345379],1),d=a[1345664],c=a[1345656]);J[d](c,0,b);C[2691310]=0}function dq(){var b,c,d=0,e=h;h=h+1040|0;c=e>>2;var f=e+16;if(n[5382616]){return n[5382616]=0,h=e,-1}for(var p=a[1345385];;){if(0==(p|0)){d=2396}else{if(0==n[p]<<24>>24){d=2396}else{var j=p}}if(2396==d&&(d=0,j=Rk(),a[1345385]=j,0==(j|0))){d=2397;break}if(1==(a[1345378]|0)){if(0!=(Pd(j,5324892,3)|0)){var k=j}else{k=j+3|0,a[1345385]=k}}else{k=j}k=eq(k);a[1345385]=k;var r=n[k];if(0==r<<24>>24){p=k}else{break}}if(2397==d){if(!n[5381560]){return h=e,-1}aa(0,5350360,(i=h,h=h+4|0,a[i>>2]=ca[5382116],i));h=e;return-1}d=a[1345158];if(60==r<<24>>24){ac(e,1024,f|0);d=a;p=a[1345385];n[5380656]=a[1345378]&255;var q;var j=0,f=h,k=(e+4|0)>>2,r=e+8|0,p=p+1|0,m=1;b:for(;;){for(;;){var w=n[p];if(60==w<<24>>24){j=2564;break}else{if(62==w<<24>>24){j=2563;break}else{if(0!=w<<24>>24){b=m;var x=w;break}}}p=Rk();if(0==(p|0)){break b}}if(2564==j){j=0,b=m+1|0,x=60}else{if(2563==j){if(j=0,b=m-1|0,0==(b|0)){q=p;j=2571;break}else{x=62}}}m=a[k];m>>>0<a[r>>2]>>>0||(qa(e,1),m=a[k]);a[k]=m+1|0;n[m]=x;p=p+1|0;m=b}2571!=j&&(q=a[1345387],aa(0,5367248,(i=h,h=h+8|0,a[i>>2]=ca[5380656],a[i+4>>2]=0!=(q|0)?q:5341336,i)),q=0);h=f;d[1345385]=0==(q|0)?0:q+1|0;b=(e+4|0)>>2;q=a[b];q>>>0<a[c+2]>>>0||(qa(e,1),q=a[b]);n[q]=0;q=a[c];a[b]=q;b=a;0==(a[1345162]|0)&&fq();0==(q|0)?x=0:(x=a[1345162],x=J[a[x>>2]](x,q-12|0,4),0==(x|0)?(x=wb(xa(q)+16|0),a[x+8>>2]=n[5381648]?-2147483647:1,ee(x+12|0,q),d=a[1345162],J[a[d>>2]](d,x,1)):(d=x+8|0,a[d>>2]=a[d>>2]+1|0),x=x+12|0);b[1331221]=x;Xb(q,a[c+3]);c=264}else{if(34==r<<24>>24){a[1345385]=gq(k,d),a[1331221]=dc(d),c=265}else{c=a[1345657];if(0!=(c|0)&&(q=xa(c),0==(Pd(k,c,q)|0))){return a[1345385]=k+q|0,h=e,263}c=hq(k,d);if(0!=(c|0)){return a[1345385]=c,a[1331221]=dc(d),h=e,264}c=n[a[1345385]];q=a[1345385];if(!(0==((33<=(c&255)&&47>=(c&255)||58<=(c&255)&&64>=(c&255)||91<=(c&255)&&96>=(c&255)||123<=(c&255)&&126>=(c&255))|0)|95==c<<24>>24)){return a[1345385]=q+1|0,c=n[q]<<24>>24,h=e,c}c=a;if(0==(q|0)){q=0}else{for(b=d;;){x=n[q];if(0==(qm(ca[q])|0)&&!(95==x<<24>>24|0>x<<24>>24)){break}n[b]=x;q=q+1|0;b=b+1|0}n[b]=0}c[1345385]=q;c=Lk(d);if(-1!=(c|0)){return h=e,c}a[1331221]=dc(d);c=264}}h=e;return c}function Lk(b){C[2690320]=0;var c=n[b];do{if(0==c<<24>>24){var d=0}else{for(var d=b,e=c,f=0;;){e=0>e<<24>>24?127:e;a:do{if(-1<f<<16>>16){var p=e&255;do{if(0==((65<=p&&90>=p)|0)){if(0!=((97<=p&&122>=p)|0)){var j=e}else{j=C[2690320]=-1;break a}}else{j=se(p)&255}}while(0);p=C[2690320]<<16>>16;j&=255;if(0==(a[(j-97<<2)+5382124>>2]&a[(p<<3)+5380348>>2]|0)){j=C[2690320]=-1}else{for(p=C[(p<<3)+5380346>>1];;){var k=p<<16>>16;if((C[(k<<2)+5380212>>1]<<16>>16|0)==(j|0)){break}else{p=p+1&65535}}j=C[(k<<2)+5380214>>1];C[2690320]=j}}else{j=f}}while(0);d=d+1|0;f=n[d];if(0==f<<24>>24){break}else{e=f,f=j}}if(0>j<<16>>16){return b=-1}d=j}}while(0);return b=C[(d<<16>>16<<3)+5380344>>1]<<16>>16}function Rk(){var b=0,c=h;h=h+8|0;for(var d=c+4|0,e=0;;){var f=a[1345379];(e+128|0)<(f|0)||(f=f+1024|0,a[1345379]=f,a[1345656]=gc(a[1345656],f),a[1345158]=gc(a[1345158],a[1345379]),f=a[1345379]);f=J[a[1345664]](a[1345656]+e+1|0,f+(e^-1)|0,a[1345384]);if(0==(f|0)){var p=e;break}var j=xa(f);do{if(10==n[f+(j-1)|0]<<24>>24){if(35==n[f]<<24>>24&0==(e|0)){var k=f+1|0,k=0==(Pd(k,5362304,4)|0)?f+5|0:k,r=gd(k,5360272,(i=h,h=h+12|0,a[i>>2]=5381512,a[i+4>>2]=d,a[i+8>>2]=c,i)),q=a[1345378];do{if(1>(r|0)){a[1345378]=q+1|0}else{if(a[1345378]=q-1|0,1<(r|0)){for(var m=k+a[c>>2]|0,w=m;;){var x=n[w];if(34==x<<24>>24|0==x<<24>>24){break}w=w+1|0}(w|0)!=(m|0)&&(n[w]=0,x=m,m=w-m|0,w=a[1311596],(w|0)<(m|0)?(w=0==(w|0)?wb(m+1|0):gc(a[1311597],m+1|0),a[1311597]=w,a[1311596]=m,m=w):m=a[1311597],ee(m,x),a[1345387]=a[1311597])}}}while(0);n[f]=0;k=1;r=0}else{a[1345378]=a[1345378]+1|0;var b=j-2|0,v=f+b|0;92!=n[v]<<24>>24?v=j:(n[v]=0,v=b);b=2462}}else{v=j,b=2462}}while(0);2462==b&&(b=0,k=v,r=v+e|0);if(10==n[f+(k-1)|0]<<24>>24){p=r;break}else{e=r}}if(0>=(p|0)){return h=c,0}d=a[1345656]+1|0;h=c;return d}function aa(b,c,d){var e=h;h=h+4|0;a[e>>2]=d;iq(b,c,a[e>>2]);h=e}function eq(b){var c=0;a:for(;;){var d=n[b];do{if(0!=d<<24>>24&&!(0==(Ze(d&255)|0)&&0==((0<=ca[b]&&31>=ca[b]||127===ca[b])|0))){b=b+1|0;continue a}}while(0);b:do{if(n[5381560]){for(var d=b,e=n[b];;){if(0==e<<24>>24){break b}else{var f=d}for(;;){var p=0==e<<24>>24,j=f+1|0;if(!(42!=e<<24>>24&(p^1))){break}f=j;e=n[j]}if(p){d=f}else{if(e=n[j],47==e<<24>>24){break}else{d=j}}}n[5381560]=0;d=f+2|0}else{d=b}}while(0);b=n[d];b:do{if(0==b<<24>>24){var k=d,c=2493;break a}else{if(47==b<<24>>24){e=n[d+1|0];if(47==e<<24>>24){var e=d,h=0}else{if(42==e<<24>>24){n[5381560]=1;n[5382116]=a[1345378]&255;var i=d+2|0;break}else{k=d;c=2494;break a}}for(;;){var m=e+1|0;if(h){i=e;break b}e=m;h=0==n[m]<<24>>24}}else{if(0!=(Ze(b&255)|0)){i=d}else{if(0==((0<=ca[d]&&31>=ca[d]||127===ca[d])|0)){k=d;c=2492;break a}else{i=d}}}}}while(0);if(0==n[i]<<24>>24){k=i;c=2495;break}else{b=i}}if(2493==c||2492==c||2494==c||2495==c){return k}}function gq(b,c){var d=h,e=n[b],f=b+1|0,p=n[f],j=0==p<<24>>24;a:do{if(p<<24>>24!=e<<24>>24&(j^1)){for(var k=c,r=b,q=f,m=p;;){if(92==m<<24>>24){var m=r+2|0,w=n[m];w<<24>>24==e<<24>>24?(q=m,m=k):92!=w<<24>>24?m=k:(n[k]=92,q=m,m=k+1|0)}else{m=k}k=m+1|0;n[m]=n[q];w=q+1|0;m=n[w];r=0==m<<24>>24;if(m<<24>>24!=e<<24>>24&(r^1)){r=q,q=w}else{var x=k,v=q,t=w,y=r;break a}}}else{x=c,v=b,t=f,y=j}}while(0);y?(e=a[1345387],f=a[1345378],aa(0,5364800,(i=h,h=h+8|0,a[i>>2]=0!=(e|0)?e:5341336,a[i+4>>2]=f,i))):t=v+2|0;n[x]=0;h=d;return t}function hq(b,c){var d=0,e=h,f=n[b];if(45==f<<24>>24){f=b+1|0;n[c]=45;var p=c+1|0,j=f,k=n[f]}else{p=c,j=b,k=f}46==k<<24>>24?(k=j+1|0,n[p]=46,f=p+1|0,j=k,p=1,k=n[k]):(f=p,p=0);a:do{if(10>((k&255)-48|0)>>>0){for(var r=j,q=f,m=k;;){var r=r+1|0,w=q+1|0;n[q]=m;m=n[r];if(10>((m&255)-48|0)>>>0){q=w}else{var x=r,v=w,t=1,y=m;break a}}}else{x=j,v=f,t=0,y=k}}while(0);do{if(46==y<<24>>24&0==(p|0)){if(n[v]=46,k=v+1|0,j=x+1|0,f=n[j],10>((f&255)-48|0)>>>0){for(var z=k;;){n[z]=f;var B=z+1|0,F=j+1|0,f=n[F];if(10>((f&255)-48|0)>>>0){z=B,j=F}else{break}}n[B]=0;z=F}else{var A=k,C=j,d=2519}}else{A=v,C=x,d=2519}}while(0);if(2519==d){n[A]=0;if(0==(t|0)){return h=e,0}z=C}d=n[z];if(0==d<<24>>24){return h=e,z}if(0==(Lf(d&255)|0)){if(95==n[z]<<24>>24){d=z}else{return h=e,z}}else{d=z}for(;;){var E=d+1|0,G=n[E];if(0==G<<24>>24){break}if(95==G<<24>>24|0!=(Lf(G&255)|0)){d=E}else{break}}n[E]=0;d=a[1345387];x=a[1345378];aa(0,5369528,(i=h,h=h+20|0,a[i>>2]=0!=(d|0)?d:5341336,a[i+4>>2]=x,a[i+8>>2]=b,a[i+12>>2]=c,a[i+16>>2]=z,i));n[E]=G;h=e;return z}function Sk(b){var c=h,d=C[2691310];C[2691310]=d+1&65535;if(0==d<<16>>16){var d=a[1345387],e=a[1345378];aa(1,5344872,(i=h,h=h+16|0,a[i>>2]=0!=(d|0)?d:5341336,a[i+4>>2]=e,a[i+8>>2]=b,a[i+12>>2]=e,i));e=0;b=h;d=a[1345656]+1|0;if(0!=(a[1345385]|0)){aa(3,5377740,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));for(var f=a[1345385];;){var p=f-1|0;if(p>>>0<=d>>>0){break}if(0==(Ze(ca[p])|0)){f=p}else{e=2548;break}}2548==e&&(e=n[p],n[p]=0,aa(3,d,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),n[p]=e);aa(3,5375036,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));d=a[1345385];e=n[d];n[d]=0;aa(3,p,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));n[a[1345385]]=e;aa(3,5372356,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));aa(3,a[1345385],(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i))}h=b}h=c}function iq(b,c,d){var e=h;h=h+4|0;a[e>>2]=d;if(3==(b|0)){var b=a[1331224],f=a[1331220];a[1331220]=f>>>0>b>>>0?f:b;b=d}else{d=2==(b|0)?1:b,a[1331224]=d,f=a[1331220],a[1331220]=f>>>0>d>>>0?f:d,Lb(a[Qa>>2],5338208,(i=h,h=h+4|0,a[i>>2]=1==(b|0)?5335388:5332544,i)),b=a[e>>2]}d=a[Qa>>2];Lb(d,c,b);h=e}function Uf(b,c){var d=a[a[b+16>>2]>>2],d=J[a[d>>2]](d,c,512);if(0==(d|0)||(a[b+32>>2]|0)==(b|0)){return d}var e=a[b+20>>2];return d=J[a[e>>2]](e,d,4)}function Zp(b,c){var d=h;h=h+4|0;a[d>>2]=c;var e=J[a[b>>2]](b,d,512);h=d;return e}function Og(b,c){var d=Uf(a[b+32>>2],c);if(0!=(d|0)){return dg(b,d),d}var d=Jk(b,c,a[a[b+40>>2]>>2]),e=a[a[b+16>>2]>>2];J[a[e>>2]](e,d|0,1);dg(b,d);return d}function Jk(b,c,d){var e,f=bc(1,n[5382644]?304:0);e=f>>2;a[f>>2]=a[f>>2]&-16|1;a[e+3]=dc(c);var c=(b+16|0)>>2,p=a[c]+16|0,j=a[p>>2];a[p>>2]=j+1|0;a[e+4]=j;a[e+5]=a[b+32>>2];p=Mb(a[a[a[c]+4>>2]+4>>2]);if(0==(p|0)){return a[e+1]=0,a[e+2]=0,f}b=(f+4|0)>>2;a[b]=bc(p,4);a[e+2]=bc((p+7|0)/8&-1,1);if(0>=(p|0)){return f}e=d+4|0;if(0==(d|0)){for(d=0;!(e=dc(a[a[a[a[a[c]+4>>2]+8>>2]+(d<<2)>>2]+4>>2]),a[a[b]+(d<<2)>>2]=e,d=d+1|0,(d|0)==(p|0));){}}else{for(c=0;!(d=dc(a[a[e>>2]+(c<<2)>>2]),a[a[b]+(c<<2)>>2]=d,c=c+1|0,(c|0)==(p|0));){}}return f}function dg(b,c){var d=b+20|0;if(0==(Zp(a[d>>2],a[c+16>>2])|0)&&(d=a[d>>2],J[a[d>>2]](d,c|0,1),0==(a[b>>2]&64|0))){var e=a[b+36>>2],d=a[e+20>>2],e=cf(d,e);if(0!=(e|0)){for(d=d+24|0;!(dg(vd(a[e+16>>2]),c),e=ah(a[d>>2],e),0==(e|0));){}}}}function pi(b,c){var d=Gg(b,c);a:do{if(0!=(d|0)){for(var e=d;;){var f=Hg(b,e,c);ni(b,e);if(0==(f|0)){break a}else{e=f}}}}while(0);a:do{if(0==(a[b>>2]&64|0)&&(d=a[b+36>>2],e=a[d+20>>2],f=zb(e,d),0!=(f|0))){d=c|0;for(e=e+28|0;;){var p=vd(a[f+12>>2]),j=a[p+20>>2];0!=(J[a[j>>2]](j,d,4)|0)&&pi(p,c);f=Db(a[e>>2],f);if(0==(f|0)){break a}}}}while(0);d=a[b+20>>2];J[a[d>>2]](d,c|0,2);(a[b+32>>2]|0)==(b|0)&&Kk(c)}function Kk(b){var c=b|0,d=b+20|0,e=a[a[a[d>>2]+16>>2]>>2];J[a[e>>2]](e,c,2);a[b>>2]|=15;Qb(a[b+12>>2]);d=a[d>>2];a:do{if(0==(a[d>>2]&64|0)&&(e=Mb(a[a[a[d+16>>2]+4>>2]+4>>2]),0<(e|0))){for(var f=b+4|0,p=0;;){if(Qb(a[a[f>>2]+(p<<2)>>2]),p=p+1|0,(p|0)==(e|0)){break a}}}}while(0);E(a[b+4>>2]);E(a[b+8>>2]);E(c)}function ha(b){return J[a[b>>2]](b,0,128)}function sa(b,c){return J[a[b>>2]](b,c|0,8)}function Vi(){var b,c,d=0,e=h;h=h+2032|0;var f=e+2e3,p=e+2008,j=e+2016,k=e+2024,r=e|0,q=e+400|0;a[1331219]=0;a[1331280]=-2;var m=f|0,w=f+4|0,x=p|0,v=p+4|0,t=j|0,y=j+4|0,z=k|0,B=k+4|0,F=0,A=0,S=r,G=r,H=q,I=q,Z=200;a:for(;;){C[G>>1]=F&65535;if(((Z-1<<1)+S|0)>>>0>G>>>0){var T=S,K=G,M=H,L=I;c=L>>2;var J=Z}else{var P=G-S>>1,N=P+1|0;if(9999<Z>>>0){d=2726;break}var R=Z<<1,Y=1e4<R>>>0?1e4:R,Q=wb((10*Y&-1)+7|0);if(0==(Q|0)){d=2726;break}var U=Q,da=S;$d(Q,da,N<<1);var ea=(((Y<<1)+7|0)>>>3<<3)+Q|0;$d(ea,H,N<<3);(S|0)!=(r|0)&&E(da);if((Y-1|0)>(P|0)){T=U,K=(P<<1)+U|0,M=ea,L=(P<<3)+ea|0,c=L>>2,J=Y}else{var wa=U;break}}if(9==(F|0)){wa=T;break}var $=n[F+5324784|0],V=$<<24>>24;if(-68==$<<24>>24){d=2658}else{var W=a[1331280];if(-2==(W|0)){var X=dq(),ba=a[1331280]=X}else{ba=W}var ma=1>(ba|0)?a[1331280]=0:267>ba>>>0?ca[ba+5324248|0]:2;var ib=ma+V|0;if(80<ib>>>0){d=2658}else{if((n[ib+5325036|0]<<24>>24|0)!=(ma|0)){d=2658}else{var ia=n[ib+5324516|0],fa=ia<<24>>24;if(1>ia<<24>>24){if(0==ia<<24>>24){d=2714}else{var O=-fa|0,d=2659}}else{a[1331280]=-2;var ga=L+8|0,ha=ga,sa=a[1331222];a[ha>>2]=a[1331221];a[ha+4>>2]=sa;var ua=fa,Da=0==(A|0)?0:A-1|0,Ja=K,Ab=ga}}}}if(2658==d){var ra=n[F+5324944|0];0==ra<<24>>24?d=2714:(O=ra&255,d=2659)}b:do{if(2659==d){var d=0,qa=ca[O+5324600|0],ya=1-qa|0,ja=a[(ya<<3>>2)+c],la=(ya<<3)+L+4|0,va=a[la>>2];if(10==(O|0)){a[1345652]=1;a[1345657]=5360020;var oa=ja,ka=va}else{if(11==(O|0)){a[1345652]=3,a[1345657]=5360020,oa=ja,ka=va}else{if(42==(O|0)){a[1345337]=a[c],oa=ja,ka=va}else{if(43==(O|0)){var Ea=L-16|0,Ka=L|0,Na=a,Ba;var Wa=a[Ea>>2],na=a[Ka>>2],ta=h;h=h+1024|0;var Ra=xa(Wa)+xa(na)+2|0;if(1025>(Ra|0)){var bb=ta|0,Xa=bb,Sa=bb}else{Xa=wb(Ra),Sa=ta|0}ee(Xa,Wa);var Oa=Xa+xa(Xa)|0;Ib=58;n[Oa]=Ib&255;Ib>>=8;n[Oa+1|0]=Ib&255;fe(Xa,na);var Va=dc(Xa);(Xa|0)!=(Sa|0)&&E(Xa);h=ta;Ba=Va;Na[1345337]=Ba;Qb(a[Ea>>2]);Qb(a[Ka>>2]);oa=ja;ka=va}else{if(44==(O|0)){a[1345524]=1,a[1345372]=a[c],oa=ja,ka=va}else{if(45==(O|0)){Qb(a[L-16+4>>2]),a[1345524]=3,oa=ja,ka=va}else{if(46==(O|0)){jq(a[c],a[c+1]),oa=ja,ka=va}else{if(12==(O|0)){a[1345524]=3,oa=ja,ka=va}else{if(13==(O|0)){a[1345524]=1,a[1345372]=a[a[a[1345484]+40>>2]>>2],oa=ja,ka=va}else{if(7==(O|0)){oa=0,ka=va}else{if(3==(O|0)){n[5382616]=1,kq(),oa=ja,ka=va}else{if(2==(O|0)){var Ta=L|0,Aa=a[Ta>>2],fb=h;h=h+128|0;if(0==(Aa|0)){var Ca=fb|0;lq(Ca);var Ya=Ca}else{Ya=Aa}var $a=Bh(Ya,a[1345652]);a[1345658]=$a;a[1345524]=3;Tk($a);n[5381556]=1;h=fb;Qb(a[Ta>>2]);oa=ja;ka=va}else{if(5==(O|0)){a[1345658]=0,oa=ja,ka=va}else{if(6==(O|0)){oa=a[c],ka=va}else{if(4==(O|0)){var La=a[1345658];0!=(La|0)&&Pe(La);a[1345658]=0;oa=ja;ka=va}else{if(47==(O|0)){a[1345522]=a[a[a[a[1345324]>>2]+40>>2]+4>>2],a[1345524]=2,oa=ja,ka=va}else{if(48==(O|0)){Uk(),oa=ja,ka=va}else{if(49==(O|0)){jq(a[c],a[c+1]),oa=ja,ka=va}else{if(50==(O|0)){a[1345522]=a[a[a[a[1345324]>>2]+40>>2]+4>>2],a[1345524]=2,oa=ja,ka=va}else{if(51==(O|0)){Uk(),oa=ja,ka=va}else{if(52==(O|0)){qi(a[c],a[c+1]),oa=ja,ka=va}else{if(53==(O|0)){qi(a[c],a[c+1]),oa=ja,ka=va}else{if(9==(O|0)){a[1345652]=2,a[1345657]=5332132,oa=ja,ka=va}else{if(14==(O|0)){a[1345524]=2,a[1345522]=a[a[a[1345484]+40>>2]+4>>2],oa=ja,ka=va}else{if(23==(O|0)){var pa=L-16|0,Ga=L|0;Vk(a[pa>>2],a[Ga>>2]);Qb(a[pa>>2]);Qb(a[Ga>>2]);oa=ja;ka=va}else{if(25==(O|0)){var Fa=L|0;Vk(a[Fa>>2],5346992);Qb(a[Fa>>2]);oa=ja;ka=va}else{if(32==(O|0)){Sk(5343328),oa=ja,ka=va}else{if(37==(O|0)){a[1345524]=3,oa=ja,ka=va}else{if(38==(O|0)){a[1345524]=3,oa=ja,ka=va}else{if(39==(O|0)){var Za=a[L-8>>2],nb=a[1345337];a[1345337]=0;oa=Za;ka=nb}else{if(40==(O|0)){var jb=L|0,cb,Ha=Og(a[1345484],a[jb>>2]);n[5381556]=0;cb=Ha;Qb(a[jb>>2]);oa=cb;ka=va}else{if(8==(O|0)){a[1345652]=0,a[1345657]=5332132,oa=ja,ka=va}else{if(67==(O|0)){oa=a[c],ka=va}else{if(68==(O|0)){var kb=L-16|0,Kb=L|0,Ma;var Pa=a[kb>>2],lb=a[Kb>>2],rb=h;h=h+1024|0;var ab=xa(Pa)+xa(lb)+1|0;if(1025>(ab|0)){var db=rb|0,ob=db,pb=db}else{ob=wb(ab),pb=rb|0}ee(ob,Pa);fe(ob,lb);var ub=dc(ob);(ob|0)!=(pb|0)&&E(ob);h=rb;Ma=ub;Qb(a[kb>>2]);Qb(a[Kb>>2]);oa=Ma;ka=va}else{if(55==(O|0)){qi(a[c],a[c+1]),oa=ja,ka=va}else{if(56==(O|0)){qi(a[c],a[c+1]),oa=ja,ka=va}else{if(58==(O|0)){ri(f),oa=a[m>>2],ka=a[w>>2]}else{if(59==(O|0)){mq(),oa=ja,ka=va}else{if(60==(O|0)){ri(p),oa=a[x>>2],ka=a[v>>2]}else{if(61==(O|0)){mq(),oa=ja,ka=va}else{if(62==(O|0)){ri(j),oa=a[t>>2],ka=a[y>>2]}else{if(63==(O|0)){var gb=h,sb=a[a[1345484]+12>>2],Ia=a[1345378];aa(0,5368468,(i=h,h=h+8|0,a[i>>2]=sb,a[i+4>>2]=Ia,i));aa(3,5366268,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));aa(3,5363788,(i=h,h=h+4|0,a[i>>2]=a[a[(a[1345482]-2<<2)+5381652>>2]+12>>2],i));h=gb;ri(k);oa=a[z>>2];ka=a[B>>2]}else{if(64==(O|0)){b=(L|0)>>2;var vb=Xp(a[a[1345658]+36>>2],a[b]),Ua=a[1345484];if(0==(vb|0)){var eb=Qh(Ua,a[b])}else{Ij(Ua,vb|0),eb=vb}Tk(eb);n[5381556]=0;Qb(a[b]);oa=ja}else{oa=65==(O|0)?a[c]:66==(O|0)?a[c]:ja}ka=va}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}var hb=(-qa<<1)+K|0,qb=(ya<<3)+L|0;a[qb>>2]=oa;a[la>>2]=ka;var Bb=ca[O+5324672|0]-21|0,mb=C[hb>>1]<<16>>16,xb=(n[Bb+5324744|0]<<24>>24)+mb|0;do{if(81>xb>>>0&&(n[xb+5325036|0]<<24>>24|0)==(mb|0)){ua=n[xb+5324516|0]<<24>>24;Da=A;Ja=hb;Ab=qb;break b}}while(0);ua=n[Bb+5324904|0]<<24>>24;Da=A;Ja=hb;Ab=qb}else{if(2714==d){d=0;do{if(0==(A|0)){a[1331219]=a[1331219]+1|0;Sk(5337092);var za=K,Nb=L,Jb=$}else{if(3==(A|0)){var Qa=a[1331280];if(1>(Qa|0)){if(0==(Qa|0)){wa=T;break a}else{za=K,Nb=L,Jb=$}}else{a[1331280]=-2,za=K,Nb=L,Jb=$}}else{za=K,Nb=L,Jb=$}}}while(0);c:for(;;){do{if(-68!=Jb<<24>>24){var zb=(Jb<<24>>24)+1|0;if(81>zb>>>0&&1==n[zb+5325036|0]<<24>>24){var tb=n[zb+5324516|0];if(0<tb<<24>>24){break c}}}}while(0);if((za|0)==(T|0)){wa=T;break a}var Cb=za-2|0,za=Cb,Nb=Nb-8|0,Jb=n[(C[Cb>>1]<<16>>16)+5324784|0]}var Db=Nb+8|0,Eb=Db,Hb=a[1331222];a[Eb>>2]=a[1331221];a[Eb+4>>2]=Hb;ua=tb<<24>>24;Da=3;Ja=za;Ab=Db}}}while(0);F=ua;A=Da;S=T;G=Ja+2|0;H=M;I=Ab;Z=J}2726==d&&(Sk(5328528),wa=S);(wa|0)!=(r|0)&&E(wa);h=e}function Vk(b,c){if(n[5381556]){var d=a[1345484],d=(a[d+32>>2]|0)==(d|0)?c:5338228}else{d=5338228}var e=a[1345524];if(0==(e|0)|3==(e|0)){e=Q(a[1345484]|0,b);if(0==(e|0)){d=mi(a[1345658],b,d)}else{if(0!=n[e+13|0]<<24>>24&&n[5381556]){return}d=e}hc(a[1345484]|0,a[d+8>>2],c)}else{if(1==(e|0)){e=Q(a[a[a[1345484]+40>>2]>>2]|0,b);if(0==(e|0)){d=Nf(a[1345658],b,d)}else{if(0!=n[e+13|0]<<24>>24&&n[5381556]){return}d=e}hc(a[1345372]|0,a[d+8>>2],c)}else{if(2==(e|0)){e=Q(a[a[a[1345484]+40>>2]+4>>2]|0,b);if(0==(e|0)){d=wf(a[1345658],b,d)}else{if(0==n[e+13|0]<<24>>24){d=e}else{if(n[5381556]){if(d=a[1345484],(a[d+32>>2]|0)!=(d|0)){d=e}else{return}}else{d=e}}}hc(a[1345522]|0,a[d+8>>2],c)}}}}function jq(b,c){var d;d=bc(1,20);a[d+16>>2]=a[1345324];a[1345324]=d;var e=bc(1,12),f=a[1345324];d=f>>2;a[d+2]=e;f=f+4|0;a[f>>2]=e;a[e>>2]=b;a[e+4>>2]=c;a[a[f>>2]+8>>2]=0;a[d+3]=n[5381552]<<24>>24;e=a[1345484];a[d]=e;Ik(e,a[e+40>>2]);n[5381552]=1}function Ve(b){return 0==(a[1345162]|0)|0==(b|0)?0:b=(n[5381648]?-2147483648:0)&a[b-4>>2]}function qi(b,c){var d,e=bc(1,12);d=(a[1345324]+8|0)>>2;a[a[d]+8>>2]=e;e=a[a[d]+8>>2];a[d]=e;a[e>>2]=b;a[e+4>>2]=c;a[a[d]+8>>2]=0}function ri(b){a[b>>2]=kq()|0;a[b+4>>2]=0}function mq(){var b=h;h=h+128|0;n[5381556]=0;var c=b|0;lq(c);Tk(Qh(a[1345484],c));h=b}function lq(b){var c=h,d=a[1331061];a[1331061]=d+1|0;Pa(b,5361428,(i=h,h=h+4|0,a[i>>2]=d,i));h=c}function dc(b){0==(a[1345162]|0)&&fq();if(0==(b|0)){return 0}var c=a[1345162],c=J[a[c>>2]](c,b-12|0,4);0==(c|0)?(c=wb(xa(b)+16|0),a[c+8>>2]=1,ee(c+12|0,b),b=a[1345162],J[a[b>>2]](b,c,1)):(b=c+8|0,a[b>>2]=a[b>>2]+1|0);b=c;return b+12|0}function fq(){a[1345162]=Bc(5381304,5380184);n[5381648]=1;n[5382268]=1}function Qb(b){var c=h,d=a[1345162];if(!(0==(d|0)|0==(b|0))){if(d=J[a[d>>2]](d,b-12|0,4),0==(d|0)){aa(1,5326536,(i=h,h=h+4|0,a[i>>2]=b,i))}else{var b=d+8|0,e=a[b>>2]-1|0;a[b>>2]=e;n[5382268]&0!=(e|0)||(b=a[1345162],J[a[b>>2]](b,d,2),E(d))}}h=c}function Wk(b){Yd(b);var c=a[b+12>>2],d=a[b+16>>2],e=xf(c,d);0==(e|0)?pd(c,d,b):Be(b,e)}function nq(b){var c=b+163|0;if(0==n[c]<<24>>24){n[c]=1;c=b+164|0;n[c]=1;var b=b+184|0,d=a[a[b>>2]>>2];a:do{if(0!=(d|0)){for(var e=0,f=d;;){var p=a[f+12>>2];0==n[p+164|0]<<24>>24?0==n[p+163|0]<<24>>24&&nq(p):(Wk(f),e=e-1|0);e=e+1|0;f=a[a[b>>2]+(e<<2)>>2];if(0==(f|0)){break a}}}}while(0);n[c]=0}}function oq(c){var d,g,c=(c+20|0)>>2;a[1312708]=Za(24*Mb(a[c])&-1);a[1312712]=0;var e=ha(a[c]);a:do{if(0!=(e|0)){for(var l=e;;){if(a[l+136>>2]=-1,l=sa(a[c],l),0==(l|0)){break a}}}}while(0);e=ha(a[c]);if(0!=(e|0)){for(;;){g=e;l=e+24|0;if(0==(a[e+220>>2]|0)){var p=da(4);d=a[1312712];var j=a[1312708];a[j+(24*d&-1)>>2]=p;a[p>>2]=g;a[j+(24*d&-1)+4>>2]=1;g=l+24|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);p=j+(24*d&-1)+8|0;f[b>>3]=g;a[p>>2]=a[b>>2];a[p+4>>2]=a[b+4>>2];g=l+32|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);j=j+(24*d&-1)+16|0;f[b>>3]=g;a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];a[l+112>>2]=d;a[1312712]=d+1|0}else{if(p=ec(g),d=p+136|0,j=a[d>>2],-1<(j|0)){d=a[1312708];var p=d+(24*j&-1)+4|0,k=a[p>>2];a[p>>2]=k+1|0;a[a[d+(24*j&-1)>>2]+(k<<2)>>2]=g;p=l+24|0;g=(d+(24*j&-1)+8|0)>>2;p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])+(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]);f[b>>3]=p;a[g]=a[b>>2];a[g+1]=a[b+4>>2];d=(d+(24*j&-1)+16|0)>>2;g=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);p=l+32|0;p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);f[b>>3]=g<p?p:g;a[d]=a[b>>2];a[d+1]=a[b+4>>2];a[l+112>>2]=j}else{var k=da(a[p+220>>2]<<2),l=a[1312712],j=a[1312708],h=j+(24*l&-1)|0;a[h>>2]=k;a[k>>2]=p;(p|0)==(g|0)?(a[j+(24*l&-1)+4>>2]=1,g=e+48|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),p=j+(24*l&-1)+8|0,f[b>>3]=g,a[p>>2]=a[b>>2],a[p+4>>2]=a[b+4>>2],g=e+56|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),j=j+(24*l&-1)+16|0,f[b>>3]=g):(a[a[h>>2]+4>>2]=g,a[j+(24*l&-1)+4>>2]=2,g=p+48|0,k=e+48|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])+(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),k=j+(24*l&-1)+8|0,f[b>>3]=g,a[k>>2]=a[b>>2],a[k+4>>2]=a[b+4>>2],g=p+56|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),p=e+56|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=j+(24*l&-1)+16|0,f[b>>3]=g<p?p:g);a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];a[d>>2]=l;a[e+136>>2]=l;a[1312712]=l+1|0}}e=sa(a[c],e);if(0==(e|0)){break}}}}function Uk(){var b=a[1345324],c=a[b+4>>2],d=c+8|0,e=a[d>>2];if(0==(e|0)){e=b}else{for(var b=c,c=d,f=e;;){var e=a[b+4>>2],d=a[f+4>>2],p=a[b>>2];1==(a[p>>2]&15|0)?b=0:(b=p,p=ha(a[p+20>>2]));var j=a[f>>2];1==(a[j>>2]&15|0)?(f=j,j=0):f=ha(a[j+20>>2]);a:do{if(0!=(p|0)){for(var k=0==(f|0),h=0==(b|0),i=0==(j|0),m=b+20|0,w=j+20|0,x=p;;){b:do{if(!k){for(var v=f;;){var t=sf(a[1345484],x,v);if(0!=(t|0)){var y=a[t+12>>2],z=(a[t+16>>2]|0)!=(y|0)&(y|0)==(x|0),y=z?d:e,z=z?e:d;0!=(y|0)&&0!=n[y]<<24>>24&&(hc(t|0,1,y),Qb(y));0!=(z|0)&&0!=n[z]<<24>>24&&(hc(t|0,2,z),Qb(z))}if(i){break b}v=sa(a[w>>2],v);if(0==(v|0)){break b}}}}while(0);if(h){break a}x=sa(a[m>>2],x);if(0==(x|0)){break a}}}}while(0);d=a[c>>2];c=d+8|0;e=a[c>>2];if(0==(e|0)){break}else{b=d,f=e}}e=c=a[1345324];c=a[c+4>>2]}if(0==(c|0)){c=e}else{for(;!(e=a[c+8>>2],1==(a[a[c>>2]>>2]&15|0)&&E(c),0==(e|0));){c=e}c=a[1345324]}e=a[1345484];(e|0)==(a[c>>2]|0)?(Up(e),c=a[1345324],n[5381552]=a[c+12>>2]&255,a[1345324]=a[c+16>>2],n[5381556]=0,E(c),a[1345524]=3):P()}function Tk(b){var c=h,d=a[1345482];63<(d|0)?(aa(1,5371220,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Qd()):(a[1345482]=d+1|0,a[(d<<2)+5381652>>2]=b,a[1345484]=b,h=c)}function kq(){var b=h,c=a[1345482];0==(c|0)&&(aa(1,5359404,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),Qd());var d=c-1|0;a[1345482]=d;var e=a[(d<<2)+5381652>>2];if(0>=(d|0)){return a[1345484]=0,h=b,e}c=a[(c-2<<2)+5381652>>2];a[1345484]=c;h=b;return e}function pq(){var b=a[1312713];if(0<(b|0)){for(var c=a[1312766],d=0,e=0,f=0;;){var p=c+(36*f&-1)|0,j=c+(36*f&-1)+12|0,k=a[j>>2],h=0==(d|0);a:do{if(0==(k|0)){var i=h?a[p>>2]:e,m=d+1|0}else{if(h){i=e,m=0}else{if((a[p>>2]|0)>(e|0)&0<(k|0)){for(var n=0,x=k;;){var v=a[a[c+(36*f&-1)+4>>2]+(n<<2)>>2],t=v+4|0;if(0<(a[t>>2]|0)){x=v|0;for(v=0;;){var y=a[a[x>>2]+(v<<2)>>2]+236|0;a[y>>2]=a[y>>2]-d|0;v=v+1|0;if((v|0)>=(a[t>>2]|0)){break}}t=a[j>>2]}else{t=x}n=n+1|0;if((n|0)<(t|0)){x=t}else{i=e;m=d;break a}}}else{i=e,m=d}}}}while(0);f=f+1|0;if((f|0)<(b|0)){d=m,e=i}else{break}}}}function qq(c){si(c);var d=a[1312713],g=Math.a(d-1|0,a[c+260>>2])|0;if(0>=(d|0)){var e,l;return d=0/g}for(var p=a[1312766],c=a[c+256>>2],j=0,k=0;;){var h=p+(36*k&-1)+20|0,h=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])+(Math.a(c,a[p+(36*k&-1)+16>>2])|0),j=j<h?h:j,h=p+(36*k&-1)+28|0,g=g+(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]),k=k+1|0;if((k|0)>=(d|0)){e=j;l=g;break}}return d=e/l}function si(c){var d,g,e;a[1312713]=0;var l=a[1312766];if(0!=(l|0)){a:do{if(0<(a[1312712]|0)){var p=0;for(g=l;;){var j=a[g+(36*p&-1)+4>>2];0!=(j|0)&&(E(j),g=a[1312766]);j=a[g+(36*p&-1)+8>>2];0!=(j|0)&&(E(j),g=a[1312766]);p=p+1|0;if((p|0)>=(a[1312712]|0)){e=g;break a}}}else{e=l}}while(0);E(e)}a[1312766]=da(36*a[1312712]&-1);l=a[1312712];a:do{if(0<(l|0)){e=0;for(p=l;;){if(p=da(p<<2),a[a[1312766]+(36*e&-1)+4>>2]=p,p=da(a[1312712]<<2),g=a[1312766],a[g+(36*e&-1)+8>>2]=p,a[g+(36*e&-1)>>2]=e,p=e+1|0,e=(g+(36*e&-1)+12|0)>>2,a[e]=0,a[e+1]=0,a[e+2]=0,a[e+3]=0,a[e+4]=0,a[e+5]=0,g=a[1312712],(p|0)<(g|0)){e=p,p=g}else{break a}}}}while(0);l=c+20|0;e=ha(a[l>>2]);a:do{if(0!=(e|0)){p=c+28|0;for(g=e;;){j=zb(c,g);b:do{if(0!=(j|0)){for(var k=j;;){d=a[a[k+16>>2]+236>>2]+1|0;var h=k+12|0;c:do{if((d|0)<(a[a[h>>2]+236>>2]|0)){for(var i=a[1312766],m=d;;){var n=i+(36*m&-1)+16|0;a[n>>2]=a[n>>2]+1|0;m=m+1|0;if((m|0)>=(a[a[h>>2]+236>>2]|0)){break c}}}}while(0);k=Db(a[p>>2],k);if(0==(k|0)){break b}}}}while(0);g=sa(a[l>>2],g);if(0==(g|0)){break a}}}}while(0);l=a[1312712];if(0<(l|0)){c=c+256|0;e=a[1312708];p=0;for(j=a[1312713];!(g=(a[a[e+(24*p&-1)>>2]>>2]+236|0)>>2,d=a[g],k=d+1|0,(k|0)>(j|0)&&(j=a[1312713]=k),k=e+(24*p&-1)+8|0,h=72*(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),k=a[1312766],d=(k+(36*d&-1)+20|0)>>2,i=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),f[b>>3]=i+h+((0<i)<<31>>31&a[c>>2]|0),a[d]=a[b>>2],a[d+1]=a[b+4>>2],h=a[g],d=(k+(36*h&-1)+28|0)>>2,i=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),m=e+(24*p&-1)+16|0,m=72*(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),i<m?(f[b>>3]=m,a[d]=a[b>>2],a[d+1]=a[b+4>>2],d=a[g]):d=h,a[a[k+(36*d&-1)+4>>2]+(a[k+(36*d&-1)+12>>2]<<2)>>2]=e+(24*p&-1)|0,g=k+(36*a[g]&-1)+12|0,a[g>>2]=a[g>>2]+1|0,p=p+1|0,(p|0)>=(l|0));){}}}function rq(c){var d,g,e=0,l=a[1312713],p=a[1311598];d=a[1312766];g=d>>2;for(var j=0;(j|0)<(l|0);){var k=a[p+(j<<2)>>2],h=j+1|0;if(2>(a[((36*k&-1)+12>>2)+g]|0)){j=h}else{e=2990;break}}if(2990==e){if((l|0)>(h|0)){var i=d+(36*a[p+(h<<2)>>2]&-1)+20|0,m=k,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3])}else{var m=k,i=0}}if((j|0)!=(l|0)){af(a[((36*m&-1)+4>>2)+g],a[((36*m&-1)+12>>2)+g],14);k=a[1312766];g=k+(36*m&-1)+20|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);if(i>.25*g){if(i<.75*g){var w=i}else{e=2995}}else{e=2995}2995==e&&(w=.5*g);e=a[k+(36*m&-1)+12>>2];if(0<(e|0)){c=c+256|0;for(j=l=g=i=0;;){var x,p=a[k+(36*m&-1)+8>>2];do{if(0==(a[p+(j<<2)>>2]|0)){var v=a[a[k+(36*m&-1)+4>>2]+(j<<2)>>2];d=(v+8|0)>>2;var t=72*(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),y=a[c>>2]&(0<l)<<31>>31|0,h=0==(i|0);if(l+t+y<=w|h){d=l+t+y,t=g,y=h?1:i,v=h?v:x,h=k}else{var h=x+4|0,z=a[h>>2];if(0<(z|0)){for(var t=v+4|0,y=x|0,v=v|0,B=0,F=a[t>>2];;){if(0<(F|0)){for(F=0;;){n[pd(a[a[y>>2]+(B<<2)>>2],a[a[v>>2]+(F<<2)>>2],0)+124|0]=1;var F=F+1|0,A=a[t>>2];if((F|0)>=(A|0)){break}}F=A;z=a[h>>2]}B=B+1|0;if((B|0)>=(z|0)){break}}h=a[1312766];t=a[h+(36*m&-1)+8>>2]}else{t=p,h=k}a[t+(j<<2)>>2]=1;t=h+(36*m&-1)+12|0;a[t>>2]=a[t>>2]-1|0;t=h+(36*m&-1)+16|0;a[t>>2]=a[t>>2]+1|0;t=72*(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3])+(a[c>>2]|0);d=(h+(36*m&-1)+20|0)>>2;t=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3])-t;f[b>>3]=t;a[d]=a[b>>2];a[d+1]=a[b+4>>2];d=l;t=g;y=i;v=x}}else{d=l,t=g+1|0,y=i,v=x,h=k}}while(0);j=j+1|0;if((j|0)<(t+e|0)){x=v,i=y,g=t,l=d,k=h}else{break}}}}}function sq(b){var c=b+4|0;if(0>=(a[c>>2]|0)){var d;return 0}for(var b=b|0,e=0,f=0;;){var p=a[a[b>>2]+(f<<2)>>2],j=a[p+20>>2],p=zb(j,p);a:do{if(0==(p|0)){var k=e}else{for(var h=j+28|0,i=e,m=p;;){if(i=i+1|0,m=Db(a[h>>2],m),0==(m|0)){k=i;break a}}}}while(0);f=f+1|0;if((f|0)<(a[c>>2]|0)){e=k}else{d=k;break}}return d}function tq(b){var c=a[1345515];return 0!=(c|0)&&(b=tb(b|0,a[c+8>>2]),0!=(b|0)&&0!=n[b]<<24>>24&&0==Xd(b)<<24>>24)?1:0}function uq(b){Xk(b);var c=b+20|0,d=ha(a[c>>2]);if(0!=(d|0)){for(var e=b+28|0;;){var f=zb(b,d);a:do{if(0!=(f|0)){for(var p=f;;){var j=p;b:do{if(0==(a[p+180>>2]|0)&&0==(tq(j)|0)){var k=p+16|0,h=ec(a[k>>2]),i=p+12|0,m=ec(a[i>>2]);if((h|0)!=(m|0)){do{if(0==(a[h+216>>2]|0)&&0==(a[m+216>>2]|0)){k=xf(h,m);0==(k|0)?pd(h,m,j):Be(j,k);break b}}while(0);vq(b,a[k>>2],a[i>>2],j)}}}while(0);p=Db(a[e>>2],p);if(0==(p|0)){break a}}}}while(0);d=sa(a[c>>2],d);if(0==(d|0)){break}}}}function vq(b,c,d,e){var f=a[e+16>>2],h=a[f+216>>2],j=a[e+12>>2],k=a[j+216>>2],h=(0==(h|0)?0:a[f+236>>2]-a[a[h+272>>2]+236>>2]|0)-(0==(k|0)?0:a[j+236>>2]-a[a[k+272>>2]+236>>2]|0)+fc[e+178>>1]|0;0<(h|0)?(f=h|0,h=0):(f=0,h=-h|0);b=Me(b);n[b+162|0]=2;c=ec(c);d=ec(d);j=e+164|0;c=Hc(b,c,h,10*hb[j>>2]&-1);a[Hc(b,d,f,hb[j>>2]&-1)+128>>2]=e;a[c+128>>2]=e}function wq(c,d){var g,e=(c|0)/2&-1|0;g=(d+104|0)>>2;var l=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])+e;f[b>>3]=l;a[g]=a[b>>2];a[g+1]=a[b+4>>2];g=(d+112|0)>>2;e=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])+e;f[b>>3]=e;a[g]=a[b>>2];a[g+1]=a[b+4>>2]}function fg(b,c,d,e){var f=a[a[c+16>>2]+236>>2],h=a[a[c+12>>2]+236>>2],f=(f|0)>(h|0)?f:h,h=c+180|0;0!=(a[h>>2]|0)&&ia(5371108,149,5379608,5329216);a[h>>2]=d;for(var b=b+256|0,e=0==(e|0),h=c+162|0,j=c+164|0,c=c+176|0;;){if(!e){var k=d+176|0;C[k>>1]=C[k>>1]+C[c>>1]&65535}k=d+162|0;C[k>>1]=C[k>>1]+C[h>>1]&65535;k=d+164|0;hb[k>>2]+=hb[j>>2];d=d+12|0;k=a[d>>2];if((a[k+236>>2]|0)==(f|0)){break}wq(a[b>>2],k);d=a[a[a[d>>2]+184>>2]>>2];if(0==(d|0)){break}}}function xq(b,c){return!(0==(b|0)|0==(c|0))&&(a[b+16>>2]|0)==(a[c+16>>2]|0)&&(a[b+12>>2]|0)==(a[c+12>>2]|0)&&(a[b+108>>2]|0)==(a[c+108>>2]|0)&&0!=(eh(b,c)|0)?1:0}function Yk(b){var c,d,e,f,h,j,k=b+216|0;a[k>>2]=0;j=(b+240|0)>>2;a[j]=0;Xk(b);h=b+208|0;a:do{if(1<=(a[h>>2]|0)){for(var r=b+212|0,i=1;;){if(yq(b,a[a[r>>2]+(i<<2)>>2]),i=i+1|0,(i|0)>(a[h>>2]|0)){break a}}}}while(0);h=(b+20|0)>>2;r=ha(a[h]);a:do{if(0!=(r|0)){for(var i=b+28|0,m=r;;){f=zb(b,m);b:do{if(0!=(f|0)){for(var w=f;;){var x=a[w+12>>2]+166|0;e=n[x];3>e<<24>>24&&(n[x]=e+1&255);x=a[w+16>>2]+166|0;e=n[x];3>e<<24>>24&&(n[x]=e+1&255);w=Db(a[i>>2],w);if(0==(w|0)){break b}}}}while(0);m=sa(a[h],m);if(0==(m|0)){break a}}}}while(0);r=ha(a[h]);a:do{if(0!=(r|0)){i=b+28|0;for(m=r;;){f=m;0==(a[m+216>>2]|0)&&(f|0)==(ec(f)|0)&&(Zk(b,f),a[j]=a[j]+1|0);w=zb(b,m);b:do{if(0!=(w|0)){x=0;f=x>>2;var v=w;for(e=v>>2;;){var t=v,y=v+24|0;c:do{if(0==(a[e+45]|0)){if(d=7==n[a[t+16>>2]+165|0]<<24>>24?1:7==n[a[t+12>>2]+165|0]<<24>>24,d&=1,0!=(d|0)){0==(xq(x,t)|0)?(zq(b,t),d=t):(d=a[f+45],0!=(d|0)?(fg(b,t,d,0),df(t)):(a[a[e+4]+236>>2]|0)==(a[a[e+3]+236>>2]|0)&&(Be(t,x),df(t)),d=x)}else{d=(v+16|0)>>2;var z=a[d];do{if(0!=(x|0)&&(z|0)==(a[f+4]|0)&&(c=a[e+3],(c|0)==(a[f+3]|0))){if((a[z+236>>2]|0)==(a[c+236>>2]|0)){Be(t,x);df(t);d=x;break c}if(0==(a[y+84>>2]|0)&&0==(a[f+27]|0)&&0!=(eh(t,x)|0)){0==n[5382112]<<24>>24?(fg(b,t,a[f+45],1),df(t)):n[y+100|0]=6;d=x;break c}}}while(0);c=(v+12|0)>>2;if((z|0)==(a[c]|0)){df(t),d=t}else{var z=ec(z),B=ec(a[c]),F=a[d];if((F|0)!=(z|0)){d=x}else{var A=a[c];if((A|0)!=(B|0)){d=x}else{var C=a[F+236>>2],E=a[A+236>>2];if((C|0)==(E|0)){fh(b,t)}else{if((E|0)>(C|0)){gh(b,z,B,t)}else{B=z=bj(b,A,F);do{if(!(0==(z|0)|(z|0)==(v|0))&&(F=z+24|0,A=F+156|0,0==(a[A>>2]|0)&&gh(b,a[z+16>>2],a[z+12>>2],B),0==(a[y+84>>2]|0)&&0==(a[F+84>>2]|0)&&0!=(eh(t,B)|0))){0==n[5382112]<<24>>24?(df(t),fg(b,t,a[A>>2],1)):(n[y+100|0]=6,n[F+137|0]=1);d=x;break c}}while(0);gh(b,a[c],a[d],t)}}d=t}}}}}else{d=t}}while(0);e=Db(a[i>>2],v);if(0==(e|0)){break b}else{x=d,f=x>>2,v=e,e=v>>2}}}}while(0);m=sa(a[h],m);if(0==(m|0)){break a}}}}while(0);(a[b+32>>2]|0)!=(b|0)&&(b=b+224|0,j=a[b>>2],j=0==(j|0)?Za(4):Oa(j,4),a[b>>2]=j,a[j>>2]=a[k>>2])}function zq(b,c){var d=Aq(a[c+16>>2]),e=Aq(a[c+12>>2]),f=(a[d+236>>2]|0)>(a[e+236>>2]|0),h=f?e:d,e=f?d:e;if((a[h+216>>2]|0)!=(a[e+216>>2]|0)){if(d=xf(h,e),0!=(d|0)){fg(b,c,d,1)}else{if(d=e+236|0,(a[h+236>>2]|0)!=(a[d>>2]|0)){gh(b,h,e,c);for(h=c+180|0;;){h=a[h>>2];if(0==(h|0)){break}e=a[h+12>>2];if((a[e+236>>2]|0)>(a[d>>2]|0)){break}n[h+124|0]=5;h=a[e+184>>2]}}}}}function gh(c,d,g,e){var l=0==(a[e+108>>2]|0)?-1:(a[g+236>>2]+a[d+236>>2]|0)/2&-1,h=e+180|0;0!=(a[h>>2]|0)&&ia(5371108,90,5379672,5351068);var j=a[d+236>>2]+1|0,k=g+236|0,r=a[k>>2];a:do{if((j|0)<=(r|0)){for(var i=d,m=j,w=r;;){if((m|0)<(w|0)){if((m|0)==(l|0)){var w=c,x=e,v=Wb,v=x+108|0,t=a[v>>2],y=t+24|0,y=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),t=t+32|0,z=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3]),t=Me(w);a[t+120>>2]=a[v>>2];v=t+104|0;f[b>>3]=a[a[a[t+20>>2]+32>>2]+256>>2]|0;a[v>>2]=a[b>>2];a[v+4>>2]=a[b+4>>2];0==n[x+126|0]<<24>>24&&(v=(t+96|0)>>2,0==(a[a[w+32>>2]+152>>2]&1|0)?(f[b>>3]=z,a[v]=a[b>>2],a[v+1]=a[b+4>>2],w=t+112|0,f[b>>3]=y):(f[b>>3]=y,a[v]=a[b>>2],a[v+1]=a[b+4>>2],w=t+112|0,f[b>>3]=z),a[w>>2]=a[b>>2],a[w+4>>2]=a[b+4>>2]);w=t}else{w=c,x=Me(w),wq(a[w+256>>2],x),w=x}a[w+236>>2]=m}else{w=g}i=pd(i,w,e);x=i+164|0;hb[x>>2]*=a[(12*Bq(a[i+16>>2])&-1)+(Bq(a[i+12>>2])<<2)+5245600>>2]|0;m=m+1|0;x=a[k>>2];if((m|0)>(x|0)){break a}else{i=w,w=x}}}}while(0);0==(a[h>>2]|0)&&ia(5371108,104,5379672,5345080)}function Aq(b){return 7==n[b+165|0]<<24>>24?a[a[a[b+216>>2]+276>>2]+(a[b+236>>2]<<2)>>2]:ec(b)}function Cq(b){var c,d;d=(b+32|0)>>2;var e=a[d],f=b+20|0,h=ha(a[f>>2]);if(0!=(h|0)){for(;;){var j=Gg(a[d],h);a:do{if(0!=(j|0)){var k=0,r=j;for(c=r>>2;;){var i=r;if(0==(fd(b,r|0)|0)){var m=r,n=0==(xq(k,m)|0),x=r+16|0,v=a[x>>2],t=a[v+236>>2],y=r+12|0,z=a[y>>2],B=a[z+236>>2],F=(t|0)==(B|0);n?F?(t=Dq(v,z),0==(t|0)?fh(e,m):((r|0)!=(t|0)&&(Eq(m,a[m+16>>2]+208|0),0==(a[c+45]|0)&&Be(m,t)),i=k)):(0==(a[c+45]|0)?(ia(5341588,234,5379720,5365176),m=a[y>>2],t=a[x>>2],k=m,m=a[m+236>>2],v=t,t=a[t+236>>2]):(k=z,m=B),(m|0)>(t|0)?Fq(v,k,i):Fq(k,v,i)):(a[c+45]=F?k:0,i=a[k+180>>2],0!=(i|0)&&(fg(b,m,i,0),Eq(m,a[m+16>>2]+208|0)),i=k)}else{i=k}r=Hg(a[d],r,h);if(0==(r|0)){break a}else{k=i,c=r>>2}}}}while(0);h=sa(a[f>>2],h);if(0==(h|0)){break}}}}function Fq(b,c,d){var e=Gq(b),f=Gq(c);Hq(e,f,d,a[d+180>>2],(e|0)==(b|0)&(f|0)==(c|0)?1:5)}function Gq(b){var c=a[b+216>>2];return 0==(c|0)||0!=n[c+280|0]<<24>>24?b:b=a[a[c+276>>2]+(a[b+236>>2]<<2)>>2]}function Iq(b){var c,d,e;e=(b+32|0)>>2;var f=a[e];c=b+244|0;d=C[c>>1];if(0<d<<16>>16){n[a[f+220>>2]+(44*((d<<16>>16)-1)&-1)+33|0]=0;var h=C[c>>1]}else{h=d}var j=h<<16>>16,k=b+246|0;a:do{if(h<<16>>16>C[k>>1]<<16>>16){var r=j}else{d=(b+220|0)>>2;var i=b+276|0;c=(f+220|0)>>2;for(var m=b,w=j;;){var x=a[a[a[i>>2]+(w<<2)>>2]+240>>2];$k(f,w,x,a[a[d]+(44*w&-1)>>2]);var v=a[d];b:do{if(0<(a[v+(44*w&-1)>>2]|0)){for(var t=0,y=x,z=v;;){if(z=a[a[z+(44*w&-1)+4>>2]+(t<<2)>>2],a[a[a[c]+(44*w&-1)+4>>2]+(y<<2)>>2]=z,a[z+240>>2]=y,a[z+20>>2]=a[e],al(m,z),Zk(a[e],z),z=a[e]+240|0,a[z>>2]=a[z>>2]+1|0,t=t+1|0,z=a[d],(t|0)<(a[z+(44*w&-1)>>2]|0)){y=y+1|0}else{var B=z;break b}}}else{B=v}}while(0);a[B+(44*w&-1)+4>>2]=(x<<2)+a[a[c]+(44*w&-1)+4>>2]|0;n[a[c]+(44*w&-1)+33|0]=0;w=w+1|0;if((w|0)>(C[k>>1]<<16>>16|0)){r=w;break a}}}}while(0);(r|0)<(C[f+246>>1]<<16>>16|0)&&(n[a[f+220>>2]+(44*r&-1)+33|0]=0);b=b+280|0;n[b]=1}function Jq(b){var c=C[b+244>>1],d=b+246|0;if(c<<16>>16<=C[d>>1]<<16>>16){for(var e=b+276|0,b=b+32|0,c=c<<16>>16;;){var f=a[a[e>>2]+(c<<2)>>2],h=f+184|0,j=a[a[h>>2]>>2];a:do{if(0!=(j|0)){for(var k=j;;){if(Yd(k),k=a[a[h>>2]>>2],0==(k|0)){break a}}}}while(0);h=f+176|0;j=a[a[h>>2]>>2];a:do{if(0!=(j|0)){for(k=j;;){if(Yd(k),k=a[a[h>>2]>>2],0==(k|0)){break a}}}}while(0);al(a[b>>2],f);a[a[e>>2]+(c<<2)>>2]=0;c=c+1|0;if((c|0)>(C[d>>1]<<16>>16|0)){break}}}}function Xk(b){var c=h,d=b+20|0,e=ha(a[d>>2]);a:do{if(0!=(e|0)){for(var f=e;;){if(7==n[f+165|0]<<24>>24&&qn(f),a[f+216>>2]=0,f=sa(a[d>>2],f),0==(f|0)){break a}}}}while(0);d=b+208|0;if(1<=(a[d>>2]|0)){e=b+212|0;b=b+12|0;for(f=1;;){var p=a[a[e>>2]+(f<<2)>>2],j=p,k=p+20|0,r=ha(a[k>>2]);a:do{if(0!=(r|0)){for(var q=p+272|0,m=p,w=p+28|0,x=r;;){var v=sa(a[k>>2],x),t=x+24|0,y=t+141|0;b:do{if(0==n[y]<<24>>24){var z=x,B=a[q>>2];(ec(z)|0)!=(z|0)&&ia(5375372,198,5380172,5353980);a[z+224>>2]=B;B=B+220|0;a[B>>2]=a[B>>2]+a[z+220>>2]|0;a[t+192>>2]=p;n[y]=7;z=zb(j,x);if(0!=(z|0)){for(;;){B=a[z+180>>2];c:do{if(0!=(B|0)){for(var F=B;;){if(0==(F|0)){break c}var F=F+12|0,A=a[F>>2];if(1!=n[A+162|0]<<24>>24){break c}a[A+216>>2]=p;F=a[a[a[F>>2]+184>>2]>>2]}}}while(0);z=Db(a[w>>2],z);if(0==(z|0)){break b}}}}else{z=a[b>>2],aa(0,5347712,(i=h,h=h+8|0,a[i>>2]=a[x+12>>2],a[i+4>>2]=z,i)),Ng(m,x|0)}}while(0);if(0==(v|0)){break a}else{x=v}}}}while(0);f=f+1|0;if((f|0)>(a[d>>2]|0)){break}}}h=c}function yq(b,c){var d,e;e=(c+246|0)>>1;d=(c+276|0)>>2;a[d]=da((C[e]<<16>>16<<2)+8|0);var f=c+244|0,h=C[f>>1];a:do{if(h<<16>>16<=C[e]<<16>>16){for(var j=b,k=c,r=0,i=h<<16>>16;;){var m=Me(j),w=m;a[a[d]+(i<<2)>>2]=w;a[m+236>>2]=i;n[m+165|0]=7;a[m+216>>2]=k;0!=(r|0)&&(r=pd(r,m,0)+162|0,C[r>>1]=1e3*C[r>>1]&65535);i=i+1|0;if((i|0)>(C[e]<<16>>16|0)){break a}else{r=w}}}}while(0);h=c+20|0;j=ha(a[h>>2]);a:do{if(0!=(j|0)){k=c+28|0;for(w=j;;){r=a[a[d]+(a[w+236>>2]<<2)>>2];i=r+220|0;a[i>>2]=a[i>>2]+1|0;i=zb(c,w);b:do{if(0!=(i|0)){for(var m=r+184|0,x=i;;){var v=a[a[x+16>>2]+236>>2],t=x+12|0;c:do{if((v|0)<(a[a[t>>2]+236>>2]|0)){for(var y=v;;){var z=a[a[m>>2]>>2]+176|0;C[z>>1]=C[z>>1]+1&65535;y=y+1|0;if((y|0)>=(a[a[t>>2]+236>>2]|0)){break c}}}}while(0);x=Db(a[k>>2],x);if(0==(x|0)){break b}}}}while(0);w=sa(a[h>>2],w);if(0==(w|0)){break a}}}}while(0);f=C[f>>1];h=C[e];if(f<<16>>16<=h<<16>>16){for(f=f<<16>>16;!(j=a[a[d]+(f<<2)>>2]+220|0,k=a[j>>2],1<(k|0)&&(a[j>>2]=k-1|0,h=C[e]),f=f+1|0,(f|0)>(h<<16>>16|0));){}}}function Kq(b,c,d,e){var f,h=c+281|0,j=d+1|0;if((n[h]<<24>>24|0)!=(j|0)){var k=c+244|0,i=C[k>>1];f=(c+246|0)>>1;var q=C[f];if(i<<16>>16>q<<16>>16){var b=i,m=q}else{q=c+276|0;for(i=i<<16>>16;!(bl(b,a[a[q>>2]+(i<<2)>>2]),i=i+1|0,m=C[f],(i|0)>(m<<16>>16|0));){}b=C[k>>1]}a:do{if(b<<16>>16<=m<<16>>16){k=c+276|0;q=e;for(i=b<<16>>16;;){if(cl(q,a[a[k>>2]+(i<<2)>>2],d),i=i+1|0,(i|0)>(C[f]<<16>>16|0)){break a}}}}while(0);n[h]=j&255}}function dl(b){var c=b+20|0,d=ha(a[c>>2]);if(0!=(d|0)){for(var e=b+28|0;;){a[d+216>>2]=0;var f=zb(b,d);a:do{if(0!=(f|0)){for(var h=f;;){var j=a[h+180>>2];b:do{if(0!=(j|0)){for(var k=j;;){if(0==(k|0)){break b}var k=k+12|0,i=a[k>>2];if(1!=n[i+162|0]<<24>>24){break b}a[i+216>>2]=0;k=a[a[a[k>>2]+184>>2]>>2]}}}while(0);h=Db(a[e>>2],h);if(0==(h|0)){break a}}}}while(0);d=sa(a[c>>2],d);if(0==(d|0)){break}}}el(b)}function el(b){var c=b+208|0;a:do{if(1<=(a[c>>2]|0)){for(var d=b+212|0,e=1;;){if(el(a[a[d>>2]+(e<<2)>>2]),e=e+1|0,(e|0)>(a[c>>2]|0)){break a}}}}while(0);c=b+20|0;e=ha(a[c>>2]);if(0!=(e|0)){for(d=b+28|0;;){var f=e+216|0;0==(a[f>>2]|0)&&(a[f>>2]=b);f=zb(b,e);a:do{if(0!=(f|0)){for(var h=f;;){var j=a[h+180>>2];b:do{if(0!=(j|0)){for(var k=j;;){if(0==(k|0)){break b}var k=k+12|0,i=a[k>>2];if(1!=n[i+162|0]<<24>>24){break b}var q=i+216|0;0==(a[q>>2]|0)?(a[q>>2]=b,k=a[k>>2]):k=i;k=a[a[k+184>>2]>>2]}}}while(0);h=Db(a[d>>2],h);if(0==(h|0)){break a}}}}while(0);e=sa(a[c>>2],e);if(0==(e|0)){break}}}}function $k(b,c,d,e){var f,h,b=(b+220|0)>>2,j=a[b];h=j>>2;var k=a[((44*c&-1)+4>>2)+h];f=k>>2;if(1>(e|0)){d=d-e|0;k=d+1|0;h=a[((44*c&-1)>>2)+h];a:do{if((k|0)<(h|0)){for(var i=d,q=k;;){var m=a[(q<<2>>2)+f],i=i+e|0;a[m+240>>2]=i;a[(i<<2>>2)+f]=m;var m=q+1|0,i=a[b],n=a[i+(44*c&-1)>>2];if((m|0)<(n|0)){i=q,q=m}else{var x=i,v=n;break a}}}else{x=j,v=h}}while(0);e=e-1|0;j=e+v|0;if((j|0)<(v|0)){for(x=j;;){if(a[(x<<2>>2)+f]=0,x=x+1|0,v=a[b],(x|0)>=(a[v+(44*c&-1)>>2]|0)){t=v;y=e;break}}c=(t+(44*c&-1)|0)>>2;b=a[c];b=y+b|0}else{var t,y,c=x+(44*c&-1)|0,c=c>>2,b=a[c],b=e+b|0}}else{y=a[((44*c&-1)>>2)+h]-1|0;a:do{if((y|0)>(d|0)){t=e-1|0;for(x=y;;){if(v=a[(x<<2>>2)+f],j=t+x|0,a[v+240>>2]=j,a[(j<<2>>2)+f]=v,x=x-1|0,(x|0)<=(d|0)){break a}}}}while(0);f=d+1|0;(f|0)<(e+d|0)&&Ef((f<<2)+k|0,0,(e<<2)-4|0);t=a[b];c=t+(44*c&-1)|0;c>>=2;b=a[c];b=(e-1|0)+b|0}a[c]=b}function gg(c,d,g){var e=g|0;if((a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])>c){return 0}e=g+16|0;if((a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])<c){return 0}c=g+8|0;if((a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])>d){return 0}g=g+24|0;d=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])>=d;return d&1}function Hq(c,d,g,e,l){var h,j;j=(c+236|0)>>2;h=(d+236|0)>>2;(a[j]|0)<(a[h]|0)||ia(5341588,109,5379620,5343556);if(!((a[e+16>>2]|0)==(c|0)&&(a[e+12>>2]|0)==(d|0))){if(1<C[e+176>>1]<<16>>16){a[g+180>>2]=0;var k=a[h],i=a[j];if(1==(k-i|0)){var q=xf(c,d);if(0!=(q|0)&&0!=(eh(g,q)|0)){Be(g,q);if(0!=n[c+162|0]<<24>>24||0!=n[d+162|0]<<24>>24){return}df(g);return}}if((i|0)<(k|0)){q=c+20|0;l&=255;for(j=k;;){if((i|0)<(j-1|0)){j=e+12|0;var k=a[q>>2],m=a[j>>2],w=m+236|0,x=a[w>>2],v=m+240|0;$k(k,x,a[v>>2],2);var t=Me(k),y=m+104|0,y=(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]),z=t+104|0;f[b>>3]=y;a[z>>2]=a[b>>2];a[z+4>>2]=a[b+4>>2];m=m+112|0;m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]);y=t+112|0;f[b>>3]=m;a[y>>2]=a[b>>2];a[y+4>>2]=a[b+4>>2];a[t+236>>2]=a[w>>2];w=a[v>>2]+1|0;a[t+240>>2]=w;k=a[a[a[k+220>>2]+(44*x&-1)+4>>2]+(w<<2)>>2]=t}else{k=d,j=e+12|0}n[pd(c,k,g)+124|0]=l;e=e+176|0;C[e>>1]=C[e>>1]-1&65535;i=i+1|0;x=a[h];if((i|0)<(x|0)){e=a[a[a[j>>2]+184>>2]>>2],c=k,j=x}else{break}}}}else{a:do{if(1==(a[h]-a[j]|0)){t=c;w=d;k=v=xf(t,w);x=g;do{if(0!=(v|0)&&0!=(eh(x,v)|0)){a[g+180>>2]=k;n[v+124|0]=l&255;e=v+176|0;C[e>>1]=C[e>>1]+1&65535;if(0!=n[c+162|0]<<24>>24){break a}if(0!=n[d+162|0]<<24>>24){break a}df(x);break a}}while(0);a[g+180>>2]=0;k=pd(t,w,x);n[k+124|0]=l&255}else{k=e}}while(0);x=a[h];if(1<(x-a[j]|0)){(a[k+16>>2]|0)==(c|0)?(e=k,h=x):(e=g+180|0,a[e>>2]=0,c=pd(c,a[k+12>>2],g),a[e>>2]=c,Yd(k),e=c,h=a[h]);c=a[e+12>>2];a:do{if((a[c+236>>2]|0)==(h|0)){q=e,i=c}else{for(j=c;;){if(j=a[a[j+184>>2]>>2],k=a[j+12>>2],(a[k+236>>2]|0)==(h|0)){q=j;i=k;break a}else{j=k}}}}while(0);(i|0)!=(d|0)&&(n[pd(a[q+16>>2],d,g)+124|0]=l&255,Yd(q))}}}}function Lq(c,d){var g,e,l,p,j,k,r,q,m,n,x,v,t,y,z,B,F,A,C,G,H,I,Z,T,K,M,L,J,P,N,R,Y,Q,da,$,ea,wa,ca,V,W,X,ba,ma,ib,fa,ha=0,O=h;h=h+224|0;var ga=O+64,sa=O+80,qa=O+96,ua=O+112,Da=O+128,Ja=O+144,Ab=O+160,ra=O+176,ta=O+192,ya=O+208,ja=d|0,la=Mq(c,U(ja,5370040)),va=Mq(c,U(ja,5374976)),oa=0!=(va|0),ka=0==(la|0);if(!(ka&(oa^1))){var Ea=d+24|0,Ka=a[Ea>>2];if(0!=(Ka|0)){if(1<(a[Ka+4>>2]|0)){var Na=a[a[d+12>>2]+12>>2];aa(0,5353440,(i=h,h=h+8|0,a[i>>2]=a[a[d+16>>2]+12>>2],a[i+4>>2]=Na,i))}else{var Ba=a[Ka>>2],Wa=a[Ba+4>>2];fa=(d+12|0)>>2;var na=a[fa];ib=(d+16|0)>>2;var xa=a[ib],Ra=Za(48);ma=(Ba+12|0)>>2;a[Ra+12>>2]=a[ma];ba=(Ba+8|0)>>2;a[Ra+8>>2]=a[ba];do{if(ka){ha=84}else{var bb=la+52|0,Xa=na+32|0,Sa=na+40|0;if(0==(gg((a[b>>2]=a[Xa>>2],a[b+4>>2]=a[Xa+4>>2],f[b>>3]),(a[b>>2]=a[Sa>>2],a[b+4>>2]=a[Sa+4>>2],f[b>>3]),bb)|0)){var Oa=a[a[ib]+12>>2],Va=a[a[fa]+12>>2],Ta=U(ja,5370040);aa(0,5345596,(i=h,h=h+12|0,a[i>>2]=Oa,a[i+4>>2]=Va,a[i+8>>2]=Ta,i));ha=84}else{X=(Ba|0)>>2;var Aa=a[X],fb=Aa|0,Ca=(a[b>>2]=a[fb>>2],a[b+4>>2]=a[fb+4>>2],f[b>>3]),Ya=Aa+8|0,$a=(a[b>>2]=a[Ya>>2],a[b+4>>2]=a[Ya+4>>2],f[b>>3]);if(0!=(gg(Ca,$a,bb)|0)){var La=xa+32|0,pa=xa+40|0;if(0!=(gg((a[b>>2]=a[La>>2],a[b+4>>2]=a[La+4>>2],f[b>>3]),(a[b>>2]=a[pa>>2],a[b+4>>2]=a[pa+4>>2],f[b>>3]),bb)|0)){var Ga=a[a[ib]+12>>2],Fa=a[a[fa]+12>>2],Ha=U(ja,5370040);aa(0,5341976,(i=h,h=h+12|0,a[i>>2]=Ga,a[i+4>>2]=Fa,a[i+8>>2]=Ha,i));ha=84}else{if(0==(a[ba]|0)){ia(5338424,364,5379700,5335620);var nb=a[X],jb=nb|0,cb=nb+8|0,Pa=(a[b>>2]=a[jb>>2],a[b+4>>2]=a[jb+4>>2],f[b>>3]),kb=(a[b>>2]=a[cb>>2],a[b+4>>2]=a[cb+4>>2],f[b>>3])}else{Pa=Ca,kb=$a}W=(Ba+16|0)>>2;V=(Ba+24|0)>>2;hh(ga,Pa,kb,(a[b>>2]=a[W],a[b+4>>2]=a[W+1],f[b>>3]),(a[b>>2]=a[V],a[b+4>>2]=a[V+1],f[b>>3]),bb);var Kb=ga|0,Ma=(a[b>>2]=a[Kb>>2],a[b+4>>2]=a[Kb+4>>2],f[b>>3]),hb=ga+8|0,lb=(a[b>>2]=a[hb>>2],a[b+4>>2]=a[hb+4>>2],f[b>>3]),rb=a[X],ab=rb+48|0;f[b>>3]=Ma;a[ab>>2]=a[b>>2];a[ab+4>>2]=a[b+4>>2];var db=rb+56|0;f[b>>3]=lb;a[db>>2]=a[b>>2];a[db+4>>2]=a[b+4>>2];var ob=a[X]+16|0;hg(sa,Ma,lb,(a[b>>2]=a[W],a[b+4>>2]=a[W+1],f[b>>3]),(a[b>>2]=a[V],a[b+4>>2]=a[V+1],f[b>>3]));ca=ob>>2;wa=sa>>2;a[ca]=a[wa];a[ca+1]=a[wa+1];a[ca+2]=a[wa+2];a[ca+3]=a[wa+3];var pb=a[X],ub=pb+16|0,gb=(a[b>>2]=a[ub>>2],a[b+4>>2]=a[ub+4>>2],f[b>>3]),sb=pb+24|0,Ia=(a[b>>2]=a[sb>>2],a[b+4>>2]=a[sb+4>>2],f[b>>3]);hg(qa,gb,Ia,(a[b>>2]=a[W],a[b+4>>2]=a[W+1],f[b>>3]),(a[b>>2]=a[V],a[b+4>>2]=a[V+1],f[b>>3]));ea=pb>>2;$=qa>>2;a[ea]=a[$];a[ea+1]=a[$+1];a[ea+2]=a[$+2];a[ea+3]=a[$+3];var vb=a[X],Ua=vb+16|0,eb=vb+24|0;hg(ua,(a[b>>2]=a[Ua>>2],a[b+4>>2]=a[Ua+4>>2],f[b>>3]),(a[b>>2]=a[eb>>2],a[b+4>>2]=a[eb+4>>2],f[b>>3]),Ma,lb);da=(vb+32|0)>>2;Q=ua>>2;a[da]=a[Q];a[da+1]=a[Q+1];a[da+2]=a[Q+2];a[da+3]=a[Q+3];var mb=a[ma],qb=0==(mb|0)?3:Gh(d,a[X],0,0,Ra,mb)+3|0}}else{for(var Bb=Wa-1|0,Qa=0;(Qa|0)<(Bb|0);){if(0==(fl((Qa<<4)+a[X]|0,bb)|0)){Qa=Qa+3|0}else{break}}var xb=a[ma],za=0!=(xb|0);if((Qa|0)==(Bb|0)){za||ia(5338424,382,5379700,5332764);Y=(Ra+32|0)>>2;var Nb=a[X],Jb=Ba+32|0,zb=(a[b>>2]=a[Jb>>2],a[b+4>>2]=a[Jb+4>>2],f[b>>3]),tb=Ba+40|0,Cb=(a[b>>2]=a[tb>>2],a[b+4>>2]=a[tb+4>>2],f[b>>3]),Db=(Bb<<4)+Nb|0,Eb=(Bb<<4)+Nb+8|0;hh(Da,zb,Cb,(a[b>>2]=a[Db>>2],a[b+4>>2]=a[Db+4>>2],f[b>>3]),(a[b>>2]=a[Eb>>2],a[b+4>>2]=a[Eb+4>>2],f[b>>3]),bb);R=Da>>2;a[Y]=a[R];a[Y+1]=a[R+1];a[Y+2]=a[R+2];a[Y+3]=a[R+3];qb=Bb}else{qb=(za?Gh(d,a[X],0,Qa,Ra,xb):Qa)+3|0}}}}}while(0);if(84==ha){var Ib=Wa-1|0;0!=(a[ma]|0)&&(N=(Ra+32|0)>>2,P=(Ba+32|0)>>2,a[N]=a[P],a[N+1]=a[P+1],a[N+2]=a[P+2],a[N+3]=a[P+3]);qb=Ib}a:do{if(oa){var wb=va+52|0,Hb=xa+32|0,Mb=xa+40|0;if(0==(gg((a[b>>2]=a[Hb>>2],a[b+4>>2]=a[Hb+4>>2],f[b>>3]),(a[b>>2]=a[Mb>>2],a[b+4>>2]=a[Mb+4>>2],f[b>>3]),wb)|0)){var Ub=a[a[ib]+12>>2],Pb=a[a[fa]+12>>2],Lb=U(ja,5374976);aa(0,5329784,(i=h,h=h+12|0,a[i>>2]=Ub,a[i+4>>2]=Pb,a[i+8>>2]=Lb,i));ha=107}else{J=(Ba|0)>>2;var Sb=a[J],Zb=(qb<<4)+Sb|0,Xb=(a[b>>2]=a[Zb>>2],a[b+4>>2]=a[Zb+4>>2],f[b>>3]),hc=(qb<<4)+Sb+8|0,bc=(a[b>>2]=a[hc>>2],a[b+4>>2]=a[hc+4>>2],f[b>>3]);if(0!=(gg(Xb,bc,wb)|0)){var fc=na+32|0,cc=na+40|0;if(0!=(gg((a[b>>2]=a[fc>>2],a[b+4>>2]=a[fc+4>>2],f[b>>3]),(a[b>>2]=a[cc>>2],a[b+4>>2]=a[cc+4>>2],f[b>>3]),wb)|0)){var pc=a[a[ib]+12>>2],gc=a[a[fa]+12>>2],ec=U(ja,5374976);aa(0,5327092,(i=h,h=h+12|0,a[i>>2]=pc,a[i+4>>2]=gc,a[i+8>>2]=ec,i));ha=107}else{if(0==(a[ma]|0)){ia(5338424,424,5379700,5332764);var ic=a[J],Vb=(qb<<4)+ic|0,Yb=(qb<<4)+ic+8|0,Jc=(a[b>>2]=a[Vb>>2],a[b+4>>2]=a[Vb+4>>2],f[b>>3]),jc=(a[b>>2]=a[Yb>>2],a[b+4>>2]=a[Yb+4>>2],f[b>>3])}else{Jc=Xb,jc=bc}L=(Ra+32|0)>>2;M=(Ra+40|0)>>2;hh(Ja,Jc,jc,(a[b>>2]=a[L],a[b+4>>2]=a[L+1],f[b>>3]),(a[b>>2]=a[M],a[b+4>>2]=a[M+1],f[b>>3]),wb);var Qb=Ja|0,ac=(a[b>>2]=a[Qb>>2],a[b+4>>2]=a[Qb+4>>2],f[b>>3]),dc=Ja+8|0,$b=(a[b>>2]=a[dc>>2],a[b+4>>2]=a[dc+4>>2],f[b>>3]),kc=qb-3|0,uc=a[J],oc=(kc<<4)+uc|0;f[b>>3]=ac;a[oc>>2]=a[b>>2];a[oc+4>>2]=a[b+4>>2];var lc=(kc<<4)+uc+8|0;f[b>>3]=$b;a[lc>>2]=a[b>>2];a[lc+4>>2]=a[b+4>>2];var tc=qb-1|0,Kc=(tc<<4)+a[J]|0;hg(Ab,ac,$b,(a[b>>2]=a[L],a[b+4>>2]=a[L+1],f[b>>3]),(a[b>>2]=a[M],a[b+4>>2]=a[M+1],f[b>>3]));K=Kc>>2;T=Ab>>2;a[K]=a[T];a[K+1]=a[T+1];a[K+2]=a[T+2];a[K+3]=a[T+3];var rc=a[J],Bc=(tc<<4)+rc|0,Cc=(a[b>>2]=a[Bc>>2],a[b+4>>2]=a[Bc+4>>2],f[b>>3]),vc=(tc<<4)+rc+8|0,Dc=(a[b>>2]=a[vc>>2],a[b+4>>2]=a[vc+4>>2],f[b>>3]);hg(ra,Cc,Dc,(a[b>>2]=a[L],a[b+4>>2]=a[L+1],f[b>>3]),(a[b>>2]=a[M],a[b+4>>2]=a[M+1],f[b>>3]));Z=((qb<<4)+rc|0)>>2;I=ra>>2;a[Z]=a[I];a[Z+1]=a[I+1];a[Z+2]=a[I+2];a[Z+3]=a[I+3];var wc=a[J],Hc=(tc<<4)+wc|0,zc=(tc<<4)+wc+8|0;hg(ta,(a[b>>2]=a[Hc>>2],a[b+4>>2]=a[Hc+4>>2],f[b>>3]),(a[b>>2]=a[zc>>2],a[b+4>>2]=a[zc+4>>2],f[b>>3]),ac,$b);H=((qb-2<<4)+wc|0)>>2;G=ta>>2;a[H]=a[G];a[H+1]=a[G+1];a[H+2]=a[G+2];a[H+3]=a[G+3];var Yc=a[ba],xc=0==(Yc|0)?kc:Hh(d,a[J],kc,kc,Ra,Yc)}}else{var Ec=O|0;C=O>>2;A=(O+16|0)>>2;F=(O+32|0)>>2;B=(O+48|0)>>2;for(var Wc=qb;;){if(0>=(Wc|0)){ha=100;break}z=((Wc<<4)+a[J]|0)>>2;a[C]=a[z];a[C+1]=a[z+1];a[C+2]=a[z+2];a[C+3]=a[z+3];var Fc=Wc-1|0;y=((Fc<<4)+a[J]|0)>>2;a[A]=a[y];a[A+1]=a[y+1];a[A+2]=a[y+2];a[A+3]=a[y+3];var Nc=Wc-2|0;t=((Nc<<4)+a[J]|0)>>2;a[F]=a[t];a[F+1]=a[t+1];a[F+2]=a[t+2];a[F+3]=a[t+3];var yc=Wc-3|0;v=((yc<<4)+a[J]|0)>>2;a[B]=a[v];a[B+1]=a[v+1];a[B+2]=a[v+2];a[B+3]=a[v+3];if(0==(fl(Ec,wb)|0)){Wc=yc}else{ha=99;break}}do{if(99==ha){x=((Wc<<4)+a[J]|0)>>2;a[x]=a[C];a[x+1]=a[C+1];a[x+2]=a[C+2];a[x+3]=a[C+3];n=((Fc<<4)+a[J]|0)>>2;a[n]=a[A];a[n+1]=a[A+1];a[n+2]=a[A+2];a[n+3]=a[A+3];m=((Nc<<4)+a[J]|0)>>2;a[m]=a[F];a[m+1]=a[F+1];a[m+2]=a[F+2];a[m+3]=a[F+3];q=((yc<<4)+a[J]|0)>>2;a[q]=a[B];a[q+1]=a[B+1];a[q+2]=a[B+2];a[q+3]=a[B+3];var Gc=yc}else{if(100==ha){if(0!=(Wc|0)){Gc=Wc-3|0}else{0==(a[ba]|0)&&ia(5338424,447,5379700,5335620);r=(Ra+16|0)>>2;var Mc=a[J],Sc=Ba+16|0,bd=(a[b>>2]=a[Sc>>2],a[b+4>>2]=a[Sc+4>>2],f[b>>3]),Vc=Ba+24|0,cd=(a[b>>2]=a[Vc>>2],a[b+4>>2]=a[Vc+4>>2],f[b>>3]),Zc=Mc|0,nc=Mc+8|0;hh(ya,bd,cd,(a[b>>2]=a[Zc>>2],a[b+4>>2]=a[Zc+4>>2],f[b>>3]),(a[b>>2]=a[nc>>2],a[b+4>>2]=a[nc+4>>2],f[b>>3]),wb);k=ya>>2;a[r]=a[k];a[r+1]=a[k+1];a[r+2]=a[k+2];a[r+3]=a[k+3];xc=0;break a}}}}while(0);var Oc=a[ba],xc=0==(Oc|0)?Gc:Hh(d,a[J],Gc,qb-3|0,Ra,Oc)}}}else{ha=107}}while(0);107==ha&&(0!=(a[ba]|0)&&(j=(Ra+16|0)>>2,p=(Ba+16|0)>>2,a[j]=a[p],a[j+1]=a[p+1],a[j+2]=a[p+2],a[j+3]=a[p+3]),xc=0);var Lc=qb-xc+1|0;l=(Ra+4|0)>>2;a[l]=Lc;var dd=Za(Lc<<4);a[Ra>>2]=dd;var Qc=Ba|0;a:do{if(0<(a[l]|0)){for(var id=0,Xc=xc,Pc=dd;;){e=((id<<4)+Pc|0)>>2;g=((Xc<<4)+a[Qc>>2]|0)>>2;a[e]=a[g];a[e+1]=a[g+1];a[e+2]=a[g+2];a[e+3]=a[g+3];var $c=id+1|0;if(($c|0)>=(a[l]|0)){break a}id=$c;Xc=Xc+1|0;Pc=a[Ra>>2]}}}while(0);E(a[Qc>>2]);E(Ba);a[a[Ea>>2]>>2]=Ra}}}h=O}function Mq(b,c){var d=h;if(0==(c|0)){var e=0}else{0==n[c]<<24>>24?e=0:(e=Xp(a[b+36>>2],c),0==(e|0)&&aa(0,5370388,(i=h,h=h+4|0,a[i>>2]=c,i)))}h=d;return e}function hg(c,d,g,e,l){var h=c|0;f[b>>3]=.5*(d+e);a[h>>2]=a[b>>2];a[h+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=.5*(g+l);a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function Nq(c,d){var g=c+8|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),g=g<d?-1:g>d&1,e=c+24|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),l=e<d?-1:e>d&1,e=c+40|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),e=e<d?-1:e>d&1,g=((e|0)!=(l|0)&0!=(l|0)&1)+((l|0)!=(g|0)&0!=(g|0)&1)+(0==(g|0)&1)|0,l=c+56|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);if(l<d){return e=-1!=(e|0)&0!=(e|0),g=(e&1)+g|0}l=(l>d&1|0)!=(e|0);e=l&0!=(e|0);return g=(e&1)+g|0}function Oq(c,d){var g=c|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),g=g<d?-1:g>d&1,e=c+16|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),l=e<d?-1:e>d&1,e=c+32|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),e=e<d?-1:e>d&1,g=((e|0)!=(l|0)&0!=(l|0)&1)+((l|0)!=(g|0)&0!=(g|0)&1)+(0==(g|0)&1)|0,l=c+48|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);if(l<d){return e=-1!=(e|0)&0!=(e|0),g=(e&1)+g|0}l=(l>d&1|0)!=(e|0);e=l&0!=(e|0);return g=(e&1)+g|0}function Pq(b){return(1==n[b+162|0]<<24>>24?1!=(a[b+180>>2]|0)?0:1!=(a[b+188>>2]|0)?0:0==(a[b+120>>2]|0):0)&1}function hh(c,d,g,e,l,p){var j=h;h=h+400|0;var k=j+100,r=j+200,q=j+300,m=p|0,m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),n=p+8|0,n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),x=p+16|0,x=(a[b>>2]=a[x>>2],a[b+4>>2]=a[x+4>>2],f[b>>3]),p=p+24|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);if(m>e){var v=((m-d)*(g-l)/(d-e)&-1|0)+g;if(!(v<n|v>p)){q=c|0;f[b>>3]=m;a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=v;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];h=j;return}}if(x<e){if(v=((x-d)*(g-l)/(d-e)&-1|0)+g,v<n|v>p){var t=x}else{q=c|0;f[b>>3]=x;a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=v;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];h=j;return}}else{t=m}if(n>l){if(t=((n-g)*(d-e)/(g-l)&-1|0)+d,t<m|t>x){v=n}else{q=c|0;f[b>>3]=t;a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=n;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];h=j;return}}if(p<l){if(t=((p-g)*(d-e)/(g-l)&-1|0)+d,t<m|t>x){v=p}else{q=c|0;f[b>>3]=t;a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=p;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];h=j;return}}d=ti(d,g,j|0);e=ti(e,l,k|0);r=ti(m,n,r|0);q=ti(x,p,q|0);aa(1,5378024,(i=h,h=h+16|0,a[i>>2]=d,a[i+4>>2]=e,a[i+8>>2]=r,a[i+12>>2]=q,i));ia(5338424,78,5380096,5340724);q=c|0;f[b>>3]=t;a[q>>2]=a[b>>2];a[q+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=v;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];h=j}function fl(c,d){var g,e,l,p,j=h;h=h+128|0;var k=j|0;e=j>>2;p=c>>2;a[e]=a[p];a[e+1]=a[p+1];a[e+2]=a[p+2];a[e+3]=a[p+3];e=(j+16|0)>>2;p=(c+16|0)>>2;a[e]=a[p];a[e+1]=a[p+1];a[e+2]=a[p+2];a[e+3]=a[p+3];e=(j+32|0)>>2;p=(c+32|0)>>2;a[e]=a[p];a[e+1]=a[p+1];a[e+2]=a[p+2];a[e+3]=a[p+3];e=(j+48|0)>>2;p=(c+48|0)>>2;a[e]=a[p];a[e+1]=a[p+1];a[e+2]=a[p+2];a[e+3]=a[p+3];p=(d|0)>>2;g=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]);l=(d+8|0)>>2;e=(d+24|0)>>2;g=ui(c,0,1,g,(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]),(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]));if(0<=g&2>g){zc(j+64,k,g,c,0);var i=g}else{i=2}g=(d+16|0)>>2;var q=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]),q=ui(c,0,1<i?1:i,q,(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]),(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]));0<=q&q<i&&(zc(j+80,k,q,c,0),i=q);l=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]);l=vi(c,0,1<i?1:i,l,(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]),(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]));0<=l&l<i?zc(j+96,k,l,c,0):l=i;e=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);p=vi(c,0,1<l?1:l,e,(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]),(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]));if(!(0<=p&p<l)){return k=2>l,h=j,k&1}zc(j+112,k,p,c,0);k=2>p;h=j;return k&1}function ui(c,d,g,e,l,p){var j=0,k=h;h=h+144|0;var i=k+64,q=k+128,m=Oq(c,e);if(0==(m|0)){return h=k,-1}1==(m|0)&&(j=182);if(182==j&&(j=c+48|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),((0>j?j-.5:j+.5)&-1|0)==((0>e?e-.5:e+.5)&-1|0))){return e=c+56|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),h=k,e<l|e>p?-1:g}j=k|0;i|=0;zc(q,c,.5,j,i);c=.5*(d+g);d=ui(j,d,c,e,l,p);if(0<=d){return h=k,d}g=ui(i,c,g,e,l,p);h=k;return g}function vi(c,d,g,e,l,p){var j=0,k=h;h=h+144|0;var i=k+64,q=k+128,m=Nq(c,e);if(0==(m|0)){return h=k,-1}1==(m|0)&&(j=197);if(197==j&&(j=c+56|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),((0>j?j-.5:j+.5)&-1|0)==((0>e?e-.5:e+.5)&-1|0))){return e=c+48|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),h=k,e<l|e>p?-1:g}j=k|0;i|=0;zc(q,c,.5,j,i);c=.5*(d+g);d=vi(j,d,c,e,l,p);if(0<=d){return h=k,d}g=vi(i,c,g,e,l,p);h=k;return g}function ti(c,d,g){var e=h;Pa(g,5372944,(i=h,h=h+16|0,f[b>>3]=c,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=d,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));h=e;return g}function Qq(b){var c,d=0;if(2<=((C[b+246>>1]<<16>>16)-(C[b+244>>1]<<16>>16)|0)){c=(b+220|0)>>2;var e=a[c];do{if(0==(a[e+88>>2]|0)){var f=1,h=e,d=224}else{for(var j=1,k=2,i=e;;){var q=a[i+(44*j&-1)>>2];a:do{if(0<(q|0)){for(var m=0,n=i,x=q;;){var v=a[n+(44*j&-1)+4>>2],t=a[v+(m<<2)>>2];do{if(0==Pq(t)<<24>>24){var y=n,z=x}else{y=t+176|0;for(z=m;;){var B=z+1|0;if((B|0)>=(x|0)){break}var F;F=a[a[y>>2]>>2];var A=a[v+(B<<2)>>2],S=a[a[A+176>>2]>>2];F=0==Pq(A)<<24>>24?0:(a[F+16>>2]|0)!=(a[S+16>>2]|0)?0:(0==gl(F,S)<<24>>24?0:0==(ig(F+28|0,S+28|0)|0))&1;if(0==F<<24>>24){break}else{z=B}}1<(B-m|0)?(hl(b,j,m,z,1),y=z=a[c],z=a[z+(44*j&-1)>>2]):(y=n,z=x)}}while(0);m=m+1|0;if((m|0)<(z|0)){n=y,x=z}else{var E=y;break a}}}else{E=i}}while(0);i=k+1|0;if(0==(a[E+(44*i&-1)>>2]|0)){break}else{j=k,k=i,i=E}}0<(k|0)&&(f=k,h=E,d=224)}}while(0);a:do{if(224==d){for(;;){d=a[h+(44*f&-1)>>2];b:do{if(0<(d|0)){e=0;j=h;for(k=d;;){B=a[j+(44*f&-1)+4>>2];E=a[B+(e<<2)>>2];do{if(0==Rq(E)<<24>>24){i=j,q=k}else{i=E+184|0;for(q=e;;){var G=q+1|0;if((G|0)>=(k|0)){break}m=a[a[i>>2]>>2];n=a[B+(G<<2)>>2];x=a[a[n+184>>2]>>2];m=0==Rq(n)<<24>>24?0:(a[m+12>>2]|0)!=(a[x+12>>2]|0)?0:(0==gl(m,x)<<24>>24?0:0==(ig(m+68|0,x+68|0)|0))&1;if(0==m<<24>>24){break}else{q=G}}1<(G-e|0)?(hl(b,f,e,q,0),i=q=a[c],q=a[q+(44*f&-1)>>2]):(i=j,q=k)}}while(0);e=e+1|0;if((e|0)<(q|0)){j=i,k=q}else{var I=i;break b}}}else{I=h}}while(0);f=f-1|0;if(0<(f|0)){h=I,d=224}else{break a}}}}while(0);c=b+208|0;if(1<=(a[c>>2]|0)){b=b+212|0;for(G=1;!(il(a[a[b>>2]+(G<<2)>>2]),G=G+1|0,(G|0)>(a[c>>2]|0));){}}}}function Rq(b){return(1==n[b+162|0]<<24>>24?1!=(a[b+188>>2]|0)?0:1!=(a[b+180>>2]|0)?0:0==(a[b+120>>2]|0):0)&1}function Sq(b,c){var d=(a[c+236>>2]<<2)+b|0,e=a[d>>2];if(0==(e|0)||(a[e+240>>2]|0)>(a[c+240>>2]|0)){a[d>>2]=c}}function gl(b,c){a:do{if(0==n[b+124|0]<<24>>24){var d=b}else{for(var e=b;;){if(e=a[e+128>>2],0==n[e+124|0]<<24>>24){d=e;break a}}}}while(0);a:do{if(0==n[c+124|0]<<24>>24){var f=c}else{for(e=c;;){if(e=a[e+128>>2],0==n[e+124|0]<<24>>24){f=e;break a}}}}while(0);return 0!=n[d+161|0]<<24>>24||0!=n[f+161|0]<<24>>24?0:d=0<(Math.a(a[a[d+16>>2]+236>>2]-a[a[d+12>>2]+236>>2]|0,a[a[f+16>>2]+236>>2]-a[a[f+12>>2]+236>>2]|0)|0)&1}function hl(b,c,d,e,f){var h,j=0;h=(b+220|0)>>2;var k=a[h],i=a[k+(44*c&-1)+4>>2],q=a[i+(d<<2)>>2],d=d+1|0;a:do{if((d|0)>(e|0)){var m=k}else{for(var n=1==(f|0),x=b,v=q+184|0,t=q,y=q+176|0,z=d,B=i;;){B=a[B+(z<<2)>>2];b:do{if(n){var F=B+184|0,A=a[a[F>>2]>>2];if(0!=(A|0)){for(var C=B+176|0;;){for(var E=a[v>>2],G=A+12|0,I=0;;){var Z=a[E+(I<<2)>>2];if(0==(Z|0)){j=283;break}if((a[Z+12>>2]|0)==(a[G>>2]|0)){var H=Z;break}else{I=I+1|0}}283==j&&(j=0,H=pd(t,a[G>>2],A));E=a[a[C>>2]>>2];c:do{if(0!=(E|0)){G=H;for(I=E;;){if(Be(I,G),Yd(I),I=a[a[C>>2]>>2],0==(I|0)){break c}}}}while(0);Yd(A);A=a[a[F>>2]>>2];if(0==(A|0)){break b}}}}else{if(F=B+176|0,A=a[a[F>>2]>>2],0!=(A|0)){for(C=B+184|0;;){E=a[y>>2];G=A+16|0;for(I=0;;){Z=a[E+(I<<2)>>2];if(0==(Z|0)){j=291;break}if((a[Z+16>>2]|0)==(a[G>>2]|0)){var K=Z;break}else{I=I+1|0}}291==j&&(j=0,K=pd(a[G>>2],t,A));E=a[a[C>>2]>>2];c:do{if(0!=(E|0)){G=K;for(I=E;;){if(Be(I,G),Yd(I),I=a[a[C>>2]>>2],0==(I|0)){break c}}}}while(0);Yd(A);A=a[a[F>>2]>>2];if(0==(A|0)){break b}}}}}while(0);(a[B+180>>2]|0)!=(-a[B+188>>2]|0)&&ia(5373088,113,5379576,5352244);al(x,B);z=z+1|0;B=a[h];if((z|0)>(e|0)){m=B;break a}B=a[B+(44*c&-1)+4>>2]}}}while(0);b=e+1|0;e=m+(44*c&-1)|0;if((b|0)<(a[e>>2]|0)){for(;;){if(m=a[m+(44*c&-1)+4>>2],e=a[m+(b<<2)>>2],a[m+(d<<2)>>2]=e,a[e+240>>2]=d,d=d+1|0,b=b+1|0,m=a[h],e=m+(44*c&-1)|0,(b|0)>=(a[e>>2]|0)){M=d;L=e;break}}a[L>>2]=M}else{var M=d,L;a[e>>2]=M}h=a[h];c=a[(h+(44*c&-1)+4|0)>>2];M=(M<<2)+c|0;a[M>>2]=0}function wi(b,c){var d=0;a[1345483]=b;var e=n[5382120]+1&255;n[5382120]=0==e<<24>>24?1:e;a[b+228>>2]=0;a[b+240>>2]=0;var e=b+20|0,f=ha(a[e>>2]);if(0!=(f|0)){for(var h=0<(c|0);;){var j=f;if(h){var d=f+24|0,k=a[d+192>>2];if(0==(k|0)){d=318}else{var i=a[a[k+276>>2]+(a[d+212>>2]<<2)>>2],d=319}}else{d=318}318==d&&(d=0,(j|0)==(ec(j)|0)&&(i=j,d=319));if(319==d&&n[i+163|0]<<24>>24!=n[5382120]<<24>>24){a[a[1345483]+216>>2]=0;a[1345386]=0;jg(i);var k=a[1345483],q=k+228|0,j=a[q>>2],d=j+1|0;a[q>>2]=d;k=a[k+224>>2];d=0==(k|0)?Za(d<<2):Oa(k,d<<2);k=a[1345483];a[k+224>>2]=d;a[d+(j<<2)>>2]=a[k+216>>2]}f=sa(a[e>>2],f);if(0==(f|0)){break}}}}function jg(b){var c=a[1345483],d=c+240|0;a[d>>2]=a[d>>2]+1|0;n[b+163|0]=n[5382120];var d=a[1345386],e=b+172|0;0==(d|0)?(a[e>>2]=0,a[c+216>>2]=b):(a[e>>2]=d,a[d+168>>2]=b);a[1345386]=b;c=b+168|0;a[c>>2]=0;var f=a[(b+184|0)>>2],e=a[(b+176|0)>>2],d=a[(b+192|0)>>2],c=a[(b+200|0)>>2];a:do{if(0!=(f|0)){var h=a[f>>2];if(0!=(h|0)){for(var j=0;;){var k=a[h+12>>2],h=(k|0)==(b|0)?a[h+16>>2]:k;n[h+163|0]<<24>>24!=n[5382120]<<24>>24&&(h|0)==(ec(h)|0)&&jg(h);j=j+1|0;h=a[f+(j<<2)>>2];if(0==(h|0)){break a}}}}}while(0);a:do{if(0!=(e|0)&&(j=a[e>>2],0!=(j|0))){for(f=0;;){if(h=a[j+12>>2],j=(h|0)==(b|0)?a[j+16>>2]:h,n[j+163|0]<<24>>24!=n[5382120]<<24>>24&&(j|0)==(ec(j)|0)&&jg(j),f=f+1|0,j=a[e+(f<<2)>>2],0==(j|0)){break a}}}}while(0);a:do{if(0!=(d|0)&&(f=a[d>>2],0!=(f|0))){for(e=0;;){if(j=a[f+12>>2],f=(j|0)==(b|0)?a[f+16>>2]:j,n[f+163|0]<<24>>24!=n[5382120]<<24>>24&&(f|0)==(ec(f)|0)&&jg(f),e=e+1|0,f=a[d+(e<<2)>>2],0==(f|0)){break a}}}}while(0);if(0!=(c|0)&&(e=a[c>>2],0!=(e|0))){for(d=0;!(f=a[e+12>>2],e=(f|0)==(b|0)?a[e+16>>2]:f,n[e+163|0]<<24>>24!=n[5382120]<<24>>24&&(e|0)==(ec(e)|0)&&jg(e),d=d+1|0,e=a[c+(d<<2)>>2],0==(e|0));){}}}function il(b){var c,d,e,f,p=0,j=h,k=b+244|0;d=C[k>>1];f=(b+246|0)>>1;a:do{if(d<<16>>16>C[f]<<16>>16){e=b+276|0,e>>=2}else{for(var r=b+276|0,q=d<<16>>16;;){if(a[a[r>>2]+(q<<2)>>2]=0,q=q+1|0,(q|0)>(C[f]<<16>>16|0)){e=r;e>>=2;break a}}}}while(0);Tq(b);d=b+20|0;r=ha(a[d>>2]);a:do{if(0!=(r|0)){for(var q=b+28|0,m=r;;){Sq(a[e],m);var w=zb(b,m);b:do{if(0!=(w|0)){for(var x=w;;){for(c=x;;){var v=a[c+180>>2];if(0==(v|0)){break}else{c=v}}c=c+12|0;var v=a[c>>2],t=x+12|0;c:do{if((a[v+236>>2]|0)<(a[a[t>>2]+236>>2]|0)){for(var y=c,z=v;;){if(Sq(a[e],z),y=a[a[a[y>>2]+184>>2]>>2]+12|0,z=a[y>>2],(a[z+236>>2]|0)>=(a[a[t>>2]+236>>2]|0)){break c}}}}while(0);x=Db(a[q>>2],x);if(0==(x|0)){break b}}}}while(0);m=sa(a[d>>2],m);if(0==(m|0)){break a}}}}while(0);r=b+32|0;d=(b+220|0)>>2;q=b+12|0;for(k=C[k>>1]<<16>>16;(k|0)<=(C[f]<<16>>16|0);){m=a[a[e]+(k<<2)>>2];w=(a[m+240>>2]<<2)+a[a[a[r>>2]+220>>2]+(44*k&-1)+4>>2]|0;if((a[w>>2]|0)!=(m|0)){p=383;break}a[a[d]+(44*k&-1)+4>>2]=w;m=0;w=-1;a:for(;;){x=a[d];if((m|0)>=(a[x+(44*k&-1)>>2]|0)){break}x=a[a[x+(44*k&-1)+4>>2]+(m<<2)>>2];if(0==(x|0)){break}b:do{if(0==n[x+162|0]<<24>>24){if(0==(fd(b,x|0)|0)){break a}else{c=m}}else{v=a[a[x+176>>2]>>2];for(c=v>>2;;){if(0==(v|0)){c=w;break b}v=a[c+32];if(0==(v|0)){break}else{c=v>>2}}c=0==(fd(b,a[c+4]|0)|0)?w:0==(fd(b,a[c+3]|0)|0)?w:m}}while(0);m=m+1|0;w=c}-1==(w|0)&&aa(0,5355328,(i=h,h=h+8|0,a[i>>2]=a[q>>2],a[i+4>>2]=k,i));a[a[d]+(44*k&-1)>>2]=w+1|0;k=k+1|0}383==p&&P();f=b+208|0;if(1<=(a[f>>2]|0)){b=b+212|0;for(p=1;!(il(a[a[b>>2]+(p<<2)>>2]),p=p+1|0,(p|0)>(a[f>>2]|0));){}}h=j}function ig(c,d){var g=h,e=c,c=h;h=h+40|0;for(var e=e>>2,l=c>>2,p=e+10;e<p;e++,l++){a[l]=a[e]}e=d;d=h;h=h+40|0;e>>=2;l=d>>2;for(p=e+10;e<p;e++,l++){a[l]=a[e]}e=n[c+28|0];if(0==n[d+28|0]<<24>>24){return h=g,0!=e<<24>>24&1}if(0==e<<24>>24){return h=g,-1}e=c|0;l=d|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])&-1;if(0!=(e|0)){return h=g,e}e=c+8|0;l=d+8|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])&-1;h=g;return e}function Uq(b){var c;c=(b+20|0)>>2;var d=ha(a[c]);a:do{if(0!=(d|0)){for(var e=d;;){var f=e,h=f>>2;un(f);Hj(f,a[a[h+5]+152>>2]&1);a[h+45]=0;a[h+44]=da(20);a[h+47]=0;a[h+46]=da(20);a[h+51]=0;a[h+50]=da(12);a[h+49]=0;a[h+48]=da(12);a[h+53]=0;a[h+52]=da(12);a[h+55]=1;e=sa(a[c],e);if(0==(e|0)){break a}}}}while(0);e=ha(a[c]);if(0!=(e|0)){for(d=b+28|0;;){f=zb(b,e);a:do{if(0!=(f|0)){for(h=f;;){var j=h,k=Wb,i=Wb;vn(j);var q=j|0,m=lc(q,a[1345491],1,0),i=(j+164|0)>>2;hb[i]=m;var k=a[1345360],w=$b(a[j+16>>2]|0,k,5338228),x=$b(a[j+12>>2]|0,k,5338228),k=(j+162|0)>>1;C[k]=1;C[j+176>>1]=1;0!=n[w]<<24>>24&(w|0)==(x|0)&&(C[k]=1e3,hb[i]=100*m);0!=(tq(j)|0)&&(C[k]=0,hb[i]=0);n[j+160|0]=ve(q,a[1345495],0)&255;C[j+178>>1]=ve(q,a[1345499],1)&65535;h=Db(a[d>>2],h);if(0==(h|0)){break a}}}}while(0);e=sa(a[c],e);if(0==(e|0)){break}}}}function jl(b){var c=a[b+216>>2],d;if(0!=(c|0)){for(d=c>>2;;){var e=a[d+42],f=c,h=a[f+180>>2];a:do{if(0<(h|0)){for(var j=f+176|0,k=h;;){var k=k-1|0,i=a[a[j>>2]+(k<<2)>>2];Yd(i);E(i|0);if(0>=(k|0)){break a}}}}while(0);h=a[f+188>>2];if(0<(h|0)){for(f=f+184|0;!(h=h-1|0,j=a[a[f>>2]+(h<<2)>>2],Yd(j),E(j|0),0>=(h|0));){}}1==n[c+162|0]<<24>>24&&(f=a[d+46],0!=(f|0)&&E(f),d=a[d+44],0!=(d|0)&&E(d),E(c|0));if(0==(e|0)){break}else{c=e,d=c>>2}}}c=b+20|0;d=ha(a[c>>2]);if(0!=(d|0)){for(e=b+28|0;;){f=d;h=zb(b,d);a:do{if(0!=(h|0)){for(j=h;;){var k=j,i=Wb,i=(k+24|0)>>2,q=a[i];if(0!=(q|0)){var m=a[q>>2];b:do{if(0<(a[q+4>>2]|0)){for(var w=0,x=m;;){E(a[x+(48*w&-1)>>2]);var w=w+1|0,v=a[i],x=a[v>>2];if((w|0)>=(a[v+4>>2]|0)){var t=x;break b}}}else{t=m}}while(0);E(t);E(a[i])}a[i]=0;tf(a[k+108>>2]);tf(a[k+120>>2]);tf(a[k+112>>2]);tf(a[k+116>>2]);k=(k+24|0)>>2;for(i=k+40;k<i;k++){a[k]=0}j=Db(a[e>>2],j);if(0==(j|0)){break a}}}}while(0);Vq(f);d=sa(a[c>>2],d);if(0==(d|0)){break}}}Wq(b)}function Vq(b){var c=b>>2,d=b+24|0,e=a[c+44];0!=(e|0)&&E(e);e=a[c+46];0!=(e|0)&&E(e);e=a[c+48];0!=(e|0)&&E(e);e=a[c+50];0!=(e|0)&&E(e);e=a[c+52];0!=(e|0)&&E(e);tf(a[c+30]);c=a[d>>2];if(0!=(c|0)){J[a[a[c+4>>2]+4>>2]](b)}b=d>>2;for(d=b+70;b<d;b++){a[b]=0}}function Wq(b){var c,d=b+44|0;c=b+208|0;var e=b+212|0,f=a[e>>2];a:do{if(1>(a[c>>2]|0)){var h=f}else{for(var j=1,k=f;;){if(k=a[k+(j<<2)>>2],n[k+250|0]=0,jl(k),j=j+1|0,k=a[e>>2],(j|0)>(a[c>>2]|0)){h=k;break a}}}}while(0);0!=(h|0)&&E(h);c=a[b+276>>2];0!=(c|0)&&E(c);c=a[b+224>>2];0!=(c|0)&&E(c);c=(b+220|0)>>2;e=a[c];do{if(0!=(e|0)){f=b+244|0;j=C[f>>1];h=b+246|0;if(j<<16>>16>C[h>>1]<<16>>16){f=j,h=e}else{j=j<<16>>16;for(k=e;;){E(a[k+(44*j&-1)+12>>2]);j=j+1|0;if((j|0)>(C[h>>1]<<16>>16|0)){break}k=a[c]}f=C[f>>1];h=a[c]}-1==f<<16>>16?E(h-44|0):E(h)}}while(0);if((a[b+32>>2]|0)!=(b|0)){b=d>>2;for(d=b+61;b<d;b++){a[b]=0}}}function xi(b,c,d,e){var f=b>>2;if(0==(c|0)){var c=a[f+4],h=a[f+3],b=(c|0)!=(h|0)?(a[c+236>>2]|0)==(a[h+236>>2]|0)?2:1:0!=n[b+56|0]<<24>>24?4:0==n[b+96|0]<<24>>24?8:4}else{b=c}a[f+43]=b|e|(0==(d|0)?2==(b|0)?(a[a[f+4]+240>>2]|0)<(a[a[f+3]+240>>2]|0)?16:32:1==(b|0)?(a[a[f+4]+236>>2]|0)<(a[a[f+3]+236>>2]|0)?16:32:16:d)}function kl(c,d){var g,e,l,p,j,k,r,q,m,w,x,v=0,t=h;h=h+388|0;var y=t+184,z=t+368,B=C[c+164>>1]&14;if(0!=(B|0)){dl(c);var F=h,A=a[1311604];a[1311604]=A+1|0;if(0>=(A|0)){var S=Za(4800);a[1311892]=S;0==(S|0)&&(aa(1,5336456,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),P());a[1312721]=300;a[1312709]=0;a[1312710]=0}h=F;var G=da(92),H=a[c+256>>2];a[z+8>>2]=(H|0)/4&-1;var I=z+12|0;a[I>>2]=H;var Z=da(512);x=(z+4|0)>>2;a[x]=0;w=(z|0)>>2;a[w]=0;var T=c+244|0,K=C[T>>1],M=K<<16>>16;m=(c+246|0)>>1;var L=C[m];if(K<<16>>16>L<<16>>16){var N=Z,Q=0,U=11520,R=M}else{for(var Y=c+220|0,$=Z,ca=0,fa=0,ea=M,wa=a[Y>>2],Fb=L;;){q=(wa+(44*ea&-1)|0)>>2;var V=a[q],W=V+fa|0,X=wa+(44*ea&-1)+4|0,ba=a[a[X>>2]>>2];if(0==(ba|0)){var ma=V}else{var ib=a[w]|0,qa=ba+32|0,na=ba+104|0,O=(a[b>>2]=a[qa>>2],a[b+4>>2]=a[qa+4>>2],f[b>>3])-(a[b>>2]=a[na>>2],a[b+4>>2]=a[na+4>>2],f[b>>3]);a[w]=(ib<O?ib:O)&-1;ma=a[q]}if(0!=(ma|0)){var ga=a[a[X>>2]+(ma-1<<2)>>2];if(0!=(ga|0)){var Tb=a[x]|0,xa=ga+32|0,ua=ga+112|0,Da=(a[b>>2]=a[xa>>2],a[b+4>>2]=a[xa+4>>2],f[b>>3])+(a[b>>2]=a[ua>>2],a[b+4>>2]=a[ua+4>>2],f[b>>3]);a[x]=(Tb>Da?Tb:Da)&-1}}a[w]=a[w]-16|0;a[x]=a[x]+16|0;if(0<(a[q]|0)){for(var Ja=$,Ab=ca,ra=0,ta=wa;;){var ya=a[a[ta+(44*ea&-1)+4>>2]+(ra<<2)>>2],ja=a[ya+128>>2];if(0!=(ja|0)){r=(ja+108|0)>>2;var la=a[r];if(0==(la|0)){ia(5346364,318,5380156,5370892);var va=a[r]}else{va=la}k=(va+56|0)>>2;j=(ya+32|0)>>2;a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];n[a[r]+81|0]=1}var oa=ya+162|0;if(0==n[oa]<<24>>24){v=545}else{if(0==J[a[1311601]](ya)<<24>>24){var ka=Ab,Ea=Ja}else{v=545}}a:do{if(545==v){var v=0,Ka=ya+184|0,Na=a[a[Ka>>2]>>2];b:do{if(0==(Na|0)){var Ba=Ja,Wa=Ab}else{for(var Ha=Ja,Qa=Ab,Ra=0,bb=Na;;){var Xa=n[bb+124|0];if(4==Xa<<24>>24|6==Xa<<24>>24){var Sa=Qa,Pa=Ha}else{xi(bb,1,16,64);var Va=Qa+1|0;a[Ha+(Qa<<2)>>2]=bb;if(0!=(Va&127|0)){Sa=Va,Pa=Ha}else{var Ta=0==(Ha|0)?Za((Qa<<2)+516|0):Oa(Ha,(Qa<<2)+516|0),Sa=Va,Pa=Ta}}var Aa=Ra+1|0,fb=a[a[Ka>>2]+(Aa<<2)>>2];if(0==(fb|0)){Ba=Pa;Wa=Sa;break b}else{Ha=Pa,Qa=Sa,Ra=Aa,bb=fb}}}}while(0);var Ca=ya+192|0,Ya=a[Ca>>2];b:do{if(0==(Ya|0)){var $a=Wa,La=Ba}else{var pa=a[Ya>>2];if(0==(pa|0)){$a=Wa,La=Ba}else{for(var Ga=Ba,Fa=Wa,hb=0,nb=pa;;){xi(nb,2,0,128);var jb=Fa+1|0;a[Ga+(Fa<<2)>>2]=nb;var cb=0==(jb&127|0)?0==(Ga|0)?Za((Fa<<2)+516|0):Oa(Ga,(Fa<<2)+516|0):Ga,eb=hb+1|0,kb=a[a[Ca>>2]+(eb<<2)>>2];if(0==(kb|0)){$a=jb;La=cb;break b}else{Ga=cb,Fa=jb,hb=eb,nb=kb}}}}}while(0);var Kb=ya+208|0,Ma=a[Kb>>2];if(0==(Ma|0)){ka=$a,Ea=La}else{if(0==n[oa]<<24>>24){p=(ya+112|0)>>2;var mb=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3]),lb=ya+244|0;f[b>>3]=a[lb>>2]|0;a[p]=a[b>>2];a[p+1]=a[b+4>>2];a[lb>>2]=mb&-1}var rb=a[Ma>>2];if(0==(rb|0)){ka=$a,Ea=La}else{for(var ab=La,db=$a,ob=0,pb=rb;;){xi(pb,0,0,128);var ub=db+1|0;a[ab+(db<<2)>>2]=pb;var gb=0==(ub&127|0)?0==(ab|0)?Za((db<<2)+516|0):Oa(ab,(db<<2)+516|0):ab,sb=ob+1|0,Ia=a[a[Kb>>2]+(sb<<2)>>2];if(0==(Ia|0)){ka=ub;Ea=gb;break a}else{ab=gb,db=ub,ob=sb,pb=Ia}}}}}}while(0);var vb=ra+1|0,Ua=a[Y>>2];if((vb|0)<(a[Ua+(44*ea&-1)>>2]|0)){Ja=Ea,Ab=ka,ra=vb,ta=Ua}else{break}}var tb=Ea,wb=ka,qb=Ua,Bb=C[m]}else{tb=$,wb=ca,qb=wa,Bb=Fb}var Cb=ea+1|0;if((Cb|0)>(Bb<<16>>16|0)){break}else{$=tb,ca=wb,fa=W,ea=Cb,wa=qb,Fb=Bb}}N=tb;Q=wb;U=(W<<5)+11520|0;R=Cb}var xb=N;af(xb,Q,292);var za=G+84|0;a[za>>2]=da(U);var Nb=z+16|0;a[Nb>>2]=da(R<<5);a:do{if(2==(B|0)){var Jb=a[c+216>>2];if(0!=(Jb|0)){for(var Eb=Jb;;){1==n[Eb+162|0]<<24>>24&&0!=(a[Eb+120>>2]|0)&&Xq(Eb);var Hb=a[Eb+168>>2];if(0==(Hb|0)){break a}else{Eb=Hb}}}}}while(0);a:do{if(0<(Q|0)){var Ib=y|0,Mb=y+16|0,Pb=y+12|0,Sb=y+28|0,Lb=y+68|0,Zb=y+124|0,Xb=y+128|0;l=(c+220|0)>>2;for(var Ub=N,hc=c,bc=t|0,fc=t+16|0,ac=t+12|0,gc=t+28|0,ec=t+68|0,ic=t+124|0,jc=t+128|0,cc=0;;){var pc=a[N+(cc<<2)>>2],Qb=ih(pc),$b=0==n[pc+56|0]<<24>>24?0==n[pc+96|0]<<24>>24?Qb:pc:pc;e=$b>>2;if(0==(a[e+43]&32|0)){var dc=$b}else{for(var Vb=($b|0)>>2,Yb=bc>>2,Jc=Vb+46;Vb<Jc;Vb++,Yb++){a[Yb]=a[Vb]}a[fc>>2]=a[e+3];a[ac>>2]=a[e+4];Vb=($b+68|0)>>2;Yb=gc>>2;for(Jc=Vb+10;Vb<Jc;Vb++,Yb++){a[Yb]=a[Vb]}Vb=($b+28|0)>>2;Yb=ec>>2;for(Jc=Vb+10;Vb<Jc;Vb++,Yb++){a[Yb]=a[Vb]}n[ic]=1;a[jc>>2]=$b;dc=t}for(var oc=dc+68|0,lc=pc+108|0,tc=pc+125|0,Bc=dc+28|0,vc=pc+172|0,kc=cc,uc=1;;){var wc=kc+1|0,yc=(wc|0)<(Q|0);if(!yc){break}var Hc=(wc<<2)+N|0,Kc=a[Hc>>2];if((Qb|0)!=(ih(Kc)|0)){break}if(0==n[tc]<<24>>24){var rc=0==n[Kc+56|0]<<24>>24?0==n[Kc+96|0]<<24>>24?Qb:Kc:Kc;g=rc>>2;if(0==(a[g+43]&32|0)){var zc=rc}else{Vb=(rc|0)>>2;Yb=Ib>>2;for(Jc=Vb+46;Vb<Jc;Vb++,Yb++){a[Yb]=a[Vb]}a[Mb>>2]=a[g+3];a[Pb>>2]=a[g+4];Vb=(rc+68|0)>>2;Yb=Sb>>2;for(Jc=Vb+10;Vb<Jc;Vb++,Yb++){a[Yb]=a[Vb]}Vb=(rc+28|0)>>2;Yb=Lb>>2;for(Jc=Vb+10;Vb<Jc;Vb++,Yb++){a[Yb]=a[Vb]}n[Zb]=1;a[Xb>>2]=rc;zc=y}if(0!=(ig(Bc,zc+28|0)|0)){break}if(0!=(ig(oc,zc+68|0)|0)){break}if(2==(a[vc>>2]&15|0)&&(a[lc>>2]|0)!=(a[Kc+108>>2]|0)){break}if(0!=(a[a[Hc>>2]+172>>2]&64|0)){break}}kc=wc;uc=uc+1|0}var Cc=a[pc+16>>2],Fc=a[pc+12>>2],Dc=a[Cc+236>>2];b:do{if((Cc|0)==(Fc|0)){if((Dc|0)==(C[m]<<16>>16|0)){if(0<(Dc|0)){var Gc=a[a[a[l]+(44*(Dc-1)&-1)+4>>2]>>2]+40|0,Nc=Cc+40|0,Ec=(a[b>>2]=a[Gc>>2],a[b+4>>2]=a[Gc+4>>2],f[b>>3])-(a[b>>2]=a[Nc>>2],a[b+4>>2]=a[Nc+4>>2],f[b>>3])&-1}else{var Yc=Cc+96|0,Ec=(a[b>>2]=a[Yc>>2],a[b+4>>2]=a[Yc+4>>2],f[b>>3])&-1}}else{if((Dc|0)==(C[T>>1]<<16>>16|0)){var xc=Cc+40|0,Mc=a[a[a[l]+(44*(Dc+1)&-1)+4>>2]>>2]+40|0,Ec=(a[b>>2]=a[xc>>2],a[b+4>>2]=a[xc+4>>2],f[b>>3])-(a[b>>2]=a[Mc>>2],a[b+4>>2]=a[Mc+4>>2],f[b>>3])&-1}else{var Wc=a[l],Qc=a[a[Wc+(44*(Dc-1)&-1)+4>>2]>>2]+40|0,Pc=(a[b>>2]=a[Qc>>2],a[b+4>>2]=a[Qc+4>>2],f[b>>3]),Rc=Cc+40|0,kd=(a[b>>2]=a[Rc>>2],a[b+4>>2]=a[Rc+4>>2],f[b>>3]),Kd=Pc-kd&-1,Sc=a[a[Wc+(44*(Dc+1)&-1)+4>>2]>>2]+40|0,bd=kd-(a[b>>2]=a[Sc>>2],a[b+4>>2]=a[Sc+4>>2],f[b>>3])&-1,Ec=(Kd|0)<(bd|0)?Kd:bd}}Qo(Ub,cc,uc,a[I>>2]|0,(Ec|0)/2&-1|0);if(0<(uc|0)){for(var Vc=0;;){var cd=a[a[N+(Vc+cc<<2)>>2]+108>>2];0!=(cd|0)&&Mg(hc,cd);var Zc=Vc+1|0;if((Zc|0)==(uc|0)){break b}else{Vc=Zc}}}}else{(Dc|0)==(a[Fc+236>>2]|0)?Yq(z,G,N,cc,uc,B):Zq(z,G,N,cc,uc,B)}}while(0);if(yc){cc=wc}else{break a}}}}while(0);var nc=a[c+216>>2];a:do{if(0!=(nc|0)){for(var Oc=c,Lc=nc;;){if(1==n[Lc+162|0]<<24>>24){var dd=Lc+120|0;0!=(a[dd>>2]|0)&&(Xq(Lc),Mg(Oc,a[dd>>2]))}var Sd=a[Lc+168>>2];if(0==(Sd|0)){break a}else{Lc=Sd}}}}while(0);if(0!=(d|0)){var id=c+20|0,Xc=ha(a[id>>2]);if(0!=(Xc|0)){for(var ud=c+28|0,$c=Xc;;){var pd=zb(c,$c);a:do{if(0!=(pd|0)){for(var gd=pd;;){if(0!=J[a[1311600]](gd)<<24>>24){var ad=a[gd+24>>2];if(0!=(ad|0)){var td=ad,Tc=Wb,fd=a[td+4>>2],Ed=Za(48*fd&-1),Tc=(td|0)>>2;if(0<(fd|0)){for(var Nd=Ed,Bd=a[Tc]+(48*(fd-1)&-1)|0,Uc=0;;){var wd=Bd,od=Nd,xd=Wb,rd=Wb,yd=Wb,vd=Wb,Cd=Wb,md=Wb,sd=a[wd+4>>2],Jd=Za(sd<<4);b:do{if(0<(sd|0)){for(var ed=Jd,zd=(sd-1<<4)+a[wd>>2]|0,ke=0;;){md=ed>>2;Cd=zd>>2;a[md]=a[Cd];a[md+1]=a[Cd+1];a[md+2]=a[Cd+2];a[md+3]=a[Cd+3];var Fd=ke+1|0;if((Fd|0)==(sd|0)){break b}else{ed=ed+16|0,zd=zd-16|0,ke=Fd}}}}while(0);a[od>>2]=Jd;a[od+4>>2]=sd;a[od+8>>2]=a[wd+12>>2];a[od+12>>2]=a[wd+8>>2];vd=(od+16|0)>>2;yd=(wd+32|0)>>2;a[vd]=a[yd];a[vd+1]=a[yd+1];a[vd+2]=a[yd+2];a[vd+3]=a[yd+3];rd=(od+32|0)>>2;xd=(wd+16|0)>>2;a[rd]=a[xd];a[rd+1]=a[xd+1];a[rd+2]=a[xd+2];a[rd+3]=a[xd+3];var jd=Uc+1|0;if((jd|0)==(fd|0)){break}else{Nd=Nd+48|0,Bd=Bd-48|0,Uc=jd}}for(var Ld=0,Ad=a[Tc];;){E(a[Ad+(48*Ld&-1)>>2]);var Gd=Ld+1|0,Dd=a[Tc];if((Gd|0)==(fd|0)){Hd=Dd;break}else{Ld=Gd,Ad=Dd}}Id=Hd}else{var Hd=a[Tc],Id=Hd}E(Id);a[Tc]=Ed}}var Od=Db(a[ud>>2],gd);if(0==(Od|0)){break a}else{gd=Od}}}}while(0);var Pd=sa(a[id>>2],$c);if(0==(Pd|0)){break}else{$c=Pd}}}}a:do{if(0!=(a[1345508]|0)|0!=(a[1345492]|0)){var Md=c,nd=c+20|0,Qd=ha(a[nd>>2]);if(0!=(Qd|0)){for(var Wd=c,Vd=c+28|0,de=c+24|0,Td=Qd;;){b:do{if(0!=(a[1345508]|0)){var Xd=cf(Md,Td);if(0!=(Xd|0)){for(var Yd=Xd;;){var ce=Yd+112|0;0!=(a[ce>>2]|0)&&(jk(Yd,1),Mg(Wd,a[ce>>2]));var ee=ah(a[de>>2],Yd);if(0==(ee|0)){break b}else{Yd=ee}}}}}while(0);b:do{if(0!=(a[1345492]|0)){var le=zb(Md,Td);if(0!=(le|0)){for(var Zd=le;;){var be=Zd+116|0;0!=(a[be>>2]|0)&&(jk(Zd,0),Mg(Wd,a[be>>2]));var $d=Db(a[Vd>>2],Zd);if(0==($d|0)){break b}else{Zd=$d}}}}}while(0);var fe=sa(a[nd>>2],Td);if(0==(fe|0)){break a}else{Td=fe}}}}}while(0);E(xb);E(a[za>>2]);E(G);E(a[Nb>>2]);var oe=a[1311604]-1|0;a[1311604]=oe;0<(oe|0)||E(a[1311892]);a[1345163]=1}h=t}function Xq(c){var d;if(0!=(a[c+180>>2]|0)){for(d=a[c+184>>2];;){var g=a[d>>2];if(0==n[g+124|0]<<24>>24){break}else{d=g+128|0}}d=(g+108|0)>>2;var g=a[d],e=0==(a[a[c+20>>2]+152>>2]&1|0)?g+24|0:g+32|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),l=c+32|0,e=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])+.5*e,g=g+56|0;f[b>>3]=e;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];c=c+40|0;c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);g=a[d]+64|0;f[b>>3]=c;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];n[a[d]+81|0]=1}}function ih(b){for(;;){var c=a[b+180>>2];if(0==(c|0)){var d=b;break}else{b=c}}for(;!(b=a[d+128>>2],0==(b|0));){d=b}return d}function $q(c,d){var g,e,l,p,j=h;h=h+368|0;p=j>>2;var k=j+184;l=k>>2;var i=a[c>>2],q=a[d>>2],m=a[i+172>>2],w=m&15,x=a[q+172>>2],v=x&15;if((w|0)!=(v|0)){return h=j,v-w|0}v=ih(i);e=v>>2;w=ih(q);g=w>>2;var t=a[e+4],y=a[e+3],z=a[t+236>>2]-a[y+236>>2]|0,B=a[g+4],F=a[g+3],A=a[B+236>>2]-a[F+236>>2]|0,z=-1<(z|0)?z:-z|0,A=-1<(A|0)?A:-A|0;if((z|0)!=(A|0)){return h=j,z-A|0}t=t+32|0;y=y+32|0;y=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3])-(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3]);B=B+32|0;F=F+32|0;y&=-1;y=-1<(y|0)?y:-y|0;F=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3])-(a[b>>2]=a[F>>2],a[b+4>>2]=a[F+4>>2],f[b>>3])&-1;F=-1<(F|0)?F:-F|0;if((y|0)!=(F|0)){return h=j,y-F|0}e=a[e+5];g=a[g+5];if((e|0)!=(g|0)){return h=j,e-g|0}0==n[i+56|0]<<24>>24?(v=g=0==n[i+96|0]<<24>>24?v:i,g=a[g+172>>2]):(v=i,g=m);if(0==(g&32|0)){p=v}else{g=(v|0)>>2;e=(j|0)>>2;for(F=g+46;g<F;g++,e++){a[e]=a[g]}a[p+4]=a[v+12>>2];a[p+3]=a[v+16>>2];g=(v+68|0)>>2;e=(j+28|0)>>2;for(F=g+10;g<F;g++,e++){a[e]=a[g]}g=(v+28|0)>>2;e=(j+68|0)>>2;for(F=g+10;g<F;g++,e++){a[e]=a[g]}n[j+124|0]=1;a[p+32]=v;p=j}0==n[q+56|0]<<24>>24?(w=v=0==n[q+96|0]<<24>>24?w:q,v=a[v+172>>2]):(w=q,v=x);if(0==(v&32|0)){l=w}else{g=(w|0)>>2;e=(k|0)>>2;for(F=g+46;g<F;g++,e++){a[e]=a[g]}a[l+4]=a[w+12>>2];a[l+3]=a[w+16>>2];g=(w+68|0)>>2;e=(k+28|0)>>2;for(F=g+10;g<F;g++,e++){a[e]=a[g]}g=(w+28|0)>>2;e=(k+68|0)>>2;for(F=g+10;g<F;g++,e++){a[e]=a[g]}n[k+124|0]=1;a[l+32]=w;l=k}k=ig(p+28|0,l+28|0);if(0!=(k|0)){return h=j,k}l=ig(p+68|0,l+68|0);if(0!=(l|0)){return h=j,l}m&=192;x&=192;i=(m|0)==(x|0)?a[i+20>>2]-a[q+20>>2]|0:m-x|0;h=j;return i}function Yq(c,d,g,e,l,p){var j,k,i,q=0,m=h;h=h+1580|0;i=m>>2;var w=m+184,x=m+188,v=m+884,t=a[g+(e<<2)>>2];k=t>>2;if(0==(a[k+43]&32|0)){i=t}else{var y=(t|0)>>2;j=(m|0)>>2;for(var z=y+46;y<z;y++,j++){a[j]=a[y]}a[i+4]=a[k+3];a[i+3]=a[k+4];y=(t+68|0)>>2;j=(m+28|0)>>2;for(z=y+10;y<z;y++,j++){a[j]=a[y]}y=(t+28|0)>>2;j=(m+68|0)>>2;for(z=y+10;y<z;y++,j++){a[j]=a[y]}n[m+124|0]=1;a[i+32]=t;i=m}k=i>>2;if(0!=n[t+125|0]<<24>>24){ar(g,e,l,a[k+3],a[k+4],p)}else{if(0!=(a[k+27]|0)){br(c,d,i,p)}else{if(2==(p|0)){ll(a[k+4],a[k+3],g,e,l,2)}else{t=n[i+61|0];y=n[i+101|0];do{if(1!=t<<24>>24|4==y<<24>>24&&1!=y<<24>>24|4==t<<24>>24){var B=a[k+4],A=a[k+3],D=a[B+20>>2],z=a[B+236>>2];if(0<(z|0)){j=a[D+220>>2]>>2;var D=(0==(n[D+149|0]&1)<<24>>24?-1:-2)+z|0,C=a[a[((44*D&-1)+4>>2)+j]>>2]+40|0,E=B+40|0,z=(a[b>>2]=a[C>>2],a[b+4>>2]=a[C+4>>2],f[b>>3])-(a[((44*D&-1)+16>>2)+j]|0)-(a[b>>2]=a[E>>2],a[b+4>>2]=a[E+4>>2],f[b>>3])-(a[((44*z&-1)+20>>2)+j]|0)}else{z=a[D+260>>2]|0}D=l+1|0;j=(a[c+12>>2]|0)/D;z/=D;jh(c,d,B,i,x,1);jh(c,d,A,i,v,0);for(var B=x+52|0,A=v+52|0,D=8==(p|0),C=d+80|0,G=0;;){if((G|0)>=(l|0)){q=715;break}var E=a[g+(G+e<<2)>>2],I=a[B>>2],H=I-1|0,J=(H<<5)+x+56|0,J=(a[b>>2]=a[J>>2],a[b+4>>2]=a[J+4>>2],f[b>>3]),K=(H<<5)+x+72|0,K=(a[b>>2]=a[K>>2],a[b+4>>2]=a[K+4>>2],f[b>>3]),H=(H<<5)+x+80|0,M=(a[b>>2]=a[H>>2],a[b+4>>2]=a[H+4>>2],f[b>>3]);f[b>>3]=J;a[1322499]=a[b>>2];a[1322500]=a[b+4>>2];f[b>>3]=M;a[1322501]=a[b>>2];a[1322502]=a[b+4>>2];var G=G+1|0,L=G|0,H=L*j;f[b>>3]=K+H;a[1322503]=a[b>>2];a[1322504]=a[b+4>>2];K=M+L*z;f[b>>3]=K;a[1322505]=a[b>>2];a[1322506]=a[b+4>>2];f[b>>3]=J;a[1322507]=a[b>>2];a[1322508]=a[b+4>>2];f[b>>3]=K;a[1322509]=a[b>>2];a[1322510]=a[b+4>>2];M=a[A>>2]-1|0;J=(M<<5)+v+72|0;J=(a[b>>2]=a[J>>2],a[b+4>>2]=a[J+4>>2],f[b>>3]);f[b>>3]=J;a[1322511]=a[b>>2];a[1322512]=a[b+4>>2];f[b>>3]=K+z;a[1322513]=a[b>>2];a[1322514]=a[b+4>>2];L=(M<<5)+v+56|0;L=(a[b>>2]=a[L>>2],a[b+4>>2]=a[L+4>>2],f[b>>3]);M=(M<<5)+v+80|0;M=(a[b>>2]=a[M>>2],a[b+4>>2]=a[M+4>>2],f[b>>3]);f[b>>3]=J;a[1322519]=a[b>>2];a[1322520]=a[b+4>>2];f[b>>3]=M;a[1322517]=a[b>>2];a[1322518]=a[b+4>>2];f[b>>3]=L-H;a[1322515]=a[b>>2];a[1322516]=a[b+4>>2];f[b>>3]=K;a[1322521]=a[b>>2];a[1322522]=a[b+4>>2];a:do{if(0<(I|0)){for(H=0;;){if(vc(d,(H<<5)+x+56|0),H=H+1|0,(H|0)>=(a[B>>2]|0)){break a}}}}while(0);vc(d,5289996);vc(d,5290028);vc(d,5290060);I=a[A>>2];a:do{if(0<(I|0)){for(H=I;;){if(H=H-1|0,vc(d,(H<<5)+v+56|0),0>=(H|0)){break a}}}}while(0);I=D?le(d,w,0):le(d,w,1);H=a[w>>2];if(0==(H|0)){q=713;break}Nd(E,a[E+12>>2],I,H);a[C>>2]=0}if(715==q){h=m;return}if(713==q){h=m;return}}}while(0);cr(c,d,g,e,l,i,8==(p|0)&1)}}}h=m}function Zq(c,d,g,e,l,p){var j,k,i,q,m,w,x,v,t,y,z,B,A,D,C,E,G,I,H,T,K,M,L,N,P,Q,R,Y,U,aa,da,ea,wa,$,V,W,X,ba,ma,ca,fa,ha,O,ga,ia,sa,ua,Da,Ja,qa,ra,na,ya,ja=0,la=h;h=h+2276|0;ya=la>>2;var va=la+4;na=va>>2;var oa=la+188;ra=oa>>2;var ka=la+372,Ea=la+556,Ka=la+1252,Na=la+1948,Ba=la+1980;qa=Ba>>2;var Wa=la+1984;Ja=Wa>>2;var xa=la+1988,ta=la+2020,Ra=la+2052,bb=la+2084,Xa=la+2116,Sa=la+2148,Ha=la+2180,Va=la+2212,Ta=la+2244;0==(a[1312760]|0)&&(a[1312760]=Za(32e3),a[1312759]=Za(32e3),a[1312762]=2e3,a[1312761]=2e3);var Aa=a[g+(e<<2)>>2];Da=(Aa+16|0)>>2;var fb=a[Da],Ca=a[fb+20>>2];ua=(Aa+12|0)>>2;var Ya=a[ua],$a=a[fb+236>>2]-a[Ya+236>>2]|0;do{if(1<((-1<($a|0)?$a:-$a|0)|0)){for(var La=Aa|0,pa=La>>2,Ga=(va|0)>>2,Fa=pa+46;pa<Fa;pa++,Ga++){a[Ga]=a[pa]}for(var Qa=0==(a[Aa+172>>2]&32|0),nb=oa|0,pa=La>>2,Ga=nb>>2,Fa=pa+46;pa<Fa;pa++,Ga++){a[Ga]=a[pa]}if(Qa){var jb=a[Da],cb=a[na+4]=jb}else{a[ra+4]=a[ua];a[ra+3]=a[Da];for(var Pa=oa+28|0,kb=Aa+68|0,pa=kb>>2,Ga=Pa>>2,Fa=pa+10;pa<Fa;pa++,Ga++){a[Ga]=a[pa]}for(var Kb=oa+68|0,pa=(Aa+28|0)>>2,Ga=Kb>>2,Fa=pa+10;pa<Fa;pa++,Ga++){a[Ga]=a[pa]}n[oa+124|0]=1;a[ra+32]=Aa;var Ma=a[ua];a[na+4]=Ma;for(var hb=va+28|0,pa=kb>>2,Ga=hb>>2,Fa=pa+10;pa<Fa;pa++,Ga++){a[Ga]=a[pa]}cb=Ma}for(var lb=ih(Aa);;){var rb=a[lb+180>>2];if(0==(rb|0)){break}else{lb=rb}}var ab=a[lb+12>>2];a[na+3]=ab;n[va+96|0]=0;n[va+124|0]=1;sa=(va+68|0)>>2;a[sa]=0;a[sa+1]=0;a[sa+2]=0;a[sa+3]=0;a[na+32]=Aa;var db=1,ob=va,pb=cb,ub=ab}else{if(0==(a[Aa+172>>2]&32|0)){db=0,ob=Aa,pb=fb,ub=Ya}else{for(var gb=va|0,pa=(Aa|0)>>2,Ga=gb>>2,Fa=pa+46;pa<Fa;pa++,Ga++){a[Ga]=a[pa]}var sb=a[ua];a[na+4]=sb;var Ia=a[Da];a[na+3]=Ia;for(var vb=va+28|0,pa=(Aa+68|0)>>2,Ga=vb>>2,Fa=pa+10;pa<Fa;pa++,Ga++){a[Ga]=a[pa]}for(var Ua=va+68|0,pa=(Aa+28|0)>>2,Ga=Ua>>2,Fa=pa+10;pa<Fa;pa++,Ga++){a[Ga]=a[pa]}n[va+124|0]=1;a[na+32]=Aa;db=0;ob=va;pb=sb;ub=Ia}}}while(0);var eb=2==(p|0);if(eb){var mb=dr(ob,a[1312760],la);a[Ja]=mb;if(0==(mb|0)){var qb=a[ob+16>>2],Bb=a[ob+12>>2],ja=730}}else{qb=pb,Bb=ub,ja=730}if(730==ja){var tb=8==(p|0);a[Ja]=0;a[ya]=Bb;Xe(xa,c,qb,0,ob);ia=Ea>>2;ga=xa>>2;a[ia]=a[ga];a[ia+1]=a[ga+1];a[ia+2]=a[ga+2];a[ia+3]=a[ga+3];a[ia+4]=a[ga+4];a[ia+5]=a[ga+5];a[ia+6]=a[ga+6];a[ia+7]=a[ga+7];O=Na>>2;a[O]=a[ga];a[O+1]=a[ga+1];a[O+2]=a[ga+2];a[O+3]=a[ga+3];a[O+4]=a[ga+4];a[O+5]=a[ga+5];a[O+6]=a[ga+6];a[O+7]=a[ga+7];Tg(d,ob,1,Ea,kh(qb));ha=(Ea+52|0)>>2;var xb=a[ha]-1|0,za=(xb<<5)+Ea+80|0,Nb=(a[b>>2]=a[za>>2],a[b+4>>2]=a[za+4>>2],f[b>>3]);fa=(Na+24|0)>>2;f[b>>3]=Nb;a[fa]=a[b>>2];a[fa+1]=a[b+4>>2];var Jb=(xb<<5)+Ea+64|0,zb=(a[b>>2]=a[Jb>>2],a[b+4>>2]=a[Jb+4>>2],f[b>>3]);ca=(Na+8|0)>>2;f[b>>3]=zb;a[ca]=a[b>>2];a[ca+1]=a[b+4>>2];var wb=qb+40|0;yf(ta,Na,1,(a[b>>2]=a[wb>>2],a[b+4>>2]=a[wb+4>>2],f[b>>3])-a[a[a[qb+20>>2]+220>>2]+(44*a[qb+236>>2]&-1)+16>>2]&-1);ma=ta>>2;a[O]=a[ma];a[O+1]=a[ma+1];a[O+2]=a[ma+2];a[O+3]=a[ma+3];a[O+4]=a[ma+4];a[O+5]=a[ma+5];a[O+6]=a[ma+6];a[O+7]=a[ma+7];ba=(Na|0)>>2;X=(Na+16|0)>>2;if((a[b>>2]=a[ba],a[b+4>>2]=a[ba+1],f[b>>3])<(a[b>>2]=a[X],a[b+4>>2]=a[X+1],f[b>>3])){if((a[b>>2]=a[ca],a[b+4>>2]=a[ca+1],f[b>>3])<(a[b>>2]=a[fa],a[b+4>>2]=a[fa+1],f[b>>3])){var Cb=a[ha];a[ha]=Cb+1|0;W=((Cb<<5)+Ea+56|0)>>2;a[W]=a[O];a[W+1]=a[O+1];a[W+2]=a[O+2];a[W+3]=a[O+3];a[W+4]=a[O+4];a[W+5]=a[O+5];a[W+6]=a[O+6];a[W+7]=a[O+7]}}V=Ra>>2;var Eb=Ca+149|0;$=bb>>2;wa=Ka>>2;ea=Xa>>2;da=(Ka+52|0)>>2;var Db=d+56|0,Hb=d+69|0;aa=Sa>>2;var Ib=d+16|0,Mb=d+29|0,Pb=-1,Ub=0,Sb=qb,Lb=ob,Zb=Bb;a:for(;;){for(var $b=0,Xb=Pb,hc=Ub,bc=Sb,Qb=Lb,cc=0,pc=Zb;;){if(1!=n[pc+162|0]<<24>>24){break a}if(0!=J[a[1311601]](pc)<<24>>24){break a}var fc=cc|1;ml(Ra,c,Ca,a[bc+236>>2]);U=((cc<<5)+5289996|0)>>2;a[U]=a[V];a[U+1]=a[V+1];a[U+2]=a[V+2];a[U+3]=a[V+3];a[U+4]=a[V+4];a[U+5]=a[V+5];a[U+6]=a[V+6];a[U+7]=a[V+7];if(0==($b|0)){var dc;for(var ac=0,Vb=pc+32|0,Yb=pc,gc=0;;){var ec=a[a[a[Yb+184>>2]>>2]+12>>2];if(1!=n[ec+162|0]<<24>>24){ac=836;break}if(1!=(a[ec+188>>2]|0)){ac=835;break}if(1!=(a[ec+180>>2]|0)){ac=833;break}var ic=ec+32|0;if((a[b>>2]=a[ic>>2],a[b+4>>2]=a[ic+4>>2],f[b>>3])!=(a[b>>2]=a[Vb>>2],a[b+4>>2]=a[Vb+4>>2],f[b>>3])){ac=834;break}else{Yb=ec,gc=gc+1|0}}dc=835==ac||833==ac||836==ac||834==ac?gc:Wb;var jc=(dc|0)<((0!=(n[Eb]&1)<<24>>24?5:3)|0),oc=jc&1^1,lc=jc?Xb:1,kc=jc?dc:dc-2|0}else{oc=$b,lc=Xb,kc=hc}if(!(0==(oc|0)|0<(lc|0))){break}Xe(bb,c,pc,Qb,a[a[pc+184>>2]>>2]);Y=((fc<<5)+5289996|0)>>2;a[Y]=a[$];a[Y+1]=a[$+1];a[Y+2]=a[$+2];a[Y+3]=a[$+3];a[Y+4]=a[$+4];a[Y+5]=a[$+5];a[Y+6]=a[$+6];a[Y+7]=a[$+7];var uc=a[a[a[ya]+184>>2]>>2],tc=a[uc+16>>2],wc=a[uc+12>>2];a[ya]=wc;$b=oc;Xb=lc-1|0;hc=kc;bc=tc;Qb=uc;cc=cc+2|0;pc=wc}Xe(Xa,c,pc,Qb,a[a[pc+184>>2]>>2]);a[wa]=a[ea];a[wa+1]=a[ea+1];a[wa+2]=a[ea+2];a[wa+3]=a[ea+3];a[wa+4]=a[ea+4];a[wa+5]=a[ea+5];a[wa+6]=a[ea+6];a[wa+7]=a[ea+7];Ug(d,Qb,1,Ka,kh(a[Qb+12>>2]));var yc=a[ya],Kc=yc+40|0;yf(Na,(a[da]-1<<5)+Ka+56|0,4,(a[b>>2]=a[Kc>>2],a[b+4>>2]=a[Kc+4>>2],f[b>>3])+a[a[a[yc+20>>2]+220>>2]+(44*a[yc+236>>2]&-1)+20>>2]&-1);if((a[b>>2]=a[ba],a[b+4>>2]=a[ba+1],f[b>>3])<(a[b>>2]=a[X],a[b+4>>2]=a[X+1],f[b>>3])){if((a[b>>2]=a[ca],a[b+4>>2]=a[ca+1],f[b>>3])<(a[b>>2]=a[fa],a[b+4>>2]=a[fa+1],f[b>>3])){var rc=a[da];a[da]=rc+1|0;R=((rc<<5)+Ka+56|0)>>2;a[R]=a[O];a[R+1]=a[O+1];a[R+2]=a[O+2];a[R+3]=a[O+3];a[R+4]=a[O+4];a[R+5]=a[O+5];a[R+6]=a[O+6];a[R+7]=a[O+7]}}f[b>>3]=1.5707963267948966;a[Db>>2]=a[b>>2];a[Db+4>>2]=a[b+4>>2];n[Hb]=1;nl(d,Lb,Qb,Ea,Ka,fc);if(tb){var Bc=le(d,Ba,0),ja=749}else{var Cc=le(d,Ba,1);if(eb){var zc=a[qa];if(4<(zc|0)){Q=(Cc+16|0)>>2;P=Cc>>2;a[Q]=a[P];a[Q+1]=a[P+1];a[Q+2]=a[P+2];a[Q+3]=a[P+3];N=(Cc+32|0)>>2;var Dc=(zc-1<<4)+Cc|0;L=Dc>>2;a[N]=a[L];a[N+1]=a[L+1];a[N+2]=a[L+2];a[N+3]=a[L+3];xg(Cc+48|0,Dc);var vc=a[qa]=4,Ec=Cc}else{var Hc=Cc,Fc=zc,ja=750}}else{Bc=Cc,ja=749}}749==ja&&(ja=0,Hc=Bc,Fc=a[qa],ja=750);if(750==ja){if(ja=0,0==(Fc|0)){ja=804;break}else{vc=Fc,Ec=Hc}}var xc=a[Ja],Gc=xc+vc|0;if((Gc|0)>(a[1312762]|0)){a[1312762]=Gc<<1;var Nc=Oa(a[1312760],Gc<<5),Mc=a[1312760]=Nc}else{Mc=a[1312760]}if(0<(vc|0)){for(var Qc=1<(vc|0)?vc:1,Pc=0,Rc=xc;;){M=((Rc<<4)+Mc|0)>>2;K=((Pc<<4)+Ec|0)>>2;a[M]=a[K];a[M+1]=a[K+1];a[M+2]=a[K+2];a[M+3]=a[K+3];var gd=Pc+1|0;if((gd|0)<(vc|0)){Pc=gd,Rc=Rc+1|0}else{break}}a[Ja]=xc+Qc|0}var Sc,bd=a[a[a[ya]+184>>2]>>2],Vc=Mc,cd=Wb,Zc=Wb,nc=Wb,Oc=Wb,Lc=Wb,dd=Wa>>2,fd=a[dd];b:do{if(0==(kc|0)){var id=bd}else{for(var Xc=kc,kd=bd;;){var $c=Xc-1|0,od=a[a[a[kd+12>>2]+184>>2]>>2];if(0==($c|0)){id=od;break b}else{Xc=$c,kd=od}}}}while(0);a[dd]=fd+1|0;Lc=((fd<<4)+Vc|0)>>2;Oc=((fd-1<<4)+Vc|0)>>2;a[Lc]=a[Oc];a[Lc+1]=a[Oc+1];a[Lc+2]=a[Oc+2];a[Lc+3]=a[Oc+3];var pd=a[dd];a[dd]=pd+1|0;nc=((pd<<4)+Vc|0)>>2;a[nc]=a[Oc];a[nc+1]=a[Oc+1];a[nc+2]=a[Oc+2];a[nc+3]=a[Oc+3];Zc=((a[dd]<<4)+Vc|0)>>2;cd=(a[id+16>>2]+32|0)>>2;a[Zc]=a[cd];a[Zc+1]=a[cd+1];a[Zc+2]=a[cd+2];a[Zc+3]=a[cd+3];Sc=id;ol(Lb,d);var ad=a[Sc+16>>2];T=ad>>2;var td=a[Sc+12>>2];a[ya]=td;Xe(Sa,c,ad,a[a[T+44]>>2],Sc);a[ia]=a[aa];a[ia+1]=a[aa+1];a[ia+2]=a[aa+2];a[ia+3]=a[aa+3];a[ia+4]=a[aa+4];a[ia+5]=a[aa+5];a[ia+6]=a[aa+6];a[ia+7]=a[aa+7];Tg(d,Sc,1,Ea,kh(ad));var Tc=ad+40|0;yf(Na,(a[ha]-1<<5)+Ea+56|0,1,(a[b>>2]=a[Tc>>2],a[b+4>>2]=a[Tc+4>>2],f[b>>3])-a[a[a[T+5]+220>>2]+(44*a[T+59]&-1)+16>>2]&-1);if((a[b>>2]=a[ba],a[b+4>>2]=a[ba+1],f[b>>3])<(a[b>>2]=a[X],a[b+4>>2]=a[X+1],f[b>>3])){if((a[b>>2]=a[ca],a[b+4>>2]=a[ca+1],f[b>>3])<(a[b>>2]=a[fa],a[b+4>>2]=a[fa+1],f[b>>3])){var ud=a[ha];a[ha]=ud+1|0;H=((ud<<5)+Ea+56|0)>>2;a[H]=a[O];a[H+1]=a[O+1];a[H+2]=a[O+2];a[H+3]=a[O+3];a[H+4]=a[O+4];a[H+5]=a[O+5];a[H+6]=a[O+6];a[H+7]=a[O+7]}}f[b>>3]=-1.5707963267948966;a[Ib>>2]=a[b>>2];a[Ib+4>>2]=a[b+4>>2];n[Mb]=1;Pb=lc;Ub=kc;Sb=ad;Lb=Sc;Zb=td}if(804==ja){h=la;return}var vd=cc|1;ml(Ha,c,Ca,a[bc+236>>2]);I=((cc<<5)+5289996|0)>>2;G=Ha>>2;a[I]=a[G];a[I+1]=a[G+1];a[I+2]=a[G+2];a[I+3]=a[G+3];a[I+4]=a[G+4];a[I+5]=a[G+5];a[I+6]=a[G+6];a[I+7]=a[G+7];Xe(Va,c,pc,Qb,0);E=Va>>2;a[wa]=a[E];a[wa+1]=a[E+1];a[wa+2]=a[E+2];a[wa+3]=a[E+3];a[wa+4]=a[E+4];a[wa+5]=a[E+5];a[wa+6]=a[E+6];a[wa+7]=a[E+7];a[O]=a[E];a[O+1]=a[E+1];a[O+2]=a[E+2];a[O+3]=a[E+3];a[O+4]=a[E+4];a[O+5]=a[E+5];a[O+6]=a[E+6];a[O+7]=a[E+7];var Bd=0!=(db|0),Ed=Qb+12|0;Ug(d,Bd?oa:Qb,1,Ka,kh(a[Ed>>2]));var Uc=a[da]-1|0,wd=(Uc<<5)+Ka+80|0,Jd=(a[b>>2]=a[wd>>2],a[b+4>>2]=a[wd+4>>2],f[b>>3]);f[b>>3]=Jd;a[fa]=a[b>>2];a[fa+1]=a[b+4>>2];var xd=(Uc<<5)+Ka+64|0,rd=(a[b>>2]=a[xd>>2],a[b+4>>2]=a[xd+4>>2],f[b>>3]);f[b>>3]=rd;a[ca]=a[b>>2];a[ca+1]=a[b+4>>2];var yd=a[ya],Fd=yd+40|0;yf(Ta,Na,4,(a[b>>2]=a[Fd>>2],a[b+4>>2]=a[Fd+4>>2],f[b>>3])+a[a[a[yd+20>>2]+220>>2]+(44*a[yd+236>>2]&-1)+20>>2]&-1);C=Ta>>2;a[O]=a[C];a[O+1]=a[C+1];a[O+2]=a[C+2];a[O+3]=a[C+3];a[O+4]=a[C+4];a[O+5]=a[C+5];a[O+6]=a[C+6];a[O+7]=a[C+7];if((a[b>>2]=a[ba],a[b+4>>2]=a[ba+1],f[b>>3])<(a[b>>2]=a[X],a[b+4>>2]=a[X+1],f[b>>3])){if((a[b>>2]=a[ca],a[b+4>>2]=a[ca+1],f[b>>3])<(a[b>>2]=a[fa],a[b+4>>2]=a[fa+1],f[b>>3])){var Cd=a[da];a[da]=Cd+1|0;D=((Cd<<5)+Ka+56|0)>>2;a[D]=a[O];a[D+1]=a[O+1];a[D+2]=a[O+2];a[D+3]=a[O+3];a[D+4]=a[O+4];a[D+5]=a[O+5];a[D+6]=a[O+6];a[D+7]=a[O+7]}}nl(d,Lb,Qb,Ea,Ka,vd);var md=tb?le(d,Ba,0):le(d,Ba,1),sd=a[qa];if(eb&4<(sd|0)){A=(md+16|0)>>2;B=md>>2;a[A]=a[B];a[A+1]=a[B+1];a[A+2]=a[B+2];a[A+3]=a[B+3];z=(md+32|0)>>2;var Gd=(sd-1<<4)+md|0;y=Gd>>2;a[z]=a[y];a[z+1]=a[y+1];a[z+2]=a[y+2];a[z+3]=a[y+3];xg(md+48|0,Gd);var ed=a[qa]=4}else{if(0!=(sd|0)){ed=sd}else{h=la;return}}var zd=a[Ja],Dd=zd+ed|0;(Dd|0)>(a[1312762]|0)&&(a[1312762]=Dd<<1,a[1312760]=Oa(a[1312760],Dd<<5));if(0<(ed|0)){for(var Td=a[1312760],jd=1<(ed|0)?ed:1,Ld=0,Ad=zd;;){t=((Ad<<4)+Td|0)>>2;v=((Ld<<4)+md|0)>>2;a[t]=a[v];a[t+1]=a[v+1];a[t+2]=a[v+2];a[t+3]=a[v+3];var Od=Ld+1|0;if((Od|0)<(ed|0)){Ld=Od,Ad=Ad+1|0}else{break}}a[Ja]=zd+jd|0}ol(Lb,d);a[ya]=Bd?a[ra+3]:a[Ed>>2]}if(1==(l|0)){Nd(ob,a[ya],a[1312760],a[Ja])}else{var Pd=c+12|0,Hd=a[Ja],Id=Hd-1|0,Qd=1<(Id|0);a:do{if(Qd){for(var Wd=(Math.a(a[Pd>>2],l-1|0)|0)/2&-1|0,Md=a[1312760],nd=1;;){x=((nd<<4)+Md|0)>>2;var Yd=(a[b>>2]=a[x],a[b+4>>2]=a[x+1],f[b>>3])-Wd;f[b>>3]=Yd;a[x]=a[b>>2];a[x+1]=a[b+4>>2];var Zd=nd+1|0;if((Zd|0)<(Id|0)){nd=Zd}else{break a}}}}while(0);var Vd=a[1312762];if((Vd|0)>(a[1312761]|0)){a[1312761]=Vd;var de=Oa(a[1312759],Vd<<4),Xd=a[1312759]=de}else{Xd=a[1312759]}var ce=0<(Hd|0);a:do{if(ce){for(var ee=a[1312760],$d=0;;){w=(($d<<4)+Xd|0)>>2;m=(($d<<4)+ee|0)>>2;a[w]=a[m];a[w+1]=a[m+1];a[w+2]=a[m+2];a[w+3]=a[m+3];var fe=$d+1|0;if((fe|0)<(Hd|0)){$d=fe}else{break a}}}}while(0);Nd(ob,a[ya],Xd,Hd);if(1<(l|0)){for(var oe=ka|0,xe=ka+16|0,be=ka+12|0,ye=ka+28|0,ze=ka+68|0,Ce=ka+124|0,De=ka+128|0,qe=1;;){var ge=a[g+(qe+e<<2)>>2];q=ge>>2;if(0==(a[q+43]&32|0)){var re=ge}else{pa=(ge|0)>>2;Ga=oe>>2;for(Fa=pa+46;pa<Fa;pa++,Ga++){a[Ga]=a[pa]}a[xe>>2]=a[q+3];a[be>>2]=a[q+4];pa=(ge+68|0)>>2;Ga=ye>>2;for(Fa=pa+10;pa<Fa;pa++,Ga++){a[Ga]=a[pa]}pa=(ge+28|0)>>2;Ga=ze>>2;for(Fa=pa+10;pa<Fa;pa++,Ga++){a[Ga]=a[pa]}n[Ce]=1;a[De>>2]=ge;re=ka}a:do{if(Qd){for(var Ee=a[1312760],se=1;;){i=((se<<4)+Ee|0)>>2;var Fe=(a[Pd>>2]|0)+(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3]);f[b>>3]=Fe;a[i]=a[b>>2];a[i+1]=a[b+4>>2];var ve=se+1|0;if((ve|0)==(Id|0)){break a}else{se=ve}}}}while(0);var we=a[1312759];a:do{if(ce){for(var He=a[1312760],pe=0;;){k=((pe<<4)+we|0)>>2;j=((pe<<4)+He|0)>>2;a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];var Ae=pe+1|0;if((Ae|0)==(Hd|0)){break a}else{pe=Ae}}}}while(0);Nd(re,a[re+12>>2],we,Hd);var Be=qe+1|0;if((Be|0)==(l|0)){break}else{qe=Be}}}}h=la}function kh(b){return(1==n[b+162|0]<<24>>24?1<(a[b+180>>2]|0)?1:1<(a[b+188>>2]|0):0)&1}function ml(c,d,g,e){var l,h,j,k,i;h=a[d+16>>2];i=((e<<5)+h|0)>>2;var q=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3]);k=((e<<5)+h+8|0)>>2;var m=(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3]);j=((e<<5)+h+16|0)>>2;var n=(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3]);h=((e<<5)+h+24|0)>>2;l=(a[b>>2]=a[h],a[b+4>>2]=a[h+1],f[b>>3]);q==n?(l=a[g+220>>2]>>2,g=a[a[((44*e&-1)+4>>2)+l]>>2],m=e+1|0,n=a[d>>2]|0,q=a[a[((44*m&-1)+4>>2)+l]>>2]+40|0,m=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])+(a[((44*m&-1)+20>>2)+l]|0),d=a[d+4>>2]|0,g=g+40|0,e=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])-(a[((44*e&-1)+16>>2)+l]|0),f[b>>3]=n,a[i]=a[b>>2],a[i+1]=a[b+4>>2],f[b>>3]=m,a[k]=a[b>>2],a[k+1]=a[b+4>>2],f[b>>3]=d,a[j]=a[b>>2],a[j+1]=a[b+4>>2],f[b>>3]=e,a[h]=a[b>>2],a[h+1]=a[b+4>>2],j=n,k=m,i=d):(j=q,k=m,i=n,e=l);h=c|0;f[b>>3]=j;a[h>>2]=a[b>>2];a[h+4>>2]=a[b+4>>2];j=c+8|0;f[b>>3]=k;a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];j=c+16|0;f[b>>3]=i;a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];c=c+24|0;f[b>>3]=e;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function dr(c,d,g){var e,l,p,j,k,i,q,m,w,x,v,t,y,z=0,B=h;h=h+64|0;var A=B+16,D=B+32,C=B+48;a:do{if(0==n[c+124|0]<<24>>24){var E=c;y=E>>2}else{for(var G=c;;){var I=a[G+128>>2];if(0==n[I+124|0]<<24>>24){E=I;y=E>>2;break a}else{G=I}}}}while(0);var H=a[y+3];t=H>>2;var J=a[y+4],K=a[t+59]-a[J+236>>2]|0,M=-1<(K|0)?K:-K|0;if(2==(M|0)){z=853}else{if(1==(M|0)){var L=0;h=B;return L}}if(853==z&&0!=(n[a[t+5]+149|0]&1)<<24>>24){return L=0,h=B,L}if((a[c+16>>2]|0)==(J|0)){a[g>>2]=H;var N=J+32|0,P=(a[b>>2]=a[N>>2],a[b+4>>2]=a[N+4>>2],f[b>>3]),Q=J+40|0,R=(a[b>>2]=a[Q>>2],a[b+4>>2]=a[Q+4>>2],f[b>>3]),Y=E+28|0,U=E+36|0;Zd(B,P,R,(a[b>>2]=a[Y>>2],a[b+4>>2]=a[Y+4>>2],f[b>>3]),(a[b>>2]=a[U>>2],a[b+4>>2]=a[U+4>>2],f[b>>3]));var aa=B|0,da=(a[b>>2]=a[aa>>2],a[b+4>>2]=a[aa+4>>2],f[b>>3]),ea=B+8|0,$=(a[b>>2]=a[ea>>2],a[b+4>>2]=a[ea+4>>2],f[b>>3]),ca=H+32|0,V=(a[b>>2]=a[ca>>2],a[b+4>>2]=a[ca+4>>2],f[b>>3]),W=H+40|0,X=(a[b>>2]=a[W>>2],a[b+4>>2]=a[W+4>>2],f[b>>3]),ba=E+68|0,ma=E+76|0;Zd(A,V,X,(a[b>>2]=a[ba>>2],a[b+4>>2]=a[ba+4>>2],f[b>>3]),(a[b>>2]=a[ma>>2],a[b+4>>2]=a[ma+4>>2],f[b>>3]));var fa=A|0,ia=A+8|0,ha=da,O=$,ga=(a[b>>2]=a[fa>>2],a[b+4>>2]=a[fa+4>>2],f[b>>3]),sa=(a[b>>2]=a[ia>>2],a[b+4>>2]=a[ia+4>>2],f[b>>3])}else{a[g>>2]=J;var qa=H+32|0,ua=(a[b>>2]=a[qa>>2],a[b+4>>2]=a[qa+4>>2],f[b>>3]),Da=H+40|0,Ja=(a[b>>2]=a[Da>>2],a[b+4>>2]=a[Da+4>>2],f[b>>3]),na=E+68|0,ra=E+76|0;Zd(D,ua,Ja,(a[b>>2]=a[na>>2],a[b+4>>2]=a[na+4>>2],f[b>>3]),(a[b>>2]=a[ra>>2],a[b+4>>2]=a[ra+4>>2],f[b>>3]));var xa=D|0,ya=(a[b>>2]=a[xa>>2],a[b+4>>2]=a[xa+4>>2],f[b>>3]),ja=D+8|0,la=(a[b>>2]=a[ja>>2],a[b+4>>2]=a[ja+4>>2],f[b>>3]),va=J+32|0,oa=(a[b>>2]=a[va>>2],a[b+4>>2]=a[va+4>>2],f[b>>3]),ka=J+40|0,Ea=(a[b>>2]=a[ka>>2],a[b+4>>2]=a[ka+4>>2],f[b>>3]),Ka=E+28|0,Na=E+36|0;Zd(C,oa,Ea,(a[b>>2]=a[Ka>>2],a[b+4>>2]=a[Ka+4>>2],f[b>>3]),(a[b>>2]=a[Na>>2],a[b+4>>2]=a[Na+4>>2],f[b>>3]));var Ba=C|0,Wa=C+8|0,ha=ya,O=la,ga=(a[b>>2]=a[Ba>>2],a[b+4>>2]=a[Ba+4>>2],f[b>>3]),sa=(a[b>>2]=a[Wa>>2],a[b+4>>2]=a[Wa+4>>2],f[b>>3])}var ta=a[y+27];if(0==(ta|0)){var Ha=d+16|0,Ra=d|0;f[b>>3]=ha;a[Ra>>2]=a[b>>2];a[Ra+4>>2]=a[b+4>>2];var bb=d+8|0;f[b>>3]=O;a[bb>>2]=a[b>>2];a[bb+4>>2]=a[b+4>>2];v=Ha>>2;x=d>>2;a[v]=a[x];a[v+1]=a[x+1];a[v+2]=a[x+2];a[v+3]=a[x+3];var Xa=d+48|0,Sa=d+32|0,Oa=Sa|0;f[b>>3]=ga;a[Oa>>2]=a[b>>2];a[Oa+4>>2]=a[b+4>>2];var Va=d+40|0;f[b>>3]=sa;a[Va>>2]=a[b>>2];a[Va+4>>2]=a[b+4>>2];w=Xa>>2;m=Sa>>2;a[w]=a[m];a[w+1]=a[m+1];a[w+2]=a[m+2];a[w+3]=a[m+3];L=4;h=B;return L}var Ta=ta+24|0,Aa=(a[b>>2]=a[Ta>>2],a[b+4>>2]=a[Ta+4>>2],f[b>>3]),fb=ta+32|0,Ca=(a[b>>2]=a[fb>>2],a[b+4>>2]=a[fb+4>>2],f[b>>3]),Ya=0==(a[a[t+5]+152>>2]&1|0),$a=Ya?Ca:Aa,La=ta+56|0,pa=(a[b>>2]=a[La>>2],a[b+4>>2]=a[La+4>>2],f[b>>3]),Ga=ta+64|0,Fa=(a[b>>2]=a[Ga>>2],a[b+4>>2]=a[Ga+4>>2],f[b>>3]),Qa=.5*(Ya?Aa:Ca);if(0==(0<((sa-O)*(pa-ha)-(Fa-O)*(ga-ha)&-1|0)&1|0)){var nb=pa-Qa,jb=Fa+.5*$a}else{nb=pa+Qa,jb=Fa-.5*$a}var cb=d+16|0,Pa=d|0;f[b>>3]=ha;a[Pa>>2]=a[b>>2];a[Pa+4>>2]=a[b+4>>2];var kb=d+8|0;f[b>>3]=O;a[kb>>2]=a[b>>2];a[kb+4>>2]=a[b+4>>2];q=cb>>2;i=d>>2;a[q]=a[i];a[q+1]=a[i+1];a[q+2]=a[i+2];a[q+3]=a[i+3];var Kb=d+32|0,Ma=d+48|0,Za=d+64|0,lb=Za|0;f[b>>3]=nb;a[lb>>2]=a[b>>2];a[lb+4>>2]=a[b+4>>2];var rb=d+72|0;f[b>>3]=jb;a[rb>>2]=a[b>>2];a[rb+4>>2]=a[b+4>>2];k=Ma>>2;j=Za>>2;a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];p=Kb>>2;a[p]=a[j];a[p+1]=a[j+1];a[p+2]=a[j+2];a[p+3]=a[j+3];var ab=d+80|0,db=d+96|0,ob=db|0;f[b>>3]=ga;a[ob>>2]=a[b>>2];a[ob+4>>2]=a[b+4>>2];var pb=d+104|0;f[b>>3]=sa;a[pb>>2]=a[b>>2];a[pb+4>>2]=a[b+4>>2];l=ab>>2;e=db>>2;a[l]=a[e];a[l+1]=a[e+1];a[l+2]=a[e+2];a[l+3]=a[e+3];L=7;h=B;return L}function Xe(c,d,g,e,l){var h,j=g>>2,k=d>>2,i=0;h=a[j+5]>>2;var d=g+32|0,q=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),d=g+104|0,m=q-(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])-4,d=a[j+59],w=a[j+60],x=a[h+55],v=er(x,d,w,e,l,-1);if(0==(v|0)){var v=0<=m,t=a[k],m=((v?m+.5:m-.5)&-1|0)<(t|0)?v?m+.5&-1:m-.5&-1:t}else{t=pl(g,v),0==(t|0)?(t=v+32|0,t=(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3])+(a[v+244>>2]|0),v=0==n[v+162|0]<<24>>24?t+.5*(a[h+64]|0):t+(a[k+2]|0)):(v=t+68|0,v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3])+(a[k+2]|0)),m=v<m?v:m,m=(0>m?m-.5:m+.5)&-1}m|=0;if(v=1==n[g+162|0]<<24>>24){if(0==(a[j+30]|0)){i=888}else{var y=q+10}}else{i=888}888==i&&(y=g+112|0,y=q+(a[b>>2]=a[y>>2],a[b+4>>2]=a[y+4>>2],f[b>>3])+4);e=er(x,d,w,e,l,1);0==(e|0)?(h=0<=y,k=a[k+1],y=((h?y+.5:y-.5)&-1|0)>(k|0)?h?y+.5&-1:y-.5&-1:k):(l=pl(g,e),0==(l|0)?(l=e+32|0,i=e+104|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])-(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),k=0==n[e+162|0]<<24>>24?l-.5*(a[h+64]|0):l-(a[k+2]|0)):(h=l+52|0,k=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])-(a[k+2]|0)),y=k>y?k:y,y=(0>y?y-.5:y+.5)&-1);y|=0;v?0==(a[j+30]|0)?j=y:(j=g+112|0,j=y-(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])):j=y;g=g+40|0;y=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);g=y-(a[x+(44*d&-1)+16>>2]|0);d=y+(a[x+(44*d&-1)+20>>2]|0);x=c|0;f[b>>3]=m;a[x>>2]=a[b>>2];a[x+4>>2]=a[b+4>>2];x=c+8|0;f[b>>3]=g;a[x>>2]=a[b>>2];a[x+4>>2]=a[b+4>>2];g=c+16|0;f[b>>3]=j;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];c=c+24|0;f[b>>3]=d;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function yf(c,d,g,e){var l,p=h;h=h+64|0;l=d>>2;d=h;h=h+32|0;a[d>>2]=a[l];a[d+4>>2]=a[l+1];a[d+8>>2]=a[l+2];a[d+12>>2]=a[l+3];a[d+16>>2]=a[l+4];a[d+20>>2]=a[l+5];a[d+24>>2]=a[l+6];a[d+28>>2]=a[l+7];l=p+32;if(4==(g|0)){var j=d|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),k=d+24|0,d=d+16|0;fr(l,j,(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),e|0);e=l|0;j=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);e=l+8|0;d=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);e=l+16|0;l=l+24|0;var k=d,i=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),q=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])}else{1==(g|0)&&(l=d|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),j=d+16|0,d=d+8|0,fr(p,l,e|0,(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])),e=p|0,j=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),e=p+8|0,d=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),l=p+16|0,e=p+24|0,k=d,i=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),q=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]))}e=c|0;f[b>>3]=j;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];e=c+8|0;f[b>>3]=k;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];e=c+16|0;f[b>>3]=i;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];c=c+24|0;f[b>>3]=q;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2];h=p}function nl(b,c,d,e,f,h){var j=ql(c,-1),c=ql(c,1);0!=(j|0)&&Vg(j);0!=(c|0)&&Vg(c);j=rl(d,-1);d=rl(d,1);0!=(j|0)&&Vg(j);0!=(d|0)&&Vg(d);d=e+52|0;a:do{if(0<(a[d>>2]|0)){for(j=0;;){if(vc(b,(j<<5)+e+56|0),j=j+1|0,(j|0)>=(a[d>>2]|0)){break a}}}}while(0);e=a[b+80>>2]+1|0;d=h-3+e|0;a:do{if(0<(h|0)){for(j=0;;){if(vc(b,(j<<5)+5289996|0),j=j+1|0,(j|0)==(h|0)){break a}}}}while(0);h=a[f+52>>2];if(0<(h|0)){for(;!(h=h-1|0,vc(b,(h<<5)+f+56|0),0>=(h|0));){}}gr(b,e,d)}function hr(c,d,g,e){var l=c+32|0;f[b>>3]=g|0;a[l>>2]=a[b>>2];a[l+4>>2]=a[b+4>>2];l=c+104|0;f[b>>3]=g-d|0;a[l>>2]=a[b>>2];a[l+4>>2]=a[b+4>>2];c=c+112|0;f[b>>3]=e-g|0;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function ql(b,c){var d,e=a[a[b+16>>2]+184>>2],f=a[e>>2];if(0==(f|0)){var h;return 0}var j=a[a[b+12>>2]+240>>2],k=0,i=0,q=f;for(d=q>>2;;){var m=a[a[d+3]+240>>2];do{if(1>(Math.a(m-j|0,c)|0)){f=k}else{if(0==(a[d+6]|0)){f=a[d+32];if(0==(f|0)){f=k;break}if(0==(a[f+24>>2]|0)){f=k;break}}f=0!=(k|0)&&0>=(Math.a(a[a[k+12>>2]+240>>2]-m|0,c)|0)?k:q}}while(0);i=i+1|0;d=a[e+(i<<2)>>2];if(0==(d|0)){h=f;break}else{k=f,q=d,d=q>>2}}return h}function rl(b,c){var d,e=a[a[b+12>>2]+176>>2],f=a[e>>2];if(0==(f|0)){var h;return 0}var j=a[a[b+16>>2]+240>>2],k=0,i=0,q=f;for(d=q>>2;;){var m=a[a[d+4]+240>>2];do{if(1>(Math.a(m-j|0,c)|0)){f=k}else{if(0==(a[d+6]|0)){f=a[d+32];if(0==(f|0)){f=k;break}if(0==(a[f+24>>2]|0)){f=k;break}}f=0!=(k|0)&&0>=(Math.a(a[a[k+16>>2]+240>>2]-m|0,c)|0)?k:q}}while(0);i=i+1|0;d=a[e+(i<<2)>>2];if(0==(d|0)){h=f;break}else{k=f,q=d,d=q>>2}}return h}function gr(c,d,g){var e,l,h,j=0,k=d-1|0,i=g+1|0;a:do{if((k|0)<(i|0)){for(var q=c+84|0,m=k;;){h=a[q>>2];e=((m<<5)+h|0)>>2;l=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);if(0==(m-d&1|0)){h=((m<<5)+h+16|0)>>2;var n=(a[b>>2]=a[h],a[b+4>>2]=a[h+1],f[b>>3]);l<n||(l=.5*(l+n)&-1,f[b>>3]=l-8|0,a[e]=a[b>>2],a[e+1]=a[b+4>>2],f[b>>3]=l+8|0,a[h]=a[b>>2],a[h+1]=a[b+4>>2])}else{h=((m<<5)+h+16|0)>>2,n=(a[b>>2]=a[h],a[b+4>>2]=a[h+1],f[b>>3]),l+16>n&&(l=.5*(l+n)&-1,f[b>>3]=l-8|0,a[e]=a[b>>2],a[e+1]=a[b+4>>2],f[b>>3]=l+8|0,a[h]=a[b>>2],a[h+1]=a[b+4>>2])}e=m+1|0;if((e|0)==(i|0)){break a}else{m=e}}}}while(0);k=c+80|0;if(0<(a[k>>2]-1|0)){c=c+84|0;for(e=0;;){m=a[c>>2];l=(e<<5)+m|0;i=e+1|0;q=(i<<5)+m|0;if((e|0)<(d|0)|(e|0)>(g|0)){j=978}else{if(0!=(e-d&1|0)){j=978}else{h=l|0;n=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])+16;h=((i<<5)+m+16|0)>>2;if(n>(a[b>>2]=a[h],a[b+4>>2]=a[h+1],f[b>>3])){f[b>>3]=n,a[h]=a[b>>2],a[h+1]=a[b+4>>2]}h=(e<<5)+m+16|0;n=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])-16;h=(q|0)>>2;if(n<(a[b>>2]=a[h],a[b+4>>2]=a[h+1],f[b>>3])){f[b>>3]=n,a[h]=a[b>>2],a[h+1]=a[b+4>>2]}}}978==j&&(j=0,(i|0)>=(d|0)&(e|0)<(g|0)&&0==(i-d&1|0)&&(l=(l|0)>>2,h=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3])+16,n=(i<<5)+m+16|0,n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),h>n&&(f[b>>3]=n-16,a[l]=a[b>>2],a[l+1]=a[b+4>>2]),e=((e<<5)+m+16|0)>>2,m=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])-16,q|=0,q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),m<q&&(f[b>>3]=q+16,a[e]=a[b>>2],a[e+1]=a[b+4>>2])));if((i|0)<(a[k>>2]-1|0)){e=i}else{break}}}}function fr(c,d,g,e,l){var h=c|0;f[b>>3]=d;a[h>>2]=a[b>>2];a[h+4>>2]=a[b+4>>2];d=c+8|0;f[b>>3]=g;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];g=c+16|0;f[b>>3]=e;a[g>>2]=a[b>>2];a[g+4>>2]=a[b+4>>2];c=c+24|0;f[b>>3]=l;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function ir(c,d){var g=c+52|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),e=d+32|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);if(g>e){return 0}g=c+68|0;if(e>(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])){return 0}g=c+60|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);e=d+40|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);if(g>e){return 0}g=c+76|0;g=e<=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);return g&1}function jr(b,c,d,e){var f,h=b>>2,b=0,c=(a[h+60]|0)>(c|0);if(1!=(a[h+47]|0)){var j;return 0}a:do{if(0!=(e|0)){var k=0;f=e;for(e=a[a[h+46]>>2];;){if(2<=(k|0)){break a}var i=a[e+12>>2],e=i>>2,q=a[f+12>>2];f=q>>2;if((i|0)==(q|0)){break a}if(c^(a[e+60]|0)>(a[f+60]|0)){j=1;break}if(1!=(a[e+47]|0)){break a}if(0==n[i+162|0]<<24>>24){break a}if(1!=(a[f+47]|0)){break a}if(0==n[q+162|0]<<24>>24){break a}k=k+1|0;f=a[a[f+46]>>2];e=a[a[e+46]>>2]}return j}}while(0);if(1!=(a[h+45]|0)|0==(d|0)){return 0}k=0;e=d;for(d=a[a[h+44]>>2];;){if(2<=(k|0)){j=0;b=1022;break}h=a[d+16>>2];d=h>>2;i=a[e+16>>2];e=i>>2;if((h|0)==(i|0)){j=0;b=1023;break}if(c^(a[d+60]|0)>(a[e+60]|0)){j=1;b=1029;break}if(1!=(a[d+45]|0)){j=0;b=1024;break}if(0==n[h+162|0]<<24>>24){j=0;b=1027;break}if(1!=(a[e+45]|0)){j=0;b=1026;break}if(0==n[i+162|0]<<24>>24){j=0;b=1028;break}k=k+1|0;e=a[a[e+44]>>2];d=a[a[d+44]>>2]}if(1026==b||1027==b||1028==b||1029==b||1022==b||1023==b||1024==b){return j}}function Zd(c,d,g,e,l){var h=c|0;f[b>>3]=d+e;a[h>>2]=a[b>>2];a[h+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=g+l;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function ol(c,d){var g=d+84|0,e=d+80|0,l=c,h=0;a:for(;;){l=a[l+12>>2];if(1!=n[l+162|0]<<24>>24){break}if(0!=J[a[1311601]](l)<<24>>24){break}for(var j=a[e>>2],k=l+40|0;;){if((h|0)>=(j|0)){break a}var i=a[g>>2],q=(h<<5)+i+8|0,m=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),q=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);if(m>q){h=h+1|0}else{break}}j=(h<<5)+i+24|0;if((a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])>=q){var j=0==(a[l+120>>2]|0),k=(h<<5)+i|0,m=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),k=m&-1,w=(h<<5)+i+16|0,w=(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]);j?hr(l,k,.5*(m+w)&-1,w&-1):(j=l+112|0,hr(l,k,w&-1,w+(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])&-1))}l=a[a[l+184>>2]>>2]}}function er(b,c,d,e,f,h){for(var j=0,k=b+(44*c&-1)|0,b=b+(44*c&-1)+4|0,c=d;;){c=c+h|0;if(-1>=(c|0)){var i=0,j=1057;break}if((c|0)>=(a[k>>2]|0)){i=0;j=1055;break}var q=a[a[b>>2]+(c<<2)>>2],m=n[q+162|0];if(1==m<<24>>24){if(0!=(a[q+120>>2]|0)){i=q;j=1054;break}}else{if(0==m<<24>>24){i=q;j=1053;break}}if(0==jr(q,d,e,f)<<24>>24){i=q;j=1056;break}}if(1056==j||1054==j||1057==j||1053==j||1055==j){return i}}function pl(b,c){if(0==n[b+162|0]<<24>>24){var d=a[b+216>>2],e=d}else{d=a[a[a[b+184>>2]>>2]+128>>2],e=a[a[d+12>>2]+216>>2],d=a[a[d+16>>2]+216>>2]}if(0==n[c+162|0]<<24>>24){var f=a[c+216>>2];return 0==(f|0)|(f|0)==(d|0)|(f|0)==(e|0)?0:f}var f=a[a[a[c+184>>2]>>2]+128>>2],h=a[a[f+16>>2]+216>>2];if(!(0==(h|0)|(h|0)==(d|0)|(h|0)==(e|0))&&0!=(ir(h,c)|0)){return h}f=a[a[f+12>>2]+216>>2];return 0==(f|0)|(f|0)==(d|0)|(f|0)==(e|0)?0:0==(ir(f,c)|0)?0:f}function ar(c,d,g,e,l,p){var j,k,i,q,m,w,x,v,t,y,z,B,A,D,C,E,G,I,H,J,K,M,L,N,P,Q,R=0,Y=h;h=h+176|0;var U=Y+16,aa=Y+32,da=Y+96,ea=Y+112,$=Y+128,ca=Y+144,V=Y+160,W=a[l+20>>2];do{if(0<(g|0)){for(var X=0,ba=0,ma=0;;){var fa=a[c+(ma+d<<2)>>2],ia=(0!=(a[fa+108>>2]|0)&1)+X|0;if(0==n[fa+56|0]<<24>>24){if(0==n[fa+96|0]<<24>>24){var ha=ba}else{R=1073}}else{R=1073}1073==R&&(R=0,ha=1);var O=ma+1|0;if((O|0)==(g|0)){break}else{X=ia,ba=ha,ma=O}}if(0==(ha|0)){if(0==(ia|0)){break}kr(l,e,c,d,g,p,ia);h=Y;return}var ga=lr(W),sa=Qh(ga,5350848);Pc(sa|0,5373028,5327616);var qa=e+32|0,ua=(a[b>>2]=a[qa>>2],a[b+4>>2]=a[qa+4>>2],f[b>>3])&-1,Da=l+32|0,Ja=(a[b>>2]=a[Da>>2],a[b+4>>2]=a[Da+4>>2],f[b>>3])&-1;Q=(W+152|0)>>2;for(var na=0==(a[Q]&1|0),ra=na?e:l,ta=na?l:e,ya=mr(sa,ta),ja=mr(ga,ra),la=0,va=0;;){for(var oa=(la+d<<2)+c|0;;){var ka=a[oa>>2];if(0==n[ka+124|0]<<24>>24){break}else{oa=ka+128|0}}var Ea;if((a[ka+16>>2]|0)==(ta|0)){var Ka=ka,Na=sf(ga,ya,ja);Rh(Ka|0,Na|0);Ea=Na}else{var Ba=ka,xa=sf(ga,ja,ya);Rh(Ba|0,xa|0);Ea=xa}var Ha=Ea;a[ka+132>>2]=Ha|0;if(0==(va|0)){if(0!=n[ka+56|0]<<24>>24){var Oa=0}else{0!=n[ka+96|0]<<24>>24?Oa=0:(a[Ha+132>>2]=ka|0,Oa=Ha)}}else{Oa=va}var Ra=la+1|0;if((Ra|0)==(g|0)){break}else{la=Ra,va=Oa}}var bb=0==(Oa|0)?sf(ga,ya,ja):Oa;hc(bb|0,a[a[1345491]+8>>2],5338256);a[ga+172>>2]=a[W+172>>2];var Xa=ga;En(Xa,p);Uq(ga);sl(ga,0);nr(Xa,0);or(Xa,0);P=(ta+32|0)>>2;var Sa=ya+32|0;N=Sa>>2;L=(ja+32|0)>>2;var Qa=a[ga+216>>2];a:do{if(0!=(Qa|0)){for(var Va=.5*((a[b>>2]=a[L],a[b+4>>2]=a[L+1],f[b>>3])+(a[b>>2]=a[N],a[b+4>>2]=a[N+1],f[b>>3]))&-1,Ta=ta+112|0,Aa=ra+32|0,fb=(a[b>>2]=a[Ta>>2],a[b+4>>2]=a[Ta+4>>2],f[b>>3]),Ca=(a[b>>2]=a[P],a[b+4>>2]=a[P+1],f[b>>3]),Ya=ra+104|0,$a=ua|0,La=Va|0,pa=Ja|0,Ga=.5*((a[b>>2]=a[Aa>>2],a[b+4>>2]=a[Aa+4>>2],f[b>>3])+(Ca-fb)+(a[b>>2]=a[Ya>>2],a[b+4>>2]=a[Ya+4>>2],f[b>>3]))&-1|0,Fa=ya+40|0,Pa=ja+40|0,nb=Qa;;){if((nb|0)==(ya|0)){f[b>>3]=$a,a[Fa>>2]=a[b>>2],a[Fa+4>>2]=a[b+4>>2],f[b>>3]=La,a[N]=a[b>>2],a[N+1]=a[b+4>>2]}else{if((nb|0)==(ja|0)){f[b>>3]=pa,a[Pa>>2]=a[b>>2],a[Pa+4>>2]=a[b+4>>2],f[b>>3]=La,a[L]=a[b>>2],a[L+1]=a[b+4>>2]}else{var jb=nb+40|0;f[b>>3]=Ga;a[jb>>2]=a[b>>2];a[jb+4>>2]=a[b+4>>2]}}var cb=a[nb+168>>2];if(0==(cb|0)){break a}else{nb=cb}}}}while(0);tl(ga);kl(ga,0);Tj(Xa);var Za=0==(a[Q]&1|0),kb=(a[b>>2]=a[P],a[b+4>>2]=a[P+1],f[b>>3]);if(Za){var Kb=ta+40|0,Ma=ya+40|0,eb=Sa,lb=(a[b>>2]=a[Kb>>2],a[b+4>>2]=a[Kb+4>>2],f[b>>3])-(a[b>>2]=a[Ma>>2],a[b+4>>2]=a[Ma+4>>2],f[b>>3])}else{var rb=ta+40|0,eb=ya+40|0,lb=(a[b>>2]=a[rb>>2],a[b+4>>2]=a[rb+4>>2],f[b>>3])+(a[b>>2]=a[N],a[b+4>>2]=a[N+1],f[b>>3])}var ab=kb-(a[b>>2]=a[eb>>2],a[b+4>>2]=a[eb+4>>2],f[b>>3]);M=Y>>2;K=U>>2;J=da>>2;H=aa>>2;var db=aa|0;I=ea>>2;G=(aa+16|0)>>2;E=$>>2;C=(aa+32|0)>>2;D=(aa+48|0)>>2;A=ca>>2;var ob=W+52|0;B=V>>2;for(var pb=W,ub=0;;){for(var gb=(ub+d<<2)+c|0;;){var sb=a[gb>>2];if(0==n[sb+124|0]<<24>>24){break}else{gb=sb+128|0}}var Ia=a[sb+132>>2];z=Ia>>2;do{if(!((Ia|0)==(bb|0)&0==(a[z+33]|0))){var vb=a[a[z+6]>>2];y=(vb+4|0)>>2;var Ua=gk(sb,a[y]);a[Ua+8>>2]=a[vb+8>>2];var hb=a[Q]&1,mb=vb+16|0,qb=vb+24|0;zf(Y,(a[b>>2]=a[mb>>2],a[b+4>>2]=a[mb+4>>2],f[b>>3]),(a[b>>2]=a[qb>>2],a[b+4>>2]=a[qb+4>>2],f[b>>3]),ab,lb,hb);t=(Ua+16|0)>>2;a[t]=a[M];a[t+1]=a[M+1];a[t+2]=a[M+2];a[t+3]=a[M+3];a[Ua+12>>2]=a[vb+12>>2];var Bb=a[Q]&1,tb=vb+32|0,xb=vb+40|0;zf(U,(a[b>>2]=a[tb>>2],a[b+4>>2]=a[tb+4>>2],f[b>>3]),(a[b>>2]=a[xb>>2],a[b+4>>2]=a[xb+4>>2],f[b>>3]),ab,lb,Bb);v=(Ua+32|0)>>2;a[v]=a[K];a[v+1]=a[K+1];a[v+2]=a[K+2];a[v+3]=a[K+3];x=(Ua|0)>>2;w=(vb|0)>>2;for(var za=0;(za|0)<(a[y]|0);){var wb=(za<<4)+a[x]|0,Jb=a[w],Cb=a[Q]&1,zb=(za<<4)+Jb|0,Eb=(za<<4)+Jb+8|0;zf(da,(a[b>>2]=a[zb>>2],a[b+4>>2]=a[zb+4>>2],f[b>>3]),(a[b>>2]=a[Eb>>2],a[b+4>>2]=a[Eb+4>>2],f[b>>3]),ab,lb,Cb);m=wb>>2;a[m]=a[J];a[m+1]=a[J+1];a[m+2]=a[J+2];a[m+3]=a[J+3];a[H]=a[J];a[H+1]=a[J+1];a[H+2]=a[J+2];a[H+3]=a[J+3];var Db=za+1|0;if((Db|0)>=(a[y]|0)){break}var Hb=(Db<<4)+a[x]|0,Ib=a[w],Mb=a[Q]&1,Lb=(Db<<4)+Ib|0,Pb=(Db<<4)+Ib+8|0;zf(ea,(a[b>>2]=a[Lb>>2],a[b+4>>2]=a[Lb+4>>2],f[b>>3]),(a[b>>2]=a[Pb>>2],a[b+4>>2]=a[Pb+4>>2],f[b>>3]),ab,lb,Mb);q=Hb>>2;a[q]=a[I];a[q+1]=a[I+1];a[q+2]=a[I+2];a[q+3]=a[I+3];a[G]=a[I];a[G+1]=a[I+1];a[G+2]=a[I+2];a[G+3]=a[I+3];var Ub=za+2|0,Sb=(Ub<<4)+a[x]|0,Qb=a[w],ac=a[Q]&1,Zb=(Ub<<4)+Qb|0,$b=(Ub<<4)+Qb+8|0;zf($,(a[b>>2]=a[Zb>>2],a[b+4>>2]=a[Zb+4>>2],f[b>>3]),(a[b>>2]=a[$b>>2],a[b+4>>2]=a[$b+4>>2],f[b>>3]),ab,lb,ac);i=Sb>>2;a[i]=a[E];a[i+1]=a[E+1];a[i+2]=a[E+2];a[i+3]=a[E+3];a[C]=a[E];a[C+1]=a[E+1];a[C+2]=a[E+2];a[C+3]=a[E+3];var Xb=za+3|0,bc=a[w],ec=a[Q]&1,cc=(Xb<<4)+bc|0,dc=(Xb<<4)+bc+8|0;zf(ca,(a[b>>2]=a[cc>>2],a[b+4>>2]=a[cc+4>>2],f[b>>3]),(a[b>>2]=a[dc>>2],a[b+4>>2]=a[dc+4>>2],f[b>>3]),ab,lb,ec);a[D]=a[A];a[D+1]=a[A+1];a[D+2]=a[A+2];a[D+3]=a[A+3];Cg(ob,db);za=Xb}k=(sb+108|0)>>2;var fc=a[k];if(0!=(fc|0)){var gc=a[z+27],jc=a[Q]&1,Vb=gc+56|0,Yb=gc+64|0;zf(V,(a[b>>2]=a[Vb>>2],a[b+4>>2]=a[Vb+4>>2],f[b>>3]),(a[b>>2]=a[Yb>>2],a[b+4>>2]=a[Yb+4>>2],f[b>>3]),ab,lb,jc);j=(fc+56|0)>>2;a[j]=a[B];a[j+1]=a[B+1];a[j+2]=a[B+2];a[j+3]=a[B+3];n[a[k]+81|0]=1;Mg(pb,a[k])}}}while(0);var ic=ub+1|0;if((ic|0)==(g|0)){break}else{ub=ic}}var lc=ga;a[1345515]=a[1330507];a[1345497]=a[1330506];a[1345496]=a[1330505];a[1345491]=a[1330504];a[1345499]=a[1330503];a[1345360]=a[1330502];a[1345163]=a[1330501];jl(lc);Pe(lc);h=Y;return}}while(0);ll(l,e,c,d,g,p);h=Y}function br(c,d,g,e){var l,p,j,k,i,q,m,w,x,v,t=h;h=h+1540|0;for(var y=t+696,z=t+1392,B=t+1396,A=t+1508,D=t+1524,C=a[g+16>>2],E=g+12|0,G=a[E>>2],I=a[C+20>>2],H=a[g+180>>2];;){var J=a[H+180>>2];if(0==(J|0)){break}else{H=J}}var K=a[H+16>>2];v=(g+108|0)>>2;var M=K+32|0;x=(a[v]+56|0)>>2;w=M>>2;a[x]=a[w];a[x+1]=a[w+1];a[x+2]=a[w+2];a[x+3]=a[w+3];n[a[v]+81|0]=1;do{if(2==(e|0)){var L=C+32|0,N=(a[b>>2]=a[L>>2],a[b+4>>2]=a[L+4>>2],f[b>>3]),Q=C+40|0,P=(a[b>>2]=a[Q>>2],a[b+4>>2]=a[Q+4>>2],f[b>>3]),R=g+28|0,Y=g+36|0;Zd(A,N,P,(a[b>>2]=a[R>>2],a[b+4>>2]=a[R+4>>2],f[b>>3]),(a[b>>2]=a[Y>>2],a[b+4>>2]=a[Y+4>>2],f[b>>3]));var U=A|0,aa=(a[b>>2]=a[U>>2],a[b+4>>2]=a[U+4>>2],f[b>>3]),da=A+8|0,ea=(a[b>>2]=a[da>>2],a[b+4>>2]=a[da+4>>2],f[b>>3]),$=G+32|0,ca=(a[b>>2]=a[$>>2],a[b+4>>2]=a[$+4>>2],f[b>>3]),V=G+40|0,W=(a[b>>2]=a[V>>2],a[b+4>>2]=a[V+4>>2],f[b>>3]),X=g+68|0,ba=g+76|0;Zd(D,ca,W,(a[b>>2]=a[X>>2],a[b+4>>2]=a[X+4>>2],f[b>>3]),(a[b>>2]=a[ba>>2],a[b+4>>2]=a[ba+4>>2],f[b>>3]));var ma=D|0,fa=(a[b>>2]=a[ma>>2],a[b+4>>2]=a[ma+4>>2],f[b>>3]),ia=D+8|0,ha=(a[b>>2]=a[ia>>2],a[b+4>>2]=a[ia+4>>2],f[b>>3]),O=a[v],ga=O+56|0,sa=(a[b>>2]=a[ga>>2],a[b+4>>2]=a[ga+4>>2],f[b>>3]),qa=O+64|0,ua=O+32|0,Da=(a[b>>2]=a[qa>>2],a[b+4>>2]=a[qa+4>>2],f[b>>3])-.5*(a[b>>2]=a[ua>>2],a[b+4>>2]=a[ua+4>>2],f[b>>3]),na=B+16|0,ta=B|0,ra=B|0;f[b>>3]=aa;a[ra>>2]=a[b>>2];a[ra+4>>2]=a[b+4>>2];var xa=B+8|0;f[b>>3]=ea;a[xa>>2]=a[b>>2];a[xa+4>>2]=a[b+4>>2];m=na>>2;q=B>>2;a[m]=a[q];a[m+1]=a[q+1];a[m+2]=a[q+2];a[m+3]=a[q+3];var ya=B+32|0,ja=B+48|0,la=B+64|0,va=la|0;f[b>>3]=sa;a[va>>2]=a[b>>2];a[va+4>>2]=a[b+4>>2];var oa=B+72|0;f[b>>3]=Da;a[oa>>2]=a[b>>2];a[oa+4>>2]=a[b+4>>2];i=ja>>2;k=la>>2;a[i]=a[k];a[i+1]=a[k+1];a[i+2]=a[k+2];a[i+3]=a[k+3];j=ya>>2;a[j]=a[k];a[j+1]=a[k+1];a[j+2]=a[k+2];a[j+3]=a[k+3];var ka=B+80|0,Ea=B+96|0,Ka=Ea|0;f[b>>3]=fa;a[Ka>>2]=a[b>>2];a[Ka+4>>2]=a[b+4>>2];var Na=B+104|0;f[b>>3]=ha;a[Na>>2]=a[b>>2];a[Na+4>>2]=a[b+4>>2];p=ka>>2;l=Ea>>2;a[p]=a[l];a[p+1]=a[l+1];a[p+2]=a[l+2];a[p+3]=a[l+3];a[z>>2]=7;var Ba=ta,Wa=7}else{var Ha=M|0,Oa=(a[b>>2]=a[Ha>>2],a[b+4>>2]=a[Ha+4>>2],f[b>>3]),Ra=K+104|0,bb=Oa-(a[b>>2]=a[Ra>>2],a[b+4>>2]=a[Ra+4>>2],f[b>>3]),Xa=K+112|0,Sa=Oa+(a[b>>2]=a[Xa>>2],a[b+4>>2]=a[Xa+4>>2],f[b>>3]),Qa=K+40|0,Va=(a[b>>2]=a[Qa>>2],a[b+4>>2]=a[Qa+4>>2],f[b>>3]),Ta=K+96|0,Aa=Va+.5*(a[b>>2]=a[Ta>>2],a[b+4>>2]=a[Ta+4>>2],f[b>>3]),fb=a[C+236>>2],Ca=a[I+220>>2],Ya=C+40|0,$a=(Va-(a[Ca+(44*fb&-1)+16>>2]|0)-(a[b>>2]=a[Ya>>2],a[b+4>>2]=a[Ya+4>>2],f[b>>3])+a[Ca+(44*fb&-1)+20>>2]&-1|0)/6&-1,La=Aa-(5>($a|0)?5:$a|0);jh(c,d,C,g,t,1);jh(c,d,G,g,y,0);var pa=t+52|0,Ga=a[pa>>2],Fa=Ga-1|0,Pa=(Fa<<5)+t+56|0,nb=(a[b>>2]=a[Pa>>2],a[b+4>>2]=a[Pa+4>>2],f[b>>3]);f[b>>3]=nb;a[1322499]=a[b>>2];a[1322500]=a[b+4>>2];var jb=(Fa<<5)+t+80|0,cb=(a[b>>2]=a[jb>>2],a[b+4>>2]=a[jb+4>>2],f[b>>3]);f[b>>3]=cb;a[1322501]=a[b>>2];a[1322502]=a[b+4>>2];f[b>>3]=bb;a[1322503]=a[b>>2];a[1322504]=a[b+4>>2];f[b>>3]=La;a[1322505]=a[b>>2];a[1322506]=a[b+4>>2];f[b>>3]=nb;a[1322507]=a[b>>2];a[1322508]=a[b+4>>2];f[b>>3]=La;a[1322509]=a[b>>2];a[1322510]=a[b+4>>2];var Za=y+52|0,kb=a[Za>>2]-1|0,eb=(kb<<5)+y+72|0,Ma=(a[b>>2]=a[eb>>2],a[b+4>>2]=a[eb+4>>2],f[b>>3]);f[b>>3]=Ma;a[1322511]=a[b>>2];a[1322512]=a[b+4>>2];f[b>>3]=Aa;a[1322513]=a[b>>2];a[1322514]=a[b+4>>2];f[b>>3]=Sa;a[1322515]=a[b>>2];a[1322516]=a[b+4>>2];f[b>>3]=La;a[1322521]=a[b>>2];a[1322522]=a[b+4>>2];var hb=(kb<<5)+y+80|0,lb=(a[b>>2]=a[hb>>2],a[b+4>>2]=a[hb+4>>2],f[b>>3]);f[b>>3]=lb;a[1322517]=a[b>>2];a[1322518]=a[b+4>>2];f[b>>3]=Ma;a[1322519]=a[b>>2];a[1322520]=a[b+4>>2];a:do{if(0<(Ga|0)){for(var rb=0;;){vc(d,(rb<<5)+t+56|0);var ab=rb+1|0;if((ab|0)<(a[pa>>2]|0)){rb=ab}else{break a}}}}while(0);vc(d,5289996);vc(d,5290028);vc(d,5290060);var db=a[Za>>2];a:do{if(0<(db|0)){for(var ob=db;;){var pb=ob-1|0;vc(d,(pb<<5)+y+56|0);if(0<(pb|0)){ob=pb}else{break a}}}}while(0);var ub=8==(e|0)?le(d,z,0):le(d,z,1),gb=a[z>>2];if(0!=(gb|0)){Ba=ub,Wa=gb}else{h=t;return}}}while(0);Nd(g,a[E>>2],Ba,Wa);h=t}function ll(c,d,g,e,l,p){var j,k,i,q,m,n,x,v,t,y,z,B,A,D,C=h;h=h+320|0;var E=C+160,G=C+176,I=C+192,H=C+208,J=C+224,K=C+240,M=C+256,L=C+272,N=C+288,Q=C+304,P=a[g+(e<<2)>>2],R=c+32|0,R=(a[b>>2]=a[R>>2],a[b+4>>2]=a[R+4>>2],f[b>>3]);q=c+40|0;q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);m=P+28|0;n=P+36|0;Zd(E,R,q,(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]));R=E|0;R=(a[b>>2]=a[R>>2],a[b+4>>2]=a[R+4>>2],f[b>>3]);E=E+8|0;E=(a[b>>2]=a[E>>2],a[b+4>>2]=a[E+4>>2],f[b>>3]);q=d+32|0;q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]);d=d+40|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);m=P+68|0;P=P+76|0;Zd(G,q,d,(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),(a[b>>2]=a[P>>2],a[b+4>>2]=a[P+4>>2],f[b>>3]));P=G|0;P=(a[b>>2]=a[P>>2],a[b+4>>2]=a[P+4>>2],f[b>>3]);G=G+8|0;G=(a[b>>2]=a[G>>2],a[b+4>>2]=a[G+4>>2],f[b>>3]);if(1<(l|0)){var c=c+96|0,d=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),c=d/(l-1|0),Y=.5*d}else{if(0<(l|0)){Y=c=0}else{h=C;return}}var U=C|0,aa=C+8|0;j=C+16|0;var da=j|0,ea=C+24|0,$=(2*R+P)/3;D=(C+32|0)>>2;A=J>>2;B=(C+48|0)>>2;z=K>>2;y=(C+64|0)>>2;t=M>>2;var ca=(2*P+R)/3;v=(C+80|0)>>2;x=L>>2;n=(C+96|0)>>2;m=N>>2;q=(C+112|0)>>2;var d=Q>>2,V=C+128|0,W=C+136|0,X=C+144|0,ba=C+152|0,ma=C|0;i=j>>2;k=I>>2;j=H>>2;for(var fa=C+48|0,ia=C+56|0,ha=0,Y=E-Y;;){var O=a[g+(ha+e<<2)>>2];f[b>>3]=R;a[U>>2]=a[b>>2];a[U+4>>2]=a[b+4>>2];f[b>>3]=E;a[aa>>2]=a[b>>2];a[aa+4>>2]=a[b+4>>2];if(8==(p|0)|2==(p|0)){ef(I,$,Y);a[i]=a[k];a[i+1]=a[k+1];a[i+2]=a[k+2];a[i+3]=a[k+3];ef(H,ca,Y);a[D]=a[j];a[D+1]=a[j+1];a[D+2]=a[j+2];a[D+3]=a[j+3];f[b>>3]=P;a[fa>>2]=a[b>>2];a[fa+4>>2]=a[b+4>>2];f[b>>3]=G;a[ia>>2]=a[b>>2];a[ia+4>>2]=a[b+4>>2];var ga=4}else{f[b>>3]=R,a[da>>2]=a[b>>2],a[da+4>>2]=a[b+4>>2],f[b>>3]=E,a[ea>>2]=a[b>>2],a[ea+4>>2]=a[b+4>>2],ef(J,$,Y),a[D]=a[A],a[D+1]=a[A+1],a[D+2]=a[A+2],a[D+3]=a[A+3],ef(K,$,Y),a[B]=a[z],a[B+1]=a[z+1],a[B+2]=a[z+2],a[B+3]=a[z+3],ef(M,$,Y),a[y]=a[t],a[y+1]=a[t+1],a[y+2]=a[t+2],a[y+3]=a[t+3],ef(L,ca,Y),a[v]=a[x],a[v+1]=a[x+1],a[v+2]=a[x+2],a[v+3]=a[x+3],ef(N,ca,Y),a[n]=a[m],a[n+1]=a[m+1],a[n+2]=a[m+2],a[n+3]=a[m+3],ef(Q,ca,Y),a[q]=a[d],a[q+1]=a[d+1],a[q+2]=a[d+2],a[q+3]=a[d+3],f[b>>3]=P,a[V>>2]=a[b>>2],a[V+4>>2]=a[b+4>>2],f[b>>3]=G,a[W>>2]=a[b>>2],a[W+4>>2]=a[b+4>>2],f[b>>3]=P,a[X>>2]=a[b>>2],a[X+4>>2]=a[b+4>>2],f[b>>3]=G,a[ba>>2]=a[b>>2],a[ba+4>>2]=a[b+4>>2],ga=10}Nd(O,a[O+12>>2],ma,ga);ha=ha+1|0;if((ha|0)==(l|0)){break}else{Y+=c}}h=C}function ef(c,d,g){var e=c|0;f[b>>3]=d;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=g;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function cr(c,d,g,e,l,p,j){var k,i=0,q=h;h=h+1396|0;var m=q+4,n=q+700,x=a[p+16>>2],v=a[p+12>>2];k=a[x+20>>2];var t=a[x+236>>2];if((t|0)<(C[k+246>>1]<<16>>16|0)){k=a[k+220>>2]>>2;var y=t+1|0,z=x+40|0,B=a[a[((44*y&-1)+4>>2)+k]>>2]+40|0;k=(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3])-(a[((44*t&-1)+24>>2)+k]|0)-((a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3])+(a[((44*y&-1)+28>>2)+k]|0))}else{k=a[k+260>>2]|0}y=l+1|0;t=(a[c+12>>2]|0)/y;k/=y;ul(c,d,x,p,m,1);ul(c,d,v,p,n,0);c=m+52|0;p=n+52|0;j=0==(j|0);x=d+80|0;for(z=0;;){if((z|0)>=(l|0)){i=1179;break}var v=a[g+(z+e<<2)>>2],y=a[c>>2],B=y-1|0,A=(B<<5)+m+56|0,A=(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]),D=(B<<5)+m+64|0,D=(a[b>>2]=a[D>>2],a[b+4>>2]=a[D+4>>2],f[b>>3]),B=(B<<5)+m+72|0,E=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]);f[b>>3]=A;a[1322499]=a[b>>2];a[1322500]=a[b+4>>2];f[b>>3]=D;a[1322505]=a[b>>2];a[1322506]=a[b+4>>2];var z=z+1|0,G=z|0,B=G*t;f[b>>3]=E+B;a[1322503]=a[b>>2];a[1322504]=a[b+4>>2];D-=G*k;f[b>>3]=D;a[1322501]=a[b>>2];a[1322502]=a[b+4>>2];f[b>>3]=A;a[1322507]=a[b>>2];a[1322508]=a[b+4>>2];f[b>>3]=D;a[1322513]=a[b>>2];a[1322514]=a[b+4>>2];E=a[p>>2]-1|0;A=(E<<5)+n+72|0;A=(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]);f[b>>3]=A;a[1322511]=a[b>>2];a[1322512]=a[b+4>>2];f[b>>3]=D-k;a[1322509]=a[b>>2];a[1322510]=a[b+4>>2];G=(E<<5)+n+56|0;G=(a[b>>2]=a[G>>2],a[b+4>>2]=a[G+4>>2],f[b>>3]);E=(E<<5)+n+64|0;E=(a[b>>2]=a[E>>2],a[b+4>>2]=a[E+4>>2],f[b>>3]);f[b>>3]=A;a[1322519]=a[b>>2];a[1322520]=a[b+4>>2];f[b>>3]=E;a[1322521]=a[b>>2];a[1322522]=a[b+4>>2];f[b>>3]=G-B;a[1322515]=a[b>>2];a[1322516]=a[b+4>>2];f[b>>3]=D;a[1322517]=a[b>>2];a[1322518]=a[b+4>>2];a:do{if(0<(y|0)){for(B=0;;){if(vc(d,(B<<5)+m+56|0),B=B+1|0,(B|0)>=(a[c>>2]|0)){break a}}}}while(0);vc(d,5289996);vc(d,5290028);vc(d,5290060);y=a[p>>2];a:do{if(0<(y|0)){for(B=y;;){if(B=B-1|0,vc(d,(B<<5)+n+56|0),0>=(B|0)){break a}}}}while(0);y=j?le(d,q,1):le(d,q,0);B=a[q>>2];if(0==(B|0)){i=1178;break}Nd(v,a[v+12>>2],y,B);a[x>>2]=0}1178==i?h=q:1179==i&&(h=q)}function jh(c,d,g,e,l,p){var j,k=h;h=h+96|0;j=k+32;var i=k+64,q=a[g+20>>2];Xe(j,c,g,0,e);c=l>>2;j>>=2;a[c]=a[j];a[c+1]=a[j+1];a[c+2]=a[j+2];a[c+3]=a[j+3];a[c+4]=a[j+4];a[c+5]=a[j+5];a[c+6]=a[j+6];a[c+7]=a[j+7];c=k>>2;a[c]=a[j];a[c+1]=a[j+1];a[c+2]=a[j+2];a[c+3]=a[j+3];a[c+4]=a[j+4];a[c+5]=a[j+5];a[c+6]=a[j+6];a[c+7]=a[j+7];a[l+48>>2]=4;0==p<<24>>24?Ug(d,e,2,l,0):Tg(d,e,2,l,0);d=(l+52|0)>>2;p=a[d]-1|0;e=(p<<5)+l+80|0;j=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);e=(k+24|0)>>2;f[b>>3]=j;a[e]=a[b>>2];a[e+1]=a[b+4>>2];p=(p<<5)+l+64|0;j=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);p=(k+8|0)>>2;f[b>>3]=j;a[p]=a[b>>2];a[p+1]=a[b+4>>2];j=g+40|0;yf(i,k,4,(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])+a[a[q+220>>2]+(44*a[g+236>>2]&-1)+20>>2]&-1);g=i>>2;a[c]=a[g];a[c+1]=a[g+1];a[c+2]=a[g+2];a[c+3]=a[g+3];a[c+4]=a[g+4];a[c+5]=a[g+5];a[c+6]=a[g+6];a[c+7]=a[g+7];g=k|0;i=k+16|0;if((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])<(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3])){if((a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])<(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])){g=a[d],a[d]=g+1|0,l=((g<<5)+l+56|0)>>2,a[l]=a[c],a[l+1]=a[c+1],a[l+2]=a[c+2],a[l+3]=a[c+3],a[l+4]=a[c+4],a[l+5]=a[c+5],a[l+6]=a[c+6],a[l+7]=a[c+7]}}h=k}function ul(c,d,g,e,l,p){var j,k=h;h=h+96|0;j=k+32;var i=k+64,q=a[g+20>>2];Xe(j,c,g,0,e);c=l>>2;j>>=2;a[c]=a[j];a[c+1]=a[j+1];a[c+2]=a[j+2];a[c+3]=a[j+3];a[c+4]=a[j+4];a[c+5]=a[j+5];a[c+6]=a[j+6];a[c+7]=a[j+7];c=k>>2;a[c]=a[j];a[c+1]=a[j+1];a[c+2]=a[j+2];a[c+3]=a[j+3];a[c+4]=a[j+4];a[c+5]=a[j+5];a[c+6]=a[j+6];a[c+7]=a[j+7];a[l+48>>2]=1;0==p<<24>>24?Ug(d,e,2,l,0):Tg(d,e,2,l,0);d=(l+52|0)>>2;p=a[d]-1|0;e=(p<<5)+l+80|0;j=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);e=(k+24|0)>>2;f[b>>3]=j;a[e]=a[b>>2];a[e+1]=a[b+4>>2];p=(p<<5)+l+64|0;j=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);p=(k+8|0)>>2;f[b>>3]=j;a[p]=a[b>>2];a[p+1]=a[b+4>>2];j=g+40|0;yf(i,k,1,(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])-a[a[q+220>>2]+(44*a[g+236>>2]&-1)+20>>2]&-1);g=i>>2;a[c]=a[g];a[c+1]=a[g+1];a[c+2]=a[g+2];a[c+3]=a[g+3];a[c+4]=a[g+4];a[c+5]=a[g+5];a[c+6]=a[g+6];a[c+7]=a[g+7];g=k|0;i=k+16|0;if((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])<(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3])){if((a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])<(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])){g=a[d],a[d]=g+1|0,l=((g<<5)+l+56|0)>>2,a[l]=a[c],a[l+1]=a[c+1],a[l+2]=a[c+2],a[l+3]=a[c+3],a[l+4]=a[c+4],a[l+5]=a[c+5],a[l+6]=a[c+6],a[l+7]=a[c+7]}}h=k}function kr(c,d,g,e,l,p,j){var k,i,q,m,w,x,v,t,y,z,B,A,C,G,H,J,I,Z,T=0,K=h;h=h+196|0;var M=K+4,L=K+164,P=K+180,N=a[g+(e<<2)>>2],Q=da(l<<2);a:do{if(0<(l|0)){for(var R=0;;){a[Q+(R<<2)>>2]=a[g+(R+e<<2)>>2];var Y=R+1|0;if((Y|0)==(l|0)){break a}else{R=Y}}}}while(0);af(Q,l,334);var U=c+32|0,aa=(a[b>>2]=a[U>>2],a[b+4>>2]=a[U+4>>2],f[b>>3]),$=c+40|0,ea=(a[b>>2]=a[$>>2],a[b+4>>2]=a[$+4>>2],f[b>>3]),ca=N+28|0,fa=N+36|0;Zd(L,aa,ea,(a[b>>2]=a[ca>>2],a[b+4>>2]=a[ca+4>>2],f[b>>3]),(a[b>>2]=a[fa>>2],a[b+4>>2]=a[fa+4>>2],f[b>>3]));var V=L|0,W=(a[b>>2]=a[V>>2],a[b+4>>2]=a[V+4>>2],f[b>>3]),X=L+8|0,ba=(a[b>>2]=a[X>>2],a[b+4>>2]=a[X+4>>2],f[b>>3]),ma=d+32|0,ia=(a[b>>2]=a[ma>>2],a[b+4>>2]=a[ma+4>>2],f[b>>3]),ha=d+40|0,sa=(a[b>>2]=a[ha>>2],a[b+4>>2]=a[ha+4>>2],f[b>>3]),O=N+68|0,ga=N+76|0;Zd(P,ia,sa,(a[b>>2]=a[O>>2],a[b+4>>2]=a[O+4>>2],f[b>>3]),(a[b>>2]=a[ga>>2],a[b+4>>2]=a[ga+4>>2],f[b>>3]));var qa=P|0,na=(a[b>>2]=a[qa>>2],a[b+4>>2]=a[qa+4>>2],f[b>>3]),ua=P+8|0,Da=(a[b>>2]=a[ua>>2],a[b+4>>2]=a[ua+4>>2],f[b>>3]),ta=c+112|0,xa=W+(a[b>>2]=a[ta>>2],a[b+4>>2]=a[ta+4>>2],f[b>>3]),ra=d+104|0,Ha=na-(a[b>>2]=a[ra>>2],a[b+4>>2]=a[ra+4>>2],f[b>>3]),ya=.5*(xa+Ha);Z=(M|0)>>2;f[b>>3]=W;a[Z]=a[b>>2];a[Z+1]=a[b+4>>2];I=(M+8|0)>>2;f[b>>3]=ba;a[I]=a[b>>2];a[I+1]=a[b+4>>2];J=(M+16|0)>>2;f[b>>3]=W;a[J]=a[b>>2];a[J+1]=a[b+4>>2];H=(M+24|0)>>2;f[b>>3]=ba;a[H]=a[b>>2];a[H+1]=a[b+4>>2];G=(M+32|0)>>2;f[b>>3]=na;a[G]=a[b>>2];a[G+1]=a[b+4>>2];C=(M+40|0)>>2;f[b>>3]=Da;a[C]=a[b>>2];a[C+1]=a[b+4>>2];A=(M+48|0)>>2;f[b>>3]=na;a[A]=a[b>>2];a[A+1]=a[b+4>>2];B=(M+56|0)>>2;f[b>>3]=Da;a[B]=a[b>>2];a[B+1]=a[b+4>>2];var ja=M|0;Nd(N,a[N+12>>2],ja,4);z=(N+108|0)>>2;var la=a[z]+56|0;f[b>>3]=ya;a[la>>2]=a[b>>2];a[la+4>>2]=a[b+4>>2];var va=a[z],oa=va+32|0,ka=ba+.5*((a[b>>2]=a[oa>>2],a[b+4>>2]=a[oa+4>>2],f[b>>3])+6),Ea=va+64|0;f[b>>3]=ka;a[Ea>>2]=a[b>>2];a[Ea+4>>2]=a[b+4>>2];n[a[z]+81|0]=1;var Ka=ba+3,Na=a[z],Ba=Na+32|0,Wa=Ka+(a[b>>2]=a[Ba>>2],a[b+4>>2]=a[Ba+4>>2],f[b>>3]),Oa=Na+24|0,Qa=.5*(a[b>>2]=a[Oa>>2],a[b+4>>2]=a[Oa+4>>2],f[b>>3]),Ra=ya-Qa,bb=ya+Qa;y=(M+64|0)>>2;t=(M+72|0)>>2;v=(M+80|0)>>2;x=(M+88|0)>>2;w=(M+96|0)>>2;m=(M+104|0)>>2;q=(M+112|0)>>2;i=(M+120|0)>>2;for(var Xa=4==(p|0)&1,Sa=Wa,Pa=Ka,Va=1;;){var Ta,Aa;if((Va|0)>=(j|0)){break}var fb=a[g+(Va+e<<2)>>2];if(0==(Va&1|0)){f[b>>3]=W;a[Z]=a[b>>2];a[Z+1]=a[b+4>>2];f[b>>3]=ba;a[I]=a[b>>2];a[I+1]=a[b+4>>2];f[b>>3]=Ra;a[J]=a[b>>2];a[J+1]=a[b+4>>2];f[b>>3]=ba;a[H]=a[b>>2];a[H+1]=a[b+4>>2];f[b>>3]=Ra;a[G]=a[b>>2];a[G+1]=a[b+4>>2];f[b>>3]=Sa;a[C]=a[b>>2];a[C+1]=a[b+4>>2];f[b>>3]=bb;a[A]=a[b>>2];a[A+1]=a[b+4>>2];f[b>>3]=Sa;a[B]=a[b>>2];a[B+1]=a[b+4>>2];f[b>>3]=bb;a[y]=a[b>>2];a[y+1]=a[b+4>>2];f[b>>3]=Da;a[t]=a[b>>2];a[t+1]=a[b+4>>2];f[b>>3]=na;a[v]=a[b>>2];a[v+1]=a[b+4>>2];f[b>>3]=Da;a[x]=a[b>>2];a[x+1]=a[b+4>>2];f[b>>3]=na;a[w]=a[b>>2];a[w+1]=a[b+4>>2];var Ca=Sa+6;f[b>>3]=Ca;a[m]=a[b>>2];a[m+1]=a[b+4>>2];f[b>>3]=W;a[q]=a[b>>2];a[q+1]=a[b+4>>2];f[b>>3]=Ca;a[i]=a[b>>2];a[i+1]=a[b+4>>2];var Ya=a[fb+108>>2]+32|0,$a=(a[b>>2]=a[Ya>>2],a[b+4>>2]=a[Ya+4>>2],f[b>>3]),La=Aa,pa=Ta,Ga=Sa+($a+6),Fa=Pa,Za=Sa+.5*$a+6}else{var nb=fb+108|0,jb=a[nb>>2];if(1==(Va|0)){var cb=jb+24|0,eb=.5*(a[b>>2]=a[cb>>2],a[b+4>>2]=a[cb+4>>2],f[b>>3]),kb=ya+eb,hb=ya-eb}else{kb=Aa,hb=Ta}var Ma=jb+32|0,mb=Pa-((a[b>>2]=a[Ma>>2],a[b+4>>2]=a[Ma+4>>2],f[b>>3])+6);f[b>>3]=W;a[Z]=a[b>>2];a[Z+1]=a[b+4>>2];f[b>>3]=ba;a[I]=a[b>>2];a[I+1]=a[b+4>>2];f[b>>3]=W;a[J]=a[b>>2];a[J+1]=a[b+4>>2];var lb=mb-6;f[b>>3]=lb;a[H]=a[b>>2];a[H+1]=a[b+4>>2];f[b>>3]=na;a[G]=a[b>>2];a[G+1]=a[b+4>>2];f[b>>3]=lb;a[C]=a[b>>2];a[C+1]=a[b+4>>2];f[b>>3]=na;a[A]=a[b>>2];a[A+1]=a[b+4>>2];f[b>>3]=Da;a[B]=a[b>>2];a[B+1]=a[b+4>>2];f[b>>3]=kb;a[y]=a[b>>2];a[y+1]=a[b+4>>2];f[b>>3]=Da;a[t]=a[b>>2];a[t+1]=a[b+4>>2];f[b>>3]=kb;a[v]=a[b>>2];a[v+1]=a[b+4>>2];f[b>>3]=mb;a[x]=a[b>>2];a[x+1]=a[b+4>>2];f[b>>3]=hb;a[w]=a[b>>2];a[w+1]=a[b+4>>2];f[b>>3]=mb;a[m]=a[b>>2];a[m+1]=a[b+4>>2];f[b>>3]=hb;a[q]=a[b>>2];a[q+1]=a[b+4>>2];f[b>>3]=ba;a[i]=a[b>>2];a[i+1]=a[b+4>>2];var rb=a[nb>>2]+32|0,La=kb,pa=hb,Ga=Sa,Fa=mb,Za=mb+.5*(a[b>>2]=a[rb>>2],a[b+4>>2]=a[rb+4>>2],f[b>>3])}var ab=Wj(W,ba,na,Da,ja,K,Xa),db=a[K>>2];if(0==(db|0)){T=1220;break}k=(fb+108|0)>>2;var ob=a[k]+56|0;f[b>>3]=ya;a[ob>>2]=a[b>>2];a[ob+4>>2]=a[b+4>>2];var pb=a[k]+64|0;f[b>>3]=Za;a[pb>>2]=a[b>>2];a[pb+4>>2]=a[b+4>>2];n[a[k]+81|0]=1;Nd(fb,a[fb+12>>2],ab,db);Aa=La;Ta=pa;Sa=Ga;Pa=Fa;Va=Va+1|0}if(1220!=T){for(var ub=(2*xa+Ha)/3,gb=(xa+2*Ha)/3,sb=Aa,Ia=Ta,vb=Sa,Ua=Pa,tb=Va;(tb|0)<(l|0);){var zb=a[g+(tb+e<<2)>>2];if(0==(tb&1|0)){f[b>>3]=W;a[Z]=a[b>>2];a[Z+1]=a[b+4>>2];f[b>>3]=ba;a[I]=a[b>>2];a[I+1]=a[b+4>>2];f[b>>3]=Ra;a[J]=a[b>>2];a[J+1]=a[b+4>>2];f[b>>3]=ba;a[H]=a[b>>2];a[H+1]=a[b+4>>2];f[b>>3]=Ra;a[G]=a[b>>2];a[G+1]=a[b+4>>2];f[b>>3]=vb;a[C]=a[b>>2];a[C+1]=a[b+4>>2];f[b>>3]=bb;a[A]=a[b>>2];a[A+1]=a[b+4>>2];f[b>>3]=vb;a[B]=a[b>>2];a[B+1]=a[b+4>>2];f[b>>3]=bb;a[y]=a[b>>2];a[y+1]=a[b+4>>2];f[b>>3]=Da;a[t]=a[b>>2];a[t+1]=a[b+4>>2];f[b>>3]=na;a[v]=a[b>>2];a[v+1]=a[b+4>>2];f[b>>3]=Da;a[x]=a[b>>2];a[x+1]=a[b+4>>2];f[b>>3]=na;a[w]=a[b>>2];a[w+1]=a[b+4>>2];var qb=vb+6,Bb=sb,wb=Ia,xb=qb,za=Ua,Cb=qb,Db=W,Eb=qb}else{var Ib=1==(tb|0),Hb=Ib?ub:Ia,Mb=Ib?gb:sb,Lb=Ua-6;f[b>>3]=W;a[Z]=a[b>>2];a[Z+1]=a[b+4>>2];f[b>>3]=ba;a[I]=a[b>>2];a[I+1]=a[b+4>>2];f[b>>3]=W;a[J]=a[b>>2];a[J+1]=a[b+4>>2];var Pb=Lb-6;f[b>>3]=Pb;a[H]=a[b>>2];a[H+1]=a[b+4>>2];f[b>>3]=na;a[G]=a[b>>2];a[G+1]=a[b+4>>2];f[b>>3]=Pb;a[C]=a[b>>2];a[C+1]=a[b+4>>2];f[b>>3]=na;a[A]=a[b>>2];a[A+1]=a[b+4>>2];f[b>>3]=Da;a[B]=a[b>>2];a[B+1]=a[b+4>>2];f[b>>3]=Mb;a[y]=a[b>>2];a[y+1]=a[b+4>>2];f[b>>3]=Da;a[t]=a[b>>2];a[t+1]=a[b+4>>2];f[b>>3]=Mb;a[v]=a[b>>2];a[v+1]=a[b+4>>2];f[b>>3]=Lb;a[x]=a[b>>2];a[x+1]=a[b+4>>2];f[b>>3]=Hb;a[w]=a[b>>2];a[w+1]=a[b+4>>2];Bb=Mb;wb=Hb;xb=vb;za=Lb;Cb=ba;Db=Hb;Eb=Lb}f[b>>3]=Eb;a[m]=a[b>>2];a[m+1]=a[b+4>>2];f[b>>3]=Db;a[q]=a[b>>2];a[q+1]=a[b+4>>2];f[b>>3]=Cb;a[i]=a[b>>2];a[i+1]=a[b+4>>2];var Sb=Wj(W,ba,na,Da,ja,K,Xa),Qb=a[K>>2];if(0==(Qb|0)){T=1221;break}Nd(zb,a[zb+12>>2],Sb,Qb);sb=Bb;Ia=wb;vb=xb;Ua=za;tb=tb+1|0}1221!=T&&E(Q)}h=K}function lr(c){var d,g=Bh(5329616,a[c>>2]>>>4&1);mi(g,5373028,5338228);var e=da(96),l=g+44|0;d=l>>2;a[l>>2]=e;var h=c+44|0,j=a[h>>2]|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);f[b>>3]=j;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];e=a[h>>2]+24|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);h=a[l>>2]+24|0;f[b>>3]=e;a[h>>2]=a[b>>2];a[h+4>>2]=a[b+4>>2];n[l+107|0]=n[c+151|0];a[d+27]=a[c+152>>2]&1^1;a[d+53]=a[c+256>>2];a[d+54]=a[c+260>>2];c=c+32|0;l=a[a[c>>2]+16>>2];e=a[a[l+4>>2]+8>>2];d=a[e>>2];if(0==(d|0)){c=l}else{for(l=e;!(l=l+4|0,Nf(g,a[d>>2],a[d+4>>2]),d=a[l>>2],0==(d|0));){}c=a[a[c>>2]+16>>2]}c=a[a[c+8>>2]+8>>2];d=a[c>>2];a:do{if(0!=(d|0)){l=c;for(e=d;;){if(l=l+4|0,wf(g,a[e>>2],a[e+4>>2]),e=a[l>>2],0==(e|0)){break a}}}}while(0);c=(g+40|0)>>2;0==(Q(a[a[c]+4>>2]|0,5377776)|0)&&wf(g,5377776,5338228);0==(Q(a[a[c]+4>>2]|0,5375068)|0)&&wf(g,5375068,5338228);a[1330507]=a[1345515];a[1330506]=a[1345497];a[1330505]=a[1345496];a[1330504]=a[1345491];a[1330503]=a[1345499];a[1330502]=a[1345360];a[1330501]=a[1345163];a[1345515]=0;a[1345497]=Q(a[a[c]+4>>2]|0,5365444);a[1345496]=Q(a[a[c]+4>>2]|0,5374600);c=Q(a[a[c]+4>>2]|0,5367600);a[1345491]=c;if(0!=(c|0)){return a[1345499]=0,a[1345360]=0,g}a[1345491]=wf(g,5367600,5338228);a[1345499]=0;a[1345360]=0;return g}function mr(b,c){var d=h,e=Og(b,a[c+12>>2]),f=e|0;Rh(c|0,f);if(2!=(rj(a[c+24>>2])|0)){return h=d,e}var p=c+120|0,j=Za(xa(a[a[p>>2]>>2])+3|0);Pa(j,5335460,(i=h,h=h+4|0,a[i>>2]=a[a[p>>2]>>2],i));Pc(f,5332600,j);h=d;return e}function zf(a,b,c,d,f,h){0==(h|0)?(h=b,b=c):(h=c,b=-b);Zd(a,h,b,d,f)}function pr(b,c,d,e,f,h){var j=0;if(!(0<(d|0)&0<(h|0))){var k;return 0}if((d|0)<(h|0)){for(b=0;;){f=a[c+(b<<2)>>2];if(0==(f|0)){k=0;j=1263;break}if((a[f+12>>2]|0)==(e|0)){k=f;j=1267;break}else{b=b+1|0}}if(1267==j||1263==j){return k}}else{for(c=0;;){e=a[f+(c<<2)>>2];if(0==(e|0)){k=0;j=1264;break}if((a[e+16>>2]|0)==(b|0)){k=e;j=1266;break}else{c=c+1|0}}if(1266==j||1264==j){return k}}}function kg(b,c){var d,e=0;d=(b+4|0)>>2;for(var f=a[d],h=b|0,j=0;;){if((j|0)>=(f|0)){e=1274;break}var k=a[h>>2],i=(j<<2)+k|0;if((a[i>>2]|0)==(c|0)){break}else{j=j+1|0}}1274!=e&&(e=f-1|0,a[d]=e,a[i>>2]=a[k+(e<<2)>>2],a[a[h>>2]+(a[d]<<2)>>2]=0)}function qr(a,b){var c=a+176|0;C[c>>1]=C[c>>1]-C[b+176>>1]&65535;c=a+162|0;C[c>>1]=C[c>>1]-C[b+162>>1]&65535;c=a+164|0;hb[c>>2]-=hb[b+164>>2]}function xf(b,c){return pr(b,a[b+184>>2],a[b+188>>2],c,a[c+176>>2],a[c+180>>2])}function Dq(b,c){return pr(b,a[b+192>>2],a[b+196>>2],c,a[c+200>>2],a[c+204>>2])}function vl(b){var c,d;d=(b+16|0)>>2;c=a[d]>>2;var e=a[c+46];c=0==(e|0)?Za((a[c+47]<<2)+8|0):Oa(e,(a[c+47]<<2)+8|0);a[a[d]+184>>2]=c;c=a[d]+188|0;e=a[c>>2];a[c>>2]=e+1|0;a[a[a[d]+184>>2]+(e<<2)>>2]=b;d=a[d];a[a[d+184>>2]+(a[d+188>>2]<<2)>>2]=0;d=(b+12|0)>>2;c=a[d]>>2;e=a[c+44];c=0==(e|0)?Za((a[c+45]<<2)+8|0):Oa(e,(a[c+45]<<2)+8|0);a[a[d]+176>>2]=c;c=a[d]+180|0;e=a[c>>2];a[c>>2]=e+1|0;a[a[a[d]+176>>2]+(e<<2)>>2]=b;d=a[d];a[a[d+176>>2]+(a[d+180>>2]<<2)>>2]=0;return b}function Yd(b){0==(b|0)&&ia(5340216,117,5379940,5366480);kg(a[b+16>>2]+184|0,b);kg(a[b+12>>2]+176|0,b)}function df(b){var c,d;d=(b+16|0)>>2;c=a[d]>>2;var e=a[c+52];c=0==(e|0)?Za((a[c+53]<<2)+8|0):Oa(e,(a[c+53]<<2)+8|0);a[a[d]+208>>2]=c;c=a[d]+212|0;e=a[c>>2];a[c>>2]=e+1|0;a[a[a[d]+208>>2]+(e<<2)>>2]=b;b=a[d];a[a[b+208>>2]+(a[b+212>>2]<<2)>>2]=0}function Eq(b,c){var d,e,f=0;e=(c+4|0)>>2;var h=a[e];d=(c|0)>>2;for(var j=a[d],k=0;(k|0)<(h|0);){if((a[j+(k<<2)>>2]|0)==(b|0)){f=1310;break}else{k=k+1|0}}1310!=f&&(f=0==(j|0)?Za((h<<2)+8|0):Oa(j,(h<<2)+8|0),a[d]=f,h=a[e],a[e]=h+1|0,a[f+(h<<2)>>2]=b,a[a[d]+(a[e]<<2)>>2]=0)}function yi(b,c,d){var e=da(184);a[e+16>>2]=b;a[e+12>>2]=c;n[e+124|0]=1;if(0==(d|0)){return hb[e+164>>2]=1,C[e+162>>1]=1,C[e+176>>1]=1,C[e+178>>1]=1,e}a[e+20>>2]=a[d+20>>2];C[e+176>>1]=C[d+176>>1];C[e+162>>1]=C[d+162>>1];hb[e+164>>2]=hb[d+164>>2];C[e+178>>1]=C[d+178>>1];var f=d+16|0;if((a[f>>2]|0)==(b|0)){for(var b=(d+28|0)>>2,h=(e+28|0)>>2,j=b+10;b<j;b++,h++){a[h]=a[b]}var k=d+12|0}else{if(k=d+12|0,(a[k>>2]|0)==(b|0)){b=(d+68|0)>>2;h=(e+28|0)>>2;for(j=b+10;b<j;b++,h++){a[h]=a[b]}}}if((a[k>>2]|0)==(c|0)){b=(d+68|0)>>2;h=(e+68|0)>>2;for(j=b+10;b<j;b++,h++){a[h]=a[b]}}else{if((a[f>>2]|0)==(c|0)){b=(d+28|0)>>2;h=(e+68|0)>>2;for(j=b+10;b<j;b++,h++){a[h]=a[b]}}}c=d+180|0;0==(a[c>>2]|0)&&(a[c>>2]=e);a[e+128>>2]=d;return e}function pd(a,b,c){return vl(yi(a,b,c))}function Zk(b,c){var d=b+216|0,e=a[d>>2],f=c+168|0;a[f>>2]=e;0!=(e|0)&&(a[e+172>>2]=c);a[d>>2]=c;a[c+172>>2]=0;(a[f>>2]|0)==(c|0)&&ia(5340216,215,5379848,5348408)}function al(b,c){for(var d=b+216|0;;){var e=a[d>>2];if(0==(e|0)|(e|0)==(c|0)){break}else{d=e+168|0}}0==(e|0)&&ia(5340216,231,5379920,5337848);var e=c+168|0,f=a[e>>2],d=c+172|0;0==(f|0)?e=0:(a[f+172>>2]=a[d>>2],e=a[e>>2]);d=a[d>>2];0==(d|0)?a[b+216>>2]=e:a[d+168>>2]=e}function Me(c){var d,g=da(304);d=g>>2;a[d+3]=5334948;a[d+5]=c;n[g+162|0]=1;var e=g+112|0;f[b>>3]=1;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];e=g+104|0;f[b>>3]=1;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];e=g+96|0;f[b>>3]=1;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];a[d+55]=1;a[d+45]=0;a[d+44]=da(20);a[d+47]=0;a[d+46]=da(20);Zk(c,g);c=c+240|0;a[c>>2]=a[c>>2]+1|0;return g}function fh(b,c){var d,e;e=(c+16|0)>>2;d=a[e]>>2;var f=a[d+48];d=0==(f|0)?Za((a[d+49]<<2)+8|0):Oa(f,(a[d+49]<<2)+8|0);a[a[e]+192>>2]=d;d=a[e]+196|0;f=a[d>>2];a[d>>2]=f+1|0;a[a[a[e]+192>>2]+(f<<2)>>2]=c;e=a[e];a[a[e+192>>2]+(a[e+196>>2]<<2)>>2]=0;e=(c+12|0)>>2;d=a[e]>>2;f=a[d+50];d=0==(f|0)?Za((a[d+51]<<2)+8|0):Oa(f,(a[d+51]<<2)+8|0);a[a[e]+200>>2]=d;d=a[e]+204|0;f=a[d>>2];a[d>>2]=f+1|0;a[a[a[e]+200>>2]+(f<<2)>>2]=c;e=a[e];a[a[e+200>>2]+(a[e+204>>2]<<2)>>2]=0;n[b+248|0]=1;n[a[b+32>>2]+248|0]=1}function wl(b){0==(b|0)&&ia(5340216,272,5379900,5366480);var c=a[b+128>>2];0!=(c|0)&&(c=c+180|0,(a[c>>2]|0)==(b|0)&&(a[c>>2]=0));kg(a[b+16>>2]+192|0,b);kg(a[b+12>>2]+200|0,b)}function Be(b,c){var d=h,e=b+180|0,f=a[e>>2];if((f|0)==(c|0)){aa(0,5332056,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i))}else{0!=(f|0)&&ia(5340216,343,5379592,5329216);a[e>>2]=c;e=c+178|0;f=C[b+178>>1];fc[e>>1]<(f&65535)&&(C[e>>1]=f);for(var e=b+176|0,f=b+162|0,p=b+164|0,j=c;;){var k=j+176|0;C[k>>1]=C[k>>1]+C[e>>1]&65535;k=j+162|0;C[k>>1]=C[k>>1]+C[f>>1]&65535;k=j+164|0;hb[k>>2]+=hb[p>>2];j=a[j+180>>2];if(0==(j|0)){break}}}h=d}function rr(b){var c;c=(b+180|0)>>2;var d=a[c];if(0!=(d|0)){for(var e=d;;){qr(e,b);d=a[e+180>>2];for(0==C[e+176>>1]<<16>>16&&sr(e);1==n[e+124|0]<<24>>24;){e=a[e+12>>2];if(1!=n[e+162|0]<<24>>24){break}if(1!=(a[e+188>>2]|0)){break}e=a[a[e+184>>2]>>2];qr(e,b)}if(0==(d|0)){break}else{e=d}}}a[c]=0}function tr(b,c,d,e){var f=(b|0)>(c|0);a[d>>2]=f?c:b;a[e>>2]=f?b:c}function sr(b){0==(b|0)&&ia(5340216,128,5379476,5366480);var c=b+16|0,d=a[c>>2],e=d+184|0,f=a[a[e>>2]>>2];a:do{if(0!=(f|0)){for(var h=0,j=e,k=f,i=d;;){if((k|0)==(b|0)&&(kg(j,b),i=a[c>>2]),h=h+1|0,j=i+184|0,k=a[a[j>>2]+(h<<2)>>2],0==(k|0)){break a}}}}while(0);c=b+12|0;f=a[c>>2];e=f+176|0;h=a[a[e>>2]>>2];if(0!=(h|0)){for(d=0;!((h|0)==(b|0)&&(kg(e,b),f=a[c>>2]),d=d+1|0,e=f+176|0,h=a[a[e>>2]+(d<<2)>>2],0==(h|0));){}}}function ur(c){var d,g,e,h=0,p=c+216|0,j=a[p>>2];a:do{if(0!=(j|0)){for(var k=j;;){var i=k+192|0,q=a[i>>2];b:do{if(0!=(q|0)&&(g=a[q>>2],0!=(g|0))){for(var m=0,w=q;;){e=a[g+16>>2]>>2;var x=a[a[g+12>>2]+240>>2];d=a[e+60];var v=(d|0)<(x|0),t=v?x:d;e=a[a[e+5]+220>>2]+(44*a[e+59]&-1)+4|0;for(x=v?d:x;;){var y=x+1|0;if((y|0)>=(t|0)){break}x=a[a[e>>2]+(y<<2)>>2];d=n[x+162|0];if(0==d<<24>>24){break}else{if(1!=d<<24>>24){x=y;continue}}if(0==(a[x+120>>2]|0)){x=y}else{break}}0!=((y|0)==(t|0)&1|0)&&(n[g+125|0]=1,w=a[i>>2]);m=m+1|0;g=a[w+(m<<2)>>2];if(0==(g|0)){break b}}}}while(0);k=a[k+168>>2];if(0==(k|0)){break a}}}}while(0);j=a[c+220>>2];0==(a[j+40>>2]|0)?0<(a[c+208>>2]|0)&&(h=1415):h=1415;a:do{if(1415==h){y=a[j+4>>2];k=0;b:for(;;){i=a[y+(k<<2)>>2];if(0==(i|0)){break a}i=a[i+200>>2];for(q=0;;){m=a[i+(q<<2)>>2];if(0==(m|0)){break}if(0!=(a[m+108>>2]|0)&&0==n[m+125|0]<<24>>24){break b}q=q+1|0}k=k+1|0}vr(c)}}while(0);wr(c);j=a[p>>2];if(0==(j|0)){return 0}h=c+152|0;for(p=0;;){y=j+192|0;k=a[y>>2];a:do{if(0==(k|0)){var z=p}else{i=a[k>>2];b:do{if(0==(i|0)){var B=p}else{q=p;m=0;for(g=i;;){if(w=a[g+108>>2],0!=(w|0)&&(0==n[g+125|0]<<24>>24?(xl(g),q=1):(w=0==(a[h>>2]&1|0)?w+24|0:w+32|0,w=(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]),g=g+144|0,f[b>>3]=w,a[g>>2]=a[b>>2],a[g+4>>2]=a[b+4>>2])),m=m+1|0,g=a[a[y>>2]+(m<<2)>>2],0==(g|0)){B=q;break b}}}}while(0);i=j+212|0;if(0<(a[i>>2]|0)){q=j+208|0;m=B;for(w=0;;){t=a[a[q>>2]+(w<<2)>>2];g=t>>2;e=a[g+4];x=a[g+3];if((a[e+236>>2]|0)!=(a[x+236>>2]|0)|(e|0)==(x|0)){d=m}else{for(d=t;!(v=a[d+180>>2],0==(v|0));){d=v}v=n[d+125|0];n[t+125|0]=v;var A=a[g+27];0==(A|0)?d=m:0==v<<24>>24?(xl(t),d=1):(v=0==(a[h>>2]&1|0)?A+24|0:A+32|0,v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),d=(d+144|0)>>2,A=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]),f[b>>3]=v>A?v:A,a[d]=a[b>>2],a[d+1]=a[b+4>>2],d=m)}g=w+1|0;if((g|0)<(a[i>>2]|0)){m=d,w=g}else{z=d;break a}}}else{z=B}}}while(0);j=a[j+168>>2];if(0==(j|0)){break}else{p=z}}if(0==(z|0)){return 0}zi(c);return z}function vr(b){var c;c=(b+244|0)>>1;0!=C[c]<<16>>16&&ia(5331152,190,5380144,5346904);var d=b+246|0,e=(C[d>>1]<<16>>16)+3|0,b=(b+220|0)>>2,f=a[b],e=(0==(f|0)?Za(44*e&-1):Oa(f,44*e&-1))+44|0;a[b]=e;d=C[d>>1];f=d<<16>>16;a:do{if(-1<d<<16>>16){for(var h=f,j=e;;){for(var k=h-1|0,i=(j+(44*k&-1)|0)>>2,j=(j+(44*h&-1)|0)>>2,q=i+11;i<q;i++,j++){a[j]=a[i]}i=a[b];if(0<(h|0)){h=k,j=i}else{var m=-1,n=i;break a}}}else{m=f,n=e}}while(0);a[n+(44*m&-1)+8>>2]=0;a[a[b]+(44*m&-1)>>2]=0;n=da(8);a[a[b]+(44*m&-1)+12>>2]=n;a[a[b]+(44*m&-1)+4>>2]=n;a[a[b]+(44*m&-1)+40>>2]=0;a[a[b]+(44*m&-1)+20>>2]=1;a[a[b]+(44*m&-1)+16>>2]=1;a[a[b]+(44*m&-1)+28>>2]=1;a[a[b]+(44*m&-1)+24>>2]=1;C[c]=C[c]-1&65535}function xl(c){var d,g,e,h,p,j,k,i;i=(c+108|0)>>2;if(0!=(a[i]|0)){k=(c+16|0)>>2;j=a[k]>>2;var q=a[j+5];g=a[j+59];p=(q+220|0)>>2;h=(c+12|0)>>2;var m=xr(a[p],a[a[h]+240>>2],g,a[j+60]);j=g-1|0;e=a[p]>>2;d=a[a[((44*j&-1)+4>>2)+e]>>2];0==(d|0)?(d=a[a[((44*g&-1)+4>>2)+e]>>2]+40|0,e=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])+(a[((44*g&-1)+20>>2)+e]|0)+(a[q+260>>2]|0)):(g=d+40|0,e=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])-(a[((44*j&-1)+16>>2)+e]|0));e&=-1;m=yr(q,j,m);d=a[i];g=d+24|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);d=d+32|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);var w=0==(a[q+152>>2]&1|0),q=w?d:g,x=m+96|0;f[b>>3]=q;a[x>>2]=a[b>>2];a[x+4>>2]=a[b+4>>2];q=.5*q&-1;w=.5*(w?g:d);g=(m+112|0)>>2;f[b>>3]=w;a[g]=a[b>>2];a[g+1]=a[b+4>>2];d=(m+104|0)>>2;f[b>>3]=w;a[d]=a[b>>2];a[d+1]=a[b+4>>2];a[m+120>>2]=a[i];i=m+40|0;f[b>>3]=q+e|0;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];i=pd(m,a[k],c);e=-(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);d=i+28|0;f[b>>3]=e;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];k=a[k]+112|0;k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);e=i+68|0;f[b>>3]=k;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];n[i+124|0]=4;k=pd(m,a[h],c);i=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]);e=k+28|0;f[b>>3]=i;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];h=a[h]+104|0;h=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]);i=k+68|0;f[b>>3]=h;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];n[k+124|0]=4;h=a[p];k=h+(44*j&-1)+16|0;(a[k>>2]|0)<(q|0)?(a[k>>2]=q,p=a[p]):p=h;p=p+(44*j&-1)+20|0;(a[p>>2]|0)<(q|0)&&(a[p>>2]=q);a[m+128>>2]=c|0}}function xr(b,c,d,e){var f=h;h=h+24|0;var p=f+16,j=f+20,k=d-1|0,d=a[b+(44*k&-1)+4>>2],i=a[b+(44*k&-1)>>2],b=f+8|0;a[b>>2]=-1;k=f|0;a[k>>2]=-1;var q=f+12|0;a[q>>2]=i;var m=f+4|0;a[m>>2]=i;tr(e,c,p,j);for(var c=a[p>>2],j=a[j>>2],p=i,e=0,n=-1,x=i;;){i=p-1|0;if((e|0)>(i|0)){var v=n,t=x;break}yl(a[d+(e<<2)>>2],k,c,j);(e|0)!=(i|0)&&yl(a[d+(i<<2)>>2],k,c,j);x=a[m>>2];n=a[k>>2];if(2>(x-n|0)){v=n;t=x;break}else{p=i,e=e+1|0}}(v|0)>(t|0)?(v=a[q>>2]+a[b>>2]|0,v=(v+1|0)/2&-1):(v=(t+v|0)+1|0,v=(v|0)/2&-1);h=f;return v}function yr(b,c,d){var e,f;f=(b+220|0)>>2;var h=a[f];e=h+(44*c&-1)|0;h=a[h+(44*c&-1)+4>>2];h=0==(h|0)?Za((a[e>>2]<<2)+8|0):Oa(h,(a[e>>2]<<2)+8|0);e=h>>2;a[a[f]+(44*c&-1)+4>>2]=h;var j=a[a[f]+(44*c&-1)>>2];a:do{if((j|0)>(d|0)){for(var k=j;;){var i=k-1|0,q=a[(i<<2>>2)+e];a[(k<<2>>2)+e]=q;k=q+240|0;a[k>>2]=a[k>>2]+1|0;if((i|0)>(d|0)){k=i}else{break a}}}}while(0);j=Me(b);b=(d<<2)+h|0;a[b>>2]=j;a[j+240>>2]=d;a[j+236>>2]=c;c=a[f]+(44*c&-1)|0;d=a[c>>2]+1|0;a[c>>2]=d;a[(d<<2>>2)+e]=0;return a[b>>2]}function yl(b,c,d,e){var c=c>>2,f=b>>2,p=0,j=h;h=h+8|0;var k=j+4;if(1==n[b+162|0]<<24>>24){if(b=a[f+60],0!=(a[f+45]|0)){var p=a[f+46],i=a[p>>2];if(0!=(i|0)){for(var q=f=k=0;;){var m=a[a[i+12>>2]+240>>2];if((m|0)>(d|0)){var m=(m|0)<(e|0)?q:1,w=f}else{m=q,w=1}k=k+1|0;i=a[p+(k<<2)>>2];if(0==(i|0)){break}else{f=w,q=m}}0!=w<<24>>24&0==m<<24>>24&&(a[c]=b+1|0);0!=m<<24>>24&0==w<<24>>24&&(a[c+1]=b-1|0)}}else{if(2!=(a[f+47]|0)&&ia(5331152,63,5379464,5359364),m=a[f+46],tr(a[a[a[m>>2]+12>>2]+240>>2],a[a[a[m+4>>2]+12>>2]+240>>2],j,k),m=a[k>>2],(m|0)>(d|0)){if(w=a[j>>2],(w|0)<(e|0)){if(k=(w|0)<(d|0),f=(m|0)>(e|0),!(k&f)){k?p=1500:(w|0)==(d|0)&(m|0)<(e|0)&&(p=1500);1500==p&&(a[c+2]=b);if(!f&&!((m|0)==(e|0)&(w|0)>(d|0))){h=j;return}a[c+3]=b}}else{a[c+1]=b,a[c+3]=b}}else{a[c]=b,a[c+2]=b}}}h=j}function zl(b){var c=b+276|0,d=a[c>>2];if(0!=(d|0)){var e=C[b+244>>1],f=b+246|0;if(e<<16>>16<=C[f>>1]<<16>>16){b=b+220|0;for(e=e<<16>>16;;){a[d+(e<<2)>>2]=a[a[a[b>>2]+(44*e&-1)+4>>2]>>2];d=e+1|0;if((d|0)>(C[f>>1]<<16>>16|0)){break}e=d;d=a[c>>2]}}}}function nr(c,d){n[5381340]=0;a[1345325]=c;var g=(Mb(a[a[c+32>>2]+28>>2])<<2)+4|0;a[1345161]=da(g);a[1345159]=da(g);a[1345374]=8;a[1345376]=24;f[b>>3]=.995;a[1345526]=a[b>>2];a[1345527]=a[b+4>>2];g=U(c|0,5376592);if(0!=(g|0)&&(g=Oe(g,Ac),0<g)){var e=(a[1345374]|0)*g;a[1345374]=1>e?1:e&-1;g*=a[1345376]|0;a[1345376]=1>g?1:g&-1}Yk(c);wi(c,1);Al(c);Ai(c);a[1345477]=C[c+244>>1]<<16>>16;a[1345478]=C[c+246>>1]<<16>>16;g=c+228|0;a:do{if(0<(a[g>>2]|0)){for(e=0;;){var h=c,p=e;a[h+216>>2]=a[a[h+224>>2]+(p<<2)>>2];if(0<(p|0)){var j=C[h+244>>1],p=h+246|0;if(j<<16>>16<=C[p>>1]<<16>>16){h=h+220|0;for(j=j<<16>>16;;){var k=a[h>>2],i=k+(44*j&-1)+4|0;a[i>>2]=(a[k+(44*j&-1)>>2]<<2)+a[i>>2]|0;a[a[h>>2]+(44*j&-1)>>2]=0;j=j+1|0;if((j|0)>(C[p>>1]<<16>>16|0)){break}}}}Bi(c,0,d);e=e+1|0;if((e|0)>=(a[g>>2]|0)){break a}}}}while(0);g=0;e=(c+228|0)>>2;if(2<=(a[e]|0)){p=c+224|0;for(h=j=0;;){k=a[a[p>>2]+(h<<2)>>2];0!=(j|0)&&(a[j+168>>2]=k);a[k+172>>2]=j;for(j=k;!(k=a[j+168>>2],0==(k|0));){j=k}h=h+1|0;if((h|0)>=(a[e]|0)){break}}a[e]=1;a[c+216>>2]=a[a[p>>2]>>2];C[c+244>>1]=a[1345477]&65535;C[c+246>>1]=a[1345478]&65535}h=C[c+244>>1];p=c+246|0;if(h<<16>>16<=C[p>>1]<<16>>16){e=(c+220|0)>>2;for(h=h<<16>>16;;){j=a[e];a[j+(44*h&-1)>>2]=a[j+(44*h&-1)+8>>2];j=a[e];a[j+(44*h&-1)+4>>2]=a[j+(44*h&-1)+12>>2];for(j=0;;){var k=a[e],q=k+(44*h&-1)|0;if((j|0)>=(a[q>>2]|0)){break}k=a[a[k+(44*h&-1)+4>>2]+(j<<2)>>2];if(0==(k|0)){g=1588;break}a[k+240>>2]=j;j=j+1|0}1588==g&&(g=0,a[q>>2]=j);h=h+1|0;if((h|0)>(C[p>>1]<<16>>16|0)){break}}}q=c+208|0;if(1<=(a[q>>2]|0)){g=c+212|0;for(e=1;;){zr(a[a[g>>2]+(e<<2)>>2],d);var e=e+1|0,m=a[q>>2];if((e|0)>(m|0)){break}}if(0<(m|0)){m=U(c|0,5330192);if(0!=(m|0)&&0==Xd(m)<<24>>24){Bl(c);return}dl(c);n[5381340]=1;Bi(c,2,d)}}Bl(c)}function Bi(c,d,g){if(1<(d|0)){var e=lh(),h=c+216|0;Cl(a[h>>2]);var p=e}else{p=2147483647,h=c+216|0}for(var e=c+32|0,j=p;;){var k;if(3<=(d|0)){var i=j,q=p,m=k;break}k=a[1345376];if(2>(d|0)){k=4<(k|0)?4:k;(a[e>>2]|0)==(c|0)&&Dl(c,d);0==(d|0)&&El(c);Fl(c);var n=lh();(n|0)>(j|0)?p=j:(Cl(a[h>>2]),p=n)}else{(p|0)>(j|0)&&Ar(c),n=p=j}for(var j=p,x=n,v=0,p=0;(p|0)<(k|0);){n=v+1|0;if((v|0)>=(a[1345374]|0)|0==(x|0)){break}x=c;v=2>((p|0)%4|0)&1;if(0==(p&1|0)){var t=C[x+244>>1],y=1,z=x+246|0,t=(t<<16>>16)+(t<<16>>16<=C[a[1345325]+244>>1]<<16>>16&1)|0}else{t=C[x+246>>1],y=-1,z=x+244|0,t=((t<<16>>16>=C[a[1345325]+246>>1]<<16>>16)<<31>>31)+(t<<16>>16)|0}z=(C[z>>1]<<16>>16)+y|0;if((t|0)!=(z|0)){for(;!(Br(x,t,v,Cr(x,t,t-y|0)&255),t=t+y|0,(t|0)==(z|0));){}}v^=1;Ci(x,v);x=lh();(x|0)>(j|0)?v=j:(Cl(a[h>>2]),v=x,n=(x|0)<(a[b>>2]=a[1345526],a[b+4>>2]=a[1345527],f[b>>3])*(j|0)?0:n);j=v;v=n;p=p+1|0}if(0==(x|0)){i=j;q=0;m=k;break}else{p=x,d=d+1|0}}(q|0)>(i|0)&&Ar(c);0<(i|0)&&(Ci(c,0),i=lh());if(0!=(g|0)&0<(m|0)){g=0}else{return i}for(;!(Dr(c),g=g+1|0,(g|0)==(m|0));){}return i}function zr(b,c){Yk(b);a[b+228>>2]=1;a[a[b+224>>2]>>2]=a[b+216>>2];Al(b);Dl(b,0);Iq(b);Cq(b);Jq(b);Ai(b);El(b);Fl(b);var d=Bi(b,2,c),e=b+208|0;if(1>(a[e>>2]|0)){var f=d;zl(b);return f}for(var h=b+212|0,j=1;;){if(d=zr(a[a[h>>2]+(j<<2)>>2],c)+d|0,j=j+1|0,(j|0)>(a[e>>2]|0)){f=d;break}}zl(b);return f}function Bl(b){var c=a[1345159];0!=(c|0)&&(E(c),a[1345159]=0);c=a[1345161];0!=(c|0)&&(E(c),a[1345161]=0);c=b+208|0;a:do{if(1<=(a[c>>2]|0)){for(var d=b+212|0,e=1;;){if(zi(a[a[d>>2]+(e<<2)>>2]),e=e+1|0,(e|0)>(a[c>>2]|0)){break a}}}}while(0);d=C[b+244>>1];c=b+246|0;if(d<<16>>16<=C[c>>1]<<16>>16){b=b+220|0;for(d=d<<16>>16;;){e=a[b>>2];a:do{if(0<(a[e+(44*d&-1)>>2]|0)){for(var f=0,h=e;;){h=a[a[h+(44*d&-1)+4>>2]+(f<<2)>>2];a[h+240>>2]=f;var h=h+192|0,j=a[h>>2];b:do{if(0!=(j|0)){var k=a[j>>2];if(0!=(k|0)){for(var i=0,q=k,k=j;;){if(4==n[q+124|0]<<24>>24&&(wl(q),E(q|0),i=i-1|0,k=a[h>>2]),i=i+1|0,q=a[k+(i<<2)>>2],0==(q|0)){break b}}}}}while(0);f=f+1|0;h=a[b>>2];if((f|0)>=(a[h+(44*d&-1)>>2]|0)){var m=h;break a}}}else{m=e}}while(0);e=a[m+(44*d&-1)+40>>2];0!=(e|0)&&(E(a[e+8>>2]),E(e));d=d+1|0;if((d|0)>(C[c>>1]<<16>>16|0)){break}}}}function wr(b){zl(b);var c=b+208|0;if(1<=(a[c>>2]|0)){for(var b=b+212|0,d=1;!(wr(a[a[b>>2]+(d<<2)>>2]),d=d+1|0,(d|0)>(a[c>>2]|0));){}}}function zi(b){var c;c=b+208|0;a:do{if(1<=(a[c>>2]|0)){for(var d=b+212|0,e=1;;){if(zi(a[a[d>>2]+(e<<2)>>2]),e=e+1|0,(e|0)>(a[c>>2]|0)){break a}}}}while(0);c=(b+276|0)>>2;var f=a[c];if(0!=(f|0)){var h=C[b+244>>1],d=b+246|0;if(h<<16>>16<=C[d>>1]<<16>>16){for(var e=b+32|0,j=b+220|0,h=h<<16>>16;;){var k=a[f+(h<<2)>>2],f=Er(b,k,-1),k=Er(b,k,1);a[a[c]+(h<<2)>>2]=f;f=f+240|0;a[a[j>>2]+(44*h&-1)+4>>2]=(a[f>>2]<<2)+a[a[a[e>>2]+220>>2]+(44*h&-1)+4>>2]|0;a[a[j>>2]+(44*h&-1)>>2]=a[k+240>>2]+1-a[f>>2]|0;h=h+1|0;if((h|0)>(C[d>>1]<<16>>16|0)){break}f=a[c]}}}}function Er(a,b,c){var d=Fr(b,c);if(0==(d|0)){var f;return b}for(;;){if(b=0==(Gl(a,d)|0)?0==(Hl(a,d)|0)?b:d:d,d=Fr(d,c),0==(d|0)){f=b;break}}return f}function Il(b,c){var d,e,f=a[c+12>>2],h=a[f+192>>2];e=(c+16|0)>>2;a:do{if(0!=(h|0)){for(var j=0;;){d=a[h+(j<<2)>>2];if(0==(d|0)){break a}if((a[d+12>>2]|0)==(a[e]|0)){break}else{j=j+1|0}}Be(c,d);f=c+180|0;0==(a[f>>2]|0)&&(a[f>>2]=d);4==n[d+124|0]<<24>>24&&(d=d+128|0,0==(a[d>>2]|0)&&(a[d>>2]=c));d=a[e]>>2;f=a[d+52];d=0==(f|0)?Za((a[d+53]<<2)+8|0):Oa(f,(a[d+53]<<2)+8|0);a[a[e]+208>>2]=d;d=a[e]+212|0;f=a[d>>2];a[d>>2]=f+1|0;a[a[a[e]+208>>2]+(f<<2)>>2]=c;e=a[e];a[a[e+208>>2]+(a[e+212>>2]<<2)>>2]=0;return}}while(0);e=yi(f,a[e],c);n[e+124|0]=4==n[c+124|0]<<24>>24?4:3;a[e+108>>2]=a[c+108>>2];fh(b,e)}function Al(b){var c,d;d=(b+246|0)>>1;var e=da((C[d]<<16>>16<<2)+8|0);c=b+20|0;var f=ha(a[c>>2]);a:do{if(0!=(f|0)){for(var h=b+28|0,j=f;;){var k=(a[j+236>>2]<<2)+e|0;a[k>>2]=a[k>>2]+1|0;k=zb(b,j);b:do{if(0!=(k|0)){for(var i=k;;){var q=a[a[i+16>>2]+236>>2],m=a[a[i+12>>2]+236>>2],n=(q|0)>(m|0),x=n?q:m,q=(n?m:q)+1|0;c:do{if((q|0)<(x|0)){for(m=q;;){if(n=(m<<2)+e|0,a[n>>2]=a[n>>2]+1|0,m=m+1|0,(m|0)>=(x|0)){break c}}}}while(0);i=Db(a[h>>2],i);if(0==(i|0)){break b}}}}while(0);j=sa(a[c>>2],j);if(0==(j|0)){break a}}}}while(0);f=da((44*(C[d]<<16>>16)&-1)+88|0);c=(b+220|0)>>2;a[c]=f;b=C[b+244>>1];if(b<<16>>16<=C[d]<<16>>16){for(b=b<<16>>16;;){h=(b<<2)+e|0;j=a[h>>2];a[f+(44*b&-1)>>2]=j;a[a[c]+(44*b&-1)+8>>2]=j;f=da((a[h>>2]<<2)+4|0);a[a[c]+(44*b&-1)+4>>2]=f;a[a[c]+(44*b&-1)+12>>2]=f;b=b+1|0;if((b|0)>(C[d]<<16>>16|0)){break}f=a[c]}}E(e)}function mh(b,c){var d=a[b+236>>2],e=b+240|0,f=a[e>>2],h=c+240|0,j=a[h>>2];a[e>>2]=j;e=a[1345325]+220|0;a[a[a[e>>2]+(44*d&-1)+4>>2]+(j<<2)>>2]=b;a[h>>2]=f;a[a[a[e>>2]+(44*d&-1)+4>>2]+(f<<2)>>2]=c}function Bq(a){return 1==n[a+162|0]<<24>>24?2:a=2>n[a+166|0]<<24>>24&1}function Jl(c,d){var g=0,e=0<(d|0),h=a[c>>2];if(0==(h|0)){var i;return 0}var j=0,k=0;a:for(;;){var k=k+1|0,r=a[c+(k<<2)>>2],q=0==(r|0);b:do{if(e){if(q){i=j;g=1697;break a}for(var m=a[a[h+12>>2]+240>>2],n=h+28|0,n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),x=h+162|0,v=j,t=k,y=r;;){var z=y+28|0,v=0>(a[a[y+12>>2]+240>>2]-m|0)*((a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3])-n)?Math.a(C[y+162>>1]<<16>>16,C[x>>1]<<16>>16)+v|0:v,t=t+1|0,y=a[c+(t<<2)>>2];if(0==(y|0)){var B=v;break b}}}else{if(q){i=j;g=1695;break a}m=a[a[h+16>>2]+240>>2];n=h+68|0;n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]);x=h+162|0;v=j;t=k;for(y=r;;){if(z=y+68|0,v=0>(a[a[y+16>>2]+240>>2]-m|0)*((a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3])-n)?Math.a(C[y+162>>1]<<16>>16,C[x>>1]<<16>>16)+v|0:v,t=t+1|0,y=a[c+(t<<2)>>2],0==(y|0)){B=v;break b}}}}while(0);if(q){i=B;g=1698;break}else{j=B,h=r}}if(1697==g||1698==g||1695==g){return i}}function Dl(b,c){var d,e=h,f=rn(a[b+240>>2]),p=b+216|0;d=a[p>>2];a:do{if(0!=(d|0)){for(var j=d;;){if(n[j+163|0]=0,j=a[j+168>>2],0==(j|0)){break a}}}}while(0);var j=b+244|0,k=C[j>>1];d=(b+246|0)>>1;a:do{if(k<<16>>16<=C[d]<<16>>16){for(var r=b+220|0,q=k<<16>>16;;){if(a[a[r>>2]+(44*q&-1)>>2]=0,q=q+1|0,(q|0)>(C[d]<<16>>16|0)){break a}}}}while(0);p=a[p>>2];a:do{if(0!=(p|0)){for(var k=0==(c|0),r=b,q=f,m=p;;){b:do{if(0==(a[a[(k?m+176|0:m+184|0)>>2]>>2]|0)){var w=m+163|0;if(0==n[w]<<24>>24&&(n[w]=1,Ig(f,m),w=Jg(f),0!=(w|0))){for(;;){if(7==n[w+165|0]<<24>>24?Kq(r,a[w+216>>2],c,q):(bl(b,w),cl(f,w,c)),w=Jg(f),0==(w|0)){break b}}}}}while(0);m=a[m+168>>2];if(0==(m|0)){break a}}}}while(0);0!=(Jg(f)|0)&&aa(1,5339812,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));j=C[j>>1];a:do{if(j<<16>>16<=C[d]<<16>>16){p=b+152|0;k=b+220|0;r=a[1345325];for(q=j<<16>>16;;){n[a[r+220>>2]+(44*q&-1)+33|0]=0;b:do{if(0!=(a[p>>2]&1|0)&&(m=a[k>>2],w=a[m+(44*q&-1)>>2],0<(w|0))){for(var m=a[m+(44*q&-1)+4>>2],w=w-1|0,x=(w|0)/2&-1,v=0;;){if(mh(a[m+(v<<2)>>2],a[m+(w-v<<2)>>2]),v=v+1|0,(v|0)>(x|0)){break b}}}}while(0);q=q+1|0;if((q|0)>(C[d]<<16>>16|0)){break a}}}}while(0);(a[b+32>>2]|0)==(b|0)&&0<(lh()|0)&&Ci(b,0);E(a[f>>2]);E(f);h=e}function cl(b,c,d){if(0==(d|0)){var d=c+188|0,e=a[d>>2];if(0<(e|0)){for(var c=c+184|0,f=0;;){var h=a[a[c>>2]+(f<<2)>>2]+12|0,j=a[h>>2]+163|0;0==n[j]<<24>>24&&(n[j]=1,Ig(b,a[h>>2]),e=a[d>>2]);f=f+1|0;if((f|0)>=(e|0)){break}}}}else{if(d=c+180|0,e=a[d>>2],0<(e|0)){c=c+176|0;for(f=0;!(h=a[a[c>>2]+(f<<2)>>2]+16|0,j=a[h>>2]+163|0,0==n[j]<<24>>24&&(n[j]=1,Ig(b,a[h>>2]),e=a[d>>2]),f=f+1|0,(f|0)>=(e|0));){}}}}function lh(){var b,c=a[1345325],d=C[c+244>>1],e=c+246|0,f=C[e>>1];if(d<<16>>16>=f<<16>>16){var h;return 0}b=(c+220|0)>>2;for(var j=0,d=d<<16>>16;;){var k=a[b];0==n[k+(44*d&-1)+33|0]<<24>>24?(f=Gr(c,d),a[a[b]+(44*d&-1)+36>>2]=f,n[a[b]+(44*d&-1)+33|0]=1,k=f,f=C[e>>1]):k=a[k+(44*d&-1)+36>>2];j=k+j|0;d=d+1|0;if((d|0)>=(f<<16>>16|0)){h=j;break}}return h}function Ci(b,c){var d,e=b+244|0,f=C[e>>1];d=(b+246|0)>>1;var h=C[d];a:do{if(f<<16>>16>h<<16>>16){var j=h,k=b+220|0}else{for(var i=b+220|0,q=f<<16>>16;;){n[a[i>>2]+(44*q&-1)+32|0]=1;var q=q+1|0,m=C[d];if((q|0)>(m<<16>>16|0)){j=m;k=i;break a}}}}while(0);for(f=j;;){h=C[e>>1];if(h<<16>>16>f<<16>>16){break}h=h<<16>>16;for(j=0;;){if(0==n[a[k>>2]+(44*h&-1)+32|0]<<24>>24){var w=j,x=f}else{w=Hr(b,h,c)+j|0,x=C[d]}f=h+1|0;if((f|0)>(x<<16>>16|0)){break}else{h=f,j=w,f=x}}if(0<(w|0)){f=x}else{break}}}function Gr(b,c){var d,e=0;d=(b+220|0)>>2;var f=a[d],h=a[f+(44*c&-1)+4>>2],j=c+1|0,k=a[a[a[1345325]+220>>2]+(44*j&-1)>>2];(a[1311668]|0)>(k|0)||(f=k+1|0,a[1311668]=f,k=a[1311667],f=0==(k|0)?Za(f<<2):Oa(k,f<<2),a[1311667]=f,f=a[d]);a:do{if(0<(a[f+(44*j&-1)>>2]|0)){for(var k=a[1311667],i=0;;){a[k+(i<<2)>>2]=0;var i=i+1|0,q=a[d];if((i|0)>=(a[q+(44*j&-1)>>2]|0)){var m=q;break a}}}else{m=f}}while(0);a:do{if(0<(a[m+(44*c&-1)>>2]|0)){for(var w=f=0,k=0,i=m;;){var x=(k<<2)+h|0,v=a[a[x>>2]+184>>2],q=a[v>>2];b:do{if(0<(f|0)){if(0==(q|0)){var t=f,y=i,z=w}else{for(var B=a[1311667],A=0,D=w,E=q;;){var G=a[a[E+12>>2]+240>>2]+1|0;c:do{if((G|0)>(f|0)){var H=D}else{for(var I=C[E+162>>1]<<16>>16,J=D,T=G;;){if(J=Math.a(I,a[B+(T<<2)>>2])+J|0,T=T+1|0,(T|0)>(f|0)){H=J;break c}}}}while(0);A=A+1|0;E=a[v+(A<<2)>>2];if(0==(E|0)){var K=H,e=1787;break b}else{D=H}}}}else{K=w,e=1787}}while(0);do{if(1787==e){e=0;if(0==(q|0)){t=f,y=i}else{t=a[1311667];y=1;z=f;for(w=q;;){var v=a[a[w+12>>2]+240>>2],M=(v|0)>(z|0)?v:z,z=(v<<2)+t|0;a[z>>2]=(C[w+162>>1]<<16>>16)+a[z>>2]|0;w=a[a[a[x>>2]+184>>2]+(y<<2)>>2];if(0==(w|0)){break}y=y+1|0;z=M}t=M;y=a[d]}z=K}}while(0);k=k+1|0;x=a[y+(44*c&-1)>>2];if((k|0)<(x|0)){f=t,w=z,i=y}else{break}}if(0<(x|0)){f=a[y+(44*c&-1)+4>>2];k=z;for(i=0;;){if(q=a[f+(i<<2)>>2],k=0==n[q+161|0]<<24>>24?k:Jl(a[q+184>>2],1)+k|0,i=i+1|0,(i|0)>=(x|0)){L=k;P=y;break a}}}else{var L=z,P=y}}else{L=0,P=m}}while(0);d=a[P+(44*j&-1)>>2];if(0>=(d|0)){var N;return L}j=a[P+(44*j&-1)+4>>2];for(P=0;;){if(e=a[j+(P<<2)>>2],L=0==n[e+161|0]<<24>>24?L:Jl(a[e+176>>2],-1)+L|0,P=P+1|0,(P|0)>=(d|0)){N=L;break}}return N}function bl(b,c){var d,e,f=h,p=a[c+236>>2];e=(b+220|0)>>2;d=a[e]>>2;var j=a[((44*p&-1)>>2)+d];if(1>(a[((44*p&-1)+8>>2)+d]|0)){var k=a[c+12>>2];aa(1,5358740,(i=h,h=h+16|0,a[i>>2]=a[b+12>>2],a[i+4>>2]=k,a[i+8>>2]=p,a[i+12>>2]=j,i));P()}a[a[((44*p&-1)+4>>2)+d]+(j<<2)>>2]=c;d=c+240|0;a[d>>2]=j;j=a[e]+(44*p&-1)|0;a[j>>2]=a[j>>2]+1|0;j=a[e];(a[j+(44*p&-1)>>2]|0)>(a[j+(44*p&-1)+8>>2]|0)&&ia(5346728,1028,5379732,5343048);j=a[d>>2];d=a[a[a[1345325]+220>>2]+(44*p&-1)+8>>2];(j|0)>(d|0)&&P();(p|0)<(C[b+244>>1]<<16>>16|0)&&P();(p|0)>(C[b+246>>1]<<16>>16|0)&&P();e=a[e];((j<<2)+a[e+(44*p&-1)+4>>2]|0)>>>0>((d<<2)+a[e+(44*p&-1)+12>>2]|0)>>>0?P():h=f}function Di(b,c,d){var e=a[c+216>>2],f=a[d+216>>2],h=(e|0)!=(f|0);if(n[5381340]){if(h){return 1}}else{if(!(0==(e|0)|h^1|0==(f|0))){return 7==n[c+165|0]<<24>>24&&1==n[c+162|0]<<24>>24||7==n[d+165|0]<<24>>24&&1==n[d+162|0]<<24>>24?0:1}}e=a[a[b+220>>2]+(44*a[c+236>>2]&-1)+40>>2];if(0==(e|0)){return 0}b=0==(a[b+152>>2]&1|0);return c=n[Math.a(a[e+4>>2],a[(b?c:d)+284>>2])+a[e+8>>2]+a[(b?d:c)+284>>2]|0]<<24>>24}function nh(c,d){var g=0,e=a[d>>2];if(0==(e|0)){var h;return 0}for(var i=a[c+176>>2],j=a[i>>2],k=0==(j|0),r=d,q=0;;){var m=C[e+162>>1]<<16>>16,n=a[a[e+16>>2]+240>>2];a:do{if(k){var x=q}else{for(var v=e+28|0,t=i,y=q,z=j;;){var B=a[a[z+16>>2]+240>>2];if(0<(B-n|0)){g=1843}else{if((B|0)!=(n|0)){var A=y}else{z=z+28|0,(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3])>(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3])?g=1843:A=y}}1843==g&&(g=0,A=Math.a(C[a[t>>2]+162>>1]<<16>>16,m)+y|0);t=t+4|0;z=a[t>>2];if(0==(z|0)){x=A;break a}else{y=A}}}}while(0);r=r+4|0;e=a[r>>2];if(0==(e|0)){h=x;break}else{q=x}}return h}function oh(c,d){var g=0,e=a[d>>2];if(0==(e|0)){var h;return 0}for(var i=a[c+184>>2],j=a[i>>2],k=0==(j|0),r=d,q=0;;){var m=C[e+162>>1]<<16>>16,n=a[a[e+12>>2]+240>>2];a:do{if(k){var x=q}else{for(var v=e+68|0,t=i,y=q,z=j;;){var B=a[a[z+12>>2]+240>>2];if(0<(B-n|0)){g=1856}else{if((B|0)!=(n|0)){var A=y}else{z=z+68|0,(a[b>>2]=a[z>>2],a[b+4>>2]=a[z+4>>2],f[b>>3])>(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3])?g=1856:A=y}}1856==g&&(g=0,A=Math.a(C[a[t>>2]+162>>1]<<16>>16,m)+y|0);t=t+4|0;z=a[t>>2];if(0==(z|0)){x=A;break a}else{y=A}}}}while(0);r=r+4|0;e=a[r>>2];if(0==(e|0)){h=x;break}else{q=x}}return h}function Ir(b){for(b>>=2;;){var c=a[b+32];if(0==(c|0)){break}else{b=c,b>>=2}}return(a[a[b+4]+216>>2]|0)!=(a[a[b+3]+216>>2]|0)&1}function Fr(b,c){var d=a[b+240>>2];return 0<=(c|0)?d=a[a[a[a[1345325]+220>>2]+(44*a[b+236>>2]&-1)+4>>2]+(d+1<<2)>>2]:0>=(d|0)?0:d=a[a[a[a[1345325]+220>>2]+(44*a[b+236>>2]&-1)+4>>2]+(d-1<<2)>>2]}function Cl(c){if(0!=(c|0)){for(;;){var d=c+32|0;f[b>>3]=a[c+240>>2]|0;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];c=a[c+168>>2];if(0==(c|0)){break}}}}function Hr(b,c,d){var e,f,h,j;j=(b+220|0)>>2;n[a[j]+(44*c&-1)+32|0]=0;var k=0<(c|0),i=c+1|0,d=0!=(d|0),q=b+244|0,m=c-1|0,w=b+246|0;h=e=0;a:for(;;){for(f=h;;){var x=a[j];if((f|0)>=(a[x+(44*c&-1)>>2]-1|0)){break a}var v=a[x+(44*c&-1)+4>>2],x=a[v+(f<<2)>>2];h=x>>2;var t=f+1|0,v=a[v+(t<<2)>>2];f=v>>2;(a[h+60]|0)<(a[f+60]|0)||ia(5346728,523,5379376,5336908);if(0!=(Di(b,x,v)|0)){f=t}else{if(k){var y=nh(x,a[f+44]),z=nh(v,a[h+44])}else{y=z=0}0<(a[a[j]+(44*i&-1)>>2]|0)&&(y=oh(x,a[f+46])+y|0,z=oh(v,a[h+46])+z|0);if((z|0)<(y|0)){break}if(d&0<(y|0)&(z|0)==(y|0)){break}else{f=t}}}mh(x,v);h=y-z+e|0;e=(a[1345325]+220|0)>>2;n[a[e]+(44*c&-1)+33|0]=0;n[a[j]+(44*c&-1)+32|0]=1;(C[q>>1]<<16>>16|0)<(c|0)&&(n[a[e]+(44*m&-1)+33|0]=0,n[a[j]+(44*m&-1)+32|0]=1);(C[w>>1]<<16>>16|0)>(c|0)&&(n[a[e]+(44*i&-1)+33|0]=0,n[a[j]+(44*i&-1)+32|0]=1);e=h;h=t}return e}function Ai(b){var c=h,d=a[1345481];if(0!=(d|0)|0!=(a[1345353]|0)){if(d=$b(b|0,d,0),0==(d|0)){var e=a[b+36>>2],d=a[e+20>>2],e=zb(d,e);a:do{if(0!=(e|0)){for(var f=d+28|0,p=e;;){var j=vd(a[p+12>>2]);0==(0==(Pd(a[j+12>>2],5375312,7)|0)&1|0)&&Ai(j);p=Db(a[f>>2],p);if(0==(p|0)){break a}}}}while(0);if(0!=(a[1345353]|0)){d=h;e=b+20|0;f=ha(a[e>>2]);if(0!=(f|0)){for(;;){p=f;j=$b(f|0,a[1345353],0);a:do{if(0!=(j|0)){var k=n[j];do{if(0==k<<24>>24){break a}else{if(111==k<<24>>24){if(0==($(j,5334004)|0)){Ei(b,p,1);break a}}else{if(105==k<<24>>24&&0==($(j,5331016)|0)){Ei(b,p,0);break a}}}}while(0);k=a[f+12>>2];aa(1,5325560,(i=h,h=h+8|0,a[i>>2]=j,a[i+4>>2]=k,i))}}while(0);f=sa(a[e>>2],f);if(0==(f|0)){break}}}h=d}}else{e=n[d];if(105==e<<24>>24){if(0==($(d,5331016)|0)){Jr(b,0);h=c;return}}else{if(111==e<<24>>24){if(0==($(d,5334004)|0)){Jr(b,1);h=c;return}}else{if(0==e<<24>>24){h=c;return}}}aa(1,5328340,(i=h,h=h+4|0,a[i>>2]=d,i))}}h=c}function Jr(b,c){var d=b+20|0,e=ha(a[d>>2]);if(0!=(e|0)){for(;!(Ei(b,e,c),e=sa(a[d>>2],e),0==(e|0));){}}}function Ei(b,c,d){var e,f=a[1345161];e=f>>2;if(0==(a[c+216>>2]|0)){d=0!=(d|0);a:do{if(d){var h=c+184|0,j=a[h>>2],k=a[j>>2];if(0==(k|0)){return}for(var i=0,q=0;;){if(0==(Ir(k)|0)&&(a[(i<<2>>2)+e]=k,i=i+1|0,j=a[h>>2]),q=q+1|0,k=a[j+(q<<2)>>2],0==(k|0)){var m=i;break a}}}else{h=c+176|0;j=a[h>>2];k=a[j>>2];if(0==(k|0)){return}for(q=i=0;;){if(0==(Ir(k)|0)&&(a[(i<<2>>2)+e]=k,i=i+1|0,j=a[h>>2]),q=q+1|0,k=a[j+(q<<2)>>2],0==(k|0)){m=i;break a}}}}while(0);if(2<=(m|0)){a[(m<<2>>2)+e]=0;af(f,m,114);for(c=1;;){m=a[(c<<2>>2)+e];if(0==(m|0)){break}f=a[(c-1<<2>>2)+e];d?(m=m+12|0,f=f+12|0):(m=m+16|0,f=f+16|0);m=a[m>>2];f=a[f>>2];if(0!=(Dq(f,m)|0)){break}f=yi(f,m,0);n[f+124|0]=4;fh(b,f);c=c+1|0}}}}function Gl(a,b){return(0==n[b+162|0]<<24>>24?0!=(fd(a,b|0)|0):0)&1}function Hl(b,c){do{if(1==n[c+162|0]<<24>>24&&1==(a[c+180>>2]|0)&&1==(a[c+188>>2]|0)){for(var d=a[c+184>>2];;){var e=a[d>>2];if(0==n[e+124|0]<<24>>24){break}else{d=e+128|0}}if(0!=(fd(b,e|0)|0)){return d=1}}}while(0);return 0}function El(b){var c,d=C[b+244>>1],e=b+246|0;if(d<<16>>16<=C[e>>1]<<16>>16){c=(b+220|0)>>2;for(var d=d<<16>>16,f=a[c];;){a:do{if(0<(a[f+(44*d&-1)>>2]|0)){for(var h=0,j=0,k=f;;){var i=a[a[k+(44*d&-1)+4>>2]+(j<<2)>>2];n[i+164|0]=0;n[i+163|0]=0;a[i+284>>2]=j;if(0<(a[i+196>>2]|0)&0==(h|0)){var q=a[a[c]+(44*d&-1)>>2],i=q,m=Wb,h=da(12),m=h>>2;a[m]=i;a[m+1]=q;a[m+2]=da(Math.a(q,i));a[a[c]+(44*d&-1)+40>>2]=h;i=1}else{i=h}j=j+1|0;q=a[c];m=a[q+(44*d&-1)>>2];if((j|0)<(m|0)){h=i,k=q}else{break}}if(0!=(i|0)&0<(m|0)){j=0;for(h=q;;){if(k=a[a[h+(44*d&-1)+4>>2]+(j<<2)>>2],0==n[k+163|0]<<24>>24&&(Kl(b,k),h=a[c]),j=j+1|0,(j|0)>=(a[h+(44*d&-1)>>2]|0)){w=h;break a}}}else{var w=q}}else{w=f}}while(0);d=d+1|0;if((d|0)>(C[e>>1]<<16>>16|0)){break}else{f=w}}}}function Fl(b){var c;if(0!=n[b+248|0]<<24>>24){var d=C[b+244>>1],e=b+246|0;if(d<<16>>16<=C[e>>1]<<16>>16){c=(b+220|0)>>2;for(var f=b+152|0,h=0,d=d<<16>>16;;){var j=a[c];if(0<(a[j+(44*d&-1)>>2]|0)){for(var k=0;;){n[a[a[j+(44*d&-1)+4>>2]+(k<<2)>>2]+163|0]=0;var i=k+1|0,j=a[c];if((i|0)<(a[j+(44*d&-1)>>2]|0)){k=i}else{break}}k=(i<<2)+4|0}else{k=4}h=k=0==(h|0)?Za(k):Oa(h,k);j=a[c];a:do{if(0<(a[j+(44*d&-1)>>2]|0)){for(var q=0,m=0,w=j;;){var x=a[a[w+(44*d&-1)+4>>2]+(m<<2)>>2],v=x+204|0,t=a[v>>2];b:do{if(0<(t|0)){for(var w=x+200|0,y=0,z=0,B=t;;){var A=a[a[w>>2]+(z<<2)>>2];0<hb[A+164>>2]&&(y=(0!=(Gl(b,a[A+16>>2])|Hl(b,a[A+16>>2])|0)&1)+y|0,B=a[v>>2]);z=z+1|0;if((z|0)>=(B|0)){var D=y;break b}}}else{D=0}}while(0);v=x+196|0;t=a[v>>2];b:do{if(0<(t|0)){w=x+192|0;z=y=0;for(B=t;;){if(A=a[a[w>>2]+(z<<2)>>2],0<hb[A+164>>2]&&(y=(0!=(Gl(b,a[A+12>>2])|Hl(b,a[A+12>>2])|0)&1)+y|0,B=a[v>>2]),z=z+1|0,(z|0)>=(B|0)){var G=y;break b}}}else{G=0}}while(0);do{if(0==(G|D|0)){a[h+(q<<2)>>2]=x,v=q+1|0}else{if(0!=n[x+163|0]<<24>>24|0!=(D|0)){v=q}else{v=(q<<2)+h|0;t=Ll(b,x,v,d);b:do{if(0==(a[f>>2]&1|0)&&(w=q-1+t|0,(q|0)<(w|0))){w=(w<<2)+h|0;for(y=v;;){if(z=a[y>>2],a[y>>2]=a[w>>2],a[w>>2]=z,y=y+4|0,w=w-4|0,y>>>0>=w>>>0){break b}}}}while(0);v=t+q|0}}}while(0);m=m+1|0;x=a[c];t=a[x+(44*d&-1)>>2];if((m|0)<(t|0)){q=v,w=x}else{break}}if(0!=(v|0)&0<(t|0)){q=a[1345325];m=0;for(w=x;;){var H=a[h+(m<<2)>>2];a[a[w+(44*d&-1)+4>>2]+(m<<2)>>2]=H;a[H+240>>2]=(a[a[c]+(44*d&-1)+4>>2]-a[a[q+220>>2]+(44*d&-1)+4>>2]>>2)+m|0;var m=m+1|0,H=a[c],J=a[H+(44*d&-1)>>2];if((m|0)<(J|0)){w=H}else{break}}if(0<(J|0)){q=0;for(m=H;;){w=a[a[m+(44*d&-1)+4>>2]+(q<<2)>>2]+192|0;y=a[w>>2];if(0==(y|0)){z=m}else{if(B=a[y>>2],0==(B|0)){z=m}else{z=0;A=B;for(B=y;!((a[a[A+12>>2]+240>>2]|0)<(a[a[A+16>>2]+240>>2]|0)&&(wl(A),Il(b,A),z=z-1|0,B=a[w>>2]),z=z+1|0,A=a[B+(z<<2)>>2],0==(A|0));){}z=a[c]}}q=q+1|0;if((q|0)<(a[z+(44*d&-1)>>2]|0)){m=z}else{break a}}}}}}while(0);n[a[a[1345325]+220>>2]+(44*d&-1)+33|0]=0;d=d+1|0;if((d|0)>(C[e>>1]<<16>>16|0)){break}}0!=(k|0)&&E(k)}}}function Ar(c){var d=a[c+216>>2];a:do{if(0!=(d|0)){for(var g=d;;){var e=g+32|0;a[g+240>>2]=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])&-1;g=a[g+168>>2];if(0==(g|0)){break a}}}}while(0);g=C[c+244>>1];d=c+246|0;if(g<<16>>16<=C[d>>1]<<16>>16){c=c+220|0;for(g=g<<16>>16;!(n[a[a[1345325]+220>>2]+(44*g&-1)+33|0]=0,e=a[c>>2],af(a[e+(44*g&-1)+4>>2],a[e+(44*g&-1)>>2],346),g=g+1|0,(g|0)>(C[d>>1]<<16>>16|0));){}}}function Dr(b){var c,d,e,f=C[b+246>>1],h=b+244|0;if(f<<16>>16>=C[h>>1]<<16>>16){e=(b+220|0)>>2;for(var f=f<<16>>16,j=a[e];;){n[j+(44*f&-1)+32|0]=0;j=a[e];a:do{if(0<(a[j+(44*f&-1)>>2]-1|0)){for(var k=0<(f|0),i=f+1|0,q=0,m=j;;){var w=a[m+(44*f&-1)+4>>2],m=a[w+(q<<2)>>2];d=m>>2;q=q+1|0;w=a[w+(q<<2)>>2];c=w>>2;(a[d+60]|0)<(a[c+60]|0)||ia(5346728,474,5380136,5336908);if(0==(Di(b,m,w)|0)){if(k){var x=nh(m,a[c+44]),v=nh(w,a[d+44])}else{v=x=0}0<(a[a[e]+(44*i&-1)>>2]|0)?(c=oh(m,a[c+46])+x|0,d=oh(w,a[d+46])+v|0):(c=x,d=v);(d|0)>(c|0)||Kr(b,f,m,w)}m=a[e];if((q|0)>=(a[m+(44*f&-1)>>2]-1|0)){var t=m;break a}}}else{t=j}}while(0);f=f-1|0;if((f|0)<(C[h>>1]<<16>>16|0)){break}else{j=t}}}}function Kr(b,c,d,e){var f=0,h=n[d+162|0];if(h<<24>>24!=n[e+162|0]<<24>>24){var b=b+220|0,j=a[b>>2],k=a[j+(44*c&-1)>>2],i=0<(k|0);do{if(i){for(var q=a[j+(44*c&-1)+4>>2],m=0,w=0,x=0;;){var v=0==n[a[q+(x<<2)>>2]+162|0]<<24>>24&1,t=v+m|0,v=(v^1)+w|0,x=x+1|0;if((x|0)<(k|0)){m=t,w=v}else{break}}q=0==h<<24>>24;if((t|0)<(v|0)){var y=q?d:e}else{var z=q,f=2104}}else{z=0==h<<24>>24,f=2104}}while(0);2104==f&&(y=z?e:d);f=j+(44*c&-1)+4|0;a:do{if(i){h=a[f>>2];for(t=0;;){var B;B=(a[h+(t<<2)>>2]|0)==(y|0)?t:B;t=t+1|0;if((t|0)>=(k|0)){var A=B,C=f;break a}}}else{C=f}}while(0);B=0==n[y+162|0]<<24>>24&1;f=A;for(i=0;;){h=f-1|0;if(0>=(f|0)){var E=A,G=0;break}if((n[a[a[C>>2]+(h<<2)>>2]+162|0]<<24>>24|0)==(B|0)){f=h,i=i+1|0}else{E=A;G=0;break}}for(;;){E=E+1|0;if((E|0)>=(k|0)){break}if((n[a[a[C>>2]+(E<<2)>>2]+162|0]<<24>>24|0)==(B|0)){G=G+1|0}else{break}}mh(d,e);b=a[b>>2];C=a[b+(44*c&-1)>>2];c=b+(44*c&-1)+4|0;a:do{if(0<(C|0)){b=a[c>>2];k=A;for(E=0;;){if(k=(a[b+(E<<2)>>2]|0)==(y|0)?E:k,E=E+1|0,(E|0)>=(C|0)){var H=k,I=c;break a}}}else{H=A,I=c}}while(0);A=H;for(y=0;;){c=A-1|0;if(0>=(A|0)){var J=H,T=0;break}if((n[a[a[I>>2]+(c<<2)>>2]+162|0]<<24>>24|0)==(B|0)){A=c,y=y+1|0}else{J=H;T=0;break}}for(;;){H=J+1|0;if((H|0)>=(C|0)){break}if((n[a[a[I>>2]+(H<<2)>>2]+162|0]<<24>>24|0)==(B|0)){J=H,T=T+1|0}else{break}}I=y-T|0;G=i-G|0;((-1<(I|0)?I:-I|0)|0)>((-1<(G|0)?G:-G|0)|0)&&mh(d,e)}}function Lr(b){var c,d,b=b>>2;if(0<(a[b+51]|0)){d=a[b+50]>>2;var e=a[a[d]+16>>2],f=a[d+1];a:do{if(0==(f|0)){c=e}else{for(var h=1,j=e,k=f;;){if(k=a[k+16>>2],j=(a[k+240>>2]|0)>(a[j+240>>2]|0)?k:j,h=h+1|0,k=a[(h<<2>>2)+d],0==(k|0)){c=j;break a}}}}while(0);c=a[c+244>>2];if(-1>=(c|0)){return 1}a[b+61]=c+1|0;return 0}if(0>=(a[b+49]|0)){return 1}c=a[b+48]>>2;e=a[a[c]+12>>2];f=a[c+1];a:do{if(0==(f|0)){d=e}else{h=1;j=e;for(k=f;;){if(k=a[k+12>>2],j=(a[k+240>>2]|0)<(a[j+240>>2]|0)?k:j,h=h+1|0,k=a[(h<<2>>2)+c],0==(k|0)){d=j;break a}}}}while(0);c=a[d+244>>2];if(0>=(c|0)){return 1}a[b+61]=c-1|0;return 0}function Cr(b,c,d){var e,f,h=0,j=a[1345159];f=j>>2;var b=(b+220|0)>>2,k=a[b],i=a[k+(44*c&-1)+4>>2];if(0>=(a[k+(44*c&-1)>>2]|0)){var q;return 0}for(var d=(d|0)>(c|0),k=j+4|0,m=0;;){var n=a[i+(m<<2)>>2];e=n>>2;a:do{if(d){var x=n+184|0,v=a[x>>2],t=a[v>>2];if(0==(t|0)){h=2158}else{for(var y=0,z=0;;){if(0<C[t+162>>1]<<16>>16&&(a[(z<<2>>2)+f]=ca[t+100|0]|a[a[t+12>>2]+240>>2]<<8,z=z+1|0,v=a[x>>2]),y=y+1|0,t=a[v+(y<<2)>>2],0==(t|0)){var B=z,h=2157;break a}}}}else{if(x=n+176|0,v=a[x>>2],t=a[v>>2],0==(t|0)){h=2158}else{for(z=y=0;;){if(0<C[t+162>>1]<<16>>16&&(a[(z<<2>>2)+f]=ca[t+60|0]|a[a[t+16>>2]+240>>2]<<8,z=z+1|0,v=a[x>>2]),y=y+1|0,t=a[v+(y<<2)>>2],0==(t|0)){B=z;h=2157;break a}}}}}while(0);2157==h&&(h=0,0==(B|0)?h=2158:1==(B|0)?a[e+61]=a[f]:2==(B|0)?a[e+61]=(a[k>>2]+a[f]|0)/2&-1:(af(j,B,18),y=(B|0)/2&-1,0!=(B&1|0)?a[e+61]=a[(y<<2>>2)+f]:(n=a[(y<<2>>2)+f],x=a[(B-1<<2>>2)+f]-n|0,y=a[(y-1<<2>>2)+f],z=y-a[f]|0,a[e+61]=(z|0)==(x|0)?(y+n|0)/2&-1:(Math.a(y,x)+Math.a(z,n)|0)/(z+x|0)&-1)));2158==h&&(h=0,a[e+61]=-1);m=m+1|0;e=a[b];n=a[e+(44*c&-1)>>2];if((m|0)>=(n|0)){break}}if(0<(n|0)){h=f=0,j=e}else{return 0}for(;;){if(B=a[i+(f<<2)>>2],0==(a[B+188>>2]|0)&&0==(a[B+180>>2]|0)&&(h=(Lr(B)|h&255)&255,j=a[b]),f=f+1|0,(f|0)>=(a[j+(44*c&-1)>>2]|0)){q=h;break}}return q}function Br(b,c,d,e){var f,h=a[b+220>>2],j=a[h+(44*c&-1)+4>>2],k=a[h+(44*c&-1)>>2];if(0<(k|0)){for(var h=0==(d|0),d=0==(e|d|0),i=0,e=(k<<2)+j|0;;){var k=k-1|0,q=j,m=i;a:for(;;){i=q;b:for(;;){if(i>>>0>=e>>>0){break a}for(;;){if(i>>>0>=e>>>0){break a}var w=a[i>>2],x=a[w+244>>2];if(0>(x|0)){i=i+4|0}else{var v=i,t=0;break}}for(;;){i=0==t<<24>>24;for(q=v;;){var y=q+4|0;if(y>>>0>=e>>>0){break a}var z=a[y>>2];f=z>>2;if(i){break}if(0==(a[f+54]|0)){break}else{q=y}}if(0!=(Di(b,w,z)|0)){i=y;continue b}var B=a[f+61];if(-1<(B|0)){break}v=y;t=0==(a[f+54]|0)?t:1}if((x|0)<=(B|0)&((x|0)!=(B|0)|h)){i=y}else{break}}mh(w,z);q=y;m=m+1|0}if(0<(k|0)){i=m,e=d?e-4|0:e}else{break}}0!=(m|0)&&(b=a[1345325]+220|0,n[a[b>>2]+(44*c&-1)+33|0]=0,0<(c|0)&&(n[a[b>>2]+(44*(c-1)&-1)+33|0]=0))}}function Ll(b,c,d,e){n[c+163|0]=1;a:do{if(0<(a[c+196>>2]|0)){var f=c+192|0,h=a[a[f>>2]>>2];if(0==(h|0)){var j=0}else{for(var k=b,i=0,q=0;;){if(0!=hb[h+164>>2]){var m=h+12|0,w=a[m>>2];0==n[w+162|0]<<24>>24&0==(fd(k,w|0)|0)||(m=a[m>>2],q=(a[m+216>>2]|0)!=(a[a[h+16>>2]+216>>2]|0)?q:0!=n[m+163|0]<<24>>24?q:Ll(b,m,(q<<2)+d|0,e)+q|0)}i=i+1|0;h=a[a[f>>2]+(i<<2)>>2];if(0==(h|0)){j=q;break a}}}}else{j=0}}while(0);if((a[c+236>>2]|0)==(e|0)){return a[((j<<2)+d|0)>>2]=c,j+1|0}ia(5346728,1161,5379516,5366084);a[((j<<2)+d|0)>>2]=c;return j+1|0}function Kl(b,c){var d,e,f,h=0,j=a[a[b+220>>2]+(44*a[c+236>>2]&-1)+40>>2];n[c+163|0]=1;var k=c+164|0;n[k]=1;var i=0<(a[a[b+32>>2]+208>>2]|0),q=c+192|0;f=a[q>>2];if(0!=(f|0)){var m=a[f>>2];if(0!=(m|0)){var w=j|0;f=(j+4|0)>>2;var j=j+8|0,x=0;for(e=m>>2;;){i?0==(fd(b,a[e+4]|0)|0)?d=x:0==(fd(b,a[e+3]|0)|0)?d=x:h=2222:h=2222;if(2222==h){h=0;if(0!=hb[e+41]){d=(m+12|0)>>2;e=a[d];var v=(a[e+284>>2]|0)<(a[w>>2]|0);if(1==n[e+164|0]<<24>>24){v||ia(5346728,933,5379788,5363580);e=m+16|0;var v=a[a[e>>2]+284>>2],t=a[f];(v|0)<(t|0)?e=v:(ia(5346728,934,5379788,5362656),t=a[f],e=a[a[e>>2]+284>>2]);n[(e+Math.a(t,a[a[d]+284>>2])|0)+a[j>>2]|0]=1;wl(m);x=x-1|0;4!=n[m+124|0]<<24>>24&&Il(b,m)}else{v||ia(5346728,942,5379788,5363580),e=m+16|0,v=a[a[e>>2]+284>>2],m=a[f],(v|0)<(m|0)?e=v:(ia(5346728,943,5379788,5362656),e=a[a[e>>2]+284>>2],m=a[f]),n[Math.a(m,e)+(a[j>>2]+a[a[d]+284>>2])|0]=1,d=a[d],0==n[d+163|0]<<24>>24&&Kl(b,d)}}d=x}x=d+1|0;m=a[a[q>>2]+(x<<2)>>2];if(0==(m|0)){break}else{e=m>>2}}}}n[k]=0}function or(c,d){if(0!=(a[c+216>>2]|0)){dl(c);Ml(c);0!=n[5382112]<<24>>24&&Qq(c);var g;Mr(c);g=a[c+216>>2];if(0!=(g|0)){for(g>>=2;;){var e=a[g+57];0!=(e|0)&&Nl(c,e);e=a[g+58];0!=(e|0)&&Nl(c,e);e=a[g+52];a:do{if(0!=(e|0)){for(var h=0;;){if(0==(a[e+(h<<2)>>2]|0)){break a}else{h=h+1|0}}}}while(0);g=a[g+42];if(0==(g|0)){break}else{g>>=2}}}0!=(ur(c)|0)&&Ml(c);Nr(a[c+216>>2]);Or(c);Pr(c);0<(a[c+208>>2]|0)&&(Qr(c),Ol(c),Rr(c),Pl(c));e=a[c+44>>2];3==(a[e+84>>2]|0)&&(g=e+64|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),e=e+72|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),1<g*e&&(Ql(c),g=0==(a[c+152>>2]&1|0)?g:e,Hc(a[c+264>>2],a[c+268>>2],65535>g?g:65535,1e3)));0!=(Nj(c,2,Sr(c))|0)&&(Tr(c),0!=(Nj(c,2,Sr(c))|0)&&ia(5374652,133,5379884,5375748));g=a[c+220>>2];var h=C[c+244>>1],e=c+246|0,i=C[e>>1];if(h<<16>>16<=i<<16>>16){for(var h=h<<16>>16,j=i;;){i=g+(44*h&-1)|0;if(0<(a[i>>2]|0)){for(var j=g+(44*h&-1)+4|0,k=0;;){var r=a[a[j>>2]+(k<<2)>>2],q=r+236|0,r=r+32|0;f[b>>3]=a[q>>2]|0;a[r>>2]=a[b>>2];a[r+4>>2]=a[b+4>>2];a[q>>2]=h;k=k+1|0;if((k|0)>=(a[i>>2]|0)){break}}i=C[e>>1]}else{i=j}h=h+1|0;if((h|0)>(i<<16>>16|0)){break}else{j=i}}}Ur(c,d);Vr(c)}}function Ml(c){var d,g,e,h,i=a[c+220>>2];h=i>>2;e=(c+244|0)>>1;var j=C[e];g=(c+246|0)>>1;var k=C[g];a:do{if(j<<16>>16<=k<<16>>16){for(var r=j<<16>>16,q=k;;){var m=i+(44*r&-1)|0;if(0<(a[m>>2]|0)){for(var q=i+(44*r&-1)+4|0,w=i+(44*r&-1)+28|0,x=i+(44*r&-1)+20|0,v=i+(44*r&-1)+24|0,t=i+(44*r&-1)+16|0,y=0;;){var z=a[a[q>>2]+(y<<2)>>2],B=z+96|0,B=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3]),B=(((0>B?B-.5:B+.5)&-1)+1|0)/2&-1,A=a[z+208>>2];b:do{if(0==(A|0)){var D=B}else{if(d=a[A>>2],0==(d|0)){D=B}else{var E=B,G=0;for(d>>=2;;){if((a[d+4]|0)==(a[d+3]|0)&&(d=a[d+27],0!=(d|0)&&(E|=0,d=d+32|0,d=.5*(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),E=(E>d?E:d)&-1)),G=G+1|0,d=a[A+(G<<2)>>2],0==(d|0)){D=E;break b}else{d>>=2}}}}}while(0);(a[w>>2]|0)<(D|0)&&(a[x>>2]=D,a[w>>2]=D);(a[v>>2]|0)<(D|0)&&(a[t>>2]=D,a[v>>2]=D);A=a[z+216>>2];0!=(A|0)&&(B=(A|0)==(c|0)?0:8,z=z+236|0,G=a[z>>2],(G|0)==(C[A+244>>1]<<16>>16|0)?(G=A+160|0,E=a[G>>2],d=B+D|0,a[G>>2]=(E|0)>(d|0)?E:d,z=a[z>>2]):z=G,(z|0)==(C[A+246>>1]<<16>>16|0)&&(z=A+156|0,A=a[z>>2],B=B+D|0,a[z>>2]=(A|0)>(B|0)?A:B));y=y+1|0;if((y|0)>=(a[m>>2]|0)){break}}m=C[g]}else{m=q}r=r+1|0;if((r|0)>(m<<16>>16|0)){break a}else{q=m}}}}while(0);i=Rl(c);D=C[g]<<16>>16;j=a[a[((44*D&-1)+4>>2)+h]>>2]+40|0;f[b>>3]=a[((44*D&-1)+16>>2)+h]|0;a[j>>2]=a[b>>2];a[j+4>>2]=a[b+4>>2];q=D-1|0;m=C[e];if((q|0)<(m<<16>>16|0)){var H=0,I=m}else{j=c+260|0;k=0;r=D;for(D=q;!(I=a[((44*D&-1)+24>>2)+h]+a[((44*r&-1)+28>>2)+h]+a[j>>2]|0,H=a[((44*r&-1)+20>>2)+h]+a[((44*D&-1)+16>>2)+h]+8|0,H=(I|0)>(H|0)?I:H,0<(a[((44*D&-1)>>2)+h]|0)?(I=a[a[((44*r&-1)+4>>2)+h]>>2]+40|0,I=(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3])+(H|0),r=a[a[((44*D&-1)+4>>2)+h]>>2]+40|0,f[b>>3]=I,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],I=C[e]):I=m,H=(k|0)>(H|0)?k:H,m=D-1|0,(m|0)<(I<<16>>16|0));){k=H,r=D,D=m,m=I}H|=0}j=c+284|0;a:do{if(0!=n[j]<<24>>24&&(D=C[g]<<16>>16,k=D-1|0,(k|0)>=(I<<16>>16|0))){for(r=I;;){if(0<(a[((44*k&-1)>>2)+h]|0)&&(D=a[a[((44*D&-1)+4>>2)+h]>>2]+40|0,D=(a[b>>2]=a[D>>2],a[b+4>>2]=a[D+4>>2],f[b>>3])+H,r=a[a[((44*k&-1)+4>>2)+h]>>2]+40|0,f[b>>3]=D,a[r>>2]=a[b>>2],a[r+4>>2]=a[b+4>>2],r=C[e]),m=k-1|0,(m|0)<(r<<16>>16|0)){break a}else{D=k,k=m}}}}while(0);0!=(i|0)&&0!=(a[c+152>>2]&1|0)&&Sl(c,ca[j]);c=a[c+216>>2];if(0!=(c|0)){for(;!(g=a[a[((44*a[c+236>>2]&-1)+4>>2)+h]>>2]+40|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),e=c+40|0,f[b>>3]=g,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],c=a[c+168>>2],0==(c|0));){}}}function Sr(b){var c=U(b|0,5330248);return 0==(c|0)?2147483647:b=Oe(c,Ac)*Mb(a[b+20>>2])&-1}function Tr(b){var c=0,d=C[b+244>>1],e=b+246|0,f=C[e>>1];if(d<<16>>16<=f<<16>>16){for(var h=b+220|0,d=d<<16>>16;;){var j=a[h>>2],k=a[j+(44*d&-1)>>2],i=j+(44*d&-1)+4|0,q=0,m=0;a:for(;;){if((q|0)>=(k|0)){c=2337;break}var w=a[a[i>>2]+(q<<2)>>2],x=a[w+256>>2];b:do{if(0!=(x|0)){for(var v=0;;){var t=a[x+(v<<2)>>2];if(0==(t|0)){break b}if((a[a[t+12>>2]+236>>2]|0)>(d|0)){var y=f;break a}if((a[a[t+16>>2]+236>>2]|0)>(d|0)){y=f;break a}else{v=v+1|0}}}}while(0);x=a[w+248>>2];b:do{if(0!=(x|0)){for(v=0;;){t=a[x+(v<<2)>>2];if(0==(t|0)){break b}if((a[a[t+16>>2]+236>>2]|0)>(d|0)){y=f;break a}if((a[a[t+12>>2]+236>>2]|0)>(d|0)){y=f;break a}else{v=v+1|0}}}}while(0);q=q+1|0;m=w}2337==c&&(c=0,0==(m|0)?y=f:(y=a[a[i>>2]>>2],j=a[a[j+(44*(((d|0)<(f<<16>>16|0)?1:-1)+d)&-1)+4>>2]>>2],0==(j|0)&&ia(5374652,110,5380064,5327696),f=Me(b),n[f+162|0]=2,Hc(f,y,0,0),Hc(f,j,0,0),y=a[y+236>>2],j=a[j+236>>2],a[f+236>>2]=(y|0)<(j|0)?y:j,y=C[e>>1]));d=d+1|0;if((d|0)>(y<<16>>16|0)){break}else{f=y}}}}function Ur(c,d){var g,e,h;Wr(c,c);a:do{if(0<C[c+246>>1]<<16>>16){var i=c+44|0,j=a[i>>2],k=a[j+84>>2];if(0!=(k|0)){h=(c+68|0)>>2;e=c+52|0;g=(a[b>>2]=a[h],a[b+4>>2]=a[h+1],f[b>>3])-(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])&-1;e=(c+76|0)>>2;var r=c+60|0,q=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])-(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3])&-1,r=c+152|0,m=0==(a[r>>2]&1|0),n=m?q:g;g=m?g:q;4==(k|0)?(k=Xr(c),i=a[i>>2]):(k=2==(k|0)&1,i=j);do{if(0==k<<24>>24){if(j=a[i+84>>2],5==(j|0)){j=i+64|0;j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);if(0>=j){break a}j/=(a[b>>2]=a[h],a[b+4>>2]=a[h+1],f[b>>3]);q=i+72|0;q=(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])/(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);if(!(1<j&1<q)){break a}j=q=j<q?j:q}else{if(1==(j|0)){j=i+16|0,q=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),m=(n|0)/(g|0),m<q?(j=1,q/=m):(j=m/q,q=1)}else{break a}}}else{j=i+64|0;j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);if(0>=j){break a}q=j/(g|0);j=i+72|0;m=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])/(n|0);1>q|1>m?q<m?(j=1,q=m/q):(j=q/m,q=1):(j=q,q=m)}}while(0);h=(e=0==(a[r>>2]&1|0))?q:j;e=e?j:q;r=a[c+216>>2];b:do{if(0!=(r|0)){for(n=r;;){if(g=(n+32|0)>>2,k=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])*e,f[b>>3]=(0>k?k-.5:k+.5)&-1|0,a[g]=a[b>>2],a[g+1]=a[b+4>>2],g=(n+40|0)>>2,k=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])*h,f[b>>3]=(0>k?k-.5:k+.5)&-1|0,a[g]=a[b>>2],a[g+1]=a[b+4>>2],n=a[n+168>>2],0==(n|0)){break b}}}}while(0);Yr(c,e,h)}}}while(0);0!=(d|0)&&(h=c+68|0,e=c+52|0,h=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])-(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),e=c+76|0,r=c+60|0,h/=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),e=d|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),h>1.1*e?a[d+24>>2]=e*(a[d+20>>2]-a[d+16>>2]|0)/h&-1:a[(d+24|0)>>2]=h>.8*e?0:-1)}function Vr(b){var b=(b+216|0)>>2,c=a[b];do{if(0==(c|0)){var d=0,e=0}else{for(d=c;;){var e=d+184|0,f=e|0,h=a[f>>2],j=a[h>>2];a:do{if(0==(j|0)){var k=h}else{for(var i=0,q=j;;){E(q|0);var i=i+1|0,m=a[f>>2],q=a[m+(i<<2)>>2];if(0==(q|0)){k=m;break a}}}}while(0);0!=(k|0)&&E(k);f=d+176|0;h=a[f>>2];0!=(h|0)&&E(h);h=d+256|0;j=a[h+4>>2];a[e>>2]=a[h>>2];a[e+4>>2]=j;e=d+248|0;h=a[e+4>>2];a[f>>2]=a[e>>2];a[f+4>>2]=h;d=a[d+168>>2];if(0==(d|0)){break}}d=0;e=a[b]}}while(0);a:for(;;){k=0==(d|0);c=d+168|0;for(f=e;;){if(0==(f|0)){break a}h=a[f+168>>2];if(2!=n[f+162|0]<<24>>24){d=f;e=h;continue a}k?a[b]=h:a[c>>2]=h;E(f|0);f=h}}a[a[b]+172>>2]=0}function Hc(b,c,d,e){var f=da(184);a[f+16>>2]=b;a[f+12>>2]=c;65535<d&&Zr(d);C[f+178>>1]=(0>d?d-.5:d+.5)&65535;hb[f+164>>2]=e|0;vl(f);return f}function Zr(c){aa(1,5333284,(i=h,h=h+12|0,f[b>>3]=c,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],a[i+8>>2]=65535,i));Qd()}function eh(c,d){var g=n[c+96|0];if(g<<24>>24!=n[d+96|0]<<24>>24){return 0}var e=c+68|0,h=d+68|0;if((a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])==(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])){if(e=c+76|0,h=d+76|0,!((a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])==(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])|0==g<<24>>24)){return 0}}else{if(0!=g<<24>>24){return 0}}g=c+28|0;e=d+28|0;if((a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])==(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])){if(g=c+36|0,e=d+36|0,(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])==(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])){return 1}}g=0==n[c+56|0]<<24>>24;return g&1}function $r(c,d,g,e,h){var i=c|0;f[b>>3]=d-e;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];c=c+8|0;f[b>>3]=g-h;a[c>>2]=a[b>>2];a[c+4>>2]=a[b+4>>2]}function as(c,d){var g;a:do{if((a[c+32>>2]|0)==(c|0)){var e=C[c+244>>1],h=C[c+246>>1];b:do{if(e<<16>>16>h<<16>>16){var i=-2147483647,j=2147483647}else{for(var k=a[c+220>>2],r=h<<16>>16,q=-2147483647,m=2147483647,w=e<<16>>16;;){var x=a[k+(44*w&-1)>>2];do{if(0==(x|0)){g=m;var v=q}else{if(g=a[k+(44*w&-1)+4>>2]>>2,v=a[g],0==(v|0)){g=m,v=q}else{var t=n[v+162|0];c:do{if(0!=t<<24>>24&1<(x|0)){for(var y=1;;){var z=a[(y<<2>>2)+g],y=y+1|0,B=n[z+162|0];if(!(0!=B<<24>>24&(y|0)<(x|0))){var A=z,D=B;break c}}}else{A=v,D=t}}while(0);if(0!=D<<24>>24){g=m,v=q}else{v=A+32|0;t=A+104|0;v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3])-(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3])&-1|0;v=m<v?m:v;t=a[(x-1<<2>>2)+g];c:do{if(0==n[t+162|0]<<24>>24){var E=t}else{for(z=x-2|0;;){if(y=a[(z<<2>>2)+g],0==n[y+162|0]<<24>>24){E=y;break c}else{z=z-1|0}}}}while(0);g=E+32|0;t=E+112|0;t=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])+(a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3])&-1|0;g=v;v=q>t?q:t}}}}while(0);w=w+1|0;if((w|0)>(r|0)){i=v;j=g;break b}else{q=v,m=g}}}}while(0);k=a[c+208>>2];if(1>(k|0)){var G=j,H=i,I=h,J=e}else{r=a[c+212>>2];q=i;w=j;for(m=1;;){if(x=a[r+(m<<2)>>2],g=x+52|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])-8&-1|0,w=w<g?w:g,x=x+68|0,x=(a[b>>2]=a[x>>2],a[b+4>>2]=a[x+4>>2],f[b>>3])+8&-1|0,q=q>x?q:x,m=m+1|0,(m|0)>(k|0)){G=w;H=q;I=h;J=e;break a}}}}else{G=a[a[c+264>>2]+236>>2]|0,H=a[a[c+268>>2]+236>>2]|0,I=C[c+246>>1],J=C[c+244>>1]}}while(0);e=a[d+220>>2];I=a[a[e+(44*(I<<16>>16)&-1)+4>>2]>>2]+40|0;I=(a[b>>2]=a[I>>2],a[b+4>>2]=a[I+4>>2],f[b>>3])-(a[c+156>>2]|0);J=a[a[e+(44*(J<<16>>16)&-1)+4>>2]>>2]+40|0;J=(a[b>>2]=a[J>>2],a[b+4>>2]=a[J+4>>2],f[b>>3])+(a[c+160>>2]|0);e=c+52|0;f[b>>3]=G;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];G=c+60|0;f[b>>3]=I;a[G>>2]=a[b>>2];a[G+4>>2]=a[b+4>>2];G=c+68|0;f[b>>3]=H;a[G>>2]=a[b>>2];a[G+4>>2]=a[b+4>>2];H=c+76|0;f[b>>3]=J;a[H>>2]=a[b>>2];a[H+4>>2]=a[b+4>>2]}function Mr(b){var c=C[b+244>>1],d=b+246|0;if(c<<16>>16<=C[d>>1]<<16>>16){b=(b+220|0)>>2;for(c=c<<16>>16;;){var e=a[b],f=a[e+(44*c&-1)>>2];a:do{if(0<(f|0)){for(var h=0,j=0,k=e;;){k=a[a[k+(44*c&-1)+4>>2]+(j<<2)>>2];a[k+240>>2]=h;var h=(6==n[k+165|0]<<24>>24?a[k+220>>2]:1)+h|0,j=j+1|0,k=a[b],i=a[k+(44*c&-1)>>2];if((j|0)>=(i|0)){var q=h,m=k,w=i;break a}}}else{q=0,m=e,w=f}}while(0);if((q|0)>(w|0)){e=a[m+(44*c&-1)+4>>2];e=0==(e|0)?Za((q<<2)+4|0):Oa(e,(q<<2)+4|0);a[a[b]+(44*c&-1)+4>>2]=e;e=a[b];f=a[e+(44*c&-1)>>2];a:do{if(0<(f|0)){h=f;for(j=e;;){if(h=h-1|0,j=a[j+(44*c&-1)+4>>2],k=a[j+(h<<2)>>2],a[j+(a[k+240>>2]<<2)>>2]=k,j=a[b],0>=(h|0)){var x=j;break a}}}else{x=e}}while(0);a[x+(44*c&-1)>>2]=q;a[a[a[b]+(44*c&-1)+4>>2]+(q<<2)>>2]=0}c=c+1|0;if((c|0)>(C[d>>1]<<16>>16|0)){break}}}}function Nl(c,d){var g,e,l=d>>2,i=h;h=h+24|0;var j=i+8,k=i+16;if(2<=(a[l+55]|0)){var r=d+32|0,q=d+104|0,m=d+40|0;bs(i,d,(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3])-(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3])&-1,(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])&-1);q=a[i>>2];m=a[i+4>>2];if(0<(a[l+47]|0)){var n=a[l+60];e=cf(c,a[a[a[l+46]>>2]+12>>2]);if(0!=(e|0)){for(var k=j|0,l=j+4|0,r=c+24|0,x=m,v=q,m=n+1|0,q=e;;){n=q;e=q+16|0;g=a[e>>2];if((g|0)!=(d|0)&&(ec(g)|0)==(d|0)){cs(j,a[e>>2],v,x,m);v=a[k>>2];x=a[l>>2];rr(n);e=(q+12|0)>>2;g=(a[e]+24|0)>>2;var t=a[g+38];g=0==(t|0)?Za((a[g+39]<<2)+8|0):Oa(t,(a[g+39]<<2)+8|0);a[a[e]+176>>2]=g;g=a[e]+180|0;t=a[g>>2];a[g>>2]=t+1|0;a[a[a[e]+176>>2]+(t<<2)>>2]=n;n=a[e]+24|0;a[a[n+152>>2]+(a[n+156>>2]<<2)>>2]=0;m=m+1|0}n=v;q=ah(a[r>>2],q);if(0==(q|0)){break}else{v=n}}}}else{if(n=a[l+60],e=zb(c,a[a[a[l+44]>>2]+16>>2]),0!=(e|0)){j=k|0;l=k+4|0;r=c+28|0;x=m;v=q;m=n+1|0;for(q=e;!(n=q,e=q+12|0,g=a[e>>2],(g|0)!=(d|0)&&(ec(g)|0)==(d|0)&&(cs(k,a[e>>2],v,x,m),v=a[j>>2],x=a[l>>2],rr(n),e=(q+16|0)>>2,g=(a[e]+24|0)>>2,t=a[g+40],g=0==(t|0)?Za((a[g+41]<<2)+8|0):Oa(t,(a[g+41]<<2)+8|0),a[a[e]+184>>2]=g,g=a[e]+188|0,t=a[g>>2],a[g>>2]=t+1|0,a[a[a[e]+184>>2]+(t<<2)>>2]=n,n=a[e]+24|0,a[a[n+160>>2]+(a[n+164>>2]<<2)>>2]=0,m=m+1|0),n=v,q=Db(a[r>>2],q),0==(q|0));){v=n}}}}h=i}function bs(c,d,g,e){var h=d+20|0;Hj(d,a[a[h>>2]+152>>2]&1);var i=d+40|0;f[b>>3]=e|0;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];i=d+104|0;g=(g|0)+(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);i=d+32|0;f[b>>3]=g;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];d=d+112|0;a[c>>2]=g+(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])+a[a[h>>2]+256>>2]&-1;a[c+4>>2]=e}function cs(b,c,d,e,f){var h=a[c+20>>2],j=ec(c);if((j|0)!=(c|0)){var k;(j|0)==(c|0)&&ia(5340216,220,5379832,5344412);var i=c+168|0;0!=(a[i>>2]|0)&&ia(5340216,221,5379832,5340836);k=(j+168|0)>>2;a[i>>2]=a[k];i=a[k];0!=(i|0)&&(a[i+172>>2]=c);i=c+172|0;a[i>>2]=j;a[k]=c}a[c+240>>2]=f;j=a[j+236>>2];a[c+236>>2]=j;a[a[a[h+220>>2]+(44*j&-1)+4>>2]+(f<<2)>>2]=c;bs(b,c,d,e)}function Wr(b,c){var d=b+208|0;if(1<=(a[d>>2]|0)){for(var e=b+212|0,f=1;!(Wr(a[a[e>>2]+(f<<2)>>2],c),f=f+1|0,(f|0)>(a[d>>2]|0));){}}as(b,c)}function Xr(c){var d,g=h;h=h+32|0;var e=g+16;d=(c+44|0)>>2;var l=a[d],i=l+48|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),j=l+56|0,k=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);if(.001>i|.001>k){return h=g,0}j=l+32|0;j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);l=l+40|0;l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);$r(g,i,k,j,l);i=g|0;k=g+8|0;$r(e,(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),j,l);i=e|0;i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);e=e+8|0;j=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);e=c+68|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);c=c+76|0;c=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);l=i/e;k=j/c;if(!(1>l|1>k)){return h=g,0}l=l<k?l:k;l=.5<l?l:.5;j=Math.ceil(l*c/j)*j/c;k=a[d]+64|0;f[b>>3]=e*(Math.ceil(l*e/i)*i/e);a[k>>2]=a[b>>2];a[k+4>>2]=a[b+4>>2];d=a[d]+72|0;f[b>>3]=c*j;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];h=g;return 1}function Yr(c,d,g){var e;e=c+208|0;a:do{if(1<=(a[e>>2]|0)){for(var h=c+212|0,i=1;;){if(Yr(a[a[h>>2]+(i<<2)>>2],d,g),i=i+1|0,(i|0)>(a[e>>2]|0)){break a}}}}while(0);e=(c+52|0)>>2;h=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])*d;f[b>>3]=h;a[e]=a[b>>2];a[e+1]=a[b+4>>2];e=(c+60|0)>>2;h=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])*g;f[b>>3]=h;a[e]=a[b>>2];a[e+1]=a[b+4>>2];e=(c+68|0)>>2;d*=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);f[b>>3]=d;a[e]=a[b>>2];a[e+1]=a[b+4>>2];c=(c+76|0)>>2;g*=(a[b>>2]=a[c],a[b+4>>2]=a[c+1],f[b>>3]);f[b>>3]=g;a[c]=a[b>>2];a[c+1]=a[b+4>>2]}function ds(c,d){var g,e,h,i,j=a[c+32>>2];i=a[j+220>>2]>>2;var k=C[c+246>>1]<<16>>16,r=C[c+244>>1]<<16>>16,q=a[((44*r&-1)+20>>2)+i];h=(c+160|0)>>2;var m=a[h];g=q-m|0;var n=a[((44*k&-1)+16>>2)+i];e=(c+156|0)>>2;var x=a[e],v=n-x|0;if((v+g|0)<(d|0)){q=k-r|0;q=(q+(d+1)|0)/(q+2|0)&-1;g=(C[j+246>>1]<<16>>16)-1|0;j=j+244|0;n=C[j>>1];if((g|0)<(n<<16>>16|0)){i=m}else{x=q;m=g;for(g=n;!(0<(a[((44*m&-1)>>2)+i]|0)&&(g=(a[a[((44*m&-1)+4>>2)+i]>>2]+40|0)>>2,n=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])+(x|0),f[b>>3]=n,a[g]=a[b>>2],a[g+1]=a[b+4>>2],g=C[j>>1]),m=m-1|0,(m|0)<(g<<16>>16|0));){x=x+q|0}i=a[h];x=a[e]}a[h]=i+q|0;a[e]=x+q|0}else{i=(d+1|0)/2&-1,(g|0)>(v|0)?(i|0)>(v|0)?(a[e]=n,a[h]=d-v+m|0):(a[e]=i+x|0,a[h]=d-i+m|0):(i|0)>(g|0)?(a[h]=q,a[e]=d-g+x|0):(a[h]=i+m|0,a[e]=d-i+x|0)}}function es(c,d){var g,e,h,i,j=a[c+32>>2];e=a[j+220>>2]>>2;g=C[c+246>>1];var k=g<<16>>16,r=C[c+244>>1],q=r<<16>>16,m=(d+1|0)/2&-1;i=(c+156|0)>>2;var n=a[i]+m-a[((44*k&-1)+16>>2)+e]|0;if(0<(n|0)){a:do{if(g<<16>>16>=r<<16>>16){for(var x=n|0,v=k;;){if(0<(a[((44*v&-1)>>2)+e]|0)){h=(a[a[((44*v&-1)+4>>2)+e]>>2]+40|0)>>2;var t=(a[b>>2]=a[h],a[b+4>>2]=a[h+1],f[b>>3])+x;f[b>>3]=t;a[h]=a[b>>2];a[h+1]=a[b+4>>2]}h=v-1|0;if((h|0)<(q|0)){break a}else{v=h}}}}while(0);g=a[c+160>>2];n=d-m+n+g-a[((44*q&-1)+20>>2)+e]|0}else{g=a[c+160>>2],n=d-m+g-a[((44*q&-1)+20>>2)+e]|0}if(0<(n|0)){k=q-1|0;j=j+244|0;r=C[j>>1];if((k|0)<(r<<16>>16|0)){e=g,j=c+160|0}else{q=n|0;n=k;for(g=r;!(0<(a[((44*n&-1)>>2)+e]|0)&&(g=(a[a[((44*n&-1)+4>>2)+e]>>2]+40|0)>>2,k=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3])+q,f[b>>3]=k,a[g]=a[b>>2],a[g+1]=a[b+4>>2],g=C[j>>1]),n=n-1|0,(n|0)<(g<<16>>16|0));){}j=c+160|0;e=a[j>>2]}q=(d-m|0)+e|0;a[j>>2]=q}else{e=(c+160|0)>>2,q=(d-m|0)+g|0,a[e]=q}e=a[i];m=e+m|0;a[i]=m}function Rl(c){var d,g,e=c+32|0,h=a[e>>2],i=a[h+220>>2];g=(c+156|0)>>2;var j=a[g];d=(c+160|0)>>2;var k=a[d],r=c+208|0;if(1>(a[r>>2]|0)){var r=k,q=j,m=0,e=h}else{for(var h=c+212|0,n=c+246|0,x=c+244|0,v=1,t=0;;){var y=a[a[h>>2]+(v<<2)>>2],m=Rl(y)|t;C[y+246>>1]<<16>>16==C[n>>1]<<16>>16?(q=a[y+156>>2]+8|0,q=(j|0)>(q|0)?j:q):q=j;C[y+244>>1]<<16>>16==C[x>>1]<<16>>16?(y=a[y+160>>2]+8|0,y=(k|0)>(y|0)?k:y):y=k;v=v+1|0;if((v|0)>(a[r>>2]|0)){break}else{k=y,j=q,t=m}}r=y;e=a[e>>2]}if((e|0)==(c|0)){return a[g]=q,a[d]=r,m}0==(a[c+48>>2]|0)?(a[g]=q,d=a[d]=r,g=q,e=m):(0==(a[e+152>>2]&1|0)?(m=c+92|0,e=c+124|0,m=q+(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])&-1,e=r+(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])&-1):(m=q,e=r),a[g]=m,d=a[d]=e,g=m,e=1);m=i+(44*(C[c+244>>1]<<16>>16)&-1)+20|0;r=a[m>>2];a[m>>2]=(r|0)>(d|0)?r:d;c=i+(44*(C[c+246>>1]<<16>>16)&-1)+16|0;i=a[c>>2];a[c>>2]=(i|0)>(g|0)?i:g;return e}function Sl(c,d){var g,e,h;h=(c+32|0)>>2;var i=a[h],j=a[i+220>>2];e=(c+156|0)>>2;var k=a[e];g=(c+160|0)>>2;var r=a[g],q=c+208|0;if(1>(a[q>>2]|0)){var q=k,m=r}else{for(var m=c+212|0,i=c+246|0,n=c+244|0,x=1;;){var v=a[a[m>>2]+(x<<2)>>2];Sl(v,d);if(C[v+246>>1]<<16>>16==C[i>>1]<<16>>16){var t=a[v+156>>2]+8|0,t=(k|0)>(t|0)?k:t}else{t=k}C[v+244>>1]<<16>>16==C[n>>1]<<16>>16?(v=a[v+160>>2]+8|0,v=(r|0)>(v|0)?r:v):v=r;x=x+1|0;if((x|0)>(a[q>>2]|0)){break}else{k=t,r=v}}q=t;m=v;i=a[h]}a[e]=q;a[g]=m;(i|0)!=(c|0)&&0!=(a[c+48>>2]|0)&&(i=c+140|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),n=c+108|0,n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),t=a[a[j+(44*(C[c+244>>1]<<16>>16)&-1)+4>>2]>>2]+40|0,x=a[a[j+(44*(C[c+246>>1]<<16>>16)&-1)+4>>2]>>2]+40|0,q=((i>n?i:n)&-1)-(m+q)-((a[b>>2]=a[t>>2],a[b+4>>2]=a[t+4>>2],f[b>>3])-(a[b>>2]=a[x>>2],a[b+4>>2]=a[x+4>>2],f[b>>3])&-1)|0,0<(q|0)&&(0==(d|0)?es(c,q):ds(c,q)));(a[h]|0)!=(c|0)&&(h=j+(44*(C[c+244>>1]<<16>>16)&-1)+20|0,q=a[h>>2],g=a[g],a[h>>2]=(q|0)>(g|0)?q:g,j=j+(44*(C[c+246>>1]<<16>>16)&-1)+16|0,g=a[j>>2],e=a[e],a[j>>2]=(g|0)>(e|0)?g:e)}function Nr(b){if(0!=(b|0)){for(var c=b,b=c>>2;;){var d=c+176|0,e=d,f=c+248|0,h=a[e>>2],e=a[e+4>>2];a[f>>2]=h;a[f+4>>2]=e;var j=f=c+184|0,c=c+256|0,e=a[j>>2],j=a[j+4>>2];a[c>>2]=e;a[c+4>>2]=j;c=f|0;for(f=0;0!=(a[e+(f<<2)>>2]|0);){f=f+1|0}d|=0;for(e=0;0!=(a[h+(e<<2)>>2]|0);){e=e+1|0}a[b+45]=0;a[d>>2]=da((e+f<<2)+16|0);a[b+47]=0;a[c>>2]=da(16);b=a[b+42];if(0==(b|0)){break}else{c=b,b=c>>2}}}}function Or(c){var d,g,e,i,p=0,j=h;h=h+8|0;i=j>>2;var k=a[c+220>>2],r=0==(n[c+149|0]&1)<<24>>24;e=(c+256|0)>>2;var q=a[e];a[i]=q;a[i+1]=r?q:5;r=c+246|0;q=C[c+244>>1]<<16>>16;a:for(;;){if((q|0)>(C[r>>1]<<16>>16|0)){p=2629;break}c=(k+(44*q&-1)+4|0)>>2;a[a[a[c]>>2]+236>>2]=0;var m=k+(44*q&-1)|0,w=a[((q&1)<<2>>2)+i]|0,x=0,v=0;b:for(;(v|0)<(a[m>>2]|0);){var t=a[a[c]+(v<<2)>>2];g=t>>2;d=(t+112|0)>>2;var y=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);a[g+61]=y&-1;if(0<(a[g+53]|0)){var z=a[g+52],B=a[z>>2];c:do{if(0==(B|0)){var A=0}else{for(var D=0,E=0,G=B;;){if(D=(a[G+16>>2]|0)==(a[G+12>>2]|0)?xt(G)+D|0:D,E=E+1|0,G=a[z+(E<<2)>>2],0==(G|0)){A=D;break c}}}}while(0);y+=A|0;f[b>>3]=y;a[d]=a[b>>2];a[d+1]=a[b+4>>2]}z=y;d=v+1|0;y=a[a[c]+(d<<2)>>2];0==(y|0)?y=x:(B=y+104|0,z=z+(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3])+w,Hc(t,y,z,0),z=x+z&-1,a[y+236>>2]=z,y=z|0);z=a[g+32];if(0!=(z|0)){g=a[g+64];B=a[g>>2];D=a[g+4>>2];g=(E=(a[a[B+12>>2]+240>>2]|0)>(a[a[D+12>>2]+240>>2]|0))?B:D;E=E?D:B;B=(Math.a(fc[z+178>>1],a[e])|0)/2&-1|0;D=a[E+12>>2];E=a[E+16>>2];if(0==(Tl(E,D)|0)){var G=E+104|0,H=D+112|0;Hc(D,E,(a[b>>2]=a[G>>2],a[b+4>>2]=a[G+4>>2],f[b>>3])+(B+(a[b>>2]=a[H>>2],a[b+4>>2]=a[H+4>>2],f[b>>3]))&-1|0,hb[z+164>>2]&-1)}D=a[g+16>>2];g=a[g+12>>2];0==(Tl(g,D)|0)&&(E=g+104|0,G=D+112|0,Hc(D,g,(a[b>>2]=a[E>>2],a[b+4>>2]=a[E+4>>2],f[b>>3])+(B+(a[b>>2]=a[G>>2],a[b+4>>2]=a[G+4>>2],f[b>>3]))&-1|0,hb[z+164>>2]&-1))}g=t+196|0;t=t+192|0;for(z=0;;){if((z|0)>=(a[g>>2]|0)){x=y;v=d;continue b}var B=a[a[t>>2]+(z<<2)>>2],E=a[B+16>>2],G=a[B+12>>2],D=(H=(a[E+240>>2]|0)<(a[G+240>>2]|0))?E:G,E=H?G:E,G=D+112|0,H=E+104|0,G=(a[b>>2]=a[G>>2],a[b+4>>2]=a[G+4>>2],f[b>>3])+(a[b>>2]=a[H>>2],a[b+4>>2]=a[H+4>>2],f[b>>3]),H=a[e],I=Math.a(fc[B+178>>1],H)+G&-1,J=xf(D,E);do{if(0==(J|0)){0==(a[B+108>>2]|0)&&Hc(D,E,I|0,hb[B+164>>2]&-1)}else{var T=I|0,K=G+(H|0),M=B+144|0,M=(a[b>>2]=a[M>>2],a[b+4>>2]=a[M+4>>2],f[b>>3]),L=0>M,T=(T>K+((L?M-.5:M+.5)&-1|0)?T:K+((L?M-.5:M+.5)&-1|0))&-1;if(65535<(T|0)){p=2623;break a}K=J+178|0;M=fc[K>>1];C[K>>1]=((M|0)>(T|0)?M:T)&65535}}while(0);z=z+1|0}}q=q+1|0}2623==p?Zr(T|0):2629==p&&(h=j)}function Pr(c){var d=a[c+216>>2];if(0!=(d|0)){for(;;){var g=d+256|0,e=a[g>>2];a:do{if(0!=(e|0)){var h=a[e>>2];if(0!=(h|0)){for(var i=0,j=h;;){h=Me(c);n[h+162|0]=2;var k=j+68|0,r=j+28|0,r=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])-(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3])&-1,q=0<(r|0),k=q?0:-r|0,r=q?r:0,q=j+16|0,m=j+164|0;Hc(h,a[q>>2],r+1|0,hb[m>>2]&-1);j=j+12|0;Hc(h,a[j>>2],k+1|0,hb[m>>2]&-1);r=a[a[q>>2]+236>>2]-r-1|0;j=a[a[j>>2]+236>>2]-k-1|0;a[h+236>>2]=(r|0)<(j|0)?r:j;i=i+1|0;h=a[a[g>>2]+(i<<2)>>2];if(0==(h|0)){break a}else{j=h}}}}}while(0);d=a[d+168>>2];if(0==(d|0)){break}}}}function Ql(c){var d=h;Fi(c);var g=a[c+264>>2],e=a[c+268>>2],l=C[c+244>>1],p=c+246|0;if(l<<16>>16<=C[p>>1]<<16>>16){for(var j=c+220|0,k=c+12|0,r=c+132|0,c=c+100|0,l=l<<16>>16;;){var q=a[j>>2];if(0!=(a[q+(44*l&-1)>>2]|0)){if(q=a[a[q+(44*l&-1)+4>>2]>>2],0==(q|0)){aa(1,5336192,(i=h,h=h+8|0,a[i>>2]=a[k>>2],a[i+4>>2]=l,i))}else{var m=q+104|0;Hc(g,q,(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])+8+(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),0);q=a[j>>2];q=a[a[q+(44*l&-1)+4>>2]+(a[q+(44*l&-1)>>2]-1<<2)>>2];m=q+112|0;Hc(q,e,(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])+8+(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]),0)}}l=l+1|0;if((l|0)>(C[p>>1]<<16>>16|0)){break}}}h=d}function Fi(c){var d,g=c+264|0;if(0==(a[g>>2]|0)){d=(c+32|0)>>2;var e=Me(a[d]);n[e+162|0]=2;var h=Me(a[d]);n[h+162|0]=2;if(0!=(a[c+48>>2]|0)&&(d=a[d],(d|0)!=(c|0)&&0==(a[d+152>>2]&1|0))){d=c+84|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);var i=c+116|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);Hc(e,h,(d>i?d:i)&-1|0,0)}a[g>>2]=e;a[c+268>>2]=h}}function Qr(b){if((a[b+32>>2]|0)!=(b|0)){Ql(b);var c=a[b+264>>2],d=a[b+268>>2],e=xf(c,d);0==(e|0)?Hc(c,d,1,128):(c=e+164|0,hb[c>>2]+=128)}c=b+208|0;if(1<=(a[c>>2]|0)){b=b+212|0;for(d=1;!(Qr(a[a[b>>2]+(d<<2)>>2]),d=d+1|0,(d|0)>(a[c>>2]|0));){}}}function Ol(c){var d=0,g=C[c+244>>1],e=c+246|0;a:do{if(g<<16>>16<=C[e>>1]<<16>>16){for(var h=c+220|0,i=c+32|0,j=c+264|0,k=c+268|0,r=g<<16>>16;;){var q=a[h>>2];b:do{if(0!=(a[q+(44*r&-1)>>2]|0)){var m=a[a[q+(44*r&-1)+4>>2]>>2];if(0!=(m|0)){for(var m=m+240|0,w=a[m>>2];;){var x=w-1|0;if(0>=(w|0)){break}var v=a[a[a[a[i>>2]+220>>2]+(44*r&-1)+4>>2]+(x<<2)>>2];if(0==n[v+162|0]<<24>>24){d=2689;break}if(0==(fs(c,v)|0)){w=x}else{d=2689;break}}2689==d&&(d=0,w=v+112|0,Hc(v,a[j>>2],(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3])+8,0));for(m=a[a[h>>2]+(44*r&-1)>>2]+a[m>>2]|0;;){w=a[a[i>>2]+220>>2];if((m|0)>=(a[w+(44*r&-1)>>2]|0)){break b}var t=a[a[w+(44*r&-1)+4>>2]+(m<<2)>>2];if(0==n[t+162|0]<<24>>24){break}if(0!=(fs(c,t)|0)){break}m=m+1|0}m=t+104|0;Hc(a[k>>2],t,(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])+8,0)}}}while(0);r=r+1|0;if((r|0)>(C[e>>1]<<16>>16|0)){break a}}}}while(0);d=c+208|0;if(1<=(a[d>>2]|0)){c=c+212|0;for(g=1;!(Ol(a[a[c>>2]+(g<<2)>>2]),g=g+1|0,(g|0)>(a[d>>2]|0));){}}}function Rr(c){Fi(c);var d=c+208|0;if(1<=(a[d>>2]|0)){for(var g=c+212|0,e=c+264|0,h=c+132|0,i=c+268|0,c=c+100|0,j=1;;){var k=a[a[g>>2]+(j<<2)>>2];Fi(k);Hc(a[e>>2],a[k+264>>2],(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])+8,0);Hc(a[k+268>>2],a[i>>2],(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])+8,0);Rr(k);j=j+1|0;if((j|0)>(a[d>>2]|0)){break}}}}function Pl(b){var c;c=(b+208|0)>>2;if(1<=(a[c]|0)){for(var b=(b+212|0)>>2,d=1;;){Fi(a[a[b]+(d<<2)>>2]);var d=d+1|0,e=a[c];if((d|0)>(e|0)){break}}if(1<=(e|0)){for(var d=1,f=e;;){var e=d+1|0,h=a[b],j=a[h+(d<<2)>>2];a:do{if((e|0)>(f|0)){var k=j}else{for(var i=e,q=h,m=j,n=f;;){var x=a[q+(i<<2)>>2],v=C[m+244>>1]<<16>>16>C[x+244>>1]<<16>>16,t=v?m:x,m=v?x:m,x=C[t+244>>1],v=x<<16>>16;C[m+246>>1]<<16>>16<x<<16>>16?t=n:(q=(a[a[a[a[m+220>>2]+(44*v&-1)+4>>2]>>2]+240>>2]|0)<(a[a[a[a[t+220>>2]+(44*v&-1)+4>>2]>>2]+240>>2]|0),Hc(a[(q?m:t)+268>>2],a[(q?t:m)+264>>2],8,0),t=a[c],q=a[b]);i=i+1|0;n=a[q+(d<<2)>>2];if((i|0)>(t|0)){k=n;break a}else{m=n,n=t}}}}while(0);Pl(k);f=a[c];if((e|0)>(f|0)){break}else{d=e}}}}}function fs(b,c){var d;if(1!=n[c+162|0]<<24>>24){return 0}d=a[a[c+256>>2]>>2];for(d>>=2;;){var e=a[d+32];if(0==(e|0)){break}else{d=e,d>>=2}}return 0!=(fd(b,a[d+4]|0)|0)?0:d=0==(fd(b,a[d+3]|0)|0)&1}function Tl(b,c){var d=0;if((b|0)==(c|0)){var e;return 1}for(var f=a[b+184>>2],h=0;;){var j=a[f+(h<<2)>>2];if(0==(j|0)){e=0;d=2735;break}if(0==(Tl(a[j+12>>2],c)|0)){h=h+1|0}else{e=1;d=2737;break}}if(2735==d||2737==d){return e}}function Tq(b){var c,d,e;e=(b+244|0)>>1;C[e]=32767;d=(b+246|0)>>1;C[d]=-1;var f=b+20|0,h=ha(a[f>>2]);if(0==(h|0)){var j=0}else{for(var k=0;;){var i=h;c=(h+236|0)>>2;var q=a[c];(C[d]<<16>>16|0)<(q|0)&&(C[d]=q&65535,q=a[c]);(C[e]<<16>>16|0)>(q|0)&&(C[e]=q&65535);k=0==(k|0)?i:(a[c]|0)<(a[k+236>>2]|0)?i:k;h=sa(a[f>>2],h);if(0==(h|0)){j=k;break}}}b=b+272|0;a[b>>2]=j}function Ul(b){var c=U(b|0,5370544),c=0==(c|0)?2147483647:Oe(c,Ac)*Mb(a[b+20>>2])&-1,d=b+228|0;if(0<(a[d>>2]|0)){for(var e=b+224|0,f=b+216|0,h=b+208|0,j=0;!(a[f>>2]=a[a[e>>2]+(j<<2)>>2],Nj(b,0==(a[h>>2]|0)&1,c),j=j+1|0,(j|0)>=(a[d>>2]|0));){}}}function sl(c,d){var g=h;h=h+8|0;if(0!=(n[c+149|0]&1)<<24>>24){var e=c+20|0,i=ha(a[e>>2]);a:do{if(0!=(i|0)){for(var p=c+28|0,j=i;;){var k=zb(c,j);b:do{if(0!=(k|0)){for(var r=k;;){var q=r+178|0;C[q>>1]<<=1;r=Db(a[p>>2],r);if(0==(r|0)){break b}}}}while(0);j=sa(a[e>>2],j);if(0==(j|0)){break a}}}}while(0);e=c+260|0;a[e>>2]=(a[e>>2]+1|0)/2&-1}if(i=0!=(d|0)){e=c+20|0;p=ha(a[e>>2]);if(0!=(p|0)){for(;!(a[p+220>>2]=0,p=sa(a[e>>2],p),0==(p|0));){}}e=c+20|0;p=ha(a[e>>2]);if(0!=(p|0)){for(;;){j=p+180|0;a:do{if(0<(a[j>>2]|0)){k=p+176|0;for(r=0;;){if(n[a[a[k>>2]+(r<<2)>>2]+124|0]=0,r=r+1|0,(r|0)>=(a[j>>2]|0)){break a}}}}while(0);p=sa(a[e>>2],p);if(0==(p|0)){break}}}}gs(c,c);uq(c);hs(g,c);p=a[g>>2];j=a[g+4>>2];wi(c,0);do{if(i){if(1>=(a[c+228>>2]|0)&&0>=(a[c+208>>2]|0)){e=d;break}a[d+32>>2]=1}e=0}while(0);i=c+228|0;if(0<(a[i>>2]|0)){k=c+224|0;r=c+216|0;for(q=0;;){var m=a[a[k>>2]+(q<<2)>>2];a[r>>2]=m;a:do{if(0!=(m|0)){for(var w=m;!(n[w+163|0]=0,w=a[w+168>>2],0==(w|0));){}w=a[r>>2];if(0!=(w|0)){for(;;){if(nq(w),w=a[w+168>>2],0==(w|0)){break a}}}}}while(0);q=q+1|0;if((q|0)>=(a[i>>2]|0)){break}}}0!=(is(c,p,j)|0)&&wi(c,0);if(0==(e|0)){Ul(c)}else{p=e;k=0;r=a[p+24>>2];oq(c);q=-1==(r|0);i=(p+8|0)>>2;m=p|0;w=c+20|0;for(j=0;;){if(!((j|0)<(r|0)|q)){k=2867;break}var x=ha(a[w>>2]);a:do{if(0!=(x|0)){for(var v=x;;){if(a[v+236>>2]=0,v=sa(a[w>>2],v),0==(v|0)){break a}}}}while(0);Ul(c);x=qq(c);f[b>>3]=x;a[i]=a[b>>2];a[i+1]=a[b+4>>2];if(q&&x<=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3])){break}x=c;v=Wb;v=(x+20|0)>>2;a[1311598]=da(Mb(a[v])<<2);if(0<(Mb(a[v])|0)){for(var t=0;!(a[a[1311598]+(t<<2)>>2]=t,t=t+1|0,(t|0)>=(Mb(a[v])|0));){}}si(x);af(a[1311598],Mb(a[x+20>>2]),304);rq(x);j=j+1|0}2867!=k&&(k=p+20|0,a[p+16>>2]=a[k>>2],a[k>>2]=j);Ul(c);si(c);pq();p=qq(c);f[b>>3]=p;a[i]=a[b>>2];a[i+1]=a[b+4>>2]}js(c,e);ks(c);h=g}function gs(b,c){var d=a[c+36>>2],e=a[d+20>>2],d=zb(e,d);if(0!=(d|0)){for(e=e+28|0;;){var f=vd(a[d+12>>2]),h;h=f;if(0!=(0==(Pd(a[h+12>>2],5375312,7)|0)&1|0)){h=7}else{var j=yj(U(h|0,5373028),5246676,5246700);n[h+282|0]=j&255;h=j}0==(h|0)?gs(b,f):7==(h|0)&100==(a[1345568]|0)?ls(b,f):ms(b,f,h);d=Db(a[e>>2],d);if(0==(d|0)){break}}}}function hs(b,c){var d,e,f=0;e=(c+236|0)>>2;f=a[e];d=(c+232|0)>>2;var h=a[d],j=0==(h|0);if(0==(f|0)){if(j){a[b>>2]=0;a[b+4>>2]=0;return}f=2796}else{if(j){var k=f,f=2797}else{f=2796}}if(2796==f){if(h=ec(h),a[d]=h,j=a[e],0==(j|0)){var i=0,q=h}else{k=j,f=2797}}if(2797==f){i=ec(k);a[e]=i;a:do{if(0==(i|0)){var m=0}else{if(q=5==n[i+165|0]<<24>>24&1,e=i+184|0,k=a[a[e>>2]>>2],0==(k|0)){m=q}else{for(;;){if(f=a[k+12>>2],(f|0)!=(ec(f)|0)&&ia(5353744,363,5379560,5338860),Wk(k),k=a[a[e>>2]>>2],0==(k|0)){m=q;break a}}}}}while(0);i=m;q=a[d]}a:do{if(0==(q|0)){var w=0}else{if(d=3==n[q+165|0]<<24>>24&1,m=q+176|0,e=a[a[m>>2]>>2],0==(e|0)){w=d}else{for(;;){if(k=a[e+16>>2],(k|0)!=(ec(k)|0)&&ia(5353744,370,5379560,5336128),Wk(e),e=a[a[m>>2]>>2],0==(e|0)){w=d;break a}}}}}while(0);a[b>>2]=w;a[b+4>>2]=i}function is(b,c,d){var e=b+236|0;if(0==(a[e>>2]|0)&&0==(a[b+232>>2]|0)){var f;return e=0}var h=b+20|0,j=ha(a[h>>2]);if(0==(j|0)){return e=0}for(var d=d&65535,b=b+232|0,c=c&65535,k=0;;){var i=j,q=j;if((j|0)==(ec(q)|0)){if(0==(a[j+188>>2]|0)){var m=a[e>>2];0==(m|0)|(i|0)==(m|0)||(k=pd(q,m,0),C[k+178>>1]=d)}0!=(a[j+180>>2]|0)?i=k:(m=a[b>>2],0==(m|0)|(i|0)==(m|0)?i=k:(i=pd(m,q,0),C[i+178>>1]=c))}else{i=k}j=sa(a[h>>2],j);if(0==(j|0)){f=i;break}else{k=i}}return e=0!=(f|0)&1}function js(b,c){var d,e,f=b+20|0,h=ha(a[f>>2]);if(0==(h|0)){C[b+246>>1]=0,C[b+244>>1]=0}else{e=(b+244|0)>>1;C[e]=32767;d=(b+246|0)>>1;C[d]=-1;for(var j=0==(c|0);;){var k=h,i=h,q=ec(i);do{if((q|0)==(i|0)){var m=a[h+236>>2]}else{var m=h+236|0,w=a[m>>2];if(!j){if(0==(w|0)){w=0}else{m=w;break}}w=w+a[q+236>>2]|0;m=a[m>>2]=w}}while(0);(C[d]<<16>>16|0)<(m|0)?(C[d]=m&65535,q=a[h+236>>2]):q=m;(C[e]<<16>>16|0)>(q|0)&&(C[e]=q&65535);k=n[k+165|0];0==k<<24>>24|6==k<<24>>24||qn(i);h=sa(a[f>>2],h);if(0==(h|0)){break}}if((a[b+32>>2]|0)==(b|0)){if(100!=(a[1345568]|0)){if(e=a[b+36>>2],d=a[e+20>>2],e=zb(d,e),0!=(e|0)){for(d=d+28|0;!(f=vd(a[e+12>>2]),7==n[f+282|0]<<24>>24&&ls(b,f),e=Db(a[d>>2],e),0==(e|0));){}}}else{if(d=b+208|0,1<=(a[d>>2]|0)){e=b+212|0;for(f=1;!(ns(a[a[e>>2]+(f<<2)>>2]),f=f+1|0,(f|0)>(a[d>>2]|0));){}}}}}}function os(b){var c;c=(b+4|0)>>2;var d=a[c];if(-1<(d|0)){for(b|=0;;){if(a[a[b>>2]+(d<<2)>>2]=0,0<(d|0)){d=d-1|0}else{break}}}a[c]=0}function ks(b){var c,d=b+224|0;c=(b+228|0)>>2;var e=a[c];a:do{if(0<(e|0)){for(var f=d|0,h=b+216|0,j=0,k=e;;){var i=a[a[f>>2]+(j<<2)>>2];a[h>>2]=i;if(0!=(i|0)){for(k=i;!(os(k+176|0),os(k+184|0),n[k+163|0]=0,k=a[k+168>>2],0==(k|0));){}k=a[c]}j=j+1|0;if((j|0)>=(k|0)){break a}}}}while(0);e=b+20|0;h=ha(a[e>>2]);if(0!=(h|0)){for(f=b+28|0;;){j=zb(b,h);a:do{if(0!=(j|0)){for(k=j;;){var i=k+180|0,q=a[i>>2],m=q;do{if(0!=(q|0)&&(k|0)==(a[q+128>>2]|0)){var w=zb(b,h);b:do{if(0!=(w|0)){for(var x=w;;){if((k|0)!=(x|0)){var v=x+180|0,t=a[v>>2];0!=(t|0)&(m|0)==(t|0)&&(a[v>>2]=0)}x=Db(a[f>>2],x);if(0==(x|0)){break b}}}}while(0);E(q|0)}}while(0);a[i>>2]=0;k=Db(a[f>>2],k);if(0==(k|0)){break a}}}}while(0);h=sa(a[e>>2],h);if(0==(h|0)){break}}}b=(d|0)>>2;d=a[b];E(d);a[b]=0;a[c]=0}function ns(b){var c=a[b+272>>2]+236|0,d=b+244|0;C[d>>1]=fc[d>>1]+a[c>>2]&65535;d=b+246|0;C[d>>1]=fc[d>>1]+a[c>>2]&65535;c=b+208|0;if(1<=(a[c>>2]|0)){b=b+212|0;for(d=1;!(ns(a[a[b>>2]+(d<<2)>>2]),d=d+1|0,(d|0)>(a[c>>2]|0));){}}}function ls(b,c){var d=c+250|0;if(0==n[d]<<24>>24&&(n[d]=1,ps(b,c),0!=(ha(a[c+20>>2])|0))){var e=b+208|0,f=a[e>>2],d=f+1|0;a[e>>2]=d;var e=b+212|0,h=a[e>>2],f=0==(h|0)?da((f<<2)+8|0):Fn(h,f+2|0,4,d);a[e>>2]=f;a[f+(d<<2)>>2]=c;ok(c);100==(a[1345568]|0)?(sl(c,0),qs(c)):Tq(c)}}function ps(b,c){var d,e=0;d=(c+20|0)>>2;var f=ha(a[d]);a:do{if(0!=(f|0)){for(var h=c,j=b+212|0,k=b+208|0,i=f;;){var q=sa(a[d],i),m=i+24|0,i=i|0;if(0==n[m+141|0]<<24>>24){for(var w=1;;){var x=a[k>>2];if((w|0)>=(x|0)){var v=x;break}if(0==(fd(a[a[j>>2]+(w<<2)>>2],i)|0)){w=w+1|0}else{e=60;break}}60==e&&(e=0,v=a[k>>2]);(w|0)<(v|0)&&Ng(h,i);a[m+192>>2]=0}else{Ng(h,i)}if(0==(q|0)){break a}else{i=q}}}}while(0);f=ha(a[d]);if(0!=(f|0)){for(e=c+32|0;;){h=zb(a[e>>2],f);a:do{if(0!=(h|0)){for(j=h;;){if(0!=(fd(c,a[j+12>>2]|0)|0)&&Ij(c,j|0),j=Db(a[a[e>>2]+28>>2],j),0==(j|0)){break a}}}}while(0);f=sa(a[d],f);if(0==(f|0)){break}}}}function qs(b){var c=0,d=a[b+216>>2];do{if(0==(d|0)){c=84}else{for(var e=0,f=d;;){var h=0==(a[f+236>>2]|0)?0==n[f+162|0]<<24>>24?f:e:e,f=a[f+168>>2];if(0==(f|0)){break}else{e=h}}if(0==(h|0)){c=84}else{var j=h}}}while(0);84==c&&(ia(5353744,235,5380080,5345700),j=0);a[b+272>>2]=j;b=b+20|0;d=ha(a[b>>2]);if(0!=(d|0)){for(c=j;!(e=d,2>(a[d+220>>2]|0)|(e|0)==(j|0)||ia(5353744,239,5380080,5342120),Lg(d,c),n[e+165|0]=7,d=sa(a[b>>2],d),0==(d|0));){}}}function ms(b,c,d){var e;e=(c+20|0)>>2;c=ha(a[e]);if(0!=(c|0)){var f=d&255,h=c+165|0;n[h]=f;var j=sa(a[e],c);a:do{if(0!=(j|0)){for(var k=c,i=j;;){if(Lg(k,i),n[i+165|0]=n[h],i=sa(a[e],i),0==(i|0)){break a}}}}while(0);if(2==(d|0)|3==(d|0)){e=(b+232|0)>>2,h=a[e],a[e]=0==(h|0)?c:Lg(h,c)}else{if(4==(d|0)|5==(d|0)){e=(b+236|0)>>2,h=a[e],a[e]=0==(h|0)?c:Lg(h,c)}else{return}}3==(d|0)?n[a[b+232>>2]+165|0]=f:5==(d|0)&&(n[a[b+236>>2]+165|0]=f)}}function tl(b){var c=0,d=h;h=h+120|0;var e=b+40|0;a[1345497]=Q(a[a[e>>2]+4>>2]|0,5365444);e=Q(a[a[e>>2]+4>>2]|0,5374600);a[1345496]=e;if(0!=(a[1345497]|0)|0!=(e|0)){var e=b+20|0,f=ha(a[e>>2]);if(0!=(f|0)){for(var i=d|0;;){var j=f;a[1312711]=0;var k=Gg(b,f);a:do{if(0!=(k|0)){for(var r=k;;){var q=r,m=a[1345497];(a[r+12>>2]|0)==(f|0)&0!=(m|0)?(m=tb(r|0,a[m+8>>2]),0==n[m]<<24>>24?c=125:Vl(i,j,q,m)):c=125;125==c&&(c=0,m=a[1345496],(a[r+16>>2]|0)==(f|0)&0!=(m|0)&&(m=tb(r|0,a[m+8>>2]),0!=n[m]<<24>>24&&Vl(i,j,q,m)));r=Hg(b,r,f);if(0==(r|0)){break a}}}}while(0);a:do{if(0<(a[1312711]|0)){for(k=0;;){if(r=d+(24*k&-1)+4|0,1<(a[d+(24*k&-1)+8>>2]|0)&&rs(j,r),r=a[r>>2],0!=(r|0)&&E(r),k=k+1|0,(k|0)>=(a[1312711]|0)){break a}}}}while(0);f=sa(a[e>>2],f);if(0==(f|0)){break}}}}h=d}function Vl(c,d,g,e){var l,p;p=c>>2;l=0;var j=h;h=h+8|0;for(var k=j+4,r=a[1312711],q=0;;){if((q|0)>=(r|0)){l=149;break}var m=a[((24*q&-1)>>2)+p];if(n[m]<<24>>24==n[e]<<24>>24&&0==($(m,e)|0)){l=144;break}q=q+1|0}if(144==l){e=(c+(24*q&-1)+4|0)>>2,l=a[e],l=0==(l|0)?Za((a[((24*q&-1)+8>>2)+p]<<2)+8|0):Oa(l,(a[((24*q&-1)+8>>2)+p]<<2)+8|0),a[e]=l,p=(c+(24*q&-1)+8|0)>>2,r=a[p],a[p]=r+1|0,a[l+(r<<2)>>2]=g,a[a[e]+(a[p]<<2)>>2]=0}else{if(149==l){l=r+1|0;a[1312711]=l;if(5<(l|0)){aa(1,5353344,(i=h,h=h+4|0,a[i>>2]=a[d+12>>2],i));h=j;return}l=(c+(24*q&-1)+8|0)>>2;a[l]=0;r=da(8);m=c+(24*q&-1)+4|0;a[m>>2]=r;var w=a[l];a[l]=w+1|0;a[r+(w<<2)>>2]=g;a[a[m>>2]+(a[l]<<2)>>2]=0;a[((24*q&-1)>>2)+p]=e;a[((24*q&-1)+12>>2)+p]=0;p=c+(24*q&-1)+16|0;f[b>>3]=0;a[p>>2]=a[b>>2];a[p+4>>2]=a[b+4>>2]}}zg(g,j,k);d=(a[g+12>>2]|0)==(d|0)?a[k>>2]:a[j>>2];0!=(d|0)&&(k=c+(24*q&-1)+12|0,p=a[k>>2],a[k>>2]=p+1|0,g=0==(p|0)?Se(g,d):0,c=c+(24*q&-1)+16|0,f[b>>3]=g,a[c>>2]=a[b>>2],a[c+4>>2]=a[b+4>>2]);h=j}function rs(c,d){var g,e,i,p,j,k,r,q,m,w=h;h=h+72|0;var x=w+4,v=w+8;m=(d+4|0)>>2;a:do{if(0<(a[m]|0)){k=d|0;e=c+32|0;j=c+40|0;for(var t=0,y=0,z=0;;){var B=a[a[k>>2]+(z<<2)>>2],A=a[B+12>>2],A=(A|0)==(c|0)?a[B+16>>2]:A,B=A+32|0,B=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3])-(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),A=A+40|0,A=(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3])-(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),C=If(B,A),y=y+B/C,t=t+A/C,z=z+1|0;if((z|0)>=(a[m]|0)){i=t;p=y;r=e;q=r>>2;r=j;r>>=2;break a}}}else{p=i=0,r=c+32|0,q=r>>2,r=c+40|0,r>>=2}}while(0);e=If(p,i);z=(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3]);t=(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3]);k=(c+104|0)>>2;j=(c+112|0)>>2;y=(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3])+(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3]);B=c+96|0;B=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3])+(a[a[c+20>>2]+260>>2]|0);B=y>B?y:B;y=p/e*B+z;B=i/e*B+t;e=v|0;p=(v|0)>>2;f[b>>3]=z;a[p]=a[b>>2];a[p+1]=a[b+4>>2];i=(v+8|0)>>2;f[b>>3]=t;a[i]=a[b>>2];a[i+1]=a[b+4>>2];A=v+16|0;f[b>>3]=(2*z+y)/3;a[A>>2]=a[b>>2];a[A+4>>2]=a[b+4>>2];A=v+24|0;f[b>>3]=(2*t+B)/3;a[A>>2]=a[b>>2];a[A+4>>2]=a[b+4>>2];A=v+32|0;f[b>>3]=(2*y+z)/3;a[A>>2]=a[b>>2];a[A+4>>2]=a[b+4>>2];z=v+40|0;f[b>>3]=(2*B+t)/3;a[z>>2]=a[b>>2];a[z+4>>2]=a[b+4>>2];t=v+48|0;f[b>>3]=y;a[t>>2]=a[b>>2];a[t+4>>2]=a[b+4>>2];v=v+56|0;f[b>>3]=B;a[v>>2]=a[b>>2];a[v+4>>2]=a[b+4>>2];v=h;h=h+8|0;t=a[c+24>>2];0!=(t|0)&&(y=t+4|0,0!=(a[a[y>>2]+12>>2]|0)&&(a[v>>2]=c,a[v+4>>2]=0,t=(c+112|0)>>2,z=(a[b>>2]=a[t],a[b+4>>2]=a[t+1],f[b>>3])&-1,B=e|0,A=c+32|0,B=(a[b>>2]=a[B>>2],a[b+4>>2]=a[B+4>>2],f[b>>3])-(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3]),A=e+8|0,C=c+40|0,y=J[a[a[y>>2]+12>>2]](v,B,(a[b>>2]=a[A>>2],a[b+4>>2]=a[A+4>>2],f[b>>3])-(a[b>>2]=a[C>>2],a[b+4>>2]=a[C+4>>2],f[b>>3])),f[b>>3]=z|0,a[t]=a[b>>2],a[t+1]=a[b+4>>2],di(v,c,e,y)));h=v;q=(a[b>>2]=a[p],a[b+4>>2]=a[p+1],f[b>>3])-(a[b>>2]=a[q],a[b+4>>2]=a[q+1],f[b>>3]);v=(a[b>>2]=a[i],a[b+4>>2]=a[i+1],f[b>>3])-(a[b>>2]=a[r],a[b+4>>2]=a[r+1],f[b>>3]);r=(0>q?q-.5:q+.5)&-1|0;q=(0>v?v-.5:v+.5)&-1|0;v=(a[b>>2]=a[k],a[b+4>>2]=a[k+1],f[b>>3]);v=256*(v+r)/(v+(a[b>>2]=a[j],a[b+4>>2]=a[j+1],f[b>>3]));v=0<=v?Math.floor(v):Math.ceil(v);if(0<(a[m]|0)){j=d|0;for(k=0;;){i=a[a[j>>2]+(k<<2)>>2];zg(i,w,x);a:do{if(0!=(i|0)){for(p=i;;){b:do{if(0!=(p|0)){t=p;for(e=t>>2;;){z=a[e+3];(z|0)==(c|0)&&(y=t+68|0,f[b>>3]=r,a[y>>2]=a[b>>2],a[y+4>>2]=a[b+4>>2],y=t+76|0,f[b>>3]=q,a[y>>2]=a[b>>2],a[y+4>>2]=a[b+4>>2],y=t+84|0,f[b>>3]=0,a[y>>2]=a[b>>2],a[y+4>>2]=a[b+4>>2],a[e+23]=0,n[t+96|0]=1,n[t+97|0]=0,n[t+98|0]=0,n[t+99|0]=0,n[t+100|0]=v,n[t+101|0]=0,a[e+26]=0);(a[e+4]|0)==(c|0)&&(y=t+28|0,f[b>>3]=r,a[y>>2]=a[b>>2],a[y+4>>2]=a[b+4>>2],y=t+36|0,f[b>>3]=q,a[y>>2]=a[b>>2],a[y+4>>2]=a[b+4>>2],y=t+44|0,f[b>>3]=0,a[y>>2]=a[b>>2],a[y+4>>2]=a[b+4>>2],a[e+13]=0,n[t+56|0]=1,n[t+57|0]=0,n[t+58|0]=0,n[t+59|0]=0,n[t+60|0]=v,n[t+61|0]=0,a[e+16]=0);if(1!=n[t+124|0]<<24>>24){var E=p;g=E>>2;break}if(1!=n[z+162|0]<<24>>24){E=p;g=E>>2;break}if(1!=(a[z+188>>2]|0)){E=p;g=E>>2;break}e=a[a[z+184>>2]>>2];if(0==(e|0)){E=p;g=E>>2;break}else{t=e,e=t>>2}}for(;;){(a[g+3]|0)==(c|0)&&(e=E+68|0,f[b>>3]=r,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],e=E+76|0,f[b>>3]=q,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],e=E+84|0,f[b>>3]=0,a[e>>2]=a[b>>2],a[e+4>>2]=a[b+4>>2],a[g+23]=0,n[E+96|0]=1,n[E+97|0]=0,n[E+98|0]=0,n[E+99|0]=0,n[E+100|0]=v,n[E+101|0]=0,a[g+26]=0);e=a[g+4];(e|0)==(c|0)&&(t=E+28|0,f[b>>3]=r,a[t>>2]=a[b>>2],a[t+4>>2]=a[b+4>>2],t=E+36|0,f[b>>3]=q,a[t>>2]=a[b>>2],a[t+4>>2]=a[b+4>>2],t=E+44|0,f[b>>3]=0,a[t>>2]=a[b>>2],a[t+4>>2]=a[b+4>>2],a[g+13]=0,n[E+56|0]=1,n[E+57|0]=0,n[E+58|0]=0,n[E+59|0]=0,n[E+60|0]=v,n[E+61|0]=0,a[g+16]=0);if(1!=n[E+124|0]<<24>>24){break b}if(1!=n[e+162|0]<<24>>24){break b}if(1!=(a[e+180>>2]|0)){break b}e=a[a[e+176>>2]>>2];if(0==(e|0)){break b}else{E=e,g=E>>2}}}}while(0);p=a[p+180>>2];if(0==(p|0)){break a}}}}while(0);k=k+1|0;if((k|0)>=(a[m]|0)){break}}}g=c+161|0;n[g]=1;h=w}function Af(b,c,d){var e=h;h=h+1024|0;var f=e|0,p=xa(d);Pa(f,5345332,(i=h,h=h+8|0,a[i>>2]=c,a[i+4>>2]=p,i));b=a[(b<<2)+5243020>>2];Cb(b,f);Cb(b,d);d=(b+4|0)>>2;f=a[d];f>>>0<a[b+8>>2]>>>0||(qa(b,1),f=a[d]);b=f+1|0;a[d]=b;n[f]=32;h=e}function ss(c){var c=a[a[c+16>>2]+8>>2],d=a[1310772];if((d|0)!=(a[1310771]|0)){var g=a[a[a[1310754]+8>>2]+8>>2];d>>>0<a[1310773]>>>0||(qa(5243084,1),d=a[1310772]);n[d]=0;d=a[1310771];a[1310772]=d;hc(c|0,g,d)}d=a[1310788];(d|0)!=(a[1310787]|0)&&(g=a[a[a[1310754]+12>>2]+8>>2],d>>>0<a[1310789]>>>0||(qa(5243148,1),d=a[1310788]),n[d]=0,d=a[1310787],a[1310788]=d,hc(c|0,g,d));f[b>>3]=1;a[1312265]=a[b>>2];a[1312266]=a[b+4>>2];f[b>>3]=1;a[1312269]=a[b>>2];a[1312270]=a[b+4>>2]}function ts(c){var c=a[a[c+16>>2]+8>>2],d=a[1310772];if((d|0)!=(a[1310771]|0)){var g=a[a[a[1310754]+16>>2]+8>>2];d>>>0<a[1310773]>>>0||(qa(5243084,1),d=a[1310772]);n[d]=0;d=a[1310771];a[1310772]=d;hc(c|0,g,d)}d=a[1310776];(d|0)!=(a[1310775]|0)&&(g=a[a[a[1310754]+24>>2]+8>>2],d>>>0<a[1310777]>>>0||(qa(5243100,1),d=a[1310776]),n[d]=0,d=a[1310775],a[1310776]=d,hc(c|0,g,d));d=a[1310780];(d|0)!=(a[1310779]|0)&&(g=a[a[a[1310754]+20>>2]+8>>2],d>>>0<a[1310781]>>>0||(qa(5243116,1),d=a[1310780]),n[d]=0,d=a[1310779],a[1310780]=d,hc(c|0,g,d));d=a[1310788];(d|0)!=(a[1310787]|0)&&(g=a[a[a[1310754]+28>>2]+8>>2],d>>>0<a[1310789]>>>0||(qa(5243148,1),d=a[1310788]),n[d]=0,d=a[1310787],a[1310788]=d,hc(c|0,g,d));d=a[1310792];(d|0)!=(a[1310791]|0)&&(g=a[a[a[1310754]+36>>2]+8>>2],d>>>0<a[1310793]>>>0||(qa(5243164,1),d=a[1310792]),n[d]=0,d=a[1310791],a[1310792]=d,hc(c|0,g,d));d=a[1310796];(d|0)!=(a[1310795]|0)&&(g=a[a[a[1310754]+32>>2]+8>>2],d>>>0<a[1310797]>>>0||(qa(5243180,1),d=a[1310796]),n[d]=0,d=a[1310795],a[1310796]=d,hc(c|0,g,d));f[b>>3]=1;a[1312267]=a[b>>2];a[1312268]=a[b+4>>2];f[b>>3]=1;a[1312271]=a[b>>2];a[1312272]=a[b+4>>2];f[b>>3]=1;a[1312253]=a[b>>2];a[1312254]=a[b+4>>2];f[b>>3]=1;a[1312255]=a[b>>2];a[1312256]=a[b+4>>2];f[b>>3]=1;a[1312261]=a[b>>2];a[1312262]=a[b+4>>2];f[b>>3]=1;a[1312263]=a[b>>2];a[1312264]=a[b+4>>2]}function us(c,d,g){var e,l,p=h;h=h+1024|0;e=a[a[c+16>>2]+12>>2];ph(c);qh(c);0==(g|0)?(c=a[(e<<2)+5243020>>2],Cb(c,5353792)):(Wl(c),c=a[(e<<2)+5243020>>2],Cb(c,5355308));l=(d|0)>>2;e=(d+8|0)>>2;gi(c,(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]),(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]));var g=p|0,j=d+16|0;l=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])-(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]);d=d+24|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])-(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);d=0>d?d-.5&-1:d+.5&-1;Pa(g,5372640,(i=h,h=h+8|0,a[i>>2]=(0>l?l-.5:l+.5)&-1,a[i+4>>2]=d,i));Cb(c,g);h=p}function ph(c){var d,g,e,l=0,p=h;h=h+1040|0;var j=p+1024,c=(c+16|0)>>2;d=a[c];g=d+96|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);e=((a[d+12>>2]<<3)+5248996|0)>>2;if(g!=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3])){f[b>>3]=g,a[e]=a[b>>2],a[e+1]=a[b+4>>2],d=p|0,Pa(d,5367556,(i=h,h=h+8|0,f[b>>3]=g,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i)),Af(a[a[c]+12>>2],5365152,d),d=a[c]}e=a[d+104>>2];if(0!=(e|0)){ac(j,1024,p|0);var k=a[e>>2];a:do{if(0==(k|0)){var r=j|0}else{g=(j+4|0)>>2;d=(j+8|0)>>2;for(var q=j|0,m=e,w=k;;){var m=m+4|0,x=n[w];102==x<<24>>24?0!=($(w,5362648)|0)&&(l=308):98==x<<24>>24?0!=($(w,5360600)|0)&&(l=308):115==x<<24>>24?0!=($(w,5365664)|0)&&(l=308):l=308;if(308==l){l=0;for(Cb(j,w);;){var v=w+1|0;if(0==n[w]<<24>>24){break}else{w=v}}if(0!=n[v]<<24>>24){w=a[g];w>>>0<a[d]>>>0||(qa(j,1),w=a[g]);x=w+1|0;a[g]=x;n[w]=40;if(0==n[v]<<24>>24){w=x}else{x=v;for(w=0;;){if(0!=(w|0)){var t=a[g];t>>>0<a[d]>>>0||(qa(j,1),t=a[g]);a[g]=t+1|0;n[t]=44}for(Cb(j,x);;){var y=x+1|0;if(0==n[x]<<24>>24){break}else{x=y}}if(0==n[y]<<24>>24){break}else{x=y,w=w+1|0}}w=a[g]}w>>>0<a[d]>>>0||(qa(j,1),w=a[g]);a[g]=w+1|0;n[w]=41}w=a[g];w>>>0<a[d]>>>0||(qa(j,1),w=a[g]);n[w]=0;w=a[q>>2];a[g]=w;Af(a[a[c]+12>>2],5365152,w)}w=a[m>>2];if(0==(w|0)){r=q;break a}}}}while(0);Xb(a[r>>2],a[j+12>>2])}h=p}function qh(b){b=b+16|0;vs(a[b>>2]+16|0);Af(a[a[b>>2]+12>>2],5338544,5289976)}function rh(c,d,g,e){var l,p=h;h=h+1024|0;c=a[(c<<2)+5243020>>2];l=(c+4|0)>>2;var j=a[l];j>>>0<a[c+8>>2]>>>0||(qa(c,1),j=a[l]);a[l]=j+1|0;n[j]=d;d=p|0;Pa(d,5375352,(i=h,h=h+4|0,a[i>>2]=e,i));Cb(c,d);if(0<(e|0)){for(d=0;!(l=(d<<4)+g|0,j=(d<<4)+g+8|0,gi(c,(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])),d=d+1|0,(d|0)==(e|0));){}}h=p}function vs(b){var c=h,d=ca[b+1|0],e=ca[b+2|0],f=ca[b+3|0];Pa(5289976,5369996,(i=h,h=h+16|0,a[i>>2]=ca[b],a[i+4>>2]=d,a[i+8>>2]=e,a[i+12>>2]=f,i));h=c}function Wl(b){b=b+16|0;vs(a[b>>2]+52|0);Af(a[a[b>>2]+12>>2],5356948,5289976)}function ws(c){var d=a[1310768];if((d|0)==(a[1310767]|0)){var g=c|0}else{var e=a[a[1310754]>>2],g=c|0;if(0==(e|0)){var d=ic(c,g,5349136,188),e=a[a[1310754]>>2]=d,h=a[1310768]}else{h=d}d=a[e+8>>2];h>>>0<a[1310769]>>>0?e=h:(qa(5243068,1),e=a[1310768]);n[e]=0;e=a[1310767];a[1310768]=e;hc(g,d,e)}0!=(a[c+48>>2]|0)&&(c=a[a[a[1310754]+4>>2]+8>>2],d=a[1310784],d>>>0<a[1310785]>>>0||(qa(5243132,1),d=a[1310784]),n[d]=0,d=a[1310783],a[1310784]=d,hc(g,c,d));fp(g,5348168,5347688);Xb(a[1310767],a[1310770]);Xb(a[1310771],a[1310774]);Xb(a[1310775],a[1310778]);Xb(a[1310779],a[1310782]);Xb(a[1310783],a[1310786]);Xb(a[1310787],a[1310790]);Xb(a[1310791],a[1310794]);Xb(a[1310795],a[1310798]);E(a[1310754]);f[b>>3]=1;a[1312249]=a[b>>2];a[1312250]=a[b+4>>2];f[b>>3]=1;a[1312257]=a[b>>2];a[1312258]=a[b+4>>2]}function xs(b,c,d){var e=wb(8232);a[1310754]=e;if(0==(a[b+208>>2]|0)){a[e>>2]=0;var f=e}else{e=ic(b,b|0,5349136,188),f=a[1310754],a[f>>2]=e}e=b+149|0;0==(n[e]&8)<<24>>24?a[f+4>>2]=0:(f=ic(b,b|0,5347208,188),a[a[1310754]+4>>2]=f);var f=b,b=(b+40|0)>>2,h=ic(f,a[a[b]>>2]|0,5349136,196);a[a[1310754]+8>>2]=h;h=ic(f,a[a[b]>>2]|0,5347208,196);a[a[1310754]+12>>2]=h;var h=ic(f,a[a[b]+4>>2]|0,5349136,260),j=a[1310754];a[j+16>>2]=h;0==(d|0)?(a[j+20>>2]=0,d=j):(d=ic(f,a[a[b]+4>>2]|0,5346752,260),h=a[1310754],a[h+20>>2]=d,d=h);0==(c|0)?a[d+24>>2]=0:(c=ic(f,a[a[b]+4>>2]|0,5346356,260),d=a[1310754],a[d+24>>2]=c);c=d;0==(n[e]&1)<<24>>24?a[c+28>>2]=0:(c=ic(f,a[a[b]+4>>2]|0,5347208,260),d=a[1310754],a[d+28>>2]=c,c=d);0==(n[e]&2)<<24>>24?a[c+32>>2]=0:(c=ic(f,a[a[b]+4>>2]|0,5346008,260),d=a[1310754],a[d+32>>2]=c,c=d);0==(n[e]&4)<<24>>24?(a[c+36>>2]=0,e=c+40|0):(e=ic(f,a[a[b]+4>>2]|0,5345716,260),f=a[1310754],a[f+36>>2]=e,e=f+40|0);ac(5243068,1024,e);e=a[1310754];ac(5243084,1024,e+1064|0);e=a[1310754];ac(5243100,1024,e+2088|0);e=a[1310754];ac(5243116,1024,e+3112|0);e=a[1310754];ac(5243132,1024,e+4136|0);e=a[1310754];ac(5243148,1024,e+5160|0);e=a[1310754];ac(5243164,1024,e+6184|0);e=a[1310754];e=e+7208|0;ac(5243180,1024,e)}function ys(c,d,g,e){var l=h,p=a[a[c+16>>2]+16>>2],j=a[1345523],k=e+24|0,r=c+348|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])*(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),r=0!=(a[c+356>>2]|0)?1.5707963267948966:0,q=a[e+4>>2],q=0==(q|0)?-1:a[q+20>>2],m=n[e+72|0]<<24>>24,m=114==(m|0)?2:108==(m|0)?0:1,d=0>d?d-.5:d+.5,g=0>g?g-.5:g+.5,e=zs(a[e>>2]);G(c,5351540,(i=h,h=h+72|0,a[i>>2]=4,a[i+4>>2]=m,a[i+8>>2]=p,a[i+12>>2]=j,a[i+16>>2]=0,a[i+20>>2]=q,f[b>>3]=k,a[i+24>>2]=a[b>>2],a[i+28>>2]=a[b+4>>2],f[b>>3]=r,a[i+32>>2]=a[b>>2],a[i+36>>2]=a[b+4>>2],a[i+40>>2]=6,f[b>>3]=0,a[i+44>>2]=a[b>>2],a[i+48>>2]=a[b+4>>2],f[b>>3]=0,a[i+52>>2]=a[b>>2],a[i+56>>2]=a[b+4>>2],a[i+60>>2]=d&-1,a[i+64>>2]=g&-1,a[i+68>>2]=e,i));h=l}function As(b,c){var d,e=0,f=h;h=h+4|0;d=(c+32|0)>>2;var p=a[d];if(5==(p|0)){for(p=0;;){var j=a[(p<<2)+5253496>>2];if(8==(p|0)){e=406;break}var k=a[c>>2];if(n[j]<<24>>24==n[k]<<24>>24&&0==($(j,k)|0)){break}p=p+1|0}406!=e&&(a[c>>2]=p)}else{1==(p|0)?(k=c+1|0,j=c+2|0,e=Bs(f,ca[c],ca[k],ca[j])+32|0,0!=(a[f>>2]|0)&&(p=ca[c],k=ca[k],j=ca[j],G(b,5354872,(i=h,h=h+20|0,a[i>>2]=0,a[i+4>>2]=e,a[i+8>>2]=p,a[i+12>>2]=k,a[i+16>>2]=j,i))),a[c>>2]=e):ia(5367128,165,5379800,5340724)}a[d]=6;h=f}function Gi(c,d,g){g>>=2;1==(c|0)?(a[d>>2]=1,f[b>>3]=10):2==(c|0)?(a[d>>2]=2,f[b>>3]=10):(a[d>>2]=0,f[b>>3]=0);a[g]=a[b>>2];a[g+1]=a[b+4>>2]}function Bs(b,c,d,e){var f=0;a[b>>2]=0;for(var h=a[1313423],j=195075,k=-1,i=0;(i|0)<(h|0);){var q=(C[(i<<1)+5253696>>1]<<16>>16)-c|0,m=(C[(i<<1)+5254208>>1]<<16>>16)-d|0,n=(C[(i<<1)+5254720>>1]<<16>>16)-e|0,q=Math.a(m,m)+Math.a(q,q)+Math.a(n,n)|0;if((q|0)<(j|0)){if(0==(q|0)){var x=i,f=425;break}else{j=q,k=i}}i=i+1|0}if(425==f){return x}a[1313423]=h+1|0;if(256==(h|0)){return k}C[(i<<1)+5253696>>1]=c&65535;C[(i<<1)+5254208>>1]=d&65535;C[(i<<1)+5254720>>1]=e&65535;a[b>>2]=1;return i}function Cs(c,d,g){var e,l=h;h=h+12|0;var p=l+4,j=a[c+16>>2];e=j>>2;var j=j+96|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])&-1,k=a[e+4],r=a[e+13],q=a[1345523];Gi(a[e+22],l,p);e=d|0;var m=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);e=(0>m?m-.5:m+.5)&-1;var n=d+8|0,x=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),n=(0>x?x-.5:x+.5)&-1,v=d+16|0,v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3]),m=v-m,d=d+24|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),x=d-x,t=a[l>>2],p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);G(c,5356372,(i=h,h=h+88|0,a[i>>2]=1,a[i+4>>2]=1,a[i+8>>2]=t,a[i+12>>2]=j,a[i+16>>2]=k,a[i+20>>2]=r,a[i+24>>2]=q,a[i+28>>2]=0,a[i+32>>2]=0!=(g|0)?20:-1,f[b>>3]=p,a[i+36>>2]=a[b>>2],a[i+40>>2]=a[b+4>>2],a[i+44>>2]=0,f[b>>3]=0,a[i+48>>2]=a[b>>2],a[i+52>>2]=a[b+4>>2],a[i+56>>2]=e,a[i+60>>2]=n,a[i+64>>2]=(0>m?m-.5:m+.5)&-1,a[i+68>>2]=(0>x?x-.5:x+.5)&-1,a[i+72>>2]=e,a[i+76>>2]=n,a[i+80>>2]=(0>v?v-.5:v+.5)&-1,a[i+84>>2]=(0>d?d-.5:d+.5)&-1,i));h=l}function Ds(c,d,g,e,l,p){var j,k,r,e=h;h=h+92|0;var l=e+4,q=e+12,m=e+76,n=c+16|0,x=a[n>>2],v=x+96|0,v=(a[b>>2]=a[v>>2],a[b+4>>2]=a[v+4>>2],f[b>>3])&-1,t=a[x+16>>2],y=a[1345523],z=3<(g|0);z||ia(5367128,354,5379820,5364664);var B=wb((140*g&-1)+140|0);Gi(a[x+88>>2],e,l);0==(p|0)?(p=-1,n=0,x=4):(p=20,n=a[a[n>>2]+52>>2],x=5);var C=d|0;j=(a[b>>2]=a[C>>2],a[b+4>>2]=a[C+4>>2],f[b>>3]);C=q+48|0;r=C|0;f[b>>3]=j;a[r>>2]=a[b>>2];a[r+4>>2]=a[b+4>>2];r=d+8|0;k=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]);r=(q+56|0)>>2;f[b>>3]=k;a[r]=a[b>>2];a[r+1]=a[b+4>>2];var D=Pa(B,5372208,(i=h,h=h+8|0,a[i>>2]=(0>j?j-.5:j+.5)&-1,a[i+4>>2]=(0>k?k-.5:k+.5)&-1,i));a:do{if(z){var H=q|0;k=q>>2;j=C>>2;for(var J=m|0,P=m+8|0,I=q+16|0,Z=q+24|0,T=q+32|0,K=q+40|0,M=q+48|0,L=0,N=1,Q=B+D|0,U=3;;){a[k]=a[j];a[k+1]=a[j+1];a[k+2]=a[j+2];a[k+3]=a[j+3];var R=L+1|0,Y=(R<<4)+d|0,Y=(a[b>>2]=a[Y>>2],a[b+4>>2]=a[Y+4>>2],f[b>>3]);f[b>>3]=Y;a[I>>2]=a[b>>2];a[I+4>>2]=a[b+4>>2];R=(R<<4)+d+8|0;R=(a[b>>2]=a[R>>2],a[b+4>>2]=a[R+4>>2],f[b>>3]);f[b>>3]=R;a[Z>>2]=a[b>>2];a[Z+4>>2]=a[b+4>>2];R=L+2|0;Y=(R<<4)+d|0;Y=(a[b>>2]=a[Y>>2],a[b+4>>2]=a[Y+4>>2],f[b>>3]);f[b>>3]=Y;a[T>>2]=a[b>>2];a[T+4>>2]=a[b+4>>2];R=(R<<4)+d+8|0;R=(a[b>>2]=a[R>>2],a[b+4>>2]=a[R+4>>2],f[b>>3]);f[b>>3]=R;a[K>>2]=a[b>>2];a[K+4>>2]=a[b+4>>2];L=L+3|0;R=(L<<4)+d|0;R=(a[b>>2]=a[R>>2],a[b+4>>2]=a[R+4>>2],f[b>>3]);f[b>>3]=R;a[M>>2]=a[b>>2];a[M+4>>2]=a[b+4>>2];L=(L<<4)+d+8|0;L=(a[b>>2]=a[L>>2],a[b+4>>2]=a[L+4>>2],f[b>>3]);f[b>>3]=L;a[r]=a[b>>2];a[r+1]=a[b+4>>2];for(L=1;;){zc(m,H,(L|0)/6,0,0);var R=(a[b>>2]=a[J>>2],a[b+4>>2]=a[J+4>>2],f[b>>3]),aa=(a[b>>2]=a[P>>2],a[b+4>>2]=a[P+4>>2],f[b>>3]),R=0>R?R-.5:R+.5,aa=0>aa?aa-.5:aa+.5,aa=Q+Pa(Q,5372208,(i=h,h=h+8|0,a[i>>2]=R&-1,a[i+4>>2]=aa&-1,i))|0,Q=L+1|0;if(7==(Q|0)){break}else{L=Q,Q=aa}}N=N+6|0;R=U+3|0;if((R|0)<(g|0)){L=U,Q=aa,U=R}else{var $=N;break a}}}else{$=1}}while(0);d=a[e>>2];g=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);G(c,5362132,(i=h,h=h+60|0,a[i>>2]=3,a[i+4>>2]=x,a[i+8>>2]=d,a[i+12>>2]=v,a[i+16>>2]=t,a[i+20>>2]=n,a[i+24>>2]=y,a[i+28>>2]=0,a[i+32>>2]=p,f[b>>3]=g,a[i+36>>2]=a[b>>2],a[i+40>>2]=a[b+4>>2],a[i+44>>2]=0,a[i+48>>2]=0,a[i+52>>2]=0,a[i+56>>2]=$,i));G(c,5360140,(i=h,h=h+4|0,a[i>>2]=B,i));E(B);if(0<($|0)){d=$-1|0;for(g=0;!(G(c,5358108,(i=h,h=h+4|0,a[i>>2]=0!=((g|0)%(d|0)|0)&1,i)),g=g+1|0,(g|0)==($|0));){}}A(c,5344600);h=e}function Xl(c,d,g,e){var l=h;a:do{if(0<(g|0)){for(var p=c,j=0;;){var k=(j<<4)+d|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),k=0>k?k-.5:k+.5,r=(j<<4)+d+8|0,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]),r=0>r?r-.5:r+.5;G(p,5372208,(i=h,h=h+8|0,a[i>>2]=k&-1,a[i+4>>2]=r&-1,i));j=j+1|0;if((j|0)==(g|0)){break a}}}}while(0);0!=(e|0)&&(g=d|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),d=d+8|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),G(c,5372208,(i=h,h=h+8|0,a[i>>2]=(0>g?g-.5:g+.5)&-1,a[i+4>>2]=(0>d?d-.5:d+.5)&-1,i)));A(c,5344600);h=l}function zs(b){var c=h,d=a[1313384];0==(d|0)&&(a[1313383]=64,d=wb(64),a[1313384]=d);var e=n[b];if(0==e<<24>>24){return n[d]=0,h=c,d}for(var f=d,d=0;;){var b=b+1|0,p=a[1313383];(d|0)>(p-8|0)?(p<<=1,a[1313383]=p,p=gc(a[1313384],p),a[1313384]=p,p=p+d|0):p=f;-1<e<<24>>24?(92==e<<24>>24&&(n[p]=92,d=d+1|0,p=p+1|0),n[p]=e,d=d+1|0,p=p+1|0):(n[p]=92,Pa(p+1|0,5349996,(i=h,h=h+4|0,a[i>>2]=e&255,i)),d=d+4|0,p=p+4|0);e=n[b];if(0==e<<24>>24){break}else{f=p}}d=a[1313384];n[p]=0;h=c;return d}function Es(b){var c=a[b+16>>2],d=a[b+64>>2];if(1==(d|0)){var d=c+148|0,e=a[d>>2];0!=(e|0)&&0!=n[e]<<24>>24&&(A(b,5345040),A(b,jc(a[d>>2])),A(b,5366668),A(b,jc(a[a[c+8>>2]+12>>2])),A(b,5344600))}else{0==(d|0)?(A(b,5345484),c=c+148|0,d=a[c>>2],0!=(d|0)&&0!=n[d]<<24>>24&&(A(b,5345040),A(b,jc(a[c>>2])),A(b,5344600))):3==(d|0)&&(c=jc(a[a[c+8>>2]+12>>2]),A(b,5344388),A(b,c),A(b,5344008),A(b,c),A(b,5346148))}}function Hi(c,d,g,e,l,p,j,k){var r,q=h;if(!(0==(g|0)|0==(e|0))){(a[1312727]|0)<(e|0)&&(r=e+10|0,a[1312727]=r,a[1312728]=gc(a[1312728],r<<3));r=0<(e|0);a:do{if(r){for(var m=0;;){var w=(m<<4)+g|0,x=(a[b>>2]=a[w>>2],a[b+4>>2]=a[w+4>>2],f[b>>3]),w=a[1312728];a[w+(m<<3)>>2]=(0>x?x-.5:x+.5)&-1;x=(m<<4)+g+8|0;x=(a[b>>2]=a[x>>2],a[b+4>>2]=a[x+4>>2],f[b>>3]);a[w+(m<<3)+4>>2]=(0>x?x-.5:x+.5)&-1;m=m+1|0;if((m|0)==(e|0)){break a}}}}while(0);g=c+64|0;m=a[g>>2];w=0==(l|0);do{if(!(0!=(m|0)|w)&&0!=n[l]<<24>>24){if(1==(d|0)){g=a[1312728]>>2,e=a[g],d=a[g+1],g=a[g+2]-e|0,G(c,5328508,(i=h,h=h+16|0,a[i>>2]=l,a[i+4>>2]=e,a[i+8>>2]=d,a[i+12>>2]=g,i))}else{if(0==(d|0)){p=a[1312728]>>2,e=a[p],d=a[p+3],g=a[p+2],p=a[p+1],G(c,5331184,(i=h,h=h+20|0,a[i>>2]=l,a[i+4>>2]=e,a[i+8>>2]=d,a[i+12>>2]=g,a[i+16>>2]=p,i))}else{if(2==(d|0)){G(c,5325728,(i=h,h=h+4|0,a[i>>2]=l,i));a:do{if(r){for(d=0;;){if(l=a[1312728],g=a[l+(d<<3)+4>>2],G(c,5376760,(i=h,h=h+8|0,a[i>>2]=a[l+(d<<3)>>2],a[i+4>>2]=g,i)),d=d+1|0,(d|0)==(e|0)){break a}}}}while(0);A(c,5344600)}else{ia(5371200,65,5379632,5340724)}}}h=q;return}}while(0);if(!(1!=(m|0)|w)&&0!=n[l]<<24>>24){0==(d|0)?(e=a[1312728]>>2,d=a[e+3],g=a[e+2],r=a[e+1],G(c,5366232,(i=h,h=h+24|0,a[i>>2]=a[e],a[i+4>>2]=d,a[i+8>>2]=g,a[i+12>>2]=r,a[i+16>>2]=l,a[i+20>>2]=p,i))):ia(5371200,77,5379632,5340724);h=q;return}if(2>(m-2|0)>>>0){1==(d|0)?A(c,5363764):0==(d|0)?A(c,5361408):2==(d|0)?A(c,5359384):ia(5371200,93,5379632,5340724);0!=(k|0)&&0!=n[k]<<24>>24&&(A(c,5357564),A(c,Uh(k)),A(c,5337992));!w&&0!=n[l]<<24>>24&&(A(c,5354312),A(c,Uh(l)),A(c,5337992));0!=(j|0)&&0!=n[j]<<24>>24&&(A(c,5356136),A(c,jc(j)),A(c,5337992));0!=(p|0)&&0!=n[p]<<24>>24&&(A(c,5351008),A(c,jc(p)),A(c,5337992));A(c,5349616);A(c,5348340);a:do{if(1==(d|0)){r=a[1312728]>>2,l=a[r],p=a[r+1],r=a[r+2]-l|0,G(c,5348292,(i=h,h=h+12|0,a[i>>2]=l,a[i+4>>2]=p,a[i+8>>2]=r,i))}else{if(0==(d|0)){l=a[1312728]>>2,p=a[l+3],r=a[l+2],j=a[l+1],G(c,5347868,(i=h,h=h+16|0,a[i>>2]=a[l],a[i+4>>2]=p,a[i+8>>2]=r,a[i+12>>2]=j,i))}else{if(2==(d|0)&&(l=a[1312728],p=a[l+4>>2],G(c,5347408,(i=h,h=h+8|0,a[i>>2]=a[l>>2],a[i+4>>2]=p,i)),1<(e|0))){for(l=1;;){if(p=a[1312728],r=a[p+(l<<3)+4>>2],G(c,5346876,(i=h,h=h+8|0,a[i>>2]=a[p+(l<<3)>>2],a[i+4>>2]=r,i)),l=l+1|0,(l|0)==(e|0)){break a}}}}}}while(0);3==(a[g>>2]|0)?A(c,5364888):A(c,5346148)}}h=q}function Fs(b){var c,d=b>>2,e=h;h=h+8|0;var f=a[d+4];n[5246412]=0;c=(b+12|0)>>2;var p=f+8|0;if(0==(a[a[c]+28>>2]|0)){G(b,5356292,(i=h,h=h+4|0,a[i>>2]=a[a[p>>2]+12>>2],i));var j=b+64|0;2==(a[j>>2]|0)?A(b,5356036):A(b,5356168);if(0==(a[a[c]+20>>2]|0)){if(2==(a[j>>2]|0)){var j=a[d+113],k=a[d+114],r=a[d+115];G(b,5355764,(i=h,h=h+16|0,a[i>>2]=a[d+112],a[i+4>>2]=j,a[i+8>>2]=k,a[i+12>>2]=r,i))}else{A(b,5355912)}}A(b,5355608);fi(b,a[a[c]+24>>2],5246860);d=h;j=a[1345521];if(0!=(j|0)&&(j=J[a[j>>2]](j,0,128),0!=(j|0))){for(;!(0==n[j+16|0]<<24>>24&&(G(b,5378212,(i=h,h=h+4|0,a[i>>2]=a[j+12>>2],i)),A(b,5375512),lk(b,a[j+52>>2]),A(b,5372764),A(b,5370204)),k=a[1345521],j=J[a[k>>2]](k,j,8),0==(j|0));){}}h=d;c=a[a[c]+20>>2];0!=(c|0)&&(d=e|0,a[d>>2]=a[c>>2],a[e+4>>2]=0,fi(b,0,d))}a[1312802]=1==n[a[p>>2]+151|0]<<24>>24&1;n[5246412]||(A(b,5355456),n[5246412]=1);f=a[f+148>>2];0!=(f|0)&&G(b,5355224,(i=h,h=h+4|0,a[i>>2]=f,i));h=e}function Gs(c){var d,g=c>>2,e=h,l=a[g+112],p=a[g+113],j=a[g+114],k=a[g+115];d=(c+12|0)>>2;var r=a[a[d]+28>>2]+1|0;G(c,5358296,(i=h,h=h+8|0,a[i>>2]=r,a[i+4>>2]=r,i));0==(a[a[d]+20>>2]|0)&&G(c,5358132,(i=h,h=h+16|0,a[i>>2]=l,a[i+4>>2]=p,a[i+8>>2]=j,a[i+12>>2]=k,i));var q=c+356|0;G(c,5358024,(i=h,h=h+4|0,a[i>>2]=0!=(a[q>>2]|0)?5357908:5357748,i));r=c+64|0;1==(a[r>>2]|0)&&G(c,5357572,(i=h,h=h+8|0,a[i>>2]=j,a[i+4>>2]=k,i));var m=a[g+49],n=a[g+50];G(c,5357432,(i=h,h=h+12|0,a[i>>2]=a[g+48],a[i+4>>2]=m,a[i+8>>2]=n,i));0==(a[a[d]+20>>2]|0)&&G(c,5357244,(i=h,h=h+16|0,a[i>>2]=l,a[i+4>>2]=p,a[i+8>>2]=j-l|0,a[i+12>>2]=k-p|0,i));var g=c+480|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),m=c+488|0,m=(a[b>>2]=a[m>>2],a[b+4>>2]=a[m+4>>2],f[b>>3]),q=a[q>>2],n=c+496|0,n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),x=c+504|0,x=(a[b>>2]=a[x>>2],a[b+4>>2]=a[x+4>>2],f[b>>3]);G(c,5357088,(i=h,h=h+36|0,f[b>>3]=g,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=m,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],a[i+16>>2]=q,f[b>>3]=n,a[i+20>>2]=a[b>>2],a[i+24>>2]=a[b+4>>2],f[b>>3]=x,a[i+28>>2]=a[b>>2],a[i+32>>2]=a[b+4>>2],i));if(1==(a[r>>2]|0)){if(14399<(j|0)|14399<(k|0)){J[a[a[d]+16>>2]](5356836,(i=h,h=h+12|0,a[i>>2]=j,a[i+4>>2]=k,a[i+8>>2]=14400,i))}G(c,5356616,(i=h,h=h+16|0,a[i>>2]=l,a[i+4>>2]=p,a[i+8>>2]=j,a[i+12>>2]=k,i))}h=e}function Hs(c,d,g,e){var h;h=(c+16|0)>>2;do{if(0!=(e|0)){var i=a[h],j=i+76|0;if(.5<(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])){Ce(c,i+52|0);i=c;A(i,5362824);var j=d|0,k=d+8|0;od(i,(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]));A(i,5362580);a:do{if(1<(g|0)){for(j=1;;){var k=(j<<4)+d|0,r=(j<<4)+d+8|0;od(i,(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]));A(i,5362396);j=j+1|0;if((j|0)==(g|0)){break a}}}}while(0);A(i,5361740)}}}while(0);e=a[h]+40|0;if(.5<(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])){sh(c);Ce(c,a[h]+16|0);A(c,5362824);h=d|0;e=d+8|0;od(c,(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]),(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]));A(c,5362580);a:do{if(1<(g|0)){for(h=1;;){if(e=(h<<4)+d|0,i=(h<<4)+d+8|0,od(c,(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3])),A(c,5362396),h=h+1|0,(h|0)==(g|0)){break a}}}}while(0);A(c,5361568)}}function Is(c,d,g,e,h,i){e=(c+16|0)>>2;do{if(0!=(i|0)){var h=a[e],j=h+76|0;if(.5<(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])){Ce(c,h+52|0);h=c;A(h,5362824);var j=d|0,k=d+8|0;od(h,(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]));A(h,5362580);a:do{if(1<(g|0)){for(j=1;;){if(xe(h,(j<<4)+d|0,3),A(h,5361944),j=j+3|0,(j|0)>=(g|0)){break a}}}}while(0);A(h,5361740)}}}while(0);i=a[e]+40|0;if(.5<(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3])){sh(c);Ce(c,a[e]+16|0);A(c,5362824);i=d|0;e=d+8|0;od(c,(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]));A(c,5362580);a:do{if(1<(g|0)){for(i=1;;){if(xe(c,(i<<4)+d|0,3),A(c,5361944),i=i+3|0,(i|0)>=(g|0)){break a}}}}while(0);A(c,5362180)}}function Ce(c,d){var g=h;if(0!=(d|0)){var e=a[a[c+16>>2]+4>>2],l=d|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),p=d+8|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=d+16|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);G(c,5363680,(i=h,h=h+28|0,f[b>>3]=l,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=p,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],f[b>>3]=j,a[i+16>>2]=a[b>>2],a[i+20>>2]=a[b+4>>2],a[i+24>>2]=0==(e|0)|1==(e|0)?5372324:3==(e|0)?5374900:2==(e|0)?5329472:5364024,i))}h=g}function sh(c){var d=0,g=h,e=c+16|0,l=a[e>>2],p=l+96|0,l=a[l+104>>2];ag(c,(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]));for(A(c,5365912);;){if(0==(l|0)){d=739;break}p=l+4|0;l=a[l>>2];if(0==(l|0)){d=740;break}if(0!=($(l,5365664)|0)){for(var j=l;;){var k=j+1|0;if(0==n[j]<<24>>24){break}else{j=k}}a:do{if(0!=n[k]<<24>>24){for(j=k;;){for(G(c,5365440,(i=h,h=h+4|0,a[i>>2]=j,i));;){var r=j+1|0;if(0==n[j]<<24>>24){break}else{j=r}}if(0==n[r]<<24>>24){break a}else{j=r}}}}while(0);0==($(l,5365092)|0)&&(j=a[e>>2]+96|0,f[b>>3]=0,a[j>>2]=a[b>>2],a[j+4>>2]=a[b+4>>2]);G(c,5364896,(i=h,h=h+4|0,a[i>>2]=l,i))}l=p}739==d?h=g:740==d&&(h=g)}function Js(c,d,g,e){var l=h,p=a[c+16>>2];A(c,5359736);var j=n[e+72|0]<<24>>24;114==(j|0)?A(c,5359324):108==(j|0)?A(c,5359564):A(c,5359132);j=e+48|0;g=-((a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])+g);G(c,5358912,(i=h,h=h+16|0,f[b>>3]=d,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=g,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));d=a[e+4>>2];if(0==(d|0)){G(c,5357864,(i=h,h=h+4|0,a[i>>2]=a[e+20>>2],i))}else{g=a[a[a[c>>2]+128>>2]+252>>2];if(1==(g|0)){var j=d+16|0,k=d+8|0,g=d|0}else{2==(g|0)?(j=d+32|0,k=d+28|0,g=d+24|0):(j=d+16|0,k=d+8|0,g=d+4|0)}var j=a[j>>2],k=a[k>>2],r=a[d+12>>2];G(c,5358684,(i=h,h=h+4|0,a[i>>2]=a[g>>2],i));d=a[d+24>>2];0!=(d|0)&&G(c,5358472,(i=h,h=h+4|0,a[i>>2]=d,i));A(c,5337992);0!=(k|0)&&G(c,5358276,(i=h,h=h+4|0,a[i>>2]=k,i));0!=(r|0)&&G(c,5358112,(i=h,h=h+4|0,a[i>>2]=r,i));0!=(j|0)&&G(c,5357988,(i=h,h=h+4|0,a[i>>2]=j,i))}d=e+24|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);G(c,5357716,(i=h,h=h+8|0,f[b>>3]=d,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i));d=p+16|0;p=a[p+48>>2];1==(p|0)?(p=ca[d+1|0],g=ca[d+2|0],G(c,5357408,(i=h,h=h+12|0,a[i>>2]=ca[d],a[i+4>>2]=p,a[i+8>>2]=g,i))):5==(p|0)?0!=(Eb(a[d>>2],5374748)|0)&&G(c,5357544,(i=h,h=h+4|0,a[i>>2]=a[d>>2],i)):ia(5361908,379,5379432,5340724);A(c,5357224);e=(e|0)>>2;e=a[e];e=jc(e);A(c,e);A(c,5357048);h=l}function th(c,d){var g,e=h,l=a[c+16>>2];g=l>>2;A(c,5364640);if(0==(d|0)){A(c,5341724)}else{var p=l+52|0;Ks(c,p);1==(a[g+21]|0)&&(p=n[p+3|0],0==p<<24>>24|-1==p<<24>>24||G(c,5364404,(i=h,h=h+8|0,f[b>>3]=(p&255)/255,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i)))}A(c,5364012);p=l+16|0;Ks(c,p);l=l+96|0;l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);1!=l&&G(c,5363660,(i=h,h=h+8|0,f[b>>3]=l,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i));l=a[g+22];1==(l|0)?G(c,5363384,(i=h,h=h+4|0,a[i>>2]=5362392,i)):2==(l|0)&&G(c,5363384,(i=h,h=h+4|0,a[i>>2]=5362576,i));1==(a[g+12]|0)&&(g=n[p+3|0],0==g<<24>>24|-1==g<<24>>24||G(c,5363092,(i=h,h=h+8|0,f[b>>3]=(g&255)/255,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i)));A(c,5337992);h=e}function Ks(b,c){var d=h,e=c,c=h;h=h+36|0;for(var e=e>>2,f=c>>2,p=e+9;e<p;e++,f++){a[f]=a[e]}e=a[c+32>>2];5==(e|0)?A(b,a[c>>2]):1==(e|0)?0==n[c+3|0]<<24>>24?A(b,5341724):(e=a[c>>2],G(b,5341348,(i=h,h=h+12|0,a[i>>2]=e&255,a[i+4>>2]=e>>>8&255,a[i+8>>2]=e>>>16&255,i))):ia(5361908,86,5379448,5340724);h=d}function Ls(c,d,g,e){var l=h,p=a[c+16>>2];if(0!=(a[p+88>>2]|0)){var j=e+24|0,k=c+348|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])*(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])&-1;0!=(j|0)&&(uh(c),A(c,5347648),od(c,d,g-.55*(j|0)),A(c,5347164),A(c,a[e>>2]),A(c,5346688),A(c,5338028),Bf(c,p+16|0),A(c,5346300),d=a[e+4>>2],d=a[(0==(d|0)?e+20|0:d+4|0)>>2],A(c,5337992),A(c,d),A(c,5337992),G(c,5345668,(i=h,h=h+4|0,a[i>>2]=j,i)),e=n[e+72|0]<<24>>24,114==(e|0)?A(c,5344860):108==(e|0)&&A(c,5345280),lg(c),A(c,5344600))}h=l}function Ms(c,d,g){var e,h,i,j=a[c+16>>2];i=(j+88|0)>>2;if(0!=(a[i]|0)){h=d+16|0;var k=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]);h=(d|0)>>2;var r=(a[b>>2]=a[h],a[b+4>>2]=a[h+1],f[b>>3]);e=d+24|0;var q=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);e=(d+8|0)>>2;var m=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);f[b>>3]=r-(k-r);a[h]=a[b>>2];a[h+1]=a[b+4>>2];f[b>>3]=m-(q-m);a[e]=a[b>>2];a[e+1]=a[b+4>>2];uh(c);A(c,5348112);xe(c,d,2);A(c,5338028);0==(g|0)?0==(a[1313373]|0)?A(c,5360332):A(c,5348884):Bf(c,j+52|0);1==(a[1313373]|0)&&(a[1313373]=0);A(c,5355052);d=j+96|0;ag(c,(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]));A(c,5348968);Bf(c,j+16|0);j=a[i];1==(j|0)?(A(c,5335180),i=a[i]):i=j;2==(i|0)&&A(c,5332424);lg(c);A(c,5344600)}}function Ns(c,d,g,e){var h,i=a[c+16>>2];h=(i+88|0)>>2;0!=(a[h]|0)&&(uh(c),A(c,5351760),xe(c,d,g),A(c,5338028),0==(e|0)?0==(a[1313373]|0)?A(c,5360332):A(c,5348884):Bf(c,i+52|0),1==(a[1313373]|0)&&(a[1313373]=0),A(c,5355052),d=i+96|0,ag(c,(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])),A(c,5348968),Bf(c,i+16|0),i=a[h],1==(i|0)?(A(c,5335180),h=a[h]):h=i,2==(h|0)&&A(c,5332424),lg(c),A(c,5344600))}function uh(b){0==n[b+140|0]<<24>>24?A(b,5356612):A(b,a[b+144>>2])}function Bf(b,c){var d=h,e=c,c=h;h=h+36|0;for(var e=e>>2,f=c>>2,p=e+9;e<p;e++,f++){a[f]=a[e]}e=a[c+32>>2];1==(e|0)?0==n[c+3|0]<<24>>24?A(b,5360332):(e=a[c>>2],G(b,5341348,(i=h,h=h+12|0,a[i>>2]=e&255,a[i+4>>2]=e>>>8&255,a[i+8>>2]=e>>>16&255,i))):5==(e|0)?A(b,a[c>>2]):ia(5367316,51,5379412,5340724);h=d}function lg(b){var c,d=h;c=a[b+16>>2]>>2;var e=a[c+3];if(1==(e|0)){var f=a[a[c+2]>>2]>>8,p=5372324,j=1}else{9==(e|0)|2==(e|0)|3==(e|0)?(f=a[a[c+2]>>2]>>8,p=5374900,j=1):11==(e|0)|6==(e|0)|7==(e|0)?(f=a[a[c+2]>>2]>>8,p=5374900,j=0):8==(e|0)?(f=a[a[c+2]>>2]>>8,p=5329472,j=1):10==(e|0)?(f=a[a[c+2]>>2]>>8,p=5329472,j=0):0==(e|0)?(f=a[a[c+2]>>2]>>8,p=5372324,j=1):4==(e|0)?(f=a[a[c+2]>>2]>>8,p=5369516,j=0):5==(e|0)?(f=a[a[c+2]>>2]>>8,p=5372324,j=0):ia(5367316,148,5379392,5340724)}G(b,5362360,(i=h,h=h+12|0,a[i>>2]=j,a[i+4>>2]=p,a[i+8>>2]=f,i));h=d}function De(b){var c=0,d=h;h=h+16|0;var e=a[1312806];if(0==(e|0)){a[1312805]=64;var e=Za(64),f=a[1312806]=e}else{f=e}var e=d+15|0,i=d+14|0,j=b,k=f,r=b=0,q=0,m=0,w=f;a:for(;;){for(var x=0==(b|0),f=j,v=k,j=q,k=m,t=w;;){if(0==(f|0)){c=991;break a}var y=n[f];if(0==y<<24>>24){c=992;break a}var z=a[1312805];(r|0)>(z-8|0)?(z<<=1,a[1312805]=z,y=Oa(t,z),a[1312806]=y,z=y+r|0,m=n[f]):(z=v,m=y,y=t);if(32==m<<24>>24){c=969;break}else{if(62==m<<24>>24){var A=4,C=5348588,c=985;break}else{if(45==m<<24>>24){var D=k,E=j,G=5,H=5344496;break}else{if(38==m<<24>>24){c=968;break}else{if(60==m<<24>>24){var I=5366660,J=4,c=983;break}}}}}if(39==m<<24>>24){A=5;C=5335100;c=985;break}else{if(34==m<<24>>24){I=5337956;J=6;c=983;break}}if(0<=m<<24>>24){I=f;J=1;c=983;break}for(var P=0,K=127,M=m&255;;){var L=P+1|0,N=K&M,K=K>>>1;if(K>>>0<N>>>0){P=L,M=N}else{break}}0<(P|0)?(K=L,P=N):(K=j,P=(k<<6)+N|0);K=K-1|0;M=f+1|0;if(0<(K|0)){f=M,v=z,j=K,k=P,t=y}else{c=979;break}}do{if(969==c){x?c=972:32==n[b]<<24>>24?(I=5340936,J=6,c=983):c=972}else{if(985==c){c=0,D=k,E=j,G=A,H=C}else{if(968==c){c=f+1|0;m=n[c];if(35!=m<<24>>24){for(;;){w=c+1|0;if(!(26>(m-97&255)|26>(m-65&255))){var Q=m;break}c=w;m=n[w]}}else{if(c=f+2|0,m=n[c],120==m<<24>>24|88==m<<24>>24){for(c=f+3|0;;){if(m=n[c],10>(m-48&255)|6>(m-97&255)|6>(m-65&255)){c=c+1|0}else{Q=m;break}}}else{for(;;){w=c+1|0;if(10<=(m-48&255)){Q=m;break}c=w;m=n[w]}}}c=59==Q<<24>>24;c&=1;0==(c|0)?(I=5340252,J=5,c=983):c=972}else{if(979==c){c=0;n[e]=59;m=i;w=3;for(q=P;;){var U=m-1|0;n[m]=((q>>>0)%10|48)&255;var R=Math.floor((q>>>0)/10),Y=w+1|0;if(12<(Y|0)){c=981;break a}if(9<q>>>0){m=U,w=Y,q=R}else{break}}m=m-2|0;n[U]=35;n[m]=38;if(0==(Y|0)){j=M;k=z;b=f;q=K;m=R;w=y;continue a}else{D=R,E=K,G=Y,H=m}}}}}}while(0);972==c&&(I=f,J=1,c=983);983==c&&(c=0,D=k,E=j,G=J,H=I);r=G+r|0;j=G;b=H;for(x=z;;){j=j-1|0;n[x]=n[b];if(0==(j|0)){break}b=b+1|0;x=x+1|0}j=f+1|0;k=z+G|0;b=f;q=E;m=D;w=y}if(981==c){re(5332228,46,1,a[Qa>>2]),Qd()}else{if(992==c||991==c){return n[v]=0,h=d,t}}}function Os(c){var d=h,g=a[c+16>>2],e=c+228|0,l=c+212|0;a[1313350]=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])&-1;e=c+220|0;l=c+204|0;a[1313349]=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])&-1;A(c,5326696);A(c,5326392);g=a[a[g+8>>2]+12>>2];0!=n[g]<<24>>24&&(A(c,5326136),A(c,De(g)),A(c,5325924));g=Math.a(a[c+164>>2],a[c+160>>2]);G(c,5325696,(i=h,h=h+4|0,a[i>>2]=g,i));A(c,5325400);A(c,5378704);A(c,5378452);A(c,5378164);A(c,5377848);A(c,5377644);A(c,5377448);A(c,5377176);A(c,5376936);A(c,5376684);A(c,5376436);A(c,5376172);A(c,5375788);A(c,5375472);A(c,5375160);A(c,5374864);A(c,5374524);A(c,5374224);A(c,5374004);A(c,5373808);A(c,5373580);A(c,5374864);A(c,5373328);A(c,5374224);A(c,5374004);A(c,5373e3);A(c,5375472);A(c,5375160);A(c,5374864);A(c,5373328);A(c,5374224);A(c,5374004);A(c,5373808);A(c,5373580);A(c,5374864);A(c,5374524);A(c,5374224);A(c,5374004);A(c,5372756);A(c,5372520);A(c,5372284);A(c,5372028);A(c,5371784);A(c,5371512);g=a[1313350]+10|0;G(c,5371268,(i=h,h=h+8|0,a[i>>2]=a[1313349],a[i+4>>2]=g,i));A(c,5371008);A(c,5370744);A(c,5370464);A(c,5370120);A(c,5369788);g=a[1313350];G(c,5369464,(i=h,h=h+8|0,a[i>>2]=a[1313349],a[i+4>>2]=g,i));g=a[1313350];G(c,5369224,(i=h,h=h+8|0,a[i>>2]=a[1313349],a[i+4>>2]=g,i));h=d}function Ps(c,d,g,e){var l,p=h,j=a[c+16>>2],k=n[e+72|0]<<24>>24;if(114==(k|0)){var k=e+56|0,r=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),k=d-r}else{108==(k|0)?(r=e+56|0,k=d,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3])):(k=e+56|0,r=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),k=d-.5*r)}l=(e+64|0)>>2;var q=(a[b>>2]=a[l],a[b+4>>2]=a[l+1],f[b>>3]),d=(e+24|0)>>2,m=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);q<m&&(q=1.1*m+1,f[b>>3]=q,a[l]=a[b>>2],a[l+1]=a[b+4>>2]);l=k-8;var g=(a[1313350]>>>0)-g,w=m/5,m=12>m?w+1.4:w+2,q=g-q+m;G(c,5334888,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));G(c,5335744,(i=h,h=h+16|0,f[b>>3]=l,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=q,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));G(c,5335432,(i=h,h=h+16|0,f[b>>3]=k+(r+8)-l,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=g+m-q,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));A(c,5334640);A(c,5334324);g=(e+4|0)>>2;k=a[g];0==(k|0)?G(c,5334072,(i=h,h=h+4|0,a[i>>2]=a[e+20>>2],i)):(G(c,5334072,(i=h,h=h+4|0,a[i>>2]=a[k+4>>2],i)),k=a[g],r=a[k+8>>2],0!=(r|0)&&(G(c,5333828,(i=h,h=h+4|0,a[i>>2]=r,i)),k=a[g]),r=a[k+12>>2],0==(r|0)?g=k:(G(c,5333560,(i=h,h=h+4|0,a[i>>2]=r,i)),g=a[g]),g=a[g+16>>2],0!=(g|0)&&G(c,5333184,(i=h,h=h+4|0,a[i>>2]=g,i)));d=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);G(c,5332876,(i=h,h=h+8|0,f[b>>3]=d,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i));d=j+16|0;j=a[j+48>>2];5==(j|0)?0!=(Eb(a[d>>2],5374748)|0)&&G(c,5332620,(i=h,h=h+4|0,a[i>>2]=a[d>>2],i)):1==(j|0)?(j=ca[d+1|0],g=ca[d+2|0],G(c,5332368,(i=h,h=h+12|0,a[i>>2]=ca[d],a[i+4>>2]=j,a[i+8>>2]=g,i))):ia(5340984,442,5379344,5340724);A(c,5332032);e=(e|0)>>2;e=a[e];e=De(e);A(c,e);A(c,5331720);A(c,5331432);h=p}function Ii(c){var d=h,g=a[c+16>>2];A(c,5343448);Qs(c,g+16|0);var e=g+96|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);1!=e&&G(c,5343016,(i=h,h=h+8|0,f[b>>3]=e,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i));g=a[g+88>>2];1==(g|0)?A(c,5342720):2==(g|0)&&A(c,5342448);A(c,5342064);h=d}function Qs(b,c){var d=h,e=c,c=h;h=h+36|0;for(var e=e>>2,f=c>>2,p=e+9;e<p;e++,f++){a[f]=a[e]}e=a[c+32>>2];1==(e|0)?0==n[c+3|0]<<24>>24?A(b,5341724):(e=a[c>>2],G(b,5341348,(i=h,h=h+12|0,a[i>>2]=e&255,a[i+4>>2]=e>>>8&255,a[i+8>>2]=e>>>16&255,i))):5==(e|0)?A(b,a[c>>2]):ia(5340984,95,5379360,5340724);h=d}function Yl(b,c){if(0==(c|0)){A(b,5337200)}else{var d=a[b+16>>2];A(b,5337724);Qs(b,d+52|0);A(b,5337428)}}function Rs(c,d,g){var e,l=d>>2,p=0,j=h;h=h+72|0;e=g>>2;g=h;h=h+32|0;a[g>>2]=a[e];a[g+4>>2]=a[e+1];a[g+8>>2]=a[e+2];a[g+12>>2]=a[e+3];a[g+16>>2]=a[e+4];a[g+20>>2]=a[e+5];a[g+24>>2]=a[e+6];a[g+28>>2]=a[e+7];0==(c|0)&&ia(5338512,146,5380024,5338204);0==(d|0)&&ia(5338512,147,5380024,5337976);0==(a[l+2]|0)&&ia(5338512,148,5380024,5337700);e=(d+52|0)>>2;if(0==(a[e]|0)){p=1118}else{var k=d+60|0,r=a[k>>2];94!=(r|0)&&(J[r](d),a[e]=0,a[k>>2]=0,a[l+14]=0,p=1118)}if(1118==p){if(0==wp(d)<<24>>24){h=j;return}p=a[l+5];2>(a[l+6]-6|0)>>>0&&(mm(p,j),k=a[j+28>>2],a[l+14]=k,r=wb(k),a[e]=r,Ri(p,r,k),n[d+16|0]=1);0!=(a[e]|0)&&(a[l+15]=94);xp(d);if(0==(a[e]|0)){h=j;return}}p=g|0;p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])-(a[l+8]|0);g=g+8|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])-(a[l+9]|0);G(c,5336392,(i=h,h=h+16|0,f[b>>3]=p,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=g,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));0==n[d+16|0]<<24>>24?G(c,5336024,(i=h,h=h+4|0,a[i>>2]=a[l+3],i)):lk(c,a[e]);G(c,5335720,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));h=j}function Ss(c,d,g){var e,l=h;e=g>>2;g=h;h=h+32|0;a[g>>2]=a[e];a[g+4>>2]=a[e+1];a[g+8>>2]=a[e+2];a[g+12>>2]=a[e+3];a[g+16>>2]=a[e+4];a[g+20>>2]=a[e+5];a[g+24>>2]=a[e+6];a[g+28>>2]=a[e+7];0==(c|0)&&ia(5338512,90,5380044,5338204);0==(d|0)&&ia(5338512,91,5380044,5337976);d=d+8|0;0==(a[d>>2]|0)&&ia(5338512,92,5380044,5337700);e=g|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);e=(0>e?e-.5:e+.5)&-1;var p=g+8|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),p=(0>p?p-.5:p+.5)&-1,j=g+16|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),j=(0>j?j-.5:j+.5)&-1,g=g+24|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),g=(0>g?g-.5:g+.5)&-1,d=a[d>>2];G(c,5332296,(i=h,h=h+76|0,a[i>>2]=2,a[i+4>>2]=5,a[i+8>>2]=0,a[i+12>>2]=0,a[i+16>>2]=0,a[i+20>>2]=-1,a[i+24>>2]=1,a[i+28>>2]=-1,a[i+32>>2]=0,f[b>>3]=0,a[i+36>>2]=a[b>>2],a[i+40>>2]=a[b+4>>2],a[i+44>>2]=0,a[i+48>>2]=0,a[i+52>>2]=0,a[i+56>>2]=0,a[i+60>>2]=0,a[i+64>>2]=5,a[i+68>>2]=0,a[i+72>>2]=d,i));G(c,5331988,(i=h,h=h+40|0,a[i>>2]=e,a[i+4>>2]=p,a[i+8>>2]=e,a[i+12>>2]=g,a[i+16>>2]=j,a[i+20>>2]=g,a[i+24>>2]=j,a[i+28>>2]=p,a[i+32>>2]=e,a[i+36>>2]=p,i));h=l}function Ts(c,d,g){var e,l=h;e=g>>2;g=h;h=h+32|0;a[g>>2]=a[e];a[g+4>>2]=a[e+1];a[g+8>>2]=a[e+2];a[g+12>>2]=a[e+3];a[g+16>>2]=a[e+4];a[g+20>>2]=a[e+5];a[g+24>>2]=a[e+6];a[g+28>>2]=a[e+7];0==(c|0)&&ia(5338512,49,5379980,5338204);0==(d|0)&&ia(5338512,50,5379980,5337976);d=d+8|0;0==(a[d>>2]|0)&&ia(5338512,51,5379980,5337700);A(c,5331688);A(c,a[d>>2]);var d=c+356|0,p=g+16|0;if(0==(a[d>>2]|0)){d=p|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);e=g|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);var j=g+24|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),g=g+8|0,g=j-(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);G(c,5330764,(i=h,h=h+32|0,f[b>>3]=d-e,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=g,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],f[b>>3]=e,a[i+16>>2]=a[b>>2],a[i+20>>2]=a[b+4>>2],f[b>>3]=-j,a[i+24>>2]=a[b>>2],a[i+28>>2]=a[b+4>>2],i))}else{e=g+24|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),j=g+8|0,j=e-(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),p|=0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),g|=0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),G(c,5331340,(i=h,h=h+32|0,f[b>>3]=j,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=p-g,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],f[b>>3]=g,a[i+16>>2]=a[b>>2],a[i+20>>2]=a[b+4>>2],f[b>>3]=e,a[i+24>>2]=a[b>>2],a[i+28>>2]=a[b+4>>2],i)),G(c,5331056,(i=h,h=h+20|0,a[i>>2]=a[d>>2],f[b>>3]=g,a[i+4>>2]=a[b>>2],a[i+8>>2]=a[b+4>>2],f[b>>3]=e,a[i+12>>2]=a[b>>2],a[i+16>>2]=a[b+4>>2],i))}A(c,5330440);h=l}function wb(b){do{if(245>b>>>0){var c=11>b>>>0?16:b+11&-8,d=c>>>3,e=a[1344719],f=e>>>(d>>>0);if(0!=(f&3|0)){var h=(f&1^1)+d|0,j=h<<1,c=(j<<2)+5378916|0,d=(j+2<<2)+5378916|0,b=a[d>>2],j=b+8|0,f=a[j>>2];(c|0)==(f|0)?a[1344719]=e&(1<<h^-1):f>>>0<a[1344723]>>>0?P():(a[d>>2]=f,a[f+12>>2]=c);h<<=3;a[b+4>>2]=h|3;h=b+(h|4)|0;a[h>>2]|=1;return j}if(c>>>0>a[1344721]>>>0){if(0==(f|0)){if(0==(a[1344720]|0)){e=c;break}j=Us(c);if(0==(j|0)){e=c;break}return j}var b=2<<d,b=f<<d&(b|-b),d=(b&-b)-1|0,b=d>>>12&16,f=d>>>(b>>>0),d=f>>>5&8,i=f>>>(d>>>0),f=i>>>2&4,r=i>>>(f>>>0),i=r>>>1&2,r=r>>>(i>>>0),q=r>>>1&1,f=(d|b|f|i|q)+(r>>>(q>>>0))|0,b=f<<1,i=(b<<2)+5378916|0,r=(b+2<<2)+5378916|0,d=a[r>>2],b=d+8|0,q=a[b>>2];(i|0)==(q|0)?a[1344719]=e&(1<<f^-1):q>>>0<a[1344723]>>>0?P():(a[r>>2]=q,a[q+12>>2]=i);f<<=3;e=f-c|0;a[d+4>>2]=c|3;i=d;d=i+c|0;a[i+(c|4)>>2]=e|1;a[i+f>>2]=e;q=a[1344721];0!=(q|0)&&(c=a[1344724],i=q>>>2&1073741822,f=(i<<2)+5378916|0,r=a[1344719],q=1<<(q>>>3),0==(r&q|0)?(a[1344719]=r|q,j=f,h=(i+2<<2)+5378916|0):(i=(i+2<<2)+5378916|0,r=a[i>>2],r>>>0<a[1344723]>>>0?P():(j=r,h=i)),a[h>>2]=c,a[j+12>>2]=c,a[c+8>>2]=j,a[c+12>>2]=f);a[1344721]=e;a[1344724]=d;return j=b}e=c}else{if(4294967231<b>>>0){e=-1}else{if(e=b+11&-8,0!=(a[1344720]|0)&&(c=Vs(e),0!=(c|0))){return j=c}}}}while(0);h=a[1344721];e>>>0>h>>>0?(j=a[1344722],e>>>0<j>>>0?(j=j-e|0,a[1344722]=j,h=a[1344725],a[1344725]=h+e|0,a[e+(h+4)>>2]=j|1,a[h+4>>2]=e|3,j=h+8|0):j=Ws(e)):(c=h-e|0,j=a[1344724],15<c>>>0?(a[1344724]=j+e|0,a[1344721]=c,a[e+(j+4)>>2]=c|1,a[j+h>>2]=c,a[j+4>>2]=e|3):(a[1344721]=0,a[1344724]=0,a[j+4>>2]=h|3,h=h+(j+4)|0,a[h>>2]|=1),j=j+8|0);return j}function Us(b){var c,d,e=a[1344720],f=(e&-e)-1|0,e=f>>>12&16,h=f>>>(e>>>0),f=h>>>5&8;d=h>>>(f>>>0);var h=d>>>2&4,j=d>>>(h>>>0);d=j>>>1&2;var j=j>>>(d>>>0),i=j>>>1&1,e=h=f=a[((f|e|h|d|i)+(j>>>(i>>>0))<<2)+5379180>>2];d=e>>2;for(f=(a[f+4>>2]&-8)-b|0;;){j=a[h+16>>2];if(0==(j|0)){if(h=a[h+20>>2],0==(h|0)){break}else{d=h}}else{d=j}j=(a[d+4>>2]&-8)-b|0;i=j>>>0<f>>>0;h=d;e=i?d:e;d=e>>2;f=i?j:f}var j=e,r=a[1344723];j>>>0<r>>>0&&P();h=j+b|0;j>>>0<h>>>0||P();var i=a[d+6],q=a[d+3];a:do{if((q|0)==(e|0)){var m=e+20|0,n=a[m>>2];do{if(0==(n|0)){var x=e+16|0,v=a[x>>2];if(0==(v|0)){var t=0;c=t>>2;break a}}else{x=m,v=n}}while(0);for(;;){if(m=v+20|0,n=a[m>>2],0!=(n|0)){x=m,v=n}else{if(m=v+16|0,n=a[m>>2],0==(n|0)){break}else{x=m,v=n}}}x>>>0<r>>>0?P():(a[x>>2]=0,t=v,c=t>>2)}else{x=a[d+2],x>>>0<r>>>0?P():(a[x+12>>2]=q,a[q+8>>2]=x,t=q,c=t>>2)}}while(0);a:do{if(0!=(i|0)){r=e+28|0;q=(a[r>>2]<<2)+5379180|0;do{if((e|0)==(a[q>>2]|0)){if(a[q>>2]=t,0==(t|0)){a[1344720]&=1<<a[r>>2]^-1;break a}}else{if(i>>>0<a[1344723]>>>0&&P(),x=i+16|0,(a[x>>2]|0)==(e|0)?a[x>>2]=t:a[i+20>>2]=t,0==(t|0)){break a}}}while(0);t>>>0<a[1344723]>>>0&&P();a[c+6]=i;r=a[d+4];0!=(r|0)&&(r>>>0<a[1344723]>>>0?P():(a[c+4]=r,a[r+24>>2]=t));r=a[d+5];0!=(r|0)&&(r>>>0<a[1344723]>>>0?P():(a[c+5]=r,a[r+24>>2]=t))}}while(0);if(16>f>>>0){var y=f+b|0;a[d+1]=y|3;y=y+(j+4)|0;a[y>>2]|=1;return y=e+8|0}a[d+1]=b|3;a[b+(j+4)>>2]=f|1;a[j+f+b>>2]=f;j=a[1344721];if(0!=(j|0)){b=a[1344724];t=j>>>2&1073741822;c=(t<<2)+5378916|0;d=a[1344719];j=1<<(j>>>3);if(0==(d&j|0)){a[1344719]=d|j;var y=c,z=(t+2<<2)+5378916|0}else{t=(t+2<<2)+5378916|0,d=a[t>>2],d>>>0<a[1344723]>>>0?P():(y=d,z=t)}a[z>>2]=b;a[y+12>>2]=b;a[b+8>>2]=y;a[b+12>>2]=c}a[1344721]=f;a[1344724]=h;return y=e+8|0}function Ws(b){var c,d=0;0==(a[1312714]|0)&&Xs();a:do{if(0==(a[1344829]&4|0)){var e=a[1344725];if(0==(e|0)){d=1277}else{if(e=Zl(e),0==(e|0)){d=1277}else{var f=a[1312716],f=b+47-a[1344722]+f&-f;if(2147483647>f>>>0){var d=Gd(f),h=(d|0)==(a[e>>2]+a[e+4>>2]|0);c=h?d:-1;var h=h?f:0,j=f,i=d,d=1284}else{var n=0}}}if(1277==d){if(e=Gd(0),-1==(e|0)){n=0}else{var f=a[1312716],f=f+(b+47)&-f,q=e,m=a[1312715],w=m-1|0,f=0==(w&q|0)?f:f-q+(w+q&-m)|0;2147483647>f>>>0?(d=Gd(f),c=(h=(d|0)==(e|0))?e:-1,h=h?f:0,j=f,i=d,d=1284):n=0}}b:do{if(1284==d){d=-j|0;if(-1!=(c|0)){var x=h,v=c,d=1297;break a}do{if(-1!=(i|0)&2147483647>j>>>0){if(j>>>0<(b+48|0)>>>0){if(n=a[1312716],n=b+47-j+n&-n,2147483647>n>>>0){if(-1==(Gd(n)|0)){Gd(d);n=h;break b}else{n=n+j|0}}else{n=j}}else{n=j}}else{n=j}}while(0);if(-1!=(i|0)){x=n;v=i;d=1297;break a}a[1344829]|=4;var t=h,d=1294;break a}}while(0);a[1344829]|=4;t=n}else{t=0}d=1294}while(0);1294==d&&(c=a[1312716],c=c+(b+47)&-c,2147483647>c>>>0&&(c=Gd(c),h=Gd(0),-1!=(h|0)&-1!=(c|0)&c>>>0<h>>>0&&(h=h-c|0,c=(j=h>>>0>(b+40|0)>>>0)?c:-1,-1!=(c|0)&&(x=j?h:t,v=c,d=1297))));do{if(1297==d){t=a[1344827]+x|0;a[1344827]=t;t>>>0>a[1344828]>>>0&&(a[1344828]=t);t=a[1344725];a:do{if(0==(t|0)){c=a[1344723];0==(c|0)|v>>>0<c>>>0&&(a[1344723]=v);a[1344830]=v;a[1344831]=x;a[1344833]=0;a[1344728]=a[1312714];a[1344727]=-1;for(c=0;!(h=c<<1,j=(h<<2)+5378916|0,a[(h+3<<2)+5378916>>2]=j,a[(h+2<<2)+5378916>>2]=j,c=c+1|0,32==(c|0));){}Ji(v,x-40|0)}else{h=5379320;for(c=h>>2;0!=(h|0);){var y=a[c],z=h+4|0,A=a[z>>2];if((v|0)==(y+A|0)){d=1306;break}h=a[c+2];c=h>>2}do{if(1306==d&&0==(a[c+3]&8|0)&&(h=t,h>>>0>=y>>>0&h>>>0<v>>>0)){a[z>>2]=A+x|0;Ji(a[1344725],a[1344722]+x|0);break a}}while(0);v>>>0<a[1344723]>>>0&&(a[1344723]=v);c=v+x|0;for(h=5379320;0!=(h|0);){var C=h|0;if((a[C>>2]|0)==(c|0)){d=1315;break}h=a[h+8>>2]}if(1315==d&&0==(a[h+12>>2]&8|0)){return a[C>>2]=v,y=h+4|0,a[y>>2]=a[y>>2]+x|0,b=Ys(v,c,b)}Zs(v,x)}}while(0);t=a[1344722];if(t>>>0>b>>>0){return x=t-b|0,a[1344722]=x,y=v=a[1344725],a[1344725]=y+b|0,a[b+(y+4)>>2]=x|1,a[v+4>>2]=b|3,b=v+8|0}}}while(0);a[Ha.d>>2]=12;return 0}function Vs(b){var c,d,e,f,h,j=b>>2,i=0,n=-b|0,q=b>>>8;if(0==(q|0)){var m=0}else{if(16777215<b>>>0){m=31}else{var w=(q+1048320|0)>>>16&8,x=q<<w,v=(x+520192|0)>>>16&4,t=x<<v,y=(t+245760|0)>>>16&2,z=14-(v|w|y)+(t<<y>>>15)|0,m=b>>>((z+7|0)>>>0)&1|z<<1}}var A=a[(m<<2)+5379180>>2];a:do{if(0==(A|0)){var C=0,D=n,E=0}else{var G=31==(m|0)?0:25-(m>>>1)|0,H=0,I=n,J=A;h=J>>2;for(var N=b<<G,K=0;;){var M=a[h+1]&-8,L=M-b|0;if(L>>>0<I>>>0){if((M|0)==(b|0)){C=J;D=L;E=J;break a}else{var Q=J,U=L}}else{Q=H,U=I}var aa=a[h+5],R=a[((N>>>31<<2)+16>>2)+h],Y=0==(aa|0)|(aa|0)==(R|0)?K:aa;if(0==(R|0)){C=Q;D=U;E=Y;break a}else{H=Q,I=U,J=R,h=J>>2,N<<=1,K=Y}}}}while(0);if(0==(E|0)&0==(C|0)){var $=2<<m,ca=a[1344720]&($|-$);if(0==(ca|0)){var da=0;return da}var ea=(ca&-ca)-1|0,fa=ea>>>12&16,ha=ea>>>(fa>>>0),V=ha>>>5&8,W=ha>>>(V>>>0),X=W>>>2&4,ba=W>>>(X>>>0),ia=ba>>>1&2,na=ba>>>(ia>>>0),sa=na>>>1&1,qa=a[((V|fa|X|ia|sa)+(na>>>(sa>>>0))<<2)+5379180>>2]}else{qa=E}a:do{if(0==(qa|0)){var O=D,ga=C;f=ga>>2}else{var ta=qa;e=ta>>2;for(var xa=D,ua=C;;){var Da=(a[e+1]&-8)-b|0,Ja=Da>>>0<xa>>>0,Ha=Ja?Da:xa,ra=Ja?ta:ua,Oa=a[e+4];if(0!=(Oa|0)){ta=Oa,e=ta>>2,xa=Ha,ua=ra}else{var ya=a[e+5];if(0==(ya|0)){O=Ha;ga=ra;f=ga>>2;break a}else{ta=ya,e=ta>>2,xa=Ha,ua=ra}}}}}while(0);if(0==(ga|0)||O>>>0>=(a[1344721]-b|0)>>>0){return da=0}var ja=ga;d=ja>>2;var la=a[1344723];ja>>>0<la>>>0&&P();var va=ja+b|0;ja>>>0<va>>>0||P();var oa=a[f+6],ka=a[f+3];a:do{if((ka|0)==(ga|0)){var Ea=ga+20|0,Ka=a[Ea>>2];do{if(0==(Ka|0)){var Na=ga+16|0,Ba=a[Na>>2];if(0==(Ba|0)){var Wa=0;c=Wa>>2;break a}else{var Qa=Na,Pa=Ba}}else{Qa=Ea,Pa=Ka}}while(0);for(;;){var Ra=Pa+20|0,bb=a[Ra>>2];if(0!=(bb|0)){Qa=Ra,Pa=bb}else{var Xa=Pa+16|0,Sa=a[Xa>>2];if(0==(Sa|0)){break}else{Qa=Xa,Pa=Sa}}}Qa>>>0<la>>>0?P():(a[Qa>>2]=0,Wa=Pa,c=Wa>>2)}else{var Za=a[f+2];Za>>>0<la>>>0?P():(a[Za+12>>2]=ka,a[ka+8>>2]=Za,Wa=ka,c=Wa>>2)}}while(0);a:do{if(0==(oa|0)){var Va=ga}else{var Ta=ga+28|0,Aa=(a[Ta>>2]<<2)+5379180|0;do{if((ga|0)==(a[Aa>>2]|0)){if(a[Aa>>2]=Wa,0==(Wa|0)){a[1344720]&=1<<a[Ta>>2]^-1;Va=ga;break a}}else{oa>>>0<a[1344723]>>>0&&P();var fb=oa+16|0;(a[fb>>2]|0)==(ga|0)?a[fb>>2]=Wa:a[oa+20>>2]=Wa;if(0==(Wa|0)){Va=ga;break a}}}while(0);Wa>>>0<a[1344723]>>>0&&P();a[c+6]=oa;var Ca=a[f+4];0!=(Ca|0)&&(Ca>>>0<a[1344723]>>>0?P():(a[c+4]=Ca,a[Ca+24>>2]=Wa));var Ya=a[f+5];0==(Ya|0)?Va=ga:Ya>>>0<a[1344723]>>>0?P():(a[c+5]=Ya,a[Ya+24>>2]=Wa,Va=ga)}}while(0);do{if(16>O>>>0){var $a=O+b|0;a[Va+4>>2]=$a|3;var La=$a+(ja+4)|0;a[La>>2]|=1}else{if(a[Va+4>>2]=b|3,a[j+(d+1)]=O|1,a[(O>>2)+d+j]=O,256>O>>>0){var pa=O>>>2&1073741822,Ga=(pa<<2)+5378916|0,Fa=a[1344719],eb=1<<(O>>>3);if(0==(Fa&eb|0)){a[1344719]=Fa|eb;var nb=Ga,jb=(pa+2<<2)+5378916|0}else{var cb=(pa+2<<2)+5378916|0,hb=a[cb>>2];hb>>>0<a[1344723]>>>0?P():(nb=hb,jb=cb)}a[jb>>2]=va;a[nb+12>>2]=va;a[j+(d+2)]=nb;a[j+(d+3)]=Ga}else{var kb=va,mb=O>>>8;if(0==(mb|0)){var Ma=0}else{if(16777215<O>>>0){Ma=31}else{var tb=(mb+1048320|0)>>>16&8,lb=mb<<tb,rb=(lb+520192|0)>>>16&4,ab=lb<<rb,db=(ab+245760|0)>>>16&2,ob=14-(rb|tb|db)+(ab<<db>>>15)|0,Ma=O>>>((ob+7|0)>>>0)&1|ob<<1}}var pb=(Ma<<2)+5379180|0;a[j+(d+7)]=Ma;a[j+(d+5)]=0;a[j+(d+4)]=0;var ub=a[1344720],gb=1<<Ma;if(0==(ub&gb|0)){a[1344720]=ub|gb,a[pb>>2]=kb,a[j+(d+6)]=pb,a[j+(d+3)]=kb,a[j+(d+2)]=kb}else{for(var sb=O<<(31==(Ma|0)?0:25-(Ma>>>1)|0),Ia=a[pb>>2];(a[Ia+4>>2]&-8|0)!=(O|0);){var vb=(sb>>>31<<2)+Ia+16|0,Ua=a[vb>>2];if(0==(Ua|0)){i=1394;break}else{sb<<=1,Ia=Ua}}if(1394==i){if(vb>>>0<a[1344723]>>>0){P()}else{a[vb>>2]=kb;a[j+(d+6)]=Ia;a[j+(d+3)]=kb;a[j+(d+2)]=kb;break}}var zb=Ia+8|0,wb=a[zb>>2],qb=a[1344723];Ia>>>0<qb>>>0&&P();wb>>>0<qb>>>0?P():(a[wb+12>>2]=kb,a[zb>>2]=kb,a[j+(d+2)]=wb,a[j+(d+3)]=Ia,a[j+(d+6)]=0)}}}}while(0);return da=Va+8|0}function $s(){var b;0==(a[1312714]|0)&&Xs();b=a[1344725];if(0!=(b|0)){var c=a[1344722];if(40<c>>>0){var d=a[1312716],e=Math.a(Math.floor(((c-41+d|0)>>>0)/(d>>>0))-1|0,d),f=Zl(b);if(0==(a[f+12>>2]&8|0)&&(c=Gd(0),b=(f+4|0)>>2,(c|0)==(a[f>>2]+a[b]|0)&&(e=Gd(-(2147483646<e>>>0?-2147483648-d|0:e)|0),d=Gd(0),-1!=(e|0)&d>>>0<c>>>0&&(e=c-d|0,(c|0)!=(d|0))))){a[b]=a[b]-e|0;a[1344827]=a[1344827]-e|0;Ji(a[1344725],a[1344722]-e|0);return}}a[1344722]>>>0>a[1344726]>>>0&&(a[1344726]=-1)}}function E(b){var c,d,e,f,h,j,i,n=b>>2,q=0;if(0!=(b|0)){var m=b-8|0,w=a[1344723];m>>>0<w>>>0&&P();var x=a[b-4>>2],v=x&3;1==(v|0)&&P();var t=x&-8;i=t>>2;var y=b+(t-8)|0;a:do{if(0==(x&1|0)){var z=a[m>>2];if(0==(v|0)){return}var A=-8-z|0;j=A>>2;var C=b+A|0,D=C,E=z+t|0;C>>>0<w>>>0&&P();if((D|0)==(a[1344724]|0)){h=(b+(t-4)|0)>>2;if(3!=(a[h]&3|0)){var G=D;f=G>>2;var H=E;break}a[1344721]=E;a[h]&=-2;a[j+(n+1)]=E|1;a[y>>2]=E;return}var I=z>>>3;if(256>z>>>0){var J=a[j+(n+2)],N=a[j+(n+3)];if((J|0)==(N|0)){a[1344719]&=1<<I^-1;G=D;f=G>>2;H=E;break}var K=((z>>>2&1073741822)<<2)+5378916|0;(J|0)!=(K|0)&J>>>0<w>>>0&&P();if((N|0)==(K|0)|N>>>0>=w>>>0){a[J+12>>2]=N;a[N+8>>2]=J;G=D;f=G>>2;H=E;break}else{P()}}var M=C,L=a[j+(n+6)],Q=a[j+(n+3)];b:do{if((Q|0)==(M|0)){var U=A+(b+20)|0,aa=a[U>>2];do{if(0==(aa|0)){var R=A+(b+16)|0,Y=a[R>>2];if(0==(Y|0)){var $=0;e=$>>2;break b}else{var da=R,ca=Y}}else{da=U,ca=aa}}while(0);for(;;){var ea=ca+20|0,fa=a[ea>>2];if(0!=(fa|0)){da=ea,ca=fa}else{var ha=ca+16|0,V=a[ha>>2];if(0==(V|0)){break}else{da=ha,ca=V}}}da>>>0<w>>>0?P():(a[da>>2]=0,$=ca,e=$>>2)}else{var W=a[j+(n+2)];W>>>0<w>>>0?P():(a[W+12>>2]=Q,a[Q+8>>2]=W,$=Q,e=$>>2)}}while(0);if(0==(L|0)){G=D,f=G>>2,H=E}else{var X=A+(b+28)|0,ba=(a[X>>2]<<2)+5379180|0;do{if((M|0)==(a[ba>>2]|0)){if(a[ba>>2]=$,0==($|0)){a[1344720]&=1<<a[X>>2]^-1;G=D;f=G>>2;H=E;break a}}else{L>>>0<a[1344723]>>>0&&P();var ia=L+16|0;(a[ia>>2]|0)==(M|0)?a[ia>>2]=$:a[L+20>>2]=$;if(0==($|0)){G=D;f=G>>2;H=E;break a}}}while(0);$>>>0<a[1344723]>>>0&&P();a[e+6]=L;var na=a[j+(n+4)];0!=(na|0)&&(na>>>0<a[1344723]>>>0?P():(a[e+4]=na,a[na+24>>2]=$));var qa=a[j+(n+5)];0==(qa|0)?(G=D,f=G>>2,H=E):qa>>>0<a[1344723]>>>0?P():(a[e+5]=qa,a[qa+24>>2]=$,G=D,f=G>>2,H=E)}}else{G=m,f=G>>2,H=t}}while(0);var sa=G;d=sa>>2;sa>>>0<y>>>0||P();var O=b+(t-4)|0,ga=a[O>>2];0==(ga&1|0)&&P();do{if(0==(ga&2|0)){if((y|0)==(a[1344725]|0)){var ta=a[1344722]+H|0;a[1344722]=ta;a[1344725]=G;a[f+1]=ta|1;(G|0)==(a[1344724]|0)&&(a[1344724]=0,a[1344721]=0);if(ta>>>0<=a[1344726]>>>0){return}$s();return}if((y|0)==(a[1344724]|0)){var xa=a[1344721]+H|0;a[1344721]=xa;a[1344724]=G;a[f+1]=xa|1;a[(xa>>2)+d]=xa;return}var ua=(ga&-8)+H|0,Da=ga>>>3;a:do{if(256>ga>>>0){var Ja=a[n+i],Ha=a[((t|4)>>2)+n];if((Ja|0)==(Ha|0)){a[1344719]&=1<<Da^-1}else{var ra=((ga>>>2&1073741822)<<2)+5378916|0;(Ja|0)!=(ra|0)&&Ja>>>0<a[1344723]>>>0&&P();(Ha|0)!=(ra|0)&&Ha>>>0<a[1344723]>>>0&&P();a[Ja+12>>2]=Ha;a[Ha+8>>2]=Ja}}else{var Oa=y,ya=a[i+(n+4)],ja=a[((t|4)>>2)+n];b:do{if((ja|0)==(Oa|0)){var la=t+(b+12)|0,va=a[la>>2];do{if(0==(va|0)){var oa=t+(b+8)|0,ka=a[oa>>2];if(0==(ka|0)){var Ea=0;c=Ea>>2;break b}else{var Ka=oa,Na=ka}}else{Ka=la,Na=va}}while(0);for(;;){var Ba=Na+20|0,Pa=a[Ba>>2];if(0!=(Pa|0)){Ka=Ba,Na=Pa}else{var Qa=Na+16|0,Za=a[Qa>>2];if(0==(Za|0)){break}else{Ka=Qa,Na=Za}}}Ka>>>0<a[1344723]>>>0?P():(a[Ka>>2]=0,Ea=Na,c=Ea>>2)}else{var Ra=a[n+i];Ra>>>0<a[1344723]>>>0?P():(a[Ra+12>>2]=ja,a[ja+8>>2]=Ra,Ea=ja,c=Ea>>2)}}while(0);if(0!=(ya|0)){var bb=t+(b+20)|0,Xa=(a[bb>>2]<<2)+5379180|0;do{if((Oa|0)==(a[Xa>>2]|0)){if(a[Xa>>2]=Ea,0==(Ea|0)){a[1344720]&=1<<a[bb>>2]^-1;break a}}else{ya>>>0<a[1344723]>>>0&&P();var Sa=ya+16|0;(a[Sa>>2]|0)==(Oa|0)?a[Sa>>2]=Ea:a[ya+20>>2]=Ea;if(0==(Ea|0)){break a}}}while(0);Ea>>>0<a[1344723]>>>0&&P();a[c+6]=ya;var eb=a[i+(n+2)];0!=(eb|0)&&(eb>>>0<a[1344723]>>>0?P():(a[c+4]=eb,a[eb+24>>2]=Ea));var Va=a[i+(n+3)];0!=(Va|0)&&(Va>>>0<a[1344723]>>>0?P():(a[c+5]=Va,a[Va+24>>2]=Ea))}}}while(0);a[f+1]=ua|1;a[(ua>>2)+d]=ua;if((G|0)!=(a[1344724]|0)){var Ta=ua}else{a[1344721]=ua;return}}else{a[O>>2]=ga&-2,a[f+1]=H|1,Ta=a[(H>>2)+d]=H}}while(0);if(256>Ta>>>0){var Aa=Ta>>>2&1073741822,fb=(Aa<<2)+5378916|0,Ca=a[1344719],Ya=1<<(Ta>>>3);if(0==(Ca&Ya|0)){a[1344719]=Ca|Ya;var $a=fb,La=(Aa+2<<2)+5378916|0}else{var pa=(Aa+2<<2)+5378916|0,Ga=a[pa>>2];Ga>>>0<a[1344723]>>>0?P():($a=Ga,La=pa)}a[La>>2]=G;a[$a+12>>2]=G;a[f+2]=$a;a[f+3]=fb}else{var Fa=G,hb=Ta>>>8;if(0==(hb|0)){var nb=0}else{if(16777215<Ta>>>0){nb=31}else{var jb=(hb+1048320|0)>>>16&8,cb=hb<<jb,mb=(cb+520192|0)>>>16&4,kb=cb<<mb,tb=(kb+245760|0)>>>16&2,Ma=14-(mb|jb|tb)+(kb<<tb>>>15)|0,nb=Ta>>>((Ma+7|0)>>>0)&1|Ma<<1}}var wb=(nb<<2)+5379180|0;a[f+7]=nb;a[f+5]=0;a[f+4]=0;var lb=a[1344720],rb=1<<nb;do{if(0==(lb&rb|0)){a[1344720]=lb|rb,a[wb>>2]=Fa,a[f+6]=wb,a[f+3]=G,a[f+2]=G}else{for(var ab=Ta<<(31==(nb|0)?0:25-(nb>>>1)|0),db=a[wb>>2];(a[db+4>>2]&-8|0)!=(Ta|0);){var ob=(ab>>>31<<2)+db+16|0,pb=a[ob>>2];if(0==(pb|0)){q=1547;break}else{ab<<=1,db=pb}}if(1547==q){if(ob>>>0<a[1344723]>>>0){P()}else{a[ob>>2]=Fa;a[f+6]=db;a[f+3]=G;a[f+2]=G;break}}var ub=db+8|0,gb=a[ub>>2],sb=a[1344723];db>>>0<sb>>>0&&P();gb>>>0<sb>>>0?P():(a[gb+12>>2]=Fa,a[ub>>2]=Fa,a[f+2]=gb,a[f+3]=db,a[f+6]=0)}}while(0);var Ia=a[1344727]-1|0;a[1344727]=Ia;if(0==(Ia|0)){for(var vb=5379328;;){var Ua=a[vb>>2];if(0==(Ua|0)){break}else{vb=Ua+8|0}}a[1344727]=-1}}}}function Zl(b){var c,d=0,e=5379320;for(c=e>>2;;){var f=a[c];if(f>>>0<=b>>>0&&(f+a[c+1]|0)>>>0>b>>>0){var h=e,d=1589;break}c=a[c+2];if(0==(c|0)){h=0;d=1590;break}else{e=c,c=e>>2}}if(1590==d||1589==d){return h}}function Ji(b,c){var d=b+8|0,d=0==(d&7|0)?0:-d&7,e=c-d|0;a[1344725]=b+d|0;a[1344722]=e;a[d+(b+4)>>2]=e|1;a[c+(b+4)>>2]=40;a[1344726]=a[1312718]}function bc(b,c){if(0==(b|0)){var d=0}else{d=Math.a(c,b),d=65535<(c|b)>>>0?(Math.floor((d>>>0)/(b>>>0))|0)==(c|0)?d:-1:d}var e=wb(d);if(0==(e|0)||0==(a[e-4>>2]&3|0)){return e}Ef(e,0,d);return e}function gc(a,b){return 0==(a|0)?wb(b):at(a,b)}function at(b,c){var d,e,f=0;if(4294967231<c>>>0){return a[Ha.d>>2]=12,0}var h=b-8|0;e=(b-4|0)>>2;var j=a[e],i=j&-8,n=i-8|0,q=b+n|0;h>>>0<a[1344723]>>>0&&P();var m=j&3;1!=(m|0)&-8<(n|0)||P();d=(b+(i-4)|0)>>2;0==(a[d]&1|0)&&P();n=11>c>>>0?16:c+11&-8;if(0==(m|0)){var w=0,x,j=a[h+4>>2]&-8;x=256>n>>>0?0:j>>>0>=(n+4|0)>>>0&&(j-n|0)>>>0<=a[1312716]<<1>>>0?h:0;f=1627}else{i>>>0<n>>>0?(q|0)==(a[1344725]|0)&&(d=a[1344722]+i|0,d>>>0>n>>>0&&(w=d-n|0,a[e]=n|j&1|2,a[b+(n-4)>>2]=w|1,a[1344725]=b+(n-8)|0,a[1344722]=w,w=0,x=h,f=1627)):(w=i-n|0,15<w>>>0?(a[e]=n|j&1|2,a[b+(n-4)>>2]=w|3,a[d]|=1,w=b+n|0):w=0,x=h,f=1627)}if(1627==f&&0!=(x|0)){return 0!=(w|0)&&E(w),x+8|0}h=wb(c);if(0==(h|0)){return 0}e=i-(0==(a[e]&3|0)?8:4)|0;$d(h,b,e>>>0<c>>>0?e:c);E(b);return h}function Xs(){if(0==(a[1312714]|0)){var b=pt();0!=(b-1&b|0)&&P();a[1312716]=b;a[1312715]=b;a[1312717]=-1;a[1312718]=2097152;a[1312719]=0;a[1344829]=0;var b=a,c=Math.floor(Date.now()/1e3);b[1312714]=c&-16^1431655768}}function Ys(b,c,d){var e,f,h,j=c>>2,i=b>>2,n=0,q=b+8|0,q=0==(q&7|0)?0:-q&7;f=c+8|0;var m=0==(f&7|0)?0:-f&7;h=m>>2;var w=c+m|0,x=q+d|0;f=x>>2;var x=b+x|0,v=w-(b+q)-d|0;a[(q+4>>2)+i]=d|3;if((w|0)==(a[1344725]|0)){return n=a[1344722]+v|0,a[1344722]=n,a[1344725]=x,a[f+(i+1)]=n|1,b=b+(q|8)|0}if((w|0)==(a[1344724]|0)){return n=a[1344721]+v|0,a[1344721]=n,a[1344724]=x,a[f+(i+1)]=n|1,a[(n>>2)+i+f]=n,b=b+(q|8)|0}var t=a[h+(j+1)];if(1==(t&3|0)){var d=t&-8,y=t>>>3;a:do{if(256>t>>>0){var z=a[((m|8)>>2)+j],A=a[h+(j+3)];if((z|0)==(A|0)){a[1344719]&=1<<y^-1}else{var C=((t>>>2&1073741822)<<2)+5378916|0;(z|0)!=(C|0)&&z>>>0<a[1344723]>>>0&&P();(A|0)!=(C|0)&&A>>>0<a[1344723]>>>0&&P();a[z+12>>2]=A;a[A+8>>2]=z}}else{z=w;A=a[((m|24)>>2)+j];C=a[h+(j+3)];b:do{if((C|0)==(z|0)){var D=m|16,E=D+(c+4)|0,G=a[E>>2];do{if(0==(G|0)){var H=c+D|0,I=a[H>>2];if(0==(I|0)){var J=0;e=J>>2;break b}}else{H=E,I=G}}while(0);for(;;){if(D=I+20|0,E=a[D>>2],0!=(E|0)){H=D,I=E}else{if(D=I+16|0,E=a[D>>2],0==(E|0)){break}else{H=D,I=E}}}H>>>0<a[1344723]>>>0?P():(a[H>>2]=0,J=I,e=J>>2)}else{H=a[((m|8)>>2)+j],H>>>0<a[1344723]>>>0?P():(a[H+12>>2]=C,a[C+8>>2]=H,J=C,e=J>>2)}}while(0);if(0!=(A|0)){C=m+(c+28)|0;H=(a[C>>2]<<2)+5379180|0;do{if((z|0)==(a[H>>2]|0)){if(a[H>>2]=J,0==(J|0)){a[1344720]&=1<<a[C>>2]^-1;break a}}else{if(A>>>0<a[1344723]>>>0&&P(),I=A+16|0,(a[I>>2]|0)==(z|0)?a[I>>2]=J:a[A+20>>2]=J,0==(J|0)){break a}}}while(0);J>>>0<a[1344723]>>>0&&P();a[e+6]=A;z=m|16;A=a[(z>>2)+j];0!=(A|0)&&(A>>>0<a[1344723]>>>0?P():(a[e+4]=A,a[A+24>>2]=J));z=a[(z+4>>2)+j];0!=(z|0)&&(z>>>0<a[1344723]>>>0?P():(a[e+5]=z,a[z+24>>2]=J))}}}while(0);e=c+(d|m)|0;c=d+v|0}else{e=w,c=v}e=e+4|0;a[e>>2]&=-2;a[f+(i+1)]=c|1;a[(c>>2)+i+f]=c;if(256>c>>>0){var N=c>>>2&1073741822,n=(N<<2)+5378916|0;e=a[1344719];c=1<<(c>>>3);if(0==(e&c|0)){a[1344719]=e|c;var K=n,M=(N+2<<2)+5378916|0}else{N=(N+2<<2)+5378916|0,c=a[N>>2],c>>>0<a[1344723]>>>0?P():(K=c,M=N)}a[M>>2]=x;a[K+12>>2]=x;a[f+(i+2)]=K;a[f+(i+3)]=n;return b=b+(q|8)|0}M=c>>>8;0==(M|0)?M=0:16777215<c>>>0?M=31:(K=(M+1048320|0)>>>16&8,e=M<<K,M=(e+520192|0)>>>16&4,e<<=M,j=(e+245760|0)>>>16&2,K=14-(M|K|j)+(e<<j>>>15)|0,M=c>>>((K+7|0)>>>0)&1|K<<1);K=(M<<2)+5379180|0;a[f+(i+7)]=M;a[f+(i+5)]=0;a[f+(i+4)]=0;e=a[1344720];j=1<<M;if(0==(e&j|0)){return a[1344720]=e|j,a[K>>2]=x,a[f+(i+6)]=K,a[f+(i+3)]=x,a[f+(i+2)]=x,b=b+(q|8)|0}M=c<<(31==(M|0)?0:25-(M>>>1)|0);for(K=a[K>>2];(a[K+4>>2]&-8|0)!=(c|0);){if(N=(M>>>31<<2)+K+16|0,e=a[N>>2],0==(e|0)){n=1714;break}else{M<<=1,K=e}}if(1714==n){return N>>>0<a[1344723]>>>0&&P(),a[N>>2]=x,a[f+(i+6)]=K,a[f+(i+3)]=x,a[f+(i+2)]=x,b=b+(q|8)|0}n=K+8|0;N=a[n>>2];M=a[1344723];K>>>0<M>>>0&&P();N>>>0<M>>>0&&P();a[N+12>>2]=x;a[n>>2]=x;a[f+(i+2)]=N;a[f+(i+3)]=K;a[f+(i+6)]=0;return b=b+(q|8)|0}function Zs(b,c){var d,e,f=0,h=a[1344725];e=h>>2;var i=Zl(h),k=a[i>>2];d=a[i+4>>2];var i=k+d|0,n=k+(d-39)|0,k=k+(d-47)+(0==(n&7|0)?0:-n&7)|0,k=k>>>0<(h+16|0)>>>0?h:k,n=k+8|0;d=n>>2;Ji(b,c-40|0);a[k+4>>2]=27;a[d]=a[1344830];a[d+1]=a[1344831];a[d+2]=a[1344832];a[d+3]=a[1344833];a[1344830]=b;a[1344831]=c;a[1344833]=0;a[1344832]=n;d=k+28|0;a[d>>2]=7;a:do{if((k+32|0)>>>0<i>>>0){for(n=d;;){var q=n+4|0;a[q>>2]=7;if((n+8|0)>>>0<i>>>0){n=q}else{break a}}}}while(0);if((k|0)!=(h|0)){if(i=k-h|0,k=i+(h+4)|0,a[k>>2]&=-2,a[e+1]=i|1,a[h+i>>2]=i,256>i>>>0){var m=i>>>2&1073741822,f=(m<<2)+5378916|0,k=a[1344719],i=1<<(i>>>3);if(0==(k&i|0)){a[1344719]=k|i;var w=f,x=(m+2<<2)+5378916|0}else{m=(m+2<<2)+5378916|0,i=a[m>>2],i>>>0<a[1344723]>>>0?P():(w=i,x=m)}a[x>>2]=h;a[w+12>>2]=h;a[e+2]=w;a[e+3]=f}else{if(x=i>>>8,0==(x|0)?x=0:16777215<i>>>0?x=31:(w=(x+1048320|0)>>>16&8,k=x<<w,x=(k+520192|0)>>>16&4,k<<=x,d=(k+245760|0)>>>16&2,w=14-(x|w|d)+(k<<d>>>15)|0,x=i>>>((w+7|0)>>>0)&1|w<<1),w=(x<<2)+5379180|0,a[e+7]=x,a[e+5]=0,a[e+4]=0,k=a[1344720],d=1<<x,0==(k&d|0)){a[1344720]=k|d,a[w>>2]=h,a[e+6]=w,a[e+3]=h,a[e+2]=h}else{x=i<<(31==(x|0)?0:25-(x>>>1)|0);for(w=a[w>>2];(a[w+4>>2]&-8|0)!=(i|0);){if(m=(x>>>31<<2)+w+16|0,k=a[m>>2],0==(k|0)){f=1753;break}else{x<<=1,w=k}}1753==f?(m>>>0<a[1344723]>>>0&&P(),a[m>>2]=h,a[e+6]=w,a[e+3]=h,a[e+2]=h):(f=w+8|0,m=a[f>>2],x=a[1344723],w>>>0<x>>>0&&P(),m>>>0<x>>>0&&P(),a[m+12>>2]=h,a[f>>2]=h,a[e+2]=m,a[e+3]=w,a[e+6]=0)}}}}function Pi(a){function b(){var c=0;hm=qc;H._main&&(wh(bt),c=H.Pa(a),H.noExitRuntime||wh(Si));if(H.postRun){for("function"==typeof H.postRun&&(H.postRun=[H.postRun]);0<H.postRun.length;){H.postRun.pop()()}}return c}a=a||H.arguments;if(0<ff){return H.o("run() called, but dependencies remain, so not running"),0}if(H.preRun){"function"==typeof H.preRun&&(H.preRun=[H.preRun]);var c=H.preRun;H.preRun=[];for(var d=c.length-1;0<=d;d--){c[d]()}if(0<ff){return 0}}return H.setStatus?(H.setStatus("Running..."),setTimeout((function(){setTimeout((function(){H.setStatus("")}),1);b()}),1),0):b()}var H={"return":"",print:(function(a){H["return"]+=a+"\n"})};try{this.Module=H}catch(Bt){this.Module=H={}}var $l="object"===typeof process&&"function"===typeof require,Ki="object"===typeof window,mg="function"===typeof importScripts,ct=!Ki&&!$l&&!mg;if($l){H.print=(function(a){process.stdout.write(a+"\n")});H.printErr=(function(a){process.stderr.write(a+"\n")});var dt=require("fs"),et=require("path");H.read=(function(a){var a=et.normalize(a),b=dt.readFileSync(a).toString();!b&&a!=et.resolve(a)&&(a=path.join(__dirname,"..","src",a),b=dt.readFileSync(a).toString());return b});H.load=(function(a){am(read(a))});H.arguments||(H.arguments=process.argv.slice(2))}ct&&(H.print=print,"undefined"!=typeof printErr&&(H.printErr=printErr),H.read="undefined"!=typeof read?read:(function(a){snarf(a)}),H.arguments||("undefined"!=typeof scriptArgs?H.arguments=scriptArgs:"undefined"!=typeof arguments&&(H.arguments=arguments)));Ki&&!mg&&(H.print||(H.print=(function(a){console.log(a)})),H.printErr||(H.printErr=(function(a){console.log(a)})));if(Ki||mg){H.read=(function(a){var b=new XMLHttpRequest;b.open("GET",a,Ud);b.send(Ac);return b.responseText}),H.arguments||"undefined"!=typeof arguments&&(H.arguments=arguments)}mg&&(H.print||(H.print=ng()),H.load=importScripts);!mg&&!Ki&&!$l&&!ct&&Ob("Unknown runtime environment. Where are we?");"undefined"==!H.load&&H.read&&(H.load=(function(a){am(H.read(a))}));H.print||(H.print=ng());H.printErr||(H.printErr=H.print);H.arguments||(H.arguments=[]);H.print=H.print;H.o=H.printErr;H.preRun||(H.preRun=[]);H.postRun||(H.postRun=[]);var fa={na:(function(){return h}),Ha:(function(a){h=a}),kd:(function(a,b){b=b||4;if(1==b){return a}if(isNumber(a)&&isNumber(b)){return Math.ceil(a/b)*b}if(isNumber(b)&&isPowerOfTwo(b)){var c=log2(b);return"(((("+a+")+"+(b-1)+")>>"+c+")<<"+c+")"}return"Math.ceil(("+a+")/"+b+")*"+b}),Za:(function(a){return a in fa.Ma||a in fa.La}),$a:(function(a){return"*"==a[a.length-1]}),bb:(function(a){return isPointerType(a)?Ud:/^\[\d+\ x\ (.*)\]/.test(a)||/<?{ ?[^}]* ?}>?/.test(a)?qc:"%"==a[0]}),Ma:{i1:0,i8:0,i16:0,i32:0,i64:0},La:{"float":0,"double":0},Q:0,O:1,P:2,Zc:(function(c,d,f,e){var h,i=Math.pow(2,e)-1;if(32>e){switch(f){case fa.Q:h=[c<<e,d<<e|(c&i<<32-e)>>>32-e];break;case fa.O:h=[(c>>>e|(d&i)<<32-e)>>0>>>0,d>>e>>>0];break;case fa.P:h=[(c>>>e|(d&i)<<32-e)>>>0,d>>>e]}}else{if(32==e){switch(f){case fa.Q:h=[0,c];break;case fa.O:h=[d,0>(d|0)?i:0];break;case fa.P:h=[d,0]}}else{switch(f){case fa.Q:h=[0,c<<e-32];break;case fa.O:h=[d>>e-32>>>0,0>(d|0)?i:0];break;case fa.P:h=[d>>>e-32,0]}}}a[b>>2]=h[0];a[b+4>>2]=h[1]}),sd:(function(a,b){return(a|0|b|0)+4294967296*(Math.round(a/4294967296)|Math.round(b/4294967296))}),Yc:(function(a,b){return((a|0)&(b|0))+4294967296*(Math.round(a/4294967296)&Math.round(b/4294967296))}),Gd:(function(a,b){return((a|0)^(b|0))+4294967296*(Math.round(a/4294967296)^Math.round(b/4294967296))}),ea:(function(a){if(1==fa.z){return 1}var b={"%i1":1,"%i8":1,"%i16":2,"%i32":4,"%i64":8,"%float":4,"%double":8}["%"+a];b||("*"==a.charAt(a.length-1)?b=fa.z:"i"==a[0]&&(a=parseInt(a.substr(1)),Nc(0==a%8),b=a/8));return b}),I:(function(a){return Math.max(fa.ea(a),fa.z)}),Ua:(function(a,b){var c={};return b?a.filter((function(a){return c[a[b]]?Ud:c[a[b]]=qc})):a.filter((function(a){return c[a]?Ud:c[a]=qc}))}),set:(function(){for(var a="object"===typeof arguments[0]?arguments[0]:arguments,b={},c=0;c<a.length;c++){b[a[c]]=0}return b}),Oa:(function(a){a.n=0;a.B=0;var b=[],c=-1;a.Aa=a.aa.map((function(d){var f,h;fa.Za(d)||fa.$a(d)?h=f=fa.ea(d):fa.bb(d)?(f=Types.types[d].n,h=Types.types[d].B):"b"==d[0]?(f=d.substr(1)|0,h=1):Ob("Unclear type in struct: "+d+", in "+a.gb+" :: "+dump(Types.types[a.gb]));h=a.td?1:Math.min(h,fa.z);a.B=Math.max(a.B,h);d=fa.A(a.n,h);a.n=d+f;0<=c&&b.push(d-c);return c=d}));a.n=fa.A(a.n,a.B);0==b.length?a.za=a.n:1==fa.Ua(b).length&&(a.za=b[0]);a.pd=1!=a.za;return a.Aa}),Xa:(function(a,b,c){var d,f;if(b){c=c||0;d=("undefined"===typeof Types?fa.Dd:Types.types)[b];if(!d){return Ac}if(d.aa.length!=a.length){return printErr("Number of named fields must match the type for "+b+": possibly duplicate struct names. Cannot return structInfo"),Ac}f=d.Aa}else{d={aa:a.map((function(a){return a[0]}))},f=fa.Oa(d)}var h={V:d.n};b?a.forEach((function(a,b){if("string"===typeof a){h[a]=f[b]+c}else{var i,s;for(s in a){i=s}h[i]=fa.Xa(a[i],d.aa[b],f[b])}})):a.forEach((function(a,b){h[a[1]]=f[b]}));return h}),t:(function(a,b,c){return c&&c.length?J[b].apply(Ac,c):J[b]()}),Xc:(function(a){var b=J,c=b.length;b.push(a);b.push(0);return c}),w:(function(a){fa.w.ka||(fa.w.ka={});fa.w.ka[a]||(fa.w.ka[a]=1,H.o(a))}),da:{},ld:(function(a,b){Nc(b);fa.da[a]||(fa.da[a]=(function(){fa.t(b,a,arguments)}));return fa.da[a]}),U:(function(){var a=[],b=0;this.Da=(function(c){c&=255;b&&(a.push(c),b--);if(0==a.length){if(128>c){return String.fromCharCode(c)}a.push(c);b=191<c&&224>c?1:2;return""}if(0<b){return""}var c=a[0],d=a[1],f=a[2],c=191<c&&224>c?String.fromCharCode((c&31)<<6|d&63):String.fromCharCode((c&15)<<12|(d&63)<<6|f&63);a.length=0;return c});this.jb=(function(a){for(var a=unescape(encodeURIComponent(a)),b=[],c=0;c<a.length;c++){b.push(a.charCodeAt(c))}return b})}),ma:(function(a){var b=h;h=h+a|0;h=h+3>>2<<2;return b}),oa:(function(a){var b=kd;kd=kd+a|0;kd=kd+3>>2<<2;kd>=sg&&og("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.");return b}),A:(function(a,b){return Math.ceil(a/(b?b:4))*(b?b:4)}),eb:(function(a,b,c){return c?(a>>>0)+4294967296*(b>>>0):(a>>>0)+4294967296*(b|0)}),z:4,Wc:0},i,Ib,Cf,jt=this;H.ccall=(function(a,b,c,d){return cm(bm(a),b,c,d)});H.cwrap=(function(a,b,c){var d=bm(a);return(function(){return cm(d,b,c,Array.prototype.slice.call(arguments))})});H.setValue=pg;H.getValue=Df;var Qi=0,ce=1,qe=2,c=3;H.ALLOC_NORMAL=Qi;H.ALLOC_STACK=ce;H.ALLOC_STATIC=qe;H.ALLOC_NONE=c;Ef=(function(a,b,c){for(c=a+c;a<c;){n[a++|0]=b}});H.allocate=d;H.Pointer_stringify=Vd;H.Array_stringify=(function(a){for(var b="",c=0;c<a.length;c++){b+=String.fromCharCode(a[c])}return b});var qt=4096,n,ca,C,fc,a,ft,hb,f,h,Li,kd,gt=H.TOTAL_STACK||5242880,sg=H.TOTAL_MEMORY||16777216;Nc(!!Int32Array&&!!Float64Array&&!!(new Int32Array(1)).subarray&&!!(new Int32Array(1)).set,"Cannot fallback to non-typed array case: Code is too specialized");var Ye=new ArrayBuffer(sg);n=new Int8Array(Ye);C=new Int16Array(Ye);a=new Int32Array(Ye);ca=new Uint8Array(Ye);fc=new Uint16Array(Ye);ft=new Uint32Array(Ye);hb=new Float32Array(Ye);f=new Float64Array(Ye);a[0]=255;Nc(255===ca[0]&&0===ca[3],"Typed arrays 2 must be run on a little-endian system");H.HEAP=Wb;H.HEAP8=n;H.HEAP16=C;H.HEAP32=a;H.HEAPU8=ca;H.HEAPU16=fc;H.HEAPU32=ft;H.HEAPF32=hb;H.HEAPF64=f;h=fa.A(1);Li=gt;var b=fa.A(d(12,"i8",ce),8);Nc(0==b%8);kd=Li;Nc(kd<sg);var lt=d(Od("(null)"),"i8",ce),ht=[],bt=[],Si=[];H.intArrayFromString=Od;H.intArrayToString=(function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c];255<d&&(d&=255);b.push(String.fromCharCode(d))}return b.join("")});H.writeStringToMemory=dm;H.writeArrayToMemory=em;Math.a||(Math.a=(function(a,b){var c=a&65535,d=b&65535;return c*d+((a>>>16)*d+c*(b>>>16)<<16)|0}));var ff=0,qg={},hm=Ud,rg=Ac;H.addRunDependency=Ni;H.removeRunDependency=xh;H.preloadedImages={};H.preloadedAudios={};Nc(kd==Li);Nc(Li==gt);kd+=139788;Nc(kd<sg);var Fe,Qa;d(4,"i8",c,5242880);d(4,"i8",c,5242884);d(4,"i8",c,5242888);d(4,"i8",c,5242892);d([0,0,0,0,0,0,0,0,258,0,0,0,172,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252,0,0,0,0,0,0,0,276,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,294,0,0,0,0,0,0,0,240,0,0,0,234,0,0,0,318,0,0,0,144,0,0,0,0,0,0,0,0,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5242896);d(4,"i8",c,5243016);d(48,"i8",c,5243020);d(128,"i8",c,5243068);d(64,"i8",c,5243196);d([102,0,0,0,0,0,0,0,110,0,0,0,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,208,0,0,0,174,0,0,0,0,0,0,0,0,0,0,0,270,0,0,0,0,0,0,0,116,0,0,0,162,0,0,0,62,0,0,0,118,0,0,0,8,0,0,0,0,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5243260);d(4,"i8",c,5243380);d(4,"i8",c,5243384);d(4,"i8",c,5243388);d(4,"i8",c,5243392);d(36,"i8",c,5243396);d([16,0,0,0,0,0,0,0,192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,316,0,0,0,0,0,0,0,74,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,0,0,0,0,0,0,0,290,0,0,0,288,0,0,0,230,0,0,0,130,0,0,0,68,0,0,0,0,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5243432);d([0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,37,117,2,154,8,27,218,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,44,212,154,230,29,167,234,63,106,222,113,138,142,228,232,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,224,63,93,220,70,3,120,11,226,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,208,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,93,220,70,3,120,11,226,63,93,220,70,3,120,11,226,63,93,220,70,3,120,11,226,63,13,113,172,139,219,104,220,63,100,93,220,70,3,120,237,63,210,111,95,7,206,25,231,63,16,122,54,171,62,87,229,63,16,122,54,171,62,87,229,63,210,111,95,7,206,25,231,63,120,11,36,40,126,140,227,63,181,21,251,203,238,201,225,63,210,111,95,7,206,25,231,63,210,111,95,7,206,25,231,63,88,168,53,205,59,78,213,63,136,133,90,211,188,227,216,63,210,111,95,7,206,25,231,63,120,11,36,40,126,140,227,63,196,66,173,105,222,113,236,63,210,111,95,7,206,25,231,63,210,111,95,7,206,25,231,63,181,21,251,203,238,201,225,63,210,111,95,7,206,25,231,63,16,122,54,171,62,87,229,63,181,21,251,203,238,201,225,63,120,11,36,40,126,140,227,63,210,111,95,7,206,25,231,63,210,111,95,7,206,25,231,63,134,56,214,197,109,52,238,63,210,111,95,7,206,25,231,63,210,111,95,7,206,25,231,63,120,11,36,40,126,140,227,63,88,168,53,205,59,78,213,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,166,10,70,37,117,2,222,63,0,0,0,0,0,0,224,63,88,168,53,205,59,78,213,63,13,113,172,139,219,104,220,63,0,0,0,0,0,0,224,63,13,113,172,139,219,104,220,63,0,0,0,0,0,0,224,63,13,113,172,139,219,104,220,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,224,63,211,188,227,20,29,201,209,63,106,222,113,138,142,228,232,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,88,168,53,205,59,78,213,63,136,133,90,211,188,227,216,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,210,111,95,7,206,25,231,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,13,113,172,139,219,104,220,63,244,108,86,125,174,182,222,63,17,54,60,189,82,150,201,63,244,108,86,125,174,182,222,63,59,1,77,132,13,79,225,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,62,232,217,172,250,92,197,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,130,115,70,148,246,6,199,63,13,113,172,139,219,104,220,63,0,0,0,0,0,0,224,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,7,240,22,72,80,252,220,63,162,180,55,248,194,100,214,63,88,168,53,205,59,78,213,63,13,113,172,139,219,104,220,63,13,113,172,139,219,104,220,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,208,63,13,113,172,139,219,104,220,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,208,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,196,66,173,105,222,113,236,63,0,0,0,0,0,0,208,63,127,217,61,121,88,168,209,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,120,11,36,40,126,140,227,63,210,111,95,7,206,25,231,63,196,66,173,105,222,113,236,63,19,242,65,207,102,213,211,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,16,122,54,171,62,87,229,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,224,63,210,111,95,7,206,25,231,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63,0,0,0,0,0,0,208,63],"i8",c,5243552);d([1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,2,0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,4,0,0,0],"i8",c,5245600);d(588,"i8",c,5245636);d([70,0,0,0,0,0,0,0,132,0,0,0,202,0,0,0,214,0,0,0,24,0,0,0,142,0,0,0,146,0,0,0,40,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,0,0,0,256,0,0,0,310,0,0,0,342,0,0,0,20,0,0,0,314,0,0,0,0,0,0,0,0,0,0,0,60,0,0,0,0,0,0,0,236,0,0,0,124,0,0,0,210,0,0,0,66,0,0,0,332,0,0,0,0,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5246224);d(4,"i8",c,5246344);d([0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,278,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],["i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5246348);d(4,"i8",c,5246384);d(4,"i8",c,5246388);d(4,"i8",c,5246392);d(4,"i8",c,5246396);d([148,0,0,0,250,0,0,0,0,0,0,0],["*",0,0,0,"*",0,0,0,"i8","i8","i8","i8"],c,5246400);d(4,"i8",c,5246412);d(4,"i8",c,5246416);d(8,"i8",c,5246420);d(4,"i8",c,5246428);d(8,"i8",c,5246432);d([0,32,193,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0],"i8",c,5246440);d([0,176,193,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,1,0,0,0],"i8",c,5246464);d([0,16,0,2,0,0,0,0,0,0,16,64,0,0,0,0,0,0,0,0,5,0,0,0],"i8",c,5246488);d([0,176,193,0,0,0,0,0,0,0,16,64,0,0,0,0,147,0,0,0,1,0,0,0],"i8",c,5246512);d([0,32,3,2,0,0,0,0,0,0,16,64,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5246536);d([4,144,195,0,0,0,0,0,0,0,16,64,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5246560);d([2,16,0,0,0,0,0,0,0,0,16,64,0,0,0,0,8,0,0,0,1,0,0,0],"i8",c,5246584);d([0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0],"i8",c,5246608);d([52,0,0,0,206,0,0,0,358,0,0,0,296,0,0,0,312,0,0,0,328,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5246632);d(4,"i8",c,5246656);d(4,"i8",c,5246660);d(4,"i8",c,5246664);d(4,"i8",c,5246668);d(4,"i8",c,5246672);d(24,"i8",c,5246676);d([1,0,0,0,2,0,0,0,3,0,0,0,4,0,0,0,5,0,0,0,0,0,0,0],"i8",c,5246700);d([186,0,0,0,86,0,0,0,42,0,0,0,0,0,0,0,340,0,0,0,0,0,0,0,154,0,0,0,30,0,0,0,200,0,0,0,246,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,158,0,0,0,2,0,0,0,46,0,0,0,152,0,0,0,164,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,156,0,0,0,0,0,0,0,126,0,0,0,92,0,0,0,100,0,0,0,128,0,0,0,286,0,0,0,198,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5246724);d(16,"i8",c,5246844);d(688,"i8",c,5246860);d(16,"i8",c,5247548);d(4,"i8",c,5247564);d(4,"i8",c,5247568);d([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5247572);d(4,"i8",c,5248832);d(4,"i8",c,5248836);d(4,"i8",c,5248840);d(4,"i8",c,5248844);d(8,"i8",c,5248848);d(8,"i8",c,5248856);d(4,"i8",c,5248864);d(4,"i8",c,5248868);d(4,"i8",c,5248872);d(8,"i8",c,5248876);d(8,"i8",c,5248884);d(4,"i8",c,5248892);d(4,"i8",c,5248896);d([244,0,0,0,170,0,0,0,218,0,0,0,242,0,0,0,84,0,0,0,262,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5248900);d(12,"i8",c,5248924);d(8,"i8",c,5248936);d(4,"i8",c,5248944);d(4,"i8",c,5248948);d(4,"i8",c,5248952);d([50,0,0,0,170,0,0,0,218,0,0,0,336,0,0,0,0,0,0,0,28,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5248956);d(4,"i8",c,5248980);d(4,"i8",c,5248984);d(4,"i8",c,5248988);d(4,"i8",c,5248992);d([0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63],"i8",c,5248996);d(256,"i8",c,5249092);d(4,"i8",c,5249348);d(4,"i8",c,5249352);d([0,0,0,0,3,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249356);d([0,0,0,0,1,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249400);d([0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,154,153,153,153,153,153,217,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249444);d([0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0],"i8",c,5249488);d([1,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249532);d([0,0,0,0,1,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249576);d([0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249620);d([0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249664);d([0,0,0,0,1,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249708);d([0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,51,51,51,51,51,51,227,63,0,0,0,0,0,0,0,0],"i8",c,5249752);d([0,0,0,0,1,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249796);d([0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0],"i8",c,5249840);d([0,0,0,0,1,0,0,0,3,0,0,0,0,0,0,0,0,128,102,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249884);d([0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,128,102,64,154,153,153,153,153,153,217,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249928);d([0,0,0,0,1,0,0,0,5,0,0,0,0,0,0,0,0,128,102,64,123,20,174,71,225,122,228,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5249972);d([0,0,0,0,1,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,123,20,174,71,225,122,228,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5250016);d([0,0,0,0,1,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5250060);d([0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0],"i8",c,5250104);d([0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5250148);d([0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,51,51,51,51,51,51,211,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5250192);d([0,0,0,0,2,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5250236);d([1,0,0,0,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5250280);d([0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,128,70,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5250324);d([0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0],"i8",c,5250368);d([1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5250412);d([0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0],"i8",c,5250456);d([0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5250500);d([1,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0],"i8",c,5250544);d([0,0,0,0,1,0,0,0,4,0,0,0,0,0,0,0,0,128,70,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0],"i8",c,5250588);d([1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0],"i8",c,5250632);d(4,"i8",c,5250676);d(4,"i8",c,5250680);d(128,"i8",c,5250684);d(4,"i8",c,5250812);d(4,"i8",c,5250816);d(4,"i8",c,5250820);d(4,"i8",c,5250824);d(4,"i8",c,5250828);d(4,"i8",c,5250832);d(4,"i8",c,5250836);d(4,"i8",c,5250840);d(4,"i8",c,5250844);d(4,"i8",c,5250848);d(4,"i8",c,5250852);d(24,"i8",c,5250856);d(4,"i8",c,5250880);d(4,"i8",c,5250884);d([45,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,46,57,57,0],"i8",c,5250888);d(4,"i8",c,5250908);d(4,"i8",c,5250912);d([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,184,0,0,0,324,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,266,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5250916);d(4,"i8",c,5251036);d(4,"i8",c,5251040);d(4,"i8",c,5251044);d(4,"i8",c,5251048);d(4,"i8",c,5251052);d(4,"i8",c,5251056);d(4,"i8",c,5251060);d(4,"i8",c,5251064);d([0,0,0,0,8,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,9,0,0,0,0,0,0,0],"i8",c,5251068);d([1,208,209,210,211,212,213,214,215,216,217,0],"i8",c,5251196);d(4,"i8",c,5251208);d(4,"i8",c,5251212);d(4,"i8",c,5251216);d(4,"i8",c,5251220);d(4,"i8",c,5251224);d(4,"i8",c,5251228);d([0,0,0,0,0,0,0,0,1,0,0,0,124,1,80,0,0,14,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5251232);d([0,0,0,0,0,0,0,0,1,0,0,0,40,2,80,0,24,14,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5251272);d([0,0,0,0,0,0,0,0,1,0,0,0,16,13,80,0,48,14,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5251312);d([0,0,0,0,0,0,0,0,1,0,0,0,4,15,80,0,72,14,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5251352);d([1,0,0,0,0,0,0,0,1,0,0,0,100,31,80,0,96,14,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5251392);d([0,0,0,0,0,0,0,0,1,0,0,0,196,41,80,0,120,14,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5251432);d([0,0,0,0,0,0,0,0,1,0,0,0,144,56,80,0,144,14,80,0,4,0,0,0,0,0,0,0,1,0,0,0,16,0,80,0,232,13,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5251472);d(20,"i8",c,5251532);d(16,"i8",c,5251552);d(4,"i8",c,5251568);d(8,"i8",c,5251572);d(8,"i8",c,5251580);d([15,0,0,0,0,0,0,0,1,0,0,0,68,56,80,0,0,0,0,0,16,0,0,0,0,0,0,0,1,0,0,0,68,56,80,0,0,0,0,0,17,0,0,0,0,0,0,0,1,0,0,0,68,56,80,0,0,0,0,0,17,0,0,0,0,0,0,0,1,0,0,0,68,56,80,0,0,0,0,0,17,0,0,0,0,0,0,0,1,0,0,0,68,56,80,0,0,0,0,0,19,0,0,0,0,0,0,0,1,0,0,0,84,56,80,0,0,0,0,0,20,0,0,0,0,0,0,0,1,0,0,0,84,56,80,0,0,0,0,0,21,0,0,0,0,0,0,0,1,0,0,0,84,56,80,0,0,0,0,0,21,0,0,0,0,0,0,0,1,0,0,0,84,56,80,0,0,0,0,0,21,0,0,0,0,0,0,0,1,0,0,0,84,56,80,0,0,0,0,0,22,0,0,0,0,0,0,0,1,0,0,0,60,56,80,0,0,0,0,0,23,0,0,0,0,0,0,0,1,0,0,0,60,56,80,0,0,0,0,0,24,0,0,0,0,0,0,0,1,0,0,0,60,56,80,0,0,0,0,0,24,0,0,0,0,0,0,0,1,0,0,0,60,56,80,0,0,0,0,0,24,0,0,0,0,0,0,0,1,0,0,0,60,56,80,0,0,0,0,0,25,0,0,0,0,0,0,0,1,0,0,0,76,56,80,0,0,0,0,0,25,0,0,0,0,0,0,0,1,0,0,0,76,56,80,0,0,0,0,0,25,0,0,0,0,0,0,0,1,0,0,0,76,56,80,0,0,0,0,0,25,0,0,0,0,0,0,0,1,0,0,0,76,56,80,0,0,0,0,0,26,0,0,0,0,0,0,0,1,0,0,0,72,56,80,0,0,0,0,0,10,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,11,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,12,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,12,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,12,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,14,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,14,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,13,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,5,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,6,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,7,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,7,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,7,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,9,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,9,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,8,0,0,0,0,0,0,0,1,0,0,0,80,56,80,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,56,56,80,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,56,56,80,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,0,0,56,56,80,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,0,0,56,56,80,0,0,0,0,0,2,0,0,0,0,0,0,0,1,0,0,0,56,56,80,0,0,0,0,0,4,0,0,0,0,0,0,0,1,0,0,0,56,56,80,0,0,0,0,0,4,0,0,0,0,0,0,0,1,0,0,0,56,56,80,0,0,0,0,0,3,0,0,0,0,0,0,0,1,0,0,0,56,56,80,0,0,0,0,0,18,0,0,0,0,0,0,0,1,0,0,0,68,56,80,0,0,0,0,0,27,0,0,0,0,0,0,0,1,0,0,0,64,56,80,0,0,0,0,0,28,0,0,0,0,0,0,0,1,0,0,0,64,56,80,0,0,0,0,0,29,0,0,0,0,0,0,0,1,0,0,0,64,56,80,0,0,0,0,0,29,0,0,0,0,0,0,0,1,0,0,0,64,56,80,0,0,0,0,0,29,0,0,0,0,0,0,0,1,0,0,0,64,56,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5251588);d([0,0,0,0,0,0,0,0,0,0,0,0,136,56,80,0,132,56,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5252608);d([0,0,0,0,238,0,0,0,0,0,0,0,302,0,0,0,0,0,0,0,302,0,0,0,0,0,0,0,354,0,0,0,0,0,0,0,354,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,106,0,0,0,0,0,0,0,106,0,0,0,0,0,0,0,34,0,0,0,0,0,0,0,34,0,0,0,0,0,0,0,90,0,0,0,0,0,0,0,90,0,0,0,0,0,0,0,180,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5252648);d([0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,8,57,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5252760);d([0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,60,57,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5252800);d([0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,112,57,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5252840);d([0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,164,57,80,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,164,57,80,0,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,116,58,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5252880);d([1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,216,57,80,0,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,12,58,80,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,12,58,80,0,3,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,12,58,80,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,216,57,80,0,3,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,216,57,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5252960);d([0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,64,58,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5253100);d([0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,168,58,80,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,168,58,80,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,220,58,80,0,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,168,58,80,0,3,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,168,58,80,0,4,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,168,58,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5253140);d([58,0,0,0,120,0,0,0,272,0,0,0,356,0,0,0,282,0,0,0,150,0,0,0,322,0,0,0,348,0,0,0,224,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5253280);d(4,"i8",c,5253316);d(4,"i8",c,5253320);d(4,"i8",c,5253324);d(16,"i8",c,5253328);d([100,0,0,0,101,0,0,0,102,0,0,0,100,0,0,0],"i8",c,5253344);d(16,"i8",c,5253360);d([0,0,0,0,1,0,0,0,2,0,0,0,255,255,255,255],"i8",c,5253376);d(4,"i8",c,5253392);d(4,"i8",c,5253396);d(4,"i8",c,5253400);d(4,"i8",c,5253404);d(4,"i8",c,5253408);d(4,"i8",c,5253412);d(4,"i8",c,5253416);d([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],["i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5253420);d([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],["i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5253456);d(4,"i8",c,5253492);d(36,"i8",c,5253496);d(4,"i8",c,5253532);d(4,"i8",c,5253536);d(32,"i8",c,5253540);d([0,0,0,0,0,0,0,0,268,0,0,0,204,0,0,0,0,0,0,0,0,0,0,0,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,300,0,0,0,344,0,0,0,82,0,0,0,320,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,166,0,0,0,306,0,0,0,248,0,0,0,350,0,0,0,26,0,0,0,274,0,0,0,190,0,0,0,0,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5253572);d(4,"i8",c,5253692);d(512,"i8",c,5253696);d(512,"i8",c,5254208);d(512,"i8",c,5254720);d([0,0,0,0,0,0,0,0,218,0,0,0,48,0,0,0,0,0,0,0,32,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5255232);d([0,0,0,0,198,0,0,0,0,0,0,0,193,0,0,0,0,0,0,0,194,0,0,0,0,0,0,0,192,0,0,0,0,0,0,0,145,3,0,0,0,0,0,0,197,0,0,0,0,0,0,0,195,0,0,0,0,0,0,0,196,0,0,0,0,0,0,0,146,3,0,0,0,0,0,0,199,0,0,0,0,0,0,0,167,3,0,0,0,0,0,0,33,32,0,0,0,0,0,0,148,3,0,0,0,0,0,0,208,0,0,0,0,0,0,0,201,0,0,0,0,0,0,0,202,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,149,3,0,0,0,0,0,0,151,3,0,0,0,0,0,0,203,0,0,0,0,0,0,0,147,3,0,0,0,0,0,0,205,0,0,0,0,0,0,0,206,0,0,0,0,0,0,0,204,0,0,0,0,0,0,0,153,3,0,0,0,0,0,0,207,0,0,0,0,0,0,0,154,3,0,0,0,0,0,0,155,3,0,0,0,0,0,0,156,3,0,0,0,0,0,0,209,0,0,0,0,0,0,0,157,3,0,0,0,0,0,0,82,1,0,0,0,0,0,0,211,0,0,0,0,0,0,0,212,0,0,0,0,0,0,0,210,0,0,0,0,0,0,0,169,3,0,0,0,0,0,0,159,3,0,0,0,0,0,0,216,0,0,0,0,0,0,0,213,0,0,0,0,0,0,0,214,0,0,0,0,0,0,0,166,3,0,0,0,0,0,0,160,3,0,0,0,0,0,0,51,32,0,0,0,0,0,0,168,3,0,0,0,0,0,0,161,3,0,0,0,0,0,0,96,1,0,0,0,0,0,0,163,3,0,0,0,0,0,0,222,0,0,0,0,0,0,0,164,3,0,0,0,0,0,0,152,3,0,0,0,0,0,0,218,0,0,0,0,0,0,0,219,0,0,0,0,0,0,0,217,0,0,0,0,0,0,0,165,3,0,0,0,0,0,0,220,0,0,0,0,0,0,0,158,3,0,0,0,0,0,0,221,0,0,0,0,0,0,0,120,1,0,0,0,0,0,0,150,3,0,0,0,0,0,0,225,0,0,0,0,0,0,0,226,0,0,0,0,0,0,0,180,0,0,0,0,0,0,0,230,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,53,33,0,0,0,0,0,0,177,3,0,0,0,0,0,0,38,0,0,0,0,0,0,0,39,34,0,0,0,0,0,0,32,34,0,0,0,0,0,0,229,0,0,0,0,0,0,0,72,34,0,0,0,0,0,0,227,0,0,0,0,0,0,0,228,0,0,0,0,0,0,0,30,32,0,0,0,0,0,0,178,3,0,0,0,0,0,0,166,0,0,0,0,0,0,0,34,32,0,0,0,0,0,0,41,34,0,0,0,0,0,0,231,0,0,0,0,0,0,0,184,0,0,0,0,0,0,0,162,0,0,0,0,0,0,0,199,3,0,0,0,0,0,0,198,2,0,0,0,0,0,0,99,38,0,0,0,0,0,0,69,34,0,0,0,0,0,0,169,0,0,0,0,0,0,0,181,33,0,0,0,0,0,0,42,34,0,0,0,0,0,0,164,0,0,0,0,0,0,0,211,33,0,0,0,0,0,0,32,32,0,0,0,0,0,0,147,33,0,0,0,0,0,0,176,0,0,0,0,0,0,0,180,3,0,0,0,0,0,0,102,38,0,0,0,0,0,0,247,0,0,0,0,0,0,0,233,0,0,0,0,0,0,0,234,0,0,0,0,0,0,0,232,0,0,0,0,0,0,0,5,34,0,0,0,0,0,0,3,32,0,0,0,0,0,0,2,32,0,0,0,0,0,0,181,3,0,0,0,0,0,0,97,34,0,0,0,0,0,0,183,3,0,0,0,0,0,0,240,0,0,0,0,0,0,0,235,0,0,0,0,0,0,0,172,32,0,0,0,0,0,0,3,34,0,0,0,0,0,0,146,1,0,0,0,0,0,0,0,34,0,0,0,0,0,0,189,0,0,0,0,0,0,0,188,0,0,0,0,0,0,0,190,0,0,0,0,0,0,0,68,32,0,0,0,0,0,0,179,3,0,0,0,0,0,0,101,34,0,0,0,0,0,0,62,0,0,0,0,0,0,0,212,33,0,0,0,0,0,0,148,33,0,0,0,0,0,0,101,38,0,0,0,0,0,0,38,32,0,0,0,0,0,0,237,0,0,0,0,0,0,0,238,0,0,0,0,0,0,0,161,0,0,0,0,0,0,0,236,0,0,0,0,0,0,0,17,33,0,0,0,0,0,0,30,34,0,0,0,0,0,0,43,34,0,0,0,0,0,0,185,3,0,0,0,0,0,0,191,0,0,0,0,0,0,0,8,34,0,0,0,0,0,0,239,0,0,0,0,0,0,0,186,3,0,0,0,0,0,0,208,33,0,0,0,0,0,0,187,3,0,0,0,0,0,0,41,35,0,0,0,0,0,0,171,0,0,0,0,0,0,0,144,33,0,0,0,0,0,0,8,35,0,0,0,0,0,0,28,32,0,0,0,0,0,0,100,34,0,0,0,0,0,0,10,35,0,0,0,0,0,0,23,34,0,0,0,0,0,0,202,37,0,0,0,0,0,0,14,32,0,0,0,0,0,0,57,32,0,0,0,0,0,0,24,32,0,0,0,0,0,0,60,0,0,0,0,0,0,0,175,0,0,0,0,0,0,0,20,32,0,0,0,0,0,0,181,0,0,0,0,0,0,0,183,0,0,0,0,0,0,0,18,34,0,0,0,0,0,0,188,3,0,0,0,0,0,0,7,34,0,0,0,0,0,0,160,0,0,0,0,0,0,0,19,32,0,0,0,0,0,0,96,34,0,0,0,0,0,0,11,34,0,0,0,0,0,0,172,0,0,0,0,0,0,0,9,34,0,0,0,0,0,0,132,34,0,0,0,0,0,0,241,0,0,0,0,0,0,0,189,3,0,0,0,0,0,0,243,0,0,0,0,0,0,0,244,0,0,0,0,0,0,0,83,1,0,0,0,0,0,0,242,0,0,0,0,0,0,0,62,32,0,0,0,0,0,0,201,3,0,0,0,0,0,0,191,3,0,0,0,0,0,0,149,34,0,0,0,0,0,0,40,34,0,0,0,0,0,0,170,0,0,0,0,0,0,0,186,0,0,0,0,0,0,0,248,0,0,0,0,0,0,0,245,0,0,0,0,0,0,0,151,34,0,0,0,0,0,0,246,0,0,0,0,0,0,0,182,0,0,0,0,0,0,0,2,34,0,0,0,0,0,0,48,32,0,0,0,0,0,0,165,34,0,0,0,0,0,0,198,3,0,0,0,0,0,0,192,3,0,0,0,0,0,0,214,3,0,0,0,0,0,0,177,0,0,0,0,0,0,0,163,0,0,0,0,0,0,0,50,32,0,0,0,0,0,0,15,34,0,0,0,0,0,0,29,34,0,0,0,0,0,0,200,3,0,0,0,0,0,0,34,0,0,0,0,0,0,0,210,33,0,0,0,0,0,0,26,34,0,0,0,0,0,0,42,35,0,0,0,0,0,0,187,0,0,0,0,0,0,0,146,33,0,0,0,0,0,0,9,35,0,0,0,0,0,0,29,32,0,0,0,0,0,0,28,33,0,0,0,0,0,0,174,0,0,0,0,0,0,0,11,35,0,0,0,0,0,0,193,3,0,0,0,0,0,0,15,32,0,0,0,0,0,0,58,32,0,0,0,0,0,0,25,32,0,0,0,0,0,0,26,32,0,0,0,0,0,0,97,1,0,0,0,0,0,0,197,34,0,0,0,0,0,0,167,0,0,0,0,0,0,0,173,0,0,0,0,0,0,0,195,3,0,0,0,0,0,0,194,3,0,0,0,0,0,0,60,34,0,0,0,0,0,0,96,38,0,0,0,0,0,0,130,34,0,0,0,0,0,0,134,34,0,0,0,0,0,0,17,34,0,0,0,0,0,0,131,34,0,0,0,0,0,0,185,0,0,0,0,0,0,0,178,0,0,0,0,0,0,0,179,0,0,0,0,0,0,0,135,34,0,0,0,0,0,0,223,0,0,0,0,0,0,0,196,3,0,0,0,0,0,0,52,34,0,0,0,0,0,0,184,3,0,0,0,0,0,0,209,3,0,0,0,0,0,0,9,32,0,0,0,0,0,0,254,0,0,0,0,0,0,0,220,2,0,0,0,0,0,0,215,0,0,0,0,0,0,0,34,33,0,0,0,0,0,0,209,33,0,0,0,0,0,0,250,0,0,0,0,0,0,0,145,33,0,0,0,0,0,0,251,0,0,0,0,0,0,0,249,0,0,0,0,0,0,0,168,0,0,0,0,0,0,0,210,3,0,0,0,0,0,0,197,3,0,0,0,0,0,0,252,0,0,0,0,0,0,0,24,33,0,0,0,0,0,0,190,3,0,0,0,0,0,0,253,0,0,0,0,0,0,0,165,0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,182,3,0,0,0,0,0,0,13,32,0,0,0,0,0,0,12,32,0,0],"i8",c,5255256);d([108,0,0,0],["*",0,0,0],c,5257272);d([72,0,0,0],["*",0,0,0],c,5257276);d([96,0,0,0],["*",0,0,0],c,5257280);d([176,0,0,0],["*",0,0,0],c,5257284);d([194,0,0,0],["*",0,0,0],c,5257288);d([38,0,0,0],["*",0,0,0],c,5257292);d([216,0,0,0],["*",0,0,0],c,5257296);d([138,0,0,0],["*",0,0,0],c,5257300);d(8,"i8",c,5257304);d(4,"i8",c,5257312);d(4,"i8",c,5257316);d(4,"i8",c,5257320);d(4,"i8",c,5257324);d(4,"i8",c,5257328);d(4,"i8",c,5257332);d(4,"i8",c,5257336);d(4,"i8",c,5257340);d(4,"i8",c,5257344);d([1,0,0,0],"i8",c,5257348);d([134,0,0,0,182,0,0,0],["*",0,0,0,"*",0,0,0],c,5257352);d([0,0,0,0,0,0,0,0,258,0,0,0,172,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],["*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5257360);d([0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,64,0,0,0,0,0,0,88,64],"i8",c,5257480);d([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,64,0,0,0,0,0,0,88,64],"i8",c,5257532);d([0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,64,0,0,0,0,0,0,82,64],"i8",c,5257584);d([96,0,0,0,0,0,0,0,0,0,66,64,0,0,0,0,0,0,66,64,0,0,0,0,0,32,131,64,0,0,0,0,0,192,136,64,0,0,0,0,0,0,82,64,0,0,0,0,0,0,82,64],"i8",c,5257636);d([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,64,0,0,0,0,0,0,88,64],"i8",c,5257688);d([0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,64,0,0,0,0,0,0,88,64],"i8",c,5257740);d([2,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,150,64,0,0,0,0,0,128,150,64],"i8",c,5257792);d([0,0,0,0,0,0,0,0,0,0,66,64,0,0,0,0,0,0,66,64,0,0,0,0,0,32,131,64,0,0,0,0,0,192,136,64,0,0,0,0,0,0,82,64,0,0,0,0,0,0,82,64],"i8",c,5257844);d([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,64,0,0,0,0,0,0,82,64],"i8",c,5257896);d([0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,82,64,0,0,0,0,0,0,82,64],"i8",c,5257948);d(12,"i8",c,5258e3);d(4,"i8",c,5258012);d(4,"i8",c,5258016);d([81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63,81,218,27,124,97,50,227,63],"i8",c,5258020);d(4,"i8",c,5260068);d(4,"i8",c,5260072);d(4,"i8",c,5260076);d(4,"i8",c,5260080);d([0,0,0,0,85,93,-55,127,-55,127,-1,0,0,0,0,0,-69,45,-44,-66,-82,-44,-1,0,0,0,0,0,20,119,-3,-3,-64,-122,-1,0,0,0,0,0,85,93,-55,127,-55,127,-1,0,0,0,0,0,-69,45,-44,-66,-82,-44,-1,0,0,0,0,0,20,119,-3,-3,-64,-122,-1,0,0,0,0,0,42,102,-1,-1,-1,-103,-1,0,0,0,0,0,85,93,-55,127,-55,127,-1,0,0,0,0,0,-69,45,-44,-66,-82,-44,-1,0,0,0,0,0,20,119,-3,-3,-64,-122,-1,0,0,0,0,0,42,102,-1,-1,-1,-103,-1,0,0,0,0,0,-105,-83,-80,56,108,-80,-1,0,0,0,0,0,85,93,-55,127,-55,127,-1,0,0,0,0,0,-69,45,-44,-66,-82,-44,-1,0,0,0,0,0,20,119,-3,-3,-64,-122,-1,0,0,0,0,0,42,102,-1,-1,-1,-103,-1,0,0,0,0,0,-105,-83,-80,56,108,-80,-1,0,0,0,0,0,-24,-4,-16,-16,2,127,-1,0,0,0,0,0,85,93,-55,127,-55,127,-1,0,0,0,0,0,-69,45,-44,-66,-82,-44,-1,0,0,0,0,0,20,119,-3,-3,-64,-122,-1,0,0,0,0,0,42,102,-1,-1,-1,-103,-1,0,0,0,0,0,-105,-83,-80,56,108,-80,-1,0,0,0,0,0,-24,-4,-16,-16,2,127,-1,0,0,0,0,0,17,-32,-65,-65,91,23,-1,0,0,0,0,0,85,93,-55,127,-55,127,-1,0,0,0,0,0,-69,45,-44,-66,-82,-44,-1,0,0,0,0,0,20,119,-3,-3,-64,-122,-1,0,0,0,0,0,42,102,-1,-1,-1,-103,-1,0,0,0,0,0,-105,-83,-80,56,108,-80,-1,0,0,0,0,0,-24,-4,-16,-16,2,127,-1,0,0,0,0,0,17,-32,-65,-65,91,23,-1,0,0,0,0,0,0,0,102,102,102,102,-1,0,0,0,0,0,-109,25,-9,-34,-21,-9,-1,0,0,0,0,0,-114,75,-31,-98,-54,-31,-1,0,0,0,0,0,-111,-68,-67,49,-126,-67,-1,0,0,0,0,0,-97,16,-1,-17,-13,-1,-1,0,0,0,0,0,-113,46,-25,-67,-41,-25,-1,0,0,0,0,0,-113,127,-42,107,-82,-42,-1,0,0,0,0,0,-109,-48,-75,33,113,-75,-1,0,0,0,0,0,-97,16,-1,-17,-13,-1,-1,0,0,0,0,0,-113,46,-25,-67,-41,-25,-1,0,0,0,0,0,-113,127,-42,107,-82,-42,-1,0,0,0,0,0,-111,-68,-67,49,-126,-67,-1,0,0,0,0,0,-107,-15,-100,8,81,-100,-1,0,0,0,0,0,-97,16,-1,-17,-13,-1,-1,0,0,0,0,0,-108,43,-17,-58,-37,-17,-1,0,0,0,0,0,-114,75,-31,-98,-54,-31,-1,0,0,0,0,0,-113,127,-42,107,-82,-42,-1,0,0,0,0,0,-111,-68,-67,49,-126,-67,-1,0,0,0,0,0,-107,-15,-100,8,81,-100,-1,0,0,0,0,0,-97,16,-1,-17,-13,-1,-1,0,0,0,0,0,-108,43,-17,-58,-37,-17,-1,0,0,0,0,0,-114,75,-31,-98,-54,-31,-1,0,0,0,0,0,-113,127,-42,107,-82,-42,-1,0,0,0,0,0,-112,-87,-58,66,-110,-58,-1,0,0,0,0,0,-109,-48,-75,33,113,-75,-1,0,0,0,0,0,-105,-15,-108,8,69,-108,-1,0,0,0,0,0,-108,8,-1,-9,-5,-1,-1,0,0,0,0,0,-109,25,-9,-34,-21,-9,-1,0,0,0,0,0,-108,43,-17,-58,-37,-17,-1,0,0,0,0,0,-114,75,-31,-98,-54,-31,-1,0,0,0,0,0,-113,127,-42,107,-82,-42,-1,0,0,0,0,0,-112,-87,-58,66,-110,-58,-1,0,0,0,0,0,-109,-48,-75,33,113,-75,-1,0,0,0,0,0,-105,-15,-108,8,69,-108,-1,0,0,0,0,0,-108,8,-1,-9,-5,-1,-1,0,0,0,0,0,-109,25,-9,-34,-21,-9,-1,0,0,0,0,0,-108,43,-17,-58,-37,-17,-1,0,0,0,0,0,-114,75,-31,-98,-54,-31,-1,0,0,0,0,0,-113,127,-42,107,-82,-42,-1,0,0,0,0,0,-112,-87,-58,66,-110,-58,-1,0,0,0,0,0,-109,-48,-75,33,113,-75,-1,0,0,0,0,0,-107,-15,-100,8,81,-100,-1,0,0,0,0,0,-104,-21,107,8,48,107,-1,0,0,0,0,0,23,-17,84,84,48,5,-1,0,0,0,0,0,119,-1,60,0,60,48,-1,0,0,0,0,0,23,-20,-116,-116,81,10,-1,0,0,0,0,0,24,-62,-65,-65,-127,45,-1,0,0,0,0,0,29,112,-33,-33,-62,125,-1,0,0,0,0,0,30,52,-10,-10,-24,-61,-1,0,0,0,0,0,121,38,-22,-57,-22,-27,-1,0,0,0,0,0,120,95,-51,-128,-51,-63,-1,0,0,0,0,0,124,-91,-105,53,-105,-113,-1,0,0,0,0,0,124,-4,102,1,102,94,-1,0,0,0,0,0,23,-17,84,84,48,5,-1,0,0,0,0,0,124,-4,102,1,102,94,-1,0,0,0,0,0,119,-1,60,0,60,48,-1,0,0,0,0,0,23,-20,-116,-116,81,10,-1,0,0,0,0,0,24,-62,-65,-65,-127,45,-1,0,0,0,0,0,29,112,-33,-33,-62,125,-1,0,0,0,0,0,30,52,-10,-10,-24,-61,-1,0,0,0,0,0,0,0,-11,-11,-11,-11,-1,0,0,0,0,0,121,38,-22,-57,-22,-27,-1,0,0,0,0,0,120,95,-51,-128,-51,-63,-1,0,0,0,0,0,124,-91,-105,53,-105,-113,-1,0,0,0,0,0,28,-121,-40,-40,-77,101,-1,0,0,0,0,0,0,0,-11,-11,-11,-11,-1,0,0,0,0,0,123,127,-76,90,-76,-84,-1,0,0,0,0,0,21,-41,-90,-90,97,26,-1,0,0,0,0,0,29,112,-33,-33,-62,125,-1,0,0,0,0,0,120,95,-51,-128,-51,-63,-1,0,0,0,0,0,121,-3,-123,1,-123,113,-1,0,0,0,0,0,21,-41,-90,-90,97,26,-1,0,0,0,0,0,29,112,-33,-33,-62,125,-1,0,0,0,0,0,0,0,-11,-11,-11,-11,-1,0,0,0,0,0,120,95,-51,-128,-51,-63,-1,0,0,0,0,0,121,-3,-123,1,-123,113,-1,0,0,0,0,0,23,-20,-116,-116,81,10,-1,0,0,0,0,0,28,-121,-40,-40,-77,101,-1,0,0,0,0,0,30,52,-10,-10,-24,-61,-1,0,0,0,0,0,121,38,-22,-57,-22,-27,-1,0,0,0,0,0,123,127,-76,90,-76,-84,-1,0,0,0,0,0,124,-4,102,1,102,94,-1,0,0,0,0,0,23,-20,-116,-116,81,10,-1,0,0,0,0,0,28,-121,-40,-40,-77,101,-1,0,0,0,0,0,30,52,-10,-10,-24,-61,-1,0,0,0,0,0,0,0,-11,-11,-11,-11,-1,0,0,0,0,0,121,38,-22,-57,-22,-27,-1,0,0,0,0,0,123,127,-76,90,-76,-84,-1,0,0,0,0,0,124,-4,102,1,102,94,-1,0,0,0,0,0,23,-20,-116,-116,81,10,-1,0,0,0,0,0,24,-62,-65,-65,-127,45,-1,0,0,0,0,0,29,112,-33,-33,-62,125,-1,0,0,0,0,0,30,52,-10,-10,-24,-61,-1,0,0,0,0,0,121,38,-22,-57,-22,-27,-1,0,0,0,0,0,120,95,-51,-128,-51,-63,-1,0,0,0,0,0,124,-91,-105,53,-105,-113,-1,0,0,0,0,0,124,-4,102,1,102,94,-1,0,0,0,0,0,23,-20,-116,-116,81,10,-1,0,0,0,0,0,24,-62,-65,-65,-127,45,-1,0,0,0,0,0,29,112,-33,-33,-62,125,-1,0,0,0,0,0,30,52,-10,-10,-24,-61,-1,0,0,0,0,0,0,0,-11,-11,-11,-11,-1,0,0,0,0,0,121,38,-22,-57,-22,-27,-1,0,0,0,0,0,120,95,-51,-128,-51,-63,-1,0,0,0,0,0,124,-91,-105,53,-105,-113,-1,0,0,0,0,0,124,-4,102,1,102,94,-1,0,0,0,0,0,-121,20,-7,-27,-11,-7,-1,0,0,0,0,0,117,74,-40,-103,-40,-55,-1,0,0,0,0,0,103,-71,-94,44,-94,95,-1,0,0,0,0,0,-120,14,-5,-19,-8,-5,-1,0,0,0,0,0,127,54,-30,-78,-30,-30,-1,0,0,0,0,0,113,120,-62,102,-62,-92,-1,0,0,0,0,0,98,-66,-117,35,-117,69,-1,0,0,0,0,0,-120,14,-5,-19,-8,-5,-1,0,0,0,0,0,127,54,-30,-78,-30,-30,-1,0,0,0,0,0,113,120,-62,102,-62,-92,-1,0,0,0,0,0,103,-71,-94,44,-94,95,-1,0,0,0,0,0,102,-1,109,0,109,44,-1,0,0,0,0,0,-120,14,-5,-19,-8,-5,-1,0,0,0,0,0,119,34,-20,-52,-20,-26,-1,0,0,0,0,0,117,74,-40,-103,-40,-55,-1,0,0,0,0,0,113,120,-62,102,-62,-92,-1,0,0,0,0,0,103,-71,-94,44,-94,95,-1,0,0,0,0,0,102,-1,109,0,109,44,-1,0,0,0,0,0,-120,14,-5,-19,-8,-5,-1,0,0,0,0,0,119,34,-20,-52,-20,-26,-1,0,0,0,0,0,117,74,-40,-103,-40,-55,-1,0,0,0,0,0,113,120,-62,102,-62,-92,-1,0,0,0,0,0,105,-97,-82,65,-82,118,-1,0,0,0,0,0,98,-66,-117,35,-117,69,-1,0,0,0,0,0,102,-1,88,0,88,36,-1,0,0,0,0,0,-122,6,-3,-9,-4,-3,-1,0,0,0,0,0,-121,20,-7,-27,-11,-7,-1,0,0,0,0,0,119,34,-20,-52,-20,-26,-1,0,0,0,0,0,117,74,-40,-103,-40,-55,-1,0,0,0,0,0,113,120,-62,102,-62,-92,-1,0,0,0,0,0,105,-97,-82,65,-82,118,-1,0,0,0,0,0,98,-66,-117,35,-117,69,-1,0,0,0,0,0,102,-1,88,0,88,36,-1,0,0,0,0,0,-122,6,-3,-9,-4,-3,-1,0,0,0,0,0,-121,20,-7,-27,-11,-7,-1,0,0,0,0,0,119,34,-20,-52,-20,-26,-1,0,0,0,0,0,117,74,-40,-103,-40,-55,-1,0,0,0,0,0,113,120,-62,102,-62,-92,-1,0,0,0,0,0,105,-97,-82,65,-82,118,-1,0,0,0,0,0,98,-66,-117,35,-117,69,-1,0,0,0,0,0,102,-1,109,0,109,44,-1,0,0,0,0,0,101,-1,68,0,68,27,-1,0,0,0,0,0,-112,20,-12,-32,-20,-12,-1,0,0,0,0,0,-108,70,-38,-98,-68,-38,-1,0,0,0,0,0,-60,123,-89,-120,86,-89,-1,0,0,0,0,0,-120,14,-5,-19,-8,-5,-1,0,0,0,0,0,-110,53,-29,-77,-51,-29,-1,0,0,0,0,0,-94,74,-58,-116,-106,-58,-1,0,0,0,0,0,-54,-107,-99,-120,65,-99,-1,0,0,0,0,0,-120,14,-5,-19,-8,-5,-1,0,0,0,0,0,-110,53,-29,-77,-51,-29,-1,0,0,0,0,0,-94,74,-58,-116,-106,-58,-1,0,0,0,0,0,-60,123,-89,-120,86,-89,-1,0,0,0,0,0,-42,-31,-127,-127,15,124,-1,0,0,0,0,0,-120,14,-5,-19,-8,-5,-1,0,0,0,0,0,-108,43,-26,-65,-45,-26,-1,0,0,0,0,0,-108,70,-38,-98,-68,-38,-1,0,0,0,0,0,-94,74,-58,-116,-106,-58,-1,0,0,0,0,0,-60,123,-89,-120,86,-89,-1,0,0,0,0,0,-42,-31,-127,-127,15,124,-1,0,0,0,0,0,-120,14,-5,-19,-8,-5,-1,0,0,0,0,0,-108,43,-26,-65,-45,-26,-1,0,0,0,0,0,-108,70,-38,-98,-68,-38,-1,0,0,0,0,0,-94,74,-58,-116,-106,-58,-1,0,0,0,0,0,-66,100,-79,-116,107,-79,-1,0,0,0,0,0,-54,-107,-99,-120,65,-99,-1,0,0,0,0,0,-43,-4,110,110,1,107,-1,0,0,0,0,0,-122,6,-3,-9,-4,-3,-1,0,0,0,0,0,-112,20,-12,-32,-20,-12,-1,0,0,0,0,0,-108,43,-26,-65,-45,-26,-1,0,0,0,0,0,-108,70,-38,-98,-68,-38,-1,0,0,0,0,0,-94,74,-58,-116,-106,-58,-1,0,0,0,0,0,-66,100,-79,-116,107,-79,-1,0,0,0,0,0,-54,-107,-99,-120,65,-99,-1,0,0,0,0,0,-43,-4,110,110,1,107,-1,0,0,0,0,0,-122,6,-3,-9,-4,-3,-1,0,0,0,0,0,-112,20,-12,-32,-20,-12,-1,0,0,0,0,0,-108,43,-26,-65,-45,-26,-1,0,0,0,0,0,-108,70,-38,-98,-68,-38,-1,0,0,0,0,0,-94,74,-58,-116,-106,-58,-1,0,0,0,0,0,-66,100,-79,-116,107,-79,-1,0,0,0,0,0,-54,-107,-99,-120,65,-99,-1,0,0,0,0,0,-42,-31,-127,-127,15,124,-1,0,0,0,0,0,-43,-1,77,77,0,75,-1,0,0,0,0,0,114,-45,-98,27,-98,119,-1,0,0,0,0,0,18,-4,-39,-39,95,2,-1,0,0,0,0,0,-83,95,-77,117,112,-77,-1,0,0,0,0,0,114,-45,-98,27,-98,119,-1,0,0,0,0,0,18,-4,-39,-39,95,2,-1,0,0,0,0,0,-83,95,-77,117,112,-77,-1,0,0,0,0,0,-23,-47,-25,-25,41,-118,-1,0,0,0,0,0,114,-45,-98,27,-98,119,-1,0,0,0,0,0,18,-4,-39,-39,95,2,-1,0,0,0,0,0,-83,95,-77,117,112,-77,-1,0,0,0,0,0,-23,-47,-25,-25,41,-118,-1,0,0,0,0,0,62,-48,-90,102,-90,30,-1,0,0,0,0,0,114,-45,-98,27,-98,119,-1,0,0,0,0,0,18,-4,-39,-39,95,2,-1,0,0,0,0,0,-83,95,-77,117,112,-77,-1,0,0,0,0,0,-23,-47,-25,-25,41,-118,-1,0,0,0,0,0,62,-48,-90,102,-90,30,-1,0,0,0,0,0,31,-4,-26,-26,-85,2,-1,0,0,0,0,0,114,-45,-98,27,-98,119,-1,0,0,0,0,0,18,-4,-39,-39,95,2,-1,0,0,0,0,0,-83,95,-77,117,112,-77,-1,0,0,0,0,0,-23,-47,-25,-25,41,-118,-1,0,0,0,0,0,62,-48,-90,102,-90,30,-1,0,0,0,0,0,31,-4,-26,-26,-85,2,-1,0,0,0,0,0,27,-46,-90,-90,118,29,-1,0,0,0,0,0,114,-45,-98,27,-98,119,-1,0,0,0,0,0,18,-4,-39,-39,95,2,-1,0,0,0,0,0,-83,95,-77,117,112,-77,-1,0,0,0,0,0,-23,-47,-25,-25,41,-118,-1,0,0,0,0,0,62,-48,-90,102,-90,30,-1,0,0,0,0,0,31,-4,-26,-26,-85,2,-1,0,0,0,0,0,27,-46,-90,-90,118,29,-1,0,0,0,0,0,0,0,102,102,102,102,-1,0,0,0,0,0,76,25,-13,-32,-13,-37,-1,0,0,0,0,0,95,61,-35,-88,-35,-75,-1,0,0,0,0,0,-116,-86,-54,67,-94,-54,-1,0,0,0,0,0,65,17,-7,-16,-7,-24,-1,0,0,0,0,0,87,46,-28,-70,-28,-68,-1,0,0,0,0,0,123,101,-52,123,-52,-60,-1,0,0,0,0,0,-115,-59,-66,43,-116,-66,-1,0,0,0,0,0,65,17,-7,-16,-7,-24,-1,0,0,0,0,0,87,46,-28,-70,-28,-68,-1,0,0,0,0,0,123,101,-52,123,-52,-60,-1,0,0,0,0,0,-116,-86,-54,67,-94,-54,-1,0,0,0,0,0,-111,-13,-84,8,104,-84,-1,0,0,0,0,0,65,17,-7,-16,-7,-24,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,95,61,-35,-88,-35,-75,-1,0,0,0,0,0,123,101,-52,123,-52,-60,-1,0,0,0,0,0,-116,-86,-54,67,-94,-54,-1,0,0,0,0,0,-111,-13,-84,8,104,-84,-1,0,0,0,0,0,65,17,-7,-16,-7,-24,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,95,61,-35,-88,-35,-75,-1,0,0,0,0,0,123,101,-52,123,-52,-60,-1,0,0,0,0,0,-119,-96,-45,78,-77,-45,-1,0,0,0,0,0,-115,-59,-66,43,-116,-66,-1,0,0,0,0,0,-109,-14,-98,8,88,-98,-1,0,0,0,0,0,60,12,-4,-9,-4,-16,-1,0,0,0,0,0,76,25,-13,-32,-13,-37,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,95,61,-35,-88,-35,-75,-1,0,0,0,0,0,123,101,-52,123,-52,-60,-1,0,0,0,0,0,-119,-96,-45,78,-77,-45,-1,0,0,0,0,0,-115,-59,-66,43,-116,-66,-1,0,0,0,0,0,-109,-14,-98,8,88,-98,-1,0,0,0,0,0,60,12,-4,-9,-4,-16,-1,0,0,0,0,0,76,25,-13,-32,-13,-37,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,95,61,-35,-88,-35,-75,-1,0,0,0,0,0,123,101,-52,123,-52,-60,-1,0,0,0,0,0,-119,-96,-45,78,-77,-45,-1,0,0,0,0,0,-115,-59,-66,43,-116,-66,-1,0,0,0,0,0,-111,-13,-84,8,104,-84,-1,0,0,0,0,0,-106,-17,-127,8,64,-127,-1,0,0,0,0,0,74,21,-11,-27,-11,-32,-1,0,0,0,0,0,80,72,-39,-95,-39,-101,-1,0,0,0,0,0,98,-78,-93,49,-93,84,-1,0,0,0,0,0,73,15,-8,-19,-8,-23,-1,0,0,0,0,0,78,54,-28,-70,-28,-77,-1,0,0,0,0,0,86,104,-60,116,-60,118,-1,0,0,0,0,0,98,-66,-117,35,-117,69,-1,0,0,0,0,0,73,15,-8,-19,-8,-23,-1,0,0,0,0,0,78,54,-28,-70,-28,-77,-1,0,0,0,0,0,86,104,-60,116,-60,118,-1,0,0,0,0,0,98,-78,-93,49,-93,84,-1,0,0,0,0,0,102,-1,109,0,109,44,-1,0,0,0,0,0,73,15,-8,-19,-8,-23,-1,0,0,0,0,0,77,44,-23,-57,-23,-64,-1,0,0,0,0,0,80,72,-39,-95,-39,-101,-1,0,0,0,0,0,86,104,-60,116,-60,118,-1,0,0,0,0,0,98,-78,-93,49,-93,84,-1,0,0,0,0,0,102,-1,109,0,109,44,-1,0,0,0,0,0,73,15,-8,-19,-8,-23,-1,0,0,0,0,0,77,44,-23,-57,-23,-64,-1,0,0,0,0,0,80,72,-39,-95,-39,-101,-1,0,0,0,0,0,86,104,-60,116,-60,118,-1,0,0,0,0,0,96,-98,-85,65,-85,93,-1,0,0,0,0,0,98,-66,-117,35,-117,69,-1,0,0,0,0,0,108,-1,90,0,90,50,-1,0,0,0,0,0,72,7,-4,-9,-4,-11,-1,0,0,0,0,0,74,21,-11,-27,-11,-32,-1,0,0,0,0,0,77,44,-23,-57,-23,-64,-1,0,0,0,0,0,80,72,-39,-95,-39,-101,-1,0,0,0,0,0,86,104,-60,116,-60,118,-1,0,0,0,0,0,96,-98,-85,65,-85,93,-1,0,0,0,0,0,98,-66,-117,35,-117,69,-1,0,0,0,0,0,108,-1,90,0,90,50,-1,0,0,0,0,0,72,7,-4,-9,-4,-11,-1,0,0,0,0,0,74,21,-11,-27,-11,-32,-1,0,0,0,0,0,77,44,-23,-57,-23,-64,-1,0,0,0,0,0,80,72,-39,-95,-39,-101,-1,0,0,0,0,0,86,104,-60,116,-60,118,-1,0,0,0,0,0,96,-98,-85,65,-85,93,-1,0,0,0,0,0,98,-66,-117,35,-117,69,-1,0,0,0,0,0,102,-1,109,0,109,44,-1,0,0,0,0,0,101,-1,68,0,68,27,-1,0,0,0,0,0,0,0,-16,-16,-16,-16,-1,0,0,0,0,0,0,0,-67,-67,-67,-67,-1,0,0,0,0,0,0,0,99,99,99,99,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,0,0,-52,-52,-52,-52,-1,0,0,0,0,0,0,0,-106,-106,-106,-106,-1,0,0,0,0,0,0,0,82,82,82,82,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,0,0,-52,-52,-52,-52,-1,0,0,0,0,0,0,0,-106,-106,-106,-106,-1,0,0,0,0,0,0,0,99,99,99,99,-1,0,0,0,0,0,0,0,37,37,37,37,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,0,0,-39,-39,-39,-39,-1,0,0,0,0,0,0,0,-67,-67,-67,-67,-1,0,0,0,0,0,0,0,-106,-106,-106,-106,-1,0,0,0,0,0,0,0,99,99,99,99,-1,0,0,0,0,0,0,0,37,37,37,37,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,0,0,-39,-39,-39,-39,-1,0,0,0,0,0,0,0,-67,-67,-67,-67,-1,0,0,0,0,0,0,0,-106,-106,-106,-106,-1,0,0,0,0,0,0,0,115,115,115,115,-1,0,0,0,0,0,0,0,82,82,82,82,-1,0,0,0,0,0,0,0,37,37,37,37,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,-16,-16,-16,-16,-1,0,0,0,0,0,0,0,-39,-39,-39,-39,-1,0,0,0,0,0,0,0,-67,-67,-67,-67,-1,0,0,0,0,0,0,0,-106,-106,-106,-106,-1,0,0,0,0,0,0,0,115,115,115,115,-1,0,0,0,0,0,0,0,82,82,82,82,-1,0,0,0,0,0,0,0,37,37,37,37,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,-16,-16,-16,-16,-1,0,0,0,0,0,0,0,-39,-39,-39,-39,-1,0,0,0,0,0,0,0,-67,-67,-67,-67,-1,0,0,0,0,0,0,0,-106,-106,-106,-106,-1,0,0,0,0,0,0,0,115,115,115,115,-1,0,0,0,0,0,0,0,82,82,82,82,-1,0,0,0,0,0,0,0,37,37,37,37,-1,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,21,48,-2,-2,-26,-50,-1,0,0,0,0,0,19,-109,-3,-3,-82,107,-1,0,0,0,0,0,14,-16,-26,-26,85,13,-1,0,0,0,0,0,19,32,-2,-2,-19,-34,-1,0,0,0,0,0,20,120,-3,-3,-66,-123,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,13,-3,-39,-39,71,1,-1,0,0,0,0,0,19,32,-2,-2,-19,-34,-1,0,0,0,0,0,20,120,-3,-3,-66,-123,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,14,-16,-26,-26,85,13,-1,0,0,0,0,0,13,-6,-90,-90,54,3,-1,0,0,0,0,0,19,32,-2,-2,-19,-34,-1,0,0,0,0,0,21,91,-3,-3,-48,-94,-1,0,0,0,0,0,19,-109,-3,-3,-82,107,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,14,-16,-26,-26,85,13,-1,0,0,0,0,0,13,-6,-90,-90,54,3,-1,0,0,0,0,0,19,32,-2,-2,-19,-34,-1,0,0,0,0,0,21,91,-3,-3,-48,-94,-1,0,0,0,0,0,19,-109,-3,-3,-82,107,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,16,-22,-15,-15,105,19,-1,0,0,0,0,0,13,-3,-39,-39,72,1,-1,0,0,0,0,0,12,-9,-116,-116,45,4,-1,0,0,0,0,0,21,20,-1,-1,-11,-21,-1,0,0,0,0,0,21,48,-2,-2,-26,-50,-1,0,0,0,0,0,21,91,-3,-3,-48,-94,-1,0,0,0,0,0,19,-109,-3,-3,-82,107,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,16,-22,-15,-15,105,19,-1,0,0,0,0,0,13,-3,-39,-39,72,1,-1,0,0,0,0,0,12,-9,-116,-116,45,4,-1,0,0,0,0,0,21,20,-1,-1,-11,-21,-1,0,0,0,0,0,21,48,-2,-2,-26,-50,-1,0,0,0,0,0,21,91,-3,-3,-48,-94,-1,0,0,0,0,0,19,-109,-3,-3,-82,107,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,16,-22,-15,-15,105,19,-1,0,0,0,0,0,13,-3,-39,-39,72,1,-1,0,0,0,0,0,13,-6,-90,-90,54,3,-1,0,0,0,0,0,12,-10,127,127,39,4,-1,0,0,0,0,0,25,54,-2,-2,-24,-56,-1,0,0,0,0,0,19,121,-3,-3,-69,-124,-1,0,0,0,0,0,5,-59,-29,-29,74,51,-1,0,0,0,0,0,26,37,-2,-2,-16,-39,-1,0,0,0,0,0,24,115,-3,-3,-52,-118,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,3,-38,-41,-41,48,31,-1,0,0,0,0,0,26,37,-2,-2,-16,-39,-1,0,0,0,0,0,24,115,-3,-3,-52,-118,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,5,-59,-29,-29,74,51,-1,0,0,0,0,0,0,-1,-77,-77,0,0,-1,0,0,0,0,0,26,37,-2,-2,-16,-39,-1,0,0,0,0,0,24,95,-3,-3,-44,-98,-1,0,0,0,0,0,19,121,-3,-3,-69,-124,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,5,-59,-29,-29,74,51,-1,0,0,0,0,0,0,-1,-77,-77,0,0,-1,0,0,0,0,0,26,37,-2,-2,-16,-39,-1,0,0,0,0,0,24,95,-3,-3,-44,-98,-1,0,0,0,0,0,19,121,-3,-3,-69,-124,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,7,-78,-17,-17,101,72,-1,0,0,0,0,0,3,-38,-41,-41,48,31,-1,0,0,0,0,0,0,-1,-103,-103,0,0,-1,0,0,0,0,0,24,18,-1,-1,-9,-20,-1,0,0,0,0,0,25,54,-2,-2,-24,-56,-1,0,0,0,0,0,24,95,-3,-3,-44,-98,-1,0,0,0,0,0,19,121,-3,-3,-69,-124,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,7,-78,-17,-17,101,72,-1,0,0,0,0,0,3,-38,-41,-41,48,31,-1,0,0,0,0,0,0,-1,-103,-103,0,0,-1,0,0,0,0,0,24,18,-1,-1,-9,-20,-1,0,0,0,0,0,25,54,-2,-2,-24,-56,-1,0,0,0,0,0,24,95,-3,-3,-44,-98,-1,0,0,0,0,0,19,121,-3,-3,-69,-124,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,7,-78,-17,-17,101,72,-1,0,0,0,0,0,3,-38,-41,-41,48,31,-1,0,0,0,0,0,0,-1,-77,-77,0,0,-1,0,0,0,0,0,0,-1,127,127,0,0,-1,0,0,0,0,0,-114,68,-29,-90,-50,-29,-1,0,0,0,0,0,-66,-103,-102,106,61,-102,-1,0,0,0,0,0,-112,-45,-76,31,120,-76,-1,0,0,0,0,0,65,97,-33,-78,-33,-118,-1,0,0,0,0,0,82,-72,-96,51,-96,44,-1,0,0,0,0,0,0,99,-5,-5,-102,-103,-1,0,0,0,0,0,-2,-31,-29,-29,26,28,-1,0,0,0,0,0,23,-113,-3,-3,-65,111,-1,0,0,0,0,0,21,-1,-1,-1,127,0,-1,0,0,0,0,0,-58,42,-42,-54,-78,-42,-1,0,0,0,0,0,-114,68,-29,-90,-50,-29,-1,0,0,0,0,0,-66,-103,-102,106,61,-102,-1,0,0,0,0,0,42,102,-1,-1,-1,-103,-1,0,0,0,0,0,-112,-45,-76,31,120,-76,-1,0,0,0,0,0,65,97,-33,-78,-33,-118,-1,0,0,0,0,0,82,-72,-96,51,-96,44,-1,0,0,0,0,0,0,99,-5,-5,-102,-103,-1,0,0,0,0,0,-2,-31,-29,-29,26,28,-1,0,0,0,0,0,23,-113,-3,-3,-65,111,-1,0,0,0,0,0,21,-1,-1,-1,127,0,-1,0,0,0,0,0,-58,42,-42,-54,-78,-42,-1,0,0,0,0,0,-114,68,-29,-90,-50,-29,-1,0,0,0,0,0,-66,-103,-102,106,61,-102,-1,0,0,0,0,0,42,102,-1,-1,-1,-103,-1,0,0,0,0,0,15,-59,-79,-79,89,40,-1,0,0,0,0,0,-112,-45,-76,31,120,-76,-1,0,0,0,0,0,65,97,-33,-78,-33,-118,-1,0,0,0,0,0,82,-72,-96,51,-96,44,-1,0,0,0,0,0,0,99,-5,-5,-102,-103,-1,0,0,0,0,0,-2,-31,-29,-29,26,28,-1,0,0,0,0,0,23,-113,-3,-3,-65,111,-1,0,0,0,0,0,21,-1,-1,-1,127,0,-1,0,0,0,0,0,-58,42,-42,-54,-78,-42,-1,0,0,0,0,0,-114,68,-29,-90,-50,-29,-1,0,0,0,0,0,-112,-45,-76,31,120,-76,-1,0,0,0,0,0,65,97,-33,-78,-33,-118,-1,0,0,0,0,0,-114,68,-29,-90,-50,-29,-1,0,0,0,0,0,-112,-45,-76,31,120,-76,-1,0,0,0,0,0,65,97,-33,-78,-33,-118,-1,0,0,0,0,0,82,-72,-96,51,-96,44,-1,0,0,0,0,0,-114,68,-29,-90,-50,-29,-1,0,0,0,0,0,-112,-45,-76,31,120,-76,-1,0,0,0,0,0,65,97,-33,-78,-33,-118,-1,0,0,0,0,0,82,-72,-96,51,-96,44,-1,0,0,0,0,0,0,99,-5,-5,-102,-103,-1,0,0,0,0,0,-114,68,-29,-90,-50,-29,-1,0,0,0,0,0,-112,-45,-76,31,120,-76,-1,0,0,0,0,0,65,97,-33,-78,-33,-118,-1,0,0,0,0,0,82,-72,-96,51,-96,44,-1,0,0,0,0,0,0,99,-5,-5,-102,-103,-1,0,0,0,0,0,-2,-31,-29,-29,26,28,-1,0,0,0,0,0,-114,68,-29,-90,-50,-29,-1,0,0,0,0,0,-112,-45,-76,31,120,-76,-1,0,0,0,0,0,65,97,-33,-78,-33,-118,-1,0,0,0,0,0,82,-72,-96,51,-96,44,-1,0,0,0,0,0,0,99,-5,-5,-102,-103,-1,0,0,0,0,0,-2,-31,-29,-29,26,28,-1,0,0,0,0,0,23,-113,-3,-3,-65,111,-1,0,0,0,0,0,-114,68,-29,-90,-50,-29,-1,0,0,0,0,0,-112,-45,-76,31,120,-76,-1,0,0,0,0,0,65,97,-33,-78,-33,-118,-1,0,0,0,0,0,82,-72,-96,51,-96,44,-1,0,0,0,0,0,0,99,-5,-5,-102,-103,-1,0,0,0,0,0,-2,-31,-29,-29,26,28,-1,0,0,0,0,0,23,-113,-3,-3,-65,111,-1,0,0,0,0,0,21,-1,-1,-1,127,0,-1,0,0,0,0,0,-114,68,-29,-90,-50,-29,-1,0,0,0,0,0,-112,-45,-76,31,120,-76,-1,0,0,0,0,0,65,97,-33,-78,-33,-118,-1,0,0,0,0,0,82,-72,-96,51,-96,44,-1,0,0,0,0,0,0,99,-5,-5,-102,-103,-1,0,0,0,0,0,-2,-31,-29,-29,26,28,-1,0,0,0,0,0,23,-113,-3,-3,-65,111,-1,0,0,0,0,0,21,-1,-1,-1,127,0,-1,0,0,0,0,0,-58,42,-42,-54,-78,-42,-1,0,0,0,0,0,3,78,-5,-5,-76,-82,-1,0,0,0,0,0,-110,53,-29,-77,-51,-29,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,3,78,-5,-5,-76,-82,-1,0,0,0,0,0,-110,53,-29,-77,-51,-29,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,-54,27,-28,-34,-53,-28,-1,0,0,0,0,0,3,78,-5,-5,-76,-82,-1,0,0,0,0,0,-110,53,-29,-77,-51,-29,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,-54,27,-28,-34,-53,-28,-1,0,0,0,0,0,24,88,-2,-2,-39,-90,-1,0,0,0,0,0,3,78,-5,-5,-76,-82,-1,0,0,0,0,0,-110,53,-29,-77,-51,-29,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,-54,27,-28,-34,-53,-28,-1,0,0,0,0,0,24,88,-2,-2,-39,-90,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,3,78,-5,-5,-76,-82,-1,0,0,0,0,0,-110,53,-29,-77,-51,-29,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,-54,27,-28,-34,-53,-28,-1,0,0,0,0,0,24,88,-2,-2,-39,-90,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,28,44,-27,-27,-40,-67,-1,0,0,0,0,0,3,78,-5,-5,-76,-82,-1,0,0,0,0,0,-110,53,-29,-77,-51,-29,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,-54,27,-28,-34,-53,-28,-1,0,0,0,0,0,24,88,-2,-2,-39,-90,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,28,44,-27,-27,-40,-67,-1,0,0,0,0,0,-23,35,-3,-3,-38,-20,-1,0,0,0,0,0,3,78,-5,-5,-76,-82,-1,0,0,0,0,0,-110,53,-29,-77,-51,-29,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,-54,27,-28,-34,-53,-28,-1,0,0,0,0,0,24,88,-2,-2,-39,-90,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,28,44,-27,-27,-40,-67,-1,0,0,0,0,0,-23,35,-3,-3,-38,-20,-1,0,0,0,0,0,0,0,-14,-14,-14,-14,-1,0,0,0,0,0,108,53,-30,-77,-30,-51,-1,0,0,0,0,0,17,81,-3,-3,-51,-84,-1,0,0,0,0,0,-101,31,-24,-53,-43,-24,-1,0,0,0,0,0,108,53,-30,-77,-30,-51,-1,0,0,0,0,0,17,81,-3,-3,-51,-84,-1,0,0,0,0,0,-101,31,-24,-53,-43,-24,-1,0,0,0,0,0,-28,43,-12,-12,-54,-28,-1,0,0,0,0,0,108,53,-30,-77,-30,-51,-1,0,0,0,0,0,17,81,-3,-3,-51,-84,-1,0,0,0,0,0,-101,31,-24,-53,-43,-24,-1,0,0,0,0,0,-28,43,-12,-12,-54,-28,-1,0,0,0,0,0,56,45,-11,-26,-11,-55,-1,0,0,0,0,0,108,53,-30,-77,-30,-51,-1,0,0,0,0,0,17,81,-3,-3,-51,-84,-1,0,0,0,0,0,-101,31,-24,-53,-43,-24,-1,0,0,0,0,0,-28,43,-12,-12,-54,-28,-1,0,0,0,0,0,56,45,-11,-26,-11,-55,-1,0,0,0,0,0,35,81,-1,-1,-14,-82,-1,0,0,0,0,0,108,53,-30,-77,-30,-51,-1,0,0,0,0,0,17,81,-3,-3,-51,-84,-1,0,0,0,0,0,-101,31,-24,-53,-43,-24,-1,0,0,0,0,0,-28,43,-12,-12,-54,-28,-1,0,0,0,0,0,56,45,-11,-26,-11,-55,-1,0,0,0,0,0,35,81,-1,-1,-14,-82,-1,0,0,0,0,0,25,39,-15,-15,-30,-52,-1,0,0,0,0,0,108,53,-30,-77,-30,-51,-1,0,0,0,0,0,17,81,-3,-3,-51,-84,-1,0,0,0,0,0,-101,31,-24,-53,-43,-24,-1,0,0,0,0,0,-28,43,-12,-12,-54,-28,-1,0,0,0,0,0,56,45,-11,-26,-11,-55,-1,0,0,0,0,0,35,81,-1,-1,-14,-82,-1,0,0,0,0,0,25,39,-15,-15,-30,-52,-1,0,0,0,0,0,0,0,-52,-52,-52,-52,-1,0,0,0,0,0,-26,-3,-114,-114,1,82,-1,0,0,0,0,0,77,-65,100,39,100,25,-1,0,0,0,0,0,-26,-36,-59,-59,27,125,-1,0,0,0,0,0,-24,118,-34,-34,119,-82,-1,0,0,0,0,0,-27,62,-15,-15,-74,-38,-1,0,0,0,0,0,-23,29,-3,-3,-32,-17,-1,0,0,0,0,0,59,38,-11,-26,-11,-48,-1,0,0,0,0,0,61,103,-31,-72,-31,-122,-1,0,0,0,0,0,63,-90,-68,127,-68,65,-1,0,0,0,0,0,68,-59,-110,77,-110,33,-1,0,0,0,0,0,-26,-3,-114,-114,1,82,-1,0,0,0,0,0,68,-59,-110,77,-110,33,-1,0,0,0,0,0,77,-65,100,39,100,25,-1,0,0,0,0,0,-26,-36,-59,-59,27,125,-1,0,0,0,0,0,-24,118,-34,-34,119,-82,-1,0,0,0,0,0,-27,62,-15,-15,-74,-38,-1,0,0,0,0,0,-23,29,-3,-3,-32,-17,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,59,38,-11,-26,-11,-48,-1,0,0,0,0,0,61,103,-31,-72,-31,-122,-1,0,0,0,0,0,63,-90,-68,127,-68,65,-1,0,0,0,0,0,-25,76,-23,-23,-93,-55,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,63,-127,-41,-95,-41,106,-1,0,0,0,0,0,-28,-36,-48,-48,28,-117,-1,0,0,0,0,0,-27,62,-15,-15,-74,-38,-1,0,0,0,0,0,61,103,-31,-72,-31,-122,-1,0,0,0,0,0,72,-58,-84,77,-84,38,-1,0,0,0,0,0,-28,-36,-48,-48,28,-117,-1,0,0,0,0,0,-27,62,-15,-15,-74,-38,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,61,103,-31,-72,-31,-122,-1,0,0,0,0,0,72,-58,-84,77,-84,38,-1,0,0,0,0,0,-26,-36,-59,-59,27,125,-1,0,0,0,0,0,-25,76,-23,-23,-93,-55,-1,0,0,0,0,0,-23,29,-3,-3,-32,-17,-1,0,0,0,0,0,59,38,-11,-26,-11,-48,-1,0,0,0,0,0,63,-127,-41,-95,-41,106,-1,0,0,0,0,0,68,-59,-110,77,-110,33,-1,0,0,0,0,0,-26,-36,-59,-59,27,125,-1,0,0,0,0,0,-25,76,-23,-23,-93,-55,-1,0,0,0,0,0,-23,29,-3,-3,-32,-17,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,59,38,-11,-26,-11,-48,-1,0,0,0,0,0,63,-127,-41,-95,-41,106,-1,0,0,0,0,0,68,-59,-110,77,-110,33,-1,0,0,0,0,0,-26,-36,-59,-59,27,125,-1,0,0,0,0,0,-24,118,-34,-34,119,-82,-1,0,0,0,0,0,-27,62,-15,-15,-74,-38,-1,0,0,0,0,0,-23,29,-3,-3,-32,-17,-1,0,0,0,0,0,59,38,-11,-26,-11,-48,-1,0,0,0,0,0,61,103,-31,-72,-31,-122,-1,0,0,0,0,0,63,-90,-68,127,-68,65,-1,0,0,0,0,0,68,-59,-110,77,-110,33,-1,0,0,0,0,0,-26,-36,-59,-59,27,125,-1,0,0,0,0,0,-24,118,-34,-34,119,-82,-1,0,0,0,0,0,-27,62,-15,-15,-74,-38,-1,0,0,0,0,0,-23,29,-3,-3,-32,-17,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,59,38,-11,-26,-11,-48,-1,0,0,0,0,0,61,103,-31,-72,-31,-122,-1,0,0,0,0,0,63,-90,-68,127,-68,65,-1,0,0,0,0,0,68,-59,-110,77,-110,33,-1,0,0,0,0,0,-50,-1,75,64,0,75,-1,0,0,0,0,0,101,-1,68,0,68,27,-1,0,0,0,0,0,-50,-83,-125,118,42,-125,-1,0,0,0,0,0,-57,87,-85,-103,112,-85,-1,0,0,0,0,0,-57,51,-49,-62,-91,-49,-1,0,0,0,0,0,-46,21,-24,-25,-44,-24,-1,0,0,0,0,0,76,30,-16,-39,-16,-45,-1,0,0,0,0,0,80,68,-37,-90,-37,-96,-1,0,0,0,0,0,88,123,-82,90,-82,97,-1,0,0,0,0,0,97,-59,120,27,120,55,-1,0,0,0,0,0,-50,-1,75,64,0,75,-1,0,0,0,0,0,97,-59,120,27,120,55,-1,0,0,0,0,0,101,-1,68,0,68,27,-1,0,0,0,0,0,-50,-83,-125,118,42,-125,-1,0,0,0,0,0,-57,87,-85,-103,112,-85,-1,0,0,0,0,0,-57,51,-49,-62,-91,-49,-1,0,0,0,0,0,-46,21,-24,-25,-44,-24,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,76,30,-16,-39,-16,-45,-1,0,0,0,0,0,80,68,-37,-90,-37,-96,-1,0,0,0,0,0,88,123,-82,90,-82,97,-1,0,0,0,0,0,-60,70,-61,-81,-115,-61,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,82,90,-65,127,-65,123,-1,0,0,0,0,0,-55,-88,-108,123,50,-108,-1,0,0,0,0,0,-57,51,-49,-62,-91,-49,-1,0,0,0,0,0,80,68,-37,-90,-37,-96,-1,0,0,0,0,0,102,-1,-120,0,-120,55,-1,0,0,0,0,0,-55,-88,-108,123,50,-108,-1,0,0,0,0,0,-57,51,-49,-62,-91,-49,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,80,68,-37,-90,-37,-96,-1,0,0,0,0,0,102,-1,-120,0,-120,55,-1,0,0,0,0,0,-50,-83,-125,118,42,-125,-1,0,0,0,0,0,-60,70,-61,-81,-115,-61,-1,0,0,0,0,0,-46,21,-24,-25,-44,-24,-1,0,0,0,0,0,76,30,-16,-39,-16,-45,-1,0,0,0,0,0,82,90,-65,127,-65,123,-1,0,0,0,0,0,97,-59,120,27,120,55,-1,0,0,0,0,0,-50,-83,-125,118,42,-125,-1,0,0,0,0,0,-60,70,-61,-81,-115,-61,-1,0,0,0,0,0,-46,21,-24,-25,-44,-24,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,76,30,-16,-39,-16,-45,-1,0,0,0,0,0,82,90,-65,127,-65,123,-1,0,0,0,0,0,97,-59,120,27,120,55,-1,0,0,0,0,0,-50,-83,-125,118,42,-125,-1,0,0,0,0,0,-57,87,-85,-103,112,-85,-1,0,0,0,0,0,-57,51,-49,-62,-91,-49,-1,0,0,0,0,0,-46,21,-24,-25,-44,-24,-1,0,0,0,0,0,76,30,-16,-39,-16,-45,-1,0,0,0,0,0,80,68,-37,-90,-37,-96,-1,0,0,0,0,0,88,123,-82,90,-82,97,-1,0,0,0,0,0,97,-59,120,27,120,55,-1,0,0,0,0,0,-50,-83,-125,118,42,-125,-1,0,0,0,0,0,-57,87,-85,-103,112,-85,-1,0,0,0,0,0,-57,51,-49,-62,-91,-49,-1,0,0,0,0,0,-46,21,-24,-25,-44,-24,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,76,30,-16,-39,-16,-45,-1,0,0,0,0,0,80,68,-37,-90,-37,-96,-1,0,0,0,0,0,88,123,-82,90,-82,97,-1,0,0,0,0,0,97,-59,120,27,120,55,-1,0,0,0,0,0,-67,11,-14,-20,-25,-14,-1,0,0,0,0,0,-105,61,-37,-90,-67,-37,-1,0,0,0,0,0,-115,-59,-66,43,-116,-66,-1,0,0,0,0,0,-71,8,-10,-15,-18,-10,-1,0,0,0,0,0,-101,40,-31,-67,-55,-31,-1,0,0,0,0,0,-111,112,-49,116,-87,-49,-1,0,0,0,0,0,-113,-9,-80,5,112,-80,-1,0,0,0,0,0,-71,8,-10,-15,-18,-10,-1,0,0,0,0,0,-101,40,-31,-67,-55,-31,-1,0,0,0,0,0,-111,112,-49,116,-87,-49,-1,0,0,0,0,0,-115,-59,-66,43,-116,-66,-1,0,0,0,0,0,-113,-9,-115,4,90,-115,-1,0,0,0,0,0,-71,8,-10,-15,-18,-10,-1,0,0,0,0,0,-88,24,-26,-48,-47,-26,-1,0,0,0,0,0,-105,61,-37,-90,-67,-37,-1,0,0,0,0,0,-111,112,-49,116,-87,-49,-1,0,0,0,0,0,-115,-59,-66,43,-116,-66,-1,0,0,0,0,0,-113,-9,-115,4,90,-115,-1,0,0,0,0,0,-71,8,-10,-15,-18,-10,-1,0,0,0,0,0,-88,24,-26,-48,-47,-26,-1,0,0,0,0,0,-105,61,-37,-90,-67,-37,-1,0,0,0,0,0,-111,112,-49,116,-87,-49,-1,0,0,0,0,0,-114,-73,-64,54,-112,-64,-1,0,0,0,0,0,-113,-9,-80,5,112,-80,-1,0,0,0,0,0,-113,-8,123,3,78,123,-1,0,0,0,0,0,-23,8,-1,-1,-9,-5,-1,0,0,0,0,0,-67,11,-14,-20,-25,-14,-1,0,0,0,0,0,-88,24,-26,-48,-47,-26,-1,0,0,0,0,0,-105,61,-37,-90,-67,-37,-1,0,0,0,0,0,-111,112,-49,116,-87,-49,-1,0,0,0,0,0,-114,-73,-64,54,-112,-64,-1,0,0,0,0,0,-113,-9,-80,5,112,-80,-1,0,0,0,0,0,-113,-8,123,3,78,123,-1,0,0,0,0,0,-23,8,-1,-1,-9,-5,-1,0,0,0,0,0,-67,11,-14,-20,-25,-14,-1,0,0,0,0,0,-88,24,-26,-48,-47,-26,-1,0,0,0,0,0,-105,61,-37,-90,-67,-37,-1,0,0,0,0,0,-111,112,-49,116,-87,-49,-1,0,0,0,0,0,-114,-73,-64,54,-112,-64,-1,0,0,0,0,0,-113,-9,-80,5,112,-80,-1,0,0,0,0,0,-113,-9,-115,4,90,-115,-1,0,0,0,0,0,-113,-7,88,2,56,88,-1,0,0,0,0,0,-56,14,-16,-20,-30,-16,-1,0,0,0,0,0,-105,61,-37,-90,-67,-37,-1,0,0,0,0,0,-126,-48,-103,28,-112,-103,-1,0,0,0,0,0,-49,8,-9,-10,-17,-9,-1,0,0,0,0,0,-101,40,-31,-67,-55,-31,-1,0,0,0,0,0,-113,-128,-49,103,-87,-49,-1,0,0,0,0,0,-126,-5,-118,2,-127,-118,-1,0,0,0,0,0,-49,8,-9,-10,-17,-9,-1,0,0,0,0,0,-101,40,-31,-67,-55,-31,-1,0,0,0,0,0,-113,-128,-49,103,-87,-49,-1,0,0,0,0,0,-126,-48,-103,28,-112,-103,-1,0,0,0,0,0,119,-4,108,1,108,89,-1,0,0,0,0,0,-49,8,-9,-10,-17,-9,-1,0,0,0,0,0,-88,24,-26,-48,-47,-26,-1,0,0,0,0,0,-105,61,-37,-90,-67,-37,-1,0,0,0,0,0,-113,-128,-49,103,-87,-49,-1,0,0,0,0,0,-126,-48,-103,28,-112,-103,-1,0,0,0,0,0,119,-4,108,1,108,89,-1,0,0,0,0,0,-49,8,-9,-10,-17,-9,-1,0,0,0,0,0,-88,24,-26,-48,-47,-26,-1,0,0,0,0,0,-105,61,-37,-90,-67,-37,-1,0,0,0,0,0,-113,-128,-49,103,-87,-49,-1,0,0,0,0,0,-114,-73,-64,54,-112,-64,-1,0,0,0,0,0,-126,-5,-118,2,-127,-118,-1,0,0,0,0,0,118,-4,100,1,100,80,-1,0,0,0,0,0,-23,8,-1,-1,-9,-5,-1,0,0,0,0,0,-56,14,-16,-20,-30,-16,-1,0,0,0,0,0,-88,24,-26,-48,-47,-26,-1,0,0,0,0,0,-105,61,-37,-90,-67,-37,-1,0,0,0,0,0,-113,-128,-49,103,-87,-49,-1,0,0,0,0,0,-114,-73,-64,54,-112,-64,-1,0,0,0,0,0,-126,-5,-118,2,-127,-118,-1,0,0,0,0,0,118,-4,100,1,100,80,-1,0,0,0,0,0,-23,8,-1,-1,-9,-5,-1,0,0,0,0,0,-56,14,-16,-20,-30,-16,-1,0,0,0,0,0,-88,24,-26,-48,-47,-26,-1,0,0,0,0,0,-105,61,-37,-90,-67,-37,-1,0,0,0,0,0,-113,-128,-49,103,-87,-49,-1,0,0,0,0,0,-114,-73,-64,54,-112,-64,-1,0,0,0,0,0,-126,-5,-118,2,-127,-118,-1,0,0,0,0,0,119,-4,108,1,108,89,-1,0,0,0,0,0,117,-5,70,1,70,54,-1,0,0,0,0,0,18,-18,127,127,59,8,-1,0,0,0,0,0,-61,-1,75,45,0,75,-1,0,0,0,0,0,20,-10,-77,-77,88,6,-1,0,0,0,0,0,22,-24,-32,-32,-126,20,-1,0,0,0,0,0,23,-101,-3,-3,-72,99,-1,0,0,0,0,0,24,72,-2,-2,-32,-74,-1,0,0,0,0,0,-91,20,-21,-40,-38,-21,-1,0,0,0,0,0,-79,47,-46,-78,-85,-46,-1,0,0,0,0,0,-77,84,-84,-128,115,-84,-1,0,0,0,0,0,-67,-75,-120,84,39,-120,-1,0,0,0,0,0,18,-18,127,127,59,8,-1,0,0,0,0,0,-67,-75,-120,84,39,-120,-1,0,0,0,0,0,-61,-1,75,45,0,75,-1,0,0,0,0,0,20,-10,-77,-77,88,6,-1,0,0,0,0,0,22,-24,-32,-32,-126,20,-1,0,0,0,0,0,23,-101,-3,-3,-72,99,-1,0,0,0,0,0,24,72,-2,-2,-32,-74,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,-91,20,-21,-40,-38,-21,-1,0,0,0,0,0,-79,47,-46,-78,-85,-46,-1,0,0,0,0,0,-77,84,-84,-128,115,-84,-1,0,0,0,0,0,23,-69,-15,-15,-93,64,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,-78,69,-61,-103,-114,-61,-1,0,0,0,0,0,17,-3,-26,-26,97,1,-1,0,0,0,0,0,23,-101,-3,-3,-72,99,-1,0,0,0,0,0,-79,47,-46,-78,-85,-46,-1,0,0,0,0,0,-71,-101,-103,94,60,-103,-1,0,0,0,0,0].concat([17,-3,-26,-26,97,1,-1,0,0,0,0,0,23,-101,-3,-3,-72,99,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,-79,47,-46,-78,-85,-46,-1,0,0,0,0,0,-71,-101,-103,94,60,-103,-1,0,0,0,0,0,20,-10,-77,-77,88,6,-1,0,0,0,0,0,23,-69,-15,-15,-93,64,-1,0,0,0,0,0,24,72,-2,-2,-32,-74,-1,0,0,0,0,0,-91,20,-21,-40,-38,-21,-1,0,0,0,0,0,-78,69,-61,-103,-114,-61,-1,0,0,0,0,0,-67,-75,-120,84,39,-120,-1,0,0,0,0,0,20,-10,-77,-77,88,6,-1,0,0,0,0,0,23,-69,-15,-15,-93,64,-1,0,0,0,0,0,24,72,-2,-2,-32,-74,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,-91,20,-21,-40,-38,-21,-1,0,0,0,0,0,-78,69,-61,-103,-114,-61,-1,0,0,0,0,0,-67,-75,-120,84,39,-120,-1,0,0,0,0,0,20,-10,-77,-77,88,6,-1,0,0,0,0,0,22,-24,-32,-32,-126,20,-1,0,0,0,0,0,23,-101,-3,-3,-72,99,-1,0,0,0,0,0,24,72,-2,-2,-32,-74,-1,0,0,0,0,0,-91,20,-21,-40,-38,-21,-1,0,0,0,0,0,-79,47,-46,-78,-85,-46,-1,0,0,0,0,0,-77,84,-84,-128,115,-84,-1,0,0,0,0,0,-67,-75,-120,84,39,-120,-1,0,0,0,0,0,20,-10,-77,-77,88,6,-1,0,0,0,0,0,22,-24,-32,-32,-126,20,-1,0,0,0,0,0,23,-101,-3,-3,-72,99,-1,0,0,0,0,0,24,72,-2,-2,-32,-74,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,-91,20,-21,-40,-38,-21,-1,0,0,0,0,0,-79,47,-46,-78,-85,-46,-1,0,0,0,0,0,-77,84,-84,-128,115,-84,-1,0,0,0,0,0,-67,-75,-120,84,39,-120,-1,0,0,0,0,0,-68,14,-17,-25,-31,-17,-1,0,0,0,0,0,-42,67,-55,-55,-108,-57,-1,0,0,0,0,0,-22,-34,-35,-35,28,119,-1,0,0,0,0,0,-71,8,-10,-15,-18,-10,-1,0,0,0,0,0,-45,41,-40,-41,-75,-40,-1,0,0,0,0,0,-28,-117,-33,-33,101,-80,-1,0,0,0,0,0,-17,-24,-50,-50,18,86,-1,0,0,0,0,0,-71,8,-10,-15,-18,-10,-1,0,0,0,0,0,-45,41,-40,-41,-75,-40,-1,0,0,0,0,0,-28,-117,-33,-33,101,-80,-1,0,0,0,0,0,-22,-34,-35,-35,28,119,-1,0,0,0,0,0,-20,-1,-104,-104,0,67,-1,0,0,0,0,0,-71,8,-10,-15,-18,-10,-1,0,0,0,0,0,-52,38,-38,-44,-71,-38,-1,0,0,0,0,0,-42,67,-55,-55,-108,-57,-1,0,0,0,0,0,-28,-117,-33,-33,101,-80,-1,0,0,0,0,0,-22,-34,-35,-35,28,119,-1,0,0,0,0,0,-20,-1,-104,-104,0,67,-1,0,0,0,0,0,-71,8,-10,-15,-18,-10,-1,0,0,0,0,0,-52,38,-38,-44,-71,-38,-1,0,0,0,0,0,-42,67,-55,-55,-108,-57,-1,0,0,0,0,0,-28,-117,-33,-33,101,-80,-1,0,0,0,0,0,-23,-47,-25,-25,41,-118,-1,0,0,0,0,0,-17,-24,-50,-50,18,86,-1,0,0,0,0,0,-20,-1,-111,-111,0,63,-1,0,0,0,0,0,-61,5,-7,-9,-12,-7,-1,0,0,0,0,0,-68,14,-17,-25,-31,-17,-1,0,0,0,0,0,-52,38,-38,-44,-71,-38,-1,0,0,0,0,0,-42,67,-55,-55,-108,-57,-1,0,0,0,0,0,-28,-117,-33,-33,101,-80,-1,0,0,0,0,0,-23,-47,-25,-25,41,-118,-1,0,0,0,0,0,-17,-24,-50,-50,18,86,-1,0,0,0,0,0,-20,-1,-111,-111,0,63,-1,0,0,0,0,0,-61,5,-7,-9,-12,-7,-1,0,0,0,0,0,-68,14,-17,-25,-31,-17,-1,0,0,0,0,0,-52,38,-38,-44,-71,-38,-1,0,0,0,0,0,-42,67,-55,-55,-108,-57,-1,0,0,0,0,0,-28,-117,-33,-33,101,-80,-1,0,0,0,0,0,-23,-47,-25,-25,41,-118,-1,0,0,0,0,0,-17,-24,-50,-50,18,86,-1,0,0,0,0,0,-20,-1,-104,-104,0,67,-1,0,0,0,0,0,-14,-1,103,103,0,31,-1,0,0,0,0,0,-76,8,-11,-17,-19,-11,-1,0,0,0,0,0,-88,37,-36,-68,-67,-36,-1,0,0,0,0,0,-80,100,-79,117,107,-79,-1,0,0,0,0,0,-74,7,-9,-14,-16,-9,-1,0,0,0,0,0,-83,28,-30,-53,-55,-30,-1,0,0,0,0,0,-83,58,-56,-98,-102,-56,-1,0,0,0,0,0,-74,-128,-93,106,81,-93,-1,0,0,0,0,0,-74,7,-9,-14,-16,-9,-1,0,0,0,0,0,-83,28,-30,-53,-55,-30,-1,0,0,0,0,0,-83,58,-56,-98,-102,-56,-1,0,0,0,0,0,-80,100,-79,117,107,-79,-1,0,0,0,0,0,-68,-71,-113,84,39,-113,-1,0,0,0,0,0,-74,7,-9,-14,-16,-9,-1,0,0,0,0,0,-86,18,-21,-38,-38,-21,-1,0,0,0,0,0,-88,37,-36,-68,-67,-36,-1,0,0,0,0,0,-83,58,-56,-98,-102,-56,-1,0,0,0,0,0,-80,100,-79,117,107,-79,-1,0,0,0,0,0,-68,-71,-113,84,39,-113,-1,0,0,0,0,0,-74,7,-9,-14,-16,-9,-1,0,0,0,0,0,-86,18,-21,-38,-38,-21,-1,0,0,0,0,0,-88,37,-36,-68,-67,-36,-1,0,0,0,0,0,-83,58,-56,-98,-102,-56,-1,0,0,0,0,0,-84,83,-70,-128,125,-70,-1,0,0,0,0,0,-74,-128,-93,106,81,-93,-1,0,0,0,0,0,-66,-40,-122,74,20,-122,-1,0,0,0,0,0,-65,2,-3,-4,-5,-3,-1,0,0,0,0,0,-76,8,-11,-17,-19,-11,-1,0,0,0,0,0,-86,18,-21,-38,-38,-21,-1,0,0,0,0,0,-88,37,-36,-68,-67,-36,-1,0,0,0,0,0,-83,58,-56,-98,-102,-56,-1,0,0,0,0,0,-84,83,-70,-128,125,-70,-1,0,0,0,0,0,-74,-128,-93,106,81,-93,-1,0,0,0,0,0,-66,-40,-122,74,20,-122,-1,0,0,0,0,0,-65,2,-3,-4,-5,-3,-1,0,0,0,0,0,-76,8,-11,-17,-19,-11,-1,0,0,0,0,0,-86,18,-21,-38,-38,-21,-1,0,0,0,0,0,-88,37,-36,-68,-67,-36,-1,0,0,0,0,0,-83,58,-56,-98,-102,-56,-1,0,0,0,0,0,-84,83,-70,-128,125,-70,-1,0,0,0,0,0,-74,-128,-93,106,81,-93,-1,0,0,0,0,0,-68,-71,-113,84,39,-113,-1,0,0,0,0,0,-65,-1,125,63,0,125,-1,0,0,0,0,0,-14,-1,103,103,0,31,-1,0,0,0,0,0,-106,-15,97,5,48,97,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,5,-93,-42,-42,96,77,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,-114,32,-16,-47,-27,-16,-1,0,0,0,0,0,-115,87,-34,-110,-59,-34,-1,0,0,0,0,0,-113,-89,-61,67,-109,-61,-1,0,0,0,0,0,-108,-50,-84,33,102,-84,-1,0,0,0,0,0,-14,-1,103,103,0,31,-1,0,0,0,0,0,-108,-50,-84,33,102,-84,-1,0,0,0,0,0,-106,-15,97,5,48,97,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,5,-93,-42,-42,96,77,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,-114,32,-16,-47,-27,-16,-1,0,0,0,0,0,-115,87,-34,-110,-59,-34,-1,0,0,0,0,0,-113,-89,-61,67,-109,-61,-1,0,0,0,0,0,12,-106,-17,-17,-118,98,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,-113,-128,-49,103,-87,-49,-1,0,0,0,0,0,-8,-1,-54,-54,0,32,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,-115,87,-34,-110,-59,-34,-1,0,0,0,0,0,-113,-9,-80,5,113,-80,-1,0,0,0,0,0,-8,-1,-54,-54,0,32,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,-115,87,-34,-110,-59,-34,-1,0,0,0,0,0,-113,-9,-80,5,113,-80,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,12,-106,-17,-17,-118,98,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,-114,32,-16,-47,-27,-16,-1,0,0,0,0,0,-113,-128,-49,103,-87,-49,-1,0,0,0,0,0,-108,-50,-84,33,102,-84,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,12,-106,-17,-17,-118,98,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,-114,32,-16,-47,-27,-16,-1,0,0,0,0,0,-113,-128,-49,103,-87,-49,-1,0,0,0,0,0,-108,-50,-84,33,102,-84,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,5,-93,-42,-42,96,77,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,-114,32,-16,-47,-27,-16,-1,0,0,0,0,0,-115,87,-34,-110,-59,-34,-1,0,0,0,0,0,-113,-89,-61,67,-109,-61,-1,0,0,0,0,0,-108,-50,-84,33,102,-84,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,5,-93,-42,-42,96,77,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,-114,32,-16,-47,-27,-16,-1,0,0,0,0,0,-115,87,-34,-110,-59,-34,-1,0,0,0,0,0,-113,-89,-61,67,-109,-61,-1,0,0,0,0,0,-108,-50,-84,33,102,-84,-1,0,0,0,0,0,-14,-1,103,103,0,31,-1,0,0,0,0,0,0,0,26,26,26,26,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,5,-93,-42,-42,96,77,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,0,0,-32,-32,-32,-32,-1,0,0,0,0,0,0,0,-70,-70,-70,-70,-1,0,0,0,0,0,0,0,-121,-121,-121,-121,-1,0,0,0,0,0,0,0,77,77,77,77,-1,0,0,0,0,0,-14,-1,103,103,0,31,-1,0,0,0,0,0,0,0,77,77,77,77,-1,0,0,0,0,0,0,0,26,26,26,26,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,5,-93,-42,-42,96,77,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,-32,-32,-32,-32,-1,0,0,0,0,0,0,0,-70,-70,-70,-70,-1,0,0,0,0,0,0,0,-121,-121,-121,-121,-1,0,0,0,0,0,12,-106,-17,-17,-118,98,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,-103,-103,-103,-103,-1,0,0,0,0,0,-8,-1,-54,-54,0,32,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,0,0,-70,-70,-70,-70,-1,0,0,0,0,0,0,0,64,64,64,64,-1,0,0,0,0,0,-8,-1,-54,-54,0,32,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,-70,-70,-70,-70,-1,0,0,0,0,0,0,0,64,64,64,64,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,12,-106,-17,-17,-118,98,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,0,0,-32,-32,-32,-32,-1,0,0,0,0,0,0,0,-103,-103,-103,-103,-1,0,0,0,0,0,0,0,77,77,77,77,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,12,-106,-17,-17,-118,98,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,-32,-32,-32,-32,-1,0,0,0,0,0,0,0,-103,-103,-103,-103,-1,0,0,0,0,0,0,0,77,77,77,77,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,5,-93,-42,-42,96,77,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,0,0,-32,-32,-32,-32,-1,0,0,0,0,0,0,0,-70,-70,-70,-70,-1,0,0,0,0,0,0,0,-121,-121,-121,-121,-1,0,0,0,0,0,0,0,77,77,77,77,-1,0,0,0,0,0,-7,-36,-78,-78,24,43,-1,0,0,0,0,0,5,-93,-42,-42,96,77,-1,0,0,0,0,0,13,119,-12,-12,-91,-126,-1,0,0,0,0,0,15,54,-3,-3,-37,-57,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,-32,-32,-32,-32,-1,0,0,0,0,0,0,0,-70,-70,-70,-70,-1,0,0,0,0,0,0,0,-121,-121,-121,-121,-1,0,0,0,0,0,0,0,77,77,77,77,-1,0,0,0,0,0,3,32,-3,-3,-32,-35,-1,0,0,0,0,0,-12,92,-6,-6,-97,-75,-1,0,0,0,0,0,-29,-36,-59,-59,27,-118,-1,0,0,0,0,0,13,28,-2,-2,-21,-30,-1,0,0,0,0,0,-4,72,-5,-5,-76,-71,-1,0,0,0,0,0,-18,-109,-9,-9,104,-95,-1,0,0,0,0,0,-32,-3,-82,-82,1,126,-1,0,0,0,0,0,13,28,-2,-2,-21,-30,-1,0,0,0,0,0,-4,72,-5,-5,-76,-71,-1,0,0,0,0,0,-18,-109,-9,-9,104,-95,-1,0,0,0,0,0,-29,-36,-59,-59,27,-118,-1,0,0,0,0,0,-43,-4,122,122,1,119,-1,0,0,0,0,0,13,28,-2,-2,-21,-30,-1,0,0,0,0,0,3,60,-4,-4,-59,-64,-1,0,0,0,0,0,-12,92,-6,-6,-97,-75,-1,0,0,0,0,0,-18,-109,-9,-9,104,-95,-1,0,0,0,0,0,-29,-36,-59,-59,27,-118,-1,0,0,0,0,0,-43,-4,122,122,1,119,-1,0,0,0,0,0,13,28,-2,-2,-21,-30,-1,0,0,0,0,0,3,60,-4,-4,-59,-64,-1,0,0,0,0,0,-12,92,-6,-6,-97,-75,-1,0,0,0,0,0,-18,-109,-9,-9,104,-95,-1,0,0,0,0,0,-26,-61,-35,-35,52,-105,-1,0,0,0,0,0,-32,-3,-82,-82,1,126,-1,0,0,0,0,0,-43,-4,122,122,1,119,-1,0,0,0,0,0,14,12,-1,-1,-9,-13,-1,0,0,0,0,0,3,32,-3,-3,-32,-35,-1,0,0,0,0,0,3,60,-4,-4,-59,-64,-1,0,0,0,0,0,-12,92,-6,-6,-97,-75,-1,0,0,0,0,0,-18,-109,-9,-9,104,-95,-1,0,0,0,0,0,-26,-61,-35,-35,52,-105,-1,0,0,0,0,0,-32,-3,-82,-82,1,126,-1,0,0,0,0,0,-43,-4,122,122,1,119,-1,0,0,0,0,0,14,12,-1,-1,-9,-13,-1,0,0,0,0,0,3,32,-3,-3,-32,-35,-1,0,0,0,0,0,3,60,-4,-4,-59,-64,-1,0,0,0,0,0,-12,92,-6,-6,-97,-75,-1,0,0,0,0,0,-18,-109,-9,-9,104,-95,-1,0,0,0,0,0,-26,-61,-35,-35,52,-105,-1,0,0,0,0,0,-32,-3,-82,-82,1,126,-1,0,0,0,0,0,-43,-4,122,122,1,119,-1,0,0,0,0,0,-57,-1,106,73,0,106,-1,0,0,0,0,0,-11,-1,-91,-91,0,38,-1,0,0,0,0,0,-89,-85,-107,49,54,-107,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,30,110,-2,-2,-32,-112,-1,0,0,0,0,0,-120,24,-8,-32,-13,-8,-1,0,0,0,0,0,-118,67,-23,-85,-39,-23,-1,0,0,0,0,0,-113,113,-47,116,-83,-47,-1,0,0,0,0,0,-105,-99,-76,69,117,-76,-1,0,0,0,0,0,-11,-1,-91,-91,0,38,-1,0,0,0,0,0,-105,-99,-76,69,117,-76,-1,0,0,0,0,0,-89,-85,-107,49,54,-107,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,30,110,-2,-2,-32,-112,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,-120,24,-8,-32,-13,-8,-1,0,0,0,0,0,-118,67,-23,-85,-39,-23,-1,0,0,0,0,0,-113,113,-47,116,-83,-47,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,-113,86,-37,-111,-65,-37,-1,0,0,0,0,0,-2,-31,-41,-41,25,28,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,-118,67,-23,-85,-39,-23,-1,0,0,0,0,0,-111,-63,-74,44,123,-74,-1,0,0,0,0,0,-2,-31,-41,-41,25,28,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,-118,67,-23,-85,-39,-23,-1,0,0,0,0,0,-111,-63,-74,44,123,-74,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,30,110,-2,-2,-32,-112,-1,0,0,0,0,0,-120,24,-8,-32,-13,-8,-1,0,0,0,0,0,-113,86,-37,-111,-65,-37,-1,0,0,0,0,0,-105,-99,-76,69,117,-76,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,30,110,-2,-2,-32,-112,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,-120,24,-8,-32,-13,-8,-1,0,0,0,0,0,-113,86,-37,-111,-65,-37,-1,0,0,0,0,0,-105,-99,-76,69,117,-76,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,30,110,-2,-2,-32,-112,-1,0,0,0,0,0,-120,24,-8,-32,-13,-8,-1,0,0,0,0,0,-118,67,-23,-85,-39,-23,-1,0,0,0,0,0,-113,113,-47,116,-83,-47,-1,0,0,0,0,0,-105,-99,-76,69,117,-76,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,30,110,-2,-2,-32,-112,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,-120,24,-8,-32,-13,-8,-1,0,0,0,0,0,-118,67,-23,-85,-39,-23,-1,0,0,0,0,0,-113,113,-47,116,-83,-47,-1,0,0,0,0,0,-105,-99,-76,69,117,-76,-1,0,0,0,0,0,-11,-1,-91,-91,0,38,-1,0,0,0,0,0,107,-1,104,0,104,55,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,51,106,-17,-39,-17,-117,-1,0,0,0,0,0,62,-126,-39,-90,-39,106,-1,0,0,0,0,0,83,121,-67,102,-67,99,-1,0,0,0,0,0,103,-45,-104,26,-104,80,-1,0,0,0,0,0,-11,-1,-91,-91,0,38,-1,0,0,0,0,0,103,-45,-104,26,-104,80,-1,0,0,0,0,0,107,-1,104,0,104,55,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,51,106,-17,-39,-17,-117,-1,0,0,0,0,0,62,-126,-39,-90,-39,106,-1,0,0,0,0,0,83,121,-67,102,-67,99,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,66,-120,-49,-111,-49,96,-1,0,0,0,0,0,-2,-31,-41,-41,25,28,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,62,-126,-39,-90,-39,106,-1,0,0,0,0,0,98,-46,-106,26,-106,65,-1,0,0,0,0,0,-2,-31,-41,-41,25,28,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,62,-126,-39,-90,-39,106,-1,0,0,0,0,0,98,-46,-106,26,-106,65,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,51,106,-17,-39,-17,-117,-1,0,0,0,0,0,66,-120,-49,-111,-49,96,-1,0,0,0,0,0,103,-45,-104,26,-104,80,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,51,106,-17,-39,-17,-117,-1,0,0,0,0,0,66,-120,-49,-111,-49,96,-1,0,0,0,0,0,103,-45,-104,26,-104,80,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,51,106,-17,-39,-17,-117,-1,0,0,0,0,0,62,-126,-39,-90,-39,106,-1,0,0,0,0,0,83,121,-67,102,-67,99,-1,0,0,0,0,0,103,-45,-104,26,-104,80,-1,0,0,0,0,0,2,-48,-41,-41,48,39,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,51,106,-17,-39,-17,-117,-1,0,0,0,0,0,62,-126,-39,-90,-39,106,-1,0,0,0,0,0,83,121,-67,102,-67,99,-1,0,0,0,0,0,103,-45,-104,26,-104,80,-1,0,0,0,0,0,13,44,-2,-2,-32,-46,-1,0,0,0,0,0,9,-117,-4,-4,-110,114,-1,0,0,0,0,0,1,-45,-34,-34,45,38,-1,0,0,0,0,0,13,37,-2,-2,-27,-39,-1,0,0,0,0,0,11,108,-4,-4,-82,-111,-1,0,0,0,0,0,7,-77,-5,-5,106,74,-1,0,0,0,0,0,-3,-32,-53,-53,24,29,-1,0,0,0,0,0,13,37,-2,-2,-27,-39,-1,0,0,0,0,0,11,108,-4,-4,-82,-111,-1,0,0,0,0,0,7,-77,-5,-5,106,74,-1,0,0,0,0,0,1,-45,-34,-34,45,38,-1,0,0,0,0,0,-3,-25,-91,-91,15,21,-1,0,0,0,0,0,13,37,-2,-2,-27,-39,-1,0,0,0,0,0,12,92,-4,-4,-69,-95,-1,0,0,0,0,0,9,-117,-4,-4,-110,114,-1,0,0,0,0,0,7,-77,-5,-5,106,74,-1,0,0,0,0,0,1,-45,-34,-34,45,38,-1,0,0,0,0,0,-3,-25,-91,-91,15,21,-1,0,0,0,0,0,13,37,-2,-2,-27,-39,-1,0,0,0,0,0,12,92,-4,-4,-69,-95,-1,0,0,0,0,0,9,-117,-4,-4,-110,114,-1,0,0,0,0,0,7,-77,-5,-5,106,74,-1,0,0,0,0,0,3,-48,-17,-17,59,44,-1,0,0,0,0,0,-3,-32,-53,-53,24,29,-1,0,0,0,0,0,-5,-1,-103,-103,0,13,-1,0,0,0,0,0,14,15,-1,-1,-11,-16,-1,0,0,0,0,0,13,44,-2,-2,-32,-46,-1,0,0,0,0,0,12,92,-4,-4,-69,-95,-1,0,0,0,0,0,9,-117,-4,-4,-110,114,-1,0,0,0,0,0,7,-77,-5,-5,106,74,-1,0,0,0,0,0,3,-48,-17,-17,59,44,-1,0,0,0,0,0,-3,-32,-53,-53,24,29,-1,0,0,0,0,0,-5,-1,-103,-103,0,13,-1,0,0,0,0,0,14,15,-1,-1,-11,-16,-1,0,0,0,0,0,13,44,-2,-2,-32,-46,-1,0,0,0,0,0,12,92,-4,-4,-69,-95,-1,0,0,0,0,0,9,-117,-4,-4,-110,114,-1,0,0,0,0,0,7,-77,-5,-5,106,74,-1,0,0,0,0,0,3,-48,-17,-17,59,44,-1,0,0,0,0,0,-3,-32,-53,-53,24,29,-1,0,0,0,0,0,-3,-25,-91,-91,15,21,-1,0,0,0,0,0,-7,-1,103,103,0,13,-1,0,0,0,0,0,-2,-31,-28,-28,26,28,-1,0,0,0,0,0,-110,-78,-72,55,126,-72,-1,0,0,0,0,0,83,-109,-81,77,-81,74,-1,0,0,0,0,0,-2,-31,-28,-28,26,28,-1,0,0,0,0,0,-110,-78,-72,55,126,-72,-1,0,0,0,0,0,83,-109,-81,77,-81,74,-1,0,0,0,0,0,-49,-124,-93,-104,78,-93,-1,0,0,0,0,0,-2,-31,-28,-28,26,28,-1,0,0,0,0,0,-110,-78,-72,55,126,-72,-1,0,0,0,0,0,83,-109,-81,77,-81,74,-1,0,0,0,0,0,-49,-124,-93,-104,78,-93,-1,0,0,0,0,0,21,-1,-1,-1,127,0,-1,0,0,0,0,0,-2,-31,-28,-28,26,28,-1,0,0,0,0,0,-110,-78,-72,55,126,-72,-1,0,0,0,0,0,83,-109,-81,77,-81,74,-1,0,0,0,0,0,-49,-124,-93,-104,78,-93,-1,0,0,0,0,0,21,-1,-1,-1,127,0,-1,0,0,0,0,0,42,-52,-1,-1,-1,51,-1,0,0,0,0,0,-2,-31,-28,-28,26,28,-1,0,0,0,0,0,-110,-78,-72,55,126,-72,-1,0,0,0,0,0,83,-109,-81,77,-81,74,-1,0,0,0,0,0,-49,-124,-93,-104,78,-93,-1,0,0,0,0,0,21,-1,-1,-1,127,0,-1,0,0,0,0,0,42,-52,-1,-1,-1,51,-1,0,0,0,0,0,15,-63,-90,-90,86,40,-1,0,0,0,0,0,-2,-31,-28,-28,26,28,-1,0,0,0,0,0,-110,-78,-72,55,126,-72,-1,0,0,0,0,0,83,-109,-81,77,-81,74,-1,0,0,0,0,0,-49,-124,-93,-104,78,-93,-1,0,0,0,0,0,21,-1,-1,-1,127,0,-1,0,0,0,0,0,42,-52,-1,-1,-1,51,-1,0,0,0,0,0,15,-63,-90,-90,86,40,-1,0,0,0,0,0,-24,121,-9,-9,-127,-65,-1,0,0,0,0,0,-2,-31,-28,-28,26,28,-1,0,0,0,0,0,-110,-78,-72,55,126,-72,-1,0,0,0,0,0,83,-109,-81,77,-81,74,-1,0,0,0,0,0,-49,-124,-93,-104,78,-93,-1,0,0,0,0,0,21,-1,-1,-1,127,0,-1,0,0,0,0,0,42,-52,-1,-1,-1,51,-1,0,0,0,0,0,15,-63,-90,-90,86,40,-1,0,0,0,0,0,-24,121,-9,-9,-127,-65,-1,0,0,0,0,0,0,0,-103,-103,-103,-103,-1,0,0,0,0,0,114,120,-62,102,-62,-91,-1,0,0,0,0,0,11,-101,-4,-4,-115,98,-1,0,0,0,0,0,-100,77,-53,-115,-96,-53,-1,0,0,0,0,0,114,120,-62,102,-62,-91,-1,0,0,0,0,0,11,-101,-4,-4,-115,98,-1,0,0,0,0,0,-100,77,-53,-115,-96,-53,-1,0,0,0,0,0,-28,102,-25,-25,-118,-61,-1,0,0,0,0,0,114,120,-62,102,-62,-91,-1,0,0,0,0,0,11,-101,-4,-4,-115,98,-1,0,0,0,0,0,-100,77,-53,-115,-96,-53,-1,0,0,0,0,0,-28,102,-25,-25,-118,-61,-1,0,0,0,0,0,58,-101,-40,-90,-40,84,-1,0,0,0,0,0,114,120,-62,102,-62,-91,-1,0,0,0,0,0,11,-101,-4,-4,-115,98,-1,0,0,0,0,0,-100,77,-53,-115,-96,-53,-1,0,0,0,0,0,-28,102,-25,-25,-118,-61,-1,0,0,0,0,0,58,-101,-40,-90,-40,84,-1,0,0,0,0,0,34,-48,-1,-1,-39,47,-1,0,0,0,0,0,114,120,-62,102,-62,-91,-1,0,0,0,0,0,11,-101,-4,-4,-115,98,-1,0,0,0,0,0,-100,77,-53,-115,-96,-53,-1,0,0,0,0,0,-28,102,-25,-25,-118,-61,-1,0,0,0,0,0,58,-101,-40,-90,-40,84,-1,0,0,0,0,0,34,-48,-1,-1,-39,47,-1,0,0,0,0,0,25,90,-27,-27,-60,-108,-1,0,0,0,0,0,114,120,-62,102,-62,-91,-1,0,0,0,0,0,11,-101,-4,-4,-115,98,-1,0,0,0,0,0,-100,77,-53,-115,-96,-53,-1,0,0,0,0,0,-28,102,-25,-25,-118,-61,-1,0,0,0,0,0,58,-101,-40,-90,-40,84,-1,0,0,0,0,0,34,-48,-1,-1,-39,47,-1,0,0,0,0,0,25,90,-27,-27,-60,-108,-1,0,0,0,0,0,0,0,-77,-77,-77,-77,-1,0,0,0,0,0,120,84,-45,-115,-45,-57,-1,0,0,0,0,0,-45,82,-67,-68,-128,-67,-1,0,0,0,0,0,42,76,-1,-1,-1,-77,-1,0,0,0,0,0,-81,37,-38,-66,-70,-38,-1,0,0,0,0,0,4,-117,-5,-5,-128,114,-1,0,0,0,0,0,-112,100,-45,-128,-79,-45,-1,0,0,0,0,0,22,-100,-3,-3,-76,98,-1,0,0,0,0,0,58,-122,-34,-77,-34,105,-1,0,0,0,0,0,-23,47,-4,-4,-51,-27,-1,0,0,0,0,0,0,0,-39,-39,-39,-39,-1,0,0,0,0,0,120,84,-45,-115,-45,-57,-1,0,0,0,0,0,-45,82,-67,-68,-128,-67,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,42,76,-1,-1,-1,-77,-1,0,0,0,0,0,-81,37,-38,-66,-70,-38,-1,0,0,0,0,0,4,-117,-5,-5,-128,114,-1,0,0,0,0,0,-112,100,-45,-128,-79,-45,-1,0,0,0,0,0,22,-100,-3,-3,-76,98,-1,0,0,0,0,0,58,-122,-34,-77,-34,105,-1,0,0,0,0,0,-23,47,-4,-4,-51,-27,-1,0,0,0,0,0,0,0,-39,-39,-39,-39,-1,0,0,0,0,0,120,84,-45,-115,-45,-57,-1,0,0,0,0,0,-45,82,-67,-68,-128,-67,-1,0,0,0,0,0,77,41,-21,-52,-21,-59,-1,0,0,0,0,0,37,-112,-1,-1,-19,111,-1,0,0,0,0,0,42,76,-1,-1,-1,-77,-1,0,0,0,0,0,-81,37,-38,-66,-70,-38,-1,0,0,0,0,0,4,-117,-5,-5,-128,114,-1,0,0,0,0,0,-112,100,-45,-128,-79,-45,-1,0,0,0,0,0,22,-100,-3,-3,-76,98,-1,0,0,0,0,0,58,-122,-34,-77,-34,105,-1,0,0,0,0,0,-23,47,-4,-4,-51,-27,-1,0,0,0,0,0,0,0,-39,-39,-39,-39,-1,0,0,0,0,0,120,84,-45,-115,-45,-57,-1,0,0,0,0,0,42,76,-1,-1,-1,-77,-1,0,0,0,0,0,-81,37,-38,-66,-70,-38,-1,0,0,0,0,0,120,84,-45,-115,-45,-57,-1,0,0,0,0,0,42,76,-1,-1,-1,-77,-1,0,0,0,0,0,-81,37,-38,-66,-70,-38,-1,0,0,0,0,0,4,-117,-5,-5,-128,114,-1,0,0,0,0,0,120,84,-45,-115,-45,-57,-1,0,0,0,0,0,42,76,-1,-1,-1,-77,-1,0,0,0,0,0,-81,37,-38,-66,-70,-38,-1,0,0,0,0,0,4,-117,-5,-5,-128,114,-1,0,0,0,0,0,-112,100,-45,-128,-79,-45,-1,0,0,0,0,0,120,84,-45,-115,-45,-57,-1,0,0,0,0,0,42,76,-1,-1,-1,-77,-1,0,0,0,0,0,-81,37,-38,-66,-70,-38,-1,0,0,0,0,0,4,-117,-5,-5,-128,114,-1,0,0,0,0,0,-112,100,-45,-128,-79,-45,-1,0,0,0,0,0,22,-100,-3,-3,-76,98,-1,0,0,0,0,0,120,84,-45,-115,-45,-57,-1,0,0,0,0,0,42,76,-1,-1,-1,-77,-1,0,0,0,0,0,-81,37,-38,-66,-70,-38,-1,0,0,0,0,0,4,-117,-5,-5,-128,114,-1,0,0,0,0,0,-112,100,-45,-128,-79,-45,-1,0,0,0,0,0,22,-100,-3,-3,-76,98,-1,0,0,0,0,0,58,-122,-34,-77,-34,105,-1,0,0,0,0,0,120,84,-45,-115,-45,-57,-1,0,0,0,0,0,42,76,-1,-1,-1,-77,-1,0,0,0,0,0,-81,37,-38,-66,-70,-38,-1,0,0,0,0,0,4,-117,-5,-5,-128,114,-1,0,0,0,0,0,-112,100,-45,-128,-79,-45,-1,0,0,0,0,0,22,-100,-3,-3,-76,98,-1,0,0,0,0,0,58,-122,-34,-77,-34,105,-1,0,0,0,0,0,-23,47,-4,-4,-51,-27,-1,0,0,0,0,0,120,84,-45,-115,-45,-57,-1,0,0,0,0,0,42,76,-1,-1,-1,-77,-1,0,0,0,0,0,-81,37,-38,-66,-70,-38,-1,0,0,0,0,0,4,-117,-5,-5,-128,114,-1,0,0,0,0,0,-112,100,-45,-128,-79,-45,-1,0,0,0,0,0,22,-100,-3,-3,-76,98,-1,0,0,0,0,0,58,-122,-34,-77,-34,105,-1,0,0,0,0,0,-23,47,-4,-4,-51,-27,-1,0,0,0,0,0,0,0,-39,-39,-39,-39,-1,0,0,0,0,0,-19,-3,-98,-98,1,66,-1,0,0,0,0,0,-79,-126,-94,94,79,-94,-1,0,0,0,0,0,-6,-76,-43,-43,62,79,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,49,96,-11,-26,-11,-104,-1,0,0,0,0,0,79,65,-35,-85,-35,-92,-1,0,0,0,0,0,114,120,-62,102,-62,-91,-1,0,0,0,0,0,-113,-69,-67,50,-120,-67,-1,0,0,0,0,0,-19,-3,-98,-98,1,66,-1,0,0,0,0,0,-113,-69,-67,50,-120,-67,-1,0,0,0,0,0,-79,-126,-94,94,79,-94,-1,0,0,0,0,0,-6,-76,-43,-43,62,79,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,49,96,-11,-26,-11,-104,-1,0,0,0,0,0,79,65,-35,-85,-35,-92,-1,0,0,0,0,0,114,120,-62,102,-62,-91,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,81,77,-43,-103,-43,-108,-1,0,0,0,0,0,-2,-31,-41,-41,25,28,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,79,65,-35,-85,-35,-92,-1,0,0,0,0,0,-113,-60,-70,43,-125,-70,-1,0,0,0,0,0,-2,-31,-41,-41,25,28,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,79,65,-35,-85,-35,-92,-1,0,0,0,0,0,-113,-60,-70,43,-125,-70,-1,0,0,0,0,0,-6,-76,-43,-43,62,79,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,49,96,-11,-26,-11,-104,-1,0,0,0,0,0,81,77,-43,-103,-43,-108,-1,0,0,0,0,0,-113,-69,-67,50,-120,-67,-1,0,0,0,0,0,-6,-76,-43,-43,62,79,-1,0,0,0,0,0,13,-92,-4,-4,-115,89,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,49,96,-11,-26,-11,-104,-1,0,0,0,0,0,81,77,-43,-103,-43,-108,-1,0,0,0,0,0,-113,-69,-67,50,-120,-67,-1,0,0,0,0,0,-6,-76,-43,-43,62,79,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,49,96,-11,-26,-11,-104,-1,0,0,0,0,0,79,65,-35,-85,-35,-92,-1,0,0,0,0,0,114,120,-62,102,-62,-91,-1,0,0,0,0,0,-113,-69,-67,50,-120,-67,-1,0,0,0,0,0,-6,-76,-43,-43,62,79,-1,0,0,0,0,0,10,-72,-12,-12,109,67,-1,0,0,0,0,0,20,-99,-3,-3,-82,97,-1,0,0,0,0,0,31,115,-2,-2,-32,-117,-1,0,0,0,0,0,42,64,-1,-1,-1,-65,-1,0,0,0,0,0,49,96,-11,-26,-11,-104,-1,0,0,0,0,0,79,65,-35,-85,-35,-92,-1,0,0,0,0,0,114,120,-62,102,-62,-91,-1,0,0,0,0,0,-113,-69,-67,50,-120,-67,-1,0,0,0,0,0,-109,15,-1,-16,-8,-1,-1,0,0,0,0,0,24,35,-6,-6,-21,-41,-1,0,0,0,0,0,127,-1,-1,0,-1,-1,-1,0,0,0,0,0,113,-128,-1,127,-1,-44,-1,0,0,0,0,0,127,15,-1,-16,-1,-1,-1,0,0,0,0,0,42,26,-11,-11,-11,-36,-1,0,0,0,0,0,23,58,-1,-1,-28,-60,-1,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,25,49,-1,-1,-21,-51,-1,0,0,0,0,0,-86,-1,-1,0,0,-1,-1,0,0,0,0,0,-64,-50,-30,-118,43,-30,-1,0,0,0,0,0,0,-66,-91,-91,42,42,-1,0,0,0,0,0,23,99,-34,-34,-72,-121,-1,0,0,0,0,0,-128,103,-96,95,-98,-96,-1,0,0,0,0,0,63,-1,-1,127,-1,0,-1,0,0,0,0,0,17,-38,-46,-46,105,30,-1,0,0,0,0,0,11,-81,-1,-1,127,80,-1,0,0,0,0,0,-102,-109,-19,100,-107,-19,-1,0,0,0,0,0,33,34,-1,-1,-8,-36,-1,0,0,0,0,0,-10,-25,-36,-36,20,60,-1,0,0,0,0,0,127,-1,-1,0,-1,-1,-1,0,0,0,0,0,-86,-1,-117,0,0,-117,-1,0,0,0,0,0,127,-1,-117,0,-117,-117,-1,0,0,0,0,0,30,-17,-72,-72,-122,11,-1,0,0,0,0,0,0,0,-87,-87,-87,-87,-1,0,0,0,0,0,85,-1,100,0,100,0,-1,0,0,0,0,0,0,0,-87,-87,-87,-87,-1,0,0,0,0,0,39,110,-67,-67,-73,107,-1,0,0,0,0,0,-44,-1,-117,-117,0,-117,-1,0,0,0,0,0,58,-114,107,85,107,47,-1,0,0,0,0,0,23,-1,-1,-1,-116,0,-1,0,0,0,0,0,-58,-64,-52,-103,50,-52,-1,0,0,0,0,0,0,-1,-117,-117,0,0,-1,0,0,0,0,0,10,121,-23,-23,-106,122,-1,0,0,0,0,0,85,61,-68,-113,-68,-113,-1,0,0,0,0,0,-81,-113,-117,72,61,-117,-1,0,0,0,0,0,127,103,79,47,79,79,-1,0,0,0,0,0,127,103,79,47,79,79,-1,0,0,0,0,0,-128,-1,-47,0,-50,-47,-1,0,0,0,0,0,-57,-1,-45,-108,0,-45,-1,0,0,0,0,0,-24,-21,-1,-1,20,-109,-1,0,0,0,0,0,-118,-1,-1,0,-65,-1,-1,0,0,0,0,0,0,0,105,105,105,105,-1,0,0,0,0,0,0,0,105,105,105,105,-1,0,0,0,0,0,-108,-31,-1,30,-112,-1,-1,0,0,0,0,0,0,-50,-78,-78,34,34,-1,0,0,0,0,0,28,15,-1,-1,-6,-16,-1,0,0,0,0,0,85,-64,-117,34,-117,34,-1,0,0,0,0,0,-44,-1,-1,-1,0,-1,-1,0,0,0,0,0,0,0,-36,-36,-36,-36,-1,0,0,0,0,0,-86,7,-1,-8,-8,-1,-1,0,0,0,0,0,35,-1,-1,-1,-41,0,-1,0,0,0,0,0,30,-39,-38,-38,-91,32,-1,0,0,0,0,0,0,0,-128,-128,-128,-128,-1,0,0,0,0,0,85,-1,-128,0,-128,0,-1,0,0,0,0,0,59,-48,-1,-83,-1,47,-1,0,0,0,0,0,0,0,-128,-128,-128,-128,-1,0,0,0,0,0,85,15,-1,-16,-1,-16,-1,0,0,0,0,0,-23,-106,-1,-1,105,-76,-1,0,0,0,0,0,0,-116,-51,-51,92,92,-1,0,0,0,0,0,-62,-1,-126,75,0,-126,-1,0,0,0,0,0,42,15,-1,-1,-1,-16,-1,0,0,0,0,0,38,106,-16,-16,-26,-116,-1,0,0,0,0,0,-86,20,-6,-26,-26,-6,-1,0,0,0,0,0,-16,15,-1,-1,-16,-11,-1,0,0,0,0,0,64,-1,-4,124,-4,0,-1,0,0,0,0,0,38,49,-1,-1,-6,-51,-1,0,0,0,0,0,-119,63,-26,-83,-40,-26,-1,0,0,0,0,0,0,119,-16,-16,-128,-128,-1,0,0,0,0,0,127,31,-1,-32,-1,-1,-1,0,0,0,0,0,42,40,-6,-6,-6,-46,-1,0,0,0,0,0,0,0,-45,-45,-45,-45,-1,0,0,0,0,0,85,100,-18,-112,-18,-112,-1,0,0,0,0,0,0,0,-45,-45,-45,-45,-1,0,0,0,0,0,-8,73,-1,-1,-74,-63,-1,0,0,0,0,0,12,-124,-1,-1,-96,122,-1,0,0,0,0,0,125,-47,-78,32,-78,-86,-1,0,0,0,0,0,-113,117,-6,-121,-50,-6,-1,0,0,0,0,0,-108,56,-103,119,-120,-103,-1,0,0,0,0,0,-108,56,-103,119,-120,-103,-1,0,0,0,0,0,-105,52,-34,-80,-60,-34,-1,0,0,0,0,0,42,31,-1,-1,-1,-32,-1,0,0,0,0,0,85,-1,-1,0,-1,0,-1,0,0,0,0,0,85,-64,-51,50,-51,50,-1,0,0,0,0,0,21,20,-6,-6,-16,-26,-1,0,0,0,0,0,-44,-1,-1,-1,0,-1,-1,0,0,0,0,0,0,-1,-128,-128,0,0,-1,0,0,0,0,0,113,-128,-51,102,-51,-86,-1,0,0,0,0,0,-86,-1,-51,0,0,-51,-1,0,0,0,0,0,-52,-104,-45,-70,85,-45,-1,0,0,0,0,0,-73,124,-37,-109,112,-37,-1,0,0,0,0,0,103,-87,-77,60,-77,113,-1,0,0,0,0,0,-80,-113,-18,123,104,-18,-1,0,0,0,0,0,111,-1,-6,0,-6,-102,-1,0,0,0,0,0,125,-89,-47,72,-47,-52,-1,0,0,0,0,0,-28,-28,-57,-57,21,-123,-1,0,0,0,0,0,-86,-58,112,25,25,112,-1,0,0,0,0,0,106,9,-1,-11,-1,-6,-1,0,0,0,0,0,4,30,-1,-1,-28,-31,-1,0,0,0,0,0,26,73,-1,-1,-28,-75,-1,0,0,0,0,0,25,81,-1,-1,-34,-83,-1,0,0,0,0,0,-86,-1,-128,0,0,-128,-1,0,0,0,0,0,27,23,-3,-3,-11,-26,-1,0,0,0,0,0,42,-1,-128,-128,-128,0,-1,0,0,0,0,0,56,-64,-114,107,-114,35,-1,0,0,0,0,0,27,-1,-1,-1,-91,0,-1,0,0,0,0,0,11,-1,-1,-1,69,0,-1,0,0,0,0,0,-42,123,-38,-38,112,-42,-1,0,0,0,0,0,38,72,-18,-18,-24,-86,-1,0,0,0,0,0,85,100,-5,-104,-5,-104,-1,0,0,0,0,0,127,67,-18,-81,-18,-18,-1,0,0,0,0,0,-15,124,-37,-37,112,-109,-1,0,0,0,0,0,26,41,-1,-1,-17,-43,-1,0,0,0,0,0,20,70,-1,-1,-38,-71,-1,0,0,0,0,0,20,-80,-51,-51,-123,63,-1,0,0,0,0,0,-9,63,-1,-1,-64,-53,-1,0,0,0,0,0,-44,70,-35,-35,-96,-35,-1,0,0,0,0,0,-124,59,-26,-80,-32,-26,-1,0,0,0,0,0,-44,-1,-128,-128,0,-128,-1,0,0,0,0,0,0,-1,-1,-1,0,0,-1,0,0,0,0,0,0,61,-68,-68,-113,-113,-1,0,0,0,0,0,-97,-75,-31,65,105,-31,-1,0,0,0,0,0,17,-36,-117,-117,69,19,-1,0,0,0,0,0,4,-118,-6,-6,-128,114,-1,0,0,0,0,0,19,-102,-12,-12,-92,96,-1,0,0,0,0,0,103,-86,-117,46,-117,87,-1,0,0,0,0,0,17,16,-1,-1,-11,-18,-1,0,0,0,0,0,13,-73,-96,-96,82,45,-1,0,0,0,0,0,0,0,-64,-64,-64,-64,-1,0,0,0,0,0,-117,108,-21,-121,-50,-21,-1,0,0,0,0,0,-81,-113,-51,106,90,-51,-1,0,0,0,0,0,-108,56,-112,112,-128,-112,-1,0,0,0,0,0,-108,56,-112,112,-128,-112,-1,0,0,0,0,0,0,5,-1,-1,-6,-6,-1,0,0,0,0,0,106,-1,-1,0,-1,127,-1,0,0,0,0,0,-110,-101,-76,70,-126,-76,-1,0,0,0,0,0,24,84,-46,-46,-76,-116,-1,0,0,0,0,0,127,-1,-128,0,-128,-128,-1,0,0,0,0,0,-44,29,-40,-40,-65,-40,-1,0,0,0,0,0,6,-72,-1,-1,99,71,-1,0,0,0,0,0,123,-74,-32,64,-32,-48,-1,0,0,0,0,0,-44,115,-18,-18,-126,-18,-1,0,0,0,0,0,27,68,-11,-11,-34,-77,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,-11,-11,-11,-11,-1,0,0,0,0,0,42,-1,-1,-1,-1,0,-1,0,0,0,0,0,56,-64,-51,-102,-51,50,-1,0,0,0,0,0,45,67,-4,-9,-4,-71,-1,0,0,0,0,0,68,91,-35,-83,-35,-114,-1,0,0,0,0,0,98,-78,-93,49,-93,84,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,62,85,-26,-62,-26,-103,-1,0,0,0,0,0,85,100,-58,120,-58,121,-1,0,0,0,0,0,99,-69,-124,35,-124,67,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,62,85,-26,-62,-26,-103,-1,0,0,0,0,0,85,100,-58,120,-58,121,-1,0,0,0,0,0,98,-78,-93,49,-93,84,-1,0,0,0,0,0,107,-1,104,0,104,55,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,55,81,-16,-39,-16,-93,-1,0,0,0,0,0,68,91,-35,-83,-35,-114,-1,0,0,0,0,0,85,100,-58,120,-58,121,-1,0,0,0,0,0,98,-78,-93,49,-93,84,-1,0,0,0,0,0,107,-1,104,0,104,55,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,55,81,-16,-39,-16,-93,-1,0,0,0,0,0,68,91,-35,-83,-35,-114,-1,0,0,0,0,0,85,100,-58,120,-58,121,-1,0,0,0,0,0,96,-98,-85,65,-85,93,-1,0,0,0,0,0,99,-69,-124,35,-124,67,-1,0,0,0,0,0,108,-1,90,0,90,50,-1,0,0,0,0,0,42,25,-1,-1,-1,-27,-1,0,0,0,0,0,45,67,-4,-9,-4,-71,-1,0,0,0,0,0,55,81,-16,-39,-16,-93,-1,0,0,0,0,0,68,91,-35,-83,-35,-114,-1,0,0,0,0,0,85,100,-58,120,-58,121,-1,0,0,0,0,0,96,-98,-85,65,-85,93,-1,0,0,0,0,0,99,-69,-124,35,-124,67,-1,0,0,0,0,0,108,-1,90,0,90,50,-1,0,0,0,0,0,42,25,-1,-1,-1,-27,-1,0,0,0,0,0,45,67,-4,-9,-4,-71,-1,0,0,0,0,0,55,81,-16,-39,-16,-93,-1,0,0,0,0,0,68,91,-35,-83,-35,-114,-1,0,0,0,0,0,85,100,-58,120,-58,121,-1,0,0,0,0,0,96,-98,-85,65]).concat([-85,93,-1,0,0,0,0,0,99,-69,-124,35,-124,67,-1,0,0,0,0,0,107,-1,104,0,104,55,-1,0,0,0,0,0,110,-1,69,0,69,41,-1,0,0,0,0,0,49,73,-8,-19,-8,-79,-1,0,0,0,0,0,117,97,-51,127,-51,-69,-1,0,0,0,0,0,-112,-62,-72,44,127,-72,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,99,66,-38,-95,-38,-76,-1,0,0,0,0,0,-124,-86,-60,65,-74,-60,-1,0,0,0,0,0,-106,-53,-88,34,94,-88,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,99,66,-38,-95,-38,-76,-1,0,0,0,0,0,-124,-86,-60,65,-74,-60,-1,0,0,0,0,0,-112,-62,-72,44,127,-72,-1,0,0,0,0,0,-92,-65,-108,37,52,-108,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,69,58,-23,-57,-23,-76,-1,0,0,0,0,0,117,97,-51,127,-51,-69,-1,0,0,0,0,0,-124,-86,-60,65,-74,-60,-1,0,0,0,0,0,-112,-62,-72,44,127,-72,-1,0,0,0,0,0,-92,-65,-108,37,52,-108,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,69,58,-23,-57,-23,-76,-1,0,0,0,0,0,117,97,-51,127,-51,-69,-1,0,0,0,0,0,-124,-86,-60,65,-74,-60,-1,0,0,0,0,0,-117,-40,-64,29,-111,-64,-1,0,0,0,0,0,-106,-53,-88,34,94,-88,-1,0,0,0,0,0,-98,-25,-124,12,44,-124,-1,0,0,0,0,0,42,38,-1,-1,-1,-39,-1,0,0,0,0,0,49,73,-8,-19,-8,-79,-1,0,0,0,0,0,69,58,-23,-57,-23,-76,-1,0,0,0,0,0,117,97,-51,127,-51,-69,-1,0,0,0,0,0,-124,-86,-60,65,-74,-60,-1,0,0,0,0,0,-117,-40,-64,29,-111,-64,-1,0,0,0,0,0,-106,-53,-88,34,94,-88,-1,0,0,0,0,0,-98,-25,-124,12,44,-124,-1,0,0,0,0,0,42,38,-1,-1,-1,-39,-1,0,0,0,0,0,49,73,-8,-19,-8,-79,-1,0,0,0,0,0,69,58,-23,-57,-23,-76,-1,0,0,0,0,0,117,97,-51,127,-51,-69,-1,0,0,0,0,0,-124,-86,-60,65,-74,-60,-1,0,0,0,0,0,-117,-40,-64,29,-111,-64,-1,0,0,0,0,0,-106,-53,-88,34,94,-88,-1,0,0,0,0,0,-92,-65,-108,37,52,-108,-1,0,0,0,0,0,-98,-25,88,8,29,88,-1,0,0,0,0,0,37,66,-1,-1,-9,-68,-1,0,0,0,0,0,28,-81,-2,-2,-60,79,-1,0,0,0,0,0,16,-18,-39,-39,95,14,-1,0,0,0,0,0,42,42,-1,-1,-1,-44,-1,0,0,0,0,0,28,112,-2,-2,-39,-114,-1,0,0,0,0,0,22,-43,-2,-2,-103,41,-1,0,0,0,0,0,15,-4,-52,-52,76,2,-1,0,0,0,0,0,42,42,-1,-1,-1,-44,-1,0,0,0,0,0,28,112,-2,-2,-39,-114,-1,0,0,0,0,0,22,-43,-2,-2,-103,41,-1,0,0,0,0,0,16,-18,-39,-39,95,14,-1,0,0,0,0,0,13,-8,-103,-103,52,4,-1,0,0,0,0,0,42,42,-1,-1,-1,-44,-1,0,0,0,0,0,31,109,-2,-2,-29,-111,-1,0,0,0,0,0,28,-81,-2,-2,-60,79,-1,0,0,0,0,0,22,-43,-2,-2,-103,41,-1,0,0,0,0,0,16,-18,-39,-39,95,14,-1,0,0,0,0,0,13,-8,-103,-103,52,4,-1,0,0,0,0,0,42,42,-1,-1,-1,-44,-1,0,0,0,0,0,31,109,-2,-2,-29,-111,-1,0,0,0,0,0,28,-81,-2,-2,-60,79,-1,0,0,0,0,0,22,-43,-2,-2,-103,41,-1,0,0,0,0,0,18,-23,-20,-20,112,20,-1,0,0,0,0,0,15,-4,-52,-52,76,2,-1,0,0,0,0,0,12,-9,-116,-116,45,4,-1,0,0,0,0,0,42,25,-1,-1,-1,-27,-1,0,0,0,0,0,37,66,-1,-1,-9,-68,-1,0,0,0,0,0,31,109,-2,-2,-29,-111,-1,0,0,0,0,0,28,-81,-2,-2,-60,79,-1,0,0,0,0,0,22,-43,-2,-2,-103,41,-1,0,0,0,0,0,18,-23,-20,-20,112,20,-1,0,0,0,0,0,15,-4,-52,-52,76,2,-1,0,0,0,0,0,12,-9,-116,-116,45,4,-1,0,0,0,0,0,42,25,-1,-1,-1,-27,-1,0,0,0,0,0,37,66,-1,-1,-9,-68,-1,0,0,0,0,0,31,109,-2,-2,-29,-111,-1,0,0,0,0,0,28,-81,-2,-2,-60,79,-1,0,0,0,0,0,22,-43,-2,-2,-103,41,-1,0,0,0,0,0,18,-23,-20,-20,112,20,-1,0,0,0,0,0,15,-4,-52,-52,76,2,-1,0,0,0,0,0,13,-8,-103,-103,52,4,-1,0,0,0,0,0,13,-16,102,102,37,6,-1,0,0,0,0,0,34,95,-1,-1,-19,-96,-1,0,0,0,0,0,24,-78,-2,-2,-78,76,-1,0,0,0,0,0,5,-35,-16,-16,59,32,-1,0,0,0,0,0,42,77,-1,-1,-1,-78,-1,0,0,0,0,0,29,-94,-2,-2,-52,92,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,-2,-31,-29,-29,26,28,-1,0,0,0,0,0,42,77,-1,-1,-1,-78,-1,0,0,0,0,0,29,-94,-2,-2,-52,92,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,5,-35,-16,-16,59,32,-1,0,0,0,0,0,-10,-1,-67,-67,0,38,-1,0,0,0,0,0,42,77,-1,-1,-1,-78,-1,0,0,0,0,0,30,-120,-2,-2,-39,118,-1,0,0,0,0,0,24,-78,-2,-2,-78,76,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,5,-35,-16,-16,59,32,-1,0,0,0,0,0,-10,-1,-67,-67,0,38,-1,0,0,0,0,0,42,77,-1,-1,-1,-78,-1,0,0,0,0,0,30,-120,-2,-2,-39,118,-1,0,0,0,0,0,24,-78,-2,-2,-78,76,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,7,-44,-4,-4,78,42,-1,0,0,0,0,0,-2,-31,-29,-29,26,28,-1,0,0,0,0,0,-11,-1,-79,-79,0,38,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,34,95,-1,-1,-19,-96,-1,0,0,0,0,0,30,-120,-2,-2,-39,118,-1,0,0,0,0,0,24,-78,-2,-2,-78,76,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,7,-44,-4,-4,78,42,-1,0,0,0,0,0,-2,-31,-29,-29,26,28,-1,0,0,0,0,0,-11,-1,-79,-79,0,38,-1,0,0,0,0,0,42,50,-1,-1,-1,-52,-1,0,0,0,0,0,34,95,-1,-1,-19,-96,-1,0,0,0,0,0,30,-120,-2,-2,-39,118,-1,0,0,0,0,0,24,-78,-2,-2,-78,76,-1,0,0,0,0,0,17,-62,-3,-3,-115,60,-1,0,0,0,0,0,7,-44,-4,-4,78,42,-1,0,0,0,0,0,-2,-31,-29,-29,26,28,-1,0,0,0,0,0,-10,-1,-67,-67,0,38,-1,0,0,0,0,0,-14,-1,-128,-128,0,38,-1,0,0,0,0,0,-109,15,-1,-16,-8,-1,-1,0,0,0,0,0,24,35,-6,-6,-21,-41,-1,0,0,0,0,0,23,36,-1,-1,-17,-37,-1,0,0,0,0,0,23,36,-18,-18,-33,-52,-1,0,0,0,0,0,23,36,-51,-51,-64,-80,-1,0,0,0,0,0,24,34,-117,-117,-125,120,-1,0,0,0,0,0,113,-128,-1,127,-1,-44,-1,0,0,0,0,0,113,-128,-1,127,-1,-44,-1,0,0,0,0,0,113,-128,-18,118,-18,-58,-1,0,0,0,0,0,113,-128,-51,102,-51,-86,-1,0,0,0,0,0,113,-128,-117,69,-117,116,-1,0,0,0,0,0,127,15,-1,-16,-1,-1,-1,0,0,0,0,0,127,15,-1,-16,-1,-1,-1,0,0,0,0,0,127,15,-18,-32,-18,-18,-1,0,0,0,0,0,127,14,-51,-63,-51,-51,-1,0,0,0,0,0,127,14,-117,-125,-117,-117,-1,0,0,0,0,0,42,26,-11,-11,-11,-36,-1,0,0,0,0,0,23,58,-1,-1,-28,-60,-1,0,0,0,0,0,23,58,-1,-1,-28,-60,-1,0,0,0,0,0,23,58,-18,-18,-43,-73,-1,0,0,0,0,0,22,58,-51,-51,-73,-98,-1,0,0,0,0,0,23,58,-117,-117,125,107,-1,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,25,49,-1,-1,-21,-51,-1,0,0,0,0,0,-86,-1,-1,0,0,-1,-1,0,0,0,0,0,-86,-1,-1,0,0,-1,-1,0,0,0,0,0,-86,-1,-18,0,0,-18,-1,0,0,0,0,0,-86,-1,-51,0,0,-51,-1,0,0,0,0,0,-86,-1,-117,0,0,-117,-1,0,0,0,0,0,-64,-50,-30,-118,43,-30,-1,0,0,0,0,0,0,-66,-91,-91,42,42,-1,0,0,0,0,0,0,-65,-1,-1,64,64,-1,0,0,0,0,0,0,-65,-18,-18,59,59,-1,0,0,0,0,0,0,-65,-51,-51,51,51,-1,0,0,0,0,0,0,-66,-117,-117,35,35,-1,0,0,0,0,0,23,99,-34,-34,-72,-121,-1,0,0,0,0,0,23,100,-1,-1,-45,-101,-1,0,0,0,0,0,23,99,-18,-18,-59,-111,-1,0,0,0,0,0,23,99,-51,-51,-86,125,-1,0,0,0,0,0,23,99,-117,-117,115,85,-1,0,0,0,0,0,-128,103,-96,95,-98,-96,-1,0,0,0,0,0,-125,103,-1,-104,-11,-1,-1,0,0,0,0,0,-125,102,-18,-114,-27,-18,-1,0,0,0,0,0,-125,103,-51,122,-59,-51,-1,0,0,0,0,0,-125,102,-117,83,-122,-117,-1,0,0,0,0,0,63,-1,-1,127,-1,0,-1,0,0,0,0,0,63,-1,-1,127,-1,0,-1,0,0,0,0,0,63,-1,-18,118,-18,0,-1,0,0,0,0,0,63,-1,-51,102,-51,0,-1,0,0,0,0,0,63,-1,-117,69,-117,0,-1,0,0,0,0,0,17,-38,-46,-46,105,30,-1,0,0,0,0,0,17,-37,-1,-1,127,36,-1,0,0,0,0,0,17,-37,-18,-18,118,33,-1,0,0,0,0,0,17,-38,-51,-51,102,29,-1,0,0,0,0,0,17,-36,-117,-117,69,19,-1,0,0,0,0,0,11,-81,-1,-1,127,80,-1,0,0,0,0,0,7,-87,-1,-1,114,86,-1,0,0,0,0,0,6,-87,-18,-18,106,80,-1,0,0,0,0,0,6,-87,-51,-51,91,69,-1,0,0,0,0,0,6,-88,-117,-117,62,47,-1,0,0,0,0,0,-102,-109,-19,100,-107,-19,-1,0,0,0,0,0,33,34,-1,-1,-8,-36,-1,0,0,0,0,0,33,34,-1,-1,-8,-36,-1,0,0,0,0,0,34,35,-18,-18,-24,-51,-1,0,0,0,0,0,34,34,-51,-51,-56,-79,-1,0,0,0,0,0,35,34,-117,-117,-120,120,-1,0,0,0,0,0,-10,-25,-36,-36,20,60,-1,0,0,0,0,0,127,-1,-1,0,-1,-1,-1,0,0,0,0,0,127,-1,-1,0,-1,-1,-1,0,0,0,0,0,127,-1,-18,0,-18,-18,-1,0,0,0,0,0,127,-1,-51,0,-51,-51,-1,0,0,0,0,0,127,-1,-117,0,-117,-117,-1,0,0,0,0,0,30,-17,-72,-72,-122,11,-1,0,0,0,0,0,30,-16,-1,-1,-71,15,-1,0,0,0,0,0,30,-16,-18,-18,-83,14,-1,0,0,0,0,0,30,-16,-51,-51,-107,12,-1,0,0,0,0,0,30,-16,-117,-117,101,8,-1,0,0,0,0,0,85,-1,100,0,100,0,-1,0,0,0,0,0,39,110,-67,-67,-73,107,-1,0,0,0,0,0,58,-114,107,85,107,47,-1,0,0,0,0,0,58,-113,-1,-54,-1,112,-1,0,0,0,0,0,58,-113,-18,-68,-18,104,-1,0,0,0,0,0,58,-113,-51,-94,-51,90,-1,0,0,0,0,0,58,-113,-117,110,-117,61,-1,0,0,0,0,0,23,-1,-1,-1,-116,0,-1,0,0,0,0,0,21,-1,-1,-1,127,0,-1,0,0,0,0,0,21,-1,-18,-18,118,0,-1,0,0,0,0,0,21,-1,-51,-51,102,0,-1,0,0,0,0,0,21,-1,-117,-117,69,0,-1,0,0,0,0,0,-58,-64,-52,-103,50,-52,-1,0,0,0,0,0,-58,-63,-1,-65,62,-1,-1,0,0,0,0,0,-58,-64,-18,-78,58,-18,-1,0,0,0,0,0,-58,-64,-51,-102,50,-51,-1,0,0,0,0,0,-58,-64,-117,104,34,-117,-1,0,0,0,0,0,10,121,-23,-23,-106,122,-1,0,0,0,0,0,85,61,-68,-113,-68,-113,-1,0,0,0,0,0,85,62,-1,-63,-1,-63,-1,0,0,0,0,0,85,62,-18,-76,-18,-76,-1,0,0,0,0,0,85,62,-51,-101,-51,-101,-1,0,0,0,0,0,85,62,-117,105,-117,105,-1,0,0,0,0,0,-81,-113,-117,72,61,-117,-1,0,0,0,0,0,127,103,79,47,79,79,-1,0,0,0,0,0,127,104,-1,-105,-1,-1,-1,0,0,0,0,0,127,103,-18,-115,-18,-18,-1,0,0,0,0,0,127,104,-51,121,-51,-51,-1,0,0,0,0,0,127,104,-117,82,-117,-117,-1,0,0,0,0,0,127,103,79,47,79,79,-1,0,0,0,0,0,-128,-1,-47,0,-50,-47,-1,0,0,0,0,0,-57,-1,-45,-108,0,-45,-1,0,0,0,0,0,-24,-21,-1,-1,20,-109,-1,0,0,0,0,0,-24,-21,-1,-1,20,-109,-1,0,0,0,0,0,-24,-21,-18,-18,18,-119,-1,0,0,0,0,0,-24,-21,-51,-51,16,118,-1,0,0,0,0,0,-25,-20,-117,-117,10,80,-1,0,0,0,0,0,-118,-1,-1,0,-65,-1,-1,0,0,0,0,0,-118,-1,-1,0,-65,-1,-1,0,0,0,0,0,-118,-1,-18,0,-78,-18,-1,0,0,0,0,0,-118,-1,-51,0,-102,-51,-1,0,0,0,0,0,-118,-1,-117,0,104,-117,-1,0,0,0,0,0,0,0,105,105,105,105,-1,0,0,0,0,0,0,0,105,105,105,105,-1,0,0,0,0,0,-108,-31,-1,30,-112,-1,-1,0,0,0,0,0,-108,-31,-1,30,-112,-1,-1,0,0,0,0,0,-108,-31,-18,28,-122,-18,-1,0,0,0,0,0,-108,-31,-51,24,116,-51,-1,0,0,0,0,0,-108,-31,-117,16,78,-117,-1,0,0,0,0,0,0,-50,-78,-78,34,34,-1,0,0,0,0,0,0,-49,-1,-1,48,48,-1,0,0,0,0,0,0,-49,-18,-18,44,44,-1,0,0,0,0,0,0,-49,-51,-51,38,38,-1,0,0,0,0,0,0,-49,-117,-117,26,26,-1,0,0,0,0,0,28,15,-1,-1,-6,-16,-1,0,0,0,0,0,85,-64,-117,34,-117,34,-1,0,0,0,0,0,0,0,-36,-36,-36,-36,-1,0,0,0,0,0,-86,7,-1,-8,-8,-1,-1,0,0,0,0,0,35,-1,-1,-1,-41,0,-1,0,0,0,0,0,35,-1,-1,-1,-41,0,-1,0,0,0,0,0,35,-1,-18,-18,-55,0,-1,0,0,0,0,0,35,-1,-51,-51,-83,0,-1,0,0,0,0,0,35,-1,-117,-117,117,0,-1,0,0,0,0,0,30,-39,-38,-38,-91,32,-1,0,0,0,0,0,30,-38,-1,-1,-63,37,-1,0,0,0,0,0,30,-38,-18,-18,-76,34,-1,0,0,0,0,0,30,-38,-51,-51,-101,29,-1,0,0,0,0,0,30,-38,-117,-117,105,20,-1,0,0,0,0,0,0,0,-64,-64,-64,-64,-1,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,3,3,3,3,-1,0,0,0,0,0,0,0,26,26,26,26,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,28,28,28,28,-1,0,0,0,0,0,0,0,31,31,31,31,-1,0,0,0,0,0,0,0,33,33,33,33,-1,0,0,0,0,0,0,0,36,36,36,36,-1,0,0,0,0,0,0,0,38,38,38,38,-1,0,0,0,0,0,0,0,41,41,41,41,-1,0,0,0,0,0,0,0,43,43,43,43,-1,0,0,0,0,0,0,0,46,46,46,46,-1,0,0,0,0,0,0,0,48,48,48,48,-1,0,0,0,0,0,0,0,5,5,5,5,-1,0,0,0,0,0,0,0,51,51,51,51,-1,0,0,0,0,0,0,0,54,54,54,54,-1,0,0,0,0,0,0,0,56,56,56,56,-1,0,0,0,0,0,0,0,59,59,59,59,-1,0,0,0,0,0,0,0,61,61,61,61,-1,0,0,0,0,0,0,0,64,64,64,64,-1,0,0,0,0,0,0,0,66,66,66,66,-1,0,0,0,0,0,0,0,69,69,69,69,-1,0,0,0,0,0,0,0,71,71,71,71,-1,0,0,0,0,0,0,0,74,74,74,74,-1,0,0,0,0,0,0,0,8,8,8,8,-1,0,0,0,0,0,0,0,77,77,77,77,-1,0,0,0,0,0,0,0,79,79,79,79,-1,0,0,0,0,0,0,0,82,82,82,82,-1,0,0,0,0,0,0,0,84,84,84,84,-1,0,0,0,0,0,0,0,87,87,87,87,-1,0,0,0,0,0,0,0,89,89,89,89,-1,0,0,0,0,0,0,0,92,92,92,92,-1,0,0,0,0,0,0,0,94,94,94,94,-1,0,0,0,0,0,0,0,97,97,97,97,-1,0,0,0,0,0,0,0,99,99,99,99,-1,0,0,0,0,0,0,0,10,10,10,10,-1,0,0,0,0,0,0,0,102,102,102,102,-1,0,0,0,0,0,0,0,105,105,105,105,-1,0,0,0,0,0,0,0,107,107,107,107,-1,0,0,0,0,0,0,0,110,110,110,110,-1,0,0,0,0,0,0,0,112,112,112,112,-1,0,0,0,0,0,0,0,115,115,115,115,-1,0,0,0,0,0,0,0,117,117,117,117,-1,0,0,0,0,0,0,0,120,120,120,120,-1,0,0,0,0,0,0,0,122,122,122,122,-1,0,0,0,0,0,0,0,125,125,125,125,-1,0,0,0,0,0,0,0,13,13,13,13,-1,0,0,0,0,0,0,0,127,127,127,127,-1,0,0,0,0,0,0,0,-126,-126,-126,-126,-1,0,0,0,0,0,0,0,-123,-123,-123,-123,-1,0,0,0,0,0,0,0,-121,-121,-121,-121,-1,0,0,0,0,0,0,0,-118,-118,-118,-118,-1,0,0,0,0,0,0,0,-116,-116,-116,-116,-1,0,0,0,0,0,0,0,-113,-113,-113,-113,-1,0,0,0,0,0,0,0,-111,-111,-111,-111,-1,0,0,0,0,0,0,0,-108,-108,-108,-108,-1,0,0,0,0,0,0,0,-106,-106,-106,-106,-1,0,0,0,0,0,0,0,15,15,15,15,-1,0,0,0,0,0,0,0,-103,-103,-103,-103,-1,0,0,0,0,0,0,0,-100,-100,-100,-100,-1,0,0,0,0,0,0,0,-98,-98,-98,-98,-1,0,0,0,0,0,0,0,-95,-95,-95,-95,-1,0,0,0,0,0,0,0,-93,-93,-93,-93,-1,0,0,0,0,0,0,0,-90,-90,-90,-90,-1,0,0,0,0,0,0,0,-88,-88,-88,-88,-1,0,0,0,0,0,0,0,-85,-85,-85,-85,-1,0,0,0,0,0,0,0,-83,-83,-83,-83,-1,0,0,0,0,0,0,0,-80,-80,-80,-80,-1,0,0,0,0,0,0,0,18,18,18,18,-1,0,0,0,0,0,0,0,-77,-77,-77,-77,-1,0,0,0,0,0,0,0,-75,-75,-75,-75,-1,0,0,0,0,0,0,0,-72,-72,-72,-72,-1,0,0,0,0,0,0,0,-70,-70,-70,-70,-1,0,0,0,0,0,0,0,-67,-67,-67,-67,-1,0,0,0,0,0,0,0,-65,-65,-65,-65,-1,0,0,0,0,0,0,0,-62,-62,-62,-62,-1,0,0,0,0,0,0,0,-60,-60,-60,-60,-1,0,0,0,0,0,0,0,-57,-57,-57,-57,-1,0,0,0,0,0,0,0,-55,-55,-55,-55,-1,0,0,0,0,0,0,0,20,20,20,20,-1,0,0,0,0,0,0,0,-52,-52,-52,-52,-1,0,0,0,0,0,0,0,-49,-49,-49,-49,-1,0,0,0,0,0,0,0,-47,-47,-47,-47,-1,0,0,0,0,0,0,0,-44,-44,-44,-44,-1,0,0,0,0,0,0,0,-42,-42,-42,-42,-1,0,0,0,0,0,0,0,-39,-39,-39,-39,-1,0,0,0,0,0,0,0,-37,-37,-37,-37,-1,0,0,0,0,0,0,0,-34,-34,-34,-34,-1,0,0,0,0,0,0,0,-32,-32,-32,-32,-1,0,0,0,0,0,0,0,-29,-29,-29,-29,-1,0,0,0,0,0,0,0,23,23,23,23,-1,0,0,0,0,0,0,0,-27,-27,-27,-27,-1,0,0,0,0,0,0,0,-24,-24,-24,-24,-1,0,0,0,0,0,0,0,-21,-21,-21,-21,-1,0,0,0,0,0,0,0,-19,-19,-19,-19,-1,0,0,0,0,0,0,0,-16,-16,-16,-16,-1,0,0,0,0,0,0,0,-14,-14,-14,-14,-1,0,0,0,0,0,0,0,-11,-11,-11,-11,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,0,0,-6,-6,-6,-6,-1,0,0,0,0,0,0,0,-4,-4,-4,-4,-1,0,0,0,0,0,85,-1,-1,0,-1,0,-1,0,0,0,0,0,85,-1,-1,0,-1,0,-1,0,0,0,0,0,85,-1,-18,0,-18,0,-1,0,0,0,0,0,85,-1,-51,0,-51,0,-1,0,0,0,0,0,85,-1,-117,0,-117,0,-1,0,0,0,0,0,59,-48,-1,-83,-1,47,-1,0,0,0,0,0,0,0,-64,-64,-64,-64,-1,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,3,3,3,3,-1,0,0,0,0,0,0,0,26,26,26,26,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,28,28,28,28,-1,0,0,0,0,0,0,0,31,31,31,31,-1,0,0,0,0,0,0,0,33,33,33,33,-1,0,0,0,0,0,0,0,36,36,36,36,-1,0,0,0,0,0,0,0,38,38,38,38,-1,0,0,0,0,0,0,0,41,41,41,41,-1,0,0,0,0,0,0,0,43,43,43,43,-1,0,0,0,0,0,0,0,46,46,46,46,-1,0,0,0,0,0,0,0,48,48,48,48,-1,0,0,0,0,0,0,0,5,5,5,5,-1,0,0,0,0,0,0,0,51,51,51,51,-1,0,0,0,0,0,0,0,54,54,54,54,-1,0,0,0,0,0,0,0,56,56,56,56,-1,0,0,0,0,0,0,0,59,59,59,59,-1,0,0,0,0,0,0,0,61,61,61,61,-1,0,0,0,0,0,0,0,64,64,64,64,-1,0,0,0,0,0,0,0,66,66,66,66,-1,0,0,0,0,0,0,0,69,69,69,69,-1,0,0,0,0,0,0,0,71,71,71,71,-1,0,0,0,0,0,0,0,74,74,74,74,-1,0,0,0,0,0,0,0,8,8,8,8,-1,0,0,0,0,0,0,0,77,77,77,77,-1,0,0,0,0,0,0,0,79,79,79,79,-1,0,0,0,0,0,0,0,82,82,82,82,-1,0,0,0,0,0,0,0,84,84,84,84,-1,0,0,0,0,0,0,0,87,87,87,87,-1,0,0,0,0,0,0,0,89,89,89,89,-1,0,0,0,0,0,0,0,92,92,92,92,-1,0,0,0,0,0,0,0,94,94,94,94,-1,0,0,0,0,0,0,0,97,97,97,97,-1,0,0,0,0,0,0,0,99,99,99,99,-1,0,0,0,0,0,0,0,10,10,10,10,-1,0,0,0,0,0,0,0,102,102,102,102,-1,0,0,0,0,0,0,0,105,105,105,105,-1,0,0,0,0,0,0,0,107,107,107,107,-1,0,0,0,0,0,0,0,110,110,110,110,-1,0,0,0,0,0,0,0,112,112,112,112,-1,0,0,0,0,0,0,0,115,115,115,115,-1,0,0,0,0,0,0,0,117,117,117,117,-1,0,0,0,0,0,0,0,120,120,120,120,-1,0,0,0,0,0,0,0,122,122,122,122,-1,0,0,0,0,0,0,0,125,125,125,125,-1,0,0,0,0,0,0,0,13,13,13,13,-1,0,0,0,0,0,0,0,127,127,127,127,-1,0,0,0,0,0,0,0,-126,-126,-126,-126,-1,0,0,0,0,0,0,0,-123,-123,-123,-123,-1,0,0,0,0,0,0,0,-121,-121,-121,-121,-1,0,0,0,0,0,0,0,-118,-118,-118,-118,-1,0,0,0,0,0,0,0,-116,-116,-116,-116,-1,0,0,0,0,0,0,0,-113,-113,-113,-113,-1,0,0,0,0,0,0,0,-111,-111,-111,-111,-1,0,0,0,0,0,0,0,-108,-108,-108,-108,-1,0,0,0,0,0,0,0,-106,-106,-106,-106,-1,0,0,0,0,0,0,0,15,15,15,15,-1,0,0,0,0,0,0,0,-103,-103,-103,-103,-1,0,0,0,0,0,0,0,-100,-100,-100,-100,-1,0,0,0,0,0,0,0,-98,-98,-98,-98,-1,0,0,0,0,0,0,0,-95,-95,-95,-95,-1,0,0,0,0,0,0,0,-93,-93,-93,-93,-1,0,0,0,0,0,0,0,-90,-90,-90,-90,-1,0,0,0,0,0,0,0,-88,-88,-88,-88,-1,0,0,0,0,0,0,0,-85,-85,-85,-85,-1,0,0,0,0,0,0,0,-83,-83,-83,-83,-1,0,0,0,0,0,0,0,-80,-80,-80,-80,-1,0,0,0,0,0,0,0,18,18,18,18,-1,0,0,0,0,0,0,0,-77,-77,-77,-77,-1,0,0,0,0,0,0,0,-75,-75,-75,-75,-1,0,0,0,0,0,0,0,-72,-72,-72,-72,-1,0,0,0,0,0,0,0,-70,-70,-70,-70,-1,0,0,0,0,0,0,0,-67,-67,-67,-67,-1,0,0,0,0,0,0,0,-65,-65,-65,-65,-1,0,0,0,0,0,0,0,-62,-62,-62,-62,-1,0,0,0,0,0,0,0,-60,-60,-60,-60,-1,0,0,0,0,0,0,0,-57,-57,-57,-57,-1,0,0,0,0,0,0,0,-55,-55,-55,-55,-1,0,0,0,0,0,0,0,20,20,20,20,-1,0,0,0,0,0,0,0,-52,-52,-52,-52,-1,0,0,0,0,0,0,0,-49,-49,-49,-49,-1,0,0,0,0,0,0,0,-47,-47,-47,-47,-1,0,0,0,0,0,0,0,-44,-44,-44,-44,-1,0,0,0,0,0,0,0,-42,-42,-42,-42,-1,0,0,0,0,0,0,0,-39,-39,-39,-39,-1,0,0,0,0,0,0,0,-37,-37,-37,-37,-1,0,0,0,0,0,0,0,-34,-34,-34,-34,-1,0,0,0,0,0,0,0,-32,-32,-32,-32,-1,0,0,0,0,0,0,0,-29,-29,-29,-29,-1,0,0,0,0,0,0,0,23,23,23,23,-1,0,0,0,0,0,0,0,-27,-27,-27,-27,-1,0,0,0,0,0,0,0,-24,-24,-24,-24,-1,0,0,0,0,0,0,0,-21,-21,-21,-21,-1,0,0,0,0,0,0,0,-19,-19,-19,-19,-1,0,0,0,0,0,0,0,-16,-16,-16,-16,-1,0,0,0,0,0,0,0,-14,-14,-14,-14,-1,0,0,0,0,0,0,0,-11,-11,-11,-11,-1,0,0,0,0,0,0,0,-9,-9,-9,-9,-1,0,0,0,0,0,0,0,-6,-6,-6,-6,-1,0,0,0,0,0,0,0,-4,-4,-4,-4,-1,0,0,0,0,0,85,15,-1,-16,-1,-16,-1,0,0,0,0,0,85,15,-1,-16,-1,-16,-1,0,0,0,0,0,85,15,-18,-32,-18,-32,-1,0,0,0,0,0,85,14,-51,-63,-51,-63,-1,0,0,0,0,0,85,14,-117,-125,-117,-125,-1,0,0,0,0,0,-23,-106,-1,-1,105,-76,-1,0,0,0,0,0,-22,-111,-1,-1,110,-76,-1,0,0,0,0,0,-21,-115,-18,-18,106,-89,-1,0,0,0,0,0,-20,-121,-51,-51,96,-112,-1,0,0,0,0,0,-22,-108,-117,-117,58,98,-1,0,0,0,0,0,0,-116,-51,-51,92,92,-1,0,0,0,0,0,0,-108,-1,-1,106,106,-1,0,0,0,0,0,0,-108,-18,-18,99,99,-1,0,0,0,0,0,0,-107,-51,-51,85,85,-1,0,0,0,0,0,0,-108,-117,-117,58,58,-1,0,0,0,0,0,-62,-1,-126,75,0,-126,-1,0,0,0,0,0,42,0,-1,-1,-1,-2,0,0,0,0,0,0,42,15,-1,-1,-1,-16,-1,0,0,0,0,0,42,15,-1,-1,-1,-16,-1,0,0,0,0,0,42,15,-18,-18,-18,-32,-1,0,0,0,0,0,42,14,-51,-51,-51,-63,-1,0,0,0,0,0,42,14,-117,-117,-117,-125,-1,0,0,0,0,0,38,106,-16,-16,-26,-116,-1,0,0,0,0,0,39,112,-1,-1,-10,-113,-1,0,0,0,0,0,39,112,-18,-18,-26,-123,-1,0,0,0,0,0,39,111,-51,-51,-58,115,-1,0,0,0,0,0,39,111,-117,-117,-122,78,-1,0,0,0,0,0,-86,20,-6,-26,-26,-6,-1,0,0,0,0,0,-16,15,-1,-1,-16,-11,-1,0,0,0,0,0,-16,15,-1,-1,-16,-11,-1,0,0,0,0,0,-17,15,-18,-18,-32,-27,-1,0,0,0,0,0,-16,14,-51,-51,-63,-59,-1,0,0,0,0,0,-17,14,-117,-117,-125,-122,-1,0,0,0,0,0,64,-1,-4,124,-4,0,-1,0,0,0,0,0,38,49,-1,-1,-6,-51,-1,0,0,0,0,0,38,49,-1,-1,-6,-51,-1,0,0,0,0,0,37,50,-18,-18,-23,-65,-1,0,0,0,0,0,38,49,-51,-51,-55,-91,-1,0,0,0,0,0,39,49,-117,-117,-119,112,-1,0,0,0,0,0,-119,63,-26,-83,-40,-26,-1,0,0,0,0,0,-118,64,-1,-65,-17,-1,-1,0,0,0,0,0,-118,64,-18,-78,-33,-18,-1,0,0,0,0,0,-118,63,-51,-102,-64,-51,-1,0,0,0,0,0,-119,64,-117,104,-125,-117,-1,0,0,0,0,0,0,119,-16,-16,-128,-128,-1,0,0,0,0,0,127,31,-1,-32,-1,-1,-1,0,0,0,0,0,127,31,-1,-32,-1,-1,-1,0,0,0,0,0,127,31,-18,-47,-18,-18,-1,0,0,0,0,0,127,31,-51,-76,-51,-51,-1,0,0,0,0,0,127,31,-117,122,-117,-117,-1,0,0,0,0,0,35,115,-18,-18,-35,-126,-1,0,0,0,0,0,35,116,-1,-1,-20,-117,-1,0,0,0,0,0,35,115,-18,-18,-36,-126,-1,0,0,0,0,0,35,115,-51,-51,-66,112,-1,0,0,0,0,0,35,115,-117,-117,-127,76,-1,0,0,0,0,0,42,40,-6,-6,-6,-46,-1,0,0,0,0,0,0,0,-45,-45,-45,-45,-1,0,0,0,0,0,0,0,-45,-45,-45,-45,-1,0,0,0,0,0,-8,73,-1,-1,-74,-63,-1,0,0,0,0,0,-7,81,-1,-1,-82,-71,-1,0,0,0,0,0,-8,81,-18,-18,-94,-83,-1,0,0,0,0,0,-7,80,-51,-51,-116,-107,-1,0,0,0,0,0,-7,80,-117,-117,95,101,-1,0,0,0,0,0,12,-124,-1,-1,-96,122,-1,0,0,0,0,0,12,-124,-1,-1,-96,122,-1,0,0,0,0,0,11,-124,-18,-18,-107,114,-1,0,0,0,0,0,12,-123,-51,-51,-127,98,-1,0,0,0,0,0,12,-123,-117,-117,87,66,-1,0,0,0,0,0,125,-47,-78,32,-78,-86,-1,0,0,0,0,0,-113,117,-6,-121,-50,-6,-1,0,0,0,0,0,-113,79,-1,-80,-30,-1,-1,0,0,0,0,0,-113,79,-18,-92,-45,-18,-1,0,0,0,0,0,-114,79,-51,-115,-74,-51,-1,0,0,0,0,0,-113,78,-117,96,123,-117,-1,0,0,0,0,0,-81,-113,-1,-124,112,-1,-1,0,0,0,0,0,-108,56,-103,119,-120,-103,-1,0,0,0,0,0,-108,56,-103,119,-120,-103,-1,0,0,0,0,0,-105,52,-34,-80,-60,-34,-1,0,0,0,0,0,-105,53,-1,-54,-31,-1,-1,0,0,0,0,0,-105,53,-18,-68,-46,-18,-1,0,0,0,0,0,-105,53,-51,-94,-75,-51,-1,0,0,0,0,0,-106,53,-117,110,123,-117,-1,0,0,0,0,0,42,31,-1,-1,-1,-32,-1,0,0,0,0,0,42,31,-1,-1,-1,-32,-1,0,0,0,0,0,42,31,-18,-18,-18,-47,-1,0,0,0,0,0,42,31,-51,-51,-51,-76,-1,0,0,0,0,0,42,31,-117,-117,-117,122,-1,0,0,0,0,0,85,-64,-51,50,-51,50,-1,0,0,0,0,0,21,20,-6,-6,-16,-26,-1,0,0,0,0,0,-44,-1,-1,-1,0,-1,-1,0,0,0,0,0,-44,-1,-1,-1,0,-1,-1,0,0,0,0,0,-44,-1,-18,-18,0,-18,-1,0,0,0,0,0,-44,-1,-51,-51,0,-51,-1,0,0,0,0,0,-44,-1,-117,-117,0,-117,-1,0,0,0,0,0,-17,-71,-80,-80,48,96,-1,0,0,0,0,0,-28,-53,-1,-1,52,-77,-1,0,0,0,0,0,-28,-53,-18,-18,48,-89,-1,0,0,0,0,0,-28,-52,-51,-51,41,-112,-1,0,0,0,0,0,-28,-53,-117,-117,28,98,-1,0,0,0,0,0,113,-128,-51,102,-51,-86,-1,0,0,0,0,0,-86,-1,-51,0,0,-51,-1,0,0,0,0,0,-52,-104,-45,-70,85,-45,-1,0,0,0,0,0,-53,-103,-1,-32,102,-1,-1,0,0,0,0,0,-53,-103,-18,-47,95,-18,-1,0,0,0,0,0,-53,-103,-51,-76,82,-51,-1,0,0,0,0,0,-53,-102,-117,122,55,-117,-1,0,0,0,0,0,-73,124,-37,-109,112,-37,-1,0,0,0,0,0,-73,125,-1,-85,-126,-1,-1,0,0,0,0,0,-73,125,-18,-97,121,-18,-1,0,0,0,0,0,-73,125,-51,-119,104,-51,-1,0,0,0,0,0,-73,124,-117,93,71,-117,-1,0,0,0,0,0,103,-87,-77,60,-77,113,-1,0,0,0,0,0,-80,-113,-18,123,104,-18,-1,0,0,0,0,0,111,-1,-6,0,-6,-102,-1,0,0,0,0,0,125,-89,-47,72,-47,-52,-1,0,0,0,0,0,-28,-28,-57,-57,21,-123,-1,0,0,0,0,0,-86,-58,112,25,25,112,-1,0,0,0,0,0,106,9,-1,-11,-1,-6,-1,0,0,0,0,0,4,30,-1,-1,-28,-31,-1,0,0,0,0,0,4,30,-1,-1,-28,-31,-1,0,0,0,0,0,4,30,-18,-18,-43,-46,-1,0,0,0,0,0,3,29,-51,-51,-73,-75,-1,0,0,0,0,0,5,29,-117,-117,125,123,-1,0,0,0,0,0,26,73,-1,-1,-28,-75,-1,0,0,0,0,0,25,81,-1,-1,-34,-83,-1,0,0,0,0,0,25,81,-1,-1,-34,-83,-1,0,0,0,0,0,25,82,-18,-18,-49,-95,-1,0,0,0,0,0,25,82,-51,-51,-77,-117,-1,0,0,0,0,0,25,82,-117,-117,121,94,-1,0,0,0,0,0,-86,-1,-128,0,0,-128,-1,0,0,0,0,0,-86,-1,-128,0,0,-128,-1,0,0,0,0,0,42,0,-1,-1,-1,-2,0,0,0,0,0,0,27,23,-3,-3,-11,-26,-1,0,0,0,0,0,56,-64,-114,107,-114,35,-1,0,0,0,0,0,56,-63,-1,-64,-1,62,-1,0,0,0,0,0,56,-64,-18,-77,-18,58,-1,0,0,0,0,0,56,-64,-51,-102,-51,50,-1,0,0,0,0,0,56,-64,-117,105,-117,34,-1,0,0,0,0,0,27,-1,-1,-1,-91,0,-1,0,0,0,0,0,27,-1,-1,-1,-91,0,-1,0,0,0,0,0,27,-1,-18,-18,-102,0,-1,0,0,0,0,0,27,-1,-51,-51,-123,0,-1,0,0,0,0,0,27,-1,-117,-117,90,0,-1,0,0,0,0,0,11,-1,-1,-1,69,0,-1,0,0,0,0,0,11,-1,-1,-1,69,0,-1,0,0,0,0,0,11,-1,-18,-18,64,0,-1,0,0,0,0,0,11,-1,-51,-51,55,0,-1,0,0,0,0,0,11,-1,-117,-117,37,0,-1,0,0,0,0,0,-42,123,-38,-38,112,-42,-1,0,0,0,0,0,-42,124,-1,-1,-125,-6,-1,0,0,0,0,0,-42,124,-18,-18,122,-23,-1,0,0,0,0,0,-42,124,-51,-51,105,-55,-1,0,0,0,0,0,-43,124,-117,-117,71,-119,-1,0,0,0,0,0,38,72,-18,-18,-24,-86,-1,0,0,0,0,0,85,100,-5,-104,-5,-104,-1,0,0,0,0,0,85,101,-1,-102,-1,-102,-1,0,0,0,0,0,85,100,-18,-112,-18,-112,-1,0,0,0,0,0,85,100,-51,124,-51,124,-1,0,0,0,0,0,85,100,-117,84,-117,84,-1,0,0,0,0,0,127,67,-18,-81,-18,-18,-1,0,0,0,0,0,127,68,-1,-69,-1,-1,-1,0,0,0,0,0,127,68,-18,-82,-18,-18,-1,0,0,0,0,0,127,68,-51,-106,-51,-51,-1,0,0,0,0,0,127,67,-117,102,-117,-117,-1,0,0,0,0,0,-15,124,-37,-37,112,-109,-1,0,0,0,0,0,-15,125,-1,-1,-126,-85,-1,0,0,0,0,0,-15,125,-18,-18,121,-97,-1,0,0,0,0,0,-15,125,-51,-51,104,-119,-1,0,0,0,0,0,-15,124,-117,-117,71,93,-1,0,0,0,0,0,26,41,-1,-1,-17,-43,-1,0,0,0,0,0,20,70,-1,-1,-38,-71,-1,0,0,0,0,0,20,70,-1,-1,-38,-71,-1,0,0,0,0,0,19,69,-18,-18,-53,-83,-1,0,0,0,0,0,19,69,-51,-51,-81,-107,-1,0,0,0,0,0,20,69,-117,-117,119,101,-1,0,0,0,0,0,20,-80,-51,-51,-123,63,-1,0,0,0,0,0,-9,63,-1,-1,-64,-53,-1,0,0,0,0,0,-11,73,-1,-1,-75,-59,-1,0,0,0,0,0,-11,73,-18,-18,-87,-72,-1,0,0,0,0,0,-11,74,-51,-51,-111,-98,-1,0,0,0,0,0,-11,73,-117,-117,99,108,-1,0,0,0,0,0,-44,70,-35,-35,-96,-35,-1,0,0,0,0,0,-44,68,-1,-1,-69,-1,-1,0,0,0,0,0,-44,68,-18,-18,-82,-18,-1,0,0,0,0,0,-44,68,-51,-51,-106,-51,-1,0,0,0,0,0,-44,67,-117,-117,102,-117,-1,0,0,0,0,0,-124,59,-26,-80,-32,-26,-1,0,0,0,0,0,-60,-35,-16,-96,32,-16,-1,0,0,0,0,0,-65,-49,-1,-101,48,-1,-1,0,0,0,0,0,-64,-49,-18,-111,44,-18,-1,0,0,0,0,0,-64,-49,-51,125,38,-51,-1,0,0,0,0,0,-64,-49,-117,85,26,-117,-1,0,0,0,0,0,0,-1,-1,-1,0,0,-1,0,0,0,0,0,0,-1,-1,-1,0,0,-1,0,0,0,0,0,0,-1,-18,-18,0,0,-1,0,0,0,0,0,0,-1,-51,-51,0,0,-1,0,0,0,0,0,0,-1,-117,-117,0,0,-1,0,0,0,0,0,0,61,-68,-68,-113,-113,-1,0,0,0,0,0,0,62,-1,-1,-63,-63,-1,0,0,0,0,0,0,62,-18,-18,-76,-76,-1,0,0,0,0,0,0,62,-51,-51,-101,-101,-1,0,0,0,0,0,0,62,-117,-117,105,105,-1,0,0,0,0,0,-97,-75,-31,65,105,-31,-1,0,0,0,0,0,-97,-73,-1,72,118,-1,-1,0,0,0,0,0,-97,-73,-18,67,110,-18,-1,0,0,0,0,0,-97,-74,-51,58,95,-51,-1,0,0,0,0,0,-97,-73,-117,39,64,-117,-1,0,0,0,0,0,17,-36,-117,-117,69,19,-1,0,0,0,0,0,4,-118,-6,-6,-128,114,-1,0,0,0,0,0,9,-106,-1,-1,-116,105,-1,0,0,0,0,0,9,-106,-18,-18,-126,98,-1,0,0,0,0,0,9,-106,-51,-51,112,84,-1,0,0,0,0,0,9,-106,-117,-117,76,57,-1,0,0,0,0,0,19,-102,-12,-12,-92,96,-1,0,0,0,0,0,103,-86,-117,46,-117,87,-1,0,0,0,0,0,103,-85,-1,84,-1,-97,-1,0,0,0,0,0,103,-85,-18,78,-18,-108,-1,0,0,0,0,0,103,-85,-51,67,-51,-128,-1,0,0,0,0,0,103,-86,-117,46,-117,87,-1,0,0,0,0,0,17,16,-1,-1,-11,-18,-1,0,0,0,0,0,17,16,-1,-1,-11,-18,-1,0,0,0,0,0,18,17,-18,-18,-27,-34,-1,0,0,0,0,0,18,17,-51,-51,-59,-65,-1,0,0,0,0,0,18,16,-117,-117,-122,-126,-1,0,0,0,0,0,13,-73,-96,-96,82,45,-1,0,0,0,0,0,13,-72,-1,-1,-126,71,-1,0,0,0,0,0,13,-72,-18,-18,121,66,-1,0,0,0,0,0,13,-72,-51,-51,104,57,-1,0,0,0,0,0,13,-71,-117,-117,71,38,-1,0,0,0,0,0,-117,108,-21,-121,-50,-21,-1,0,0,0,0,0,-112,120,-1,-121,-50,-1,-1,0,0,0,0,0,-112,120,-18,126,-64,-18,-1,0,0,0,0,0,-112,120,-51,108,-90,-51,-1,0,0,0,0,0,-111,119,-117,74,112,-117,-1,0,0,0,0,0,-81,-113,-51,106,90,-51,-1,0,0,0,0,0,-81,-112,-1,-125,111,-1,-1,0,0,0,0,0,-81,-112,-18,122,103,-18,-1,0,0,0,0,0,-81,-112,-51,105,89,-51,-1,0,0,0,0,0,-81,-112,-117,71,60,-117,-1,0,0,0,0,0,-108,56,-112,112,-128,-112,-1,0,0,0,0,0,-107,56,-1,-58,-30,-1,-1,0,0,0,0,0,-107,56,-18,-71,-45,-18,-1,0,0,0,0,0,-108,57,-51,-97,-74,-51,-1,0,0,0,0,0,-107,56,-117,108,123,-117,-1,0,0,0,0,0,-108,56,-112,112,-128,-112,-1,0,0,0,0,0,0,5,-1,-1,-6,-6,-1,0,0,0,0,0,0,5,-1,-1,-6,-6,-1,0,0,0,0,0,0,5,-18,-18,-23,-23,-1,0,0,0,0,0,0,4,-51,-51,-55,-55,-1,0,0,0,0,0,0,3,-117,-117,-119,-119,-1,0,0,0,0,0,106,-1,-1,0,-1,127,-1,0,0,0,0,0,106,-1,-1,0,-1,127,-1,0,0,0,0,0,106,-1,-18,0,-18,118,-1,0,0,0,0,0,106,-1,-51,0,-51,102,-1,0,0,0,0,0,106,-1,-117,0,-117,69,-1,0,0,0,0,0,-110,-101,-76,70,-126,-76,-1,0,0,0,0,0,-110,-100,-1,99,-72,-1,-1,0,0,0,0,0,-110,-100,-18,92,-84,-18,-1,0,0,0,0,0,-110,-100,-51,79,-108,-51,-1,0,0,0,0,0,-109,-101,-117,54,100,-117,-1,0,0,0,0,0,24,84,-46,-46,-76,-116,-1,0,0,0,0,0,20,-80,-1,-1,-91,79,-1,0,0,0,0,0,20,-80,-18,-18,-102,73,-1,0,0,0,0,0,20,-80,-51,-51,-123,63,-1,0,0,0,0,0,20,-80,-117,-117,90,43,-1,0,0,0,0,0,-44,29,-40,-40,-65,-40,-1,0,0,0,0,0,-44,30,-1,-1,-31,-1,-1,0,0,0,0,0,-44,30,-18,-18,-46,-18,-1,0,0,0,0,0,-44,29,-51,-51,-75,-51,-1,0,0,0,0,0,-44,29,-117,-117,123,-117,-1,0,0,0,0,0,6,-72,-1,-1,99,71,-1,0,0,0,0,0,6,-72,-1,-1,99,71,-1,0,0,0,0,0,6,-72,-18,-18,92,66,-1,0,0,0,0,0,6,-72,-51,-51,79,57,-1,0,0,0,0,0,6,-71,-117,-117,54,38,-1,0,0,0,0,0,42,0,-1,-1,-1,-2,0,0,0,0,0,0,123,-74,-32,64,-32,-48,-1,0,0,0,0,0,-127,-1,-1,0,-11,-1,-1,0,0,0,0,0,-127,-1,-18,0,-27,-18,-1,0,0,0,0,0,-127,-1,-51,0,-59,-51,-1,0,0,0,0,0,-127,-1,-117,0,-122,-117,-1,0,0,0,0,0,-44,115,-18,-18,-126,-18,-1,0,0,0,0,0,-29,-41,-48,-48,32,-112,-1,0,0,0,0,0,-21,-63,-1,-1,62,-106,-1,0,0,0,0,0,-21,-64,-18,-18,58,-116,-1,0,0,0,0,0,-21,-64,-51,-51,50,120,-1,0,0,0,0,0,-21,-64,-117,-117,34,82,-1,0,0,0,0,0,27,68,-11,-11,-34,-77,-1,0,0,0,0,0,27,69,-1,-1,-25,-70,-1,0,0,0,0,0,27,68,-18,-18,-40,-82,-1,0,0,0,0,0,27,68,-51,-51,-70,-106,-1,0,0,0,0,0,27,67,-117,-117,126,102,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,-11,-11,-11,-11,-1,0,0,0,0,0,42,-1,-1,-1,-1,0,-1,0,0,0,0,0,42,-1,-1,-1,-1,0,-1,0,0,0,0,0,42,-1,-18,-18,-18,0,-1,0,0,0,0,0,42,-1,-51,-51,-51,0,-1,0,0,0,0,0,42,-1,-117,-117,-117,0,-1,0,0,0,0,0,56,-64,-51,-102,-51,50,-1,0]),"i8",c,5260084);d(10,"i8",c,5289976);d(4,"i8",c,5289988);d(4,"i8",c,5289992);d(32e3,"i8",c,5289996);d(4,"i8",c,5321996);d(4,"i8",c,5322e3);d(4,"i8",c,5322004);d(4,"i8",c,5322008);d(4,"i8",c,5322012);d(4,"i8",c,5322016);d(4,"i8",c,5322020);d(4,"i8",c,5322024);d(4,"i8",c,5322028);d([211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,244,108,86,125,174,182,214,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,196,66,173,105,222,113,236,63,16,122,54,171,62,87,229,63,245,219,215,129,115,70,204,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,136,133,90,211,188,227,216,63,1,77,132,13,79,175,226,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,1,77,132,13,79,175,226,63,1,77,132,13,79,175,226,63,1,77,132,13,79,175,226,63,181,21,251,203,238,201,225,63,204,93,75,200,7,61,240,63,16,122,54,171,62,87,229,63,16,122,54,171,62,87,229,63,210,111,95,7,206,25,231,63,210,111,95,7,206,25,231,63,16,122,54,171,62,87,229,63,120,11,36,40,126,140,227,63,106,222,113,138,142,228,232,63,210,111,95,7,206,25,231,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,224,63,16,122,54,171,62,87,229,63,181,21,251,203,238,201,225,63,44,212,154,230,29,167,234,63,210,111,95,7,206,25,231,63,106,222,113,138,142,228,232,63,16,122,54,171,62,87,229,63,106,222,113,138,142,228,232,63,210,111,95,7,206,25,231,63,16,122,54,171,62,87,229,63,120,11,36,40,126,140,227,63,210,111,95,7,206,25,231,63,16,122,54,171,62,87,229,63,134,56,214,197,109,52,238,63,16,122,54,171,62,87,229,63,16,122,54,171,62,87,229,63,120,11,36,40,126,140,227,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,166,10,70,37,117,2,222,63,181,21,251,203,238,201,225,63,72,191,125,29,56,103,204,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,0,0,0,0,0,0,224,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,211,188,227,20,29,201,209,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,72,191,125,29,56,103,204,63,72,191,125,29,56,103,204,63,0,0,0,0,0,0,224,63,72,191,125,29,56,103,204,63,44,212,154,230,29,167,234,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,224,63,211,188,227,20,29,201,209,63,181,21,251,203,238,201,225,63,0,0,0,0,0,0,224,63,210,111,95,7,206,25,231,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,2,154,8,27,158,94,213,63,224,190,14,156,51,162,208,63,2,154,8,27,158,94,213,63,1,77,132,13,79,175,226,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,62,232,217,172,250,92,197,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,29,56,103,68,105,111,200,63,88,168,53,205,59,78,213,63,181,21,251,203,238,201,225,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,224,63,0,0,0,0,0,0,224,63,211,188,227,20,29,201,209,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,181,21,251,203,238,201,225,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,231,29,167,232,72,46,225,63,162,180,55,248,194,100,214,63,72,191,125,29,56,103,204,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,181,21,251,203,238,201,225,63,0,0,0,0,0,0,240,63,0,0,0,0,0,0,240,63,211,188,227,20,29,201,209,63,120,11,36,40,126,140,227,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,211,188,227,20,29,201,209,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,88,168,53,205,59,78,213,63,0,0,0,0,0,0,240,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,0,0,0,0,0,0,240,63,211,188,227,20,29,201,209,63,234,149,178,12,113,172,215,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,181,21,251,203,238,201,225,63,106,222,113,138,142,228,232,63,0,0,0,0,0,0,240,63,152,221,147,135,133,90,215,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,196,66,173,105,222,113,236,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,72,191,125,29,56,103,204,63,120,11,36,40,126,140,227,63,134,56,214,197,109,52,238,63,120,11,36,40,126,140,227,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63,211,188,227,20,29,201,209,63],"i8",c,5322032);d([3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5324080);d([1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5324208);d(20,"i8",c,5324224);d(4,"i8",c,5324244);d([0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,20,14,2,2,2,2,2,2,2,2,2,2,2,2,2,19,18,2,17,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,15,2,16,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,12,2,13,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,3,4,5,6,7,8,9,10,11],"i8",c,5324248);d([13,65,57,55,251,1,9,2,3,4,85,16,87,19,66,20,68,40,21,22,17,10,11,23,24,229,10,11,23,24,7,8,57,88,89,18,59,42,10,11,19,39,20,64,44,21,22,67,10,11,23,24,230,10,11,46,76,210,207,49,52,62,53,70,69,78,59,203,71,80,81,200,86,82,73,74,0,75,0,0,45],"i8",c,5324516);d([0,2,0,6,1,0,1,0,1,2,1,2,1,1,1,3,0,0,1,3,2,0,1,3,1,1,1,0,1,2,1,2,1,1,1,1,1,2,1,2,1,0,2,4,0,3,0,0,5,0,0,5,2,0,4,2,0,4,4,0,5,0,4,1,2,1,1,1,3],"i8",c,5324600);d([0,21,23,22,22,22,24,24,25,25,25,25,26,26,26,27,27,28,28,29,30,30,31,32,33,33,34,34,35,35,36,36,36,37,37,37,37,38,38,39,40,41,41,41,43,42,45,46,44,47,48,44,49,50,49,49,51,49,52,53,52,54,52,52,55,56,56,57,57],"i8",c,5324672);d([188,188,188,188,188,188,1,188,14,188,189,216,188,218,188,52,188,188,13,188,188,188,188,188,188,188,188,188,206,188,188,15,188,188,188,250,188],"i8",c,5324744);d([4,188,188,188,27,6,44,188,188,188,188,188,188,188,247,8,25,12,188,188,188,188,188,29,188,22,188,31,39,188,37,188,49,40,188,188,50,48,45,188,188,12,44,188,188,188,188,188,53,44,188,53,12,44,12,51,47,188,54,45,22,188,17,188,46,188,56,188,57,188,188,188,44,188,59,63,188,188,44,188,188,188,188,53,53,188,188,188,188,188],"i8",c,5324784);d(4,"i8",c,5324876);d(4,"i8",c,5324880);d(8,"i8",c,5324884);d([239,187,191],"i8",c,5324892);d(4,"i8",c,5324896);d(4,"i8",c,5324900);d([255,5,15,12,6,25,56,72,43,60,61,26,58,27,28,29,30,31,32,33,50,34,47,35,48,77,51,79,63,83,84,36,54,41,37,38,14],"i8",c,5324904);d([0,4,8,10,0,0,7,9,11,1,65,67,2,6,66,0,0,0,68,32,12,13,14,0,61,0,38,0,0,28,30,35,44,41,33,34,36,63,40,59,64,0,16,37,3,29,31,21,0,0,39,0,0,0,0,0,0,24,17,25,22,45,0,47,42,50,0,23,0,62,19,18,16,20,52,55,40,21,0,21,58,60,15,0,0,48,43,51,54,57],"i8",c,5324944);d([6,51,42,41,0,1,0,3,4,5,77,20,79,1,52,3,54,23,6,7,12,9,10,11,12,13,9,10,11,12,3,4,72,83,84,10,42,15,9,10,1,12,3,49,13,6,7,53,9,10,11,12,13,9,10,18,62,8,8,19,12,8,17,16,13,19,72,8,14,13,13,8,78,72,60,62,255,62,255,255,28],"i8",c,5325036);d(4,"i8",c,5325120);d([0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5325124);d([16,0,0,0,4,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5325160);d([12,0,0,0,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5325196);d([0,0,0,0,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5325232);d([0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5325268);d([20,0,0,0,4,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5325304);d([47,114,100,98,117,52,47,50,0],"i8",c,5325340);d([47,98,114,98,103,51,47,50,0],"i8",c,5325352);d([47,114,100,98,117,52,47,49,0],"i8",c,5325364);d([47,114,100,98,117,51,47,51,0],"i8",c,5325376);d([47,114,100,98,117,51,47,50,0],"i8",c,5325388);d([32,32,32,60,83,67,82,73,80,84,32,76,65,78,71,85,65,71,69,61,39,74,97,118,97,115,99,114,105,112,116,39,62,10,0],"i8",c,5325400);d([47,114,100,98,117,51,47,49,0],"i8",c,5325436);d([47,114,100,98,117,49,49,47,57,0],"i8",c,5325448);d([47,101,110,100,112,97,103,101,32,123,32,115,104,111,119,112,97,103,101,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5325460);d([109,105,110,116,99,114,101,97,109,0],"i8",c,5325492);d([47,114,100,98,117,49,49,47,56,0],"i8",c,5325504);d([116,97,105,108,99,108,105,112,0],"i8",c,5325516);d([97,99,117,116,101,0],"i8",c,5325528);d([47,114,100,98,117,49,49,47,55,0],"i8",c,5325536);d([47,114,100,98,117,49,49,47,54,0],"i8",c,5325548);d([111,114,100,101,114,105,110,103,32,39,37,115,39,32,110,111,116,32,114,101,99,111,103,110,105,122,101,100,32,102,111,114,32,110,111,100,101,32,39,37,115,39,46,10,0],"i8",c,5325560);d([47,114,100,98,117,49,49,47,53,0],"i8",c,5325608);d([108,97,98,101,108,116,111,111,108,116,105,112,0],"i8",c,5325620);d([47,114,100,98,117,49,49,47,52,0],"i8",c,5325636);d([47,98,114,98,103,51,47,49,0],"i8",c,5325648);d([47,114,100,98,117,49,49,47,51,0],"i8",c,5325660);d([47,114,100,98,117,49,49,47,50,0],"i8",c,5325672);d([47,114,100,98,117,49,49,47,49,49,0],"i8",c,5325684);d([60,33,45,45,32,80,97,103,101,115,58,32,37,100,32,45,45,62,10,0],"i8",c,5325696);d([47,114,100,98,117,49,49,47,49,48,0],"i8",c,5325716);d([112,111,108,121,32,37,115,0],"i8",c,5325728);d([47,114,100,98,117,49,49,47,49,0],"i8",c,5325736);d([9,115,101,116,109,97,116,114,105,120,0],"i8",c,5325748);d([109,105,100,110,105,103,104,116,98,108,117,101,0],"i8",c,5325760);d([47,114,100,98,117,49,48,47,57,0],"i8",c,5325776);d([99,111,110,115,116,114,97,105,110,116,0],"i8",c,5325788);d([98,103,99,111,108,111,114,0],"i8",c,5325800);d([97,99,105,114,99,0],"i8",c,5325808);d([47,114,100,98,117,49,48,47,56,0],"i8",c,5325816);d([47,114,100,98,117,49,48,47,55,0],"i8",c,5325828);d([47,114,100,98,117,49,48,47,54,0],"i8",c,5325840);d([101,100,103,101,116,111,111,108,116,105,112,0],"i8",c,5325852);d([47,114,100,98,117,49,48,47,53,0],"i8",c,5325864);d([47,98,114,98,103,49,49,47,57,0],"i8",c,5325876);d([47,114,100,98,117,49,48,47,52,0],"i8",c,5325888);d([47,114,100,98,117,49,48,47,51,0],"i8",c,5325900);d([47,114,100,98,117,49,48,47,50,0],"i8",c,5325912);d([60,47,84,73,84,76,69,62,0],"i8",c,5325924);d([47,114,100,98,117,49,48,47,49,48,0],"i8",c,5325936);d([47,114,100,98,117,49,48,47,49,0],"i8",c,5325948);d([9,48,32,48,32,49,32,48,32,51,54,48,32,97,114,99,0],"i8",c,5325960);d([109,101,100,105,117,109,118,105,111,108,101,116,114,101,100,0],"i8",c,5325980);d([47,112,117,114,112,108,101,115,57,47,57,0],"i8",c,5325996);d([97,114,114,111,119,115,105,122,101,0],"i8",c,5326008);d([47,97,99,99,101,110,116,53,47,49,0],"i8",c,5326020);d([97,97,99,117,116,101,0],"i8",c,5326032);d([47,112,117,114,112,108,101,115,57,47,56,0],"i8",c,5326040);d([47,112,117,114,112,108,101,115,57,47,55,0],"i8",c,5326052);d([47,112,117,114,112,108,101,115,57,47,54,0],"i8",c,5326064);d([47,112,117,114,112,108,101,115,57,47,53,0],"i8",c,5326076);d([47,98,114,98,103,49,49,47,56,0],"i8",c,5326088);d([47,112,117,114,112,108,101,115,57,47,52,0],"i8",c,5326100);d([47,112,117,114,112,108,101,115,57,47,51,0],"i8",c,5326112);d([47,112,117,114,112,108,101,115,57,47,50,0],"i8",c,5326124);d([60,84,73,84,76,69,62,0],"i8",c,5326136);d([47,112,117,114,112,108,101,115,57,47,49,0],"i8",c,5326144);d([47,112,117,114,112,108,101,115,56,47,56,0],"i8",c,5326156);d([9,114,120,32,114,121,32,115,99,97,108,101,0],"i8",c,5326168);d([109,101,100,105,117,109,116,117,114,113,117,111,105,115,101,0],"i8",c,5326184);d([47,112,117,114,112,108,101,115,56,47,55,0],"i8",c,5326200);d([117,115,105,110,103,32,37,115,32,102,111,114,32,117,110,107,110,111,119,110,32,115,104,97,112,101,32,37,115,10,0],"i8",c,5326212);d([100,101,99,111,114,97,116,101,0],"i8",c,5326244);d([106,112,103,58,102,105,103,0],"i8",c,5326256);d([90,101,116,97,0],"i8",c,5326264);d([47,112,117,114,112,108,101,115,56,47,54,0],"i8",c,5326272);d([37,100,32,98,111,120,101,115,58,10,0],"i8",c,5326284);d([47,112,117,114,112,108,101,115,56,47,53,0],"i8",c,5326296);d([47,112,117,114,112,108,101,115,56,47,52,0],"i8",c,5326308);d([104,101,97,100,116,97,114,103,101,116,0],"i8",c,5326320);d([47,112,117,114,112,108,101,115,56,47,51,0],"i8",c,5326332);d([47,98,114,98,103,49,49,47,55,0],"i8",c,5326344);d([47,112,117,114,112,108,101,115,56,47,50,0],"i8",c,5326356);d([47,112,117,114,112,108,101,115,56,47,49,0],"i8",c,5326368);d([47,112,117,114,112,108,101,115,55,47,55,0],"i8",c,5326380);d([60,77,69,84,65,32,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110,116,101,110,116,45,84,121,112,101,34,32,99,111,110,116,101,110,116,61,34,116,101,120,116,47,104,116,109,108,59,32,99,104,97,114,115,101,116,61,85,84,70,45,56,34,62,10,0],"i8",c,5326392);d([47,112,117,114,112,108,101,115,55,47,54,0],"i8",c,5326464);d([47,112,117,114,112,108,101,115,55,47,53,0],"i8",c,5326476);d([9,120,32,121,32,116,114,97,110,115,108,97,116,101,0],"i8",c,5326488);d([109,101,100,105,117,109,115,112,114,105,110,103,103,114,101,101,110,0],"i8",c,5326504);d([47,112,117,114,112,108,101,115,55,47,52,0],"i8",c,5326524);d([97,103,115,116,114,102,114,101,101,32,108,111,115,116,32,37,115,10,0],"i8",c,5326536);d([109,105,110,108,101,110,0],"i8",c,5326556);d([89,117,109,108,0],"i8",c,5326564);d([47,112,117,114,112,108,101,115,55,47,51,0],"i8",c,5326572);d([47,112,117,114,112,108,101,115,55,47,50,0],"i8",c,5326584);d([47,112,117,114,112,108,101,115,55,47,49,0],"i8",c,5326596);d([116,97,105,108,116,97,114,103,101,116,0],"i8",c,5326608);d([47,112,117,114,112,108,101,115,54,47,54,0],"i8",c,5326620);d([118,109,108,58,118,109,108,0],"i8",c,5326632);d([47,98,114,98,103,49,49,47,54,0],"i8",c,5326640);d([47,112,117,114,112,108,101,115,54,47,53,0],"i8",c,5326652);d([47,112,117,114,112,108,101,115,54,47,52,0],"i8",c,5326664);d([112,108,117,115,0],"i8",c,5326676);d([47,112,117,114,112,108,101,115,54,47,51,0],"i8",c,5326684);d([60,72,69,65,68,62,0],"i8",c,5326696);d([47,112,117,114,112,108,101,115,54,47,50,0],"i8",c,5326704);d([47,112,117,114,112,108,101,115,54,47,49,0],"i8",c,5326716);d([9,110,101,119,112,97,116,104,0],"i8",c,5326728);d([109,101,100,105,117,109,115,108,97,116,101,98,108,117,101,0],"i8",c,5326740);d([47,112,117,114,112,108,101,115,53,47,53,0],"i8",c,5326756);d([108,97,98,101,108,97,110,103,108,101,0],"i8",c,5326768);d([89,97,99,117,116,101,0],"i8",c,5326780);d([47,112,117,114,112,108,101,115,53,47,52,0],"i8",c,5326788);d([47,112,117,114,112,108,101,115,53,47,51,0],"i8",c,5326800);d([47,112,117,114,112,108,101,115,53,47,50,0],"i8",c,5326812);d([108,97,98,101,108,116,97,114,103,101,116,0],"i8",c,5326824);d([47,112,117,114,112,108,101,115,53,47,49,0],"i8",c,5326836);d([47,98,114,98,103,49,49,47,53,0],"i8",c,5326848);d([47,112,117,114,112,108,101,115,52,47,52,0],"i8",c,5326860);d([47,112,117,114,112,108,101,115,52,47,51,0],"i8",c,5326872);d([47,112,117,114,112,108,101,115,52,47,50,0],"i8",c,5326884);d([60,47,66,79,68,89,62,10,60,47,72,84,77,76,62,10,0],"i8",c,5326896);d([85,82,87,32,71,111,116,104,105,99,32,76,0],"i8",c,5326916);d([47,112,117,114,112,108,101,115,52,47,49,0],"i8",c,5326932);d([47,112,117,114,112,108,101,115,51,47,51,0],"i8",c,5326944);d([9,109,97,116,114,105,120,32,99,117,114,114,101,110,116,109,97,116,114,105,120,0],"i8",c,5326956);d([109,101,100,105,117,109,115,101,97,103,114,101,101,110,0],"i8",c,5326980);d([47,112,117,114,112,108,101,115,51,47,50,0],"i8",c,5326996);d([108,97,98,101,108,100,105,115,116,97,110,99,101,0],"i8",c,5327008);d([88,105,0],"i8",c,5327024);d([47,112,117,114,112,108,101,115,51,47,49,0],"i8",c,5327028);d([47,112,117,114,100,57,47,57,0],"i8",c,5327040);d([112,108,97,105,110,45,101,120,116,58,100,111,116,0],"i8",c,5327052);d([47,112,117,114,100,57,47,56,0],"i8",c,5327068);d([101,100,103,101,116,97,114,103,101,116,0],"i8",c,5327080);d([37,115,32,45,62,32,37,115,58,32,104,101,97,100,32,105,115,32,105,110,115,105,100,101,32,116,97,105,108,32,99,108,117,115,116,101,114,32,37,115,10,0],"i8",c,5327092);d([47,112,117,114,100,57,47,55,0],"i8",c,5327136);d([110,111,32,109,101,109,111,114,121,32,102,114,111,109,32,122,109,97,108,108,111,99,40,41,10,0],"i8",c,5327148);d([109,101,109,111,114,121,32,97,108,108,111,99,97,116,105,111,110,32,102,97,105,108,117,114,101,10,0],"i8",c,5327176);d([47,98,114,98,103,49,49,47,52,0],"i8",c,5327204);d([47,112,117,114,100,57,47,54,0],"i8",c,5327216);d([32,123,10,0],"i8",c,5327228);d([99,97,110,110,111,116,32,109,97,108,108,111,99,32,112,110,108,115,0],"i8",c,5327232);d([47,112,117,114,100,57,47,53,0],"i8",c,5327252);d([112,111,115,0],"i8",c,5327264);d([47,112,117,114,100,57,47,52,0],"i8",c,5327268);d([60,33,45,45,32,105,110,115,101,114,116,32,97,110,121,32,111,116,104,101,114,32,78,79,78,45,73,69,32,104,116,109,108,32,99,111,110,116,101,110,116,32,104,101,114,101,32,45,45,62,10,0],"i8",c,5327280);d([95,76,84,88,95,108,105,98,114,97,114,121,0],"i8",c,5327332);d([84,82,65,73,76,69,82,0],"i8",c,5327348);d([47,112,117,114,100,57,47,51,0],"i8",c,5327356);d([47,112,117,114,100,57,47,50,0],"i8",c,5327368);d([9,47,120,32,101,120,99,104,32,100,101,102,0],"i8",c,5327380);d([109,101,100,105,117,109,112,117,114,112,108,101,0],"i8",c,5327396);d([47,112,117,114,100,57,47,49,0],"i8",c,5327412);d([108,97,98,101,108,102,111,110,116,99,111,108,111,114,0],"i8",c,5327424);d([85,117,109,108,0],"i8",c,5327440);d([47,112,117,114,100,56,47,56,0],"i8",c,5327448);d([47,112,117,114,100,56,47,55,0],"i8",c,5327460);d([47,112,117,114,100,56,47,54,0],"i8",c,5327472);d([116,97,114,103,101,116,0],"i8",c,5327484);d([47,112,117,114,100,56,47,53,0],"i8",c,5327492);d([47,98,114,98,103,49,49,47,51,0],"i8",c,5327504);d([47,112,117,114,100,56,47,52,0],"i8",c,5327516);d([47,112,117,114,100,56,47,51,0],"i8",c,5327528);d([47,112,117,114,100,56,47,50,0],"i8",c,5327540);d([60,68,73,86,32,105,100,61,39,95,110,111,116,86,77,76,50,95,39,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,34,62,10,0],"i8",c,5327552);d([47,112,117,114,100,56,47,49,0],"i8",c,5327604);d([115,111,117,114,99,101,0],"i8",c,5327616);d([47,112,117,114,100,55,47,55,0],"i8",c,5327624);d([9,47,121,32,101,120,99,104,32,100,101,102,0],"i8",c,5327636);d([109,101,100,105,117,109,111,114,99,104,105,100,0],"i8",c,5327652);d([47,112,117,114,100,55,47,54,0],"i8",c,5327668);d([108,97,98,101,108,102,111,110,116,110,97,109,101,0],"i8",c,5327680);d([104,112,0],"i8",c,5327696);d([110,111,0],"i8",c,5327700);d([69,110,99,111,100,105,110,103,86,101,99,116,111,114,32,52,53,32,47,104,121,112,104,101,110,32,112,117,116,0],"i8",c,5327704);d([85,112,115,105,108,111,110,0],"i8",c,5327736);d([47,112,117,114,100,55,47,53,0],"i8",c,5327744);d([47,112,117,114,100,55,47,52,0],"i8",c,5327756);d([47,112,117,114,100,55,47,51,0],"i8",c,5327768);d([104,101,97,100,85,82,76,0],"i8",c,5327780);d([47,112,117,114,100,55,47,50,0],"i8",c,5327788);d([47,98,114,98,103,49,49,47,50,0],"i8",c,5327800);d([47,112,117,114,100,55,47,49,0],"i8",c,5327812);d([47,112,117,114,100,54,47,54,0],"i8",c,5327824);d([47,112,117,114,100,54,47,53,0],"i8",c,5327836);d([60,72,50,62,83,111,114,114,121,44,32,116,104,105,115,32,100,105,97,103,114,97,109,32,119,105,108,108,32,111,110,108,121,32,100,105,115,112,108,97,121,32,99,111,114,114,101,99,116,108,121,32,111,110,32,73,110,116,101,114,110,101,116,32,69,120,112,108,111,114,101,114,32,53,32,40,97,110,100,32,117,112,41,32,98,114,111,119,115,101,114,115,46,60,47,72,50,62,10,0],"i8",c,5327848);d([47,112,117,114,100,54,47,52,0],"i8",c,5327948);d([47,112,117,114,100,54,47,51,0],"i8",c,5327960);d([9,47,114,120,32,101,120,99,104,32,100,101,102,0],"i8",c,5327972);d([109,101,100,105,117,109,98,108,117,101,0],"i8",c,5327988);d([47,112,117,114,100,54,47,50,0],"i8",c,5328e3);d([108,97,98,101,108,102,111,110,116,115,105,122,101,0],"i8",c,5328012);d([85,103,114,97,118,101,0],"i8",c,5328028);d([47,112,117,114,100,54,47,49,0],"i8",c,5328036);d([47,112,117,114,100,53,47,53,0],"i8",c,5328048);d([47,112,117,114,100,53,47,52,0],"i8",c,5328060);d([104,101,97,100,104,114,101,102,0],"i8",c,5328072);d([112,101,110,0],"i8",c,5328084);d([47,112,117,114,100,53,47,51,0],"i8",c,5328088);d([47,98,114,98,103,49,49,47,49,49,0],"i8",c,5328100);d([47,112,117,114,100,53,47,50,0],"i8",c,5328112);d([47,112,117,114,100,53,47,49,0],"i8",c,5328124);d([47,112,117,114,100,52,47,52,0],"i8",c,5328136);d([60,33,45,45,32,116,104,105,115,32,115,104,111,117,108,100,32,111,110,108,121,32,100,105,115,112,108,97,121,32,111,110,32,78,79,78,45,73,69,32,98,114,111,119,115,101,114,115,32,45,45,62,10,0],"i8",c,5328148);d([47,112,117,114,100,52,47,51,0],"i8",c,5328204);d([47,112,117,114,100,52,47,50,0],"i8",c,5328216);d([9,47,114,121,32,101,120,99,104,32,100,101,102,0],"i8",c,5328228);d([109,101,100,105,117,109,97,113,117,97,109,97,114,105,110,101,0],"i8",c,5328244);d([47,112,117,114,100,52,47,49,0],"i8",c,5328264);d([116,97,105,108,108,97,98,101,108,0],"i8",c,5328276);d([85,99,105,114,99,0],"i8",c,5328288);d([47,112,117,114,100,51,47,51,0],"i8",c,5328296);d([47,112,117,114,100,51,47,50,0],"i8",c,5328308);d([47,112,117,114,100,51,47,49,0],"i8",c,5328320);d([116,97,105,108,85,82,76,0],"i8",c,5328332);d([111,114,100,101,114,105,110,103,32,39,37,115,39,32,110,111,116,32,114,101,99,111,103,110,105,122,101,100,46,10,0],"i8",c,5328340);d([47,112,117,111,114,57,47,57,0],"i8",c,5328372);d([47,98,114,98,103,49,49,47,49,48,0],"i8",c,5328384);d([47,112,117,111,114,57,47,56,0],"i8",c,5328396);d([47,112,117,111,114,57,47,55,0],"i8",c,5328408);d([47,112,117,111,114,57,47,54,0],"i8",c,5328420);d([60,68,73,86,32,105,100,61,39,95,110,111,116,86,77,76,49,95,39,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,34,62,10,0],"i8",c,5328432);d([47,112,117,111,114,57,47,53,0],"i8",c,5328484);d([47,112,117,111,114,57,47,52,0],"i8",c,5328496);d([99,105,114,99,108,101,32,37,115,32,37,100,44,37,100,44,37,100,10,0],"i8",c,5328508);d([109,101,109,111,114,121,32,101,120,104,97,117,115,116,101,100,0],"i8",c,5328528);d([47,101,108,108,105,112,115,101,95,112,97,116,104,32,123,0],"i8",c,5328548);d([47,112,117,111,114,57,47,51,0],"i8",c,5328564);d([104,101,97,100,108,97,98,101,108,0],"i8",c,5328576);d([85,97,99,117,116,101,0],"i8",c,5328588);d([47,112,117,111,114,57,47,50,0],"i8",c,5328596);d([47,112,117,111,114,57,47,49,0],"i8",c,5328608);d([47,112,117,111,114,56,47,56,0],"i8",c,5328620);d([116,97,105,108,104,114,101,102,0],"i8",c,5328632);d([47,112,117,111,114,56,47,55,0],"i8",c,5328644);d([47,98,114,98,103,49,49,47,49,0],"i8",c,5328656);d([47,112,117,111,114,56,47,54,0],"i8",c,5328668);d([47,112,117,111,114,56,47,53,0],"i8",c,5328680);d([47,112,117,111,114,56,47,52,0],"i8",c,5328692);d([60,33,45,45,32,105,110,115,101,114,116,32,97,110,121,32,111,116,104,101,114,32,104,116,109,108,32,99,111,110,116,101,110,116,32,104,101,114,101,32,45,45,62,10,0],"i8",c,5328704);d([47,112,117,111,114,56,47,51,0],"i8",c,5328752);d([47,112,117,111,114,56,47,50,0],"i8",c,5328764);d([9,9,99,108,111,115,101,112,97,116,104,0],"i8",c,5328776);d([109,97,103,101,110,116,97,0],"i8",c,5328788);d([47,112,117,111,114,56,47,49,0],"i8",c,5328796);d([97,114,114,111,119,116,97,105,108,0],"i8",c,5328808);d([47,97,99,99,101,110,116,52,47,52,0],"i8",c,5328820);d([84,104,101,116,97,0],"i8",c,5328832);d([47,112,117,111,114,55,47,55,0],"i8",c,5328840);d([47,112,117,111,114,55,47,54,0],"i8",c,5328852);d([47,112,117,111,114,55,47,53,0],"i8",c,5328864);d([108,97,98,101,108,85,82,76,0],"i8",c,5328876);d([47,112,117,111,114,55,47,52,0],"i8",c,5328888);d([47,98,114,98,103,49,48,47,57,0],"i8",c,5328900);d([47,112,117,111,114,55,47,51,0],"i8",c,5328912);d([47,112,117,111,114,55,47,50,0],"i8",c,5328924);d([47,112,117,111,114,55,47,49,0],"i8",c,5328936);d([60,68,73,86,32,105,100,61,39,95,86,77,76,50,95,39,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,118,105,115,105,98,105,108,105,116,121,58,104,105,100,100,101,110,34,62,10,0],"i8",c,5328948);d([47,112,117,111,114,54,47,54,0],"i8",c,5329012);d([47,112,117,111,114,54,47,53,0],"i8",c,5329024);d([9,9,112,111,112,32,110,101,103,32,48,32,114,108,105,110,101,116,111,0],"i8",c,5329036);d([108,105,110,101,110,0],"i8",c,5329056);d([47,112,117,111,114,54,47,52,0],"i8",c,5329064);d([97,114,114,111,119,104,101,97,100,0],"i8",c,5329076);d([106,112,101,58,102,105,103,0],"i8",c,5329088);d([47,112,117,111,114,54,47,51,0],"i8",c,5329096);d([84,97,117,0],"i8",c,5329108);d([47,112,117,111,114,54,47,50,0],"i8",c,5329112);d([47,112,117,111,114,54,47,49,0],"i8",c,5329124);d([108,97,98,101,108,104,114,101,102,0],"i8",c,5329136);d([47,112,117,111,114,53,47,53,0],"i8",c,5329148);d([47,98,114,98,103,49,48,47,56,0],"i8",c,5329160);d([47,112,117,111,114,53,47,52,0],"i8",c,5329172);d([47,112,117,111,114,53,47,51,0],"i8",c,5329184);d([47,112,117,111,114,53,47,50,0],"i8",c,5329196);d([60,47,68,73,86,62,10,0],"i8",c,5329208);d([69,68,95,116,111,95,118,105,114,116,40,101,41,32,61,61,32,78,85,76,76,0],"i8",c,5329216);d([47,112,117,111,114,53,47,49,0],"i8",c,5329240);d([47,112,117,111,114,52,47,52,0],"i8",c,5329252);d([9,9,48,32,101,120,99,104,32,114,108,105,110,101,116,111,0],"i8",c,5329264);d([108,105,109,101,103,114,101,101,110,0],"i8",c,5329284);d([47,112,117,111,114,52,47,51,0],"i8",c,5329296);d([100,105,114,0],"i8",c,5329308);d([47,112,117,111,114,52,47,50,0],"i8",c,5329312);d([84,72,79,82,78,0],"i8",c,5329324);d([47,112,117,111,114,52,47,49,0],"i8",c,5329332);d([47,112,117,111,114,51,47,51,0],"i8",c,5329344);d([101,100,103,101,85,82,76,0],"i8",c,5329356);d([47,112,117,111,114,51,47,50,0],"i8",c,5329364);d([47,98,114,98,103,49,48,47,55,0],"i8",c,5329376);d([118,109,108,0],"i8",c,5329388);d([47,112,117,111,114,51,47,49,0],"i8",c,5329392);d([47,112,117,111,114,49,49,47,57,0],"i8",c,5329404);d([47,112,117,111,114,49,49,47,56,0],"i8",c,5329416);d([60,47,118,58,103,114,111,117,112,62,10,0],"i8",c,5329428);d([75,80,95,68,111,119,110,0],"i8",c,5329440);d([47,112,117,111,114,49,49,47,55,0],"i8",c,5329448);d([47,112,117,111,114,49,49,47,54,0],"i8",c,5329460);d([110,111,100,101,0],"i8",c,5329472);d([9,9,101,120,99,104,32,48,32,114,108,105,110,101,116,111,0],"i8",c,5329480);d([47,112,117,111,114,49,49,47,53,0],"i8",c,5329500);d([108,97,98,101,108,102,108,111,97,116,0],"i8",c,5329512);d([47,112,117,111,114,49,49,47,52,0],"i8",c,5329524);d([83,105,103,109,97,0],"i8",c,5329536);d([47,112,117,111,114,49,49,47,51,0],"i8",c,5329544);d([47,112,117,111,114,49,49,47,50,0],"i8",c,5329556);d([101,100,103,101,104,114,101,102,0],"i8",c,5329568);d([47,112,117,111,114,49,49,47,49,49,0],"i8",c,5329580);d([47,98,114,98,103,49,48,47,54,0],"i8",c,5329592);d([47,112,117,111,114,49,49,47,49,48,0],"i8",c,5329604);d([97,117,120,103,0],"i8",c,5329616);d([47,112,117,111,114,49,49,47,49,0],"i8",c,5329624);d([47,112,117,111,114,49,48,47,57,0],"i8",c,5329636);d([62,10,0],"i8",c,5329648);d([65,118,97,110,116,71,97,114,100,101,45,66,111,111,107,0],"i8",c,5329652);d([47,112,117,111,114,49,48,47,56,0],"i8",c,5329668);d([47,112,117,111,114,49,48,47,55,0],"i8",c,5329680);d([9,9,50,32,99,111,112,121,0],"i8",c,5329692);d([47,112,117,111,114,49,48,47,54,0],"i8",c,5329704);d([108,105,103,104,116,121,101,108,108,111,119,0],"i8",c,5329716);d([47,112,117,111,114,49,48,47,53,0],"i8",c,5329728);d([83,99,97,114,111,110,0],"i8",c,5329740);d([47,112,117,111,114,49,48,47,52,0],"i8",c,5329748);d([112,108,97,105,110,58,100,111,116,0],"i8",c,5329760);d([47,112,117,111,114,49,48,47,51,0],"i8",c,5329772);d([37,115,32,45,62,32,37,115,58,32,116,97,105,108,32,110,111,116,32,105,110,115,105,100,101,32,116,97,105,108,32,99,108,117,115,116,101,114,32,37,115,10,0],"i8",c,5329784);d([47,112,117,111,114,49,48,47,50,0],"i8",c,5329828);d([47,112,117,111,114,49,48,47,49,48,0],"i8",c,5329840);d([47,98,114,98,103,49,48,47,53,0],"i8",c,5329852);d([95,97,110,111,110,121,109,111,117,115,0],"i8",c,5329864);d([99,97,110,110,111,116,32,114,101,97,108,108,111,99,32,100,113,46,112,110,108,115,0],"i8",c,5329876);d([47,112,117,111,114,49,48,47,49,0],"i8",c,5329900);d([115,116,111,112,10,0],"i8",c,5329912);d([47,112,117,98,117,103,110,57,47,57,0],"i8",c,5329920);d([32,116,97,114,103,101,116,61,34,37,115,34,0],"i8",c,5329932);d([69,78,68,0],"i8",c,5329948);d([47,112,117,98,117,103,110,57,47,56,0],"i8",c,5329952);d([47,112,117,98,117,103,110,57,47,55,0],"i8",c,5329964);d([9,9,109,111,118,101,116,111,0],"i8",c,5329976);d([47,112,117,98,117,103,110,57,47,54,0],"i8",c,5329988);d([108,105,103,104,116,115,116,101,101,108,98,108,117,101,0],"i8",c,533e4);d([122,0],"i8",c,5330016);d([98,105,115,113,117,101,0],"i8",c,5330020);d([47,112,117,98,117,103,110,57,47,53,0],"i8",c,5330028);d([82,104,111,0],"i8",c,5330040);d([47,112,117,98,117,103,110,57,47,52,0],"i8",c,5330044);d([47,112,117,98,117,103,110,57,47,51,0],"i8",c,5330056);d([47,112,117,98,117,103,110,57,47,50,0],"i8",c,5330068);d([47,112,117,98,117,103,110,57,47,49,0],"i8",c,5330080);d([47,98,114,98,103,49,48,47,52,0],"i8",c,5330092);d([47,112,117,98,117,103,110,56,47,56,0],"i8",c,5330104);d([47,112,117,98,117,103,110,56,47,55,0],"i8",c,5330116);d([32,116,105,116,108,101,61,34,37,115,34,0],"i8",c,5330128);d([47,112,117,98,117,103,110,56,47,54,0],"i8",c,5330140);d([47,112,117,98,117,103,110,56,47,53,0],"i8",c,5330152);d([109,105,110,0],"i8",c,5330164);d([9,9,52,32,50,32,114,111,108,108,0],"i8",c,5330168);d([47,112,117,98,117,103,110,56,47,52,0],"i8",c,5330180);d([114,101,109,105,110,99,114,111,115,115,0],"i8",c,5330192);d([108,105,103,104,116,115,108,97,116,101,103,114,101,121,0],"i8",c,5330204);d([104,101,105,103,104,116,61,34,37,108,102,37,50,115,34,0],"i8",c,5330220);d([118,101,114,116,105,99,101,115,0],"i8",c,5330236);d([110,115,108,105,109,105,116,0],"i8",c,5330248);d([73,83,79,76,97,116,105,110,49,69,110,99,111,100,105,110,103,32,48,32,50,53,53,32,103,101,116,105,110,116,101,114,118,97,108,32,112,117,116,105,110,116,101,114,118,97,108,0],"i8",c,5330256);d([47,112,117,98,117,103,110,56,47,51,0],"i8",c,5330304);d([80,115,105,0],"i8",c,5330316);d([47,112,117,98,117,103,110,56,47,50,0],"i8",c,5330320);d([47,112,117,98,117,103,110,56,47,49,0],"i8",c,5330332);d([78,111,32,99,111,109,109,97,32,105,110,32,99,111,108,111,114,32,115,112,101,99,32,34,37,115,34,32,105,110,32,99,111,108,111,114,32,97,116,116,114,105,98,117,116,101,32,0],"i8",c,5330344);d([47,112,117,98,117,103,110,55,47,55,0],"i8",c,5330392);d([47,112,117,98,117,103,110,55,47,54,0],"i8",c,5330404);d([47,98,114,98,103,49,48,47,51,0],"i8",c,5330416);d([47,112,117,98,117,103,110,55,47,53,0],"i8",c,5330428);d([47,62,10,0],"i8",c,5330440);d([47,112,117,98,117,103,110,55,47,52,0],"i8",c,5330444);d([32,104,114,101,102,61,34,37,115,34,0],"i8",c,5330456);d([47,112,117,98,117,103,110,55,47,51,0],"i8",c,5330468);d([47,112,117,98,117,103,110,55,47,50,0],"i8",c,5330480);d([47,98,111,120,112,114,105,109,32,123,9,9,9,9,37,32,120,99,111,114,110,101,114,32,121,99,111,114,110,101,114,32,120,115,105,122,101,32,121,115,105,122,101,0],"i8",c,5330492);d([47,112,117,98,117,103,110,55,47,49,0],"i8",c,5330536);d([108,105,103,104,116,115,108,97,116,101,103,114,97,121,0],"i8",c,5330548);d([99,111,109,109,101,110,116,0],"i8",c,5330564);d([47,112,117,98,117,103,110,54,47,54,0],"i8",c,5330572);d([80,114,105,109,101,0],"i8",c,5330584);d([47,112,117,98,117,103,110,54,47,53,0],"i8",c,5330592);d([47,112,117,98,117,103,110,54,47,52,0],"i8",c,5330604);d([73,108,108,101,103,97,108,32,108,101,110,103,116,104,32,118,97,108,117,101,32,105,110,32,34,37,115,34,32,99,111,108,111,114,32,97,116,116,114,105,98,117,116,101,32,0],"i8",c,5330616);d([118,101,101,0],"i8",c,5330664);d([47,112,117,98,117,103,110,54,47,51,0],"i8",c,5330668);d([47,112,117,98,117,103,110,54,47,50,0],"i8",c,5330680);d([47,98,114,98,103,49,48,47,50,0],"i8",c,5330692);d([47,112,117,98,117,103,110,54,47,49,0],"i8",c,5330704);d([110,111,100,101,32,39,37,115,39,44,32,103,114,97,112,104,32,39,37,115,39,32,115,105,122,101,32,116,111,111,32,115,109,97,108,108,32,102,111,114,32,108,97,98,101,108,10,0],"i8",c,5330716);d([34,32,119,105,100,116,104,61,34,37,103,112,120,34,32,104,101,105,103,104,116,61,34,37,103,112,120,34,32,112,114,101,115,101,114,118,101,65,115,112,101,99,116,82,97,116,105,111,61,34,120,77,105,110,89,77,105,110,32,109,101,101,116,34,32,120,61,34,37,103,34,32,121,61,34,37,103,34,0],"i8",c,5330764);d([47,112,117,98,117,103,110,53,47,53,0],"i8",c,5330844);d([60,97,0],"i8",c,5330856);d([47,112,117,98,117,103,110,53,47,52,0],"i8",c,5330860);d([47,112,117,98,117,103,110,53,47,51,0],"i8",c,5330872);d([9,103,114,101,115,116,111,114,101,0],"i8",c,5330884);d([47,112,117,98,117,103,110,53,47,50,0],"i8",c,5330896);d([108,105,103,104,116,115,107,121,98,108,117,101,0],"i8",c,5330908);d([103,114,111,117,112,0],"i8",c,5330924);d([47,112,117,98,117,103,110,53,47,49,0],"i8",c,5330932);d([80,105,0],"i8",c,5330944);d([47,112,117,98,117,103,110,52,47,52,0],"i8",c,5330948);d([47,112,117,98,117,103,110,52,47,51,0],"i8",c,5330960);d([48,45,108,101,110,103,116,104,32,105,110,32,99,111,108,111,114,32,115,112,101,99,32,34,37,115,34,10,0],"i8",c,5330972);d([47,112,117,98,117,103,110,52,47,50,0],"i8",c,5331004);d([105,110,0],"i8",c,5331016);d([47,112,117,98,117,103,110,52,47,49,0],"i8",c,5331020);d([47,98,114,98,103,49,48,47,49,48,0],"i8",c,5331032);d([47,112,117,98,117,103,110,51,47,51,0],"i8",c,5331044);d([32,116,114,97,110,115,102,111,114,109,61,34,114,111,116,97,116,101,40,37,100,32,37,103,32,37,103,41,34,0],"i8",c,5331056);d([47,112,117,98,117,103,110,51,47,50,0],"i8",c,5331088);d([60,47,97,62,10,0],"i8",c,5331100);d([47,112,117,98,117,103,110,51,47,49,0],"i8",c,5331108);d([47,112,117,98,117,57,47,57,0],"i8",c,5331120);d([9,9,125,32,105,102,0],"i8",c,5331132);d([47,112,117,98,117,57,47,56,0],"i8",c,5331140);d([102,108,97,116,46,99,0],"i8",c,5331152);d([108,105,103,104,116,115,101,97,103,114,101,101,110,0],"i8",c,5331160);d([108,97,121,101,114,0],"i8",c,5331176);d([114,101,99,116,32,37,115,32,37,100,44,37,100,32,37,100,44,37,100,10,0],"i8",c,5331184);d([47,112,117,98,117,57,47,55,0],"i8",c,5331208);d([80,104,105,0],"i8",c,5331220);d([47,112,117,98,117,57,47,54,0],"i8",c,5331224);d([47,112,117,98,117,57,47,53,0],"i8",c,5331236);d([47,112,117,98,117,57,47,52,0],"i8",c,5331248);d([47,112,117,98,117,57,47,51,0],"i8",c,5331260);d([47,98,114,98,103,49,48,47,49,0],"i8",c,5331272);d([47,112,117,98,117,57,47,50,0],"i8",c,5331284);d([78,111,32,111,114,32,105,109,112,114,111,112,101,114,32,105,109,97,103,101,61,34,37,115,34,32,102,111,114,32,110,111,100,101,32,34,37,115,34,10,0],"i8",c,5331296);d([34,32,119,105,100,116,104,61,34,37,103,112,120,34,32,104,101,105,103,104,116,61,34,37,103,112,120,34,32,112,114,101,115,101,114,118,101,65,115,112,101,99,116,82,97,116,105,111,61,34,120,77,105,100,89,77,105,100,32,109,101,101,116,34,32,120,61,34,37,103,34,32,121,61,34,37,103,34,0],"i8",c,5331340);d([47,112,117,98,117,57,47,49,0],"i8",c,5331420);d([60,47,118,58,114,101,99,116,62,10,0],"i8",c,5331432);d([47,112,117,98,117,56,47,56,0],"i8",c,5331444);d([47,112,117,98,117,56,47,55,0],"i8",c,5331456);d([9,9,9,116,101,120,116,32,115,116,114,105,110,103,119,105,100,116,104,32,112,111,112,32,119,105,100,116,104,32,101,120,99,104,32,115,117,98,32,116,101,120,116,32,108,101,110,103,116,104,32,100,105,118,32,48,32,116,101,120,116,32,97,115,104,111,119,0],"i8",c,5331468);d([47,112,117,98,117,56,47,54,0],"i8",c,5331536);d([108,105,103,104,116,115,97,108,109,111,110,0],"i8",c,5331548);d([110,111,106,117,115,116,105,102,121,0],"i8",c,5331560);d([47,97,99,99,101,110,116,52,47,51,0],"i8",c,5331572);d([47,112,117,98,117,56,47,53,0],"i8",c,5331584);d([79,117,109,108,0],"i8",c,5331596);d([47,112,117,98,117,56,47,52,0],"i8",c,5331604);d([47,112,117,98,117,56,47,51,0],"i8",c,5331616);d([47,112,117,98,117,56,47,50,0],"i8",c,5331628);d([47,112,117,98,117,56,47,49,0],"i8",c,5331640);d([47,98,108,117,101,115,57,47,57,0],"i8",c,5331652);d([58,0],"i8",c,5331664);d([47,112,117,98,117,55,47,55,0],"i8",c,5331668);d([60,110,105,108,62,0],"i8",c,5331680);d([60,105,109,97,103,101,32,120,108,105,110,107,58,104,114,101,102,61,34,0],"i8",c,5331688);d([47,112,117,98,117,55,47,54,0],"i8",c,5331708);d([60,47,99,101,110,116,101,114,62,60,47,118,58,116,101,120,116,98,111,120,62,10,0],"i8",c,5331720);d([47,112,117,98,117,55,47,53,0],"i8",c,5331744);d([47,112,117,98,117,55,47,52,0],"i8",c,5331756);d([9,9,9,91,93,32,48,32,115,101,116,100,97,115,104,0],"i8",c,5331768);d([47,112,117,98,117,55,47,51,0],"i8",c,5331784);d([108,105,103,104,116,112,105,110,107,0],"i8",c,5331796);d([105,109,97,103,101,115,99,97,108,101,0],"i8",c,5331808);d([106,112,101,103,58,102,105,103,0],"i8",c,5331820);d([47,112,117,98,117,55,47,50,0],"i8",c,5331832);d([79,116,105,108,100,101,0],"i8",c,5331844);d([47,112,117,98,117,55,47,49,0],"i8",c,5331852);d([47,112,117,98,117,54,47,54,0],"i8",c,5331864);d([105,110,32,101,100,103,101,32,37,115,37,115,37,115,10,0],"i8",c,5331876);d([47,112,117,98,117,54,47,53,0],"i8",c,5331892);d([47,112,117,98,117,54,47,52,0],"i8",c,5331904);d([47,98,108,117,101,115,57,47,56,0],"i8",c,5331916);d([47,112,117,98,117,54,47,51,0],"i8",c,5331928);d([78,111,32,111,114,32,105,109,112,114,111,112,101,114,32,115,104,97,112,101,102,105,108,101,61,34,37,115,34,32,102,111,114,32,110,111,100,101,32,34,37,115,34,10,0],"i8",c,5331940);d([32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,10,0],"i8",c,5331988);d([47,112,117,98,117,54,47,50,0],"i8",c,5332020);d([34,62,60,99,101,110,116,101,114,62,0],"i8",c,5332032);d([47,112,117,98,117,54,47,49,0],"i8",c,5332044);d([109,101,114,103,101,95,111,110,101,119,97,121,32,103,108,105,116,99,104,10,0],"i8",c,5332056);d([47,112,117,98,117,53,47,53,0],"i8",c,5332080);d([9,9,119,105,100,116,104,32,48,32,103,116,32,123,0],"i8",c,5332092);d([47,112,117,98,117,53,47,52,0],"i8",c,5332108);d([108,105,103,104,116,103,114,101,121,0],"i8",c,5332120);d([45,45,0],"i8",c,5332132);d([102,105,120,101,100,115,105,122,101,0],"i8",c,5332136);d([47,112,117,98,117,53,47,51,0],"i8",c,5332148);d([79,115,108,97,115,104,0],"i8",c,5332160);d([47,112,117,98,117,53,47,50,0],"i8",c,5332168);d([47,112,117,98,117,53,47,49,0],"i8",c,5332180);d([47,112,117,98,117,52,47,52,0],"i8",c,5332192);d([47,112,117,98,117,52,47,51,0],"i8",c,5332204);d([47,98,108,117,101,115,57,47,55,0],"i8",c,5332216);d([69,114,114,111,114,32,100,117,114,105,110,103,32,99,111,110,118,101,114,115,105,111,110,32,116,111,32,34,85,84,70,45,56,34,46,32,32,81,117,105,116,105,110,103,46,10,0],"i8",c,5332228);d([47,112,117,98,117,52,47,50,0],"i8",c,5332276);d([114,101,103,117,108,97,114,0],"i8",c,5332288);d([37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,46,49,102,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,10,32,37,100,32,37,115,10,0],"i8",c,5332296);d([47,112,117,98,117,52,47,49,0],"i8",c,5332356);d([99,111,108,111,114,58,35,37,48,50,120,37,48,50,120,37,48,50,120,59,0],"i8",c,5332368);d([47,112,117,98,117,51,47,51,0],"i8",c,5332392);d([68,111,119,110,0],"i8",c,5332404);d([47,112,117,98,117,51,47,50,0],"i8",c,5332412);d([32,45,100,97,115,104,32,50,0],"i8",c,5332424);d([9,103,115,97,118,101,0],"i8",c,5332436);d([47,112,117,98,117,51,47,49,0],"i8",c,5332444);d([108,105,103,104,116,103,114,101,101,110,0],"i8",c,5332456);d([100,105,115,116,111,114,116,105,111,110,0],"i8",c,5332468);d([47,112,114,103,110,57,47,57,0],"i8",c,5332480);d([79,109,105,99,114,111,110,0],"i8",c,5332492);d([47,112,114,103,110,57,47,56,0],"i8",c,5332500);d([47,112,114,103,110,57,47,55,0],"i8",c,5332512);d([37,115,45,37,115,0],"i8",c,5332524);d([47,112,114,103,110,57,47,54,0],"i8",c,5332532);d([87,97,114,110,105,110,103,0],"i8",c,5332544);d([47,112,114,103,110,57,47,53,0],"i8",c,5332552);d([47,98,108,117,101,115,57,47,54,0],"i8",c,5332564);d([47,112,114,103,110,57,47,52,0],"i8",c,5332576);d([37,108,102,44,37,108,102,0],"i8",c,5332588);d([125,10,0],"i8",c,5332596);d([108,97,98,101,108,0],"i8",c,5332600);d([47,112,114,103,110,57,47,51,0],"i8",c,5332608);d([99,111,108,111,114,58,37,115,59,0],"i8",c,5332620);d([47,112,114,103,110,57,47,50,0],"i8",c,5332632);d([47,112,114,103,110,57,47,49,0],"i8",c,5332644);d([9,47,119,105,100,116,104,32,101,120,99,104,32,100,101,102,0],"i8",c,5332656);d([47,112,114,103,110,56,47,56,0],"i8",c,5332676);d([108,105,103,104,116,103,114,97,121,0],"i8",c,5332688);d([115,107,101,119,0],"i8",c,5332700);d([47,112,114,103,110,56,47,55,0],"i8",c,5332708);d([79,109,101,103,97,0],"i8",c,5332720);d([47,112,114,103,110,56,47,54,0],"i8",c,5332728);d([99,97,110,111,110,58,100,111,116,0],"i8",c,5332740);d([47,112,114,103,110,56,47,53,0],"i8",c,5332752);d([98,101,122,45,62,101,102,108,97,103,0],"i8",c,5332764);d([47,112,114,103,110,56,47,52,0],"i8",c,5332776);d([47,112,114,103,110,56,47,51,0],"i8",c,5332788);d([47,98,108,117,101,115,57,47,53,0],"i8",c,5332800);d([99,97,110,110,111,116,32,109,97,108,108,111,99,32,100,113,46,112,110,108,115,0],"i8",c,5332812);d([47,112,114,103,110,56,47,50,0],"i8",c,5332836);d([109,97,114,103,105,110,0],"i8",c,5332848);d([32,32,125,10,0],"i8",c,5332856);d([47,112,114,103,110,56,47,49,0],"i8",c,5332864);d([32,102,111,110,116,45,115,105,122,101,58,32,37,46,50,102,112,116,59,0],"i8",c,5332876);d([76,97,121,111,117,116,32,119,97,115,32,110,111,116,32,100,111,110,101,10,0],"i8",c,5332896);d([66,69,71,73,78,0],"i8",c,5332920);d([47,112,114,103,110,55,47,55,0],"i8",c,5332928);d([47,112,114,103,110,55,47,54,0],"i8",c,5332940);d([9,47,116,101,120,116,32,101,120,99,104,32,100,101,102,0],"i8",c,5332952);d([47,112,114,103,110,55,47,53,0],"i8",c,5332968);d([108,105,103,104,116,103,111,108,100,101,110,114,111,100,121,101,108,108,111,119,0],"i8",c,5332980);d([112,101,114,105,112,104,101,114,105,101,115,0],"i8",c,5333004);d([98,101,105,103,101,0],"i8",c,5333016);d([47,112,114,103,110,55,47,52,0],"i8",c,5333024);d([79,103,114,97,118,101,0],"i8",c,5333036);d([47,112,114,103,110,55,47,51,0],"i8",c,5333044);d([47,112,114,103,110,55,47,50,0],"i8",c,5333056);d([47,112,114,103,110,55,47,49,0],"i8",c,5333068);d([47,112,114,103,110,54,47,54,0],"i8",c,5333080);d([47,98,108,117,101,115,57,47,52,0],"i8",c,5333092);d([47,112,114,103,110,54,47,53,0],"i8",c,5333104);d([35,37,50,120,37,50,120,37,50,120,37,50,120,0],"i8",c,5333116);d([32,32,32,32,116,101,120,116,117,114,101,32,73,109,97,103,101,84,101,120,116,117,114,101,32,123,32,117,114,108,32,34,37,115,34,32,125,10,0],"i8",c,5333132);d([47,112,114,103,110,54,47,52,0],"i8",c,5333172);d([102,111,110,116,45,115,116,121,108,101,58,32,37,115,59,0],"i8",c,5333184);d([47,112,114,103,110,54,47,51,0],"i8",c,5333200);d([47,112,114,103,110,54,47,50,0],"i8",c,5333212);d([115,97,109,101,0],"i8",c,5333224);d([109,97,112,0],"i8",c,5333232);d([47,112,114,103,110,54,47,49,0],"i8",c,5333236);d([108,105,103,104,116,99,121,97,110,0],"i8",c,5333248);d([119,105,100,116,104,61,34,37,108,102,37,50,115,34,0],"i8",c,5333260);d([115,105,100,101,115,0],"i8",c,5333276);d([69,100,103,101,32,108,101,110,103,116,104,32,37,102,32,108,97,114,103,101,114,32,116,104,97,110,32,109,97,120,105,109,117,109,32,37,117,32,97,108,108,111,119,101,100,46,10,67,104,101,99,107,32,102,111,114,32,111,118,101,114,119,105,100,101,32,110,111,100,101,40,115,41,46,10,0],"i8",c,5333284);d([47,112,114,103,110,53,47,53,0],"i8",c,5333360);d([32,69,110,99,111,100,105,110,103,86,101,99,116,111,114,32,48,0],"i8",c,5333372);d([79,99,105,114,99,0],"i8",c,5333392);d([47,97,108,105,103,110,101,100,116,101,120,116,32,123,9,9,9,37,32,119,105,100,116,104,32,116,101,120,116,0],"i8",c,5333400);d([47,112,114,103,110,53,47,52,0],"i8",c,5333432);d([47,112,114,103,110,53,47,51,0],"i8",c,5333444);d([47,112,114,103,110,53,47,50,0],"i8",c,5333456);d([115,112,108,105,110,101,115,46,99,0],"i8",c,5333468);d([47,112,114,103,110,53,47,49,0],"i8",c,5333480);d([47,98,108,117,101,115,57,47,51,0],"i8",c,5333492);d([47,112,114,103,110,52,47,52,0],"i8",c,5333504);d([98,97,100,32,108,97,98,101,108,32,102,111,114,109,97,116,32,37,115,10,0],"i8",c,5333516);d([32,32,32,32,125,10,0],"i8",c,5333540);d([47,112,114,103,110,52,47,51,0],"i8",c,5333548);d([102,111,110,116,45,115,116,114,101,116,99,104,58,32,37,115,59,0],"i8",c,5333560);d([47,112,114,103,110,52,47,50,0],"i8",c,5333580);d([47,112,114,103,110,52,47,49,0],"i8",c,5333592);d([37,32,100,114,97,119,32,116,101,120,116,32,102,105,116,116,101,100,32,116,111,32,105,116,115,32,101,120,112,101,99,116,101,100,32,119,105,100,116,104,0],"i8",c,5333604);d([47,112,114,103,110,51,47,51,0],"i8",c,5333648);d([108,105,103,104,116,99,111,114,97,108,0],"i8",c,5333660);d([112,101,110,119,105,100,116,104,0],"i8",c,5333672);d([47,112,114,103,110,51,47,50,0],"i8",c,5333684);d([79,97,99,117,116,101,0],"i8",c,5333696);d([47,112,114,103,110,51,47,49,0],"i8",c,5333704);d([47,112,114,103,110,49,49,47,57,0],"i8",c,5333716);d([105,110,118,0],"i8",c,5333728);d([47,112,114,103,110,49,49,47,56,0],"i8",c,5333732);d([47,112,114,103,110,49,49,47,55,0],"i8",c,5333744);d([47,98,108,117,101,115,57,47,50,0],"i8",c,5333756);d([47,112,114,103,110,49,49,47,54,0],"i8",c,5333768);d([102,97,108,115,101,0],"i8",c,5333780);d([32,32,32,32,32,32,32,32,100,105,102,102,117,115,101,67,111,108,111,114,32,49,32,49,32,49,10,0],"i8",c,5333788);d([47,112,114,103,110,49,49,47,53,0],"i8",c,5333816);d([102,111,110,116,45,119,101,105,103,104,116,58,32,37,115,59,0],"i8",c,5333828);d([47,112,114,103,110,49,49,47,52,0],"i8",c,5333848);d([47,112,114,103,110,49,49,47,51,0],"i8",c,5333860);d([9,115,99,97,108,101,102,111,110,116,32,115,101,116,102,111,110,116,0],"i8",c,5333872);d([47,112,114,103,110,49,49,47,50,0],"i8",c,5333892);d([108,105,103,104,116,98,108,117,101,0],"i8",c,5333904);d([120,108,97,98,101,108,0],"i8",c,5333916);d([47,112,114,103,110,49,49,47,49,49,0],"i8",c,5333924);d([79,69,108,105,103,0],"i8",c,5333936);d([47,112,114,103,110,49,49,47,49,48,0],"i8",c,5333944);d([47,112,114,103,110,49,49,47,49,0],"i8",c,5333956);d([47,112,114,103,110,49,48,47,57,0],"i8",c,5333968);d([47,112,114,103,110,49,48,47,56,0],"i8",c,5333980);d([47,98,108,117,101,115,57,47,49,0],"i8",c,5333992);d([111,117,116,0],"i8",c,5334004);d([47,112,114,103,110,49,48,47,55,0],"i8",c,5334008);d([105,109,97,103,101,0],"i8",c,5334020);d([32,32,32,32,32,32,97,109,98,105,101,110,116,73,110,116,101,110,115,105,116,121,32,48,46,51,51,10,0],"i8",c,5334028);d([47,112,114,103,110,49,48,47,54,0],"i8",c,5334060);d([102,111,110,116,45,102,97,109,105,108,121,58,32,39,37,115,39,59,0],"i8",c,5334072);d([47,112,114,103,110,49,48,47,53,0],"i8",c,5334092);d([47,112,114,103,110,49,48,47,52,0],"i8",c,5334104);d([9,102,105,110,100,102,111,110,116,32,101,120,99,104,0],"i8",c,5334116);d([47,112,114,103,110,49,48,47,51,0],"i8",c,5334132);d([108,101,109,111,110,99,104,105,102,102,111,110,0],"i8",c,5334144);d([102,111,110,116,99,111,108,111,114,0],"i8",c,5334160);d([47,112,114,103,110,49,48,47,50,0],"i8",c,5334172);d([78,117,0],"i8",c,5334184);d([47,112,114,103,110,49,48,47,49,48,0],"i8",c,5334188);d([47,112,114,103,110,49,48,47,49,0],"i8",c,5334200);d([99,109,97,112,120,95,110,112,58,109,97,112,0],"i8",c,5334212);d([47,112,105,121,103,57,47,57,0],"i8",c,5334228);d([47,112,105,121,103,57,47,56,0],"i8",c,5334240);d([47,98,108,117,101,115,56,47,56,0],"i8",c,5334252);d([47,112,105,121,103,57,47,55,0],"i8",c,5334264);d([102,105,108,108,101,100,0,0],"i8",c,5334276);d([32,32,32,32,109,97,116,101,114,105,97,108,32,77,97,116,101,114,105,97,108,32,123,10,0],"i8",c,5334284);d([47,112,105,121,103,57,47,54,0],"i8",c,5334312);d([60,118,58,116,101,120,116,98,111,120,32,105,110,115,101,116,61,34,48,44,48,44,48,44,48,34,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,32,118,45,116,101,120,116,45,119,114,97,112,112,105,110,103,58,39,102,97,108,115,101,39,59,112,97,100,100,105,110,103,58,39,48,39,59,0],"i8",c,5334324);d([47,112,105,121,103,57,47,53,0],"i8",c,5334416);d([47,112,105,121,103,57,47,52,0],"i8",c,5334428);d([47,115,101,116,95,102,111,110,116,32,123,0],"i8",c,5334440);d([47,112,105,121,103,57,47,51,0],"i8",c,5334452);d([108,97,119,110,103,114,101,101,110,0],"i8",c,5334464);d([102,111,110,116,110,97,109,101,0],"i8",c,5334476);d([47,97,99,99,101,110,116,52,47,50,0],"i8",c,5334488);d([47,112,105,121,103,57,47,50,0],"i8",c,5334500);d([78,116,105,108,100,101,0],"i8",c,5334512);d([47,112,105,121,103,57,47,49,0],"i8",c,5334520);d([47,112,105,121,103,56,47,56,0],"i8",c,5334532);d([47,112,105,121,103,56,47,55,0],"i8",c,5334544);d([47,112,105,121,103,56,47,54,0],"i8",c,5334556);d([47,98,108,117,101,115,56,47,55,0],"i8",c,5334568);d([47,112,105,121,103,56,47,53,0],"i8",c,5334580);d([105,110,118,105,115,0,0],"i8",c,5334592);d([32,32,97,112,112,101,97,114,97,110,99,101,32,65,112,112,101,97,114,97,110,99,101,32,123,10,0],"i8",c,5334600);d([47,112,105,121,103,56,47,52,0],"i8",c,5334628);d([32,115,116,114,111,107,101,100,61,34,102,97,108,115,101,34,32,102,105,108,108,101,100,61,34,102,97,108,115,101,34,62,10,0],"i8",c,5334640);d([47,112,105,121,103,56,47,51,0],"i8",c,5334676);d([47,112,105,121,103,56,47,50,0],"i8",c,5334688);d([9,125,32,105,102,0],"i8",c,5334700);d([47,112,105,121,103,56,47,49,0],"i8",c,5334708);d([108,97,118,101,110,100,101,114,98,108,117,115,104,0],"i8",c,5334720);d([101,0],"i8",c,5334736);d([102,111,110,116,115,105,122,101,0],"i8",c,5334740);d([103,105,102,58,102,105,103,0],"i8",c,5334752);d([47,112,105,121,103,55,47,55,0],"i8",c,5334760);d([77,117,0],"i8",c,5334772);d([47,112,105,121,103,55,47,54,0],"i8",c,5334776);d([47,112,105,121,103,55,47,53,0],"i8",c,5334788);d([9,37,115,32,37,100,10,0],"i8",c,5334800);d([47,112,105,121,103,55,47,52,0],"i8",c,5334808);d([47,112,105,121,103,55,47,51,0],"i8",c,5334820);d([47,98,108,117,101,115,56,47,54,0],"i8",c,5334832);d([47,112,105,121,103,55,47,50,0],"i8",c,5334844);d([35,102,56,102,56,102,56,0],"i8",c,5334856);d([83,104,97,112,101,32,123,10,0],"i8",c,5334864);d([47,112,105,121,103,55,47,49,0],"i8",c,5334876);d([60,118,58,114,101,99,116,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,32,0],"i8",c,5334888);d([47,112,105,121,103,54,47,54,0],"i8",c,5334924);d([47,112,105,121,103,54,47,53,0],"i8",c,5334936);d([118,105,114,116,117,97,108,0],"i8",c,5334948);d([9,9,103,114,101,115,116,111,114,101,0],"i8",c,5334956);d([47,112,105,121,103,54,47,52,0],"i8",c,5334968);d([108,97,118,101,110,100,101,114,0],"i8",c,5334980);d([115,116,121,108,101,0],"i8",c,5334992);d([47,112,105,121,103,54,47,51,0],"i8",c,5335e3);d([76,97,109,98,100,97,0],"i8",c,5335012);d([47,112,105,121,103,54,47,50,0],"i8",c,5335020);d([47,112,105,121,103,54,47,49,0],"i8",c,5335032);d([98,122,46,115,105,122,101,32,37,32,51,32,61,61,32,49,0],"i8",c,5335044);d([47,112,105,121,103,53,47,53,0],"i8",c,5335064);d([47,112,105,121,103,53,47,52,0],"i8",c,5335076);d([47,98,108,117,101,115,56,47,53,0],"i8",c,5335088);d([38,35,51,57,59,0],"i8",c,5335100);d([47,112,105,121,103,53,47,51,0],"i8",c,5335108);d([35,49,48,49,48,49,48,0],"i8",c,5335120);d([110,0],"i8",c,5335128);d([47,112,105,121,103,53,47,50,0],"i8",c,5335132);d([60,47,118,58,111,118,97,108,62,10,0],"i8",c,5335144);d([47,112,105,121,103,53,47,49,0],"i8",c,5335156);d([47,112,105,121,103,52,47,52,0],"i8",c,5335168);d([32,45,100,97,115,104,32,53,0],"i8",c,5335180);d([75,80,95,85,112,0],"i8",c,5335192);d([9,9,9,40,92,40,41,32,115,104,111,119,32,105,32,115,116,114,32,99,118,115,32,115,104,111,119,32,40,44,41,32,115,104,111,119,32,106,32,115,116,114,32,99,118,115,32,115,104,111,119,32,40,92,41,41,32,115,104,111,119,0],"i8",c,5335200);d([47,112,105,121,103,52,47,51,0],"i8",c,5335264);d([107,104,97,107,105,0],"i8",c,5335276);d([102,105,108,108,99,111,108,111,114,0],"i8",c,5335284);d([47,112,105,121,103,52,47,50,0],"i8",c,5335296);d([75,97,112,112,97,0],"i8",c,5335308);d([47,112,105,121,103,52,47,49,0],"i8",c,5335316);d([47,112,105,121,103,51,47,51,0],"i8",c,5335328);d([98,122,46,115,105,122,101,32,62,32,48,0],"i8",c,5335340);d([47,112,105,121,103,51,47,50,0],"i8",c,5335352);d([47,112,105,121,103,51,47,49,0],"i8",c,5335364);d([47,98,108,117,101,115,56,47,52,0],"i8",c,5335376);d([69,114,114,111,114,0],"i8",c,5335388);d([47,112,105,121,103,49,49,47,57,0],"i8",c,5335396);d([35,102,48,102,48,102,48,0],"i8",c,5335408);d([111,98,106,0],"i8",c,5335416);d([47,112,105,121,103,49,49,47,56,0],"i8",c,5335420);d([32,119,105,100,116,104,58,32,37,46,50,102,59,32,104,101,105,103,104,116,58,32,37,46,50,102,34,0],"i8",c,5335432);d([123,37,115,125,0],"i8",c,5335460);d([47,112,105,121,103,49,49,47,55,0],"i8",c,5335468);d([47,112,105,121,103,49,49,47,54,0],"i8",c,5335480);d([9,9,9,48,32,48,32,109,111,118,101,116,111,0],"i8",c,5335492);d([47,112,105,121,103,49,49,47,53,0],"i8",c,5335508);d([105,118,111,114,121,0],"i8",c,5335520);d([99,111,108,111,114,0],"i8",c,5335528);d([47,112,105,121,103,49,49,47,52,0],"i8",c,5335536);d([73,117,109,108,0],"i8",c,5335548);d([47,112,105,121,103,49,49,47,51,0],"i8",c,5335556);d([107,105,110,100,32,61,61,32,76,84,95,78,79,78,69,0],"i8",c,5335568);d([103,118,58,100,111,116,0],"i8",c,5335584);d([47,112,105,121,103,49,49,47,50,0],"i8",c,5335592);d([115,112,108,45,62,115,105,122,101,32,62,32,48,0],"i8",c,5335604);d([98,101,122,45,62,115,102,108,97,103,0],"i8",c,5335620);d([100,105,103,114,97,112,104,0],"i8",c,5335632);d([47,112,105,121,103,49,49,47,49,49,0],"i8",c,5335640);d([47,112,105,121,103,49,49,47,49,48,0],"i8",c,5335652);d([47,98,108,117,101,115,56,47,51,0],"i8",c,5335664);d([37,100,0],"i8",c,5335676);d([99,97,110,110,111,116,32,114,101,97,108,108,111,99,32,111,112,115,0],"i8",c,5335680);d([47,112,105,121,103,49,49,47,49,0],"i8",c,5335700);d([35,101,48,101,48,101,48,0],"i8",c,5335712);d([103,114,101,115,116,111,114,101,10,0],"i8",c,5335720);d([47,112,105,121,103,49,48,47,57,0],"i8",c,5335732);d([32,108,101,102,116,58,32,37,46,50,102,59,32,116,111,112,58,32,37,46,50,102,59,0],"i8",c,5335744);d([78,111,32,108,105,98,122,32,115,117,112,112,111,114,116,10,0],"i8",c,5335768);d([69,79,70,0],"i8",c,5335788);d([47,112,105,121,103,49,48,47,56,0],"i8",c,5335792);d([68,105,110,103,98,97,116,115,0],"i8",c,5335804);d([47,112,105,121,103,49,48,47,55,0],"i8",c,5335816);d([9,9,9,99,111,111,114,100,102,111,110,116,32,115,101,116,102,111,110,116,0],"i8",c,5335828);d([47,112,105,121,103,49,48,47,54,0],"i8",c,5335852);d([105,110,100,105,103,111,0],"i8",c,5335864);d([115,104,97,112,101,0],"i8",c,5335872);d([97,122,117,114,101,0],"i8",c,5335880);d([47,112,105,121,103,49,48,47,53,0],"i8",c,5335888);d([73,111,116,97,0],"i8",c,5335900);d([47,112,105,121,103,49,48,47,52,0],"i8",c,5335908);d([47,112,105,121,103,49,48,47,51,0],"i8",c,5335920);d([115,104,97,112,101,115,46,99,0],"i8",c,5335932);d([115,101,116,108,105,110,101,119,105,100,116,104,0,49,0,0],"i8",c,5335944);d([47,112,105,121,103,49,48,47,50,0],"i8",c,5335960);d([47,112,105,121,103,49,48,47,49,48,0],"i8",c,5335972);d([47,98,108,117,101,115,56,47,50,0],"i8",c,5335984);d([112,110,103,58,115,118,103,0],"i8",c,5335996);d([47,112,105,121,103,49,48,47,49,0],"i8",c,5336004);d([35,101,56,101,56,101,56,0],"i8",c,5336016);d([117,115,101,114,95,115,104,97,112,101,95,37,100,10,0],"i8",c,5336024);d([47,112,97,115,116,101,108,50,56,47,56,0],"i8",c,5336040);d([32,32,60,118,58,111,118,97,108,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,0],"i8",c,5336052);d([47,112,97,115,116,101,108,50,56,47,55,0],"i8",c,5336088);d([90,97,112,102,68,105,110,103,98,97,116,115,0],"i8",c,5336100);d([47,112,97,115,116,101,108,50,56,47,54,0],"i8",c,5336116);d([97,103,116,97,105,108,40,101,41,32,61,61,32,85,70,95,102,105,110,100,40,97,103,116,97,105,108,40,101,41,41,0],"i8",c,5336128);d([9,9,103,115,97,118,101,0],"i8",c,5336160);d([47,112,97,115,116,101,108,50,56,47,53,0],"i8",c,5336168);d([105,110,100,105,97,110,114,101,100,0],"i8",c,5336180);d([99,111,110,116,97,105,110,95,110,111,100,101,115,32,99,108,117,115,116,32,37,115,32,114,97,110,107,32,37,100,32,109,105,115,115,105,110,103,32,110,111,100,101,10,0],"i8",c,5336192);d([47,112,97,115,116,101,108,50,56,47,52,0],"i8",c,5336240);d([47,69,110,99,111,100,105,110,103,86,101,99,116,111,114,32,50,53,54,32,97,114,114,97,121,32,100,101,102,0],"i8",c,5336252);d([73,103,114,97,118,101,0],"i8",c,5336284);d([47,112,97,115,116,101,108,50,56,47,51,0],"i8",c,5336292);d([105,110,118,105,115,105,98,108,101,0],"i8",c,5336304);d([47,112,97,115,116,101,108,50,56,47,50,0],"i8",c,5336316);d([115,111,108,105,100,0,0],"i8",c,5336328);d([47,112,97,115,116,101,108,50,56,47,49,0],"i8",c,5336336);d([47,112,97,115,116,101,108,50,55,47,55,0],"i8",c,5336348);d([47,98,108,117,101,115,56,47,49,0],"i8",c,5336360);d([47,112,97,115,116,101,108,50,55,47,54,0],"i8",c,5336372);d([35,51,48,51,48,51,48,0],"i8",c,5336384);d([103,115,97,118,101,32,37,103,32,37,103,32,116,114,97,110,115,108,97,116,101,32,110,101,119,112,97,116,104,10,0],"i8",c,5336392);d([47,112,97,115,116,101,108,50,55,47,53,0],"i8",c,5336424);d([120,32,101,32,34,47,62,0],"i8",c,5336436);d([47,112,97,115,116,101,108,50,55,47,52,0],"i8",c,5336444);d([99,97,110,110,111,116,32,97,108,108,111,99,97,116,101,32,112,115,10,0],"i8",c,5336456);d([109,101,100,105,117,109,0],"i8",c,5336476);d([47,112,97,115,116,101,108,50,55,47,51,0],"i8",c,5336484);d([9,110,112,97,103,101,115,32,49,32,103,116,32,123,0],"i8",c,5336496);d([47,112,97,115,116,101,108,50,55,47,50,0],"i8",c,5336512);d([104,111,116,112,105,110,107,0],"i8",c,5336524);d([100,121,110,97,109,105,99,32,108,111,97,100,105,110,103,32,110,111,116,32,97,118,97,105,108,97,98,108,101,10,0],"i8",c,5336532);d([47,112,97,115,116,101,108,50,55,47,49,0],"i8",c,5336564);d([73,99,105,114,99,0],"i8",c,5336576);d([47,112,97,115,116,101,108,50,54,47,54,0],"i8",c,5336584);d([47,112,97,115,116,101,108,50,54,47,53,0],"i8",c,5336596);d([47,112,97,115,116,101,108,50,54,47,52,0],"i8",c,5336608);d([47,112,97,115,116,101,108,50,54,47,51,0],"i8",c,5336620);d([47,98,108,117,101,115,55,47,55,0],"i8",c,5336632);d([47,112,97,115,116,101,108,50,54,47,50,0],"i8",c,5336644);d([35,102,99,102,99,102,99,0],"i8",c,5336656);d([93,32,32,37,100,32,102,97,108,115,101,32,37,115,10,0],"i8",c,5336664);d([47,112,97,115,116,101,108,50,54,47,49,0],"i8",c,5336680);d([108,32,0],"i8",c,5336692);d([47,112,97,115,116,101,108,50,53,47,53,0],"i8",c,5336696);d([85,82,87,32,67,104,97,110,99,101,114,121,32,76,0],"i8",c,5336708);d([47,112,97,115,116,101,108,50,53,47,52,0],"i8",c,5336724);d([9,47,115,116,114,32,49,48,32,115,116,114,105,110,103,32,100,101,102,0],"i8",c,5336736);d([47,112,97,115,116,101,108,50,53,47,51,0],"i8",c,5336756);d([104,111,110,101,121,100,101,119,0],"i8",c,5336768);d([111,114,100,101,114,105,110,103,0],"i8",c,5336780);d([47,112,97,115,116,101,108,50,53,47,50,0],"i8",c,5336792);d([73,97,99,117,116,101,0],"i8",c,5336804);d([47,112,97,115,116,101,108,50,53,47,49,0],"i8",c,5336812);d([47,112,97,115,116,101,108,50,52,47,52,0],"i8",c,5336824);d([47,112,97,115,116,101,108,50,52,47,51,0],"i8",c,5336836);d([47,112,97,115,116,101,108,50,52,47,50,0],"i8",c,5336848);d([47,98,108,117,101,115,55,47,54,0],"i8",c,5336860);d([47,112,97,115,116,101,108,50,52,47,49,0],"i8",c,5336872);d([35,56,48,56,48,56,48,0],"i8",c,5336884);d([93,32,32,37,100,32,116,114,117,101,32,37,115,10,0],"i8",c,5336892);d([78,68,95,111,114,100,101,114,40,118,41,32,60,32,78,68,95,111,114,100,101,114,40,119,41,0],"i8",c,5336908);d([47,112,97,115,116,101,108,50,51,47,51,0],"i8",c,5336936);d([37,46,48,102,32,37,46,48,102,32,0],"i8",c,5336948);d([47,112,97,115,116,101,108,50,51,47,50,0],"i8",c,5336960);d([90,97,112,102,67,104,97,110,99,101,114,121,45,77,101,100,105,117,109,73,116,97,108,105,99,0],"i8",c,5336972);d([47,112,97,115,116,101,108,50,51,47,49,0],"i8",c,5337e3);d([9,47,105,32,101,120,99,104,32,100,101,102,0],"i8",c,5337012);d([47,112,97,115,116,101,108,49,57,47,57,0],"i8",c,5337028);d([103,114,101,121,0],"i8",c,5337040);d([114,101,115,111,108,117,116,105,111,110,0],"i8",c,5337048);d([47,112,97,115,116,101,108,49,57,47,56,0],"i8",c,5337060);d([71,97,109,109,97,0],"i8",c,5337072);d([47,112,97,115,116,101,108,49,57,47,55,0],"i8",c,5337080);d([115,121,110,116,97,120,32,101,114,114,111,114,0],"i8",c,5337092);d([47,112,97,115,116,101,108,49,57,47,54,0],"i8",c,5337108);d([47,112,97,115,116,101,108,49,57,47,53,0],"i8",c,5337120);d([105,109,97,112,95,110,112,58,109,97,112,0],"i8",c,5337132);d([47,112,97,115,116,101,108,49,57,47,52,0],"i8",c,5337144);d([47,98,108,117,101,115,55,47,53,0],"i8",c,5337156);d([47,112,97,115,116,101,108,49,57,47,51,0],"i8",c,5337168);d([37,103,32,37,103,32,0],"i8",c,5337180);d([47,112,97,115,116,101,108,49,57,47,50,0],"i8",c,5337188);d([32,102,105,108,108,101,100,61,34,102,97,108,115,101,34,32,0],"i8",c,5337200);d([47,112,97,115,116,101,108,49,57,47,49,0],"i8",c,5337220);d([47,112,97,115,116,101,108,49,56,47,56,0],"i8",c,5337232);d([9,47,106,32,101,120,99,104,32,100,101,102,0],"i8",c,5337244);d([47,112,97,115,116,101,108,49,56,47,55,0],"i8",c,5337260);d([103,114,101,101,110,121,101,108,108,111,119,0],"i8",c,5337272);d([100,112,105,0],"i8",c,5337284);d([47,97,99,99,101,110,116,52,47,49,0],"i8",c,5337288);d([47,112,97,115,116,101,108,49,56,47,54,0],"i8",c,5337300);d([69,117,109,108,0],"i8",c,5337312);d([47,112,97,115,116,101,108,49,56,47,53,0],"i8",c,5337320);d([47,112,97,115,116,101,108,49,56,47,52,0],"i8",c,5337332);d([112,97,103,101,100,105,114,0],"i8",c,5337344);d([47,112,97,115,116,101,108,49,56,47,51,0],"i8",c,5337352);d([47,112,97,115,116,101,108,49,56,47,50,0],"i8",c,5337364);d([47,98,108,117,101,115,55,47,52,0],"i8",c,5337376);d([47,112,97,115,116,101,108,49,56,47,49,0],"i8",c,5337388);d([100,105,97,103,111,110,97,108,115,0],"i8",c,5337400);d([91,32,0],"i8",c,5337412);d([47,112,97,115,116,101,108,49,55,47,55,0],"i8",c,5337416);d([34,32,0],"i8",c,5337428);d([47,112,97,115,116,101,108,49,55,47,54,0],"i8",c,5337432);d([47,112,97,115,116,101,108,49,55,47,53,0],"i8",c,5337444);d([84,105,109,101,115,45,73,116,97,108,105,99,0],"i8",c,5337456);d([9,47,110,112,97,103,101,115,32,101,120,99,104,32,100,101,102,0],"i8",c,5337472);d([47,112,97,115,116,101,108,49,55,47,52,0],"i8",c,5337492);d([99,111,110,99,101,110,116,114,97,116,101,0],"i8",c,5337504);d([115,0],"i8",c,5337516);d([112,110,103,58,102,105,103,0],"i8",c,5337520);d([47,112,97,115,116,101,108,49,55,47,51,0],"i8",c,5337528);d([69,116,97,0],"i8",c,5337540);d([105,110,32,99,104,101,99,107,112,97,116,104,44,32,98,111,120,32,37,100,32,104,97,115,32,76,76,32,99,111,111,114,100,32,62,32,85,82,32,99,111,111,114,100,10,0],"i8",c,5337544);d([47,112,97,115,116,101,108,49,55,47,50,0],"i8",c,5337592);d([47,112,97,115,116,101,108,49,55,47,49,0],"i8",c,5337604);d([66,76,0],"i8",c,5337616);d([116,114,111,117,98,108,101,32,105,110,32,105,110,105,116,95,114,97,110,107,10,0],"i8",c,5337620);d([47,112,97,115,116,101,108,49,54,47,54,0],"i8",c,5337644);d([47,112,97,115,116,101,108,49,54,47,53,0],"i8",c,5337656);d([47,98,108,117,101,115,55,47,51,0],"i8",c,5337668);d([47,112,97,115,116,101,108,49,54,47,52,0],"i8",c,5337680);d([114,111,117,110,100,101,100,0],"i8",c,5337692);d([117,115,45,62,110,97,109,101,0],"i8",c,5337700);d([47,112,97,115,116,101,108,49,54,47,51,0],"i8",c,5337712);d([32,102,105,108,108,101,100,61,34,116,114,117,101,34,32,102,105,108,108,99,111,108,111,114,61,34,0],"i8",c,5337724);d([47,112,97,115,116,101,108,49,54,47,50,0],"i8",c,5337752);d([47,112,97,115,116,101,108,49,54,47,49,0],"i8",c,5337764);d([84,105,109,101,115,45,66,111,108,100,73,116,97,108,105,99,0],"i8",c,5337776);d([47,98,101,103,105,110,112,97,103,101,32,123,9,37,32,105,32,106,32,110,112,97,103,101,115,0],"i8",c,5337796);d([47,112,97,115,116,101,108,49,53,47,53,0],"i8",c,5337824);d([99,108,117,115,116,101,114,114,97,110,107,0],"i8",c,5337836);d([102,105,110,100,95,102,97,115,116,95,110,111,100,101,40,103,44,32,110,41,0],"i8",c,5337848);d([47,112,97,115,116,101,108,49,53,47,52,0],"i8",c,5337872);d([69,112,115,105,108,111,110,0],"i8",c,5337884);d([47,112,97,115,116,101,108,49,53,47,51,0],"i8",c,5337892);d([47,112,97,115,116,101,108,49,53,47,50,0],"i8",c,5337904);d([112,97,100,0],"i8",c,5337916);d([47,112,97,115,116,101,108,49,53,47,49,0],"i8",c,5337920);d([47,112,97,115,116,101,108,49,52,47,52,0],"i8",c,5337932);d([47,98,108,117,101,115,55,47,50,0],"i8",c,5337944);d([38,113,117,111,116,59,0],"i8",c,5337956);d([47,112,97,115,116,101,108,49,52,47,51,0],"i8",c,5337964);d([117,115,0],"i8",c,5337976);d([47,112,97,115,116,101,108,49,52,47,50,0],"i8",c,5337980);d([34,0],"i8",c,5337992);d([47,112,97,115,116,101,108,49,52,47,49,0],"i8",c,5337996);d([47,112,97,115,116,101,108,49,51,47,51,0],"i8",c,5338008);d([84,105,109,101,115,0],"i8",c,5338020);d([32,45,102,105,108,108,32,0],"i8",c,5338028);d([47,110,111,112,99,111,108,111,114,32,123,112,111,112,32,112,111,112,32,112,111,112,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5338036);d([47,112,97,115,116,101,108,49,51,47,50,0],"i8",c,5338072);d([103,111,108,100,101,110,114,111,100,0],"i8",c,5338084);d([108,97,110,100,115,99,97,112,101,0],"i8",c,5338096);d([85,112,0],"i8",c,5338108);d([47,112,97,115,116,101,108,49,51,47,49,0],"i8",c,5338112);d([69,103,114,97,118,101,0],"i8",c,5338124);d([47,112,97,105,114,101,100,57,47,57,0],"i8",c,5338132);d([47,112,97,105,114,101,100,57,47,56,0],"i8",c,5338144);d([47,112,97,105,114,101,100,57,47,55,0],"i8",c,5338156);d([47,112,97,105,114,101,100,57,47,54,0],"i8",c,5338168);d([47,98,108,117,101,115,55,47,49,0],"i8",c,5338180);d([47,112,97,105,114,101,100,57,47,53,0],"i8",c,5338192);d([106,111,98,0],"i8",c,5338204);d([37,115,58,32,0],"i8",c,5338208);d([47,112,97,105,114,101,100,57,47,52,0],"i8",c,5338216);d(1,"i8",c,5338228);d([47,112,97,105,114,101,100,57,47,51,0],"i8",c,5338232);d([104,101,108,118,101,116,105,99,97,0],"i8",c,5338244);d([49,48,48,48,48,0],"i8",c,5338256);d([47,112,97,105,114,101,100,57,47,50,0],"i8",c,5338264);d([84,105,109,101,115,45,66,111,108,100,0],"i8",c,5338276);d([47,103,114,97,112,104,99,111,108,111,114,32,123,32,115,101,116,104,115,98,99,111,108,111,114,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5338288);d([47,112,97,105,114,101,100,57,47,49,0],"i8",c,5338328);d([103,111,108,100,0],"i8",c,5338340);d([111,114,105,101,110,116,97,116,105,111,110,0],"i8",c,5338348);d([47,112,97,105,114,101,100,56,47,56,0],"i8",c,5338360);d([69,99,105,114,99,0],"i8",c,5338372);d([47,112,97,105,114,101,100,56,47,55,0],"i8",c,5338380);d([108,97,98,101,108,115,46,99,0],"i8",c,5338392);d([100,111,116,58,100,111,116,0],"i8",c,5338404);d([47,112,97,105,114,101,100,56,47,54,0],"i8",c,5338412);d([99,111,109,112,111,117,110,100,46,99,0],"i8",c,5338424);d([47,112,97,105,114,101,100,56,47,53,0],"i8",c,5338436);d([115,116,114,105,99,116,32,0],"i8",c,5338448);d([47,112,97,105,114,101,100,56,47,52,0],"i8",c,5338456);d([47,98,108,117,101,115,54,47,54,0],"i8",c,5338468);d([108,105,98,112,97,116,104,47,37,115,58,37,100,58,32,37,115,10,0],"i8",c,5338480);d([47,112,97,105,114,101,100,56,47,51,0],"i8",c,5338500);d([103,118,108,111,97,100,105,109,97,103,101,95,99,111,114,101,46,99,0],"i8",c,5338512);d([47,112,97,105,114,101,100,56,47,50,0],"i8",c,5338532);d([99,32,0],"i8",c,5338544);d([47,112,97,105,114,101,100,56,47,49,0],"i8",c,5338548);d([99,97,110,39,116,32,111,112,101,110,32,108,105,98,114,97,114,121,32,102,105,108,101,32,37,115,10,0],"i8",c,5338560);d([47,112,97,105,114,101,100,55,47,55,0],"i8",c,5338588);d([102,97,110,116,97,115,121,0],"i8",c,5338600);d([47,101,100,103,101,99,111,108,111,114,32,123,32,115,101,116,104,115,98,99,111,108,111,114,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5338608);d([47,112,97,105,114,101,100,55,47,54,0],"i8",c,5338644);d([103,104,111,115,116,119,104,105,116,101,0],"i8",c,5338656);d([114,111,116,97,116,101,0],"i8",c,5338668);d([97,113,117,97,109,97,114,105,110,101,0],"i8",c,5338676);d([47,112,97,105,114,101,100,55,47,53,0],"i8",c,5338688);d([69,97,99,117,116,101,0],"i8",c,5338700);d([47,112,97,105,114,101,100,55,47,52,0],"i8",c,5338708);d([47,112,97,105,114,101,100,55,47,51,0],"i8",c,5338720);d([58,9,32,0],"i8",c,5338732);d([47,112,97,105,114,101,100,55,47,50,0],"i8",c,5338736);d([1,112,114,111,116,111,0],"i8",c,5338748);d([47,112,97,105,114,101,100,55,47,49,0],"i8",c,5338756);d([47,98,108,117,101,115,54,47,53,0],"i8",c,5338768);d([47,112,97,105,114,101,100,54,47,54,0],"i8",c,5338780);d([32,47,62,10,0],"i8",c,5338792);d([47,112,97,105,114,101,100,54,47,53,0],"i8",c,5338800);d([37,115,37,46,48,102,44,37,46,48,102,32,0],"i8",c,5338812);d([47,112,97,105,114,101,100,54,47,52,0],"i8",c,5338828);d([47,112,97,105,114,101,100,54,47,51,0],"i8",c,5338840);d([83,121,109,98,111,108,0],"i8",c,5338852);d([97,103,104,101,97,100,40,101,41,32,61,61,32,85,70,95,102,105,110,100,40,97,103,104,101,97,100,40,101,41,41,0],"i8",c,5338860);d([47,110,111,100,101,99,111,108,111,114,32,123,32,115,101,116,104,115,98,99,111,108,111,114,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5338892);d([47,112,97,105,114,101,100,54,47,50,0],"i8",c,5338928);d([103,97,105,110,115,98,111,114,111,0],"i8",c,5338940);d([34,37,115,34,32,119,97,115,32,110,111,116,32,102,111,117,110,100,32,97,115,32,97,32,102,105,108,101,32,111,114,32,97,115,32,97,32,115,104,97,112,101,32,108,105,98,114,97,114,121,32,109,101,109,98,101,114,10,0],"i8",c,5338952);d([99,101,110,116,101,114,0],"i8",c,5339012);d([47,112,97,105,114,101,100,54,47,49,0],"i8",c,5339020);d([109,97,114,107,0],"i8",c,5339032);d([69,84,72,0],"i8",c,5339040);d([99,97,110,110,111,116,32,109,97,108,108,111,99,32,111,112,115,0],"i8",c,5339044);d([47,112,97,105,114,101,100,53,47,53,0],"i8",c,5339064);d([47,112,97,105,114,101,100,53,47,52,0],"i8",c,5339076);d([108,97,121,101,114,115,101,112,0],"i8",c,5339088);d([47,112,97,105,114,101,100,53,47,51,0],"i8",c,5339100);d([47,112,97,105,114,101,100,53,47,50,0],"i8",c,5339112);d([47,98,108,117,101,115,54,47,52,0],"i8",c,5339124);d([47,112,97,105,114,101,100,53,47,49,0],"i8",c,5339136);d([110,111,100,101,32,37,115,44,32,112,111,114,116,32,37,115,32,117,110,114,101,99,111,103,110,105,122,101,100,10,0],"i8",c,5339148);d([60,118,58,105,109,97,103,101,32,115,114,99,61,34,37,115,34,32,115,116,121,108,101,61,34,32,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,32,119,105,100,116,104,58,37,46,50,102,59,32,104,101,105,103,104,116,58,37,46,50,102,59,32,108,101,102,116,58,37,46,50,102,32,59,32,116,111,112,58,37,46,50,102,34,0],"i8",c,5339180);d([47,112,97,105,114,101,100,52,47,52,0],"i8",c,5339272);d([109,32,0],"i8",c,5339284);d([47,112,97,105,114,101,100,52,47,51,0],"i8",c,5339288);d([47,112,97,105,114,101,100,52,47,50,0],"i8",c,5339300);d([80,97,108,97,116,105,110,111,45,82,111,109,97,110,0],"i8",c,5339312);d([37,32,104,111,111,107,115,32,102,111,114,32,115,101,116,116,105,110,103,32,99,111,108,111,114,32,0],"i8",c,5339328);d([47,112,97,105,114,101,100,52,47,49,0],"i8",c,5339356);d([112,97,103,101,0],"i8",c,5339368);d([47,112,97,105,114,101,100,51,47,51,0],"i8",c,5339376);d([68,101,108,116,97,0],"i8",c,5339388);d([47,112,97,105,114,101,100,51,47,50,0],"i8",c,5339396);d([47,112,97,105,114,101,100,51,47,49,0],"i8",c,5339408);d([108,97,121,101,114,115,0],"i8",c,5339420);d([47,112,97,105,114,101,100,49,50,47,57,0],"i8",c,5339428);d([47,112,97,105,114,101,100,49,50,47,56,0],"i8",c,5339440);d([47,98,108,117,101,115,54,47,51,0],"i8",c,5339452);d([47,112,97,105,114,101,100,49,50,47,55,0],"i8",c,5339464);d([110,111,100,101,32,37,115,44,32,112,111,114,116,32,37,115,44,32,117,110,114,101,99,111,103,110,105,122,101,100,32,99,111,109,112,97,115,115,32,112,111,105,110,116,32,39,37,115,39,32,45,32,105,103,110,111,114,101,100,10,0],"i8",c,5339476);d([106,112,103,58,118,109,108,0],"i8",c,5339540);d([47,112,97,105,114,101,100,49,50,47,54,0],"i8",c,5339548);d([47,62,60,47,118,58,115,104,97,112,101,62,10,0],"i8",c,5339560);d([47,112,97,105,114,101,100,49,50,47,53,0],"i8",c,5339576);d([47,112,97,105,114,101,100,49,50,47,52,0],"i8",c,5339588);d([80,97,108,97,116,105,110,111,45,73,116,97,108,105,99,0],"i8",c,5339600);d([47,100,105,97,103,111,110,97,108,115,32,123,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5339616);d([47,112,97,105,114,101,100,49,50,47,51,0],"i8",c,5339640);d([102,111,114,101,115,116,103,114,101,101,110,0],"i8",c,5339652);d([115,105,122,101,0],"i8",c,5339664);d([47,112,97,105,114,101,100,49,50,47,50,0],"i8",c,5339672);d([68,97,103,103,101,114,0],"i8",c,5339684);d([47,112,97,105,114,101,100,49,50,47,49,50,0],"i8",c,5339692);d([47,112,97,105,114,101,100,49,50,47,49,49,0],"i8",c,5339708);d([100,103,101,115,102,105,114,115,116,0],"i8",c,5339724);d([47,112,97,105,114,101,100,49,50,47,49,48,0],"i8",c,5339736);d([47,112,97,105,114,101,100,49,50,47,49,0],"i8",c,5339752);d([47,98,108,117,101,115,54,47,50,0],"i8",c,5339764);d([47,112,97,105,114,101,100,49,49,47,57,0],"i8",c,5339776);d([95,0],"i8",c,5339788);d([106,112,101,58,118,109,108,0],"i8",c,5339792);d([47,112,97,105,114,101,100,49,49,47,56,0],"i8",c,5339800);d([115,117,114,112,114,105,115,101,10,0],"i8",c,5339812);d([60,118,58,112,97,116,104,32,32,118,61,34,0],"i8",c,5339824);d([47,112,97,105,114,101,100,49,49,47,55,0],"i8",c,5339840);d([47,112,97,105,114,101,100,49,49,47,54,0],"i8",c,5339852);d([80,97,108,97,116,105,110,111,45,66,111,108,100,73,116,97,108,105,99,0],"i8",c,5339864);d([47,114,111,117,110,100,101,100,32,123,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5339884);d([47,112,97,105,114,101,100,49,49,47,53,0],"i8",c,5339908);d([102,108,111,114,97,108,119,104,105,116,101,0],"i8",c,5339920);d([102,111,110,116,110,97,109,101,115,0],"i8",c,5339932);d([47,112,97,105,114,101,100,49,49,47,52,0],"i8",c,5339944);d([67,104,105,0],"i8",c,5339956);d([47,112,97,105,114,101,100,49,49,47,51,0],"i8",c,5339960);d([47,112,97,105,114,101,100,49,49,47,50,0],"i8",c,5339972);d([111,100,101,115,102,105,114,115,116,0],"i8",c,5339984);d([47,112,97,105,114,101,100,49,49,47,49,49,0],"i8",c,5339996);d([47,112,97,105,114,101,100,49,49,47,49,48,0],"i8",c,5340012);d([47,98,108,117,101,115,54,47,49,0],"i8",c,5340028);d([99,109,97,112,120,58,109,97,112,0],"i8",c,5340040);d([47,112,97,105,114,101,100,49,49,47,49,0],"i8",c,5340052);d([37,46,53,103,32,37,46,53,103,32,116,114,97,110,115,108,97,116,101,32,110,101,119,112,97,116,104,32,117,115,101,114,95,115,104,97,112,101,95,37,100,10,0],"i8",c,5340064);d([106,112,101,103,58,118,109,108,0],"i8",c,5340108);d([47,112,97,105,114,101,100,49,48,47,57,0],"i8",c,5340120);d([32,62,0],"i8",c,5340132);d([47,112,97,105,114,101,100,49,48,47,56,0],"i8",c,5340136);d([47,112,97,105,114,101,100,49,48,47,55,0],"i8",c,5340148);d([80,97,108,97,116,105,110,111,32,76,105,110,111,116,121,112,101,0],"i8",c,5340160);d([47,117,110,102,105,108,108,101,100,32,123,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5340180);d([47,112,97,105,114,101,100,49,48,47,54,0],"i8",c,5340204);d([102,97,115,116,103,114,46,99,0],"i8",c,5340216);d([102,105,114,101,98,114,105,99,107,0],"i8",c,5340228);d([115,104,111,119,98,111,120,101,115,0],"i8",c,5340240);d([38,97,109,112,59,0],"i8",c,5340252);d([47,97,99,99,101,110,116,51,47,51,0],"i8",c,5340260);d([47,112,97,105,114,101,100,49,48,47,53,0],"i8",c,5340272);d([67,99,101,100,105,108,0],"i8",c,5340284);d([47,112,97,105,114,101,100,49,48,47,52,0],"i8",c,5340292);d([47,112,97,105,114,101,100,49,48,47,51,0],"i8",c,5340304);d([111,117,116,112,117,116,111,114,100,101,114,0],"i8",c,5340316);d([47,112,97,105,114,101,100,49,48,47,50,0],"i8",c,5340328);d([47,112,97,105,114,101,100,49,48,47,49,48,0],"i8",c,5340340);d([47,98,108,117,101,115,53,47,53,0],"i8",c,5340356);d([47,112,97,105,114,101,100,49,48,47,49,0],"i8",c,5340368);d([77,114,101,99,111,114,100,0],"i8",c,5340380);d([103,105,102,58,118,109,108,0],"i8",c,5340388);d([47,111,114,114,100,57,47,57,0],"i8",c,5340396);d([32,119,105,100,116,104,58,32,37,100,59,32,104,101,105,103,104,116,58,32,37,100,34,0],"i8",c,5340408);d([47,111,114,114,100,57,47,56,0],"i8",c,5340432);d([47,111,114,114,100,57,47,55,0],"i8",c,5340444);d([80,97,108,97,116,105,110,111,45,66,111,108,100,0],"i8",c,5340456);d([47,102,105,108,108,101,100,32,123,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5340472);d([47,111,114,114,100,57,47,54,0],"i8",c,5340496);d([100,111,100,103,101,114,98,108,117,101,0],"i8",c,5340508);d([101,113,117,97,108,108,121,0],"i8",c,5340520);d([99,117,115,116,111,109,0],"i8",c,5340528);d([106,112,103,58,115,118,103,0],"i8",c,5340536);d([47,111,114,114,100,57,47,53,0],"i8",c,5340544);d([66,101,116,97,0],"i8",c,5340556);d([47,111,114,114,100,57,47,52,0],"i8",c,5340564);d([105,110,32,99,104,101,99,107,112,97,116,104,44,32,98,111,120,32,48,32,104,97,115,32,76,76,32,99,111,111,114,100,32,62,32,85,82,32,99,111,111,114,100,10,0],"i8",c,5340576);d([47,111,114,114,100,57,47,51,0],"i8",c,5340624);d([37,108,102,44,37,108,102,44,37,108,102,44,37,108,102,44,37,108,102,0],"i8",c,5340636);d([47,111,114,114,100,57,47,50,0],"i8",c,5340656);d([47,111,114,114,100,57,47,49,0],"i8",c,5340668);d([47,98,108,117,101,115,53,47,52,0],"i8",c,5340680);d([47,111,114,114,100,56,47,56,0],"i8",c,5340692);d([112,110,103,58,118,109,108,0],"i8",c,5340704);d([47,111,114,114,100,56,47,55,0],"i8",c,5340712);d([48,0],"i8",c,5340724);d([47,111,114,114,100,56,47,54,0],"i8",c,5340728);d([47,111,114,114,100,56,47,53,0],"i8",c,5340740);d([114,111,109,97,110,0],"i8",c,5340752);d([47,98,111,108,100,32,123,32,50,32,115,101,116,108,105,110,101,119,105,100,116,104,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5340760);d([47,111,114,114,100,56,47,52,0],"i8",c,5340796);d([100,105,109,103,114,101,121,0],"i8",c,5340808);d([47,111,114,114,100,56,47,51,0],"i8",c,5340816);d([65,117,109,108,0],"i8",c,5340828);d([78,68,95,110,101,120,116,40,118,41,32,61,61,32,78,85,76,76,0],"i8",c,5340836);d([47,111,114,114,100,56,47,50,0],"i8",c,5340856);d([47,111,114,114,100,56,47,49,0],"i8",c,5340868);d([37,108,102,44,37,108,102,44,37,108,102,44,37,91,94,44,93,37,115,0],"i8",c,5340880);d([47,111,114,114,100,55,47,55,0],"i8",c,5340900);d([47,111,114,114,100,55,47,54,0],"i8",c,5340912);d([47,98,108,117,101,115,53,47,51,0],"i8",c,5340924);d([38,35,49,54,48,59,0],"i8",c,5340936);d([47,111,114,114,100,55,47,53,0],"i8",c,5340944);d([77,99,105,114,99,108,101,0],"i8",c,5340956);d([115,118,103,58,115,118,103,0],"i8",c,5340964);d([47,111,114,114,100,55,47,52,0],"i8",c,5340972);d([103,118,114,101,110,100,101,114,95,99,111,114,101,95,118,109,108,46,99,0],"i8",c,5340984);d([47,111,114,114,100,55,47,51,0],"i8",c,5341004);d([47,111,114,114,100,55,47,50,0],"i8",c,5341016);d([78,101,119,67,101,110,116,117,114,121,83,99,104,108,98,107,45,82,111,109,97,110,0],"i8",c,5341028);d([32,99,114,101,97,116,101,32,108,105,110,101,32,0],"i8",c,5341052);d([47,105,110,118,105,115,32,123,47,102,105,108,108,32,123,110,101,119,112,97,116,104,125,32,100,101,102,32,47,115,116,114,111,107,101,32,123,110,101,119,112,97,116,104,125,32,100,101,102,32,47,115,104,111,119,32,123,112,111,112,32,110,101,119,112,97,116,104,125,32,100,101,102,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5341068);d([47,111,114,114,100,55,47,49,0],"i8",c,5341152);d([100,105,109,103,114,97,121,0],"i8",c,5341164);d([110,111,100,101,115,101,112,0],"i8",c,5341172);d([47,111,114,114,100,54,47,54,0],"i8",c,5341180);d([65,116,105,108,100,101,0],"i8",c,5341192);d([75,80,95,82,105,103,104,116,0],"i8",c,5341200);d([47,111,114,114,100,54,47,53,0],"i8",c,5341212);d([47,111,114,114,100,54,47,52,0],"i8",c,5341224);d([37,108,102,44,37,108,102,44,37,108,102,44,39,37,91,94,39,93,39,0],"i8",c,5341236);d([47,111,114,114,100,54,47,51,0],"i8",c,5341256);d([47,111,114,114,100,54,47,50,0],"i8",c,5341268);d([47,98,108,117,101,115,53,47,50,0],"i8",c,5341280);d([47,111,114,114,100,54,47,49,0],"i8",c,5341292);d([77,115,113,117,97,114,101,0],"i8",c,5341304);d([115,118,103,58,120,100,111,116,0],"i8",c,5341312);d([47,111,114,114,100,53,47,53,0],"i8",c,5341324);d([60,117,110,107,110,111,119,110,62,0],"i8",c,5341336);d([35,37,48,50,120,37,48,50,120,37,48,50,120,0],"i8",c,5341348);d([47,111,114,114,100,53,47,52,0],"i8",c,5341364);d([97,114,105,97,108,0],"i8",c,5341376);d([47,111,114,114,100,53,47,51,0],"i8",c,5341384);d([78,101,119,67,101,110,116,117,114,121,83,99,104,108,98,107,45,73,116,97,108,105,99,0],"i8",c,5341396);d([47,100,111,116,116,101,100,32,123,32,91,49,32,73,110,118,83,99,97,108,101,70,97,99,116,111,114,32,109,117,108,32,54,32,73,110,118,83,99,97,108,101,70,97,99,116,111,114,32,109,117,108,93,32,48,32,115,101,116,100,97,115,104,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5341420);d([47,111,114,114,100,53,47,50,0],"i8",c,5341496);d([100,101,101,112,115,107,121,98,108,117,101,0],"i8",c,5341508);d([82,76,0],"i8",c,5341520);d([47,111,114,114,100,53,47,49,0],"i8",c,5341524);d([65,114,105,110,103,0],"i8",c,5341536);d([47,111,114,114,100,52,47,52,0],"i8",c,5341544);d([120,100,111,116,0],"i8",c,5341556);d([47,111,114,114,100,52,47,51,0],"i8",c,5341564);d([118,105,101,119,112,111,114,116,0],"i8",c,5341576);d([99,108,117,115,116,101,114,46,99,0],"i8",c,5341588);d([47,111,114,114,100,52,47,50,0],"i8",c,5341600);d([47,111,114,114,100,52,47,49,0],"i8",c,5341612);d([47,98,108,117,101,115,53,47,49,0],"i8",c,5341624);d([116,107,0],"i8",c,5341636);d([99,97,110,110,111,116,32,102,105,110,100,32,116,114,105,97,110,103,108,101,32,112,97,116,104,0],"i8",c,5341640);d([32,45,45,32,0],"i8",c,5341668);d([47,111,114,114,100,51,47,51,0],"i8",c,5341676);d([77,100,105,97,109,111,110,100,0],"i8",c,5341688);d([101,112,115,58,120,100,111,116,0],"i8",c,5341700);d([47,111,114,114,100,51,47,50,0],"i8",c,5341712);d([110,111,110,101,0],"i8",c,5341724);d([98,98,0],"i8",c,5341732);d([47,111,114,114,100,51,47,49,0],"i8",c,5341736);d([47,111,114,97,110,103,101,115,57,47,57,0],"i8",c,5341748);d([78,101,119,67,101,110,116,117,114,121,83,99,104,108,98,107,45,66,111,108,100,73,116,97,108,105,99,0],"i8",c,5341760);d([47,100,97,115,104,101,100,32,123,32,91,57,32,73,110,118,83,99,97,108,101,70,97,99,116,111,114,32,109,117,108,32,100,117,112,32,93,32,48,32,115,101,116,100,97,115,104,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5341788);d([47,111,114,97,110,103,101,115,57,47,56,0],"i8",c,5341848);d([100,101,101,112,112,105,110,107,0],"i8",c,5341860);d([66,84,0],"i8",c,5341872);d([47,111,114,97,110,103,101,115,57,47,55,0],"i8",c,5341876);d([65,108,112,104,97,0],"i8",c,5341888);d([47,111,114,97,110,103,101,115,57,47,54,0],"i8",c,5341896);d([47,111,114,97,110,103,101,115,57,47,53,0],"i8",c,5341908);d([112,97,103,101,100,105,114,61,37,115,32,105,103,110,111,114,101,100,10,0],"i8",c,5341920);d([47,111,114,97,110,103,101,115,57,47,52,0],"i8",c,5341940);d([47,111,114,97,110,103,101,115,57,47,51,0],"i8",c,5341952);d([47,98,108,117,101,115,52,47,52,0],"i8",c,5341964);d([37,115,32,45,62,32,37,115,58,32,116,97,105,108,32,105,115,32,105,110,115,105,100,101,32,104,101,97,100,32,99,108,117,115,116,101,114,32,37,115,10,0],"i8",c,5341976);d([47,111,114,97,110,103,101,115,57,47,50,0],"i8",c,5342020);d([105,110,118,104,111,117,115,101,0],"i8",c,5342032);d([112,115,58,120,100,111,116,0],"i8",c,5342044);d([47,111,114,97,110,103,101,115,57,47,49,0],"i8",c,5342052);d([34,32,47,62,0],"i8",c,5342064);d([47,111,114,97,110,103,101,115,56,47,56,0],"i8",c,5342072);d([47,111,114,97,110,103,101,115,56,47,55,0],"i8",c,5342084);d([67,101,110,116,117,114,121,32,83,99,104,111,111,108,98,111,111,107,32,76,0],"i8",c,5342096);d([40,78,68,95,85,70,95,115,105,122,101,40,110,41,32,60,61,32,49,41,32,124,124,32,40,110,32,61,61,32,108,101,97,100,101,114,41,0],"i8",c,5342120);d([47,115,111,108,105,100,32,123,32,91,93,32,48,32,115,101,116,100,97,115,104,32,125,32,98,105,110,100,32,100,101,102,0],"i8",c,5342160);d([47,111,114,97,110,103,101,115,56,47,54,0],"i8",c,5342196);d([108,111,97,100,105,109,97,103,101,0],"i8",c,5342208);d([100,97,114,107,118,105,111,108,101,116,0],"i8",c,5342220);d([37,115,32,119,104,105,108,101,32,111,112,101,110,105,110,103,32,37,115,10,0],"i8",c,5342232);d([47,111,114,97,110,103,101,115,56,47,53,0],"i8",c,5342256);d([47,115,101,116,117,112,76,97,116,105,110,49,32,123,0],"i8",c,5342268);d([65,103,114,97,118,101,0],"i8",c,5342284);d([47,111,114,97,110,103,101,115,56,47,52,0],"i8",c,5342292);d([100,111,116,116,101,100,0],"i8",c,5342304);d([47,111,114,97,110,103,101,115,56,47,51,0],"i8",c,5342312);d([114,101,110,100,101,114,101,114,32,102,111,114,32,37,115,32,105,115,32,117,110,97,118,97,105,108,97,98,108,101,10,0],"i8",c,5342324);d([47,111,114,97,110,103,101,115,56,47,50,0],"i8",c,5342356);d([47,111,114,97,110,103,101,115,56,47,49,0],"i8",c,5342368);d([47,98,108,117,101,115,52,47,51,0],"i8",c,5342380);d([47,111,114,97,110,103,101,115,55,47,55,0],"i8",c,5342392);d([105,110,118,116,114,97,112,101,122,105,117,109,0],"i8",c,5342404);d([106,112,103,58,120,100,111,116,0],"i8",c,5342420);d([47,111,114,97,110,103,101,115,55,47,54,0],"i8",c,5342432);d([95,37,100,0],"i8",c,5342444);d([34,32,100,97,115,104,115,116,121,108,101,61,34,100,111,116,0],"i8",c,5342448);d([47,111,114,97,110,103,101,115,55,47,53,0],"i8",c,5342468);d([41,10,0],"i8",c,5342480);d([47,111,114,97,110,103,101,115,55,47,52,0],"i8",c,5342484);d([78,101,119,67,101,110,116,117,114,121,83,99,104,108,98,107,45,66,111,108,100,0],"i8",c,5342496);d([37,32,115,116,121,108,101,115,0],"i8",c,5342520);d([47,111,114,97,110,103,101,115,55,47,51,0],"i8",c,5342532);d([100,101,118,105,99,101,0],"i8",c,5342544);d([100,97,114,107,116,117,114,113,117,111,105,115,101,0],"i8",c,5342552);d([47,111,114,97,110,103,101,115,55,47,50,0],"i8",c,5342568);d([65,99,105,114,99,0],"i8",c,5342580);d([47,111,114,97,110,103,101,115,55,47,49,0],"i8",c,5342588);d([47,111,114,97,110,103,101,115,54,47,54,0],"i8",c,5342600);d([108,97,121,111,117,116,32,119,97,115,32,110,111,116,32,100,111,110,101,10,0],"i8",c,5342612);d([47,111,114,97,110,103,101,115,54,47,53,0],"i8",c,5342636);d([47,111,114,97,110,103,101,115,54,47,52,0],"i8",c,5342648);d([47,98,108,117,101,115,52,47,50,0],"i8",c,5342660);d([47,111,114,97,110,103,101,115,54,47,51,0],"i8",c,5342672);d([105,110,118,116,114,105,97,110,103,108,101,0],"i8",c,5342684);d([106,112,101,58,120,100,111,116,0],"i8",c,5342696);d([47,111,114,97,110,103,101,115,54,47,50,0],"i8",c,5342708);d([34,32,100,97,115,104,115,116,121,108,101,61,34,100,97,115,104,0],"i8",c,5342720);d([47,111,114,97,110,103,101,115,54,47,49,0],"i8",c,5342740);d([47,111,114,97,110,103,101,115,53,47,53,0],"i8",c,5342752);d([72,101,108,118,101,116,105,99,97,45,79,98,108,105,113,117,101,0],"i8",c,5342764);d([32,32,32,32,32,32,32,115,99,97,108,101,0],"i8",c,5342784);d([47,111,114,97,110,103,101,115,53,47,52,0],"i8",c,5342800);d([113,117,97,110,116,117,109,0],"i8",c,5342812);d([100,97,114,107,115,108,97,116,101,103,114,101,121,0],"i8",c,5342820);d([47,111,114,97,110,103,101,115,53,47,51,0],"i8",c,5342836);d([65,97,99,117,116,101,0],"i8",c,5342848);d([47,111,114,97,110,103,101,115,53,47,50,0],"i8",c,5342856);d([47,111,114,97,110,103,101,115,53,47,49,0],"i8",c,5342868);d([76,97,121,111,117,116,32,119,97,115,32,110,111,116,32,100,111,110,101,46,32,32,77,105,115,115,105,110,103,32,108,97,121,111,117,116,32,112,108,117,103,105,110,115,63,32,10,0],"i8",c,5342880);d([47,111,114,97,110,103,101,115,52,47,52,0],"i8",c,5342928);d([47,111,114,97,110,103,101,115,52,47,51,0],"i8",c,5342940);d([47,98,108,117,101,115,52,47,49,0],"i8",c,5342952);d([47,111,114,97,110,103,101,115,52,47,50,0],"i8",c,5342964);d([116,114,105,112,108,101,111,99,116,97,103,111,110,0],"i8",c,5342976);d([106,112,101,103,58,120,100,111,116,0],"i8",c,5342992);d([47,111,114,97,110,103,101,115,52,47,49,0],"i8",c,5343004);d([34,32,119,101,105,103,104,116,61,34,37,46,48,102,112,116,0],"i8",c,5343016);d([47,111,114,97,110,103,101,115,51,47,51,0],"i8",c,5343036);d([71,68,95,114,97,110,107,40,103,41,91,114,93,46,110,32,60,61,32,71,68,95,114,97,110,107,40,103,41,91,114,93,46,97,110,0],"i8",c,5343048);d([47,111,114,97,110,103,101,115,51,47,50,0],"i8",c,5343084);d([72,101,108,118,101,116,105,99,97,45,78,97,114,114,111,119,45,79,98,108,105,113,117,101,0],"i8",c,5343096);d([32,32,32,32,32,32,32,100,117,112,32,49,32,101,120,99,104,32,100,105,118,32,47,73,110,118,83,99,97,108,101,70,97,99,116,111,114,32,101,120,99,104,32,100,101,102,0],"i8",c,5343124);d([47,111,114,97,110,103,101,115,51,47,49,0],"i8",c,5343172);d([100,101,115,116,105,110,97,116,105,111,110,32,112,111,105,110,116,32,110,111,116,32,105,110,32,97,110,121,32,116,114,105,97,110,103,108,101,0],"i8",c,5343184);d([108,97,121,111,117,116,0],"i8",c,5343224);d([71,68,70,79,78,84,80,65,84,72,61,0],"i8",c,5343232);d([100,97,114,107,115,108,97,116,101,103,114,97,121,0],"i8",c,5343244);d([47,103,114,101,121,115,57,47,57,0],"i8",c,5343260);d([65,69,108,105,103,0],"i8",c,5343272);d([47,103,114,101,121,115,57,47,56,0],"i8",c,5343280);d([47,103,114,101,121,115,57,47,55,0],"i8",c,5343292);d([67,0],"i8",c,5343304);d([114,101,110,100,101,114,0],"i8",c,5343308);d([47,103,114,101,121,115,57,47,54,0],"i8",c,5343316);d([115,121,110,116,97,120,32,101,114,114,111,114,44,32,115,116,97,116,101,109,101,110,116,32,115,107,105,112,112,101,100,0],"i8",c,5343328);d([47,103,114,101,121,115,57,47,53,0],"i8",c,5343360);d([47,98,108,117,101,115,51,47,51,0],"i8",c,5343372);d([47,103,114,101,121,115,57,47,52,0],"i8",c,5343384);d([100,111,117,98,108,101,111,99,116,97,103,111,110,0],"i8",c,5343396);d([103,105,102,58,120,100,111,116,0],"i8",c,5343412);d([105,109,97,112,58,109,97,112,0],"i8",c,5343424);d([47,103,114,101,121,115,57,47,51,0],"i8",c,5343436);d([60,118,58,115,116,114,111,107,101,32,99,111,108,111,114,61,34,0],"i8",c,5343448);d([47,103,114,101,121,115,57,47,50,0],"i8",c,5343468);d([35,32,71,101,110,101,114,97,116,101,100,32,98,121,32,0],"i8",c,5343480);d([47,103,114,101,121,115,57,47,49,0],"i8",c,5343496);d([72,101,108,118,101,116,105,99,97,45,78,97,114,114,111,119,45,66,111,108,100,79,98,108,105,113,117,101,0],"i8",c,5343508);d([32,50,10,0],"i8",c,5343540);d([47,103,114,101,121,115,56,47,56,0],"i8",c,5343544);d([78,68,95,114,97,110,107,40,102,114,111,109,41,32,60,32,78,68,95,114,97,110,107,40,116,111,41,0],"i8",c,5343556);d([68,79,84,70,79,78,84,80,65,84,72,0],"i8",c,5343584);d([81,0],"i8",c,5343596);d([100,97,114,107,115,108,97,116,101,98,108,117,101,0],"i8",c,5343600);d([47,97,99,99,101,110,116,51,47,50,0],"i8",c,5343616);d([47,103,114,101,121,115,56,47,55,0],"i8",c,5343628);d([98,122,46,115,105,122,101,0],"i8",c,5343640);d([47,115,101,116,95,115,99,97,108,101,32,123,0],"i8",c,5343648);d([47,103,114,101,121,115,56,47,54,0],"i8",c,5343664);d([47,103,114,101,121,115,56,47,53,0],"i8",c,5343676);d([117,110,109,97,116,99,104,101,100,32,39,40,39,32,105,110,32,115,116,121,108,101,58,32,37,115,10,0],"i8",c,5343688);d([47,103,114,101,121,115,56,47,52,0],"i8",c,5343716);d([47,103,114,101,121,115,56,47,51,0],"i8",c,5343728);d([47,98,108,117,101,115,51,47,50,0],"i8",c,5343740);d([47,103,114,101,121,115,56,47,50,0],"i8",c,5343752);d([100,111,117,98,108,101,99,105,114,99,108,101,0],"i8",c,5343764);d([112,110,103,58,120,100,111,116,0],"i8",c,5343780);d([47,103,114,101,121,115,56,47,49,0],"i8",c,5343792);d([60,47,118,58,115,104,97,112,101,62,10,0],"i8",c,5343804);d([47,103,114,101,121,115,55,47,55,0],"i8",c,5343816);d([32,80,97,103,101,115,58,32,37,100,10,0],"i8",c,5343828);d([47,103,114,101,121,115,55,47,54,0],"i8",c,5343840);d([72,101,108,118,101,116,105,99,97,45,78,97,114,114,111,119,45,66,111,108,100,0],"i8",c,5343852);d([85,115,105,110,103,32,37,115,58,32,37,115,58,37,115,10,0],"i8",c,5343876);d([49,50,48,48,0],"i8",c,5343896);d([47,103,114,101,121,115,55,47,53,0],"i8",c,5343904);d([102,111,110,116,112,97,116,104,0],"i8",c,5343916);d([100,97,114,107,115,101,97,103,114,101,101,110,0],"i8",c,5343928);d([101,112,115,102,0],"i8",c,5343944);d([106,112,101,58,115,118,103,0],"i8",c,5343952);d([47,103,114,101,121,115,55,47,52,0],"i8",c,5343960);d([120,109,108,0],"i8",c,5343972);d([115,112,108,105,110,101,115,0],"i8",c,5343976);d([47,73,110,118,83,99,97,108,101,70,97,99,116,111,114,32,49,46,48,32,100,101,102,0],"i8",c,5343984);d([34,32,110,97,109,101,61,34,0],"i8",c,5344008);d([47,103,114,101,121,115,55,47,51,0],"i8",c,5344020);d([105,110,32,114,111,117,116,101,115,112,108,105,110,101,115,44,32,99,97,110,110,111,116,32,102,105,110,100,32,78,79,82,77,65,76,32,101,100,103,101,10,0],"i8",c,5344032);d([47,103,114,101,121,115,55,47,50,0],"i8",c,5344076);d([116,114,117,110,99,97,116,105,110,103,32,115,116,121,108,101,32,39,37,115,39,10,0],"i8",c,5344088);d([47,103,114,101,121,115,55,47,49,0],"i8",c,5344112);d([47,103,114,101,121,115,54,47,54,0],"i8",c,5344124);d([47,98,108,117,101,115,51,47,49,0],"i8",c,5344136);d([47,103,114,101,121,115,54,47,53,0],"i8",c,5344148);d([115,113,117,97,114,101,0],"i8",c,5344160);d([115,118,103,58,100,111,116,0],"i8",c,5344168);d([47,103,114,101,121,115,54,47,52,0],"i8",c,5344176);d([34,47,62,0],"i8",c,5344188);d([47,103,114,101,121,115,54,47,51,0],"i8",c,5344192);d([32,84,105,116,108,101,58,32,0],"i8",c,5344204);d([47,103,114,101,121,115,54,47,50,0],"i8",c,5344216);d([99,111,110,100,101,110,115,101,100,0],"i8",c,5344228);d([45,50,10,0],"i8",c,5344240);d([47,103,114,101,121,115,54,47,49,0],"i8",c,5344244);d([100,97,114,107,115,97,108,109,111,110,0],"i8",c,5344256);d([47,103,114,101,121,115,53,47,53,0],"i8",c,5344268);d([60,63,120,109,108,0],"i8",c,5344280);d([85,110,107,110,111,119,110,32,34,115,112,108,105,110,101,115,34,32,118,97,108,117,101,58,32,34,37,115,34,32,45,32,105,103,110,111,114,101,100,10,0],"i8",c,5344288);d([47,99,111,111,114,100,102,111,110,116,32,99,111,111,114,100,45,102,111,110,116,45,102,97,109,105,108,121,32,102,105,110,100,102,111,110,116,32,56,32,115,99,97,108,101,102,111,110,116,32,100,101,102,0],"i8",c,5344332);d([60,109,97,112,32,105,100,61,34,0],"i8",c,5344388);d([47,103,114,101,121,115,53,47,52,0],"i8",c,5344400);d([117,32,33,61,32,118,0],"i8",c,5344412);d([47,103,114,101,121,115,53,47,51,0],"i8",c,5344420);d([117,110,109,97,116,99,104,101,100,32,39,41,39,32,105,110,32,115,116,121,108,101,58,32,37,115,10,0],"i8",c,5344432);d([47,103,114,101,121,115,53,47,50,0],"i8",c,5344460);d([47,103,114,101,121,115,53,47,49,0],"i8",c,5344472);d([47,97,99,99,101,110,116,56,47,56,0],"i8",c,5344484);d([38,35,52,53,59,0],"i8",c,5344496);d([47,103,114,101,121,115,52,47,52,0],"i8",c,5344504);d([114,101,99,116,97,110,103,108,101,0],"i8",c,5344516);d([101,112,115,58,100,111,116,0],"i8",c,5344528);d([47,103,114,101,121,115,52,47,51,0],"i8",c,5344536);d([32,101,32,0],"i8",c,5344548);d([47,103,114,101,121,115,52,47,50,0],"i8",c,5344552);d([35,0],"i8",c,5344564);d([47,103,114,101,121,115,52,47,49,0],"i8",c,5344568);d([72,101,108,118,101,116,105,99,97,45,78,97,114,114,111,119,0],"i8",c,5344580);d([10,0],"i8",c,5344600);d([83,105,110,103,108,101,10,0],"i8",c,5344604);d([47,103,114,101,121,115,51,47,51,0],"i8",c,5344612);d([100,97,114,107,114,101,100,0],"i8",c,5344624);d([47,103,114,101,121,115,51,47,50,0],"i8",c,5344632);d([101,112,115,0],"i8",c,5344644);d([101,115,0],"i8",c,5344648);d([47,100,101,102,97,117,108,116,45,102,111,110,116,45,102,97,109,105,108,121,32,47,84,105,109,101,115,45,82,111,109,97,110,32,100,101,102,0],"i8",c,5344652);d([47,103,114,101,121,115,51,47,49,0],"i8",c,5344692);d([82,105,103,104,116,0],"i8",c,5344704);d([47,103,114,101,101,110,115,57,47,57,0],"i8",c,5344712);d([110,101,115,116,105,110,103,32,110,111,116,32,97,108,108,111,119,101,100,32,105,110,32,115,116,121,108,101,58,32,37,115,10,0],"i8",c,5344724);d([47,103,114,101,101,110,115,57,47,56,0],"i8",c,5344760);d([47,103,114,101,101,110,115,57,47,55,0],"i8",c,5344772);d([47,97,99,99,101,110,116,56,47,55,0],"i8",c,5344784);d([49,48,48,46,48,48,10,0],"i8",c,5344796);d([47,103,114,101,101,110,115,57,47,54,0],"i8",c,5344804);d([114,101,99,116,0],"i8",c,5344816);d([112,115,58,100,111,116,0],"i8",c,5344824);d([47,103,114,101,101,110,115,57,47,53,0],"i8",c,5344832);d([32,108,32,0],"i8",c,5344844);d([47,103,114,101,101,110,115,57,47,52,0],"i8",c,5344848);d([32,45,97,110,99,104,111,114,32,101,0],"i8",c,5344860);d([37,115,58,37,100,58,32,37,115,32,110,101,97,114,32,108,105,110,101,32,37,100,10,0],"i8",c,5344872);d([47,103,114,101,101,110,115,57,47,51,0],"i8",c,5344896);d([72,101,108,118,101,116,105,99,97,45,66,111,108,100,79,98,108,105,113,117,101,0],"i8",c,5344908);d([47,103,114,101,101,110,115,57,47,50,0],"i8",c,5344932);d([102,105,103,0],"i8",c,5344944);d([111,117,116,32,111,102,32,109,101,109,111,114,121,10,0],"i8",c,5344948);d([103,100,0],"i8",c,5344964);d([100,97,114,107,111,114,99,104,105,100,0],"i8",c,5344968);d([47,103,114,101,101,110,115,57,47,49,0],"i8",c,5344980);d([197,208,211,198,0],"i8",c,5344992);d([114,117,101,0],"i8",c,5345e3);d([47,99,111,111,114,100,45,102,111,110,116,45,102,97,109,105,108,121,32,47,84,105,109,101,115,45,82,111,109,97,110,32,100,101,102,0],"i8",c,5345004);d([100,101,102,97,117,108,116,32,0],"i8",c,5345040);d([47,103,114,101,101,110,115,56,47,56,0],"i8",c,5345052);d([100,111,116,0],"i8",c,5345064);d([47,103,114,101,101,110,115,56,47,55,0],"i8",c,5345068);d([69,68,95,116,111,95,118,105,114,116,40,111,114,105,103,41,32,33,61,32,78,85,76,76,0],"i8",c,5345080);d([47,103,114,101,101,110,115,56,47,54,0],"i8",c,5345108);d([47,103,114,101,101,110,115,56,47,53,0],"i8",c,5345120);d([107,101,121,0],"i8",c,5345132);d([47,97,99,99,101,110,116,56,47,54,0],"i8",c,5345136);d([47,103,114,101,101,110,115,56,47,52,0],"i8",c,5345148);d([76,101,116,116,101,114,10,0],"i8",c,5345160);d([99,111,109,112,111,110,101,110,116,0],"i8",c,5345168);d([106,112,103,58,100,111,116,0],"i8",c,5345180);d([37,108,102,44,37,100,0],"i8",c,5345188);d([32,45,62,32,0],"i8",c,5345196);d([47,103,114,101,101,110,115,56,47,51,0],"i8",c,5345204);d([37,46,48,102,44,37,46,48,102,32,0],"i8",c,5345216);d([37,100,32,37,100,32,37,100,32,37,100,0],"i8",c,5345228);d([99,97,110,39,116,32,102,105,110,100,32,108,105,98,114,97,114,121,32,102,105,108,101,32,37,115,10,0],"i8",c,5345240);d([47,103,114,101,101,110,115,56,47,50,0],"i8",c,5345268);d([32,45,97,110,99,104,111,114,32,119,0],"i8",c,5345280);d([47,103,114,101,101,110,115,56,47,49,0],"i8",c,5345292);d([72,101,108,118,101,116,105,99,97,45,66,111,108,100,0],"i8",c,5345304);d([47,103,114,101,101,110,115,55,47,55,0],"i8",c,5345320);d([37,115,37,100,32,45,0],"i8",c,5345332);d([37,46,53,103,44,37,46,53,103,44,37,46,53,103,44,37,46,53,103,32,0],"i8",c,5345340);d([100,97,114,107,111,114,97,110,103,101,0],"i8",c,5345364);d([103,118,119,114,105,116,101,95,110,111,95,122,32,112,114,111,98,108,101,109,32,37,100,10,0],"i8",c,5345376);d([47,103,114,101,101,110,115,55,47,54,0],"i8",c,5345404);d([97,110,116,105,113,117,101,119,104,105,116,101,0],"i8",c,5345416);d([112,100,102,0],"i8",c,5345432);d([112,108,105,110,101,0],"i8",c,5345436);d([37,37,66,101,103,105,110,82,101,115,111,117,114,99,101,58,32,112,114,111,99,115,101,116,32,103,114,97,112,104,118,105,122,32,48,32,48,0],"i8",c,5345444);d([98,97,115,101,32,114,101,102,101,114,101,114,10,0],"i8",c,5345484);d([47,103,114,101,101,110,115,55,47,53,0],"i8",c,5345500);d([47,103,114,101,101,110,115,55,47,52,0],"i8",c,5345512);d([47,103,114,101,101,110,115,55,47,51,0],"i8",c,5345524);d([47,103,114,101,101,110,115,55,47,50,0],"i8",c,5345536);d([47,97,99,99,101,110,116,56,47,53,0],"i8",c,5345548);d([47,103,114,101,101,110,115,55,47,49,0],"i8",c,5345560);d([73,110,99,104,101,115,10,0],"i8",c,5345572);d([98,111,120,51,100,0],"i8",c,5345580);d([106,112,101,58,100,111,116,0],"i8",c,5345588);d([37,115,32,45,62,32,37,115,58,32,104,101,97,100,32,110,111,116,32,105,110,115,105,100,101,32,104,101,97,100,32,99,108,117,115,116,101,114,32,37,115,10,0],"i8",c,5345596);d([47,103,114,101,101,110,115,54,47,54,0],"i8",c,5345640);d([32,109,32,0],"i8",c,5345652);d([47,103,114,101,101,110,115,54,47,53,0],"i8",c,5345656);d([32,37,100,125,0],"i8",c,5345668);d([47,103,114,101,101,110,115,54,47,52,0],"i8",c,5345676);d([72,101,108,118,101,116,105,99,97,0],"i8",c,5345688);d([108,101,97,100,101,114,32,33,61,32,78,85,76,76,0],"i8",c,5345700);d([95,116,108,100,114,97,119,95,0],"i8",c,5345716);d([47,103,114,101,101,110,115,54,47,51,0],"i8",c,5345728);d([37,46,53,103,44,37,46,53,103,44,37,46,53,103,44,37,46,53,103,0],"i8",c,5345740);d([103,108,111,98,97,108,0],"i8",c,5345760);d([100,97,114,107,111,108,105,118,101,103,114,101,101,110,0],"i8",c,5345768);d([114,0],"i8",c,5345784);d([47,103,114,101,101,110,115,54,47,50,0],"i8",c,5345788);d([37,80,68,70,45,0],"i8",c,5345800);d([111,108,121,108,105,110,101,0],"i8",c,5345808);d([125,32,98,105,110,100,32,100,101,102,0],"i8",c,5345816);d([60,47,109,97,112,62,10,0],"i8",c,5345828);d([47,103,114,101,101,110,115,54,47,49,0],"i8",c,5345836);d([100,97,115,104,101,100,0],"i8",c,5345848);d([47,103,114,101,101,110,115,53,47,53,0],"i8",c,5345856);d([47,103,114,101,101,110,115,53,47,52,0],"i8",c,5345868);d([47,103,114,101,101,110,115,53,47,51,0],"i8",c,5345880);d([47,97,99,99,101,110,116,56,47,52,0],"i8",c,5345892);d([47,103,114,101,101,110,115,53,47,50,0],"i8",c,5345904);d([67,101,110,116,101,114,10,0],"i8",c,5345916);d([102,111,108,100,101,114,0],"i8",c,5345924);d([106,112,101,103,58,100,111,116,0],"i8",c,5345932);d([47,103,114,101,101,110,115,53,47,49,0],"i8",c,5345944);d([60,118,58,112,97,116,104,32,118,61,34,0],"i8",c,5345956);d([47,103,114,101,101,110,115,52,47,52,0],"i8",c,5345968);d([47,103,114,101,101,110,115,52,47,51,0],"i8",c,5345980);d([67,111,117,114,105,101,114,45,79,98,108,105,113,117,101,0],"i8",c,5345992);d([95,104,108,100,114,97,119,95,0],"i8",c,5346008);d([47,103,114,101,101,110,115,52,47,50,0],"i8",c,5346020);d([108,111,99,97,108,0],"i8",c,5346032);d([100,97,114,107,109,97,103,101,110,116,97,0],"i8",c,5346040);d([99,111,114,101,0],"i8",c,5346052);d([47,103,114,101,101,110,115,52,47,49,0],"i8",c,5346060);d([100,111,116,95,108,97,121,111,117,116,0],"i8",c,5346072);d([105,110,32,108,97,98,101,108,32,111,102,32,103,114,97,112,104,32,37,115,10,0],"i8",c,5346084);d([106,112,101,103,0],"i8",c,5346108);d([114,116,104,111,0],"i8",c,5346116);d([99,108,101,97,114,116,111,109,97,114,107,0],"i8",c,5346124);d([47,103,114,101,101,110,115,51,47,51,0],"i8",c,5346136);d([34,62,10,0],"i8",c,5346148);d([47,103,114,101,101,110,115,51,47,50,0],"i8",c,5346152);d([47,103,114,101,101,110,115,51,47,49,0],"i8",c,5346164);d([47,103,110,98,117,57,47,57,0],"i8",c,5346176);d([47,97,99,99,101,110,116,56,47,51,0],"i8",c,5346188);d([47,103,110,98,117,57,47,56,0],"i8",c,5346200);d([80,111,114,116,114,97,105,116,10,0],"i8",c,5346212);d([116,97,98,0],"i8",c,5346224);d([103,105,102,58,100,111,116,0],"i8",c,5346228);d([47,103,110,98,117,57,47,55,0],"i8",c,5346236);d([47,103,110,98,117,57,47,54,0],"i8",c,5346248);d([32,119,105,100,116,104,58,32,37,100,59,32,104,101,105,103,104,116,58,32,37,100,34,32,102,105,108,108,101,100,61,34,102,97,108,115,101,34,62,0],"i8",c,5346260);d([32,45,102,111,110,116,32,123,0],"i8",c,5346300);d([47,103,110,98,117,57,47,53,0],"i8",c,5346312);d([67,111,117,114,105,101,114,45,66,111,108,100,79,98,108,105,113,117,101,0],"i8",c,5346324);d([47,103,110,98,117,57,47,52,0],"i8",c,5346344);d([95,116,100,114,97,119,95,0],"i8",c,5346356);d([100,111,116,115,112,108,105,110,101,115,46,99,0],"i8",c,5346364);d([101,44,37,46,53,103,44,37,46,53,103,32,0],"i8",c,5346380);d([100,97,114,107,107,104,97,107,105,0],"i8",c,5346396);d([47,103,110,98,117,57,47,51,0],"i8",c,5346408);d([255,216,255,224,0],"i8",c,5346420);d([111,0],"i8",c,5346428);d([47,67,111,117,114,105,101,114,45,66,111,108,100,79,98,108,105,113,117,101,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5346432);d([47,103,110,98,117,57,47,50,0],"i8",c,5346468);d([47,103,110,98,117,57,47,49,0],"i8",c,5346480);d([110,97,109,101,0],"i8",c,5346492);d([112,101,110,99,111,108,111,114,0],"i8",c,5346500);d([47,103,110,98,117,56,47,56,0],"i8",c,5346512);d([122,119,110,106,0],"i8",c,5346524);d([47,103,110,98,117,56,47,55,0],"i8",c,5346532);d([122,119,106,0],"i8",c,5346544);d([47,97,99,99,101,110,116,56,47,50,0],"i8",c,5346548);d([47,103,110,98,117,56,47,54,0],"i8",c,5346560);d([122,101,116,97,0],"i8",c,5346572);d([35,32,80,97,103,101,115,58,32,37,100,10,0],"i8",c,5346580);d([110,111,116,101,0],"i8",c,5346596);d([112,110,103,58,100,111,116,0],"i8",c,5346604);d([47,103,110,98,117,56,47,53,0],"i8",c,5346612);d([121,117,109,108,0],"i8",c,5346624);d([47,103,110,98,117,56,47,52,0],"i8",c,5346632);d([32,60,118,58,115,104,97,112,101,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,97,98,115,111,108,117,116,101,59,32,0],"i8",c,5346644);d([121,101,110,0],"i8",c,5346684);d([125,0],"i8",c,5346688);d([47,103,110,98,117,56,47,51,0],"i8",c,5346692);d([121,97,99,117,116,101,0],"i8",c,5346704);d([67,111,117,114,105,101,114,45,66,111,108,100,0],"i8",c,5346712);d([109,105,110,99,114,111,115,115,46,99,0],"i8",c,5346728);d([47,103,110,98,117,56,47,50,0],"i8",c,5346740);d([95,104,100,114,97,119,95,0],"i8",c,5346752);d([120,105,0],"i8",c,5346760);d([47,103,110,98,117,56,47,49,0],"i8",c,5346764);d([9,37,112,32,37,115,44,37,115,10,0],"i8",c,5346776);d([115,44,37,46,53,103,44,37,46,53,103,32,0],"i8",c,5346788);d([100,97,114,107,103,114,101,121,0],"i8",c,5346804);d([119,101,105,101,114,112,0],"i8",c,5346816);d([47,103,110,98,117,55,47,55,0],"i8",c,5346824);d([103,105,102,0],"i8",c,5346836);d([111,110,101,0],"i8",c,5346840);d([47,67,111,117,114,105,101,114,45,66,111,108,100,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5346844);d([44,37,100,44,37,100,0],"i8",c,5346876);d([117,117,109,108,0],"i8",c,5346884);d([47,103,110,98,117,55,47,54,0],"i8",c,5346892);d([71,68,95,109,105,110,114,97,110,107,40,103,41,32,61,61,32,48,0],"i8",c,5346904);d([117,112,115,105,108,111,110,0],"i8",c,5346924);d([47,103,110,98,117,55,47,53,0],"i8",c,5346932);d([117,112,115,105,104,0],"i8",c,5346944);d([47,103,110,98,117,55,47,52,0],"i8",c,5346952);d([117,109,108,0],"i8",c,5346964);d([47,103,110,98,117,55,47,51,0],"i8",c,5346968);d([47,97,99,99,101,110,116,56,47,49,0],"i8",c,5346980);d([116,114,117,101,0],"i8",c,5346992);d([117,103,114,97,118,101,0],"i8",c,5347e3);d([47,103,110,98,117,55,47,50,0],"i8",c,5347008);d([111,99,116,97,103,111,110,0],"i8",c,5347020);d([115,118,103,58,109,97,112,0],"i8",c,5347028);d([35,32,84,105,116,108,101,58,32,37,115,10,0],"i8",c,5347036);d([117,99,105,114,99,0],"i8",c,5347052);d([47,103,110,98,117,55,47,49,0],"i8",c,5347060);d([99,109,97,112,58,109,97,112,0],"i8",c,5347072);d([32,45,45,62,10,0],"i8",c,5347084);d([117,97,114,114,0],"i8",c,5347092);d([47,103,110,98,117,54,47,54,0],"i8",c,5347100);d([97,103,105,110,105,116,40,41,32,99,97,108,108,101,100,32,109,117,108,116,105,112,108,121,32,119,105,116,104,32,105,110,99,111,110,115,105,115,116,101,110,116,32,97,114,103,115,10,0],"i8",c,5347112);d([32,45,116,101,120,116,32,123,0],"i8",c,5347164);d([117,97,99,117,116,101,0],"i8",c,5347176);d([47,103,110,98,117,54,47,53,0],"i8",c,5347184);d([109,111,110,111,115,112,97,99,101,0],"i8",c,5347196);d([95,108,100,114,97,119,95,0],"i8",c,5347208);d([117,65,114,114,0],"i8",c,5347216);d([47,103,110,98,117,54,47,52,0],"i8",c,5347224);d([115,111,117,114,99,101,32,112,111,105,110,116,32,110,111,116,32,105,110,32,97,110,121,32,116,114,105,97,110,103,108,101,0],"i8",c,5347236);d([37,46,53,103,32,37,46,53,103,0],"i8",c,5347272);d([115,117,98,103,114,97,112,104,0],"i8",c,5347284);d([100,97,114,107,103,114,101,101,110,0],"i8",c,5347296);d([116,114,97,100,101,0],"i8",c,5347308);d([47,103,110,98,117,54,47,51,0],"i8",c,5347316);d([47,97,99,99,101,110,116,51,47,49,0],"i8",c,5347328);d([71,73,70,56,0],"i8",c,5347340);d([105,110,101,0],"i8",c,5347348);d([47,67,111,117,114,105,101,114,45,79,98,108,105,113,117,101,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5347352);d([80,45,62,101,110,100,46,116,104,101,116,97,32,60,32,50,32,42,32,77,95,80,73,0],"i8",c,5347384);d([37,100,44,37,100,0],"i8",c,5347408);d([116,105,109,101,115,0],"i8",c,5347416);d([47,103,110,98,117,54,47,50,0],"i8",c,5347424);d([116,105,108,100,101,0],"i8",c,5347436);d([47,103,110,98,117,54,47,49,0],"i8",c,5347444);d([116,104,111,114,110,0],"i8",c,5347456);d([47,103,110,98,117,53,47,53,0],"i8",c,5347464);d([116,104,105,110,115,112,0],"i8",c,5347476);d([47,103,110,98,117,53,47,52,0],"i8",c,5347484);d([47,97,99,99,101,110,116,55,47,55,0],"i8",c,5347496);d([116,104,101,116,97,115,121,109,0],"i8",c,5347508);d([47,103,110,98,117,53,47,51,0],"i8",c,5347520);d([103,114,97,112,104,32,0],"i8",c,5347532);d([115,101,112,116,97,103,111,110,0],"i8",c,5347540);d([101,112,115,58,109,97,112,0],"i8",c,5347552);d([35,32,71,101,110,101,114,97,116,101,100,32,98,121,32,37,115,32,118,101,114,115,105,111,110,32,37,115,32,40,37,115,41,10,0],"i8",c,5347560);d([116,104,101,116,97,0],"i8",c,5347596);d([47,103,110,98,117,53,47,50,0],"i8",c,5347604);d([32,32,32,32,32,32,60,33,45,45,32,0],"i8",c,5347616);d([116,104,101,114,101,52,0],"i8",c,5347628);d([47,103,110,98,117,53,47,49,0],"i8",c,5347636);d([32,99,114,101,97,116,101,32,116,101,120,116,32,0],"i8",c,5347648);d([116,97,117,0],"i8",c,5347664);d([47,103,110,98,117,52,47,52,0],"i8",c,5347668);d([67,111,117,114,105,101,114,0],"i8",c,5347680);d([49,46,50,0],"i8",c,5347688);d([115,122,108,105,103,0],"i8",c,5347692);d([47,103,110,98,117,52,47,51,0],"i8",c,5347700);d([37,115,32,119,97,115,32,97,108,114,101,97,100,121,32,105,110,32,97,32,114,97,110,107,115,101,116,44,32,100,101,108,101,116,101,100,32,102,114,111,109,32,99,108,117,115,116,101,114,32,37,115,10,0],"i8",c,5347712);d([115,97,109,112,108,101,112,111,105,110,116,115,0],"i8",c,5347768);d([37,108,102,0],"i8",c,5347784);d([100,97,114,107,103,114,97,121,0],"i8",c,5347788);d([115,117,112,101,0],"i8",c,5347800);d([47,103,110,98,117,52,47,50,0],"i8",c,5347808);d([106,112,101,103,58,115,118,103,0],"i8",c,5347820);d([98,109,112,0],"i8",c,5347832);d([97,108,115,101,0],"i8",c,5347836);d([47,67,111,117,114,105,101,114,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5347844);d([37,100,44,37,100,44,37,100,44,37,100,0],"i8",c,5347868);d([115,117,112,51,0],"i8",c,5347880);d([47,103,110,98,117,52,47,49,0],"i8",c,5347888);d([99,97,110,110,111,116,32,114,101,45,97,108,108,111,99,97,116,101,32,112,115,10,0],"i8",c,5347900);d([108,111,115,116,32,37,115,32,37,115,32,101,100,103,101,10,0],"i8",c,5347924);d([115,117,112,50,0],"i8",c,5347944);d([47,103,110,98,117,51,47,51,0],"i8",c,5347952);d([115,101,97,114,99,104,115,105,122,101,0],"i8",c,5347964);d([115,117,112,49,0],"i8",c,5347976);d([47,103,110,98,117,51,47,50,0],"i8",c,5347984);d([115,117,112,0],"i8",c,5347996);d([47,103,110,98,117,51,47,49,0],"i8",c,5348e3);d([47,97,99,99,101,110,116,55,47,54,0],"i8",c,5348012);d([115,117,109,0],"i8",c,5348024);d([47,100,97,114,107,50,56,47,56,0],"i8",c,5348028);d([104,101,120,97,103,111,110,0],"i8",c,5348040);d([112,115,58,109,97,112,0],"i8",c,5348048);d([35,70,73,71,32,51,46,50,10,0],"i8",c,5348056);d([115,117,98,101,0],"i8",c,5348068);d([47,100,97,114,107,50,56,47,55,0],"i8",c,5348076);d([121,101,108,108,111,119,0],"i8",c,5348088);d([115,117,98,0],"i8",c,5348096);d([47,100,97,114,107,50,56,47,54,0],"i8",c,5348100);d([32,99,114,101,97,116,101,32,111,118,97,108,32,0],"i8",c,5348112);d([115,112,97,100,101,115,0],"i8",c,5348128);d([47,100,97,114,107,50,56,47,53,0],"i8",c,5348136);d([66,111,111,107,109,97,110,45,76,105,103,104,116,73,116,97,108,105,99,0],"i8",c,5348148);d([120,100,111,116,118,101,114,115,105,111,110,0],"i8",c,5348168);d([115,105,109,0],"i8",c,5348180);d([47,100,97,114,107,50,56,47,52,0],"i8",c,5348184);d([114,101,99,111,114,100,0],"i8",c,5348196);d([100,97,114,107,103,111,108,100,101,110,114,111,100,0],"i8",c,5348204);d([115,105,103,109,97,102,0],"i8",c,5348220);d([47,100,97,114,107,50,56,47,51,0],"i8",c,5348228);d([66,77,0],"i8",c,5348240);d([111,109,112,111,117,110,100,0],"i8",c,5348244);d([47,72,101,108,118,101,116,105,99,97,45,66,111,108,100,79,98,108,105,113,117,101,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5348252);d([37,100,44,37,100,44,37,100,0],"i8",c,5348292);d([115,105,103,109,97,0],"i8",c,5348304);d([47,100,97,114,107,50,56,47,50,0],"i8",c,5348312);d([115,104,121,0],"i8",c,5348324);d([47,100,97,114,107,50,56,47,49,0],"i8",c,5348328);d([32,99,111,111,114,100,115,61,34,0],"i8",c,5348340);d([115,104,97,112,101,102,105,108,101,0],"i8",c,5348352);d([47,37,115,47,37,115,0],"i8",c,5348364);d([88,49,49,47,0],"i8",c,5348372);d([105,103,104,116,103,114,101,121,0],"i8",c,5348380);d([104,105,116,101,0],"i8",c,5348392);d([108,97,99,107,0],"i8",c,5348400);d([110,32,33,61,32,78,68,95,110,101,120,116,40,110,41,0],"i8",c,5348408);d([121,101,108,108,111,119,52,0],"i8",c,5348424);d([121,101,108,108,111,119,51,0],"i8",c,5348432);d([115,101,99,116,0],"i8",c,5348440);d([47,100,97,114,107,50,55,47,55,0],"i8",c,5348448);d([121,101,108,108,111,119,50,0],"i8",c,5348460);d([121,101,108,108,111,119,49,0],"i8",c,5348468);d([119,104,101,97,116,52,0],"i8",c,5348476);d([119,104,101,97,116,51,0],"i8",c,5348484);d([119,104,101,97,116,50,0],"i8",c,5348492);d([119,104,101,97,116,49,0],"i8",c,5348500);d([115,100,111,116,0],"i8",c,5348508);d([47,100,97,114,107,50,55,47,54,0],"i8",c,5348516);d([118,105,111,108,101,116,114,101,100,52,0],"i8",c,5348528);d([118,105,111,108,101,116,114,101,100,51,0],"i8",c,5348540);d([118,105,111,108,101,116,114,101,100,50,0],"i8",c,5348552);d([118,105,111,108,101,116,114,101,100,49,0],"i8",c,5348564);d([118,105,111,108,101,116,114,101,100,0],"i8",c,5348576);d([38,103,116,59,0],"i8",c,5348588);d([47,97,99,99,101,110,116,55,47,53,0],"i8",c,5348596);d([116,117,114,113,117,111,105,115,101,52,0],"i8",c,5348608);d([116,117,114,113,117,111,105,115,101,51,0],"i8",c,5348620);d([116,117,114,113,117,111,105,115,101,50,0],"i8",c,5348632);d([116,117,114,113,117,111,105,115,101,49,0],"i8",c,5348644);d([115,99,97,114,111,110,0],"i8",c,5348656);d([47,100,97,114,107,50,55,47,53,0],"i8",c,5348664);d([116,114,97,110,115,112,97,114,101,110,116,0],"i8",c,5348676);d([115,98,113,117,111,0],"i8",c,5348688);d([116,111,109,97,116,111,52,0],"i8",c,5348696);d([116,111,109,97,116,111,51,0],"i8",c,5348704);d([116,111,109,97,116,111,50,0],"i8",c,5348712);d([112,101,110,116,97,103,111,110,0],"i8",c,5348720);d([106,112,103,58,109,97,112,0],"i8",c,5348732);d([116,111,109,97,116,111,49,0],"i8",c,5348740);d([116,104,105,115,116,108,101,52,0],"i8",c,5348748);d([35,32,101,110,100,32,111,102,32,70,73,71,32,102,105,108,101,10,0],"i8",c,5348760);d([116,104,105,115,116,108,101,51,0],"i8",c,5348780);d([116,104,105,115,116,108,101,50,0],"i8",c,5348792);d([47,100,97,114,107,50,55,47,52,0],"i8",c,5348804);d([116,104,105,115,116,108,101,49,0],"i8",c,5348816);d([116,97,110,52,0],"i8",c,5348828);d([116,97,110,51,0],"i8",c,5348836);d([116,97,110,50,0],"i8",c,5348844);d([116,97,110,49,0],"i8",c,5348852);d([115,116,101,101,108,98,108,117,101,52,0],"i8",c,5348860);d([115,116,101,101,108,98,108,117,101,51,0],"i8",c,5348872);d([119,104,105,116,101,0],"i8",c,5348884);d([115,116,101,101,108,98,108,117,101,50,0],"i8",c,5348892);d([114,115,113,117,111,0],"i8",c,5348904);d([47,100,97,114,107,50,55,47,51,0],"i8",c,5348912);d([115,116,101,101,108,98,108,117,101,49,0],"i8",c,5348924);d([115,112,114,105,110,103,103,114,101,101,110,52,0],"i8",c,5348936);d([115,112,114,105,110,103,103,114,101,101,110,51,0],"i8",c,5348952);d([32,45,111,117,116,108,105,110,101,32,0],"i8",c,5348968);d([115,112,114,105,110,103,103,114,101,101,110,50,0],"i8",c,5348980);d([115,112,114,105,110,103,103,114,101,101,110,49,0],"i8",c,5348996);d([115,110,111,119,52,0],"i8",c,5349012);d([115,110,111,119,51,0],"i8",c,5349020);d([115,110,111,119,50,0],"i8",c,5349028);d([114,115,97,113,117,111,0],"i8",c,5349036);d([47,100,97,114,107,50,55,47,50,0],"i8",c,5349044);d([115,110,111,119,49,0],"i8",c,5349056);d([108,105,103,104,116,0],"i8",c,5349064);d([115,108,97,116,101,103,114,97,121,52,0],"i8",c,5349072);d([115,108,97,116,101,103,114,97,121,51,0],"i8",c,5349084);d([115,108,97,116,101,103,114,97,121,50,0],"i8",c,5349096);d([35,32,0],"i8",c,5349108);d([115,108,97,116,101,103,114,97,121,49,0],"i8",c,5349112);d([115,108,97,116,101,98,108,117,101,52,0],"i8",c,5349124);d([95,100,114,97,119,95,0],"i8",c,5349136);d([115,108,97,116,101,98,108,117,101,51,0],"i8",c,5349144);d([114,108,109,0],"i8",c,5349156);d([47,100,97,114,107,50,55,47,49,0],"i8",c,5349160);d([115,108,97,116,101,98,108,117,101,50,0],"i8",c,5349172);d([115,108,97,116,101,98,108,117,101,49,0],"i8",c,5349184);d([37,46,53,103,0],"i8",c,5349196);d([115,107,121,98,108,117,101,52,0],"i8",c,5349204);d([115,107,121,98,108,117,101,51,0],"i8",c,5349216);d([115,107,121,98,108,117,101,50,0],"i8",c,5349228);d([100,97,114,107,99,121,97,110,0],"i8",c,5349240);d([115,107,121,98,108,117,101,49,0],"i8",c,5349252);d([115,105,101,110,110,97,52,0],"i8",c,5349264);d([115,105,101,110,110,97,51,0],"i8",c,5349272);d([114,104,111,0],"i8",c,5349280);d([47,100,97,114,107,50,54,47,54,0],"i8",c,5349284);d([115,105,101,110,110,97,50,0],"i8",c,5349296);d([115,105,101,110,110,97,49,0],"i8",c,5349304);d([115,101,97,115,104,101,108,108,52,0],"i8",c,5349312);d([115,101,97,115,104,101,108,108,51,0],"i8",c,5349324);d([115,101,97,115,104,101,108,108,50,0],"i8",c,5349336);d([85,84,70,56,32,99,111,100,101,115,32,62,32,51,32,98,121,116,101,115,32,97,114,101,32,110,111,116,32,99,117,114,114,101,110,116,108,121,32,115,117,112,112,111,114,116,101,100,46,32,79,114,32,112,101,114,104,97,112,115,32,34,45,71,99,104,97,114,115,101,116,61,108,97,116,105,110,49,34,32,105,115,32,110,101,101,100,101,100,63,10,0],"i8",c,5349348);d([47,72,101,108,118,101,116,105,99,97,45,66,111,108,100,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5349440);d([115,101,97,115,104,101,108,108,49,0],"i8",c,5349472);d([115,101,97,103,114,101,101,110,52,0],"i8",c,5349484);d([115,101,97,103,114,101,101,110,51,0],"i8",c,5349496);d([114,102,108,111,111,114,0],"i8",c,5349508);d([47,100,97,114,107,50,54,47,53,0],"i8",c,5349516);d([115,101,97,103,114,101,101,110,50,0],"i8",c,5349528);d([115,101,97,103,114,101,101,110,49,0],"i8",c,5349540);d([115,97,108,109,111,110,52,0],"i8",c,5349552);d([115,97,108,109,111,110,51,0],"i8",c,5349560);d([115,97,108,109,111,110,50,0],"i8",c,5349568);d([115,97,108,109,111,110,49,0],"i8",c,5349576);d([114,101,103,0],"i8",c,5349584);d([116,101,101,0],"i8",c,5349588);d([47,100,97,114,107,50,54,47,52,0],"i8",c,5349592);d([114,111,121,97,108,98,108,117,101,52,0],"i8",c,5349604);d([32,97,108,116,61,34,34,0],"i8",c,5349616);d([114,111,121,97,108,98,108,117,101,51,0],"i8",c,5349624);d([114,111,121,97,108,98,108,117,101,50,0],"i8",c,5349636);d([114,111,121,97,108,98,108,117,101,49,0],"i8",c,5349648);d([114,111,115,121,98,114,111,119,110,52,0],"i8",c,5349660);d([114,111,115,121,98,114,111,119,110,51,0],"i8",c,5349672);d([75,80,95,76,101,102,116,0],"i8",c,5349684);d([114,111,115,121,98,114,111,119,110,50,0],"i8",c,5349692);d([114,111,115,121,98,114,111,119,110,49,0],"i8",c,5349704);d([114,101,97,108,0],"i8",c,5349716);d([47,100,97,114,107,50,54,47,51,0],"i8",c,5349724);d([114,101,100,52,0],"i8",c,5349736);d([114,101,100,51,0],"i8",c,5349744);d([114,101,100,50,0],"i8",c,5349752);d([114,101,100,49,0],"i8",c,5349760);d([112,117,114,112,108,101,52,0],"i8",c,5349768);d([112,117,114,112,108,101,51,0],"i8",c,5349776);d([112,117,114,112,108,101,50,0],"i8",c,5349784);d([112,117,114,112,108,101,49,0],"i8",c,5349792);d([114,100,113,117,111,0],"i8",c,5349800);d([47,100,97,114,107,50,54,47,50,0],"i8",c,5349808);d([112,108,117,109,52,0],"i8",c,5349820);d([112,108,117,109,51,0],"i8",c,5349828);d([112,108,117,109,50,0],"i8",c,5349836);d([112,108,117,109,49,0],"i8",c,5349844);d([47,97,99,99,101,110,116,55,47,52,0],"i8",c,5349852);d([112,105,110,107,52,0],"i8",c,5349864);d([112,105,110,107,51,0],"i8",c,5349872);d([112,105,110,107,50,0],"i8",c,5349880);d([112,105,110,107,49,0],"i8",c,5349888);d([114,99,101,105,108,0],"i8",c,5349896);d([47,100,97,114,107,50,54,47,49,0],"i8",c,5349904);d([112,101,97,99,104,112,117,102,102,52,0],"i8",c,5349916);d([112,101,97,99,104,112,117,102,102,51,0],"i8",c,5349928);d([112,101,97,99,104,112,117,102,102,50,0],"i8",c,5349940);d([104,111,117,115,101,0],"i8",c,5349952);d([106,112,101,58,109,97,112,0],"i8",c,5349960);d([112,101,97,99,104,112,117,102,102,49,0],"i8",c,5349968);d([112,97,108,101,118,105,111,108,101,116,114,101,100,52,0],"i8",c,5349980);d([37,48,51,111,0],"i8",c,5349996);d([112,97,108,101,118,105,111,108,101,116,114,101,100,51,0],"i8",c,5350004);d([114,97,114,114,0],"i8",c,5350020);d([47,100,97,114,107,50,53,47,53,0],"i8",c,5350028);d([112,97,108,101,118,105,111,108,101,116,114,101,100,50,0],"i8",c,5350040);d([112,97,108,101,118,105,111,108,101,116,114,101,100,49,0],"i8",c,5350056);d([112,97,108,101,116,117,114,113,117,111,105,115,101,52,0],"i8",c,5350072);d([112,97,108,101,116,117,114,113,117,111,105,115,101,51,0],"i8",c,5350088);d([112,97,108,101,116,117,114,113,117,111,105,115,101,50,0],"i8",c,5350104);d([112,97,108,101,116,117,114,113,117,111,105,115,101,49,0],"i8",c,5350120);d([112,97,108,101,103,114,101,101,110,52,0],"i8",c,5350136);d([112,97,108,101,103,114,101,101,110,51,0],"i8",c,5350148);d([114,97,113,117,111,0],"i8",c,5350160);d([116,101,97,108,0],"i8",c,5350168);d([47,100,97,114,107,50,53,47,52,0],"i8",c,5350176);d([112,97,108,101,103,114,101,101,110,50,0],"i8",c,5350188);d([112,97,108,101,103,114,101,101,110,49,0],"i8",c,5350200);d([111,114,99,104,105,100,52,0],"i8",c,5350212);d([111,114,99,104,105,100,51,0],"i8",c,5350220);d([99,111,117,114,0],"i8",c,5350228);d([111,114,99,104,105,100,50,0],"i8",c,5350236);d([111,114,99,104,105,100,49,0],"i8",c,5350244);d([111,114,97,110,103,101,114,101,100,52,0],"i8",c,5350252);d([114,97,110,103,0],"i8",c,5350264);d([47,100,97,114,107,50,53,47,51,0],"i8",c,5350272);d([111,114,97,110,103,101,114,101,100,51,0],"i8",c,5350284);d([111,114,97,110,103,101,114,101,100,50,0],"i8",c,5350296);d([111,114,97,110,103,101,114,101,100,49,0],"i8",c,5350308);d([66,111,111,107,109,97,110,45,76,105,103,104,116,0],"i8",c,5350320);d([111,114,97,110,103,101,52,0],"i8",c,5350336);d([111,114,97,110,103,101,51,0],"i8",c,5350344);d([111,114,97,110,103,101,50,0],"i8",c,5350352);d([110,111,110,116,101,114,109,105,110,97,116,101,100,32,99,111,109,109,101,110,116,32,105,110,32,108,105,110,101,32,37,100,10,0],"i8",c,5350360);d([111,114,97,110,103,101,49,0],"i8",c,5350396);d([84,32,0],"i8",c,5350404);d([111,108,105,118,101,100,114,97,98,52,0],"i8",c,5350408);d([114,97,100,105,99,0],"i8",c,5350420);d([100,111,116,32,100,111,101,115,32,110,111,116,32,115,117,112,112,111,114,116,32,116,104,101,32,97,115,112,101,99,116,32,97,116,116,114,105,98,117,116,101,32,102,111,114,32,100,105,115,99,111,110,110,101,99,116,101,100,32,103,114,97,112,104,115,32,111,114,32,103,114,97,112,104,115,32,119,105,116,104,32,99,108,117,115,116,101,114,115,10,0],"i8",c,5350428);d([47,100,97,114,107,50,53,47,50,0],"i8",c,5350520);d([111,108,105,118,101,100,114,97,98,51,0],"i8",c,5350532);d([111,108,105,118,101,100,114,97,98,50,0],"i8",c,5350544);d([93,59,10,0],"i8",c,5350556);d([111,108,105,118,101,100,114,97,98,49,0],"i8",c,5350560);d([44,37,46,53,103,0],"i8",c,5350572);d([100,97,114,107,98,108,117,101,0],"i8",c,5350580);d([110,97,118,121,98,108,117,101,0],"i8",c,5350592);d([110,97,118,97,106,111,119,104,105,116,101,52,0],"i8",c,5350604);d([110,97,118,97,106,111,119,104,105,116,101,51,0],"i8",c,5350620);d([114,65,114,114,0],"i8",c,5350636);d([47,100,97,114,107,50,53,47,49,0],"i8",c,5350644);d([110,97,118,97,106,111,119,104,105,116,101,50,0],"i8",c,5350656);d([110,97,118,97,106,111,119,104,105,116,101,49,0],"i8",c,5350672);d([109,105,115,116,121,114,111,115,101,52,0],"i8",c,5350688);d([37,33,80,83,45,65,100,111,98,101,45,0],"i8",c,5350700);d([109,105,115,116,121,114,111,115,101,51,0],"i8",c,5350712);d([73,110,118,97,108,105,100,32,51,45,98,121,116,101,32,85,84,70,56,32,102,111,117,110,100,32,105,110,32,105,110,112,117,116,46,32,80,101,114,104,97,112,115,32,34,45,71,99,104,97,114,115,101,116,61,108,97,116,105,110,49,34,32,105,115,32,110,101,101,100,101,100,63,10,0],"i8",c,5350724);d([47,72,101,108,118,101,116,105,99,97,45,79,98,108,105,113,117,101,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5350800);d([109,105,115,116,121,114,111,115,101,50,0],"i8",c,5350836);d([120,120,120,0],"i8",c,5350848);d([109,105,115,116,121,114,111,115,101,49,0],"i8",c,5350852);d([113,117,111,116,0],"i8",c,5350864);d([47,100,97,114,107,50,52,47,52,0],"i8",c,5350872);d([105,110,32,108,97,98,101,108,32,111,102,32,101,100,103,101,32,37,115,32,37,115,32,37,115,10,0],"i8",c,5350884);d([109,101,100,105,117,109,112,117,114,112,108,101,52,0],"i8",c,5350912);d([109,101,100,105,117,109,112,117,114,112,108,101,51,0],"i8",c,5350928);d([109,101,100,105,117,109,112,117,114,112,108,101,50,0],"i8",c,5350944);d([109,101,100,105,117,109,112,117,114,112,108,101,49,0],"i8",c,5350960);d([112,115,105,0],"i8",c,5350976);d([47,100,97,114,107,50,52,47,51,0],"i8",c,5350980);d([109,101,100,105,117,109,111,114,99,104,105,100,52,0],"i8",c,5350992);d([32,116,105,116,108,101,61,34,0],"i8",c,5351008);d([109,101,100,105,117,109,111,114,99,104,105,100,51,0],"i8",c,5351020);d([109,101,100,105,117,109,111,114,99,104,105,100,50,0],"i8",c,5351036);d([109,101,100,105,117,109,111,114,99,104,105,100,49,0],"i8",c,5351052);d([69,68,95,116,111,95,118,105,114,116,40,111,114,105,103,41,32,61,61,32,78,85,76,76,0],"i8",c,5351068);d([109,97,114,111,111,110,52,0],"i8",c,5351096);d([109,97,114,111,111,110,51,0],"i8",c,5351104);d([112,114,111,112,0],"i8",c,5351112);d([47,100,97,114,107,50,52,47,50,0],"i8",c,5351120);d([109,97,114,111,111,110,50,0],"i8",c,5351132);d([109,97,114,111,111,110,49,0],"i8",c,5351140);d([109,97,103,101,110,116,97,52,0],"i8",c,5351148);d([109,97,103,101,110,116,97,51,0],"i8",c,5351160);d([109,97,103,101,110,116,97,50,0],"i8",c,5351172);d([109,97,103,101,110,116,97,49,0],"i8",c,5351184);d([112,114,111,100,0],"i8",c,5351196);d([47,100,97,114,107,50,52,47,49,0],"i8",c,5351204);d([108,105,103,104,116,121,101,108,108,111,119,52,0],"i8",c,5351216);d([108,105,103,104,116,121,101,108,108,111,119,51,0],"i8",c,5351232);d([108,105,103,104,116,121,101,108,108,111,119,50,0],"i8",c,5351248);d([108,105,103,104,116,121,101,108,108,111,119,49,0],"i8",c,5351264);d([80,114,111,116,111,71,114,97,112,104,0],"i8",c,5351280);d([108,105,103,104,116,115,116,101,101,108,98,108,117,101,52,0],"i8",c,5351292);d([47,97,99,99,101,110,116,55,47,51,0],"i8",c,5351308);d([108,105,103,104,116,115,116,101,101,108,98,108,117,101,51,0],"i8",c,5351320);d([108,105,103,104,116,115,116,101,101,108,98,108,117,101,50,0],"i8",c,5351336);d([108,105,103,104,116,115,116,101,101,108,98,108,117,101,49,0],"i8",c,5351352);d([112,114,105,109,101,0],"i8",c,5351368);d([47,100,97,114,107,50,51,47,51,0],"i8",c,5351376);d([108,105,103,104,116,115,108,97,116,101,98,108,117,101,0],"i8",c,5351388);d([110,111,100,101,32,0],"i8",c,5351404);d([108,105,103,104,116,115,107,121,98,108,117,101,52,0],"i8",c,5351412);d([108,105,103,104,116,115,107,121,98,108,117,101,51,0],"i8",c,5351428);d([112,97,114,97,108,108,101,108,111,103,114,97,109,0],"i8",c,5351444);d([108,105,103,104,116,115,107,121,98,108,117,101,50,0],"i8",c,5351460);d([106,112,101,103,58,109,97,112,0],"i8",c,5351476);d([108,105,103,104,116,115,107,121,98,108,117,101,49,0],"i8",c,5351488);d([108,105,103,104,116,115,97,108,109,111,110,52,0],"i8",c,5351504);d([112,111,117,110,100,0],"i8",c,5351520);d([47,100,97,114,107,50,51,47,50,0],"i8",c,5351528);d([37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,46,49,102,32,37,46,52,102,32,37,100,32,37,46,49,102,32,37,46,49,102,32,37,100,32,37,100,32,37,115,92,48,48,49,10,0],"i8",c,5351540);d([108,105,103,104,116,115,97,108,109,111,110,51,0],"i8",c,5351596);d([108,105,103,104,116,115,97,108,109,111,110,50,0],"i8",c,5351612);d([108,105,103,104,116,115,97,108,109,111,110,49,0],"i8",c,5351628);d([108,105,103,104,116,112,105,110,107,52,0],"i8",c,5351644);d([108,105,103,104,116,112,105,110,107,51,0],"i8",c,5351656);d([108,105,103,104,116,112,105,110,107,50,0],"i8",c,5351668);d([97,115,112,101,99,116,0],"i8",c,5351680);d([108,105,103,104,116,112,105,110,107,49,0],"i8",c,5351688);d([112,108,117,115,109,110,0],"i8",c,5351700);d([115,105,108,118,101,114,0],"i8",c,5351708);d([47,100,97,114,107,50,51,47,49,0],"i8",c,5351716);d([108,105,103,104,116,103,111,108,100,101,110,114,111,100,52,0],"i8",c,5351728);d([108,105,103,104,116,103,111,108,100,101,110,114,111,100,51,0],"i8",c,5351744);d([32,99,114,101,97,116,101,32,112,111,108,121,103,111,110,32,0],"i8",c,5351760);d([108,105,103,104,116,103,111,108,100,101,110,114,111,100,50,0],"i8",c,5351780);d([108,105,103,104,116,103,111,108,100,101,110,114,111,100,49,0],"i8",c,5351796);d([60,33,45,45,32,71,101,110,101,114,97,116,101,100,32,98,121,32,0],"i8",c,5351812);d([108,105,103,104,116,103,111,108,100,101,110,114,111,100,0],"i8",c,5351832);d([108,105,103,104,116,99,121,97,110,52,0],"i8",c,5351848);d([108,105,103,104,116,99,121,97,110,51,0],"i8",c,5351860);d([108,105,103,104,116,99,121,97,110,50,0],"i8",c,5351872);d([112,105,118,0],"i8",c,5351884);d([47,98,117,112,117,57,47,57,0],"i8",c,5351888);d([108,105,103,104,116,99,121,97,110,49,0],"i8",c,5351900);d([66,111,111,107,109,97,110,45,68,101,109,105,73,116,97,108,105,99,0],"i8",c,5351912);d([108,105,103,104,116,98,108,117,101,52,0],"i8",c,5351932);d([108,105,103,104,116,98,108,117,101,51,0],"i8",c,5351944);d([108,105,103,104,116,98,108,117,101,50,0],"i8",c,5351956);d([32,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,71,114,97,112,104,105,99,115,47,83,86,71,47,49,46,49,47,68,84,68,47,115,118,103,49,49,46,100,116,100,34,62,10,0],"i8",c,5351968);d([108,105,103,104,116,98,108,117,101,49,0],"i8",c,5352024);d([108,101,109,111,110,99,104,105,102,102,111,110,52,0],"i8",c,5352036);d([70,32,37,102,32,0],"i8",c,5352052);d([108,101,109,111,110,99,104,105,102,102,111,110,51,0],"i8",c,5352060);d([112,105,0],"i8",c,5352076);d([47,98,117,112,117,57,47,56,0],"i8",c,5352080);d([108,101,109,111,110,99,104,105,102,102,111,110,50,0],"i8",c,5352092);d([108,101,109,111,110,99,104,105,102,102,111,110,49,0],"i8",c,5352108);d([37,46,53,103,44,37,46,53,103,44,37,46,53,103,0],"i8",c,5352124);d([108,97,118,101,110,100,101,114,98,108,117,115,104,52,0],"i8",c,5352140);d([108,97,118,101,110,100,101,114,98,108,117,115,104,51,0],"i8",c,5352156);d([99,121,97,110,0],"i8",c,5352172);d([60,33,68,79,67,84,89,80,69,32,115,118,103,32,80,85,66,76,73,67,32,34,45,47,47,87,51,67,47,47,68,84,68,32,83,86,71,32,49,46,49,47,47,69,78,34,10,0],"i8",c,5352180);d([108,97,118,101,110,100,101,114,98,108,117,115,104,50,0],"i8",c,5352228);d([78,68,95,105,110,40,114,105,103,104,116,41,46,115,105,122,101,32,43,32,78,68,95,111,117,116,40,114,105,103,104,116,41,46,115,105,122,101,32,61,61,32,48,0],"i8",c,5352244);d([112,104,105,0],"i8",c,5352288);d([108,97,118,101,110,100,101,114,98,108,117,115,104,49,0],"i8",c,5352292);d([32,32,34,37,115,34,10,0],"i8",c,5352308);d([47,98,117,112,117,57,47,55,0],"i8",c,5352316);d([107,104,97,107,105,52,0],"i8",c,5352328);d([107,104,97,107,105,51,0],"i8",c,5352336);d([97,108,105,99,101,98,108,117,101,0],"i8",c,5352344);d([107,104,97,107,105,50,0],"i8",c,5352356);d([107,104,97,107,105,49,0],"i8",c,5352364);d([112,110,103,0],"i8",c,5352372);d([105,118,111,114,121,52,0],"i8",c,5352376);d([73,110,118,97,108,105,100,32,50,45,98,121,116,101,32,85,84,70,56,32,102,111,117,110,100,32,105,110,32,105,110,112,117,116,46,32,80,101,114,104,97,112,115,32,34,45,71,99,104,97,114,115,101,116,61,108,97,116,105,110,49,34,32,105,115,32,110,101,101,100,101,100,63,10,0],"i8",c,5352384);d([47,72,101,108,118,101,116,105,99,97,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5352460);d([34,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,63,62,10,0],"i8",c,5352488);d([105,118,111,114,121,51,0],"i8",c,5352512);d([78,111,32,108,105,98,122,32,115,117,112,112,111,114,116,46,10,0],"i8",c,5352520);d([105,118,111,114,121,50,0],"i8",c,5352540);d([105,118,111,114,121,49,0],"i8",c,5352548);d([112,101,114,112,0],"i8",c,5352556);d([47,98,117,112,117,57,47,54,0],"i8",c,5352564);d([105,110,100,105,97,110,114,101,100,52,0],"i8",c,5352576);d([105,110,100,105,97,110,114,101,100,51,0],"i8",c,5352588);d([105,110,100,105,97,110,114,101,100,50,0],"i8",c,5352600);d([105,110,100,105,97,110,114,101,100,49,0],"i8",c,5352612);d([60,63,120,109,108,45,115,116,121,108,101,115,104,101,101,116,32,104,114,101,102,61,34,0],"i8",c,5352624);d([104,111,116,112,105,110,107,52,0],"i8",c,5352648);d([104,111,116,112,105,110,107,51,0],"i8",c,5352660);d([104,111,116,112,105,110,107,50,0],"i8",c,5352672);d([112,101,114,109,105,108,0],"i8",c,5352684);d([47,98,117,112,117,57,47,53,0],"i8",c,5352692);d([104,111,116,112,105,110,107,49,0],"i8",c,5352704);d([104,111,110,101,121,100,101,119,52,0],"i8",c,5352716);d([104,111,110,101,121,100,101,119,51,0],"i8",c,5352728);d([104,111,110,101,121,100,101,119,50,0],"i8",c,5352740);d([104,111,110,101,121,100,101,119,49,0],"i8",c,5352752);d([115,116,121,108,101,115,104,101,101,116,0],"i8",c,5352764);d([103,114,101,121,57,57,0],"i8",c,5352776);d([103,114,101,121,57,56,0],"i8",c,5352784);d([103,114,101,121,57,55,0],"i8",c,5352792);d([112,97,114,116,0],"i8",c,5352800);d([47,98,117,112,117,57,47,52,0],"i8",c,5352808);d([103,114,101,121,57,54,0],"i8",c,5352820);d([103,114,101,121,57,53,0],"i8",c,5352828);d([103,114,101,121,57,52,0],"i8",c,5352836);d([103,114,101,121,57,51,0],"i8",c,5352844);d([103,114,101,121,57,50,0],"i8",c,5352852);d([103,114,101,121,57,49,0],"i8",c,5352860);d([60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101,110,99,111,100,105,110,103,61,34,85,84,70,45,56,34,32,115,116,97,110,100,97,108,111,110,101,61,34,110,111,34,63,62,10,0],"i8",c,5352868);d([103,114,101,121,57,48,0],"i8",c,5352924);d([103,114,101,121,57,0],"i8",c,5352932);d([103,114,101,121,56,57,0],"i8",c,5352940);d([103,114,101,121,56,56,0],"i8",c,5352948);d([112,97,114,97,0],"i8",c,5352956);d([47,98,117,112,117,57,47,51,0],"i8",c,5352964);d([103,114,101,121,56,55,0],"i8",c,5352976);d([103,114,101,121,56,54,0],"i8",c,5352984);d([103,114,101,121,56,53,0],"i8",c,5352992);d([103,114,101,121,56,52,0],"i8",c,5353e3);d([103,114,101,121,56,51,0],"i8",c,5353008);d([103,114,101,121,56,50,0],"i8",c,5353016);d([47,97,99,99,101,110,116,55,47,50,0],"i8",c,5353024);d([32,120,109,108,110,115,58,120,108,105,110,107,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,49,57,57,57,47,120,108,105,110,107,34,0],"i8",c,5353036);d([103,114,101,121,56,49,0],"i8",c,5353080);d([103,114,101,121,56,48,0],"i8",c,5353088);d([103,114,101,121,56,0],"i8",c,5353096);d([103,114,101,121,55,57,0],"i8",c,5353104);d([111,117,109,108,0],"i8",c,5353112);d([47,98,117,112,117,57,47,50,0],"i8",c,5353120);d([103,114,101,121,55,56,0],"i8",c,5353132);d([103,114,101,121,55,55,0],"i8",c,5353140);d([103,114,101,121,55,54,0],"i8",c,5353148);d([103,114,101,121,55,53,0],"i8",c,5353156);d([103,114,101,121,55,52,0],"i8",c,5353164);d([116,114,97,112,101,122,105,117,109,0],"i8",c,5353172);d([103,114,101,121,55,51,0],"i8",c,5353184);d([103,105,102,58,109,97,112,0],"i8",c,5353192);d([32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,50,48,48,48,47,115,118,103,34,0],"i8",c,5353200);d([103,114,101,121,55,50,0],"i8",c,5353236);d([50,48,49,49,48,53,48,55,46,48,51,50,55,0],"i8",c,5353244);d([103,114,101,121,55,49,0],"i8",c,5353260);d([103,114,101,121,55,48,0],"i8",c,5353268);d([103,114,101,121,55,0],"i8",c,5353276);d([111,116,105,109,101,115,0],"i8",c,5353284);d([47,98,117,112,117,57,47,49,0],"i8",c,5353292);d([103,114,101,121,54,57,0],"i8",c,5353304);d([103,114,101,121,54,56,0],"i8",c,5353312);d([103,114,101,121,54,55,0],"i8",c,5353320);d([103,114,101,121,54,54,0],"i8",c,5353328);d([103,114,101,121,54,53,0],"i8",c,5353336);d([116,111,111,32,109,97,110,121,32,115,97,109,101,123,104,101,97,100,44,116,97,105,108,125,32,103,114,111,117,112,115,32,102,111,114,32,110,111,100,101,32,37,115,10,0],"i8",c,5353344);d([103,114,101,121,54,52,0],"i8",c,5353392);d([32,118,105,101,119,66,111,120,61,34,37,46,50,102,32,37,46,50,102,32,37,46,50,102,32,37,46,50,102,34,0],"i8",c,5353400);d([103,114,101,121,54,51,0],"i8",c,5353432);d([37,115,32,45,62,32,37,115,58,32,115,112,108,105,110,101,32,115,105,122,101,32,62,32,49,32,110,111,116,32,115,117,112,112,111,114,116,101,100,10,0],"i8",c,5353440);d([103,114,101,121,54,50,0],"i8",c,5353484);d([103,114,101,121,54,49,0],"i8",c,5353492);d([103,114,101,121,54,48,0],"i8",c,5353500);d([111,116,105,108,100,101,0],"i8",c,5353508);d([114,101,100,0],"i8",c,5353516);d([47,98,117,112,117,56,47,56,0],"i8",c,5353520);d([103,114,101,121,54,0],"i8",c,5353532);d([103,114,101,121,53,57,0],"i8",c,5353540);d([103,114,101,121,53,56,0],"i8",c,5353548);d([103,114,101,121,53,55,0],"i8",c,5353556);d([32,45,115,109,111,111,116,104,32,98,101,122,105,101,114,32,0],"i8",c,5353564);d([103,114,101,121,53,54,0],"i8",c,5353584);d([103,114,101,121,53,53,0],"i8",c,5353592);d([60,115,118,103,32,119,105,100,116,104,61,34,37,100,112,116,34,32,104,101,105,103,104,116,61,34,37,100,112,116,34,10,0],"i8",c,5353600);d([103,114,101,121,53,52,0],"i8",c,5353636);d([103,114,101,121,53,51,0],"i8",c,5353644);d([103,114,101,121,53,50,0],"i8",c,5353652);d([103,114,101,121,53,49,0],"i8",c,5353660);d([111,115,108,97,115,104,0],"i8",c,5353668);d([47,98,117,112,117,56,47,55,0],"i8",c,5353676);d([103,114,101,121,53,48,0],"i8",c,5353688);d([103,114,101,121,53,0],"i8",c,5353696);d([103,114,101,121,52,57,0],"i8",c,5353704);d([115,101,114,105,102,0],"i8",c,5353712);d([103,114,101,121,52,56,0],"i8",c,5353720);d([103,114,101,121,52,55,0],"i8",c,5353728);d([103,114,101,121,52,54,0],"i8",c,5353736);d([114,97,110,107,46,99,0],"i8",c,5353744);d([32,80,97,103,101,115,58,32,37,100,32,45,45,62,10,0],"i8",c,5353752);d([103,114,101,121,52,53,0],"i8",c,5353768);d([103,114,101,121,52,52,0],"i8",c,5353776);d([103,114,101,121,52,51,0],"i8",c,5353784);d([101,32,0],"i8",c,5353792);d([103,114,101,121,52,50,0],"i8",c,5353796);d([111,114,100,109,0],"i8",c,5353804);d([47,98,117,112,117,56,47,54,0],"i8",c,5353812);d([103,114,101,121,52,49,0],"i8",c,5353824);d([103,114,101,121,52,48,0],"i8",c,5353832);d([103,114,101,121,52,0],"i8",c,5353840);d([103,114,101,121,51,57,0],"i8",c,5353848);d([104,114,101,102,0],"i8",c,5353856);d([103,114,101,121,51,56,0],"i8",c,5353864);d([103,114,101,121,51,55,0],"i8",c,5353872);d([99,114,105,109,115,111,110,0],"i8",c,5353880);d([103,114,101,121,51,54,0],"i8",c,5353888);d([103,114,101,121,51,53,0],"i8",c,5353896);d([103,114,101,121,51,52,0],"i8",c,5353904);d([103,114,101,121,51,51,0],"i8",c,5353912);d([111,114,100,102,0],"i8",c,5353920);d([47,98,117,112,117,56,47,53,0],"i8",c,5353928);d([103,114,101,121,51,50,0],"i8",c,5353940);d([103,114,101,121,51,49,0],"i8",c,5353948);d([103,114,101,121,51,48,0],"i8",c,5353956);d([103,114,101,121,51,0],"i8",c,5353964);d([103,114,101,121,50,57,0],"i8",c,5353972);d([117,32,61,61,32,85,70,95,102,105,110,100,40,117,41,0],"i8",c,5353980);d([68,111,116,68,105,99,116,32,98,101,103,105,110,0],"i8",c,5353996);d([60,33,45,45,0],"i8",c,5354012);d([137,80,78,71,13,10,26,10,0],"i8",c,5354020);d([103,114,101,121,50,56,0],"i8",c,5354032);d([47,84,105,109,101,115,45,66,111,108,100,73,116,97,108,105,99,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5354040);d([115,118,103,0],"i8",c,5354076);d([103,114,101,121,50,55,0],"i8",c,5354080);d([103,114,101,121,50,54,0],"i8",c,5354088);d([103,114,101,121,50,53,0],"i8",c,5354096);d([103,114,101,121,50,52,0],"i8",c,5354104);d([111,114,0],"i8",c,5354112);d([47,98,117,112,117,56,47,52,0],"i8",c,5354116);d([103,114,101,121,50,51,0],"i8",c,5354128);d([103,114,101,121,50,50,0],"i8",c,5354136);d([103,114,101,121,50,49,0],"i8",c,5354144);d([103,114,101,121,50,48,0],"i8",c,5354152);d([103,114,101,121,50,0],"i8",c,5354160);d([60,47,115,118,103,62,10,0],"i8",c,5354168);d([103,114,101,121,49,57,0],"i8",c,5354176);d([37,37,37,37,67,114,101,97,116,111,114,58,32,37,115,32,118,101,114,115,105,111,110,32,37,115,32,40,37,115,41,10,0],"i8",c,5354184);d([103,114,101,121,49,56,0],"i8",c,5354220);d([103,114,101,121,49,55,0],"i8",c,5354228);d([103,114,101,121,49,54,0],"i8",c,5354236);d([115,111,108,105,100,0],"i8",c,5354244);d([103,114,101,121,49,53,0],"i8",c,5354252);d([111,112,108,117,115,0],"i8",c,5354260);d([47,98,117,112,117,56,47,51,0],"i8",c,5354268);d([103,114,101,121,49,52,0],"i8",c,5354280);d([103,114,101,121,49,51,0],"i8",c,5354288);d([103,114,101,121,49,50,0],"i8",c,5354296);d([103,114,101,121,49,49,0],"i8",c,5354304);d([32,104,114,101,102,61,34,0],"i8",c,5354312);d([103,114,101,121,49,48,48,0],"i8",c,5354320);d([34,32,99,108,97,115,115,61,34,108,97,121,101,114,34,62,10,0],"i8",c,5354328);d([103,114,101,121,49,48,0],"i8",c,5354348);d([32,69,80,83,70,45,51,46,48,10,0],"i8",c,5354356);d([103,114,101,121,49,0],"i8",c,5354368);d([103,114,101,121,48,0],"i8",c,5354376);d([111,109,105,99,114,111,110,0],"i8",c,5354384);d([47,98,117,112,117,56,47,50,0],"i8",c,5354392);d([103,114,101,101,110,52,0],"i8",c,5354404);d([103,114,101,101,110,51,0],"i8",c,5354412);d([103,114,101,101,110,50,0],"i8",c,5354420);d([103,114,101,101,110,49,0],"i8",c,5354428);d([32,116,114,97,110,115,102,111,114,109,61,34,115,99,97,108,101,40,37,103,32,37,103,41,32,114,111,116,97,116,101,40,37,100,41,32,116,114,97,110,115,108,97,116,101,40,37,103,32,37,103,41,34,62,10,0],"i8",c,5354436);d([103,114,97,121,57,57,0],"i8",c,5354492);d([37,33,80,83,45,65,100,111,98,101,45,51,46,48,0],"i8",c,5354500);d([103,114,97,121,57,56,0],"i8",c,5354516);d([103,114,97,121,57,55,0],"i8",c,5354524);d([103,114,97,121,57,54,0],"i8",c,5354532);d([103,114,97,121,57,53,0],"i8",c,5354540);d([111,109,101,103,97,0],"i8",c,5354548);d([47,98,117,112,117,56,47,49,0],"i8",c,5354556);d([103,114,97,121,57,52,0],"i8",c,5354568);d([103,114,97,121,57,51,0],"i8",c,5354576);d([103,114,97,121,57,50,0],"i8",c,5354584);d([103,114,97,121,57,49,0],"i8",c,5354592);d([103,114,97,121,57,48,0],"i8",c,5354600);d([34,32,99,108,97,115,115,61,34,103,114,97,112,104,34,0],"i8",c,5354608);d([103,114,97,121,57,0],"i8",c,5354624);d([47,97,99,99,101,110,116,55,47,49,0],"i8",c,5354632);d([37,37,69,79,70,10,0],"i8",c,5354644);d([103,114,97,121,56,57,0],"i8",c,5354652);d([103,114,97,121,56,56,0],"i8",c,5354660);d([103,114,97,121,56,55,0],"i8",c,5354668);d([103,114,97,121,56,54,0],"i8",c,5354676);d([111,108,105,110,101,0],"i8",c,5354684);d([47,98,117,112,117,55,47,55,0],"i8",c,5354692);d([103,114,97,121,56,53,0],"i8",c,5354704);d([103,114,97,121,56,52,0],"i8",c,5354712);d([103,114,97,121,56,51,0],"i8",c,5354720);d([103,114,97,121,56,50,0],"i8",c,5354728);d([103,114,97,121,56,49,0],"i8",c,5354736);d([34,32,99,108,97,115,115,61,34,99,108,117,115,116,101,114,34,62,0],"i8",c,5354744);d([100,105,97,109,111,110,100,0],"i8",c,5354764);d([103,114,97,121,56,48,0],"i8",c,5354772);d([112,110,103,58,109,97,112,0],"i8",c,5354780);d([101,110,100,10,114,101,115,116,111,114,101,10,0],"i8",c,5354788);d([103,114,97,121,56,0],"i8",c,5354804);d([103,114,97,121,55,57,0],"i8",c,5354812);d([103,114,97,121,55,56,0],"i8",c,5354820);d([103,114,97,121,55,55,0],"i8",c,5354828);d([111,103,114,97,118,101,0],"i8",c,5354836);d([47,98,117,112,117,55,47,54,0],"i8",c,5354844);d([103,114,97,121,55,54,0],"i8",c,5354856);d([103,114,97,121,55,53,0],"i8",c,5354864);d([37,100,32,37,100,32,35,37,48,50,120,37,48,50,120,37,48,50,120,10,0],"i8",c,5354872);d([103,114,97,121,55,52,0],"i8",c,5354896);d([103,114,97,121,55,51,0],"i8",c,5354904);d([103,114,97,121,55,50,0],"i8",c,5354912);d([34,32,99,108,97,115,115,61,34,110,111,100,101,34,62,0],"i8",c,5354920);d([103,114,97,121,55,49,0],"i8",c,5354936);d([37,37,37,37,80,97,103,101,115,58,32,37,100,10,0],"i8",c,5354944);d([103,114,97,121,55,48,0],"i8",c,5354960);d([103,114,97,121,55,0],"i8",c,5354968);d([103,114,97,121,54,57,0],"i8",c,5354976);d([103,114,97,121,54,56,0],"i8",c,5354984);d([111,101,108,105,103,0],"i8",c,5354992);d([112,117,114,112,108,101,0],"i8",c,5355e3);d([47,98,117,112,117,55,47,53,0],"i8",c,5355008);d([103,114,97,121,54,55,0],"i8",c,5355020);d([103,114,97,121,54,54,0],"i8",c,5355028);d([103,114,97,121,54,53,0],"i8",c,5355036);d([103,114,97,121,54,52,0],"i8",c,5355044);d([32,45,119,105,100,116,104,32,0],"i8",c,5355052);d([103,114,97,121,54,51,0],"i8",c,5355064);d([60,47,116,105,116,108,101,62,10,0],"i8",c,5355072);d([103,114,97,121,54,50,0],"i8",c,5355084);d([37,37,84,114,97,105,108,101,114,10,0],"i8",c,5355092);d([103,114,97,121,54,49,0],"i8",c,5355104);d([103,114,97,121,54,48,0],"i8",c,5355112);d([103,114,97,121,54,0],"i8",c,5355120);d([103,114,97,121,53,57,0],"i8",c,5355128);d([111,99,105,114,99,0],"i8",c,5355136);d([47,98,117,112,117,55,47,52,0],"i8",c,5355144);d([103,114,97,121,53,56,0],"i8",c,5355156);d([103,114,97,121,53,55,0],"i8",c,5355164);d([103,114,97,121,53,54,0],"i8",c,5355172);d([85,82,87,32,66,111,111,107,109,97,110,32,76,0],"i8",c,5355180);d([103,114,97,121,53,53,0],"i8",c,5355196);d([103,114,97,121,53,52,0],"i8",c,5355204);d([92,69,0],"i8",c,5355212);d([103,114,97,121,53,51,0],"i8",c,5355216);d([91,32,123,67,97,116,97,108,111,103,125,32,60,60,32,47,85,82,73,32,60,60,32,47,66,97,115,101,32,40,37,115,41,32,62,62,32,62,62,10,47,80,85,84,32,112,100,102,109,97,114,107,10,0],"i8",c,5355224);d([103,114,97,121,53,50,0],"i8",c,5355280);d([92,76,0],"i8",c,5355288);d([103,114,97,121,53,49,0],"i8",c,5355292);d([103,114,97,121,53,48,0],"i8",c,5355300);d([69,32,0],"i8",c,5355308);d([103,114,97,121,53,0],"i8",c,5355312);d([111,97,99,117,116,101,0],"i8",c,5355320);d([100,101,103,101,110,101,114,97,116,101,32,99,111,110,99,101,110,116,114,97,116,101,100,32,114,97,110,107,32,37,115,44,37,100,10,0],"i8",c,5355328);d([47,98,117,112,117,55,47,51,0],"i8",c,5355364);d([103,114,97,121,52,57,0],"i8",c,5355376);d([103,114,97,121,52,56,0],"i8",c,5355384);d([103,114,97,121,52,55,0],"i8",c,5355392);d([37,46,50,102,0],"i8",c,5355400);d([103,114,97,121,52,54,0],"i8",c,5355408);d([85,82,76,0],"i8",c,5355416);d([103,114,97,121,52,53,0],"i8",c,5355420);d([60,116,105,116,108,101,62,0],"i8",c,5355428);d([103,114,97,121,52,52,0],"i8",c,5355436);d([99,111,114,110,115,105,108,107,0],"i8",c,5355444);d([115,101,116,117,112,76,97,116,105,110,49,10,0],"i8",c,5355456);d([103,114,97,121,52,51,0],"i8",c,5355472);d([103,114,97,121,52,50,0],"i8",c,5355480);d([103,114,97,121,52,49,0],"i8",c,5355488);d([103,114,97,121,52,48,0],"i8",c,5355496);d([110,117,0],"i8",c,5355504);d([47,98,117,112,117,55,47,50,0],"i8",c,5355508);d([103,114,97,121,52,0],"i8",c,5355520);d([103,114,97,121,51,57,0],"i8",c,5355528);d([103,114,97,121,51,56,0],"i8",c,5355536);d([103,114,97,121,51,55,0],"i8",c,5355544);d([103,114,97,121,51,54,0],"i8",c,5355552);d([34,32,99,108,97,115,115,61,34,101,100,103,101,34,62,0],"i8",c,5355560);d([40,108,105,98,41,0],"i8",c,5355576);d([103,114,97,121,51,53,0],"i8",c,5355584);d([95,95,99,108,117,115,116,101,114,110,111,100,101,115,0],"i8",c,5355592);d([37,37,69,110,100,67,111,109,109,101,110,116,115,10,115,97,118,101,10,0],"i8",c,5355608);d([47,84,105,109,101,115,45,66,111,108,100,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5355628);d([103,114,97,121,51,52,0],"i8",c,5355656);d([103,114,97,121,51,51,0],"i8",c,5355664);d([103,114,97,121,51,50,0],"i8",c,5355672);d([103,114,97,121,51,49,0],"i8",c,5355680);d([110,116,105,108,100,101,0],"i8",c,5355688);d([47,98,117,112,117,55,47,49,0],"i8",c,5355696);d([103,114,97,121,51,48,0],"i8",c,5355708);d([103,114,97,121,51,0],"i8",c,5355716);d([103,114,97,121,50,57,0],"i8",c,5355724);d([103,114,97,121,50,56,0],"i8",c,5355732);d([103,114,97,121,50,55,0],"i8",c,5355740);d([60,103,32,105,100,61,34,0],"i8",c,5355748);d([103,114,97,121,50,54,0],"i8",c,5355756);d([37,37,37,37,66,111,117,110,100,105,110,103,66,111,120,58,32,37,100,32,37,100,32,37,100,32,37,100,10,0],"i8",c,5355764);d([103,114,97,121,50,53,0],"i8",c,5355796);d([103,114,97,121,50,52,0],"i8",c,5355804);d([103,114,97,121,50,51,0],"i8",c,5355812);d([103,114,97,121,50,50,0],"i8",c,5355820);d([110,115,117,98,0],"i8",c,5355828);d([110,111,114,109,97,108,0],"i8",c,5355836);d([47,98,117,112,117,54,47,54,0],"i8",c,5355844);d([103,114,97,121,50,49,0],"i8",c,5355856);d([103,114,97,121,50,48,0],"i8",c,5355864);d([103,114,97,121,50,0],"i8",c,5355872);d([103,114,97,121,49,57,0],"i8",c,5355880);d([103,114,97,121,49,56,0],"i8",c,5355888);d([60,47,103,62,10,0],"i8",c,5355896);d([103,114,97,121,49,55,0],"i8",c,5355904);d([37,37,66,111,117,110,100,105,110,103,66,111,120,58,32,40,97,116,101,110,100,41,10,0],"i8",c,5355912);d([103,114,97,121,49,54,0],"i8",c,5355936);d([103,114,97,121,49,53,0],"i8",c,5355944);d([103,114,97,121,49,52,0],"i8",c,5355952);d([103,114,97,121,49,51,0],"i8",c,5355960);d([110,111,116,105,110,0],"i8",c,5355968);d([47,98,117,112,117,54,47,53,0],"i8",c,5355976);d([103,114,97,121,49,50,0],"i8",c,5355988);d([103,114,97,121,49,49,0],"i8",c,5355996);d([103,114,97,121,49,48,48,0],"i8",c,5356004);d([103,114,97,121,49,48,0],"i8",c,5356012);d([103,114,97,121,49,0],"i8",c,5356020);d([103,114,97,121,48,0],"i8",c,5356028);d([37,37,80,97,103,101,115,58,32,49,10,0],"i8",c,5356036);d([103,111,108,100,101,110,114,111,100,52,0],"i8",c,5356048);d([103,111,108,100,101,110,114,111,100,51,0],"i8",c,5356060);d([103,111,108,100,101,110,114,111,100,50,0],"i8",c,5356072);d([110,111,116,0],"i8",c,5356084);d([47,98,117,112,117,54,47,52,0],"i8",c,5356088);d([103,111,108,100,101,110,114,111,100,49,0],"i8",c,5356100);d([103,111,108,100,52,0],"i8",c,5356112);d([103,111,108,100,51,0],"i8",c,5356120);d([103,111,108,100,50,0],"i8",c,5356128);d([32,116,97,114,103,101,116,61,34,0],"i8",c,5356136);d([103,111,108,100,49,0],"i8",c,5356148);d([47,97,99,99,101,110,116,54,47,54,0],"i8",c,5356156);d([37,37,80,97,103,101,115,58,32,40,97,116,101,110,100,41,10,0],"i8",c,5356168);d([110,105,0],"i8",c,5356188);d([47,98,117,112,117,54,47,51,0],"i8",c,5356192);d([102,105,114,101,98,114,105,99,107,52,0],"i8",c,5356204);d([102,105,114,101,98,114,105,99,107,51,0],"i8",c,5356216);d([102,105,114,101,98,114,105,99,107,50,0],"i8",c,5356228);d([102,105,114,101,98,114,105,99,107,49,0],"i8",c,5356240);d([32,120,108,105,110,107,58,116,105,116,108,101,61,34,0],"i8",c,5356252);d([112,108,97,105,110,116,101,120,116,0],"i8",c,5356268);d([40,108,105,98,41,58,112,115,0],"i8",c,5356280);d([37,37,37,37,84,105,116,108,101,58,32,37,115,10,0],"i8",c,5356292);d([100,111,100,103,101,114,98,108,117,101,52,0],"i8",c,5356308);d([100,111,100,103,101,114,98,108,117,101,51,0],"i8",c,5356320);d([100,111,100,103,101,114,98,108,117,101,50,0],"i8",c,5356332);d([100,111,100,103,101,114,98,108,117,101,49,0],"i8",c,5356344);d([110,101,0],"i8",c,5356356);d([47,98,117,112,117,54,47,50,0],"i8",c,5356360);d([37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,46,51,102,32,37,100,32,37,46,52,102,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,10,0],"i8",c,5356372);d([100,101,101,112,115,107,121,98,108,117,101,52,0],"i8",c,5356440);d([100,101,101,112,115,107,121,98,108,117,101,51,0],"i8",c,5356456);d([32,120,108,105,110,107,58,104,114,101,102,61,34,0],"i8",c,5356472);d([100,101,101,112,115,107,121,98,108,117,101,50,0],"i8",c,5356488);d([37,100,32,37,100,32,115,101,116,108,97,121,101,114,10,0],"i8",c,5356504);d([100,101,101,112,115,107,121,98,108,117,101,49,0],"i8",c,5356520);d([100,101,101,112,112,105,110,107,52,0],"i8",c,5356536);d([100,101,101,112,112,105,110,107,51,0],"i8",c,5356548);d([110,100,97,115,104,0],"i8",c,5356560);d([111,108,105,118,101,0],"i8",c,5356568);d([47,98,117,112,117,54,47,49,0],"i8",c,5356576);d([100,101,101,112,112,105,110,107,50,0],"i8",c,5356588);d([100,101,101,112,112,105,110,107,49,0],"i8",c,5356600);d([36,99,0],"i8",c,5356612);d([91,32,47,67,114,111,112,66,111,120,32,91,37,100,32,37,100,32,37,100,32,37,100,93,32,47,80,65,71,69,83,32,112,100,102,109,97,114,107,10,0],"i8",c,5356616);d([100,97,114,107,115,108,97,116,101,103,114,97,121,52,0],"i8",c,5356660);d([100,97,114,107,115,108,97,116,101,103,114,97,121,51,0],"i8",c,5356676);d([100,97,114,107,115,108,97,116,101,103,114,97,121,50,0],"i8",c,5356692);d([100,97,114,107,115,108,97,116,101,103,114,97,121,49,0],"i8",c,5356708);d([110,98,115,112,0],"i8",c,5356724);d([47,98,117,112,117,53,47,53,0],"i8",c,5356732);d([99,111,108,111,114,115,99,104,101,109,101,0],"i8",c,5356744);d([100,97,114,107,115,101,97,103,114,101,101,110,52,0],"i8",c,5356756);d([66,111,111,107,109,97,110,45,68,101,109,105,0],"i8",c,5356772);d([100,97,114,107,115,101,97,103,114,101,101,110,51,0],"i8",c,5356788);d([100,97,114,107,115,101,97,103,114,101,101,110,50,0],"i8",c,5356804);d([100,97,114,107,115,101,97,103,114,101,101,110,49,0],"i8",c,5356820);d([99,97,110,118,97,115,32,115,105,122,101,32,40,37,100,44,37,100,41,32,101,120,99,101,101,100,115,32,80,68,70,32,108,105,109,105,116,32,40,37,100,41,10,9,40,115,117,103,103,101,115,116,32,115,101,116,116,105,110,103,32,97,32,98,111,117,110,100,105,110,103,32,98,111,120,32,115,105,122,101,44,32,115,101,101,32,100,111,116,40,49,41,41,10,0],"i8",c,5356836);d([92,84,0],"i8",c,5356932);d([100,97,114,107,111,114,99,104,105,100,52,0],"i8",c,5356936);d([67,32,0],"i8",c,5356948);d([100,97,114,107,111,114,99,104,105,100,51,0],"i8",c,5356952);d([110,97,98,108,97,0],"i8",c,5356964);d([47,98,117,112,117,53,47,52,0],"i8",c,5356972);d([100,97,114,107,111,114,99,104,105,100,50,0],"i8",c,5356984);d([100,97,114,107,111,114,99,104,105,100,49,0],"i8",c,5356996);d([37,46,53,103,44,37,46,53,103,0],"i8",c,5357008);d([100,97,114,107,111,114,97,110,103,101,52,0],"i8",c,5357020);d([119,0],"i8",c,5357032);d([100,97,114,107,111,114,97,110,103,101,51,0],"i8",c,5357036);d([60,47,116,101,120,116,62,10,0],"i8",c,5357048);d([100,97,114,107,111,114,97,110,103,101,50,0],"i8",c,5357060);d([99,111,114,110,102,108,111,119,101,114,98,108,117,101,0],"i8",c,5357072);d([37,103,32,37,103,32,115,101,116,95,115,99,97,108,101,32,37,100,32,114,111,116,97,116,101,32,37,103,32,37,103,32,116,114,97,110,115,108,97,116,101,10,0],"i8",c,5357088);d([100,97,114,107,111,114,97,110,103,101,49,0],"i8",c,5357132);d([100,97,114,107,111,108,105,118,101,103,114,101,101,110,52,0],"i8",c,5357144);d([100,97,114,107,111,108,105,118,101,103,114,101,101,110,51,0],"i8",c,5357160);d([109,117,0],"i8",c,5357176);d([47,98,117,112,117,53,47,51,0],"i8",c,5357180);d([100,97,114,107,111,108,105,118,101,103,114,101,101,110,50,0],"i8",c,5357192);d([100,97,114,107,111,108,105,118,101,103,114,101,101,110,49,0],"i8",c,5357208);d([62,0],"i8",c,5357224);d([100,97,114,107,103,111,108,100,101,110,114,111,100,52,0],"i8",c,5357228);d([103,115,97,118,101,10,37,100,32,37,100,32,37,100,32,37,100,32,98,111,120,112,114,105,109,32,99,108,105,112,32,110,101,119,112,97,116,104,10,0],"i8",c,5357244);d([47,84,105,109,101,115,45,73,116,97,108,105,99,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5357284);d([100,97,114,107,103,111,108,100,101,110,114,111,100,51,0],"i8",c,5357316);d([100,97,114,107,103,111,108,100,101,110,114,111,100,50,0],"i8",c,5357332);d([100,97,114,107,103,111,108,100,101,110,114,111,100,49,0],"i8",c,5357348);d([47,98,117,112,117,53,47,50,0],"i8",c,5357364);d([99,121,97,110,52,0],"i8",c,5357376);d([99,121,97,110,51,0],"i8",c,5357384);d([99,121,97,110,50,0],"i8",c,5357392);d([99,121,97,110,49,0],"i8",c,5357400);d([32,102,105,108,108,61,34,35,37,48,50,120,37,48,50,120,37,48,50,120,34,0],"i8",c,5357408);d([37,100,32,37,100,32,37,100,32,98,101,103,105,110,112,97,103,101,10,0],"i8",c,5357432);d([99,111,114,110,115,105,108,107,52,0],"i8",c,5357452);d([99,111,114,110,115,105,108,107,51,0],"i8",c,5357464);d([99,111,114,110,115,105,108,107,50,0],"i8",c,5357476);d([99,111,114,110,115,105,108,107,49,0],"i8",c,5357488);d([109,105,100,100,111,116,0],"i8",c,5357500);d([47,98,117,112,117,53,47,49,0],"i8",c,5357508);d([99,111,114,97,108,52,0],"i8",c,5357520);d([99,111,114,97,108,51,0],"i8",c,5357528);d([99,111,114,97,108,50,0],"i8",c,5357536);d([32,102,105,108,108,61,34,37,115,34,0],"i8",c,5357544);d([99,111,114,97,108,49,0],"i8",c,5357556);d([32,105,100,61,34,0],"i8",c,5357564);d([60,60,32,47,80,97,103,101,83,105,122,101,32,91,37,100,32,37,100,93,32,62,62,32,115,101,116,112,97,103,101,100,101,118,105,99,101,10,0],"i8",c,5357572);d([99,104,111,99,111,108,97,116,101,52,0],"i8",c,5357612);d([99,104,111,99,111,108,97,116,101,51,0],"i8",c,5357624);d([99,104,111,99,111,108,97,116,101,50,0],"i8",c,5357636);d([109,105,99,114,111,0],"i8",c,5357648);d([47,98,117,112,117,52,47,52,0],"i8",c,5357656);d([99,104,111,99,111,108,97,116,101,49,0],"i8",c,5357668);d([99,104,97,114,116,114,101,117,115,101,52,0],"i8",c,5357680);d([99,104,97,114,116,114,101,117,115,101,51,0],"i8",c,5357692);d([99,104,97,114,116,114,101,117,115,101,50,0],"i8",c,5357704);d([32,102,111,110,116,45,115,105,122,101,61,34,37,46,50,102,34,0],"i8",c,5357716);d([99,104,97,114,116,114,101,117,115,101,49,0],"i8",c,5357736);d([80,111,114,116,114,97,105,116,0],"i8",c,5357748);d([99,97,100,101,116,98,108,117,101,52,0],"i8",c,5357760);d([99,97,100,101,116,98,108,117,101,51,0],"i8",c,5357772);d([99,97,100,101,116,98,108,117,101,50,0],"i8",c,5357784);d([109,100,97,115,104,0],"i8",c,5357796);d([47,98,117,112,117,52,47,51,0],"i8",c,5357804);d([99,97,100,101,116,98,108,117,101,49,0],"i8",c,5357816);d([98,117,114,108,121,119,111,111,100,52,0],"i8",c,5357828);d([98,117,114,108,121,119,111,111,100,51,0],"i8",c,5357840);d([98,117,114,108,121,119,111,111,100,50,0],"i8",c,5357852);d([32,102,111,110,116,45,102,97,109,105,108,121,61,34,37,115,34,0],"i8",c,5357864);d([98,117,114,108,121,119,111,111,100,49,0],"i8",c,5357884);d([47,97,99,99,101,110,116,54,47,53,0],"i8",c,5357896);d([76,97,110,100,115,99,97,112,101,0],"i8",c,5357908);d([98,114,111,119,110,52,0],"i8",c,5357920);d([98,114,111,119,110,51,0],"i8",c,5357928);d([98,114,111,119,110,50,0],"i8",c,5357936);d([109,97,99,114,0],"i8",c,5357944);d([47,98,117,112,117,52,47,50,0],"i8",c,5357952);d([98,114,111,119,110,49,0],"i8",c,5357964);d([98,108,117,101,52,0],"i8",c,5357972);d([98,108,117,101,51,0],"i8",c,5357980);d([32,102,111,110,116,45,115,116,121,108,101,61,34,37,115,34,0],"i8",c,5357988);d([98,108,117,101,50,0],"i8",c,5358008);d([112,115,58,108,97,115,105,0],"i8",c,5358016);d([37,37,37,37,80,97,103,101,79,114,105,101,110,116,97,116,105,111,110,58,32,37,115,10,0],"i8",c,5358024);d([98,108,117,101,49,0],"i8",c,5358052);d([108,116,0],"i8",c,5358060);d([47,98,117,112,117,52,47,49,0],"i8",c,5358064);d([98,105,115,113,117,101,52,0],"i8",c,5358076);d([98,105,115,113,117,101,51,0],"i8",c,5358084);d([98,105,115,113,117,101,50,0],"i8",c,5358092);d([98,105,115,113,117,101,49,0],"i8",c,5358100);d([32,37,100,0],"i8",c,5358108);d([32,102,111,110,116,45,115,116,114,101,116,99,104,61,34,37,115,34,0],"i8",c,5358112);d([37,37,37,37,80,97,103,101,66,111,117,110,100,105,110,103,66,111,120,58,32,37,100,32,37,100,32,37,100,32,37,100,10,0],"i8",c,5358132);d([97,122,117,114,101,52,0],"i8",c,5358168);d([97,122,117,114,101,51,0],"i8",c,5358176);d([97,122,117,114,101,50,0],"i8",c,5358184);d([97,122,117,114,101,49,0],"i8",c,5358192);d([108,115,113,117,111,0],"i8",c,5358200);d([110,97,118,121,0],"i8",c,5358208);d([47,98,117,112,117,51,47,51,0],"i8",c,5358216);d([97,113,117,97,109,97,114,105,110,101,52,0],"i8",c,5358228);d([97,113,117,97,109,97,114,105,110,101,51,0],"i8",c,5358240);d([97,113,117,97,109,97,114,105,110,101,50,0],"i8",c,5358252);d([97,113,117,97,109,97,114,105,110,101,49,0],"i8",c,5358264);d([32,102,111,110,116,45,119,101,105,103,104,116,61,34,37,115,34,0],"i8",c,5358276);d([37,37,37,37,80,97,103,101,58,32,37,100,32,37,100,10,0],"i8",c,5358296);d([97,110,116,105,113,117,101,119,104,105,116,101,52,0],"i8",c,5358316);d([97,110,116,105,113,117,101,119,104,105,116,101,51,0],"i8",c,5358332);d([97,110,116,105,113,117,101,119,104,105,116,101,50,0],"i8",c,5358348);d([97,110,116,105,113,117,101,119,104,105,116,101,49,0],"i8",c,5358364);d([108,115,97,113,117,111,0],"i8",c,5358380);d([47,98,117,112,117,51,47,50,0],"i8",c,5358388);d([47,121,108,111,114,114,100,57,47,57,0],"i8",c,5358400);d([65,118,97,110,116,71,97,114,100,101,45,68,101,109,105,79,98,108,105,113,117,101,0],"i8",c,5358412);d([47,121,108,111,114,114,100,57,47,56,0],"i8",c,5358436);d([47,121,108,111,114,114,100,57,47,55,0],"i8",c,5358448);d([47,121,108,111,114,114,100,57,47,54,0],"i8",c,5358460);d([44,37,115,0],"i8",c,5358472);d([37,37,37,37,69,110,100,80,97,103,101,58,32,37,100,10,0],"i8",c,5358476);d([47,121,108,111,114,114,100,57,47,53,0],"i8",c,5358496);d([92,72,0],"i8",c,5358508);d([47,121,108,111,114,114,100,57,47,52,0],"i8",c,5358512);d([47,121,108,111,114,114,100,57,47,51,0],"i8",c,5358524);d([47,121,108,111,114,114,100,57,47,50,0],"i8",c,5358536);d([108,114,109,0],"i8",c,5358548);d([47,121,108,111,114,114,100,57,47,49,0],"i8",c,5358552);d([47,98,117,112,117,51,47,49,0],"i8",c,5358564);d([47,121,108,111,114,114,100,56,47,56,0],"i8",c,5358576);d([47,121,108,111,114,114,100,56,47,55,0],"i8",c,5358588);d([108,104,101,105,103,104,116,0],"i8",c,5358600);d([47,121,108,111,114,114,100,56,47,54,0],"i8",c,5358608);d([66,111,117,110,100,105,110,103,66,111,120,32,110,111,116,32,102,111,117,110,100,32,105,110,32,101,112,115,102,32,102,105,108,101,32,37,115,10,0],"i8",c,5358620);d([47,121,108,111,114,114,100,56,47,53,0],"i8",c,5358660);d([47,121,108,111,114,114,100,56,47,52,0],"i8",c,5358672);d([32,102,111,110,116,45,102,97,109,105,108,121,61,34,37,115,0],"i8",c,5358684);d([99,111,114,97,108,0],"i8",c,5358704);d([37,37,80,97,103,101,84,114,97,105,108,101,114,10,0],"i8",c,5358712);d([47,121,108,111,114,114,100,56,47,51,0],"i8",c,5358728);d([105,110,115,116,97,108,108,95,105,110,95,114,97,110,107,32,37,115,32,37,115,32,114,97,110,107,32,37,100,32,105,32,61,32,37,100,32,97,110,32,61,32,48,10,0],"i8",c,5358740);d([47,121,108,111,114,114,100,56,47,50,0],"i8",c,5358788);d([47,121,108,111,114,114,100,56,47,49,0],"i8",c,5358800);d([47,121,108,111,114,114,100,55,47,55,0],"i8",c,5358812);d([108,111,122,0],"i8",c,5358824);d([47,121,108,111,114,114,100,55,47,54,0],"i8",c,5358828);d([47,98,117,103,110,57,47,57,0],"i8",c,5358840);d([47,121,108,111,114,114,100,55,47,53,0],"i8",c,5358852);d([47,121,108,111,114,114,100,55,47,52,0],"i8",c,5358864);d([47,121,108,111,114,114,100,55,47,51,0],"i8",c,5358876);d([47,121,108,111,114,114,100,55,47,50,0],"i8",c,5358888);d([47,121,108,111,114,114,100,55,47,49,0],"i8",c,5358900);d([32,120,61,34,37,103,34,32,121,61,34,37,103,34,0],"i8",c,5358912);d([60,115,118,103,0],"i8",c,5358928);d([101,110,100,112,97,103,101,10,115,104,111,119,112,97,103,101,10,103,114,101,115,116,111,114,101,10,0],"i8",c,5358936);d([47,84,105,109,101,115,45,82,111,109,97,110,32,115,116,97,114,110,101,116,73,83,79,32,100,101,102,0],"i8",c,5358964);d([47,121,108,111,114,114,100,54,47,54,0],"i8",c,5358992);d([47,121,108,111,114,114,100,54,47,53,0],"i8",c,5359004);d([47,121,108,111,114,114,100,54,47,52,0],"i8",c,5359016);d([47,121,108,111,114,114,100,54,47,51,0],"i8",c,5359028);d([108,111,119,97,115,116,0],"i8",c,5359040);d([47,121,108,111,114,114,100,54,47,50,0],"i8",c,5359048);d([47,98,117,103,110,57,47,56,0],"i8",c,5359060);d([47,121,108,111,114,114,100,54,47,49,0],"i8",c,5359072);d([47,121,108,111,114,114,100,53,47,53,0],"i8",c,5359084);d([47,121,108,111,114,114,100,53,47,52,0],"i8",c,5359096);d([47,121,108,111,114,114,100,53,47,51,0],"i8",c,5359108);d([47,121,108,111,114,114,100,53,47,50,0],"i8",c,5359120);d([32,116,101,120,116,45,97,110,99,104,111,114,61,34,109,105,100,100,108,101,34,0],"i8",c,5359132);d([48,32,48,32,48,32,101,100,103,101,99,111,108,111,114,10,0],"i8",c,5359156);d([47,121,108,111,114,114,100,53,47,49,0],"i8",c,5359176);d([47,121,108,111,114,114,100,52,47,52,0],"i8",c,5359188);d([47,121,108,111,114,114,100,52,47,51,0],"i8",c,5359200);d([47,121,108,111,114,114,100,52,47,50,0],"i8",c,5359212);d([108,102,108,111,111,114,0],"i8",c,5359224);d([98,97,99,107,0],"i8",c,5359232);d([47,121,108,111,114,114,100,52,47,49,0],"i8",c,5359240);d([47,98,117,103,110,57,47,55,0],"i8",c,5359252);d([47,121,108,111,114,114,100,51,47,51,0],"i8",c,5359264);d([47,121,108,111,114,114,100,51,47,50,0],"i8",c,5359276);d([47,121,108,111,114,114,100,51,47,49,0],"i8",c,5359288);d([47,121,108,111,114,98,114,57,47,57,0],"i8",c,5359300);d([47,121,108,111,114,98,114,57,47,56,0],"i8",c,5359312);d([32,116,101,120,116,45,97,110,99,104,111,114,61,34,101,110,100,34,0],"i8",c,5359324);d([37,37,32,37,115,10,0],"i8",c,5359344);d([47,121,108,111,114,98,114,57,47,55,0],"i8",c,5359352);d([78,68,95,111,117,116,40,118,41,46,115,105,122,101,32,61,61,32,50,0],"i8",c,5359364);d([60,97,114,101,97,32,115,104,97,112,101,61,34,112,111,108,121,34,0],"i8",c,5359384);d([71,115,116,97,99,107,32,117,110,100,101,114,102,108,111,119,32,105,110,32,103,114,97,112,104,32,112,97,114,115,101,114,10,0],"i8",c,5359404);d([47,121,108,111,114,98,114,57,47,54,0],"i8",c,5359440);d([47,121,108,111,114,98,114,57,47,53,0],"i8",c,5359452);d([47,121,108,111,114,98,114,57,47,52,0],"i8",c,5359464);d([108,101,0],"i8",c,5359476);d([47,121,108,111,114,98,114,57,47,51,0],"i8",c,5359480);d([47,98,117,103,110,57,47,54,0],"i8",c,5359492);d([47,121,108,111,114,98,114,57,47,50,0],"i8",c,5359504);d([47,121,108,111,114,98,114,57,47,49,0],"i8",c,5359516);d([47,121,108,111,114,98,114,56,47,56,0],"i8",c,5359528);d([47,121,108,111,114,98,114,56,47,55,0],"i8",c,5359540);d([47,121,108,111,114,98,114,56,47,54,0],"i8",c,5359552);d([32,116,101,120,116,45,97,110,99,104,111,114,61,34,115,116,97,114,116,34,0],"i8",c,5359564);d([103,115,97,118,101,10,0],"i8",c,5359588);d([47,121,108,111,114,98,114,56,47,53,0],"i8",c,5359596);d([47,121,108,111,114,98,114,56,47,52,0],"i8",c,5359608);d([47,121,108,111,114,98,114,56,47,51,0],"i8",c,5359620);d([47,121,108,111,114,98,114,56,47,50,0],"i8",c,5359632);d([108,100,113,117,111,0],"i8",c,5359644);d([47,121,108,111,114,98,114,56,47,49,0],"i8",c,5359652);d([47,98,117,103,110,57,47,53,0],"i8",c,5359664);d([47,121,108,111,114,98,114,55,47,55,0],"i8",c,5359676);d([47,121,108,111,114,98,114,55,47,54,0],"i8",c,5359688);d([47,121,108,111,114,98,114,55,47,53,0],"i8",c,5359700);d([47,121,108,111,114,98,114,55,47,52,0],"i8",c,5359712);d([47,121,108,111,114,98,114,55,47,51,0],"i8",c,5359724);d([60,116,101,120,116,0],"i8",c,5359736);d([47,97,99,99,101,110,116,54,47,52,0],"i8",c,5359744);d([47,121,108,111,114,98,114,55,47,50,0],"i8",c,5359756);d([47,121,108,111,114,98,114,55,47,49,0],"i8",c,5359768);d([47,121,108,111,114,98,114,54,47,54,0],"i8",c,5359780);d([47,121,108,111,114,98,114,54,47,53,0],"i8",c,5359792);d([108,99,101,105,108,0],"i8",c,5359804);d([47,121,108,111,114,98,114,54,47,52,0],"i8",c,5359812);d([47,98,117,103,110,57,47,52,0],"i8",c,5359824);d([47,121,108,111,114,98,114,54,47,51,0],"i8",c,5359836);d([47,121,108,111,114,98,114,54,47,50,0],"i8",c,5359848);d([47,121,108,111,114,98,114,54,47,49,0],"i8",c,5359860);d([47,121,108,111,114,98,114,53,47,53,0],"i8",c,5359872);d([47,121,108,111,114,98,114,53,47,52,0],"i8",c,5359884);d([116,114,105,97,110,103,108,101,0],"i8",c,5359896);d([112,115,58,112,115,0],"i8",c,5359908);d([32,32,47,66,111,114,100,101,114,32,91,32,48,32,48,32,48,32,93,10,32,32,47,65,99,116,105,111,110,32,60,60,32,47,83,117,98,116,121,112,101,32,47,85,82,73,32,47,85,82,73,32,37,115,32,62,62,10,32,32,47,83,117,98,116,121,112,101,32,47,76,105,110,107,10,47,65,78,78,32,112,100,102,109,97,114,107,10,0],"i8",c,5359916);d([47,121,108,111,114,98,114,53,47,51,0],"i8",c,5360008);d([45,62,0],"i8",c,5360020);d([47,121,108,111,114,98,114,53,47,50,0],"i8",c,5360024);d([47,121,108,111,114,98,114,53,47,49,0],"i8",c,5360036);d([47,121,108,111,114,98,114,52,47,52,0],"i8",c,5360048);d([108,97,114,114,0],"i8",c,5360060);d([47,121,108,111,114,98,114,52,47,51,0],"i8",c,5360068);d([47,98,117,103,110,57,47,51,0],"i8",c,5360080);d([47,121,108,111,114,98,114,52,47,50,0],"i8",c,5360092);d([47,121,108,111,114,98,114,52,47,49,0],"i8",c,5360104);d([47,121,108,111,114,98,114,51,47,51,0],"i8",c,5360116);d([47,121,108,111,114,98,114,51,47,50,0],"i8",c,5360128);d([32,37,115,10,0],"i8",c,5360140);d([47,121,108,111,114,98,114,51,47,49,0],"i8",c,5360148);d([32,114,120,61,34,37,103,34,32,114,121,61,34,37,103,34,0],"i8",c,5360160);d([32,93,10,0],"i8",c,5360180);d([47,121,108,103,110,98,117,57,47,57,0],"i8",c,5360184);d([47,121,108,103,110,98,117,57,47,56,0],"i8",c,5360196);d([47,121,108,103,110,98,117,57,47,55,0],"i8",c,5360208);d([47,121,108,103,110,98,117,57,47,54,0],"i8",c,5360220);d([108,97,113,117,111,0],"i8",c,5360232);d([109,97,114,111,111,110,0],"i8",c,5360240);d([47,121,108,103,110,98,117,57,47,53,0],"i8",c,5360248);d([47,98,117,103,110,57,47,50,0],"i8",c,5360260);d([37,100,32,37,49,91,34,93,37,110,0],"i8",c,5360272);d([47,121,108,103,110,98,117,57,47,52,0],"i8",c,5360284);d([47,121,108,103,110,98,117,57,47,51,0],"i8",c,5360296);d([47,121,108,103,110,98,117,57,47,50,0],"i8",c,5360308);d([47,121,108,103,110,98,117,57,47,49,0],"i8",c,5360320);d([34,34,0],"i8",c,5360332);d([47,121,108,103,110,98,117,56,47,56,0],"i8",c,5360336);d([32,99,120,61,34,37,103,34,32,99,121,61,34,37,103,34,0],"i8",c,5360348);d([105,115,109,97,112,58,109,97,112,0],"i8",c,5360368);d([47,121,108,103,110,98,117,56,47,55,0],"i8",c,5360380);d([47,121,108,103,110,98,117,56,47,54,0],"i8",c,5360392);d([91,32,47,82,101,99,116,32,91,32,0],"i8",c,5360404);d([47,121,108,103,110,98,117,56,47,53,0],"i8",c,5360416);d([47,121,108,103,110,98,117,56,47,52,0],"i8",c,5360428);d([108,97,110,103,0],"i8",c,5360440);d([47,121,108,103,110,98,117,56,47,51,0],"i8",c,5360448);d([47,98,117,103,110,57,47,49,0],"i8",c,5360460);d([47,121,108,103,110,98,117,56,47,50,0],"i8",c,5360472);d([47,121,108,103,110,98,117,56,47,49,0],"i8",c,5360484);d([47,121,108,103,110,98,117,55,47,55,0],"i8",c,5360496);d([47,121,108,103,110,98,117,55,47,54,0],"i8",c,5360508);d([47,121,108,103,110,98,117,55,47,53,0],"i8",c,5360520);d([60,101,108,108,105,112,115,101,0],"i8",c,5360532);d([32,37,115,32,97,108,105,103,110,101,100,116,101,120,116,10,0],"i8",c,5360544);d([47,121,108,103,110,98,117,55,47,52,0],"i8",c,5360564);d([47,121,108,103,110,98,117,55,47,51,0],"i8",c,5360576);d([47,121,108,103,110,98,117,55,47,50,0],"i8",c,5360588);d([98,111,108,100,0],"i8",c,5360600);d([47,121,108,103,110,98,117,55,47,49,0],"i8",c,5360608);d([108,97,109,98,100,97,0],"i8",c,5360620);d([47,121,108,103,110,98,117,54,47,54,0],"i8",c,5360628);d([47,98,117,103,110,56,47,56,0],"i8",c,5360640);d([47,121,108,103,110,98,117,54,47,53,0],"i8",c,5360652);d([69,100,103,101,32,37,112,32,119,97,115,32,110,111,116,32,102,111,117,110,100,10,0],"i8",c,5360664);d([47,121,108,103,110,98,117,54,47,52,0],"i8",c,5360688);d([108,119,105,100,116,104,0],"i8",c,5360700);d([47,121,108,103,110,98,117,54,47,51,0],"i8",c,5360708);d([116,111,111,108,116,105,112,0],"i8",c,5360720);d([114,101,97,100,0],"i8",c,5360728);d([47,121,108,103,110,98,117,54,47,50,0],"i8",c,5360736);d([47,121,108,103,110,98,117,54,47,49,0],"i8",c,5360748);d([37,103,44,37,103,0],"i8",c,5360760);d([32,109,111,118,101,116,111,32,0],"i8",c,5360768);d([99,104,111,99,111,108,97,116,101,0],"i8",c,5360780);d([47,121,108,103,110,98,117,53,47,53,0],"i8",c,5360792);d([47,121,108,103,110,98,117,53,47,52,0],"i8",c,5360804);d([47,121,108,103,110,98,117,53,47,51,0],"i8",c,5360816);d([47,121,108,103,110,98,117,53,47,50,0],"i8",c,5360828);d([108,65,114,114,0],"i8",c,5360840);d([47,121,108,103,110,98,117,53,47,49,0],"i8",c,5360848);d([47,98,117,103,110,56,47,55,0],"i8",c,5360860);d([47,121,108,103,110,98,117,52,47,52,0],"i8",c,5360872);d([37,108,102,37,108,102,37,108,102,0],"i8",c,5360884);d([47,121,108,103,110,98,117,52,47,51,0],"i8",c,5360896);d([47,121,108,103,110,98,117,52,47,50,0],"i8",c,5360908);d([47,121,108,103,110,98,117,52,47,49,0],"i8",c,5360920);d([47,121,108,103,110,98,117,51,47,51,0],"i8",c,5360932);d([60,112,111,108,121,103,111,110,0],"i8",c,5360944);d([37,37,37,37,66,111,117,110,100,105,110,103,66,111,120,58,32,37,100,32,37,100,32,37,100,32,37,100,0],"i8",c,5360956);d([32,47,37,115,32,115,101,116,95,102,111,110,116,10,0],"i8",c,5360988);d([47,121,108,103,110,98,117,51,47,50,0],"i8",c,5361004);d([125,32,100,101,102,0],"i8",c,5361016);d([47,121,108,103,110,98,117,51,47,49,0],"i8",c,5361024);d([101,114,114,111,114,32,105,110,32,99,111,108,120,108,97,116,101,40,41,10,0],"i8",c,5361036);d([47,121,108,103,110,57,47,57,0],"i8",c,5361060);d([47,121,108,103,110,57,47,56,0],"i8",c,5361072);d([107,97,112,112,97,0],"i8",c,5361084);d([47,121,108,103,110,57,47,55,0],"i8",c,5361092);d([47,98,117,103,110,56,47,54,0],"i8",c,5361104);d([47,121,108,103,110,57,47,54,0],"i8",c,5361116);d([47,121,108,103,110,57,47,53,0],"i8",c,5361128);d([47,121,108,103,110,57,47,52,0],"i8",c,5361140);d([47,121,108,103,110,57,47,51,0],"i8",c,5361152);d([47,121,108,103,110,57,47,50,0],"i8",c,5361164);d([37,99,37,103,44,37,103,0],"i8",c,5361176);d([32,101,108,108,105,112,115,101,95,112,97,116,104,32,115,116,114,111,107,101,10,0],"i8",c,5361184);d([47,121,108,103,110,57,47,49,0],"i8",c,5361208);d([47,121,108,103,110,56,47,56,0],"i8",c,5361220);d([47,121,108,103,110,56,47,55,0],"i8",c,5361232);d([47,121,108,103,110,56,47,54,0],"i8",c,5361244);d([105,117,109,108,0],"i8",c,5361256);d([102,111,114,119,97,114,100,0],"i8",c,5361264);d([47,121,108,103,110,56,47,53,0],"i8",c,5361272);d([47,98,117,103,110,56,47,53,0],"i8",c,5361284);d([47,121,108,103,110,56,47,52,0],"i8",c,5361296);d([47,121,108,103,110,56,47,51,0],"i8",c,5361308);d([47,121,108,103,110,56,47,50,0],"i8",c,5361320);d([47,121,108,103,110,56,47,49,0],"i8",c,5361332);d([47,121,108,103,110,55,47,55,0],"i8",c,5361344);d([32,100,61,34,0],"i8",c,5361356);d([32,101,108,108,105,112,115,101,95,112,97,116,104,32,102,105,108,108,10,0],"i8",c,5361364);d([47,121,108,103,110,55,47,54,0],"i8",c,5361384);d([47,121,108,103,110,55,47,53,0],"i8",c,5361396);d([60,97,114,101,97,32,115,104,97,112,101,61,34,114,101,99,116,34,0],"i8",c,5361408);d([95,97,110,111,110,121,109,111,117,115,95,37,100,0],"i8",c,5361428);d([47,121,108,103,110,55,47,52,0],"i8",c,5361444);d([47,121,108,103,110,55,47,51,0],"i8",c,5361456);d([105,115,105,110,0],"i8",c,5361468);d([47,121,108,103,110,55,47,50,0],"i8",c,5361476);d([47,98,117,103,110,56,47,52,0],"i8",c,5361488);d([47,121,108,103,110,55,47,49,0],"i8",c,5361500);d([47,121,108,103,110,54,47,54,0],"i8",c,5361512);d([47,121,108,103,110,54,47,53,0],"i8",c,5361524);d([47,121,108,103,110,54,47,52,0],"i8",c,5361536);d([47,121,108,103,110,54,47,51,0],"i8",c,5361548);d([60,112,97,116,104,0],"i8",c,5361560);d([99,108,111,115,101,112,97,116,104,32,115,116,114,111,107,101,10,0],"i8",c,5361568);d([47,121,108,103,110,54,47,50,0],"i8",c,5361588);d([47,121,108,103,110,54,47,49,0],"i8",c,5361600);d([47,121,108,103,110,53,47,53,0],"i8",c,5361612);d([47,121,108,103,110,53,47,52,0],"i8",c,5361624);d([105,113,117,101,115,116,0],"i8",c,5361636);d([47,121,108,103,110,53,47,51,0],"i8",c,5361644);d([47,98,117,103,110,56,47,51,0],"i8",c,5361656);d([47,121,108,103,110,53,47,50,0],"i8",c,5361668);d([47,121,108,103,110,53,47,49,0],"i8",c,5361680);d([47,121,108,103,110,52,47,52,0],"i8",c,5361692);d([47,121,108,103,110,52,47,51,0],"i8",c,5361704);d([47,121,108,103,110,52,47,50,0],"i8",c,5361716);d([47,97,99,99,101,110,116,54,47,51,0],"i8",c,5361728);d([99,108,111,115,101,112,97,116,104,32,102,105,108,108,10,0],"i8",c,5361740);d([47,121,108,103,110,52,47,49,0],"i8",c,5361756);d([47,121,108,103,110,51,47,51,0],"i8",c,5361768);d([47,121,108,103,110,51,47,50,0],"i8",c,5361780);d([47,121,108,103,110,51,47,49,0],"i8",c,5361792);d([105,111,116,97,0],"i8",c,5361804);d([47,115,118,103,47,121,101,108,108,111,119,103,114,101,101,110,0],"i8",c,5361812);d([47,98,117,103,110,56,47,50,0],"i8",c,5361832);d([47,115,118,103,47,121,101,108,108,111,119,0],"i8",c,5361844);d([47,115,118,103,47,119,104,105,116,101,115,109,111,107,101,0],"i8",c,5361856);d([47,115,118,103,47,119,104,105,116,101,0],"i8",c,5361872);d([47,115,118,103,47,119,104,101,97,116,0],"i8",c,5361884);d([47,115,118,103,47,118,105,111,108,101,116,0],"i8",c,5361896);d([103,118,114,101,110,100,101,114,95,99,111,114,101,95,115,118,103,46,99,0],"i8",c,5361908);d([101,103,103,0],"i8",c,5361928);d([101,112,115,58,108,97,115,105,0],"i8",c,5361932);d([32,99,117,114,118,101,116,111,10,0],"i8",c,5361944);d([47,115,118,103,47,116,117,114,113,117,111,105,115,101,0],"i8",c,5361956);d([116,101,120,116,108,97,121,111,117,116,0],"i8",c,5361972);d([47,115,118,103,47,116,111,109,97,116,111,0],"i8",c,5361984);d([47,115,118,103,47,116,104,105,115,116,108,101,0],"i8",c,5361996);d([47,115,118,103,47,116,101,97,108,0],"i8",c,5362012);d([105,110,116,0],"i8",c,5362024);d([47,115,118,103,47,116,97,110,0],"i8",c,5362028);d([47,98,117,103,110,56,47,49,0],"i8",c,5362040);d([47,115,118,103,47,115,116,101,101,108,98,108,117,101,0],"i8",c,5362052);d([47,115,118,103,47,115,112,114,105,110,103,103,114,101,101,110,0],"i8",c,5362068);d([47,115,118,103,47,115,110,111,119,0],"i8",c,5362088);d([47,115,118,103,47,115,108,97,116,101,103,114,101,121,0],"i8",c,5362100);d([47,115,118,103,47,115,108,97,116,101,103,114,97,121,0],"i8",c,5362116);d([37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,46,49,102,32,37,100,32,37,100,32,37,100,32,37,100,10,0],"i8",c,5362132);d([115,116,114,111,107,101,10,0],"i8",c,5362180);d([47,115,118,103,47,115,108,97,116,101,98,108,117,101,0],"i8",c,5362188);d([47,115,118,103,47,115,107,121,98,108,117,101,0],"i8",c,5362204);d([47,115,118,103,47,115,105,108,118,101,114,0],"i8",c,5362220);d([47,115,118,103,47,115,105,101,110,110,97,0],"i8",c,5362232);d([105,110,102,105,110,0],"i8",c,5362244);d([108,105,109,101,0],"i8",c,5362252);d([47,115,118,103,47,115,101,97,115,104,101,108,108,0],"i8",c,5362260);d([47,98,117,103,110,55,47,55,0],"i8",c,5362276);d([47,115,118,103,47,115,101,97,103,114,101,101,110,0],"i8",c,5362288);d([108,105,110,101,0],"i8",c,5362304);d([47,115,118,103,47,115,97,110,100,121,98,114,111,119,110,0],"i8",c,5362312);d([47,115,118,103,47,115,97,108,109,111,110,0],"i8",c,5362328);d([47,115,118,103,47,115,97,100,100,108,101,98,114,111,119,110,0],"i8",c,5362340);d([32,45,116,97,103,115,32,123,37,100,37,115,37,100,125,0],"i8",c,5362360);d([47,115,118,103,47,114,111,121,97,108,98,108,117,101,0],"i8",c,5362376);d([53,44,50,0],"i8",c,5362392);d([32,108,105,110,101,116,111,10,0],"i8",c,5362396);d([47,115,118,103,47,114,111,115,121,98,114,111,119,110,0],"i8",c,5362408);d([47,115,118,103,47,114,101,100,0],"i8",c,5362424);d([47,115,118,103,47,112,117,114,112,108,101,0],"i8",c,5362436);d([47,115,118,103,47,112,111,119,100,101,114,98,108,117,101,0],"i8",c,5362448);d([47,115,118,103,47,112,108,117,109,0],"i8",c,5362464);d([47,98,117,103,110,55,47,54,0],"i8",c,5362476);d([47,115,118,103,47,112,105,110,107,0],"i8",c,5362488);d([47,115,118,103,47,112,101,114,117,0],"i8",c,5362500);d([47,115,118,103,47,112,101,97,99,104,112,117,102,102,0],"i8",c,5362512);d([37,108,100,0],"i8",c,5362528);d([100,101,109,105,0],"i8",c,5362532);d([47,115,118,103,47,112,97,112,97,121,97,119,104,105,112,0],"i8",c,5362540);d([47,115,118,103,47,112,97,108,101,118,105,111,108,101,116,114,101,100,0],"i8",c,5362556);d([49,44,53,0],"i8",c,5362576);d([32,109,111,118,101,116,111,10,0],"i8",c,5362580);d([47,115,118,103,47,112,97,108,101,116,117,114,113,117,111,105,115,101,0],"i8",c,5362592);d([47,115,118,103,47,112,97,108,101,103,114,101,101,110,0],"i8",c,5362612);d([47,115,118,103,47,112,97,108,101,103,111,108,100,101,110,114,111,100,0],"i8",c,5362628);d([102,105,108,108,101,100,0],"i8",c,5362648);d([102,108,97,116,105,110,100,101,120,40,97,103,116,97,105,108,40,101,41,41,32,60,32,77,45,62,110,99,111,108,115,0],"i8",c,5362656);d([47,115,118,103,47,111,114,99,104,105,100,0],"i8",c,5362688);d([105,103,114,97,118,101,0],"i8",c,5362700);d([47,115,118,103,47,111,114,97,110,103,101,114,101,100,0],"i8",c,5362708);d([47,98,117,103,110,55,47,53,0],"i8",c,5362724);d([47,115,118,103,47,111,114,97,110,103,101,0],"i8",c,5362736);d([115,104,111,114,116,101,115,116,46,99,0],"i8",c,5362748);d([47,115,118,103,47,111,108,105,118,101,100,114,97,98,0],"i8",c,5362760);d([116,97,105,108,95,108,112,0],"i8",c,5362776);d([47,115,118,103,47,111,108,105,118,101,0],"i8",c,5362784);d([47,115,118,103,47,111,108,100,108,97,99,101,0],"i8",c,5362796);d([47,115,118,103,47,110,97,118,121,0],"i8",c,5362812);d([110,101,119,112,97,116,104,32,0],"i8",c,5362824);d([99,104,97,114,116,114,101,117,115,101,0],"i8",c,5362836);d([47,115,118,103,47,110,97,118,97,106,111,119,104,105,116,101,0],"i8",c,5362848);d([47,115,118,103,47,109,111,99,99,97,115,105,110,0],"i8",c,5362868);d([47,115,118,103,47,109,105,115,116,121,114,111,115,101,0],"i8",c,5362884);d([115,105,100,101,115,32,61,61,32,52,0],"i8",c,5362900);d([47,115,118,103,47,109,105,110,116,99,114,101,97,109,0],"i8",c,5362912);d([105,101,120,99,108,0],"i8",c,5362928);d([47,115,118,103,47,109,105,100,110,105,103,104,116,98,108,117,101,0],"i8",c,5362936);d([47,98,117,103,110,55,47,52,0],"i8",c,5362956);d([103,105,102,58,115,118,103,0],"i8",c,5362968);d([47,115,118,103,47,109,101,100,105,117,109,118,105,111,108,101,116,114,101,100,0],"i8",c,5362976);d([47,115,118,103,47,109,101,100,105,117,109,116,117,114,113,117,111,105,115,101,0],"i8",c,5363e3);d([47,115,118,103,47,109,101,100,105,117,109,115,112,114,105,110,103,103,114,101,101,110,0],"i8",c,5363024);d([47,115,118,103,47,109,101,100,105,117,109,115,108,97,116,101,98,108,117,101,0],"i8",c,5363048);d([47,115,118,103,47,109,101,100,105,117,109,115,101,97,103,114,101,101,110,0],"i8",c,5363072);d([34,32,115,116,114,111,107,101,45,111,112,97,99,105,116,121,61,34,37,102,0],"i8",c,5363092);d([37,37,66,111,117,110,100,105,110,103,66,111,120,58,0],"i8",c,5363116);d([47,115,118,103,47,109,101,100,105,117,109,112,117,114,112,108,101,0],"i8",c,5363132);d([32,32,32,32,32,32,32,32,99,117,114,114,101,110,116,100,105,99,116,32,101,110,100,32,100,101,102,105,110,101,102,111,110,116,0],"i8",c,5363152);d([47,115,118,103,47,109,101,100,105,117,109,111,114,99,104,105,100,0],"i8",c,5363188);d([37,115,32,105,115,32,110,111,116,32,97,32,107,110,111,119,110,32,99,111,108,111,114,46,10,0],"i8",c,5363208);d([47,115,118,103,47,109,101,100,105,117,109,98,108,117,101,0],"i8",c,5363236);d([47,115,118,103,47,109,101,100,105,117,109,97,113,117,97,109,97,114,105,110,101,0],"i8",c,5363252);d([105,99,105,114,99,0],"i8",c,5363276);d([47,115,118,103,47,109,97,114,111,111,110,0],"i8",c,5363284);d([47,98,117,103,110,55,47,51,0],"i8",c,5363296);d([47,115,118,103,47,109,97,103,101,110,116,97,0],"i8",c,5363308);d([47,115,118,103,47,108,105,110,101,110,0],"i8",c,5363324);d([47,115,118,103,47,108,105,109,101,103,114,101,101,110,0],"i8",c,5363336);d([47,115,118,103,47,108,105,109,101,0],"i8",c,5363352);d([47,115,118,103,47,108,105,103,104,116,121,101,108,108,111,119,0],"i8",c,5363364);d([34,32,115,116,114,111,107,101,45,100,97,115,104,97,114,114,97,121,61,34,37,115,0],"i8",c,5363384);d([37,32,0],"i8",c,5363408);d([47,115,118,103,47,108,105,103,104,116,115,116,101,101,108,98,108,117,101,0],"i8",c,5363412);d([47,115,118,103,47,108,105,103,104,116,115,108,97,116,101,103,114,101,121,0],"i8",c,5363432);d([47,115,118,103,47,108,105,103,104,116,115,108,97,116,101,103,114,97,121,0],"i8",c,5363452);d([47,115,118,103,47,108,105,103,104,116,115,107,121,98,108,117,101,0],"i8",c,5363472);d([105,97,99,117,116,101,0],"i8",c,5363492);d([105,110,118,101,109,112,116,121,0],"i8",c,5363500);d([47,115,118,103,47,108,105,103,104,116,115,101,97,103,114,101,101,110,0],"i8",c,5363512);d([47,98,117,103,110,55,47,50,0],"i8",c,5363532);d([47,115,118,103,47,108,105,103,104,116,115,97,108,109,111,110,0],"i8",c,5363544);d([47,115,118,103,47,108,105,103,104,116,112,105,110,107,0],"i8",c,5363564);d([102,108,97,116,105,110,100,101,120,40,97,103,104,101,97,100,40,101,41,41,32,60,32,77,45,62,110,114,111,119,115,0],"i8",c,5363580);d([47,115,118,103,47,108,105,103,104,116,103,114,101,121,0],"i8",c,5363612);d([47,115,118,103,47,108,105,103,104,116,103,114,101,101,110,0],"i8",c,5363628);d([47,115,118,103,47,108,105,103,104,116,103,114,97,121,0],"i8",c,5363644);d([34,32,115,116,114,111,107,101,45,119,105,100,116,104,61,34,37,103,0],"i8",c,5363660);d([37,46,53,103,32,37,46,53,103,32,37,46,53,103,32,37,115,99,111,108,111,114,10,0],"i8",c,5363680);d([47,115,118,103,47,108,105,103,104,116,103,111,108,100,101,110,114,111,100,121,101,108,108,111,119,0],"i8",c,5363704);d([47,115,118,103,47,108,105,103,104,116,99,121,97,110,0],"i8",c,5363732);d([47,115,118,103,47,108,105,103,104,116,99,111,114,97,108,0],"i8",c,5363748);d([60,97,114,101,97,32,115,104,97,112,101,61,34,99,105,114,99,108,101,34,0],"i8",c,5363764);d([80,108,101,97,115,101,32,117,115,101,32,97,32,115,105,110,103,108,101,32,100,101,102,105,110,105,116,105,111,110,32,111,102,32,116,104,101,32,115,117,98,103,114,97,112,104,32,119,105,116,104,105,110,32,116,104,101,32,99,111,110,116,101,120,116,32,111,102,32,105,116,115,32,112,97,114,101,110,116,32,103,114,97,112,104,32,34,37,115,34,10,0],"i8",c,5363788);d([47,115,118,103,47,108,105,103,104,116,98,108,117,101,0],"i8",c,5363880);d([104,101,108,108,105,112,0],"i8",c,5363896);d([47,115,118,103,47,108,101,109,111,110,99,104,105,102,102,111,110,0],"i8",c,5363904);d([47,98,117,103,110,55,47,49,0],"i8",c,5363924);d([47,115,118,103,47,108,97,119,110,103,114,101,101,110,0],"i8",c,5363936);d([47,115,118,103,47,108,97,118,101,110,100,101,114,98,108,117,115,104,0],"i8",c,5363952);d([47,115,118,103,47,108,97,118,101,110,100,101,114,0],"i8",c,5363972);d([47,115,118,103,47,107,104,97,107,105,0],"i8",c,5363988);d([47,115,118,103,47,105,118,111,114,121,0],"i8",c,5364e3);d([34,32,115,116,114,111,107,101,61,34,0],"i8",c,5364012);d([115,101,116,104,115,98,0],"i8",c,5364024);d([47,115,118,103,47,105,110,100,105,103,111,0],"i8",c,5364032);d([47,115,118,103,47,105,110,100,105,97,110,114,101,100,0],"i8",c,5364044);d([47,115,118,103,47,104,111,116,112,105,110,107,0],"i8",c,5364060);d([47,115,118,103,47,104,111,110,101,121,100,101,119,0],"i8",c,5364076);d([104,101,97,114,116,115,0],"i8",c,5364092);d([47,115,118,103,47,103,114,101,121,0],"i8",c,5364100);d([47,98,117,103,110,54,47,54,0],"i8",c,5364112);d([47,115,118,103,47,103,114,101,101,110,121,101,108,108,111,119,0],"i8",c,5364124);d([47,115,118,103,47,103,114,101,101,110,0],"i8",c,5364144);d([47,115,118,103,47,103,114,97,121,0],"i8",c,5364156);d([76,82,0],"i8",c,5364168);d([47,115,118,103,47,103,111,108,100,101,110,114,111,100,0],"i8",c,5364172);d([47,115,118,103,47,103,111,108,100,0],"i8",c,5364188);d([47,97,99,99,101,110,116,54,47,50,0],"i8",c,5364200);d([47,115,118,103,47,103,104,111,115,116,119,104,105,116,101,0],"i8",c,5364212);d([47,115,118,103,47,103,97,105,110,115,98,111,114,111,0],"i8",c,5364228);d([47,115,118,103,47,102,117,99,104,115,105,97,0],"i8",c,5364244);d([47,115,118,103,47,102,111,114,101,115,116,103,114,101,101,110,0],"i8",c,5364260);d([104,97,114,114,0],"i8",c,5364280);d([47,115,118,103,47,102,108,111,114,97,108,119,104,105,116,101,0],"i8",c,5364288);d([47,98,117,103,110,54,47,53,0],"i8",c,5364308);d([47,115,118,103,47,102,105,114,101,98,114,105,99,107,0],"i8",c,5364320);d([47,115,118,103,47,100,111,100,103,101,114,98,108,117,101,0],"i8",c,5364336);d([47,115,118,103,47,100,105,109,103,114,101,121,0],"i8",c,5364352);d([47,115,118,103,47,100,105,109,103,114,97,121,0],"i8",c,5364368);d([47,115,118,103,47,100,101,101,112,115,107,121,98,108,117,101,0],"i8",c,5364384);d([34,32,102,105,108,108,45,111,112,97,99,105,116,121,61,34,37,102,0],"i8",c,5364404);d([112,111,105,110,116,0],"i8",c,5364424);d([101,112,115,58,112,115,0],"i8",c,5364432);d([47,115,118,103,47,100,101,101,112,112,105,110,107,0],"i8",c,5364440);d([47,115,118,103,47,100,97,114,107,118,105,111,108,101,116,0],"i8",c,5364456);d([47,115,118,103,47,100,97,114,107,116,117,114,113,117,111,105,115,101,0],"i8",c,5364472);d([47,115,118,103,47,100,97,114,107,115,108,97,116,101,103,114,101,121,0],"i8",c,5364492);d([104,65,114,114,0],"i8",c,5364512);d([47,115,118,103,47,100,97,114,107,115,108,97,116,101,103,114,97,121,0],"i8",c,5364520);d([47,98,117,103,110,54,47,52,0],"i8",c,5364540);d([47,115,118,103,47,100,97,114,107,115,108,97,116,101,98,108,117,101,0],"i8",c,5364552);d([47,115,118,103,47,100,97,114,107,115,101,97,103,114,101,101,110,0],"i8",c,5364572);d([47,115,118,103,47,100,97,114,107,115,97,108,109,111,110,0],"i8",c,5364592);d([47,115,118,103,47,100,97,114,107,114,101,100,0],"i8",c,5364608);d([47,115,118,103,47,100,97,114,107,111,114,99,104,105,100,0],"i8",c,5364624);d([32,102,105,108,108,61,34,0],"i8",c,5364640);d([47,115,118,103,47,100,97,114,107,111,114,97,110,103,101,0],"i8",c,5364648);d([110,32,62,61,32,52,0],"i8",c,5364664);d([47,115,118,103,47,100,97,114,107,111,108,105,118,101,103,114,101,101,110,0],"i8",c,5364672);d([47,115,118,103,47,100,97,114,107,109,97,103,101,110,116,97,0],"i8",c,5364692);d([47,115,118,103,47,100,97,114,107,107,104,97,107,105,0],"i8",c,5364712);d([103,116,0],"i8",c,5364728);d([103,114,101,101,110,0],"i8",c,5364732);d([47,115,118,103,47,100,97,114,107,103,114,101,121,0],"i8",c,5364740);d([47,98,117,103,110,54,47,51,0],"i8",c,5364756);d([47,115,118,103,47,100,97,114,107,103,114,101,101,110,0],"i8",c,5364768);d([47,115,118,103,47,100,97,114,107,103,114,97,121,0],"i8",c,5364784);d([37,115,58,37,100,58,32,115,116,114,105,110,103,32,114,97,110,32,112,97,115,116,32,101,110,100,32,111,102,32,108,105,110,101,10,0],"i8",c,5364800);d([47,115,118,103,47,100,97,114,107,103,111,108,100,101,110,114,111,100,0],"i8",c,5364836);d([47,115,118,103,47,100,97,114,107,99,121,97,110,0],"i8",c,5364856);d([47,115,118,103,47,100,97,114,107,98,108,117,101,0],"i8",c,5364872);d([34,47,62,10,0],"i8",c,5364888);d([37,115,10,0],"i8",c,5364896);d([47,115,118,103,47,99,121,97,110,0],"i8",c,5364900);d([47,115,118,103,47,99,114,105,109,115,111,110,0],"i8",c,5364912);d([47,115,118,103,47,99,111,114,110,115,105,108,107,0],"i8",c,5364928);d([47,115,118,103,47,99,111,114,110,102,108,111,119,101,114,98,108,117,101,0],"i8",c,5364944);d([103,101,0],"i8",c,5364964);d([47,115,118,103,47,99,111,114,97,108,0],"i8",c,5364968);d([47,98,117,103,110,54,47,50,0],"i8",c,5364980);d([47,115,118,103,47,99,104,111,99,111,108,97,116,101,0],"i8",c,5364992);d([47,115,118,103,47,99,104,97,114,116,114,101,117,115,101,0],"i8",c,5365008);d([47,115,118,103,47,99,97,100,101,116,98,108,117,101,0],"i8",c,5365024);d([65,118,97,110,116,71,97,114,100,101,45,68,101,109,105,0],"i8",c,5365040);d([47,115,118,103,47,98,117,114,108,121,119,111,111,100,0],"i8",c,5365056);d([47,115,118,103,47,98,114,111,119,110,0],"i8",c,5365072);d([37,103,44,37,103,32,0],"i8",c,5365084);d([105,110,118,105,115,0],"i8",c,5365092);d([47,115,118,103,47,98,108,117,101,118,105,111,108,101,116,0],"i8",c,5365100);d([47,115,118,103,47,98,108,117,101,0],"i8",c,5365116);d([92,71,0],"i8",c,5365128);d([47,115,118,103,47,98,108,97,110,99,104,101,100,97,108,109,111,110,100,0],"i8",c,5365132);d([83,32,0],"i8",c,5365152);d([47,115,118,103,47,98,108,97,99,107,0],"i8",c,5365156);d([103,97,109,109,97,0],"i8",c,5365168);d([69,68,95,116,111,95,118,105,114,116,40,101,41,32,33,61,32,78,85,76,76,0],"i8",c,5365176);d([47,115,118,103,47,98,105,115,113,117,101,0],"i8",c,5365200);d([47,98,117,103,110,54,47,49,0],"i8",c,5365212);d([47,115,118,103,47,98,101,105,103,101,0],"i8",c,5365224);d([44,32,0],"i8",c,5365236);d([99,97,110,110,111,116,32,114,101,97,108,108,111,99,32,116,114,105,115,0],"i8",c,5365240);d([47,115,118,103,47,97,122,117,114,101,0],"i8",c,5365260);d([78,111,116,32,98,117,105,108,116,32,119,105,116,104,32,108,105,98,101,120,112,97,116,46,32,84,97,98,108,101,32,102,111,114,109,97,116,116,105,110,103,32,105,115,32,110,111,116,32,97,118,97,105,108,97,98,108,101,46,10,0],"i8",c,5365272);d([104,101,97,100,95,108,112,0],"i8",c,5365336);d([47,115,118,103,47,97,113,117,97,109,97,114,105,110,101,0],"i8",c,5365344);d([110,101,119,46,103,118,0],"i8",c,5365360);d([99,111,117,108,100,110,39,116,32,111,112,101,110,32,101,112,115,102,32,102,105,108,101,32,37,115,10,0],"i8",c,5365368);d([47,115,118,103,47,97,113,117,97,0],"i8",c,5365396);d([47,115,118,103,47,97,110,116,105,113,117,101,119,104,105,116,101,0],"i8",c,5365408);d([32,112,111,105,110,116,115,61,34,0],"i8",c,5365428);d([37,115,32,0],"i8",c,5365440);d([115,97,109,101,104,101,97,100,0],"i8",c,5365444);d([99,97,100,101,116,98,108,117,101,0],"i8",c,5365456);d([47,115,118,103,47,97,108,105,99,101,98,108,117,101,0],"i8",c,5365468);d([47,115,112,101,99,116,114,97,108,57,47,57,0],"i8",c,5365484);d([47,115,112,101,99,116,114,97,108,57,47,56,0],"i8",c,5365500);d([47,115,112,101,99,116,114,97,108,57,47,55,0],"i8",c,5365516);d([102,114,97,115,108,0],"i8",c,5365532);d([47,115,112,101,99,116,114,97,108,57,47,54,0],"i8",c,5365540);d([47,98,117,103,110,53,47,53,0],"i8",c,5365556);d([47,115,112,101,99,116,114,97,108,57,47,53,0],"i8",c,5365568);d([47,115,112,101,99,116,114,97,108,57,47,52,0],"i8",c,5365584);d([47,115,112,101,99,116,114,97,108,57,47,51,0],"i8",c,5365600);d([47,115,112,101,99,116,114,97,108,57,47,50,0],"i8",c,5365616);d([47,115,112,101,99,116,114,97,108,57,47,49,0],"i8",c,5365632);d([60,112,111,108,121,108,105,110,101,0],"i8",c,5365648);d([109,109,0],"i8",c,5365660);d([115,101,116,108,105,110,101,119,105,100,116,104,0],"i8",c,5365664);d([47,115,112,101,99,116,114,97,108,56,47,56,0],"i8",c,5365680);d([32,32,32,32,32,32,32,32,47,69,110,99,111,100,105,110,103,32,69,110,99,111,100,105,110,103,86,101,99,116,111,114,32,100,101,102,0],"i8",c,5365696);d([47,115,112,101,99,116,114,97,108,56,47,55,0],"i8",c,5365736);d([99,111,108,111,114,32,37,115,0],"i8",c,5365752);d([47,115,112,101,99,116,114,97,108,56,47,54,0],"i8",c,5365764);d([47,115,112,101,99,116,114,97,108,56,47,53,0],"i8",c,5365780);d([102,114,97,99,51,52,0],"i8",c,5365796);d([47,115,112,101,99,116,114,97,108,56,47,52,0],"i8",c,5365804);d([47,98,117,103,110,53,47,52,0],"i8",c,5365820);d([47,115,112,101,99,116,114,97,108,56,47,51,0],"i8",c,5365832);d([47,115,112,101,99,116,114,97,108,56,47,50,0],"i8",c,5365848);d([47,115,112,101,99,116,114,97,108,56,47,49,0],"i8",c,5365864);d([47,115,112,101,99,116,114,97,108,55,47,55,0],"i8",c,5365880);d([47,115,112,101,99,116,114,97,108,55,47,54,0],"i8",c,5365896);d([32,115,101,116,108,105,110,101,119,105,100,116,104,10,0],"i8",c,5365912);d([47,115,112,101,99,116,114,97,108,55,47,53,0],"i8",c,5365928);d([47,115,112,101,99,116,114,97,108,55,47,52,0],"i8",c,5365944);d([47,115,112,101,99,116,114,97,108,55,47,51,0],"i8",c,5365960);d([47,115,112,101,99,116,114,97,108,55,47,50,0],"i8",c,5365976);d([102,114,97,99,49,52,0],"i8",c,5365992);d([104,97,108,102,0],"i8",c,5366e3);d([47,115,112,101,99,116,114,97,108,55,47,49,0],"i8",c,5366008);d([47,98,117,103,110,53,47,51,0],"i8",c,5366024);d([47,115,112,101,99,116,114,97,108,54,47,54,0],"i8",c,5366036);d([47,115,112,101,99,116,114,97,108,54,47,53,0],"i8",c,5366052);d([47,115,112,101,99,116,114,97,108,54,47,52,0],"i8",c,5366068);d([78,68,95,114,97,110,107,40,118,41,32,61,61,32,114,0],"i8",c,5366084);d([47,115,112,101,99,116,114,97,108,54,47,51,0],"i8",c,5366100);d([47,115,112,101,99,116,114,97,108,54,47,50,0],"i8",c,5366116);d([60,33,45,45,32,0],"i8",c,5366132);d([32,93,32,32,37,100,32,102,97,108,115,101,32,37,115,10,0],"i8",c,5366140);d([47,115,112,101,99,116,114,97,108,54,47,49,0],"i8",c,5366160);d([47,115,112,101,99,116,114,97,108,53,47,53,0],"i8",c,5366176);d([47,115,112,101,99,116,114,97,108,53,47,52,0],"i8",c,5366192);d([47,115,112,101,99,116,114,97,108,53,47,51,0],"i8",c,5366208);d([102,114,97,99,49,50,0],"i8",c,5366224);d([114,101,99,116,97,110,103,108,101,32,40,37,100,44,37,100,41,32,40,37,100,44,37,100,41,32,37,115,32,37,115,10,0],"i8",c,5366232);d([84,104,105,115,32,109,97,121,32,99,97,117,115,101,32,117,110,101,120,112,101,99,116,101,100,32,98,101,104,97,118,105,111,114,32,111,114,32,99,114,97,115,104,32,116,104,101,32,112,114,111,103,114,97,109,46,10,0],"i8",c,5366268);d([47,115,112,101,99,116,114,97,108,53,47,50,0],"i8",c,5366328);d([47,98,117,103,110,53,47,50,0],"i8",c,5366344);d([47,115,112,101,99,116,114,97,108,53,47,49,0],"i8",c,5366356);d([47,115,112,101,99,116,114,97,108,52,47,52,0],"i8",c,5366372);d([47,115,112,101,99,116,114,97,108,52,47,51,0],"i8",c,5366388);d([47,115,112,101,99,116,114,97,108,52,47,50,0],"i8",c,5366404);d([47,115,112,101,99,116,114,97,108,52,47,49,0],"i8",c,5366420);d([121,101,108,108,111,119,103,114,101,101,110,0],"i8",c,5366436);d([32,93,32,32,37,100,32,116,114,117,101,32,37,115,10,0],"i8",c,5366448);d([47,115,112,101,99,116,114,97,108,51,47,51,0],"i8",c,5366464);d([101,32,33,61,32,78,85,76,76,0],"i8",c,5366480);d([47,115,112,101,99,116,114,97,108,51,47,50,0],"i8",c,5366492);d([47,115,112,101,99,116,114,97,108,51,47,49,0],"i8",c,5366508);d([47,115,112,101,99,116,114,97,108,49,49,47,57,0],"i8",c,5366524);d([102,111,114,97,108,108,0],"i8",c,5366540);d([47,115,112,101,99,116,114,97,108,49,49,47,56,0],"i8",c,5366548);d([47,98,117,103,110,53,47,49,0],"i8",c,5366564);d([47,115,112,101,99,116,114,97,108,49,49,47,55,0],"i8",c,5366576);d([47,115,112,101,99,116,114,97,108,49,49,47,54,0],"i8",c,5366592);d([47,115,112,101,99,116,114,97,108,49,49,47,53,0],"i8",c,5366608);d([47,115,112,101,99,116,114,97,108,49,49,47,52,0],"i8",c,5366624);d([71,0],"i8",c,5366640);d([47,115,112,101,99,116,114,97,108,49,49,47,51,0],"i8",c,5366644);d([38,108,116,59,0],"i8",c,5366660);d([32,0],"i8",c,5366668);d([47,97,99,99,101,110,116,54,47,49,0],"i8",c,5366672);d([47,115,112,101,99,116,114,97,108,49,49,47,50,0],"i8",c,5366684);d([47,115,112,101,99,116,114,97,108,49,49,47,49,49,0],"i8",c,5366700);d([47,115,112,101,99,116,114,97,108,49,49,47,49,48,0],"i8",c,5366716);d([47,115,112,101,99,116,114,97,108,49,49,47,49,0],"i8",c,5366732);d([102,110,111,102,0],"i8",c,5366748);d([47,115,112,101,99,116,114,97,108,49,48,47,57,0],"i8",c,5366756);d([47,98,117,103,110,52,47,52,0],"i8",c,5366772);d([47,115,112,101,99,116,114,97,108,49,48,47,56,0],"i8",c,5366784);d([47,115,112,101,99,116,114,97,108,49,48,47,55,0],"i8",c,5366800);d([47,115,112,101,99,116,114,97,108,49,48,47,54,0],"i8",c,5366816);d([47,115,112,101,99,116,114,97,108,49,48,47,53,0],"i8",c,5366832);d([47,115,112,101,99,116,114,97,108,49,48,47,52,0],"i8",c,5366848);d([119,104,105,116,101,115,109,111,107,101,0],"i8",c,5366864);d([99,105,114,99,108,101,0],"i8",c,5366876);d([106,112,103,58,118,114,109,108,0],"i8",c,5366884);d([47,115,112,101,99,116,114,97,108,49,48,47,51,0],"i8",c,5366896);d([47,115,112,101,99,116,114,97,108,49,48,47,50,0],"i8",c,5366912);d([101,110,100,32,112,111,114,116,58,32,40,37,46,53,103,44,32,37,46,53,103,41,44,32,116,97,110,103,101,110,116,32,97,110,103,108,101,58,32,37,46,53,103,44,32,37,115,10,0],"i8",c,5366928);d([47,115,112,101,99,116,114,97,108,49,48,47,49,48,0],"i8",c,5366980);d([47,115,112,101,99,116,114,97,108,49,48,47,49,0],"i8",c,5366996);d([101,120,105,115,116,0],"i8",c,5367012);d([47,115,101,116,51,57,47,57,0],"i8",c,5367020);d([47,98,117,103,110,52,47,51,0],"i8",c,5367032);d([47,115,101,116,51,57,47,56,0],"i8",c,5367044);d([47,115,101,116,51,57,47,55,0],"i8",c,5367056);d([47,115,101,116,51,57,47,54,0],"i8",c,5367068);d([47,115,101,116,51,57,47,53,0],"i8",c,5367080);d([47,115,101,116,51,57,47,52,0],"i8",c,5367092);d([47,115,101,116,51,57,47,51,0],"i8",c,5367104);d([47,115,101,116,51,57,47,50,0],"i8",c,5367116);d([103,118,114,101,110,100,101,114,95,99,111,114,101,95,102,105,103,46,99,0],"i8",c,5367128);d([47,115,101,116,51,57,47,49,0],"i8",c,5367148);d([47,115,101,116,51,56,47,56,0],"i8",c,5367160);d([101,117,114,111,0],"i8",c,5367172);d([103,114,97,121,0],"i8",c,5367180);d([47,115,101,116,51,56,47,55,0],"i8",c,5367188);d([47,98,117,103,110,52,47,50,0],"i8",c,5367200);d([47,115,101,116,51,56,47,54,0],"i8",c,5367212);d([47,115,101,116,51,56,47,53,0],"i8",c,5367224);d([47,115,101,116,51,56,47,52,0],"i8",c,5367236);d([110,111,110,45,116,101,114,109,105,110,97,116,101,100,32,72,84,77,76,32,115,116,114,105,110,103,32,115,116,97,114,116,105,110,103,32,108,105,110,101,32,37,100,44,32,102,105,108,101,32,37,115,10,0],"i8",c,5367248);d([47,115,101,116,51,56,47,51,0],"i8",c,5367304);d([103,118,114,101,110,100,101,114,95,99,111,114,101,95,116,107,46,99,0],"i8",c,5367316);d([47,115,101,116,51,56,47,50,0],"i8",c,5367336);d([119,104,101,97,116,0],"i8",c,5367348);d([112,115,50,58,112,115,0],"i8",c,5367356);d([47,115,101,116,51,56,47,49,0],"i8",c,5367364);d([47,115,101,116,51,55,47,55,0],"i8",c,5367376);d([47,115,101,116,51,55,47,54,0],"i8",c,5367388);d([47,115,101,116,51,55,47,53,0],"i8",c,5367400);d([101,117,109,108,0],"i8",c,5367412);d([47,115,101,116,51,55,47,52,0],"i8",c,5367420);d([47,98,117,103,110,52,47,49,0],"i8",c,5367432);d([47,115,101,116,51,55,47,51,0],"i8",c,5367444);d([47,115,101,116,51,55,47,50,0],"i8",c,5367456);d([47,115,101,116,51,55,47,49,0],"i8",c,5367468);d([105,116,97,108,105,99,0],"i8",c,5367480);d([47,115,101,116,51,54,47,54,0],"i8",c,5367488);d([47,115,101,116,51,54,47,53,0],"i8",c,5367500);d([118,105,111,108,101,116,0],"i8",c,5367512);d([47,115,101,116,51,54,47,52,0],"i8",c,5367520);d([47,115,101,116,51,54,47,51,0],"i8",c,5367532);d([47,115,101,116,51,54,47,50,0],"i8",c,5367544);d([115,101,116,108,105,110,101,119,105,100,116,104,40,37,46,51,102,41,0],"i8",c,5367556);d([116,107,58,116,107,0],"i8",c,5367576);d([47,115,101,116,51,54,47,49,0],"i8",c,5367584);d([101,116,104,0],"i8",c,5367596);d([119,101,105,103,104,116,0],"i8",c,5367600);d([47,115,101,116,51,53,47,53,0],"i8",c,5367608);d([47,98,117,103,110,51,47,51,0],"i8",c,5367620);d([47,115,101,116,51,53,47,52,0],"i8",c,5367632);d([44,10,0],"i8",c,5367644);d([99,97,110,110,111,116,32,109,97,108,108,111,99,32,116,114,105,115,0],"i8",c,5367648);d([47,115,101,116,51,53,47,51,0],"i8",c,5367668);d([108,112,0],"i8",c,5367680);d([47,115,101,116,51,53,47,50,0],"i8",c,5367684);d([85,84,70,45,56,32,105,110,112,117,116,32,117,115,101,115,32,110,111,110,45,76,97,116,105,110,49,32,99,104,97,114,97,99,116,101,114,115,32,119,104,105,99,104,32,99,97,110,110,111,116,32,98,101,32,104,97,110,100,108,101,100,32,98,121,32,116,104,105,115,32,80,111,115,116,83,99,114,105,112,116,32,100,114,105,118,101,114,10,0],"i8",c,5367696);d([103,114,97,112,104,118,105,122,0],"i8",c,5367788);d([47,115,101,116,51,53,47,49,0],"i8",c,5367800);d([47,115,101,116,51,52,47,52,0],"i8",c,5367812);d([116,117,114,113,117,111,105,115,101,0],"i8",c,5367824);d([112,115,0],"i8",c,5367836);d([47,115,101,116,51,52,47,51,0],"i8",c,5367840);d([98,117,114,108,121,119,111,111,100,0],"i8",c,5367852);d([47,115,101,116,51,52,47,50,0],"i8",c,5367864);d([47,115,101,116,51,52,47,49,0],"i8",c,5367876);d([47,115,101,116,51,51,47,51,0],"i8",c,5367888);d([101,116,97,0],"i8",c,5367900);d([47,115,101,116,51,51,47,50,0],"i8",c,5367904);d([47,98,117,103,110,51,47,50,0],"i8",c,5367916);d([47,115,101,116,51,51,47,49,0],"i8",c,5367928);d([47,115,101,116,51,49,50,47,57,0],"i8",c,5367940);d([47,115,101,116,51,49,50,47,56,0],"i8",c,5367952);d([47,115,101,116,51,49,50,47,55,0],"i8",c,5367964);d([47,115,101,116,51,49,50,47,54,0],"i8",c,5367976);d([116,111,109,97,116,111,0],"i8",c,5367988);d([99,109,0],"i8",c,5367996);d([37,37,69,110,100,83,101,116,117,112,0],"i8",c,5368e3);d([47,115,101,116,51,49,50,47,53,0],"i8",c,5368012);d([32,32,32,32,32,32,32,32,125,32,102,111,114,97,108,108,0],"i8",c,5368024);d([47,115,101,116,51,49,50,47,52,0],"i8",c,5368044);d([98,111,116,104,0],"i8",c,5368056);d([47,115,101,116,51,49,50,47,51,0],"i8",c,5368064);d([47,115,101,116,51,49,50,47,50,0],"i8",c,5368076);d([101,113,117,105,118,0],"i8",c,5368088);d([47,115,101,116,51,49,50,47,49,50,0],"i8",c,5368096);d([47,98,117,103,110,51,47,49,0],"i8",c,5368108);d([47,115,101,116,51,49,50,47,49,49,0],"i8",c,5368120);d([47,115,101,116,51,49,50,47,49,48,0],"i8",c,5368132);d([41,10,45,45,62,10,0],"i8",c,5368144);d([47,115,101,116,51,49,50,47,49,0],"i8",c,5368152);d([47,115,101,116,51,49,49,47,57,0],"i8",c,5368164);d([47,115,101,116,51,49,49,47,56,0],"i8",c,5368176);d([116,104,105,115,116,108,101,0],"i8",c,5368188);d([125,32,105,102,0],"i8",c,5368196);d([47,115,101,116,51,49,49,47,55,0],"i8",c,5368204);d([47,115,101,116,51,49,49,47,54,0],"i8",c,5368216);d([47,115,101,116,51,49,49,47,53,0],"i8",c,5368228);d([47,115,101,116,51,49,49,47,52,0],"i8",c,5368240);d([101,112,115,105,108,111,110,0],"i8",c,5368252);d([47,115,101,116,51,49,49,47,51,0],"i8",c,5368260);d([47,98,114,98,103,57,47,57,0],"i8",c,5368272);d([47,115,101,116,51,49,49,47,50,0],"i8",c,5368284);d([47,115,101,116,51,49,49,47,49,49,0],"i8",c,5368296);d([32,40,0],"i8",c,5368308);d([47,115,101,116,51,49,49,47,49,48,0],"i8",c,5368312);d([47,115,101,116,51,49,49,47,49,0],"i8",c,5368324);d([47,115,101,116,51,49,48,47,57,0],"i8",c,5368336);d([32,32,32,32,117,115,101,114,100,105,99,116,32,40,62,62,41,32,99,118,110,32,40,91,41,32,99,118,110,32,108,111,97,100,32,112,117,116,0],"i8",c,5368348);d([47,115,101,116,51,49,48,47,56,0],"i8",c,5368388);d([47,115,101,116,51,49,48,47,55,0],"i8",c,5368400);d([47,115,101,116,51,49,48,47,54,0],"i8",c,5368412);d([47,115,101,116,51,49,48,47,53,0],"i8",c,5368424);d([101,110,115,112,0],"i8",c,5368436);d([47,115,101,116,51,49,48,47,52,0],"i8",c,5368444);d([47,98,114,98,103,57,47,56,0],"i8",c,5368456);d([84,104,101,32,117,115,101,32,111,102,32,34,115,117,98,103,114,97,112,104,32,37,115,34,44,32,108,105,110,101,32,37,100,44,32,119,105,116,104,111,117,116,32,97,32,98,111,100,121,32,105,115,32,100,101,112,114,101,99,97,116,101,100,46,10,0],"i8",c,5368468);d([47,115,101,116,51,49,48,47,51,0],"i8",c,5368536);d([47,115,101,116,51,49,48,47,50,0],"i8",c,5368548);d([32,118,101,114,115,105,111,110,32,0],"i8",c,5368560);d([47,115,101,116,51,49,48,47,49,48,0],"i8",c,5368572);d([47,115,101,116,51,49,48,47,49,0],"i8",c,5368584);d([47,115,101,116,50,56,47,56,0],"i8",c,5368596);d([116,97,110,0],"i8",c,5368608);d([32,32,32,32,117,115,101,114,100,105,99,116,32,40,60,60,41,32,99,118,110,32,40,91,41,32,99,118,110,32,108,111,97,100,32,112,117,116,0],"i8",c,5368612);d([47,115,101,116,50,56,47,55,0],"i8",c,5368652);d([76,101,102,116,0],"i8",c,5368664);d([47,115,101,116,50,56,47,54,0],"i8",c,5368672);d([47,115,101,116,50,56,47,53,0],"i8",c,5368684);d([47,115,101,116,50,56,47,52,0],"i8",c,5368696);d([101,109,115,112,0],"i8",c,5368708);d([47,115,101,116,50,56,47,51,0],"i8",c,5368716);d([47,98,114,98,103,57,47,55,0],"i8",c,5368728);d([47,115,101,116,50,56,47,50,0],"i8",c,5368740);d([47,115,101,116,50,56,47,49,0],"i8",c,5368752);d([10,60,33,45,45,32,71,101,110,101,114,97,116,101,100,32,98,121,32,0],"i8",c,5368764);d([47,115,101,116,50,55,47,55,0],"i8",c,5368784);d([47,115,101,116,50,55,47,54,0],"i8",c,5368796);d([47,115,101,116,50,55,47,53,0],"i8",c,5368808);d([115,116,101,101,108,98,108,117,101,0],"i8",c,5368820);d([92,78,0],"i8",c,5368832);d([50,32,108,116,32,123,0],"i8",c,5368836);d([47,97,99,99,101,110,116,53,47,53,0],"i8",c,5368844);d([47,115,101,116,50,55,47,52,0],"i8",c,5368856);d([47,115,101,116,50,55,47,51,0],"i8",c,5368868);d([47,115,101,116,50,55,47,50,0],"i8",c,5368880);d([47,115,101,116,50,55,47,49,0],"i8",c,5368892);d([101,109,112,116,121,0],"i8",c,5368904);d([47,115,101,116,50,54,47,54,0],"i8",c,5368912);d([47,98,114,98,103,57,47,54,0],"i8",c,5368924);d([47,115,101,116,50,54,47,53,0],"i8",c,5368936);d([47,115,101,116,50,54,47,52,0],"i8",c,5368948);d([60,72,84,77,76,62,10,0],"i8",c,5368960);d([47,115,101,116,50,54,47,51,0],"i8",c,5368968);d([47,115,101,116,50,54,47,50,0],"i8",c,5368980);d([47,115,101,116,50,54,47,49,0],"i8",c,5368992);d([115,112,114,105,110,103,103,114,101,101,110,0],"i8",c,5369004);d([111,118,97,108,0],"i8",c,5369016);d([102,105,103,58,102,105,103,0],"i8",c,5369024);d([106,112,101,58,118,114,109,108,0],"i8",c,5369032);d([47,115,101,116,50,53,47,53,0],"i8",c,5369044);d([47,115,101,116,50,53,47,52,0],"i8",c,5369056);d([110,111,116,32,99,111,110,115,116,114,97,105,110,101,100,0],"i8",c,5369068);d([47,108,97,110,103,117,97,103,101,108,101,118,101,108,32,119,104,101,114,101,32,123,112,111,112,32,108,97,110,103,117,97,103,101,108,101,118,101,108,125,123,49,125,32,105,102,101,108,115,101,0],"i8",c,5369084);d([47,115,101,116,50,53,47,51,0],"i8",c,5369136);d([47,115,101,116,50,53,47,50,0],"i8",c,5369148);d([101,103,114,97,118,101,0],"i8",c,5369160);d([47,115,101,116,50,53,47,49,0],"i8",c,5369168);d([47,98,114,98,103,57,47,53,0],"i8",c,5369180);d([47,115,101,116,50,52,47,52,0],"i8",c,5369192);d([47,115,101,116,50,52,47,51,0],"i8",c,5369204);d([101,99,105,114,99,0],"i8",c,5369216);d([32,99,111,111,114,100,111,114,105,103,105,110,61,34,48,44,48,34,32,99,111,111,114,100,115,105,122,101,61,34,37,100,44,37,100,34,32,62,0],"i8",c,5369224);d([47,115,101,116,50,52,47,50,0],"i8",c,5369264);d([47,115,101,116,50,52,47,49,0],"i8",c,5369276);d([47,115,101,116,50,51,47,51,0],"i8",c,5369288);d([115,110,111,119,0],"i8",c,5369300);d([37,32,109,97,107,101,32,39,60,60,39,32,97,110,100,32,39,62,62,39,32,115,97,102,101,32,111,110,32,80,83,32,76,101,118,101,108,32,49,32,100,101,118,105,99,101,115,0],"i8",c,5369308);d([47,115,101,116,50,51,47,50,0],"i8",c,5369356);d([47,115,101,116,50,51,47,49,0],"i8",c,5369368);d([47,115,101,116,49,57,47,57,0],"i8",c,5369380);d([47,115,101,116,49,57,47,56,0],"i8",c,5369392);d([108,0],"i8",c,5369404);d([47,115,101,116,49,57,47,55,0],"i8",c,5369408);d([102,117,99,104,115,105,97,0],"i8",c,5369420);d([47,98,114,98,103,57,47,52,0],"i8",c,5369428);d([47,115,101,116,49,57,47,54,0],"i8",c,5369440);d([47,115,101,116,49,57,47,53,0],"i8",c,5369452);d([32,119,105,100,116,104,58,32,37,100,112,116,59,32,104,101,105,103,104,116,58,32,37,100,112,116,34,0],"i8",c,5369464);d([47,115,101,116,49,57,47,52,0],"i8",c,5369492);d([47,115,101,116,49,57,47,51,0],"i8",c,5369504);d([103,114,97,112,104,32,108,97,98,101,108,0],"i8",c,5369516);d([37,115,58,37,100,58,32,97,109,98,105,103,117,111,117,115,32,34,37,115,34,32,115,112,108,105,116,115,32,105,110,116,111,32,116,119,111,32,110,97,109,101,115,58,32,34,37,115,34,32,97,110,100,32,34,37,115,34,10,0],"i8",c,5369528);d([47,115,101,116,49,57,47,50,0],"i8",c,5369588);d([115,108,97,116,101,103,114,101,121,0],"i8",c,5369600);d([47,112,100,102,109,97,114,107,32,119,104,101,114,101,32,123,112,111,112,125,32,123,117,115,101,114,100,105,99,116,32,47,112,100,102,109,97,114,107,32,47,99,108,101,97,114,116,111,109,97,114,107,32,108,111,97,100,32,112,117,116,125,32,105,102,101,108,115,101,0],"i8",c,5369612);d([47,115,101,116,49,57,47,49,0],"i8",c,5369684);d([47,115,101,116,49,56,47,56,0],"i8",c,5369696);d([47,115,101,116,49,56,47,55,0],"i8",c,5369708);d([47,115,101,116,49,56,47,54,0],"i8",c,5369720);d([101,97,99,117,116,101,0],"i8",c,5369732);d([47,115,101,116,49,56,47,53,0],"i8",c,5369740);d([47,98,114,98,103,57,47,51,0],"i8",c,5369752);d([47,115,101,116,49,56,47,52,0],"i8",c,5369764);d([47,115,101,116,49,56,47,51,0],"i8",c,5369776);d([32,60,118,58,103,114,111,117,112,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,32,0],"i8",c,5369788);d([47,115,101,116,49,56,47,50,0],"i8",c,5369828);d([111,98,108,105,113,117,101,0],"i8",c,5369840);d([47,115,101,116,49,56,47,49,0],"i8",c,5369848);d([47,115,101,116,49,55,47,55,0],"i8",c,5369860);d([115,108,97,116,101,103,114,97,121,0],"i8",c,5369872);d([37,32,109,97,107,101,32,115,117,114,101,32,112,100,102,109,97,114,107,32,105,115,32,104,97,114,109,108,101,115,115,32,102,111,114,32,80,83,45,105,110,116,101,114,112,114,101,116,101,114,115,32,111,116,104,101,114,32,116,104,97,110,32,68,105,115,116,105,108,108,101,114,0],"i8",c,5369884);d([47,115,101,116,49,55,47,54,0],"i8",c,5369960);d([47,115,101,116,49,55,47,53,0],"i8",c,5369972);d([47,115,101,116,49,55,47,52,0],"i8",c,5369984);d([35,37,48,50,120,37,48,50,120,37,48,50,120,37,48,50,120,0],"i8",c,5369996);d([32,91,0],"i8",c,5370016);d([47,115,101,116,49,55,47,51,0],"i8",c,5370020);d([100,105,118,105,100,101,0],"i8",c,5370032);d([108,104,101,97,100,0],"i8",c,5370040);d([47,115,101,116,49,55,47,50,0],"i8",c,5370048);d([47,98,114,98,103,57,47,50,0],"i8",c,5370060);d([47,115,101,116,49,55,47,49,0],"i8",c,5370072);d([97,103,117,115,101,114,103,114,97,112,104,0],"i8",c,5370084);d([114,111,117,116,101,46,99,0],"i8",c,5370096);d([47,115,101,116,49,54,47,54,0],"i8",c,5370104);d([120,108,112,0],"i8",c,5370116);d([60,120,109,108,58,110,97,109,101,115,112,97,99,101,32,110,115,61,34,117,114,110,58,115,99,104,101,109,97,115,45,109,105,99,114,111,115,111,102,116,45,99,111,109,58,118,109,108,34,32,112,114,101,102,105,120,61,34,118,34,32,47,62,10,0],"i8",c,5370120);d([47,115,101,116,49,54,47,53,0],"i8",c,5370188);d([70,0],"i8",c,5370200);d([125,32,98,105,110,100,32,100,101,102,10,0],"i8",c,5370204);d([47,115,101,116,49,54,47,52,0],"i8",c,5370216);d([47,115,101,116,49,54,47,51,0],"i8",c,5370228);d([115,108,97,116,101,98,108,117,101,0],"i8",c,5370240);d([37,32,47,97,114,114,111,119,119,105,100,116,104,32,53,32,100,101,102,0],"i8",c,5370252);d([47,115,101,116,49,54,47,50,0],"i8",c,5370272);d([98,114,111,119,110,0],"i8",c,5370284);d([76,97,121,111,117,116,32,116,121,112,101,58,32,34,37,115,34,32,110,111,116,32,114,101,99,111,103,110,105,122,101,100,46,32,85,115,101,32,111,110,101,32,111,102,58,37,115,10,0],"i8",c,5370292);d([47,115,101,116,49,54,47,49,0],"i8",c,5370344);d([47,115,101,116,49,53,47,53,0],"i8",c,5370356);d([47,115,101,116,49,53,47,52,0],"i8",c,5370368);d([100,105,97,109,115,0],"i8",c,5370380);d([99,108,117,115,116,101,114,32,110,97,109,101,100,32,37,115,32,110,111,116,32,102,111,117,110,100,10,0],"i8",c,5370388);d([47,115,101,116,49,53,47,51,0],"i8",c,5370416);d([47,98,114,98,103,57,47,49,0],"i8",c,5370428);d([47,115,101,116,49,53,47,50,0],"i8",c,5370440);d([47,115,101,116,49,53,47,49,0],"i8",c,5370452);d([60,47,83,84,89,76,69,62,10,0],"i8",c,5370464);d([47,115,101,116,49,52,47,52,0],"i8",c,5370476);d([47,115,101,116,49,52,47,51,0],"i8",c,5370488);d([47,115,101,116,49,52,47,50,0],"i8",c,5370500);d([115,107,121,98,108,117,101,0],"i8",c,5370512);d([37,32,47,97,114,114,111,119,108,101,110,103,116,104,32,49,48,32,100,101,102,0],"i8",c,5370520);d([110,115,108,105,109,105,116,49,0],"i8",c,5370544);d([47,115,101,116,49,52,47,49,0],"i8",c,5370556);d([32,32,32,32,32,32,32,32,123,32,49,32,105,110,100,101,120,32,47,70,73,68,32,110,101,32,123,32,100,101,102,32,125,123,32,112,111,112,32,112,111,112,32,125,32,105,102,101,108,115,101,0],"i8",c,5370568);d([116,114,105,97,110,103,117,108,97,116,105,111,110,32,102,97,105,108,101,100,0],"i8",c,5370620);d([47,115,101,116,49,51,47,51,0],"i8",c,5370644);d([104,101,105,103,104,116,0],"i8",c,5370656);d([47,115,101,116,49,51,47,50,0],"i8",c,5370664);d([47,115,101,116,49,51,47,49,0],"i8",c,5370676);d([100,101,108,116,97,0],"i8",c,5370688);d([47,114,101,100,115,57,47,57,0],"i8",c,5370696);d([47,98,114,98,103,56,47,56,0],"i8",c,5370708);d([47,114,101,100,115,57,47,56,0],"i8",c,5370720);d([47,114,101,100,115,57,47,55,0],"i8",c,5370732);d([118,92,58,42,32,123,32,98,101,104,97,118,105,111,114,58,32,117,114,108,40,35,100,101,102,97,117,108,116,35,86,77,76,41,59,100,105,115,112,108,97,121,58,105,110,108,105,110,101,45,98,108,111,99,107,125,10,0],"i8",c,5370744);d([47,114,101,100,115,57,47,54,0],"i8",c,5370804);d([47,114,101,100,115,57,47,53,0],"i8",c,5370816);d([47,114,101,100,115,57,47,52,0],"i8",c,5370828);d([49,32,115,101,116,109,105,116,101,114,108,105,109,105,116,0],"i8",c,5370840);d([47,114,101,100,115,57,47,51,0],"i8",c,5370856);d([105,110,32,108,97,98,101,108,32,111,102,32,110,111,100,101,32,37,115,10,0],"i8",c,5370868);d([69,68,95,108,97,98,101,108,40,102,101,41,0],"i8",c,5370892);d([73,32,0],"i8",c,5370908);d([47,114,101,100,115,57,47,50,0],"i8",c,5370912);d([47,114,101,100,115,57,47,49,0],"i8",c,5370924);d([47,114,101,100,115,56,47,56,0],"i8",c,5370936);d([100,101,103,0],"i8",c,5370948);d([99,114,111,119,0],"i8",c,5370952);d([47,114,101,100,115,56,47,55,0],"i8",c,5370960);d([47,98,114,98,103,56,47,55,0],"i8",c,5370972);d([47,114,101,100,115,56,47,54,0],"i8",c,5370984);d([47,114,101,100,115,56,47,53,0],"i8",c,5370996);d([60,83,84,89,76,69,62,10,0],"i8",c,5371008);d([47,114,101,100,115,56,47,52,0],"i8",c,5371020);d([47,114,101,100,115,56,47,51,0],"i8",c,5371032);d([47,114,101,100,115,56,47,50,0],"i8",c,5371044);d([115,105,101,110,110,97,0],"i8",c,5371056);d([49,52,32,100,101,102,97,117,108,116,45,102,111,110,116,45,102,97,109,105,108,121,32,115,101,116,95,102,111,110,116,0],"i8",c,5371064);d([47,114,101,100,115,56,47,49,0],"i8",c,5371096);d([99,108,97,115,115,50,46,99,0],"i8",c,5371108);d([47,114,101,100,115,55,47,55,0],"i8",c,5371120);d([47,114,101,100,115,55,47,54,0],"i8",c,5371132);d([47,114,101,100,115,55,47,53,0],"i8",c,5371144);d([100,97,114,114,0],"i8",c,5371156);d([47,114,101,100,115,55,47,52,0],"i8",c,5371164);d([47,98,114,98,103,56,47,54,0],"i8",c,5371176);d([47,114,101,100,115,55,47,51,0],"i8",c,5371188);d([103,118,114,101,110,100,101,114,95,99,111,114,101,95,109,97,112,46,99,0],"i8",c,5371200);d([71,115,116,97,99,107,32,111,118,101,114,102,108,111,119,32,105,110,32,103,114,97,112,104,32,112,97,114,115,101,114,10,0],"i8",c,5371220);d([47,114,101,100,115,55,47,50,0],"i8",c,5371256);d([32,119,105,100,116,104,58,32,37,100,112,116,59,32,104,101,105,103,104,116,58,32,37,100,112,116,34,62,10,0],"i8",c,5371268);d([47,114,101,100,115,55,47,49,0],"i8",c,5371300);d([47,114,101,100,115,54,47,54,0],"i8",c,5371312);d([47,114,101,100,115,54,47,53,0],"i8",c,5371324);d([115,101,97,115,104,101,108,108,0],"i8",c,5371336);d([37,37,66,101,103,105,110,83,101,116,117,112,0],"i8",c,5371348);d([47,114,101,100,115,54,47,52,0],"i8",c,5371364);d([85,110,115,117,112,112,111,114,116,101,100,32,99,104,97,114,115,101,116,32,34,37,115,34,32,45,32,97,115,115,117,109,105,110,103,32,117,116,102,45,56,10,0],"i8",c,5371376);d([47,114,101,100,115,54,47,51,0],"i8",c,5371420);d([47,114,101,100,115,54,47,50,0],"i8",c,5371432);d([47,114,101,100,115,54,47,49,0],"i8",c,5371444);d([100,97,103,103,101,114,0],"i8",c,5371456);d([47,114,101,100,115,53,47,53,0],"i8",c,5371464);d([47,98,114,98,103,56,47,53,0],"i8",c,5371476);d([47,114,101,100,115,53,47,52,0],"i8",c,5371488);d([47,114,101,100,115,53,47,51,0],"i8",c,5371500);d([60,68,73,86,32,105,100,61,39,95,86,77,76,49,95,39,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,32,100,105,115,112,108,97,121,58,105,110,108,105,110,101,59,32,118,105,115,105,98,105,108,105,116,121,58,104,105,100,100,101,110,0],"i8",c,5371512);d([47,114,101,100,115,53,47,50,0],"i8",c,5371592);d([47,114,101,100,115,53,47,49,0],"i8",c,5371604);d([47,114,101,100,115,52,47,52,0],"i8",c,5371616);d([115,101,97,103,114,101,101,110,0],"i8",c,5371628);d([47,114,101,100,115,52,47,51,0],"i8",c,5371640);d([47,97,99,99,101,110,116,53,47,52,0],"i8",c,5371652);d([117,116,102,56,0],"i8",c,5371664);d([114,97,110,107,115,101,112,0],"i8",c,5371672);d([47,114,101,100,115,52,47,50,0],"i8",c,5371680);d([37,37,69,110,100,80,114,111,108,111,103,0],"i8",c,5371692);d([47,114,101,100,115,52,47,49,0],"i8",c,5371704);d([47,114,101,100,115,51,47,51,0],"i8",c,5371716);d([100,65,114,114,0],"i8",c,5371728);d([47,114,101,100,115,51,47,50,0],"i8",c,5371736);d([47,98,114,98,103,56,47,52,0],"i8",c,5371748);d([47,114,101,100,115,51,47,49,0],"i8",c,5371760);d([47,114,100,121,108,103,110,57,47,57,0],"i8",c,5371772);d([60,66,79,68,89,32,111,110,108,111,97,100,61,39,98,114,111,119,115,101,114,99,104,101,99,107,40,41,59,39,62,10,0],"i8",c,5371784);d([47,114,100,121,108,103,110,57,47,56,0],"i8",c,5371820);d([47,114,100,121,108,103,110,57,47,55,0],"i8",c,5371832);d([47,114,100,121,108,103,110,57,47,54,0],"i8",c,5371844);d([115,97,110,100,121,98,114,111,119,110,0],"i8",c,5371856);d([37,37,69,110,100,82,101,115,111,117,114,99,101,0],"i8",c,5371868);d([101,108,108,105,112,115,101,0],"i8",c,5371884);d([47,114,100,121,108,103,110,57,47,53,0],"i8",c,5371892);d([106,112,101,103,58,118,114,109,108,0],"i8",c,5371904);d([98,105,103,53,0],"i8",c,5371916);d([47,114,100,121,108,103,110,57,47,52,0],"i8",c,5371924);d([99,111,110,115,116,114,97,105,110,101,100,0],"i8",c,5371936);d([47,114,100,121,108,103,110,57,47,51,0],"i8",c,5371948);d([47,114,100,121,108,103,110,57,47,50,0],"i8",c,5371960);d([99,117,114,114,101,110,0],"i8",c,5371972);d([47,114,100,121,108,103,110,57,47,49,0],"i8",c,5371980);d([47,98,114,98,103,56,47,51,0],"i8",c,5371992);d([47,114,100,121,108,103,110,56,47,56,0],"i8",c,5372004);d([47,114,100,121,108,103,110,56,47,55,0],"i8",c,5372016);d([60,47,72,69,65,68,62,0],"i8",c,5372028);d([47,114,100,121,108,103,110,56,47,54,0],"i8",c,5372036);d([47,114,100,121,108,103,110,56,47,53,0],"i8",c,5372048);d([47,114,100,121,108,103,110,56,47,52,0],"i8",c,5372060);d([115,97,108,109,111,110,0],"i8",c,5372072);d([47,99,117,114,108,97,121,101,114,32,48,32,100,101,102,0],"i8",c,5372080);d([47,114,100,121,108,103,110,56,47,51,0],"i8",c,5372096);d([98,105,103,45,53,0],"i8",c,5372108);d([47,114,100,121,108,103,110,56,47,50,0],"i8",c,5372116);d([47,114,100,121,108,103,110,56,47,49,0],"i8",c,5372128);d([47,114,100,121,108,103,110,55,47,55,0],"i8",c,5372140);d([99,117,112,0],"i8",c,5372152);d([115,104,97,112,101,102,105,108,101,32,110,111,116,32,115,101,116,32,111,114,32,110,111,116,32,102,111,117,110,100,32,102,111,114,32,101,112,115,102,32,110,111,100,101,32,37,115,10,0],"i8",c,5372156);d([32,37,100,32,37,100,0],"i8",c,5372208);d([75,80,95,83,117,98,116,114,97,99,116,0],"i8",c,5372216);d([47,114,100,121,108,103,110,55,47,54,0],"i8",c,5372228);d([98,108,117,101,0],"i8",c,5372240);d([47,98,114,98,103,56,47,50,0],"i8",c,5372248);d([47,114,100,121,108,103,110,55,47,53,0],"i8",c,5372260);d([47,114,100,121,108,103,110,55,47,52,0],"i8",c,5372272);d([32,32,32,60,47,83,67,82,73,80,84,62,10,0],"i8",c,5372284);d([47,114,100,121,108,103,110,55,47,51,0],"i8",c,5372300);d([47,114,100,121,108,103,110,55,47,50,0],"i8",c,5372312);d([103,114,97,112,104,0],"i8",c,5372324);d([47,114,100,121,108,103,110,55,47,49,0],"i8",c,5372332);d([115,97,100,100,108,101,98,114,111,119,110,0],"i8",c,5372344);d([32,60,60,60,32,0],"i8",c,5372356);d([9,123,105,110,118,105,115,125,32,105,102,0],"i8",c,5372364);d([47,114,100,121,108,103,110,54,47,54,0],"i8",c,5372376);d([99,111,109,112,111,117,110,100,0],"i8",c,5372388);d([59,10,0],"i8",c,5372400);d([73,83,79,45,73,82,45,49,48,48,0],"i8",c,5372404);d([47,114,100,121,108,103,110,54,47,53,0],"i8",c,5372416);d([47,114,100,121,108,103,110,54,47,52,0],"i8",c,5372428);d([47,114,100,121,108,103,110,54,47,51,0],"i8",c,5372440);d([99,114,97,114,114,0],"i8",c,5372452);d([47,114,100,121,108,103,110,54,47,50,0],"i8",c,5372460);d([47,98,114,98,103,56,47,49,0],"i8",c,5372472);d([47,114,100,121,108,103,110,54,47,49,0],"i8",c,5372484);d([47,114,100,121,108,103,110,53,47,53,0],"i8",c,5372496);d([47,114,100,121,108,103,110,53,47,52,0],"i8",c,5372508);d([32,32,32,125,10,0],"i8",c,5372520);d([65,118,97,110,116,71,97,114,100,101,45,66,111,111,107,79,98,108,105,113,117,101,0],"i8",c,5372528);d([47,114,100,121,108,103,110,53,47,51,0],"i8",c,5372552);d([47,114,100,121,108,103,110,53,47,50,0],"i8",c,5372564);d([114,111,121,97,108,98,108,117,101,0],"i8",c,5372576);d([9,111,114,0],"i8",c,5372588);d([47,114,100,121,108,103,110,53,47,49,0],"i8",c,5372592);d([73,83,79,56,56,53,57,45,49,0],"i8",c,5372604);d([47,114,100,121,108,103,110,52,47,52,0],"i8",c,5372616);d([47,114,100,121,108,103,110,52,47,51,0],"i8",c,5372628);d([37,100,32,37,100,32,0],"i8",c,5372640);d([47,114,100,121,108,103,110,52,47,50,0],"i8",c,5372648);d([99,111,112,121,0],"i8",c,5372660);d([47,114,100,121,108,103,110,52,47,49,0],"i8",c,5372668);d([47,98,114,98,103,55,47,55,0],"i8",c,5372680);d([47,114,100,121,108,103,110,51,47,51,0],"i8",c,5372692);d([123,10,0],"i8",c,5372704);d([99,97,110,110,111,116,32,114,101,97,108,108,111,99,32,112,110,108,112,115,0],"i8",c,5372708);d([47,114,100,121,108,103,110,51,47,50,0],"i8",c,5372732);d([47,114,100,121,108,103,110,51,47,49,0],"i8",c,5372744);d([32,32,32,32,32,125,10,0],"i8",c,5372756);d([37,37,69,110,100,68,111,99,117,109,101,110,116,10,0],"i8",c,5372764);d([47,114,100,121,108,103,110,49,49,47,57,0],"i8",c,5372780);d([47,114,100,121,108,103,110,49,49,47,56,0],"i8",c,5372792);d([114,111,115,121,98,114,111,119,110,0],"i8",c,5372804);d([9,99,117,114,108,97,121,101,114,32,109,121,117,112,112,101,114,32,103,116,0],"i8",c,5372816);d([47,114,100,121,108,103,110,49,49,47,55,0],"i8",c,5372840);d([98,108,117,101,118,105,111,108,101,116,0],"i8",c,5372852);d([73,83,79,95,56,56,53,57,45,49,0],"i8",c,5372864);d([47,114,100,121,108,103,110,49,49,47,54,0],"i8",c,5372876);d([47,114,100,121,108,103,110,49,49,47,53,0],"i8",c,5372888);d([47,114,100,121,108,103,110,49,49,47,52,0],"i8",c,5372900);d([99,111,110,103,0],"i8",c,5372912);d([47,114,100,121,108,103,110,49,49,47,51,0],"i8",c,5372920);d([47,98,114,98,103,55,47,54,0],"i8",c,5372932);d([40,37,46,53,103,44,37,46,53,103,41,0],"i8",c,5372944);d([47,114,100,121,108,103,110,49,49,47,50,0],"i8",c,5372956);d([47,114,100,121,108,103,110,49,49,47,49,49,0],"i8",c,5372968);d([47,114,100,121,108,103,110,49,49,47,49,48,0],"i8",c,5372984);d([32,32,32,32,32,125,101,108,115,101,123,10,0],"i8",c,5373e3);d([47,114,100,121,108,103,110,49,49,47,49,0],"i8",c,5373016);d([114,97,110,107,0],"i8",c,5373028);d([47,114,100,121,108,103,110,49,48,47,57,0],"i8",c,5373036);d([112,116,0],"i8",c,5373048);d([9,99,117,114,108,97,121,101,114,32,109,121,108,111,119,101,114,32,108,116,0],"i8",c,5373052);d([47,114,100,121,108,103,110,49,48,47,56,0],"i8",c,5373076);d([99,111,110,99,46,99,0],"i8",c,5373088);d([108,49,0],"i8",c,5373096);d([103,118,117,115,101,114,115,104,97,112,101,46,99,0],"i8",c,5373100);d([32,32,32,32,32,32,32,32,100,117,112,32,100,117,112,32,102,105,110,100,102,111,110,116,32,100,117,112,32,108,101,110,103,116,104,32,100,105,99,116,32,98,101,103,105,110,0],"i8",c,5373116);d([99,108,117,98,115,0],"i8",c,5373164);d([47,114,100,121,108,103,110,49,48,47,55,0],"i8",c,5373172);d([119,105,100,116,104,0],"i8",c,5373184);d([47,114,100,121,108,103,110,49,48,47,54,0],"i8",c,5373192);d([47,114,100,121,108,103,110,49,48,47,53,0],"i8",c,5373204);d([67,111,117,108,100,32,110,111,116,32,112,97,114,115,101,32,34,95,100,114,97,119,95,34,32,97,116,116,114,105,98,117,116,101,32,105,110,32,103,114,97,112,104,32,37,115,10,0],"i8",c,5373216);d([47,114,100,121,108,103,110,49,48,47,52,0],"i8",c,5373264);d([47,98,114,98,103,55,47,53,0],"i8",c,5373276);d([47,114,100,121,108,103,110,49,48,47,51,0],"i8",c,5373288);d([47,114,100,121,108,103,110,49,48,47,50,0],"i8",c,5373300);d([47,114,100,121,108,103,110,49,48,47,49,48,0],"i8",c,5373312);d([32,32,32,32,32,32,32,32,32,32,32,105,116,101,109,46,115,116,121,108,101,46,118,105,115,105,98,105,108,105,116,121,61,39,104,105,100,100,101,110,39,59,10,0],"i8",c,5373328);d([47,114,100,121,108,103,110,49,48,47,49,0],"i8",c,5373372);d([47,114,100,121,108,98,117,57,47,57,0],"i8",c,5373384);d([9,47,109,121,108,111,119,101,114,32,101,120,99,104,32,100,101,102,0],"i8",c,5373396);d([47,114,100,121,108,98,117,57,47,56,0],"i8",c,5373416);d([108,97,116,105,110,49,0],"i8",c,5373428);d([67,111,117,108,100,32,110,111,116,32,111,112,101,110,32,34,37,115,34,32,102,111,114,32,119,114,105,116,105,110,103,32,58,32,37,115,10,0],"i8",c,5373436);d([47,114,100,121,108,98,117,57,47,55,0],"i8",c,5373476);d([47,114,100,121,108,98,117,57,47,54,0],"i8",c,5373488);d([47,114,100,121,108,98,117,57,47,53,0],"i8",c,5373500);d([99,105,114,99,0],"i8",c,5373512);d([47,114,100,121,108,98,117,57,47,52,0],"i8",c,5373520);d([47,98,114,98,103,55,47,52,0],"i8",c,5373532);d([47,114,100,121,108,98,117,57,47,51,0],"i8",c,5373544);d([47,114,100,121,108,98,117,57,47,50,0],"i8",c,5373556);d([47,114,100,121,108,98,117,57,47,49,0],"i8",c,5373568);d([32,32,32,32,32,32,32,32,32,105,116,101,109,32,61,32,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,66,121,73,100,40,86,77,76,110,111,91,120,93,41,59,10,0],"i8",c,5373580);d([47,114,100,121,108,98,117,56,47,56,0],"i8",c,5373632);d([47,114,100,121,108,98,117,56,47,55,0],"i8",c,5373644);d([112,111,119,100,101,114,98,108,117,101,0],"i8",c,5373656);d([9,47,109,121,117,112,112,101,114,32,101,120,99,104,32,100,101,102,0],"i8",c,5373668);d([47,114,100,121,108,98,117,56,47,54,0],"i8",c,5373688);d([108,97,116,105,110,45,49,0],"i8",c,5373700);d([47,114,100,121,108,98,117,56,47,53,0],"i8",c,5373708);d([47,114,100,121,108,98,117,56,47,52,0],"i8",c,5373720);d([47,114,100,121,108,98,117,56,47,51,0],"i8",c,5373732);d([99,104,105,0],"i8",c,5373744);d([47,114,100,121,108,98,117,56,47,50,0],"i8",c,5373748);d([47,98,114,98,103,55,47,51,0],"i8",c,5373760);d([47,114,100,121,108,98,117,56,47,49,0],"i8",c,5373772);d([47,114,100,121,108,98,117,55,47,55,0],"i8",c,5373784);d([47,114,100,121,108,98,117,55,47,54,0],"i8",c,5373796);d([32,32,32,32,32,32,32,102,111,114,32,40,120,32,105,110,32,86,77,76,110,111,41,123,10,0],"i8",c,5373808);d([47,114,100,121,108,98,117,55,47,53,0],"i8",c,5373836);d([47,114,100,121,108,98,117,55,47,52,0],"i8",c,5373848);d([112,108,117,109,0],"i8",c,5373860);d([47,111,110,108,97,121,101,114,115,32,123,0],"i8",c,5373868);d([47,114,100,121,108,98,117,55,47,51,0],"i8",c,5373880);d([117,116,102,45,56,0],"i8",c,5373892);d([47,114,100,121,108,98,117,55,47,50,0],"i8",c,5373900);d([47,114,100,121,108,98,117,55,47,49,0],"i8",c,5373912);d([47,114,100,121,108,98,117,54,47,54,0],"i8",c,5373924);d([99,101,110,116,0],"i8",c,5373936);d([47,114,100,121,108,98,117,54,47,53,0],"i8",c,5373944);d([47,98,114,98,103,55,47,50,0],"i8",c,5373956);d([47,114,100,121,108,98,117,54,47,52,0],"i8",c,5373968);d([47,114,100,121,108,98,117,54,47,51,0],"i8",c,5373980);d([47,114,100,121,108,98,117,54,47,50,0],"i8",c,5373992);d([32,32,32,32,32,32,32,125,10,0],"i8",c,5374004);d([47,114,100,121,108,98,117,54,47,49,0],"i8",c,5374016);d([47,114,100,121,108,98,117,53,47,53,0],"i8",c,5374028);d([112,105,110,107,0],"i8",c,5374040);d([47,111,110,108,97,121,101,114,32,123,32,99,117,114,108,97,121,101,114,32,110,101,32,123,105,110,118,105,115,125,32,105,102,32,125,32,100,101,102,0],"i8",c,5374048);d([47,114,100,121,108,98,117,53,47,52,0],"i8",c,5374088);d([47,97,99,99,101,110,116,53,47,51,0],"i8",c,5374100);d([99,104,97,114,115,101,116,0],"i8",c,5374112);d([47,114,100,121,108,98,117,53,47,51,0],"i8",c,5374120);d([47,114,100,121,108,98,117,53,47,50,0],"i8",c,5374132);d([47,114,100,121,108,98,117,53,47,49,0],"i8",c,5374144);d([99,101,100,105,108,0],"i8",c,5374156);d([47,114,100,121,108,98,117,52,47,52,0],"i8",c,5374164);d([47,98,114,98,103,55,47,49,0],"i8",c,5374176);d([47,114,100,121,108,98,117,52,47,51,0],"i8",c,5374188);d([47,114,100,121,108,98,117,52,47,50,0],"i8",c,5374200);d([47,114,100,121,108,98,117,52,47,49,0],"i8",c,5374212);d([32,32,32,32,32,32,32,32,32,125,10,0],"i8",c,5374224);d([47,114,100,121,108,98,117,51,47,51,0],"i8",c,5374236);d([47,114,100,121,108,98,117,51,47,50,0],"i8",c,5374248);d([112,101,114,117,0],"i8",c,5374260);d([78,111,32,108,111,97,100,105,109,97,103,101,32,112,108,117,103,105,110,32,102,111,114,32,34,37,115,34,10,0],"i8",c,5374268);d([9,47,103,114,97,112,104,99,111,108,111,114,32,123,110,111,112,99,111,108,111,114,125,32,100,101,102,0],"i8",c,5374300);d([112,111,108,121,103,111,110,0],"i8",c,5374328);d([47,114,100,121,108,98,117,51,47,49,0],"i8",c,5374336);d([103,105,102,58,118,114,109,108,0],"i8",c,5374348);d([102,105,108,108,0],"i8",c,5374360);d([47,114,100,121,108,98,117,49,49,47,57,0],"i8",c,5374368);d([115,116,97,114,116,32,112,111,114,116,58,32,40,37,46,53,103,44,32,37,46,53,103,41,44,32,116,97,110,103,101,110,116,32,97,110,103,108,101,58,32,37,46,53,103,44,32,37,115,10,0],"i8",c,5374380);d([47,114,100,121,108,98,117,49,49,47,56,0],"i8",c,5374432);d([47,114,100,121,108,98,117,49,49,47,55,0],"i8",c,5374444);d([99,99,101,100,105,108,0],"i8",c,5374456);d([47,114,100,121,108,98,117,49,49,47,54,0],"i8",c,5374464);d([47,98,114,98,103,54,47,54,0],"i8",c,5374476);d([47,114,100,121,108,98,117,49,49,47,53,0],"i8",c,5374488);d([47,114,100,121,108,98,117,49,49,47,52,0],"i8",c,5374500);d([47,114,100,121,108,98,117,49,49,47,51,0],"i8",c,5374512);d([32,32,32,32,32,32,32,32,32,32,32,105,116,101,109,46,115,116,121,108,101,46,118,105,115,105,98,105,108,105,116,121,61,39,118,105,115,105,98,108,101,39,59,10,0],"i8",c,5374524);d([47,114,100,121,108,98,117,49,49,47,50,0],"i8",c,5374572);d([47,114,100,121,108,98,117,49,49,47,49,49,0],"i8",c,5374584);d([115,97,109,101,116,97,105,108,0],"i8",c,5374600);d([112,101,97,99,104,112,117,102,102,0],"i8",c,5374612);d([9,47,101,100,103,101,99,111,108,111,114,32,123,110,111,112,99,111,108,111,114,125,32,100,101,102,0],"i8",c,5374624);d([112,111,115,105,116,105,111,110,46,99,0],"i8",c,5374652);d([47,114,100,121,108,98,117,49,49,47,49,48,0],"i8",c,5374664);d([101,120,112,97,110,100,0],"i8",c,5374680);d([50,46,50,56,46,48,0],"i8",c,5374688);d([47,114,100,121,108,98,117,49,49,47,49,0],"i8",c,5374696);d([47,114,100,121,108,98,117,49,48,47,57,0],"i8",c,5374708);d([47,114,100,121,108,98,117,49,48,47,56,0],"i8",c,5374720);d([99,97,112,0],"i8",c,5374732);d([47,114,100,121,108,98,117,49,48,47,55,0],"i8",c,5374736);d([98,108,97,99,107,0],"i8",c,5374748);d([47,98,114,98,103,54,47,53,0],"i8",c,5374756);d([37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,46,49,102,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,32,37,100,10,0],"i8",c,5374768);d([109,105,110,117,115,0],"i8",c,5374820);d([47,114,100,121,108,98,117,49,48,47,54,0],"i8",c,5374828);d([47,114,100,121,108,98,117,49,48,47,53,0],"i8",c,5374840);d([47,114,100,121,108,98,117,49,48,47,52,0],"i8",c,5374852);d([32,32,32,32,32,32,32,32,32,105,102,32,40,105,116,101,109,41,32,123,10,0],"i8",c,5374864);d([47,114,100,121,108,98,117,49,48,47,51,0],"i8",c,5374888);d([101,100,103,101,0],"i8",c,5374900);d([47,114,100,121,108,98,117,49,48,47,50,0],"i8",c,5374908);d([112,97,112,97,121,97,119,104,105,112,0],"i8",c,5374920);d([9,47,110,111,100,101,99,111,108,111,114,32,123,110,111,112,99,111,108,111,114,125,32,100,101,102,0],"i8",c,5374932);d([47,114,100,121,108,98,117,49,48,47,49,48,0],"i8",c,5374960);d([108,116,97,105,108,0],"i8",c,5374976);d([108,105,98,97,103,32,101,114,114,111,114,32,45,45,32,97,103,105,110,105,116,40,41,32,119,97,115,32,110,111,116,32,99,97,108,108,101,100,10,0],"i8",c,5374984);d([99,111,109,112,114,101,115,115,0],"i8",c,5375024);d([32,62,62,62,32,0],"i8",c,5375036);d([47,114,100,121,108,98,117,49,48,47,49,0],"i8",c,5375044);d([47,114,100,112,117,57,47,57,0],"i8",c,5375056);d([116,97,105,108,112,111,114,116,0],"i8",c,5375068);d([47,114,100,112,117,57,47,56,0],"i8",c,5375080);d([98,117,108,108,0],"i8",c,5375092);d([47,114,100,112,117,57,47,55,0],"i8",c,5375100);d([47,98,114,98,103,54,47,52,0],"i8",c,5375112);d([47,114,100,112,117,57,47,54,0],"i8",c,5375124);d([47,114,100,112,117,57,47,53,0],"i8",c,5375136);d([47,114,100,112,117,57,47,52,0],"i8",c,5375148);d([32,32,32,32,32,32,32,32,32,105,116,101,109,32,61,32,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,66,121,73,100,40,86,77,76,121,101,115,91,120,93,41,59,10,0],"i8",c,5375160);d([115,97,110,115,45,83,101,114,105,102,0],"i8",c,5375216);d([47,114,100,112,117,57,47,51,0],"i8",c,5375228);d([47,114,100,112,117,57,47,50,0],"i8",c,5375240);d([112,97,108,101,118,105,111,108,101,116,114,101,100,0],"i8",c,5375252);d([9,97,108,111,97,100,32,112,111,112,32,115,101,116,104,115,98,99,111,108,111,114,0],"i8",c,5375268);d([47,114,100,112,117,57,47,49,0],"i8",c,5375292);d([97,117,116,111,0],"i8",c,5375304);d([99,108,117,115,116,101,114,0],"i8",c,5375312);d([98,114,118,98,97,114,0],"i8",c,5375320);d([47,114,100,112,117,56,47,56,0],"i8",c,5375328);d([47,114,100,112,117,56,47,55,0],"i8",c,5375340);d([32,37,100,32,0],"i8",c,5375352);d([47,114,100,112,117,56,47,54,0],"i8",c,5375360);d([117,116,105,108,115,46,99,0],"i8",c,5375372);d([47,114,100,112,117,56,47,53,0],"i8",c,5375380);d([47,98,114,98,103,54,47,51,0],"i8",c,5375392);d([47,114,100,112,117,56,47,52,0],"i8",c,5375404);d([115,117,98,103,114,97,112,104,32,0],"i8",c,5375416);d([99,97,110,110,111,116,32,114,101,97,108,108,111,99,32,112,110,108,115,0],"i8",c,5375428);d([47,114,100,112,117,56,47,51,0],"i8",c,5375448);d([47,114,100,112,117,56,47,50,0],"i8",c,5375460);d([32,32,32,32,32,32,32,102,111,114,32,40,120,32,105,110,32,86,77,76,121,101,115,41,123,10,0],"i8",c,5375472);d([110,111,110,97,109,101,46,103,118,0],"i8",c,5375500);d([37,37,66,101,103,105,110,68,111,99,117,109,101,110,116,58,10,0],"i8",c,5375512);d([47,114,100,112,117,56,47,49,0],"i8",c,5375532);d([47,114,100,112,117,55,47,55,0],"i8",c,5375544);d([112,97,108,101,116,117,114,113,117,111,105,115,101,0],"i8",c,5375556);d([37,37,66,101,103,105,110,80,114,111,108,111,103,0],"i8",c,5375572);d([47,114,100,112,117,55,47,54,0],"i8",c,5375588);d([114,97,116,105,111,0],"i8",c,5375600);d([98,101,116,97,0],"i8",c,5375608);d([47,114,100,112,117,55,47,53,0],"i8",c,5375616);d([9,108,97,121,101,114,99,111,108,111,114,115,101,113,32,99,117,114,108,97,121,101,114,32,49,32,115,117,98,32,108,97,121,101,114,108,101,110,32,109,111,100,32,103,101,116,0],"i8",c,5375628);d([47,114,100,112,117,55,47,52,0],"i8",c,5375676);d([47,114,100,112,117,55,47,51,0],"i8",c,5375688);d([47,114,100,112,117,55,47,50,0],"i8",c,5375700);d([47,98,114,98,103,54,47,50,0],"i8",c,5375712);d([47,114,100,112,117,55,47,49,0],"i8",c,5375724);d([47,114,100,112,117,54,47,54,0],"i8",c,5375736);d([114,97,110,107,40,103,44,32,50,44,32,110,115,105,116,101,114,50,40,103,41,41,32,61,61,32,48,0],"i8",c,5375748);d([47,114,100,112,117,54,47,53,0],"i8",c,5375776);d([32,32,32,32,32,32,105,102,32,40,105,101,118,101,114,115,62,61,53,41,123,10,0],"i8",c,5375788);d([47,114,100,112,117,54,47,52,0],"i8",c,5375812);d([115,105,110,107,0],"i8",c,5375824);d([47,114,100,112,117,54,47,51,0],"i8",c,5375832);d([47,68,111,116,68,105,99,116,32,50,48,48,32,100,105,99,116,32,100,101,102,0],"i8",c,5375844);d([112,97,108,101,103,114,101,101,110,0],"i8",c,5375868);d([112,99,0],"i8",c,5375880);d([47,115,101,116,108,97,121,101,114,32,123,47,109,97,120,108,97,121,101,114,32,101,120,99,104,32,100,101,102,32,47,99,117,114,108,97,121,101,114,32,101,120,99,104,32,100,101,102,0],"i8",c,5375884);d([47,114,100,112,117,54,47,50,0],"i8",c,5375936);d([37,108,102,37,99,0],"i8",c,5375948);d([121,101,115,0],"i8",c,5375956);d([47,115,116,97,114,110,101,116,73,83,79,32,123,0],"i8",c,5375960);d([98,100,113,117,111,0],"i8",c,5375976);d([47,114,100,112,117,54,47,49,0],"i8",c,5375984);d([47,114,100,112,117,53,47,53,0],"i8",c,5375996);d([103,118,114,101,110,100,101,114,95,115,101,116,95,115,116,121,108,101,58,32,117,110,115,117,112,112,111,114,116,101,100,32,115,116,121,108,101,32,37,115,32,45,32,105,103,110,111,114,105,110,103,10,0],"i8",c,5376008);d([47,114,100,112,117,53,47,52,0],"i8",c,5376064);d([108,97,121,101,114,115,32,110,111,116,32,115,117,112,112,111,114,116,101,100,32,105,110,32,37,115,32,111,117,116,112,117,116,10,0],"i8",c,5376076);d([47,114,100,112,117,53,47,51,0],"i8",c,5376112);d([47,98,114,98,103,54,47,49,0],"i8",c,5376124);d([47,114,100,112,117,53,47,50,0],"i8",c,5376136);d([47,114,100,112,117,53,47,49,0],"i8",c,5376148);d([47,114,100,112,117,52,47,52,0],"i8",c,5376160);d([32,32,32,32,32,32,125,10,0],"i8",c,5376172);d([47,114,100,112,117,52,47,51,0],"i8",c,5376184);d([47,114,100,112,117,52,47,50,0],"i8",c,5376196);d([112,97,108,101,103,111,108,100,101,110,114,111,100,0],"i8",c,5376208);d([47,108,97,121,101,114,108,101,110,32,108,97,121,101,114,99,111,108,111,114,115,101,113,32,108,101,110,103,116,104,32,100,101,102,0],"i8",c,5376224);d([47,114,100,112,117,52,47,49,0],"i8",c,5376260);d([37,108,102,44,37,108,102,37,99,0],"i8",c,5376272);d([97,117,109,108,0],"i8",c,5376284);d([47,114,100,112,117,51,47,51,0],"i8",c,5376292);d([47,114,100,112,117,51,47,50,0],"i8",c,5376304);d([47,114,100,112,117,51,47,49,0],"i8",c,5376316);d([73,109,97,103,101,115,32,117,110,115,117,112,112,111,114,116,101,100,32,105,110,32,34,98,97,99,107,103,114,111,117,110,100,34,32,97,116,116,114,105,98,117,116,101,10,0],"i8",c,5376328);d([47,114,100,103,121,57,47,57,0],"i8",c,5376376);d([47,98,114,98,103,53,47,53,0],"i8",c,5376388);d([47,114,100,103,121,57,47,56,0],"i8",c,5376400);d([47,114,100,103,121,57,47,55,0],"i8",c,5376412);d([47,114,100,103,121,57,47,54,0],"i8",c,5376424);d([32,32,32,32,32,32,32,32,32,105,101,118,101,114,115,61,32,112,97,114,115,101,73,110,116,32,40,117,97,46,115,117,98,115,116,114,105,110,103,32,40,109,115,105,101,43,53,44,32,117,97,46,105,110,100,101,120,79,102,32,40,39,46,39,44,32,109,115,105,101,32,41,41,41,10,0],"i8",c,5376436);d([47,114,100,103,121,57,47,53,0],"i8",c,5376512);d([47,114,100,103,121,57,47,52,0],"i8",c,5376524);d([111,114,99,104,105,100,0],"i8",c,5376536);d([100,101,102,0],"i8",c,5376544);d([47,114,100,103,121,57,47,51,0],"i8",c,5376548);d([108,97,98,101,108,106,117,115,116,0],"i8",c,5376560);d([97,116,105,108,100,101,0],"i8",c,5376572);d([47,114,100,103,121,57,47,50,0],"i8",c,5376580);d([109,99,108,105,109,105,116,0],"i8",c,5376592);d([47,114,100,103,121,57,47,49,0],"i8",c,5376600);d([47,114,100,103,121,56,47,56,0],"i8",c,5376612);d([47,114,100,103,121,56,47,55,0],"i8",c,5376624);d([47,98,114,98,103,53,47,52,0],"i8",c,5376636);d([47,114,100,103,121,56,47,54,0],"i8",c,5376648);d([47,114,100,103,121,56,47,53,0],"i8",c,5376660);d([47,114,100,103,121,56,47,52,0],"i8",c,5376672);d([32,32,32,32,32,32,105,102,32,40,32,109,115,105,101,32,62,32,48,32,41,123,32,32,32,32,32,32,47,47,32,73,102,32,73,110,116,101,114,110,101,116,32,69,120,112,108,111,114,101,114,44,32,114,101,116,117,114,110,32,118,101,114,115,105,111,110,32,110,117,109,98,101,114,10,0],"i8",c,5376684);d([32,37,100,44,37,100,0],"i8",c,5376760);d([47,114,100,103,121,56,47,51,0],"i8",c,5376768);d([47,114,100,103,121,56,47,50,0],"i8",c,5376780);d([111,114,97,110,103,101,114,101,100,0],"i8",c,5376792);d([9,93,0],"i8",c,5376804);d([47,114,100,103,121,56,47,49,0],"i8",c,5376808);d([108,97,98,101,108,108,111,99,0],"i8",c,5376820);d([97,115,121,109,112,0],"i8",c,5376832);d([47,114,100,103,121,55,47,55,0],"i8",c,5376840);d([47,114,100,103,121,55,47,54,0],"i8",c,5376852);d([47,114,100,103,121,55,47,53,0],"i8",c,5376864);d([47,114,100,103,121,55,47,52,0],"i8",c,5376876);d([47,98,114,98,103,53,47,51,0],"i8",c,5376888);d([47,114,100,103,121,55,47,51,0],"i8",c,5376900);d([47,114,100,103,121,55,47,50,0],"i8",c,5376912);d([47,114,100,103,121,55,47,49,0],"i8",c,5376924);d([32,32,32,32,32,32,118,97,114,32,86,77,76,110,111,61,110,101,119,32,65,114,114,97,121,40,39,95,110,111,116,86,77,76,49,95,39,44,39,95,110,111,116,86,77,76,50,95,39,41,59,10,0],"i8",c,5376936);d([47,114,100,103,121,54,47,54,0],"i8",c,5376992);d([47,114,100,103,121,54,47,53,0],"i8",c,5377004);d([111,114,97,110,103,101,0],"i8",c,5377016);d([9,9,91,46,56,32,46,56,32,46,56,93,0],"i8",c,5377024);d([47,114,100,103,121,54,47,52,0],"i8",c,5377040);d([47,97,99,99,101,110,116,53,47,50,0],"i8",c,5377052);d([97,114,105,110,103,0],"i8",c,5377064);d([47,114,100,103,121,54,47,51,0],"i8",c,5377072);d([47,114,100,103,121,54,47,50,0],"i8",c,5377084);d([114,97,110,107,100,105,114,0],"i8",c,5377096);d([47,114,100,103,121,54,47,49,0],"i8",c,5377104);d([47,114,100,103,121,53,47,53,0],"i8",c,5377116);d([47,98,114,98,103,53,47,50,0],"i8",c,5377128);d([47,114,100,103,121,53,47,52,0],"i8",c,5377140);d([47,114,100,103,121,53,47,51,0],"i8",c,5377152);d([47,114,100,103,121,53,47,50,0],"i8",c,5377164);d([32,32,32,32,32,32,118,97,114,32,86,77,76,121,101,115,61,110,101,119,32,65,114,114,97,121,40,39,95,86,77,76,49,95,39,44,39,95,86,77,76,50,95,39,41,59,10,0],"i8",c,5377176);d([47,114,100,103,121,53,47,49,0],"i8",c,5377224);d([47,114,100,103,121,52,47,52,0],"i8",c,5377236);d([111,108,105,118,101,100,114,97,98,0],"i8",c,5377248);d([9,9,91,46,54,32,46,56,32,46,56,93,0],"i8",c,5377260);d([98,111,120,0],"i8",c,5377276);d([47,114,100,103,121,52,47,51,0],"i8",c,5377280);d([112,110,103,58,118,114,109,108,0],"i8",c,5377292);d([84,105,109,101,115,45,82,111,109,97,110,0],"i8",c,5377304);d([97,110,103,0],"i8",c,5377316);d([47,114,100,103,121,52,47,50,0],"i8",c,5377320);d([37,100,32,40,37,46,53,103,44,32,37,46,53,103,41,44,32,40,37,46,53,103,44,32,37,46,53,103,41,10,0],"i8",c,5377332);d([47,114,100,103,121,52,47,49,0],"i8",c,5377364);d([47,114,100,103,121,51,47,51,0],"i8",c,5377376);d([47,114,100,103,121,51,47,50,0],"i8",c,5377388);d([47,98,114,98,103,53,47,49,0],"i8",c,5377400);d([47,114,100,103,121,51,47,49,0],"i8",c,5377412);d([47,114,100,103,121,49,49,47,57,0],"i8",c,5377424);d([47,114,100,103,121,49,49,47,56,0],"i8",c,5377436);d([32,32,32,32,32,32,118,97,114,32,105,116,101,109,59,10,0],"i8",c,5377448);d([47,114,100,103,121,49,49,47,55,0],"i8",c,5377468);d([47,114,100,103,121,49,49,47,54,0],"i8",c,5377480);d([9,9,91,46,52,32,46,56,32,46,56,93,0],"i8",c,5377492);d([47,114,100,103,121,49,49,47,53,0],"i8",c,5377508);d([97,110,100,0],"i8",c,5377520);d([47,114,100,103,121,49,49,47,52,0],"i8",c,5377524);d([47,114,100,103,121,49,49,47,51,0],"i8",c,5377536);d([47,114,100,103,121,49,49,47,50,0],"i8",c,5377548);d([47,114,100,103,121,49,49,47,49,49,0],"i8",c,5377560);d([97,113,117,97,0],"i8",c,5377572);d([47,98,114,98,103,52,47,52,0],"i8",c,5377580);d([47,114,100,103,121,49,49,47,49,48,0],"i8",c,5377592);d([35,32,37,115,10,0],"i8",c,5377604);d([75,80,95,65,100,100,0],"i8",c,5377612);d([47,114,100,103,121,49,49,47,49,0],"i8",c,5377620);d([47,114,100,103,121,49,48,47,57,0],"i8",c,5377632);d([32,32,32,32,32,32,118,97,114,32,105,101,118,101,114,115,59,10,0],"i8",c,5377644);d([47,114,100,103,121,49,48,47,56,0],"i8",c,5377664);d([47,114,100,103,121,49,48,47,55,0],"i8",c,5377676);d([111,108,100,108,97,99,101,0],"i8",c,5377688);d([9,9,91,46,50,32,46,56,32,46,56,93,0],"i8",c,5377696);d([47,114,100,103,121,49,48,47,54,0],"i8",c,5377712);d([97,109,112,0],"i8",c,5377724);d([47,114,100,103,121,49,48,47,53,0],"i8",c,5377728);d([99,111,110,116,101,120,116,58,32,0],"i8",c,5377740);d([47,114,100,103,121,49,48,47,52,0],"i8",c,5377752);d([47,114,100,103,121,49,48,47,51,0],"i8",c,5377764);d([104,101,97,100,112,111,114,116,0],"i8",c,5377776);d([47,114,100,103,121,49,48,47,50,0],"i8",c,5377788);d([47,98,114,98,103,52,47,51,0],"i8",c,5377800);d([47,114,100,103,121,49,48,47,49,48,0],"i8",c,5377812);d([47,114,100,103,121,49,48,47,49,0],"i8",c,5377824);d([47,114,100,98,117,57,47,57,0],"i8",c,5377836);d([32,32,32,32,32,32,118,97,114,32,109,115,105,101,32,61,32,117,97,46,105,110,100,101,120,79,102,32,40,32,39,77,83,73,69,32,39,32,41,10,0],"i8",c,5377848);d([98,111,111,107,0],"i8",c,5377892);d([47,114,100,98,117,57,47,56,0],"i8",c,5377900);d([47,114,100,98,117,57,47,55,0],"i8",c,5377912);d([9,9,91,48,32,48,32,48,93,0],"i8",c,5377924);d([47,114,100,98,117,57,47,54,0],"i8",c,5377936);d([73,83,79,45,56,56,53,57,45,49,0],"i8",c,5377948);d([97,108,112,104,97,0],"i8",c,5377960);d([47,114,100,98,117,57,47,53,0],"i8",c,5377968);d([47,114,100,98,117,57,47,52,0],"i8",c,5377980);d([120,100,111,116,58,120,100,111,116,0],"i8",c,5377992);d([47,114,100,98,117,57,47,51,0],"i8",c,5378004);d([101,109,105,116,46,99,0],"i8",c,5378016);d([115,101,103,109,101,110,116,32,91,37,115,44,37,115,93,32,100,111,101,115,32,110,111,116,32,105,110,116,101,114,115,101,99,116,32,98,111,120,32,108,108,61,37,115,44,117,114,61,37,115,10,0],"i8",c,5378024);d([47,114,100,98,117,57,47,50,0],"i8",c,5378076);d([47,98,114,98,103,52,47,50,0],"i8",c,5378088);d([47,114,100,98,117,57,47,49,0],"i8",c,5378100);d([99,97,110,110,111,116,32,109,97,108,108,111,99,32,112,110,108,112,115,0],"i8",c,5378112);d([47,114,100,98,117,56,47,56,0],"i8",c,5378132);d([114,101,99,116,115,0],"i8",c,5378144);d([47,114,100,98,117,56,47,55,0],"i8",c,5378152);d([32,32,32,32,32,32,118,97,114,32,117,97,32,61,32,119,105,110,100,111,119,46,110,97,118,105,103,97,116,111,114,46,117,115,101,114,65,103,101,110,116,10,0],"i8",c,5378164);d([46,37,100,0],"i8",c,5378208);d([47,117,115,101,114,95,115,104,97,112,101,95,37,100,32,123,10,0],"i8",c,5378212);d([47,114,100,98,117,56,47,54,0],"i8",c,5378232);d([47,114,100,98,117,56,47,53,0],"i8",c,5378244);d([9,91,9,37,32,108,97,121,101,114,32,99,111,108,111,114,32,115,101,113,117,101,110,99,101,32,45,32,100,97,114,107,101,115,116,32,116,111,32,108,105,103,104,116,101,115,116,0],"i8",c,5378256);d([110,97,118,97,106,111,119,104,105,116,101,0],"i8",c,5378304);d([47,114,100,98,117,56,47,52,0],"i8",c,5378316);d([98,108,97,110,99,104,101,100,97,108,109,111,110,100,0],"i8",c,5378328);d([97,108,101,102,115,121,109,0],"i8",c,5378344);d([47,114,100,98,117,56,47,51,0],"i8",c,5378352);d([47,114,100,98,117,56,47,50,0],"i8",c,5378364);d([47,114,100,98,117,56,47,49,0],"i8",c,5378376);d([97,108,108,0],"i8",c,5378388);d([47,114,100,98,117,55,47,55,0],"i8",c,5378392);d([47,98,114,98,103,52,47,49,0],"i8",c,5378404);d([47,114,100,98,117,55,47,54,0],"i8",c,5378416);d([47,114,100,98,117,55,47,53,0],"i8",c,5378428);d([47,114,100,98,117,55,47,52,0],"i8",c,5378440);d([32,32,32,123,10,0],"i8",c,5378452);d([47,114,100,98,117,55,47,51,0],"i8",c,5378460);d([109,97,120,0],"i8",c,5378472);d([47,114,100,98,117,55,47,50,0],"i8",c,5378476);d([47,108,97,121,101,114,99,111,108,111,114,115,101,113,0],"i8",c,5378488);d([109,111,99,99,97,115,105,110,0],"i8",c,5378504);d([112,120,0],"i8",c,5378516);d([47,114,100,98,117,55,47,49,0],"i8",c,5378520);d([105,100,0],"i8",c,5378532);d([37,32,83,101,116,32,117,112,32,73,83,79,32,76,97,116,105,110,32,49,32,99,104,97,114,97,99,116,101,114,32,101,110,99,111,100,105,110,103,0],"i8",c,5378536);d([97,103,114,97,118,101,0],"i8",c,5378576);d([47,114,100,98,117,54,47,54,0],"i8",c,5378584);d([47,114,100,98,117,54,47,53,0],"i8",c,5378596);d([117,110,102,105,108,108,101,100,0],"i8",c,5378608);d([47,114,100,98,117,54,47,52,0],"i8",c,5378620);d([104,101,97,100,116,111,111,108,116,105,112,0],"i8",c,5378632);d([47,114,100,98,117,54,47,51,0],"i8",c,5378644);d([47,98,114,98,103,51,47,51,0],"i8",c,5378656);d([47,114,100,98,117,54,47,50,0],"i8",c,5378668);d([47,114,100,98,117,54,47,49,0],"i8",c,5378680);d([47,114,100,98,117,53,47,53,0],"i8",c,5378692);d([32,32,32,102,117,110,99,116,105,111,110,32,98,114,111,119,115,101,114,99,104,101,99,107,40,41,10,0],"i8",c,5378704);d([47,114,100,98,117,53,47,52,0],"i8",c,5378732);d([47,114,100,98,117,53,47,51,0],"i8",c,5378744);d([47,115,104,111,119,112,97,103,101,32,123,32,125,32,100,101,102,0],"i8",c,5378756);d([109,105,115,116,121,114,111,115,101,0],"i8",c,5378776);d([47,114,100,98,117,53,47,50,0],"i8",c,5378788);d([104,101,97,100,99,108,105,112,0],"i8",c,5378800);d([97,101,108,105,103,0],"i8",c,5378812);d([47,114,100,98,117,53,47,49,0],"i8",c,5378820);d([47,114,100,98,117,52,47,52,0],"i8",c,5378832);d([47,114,100,98,117,52,47,51,0],"i8",c,5378844);d([116,97,105,108,116,111,111,108,116,105,112,0],"i8",c,5378856);d([109,112,116,121,0],"i8",c,5378868);d(468,"i8",c,5378876);d([118,109,108,95,116,101,120,116,112,97,114,97,0],"i8",c,5379344);d([118,109,108,95,112,114,105,110,116,95,99,111,108,111,114,0],"i8",c,5379360);d([116,114,97,110,115,112,111,115,101,95,115,116,101,112,0],"i8",c,5379376);d([116,107,103,101,110,95,112,114,105,110,116,95,116,97,103,115,0],"i8",c,5379392);d([116,107,103,101,110,95,112,114,105,110,116,95,99,111,108,111,114,0],"i8",c,5379412);d([115,118,103,95,116,101,120,116,112,97,114,97,0],"i8",c,5379432);d([115,118,103,95,112,114,105,110,116,95,99,111,108,111,114,0],"i8",c,5379448);d([115,101,116,98,111,117,110,100,115,0],"i8",c,5379464);d([115,97,102,101,95,100,101,108,101,116,101,95,102,97,115,116,95,101,100,103,101,0],"i8",c,5379476);d([114,111,117,110,100,95,99,111,114,110,101,114,115,0],"i8",c,5379500);d([112,111,115,116,111,114,100,101,114,0],"i8",c,5379516);d([112,111,112,95,111,98,106,95,115,116,97,116,101,0],"i8",c,5379528);d([111,118,101,114,108,97,112,95,98,101,122,105,101,114,0],"i8",c,5379544);d([109,105,110,109,97,120,95,101,100,103,101,115,0],"i8",c,5379560);d([109,101,114,103,101,118,105,114,116,117,97,108,0],"i8",c,5379576);d([109,101,114,103,101,95,111,110,101,119,97,121,0],"i8",c,5379592);d([109,101,114,103,101,95,99,104,97,105,110,0],"i8",c,5379608);d([109,97,112,95,112,97,116,104,0],"i8",c,5379620);d([109,97,112,95,111,117,116,112,117,116,95,115,104,97,112,101,0],"i8",c,5379632);d([109,97,112,78,0],"i8",c,5379652);d([109,97,107,101,95,108,97,98,101,108,0],"i8",c,5379660);d([109,97,107,101,95,99,104,97,105,110,0],"i8",c,5379672);d([109,97,107,101,83,101,108,102,69,100,103,101,0],"i8",c,5379684);d([109,97,107,101,67,111,109,112,111,117,110,100,69,100,103,101,0],"i8",c,5379700);d([105,110,116,101,114,99,108,101,120,112,0],"i8",c,5379720);d([105,110,115,116,97,108,108,95,105,110,95,114,97,110,107,0],"i8",c,5379732);d([105,110,105,116,95,115,112,108,105,110,101,115,95,98,98,0],"i8",c,5379748);d([103,118,117,115,101,114,115,104,97,112,101,95,102,105,108,101,95,97,99,99,101,115,115,0],"i8",c,5379764);d([102,108,97,116,95,115,101,97,114,99,104,0],"i8",c,5379788);d([102,105,103,95,114,101,115,111,108,118,101,95,99,111,108,111,114,0],"i8",c,5379800);d([102,105,103,95,98,101,122,105,101,114,0],"i8",c,5379820);d([102,97,115,116,95,110,111,100,101,97,112,112,0],"i8",c,5379832);d([102,97,115,116,95,110,111,100,101,0],"i8",c,5379848);d([101,110,100,112,97,116,104,0],"i8",c,5379860);d([101,109,105,116,95,101,100,103,101,95,108,97,98,101,108,0],"i8",c,5379868);d([100,111,116,95,112,111,115,105,116,105,111,110,0],"i8",c,5379884);d([100,101,108,101,116,101,95,102,108,97,116,95,101,100,103,101,0],"i8",c,5379900);d([100,101,108,101,116,101,95,102,97,115,116,95,110,111,100,101,0],"i8",c,5379920);d([100,101,108,101,116,101,95,102,97,115,116,95,101,100,103,101,0],"i8",c,5379940);d([99,111,114,101,95,108,111,97,100,105,109,97,103,101,95,118,114,109,108,0],"i8",c,5379960);d([99,111,114,101,95,108,111,97,100,105,109,97,103,101,95,115,118,103,0],"i8",c,5379980);d([99,111,114,101,95,108,111,97,100,105,109,97,103,101,95,112,115,108,105,98,0],"i8",c,538e4);d([99,111,114,101,95,108,111,97,100,105,109,97,103,101,95,112,115,0],"i8",c,5380024);d([99,111,114,101,95,108,111,97,100,105,109,97,103,101,95,102,105,103,0],"i8",c,5380044);d([99,111,110,110,101,99,116,71,114,97,112,104,0],"i8",c,5380064);d([99,108,117,115,116,101,114,95,108,101,97,100,101,114,0],"i8",c,5380080);d([98,111,120,73,110,116,101,114,115,101,99,116,102,0],"i8",c,5380096);d([98,101,122,105,101,114,95,98,98,0],"i8",c,5380112);d([98,101,103,105,110,112,97,116,104,0],"i8",c,5380124);d([98,97,108,97,110,99,101,0],"i8",c,5380136);d([97,98,111,109,105,110,97,116,105,111,110,0],"i8",c,5380144);d([95,100,111,116,95,115,112,108,105,110,101,115,0],"i8",c,5380156);d([85,70,95,115,101,116,110,97,109,101,0],"i8",c,5380172);d([330,0,0,0,4,0,0,0],["*",0,0,0,"i32",0,0,0],c,5380184);d([4,0,0,0,64,0,0,0],["*",0,0,0,"i32",0,0,0],c,5380192);d([330,0,0,0,4,0,0,0],["*",0,0,0,"i32",0,0,0],c,5380200);d(4,"i8",c,5380208);d([115,0,21,0,101,0,8,0,103,0,12,0,110,0,17,0,100,0,1,0,105,0,2,0,103,0,3,0,114,0,4,0,97,0,5,0,112,0,6,0,104,0,7,0,100,0,9,0,103,0,10,0,101,0,11,0,114,0,13,0,97,0,14,0,112,0,15,0,104,0,16,0,111,0,18,0,100,0,19,0,101,0,20,0,116,0,22,0,117,0,27,0,114,0,23,0,105,0,24,0,99,0,25,0,116,0,26,0,98,0,28,0,103,0,29,0,114,0,30,0,97,0,31,0,112,0,32,0,104,0,33,0],"i8",c,5380212);d([255,255,0,0,88,32,4,0,255,255,5,0,0,1,0,0,255,255,6,0,64,0,0,0,255,255,7,0,0,0,2,0,255,255,8,0,1,0,0,0,255,255,9,0,0,128,0,0,255,255,10,0,128,0,0,0,3,1,11,0,0,0,0,0,255,255,11,0,8,0,0,0,255,255,12,0,64,0,0,0,255,255,13,0,16,0,0,0,6,1,14,0,0,0,0,0,255,255,14,0,0,0,2,0,255,255,15,0,1,0,0,0,255,255,16,0,0,128,0,0,255,255,17,0,128,0,0,0,2,1,18,0,0,0,0,0,255,255,18,0,0,64,0,0,255,255,19,0,8,0,0,0,255,255,20,0,16,0,0,0,5,1,21,0,0,0,0,0,255,255,21,0,0,0,24,0,255,255,23,0,0,0,2,0,255,255,24,0,0,1,0,0,255,255,25,0,4,0,0,0,255,255,26,0,0,0,8,0,4,1,27,0,0,0,0,0,255,255,27,0,2,0,0,0,255,255,28,0,64,0,0,0,255,255,29,0,0,0,2,0,255,255,30,0,1,0,0,0,255,255,31,0,0,128,0,0,255,255,32,0,128,0,0,0,10,1,33,0,0,0,0,0],"i8",c,5380344);d(4,"i8",c,5380616);d(4,"i8",c,5380620);d(4,"i8",c,5380624);d(4,"i8",c,5380628);d(4,"i8",c,5380632);d(4,"i8",c,5380636);d(4,"i8",c,5380640);d(4,"i8",c,5380644);d(4,"i8",c,5380648);d(4,"i8",c,5380652);d(4,"i8",c,5380656);d(4,"i8",c,5380660);d([0,0,0,0,132,23,80,0,196,29,80,0,0,0,0,0,0,0,0,0,132,23,80,0,84,26,80,0,0,0,0,0,0,0,0,0,132,23,80,0,100,28,80,0,0,0,0,0,0,0,0,0,132,23,80,0,100,28,80,0,0,0,0,0,0,0,0,0,132,23,80,0,108,29,80,0,0,0,0,0,0,0,0,0,188,23,80,0,108,29,80,0,0,0,0,0,0,0,0,0,132,23,80,0,144,28,80,0,0,0,0,0,0,0,0,0,132,23,80,0,120,25,80,0,0,0,0,0,0,0,0,0,132,23,80,0,128,26,80,0,0,0,0,0,0,0,0,0,132,23,80,0,128,26,80,0,0,0,0,0,0,0,0,0,132,23,80,0,20,29,80,0,0,0,0,0,0,0,0,0,132,23,80,0,164,25,80,0,0,0,0,0,0,0,0,0,132,23,80,0,216,26,80,0,0,0,0,0,0,0,0,0,132,23,80,0,224,27,80,0,0,0,0,0,0,0,0,0,132,23,80,0,172,26,80,0,0,0,0,0,0,0,0,0,132,23,80,0,12,28,80,0,0,0,0,0,0,0,0,0,132,23,80,0,40,26,80,0,0,0,0,0,0,0,0,0,132,23,80,0,4,27,80,0,0,0,0,0,0,0,0,0,132,23,80,0,48,27,80,0,0,0,0,0,0,0,0,0,132,23,80,0,208,25,80,0,0,0,0,0,0,0,0,0,132,23,80,0,56,28,80,0,0,0,0,0,0,0,0,0,132,23,80,0,152,29,80,0,0,0,0,0,0,0,0,0,132,23,80,0,64,29,80,0,0,0,0,0,0,0,0,0,132,23,80,0,196,29,80,0,0,0,0,0,0,0,0,0,132,23,80,0,196,29,80,0,0,0,0,0,0,0,0,0,132,23,80,0,252,25,80,0,0,0,0,0,0,0,0,0,132,23,80,0,232,28,80,0,0,0,0,0,0,0,0,0,132,23,80,0,188,28,80,0,0,0,0,0,0,0,0,0,132,23,80,0,76,25,80,0,0,0,0,0,0,0,0,0,132,23,80,0,92,27,80,0,0,0,0,0,0,0,0,0,132,23,80,0,136,27,80,0,0,0,0,0,0,0,0,0,132,23,80,0,180,27,80,0,0,0,0,0,0,0,0,0,132,23,80,0,28,30,80,0,0,0,0,0,0,0,0,0,132,23,80,0,240,29,80,0,0,0,0,0,0,0,0,0,132,23,80,0,72,30,80,0,0,0,0,0,0,0,0,0,168,14,80,0,0,0,0,0,0,0,0,0,0,0,0,0,168,14,80,0,0,0,0,0,0,0,0,0,0,0,0,0,64,48,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5380664);d(4,"i8",c,5381288);d(4,"i8",c,5381292);d(4,"i8",c,5381296);d(4,"i8",c,5381300);d([12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5381304);d(4,"i8",c,5381340);d(4,"i8",c,5381344);d(4,"i8",c,5381348);d(16,"i8",c,5381352);d(4,"i8",c,5381368);d(4,"i8",c,5381372);d(4,"i8",c,5381376);d(4,"i8",c,5381380);d(4,"i8",c,5381384);d(4,"i8",c,5381388);d(4,"i8",c,5381392);d(4,"i8",c,5381396);d(4,"i8",c,5381400);d(4,"i8",c,5381404);d(4,"i8",c,5381408);d(4,"i8",c,5381412);d(4,"i8",c,5381416);d(4,"i8",c,5381420);d(4,"i8",c,5381424);d(4,"i8",c,5381428);d(4,"i8",c,5381432);d(4,"i8",c,5381436);d(4,"i8",c,5381440);d(4,"i8",c,5381444);d(4,"i8",c,5381448);d(4,"i8",c,5381452);d(4,"i8",c,5381456);d(4,"i8",c,5381460);d(4,"i8",c,5381464);d(4,"i8",c,5381468);d(4,"i8",c,5381472);d(4,"i8",c,5381476);d(4,"i8",c,5381480);d(4,"i8",c,5381484);d(4,"i8",c,5381488);d(4,"i8",c,5381492);d(4,"i8",c,5381496);d(4,"i8",c,5381500);d(4,"i8",c,5381504);d(4,"i8",c,5381508);d(4,"i8",c,5381512);d(4,"i8",c,5381516);d(4,"i8",c,5381520);d(12,"i8",c,5381524);d(4,"i8",c,5381536);d(4,"i8",c,5381540);d(4,"i8",c,5381544);d(4,"i8",c,5381548);d(4,"i8",c,5381552);d(4,"i8",c,5381556);d(4,"i8",c,5381560);d([8,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,232,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],["i32",0,0,0,"i32",0,0,0,"i32",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0,"*",0,0,0],c,5381564);d([8,0,0,0,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5381600);d(4,"i8",c,5381636);d(4,"i8",c,5381640);d(4,"i8",c,5381644);d(4,"i8",c,5381648);d(256,"i8",c,5381652);d(4,"i8",c,5381908);d(4,"i8",c,5381912);d(4,"i8",c,5381916);d(4,"i8",c,5381920);d(4,"i8",c,5381924);d(4,"i8",c,5381928);d(4,"i8",c,5381932);d(4,"i8",c,5381936);d(4,"i8",c,5381940);d(4,"i8",c,5381944);d(4,"i8",c,5381948);d(4,"i8",c,5381952);d(4,"i8",c,5381956);d(4,"i8",c,5381960);d(4,"i8",c,5381964);d(4,"i8",c,5381968);d(4,"i8",c,5381972);d(4,"i8",c,5381976);d(4,"i8",c,5381980);d(4,"i8",c,5381984);d(4,"i8",c,5381988);d(4,"i8",c,5381992);d(4,"i8",c,5381996);d(4,"i8",c,5382e3);d(4,"i8",c,5382004);d(4,"i8",c,5382008);d(4,"i8",c,5382012);d(4,"i8",c,5382016);d(4,"i8",c,5382020);d(4,"i8",c,5382024);d(4,"i8",c,5382028);d(4,"i8",c,5382032);d(4,"i8",c,5382036);d(4,"i8",c,5382040);d(4,"i8",c,5382044);d(4,"i8",c,5382048);d(4,"i8",c,5382052);d(4,"i8",c,5382056);d(4,"i8",c,5382060);d(4,"i8",c,5382064);d(4,"i8",c,5382068);d(4,"i8",c,5382072);d(4,"i8",c,5382076);d(4,"i8",c,5382080);d(4,"i8",c,5382084);d(4,"i8",c,5382088);d(4,"i8",c,5382092);d(4,"i8",c,5382096);d(4,"i8",c,5382100);d(8,"i8",c,5382104);d(4,"i8",c,5382112);d(4,"i8",c,5382116);d(4,"i8",c,5382120);d([1,0,0,0,2,0,0,0,4,0,0,0,8,0,0,0,16,0,0,0,32,0,0,0,64,0,0,0,128,0,0,0,0,1,0,0,0,2,0,0,0,4,0,0,0,8,0,0,0,16,0,0,0,32,0,0,0,64,0,0,0,128,0,0,0,0,1,0,0,0,2,0,0,0,4,0,0,0,8,0,0,0,16,0,0,0,32,0,0,0,64,0,0,0,128,0,0,0,0,1,0,0,0,2],"i8",c,5382124);d([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,191,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0],"i8",c,5382228);d(4,"i8",c,5382268);d(4,"i8",c,5382272);d([1,0,0,0,1,0,0,0,0,0,0,0,222,0,0,0,2,0,0,0,1,0,0,0,0,0,0,0,36,0,0,0,3,0,0,0,.5,0,0,0,0,0,0,0,140,0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,12,0,0,0,5,0,0,0,1.2,0,0,0,0,0,0,0,80,0,0,0,6,0,0,0,.8,0,0,0,0,0,0,0,44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],["i32",0,0,0,"double",0,0,0,0,0,0,0,"*",0,0,0,"i32",0,0,0,"double",0,0,0,0,0,0,0,"*",0,0,0,"i32",0,0,0,"double",0,0,0,0,0,0,0,"*",0,0,0,"i32",0,0,0,"double",0,0,0,0,0,0,0,"*",0,0,0,"i32",0,0,0,"double",0,0,0,0,0,0,0,"*",0,0,0,"i32",0,0,0,"double",0,0,0,0,0,0,0,"*",0,0,0,"i32",0,0,0,"double",0,0,0,0,0,0,0,"*",0,0,0],c,5382276);d([0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5382388);d([0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5382404);d([0,0,0,0,8,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5382500);d([0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"i8",c,5382548);d(4,"i8",c,5382608);d(4,"i8",c,5382612);d(4,"i8",c,5382616);d(4,"i8",c,5382620);d(4,"i8",c,5382624);d(4,"i8",c,5382628);d(4,"i8",c,5382632);d(4,"i8",c,5382636);d(4,"i8",c,5382640);d(4,"i8",c,5382644);d(4,"i8",c,5382648);d(4,"i8",c,5382652);d(4,"i8",c,5382656);d(4,"i8",c,5382660);d(4,"i8",c,5382664);a[1310755]=5243068;a[1310756]=5243084;a[1310757]=5243100;a[1310758]=5243116;a[1310759]=5243132;a[1310760]=5243148;a[1310761]=5243164;a[1310762]=5243180;a[1310763]=5243084;a[1310764]=5243084;a[1310765]=5243148;a[1310766]=5243148;a[1310799]=5377572;a[1310800]=5374748;a[1310801]=5372240;a[1310802]=5369420;a[1310803]=5367180;a[1310804]=5364732;a[1310805]=5362252;a[1310806]=5360240;a[1310807]=5358208;a[1310808]=5356568;a[1310809]=5355e3;a[1310810]=5353516;a[1310811]=5351708;a[1310812]=5350168;a[1310813]=5348884;a[1310814]=5348088;a[1311409]=5352344;a[1311410]=5345416;a[1311411]=5377572;a[1311412]=5338676;a[1311413]=5335880;a[1311414]=5333016;a[1311415]=5330020;a[1311416]=5374748;a[1311417]=5378328;a[1311418]=5372240;a[1311419]=5372852;a[1311420]=5370284;a[1311421]=5367852;a[1311422]=5365456;a[1311423]=5362836;a[1311424]=5360780;a[1311425]=5358704;a[1311426]=5357072;a[1311427]=5355444;a[1311428]=5353880;a[1311429]=5352172;a[1311430]=5350580;a[1311431]=5349240;a[1311432]=5348204;a[1311433]=5347788;a[1311434]=5347296;a[1311435]=5346804;a[1311436]=5346396;a[1311437]=5346040;a[1311438]=5345768;a[1311439]=5345364;a[1311440]=5344968;a[1311441]=5344624;a[1311442]=5344256;a[1311443]=5343928;a[1311444]=5343600;a[1311445]=5343244;a[1311446]=5342820;a[1311447]=5342552;a[1311448]=5342220;a[1311449]=5341860;a[1311450]=5341508;a[1311451]=5341164;a[1311452]=5340808;a[1311453]=5340508;a[1311454]=5340228;a[1311455]=5339920;a[1311456]=5339652;a[1311457]=5369420;a[1311458]=5338940;a[1311459]=5338656;a[1311460]=5338340;a[1311461]=5338084;a[1311462]=5367180;a[1311463]=5364732;a[1311464]=5337272;a[1311465]=5337040;a[1311466]=5336768;a[1311467]=5336524;a[1311468]=5336180;a[1311469]=5335864;a[1311470]=5335520;a[1311471]=5335276;a[1311472]=5334980;a[1311473]=5334720;a[1311474]=5334464;a[1311475]=5334144;a[1311476]=5333904;a[1311477]=5333660;a[1311478]=5333248;a[1311479]=5332980;a[1311480]=5332688;a[1311481]=5332456;a[1311482]=5332120;a[1311483]=5331796;a[1311484]=5331548;a[1311485]=5331160;a[1311486]=5330908;a[1311487]=5330548;a[1311488]=5330204;a[1311489]=533e4;a[1311490]=5329716;a[1311491]=5362252;a[1311492]=5329284;a[1311493]=5329056;a[1311494]=5328788;a[1311495]=5360240;a[1311496]=5328244;a[1311497]=5327988;a[1311498]=5327652;a[1311499]=5327396;a[1311500]=5326980;a[1311501]=5326740;a[1311502]=5326504;a[1311503]=5326184;a[1311504]=5325980;a[1311505]=5325760;a[1311506]=5325492;a[1311507]=5378776;a[1311508]=5378504;a[1311509]=5378304;a[1311510]=5358208;a[1311511]=5377688;a[1311512]=5356568;a[1311513]=5377248;a[1311514]=5377016;a[1311515]=5376792;a[1311516]=5376536;a[1311517]=5376208;a[1311518]=5375868;a[1311519]=5375556;a[1311520]=5375252;a[1311521]=5374920;a[1311522]=5374612;a[1311523]=5374260;a[1311524]=5374040;a[1311525]=5373860;a[1311526]=5373656;a[1311527]=5355e3;a[1311528]=5353516;a[1311529]=5372804;a[1311530]=5372576;a[1311531]=5372344;a[1311532]=5372072;a[1311533]=5371856;a[1311534]=5371628;a[1311535]=5371336;a[1311536]=5371056;a[1311537]=5351708;a[1311538]=5370512;a[1311539]=5370240;a[1311540]=5369872;a[1311541]=5369600;a[1311542]=5369300;a[1311543]=5369004;a[1311544]=5368820;a[1311545]=5368608;a[1311546]=5350168;a[1311547]=5368188;a[1311548]=5367988;a[1311549]=5367824;a[1311550]=5367512;a[1311551]=5367348;a[1311552]=5348884;a[1311553]=5366864;a[1311554]=5348088;a[1311555]=5366436;a[1311619]=5243196;a[1311631]=5245636;a[1311649]=5253540;a[1311669]=5333224;a[1311670]=5330164;a[1311671]=5327616;a[1311672]=5378472;a[1311673]=5375824;a[1311715]=5375572;a[1311716]=5375844;a[1311717]=5353996;a[1311718]=5338228;a[1311719]=5342268;a[1311720]=5339032;a[1311721]=5336252;a[1311722]=5333372;a[1311723]=5338228;a[1311724]=5330256;a[1311725]=5327704;a[1311726]=5338228;a[1311727]=5378536;a[1311728]=5375960;a[1311729]=5373116;a[1311730]=5370568;a[1311731]=5368024;a[1311732]=5365696;a[1311733]=5363152;a[1311734]=5361016;a[1311735]=5358964;a[1311736]=5357284;a[1311737]=5355628;a[1311738]=5354040;a[1311739]=5352460;a[1311740]=5350800;a[1311741]=5349440;a[1311742]=5348252;a[1311743]=5347844;a[1311744]=5347352;a[1311745]=5346844;a[1311746]=5346432;a[1311747]=5346124;a[1311748]=5345816;a[1311749]=5338228;a[1311750]=5345444;a[1311751]=5345004;a[1311752]=5344652;a[1311753]=5344332;a[1311754]=5338228;a[1311755]=5343984;a[1311756]=5343648;a[1311757]=5343124;a[1311758]=5342784;a[1311759]=5345816;a[1311760]=5338228;a[1311761]=5342520;a[1311762]=5342160;a[1311763]=5341788;a[1311764]=5341420;a[1311765]=5341068;a[1311766]=5340760;a[1311767]=5340472;a[1311768]=5340180;a[1311769]=5339884;a[1311770]=5339616;a[1311771]=5338228;a[1311772]=5339328;a[1311773]=5338892;a[1311774]=5338608;a[1311775]=5338288;a[1311776]=5338036;a[1311777]=5338228;a[1311778]=5337796;a[1311779]=5337472;a[1311780]=5337244;a[1311781]=5337012;a[1311782]=5336736;a[1311783]=5336496;a[1311784]=5336160;a[1311785]=5335828;a[1311786]=5335492;a[1311787]=5335200;a[1311788]=5334956;a[1311789]=5334700;a[1311790]=5345816;a[1311791]=5338228;a[1311792]=5334440;a[1311793]=5334116;a[1311794]=5333872;a[1311795]=5361016;a[1311796]=5338228;a[1311797]=5333604;a[1311798]=5333400;a[1311799]=5332952;a[1311800]=5332656;a[1311801]=5332436;a[1311802]=5332092;a[1311803]=5331768;a[1311804]=5331468;a[1311805]=5331132;a[1311806]=5330884;a[1311807]=5361016;a[1311808]=5338228;a[1311809]=5330492;a[1311810]=5330168;a[1311811]=5329976;a[1311812]=5329692;a[1311813]=5329480;a[1311814]=5329264;a[1311815]=5329036;a[1311816]=5328776;a[1311817]=5345816;a[1311818]=5338228;a[1311819]=5328548;a[1311820]=5328228;a[1311821]=5327972;a[1311822]=5327636;a[1311823]=5327380;a[1311824]=5326956;a[1311825]=5326728;a[1311826]=5326488;a[1311827]=5326168;a[1311828]=5325960;a[1311829]=5325748;a[1311830]=5345816;a[1311831]=5338228;a[1311832]=5325460;a[1311833]=5378756;a[1311834]=5338228;a[1311835]=5378488;a[1311836]=5378256;a[1311837]=5377924;a[1311838]=5377696;a[1311839]=5377492;a[1311840]=5377260;a[1311841]=5377024;a[1311842]=5376804;a[1311843]=5376544;a[1311844]=5338228;a[1311845]=5376224;a[1311846]=5338228;a[1311847]=5375884;a[1311848]=5375628;a[1311849]=5375268;a[1311850]=5374932;a[1311851]=5374624;a[1311852]=5374300;a[1311853]=5345816;a[1311854]=5338228;a[1311855]=5374048;a[1311856]=5338228;a[1311857]=5373868;a[1311858]=5373668;a[1311859]=5373396;a[1311860]=5373052;a[1311861]=5372816;a[1311862]=5372588;a[1311863]=5372364;a[1311864]=5361016;a[1311865]=5338228;a[1311866]=5372080;a[1311867]=5338228;a[1311868]=5371868;a[1311869]=5371692;a[1311870]=5371348;a[1311871]=5371064;a[1311872]=5370840;a[1311873]=5370520;a[1311874]=5370252;a[1311875]=5338228;a[1311876]=5369884;a[1311877]=5369612;a[1311878]=5369308;a[1311879]=5369084;a[1311880]=5368836;a[1311881]=5368612;a[1311882]=5368348;a[1311883]=5368196;a[1311884]=5338228;a[1311885]=5368e3;a[1311893]=5329652;a[1311894]=5326916;a[1311895]=5377892;a[1311899]=5375216;a[1311902]=5372528;a[1311903]=5326916;a[1311904]=5377892;a[1311906]=5369840;a[1311908]=5375216;a[1311910]=5367480;a[1311911]=5365040;a[1311912]=5326916;a[1311913]=5362532;a[1311917]=5375216;a[1311918]=5360600;a[1311920]=5358412;a[1311921]=5326916;a[1311922]=5362532;a[1311924]=5369840;a[1311926]=5375216;a[1311927]=5360600;a[1311928]=5367480;a[1311929]=5356772;a[1311930]=5355180;a[1311931]=5362532;a[1311935]=5353712;a[1311936]=5360600;a[1311938]=5351912;a[1311939]=5355180;a[1311940]=5362532;a[1311942]=5367480;a[1311944]=5353712;a[1311945]=5360600;a[1311946]=5367480;a[1311947]=5350320;a[1311948]=5355180;a[1311949]=5349064;a[1311953]=5353712;a[1311956]=5348148;a[1311957]=5355180;a[1311958]=5349064;a[1311960]=5367480;a[1311962]=5353712;a[1311964]=5367480;a[1311965]=5347680;a[1311966]=5347680;a[1311971]=5347196;a[1311974]=5346712;a[1311975]=5347680;a[1311976]=5360600;a[1311980]=5347196;a[1311981]=5360600;a[1311983]=5346324;a[1311984]=5347680;a[1311985]=5360600;a[1311987]=5369840;a[1311989]=5347196;a[1311990]=5360600;a[1311991]=5367480;a[1311992]=5345992;a[1311993]=5347680;a[1311996]=5369840;a[1311998]=5347196;a[1312e3]=5367480;a[1312001]=5345688;a[1312002]=5345688;a[1312007]=5375216;a[1312010]=5345304;a[1312011]=5345688;a[1312012]=5360600;a[1312016]=5375216;a[1312017]=5360600;a[1312019]=5344908;a[1312020]=5345688;a[1312021]=5360600;a[1312023]=5369840;a[1312025]=5375216;a[1312026]=5360600;a[1312027]=5367480;a[1312028]=5344580;a[1312029]=5345688;a[1312031]=5344228;a[1312034]=5375216;a[1312037]=5343852;a[1312038]=5345688;a[1312039]=5360600;a[1312040]=5344228;a[1312043]=5375216;a[1312044]=5360600;a[1312046]=5343508;a[1312047]=5345688;a[1312048]=5360600;a[1312049]=5344228;a[1312050]=5369840;a[1312052]=5375216;a[1312053]=5360600;a[1312054]=5367480;a[1312055]=5343096;a[1312056]=5345688;a[1312058]=5344228;a[1312059]=5369840;a[1312061]=5375216;a[1312063]=5367480;a[1312064]=5342764;a[1312065]=5345688;a[1312068]=5369840;a[1312070]=5375216;a[1312072]=5367480;a[1312073]=5342496;a[1312074]=5342096;a[1312075]=5360600;a[1312079]=5353712;a[1312080]=5360600;a[1312082]=5341760;a[1312083]=5342096;a[1312084]=5360600;a[1312086]=5367480;a[1312088]=5353712;a[1312089]=5360600;a[1312090]=5367480;a[1312091]=5341396;a[1312092]=5342096;a[1312095]=5367480;a[1312097]=5353712;a[1312099]=5367480;a[1312100]=5341028;a[1312101]=5342096;a[1312102]=5340752;a[1312106]=5353712;a[1312109]=5340456;a[1312110]=5340160;a[1312111]=5360600;a[1312115]=5353712;a[1312116]=5360600;a[1312118]=5339864;a[1312119]=5340160;a[1312120]=5360600;a[1312122]=5367480;a[1312124]=5353712;a[1312125]=5360600;a[1312126]=5367480;a[1312127]=5339600;a[1312128]=5340160;a[1312131]=5367480;a[1312133]=5353712;a[1312135]=5367480;a[1312136]=5339312;a[1312137]=5340160;a[1312138]=5340752;a[1312142]=5353712;a[1312145]=5338852;a[1312146]=5338852;a[1312151]=5338600;a[1312154]=5338276;a[1312155]=5338020;a[1312156]=5360600;a[1312160]=5353712;a[1312161]=5360600;a[1312163]=5337776;a[1312164]=5338020;a[1312165]=5360600;a[1312167]=5367480;a[1312169]=5353712;a[1312170]=5360600;a[1312171]=5367480;a[1312172]=5337456;a[1312173]=5338020;a[1312176]=5367480;a[1312178]=5353712;a[1312180]=5367480;a[1312181]=5377304;a[1312182]=5338020;a[1312187]=5353712;a[1312190]=5336972;a[1312191]=5336708;a[1312192]=5336476;a[1312194]=5367480;a[1312196]=5353712;a[1312198]=5367480;a[1312199]=5336100;a[1312200]=5335804;a[1312205]=5338600;a[1312231]=5334592;a[1312232]=5334276;a[1312765]=338;a[1312767]=5354020;a[1312770]=5352372;a[1312771]=5350700;a[1312774]=5367836;a[1312775]=5348240;a[1312778]=5347832;a[1312779]=5347340;a[1312782]=5346836;a[1312783]=5346420;a[1312786]=5346108;a[1312787]=5345800;a[1312790]=5345432;a[1312791]=5344992;a[1312794]=5344644;a[1312795]=5344280;a[1312798]=5343972;a[1312809]=5329388;a[1312819]=5341636;a[1312829]=5354076;a[1312839]=5367836;a[1312849]=5333232;a[1312859]=5344944;a[1312869]=5345064;a[1312874]=5341556;a[1312893]=5346072;a[1312894]=5324208;a[1312895]=5346052;a[1312896]=5324080;a[1312898]=5335996;a[1312903]=5362968;a[1312908]=5347820;a[1312913]=5343952;a[1312918]=5340536;a[1312923]=5337520;a[1312928]=5334752;a[1312933]=5331820;a[1312938]=5329088;a[1312943]=5326256;a[1312948]=5377292;a[1312953]=5374348;a[1312958]=5371904;a[1312963]=5369032;a[1312968]=5366884;a[1312973]=5364432;a[1312978]=5361932;a[1312983]=5359908;a[1312988]=5358016;a[1312993]=5356280;a[1312998]=5354780;a[1313003]=5353192;a[1313008]=5351476;a[1313013]=5349960;a[1313018]=5348732;a[1313023]=5348048;a[1313028]=5347552;a[1313033]=5347028;a[1313038]=5346604;a[1313043]=5346228;a[1313048]=5345932;a[1313053]=5345588;a[1313058]=5345180;a[1313063]=5344824;a[1313068]=5344528;a[1313073]=5344168;a[1313078]=5343780;a[1313083]=5343412;a[1313088]=5342992;a[1313093]=5342696;a[1313098]=5342420;a[1313103]=5342044;a[1313108]=5341700;a[1313113]=5341312;a[1313118]=5340964;a[1313123]=5340704;a[1313128]=5340388;a[1313133]=5340108;a[1313138]=5339792;a[1313143]=5339540;a[1313153]=5345064;a[1313162]=5343596;a[1313164]=5368664;a[1313166]=5349684;a[1313168]=5344704;a[1313170]=5341200;a[1313172]=5338108;a[1313174]=5335192;a[1313176]=5332404;a[1313178]=5329440;a[1313180]=5326676;a[1313182]=5377612;a[1313184]=5374820;a[1313186]=5372216;a[1313188]=5370200;a[1313191]=5326632;a[1313201]=5367576;a[1313211]=5340964;a[1313221]=5359908;a[1313226]=5367356;a[1313231]=5364432;a[1313241]=5360368;a[1313246]=5347072;a[1313251]=5343424;a[1313256]=5340040;a[1313261]=5337132;a[1313266]=5334212;a[1313276]=5369024;a[1313286]=5338404;a[1313291]=5335584;a[1313296]=5332740;a[1313301]=5329760;a[1313306]=5327052;a[1313311]=5377992;a[1313332]=5346032;a[1313333]=5345760;a[1313334]=5341724;a[1313340]=5344964;a[1313341]=5367836;a[1313342]=5354076;a[1313374]=5374748;a[1313375]=5372240;a[1313376]=5364732;a[1313377]=5352172;a[1313378]=5353516;a[1313379]=5328788;a[1313380]=5348088;a[1313381]=5348884;a[1313385]=5374748;a[1313386]=5372240;a[1313387]=5352172;a[1313388]=5364732;a[1313389]=5328788;a[1313390]=5353516;a[1313391]=5348884;a[1313392]=5348088;a[1313808]=326;a[1313809]=76;a[1313814]=5343272;a[1313816]=5342848;a[1313818]=5342580;a[1313820]=5342284;a[1313822]=5341888;a[1313824]=5341536;a[1313826]=5341192;a[1313828]=5340828;a[1313830]=5340556;a[1313832]=5340284;a[1313834]=5339956;a[1313836]=5339684;a[1313838]=5339388;a[1313840]=5339040;a[1313842]=5338700;a[1313844]=5338372;a[1313846]=5338124;a[1313848]=5337884;a[1313850]=5337540;a[1313852]=5337312;a[1313854]=5337072;a[1313856]=5336804;a[1313858]=5336576;a[1313860]=5336284;a[1313862]=5335900;a[1313864]=5335548;a[1313866]=5335308;a[1313868]=5335012;a[1313870]=5334772;a[1313872]=5334512;a[1313874]=5334184;a[1313876]=5333936;a[1313878]=5333696;a[1313880]=5333392;a[1313882]=5333036;a[1313884]=5332720;a[1313886]=5332492;a[1313888]=5332160;a[1313890]=5331844;a[1313892]=5331596;a[1313894]=5331220;a[1313896]=5330944;a[1313898]=5330584;a[1313900]=5330316;a[1313902]=5330040;a[1313904]=5329740;a[1313906]=5329536;a[1313908]=5329324;a[1313910]=5329108;a[1313912]=5328832;a[1313914]=5328588;a[1313916]=5328288;a[1313918]=5328028;a[1313920]=5327736;a[1313922]=5327440;a[1313924]=5327024;a[1313926]=5326780;a[1313928]=5326564;a[1313930]=5326264;a[1313932]=5326032;a[1313934]=5325808;a[1313936]=5325528;a[1313938]=5378812;a[1313940]=5378576;a[1313942]=5378344;a[1313944]=5377960;a[1313946]=5377724;a[1313948]=5377520;a[1313950]=5377316;a[1313952]=5377064;a[1313954]=5376832;a[1313956]=5376572;a[1313958]=5376284;a[1313960]=5375976;a[1313962]=5375608;a[1313964]=5375320;a[1313966]=5375092;a[1313968]=5374732;a[1313970]=5374456;a[1313972]=5374156;a[1313974]=5373936;a[1313976]=5373744;a[1313978]=5373512;a[1313980]=5373164;a[1313982]=5372912;a[1313984]=5372660;a[1313986]=5372452;a[1313988]=5372152;a[1313990]=5371972;a[1313992]=5371728;a[1313994]=5371456;a[1313996]=5371156;a[1313998]=5370948;a[1314e3]=5370688;a[1314002]=5370380;a[1314004]=5370032;a[1314006]=5369732;a[1314008]=5369216;a[1314010]=5369160;a[1314012]=5368904;a[1314014]=5368708;a[1314016]=5368436;a[1314018]=5368252;a[1314020]=5368088;a[1314022]=5367900;a[1314024]=5367596;a[1314026]=5367412;a[1314028]=5367172;a[1314030]=5367012;a[1314032]=5366748;a[1314034]=5366540;a[1314036]=5366224;a[1314038]=5365992;a[1314040]=5365796;a[1314042]=5365532;a[1314044]=5365168;a[1314046]=5364964;a[1314048]=5364728;a[1314050]=5364512;a[1314052]=5364280;a[1314054]=5364092;a[1314056]=5363896;a[1314058]=5363492;a[1314060]=5363276;a[1314062]=5362928;a[1314064]=5362700;a[1314066]=5334020;a[1314068]=5362244;a[1314070]=5362024;a[1314072]=5361804;a[1314074]=5361636;a[1314076]=5361468;a[1314078]=5361256;a[1314080]=5361084;a[1314082]=5360840;a[1314084]=5360620;a[1314086]=5360440;a[1314088]=5360232;a[1314090]=5360060;a[1314092]=5359804;a[1314094]=5359644;a[1314096]=5359476;a[1314098]=5359224;a[1314100]=5359040;a[1314102]=5358824;a[1314104]=5358548;a[1314106]=5358380;a[1314108]=5358200;a[1314110]=5358060;a[1314112]=5357944;a[1314114]=5357796;a[1314116]=5357648;a[1314118]=5357500;a[1314120]=5374820;a[1314122]=5357176;a[1314124]=5356964;a[1314126]=5356724;a[1314128]=5356560;a[1314130]=5356356;a[1314132]=5356188;a[1314134]=5356084;a[1314136]=5355968;a[1314138]=5355828;a[1314140]=5355688;a[1314142]=5355504;a[1314144]=5355320;a[1314146]=5355136;a[1314148]=5354992;a[1314150]=5354836;a[1314152]=5354684;a[1314154]=5354548;a[1314156]=5354384;a[1314158]=5354260;a[1314160]=5354112;a[1314162]=5353920;a[1314164]=5353804;a[1314166]=5353668;a[1314168]=5353508;a[1314170]=5353284;a[1314172]=5353112;a[1314174]=5352956;a[1314176]=5352800;a[1314178]=5352684;a[1314180]=5352556;a[1314182]=5352288;a[1314184]=5352076;a[1314186]=5351884;a[1314188]=5351700;a[1314190]=5351520;a[1314192]=5351368;a[1314194]=5351196;a[1314196]=5351112;a[1314198]=5350976;a[1314200]=5350864;a[1314202]=5350636;a[1314204]=5350420;a[1314206]=5350264;a[1314208]=5350160;a[1314210]=5350020;a[1314212]=5349896;a[1314214]=5349800;a[1314216]=5349716;a[1314218]=5349584;a[1314220]=5349508;a[1314222]=5349280;a[1314224]=5349156;a[1314226]=5349036;a[1314228]=5348904;a[1314230]=5348688;a[1314232]=5348656;a[1314234]=5348508;a[1314236]=5348440;a[1314238]=5348324;a[1314240]=5348304;a[1314242]=5348220;a[1314244]=5348180;a[1314246]=5348128;a[1314248]=5348096;a[1314250]=5348068;a[1314252]=5348024;a[1314254]=5347996;a[1314256]=5347976;a[1314258]=5347944;a[1314260]=5347880;a[1314262]=5347800;a[1314264]=5347692;a[1314266]=5347664;a[1314268]=5347628;a[1314270]=5347596;a[1314272]=5347508;a[1314274]=5347476;a[1314276]=5347456;a[1314278]=5347436;a[1314280]=5347416;a[1314282]=5347308;a[1314284]=5347216;a[1314286]=5347176;a[1314288]=5347092;a[1314290]=5347052;a[1314292]=5347e3;a[1314294]=5346964;a[1314296]=5346944;a[1314298]=5346924;a[1314300]=5346884;a[1314302]=5346816;a[1314304]=5346760;a[1314306]=5346704;a[1314308]=5346684;a[1314310]=5346624;a[1314312]=5346572;a[1314314]=5346544;a[1314316]=5346524;a[1314500]=5336328;a[1314501]=5335944;a[1315021]=5347328;a[1315024]=5343616;a[1315027]=5340260;a[1315030]=5337288;a[1315033]=5334488;a[1315036]=5331572;a[1315039]=5328820;a[1315042]=5326020;a[1315045]=5377052;a[1315048]=5374100;a[1315051]=5371652;a[1315054]=5368844;a[1315057]=5366672;a[1315060]=5364200;a[1315063]=5361728;a[1315066]=5359744;a[1315069]=5357896;a[1315072]=5356156;a[1315075]=5354632;a[1315078]=5353024;a[1315081]=5351308;a[1315084]=5349852;a[1315087]=5348596;a[1315090]=5348012;a[1315093]=5347496;a[1315096]=5346980;a[1315099]=5346548;a[1315102]=5346188;a[1315105]=5345892;a[1315108]=5345548;a[1315111]=5345136;a[1315114]=5344784;a[1315117]=5344484;a[1315120]=5344136;a[1315123]=5343740;a[1315126]=5343372;a[1315129]=5342952;a[1315132]=5342660;a[1315135]=5342380;a[1315138]=5341964;a[1315141]=5341624;a[1315144]=5341280;a[1315147]=5340924;a[1315150]=5340680;a[1315153]=5340356;a[1315156]=5340028;a[1315159]=5339764;a[1315162]=5339452;a[1315165]=5339124;a[1315168]=5338768;a[1315171]=5338468;a[1315174]=5338180;a[1315177]=5337944;a[1315180]=5337668;a[1315183]=5337376;a[1315186]=5337156;a[1315189]=5336860;a[1315192]=5336632;a[1315195]=5336360;a[1315198]=5335984;a[1315201]=5335664;a[1315204]=5335376;a[1315207]=5335088;a[1315210]=5334832;a[1315213]=5334568;a[1315216]=5334252;a[1315219]=5333992;a[1315222]=5333756;a[1315225]=5333492;a[1315228]=5333092;a[1315231]=5332800;a[1315234]=5332564;a[1315237]=5332216;a[1315240]=5331916;a[1315243]=5331652;a[1315246]=5331272;a[1315249]=5331032;a[1315252]=5330692;a[1315255]=5330416;a[1315258]=5330092;a[1315261]=5329852;a[1315264]=5329592;a[1315267]=5329376;a[1315270]=5329160;a[1315273]=5328900;a[1315276]=5328656;a[1315279]=5328384;a[1315282]=5328100;a[1315285]=5327800;a[1315288]=5327504;a[1315291]=5327204;a[1315294]=5326848;a[1315297]=5326640;a[1315300]=5326344;a[1315303]=5326088;a[1315306]=5325876;a[1315309]=5325648;a[1315312]=5325352;a[1315315]=5378656;a[1315318]=5378404;a[1315321]=5378088;a[1315324]=5377800;a[1315327]=5377580;a[1315330]=5377400;a[1315333]=5377128;a[1315336]=5376888;a[1315339]=5376636;a[1315342]=5376388;a[1315345]=5376124;a[1315348]=5375712;a[1315351]=5375392;a[1315354]=5375112;a[1315357]=5374756;a[1315360]=5374476;a[1315363]=5374176;a[1315366]=5373956;a[1315369]=5373760;a[1315372]=5373532;a[1315375]=5373276;a[1315378]=5372932;a[1315381]=5372680;a[1315384]=5372472;a[1315387]=5372248;a[1315390]=5371992;a[1315393]=5371748;a[1315396]=5371476;a[1315399]=5371176;a[1315402]=5370972;a[1315405]=5370708;a[1315408]=5370428;a[1315411]=5370060;a[1315414]=5369752;a[1315417]=5369428;a[1315420]=5369180;a[1315423]=5368924;a[1315426]=5368728;a[1315429]=5368456;a[1315432]=5368272;a[1315435]=5368108;a[1315438]=5367916;a[1315441]=5367620;a[1315444]=5367432;a[1315447]=5367200;a[1315450]=5367032;a[1315453]=5366772;a[1315456]=5366564;a[1315459]=5366344;a[1315462]=5366024;a[1315465]=5365820;a[1315468]=5365556;a[1315471]=5365212;a[1315474]=5364980;a[1315477]=5364756;a[1315480]=5364540;a[1315483]=5364308;a[1315486]=5364112;a[1315489]=5363924;a[1315492]=5363532;a[1315495]=5363296;a[1315498]=5362956;a[1315501]=5362724;a[1315504]=5362476;a[1315507]=5362276;a[1315510]=5362040;a[1315513]=5361832;a[1315516]=5361656;a[1315519]=5361488;a[1315522]=5361284;a[1315525]=5361104;a[1315528]=5360860;a[1315531]=5360640;a[1315534]=5360460;a[1315537]=5360260;a[1315540]=5360080;a[1315543]=5359824;a[1315546]=5359664;a[1315549]=5359492;a[1315552]=5359252;a[1315555]=5359060;a[1315558]=5358840;a[1315561]=5358564;a[1315564]=5358388;a[1315567]=5358216;a[1315570]=5358064;a[1315573]=5357952;a[1315576]=5357804;a[1315579]=5357656;a[1315582]=5357508;a[1315585]=5357364;a[1315588]=5357180;a[1315591]=5356972;a[1315594]=5356732;a[1315597]=5356576;a[1315600]=5356360;a[1315603]=5356192;a[1315606]=5356088;a[1315609]=5355976;a[1315612]=5355844;a[1315615]=5355696;a[1315618]=5355508;a[1315621]=5355364;a[1315624]=5355144;a[1315627]=5355008;a[1315630]=5354844;a[1315633]=5354692;a[1315636]=5354556;a[1315639]=5354392;a[1315642]=5354268;a[1315645]=5354116;a[1315648]=5353928;a[1315651]=5353812;a[1315654]=5353676;a[1315657]=5353520;a[1315660]=5353292;a[1315663]=5353120;a[1315666]=5352964;a[1315669]=5352808;a[1315672]=5352692;a[1315675]=5352564;a[1315678]=5352316;a[1315681]=5352080;a[1315684]=5351888;a[1315687]=5351716;a[1315690]=5351528;a[1315693]=5351376;a[1315696]=5351204;a[1315699]=5351120;a[1315702]=5350980;a[1315705]=5350872;a[1315708]=5350644;a[1315711]=5350520;a[1315714]=5350272;a[1315717]=5350176;a[1315720]=5350028;a[1315723]=5349904;a[1315726]=5349808;a[1315729]=5349724;a[1315732]=5349592;a[1315735]=5349516;a[1315738]=5349284;a[1315741]=5349160;a[1315744]=5349044;a[1315747]=5348912;a[1315750]=5348804;a[1315753]=5348664;a[1315756]=5348516;a[1315759]=5348448;a[1315762]=5348328;a[1315765]=5348312;a[1315768]=5348228;a[1315771]=5348184;a[1315774]=5348136;a[1315777]=5348100;a[1315780]=5348076;a[1315783]=5348028;a[1315786]=5348e3;a[1315789]=5347984;a[1315792]=5347952;a[1315795]=5347888;a[1315798]=5347808;a[1315801]=5347700;a[1315804]=5347668;a[1315807]=5347636;a[1315810]=5347604;a[1315813]=5347520;a[1315816]=5347484;a[1315819]=5347464;a[1315822]=5347444;a[1315825]=5347424;a[1315828]=5347316;a[1315831]=5347224;a[1315834]=5347184;a[1315837]=5347100;a[1315840]=5347060;a[1315843]=5347008;a[1315846]=5346968;a[1315849]=5346952;a[1315852]=5346932;a[1315855]=5346892;a[1315858]=5346824;a[1315861]=5346764;a[1315864]=5346740;a[1315867]=5346692;a[1315870]=5346632;a[1315873]=5346612;a[1315876]=5346560;a[1315879]=5346532;a[1315882]=5346512;a[1315885]=5346480;a[1315888]=5346468;a[1315891]=5346408;a[1315894]=5346344;a[1315897]=5346312;a[1315900]=5346248;a[1315903]=5346236;a[1315906]=5346200;a[1315909]=5346176;a[1315912]=5346164;a[1315915]=5346152;a[1315918]=5346136;a[1315921]=5346060;a[1315924]=5346020;a[1315927]=5345980;a[1315930]=5345968;a[1315933]=5345944;a[1315936]=5345904;a[1315939]=5345880;a[1315942]=5345868;a[1315945]=5345856;a[1315948]=5345836;a[1315951]=5345788;a[1315954]=5345728;a[1315957]=5345676;a[1315960]=5345656;a[1315963]=5345640;a[1315966]=5345560;a[1315969]=5345536;a[1315972]=5345524;a[1315975]=5345512;a[1315978]=5345500;a[1315981]=5345404;a[1315984]=5345320;a[1315987]=5345292;a[1315990]=5345268;a[1315993]=5345204;a[1315996]=5345148;a[1315999]=5345120;a[1316002]=5345108;a[1316005]=5345068;a[1316008]=5345052;a[1316011]=5344980;a[1316014]=5344932;a[1316017]=5344896;a[1316020]=5344848;a[1316023]=5344832;a[1316026]=5344804;a[1316029]=5344772;a[1316032]=5344760;a[1316035]=5344712;a[1316038]=5344692;a[1316041]=5344632;a[1316044]=5344612;a[1316047]=5344568;a[1316050]=5344552;a[1316053]=5344536;a[1316056]=5344504;a[1316059]=5344472;a[1316062]=5344460;a[1316065]=5344420;a[1316068]=5344400;a[1316071]=5344268;a[1316074]=5344244;a[1316077]=5344216;a[1316080]=5344192;a[1316083]=5344176;a[1316086]=5344148;a[1316089]=5344124;a[1316092]=5344112;a[1316095]=5344076;a[1316098]=5344020;a[1316101]=5343960;a[1316104]=5343904;a[1316107]=5343840;a[1316110]=5343816;a[1316113]=5343792;a[1316116]=5343752;a[1316119]=5343728;a[1316122]=5343716;a[1316125]=5343676;a[1316128]=5343664;a[1316131]=5343628;a[1316134]=5343544;a[1316137]=5343496;a[1316140]=5343468;a[1316143]=5343436;a[1316146]=5343384;a[1316149]=5343360;a[1316152]=5343316;a[1316155]=5343292;a[1316158]=5343280;a[1316161]=5343260;a[1316164]=5343172;a[1316167]=5343084;a[1316170]=5343036;a[1316173]=5343004;a[1316176]=5342964;a[1316179]=5342940;a[1316182]=5342928;a[1316185]=5342868;a[1316188]=5342856;a[1316191]=5342836;a[1316194]=5342800;a[1316197]=5342752;a[1316200]=5342740;a[1316203]=5342708;a[1316206]=5342672;a[1316209]=5342648;a[1316212]=5342636;a[1316215]=5342600;a[1316218]=5342588;a[1316221]=5342568;a[1316224]=5342532;a[1316227]=5342484;a[1316230]=5342468;a[1316233]=5342432;a[1316236]=5342392;a[1316239]=5342368;a[1316242]=5342356;a[1316245]=5342312;a[1316248]=5342292;a[1316251]=5342256;a[1316254]=5342196;a[1316257]=5342084;a[1316260]=5342072;a[1316263]=5342052;a[1316266]=5342020;a[1316269]=5341952;a[1316272]=5341940;a[1316275]=5341908;a[1316278]=5341896;a[1316281]=5341876;a[1316284]=5341848;a[1316287]=5341748;a[1316290]=5341736;a[1316293]=5341712;a[1316296]=5341676;a[1316299]=5341612;a[1316302]=5341600;a[1316305]=5341564;a[1316308]=5341544;a[1316311]=5341524;a[1316314]=5341496;a[1316317]=5341384;a[1316320]=5341364;a[1316323]=5341324;a[1316326]=5341292;a[1316329]=5341268;a[1316332]=5341256;a[1316335]=5341224;a[1316338]=5341212;a[1316341]=5341180;a[1316344]=5341152;a[1316347]=5341016;a[1316350]=5341004;a[1316353]=5340972;a[1316356]=5340944;a[1316359]=5340912;a[1316362]=5340900;a[1316365]=5340868;a[1316368]=5340856;a[1316371]=5340816;a[1316374]=5340796;a[1316377]=5340740;a[1316380]=5340728;a[1316383]=5340712;a[1316386]=5340692;a[1316389]=5340668;a[1316392]=5340656;a[1316395]=5340624;a[1316398]=5340564;a[1316401]=5340544;a[1316404]=5340496;a[1316407]=5340444;a[1316410]=5340432;a[1316413]=5340396;a[1316416]=5340368;a[1316419]=5340340;a[1316422]=5340328;a[1316425]=5340304;a[1316428]=5340292;a[1316431]=5340272;a[1316434]=5340204;a[1316437]=5340148;a[1316440]=5340136;a[1316443]=5340120;a[1316446]=5340052;a[1316449]=5340012;a[1316452]=5339996;a[1316455]=5339972;a[1316458]=5339960;a[1316461]=5339944;a[1316464]=5339908;a[1316467]=5339852;a[1316470]=5339840;a[1316473]=5339800;a[1316476]=5339776;a[1316479]=5339752;a[1316482]=5339736;a[1316485]=5339708;a[1316488]=5339692;a[1316491]=5339672;a[1316494]=5339640;a[1316497]=5339588;a[1316500]=5339576;a[1316503]=5339548;a[1316506]=5339464;a[1316509]=5339440;a[1316512]=5339428;a[1316515]=5339408;a[1316518]=5339396;a[1316521]=5339376;a[1316524]=5339356;a[1316527]=5339300;a[1316530]=5339288;a[1316533]=5339272;a[1316536]=5339136;a[1316539]=5339112;a[1316542]=5339100;a[1316545]=5339076;a[1316548]=5339064;a[1316551]=5339020;a[1316554]=5338928;a[1316557]=5338840;a[1316560]=5338828;a[1316563]=5338800;a[1316566]=5338780;a[1316569]=5338756;a[1316572]=5338736;a[1316575]=5338720;a[1316578]=5338708;a[1316581]=5338688;a[1316584]=5338644;a[1316587]=5338588;a[1316590]=5338548;a[1316593]=5338532;a[1316596]=5338500;a[1316599]=5338456;a[1316602]=5338436;a[1316605]=5338412;a[1316608]=5338380;a[1316611]=5338360;a[1316614]=5338328;a[1316617]=5338264;a[1316620]=5338232;a[1316623]=5338216;a[1316626]=5338192;a[1316629]=5338168;a[1316632]=5338156;a[1316635]=5338144;a[1316638]=5338132;a[1316641]=5338112;a[1316644]=5338072;a[1316647]=5338008;a[1316650]=5337996;a[1316653]=5337980;a[1316656]=5337964;a[1316659]=5337932;a[1316662]=5337920;a[1316665]=5337904;a[1316668]=5337892;a[1316671]=5337872;a[1316674]=5337824;a[1316677]=5337764;a[1316680]=5337752;a[1316683]=5337712;a[1316686]=5337680;a[1316689]=5337656;a[1316692]=5337644;a[1316695]=5337604;a[1316698]=5337592;a[1316701]=5337528;a[1316704]=5337492;a[1316707]=5337444;a[1316710]=5337432;a[1316713]=5337416;a[1316716]=5337388;a[1316719]=5337364;a[1316722]=5337352;a[1316725]=5337332;a[1316728]=5337320;a[1316731]=5337300;a[1316734]=5337260;a[1316737]=5337232;a[1316740]=5337220;a[1316743]=5337188;a[1316746]=5337168;a[1316749]=5337144;a[1316752]=5337120;a[1316755]=5337108;a[1316758]=5337080;a[1316761]=5337060;a[1316764]=5337028;a[1316767]=5337e3;a[1316770]=5336960;a[1316773]=5336936;a[1316776]=5336872;a[1316779]=5336848;a[1316782]=5336836;a[1316785]=5336824;a[1316788]=5336812;a[1316791]=5336792;a[1316794]=5336756;a[1316797]=5336724;a[1316800]=5336696;a[1316803]=5336680;a[1316806]=5336644;a[1316809]=5336620;a[1316812]=5336608;a[1316815]=5336596;a[1316818]=5336584;a[1316821]=5336564;a[1316824]=5336512;a[1316827]=5336484;a[1316830]=5336444;a[1316833]=5336424;a[1316836]=5336372;a[1316839]=5336348;a[1316842]=5336336;a[1316845]=5336316;a[1316848]=5336292;a[1316851]=5336240;a[1316854]=5336168;a[1316857]=5336116;a[1316860]=5336088;a[1316863]=5336040;a[1316866]=5336004;a[1316869]=5335972;a[1316872]=5335960;a[1316875]=5335920;a[1316878]=5335908;a[1316881]=5335888;a[1316884]=5335852;a[1316887]=5335816;a[1316890]=5335792;a[1316893]=5335732;a[1316896]=5335700;a[1316899]=5335652;a[1316902]=5335640;a[1316905]=5335592;a[1316908]=5335556;a[1316911]=5335536;a[1316914]=5335508;a[1316917]=5335480;a[1316920]=5335468;a[1316923]=5335420;a[1316926]=5335396;a[1316929]=5335364;a[1316932]=5335352;a[1316935]=5335328;a[1316938]=5335316;a[1316941]=5335296;a[1316944]=5335264;a[1316947]=5335168;a[1316950]=5335156;a[1316953]=5335132;a[1316956]=5335108;a[1316959]=5335076;a[1316962]=5335064;a[1316965]=5335032;a[1316968]=5335020;a[1316971]=5335e3;a[1316974]=5334968;a[1316977]=5334936;a[1316980]=5334924;a[1316983]=5334876;a[1316986]=5334844;a[1316989]=5334820;a[1316992]=5334808;a[1316995]=5334788;a[1316998]=5334776;a[1317001]=5334760;a[1317004]=5334708;a[1317007]=5334688;a[1317010]=5334676;a[1317013]=5334628;a[1317016]=5334580;a[1317019]=5334556;a[1317022]=5334544;a[1317025]=5334532;a[1317028]=5334520;a[1317031]=5334500;a[1317034]=5334452;a[1317037]=5334428;a[1317040]=5334416;a[1317043]=5334312;a[1317046]=5334264;a[1317049]=5334240;a[1317052]=5334228;a[1317055]=5334200;a[1317058]=5334188;a[1317061]=5334172;a[1317064]=5334132;a[1317067]=5334104;a[1317070]=5334092;a[1317073]=5334060;a[1317076]=5334008;a[1317079]=5333980;a[1317082]=5333968;a[1317085]=5333956;a[1317088]=5333944;a[1317091]=5333924;a[1317094]=5333892;a[1317097]=5333860;a[1317100]=5333848;a[1317103]=5333816;a[1317106]=5333768;a[1317109]=5333744;a[1317112]=5333732;a[1317115]=5333716;a[1317118]=5333704;a[1317121]=5333684;a[1317124]=5333648;a[1317127]=5333592;a[1317130]=5333580;a[1317133]=5333548;a[1317136]=5333504;a[1317139]=5333480;a[1317142]=5333456;a[1317145]=5333444;a[1317148]=5333432;a[1317151]=5333360;a[1317154]=5333236;a[1317157]=5333212;a[1317160]=5333200;a[1317163]=5333172;a[1317166]=5333104;a[1317169]=5333080;a[1317172]=5333068;a[1317175]=5333056;a[1317178]=5333044;a[1317181]=5333024;a[1317184]=5332968;a[1317187]=5332940;a[1317190]=5332928;a[1317193]=5332864;a[1317196]=5332836;a[1317199]=5332788;a[1317202]=5332776;a[1317205]=5332752;a[1317208]=5332728;a[1317211]=5332708;a[1317214]=5332676;a[1317217]=5332644;a[1317220]=5332632;a[1317223]=5332608;a[1317226]=5332576;a[1317229]=5332552;a[1317232]=5332532;a[1317235]=5332512;a[1317238]=5332500;a[1317241]=5332480;a[1317244]=5332444;a[1317247]=5332412;a[1317250]=5332392;a[1317253]=5332356;a[1317256]=5332276;a[1317259]=5332204;a[1317262]=5332192;a[1317265]=5332180;a[1317268]=5332168;a[1317271]=5332148;a[1317274]=5332108;a[1317277]=5332080;a[1317280]=5332044;a[1317283]=5332020;a[1317286]=5331928;a[1317289]=5331904;a[1317292]=5331892;a[1317295]=5331864;a[1317298]=5331852;a[1317301]=5331832;a[1317304]=5331784;a[1317307]=5331756;a[1317310]=5331744;a[1317313]=5331708;a[1317316]=5331668;a[1317319]=5331640;a[1317322]=5331628;a[1317325]=5331616;a[1317328]=5331604;a[1317331]=5331584;a[1317334]=5331536;a[1317337]=5331456;a[1317340]=5331444;a[1317343]=5331420;a[1317346]=5331284;a[1317349]=5331260;a[1317352]=5331248;a[1317355]=5331236;a[1317358]=5331224;a[1317361]=5331208;a[1317364]=5331140;a[1317367]=5331120;a[1317370]=5331108;a[1317373]=5331088;a[1317376]=5331044;a[1317379]=5331020;a[1317382]=5331004;a[1317385]=5330960;a[1317388]=5330948;a[1317391]=5330932;a[1317394]=5330896;a[1317397]=5330872;a[1317400]=5330860;a[1317403]=5330844;a[1317406]=5330704;a[1317409]=5330680;a[1317412]=5330668;a[1317415]=5330604;a[1317418]=5330592;a[1317421]=5330572;a[1317424]=5330536;a[1317427]=5330480;a[1317430]=5330468;a[1317433]=5330444;a[1317436]=5330428;a[1317439]=5330404;a[1317442]=5330392;a[1317445]=5330332;a[1317448]=5330320;a[1317451]=5330304;a[1317454]=5330180;a[1317457]=5330152;a[1317460]=5330140;a[1317463]=5330116;a[1317466]=5330104;a[1317469]=5330080;a[1317472]=5330068;a[1317475]=5330056;a[1317478]=5330044;a[1317481]=5330028;a[1317484]=5329988;a[1317487]=5329964;a[1317490]=5329952;a[1317493]=5329920;a[1317496]=5329900;a[1317499]=5329840;a[1317502]=5329828;a[1317505]=5329772;a[1317508]=5329748;a[1317511]=5329728;a[1317514]=5329704;a[1317517]=5329680;a[1317520]=5329668;a[1317523]=5329636;a[1317526]=5329624;a[1317529]=5329604;a[1317532]=5329580;a[1317535]=5329556;a[1317538]=5329544;a[1317541]=5329524;a[1317544]=5329500;a[1317547]=5329460;a[1317550]=5329448;a[1317553]=5329416;a[1317556]=5329404;a[1317559]=5329392;a[1317562]=5329364;a[1317565]=5329344;a[1317568]=5329332;a[1317571]=5329312;a[1317574]=5329296;a[1317577]=5329252;a[1317580]=5329240;a[1317583]=5329196;a[1317586]=5329184;a[1317589]=5329172;a[1317592]=5329148;a[1317595]=5329124;a[1317598]=5329112;a[1317601]=5329096;a[1317604]=5329064;a[1317607]=5329024;a[1317610]=5329012;a[1317613]=5328936;a[1317616]=5328924;a[1317619]=5328912;a[1317622]=5328888;a[1317625]=5328864;a[1317628]=5328852;a[1317631]=5328840;a[1317634]=5328796;a[1317637]=5328764;a[1317640]=5328752;a[1317643]=5328692;a[1317646]=5328680;a[1317649]=5328668;a[1317652]=5328644;a[1317655]=5328620;a[1317658]=5328608;a[1317661]=5328596;a[1317664]=5328564;a[1317667]=5328496;a[1317670]=5328484;a[1317673]=5328420;a[1317676]=5328408;a[1317679]=5328396;a[1317682]=5328372;a[1317685]=5328320;a[1317688]=5328308;a[1317691]=5328296;a[1317694]=5328264;a[1317697]=5328216;a[1317700]=5328204;a[1317703]=5328136;a[1317706]=5328124;a[1317709]=5328112;a[1317712]=5328088;a[1317715]=5328060;a[1317718]=5328048;a[1317721]=5328036;a[1317724]=5328e3;a[1317727]=5327960;a[1317730]=5327948;a[1317733]=5327836;a[1317736]=5327824;a[1317739]=5327812;a[1317742]=5327788;a[1317745]=5327768;a[1317748]=5327756;a[1317751]=5327744;a[1317754]=5327668;a[1317757]=5327624;a[1317760]=5327604;a[1317763]=5327540;a[1317766]=5327528;a[1317769]=5327516;a[1317772]=5327492;a[1317775]=5327472;a[1317778]=5327460;a[1317781]=5327448;a[1317784]=5327412;a[1317787]=5327368;a[1317790]=5327356;a[1317793]=5327268;a[1317796]=5327252;a[1317799]=5327216;a[1317802]=5327136;a[1317805]=5327068;a[1317808]=5327040;a[1317811]=5327028;a[1317814]=5326996;a[1317817]=5326944;a[1317820]=5326932;a[1317823]=5326884;a[1317826]=5326872;a[1317829]=5326860;a[1317832]=5326836;a[1317835]=5326812;a[1317838]=5326800;a[1317841]=5326788;a[1317844]=5326756;a[1317847]=5326716;a[1317850]=5326704;a[1317853]=5326684;a[1317856]=5326664;a[1317859]=5326652;a[1317862]=5326620;a[1317865]=5326596;a[1317868]=5326584;a[1317871]=5326572;a[1317874]=5326524;a[1317877]=5326476;a[1317880]=5326464;a[1317883]=5326380;a[1317886]=5326368;a[1317889]=5326356;a[1317892]=5326332;a[1317895]=5326308;a[1317898]=5326296;a[1317901]=5326272;a[1317904]=5326200;a[1317907]=5326156;a[1317910]=5326144;a[1317913]=5326124;a[1317916]=5326112;a[1317919]=5326100;a[1317922]=5326076;a[1317925]=5326064;a[1317928]=5326052;a[1317931]=5326040;a[1317934]=5325996;a[1317937]=5325948;a[1317940]=5325936;a[1317943]=5325912;a[1317946]=5325900;a[1317949]=5325888;a[1317952]=5325864;a[1317955]=5325840;a[1317958]=5325828;a[1317961]=5325816;a[1317964]=5325776;a[1317967]=5325736;a[1317970]=5325716;a[1317973]=5325684;a[1317976]=5325672;a[1317979]=5325660;a[1317982]=5325636;a[1317985]=5325608;a[1317988]=5325548;a[1317991]=5325536;a[1317994]=5325504;a[1317997]=5325448;a[1318e3]=5325436;a[1318003]=5325388;a[1318006]=5325376;a[1318009]=5325364;a[1318012]=5325340;a[1318015]=5378844;a[1318018]=5378832;a[1318021]=5378820;a[1318024]=5378788;a[1318027]=5378744;a[1318030]=5378732;a[1318033]=5378692;a[1318036]=5378680;a[1318039]=5378668;a[1318042]=5378644;a[1318045]=5378620;a[1318048]=5378596;a[1318051]=5378584;a[1318054]=5378520;a[1318057]=5378476;a[1318060]=5378460;a[1318063]=5378440;a[1318066]=5378428;a[1318069]=5378416;a[1318072]=5378392;a[1318075]=5378376;a[1318078]=5378364;a[1318081]=5378352;a[1318084]=5378316;a[1318087]=5378244;a[1318090]=5378232;a[1318093]=5378152;a[1318096]=5378132;a[1318099]=5378100;a[1318102]=5378076;a[1318105]=5378004;a[1318108]=5377980;a[1318111]=5377968;a[1318114]=5377936;a[1318117]=5377912;a[1318120]=5377900;a[1318123]=5377836;a[1318126]=5377824;a[1318129]=5377812;a[1318132]=5377788;a[1318135]=5377764;a[1318138]=5377752;a[1318141]=5377728;a[1318144]=5377712;a[1318147]=5377676;a[1318150]=5377664;a[1318153]=5377632;a[1318156]=5377620;a[1318159]=5377592;a[1318162]=5377560;a[1318165]=5377548;a[1318168]=5377536;a[1318171]=5377524;a[1318174]=5377508;a[1318177]=5377480;a[1318180]=5377468;a[1318183]=5377436;a[1318186]=5377424;a[1318189]=5377412;a[1318192]=5377388;a[1318195]=5377376;a[1318198]=5377364;a[1318201]=5377320;a[1318204]=5377280;a[1318207]=5377236;a[1318210]=5377224;a[1318213]=5377164;a[1318216]=5377152;a[1318219]=5377140;a[1318222]=5377116;a[1318225]=5377104;a[1318228]=5377084;a[1318231]=5377072;a[1318234]=5377040;a[1318237]=5377004;a[1318240]=5376992;a[1318243]=5376924;a[1318246]=5376912;a[1318249]=5376900;a[1318252]=5376876;a[1318255]=5376864;a[1318258]=5376852;a[1318261]=5376840;a[1318264]=5376808;a[1318267]=5376780;a[1318270]=5376768;a[1318273]=5376672;a[1318276]=5376660;a[1318279]=5376648;a[1318282]=5376624;a[1318285]=5376612;a[1318288]=5376600;a[1318291]=5376580;a[1318294]=5376548;a[1318297]=5376524;a[1318300]=5376512;a[1318303]=5376424;a[1318306]=5376412;a[1318309]=5376400;a[1318312]=5376376;a[1318315]=5376316;a[1318318]=5376304;a[1318321]=5376292;a[1318324]=5376260;a[1318327]=5376196;a[1318330]=5376184;a[1318333]=5376160;a[1318336]=5376148;a[1318339]=5376136;a[1318342]=5376112;a[1318345]=5376064;a[1318348]=5375996;a[1318351]=5375984;a[1318354]=5375936;a[1318357]=5375832;a[1318360]=5375812;a[1318363]=5375776;a[1318366]=5375736;a[1318369]=5375724;a[1318372]=5375700;a[1318375]=5375688;a[1318378]=5375676;a[1318381]=5375616;a[1318384]=5375588;a[1318387]=5375544;a[1318390]=5375532;a[1318393]=5375460;a[1318396]=5375448;a[1318399]=5375404;a[1318402]=5375380;a[1318405]=5375360;a[1318408]=5375340;a[1318411]=5375328;a[1318414]=5375292;a[1318417]=5375240;a[1318420]=5375228;a[1318423]=5375148;a[1318426]=5375136;a[1318429]=5375124;a[1318432]=5375100;a[1318435]=5375080;a[1318438]=5375056;a[1318441]=5375044;a[1318444]=5374960;a[1318447]=5374908;a[1318450]=5374888;a[1318453]=5374852;a[1318456]=5374840;a[1318459]=5374828;a[1318462]=5374736;a[1318465]=5374720;a[1318468]=5374708;a[1318471]=5374696;a[1318474]=5374664;a[1318477]=5374584;a[1318480]=5374572;a[1318483]=5374512;a[1318486]=5374500;a[1318489]=5374488;a[1318492]=5374464;a[1318495]=5374444;a[1318498]=5374432;a[1318501]=5374368;a[1318504]=5374336;a[1318507]=5374248;a[1318510]=5374236;a[1318513]=5374212;a[1318516]=5374200;a[1318519]=5374188;a[1318522]=5374164;a[1318525]=5374144;a[1318528]=5374132;a[1318531]=5374120;a[1318534]=5374088;a[1318537]=5374028;a[1318540]=5374016;a[1318543]=5373992;a[1318546]=5373980;a[1318549]=5373968;a[1318552]=5373944;a[1318555]=5373924;a[1318558]=5373912;a[1318561]=5373900;a[1318564]=5373880;a[1318567]=5373848;a[1318570]=5373836;a[1318573]=5373796;a[1318576]=5373784;a[1318579]=5373772;a[1318582]=5373748;a[1318585]=5373732;a[1318588]=5373720;a[1318591]=5373708;a[1318594]=5373688;a[1318597]=5373644;a[1318600]=5373632;a[1318603]=5373568;a[1318606]=5373556;a[1318609]=5373544;a[1318612]=5373520;a[1318615]=5373500;a[1318618]=5373488;a[1318621]=5373476;a[1318624]=5373416;a[1318627]=5373384;a[1318630]=5373372;a[1318633]=5373312;a[1318636]=5373300;a[1318639]=5373288;a[1318642]=5373264;a[1318645]=5373204;a[1318648]=5373192;a[1318651]=5373172;a[1318654]=5373076;a[1318657]=5373036;a[1318660]=5373016;a[1318663]=5372984;a[1318666]=5372968;a[1318669]=5372956;a[1318672]=5372920;a[1318675]=5372900;a[1318678]=5372888;a[1318681]=5372876;a[1318684]=5372840;a[1318687]=5372792;a[1318690]=5372780;a[1318693]=5372744;a[1318696]=5372732;a[1318699]=5372692;a[1318702]=5372668;a[1318705]=5372648;a[1318708]=5372628;a[1318711]=5372616;a[1318714]=5372592;a[1318717]=5372564;a[1318720]=5372552;a[1318723]=5372508;a[1318726]=5372496;a[1318729]=5372484;a[1318732]=5372460;a[1318735]=5372440;a[1318738]=5372428;a[1318741]=5372416;a[1318744]=5372376;a[1318747]=5372332;a[1318750]=5372312;a[1318753]=5372300;a[1318756]=5372272;a[1318759]=5372260;a[1318762]=5372228;a[1318765]=5372140;a[1318768]=5372128;a[1318771]=5372116;a[1318774]=5372096;a[1318777]=5372060;a[1318780]=5372048;a[1318783]=5372036;a[1318786]=5372016;a[1318789]=5372004;a[1318792]=5371980;a[1318795]=5371960;a[1318798]=5371948;a[1318801]=5371924;a[1318804]=5371892;a[1318807]=5371844;a[1318810]=5371832;a[1318813]=5371820;a[1318816]=5371772;a[1318819]=5371760;a[1318822]=5371736;a[1318825]=5371716;a[1318828]=5371704;a[1318831]=5371680;a[1318834]=5371640;a[1318837]=5371616;a[1318840]=5371604;a[1318843]=5371592;a[1318846]=5371500;a[1318849]=5371488;a[1318852]=5371464;a[1318855]=5371444;a[1318858]=5371432;a[1318861]=5371420;a[1318864]=5371364;a[1318867]=5371324;a[1318870]=5371312;a[1318873]=5371300;a[1318876]=5371256;a[1318879]=5371188;a[1318882]=5371164;a[1318885]=5371144;a[1318888]=5371132;a[1318891]=5371120;a[1318894]=5371096;a[1318897]=5371044;a[1318900]=5371032;a[1318903]=5371020;a[1318906]=5370996;a[1318909]=5370984;a[1318912]=5370960;a[1318915]=5370936;a[1318918]=5370924;a[1318921]=5370912;a[1318924]=5370856;a[1318927]=5370828;a[1318930]=5370816;a[1318933]=5370804;a[1318936]=5370732;a[1318939]=5370720;a[1318942]=5370696;a[1318945]=5370676;a[1318948]=5370664;a[1318951]=5370644;a[1318954]=5370556;a[1318957]=5370500;a[1318960]=5370488;a[1318963]=5370476;a[1318966]=5370452;a[1318969]=5370440;a[1318972]=5370416;a[1318975]=5370368;a[1318978]=5370356;a[1318981]=5370344;a[1318984]=5370272;a[1318987]=5370228;a[1318990]=5370216;a[1318993]=5370188;a[1318996]=5370104;a[1318999]=5370072;a[1319002]=5370048;a[1319005]=5370020;a[1319008]=5369984;a[1319011]=5369972;a[1319014]=5369960;a[1319017]=5369860;a[1319020]=5369848;a[1319023]=5369828;a[1319026]=5369776;a[1319029]=5369764;a[1319032]=5369740;a[1319035]=5369720;a[1319038]=5369708;a[1319041]=5369696;a[1319044]=5369684;a[1319047]=5369588;a[1319050]=5369504;a[1319053]=5369492;a[1319056]=5369452;a[1319059]=5369440;a[1319062]=5369408;a[1319065]=5369392;a[1319068]=5369380;a[1319071]=5369368;a[1319074]=5369356;a[1319077]=5369288;a[1319080]=5369276;a[1319083]=5369264;a[1319086]=5369204;a[1319089]=5369192;a[1319092]=5369168;a[1319095]=5369148;a[1319098]=5369136;a[1319101]=5369056;a[1319104]=5369044;a[1319107]=5368992;a[1319110]=5368980;a[1319113]=5368968;a[1319116]=5368948;a[1319119]=5368936;a[1319122]=5368912;a[1319125]=5368892;a[1319128]=5368880;a[1319131]=5368868;a[1319134]=5368856;a[1319137]=5368808;a[1319140]=5368796;a[1319143]=5368784;a[1319146]=5368752;a[1319149]=5368740;a[1319152]=5368716;a[1319155]=5368696;a[1319158]=5368684;a[1319161]=5368672;a[1319164]=5368652;a[1319167]=5368596;a[1319170]=5368584;a[1319173]=5368572;a[1319176]=5368548;a[1319179]=5368536;a[1319182]=5368444;a[1319185]=5368424;a[1319188]=5368412;a[1319191]=5368400;a[1319194]=5368388;a[1319197]=5368336;a[1319200]=5368324;a[1319203]=5368312;a[1319206]=5368296;a[1319209]=5368284;a[1319212]=5368260;a[1319215]=5368240;a[1319218]=5368228;a[1319221]=5368216;a[1319224]=5368204;a[1319227]=5368176;a[1319230]=5368164;a[1319233]=5368152;a[1319236]=5368132;a[1319239]=5368120;a[1319242]=5368096;a[1319245]=5368076;a[1319248]=5368064;a[1319251]=5368044;a[1319254]=5368012;a[1319257]=5367976;a[1319260]=5367964;a[1319263]=5367952;a[1319266]=5367940;a[1319269]=5367928;a[1319272]=5367904;a[1319275]=5367888;a[1319278]=5367876;a[1319281]=5367864;a[1319284]=5367840;a[1319287]=5367812;a[1319290]=5367800;a[1319293]=5367684;a[1319296]=5367668;a[1319299]=5367632;a[1319302]=5367608;a[1319305]=5367584;a[1319308]=5367544;a[1319311]=5367532;a[1319314]=5367520;a[1319317]=5367500;a[1319320]=5367488;a[1319323]=5367468;a[1319326]=5367456;a[1319329]=5367444;a[1319332]=5367420;a[1319335]=5367400;a[1319338]=5367388;a[1319341]=5367376;a[1319344]=5367364;a[1319347]=5367336;a[1319350]=5367304;a[1319353]=5367236;a[1319356]=5367224;a[1319359]=5367212;a[1319362]=5367188;a[1319365]=5367160;a[1319368]=5367148;a[1319371]=5367116;a[1319374]=5367104;a[1319377]=5367092;a[1319380]=5367080;a[1319383]=5367068;a[1319386]=5367056;a[1319389]=5367044;a[1319392]=5367020;a[1319395]=5366996;a[1319398]=5366980;a[1319401]=5366912;a[1319404]=5366896;a[1319407]=5366848;a[1319410]=5366832;a[1319413]=5366816;a[1319416]=5366800;a[1319419]=5366784;a[1319422]=5366756;a[1319425]=5366732;a[1319428]=5366716;a[1319431]=5366700;a[1319434]=5366684;a[1319437]=5366644;a[1319440]=5366624;a[1319443]=5366608;a[1319446]=5366592;a[1319449]=5366576;a[1319452]=5366548;a[1319455]=5366524;a[1319458]=5366508;a[1319461]=5366492;a[1319464]=5366464;a[1319467]=5366420;a[1319470]=5366404;a[1319473]=5366388;a[1319476]=5366372;a[1319479]=5366356;a[1319482]=5366328;a[1319485]=5366208;a[1319488]=5366192;a[1319491]=5366176;a[1319494]=5366160;a[1319497]=5366116;a[1319500]=5366100;a[1319503]=5366068;a[1319506]=5366052;a[1319509]=5366036;a[1319512]=5366008;a[1319515]=5365976;a[1319518]=5365960;a[1319521]=5365944;a[1319524]=5365928;a[1319527]=5365896;a[1319530]=5365880;a[1319533]=5365864;a[1319536]=5365848;a[1319539]=5365832;a[1319542]=5365804;a[1319545]=5365780;a[1319548]=5365764;a[1319551]=5365736;a[1319554]=5365680;a[1319557]=5365632;a[1319560]=5365616;a[1319563]=5365600;a[1319566]=5365584;a[1319569]=5365568;a[1319572]=5365540;a[1319575]=5365516;a[1319578]=5365500;a[1319581]=5365484;a[1319584]=5365468;a[1319587]=5365408;a[1319590]=5365396;a[1319593]=5365344;a[1319596]=5365260;a[1319599]=5365224;a[1319602]=5365200;a[1319605]=5365156;a[1319608]=5365132;a[1319611]=5365116;a[1319614]=5365100;a[1319617]=5365072;a[1319620]=5365056;a[1319623]=5365024;a[1319626]=5365008;a[1319629]=5364992;a[1319632]=5364968;a[1319635]=5364944;a[1319638]=5364928;a[1319641]=5364912;a[1319644]=5364900;a[1319647]=5364872;a[1319650]=5364856;a[1319653]=5364836;a[1319656]=5364784;a[1319659]=5364768;a[1319662]=5364740;a[1319665]=5364712;a[1319668]=5364692;a[1319671]=5364672;a[1319674]=5364648;a[1319677]=5364624;a[1319680]=5364608;a[1319683]=5364592;a[1319686]=5364572;a[1319689]=5364552;a[1319692]=5364520;a[1319695]=5364492;a[1319698]=5364472;a[1319701]=5364456;a[1319704]=5364440;a[1319707]=5364384;a[1319710]=5364368;a[1319713]=5364352;a[1319716]=5364336;a[1319719]=5364320;a[1319722]=5364288;a[1319725]=5364260;a[1319728]=5364244;a[1319731]=5364228;a[1319734]=5364212;a[1319737]=5364188;a[1319740]=5364172;a[1319743]=5364156;a[1319746]=5364144;a[1319749]=5364124;a[1319752]=5364100;a[1319755]=5364076;a[1319758]=5364060;a[1319761]=5364044;a[1319764]=5364032;a[1319767]=5364e3;a[1319770]=5363988;a[1319773]=5363972;a[1319776]=5363952;a[1319779]=5363936;a[1319782]=5363904;a[1319785]=5363880;a[1319788]=5363748;a[1319791]=5363732;a[1319794]=5363704;a[1319797]=5363644;a[1319800]=5363628;a[1319803]=5363612;a[1319806]=5363564;a[1319809]=5363544;a[1319812]=5363512;a[1319815]=5363472;a[1319818]=5363452;a[1319821]=5363432;a[1319824]=5363412;a[1319827]=5363364;a[1319830]=5363352;a[1319833]=5363336;a[1319836]=5363324;a[1319839]=5363308;a[1319842]=5363284;a[1319845]=5363252;a[1319848]=5363236;a[1319851]=5363188;a[1319854]=5363132;a[1319857]=5363072;a[1319860]=5363048;a[1319863]=5363024;a[1319866]=5363e3;a[1319869]=5362976;a[1319872]=5362936;a[1319875]=5362912;a[1319878]=5362884;a[1319881]=5362868;a[1319884]=5362848;a[1319887]=5362812;a[1319890]=5362796;a[1319893]=5362784;a[1319896]=5362760;a[1319899]=5362736;a[1319902]=5362708;a[1319905]=5362688;a[1319908]=5362628;a[1319911]=5362612;a[1319914]=5362592;a[1319917]=5362556;a[1319920]=5362540;a[1319923]=5362512;a[1319926]=5362500;a[1319929]=5362488;a[1319932]=5362464;a[1319935]=5362448;a[1319938]=5362436;a[1319941]=5362424;a[1319944]=5362408;a[1319947]=5362376;a[1319950]=5362340;a[1319953]=5362328;a[1319956]=5362312;a[1319959]=5362288;a[1319962]=5362260;a[1319965]=5362232;a[1319968]=5362220;a[1319971]=5362204;a[1319974]=5362188;a[1319977]=5362116;a[1319980]=5362100;a[1319983]=5362088;a[1319986]=5362068;a[1319989]=5362052;a[1319992]=5362028;a[1319995]=5362012;a[1319998]=5361996;a[1320001]=5361984;a[1320004]=5361956;a[1320007]=5361896;a[1320010]=5361884;a[1320013]=5361872;a[1320016]=5361856;a[1320019]=5361844;a[1320022]=5361812;a[1320025]=5361792;a[1320028]=5361780;a[1320031]=5361768;a[1320034]=5361756;a[1320037]=5361716;a[1320040]=5361704;a[1320043]=5361692;a[1320046]=5361680;a[1320049]=5361668;a[1320052]=5361644;a[1320055]=5361624;a[1320058]=5361612;a[1320061]=5361600;a[1320064]=5361588;a[1320067]=5361548;a[1320070]=5361536;a[1320073]=5361524;a[1320076]=5361512;a[1320079]=5361500;a[1320082]=5361476;a[1320085]=5361456;a[1320088]=5361444;a[1320091]=5361396;a[1320094]=5361384;a[1320097]=5361344;a[1320100]=5361332;a[1320103]=5361320;a[1320106]=5361308;a[1320109]=5361296;a[1320112]=5361272;a[1320115]=5361244;a[1320118]=5361232;a[1320121]=5361220;a[1320124]=5361208;a[1320127]=5361164;a[1320130]=5361152;a[1320133]=5361140;a[1320136]=5361128;a[1320139]=5361116;a[1320142]=5361092;a[1320145]=5361072;a[1320148]=5361060;a[1320151]=5361024;a[1320154]=5361004;a[1320157]=5360932;a[1320160]=5360920;a[1320163]=5360908;a[1320166]=5360896;a[1320169]=5360872;a[1320172]=5360848;a[1320175]=5360828;a[1320178]=5360816;a[1320181]=5360804;a[1320184]=5360792;a[1320187]=5360748;a[1320190]=5360736;a[1320193]=5360708;a[1320196]=5360688;a[1320199]=5360652;a[1320202]=5360628;a[1320205]=5360608;a[1320208]=5360588;a[1320211]=5360576;a[1320214]=5360564;a[1320217]=5360520;a[1320220]=5360508;a[1320223]=5360496;a[1320226]=5360484;a[1320229]=5360472;a[1320232]=5360448;a[1320235]=5360428;a[1320238]=5360416;a[1320241]=5360392;a[1320244]=5360380;a[1320247]=5360336;a[1320250]=5360320;a[1320253]=5360308;a[1320256]=5360296;a[1320259]=5360284;a[1320262]=5360248;a[1320265]=5360220;a[1320268]=5360208;a[1320271]=5360196;a[1320274]=5360184;a[1320277]=5360148;a[1320280]=5360128;a[1320283]=5360116;a[1320286]=5360104;a[1320289]=5360092;a[1320292]=5360068;a[1320295]=5360048;a[1320298]=5360036;a[1320301]=5360024;a[1320304]=5360008;a[1320307]=5359884;a[1320310]=5359872;a[1320313]=5359860;a[1320316]=5359848;a[1320319]=5359836;a[1320322]=5359812;a[1320325]=5359792;a[1320328]=5359780;a[1320331]=5359768;a[1320334]=5359756;a[1320337]=5359724;a[1320340]=5359712;a[1320343]=5359700;a[1320346]=5359688;a[1320349]=5359676;a[1320352]=5359652;a[1320355]=5359632;a[1320358]=5359620;a[1320361]=5359608;a[1320364]=5359596;a[1320367]=5359552;a[1320370]=5359540;a[1320373]=5359528;a[1320376]=5359516;a[1320379]=5359504;a[1320382]=5359480;a[1320385]=5359464;a[1320388]=5359452;a[1320391]=5359440;a[1320394]=5359352;a[1320397]=5359312;a[1320400]=5359300;a[1320403]=5359288;a[1320406]=5359276;a[1320409]=5359264;a[1320412]=5359240;a[1320415]=5359212;a[1320418]=5359200;a[1320421]=5359188;a[1320424]=5359176;a[1320427]=5359120;a[1320430]=5359108;a[1320433]=5359096;a[1320436]=5359084;a[1320439]=5359072;a[1320442]=5359048;a[1320445]=5359028;a[1320448]=5359016;a[1320451]=5359004;a[1320454]=5358992;a[1320457]=5358900;a[1320460]=5358888;a[1320463]=5358876;a[1320466]=5358864;a[1320469]=5358852;a[1320472]=5358828;a[1320475]=5358812;a[1320478]=5358800;a[1320481]=5358788;a[1320484]=5358728;a[1320487]=5358672;a[1320490]=5358660;a[1320493]=5358608;a[1320496]=5358588;a[1320499]=5358576;a[1320502]=5358552;a[1320505]=5358536;a[1320508]=5358524;a[1320511]=5358512;a[1320514]=5358496;a[1320517]=5358460;a[1320520]=5358448;a[1320523]=5358436;a[1320526]=5358400;a[1320529]=5352344;a[1320532]=5345416;a[1320535]=5358364;a[1320538]=5358348;a[1320541]=5358332;a[1320544]=5358316;a[1320547]=5338676;a[1320550]=5358264;a[1320553]=5358252;a[1320556]=5358240;a[1320559]=5358228;a[1320562]=5335880;a[1320565]=5358192;a[1320568]=5358184;a[1320571]=5358176;a[1320574]=5358168;a[1320577]=5333016;a[1320580]=5330020;a[1320583]=5358100;a[1320586]=5358092;a[1320589]=5358084;a[1320592]=5358076;a[1320595]=5374748;a[1320598]=5378328;a[1320601]=5372240;a[1320604]=5358052;a[1320607]=5358008;a[1320610]=5357980;a[1320613]=5357972;a[1320616]=5372852;a[1320619]=5370284;a[1320622]=5357964;a[1320625]=5357936;a[1320628]=5357928;a[1320631]=5357920;a[1320634]=5367852;a[1320637]=5357884;a[1320640]=5357852;a[1320643]=5357840;a[1320646]=5357828;a[1320649]=5365456;a[1320652]=5357816;a[1320655]=5357784;a[1320658]=5357772;a[1320661]=5357760;a[1320664]=5362836;a[1320667]=5357736;a[1320670]=5357704;a[1320673]=5357692;a[1320676]=5357680;a[1320679]=5360780;a[1320682]=5357668;a[1320685]=5357636;a[1320688]=5357624;a[1320691]=5357612;a[1320694]=5358704;a[1320697]=5357556;a[1320700]=5357536;a[1320703]=5357528;a[1320706]=5357520;a[1320709]=5357072;a[1320712]=5355444;a[1320715]=5357488;a[1320718]=5357476;a[1320721]=5357464;a[1320724]=5357452;a[1320727]=5353880;a[1320730]=5352172;a[1320733]=5357400;a[1320736]=5357392;a[1320739]=5357384;a[1320742]=5357376;a[1320745]=5348204;a[1320748]=5357348;a[1320751]=5357332;a[1320754]=5357316;a[1320757]=5357228;a[1320760]=5347296;a[1320763]=5346396;a[1320766]=5345768;a[1320769]=5357208;a[1320772]=5357192;a[1320775]=5357160;a[1320778]=5357144;a[1320781]=5345364;a[1320784]=5357132;a[1320787]=5357060;a[1320790]=5357036;a[1320793]=5357020;a[1320796]=5344968;a[1320799]=5356996;a[1320802]=5356984;a[1320805]=5356952;a[1320808]=5356936;a[1320811]=5344256;a[1320814]=5343928;a[1320817]=5356820;a[1320820]=5356804;a[1320823]=5356788;a[1320826]=5356756;a[1320829]=5343600;a[1320832]=5343244;a[1320835]=5356708;a[1320838]=5356692;a[1320841]=5356676;a[1320844]=5356660;a[1320847]=5342820;a[1320850]=5342552;a[1320853]=5342220;a[1320856]=5341860;a[1320859]=5356600;a[1320862]=5356588;a[1320865]=5356548;a[1320868]=5356536;a[1320871]=5341508;a[1320874]=5356520;a[1320877]=5356488;a[1320880]=5356456;a[1320883]=5356440;a[1320886]=5341164;a[1320889]=5340808;a[1320892]=5340508;a[1320895]=5356344;a[1320898]=5356332;a[1320901]=5356320;a[1320904]=5356308;a[1320907]=5340228;a[1320910]=5356240;a[1320913]=5356228;a[1320916]=5356216;a[1320919]=5356204;a[1320922]=5339920;a[1320925]=5339652;a[1320928]=5338940;a[1320931]=5338656;a[1320934]=5338340;a[1320937]=5356148;a[1320940]=5356128;a[1320943]=5356120;a[1320946]=5356112;a[1320949]=5338084;a[1320952]=5356100;a[1320955]=5356072;a[1320958]=5356060;a[1320961]=5356048;a[1320964]=5367180;a[1320967]=5356028;a[1320970]=5356020;a[1320973]=5356012;a[1320976]=5356004;a[1320979]=5355996;a[1320982]=5355988;a[1320985]=5355960;a[1320988]=5355952;a[1320991]=5355944;a[1320994]=5355936;a[1320997]=5355904;a[1321e3]=5355888;a[1321003]=5355880;a[1321006]=5355872;a[1321009]=5355864;a[1321012]=5355856;a[1321015]=5355820;a[1321018]=5355812;a[1321021]=5355804;a[1321024]=5355796;a[1321027]=5355756;a[1321030]=5355740;a[1321033]=5355732;a[1321036]=5355724;a[1321039]=5355716;a[1321042]=5355708;a[1321045]=5355680;a[1321048]=5355672;a[1321051]=5355664;a[1321054]=5355656;a[1321057]=5355584;a[1321060]=5355552;a[1321063]=5355544;a[1321066]=5355536;a[1321069]=5355528;a[1321072]=5355520;a[1321075]=5355496;a[1321078]=5355488;a[1321081]=5355480;a[1321084]=5355472;a[1321087]=5355436;a[1321090]=5355420;a[1321093]=5355408;a[1321096]=5355392;a[1321099]=5355384;a[1321102]=5355376;a[1321105]=5355312;a[1321108]=5355300;a[1321111]=5355292;a[1321114]=5355280;a[1321117]=5355216;a[1321120]=5355204;a[1321123]=5355196;a[1321126]=5355172;a[1321129]=5355164;a[1321132]=5355156;a[1321135]=5355128;a[1321138]=5355120;a[1321141]=5355112;a[1321144]=5355104;a[1321147]=5355084;a[1321150]=5355064;a[1321153]=5355044;a[1321156]=5355036;a[1321159]=5355028;a[1321162]=5355020;a[1321165]=5354984;a[1321168]=5354976;a[1321171]=5354968;a[1321174]=5354960;a[1321177]=5354936;a[1321180]=5354912;a[1321183]=5354904;a[1321186]=5354896;a[1321189]=5354864;a[1321192]=5354856;a[1321195]=5354828;a[1321198]=5354820;a[1321201]=5354812;a[1321204]=5354804;a[1321207]=5354772;a[1321210]=5354736;a[1321213]=5354728;a[1321216]=5354720;a[1321219]=5354712;a[1321222]=5354704;a[1321225]=5354676;a[1321228]=5354668;a[1321231]=5354660;a[1321234]=5354652;a[1321237]=5354624;a[1321240]=5354600;a[1321243]=5354592;a[1321246]=5354584;a[1321249]=5354576;a[1321252]=5354568;a[1321255]=5354540;a[1321258]=5354532;a[1321261]=5354524;a[1321264]=5354516;a[1321267]=5354492;a[1321270]=5364732;a[1321273]=5354428;a[1321276]=5354420;a[1321279]=5354412;a[1321282]=5354404;a[1321285]=5337272;a[1321288]=5337040;a[1321291]=5354376;a[1321294]=5354368;a[1321297]=5354348;a[1321300]=5354320;a[1321303]=5354304;a[1321306]=5354296;a[1321309]=5354288;a[1321312]=5354280;a[1321315]=5354252;a[1321318]=5354236;a[1321321]=5354228;a[1321324]=5354220;a[1321327]=5354176;a[1321330]=5354160;a[1321333]=5354152;a[1321336]=5354144;a[1321339]=5354136;a[1321342]=5354128;a[1321345]=5354104;a[1321348]=5354096;a[1321351]=5354088;a[1321354]=5354080;a[1321357]=5354032;a[1321360]=5353972;a[1321363]=5353964;a[1321366]=5353956;a[1321369]=5353948;a[1321372]=5353940;a[1321375]=5353912;a[1321378]=5353904;a[1321381]=5353896;a[1321384]=5353888;a[1321387]=5353872;a[1321390]=5353864;a[1321393]=5353848;a[1321396]=5353840;a[1321399]=5353832;a[1321402]=5353824;a[1321405]=5353796;a[1321408]=5353784;a[1321411]=5353776;a[1321414]=5353768;a[1321417]=5353736;a[1321420]=5353728;a[1321423]=5353720;a[1321426]=5353704;a[1321429]=5353696;a[1321432]=5353688;a[1321435]=5353660;a[1321438]=5353652;a[1321441]=5353644;a[1321444]=5353636;a[1321447]=5353592;a[1321450]=5353584;a[1321453]=5353556;a[1321456]=5353548;a[1321459]=5353540;a[1321462]=5353532;a[1321465]=5353500;a[1321468]=5353492;a[1321471]=5353484;a[1321474]=5353432;a[1321477]=5353392;a[1321480]=5353336;a[1321483]=5353328;a[1321486]=5353320;a[1321489]=5353312;a[1321492]=5353304;a[1321495]=5353276;a[1321498]=5353268;a[1321501]=5353260;a[1321504]=5353236;a[1321507]=5353184;a[1321510]=5353164;a[1321513]=5353156;a[1321516]=5353148;a[1321519]=5353140;a[1321522]=5353132;a[1321525]=5353104;a[1321528]=5353096;a[1321531]=5353088;a[1321534]=5353080;a[1321537]=5353016;a[1321540]=5353008;a[1321543]=5353e3;a[1321546]=5352992;a[1321549]=5352984;a[1321552]=5352976;a[1321555]=5352948;a[1321558]=5352940;a[1321561]=5352932;a[1321564]=5352924;a[1321567]=5352860;a[1321570]=5352852;a[1321573]=5352844;a[1321576]=5352836;a[1321579]=5352828;a[1321582]=5352820;a[1321585]=5352792;a[1321588]=5352784;a[1321591]=5352776;a[1321594]=5336768;a[1321597]=5352752;a[1321600]=5352740;a[1321603]=5352728;a[1321606]=5352716;a[1321609]=5336524;a[1321612]=5352704;a[1321615]=5352672;a[1321618]=5352660;a[1321621]=5352648;a[1321624]=5336180;a[1321627]=5352612;a[1321630]=5352600;a[1321633]=5352588;a[1321636]=5352576;a[1321639]=5335864;a[1321642]=5365092;a[1321645]=5335520;a[1321648]=5352548;a[1321651]=5352540;a[1321654]=5352512;a[1321657]=5352376;a[1321660]=5335276;a[1321663]=5352364;a[1321666]=5352356;a[1321669]=5352336;a[1321672]=5352328;a[1321675]=5334980;a[1321678]=5334720;a[1321681]=5352292;a[1321684]=5352228;a[1321687]=5352156;a[1321690]=5352140;a[1321693]=5334464;a[1321696]=5334144;a[1321699]=5352108;a[1321702]=5352092;a[1321705]=5352060;a[1321708]=5352036;a[1321711]=5333904;a[1321714]=5352024;a[1321717]=5351956;a[1321720]=5351944;a[1321723]=5351932;a[1321726]=5333660;a[1321729]=5333248;a[1321732]=5351900;a[1321735]=5351872;a[1321738]=5351860;a[1321741]=5351848;a[1321744]=5351832;a[1321747]=5351796;a[1321750]=5351780;a[1321753]=5351744;a[1321756]=5351728;a[1321759]=5332980;a[1321762]=5332688;a[1321765]=5332120;a[1321768]=5331796;a[1321771]=5351688;a[1321774]=5351668;a[1321777]=5351656;a[1321780]=5351644;a[1321783]=5331548;a[1321786]=5351628;a[1321789]=5351612;a[1321792]=5351596;a[1321795]=5351504;a[1321798]=5331160;a[1321801]=5330908;a[1321804]=5351488;a[1321807]=5351460;a[1321810]=5351428;a[1321813]=5351412;a[1321816]=5351388;a[1321819]=5330548;a[1321822]=5330204;a[1321825]=533e4;a[1321828]=5351352;a[1321831]=5351336;a[1321834]=5351320;a[1321837]=5351292;a[1321840]=5329716;a[1321843]=5351264;a[1321846]=5351248;a[1321849]=5351232;a[1321852]=5351216;a[1321855]=5329284;a[1321858]=5329056;a[1321861]=5328788;a[1321864]=5351184;a[1321867]=5351172;a[1321870]=5351160;a[1321873]=5351148;a[1321876]=5360240;a[1321879]=5351140;a[1321882]=5351132;a[1321885]=5351104;a[1321888]=5351096;a[1321891]=5328244;a[1321894]=5327988;a[1321897]=5327652;a[1321900]=5351052;a[1321903]=5351036;a[1321906]=5351020;a[1321909]=5350992;a[1321912]=5327396;a[1321915]=5350960;a[1321918]=5350944;a[1321921]=5350928;a[1321924]=5350912;a[1321927]=5326980;a[1321930]=5326740;a[1321933]=5326504;a[1321936]=5326184;a[1321939]=5325980;a[1321942]=5325760;a[1321945]=5325492;a[1321948]=5378776;a[1321951]=5350852;a[1321954]=5350836;a[1321957]=5350712;a[1321960]=5350688;a[1321963]=5378504;a[1321966]=5378304;a[1321969]=5350672;a[1321972]=5350656;a[1321975]=5350620;a[1321978]=5350604;a[1321981]=5358208;a[1321984]=5350592;a[1321987]=5341724;a[1321990]=5377688;a[1321993]=5377248;a[1321996]=5350560;a[1321999]=5350544;a[1322002]=5350532;a[1322005]=5350408;a[1322008]=5377016;a[1322011]=5350396;a[1322014]=5350352;a[1322017]=5350344;a[1322020]=5350336;a[1322023]=5376792;a[1322026]=5350308;a[1322029]=5350296;a[1322032]=5350284;a[1322035]=5350252;a[1322038]=5376536;a[1322041]=5350244;a[1322044]=5350236;a[1322047]=5350220;a[1322050]=5350212;a[1322053]=5376208;a[1322056]=5375868;a[1322059]=5350200;a[1322062]=5350188;a[1322065]=5350148;a[1322068]=5350136;a[1322071]=5375556;a[1322074]=5350120;a[1322077]=5350104;a[1322080]=5350088;a[1322083]=5350072;a[1322086]=5375252;a[1322089]=5350056;a[1322092]=5350040;a[1322095]=5350004;a[1322098]=5349980;a[1322101]=5374920;a[1322104]=5374612;a[1322107]=5349968;a[1322110]=5349940;a[1322113]=5349928;a[1322116]=5349916;a[1322119]=5374260;a[1322122]=5374040;a[1322125]=5349888;a[1322128]=5349880;a[1322131]=5349872;a[1322134]=5349864;a[1322137]=5373860;a[1322140]=5349844;a[1322143]=5349836;a[1322146]=5349828;a[1322149]=5349820;a[1322152]=5373656;a[1322155]=5355e3;a[1322158]=5349792;a[1322161]=5349784;a[1322164]=5349776;a[1322167]=5349768;a[1322170]=5353516;a[1322173]=5349760;a[1322176]=5349752;a[1322179]=5349744;a[1322182]=5349736;a[1322185]=5372804;a[1322188]=5349704;a[1322191]=5349692;a[1322194]=5349672;a[1322197]=5349660;a[1322200]=5372576;a[1322203]=5349648;a[1322206]=5349636;a[1322209]=5349624;a[1322212]=5349604;a[1322215]=5372344;a[1322218]=5372072;a[1322221]=5349576;a[1322224]=5349568;a[1322227]=5349560;a[1322230]=5349552;a[1322233]=5371856;a[1322236]=5371628;a[1322239]=5349540;a[1322242]=5349528;a[1322245]=5349496;a[1322248]=5349484;a[1322251]=5371336;a[1322254]=5349472;a[1322257]=5349336;a[1322260]=5349324;a[1322263]=5349312;a[1322266]=5371056;a[1322269]=5349304;a[1322272]=5349296;a[1322275]=5349272;a[1322278]=5349264;a[1322281]=5370512;a[1322284]=5349252;a[1322287]=5349228;a[1322290]=5349216;a[1322293]=5349204;a[1322296]=5370240;a[1322299]=5349184;a[1322302]=5349172;a[1322305]=5349144;a[1322308]=5349124;a[1322311]=5369872;a[1322314]=5349112;a[1322317]=5349096;a[1322320]=5349084;a[1322323]=5349072;a[1322326]=5369600;a[1322329]=5369300;a[1322332]=5349056;a[1322335]=5349028;a[1322338]=5349020;a[1322341]=5349012;a[1322344]=5369004;a[1322347]=5348996;a[1322350]=5348980;a[1322353]=5348952;a[1322356]=5348936;a[1322359]=5368820;a[1322362]=5348924;a[1322365]=5348892;a[1322368]=5348872;a[1322371]=5348860;a[1322374]=5368608;a[1322377]=5348852;a[1322380]=5348844;a[1322383]=5348836;a[1322386]=5348828;a[1322389]=5368188;a[1322392]=5348816;a[1322395]=5348792;a[1322398]=5348780;a[1322401]=5348748;a[1322404]=5367988;a[1322407]=5348740;a[1322410]=5348712;a[1322413]=5348704;a[1322416]=5348696;a[1322419]=5348676;a[1322422]=5367824;a[1322425]=5348644;a[1322428]=5348632;a[1322431]=5348620;a[1322434]=5348608;a[1322437]=5367512;a[1322440]=5348576;a[1322443]=5348564;a[1322446]=5348552;a[1322449]=5348540;a[1322452]=5348528;a[1322455]=5367348;a[1322458]=5348500;a[1322461]=5348492;a[1322464]=5348484;a[1322467]=5348476;a[1322470]=5348884;a[1322473]=5366864;a[1322476]=5348088;a[1322479]=5348468;a[1322482]=5348460;a[1322485]=5348432;a[1322488]=5348424;a[1322491]=5366436;a[1331021]=5253140;a[1331023]=5253100;a[1331025]=5252960;a[1331027]=5252880;a[1331029]=5252840;a[1331031]=5252800;a[1331033]=5252760;a[1331035]=5251472;a[1331037]=5251432;a[1331039]=5251392;a[1331041]=5251352;a[1331043]=5251312;a[1331045]=5251272;a[1331047]=5251232;a[1331049]=5251588;a[1331053]=5252608;a[1331056]=5343308;a[1331057]=5343224;a[1331058]=5361972;a[1331059]=5342544;a[1331060]=5342208;a[1331286]=298;a[1331295]=226;a[1331322]=264;a[1331331]=226;a[1345166]=5377276;a[1345170]=5374328;a[1345174]=5371884;a[1345178]=5369016;a[1345182]=5366876;a[1345186]=5364424;a[1345190]=5361928;a[1345194]=5359896;a[1345198]=5341724;a[1345202]=5356268;a[1345206]=5354764;a[1345210]=5353172;a[1345214]=5351444;a[1345218]=5349952;a[1345222]=5348720;a[1345226]=5348040;a[1345230]=5347540;a[1345234]=5347020;a[1345238]=5346596;a[1345242]=5346224;a[1345246]=5345924;a[1345250]=5345580;a[1345254]=5345168;a[1345258]=5344816;a[1345262]=5344516;a[1345266]=5344160;a[1345270]=5343764;a[1345274]=5343396;a[1345278]=5342976;a[1345282]=5342684;a[1345286]=5342404;a[1345290]=5342032;a[1345294]=5341688;a[1345298]=5341304;a[1345302]=5340956;a[1345306]=5348196;a[1345310]=5340380;a[1345314]=5343944;a[1345381]=5367788;a[1345382]=5374688;a[1345383]=5353244;a[1345404]=228;a[1345597]=5363500;a[1345601]=5355836;a[1345603]=5370952;a[1345605]=5349588;a[1345607]=5377276;a[1345609]=5354764;a[1345611]=5345064;a[1345613]=5341724;a[1345615]=5333728;a[1345617]=5330664;a[1345619]=5328084;a[1345621]=5378868;a[1345625]=5346428;a[1345627]=5345784;a[1345629]=5369404;a[1345631]=5334736;a[1345633]=5366e3;a[1345637]=5361264;a[1345640]=5359232;a[1345643]=5368056;a[1345646]=5341724;var yt,ta={Gb:7,j:13,Hb:98,Ib:99,Jb:97,Kb:11,Lb:114,l:9,Mb:74,Nb:16,Ob:125,Pb:10,Qb:103,Rb:111,Sb:104,Tb:35,Ub:89,Vb:33,Wb:122,pa:17,Xb:14,Yb:27,Zb:113,$b:43,ac:84,bc:115,cc:4,i:22,r:5,dc:106,R:21,Ka:40,ec:24,fc:31,gc:90,hc:72,ic:36,jc:100,kc:102,lc:101,mc:23,nc:105,oc:61,pc:19,S:2,qc:8,rc:37,sc:67,tc:12,uc:42,vc:92,wc:28,xc:63,yc:60,zc:38,Ac:107,qa:20,Bc:39,Cc:131,Dc:88,Ec:95,Fc:25,ra:6,Gc:75,Hc:130,Ic:1,Jc:32,Kc:71,Lc:93,Mc:91,sa:34,Nc:30,Oc:29,Pc:3,Qc:116,Rc:62,Sc:110,Tc:26,Uc:11,Vc:18},vh=d(1,"i32*",ce);Fe=d(1,"i32*",ce);Qa=d(1,"i32*",ce);var At=d(1,"i32*",ce),N={Ta:"/",hb:2,b:[Ac],Ca:qc,cb:(function(a,b){for(var c=a[0],d=1;d<a.length;d++){"/"!=c[c.length-1]&&(c+="/"),c+=a[d]}b&&"/"==c[0]&&(c=c.substr(1));return c}),ta:(function(a,b){if("string"!==typeof a){return Ac}b===Wb&&(b=N.Ta);a&&"/"==a[0]&&(b="");for(var c=(b+"/"+a).split("/").reverse(),d=[""];c.length;){var f=c.pop();""==f||"."==f||(".."==f?1<d.length&&d.pop():d.push(f))}return 1==d.length?"/":d.join("/")}),C:(function(a,b,c){var d={ab:Ud,H:Ud,error:0,name:Ac,path:Ac,object:Ac,L:Ud,ia:Ac,v:Ac},a=N.ta(a);if("/"==a){d.ab=qc,d.H=d.L=qc,d.name="/",d.path=d.ia="/",d.object=d.v=N.root}else{if(a!==Ac){for(var c=c||0,a=a.slice(1).split("/"),f=N.root,h=[""];a.length;){1==a.length&&f.g&&(d.L=qc,d.ia=1==h.length?"/":h.join("/"),d.v=f,d.name=a[0]);var i=a.shift();if(f.g){if(f.N){if(!f.c.hasOwnProperty(i)){d.error=ta.S;break}}else{d.error=ta.j;break}}else{d.error=ta.qa;break}f=f.c[i];if(f.link&&!(b&&0==a.length)){if(40<c){d.error=ta.Ka;break}d=N.ta(f.link,h.join("/"));d=N.C([d].concat(a).join("/"),b,c+1);break}h.push(i);0==a.length&&(d.H=qc,d.path=h.join("/"),d.object=f)}}}return d}),ba:(function(a,b){N.ya();var c=N.C(a,b);if(c.H){return c.object}Ha(c.error);return Ac}),va:(function(a,b,c,d,f){a||(a="/");"string"===typeof a&&(a=N.ba(a));a||(Ha(ta.j),Ob(Error("Parent path must exist.")));a.g||(Ha(ta.qa),Ob(Error("Parent must be a folder.")));!a.write&&!N.Ca&&(Ha(ta.j),Ob(Error("Parent folder must be writeable.")));if(!b||"."==b||".."==b){Ha(ta.S),Ob(Error("Name must not be empty."))}a.c.hasOwnProperty(b)&&(Ha(ta.pa),Ob(Error("Can't overwrite object.")));a.c[b]={N:d===Wb?qc:d,write:f===Wb?Ud:f,timestamp:Date.now(),ga:N.hb++};for(var h in c){c.hasOwnProperty(h)&&(a.c[b][h]=c[h])}return a.c[b]}),G:(function(a,b,c,d){return N.va(a,b,{g:qc,e:Ud,c:{}},c,d)}),wa:(function(a,b,c,d){a=N.ba(a);a===Ac&&Ob(Error("Invalid parent."));for(b=b.split("/").reverse();b.length;){var f=b.pop();f&&(a.c.hasOwnProperty(f)||N.G(a,f,c,d),a=a.c[f])}return a}),F:(function(a,b,c,d,f){c.g=Ud;return N.va(a,b,c,d,f)}),$:(function(a,b,c,d,f){if("string"===typeof c){for(var h=Array(c.length),i=0,k=c.length;i<k;++i){h[i]=c.charCodeAt(i)}c=h}c={e:Ud,c:c.subarray?c.subarray(0):c};return N.F(a,b,c,d,f)}),Qa:(function(a,b,c,d,f){if("undefined"!==typeof XMLHttpRequest){mg||Ob("Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc");var h=(function(a,b){this.length=b;this.ua=a;this.D=[]});h.prototype.get=(function(a){if(!(a>this.length-1||0>a)){var b=a%q;return this.Ya(Math.floor(a/q))[b]}});h.prototype.pb=(function(a){this.Ya=a});var i=new XMLHttpRequest;i.open("HEAD",c,Ud);i.send(Ac);200<=i.status&&300>i.status||304===i.status||Ob(Error("Couldn't load "+c+". Status: "+i.status));var k=Number(i.getResponseHeader("Content-length")),n,q=1048576;if(!((n=i.getResponseHeader("Accept-Ranges"))&&"bytes"===n)){q=k}var m=new h(q,k);m.pb((function(a){var b=a*m.ua,d=(a+1)*m.ua-1,d=Math.min(d,k-1);if("undefined"===typeof m.D[a]){var e=m.D;b>d&&Ob(Error("invalid range ("+b+", "+d+") or no bytes requested!"));d>k-1&&Ob(Error("only "+k+" bytes available! programmer error!"));var f=new XMLHttpRequest;f.open("GET",c,Ud);k!==q&&f.setRequestHeader("Range","bytes="+b+"-"+d);"undefined"!=typeof Uint8Array&&(f.responseType="arraybuffer");f.overrideMimeType&&f.overrideMimeType("text/plain; charset=x-user-defined");f.send(Ac);200<=f.status&&300>f.status||304===f.status||Ob(Error("Couldn't load "+c+". Status: "+f.status));b=f.response!==Wb?new Uint8Array(f.response||[]):Od(f.responseText||"",qc);e[a]=b}"undefined"===typeof m.D[a]&&Ob(Error("doXHR failed!"));return m.D[a]}));h={e:Ud,c:m}}else{h={e:Ud,url:c}}return N.F(a,b,h,d,f)}),Sa:(function(a,b,c,d,f,h,i,k){function n(c){function g(c){k||N.$(a,b,c,d,f);h&&h();xh("cp "+q)}var r=Ud;H.preloadPlugins.forEach((function(a){!r&&a.canHandle(q)&&(a.handle(c,q,g,(function(){i&&i();xh("cp "+q)})),r=qc)}));r||g(c)}Pb.Va();var q=N.cb([a,b],qc);Ni("cp "+q);"string"==typeof c?Pb.Na(c,(function(a){n(a)}),i):n(c)}),Ra:(function(a,b,c,d,f){return N.F(a,b,{e:Ud,link:c},d,f)}),s:(function(a,b,c,d){!c&&!d&&Ob(Error("A device must have at least one callback defined."));return N.F(a,b,{e:qc,input:c,m:d},Boolean(c),Boolean(d))}),Ba:(function(a){if(a.e||a.g||a.link||a.c){return qc}var b=qc;"undefined"!==typeof XMLHttpRequest&&Ob(Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."));if(H.read){try{a.c=Od(H.read(a.url),qc)}catch(c){b=Ud}}else{Ob(Error("Cannot load without read() or XMLHttpRequest."))}b||Ha(ta.r);return b}),ya:(function(){N.root||(N.root={N:qc,write:qc,g:qc,e:Ud,timestamp:Date.now(),ga:1,c:{}})}),u:(function(b,f,g){function e(a){a===Ac||10===a?(f.M(f.buffer.join("")),f.buffer=[]):f.buffer.push(k.Da(a))}Nc(!N.u.fa,"FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)");N.u.fa=qc;N.ya();var b=b||H.stdin,f=f||H.stdout,g=g||H.stderr,h=qc,i=qc,j=qc;b||(h=Ud,b=(function(){if(!b.Y||!b.Y.length){var a;"undefined"!=typeof window&&"function"==typeof window.prompt?(a=window.prompt("Input: "),a===Ac&&(a=String.fromCharCode(0))):"function"==typeof readline&&(a=readline());a||(a="");b.Y=Od(a+"\n",qc)}return b.Y.shift()}));var k=new fa.U;f||(i=Ud,f=e);f.M||(f.M=H.print);f.buffer||(f.buffer=[]);g||(j=Ud,g=e);g.M||(g.M=H.print);g.buffer||(g.buffer=[]);try{N.G("/","tmp",qc,qc)}catch(n){}var q=N.G("/","dev",qc,qc),m=N.s(q,"stdin",b),w=N.s(q,"stdout",Ac,f),g=N.s(q,"stderr",Ac,g);N.s(q,"tty",b,f);N.b[1]={path:"/dev/stdin",object:m,position:0,p:qc,q:Ud,K:Ud,ha:!h,error:Ud,f:Ud,h:[]};N.b[2]={path:"/dev/stdout",object:w,position:0,p:Ud,q:qc,K:Ud,ha:!i,error:Ud,f:Ud,h:[]};N.b[3]={path:"/dev/stderr",object:g,position:0,p:Ud,q:qc,K:Ud,ha:!j,error:Ud,f:Ud,h:[]};Nc(128>Math.max(vh,Fe,Qa));a[vh>>2]=1;a[Fe>>2]=2;a[Qa>>2]=3;N.wa("/","dev/shm/tmp",qc,qc);for(h=N.b.length;h<Math.max(vh,Fe,Qa)+4;h++){N.b[h]=Ac}N.b[vh]=N.b[1];N.b[Fe]=N.b[2];N.b[Qa]=N.b[3];d([d([0,0,0,0,vh,0,0,0,Fe,0,0,0,Qa,0,0,0],"void*",qe)],"void*",c,At)}),kb:(function(){N.u.fa&&(N.b[2]&&0<N.b[2].object.m.buffer.length&&N.b[2].object.m(10),N.b[3]&&0<N.b[3].object.m.buffer.length&&N.b[3].object.m(10))}),Cd:(function(a){"./"==a.substr(0,2)&&(a=a.substr(2));return a}),gd:(function(a){a=N.C(a);(!a.L||!a.H)&&Ob("Invalid path "+a);delete a.v.c[a.name]})},ud=0,lm={V:1040,bd:0,cd:4,dd:1028,ed:1032,fd:1036},ot={V:68,ub:0,wb:4,xb:8,zb:12,Cb:16,vb:20,Ab:24,Bb:28,la:32,yd:36,Ga:40,zd:44,Fa:48,Ad:52,rb:56,sb:60,Bd:64},om=d(1,"i32*",ce),Fd={},zt,Ti={1:"Operation not permitted",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"Input/output error",6:"No such device or address",8:"Exec format error",9:"Bad file descriptor",10:"No child processes",11:"Resource temporarily unavailable",12:"Cannot allocate memory",13:"Permission denied",14:"Bad address",16:"Device or resource busy",17:"File exists",18:"Invalid cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Inappropriate ioctl for device",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read-only file system",31:"Too many links",32:"Broken pipe",33:"Numerical argument out of domain",34:"Numerical result out of range",35:"Resource deadlock avoided",36:"File name too long",37:"No locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many levels of symbolic links",42:"No message of desired type",43:"Identifier removed",60:"Device not a stream",61:"No data available",62:"Timer expired",63:"Out of streams resources",67:"Link has been severed",71:"Protocol error",72:"Multihop attempted",74:"Bad message",75:"Value too large for defined data type",84:"Invalid or incomplete multibyte or wide character",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Protocol not supported",95:"Operation not supported",97:"Address family not supported by protocol",98:"Address already in use",99:"Cannot assign requested address",100:"Network is down",101:"Network is unreachable",102:"Network dropped connection on reset",103:"Software caused connection abort",104:"Connection reset by peer",105:"No buffer space available",106:"Transport endpoint is already connected",107:"Transport endpoint is not connected",110:"Connection timed out",111:"Connection refused",113:"No route to host",114:"Operation already in progress",115:"Operation now in progress",116:"Stale NFS file handle",122:"Disk quota exceeded",125:"Operation canceled",130:"Owner died",131:"State not recoverable"},Pb={k:{ob:Ac,Ea:Ud,paused:Ud,ud:[],pause:(function(){Pb.k.Ea=qc}),nb:(function(){Pb.k.paused&&(Pb.k.paused=Ud,Pb.k.ob());Pb.k.Ea=Ud}),updateStatus:(function(){if(H.setStatus){var a=H.statusMessage||"Please wait...",b=Pb.k.vd,c=Pb.k.jd;b?b<c?H.setStatus(a+" ("+(c-b)+"/"+c+")"):H.setStatus(a):H.setStatus("")}})},ib:Ud,fb:[],Fd:[],Va:(function(){function a(b){return{jpg:"image/jpeg",jpeg:"image/jpeg",png:"image/png",bmp:"image/bmp",ogg:"audio/ogg",wav:"audio/wav",mp3:"audio/mpeg"}[b.substr(-3)]}if(!Pb.Wa){Pb.Wa=qc;try{new Blob,Pb.J=qc}catch(b){Pb.J=Ud,console.log("warning: no blob constructor, cannot create blobs with mimetypes")}Pb.BlobBuilder="undefined"!=typeof MozBlobBuilder?MozBlobBuilder:"undefined"!=typeof WebKitBlobBuilder?WebKitBlobBuilder:!Pb.J?console.log("warning: no BlobBuilder"):Ac;Pb.T="undefined"!=typeof window?window.URL?window.URL:window.webkitURL:console.log("warning: cannot create object URLs");H.preloadPlugins||(H.preloadPlugins=[]);H.preloadPlugins.push({canHandle:(function(a){return!H.rd&&/\.(jpg|jpeg|png|bmp)$/.exec(a)}),handle:(function(b,c,d,f){var h=Ac;if(Pb.J){try{h=new Blob([b],{type:a(c)})}catch(i){fa.w("Blob constructor present but fails: "+i+"; falling back to blob builder")}}h||(h=new Pb.BlobBuilder,h.append((new Uint8Array(b)).buffer),h=h.getBlob());var s=Pb.T.createObjectURL(h),n=new Image;n.onload=(function(){Nc(n.complete,"Image "+c+" could not be decoded");var a=document.createElement("canvas");a.width=n.width;a.height=n.height;a.getContext("2d").drawImage(n,0,0);H.preloadedImages[c]=a;Pb.T.revokeObjectURL(s);d&&d(b)});n.onerror=(function(){console.log("Image "+s+" could not be decoded");f&&f()});n.src=s})});H.preloadPlugins.push({canHandle:(function(a){return!H.qd&&a.substr(-4)in{".ogg":1,".wav":1,".mp3":1}}),handle:(function(b,c,d,f){function h(a){s||(s=qc,H.preloadedAudios[c]=a,d&&d(b))}function i(){s||(s=qc,H.preloadedAudios[c]=new Audio,f&&f())}var s=Ud;if(Pb.J){try{var n=new Blob([b],{type:a(c)})}catch(m){return i()}var n=Pb.T.createObjectURL(n),w=new Audio;w.addEventListener("canplaythrough",(function(){h(w)}),Ud);w.onerror=(function(){if(!s){console.log("warning: browser could not fully decode audio "+c+", trying slower base64 approach");for(var a="",d=0,f=0,i=0;i<b.length;i++){d=d<<8|b[i];for(f+=8;6<=f;){var k=d>>f-6&63,f=f-6,a=a+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[k]}}2==f?(a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(d&3)<<4],a+="=="):4==f&&(a+="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(d&15)<<2],a+="=");w.src="data:audio/x-"+c.substr(-3)+";base64,"+a;h(w)}});w.src=n;setTimeout((function(){h(w)}),1e4)}else{return i()}})})}}),$c:(function(a,b,c){var d;try{(d=b?a.getContext("experimental-webgl",{alpha:Ud}):a.getContext("2d"))||Ob(":(")}catch(f){return H.print("Could not create canvas - "+f),Ac}b&&(a.style.backgroundColor="black",a.addEventListener("webglcontextlost",(function(){alert("WebGL context lost. You will need to reload the page.")}),Ud));c&&(H.ad=d,H.Ed=b,Pb.fb.forEach((function(a){a()})));return d}),hd:ng(),ja:(function(){function a(){var b=Ud;if((document.webkitFullScreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.mozFullscreenElement||document.fullScreenElement||document.fullscreenElement)===c){c.lb=c.requestPointerLock||c.mozRequestPointerLock||c.webkitRequestPointerLock,c.lb(),b=qc}if(H.onFullScreen){H.onFullScreen(b)}}function b(){Pb.ib=document.pointerLockElement===c||document.mozPointerLockElement===c||document.webkitPointerLockElement===c}var c=H.canvas;document.addEventListener("fullscreenchange",a,Ud);document.addEventListener("mozfullscreenchange",a,Ud);document.addEventListener("webkitfullscreenchange",a,Ud);document.addEventListener("pointerlockchange",b,Ud);document.addEventListener("mozpointerlockchange",b,Ud);document.addEventListener("webkitpointerlockchange",b,Ud);c.ja=c.requestFullScreen||c.mozRequestFullScreen||(c.webkitRequestFullScreen?(function(){c.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT)}):Ac);c.ja()}),requestAnimationFrame:(function(a){window.requestAnimationFrame||(window.requestAnimationFrame=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||window.setTimeout);window.requestAnimationFrame(a)}),nd:(function(a){return a.movementX||a.mozMovementX||a.webkitMovementX||0}),od:(function(a){return a.movementY||a.mozMovementY||a.webkitMovementY||0}),Eb:(function(a,b,c){var d=new XMLHttpRequest;d.open("GET",a,qc);d.responseType="arraybuffer";d.onload=(function(){200==d.status?b(d.response):c()});d.onerror=c;d.send(Ac)}),Na:(function(a,b,c,d){Pb.Eb(a,(function(c){Nc(c,'Loading data file "'+a+'" failed (no arrayBuffer).');b(new Uint8Array(c));d||xh("al "+a)}),(function(){c?c():Ob('Loading data file "'+a+'" failed.')}));d||Ni("al "+a)}),mb:[],Db:(function(){var a=H.canvas;Pb.mb.forEach((function(b){b(a.width,a.height)}))}),xd:(function(a,b,c){var d=H.canvas;d.width=a;d.height=b;c||Pb.Db()})};ht.unshift({ca:(function(){!H.noFSInit&&!N.u.fa&&N.u()})});bt.push({ca:(function(){N.Ca=Ud})});Si.push({ca:(function(){N.kb()})});H.FS_createFolder=N.G;H.FS_createPath=N.wa;H.FS_createDataFile=N.$;H.FS_createPreloadedFile=N.Sa;H.FS_createLazyFile=N.Qa;H.FS_createLink=N.Ra;H.FS_createDevice=N.s;Ha(0);ud=fa.oa(4);Gf.d=d([0],"i8",qe);Ah(Fd);H.requestFullScreen=(function(){Pb.ja()});H.requestAnimationFrame=(function(a){Pb.requestAnimationFrame(a)});H.pauseMainLoop=(function(){Pb.k.pause()});H.resumeMainLoop=(function(){Pb.k.nb()});var J=[0,0,(function(a){A(a,5335720)}),0,xm,0,(function(a,b){E(b)}),0,(function(a,b){A(a,5347616);A(a,De(b));A(a,5347084)}),0,(function(c){var d;n[c+528|0]=0;d=c+348|0;var g=10/(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);d=(c+340|0)>>2;g=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3])-g;f[b>>3]=g;a[d]=a[b>>2];a[d+1]=a[b+4>>2];n[c+529|0]=1;return 0}),0,Hm,0,(function(b,c){var d=sq(a[b>>2]),e=sq(a[c>>2]);return((e|0)<(d|0)&1)-((e|0)>(d|0)&1)|0}),0,(function(b){var c;A(b,5343480);c=(b+12|0)>>2;A(b,a[a[a[c]>>2]>>2]);A(b,5368560);A(b,a[a[a[c]>>2]+4>>2]);A(b,5368308);A(b,a[a[a[c]>>2]+8>>2]);A(b,5342480)}),0,(function(b,c){return a[b>>2]-a[c>>2]|0}),0,(function(a,b,c,d){A(a,5330856);0!=(b|0)&&0!=n[b]<<24>>24&&(A(a,5356472),A(a,Uh(b)),A(a,5337992));0!=(c|0)&&0!=n[c]<<24>>24&&(A(a,5356252),A(a,jc(c)),A(a,5337992));0!=(d|0)&&0!=n[d]<<24>>24&&(A(a,5356136),A(a,jc(d)),A(a,5337992));A(a,5329648)}),0,(function(b,c,d){var e=0;0==(c|0)&&(a[1312720]=d);for(var c=c-1|0,d=0,f=b;;){if((d|0)>=(c|0)){var h=b,i=f;break}var k=a[1312720],r=n[k];if(0==r<<24>>24){e=2046;break}a[1312720]=k+1|0;k=f+1|0;n[f]=r;if(10==r<<24>>24){h=b;i=k;break}else{d=d+1|0,f=k}}2046==e&&(0==(d|0)?(h=a[1312720]=0,i=f):(n[f]=10,h=b,i=f+1|0));n[i]=0;return h}),0,(function(a){A(a,5355896)}),0,Ds,0,Ko,0,(function(b){var c,d=h;c=(b+12|0)>>2;0!=(a[a[c]+20>>2]|0)&&(A(b,5359156),fi(b,0,a[a[c]+20>>2]+4|0));A(b,5358936);A(b,5358712);G(b,5358476,(i=h,h=h+4|0,a[i>>2]=a[a[c]+28>>2],i));h=d}),0,Do,0,(function(c){var d;n[c+528|0]=0;d=(c+348|0)>>2;var g=1.1*(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);f[b>>3]=g;a[d]=a[b>>2];a[d+1]=a[b+4>>2];n[c+529|0]=1;return 0}),0,Fm,0,Rs,0,(function(b){var c=a[b+16>>2];A(b,5355748);A(b,jc(a[c+152>>2]));A(b,5354744);A(b,5355428);A(b,jc(a[a[c+8>>2]+12>>2]));A(b,5355072)}),0,Fs,0,(function(c,d,g,e,i,p,j,k){p=h;h=h+32|0;j=.5*Math.sqrt(e*e+i*i);d=.5*e+d;e=p|0;f[b>>3]=d-j;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];g=.5*i+g;i=p+8|0;f[b>>3]=g-j;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];i=p+16|0;f[b>>3]=d+j;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];i=p+24|0;f[b>>3]=g+j;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];Kg(c,p|0,(k>>>3&1^1)&255);h=p}),0,(function(a){A(a,5359588)}),0,(function(c,d,g){var e=h;h=h+16|0;c=a[c>>2];Wf(e,d,g,90*(a[a[c+20>>2]+152>>2]&3)&-1);var d=e|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),g=e+8|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),i=c+96|0,i=.5*(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);if(g<-i|g>i){return h=e,0}g=c+104|0;if(d<-(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])){return h=e,0}c=c+112|0;c=d<=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3]);h=e;return c&1}),0,xo,0,wo,0,pm,0,(function(c){var d=a[a[c+16>>2]+8>>2],c=d|0,g=a[a[a[1310754]>>2]+8>>2],e=a[1310772];e>>>0<a[1310773]>>>0||(qa(5243084,1),e=a[1310772]);n[e]=0;e=a[1310771];a[1310772]=e;hc(c,g,e);0!=(a[d+48>>2]|0)&&(d=a[a[a[1310754]+4>>2]+8>>2],g=a[1310788],g>>>0<a[1310789]>>>0||(qa(5243148,1),g=a[1310788]),n[g]=0,g=a[1310787],a[1310788]=g,hc(c,d,g));f[b>>3]=1;a[1312251]=a[b>>2];a[1312252]=a[b+4>>2];f[b>>3]=1;a[1312259]=a[b>>2];a[1312260]=a[b+4>>2]}),0,(function(b){var c=a[a[b>>2]+128>>2],d=b+572|0;0==(a[d>>2]|0)&&(a[d>>2]=c|0,d=c+148|0,n[d]|=2,vk(b,c));fj(b,c);n[b+532|0]=1}),0,Js,0,(function(c,d,g,e,l,p){e=h;A(c,5346644);l=a[1313350];G(c,5340408,(i=h,h=h+8|0,a[i>>2]=a[1313349],a[i+4>>2]=l,i));Yl(c,p);A(c,5340132);Ii(c);A(c,5339824);p=h;if(0<(g|0)){for(var l=0,j=5339284;;){var k=(l<<4)+d|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),n=(l<<4)+d+8|0,n=(a[1313350]>>>0)-(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]);G(c,5338812,(i=h,h=h+20|0,a[i>>2]=j,f[b>>3]=k,a[i+4>>2]=a[b>>2],a[i+8>>2]=a[b+4>>2],f[b>>3]=n,a[i+12>>2]=a[b>>2],a[i+16>>2]=a[b+4>>2],i));j=0==(l|0)?5338544:5338228;l=l+1|0;if((l|0)==(g|0)){break}}}A(c,5337992);h=p;A(c,5339560);h=e}),0,(function(b,c){var d=h,e=a[a[c+16>>2]+12>>2],f=a[a[c+12>>2]+12>>2];aa(3,5346776,(i=h,h=h+12|0,a[i>>2]=c,a[i+4>>2]=e,a[i+8>>2]=f,i));h=d;return 0}),0,(function(c,d,g){var e=h;A(c,5365648);th(c,0);A(c,5365428);if(0<(g|0)){for(var l=0;;){var p=(l<<4)+d|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=(l<<4)+d+8|0,j=-(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);G(c,5365084,(i=h,h=h+16|0,f[b>>3]=p,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));l=l+1|0;if((l|0)==(g|0)){break}}}A(c,5364888);h=e}),0,(function(a,b){A(a,5349108);A(a,b);A(a,5344600)}),0,(function(b){var c;A(b,5352868);c=U(a[a[b>>2]+128>>2]|0,5352764);0!=(c|0)&&0!=n[c]<<24>>24&&(A(b,5352624),A(b,c),A(b,5352488));A(b,5352180);A(b,5351968);A(b,5351812);c=(b+12|0)>>2;A(b,jc(a[a[a[c]>>2]>>2]));A(b,5368560);A(b,jc(a[a[a[c]>>2]+4>>2]));A(b,5368308);A(b,jc(a[a[a[c]>>2]+8>>2]));A(b,5342480);A(b,5347084)}),0,(function(b,c,d){var e,f=h;e=d>>2;d=h;h=h+32|0;a[d>>2]=a[e];a[d+4>>2]=a[e+1];a[d+8>>2]=a[e+2];a[d+12>>2]=a[e+3];a[d+16>>2]=a[e+4];a[d+20>>2]=a[e+5];a[d+24>>2]=a[e+6];a[d+28>>2]=a[e+7];0==(b|0)&&ia(5338512,114,5379960,5338204);d=b+16|0;0==(a[d>>2]|0)&&ia(5338512,116,5379960,5335416);0==(c|0)&&ia(5338512,117,5379960,5337976);c=c+8|0;0==(a[c>>2]|0)&&ia(5338512,118,5379960,5337700);0==(a[a[d>>2]+8>>2]|0)&&ia(5338512,121,5379960,5335128);G(b,5334864,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));G(b,5334600,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));G(b,5334284,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));G(b,5334028,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));G(b,5333788,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));G(b,5333540,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));G(b,5333132,(i=h,h=h+4|0,a[i>>2]=a[c>>2],i));G(b,5332856,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));G(b,5332596,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));h=f}),0,(function(){a[1313373]=-1}),0,(function(b){b=a[b+28>>2];0!=(b|0)&&E(b)}),0,(function(a){A(a,5329428);A(a,5329208);A(a,5328948);A(a,5328704);A(a,5329208);A(a,5328432);A(a,5328148);A(a,5327848);A(a,5329208);A(a,5327552);A(a,5327280);A(a,5329208);A(a,5326896)}),0,Im,0,(function(){a[1345523]=0}),0,(function(){return 0}),0,(function(b){var c=h;A(b,5355092);var d=b+64|0,e=b+12|0;2!=(a[d>>2]|0)&&G(b,5354944,(i=h,h=h+4|0,a[i>>2]=a[a[e>>2]+28>>2],i));if(0==(a[a[e>>2]+20>>2]|0)&&2!=(a[d>>2]|0)){var d=a[b+468>>2],e=a[b+472>>2],f=a[b+476>>2];G(b,5355764,(i=h,h=h+16|0,a[i>>2]=a[b+464>>2],a[i+4>>2]=d,a[i+8>>2]=e,a[i+12>>2]=f,i))}A(b,5354788);A(b,5354644);h=c}),0,(function(b,c){var d=h;h=h+4|0;a[d>>2]=c;iq(1,b,a[d>>2]);h=d}),0,(function(c){var d;n[c+528|0]=0;d=(c+348|0)>>2;var g=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3])/1.1;f[b>>3]=g;a[d]=a[b>>2];a[d+1]=a[b+4>>2];n[c+529|0]=1;return 0}),0,Hs,0,(function(b){E(a[b+52>>2])}),0,(function(c,d,g){var e,l=h;e=g>>2;g=h;h=h+32|0;a[g>>2]=a[e];a[g+4>>2]=a[e+1];a[g+8>>2]=a[e+2];a[g+12>>2]=a[e+3];a[g+16>>2]=a[e+4];a[g+20>>2]=a[e+5];a[g+24>>2]=a[e+6];a[g+28>>2]=a[e+7];e=c+228|0;var p=c+212|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])&-1;var d=a[d+8>>2],p=g+16|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=g|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),k=g+24|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),g=g+8|0,g=k-(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);G(c,5339180,(i=h,h=h+36|0,a[i>>2]=d,f[b>>3]=p-j,a[i+4>>2]=a[b>>2],a[i+8>>2]=a[b+4>>2],f[b>>3]=g,a[i+12>>2]=a[b>>2],a[i+16>>2]=a[b+4>>2],f[b>>3]=j,a[i+20>>2]=a[b>>2],a[i+24>>2]=a[b+4>>2],f[b>>3]=(e>>>0)-k,a[i+28>>2]=a[b>>2],a[i+32>>2]=a[b+4>>2],i));A(c,5338792);h=l}),0,(function(a,b,c,d){return pe(d,a,c)}),0,Is,0,(function(b){var c;A(b,5368960);A(b,5368764);c=(b+12|0)>>2;A(b,De(a[a[a[c]>>2]>>2]));A(b,5368560);A(b,De(a[a[a[c]>>2]+4>>2]));A(b,5368308);A(b,De(a[a[a[c]>>2]+8>>2]));A(b,5368144)}),0,(function(b,c){return $(a[b>>2],a[c>>2])}),0,(function(c){var d;n[c+528|0]=0;var g=c+348|0;d=(c+340|0)>>2;g=10/(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])+(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);f[b>>3]=g;a[d]=a[b>>2];a[d+1]=a[b+4>>2];n[c+529|0]=1;return 0}),0,(function(c,d,g){var e,l=h;h=h+1024|0;e=g>>2;g=h;h=h+32|0;a[g>>2]=a[e];a[g+4>>2]=a[e+1];a[g+8>>2]=a[e+2];a[g+12>>2]=a[e+3];a[g+16>>2]=a[e+4];a[g+20>>2]=a[e+5];a[g+24>>2]=a[e+6];a[g+28>>2]=a[e+7];c=c+16|0;e=a[(a[a[c>>2]+12>>2]<<2)+5243020>>2];Cb(e,5370908);var p=g|0,j=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),p=g+8|0,k=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);gi(e,j,k);var p=l|0,n=g+16|0,j=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3])-j,g=g+24|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])-k;Pa(p,5372640,(i=h,h=h+8|0,a[i>>2]=(0>j?j-.5:j+.5)&-1,a[i+4>>2]=(0>g?g-.5:g+.5)&-1,i));Cb(e,p);Af(a[a[c>>2]+12>>2],5338228,a[d+8>>2]);h=l}),0,Os,0,(function(b){var c=a[b+16>>2];A(b,5355748);A(b,jc(a[c+152>>2]));A(b,5354920);A(b,5355428);A(b,jc(a[a[c+8>>2]+12>>2]));A(b,5355072)}),0,(function(b,c){return a[a[b>>2]+20>>2]-a[a[c>>2]+20>>2]|0}),0,(function(c,d,g){var e=h;A(c,5336052);var l=d+16|0,p=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),l=d|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),p=p-l,j=d+24|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),d=d+8|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),j=j-d,d=(a[1313350]>>>0)-(d+j);G(c,5335744,(i=h,h=h+16|0,f[b>>3]=l-p,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=d,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));G(c,5335432,(i=h,h=h+16|0,f[b>>3]=2*p,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=2*j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));Yl(c,g);A(c,5340132);Ii(c);A(c,5335144);h=e}),0,(function(c,d,g){var e=h;A(c,5346644);var l=a[1313350];G(c,5346260,(i=h,h=h+8|0,a[i>>2]=a[1313349],a[i+4>>2]=l,i));A(c,5345956);if(0<(g|0)){for(var l=g-1|0,p=d|0,j=d+8|0,k=0;;){if(0==(k|0)){A(c,5345652);var n=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),q=(a[1313350]>>>0)-(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);G(c,5345216,(i=h,h=h+16|0,f[b>>3]=n,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=q,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));A(c,5344844)}else{n=(k<<4)+d|0,n=(a[b>>2]=a[n>>2],a[b+4>>2]=a[n+4>>2],f[b>>3]),q=(k<<4)+d+8|0,q=(a[1313350]>>>0)-(a[b>>2]=a[q>>2],a[b+4>>2]=a[q+4>>2],f[b>>3]),G(c,5345216,(i=h,h=h+16|0,f[b>>3]=n,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=q,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i))}(k|0)==(l|0)&&A(c,5344548);k=k+1|0;if((k|0)==(g|0)){break}}}A(c,5344188);Ii(c);A(c,5343804);h=e}),0,kp,0,(function(b,c){return $(a[b>>2],a[c>>2])}),0,(function(c,d,g,e){var l=h;A(c,5360944);th(c,e);A(c,5365428);a:do{if(0<(g|0)){for(e=0;;){var p=(e<<4)+d|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),j=(e<<4)+d+8|0,j=-(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);G(c,5365084,(i=h,h=h+16|0,f[b>>3]=p,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));e=e+1|0;if((e|0)==(g|0)){break a}}}}while(0);g=d|0;g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);d=d+8|0;d=-(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);G(c,5360760,(i=h,h=h+16|0,f[b>>3]=g,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=d,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));A(c,5364888);h=l}),0,(function(c,d,g){var e,i,p=h;h=h+32|0;var j=p|0;i=p>>2;e=d>>2;a[i]=a[e];a[i+1]=a[e+1];a[i+2]=a[e+2];a[i+3]=a[e+3];e=d+16|0;i=d|0;e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]);i=p+16|0;f[b>>3]=e;a[i>>2]=a[b>>2];a[i+4>>2]=a[b+4>>2];e=d+24|0;d=d+8|0;d=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])-(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);e=p+24|0;f[b>>3]=d;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];d=(c+16|0)>>2;if(0!=(g|0)&&(g=a[d],e=g+76|0,.5<(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]))){Ce(c,g+52|0),xe(c,j,2),A(c,5361364)}g=a[d]+40|0;if(.5<(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])){sh(c),Ce(c,a[d]+16|0),xe(c,j,2),A(c,5361184)}h=p}),0,(function(c,d,g){var e=c+16|0,h=a[e>>2]+40|0;if(.5<(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3])){sh(c);Ce(c,a[e>>2]+16|0);A(c,5362824);e=d|0;h=d+8|0;od(c,(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]));A(c,5362580);a:do{if(1<(g|0)){for(e=1;;){var h=(e<<4)+d|0,i=(e<<4)+d+8|0;od(c,(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]),(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]));A(c,5362396);e=e+1|0;if((e|0)==(g|0)){break a}}}}while(0);A(c,5362180)}}),0,(function(b,c,d){var e,f=a[b+16>>2];e=(f+88|0)>>2;0!=(a[e]|0)&&(uh(b),A(b,5341052),xe(b,c,d),A(b,5338028),Bf(b,f+16|0),c=a[e],1==(c|0)?(A(b,5335180),e=a[e]):e=c,2==(e|0)&&A(b,5332424),lg(b),A(b,5344600))}),0,(function(c){var d=c>>2,g=h,e=a[d+4];A(c,5354012);e=e+8|0;0!=n[a[a[e>>2]+12>>2]]<<24>>24&&(A(c,5344204),A(c,jc(a[a[e>>2]+12>>2])));e=Math.a(a[d+41],a[d+40]);G(c,5353752,(i=h,h=h+4|0,a[i>>2]=e,i));e=a[d+111];G(c,5353600,(i=h,h=h+8|0,a[i>>2]=a[d+110],a[i+4>>2]=e,i));var d=c+376|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),e=c+384|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),l=c+392|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),p=c+400|0,p=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]);G(c,5353400,(i=h,h=h+32|0,f[b>>3]=d,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=e,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],f[b>>3]=l,a[i+16>>2]=a[b>>2],a[i+20>>2]=a[b+4>>2],f[b>>3]=p,a[i+24>>2]=a[b>>2],a[i+28>>2]=a[b+4>>2],i));A(c,5353200);A(c,5353036);A(c,5329648);h=g}),0,(function(c){var d=h;h=h+36|0;En(c,8);var g;var e=d>>2,l=h;h=h+12|0;g=l>>2;var p=l+8;a[p>>2]=5;var j=U(c|0,5351680);0!=(j|0)&&1<=(gd(j,5345188,(i=h,h=h+8|0,a[i>>2]=l,a[i+4>>2]=p,i))|0)?(j=(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]),1>j?(f[b>>3]=1,a[g]=a[b>>2],a[g+1]=a[b+4>>2],g=1):20<j?(f[b>>3]=20,a[g]=a[b>>2],a[g+1]=a[b+4>>2],g=20):g=j,j=d|0,f[b>>3]=g,a[j>>2]=a[b>>2],a[j+4>>2]=a[b+4>>2],a[e+6]=-1,a[e+7]=a[p>>2],a[e+8]=0,e=d):(a[e+6]=0,e=a[e+8]=0);h=l;g=e;Uq(c);l=d+32|0;e=d+28|0;for(p=d+24|0;!(sl(c,g),0!=(a[l>>2]|0)&&(aa(0,5350428,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),g=a[p>>2]=0),nr(c,0!=(g|0)&1),or(c,g),j=a[e>>2]-1|0,a[e>>2]=j,0==(a[p>>2]|0)|0==(j|0));){}tl(c);kl(c,1);if(0!=Ph(U(c|0,5372388))<<24>>24&&(l=c+20|0,p=ha(a[l>>2]),0!=(p|0))){for(e=c+28|0;;){g=zb(c,p);a:do{if(0!=(g|0)){for(j=g;;){if(Lq(c,j),j=Db(a[e>>2],j),0==(j|0)){break a}}}}while(0);p=sa(a[l>>2],p);if(0==(p|0)){break}}}Tj(c);h=d}),0,(function(a,b,c){a=0==(c|0);0==(b|0)?b=a?0:wb(c):a?(E(b),b=0):b=gc(b,c);return b}),0,Ss,0,Gm,0,(function(c){var d=h,g=a[c+16>>2];A(c,5355748);A(c,jc(a[g+152>>2]));A(c,5354608);var e=c+480|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),l=c+488|0,l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),p=-a[c+356>>2]|0,j=c+496|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),k=c+504|0,k=-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);G(c,5354436,(i=h,h=h+36|0,f[b>>3]=e,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=l,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],a[i+16>>2]=p,f[b>>3]=j,a[i+20>>2]=a[b>>2],a[i+24>>2]=a[b+4>>2],f[b>>3]=k,a[i+28>>2]=a[b>>2],a[i+32>>2]=a[b+4>>2],i));g=g+8|0;0!=n[a[a[g>>2]+12>>2]]<<24>>24&&(A(c,5355428),A(c,jc(a[a[g>>2]+12>>2])),A(c,5355072));h=d}),0,(function(b,c,d){ph(b);qh(b);rh(a[a[b+16>>2]+12>>2],76,c,d)}),0,(function(a){A(a,5355896)}),0,(function(b){var c;for(c=b>>2;!(b=a[c+32],0==(b|0));){c=b>>2}var b=a[c+3],d=a[b+236>>2];c=a[c+4];var e=a[c+236>>2];return(d|0)>(e|0)?0:(d|0)<(e|0)?1:b=(a[b+240>>2]|0)<(a[c+240>>2]|0)&1}),0,ng(),0,(function(a){A(a,5335720)}),0,Gs,0,(function(c,d,g,e){var l=h,p=a[c+16>>2],j=p+40|0;if(.5<=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])){Ce(c,p+16|0),p=e+24|0,ag(c,(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])),G(c,5360988,(i=h,h=h+4|0,a[i>>2]=a[e+20>>2],i)),p=mk(a[e>>2],a[1312802]),j=n[e+72|0]<<24>>24,108==(j|0)?j=e+56|0:114==(j|0)?(j=e+56|0,d-=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])):(j=e+56|0,d-=.5*(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])),e=e+48|0,od(c,d,(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3])+g),A(c,5360768),ag(c,(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])),G(c,5360544,(i=h,h=h+4|0,a[i>>2]=p,i))}h=l}),0,(function(a){A(a,5359588)}),0,(function(b){return 0!=(a[a[b>>2]+116>>2]|0)||0!=(a[b+40>>2]|0)?0:b=pm(a[b+36>>2])}),0,(function(c,d,g,e){var l=h;A(c,5346644);var p=a[1313350];G(c,5340408,(i=h,h=h+8|0,a[i>>2]=a[1313349],a[i+4>>2]=p,i));Yl(c,e);A(c,5340132);Ii(c);A(c,5339824);if(0<(g|0)){e=g-1|0;for(p=0;;){var j=(p<<4)+d|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),k=(p<<4)+d+8|0,k=(a[1313350]>>>0)-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);0==(p|0)?(A(c,5339284),G(c,5336948,(i=h,h=h+16|0,f[b>>3]=j,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=k,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i)),A(c,5336692)):G(c,5336948,(i=h,h=h+16|0,f[b>>3]=j,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=k,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));(p|0)==(e|0)&&A(c,5336436);p=p+1|0;if((p|0)==(g|0)){break}}}A(c,5343804);h=l}),0,(function(b,c){var d=h;if(0!=(c|0)){var e=a[b+16>>2]+212|0;0!=(a[e>>2]|0)&&(A(b,5360404),xe(b,a[e>>2],2),A(b,5360180),e=mk(c,a[1312802]),G(b,5359916,(i=h,h=h+4|0,a[i>>2]=e,i)))}h=d}),0,ys,0,re,0,(function(b){b=a[b+28>>2];0!=(b|0)&&(E(a[b+40>>2]),E(b))}),0,(function(b){var c=a[a[b+16>>2]+8>>2];aq(98,160);var d=a[b+64>>2];3==(d|0)?pk(b,c,b,1):2==(d|0)?pk(b,c,b,0):4==(d|0)?(ws(c),0==(a[b+148>>2]&134217728|0)&&Ok(c,b)):0==(d|0)|1==(d|0)&&0==(a[b+148>>2]&134217728|0)&&Ok(c,b);aq(0,0)}),0,(function(a){A(a,5331100)}),0,Ts,0,(function(){a[1345523]=2}),0,(function(c){var d;d=c+528|0;var g=0==n[d]<<24>>24;n[d]=g&1;if(!g){return 0}d=a[c+440>>2];g=a[c+444>>2];d=(d>>>0)/(d|0);var g=(g>>>0)/(g|0),e=c+348|0;f[b>>3]=d<g?d:g;a[e>>2]=a[b>>2];a[e+4>>2]=a[b+4>>2];d=(c+332|0)>>2;a[d]=0;a[d+1]=0;a[d+2]=0;a[d+3]=0;n[c+529|0]=1;return 0}),0,jl,0,Es,0,(function(b){var c,d=h;A(b,5354500);2==(a[b+64>>2]|0)?A(b,5354356):A(b,5344600);c=a[a[b+12>>2]>>2]>>2;var e=a[c+1],f=a[c+2];G(b,5354184,(i=h,h=h+12|0,a[i>>2]=a[c],a[i+4>>2]=e,a[i+8>>2]=f,i));h=d}),0,mi,0,(function(b,c){var d=h;G(b,5377604,(i=h,h=h+4|0,a[i>>2]=c,i));h=d}),0,(function(b){var c=h,d=a[b+16>>2];A(b,5344564);d=d+8|0;0!=n[a[a[d>>2]+12>>2]]<<24>>24&&(A(b,5344204),A(b,a[a[d>>2]+12>>2]));d=Math.a(a[b+164>>2],a[b+160>>2]);G(b,5343828,(i=h,h=h+4|0,a[i>>2]=d,i));h=c}),0,(function(c,d,g,e){var l,p=h;l=g>>2;g=h;h=h+32|0;a[g>>2]=a[l];a[g+4>>2]=a[l+1];a[g+8>>2]=a[l+2];a[g+12>>2]=a[l+3];a[g+16>>2]=a[l+4];a[g+20>>2]=a[l+5];a[g+24>>2]=a[l+6];a[g+28>>2]=a[l+7];0==(c|0)&&ia(5338512,205,538e4,5338204);0==(d|0)&&ia(5338512,206,538e4,5337976);l=(d+8|0)>>2;0==(a[l]|0)&&ia(5338512,207,538e4,5337700);if(0!=(a[d+52>>2]|0)){var d=g|0,d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]),j=g+8|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),k=g+16|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]),g=g+24|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);0!=e<<24>>24&&(G(c,5337412,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i)),G(c,5337180,(i=h,h=h+16|0,f[b>>3]=d,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i)),G(c,5337180,(i=h,h=h+16|0,f[b>>3]=d,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=g,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i)),G(c,5337180,(i=h,h=h+16|0,f[b>>3]=k,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=g,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i)),G(c,5337180,(i=h,h=h+16|0,f[b>>3]=k,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i)),G(c,5337180,(i=h,h=h+16|0,f[b>>3]=d,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i)),e=a[l],G(c,5336892,(i=h,h=h+8|0,a[i>>2]=4,a[i+4>>2]=e,i)));G(c,5337412,(i=h,h=h+1|0,h=h+3>>2<<2,a[i>>2]=0,i));G(c,5337180,(i=h,h=h+16|0,f[b>>3]=d,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));G(c,5337180,(i=h,h=h+16|0,f[b>>3]=d,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=g,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));G(c,5337180,(i=h,h=h+16|0,f[b>>3]=k,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=g,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));G(c,5337180,(i=h,h=h+16|0,f[b>>3]=k,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));G(c,5337180,(i=h,h=h+16|0,f[b>>3]=d,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));e=a[l];G(c,5336664,(i=h,h=h+8|0,a[i>>2]=4,a[i+4>>2]=e,i))}h=p}),0,Nf,0,(function(c,d,g,e,l){var p,j=h;p=(c+16|0)>>2;if(0!=(l|0)){var l=a[p],k=l+76|0;if(.5<(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])){Ce(c,l+52|0),A(c,5337412),xe(c,g,e),A(c,5366668),l=g|0,k=g+8|0,od(c,(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]),(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])),G(c,5366448,(i=h,h=h+8|0,a[i>>2]=e,a[i+4>>2]=d,i))}}l=a[p]+40|0;if(.5<(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3])){sh(c),Ce(c,a[p]+16|0),A(c,5337412),xe(c,g,e),A(c,5366668),p=g|0,g=g+8|0,od(c,(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3]),(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])),G(c,5366140,(i=h,h=h+8|0,a[i>>2]=e,a[i+4>>2]=d,i))}h=j}),0,(function(b){var c=h;G(b,5359344,(i=h,h=h+4|0,a[i>>2]=a[a[a[b+16>>2]+8>>2]+12>>2],i));A(b,5359588);h=c}),0,(function(a){A(a,5354168)}),0,(function(a){A(a,5348760)}),0,(function(b){fk(a[b+28>>2])}),0,(function(b,c,d,e){var f=h;A(b,5330856);0!=(c|0)&&0!=n[c]<<24>>24&&(c=De(c),G(b,5330456,(i=h,h=h+4|0,a[i>>2]=c,i)));0!=(d|0)&&0!=n[d]<<24>>24&&(d=De(d),G(b,5330128,(i=h,h=h+4|0,a[i>>2]=d,i)));0!=(e|0)&&0!=n[e]<<24>>24&&(e=De(e),G(b,5329932,(i=h,h=h+4|0,a[i>>2]=e,i)));A(b,5329648);h=f}),0,(function(c,d,g,e,l,p){A(c,5361560);th(c,p);A(c,5361356);e=h;if(0<(g|0)){l=0;for(p=77;;){var j=(l<<4)+d|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]),k=(l<<4)+d+8|0,k=-(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3]);G(c,5361176,(i=h,h=h+20|0,a[i>>2]=p,f[b>>3]=j,a[i+4>>2]=a[b>>2],a[i+8>>2]=a[b+4>>2],f[b>>3]=k,a[i+12>>2]=a[b>>2],a[i+16>>2]=a[b+4>>2],i));p=0==(l|0)?67:32;l=l+1|0;if((l|0)==(g|0)){break}}}h=e;A(c,5364888)}),0,(function(b,c){var d=a[1345525];J[a[d>>2]](d,c,1);return 0}),0,(function(a,b){A(a,5355748);A(a,jc(b));A(a,5354328)}),0,(function(b,c,d){c=h;b=d>>2;d=h;h=h+32|0;a[d>>2]=a[b];a[d+4>>2]=a[b+1];a[d+8>>2]=a[b+2];a[d+12>>2]=a[b+3];a[d+16>>2]=a[b+4];a[d+20>>2]=a[b+5];a[d+24>>2]=a[b+6];a[d+28>>2]=a[b+7];h=c}),0,Bo,0,Ls,0,Em,0,(function(b,c,d){var b=a[b>>2],e=a[a[b+128>>2]+32>>2],f;um(b,c);c=a[b+124>>2];f=c>>2;a[f+14]=Dh(c,a[f+13]);if(0==(a[e+44>>2]|0)&&0==(a[f+37]&67108864|0)){re(5332896,20,1,a[Qa>>2])}else{f=b+120|0;var h=a[f>>2];0==(h|0)?(h=da(624),a[f>>2]=h,a[b+124>>2]=h,f=a[1312670]=h):(f=a[1312670],0==(f|0)?f=a[1312670]=h:(f=a[f+4>>2],0==(f|0)&&(f=da(624),a[a[1312670]+4>>2]=f),a[1312670]=f));a[f+32>>2]=d;a[f>>2]=b;Wi(b,e);Xi(c);jp(c);Yi(b)}}),0,(function(b,c,d){return a[c>>2]-a[d>>2]|0}),0,(function(b,c){E(a[c+52>>2])}),0,(function(c,d,g){var e,h=a[c+16>>2];e=(h+88|0)>>2;0!=(a[e]|0)&&(uh(c),A(c,5341052),xe(c,d,g),A(c,5338028),Bf(c,h+16|0),A(c,5355052),d=h+96|0,ag(c,(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])),d=a[e],1==(d|0)?(A(c,5335180),e=a[e]):e=d,2==(e|0)&&A(c,5332424),A(c,5353564),lg(c),A(c,5344600))}),0,(function(b,c){var d=a[c+20>>2];0!=(d|0)&&Jf(d);if(0!=(a[c+52>>2]|0)&&(d=a[c+60>>2],0!=(d|0))){J[d](c)}E(c)}),0,(function(b,c,d,e){ph(b);qh(b);0==(e|0)?rh(a[a[b+16>>2]+12>>2],112,c,d):(Wl(b),rh(a[a[b+16>>2]+12>>2],80,c,d))}),0,(function(c,d,g){var e,l=h;A(c,5360532);th(c,g);e=(d|0)>>2;var p=(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]),g=(d+8|0)>>2,j=-(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]);G(c,5360348,(i=h,h=h+16|0,f[b>>3]=p,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=j,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));p=d+16|0;e=(a[b>>2]=a[p>>2],a[b+4>>2]=a[p+4>>2],f[b>>3])-(a[b>>2]=a[e],a[b+4>>2]=a[e+1],f[b>>3]);d=d+24|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])-(a[b>>2]=a[g],a[b+4>>2]=a[g+1],f[b>>3]);G(c,5360160,(i=h,h=h+16|0,f[b>>3]=e,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],f[b>>3]=d,a[i+8>>2]=a[b>>2],a[i+12>>2]=a[b+4>>2],i));A(c,5330440);h=l}),0,(function(){return 1}),0,us,0,Lo,0,to,0,(function(a){A(a,5335720)}),0,Cs,0,kh,0,ss,0,(function(a){A(a,5355896)}),0,(function(a){A(a,5355896)}),0,(function(b){var c=h;h=h+8|0;var d=c+4,e=a[a[b+16>>2]+8>>2],b=a[b+64>>2];0==(b|0)?(d=h,h=h+8|0,rk(e,d+4,d),h=d):1==(b|0)?0!=(C[e+164>>1]&1)<<16>>16&&yn(e):4==(b|0)&&(rk(e,d,c),xs(e,a[d>>2],a[c>>2]));h=c}),0,wf,0,Mo,0,(function(b,c,d){var b=a[c+16>>2],b=0==(b|0)?-1:a[b+16>>2],e=a[c+12>>2],e=0==(e|0)?-1:a[e+16>>2],f=a[d+16>>2],f=0==(f|0)?-1:a[f+16>>2],h=a[d+12>>2],h=0==(h|0)?-1:a[h+16>>2];return(e|0)!=(h|0)?e-h|0:c=(b|0)==(f|0)?Tp(a[c+4>>2],d):b-f|0}),0,(function(b,c,d,e,f){var h;h=a[b+16>>2]>>2;Hi(b,a[h+51],a[h+53],a[h+52],c,d,e,f)}),0,(function(b){var c,d=h,e=a[b+16>>2];A(b,5348056);c=a[a[b+12>>2]>>2]>>2;var f=a[c+1],p=a[c+2];G(b,5347560,(i=h,h=h+12|0,a[i>>2]=a[c],a[i+4>>2]=f,a[i+8>>2]=p,i));G(b,5347036,(i=h,h=h+4|0,a[i>>2]=a[a[e+8>>2]+12>>2],i));c=Math.a(a[b+164>>2],a[b+160>>2]);G(b,5346580,(i=h,h=h+4|0,a[i>>2]=c,i));A(b,5346212);A(b,5345916);A(b,5345572);A(b,5345160);A(b,5344796);A(b,5344604);A(b,5344240);A(b,5343896);A(b,5343540);h=d}),0,Ps,0,(function(a){n[a+530|0]=0;n[a+533|0]=0}),0,(function(c,d,g){var e=h;h=h+12|0;var l=e+4,p=a[c+16>>2],j=p+96|0,j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3])&-1,k=a[p+16>>2],n=a[1345523];Gi(a[p+88>>2],e,l);p=a[e>>2];l=(a[b>>2]=a[l>>2],a[b+4>>2]=a[l+4>>2],f[b>>3]);G(c,5374768,(i=h,h=h+68|0,a[i>>2]=2,a[i+4>>2]=1,a[i+8>>2]=p,a[i+12>>2]=j,a[i+16>>2]=k,a[i+20>>2]=0,a[i+24>>2]=n,a[i+28>>2]=0,a[i+32>>2]=0,f[b>>3]=l,a[i+36>>2]=a[b>>2],a[i+40>>2]=a[b+4>>2],a[i+44>>2]=0,a[i+48>>2]=0,a[i+52>>2]=0,a[i+56>>2]=0,a[i+60>>2]=0,a[i+64>>2]=g,i));Xl(c,d,g,0);h=e}),0,ts,0,(function(a,b){Qb(b)}),0,(function(b,c){return Eb(a[b>>2],a[c>>2])}),0,ng(),0,(function(b,c){return Eb(a[b>>2],a[c>>2])}),0,(function(a,b){A(a,5363408);A(a,b);A(a,5344600)}),0,Ns,0,Ms,0,$q,0,(function(c,d,g,e){var l,p=h;h=h+1024|0;l=(c+16|0)>>2;var j=a[a[l]+12>>2],k=p|0,r=e+24|0,r=(a[b>>2]=a[r>>2],a[b+4>>2]=a[r+4>>2],f[b>>3]);Pa(k,5352052,(i=h,h=h+8|0,f[b>>3]=r,a[i>>2]=a[b>>2],a[i+4>>2]=a[b+4>>2],i));j=a[(j<<2)+5243020>>2];Cb(j,k);Af(a[a[l]+12>>2],5338228,a[e+20>>2]);qh(c);c=n[e+72|0]<<24>>24;c=108==(c|0)?-1:114==(c|0)?1:0;Cb(j,5350404);gi(j,d,g);d=e+56|0;d=(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3])&-1;Pa(k,5372640,(i=h,h=h+8|0,a[i>>2]=c,a[i+4>>2]=d,i));Cb(j,k);Af(a[a[l]+12>>2],5338228,a[e>>2]);h=p}),0,Eo,0,(function(b,c,d){var b=a[c+16>>2],b=0==(b|0)?-1:a[b+16>>2],e=a[c+12>>2],e=0==(e|0)?-1:a[e+16>>2],f=a[d+16>>2],f=0==(f|0)?-1:a[f+16>>2],h=a[d+12>>2],h=0==(h|0)?-1:a[h+16>>2];return(b|0)!=(f|0)?b-f|0:c=(e|0)==(h|0)?Tp(a[c+4>>2],d):e-h|0}),0,(function(){a[1345523]=1}),0,(function(c){var d;n[c+528|0]=0;var g=c+348|0;d=(c+332|0)>>2;g=10/(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3])+(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3]);f[b>>3]=g;a[d]=a[b>>2];a[d+1]=a[b+4>>2];n[c+529|0]=1;return 0}),0,(function(c,d){var g=a[1312766],e=g+(36*a[d>>2]&-1)+20|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),g=g+(36*a[c>>2]&-1)+20|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]);return(e>g&1)-(e<g&1)|0}),0,As,0,(function(c,d,g){var e=a[c>>2],h=e|0,d=d-(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]),e=e+8|0,g=g-(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]),c=a[c+4>>2];return d*d+g*g<=(a[b>>2]=a[c>>2],a[b+4>>2]=a[c+4>>2],f[b>>3])&1}),0,(function(b){var c=a[b+16>>2];A(b,5355748);A(b,jc(a[c+152>>2]));A(b,5355560);A(b,5355428);c=Zb(5355212,a[c+8>>2]|0);A(b,jc(c));E(c);A(b,5355072)}),0,Fo,0,(function(a){A(a,5331100)}),0,(function(){a[1313373]=1}),0,(function(b,c,d,e,f,h){ph(b);qh(b);0==(h|0)?rh(a[a[b+16>>2]+12>>2],66,c,d):(Wl(b),rh(a[a[b+16>>2]+12>>2],98,c,d))}),0,(function(){a[1345523]=2}),0,np,0,(function(b){var c;c=a[b+16>>2]>>2;var d=a[b+64>>2];2==(d|0)?Hi(b,a[c+51],a[c+53],a[c+52],a[c+37],a[c+42],a[c+46],a[c+38]):3==(d|0)&&(Hi(b,a[c+51],a[c+53],a[c+52],a[c+37],a[c+42],a[c+46],a[c+38]),A(b,5345828))}),0,(function(c){var d,g,e=h;g=Oh(U(c|0,5348352));if(0==(g|0)){aa(0,5372156,(i=h,h=h+4|0,a[i>>2]=a[c+12>>2],i))}else{var l=Yo(g);g=l>>2;if(0!=(l|0)){var l=a[g+10],p=a[g+11];d=c+48|0;f[b>>3]=(l|0)/72;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];d=c+56|0;f[b>>3]=(p|0)/72;a[d>>2]=a[b>>2];a[d+4>>2]=a[b+4>>2];var j=da(12);d=j>>2;a[c+28>>2]=j;a[d]=a[g+3];a[d+1]=((l|0)/-2&-1)-a[g+8]|0;a[d+2]=((p|0)/-2&-1)-a[g+9]|0}}h=e}),0,Go,0,ym,0,(function(a,b){A(a,5366132);A(a,jc(b));A(a,5347084)}),0,(function(c,d){var g=a[a[c>>2]+108>>2],e=a[a[d>>2]+108>>2],h=0!=(e|0);if(0==(g|0)){return h&1}if(!h){return-1}var h=g+24|0,h=(a[b>>2]=a[h>>2],a[b+4>>2]=a[h+4>>2],f[b>>3]),g=g+32|0,g=(a[b>>2]=a[g>>2],a[b+4>>2]=a[g+4>>2],f[b>>3]),i=e+24|0,i=(a[b>>2]=a[i>>2],a[b+4>>2]=a[i+4>>2],f[b>>3]),e=e+32|0,e=(a[b>>2]=a[e>>2],a[b+4>>2]=a[e+4>>2],f[b>>3]);return h>i?-1:h<i?1:g>e?-1:g<e&1}),0,Jo,0,sm,0,(function(b,c,d,e){c=h;G(b,5356504,(i=h,h=h+8|0,a[i>>2]=d,a[i+4>>2]=e,i));h=c}),0,(function(a){A(a,5355896)}),0,(function(){a[1345523]=2}),0,(function(b,c){return a[a[b>>2]+240>>2]-a[a[c>>2]+240>>2]|0}),0,(function(b,c){var d=a[b>>2];Ch(d,a[d+128>>2],c)}),0,(function(c,d,g,e){var l,n=h;h=h+12|0;var j=n+4,k=a[c+16>>2];l=k>>2;var k=k+96|0,k=(a[b>>2]=a[k>>2],a[b+4>>2]=a[k+4>>2],f[b>>3])&-1,r=a[l+4],q=a[l+13],m=a[1345523];Gi(a[l+22],n,j);l=a[n>>2];j=(a[b>>2]=a[j>>2],a[b+4>>2]=a[j+4>>2],f[b>>3]);G(c,5374768,(i=h,h=h+68|0,a[i>>2]=2,a[i+4>>2]=3,a[i+8>>2]=l,a[i+12>>2]=k,a[i+16>>2]=r,a[i+20>>2]=q,a[i+24>>2]=m,a[i+28>>2]=0,a[i+32>>2]=0!=(e|0)?20:-1,f[b>>3]=j,a[i+36>>2]=a[b>>2],a[i+40>>2]=a[b+4>>2],a[i+44>>2]=0,a[i+48>>2]=0,a[i+52>>2]=0,a[i+56>>2]=0,a[i+60>>2]=0,a[i+64>>2]=g+1|0,i));Xl(c,d,g,1);h=n}),0,Hf,0,(function(c){var d;n[c+528|0]=0;d=c+348|0;var g=10/(a[b>>2]=a[d>>2],a[b+4>>2]=a[d+4>>2],f[b>>3]);d=(c+332|0)>>2;g=(a[b>>2]=a[d],a[b+4>>2]=a[d+1],f[b>>3])-g;f[b>>3]=g;a[d]=a[b>>2];a[d+1]=a[b+4>>2];n[c+529|0]=1;return 0}),0,mp,0,(function(b,c,d,e){var f=h;h=h+40|0;if(0==n[d]<<24>>24){c=1345557}else{var e=0==(e|0)?5339788:e,p=a[c+28>>2],j=Io(p,d);0==(j|0)?0!=(Yf(c,p+16|0,f,d,15,0)|0)&&Co(a[c+12>>2],d):0!=(Yf(c,j+16|0,f,e,ca[j+65|0],0)|0)&&aa(0,5339476,(i=h,h=h+12|0,a[i>>2]=a[c+12>>2],a[i+4>>2]=d,a[i+8>>2]=e,i));c=f>>2}b>>=2;for(d=c+10;c<d;c++,b++){a[b]=a[c]}h=f}),0];rm.X=1;H._vizRenderFromString=sm;Rc.X=1;yg.X=1;xm.X=1;Bc.X=1;wm.X=1;ym.X=1;Of.X=1;zg.X=1;Se.X=1;Gh.X=1;Hh.X=1;Dm.X=1;mf.X=1;nf.X=1;Em.X=1;Fm.X=1;Gm.X=1;Hm.X=1;Im.X=1;Qf.X=1;dj.X=1;Ih.X=1;Cg.X=1;fj.X=1;Lm.X=1;Mm.X=1;Nm.X=1;Eg.X=1;qf.X=1;Sf.X=1;pf.X=1;Wi.X=1;$m.X=1;cn.X=1;dn.X=1;an.X=1;Zm.X=1;lj.X=1;Vm.X=1;Wm.X=1;Xm.X=1;Vf.X=1;nj.X=1;jn.X=1;hn.X=1;fn.X=1;mn.X=1;oj.X=1;en.X=1;on.X=1;Tf.X=1;Um.X=1;Qm.X=1;ij.X=1;Rm.X=1;Lg.X=1;zc.X=1;ln.X=1;un.X=1;vn.X=1;Bj.X=1;Dj.X=1;Ej.X=1;Fj.X=1;zn.X=1;An.X=1;Gj.X=1;Dn.X=1;Cj.X=1;Jj.X=1;Th.X=1;we.X=1;Kj.X=1;Te.X=1;jc.X=1;Uh.X=1;Bn.X=1;Gn.X=1;Kn.X=1;Pn.X=1;Lj.X=1;Xn.X=1;Hn.X=1;Zn.X=1;Un.X=1;Pg.X=1;Tn.X=1;Qg.X=1;$n.X=1;ao.X=1;co.X=1;ko.X=1;bo.X=1;go.X=1;ho.X=1;He.X=1;eo.X=1;Qj.X=1;Rg.X=1;Xh.X=1;Wh.X=1;lo.X=1;Yh.X=1;Sj.X=1;Rj.X=1;Tj.X=1;Vj.X=1;Uj.X=1;no.X=1;oo.X=1;Wj.X=1;le.X=1;Sg.X=1;ro.X=1;Rf.X=1;to.X=1;wo.X=1;xo.X=1;zo.X=1;Yf.X=1;Bo.X=1;Do.X=1;Eo.X=1;Fo.X=1;Go.X=1;dk.X=1;ek.X=1;Jo.X=1;Ko.X=1;Lo.X=1;Mo.X=1;$h.X=1;$j.X=1;ak.X=1;bk.X=1;Ag.X=1;di.X=1;gk.X=1;Nd.X=1;Oo.X=1;Tg.X=1;hk.X=1;Ug.X=1;Qo.X=1;To.X=1;ik.X=1;So.X=1;Ro.X=1;jk.X=1;Vo.X=1;Wo.X=1;Yo.X=1;fi.X=1;lk.X=1;mk.X=1;$o.X=1;ap.X=1;nk.X=1;ok.X=1;pk.X=1;rk.X=1;sk.X=1;Ch.X=1;bn.X=1;hp.X=1;ip.X=1;hi.X=1;ep.X=1;kp.X=1;mp.X=1;np.X=1;op.X=1;pp.X=1;lp.X=1;vk.X=1;sp.X=1;rp.X=1;Wd.X=1;gp.X=1;lf.X=1;tk.X=1;Dh.X=1;Dd.X=1;Mj.X=1;yp.X=1;zp.X=1;Ap.X=1;Bp.X=1;xk.X=1;ii.X=1;Dp.X=1;Ep.X=1;Gp.X=1;Hp.X=1;Ip.X=1;Xj.X=1;Bk.X=1;Jp.X=1;Dk.X=1;Kp.X=1;ki.X=1;Yj.X=1;Pp.X=1;Op.X=1;Ae.X=1;$g.X=1;Hg.X=1;Hk.X=1;sf.X=1;ni.X=1;oi.X=1;Pe.X=1;bh.X=1;Mk.X=1;Nk.X=1;Ok.X=1;Qk.X=1;dh.X=1;dq.X=1;Lk.X=1;Rk.X=1;eq.X=1;gq.X=1;hq.X=1;Jk.X=1;pi.X=1;Kk.X=1;Vi.X=1;Vk.X=1;oq.X=1;Uk.X=1;pq.X=1;si.X=1;rq.X=1;uq.X=1;vq.X=1;fg.X=1;Yk.X=1;zq.X=1;gh.X=1;Cq.X=1;Iq.X=1;Jq.X=1;Xk.X=1;yq.X=1;Kq.X=1;el.X=1;$k.X=1;Hq.X=1;Lq.X=1;Nq.X=1;Oq.X=1;hh.X=1;fl.X=1;Qq.X=1;gl.X=1;hl.X=1;wi.X=1;jg.X=1;il.X=1;Vq.X=1;Wq.X=1;xi.X=1;kl.X=1;$q.X=1;Yq.X=1;Zq.X=1;ml.X=1;dr.X=1;Xe.X=1;yf.X=1;nl.X=1;ql.X=1;rl.X=1;gr.X=1;jr.X=1;ol.X=1;pl.X=1;ar.X=1;br.X=1;ll.X=1;cr.X=1;jh.X=1;ul.X=1;kr.X=1;lr.X=1;vl.X=1;yi.X=1;fh.X=1;sr.X=1;ur.X=1;vr.X=1;xl.X=1;xr.X=1;yr.X=1;yl.X=1;Bi.X=1;Bl.X=1;zi.X=1;Il.X=1;Al.X=1;Jl.X=1;Dl.X=1;cl.X=1;Ci.X=1;Gr.X=1;bl.X=1;Di.X=1;nh.X=1;oh.X=1;Hr.X=1;Ai.X=1;Ei.X=1;El.X=1;Fl.X=1;Dr.X=1;Kr.X=1;Lr.X=1;Cr.X=1;Br.X=1;Ll.X=1;Kl.X=1;Ml.X=1;Tr.X=1;Ur.X=1;Vr.X=1;as.X=1;Mr.X=1;Nl.X=1;Xr.X=1;ds.X=1;es.X=1;Rl.X=1;Sl.X=1;Nr.X=1;Or.X=1;Pr.X=1;Ql.X=1;Ol.X=1;Pl.X=1;hs.X=1;is.X=1;js.X=1;ks.X=1;ps.X=1;qs.X=1;ms.X=1;tl.X=1;Vl.X=1;rs.X=1;ss.X=1;ts.X=1;us.X=1;ph.X=1;ws.X=1;xs.X=1;ys.X=1;As.X=1;Bs.X=1;Cs.X=1;Ds.X=1;Xl.X=1;zs.X=1;Es.X=1;Hi.X=1;Fs.X=1;Gs.X=1;Hs.X=1;Is.X=1;Js.X=1;th.X=1;Ls.X=1;Ms.X=1;Ns.X=1;lg.X=1;De.X=1;Os.X=1;Ps.X=1;Rs.X=1;Ss.X=1;Ts.X=1;wb.X=1;Us.X=1;Ws.X=1;Vs.X=1;$s.X=1;E.X=1;H._calloc=bc;H._realloc=gc;at.X=1;Ys.X=1;Zs.X=1;var tg=Ac;H.Pa=(function(a){function b(){for(var a=0;3>a;a++){e.push(0)}}var c=a.length+1,e=[d(Od("/bin/this.program"),"i8",qe)];b();for(var f=0;f<c-1;f+=1){e.push(d(Od(a[f]),"i8",qe)),b()}e.push(0);e=d(e,"i32",qe);return H._main(c,e,0)});H.run=H.wd=Pi;if(H.preInit){for("function"==typeof H.preInit&&(H.preInit=[H.preInit]);0<H.preInit.length;){H.preInit.pop()()}}wh(ht);var Oi=qc;H.noInitialRun&&(Oi=Ud);Oi&&Pi();H.ccall("vizRenderFromString","number",["string","string"],[Mi,it]);return H["return"]}) + + + + diff --git a/src/url.php b/src/url.php new file mode 100644 index 0000000..4192d4a --- /dev/null +++ b/src/url.php @@ -0,0 +1,157 @@ +<?php +require_once("core/core.inc.php"); + +org_glizy_ObjectValues::set('org.glizy', 'editingLanguageId', 1); + +$application = org_glizy_ObjectFactory::createObject('org.glizycms.core.application.Application', 'application'); +org_glizy_Paths::addClassSearchPath('admin/application/classes/'); +$application->runSoft(); + +$req = __Request::get('req'); +$timestamp = __Request::get('timestamp'); +$languageCode = __Request::get('languageCode'); +$action = __Request::get('action'); + +if ($languageCode) { + $ar = org_glizy_ObjectFactory::createModel('org.glizycms.core.models.Language'); + $result = $ar->find(array('language_code' => $languageCode)); + if ($result) { + org_glizy_ObjectValues::set('org.glizy', 'editingLanguageId', $ar->language_id); + } else { + header("Content-Type: application/json"); + echo json_encode('NO_LANGUAGE'); + die; + } +} + +if ($req == 'checkUrl') { + $result = array('status' => true); +} else if ($req == 'news') { + $it = org_glizy_ObjectFactory::createModelIterator('movio.modules.news.models.News'); + + if ($timestamp) { + $it->where('document_detail_modificationDate', date('Y-m-d H:i:s', $timestamp), '>'); + } + + $result = array(); + + foreach ($it as $ar) { + $item = $ar->getValues(false, false, false, false); + + $item->externalId = $ar->getid(); + + $item->images = new StdClass(); + + foreach ((array)$ar->images->image as $i => $image) { + $item->images->image[$i] = imageAbsoluteUrl($image); + } + + $item->attaches = new StdClass(); + + foreach ((array)$ar->attaches->media as $i => $media) { + $item->attaches->media[$i] = imageAbsoluteUrl($media); + } + + unset($item->fulltext); + + $result[] = $item; + } +} else if ($req == 'mostra') { + $result = getDataFromPageType('Exhibition', $timestamp); +} else if ($req == 'mostraDigitale') { + $result = getDataFromPageType('DigitalExhibition', $timestamp); +} else if ($req == 'getLanguageCodes') { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Language'); + $result = array(); + foreach ($it as $ar) { + $result[] = $ar->language_code; + } +} + +header("Content-Type: application/json"); +echo json_encode($result); + +function imageAbsoluteUrl($item, $field) { + $json = $item->$field; + if (preg_match('/getImage[^"]+/', $json, $m)) { + $media = json_decode($json); + $item->{$field.'Title'} = $media->title; + $item->{$field.'Url'} = GLZ_HOST.'/'.org_glizy_helpers_Media::getUrlById($media->id, true); + } else { + $item->{$field.'Title'} = ''; + $item->{$field.'Url'} = ''; + } + unset($item->$field); +} + +function mediaAbsoluteUrl($item, $field) { + $json = $item->$field; + if (preg_match('/{"id":(\d+)/', $json, $m)) { + $media = json_decode($json); + $item->{$field.'Title'} = $media->title; + $m = org_glizycms_mediaArchive_MediaManager::getMediaById($media->id); + + if ($m->type == 'VIDEO') { + $item->{$field.'Url'} = GLZ_HOST.'/'.org_glizy_helpers_Media::getFileUrlById($media->id, true); + } else { + $item->{$field.'Url'} = GLZ_HOST.'/'.org_glizy_helpers_Media::getFileUrlById($media->id); + } + } else { + $item->{$field.'Title'} = ''; + $item->{$field.'Url'} = ''; + } + unset($item->$field); +} + +function getDataFromPageType($pageType, $timestamp) { + $it = org_glizy_ObjectFactory::createModelIterator('org.glizycms.core.models.Menu'); + $it->where('menu_pageType', $pageType); + + if ($timestamp) { + $it->where('menu_modificationDate', date('d/m/Y H:i:s', $timestamp), '>'); + } + + $result = array(); + + foreach($it as $ar) { + $menuId = $ar->getId(); + $contentProxy = org_glizy_ObjectFactory::createObject('org.glizycms.contents.models.proxy.ContentProxy'); + $item = $contentProxy->readContentFromMenu($menuId, org_glizy_ObjectValues::get('org.glizy', 'editingLanguageId')); + $item->externalId = $item->__id; + $item->title = $item->__title; + + foreach ($item as $k => $v) { + if (strpos($k, '__') === 0 ) { + unset($item->$k); + } + } + + imageAbsoluteUrl($item, 'banner'); + imageAbsoluteUrl($item, 'appImage'); + mediaAbsoluteUrl($item, 'video'); + + foreach ((array)$item->images->image as $i => $image) { + $obj = new StdClass; + $obj->image = $image; + imageAbsoluteUrl($obj, 'image'); + $item->images->title[$i] = $obj->imageTitle; + $item->images->url[$i] = $obj->imageUrl; + } + + unset($item->images->image); + + foreach ((array)$item->attaches->media as $i => $media) { + $obj = new StdClass; + $obj->media = $media; + mediaAbsoluteUrl($obj, 'media'); + $item->attaches->title[$i] = $obj->mediaTitle; + $item->attaches->url[$i] = $obj->mediaUrl; + } + + unset($item->attaches->media); + + $result[] = $item; + } + + return $result; +} \ No newline at end of file diff --git a/src/zoom.php b/src/zoom.php new file mode 100644 index 0000000..c5b6377 --- /dev/null +++ b/src/zoom.php @@ -0,0 +1,35 @@ +<?php +$id = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : NULL; +$w = isset($_REQUEST['w']) ? intval($_REQUEST['w']) : 0; +if (is_null($id)) exit; +if (!defined('GLZ_LOADED')) +{ + require_once('core/core.inc.php'); + org_glizy_Paths::init('application', ''); + org_glizy_Config::init(); + + if (file_exists(org_glizy_Paths::get('APPLICATION_STARTUP'))) + { + // if the startup folder is defined all files are included + glz_require_once_dir(org_glizy_Paths::get('APPLICATION_STARTUP')); + } + org_glizy_ObjectValues::set('org.glizy', 'languageId', 1); +} +$zoomFile = __Paths::get('CACHE').'/zoom_'.$id.'_'.$w.'.xml'; +if ( !file_exists( $zoomFile ) ) +{ + glz_import('org.glizycms.mediaArchive.MediaManager'); + set_time_limit(0); + $media = org_glizycms_mediaArchive_MediaManager::getMediaById($id); + + if (preg_match('/\.tif$/', $media->fileName)) { + $mediaInfo = $media->getResizeImage(2000, 2000); + $media->fileName = $mediaInfo['fileName']; + } + + set_include_path(implode(PATH_SEPARATOR, array( realpath('application/libs/openzoom/'), get_include_path()))); + require 'Oz/Deepzoom/ImageCreator.php'; + $converter = new Oz_Deepzoom_ImageCreator( 254, 1, "jpg", 0.80 ); + $converter->create( realpath( $media->getFileName() ), $zoomFile ); +} +echo json_encode( true );